diff --git a/.gitignore b/.gitignore index cf56b0ad0d3..7e1769ae12b 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,8 @@ npm-debug.log /coverage /.nyc_output -/tests/integration/config +/tests/config /temp /.vscode +/.ts-node /.idea diff --git a/.travis.yml b/.travis.yml index daceaf47f74..57a613d9ba0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,8 +16,6 @@ addons: - g++-4.8 before_script: - "export DISPLAY=:99.0" + - "mkdir -p tests/config && echo \"$PROJECT_CONFIG\" > tests/config/project.json" script: - xvfb-run npm test -branches: - only: - - master \ No newline at end of file diff --git a/gulp/config.js b/gulp/config.js index 18e78120e89..93e59435aea 100644 --- a/gulp/config.js +++ b/gulp/config.js @@ -17,9 +17,13 @@ const path = require('path'); const cwd = process.cwd(); const karma = require('karma'); -module.exports = { +const configObj = { root: path.resolve(cwd), pkg: require(path.resolve(cwd, 'package.json')), + testConfig: { + timeout: 5000, + retries: 5 + }, tsconfig: require(path.resolve(cwd, 'tsconfig.json')), tsconfigTest: require(path.resolve(cwd, 'tsconfig.test.json')), paths: { @@ -30,6 +34,7 @@ module.exports = { 'tests/**/*.test.ts', '!tests/**/browser/**/*.test.ts', '!tests/**/binary/**/*.test.ts', + '!src/firebase-*.ts', ], binary: [ 'tests/**/binary/**/*.test.ts', @@ -44,11 +49,10 @@ module.exports = { }, babel: { plugins: [ - require('babel-plugin-add-module-exports'), - require('babel-plugin-minify-dead-code-elimination') + 'add-module-exports', ], presets: [ - [require('babel-preset-env'), { + ['env', { "targets": { "browsers": [ "ie >= 9" @@ -103,7 +107,7 @@ module.exports = { // start these browsers // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher - browsers: ['Chrome', 'Firefox'], + browsers: ['ChromeHeadless', 'Firefox'], // Continuous Integration mode // if true, Karma captures browsers, runs the tests and exits @@ -116,6 +120,16 @@ module.exports = { // karma-typescript config karmaTypescriptConfig: { tsconfig: `./tsconfig.test.json` + }, + + // Stub for client config + client: { + mocha: {} } } -}; \ No newline at end of file +}; + +configObj.karma.client.mocha.timeout = configObj.testConfig.timeout; +configObj.karma.client.mocha.retries = configObj.testConfig.retries; + +module.exports = configObj; \ No newline at end of file diff --git a/gulp/tasks/build.js b/gulp/tasks/build.js index d617e54247a..8695cc0b541 100644 --- a/gulp/tasks/build.js +++ b/gulp/tasks/build.js @@ -42,7 +42,6 @@ const glob = require('glob'); const fs = require('fs'); const gzipSize = require('gzip-size'); const WrapperPlugin = require('wrapper-webpack-plugin'); -const legacyBuild = require('./build.legacy'); function cleanDist(dir) { return function cleanDistDirectory(done) { @@ -135,11 +134,12 @@ function compileIndvES2015ModulesToBrowser() { 'firebase-app': './src/app.ts', 'firebase-storage': './src/storage.ts', 'firebase-messaging': './src/messaging.ts', + 'firebase-database': './src/database.ts', }, output: { - path: path.resolve(__dirname, './dist/browser'), filename: '[name].js', - jsonpFunction: 'webpackJsonpFirebase' + jsonpFunction: 'webpackJsonpFirebase', + path: path.resolve(__dirname, './dist/browser'), }, module: { rules: [{ @@ -158,6 +158,7 @@ function compileIndvES2015ModulesToBrowser() { }] }, plugins: [ + new webpack.optimize.ModuleConcatenationPlugin(), new webpack.optimize.CommonsChunkPlugin({ name: 'firebase-app' }), @@ -193,27 +194,6 @@ function compileIndvES2015ModulesToBrowser() { .pipe(gulp.dest(`${config.paths.outDir}/browser`)); } -function compileSDKES2015ToBrowser() { - return gulp.src('./dist/es2015/firebase.js') - .pipe(webpackStream({ - plugins: [ - new webpack.DefinePlugin({ - TARGET_ENVIRONMENT: JSON.stringify('browser') - }) - ] - }, webpack)) - .pipe(sourcemaps.init({ loadMaps: true })) - .pipe(through.obj(function(file, enc, cb) { - // Dont pipe through any source map files as it will be handled - // by gulp-sourcemaps - var isSourceMap = /\.map$/.test(file.path); - if (!isSourceMap) this.push(file); - cb(); - })) - .pipe(sourcemaps.write('.')) - .pipe(gulp.dest(`${config.paths.outDir}/browser`)); -} - function buildBrowserFirebaseJs() { return gulp.src('./dist/browser/*.js') .pipe(sourcemaps.init({ loadMaps: true })) @@ -223,32 +203,18 @@ function buildBrowserFirebaseJs() { } function buildAltEnvFirebaseJs() { - const envs = [ - 'browser', - 'node', - 'react-native' - ]; - - const streams = envs.map(env => { - const babelConfig = Object.assign({}, config.babel, { - plugins: [ - ['inline-replace-variables', { - 'TARGET_ENVIRONMENT': env - }], - ...config.babel.plugins - ] - }); - return gulp.src('./dist/es2015/firebase.js') - .pipe(sourcemaps.init({ loadMaps: true })) - .pipe(babel(babelConfig)) - .pipe(rename({ - suffix: `-${env}` - })) - .pipe(sourcemaps.write('.')) - .pipe(gulp.dest(`${config.paths.outDir}/cjs`)); + const babelConfig = Object.assign({}, config.babel, { + plugins: config.babel.plugins }); - - return merge(streams); + return gulp.src([ + './dist/es2015/firebase-browser.js', + './dist/es2015/firebase-node.js', + './dist/es2015/firebase-react-native.js', + ]) + .pipe(sourcemaps.init({ loadMaps: true })) + .pipe(babel(babelConfig)) + .pipe(sourcemaps.write('.')) + .pipe(gulp.dest(`${config.paths.outDir}/cjs`)); } function copyPackageContents() { @@ -429,7 +395,6 @@ gulp.task('build:cjs', gulp.parallel([ gulp.parallel(compileES2015ToCJS, buildAltEnvFirebaseJs) ]), processPrebuiltFilesForCJS, - legacyBuild.compileDatabaseForCJS ])); gulp.task('process:prebuilt', gulp.parallel([ @@ -444,8 +409,6 @@ const compileSourceAssets = gulp.series([ gulp.parallel([ compileIndvES2015ModulesToBrowser, compileES2015ToCJS, - legacyBuild.compileDatabaseForBrowser, - legacyBuild.compileDatabaseForCJS ]) ]); @@ -455,7 +418,6 @@ gulp.task('build:browser', gulp.series([ gulp.parallel([ compileSourceAssets, processPrebuiltFilesForBrowser, - legacyBuild.compileDatabaseForBrowser ]), buildBrowserFirebaseJs ])); diff --git a/gulp/tasks/build.legacy.js b/gulp/tasks/build.legacy.js deleted file mode 100644 index 392b3626378..00000000000 --- a/gulp/tasks/build.legacy.js +++ /dev/null @@ -1,141 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -const gulp = require('gulp'); -const path = require('path'); -const config = require('../config'); -const closureJar = path.resolve(`${config.root}/tools/third_party/closure-compiler.jar`); -const spawn = require('child-process-promise').spawn; -const mkdirp = require('mkdirp'); - -const getClosureOptions = env => { - const baseOptions = [ - '-jar', closureJar, - '--closure_entry_point', 'fb.core.registerService', - '--only_closure_dependencies', - '--warning_level', 'VERBOSE', - '--language_in', 'ECMASCRIPT5', - '--compilation_level', 'ADVANCED', - '--generate_exports', 'true', - '--externs', `${config.root}/externs/firebase-externs.js`, - '--externs', `${config.root}/externs/firebase-app-externs.js`, - '--externs', `${config.root}/externs/firebase-app-internal-externs.js`, - '--source_map_location_mapping', `${config.root}|`, - `${config.root}/src/database/third_party/closure-library/**.js`, - `${config.root}/src/database/common/**.js`, - `${config.root}/src/database/js-client/**.js`, - `!${config.root}/src/database/js-client/**-externs.js`, - `!${config.root}/src/database/js-client/**-wrapper.js`, - ] - - let finalOptions = []; - switch (env) { - case 'node': - finalOptions = [ - ...baseOptions, - '--define', 'NODE_CLIENT=true', - '--define', 'NODE_ADMIN=false', - '--js_output_file', `${config.root}/dist/cjs/database-node.js`, - '--output_wrapper', `(function() { - var firebase = require('./app'); - %output% - module.exports = firebase.database; - })(); - //# sourceMappingURL=database-node.js.map - `, - '--create_source_map', `${config.root}/dist/cjs/database-node.js.map`, - ]; - break; - case 'browser-cdn': - finalOptions = [ - ...baseOptions, - '--jscomp_warning', 'checkDebuggerStatement', - '--jscomp_warning', 'const', - '--jscomp_warning', 'strictModuleDepCheck', - '--jscomp_warning', 'undefinedNames', - '--jscomp_warning', 'visibility', - '--jscomp_warning', 'missingProperties', - '--jscomp_warning', 'accessControls', - '--jscomp_warning', 'checkRegExp', - '--jscomp_warning', 'missingRequire', - '--jscomp_warning', 'missingProvide', - '--define', 'NODE_CLIENT=false', - '--define', 'NODE_ADMIN=false', - '--js_output_file', `${config.root}/dist/browser/firebase-database.js`, - '--output_wrapper', `(function() {%output%})(); - //# sourceMappingURL=firebase-database.js.map`, - '--create_source_map', `${config.root}/dist/browser/firebase-database.js.map`, - ]; - break; - case 'browser-built': - finalOptions = [ - ...baseOptions, - '--jscomp_warning', 'checkDebuggerStatement', - '--jscomp_warning', 'const', - '--jscomp_warning', 'strictModuleDepCheck', - '--jscomp_warning', 'undefinedNames', - '--jscomp_warning', 'visibility', - '--jscomp_warning', 'missingProperties', - '--jscomp_warning', 'accessControls', - '--jscomp_warning', 'checkRegExp', - '--jscomp_warning', 'missingRequire', - '--jscomp_warning', 'missingProvide', - '--define', 'NODE_CLIENT=false', - '--define', 'NODE_ADMIN=false', - '--js_output_file', `${config.root}/dist/cjs/database.js`, - '--output_wrapper', `(function() { - var firebase = require('./app'); - %output% - module.exports = firebase.database; - })(); - //# sourceMappingURL=database.js.map - `, - '--create_source_map', `${config.root}/dist/cjs/database.js.map`, - ] - break; - } - return finalOptions; -}; - -function compileDatabaseForBrowser() { - return new Promise(resolve => { - mkdirp(`${config.root}/dist/browser`, err => { - if (err) throw err; - resolve(); - }); - }) - .then(() => spawn(`java`, getClosureOptions('browser-cdn'))); -} - -function compileDatabaseForCJS() { - return new Promise(resolve => { - mkdirp(`${config.root}/dist/cjs`, err => { - if (err) throw err; - resolve(); - }); - }) - .then(() => { - return Promise.all([ - spawn(`java`, getClosureOptions('node')), - spawn(`java`, getClosureOptions('browser-built')) - ]); - }) -} - -exports.compileDatabaseForBrowser = compileDatabaseForBrowser - -exports.compileDatabaseForCJS = compileDatabaseForCJS; - -gulp.task('compile-database', gulp.parallel(compileDatabaseForBrowser, compileDatabaseForCJS)); diff --git a/gulp/tasks/dev.js b/gulp/tasks/dev.js index 0bbc3d7f2e6..96fc824a257 100644 --- a/gulp/tasks/dev.js +++ b/gulp/tasks/dev.js @@ -17,19 +17,18 @@ const gulp = require('gulp'); const config = require('../config'); // Ensure that the test tasks get set up -require('./test'); +const testFxns = require('./test'); function watchDevFiles() { const stream = gulp.watch([ `${config.root}/src/**/*.ts`, - config.paths.test.unit - ], gulp.parallel('test:unit')); + 'tests/**/*.test.ts' + ], testFxns.runBrowserUnitTests(true)); - stream.on('error', () => {}); + stream.on('error', err => {}); return stream; } gulp.task('dev', gulp.parallel([ - 'test:unit', watchDevFiles ])); \ No newline at end of file diff --git a/gulp/tasks/test.js b/gulp/tasks/test.js index 22485e3910a..324f46da759 100644 --- a/gulp/tasks/test.js +++ b/gulp/tasks/test.js @@ -32,7 +32,9 @@ function runNodeUnitTests() { .pipe(envs) .pipe(mocha({ reporter: 'spec', - compilers: 'ts:ts-node/register' + compilers: 'ts:ts-node/register', + timeout: config.testConfig.timeout, + retries: config.testConfig.retries })); } @@ -47,33 +49,41 @@ function runNodeBinaryTests() { .pipe(envs) .pipe(mocha({ reporter: 'spec', - compilers: 'ts:ts-node/register' + compilers: 'ts:ts-node/register', + timeout: config.testConfig.timeout, + retries: config.testConfig.retries })); } /** * Runs all of the browser unit tests in karma */ -function runBrowserUnitTests(done) { - const karmaConfig = Object.assign({}, config.karma, { - // list of files / patterns to load in the browser - files: [ - './+(src|tests)/**/*.ts' - ], - - // list of files to exclude from the included globs above - exclude: [ - // we don't want this file as it references files that only exist once compiled - `./src/firebase.ts`, +function runBrowserUnitTests(dev) { + return (done) => { + const karmaConfig = Object.assign({}, config.karma, { + // list of files / patterns to load in the browser + files: [ + './+(src|tests)/**/*.ts' + ], + + // list of files to exclude from the included globs above + exclude: [ + // we don't want this file as it references files that only exist once compiled + `./src/firebase-*.ts`, - // Don't include node test files - './tests/**/node/**/*.test.ts', + // We don't want to load the node env + `./src/utils/nodePatches.ts`, - // Don't include binary test files - './tests/**/binary/**/*.test.ts', - ], - }); - new karma.Server(karmaConfig, done).start(); + // Don't include node test files + './tests/**/node/**/*.test.ts', + + // Don't include binary test files + './tests/**/binary/**/*.test.ts', + ], + browsers: !!dev ? ['ChromeHeadless'] : config.karma.browsers, + }); + new karma.Server(karmaConfig, done).start(); + }; } /** @@ -111,7 +121,10 @@ function runAllKarmaTests(done) { // list of files to exclude from the included globs above exclude: [ // we don't want this file as it references files that only exist once compiled - `./src/firebase.ts`, + `./src/firebase-*.ts`, + + // We don't want to load the node env + `./src/utils/nodePatches.ts`, // Don't include node test files './tests/**/node/**/*.test.ts', @@ -121,9 +134,9 @@ function runAllKarmaTests(done) { } gulp.task('test:unit:node', runNodeUnitTests); -gulp.task('test:unit:browser', runBrowserUnitTests); +gulp.task('test:unit:browser', runBrowserUnitTests()); -const unitTestSuite = gulp.parallel(runNodeUnitTests, runBrowserUnitTests); +const unitTestSuite = gulp.parallel(runNodeUnitTests, runBrowserUnitTests()); gulp.task('test:unit', unitTestSuite); gulp.task('test:binary:browser', runBrowserBinaryTests); @@ -137,3 +150,6 @@ gulp.task('test', gulp.parallel([ runNodeBinaryTests, runAllKarmaTests ])); + +exports.runNodeUnitTests = runNodeUnitTests; +exports.runBrowserUnitTests = runBrowserUnitTests; \ No newline at end of file diff --git a/package.json b/package.json index 6b53d8cba5e..e1b0f1b53e7 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "babel-preset-env": "^1.2.1", "chai": "^3.5.0", "child-process-promise": "^2.2.1", + "cross-env": "^5.0.1", "cz-customizable": "^5.0.0", "filesize": "^3.5.6", "git-rev-sync": "^1.9.0", @@ -82,7 +83,7 @@ "typescript": "^2.2.1", "validate-commit-msg": "^2.12.1", "vinyl-named": "^1.1.0", - "webpack": "^2.5.0", + "webpack": "^3.0.0", "webpack-stream": "^3.2.0", "wrapper-webpack-plugin": "^0.1.11" }, diff --git a/src/app/deep_copy.ts b/src/app/deep_copy.ts deleted file mode 100644 index e1500dfc67f..00000000000 --- a/src/app/deep_copy.ts +++ /dev/null @@ -1,76 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -/** - * Do a deep-copy of basic JavaScript Objects or Arrays. - */ -export function deepCopy(value: T): T { - return deepExtend(undefined, value); -} - -/** - * Copy properties from source to target (recursively allows extension - * of Objects and Arrays). Scalar values in the target are over-written. - * If target is undefined, an object of the appropriate type will be created - * (and returned). - * - * We recursively copy all child properties of plain Objects in the source- so - * that namespace- like dictionaries are merged. - * - * Note that the target can be a function, in which case the properties in - * the source Object are copied onto it as static properties of the Function. - */ -export function deepExtend(target: any, source: any): any { - if (!(source instanceof Object)) { - return source; - } - - switch (source.constructor) { - case Date: - // Treat Dates like scalars; if the target date object had any child - // properties - they will be lost! - let dateValue = (source as any) as Date; - return new Date(dateValue.getTime()); - - case Object: - if (target === undefined) { - target = {}; - } - break; - - case Array: - // Always copy the array source and overwrite the target. - target = []; - break; - - default: - // Not a plain Object - treat it as a scalar. - return source; - } - - for (let prop in source) { - if (!source.hasOwnProperty(prop)) { - continue; - } - target[prop] = deepExtend(target[prop], source[prop]); - } - - return target; -} - -// TODO: Really needed (for JSCompiler type checking)? -export function patchProperty(obj: any, prop: string, value: any) { - obj[prop] = value; -} \ No newline at end of file diff --git a/src/app/firebase_app.ts b/src/app/firebase_app.ts index e17650f5040..292dce3122c 100644 --- a/src/app/firebase_app.ts +++ b/src/app/firebase_app.ts @@ -22,8 +22,8 @@ import { ErrorFactory, FirebaseError } from './errors'; -import { local } from './shared_promise'; -import { patchProperty, deepCopy, deepExtend } from './deep_copy'; +import { PromiseImpl } from '../utils/promise'; +import { patchProperty, deepCopy, deepExtend } from '../utils/deep_copy'; export interface FirebaseAuthTokenData { accessToken: string; } @@ -221,8 +221,6 @@ const contains = function(obj, key) { return Object.prototype.hasOwnProperty.call(obj, key); }; -let LocalPromise = local.Promise as typeof Promise; - const DEFAULT_ENTRY_NAME = '[DEFAULT]'; // An array to capture listeners before the true auth functions @@ -252,7 +250,7 @@ class FirebaseAppImpl implements FirebaseApp { this.options_ = deepCopy(options); this.INTERNAL = { 'getUid': () => null, - 'getToken': () => LocalPromise.resolve(null), + 'getToken': () => PromiseImpl.resolve(null), 'addAuthTokenListener': (callback: (token: string|null) => void) => { tokenListeners.push(callback); // Make sure callback is called, asynchronously, in the absence of the auth module @@ -275,7 +273,7 @@ class FirebaseAppImpl implements FirebaseApp { } delete(): Promise { - return new LocalPromise((resolve) => { + return new PromiseImpl((resolve) => { this.checkDestroyed_(); resolve(); }) @@ -287,7 +285,7 @@ class FirebaseAppImpl implements FirebaseApp { services.push(this.services_[serviceKey][instanceKey]); }); }); - return LocalPromise.all(services.map((service) => { + return PromiseImpl.all(services.map((service) => { return service.INTERNAL!.delete(); })); }) @@ -394,7 +392,7 @@ export function createFirebaseNamespace(): FirebaseNamespace { 'initializeApp': initializeApp, 'app': app as any, 'apps': null as any, - 'Promise': LocalPromise, + 'Promise': PromiseImpl, 'SDK_VERSION': '${JSCORE_VERSION}', 'INTERNAL': { 'registerService': registerService, @@ -405,7 +403,7 @@ export function createFirebaseNamespace(): FirebaseNamespace { 'removeApp': removeApp, 'factories': factories, 'useAsService': useAsService, - 'Promise': local.GoogPromise as typeof Promise, + 'Promise': PromiseImpl, 'deepExtend': deepExtend, } }; diff --git a/src/app/shared_promise.ts b/src/app/shared_promise.ts deleted file mode 100644 index 5c161141da3..00000000000 --- a/src/app/shared_promise.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -let scope; - -if (typeof global !== 'undefined') { - scope = global; -} else if (typeof self !== 'undefined') { - scope = self; -} else { - try { - scope = Function('return this')(); - } catch (e) { - throw new Error('polyfill failed because global object is unavailable in this environment'); - } -} - -let PromiseImpl = scope.Promise || require('promise-polyfill'); - -export let local:any = { - Promise: PromiseImpl, - GoogPromise: PromiseImpl -}; diff --git a/src/app/subscribe.ts b/src/app/subscribe.ts index 8705f764d20..d44b7e9869f 100644 --- a/src/app/subscribe.ts +++ b/src/app/subscribe.ts @@ -52,9 +52,7 @@ export interface Observable { subscribe: Subscribe; } -import {local} from './shared_promise'; - -let LocalPromise = local.Promise as typeof Promise; +import { PromiseImpl } from '../utils/promise'; export type Executor = (observer: Observer) => void; @@ -83,7 +81,7 @@ class ObserverProxy implements Observer{ private onNoObservers: Executor|undefined; private observerCount = 0; // Micro-task scheduling by calling task.then(). - private task = LocalPromise.resolve(); + private task = PromiseImpl.resolve(); private finalized = false; private finalError: Error; @@ -257,7 +255,7 @@ class ObserverProxy implements Observer{ /** Turn synchronous function into one called asynchronously. */ export function async(fn: Function, onError?: ErrorFn): Function { return (...args: any[]) => { - LocalPromise.resolve(true) + PromiseImpl.resolve(true) .then(() => { fn(...args); }) diff --git a/src/database.ts b/src/database.ts new file mode 100644 index 00000000000..f56ccb48258 --- /dev/null +++ b/src/database.ts @@ -0,0 +1,73 @@ +/** +* Copyright 2017 Google Inc. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import firebase from './app'; +import { FirebaseApp, FirebaseNamespace } from "./app/firebase_app"; +import { Database } from "./database/api/Database"; +import { Query } from "./database/api/Query"; +import { Reference } from "./database/api/Reference"; +import { enableLogging } from "./database/core/util/util"; +import { RepoManager } from "./database/core/RepoManager"; +import * as INTERNAL from './database/api/internal'; +import * as TEST_ACCESS from './database/api/test_access'; +import { isNodeSdk } from "./utils/environment"; + +export function registerDatabase(instance) { + // Register the Database Service with the 'firebase' namespace. + const namespace = instance.INTERNAL.registerService( + 'database', + app => RepoManager.getInstance().databaseFromApp(app), + // firebase.database namespace properties + { + Reference, + Query, + Database, + enableLogging, + INTERNAL, + ServerValue: Database.ServerValue, + TEST_ACCESS + } + ); + + if (isNodeSdk()) { + module.exports = namespace; + } +} + +/** + * Extensions to the FirebaseApp and FirebaseNamespaces interfaces + */ +declare module './app/firebase_app' { + interface FirebaseApp { + database?(): Database + } +} + +declare module './app/firebase_app' { + interface FirebaseNamespace { + database?: { + (app?: FirebaseApp): Database, + Database, + enableLogging, + INTERNAL, + Query, + Reference, + ServerValue, + } + } +} + +registerDatabase(firebase); diff --git a/src/database/api/DataSnapshot.ts b/src/database/api/DataSnapshot.ts new file mode 100644 index 00000000000..472393fff3e --- /dev/null +++ b/src/database/api/DataSnapshot.ts @@ -0,0 +1,168 @@ +import { validateArgCount, validateCallback } from '../../utils/validation'; +import { validatePathString } from '../core/util/validation'; +import { Path } from '../core/util/Path'; +import { PRIORITY_INDEX } from '../core/snap/indexes/PriorityIndex'; +import { Node } from '../core/snap/Node'; +import { Reference } from './Reference'; +import { Index } from '../core/snap/indexes/Index'; +import { ChildrenNode } from '../core/snap/ChildrenNode'; + +/** + * Class representing a firebase data snapshot. It wraps a SnapshotNode and + * surfaces the public methods (val, forEach, etc.) we want to expose. + */ +export class DataSnapshot { + /** + * @param {!Node} node_ A SnapshotNode to wrap. + * @param {!Reference} ref_ The ref of the location this snapshot came from. + * @param {!Index} index_ The iteration order for this snapshot + */ + constructor(private readonly node_: Node, + private readonly ref_: Reference, + private readonly index_: Index) { + } + + /** + * Retrieves the snapshot contents as JSON. Returns null if the snapshot is + * empty. + * + * @return {*} JSON representation of the DataSnapshot contents, or null if empty. + */ + val(): any { + validateArgCount('DataSnapshot.val', 0, 0, arguments.length); + return this.node_.val(); + } + + /** + * Returns the snapshot contents as JSON, including priorities of node. Suitable for exporting + * the entire node contents. + * @return {*} JSON representation of the DataSnapshot contents, or null if empty. + */ + exportVal(): any { + validateArgCount('DataSnapshot.exportVal', 0, 0, arguments.length); + return this.node_.val(true); + } + + // Do not create public documentation. This is intended to make JSON serialization work but is otherwise unnecessary + // for end-users + toJSON(): any { + // Optional spacer argument is unnecessary because we're depending on recursion rather than stringifying the content + validateArgCount('DataSnapshot.toJSON', 0, 1, arguments.length); + return this.exportVal(); + } + + /** + * Returns whether the snapshot contains a non-null value. + * + * @return {boolean} Whether the snapshot contains a non-null value, or is empty. + */ + exists(): boolean { + validateArgCount('DataSnapshot.exists', 0, 0, arguments.length); + return !this.node_.isEmpty(); + } + + /** + * Returns a DataSnapshot of the specified child node's contents. + * + * @param {!string} childPathString Path to a child. + * @return {!DataSnapshot} DataSnapshot for child node. + */ + child(childPathString: string): DataSnapshot { + validateArgCount('DataSnapshot.child', 0, 1, arguments.length); + // Ensure the childPath is a string (can be a number) + childPathString = String(childPathString); + validatePathString('DataSnapshot.child', 1, childPathString, false); + + const childPath = new Path(childPathString); + const childRef = this.ref_.child(childPath); + return new DataSnapshot(this.node_.getChild(childPath), childRef, PRIORITY_INDEX); + } + + /** + * Returns whether the snapshot contains a child at the specified path. + * + * @param {!string} childPathString Path to a child. + * @return {boolean} Whether the child exists. + */ + hasChild(childPathString: string): boolean { + validateArgCount('DataSnapshot.hasChild', 1, 1, arguments.length); + validatePathString('DataSnapshot.hasChild', 1, childPathString, false); + + const childPath = new Path(childPathString); + return !this.node_.getChild(childPath).isEmpty(); + } + + /** + * Returns the priority of the object, or null if no priority was set. + * + * @return {string|number|null} The priority. + */ + getPriority(): string | number | null { + validateArgCount('DataSnapshot.getPriority', 0, 0, arguments.length); + + // typecast here because we never return deferred values or internal priorities (MAX_PRIORITY) + return /**@type {string|number|null} */ (this.node_.getPriority().val()); + } + + /** + * Iterates through child nodes and calls the specified action for each one. + * + * @param {function(!DataSnapshot)} action Callback function to be called + * for each child. + * @return {boolean} True if forEach was canceled by action returning true for + * one of the child nodes. + */ + forEach(action: (d: DataSnapshot) => any): boolean { + validateArgCount('DataSnapshot.forEach', 1, 1, arguments.length); + validateCallback('DataSnapshot.forEach', 1, action, false); + + if (this.node_.isLeafNode()) + return false; + + const childrenNode = /**@type {ChildrenNode} */ (this.node_); + // Sanitize the return value to a boolean. ChildrenNode.forEachChild has a weird return type... + return !!childrenNode.forEachChild(this.index_, (key, node) => { + return action(new DataSnapshot(node, this.ref_.child(key), PRIORITY_INDEX)); + }); + } + + /** + * Returns whether this DataSnapshot has children. + * @return {boolean} True if the DataSnapshot contains 1 or more child nodes. + */ + hasChildren(): boolean { + validateArgCount('DataSnapshot.hasChildren', 0, 0, arguments.length); + + if (this.node_.isLeafNode()) + return false; + else + return !this.node_.isEmpty(); + } + + get key() { + return this.ref_.getKey(); + } + + /** + * Returns the number of children for this DataSnapshot. + * @return {number} The number of children that this DataSnapshot contains. + */ + numChildren(): number { + validateArgCount('DataSnapshot.numChildren', 0, 0, arguments.length); + + return this.node_.numChildren(); + } + + /** + * @return {Reference} The Firebase reference for the location this snapshot's data came from. + */ + getRef(): Reference { + validateArgCount('DataSnapshot.ref', 0, 0, arguments.length); + + return this.ref_; + } + + get ref() { + return this.getRef(); + } +} diff --git a/src/database/api/Database.ts b/src/database/api/Database.ts new file mode 100644 index 00000000000..6701c8980fe --- /dev/null +++ b/src/database/api/Database.ts @@ -0,0 +1,133 @@ +import { fatal } from "../core/util/util"; +import { parseRepoInfo } from "../core/util/libs/parser"; +import { Path } from "../core/util/Path"; +import { PromiseImpl } from "../../utils/promise"; +import { Reference } from "./Reference"; +import { Repo } from "../core/Repo"; +import { RepoManager } from "../core/RepoManager"; +import { validateArgCount } from "../../utils/validation"; +import { FirebaseApp } from "../../app/firebase_app"; +import { validateUrl } from "../core/util/validation"; + +/** + * Class representing a firebase database. + * @implements {firebase.Service} + */ +export class Database { + repo_: Repo; + root_: Reference; + INTERNAL; + + static ServerValue = { + 'TIMESTAMP': { + '.sv' : 'timestamp' + } + } + + /** + * The constructor should not be called by users of our public API. + * @param {!Repo} repo + */ + constructor(repo) { + if (!(repo instanceof Repo)) { + fatal("Don't call new Database() directly - please use firebase.database()."); + } + + /** @type {Repo} */ + this.repo_ = repo; + + /** @type {Firebase} */ + this.root_ = new Reference(repo, Path.Empty); + + this.INTERNAL = new DatabaseInternals(this); + } + + get app(): FirebaseApp { + return this.repo_.app; + } + + /** + * Returns a reference to the root or the path specified in opt_pathString. + * @param {string=} pathString + * @return {!Firebase} Firebase reference. + */ + ref(pathString?: string): Reference { + this.checkDeleted_('ref'); + validateArgCount('database.ref', 0, 1, arguments.length); + + return pathString !== undefined ? this.root_.child(pathString) : this.root_; + } + + /** + * Returns a reference to the root or the path specified in url. + * We throw a exception if the url is not in the same domain as the + * current repo. + * @param {string} url + * @return {!Firebase} Firebase reference. + */ + refFromURL(url) { + /** @const {string} */ + var apiName = 'database.refFromURL'; + this.checkDeleted_(apiName); + validateArgCount(apiName, 1, 1, arguments.length); + var parsedURL = parseRepoInfo(url); + validateUrl(apiName, 1, parsedURL); + + var repoInfo = parsedURL.repoInfo; + if (repoInfo.host !== this.repo_.repoInfo_.host) { + fatal(apiName + ": Host name does not match the current database: " + + "(found " + repoInfo.host + " but expected " + this.repo_.repoInfo_.host + ")"); + } + + return this.ref(parsedURL.path.toString()); + } + + /** + * @param {string} apiName + */ + private checkDeleted_(apiName) { + if (this.repo_ === null) { + fatal("Cannot call " + apiName + " on a deleted database."); + } + } + + // Make individual repo go offline. + goOffline() { + validateArgCount('database.goOffline', 0, 0, arguments.length); + this.checkDeleted_('goOffline'); + this.repo_.interrupt(); + } + + goOnline () { + validateArgCount('database.goOnline', 0, 0, arguments.length); + this.checkDeleted_('goOnline'); + this.repo_.resume(); + } +}; + +Object.defineProperty(Repo.prototype, 'database', { + get() { + return this.__database || (this.__database = new Database(this)); + } +}); + +class DatabaseInternals { + database + /** @param {!Database} database */ + constructor(database) { + this.database = database; + } + + /** @return {firebase.Promise} */ + delete() { + this.database.checkDeleted_('delete'); + RepoManager.getInstance().deleteRepo(/** @type {!Repo} */ (this.database.repo_)); + + this.database.repo_ = null; + this.database.root_ = null; + this.database.INTERNAL = null; + this.database = null; + return PromiseImpl.resolve(); + } +}; + diff --git a/src/database/api/Query.ts b/src/database/api/Query.ts new file mode 100644 index 00000000000..6f7218143d9 --- /dev/null +++ b/src/database/api/Query.ts @@ -0,0 +1,520 @@ +import { assert } from '../../utils/assert'; +import { KEY_INDEX } from '../core/snap/indexes/KeyIndex'; +import { PRIORITY_INDEX } from '../core/snap/indexes/PriorityIndex'; +import { VALUE_INDEX } from '../core/snap/indexes/ValueIndex'; +import { PathIndex } from '../core/snap/indexes/PathIndex'; +import { MIN_NAME, MAX_NAME, ObjectToUniqueKey } from '../core/util/util'; +import { Path } from '../core/util/Path'; +import { + isValidPriority, + validateEventType, + validatePathString, + validateFirebaseDataArg, + validateKey, +} from '../core/util/validation'; +import { errorPrefix, validateArgCount, validateCallback, validateContextObject } from '../../utils/validation'; +import { ValueEventRegistration, ChildEventRegistration } from '../core/view/EventRegistration'; +import { Deferred, attachDummyErrorHandler } from '../../utils/promise'; +import { Repo } from '../core/Repo'; +import { QueryParams } from '../core/view/QueryParams'; +import { Reference } from './Reference'; +import { DataSnapshot } from './DataSnapshot'; + +let __referenceConstructor: new(repo: Repo, path: Path) => Query; + +export interface SnapshotCallback { + (a: DataSnapshot, b?: string): any +} + +/** + * A Query represents a filter to be applied to a firebase location. This object purely represents the + * query expression (and exposes our public API to build the query). The actual query logic is in ViewBase.js. + * + * Since every Firebase reference is a query, Firebase inherits from this object. + */ +export class Query { + static set __referenceConstructor(val) { + __referenceConstructor = val; + } + + static get __referenceConstructor() { + assert(__referenceConstructor, 'Reference.ts has not been loaded'); + return __referenceConstructor; + } + + constructor(public repo: Repo, public path: Path, private queryParams_: QueryParams, private orderByCalled_: boolean) {} + + /** + * Validates start/end values for queries. + * @param {!QueryParams} params + * @private + */ + private static validateQueryEndpoints_(params: QueryParams) { + let startNode = null; + let endNode = null; + if (params.hasStart()) { + startNode = params.getIndexStartValue(); + } + if (params.hasEnd()) { + endNode = params.getIndexEndValue(); + } + + if (params.getIndex() === KEY_INDEX) { + const tooManyArgsError = 'Query: When ordering by key, you may only pass one argument to ' + + 'startAt(), endAt(), or equalTo().'; + const wrongArgTypeError = 'Query: When ordering by key, the argument passed to startAt(), endAt(),' + + 'or equalTo() must be a string.'; + if (params.hasStart()) { + const startName = params.getIndexStartName(); + if (startName != MIN_NAME) { + throw new Error(tooManyArgsError); + } else if (typeof(startNode) !== 'string') { + throw new Error(wrongArgTypeError); + } + } + if (params.hasEnd()) { + const endName = params.getIndexEndName(); + if (endName != MAX_NAME) { + throw new Error(tooManyArgsError); + } else if (typeof(endNode) !== 'string') { + throw new Error(wrongArgTypeError); + } + } + } + else if (params.getIndex() === PRIORITY_INDEX) { + if ((startNode != null && !isValidPriority(startNode)) || + (endNode != null && !isValidPriority(endNode))) { + throw new Error('Query: When ordering by priority, the first argument passed to startAt(), ' + + 'endAt(), or equalTo() must be a valid priority value (null, a number, or a string).'); + } + } else { + assert((params.getIndex() instanceof PathIndex) || + (params.getIndex() === VALUE_INDEX), 'unknown index type.'); + if ((startNode != null && typeof startNode === 'object') || + (endNode != null && typeof endNode === 'object')) { + throw new Error('Query: First argument passed to startAt(), endAt(), or equalTo() cannot be ' + + 'an object.'); + } + } + } + + /** + * Validates that limit* has been called with the correct combination of parameters + * @param {!QueryParams} params + * @private + */ + private static validateLimit_(params: QueryParams) { + if (params.hasStart() && params.hasEnd() && params.hasLimit() && !params.hasAnchoredLimit()) { + throw new Error( + 'Query: Can\'t combine startAt(), endAt(), and limit(). Use limitToFirst() or limitToLast() instead.' + ); + } + } + + /** + * Validates that no other order by call has been made + * @param {!string} fnName + * @private + */ + private validateNoPreviousOrderByCall_(fnName: string) { + if (this.orderByCalled_ === true) { + throw new Error(fnName + ': You can\'t combine multiple orderBy calls.'); + } + } + + /** + * @return {!QueryParams} + */ + getQueryParams(): QueryParams { + return this.queryParams_; + } + + /** + * @return {!Reference} + */ + getRef(): Reference { + validateArgCount('Query.ref', 0, 0, arguments.length); + // This is a slight hack. We cannot goog.require('fb.api.Firebase'), since Firebase requires fb.api.Query. + // However, we will always export 'Firebase' to the global namespace, so it's guaranteed to exist by the time this + // method gets called. + return (new Query.__referenceConstructor(this.repo, this.path)); + } + + /** + * @param {!string} eventType + * @param {!function(DataSnapshot, string=)} callback + * @param {(function(Error)|Object)=} cancelCallbackOrContext + * @param {Object=} context + * @return {!function(DataSnapshot, string=)} + */ + on(eventType: string, callback: SnapshotCallback, + cancelCallbackOrContext?: ((a: Error) => any) | Object, context?: Object): SnapshotCallback { + validateArgCount('Query.on', 2, 4, arguments.length); + validateEventType('Query.on', 1, eventType, false); + validateCallback('Query.on', 2, callback, false); + + const ret = Query.getCancelAndContextArgs_('Query.on', cancelCallbackOrContext, context); + + if (eventType === 'value') { + this.onValueEvent(callback, ret.cancel, ret.context); + } else { + const callbacks = {}; + callbacks[eventType] = callback; + this.onChildEvent(callbacks, ret.cancel, ret.context); + } + return callback; + } + + /** + * @param {!function(!DataSnapshot)} callback + * @param {?function(Error)} cancelCallback + * @param {?Object} context + * @protected + */ + onValueEvent(callback: (a: DataSnapshot) => any, cancelCallback: ((a: Error) => any) | null, context: Object | null) { + const container = new ValueEventRegistration(callback, cancelCallback || null, context || null); + this.repo.addEventCallbackForQuery(this, container); + } + + /** + * @param {!Object.} callbacks + * @param {?function(Error)} cancelCallback + * @param {?Object} context + */ + onChildEvent(callbacks: { [k: string]: SnapshotCallback }, + cancelCallback: ((a: Error) => any) | null, context: Object | null) { + const container = new ChildEventRegistration(callbacks, cancelCallback, context); + this.repo.addEventCallbackForQuery(this, container); + } + + /** + * @param {string=} eventType + * @param {(function(!DataSnapshot, ?string=))=} callback + * @param {Object=} context + */ + off(eventType?: string, callback?: SnapshotCallback, context?: Object) { + validateArgCount('Query.off', 0, 3, arguments.length); + validateEventType('Query.off', 1, eventType, true); + validateCallback('Query.off', 2, callback, true); + validateContextObject('Query.off', 3, context, true); + + let container = null; + let callbacks = null; + if (eventType === 'value') { + const valueCallback = /** @type {function(!DataSnapshot)} */ (callback) || null; + container = new ValueEventRegistration(valueCallback, null, context || null); + } else if (eventType) { + if (callback) { + callbacks = {}; + callbacks[eventType] = callback; + } + container = new ChildEventRegistration(callbacks, null, context || null); + } + this.repo.removeEventCallbackForQuery(this, container); + } + + /** + * Attaches a listener, waits for the first event, and then removes the listener + * @param {!string} eventType + * @param {!function(!DataSnapshot, string=)} userCallback + * @param cancelOrContext + * @param context + * @return {!firebase.Promise} + */ + once(eventType: string, + userCallback?: SnapshotCallback, + cancelOrContext?, context?: Object): Promise { + validateArgCount('Query.once', 1, 4, arguments.length); + validateEventType('Query.once', 1, eventType, false); + validateCallback('Query.once', 2, userCallback, true); + + const ret = Query.getCancelAndContextArgs_('Query.once', cancelOrContext, context); + + // TODO: Implement this more efficiently (in particular, use 'get' wire protocol for 'value' event) + // TODO: consider actually wiring the callbacks into the promise. We cannot do this without a breaking change + // because the API currently expects callbacks will be called synchronously if the data is cached, but this is + // against the Promise specification. + let firstCall = true; + const deferred = new Deferred(); + attachDummyErrorHandler(deferred.promise); + + const onceCallback = (snapshot) => { + // NOTE: Even though we unsubscribe, we may get called multiple times if a single action (e.g. set() with JSON) + // triggers multiple events (e.g. child_added or child_changed). + if (firstCall) { + firstCall = false; + this.off(eventType, onceCallback); + + if (userCallback) { + userCallback.bind(ret.context)(snapshot); + } + deferred.resolve(snapshot); + } + }; + + this.on(eventType, onceCallback, /*cancel=*/ (err) => { + this.off(eventType, onceCallback); + + if (ret.cancel) + ret.cancel.bind(ret.context)(err); + deferred.reject(err); + }); + return deferred.promise; + } + + /** + * Set a limit and anchor it to the start of the window. + * @param {!number} limit + * @return {!Query} + */ + limitToFirst(limit: number): Query { + validateArgCount('Query.limitToFirst', 1, 1, arguments.length); + if (typeof limit !== 'number' || Math.floor(limit) !== limit || limit <= 0) { + throw new Error('Query.limitToFirst: First argument must be a positive integer.'); + } + if (this.queryParams_.hasLimit()) { + throw new Error('Query.limitToFirst: Limit was already set (by another call to limit, ' + + 'limitToFirst, or limitToLast).'); + } + + return new Query(this.repo, this.path, this.queryParams_.limitToFirst(limit), this.orderByCalled_); + } + + /** + * Set a limit and anchor it to the end of the window. + * @param {!number} limit + * @return {!Query} + */ + limitToLast(limit: number): Query { + validateArgCount('Query.limitToLast', 1, 1, arguments.length); + if (typeof limit !== 'number' || Math.floor(limit) !== limit || limit <= 0) { + throw new Error('Query.limitToLast: First argument must be a positive integer.'); + } + if (this.queryParams_.hasLimit()) { + throw new Error('Query.limitToLast: Limit was already set (by another call to limit, ' + + 'limitToFirst, or limitToLast).'); + } + + return new Query(this.repo, this.path, this.queryParams_.limitToLast(limit), + this.orderByCalled_); + } + + /** + * Given a child path, return a new query ordered by the specified grandchild path. + * @param {!string} path + * @return {!Query} + */ + orderByChild(path: string): Query { + validateArgCount('Query.orderByChild', 1, 1, arguments.length); + if (path === '$key') { + throw new Error('Query.orderByChild: "$key" is invalid. Use Query.orderByKey() instead.'); + } else if (path === '$priority') { + throw new Error('Query.orderByChild: "$priority" is invalid. Use Query.orderByPriority() instead.'); + } else if (path === '$value') { + throw new Error('Query.orderByChild: "$value" is invalid. Use Query.orderByValue() instead.'); + } + validatePathString('Query.orderByChild', 1, path, false); + this.validateNoPreviousOrderByCall_('Query.orderByChild'); + const parsedPath = new Path(path); + if (parsedPath.isEmpty()) { + throw new Error('Query.orderByChild: cannot pass in empty path. Use Query.orderByValue() instead.'); + } + const index = new PathIndex(parsedPath); + const newParams = this.queryParams_.orderBy(index); + Query.validateQueryEndpoints_(newParams); + + return new Query(this.repo, this.path, newParams, /*orderByCalled=*/true); + } + + /** + * Return a new query ordered by the KeyIndex + * @return {!Query} + */ + orderByKey(): Query { + validateArgCount('Query.orderByKey', 0, 0, arguments.length); + this.validateNoPreviousOrderByCall_('Query.orderByKey'); + const newParams = this.queryParams_.orderBy(KEY_INDEX); + Query.validateQueryEndpoints_(newParams); + return new Query(this.repo, this.path, newParams, /*orderByCalled=*/true); + } + + /** + * Return a new query ordered by the PriorityIndex + * @return {!Query} + */ + orderByPriority(): Query { + validateArgCount('Query.orderByPriority', 0, 0, arguments.length); + this.validateNoPreviousOrderByCall_('Query.orderByPriority'); + const newParams = this.queryParams_.orderBy(PRIORITY_INDEX); + Query.validateQueryEndpoints_(newParams); + return new Query(this.repo, this.path, newParams, /*orderByCalled=*/true); + } + + /** + * Return a new query ordered by the ValueIndex + * @return {!Query} + */ + orderByValue(): Query { + validateArgCount('Query.orderByValue', 0, 0, arguments.length); + this.validateNoPreviousOrderByCall_('Query.orderByValue'); + const newParams = this.queryParams_.orderBy(VALUE_INDEX); + Query.validateQueryEndpoints_(newParams); + return new Query(this.repo, this.path, newParams, /*orderByCalled=*/true); + } + + /** + * @param {number|string|boolean|null} value + * @param {?string=} name + * @return {!Query} + */ + startAt(value: number | string | boolean | null = null, name?: string | null): Query { + validateArgCount('Query.startAt', 0, 2, arguments.length); + validateFirebaseDataArg('Query.startAt', 1, value, this.path, true); + validateKey('Query.startAt', 2, name, true); + + const newParams = this.queryParams_.startAt(value, name); + Query.validateLimit_(newParams); + Query.validateQueryEndpoints_(newParams); + if (this.queryParams_.hasStart()) { + throw new Error('Query.startAt: Starting point was already set (by another call to startAt ' + + 'or equalTo).'); + } + + // Calling with no params tells us to start at the beginning. + if (value === undefined) { + value = null; + name = null; + } + return new Query(this.repo, this.path, newParams, this.orderByCalled_); + } + + /** + * @param {number|string|boolean|null} value + * @param {?string=} name + * @return {!Query} + */ + endAt(value: number | string | boolean | null = null, name?: string | null): Query { + validateArgCount('Query.endAt', 0, 2, arguments.length); + validateFirebaseDataArg('Query.endAt', 1, value, this.path, true); + validateKey('Query.endAt', 2, name, true); + + const newParams = this.queryParams_.endAt(value, name); + Query.validateLimit_(newParams); + Query.validateQueryEndpoints_(newParams); + if (this.queryParams_.hasEnd()) { + throw new Error('Query.endAt: Ending point was already set (by another call to endAt or ' + + 'equalTo).'); + } + + return new Query(this.repo, this.path, newParams, this.orderByCalled_); + } + + /** + * Load the selection of children with exactly the specified value, and, optionally, + * the specified name. + * @param {number|string|boolean|null} value + * @param {string=} name + * @return {!Query} + */ + equalTo(value: number | string | boolean | null, name?: string) { + validateArgCount('Query.equalTo', 1, 2, arguments.length); + validateFirebaseDataArg('Query.equalTo', 1, value, this.path, false); + validateKey('Query.equalTo', 2, name, true); + if (this.queryParams_.hasStart()) { + throw new Error('Query.equalTo: Starting point was already set (by another call to startAt or ' + + 'equalTo).'); + } + if (this.queryParams_.hasEnd()) { + throw new Error('Query.equalTo: Ending point was already set (by another call to endAt or ' + + 'equalTo).'); + } + return this.startAt(value, name).endAt(value, name); + } + + /** + * @return {!string} URL for this location. + */ + toString(): string { + validateArgCount('Query.toString', 0, 0, arguments.length); + + return this.repo.toString() + this.path.toUrlEncodedString(); + } + + // Do not create public documentation. This is intended to make JSON serialization work but is otherwise unnecessary + // for end-users. + toJSON() { + // An optional spacer argument is unnecessary for a string. + validateArgCount('Query.toJSON', 0, 1, arguments.length); + return this.toString(); + } + + /** + * An object representation of the query parameters used by this Query. + * @return {!Object} + */ + queryObject(): Object { + return this.queryParams_.getQueryObject(); + } + + /** + * @return {!string} + */ + queryIdentifier(): string { + const obj = this.queryObject(); + const id = ObjectToUniqueKey(obj); + return (id === '{}') ? 'default' : id; + } + + /** + * Return true if this query and the provided query are equivalent; otherwise, return false. + * @param {Query} other + * @return {boolean} + */ + isEqual(other: Query): boolean { + validateArgCount('Query.isEqual', 1, 1, arguments.length); + if (!(other instanceof Query)) { + const error = 'Query.isEqual failed: First argument must be an instance of firebase.database.Query.'; + throw new Error(error); + } + + const sameRepo = (this.repo === other.repo); + const samePath = this.path.equals(other.path); + const sameQueryIdentifier = (this.queryIdentifier() === other.queryIdentifier()); + + return (sameRepo && samePath && sameQueryIdentifier); + } + + /** + * Helper used by .on and .once to extract the context and or cancel arguments. + * @param {!string} fnName The function name (on or once) + * @param {(function(Error)|Object)=} cancelOrContext + * @param {Object=} context + * @return {{cancel: ?function(Error), context: ?Object}} + * @private + */ + private static getCancelAndContextArgs_(fnName: string, cancelOrContext?: ((a: Error) => any) | Object, + context?: Object): { cancel: ((a: Error) => any) | null, context: Object | null } { + const ret = {cancel: null, context: null}; + if (cancelOrContext && context) { + ret.cancel = /** @type {function(Error)} */ (cancelOrContext); + validateCallback(fnName, 3, ret.cancel, true); + + ret.context = context; + validateContextObject(fnName, 4, ret.context, true); + } else if (cancelOrContext) { // we have either a cancel callback or a context. + if (typeof cancelOrContext === 'object' && cancelOrContext !== null) { // it's a context! + ret.context = cancelOrContext; + } else if (typeof cancelOrContext === 'function') { + ret.cancel = cancelOrContext; + } else { + throw new Error(errorPrefix(fnName, 3, true) + + ' must either be a cancel callback or a context object.'); + } + } + return ret; + } + + get ref(): Reference { + return this.getRef(); + } +} diff --git a/src/database/api/Reference.ts b/src/database/api/Reference.ts new file mode 100644 index 00000000000..5654eaf9b7b --- /dev/null +++ b/src/database/api/Reference.ts @@ -0,0 +1,311 @@ +import { OnDisconnect } from './onDisconnect'; +import { TransactionResult } from './TransactionResult'; +import { warn } from '../core/util/util'; +import { nextPushId } from '../core/util/NextPushId'; +import { Query } from './Query'; +import { Repo } from '../core/Repo'; +import { Path } from '../core/util/Path'; +import { QueryParams } from '../core/view/QueryParams'; +import { + validateRootPathString, + validatePathString, + validateFirebaseMergeDataArg, + validateBoolean, + validatePriority, + validateFirebaseDataArg, + validateWritablePath, +} from '../core/util/validation'; +import { + validateArgCount, + validateCallback, +} from '../../utils/validation'; +import { Deferred, attachDummyErrorHandler, PromiseImpl } from '../../utils/promise'; +import { SyncPoint } from '../core/SyncPoint'; +import { Database } from './Database'; +import { DataSnapshot } from './DataSnapshot'; + +export class Reference extends Query { + public then; + public catch; + + /** + * Call options: + * new Reference(Repo, Path) or + * new Reference(url: string, string|RepoManager) + * + * Externally - this is the firebase.database.Reference type. + * + * @param {!Repo} repo + * @param {(!Path)} path + * @extends {Query} + */ + constructor(repo: Repo, path: Path) { + if (!(repo instanceof Repo)) { + throw new Error('new Reference() no longer supported - use app.database().'); + } + + // call Query's constructor, passing in the repo and path. + super(repo, path, QueryParams.DEFAULT, false); + } + + /** @return {?string} */ + getKey(): string | null { + validateArgCount('Reference.key', 0, 0, arguments.length); + + if (this.path.isEmpty()) + return null; + else + return this.path.getBack(); + } + + /** + * @param {!(string|Path)} pathString + * @return {!Reference} + */ + child(pathString: string | Path): Reference { + validateArgCount('Reference.child', 1, 1, arguments.length); + if (typeof pathString === 'number') { + pathString = String(pathString); + } else if (!(pathString instanceof Path)) { + if (this.path.getFront() === null) + validateRootPathString('Reference.child', 1, pathString, false); + else + validatePathString('Reference.child', 1, pathString, false); + } + + return new Reference(this.repo, this.path.child(pathString)); + } + + /** @return {?Reference} */ + getParent(): Reference | null { + validateArgCount('Reference.parent', 0, 0, arguments.length); + + const parentPath = this.path.parent(); + return parentPath === null ? null : new Reference(this.repo, parentPath); + } + + /** @return {!Reference} */ + getRoot(): Reference { + validateArgCount('Reference.root', 0, 0, arguments.length); + + let ref = this; + while (ref.getParent() !== null) { + ref = ref.getParent(); + } + return ref; + } + + /** @return {!Database} */ + databaseProp(): Database { + return this.repo.database; + } + + /** + * @param {*} newVal + * @param {function(?Error)=} onComplete + * @return {!Promise} + */ + set(newVal: any, onComplete?: (a: Error | null) => any): Promise { + validateArgCount('Reference.set', 1, 2, arguments.length); + validateWritablePath('Reference.set', this.path); + validateFirebaseDataArg('Reference.set', 1, newVal, this.path, false); + validateCallback('Reference.set', 2, onComplete, true); + + const deferred = new Deferred(); + this.repo.setWithPriority(this.path, newVal, /*priority=*/ null, deferred.wrapCallback(onComplete)); + return deferred.promise; + } + + /** + * @param {!Object} objectToMerge + * @param {function(?Error)=} onComplete + * @return {!Promise} + */ + update(objectToMerge: Object, onComplete?: (a: Error | null) => any): Promise { + validateArgCount('Reference.update', 1, 2, arguments.length); + validateWritablePath('Reference.update', this.path); + + if (Array.isArray(objectToMerge)) { + const newObjectToMerge = {}; + for (let i = 0; i < objectToMerge.length; ++i) { + newObjectToMerge['' + i] = objectToMerge[i]; + } + objectToMerge = newObjectToMerge; + warn('Passing an Array to Firebase.update() is deprecated. ' + + 'Use set() if you want to overwrite the existing data, or ' + + 'an Object with integer keys if you really do want to ' + + 'only update some of the children.' + ); + } + validateFirebaseMergeDataArg('Reference.update', 1, objectToMerge, this.path, false); + validateCallback('Reference.update', 2, onComplete, true); + const deferred = new Deferred(); + this.repo.update(this.path, objectToMerge, deferred.wrapCallback(onComplete)); + return deferred.promise; + } + + /** + * @param {*} newVal + * @param {string|number|null} newPriority + * @param {function(?Error)=} onComplete + * @return {!Promise} + */ + setWithPriority(newVal: any, newPriority: string | number | null, + onComplete?: (a: Error | null) => any): Promise { + validateArgCount('Reference.setWithPriority', 2, 3, arguments.length); + validateWritablePath('Reference.setWithPriority', this.path); + validateFirebaseDataArg('Reference.setWithPriority', 1, newVal, this.path, false); + validatePriority('Reference.setWithPriority', 2, newPriority, false); + validateCallback('Reference.setWithPriority', 3, onComplete, true); + + if (this.getKey() === '.length' || this.getKey() === '.keys') + throw 'Reference.setWithPriority failed: ' + this.getKey() + ' is a read-only object.'; + + const deferred = new Deferred(); + this.repo.setWithPriority(this.path, newVal, newPriority, deferred.wrapCallback(onComplete)); + return deferred.promise; + } + + /** + * @param {function(?Error)=} onComplete + * @return {!Promise} + */ + remove(onComplete?: (a: Error | null) => any): Promise { + validateArgCount('Reference.remove', 0, 1, arguments.length); + validateWritablePath('Reference.remove', this.path); + validateCallback('Reference.remove', 1, onComplete, true); + + return this.set(null, onComplete); + } + + /** + * @param {function(*):*} transactionUpdate + * @param {(function(?Error, boolean, ?DataSnapshot))=} onComplete + * @param {boolean=} applyLocally + * @return {!Promise} + */ + transaction(transactionUpdate: (a: any) => any, + onComplete?: (a: Error | null, b: boolean, c: DataSnapshot | null) => any, + applyLocally?: boolean): Promise { + validateArgCount('Reference.transaction', 1, 3, arguments.length); + validateWritablePath('Reference.transaction', this.path); + validateCallback('Reference.transaction', 1, transactionUpdate, false); + validateCallback('Reference.transaction', 2, onComplete, true); + // NOTE: applyLocally is an internal-only option for now. We need to decide if we want to keep it and how + // to expose it. + validateBoolean('Reference.transaction', 3, applyLocally, true); + + if (this.getKey() === '.length' || this.getKey() === '.keys') + throw 'Reference.transaction failed: ' + this.getKey() + ' is a read-only object.'; + + if (applyLocally === undefined) + applyLocally = true; + + const deferred = new Deferred(); + if (typeof onComplete === 'function') { + attachDummyErrorHandler(deferred.promise); + } + + const promiseComplete = function (error, committed, snapshot) { + if (error) { + deferred.reject(error); + } else { + deferred.resolve(new TransactionResult(committed, snapshot)); + } + if (typeof onComplete === 'function') { + onComplete(error, committed, snapshot); + } + }; + this.repo.startTransaction(this.path, transactionUpdate, promiseComplete, applyLocally); + + return deferred.promise; + } + + /** + * @param {string|number|null} priority + * @param {function(?Error)=} onComplete + * @return {!Promise} + */ + setPriority(priority: string | number | null, onComplete?: (a: Error | null) => any): Promise { + validateArgCount('Reference.setPriority', 1, 2, arguments.length); + validateWritablePath('Reference.setPriority', this.path); + validatePriority('Reference.setPriority', 1, priority, false); + validateCallback('Reference.setPriority', 2, onComplete, true); + + const deferred = new Deferred(); + this.repo.setWithPriority(this.path.child('.priority'), priority, null, deferred.wrapCallback(onComplete)); + return deferred.promise; + } + + /** + * @param {*=} value + * @param {function(?Error)=} onComplete + * @return {!Reference} + */ + push(value?: any, onComplete?: (a: Error | null) => any): Reference { + validateArgCount('Reference.push', 0, 2, arguments.length); + validateWritablePath('Reference.push', this.path); + validateFirebaseDataArg('Reference.push', 1, value, this.path, true); + validateCallback('Reference.push', 2, onComplete, true); + + const now = this.repo.serverTime(); + const name = nextPushId(now); + + // push() returns a ThennableReference whose promise is fulfilled with a regular Reference. + // We use child() to create handles to two different references. The first is turned into a + // ThennableReference below by adding then() and catch() methods and is used as the + // return value of push(). The second remains a regular Reference and is used as the fulfilled + // value of the first ThennableReference. + const thennablePushRef = this.child(name); + const pushRef = this.child(name); + + let promise; + if (value != null) { + promise = thennablePushRef.set(value, onComplete).then(() => pushRef); + } else { + promise = PromiseImpl.resolve(pushRef); + } + + thennablePushRef.then = promise.then.bind(promise); + thennablePushRef.catch = promise.then.bind(promise, undefined); + + if (typeof onComplete === 'function') { + attachDummyErrorHandler(promise); + } + + return thennablePushRef; + } + + /** + * @return {!OnDisconnect} + */ + onDisconnect(): OnDisconnect { + validateWritablePath('Reference.onDisconnect', this.path); + return new OnDisconnect(this.repo, this.path); + } + + get database(): Database { + return this.databaseProp(); + } + + get key(): string | null { + return this.getKey(); + } + + get parent(): Reference | null { + return this.getParent(); + } + + get root(): Reference { + return this.getRoot(); + } +} + +/** + * Define reference constructor in various modules + * + * We are doing this here to avoid several circular + * dependency issues + */ +Query.__referenceConstructor = Reference; +SyncPoint.__referenceConstructor = Reference; \ No newline at end of file diff --git a/src/database/api/TransactionResult.ts b/src/database/api/TransactionResult.ts new file mode 100644 index 00000000000..d089b2ed47b --- /dev/null +++ b/src/database/api/TransactionResult.ts @@ -0,0 +1,10 @@ +export class TransactionResult { + /** + * A type for the resolve value of Firebase.transaction. + * @constructor + * @dict + * @param {boolean} committed + * @param {fb.api.DataSnapshot} snapshot + */ + constructor(public committed, public snapshot) {} +} \ No newline at end of file diff --git a/src/database/api/internal.ts b/src/database/api/internal.ts new file mode 100644 index 00000000000..b52d60f1d28 --- /dev/null +++ b/src/database/api/internal.ts @@ -0,0 +1,44 @@ +import { WebSocketConnection } from "../realtime/WebSocketConnection"; +import { BrowserPollConnection } from "../realtime/BrowserPollConnection"; + +/** + * INTERNAL methods for internal-use only (tests, etc.). + * + * Customers shouldn't use these or else should be aware that they could break at any time. + * + * @const + */ + +export const forceLongPolling = function() { + WebSocketConnection.forceDisallow(); + BrowserPollConnection.forceAllow(); +}; + +export const forceWebSockets = function() { + BrowserPollConnection.forceDisallow(); +}; + +/* Used by App Manager */ +export const isWebSocketsAvailable = function() { + return WebSocketConnection['isAvailable'](); +}; + +export const setSecurityDebugCallback = function(ref, callback) { + ref.repo.persistentConnection_.securityDebugCallback_ = callback; +}; + +export const stats = function(ref, showDelta) { + ref.repo.stats(showDelta); +}; + +export const statsIncrementCounter = function(ref, metric) { + ref.repo.statsIncrementCounter(metric); +}; + +export const dataUpdateCount = function(ref) { + return ref.repo.dataUpdateCount; +}; + +export const interceptServerData = function(ref, callback) { + return ref.repo.interceptServerData_(callback); +}; diff --git a/src/database/api/onDisconnect.ts b/src/database/api/onDisconnect.ts new file mode 100644 index 00000000000..d192817ce68 --- /dev/null +++ b/src/database/api/onDisconnect.ts @@ -0,0 +1,113 @@ +import { + validateArgCount, + validateCallback +} from "../../utils/validation"; +import { + validateWritablePath, + validateFirebaseDataArg, + validatePriority, + validateFirebaseMergeDataArg, +} from "../core/util/validation"; +import { warn } from "../core/util/util"; +import { Deferred } from "../../utils/promise"; +import { Repo } from '../core/Repo'; +import { Path } from '../core/util/Path'; + +/** + * @constructor + */ +export class OnDisconnect { + /** + * @param {!Repo} repo_ + * @param {!Path} path_ + */ + constructor(private repo_: Repo, + private path_: Path) { + } + + /** + * @param {function(?Error)=} onComplete + * @return {!firebase.Promise} + */ + cancel(onComplete?) { + validateArgCount('OnDisconnect.cancel', 0, 1, arguments.length); + validateCallback('OnDisconnect.cancel', 1, onComplete, true); + const deferred = new Deferred(); + this.repo_.onDisconnectCancel(this.path_, deferred.wrapCallback(onComplete)); + return deferred.promise; + } + + /** + * @param {function(?Error)=} onComplete + * @return {!firebase.Promise} + */ + remove(onComplete?) { + validateArgCount('OnDisconnect.remove', 0, 1, arguments.length); + validateWritablePath('OnDisconnect.remove', this.path_); + validateCallback('OnDisconnect.remove', 1, onComplete, true); + const deferred = new Deferred(); + this.repo_.onDisconnectSet(this.path_, null, deferred.wrapCallback(onComplete)); + return deferred.promise; + } + + /** + * @param {*} value + * @param {function(?Error)=} onComplete + * @return {!firebase.Promise} + */ + set(value, onComplete?) { + validateArgCount('OnDisconnect.set', 1, 2, arguments.length); + validateWritablePath('OnDisconnect.set', this.path_); + validateFirebaseDataArg('OnDisconnect.set', 1, value, this.path_, false); + validateCallback('OnDisconnect.set', 2, onComplete, true); + const deferred = new Deferred(); + this.repo_.onDisconnectSet(this.path_, value, deferred.wrapCallback(onComplete)); + return deferred.promise; + } + + /** + * @param {*} value + * @param {number|string|null} priority + * @param {function(?Error)=} onComplete + * @return {!firebase.Promise} + */ + setWithPriority(value, priority, onComplete?) { + validateArgCount('OnDisconnect.setWithPriority', 2, 3, arguments.length); + validateWritablePath('OnDisconnect.setWithPriority', this.path_); + validateFirebaseDataArg('OnDisconnect.setWithPriority', + 1, value, this.path_, false); + validatePriority('OnDisconnect.setWithPriority', 2, priority, false); + validateCallback('OnDisconnect.setWithPriority', 3, onComplete, true); + + const deferred = new Deferred(); + this.repo_.onDisconnectSetWithPriority(this.path_, value, priority, deferred.wrapCallback(onComplete)); + return deferred.promise; + } + + /** + * @param {!Object} objectToMerge + * @param {function(?Error)=} onComplete + * @return {!firebase.Promise} + */ + update(objectToMerge, onComplete?) { + validateArgCount('OnDisconnect.update', 1, 2, arguments.length); + validateWritablePath('OnDisconnect.update', this.path_); + if (Array.isArray(objectToMerge)) { + const newObjectToMerge = {}; + for (let i = 0; i < objectToMerge.length; ++i) { + newObjectToMerge['' + i] = objectToMerge[i]; + } + objectToMerge = newObjectToMerge; + warn( + 'Passing an Array to firebase.database.onDisconnect().update() is deprecated. Use set() if you want to overwrite the ' + + 'existing data, or an Object with integer keys if you really do want to only update some of the children.' + ); + } + validateFirebaseMergeDataArg('OnDisconnect.update', 1, objectToMerge, + this.path_, false); + validateCallback('OnDisconnect.update', 2, onComplete, true); + const deferred = new Deferred(); + this.repo_.onDisconnectUpdate(this.path_, objectToMerge, deferred.wrapCallback(onComplete)); + return deferred.promise; + } +} \ No newline at end of file diff --git a/src/database/api/test_access.ts b/src/database/api/test_access.ts new file mode 100644 index 00000000000..fbed5b74862 --- /dev/null +++ b/src/database/api/test_access.ts @@ -0,0 +1,72 @@ +import { RepoInfo } from "../core/RepoInfo"; +import { PersistentConnection } from "../core/PersistentConnection"; +import { RepoManager } from "../core/RepoManager"; +import { Connection } from "../realtime/Connection"; + +export const DataConnection = PersistentConnection; + +/** + * @param {!string} pathString + * @param {function(*)} onComplete + */ +(PersistentConnection.prototype as any).simpleListen = function(pathString, onComplete) { + this.sendRequest('q', {'p': pathString}, onComplete); +}; + +/** + * @param {*} data + * @param {function(*)} onEcho + */ +(PersistentConnection.prototype as any).echo = function(data, onEcho) { + this.sendRequest('echo', {'d': data}, onEcho); +}; + +// RealTimeConnection properties that we use in tests. +export const RealTimeConnection = Connection; + +/** + * @param {function(): string} newHash + * @return {function()} + */ +export const hijackHash = function(newHash) { + var oldPut = PersistentConnection.prototype.put; + PersistentConnection.prototype.put = function(pathString, data, opt_onComplete, opt_hash) { + if (opt_hash !== undefined) { + opt_hash = newHash(); + } + oldPut.call(this, pathString, data, opt_onComplete, opt_hash); + }; + return function() { + PersistentConnection.prototype.put = oldPut; + } +}; + +/** + * @type {function(new:fb.core.RepoInfo, !string, boolean, !string, boolean): undefined} + */ +export const ConnectionTarget = RepoInfo; + +/** + * @param {!fb.api.Query} query + * @return {!string} + */ +export const queryIdentifier = function(query) { + return query.queryIdentifier(); +}; + +/** + * @param {!fb.api.Query} firebaseRef + * @return {!Object} + */ +export const listens = function(firebaseRef) { + return firebaseRef.repo.persistentConnection_.listens_; +}; + +/** + * Forces the RepoManager to create Repos that use ReadonlyRestClient instead of PersistentConnection. + * + * @param {boolean} forceRestClient + */ +export const forceRestClient = function(forceRestClient) { + RepoManager.getInstance().forceRestClient(forceRestClient); +}; diff --git a/src/database/common/constants.js b/src/database/common/constants.js deleted file mode 100644 index 7c7d5df7b23..00000000000 --- a/src/database/common/constants.js +++ /dev/null @@ -1,40 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.constants'); - -/** - * @fileoverview Firebase constants. Some of these (@defines) can be overridden at compile-time. - */ - - -/** - * @define {boolean} Whether this is the client Node.js SDK. - */ -var NODE_CLIENT = false; - - -/** - * @define {boolean} Whether this is the Admin Node.js SDK. - */ -var NODE_ADMIN = false; - - -/** - * Public export for NODE_CLIENT and NODE_ADMIN. The linter really hates the way we consume globals - * from other pacakges. - */ -fb.constants.NODE_ADMIN = NODE_ADMIN; -fb.constants.NODE_CLIENT = NODE_CLIENT; diff --git a/src/database/common/util/assert.js b/src/database/common/util/assert.js deleted file mode 100644 index 2d227306499..00000000000 --- a/src/database/common/util/assert.js +++ /dev/null @@ -1,41 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.util.assert'); -goog.provide('fb.util.assertionError'); - -goog.require('fb.constants'); - - -/** - * Throws an error if the provided assertion is falsy - * @param {*} assertion The assertion to be tested for falsiness - * @param {!string} message The message to display if the check fails - */ -fb.util.assert = function(assertion, message) { - if (!assertion) { - throw fb.util.assertionError(message); - } -}; - - -/** - * Returns an Error object suitable for throwing. - * @param {string} message - * @return {!Error} - */ -fb.util.assertionError = function(message) { - return new Error('Firebase Database (' + firebase.SDK_VERSION + ') INTERNAL ASSERT FAILED: ' + message); -}; diff --git a/src/database/common/util/json.js b/src/database/common/util/json.js deleted file mode 100644 index 76a89cd921b..00000000000 --- a/src/database/common/util/json.js +++ /dev/null @@ -1,48 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.util.json'); -goog.require('goog.json'); - - -/** - * Evaluates a JSON string into a javascript object. - * - * @param {string} str A string containing JSON. - * @return {*} The javascript object representing the specified JSON. - */ -fb.util.json.eval = function(str) { - if (typeof JSON !== 'undefined' && goog.isDef(JSON.parse)) { - return JSON.parse(str); - } else { - // NOTE: We could just use eval(), since this case is so rare and the strings we eval are always pretty safe - // (generated by the server or the developer). But goog.json.parse is only a few lines of code, so not - // bothering for now. - return goog.json.parse(str); - } -}; - - -/** - * Returns JSON representing a javascript object. - * @param {*} data Javascript object to be stringified. - * @return {string} The JSON contents of the object. - */ -fb.util.json.stringify = function(data) { - if (typeof JSON !== 'undefined' && goog.isDef(JSON.stringify)) - return JSON.stringify(data); - else - return goog.json.serialize(data); -}; diff --git a/src/database/common/util/jwt.js b/src/database/common/util/jwt.js deleted file mode 100644 index ffe0bad4aae..00000000000 --- a/src/database/common/util/jwt.js +++ /dev/null @@ -1,144 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.util.jwt'); -goog.require('fb.core.util'); -goog.require('fb.util.json'); -goog.require('fb.util.obj'); -goog.require('goog.crypt.base64'); -goog.require('goog.json'); - - -/** - * Decodes a Firebase auth. token into constituent parts. - * - * Notes: - * - May return with invalid / incomplete claims if there's no native base64 decoding support. - * - Doesn't check if the token is actually valid. - * - * @param {?string} token - * @return {{header: *, claims: *, data: *, signature: string}} - */ -fb.util.jwt.decode = function(token) { - var header = {}, - claims = {}, - data = {}, - signature = ''; - - try { - var parts = token.split('.'); - header = fb.util.json.eval(fb.core.util.base64Decode(parts[0]) || ''); - claims = fb.util.json.eval(fb.core.util.base64Decode(parts[1]) || ''); - signature = parts[2]; - data = claims['d'] || {}; - delete claims['d']; - } catch (e) {} - - return { - header: header, - claims: claims, - data: data, - signature: signature - }; -}; - -/** - * Decodes a Firebase auth. token and checks the validity of its time-based claims. Will return true if the - * token is within the time window authorized by the 'nbf' (not-before) and 'iat' (issued-at) claims. - * - * Notes: - * - May return a false negative if there's no native base64 decoding support. - * - Doesn't check if the token is actually valid. - * - * @param {?string} token - * @return {boolean} - */ -fb.util.jwt.isValidTimestamp = function(token) { - var claims = fb.util.jwt.decode(token).claims, - now = Math.floor(new Date().getTime() / 1000), - validSince, validUntil; - - if (typeof claims === 'object') { - if (claims.hasOwnProperty('nbf')) { - validSince = fb.util.obj.get(claims, 'nbf'); - } else if (claims.hasOwnProperty('iat')) { - validSince = fb.util.obj.get(claims, 'iat'); - } - - if (claims.hasOwnProperty('exp')) { - validUntil = fb.util.obj.get(claims, 'exp'); - } else { - // token will expire after 24h by default - validUntil = validSince + 86400; - } - } - - return now && validSince && validUntil && - (now >= validSince) && (now <= validUntil); -}; - -/** - * Decodes a Firebase auth. token and returns its issued at time if valid, null otherwise. - * - * Notes: - * - May return null if there's no native base64 decoding support. - * - Doesn't check if the token is actually valid. - * - * @param {?string} token - * @return {?number} - */ -fb.util.jwt.issuedAtTime = function(token) { - var claims = fb.util.jwt.decode(token).claims; - if (typeof claims === 'object' && claims.hasOwnProperty('iat')) { - return fb.util.obj.get(claims, 'iat'); - } - return null; -}; - -/** - * Decodes a Firebase auth. token and checks the validity of its format. Expects a valid issued-at time and non-empty - * signature. - * - * Notes: - * - May return a false negative if there's no native base64 decoding support. - * - Doesn't check if the token is actually valid. - * - * @param {?string} token - * @return {boolean} - */ -fb.util.jwt.isValidFormat = function(token) { - var decoded = fb.util.jwt.decode(token), - claims = decoded.claims; - - return !!decoded.signature && - !!claims && - (typeof claims === 'object') && - claims.hasOwnProperty('iat'); -}; - -/** - * Attempts to peer into an auth token and determine if it's an admin auth token by looking at the claims portion. - * - * Notes: - * - May return a false negative if there's no native base64 decoding support. - * - Doesn't check if the token is actually valid. - * - * @param {?string} token - * @return {boolean} - */ -fb.util.jwt.isAdmin = function(token) { - var claims = fb.util.jwt.decode(token).claims; - return (typeof claims === 'object' && fb.util.obj.get(claims, 'admin') === true); -}; diff --git a/src/database/common/util/obj.js b/src/database/common/util/obj.js deleted file mode 100644 index 6d042b7a3f5..00000000000 --- a/src/database/common/util/obj.js +++ /dev/null @@ -1,78 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.util.obj'); - -// See http://www.devthought.com/2012/01/18/an-object-is-not-a-hash/ - -fb.util.obj.contains = function(obj, key) { - return Object.prototype.hasOwnProperty.call(obj, key); -}; - -fb.util.obj.get = function(obj, key) { - if (Object.prototype.hasOwnProperty.call(obj, key)) - return obj[key]; - // else return undefined. -}; - -/** - * Enumerates the keys/values in an object, excluding keys defined on the prototype. - * - * @param {?Object.} obj Object to enumerate. - * @param {!function(K, V)} fn Function to call for each key and value. - * @template K,V - */ -fb.util.obj.foreach = function(obj, fn) { - for (var key in obj) { - if (Object.prototype.hasOwnProperty.call(obj, key)) { - fn(key, obj[key]); - } - } -}; - -/** - * Copies all the (own) properties from one object to another. - * @param {!Object} objTo - * @param {!Object} objFrom - * @return {!Object} objTo - */ -fb.util.obj.extend = function(objTo, objFrom) { - fb.util.obj.foreach(objFrom, function(key, value) { - objTo[key] = value; - }); - return objTo; -} - - -/** - * Returns a clone of the specified object. - * @param {!Object} obj - * @return {!Object} cloned obj. - */ -fb.util.obj.clone = function(obj) { - return fb.util.obj.extend({}, obj); -}; - - -/** - * Returns true if obj has typeof "object" and is not null. Unlike goog.isObject(), does not return true - * for functions. - * - * @param obj {*} A potential object. - * @returns {boolean} True if it's an object. - */ -fb.util.obj.isNonNullObject = function(obj) { - return typeof obj === 'object' && obj !== null; -}; diff --git a/src/database/common/util/promise.js b/src/database/common/util/promise.js deleted file mode 100644 index aa42c3e8138..00000000000 --- a/src/database/common/util/promise.js +++ /dev/null @@ -1,96 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.util.promise'); -goog.provide('fb.util.promise.Deferred'); -goog.provide('fb.util.promise.Promise'); - -goog.scope(function() { -'use strict'; - - -/** - * Import the Promise implementation from firebase namespace. - */ -fb.util.promise.Promise = firebase.Promise; - - -/** - * A deferred promise implementation. - */ -fb.util.promise.Deferred = goog.defineClass(null, { - /** @constructor */ - constructor: function() { - var self = this; - this.resolve = null; - this.reject = null; - this.promise = new fb.util.promise.Promise(function(resolve, reject) { - self.resolve = resolve; - self.reject = reject; - }); - }, - - /** - * Our API internals are not promiseified and cannot because our callback APIs have subtle expectations around - * invoking promises inline, which Promises are forbidden to do. This method accepts an optional node-style callback - * and returns a node-style callback which will resolve or reject the Deferred's promise. - * @param {((?function(?(Error)): (?|undefined))| (?function(?(Error),?=): (?|undefined)))=} opt_nodeCallback - * @return {!function(?(Error), ?=)} - */ - wrapCallback: function(opt_nodeCallback) { - var self = this; - /** - * @param {?Error} error - * @param {?=} opt_value - */ - function meta(error, opt_value) { - if (error) { - self.reject(error); - } else { - self.resolve(opt_value); - } - if (goog.isFunction(opt_nodeCallback)) { - fb.util.promise.attachDummyErrorHandler(self.promise); - - // Some of our callbacks don't expect a value and our own tests - // assert that the parameter length is 1 - if (opt_nodeCallback.length === 1) { - opt_nodeCallback(error); - } else { - opt_nodeCallback(error, opt_value); - } - } - } - return meta; - } -}); - - -/** - * Chrome (and maybe other browsers) report an Error in the console if you reject a promise - * and nobody handles the error. This is normally a good thing, but this will confuse devs who - * never intended to use promises in the first place. So in some cases (in particular, if the - * developer attached a callback), we should attach a dummy resolver to the promise to suppress - * this error. - * - * Note: We can't do this all the time, since it breaks the Promise spec (though in the obscure - * 3.3.3 section related to upgrading non-compliant promises). - * @param {!firebase.Promise} promise - */ -fb.util.promise.attachDummyErrorHandler = function(promise) { - promise.then(void 0, goog.nullFunction); -}; - -}); // goog.scope diff --git a/src/database/common/util/utf8.js b/src/database/common/util/utf8.js deleted file mode 100644 index 15282ffbb57..00000000000 --- a/src/database/common/util/utf8.js +++ /dev/null @@ -1,92 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.util.utf8'); -goog.require('fb.util.assert'); - - -// Code originally came from goog.crypt.stringToUtf8ByteArray, but for some reason they -// automatically replaced '\r\n' with '\n', and they didn't handle surrogate pairs, -// so it's been modified. - -// Note that not all Unicode characters appear as single characters in JavaScript strings. -// fromCharCode returns the UTF-16 encoding of a character - so some Unicode characters -// use 2 characters in Javascript. All 4-byte UTF-8 characters begin with a first -// character in the range 0xD800 - 0xDBFF (the first character of a so-called surrogate -// pair). -// See http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.3 - - -/** - * @param {string} str - * @return {Array} - */ -fb.util.utf8.stringToByteArray = function(str) { - var out = [], p = 0; - for (var i = 0; i < str.length; i++) { - var c = str.charCodeAt(i); - - // Is this the lead surrogate in a surrogate pair? - if (c >= 0xd800 && c <= 0xdbff) { - var high = c - 0xd800; // the high 10 bits. - i++; - fb.util.assert(i < str.length, 'Surrogate pair missing trail surrogate.'); - var low = str.charCodeAt(i) - 0xdc00; // the low 10 bits. - c = 0x10000 + (high << 10) + low; - } - - if (c < 128) { - out[p++] = c; - } else if (c < 2048) { - out[p++] = (c >> 6) | 192; - out[p++] = (c & 63) | 128; - } else if (c < 65536) { - out[p++] = (c >> 12) | 224; - out[p++] = ((c >> 6) & 63) | 128; - out[p++] = (c & 63) | 128; - } else { - out[p++] = (c >> 18) | 240; - out[p++] = ((c >> 12) & 63) | 128; - out[p++] = ((c >> 6) & 63) | 128; - out[p++] = (c & 63) | 128; - } - } - return out; -}; - - -/** - * Calculate length without actually converting; useful for doing cheaper validation. - * @param {string} str - * @return {number} - */ -fb.util.utf8.stringLength = function(str) { - var p = 0; - for (var i = 0; i < str.length; i++) { - var c = str.charCodeAt(i); - if (c < 128) { - p++; - } else if (c < 2048) { - p += 2; - } else if (c >= 0xd800 && c <= 0xdbff) { - // Lead surrogate of a surrogate pair. The pair together will take 4 bytes to represent. - p += 4; - i++; // skip trail surrogate. - } else { - p += 3; - } - } - return p; -}; diff --git a/src/database/common/util/util.js b/src/database/common/util/util.js deleted file mode 100644 index 49849256d0d..00000000000 --- a/src/database/common/util/util.js +++ /dev/null @@ -1,60 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.util'); -goog.require('fb.util.obj'); - - -/** - * Returns a querystring-formatted string (e.g. &arg=val&arg2=val2) from a params - * object (e.g. {arg: 'val', arg2: 'val2'}) - * Note: You must prepend it with ? when adding it to a URL. - * - * @param {!Object} querystringParams - * @return {string} - */ -fb.util.querystring = function(querystringParams) { - var params = []; - fb.util.obj.foreach(querystringParams, function(key, value) { - if (goog.isArray(value)) { - goog.array.forEach(value, function(arrayVal) { - params.push(encodeURIComponent(key) + '=' + encodeURIComponent(arrayVal)); - }); - } else { - params.push(encodeURIComponent(key) + '=' + encodeURIComponent(value)); - } - }); - return (params.length) ? '&' + params.join('&') : ''; -}; - - -/** - * Decodes a querystring (e.g. ?arg=val&arg2=val2) into a params object (e.g. {arg: 'val', arg2: 'val2'}) - * - * @param {string} querystring - * @return {!Object} - */ -fb.util.querystringDecode = function(querystring) { - var obj = {}; - var tokens = querystring.replace(/^\?/, '').split('&'); - - goog.array.forEach(tokens, function(token) { - if (token) { - var key = token.split('='); - obj[key[0]] = key[1]; - } - }); - return obj; -}; diff --git a/src/database/common/util/validation.js b/src/database/common/util/validation.js deleted file mode 100644 index c48b69e663e..00000000000 --- a/src/database/common/util/validation.js +++ /dev/null @@ -1,104 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.util.validation'); - -/** - * Check to make sure the appropriate number of arguments are provided for a public function. - * Throws an error if it fails. - * - * @param {!string} fnName The function name - * @param {!number} minCount The minimum number of arguments to allow for the function call - * @param {!number} maxCount The maximum number of argument to allow for the function call - * @param {!number} argCount The actual number of arguments provided. - */ -fb.util.validation.validateArgCount = function(fnName, minCount, maxCount, argCount) { - var argError; - if (argCount < minCount) { - argError = 'at least ' + minCount; - } else if (argCount > maxCount) { - argError = (maxCount === 0) ? 'none' : ('no more than ' + maxCount); - } - if (argError) { - var error = fnName + ' failed: Was called with ' + argCount + - ((argCount === 1) ? ' argument.' : ' arguments.') + - ' Expects ' + argError + '.'; - throw new Error(error); - } -}; - -/** - * Generates a string to prefix an error message about failed argument validation - * - * @param {!string} fnName The function name - * @param {!number} argumentNumber The index of the argument - * @param {boolean} optional Whether or not the argument is optional - * @return {!string} The prefix to add to the error thrown for validation. - */ -fb.util.validation.errorPrefix = function(fnName, argumentNumber, optional) { - var argName = ''; - switch (argumentNumber) { - case 1: - argName = optional ? 'first' : 'First'; - break; - case 2: - argName = optional ? 'second' : 'Second'; - break; - case 3: - argName = optional ? 'third' : 'Third'; - break; - case 4: - argName = optional ? 'fourth' : 'Fourth'; - break; - default: - throw new Error('errorPrefix called with argumentNumber > 4. Need to update it?'); - } - - var error = fnName + ' failed: '; - - error += argName + ' argument '; - return error; -}; - -/** - * @param {!string} fnName - * @param {!number} argumentNumber - * @param {!string} namespace - * @param {boolean} optional - */ -fb.util.validation.validateNamespace = function(fnName, argumentNumber, namespace, optional) { - if (optional && !goog.isDef(namespace)) - return; - if (!goog.isString(namespace)) { - //TODO: I should do more validation here. We only allow certain chars in namespaces. - throw new Error(fb.util.validation.errorPrefix(fnName, argumentNumber, optional) + - 'must be a valid firebase namespace.'); - } -}; - -fb.util.validation.validateCallback = function(fnName, argumentNumber, callback, optional) { - if (optional && !goog.isDef(callback)) - return; - if (!goog.isFunction(callback)) - throw new Error(fb.util.validation.errorPrefix(fnName, argumentNumber, optional) + 'must be a valid function.'); -}; - -fb.util.validation.validateContextObject = function(fnName, argumentNumber, context, optional) { - if (optional && !goog.isDef(context)) - return; - if (!goog.isObject(context) || context === null) - throw new Error(fb.util.validation.errorPrefix(fnName, argumentNumber, optional) + - 'must be a valid context object.'); -}; diff --git a/src/database/core/AuthTokenProvider.ts b/src/database/core/AuthTokenProvider.ts new file mode 100644 index 00000000000..1dd486c9517 --- /dev/null +++ b/src/database/core/AuthTokenProvider.ts @@ -0,0 +1,67 @@ +import { log, warn } from "./util/util"; + +/** + * Abstraction around FirebaseApp's token fetching capabilities. + */ +export class AuthTokenProvider { + private app_; + + /** + * @param {!firebase.app.App} app + */ + constructor(app) { + /** @private {!firebase.app.App} */ + this.app_ = app; + } + + /** + * @param {boolean} forceRefresh + * @return {!Promise} + */ + getToken(forceRefresh) { + return this.app_['INTERNAL']['getToken'](forceRefresh) + .then( + null, + // .catch + function(error) { + // TODO: Need to figure out all the cases this is raised and whether + // this makes sense. + if (error && error.code === 'auth/token-not-initialized') { + log('Got auth/token-not-initialized error. Treating as null token.'); + return null; + } else { + return Promise.reject(error); + } + }); + } + + addTokenChangeListener(listener) { + // TODO: We might want to wrap the listener and call it with no args to + // avoid a leaky abstraction, but that makes removing the listener harder. + this.app_['INTERNAL']['addAuthTokenListener'](listener); + } + + removeTokenChangeListener(listener) { + this.app_['INTERNAL']['removeAuthTokenListener'](listener); + } + + notifyForInvalidToken() { + var errorMessage = 'Provided authentication credentials for the app named "' + + this.app_.name + '" are invalid. This usually indicates your app was not ' + + 'initialized correctly. '; + if ('credential' in this.app_.options) { + errorMessage += 'Make sure the "credential" property provided to initializeApp() ' + + 'is authorized to access the specified "databaseURL" and is from the correct ' + + 'project.'; + } else if ('serviceAccount' in this.app_.options) { + errorMessage += 'Make sure the "serviceAccount" property provided to initializeApp() ' + + 'is authorized to access the specified "databaseURL" and is from the correct ' + + 'project.'; + } else { + errorMessage += 'Make sure the "apiKey" and "databaseURL" properties provided to ' + + 'initializeApp() match the values provided for your app at ' + + 'https://console.firebase.google.com/.'; + } + warn(errorMessage); + } +}; diff --git a/src/database/core/CompoundWrite.ts b/src/database/core/CompoundWrite.ts new file mode 100644 index 00000000000..1843b7429a2 --- /dev/null +++ b/src/database/core/CompoundWrite.ts @@ -0,0 +1,196 @@ +import { ImmutableTree } from "./util/ImmutableTree"; +import { Path } from "./util/Path"; +import { forEach } from "../../utils/obj"; +import { Node, NamedNode } from "./snap/Node"; +import { PRIORITY_INDEX } from "./snap/indexes/PriorityIndex"; +import { assert } from "../../utils/assert"; + +/** + * This class holds a collection of writes that can be applied to nodes in unison. It abstracts away the logic with + * dealing with priority writes and multiple nested writes. At any given path there is only allowed to be one write + * modifying that path. Any write to an existing path or shadowing an existing path will modify that existing write + * to reflect the write added. + * + * @constructor + * @param {!ImmutableTree.} writeTree + */ +export class CompoundWrite { + constructor(private writeTree_: ImmutableTree) {}; + /** + * @type {!CompoundWrite} + */ + static Empty = new CompoundWrite(new ImmutableTree(null)); + + /** + * @param {!Path} path + * @param {!Node} node + * @return {!CompoundWrite} + */ + addWrite(path: Path, node: Node): CompoundWrite { + if (path.isEmpty()) { + return new CompoundWrite(new ImmutableTree(node)); + } else { + var rootmost = this.writeTree_.findRootMostValueAndPath(path); + if (rootmost != null) { + var rootMostPath = rootmost.path + var value = rootmost.value; + var relativePath = Path.relativePath(rootMostPath, path); + value = value.updateChild(relativePath, node); + return new CompoundWrite(this.writeTree_.set(rootMostPath, value)); + } else { + var subtree = new ImmutableTree(node); + var newWriteTree = this.writeTree_.setTree(path, subtree); + return new CompoundWrite(newWriteTree); + } + } + }; + + /** + * @param {!Path} path + * @param {!Object.} updates + * @return {!CompoundWrite} + */ + addWrites(path: Path, updates: { [name: string]: Node }): CompoundWrite { + var newWrite = this; + forEach(updates, function(childKey, node) { + newWrite = newWrite.addWrite(path.child(childKey), node); + }); + return newWrite; + }; + + /** + * Will remove a write at the given path and deeper paths. This will not modify a write at a higher + * location, which must be removed by calling this method with that path. + * + * @param {!Path} path The path at which a write and all deeper writes should be removed + * @return {!CompoundWrite} The new CompoundWrite with the removed path + */ + removeWrite(path: Path): CompoundWrite { + if (path.isEmpty()) { + return CompoundWrite.Empty; + } else { + var newWriteTree = this.writeTree_.setTree(path, ImmutableTree.Empty); + return new CompoundWrite(newWriteTree); + } + }; + + /** + * Returns whether this CompoundWrite will fully overwrite a node at a given location and can therefore be + * considered "complete". + * + * @param {!Path} path The path to check for + * @return {boolean} Whether there is a complete write at that path + */ + hasCompleteWrite(path: Path): boolean { + return this.getCompleteNode(path) != null; + }; + + /** + * Returns a node for a path if and only if the node is a "complete" overwrite at that path. This will not aggregate + * writes from deeper paths, but will return child nodes from a more shallow path. + * + * @param {!Path} path The path to get a complete write + * @return {?Node} The node if complete at that path, or null otherwise. + */ + getCompleteNode(path: Path): Node { + var rootmost = this.writeTree_.findRootMostValueAndPath(path); + if (rootmost != null) { + return this.writeTree_.get(rootmost.path).getChild(Path.relativePath(rootmost.path, path)); + } else { + return null; + } + }; + + /** + * Returns all children that are guaranteed to be a complete overwrite. + * + * @return {!Array.} A list of all complete children. + */ + getCompleteChildren(): Array { + var children = []; + var node = this.writeTree_.value; + if (node != null) { + // If it's a leaf node, it has no children; so nothing to do. + if (!node.isLeafNode()) { + node = /** @type {!ChildrenNode} */ (node); + node.forEachChild(PRIORITY_INDEX, function(childName, childNode) { + children.push(new NamedNode(childName, childNode)); + }); + } + } else { + this.writeTree_.children.inorderTraversal(function(childName, childTree) { + if (childTree.value != null) { + children.push(new NamedNode(childName, childTree.value)); + } + }); + } + return children; + }; + + /** + * @param {!Path} path + * @return {!CompoundWrite} + */ + childCompoundWrite(path: Path) { + if (path.isEmpty()) { + return this; + } else { + var shadowingNode = this.getCompleteNode(path); + if (shadowingNode != null) { + return new CompoundWrite(new ImmutableTree(shadowingNode)); + } else { + return new CompoundWrite(this.writeTree_.subtree(path)); + } + } + }; + + /** + * Returns true if this CompoundWrite is empty and therefore does not modify any nodes. + * @return {boolean} Whether this CompoundWrite is empty + */ + isEmpty() { + return this.writeTree_.isEmpty(); + }; + + /** + * Applies this CompoundWrite to a node. The node is returned with all writes from this CompoundWrite applied to the + * node + * @param {!Node} node The node to apply this CompoundWrite to + * @return {!Node} The node with all writes applied + */ + apply(node: Node) { + return CompoundWrite.applySubtreeWrite_(Path.Empty, this.writeTree_, node); + }; + + /** + * @param {!Path} relativePath + * @param {!ImmutableTree.} writeTree + * @param {!Node} node + * @return {!Node} + * @private + */ + static applySubtreeWrite_ = function(relativePath: Path, writeTree: ImmutableTree, node: Node) { + if (writeTree.value != null) { + // Since there a write is always a leaf, we're done here + return node.updateChild(relativePath, writeTree.value); + } else { + var priorityWrite = null; + writeTree.children.inorderTraversal(function(childKey, childTree) { + if (childKey === '.priority') { + // Apply priorities at the end so we don't update priorities for either empty nodes or forget + // to apply priorities to empty nodes that are later filled + assert(childTree.value !== null, 'Priority writes must always be leaf nodes'); + priorityWrite = childTree.value; + } else { + node = CompoundWrite.applySubtreeWrite_(relativePath.child(childKey), childTree, node); + } + }); + // If there was a priority write, we only apply it if the node is not empty + if (!node.getChild(relativePath).isEmpty() && priorityWrite !== null) { + node = node.updateChild(relativePath.child('.priority'), priorityWrite); + } + return node; + } + }; +} + diff --git a/src/database/core/PersistentConnection.ts b/src/database/core/PersistentConnection.ts new file mode 100644 index 00000000000..34741d4bfc4 --- /dev/null +++ b/src/database/core/PersistentConnection.ts @@ -0,0 +1,888 @@ +import firebase from "../../app"; +import { forEach, contains, isEmpty, getCount, safeGet } from "../../utils/obj"; +import { stringify } from "../../utils/json"; +import { assert } from '../../utils/assert'; +import { error, log, logWrapper, warn, ObjectToUniqueKey } from "./util/util"; +import { Path } from "./util/Path"; +import { VisibilityMonitor } from "./util/VisibilityMonitor"; +import { OnlineMonitor } from "./util/OnlineMonitor"; +import { isAdmin, isValidFormat } from "../../utils/jwt"; +import { Connection } from "../realtime/Connection"; +import { CONSTANTS } from "../../utils/constants"; +import { + isMobileCordova, + isReactNative, + isNodeSdk +} from "../../utils/environment"; + +var RECONNECT_MIN_DELAY = 1000; +var RECONNECT_MAX_DELAY_DEFAULT = 60 * 5 * 1000; // 5 minutes in milliseconds (Case: 1858) +var RECONNECT_MAX_DELAY_FOR_ADMINS = 30 * 1000; // 30 seconds for admin clients (likely to be a backend server) +var RECONNECT_DELAY_MULTIPLIER = 1.3; +var RECONNECT_DELAY_RESET_TIMEOUT = 30000; // Reset delay back to MIN_DELAY after being connected for 30sec. +var SERVER_KILL_INTERRUPT_REASON = "server_kill"; + +// If auth fails repeatedly, we'll assume something is wrong and log a warning / back off. +var INVALID_AUTH_TOKEN_THRESHOLD = 3; + +/** + * Firebase connection. Abstracts wire protocol and handles reconnecting. + * + * NOTE: All JSON objects sent to the realtime connection must have property names enclosed + * in quotes to make sure the closure compiler does not minify them. + */ +export class PersistentConnection { + // Used for diagnostic logging. + id; + log_; + /** @private {Object} */ + interruptReasons_; + listens_; + outstandingPuts_; + outstandingPutCount_; + onDisconnectRequestQueue_; + connected_; + reconnectDelay_; + maxReconnectDelay_; + onDataUpdate_; + onConnectStatus_; + onServerInfoUpdate_; + repoInfo_; + securityDebugCallback_; + lastSessionId; + /** @private {?{ + * sendRequest(Object), + * close() + * }} */ + private realtime_; + /** @private {string|null} */ + authToken_; + authTokenProvider_; + forceTokenRefresh_; + invalidAuthTokenCount_; + /** @private {Object|null|undefined} */ + private authOverride_; + /** @private {number|null} */ + private establishConnectionTimer_; + /** @private {boolean} */ + private visible_; + + // Before we get connected, we keep a queue of pending messages to send. + requestCBHash_; + requestNumber_; + + firstConnection_; + lastConnectionAttemptTime_; + lastConnectionEstablishedTime_; + + /** + * @private + */ + static nextPersistentConnectionId_ = 0; + + /** + * Counter for number of connections created. Mainly used for tagging in the logs + * @type {number} + * @private + */ + static nextConnectionId_ = 0; + /** + * @implements {ServerActions} + * @param {!RepoInfo} repoInfo Data about the namespace we are connecting to + * @param {function(string, *, boolean, ?number)} onDataUpdate A callback for new data from the server + */ + constructor(repoInfo, onDataUpdate, onConnectStatus, + onServerInfoUpdate, authTokenProvider, authOverride) { + // Used for diagnostic logging. + this.id = PersistentConnection.nextPersistentConnectionId_++; + this.log_ = logWrapper('p:' + this.id + ':'); + /** @private {Object} */ + this.interruptReasons_ = { }; + this.listens_ = {}; + this.outstandingPuts_ = []; + this.outstandingPutCount_ = 0; + this.onDisconnectRequestQueue_ = []; + this.connected_ = false; + this.reconnectDelay_ = RECONNECT_MIN_DELAY; + this.maxReconnectDelay_ = RECONNECT_MAX_DELAY_DEFAULT; + this.onDataUpdate_ = onDataUpdate; + this.onConnectStatus_ = onConnectStatus; + this.onServerInfoUpdate_ = onServerInfoUpdate; + this.repoInfo_ = repoInfo; + this.securityDebugCallback_ = null; + this.lastSessionId = null; + /** @private {?{ + * sendRequest(Object), + * close() + * }} */ + this.realtime_ = null; + /** @private {string|null} */ + this.authToken_ = null; + this.authTokenProvider_ = authTokenProvider; + this.forceTokenRefresh_ = false; + this.invalidAuthTokenCount_ = 0; + if (authOverride && !isNodeSdk()) { + throw new Error('Auth override specified in options, but not supported on non Node.js platforms'); + } + /** private {Object|null|undefined} */ + this.authOverride_ = authOverride; + /** @private {number|null} */ + this.establishConnectionTimer_ = null; + /** @private {boolean} */ + this.visible_ = false; + + // Before we get connected, we keep a queue of pending messages to send. + this.requestCBHash_ = {}; + this.requestNumber_ = 0; + + this.firstConnection_ = true; + this.lastConnectionAttemptTime_ = null; + this.lastConnectionEstablishedTime_ = null; + this.scheduleConnect_(0); + + VisibilityMonitor.getInstance().on('visible', this.onVisible_, this); + + if (repoInfo.host.indexOf('fblocal') === -1) { + OnlineMonitor.getInstance().on('online', this.onOnline_, this); + } + } + + /** + * @param {!string} action + * @param {*} body + * @param {function(*)=} onResponse + * @protected + */ + sendRequest(action, body, onResponse?) { + var curReqNum = ++this.requestNumber_; + + var msg = {'r': curReqNum, 'a': action, 'b': body}; + this.log_(stringify(msg)); + assert(this.connected_, "sendRequest call when we're not connected not allowed."); + this.realtime_.sendRequest(msg); + if (onResponse) { + this.requestCBHash_[curReqNum] = onResponse; + } + } + + /** + * @inheritDoc + */ + listen(query, currentHashFn, tag, onComplete) { + var queryId = query.queryIdentifier(); + var pathString = query.path.toString(); + this.log_('Listen called for ' + pathString + ' ' + queryId); + this.listens_[pathString] = this.listens_[pathString] || {}; + assert(query.getQueryParams().isDefault() || !query.getQueryParams().loadsAllData(), + 'listen() called for non-default but complete query'); + assert(!this.listens_[pathString][queryId], 'listen() called twice for same path/queryId.'); + var listenSpec = { + onComplete: onComplete, + hashFn: currentHashFn, + query: query, + tag: tag + }; + this.listens_[pathString][queryId] = listenSpec; + + if (this.connected_) { + this.sendListen_(listenSpec); + } + } + + /** + * @param {!{onComplete(), + * hashFn():!string, + * query: !Query, + * tag: ?number}} listenSpec + * @private + */ + sendListen_(listenSpec) { + var query = listenSpec.query; + var pathString = query.path.toString(); + var queryId = query.queryIdentifier(); + var self = this; + this.log_('Listen on ' + pathString + ' for ' + queryId); + var req = {/*path*/ 'p': pathString}; + + var action = 'q'; + + // Only bother to send query if it's non-default. + if (listenSpec.tag) { + req['q'] = query.queryObject(); + req['t'] = listenSpec.tag; + } + + req[/*hash*/'h'] = listenSpec.hashFn(); + + this.sendRequest(action, req, function(message) { + var payload = message[/*data*/ 'd']; + var status = message[/*status*/ 's']; + + // print warnings in any case... + self.warnOnListenWarnings_(payload, query); + + var currentListenSpec = self.listens_[pathString] && self.listens_[pathString][queryId]; + // only trigger actions if the listen hasn't been removed and readded + if (currentListenSpec === listenSpec) { + self.log_('listen response', message); + + if (status !== 'ok') { + self.removeListen_(pathString, queryId); + } + + if (listenSpec.onComplete) { + listenSpec.onComplete(status, payload); + } + } + }); + } + + /** + * @param {*} payload + * @param {!Query} query + * @private + */ + warnOnListenWarnings_(payload, query) { + if (payload && typeof payload === 'object' && contains(payload, 'w')) { + var warnings = safeGet(payload, 'w'); + if (Array.isArray(warnings) && ~warnings.indexOf('no_index')) { + var indexSpec = '".indexOn": "' + query.getQueryParams().getIndex().toString() + '"'; + var indexPath = query.path.toString(); + warn('Using an unspecified index. Consider adding ' + indexSpec + ' at ' + indexPath + + ' to your security rules for better performance'); + } + } + } + + /** + * @inheritDoc + */ + refreshAuthToken(token) { + this.authToken_ = token; + this.log_('Auth token refreshed'); + if (this.authToken_) { + this.tryAuth(); + } else { + //If we're connected we want to let the server know to unauthenticate us. If we're not connected, simply delete + //the credential so we dont become authenticated next time we connect. + if (this.connected_) { + this.sendRequest('unauth', {}, function() { }); + } + } + + this.reduceReconnectDelayIfAdminCredential_(token); + } + + /** + * @param {!string} credential + * @private + */ + reduceReconnectDelayIfAdminCredential_(credential) { + // NOTE: This isn't intended to be bulletproof (a malicious developer can always just modify the client). + // Additionally, we don't bother resetting the max delay back to the default if auth fails / expires. + var isFirebaseSecret = credential && credential.length === 40; + if (isFirebaseSecret || isAdmin(credential)) { + this.log_('Admin auth credential detected. Reducing max reconnect time.'); + this.maxReconnectDelay_ = RECONNECT_MAX_DELAY_FOR_ADMINS; + } + } + + /** + * Attempts to authenticate with the given credentials. If the authentication attempt fails, it's triggered like + * a auth revoked (the connection is closed). + */ + tryAuth() { + var self = this; + if (this.connected_ && this.authToken_) { + var token = this.authToken_; + var authMethod = isValidFormat(token) ? 'auth' : 'gauth'; + var requestData = {'cred': token}; + if (this.authOverride_ === null) { + requestData['noauth'] = true; + } else if (typeof this.authOverride_ === 'object') { + requestData['authvar'] = this.authOverride_; + } + this.sendRequest(authMethod, requestData, function(res) { + var status = res[/*status*/ 's']; + var data = res[/*data*/ 'd'] || 'error'; + + if (self.authToken_ === token) { + if (status === 'ok') { + self.invalidAuthTokenCount_ = 0; + } else { + // Triggers reconnect and force refresh for auth token + self.onAuthRevoked_(status, data); + } + } + }); + } + } + + /** + * @inheritDoc + */ + unlisten(query, tag) { + var pathString = query.path.toString(); + var queryId = query.queryIdentifier(); + + this.log_("Unlisten called for " + pathString + " " + queryId); + + assert(query.getQueryParams().isDefault() || !query.getQueryParams().loadsAllData(), + 'unlisten() called for non-default but complete query'); + var listen = this.removeListen_(pathString, queryId); + if (listen && this.connected_) { + this.sendUnlisten_(pathString, queryId, query.queryObject(), tag); + } + } + + sendUnlisten_(pathString, queryId, queryObj, tag) { + this.log_('Unlisten on ' + pathString + ' for ' + queryId); + var self = this; + + var req = {/*path*/ 'p': pathString}; + var action = 'n'; + // Only bother send queryId if it's non-default. + if (tag) { + req['q'] = queryObj; + req['t'] = tag; + } + + this.sendRequest(action, req); + } + + /** + * @inheritDoc + */ + onDisconnectPut(pathString, data, opt_onComplete) { + if (this.connected_) { + this.sendOnDisconnect_('o', pathString, data, opt_onComplete); + } else { + this.onDisconnectRequestQueue_.push({ + pathString: pathString, + action: 'o', + data: data, + onComplete: opt_onComplete + }); + } + } + + /** + * @inheritDoc + */ + onDisconnectMerge(pathString, data, opt_onComplete) { + if (this.connected_) { + this.sendOnDisconnect_('om', pathString, data, opt_onComplete); + } else { + this.onDisconnectRequestQueue_.push({ + pathString: pathString, + action: 'om', + data: data, + onComplete: opt_onComplete + }); + } + } + + /** + * @inheritDoc + */ + onDisconnectCancel(pathString, opt_onComplete) { + if (this.connected_) { + this.sendOnDisconnect_('oc', pathString, null, opt_onComplete); + } else { + this.onDisconnectRequestQueue_.push({ + pathString: pathString, + action: 'oc', + data: null, + onComplete: opt_onComplete + }); + } + } + + sendOnDisconnect_(action, pathString, data, opt_onComplete) { + var self = this; + var request = {/*path*/ 'p': pathString, /*data*/ 'd': data}; + self.log_('onDisconnect ' + action, request); + this.sendRequest(action, request, function(response) { + if (opt_onComplete) { + setTimeout(function() { + opt_onComplete(response[/*status*/ 's'], response[/* data */'d']); + }, Math.floor(0)); + } + }); + } + + /** + * @inheritDoc + */ + put(pathString, data, opt_onComplete, opt_hash) { + this.putInternal('p', pathString, data, opt_onComplete, opt_hash); + } + + /** + * @inheritDoc + */ + merge(pathString, data, onComplete, opt_hash) { + this.putInternal('m', pathString, data, onComplete, opt_hash); + } + + putInternal(action, pathString, data, opt_onComplete, opt_hash) { + var request = {/*path*/ 'p': pathString, /*data*/ 'd': data }; + + if (opt_hash !== undefined) + request[/*hash*/ 'h'] = opt_hash; + + // TODO: Only keep track of the most recent put for a given path? + this.outstandingPuts_.push({ + action: action, + request: request, + onComplete: opt_onComplete + }); + + this.outstandingPutCount_++; + var index = this.outstandingPuts_.length - 1; + + if (this.connected_) { + this.sendPut_(index); + } else { + this.log_('Buffering put: ' + pathString); + } + } + + sendPut_(index) { + var self = this; + var action = this.outstandingPuts_[index].action; + var request = this.outstandingPuts_[index].request; + var onComplete = this.outstandingPuts_[index].onComplete; + this.outstandingPuts_[index].queued = this.connected_; + + this.sendRequest(action, request, function(message) { + self.log_(action + ' response', message); + + delete self.outstandingPuts_[index]; + self.outstandingPutCount_--; + + // Clean up array occasionally. + if (self.outstandingPutCount_ === 0) { + self.outstandingPuts_ = []; + } + + if (onComplete) + onComplete(message[/*status*/ 's'], message[/* data */ 'd']); + }); + } + + /** + * @inheritDoc + */ + reportStats(stats) { + // If we're not connected, we just drop the stats. + if (this.connected_) { + var request = { /*counters*/ 'c': stats }; + this.log_('reportStats', request); + + this.sendRequest(/*stats*/ 's', request, function(result) { + var status = result[/*status*/ 's']; + if (status !== 'ok') { + var errorReason = result[/* data */ 'd']; + this.log_('reportStats', 'Error sending stats: ' + errorReason); + } + }); + } + } + + /** + * @param {*} message + * @private + */ + onDataMessage_(message) { + if ('r' in message) { + // this is a response + this.log_('from server: ' + stringify(message)); + var reqNum = message['r']; + var onResponse = this.requestCBHash_[reqNum]; + if (onResponse) { + delete this.requestCBHash_[reqNum]; + onResponse(message[/*body*/ 'b']); + } + } else if ('error' in message) { + throw 'A server-side error has occurred: ' + message['error']; + } else if ('a' in message) { + // a and b are action and body, respectively + this.onDataPush_(message['a'], message['b']); + } + } + + onDataPush_(action, body) { + this.log_('handleServerMessage', action, body); + if (action === 'd') + this.onDataUpdate_(body[/*path*/ 'p'], body[/*data*/ 'd'], /*isMerge*/false, body['t']); + else if (action === 'm') + this.onDataUpdate_(body[/*path*/ 'p'], body[/*data*/ 'd'], /*isMerge=*/true, body['t']); + else if (action === 'c') + this.onListenRevoked_(body[/*path*/ 'p'], body[/*query*/ 'q']); + else if (action === 'ac') + this.onAuthRevoked_(body[/*status code*/ 's'], body[/* explanation */ 'd']); + else if (action === 'sd') + this.onSecurityDebugPacket_(body); + else + error('Unrecognized action received from server: ' + stringify(action) + + '\nAre you using the latest client?'); + } + + onReady_(timestamp, sessionId) { + this.log_('connection ready'); + this.connected_ = true; + this.lastConnectionEstablishedTime_ = new Date().getTime(); + this.handleTimestamp_(timestamp); + this.lastSessionId = sessionId; + if (this.firstConnection_) { + this.sendConnectStats_(); + } + this.restoreState_(); + this.firstConnection_ = false; + this.onConnectStatus_(true); + } + + scheduleConnect_(timeout) { + assert(!this.realtime_, "Scheduling a connect when we're already connected/ing?"); + + if (this.establishConnectionTimer_) { + clearTimeout(this.establishConnectionTimer_); + } + + // NOTE: Even when timeout is 0, it's important to do a setTimeout to work around an infuriating "Security Error" in + // Firefox when trying to write to our long-polling iframe in some scenarios (e.g. Forge or our unit tests). + + var self = this; + this.establishConnectionTimer_ = setTimeout(function() { + self.establishConnectionTimer_ = null; + self.establishConnection_(); + }, Math.floor(timeout)); + } + + /** + * @param {boolean} visible + * @private + */ + onVisible_(visible) { + // NOTE: Tabbing away and back to a window will defeat our reconnect backoff, but I think that's fine. + if (visible && !this.visible_ && this.reconnectDelay_ === this.maxReconnectDelay_) { + this.log_('Window became visible. Reducing delay.'); + this.reconnectDelay_ = RECONNECT_MIN_DELAY; + + if (!this.realtime_) { + this.scheduleConnect_(0); + } + } + this.visible_ = visible; + } + + onOnline_(online) { + if (online) { + this.log_('Browser went online.'); + this.reconnectDelay_ = RECONNECT_MIN_DELAY; + if (!this.realtime_) { + this.scheduleConnect_(0); + } + } else { + this.log_("Browser went offline. Killing connection."); + if (this.realtime_) { + this.realtime_.close(); + } + } + } + + onRealtimeDisconnect_() { + this.log_('data client disconnected'); + this.connected_ = false; + this.realtime_ = null; + + // Since we don't know if our sent transactions succeeded or not, we need to cancel them. + this.cancelSentTransactions_(); + + // Clear out the pending requests. + this.requestCBHash_ = {}; + + if (this.shouldReconnect_()) { + if (!this.visible_) { + this.log_("Window isn't visible. Delaying reconnect."); + this.reconnectDelay_ = this.maxReconnectDelay_; + this.lastConnectionAttemptTime_ = new Date().getTime(); + } else if (this.lastConnectionEstablishedTime_) { + // If we've been connected long enough, reset reconnect delay to minimum. + var timeSinceLastConnectSucceeded = new Date().getTime() - this.lastConnectionEstablishedTime_; + if (timeSinceLastConnectSucceeded > RECONNECT_DELAY_RESET_TIMEOUT) + this.reconnectDelay_ = RECONNECT_MIN_DELAY; + this.lastConnectionEstablishedTime_ = null; + } + + var timeSinceLastConnectAttempt = new Date().getTime() - this.lastConnectionAttemptTime_; + var reconnectDelay = Math.max(0, this.reconnectDelay_ - timeSinceLastConnectAttempt); + reconnectDelay = Math.random() * reconnectDelay; + + this.log_('Trying to reconnect in ' + reconnectDelay + 'ms'); + this.scheduleConnect_(reconnectDelay); + + // Adjust reconnect delay for next time. + this.reconnectDelay_ = Math.min(this.maxReconnectDelay_, this.reconnectDelay_ * RECONNECT_DELAY_MULTIPLIER); + } + this.onConnectStatus_(false); + } + + establishConnection_() { + if (this.shouldReconnect_()) { + this.log_('Making a connection attempt'); + this.lastConnectionAttemptTime_ = new Date().getTime(); + this.lastConnectionEstablishedTime_ = null; + var onDataMessage = this.onDataMessage_.bind(this); + var onReady = this.onReady_.bind(this); + var onDisconnect = this.onRealtimeDisconnect_.bind(this); + var connId = this.id + ':' + PersistentConnection.nextConnectionId_++; + var self = this; + var lastSessionId = this.lastSessionId; + var canceled = false; + var connection = null; + var closeFn = function() { + if (connection) { + connection.close(); + } else { + canceled = true; + onDisconnect(); + } + }; + var sendRequestFn = function(msg) { + assert(connection, "sendRequest call when we're not connected not allowed."); + connection.sendRequest(msg); + }; + + this.realtime_ = { + close: closeFn, + sendRequest: sendRequestFn + }; + + var forceRefresh = this.forceTokenRefresh_; + this.forceTokenRefresh_ = false; + + // First fetch auth token, and establish connection after fetching the token was successful + this.authTokenProvider_.getToken(forceRefresh).then(function(result) { + if (!canceled) { + log('getToken() completed. Creating connection.'); + self.authToken_ = result && result.accessToken; + connection = new Connection(connId, self.repoInfo_, + onDataMessage, + onReady, + onDisconnect, /* onKill= */ function (reason) { + warn(reason + ' (' + self.repoInfo_.toString() + ')'); + self.interrupt(SERVER_KILL_INTERRUPT_REASON); + }, + lastSessionId); + } else { + log('getToken() completed but was canceled'); + } + }).then(null, function(error) { + self.log_('Failed to get token: ' + error); + if (!canceled) { + if (CONSTANTS.NODE_ADMIN) { + // This may be a critical error for the Admin Node.js SDK, so log a warning. + // But getToken() may also just have temporarily failed, so we still want to + // continue retrying. + warn(error); + } + closeFn(); + } + }); + } + } + + /** + * @param {string} reason + */ + interrupt(reason) { + log('Interrupting connection for reason: ' + reason); + this.interruptReasons_[reason] = true; + if (this.realtime_) { + this.realtime_.close(); + } else { + if (this.establishConnectionTimer_) { + clearTimeout(this.establishConnectionTimer_); + this.establishConnectionTimer_ = null; + } + if (this.connected_) { + this.onRealtimeDisconnect_(); + } + } + } + + /** + * @param {string} reason + */ + resume(reason) { + log('Resuming connection for reason: ' + reason); + delete this.interruptReasons_[reason]; + if (isEmpty(this.interruptReasons_)) { + this.reconnectDelay_ = RECONNECT_MIN_DELAY; + if (!this.realtime_) { + this.scheduleConnect_(0); + } + } + } + + /** + * @param reason + * @return {boolean} + */ + isInterrupted(reason) { + return this.interruptReasons_[reason] || false; + } + + handleTimestamp_(timestamp) { + var delta = timestamp - new Date().getTime(); + this.onServerInfoUpdate_({'serverTimeOffset': delta}); + } + + cancelSentTransactions_() { + for (var i = 0; i < this.outstandingPuts_.length; i++) { + var put = this.outstandingPuts_[i]; + if (put && /*hash*/'h' in put.request && put.queued) { + if (put.onComplete) + put.onComplete('disconnect'); + + delete this.outstandingPuts_[i]; + this.outstandingPutCount_--; + } + } + + // Clean up array occasionally. + if (this.outstandingPutCount_ === 0) + this.outstandingPuts_ = []; + } + + /** + * @param {!string} pathString + * @param {Array.<*>=} opt_query + * @private + */ + onListenRevoked_(pathString, opt_query) { + // Remove the listen and manufacture a "permission_denied" error for the failed listen. + var queryId; + if (!opt_query) { + queryId = 'default'; + } else { + queryId = opt_query.map(function(q) { return ObjectToUniqueKey(q); }).join('$'); + } + var listen = this.removeListen_(pathString, queryId); + if (listen && listen.onComplete) + listen.onComplete('permission_denied'); + } + + /** + * @param {!string} pathString + * @param {!string} queryId + * @return {{queries:Array., onComplete:function(string)}} + * @private + */ + removeListen_(pathString, queryId) { + var normalizedPathString = new Path(pathString).toString(); // normalize path. + var listen; + if (this.listens_[normalizedPathString] !== undefined) { + listen = this.listens_[normalizedPathString][queryId]; + delete this.listens_[normalizedPathString][queryId]; + if (getCount(this.listens_[normalizedPathString]) === 0) { + delete this.listens_[normalizedPathString]; + } + } else { + // all listens for this path has already been removed + listen = undefined; + } + return listen; + } + + onAuthRevoked_(statusCode, explanation) { + log('Auth token revoked: ' + statusCode + '/' + explanation); + this.authToken_ = null; + this.forceTokenRefresh_ = true; + this.realtime_.close(); + if (statusCode === 'invalid_token' || statusCode === 'permission_denied') { + // We'll wait a couple times before logging the warning / increasing the + // retry period since oauth tokens will report as "invalid" if they're + // just expired. Plus there may be transient issues that resolve themselves. + this.invalidAuthTokenCount_++; + if (this.invalidAuthTokenCount_ >= INVALID_AUTH_TOKEN_THRESHOLD) { + // Set a long reconnect delay because recovery is unlikely + this.reconnectDelay_ = RECONNECT_MAX_DELAY_FOR_ADMINS; + + // Notify the auth token provider that the token is invalid, which will log + // a warning + this.authTokenProvider_.notifyForInvalidToken(); + } + } + } + + onSecurityDebugPacket_(body) { + if (this.securityDebugCallback_) { + this.securityDebugCallback_(body); + } else { + if ('msg' in body && typeof console !== 'undefined') { + console.log('FIREBASE: ' + body['msg'].replace('\n', '\nFIREBASE: ')); + } + } + } + + restoreState_() { + //Re-authenticate ourselves if we have a credential stored. + this.tryAuth(); + + // Puts depend on having received the corresponding data update from the server before they complete, so we must + // make sure to send listens before puts. + var self = this; + forEach(this.listens_, function(pathString, queries) { + forEach(queries, function(key, listenSpec) { + self.sendListen_(listenSpec); + }); + }); + + for (var i = 0; i < this.outstandingPuts_.length; i++) { + if (this.outstandingPuts_[i]) + this.sendPut_(i); + } + + while (this.onDisconnectRequestQueue_.length) { + var request = this.onDisconnectRequestQueue_.shift(); + this.sendOnDisconnect_(request.action, request.pathString, request.data, request.onComplete); + } + } + + /** + * Sends client stats for first connection + * @private + */ + sendConnectStats_() { + var stats = {}; + + var clientName = 'js'; + if (CONSTANTS.NODE_ADMIN) { + clientName = 'admin_node'; + } else if (CONSTANTS.NODE_CLIENT) { + clientName = 'node'; + } + + stats['sdk.' + clientName + '.' + firebase.SDK_VERSION.replace(/\./g, '-')] = 1; + + if (isMobileCordova()) { + stats['framework.cordova'] = 1; + } + else if (isReactNative()) { + stats['framework.reactnative'] = 1; + } + this.reportStats(stats); + } + + /** + * @return {boolean} + * @private + */ + shouldReconnect_() { + var online = OnlineMonitor.getInstance().currentlyOnline(); + return isEmpty(this.interruptReasons_) && online; + } +}; // end PersistentConnection diff --git a/src/database/core/ReadonlyRestClient.ts b/src/database/core/ReadonlyRestClient.ts new file mode 100644 index 00000000000..8228a613ca9 --- /dev/null +++ b/src/database/core/ReadonlyRestClient.ts @@ -0,0 +1,175 @@ +import { assert } from '../../utils/assert'; +import { logWrapper, warn } from './util/util'; +import { jsonEval } from '../../utils/json'; +import { safeGet } from '../../utils/obj'; +import { querystring } from '../../utils/util'; +import { ServerActions } from './ServerActions'; +import { RepoInfo } from './RepoInfo'; +import { AuthTokenProvider } from './AuthTokenProvider'; +import { Query } from '../api/Query'; + +/** + * An implementation of ServerActions that communicates with the server via REST requests. + * This is mostly useful for compatibility with crawlers, where we don't want to spin up a full + * persistent connection (using WebSockets or long-polling) + */ +export class ReadonlyRestClient implements ServerActions { + /** @private {function(...[*])} */ + private log_: (...args: any[]) => any = logWrapper('p:rest:'); + + /** + * We don't actually need to track listens, except to prevent us calling an onComplete for a listen + * that's been removed. :-/ + * + * @private {!Object.} + */ + private listens_: { [k: string]: Object } = {}; + + /** + * @param {!Query} query + * @param {?number=} tag + * @return {string} + * @private + */ + static getListenId_(query: Query, tag?: number | null): string { + if (tag !== undefined) { + return 'tag$' + tag; + } else { + assert(query.getQueryParams().isDefault(), 'should have a tag if it\'s not a default query.'); + return query.path.toString(); + } + } + + /** + * @param {!RepoInfo} repoInfo_ Data about the namespace we are connecting to + * @param {function(string, *, boolean, ?number)} onDataUpdate_ A callback for new data from the server + * @param {AuthTokenProvider} authTokenProvider_ + * @implements {ServerActions} + */ + constructor(private repoInfo_: RepoInfo, + private onDataUpdate_: (a: string, b: any, c: boolean, d: number | null) => any, + private authTokenProvider_: AuthTokenProvider) { + } + + /** @inheritDoc */ + listen(query: Query, currentHashFn: () => string, tag: number | null, onComplete: (a: string, b: any) => any) { + const pathString = query.path.toString(); + this.log_('Listen called for ' + pathString + ' ' + query.queryIdentifier()); + + // Mark this listener so we can tell if it's removed. + const listenId = ReadonlyRestClient.getListenId_(query, tag); + const thisListen = {}; + this.listens_[listenId] = thisListen; + + const queryStringParamaters = query.getQueryParams().toRestQueryStringParameters(); + + this.restRequest_(pathString + '.json', queryStringParamaters, (error, result) => { + let data = result; + + if (error === 404) { + data = null; + error = null; + } + + if (error === null) { + this.onDataUpdate_(pathString, data, /*isMerge=*/false, tag); + } + + if (safeGet(this.listens_, listenId) === thisListen) { + let status; + if (!error) { + status = 'ok'; + } else if (error == 401) { + status = 'permission_denied'; + } else { + status = 'rest_error:' + error; + } + + onComplete(status, null); + } + }); + } + + /** @inheritDoc */ + unlisten(query: Query, tag: number | null) { + const listenId = ReadonlyRestClient.getListenId_(query, tag); + delete this.listens_[listenId]; + } + + /** @inheritDoc */ + refreshAuthToken(token: string) { + // no-op since we just always call getToken. + } + + /** @inheritDoc */ + onDisconnectPut(pathString: string, data: any, onComplete?: (a: string, b: string) => any) { } + + /** @inheritDoc */ + onDisconnectMerge(pathString: string, data: any, onComplete?: (a: string, b: string) => any) { } + + /** @inheritDoc */ + onDisconnectCancel(pathString: string, onComplete?: (a: string, b: string) => any) { } + + /** @inheritDoc */ + put(pathString: string, data: any, onComplete?: (a: string, b: string) => any, hash?: string) { } + + /** @inheritDoc */ + merge(pathString: string, data: any, onComplete: (a: string, b: string | null) => any, hash?: string) { } + + /** @inheritDoc */ + reportStats(stats: { [k: string]: any }) { } + + /** + * Performs a REST request to the given path, with the provided query string parameters, + * and any auth credentials we have. + * + * @param {!string} pathString + * @param {!Object.} queryStringParameters + * @param {?function(?number, *=)} callback + * @private + */ + private restRequest_(pathString: string, queryStringParameters: {[k: string]: any} = {}, + callback: ((a: number | null, b?: any) => any) | null) { + queryStringParameters['format'] = 'export'; + + this.authTokenProvider_.getToken(/*forceRefresh=*/false).then((authTokenData) => { + const authToken = authTokenData && authTokenData.accessToken; + if (authToken) { + queryStringParameters['auth'] = authToken; + } + + const url = (this.repoInfo_.secure ? 'https://' : 'http://') + + this.repoInfo_.host + + pathString + + '?' + + querystring(queryStringParameters); + + this.log_('Sending REST request for ' + url); + const xhr = new XMLHttpRequest(); + xhr.onreadystatechange = () => { + if (callback && xhr.readyState === 4) { + this.log_('REST Response for ' + url + ' received. status:', xhr.status, 'response:', xhr.responseText); + let res = null; + if (xhr.status >= 200 && xhr.status < 300) { + try { + res = jsonEval(xhr.responseText); + } catch (e) { + warn('Failed to parse JSON response for ' + url + ': ' + xhr.responseText); + } + callback(null, res); + } else { + // 401 and 404 are expected. + if (xhr.status !== 401 && xhr.status !== 404) { + warn('Got unsuccessful REST response for ' + url + ' Status: ' + xhr.status); + } + callback(xhr.status); + } + callback = null; + } + }; + + xhr.open('GET', url, /*asynchronous=*/true); + xhr.send(); + }); + } +} diff --git a/src/database/core/Repo.ts b/src/database/core/Repo.ts new file mode 100644 index 00000000000..ce8dc96de1f --- /dev/null +++ b/src/database/core/Repo.ts @@ -0,0 +1,566 @@ +import { + generateWithValues, + resolveDeferredValueSnapshot, + resolveDeferredValueTree +} from './util/ServerValues'; +import { nodeFromJSON } from './snap/nodeFromJSON'; +import { Path } from './util/Path'; +import { SparseSnapshotTree } from './SparseSnapshotTree'; +import { SyncTree } from './SyncTree'; +import { SnapshotHolder } from './SnapshotHolder'; +import { stringify } from '../../utils/json'; +import { beingCrawled, each, exceptionGuard, warn, log } from './util/util'; +import { map, forEach, isEmpty } from '../../utils/obj'; +import { AuthTokenProvider } from './AuthTokenProvider'; +import { StatsManager } from './stats/StatsManager'; +import { StatsReporter } from './stats/StatsReporter'; +import { StatsListener } from './stats/StatsListener'; +import { EventQueue } from './view/EventQueue'; +import { PersistentConnection } from './PersistentConnection'; +import { ReadonlyRestClient } from './ReadonlyRestClient'; +import { FirebaseApp } from '../../app/firebase_app'; +import { RepoInfo } from './RepoInfo'; +import { Database } from '../api/Database'; +import { ServerActions } from './ServerActions'; +import { Query } from '../api/Query'; +import { EventRegistration } from './view/EventRegistration'; + +const INTERRUPT_REASON = 'repo_interrupt'; + +/** + * A connection to a single data repository. + */ +export class Repo { + /** @type {!Database} */ + database: Database; + infoSyncTree_: SyncTree; + dataUpdateCount; + serverSyncTree_: SyncTree; + + public repoInfo_; + private stats_; + private statsListener_; + private eventQueue_; + private nextWriteId_; + private server_: ServerActions; + private statsReporter_; + private transactions_init_; + private infoData_; + private onDisconnect_; + private abortTransactions_; + private rerunTransactions_; + private interceptServerDataCallback_; + + /** + * TODO: This should be @private but it's used by test_access.js and internal.js + * @type {?PersistentConnection} + */ + persistentConnection_: PersistentConnection | null = null; + + /** + * @param {!RepoInfo} repoInfo + * @param {boolean} forceRestClient + * @param {!FirebaseApp} app + */ + constructor(repoInfo: RepoInfo, forceRestClient: boolean, public app: FirebaseApp) { + /** @type {!AuthTokenProvider} */ + const authTokenProvider = new AuthTokenProvider(app); + + this.repoInfo_ = repoInfo; + this.stats_ = StatsManager.getCollection(repoInfo); + /** @type {StatsListener} */ + this.statsListener_ = null; + this.eventQueue_ = new EventQueue(); + this.nextWriteId_ = 1; + + if (forceRestClient || beingCrawled()) { + this.server_ = new ReadonlyRestClient(this.repoInfo_, + this.onDataUpdate_.bind(this), + authTokenProvider); + + // Minor hack: Fire onConnect immediately, since there's no actual connection. + setTimeout(this.onConnectStatus_.bind(this, true), 0); + } else { + const authOverride = app.options['databaseAuthVariableOverride']; + // Validate authOverride + if (typeof authOverride !== 'undefined' && authOverride !== null) { + if (typeof authOverride !== 'object') { + throw new Error('Only objects are supported for option databaseAuthVariableOverride'); + } + try { + stringify(authOverride); + } catch (e) { + throw new Error('Invalid authOverride provided: ' + e); + } + } + + this.persistentConnection_ = new PersistentConnection(this.repoInfo_, + this.onDataUpdate_.bind(this), + this.onConnectStatus_.bind(this), + this.onServerInfoUpdate_.bind(this), + authTokenProvider, + authOverride); + + this.server_ = this.persistentConnection_; + } + + authTokenProvider.addTokenChangeListener((token) => { + this.server_.refreshAuthToken(token); + }); + + // In the case of multiple Repos for the same repoInfo (i.e. there are multiple Firebase.Contexts being used), + // we only want to create one StatsReporter. As such, we'll report stats over the first Repo created. + this.statsReporter_ = StatsManager.getOrCreateReporter(repoInfo, + () => new StatsReporter(this.stats_, this.server_)); + + this.transactions_init_(); + + // Used for .info. + this.infoData_ = new SnapshotHolder(); + this.infoSyncTree_ = new SyncTree({ + startListening: (query, tag, currentHashFn, onComplete) => { + let infoEvents = []; + const node = this.infoData_.getNode(query.path); + // This is possibly a hack, but we have different semantics for .info endpoints. We don't raise null events + // on initial data... + if (!node.isEmpty()) { + infoEvents = this.infoSyncTree_.applyServerOverwrite(query.path, node); + setTimeout(() => { + onComplete('ok'); + }, 0); + } + return infoEvents; + }, + stopListening: () => {} + }); + this.updateInfo_('connected', false); + + // A list of data pieces and paths to be set when this client disconnects. + this.onDisconnect_ = new SparseSnapshotTree(); + + this.dataUpdateCount = 0; + + this.interceptServerDataCallback_ = null; + + this.serverSyncTree_ = new SyncTree({ + startListening: (query, tag, currentHashFn, onComplete) => { + this.server_.listen(query, currentHashFn, tag, (status, data) => { + const events = onComplete(status, data); + this.eventQueue_.raiseEventsForChangedPath(query.path, events); + }); + // No synchronous events for network-backed sync trees + return []; + }, + stopListening: (query, tag) => { + this.server_.unlisten(query, tag); + } + }); + } + + /** + * @return {string} The URL corresponding to the root of this Firebase. + */ + toString(): string { + return (this.repoInfo_.secure ? 'https://' : 'http://') + this.repoInfo_.host; + } + + /** + * @return {!string} The namespace represented by the repo. + */ + name(): string { + return this.repoInfo_.namespace; + } + + /** + * @return {!number} The time in milliseconds, taking the server offset into account if we have one. + */ + serverTime(): number { + const offsetNode = this.infoData_.getNode(new Path('.info/serverTimeOffset')); + const offset = /** @type {number} */ (offsetNode.val()) || 0; + return new Date().getTime() + offset; + } + + /** + * Generate ServerValues using some variables from the repo object. + * @return {!Object} + */ + generateServerValues(): Object { + return generateWithValues({ + 'timestamp': this.serverTime() + }); + } + + /** + * Called by realtime when we get new messages from the server. + * + * @private + * @param {string} pathString + * @param {*} data + * @param {boolean} isMerge + * @param {?number} tag + */ + private onDataUpdate_(pathString: string, data: any, isMerge: boolean, tag: number | null) { + // For testing. + this.dataUpdateCount++; + const path = new Path(pathString); + data = this.interceptServerDataCallback_ ? this.interceptServerDataCallback_(pathString, data) : data; + let events = []; + if (tag) { + if (isMerge) { + const taggedChildren = map(/**@type {!Object.} */ (data), (raw) => nodeFromJSON(raw)); + events = this.serverSyncTree_.applyTaggedQueryMerge(path, taggedChildren, tag); + } else { + const taggedSnap = nodeFromJSON(data); + events = this.serverSyncTree_.applyTaggedQueryOverwrite(path, taggedSnap, tag); + } + } else if (isMerge) { + const changedChildren = map(/**@type {!Object.} */ (data), (raw) => nodeFromJSON(raw)); + events = this.serverSyncTree_.applyServerMerge(path, changedChildren); + } else { + const snap = nodeFromJSON(data); + events = this.serverSyncTree_.applyServerOverwrite(path, snap); + } + let affectedPath = path; + if (events.length > 0) { + // Since we have a listener outstanding for each transaction, receiving any events + // is a proxy for some change having occurred. + affectedPath = this.rerunTransactions_(path); + } + this.eventQueue_.raiseEventsForChangedPath(affectedPath, events); + } + + /** + * @param {?function(!string, *):*} callback + * @private + */ + private interceptServerData_(callback: (a: string, b: any) => any) { + this.interceptServerDataCallback_ = callback; + } + + /** + * @param {!boolean} connectStatus + * @private + */ + private onConnectStatus_(connectStatus: boolean) { + this.updateInfo_('connected', connectStatus); + if (connectStatus === false) { + this.runOnDisconnectEvents_(); + } + } + + /** + * @param {!Object} updates + * @private + */ + private onServerInfoUpdate_(updates: Object) { + each(updates, (value: any, key: string) => { + this.updateInfo_(key, value); + }); + } + + /** + * + * @param {!string} pathString + * @param {*} value + * @private + */ + private updateInfo_(pathString: string, value: any) { + const path = new Path('/.info/' + pathString); + const newNode = nodeFromJSON(value); + this.infoData_.updateSnapshot(path, newNode); + const events = this.infoSyncTree_.applyServerOverwrite(path, newNode); + this.eventQueue_.raiseEventsForChangedPath(path, events); + } + + /** + * @return {!number} + * @private + */ + private getNextWriteId_(): number { + return this.nextWriteId_++; + } + + /** + * @param {!Path} path + * @param {*} newVal + * @param {number|string|null} newPriority + * @param {?function(?Error, *=)} onComplete + */ + setWithPriority(path: Path, newVal: any, + newPriority: number | string | null, + onComplete: ((status: Error | null, errorReason?: string) => any) | null) { + this.log_('set', {path: path.toString(), value: newVal, priority: newPriority}); + + // TODO: Optimize this behavior to either (a) store flag to skip resolving where possible and / or + // (b) store unresolved paths on JSON parse + const serverValues = this.generateServerValues(); + const newNodeUnresolved = nodeFromJSON(newVal, newPriority); + const newNode = resolveDeferredValueSnapshot(newNodeUnresolved, serverValues); + + const writeId = this.getNextWriteId_(); + const events = this.serverSyncTree_.applyUserOverwrite(path, newNode, writeId, true); + this.eventQueue_.queueEvents(events); + this.server_.put(path.toString(), newNodeUnresolved.val(/*export=*/true), (status, errorReason) => { + const success = status === 'ok'; + if (!success) { + warn('set at ' + path + ' failed: ' + status); + } + + const clearEvents = this.serverSyncTree_.ackUserWrite(writeId, !success); + this.eventQueue_.raiseEventsForChangedPath(path, clearEvents); + this.callOnCompleteCallback(onComplete, status, errorReason); + }); + const affectedPath = this.abortTransactions_(path); + this.rerunTransactions_(affectedPath); + // We queued the events above, so just flush the queue here + this.eventQueue_.raiseEventsForChangedPath(affectedPath, []); + } + + /** + * @param {!Path} path + * @param {!Object} childrenToMerge + * @param {?function(?Error, *=)} onComplete + */ + update(path: Path, childrenToMerge: Object, + onComplete: ((status: Error | null, errorReason?: string) => any) | null) { + this.log_('update', {path: path.toString(), value: childrenToMerge}); + + // Start with our existing data and merge each child into it. + let empty = true; + const serverValues = this.generateServerValues(); + const changedChildren = {}; + forEach(childrenToMerge, function (changedKey, changedValue) { + empty = false; + const newNodeUnresolved = nodeFromJSON(changedValue); + changedChildren[changedKey] = resolveDeferredValueSnapshot(newNodeUnresolved, serverValues); + }); + + if (!empty) { + const writeId = this.getNextWriteId_(); + const events = this.serverSyncTree_.applyUserMerge(path, changedChildren, writeId); + this.eventQueue_.queueEvents(events); + this.server_.merge(path.toString(), childrenToMerge, (status, errorReason) => { + const success = status === 'ok'; + if (!success) { + warn('update at ' + path + ' failed: ' + status); + } + + const clearEvents = this.serverSyncTree_.ackUserWrite(writeId, !success); + const affectedPath = (clearEvents.length > 0) ? this.rerunTransactions_(path) : path; + this.eventQueue_.raiseEventsForChangedPath(affectedPath, clearEvents); + this.callOnCompleteCallback(onComplete, status, errorReason); + }); + + forEach(childrenToMerge, (changedPath, changedValue) => { + const affectedPath = this.abortTransactions_(path.child(changedPath)); + this.rerunTransactions_(affectedPath); + }); + + // We queued the events above, so just flush the queue here + this.eventQueue_.raiseEventsForChangedPath(path, []); + } else { + log('update() called with empty data. Don\'t do anything.'); + this.callOnCompleteCallback(onComplete, 'ok'); + } + } + + /** + * Applies all of the changes stored up in the onDisconnect_ tree. + * @private + */ + private runOnDisconnectEvents_() { + this.log_('onDisconnectEvents'); + + const serverValues = this.generateServerValues(); + const resolvedOnDisconnectTree = resolveDeferredValueTree(this.onDisconnect_, serverValues); + let events = []; + + resolvedOnDisconnectTree.forEachTree(Path.Empty, (path, snap) => { + events = events.concat(this.serverSyncTree_.applyServerOverwrite(path, snap)); + const affectedPath = this.abortTransactions_(path); + this.rerunTransactions_(affectedPath); + }); + + this.onDisconnect_ = new SparseSnapshotTree(); + this.eventQueue_.raiseEventsForChangedPath(Path.Empty, events); + } + + /** + * @param {!Path} path + * @param {?function(?Error, *=)} onComplete + */ + onDisconnectCancel(path: Path, onComplete: ((status: Error | null, errorReason?: string) => any) | null) { + this.server_.onDisconnectCancel(path.toString(), (status, errorReason) => { + if (status === 'ok') { + this.onDisconnect_.forget(path); + } + this.callOnCompleteCallback(onComplete, status, errorReason); + }); + } + + /** + * @param {!Path} path + * @param {*} value + * @param {?function(?Error, *=)} onComplete + */ + onDisconnectSet(path: Path, value: any, onComplete: ((status: Error | null, errorReason?: string) => any) | null) { + const newNode = nodeFromJSON(value); + this.server_.onDisconnectPut(path.toString(), newNode.val(/*export=*/true), (status, errorReason) => { + if (status === 'ok') { + this.onDisconnect_.remember(path, newNode); + } + this.callOnCompleteCallback(onComplete, status, errorReason); + }); + } + + /** + * @param {!Path} path + * @param {*} value + * @param {*} priority + * @param {?function(?Error, *=)} onComplete + */ + onDisconnectSetWithPriority(path, value, priority, onComplete: ((status: Error | null, errorReason?: string) => any) | null) { + const newNode = nodeFromJSON(value, priority); + this.server_.onDisconnectPut(path.toString(), newNode.val(/*export=*/true), (status, errorReason) => { + if (status === 'ok') { + this.onDisconnect_.remember(path, newNode); + } + this.callOnCompleteCallback(onComplete, status, errorReason); + }); + } + + /** + * @param {!Path} path + * @param {*} childrenToMerge + * @param {?function(?Error, *=)} onComplete + */ + onDisconnectUpdate(path, childrenToMerge, + onComplete: ((status: Error | null, errorReason?: string) => any) | null) { + if (isEmpty(childrenToMerge)) { + log('onDisconnect().update() called with empty data. Don\'t do anything.'); + this.callOnCompleteCallback(onComplete, 'ok'); + return; + } + + this.server_.onDisconnectMerge(path.toString(), childrenToMerge, (status, errorReason) => { + if (status === 'ok') { + forEach(childrenToMerge, (childName: string, childNode: any) => { + const newChildNode = nodeFromJSON(childNode); + this.onDisconnect_.remember(path.child(childName), newChildNode); + }); + } + this.callOnCompleteCallback(onComplete, status, errorReason); + }); + } + + /** + * @param {!Query} query + * @param {!EventRegistration} eventRegistration + */ + addEventCallbackForQuery(query: Query, eventRegistration: EventRegistration) { + let events; + if (query.path.getFront() === '.info') { + events = this.infoSyncTree_.addEventRegistration(query, eventRegistration); + } else { + events = this.serverSyncTree_.addEventRegistration(query, eventRegistration); + } + this.eventQueue_.raiseEventsAtPath(query.path, events); + } + + /** + * @param {!Query} query + * @param {?EventRegistration} eventRegistration + */ + removeEventCallbackForQuery(query: Query, eventRegistration: EventRegistration) { + // These are guaranteed not to raise events, since we're not passing in a cancelError. However, we can future-proof + // a little bit by handling the return values anyways. + let events; + if (query.path.getFront() === '.info') { + events = this.infoSyncTree_.removeEventRegistration(query, eventRegistration); + } else { + events = this.serverSyncTree_.removeEventRegistration(query, eventRegistration); + } + this.eventQueue_.raiseEventsAtPath(query.path, events); + } + + interrupt() { + if (this.persistentConnection_) { + this.persistentConnection_.interrupt(INTERRUPT_REASON); + } + } + + resume() { + if (this.persistentConnection_) { + this.persistentConnection_.resume(INTERRUPT_REASON); + } + } + + stats(showDelta: boolean = false) { + if (typeof console === 'undefined') + return; + + let stats; + if (showDelta) { + if (!this.statsListener_) + this.statsListener_ = new StatsListener(this.stats_); + stats = this.statsListener_.get(); + } else { + stats = this.stats_.get(); + } + + const longestName = Object.keys(stats).reduce( + function (previousValue, currentValue, index, array) { + return Math.max(currentValue.length, previousValue); + }, 0); + + forEach(stats, (stat, value) => { + // pad stat names to be the same length (plus 2 extra spaces). + for (let i = stat.length; i < longestName + 2; i++) + stat += ' '; + console.log(stat + value); + }); + } + + statsIncrementCounter(metric) { + this.stats_.incrementCounter(metric); + this.statsReporter_.includeStat(metric); + } + + /** + * @param {...*} var_args + * @private + */ + private log_(...var_args: any[]) { + let prefix = ''; + if (this.persistentConnection_) { + prefix = this.persistentConnection_.id + ':'; + } + log(prefix, var_args); + } + + /** + * @param {?function(?Error, *=)} callback + * @param {!string} status + * @param {?string=} errorReason + */ + callOnCompleteCallback(callback: ((status: Error | null, errorReason?: string) => any) | null, + status: string, errorReason?: string | null) { + if (callback) { + exceptionGuard(function () { + if (status == 'ok') { + callback(null); + } else { + const code = (status || 'error').toUpperCase(); + let message = code; + if (errorReason) + message += ': ' + errorReason; + + const error = new Error(message); + (error as any).code = code; + callback(error); + } + }); + } + } +} + diff --git a/src/database/core/RepoInfo.ts b/src/database/core/RepoInfo.ts new file mode 100644 index 00000000000..96fd5567896 --- /dev/null +++ b/src/database/core/RepoInfo.ts @@ -0,0 +1,100 @@ +import { assert } from "../../utils/assert"; +import { forEach } from "../../utils/obj"; +import { PersistentStorage } from './storage/storage'; +import { CONSTANTS } from "../realtime/Constants"; +/** + * A class that holds metadata about a Repo object + * @param {string} host Hostname portion of the url for the repo + * @param {boolean} secure Whether or not this repo is accessed over ssl + * @param {string} namespace The namespace represented by the repo + * @param {boolean} webSocketOnly Whether to prefer websockets over all other transports (used by Nest). + * @param {string=} persistenceKey Override the default session persistence storage key + * @constructor + */ +export class RepoInfo { + host; + domain; + secure; + namespace; + webSocketOnly; + persistenceKey; + internalHost; + + constructor(host, secure, namespace, webSocketOnly, persistenceKey?) { + this.host = host.toLowerCase(); + this.domain = this.host.substr(this.host.indexOf('.') + 1); + this.secure = secure; + this.namespace = namespace; + this.webSocketOnly = webSocketOnly; + this.persistenceKey = persistenceKey || ''; + this.internalHost = PersistentStorage.get('host:' + host) || this.host; + } + needsQueryParam() { + return this.host !== this.internalHost; + }; + + isCacheableHost() { + return this.internalHost.substr(0, 2) === 's-'; + }; + + isDemoHost() { + return this.domain === 'firebaseio-demo.com'; + }; + + isCustomHost() { + return this.domain !== 'firebaseio.com' && this.domain !== 'firebaseio-demo.com'; + }; + + updateHost(newHost) { + if (newHost !== this.internalHost) { + this.internalHost = newHost; + if (this.isCacheableHost()) { + PersistentStorage.set('host:' + this.host, this.internalHost); + } + } + }; + + /** + * Returns the websocket URL for this repo + * @param {string} type of connection + * @param {Object} params list + * @return {string} The URL for this repo + */ + connectionURL(type, params) { + assert(typeof type === 'string', 'typeof type must == string'); + assert(typeof params === 'object', 'typeof params must == object'); + var connURL; + if (type === CONSTANTS.WEBSOCKET) { + connURL = (this.secure ? 'wss://' : 'ws://') + this.internalHost + '/.ws?'; + } else if (type === CONSTANTS.LONG_POLLING) { + connURL = (this.secure ? 'https://' : 'http://') + this.internalHost + '/.lp?'; + } else { + throw new Error('Unknown connection type: ' + type); + } + if (this.needsQueryParam()) { + params['ns'] = this.namespace; + } + + var pairs = []; + + forEach(params, (key, value) => { + pairs.push(key + '=' + value); + }); + + return connURL + pairs.join('&'); + }; + + /** @return {string} */ + toString() { + var str = this.toURLString(); + if (this.persistenceKey) { + str += '<' + this.persistenceKey + '>'; + } + return str; + }; + + /** @return {string} */ + toURLString() { + return (this.secure ? 'https://' : 'http://') + this.host; + }; +} diff --git a/src/database/core/RepoManager.ts b/src/database/core/RepoManager.ts new file mode 100644 index 00000000000..e7066769fe2 --- /dev/null +++ b/src/database/core/RepoManager.ts @@ -0,0 +1,121 @@ +import { FirebaseApp } from "../../app/firebase_app"; +import { safeGet } from "../../utils/obj"; +import { Repo } from "./Repo"; +import { fatal } from "./util/util"; +import { parseRepoInfo } from "./util/libs/parser"; +import { validateUrl } from "./util/validation"; +import "./Repo_transaction"; +import { Database } from '../api/Database'; + +/** @const {string} */ +var DATABASE_URL_OPTION = 'databaseURL'; + +let _staticInstance; + +/** + * Creates and caches Repo instances. + */ +export class RepoManager { + /** + * @private {!Object.} + */ + private repos_: { + [name: string]: Repo + } = {}; + + /** + * If true, new Repos will be created to use ReadonlyRestClient (for testing purposes). + * @private {boolean} + */ + private useRestClient_: boolean = false; + + static getInstance() { + if (!_staticInstance) { + _staticInstance = new RepoManager(); + } + return _staticInstance; + } + + // TODO(koss): Remove these functions unless used in tests? + interrupt() { + for (var repo in this.repos_) { + this.repos_[repo].interrupt(); + } + } + + resume() { + for (var repo in this.repos_) { + this.repos_[repo].resume(); + } + } + + /** + * This function should only ever be called to CREATE a new database instance. + * + * @param {!App} app + * @return {!Database} + */ + databaseFromApp(app: FirebaseApp): Database { + var dbUrl: string = app.options[DATABASE_URL_OPTION]; + if (dbUrl === undefined) { + fatal("Can't determine Firebase Database URL. Be sure to include " + + DATABASE_URL_OPTION + + " option when calling firebase.intializeApp()."); + } + + var parsedUrl = parseRepoInfo(dbUrl); + var repoInfo = parsedUrl.repoInfo; + + validateUrl('Invalid Firebase Database URL', 1, parsedUrl); + if (!parsedUrl.path.isEmpty()) { + fatal("Database URL must point to the root of a Firebase Database " + + "(not including a child path)."); + } + + var repo = this.createRepo(repoInfo, app); + + return repo.database; + } + + /** + * Remove the repo and make sure it is disconnected. + * + * @param {!Repo} repo + */ + deleteRepo(repo) { + + // This should never happen... + if (safeGet(this.repos_, repo.app.name) !== repo) { + fatal("Database " + repo.app.name + " has already been deleted."); + } + repo.interrupt(); + delete this.repos_[repo.app.name]; + } + + /** + * Ensures a repo doesn't already exist and then creates one using the + * provided app. + * + * @param {!RepoInfo} repoInfo The metadata about the Repo + * @param {!FirebaseApp} app + * @return {!Repo} The Repo object for the specified server / repoName. + */ + createRepo(repoInfo, app: FirebaseApp): Repo { + var repo = safeGet(this.repos_, app.name); + if (repo) { + fatal('FIREBASE INTERNAL ERROR: Database initialized multiple times.'); + } + repo = new Repo(repoInfo, this.useRestClient_, app); + this.repos_[app.name] = repo; + + return repo; + } + + /** + * Forces us to use ReadonlyRestClient instead of PersistentConnection for new Repos. + * @param {boolean} forceRestClient + */ + forceRestClient(forceRestClient) { + this.useRestClient_ = forceRestClient; + } +}; // end RepoManager \ No newline at end of file diff --git a/src/database/core/Repo_transaction.ts b/src/database/core/Repo_transaction.ts new file mode 100644 index 00000000000..fa9a95ab805 --- /dev/null +++ b/src/database/core/Repo_transaction.ts @@ -0,0 +1,654 @@ +import { assert } from "../../utils/assert"; +import { Reference } from "../api/Reference"; +import { DataSnapshot } from "../api/DataSnapshot"; +import { Path } from "./util/Path"; +import { Tree } from "./util/Tree"; +import { PRIORITY_INDEX } from "./snap/indexes/PriorityIndex"; +import { Node } from "./snap/Node"; +import { + LUIDGenerator, + warn, + exceptionGuard, +} from "./util/util"; +import { resolveDeferredValueSnapshot } from "./util/ServerValues"; +import { isValidPriority, validateFirebaseData } from "./util/validation"; +import { contains, safeGet } from "../../utils/obj"; +import { nodeFromJSON } from "./snap/nodeFromJSON"; +import { ChildrenNode } from "./snap/ChildrenNode"; +import { Repo } from "./Repo"; + +// TODO: This is pretty messy. Ideally, a lot of this would move into FirebaseData, or a transaction-specific +// component used by FirebaseData, but it has ties to user callbacks (transaction update and onComplete) as well +// as the realtime connection (to send transactions to the server). So that all needs to be decoupled first. +// For now it's part of Repo, but in its own file. + +/** + * @enum {number} + */ +export const TransactionStatus = { + // We've run the transaction and updated transactionResultData_ with the result, but it isn't currently sent to the + // server. A transaction will go from RUN -> SENT -> RUN if it comes back from the server as rejected due to + // mismatched hash. + RUN: 1, + + // We've run the transaction and sent it to the server and it's currently outstanding (hasn't come back as accepted + // or rejected yet). + SENT: 2, + + // Temporary state used to mark completed transactions (whether successful or aborted). The transaction will be + // removed when we get a chance to prune completed ones. + COMPLETED: 3, + + // Used when an already-sent transaction needs to be aborted (e.g. due to a conflicting set() call that was made). + // If it comes back as unsuccessful, we'll abort it. + SENT_NEEDS_ABORT: 4, + + // Temporary state used to mark transactions that need to be aborted. + NEEDS_ABORT: 5 +}; + +/** + * If a transaction does not succeed after 25 retries, we abort it. Among other things this ensure that if there's + * ever a bug causing a mismatch between client / server hashes for some data, we won't retry indefinitely. + * @type {number} + * @const + * @private + */ +(Repo as any).MAX_TRANSACTION_RETRIES_ = 25; + +/** + * @typedef {{ + * path: !Path, + * update: function(*):*, + * onComplete: ?function(?Error, boolean, ?DataSnapshot), + * status: ?TransactionStatus, + * order: !number, + * applyLocally: boolean, + * retryCount: !number, + * unwatcher: function(), + * abortReason: ?string, + * currentWriteId: !number, + * currentHash: ?string, + * currentInputSnapshot: ?Node, + * currentOutputSnapshotRaw: ?Node, + * currentOutputSnapshotResolved: ?Node + * }} + */ + +/** + * Setup the transaction data structures + * @private + */ +(Repo.prototype as any).transactions_init_ = function() { + /** + * Stores queues of outstanding transactions for Firebase locations. + * + * @type {!Tree.>} + * @private + */ + this.transactionQueueTree_ = new Tree(); +}; + +declare module './Repo' { + interface Repo { + startTransaction(path: Path, transactionUpdate, onComplete, applyLocally): void + } +} + +type Transaction = { + path: Path, + update: Function, + onComplete: Function, + status: number, + order: number, + applyLocally: boolean, + retryCount: number, + unwatcher: Function, + abortReason: any, + currentWriteId: any, + currentInputSnapshot: any, + currentOutputSnapshotRaw: any, + currentOutputSnapshotResolved: any +} + +/** + * Creates a new transaction, adds it to the transactions we're tracking, and sends it to the server if possible. + * + * @param {!Path} path Path at which to do transaction. + * @param {function(*):*} transactionUpdate Update callback. + * @param {?function(?Error, boolean, ?DataSnapshot)} onComplete Completion callback. + * @param {boolean} applyLocally Whether or not to make intermediate results visible + */ +(Repo.prototype as any).startTransaction = function(path: Path, + transactionUpdate: () => any, + onComplete: (Error, boolean, DataSnapshot) => any, + applyLocally: boolean) { + this.log_('transaction on ' + path); + + // Add a watch to make sure we get server updates. + var valueCallback = function() { }; + var watchRef = new Reference(this, path); + watchRef.on('value', valueCallback); + var unwatcher = function() { watchRef.off('value', valueCallback); }; + + // Initialize transaction. + var transaction: Transaction = { + path: path, + update: transactionUpdate, + onComplete: onComplete, + + // One of TransactionStatus enums. + status: null, + + // Used when combining transactions at different locations to figure out which one goes first. + order: LUIDGenerator(), + + // Whether to raise local events for this transaction. + applyLocally: applyLocally, + + // Count of how many times we've retried the transaction. + retryCount: 0, + + // Function to call to clean up our .on() listener. + unwatcher: unwatcher, + + // Stores why a transaction was aborted. + abortReason: null, + + currentWriteId: null, + + currentInputSnapshot: null, + + currentOutputSnapshotRaw: null, + + currentOutputSnapshotResolved: null + }; + + + // Run transaction initially. + var currentState = this.getLatestState_(path); + transaction.currentInputSnapshot = currentState; + var newVal = transaction.update(currentState.val()); + if (newVal === undefined) { + // Abort transaction. + transaction.unwatcher(); + transaction.currentOutputSnapshotRaw = null; + transaction.currentOutputSnapshotResolved = null; + if (transaction.onComplete) { + // We just set the input snapshot, so this cast should be safe + var snapshot = new DataSnapshot(transaction.currentInputSnapshot, new Reference(this, transaction.path), PRIORITY_INDEX); + transaction.onComplete(null, false, snapshot); + } + } else { + validateFirebaseData('transaction failed: Data returned ', newVal, transaction.path); + + // Mark as run and add to our queue. + transaction.status = TransactionStatus.RUN; + var queueNode = this.transactionQueueTree_.subTree(path); + var nodeQueue = queueNode.getValue() || []; + nodeQueue.push(transaction); + + queueNode.setValue(nodeQueue); + + // Update visibleData and raise events + // Note: We intentionally raise events after updating all of our transaction state, since the user could + // start new transactions from the event callbacks. + var priorityForNode; + if (typeof newVal === 'object' && newVal !== null && contains(newVal, '.priority')) { + priorityForNode = safeGet(newVal, '.priority'); + assert(isValidPriority(priorityForNode), 'Invalid priority returned by transaction. ' + + 'Priority must be a valid string, finite number, server value, or null.'); + } else { + var currentNode = this.serverSyncTree_.calcCompleteEventCache(path) || ChildrenNode.EMPTY_NODE; + priorityForNode = currentNode.getPriority().val(); + } + priorityForNode = /** @type {null|number|string} */ (priorityForNode); + + var serverValues = this.generateServerValues(); + var newNodeUnresolved = nodeFromJSON(newVal, priorityForNode); + var newNode = resolveDeferredValueSnapshot(newNodeUnresolved, serverValues); + transaction.currentOutputSnapshotRaw = newNodeUnresolved; + transaction.currentOutputSnapshotResolved = newNode; + transaction.currentWriteId = this.getNextWriteId_(); + + var events = this.serverSyncTree_.applyUserOverwrite(path, newNode, transaction.currentWriteId, transaction.applyLocally); + this.eventQueue_.raiseEventsForChangedPath(path, events); + + this.sendReadyTransactions_(); + } +}; + +/** + * @param {!Path} path + * @param {Array.=} excludeSets A specific set to exclude + * @return {Node} + * @private + */ +(Repo.prototype as any).getLatestState_ = function(path: Path, excludeSets: [number]): Node { + return this.serverSyncTree_.calcCompleteEventCache(path, excludeSets) || ChildrenNode.EMPTY_NODE; +}; + + +/** + * Sends any already-run transactions that aren't waiting for outstanding transactions to + * complete. + * + * Externally it's called with no arguments, but it calls itself recursively with a particular + * transactionQueueTree node to recurse through the tree. + * + * @param {Tree.>=} opt_node transactionQueueTree node to start at. + * @private + */ +(Repo.prototype as any).sendReadyTransactions_ = function(node?) { + var node = /** @type {!Tree.>} */ (node || this.transactionQueueTree_); + + // Before recursing, make sure any completed transactions are removed. + if (!node) { + this.pruneCompletedTransactionsBelowNode_(node); + } + + if (node.getValue() !== null) { + var queue = this.buildTransactionQueue_(node); + assert(queue.length > 0, 'Sending zero length transaction queue'); + + var allRun = queue.every(function(transaction) { + return transaction.status === TransactionStatus.RUN; + }); + + // If they're all run (and not sent), we can send them. Else, we must wait. + if (allRun) { + this.sendTransactionQueue_(node.path(), queue); + } + } else if (node.hasChildren()) { + var self = this; + node.forEachChild(function(childNode) { + self.sendReadyTransactions_(childNode); + }); + } +}; + + +/** + * Given a list of run transactions, send them to the server and then handle the result (success or failure). + * + * @param {!Path} path The location of the queue. + * @param {!Array.} queue Queue of transactions under the specified location. + * @private + */ +(Repo.prototype as any).sendTransactionQueue_ = function(path: Path, queue: Array) { + // Mark transactions as sent and increment retry count! + var setsToIgnore = queue.map(function(txn) { return txn.currentWriteId; }); + var latestState = this.getLatestState_(path, setsToIgnore); + var snapToSend = latestState; + var latestHash = latestState.hash(); + for (var i = 0; i < queue.length; i++) { + var txn = queue[i]; + assert(txn.status === TransactionStatus.RUN, + 'tryToSendTransactionQueue_: items in queue should all be run.'); + txn.status = TransactionStatus.SENT; + txn.retryCount++; + var relativePath = Path.relativePath(path, txn.path); + // If we've gotten to this point, the output snapshot must be defined. + snapToSend = snapToSend.updateChild(relativePath, /**@type {!Node} */ (txn.currentOutputSnapshotRaw)); + } + + var dataToSend = snapToSend.val(true); + var pathToSend = path; + + // Send the put. + var self = this; + this.server_.put(pathToSend.toString(), dataToSend, function(status) { + self.log_('transaction put response', {path: pathToSend.toString(), status: status}); + + var events = []; + if (status === 'ok') { + // Queue up the callbacks and fire them after cleaning up all of our transaction state, since + // the callback could trigger more transactions or sets. + var callbacks = []; + for (i = 0; i < queue.length; i++) { + queue[i].status = TransactionStatus.COMPLETED; + events = events.concat(self.serverSyncTree_.ackUserWrite(queue[i].currentWriteId)); + if (queue[i].onComplete) { + // We never unset the output snapshot, and given that this transaction is complete, it should be set + var node = /** @type {!Node} */ (queue[i].currentOutputSnapshotResolved); + var ref = new Reference(self, queue[i].path); + var snapshot = new DataSnapshot(node, ref, PRIORITY_INDEX); + callbacks.push(queue[i].onComplete.bind(null, null, true, snapshot)); + } + queue[i].unwatcher(); + } + + // Now remove the completed transactions. + self.pruneCompletedTransactionsBelowNode_(self.transactionQueueTree_.subTree(path)); + // There may be pending transactions that we can now send. + self.sendReadyTransactions_(); + + self.eventQueue_.raiseEventsForChangedPath(path, events); + + // Finally, trigger onComplete callbacks. + for (i = 0; i < callbacks.length; i++) { + exceptionGuard(callbacks[i]); + } + } else { + // transactions are no longer sent. Update their status appropriately. + if (status === 'datastale') { + for (i = 0; i < queue.length; i++) { + if (queue[i].status === TransactionStatus.SENT_NEEDS_ABORT) + queue[i].status = TransactionStatus.NEEDS_ABORT; + else + queue[i].status = TransactionStatus.RUN; + } + } else { + warn('transaction at ' + pathToSend.toString() + ' failed: ' + status); + for (i = 0; i < queue.length; i++) { + queue[i].status = TransactionStatus.NEEDS_ABORT; + queue[i].abortReason = status; + } + } + + self.rerunTransactions_(path); + } + }, latestHash); +}; + +/** + * Finds all transactions dependent on the data at changedPath and reruns them. + * + * Should be called any time cached data changes. + * + * Return the highest path that was affected by rerunning transactions. This is the path at which events need to + * be raised for. + * + * @param {!Path} changedPath The path in mergedData that changed. + * @return {!Path} The rootmost path that was affected by rerunning transactions. + * @private + */ +(Repo.prototype as any).rerunTransactions_ = function(changedPath: Path) { + var rootMostTransactionNode = this.getAncestorTransactionNode_(changedPath); + var path = rootMostTransactionNode.path(); + + var queue = this.buildTransactionQueue_(rootMostTransactionNode); + this.rerunTransactionQueue_(queue, path); + + return path; +}; + + +/** + * Does all the work of rerunning transactions (as well as cleans up aborted transactions and whatnot). + * + * @param {Array.} queue The queue of transactions to run. + * @param {!Path} path The path the queue is for. + * @private + */ +(Repo.prototype as any).rerunTransactionQueue_ = function(queue: Array, path: Path) { + if (queue.length === 0) { + return; // Nothing to do! + } + + // Queue up the callbacks and fire them after cleaning up all of our transaction state, since + // the callback could trigger more transactions or sets. + var callbacks = []; + var events = []; + // Ignore all of the sets we're going to re-run. + var txnsToRerun = queue.filter(function(q) { return q.status === TransactionStatus.RUN; }); + var setsToIgnore = txnsToRerun.map(function(q) { return q.currentWriteId; }); + for (var i = 0; i < queue.length; i++) { + var transaction = queue[i]; + var relativePath = Path.relativePath(path, transaction.path); + var abortTransaction = false, abortReason; + assert(relativePath !== null, 'rerunTransactionsUnderNode_: relativePath should not be null.'); + + if (transaction.status === TransactionStatus.NEEDS_ABORT) { + abortTransaction = true; + abortReason = transaction.abortReason; + events = events.concat(this.serverSyncTree_.ackUserWrite(transaction.currentWriteId, true)); + } else if (transaction.status === TransactionStatus.RUN) { + if (transaction.retryCount >= (Repo as any).MAX_TRANSACTION_RETRIES_) { + abortTransaction = true; + abortReason = 'maxretry'; + events = events.concat(this.serverSyncTree_.ackUserWrite(transaction.currentWriteId, true)); + } else { + // This code reruns a transaction + var currentNode = this.getLatestState_(transaction.path, setsToIgnore); + transaction.currentInputSnapshot = currentNode; + var newData = queue[i].update(currentNode.val()); + if (newData !== undefined) { + validateFirebaseData('transaction failed: Data returned ', newData, transaction.path); + var newDataNode = nodeFromJSON(newData); + var hasExplicitPriority = (typeof newData === 'object' && newData != null && + contains(newData, '.priority')); + if (!hasExplicitPriority) { + // Keep the old priority if there wasn't a priority explicitly specified. + newDataNode = newDataNode.updatePriority(currentNode.getPriority()); + } + + var oldWriteId = transaction.currentWriteId; + var serverValues = this.generateServerValues(); + var newNodeResolved = resolveDeferredValueSnapshot(newDataNode, serverValues); + + transaction.currentOutputSnapshotRaw = newDataNode; + transaction.currentOutputSnapshotResolved = newNodeResolved; + transaction.currentWriteId = this.getNextWriteId_(); + // Mutates setsToIgnore in place + setsToIgnore.splice(setsToIgnore.indexOf(oldWriteId), 1); + events = events.concat( + this.serverSyncTree_.applyUserOverwrite(transaction.path, newNodeResolved, transaction.currentWriteId, + transaction.applyLocally) + ); + events = events.concat(this.serverSyncTree_.ackUserWrite(oldWriteId, true)); + } else { + abortTransaction = true; + abortReason = 'nodata'; + events = events.concat(this.serverSyncTree_.ackUserWrite(transaction.currentWriteId, true)); + } + } + } + this.eventQueue_.raiseEventsForChangedPath(path, events); + events = []; + if (abortTransaction) { + // Abort. + queue[i].status = TransactionStatus.COMPLETED; + + // Removing a listener can trigger pruning which can muck with mergedData/visibleData (as it prunes data). + // So defer the unwatcher until we're done. + (function(unwatcher) { + setTimeout(unwatcher, Math.floor(0)); + })(queue[i].unwatcher); + + if (queue[i].onComplete) { + if (abortReason === 'nodata') { + var ref = new Reference(this, queue[i].path); + // We set this field immediately, so it's safe to cast to an actual snapshot + var lastInput = /** @type {!Node} */ (queue[i].currentInputSnapshot); + var snapshot = new DataSnapshot(lastInput, ref, PRIORITY_INDEX); + callbacks.push(queue[i].onComplete.bind(null, null, false, snapshot)); + } else { + callbacks.push(queue[i].onComplete.bind(null, new Error(abortReason), false, null)); + } + } + } + } + + // Clean up completed transactions. + this.pruneCompletedTransactionsBelowNode_(this.transactionQueueTree_); + + // Now fire callbacks, now that we're in a good, known state. + for (i = 0; i < callbacks.length; i++) { + exceptionGuard(callbacks[i]); + } + + // Try to send the transaction result to the server. + this.sendReadyTransactions_(); +}; + + +/** + * Returns the rootmost ancestor node of the specified path that has a pending transaction on it, or just returns + * the node for the given path if there are no pending transactions on any ancestor. + * + * @param {!Path} path The location to start at. + * @return {!Tree.>} The rootmost node with a transaction. + * @private + */ +(Repo.prototype as any).getAncestorTransactionNode_ = function(path: Path): Tree { + var front; + + // Start at the root and walk deeper into the tree towards path until we find a node with pending transactions. + var transactionNode = this.transactionQueueTree_; + while ((front = path.getFront()) !== null && transactionNode.getValue() === null) { + transactionNode = transactionNode.subTree(front); + path = path.popFront(); + } + + return transactionNode; +}; + + +/** + * Builds the queue of all transactions at or below the specified transactionNode. + * + * @param {!Tree.>} transactionNode + * @return {Array.} The generated queue. + * @private + */ +(Repo.prototype as any).buildTransactionQueue_ = function(transactionNode: Tree): Array { + // Walk any child transaction queues and aggregate them into a single queue. + var transactionQueue = []; + this.aggregateTransactionQueuesForNode_(transactionNode, transactionQueue); + + // Sort them by the order the transactions were created. + transactionQueue.sort(function(a, b) { return a.order - b.order; }); + + return transactionQueue; +}; + +/** + * @param {!Tree.>} node + * @param {Array.} queue + * @private + */ +(Repo.prototype as any).aggregateTransactionQueuesForNode_ = function(node: Tree, queue: Array) { + var nodeQueue = node.getValue(); + if (nodeQueue !== null) { + for (var i = 0; i < nodeQueue.length; i++) { + queue.push(nodeQueue[i]); + } + } + + var self = this; + node.forEachChild(function(child) { + self.aggregateTransactionQueuesForNode_(child, queue); + }); +}; + + +/** + * Remove COMPLETED transactions at or below this node in the transactionQueueTree_. + * + * @param {!Tree.>} node + * @private + */ +(Repo.prototype as any).pruneCompletedTransactionsBelowNode_ = function(node: Tree) { + var queue = node.getValue(); + if (queue) { + var to = 0; + for (var from = 0; from < queue.length; from++) { + if (queue[from].status !== TransactionStatus.COMPLETED) { + queue[to] = queue[from]; + to++; + } + } + queue.length = to; + node.setValue(queue.length > 0 ? queue : null); + } + + var self = this; + node.forEachChild(function(childNode) { + self.pruneCompletedTransactionsBelowNode_(childNode); + }); +}; + + +/** + * Aborts all transactions on ancestors or descendants of the specified path. Called when doing a set() or update() + * since we consider them incompatible with transactions. + * + * @param {!Path} path Path for which we want to abort related transactions. + * @return {!Path} + * @private + */ +(Repo.prototype as any).abortTransactions_ = function(path: Path) { + var affectedPath = this.getAncestorTransactionNode_(path).path(); + + var transactionNode = this.transactionQueueTree_.subTree(path); + var self = this; + + transactionNode.forEachAncestor(function(node) { + self.abortTransactionsOnNode_(node); + }); + + this.abortTransactionsOnNode_(transactionNode); + + transactionNode.forEachDescendant(function(node) { + self.abortTransactionsOnNode_(node); + }); + + return affectedPath; +}; + + +/** + * Abort transactions stored in this transaction queue node. + * + * @param {!Tree.>} node Node to abort transactions for. + * @private + */ +(Repo.prototype as any).abortTransactionsOnNode_ = function(node: Tree) { + var queue = node.getValue(); + if (queue !== null) { + + // Queue up the callbacks and fire them after cleaning up all of our transaction state, since + // the callback could trigger more transactions or sets. + var callbacks = []; + + // Go through queue. Any already-sent transactions must be marked for abort, while the unsent ones + // can be immediately aborted and removed. + var events = []; + var lastSent = -1; + for (var i = 0; i < queue.length; i++) { + if (queue[i].status === TransactionStatus.SENT_NEEDS_ABORT) { + // Already marked. No action needed. + } else if (queue[i].status === TransactionStatus.SENT) { + assert(lastSent === i - 1, 'All SENT items should be at beginning of queue.'); + lastSent = i; + // Mark transaction for abort when it comes back. + queue[i].status = TransactionStatus.SENT_NEEDS_ABORT; + queue[i].abortReason = 'set'; + } else { + assert(queue[i].status === TransactionStatus.RUN, + 'Unexpected transaction status in abort'); + // We can abort it immediately. + queue[i].unwatcher(); + events = events.concat(this.serverSyncTree_.ackUserWrite(queue[i].currentWriteId, true)); + if (queue[i].onComplete) { + var snapshot = null; + callbacks.push(queue[i].onComplete.bind(null, new Error('set'), false, snapshot)); + } + } + } + if (lastSent === -1) { + // We're not waiting for any sent transactions. We can clear the queue. + node.setValue(null); + } else { + // Remove the transactions we aborted. + queue.length = lastSent + 1; + } + + // Now fire the callbacks. + this.eventQueue_.raiseEventsForChangedPath(node.path(), events); + for (i = 0; i < callbacks.length; i++) { + exceptionGuard(callbacks[i]); + } + } +}; diff --git a/src/database/core/ServerActions.ts b/src/database/core/ServerActions.ts new file mode 100644 index 00000000000..e593a55487f --- /dev/null +++ b/src/database/core/ServerActions.ts @@ -0,0 +1,74 @@ +import { Query } from '../api/Query'; + +/** + * Interface defining the set of actions that can be performed against the Firebase server + * (basically corresponds to our wire protocol). + * + * @interface + */ +export interface ServerActions { + + /** + * @param {!Query} query + * @param {function():string} currentHashFn + * @param {?number} tag + * @param {function(string, *)} onComplete + */ + listen(query: Query, currentHashFn: () => string, tag: number | null, onComplete: (a: string, b: any) => any); + + /** + * Remove a listen. + * + * @param {!Query} query + * @param {?number} tag + */ + unlisten(query: Query, tag: number | null); + + /** + * @param {string} pathString + * @param {*} data + * @param {function(string, string)=} onComplete + * @param {string=} hash + */ + put(pathString: string, data: any, onComplete?: (a: string, b: string) => any, hash?: string); + + /** + * @param {string} pathString + * @param {*} data + * @param {function(string, ?string)} onComplete + * @param {string=} hash + */ + merge(pathString: string, data: any, onComplete: (a: string, b: string | null) => any, hash?: string); + + /** + * Refreshes the auth token for the current connection. + * @param {string} token The authentication token + */ + refreshAuthToken(token: string); + + /** + * @param {string} pathString + * @param {*} data + * @param {function(string, string)=} onComplete + */ + onDisconnectPut(pathString: string, data: any, onComplete?: (a: string, b: string) => any); + + /** + * @param {string} pathString + * @param {*} data + * @param {function(string, string)=} onComplete + */ + onDisconnectMerge(pathString: string, data: any, onComplete?: (a: string, b: string) => any); + + /** + * @param {string} pathString + * @param {function(string, string)=} onComplete + */ + onDisconnectCancel(pathString: string, onComplete?: (a: string, b: string) => any); + + /** + * @param {Object.} stats + */ + reportStats(stats: { [k: string]: any }); + +} diff --git a/src/database/core/SnapshotHolder.ts b/src/database/core/SnapshotHolder.ts new file mode 100644 index 00000000000..880dad4cd3f --- /dev/null +++ b/src/database/core/SnapshotHolder.ts @@ -0,0 +1,19 @@ +import { ChildrenNode } from "./snap/ChildrenNode"; + +/** + * Mutable object which basically just stores a reference to the "latest" immutable snapshot. + * + * @constructor + */ +export class SnapshotHolder { + private rootNode_; + constructor() { + this.rootNode_ = ChildrenNode.EMPTY_NODE; + } + getNode(path) { + return this.rootNode_.getChild(path); + } + updateSnapshot(path, newSnapshotNode) { + this.rootNode_ = this.rootNode_.updateChild(path, newSnapshotNode); + } +} diff --git a/src/database/core/SparseSnapshotTree.ts b/src/database/core/SparseSnapshotTree.ts new file mode 100644 index 00000000000..0b0321778bc --- /dev/null +++ b/src/database/core/SparseSnapshotTree.ts @@ -0,0 +1,161 @@ +import { Path } from "./util/Path"; +import { PRIORITY_INDEX } from "./snap/indexes/PriorityIndex"; +import { CountedSet } from "./util/CountedSet"; + +/** + * Helper class to store a sparse set of snapshots. + * + * @constructor + */ +export class SparseSnapshotTree { + value_; + children_; + constructor() { + /** + * @private + * @type {Node} + */ + this.value_ = null; + + /** + * @private + * @type {CountedSet} + */ + this.children_ = null; + }; + /** + * Gets the node stored at the given path if one exists. + * + * @param {!Path} path Path to look up snapshot for. + * @return {?Node} The retrieved node, or null. + */ + find(path) { + if (this.value_ != null) { + return this.value_.getChild(path); + } else if (!path.isEmpty() && this.children_ != null) { + var childKey = path.getFront(); + path = path.popFront(); + if (this.children_.contains(childKey)) { + var childTree = this.children_.get(childKey); + return childTree.find(path); + } else { + return null; + } + } else { + return null; + } + }; + + + /** + * Stores the given node at the specified path. If there is already a node + * at a shallower path, it merges the new data into that snapshot node. + * + * @param {!Path} path Path to look up snapshot for. + * @param {!Node} data The new data, or null. + */ + remember(path, data) { + if (path.isEmpty()) { + this.value_ = data; + this.children_ = null; + } else if (this.value_ !== null) { + this.value_ = this.value_.updateChild(path, data); + } else { + if (this.children_ == null) { + this.children_ = new CountedSet(); + } + + var childKey = path.getFront(); + if (!this.children_.contains(childKey)) { + this.children_.add(childKey, new SparseSnapshotTree()); + } + + var child = this.children_.get(childKey); + path = path.popFront(); + child.remember(path, data); + } + }; + + + /** + * Purge the data at path from the cache. + * + * @param {!Path} path Path to look up snapshot for. + * @return {boolean} True if this node should now be removed. + */ + forget(path) { + if (path.isEmpty()) { + this.value_ = null; + this.children_ = null; + return true; + } else { + if (this.value_ !== null) { + if (this.value_.isLeafNode()) { + // We're trying to forget a node that doesn't exist + return false; + } else { + var value = this.value_; + this.value_ = null; + + var self = this; + value.forEachChild(PRIORITY_INDEX, function(key, tree) { + self.remember(new Path(key), tree); + }); + + return this.forget(path); + } + } else if (this.children_ !== null) { + var childKey = path.getFront(); + path = path.popFront(); + if (this.children_.contains(childKey)) { + var safeToRemove = this.children_.get(childKey).forget(path); + if (safeToRemove) { + this.children_.remove(childKey); + } + } + + if (this.children_.isEmpty()) { + this.children_ = null; + return true; + } else { + return false; + } + + } else { + return true; + } + } + }; + + /** + * Recursively iterates through all of the stored tree and calls the + * callback on each one. + * + * @param {!Path} prefixPath Path to look up node for. + * @param {!Function} func The function to invoke for each tree. + */ + forEachTree(prefixPath, func) { + if (this.value_ !== null) { + func(prefixPath, this.value_); + } else { + this.forEachChild(function(key, tree) { + var path = new Path(prefixPath.toString() + '/' + key); + tree.forEachTree(path, func); + }); + } + }; + + + /** + * Iterates through each immediate child and triggers the callback. + * + * @param {!Function} func The function to invoke for each child. + */ + forEachChild(func) { + if (this.children_ !== null) { + this.children_.each(function(key, tree) { + func(key, tree); + }); + } + }; +} diff --git a/src/database/core/SyncPoint.ts b/src/database/core/SyncPoint.ts new file mode 100644 index 00000000000..ab58339d474 --- /dev/null +++ b/src/database/core/SyncPoint.ts @@ -0,0 +1,229 @@ +import { CacheNode } from "./view/CacheNode"; +import { ChildrenNode } from "./snap/ChildrenNode"; +import { assert } from "../../utils/assert"; +import { isEmpty, forEach, findValue, safeGet } from "../../utils/obj"; +import { ViewCache } from "./view/ViewCache"; +import { View } from "./view/View"; + +let __referenceConstructor; + +/** + * SyncPoint represents a single location in a SyncTree with 1 or more event registrations, meaning we need to + * maintain 1 or more Views at this location to cache server data and raise appropriate events for server changes + * and user writes (set, transaction, update). + * + * It's responsible for: + * - Maintaining the set of 1 or more views necessary at this location (a SyncPoint with 0 views should be removed). + * - Proxying user / server operations to the views as appropriate (i.e. applyServerOverwrite, + * applyUserOverwrite, etc.) + */ +export class SyncPoint { + static set __referenceConstructor(val) { + assert(!__referenceConstructor, '__referenceConstructor has already been defined'); + __referenceConstructor = val; + } + static get __referenceConstructor() { + assert(__referenceConstructor, 'Reference.ts has not been loaded'); + return __referenceConstructor; + } + + views_: object; + constructor() { + /** + * The Views being tracked at this location in the tree, stored as a map where the key is a + * queryId and the value is the View for that query. + * + * NOTE: This list will be quite small (usually 1, but perhaps 2 or 3; any more is an odd use case). + * + * @type {!Object.} + * @private + */ + this.views_ = { }; + }; + /** + * @return {boolean} + */ + isEmpty() { + return isEmpty(this.views_); + }; + + /** + * + * @param {!Operation} operation + * @param {!WriteTreeRef} writesCache + * @param {?Node} optCompleteServerCache + * @return {!Array.} + */ + applyOperation(operation, writesCache, optCompleteServerCache) { + var queryId = operation.source.queryId; + if (queryId !== null) { + var view = safeGet(this.views_, queryId); + assert(view != null, 'SyncTree gave us an op for an invalid query.'); + return view.applyOperation(operation, writesCache, optCompleteServerCache); + } else { + var events = []; + + forEach(this.views_, function(key, view) { + events = events.concat(view.applyOperation(operation, writesCache, optCompleteServerCache)); + }); + + return events; + } + }; + + /** + * Add an event callback for the specified query. + * + * @param {!Query} query + * @param {!EventRegistration} eventRegistration + * @param {!WriteTreeRef} writesCache + * @param {?Node} serverCache Complete server cache, if we have it. + * @param {boolean} serverCacheComplete + * @return {!Array.} Events to raise. + */ + addEventRegistration(query, eventRegistration, writesCache, serverCache, serverCacheComplete) { + var queryId = query.queryIdentifier(); + var view = safeGet(this.views_, queryId); + if (!view) { + // TODO: make writesCache take flag for complete server node + var eventCache = writesCache.calcCompleteEventCache(serverCacheComplete ? serverCache : null); + var eventCacheComplete = false; + if (eventCache) { + eventCacheComplete = true; + } else if (serverCache instanceof ChildrenNode) { + eventCache = writesCache.calcCompleteEventChildren(serverCache); + eventCacheComplete = false; + } else { + eventCache = ChildrenNode.EMPTY_NODE; + eventCacheComplete = false; + } + var viewCache = new ViewCache( + new CacheNode(/** @type {!Node} */ (eventCache), eventCacheComplete, false), + new CacheNode(/** @type {!Node} */ (serverCache), serverCacheComplete, false) + ); + view = new View(query, viewCache); + this.views_[queryId] = view; + } + + // This is guaranteed to exist now, we just created anything that was missing + view.addEventRegistration(eventRegistration); + return view.getInitialEvents(eventRegistration); + }; + + /** + * Remove event callback(s). Return cancelEvents if a cancelError is specified. + * + * If query is the default query, we'll check all views for the specified eventRegistration. + * If eventRegistration is null, we'll remove all callbacks for the specified view(s). + * + * @param {!Query} query + * @param {?EventRegistration} eventRegistration If null, remove all callbacks. + * @param {Error=} cancelError If a cancelError is provided, appropriate cancel events will be returned. + * @return {{removed:!Array., events:!Array.}} removed queries and any cancel events + */ + removeEventRegistration(query, eventRegistration, cancelError) { + var queryId = query.queryIdentifier(); + var removed = []; + var cancelEvents = []; + var hadCompleteView = this.hasCompleteView(); + if (queryId === 'default') { + // When you do ref.off(...), we search all views for the registration to remove. + var self = this; + forEach(this.views_, function(viewQueryId, view) { + cancelEvents = cancelEvents.concat(view.removeEventRegistration(eventRegistration, cancelError)); + if (view.isEmpty()) { + delete self.views_[viewQueryId]; + + // We'll deal with complete views later. + if (!view.getQuery().getQueryParams().loadsAllData()) { + removed.push(view.getQuery()); + } + } + }); + } else { + // remove the callback from the specific view. + var view = safeGet(this.views_, queryId); + if (view) { + cancelEvents = cancelEvents.concat(view.removeEventRegistration(eventRegistration, cancelError)); + if (view.isEmpty()) { + delete this.views_[queryId]; + + // We'll deal with complete views later. + if (!view.getQuery().getQueryParams().loadsAllData()) { + removed.push(view.getQuery()); + } + } + } + } + + if (hadCompleteView && !this.hasCompleteView()) { + // We removed our last complete view. + removed.push(new SyncPoint.__referenceConstructor(query.repo, query.path)); + } + + return {removed: removed, events: cancelEvents}; + }; + + /** + * @return {!Array.} + */ + getQueryViews() { + const values = Object.keys(this.views_) + .map(key => this.views_[key]); + return values.filter(function(view) { + return !view.getQuery().getQueryParams().loadsAllData(); + }); + }; + + /** + * + * @param {!Path} path The path to the desired complete snapshot + * @return {?Node} A complete cache, if it exists + */ + getCompleteServerCache(path) { + var serverCache = null; + forEach(this.views_, (key, view) => { + serverCache = serverCache || view.getCompleteServerCache(path); + }); + return serverCache; + }; + + /** + * @param {!Query} query + * @return {?View} + */ + viewForQuery(query) { + var params = query.getQueryParams(); + if (params.loadsAllData()) { + return this.getCompleteView(); + } else { + var queryId = query.queryIdentifier(); + return safeGet(this.views_, queryId); + } + }; + + /** + * @param {!Query} query + * @return {boolean} + */ + viewExistsForQuery(query) { + return this.viewForQuery(query) != null; + }; + + /** + * @return {boolean} + */ + hasCompleteView() { + return this.getCompleteView() != null; + }; + + /** + * @return {?View} + */ + getCompleteView() { + var completeView = findValue(this.views_, function(view) { + return view.getQuery().getQueryParams().loadsAllData(); + }); + return completeView || null; + }; +} diff --git a/src/database/core/SyncTree.ts b/src/database/core/SyncTree.ts new file mode 100644 index 00000000000..3310d6a34cb --- /dev/null +++ b/src/database/core/SyncTree.ts @@ -0,0 +1,749 @@ +import { assert } from '../../utils/assert'; +import { errorForServerCode } from "./util/util"; +import { AckUserWrite } from "./operation/AckUserWrite"; +import { ChildrenNode } from "./snap/ChildrenNode"; +import { forEach, safeGet } from "../../utils/obj"; +import { ImmutableTree } from "./util/ImmutableTree"; +import { ListenComplete } from "./operation/ListenComplete"; +import { Merge } from "./operation/Merge"; +import { OperationSource } from "./operation/Operation"; +import { Overwrite } from "./operation/Overwrite"; +import { Path } from "./util/Path"; +import { SyncPoint } from "./SyncPoint"; +import { WriteTree } from "./WriteTree"; +import { Query } from "../api/Query"; + +/** + * @typedef {{ + * startListening: function( + * !Query, + * ?number, + * function():string, + * function(!string, *):!Array. + * ):!Array., + * + * stopListening: function(!Query, ?number) + * }} + */ + +/** + * SyncTree is the central class for managing event callback registration, data caching, views + * (query processing), and event generation. There are typically two SyncTree instances for + * each Repo, one for the normal Firebase data, and one for the .info data. + * + * It has a number of responsibilities, including: + * - Tracking all user event callbacks (registered via addEventRegistration() and removeEventRegistration()). + * - Applying and caching data changes for user set(), transaction(), and update() calls + * (applyUserOverwrite(), applyUserMerge()). + * - Applying and caching data changes for server data changes (applyServerOverwrite(), + * applyServerMerge()). + * - Generating user-facing events for server and user changes (all of the apply* methods + * return the set of events that need to be raised as a result). + * - Maintaining the appropriate set of server listens to ensure we are always subscribed + * to the correct set of paths and queries to satisfy the current set of user event + * callbacks (listens are started/stopped using the provided listenProvider). + * + * NOTE: Although SyncTree tracks event callbacks and calculates events to raise, the actual + * events are returned to the caller rather than raised synchronously. + * + * @constructor + * @param {!ListenProvider} listenProvider Used by SyncTree to start / stop listening + * to server data. + */ +export class SyncTree { + /** + * Tree of SyncPoints. There's a SyncPoint at any location that has 1 or more views. + * @type {!ImmutableTree.} + * @private + */ + syncPointTree_; + + /** + * A tree of all pending user writes (user-initiated set()'s, transaction()'s, update()'s, etc.). + * @type {!WriteTree} + * @private + */ + pendingWriteTree_; + tagToQueryMap_; + queryToTagMap_; + listenProvider_; + + constructor(listenProvider) { + this.syncPointTree_ = ImmutableTree.Empty; + this.pendingWriteTree_ = new WriteTree(); + this.tagToQueryMap_ = {}; + this.queryToTagMap_ = {}; + this.listenProvider_ = listenProvider; + }; + + /** + * Apply the data changes for a user-generated set() or transaction() call. + * + * @param {!Path} path + * @param {!Node} newData + * @param {number} writeId + * @param {boolean=} visible + * @return {!Array.} Events to raise. + */ + applyUserOverwrite(path, newData, writeId, visible) { + // Record pending write. + this.pendingWriteTree_.addOverwrite(path, newData, writeId, visible); + + if (!visible) { + return []; + } else { + return this.applyOperationToSyncPoints_( + new Overwrite(OperationSource.User, path, newData)); + } + }; + + /** + * Apply the data from a user-generated update() call + * + * @param {!Path} path + * @param {!Object.} changedChildren + * @param {!number} writeId + * @return {!Array.} Events to raise. + */ + applyUserMerge(path, changedChildren, writeId) { + // Record pending merge. + this.pendingWriteTree_.addMerge(path, changedChildren, writeId); + + var changeTree = ImmutableTree.fromObject(changedChildren); + + return this.applyOperationToSyncPoints_( + new Merge(OperationSource.User, path, changeTree)); + }; + + /** + * Acknowledge a pending user write that was previously registered with applyUserOverwrite() or applyUserMerge(). + * + * @param {!number} writeId + * @param {boolean=} revert True if the given write failed and needs to be reverted + * @return {!Array.} Events to raise. + */ + ackUserWrite(writeId, revert) { + revert = revert || false; + + var write = this.pendingWriteTree_.getWrite(writeId); + var needToReevaluate = this.pendingWriteTree_.removeWrite(writeId); + if (!needToReevaluate) { + return []; + } else { + var affectedTree = ImmutableTree.Empty; + if (write.snap != null) { // overwrite + affectedTree = affectedTree.set(Path.Empty, true); + } else { + forEach(write.children, function(pathString, node) { + affectedTree = affectedTree.set(new Path(pathString), node); + }); + } + return this.applyOperationToSyncPoints_(new AckUserWrite(write.path, affectedTree, revert)); + } + }; + + /** + * Apply new server data for the specified path.. + * + * @param {!Path} path + * @param {!Node} newData + * @return {!Array.} Events to raise. + */ + applyServerOverwrite(path, newData) { + return this.applyOperationToSyncPoints_( + new Overwrite(OperationSource.Server, path, newData)); + }; + + /** + * Apply new server data to be merged in at the specified path. + * + * @param {!Path} path + * @param {!Object.} changedChildren + * @return {!Array.} Events to raise. + */ + applyServerMerge(path, changedChildren) { + var changeTree = ImmutableTree.fromObject(changedChildren); + + return this.applyOperationToSyncPoints_( + new Merge(OperationSource.Server, path, changeTree)); + }; + + /** + * Apply a listen complete for a query + * + * @param {!Path} path + * @return {!Array.} Events to raise. + */ + applyListenComplete(path) { + return this.applyOperationToSyncPoints_( + new ListenComplete(OperationSource.Server, path)); + }; + + /** + * Apply new server data for the specified tagged query. + * + * @param {!Path} path + * @param {!Node} snap + * @param {!number} tag + * @return {!Array.} Events to raise. + */ + applyTaggedQueryOverwrite(path, snap, tag) { + var queryKey = this.queryKeyForTag_(tag); + if (queryKey != null) { + var r = this.parseQueryKey_(queryKey); + var queryPath = r.path, queryId = r.queryId; + var relativePath = Path.relativePath(queryPath, path); + var op = new Overwrite(OperationSource.forServerTaggedQuery(queryId), + relativePath, snap); + return this.applyTaggedOperation_(queryPath, queryId, op); + } else { + // Query must have been removed already + return []; + } + }; + + /** + * Apply server data to be merged in for the specified tagged query. + * + * @param {!Path} path + * @param {!Object.} changedChildren + * @param {!number} tag + * @return {!Array.} Events to raise. + */ + applyTaggedQueryMerge(path, changedChildren, tag) { + var queryKey = this.queryKeyForTag_(tag); + if (queryKey) { + var r = this.parseQueryKey_(queryKey); + var queryPath = r.path, queryId = r.queryId; + var relativePath = Path.relativePath(queryPath, path); + var changeTree = ImmutableTree.fromObject(changedChildren); + var op = new Merge(OperationSource.forServerTaggedQuery(queryId), + relativePath, changeTree); + return this.applyTaggedOperation_(queryPath, queryId, op); + } else { + // We've already removed the query. No big deal, ignore the update + return []; + } + }; + + /** + * Apply a listen complete for a tagged query + * + * @param {!Path} path + * @param {!number} tag + * @return {!Array.} Events to raise. + */ + applyTaggedListenComplete(path, tag) { + var queryKey = this.queryKeyForTag_(tag); + if (queryKey) { + var r = this.parseQueryKey_(queryKey); + var queryPath = r.path, queryId = r.queryId; + var relativePath = Path.relativePath(queryPath, path); + var op = new ListenComplete(OperationSource.forServerTaggedQuery(queryId), + relativePath); + return this.applyTaggedOperation_(queryPath, queryId, op); + } else { + // We've already removed the query. No big deal, ignore the update + return []; + } + }; + + /** + * Add an event callback for the specified query. + * + * @param {!Query} query + * @param {!EventRegistration} eventRegistration + * @return {!Array.} Events to raise. + */ + addEventRegistration(query, eventRegistration) { + var path = query.path; + + var serverCache = null; + var foundAncestorDefaultView = false; + // Any covering writes will necessarily be at the root, so really all we need to find is the server cache. + // Consider optimizing this once there's a better understanding of what actual behavior will be. + this.syncPointTree_.foreachOnPath(path, function(pathToSyncPoint, sp) { + var relativePath = Path.relativePath(pathToSyncPoint, path); + serverCache = serverCache || sp.getCompleteServerCache(relativePath); + foundAncestorDefaultView = foundAncestorDefaultView || sp.hasCompleteView(); + }); + var syncPoint = this.syncPointTree_.get(path); + if (!syncPoint) { + syncPoint = new SyncPoint(); + this.syncPointTree_ = this.syncPointTree_.set(path, syncPoint); + } else { + foundAncestorDefaultView = foundAncestorDefaultView || syncPoint.hasCompleteView(); + serverCache = serverCache || syncPoint.getCompleteServerCache(Path.Empty); + } + + var serverCacheComplete; + if (serverCache != null) { + serverCacheComplete = true; + } else { + serverCacheComplete = false; + serverCache = ChildrenNode.EMPTY_NODE; + var subtree = this.syncPointTree_.subtree(path); + subtree.foreachChild(function(childName, childSyncPoint) { + var completeCache = childSyncPoint.getCompleteServerCache(Path.Empty); + if (completeCache) { + serverCache = serverCache.updateImmediateChild(childName, completeCache); + } + }); + } + + var viewAlreadyExists = syncPoint.viewExistsForQuery(query); + if (!viewAlreadyExists && !query.getQueryParams().loadsAllData()) { + // We need to track a tag for this query + var queryKey = this.makeQueryKey_(query); + assert(!(queryKey in this.queryToTagMap_), + 'View does not exist, but we have a tag'); + var tag = SyncTree.getNextQueryTag_(); + this.queryToTagMap_[queryKey] = tag; + // Coerce to string to avoid sparse arrays. + this.tagToQueryMap_['_' + tag] = queryKey; + } + var writesCache = this.pendingWriteTree_.childWrites(path); + var events = syncPoint.addEventRegistration(query, eventRegistration, writesCache, serverCache, serverCacheComplete); + if (!viewAlreadyExists && !foundAncestorDefaultView) { + var view = /** @type !View */ (syncPoint.viewForQuery(query)); + events = events.concat(this.setupListener_(query, view)); + } + return events; + }; + + /** + * Remove event callback(s). + * + * If query is the default query, we'll check all queries for the specified eventRegistration. + * If eventRegistration is null, we'll remove all callbacks for the specified query/queries. + * + * @param {!Query} query + * @param {?EventRegistration} eventRegistration If null, all callbacks are removed. + * @param {Error=} cancelError If a cancelError is provided, appropriate cancel events will be returned. + * @return {!Array.} Cancel events, if cancelError was provided. + */ + removeEventRegistration(query, eventRegistration, cancelError?) { + // Find the syncPoint first. Then deal with whether or not it has matching listeners + var path = query.path; + var maybeSyncPoint = this.syncPointTree_.get(path); + var cancelEvents = []; + // A removal on a default query affects all queries at that location. A removal on an indexed query, even one without + // other query constraints, does *not* affect all queries at that location. So this check must be for 'default', and + // not loadsAllData(). + if (maybeSyncPoint && (query.queryIdentifier() === 'default' || maybeSyncPoint.viewExistsForQuery(query))) { + /** + * @type {{removed: !Array., events: !Array.}} + */ + var removedAndEvents = maybeSyncPoint.removeEventRegistration(query, eventRegistration, cancelError); + if (maybeSyncPoint.isEmpty()) { + this.syncPointTree_ = this.syncPointTree_.remove(path); + } + var removed = removedAndEvents.removed; + cancelEvents = removedAndEvents.events; + // We may have just removed one of many listeners and can short-circuit this whole process + // We may also not have removed a default listener, in which case all of the descendant listeners should already be + // properly set up. + // + // Since indexed queries can shadow if they don't have other query constraints, check for loadsAllData(), instead of + // queryId === 'default' + var removingDefault = -1 !== removed.findIndex(function(query) { + return query.getQueryParams().loadsAllData(); + }); + var covered = this.syncPointTree_.findOnPath(path, function(relativePath, parentSyncPoint) { + return parentSyncPoint.hasCompleteView(); + }); + + if (removingDefault && !covered) { + var subtree = this.syncPointTree_.subtree(path); + // There are potentially child listeners. Determine what if any listens we need to send before executing the + // removal + if (!subtree.isEmpty()) { + // We need to fold over our subtree and collect the listeners to send + var newViews = this.collectDistinctViewsForSubTree_(subtree); + + // Ok, we've collected all the listens we need. Set them up. + for (var i = 0; i < newViews.length; ++i) { + var view = newViews[i], newQuery = view.getQuery(); + var listener = this.createListenerForView_(view); + this.listenProvider_.startListening(this.queryForListening_(newQuery), this.tagForQuery_(newQuery), + listener.hashFn, listener.onComplete); + } + } else { + // There's nothing below us, so nothing we need to start listening on + } + } + // If we removed anything and we're not covered by a higher up listen, we need to stop listening on this query + // The above block has us covered in terms of making sure we're set up on listens lower in the tree. + // Also, note that if we have a cancelError, it's already been removed at the provider level. + if (!covered && removed.length > 0 && !cancelError) { + // If we removed a default, then we weren't listening on any of the other queries here. Just cancel the one + // default. Otherwise, we need to iterate through and cancel each individual query + if (removingDefault) { + // We don't tag default listeners + var defaultTag = null; + this.listenProvider_.stopListening(this.queryForListening_(query), defaultTag); + } else { + var self = this; + removed.forEach(function(queryToRemove) { + var queryIdToRemove = queryToRemove.queryIdentifier(); + var tagToRemove = self.queryToTagMap_[self.makeQueryKey_(queryToRemove)]; + self.listenProvider_.stopListening(self.queryForListening_(queryToRemove), tagToRemove); + }); + } + } + // Now, clear all of the tags we're tracking for the removed listens + this.removeTags_(removed); + } else { + // No-op, this listener must've been already removed + } + return cancelEvents; + }; + + /** + * Returns a complete cache, if we have one, of the data at a particular path. The location must have a listener above + * it, but as this is only used by transaction code, that should always be the case anyways. + * + * Note: this method will *include* hidden writes from transaction with applyLocally set to false. + * @param {!Path} path The path to the data we want + * @param {Array.=} writeIdsToExclude A specific set to be excluded + * @return {?Node} + */ + calcCompleteEventCache(path, writeIdsToExclude) { + var includeHiddenSets = true; + var writeTree = this.pendingWriteTree_; + var serverCache = this.syncPointTree_.findOnPath(path, function(pathSoFar, syncPoint) { + var relativePath = Path.relativePath(pathSoFar, path); + var serverCache = syncPoint.getCompleteServerCache(relativePath); + if (serverCache) { + return serverCache; + } + }); + return writeTree.calcCompleteEventCache(path, serverCache, writeIdsToExclude, includeHiddenSets); + }; + + /** + * This collapses multiple unfiltered views into a single view, since we only need a single + * listener for them. + * + * @param {!ImmutableTree.} subtree + * @return {!Array.} + * @private + */ + collectDistinctViewsForSubTree_(subtree) { + return subtree.fold(function(relativePath, maybeChildSyncPoint, childMap) { + if (maybeChildSyncPoint && maybeChildSyncPoint.hasCompleteView()) { + var completeView = maybeChildSyncPoint.getCompleteView(); + return [completeView]; + } else { + // No complete view here, flatten any deeper listens into an array + var views = []; + if (maybeChildSyncPoint) { + views = maybeChildSyncPoint.getQueryViews(); + } + forEach(childMap, function(key, childViews) { + views = views.concat(childViews); + }); + return views; + } + }); + }; + + /** + * @param {!Array.} queries + * @private + */ + removeTags_(queries) { + for (var j = 0; j < queries.length; ++j) { + var removedQuery = queries[j]; + if (!removedQuery.getQueryParams().loadsAllData()) { + // We should have a tag for this + var removedQueryKey = this.makeQueryKey_(removedQuery); + var removedQueryTag = this.queryToTagMap_[removedQueryKey]; + delete this.queryToTagMap_[removedQueryKey]; + delete this.tagToQueryMap_['_' + removedQueryTag]; + } + } + }; + + + /** + * Normalizes a query to a query we send the server for listening + * @param {!Query} query + * @return {!Query} The normalized query + * @private + */ + queryForListening_(query: Query) { + if (query.getQueryParams().loadsAllData() && !query.getQueryParams().isDefault()) { + // We treat queries that load all data as default queries + // Cast is necessary because ref() technically returns Firebase which is actually fb.api.Firebase which inherits + // from Query + return /** @type {!Query} */(query.getRef()); + } else { + return query; + } + }; + + + /** + * For a given new listen, manage the de-duplication of outstanding subscriptions. + * + * @param {!Query} query + * @param {!View} view + * @return {!Array.} This method can return events to support synchronous data sources + * @private + */ + setupListener_(query, view) { + var path = query.path; + var tag = this.tagForQuery_(query); + var listener = this.createListenerForView_(view); + + var events = this.listenProvider_.startListening(this.queryForListening_(query), tag, listener.hashFn, + listener.onComplete); + + var subtree = this.syncPointTree_.subtree(path); + // The root of this subtree has our query. We're here because we definitely need to send a listen for that, but we + // may need to shadow other listens as well. + if (tag) { + assert(!subtree.value.hasCompleteView(), "If we're adding a query, it shouldn't be shadowed"); + } else { + // Shadow everything at or below this location, this is a default listener. + var queriesToStop = subtree.fold(function(relativePath, maybeChildSyncPoint, childMap) { + if (!relativePath.isEmpty() && maybeChildSyncPoint && maybeChildSyncPoint.hasCompleteView()) { + return [maybeChildSyncPoint.getCompleteView().getQuery()]; + } else { + // No default listener here, flatten any deeper queries into an array + var queries = []; + if (maybeChildSyncPoint) { + queries = queries.concat( + maybeChildSyncPoint.getQueryViews().map(function(view) { + return view.getQuery(); + }) + ); + } + forEach(childMap, function(key, childQueries) { + queries = queries.concat(childQueries); + }); + return queries; + } + }); + for (var i = 0; i < queriesToStop.length; ++i) { + var queryToStop = queriesToStop[i]; + this.listenProvider_.stopListening(this.queryForListening_(queryToStop), this.tagForQuery_(queryToStop)); + } + } + return events; + }; + + /** + * + * @param {!View} view + * @return {{hashFn: function(), onComplete: function(!string, *)}} + * @private + */ + createListenerForView_(view) { + var self = this; + var query = view.getQuery(); + var tag = this.tagForQuery_(query); + + return { + hashFn: function() { + var cache = view.getServerCache() || ChildrenNode.EMPTY_NODE; + return cache.hash(); + }, + onComplete: function(status, data) { + if (status === 'ok') { + if (tag) { + return self.applyTaggedListenComplete(query.path, tag); + } else { + return self.applyListenComplete(query.path); + } + } else { + // If a listen failed, kill all of the listeners here, not just the one that triggered the error. + // Note that this may need to be scoped to just this listener if we change permissions on filtered children + var error = errorForServerCode(status, query); + return self.removeEventRegistration(query, /*eventRegistration*/null, error); + } + } + }; + }; + + /** + * Given a query, computes a "queryKey" suitable for use in our queryToTagMap_. + * @private + * @param {!Query} query + * @return {string} + */ + makeQueryKey_(query) { + return query.path.toString() + '$' + query.queryIdentifier(); + }; + + /** + * Given a queryKey (created by makeQueryKey), parse it back into a path and queryId. + * @private + * @param {!string} queryKey + * @return {{queryId: !string, path: !Path}} + */ + parseQueryKey_(queryKey) { + var splitIndex = queryKey.indexOf('$'); + assert(splitIndex !== -1 && splitIndex < queryKey.length - 1, 'Bad queryKey.'); + return { + queryId: queryKey.substr(splitIndex + 1), + path: new Path(queryKey.substr(0, splitIndex)) + }; + }; + + /** + * Return the query associated with the given tag, if we have one + * @param {!number} tag + * @return {?string} + * @private + */ + queryKeyForTag_(tag) { + return this.tagToQueryMap_['_' + tag]; + }; + + /** + * Return the tag associated with the given query. + * @param {!Query} query + * @return {?number} + * @private + */ + tagForQuery_(query) { + var queryKey = this.makeQueryKey_(query); + return safeGet(this.queryToTagMap_, queryKey); + }; + + /** + * Static tracker for next query tag. + * @type {number} + * @private + */ + static nextQueryTag_ = 1; + + /** + * Static accessor for query tags. + * @return {number} + * @private + */ + static getNextQueryTag_ = function() { + return SyncTree.nextQueryTag_++; + }; + + /** + * A helper method to apply tagged operations + * + * @param {!Path} queryPath + * @param {!string} queryId + * @param {!Operation} operation + * @return {!Array.} + * @private + */ + applyTaggedOperation_(queryPath, queryId, operation) { + var syncPoint = this.syncPointTree_.get(queryPath); + assert(syncPoint, "Missing sync point for query tag that we're tracking"); + var writesCache = this.pendingWriteTree_.childWrites(queryPath); + return syncPoint.applyOperation(operation, writesCache, /*serverCache=*/null); + } + + /** + * A helper method that visits all descendant and ancestor SyncPoints, applying the operation. + * + * NOTES: + * - Descendant SyncPoints will be visited first (since we raise events depth-first). + + * - We call applyOperation() on each SyncPoint passing three things: + * 1. A version of the Operation that has been made relative to the SyncPoint location. + * 2. A WriteTreeRef of any writes we have cached at the SyncPoint location. + * 3. A snapshot Node with cached server data, if we have it. + + * - We concatenate all of the events returned by each SyncPoint and return the result. + * + * @param {!Operation} operation + * @return {!Array.} + * @private + */ + applyOperationToSyncPoints_(operation) { + return this.applyOperationHelper_(operation, this.syncPointTree_, /*serverCache=*/ null, + this.pendingWriteTree_.childWrites(Path.Empty)); + + }; + + /** + * Recursive helper for applyOperationToSyncPoints_ + * + * @private + * @param {!Operation} operation + * @param {ImmutableTree.} syncPointTree + * @param {?Node} serverCache + * @param {!WriteTreeRef} writesCache + * @return {!Array.} + */ + applyOperationHelper_(operation, syncPointTree, serverCache, writesCache) { + + if (operation.path.isEmpty()) { + return this.applyOperationDescendantsHelper_(operation, syncPointTree, serverCache, writesCache); + } else { + var syncPoint = syncPointTree.get(Path.Empty); + + // If we don't have cached server data, see if we can get it from this SyncPoint. + if (serverCache == null && syncPoint != null) { + serverCache = syncPoint.getCompleteServerCache(Path.Empty); + } + + var events = []; + var childName = operation.path.getFront(); + var childOperation = operation.operationForChild(childName); + var childTree = syncPointTree.children.get(childName); + if (childTree && childOperation) { + var childServerCache = serverCache ? serverCache.getImmediateChild(childName) : null; + var childWritesCache = writesCache.child(childName); + events = events.concat( + this.applyOperationHelper_(childOperation, childTree, childServerCache, childWritesCache)); + } + + if (syncPoint) { + events = events.concat(syncPoint.applyOperation(operation, writesCache, serverCache)); + } + + return events; + } + }; + + /** + * Recursive helper for applyOperationToSyncPoints_ + * + * @private + * @param {!Operation} operation + * @param {ImmutableTree.} syncPointTree + * @param {?Node} serverCache + * @param {!WriteTreeRef} writesCache + * @return {!Array.} + */ + applyOperationDescendantsHelper_(operation, syncPointTree, + serverCache, writesCache) { + var syncPoint = syncPointTree.get(Path.Empty); + + // If we don't have cached server data, see if we can get it from this SyncPoint. + if (serverCache == null && syncPoint != null) { + serverCache = syncPoint.getCompleteServerCache(Path.Empty); + } + + var events = []; + var self = this; + syncPointTree.children.inorderTraversal(function(childName, childTree) { + var childServerCache = serverCache ? serverCache.getImmediateChild(childName) : null; + var childWritesCache = writesCache.child(childName); + var childOperation = operation.operationForChild(childName); + if (childOperation) { + events = events.concat( + self.applyOperationDescendantsHelper_(childOperation, childTree, childServerCache, childWritesCache)); + } + }); + + if (syncPoint) { + events = events.concat(syncPoint.applyOperation(operation, writesCache, serverCache)); + } + + return events; + }; +} diff --git a/src/database/core/WriteTree.ts b/src/database/core/WriteTree.ts new file mode 100644 index 00000000000..e780039f000 --- /dev/null +++ b/src/database/core/WriteTree.ts @@ -0,0 +1,639 @@ +import { findKey, forEach, safeGet } from "../../utils/obj"; +import { assert, assertionError } from "../../utils/assert"; +import { Path } from "./util/Path"; +import { CompoundWrite } from "./CompoundWrite"; +import { PRIORITY_INDEX } from "./snap/indexes/PriorityIndex"; +import { ChildrenNode } from "./snap/ChildrenNode"; + +/** + * Defines a single user-initiated write operation. May be the result of a set(), transaction(), or update() call. In + * the case of a set() or transaction, snap wil be non-null. In the case of an update(), children will be non-null. + * + * @typedef {{ + * writeId: number, + * path: !Path, + * snap: ?Node, + * children: ?Object., + * visible: boolean + * }} + */ + +/** + * WriteTree tracks all pending user-initiated writes and has methods to calculate the result of merging them + * with underlying server data (to create "event cache" data). Pending writes are added with addOverwrite() + * and addMerge(), and removed with removeWrite(). + * + * @constructor + */ +export class WriteTree { + /** + * A tree tracking the result of applying all visible writes. This does not include transactions with + * applyLocally=false or writes that are completely shadowed by other writes. + * + * @type {!CompoundWrite} + * @private + */ + visibleWrites_; + + /** + * A list of all pending writes, regardless of visibility and shadowed-ness. Used to calculate arbitrary + * sets of the changed data, such as hidden writes (from transactions) or changes with certain writes excluded (also + * used by transactions). + * + * @type {!Array.} + * @private + */ + allWrites_; + lastWriteId_; + + constructor() { + this.visibleWrites_ = CompoundWrite.Empty; + this.allWrites_ = []; + this.lastWriteId_ = -1; + }; + /** + * Create a new WriteTreeRef for the given path. For use with a new sync point at the given path. + * + * @param {!Path} path + * @return {!WriteTreeRef} + */ + childWrites(path): WriteTreeRef { + return new WriteTreeRef(path, this); + }; + + /** + * Record a new overwrite from user code. + * + * @param {!Path} path + * @param {!Node} snap + * @param {!number} writeId + * @param {boolean=} visible This is set to false by some transactions. It should be excluded from event caches + */ + addOverwrite(path, snap, writeId, visible) { + assert(writeId > this.lastWriteId_, 'Stacking an older write on top of newer ones'); + if (visible === undefined) { + visible = true; + } + this.allWrites_.push({path: path, snap: snap, writeId: writeId, visible: visible}); + + if (visible) { + this.visibleWrites_ = this.visibleWrites_.addWrite(path, snap); + } + this.lastWriteId_ = writeId; + }; + + /** + * Record a new merge from user code. + * + * @param {!Path} path + * @param {!Object.} changedChildren + * @param {!number} writeId + */ + addMerge(path, changedChildren, writeId) { + assert(writeId > this.lastWriteId_, 'Stacking an older merge on top of newer ones'); + this.allWrites_.push({path: path, children: changedChildren, writeId: writeId, visible: true}); + + this.visibleWrites_ = this.visibleWrites_.addWrites(path, changedChildren); + this.lastWriteId_ = writeId; + }; + + + /** + * @param {!number} writeId + * @return {?WriteRecord} + */ + getWrite(writeId) { + for (var i = 0; i < this.allWrites_.length; i++) { + var record = this.allWrites_[i]; + if (record.writeId === writeId) { + return record; + } + } + return null; + }; + + + /** + * Remove a write (either an overwrite or merge) that has been successfully acknowledge by the server. Recalculates + * the tree if necessary. We return true if it may have been visible, meaning views need to reevaluate. + * + * @param {!number} writeId + * @return {boolean} true if the write may have been visible (meaning we'll need to reevaluate / raise + * events as a result). + */ + removeWrite(writeId) { + // Note: disabling this check. It could be a transaction that preempted another transaction, and thus was applied + // out of order. + //var validClear = revert || this.allWrites_.length === 0 || writeId <= this.allWrites_[0].writeId; + //assert(validClear, "Either we don't have this write, or it's the first one in the queue"); + + var idx = this.allWrites_.findIndex(function(s) { return s.writeId === writeId; }); + assert(idx >= 0, 'removeWrite called with nonexistent writeId.'); + var writeToRemove = this.allWrites_[idx]; + this.allWrites_.splice(idx, 1); + + var removedWriteWasVisible = writeToRemove.visible; + var removedWriteOverlapsWithOtherWrites = false; + + var i = this.allWrites_.length - 1; + + while (removedWriteWasVisible && i >= 0) { + var currentWrite = this.allWrites_[i]; + if (currentWrite.visible) { + if (i >= idx && this.recordContainsPath_(currentWrite, writeToRemove.path)) { + // The removed write was completely shadowed by a subsequent write. + removedWriteWasVisible = false; + } else if (writeToRemove.path.contains(currentWrite.path)) { + // Either we're covering some writes or they're covering part of us (depending on which came first). + removedWriteOverlapsWithOtherWrites = true; + } + } + i--; + } + + if (!removedWriteWasVisible) { + return false; + } else if (removedWriteOverlapsWithOtherWrites) { + // There's some shadowing going on. Just rebuild the visible writes from scratch. + this.resetTree_(); + return true; + } else { + // There's no shadowing. We can safely just remove the write(s) from visibleWrites. + if (writeToRemove.snap) { + this.visibleWrites_ = this.visibleWrites_.removeWrite(writeToRemove.path); + } else { + var children = writeToRemove.children; + var self = this; + forEach(children, function(childName, childSnap) { + self.visibleWrites_ = self.visibleWrites_.removeWrite(writeToRemove.path.child(childName)); + }); + } + return true; + } + }; + + /** + * Return a complete snapshot for the given path if there's visible write data at that path, else null. + * No server data is considered. + * + * @param {!Path} path + * @return {?Node} + */ + getCompleteWriteData(path) { + return this.visibleWrites_.getCompleteNode(path); + }; + + /** + * Given optional, underlying server data, and an optional set of constraints (exclude some sets, include hidden + * writes), attempt to calculate a complete snapshot for the given path + * + * @param {!Path} treePath + * @param {?Node} completeServerCache + * @param {Array.=} writeIdsToExclude An optional set to be excluded + * @param {boolean=} includeHiddenWrites Defaults to false, whether or not to layer on writes with visible set to false + * @return {?Node} + */ + calcCompleteEventCache(treePath, completeServerCache, writeIdsToExclude, + includeHiddenWrites) { + if (!writeIdsToExclude && !includeHiddenWrites) { + var shadowingNode = this.visibleWrites_.getCompleteNode(treePath); + if (shadowingNode != null) { + return shadowingNode; + } else { + var subMerge = this.visibleWrites_.childCompoundWrite(treePath); + if (subMerge.isEmpty()) { + return completeServerCache; + } else if (completeServerCache == null && !subMerge.hasCompleteWrite(Path.Empty)) { + // We wouldn't have a complete snapshot, since there's no underlying data and no complete shadow + return null; + } else { + var layeredCache = completeServerCache || ChildrenNode.EMPTY_NODE; + return subMerge.apply(layeredCache); + } + } + } else { + var merge = this.visibleWrites_.childCompoundWrite(treePath); + if (!includeHiddenWrites && merge.isEmpty()) { + return completeServerCache; + } else { + // If the server cache is null, and we don't have a complete cache, we need to return null + if (!includeHiddenWrites && completeServerCache == null && !merge.hasCompleteWrite(Path.Empty)) { + return null; + } else { + var filter = function(write) { + return (write.visible || includeHiddenWrites) && + (!writeIdsToExclude || !~writeIdsToExclude.indexOf(write.writeId)) && + (write.path.contains(treePath) || treePath.contains(write.path)); + }; + var mergeAtPath = WriteTree.layerTree_(this.allWrites_, filter, treePath); + layeredCache = completeServerCache || ChildrenNode.EMPTY_NODE; + return mergeAtPath.apply(layeredCache); + } + } + } + }; + + /** + * With optional, underlying server data, attempt to return a children node of children that we have complete data for. + * Used when creating new views, to pre-fill their complete event children snapshot. + * + * @param {!Path} treePath + * @param {?ChildrenNode} completeServerChildren + * @return {!ChildrenNode} + */ + calcCompleteEventChildren(treePath, completeServerChildren) { + var completeChildren = ChildrenNode.EMPTY_NODE; + var topLevelSet = this.visibleWrites_.getCompleteNode(treePath); + if (topLevelSet) { + if (!topLevelSet.isLeafNode()) { + // we're shadowing everything. Return the children. + topLevelSet.forEachChild(PRIORITY_INDEX, function(childName, childSnap) { + completeChildren = completeChildren.updateImmediateChild(childName, childSnap); + }); + } + return completeChildren; + } else if (completeServerChildren) { + // Layer any children we have on top of this + // We know we don't have a top-level set, so just enumerate existing children + var merge = this.visibleWrites_.childCompoundWrite(treePath); + completeServerChildren.forEachChild(PRIORITY_INDEX, function(childName, childNode) { + var node = merge.childCompoundWrite(new Path(childName)).apply(childNode); + completeChildren = completeChildren.updateImmediateChild(childName, node); + }); + // Add any complete children we have from the set + merge.getCompleteChildren().forEach(function(namedNode) { + completeChildren = completeChildren.updateImmediateChild(namedNode.name, namedNode.node); + }); + return completeChildren; + } else { + // We don't have anything to layer on top of. Layer on any children we have + // Note that we can return an empty snap if we have a defined delete + merge = this.visibleWrites_.childCompoundWrite(treePath); + merge.getCompleteChildren().forEach(function(namedNode) { + completeChildren = completeChildren.updateImmediateChild(namedNode.name, namedNode.node); + }); + return completeChildren; + } + }; + + /** + * Given that the underlying server data has updated, determine what, if anything, needs to be + * applied to the event cache. + * + * Possibilities: + * + * 1. No writes are shadowing. Events should be raised, the snap to be applied comes from the server data + * + * 2. Some write is completely shadowing. No events to be raised + * + * 3. Is partially shadowed. Events + * + * Either existingEventSnap or existingServerSnap must exist + * + * @param {!Path} treePath + * @param {!Path} childPath + * @param {?Node} existingEventSnap + * @param {?Node} existingServerSnap + * @return {?Node} + */ + calcEventCacheAfterServerOverwrite(treePath, childPath, existingEventSnap, + existingServerSnap) { + assert(existingEventSnap || existingServerSnap, + 'Either existingEventSnap or existingServerSnap must exist'); + var path = treePath.child(childPath); + if (this.visibleWrites_.hasCompleteWrite(path)) { + // At this point we can probably guarantee that we're in case 2, meaning no events + // May need to check visibility while doing the findRootMostValueAndPath call + return null; + } else { + // No complete shadowing. We're either partially shadowing or not shadowing at all. + var childMerge = this.visibleWrites_.childCompoundWrite(path); + if (childMerge.isEmpty()) { + // We're not shadowing at all. Case 1 + return existingServerSnap.getChild(childPath); + } else { + // This could be more efficient if the serverNode + updates doesn't change the eventSnap + // However this is tricky to find out, since user updates don't necessary change the server + // snap, e.g. priority updates on empty nodes, or deep deletes. Another special case is if the server + // adds nodes, but doesn't change any existing writes. It is therefore not enough to + // only check if the updates change the serverNode. + // Maybe check if the merge tree contains these special cases and only do a full overwrite in that case? + return childMerge.apply(existingServerSnap.getChild(childPath)); + } + } + }; + + /** + * Returns a complete child for a given server snap after applying all user writes or null if there is no + * complete child for this ChildKey. + * + * @param {!Path} treePath + * @param {!string} childKey + * @param {!CacheNode} existingServerSnap + * @return {?Node} + */ + calcCompleteChild(treePath, childKey, existingServerSnap) { + var path = treePath.child(childKey); + var shadowingNode = this.visibleWrites_.getCompleteNode(path); + if (shadowingNode != null) { + return shadowingNode; + } else { + if (existingServerSnap.isCompleteForChild(childKey)) { + var childMerge = this.visibleWrites_.childCompoundWrite(path); + return childMerge.apply(existingServerSnap.getNode().getImmediateChild(childKey)); + } else { + return null; + } + } + }; + + /** + * Returns a node if there is a complete overwrite for this path. More specifically, if there is a write at + * a higher path, this will return the child of that write relative to the write and this path. + * Returns null if there is no write at this path. + * + * @param {!Path} path + * @return {?Node} + */ + shadowingWrite(path) { + return this.visibleWrites_.getCompleteNode(path); + }; + + /** + * This method is used when processing child remove events on a query. If we can, we pull in children that were outside + * the window, but may now be in the window. + * + * @param {!Path} treePath + * @param {?Node} completeServerData + * @param {!NamedNode} startPost + * @param {!number} count + * @param {boolean} reverse + * @param {!Index} index + * @return {!Array.} + */ + calcIndexedSlice(treePath, completeServerData, startPost, count, reverse, + index) { + var toIterate; + var merge = this.visibleWrites_.childCompoundWrite(treePath); + var shadowingNode = merge.getCompleteNode(Path.Empty); + if (shadowingNode != null) { + toIterate = shadowingNode; + } else if (completeServerData != null) { + toIterate = merge.apply(completeServerData); + } else { + // no children to iterate on + return []; + } + toIterate = toIterate.withIndex(index); + if (!toIterate.isEmpty() && !toIterate.isLeafNode()) { + var nodes = []; + var cmp = index.getCompare(); + var iter = reverse ? toIterate.getReverseIteratorFrom(startPost, index) : + toIterate.getIteratorFrom(startPost, index); + var next = iter.getNext(); + while (next && nodes.length < count) { + if (cmp(next, startPost) !== 0) { + nodes.push(next); + } + next = iter.getNext(); + } + return nodes; + } else { + return []; + } + }; + + /** + * @param {!WriteRecord} writeRecord + * @param {!Path} path + * @return {boolean} + * @private + */ + recordContainsPath_(writeRecord, path) { + if (writeRecord.snap) { + return writeRecord.path.contains(path); + } else { + // findKey can return undefined, so use !! to coerce to boolean + return !!findKey(writeRecord.children, function(childSnap, childName) { + return writeRecord.path.child(childName).contains(path); + }); + } + }; + + /** + * Re-layer the writes and merges into a tree so we can efficiently calculate event snapshots + * @private + */ + resetTree_() { + this.visibleWrites_ = WriteTree.layerTree_(this.allWrites_, WriteTree.DefaultFilter_, + Path.Empty); + if (this.allWrites_.length > 0) { + this.lastWriteId_ = this.allWrites_[this.allWrites_.length - 1].writeId; + } else { + this.lastWriteId_ = -1; + } + }; + + /** + * The default filter used when constructing the tree. Keep everything that's visible. + * + * @param {!WriteRecord} write + * @return {boolean} + * @private + * @const + */ + static DefaultFilter_ = function(write) { return write.visible; }; + + /** + * Static method. Given an array of WriteRecords, a filter for which ones to include, and a path, construct the tree of + * event data at that path. + * + * @param {!Array.} writes + * @param {!function(!WriteRecord):boolean} filter + * @param {!Path} treeRoot + * @return {!CompoundWrite} + * @private + */ + static layerTree_ = function(writes, filter, treeRoot) { + var compoundWrite = CompoundWrite.Empty; + for (var i = 0; i < writes.length; ++i) { + var write = writes[i]; + // Theory, a later set will either: + // a) abort a relevant transaction, so no need to worry about excluding it from calculating that transaction + // b) not be relevant to a transaction (separate branch), so again will not affect the data for that transaction + if (filter(write)) { + var writePath = write.path; + var relativePath; + if (write.snap) { + if (treeRoot.contains(writePath)) { + relativePath = Path.relativePath(treeRoot, writePath); + compoundWrite = compoundWrite.addWrite(relativePath, write.snap); + } else if (writePath.contains(treeRoot)) { + relativePath = Path.relativePath(writePath, treeRoot); + compoundWrite = compoundWrite.addWrite(Path.Empty, write.snap.getChild(relativePath)); + } else { + // There is no overlap between root path and write path, ignore write + } + } else if (write.children) { + if (treeRoot.contains(writePath)) { + relativePath = Path.relativePath(treeRoot, writePath); + compoundWrite = compoundWrite.addWrites(relativePath, write.children); + } else if (writePath.contains(treeRoot)) { + relativePath = Path.relativePath(writePath, treeRoot); + if (relativePath.isEmpty()) { + compoundWrite = compoundWrite.addWrites(Path.Empty, write.children); + } else { + var child = safeGet(write.children, relativePath.getFront()); + if (child) { + // There exists a child in this node that matches the root path + var deepNode = child.getChild(relativePath.popFront()); + compoundWrite = compoundWrite.addWrite(Path.Empty, deepNode); + } + } + } else { + // There is no overlap between root path and write path, ignore write + } + } else { + throw assertionError('WriteRecord should have .snap or .children'); + } + } + } + return compoundWrite; + }; +} + +/** + * A WriteTreeRef wraps a WriteTree and a path, for convenient access to a particular subtree. All of the methods + * just proxy to the underlying WriteTree. + * + * @param {!Path} path + * @param {!WriteTree} writeTree + * @constructor + */ +export class WriteTreeRef { + /** + * The path to this particular write tree ref. Used for calling methods on writeTree_ while exposing a simpler + * interface to callers. + * + * @type {!Path} + * @private + * @const + */ + treePath_; + + /** + * * A reference to the actual tree of write data. All methods are pass-through to the tree, but with the appropriate + * path prefixed. + * + * This lets us make cheap references to points in the tree for sync points without having to copy and maintain all of + * the data. + * + * @type {!WriteTree} + * @private + * @const + */ + writeTree_; + + constructor(path, writeTree) { + this.treePath_ = path; + this.writeTree_ = writeTree; + }; + /** + * If possible, returns a complete event cache, using the underlying server data if possible. In addition, can be used + * to get a cache that includes hidden writes, and excludes arbitrary writes. Note that customizing the returned node + * can lead to a more expensive calculation. + * + * @param {?Node} completeServerCache + * @param {Array.=} writeIdsToExclude Optional writes to exclude. + * @param {boolean=} includeHiddenWrites Defaults to false, whether or not to layer on writes with visible set to false + * @return {?Node} + */ + calcCompleteEventCache(completeServerCache, writeIdsToExclude, + includeHiddenWrites) { + return this.writeTree_.calcCompleteEventCache(this.treePath_, completeServerCache, writeIdsToExclude, + includeHiddenWrites); + }; + + /** + * If possible, returns a children node containing all of the complete children we have data for. The returned data is a + * mix of the given server data and write data. + * + * @param {?ChildrenNode} completeServerChildren + * @return {!ChildrenNode} + */ + calcCompleteEventChildren(completeServerChildren) { + return this.writeTree_.calcCompleteEventChildren(this.treePath_, completeServerChildren); + }; + + /** + * Given that either the underlying server data has updated or the outstanding writes have updated, determine what, + * if anything, needs to be applied to the event cache. + * + * Possibilities: + * + * 1. No writes are shadowing. Events should be raised, the snap to be applied comes from the server data + * + * 2. Some write is completely shadowing. No events to be raised + * + * 3. Is partially shadowed. Events should be raised + * + * Either existingEventSnap or existingServerSnap must exist, this is validated via an assert + * + * @param {!Path} path + * @param {?Node} existingEventSnap + * @param {?Node} existingServerSnap + * @return {?Node} + */ + calcEventCacheAfterServerOverwrite(path, existingEventSnap, existingServerSnap) { + return this.writeTree_.calcEventCacheAfterServerOverwrite(this.treePath_, path, existingEventSnap, existingServerSnap); + }; + + /** + * Returns a node if there is a complete overwrite for this path. More specifically, if there is a write at + * a higher path, this will return the child of that write relative to the write and this path. + * Returns null if there is no write at this path. + * + * @param {!Path} path + * @return {?Node} + */ + shadowingWrite(path) { + return this.writeTree_.shadowingWrite(this.treePath_.child(path)); + }; + + /** + * This method is used when processing child remove events on a query. If we can, we pull in children that were outside + * the window, but may now be in the window + * + * @param {?Node} completeServerData + * @param {!NamedNode} startPost + * @param {!number} count + * @param {boolean} reverse + * @param {!Index} index + * @return {!Array.} + */ + calcIndexedSlice(completeServerData, startPost, count, reverse, index) { + return this.writeTree_.calcIndexedSlice(this.treePath_, completeServerData, startPost, count, reverse, index); + }; + + /** + * Returns a complete child for a given server snap after applying all user writes or null if there is no + * complete child for this ChildKey. + * + * @param {!string} childKey + * @param {!CacheNode} existingServerCache + * @return {?Node} + */ + calcCompleteChild(childKey, existingServerCache) { + return this.writeTree_.calcCompleteChild(this.treePath_, childKey, existingServerCache); + }; + + /** + * Return a WriteTreeRef for a child. + * + * @param {string} childName + * @return {!WriteTreeRef} + */ + child(childName) { + return new WriteTreeRef(this.treePath_.child(childName), this.writeTree_); + }; +} diff --git a/src/database/core/operation/AckUserWrite.ts b/src/database/core/operation/AckUserWrite.ts new file mode 100644 index 00000000000..cc7da8cde60 --- /dev/null +++ b/src/database/core/operation/AckUserWrite.ts @@ -0,0 +1,42 @@ +import { assert } from "../../../utils/assert"; +import { Path } from "../util/Path"; +import { Operation, OperationSource, OperationType } from './Operation'; +import { ImmutableTree } from '../util/ImmutableTree'; + +export class AckUserWrite implements Operation { + /** @inheritDoc */ + type = OperationType.ACK_USER_WRITE; + + /** @inheritDoc */ + source = OperationSource.User; + + /** + * + * @param {!Path} path + * @param {!ImmutableTree} affectedTree A tree containing true for each affected path. Affected paths can't overlap. + * @param {!boolean} revert + */ + constructor(/**@inheritDoc */ public path: Path, + /**@inheritDoc */ public affectedTree: ImmutableTree, + /**@inheritDoc */ public revert: boolean) { + + } + + /** + * @inheritDoc + */ + operationForChild(childName: string): AckUserWrite { + if (!this.path.isEmpty()) { + assert(this.path.getFront() === childName, 'operationForChild called for unrelated child.'); + return new AckUserWrite(this.path.popFront(), this.affectedTree, this.revert); + } else if (this.affectedTree.value != null) { + assert(this.affectedTree.children.isEmpty(), + 'affectedTree should not have overlapping affected paths.'); + // All child locations are affected as well; just return same operation. + return this; + } else { + const childTree = this.affectedTree.subtree(new Path(childName)); + return new AckUserWrite(Path.Empty, childTree, this.revert); + } + } +} \ No newline at end of file diff --git a/src/database/core/operation/ListenComplete.ts b/src/database/core/operation/ListenComplete.ts new file mode 100644 index 00000000000..0a9ab05858f --- /dev/null +++ b/src/database/core/operation/ListenComplete.ts @@ -0,0 +1,24 @@ +import { Path } from "../util/Path"; +import { Operation, OperationSource, OperationType } from './Operation'; + +/** + * @param {!OperationSource} source + * @param {!Path} path + * @constructor + * @implements {Operation} + */ +export class ListenComplete implements Operation { + /** @inheritDoc */ + type = OperationType.LISTEN_COMPLETE; + + constructor(public source: OperationSource, public path: Path) { + } + + operationForChild(childName: string): ListenComplete { + if (this.path.isEmpty()) { + return new ListenComplete(this.source, Path.Empty); + } else { + return new ListenComplete(this.source, this.path.popFront()); + } + } +} diff --git a/src/database/core/operation/Merge.ts b/src/database/core/operation/Merge.ts new file mode 100644 index 00000000000..9d1578a6785 --- /dev/null +++ b/src/database/core/operation/Merge.ts @@ -0,0 +1,52 @@ +import { Operation, OperationSource, OperationType } from './Operation'; +import { Overwrite } from "./Overwrite"; +import { Path } from "../util/Path"; +import { assert } from "../../../utils/assert"; +import { ImmutableTree } from '../util/ImmutableTree'; + +/** + * @param {!OperationSource} source + * @param {!Path} path + * @param {!ImmutableTree.} children + * @constructor + * @implements {Operation} + */ +export class Merge implements Operation { + /** @inheritDoc */ + type = OperationType.MERGE; + + constructor(/**@inheritDoc */ public source: OperationSource, + /**@inheritDoc */ public path: Path, + /**@inheritDoc */ public children: ImmutableTree) { + } + + /** + * @inheritDoc + */ + operationForChild(childName: string): Operation { + if (this.path.isEmpty()) { + const childTree = this.children.subtree(new Path(childName)); + if (childTree.isEmpty()) { + // This child is unaffected + return null; + } else if (childTree.value) { + // We have a snapshot for the child in question. This becomes an overwrite of the child. + return new Overwrite(this.source, Path.Empty, childTree.value); + } else { + // This is a merge at a deeper level + return new Merge(this.source, Path.Empty, childTree); + } + } else { + assert(this.path.getFront() === childName, + 'Can\'t get a merge for a child not on the path of the operation'); + return new Merge(this.source, this.path.popFront(), this.children); + } + } + + /** + * @inheritDoc + */ + toString(): string { + return 'Operation(' + this.path + ': ' + this.source.toString() + ' merge: ' + this.children.toString() + ')'; + } +} \ No newline at end of file diff --git a/src/database/core/operation/Operation.ts b/src/database/core/operation/Operation.ts new file mode 100644 index 00000000000..090763b634c --- /dev/null +++ b/src/database/core/operation/Operation.ts @@ -0,0 +1,74 @@ +import { assert } from "../../../utils/assert"; +import { Path } from '../util/Path'; + +/** + * + * @enum + */ +export enum OperationType { + OVERWRITE, + MERGE, + ACK_USER_WRITE, + LISTEN_COMPLETE +} + +/** + * @interface + */ +export interface Operation { + /** + * @type {!OperationSource} + */ + source: OperationSource; + + /** + * @type {!OperationType} + */ + type: OperationType; + + /** + * @type {!Path} + */ + path: Path; + + /** + * @param {string} childName + * @return {?Operation} + */ + operationForChild(childName: string): Operation | null; +} + +/** + * @param {boolean} fromUser + * @param {boolean} fromServer + * @param {?string} queryId + * @param {boolean} tagged + * @constructor + */ +export class OperationSource { + constructor(public fromUser: boolean, + public fromServer: boolean, + public queryId: string | null, + public tagged: boolean) { + assert(!tagged || fromServer, 'Tagged queries must be from server.'); + } + /** + * @const + * @type {!OperationSource} + */ + static User = new OperationSource(/*fromUser=*/true, false, null, /*tagged=*/false); + + /** + * @const + * @type {!OperationSource} + */ + static Server = new OperationSource(false, /*fromServer=*/true, null, /*tagged=*/false); + + /** + * @param {string} queryId + * @return {!OperationSource} + */ + static forServerTaggedQuery = function(queryId) { + return new OperationSource(false, /*fromServer=*/true, queryId, /*tagged=*/true); + }; +} \ No newline at end of file diff --git a/src/database/core/operation/Overwrite.ts b/src/database/core/operation/Overwrite.ts new file mode 100644 index 00000000000..1af32ce1d26 --- /dev/null +++ b/src/database/core/operation/Overwrite.ts @@ -0,0 +1,29 @@ +import { Operation, OperationSource, OperationType } from './Operation'; +import { Path } from "../util/Path"; +import { Node } from '../snap/Node'; + +/** + * @param {!OperationSource} source + * @param {!Path} path + * @param {!Node} snap + * @constructor + * @implements {Operation} + */ +export class Overwrite implements Operation { + /** @inheritDoc */ + type = OperationType.OVERWRITE; + + constructor(public source: OperationSource, + public path: Path, + public snap: Node) { + } + + operationForChild(childName: string): Overwrite { + if (this.path.isEmpty()) { + return new Overwrite(this.source, Path.Empty, + this.snap.getImmediateChild(childName)); + } else { + return new Overwrite(this.source, this.path.popFront(), this.snap); + } + } +} \ No newline at end of file diff --git a/src/database/core/snap/ChildrenNode.ts b/src/database/core/snap/ChildrenNode.ts new file mode 100644 index 00000000000..18e8e79b27a --- /dev/null +++ b/src/database/core/snap/ChildrenNode.ts @@ -0,0 +1,539 @@ +import { assert } from "../../../utils/assert"; +import { + sha1, + MAX_NAME, + MIN_NAME +} from "../util/util"; +import { SortedMap } from "../util/SortedMap"; +import { Node, NamedNode } from "./Node"; +import { + validatePriorityNode, + priorityHashText, + setMaxNode +} from "./snap"; +import { PRIORITY_INDEX, setMaxNode as setPriorityMaxNode } from "./indexes/PriorityIndex"; +import { KEY_INDEX, KeyIndex } from "./indexes/KeyIndex"; +import { IndexMap } from "./IndexMap"; +import { LeafNode } from "./LeafNode"; +import { NAME_COMPARATOR } from "./comparators"; +import "./indexes/Index"; + +// TODO: For memory savings, don't store priorityNode_ if it's empty. + +let EMPTY_NODE; + +/** + * ChildrenNode is a class for storing internal nodes in a DataSnapshot + * (i.e. nodes with children). It implements Node and stores the + * list of children in the children property, sorted by child name. + * + * @constructor + * @implements {Node} + * @param {!SortedMap.} children List of children + * of this node.. + * @param {?Node} priorityNode The priority of this node (as a snapshot node). + * @param {!IndexMap} indexMap + */ +export class ChildrenNode implements Node { + children_; + priorityNode_; + indexMap_; + lazyHash_; + + static get EMPTY_NODE() { + return EMPTY_NODE || (EMPTY_NODE = new ChildrenNode(new SortedMap(NAME_COMPARATOR), null, IndexMap.Default)); + } + + constructor(children, priorityNode, indexMap) { + /** + * @private + * @const + * @type {!SortedMap.} + */ + this.children_ = children; + + /** + * Note: The only reason we allow null priority is to for EMPTY_NODE, since we can't use + * EMPTY_NODE as the priority of EMPTY_NODE. We might want to consider making EMPTY_NODE its own + * class instead of an empty ChildrenNode. + * + * @private + * @const + * @type {?Node} + */ + this.priorityNode_ = priorityNode; + if (this.priorityNode_) { + validatePriorityNode(this.priorityNode_); + } + + if (children.isEmpty()) { + assert(!this.priorityNode_ || this.priorityNode_.isEmpty(), 'An empty node cannot have a priority'); + } + + /** + * + * @type {!IndexMap} + * @private + */ + this.indexMap_ = indexMap; + + /** + * + * @type {?string} + * @private + */ + this.lazyHash_ = null; + }; + + /** @inheritDoc */ + isLeafNode() { + return false; + }; + + /** @inheritDoc */ + getPriority() { + return this.priorityNode_ || EMPTY_NODE; + }; + + /** @inheritDoc */ + updatePriority(newPriorityNode) { + if (this.children_.isEmpty()) { + // Don't allow priorities on empty nodes + return this; + } else { + return new ChildrenNode(this.children_, newPriorityNode, this.indexMap_); + } + }; + + /** @inheritDoc */ + getImmediateChild(childName) { + // Hack to treat priority as a regular child + if (childName === '.priority') { + return this.getPriority(); + } else { + var child = this.children_.get(childName); + return child === null ? EMPTY_NODE : child; + } + }; + + /** @inheritDoc */ + getChild(path) { + var front = path.getFront(); + if (front === null) + return this; + + return this.getImmediateChild(front).getChild(path.popFront()); + }; + + /** @inheritDoc */ + hasChild(childName) { + return this.children_.get(childName) !== null; + }; + + /** @inheritDoc */ + updateImmediateChild(childName, newChildNode) { + assert(newChildNode, 'We should always be passing snapshot nodes'); + if (childName === '.priority') { + return this.updatePriority(newChildNode); + } else { + var namedNode = new NamedNode(childName, newChildNode); + var newChildren, newIndexMap, newPriority; + if (newChildNode.isEmpty()) { + newChildren = this.children_.remove(childName); + newIndexMap = this.indexMap_.removeFromIndexes(namedNode, this.children_ + ); + } else { + newChildren = this.children_.insert(childName, newChildNode); + newIndexMap = this.indexMap_.addToIndexes(namedNode, this.children_); + } + + newPriority = newChildren.isEmpty() ? EMPTY_NODE : this.priorityNode_; + return new ChildrenNode(newChildren, newPriority, newIndexMap); + } + }; + + /** @inheritDoc */ + updateChild(path, newChildNode) { + var front = path.getFront(); + if (front === null) { + return newChildNode; + } else { + assert(path.getFront() !== '.priority' || path.getLength() === 1, + '.priority must be the last token in a path'); + var newImmediateChild = this.getImmediateChild(front). + updateChild(path.popFront(), newChildNode); + return this.updateImmediateChild(front, newImmediateChild); + } + }; + + /** @inheritDoc */ + isEmpty() { + return this.children_.isEmpty(); + }; + + /** @inheritDoc */ + numChildren() { + return this.children_.count(); + }; + + /** + * @private + * @type {RegExp} + */ + static INTEGER_REGEXP_ = /^(0|[1-9]\d*)$/; + + /** @inheritDoc */ + val(opt_exportFormat) { + if (this.isEmpty()) + return null; + + var obj = { }; + var numKeys = 0, maxKey = 0, allIntegerKeys = true; + this.forEachChild(PRIORITY_INDEX, function(key, childNode) { + obj[key] = childNode.val(opt_exportFormat); + + numKeys++; + if (allIntegerKeys && ChildrenNode.INTEGER_REGEXP_.test(key)) { + maxKey = Math.max(maxKey, Number(key)); + } else { + allIntegerKeys = false; + } + }); + + if (!opt_exportFormat && allIntegerKeys && maxKey < 2 * numKeys) { + // convert to array. + var array = []; + for (var key in obj) + array[key] = obj[key]; + + return array; + } else { + if (opt_exportFormat && !this.getPriority().isEmpty()) { + obj['.priority'] = this.getPriority().val(); + } + return obj; + } + }; + + + /** @inheritDoc */ + hash() { + if (this.lazyHash_ === null) { + var toHash = ''; + if (!this.getPriority().isEmpty()) + toHash += 'priority:' + priorityHashText( + /**@type {(!string|!number)} */ (this.getPriority().val())) + ':'; + + this.forEachChild(PRIORITY_INDEX, function(key, childNode) { + var childHash = childNode.hash(); + if (childHash !== '') + toHash += ':' + key + ':' + childHash; + }); + + this.lazyHash_ = (toHash === '') ? '' : sha1(toHash); + } + return this.lazyHash_; + }; + + + /** @inheritDoc */ + getPredecessorChildName(childName, childNode, index) { + var idx = this.resolveIndex_(index); + if (idx) { + var predecessor = idx.getPredecessorKey(new NamedNode(childName, childNode)); + return predecessor ? predecessor.name : null; + } else { + return this.children_.getPredecessorKey(childName); + } + }; + + /** + * @param {!fb.core.snap.Index} indexDefinition + * @return {?string} + */ + getFirstChildName(indexDefinition) { + var idx = this.resolveIndex_(indexDefinition); + if (idx) { + var minKey = idx.minKey(); + return minKey && minKey.name; + } else { + return this.children_.minKey(); + } + }; + + /** + * @param {!fb.core.snap.Index} indexDefinition + * @return {?NamedNode} + */ + getFirstChild(indexDefinition) { + var minKey = this.getFirstChildName(indexDefinition); + if (minKey) { + return new NamedNode(minKey, this.children_.get(minKey)); + } else { + return null; + } + }; + + /** + * Given an index, return the key name of the largest value we have, according to that index + * @param {!fb.core.snap.Index} indexDefinition + * @return {?string} + */ + getLastChildName(indexDefinition) { + var idx = this.resolveIndex_(indexDefinition); + if (idx) { + var maxKey = idx.maxKey(); + return maxKey && maxKey.name; + } else { + return this.children_.maxKey(); + } + }; + + /** + * @param {!fb.core.snap.Index} indexDefinition + * @return {?NamedNode} + */ + getLastChild(indexDefinition) { + var maxKey = this.getLastChildName(indexDefinition); + if (maxKey) { + return new NamedNode(maxKey, this.children_.get(maxKey)); + } else { + return null; + } + }; + + + /** + * @inheritDoc + */ + forEachChild(index, action) { + var idx = this.resolveIndex_(index); + if (idx) { + return idx.inorderTraversal(function(wrappedNode) { + return action(wrappedNode.name, wrappedNode.node); + }); + } else { + return this.children_.inorderTraversal(action); + } + }; + + /** + * @param {!fb.core.snap.Index} indexDefinition + * @return {SortedMapIterator} + */ + getIterator(indexDefinition) { + return this.getIteratorFrom(indexDefinition.minPost(), indexDefinition); + }; + + /** + * + * @param {!NamedNode} startPost + * @param {!fb.core.snap.Index} indexDefinition + * @return {!SortedMapIterator} + */ + getIteratorFrom(startPost, indexDefinition) { + var idx = this.resolveIndex_(indexDefinition); + if (idx) { + return idx.getIteratorFrom(startPost, function(key) { return key; }); + } else { + var iterator = this.children_.getIteratorFrom(startPost.name, NamedNode.Wrap); + var next = iterator.peek(); + while (next != null && indexDefinition.compare(next, startPost) < 0) { + iterator.getNext(); + next = iterator.peek(); + } + return iterator; + } + }; + + /** + * @param {!fb.core.snap.Index} indexDefinition + * @return {!SortedMapIterator} + */ + getReverseIterator(indexDefinition) { + return this.getReverseIteratorFrom(indexDefinition.maxPost(), indexDefinition); + }; + + /** + * @param {!NamedNode} endPost + * @param {!fb.core.snap.Index} indexDefinition + * @return {!SortedMapIterator} + */ + getReverseIteratorFrom(endPost, indexDefinition) { + var idx = this.resolveIndex_(indexDefinition); + if (idx) { + return idx.getReverseIteratorFrom(endPost, function(key) { return key; }); + } else { + var iterator = this.children_.getReverseIteratorFrom(endPost.name, NamedNode.Wrap); + var next = iterator.peek(); + while (next != null && indexDefinition.compare(next, endPost) > 0) { + iterator.getNext(); + next = iterator.peek(); + } + return iterator; + } + }; + + /** + * @inheritDoc + */ + compareTo(other) { + if (this.isEmpty()) { + if (other.isEmpty()) { + return 0; + } else { + return -1; + } + } else if (other.isLeafNode() || other.isEmpty()) { + return 1; + } else if (other === MAX_NODE) { + return -1; + } else { + // Must be another node with children. + return 0; + } + }; + + /** + * @inheritDoc + */ + withIndex(indexDefinition) { + if (indexDefinition === KEY_INDEX || this.indexMap_.hasIndex(indexDefinition)) { + return this; + } else { + var newIndexMap = this.indexMap_.addIndex(indexDefinition, this.children_); + return new ChildrenNode(this.children_, this.priorityNode_, newIndexMap); + } + }; + + /** + * @inheritDoc + */ + isIndexed(index) { + return index === KEY_INDEX || this.indexMap_.hasIndex(index); + }; + + /** + * @inheritDoc + */ + equals(other) { + if (other === this) { + return true; + } + else if (other.isLeafNode()) { + return false; + } else { + var otherChildrenNode = /** @type {!ChildrenNode} */ (other); + if (!this.getPriority().equals(otherChildrenNode.getPriority())) { + return false; + } else if (this.children_.count() === otherChildrenNode.children_.count()) { + var thisIter = this.getIterator(PRIORITY_INDEX); + var otherIter = otherChildrenNode.getIterator(PRIORITY_INDEX); + var thisCurrent = thisIter.getNext(); + var otherCurrent = otherIter.getNext(); + while (thisCurrent && otherCurrent) { + if (thisCurrent.name !== otherCurrent.name || !thisCurrent.node.equals(otherCurrent.node)) { + return false; + } + thisCurrent = thisIter.getNext(); + otherCurrent = otherIter.getNext(); + } + return thisCurrent === null && otherCurrent === null; + } else { + return false; + } + } + }; + + + /** + * Returns a SortedMap ordered by index, or null if the default (by-key) ordering can be used + * instead. + * + * @private + * @param {!fb.core.snap.Index} indexDefinition + * @return {?SortedMap.} + */ + resolveIndex_(indexDefinition) { + if (indexDefinition === KEY_INDEX) { + return null; + } else { + return this.indexMap_.get(indexDefinition.toString()); + } + }; + +} + +/** + * @constructor + * @extends {ChildrenNode} + * @private + */ +export class MaxNode extends ChildrenNode { + constructor() { + super(new SortedMap(NAME_COMPARATOR), ChildrenNode.EMPTY_NODE, IndexMap.Default); + } + + compareTo(other) { + if (other === this) { + return 0; + } else { + return 1; + } + }; + + + equals(other) { + // Not that we every compare it, but MAX_NODE is only ever equal to itself + return other === this; + }; + + + getPriority() { + return this; + }; + + + getImmediateChild(childName) { + return ChildrenNode.EMPTY_NODE; + }; + + + isEmpty() { + return false; + }; +} + +/** + * Marker that will sort higher than any other snapshot. + * @type {!MAX_NODE} + * @const + */ +export const MAX_NODE = new MaxNode(); + +/** + * Document NamedNode extensions + */ +declare module './Node' { + interface NamedNode { + MIN: NamedNode, + MAX: NamedNode + } +} + +Object.defineProperties(NamedNode, { + MIN: { + value: new NamedNode(MIN_NAME, ChildrenNode.EMPTY_NODE) + }, + MAX: { + value: new NamedNode(MAX_NAME, MAX_NODE) + } +}); + +/** + * Reference Extensions + */ +KeyIndex.__EMPTY_NODE = ChildrenNode.EMPTY_NODE; +LeafNode.__childrenNodeConstructor = ChildrenNode; +setMaxNode(MAX_NODE); +setPriorityMaxNode(MAX_NODE); \ No newline at end of file diff --git a/src/database/core/snap/IndexMap.ts b/src/database/core/snap/IndexMap.ts new file mode 100644 index 00000000000..9d5eb731d06 --- /dev/null +++ b/src/database/core/snap/IndexMap.ts @@ -0,0 +1,162 @@ +import { assert } from "../../../utils/assert"; +import { buildChildSet } from "./childSet"; +import { contains, clone, map, safeGet } from "../../../utils/obj"; +import { NamedNode } from "./Node"; +import { PRIORITY_INDEX } from "./indexes/PriorityIndex"; +import { KEY_INDEX } from "./indexes/KeyIndex"; +let _defaultIndexMap; + +const fallbackObject = {}; + +/** + * + * @param {Object.>} indexes + * @param {Object.} indexSet + * @constructor + */ +export class IndexMap { + indexes_; + indexSet_; + + /** + * The default IndexMap for nodes without a priority + * @type {!IndexMap} + * @const + */ + static get Default() { + assert(fallbackObject && PRIORITY_INDEX, 'ChildrenNode.ts has not been loaded'); + _defaultIndexMap = _defaultIndexMap || new IndexMap( + { '.priority': fallbackObject }, + { '.priority': PRIORITY_INDEX } + ); + return _defaultIndexMap; + } + + constructor(indexes, indexSet) { + this.indexes_ = indexes; + this.indexSet_ = indexSet; + } + /** + * + * @param {!string} indexKey + * @return {?SortedMap.} + */ + get(indexKey) { + var sortedMap = safeGet(this.indexes_, indexKey); + if (!sortedMap) throw new Error('No index defined for ' + indexKey); + + if (sortedMap === fallbackObject) { + // The index exists, but it falls back to just name comparison. Return null so that the calling code uses the + // regular child map + return null; + } else { + return sortedMap; + } + }; + + /** + * @param {!Index} indexDefinition + * @return {boolean} + */ + hasIndex(indexDefinition) { + return contains(this.indexSet_, indexDefinition.toString()); + }; + + /** + * @param {!Index} indexDefinition + * @param {!SortedMap.} existingChildren + * @return {!IndexMap} + */ + addIndex(indexDefinition, existingChildren) { + assert(indexDefinition !== KEY_INDEX, + "KeyIndex always exists and isn't meant to be added to the IndexMap."); + var childList = []; + var sawIndexedValue = false; + var iter = existingChildren.getIterator(NamedNode.Wrap); + var next = iter.getNext(); + while (next) { + sawIndexedValue = sawIndexedValue || indexDefinition.isDefinedOn(next.node); + childList.push(next); + next = iter.getNext(); + } + var newIndex; + if (sawIndexedValue) { + newIndex = buildChildSet(childList, indexDefinition.getCompare()); + } else { + newIndex = fallbackObject; + } + var indexName = indexDefinition.toString(); + var newIndexSet = clone(this.indexSet_); + newIndexSet[indexName] = indexDefinition; + var newIndexes = clone(this.indexes_); + newIndexes[indexName] = newIndex; + return new IndexMap(newIndexes, newIndexSet); + }; + + + /** + * Ensure that this node is properly tracked in any indexes that we're maintaining + * @param {!NamedNode} namedNode + * @param {!SortedMap.} existingChildren + * @return {!IndexMap} + */ + addToIndexes(namedNode, existingChildren) { + var self = this; + var newIndexes = map(this.indexes_, function(indexedChildren, indexName) { + var index = safeGet(self.indexSet_, indexName); + assert(index, 'Missing index implementation for ' + indexName); + if (indexedChildren === fallbackObject) { + // Check to see if we need to index everything + if (index.isDefinedOn(namedNode.node)) { + // We need to build this index + var childList = []; + var iter = existingChildren.getIterator(NamedNode.Wrap); + var next = iter.getNext(); + while (next) { + if (next.name != namedNode.name) { + childList.push(next); + } + next = iter.getNext(); + } + childList.push(namedNode); + return buildChildSet(childList, index.getCompare()); + } else { + // No change, this remains a fallback + return fallbackObject; + } + } else { + var existingSnap = existingChildren.get(namedNode.name); + var newChildren = indexedChildren; + if (existingSnap) { + newChildren = newChildren.remove(new NamedNode(namedNode.name, existingSnap)); + } + return newChildren.insert(namedNode, namedNode.node); + } + }); + return new IndexMap(newIndexes, this.indexSet_); + }; + + /** + * Create a new IndexMap instance with the given value removed + * @param {!NamedNode} namedNode + * @param {!SortedMap.} existingChildren + * @return {!IndexMap} + */ + removeFromIndexes(namedNode, existingChildren) { + var newIndexes = map(this.indexes_, function(indexedChildren) { + if (indexedChildren === fallbackObject) { + // This is the fallback. Just return it, nothing to do in this case + return indexedChildren; + } else { + var existingSnap = existingChildren.get(namedNode.name); + if (existingSnap) { + return indexedChildren.remove(new NamedNode(namedNode.name, existingSnap)); + } else { + // No record of this child + return indexedChildren; + } + } + }); + return new IndexMap(newIndexes, this.indexSet_); + }; +} diff --git a/src/database/core/snap/LeafNode.ts b/src/database/core/snap/LeafNode.ts new file mode 100644 index 00000000000..47adae5d179 --- /dev/null +++ b/src/database/core/snap/LeafNode.ts @@ -0,0 +1,271 @@ +import { assert } from '../../../utils/assert' +import { + doubleToIEEE754String, + sha1 +} from "../util/util"; +import { + priorityHashText, + validatePriorityNode +} from "./snap"; +import { Node } from "./Node"; + +let __childrenNodeConstructor; + +/** + * LeafNode is a class for storing leaf nodes in a DataSnapshot. It + * implements Node and stores the value of the node (a string, + * number, or boolean) accessible via getValue(). + */ +export class LeafNode implements Node { + static set __childrenNodeConstructor(val) { + __childrenNodeConstructor = val; + } + static get __childrenNodeConstructor() { + return __childrenNodeConstructor; + } + /** + * The sort order for comparing leaf nodes of different types. If two leaf nodes have + * the same type, the comparison falls back to their value + * @type {Array.} + * @const + */ + static VALUE_TYPE_ORDER = ['object', 'boolean', 'number', 'string']; + + value_; + priorityNode_; + lazyHash_; + /** + * @implements {Node} + * @param {!(string|number|boolean|Object)} value The value to store in this leaf node. + * The object type is possible in the event of a deferred value + * @param {!Node=} opt_priorityNode The priority of this node. + */ + constructor(value, opt_priorityNode?) { + /** + * @private + * @const + * @type {!(string|number|boolean|Object)} + */ + this.value_ = value; + assert(this.value_ !== undefined && this.value_ !== null, + "LeafNode shouldn't be created with null/undefined value."); + + /** + * @private + * @const + * @type {!Node} + */ + this.priorityNode_ = opt_priorityNode || LeafNode.__childrenNodeConstructor.EMPTY_NODE; + validatePriorityNode(this.priorityNode_); + + this.lazyHash_ = null; + } + + /** @inheritDoc */ + isLeafNode() { + return true; + } + + /** @inheritDoc */ + getPriority() { + return this.priorityNode_; + } + + /** @inheritDoc */ + updatePriority(newPriorityNode) { + return new LeafNode(this.value_, newPriorityNode); + } + + /** @inheritDoc */ + getImmediateChild(childName) { + // Hack to treat priority as a regular child + if (childName === '.priority') { + return this.priorityNode_; + } else { + return LeafNode.__childrenNodeConstructor.EMPTY_NODE; + } + } + + /** @inheritDoc */ + getChild(path) { + if (path.isEmpty()) { + return this; + } else if (path.getFront() === '.priority') { + return this.priorityNode_; + } else { + return LeafNode.__childrenNodeConstructor.EMPTY_NODE; + } + } + + /** + * @inheritDoc + */ + hasChild() { + return false; + } + + /** @inheritDoc */ + getPredecessorChildName(childName, childNode) { + return null; + } + + /** @inheritDoc */ + updateImmediateChild(childName, newChildNode) { + if (childName === '.priority') { + return this.updatePriority(newChildNode); + } else if (newChildNode.isEmpty() && childName !== '.priority') { + return this; + } else { + return LeafNode.__childrenNodeConstructor.EMPTY_NODE + .updateImmediateChild(childName, newChildNode) + .updatePriority(this.priorityNode_); + } + } + + /** @inheritDoc */ + updateChild(path, newChildNode) { + var front = path.getFront(); + if (front === null) { + return newChildNode; + } else if (newChildNode.isEmpty() && front !== '.priority') { + return this; + } else { + assert(front !== '.priority' || path.getLength() === 1, + '.priority must be the last token in a path'); + + return this.updateImmediateChild(front, LeafNode.__childrenNodeConstructor.EMPTY_NODE.updateChild(path.popFront(), newChildNode)); + } + } + + /** @inheritDoc */ + isEmpty() { + return false; + } + + /** @inheritDoc */ + numChildren() { + return 0; + } + + /** @inheritDoc */ + forEachChild(index, action) { + return false; + } + + /** + * @inheritDoc + */ + val(opt_exportFormat) { + if (opt_exportFormat && !this.getPriority().isEmpty()) + return { '.value': this.getValue(), '.priority' : this.getPriority().val() }; + else + return this.getValue(); + } + + /** @inheritDoc */ + hash() { + if (this.lazyHash_ === null) { + var toHash = ''; + if (!this.priorityNode_.isEmpty()) + toHash += 'priority:' + priorityHashText( + /** @type {(number|string)} */ (this.priorityNode_.val())) + ':'; + + var type = typeof this.value_; + toHash += type + ':'; + if (type === 'number') { + toHash += doubleToIEEE754String(/** @type {number} */ (this.value_)); + } else { + toHash += this.value_; + } + this.lazyHash_ = sha1(toHash); + } + return /**@type {!string} */ (this.lazyHash_); + } + + /** + * Returns the value of the leaf node. + * @return {Object|string|number|boolean} The value of the node. + */ + getValue() { + return this.value_; + } + + /** + * @inheritDoc + */ + compareTo(other) { + if (other === LeafNode.__childrenNodeConstructor.EMPTY_NODE) { + return 1; + } else if (other instanceof LeafNode.__childrenNodeConstructor) { + return -1; + } else { + assert(other.isLeafNode(), 'Unknown node type'); + return this.compareToLeafNode_(/** @type {!LeafNode} */ (other)); + } + } + + /** + * Comparison specifically for two leaf nodes + * @param {!LeafNode} otherLeaf + * @return {!number} + * @private + */ + compareToLeafNode_(otherLeaf) { + var otherLeafType = typeof otherLeaf.value_; + var thisLeafType = typeof this.value_; + var otherIndex = LeafNode.VALUE_TYPE_ORDER.indexOf(otherLeafType); + var thisIndex = LeafNode.VALUE_TYPE_ORDER.indexOf(thisLeafType); + assert(otherIndex >= 0, 'Unknown leaf type: ' + otherLeafType); + assert(thisIndex >= 0, 'Unknown leaf type: ' + thisLeafType); + if (otherIndex === thisIndex) { + // Same type, compare values + if (thisLeafType === 'object') { + // Deferred value nodes are all equal, but we should also never get to this point... + return 0; + } else { + // Note that this works because true > false, all others are number or string comparisons + if (this.value_ < otherLeaf.value_) { + return -1; + } else if (this.value_ === otherLeaf.value_) { + return 0; + } else { + return 1; + } + } + } else { + return thisIndex - otherIndex; + } + } + + /** + * @inheritDoc + */ + withIndex() { + return this; + } + + /** + * @inheritDoc + */ + isIndexed() { + return true; + } + + /** + * @inheritDoc + */ + equals(other) { + /** + * @inheritDoc + */ + if (other === this) { + return true; + } + else if (other.isLeafNode()) { + var otherLeaf = /** @type {!LeafNode} */ (other); + return this.value_ === otherLeaf.value_ && this.priorityNode_.equals(otherLeaf.priorityNode_); + } else { + return false; + } + } +}; // end LeafNode \ No newline at end of file diff --git a/src/database/core/snap/Node.ts b/src/database/core/snap/Node.ts new file mode 100644 index 00000000000..d6b40b5a090 --- /dev/null +++ b/src/database/core/snap/Node.ts @@ -0,0 +1,161 @@ +import { Path } from "../util/Path"; +import { Index } from "./indexes/Index"; + +/** + * Node is an interface defining the common functionality for nodes in + * a DataSnapshot. + * + * @interface + */ +export interface Node { + /** + * Whether this node is a leaf node. + * @return {boolean} Whether this is a leaf node. + */ + isLeafNode(): boolean; + + + /** + * Gets the priority of the node. + * @return {!Node} The priority of the node. + */ + getPriority(): Node; + + + /** + * Returns a duplicate node with the new priority. + * @param {!Node} newPriorityNode New priority to set for the node. + * @return {!Node} Node with new priority. + */ + updatePriority(newPriorityNode: Node): Node; + + + /** + * Returns the specified immediate child, or null if it doesn't exist. + * @param {string} childName The name of the child to retrieve. + * @return {!Node} The retrieved child, or an empty node. + */ + getImmediateChild(childName: string): Node; + + + /** + * Returns a child by path, or null if it doesn't exist. + * @param {!Path} path The path of the child to retrieve. + * @return {!Node} The retrieved child or an empty node. + */ + getChild(path: Path): Node; + + + /** + * Returns the name of the child immediately prior to the specified childNode, or null. + * @param {!string} childName The name of the child to find the predecessor of. + * @param {!Node} childNode The node to find the predecessor of. + * @param {!Index} index The index to use to determine the predecessor + * @return {?string} The name of the predecessor child, or null if childNode is the first child. + */ + getPredecessorChildName(childName: String, childNode: Node, index: Index): string; + + /** + * Returns a duplicate node, with the specified immediate child updated. + * Any value in the node will be removed. + * @param {string} childName The name of the child to update. + * @param {!Node} newChildNode The new child node + * @return {!Node} The updated node. + */ + updateImmediateChild(childName: string, newChildNode: Node): Node; + + + /** + * Returns a duplicate node, with the specified child updated. Any value will + * be removed. + * @param {!Path} path The path of the child to update. + * @param {!Node} newChildNode The new child node, which may be an empty node + * @return {!Node} The updated node. + */ + updateChild(path: Path, newChildNode: Node): Node; + + /** + * True if the immediate child specified exists + * @param {!string} childName + * @return {boolean} + */ + hasChild(childName: string): boolean; + + /** + * @return {boolean} True if this node has no value or children. + */ + isEmpty(): boolean; + + + /** + * @return {number} The number of children of this node. + */ + numChildren(): number; + + + /** + * Calls action for each child. + * @param {!Index} index + * @param {function(string, !Node)} action Action to be called for + * each child. It's passed the child name and the child node. + * @return {*} The first truthy value return by action, or the last falsey one + */ + forEachChild(index: Index, action: (string, node) => any): any; + + /** + * @param {boolean=} opt_exportFormat True for export format (also wire protocol format). + * @return {*} Value of this node as JSON. + */ + val(exportFormat?: boolean): Object; + + /** + * @return {string} hash representing the node contents. + */ + hash(): string; + + /** + * @param {!Node} other Another node + * @return {!number} -1 for less than, 0 for equal, 1 for greater than other + */ + compareTo(other: Node): number; + + /** + * @param {!Node} other + * @return {boolean} Whether or not this snapshot equals other + */ + equals(other: Node): boolean; + + /** + * @param {!Index} indexDefinition + * @return {!Node} This node, with the specified index now available + */ + withIndex(indexDefinition: Index): Node; + + /** + * @param {!Index} indexDefinition + * @return {boolean} + */ + isIndexed(indexDefinition: Index): boolean; +} + +/** + * + * @param {!string} name + * @param {!Node} node + * @constructor + * @struct + */ +export class NamedNode { + constructor(public name: string, public node: Node) {} + + /** + * + * @param {!string} name + * @param {!Node} node + * @return {NamedNode} + */ + static Wrap(name: string, node: Node) { + return new NamedNode(name, node); + } +} + diff --git a/src/database/core/snap/childSet.ts b/src/database/core/snap/childSet.ts new file mode 100644 index 00000000000..e62fa02b79f --- /dev/null +++ b/src/database/core/snap/childSet.ts @@ -0,0 +1,119 @@ +import { LLRBNode } from "../util/SortedMap"; +import { SortedMap } from "../util/SortedMap"; + +const LOG_2 = Math.log(2); + +/** + * @param {number} length + * @constructor + */ +class Base12Num { + count; + current_; + bits_; + + constructor(length) { + var logBase2 = function(num) { + return parseInt((Math.log(num) / LOG_2 as any), 10); + }; + var bitMask = function(bits) { + return parseInt(Array(bits + 1).join('1'), 2); + }; + this.count = logBase2(length + 1); + this.current_ = this.count - 1; + var mask = bitMask(this.count); + this.bits_ = (length + 1) & mask; + } + + /** + * @return {boolean} + */ + nextBitIsOne() { + //noinspection JSBitwiseOperatorUsage + var result = !(this.bits_ & (0x1 << this.current_)); + this.current_--; + return result; + }; +} + +/** + * Takes a list of child nodes and constructs a SortedSet using the given comparison + * function + * + * Uses the algorithm described in the paper linked here: + * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.46.1458 + * + * @template K, V + * @param {Array.} childList Unsorted list of children + * @param {function(!NamedNode, !NamedNode):number} cmp The comparison method to be used + * @param {(function(NamedNode):K)=} keyFn An optional function to extract K from a node wrapper, if K's + * type is not NamedNode + * @param {(function(K, K):number)=} mapSortFn An optional override for comparator used by the generated sorted map + * @return {SortedMap.} + */ +export const buildChildSet = function(childList, cmp, keyFn?, mapSortFn?) { + childList.sort(cmp); + + var buildBalancedTree = function(low, high) { + var length = high - low; + if (length == 0) { + return null; + } else if (length == 1) { + var namedNode = childList[low]; + var key = keyFn ? keyFn(namedNode) : namedNode; + return new LLRBNode(key, namedNode.node, LLRBNode.BLACK, null, null); + } else { + var middle = parseInt((length / 2 as any), 10) + low; + var left = buildBalancedTree(low, middle); + var right = buildBalancedTree(middle + 1, high); + namedNode = childList[middle]; + key = keyFn ? keyFn(namedNode) : namedNode; + return new LLRBNode(key, namedNode.node, LLRBNode.BLACK, left, right); + } + }; + + var buildFrom12Array = function(base12) { + var node = null; + var root = null; + var index = childList.length; + + var buildPennant = function(chunkSize, color) { + var low = index - chunkSize; + var high = index; + index -= chunkSize; + var childTree = buildBalancedTree(low + 1, high); + var namedNode = childList[low]; + var key = keyFn ? keyFn(namedNode) : namedNode; + attachPennant(new LLRBNode(key, namedNode.node, color, null, childTree)); + }; + + var attachPennant = function(pennant) { + if (node) { + node.left = pennant; + node = pennant; + } else { + root = pennant; + node = pennant; + } + }; + + for (var i = 0; i < base12.count; ++i) { + var isOne = base12.nextBitIsOne(); + // The number of nodes taken in each slice is 2^(arr.length - (i + 1)) + var chunkSize = Math.pow(2, base12.count - (i + 1)); + if (isOne) { + buildPennant(chunkSize, LLRBNode.BLACK); + } else { + // current == 2 + buildPennant(chunkSize, LLRBNode.BLACK); + buildPennant(chunkSize, LLRBNode.RED); + } + } + return root; + }; + + var base12 = new Base12Num(childList.length); + var root = buildFrom12Array(base12); + + return new SortedMap(mapSortFn || cmp, root); +}; \ No newline at end of file diff --git a/src/database/core/snap/comparators.ts b/src/database/core/snap/comparators.ts new file mode 100644 index 00000000000..89fdbc03d2e --- /dev/null +++ b/src/database/core/snap/comparators.ts @@ -0,0 +1,9 @@ +import { nameCompare } from "../util/util"; + +export function NAME_ONLY_COMPARATOR(left, right) { + return nameCompare(left.name, right.name); +}; + +export function NAME_COMPARATOR(left, right) { + return nameCompare(left, right); +}; diff --git a/src/database/core/snap/indexes/Index.ts b/src/database/core/snap/indexes/Index.ts new file mode 100644 index 00000000000..3df5f420a2b --- /dev/null +++ b/src/database/core/snap/indexes/Index.ts @@ -0,0 +1,73 @@ +import { Node, NamedNode } from "../Node"; +import { MIN_NAME, MAX_NAME } from "../../util/util"; + +/** + * + * @constructor + */ +export abstract class Index { + /** + * @param {!NamedNode} a + * @param {!NamedNode} b + * @return {number} + */ + abstract compare(a: NamedNode, b: NamedNode): number; + + /** + * @param {!Node} node + * @return {boolean} + */ + abstract isDefinedOn(node: Node): boolean; + + + /** + * @return {function(!NamedNode, !NamedNode):number} A standalone comparison function for + * this index + */ + getCompare() { + return this.compare.bind(this); + }; + /** + * Given a before and after value for a node, determine if the indexed value has changed. Even if they are different, + * it's possible that the changes are isolated to parts of the snapshot that are not indexed. + * + * @param {!Node} oldNode + * @param {!Node} newNode + * @return {boolean} True if the portion of the snapshot being indexed changed between oldNode and newNode + */ + indexedValueChanged(oldNode, newNode) { + var oldWrapped = new NamedNode(MIN_NAME, oldNode); + var newWrapped = new NamedNode(MIN_NAME, newNode); + return this.compare(oldWrapped, newWrapped) !== 0; + }; + + + /** + * @return {!NamedNode} a node wrapper that will sort equal to or less than + * any other node wrapper, using this index + */ + minPost() { + return (NamedNode as any).MIN; + }; + + + /** + * @return {!NamedNode} a node wrapper that will sort greater than or equal to + * any other node wrapper, using this index + */ + abstract maxPost(): NamedNode; + + + /** + * @param {*} indexValue + * @param {string} name + * @return {!NamedNode} + */ + abstract makePost(indexValue: object, name: string): NamedNode; + + + /** + * @return {!string} String representation for inclusion in a query spec + */ + abstract toString(): string; +}; diff --git a/src/database/core/snap/indexes/KeyIndex.ts b/src/database/core/snap/indexes/KeyIndex.ts new file mode 100644 index 00000000000..d000dd7b8c0 --- /dev/null +++ b/src/database/core/snap/indexes/KeyIndex.ts @@ -0,0 +1,83 @@ +import { Index } from "./Index"; +import { Node, NamedNode } from "../Node"; +import { nameCompare, MAX_NAME } from "../../util/util"; +import { assert, assertionError } from "../../../../utils/assert"; +import { ChildrenNode } from "../ChildrenNode"; + +let __EMPTY_NODE; + +export class KeyIndex extends Index { + static get __EMPTY_NODE() { + return __EMPTY_NODE; + } + static set __EMPTY_NODE(val) { + __EMPTY_NODE = val; + } + constructor() { + super(); + } + /** + * @inheritDoc + */ + compare(a, b) { + return nameCompare(a.name, b.name); + }; + + + /** + * @inheritDoc + */ + isDefinedOn(node: Node): boolean { + // We could probably return true here (since every node has a key), but it's never called + // so just leaving unimplemented for now. + throw assertionError('KeyIndex.isDefinedOn not expected to be called.'); + }; + + + /** + * @inheritDoc + */ + indexedValueChanged(oldNode, newNode) { + return false; // The key for a node never changes. + }; + + + /** + * @inheritDoc + */ + minPost() { + return (NamedNode as any).MIN; + }; + + + /** + * @inheritDoc + */ + maxPost() { + // TODO: This should really be created once and cached in a static property, but + // NamedNode isn't defined yet, so I can't use it in a static. Bleh. + return new NamedNode(MAX_NAME, __EMPTY_NODE); + }; + + + /** + * @param {*} indexValue + * @param {string} name + * @return {!NamedNode} + */ + makePost(indexValue, name) { + assert(typeof indexValue === 'string', 'KeyIndex indexValue must always be a string.'); + // We just use empty node, but it'll never be compared, since our comparator only looks at name. + return new NamedNode(indexValue, __EMPTY_NODE); + }; + + + /** + * @return {!string} String representation for inclusion in a query spec + */ + toString() { + return '.key'; + }; +}; + +export const KEY_INDEX = new KeyIndex(); \ No newline at end of file diff --git a/src/database/core/snap/indexes/PathIndex.ts b/src/database/core/snap/indexes/PathIndex.ts new file mode 100644 index 00000000000..1e2da0823ad --- /dev/null +++ b/src/database/core/snap/indexes/PathIndex.ts @@ -0,0 +1,86 @@ +import { assert } from "../../../../utils/assert"; +import { nameCompare, MAX_NAME } from "../../util/util"; +import { Index } from "./Index"; +import { ChildrenNode, MAX_NODE } from "../ChildrenNode"; +import { NamedNode } from "../Node"; +import { nodeFromJSON } from "../nodeFromJSON"; + +/** + * @param {!Path} indexPath + * @constructor + * @extends {Index} + */ +export class PathIndex extends Index { + indexPath_; + + constructor(indexPath) { + super(); + + assert(!indexPath.isEmpty() && indexPath.getFront() !== '.priority', + 'Can\'t create PathIndex with empty path or .priority key'); + /** + * + * @type {!Path} + * @private + */ + this.indexPath_ = indexPath; + }; + /** + * @param {!Node} snap + * @return {!Node} + * @protected + */ + extractChild(snap) { + return snap.getChild(this.indexPath_); + }; + + + /** + * @inheritDoc + */ + isDefinedOn(node) { + return !node.getChild(this.indexPath_).isEmpty(); + }; + + + /** + * @inheritDoc + */ + compare(a, b) { + var aChild = this.extractChild(a.node); + var bChild = this.extractChild(b.node); + var indexCmp = aChild.compareTo(bChild); + if (indexCmp === 0) { + return nameCompare(a.name, b.name); + } else { + return indexCmp; + } + }; + + + /** + * @inheritDoc + */ + makePost(indexValue, name) { + var valueNode = nodeFromJSON(indexValue); + var node = ChildrenNode.EMPTY_NODE.updateChild(this.indexPath_, valueNode); + return new NamedNode(name, node); + }; + + + /** + * @inheritDoc + */ + maxPost() { + var node = ChildrenNode.EMPTY_NODE.updateChild(this.indexPath_, MAX_NODE); + return new NamedNode(MAX_NAME, node); + }; + + + /** + * @inheritDoc + */ + toString() { + return this.indexPath_.slice().join('/'); + }; +} \ No newline at end of file diff --git a/src/database/core/snap/indexes/PriorityIndex.ts b/src/database/core/snap/indexes/PriorityIndex.ts new file mode 100644 index 00000000000..471c58c6965 --- /dev/null +++ b/src/database/core/snap/indexes/PriorityIndex.ts @@ -0,0 +1,95 @@ +import { Index } from './Index'; +import { nameCompare, MAX_NAME } from "../../util/util"; +import { NamedNode } from "../Node"; +import { LeafNode } from "../LeafNode"; + +let nodeFromJSON; +let MAX_NODE; + +export function setNodeFromJSON(val) { + nodeFromJSON = val; +} + +export function setMaxNode(val) { + MAX_NODE = val; +} + + +/** + * @constructor + * @extends {Index} + * @private + */ +export class PriorityIndex extends Index { + + constructor() { + super(); + } + + /** + * @inheritDoc + */ + compare(a, b) { + var aPriority = a.node.getPriority(); + var bPriority = b.node.getPriority(); + var indexCmp = aPriority.compareTo(bPriority); + if (indexCmp === 0) { + return nameCompare(a.name, b.name); + } else { + return indexCmp; + } + }; + + + /** + * @inheritDoc + */ + isDefinedOn(node) { + return !node.getPriority().isEmpty(); + }; + + + /** + * @inheritDoc + */ + indexedValueChanged(oldNode, newNode) { + return !oldNode.getPriority().equals(newNode.getPriority()); + }; + + + /** + * @inheritDoc + */ + minPost() { + return (NamedNode as any).MIN; + }; + + + /** + * @inheritDoc + */ + maxPost() { + return new NamedNode(MAX_NAME, new LeafNode('[PRIORITY-POST]', MAX_NODE)); + }; + + + /** + * @param {*} indexValue + * @param {string} name + * @return {!NamedNode} + */ + makePost(indexValue, name) { + var priorityNode = nodeFromJSON(indexValue); + return new NamedNode(name, new LeafNode('[PRIORITY-POST]', priorityNode)); + }; + + + /** + * @return {!string} String representation for inclusion in a query spec + */ + toString() { + return '.priority'; + }; +}; + +export const PRIORITY_INDEX = new PriorityIndex(); diff --git a/src/database/core/snap/indexes/ValueIndex.ts b/src/database/core/snap/indexes/ValueIndex.ts new file mode 100644 index 00000000000..391c2a4678c --- /dev/null +++ b/src/database/core/snap/indexes/ValueIndex.ts @@ -0,0 +1,74 @@ +import { Index } from "./Index"; +import { NamedNode } from "../Node"; +import { nameCompare } from "../../util/util"; +import { nodeFromJSON } from "../nodeFromJSON"; + +/** + * @constructor + * @extends {Index} + * @private + */ +export class ValueIndex extends Index { + constructor() { + super(); + } + + /** + * @inheritDoc + */ + compare(a, b) { + var indexCmp = a.node.compareTo(b.node); + if (indexCmp === 0) { + return nameCompare(a.name, b.name); + } else { + return indexCmp; + } + }; + + /** + * @inheritDoc + */ + isDefinedOn(node) { + return true; + }; + + /** + * @inheritDoc + */ + indexedValueChanged(oldNode, newNode) { + return !oldNode.equals(newNode); + }; + + /** + * @inheritDoc + */ + minPost() { + return (NamedNode as any).MIN; + }; + + /** + * @inheritDoc + */ + maxPost() { + return (NamedNode as any).MAX; + }; + + /** + * @param {*} indexValue + * @param {string} name + * @return {!NamedNode} + */ + makePost(indexValue, name) { + var valueNode = nodeFromJSON(indexValue); + return new NamedNode(name, valueNode); + }; + + /** + * @return {!string} String representation for inclusion in a query spec + */ + toString() { + return '.value'; + }; +}; + +export const VALUE_INDEX = new ValueIndex(); \ No newline at end of file diff --git a/src/database/core/snap/nodeFromJSON.ts b/src/database/core/snap/nodeFromJSON.ts new file mode 100644 index 00000000000..e35e4fef150 --- /dev/null +++ b/src/database/core/snap/nodeFromJSON.ts @@ -0,0 +1,95 @@ +import { ChildrenNode } from "./ChildrenNode"; +import { LeafNode } from "./LeafNode"; +import { NamedNode } from "./Node"; +import { forEach, contains } from "../../../utils/obj"; +import { assert } from "../../../utils/assert"; +import { buildChildSet } from "./childSet"; +import { NAME_COMPARATOR, NAME_ONLY_COMPARATOR } from "./comparators"; +import { IndexMap } from "./IndexMap"; +import { PRIORITY_INDEX, setNodeFromJSON } from "./indexes/PriorityIndex"; + +const USE_HINZE = true; + +/** + * Constructs a snapshot node representing the passed JSON and returns it. + * @param {*} json JSON to create a node for. + * @param {?string|?number=} opt_priority Optional priority to use. This will be ignored if the + * passed JSON contains a .priority property. + * @return {!Node} + */ +export function nodeFromJSON(json, priority?) { + if (json === null) { + return ChildrenNode.EMPTY_NODE; + } + + priority = priority !== undefined ? priority : null; + if (typeof json === 'object' && '.priority' in json) { + priority = json['.priority']; + } + + assert( + priority === null || + typeof priority === 'string' || + typeof priority === 'number' || + (typeof priority === 'object' && '.sv' in priority), + 'Invalid priority type found: ' + (typeof priority) + ); + + if (typeof json === 'object' && '.value' in json && json['.value'] !== null) { + json = json['.value']; + } + + // Valid leaf nodes include non-objects or server-value wrapper objects + if (typeof json !== 'object' || '.sv' in json) { + var jsonLeaf = /** @type {!(string|number|boolean|Object)} */ (json); + return new LeafNode(jsonLeaf, nodeFromJSON(priority)); + } + + if (!(json instanceof Array) && USE_HINZE) { + var children = []; + var childrenHavePriority = false; + var hinzeJsonObj = /** @type {!Object} */ (json); + forEach(hinzeJsonObj, function(key, child) { + if (typeof key !== 'string' || key.substring(0, 1) !== '.') { // Ignore metadata nodes + var childNode = nodeFromJSON(hinzeJsonObj[key]); + if (!childNode.isEmpty()) { + childrenHavePriority = childrenHavePriority || !childNode.getPriority().isEmpty(); + children.push(new NamedNode(key, childNode)); + } + } + }); + + if (children.length == 0) { + return ChildrenNode.EMPTY_NODE; + } + + var childSet = /**@type {!SortedMap.} */ (buildChildSet( + children, NAME_ONLY_COMPARATOR, function(namedNode) { return namedNode.name; }, + NAME_COMPARATOR + )); + if (childrenHavePriority) { + var sortedChildSet = buildChildSet(children, PRIORITY_INDEX.getCompare()); + return new ChildrenNode(childSet, nodeFromJSON(priority), + new IndexMap({'.priority': sortedChildSet}, {'.priority': PRIORITY_INDEX})); + } else { + return new ChildrenNode(childSet, nodeFromJSON(priority), + IndexMap.Default); + } + } else { + var node = ChildrenNode.EMPTY_NODE; + var jsonObj = /** @type {!Object} */ (json); + forEach(jsonObj, function(key, childData) { + if (contains(jsonObj, key)) { + if (key.substring(0, 1) !== '.') { // ignore metadata nodes. + var childNode = nodeFromJSON(childData); + if (childNode.isLeafNode() || !childNode.isEmpty()) + node = node.updateImmediateChild(key, childNode); + } + } + }); + + return node.updatePriority(nodeFromJSON(priority)); + } +}; + +setNodeFromJSON(nodeFromJSON); \ No newline at end of file diff --git a/src/database/core/snap/snap.ts b/src/database/core/snap/snap.ts new file mode 100644 index 00000000000..63baab5ea48 --- /dev/null +++ b/src/database/core/snap/snap.ts @@ -0,0 +1,43 @@ +import { assert } from '../../../utils/assert'; +import { + doubleToIEEE754String, +} from "../util/util"; +import { contains } from "../../../utils/obj"; +import { NamedNode } from "./Node"; + +let MAX_NODE; + +export function setMaxNode(val) { + MAX_NODE = val; +} + +/** + * @param {(!string|!number)} priority + * @return {!string} + */ +export const priorityHashText = function(priority) { + if (typeof priority === 'number') + return 'number:' + doubleToIEEE754String(priority); + else + return 'string:' + priority; +}; + +/** + * Validates that a priority snapshot Node is valid. + * + * @param {!Node} priorityNode + */ +export const validatePriorityNode = function(priorityNode) { + if (priorityNode.isLeafNode()) { + var val = priorityNode.val(); + assert(typeof val === 'string' || typeof val === 'number' || + (typeof val === 'object' && contains(val, '.sv')), + 'Priority must be a string or number.'); + } else { + assert(priorityNode === MAX_NODE || priorityNode.isEmpty(), + 'priority of unexpected type.'); + } + // Don't call getPriority() on MAX_NODE to avoid hitting assertion. + assert(priorityNode === MAX_NODE || priorityNode.getPriority().isEmpty(), + "Priority nodes can't have a priority of their own."); +}; diff --git a/src/database/core/stats/StatsCollection.ts b/src/database/core/stats/StatsCollection.ts new file mode 100644 index 00000000000..7dfb813a194 --- /dev/null +++ b/src/database/core/stats/StatsCollection.ts @@ -0,0 +1,27 @@ +import { deepCopy } from '../../../utils/deep_copy'; +import { contains } from '../../../utils/obj'; + +/** + * Tracks a collection of stats. + * + * @constructor + */ +export class StatsCollection { + counters_: object; + constructor() { + this.counters_ = { }; + } + incrementCounter(name, amount) { + if (amount === undefined) + amount = 1; + + if (!contains(this.counters_, name)) + this.counters_[name] = 0; + + this.counters_[name] += amount; + } + get() { + return deepCopy(this.counters_); + }; +} + diff --git a/src/database/core/stats/StatsListener.ts b/src/database/core/stats/StatsListener.ts new file mode 100644 index 00000000000..9b829256f5d --- /dev/null +++ b/src/database/core/stats/StatsListener.ts @@ -0,0 +1,29 @@ +import { clone, forEach } from '../../../utils/obj'; + +/** + * Returns the delta from the previous call to get stats. + * + * @param collection_ The collection to "listen" to. + * @constructor + */ +export class StatsListener { + private last_ = null; + + constructor(private collection_) { + } + + get() { + const newStats = this.collection_.get(); + + const delta = clone(newStats); + if (this.last_) { + forEach(this.last_, (stat, value) => { + delta[stat] = delta[stat] - value; + }); + } + this.last_ = newStats; + + return delta; + } +} + diff --git a/src/database/core/stats/StatsManager.ts b/src/database/core/stats/StatsManager.ts new file mode 100644 index 00000000000..a47fe0a4961 --- /dev/null +++ b/src/database/core/stats/StatsManager.ts @@ -0,0 +1,22 @@ +import { StatsCollection } from "./StatsCollection"; + +export const StatsManager = { + collections_:{ }, + reporters_:{ }, + getCollection:function(repoInfo) { + var hashString = repoInfo.toString(); + if (!this.collections_[hashString]) { + this.collections_[hashString] = new StatsCollection(); + } + return this.collections_[hashString]; + }, + getOrCreateReporter:function(repoInfo, creatorFunction) { + var hashString = repoInfo.toString(); + if (!this.reporters_[hashString]) { + this.reporters_[hashString] = creatorFunction(); + } + + return this.reporters_[hashString]; + } +}; + diff --git a/src/database/core/stats/StatsReporter.ts b/src/database/core/stats/StatsReporter.ts new file mode 100644 index 00000000000..daa88fd1a0d --- /dev/null +++ b/src/database/core/stats/StatsReporter.ts @@ -0,0 +1,54 @@ +import { contains, forEach } from '../../../utils/obj'; +import { setTimeoutNonBlocking } from "../util/util"; +import { StatsListener } from "./StatsListener"; + +// Assuming some apps may have a short amount of time on page, and a bulk of firebase operations probably +// happen on page load, we try to report our first set of stats pretty quickly, but we wait at least 10 +// seconds to try to ensure the Firebase connection is established / settled. +const FIRST_STATS_MIN_TIME = 10 * 1000; +const FIRST_STATS_MAX_TIME = 30 * 1000; + +// We'll continue to report stats on average every 5 minutes. +const REPORT_STATS_INTERVAL = 5 * 60 * 1000; + +/** + * + * @param collection + * @param server_ + * @constructor + */ +export class StatsReporter { + private statsListener_; + private statsToReport_ = {}; + + constructor(collection, private server_: any) { + this.statsListener_ = new StatsListener(collection); + + const timeout = FIRST_STATS_MIN_TIME + (FIRST_STATS_MAX_TIME - FIRST_STATS_MIN_TIME) * Math.random(); + setTimeoutNonBlocking(this.reportStats_.bind(this), Math.floor(timeout)); + } + + includeStat(stat) { + this.statsToReport_[stat] = true; + } + + private reportStats_() { + const stats = this.statsListener_.get(); + const reportedStats = {}; + let haveStatsToReport = false; + + forEach(stats, (stat, value) => { + if (value > 0 && contains(this.statsToReport_, stat)) { + reportedStats[stat] = value; + haveStatsToReport = true; + } + }); + + if (haveStatsToReport) { + this.server_.reportStats(reportedStats); + } + + // queue our next run. + setTimeoutNonBlocking(this.reportStats_.bind(this), Math.floor(Math.random() * 2 * REPORT_STATS_INTERVAL)); + } +} diff --git a/src/database/core/storage/DOMStorageWrapper.ts b/src/database/core/storage/DOMStorageWrapper.ts new file mode 100644 index 00000000000..637f7faa116 --- /dev/null +++ b/src/database/core/storage/DOMStorageWrapper.ts @@ -0,0 +1,70 @@ +import { jsonEval, stringify } from "../../../utils/json"; + +/** + * Wraps a DOM Storage object and: + * - automatically encode objects as JSON strings before storing them to allow us to store arbitrary types. + * - prefixes names with "firebase:" to avoid collisions with app data. + * + * We automatically (see storage.js) create two such wrappers, one for sessionStorage, + * and one for localStorage. + * + * @param {Storage} domStorage The underlying storage object (e.g. localStorage or sessionStorage) + * @constructor + */ +export class DOMStorageWrapper { + prefix_; + domStorage_; + + constructor(domStorage) { + this.domStorage_ = domStorage; + + // Use a prefix to avoid collisions with other stuff saved by the app. + this.prefix_ = 'firebase:'; + }; + + /** + * @param {string} key The key to save the value under + * @param {?Object} value The value being stored, or null to remove the key. + */ + set(key, value) { + if (value == null) { + this.domStorage_.removeItem(this.prefixedName_(key)); + } else { + this.domStorage_.setItem(this.prefixedName_(key), stringify(value)); + } + }; + + /** + * @param {string} key + * @return {*} The value that was stored under this key, or null + */ + get(key) { + var storedVal = this.domStorage_.getItem(this.prefixedName_(key)); + if (storedVal == null) { + return null; + } else { + return jsonEval(storedVal); + } + }; + + /** + * @param {string} key + */ + remove(key) { + this.domStorage_.removeItem(this.prefixedName_(key)); + }; + + isInMemoryStorage; + + /** + * @param {string} name + * @return {string} + */ + prefixedName_(name) { + return this.prefix_ + name; + }; + + toString() { + return this.domStorage_.toString(); + }; +} diff --git a/src/database/core/storage/MemoryStorage.ts b/src/database/core/storage/MemoryStorage.ts new file mode 100644 index 00000000000..e0fba630d3a --- /dev/null +++ b/src/database/core/storage/MemoryStorage.ts @@ -0,0 +1,34 @@ +import { contains } from "../../../utils/obj"; + +/** + * An in-memory storage implementation that matches the API of DOMStorageWrapper + * (TODO: create interface for both to implement). + * + * @constructor + */ +export class MemoryStorage { + cache_: object; + constructor() { + this.cache_ = {}; + } + set(key, value) { + if (value == null) { + delete this.cache_[key]; + } else { + this.cache_[key] = value; + } + }; + + get(key) { + if (contains(this.cache_, key)) { + return this.cache_[key]; + } + return null; + }; + + remove(key) { + delete this.cache_[key]; + }; + + isInMemoryStorage = true; +} diff --git a/src/database/core/storage/storage.ts b/src/database/core/storage/storage.ts new file mode 100644 index 00000000000..db63fb0d580 --- /dev/null +++ b/src/database/core/storage/storage.ts @@ -0,0 +1,38 @@ +import { DOMStorageWrapper } from './DOMStorageWrapper'; +import { MemoryStorage } from './MemoryStorage'; + +/** +* Helper to create a DOMStorageWrapper or else fall back to MemoryStorage. +* TODO: Once MemoryStorage and DOMStorageWrapper have a shared interface this method annotation should change +* to reflect this type +* +* @param {string} domStorageName Name of the underlying storage object +* (e.g. 'localStorage' or 'sessionStorage'). +* @return {?} Turning off type information until a common interface is defined. +*/ +const createStoragefor = function(domStorageName) { + try { + // NOTE: just accessing "localStorage" or "window['localStorage']" may throw a security exception, + // so it must be inside the try/catch. + if (typeof window !== 'undefined' && typeof window[domStorageName] !== 'undefined') { + // Need to test cache. Just because it's here doesn't mean it works + var domStorage = window[domStorageName]; + domStorage.setItem('firebase:sentinel', 'cache'); + domStorage.removeItem('firebase:sentinel'); + return new DOMStorageWrapper(domStorage); + } + } catch (e) { + } + + // Failed to create wrapper. Just return in-memory storage. + // TODO: log? + return new MemoryStorage(); +}; + + +/** A storage object that lasts across sessions */ +export const PersistentStorage = createStoragefor('localStorage'); + + +/** A storage object that only lasts one session */ +export const SessionStorage = createStoragefor('sessionStorage'); diff --git a/src/database/core/util/CountedSet.ts b/src/database/core/util/CountedSet.ts new file mode 100644 index 00000000000..6764d324956 --- /dev/null +++ b/src/database/core/util/CountedSet.ts @@ -0,0 +1,91 @@ +import { isEmpty, getCount, forEach, contains } from "../../../utils/obj"; + +/** + * Implements a set with a count of elements. + * + */ +export class CountedSet { + set: object; + + /** + * @template K, V + */ + constructor() { + this.set = {}; + } + + /** + * @param {!K} item + * @param {V} val + */ + add(item, val) { + this.set[item] = val !== null ? val : true; + } + + /** + * @param {!K} key + * @return {boolean} + */ + contains(key) { + return contains(this.set, key); + } + + /** + * @param {!K} item + * @return {V} + */ + get(item) { + return this.contains(item) ? this.set[item] : undefined; + } + + /** + * @param {!K} item + */ + remove(item) { + delete this.set[item]; + } + + /** + * Deletes everything in the set + */ + clear() { + this.set = {}; + } + + /** + * True if there's nothing in the set + * @return {boolean} + */ + isEmpty() { + return isEmpty(this.set); + } + + /** + * @return {number} The number of items in the set + */ + count() { + return getCount(this.set); + } + + /** + * Run a function on each k,v pair in the set + * @param {function(K, V)} fn + */ + each(fn) { + forEach(this.set, function(k, v) { + fn(k, v); + }); + } + + /** + * Mostly for debugging + * @return {Array.} The keys present in this CountedSet + */ + keys() { + var keys = []; + forEach(this.set, function(k, v) { + keys.push(k); + }); + return keys; + } +}; // end fb.core.util.CountedSet diff --git a/src/database/core/util/EventEmitter.ts b/src/database/core/util/EventEmitter.ts new file mode 100644 index 00000000000..f89f9cd5b61 --- /dev/null +++ b/src/database/core/util/EventEmitter.ts @@ -0,0 +1,76 @@ +import { assert } from "../../../utils/assert"; + +/** + * Base class to be used if you want to emit events. Call the constructor with + * the set of allowed event names. + */ +export abstract class EventEmitter { + allowedEvents_; + listeners_; + /** + * @param {!Array.} allowedEvents + */ + constructor(allowedEvents: Array) { + assert(Array.isArray(allowedEvents) && allowedEvents.length > 0, + 'Requires a non-empty array'); + this.allowedEvents_ = allowedEvents; + this.listeners_ = {}; + } + + /** + * To be overridden by derived classes in order to fire an initial event when + * somebody subscribes for data. + * + * @param {!string} eventType + * @return {Array.<*>} Array of parameters to trigger initial event with. + */ + abstract getInitialEvent(eventType: string); + + /** + * To be called by derived classes to trigger events. + * @param {!string} eventType + * @param {...*} var_args + */ + trigger(eventType, var_args) { + if (Array.isArray(this.listeners_[eventType])) { + // Clone the list, since callbacks could add/remove listeners. + var listeners = [ + ...this.listeners_[eventType] + ]; + + for (var i = 0; i < listeners.length; i++) { + listeners[i].callback.apply(listeners[i].context, Array.prototype.slice.call(arguments, 1)); + } + } + } + + on(eventType, callback, context) { + this.validateEventType_(eventType); + this.listeners_[eventType] = this.listeners_[eventType] || []; + this.listeners_[eventType].push({callback: callback, context: context }); + + var eventData = this.getInitialEvent(eventType); + if (eventData) { + callback.apply(context, eventData); + } + } + + off(eventType, callback, context) { + this.validateEventType_(eventType); + var listeners = this.listeners_[eventType] || []; + for (var i = 0; i < listeners.length; i++) { + if (listeners[i].callback === callback && (!context || context === listeners[i].context)) { + listeners.splice(i, 1); + return; + } + } + } + + validateEventType_(eventType) { + assert(this.allowedEvents_.find(function(et) { + return et === eventType; + }), + 'Unknown event: ' + eventType + ); + } +}; // end fb.core.util.EventEmitter diff --git a/src/database/core/util/ImmutableTree.ts b/src/database/core/util/ImmutableTree.ts new file mode 100644 index 00000000000..ced2fbf6bc7 --- /dev/null +++ b/src/database/core/util/ImmutableTree.ts @@ -0,0 +1,342 @@ +import { SortedMap } from "./SortedMap"; +import { Path } from "./Path"; +import { stringCompare } from "./util"; +import { forEach } from "../../../utils/obj"; + +let emptyChildrenSingleton; + +/** + * A tree with immutable elements. + */ +export class ImmutableTree { + value; + children; + + static Empty = new ImmutableTree(null); + + /** + * Singleton empty children collection. + * + * @const + * @type {!SortedMap.>} + * @private + */ + static get EmptyChildren_() { + if (!emptyChildrenSingleton) { + emptyChildrenSingleton = new SortedMap(stringCompare); + } + return emptyChildrenSingleton; + } + + /** + * @template T + * @param {!Object.} obj + * @return {!ImmutableTree.} + */ + static fromObject(obj) { + var tree = ImmutableTree.Empty; + forEach(obj, function(childPath, childSnap) { + tree = tree.set(new Path(childPath), childSnap); + }); + return tree; + } + + /** + * @template T + * @param {?T} value + * @param {SortedMap.>=} opt_children + */ + constructor(value, children?) { + /** + * @const + * @type {?T} + */ + this.value = value; + + /** + * @const + * @type {!SortedMap.>} + */ + this.children = children || ImmutableTree.EmptyChildren_; + } + + /** + * True if the value is empty and there are no children + * @return {boolean} + */ + isEmpty() { + return this.value === null && this.children.isEmpty(); + } + + /** + * Given a path and predicate, return the first node and the path to that node + * where the predicate returns true. + * + * TODO Do a perf test -- If we're creating a bunch of {path: value:} objects + * on the way back out, it may be better to pass down a pathSoFar obj. + * + * @param {!Path} relativePath The remainder of the path + * @param {function(T):boolean} predicate The predicate to satisfy to return a + * node + * @return {?{path:!Path, value:!T}} + */ + findRootMostMatchingPathAndValue(relativePath: Path, predicate) { + if (this.value != null && predicate(this.value)) { + return {path: Path.Empty, value: this.value}; + } else { + if (relativePath.isEmpty()) { + return null; + } else { + var front = relativePath.getFront(); + var child = this.children.get(front); + if (child !== null) { + var childExistingPathAndValue = + child.findRootMostMatchingPathAndValue(relativePath.popFront(), + predicate); + if (childExistingPathAndValue != null) { + var fullPath = new Path(front).child(childExistingPathAndValue.path); + return {path: fullPath, value: childExistingPathAndValue.value}; + } else { + return null; + } + } else { + return null; + } + } + } + } + + /** + * Find, if it exists, the shortest subpath of the given path that points a defined + * value in the tree + * @param {!Path} relativePath + * @return {?{path: !Path, value: !T}} + */ + findRootMostValueAndPath(relativePath) { + return this.findRootMostMatchingPathAndValue(relativePath, function() { return true; }); + } + + /** + * @param {!Path} relativePath + * @return {!ImmutableTree.} The subtree at the given path + */ + subtree(relativePath) { + if (relativePath.isEmpty()) { + return this; + } else { + var front = relativePath.getFront(); + var childTree = this.children.get(front); + if (childTree !== null) { + return childTree.subtree(relativePath.popFront()); + } else { + return ImmutableTree.Empty; + } + } + } + + /** + * Sets a value at the specified path. + * + * @param {!Path} relativePath Path to set value at. + * @param {?T} toSet Value to set. + * @return {!ImmutableTree.} Resulting tree. + */ + set(relativePath, toSet) { + if (relativePath.isEmpty()) { + return new ImmutableTree(toSet, this.children); + } else { + var front = relativePath.getFront(); + var child = this.children.get(front) || ImmutableTree.Empty; + var newChild = child.set(relativePath.popFront(), toSet); + var newChildren = this.children.insert(front, newChild); + return new ImmutableTree(this.value, newChildren); + } + } + + /** + * Removes the value at the specified path. + * + * @param {!Path} relativePath Path to value to remove. + * @return {!ImmutableTree.} Resulting tree. + */ + remove(relativePath) { + if (relativePath.isEmpty()) { + if (this.children.isEmpty()) { + return ImmutableTree.Empty; + } else { + return new ImmutableTree(null, this.children); + } + } else { + var front = relativePath.getFront(); + var child = this.children.get(front); + if (child) { + var newChild = child.remove(relativePath.popFront()); + var newChildren; + if (newChild.isEmpty()) { + newChildren = this.children.remove(front); + } else { + newChildren = this.children.insert(front, newChild); + } + if (this.value === null && newChildren.isEmpty()) { + return ImmutableTree.Empty; + } else { + return new ImmutableTree(this.value, newChildren); + } + } else { + return this; + } + } + } + + /** + * Gets a value from the tree. + * + * @param {!Path} relativePath Path to get value for. + * @return {?T} Value at path, or null. + */ + get(relativePath) { + if (relativePath.isEmpty()) { + return this.value; + } else { + var front = relativePath.getFront(); + var child = this.children.get(front); + if (child) { + return child.get(relativePath.popFront()); + } else { + return null; + } + } + } + + /** + * Replace the subtree at the specified path with the given new tree. + * + * @param {!Path} relativePath Path to replace subtree for. + * @param {!ImmutableTree} newTree New tree. + * @return {!ImmutableTree} Resulting tree. + */ + setTree(relativePath, newTree) { + if (relativePath.isEmpty()) { + return newTree; + } else { + var front = relativePath.getFront(); + var child = this.children.get(front) || ImmutableTree.Empty; + var newChild = child.setTree(relativePath.popFront(), newTree); + var newChildren; + if (newChild.isEmpty()) { + newChildren = this.children.remove(front); + } else { + newChildren = this.children.insert(front, newChild); + } + return new ImmutableTree(this.value, newChildren); + } + } + + /** + * Performs a depth first fold on this tree. Transforms a tree into a single + * value, given a function that operates on the path to a node, an optional + * current value, and a map of child names to folded subtrees + * @template V + * @param {function(Path, ?T, Object.):V} fn + * @return {V} + */ + fold(fn) { + return this.fold_(Path.Empty, fn); + } + + /** + * Recursive helper for public-facing fold() method + * @template V + * @param {!Path} pathSoFar + * @param {function(Path, ?T, Object.):V} fn + * @return {V} + * @private + */ + fold_(pathSoFar, fn) { + var accum = {}; + this.children.inorderTraversal(function(childKey, childTree) { + accum[childKey] = childTree.fold_(pathSoFar.child(childKey), fn); + }); + return fn(pathSoFar, this.value, accum); + } + + /** + * Find the first matching value on the given path. Return the result of applying f to it. + * @template V + * @param {!Path} path + * @param {!function(!Path, !T):?V} f + * @return {?V} + */ + findOnPath(path, f) { + return this.findOnPath_(path, Path.Empty, f); + } + + findOnPath_(pathToFollow, pathSoFar, f) { + var result = this.value ? f(pathSoFar, this.value) : false; + if (result) { + return result; + } else { + if (pathToFollow.isEmpty()) { + return null; + } else { + var front = pathToFollow.getFront(); + var nextChild = this.children.get(front); + if (nextChild) { + return nextChild.findOnPath_(pathToFollow.popFront(), pathSoFar.child(front), f); + } else { + return null; + } + } + } + } + + foreachOnPath(path, f) { + return this.foreachOnPath_(path, Path.Empty, f); + } + + foreachOnPath_(pathToFollow, currentRelativePath, f) { + if (pathToFollow.isEmpty()) { + return this; + } else { + if (this.value) { + f(currentRelativePath, this.value); + } + var front = pathToFollow.getFront(); + var nextChild = this.children.get(front); + if (nextChild) { + return nextChild.foreachOnPath_(pathToFollow.popFront(), + currentRelativePath.child(front), f); + } else { + return ImmutableTree.Empty; + } + } + } + + /** + * Calls the given function for each node in the tree that has a value. + * + * @param {function(!Path, !T)} f A function to be called with + * the path from the root of the tree to a node, and the value at that node. + * Called in depth-first order. + */ + foreach(f) { + this.foreach_(Path.Empty, f); + } + + foreach_(currentRelativePath, f) { + this.children.inorderTraversal(function(childName, childTree) { + childTree.foreach_(currentRelativePath.child(childName), f); + }); + if (this.value) { + f(currentRelativePath, this.value); + } + } + + foreachChild(f) { + this.children.inorderTraversal(function(childName, childTree) { + if (childTree.value) { + f(childName, childTree.value); + } + }); + } +}; // end ImmutableTree diff --git a/src/database/core/util/NextPushId.ts b/src/database/core/util/NextPushId.ts new file mode 100644 index 00000000000..92fe6ebdb4f --- /dev/null +++ b/src/database/core/util/NextPushId.ts @@ -0,0 +1,65 @@ +import { assert } from "../../../utils/assert"; + +/** + * Fancy ID generator that creates 20-character string identifiers with the + * following properties: + * + * 1. They're based on timestamp so that they sort *after* any existing ids. + * 2. They contain 72-bits of random data after the timestamp so that IDs won't + * collide with other clients' IDs. + * 3. They sort *lexicographically* (so the timestamp is converted to characters + * that will sort properly). + * 4. They're monotonically increasing. Even if you generate more than one in + * the same timestamp, the latter ones will sort after the former ones. We do + * this by using the previous random bits but "incrementing" them by 1 (only + * in the case of a timestamp collision). + */ +export const nextPushId = (function() { + // Modeled after base64 web-safe chars, but ordered by ASCII. + var PUSH_CHARS = '-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz'; + + // Timestamp of last push, used to prevent local collisions if you push twice + // in one ms. + var lastPushTime = 0; + + // We generate 72-bits of randomness which get turned into 12 characters and + // appended to the timestamp to prevent collisions with other clients. We + // store the last characters we generated because in the event of a collision, + // we'll use those same characters except "incremented" by one. + var lastRandChars = []; + + return function(now) { + var duplicateTime = (now === lastPushTime); + lastPushTime = now; + + var timeStampChars = new Array(8); + for (var i = 7; i >= 0; i--) { + timeStampChars[i] = PUSH_CHARS.charAt(now % 64); + // NOTE: Can't use << here because javascript will convert to int and lose + // the upper bits. + now = Math.floor(now / 64); + } + assert(now === 0, 'Cannot push at time == 0'); + + var id = timeStampChars.join(''); + + if (!duplicateTime) { + for (i = 0; i < 12; i++) { + lastRandChars[i] = Math.floor(Math.random() * 64); + } + } else { + // If the timestamp hasn't changed since last push, use the same random + // number, except incremented by 1. + for (i = 11; i >= 0 && lastRandChars[i] === 63; i--) { + lastRandChars[i] = 0; + } + lastRandChars[i]++; + } + for (i = 0; i < 12; i++) { + id += PUSH_CHARS.charAt(lastRandChars[i]); + } + assert(id.length === 20, 'nextPushId: Length should be 20.'); + + return id; + }; +})(); diff --git a/src/database/core/util/OnlineMonitor.ts b/src/database/core/util/OnlineMonitor.ts new file mode 100644 index 00000000000..286699ca99a --- /dev/null +++ b/src/database/core/util/OnlineMonitor.ts @@ -0,0 +1,64 @@ +import { assert } from "../../../utils/assert"; +import { EventEmitter } from "./EventEmitter"; +import { isMobileCordova } from "../../../utils/environment"; + +/** + * Monitors online state (as reported by window.online/offline events). + * + * The expectation is that this could have many false positives (thinks we are online + * when we're not), but no false negatives. So we can safely use it to determine when + * we definitely cannot reach the internet. + * + * @extends {fb.core.util.EventEmitter} + */ +export class OnlineMonitor extends EventEmitter { + online_; + + static getInstance() { + return new OnlineMonitor(); + } + + constructor() { + super(['online']); + this.online_ = true; + + // We've had repeated complaints that Cordova apps can get stuck "offline", e.g. + // https://forum.ionicframework.com/t/firebase-connection-is-lost-and-never-come-back/43810 + // It would seem that the 'online' event does not always fire consistently. So we disable it + // for Cordova. + if (typeof window !== 'undefined' && + typeof window.addEventListener !== 'undefined' && + !isMobileCordova()) { + var self = this; + window.addEventListener('online', function() { + if (!self.online_) { + self.online_ = true; + self.trigger('online', true); + } + }, false); + + window.addEventListener('offline', function() { + if (self.online_) { + self.online_ = false; + self.trigger('online', false); + } + }, false); + } + } + + /** + * @param {!string} eventType + * @return {Array.} + */ + getInitialEvent(eventType) { + assert(eventType === 'online', 'Unknown event type: ' + eventType); + return [this.online_]; + } + + /** + * @return {boolean} + */ + currentlyOnline() { + return this.online_; + } +}; // end OnlineMonitor diff --git a/src/database/core/util/Path.ts b/src/database/core/util/Path.ts new file mode 100644 index 00000000000..12edb44a1bf --- /dev/null +++ b/src/database/core/util/Path.ts @@ -0,0 +1,322 @@ +import { nameCompare } from "./util"; +import { stringLength } from "../../../utils/utf8"; +/** + * An immutable object representing a parsed path. It's immutable so that you + * can pass them around to other functions without worrying about them changing + * it. + */ + +export class Path { + pieces_; + pieceNum_; + + /** + * Singleton to represent an empty path + * + * @const + */ + static get Empty() { + return new Path(''); + } + /** + * @param {string|Array.} pathOrString Path string to parse, + * or another path, or the raw tokens array + * @param {number=} opt_pieceNum + */ + constructor(pathOrString: string|string[], opt_pieceNum?) { + if (arguments.length == 1) { + this.pieces_ = (pathOrString).split('/'); + + // Remove empty pieces. + var copyTo = 0; + for (var i = 0; i < this.pieces_.length; i++) { + if (this.pieces_[i].length > 0) { + this.pieces_[copyTo] = this.pieces_[i]; + copyTo++; + } + } + this.pieces_.length = copyTo; + + this.pieceNum_ = 0; + } else { + this.pieces_ = pathOrString; + this.pieceNum_ = opt_pieceNum; + } + } + + getFront() { + if (this.pieceNum_ >= this.pieces_.length) + return null; + + return this.pieces_[this.pieceNum_]; + } + + /** + * @return {number} The number of segments in this path + */ + getLength() { + return this.pieces_.length - this.pieceNum_; + } + + /** + * @return {!Path} + */ + popFront() { + var pieceNum = this.pieceNum_; + if (pieceNum < this.pieces_.length) { + pieceNum++; + } + return new Path(this.pieces_, pieceNum); + } + + /** + * @return {?string} + */ + getBack() { + if (this.pieceNum_ < this.pieces_.length) + return this.pieces_[this.pieces_.length - 1]; + + return null; + } + + toString() { + var pathString = ''; + for (var i = this.pieceNum_; i < this.pieces_.length; i++) { + if (this.pieces_[i] !== '') + pathString += '/' + this.pieces_[i]; + } + + return pathString || '/'; + } + + toUrlEncodedString() { + var pathString = ''; + for (var i = this.pieceNum_; i < this.pieces_.length; i++) { + if (this.pieces_[i] !== '') + pathString += '/' + encodeURIComponent(String(this.pieces_[i])); + } + + return pathString || '/'; + } + + /** + * Shallow copy of the parts of the path. + * + * @param {number=} opt_begin + * @return {!Array} + */ + slice(opt_begin) { + var begin = opt_begin || 0; + return this.pieces_.slice(this.pieceNum_ + begin); + } + + /** + * @return {?Path} + */ + parent() { + if (this.pieceNum_ >= this.pieces_.length) + return null; + + var pieces = []; + for (var i = this.pieceNum_; i < this.pieces_.length - 1; i++) + pieces.push(this.pieces_[i]); + + return new Path(pieces, 0); + } + + /** + * @param {string|!Path} childPathObj + * @return {!Path} + */ + child(childPathObj) { + var pieces = []; + for (var i = this.pieceNum_; i < this.pieces_.length; i++) + pieces.push(this.pieces_[i]); + + if (childPathObj instanceof Path) { + for (i = childPathObj.pieceNum_; i < childPathObj.pieces_.length; i++) { + pieces.push(childPathObj.pieces_[i]); + } + } else { + var childPieces = childPathObj.split('/'); + for (i = 0; i < childPieces.length; i++) { + if (childPieces[i].length > 0) + pieces.push(childPieces[i]); + } + } + + return new Path(pieces, 0); + } + + /** + * @return {boolean} True if there are no segments in this path + */ + isEmpty() { + return this.pieceNum_ >= this.pieces_.length; + } + + /** + * @param {!Path} outerPath + * @param {!Path} innerPath + * @return {!Path} The path from outerPath to innerPath + */ + static relativePath(outerPath, innerPath) { + var outer = outerPath.getFront(), inner = innerPath.getFront(); + if (outer === null) { + return innerPath; + } else if (outer === inner) { + return Path.relativePath(outerPath.popFront(), + innerPath.popFront()); + } else { + throw new Error('INTERNAL ERROR: innerPath (' + innerPath + ') is not within ' + + 'outerPath (' + outerPath + ')'); + } + } + /** + * @param {!Path} left + * @param {!Path} right + * @return {number} -1, 0, 1 if left is less, equal, or greater than the right. + */ + static comparePaths(left, right) { + var leftKeys = left.slice(); + var rightKeys = right.slice(); + for (var i = 0; i < leftKeys.length && i < rightKeys.length; i++) { + var cmp = nameCompare(leftKeys[i], rightKeys[i]); + if (cmp !== 0) return cmp; + } + if (leftKeys.length === rightKeys.length) return 0; + return (leftKeys.length < rightKeys.length) ? -1 : 1; + } + + /** + * + * @param {Path} other + * @return {boolean} true if paths are the same. + */ + equals(other) { + if (this.getLength() !== other.getLength()) { + return false; + } + + for (var i = this.pieceNum_, j = other.pieceNum_; i <= this.pieces_.length; i++, j++) { + if (this.pieces_[i] !== other.pieces_[j]) { + return false; + } + } + + return true; + } + + /** + * + * @param {!Path} other + * @return {boolean} True if this path is a parent (or the same as) other + */ + contains(other) { + var i = this.pieceNum_; + var j = other.pieceNum_; + if (this.getLength() > other.getLength()) { + return false; + } + while (i < this.pieces_.length) { + if (this.pieces_[i] !== other.pieces_[j]) { + return false; + } + ++i; + ++j; + } + return true; + } +} // end Path + +/** + * Dynamic (mutable) path used to count path lengths. + * + * This class is used to efficiently check paths for valid + * length (in UTF8 bytes) and depth (used in path validation). + * + * Throws Error exception if path is ever invalid. + * + * The definition of a path always begins with '/'. + */ +export class ValidationPath { + /** @type {!Array} */ + parts_; + /** @type {number} Initialize to number of '/' chars needed in path. */ + byteLength_; + /** @type {string} */ + errorPrefix_; + + /** + * @param {!Path} path Initial Path. + * @param {string} errorPrefix Prefix for any error messages. + */ + constructor(path, errorPrefix) { + /** @type {!Array} */ + this.parts_ = path.slice(); + /** @type {number} Initialize to number of '/' chars needed in path. */ + this.byteLength_ = Math.max(1, this.parts_.length); + /** @type {string} */ + this.errorPrefix_ = errorPrefix; + + for (var i = 0; i < this.parts_.length; i++) { + this.byteLength_ += stringLength(this.parts_[i]); + } + this.checkValid_(); + } + /** @const {number} Maximum key depth. */ + static get MAX_PATH_DEPTH() { + return 32; + } + + /** @const {number} Maximum number of (UTF8) bytes in a Firebase path. */ + static get MAX_PATH_LENGTH_BYTES() { + return 768 + } + + /** @param {string} child */ + push(child) { + // Count the needed '/' + if (this.parts_.length > 0) { + this.byteLength_ += 1; + } + this.parts_.push(child); + this.byteLength_ += stringLength(child); + this.checkValid_(); + } + + pop() { + var last = this.parts_.pop(); + this.byteLength_ -= stringLength(last); + // Un-count the previous '/' + if (this.parts_.length > 0) { + this.byteLength_ -= 1; + } + } + + checkValid_() { + if (this.byteLength_ > ValidationPath.MAX_PATH_LENGTH_BYTES) { + throw new Error(this.errorPrefix_ + 'has a key path longer than ' + + ValidationPath.MAX_PATH_LENGTH_BYTES + ' bytes (' + + this.byteLength_ + ').'); + } + if (this.parts_.length > ValidationPath.MAX_PATH_DEPTH) { + throw new Error(this.errorPrefix_ + 'path specified exceeds the maximum depth that can be written (' + + ValidationPath.MAX_PATH_DEPTH + + ') or object contains a cycle ' + this.toErrorString()); + } + } + + /** + * String for use in error messages - uses '.' notation for path. + * + * @return {string} + */ + toErrorString() { + if (this.parts_.length == 0) { + return ''; + } + return 'in property \'' + this.parts_.join('.') + '\''; + } + +}; // end fb.core.util.validation.ValidationPath diff --git a/src/database/core/util/ServerValues.ts b/src/database/core/util/ServerValues.ts new file mode 100644 index 00000000000..89a9b52362b --- /dev/null +++ b/src/database/core/util/ServerValues.ts @@ -0,0 +1,87 @@ +import { assert } from "../../../utils/assert"; +import { Path } from "./Path"; +import { SparseSnapshotTree } from "../SparseSnapshotTree"; +import { LeafNode } from "../snap/LeafNode"; +import { nodeFromJSON } from "../snap/nodeFromJSON"; +import { PRIORITY_INDEX } from "../snap/indexes/PriorityIndex"; +/** + * Generate placeholders for deferred values. + * @param {?Object} values + * @return {!Object} + */ +export const generateWithValues = function(values) { + values = values || {}; + values['timestamp'] = values['timestamp'] || new Date().getTime(); + return values; +}; + + +/** + * Value to use when firing local events. When writing server values, fire + * local events with an approximate value, otherwise return value as-is. + * @param {(Object|string|number|boolean)} value + * @param {!Object} serverValues + * @return {!(string|number|boolean)} + */ +export const resolveDeferredValue = function(value, serverValues) { + if (!value || (typeof value !== 'object')) { + return /** @type {(string|number|boolean)} */ (value); + } else { + assert('.sv' in value, 'Unexpected leaf node or priority contents'); + return serverValues[value['.sv']]; + } +}; + + +/** + * Recursively replace all deferred values and priorities in the tree with the + * specified generated replacement values. + * @param {!SparseSnapshotTree} tree + * @param {!Object} serverValues + * @return {!SparseSnapshotTree} + */ +export const resolveDeferredValueTree = function(tree, serverValues) { + var resolvedTree = new SparseSnapshotTree(); + tree.forEachTree(new Path(''), function(path, node) { + resolvedTree.remember(path, resolveDeferredValueSnapshot(node, serverValues)); + }); + return resolvedTree; +}; + + +/** + * Recursively replace all deferred values and priorities in the node with the + * specified generated replacement values. If there are no server values in the node, + * it'll be returned as-is. + * @param {!fb.core.snap.Node} node + * @param {!Object} serverValues + * @return {!fb.core.snap.Node} + */ +export const resolveDeferredValueSnapshot = function(node, serverValues) { + var rawPri = /** @type {Object|boolean|null|number|string} */ (node.getPriority().val()), + priority = resolveDeferredValue(rawPri, serverValues), + newNode; + + if (node.isLeafNode()) { + var leafNode = /** @type {!LeafNode} */ (node); + var value = resolveDeferredValue(leafNode.getValue(), serverValues); + if (value !== leafNode.getValue() || priority !== leafNode.getPriority().val()) { + return new LeafNode(value, nodeFromJSON(priority)); + } else { + return node; + } + } else { + var childrenNode = /** @type {!fb.core.snap.ChildrenNode} */ (node); + newNode = childrenNode; + if (priority !== childrenNode.getPriority().val()) { + newNode = newNode.updatePriority(new LeafNode(priority)); + } + childrenNode.forEachChild(PRIORITY_INDEX, function(childName, childNode) { + var newChildNode = resolveDeferredValueSnapshot(childNode, serverValues); + if (newChildNode !== childNode) { + newNode = newNode.updateImmediateChild(childName, newChildNode); + } + }); + return newNode; + } +}; diff --git a/src/database/core/util/SortedMap.ts b/src/database/core/util/SortedMap.ts new file mode 100644 index 00000000000..2cb19374dc8 --- /dev/null +++ b/src/database/core/util/SortedMap.ts @@ -0,0 +1,748 @@ +/** + * @fileoverview Implementation of an immutable SortedMap using a Left-leaning + * Red-Black Tree, adapted from the implementation in Mugs + * (http://mads379.github.com/mugs/) by Mads Hartmann Jensen + * (mads379@gmail.com). + * + * Original paper on Left-leaning Red-Black Trees: + * http://www.cs.princeton.edu/~rs/talks/LLRB/LLRB.pdf + * + * Invariant 1: No red node has a red child + * Invariant 2: Every leaf path has the same number of black nodes + * Invariant 3: Only the left child can be red (left leaning) + */ + + +// TODO: There are some improvements I'd like to make to improve memory / perf: +// * Create two prototypes, LLRedNode and LLBlackNode, instead of storing a +// color property in every node. +// TODO: It would also be good (and possibly necessary) to create a base +// interface for LLRBNode and LLRBEmptyNode. + + +/** + * An iterator over an LLRBNode. + */ +export class SortedMapIterator { + /** @private + * @type {?function(!K, !V): T} + */ + resultGenerator_; + isReverse_; + + /** @private + * @type {Array.} + */ + nodeStack_: Array; + + /** + * @template K, V, T + * @param {LLRBNode|LLRBEmptyNode} node Node to iterate. + * @param {?K} startKey + * @param {function(K, K): number} comparator + * @param {boolean} isReverse Whether or not to iterate in reverse + * @param {(function(K, V):T)=} opt_resultGenerator + */ + constructor(node, startKey, comparator, isReverse, opt_resultGenerator?) { + /** @private + * @type {?function(!K, !V): T} + */ + this.resultGenerator_ = opt_resultGenerator || null; + this.isReverse_ = isReverse; + + /** @private + * @type {Array.} + */ + this.nodeStack_ = []; + + var cmp = 1; + while (!node.isEmpty()) { + cmp = startKey ? comparator(node.key, startKey) : 1; + // flip the comparison if we're going in reverse + if (isReverse) cmp *= -1; + + if (cmp < 0) { + // This node is less than our start key. ignore it + if (this.isReverse_) { + node = node.left; + } else { + node = node.right; + } + } else if (cmp === 0) { + // This node is exactly equal to our start key. Push it on the stack, but stop iterating; + this.nodeStack_.push(node); + break; + } else { + // This node is greater than our start key, add it to the stack and move to the next one + this.nodeStack_.push(node); + if (this.isReverse_) { + node = node.right; + } else { + node = node.left; + } + } + } + } + + getNext() { + if (this.nodeStack_.length === 0) + return null; + + var node = this.nodeStack_.pop(), result; + if (this.resultGenerator_) + result = this.resultGenerator_(node.key, node.value); + else + result = {key: node.key, value: node.value}; + + if (this.isReverse_) { + node = node.left; + while (!node.isEmpty()) { + this.nodeStack_.push(node); + node = node.right; + } + } else { + node = node.right; + while (!node.isEmpty()) { + this.nodeStack_.push(node); + node = node.left; + } + } + + return result; + } + + hasNext() { + return this.nodeStack_.length > 0; + } + + peek() { + if (this.nodeStack_.length === 0) + return null; + + var node = this.nodeStack_[this.nodeStack_.length - 1]; + if (this.resultGenerator_) { + return this.resultGenerator_(node.key, node.value); + } else { + return { key: node.key, value: node.value }; + } + } +}; // end SortedMapIterator + + +/** + * Represents a node in a Left-leaning Red-Black tree. + */ +export class LLRBNode { + key; + value; + color; + left; + right; + + /** + * @template K, V + * @param {!K} key Key associated with this node. + * @param {!V} value Value associated with this node. + * @param {?boolean} color Whether this node is red. + * @param {?(LLRBNode|LLRBEmptyNode)=} opt_left Left child. + * @param {?(LLRBNode|LLRBEmptyNode)=} opt_right Right child. + */ + constructor(key, value, color, opt_left?, opt_right?) { + this.key = key; + this.value = value; + this.color = color != null ? color : LLRBNode.RED; + this.left = opt_left != null ? opt_left : SortedMap.EMPTY_NODE_; + this.right = opt_right != null ? opt_right : SortedMap.EMPTY_NODE_; + } + + static RED = true; + static BLACK = false; + + /** + * Returns a copy of the current node, optionally replacing pieces of it. + * + * @param {?K} key New key for the node, or null. + * @param {?V} value New value for the node, or null. + * @param {?boolean} color New color for the node, or null. + * @param {?LLRBNode|LLRBEmptyNode} left New left child for the node, or null. + * @param {?LLRBNode|LLRBEmptyNode} right New right child for the node, or null. + * @return {!LLRBNode} The node copy. + */ + copy(key, value, color, left, right) { + return new LLRBNode( + (key != null) ? key : this.key, + (value != null) ? value : this.value, + (color != null) ? color : this.color, + (left != null) ? left : this.left, + (right != null) ? right : this.right); + } + + /** + * @return {number} The total number of nodes in the tree. + */ + count() { + return this.left.count() + 1 + this.right.count(); + } + + /** + * @return {boolean} True if the tree is empty. + */ + isEmpty() { + return false; + } + + /** + * Traverses the tree in key order and calls the specified action function + * for each node. + * + * @param {function(!K, !V):*} action Callback function to be called for each + * node. If it returns true, traversal is aborted. + * @return {*} The first truthy value returned by action, or the last falsey + * value returned by action + */ + inorderTraversal(action) { + return this.left.inorderTraversal(action) || + action(this.key, this.value) || + this.right.inorderTraversal(action); + } + + /** + * Traverses the tree in reverse key order and calls the specified action function + * for each node. + * + * @param {function(!Object, !Object)} action Callback function to be called for each + * node. If it returns true, traversal is aborted. + * @return {*} True if traversal was aborted. + */ + reverseTraversal(action) { + return this.right.reverseTraversal(action) || + action(this.key, this.value) || + this.left.reverseTraversal(action); + } + + /** + * @return {!Object} The minimum node in the tree. + * @private + */ + min_() { + if (this.left.isEmpty()) { + return this; + } else { + return this.left.min_(); + } + } + + /** + * @return {!K} The maximum key in the tree. + */ + minKey() { + return this.min_().key; + } + + /** + * @return {!K} The maximum key in the tree. + */ + maxKey() { + if (this.right.isEmpty()) { + return this.key; + } else { + return this.right.maxKey(); + } + } + + /** + * + * @param {!Object} key Key to insert. + * @param {!Object} value Value to insert. + * @param {fb.Comparator} comparator Comparator. + * @return {!LLRBNode} New tree, with the key/value added. + */ + insert(key, value, comparator) { + var cmp, n; + n = this; + cmp = comparator(key, n.key); + if (cmp < 0) { + n = n.copy(null, null, null, n.left.insert(key, value, comparator), null); + } else if (cmp === 0) { + n = n.copy(null, value, null, null, null); + } else { + n = n.copy(null, null, null, null, n.right.insert(key, value, comparator)); + } + return n.fixUp_(); + } + + /** + * @private + * @return {!LLRBNode|LLRBEmptyNode} New tree, with the minimum key removed. + */ + removeMin_() { + var n; + if (this.left.isEmpty()) { + return SortedMap.EMPTY_NODE_; + } + n = this; + if (!n.left.isRed_() && !n.left.left.isRed_()) + n = n.moveRedLeft_(); + n = n.copy(null, null, null, n.left.removeMin_(), null); + return n.fixUp_(); + } + + /** + * @param {!Object} key The key of the item to remove. + * @param {fb.Comparator} comparator Comparator. + * @return {!LLRBNode|LLRBEmptyNode} New tree, with the specified item removed. + */ + remove(key, comparator) { + var n, smallest; + n = this; + if (comparator(key, n.key) < 0) { + if (!n.left.isEmpty() && !n.left.isRed_() && !n.left.left.isRed_()) { + n = n.moveRedLeft_(); + } + n = n.copy(null, null, null, n.left.remove(key, comparator), null); + } else { + if (n.left.isRed_()) n = n.rotateRight_(); + if (!n.right.isEmpty() && !n.right.isRed_() && !n.right.left.isRed_()) { + n = n.moveRedRight_(); + } + if (comparator(key, n.key) === 0) { + if (n.right.isEmpty()) { + return SortedMap.EMPTY_NODE_; + } else { + smallest = n.right.min_(); + n = n.copy(smallest.key, smallest.value, null, null, + n.right.removeMin_()); + } + } + n = n.copy(null, null, null, null, n.right.remove(key, comparator)); + } + return n.fixUp_(); + } + + /** + * @private + * @return {boolean} Whether this is a RED node. + */ + isRed_() { + return this.color; + } + + /** + * @private + * @return {!LLRBNode} New tree after performing any needed rotations. + */ + fixUp_() { + var n = this; + if (n.right.isRed_() && !n.left.isRed_()) n = n.rotateLeft_(); + if (n.left.isRed_() && n.left.left.isRed_()) n = n.rotateRight_(); + if (n.left.isRed_() && n.right.isRed_()) n = n.colorFlip_(); + return n; + } + + /** + * @private + * @return {!LLRBNode} New tree, after moveRedLeft. + */ + moveRedLeft_() { + var n = this.colorFlip_(); + if (n.right.left.isRed_()) { + n = n.copy(null, null, null, null, n.right.rotateRight_()); + n = n.rotateLeft_(); + n = n.colorFlip_(); + } + return n; + } + + /** + * @private + * @return {!LLRBNode} New tree, after moveRedRight. + */ + moveRedRight_() { + var n = this.colorFlip_(); + if (n.left.left.isRed_()) { + n = n.rotateRight_(); + n = n.colorFlip_(); + } + return n; + } + + /** + * @private + * @return {!LLRBNode} New tree, after rotateLeft. + */ + rotateLeft_() { + var nl; + nl = this.copy(null, null, LLRBNode.RED, null, this.right.left); + return this.right.copy(null, null, this.color, nl, null); + } + + /** + * @private + * @return {!LLRBNode} New tree, after rotateRight. + */ + rotateRight_() { + var nr; + nr = this.copy(null, null, LLRBNode.RED, this.left.right, null); + return this.left.copy(null, null, this.color, null, nr); + } + + /** + * @private + * @return {!LLRBNode} New tree, after colorFlip. + */ + colorFlip_() { + var left, right; + left = this.left.copy(null, null, !this.left.color, null, null); + right = this.right.copy(null, null, !this.right.color, null, null); + return this.copy(null, null, !this.color, left, right); + } + + /** + * For testing. + * + * @private + * @return {boolean} True if all is well. + */ + checkMaxDepth_() { + var blackDepth; + blackDepth = this.check_(); + if (Math.pow(2.0, blackDepth) <= this.count() + 1) { + return true; + } else { + return false; + } + } + + /** + * @private + * @return {number} Not sure what this returns exactly. :-). + */ + check_() { + var blackDepth; + if (this.isRed_() && this.left.isRed_()) { + throw new Error('Red node has red child(' + this.key + ',' + + this.value + ')'); + } + if (this.right.isRed_()) { + throw new Error('Right child of (' + this.key + ',' + + this.value + ') is red'); + } + blackDepth = this.left.check_(); + if (blackDepth !== this.right.check_()) { + throw new Error('Black depths differ'); + } else { + return blackDepth + (this.isRed_() ? 0 : 1); + } + } +}; // end LLRBNode + + +/** + * Represents an empty node (a leaf node in the Red-Black Tree). + */ +export class LLRBEmptyNode { + /** + * @template K, V + */ + constructor() {} + + /** + * Returns a copy of the current node. + * + * @return {!LLRBEmptyNode} The node copy. + */ + copy() { + return this; + } + + /** + * Returns a copy of the tree, with the specified key/value added. + * + * @param {!K} key Key to be added. + * @param {!V} value Value to be added. + * @param {fb.Comparator} comparator Comparator. + * @return {!LLRBNode} New tree, with item added. + */ + insert(key, value, comparator) { + return new LLRBNode(key, value, null); + } + + /** + * Returns a copy of the tree, with the specified key removed. + * + * @param {!K} key The key to remove. + * @return {!LLRBEmptyNode} New tree, with item removed. + */ + remove(key, comparator) { + return this; + } + + /** + * @return {number} The total number of nodes in the tree. + */ + count() { + return 0; + } + + /** + * @return {boolean} True if the tree is empty. + */ + isEmpty() { + return true; + } + + /** + * Traverses the tree in key order and calls the specified action function + * for each node. + * + * @param {function(!K, !V)} action Callback function to be called for each + * node. If it returns true, traversal is aborted. + * @return {boolean} True if traversal was aborted. + */ + inorderTraversal(action) { + return false; + } + + /** + * Traverses the tree in reverse key order and calls the specified action function + * for each node. + * + * @param {function(!K, !V)} action Callback function to be called for each + * node. If it returns true, traversal is aborted. + * @return {boolean} True if traversal was aborted. + */ + reverseTraversal(action) { + return false; + } + + /** + * @return {null} + */ + minKey() { + return null; + } + + /** + * @return {null} + */ + maxKey() { + return null; + } + + /** + * @private + * @return {number} Not sure what this returns exactly. :-). + */ + check_() { return 0; } + + /** + * @private + * @return {boolean} Whether this node is red. + */ + isRed_() { return false; } +}; // end LLRBEmptyNode + +/** + * An immutable sorted map implementation, based on a Left-leaning Red-Black + * tree. + */ +export class SortedMap { + /** @private */ + comparator_; + + /** @private */ + root_; + + /** + * Always use the same empty node, to reduce memory. + * @private + * @const + */ + static EMPTY_NODE_ = new LLRBEmptyNode(); + + /** + * @template K, V + * @param {function(K, K):number} comparator Key comparator. + * @param {LLRBNode=} opt_root (Optional) Root node for the map. + */ + constructor(comparator, opt_root?) { + /** @private */ + this.comparator_ = comparator; + + /** @private */ + this.root_ = opt_root ? opt_root : SortedMap.EMPTY_NODE_; + } + + /** + * Returns a copy of the map, with the specified key/value added or replaced. + * (TODO: We should perhaps rename this method to 'put') + * + * @param {!K} key Key to be added. + * @param {!V} value Value to be added. + * @return {!SortedMap.} New map, with item added. + */ + insert(key, value) { + return new SortedMap( + this.comparator_, + this.root_.insert(key, value, this.comparator_) + .copy(null, null, LLRBNode.BLACK, null, null)); + } + + /** + * Returns a copy of the map, with the specified key removed. + * + * @param {!K} key The key to remove. + * @return {!SortedMap.} New map, with item removed. + */ + remove(key) { + return new SortedMap( + this.comparator_, + this.root_.remove(key, this.comparator_) + .copy(null, null, LLRBNode.BLACK, null, null)); + } + + /** + * Returns the value of the node with the given key, or null. + * + * @param {!K} key The key to look up. + * @return {?V} The value of the node with the given key, or null if the + * key doesn't exist. + */ + get(key) { + var cmp; + var node = this.root_; + while (!node.isEmpty()) { + cmp = this.comparator_(key, node.key); + if (cmp === 0) { + return node.value; + } else if (cmp < 0) { + node = node.left; + } else if (cmp > 0) { + node = node.right; + } + } + return null; + } + + /** + * Returns the key of the item *before* the specified key, or null if key is the first item. + * @param {K} key The key to find the predecessor of + * @return {?K} The predecessor key. + */ + getPredecessorKey(key) { + var cmp, node = this.root_, rightParent = null; + while (!node.isEmpty()) { + cmp = this.comparator_(key, node.key); + if (cmp === 0) { + if (!node.left.isEmpty()) { + node = node.left; + while (!node.right.isEmpty()) + node = node.right; + return node.key; + } else if (rightParent) { + return rightParent.key; + } else { + return null; // first item. + } + } else if (cmp < 0) { + node = node.left; + } else if (cmp > 0) { + rightParent = node; + node = node.right; + } + } + + throw new Error('Attempted to find predecessor key for a nonexistent key. What gives?'); + } + + /** + * @return {boolean} True if the map is empty. + */ + isEmpty() { + return this.root_.isEmpty(); + } + + /** + * @return {number} The total number of nodes in the map. + */ + count() { + return this.root_.count(); + } + + /** + * @return {?K} The minimum key in the map. + */ + minKey() { + return this.root_.minKey(); + } + + /** + * @return {?K} The maximum key in the map. + */ + maxKey() { + return this.root_.maxKey(); + } + + /** + * Traverses the map in key order and calls the specified action function + * for each key/value pair. + * + * @param {function(!K, !V):*} action Callback function to be called + * for each key/value pair. If action returns true, traversal is aborted. + * @return {*} The first truthy value returned by action, or the last falsey + * value returned by action + */ + inorderTraversal(action) { + return this.root_.inorderTraversal(action); + } + + /** + * Traverses the map in reverse key order and calls the specified action function + * for each key/value pair. + * + * @param {function(!Object, !Object)} action Callback function to be called + * for each key/value pair. If action returns true, traversal is aborted. + * @return {*} True if the traversal was aborted. + */ + reverseTraversal(action) { + return this.root_.reverseTraversal(action); + } + + /** + * Returns an iterator over the SortedMap. + * @template T + * @param {(function(K, V):T)=} opt_resultGenerator + * @return {SortedMapIterator.} The iterator. + */ + getIterator(resultGenerator?) { + return new SortedMapIterator(this.root_, + null, + this.comparator_, + false, + resultGenerator); + } + + getIteratorFrom(key, resultGenerator?) { + return new SortedMapIterator(this.root_, + key, + this.comparator_, + false, + resultGenerator); + } + + getReverseIteratorFrom(key, resultGenerator?) { + return new SortedMapIterator(this.root_, + key, + this.comparator_, + true, + resultGenerator); + } + + getReverseIterator(resultGenerator?) { + return new SortedMapIterator(this.root_, + null, + this.comparator_, + true, + resultGenerator); + } +}; // end SortedMap \ No newline at end of file diff --git a/src/database/core/util/Tree.ts b/src/database/core/util/Tree.ts new file mode 100644 index 00000000000..75caba7ed7c --- /dev/null +++ b/src/database/core/util/Tree.ts @@ -0,0 +1,230 @@ +import { assert } from "../../../utils/assert"; +import { Path } from "./Path"; +import { forEach, contains, safeGet } from '../../../utils/obj' + +/** + * Node in a Tree. + */ +export class TreeNode { + children; + childCount; + value; + + constructor() { + // TODO: Consider making accessors that create children and value lazily or + // separate Internal / Leaf 'types'. + this.children = { }; + this.childCount = 0; + this.value = null; + } +}; // end TreeNode + + +/** + * A light-weight tree, traversable by path. Nodes can have both values and children. + * Nodes are not enumerated (by forEachChild) unless they have a value or non-empty + * children. + */ +export class Tree { + name_; + parent_; + node_; + + /** + * @template T + * @param {string=} opt_name Optional name of the node. + * @param {Tree=} opt_parent Optional parent node. + * @param {TreeNode=} opt_node Optional node to wrap. + */ + constructor(opt_name?, opt_parent?, opt_node?) { + this.name_ = opt_name ? opt_name : ''; + this.parent_ = opt_parent ? opt_parent : null; + this.node_ = opt_node ? opt_node : new TreeNode(); + } + + /** + * Returns a sub-Tree for the given path. + * + * @param {!(string|Path)} pathObj Path to look up. + * @return {!Tree.} Tree for path. + */ + subTree(pathObj) { + // TODO: Require pathObj to be Path? + var path = (pathObj instanceof Path) ? + pathObj : new Path(pathObj); + var child = this, next; + while ((next = path.getFront()) !== null) { + var childNode = safeGet(child.node_.children, next) || new TreeNode(); + child = new Tree(next, child, childNode); + path = path.popFront(); + } + + return child; + } + + /** + * Returns the data associated with this tree node. + * + * @return {?T} The data or null if no data exists. + */ + getValue() { + return this.node_.value; + } + + /** + * Sets data to this tree node. + * + * @param {!T} value Value to set. + */ + setValue(value) { + assert(typeof value !== 'undefined', 'Cannot set value to undefined'); + this.node_.value = value; + this.updateParents_(); + } + + /** + * Clears the contents of the tree node (its value and all children). + */ + clear() { + this.node_.value = null; + this.node_.children = { }; + this.node_.childCount = 0; + this.updateParents_(); + } + + /** + * @return {boolean} Whether the tree has any children. + */ + hasChildren() { + return this.node_.childCount > 0; + } + + /** + * @return {boolean} Whether the tree is empty (no value or children). + */ + isEmpty() { + return this.getValue() === null && !this.hasChildren(); + } + + /** + * Calls action for each child of this tree node. + * + * @param {function(!Tree.)} action Action to be called for each child. + */ + forEachChild(action) { + var self = this; + forEach(this.node_.children, function(child, childTree) { + action(new Tree(child, self, childTree)); + }); + } + + /** + * Does a depth-first traversal of this node's descendants, calling action for each one. + * + * @param {function(!Tree.)} action Action to be called for each child. + * @param {boolean=} opt_includeSelf Whether to call action on this node as well. Defaults to + * false. + * @param {boolean=} opt_childrenFirst Whether to call action on children before calling it on + * parent. + */ + forEachDescendant(action, opt_includeSelf, opt_childrenFirst) { + if (opt_includeSelf && !opt_childrenFirst) + action(this); + + this.forEachChild(function(child) { + child.forEachDescendant(action, /*opt_includeSelf=*/true, opt_childrenFirst); + }); + + if (opt_includeSelf && opt_childrenFirst) + action(this); + } + + /** + * Calls action on each ancestor node. + * + * @param {function(!Tree.)} action Action to be called on each parent; return + * true to abort. + * @param {boolean=} opt_includeSelf Whether to call action on this node as well. + * @return {boolean} true if the action callback returned true. + */ + forEachAncestor(action, opt_includeSelf) { + var node = opt_includeSelf ? this : this.parent(); + while (node !== null) { + if (action(node)) { + return true; + } + node = node.parent(); + } + return false; + } + + /** + * Does a depth-first traversal of this node's descendants. When a descendant with a value + * is found, action is called on it and traversal does not continue inside the node. + * Action is *not* called on this node. + * + * @param {function(!Tree.)} action Action to be called for each child. + */ + forEachImmediateDescendantWithValue(action) { + this.forEachChild(function(child) { + if (child.getValue() !== null) + action(child); + else + child.forEachImmediateDescendantWithValue(action); + }); + } + + /** + * @return {!Path} The path of this tree node, as a Path. + */ + path() { + return new Path(this.parent_ === null ? + this.name_ : this.parent_.path() + '/' + this.name_); + } + + /** + * @return {string} The name of the tree node. + */ + name() { + return this.name_; + } + + /** + * @return {?Tree} The parent tree node, or null if this is the root of the tree. + */ + parent() { + return this.parent_; + } + + /** + * Adds or removes this child from its parent based on whether it's empty or not. + * + * @private + */ + updateParents_() { + if (this.parent_ !== null) + this.parent_.updateChild_(this.name_, this); + } + + /** + * Adds or removes the passed child to this tree node, depending on whether it's empty. + * + * @param {string} childName The name of the child to update. + * @param {!Tree.} child The child to update. + * @private + */ + updateChild_(childName, child) { + var childEmpty = child.isEmpty(); + var childExists = contains(this.node_.children, childName); + if (childEmpty && childExists) { + delete (this.node_.children[childName]); + this.node_.childCount--; + this.updateParents_(); + } + else if (!childEmpty && !childExists) { + this.node_.children[childName] = child.node_; + this.node_.childCount++; + this.updateParents_(); + } + } +}; // end Tree diff --git a/src/database/core/util/VisibilityMonitor.ts b/src/database/core/util/VisibilityMonitor.ts new file mode 100644 index 00000000000..42d489650c0 --- /dev/null +++ b/src/database/core/util/VisibilityMonitor.ts @@ -0,0 +1,60 @@ +import { EventEmitter } from "./EventEmitter"; +import { assert } from "../../../utils/assert"; + +/** + * @extends {fb.core.util.EventEmitter} + */ +export class VisibilityMonitor extends EventEmitter { + visible_; + + static getInstance() { + return new VisibilityMonitor(); + } + + constructor() { + super(['visible']); + var hidden, visibilityChange; + if (typeof document !== 'undefined' && typeof document.addEventListener !== 'undefined') { + if (typeof document['hidden'] !== 'undefined') { + // Opera 12.10 and Firefox 18 and later support + visibilityChange = 'visibilitychange'; + hidden = 'hidden'; + } else if (typeof document['mozHidden'] !== 'undefined') { + visibilityChange = 'mozvisibilitychange'; + hidden = 'mozHidden'; + } else if (typeof document['msHidden'] !== 'undefined') { + visibilityChange = 'msvisibilitychange'; + hidden = 'msHidden'; + } else if (typeof document['webkitHidden'] !== 'undefined') { + visibilityChange = 'webkitvisibilitychange'; + hidden = 'webkitHidden'; + } + } + + // Initially, we always assume we are visible. This ensures that in browsers + // without page visibility support or in cases where we are never visible + // (e.g. chrome extension), we act as if we are visible, i.e. don't delay + // reconnects + this.visible_ = true; + + if (visibilityChange) { + var self = this; + document.addEventListener(visibilityChange, function() { + var visible = !document[hidden]; + if (visible !== self.visible_) { + self.visible_ = visible; + self.trigger('visible', visible); + } + }, false); + } + } + + /** + * @param {!string} eventType + * @return {Array.} + */ + getInitialEvent(eventType) { + assert(eventType === 'visible', 'Unknown event type: ' + eventType); + return [this.visible_]; + } +}; // end VisibilityMonitor \ No newline at end of file diff --git a/src/database/core/util/libs/parser.ts b/src/database/core/util/libs/parser.ts new file mode 100644 index 00000000000..593bc6e3826 --- /dev/null +++ b/src/database/core/util/libs/parser.ts @@ -0,0 +1,111 @@ +import { Path } from "../Path"; +import { RepoInfo } from "../../RepoInfo"; +import { warnIfPageIsSecure, fatal } from "../util"; + +/** + * @param {!string} pathString + * @return {string} + */ +function decodePath(pathString) { + var pathStringDecoded = ''; + var pieces = pathString.split('/'); + for (var i = 0; i < pieces.length; i++) { + if (pieces[i].length > 0) { + var piece = pieces[i]; + try { + piece = decodeURIComponent(piece.replace(/\+/g, " ")); + } catch (e) {} + pathStringDecoded += '/' + piece; + } + } + return pathStringDecoded; +}; + +/** + * + * @param {!string} dataURL + * @return {{repoInfo: !RepoInfo, path: !Path}} + */ +export const parseRepoInfo = function(dataURL) { + var parsedUrl = parseURL(dataURL), + namespace = parsedUrl.subdomain; + + if (parsedUrl.domain === 'firebase') { + fatal(parsedUrl.host + + ' is no longer supported. ' + + 'Please use .firebaseio.com instead'); + } + + // Catch common error of uninitialized namespace value. + if (!namespace || namespace == 'undefined') { + fatal('Cannot parse Firebase url. Please use https://.firebaseio.com'); + } + + if (!parsedUrl.secure) { + warnIfPageIsSecure(); + } + + var webSocketOnly = (parsedUrl.scheme === 'ws') || (parsedUrl.scheme === 'wss'); + + return { + repoInfo: new RepoInfo(parsedUrl.host, parsedUrl.secure, namespace, webSocketOnly), + path: new Path(parsedUrl.pathString) + }; +}; + +/** + * + * @param {!string} dataURL + * @return {{host: string, port: number, domain: string, subdomain: string, secure: boolean, scheme: string, pathString: string}} + */ +export const parseURL = function(dataURL) { + // Default to empty strings in the event of a malformed string. + var host = '', domain = '', subdomain = '', pathString = ''; + + // Always default to SSL, unless otherwise specified. + var secure = true, scheme = 'https', port = 443; + + // Don't do any validation here. The caller is responsible for validating the result of parsing. + if (typeof dataURL === 'string') { + // Parse scheme. + var colonInd = dataURL.indexOf('//'); + if (colonInd >= 0) { + scheme = dataURL.substring(0, colonInd - 1); + dataURL = dataURL.substring(colonInd + 2); + } + + // Parse host and path. + var slashInd = dataURL.indexOf('/'); + if (slashInd === -1) { + slashInd = dataURL.length; + } + host = dataURL.substring(0, slashInd); + pathString = decodePath(dataURL.substring(slashInd)); + + var parts = host.split('.'); + if (parts.length === 3) { + // Normalize namespaces to lowercase to share storage / connection. + domain = parts[1]; + subdomain = parts[0].toLowerCase(); + } else if (parts.length === 2) { + domain = parts[0]; + } + + // If we have a port, use scheme for determining if it's secure. + colonInd = host.indexOf(':'); + if (colonInd >= 0) { + secure = (scheme === 'https') || (scheme === 'wss'); + port = parseInt(host.substring(colonInd + 1), 10); + } + } + + return { + host: host, + port: port, + domain: domain, + subdomain: subdomain, + secure: secure, + scheme: scheme, + pathString: pathString + }; +}; \ No newline at end of file diff --git a/src/database/core/util/util.ts b/src/database/core/util/util.ts new file mode 100644 index 00000000000..6a33c737f38 --- /dev/null +++ b/src/database/core/util/util.ts @@ -0,0 +1,697 @@ +declare const Windows; + +import { assert } from '../../../utils/assert'; +import { forEach } from '../../../utils/obj'; +import { base64 } from '../../../utils/crypt'; +import { Sha1 } from '../../../utils/Sha1'; +import { + assert as _assert, + assertionError as _assertError +} from "../../../utils/assert"; +import { stringToByteArray } from "../../../utils/utf8"; +import { stringify } from "../../../utils/json"; +import { SessionStorage } from "../storage/storage"; +import { RepoInfo } from "../RepoInfo"; +import { isNodeSdk } from "../../../utils/environment"; + +/** + * Returns a locally-unique ID (generated by just incrementing up from 0 each time its called). + * @type {function(): number} Generated ID. + */ +export const LUIDGenerator = (function() { + var id = 1; + return function() { + return id++; + }; +})(); + +/** + * Same as fb.util.assert(), but forcefully logs instead of throws. + * @param {*} assertion The assertion to be tested for falsiness + * @param {!string} message The message to be logged on failure + */ +export const assertWeak = function(assertion, message) { + if (!assertion) { + error(message); + } +}; + + +/** + * URL-safe base64 encoding + * @param {!string} str + * @return {!string} + */ +export const base64Encode = function(str) { + var utf8Bytes = stringToByteArray(str); + return base64.encodeByteArray(utf8Bytes, /*useWebSafe=*/true); +}; + + +let BufferImpl; +export function setBufferImpl(impl) { + BufferImpl = impl; +} +/** + * URL-safe base64 decoding + * + * NOTE: DO NOT use the global atob() function - it does NOT support the + * base64Url variant encoding. + * + * @param {string} str To be decoded + * @return {?string} Decoded result, if possible + */ +export const base64Decode = function(str) { + try { + if (BufferImpl()) { + return new BufferImpl(str, 'base64').toString('utf8'); + } else { + return base64.decodeString(str, /*useWebSafe=*/true); + } + } catch (e) { + log('base64Decode failed: ', e); + } + return null; +}; + + +/** + * Sha1 hash of the input string + * @param {!string} str The string to hash + * @return {!string} The resulting hash + */ +export const sha1 = function(str) { + var utf8Bytes = stringToByteArray(str); + var sha1 = new Sha1(); + sha1.update(utf8Bytes); + var sha1Bytes = sha1.digest(); + return base64.encodeByteArray(sha1Bytes); +}; + + +/** + * @param {...*} var_args + * @return {string} + * @private + */ +export const buildLogMessage_ = function(var_args) { + var message = ''; + for (var i = 0; i < arguments.length; i++) { + if (Array.isArray(arguments[i]) || + (arguments[i] && typeof arguments[i] === 'object' && typeof arguments[i].length === 'number')) { + message += buildLogMessage_.apply(null, arguments[i]); + } + else if (typeof arguments[i] === 'object') { + message += stringify(arguments[i]); + } + else { + message += arguments[i]; + } + message += ' '; + } + + return message; +}; + + +/** + * Use this for all debug messages in Firebase. + * @type {?function(string)} + */ +export var logger = null; + + +/** + * Flag to check for log availability on first log message + * @type {boolean} + * @private + */ +export var firstLog_ = true; + + +/** + * The implementation of Firebase.enableLogging (defined here to break dependencies) + * @param {boolean|?function(string)} logger A flag to turn on logging, or a custom logger + * @param {boolean=} opt_persistent Whether or not to persist logging settings across refreshes + */ +export const enableLogging = function(logger, opt_persistent?) { + assert(!opt_persistent || (logger === true || logger === false), "Can't turn on custom loggers persistently."); + if (logger === true) { + if (typeof console !== 'undefined') { + if (typeof console.log === 'function') { + logger = console.log.bind(console); + } else if (typeof console.log === 'object') { + // IE does this. + logger = function(message) { console.log(message); }; + } + } + if (opt_persistent) + SessionStorage.set('logging_enabled', true); + } + else if (typeof logger === 'function') { + logger = logger; + } else { + logger = null; + SessionStorage.remove('logging_enabled'); + } +}; + + +/** + * + * @param {...(string|Arguments)} var_args + */ +export const log = function(...var_args) { + if (firstLog_ === true) { + firstLog_ = false; + if (logger === null && SessionStorage.get('logging_enabled') === true) + enableLogging(true); + } + + if (logger) { + var message = buildLogMessage_.apply(null, arguments); + logger(message); + } +}; + + +/** + * @param {!string} prefix + * @return {function(...[*])} + */ +export const logWrapper = function(prefix) { + return function() { + log(prefix, arguments); + }; +}; + + +/** + * @param {...string} var_args + */ +export const error = function(var_args) { + if (typeof console !== 'undefined') { + var message = 'FIREBASE INTERNAL ERROR: ' + + buildLogMessage_.apply(null, arguments); + if (typeof console.error !== 'undefined') { + console.error(message); + } else { + console.log(message); + } + } +}; + + +/** + * @param {...string} var_args + */ +export const fatal = function(var_args) { + var message = buildLogMessage_.apply(null, arguments); + throw new Error('FIREBASE FATAL ERROR: ' + message); +}; + + +/** + * @param {...*} var_args + */ +export const warn = function(...var_args) { + if (typeof console !== 'undefined') { + var message = 'FIREBASE WARNING: ' + buildLogMessage_.apply(null, arguments); + if (typeof console.warn !== 'undefined') { + console.warn(message); + } else { + console.log(message); + } + } +}; + + +/** + * Logs a warning if the containing page uses https. Called when a call to new Firebase + * does not use https. + */ +export const warnIfPageIsSecure = function() { + // Be very careful accessing browser globals. Who knows what may or may not exist. + if (typeof window !== 'undefined' && window.location && window.location.protocol && + window.location.protocol.indexOf('https:') !== -1) { + warn('Insecure Firebase access from a secure page. ' + + 'Please use https in calls to new Firebase().'); + } +}; + + +/** + * @param {!String} methodName + */ +export const warnAboutUnsupportedMethod = function(methodName) { + warn(methodName + + ' is unsupported and will likely change soon. ' + + 'Please do not use.'); +}; + + +/** + * Returns true if data is NaN, or +/- Infinity. + * @param {*} data + * @return {boolean} + */ +export const isInvalidJSONNumber = function(data) { + return typeof data === 'number' && + (data != data || // NaN + data == Number.POSITIVE_INFINITY || + data == Number.NEGATIVE_INFINITY); +}; + + +/** + * @param {function()} fn + */ +export const executeWhenDOMReady = function(fn) { + if (isNodeSdk() || document.readyState === 'complete') { + fn(); + } else { + // Modeled after jQuery. Try DOMContentLoaded and onreadystatechange (which + // fire before onload), but fall back to onload. + + var called = false; + let wrappedFn = function() { + if (!document.body) { + setTimeout(wrappedFn, Math.floor(10)); + return; + } + + if (!called) { + called = true; + fn(); + } + }; + + if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', wrappedFn, false); + // fallback to onload. + window.addEventListener('load', wrappedFn, false); + } else if ((document as any).attachEvent) { + // IE. + (document as any).attachEvent('onreadystatechange', + function() { + if (document.readyState === 'complete') + wrappedFn(); + } + ); + // fallback to onload. + (window as any).attachEvent('onload', wrappedFn); + + // jQuery has an extra hack for IE that we could employ (based on + // http://javascript.nwbox.com/IEContentLoaded/) But it looks really old. + // I'm hoping we don't need it. + } + } +}; + + +/** + * Minimum key name. Invalid for actual data, used as a marker to sort before any valid names + * @type {!string} + */ +export const MIN_NAME = '[MIN_NAME]'; + + +/** + * Maximum key name. Invalid for actual data, used as a marker to sort above any valid names + * @type {!string} + */ +export const MAX_NAME = '[MAX_NAME]'; + + +/** + * Compares valid Firebase key names, plus min and max name + * @param {!string} a + * @param {!string} b + * @return {!number} + */ +export const nameCompare = function(a, b) { + if (a === b) { + return 0; + } else if (a === MIN_NAME || b === MAX_NAME) { + return -1; + } else if (b === MIN_NAME || a === MAX_NAME) { + return 1; + } else { + var aAsInt = tryParseInt(a), + bAsInt = tryParseInt(b); + + if (aAsInt !== null) { + if (bAsInt !== null) { + return (aAsInt - bAsInt) == 0 ? (a.length - b.length) : (aAsInt - bAsInt); + } else { + return -1; + } + } else if (bAsInt !== null) { + return 1; + } else { + return (a < b) ? -1 : 1; + } + } +}; + + +/** + * @param {!string} a + * @param {!string} b + * @return {!number} comparison result. + */ +export const stringCompare = function(a, b) { + if (a === b) { + return 0; + } else if (a < b) { + return -1; + } else { + return 1; + } +}; + + +/** + * @param {string} key + * @param {Object} obj + * @return {*} + */ +export const requireKey = function(key, obj) { + if (obj && (key in obj)) { + return obj[key]; + } else { + throw new Error('Missing required key (' + key + ') in object: ' + stringify(obj)); + } +}; + + +/** + * @param {*} obj + * @return {string} + */ +export const ObjectToUniqueKey = function(obj) { + if (typeof obj !== 'object' || obj === null) + return stringify(obj); + + var keys = []; + for (var k in obj) { + keys.push(k); + } + + // Export as json, but with the keys sorted. + keys.sort(); + var key = '{'; + for (var i = 0; i < keys.length; i++) { + if (i !== 0) + key += ','; + key += stringify(keys[i]); + key += ':'; + key += ObjectToUniqueKey(obj[keys[i]]); + } + + key += '}'; + return key; +}; + + +/** + * Splits a string into a number of smaller segments of maximum size + * @param {!string} str The string + * @param {!number} segsize The maximum number of chars in the string. + * @return {Array.} The string, split into appropriately-sized chunks + */ +export const splitStringBySize = function(str, segsize) { + if (str.length <= segsize) { + return [str]; + } + + var dataSegs = []; + for (var c = 0; c < str.length; c += segsize) { + if (c + segsize > str) { + dataSegs.push(str.substring(c, str.length)); + } + else { + dataSegs.push(str.substring(c, c + segsize)); + } + } + return dataSegs; +}; + + +/** + * Apply a function to each (key, value) pair in an object or + * apply a function to each (index, value) pair in an array + * @param {!(Object|Array)} obj The object or array to iterate over + * @param {function(?, ?)} fn The function to apply + */ +export const each = function(obj, fn) { + if (Array.isArray(obj)) { + for (var i = 0; i < obj.length; ++i) { + fn(i, obj[i]); + } + } else { + /** + * in the conversion of code we removed the goog.object.forEach + * function which did a value,key callback. We standardized on + * a single impl that does a key, value callback. So we invert + * to not have to touch the `each` code points + */ + forEach(obj, (key, val) => fn(val, key)); + } +}; + + +/** + * Like goog.bind, but doesn't bother to create a closure if opt_context is null/undefined. + * @param {function(*)} callback Callback function. + * @param {?Object=} opt_context Optional context to bind to. + * @return {function(*)} + */ +export const bindCallback = function(callback, opt_context) { + return opt_context ? callback.bind(opt_context) : callback; +}; + + +/** + * Borrowed from http://hg.secondlife.com/llsd/src/tip/js/typedarray.js (MIT License) + * I made one modification at the end and removed the NaN / Infinity + * handling (since it seemed broken [caused an overflow] and we don't need it). See MJL comments. + * @param {!number} v A double + * @return {string} + */ +export const doubleToIEEE754String = function(v) { + assert(!isInvalidJSONNumber(v), 'Invalid JSON number'); // MJL + + var ebits = 11, fbits = 52; + var bias = (1 << (ebits - 1)) - 1, + s, e, f, ln, + i, bits, str, bytes; + + // Compute sign, exponent, fraction + // Skip NaN / Infinity handling --MJL. + if (v === 0) { + e = 0; f = 0; s = (1 / v === -Infinity) ? 1 : 0; + } + else { + s = v < 0; + v = Math.abs(v); + + if (v >= Math.pow(2, 1 - bias)) { + // Normalized + ln = Math.min(Math.floor(Math.log(v) / Math.LN2), bias); + e = ln + bias; + f = Math.round(v * Math.pow(2, fbits - ln) - Math.pow(2, fbits)); + } + else { + // Denormalized + e = 0; + f = Math.round(v / Math.pow(2, 1 - bias - fbits)); + } + } + + // Pack sign, exponent, fraction + bits = []; + for (i = fbits; i; i -= 1) { bits.push(f % 2 ? 1 : 0); f = Math.floor(f / 2); } + for (i = ebits; i; i -= 1) { bits.push(e % 2 ? 1 : 0); e = Math.floor(e / 2); } + bits.push(s ? 1 : 0); + bits.reverse(); + str = bits.join(''); + + // Return the data as a hex string. --MJL + var hexByteString = ''; + for (i = 0; i < 64; i += 8) { + var hexByte = parseInt(str.substr(i, 8), 2).toString(16); + if (hexByte.length === 1) + hexByte = '0' + hexByte; + hexByteString = hexByteString + hexByte; + } + return hexByteString.toLowerCase(); +}; + + +/** + * Used to detect if we're in a Chrome content script (which executes in an + * isolated environment where long-polling doesn't work). + * @return {boolean} + */ +export const isChromeExtensionContentScript = function() { + return !!(typeof window === 'object' && + window['chrome'] && + window['chrome']['extension'] && + !/^chrome/.test(window.location.href) + ); +}; + + +/** + * Used to detect if we're in a Windows 8 Store app. + * @return {boolean} + */ +export const isWindowsStoreApp = function() { + // Check for the presence of a couple WinRT globals + return typeof Windows === 'object' && typeof Windows.UI === 'object'; +}; + + +/** + * Converts a server error code to a Javascript Error + * @param {!string} code + * @param {!fb.api.Query} query + * @return {Error} + */ +export const errorForServerCode = function(code, query) { + var reason = 'Unknown Error'; + if (code === 'too_big') { + reason = 'The data requested exceeds the maximum size ' + + 'that can be accessed with a single request.'; + } else if (code == 'permission_denied') { + reason = "Client doesn't have permission to access the desired data."; + } else if (code == 'unavailable') { + reason = 'The service is unavailable'; + } + + var error = new Error(code + ' at ' + query.path.toString() + ': ' + reason); + (error as any).code = code.toUpperCase(); + return error; +}; + + +/** + * Used to test for integer-looking strings + * @type {RegExp} + * @private + */ +export const INTEGER_REGEXP_ = new RegExp('^-?\\d{1,10}$'); + + +/** + * If the string contains a 32-bit integer, return it. Else return null. + * @param {!string} str + * @return {?number} + */ +export const tryParseInt = function(str) { + if (INTEGER_REGEXP_.test(str)) { + var intVal = Number(str); + if (intVal >= -2147483648 && intVal <= 2147483647) { + return intVal; + } + } + return null; +}; + + +/** + * Helper to run some code but catch any exceptions and re-throw them later. + * Useful for preventing user callbacks from breaking internal code. + * + * Re-throwing the exception from a setTimeout is a little evil, but it's very + * convenient (we don't have to try to figure out when is a safe point to + * re-throw it), and the behavior seems reasonable: + * + * * If you aren't pausing on exceptions, you get an error in the console with + * the correct stack trace. + * * If you're pausing on all exceptions, the debugger will pause on your + * exception and then again when we rethrow it. + * * If you're only pausing on uncaught exceptions, the debugger will only pause + * on us re-throwing it. + * + * @param {!function()} fn The code to guard. + */ +export const exceptionGuard = function(fn) { + try { + fn(); + } catch (e) { + // Re-throw exception when it's safe. + setTimeout(function() { + // It used to be that "throw e" would result in a good console error with + // relevant context, but as of Chrome 39, you just get the firebase.js + // file/line number where we re-throw it, which is useless. So we log + // e.stack explicitly. + var stack = e.stack || ''; + warn('Exception was thrown by user callback.', stack); + throw e; + }, Math.floor(0)); + } +}; + + +/** + * Helper function to safely call opt_callback with the specified arguments. It: + * 1. Turns into a no-op if opt_callback is null or undefined. + * 2. Wraps the call inside exceptionGuard to prevent exceptions from breaking our state. + * + * @param {?Function=} opt_callback Optional onComplete callback. + * @param {...*} var_args Arbitrary args to be passed to opt_onComplete + */ +export const callUserCallback = function(opt_callback, var_args) { + if (typeof opt_callback === 'function') { + var args = Array.prototype.slice.call(arguments, 1); + var newArgs = args.slice(); + exceptionGuard(function() { + opt_callback.apply(null, newArgs); + }); + } +}; + + +/** + * @return {boolean} true if we think we're currently being crawled. +*/ +export const beingCrawled = function() { + var userAgent = (typeof window === 'object' && window['navigator'] && window['navigator']['userAgent']) || ''; + + // For now we whitelist the most popular crawlers. We should refine this to be the set of crawlers we + // believe to support JavaScript/AJAX rendering. + // NOTE: Google Webmaster Tools doesn't really belong, but their "This is how a visitor to your website + // would have seen the page" is flaky if we don't treat it as a crawler. + return userAgent.search(/googlebot|google webmaster tools|bingbot|yahoo! slurp|baiduspider|yandexbot|duckduckbot/i) >= + 0; +}; + +/** + * Export a property of an object using a getter function. + * + * @param {!Object} object + * @param {string} name + * @param {!function(): *} fnGet + */ +export const exportPropGetter = function(object, name, fnGet) { + Object.defineProperty(object, name, {get: fnGet}); +}; + +/** + * Same as setTimeout() except on Node.JS it will /not/ prevent the process from exiting. + * + * It is removed with clearTimeout() as normal. + * + * @param fn {Function} Function to run. + * @param time {number} Milliseconds to wait before running. + * @return {number|Object} The setTimeout() return value. + */ +export const setTimeoutNonBlocking = function(fn, time) { + var timeout = setTimeout(fn, time); + if (typeof timeout === 'object' && timeout['unref']) { + timeout['unref'](); + } + return timeout; +}; diff --git a/src/database/core/util/validation.ts b/src/database/core/util/validation.ts new file mode 100644 index 00000000000..73305e471d0 --- /dev/null +++ b/src/database/core/util/validation.ts @@ -0,0 +1,380 @@ +import { Path, ValidationPath } from "./Path"; +import { forEach, contains, safeGet } from "../../../utils/obj"; +import { isInvalidJSONNumber } from "./util"; +import { errorPrefix as errorPrefixFxn } from "../../../utils/validation"; +import { stringLength } from "../../../utils/utf8"; + +/** + * True for invalid Firebase keys + * @type {RegExp} + * @private + */ +export const INVALID_KEY_REGEX_ = /[\[\].#$\/\u0000-\u001F\u007F]/; + +/** + * True for invalid Firebase paths. + * Allows '/' in paths. + * @type {RegExp} + * @private + */ +export const INVALID_PATH_REGEX_ = /[\[\].#$\u0000-\u001F\u007F]/; + +/** + * Maximum number of characters to allow in leaf value + * @type {number} + * @private + */ +export const MAX_LEAF_SIZE_ = 10 * 1024 * 1024; + + +/** + * @param {*} key + * @return {boolean} + */ +export const isValidKey = function(key) { + return typeof key === 'string' && key.length !== 0 && + !INVALID_KEY_REGEX_.test(key); +} + +/** + * @param {string} pathString + * @return {boolean} + */ +export const isValidPathString = function(pathString) { + return typeof pathString === 'string' && pathString.length !== 0 && + !INVALID_PATH_REGEX_.test(pathString); +} + +/** + * @param {string} pathString + * @return {boolean} + */ +export const isValidRootPathString = function(pathString) { + if (pathString) { + // Allow '/.info/' at the beginning. + pathString = pathString.replace(/^\/*\.info(\/|$)/, '/'); + } + + return isValidPathString(pathString); +} + +/** + * @param {*} priority + * @return {boolean} + */ +export const isValidPriority = function(priority) { + return priority === null || + typeof priority === 'string' || + (typeof priority === 'number' && !isInvalidJSONNumber(priority)) || + ((priority && typeof priority === 'object') && contains(priority, '.sv')); +} + +/** + * Pre-validate a datum passed as an argument to Firebase function. + * + * @param {string} fnName + * @param {number} argumentNumber + * @param {*} data + * @param {!Path} path + * @param {boolean} optional + */ +export const validateFirebaseDataArg = function(fnName, argumentNumber, data, path, optional) { + if (optional && data === undefined) + return; + + validateFirebaseData( + errorPrefixFxn(fnName, argumentNumber, optional), + data, path + ); +} + +/** + * Validate a data object client-side before sending to server. + * + * @param {string} errorPrefix + * @param {*} data + * @param {!Path|!ValidationPath} path + */ +export const validateFirebaseData = function(errorPrefix, data, path) { + if (path instanceof Path) { + path = new ValidationPath(path, errorPrefix); + } + + if (data === undefined) { + throw new Error(errorPrefix + 'contains undefined ' + path.toErrorString()); + } + if (typeof data === 'function') { + throw new Error(errorPrefix + 'contains a function ' + path.toErrorString() + + ' with contents = ' + data.toString()); + } + if (isInvalidJSONNumber(data)) { + throw new Error(errorPrefix + 'contains ' + data.toString() + ' ' + path.toErrorString()); + } + + // Check max leaf size, but try to avoid the utf8 conversion if we can. + if (typeof data === 'string' && + data.length > MAX_LEAF_SIZE_ / 3 && + stringLength(data) > MAX_LEAF_SIZE_) { + throw new Error(errorPrefix + 'contains a string greater than ' + + MAX_LEAF_SIZE_ + + ' utf8 bytes ' + path.toErrorString() + + " ('" + data.substring(0, 50) + "...')"); + } + + // TODO = Perf = Consider combining the recursive validation of keys into NodeFromJSON + // to save extra walking of large objects. + if ((data && typeof data === 'object')) { + var hasDotValue = false, hasActualChild = false; + forEach(data, function(key, value) { + if (key === '.value') { + hasDotValue = true; + } + else if (key !== '.priority' && key !== '.sv') { + hasActualChild = true; + if (!isValidKey(key)) { + throw new Error(errorPrefix + ' contains an invalid key (' + key + ') ' + + path.toErrorString() + + '. Keys must be non-empty strings ' + + 'and can\'t contain ".", "#", "$", "/", "[", or "]"'); + } + } + + path.push(key); + validateFirebaseData(errorPrefix, value, path); + path.pop(); + }); + + if (hasDotValue && hasActualChild) { + throw new Error(errorPrefix + ' contains ".value" child ' + + path.toErrorString() + + ' in addition to actual children.'); + } + } +} + +/** + * Pre-validate paths passed in the firebase function. + * + * @param {string} errorPrefix + * @param {Array} mergePaths + */ +export const validateFirebaseMergePaths = function(errorPrefix, mergePaths) { + var i, curPath; + for (i = 0; i < mergePaths.length; i++) { + curPath = mergePaths[i]; + var keys = curPath.slice(); + for (var j = 0; j < keys.length; j++) { + if (keys[j] === '.priority' && j === (keys.length - 1)) { + // .priority is OK + } else if (!isValidKey(keys[j])) { + throw new Error(errorPrefix + 'contains an invalid key (' + keys[j] + ') in path ' + + curPath.toString() + + '. Keys must be non-empty strings ' + + 'and can\'t contain ".", "#", "$", "/", "[", or "]"'); + } + } + } + + // Check that update keys are not descendants of each other. + // We rely on the property that sorting guarantees that ancestors come + // right before descendants. + mergePaths.sort(Path.comparePaths); + var prevPath = null; + for (i = 0; i < mergePaths.length; i++) { + curPath = mergePaths[i]; + if (prevPath !== null && prevPath.contains(curPath)) { + throw new Error(errorPrefix + 'contains a path ' + prevPath.toString() + + ' that is ancestor of another path ' + curPath.toString()); + } + prevPath = curPath; + } +} + +/** + * pre-validate an object passed as an argument to firebase function ( + * must be an object - e.g. for firebase.update()). + * + * @param {string} fnName + * @param {number} argumentNumber + * @param {*} data + * @param {!Path} path + * @param {boolean} optional + */ +export const validateFirebaseMergeDataArg = function(fnName, argumentNumber, data, path, optional) { + if (optional && data === undefined) + return; + + var errorPrefix = errorPrefixFxn(fnName, argumentNumber, optional); + + if (!(data && typeof data === 'object') || Array.isArray(data)) { + throw new Error(errorPrefix + ' must be an object containing the children to replace.'); + } + + var mergePaths = []; + forEach(data, function(key, value) { + var curPath = new Path(key); + validateFirebaseData(errorPrefix, value, path.child(curPath)); + if (curPath.getBack() === '.priority') { + if (!isValidPriority(value)) { + throw new Error( + errorPrefix + 'contains an invalid value for \'' + curPath.toString() + '\', which must be a valid ' + + 'Firebase priority (a string, finite number, server value, or null).'); + } + } + mergePaths.push(curPath); + }); + validateFirebaseMergePaths(errorPrefix, mergePaths); +} + +export const validatePriority = function(fnName, argumentNumber, priority, optional) { + if (optional && priority === undefined) + return; + if (isInvalidJSONNumber(priority)) + throw new Error( + errorPrefixFxn(fnName, argumentNumber, optional) + + 'is ' + priority.toString() + + ', but must be a valid Firebase priority (a string, finite number, ' + + 'server value, or null).'); + // Special case to allow importing data with a .sv. + if (!isValidPriority(priority)) + throw new Error( + errorPrefixFxn(fnName, argumentNumber, optional) + + 'must be a valid Firebase priority ' + + '(a string, finite number, server value, or null).'); +} + +export const validateEventType = function(fnName, argumentNumber, eventType, optional) { + if (optional && eventType === undefined) + return; + + switch (eventType) { + case 'value': + case 'child_added': + case 'child_removed': + case 'child_changed': + case 'child_moved': + break; + default: + throw new Error( + errorPrefixFxn(fnName, argumentNumber, optional) + + 'must be a valid event type = "value", "child_added", "child_removed", ' + + '"child_changed", or "child_moved".'); + } +} + +export const validateKey = function(fnName, argumentNumber, key, optional) { + if (optional && key === undefined) + return; + if (!isValidKey(key)) + throw new Error(errorPrefixFxn(fnName, argumentNumber, optional) + + 'was an invalid key = "' + key + + '". Firebase keys must be non-empty strings and ' + + 'can\'t contain ".", "#", "$", "/", "[", or "]").'); +} + +export const validatePathString = function(fnName, argumentNumber, pathString, optional) { + if (optional && pathString === undefined) + return; + + if (!isValidPathString(pathString)) + throw new Error(errorPrefixFxn(fnName, argumentNumber, optional) + + 'was an invalid path = "' + + pathString + + '". Paths must be non-empty strings and ' + + 'can\'t contain ".", "#", "$", "[", or "]"'); +} + +export const validateRootPathString = function(fnName, argumentNumber, pathString, optional) { + if (pathString) { + // Allow '/.info/' at the beginning. + pathString = pathString.replace(/^\/*\.info(\/|$)/, '/'); + } + + validatePathString(fnName, argumentNumber, pathString, optional); +} + +export const validateWritablePath = function(fnName, path) { + if (path.getFront() === '.info') { + throw new Error(fnName + ' failed = Can\'t modify data under /.info/'); + } +} + +export const validateUrl = function(fnName, argumentNumber, parsedUrl) { + // TODO = Validate server better. + var pathString = parsedUrl.path.toString(); + if (!(typeof parsedUrl.repoInfo.host === 'string') || parsedUrl.repoInfo.host.length === 0 || + !isValidKey(parsedUrl.repoInfo.namespace) || + (pathString.length !== 0 && !isValidRootPathString(pathString))) { + throw new Error(errorPrefixFxn(fnName, argumentNumber, false) + + 'must be a valid firebase URL and ' + + 'the path can\'t contain ".", "#", "$", "[", or "]".'); + } +} + +export const validateCredential = function(fnName, argumentNumber, cred, optional) { + if (optional && cred === undefined) + return; + if (!(typeof cred === 'string')) + throw new Error( + errorPrefixFxn(fnName, argumentNumber, optional) + + 'must be a valid credential (a string).'); +} + +export const validateBoolean = function(fnName, argumentNumber, bool, optional) { + if (optional && bool === undefined) + return; + if (typeof bool !== 'boolean') + throw new Error(errorPrefixFxn(fnName, argumentNumber, optional) + + 'must be a boolean.'); +} + +export const validateString = function(fnName, argumentNumber, string, optional) { + if (optional && string === undefined) + return; + if (!(typeof string === 'string')) { + throw new Error( + errorPrefixFxn(fnName, argumentNumber, optional) + + 'must be a valid string.'); + } +} + +export const validateObject = function(fnName, argumentNumber, obj, optional) { + if (optional && obj === undefined) + return; + if (!(obj && typeof obj === 'object') || obj === null) { + throw new Error( + errorPrefixFxn(fnName, argumentNumber, optional) + + 'must be a valid object.'); + } +} + +export const validateObjectContainsKey = function(fnName, argumentNumber, obj, key, optional, opt_type) { + var objectContainsKey = ((obj && typeof obj === 'object') && contains(obj, key)); + + if (!objectContainsKey) { + if (optional) { + return; + } else { + throw new Error( + errorPrefixFxn(fnName, argumentNumber, optional) + + 'must contain the key "' + key + '"'); + } + } + + if (opt_type) { + var val = safeGet(obj, key); + if ((opt_type === 'number' && !(typeof val === 'number')) || + (opt_type === 'string' && !(typeof val === 'string')) || + (opt_type === 'boolean' && !(typeof val === 'boolean')) || + (opt_type === 'function' && !(typeof val === 'function')) || + (opt_type === 'object' && !(typeof val === 'object') && val)) { + if (optional) { + throw new Error(errorPrefixFxn(fnName, argumentNumber, optional) + + 'contains invalid value for key "' + key + '" (must be of type "' + opt_type + '")'); + } else { + throw new Error(errorPrefixFxn(fnName, argumentNumber, optional) + + 'must contain the key "' + key + '" with type "' + opt_type + '"'); + } + } + } +} diff --git a/src/database/core/view/CacheNode.ts b/src/database/core/view/CacheNode.ts new file mode 100644 index 00000000000..db24e74a7c7 --- /dev/null +++ b/src/database/core/view/CacheNode.ts @@ -0,0 +1,66 @@ +import { Node } from '../snap/Node'; +import { Path } from '../util/Path'; + +/** + * A cache node only stores complete children. Additionally it holds a flag whether the node can be considered fully + * initialized in the sense that we know at one point in time this represented a valid state of the world, e.g. + * initialized with data from the server, or a complete overwrite by the client. The filtered flag also tracks + * whether a node potentially had children removed due to a filter. + */ +export class CacheNode { + /** + * @param {!Node} node_ + * @param {boolean} fullyInitialized_ + * @param {boolean} filtered_ + */ + constructor(private node_: Node, + private fullyInitialized_: boolean, + private filtered_: boolean) { + + } + + /** + * Returns whether this node was fully initialized with either server data or a complete overwrite by the client + * @return {boolean} + */ + isFullyInitialized(): boolean { + return this.fullyInitialized_; + } + + /** + * Returns whether this node is potentially missing children due to a filter applied to the node + * @return {boolean} + */ + isFiltered(): boolean { + return this.filtered_; + } + + /** + * @param {!Path} path + * @return {boolean} + */ + isCompleteForPath(path: Path): boolean { + if (path.isEmpty()) { + return this.isFullyInitialized() && !this.filtered_; + } + + const childKey = path.getFront(); + return this.isCompleteForChild(childKey); + } + + /** + * @param {!string} key + * @return {boolean} + */ + isCompleteForChild(key: string): boolean { + return (this.isFullyInitialized() && !this.filtered_) || this.node_.hasChild(key); + } + + /** + * @return {!Node} + */ + getNode(): Node { + return this.node_; + } + +} diff --git a/src/database/core/view/Change.ts b/src/database/core/view/Change.ts new file mode 100644 index 00000000000..8f9396849a4 --- /dev/null +++ b/src/database/core/view/Change.ts @@ -0,0 +1,81 @@ +import { Node } from '../snap/Node'; + +/** + * @constructor + * @struct + * @param {!string} type The event type + * @param {!Node} snapshotNode The data + * @param {string=} childName The name for this child, if it's a child event + * @param {Node=} oldSnap Used for intermediate processing of child changed events + * @param {string=} prevName The name for the previous child, if applicable + */ +export class Change { + constructor(public type: string, + public snapshotNode: Node, + public childName?: string, + public oldSnap?: Node, + public prevName?: string) { + }; + + /** + * @param {!Node} snapshot + * @return {!Change} + */ + static valueChange(snapshot: Node): Change { + return new Change(Change.VALUE, snapshot); + }; + + /** + * @param {string} childKey + * @param {!Node} snapshot + * @return {!Change} + */ + static childAddedChange(childKey: string, snapshot: Node): Change { + return new Change(Change.CHILD_ADDED, snapshot, childKey); + }; + + /** + * @param {string} childKey + * @param {!Node} snapshot + * @return {!Change} + */ + static childRemovedChange(childKey: string, snapshot: Node): Change { + return new Change(Change.CHILD_REMOVED, snapshot, childKey); + }; + + /** + * @param {string} childKey + * @param {!Node} newSnapshot + * @param {!Node} oldSnapshot + * @return {!Change} + */ + static childChangedChange(childKey: string, newSnapshot: Node, oldSnapshot: Node): Change { + return new Change(Change.CHILD_CHANGED, newSnapshot, childKey, oldSnapshot); + }; + + /** + * @param {string} childKey + * @param {!Node} snapshot + * @return {!Change} + */ + static childMovedChange(childKey: string, snapshot: Node): Change { + return new Change(Change.CHILD_MOVED, snapshot, childKey); + }; + + //event types + /** Event type for a child added */ + static CHILD_ADDED = 'child_added'; + + /** Event type for a child removed */ + static CHILD_REMOVED = 'child_removed'; + + /** Event type for a child changed */ + static CHILD_CHANGED = 'child_changed'; + + /** Event type for a child moved */ + static CHILD_MOVED = 'child_moved'; + + /** Event type for a value change */ + static VALUE = 'value'; +} + diff --git a/src/database/core/view/ChildChangeAccumulator.ts b/src/database/core/view/ChildChangeAccumulator.ts new file mode 100644 index 00000000000..ae082bf2c2f --- /dev/null +++ b/src/database/core/view/ChildChangeAccumulator.ts @@ -0,0 +1,53 @@ +import { getValues, safeGet } from '../../../utils/obj'; +import { Change } from "./Change"; +import { assert, assertionError } from "../../../utils/assert"; + +/** + * @constructor + */ +export class ChildChangeAccumulator { + changeMap_ = {}; + + /** + * @param {!Change} change + */ + trackChildChange(change: Change) { + const type = change.type; + const childKey = /** @type {!string} */ (change.childName); + assert(type == Change.CHILD_ADDED || + type == Change.CHILD_CHANGED || + type == Change.CHILD_REMOVED, 'Only child changes supported for tracking'); + assert(childKey !== '.priority', 'Only non-priority child changes can be tracked.'); + const oldChange = safeGet(this.changeMap_, childKey); + if (oldChange) { + const oldType = oldChange.type; + if (type == Change.CHILD_ADDED && oldType == Change.CHILD_REMOVED) { + this.changeMap_[childKey] = Change.childChangedChange(childKey, change.snapshotNode, oldChange.snapshotNode); + } else if (type == Change.CHILD_REMOVED && oldType == Change.CHILD_ADDED) { + delete this.changeMap_[childKey]; + } else if (type == Change.CHILD_REMOVED && oldType == Change.CHILD_CHANGED) { + this.changeMap_[childKey] = Change.childRemovedChange(childKey, + /** @type {!Node} */ (oldChange.oldSnap)); + } else if (type == Change.CHILD_CHANGED && oldType == Change.CHILD_ADDED) { + this.changeMap_[childKey] = Change.childAddedChange(childKey, change.snapshotNode); + } else if (type == Change.CHILD_CHANGED && oldType == Change.CHILD_CHANGED) { + this.changeMap_[childKey] = Change.childChangedChange(childKey, change.snapshotNode, + /** @type {!Node} */ (oldChange.oldSnap)); + } else { + throw assertionError('Illegal combination of changes: ' + change + ' occurred after ' + oldChange); + } + } else { + this.changeMap_[childKey] = change; + } + }; + + + /** + * @return {!Array.} + */ + getChanges(): Change[] { + return getValues(this.changeMap_); + }; +} + + diff --git a/src/database/core/view/CompleteChildSource.ts b/src/database/core/view/CompleteChildSource.ts new file mode 100644 index 00000000000..18f5602614d --- /dev/null +++ b/src/database/core/view/CompleteChildSource.ts @@ -0,0 +1,110 @@ +import { CacheNode } from './CacheNode'; +import { NamedNode, Node } from '../snap/Node'; +import { Index } from '../snap/indexes/Index'; +import { WriteTreeRef } from '../WriteTree'; +import { ViewCache } from './ViewCache'; + +/** + * Since updates to filtered nodes might require nodes to be pulled in from "outside" the node, this interface + * can help to get complete children that can be pulled in. + * A class implementing this interface takes potentially multiple sources (e.g. user writes, server data from + * other views etc.) to try it's best to get a complete child that might be useful in pulling into the view. + * + * @interface + */ +export interface CompleteChildSource { + /** + * @param {!string} childKey + * @return {?Node} + */ + getCompleteChild(childKey: string): Node | null; + + /** + * @param {!Index} index + * @param {!NamedNode} child + * @param {boolean} reverse + * @return {?NamedNode} + */ + getChildAfterChild(index: Index, child: NamedNode, reverse: boolean): NamedNode | null; +} + + +/** + * An implementation of CompleteChildSource that never returns any additional children + * + * @private + * @constructor + * @implements CompleteChildSource + */ +export class NoCompleteChildSource_ implements CompleteChildSource { + + /** + * @inheritDoc + */ + getCompleteChild() { + return null; + } + + /** + * @inheritDoc + */ + getChildAfterChild() { + return null; + } +} + + +/** + * Singleton instance. + * @const + * @type {!CompleteChildSource} + */ +export const NO_COMPLETE_CHILD_SOURCE = new NoCompleteChildSource_(); + + +/** + * An implementation of CompleteChildSource that uses a WriteTree in addition to any other server data or + * old event caches available to calculate complete children. + * + * + * @implements CompleteChildSource + */ +export class WriteTreeCompleteChildSource implements CompleteChildSource { + /** + * @param {!WriteTreeRef} writes_ + * @param {!ViewCache} viewCache_ + * @param {?Node} optCompleteServerCache_ + */ + constructor(private writes_: WriteTreeRef, + private viewCache_: ViewCache, + private optCompleteServerCache_: Node | null = null) { + } + + /** + * @inheritDoc + */ + getCompleteChild(childKey) { + const node = this.viewCache_.getEventCache(); + if (node.isCompleteForChild(childKey)) { + return node.getNode().getImmediateChild(childKey); + } else { + const serverNode = this.optCompleteServerCache_ != null ? + new CacheNode(this.optCompleteServerCache_, true, false) : this.viewCache_.getServerCache(); + return this.writes_.calcCompleteChild(childKey, serverNode); + } + } + + /** + * @inheritDoc + */ + getChildAfterChild(index, child, reverse) { + const completeServerData = this.optCompleteServerCache_ != null ? this.optCompleteServerCache_ : + this.viewCache_.getCompleteServerSnap(); + const nodes = this.writes_.calcIndexedSlice(completeServerData, child, 1, reverse, index); + if (nodes.length === 0) { + return null; + } else { + return nodes[0]; + } + } +} diff --git a/src/database/core/view/Event.ts b/src/database/core/view/Event.ts new file mode 100644 index 00000000000..a18729e1538 --- /dev/null +++ b/src/database/core/view/Event.ts @@ -0,0 +1,124 @@ +import { stringify } from '../../../utils/json'; +import { Path } from '../util/Path'; +import { EventRegistration } from './EventRegistration'; +import { DataSnapshot } from '../../api/DataSnapshot'; + +/** + * Encapsulates the data needed to raise an event + * @interface + */ +export interface Event { + /** + * @return {!Path} + */ + getPath(): Path; + + /** + * @return {!string} + */ + getEventType(): string; + + /** + * @return {!function()} + */ + getEventRunner(): () => void; + + /** + * @return {!string} + */ + toString(): string; +} + + +/** + * Encapsulates the data needed to raise an event + * @implements {Event} + */ +export class DataEvent implements Event { + /** + * @param {!string} eventType One of: value, child_added, child_changed, child_moved, child_removed + * @param {!EventRegistration} eventRegistration The function to call to with the event data. User provided + * @param {!DataSnapshot} snapshot The data backing the event + * @param {?string=} prevName Optional, the name of the previous child for child_* events. + */ + constructor(public eventType: 'value' | ' child_added' | ' child_changed' | ' child_moved' | ' child_removed', + public eventRegistration: EventRegistration, + public snapshot: DataSnapshot, + public prevName?: string | null) { + } + + /** + * @inheritDoc + */ + getPath(): Path { + const ref = this.snapshot.getRef(); + if (this.eventType === 'value') { + return ref.path; + } else { + return ref.getParent().path; + } + } + + /** + * @inheritDoc + */ + getEventType(): string { + return this.eventType; + } + + /** + * @inheritDoc + */ + getEventRunner(): () => void { + return this.eventRegistration.getEventRunner(this); + } + + /** + * @inheritDoc + */ + toString(): string { + return this.getPath().toString() + ':' + this.eventType + ':' + + stringify(this.snapshot.exportVal()); + } +} + + +export class CancelEvent implements Event { + /** + * @param {EventRegistration} eventRegistration + * @param {Error} error + * @param {!Path} path + */ + constructor(public eventRegistration: EventRegistration, + public error: Error, + public path: Path) { + } + + /** + * @inheritDoc + */ + getPath(): Path { + return this.path; + } + + /** + * @inheritDoc + */ + getEventType(): string { + return 'cancel'; + } + + /** + * @inheritDoc + */ + getEventRunner(): () => any { + return this.eventRegistration.getEventRunner(this); + } + + /** + * @inheritDoc + */ + toString(): string { + return this.path.toString() + ':cancel'; + } +} diff --git a/src/database/core/view/EventGenerator.ts b/src/database/core/view/EventGenerator.ts new file mode 100644 index 00000000000..9ef6061a4a5 --- /dev/null +++ b/src/database/core/view/EventGenerator.ts @@ -0,0 +1,117 @@ +import { NamedNode, Node } from '../snap/Node'; +import { Change } from "./Change"; +import { assertionError } from "../../../utils/assert"; +import { Query } from '../../api/Query'; +import { Index } from '../snap/indexes/Index'; +import { EventRegistration } from './EventRegistration'; +import { Event } from './Event'; + +/** + * An EventGenerator is used to convert "raw" changes (Change) as computed by the + * CacheDiffer into actual events (Event) that can be raised. See generateEventsForChanges() + * for details. + * + * @param {!Query} query + * @constructor + */ +export class EventGenerator { + private index_: Index; + + constructor(private query_: Query) { + /** + * @private + * @type {!Index} + */ + this.index_ = this.query_.getQueryParams().getIndex(); + } + + /** + * Given a set of raw changes (no moved events and prevName not specified yet), and a set of + * EventRegistrations that should be notified of these changes, generate the actual events to be raised. + * + * Notes: + * - child_moved events will be synthesized at this time for any child_changed events that affect + * our index. + * - prevName will be calculated based on the index ordering. + * + * @param {!Array.} changes + * @param {!Node} eventCache + * @param {!Array.} eventRegistrations + * @return {!Array.} + */ + generateEventsForChanges(changes: Change[], eventCache: Node, eventRegistrations: EventRegistration[]): Event[] { + const events = []; + const moves = []; + + changes.forEach((change) => { + if (change.type === Change.CHILD_CHANGED && + this.index_.indexedValueChanged(/** @type {!Node} */ (change.oldSnap), change.snapshotNode)) { + moves.push(Change.childMovedChange(/** @type {!string} */ (change.childName), change.snapshotNode)); + } + }); + + this.generateEventsForType_(events, Change.CHILD_REMOVED, changes, eventRegistrations, eventCache); + this.generateEventsForType_(events, Change.CHILD_ADDED, changes, eventRegistrations, eventCache); + this.generateEventsForType_(events, Change.CHILD_MOVED, moves, eventRegistrations, eventCache); + this.generateEventsForType_(events, Change.CHILD_CHANGED, changes, eventRegistrations, eventCache); + this.generateEventsForType_(events, Change.VALUE, changes, eventRegistrations, eventCache); + + return events; + } + + /** + * Given changes of a single change type, generate the corresponding events. + * + * @param {!Array.} events + * @param {!string} eventType + * @param {!Array.} changes + * @param {!Array.} registrations + * @param {!Node} eventCache + * @private + */ + private generateEventsForType_(events: Event[], eventType: string, changes: Change[], + registrations: EventRegistration[], eventCache: Node) { + const filteredChanges = changes.filter((change) => change.type === eventType); + + filteredChanges.sort(this.compareChanges_.bind(this)); + filteredChanges.forEach((change) => { + const materializedChange = this.materializeSingleChange_(change, eventCache); + registrations.forEach((registration) => { + if (registration.respondsTo(change.type)) { + events.push(registration.createEvent(materializedChange, this.query_)); + } + }); + }); + } + + /** + * @param {!Change} change + * @param {!Node} eventCache + * @return {!Change} + * @private + */ + private materializeSingleChange_(change: Change, eventCache: Node): Change { + if (change.type === 'value' || change.type === 'child_removed') { + return change; + } else { + change.prevName = eventCache.getPredecessorChildName(/** @type {!string} */ (change.childName), change.snapshotNode, + this.index_); + return change; + } + } + + /** + * @param {!Change} a + * @param {!Change} b + * @return {number} + * @private + */ + private compareChanges_(a: Change, b: Change) { + if (a.childName == null || b.childName == null) { + throw assertionError('Should only compare child_ events.'); + } + const aWrapped = new NamedNode(a.childName, a.snapshotNode); + const bWrapped = new NamedNode(b.childName, b.snapshotNode); + return this.index_.compare(aWrapped, bWrapped); + } +} diff --git a/src/database/core/view/EventQueue.ts b/src/database/core/view/EventQueue.ts new file mode 100644 index 00000000000..2fd51ddb91a --- /dev/null +++ b/src/database/core/view/EventQueue.ts @@ -0,0 +1,165 @@ +import { Path } from '../util/Path'; +import { log, logger, exceptionGuard } from '../util/util'; +import { Event } from './Event'; + +/** + * The event queue serves a few purposes: + * 1. It ensures we maintain event order in the face of event callbacks doing operations that result in more + * events being queued. + * 2. raiseQueuedEvents() handles being called reentrantly nicely. That is, if in the course of raising events, + * raiseQueuedEvents() is called again, the "inner" call will pick up raising events where the "outer" call + * left off, ensuring that the events are still raised synchronously and in order. + * 3. You can use raiseEventsAtPath and raiseEventsForChangedPath to ensure only relevant previously-queued + * events are raised synchronously. + * + * NOTE: This can all go away if/when we move to async events. + * + * @constructor + */ +export class EventQueue { + /** + * @private + * @type {!Array.} + */ + private eventLists_: EventList[] = []; + + /** + * Tracks recursion depth of raiseQueuedEvents_, for debugging purposes. + * @private + * @type {!number} + */ + private recursionDepth_ = 0; + + + /** + * @param {!Array.} eventDataList The new events to queue. + */ + queueEvents(eventDataList: Event[]) { + // We group events by path, storing them in a single EventList, to make it easier to skip over them quickly. + let currList = null; + for (let i = 0; i < eventDataList.length; i++) { + const eventData = eventDataList[i]; + const eventPath = eventData.getPath(); + if (currList !== null && !eventPath.equals(currList.getPath())) { + this.eventLists_.push(currList); + currList = null; + } + + if (currList === null) { + currList = new EventList(eventPath); + } + + currList.add(eventData); + } + if (currList) { + this.eventLists_.push(currList); + } + } + + /** + * Queues the specified events and synchronously raises all events (including previously queued ones) + * for the specified path. + * + * It is assumed that the new events are all for the specified path. + * + * @param {!Path} path The path to raise events for. + * @param {!Array.} eventDataList The new events to raise. + */ + raiseEventsAtPath(path: Path, eventDataList: Event[]) { + this.queueEvents(eventDataList); + this.raiseQueuedEventsMatchingPredicate_((eventPath: Path) => eventPath.equals(path)); + } + + /** + * Queues the specified events and synchronously raises all events (including previously queued ones) for + * locations related to the specified change path (i.e. all ancestors and descendants). + * + * It is assumed that the new events are all related (ancestor or descendant) to the specified path. + * + * @param {!Path} changedPath The path to raise events for. + * @param {!Array.} eventDataList The events to raise + */ + raiseEventsForChangedPath(changedPath: Path, eventDataList: Event[]) { + this.queueEvents(eventDataList); + + this.raiseQueuedEventsMatchingPredicate_((eventPath: Path) => { + return eventPath.contains(changedPath) || changedPath.contains(eventPath); + }); + }; + + /** + * @param {!function(!Path):boolean} predicate + * @private + */ + private raiseQueuedEventsMatchingPredicate_(predicate: (path: Path) => boolean) { + this.recursionDepth_++; + + let sentAll = true; + for (let i = 0; i < this.eventLists_.length; i++) { + const eventList = this.eventLists_[i]; + if (eventList) { + const eventPath = eventList.getPath(); + if (predicate(eventPath)) { + this.eventLists_[i].raise(); + this.eventLists_[i] = null; + } else { + sentAll = false; + } + } + } + + if (sentAll) { + this.eventLists_ = []; + } + + this.recursionDepth_--; + } +} + + +/** + * @param {!Path} path + * @constructor + */ +export class EventList { + /** + * @type {!Array.} + * @private + */ + private events_: Event[] = []; + + constructor(private readonly path_: Path) { + } + + /** + * @param {!Event} eventData + */ + add(eventData: Event) { + this.events_.push(eventData); + } + + /** + * Iterates through the list and raises each event + */ + raise() { + for (let i = 0; i < this.events_.length; i++) { + const eventData = this.events_[i]; + if (eventData !== null) { + this.events_[i] = null; + const eventFn = eventData.getEventRunner(); + if (logger) { + log('event: ' + eventData.toString()); + } + exceptionGuard(eventFn); + } + } + } + + /** + * @return {!Path} + */ + getPath(): Path { + return this.path_; + } +} + diff --git a/src/database/core/view/EventRegistration.ts b/src/database/core/view/EventRegistration.ts new file mode 100644 index 00000000000..39febc024f1 --- /dev/null +++ b/src/database/core/view/EventRegistration.ts @@ -0,0 +1,260 @@ +import { DataSnapshot } from '../../api/DataSnapshot'; +import { DataEvent, CancelEvent, Event } from './Event'; +import { contains, getCount, getAnyKey, every } from '../../../utils/obj'; +import { assert } from '../../../utils/assert'; +import { Path } from '../util/Path'; +import { Change } from './Change'; +import { Query } from '../../api/Query'; + +/** + * An EventRegistration is basically an event type ('value', 'child_added', etc.) and a callback + * to be notified of that type of event. + * + * That said, it can also contain a cancel callback to be notified if the event is canceled. And + * currently, this code is organized around the idea that you would register multiple child_ callbacks + * together, as a single EventRegistration. Though currently we don't do that. + */ +export interface EventRegistration { + /** + * True if this container has a callback to trigger for this event type + * @param {!string} eventType + * @return {boolean} + */ + respondsTo(eventType: string): boolean; + + /** + * @param {!Change} change + * @param {!Query} query + * @return {!Event} + */ + createEvent(change: Change, query: Query): Event; + + /** + * Given event data, return a function to trigger the user's callback + * @param {!Event} eventData + * @return {function()} + */ + getEventRunner(eventData: Event): () => any; + + /** + * @param {!Error} error + * @param {!Path} path + * @return {?CancelEvent} + */ + createCancelEvent(error: Error, path: Path): CancelEvent | null; + + /** + * @param {!EventRegistration} other + * @return {boolean} + */ + matches(other: EventRegistration): boolean; + + /** + * False basically means this is a "dummy" callback container being used as a sentinel + * to remove all callback containers of a particular type. (e.g. if the user does + * ref.off('value') without specifying a specific callback). + * + * (TODO: Rework this, since it's hacky) + * + * @return {boolean} + */ + hasAnyCallback(): boolean; +} + + +/** + * Represents registration for 'value' events. + */ +export class ValueEventRegistration implements EventRegistration { + /** + * @param {?function(!DataSnapshot)} callback_ + * @param {?function(Error)} cancelCallback_ + * @param {?Object} context_ + */ + constructor(private callback_: ((d: DataSnapshot) => any) | null, + private cancelCallback_: ((e: Error) => any) | null, + private context_: Object | null) { + } + + /** + * @inheritDoc + */ + respondsTo(eventType: string): boolean { + return eventType === 'value'; + } + + /** + * @inheritDoc + */ + createEvent(change: Change, query: Query): DataEvent { + const index = query.getQueryParams().getIndex(); + return new DataEvent('value', this, new DataSnapshot(change.snapshotNode, query.getRef(), index)); + } + + /** + * @inheritDoc + */ + getEventRunner(eventData: CancelEvent | DataEvent): () => void { + const ctx = this.context_; + if (eventData.getEventType() === 'cancel') { + assert(this.cancelCallback_, 'Raising a cancel event on a listener with no cancel callback'); + const cancelCB = this.cancelCallback_; + return function () { + // We know that error exists, we checked above that this is a cancel event + cancelCB.call(ctx, (eventData).error); + }; + } else { + const cb = this.callback_; + return function () { + cb.call(ctx, (eventData).snapshot); + }; + } + } + + /** + * @inheritDoc + */ + createCancelEvent(error: Error, path: Path): CancelEvent | null { + if (this.cancelCallback_) { + return new CancelEvent(this, error, path); + } else { + return null; + } + } + + /** + * @inheritDoc + */ + matches(other: EventRegistration): boolean { + if (!(other instanceof ValueEventRegistration)) { + return false; + } else if (!other.callback_ || !this.callback_) { + // If no callback specified, we consider it to match any callback. + return true; + } else { + return other.callback_ === this.callback_ && other.context_ === this.context_; + } + } + + /** + * @inheritDoc + */ + hasAnyCallback(): boolean { + return this.callback_ !== null; + } +} + +/** + * Represents the registration of 1 or more child_xxx events. + * + * Currently, it is always exactly 1 child_xxx event, but the idea is we might let you + * register a group of callbacks together in the future. + * + * @constructor + * @implements {EventRegistration} + */ +export class ChildEventRegistration implements EventRegistration { + /** + * @param {?Object.} callbacks_ + * @param {?function(Error)} cancelCallback_ + * @param {Object=} context_ + */ + constructor(private callbacks_: ({ [k: string]: (d: DataSnapshot, s?: string | null) => any }) | null, + private cancelCallback_: ((e: Error) => any) | null, + private context_: Object) { + } + + /** + * @inheritDoc + */ + respondsTo(eventType): boolean { + let eventToCheck = eventType === 'children_added' ? 'child_added' : eventType; + eventToCheck = eventToCheck === 'children_removed' ? 'child_removed' : eventToCheck; + return contains(this.callbacks_, eventToCheck); + } + + /** + * @inheritDoc + */ + createCancelEvent(error: Error, path: Path): CancelEvent | null { + if (this.cancelCallback_) { + return new CancelEvent(this, error, path); + } else { + return null; + } + } + + /** + * @inheritDoc + */ + createEvent(change: Change, query: Query): DataEvent { + assert(change.childName != null, 'Child events should have a childName.'); + const ref = query.getRef().child(/** @type {!string} */ (change.childName)); + const index = query.getQueryParams().getIndex(); + return new DataEvent(change.type, this, new DataSnapshot(change.snapshotNode, ref, index), + change.prevName); + } + + /** + * @inheritDoc + */ + getEventRunner(eventData: CancelEvent | DataEvent): () => void { + const ctx = this.context_; + if (eventData.getEventType() === 'cancel') { + assert(this.cancelCallback_, 'Raising a cancel event on a listener with no cancel callback'); + const cancelCB = this.cancelCallback_; + return function () { + // We know that error exists, we checked above that this is a cancel event + cancelCB.call(ctx, (eventData).error); + }; + } else { + const cb = this.callbacks_[(eventData).eventType]; + return function () { + cb.call(ctx, (eventData).snapshot, (eventData).prevName); + } + } + } + + /** + * @inheritDoc + */ + matches(other: EventRegistration): boolean { + if (other instanceof ChildEventRegistration) { + if (!this.callbacks_ || !other.callbacks_) { + return true; + } else if (this.context_ === other.context_) { + const otherCount = getCount(other.callbacks_); + const thisCount = getCount(this.callbacks_); + if (otherCount === thisCount) { + // If count is 1, do an exact match on eventType, if either is defined but null, it's a match. + // If event types don't match, not a match + // If count is not 1, exact match across all + + if (otherCount === 1) { + const otherKey = /** @type {!string} */ (getAnyKey(other.callbacks_)); + const thisKey = /** @type {!string} */ (getAnyKey(this.callbacks_)); + return (thisKey === otherKey && ( + !other.callbacks_[otherKey] || + !this.callbacks_[thisKey] || + other.callbacks_[otherKey] === this.callbacks_[thisKey] + ) + ); + } else { + // Exact match on each key. + return every(this.callbacks_, (eventType, cb) => other.callbacks_[eventType] === cb); + } + } + } + } + + return false; + } + + /** + * @inheritDoc + */ + hasAnyCallback(): boolean { + return (this.callbacks_ !== null); + } +} + diff --git a/src/database/core/view/QueryParams.ts b/src/database/core/view/QueryParams.ts new file mode 100644 index 00000000000..a2c8b320a65 --- /dev/null +++ b/src/database/core/view/QueryParams.ts @@ -0,0 +1,425 @@ +import { assert } from "../../../utils/assert"; +import { + MIN_NAME, + MAX_NAME +} from "../util/util"; +import { KEY_INDEX } from "../snap/indexes/KeyIndex"; +import { PRIORITY_INDEX } from "../snap/indexes/PriorityIndex"; +import { VALUE_INDEX } from "../snap/indexes/ValueIndex"; +import { PathIndex } from "../snap/indexes/PathIndex"; +import { IndexedFilter } from "./filter/IndexedFilter"; +import { LimitedFilter } from "./filter/LimitedFilter"; +import { RangedFilter } from "./filter/RangedFilter"; +import { stringify } from "../../../utils/json"; + +/** + * This class is an immutable-from-the-public-api struct containing a set of query parameters defining a + * range to be returned for a particular location. It is assumed that validation of parameters is done at the + * user-facing API level, so it is not done here. + * @constructor + */ +export class QueryParams { + endNameSet_ + endSet_ + index_ + indexEndName_ + indexEndValue_ + indexStartName_ + indexStartValue_ + limit_ + limitSet_ + startEndSet_ + startNameSet_ + startSet_ + viewFrom_ + + constructor() { + this.limitSet_ = false; + this.startSet_ = false; + this.startNameSet_ = false; + this.endSet_ = false; + this.endNameSet_ = false; + + this.limit_ = 0; + this.viewFrom_ = ''; + this.indexStartValue_ = null; + this.indexStartName_ = ''; + this.indexEndValue_ = null; + this.indexEndName_ = ''; + + this.index_ = PRIORITY_INDEX; + }; + /** + * Wire Protocol Constants + * @const + * @enum {string} + * @private + */ + private static WIRE_PROTOCOL_CONSTANTS_ = { + INDEX_START_VALUE: 'sp', + INDEX_START_NAME: 'sn', + INDEX_END_VALUE: 'ep', + INDEX_END_NAME: 'en', + LIMIT: 'l', + VIEW_FROM: 'vf', + VIEW_FROM_LEFT: 'l', + VIEW_FROM_RIGHT: 'r', + INDEX: 'i' + }; + + /** + * REST Query Constants + * @const + * @enum {string} + * @private + */ + private static REST_QUERY_CONSTANTS_ = { + ORDER_BY: 'orderBy', + PRIORITY_INDEX: '$priority', + VALUE_INDEX: '$value', + KEY_INDEX: '$key', + START_AT: 'startAt', + END_AT: 'endAt', + LIMIT_TO_FIRST: 'limitToFirst', + LIMIT_TO_LAST: 'limitToLast' + }; + + /** + * Default, empty query parameters + * @type {!QueryParams} + * @const + */ + static DEFAULT = new QueryParams(); + + /** + * @return {boolean} + */ + hasStart() { + return this.startSet_; + }; + + /** + * @return {boolean} True if it would return from left. + */ + isViewFromLeft() { + if (this.viewFrom_ === '') { + // limit(), rather than limitToFirst or limitToLast was called. + // This means that only one of startSet_ and endSet_ is true. Use them + // to calculate which side of the view to anchor to. If neither is set, + // anchor to the end. + return this.startSet_; + } else { + return this.viewFrom_ === QueryParams.WIRE_PROTOCOL_CONSTANTS_.VIEW_FROM_LEFT; + } + }; + + /** + * Only valid to call if hasStart() returns true + * @return {*} + */ + getIndexStartValue() { + assert(this.startSet_, 'Only valid if start has been set'); + return this.indexStartValue_; + }; + + /** + * Only valid to call if hasStart() returns true. + * Returns the starting key name for the range defined by these query parameters + * @return {!string} + */ + getIndexStartName() { + assert(this.startSet_, 'Only valid if start has been set'); + if (this.startNameSet_) { + return this.indexStartName_; + } else { + return MIN_NAME; + } + }; + + /** + * @return {boolean} + */ + hasEnd() { + return this.endSet_; + }; + + /** + * Only valid to call if hasEnd() returns true. + * @return {*} + */ + getIndexEndValue() { + assert(this.endSet_, 'Only valid if end has been set'); + return this.indexEndValue_; + }; + + /** + * Only valid to call if hasEnd() returns true. + * Returns the end key name for the range defined by these query parameters + * @return {!string} + */ + getIndexEndName() { + assert(this.endSet_, 'Only valid if end has been set'); + if (this.endNameSet_) { + return this.indexEndName_; + } else { + return MAX_NAME; + } + }; + + /** + * @return {boolean} + */ + hasLimit() { + return this.limitSet_; + }; + + /** + * @return {boolean} True if a limit has been set and it has been explicitly anchored + */ + hasAnchoredLimit() { + return this.limitSet_ && this.viewFrom_ !== ''; + }; + + /** + * Only valid to call if hasLimit() returns true + * @return {!number} + */ + getLimit() { + assert(this.limitSet_, 'Only valid if limit has been set'); + return this.limit_; + }; + + /** + * @return {!Index} + */ + getIndex() { + return this.index_; + }; + + /** + * @return {!QueryParams} + * @private + */ + copy_() { + var copy = new QueryParams(); + copy.limitSet_ = this.limitSet_; + copy.limit_ = this.limit_; + copy.startSet_ = this.startSet_; + copy.indexStartValue_ = this.indexStartValue_; + copy.startNameSet_ = this.startNameSet_; + copy.indexStartName_ = this.indexStartName_; + copy.endSet_ = this.endSet_; + copy.indexEndValue_ = this.indexEndValue_; + copy.endNameSet_ = this.endNameSet_; + copy.indexEndName_ = this.indexEndName_; + copy.index_ = this.index_; + copy.viewFrom_ = this.viewFrom_; + return copy; + }; + + /** + * @param {!number} newLimit + * @return {!QueryParams} + */ + limit(newLimit) { + var newParams = this.copy_(); + newParams.limitSet_ = true; + newParams.limit_ = newLimit; + newParams.viewFrom_ = ''; + return newParams; + }; + + /** + * @param {!number} newLimit + * @return {!QueryParams} + */ + limitToFirst(newLimit) { + var newParams = this.copy_(); + newParams.limitSet_ = true; + newParams.limit_ = newLimit; + newParams.viewFrom_ = QueryParams.WIRE_PROTOCOL_CONSTANTS_.VIEW_FROM_LEFT; + return newParams; + }; + + /** + * @param {!number} newLimit + * @return {!QueryParams} + */ + limitToLast(newLimit) { + var newParams = this.copy_(); + newParams.limitSet_ = true; + newParams.limit_ = newLimit; + newParams.viewFrom_ = QueryParams.WIRE_PROTOCOL_CONSTANTS_.VIEW_FROM_RIGHT; + return newParams; + }; + + /** + * @param {*} indexValue + * @param {?string=} key + * @return {!QueryParams} + */ + startAt(indexValue, key) { + var newParams = this.copy_(); + newParams.startSet_ = true; + if (!(indexValue !== undefined)) { + indexValue = null; + } + newParams.indexStartValue_ = indexValue; + if (key != null) { + newParams.startNameSet_ = true; + newParams.indexStartName_ = key; + } else { + newParams.startNameSet_ = false; + newParams.indexStartName_ = ''; + } + return newParams; + }; + + /** + * @param {*} indexValue + * @param {?string=} key + * @return {!QueryParams} + */ + endAt(indexValue, key) { + var newParams = this.copy_(); + newParams.endSet_ = true; + if (!(indexValue !== undefined)) { + indexValue = null; + } + newParams.indexEndValue_ = indexValue; + if ((key !== undefined)) { + newParams.endNameSet_ = true; + newParams.indexEndName_ = key; + } else { + newParams.startEndSet_ = false; + newParams.indexEndName_ = ''; + } + return newParams; + }; + + /** + * @param {!Index} index + * @return {!QueryParams} + */ + orderBy(index) { + var newParams = this.copy_(); + newParams.index_ = index; + return newParams; + }; + + /** + * @return {!Object} + */ + getQueryObject() { + var WIRE_PROTOCOL_CONSTANTS = QueryParams.WIRE_PROTOCOL_CONSTANTS_; + var obj = {}; + if (this.startSet_) { + obj[WIRE_PROTOCOL_CONSTANTS.INDEX_START_VALUE] = this.indexStartValue_; + if (this.startNameSet_) { + obj[WIRE_PROTOCOL_CONSTANTS.INDEX_START_NAME] = this.indexStartName_; + } + } + if (this.endSet_) { + obj[WIRE_PROTOCOL_CONSTANTS.INDEX_END_VALUE] = this.indexEndValue_; + if (this.endNameSet_) { + obj[WIRE_PROTOCOL_CONSTANTS.INDEX_END_NAME] = this.indexEndName_; + } + } + if (this.limitSet_) { + obj[WIRE_PROTOCOL_CONSTANTS.LIMIT] = this.limit_; + var viewFrom = this.viewFrom_; + if (viewFrom === '') { + if (this.isViewFromLeft()) { + viewFrom = WIRE_PROTOCOL_CONSTANTS.VIEW_FROM_LEFT; + } else { + viewFrom = WIRE_PROTOCOL_CONSTANTS.VIEW_FROM_RIGHT; + } + } + obj[WIRE_PROTOCOL_CONSTANTS.VIEW_FROM] = viewFrom; + } + // For now, priority index is the default, so we only specify if it's some other index + if (this.index_ !== PRIORITY_INDEX) { + obj[WIRE_PROTOCOL_CONSTANTS.INDEX] = this.index_.toString(); + } + return obj; + }; + + /** + * @return {boolean} + */ + loadsAllData() { + return !(this.startSet_ || this.endSet_ || this.limitSet_); + }; + + /** + * @return {boolean} + */ + isDefault() { + return this.loadsAllData() && this.index_ == PRIORITY_INDEX; + }; + + /** + * @return {!NodeFilter} + */ + getNodeFilter() { + if (this.loadsAllData()) { + return new IndexedFilter(this.getIndex()); + } else if (this.hasLimit()) { + return new LimitedFilter(this); + } else { + return new RangedFilter(this); + } + }; + + + /** + * Returns a set of REST query string parameters representing this query. + * + * @return {!Object.} query string parameters + */ + toRestQueryStringParameters() { + var REST_CONSTANTS = QueryParams.REST_QUERY_CONSTANTS_; + var qs = { }; + + if (this.isDefault()) { + return qs; + } + + var orderBy; + if (this.index_ === PRIORITY_INDEX) { + orderBy = REST_CONSTANTS.PRIORITY_INDEX; + } else if (this.index_ === VALUE_INDEX) { + orderBy = REST_CONSTANTS.VALUE_INDEX; + } else if (this.index_ === KEY_INDEX) { + orderBy = REST_CONSTANTS.KEY_INDEX; + } else { + assert(this.index_ instanceof PathIndex, 'Unrecognized index type!'); + orderBy = this.index_.toString(); + } + qs[REST_CONSTANTS.ORDER_BY] = stringify(orderBy); + + if (this.startSet_) { + qs[REST_CONSTANTS.START_AT] = stringify(this.indexStartValue_); + if (this.startNameSet_) { + qs[REST_CONSTANTS.START_AT] += ',' + stringify(this.indexStartName_); + } + } + + if (this.endSet_) { + qs[REST_CONSTANTS.END_AT] = stringify(this.indexEndValue_); + if (this.endNameSet_) { + qs[REST_CONSTANTS.END_AT] += ',' + stringify(this.indexEndName_); + } + } + + if (this.limitSet_) { + if (this.isViewFromLeft()) { + qs[REST_CONSTANTS.LIMIT_TO_FIRST] = this.limit_; + } else { + qs[REST_CONSTANTS.LIMIT_TO_LAST] = this.limit_; + } + } + + return qs; + }; +} diff --git a/src/database/core/view/View.ts b/src/database/core/view/View.ts new file mode 100644 index 00000000000..3703c8613f8 --- /dev/null +++ b/src/database/core/view/View.ts @@ -0,0 +1,223 @@ +import { IndexedFilter } from "./filter/IndexedFilter"; +import { ViewProcessor } from "./ViewProcessor"; +import { ChildrenNode } from "../snap/ChildrenNode"; +import { CacheNode } from "./CacheNode"; +import { ViewCache } from "./ViewCache"; +import { EventGenerator } from "./EventGenerator"; +import { assert } from "../../../utils/assert"; +import { OperationType } from "../operation/Operation"; +import { Change } from "./Change"; +import { PRIORITY_INDEX } from "../snap/indexes/PriorityIndex"; +import { Query } from "../../api/Query"; + +/** + * A view represents a specific location and query that has 1 or more event registrations. + * + * It does several things: + * - Maintains the list of event registrations for this location/query. + * - Maintains a cache of the data visible for this location/query. + * - Applies new operations (via applyOperation), updates the cache, and based on the event + * registrations returns the set of events to be raised. + * + * @param {!fb.api.Query} query + * @param {!ViewCache} initialViewCache + * @constructor + */ +export class View { + query_: Query + processor_ + viewCache_ + eventRegistrations_ + eventGenerator_ + constructor(query, initialViewCache) { + /** + * @type {!fb.api.Query} + * @private + */ + this.query_ = query; + var params = query.getQueryParams(); + + var indexFilter = new IndexedFilter(params.getIndex()); + var filter = params.getNodeFilter(); + + /** + * @type {ViewProcessor} + * @private + */ + this.processor_ = new ViewProcessor(filter); + + var initialServerCache = initialViewCache.getServerCache(); + var initialEventCache = initialViewCache.getEventCache(); + + // Don't filter server node with other filter than index, wait for tagged listen + var serverSnap = indexFilter.updateFullNode(ChildrenNode.EMPTY_NODE, initialServerCache.getNode(), null); + var eventSnap = filter.updateFullNode(ChildrenNode.EMPTY_NODE, initialEventCache.getNode(), null); + var newServerCache = new CacheNode(serverSnap, initialServerCache.isFullyInitialized(), + indexFilter.filtersNodes()); + var newEventCache = new CacheNode(eventSnap, initialEventCache.isFullyInitialized(), + filter.filtersNodes()); + + /** + * @type {!ViewCache} + * @private + */ + this.viewCache_ = new ViewCache(newEventCache, newServerCache); + + /** + * @type {!Array.} + * @private + */ + this.eventRegistrations_ = []; + + /** + * @type {!EventGenerator} + * @private + */ + this.eventGenerator_ = new EventGenerator(query); + }; + /** + * @return {!fb.api.Query} + */ + getQuery() { + return this.query_; + }; + + /** + * @return {?fb.core.snap.Node} + */ + getServerCache() { + return this.viewCache_.getServerCache().getNode(); + }; + + /** + * @param {!Path} path + * @return {?fb.core.snap.Node} + */ + getCompleteServerCache(path) { + var cache = this.viewCache_.getCompleteServerSnap(); + if (cache) { + // If this isn't a "loadsAllData" view, then cache isn't actually a complete cache and + // we need to see if it contains the child we're interested in. + if (this.query_.getQueryParams().loadsAllData() || + (!path.isEmpty() && !cache.getImmediateChild(path.getFront()).isEmpty())) { + return cache.getChild(path); + } + } + return null; + }; + + /** + * @return {boolean} + */ + isEmpty() { + return this.eventRegistrations_.length === 0; + }; + + /** + * @param {!fb.core.view.EventRegistration} eventRegistration + */ + addEventRegistration(eventRegistration) { + this.eventRegistrations_.push(eventRegistration); + }; + + /** + * @param {?fb.core.view.EventRegistration} eventRegistration If null, remove all callbacks. + * @param {Error=} cancelError If a cancelError is provided, appropriate cancel events will be returned. + * @return {!Array.} Cancel events, if cancelError was provided. + */ + removeEventRegistration(eventRegistration, cancelError) { + var cancelEvents = []; + if (cancelError) { + assert(eventRegistration == null, 'A cancel should cancel all event registrations.'); + var path = this.query_.path; + this.eventRegistrations_.forEach(function(registration) { + cancelError = /** @type {!Error} */ (cancelError); + var maybeEvent = registration.createCancelEvent(cancelError, path); + if (maybeEvent) { + cancelEvents.push(maybeEvent); + } + }); + } + + if (eventRegistration) { + var remaining = []; + for (var i = 0; i < this.eventRegistrations_.length; ++i) { + var existing = this.eventRegistrations_[i]; + if (!existing.matches(eventRegistration)) { + remaining.push(existing); + } else if (eventRegistration.hasAnyCallback()) { + // We're removing just this one + remaining = remaining.concat(this.eventRegistrations_.slice(i + 1)); + break; + } + } + this.eventRegistrations_ = remaining; + } else { + this.eventRegistrations_ = []; + } + return cancelEvents; + }; + + /** + * Applies the given Operation, updates our cache, and returns the appropriate events. + * + * @param {!fb.core.Operation} operation + * @param {!fb.core.WriteTreeRef} writesCache + * @param {?fb.core.snap.Node} optCompleteServerCache + * @return {!Array.} + */ + applyOperation(operation, writesCache, optCompleteServerCache) { + if (operation.type === OperationType.MERGE && + operation.source.queryId !== null) { + + assert(this.viewCache_.getCompleteServerSnap(), + 'We should always have a full cache before handling merges'); + assert(this.viewCache_.getCompleteEventSnap(), + 'Missing event cache, even though we have a server cache'); + } + + var oldViewCache = this.viewCache_; + var result = this.processor_.applyOperation(oldViewCache, operation, writesCache, optCompleteServerCache); + this.processor_.assertIndexed(result.viewCache); + + assert(result.viewCache.getServerCache().isFullyInitialized() || + !oldViewCache.getServerCache().isFullyInitialized(), + 'Once a server snap is complete, it should never go back'); + + this.viewCache_ = result.viewCache; + + return this.generateEventsForChanges_(result.changes, result.viewCache.getEventCache().getNode(), null); + }; + + /** + * @param {!fb.core.view.EventRegistration} registration + * @return {!Array.} + */ + getInitialEvents(registration) { + var eventSnap = this.viewCache_.getEventCache(); + var initialChanges = []; + if (!eventSnap.getNode().isLeafNode()) { + var eventNode = /** @type {!fb.core.snap.ChildrenNode} */ (eventSnap.getNode()); + eventNode.forEachChild(PRIORITY_INDEX, function(key, childNode) { + initialChanges.push(Change.childAddedChange(key, childNode)); + }); + } + if (eventSnap.isFullyInitialized()) { + initialChanges.push(Change.valueChange(eventSnap.getNode())); + } + return this.generateEventsForChanges_(initialChanges, eventSnap.getNode(), registration); + }; + + /** + * @private + * @param {!Array.} changes + * @param {!fb.core.snap.Node} eventCache + * @param {fb.core.view.EventRegistration=} opt_eventRegistration + * @return {!Array.} + */ + generateEventsForChanges_(changes, eventCache, opt_eventRegistration) { + var registrations = opt_eventRegistration ? [opt_eventRegistration] : this.eventRegistrations_; + return this.eventGenerator_.generateEventsForChanges(changes, eventCache, registrations); + }; +} + diff --git a/src/database/core/view/ViewCache.ts b/src/database/core/view/ViewCache.ts new file mode 100644 index 00000000000..a407582562a --- /dev/null +++ b/src/database/core/view/ViewCache.ts @@ -0,0 +1,99 @@ +import { ChildrenNode } from "../snap/ChildrenNode"; +import { CacheNode } from "./CacheNode"; + +/** + * Stores the data we have cached for a view. + * + * serverSnap is the cached server data, eventSnap is the cached event data (server data plus any local writes). + * + * @param {!CacheNode} eventCache + * @param {!CacheNode} serverCache + * @constructor + */ +export class ViewCache { + /** + * @const + * @type {!CacheNode} + * @private + */ + private eventCache_; + + /** + * @const + * @type {!CacheNode} + * @private + */ + private serverCache_; + constructor(eventCache, serverCache) { + /** + * @const + * @type {!CacheNode} + * @private + */ + this.eventCache_ = eventCache; + + /** + * @const + * @type {!CacheNode} + * @private + */ + this.serverCache_ = serverCache; + }; + /** + * @const + * @type {ViewCache} + */ + static Empty = new ViewCache( + new CacheNode(ChildrenNode.EMPTY_NODE, /*fullyInitialized=*/false, /*filtered=*/false), + new CacheNode(ChildrenNode.EMPTY_NODE, /*fullyInitialized=*/false, /*filtered=*/false) + ); + + /** + * @param {!fb.core.snap.Node} eventSnap + * @param {boolean} complete + * @param {boolean} filtered + * @return {!ViewCache} + */ + updateEventSnap(eventSnap, complete, filtered) { + return new ViewCache(new CacheNode(eventSnap, complete, filtered), this.serverCache_); + }; + + /** + * @param {!fb.core.snap.Node} serverSnap + * @param {boolean} complete + * @param {boolean} filtered + * @return {!ViewCache} + */ + updateServerSnap(serverSnap, complete, filtered) { + return new ViewCache(this.eventCache_, new CacheNode(serverSnap, complete, filtered)); + }; + + /** + * @return {!CacheNode} + */ + getEventCache() { + return this.eventCache_; + }; + + /** + * @return {?fb.core.snap.Node} + */ + getCompleteEventSnap() { + return (this.eventCache_.isFullyInitialized()) ? this.eventCache_.getNode() : null; + }; + + /** + * @return {!CacheNode} + */ + getServerCache() { + return this.serverCache_; + }; + + /** + * @return {?fb.core.snap.Node} + */ + getCompleteServerSnap() { + return this.serverCache_.isFullyInitialized() ? this.serverCache_.getNode() : null; + }; +} + diff --git a/src/database/core/view/ViewProcessor.ts b/src/database/core/view/ViewProcessor.ts new file mode 100644 index 00000000000..8dbeb57988c --- /dev/null +++ b/src/database/core/view/ViewProcessor.ts @@ -0,0 +1,571 @@ +import { OperationType } from "../operation/Operation"; +import { assert, assertionError } from "../../../utils/assert"; +import { ChildChangeAccumulator } from "./ChildChangeAccumulator"; +import { Change } from "./Change"; +import { ChildrenNode } from "../snap/ChildrenNode"; +import { KEY_INDEX } from "../snap/indexes/KeyIndex"; +import { ImmutableTree } from "../util/ImmutableTree"; +import { Path } from "../util/Path"; +import { WriteTreeCompleteChildSource, NO_COMPLETE_CHILD_SOURCE } from "./CompleteChildSource"; + +/** + * @param {!ViewCache} viewCache + * @param {!Array.} changes + * @constructor + * @struct + */ +export class ProcessorResult { + /** + * @const + * @type {!ViewCache} + */ + viewCache; + + /** + * @const + * @type {!Array.} + */ + changes; + + constructor(viewCache, changes) { + this.viewCache = viewCache; + this.changes = changes; + }; +} + +/** + * @param {!NodeFilter} filter + * @constructor + */ +export class ViewProcessor { + /** + * @type {!NodeFilter} + * @private + * @const + */ + private filter_; + constructor(filter) { + this.filter_ = filter; + }; + + /** + * @param {!ViewCache} viewCache + */ + assertIndexed(viewCache) { + assert(viewCache.getEventCache().getNode().isIndexed(this.filter_.getIndex()), 'Event snap not indexed'); + assert(viewCache.getServerCache().getNode().isIndexed(this.filter_.getIndex()), + 'Server snap not indexed'); + }; + + /** + * @param {!ViewCache} oldViewCache + * @param {!fb.core.Operation} operation + * @param {!fb.core.WriteTreeRef} writesCache + * @param {?fb.core.snap.Node} optCompleteCache + * @return {!ProcessorResult} + */ + applyOperation(oldViewCache, operation, writesCache, optCompleteCache) { + var accumulator = new ChildChangeAccumulator(); + var newViewCache, filterServerNode; + if (operation.type === OperationType.OVERWRITE) { + var overwrite = /** @type {!fb.core.operation.Overwrite} */ (operation); + if (overwrite.source.fromUser) { + newViewCache = this.applyUserOverwrite_(oldViewCache, overwrite.path, overwrite.snap, + writesCache, optCompleteCache, accumulator); + } else { + assert(overwrite.source.fromServer, 'Unknown source.'); + // We filter the node if it's a tagged update or the node has been previously filtered and the + // update is not at the root in which case it is ok (and necessary) to mark the node unfiltered + // again + filterServerNode = overwrite.source.tagged || + (oldViewCache.getServerCache().isFiltered() && !overwrite.path.isEmpty()); + newViewCache = this.applyServerOverwrite_(oldViewCache, overwrite.path, overwrite.snap, writesCache, + optCompleteCache, filterServerNode, accumulator); + } + } else if (operation.type === OperationType.MERGE) { + var merge = /** @type {!fb.core.operation.Merge} */ (operation); + if (merge.source.fromUser) { + newViewCache = this.applyUserMerge_(oldViewCache, merge.path, merge.children, writesCache, + optCompleteCache, accumulator); + } else { + assert(merge.source.fromServer, 'Unknown source.'); + // We filter the node if it's a tagged update or the node has been previously filtered + filterServerNode = merge.source.tagged || oldViewCache.getServerCache().isFiltered(); + newViewCache = this.applyServerMerge_(oldViewCache, merge.path, merge.children, writesCache, optCompleteCache, + filterServerNode, accumulator); + } + } else if (operation.type === OperationType.ACK_USER_WRITE) { + var ackUserWrite = /** @type {!fb.core.operation.AckUserWrite} */ (operation); + if (!ackUserWrite.revert) { + newViewCache = this.ackUserWrite_(oldViewCache, ackUserWrite.path, ackUserWrite.affectedTree, writesCache, + optCompleteCache, accumulator); + } else { + newViewCache = this.revertUserWrite_(oldViewCache, ackUserWrite.path, writesCache, optCompleteCache, accumulator); + } + } else if (operation.type === OperationType.LISTEN_COMPLETE) { + newViewCache = this.listenComplete_(oldViewCache, operation.path, writesCache, optCompleteCache, accumulator); + } else { + throw assertionError('Unknown operation type: ' + operation.type); + } + var changes = accumulator.getChanges(); + this.maybeAddValueEvent_(oldViewCache, newViewCache, changes); + return new ProcessorResult(newViewCache, changes); + }; + + /** + * @param {!ViewCache} oldViewCache + * @param {!ViewCache} newViewCache + * @param {!Array.} accumulator + * @private + */ + maybeAddValueEvent_(oldViewCache, newViewCache, accumulator) { + var eventSnap = newViewCache.getEventCache(); + if (eventSnap.isFullyInitialized()) { + var isLeafOrEmpty = eventSnap.getNode().isLeafNode() || eventSnap.getNode().isEmpty(); + var oldCompleteSnap = oldViewCache.getCompleteEventSnap(); + if (accumulator.length > 0 || + !oldViewCache.getEventCache().isFullyInitialized() || + (isLeafOrEmpty && !eventSnap.getNode().equals(/** @type {!fb.core.snap.Node} */ (oldCompleteSnap))) || + !eventSnap.getNode().getPriority().equals(oldCompleteSnap.getPriority())) { + accumulator.push(Change.valueChange( + /** @type {!fb.core.snap.Node} */ (newViewCache.getCompleteEventSnap()))); + } + } + }; + + /** + * @param {!ViewCache} viewCache + * @param {!Path} changePath + * @param {!fb.core.WriteTreeRef} writesCache + * @param {!fb.core.view.CompleteChildSource} source + * @param {!ChildChangeAccumulator} accumulator + * @return {!ViewCache} + * @private + */ + generateEventCacheAfterServerEvent_(viewCache, changePath, writesCache, source, accumulator) { + var oldEventSnap = viewCache.getEventCache(); + if (writesCache.shadowingWrite(changePath) != null) { + // we have a shadowing write, ignore changes + return viewCache; + } else { + var newEventCache, serverNode; + if (changePath.isEmpty()) { + // TODO: figure out how this plays with "sliding ack windows" + assert(viewCache.getServerCache().isFullyInitialized(), + 'If change path is empty, we must have complete server data'); + if (viewCache.getServerCache().isFiltered()) { + // We need to special case this, because we need to only apply writes to complete children, or + // we might end up raising events for incomplete children. If the server data is filtered deep + // writes cannot be guaranteed to be complete + var serverCache = viewCache.getCompleteServerSnap(); + var completeChildren = (serverCache instanceof ChildrenNode) ? serverCache : + ChildrenNode.EMPTY_NODE; + var completeEventChildren = writesCache.calcCompleteEventChildren(completeChildren); + newEventCache = this.filter_.updateFullNode(viewCache.getEventCache().getNode(), completeEventChildren, + accumulator); + } else { + var completeNode = /** @type {!fb.core.snap.Node} */ + (writesCache.calcCompleteEventCache(viewCache.getCompleteServerSnap())); + newEventCache = this.filter_.updateFullNode(viewCache.getEventCache().getNode(), completeNode, accumulator); + } + } else { + var childKey = changePath.getFront(); + if (childKey == '.priority') { + assert(changePath.getLength() == 1, "Can't have a priority with additional path components"); + var oldEventNode = oldEventSnap.getNode(); + serverNode = viewCache.getServerCache().getNode(); + // we might have overwrites for this priority + var updatedPriority = writesCache.calcEventCacheAfterServerOverwrite(changePath, oldEventNode, serverNode); + if (updatedPriority != null) { + newEventCache = this.filter_.updatePriority(oldEventNode, updatedPriority); + } else { + // priority didn't change, keep old node + newEventCache = oldEventSnap.getNode(); + } + } else { + var childChangePath = changePath.popFront(); + // update child + var newEventChild; + if (oldEventSnap.isCompleteForChild(childKey)) { + serverNode = viewCache.getServerCache().getNode(); + var eventChildUpdate = writesCache.calcEventCacheAfterServerOverwrite(changePath, oldEventSnap.getNode(), + serverNode); + if (eventChildUpdate != null) { + newEventChild = oldEventSnap.getNode().getImmediateChild(childKey).updateChild(childChangePath, + eventChildUpdate); + } else { + // Nothing changed, just keep the old child + newEventChild = oldEventSnap.getNode().getImmediateChild(childKey); + } + } else { + newEventChild = writesCache.calcCompleteChild(childKey, viewCache.getServerCache()); + } + if (newEventChild != null) { + newEventCache = this.filter_.updateChild(oldEventSnap.getNode(), childKey, newEventChild, childChangePath, + source, accumulator); + } else { + // no complete child available or no change + newEventCache = oldEventSnap.getNode(); + } + } + } + return viewCache.updateEventSnap(newEventCache, oldEventSnap.isFullyInitialized() || changePath.isEmpty(), + this.filter_.filtersNodes()); + } + }; + + /** + * @param {!ViewCache} oldViewCache + * @param {!Path} changePath + * @param {!fb.core.snap.Node} changedSnap + * @param {!fb.core.WriteTreeRef} writesCache + * @param {?fb.core.snap.Node} optCompleteCache + * @param {boolean} filterServerNode + * @param {!ChildChangeAccumulator} accumulator + * @return {!ViewCache} + * @private + */ + applyServerOverwrite_(oldViewCache, changePath, changedSnap, + writesCache, optCompleteCache, filterServerNode, + accumulator) { + var oldServerSnap = oldViewCache.getServerCache(); + var newServerCache; + var serverFilter = filterServerNode ? this.filter_ : this.filter_.getIndexedFilter(); + if (changePath.isEmpty()) { + newServerCache = serverFilter.updateFullNode(oldServerSnap.getNode(), changedSnap, null); + } else if (serverFilter.filtersNodes() && !oldServerSnap.isFiltered()) { + // we want to filter the server node, but we didn't filter the server node yet, so simulate a full update + var newServerNode = oldServerSnap.getNode().updateChild(changePath, changedSnap); + newServerCache = serverFilter.updateFullNode(oldServerSnap.getNode(), newServerNode, null); + } else { + var childKey = changePath.getFront(); + if (!oldServerSnap.isCompleteForPath(changePath) && changePath.getLength() > 1) { + // We don't update incomplete nodes with updates intended for other listeners + return oldViewCache; + } + var childChangePath = changePath.popFront(); + var childNode = oldServerSnap.getNode().getImmediateChild(childKey); + var newChildNode = childNode.updateChild(childChangePath, changedSnap); + if (childKey == '.priority') { + newServerCache = serverFilter.updatePriority(oldServerSnap.getNode(), newChildNode); + } else { + newServerCache = serverFilter.updateChild(oldServerSnap.getNode(), childKey, newChildNode, childChangePath, + NO_COMPLETE_CHILD_SOURCE, null); + } + } + var newViewCache = oldViewCache.updateServerSnap(newServerCache, + oldServerSnap.isFullyInitialized() || changePath.isEmpty(), serverFilter.filtersNodes()); + var source = new WriteTreeCompleteChildSource(writesCache, newViewCache, optCompleteCache); + return this.generateEventCacheAfterServerEvent_(newViewCache, changePath, writesCache, source, accumulator); + }; + + /** + * @param {!ViewCache} oldViewCache + * @param {!Path} changePath + * @param {!fb.core.snap.Node} changedSnap + * @param {!fb.core.WriteTreeRef} writesCache + * @param {?fb.core.snap.Node} optCompleteCache + * @param {!ChildChangeAccumulator} accumulator + * @return {!ViewCache} + * @private + */ + applyUserOverwrite_(oldViewCache, changePath, changedSnap, writesCache, + optCompleteCache, accumulator) { + var oldEventSnap = oldViewCache.getEventCache(); + var newViewCache, newEventCache; + var source = new WriteTreeCompleteChildSource(writesCache, oldViewCache, optCompleteCache); + if (changePath.isEmpty()) { + newEventCache = this.filter_.updateFullNode(oldViewCache.getEventCache().getNode(), changedSnap, accumulator); + newViewCache = oldViewCache.updateEventSnap(newEventCache, true, this.filter_.filtersNodes()); + } else { + var childKey = changePath.getFront(); + if (childKey === '.priority') { + newEventCache = this.filter_.updatePriority(oldViewCache.getEventCache().getNode(), changedSnap); + newViewCache = oldViewCache.updateEventSnap(newEventCache, oldEventSnap.isFullyInitialized(), + oldEventSnap.isFiltered()); + } else { + var childChangePath = changePath.popFront(); + var oldChild = oldEventSnap.getNode().getImmediateChild(childKey); + var newChild; + if (childChangePath.isEmpty()) { + // Child overwrite, we can replace the child + newChild = changedSnap; + } else { + var childNode = source.getCompleteChild(childKey); + if (childNode != null) { + if (childChangePath.getBack() === '.priority' && + childNode.getChild(/** @type {!Path} */ (childChangePath.parent())).isEmpty()) { + // This is a priority update on an empty node. If this node exists on the server, the + // server will send down the priority in the update, so ignore for now + newChild = childNode; + } else { + newChild = childNode.updateChild(childChangePath, changedSnap); + } + } else { + // There is no complete child node available + newChild = ChildrenNode.EMPTY_NODE; + } + } + if (!oldChild.equals(newChild)) { + var newEventSnap = this.filter_.updateChild(oldEventSnap.getNode(), childKey, newChild, childChangePath, + source, accumulator); + newViewCache = oldViewCache.updateEventSnap(newEventSnap, oldEventSnap.isFullyInitialized(), + this.filter_.filtersNodes()); + } else { + newViewCache = oldViewCache; + } + } + } + return newViewCache; + }; + + /** + * @param {!ViewCache} viewCache + * @param {string} childKey + * @return {boolean} + * @private + */ + static cacheHasChild_(viewCache, childKey) { + return viewCache.getEventCache().isCompleteForChild(childKey); + }; + + /** + * @param {!ViewCache} viewCache + * @param {!Path} path + * @param {ImmutableTree.} changedChildren + * @param {!fb.core.WriteTreeRef} writesCache + * @param {?fb.core.snap.Node} serverCache + * @param {!ChildChangeAccumulator} accumulator + * @return {!ViewCache} + * @private + */ + applyUserMerge_(viewCache, path, changedChildren, writesCache, + serverCache, accumulator) { + // HACK: In the case of a limit query, there may be some changes that bump things out of the + // window leaving room for new items. It's important we process these changes first, so we + // iterate the changes twice, first processing any that affect items currently in view. + // TODO: I consider an item "in view" if cacheHasChild is true, which checks both the server + // and event snap. I'm not sure if this will result in edge cases when a child is in one but + // not the other. + var self = this; + var curViewCache = viewCache; + changedChildren.foreach(function(relativePath, childNode) { + var writePath = path.child(relativePath); + if (ViewProcessor.cacheHasChild_(viewCache, writePath.getFront())) { + curViewCache = self.applyUserOverwrite_(curViewCache, writePath, childNode, writesCache, + serverCache, accumulator); + } + }); + + changedChildren.foreach(function(relativePath, childNode) { + var writePath = path.child(relativePath); + if (!ViewProcessor.cacheHasChild_(viewCache, writePath.getFront())) { + curViewCache = self.applyUserOverwrite_(curViewCache, writePath, childNode, writesCache, + serverCache, accumulator); + } + }); + + return curViewCache; + }; + + /** + * @param {!fb.core.snap.Node} node + * @param {ImmutableTree.} merge + * @return {!fb.core.snap.Node} + * @private + */ + applyMerge_(node, merge) { + merge.foreach(function(relativePath, childNode) { + node = node.updateChild(relativePath, childNode); + }); + return node; + }; + + /** + * @param {!ViewCache} viewCache + * @param {!Path} path + * @param {!ImmutableTree.} changedChildren + * @param {!fb.core.WriteTreeRef} writesCache + * @param {?fb.core.snap.Node} serverCache + * @param {boolean} filterServerNode + * @param {!ChildChangeAccumulator} accumulator + * @return {!ViewCache} + * @private + */ + applyServerMerge_(viewCache, path, changedChildren, writesCache, serverCache, filterServerNode, accumulator) { + // If we don't have a cache yet, this merge was intended for a previously listen in the same location. Ignore it and + // wait for the complete data update coming soon. + if (viewCache.getServerCache().getNode().isEmpty() && !viewCache.getServerCache().isFullyInitialized()) { + return viewCache; + } + + // HACK: In the case of a limit query, there may be some changes that bump things out of the + // window leaving room for new items. It's important we process these changes first, so we + // iterate the changes twice, first processing any that affect items currently in view. + // TODO: I consider an item "in view" if cacheHasChild is true, which checks both the server + // and event snap. I'm not sure if this will result in edge cases when a child is in one but + // not the other. + var curViewCache = viewCache; + var viewMergeTree; + if (path.isEmpty()) { + viewMergeTree = changedChildren; + } else { + viewMergeTree = ImmutableTree.Empty.setTree(path, changedChildren); + } + var serverNode = viewCache.getServerCache().getNode(); + var self = this; + viewMergeTree.children.inorderTraversal(function(childKey, childTree) { + if (serverNode.hasChild(childKey)) { + var serverChild = viewCache.getServerCache().getNode().getImmediateChild(childKey); + var newChild = self.applyMerge_(serverChild, childTree); + curViewCache = self.applyServerOverwrite_(curViewCache, new Path(childKey), newChild, + writesCache, serverCache, filterServerNode, accumulator); + } + }); + viewMergeTree.children.inorderTraversal(function(childKey, childMergeTree) { + var isUnknownDeepMerge = !viewCache.getServerCache().isCompleteForChild(childKey) && childMergeTree.value == null; + if (!serverNode.hasChild(childKey) && !isUnknownDeepMerge) { + var serverChild = viewCache.getServerCache().getNode().getImmediateChild(childKey); + var newChild = self.applyMerge_(serverChild, childMergeTree); + curViewCache = self.applyServerOverwrite_(curViewCache, new Path(childKey), newChild, writesCache, + serverCache, filterServerNode, accumulator); + } + }); + + return curViewCache; + }; + + /** + * @param {!ViewCache} viewCache + * @param {!Path} ackPath + * @param {!ImmutableTree} affectedTree + * @param {!fb.core.WriteTreeRef} writesCache + * @param {?fb.core.snap.Node} optCompleteCache + * @param {!ChildChangeAccumulator} accumulator + * @return {!ViewCache} + * @private + */ + ackUserWrite_(viewCache, ackPath, affectedTree, writesCache, + optCompleteCache, accumulator) { + if (writesCache.shadowingWrite(ackPath) != null) { + return viewCache; + } + + // Only filter server node if it is currently filtered + var filterServerNode = viewCache.getServerCache().isFiltered(); + + // Essentially we'll just get our existing server cache for the affected paths and re-apply it as a server update + // now that it won't be shadowed. + var serverCache = viewCache.getServerCache(); + if (affectedTree.value != null) { + // This is an overwrite. + if ((ackPath.isEmpty() && serverCache.isFullyInitialized()) || serverCache.isCompleteForPath(ackPath)) { + return this.applyServerOverwrite_(viewCache, ackPath, serverCache.getNode().getChild(ackPath), + writesCache, optCompleteCache, filterServerNode, accumulator); + } else if (ackPath.isEmpty()) { + // This is a goofy edge case where we are acking data at this location but don't have full data. We + // should just re-apply whatever we have in our cache as a merge. + var changedChildren = /** @type {ImmutableTree} */ + (ImmutableTree.Empty); + serverCache.getNode().forEachChild(KEY_INDEX, function(name, node) { + changedChildren = changedChildren.set(new Path(name), node); + }); + return this.applyServerMerge_(viewCache, ackPath, changedChildren, writesCache, optCompleteCache, + filterServerNode, accumulator); + } else { + return viewCache; + } + } else { + // This is a merge. + var changedChildren = /** @type {ImmutableTree} */ + (ImmutableTree.Empty); + affectedTree.foreach(function(mergePath, value) { + var serverCachePath = ackPath.child(mergePath); + if (serverCache.isCompleteForPath(serverCachePath)) { + changedChildren = changedChildren.set(mergePath, serverCache.getNode().getChild(serverCachePath)); + } + }); + return this.applyServerMerge_(viewCache, ackPath, changedChildren, writesCache, optCompleteCache, + filterServerNode, accumulator); + } + }; + + /** + * @param {!ViewCache} viewCache + * @param {!Path} path + * @param {!fb.core.WriteTreeRef} writesCache + * @param {?fb.core.snap.Node} optCompleteServerCache + * @param {!ChildChangeAccumulator} accumulator + * @return {!ViewCache} + * @private + */ + revertUserWrite_(viewCache, path, writesCache, optCompleteServerCache, + accumulator) { + var complete; + if (writesCache.shadowingWrite(path) != null) { + return viewCache; + } else { + var source = new WriteTreeCompleteChildSource(writesCache, viewCache, optCompleteServerCache); + var oldEventCache = viewCache.getEventCache().getNode(); + var newEventCache; + if (path.isEmpty() || path.getFront() === '.priority') { + var newNode; + if (viewCache.getServerCache().isFullyInitialized()) { + newNode = writesCache.calcCompleteEventCache(viewCache.getCompleteServerSnap()); + } else { + var serverChildren = viewCache.getServerCache().getNode(); + assert(serverChildren instanceof ChildrenNode, + 'serverChildren would be complete if leaf node'); + newNode = writesCache.calcCompleteEventChildren(/** @type {!ChildrenNode} */ (serverChildren)); + } + newNode = /** @type {!fb.core.snap.Node} newNode */ (newNode); + newEventCache = this.filter_.updateFullNode(oldEventCache, newNode, accumulator); + } else { + var childKey = path.getFront(); + var newChild = writesCache.calcCompleteChild(childKey, viewCache.getServerCache()); + if (newChild == null && viewCache.getServerCache().isCompleteForChild(childKey)) { + newChild = oldEventCache.getImmediateChild(childKey); + } + if (newChild != null) { + newEventCache = this.filter_.updateChild(oldEventCache, childKey, newChild, path.popFront(), source, + accumulator); + } else if (viewCache.getEventCache().getNode().hasChild(childKey)) { + // No complete child available, delete the existing one, if any + newEventCache = this.filter_.updateChild(oldEventCache, childKey, ChildrenNode.EMPTY_NODE, path.popFront(), + source, accumulator); + } else { + newEventCache = oldEventCache; + } + if (newEventCache.isEmpty() && viewCache.getServerCache().isFullyInitialized()) { + // We might have reverted all child writes. Maybe the old event was a leaf node + complete = writesCache.calcCompleteEventCache(viewCache.getCompleteServerSnap()); + if (complete.isLeafNode()) { + newEventCache = this.filter_.updateFullNode(newEventCache, complete, accumulator); + } + } + } + complete = viewCache.getServerCache().isFullyInitialized() || + writesCache.shadowingWrite(Path.Empty) != null; + return viewCache.updateEventSnap(newEventCache, complete, this.filter_.filtersNodes()); + } + }; + + /** + * @param {!ViewCache} viewCache + * @param {!Path} path + * @param {!fb.core.WriteTreeRef} writesCache + * @param {?fb.core.snap.Node} serverCache + * @param {!ChildChangeAccumulator} accumulator + * @return {!ViewCache} + * @private + */ + listenComplete_(viewCache, path, writesCache, serverCache, + accumulator) { + var oldServerNode = viewCache.getServerCache(); + var newViewCache = viewCache.updateServerSnap(oldServerNode.getNode(), + oldServerNode.isFullyInitialized() || path.isEmpty(), oldServerNode.isFiltered()); + return this.generateEventCacheAfterServerEvent_(newViewCache, path, writesCache, + NO_COMPLETE_CHILD_SOURCE, accumulator); + }; +} + diff --git a/src/database/core/view/filter/IndexedFilter.ts b/src/database/core/view/filter/IndexedFilter.ts new file mode 100644 index 00000000000..f8b627a0708 --- /dev/null +++ b/src/database/core/view/filter/IndexedFilter.ts @@ -0,0 +1,123 @@ +import { assert } from "../../../../utils/assert"; +import { Change } from "../Change"; +import { ChildrenNode } from "../../snap/ChildrenNode"; +import { PRIORITY_INDEX } from "../../snap/indexes/PriorityIndex"; +import { NodeFilter } from './NodeFilter'; +import { Index } from '../../snap/indexes/Index'; +import { Path } from '../../util/Path'; +import { CompleteChildSource } from '../CompleteChildSource'; +import { ChildChangeAccumulator } from '../ChildChangeAccumulator'; +import { Node } from '../../snap/Node'; + +/** + * Doesn't really filter nodes but applies an index to the node and keeps track of any changes + * + * @constructor + * @implements {NodeFilter} + * @param {!Index} index + */ +export class IndexedFilter implements NodeFilter { + constructor(private readonly index_: Index) { + } + + updateChild(snap: Node, key: string, newChild: Node, affectedPath: Path, + source: CompleteChildSource, + optChangeAccumulator: ChildChangeAccumulator | null): Node { + assert(snap.isIndexed(this.index_), 'A node must be indexed if only a child is updated'); + const oldChild = snap.getImmediateChild(key); + // Check if anything actually changed. + if (oldChild.getChild(affectedPath).equals(newChild.getChild(affectedPath))) { + // There's an edge case where a child can enter or leave the view because affectedPath was set to null. + // In this case, affectedPath will appear null in both the old and new snapshots. So we need + // to avoid treating these cases as "nothing changed." + if (oldChild.isEmpty() == newChild.isEmpty()) { + // Nothing changed. + + // This assert should be valid, but it's expensive (can dominate perf testing) so don't actually do it. + //assert(oldChild.equals(newChild), 'Old and new snapshots should be equal.'); + return snap; + } + } + + if (optChangeAccumulator != null) { + if (newChild.isEmpty()) { + if (snap.hasChild(key)) { + optChangeAccumulator.trackChildChange(Change.childRemovedChange(key, oldChild)); + } else { + assert(snap.isLeafNode(), 'A child remove without an old child only makes sense on a leaf node'); + } + } else if (oldChild.isEmpty()) { + optChangeAccumulator.trackChildChange(Change.childAddedChange(key, newChild)); + } else { + optChangeAccumulator.trackChildChange(Change.childChangedChange(key, newChild, oldChild)); + } + } + if (snap.isLeafNode() && newChild.isEmpty()) { + return snap; + } else { + // Make sure the node is indexed + return snap.updateImmediateChild(key, newChild).withIndex(this.index_); + } + }; + + /** + * @inheritDoc + */ + updateFullNode(oldSnap: Node, newSnap: Node, + optChangeAccumulator: ChildChangeAccumulator | null): Node { + if (optChangeAccumulator != null) { + if (!oldSnap.isLeafNode()) { + oldSnap.forEachChild(PRIORITY_INDEX, function(key, childNode) { + if (!newSnap.hasChild(key)) { + optChangeAccumulator.trackChildChange(Change.childRemovedChange(key, childNode)); + } + }); + } + if (!newSnap.isLeafNode()) { + newSnap.forEachChild(PRIORITY_INDEX, function(key, childNode) { + if (oldSnap.hasChild(key)) { + const oldChild = oldSnap.getImmediateChild(key); + if (!oldChild.equals(childNode)) { + optChangeAccumulator.trackChildChange(Change.childChangedChange(key, childNode, oldChild)); + } + } else { + optChangeAccumulator.trackChildChange(Change.childAddedChange(key, childNode)); + } + }); + } + } + return newSnap.withIndex(this.index_); + }; + + /** + * @inheritDoc + */ + updatePriority(oldSnap: Node, newPriority: Node): Node { + if (oldSnap.isEmpty()) { + return ChildrenNode.EMPTY_NODE; + } else { + return oldSnap.updatePriority(newPriority); + } + }; + + /** + * @inheritDoc + */ + filtersNodes(): boolean { + return false; + }; + + /** + * @inheritDoc + */ + getIndexedFilter(): IndexedFilter { + return this; + }; + + /** + * @inheritDoc + */ + getIndex(): Index { + return this.index_; + }; +} diff --git a/src/database/core/view/filter/LimitedFilter.ts b/src/database/core/view/filter/LimitedFilter.ts new file mode 100644 index 00000000000..9acc36cb7e1 --- /dev/null +++ b/src/database/core/view/filter/LimitedFilter.ts @@ -0,0 +1,268 @@ +import { RangedFilter } from "./RangedFilter"; +import { ChildrenNode } from "../../snap/ChildrenNode"; +import { Node, NamedNode } from "../../snap/Node"; +import { assert } from "../../../../utils/assert"; +import { Change } from "../Change"; +/** + * Applies a limit and a range to a node and uses RangedFilter to do the heavy lifting where possible + * + * @constructor + * @implements {NodeFilter} + * @param {!QueryParams} params + */ +export class LimitedFilter { + /** + * @const + * @type {RangedFilter} + * @private + */ + private rangedFilter_; + + /** + * @const + * @type {!Index} + * @private + */ + private index_; + + /** + * @const + * @type {number} + * @private + */ + private limit_; + + /** + * @const + * @type {boolean} + * @private + */ + private reverse_; + + constructor(params) { + /** + * @const + * @type {RangedFilter} + * @private + */ + this.rangedFilter_ = new RangedFilter(params); + + /** + * @const + * @type {!Index} + * @private + */ + this.index_ = params.getIndex(); + + /** + * @const + * @type {number} + * @private + */ + this.limit_ = params.getLimit(); + + /** + * @const + * @type {boolean} + * @private + */ + this.reverse_ = !params.isViewFromLeft(); + }; + /** + * @inheritDoc + */ + updateChild(snap, key, newChild, affectedPath, source, optChangeAccumulator) { + if (!this.rangedFilter_.matches(new NamedNode(key, newChild))) { + newChild = ChildrenNode.EMPTY_NODE; + } + if (snap.getImmediateChild(key).equals(newChild)) { + // No change + return snap; + } else if (snap.numChildren() < this.limit_) { + return this.rangedFilter_.getIndexedFilter().updateChild(snap, key, newChild, affectedPath, source, + optChangeAccumulator); + } else { + return this.fullLimitUpdateChild_(snap, key, newChild, source, optChangeAccumulator); + } + }; + + /** + * @inheritDoc + */ + updateFullNode(oldSnap, newSnap, optChangeAccumulator) { + var filtered; + if (newSnap.isLeafNode() || newSnap.isEmpty()) { + // Make sure we have a children node with the correct index, not a leaf node; + filtered = ChildrenNode.EMPTY_NODE.withIndex(this.index_); + } else { + if (this.limit_ * 2 < newSnap.numChildren() && newSnap.isIndexed(this.index_)) { + // Easier to build up a snapshot, since what we're given has more than twice the elements we want + filtered = ChildrenNode.EMPTY_NODE.withIndex(this.index_); + // anchor to the startPost, endPost, or last element as appropriate + var iterator; + newSnap = /** @type {!ChildrenNode} */ (newSnap); + if (this.reverse_) { + iterator = newSnap.getReverseIteratorFrom(this.rangedFilter_.getEndPost(), this.index_); + } else { + iterator = newSnap.getIteratorFrom(this.rangedFilter_.getStartPost(), this.index_); + } + var count = 0; + while (iterator.hasNext() && count < this.limit_) { + var next = iterator.getNext(); + var inRange; + if (this.reverse_) { + inRange = this.index_.compare(this.rangedFilter_.getStartPost(), next) <= 0; + } else { + inRange = this.index_.compare(next, this.rangedFilter_.getEndPost()) <= 0; + } + if (inRange) { + filtered = filtered.updateImmediateChild(next.name, next.node); + count++; + } else { + // if we have reached the end post, we cannot keep adding elemments + break; + } + } + } else { + // The snap contains less than twice the limit. Faster to delete from the snap than build up a new one + filtered = newSnap.withIndex(this.index_); + // Don't support priorities on queries + filtered = /** @type {!ChildrenNode} */ (filtered.updatePriority(ChildrenNode.EMPTY_NODE)); + var startPost; + var endPost; + var cmp; + if (this.reverse_) { + iterator = filtered.getReverseIterator(this.index_); + startPost = this.rangedFilter_.getEndPost(); + endPost = this.rangedFilter_.getStartPost(); + var indexCompare = this.index_.getCompare(); + cmp = function(a, b) { return indexCompare(b, a); }; + } else { + iterator = filtered.getIterator(this.index_); + startPost = this.rangedFilter_.getStartPost(); + endPost = this.rangedFilter_.getEndPost(); + cmp = this.index_.getCompare(); + } + + count = 0; + var foundStartPost = false; + while (iterator.hasNext()) { + next = iterator.getNext(); + if (!foundStartPost && cmp(startPost, next) <= 0) { + // start adding + foundStartPost = true; + } + inRange = foundStartPost && count < this.limit_ && cmp(next, endPost) <= 0; + if (inRange) { + count++; + } else { + filtered = filtered.updateImmediateChild(next.name, ChildrenNode.EMPTY_NODE); + } + } + } + } + return this.rangedFilter_.getIndexedFilter().updateFullNode(oldSnap, filtered, optChangeAccumulator); + }; + + /** + * @inheritDoc + */ + updatePriority(oldSnap, newPriority) { + // Don't support priorities on queries + return oldSnap; + }; + + /** + * @inheritDoc + */ + filtersNodes() { + return true; + }; + + /** + * @inheritDoc + */ + getIndexedFilter() { + return this.rangedFilter_.getIndexedFilter(); + }; + + /** + * @inheritDoc + */ + getIndex() { + return this.index_; + }; + + /** + * @param {!Node} snap + * @param {string} childKey + * @param {!Node} childSnap + * @param {!CompleteChildSource} source + * @param {?ChildChangeAccumulator} optChangeAccumulator + * @return {!Node} + * @private + */ + fullLimitUpdateChild_(snap: Node, childKey: string, childSnap: Node, source, changeAccumulator?) { + // TODO: rename all cache stuff etc to general snap terminology + var cmp; + if (this.reverse_) { + var indexCmp = this.index_.getCompare(); + cmp = function(a, b) { return indexCmp(b, a); }; + } else { + cmp = this.index_.getCompare(); + } + var oldEventCache = snap; + assert(oldEventCache.numChildren() == this.limit_, ''); + var newChildNamedNode = new NamedNode(childKey, childSnap); + var windowBoundary = (this.reverse_ ? oldEventCache.getFirstChild(this.index_) : oldEventCache.getLastChild(this.index_)); + var inRange = this.rangedFilter_.matches(newChildNamedNode); + if (oldEventCache.hasChild(childKey)) { + var oldChildSnap = oldEventCache.getImmediateChild(childKey); + var nextChild = source.getChildAfterChild(this.index_, windowBoundary, this.reverse_); + while (nextChild != null && (nextChild.name == childKey || oldEventCache.hasChild(nextChild.name))) { + // There is a weird edge case where a node is updated as part of a merge in the write tree, but hasn't + // been applied to the limited filter yet. Ignore this next child which will be updated later in + // the limited filter... + nextChild = source.getChildAfterChild(this.index_, nextChild, this.reverse_); + } + var compareNext = nextChild == null ? 1 : cmp(nextChild, newChildNamedNode); + var remainsInWindow = inRange && !childSnap.isEmpty() && compareNext >= 0; + if (remainsInWindow) { + if (changeAccumulator != null) { + changeAccumulator.trackChildChange(Change.childChangedChange(childKey, childSnap, oldChildSnap)); + } + return oldEventCache.updateImmediateChild(childKey, childSnap); + } else { + if (changeAccumulator != null) { + changeAccumulator.trackChildChange(Change.childRemovedChange(childKey, oldChildSnap)); + } + var newEventCache = oldEventCache.updateImmediateChild(childKey, ChildrenNode.EMPTY_NODE); + var nextChildInRange = nextChild != null && this.rangedFilter_.matches(nextChild); + if (nextChildInRange) { + if (changeAccumulator != null) { + changeAccumulator.trackChildChange(Change.childAddedChange(nextChild.name, nextChild.node)); + } + return newEventCache.updateImmediateChild(nextChild.name, nextChild.node); + } else { + return newEventCache; + } + } + } else if (childSnap.isEmpty()) { + // we're deleting a node, but it was not in the window, so ignore it + return snap; + } else if (inRange) { + if (cmp(windowBoundary, newChildNamedNode) >= 0) { + if (changeAccumulator != null) { + changeAccumulator.trackChildChange(Change.childRemovedChange(windowBoundary.name, windowBoundary.node)); + changeAccumulator.trackChildChange(Change.childAddedChange(childKey, childSnap)); + } + return oldEventCache.updateImmediateChild(childKey, childSnap).updateImmediateChild(windowBoundary.name, + ChildrenNode.EMPTY_NODE); + } else { + return snap; + } + } else { + return snap; + } + }; +} diff --git a/src/database/core/view/filter/NodeFilter.ts b/src/database/core/view/filter/NodeFilter.ts new file mode 100644 index 00000000000..eb0dea1cb52 --- /dev/null +++ b/src/database/core/view/filter/NodeFilter.ts @@ -0,0 +1,69 @@ +import { Node } from '../../snap/Node'; +import { Path } from '../../util/Path'; +import { CompleteChildSource } from '../CompleteChildSource'; +import { ChildChangeAccumulator } from '../ChildChangeAccumulator'; +import { Index } from '../../snap/indexes/Index'; + +/** + * NodeFilter is used to update nodes and complete children of nodes while applying queries on the fly and keeping + * track of any child changes. This class does not track value changes as value changes depend on more + * than just the node itself. Different kind of queries require different kind of implementations of this interface. + * @interface + */ +export interface NodeFilter { + + /** + * Update a single complete child in the snap. If the child equals the old child in the snap, this is a no-op. + * The method expects an indexed snap. + * + * @param {!Node} snap + * @param {string} key + * @param {!Node} newChild + * @param {!Path} affectedPath + * @param {!CompleteChildSource} source + * @param {?ChildChangeAccumulator} optChangeAccumulator + * @return {!Node} + */ + updateChild(snap: Node, key: string, newChild: Node, affectedPath: Path, + source: CompleteChildSource, + optChangeAccumulator: ChildChangeAccumulator | null): Node; + + /** + * Update a node in full and output any resulting change from this complete update. + * + * @param {!Node} oldSnap + * @param {!Node} newSnap + * @param {?ChildChangeAccumulator} optChangeAccumulator + * @return {!Node} + */ + updateFullNode(oldSnap: Node, newSnap: Node, + optChangeAccumulator: ChildChangeAccumulator | null): Node; + + /** + * Update the priority of the root node + * + * @param {!Node} oldSnap + * @param {!Node} newPriority + * @return {!Node} + */ + updatePriority(oldSnap: Node, newPriority: Node): Node; + + /** + * Returns true if children might be filtered due to query criteria + * + * @return {boolean} + */ + filtersNodes(): boolean; + + /** + * Returns the index filter that this filter uses to get a NodeFilter that doesn't filter any children. + * @return {!NodeFilter} + */ + getIndexedFilter(): NodeFilter; + + /** + * Returns the index that this filter uses + * @return {!Index} + */ + getIndex(): Index; +} diff --git a/src/database/core/view/filter/RangedFilter.ts b/src/database/core/view/filter/RangedFilter.ts new file mode 100644 index 00000000000..c9a16137811 --- /dev/null +++ b/src/database/core/view/filter/RangedFilter.ts @@ -0,0 +1,156 @@ +import { IndexedFilter } from "./IndexedFilter"; +import { PRIORITY_INDEX } from "../../../core/snap/indexes/PriorityIndex"; +import { Node, NamedNode } from "../../../core/snap/Node"; +import { ChildrenNode } from "../../../core/snap/ChildrenNode"; +/** + * Filters nodes by range and uses an IndexFilter to track any changes after filtering the node + * + * @constructor + * @implements {NodeFilter} + * @param {!fb.core.view.QueryParams} params + */ +export class RangedFilter { + /** + * @type {!IndexedFilter} + * @const + * @private + */ + private indexedFilter_: IndexedFilter; + + /** + * @const + * @type {!Index} + * @private + */ + private index_; + + /** + * @const + * @type {!NamedNode} + * @private + */ + private startPost_; + + /** + * @const + * @type {!NamedNode} + * @private + */ + private endPost_; + + constructor(params) { + this.indexedFilter_ = new IndexedFilter(params.getIndex()); + this.index_ = params.getIndex(); + this.startPost_ = this.getStartPost_(params); + this.endPost_ = this.getEndPost_(params); + }; + + /** + * @return {!NamedNode} + */ + getStartPost() { + return this.startPost_; + }; + + /** + * @return {!NamedNode} + */ + getEndPost() { + return this.endPost_; + }; + + /** + * @param {!NamedNode} node + * @return {boolean} + */ + matches(node) { + return (this.index_.compare(this.getStartPost(), node) <= 0 && this.index_.compare(node, this.getEndPost()) <= 0); + }; + + /** + * @inheritDoc + */ + updateChild(snap, key, newChild, affectedPath, source, optChangeAccumulator) { + if (!this.matches(new NamedNode(key, newChild))) { + newChild = ChildrenNode.EMPTY_NODE; + } + return this.indexedFilter_.updateChild(snap, key, newChild, affectedPath, source, optChangeAccumulator); + }; + + /** + * @inheritDoc + */ + updateFullNode(oldSnap, newSnap, optChangeAccumulator) { + if (newSnap.isLeafNode()) { + // Make sure we have a children node with the correct index, not a leaf node; + newSnap = ChildrenNode.EMPTY_NODE; + } + var filtered = newSnap.withIndex(this.index_); + // Don't support priorities on queries + filtered = filtered.updatePriority(ChildrenNode.EMPTY_NODE); + var self = this; + newSnap.forEachChild(PRIORITY_INDEX, function(key, childNode) { + if (!self.matches(new NamedNode(key, childNode))) { + filtered = filtered.updateImmediateChild(key, ChildrenNode.EMPTY_NODE); + } + }); + return this.indexedFilter_.updateFullNode(oldSnap, filtered, optChangeAccumulator); + }; + + /** + * @inheritDoc + */ + updatePriority(oldSnap, newPriority) { + // Don't support priorities on queries + return oldSnap; + }; + + /** + * @inheritDoc + */ + filtersNodes() { + return true; + }; + + /** + * @inheritDoc + */ + getIndexedFilter() { + return this.indexedFilter_; + }; + + /** + * @inheritDoc + */ + getIndex() { + return this.index_; + }; + + /** + * @param {!fb.core.view.QueryParams} params + * @return {!NamedNode} + * @private + */ + getStartPost_(params) { + if (params.hasStart()) { + var startName = params.getIndexStartName(); + return params.getIndex().makePost(params.getIndexStartValue(), startName); + } else { + return params.getIndex().minPost(); + } + }; + + /** + * @param {!fb.core.view.QueryParams} params + * @return {!NamedNode} + * @private + */ + getEndPost_(params) { + if (params.hasEnd()) { + var endName = params.getIndexEndName(); + return params.getIndex().makePost(params.getIndexEndValue(), endName); + } else { + return params.getIndex().maxPost(); + } + }; +} diff --git a/src/database/js-client/api/DataSnapshot.js b/src/database/js-client/api/DataSnapshot.js deleted file mode 100644 index 80e39155eb0..00000000000 --- a/src/database/js-client/api/DataSnapshot.js +++ /dev/null @@ -1,221 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.api.DataSnapshot'); -goog.require('fb.core.snap'); -goog.require('fb.core.util.SortedMap'); -goog.require('fb.core.util.validation'); - - -/** - * Class representing a firebase data snapshot. It wraps a SnapshotNode and - * surfaces the public methods (val, forEach, etc.) we want to expose. - * - * @constructor - * @param {!fb.core.snap.Node} node A SnapshotNode to wrap. - * @param {!Firebase} ref The ref of the location this snapshot came from. - * @param {!fb.core.snap.Index} index The iteration order for this snapshot - */ -fb.api.DataSnapshot = function(node, ref, index) { - /** - * @private - * @const - * @type {!fb.core.snap.Node} - */ - this.node_ = node; - - /** - * @private - * @type {!Firebase} - * @const - */ - this.query_ = ref; - - /** - * @const - * @type {!fb.core.snap.Index} - * @private - */ - this.index_ = index; -}; - - -/** - * Retrieves the snapshot contents as JSON. Returns null if the snapshot is - * empty. - * - * @return {*} JSON representation of the DataSnapshot contents, or null if empty. - */ -fb.api.DataSnapshot.prototype.val = function() { - fb.util.validation.validateArgCount('Firebase.DataSnapshot.val', 0, 0, arguments.length); - return this.node_.val(); -}; -goog.exportProperty(fb.api.DataSnapshot.prototype, 'val', fb.api.DataSnapshot.prototype.val); - - -/** - * Returns the snapshot contents as JSON, including priorities of node. Suitable for exporting - * the entire node contents. - * @return {*} JSON representation of the DataSnapshot contents, or null if empty. - */ -fb.api.DataSnapshot.prototype.exportVal = function() { - fb.util.validation.validateArgCount('Firebase.DataSnapshot.exportVal', 0, 0, arguments.length); - return this.node_.val(true); -}; -goog.exportProperty(fb.api.DataSnapshot.prototype, 'exportVal', fb.api.DataSnapshot.prototype.exportVal); - - -// Do not create public documentation. This is intended to make JSON serialization work but is otherwise unnecessary -// for end-users -fb.api.DataSnapshot.prototype.toJSON = function() { - // Optional spacer argument is unnecessary because we're depending on recursion rather than stringifying the content - fb.util.validation.validateArgCount('Firebase.DataSnapshot.toJSON', 0, 1, arguments.length); - return this.exportVal(); -}; -goog.exportProperty(fb.api.DataSnapshot.prototype, 'toJSON', fb.api.DataSnapshot.prototype.toJSON); - -/** - * Returns whether the snapshot contains a non-null value. - * - * @return {boolean} Whether the snapshot contains a non-null value, or is empty. - */ -fb.api.DataSnapshot.prototype.exists = function() { - fb.util.validation.validateArgCount('Firebase.DataSnapshot.exists', 0, 0, arguments.length); - return !this.node_.isEmpty(); -}; -goog.exportProperty(fb.api.DataSnapshot.prototype, 'exists', fb.api.DataSnapshot.prototype.exists); - - -/** - * Returns a DataSnapshot of the specified child node's contents. - * - * @param {!string} childPathString Path to a child. - * @return {!fb.api.DataSnapshot} DataSnapshot for child node. - */ -fb.api.DataSnapshot.prototype.child = function(childPathString) { - fb.util.validation.validateArgCount('Firebase.DataSnapshot.child', 0, 1, arguments.length); - if (goog.isNumber(childPathString)) - childPathString = String(childPathString); - fb.core.util.validation.validatePathString('Firebase.DataSnapshot.child', 1, childPathString, false); - - var childPath = new fb.core.util.Path(childPathString); - var childRef = this.query_.child(childPath); - return new fb.api.DataSnapshot(this.node_.getChild(childPath), childRef, fb.core.snap.PriorityIndex); -}; -goog.exportProperty(fb.api.DataSnapshot.prototype, 'child', fb.api.DataSnapshot.prototype.child); - - -/** - * Returns whether the snapshot contains a child at the specified path. - * - * @param {!string} childPathString Path to a child. - * @return {boolean} Whether the child exists. - */ -fb.api.DataSnapshot.prototype.hasChild = function(childPathString) { - fb.util.validation.validateArgCount('Firebase.DataSnapshot.hasChild', 1, 1, arguments.length); - fb.core.util.validation.validatePathString('Firebase.DataSnapshot.hasChild', 1, childPathString, false); - - var childPath = new fb.core.util.Path(childPathString); - return !this.node_.getChild(childPath).isEmpty(); -}; -goog.exportProperty(fb.api.DataSnapshot.prototype, 'hasChild', fb.api.DataSnapshot.prototype.hasChild); - - -/** - * Returns the priority of the object, or null if no priority was set. - * - * @return {string|number|null} The priority. - */ -fb.api.DataSnapshot.prototype.getPriority = function() { - fb.util.validation.validateArgCount('Firebase.DataSnapshot.getPriority', 0, 0, arguments.length); - - // typecast here because we never return deferred values or internal priorities (MAX_PRIORITY) - return /**@type {string|number|null} */ (this.node_.getPriority().val()); -}; -goog.exportProperty(fb.api.DataSnapshot.prototype, 'getPriority', fb.api.DataSnapshot.prototype.getPriority); - - -/** - * Iterates through child nodes and calls the specified action for each one. - * - * @param {function(!fb.api.DataSnapshot)} action Callback function to be called - * for each child. - * @return {boolean} True if forEach was canceled by action returning true for - * one of the child nodes. - */ -fb.api.DataSnapshot.prototype.forEach = function(action) { - fb.util.validation.validateArgCount('Firebase.DataSnapshot.forEach', 1, 1, arguments.length); - fb.util.validation.validateCallback('Firebase.DataSnapshot.forEach', 1, action, false); - - if (this.node_.isLeafNode()) - return false; - - var childrenNode = /** @type {!fb.core.snap.ChildrenNode} */ (this.node_); - var self = this; - // Sanitize the return value to a boolean. ChildrenNode.forEachChild has a weird return type... - return !!childrenNode.forEachChild(this.index_, function(key, node) { - return action(new fb.api.DataSnapshot(node, self.query_.child(key), fb.core.snap.PriorityIndex)); - }); -}; -goog.exportProperty(fb.api.DataSnapshot.prototype, 'forEach', fb.api.DataSnapshot.prototype.forEach); - - -/** - * Returns whether this DataSnapshot has children. - * @return {boolean} True if the DataSnapshot contains 1 or more child nodes. - */ -fb.api.DataSnapshot.prototype.hasChildren = function() { - fb.util.validation.validateArgCount('Firebase.DataSnapshot.hasChildren', 0, 0, arguments.length); - - if (this.node_.isLeafNode()) - return false; - else - return !this.node_.isEmpty(); -}; -goog.exportProperty(fb.api.DataSnapshot.prototype, 'hasChildren', fb.api.DataSnapshot.prototype.hasChildren); - - -/** - * @return {?string} The key of the location this snapshot's data came from. - */ -fb.api.DataSnapshot.prototype.getKey = function() { - fb.util.validation.validateArgCount('Firebase.DataSnapshot.key', 0, 0, arguments.length); - - return this.query_.getKey(); -}; -fb.core.util.exportPropGetter(fb.api.DataSnapshot.prototype, 'key', fb.api.DataSnapshot.prototype.getKey); - - -/** - * Returns the number of children for this DataSnapshot. - * @return {number} The number of children that this DataSnapshot contains. - */ -fb.api.DataSnapshot.prototype.numChildren = function() { - fb.util.validation.validateArgCount('Firebase.DataSnapshot.numChildren', 0, 0, arguments.length); - - return this.node_.numChildren(); -}; -goog.exportProperty(fb.api.DataSnapshot.prototype, 'numChildren', fb.api.DataSnapshot.prototype.numChildren); - - -/** - * @return {Firebase} The Firebase reference for the location this snapshot's data came from. - */ -fb.api.DataSnapshot.prototype.getRef = function() { - fb.util.validation.validateArgCount('Firebase.DataSnapshot.ref', 0, 0, arguments.length); - - return this.query_; -}; -fb.core.util.exportPropGetter(fb.api.DataSnapshot.prototype, 'ref', fb.api.DataSnapshot.prototype.getRef); diff --git a/src/database/js-client/api/Database.js b/src/database/js-client/api/Database.js deleted file mode 100644 index 5cd8d28c940..00000000000 --- a/src/database/js-client/api/Database.js +++ /dev/null @@ -1,151 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.api.Database'); -goog.require('fb.core.util.Path'); - - -/** - * Class representing a firebase database. - * @implements {firebase.Service} - */ -fb.api.Database = goog.defineClass(null, { - /** - * The constructor should not be called by users of our public API. - * @param {!fb.core.Repo} repo - */ - constructor: function(repo) { - if (!(repo instanceof fb.core.Repo)) { - fb.core.util.fatal("Don't call new Database() directly - please use firebase.database()."); - } - - /** @type {fb.core.Repo} */ - this.repo_ = repo; - - /** @type {Firebase} */ - this.root_ = new Firebase(repo, fb.core.util.Path.Empty); - - this.INTERNAL = new fb.api.DatabaseInternals(this); - }, - - app: null, - - /** - * Returns a reference to the root or the path specified in opt_pathString. - * @param {string=} opt_pathString - * @return {!Firebase} Firebase reference. - */ - ref: function(opt_pathString) { - this.checkDeleted_('ref'); - fb.util.validation.validateArgCount('database.ref', 0, 1, arguments.length); - - return goog.isDef(opt_pathString) ? this.root_.child(opt_pathString) : - /** @type {!Firebase} */ (this.root_); - }, - - /** - * Returns a reference to the root or the path specified in url. - * We throw a exception if the url is not in the same domain as the - * current repo. - * @param {string} url - * @return {!Firebase} Firebase reference. - */ - refFromURL: function(url) { - /** @const {string} */ - var apiName = 'database.refFromURL'; - this.checkDeleted_(apiName); - fb.util.validation.validateArgCount(apiName, 1, 1, arguments.length); - var parsedURL = fb.core.util.parseRepoInfo(url); - fb.core.util.validation.validateUrl(apiName, 1, parsedURL); - - var repoInfo = parsedURL.repoInfo; - if (repoInfo.host !== this.repo_.repoInfo_.host) { - fb.core.util.fatal(apiName + ": Host name does not match the current database: " + - "(found " + repoInfo.host + " but expected " + this.repo_.repoInfo_.host + ")"); - } - - return this.ref(parsedURL.path.toString()); - }, - - /** - * @param {string} apiName - * @private - */ - checkDeleted_: function(apiName) { - if (this.repo_ === null) { - fb.core.util.fatal("Cannot call " + apiName + " on a deleted database."); - } - }, - - // Make individual repo go offline. - goOffline: function() { - fb.util.validation.validateArgCount('database.goOffline', 0, 0, arguments.length); - this.checkDeleted_('goOffline'); - this.repo_.interrupt(); - }, - - goOnline: function () { - fb.util.validation.validateArgCount('database.goOnline', 0, 0, arguments.length); - this.checkDeleted_('goOnline'); - this.repo_.resume(); - }, - - statics: { - ServerValue: { - 'TIMESTAMP': { - '.sv' : 'timestamp' - } - } - } -}); - -// Note: This is an un-minfied property of the Database only. -Object.defineProperty(fb.api.Database.prototype, 'app', { - /** - * @this {!fb.api.Database} - * @return {!firebase.app.App} - */ - get: function() { - return this.repo_.app; - } -}); - - -fb.api.DatabaseInternals = goog.defineClass(null, { - /** @param {!fb.api.Database} database */ - constructor: function(database) { - this.database = database; - }, - - /** @return {firebase.Promise} */ - delete: function() { - this.database.checkDeleted_('delete'); - fb.core.RepoManager.getInstance().deleteRepo(/** @type {!fb.core.Repo} */ (this.database.repo_)); - - this.database.repo_ = null; - this.database.root_ = null; - this.database.INTERNAL = null; - this.database = null; - return firebase.Promise.resolve(); - }, -}); - -goog.exportProperty(fb.api.Database.prototype, 'ref', fb.api.Database.prototype.ref); -goog.exportProperty(fb.api.Database.prototype, 'refFromURL', fb.api.Database.prototype.refFromURL); -goog.exportProperty(fb.api.Database.prototype, 'goOnline', fb.api.Database.prototype.goOnline); -goog.exportProperty(fb.api.Database.prototype, 'goOffline', fb.api.Database.prototype.goOffline); - -goog.exportProperty(fb.api.DatabaseInternals.prototype, 'delete', - fb.api.DatabaseInternals.prototype.delete); diff --git a/src/database/js-client/api/Firebase.js b/src/database/js-client/api/Firebase.js deleted file mode 100644 index 54057de2500..00000000000 --- a/src/database/js-client/api/Firebase.js +++ /dev/null @@ -1,326 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -// TODO(koss): Change to provide fb.api.Firebase - no longer provide the global. -goog.provide('Firebase'); - -goog.require('fb.api.INTERNAL'); -goog.require('fb.api.OnDisconnect'); -goog.require('fb.api.Query'); -goog.require('fb.api.TEST_ACCESS'); -goog.require('fb.api.TransactionResult'); -goog.require('fb.constants'); -goog.require('fb.core.Repo'); -goog.require('fb.core.RepoManager'); -goog.require('fb.core.util'); -goog.require('fb.core.util.Path'); -goog.require('fb.core.util.nextPushId'); -goog.require('fb.core.util.validation'); -goog.require('fb.core.view.QueryParams'); -goog.require('fb.util.obj'); -goog.require('fb.util.promise'); -goog.require('fb.util.promise.Deferred'); -goog.require('fb.util.validation'); - - -/** @interface */ -function letMeUseMapAccessors() {} - - -Firebase = goog.defineClass(fb.api.Query, { - /** - * Call options: - * new Firebase(Repo, Path) or - * new Firebase(url: string, string|RepoManager) - * - * Externally - this is the firebase.database.Reference type. - * - * @param {!fb.core.Repo} repo - * @param {(!fb.core.util.Path)} path - * @extends {fb.api.Query} - */ - constructor: function(repo, path) { - if (!(repo instanceof fb.core.Repo)) { - throw new Error("new Firebase() no longer supported - use app.database()."); - } - - // call Query's constructor, passing in the repo and path. - fb.api.Query.call(this, repo, path, fb.core.view.QueryParams.DEFAULT, - /*orderByCalled=*/false); - - /** - * When defined is the then function for the promise + Firebase hybrid - * returned by push() When then is defined, catch will be as well, though - * it's created using some hackery to get around conflicting ES3 and Closure - * Compiler limitations. - * @type {Function|undefined} - */ - this.then = void 0; - /** @type {letMeUseMapAccessors} */ (this)['catch'] = void 0; - }, - - /** @return {?string} */ - getKey: function() { - fb.util.validation.validateArgCount('Firebase.key', 0, 0, arguments.length); - - if (this.path.isEmpty()) - return null; - else - return this.path.getBack(); - }, - - /** - * @param {!(string|fb.core.util.Path)} pathString - * @return {!Firebase} - */ - child: function(pathString) { - fb.util.validation.validateArgCount('Firebase.child', 1, 1, arguments.length); - if (goog.isNumber(pathString)) { - pathString = String(pathString); - } else if (!(pathString instanceof fb.core.util.Path)) { - if (this.path.getFront() === null) - fb.core.util.validation.validateRootPathString('Firebase.child', 1, pathString, false); - else - fb.core.util.validation.validatePathString('Firebase.child', 1, pathString, false); - } - - return new Firebase(this.repo, this.path.child(pathString)); - }, - - /** @return {?Firebase} */ - getParent: function() { - fb.util.validation.validateArgCount('Firebase.parent', 0, 0, arguments.length); - - var parentPath = this.path.parent(); - return parentPath === null ? null : new Firebase(this.repo, parentPath); - }, - - /** @return {!Firebase} */ - getRoot: function() { - fb.util.validation.validateArgCount('Firebase.ref', 0, 0, arguments.length); - - var ref = this; - while (ref.getParent() !== null) { - ref = ref.getParent(); - } - return ref; - }, - - /** @return {!fb.api.Database} */ - databaseProp: function() { - return this.repo.database; - }, - - /** - * @param {*} newVal - * @param {function(?Error)=} opt_onComplete - * @return {!firebase.Promise} - */ - set: function(newVal, opt_onComplete) { - fb.util.validation.validateArgCount('Firebase.set', 1, 2, arguments.length); - fb.core.util.validation.validateWritablePath('Firebase.set', this.path); - fb.core.util.validation.validateFirebaseDataArg('Firebase.set', 1, newVal, this.path, false); - fb.util.validation.validateCallback('Firebase.set', 2, opt_onComplete, true); - - var deferred = new fb.util.promise.Deferred(); - this.repo.setWithPriority(this.path, newVal, /*priority=*/ null, deferred.wrapCallback(opt_onComplete)); - return deferred.promise; - }, - - /** - * @param {!Object} objectToMerge - * @param {function(?Error)=} opt_onComplete - * @return {!firebase.Promise} - */ - update: function(objectToMerge, opt_onComplete) { - fb.util.validation.validateArgCount('Firebase.update', 1, 2, arguments.length); - fb.core.util.validation.validateWritablePath('Firebase.update', this.path); - - if (goog.isArray(objectToMerge)) { - var newObjectToMerge = {}; - for (var i = 0; i < objectToMerge.length; ++i) { - newObjectToMerge['' + i] = objectToMerge[i]; - } - objectToMerge = newObjectToMerge; - fb.core.util.warn('Passing an Array to Firebase.update() is deprecated. ' + - 'Use set() if you want to overwrite the existing data, or ' + - 'an Object with integer keys if you really do want to ' + - 'only update some of the children.' - ); - } - fb.core.util.validation.validateFirebaseMergeDataArg('Firebase.update', 1, objectToMerge, this.path, false); - fb.util.validation.validateCallback('Firebase.update', 2, opt_onComplete, true); - var deferred = new fb.util.promise.Deferred(); - this.repo.update(this.path, objectToMerge, deferred.wrapCallback(opt_onComplete)); - return deferred.promise; - }, - - /** - * @param {*} newVal - * @param {string|number|null} newPriority - * @param {function(?Error)=} opt_onComplete - * @return {!firebase.Promise} - */ - setWithPriority: function(newVal, newPriority, opt_onComplete) { - fb.util.validation.validateArgCount('Firebase.setWithPriority', 2, 3, arguments.length); - fb.core.util.validation.validateWritablePath('Firebase.setWithPriority', this.path); - fb.core.util.validation.validateFirebaseDataArg('Firebase.setWithPriority', 1, newVal, this.path, false); - fb.core.util.validation.validatePriority('Firebase.setWithPriority', 2, newPriority, false); - fb.util.validation.validateCallback('Firebase.setWithPriority', 3, opt_onComplete, true); - - if (this.getKey() === '.length' || this.getKey() === '.keys') - throw 'Firebase.setWithPriority failed: ' + this.getKey() + ' is a read-only object.'; - - var deferred = new fb.util.promise.Deferred(); - this.repo.setWithPriority(this.path, newVal, newPriority, deferred.wrapCallback(opt_onComplete)); - return deferred.promise; - }, - - /** - * @param {function(?Error)=} opt_onComplete - * @return {!firebase.Promise} - */ - remove: function(opt_onComplete) { - fb.util.validation.validateArgCount('Firebase.remove', 0, 1, arguments.length); - fb.core.util.validation.validateWritablePath('Firebase.remove', this.path); - fb.util.validation.validateCallback('Firebase.remove', 1, opt_onComplete, true); - - return this.set(null, opt_onComplete); - }, - - /** - * @param {function(*):*} transactionUpdate - * @param {(function(?Error, boolean, ?fb.api.DataSnapshot))=} opt_onComplete - * @param {boolean=} opt_applyLocally - * @return {!firebase.Promise} - */ - transaction: function(transactionUpdate, opt_onComplete, opt_applyLocally) { - fb.util.validation.validateArgCount('Firebase.transaction', 1, 3, arguments.length); - fb.core.util.validation.validateWritablePath('Firebase.transaction', this.path); - fb.util.validation.validateCallback('Firebase.transaction', 1, transactionUpdate, false); - fb.util.validation.validateCallback('Firebase.transaction', 2, opt_onComplete, true); - // NOTE: opt_applyLocally is an internal-only option for now. We need to decide if we want to keep it and how - // to expose it. - fb.core.util.validation.validateBoolean('Firebase.transaction', 3, opt_applyLocally, true); - - if (this.getKey() === '.length' || this.getKey() === '.keys') - throw 'Firebase.transaction failed: ' + this.getKey() + ' is a read-only object.'; - - if (typeof opt_applyLocally === 'undefined') - opt_applyLocally = true; - - var deferred = new fb.util.promise.Deferred(); - if (goog.isFunction(opt_onComplete)) { - fb.util.promise.attachDummyErrorHandler(deferred.promise); - } - - var promiseComplete = function(error, committed, snapshot) { - if (error) { - deferred.reject(error); - } else { - deferred.resolve(new fb.api.TransactionResult(committed, snapshot)); - } - if (goog.isFunction(opt_onComplete)) { - opt_onComplete(error, committed, snapshot); - } - }; - this.repo.startTransaction(this.path, transactionUpdate, promiseComplete, opt_applyLocally); - - return deferred.promise; - }, - - /** - * @param {string|number|null} priority - * @param {function(?Error)=} opt_onComplete - * @return {!firebase.Promise} - */ - setPriority: function(priority, opt_onComplete) { - fb.util.validation.validateArgCount('Firebase.setPriority', 1, 2, arguments.length); - fb.core.util.validation.validateWritablePath('Firebase.setPriority', this.path); - fb.core.util.validation.validatePriority('Firebase.setPriority', 1, priority, false); - fb.util.validation.validateCallback('Firebase.setPriority', 2, opt_onComplete, true); - - var deferred = new fb.util.promise.Deferred(); - this.repo.setWithPriority(this.path.child('.priority'), priority, null, deferred.wrapCallback(opt_onComplete)); - return deferred.promise; - }, - - /** - * @param {*=} opt_value - * @param {function(?Error)=} opt_onComplete - * @return {!Firebase} - */ - push: function(opt_value, opt_onComplete) { - fb.util.validation.validateArgCount('Firebase.push', 0, 2, arguments.length); - fb.core.util.validation.validateWritablePath('Firebase.push', this.path); - fb.core.util.validation.validateFirebaseDataArg('Firebase.push', 1, opt_value, this.path, true); - fb.util.validation.validateCallback('Firebase.push', 2, opt_onComplete, true); - - var now = this.repo.serverTime(); - var name = fb.core.util.nextPushId(now); - - // push() returns a ThennableReference whose promise is fulfilled with a regular Reference. - // We use child() to create handles to two different references. The first is turned into a - // ThennableReference below by adding then() and catch() methods and is used as the - // return value of push(). The second remains a regular Reference and is used as the fulfilled - // value of the first ThennableReference. - var thennablePushRef = this.child(name); - var pushRef = this.child(name); - - var promise; - if (goog.isDefAndNotNull(opt_value)) { - promise = thennablePushRef.set(opt_value, opt_onComplete).then(function () { return pushRef; }); - } else { - promise = fb.util.promise.Promise.resolve(pushRef); - } - - thennablePushRef.then = goog.bind(promise.then, promise); - /** @type {letMeUseMapAccessors} */ (thennablePushRef)["catch"] = goog.bind(promise.then, promise, void 0); - - if (goog.isFunction(opt_onComplete)) { - fb.util.promise.attachDummyErrorHandler(promise); - } - - return thennablePushRef; - }, - - /** - * @return {!fb.api.OnDisconnect} - */ - onDisconnect: function() { - fb.core.util.validation.validateWritablePath('Firebase.onDisconnect', this.path); - return new fb.api.OnDisconnect(this.repo, this.path); - } -}); // end Firebase - - -// Export Firebase (Reference) methods -goog.exportProperty(Firebase.prototype, 'child', Firebase.prototype.child); -goog.exportProperty(Firebase.prototype, 'set', Firebase.prototype.set); -goog.exportProperty(Firebase.prototype, 'update', Firebase.prototype.update); -goog.exportProperty(Firebase.prototype, 'setWithPriority', Firebase.prototype.setWithPriority); -goog.exportProperty(Firebase.prototype, 'remove', Firebase.prototype.remove); -goog.exportProperty(Firebase.prototype, 'transaction', Firebase.prototype.transaction); -goog.exportProperty(Firebase.prototype, 'setPriority', Firebase.prototype.setPriority); -goog.exportProperty(Firebase.prototype, 'push', Firebase.prototype.push); -goog.exportProperty(Firebase.prototype, 'onDisconnect', Firebase.prototype.onDisconnect); - -// Internal code should NOT use these exported properties - because when they are -// minified, they will refernce the minified name. We could fix this by including -// our our externs file for all our exposed symbols. -fb.core.util.exportPropGetter(Firebase.prototype, 'database', Firebase.prototype.databaseProp); -fb.core.util.exportPropGetter(Firebase.prototype, 'key', Firebase.prototype.getKey); -fb.core.util.exportPropGetter(Firebase.prototype, 'parent', Firebase.prototype.getParent); -fb.core.util.exportPropGetter(Firebase.prototype, 'root', Firebase.prototype.getRoot); diff --git a/src/database/js-client/api/Query.js b/src/database/js-client/api/Query.js deleted file mode 100644 index 3bb3595d10a..00000000000 --- a/src/database/js-client/api/Query.js +++ /dev/null @@ -1,539 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.api.Query'); -goog.require('fb.core.snap.KeyIndex'); -goog.require('fb.core.snap.PathIndex'); -goog.require('fb.core.snap.PriorityIndex'); -goog.require('fb.core.snap.ValueIndex'); -goog.require('fb.core.util'); -goog.require('fb.core.util.ObjectToUniqueKey'); -goog.require('fb.core.util.Path'); -goog.require('fb.core.util.validation'); -goog.require('fb.core.view.ChildEventRegistration'); -goog.require('fb.core.view.ValueEventRegistration'); -goog.require('fb.util.promise'); -goog.require('fb.util.promise.Deferred'); -goog.require('fb.util.validation'); - - -/** - * A Query represents a filter to be applied to a firebase location. This object purely represents the - * query expression (and exposes our public API to build the query). The actual query logic is in ViewBase.js. - * - * Since every Firebase reference is a query, Firebase inherits from this object. - */ -fb.api.Query = goog.defineClass(null, { - /** - * @param {!fb.core.Repo} repo - * @param {!fb.core.util.Path} path - * @param {!fb.core.view.QueryParams} queryParams - * @param {!boolean} orderByCalled - */ - constructor: function(repo, path, queryParams, orderByCalled) { - this.repo = repo; - this.path = path; - this.queryParams_ = queryParams; - this.orderByCalled_ = orderByCalled; - }, - - /** - * Validates start/end values for queries. - * @param {!fb.core.view.QueryParams} params - * @private - */ - validateQueryEndpoints_: function(params) { - var startNode = null; - var endNode = null; - if (params.hasStart()) { - startNode = params.getIndexStartValue(); - } - if (params.hasEnd()) { - endNode = params.getIndexEndValue(); - } - - if (params.getIndex() === fb.core.snap.KeyIndex) { - var tooManyArgsError = 'Query: When ordering by key, you may only pass one argument to ' + - 'startAt(), endAt(), or equalTo().'; - var wrongArgTypeError = 'Query: When ordering by key, the argument passed to startAt(), endAt(),' + - 'or equalTo() must be a string.'; - if (params.hasStart()) { - var startName = params.getIndexStartName(); - if (startName != fb.core.util.MIN_NAME) { - throw new Error(tooManyArgsError); - } else if (typeof(startNode) !== 'string') { - throw new Error(wrongArgTypeError); - } - } - if (params.hasEnd()) { - var endName = params.getIndexEndName(); - if (endName != fb.core.util.MAX_NAME) { - throw new Error(tooManyArgsError); - } else if (typeof(endNode) !== 'string') { - throw new Error(wrongArgTypeError); - } - } - } - else if (params.getIndex() === fb.core.snap.PriorityIndex) { - if ((startNode != null && !fb.core.util.validation.isValidPriority(startNode)) || - (endNode != null && !fb.core.util.validation.isValidPriority(endNode))) { - throw new Error('Query: When ordering by priority, the first argument passed to startAt(), ' + - 'endAt(), or equalTo() must be a valid priority value (null, a number, or a string).'); - } - } else { - fb.core.util.assert((params.getIndex() instanceof fb.core.snap.PathIndex) || - (params.getIndex() === fb.core.snap.ValueIndex), 'unknown index type.'); - if ((startNode != null && typeof startNode === 'object') || - (endNode != null && typeof endNode === 'object')) { - throw new Error('Query: First argument passed to startAt(), endAt(), or equalTo() cannot be ' + - 'an object.'); - } - } - }, - - /** - * Validates that limit* has been called with the correct combination of parameters - * @param {!fb.core.view.QueryParams} params - * @private - */ - validateLimit_: function(params) { - if (params.hasStart() && params.hasEnd() && params.hasLimit() && !params.hasAnchoredLimit()) { - throw new Error( - "Query: Can't combine startAt(), endAt(), and limit(). Use limitToFirst() or limitToLast() instead." - ); - } - }, - - /** - * Validates that no other order by call has been made - * @param {!string} fnName - * @private - */ - validateNoPreviousOrderByCall_: function(fnName) { - if (this.orderByCalled_ === true) { - throw new Error(fnName + ": You can't combine multiple orderBy calls."); - } - }, - - /** - * @return {!fb.core.view.QueryParams} - */ - getQueryParams: function() { - return this.queryParams_; - }, - - /** - * @return {!Firebase} - */ - getRef: function() { - fb.util.validation.validateArgCount('Query.ref', 0, 0, arguments.length); - // This is a slight hack. We cannot goog.require('fb.api.Firebase'), since Firebase requires fb.api.Query. - // However, we will always export 'Firebase' to the global namespace, so it's guaranteed to exist by the time this - // method gets called. - return new Firebase(this.repo, this.path); - }, - - /** - * @param {!string} eventType - * @param {!function(fb.api.DataSnapshot, string=)} callback - * @param {(function(Error)|Object)=} opt_cancelCallbackOrContext - * @param {Object=} opt_context - * @return {!function(fb.api.DataSnapshot, string=)} - */ - on: function(eventType, callback, opt_cancelCallbackOrContext, opt_context) { - fb.util.validation.validateArgCount('Query.on', 2, 4, arguments.length); - fb.core.util.validation.validateEventType('Query.on', 1, eventType, false); - fb.util.validation.validateCallback('Query.on', 2, callback, false); - - var ret = this.getCancelAndContextArgs_('Query.on', opt_cancelCallbackOrContext, opt_context); - - if (eventType === 'value') { - this.onValueEvent(callback, ret.cancel, ret.context); - } else { - var callbacks = {}; - callbacks[eventType] = callback; - this.onChildEvent(callbacks, ret.cancel, ret.context); - } - return callback; - }, - - /** - * @param {!function(!fb.api.DataSnapshot)} callback - * @param {?function(Error)} cancelCallback - * @param {?Object} context - * @protected - */ - onValueEvent: function(callback, cancelCallback, context) { - var container = new fb.core.view.ValueEventRegistration(callback, cancelCallback || null, context || null); - this.repo.addEventCallbackForQuery(this, container); - }, - - /** - * @param {!Object.} callbacks - * @param {?function(Error)} cancelCallback - * @param {?Object} context - */ - onChildEvent: function(callbacks, cancelCallback, context) { - var container = new fb.core.view.ChildEventRegistration(callbacks, cancelCallback, context); - this.repo.addEventCallbackForQuery(this, container); - }, - - /** - * @param {string=} opt_eventType - * @param {(function(!fb.api.DataSnapshot, ?string=))=} opt_callback - * @param {Object=} opt_context - */ - off: function(opt_eventType, opt_callback, opt_context) { - fb.util.validation.validateArgCount('Query.off', 0, 3, arguments.length); - fb.core.util.validation.validateEventType('Query.off', 1, opt_eventType, true); - fb.util.validation.validateCallback('Query.off', 2, opt_callback, true); - fb.util.validation.validateContextObject('Query.off', 3, opt_context, true); - - var container = null; - var callbacks = null; - if (opt_eventType === 'value') { - var valueCallback = /** @type {function(!fb.api.DataSnapshot)} */ (opt_callback) || null; - container = new fb.core.view.ValueEventRegistration(valueCallback, null, opt_context || null); - } else if (opt_eventType) { - if (opt_callback) { - callbacks = {}; - callbacks[opt_eventType] = opt_callback; - } - container = new fb.core.view.ChildEventRegistration(callbacks, null, opt_context || null); - } - this.repo.removeEventCallbackForQuery(this, container); - }, - - /** - * Attaches a listener, waits for the first event, and then removes the listener - * @param {!string} eventType - * @param {!function(!fb.api.DataSnapshot, string=)} userCallback - * @return {!firebase.Promise} - */ - once: function(eventType, userCallback) { - fb.util.validation.validateArgCount('Query.once', 1, 4, arguments.length); - fb.core.util.validation.validateEventType('Query.once', 1, eventType, false); - fb.util.validation.validateCallback('Query.once', 2, userCallback, true); - - var ret = this.getCancelAndContextArgs_('Query.once', arguments[2], arguments[3]); - - // TODO: Implement this more efficiently (in particular, use 'get' wire protocol for 'value' event) - // TODO: consider actually wiring the callbacks into the promise. We cannot do this without a breaking change - // because the API currently expects callbacks will be called synchronously if the data is cached, but this is - // against the Promise specification. - var self = this, firstCall = true; - var deferred = new fb.util.promise.Deferred(); - fb.util.promise.attachDummyErrorHandler(deferred.promise); - - var onceCallback = function(snapshot) { - // NOTE: Even though we unsubscribe, we may get called multiple times if a single action (e.g. set() with JSON) - // triggers multiple events (e.g. child_added or child_changed). - if (firstCall) { - firstCall = false; - self.off(eventType, onceCallback); - - if (userCallback) { - goog.bind(userCallback, ret.context)(snapshot); - } - deferred.resolve(snapshot); - } - }; - - this.on(eventType, onceCallback, /*cancel=*/ function(err) { - self.off(eventType, onceCallback); - - if (ret.cancel) - goog.bind(ret.cancel, ret.context)(err); - deferred.reject(err); - }); - return deferred.promise; - }, - - /** - * Set a limit and anchor it to the start of the window. - * @param {!number} limit - * @return {!fb.api.Query} - */ - limitToFirst: function(limit) { - fb.util.validation.validateArgCount('Query.limitToFirst', 1, 1, arguments.length); - if (!goog.isNumber(limit) || Math.floor(limit) !== limit || limit <= 0) { - throw new Error('Query.limitToFirst: First argument must be a positive integer.'); - } - if (this.queryParams_.hasLimit()) { - throw new Error('Query.limitToFirst: Limit was already set (by another call to limit, ' + - 'limitToFirst, or limitToLast).'); - } - - return new fb.api.Query(this.repo, this.path, this.queryParams_.limitToFirst(limit), this.orderByCalled_); - }, - - /** - * Set a limit and anchor it to the end of the window. - * @param {!number} limit - * @return {!fb.api.Query} - */ - limitToLast: function(limit) { - fb.util.validation.validateArgCount('Query.limitToLast', 1, 1, arguments.length); - if (!goog.isNumber(limit) || Math.floor(limit) !== limit || limit <= 0) { - throw new Error('Query.limitToLast: First argument must be a positive integer.'); - } - if (this.queryParams_.hasLimit()) { - throw new Error('Query.limitToLast: Limit was already set (by another call to limit, ' + - 'limitToFirst, or limitToLast).'); - } - - return new fb.api.Query(this.repo, this.path, this.queryParams_.limitToLast(limit), - this.orderByCalled_); - }, - - /** - * Given a child path, return a new query ordered by the specified grandchild path. - * @param {!string} path - * @return {!fb.api.Query} - */ - orderByChild: function(path) { - fb.util.validation.validateArgCount('Query.orderByChild', 1, 1, arguments.length); - if (path === '$key') { - throw new Error('Query.orderByChild: "$key" is invalid. Use Query.orderByKey() instead.'); - } else if (path === '$priority') { - throw new Error('Query.orderByChild: "$priority" is invalid. Use Query.orderByPriority() instead.'); - } else if (path === '$value') { - throw new Error('Query.orderByChild: "$value" is invalid. Use Query.orderByValue() instead.'); - } - fb.core.util.validation.validatePathString('Query.orderByChild', 1, path, false); - this.validateNoPreviousOrderByCall_('Query.orderByChild'); - var parsedPath = new fb.core.util.Path(path); - if (parsedPath.isEmpty()) { - throw new Error('Query.orderByChild: cannot pass in empty path. Use Query.orderByValue() instead.'); - } - var index = new fb.core.snap.PathIndex(parsedPath); - var newParams = this.queryParams_.orderBy(index); - this.validateQueryEndpoints_(newParams); - - return new fb.api.Query(this.repo, this.path, newParams, /*orderByCalled=*/true); - }, - - /** - * Return a new query ordered by the KeyIndex - * @return {!fb.api.Query} - */ - orderByKey: function() { - fb.util.validation.validateArgCount('Query.orderByKey', 0, 0, arguments.length); - this.validateNoPreviousOrderByCall_('Query.orderByKey'); - var newParams = this.queryParams_.orderBy(fb.core.snap.KeyIndex); - this.validateQueryEndpoints_(newParams); - return new fb.api.Query(this.repo, this.path, newParams, /*orderByCalled=*/true); - }, - - /** - * Return a new query ordered by the PriorityIndex - * @return {!fb.api.Query} - */ - orderByPriority: function() { - fb.util.validation.validateArgCount('Query.orderByPriority', 0, 0, arguments.length); - this.validateNoPreviousOrderByCall_('Query.orderByPriority'); - var newParams = this.queryParams_.orderBy(fb.core.snap.PriorityIndex); - this.validateQueryEndpoints_(newParams); - return new fb.api.Query(this.repo, this.path, newParams, /*orderByCalled=*/true); - }, - - /** - * Return a new query ordered by the ValueIndex - * @return {!fb.api.Query} - */ - orderByValue: function() { - fb.util.validation.validateArgCount('Query.orderByValue', 0, 0, arguments.length); - this.validateNoPreviousOrderByCall_('Query.orderByValue'); - var newParams = this.queryParams_.orderBy(fb.core.snap.ValueIndex); - this.validateQueryEndpoints_(newParams); - return new fb.api.Query(this.repo, this.path, newParams, /*orderByCalled=*/true); - }, - - /** - * @param {number|string|boolean|null} value - * @param {?string=} opt_name - * @return {!fb.api.Query} - */ - startAt: function(value, opt_name) { - fb.util.validation.validateArgCount('Query.startAt', 0, 2, arguments.length); - fb.core.util.validation.validateFirebaseDataArg('Query.startAt', 1, value, this.path, true); - fb.core.util.validation.validateKey('Query.startAt', 2, opt_name, true); - - var newParams = this.queryParams_.startAt(value, opt_name); - this.validateLimit_(newParams); - this.validateQueryEndpoints_(newParams); - if (this.queryParams_.hasStart()) { - throw new Error('Query.startAt: Starting point was already set (by another call to startAt ' + - 'or equalTo).'); - } - - // Calling with no params tells us to start at the beginning. - if (!goog.isDef(value)) { - value = null; - opt_name = null; - } - return new fb.api.Query(this.repo, this.path, newParams, this.orderByCalled_); - }, - - /** - * @param {number|string|boolean|null} value - * @param {?string=} opt_name - * @return {!fb.api.Query} - */ - endAt: function(value, opt_name) { - fb.util.validation.validateArgCount('Query.endAt', 0, 2, arguments.length); - fb.core.util.validation.validateFirebaseDataArg('Query.endAt', 1, value, this.path, true); - fb.core.util.validation.validateKey('Query.endAt', 2, opt_name, true); - - var newParams = this.queryParams_.endAt(value, opt_name); - this.validateLimit_(newParams); - this.validateQueryEndpoints_(newParams); - if (this.queryParams_.hasEnd()) { - throw new Error('Query.endAt: Ending point was already set (by another call to endAt or ' + - 'equalTo).'); - } - - return new fb.api.Query(this.repo, this.path, newParams, this.orderByCalled_); - }, - - /** - * Load the selection of children with exactly the specified value, and, optionally, - * the specified name. - * @param {number|string|boolean|null} value - * @param {string=} opt_name - * @return {!fb.api.Query} - */ - equalTo: function(value, opt_name) { - fb.util.validation.validateArgCount('Query.equalTo', 1, 2, arguments.length); - fb.core.util.validation.validateFirebaseDataArg('Query.equalTo', 1, value, this.path, false); - fb.core.util.validation.validateKey('Query.equalTo', 2, opt_name, true); - if (this.queryParams_.hasStart()) { - throw new Error('Query.equalTo: Starting point was already set (by another call to startAt or ' + - 'equalTo).'); - } - if (this.queryParams_.hasEnd()) { - throw new Error('Query.equalTo: Ending point was already set (by another call to endAt or ' + - 'equalTo).'); - } - return this.startAt(value, opt_name).endAt(value, opt_name); - }, - - /** - * @return {!string} URL for this location. - */ - toString: function() { - fb.util.validation.validateArgCount('Query.toString', 0, 0, arguments.length); - - return this.repo.toString() + this.path.toUrlEncodedString(); - }, - - // Do not create public documentation. This is intended to make JSON serialization work but is otherwise unnecessary - // for end-users. - toJSON: function() { - // An optional spacer argument is unnecessary for a string. - fb.util.validation.validateArgCount('Query.toJSON', 0, 1, arguments.length); - return this.toString(); - }, - - /** - * An object representation of the query parameters used by this Query. - * @return {!Object} - */ - queryObject: function() { - return this.queryParams_.getQueryObject(); - }, - - /** - * @return {!string} - */ - queryIdentifier: function() { - var obj = this.queryObject(); - var id = fb.core.util.ObjectToUniqueKey(obj); - return (id === '{}') ? 'default' : id; - }, - - /** - * Return true if this query and the provided query are equivalent; otherwise, return false. - * @param {fb.api.Query} other - * @return {boolean} - */ - isEqual: function(other) { - fb.util.validation.validateArgCount('Query.isEqual', 1, 1, arguments.length); - if (!(other instanceof fb.api.Query)) { - var error = 'Query.isEqual failed: First argument must be an instance of firebase.database.Query.'; - throw new Error(error); - } - - var sameRepo = (this.repo === other.repo); - var samePath = this.path.equals(other.path); - var sameQueryIdentifier = (this.queryIdentifier() === other.queryIdentifier()); - - return (sameRepo && samePath && sameQueryIdentifier); - }, - - /** - * Helper used by .on and .once to extract the context and or cancel arguments. - * @param {!string} fnName The function name (on or once) - * @param {(function(Error)|Object)=} opt_cancelOrContext - * @param {Object=} opt_context - * @return {{cancel: ?function(Error), context: ?Object}} - * @private - */ - getCancelAndContextArgs_: function(fnName, opt_cancelOrContext, opt_context) { - var ret = {cancel: null, context: null}; - if (opt_cancelOrContext && opt_context) { - ret.cancel = /** @type {function(Error)} */ (opt_cancelOrContext); - fb.util.validation.validateCallback(fnName, 3, ret.cancel, true); - - ret.context = opt_context; - fb.util.validation.validateContextObject(fnName, 4, ret.context, true); - } else if (opt_cancelOrContext) { // we have either a cancel callback or a context. - if (typeof opt_cancelOrContext === 'object' && opt_cancelOrContext !== null) { // it's a context! - ret.context = opt_cancelOrContext; - } else if (typeof opt_cancelOrContext === 'function') { - ret.cancel = opt_cancelOrContext; - } else { - throw new Error(fb.util.validation.errorPrefix(fnName, 3, true) + - ' must either be a cancel callback or a context object.'); - } - } - return ret; - } -}); // end fb.api.Query - -goog.exportProperty(fb.api.Query.prototype, 'on', fb.api.Query.prototype.on); -// If we want to distinguish between value event listeners and child event listeners, like in the Java client, we can -// consider exporting this. If we do, add argument validation. Otherwise, arguments are validated in the public-facing -// portions of the API. -//goog.exportProperty(fb.api.Query.prototype, 'onValueEvent', fb.api.Query.prototype.onValueEvent); -// Note: as with the above onValueEvent method, we may wish to expose this at some point. -goog.exportProperty(fb.api.Query.prototype, 'off', fb.api.Query.prototype.off); -goog.exportProperty(fb.api.Query.prototype, 'once', fb.api.Query.prototype.once); -goog.exportProperty(fb.api.Query.prototype, 'limitToFirst', fb.api.Query.prototype.limitToFirst); -goog.exportProperty(fb.api.Query.prototype, 'limitToLast', fb.api.Query.prototype.limitToLast); -goog.exportProperty(fb.api.Query.prototype, 'orderByChild', fb.api.Query.prototype.orderByChild); -goog.exportProperty(fb.api.Query.prototype, 'orderByKey', fb.api.Query.prototype.orderByKey); -goog.exportProperty(fb.api.Query.prototype, 'orderByPriority', fb.api.Query.prototype.orderByPriority); -goog.exportProperty(fb.api.Query.prototype, 'orderByValue', fb.api.Query.prototype.orderByValue); -goog.exportProperty(fb.api.Query.prototype, 'startAt', fb.api.Query.prototype.startAt); -goog.exportProperty(fb.api.Query.prototype, 'endAt', fb.api.Query.prototype.endAt); -goog.exportProperty(fb.api.Query.prototype, 'equalTo', fb.api.Query.prototype.equalTo); -goog.exportProperty(fb.api.Query.prototype, 'toString', fb.api.Query.prototype.toString); -goog.exportProperty(fb.api.Query.prototype, 'isEqual', fb.api.Query.prototype.isEqual); - -// Internal code should NOT use these exported properties - because when they are -// minified, they will refernce the minified name. We could fix this by including -// our our externs file for all our exposed symbols. -fb.core.util.exportPropGetter(fb.api.Query.prototype, 'ref', fb.api.Query.prototype.getRef); diff --git a/src/database/js-client/api/TransactionResult.js b/src/database/js-client/api/TransactionResult.js deleted file mode 100644 index 9166358e9a1..00000000000 --- a/src/database/js-client/api/TransactionResult.js +++ /dev/null @@ -1,35 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.api.TransactionResult'); - - -/** - * A type for the resolve value of Firebase.transaction. - * @constructor - * @dict - * @param {boolean} committed - * @param {fb.api.DataSnapshot} snapshot - */ -fb.api.TransactionResult = function (committed, snapshot) { - /** - * @type {boolean} - */ - this['committed'] = committed; - /** - * @type {fb.api.DataSnapshot} - */ - this['snapshot'] = snapshot; -}; \ No newline at end of file diff --git a/src/database/js-client/api/internal.js b/src/database/js-client/api/internal.js deleted file mode 100644 index 8b83d1d0fd5..00000000000 --- a/src/database/js-client/api/internal.js +++ /dev/null @@ -1,70 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.api.INTERNAL'); -goog.require('fb.core.PersistentConnection'); -goog.require('fb.realtime.Connection'); - -/** - * INTERNAL methods for internal-use only (tests, etc.). - * - * Customers shouldn't use these or else should be aware that they could break at any time. - * - * @const - */ -fb.api.INTERNAL = {}; - - -fb.api.INTERNAL.forceLongPolling = function() { - fb.realtime.WebSocketConnection.forceDisallow(); - fb.realtime.BrowserPollConnection.forceAllow(); -}; -goog.exportProperty(fb.api.INTERNAL, 'forceLongPolling', fb.api.INTERNAL.forceLongPolling); - -fb.api.INTERNAL.forceWebSockets = function() { - fb.realtime.BrowserPollConnection.forceDisallow(); -}; -goog.exportProperty(fb.api.INTERNAL, 'forceWebSockets', fb.api.INTERNAL.forceWebSockets); - -/* Used by App Manager */ -fb.api.INTERNAL.isWebSocketsAvailable = function() { - return fb.realtime.WebSocketConnection['isAvailable'](); -}; -goog.exportProperty(fb.api.INTERNAL, 'isWebSocketsAvailable', fb.api.INTERNAL.isWebSocketsAvailable); - -fb.api.INTERNAL.setSecurityDebugCallback = function(ref, callback) { - ref.repo.persistentConnection_.securityDebugCallback_ = callback; -}; -goog.exportProperty(fb.api.INTERNAL, 'setSecurityDebugCallback', fb.api.INTERNAL.setSecurityDebugCallback); - -fb.api.INTERNAL.stats = function(ref, showDelta) { - ref.repo.stats(showDelta); -}; -goog.exportProperty(fb.api.INTERNAL, 'stats', fb.api.INTERNAL.stats); - -fb.api.INTERNAL.statsIncrementCounter = function(ref, metric) { - ref.repo.statsIncrementCounter(metric); -}; -goog.exportProperty(fb.api.INTERNAL, 'statsIncrementCounter', fb.api.INTERNAL.statsIncrementCounter); - -fb.api.INTERNAL.dataUpdateCount = function(ref) { - return ref.repo.dataUpdateCount; -}; -goog.exportProperty(fb.api.INTERNAL, 'dataUpdateCount', fb.api.INTERNAL.dataUpdateCount); - -fb.api.INTERNAL.interceptServerData = function(ref, callback) { - return ref.repo.interceptServerData_(callback); -}; -goog.exportProperty(fb.api.INTERNAL, 'interceptServerData', fb.api.INTERNAL.interceptServerData); diff --git a/src/database/js-client/api/onDisconnect.js b/src/database/js-client/api/onDisconnect.js deleted file mode 100644 index f103c0647a4..00000000000 --- a/src/database/js-client/api/onDisconnect.js +++ /dev/null @@ -1,142 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.api.OnDisconnect'); -goog.require('fb.core.util'); -goog.require('fb.core.util.validation'); -goog.require('fb.util.promise.Deferred'); -goog.require('fb.util.validation'); - - - -/** - * @constructor - * @param {!fb.core.Repo} repo - * @param {!fb.core.util.Path} path - */ -fb.api.OnDisconnect = function(repo, path) { - /** @private */ - this.repo_ = repo; - - /** @private */ - this.path_ = path; -}; - - -/** - * @param {function(?Error)=} opt_onComplete - * @return {!firebase.Promise} - */ -fb.api.OnDisconnect.prototype.cancel = function(opt_onComplete) { - fb.util.validation.validateArgCount('Firebase.onDisconnect().cancel', 0, 1, arguments.length); - fb.util.validation.validateCallback('Firebase.onDisconnect().cancel', 1, opt_onComplete, true); - var deferred = new fb.util.promise.Deferred(); - this.repo_.onDisconnectCancel(this.path_, deferred.wrapCallback(opt_onComplete)); - return deferred.promise; -}; -goog.exportProperty(fb.api.OnDisconnect.prototype, 'cancel', fb.api.OnDisconnect.prototype.cancel); - - -/** - * @param {function(?Error)=} opt_onComplete - * @return {!firebase.Promise} - */ -fb.api.OnDisconnect.prototype.remove = function(opt_onComplete) { - fb.util.validation.validateArgCount('Firebase.onDisconnect().remove', 0, 1, arguments.length); - fb.core.util.validation.validateWritablePath('Firebase.onDisconnect().remove', this.path_); - fb.util.validation.validateCallback('Firebase.onDisconnect().remove', 1, opt_onComplete, true); - var deferred = new fb.util.promise.Deferred(); - this.repo_.onDisconnectSet(this.path_, null, deferred.wrapCallback(opt_onComplete)); - return deferred.promise; -}; -goog.exportProperty(fb.api.OnDisconnect.prototype, 'remove', fb.api.OnDisconnect.prototype.remove); - - -/** - * @param {*} value - * @param {function(?Error)=} opt_onComplete - * @return {!firebase.Promise} - */ -fb.api.OnDisconnect.prototype.set = function(value, opt_onComplete) { - fb.util.validation.validateArgCount('Firebase.onDisconnect().set', 1, 2, arguments.length); - fb.core.util.validation.validateWritablePath('Firebase.onDisconnect().set', this.path_); - fb.core.util.validation.validateFirebaseDataArg('Firebase.onDisconnect().set', 1, value, this.path_, false); - fb.util.validation.validateCallback('Firebase.onDisconnect().set', 2, opt_onComplete, true); - var deferred = new fb.util.promise.Deferred(); - this.repo_.onDisconnectSet(this.path_, value, deferred.wrapCallback(opt_onComplete)); - return deferred.promise; -}; -goog.exportProperty(fb.api.OnDisconnect.prototype, 'set', fb.api.OnDisconnect.prototype.set); - - -/* TODO: Enable onDisconnect().setPriority(priority, callback) -fb.api.OnDisconnect.prototype.setPriority = function(priority, opt_onComplete) - fb.util.validation.validateArgCount("Firebase.onDisconnect().setPriority", 1, 2, arguments.length); - fb.core.util.validation.validateWritablePath('Firebase.onDisconnect().setPriority', this.path_); - fb.core.util.validation.validatePriority("Firebase.onDisconnect().setPriority", 1, priority, false); - fb.util.validation.validateCallback("Firebase.onDisconnect().setPriority", 2, opt_onComplete, true); - this.repo_.onDisconnectSetPriority(this.path_, priority, opt_onComplete); -}; -goog.exportProperty(fb.api.OnDisconnect.prototype, 'setPriority', fb.api.OnDisconnect.prototype.setPriority); */ - - -/** - * @param {*} value - * @param {number|string|null} priority - * @param {function(?Error)=} opt_onComplete - * @return {!firebase.Promise} - */ -fb.api.OnDisconnect.prototype.setWithPriority = function(value, priority, opt_onComplete) { - fb.util.validation.validateArgCount('Firebase.onDisconnect().setWithPriority', 2, 3, arguments.length); - fb.core.util.validation.validateWritablePath('Firebase.onDisconnect().setWithPriority', this.path_); - fb.core.util.validation.validateFirebaseDataArg('Firebase.onDisconnect().setWithPriority', - 1, value, this.path_, false); - fb.core.util.validation.validatePriority('Firebase.onDisconnect().setWithPriority', 2, priority, false); - fb.util.validation.validateCallback('Firebase.onDisconnect().setWithPriority', 3, opt_onComplete, true); - - var deferred = new fb.util.promise.Deferred(); - this.repo_.onDisconnectSetWithPriority(this.path_, value, priority, deferred.wrapCallback(opt_onComplete)); - return deferred.promise; -}; -goog.exportProperty(fb.api.OnDisconnect.prototype, 'setWithPriority', fb.api.OnDisconnect.prototype.setWithPriority); - - -/** - * @param {!Object} objectToMerge - * @param {function(?Error)=} opt_onComplete - * @return {!firebase.Promise} - */ -fb.api.OnDisconnect.prototype.update = function(objectToMerge, opt_onComplete) { - fb.util.validation.validateArgCount('Firebase.onDisconnect().update', 1, 2, arguments.length); - fb.core.util.validation.validateWritablePath('Firebase.onDisconnect().update', this.path_); - if (goog.isArray(objectToMerge)) { - var newObjectToMerge = {}; - for (var i = 0; i < objectToMerge.length; ++i) { - newObjectToMerge['' + i] = objectToMerge[i]; - } - objectToMerge = newObjectToMerge; - fb.core.util.warn( - 'Passing an Array to Firebase.onDisconnect().update() is deprecated. Use set() if you want to overwrite the ' + - 'existing data, or an Object with integer keys if you really do want to only update some of the children.' - ); - } - fb.core.util.validation.validateFirebaseMergeDataArg('Firebase.onDisconnect().update', 1, objectToMerge, - this.path_, false); - fb.util.validation.validateCallback('Firebase.onDisconnect().update', 2, opt_onComplete, true); - var deferred = new fb.util.promise.Deferred(); - this.repo_.onDisconnectUpdate(this.path_, objectToMerge, deferred.wrapCallback(opt_onComplete)); - return deferred.promise; -}; -goog.exportProperty(fb.api.OnDisconnect.prototype, 'update', fb.api.OnDisconnect.prototype.update); diff --git a/src/database/js-client/api/test_access.js b/src/database/js-client/api/test_access.js deleted file mode 100644 index 64ae79bfcc6..00000000000 --- a/src/database/js-client/api/test_access.js +++ /dev/null @@ -1,112 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.api.TEST_ACCESS'); - -goog.require('fb.core.PersistentConnection'); -goog.require('fb.core.RepoManager'); - - -fb.api.TEST_ACCESS.DataConnection = fb.core.PersistentConnection; -goog.exportProperty(fb.api.TEST_ACCESS, 'DataConnection', fb.api.TEST_ACCESS.DataConnection); - -/** - * @param {!string} pathString - * @param {function(*)} onComplete - */ -fb.core.PersistentConnection.prototype.simpleListen = function(pathString, onComplete) { - this.sendRequest('q', {'p': pathString}, onComplete); -}; -goog.exportProperty(fb.api.TEST_ACCESS.DataConnection.prototype, 'simpleListen', - fb.api.TEST_ACCESS.DataConnection.prototype.simpleListen -); - -/** - * @param {*} data - * @param {function(*)} onEcho - */ -fb.core.PersistentConnection.prototype.echo = function(data, onEcho) { - this.sendRequest('echo', {'d': data}, onEcho); -}; -goog.exportProperty(fb.api.TEST_ACCESS.DataConnection.prototype, 'echo', - fb.api.TEST_ACCESS.DataConnection.prototype.echo); - -goog.exportProperty(fb.core.PersistentConnection.prototype, 'interrupt', - fb.core.PersistentConnection.prototype.interrupt -); - - -// RealTimeConnection properties that we use in tests. -fb.api.TEST_ACCESS.RealTimeConnection = fb.realtime.Connection; -goog.exportProperty(fb.api.TEST_ACCESS, 'RealTimeConnection', fb.api.TEST_ACCESS.RealTimeConnection); -goog.exportProperty(fb.realtime.Connection.prototype, 'sendRequest', fb.realtime.Connection.prototype.sendRequest); -goog.exportProperty(fb.realtime.Connection.prototype, 'close', fb.realtime.Connection.prototype.close); - - - -/** - * @param {function(): string} newHash - * @return {function()} - */ -fb.api.TEST_ACCESS.hijackHash = function(newHash) { - var oldPut = fb.core.PersistentConnection.prototype.put; - fb.core.PersistentConnection.prototype.put = function(pathString, data, opt_onComplete, opt_hash) { - if (goog.isDef(opt_hash)) { - opt_hash = newHash(); - } - oldPut.call(this, pathString, data, opt_onComplete, opt_hash); - }; - return function() { - fb.core.PersistentConnection.prototype.put = oldPut; - } -}; -goog.exportProperty(fb.api.TEST_ACCESS, 'hijackHash', fb.api.TEST_ACCESS.hijackHash); - -/** - * @type {function(new:fb.core.RepoInfo, !string, boolean, !string, boolean): undefined} - */ -fb.api.TEST_ACCESS.ConnectionTarget = fb.core.RepoInfo; -goog.exportProperty(fb.api.TEST_ACCESS, 'ConnectionTarget', fb.api.TEST_ACCESS.ConnectionTarget); - -/** - * @param {!fb.api.Query} query - * @return {!string} - */ -fb.api.TEST_ACCESS.queryIdentifier = function(query) { - return query.queryIdentifier(); -}; -goog.exportProperty(fb.api.TEST_ACCESS, 'queryIdentifier', fb.api.TEST_ACCESS.queryIdentifier); - -/** - * @param {!fb.api.Query} firebaseRef - * @return {!Object} - */ -fb.api.TEST_ACCESS.listens = function(firebaseRef) { - return firebaseRef.repo.persistentConnection_.listens_; -}; -goog.exportProperty(fb.api.TEST_ACCESS, 'listens', fb.api.TEST_ACCESS.listens); - - -/** - * Forces the RepoManager to create Repos that use ReadonlyRestClient instead of PersistentConnection. - * - * @param {boolean} forceRestClient - */ -fb.api.TEST_ACCESS.forceRestClient = function(forceRestClient) { - fb.core.RepoManager.getInstance().forceRestClient(forceRestClient); -}; -goog.exportProperty(fb.api.TEST_ACCESS, 'forceRestClient', fb.api.TEST_ACCESS.forceRestClient); - -goog.exportProperty(fb.api.TEST_ACCESS, 'Context', fb.core.RepoManager); diff --git a/src/database/js-client/core/AuthTokenProvider.js b/src/database/js-client/core/AuthTokenProvider.js deleted file mode 100644 index bdb653a1d68..00000000000 --- a/src/database/js-client/core/AuthTokenProvider.js +++ /dev/null @@ -1,81 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.AuthTokenProvider'); - - -/** - * Abstraction around FirebaseApp's token fetching capabilities. - */ -fb.core.AuthTokenProvider = goog.defineClass(null, { - /** - * @param {!firebase.app.App} app - */ - constructor: function(app) { - /** @private {!firebase.app.App} */ - this.app_ = app; - }, - - /** - * @param {boolean} forceRefresh - * @return {!Promise} - */ - getToken: function(forceRefresh) { - return this.app_['INTERNAL']['getToken'](forceRefresh) - .then( - null, - // .catch - function(error) { - // TODO: Need to figure out all the cases this is raised and whether - // this makes sense. - if (error && error.code === 'auth/token-not-initialized') { - fb.core.util.log('Got auth/token-not-initialized error. Treating as null token.'); - return null; - } else { - return Promise.reject(error); - } - }); - }, - - addTokenChangeListener: function(listener) { - // TODO: We might want to wrap the listener and call it with no args to - // avoid a leaky abstraction, but that makes removing the listener harder. - this.app_['INTERNAL']['addAuthTokenListener'](listener); - }, - - removeTokenChangeListener: function(listener) { - this.app_['INTERNAL']['removeAuthTokenListener'](listener); - }, - - notifyForInvalidToken: function() { - var errorMessage = 'Provided authentication credentials for the app named "' + - this.app_.name + '" are invalid. This usually indicates your app was not ' + - 'initialized correctly. '; - if ('credential' in this.app_.options) { - errorMessage += 'Make sure the "credential" property provided to initializeApp() ' + - 'is authorized to access the specified "databaseURL" and is from the correct ' + - 'project.'; - } else if ('serviceAccount' in this.app_.options) { - errorMessage += 'Make sure the "serviceAccount" property provided to initializeApp() ' + - 'is authorized to access the specified "databaseURL" and is from the correct ' + - 'project.'; - } else { - errorMessage += 'Make sure the "apiKey" and "databaseURL" properties provided to ' + - 'initializeApp() match the values provided for your app at ' + - 'https://console.firebase.google.com/.'; - } - fb.core.util.warn(errorMessage); - } -}); diff --git a/src/database/js-client/core/CompoundWrite.js b/src/database/js-client/core/CompoundWrite.js deleted file mode 100644 index bfbba520af4..00000000000 --- a/src/database/js-client/core/CompoundWrite.js +++ /dev/null @@ -1,216 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.CompoundWrite'); -goog.require('fb.core.snap.Node'); -goog.require('fb.core.util'); -goog.require('fb.core.util.ImmutableTree'); - -/** - * This class holds a collection of writes that can be applied to nodes in unison. It abstracts away the logic with - * dealing with priority writes and multiple nested writes. At any given path there is only allowed to be one write - * modifying that path. Any write to an existing path or shadowing an existing path will modify that existing write - * to reflect the write added. - * - * @constructor - * @param {!fb.core.util.ImmutableTree.} writeTree - */ -fb.core.CompoundWrite = function(writeTree) { - /** - * @type {!fb.core.util.ImmutableTree.} - * @private - */ - this.writeTree_ = writeTree; -}; - -/** - * @type {!fb.core.CompoundWrite} - */ -fb.core.CompoundWrite.Empty = new fb.core.CompoundWrite( - /** @type {!fb.core.util.ImmutableTree.} */ (new fb.core.util.ImmutableTree(null)) -); - -/** - * @param {!fb.core.util.Path} path - * @param {!fb.core.snap.Node} node - * @return {!fb.core.CompoundWrite} - */ -fb.core.CompoundWrite.prototype.addWrite = function(path, node) { - if (path.isEmpty()) { - return new fb.core.CompoundWrite(new fb.core.util.ImmutableTree(node)); - } else { - var rootmost = this.writeTree_.findRootMostValueAndPath(path); - if (rootmost != null) { - var rootMostPath = rootmost.path, value = rootmost.value; - var relativePath = fb.core.util.Path.relativePath(rootMostPath, path); - value = value.updateChild(relativePath, node); - return new fb.core.CompoundWrite(this.writeTree_.set(rootMostPath, value)); - } else { - var subtree = new fb.core.util.ImmutableTree(node); - var newWriteTree = this.writeTree_.setTree(path, subtree); - return new fb.core.CompoundWrite(newWriteTree); - } - } -}; - -/** - * @param {!fb.core.util.Path} path - * @param {!Object.} updates - * @return {!fb.core.CompoundWrite} - */ -fb.core.CompoundWrite.prototype.addWrites = function(path, updates) { - var newWrite = this; - fb.util.obj.foreach(updates, function(childKey, node) { - newWrite = newWrite.addWrite(path.child(childKey), node); - }); - return newWrite; -}; - -/** - * Will remove a write at the given path and deeper paths. This will not modify a write at a higher - * location, which must be removed by calling this method with that path. - * - * @param {!fb.core.util.Path} path The path at which a write and all deeper writes should be removed - * @return {!fb.core.CompoundWrite} The new CompoundWrite with the removed path - */ -fb.core.CompoundWrite.prototype.removeWrite = function(path) { - if (path.isEmpty()) { - return fb.core.CompoundWrite.Empty; - } else { - var newWriteTree = this.writeTree_.setTree(path, fb.core.util.ImmutableTree.Empty); - return new fb.core.CompoundWrite(newWriteTree); - } -}; - -/** - * Returns whether this CompoundWrite will fully overwrite a node at a given location and can therefore be - * considered "complete". - * - * @param {!fb.core.util.Path} path The path to check for - * @return {boolean} Whether there is a complete write at that path - */ -fb.core.CompoundWrite.prototype.hasCompleteWrite = function(path) { - return this.getCompleteNode(path) != null; -}; - -/** - * Returns a node for a path if and only if the node is a "complete" overwrite at that path. This will not aggregate - * writes from deeper paths, but will return child nodes from a more shallow path. - * - * @param {!fb.core.util.Path} path The path to get a complete write - * @return {?fb.core.snap.Node} The node if complete at that path, or null otherwise. - */ -fb.core.CompoundWrite.prototype.getCompleteNode = function(path) { - var rootmost = this.writeTree_.findRootMostValueAndPath(path); - if (rootmost != null) { - return this.writeTree_.get(rootmost.path).getChild( - fb.core.util.Path.relativePath(rootmost.path, path)); - } else { - return null; - } -}; - -/** - * Returns all children that are guaranteed to be a complete overwrite. - * - * @return {!Array.} A list of all complete children. - */ -fb.core.CompoundWrite.prototype.getCompleteChildren = function() { - var children = []; - var node = this.writeTree_.value; - if (node != null) { - // If it's a leaf node, it has no children; so nothing to do. - if (!node.isLeafNode()) { - node = /** @type {!fb.core.snap.ChildrenNode} */ (node); - node.forEachChild(fb.core.snap.PriorityIndex, function(childName, childNode) { - children.push(new fb.core.snap.NamedNode(childName, childNode)); - }); - } - } else { - this.writeTree_.children.inorderTraversal(function(childName, childTree) { - if (childTree.value != null) { - children.push(new fb.core.snap.NamedNode(childName, childTree.value)); - } - }); - } - return children; -}; - -/** - * @param {!fb.core.util.Path} path - * @return {!fb.core.CompoundWrite} - */ -fb.core.CompoundWrite.prototype.childCompoundWrite = function(path) { - if (path.isEmpty()) { - return this; - } else { - var shadowingNode = this.getCompleteNode(path); - if (shadowingNode != null) { - return new fb.core.CompoundWrite(new fb.core.util.ImmutableTree(shadowingNode)); - } else { - return new fb.core.CompoundWrite(this.writeTree_.subtree(path)); - } - } -}; - -/** - * Returns true if this CompoundWrite is empty and therefore does not modify any nodes. - * @return {boolean} Whether this CompoundWrite is empty - */ -fb.core.CompoundWrite.prototype.isEmpty = function() { - return this.writeTree_.isEmpty(); -}; - -/** - * Applies this CompoundWrite to a node. The node is returned with all writes from this CompoundWrite applied to the - * node - * @param {!fb.core.snap.Node} node The node to apply this CompoundWrite to - * @return {!fb.core.snap.Node} The node with all writes applied - */ -fb.core.CompoundWrite.prototype.apply = function(node) { - return fb.core.CompoundWrite.applySubtreeWrite_(fb.core.util.Path.Empty, this.writeTree_, node); -}; - -/** - * @param {!fb.core.util.Path} relativePath - * @param {!fb.core.util.ImmutableTree.} writeTree - * @param {!fb.core.snap.Node} node - * @return {!fb.core.snap.Node} - * @private - */ -fb.core.CompoundWrite.applySubtreeWrite_ = function(relativePath, writeTree, node) { - if (writeTree.value != null) { - // Since there a write is always a leaf, we're done here - return node.updateChild(relativePath, writeTree.value); - } else { - var priorityWrite = null; - writeTree.children.inorderTraversal(function(childKey, childTree) { - if (childKey === '.priority') { - // Apply priorities at the end so we don't update priorities for either empty nodes or forget - // to apply priorities to empty nodes that are later filled - fb.core.util.assert(childTree.value !== null, 'Priority writes must always be leaf nodes'); - priorityWrite = childTree.value; - } else { - node = fb.core.CompoundWrite.applySubtreeWrite_(relativePath.child(childKey), childTree, node); - } - }); - // If there was a priority write, we only apply it if the node is not empty - if (!node.getChild(relativePath).isEmpty() && priorityWrite !== null) { - node = node.updateChild(relativePath.child('.priority'), - /** @type {!fb.core.snap.Node} */ (priorityWrite)); - } - return node; - } -}; diff --git a/src/database/js-client/core/PersistentConnection.js b/src/database/js-client/core/PersistentConnection.js deleted file mode 100644 index d234a071aad..00000000000 --- a/src/database/js-client/core/PersistentConnection.js +++ /dev/null @@ -1,856 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.PersistentConnection'); -goog.require('fb.core.ServerActions'); -goog.require('fb.core.util'); -goog.require('fb.core.util.OnlineMonitor'); -goog.require('fb.core.util.VisibilityMonitor'); -goog.require('fb.login.util.environment'); -goog.require('fb.realtime.Connection'); -goog.require('fb.util.json'); -goog.require('fb.util.jwt'); - -var RECONNECT_MIN_DELAY = 1000; -var RECONNECT_MAX_DELAY_DEFAULT = 60 * 5 * 1000; // 5 minutes in milliseconds (Case: 1858) -var RECONNECT_MAX_DELAY_FOR_ADMINS = 30 * 1000; // 30 seconds for admin clients (likely to be a backend server) -var RECONNECT_DELAY_MULTIPLIER = 1.3; -var RECONNECT_DELAY_RESET_TIMEOUT = 30000; // Reset delay back to MIN_DELAY after being connected for 30sec. -var SERVER_KILL_INTERRUPT_REASON = "server_kill"; - -// If auth fails repeatedly, we'll assume something is wrong and log a warning / back off. -var INVALID_AUTH_TOKEN_THRESHOLD = 3; - -/** - * Firebase connection. Abstracts wire protocol and handles reconnecting. - * - * NOTE: All JSON objects sent to the realtime connection must have property names enclosed - * in quotes to make sure the closure compiler does not minify them. - */ -fb.core.PersistentConnection = goog.defineClass(null, { - /** - * @implements {fb.core.ServerActions} - * @param {!fb.core.RepoInfo} repoInfo Data about the namespace we are connecting to - * @param {function(string, *, boolean, ?number)} onDataUpdate A callback for new data from the server - */ - constructor: function(repoInfo, onDataUpdate, onConnectStatus, - onServerInfoUpdate, authTokenProvider, authOverride) { - // Used for diagnostic logging. - this.id = fb.core.PersistentConnection.nextPersistentConnectionId_++; - this.log_ = fb.core.util.logWrapper('p:' + this.id + ':'); - /** @private {Object} */ - this.interruptReasons_ = { }; - this.listens_ = {}; - this.outstandingPuts_ = []; - this.outstandingPutCount_ = 0; - this.onDisconnectRequestQueue_ = []; - this.connected_ = false; - this.reconnectDelay_ = RECONNECT_MIN_DELAY; - this.maxReconnectDelay_ = RECONNECT_MAX_DELAY_DEFAULT; - this.onDataUpdate_ = onDataUpdate; - this.onConnectStatus_ = onConnectStatus; - this.onServerInfoUpdate_ = onServerInfoUpdate; - this.repoInfo_ = repoInfo; - this.securityDebugCallback_ = null; - this.lastSessionId = null; - /** @private {?{ - * sendRequest: function(Object), - * close: function() - * }} */ - this.realtime_ = null; - /** @private {string|null} */ - this.authToken_ = null; - this.authTokenProvider_ = authTokenProvider; - this.forceTokenRefresh_ = false; - this.invalidAuthTokenCount_ = 0; - if (authOverride && !fb.login.util.environment.isNodeSdk()) { - throw new Error('Auth override specified in options, but not supported on non Node.js platforms'); - } - /** private {Object|null|undefined} */ - this.authOverride_ = authOverride; - /** @private {number|null} */ - this.establishConnectionTimer_ = null; - /** @private {boolean} */ - this.visible_ = false; - - // Before we get connected, we keep a queue of pending messages to send. - this.requestCBHash_ = {}; - this.requestNumber_ = 0; - - this.firstConnection_ = true; - this.lastConnectionAttemptTime_ = null; - this.lastConnectionEstablishedTime_ = null; - this.scheduleConnect_(0); - - fb.core.util.VisibilityMonitor.getInstance().on('visible', this.onVisible_, this); - - if (repoInfo.host.indexOf('fblocal') === -1) { - fb.core.util.OnlineMonitor.getInstance().on('online', this.onOnline_, this); - } - }, - - statics: { - /** - * @private - */ - nextPersistentConnectionId_: 0, - - /** - * Counter for number of connections created. Mainly used for tagging in the logs - * @type {number} - * @private - */ - nextConnectionId_: 0 - }, - - /** - * @param {!string} action - * @param {*} body - * @param {function(*)=} onResponse - * @protected - */ - sendRequest: function(action, body, onResponse) { - var curReqNum = ++this.requestNumber_; - - var msg = {'r': curReqNum, 'a': action, 'b': body}; - this.log_(fb.util.json.stringify(msg)); - fb.core.util.assert(this.connected_, "sendRequest call when we're not connected not allowed."); - this.realtime_.sendRequest(msg); - if (onResponse) { - this.requestCBHash_[curReqNum] = onResponse; - } - }, - - /** - * @inheritDoc - */ - listen: function(query, currentHashFn, tag, onComplete) { - var queryId = query.queryIdentifier(); - var pathString = query.path.toString(); - this.log_('Listen called for ' + pathString + ' ' + queryId); - this.listens_[pathString] = this.listens_[pathString] || {}; - fb.core.util.assert(query.getQueryParams().isDefault() || !query.getQueryParams().loadsAllData(), - 'listen() called for non-default but complete query'); - fb.core.util.assert(!this.listens_[pathString][queryId], 'listen() called twice for same path/queryId.'); - var listenSpec = { - onComplete: onComplete, - hashFn: currentHashFn, - query: query, - tag: tag - }; - this.listens_[pathString][queryId] = listenSpec; - - if (this.connected_) { - this.sendListen_(listenSpec); - } - }, - - /** - * @param {!{onComplete: function(), - * hashFn: function():!string, - * query: !fb.api.Query, - * tag: ?number}} listenSpec - * @private - */ - sendListen_: function(listenSpec) { - var query = listenSpec.query; - var pathString = query.path.toString(); - var queryId = query.queryIdentifier(); - var self = this; - this.log_('Listen on ' + pathString + ' for ' + queryId); - var req = {/*path*/ 'p': pathString}; - - var action = 'q'; - - // Only bother to send query if it's non-default. - if (listenSpec.tag) { - req['q'] = query.queryObject(); - req['t'] = listenSpec.tag; - } - - req[/*hash*/'h'] = listenSpec.hashFn(); - - this.sendRequest(action, req, function(message) { - var payload = message[/*data*/ 'd']; - var status = message[/*status*/ 's']; - - // print warnings in any case... - self.warnOnListenWarnings_(payload, query); - - var currentListenSpec = self.listens_[pathString] && self.listens_[pathString][queryId]; - // only trigger actions if the listen hasn't been removed and readded - if (currentListenSpec === listenSpec) { - self.log_('listen response', message); - - if (status !== 'ok') { - self.removeListen_(pathString, queryId); - } - - if (listenSpec.onComplete) { - listenSpec.onComplete(status, payload); - } - } - }); - }, - - /** - * @param {*} payload - * @param {!fb.api.Query} query - * @private - */ - warnOnListenWarnings_: function(payload, query) { - if (payload && typeof payload === 'object' && fb.util.obj.contains(payload, 'w')) { - var warnings = fb.util.obj.get(payload, 'w'); - if (goog.isArray(warnings) && goog.array.contains(warnings, 'no_index')) { - var indexSpec = '".indexOn": "' + query.getQueryParams().getIndex().toString() + '"'; - var indexPath = query.path.toString(); - fb.core.util.warn('Using an unspecified index. Consider adding ' + indexSpec + ' at ' + indexPath + - ' to your security rules for better performance'); - } - } - }, - - /** - * @inheritDoc - */ - refreshAuthToken: function(token) { - this.authToken_ = token; - this.log_('Auth token refreshed'); - if (this.authToken_) { - this.tryAuth(); - } else { - //If we're connected we want to let the server know to unauthenticate us. If we're not connected, simply delete - //the credential so we dont become authenticated next time we connect. - if (this.connected_) { - this.sendRequest('unauth', {}, function() { }); - } - } - - this.reduceReconnectDelayIfAdminCredential_(token); - }, - - /** - * @param {!string} credential - * @private - */ - reduceReconnectDelayIfAdminCredential_: function(credential) { - // NOTE: This isn't intended to be bulletproof (a malicious developer can always just modify the client). - // Additionally, we don't bother resetting the max delay back to the default if auth fails / expires. - var isFirebaseSecret = credential && credential.length === 40; - if (isFirebaseSecret || fb.util.jwt.isAdmin(credential)) { - this.log_('Admin auth credential detected. Reducing max reconnect time.'); - this.maxReconnectDelay_ = RECONNECT_MAX_DELAY_FOR_ADMINS; - } - }, - - /** - * Attempts to authenticate with the given credentials. If the authentication attempt fails, it's triggered like - * a auth revoked (the connection is closed). - */ - tryAuth: function() { - var self = this; - if (this.connected_ && this.authToken_) { - var token = this.authToken_; - var authMethod = fb.util.jwt.isValidFormat(token) ? 'auth' : 'gauth'; - var requestData = {'cred': token}; - if (this.authOverride_ === null) { - requestData['noauth'] = true; - } else if (typeof this.authOverride_ === 'object') { - requestData['authvar'] = this.authOverride_; - } - this.sendRequest(authMethod, requestData, function(res) { - var status = res[/*status*/ 's']; - var data = res[/*data*/ 'd'] || 'error'; - - if (self.authToken_ === token) { - if (status === 'ok') { - self.invalidAuthTokenCount_ = 0; - } else { - // Triggers reconnect and force refresh for auth token - self.onAuthRevoked_(status, data); - } - } - }); - } - }, - - /** - * @inheritDoc - */ - unlisten: function(query, tag) { - var pathString = query.path.toString(); - var queryId = query.queryIdentifier(); - - this.log_("Unlisten called for " + pathString + " " + queryId); - - fb.core.util.assert(query.getQueryParams().isDefault() || !query.getQueryParams().loadsAllData(), - 'unlisten() called for non-default but complete query'); - var listen = this.removeListen_(pathString, queryId); - if (listen && this.connected_) { - this.sendUnlisten_(pathString, queryId, query.queryObject(), tag); - } - }, - - sendUnlisten_: function(pathString, queryId, queryObj, tag) { - this.log_('Unlisten on ' + pathString + ' for ' + queryId); - var self = this; - - var req = {/*path*/ 'p': pathString}; - var action = 'n'; - // Only bother send queryId if it's non-default. - if (tag) { - req['q'] = queryObj; - req['t'] = tag; - } - - this.sendRequest(action, req); - }, - - /** - * @inheritDoc - */ - onDisconnectPut: function(pathString, data, opt_onComplete) { - if (this.connected_) { - this.sendOnDisconnect_('o', pathString, data, opt_onComplete); - } else { - this.onDisconnectRequestQueue_.push({ - pathString: pathString, - action: 'o', - data: data, - onComplete: opt_onComplete - }); - } - }, - - /** - * @inheritDoc - */ - onDisconnectMerge: function(pathString, data, opt_onComplete) { - if (this.connected_) { - this.sendOnDisconnect_('om', pathString, data, opt_onComplete); - } else { - this.onDisconnectRequestQueue_.push({ - pathString: pathString, - action: 'om', - data: data, - onComplete: opt_onComplete - }); - } - }, - - /** - * @inheritDoc - */ - onDisconnectCancel: function(pathString, opt_onComplete) { - if (this.connected_) { - this.sendOnDisconnect_('oc', pathString, null, opt_onComplete); - } else { - this.onDisconnectRequestQueue_.push({ - pathString: pathString, - action: 'oc', - data: null, - onComplete: opt_onComplete - }); - } - }, - - sendOnDisconnect_: function(action, pathString, data, opt_onComplete) { - var self = this; - var request = {/*path*/ 'p': pathString, /*data*/ 'd': data}; - self.log_('onDisconnect ' + action, request); - this.sendRequest(action, request, function(response) { - if (opt_onComplete) { - setTimeout(function() { - opt_onComplete(response[/*status*/ 's'], response[/* data */'d']); - }, Math.floor(0)); - } - }); - }, - - /** - * @inheritDoc - */ - put: function(pathString, data, opt_onComplete, opt_hash) { - this.putInternal('p', pathString, data, opt_onComplete, opt_hash); - }, - - /** - * @inheritDoc - */ - merge: function(pathString, data, onComplete, opt_hash) { - this.putInternal('m', pathString, data, onComplete, opt_hash); - }, - - putInternal: function(action, pathString, data, opt_onComplete, opt_hash) { - var request = {/*path*/ 'p': pathString, /*data*/ 'd': data }; - - if (goog.isDef(opt_hash)) - request[/*hash*/ 'h'] = opt_hash; - - // TODO: Only keep track of the most recent put for a given path? - this.outstandingPuts_.push({ - action: action, - request: request, - onComplete: opt_onComplete - }); - - this.outstandingPutCount_++; - var index = this.outstandingPuts_.length - 1; - - if (this.connected_) { - this.sendPut_(index); - } else { - this.log_('Buffering put: ' + pathString); - } - }, - - sendPut_: function(index) { - var self = this; - var action = this.outstandingPuts_[index].action; - var request = this.outstandingPuts_[index].request; - var onComplete = this.outstandingPuts_[index].onComplete; - this.outstandingPuts_[index].queued = this.connected_; - - this.sendRequest(action, request, function(message) { - self.log_(action + ' response', message); - - delete self.outstandingPuts_[index]; - self.outstandingPutCount_--; - - // Clean up array occasionally. - if (self.outstandingPutCount_ === 0) { - self.outstandingPuts_ = []; - } - - if (onComplete) - onComplete(message[/*status*/ 's'], message[/* data */ 'd']); - }); - }, - - /** - * @inheritDoc - */ - reportStats: function(stats) { - // If we're not connected, we just drop the stats. - if (this.connected_) { - var request = { /*counters*/ 'c': stats }; - this.log_('reportStats', request); - - this.sendRequest(/*stats*/ 's', request, function(result) { - var status = result[/*status*/ 's']; - if (status !== 'ok') { - var errorReason = result[/* data */ 'd']; - this.log_('reportStats', 'Error sending stats: ' + errorReason); - } - }); - } - }, - - /** - * @param {*} message - * @private - */ - onDataMessage_: function(message) { - if ('r' in message) { - // this is a response - this.log_('from server: ' + fb.util.json.stringify(message)); - var reqNum = message['r']; - var onResponse = this.requestCBHash_[reqNum]; - if (onResponse) { - delete this.requestCBHash_[reqNum]; - onResponse(message[/*body*/ 'b']); - } - } else if ('error' in message) { - throw 'A server-side error has occurred: ' + message['error']; - } else if ('a' in message) { - // a and b are action and body, respectively - this.onDataPush_(message['a'], message['b']); - } - }, - - onDataPush_: function(action, body) { - this.log_('handleServerMessage', action, body); - if (action === 'd') - this.onDataUpdate_(body[/*path*/ 'p'], body[/*data*/ 'd'], /*isMerge*/false, body['t']); - else if (action === 'm') - this.onDataUpdate_(body[/*path*/ 'p'], body[/*data*/ 'd'], /*isMerge=*/true, body['t']); - else if (action === 'c') - this.onListenRevoked_(body[/*path*/ 'p'], body[/*query*/ 'q']); - else if (action === 'ac') - this.onAuthRevoked_(body[/*status code*/ 's'], body[/* explanation */ 'd']); - else if (action === 'sd') - this.onSecurityDebugPacket_(body); - else - fb.core.util.error('Unrecognized action received from server: ' + fb.util.json.stringify(action) + - '\nAre you using the latest client?'); - }, - - onReady_: function(timestamp, sessionId) { - this.log_('connection ready'); - this.connected_ = true; - this.lastConnectionEstablishedTime_ = new Date().getTime(); - this.handleTimestamp_(timestamp); - this.lastSessionId = sessionId; - if (this.firstConnection_) { - this.sendConnectStats_(); - } - this.restoreState_(); - this.firstConnection_ = false; - this.onConnectStatus_(true); - }, - - scheduleConnect_: function(timeout) { - fb.core.util.assert(!this.realtime_, "Scheduling a connect when we're already connected/ing?"); - - if (this.establishConnectionTimer_) { - clearTimeout(this.establishConnectionTimer_); - } - - // NOTE: Even when timeout is 0, it's important to do a setTimeout to work around an infuriating "Security Error" in - // Firefox when trying to write to our long-polling iframe in some scenarios (e.g. Forge or our unit tests). - - var self = this; - this.establishConnectionTimer_ = setTimeout(function() { - self.establishConnectionTimer_ = null; - self.establishConnection_(); - }, Math.floor(timeout)); - }, - - /** - * @param {boolean} visible - * @private - */ - onVisible_: function(visible) { - // NOTE: Tabbing away and back to a window will defeat our reconnect backoff, but I think that's fine. - if (visible && !this.visible_ && this.reconnectDelay_ === this.maxReconnectDelay_) { - this.log_('Window became visible. Reducing delay.'); - this.reconnectDelay_ = RECONNECT_MIN_DELAY; - - if (!this.realtime_) { - this.scheduleConnect_(0); - } - } - this.visible_ = visible; - }, - - onOnline_: function(online) { - if (online) { - this.log_('Browser went online.'); - this.reconnectDelay_ = RECONNECT_MIN_DELAY; - if (!this.realtime_) { - this.scheduleConnect_(0); - } - } else { - this.log_("Browser went offline. Killing connection."); - if (this.realtime_) { - this.realtime_.close(); - } - } - }, - - onRealtimeDisconnect_: function() { - this.log_('data client disconnected'); - this.connected_ = false; - this.realtime_ = null; - - // Since we don't know if our sent transactions succeeded or not, we need to cancel them. - this.cancelSentTransactions_(); - - // Clear out the pending requests. - this.requestCBHash_ = {}; - - if (this.shouldReconnect_()) { - if (!this.visible_) { - this.log_("Window isn't visible. Delaying reconnect."); - this.reconnectDelay_ = this.maxReconnectDelay_; - this.lastConnectionAttemptTime_ = new Date().getTime(); - } else if (this.lastConnectionEstablishedTime_) { - // If we've been connected long enough, reset reconnect delay to minimum. - var timeSinceLastConnectSucceeded = new Date().getTime() - this.lastConnectionEstablishedTime_; - if (timeSinceLastConnectSucceeded > RECONNECT_DELAY_RESET_TIMEOUT) - this.reconnectDelay_ = RECONNECT_MIN_DELAY; - this.lastConnectionEstablishedTime_ = null; - } - - var timeSinceLastConnectAttempt = new Date().getTime() - this.lastConnectionAttemptTime_; - var reconnectDelay = Math.max(0, this.reconnectDelay_ - timeSinceLastConnectAttempt); - reconnectDelay = Math.random() * reconnectDelay; - - this.log_('Trying to reconnect in ' + reconnectDelay + 'ms'); - this.scheduleConnect_(reconnectDelay); - - // Adjust reconnect delay for next time. - this.reconnectDelay_ = Math.min(this.maxReconnectDelay_, this.reconnectDelay_ * RECONNECT_DELAY_MULTIPLIER); - } - this.onConnectStatus_(false); - }, - - establishConnection_: function() { - if (this.shouldReconnect_()) { - this.log_('Making a connection attempt'); - this.lastConnectionAttemptTime_ = new Date().getTime(); - this.lastConnectionEstablishedTime_ = null; - var onDataMessage = goog.bind(this.onDataMessage_, this); - var onReady = goog.bind(this.onReady_, this); - var onDisconnect = goog.bind(this.onRealtimeDisconnect_, this); - var connId = this.id + ':' + fb.core.PersistentConnection.nextConnectionId_++; - var self = this; - var lastSessionId = this.lastSessionId; - var canceled = false; - var connection = null; - var closeFn = function() { - if (connection) { - connection.close(); - } else { - canceled = true; - onDisconnect(); - } - }; - var sendRequestFn = function(msg) { - fb.core.util.assert(connection, "sendRequest call when we're not connected not allowed."); - connection.sendRequest(msg); - }; - - this.realtime_ = { - close: closeFn, - sendRequest: sendRequestFn - }; - - var forceRefresh = this.forceTokenRefresh_; - this.forceTokenRefresh_ = false; - - // First fetch auth token, and establish connection after fetching the token was successful - this.authTokenProvider_.getToken(forceRefresh).then(function(result) { - if (!canceled) { - fb.core.util.log('getToken() completed. Creating connection.'); - self.authToken_ = result && result.accessToken; - connection = new fb.realtime.Connection(connId, self.repoInfo_, - onDataMessage, - onReady, - onDisconnect, /* onKill= */ function (reason) { - fb.core.util.warn(reason + ' (' + self.repoInfo_.toString() + ')'); - self.interrupt(SERVER_KILL_INTERRUPT_REASON); - }, - lastSessionId); - } else { - fb.core.util.log('getToken() completed but was canceled'); - } - }).then(null, function(error) { - self.log_('Failed to get token: ' + error); - if (!canceled) { - if (fb.constants.NODE_ADMIN) { - // This may be a critical error for the Admin Node.js SDK, so log a warning. - // But getToken() may also just have temporarily failed, so we still want to - // continue retrying. - fb.core.util.warn(error); - } - closeFn(); - } - }); - } - }, - - /** - * @param {string} reason - */ - interrupt: function(reason) { - fb.core.util.log('Interrupting connection for reason: ' + reason); - this.interruptReasons_[reason] = true; - if (this.realtime_) { - this.realtime_.close(); - } else { - if (this.establishConnectionTimer_) { - clearTimeout(this.establishConnectionTimer_); - this.establishConnectionTimer_ = null; - } - if (this.connected_) { - this.onRealtimeDisconnect_(); - } - } - }, - - /** - * @param {string} reason - */ - resume: function(reason) { - fb.core.util.log('Resuming connection for reason: ' + reason); - delete this.interruptReasons_[reason]; - if (goog.object.isEmpty(this.interruptReasons_)) { - this.reconnectDelay_ = RECONNECT_MIN_DELAY; - if (!this.realtime_) { - this.scheduleConnect_(0); - } - } - }, - - /** - * @param reason - * @return {boolean} - */ - isInterrupted: function(reason) { - return this.interruptReasons_[reason] || false; - }, - - handleTimestamp_: function(timestamp) { - var delta = timestamp - new Date().getTime(); - this.onServerInfoUpdate_({'serverTimeOffset': delta}); - }, - - cancelSentTransactions_: function() { - for (var i = 0; i < this.outstandingPuts_.length; i++) { - var put = this.outstandingPuts_[i]; - if (put && /*hash*/'h' in put.request && put.queued) { - if (put.onComplete) - put.onComplete('disconnect'); - - delete this.outstandingPuts_[i]; - this.outstandingPutCount_--; - } - } - - // Clean up array occasionally. - if (this.outstandingPutCount_ === 0) - this.outstandingPuts_ = []; - }, - - /** - * @param {!string} pathString - * @param {Array.<*>=} opt_query - * @private - */ - onListenRevoked_: function(pathString, opt_query) { - // Remove the listen and manufacture a "permission_denied" error for the failed listen. - var queryId; - if (!opt_query) { - queryId = 'default'; - } else { - queryId = goog.array.map(opt_query, function(q) { return fb.core.util.ObjectToUniqueKey(q); }).join('$'); - } - var listen = this.removeListen_(pathString, queryId); - if (listen && listen.onComplete) - listen.onComplete('permission_denied'); - }, - - /** - * @param {!string} pathString - * @param {!string} queryId - * @return {{queries:Array., onComplete:function(string)}} - * @private - */ - removeListen_: function(pathString, queryId) { - var normalizedPathString = new fb.core.util.Path(pathString).toString(); // normalize path. - var listen; - if (goog.isDef(this.listens_[normalizedPathString])) { - listen = this.listens_[normalizedPathString][queryId]; - delete this.listens_[normalizedPathString][queryId]; - if (goog.object.getCount(this.listens_[normalizedPathString]) === 0) { - delete this.listens_[normalizedPathString]; - } - } else { - // all listens for this path has already been removed - listen = undefined; - } - return listen; - }, - - onAuthRevoked_: function(statusCode, explanation) { - fb.core.util.log('Auth token revoked: ' + statusCode + '/' + explanation); - this.authToken_ = null; - this.forceTokenRefresh_ = true; - this.realtime_.close(); - if (statusCode === 'invalid_token' || statusCode === 'permission_denied') { - // We'll wait a couple times before logging the warning / increasing the - // retry period since oauth tokens will report as "invalid" if they're - // just expired. Plus there may be transient issues that resolve themselves. - this.invalidAuthTokenCount_++; - if (this.invalidAuthTokenCount_ >= INVALID_AUTH_TOKEN_THRESHOLD) { - // Set a long reconnect delay because recovery is unlikely - this.reconnectDelay_ = RECONNECT_MAX_DELAY_FOR_ADMINS; - - // Notify the auth token provider that the token is invalid, which will log - // a warning - this.authTokenProvider_.notifyForInvalidToken(); - } - } - }, - - onSecurityDebugPacket_: function(body) { - if (this.securityDebugCallback_) { - this.securityDebugCallback_(body); - } else { - if ('msg' in body && typeof console !== 'undefined') { - console.log('FIREBASE: ' + body['msg'].replace('\n', '\nFIREBASE: ')); - } - } - }, - - restoreState_: function() { - //Re-authenticate ourselves if we have a credential stored. - this.tryAuth(); - - // Puts depend on having received the corresponding data update from the server before they complete, so we must - // make sure to send listens before puts. - var self = this; - goog.object.forEach(this.listens_, function(queries, pathString) { - goog.object.forEach(queries, function(listenSpec) { - self.sendListen_(listenSpec); - }); - }); - - for (var i = 0; i < this.outstandingPuts_.length; i++) { - if (this.outstandingPuts_[i]) - this.sendPut_(i); - } - - while (this.onDisconnectRequestQueue_.length) { - var request = this.onDisconnectRequestQueue_.shift(); - this.sendOnDisconnect_(request.action, request.pathString, request.data, request.onComplete); - } - }, - - /** - * Sends client stats for first connection - * @private - */ - sendConnectStats_: function() { - var stats = {}; - - var clientName = 'js'; - if (fb.constants.NODE_ADMIN) { - clientName = 'admin_node'; - } else if (fb.constants.NODE_CLIENT) { - clientName = 'node'; - } - - stats['sdk.' + clientName + '.' + firebase.SDK_VERSION.replace(/\./g, '-')] = 1; - - if (fb.login.util.environment.isMobileCordova()) { - stats['framework.cordova'] = 1; - } - else if (fb.login.util.environment.isReactNative()) { - stats['framework.reactnative'] = 1; - } - this.reportStats(stats); - }, - - /** - * @return {boolean} - * @private - */ - shouldReconnect_: function() { - var online = fb.core.util.OnlineMonitor.getInstance().currentlyOnline(); - return goog.object.isEmpty(this.interruptReasons_) && online; - } -}); // end fb.core.PersistentConnection diff --git a/src/database/js-client/core/ReadonlyRestClient.js b/src/database/js-client/core/ReadonlyRestClient.js deleted file mode 100644 index 895b198c3ba..00000000000 --- a/src/database/js-client/core/ReadonlyRestClient.js +++ /dev/null @@ -1,199 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.ReadonlyRestClient'); -goog.require('fb.core.util'); -goog.require('fb.util'); -goog.require('fb.util.json'); -goog.require('fb.util.jwt'); -goog.require('fb.util.obj'); - - -/** - * An implementation of fb.core.ServerActions that communicates with the server via REST requests. - * This is mostly useful for compatibility with crawlers, where we don't want to spin up a full - * persistent connection (using WebSockets or long-polling) - */ -fb.core.ReadonlyRestClient = goog.defineClass(null, { - /** - * @param {!fb.core.RepoInfo} repoInfo Data about the namespace we are connecting to - * @param {function(string, *, boolean, ?number)} onDataUpdate A callback for new data from the server - * @implements {fb.core.ServerActions} - */ - constructor: function(repoInfo, onDataUpdate, authTokenProvider) { - /** @private {function(...[*])} */ - this.log_ = fb.core.util.logWrapper('p:rest:'); - - /** @private {!fb.core.RepoInfo} */ - this.repoInfo_ = repoInfo; - - /** @private {function(string, *, boolean, ?number)} */ - this.onDataUpdate_ = onDataUpdate; - - /** @private {!fb.core.AuthTokenProvider} */ - this.authTokenProvider_ = authTokenProvider; - - /** - * We don't actually need to track listens, except to prevent us calling an onComplete for a listen - * that's been removed. :-/ - * - * @private {!Object.} - */ - this.listens_ = { }; - }, - - /** @inheritDoc */ - listen: function(query, currentHashFn, tag, onComplete) { - var pathString = query.path.toString(); - this.log_('Listen called for ' + pathString + ' ' + query.queryIdentifier()); - - // Mark this listener so we can tell if it's removed. - var listenId = fb.core.ReadonlyRestClient.getListenId_(query, tag); - var thisListen = new Object(); - this.listens_[listenId] = thisListen; - - var queryStringParamaters = query.getQueryParams().toRestQueryStringParameters(); - - var self = this; - this.restRequest_(pathString + '.json', queryStringParamaters, function(error, result) { - var data = result; - - if (error === 404) { - data = null; - error = null; - } - - if (error === null) { - self.onDataUpdate_(pathString, data, /*isMerge=*/false, tag); - } - - if (fb.util.obj.get(self.listens_, listenId) === thisListen) { - var status; - if (!error) { - status = 'ok'; - } else if (error == 401) { - status = 'permission_denied'; - } else { - status = 'rest_error:' + error; - } - - onComplete(status, null); - } - }); - }, - - /** @inheritDoc */ - unlisten: function(query, tag) { - var listenId = fb.core.ReadonlyRestClient.getListenId_(query, tag); - delete this.listens_[listenId]; - }, - - /** @inheritDoc */ - refreshAuthToken: function(token) { - // no-op since we just always call getToken. - }, - - /** @inheritDoc */ - onDisconnectPut: function(pathString, data, opt_onComplete) { }, - - /** @inheritDoc */ - onDisconnectMerge: function(pathString, data, opt_onComplete) { }, - - /** @inheritDoc */ - onDisconnectCancel: function(pathString, opt_onComplete) { }, - - /** @inheritDoc */ - put: function(pathString, data, opt_onComplete, opt_hash) { }, - - /** @inheritDoc */ - merge: function(pathString, data, onComplete, opt_hash) { }, - - /** @inheritDoc */ - reportStats: function(stats) { }, - - /** - * Performs a REST request to the given path, with the provided query string parameters, - * and any auth credentials we have. - * - * @param {!string} pathString - * @param {!Object.} queryStringParameters - * @param {?function(?number, *=)} callback - * @private - */ - restRequest_: function(pathString, queryStringParameters, callback) { - queryStringParameters = queryStringParameters || { }; - - queryStringParameters['format'] = 'export'; - - var self = this; - - this.authTokenProvider_.getToken(/*forceRefresh=*/false).then(function(authTokenData) { - var authToken = authTokenData && authTokenData.accessToken; - if (authToken) { - queryStringParameters['auth'] = authToken; - } - - var url = (self.repoInfo_.secure ? 'https://' : 'http://') + - self.repoInfo_.host + - pathString + - '?' + - fb.util.querystring(queryStringParameters); - - self.log_('Sending REST request for ' + url); - var xhr = new XMLHttpRequest(); - xhr.onreadystatechange = function () { - if (callback && xhr.readyState === 4) { - self.log_('REST Response for ' + url + ' received. status:', xhr.status, 'response:', xhr.responseText); - var res = null; - if (xhr.status >= 200 && xhr.status < 300) { - try { - res = fb.util.json.eval(xhr.responseText); - } catch (e) { - fb.core.util.warn('Failed to parse JSON response for ' + url + ': ' + xhr.responseText); - } - callback(null, res); - } else { - // 401 and 404 are expected. - if (xhr.status !== 401 && xhr.status !== 404) { - fb.core.util.warn('Got unsuccessful REST response for ' + url + ' Status: ' + xhr.status); - } - callback(xhr.status); - } - callback = null; - } - }; - - xhr.open('GET', url, /*asynchronous=*/true); - xhr.send(); - }); - }, - - statics: { - /** - * @param {!fb.api.Query} query - * @param {?number=} opt_tag - * @return {string} - * @private - */ - getListenId_: function(query, opt_tag) { - if (goog.isDef(opt_tag)) { - return 'tag$' + opt_tag; - } else { - fb.core.util.assert(query.getQueryParams().isDefault(), "should have a tag if it's not a default query."); - return query.path.toString(); - } - } - } -}); // end fb.core.ReadonlyRestClient diff --git a/src/database/js-client/core/Repo.js b/src/database/js-client/core/Repo.js deleted file mode 100644 index afa74a41255..00000000000 --- a/src/database/js-client/core/Repo.js +++ /dev/null @@ -1,580 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.Repo'); -goog.require('fb.api.DataSnapshot'); -goog.require('fb.api.Database'); -goog.require('fb.core.AuthTokenProvider'); -goog.require('fb.core.PersistentConnection'); -goog.require('fb.core.ReadonlyRestClient'); -goog.require('fb.core.SnapshotHolder'); -goog.require('fb.core.SparseSnapshotTree'); -goog.require('fb.core.SyncTree'); -goog.require('fb.core.stats.StatsCollection'); -goog.require('fb.core.stats.StatsListener'); -goog.require('fb.core.stats.StatsManager'); -goog.require('fb.core.stats.StatsReporter'); -goog.require('fb.core.util'); -goog.require('fb.core.util.ServerValues'); -goog.require('fb.core.util.Tree'); -goog.require('fb.core.view.EventQueue'); -goog.require('fb.util.json'); -goog.require('fb.util.jwt'); -goog.require('goog.string'); - - -var INTERRUPT_REASON = 'repo_interrupt'; - - -/** - * A connection to a single data repository. - */ -fb.core.Repo = goog.defineClass(null, { - /** - * @param {!fb.core.RepoInfo} repoInfo - * @param {boolean} forceRestClient - * @param {!firebase.app.App} app - */ - constructor: function(repoInfo, forceRestClient, app) { - /** @type {!firebase.app.App} */ - this.app = app; - - /** @type {!fb.core.AuthTokenProvider} */ - var authTokenProvider = new fb.core.AuthTokenProvider(app); - - this.repoInfo_ = repoInfo; - this.stats_ = fb.core.stats.StatsManager.getCollection(repoInfo); - /** @type {fb.core.stats.StatsListener} */ - this.statsListener_ = null; - this.eventQueue_ = new fb.core.view.EventQueue(); - this.nextWriteId_ = 1; - - /** - * TODO: This should be @private but it's used by test_access.js and internal.js - * @type {?fb.core.PersistentConnection} - */ - this.persistentConnection_ = null; - - /** - * @private {!fb.core.ServerActions} - */ - this.server_; - - if (forceRestClient || fb.core.util.beingCrawled()) { - this.server_ = new fb.core.ReadonlyRestClient(this.repoInfo_, - goog.bind(this.onDataUpdate_, this), - authTokenProvider); - - // Minor hack: Fire onConnect immediately, since there's no actual connection. - setTimeout(goog.bind(this.onConnectStatus_, this, true), 0); - } else { - var authOverride = app.options['databaseAuthVariableOverride']; - // Validate authOverride - if (goog.typeOf(authOverride) !== 'undefined' && authOverride !== null) { - if (goog.typeOf(authOverride) !== 'object') { - throw new Error('Only objects are supported for option databaseAuthVariableOverride'); - } - try { - fb.util.json.stringify(authOverride); - } catch (e) { - throw new Error('Invalid authOverride provided: ' + e); - } - } - - this.persistentConnection_ = new fb.core.PersistentConnection(this.repoInfo_, - goog.bind(this.onDataUpdate_, this), - goog.bind(this.onConnectStatus_, this), - goog.bind(this.onServerInfoUpdate_, this), - authTokenProvider, - authOverride); - - this.server_ = this.persistentConnection_; - } - var self = this; - authTokenProvider.addTokenChangeListener(function(token) { - self.server_.refreshAuthToken(token); - }); - - // In the case of multiple Repos for the same repoInfo (i.e. there are multiple Firebase.Contexts being used), - // we only want to create one StatsReporter. As such, we'll report stats over the first Repo created. - this.statsReporter_ = fb.core.stats.StatsManager.getOrCreateReporter(repoInfo, - goog.bind(function() { return new fb.core.stats.StatsReporter(this.stats_, this.server_); }, this)); - - this.transactions_init_(); - - // Used for .info. - this.infoData_ = new fb.core.SnapshotHolder(); - this.infoSyncTree_ = new fb.core.SyncTree({ - startListening: function(query, tag, currentHashFn, onComplete) { - var infoEvents = []; - var node = self.infoData_.getNode(query.path); - // This is possibly a hack, but we have different semantics for .info endpoints. We don't raise null events - // on initial data... - if (!node.isEmpty()) { - infoEvents = self.infoSyncTree_.applyServerOverwrite(query.path, node); - setTimeout(function() { - onComplete('ok'); - }, 0); - } - return infoEvents; - }, - stopListening: goog.nullFunction - }); - this.updateInfo_('connected', false); - - // A list of data pieces and paths to be set when this client disconnects. - this.onDisconnect_ = new fb.core.SparseSnapshotTree(); - - /** @type {!fb.api.Database} */ - this.database = new fb.api.Database(this); - - this.dataUpdateCount = 0; - - this.interceptServerDataCallback_ = null; - - this.serverSyncTree_ = new fb.core.SyncTree({ - startListening: function(query, tag, currentHashFn, onComplete) { - self.server_.listen(query, currentHashFn, tag, function(status, data) { - var events = onComplete(status, data); - self.eventQueue_.raiseEventsForChangedPath(query.path, events); - }); - // No synchronous events for network-backed sync trees - return []; - }, - stopListening: function(query, tag) { - self.server_.unlisten(query, tag); - } - }); - }, - - /** - * @return {string} The URL corresponding to the root of this Firebase. - */ - toString: function() { - return (this.repoInfo_.secure ? 'https://' : 'http://') + this.repoInfo_.host; - }, - - /** - * @return {!string} The namespace represented by the repo. - */ - name: function() { - return this.repoInfo_.namespace; - }, - - /** - * @return {!number} The time in milliseconds, taking the server offset into account if we have one. - */ - serverTime: function() { - var offsetNode = this.infoData_.getNode(new fb.core.util.Path('.info/serverTimeOffset')); - var offset = /** @type {number} */ (offsetNode.val()) || 0; - return new Date().getTime() + offset; - }, - - /** - * Generate ServerValues using some variables from the repo object. - * @return {!Object} - */ - generateServerValues: function() { - return fb.core.util.ServerValues.generateWithValues({ - 'timestamp': this.serverTime() - }); - }, - - /** - * Called by realtime when we get new messages from the server. - * - * @private - * @param {string} pathString - * @param {*} data - * @param {boolean} isMerge - * @param {?number} tag - */ - onDataUpdate_: function(pathString, data, isMerge, tag) { - // For testing. - this.dataUpdateCount++; - var path = new fb.core.util.Path(pathString); - data = this.interceptServerDataCallback_ ? this.interceptServerDataCallback_(pathString, data) : data; - var events = []; - if (tag) { - if (isMerge) { - var taggedChildren = goog.object.map(/**@type {!Object.} */ (data), function(raw) { - return fb.core.snap.NodeFromJSON(raw); - }); - events = this.serverSyncTree_.applyTaggedQueryMerge(path, taggedChildren, tag); - } else { - var taggedSnap = fb.core.snap.NodeFromJSON(data); - events = this.serverSyncTree_.applyTaggedQueryOverwrite(path, taggedSnap, tag); - } - } else if (isMerge) { - var changedChildren = goog.object.map(/**@type {!Object.} */ (data), function(raw) { - return fb.core.snap.NodeFromJSON(raw); - }); - events = this.serverSyncTree_.applyServerMerge(path, changedChildren); - } else { - var snap = fb.core.snap.NodeFromJSON(data); - events = this.serverSyncTree_.applyServerOverwrite(path, snap); - } - var affectedPath = path; - if (events.length > 0) { - // Since we have a listener outstanding for each transaction, receiving any events - // is a proxy for some change having occurred. - affectedPath = this.rerunTransactions_(path); - } - this.eventQueue_.raiseEventsForChangedPath(affectedPath, events); - }, - - /** - * @param {?function(!string, *):*} callback - * @private - */ - interceptServerData_: function(callback) { - this.interceptServerDataCallback_ = callback; - }, - - /** - * @param {!boolean} connectStatus - * @private - */ - onConnectStatus_: function(connectStatus) { - this.updateInfo_('connected', connectStatus); - if (connectStatus === false) { - this.runOnDisconnectEvents_(); - } - }, - - /** - * @param {!Object} updates - * @private - */ - onServerInfoUpdate_: function(updates) { - var self = this; - fb.core.util.each(updates, function(value, key) { - self.updateInfo_(key, value); - }); - }, - - /** - * - * @param {!string} pathString - * @param {*} value - * @private - */ - updateInfo_: function(pathString, value) { - var path = new fb.core.util.Path('/.info/' + pathString); - var newNode = fb.core.snap.NodeFromJSON(value); - this.infoData_.updateSnapshot(path, newNode); - var events = this.infoSyncTree_.applyServerOverwrite(path, newNode); - this.eventQueue_.raiseEventsForChangedPath(path, events); - }, - - /** - * @return {!number} - * @private - */ - getNextWriteId_: function() { - return this.nextWriteId_++; - }, - - /** - * @param {!fb.core.util.Path} path - * @param {*} newVal - * @param {number|string|null} newPriority - * @param {?function(?Error, *=)} onComplete - */ - setWithPriority: function(path, newVal, newPriority, onComplete) { - this.log_('set', {path: path.toString(), value: newVal, priority: newPriority}); - - // TODO: Optimize this behavior to either (a) store flag to skip resolving where possible and / or - // (b) store unresolved paths on JSON parse - var serverValues = this.generateServerValues(); - var newNodeUnresolved = fb.core.snap.NodeFromJSON(newVal, newPriority); - var newNode = fb.core.util.ServerValues.resolveDeferredValueSnapshot(newNodeUnresolved, serverValues); - - var writeId = this.getNextWriteId_(); - var events = this.serverSyncTree_.applyUserOverwrite(path, newNode, writeId, true); - this.eventQueue_.queueEvents(events); - var self = this; - this.server_.put(path.toString(), newNodeUnresolved.val(/*export=*/true), function(status, errorReason) { - var success = status === 'ok'; - if (!success) { - fb.core.util.warn('set at ' + path + ' failed: ' + status); - } - - var clearEvents = self.serverSyncTree_.ackUserWrite(writeId, !success); - self.eventQueue_.raiseEventsForChangedPath(path, clearEvents); - self.callOnCompleteCallback(onComplete, status, errorReason); - }); - var affectedPath = this.abortTransactions_(path); - this.rerunTransactions_(affectedPath); - // We queued the events above, so just flush the queue here - this.eventQueue_.raiseEventsForChangedPath(affectedPath, []); - }, - - /** - * @param {!fb.core.util.Path} path - * @param {!Object} childrenToMerge - * @param {?function(?Error, *=)} onComplete - */ - update: function(path, childrenToMerge, onComplete) { - this.log_('update', {path: path.toString(), value: childrenToMerge}); - - // Start with our existing data and merge each child into it. - var empty = true; - var serverValues = this.generateServerValues(); - var changedChildren = {}; - goog.object.forEach(childrenToMerge, function(changedValue, changedKey) { - empty = false; - var newNodeUnresolved = fb.core.snap.NodeFromJSON(changedValue); - changedChildren[changedKey] = - fb.core.util.ServerValues.resolveDeferredValueSnapshot(newNodeUnresolved, serverValues); - }); - - if (!empty) { - var writeId = this.getNextWriteId_(); - var events = this.serverSyncTree_.applyUserMerge(path, changedChildren, writeId); - this.eventQueue_.queueEvents(events); - var self = this; - this.server_.merge(path.toString(), childrenToMerge, function(status, errorReason) { - var success = status === 'ok'; - if (!success) { - fb.core.util.warn('update at ' + path + ' failed: ' + status); - } - - var clearEvents = self.serverSyncTree_.ackUserWrite(writeId, !success); - var affectedPath = path; - if (clearEvents.length > 0) { - affectedPath = self.rerunTransactions_(path); - } - self.eventQueue_.raiseEventsForChangedPath(affectedPath, clearEvents); - self.callOnCompleteCallback(onComplete, status, errorReason); - }); - - goog.object.forEach(childrenToMerge, function(changedValue, changedPath) { - var affectedPath = self.abortTransactions_(path.child(changedPath)); - self.rerunTransactions_(affectedPath); - }); - - // We queued the events above, so just flush the queue here - this.eventQueue_.raiseEventsForChangedPath(path, []); - } else { - fb.core.util.log('update() called with empty data. Don\'t do anything.'); - this.callOnCompleteCallback(onComplete, 'ok'); - } - }, - - /** - * Applies all of the changes stored up in the onDisconnect_ tree. - * @private - */ - runOnDisconnectEvents_: function() { - this.log_('onDisconnectEvents'); - var self = this; - - var serverValues = this.generateServerValues(); - var resolvedOnDisconnectTree = fb.core.util.ServerValues.resolveDeferredValueTree(this.onDisconnect_, serverValues); - var events = []; - - resolvedOnDisconnectTree.forEachTree(fb.core.util.Path.Empty, function(path, snap) { - events = events.concat(self.serverSyncTree_.applyServerOverwrite(path, snap)); - var affectedPath = self.abortTransactions_(path); - self.rerunTransactions_(affectedPath); - }); - - this.onDisconnect_ = new fb.core.SparseSnapshotTree(); - this.eventQueue_.raiseEventsForChangedPath(fb.core.util.Path.Empty, events); - }, - - /** - * @param {!fb.core.util.Path} path - * @param {?function(?Error)} onComplete - */ - onDisconnectCancel: function(path, onComplete) { - var self = this; - this.server_.onDisconnectCancel(path.toString(), function(status, errorReason) { - if (status === 'ok') { - self.onDisconnect_.forget(path); - } - self.callOnCompleteCallback(onComplete, status, errorReason); - }); - }, - - onDisconnectSet: function(path, value, onComplete) { - var self = this; - var newNode = fb.core.snap.NodeFromJSON(value); - this.server_.onDisconnectPut(path.toString(), newNode.val(/*export=*/true), function(status, errorReason) { - if (status === 'ok') { - self.onDisconnect_.remember(path, newNode); - } - self.callOnCompleteCallback(onComplete, status, errorReason); - }); - }, - - onDisconnectSetWithPriority: function(path, value, priority, onComplete) { - var self = this; - var newNode = fb.core.snap.NodeFromJSON(value, priority); - this.server_.onDisconnectPut(path.toString(), newNode.val(/*export=*/true), function(status, errorReason) { - if (status === 'ok') { - self.onDisconnect_.remember(path, newNode); - } - self.callOnCompleteCallback(onComplete, status, errorReason); - }); - }, - - onDisconnectUpdate: function(path, childrenToMerge, onComplete) { - var empty = true; - for (var childName in childrenToMerge) { - empty = false; - } - if (empty) { - fb.core.util.log('onDisconnect().update() called with empty data. Don\'t do anything.'); - this.callOnCompleteCallback(onComplete, 'ok'); - return; - } - - var self = this; - this.server_.onDisconnectMerge(path.toString(), childrenToMerge, function(status, errorReason) { - if (status === 'ok') { - for (var childName in childrenToMerge) { - var newChildNode = fb.core.snap.NodeFromJSON(childrenToMerge[childName]); - self.onDisconnect_.remember(path.child(childName), newChildNode); - } - } - self.callOnCompleteCallback(onComplete, status, errorReason); - }); - }, - - /** - * @param {!fb.api.Query} query - * @param {!fb.core.view.EventRegistration} eventRegistration - */ - addEventCallbackForQuery: function(query, eventRegistration) { - var events; - if (query.path.getFront() === '.info') { - events = this.infoSyncTree_.addEventRegistration(query, eventRegistration); - } else { - events = this.serverSyncTree_.addEventRegistration(query, eventRegistration); - } - this.eventQueue_.raiseEventsAtPath(query.path, events); - }, - - /** - * @param {!fb.api.Query} query - * @param {?fb.core.view.EventRegistration} eventRegistration - */ - removeEventCallbackForQuery: function(query, eventRegistration) { - // These are guaranteed not to raise events, since we're not passing in a cancelError. However, we can future-proof - // a little bit by handling the return values anyways. - var events; - if (query.path.getFront() === '.info') { - events = this.infoSyncTree_.removeEventRegistration(query, eventRegistration); - } else { - events = this.serverSyncTree_.removeEventRegistration(query, eventRegistration); - } - this.eventQueue_.raiseEventsAtPath(query.path, events); - }, - - interrupt: function() { - if (this.persistentConnection_) { - this.persistentConnection_.interrupt(INTERRUPT_REASON); - } - }, - - resume: function() { - if (this.persistentConnection_) { - this.persistentConnection_.resume(INTERRUPT_REASON); - } - }, - - stats: function(showDelta) { - if (typeof console === 'undefined') - return; - - var stats; - if (showDelta) { - if (!this.statsListener_) - this.statsListener_ = new fb.core.stats.StatsListener(this.stats_); - stats = this.statsListener_.get(); - } else { - stats = this.stats_.get(); - } - - var longestName = goog.array.reduce( - goog.object.getKeys(stats), - function(previousValue, currentValue, index, array) { - return Math.max(currentValue.length, previousValue); - }, - 0); - - for (var stat in stats) { - var value = stats[stat]; - // pad stat names to be the same length (plus 2 extra spaces). - for (var i = stat.length; i < longestName + 2; i++) - stat += ' '; - console.log(stat + value); - } - }, - - statsIncrementCounter: function(metric) { - this.stats_.incrementCounter(metric); - this.statsReporter_.includeStat(metric); - }, - - /** - * @param {...*} var_args - * @private - */ - log_: function(var_args) { - var prefix = ''; - if (this.persistentConnection_) { - prefix = this.persistentConnection_.id + ':'; - } - fb.core.util.log(prefix, arguments); - }, - - /** - * @param {?function(?Error, *=)} callback - * @param {!string} status - * @param {?string=} errorReason - */ - callOnCompleteCallback: function(callback, status, errorReason) { - if (callback) { - fb.core.util.exceptionGuard(function() { - if (status == 'ok') { - callback(null); - } else { - var code = (status || 'error').toUpperCase(); - var message = code; - if (errorReason) - message += ': ' + errorReason; - - var error = new Error(message); - error.code = code; - callback(error); - } - }); - } - } -}); // end fb.core.Repo - - -// TODO: This code is largely the same as .setWithPriority. Refactor? - -/* TODO: Enable onDisconnect().setPriority(priority, callback) -fb.core.Repo.prototype.onDisconnectSetPriority = function(path, priority, onComplete) { - var self = this; - this.server_.onDisconnectPut(path.toString() + '/.priority', priority, function(status) { - self.callOnCompleteCallback(onComplete, status); - }); -};*/ diff --git a/src/database/js-client/core/RepoInfo.js b/src/database/js-client/core/RepoInfo.js deleted file mode 100644 index d62353df708..00000000000 --- a/src/database/js-client/core/RepoInfo.js +++ /dev/null @@ -1,106 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.RepoInfo'); -goog.require('fb.core.storage'); - -/** - * A class that holds metadata about a Repo object - * @param {string} host Hostname portion of the url for the repo - * @param {boolean} secure Whether or not this repo is accessed over ssl - * @param {string} namespace The namespace represented by the repo - * @param {boolean} webSocketOnly Whether to prefer websockets over all other transports (used by Nest). - * @param {string=} persistenceKey Override the default session persistence storage key - * @constructor - */ -fb.core.RepoInfo = function(host, secure, namespace, webSocketOnly, persistenceKey) { - this.host = host.toLowerCase(); - this.domain = this.host.substr(this.host.indexOf('.') + 1); - this.secure = secure; - this.namespace = namespace; - this.webSocketOnly = webSocketOnly; - this.persistenceKey = persistenceKey || ''; - this.internalHost = fb.core.storage.PersistentStorage.get('host:' + host) || this.host; -}; - -fb.core.RepoInfo.prototype.needsQueryParam = function() { - return this.host !== this.internalHost; -}; - -fb.core.RepoInfo.prototype.isCacheableHost = function() { - return this.internalHost.substr(0, 2) === 's-'; -}; - -fb.core.RepoInfo.prototype.isDemoHost = function() { - return this.domain === 'firebaseio-demo.com'; -}; - -fb.core.RepoInfo.prototype.isCustomHost = function() { - return this.domain !== 'firebaseio.com' && this.domain !== 'firebaseio-demo.com'; -}; - -fb.core.RepoInfo.prototype.updateHost = function(newHost) { - if (newHost !== this.internalHost) { - this.internalHost = newHost; - if (this.isCacheableHost()) { - fb.core.storage.PersistentStorage.set('host:' + this.host, this.internalHost); - } - } -}; - - -/** - * Returns the websocket URL for this repo - * @param {string} type of connection - * @param {Object} params list - * @return {string} The URL for this repo - */ -fb.core.RepoInfo.prototype.connectionURL = function(type, params) { - fb.core.util.assert(typeof type === 'string', 'typeof type must == string'); - fb.core.util.assert(typeof params === 'object', 'typeof params must == object'); - var connURL; - if (type === fb.realtime.Constants.WEBSOCKET) { - connURL = (this.secure ? 'wss://' : 'ws://') + this.internalHost + '/.ws?'; - } else if (type === fb.realtime.Constants.LONG_POLLING) { - connURL = (this.secure ? 'https://' : 'http://') + this.internalHost + '/.lp?'; - } else { - throw new Error('Unknown connection type: ' + type); - } - if (this.needsQueryParam()) { - params['ns'] = this.namespace; - } - - var pairs = []; - - goog.object.forEach(params, function(element, index, obj) { - pairs.push(index + '=' + element); - }); - - return connURL + pairs.join('&'); -}; - -/** @return {string} */ -fb.core.RepoInfo.prototype.toString = function() { - var str = this.toURLString(); - if (this.persistenceKey) { - str += '<' + this.persistenceKey + '>'; - } - return str; -}; - -/** @return {string} */ -fb.core.RepoInfo.prototype.toURLString = function() { - return (this.secure ? 'https://' : 'http://') + this.host; -}; diff --git a/src/database/js-client/core/RepoManager.js b/src/database/js-client/core/RepoManager.js deleted file mode 100644 index 2a4582d2f33..00000000000 --- a/src/database/js-client/core/RepoManager.js +++ /dev/null @@ -1,128 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.RepoManager'); -goog.require('fb.core.Repo'); -goog.require('fb.core.Repo_transaction'); -goog.require('fb.util.obj'); - - -/** @const {string} */ -var DATABASE_URL_OPTION = 'databaseURL'; - - -/** - * Creates and caches fb.core.Repo instances. - */ -fb.core.RepoManager = goog.defineClass(null, { - constructor: function() { - /** - * @private {!Object.} - */ - this.repos_ = { }; - - /** - * If true, new Repos will be created to use ReadonlyRestClient (for testing purposes). - * @private {boolean} - */ - this.useRestClient_ = false; - }, - - // TODO(koss): Remove these functions unless used in tests? - interrupt: function() { - for (var repo in this.repos_) { - this.repos_[repo].interrupt(); - } - }, - - resume: function() { - for (var repo in this.repos_) { - this.repos_[repo].resume(); - } - }, - - /** - * This function should only ever be called to CREATE a new database instance. - * - * @param {!firebase.app.App} app - * @return {!fb.api.Database} - */ - databaseFromApp: function(app) { - var dbUrl = app.options[DATABASE_URL_OPTION]; - if (!goog.isDef(dbUrl)) { - fb.core.util.fatal("Can't determine Firebase Database URL. Be sure to include " + - DATABASE_URL_OPTION + - " option when calling firebase.intializeApp()."); - } - - var parsedUrl = fb.core.util.parseRepoInfo(dbUrl); - var repoInfo = parsedUrl.repoInfo; - - fb.core.util.validation.validateUrl('Invalid Firebase Database URL', 1, parsedUrl); - if (!parsedUrl.path.isEmpty()) { - fb.core.util.fatal("Database URL must point to the root of a Firebase Database " + - "(not including a child path)."); - } - - var repo = this.createRepo(repoInfo, app); - - return repo.database; - }, - - /** - * Remove the repo and make sure it is disconnected. - * - * @param {!fb.core.Repo} repo - */ - deleteRepo: function(repo) { - // This should never happen... - if (fb.util.obj.get(this.repos_, repo.app.name) !== repo) { - fb.core.util.fatal("Database " + repo.app.name + " has already been deleted."); - } - repo.interrupt(); - delete this.repos_[repo.app.name]; - }, - - /** - * Ensures a repo doesn't already exist and then creates one using the - * provided app. - * - * @param {!fb.core.RepoInfo} repoInfo The metadata about the Repo - * @param {!firebase.app.App} app - * @return {!fb.core.Repo} The Repo object for the specified server / repoName. - */ - createRepo: function(repoInfo, app) { - var repo = fb.util.obj.get(this.repos_, app.name); - if (repo) { - fb.core.util.fatal('FIREBASE INTERNAL ERROR: Database initialized multiple times.'); - } - repo = new fb.core.Repo(repoInfo, this.useRestClient_, app); - this.repos_[app.name] = repo; - - return repo; - }, - - /** - * Forces us to use ReadonlyRestClient instead of PersistentConnection for new Repos. - * @param {boolean} forceRestClient - */ - forceRestClient: function(forceRestClient) { - this.useRestClient_ = forceRestClient; - }, -}); // end fb.core.RepoManager - -goog.addSingletonGetter(fb.core.RepoManager); -goog.exportProperty(fb.core.RepoManager.prototype, 'interrupt', fb.core.RepoManager.prototype.interrupt); -goog.exportProperty(fb.core.RepoManager.prototype, 'resume', fb.core.RepoManager.prototype.resume); diff --git a/src/database/js-client/core/Repo_transaction.js b/src/database/js-client/core/Repo_transaction.js deleted file mode 100644 index 299d4df4f91..00000000000 --- a/src/database/js-client/core/Repo_transaction.js +++ /dev/null @@ -1,633 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.Repo_transaction'); -goog.require('fb.core.Repo'); -goog.require('fb.core.snap.PriorityIndex'); -goog.require('fb.core.util'); - -// TODO: This is pretty messy. Ideally, a lot of this would move into FirebaseData, or a transaction-specific -// component used by FirebaseData, but it has ties to user callbacks (transaction update and onComplete) as well -// as the realtime connection (to send transactions to the server). So that all needs to be decoupled first. -// For now it's part of Repo, but in its own file. - -/** - * @enum {number} - */ -fb.core.TransactionStatus = { - // We've run the transaction and updated transactionResultData_ with the result, but it isn't currently sent to the - // server. A transaction will go from RUN -> SENT -> RUN if it comes back from the server as rejected due to - // mismatched hash. - RUN: 1, - - // We've run the transaction and sent it to the server and it's currently outstanding (hasn't come back as accepted - // or rejected yet). - SENT: 2, - - // Temporary state used to mark completed transactions (whether successful or aborted). The transaction will be - // removed when we get a chance to prune completed ones. - COMPLETED: 3, - - // Used when an already-sent transaction needs to be aborted (e.g. due to a conflicting set() call that was made). - // If it comes back as unsuccessful, we'll abort it. - SENT_NEEDS_ABORT: 4, - - // Temporary state used to mark transactions that need to be aborted. - NEEDS_ABORT: 5 -}; - -/** - * If a transaction does not succeed after 25 retries, we abort it. Among other things this ensure that if there's - * ever a bug causing a mismatch between client / server hashes for some data, we won't retry indefinitely. - * @type {number} - * @const - * @private - */ -fb.core.Repo.MAX_TRANSACTION_RETRIES_ = 25; - -/** - * @typedef {{ - * path: !fb.core.util.Path, - * update: function(*):*, - * onComplete: ?function(?Error, boolean, ?fb.api.DataSnapshot), - * status: ?fb.core.TransactionStatus, - * order: !number, - * applyLocally: boolean, - * retryCount: !number, - * unwatcher: function(), - * abortReason: ?string, - * currentWriteId: !number, - * currentHash: ?string, - * currentInputSnapshot: ?fb.core.snap.Node, - * currentOutputSnapshotRaw: ?fb.core.snap.Node, - * currentOutputSnapshotResolved: ?fb.core.snap.Node - * }} - */ -fb.core.Transaction; - -/** - * Setup the transaction data structures - * @private - */ -fb.core.Repo.prototype.transactions_init_ = function() { - /** - * Stores queues of outstanding transactions for Firebase locations. - * - * @type {!fb.core.util.Tree.>} - * @private - */ - this.transactionQueueTree_ = new fb.core.util.Tree(); -}; - -/** - * Creates a new transaction, adds it to the transactions we're tracking, and sends it to the server if possible. - * - * @param {!fb.core.util.Path} path Path at which to do transaction. - * @param {function(*):*} transactionUpdate Update callback. - * @param {?function(?Error, boolean, ?fb.api.DataSnapshot)} onComplete Completion callback. - * @param {boolean} applyLocally Whether or not to make intermediate results visible - */ -fb.core.Repo.prototype.startTransaction = function(path, transactionUpdate, onComplete, applyLocally) { - this.log_('transaction on ' + path); - - // Add a watch to make sure we get server updates. - var valueCallback = function() { }; - var watchRef = new Firebase(this, path); - watchRef.on('value', valueCallback); - var unwatcher = function() { watchRef.off('value', valueCallback); }; - - // Initialize transaction. - var transaction = /** @type {fb.core.Transaction} */ ({ - path: path, - update: transactionUpdate, - onComplete: onComplete, - - // One of fb.core.TransactionStatus enums. - status: null, - - // Used when combining transactions at different locations to figure out which one goes first. - order: fb.core.util.LUIDGenerator(), - - // Whether to raise local events for this transaction. - applyLocally: applyLocally, - - // Count of how many times we've retried the transaction. - retryCount: 0, - - // Function to call to clean up our .on() listener. - unwatcher: unwatcher, - - // Stores why a transaction was aborted. - abortReason: null, - - currentWriteId: null, - - currentInputSnapshot: null, - - currentOutputSnapshotRaw: null, - - currentOutputSnapshotResolved: null - }); - - - // Run transaction initially. - var currentState = this.getLatestState_(path); - transaction.currentInputSnapshot = currentState; - var newVal = transaction.update(currentState.val()); - if (!goog.isDef(newVal)) { - // Abort transaction. - transaction.unwatcher(); - transaction.currentOutputSnapshotRaw = null; - transaction.currentOutputSnapshotResolved = null; - if (transaction.onComplete) { - // We just set the input snapshot, so this cast should be safe - var snapshot = new fb.api.DataSnapshot(/** @type {!fb.core.snap.Node} */ (transaction.currentInputSnapshot), - new Firebase(this, transaction.path), fb.core.snap.PriorityIndex); - transaction.onComplete(/*error=*/null, /*committed=*/false, snapshot); - } - } else { - fb.core.util.validation.validateFirebaseData('transaction failed: Data returned ', newVal, transaction.path); - - // Mark as run and add to our queue. - transaction.status = fb.core.TransactionStatus.RUN; - var queueNode = this.transactionQueueTree_.subTree(path); - var nodeQueue = queueNode.getValue() || []; - nodeQueue.push(transaction); - - queueNode.setValue(nodeQueue); - - // Update visibleData and raise events - // Note: We intentionally raise events after updating all of our transaction state, since the user could - // start new transactions from the event callbacks. - var priorityForNode; - if (typeof newVal === 'object' && newVal !== null && fb.util.obj.contains(newVal, '.priority')) { - priorityForNode = fb.util.obj.get(newVal, '.priority'); - fb.core.util.assert(fb.core.util.validation.isValidPriority(priorityForNode), 'Invalid priority returned by transaction. ' + - 'Priority must be a valid string, finite number, server value, or null.'); - } else { - var currentNode = this.serverSyncTree_.calcCompleteEventCache(path) || fb.core.snap.EMPTY_NODE; - priorityForNode = currentNode.getPriority().val(); - } - priorityForNode = /** @type {null|number|string} */ (priorityForNode); - - var serverValues = this.generateServerValues(); - var newNodeUnresolved = fb.core.snap.NodeFromJSON(newVal, priorityForNode); - var newNode = fb.core.util.ServerValues.resolveDeferredValueSnapshot(newNodeUnresolved, serverValues); - transaction.currentOutputSnapshotRaw = newNodeUnresolved; - transaction.currentOutputSnapshotResolved = newNode; - transaction.currentWriteId = this.getNextWriteId_(); - - var events = this.serverSyncTree_.applyUserOverwrite(path, newNode, transaction.currentWriteId, - transaction.applyLocally); - this.eventQueue_.raiseEventsForChangedPath(path, events); - - this.sendReadyTransactions_(); - } -}; - -/** - * @param {!fb.core.util.Path} path - * @param {Array.=} excludeSets A specific set to exclude - * @return {fb.core.snap.Node} - * @private - */ -fb.core.Repo.prototype.getLatestState_ = function(path, excludeSets) { - return this.serverSyncTree_.calcCompleteEventCache(path, excludeSets) || fb.core.snap.EMPTY_NODE; -}; - - -/** - * Sends any already-run transactions that aren't waiting for outstanding transactions to - * complete. - * - * Externally it's called with no arguments, but it calls itself recursively with a particular - * transactionQueueTree node to recurse through the tree. - * - * @param {fb.core.util.Tree.>=} opt_node transactionQueueTree node to start at. - * @private - */ -fb.core.Repo.prototype.sendReadyTransactions_ = function(opt_node) { - var node = /** @type {!fb.core.util.Tree.>} */ (opt_node || this.transactionQueueTree_); - - // Before recursing, make sure any completed transactions are removed. - if (!opt_node) { - this.pruneCompletedTransactionsBelowNode_(node); - } - - if (node.getValue() !== null) { - var queue = this.buildTransactionQueue_(node); - fb.core.util.assert(queue.length > 0, 'Sending zero length transaction queue'); - - var allRun = goog.array.every(queue, function(transaction) { - return transaction.status === fb.core.TransactionStatus.RUN; - }); - - // If they're all run (and not sent), we can send them. Else, we must wait. - if (allRun) { - this.sendTransactionQueue_(node.path(), queue); - } - } else if (node.hasChildren()) { - var self = this; - node.forEachChild(function(childNode) { - self.sendReadyTransactions_(childNode); - }); - } -}; - - -/** - * Given a list of run transactions, send them to the server and then handle the result (success or failure). - * - * @param {!fb.core.util.Path} path The location of the queue. - * @param {!Array.} queue Queue of transactions under the specified location. - * @private - */ -fb.core.Repo.prototype.sendTransactionQueue_ = function(path, queue) { - // Mark transactions as sent and increment retry count! - var setsToIgnore = goog.array.map(queue, function(txn) { return txn.currentWriteId; }); - var latestState = this.getLatestState_(path, setsToIgnore); - var snapToSend = latestState; - var latestHash = latestState.hash(); - for (var i = 0; i < queue.length; i++) { - var txn = queue[i]; - fb.core.util.assert(txn.status === fb.core.TransactionStatus.RUN, - 'tryToSendTransactionQueue_: items in queue should all be run.'); - txn.status = fb.core.TransactionStatus.SENT; - txn.retryCount++; - var relativePath = fb.core.util.Path.relativePath(path, txn.path); - // If we've gotten to this point, the output snapshot must be defined. - snapToSend = snapToSend.updateChild(relativePath, /**@type {!fb.core.snap.Node} */ (txn.currentOutputSnapshotRaw)); - } - - var dataToSend = snapToSend.val(true); - var pathToSend = path; - - // Send the put. - var self = this; - this.server_.put(pathToSend.toString(), dataToSend, function(status) { - self.log_('transaction put response', {path: pathToSend.toString(), status: status}); - - var events = []; - if (status === 'ok') { - // Queue up the callbacks and fire them after cleaning up all of our transaction state, since - // the callback could trigger more transactions or sets. - var callbacks = []; - for (i = 0; i < queue.length; i++) { - queue[i].status = fb.core.TransactionStatus.COMPLETED; - events = events.concat(self.serverSyncTree_.ackUserWrite(queue[i].currentWriteId)); - if (queue[i].onComplete) { - // We never unset the output snapshot, and given that this transaction is complete, it should be set - var node = /** @type {!fb.core.snap.Node} */ (queue[i].currentOutputSnapshotResolved); - var ref = new Firebase(self, queue[i].path); - var snapshot = new fb.api.DataSnapshot(node, ref, fb.core.snap.PriorityIndex); - callbacks.push(goog.bind(queue[i].onComplete, null, null, true, snapshot)); - } - queue[i].unwatcher(); - } - - // Now remove the completed transactions. - self.pruneCompletedTransactionsBelowNode_(self.transactionQueueTree_.subTree(path)); - // There may be pending transactions that we can now send. - self.sendReadyTransactions_(); - - self.eventQueue_.raiseEventsForChangedPath(path, events); - - // Finally, trigger onComplete callbacks. - for (i = 0; i < callbacks.length; i++) { - fb.core.util.exceptionGuard(callbacks[i]); - } - } else { - // transactions are no longer sent. Update their status appropriately. - if (status === 'datastale') { - for (i = 0; i < queue.length; i++) { - if (queue[i].status === fb.core.TransactionStatus.SENT_NEEDS_ABORT) - queue[i].status = fb.core.TransactionStatus.NEEDS_ABORT; - else - queue[i].status = fb.core.TransactionStatus.RUN; - } - } else { - fb.core.util.warn('transaction at ' + pathToSend.toString() + ' failed: ' + status); - for (i = 0; i < queue.length; i++) { - queue[i].status = fb.core.TransactionStatus.NEEDS_ABORT; - queue[i].abortReason = status; - } - } - - self.rerunTransactions_(path); - } - }, latestHash); -}; - -/** - * Finds all transactions dependent on the data at changedPath and reruns them. - * - * Should be called any time cached data changes. - * - * Return the highest path that was affected by rerunning transactions. This is the path at which events need to - * be raised for. - * - * @param {!fb.core.util.Path} changedPath The path in mergedData that changed. - * @return {!fb.core.util.Path} The rootmost path that was affected by rerunning transactions. - * @private - */ -fb.core.Repo.prototype.rerunTransactions_ = function(changedPath) { - var rootMostTransactionNode = this.getAncestorTransactionNode_(changedPath); - var path = rootMostTransactionNode.path(); - - var queue = this.buildTransactionQueue_(rootMostTransactionNode); - this.rerunTransactionQueue_(queue, path); - - return path; -}; - - -/** - * Does all the work of rerunning transactions (as well as cleans up aborted transactions and whatnot). - * - * @param {Array.} queue The queue of transactions to run. - * @param {!fb.core.util.Path} path The path the queue is for. - * @private - */ -fb.core.Repo.prototype.rerunTransactionQueue_ = function(queue, path) { - if (queue.length === 0) { - return; // Nothing to do! - } - - // Queue up the callbacks and fire them after cleaning up all of our transaction state, since - // the callback could trigger more transactions or sets. - var callbacks = []; - var events = []; - // Ignore all of the sets we're going to re-run. - var txnsToRerun = goog.array.filter(queue, function(q) { return q.status === fb.core.TransactionStatus.RUN; }); - var setsToIgnore = goog.array.map(txnsToRerun, function(q) { return q.currentWriteId; }); - for (var i = 0; i < queue.length; i++) { - var transaction = queue[i]; - var relativePath = fb.core.util.Path.relativePath(path, transaction.path); - var abortTransaction = false, abortReason; - fb.core.util.assert(relativePath !== null, 'rerunTransactionsUnderNode_: relativePath should not be null.'); - - if (transaction.status === fb.core.TransactionStatus.NEEDS_ABORT) { - abortTransaction = true; - abortReason = transaction.abortReason; - events = events.concat(this.serverSyncTree_.ackUserWrite(transaction.currentWriteId, true)); - } else if (transaction.status === fb.core.TransactionStatus.RUN) { - if (transaction.retryCount >= fb.core.Repo.MAX_TRANSACTION_RETRIES_) { - abortTransaction = true; - abortReason = 'maxretry'; - events = events.concat(this.serverSyncTree_.ackUserWrite(transaction.currentWriteId, true)); - } else { - // This code reruns a transaction - var currentNode = this.getLatestState_(transaction.path, setsToIgnore); - transaction.currentInputSnapshot = currentNode; - var newData = queue[i].update(currentNode.val()); - if (goog.isDef(newData)) { - fb.core.util.validation.validateFirebaseData('transaction failed: Data returned ', newData, transaction.path); - var newDataNode = fb.core.snap.NodeFromJSON(newData); - var hasExplicitPriority = (typeof newData === 'object' && newData != null && - fb.util.obj.contains(newData, '.priority')); - if (!hasExplicitPriority) { - // Keep the old priority if there wasn't a priority explicitly specified. - newDataNode = newDataNode.updatePriority(currentNode.getPriority()); - } - - var oldWriteId = transaction.currentWriteId; - var serverValues = this.generateServerValues(); - var newNodeResolved = fb.core.util.ServerValues.resolveDeferredValueSnapshot(newDataNode, serverValues); - - transaction.currentOutputSnapshotRaw = newDataNode; - transaction.currentOutputSnapshotResolved = newNodeResolved; - transaction.currentWriteId = this.getNextWriteId_(); - // Mutates setsToIgnore in place - goog.array.remove(setsToIgnore, oldWriteId); - events = events.concat( - this.serverSyncTree_.applyUserOverwrite(transaction.path, newNodeResolved, transaction.currentWriteId, - transaction.applyLocally) - ); - events = events.concat(this.serverSyncTree_.ackUserWrite(oldWriteId, true)); - } else { - abortTransaction = true; - abortReason = 'nodata'; - events = events.concat(this.serverSyncTree_.ackUserWrite(transaction.currentWriteId, true)); - } - } - } - this.eventQueue_.raiseEventsForChangedPath(path, events); - events = []; - if (abortTransaction) { - // Abort. - queue[i].status = fb.core.TransactionStatus.COMPLETED; - - // Removing a listener can trigger pruning which can muck with mergedData/visibleData (as it prunes data). - // So defer the unwatcher until we're done. - (function(unwatcher) { - setTimeout(unwatcher, Math.floor(0)); - })(queue[i].unwatcher); - - if (queue[i].onComplete) { - if (abortReason === 'nodata') { - var ref = new Firebase(this, queue[i].path); - // We set this field immediately, so it's safe to cast to an actual snapshot - var lastInput = /** @type {!fb.core.snap.Node} */ (queue[i].currentInputSnapshot); - var snapshot = new fb.api.DataSnapshot(lastInput, ref, fb.core.snap.PriorityIndex); - callbacks.push(goog.bind(queue[i].onComplete, null, null, false, snapshot)); - } else { - callbacks.push(goog.bind(queue[i].onComplete, null, new Error(abortReason), false, null)); - } - } - } - } - - // Clean up completed transactions. - this.pruneCompletedTransactionsBelowNode_(this.transactionQueueTree_); - - // Now fire callbacks, now that we're in a good, known state. - for (i = 0; i < callbacks.length; i++) { - fb.core.util.exceptionGuard(callbacks[i]); - } - - // Try to send the transaction result to the server. - this.sendReadyTransactions_(); -}; - - -/** - * Returns the rootmost ancestor node of the specified path that has a pending transaction on it, or just returns - * the node for the given path if there are no pending transactions on any ancestor. - * - * @param {!fb.core.util.Path} path The location to start at. - * @return {!fb.core.util.Tree.>} The rootmost node with a transaction. - * @private - */ -fb.core.Repo.prototype.getAncestorTransactionNode_ = function(path) { - var front; - - // Start at the root and walk deeper into the tree towards path until we find a node with pending transactions. - var transactionNode = this.transactionQueueTree_; - while ((front = path.getFront()) !== null && transactionNode.getValue() === null) { - transactionNode = transactionNode.subTree(front); - path = path.popFront(); - } - - return transactionNode; -}; - - -/** - * Builds the queue of all transactions at or below the specified transactionNode. - * - * @param {!fb.core.util.Tree.>} transactionNode - * @return {Array.} The generated queue. - * @private - */ -fb.core.Repo.prototype.buildTransactionQueue_ = function(transactionNode) { - // Walk any child transaction queues and aggregate them into a single queue. - var transactionQueue = []; - this.aggregateTransactionQueuesForNode_(transactionNode, transactionQueue); - - // Sort them by the order the transactions were created. - transactionQueue.sort(function(a, b) { return a.order - b.order; }); - - return transactionQueue; -}; - -/** - * @param {!fb.core.util.Tree.>} node - * @param {Array.} queue - * @private - */ -fb.core.Repo.prototype.aggregateTransactionQueuesForNode_ = function(node, queue) { - var nodeQueue = node.getValue(); - if (nodeQueue !== null) { - for (var i = 0; i < nodeQueue.length; i++) { - queue.push(nodeQueue[i]); - } - } - - var self = this; - node.forEachChild(function(child) { - self.aggregateTransactionQueuesForNode_(child, queue); - }); -}; - - -/** - * Remove COMPLETED transactions at or below this node in the transactionQueueTree_. - * - * @param {!fb.core.util.Tree.>} node - * @private - */ -fb.core.Repo.prototype.pruneCompletedTransactionsBelowNode_ = function(node) { - var queue = node.getValue(); - if (queue) { - var to = 0; - for (var from = 0; from < queue.length; from++) { - if (queue[from].status !== fb.core.TransactionStatus.COMPLETED) { - queue[to] = queue[from]; - to++; - } - } - queue.length = to; - node.setValue(queue.length > 0 ? queue : null); - } - - var self = this; - node.forEachChild(function(childNode) { - self.pruneCompletedTransactionsBelowNode_(childNode); - }); -}; - - -/** - * Aborts all transactions on ancestors or descendants of the specified path. Called when doing a set() or update() - * since we consider them incompatible with transactions. - * - * @param {!fb.core.util.Path} path Path for which we want to abort related transactions. - * @return {!fb.core.util.Path} - * @private - */ -fb.core.Repo.prototype.abortTransactions_ = function(path) { - var affectedPath = this.getAncestorTransactionNode_(path).path(); - - var transactionNode = this.transactionQueueTree_.subTree(path); - var self = this; - - transactionNode.forEachAncestor(function(node) { - self.abortTransactionsOnNode_(node); - }); - - this.abortTransactionsOnNode_(transactionNode); - - transactionNode.forEachDescendant(function(node) { - self.abortTransactionsOnNode_(node); - }); - - return affectedPath; -}; - - -/** - * Abort transactions stored in this transaction queue node. - * - * @param {!fb.core.util.Tree.>} node Node to abort transactions for. - * @private - */ -fb.core.Repo.prototype.abortTransactionsOnNode_ = function(node) { - var queue = node.getValue(); - if (queue !== null) { - - // Queue up the callbacks and fire them after cleaning up all of our transaction state, since - // the callback could trigger more transactions or sets. - var callbacks = []; - - // Go through queue. Any already-sent transactions must be marked for abort, while the unsent ones - // can be immediately aborted and removed. - var events = []; - var lastSent = -1; - for (var i = 0; i < queue.length; i++) { - if (queue[i].status === fb.core.TransactionStatus.SENT_NEEDS_ABORT) { - // Already marked. No action needed. - } else if (queue[i].status === fb.core.TransactionStatus.SENT) { - fb.core.util.assert(lastSent === i - 1, 'All SENT items should be at beginning of queue.'); - lastSent = i; - // Mark transaction for abort when it comes back. - queue[i].status = fb.core.TransactionStatus.SENT_NEEDS_ABORT; - queue[i].abortReason = 'set'; - } else { - fb.core.util.assert(queue[i].status === fb.core.TransactionStatus.RUN, - 'Unexpected transaction status in abort'); - // We can abort it immediately. - queue[i].unwatcher(); - events = events.concat(this.serverSyncTree_.ackUserWrite(queue[i].currentWriteId, true)); - if (queue[i].onComplete) { - var snapshot = null; - callbacks.push(goog.bind(queue[i].onComplete, null, new Error('set'), false, snapshot)); - } - } - } - if (lastSent === -1) { - // We're not waiting for any sent transactions. We can clear the queue. - node.setValue(null); - } else { - // Remove the transactions we aborted. - queue.length = lastSent + 1; - } - - // Now fire the callbacks. - this.eventQueue_.raiseEventsForChangedPath(node.path(), events); - for (i = 0; i < callbacks.length; i++) { - fb.core.util.exceptionGuard(callbacks[i]); - } - } -}; diff --git a/src/database/js-client/core/ServerActions.js b/src/database/js-client/core/ServerActions.js deleted file mode 100644 index 0275b5ebb20..00000000000 --- a/src/database/js-client/core/ServerActions.js +++ /dev/null @@ -1,91 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.ServerActions'); - - - -/** - * Interface defining the set of actions that can be performed against the Firebase server - * (basically corresponds to our wire protocol). - * - * @interface - */ -fb.core.ServerActions = goog.defineClass(null, { - - /** - * @param {!fb.api.Query} query - * @param {function():string} currentHashFn - * @param {?number} tag - * @param {function(string, *)} onComplete - */ - listen: goog.abstractMethod, - - /** - * Remove a listen. - * - * @param {!fb.api.Query} query - * @param {?number} tag - */ - unlisten: goog.abstractMethod, - - /** - * @param {string} pathString - * @param {*} data - * @param {function(string, string)=} opt_onComplete - * @param {string=} opt_hash - */ - put: goog.abstractMethod, - - /** - * @param {string} pathString - * @param {*} data - * @param {function(string, ?string)} onComplete - * @param {string=} opt_hash - */ - merge: goog.abstractMethod, - - /** - * Refreshes the auth token for the current connection. - * @param {string} token The authentication token - */ - refreshAuthToken: goog.abstractMethod, - - /** - * @param {string} pathString - * @param {*} data - * @param {function(string, string)=} opt_onComplete - */ - onDisconnectPut: goog.abstractMethod, - - /** - * @param {string} pathString - * @param {*} data - * @param {function(string, string)=} opt_onComplete - */ - onDisconnectMerge: goog.abstractMethod, - - /** - * @param {string} pathString - * @param {function(string, string)=} opt_onComplete - */ - onDisconnectCancel: goog.abstractMethod, - - /** - * @param {Object.} stats - */ - reportStats: goog.abstractMethod - -}); // fb.core.ServerActions diff --git a/src/database/js-client/core/SnapshotHolder.js b/src/database/js-client/core/SnapshotHolder.js deleted file mode 100644 index 47bc19f1f88..00000000000 --- a/src/database/js-client/core/SnapshotHolder.js +++ /dev/null @@ -1,52 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.SnapshotHolder'); - - -/** - * Mutable object which basically just stores a reference to the "latest" immutable snapshot. - * - * @constructor - */ -fb.core.SnapshotHolder = function() { - /** @private */ - this.rootNode_ = fb.core.snap.EMPTY_NODE; -}; - -/** - * @param {!fb.core.util.Path} path - * @return {!fb.core.snap.Node} - */ -fb.core.SnapshotHolder.prototype.getNode = function(path) { - return this.rootNode_.getChild(path); -}; - -/** - * @param {!fb.core.util.Path} path - * @param {!fb.core.snap.Node} newSnapshotNode - */ -fb.core.SnapshotHolder.prototype.updateSnapshot = function(path, newSnapshotNode) { - this.rootNode_ = this.rootNode_.updateChild(path, newSnapshotNode); -}; - -if (goog.DEBUG) { - /** - * @return {!string} - */ - fb.core.SnapshotHolder.prototype.toString = function() { - return this.rootNode_.toString(); - }; -} diff --git a/src/database/js-client/core/SparseSnapshotTree.js b/src/database/js-client/core/SparseSnapshotTree.js deleted file mode 100644 index dbf9ebc3aca..00000000000 --- a/src/database/js-client/core/SparseSnapshotTree.js +++ /dev/null @@ -1,175 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.SparseSnapshotTree'); -goog.require('fb.core.snap.Node'); -goog.require('fb.core.snap.PriorityIndex'); -goog.require('fb.core.util.CountedSet'); -goog.require('fb.core.util.Path'); - -/** - * Helper class to store a sparse set of snapshots. - * - * @constructor - */ -fb.core.SparseSnapshotTree = function() { - /** - * @private - * @type {fb.core.snap.Node} - */ - this.value_ = null; - - /** - * @private - * @type {fb.core.util.CountedSet} - */ - this.children_ = null; -}; - -/** - * Gets the node stored at the given path if one exists. - * - * @param {!fb.core.util.Path} path Path to look up snapshot for. - * @return {?fb.core.snap.Node} The retrieved node, or null. - */ -fb.core.SparseSnapshotTree.prototype.find = function(path) { - if (this.value_ != null) { - return this.value_.getChild(path); - } else if (!path.isEmpty() && this.children_ != null) { - var childKey = path.getFront(); - path = path.popFront(); - if (this.children_.contains(childKey)) { - var childTree = this.children_.get(childKey); - return childTree.find(path); - } else { - return null; - } - } else { - return null; - } -}; - - -/** - * Stores the given node at the specified path. If there is already a node - * at a shallower path, it merges the new data into that snapshot node. - * - * @param {!fb.core.util.Path} path Path to look up snapshot for. - * @param {!fb.core.snap.Node} data The new data, or null. - */ -fb.core.SparseSnapshotTree.prototype.remember = function(path, data) { - if (path.isEmpty()) { - this.value_ = data; - this.children_ = null; - } else if (this.value_ !== null) { - this.value_ = this.value_.updateChild(path, data); - } else { - if (this.children_ == null) { - this.children_ = new fb.core.util.CountedSet(); - } - - var childKey = path.getFront(); - if (!this.children_.contains(childKey)) { - this.children_.add(childKey, new fb.core.SparseSnapshotTree()); - } - - var child = this.children_.get(childKey); - path = path.popFront(); - child.remember(path, data); - } -}; - - -/** - * Purge the data at path from the cache. - * - * @param {!fb.core.util.Path} path Path to look up snapshot for. - * @return {boolean} True if this node should now be removed. - */ -fb.core.SparseSnapshotTree.prototype.forget = function(path) { - if (path.isEmpty()) { - this.value_ = null; - this.children_ = null; - return true; - } else { - if (this.value_ !== null) { - if (this.value_.isLeafNode()) { - // We're trying to forget a node that doesn't exist - return false; - } else { - var value = this.value_; - this.value_ = null; - - var self = this; - value.forEachChild(fb.core.snap.PriorityIndex, function(key, tree) { - self.remember(new fb.core.util.Path(key), tree); - }); - - return this.forget(path); - } - } else if (this.children_ !== null) { - var childKey = path.getFront(); - path = path.popFront(); - if (this.children_.contains(childKey)) { - var safeToRemove = this.children_.get(childKey).forget(path); - if (safeToRemove) { - this.children_.remove(childKey); - } - } - - if (this.children_.isEmpty()) { - this.children_ = null; - return true; - } else { - return false; - } - - } else { - return true; - } - } -}; - -/** - * Recursively iterates through all of the stored tree and calls the - * callback on each one. - * - * @param {!fb.core.util.Path} prefixPath Path to look up node for. - * @param {!Function} func The function to invoke for each tree. - */ -fb.core.SparseSnapshotTree.prototype.forEachTree = function(prefixPath, func) { - if (this.value_ !== null) { - func(prefixPath, this.value_); - } else { - this.forEachChild(function(key, tree) { - var path = new fb.core.util.Path(prefixPath.toString() + '/' + key); - tree.forEachTree(path, func); - }); - } -}; - - -/** - * Iterates through each immediate child and triggers the callback. - * - * @param {!Function} func The function to invoke for each child. - */ -fb.core.SparseSnapshotTree.prototype.forEachChild = function(func) { - if (this.children_ !== null) { - this.children_.each(function(key, tree) { - func(key, tree); - }); - } -}; diff --git a/src/database/js-client/core/SyncPoint.js b/src/database/js-client/core/SyncPoint.js deleted file mode 100644 index fb8a2ebaf87..00000000000 --- a/src/database/js-client/core/SyncPoint.js +++ /dev/null @@ -1,233 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.SyncPoint'); -goog.require('fb.core.util'); -goog.require('fb.core.util.ImmutableTree'); -goog.require('fb.core.view.ViewCache'); -goog.require('fb.core.view.EventRegistration'); -goog.require('fb.core.view.View'); -goog.require('goog.array'); - -/** - * SyncPoint represents a single location in a SyncTree with 1 or more event registrations, meaning we need to - * maintain 1 or more Views at this location to cache server data and raise appropriate events for server changes - * and user writes (set, transaction, update). - * - * It's responsible for: - * - Maintaining the set of 1 or more views necessary at this location (a SyncPoint with 0 views should be removed). - * - Proxying user / server operations to the views as appropriate (i.e. applyServerOverwrite, - * applyUserOverwrite, etc.) - * - * @constructor - */ -fb.core.SyncPoint = function() { - /** - * The Views being tracked at this location in the tree, stored as a map where the key is a - * queryId and the value is the View for that query. - * - * NOTE: This list will be quite small (usually 1, but perhaps 2 or 3; any more is an odd use case). - * - * @type {!Object.} - * @private - */ - this.views_ = { }; -}; - -/** - * @return {boolean} - */ -fb.core.SyncPoint.prototype.isEmpty = function() { - return goog.object.isEmpty(this.views_); -}; - -/** - * - * @param {!fb.core.Operation} operation - * @param {!fb.core.WriteTreeRef} writesCache - * @param {?fb.core.snap.Node} optCompleteServerCache - * @return {!Array.} - */ -fb.core.SyncPoint.prototype.applyOperation = function(operation, writesCache, optCompleteServerCache) { - var queryId = operation.source.queryId; - if (queryId !== null) { - var view = fb.util.obj.get(this.views_, queryId); - fb.core.util.assert(view != null, 'SyncTree gave us an op for an invalid query.'); - return view.applyOperation(operation, writesCache, optCompleteServerCache); - } else { - var events = []; - - goog.object.forEach(this.views_, function(view) { - events = events.concat(view.applyOperation(operation, writesCache, optCompleteServerCache)); - }); - - return events; - } -}; - -/** - * Add an event callback for the specified query. - * - * @param {!fb.api.Query} query - * @param {!fb.core.view.EventRegistration} eventRegistration - * @param {!fb.core.WriteTreeRef} writesCache - * @param {?fb.core.snap.Node} serverCache Complete server cache, if we have it. - * @param {boolean} serverCacheComplete - * @return {!Array.} Events to raise. - */ -fb.core.SyncPoint.prototype.addEventRegistration = function(query, eventRegistration, writesCache, serverCache, - serverCacheComplete) { - var queryId = query.queryIdentifier(); - var view = fb.util.obj.get(this.views_, queryId); - if (!view) { - // TODO: make writesCache take flag for complete server node - var eventCache = writesCache.calcCompleteEventCache(serverCacheComplete ? serverCache : null); - var eventCacheComplete = false; - if (eventCache) { - eventCacheComplete = true; - } else if (serverCache instanceof fb.core.snap.ChildrenNode) { - eventCache = writesCache.calcCompleteEventChildren(serverCache); - eventCacheComplete = false; - } else { - eventCache = fb.core.snap.EMPTY_NODE; - eventCacheComplete = false; - } - var viewCache = new fb.core.view.ViewCache( - new fb.core.view.CacheNode(/** @type {!fb.core.snap.Node} */ (eventCache), eventCacheComplete, false), - new fb.core.view.CacheNode(/** @type {!fb.core.snap.Node} */ (serverCache), serverCacheComplete, false) - ); - view = new fb.core.view.View(query, viewCache); - this.views_[queryId] = view; - } - - // This is guaranteed to exist now, we just created anything that was missing - view.addEventRegistration(eventRegistration); - return view.getInitialEvents(eventRegistration); -}; - -/** - * Remove event callback(s). Return cancelEvents if a cancelError is specified. - * - * If query is the default query, we'll check all views for the specified eventRegistration. - * If eventRegistration is null, we'll remove all callbacks for the specified view(s). - * - * @param {!fb.api.Query} query - * @param {?fb.core.view.EventRegistration} eventRegistration If null, remove all callbacks. - * @param {Error=} cancelError If a cancelError is provided, appropriate cancel events will be returned. - * @return {{removed:!Array., events:!Array.}} removed queries and any cancel events - */ -fb.core.SyncPoint.prototype.removeEventRegistration = function(query, eventRegistration, cancelError) { - var queryId = query.queryIdentifier(); - var removed = []; - var cancelEvents = []; - var hadCompleteView = this.hasCompleteView(); - if (queryId === 'default') { - // When you do ref.off(...), we search all views for the registration to remove. - var self = this; - goog.object.forEach(this.views_, function(view, viewQueryId) { - cancelEvents = cancelEvents.concat(view.removeEventRegistration(eventRegistration, cancelError)); - if (view.isEmpty()) { - delete self.views_[viewQueryId]; - - // We'll deal with complete views later. - if (!view.getQuery().getQueryParams().loadsAllData()) { - removed.push(view.getQuery()); - } - } - }); - } else { - // remove the callback from the specific view. - var view = fb.util.obj.get(this.views_, queryId); - if (view) { - cancelEvents = cancelEvents.concat(view.removeEventRegistration(eventRegistration, cancelError)); - if (view.isEmpty()) { - delete this.views_[queryId]; - - // We'll deal with complete views later. - if (!view.getQuery().getQueryParams().loadsAllData()) { - removed.push(view.getQuery()); - } - } - } - } - - if (hadCompleteView && !this.hasCompleteView()) { - // We removed our last complete view. - removed.push(new Firebase(query.repo, query.path)); - } - - return {removed: removed, events: cancelEvents}; -}; - -/** - * @return {!Array.} - */ -fb.core.SyncPoint.prototype.getQueryViews = function() { - return goog.array.filter(goog.object.getValues(this.views_), function(view) { - return !view.getQuery().getQueryParams().loadsAllData(); - }); -}; - -/** - * - * @param {!fb.core.util.Path} path The path to the desired complete snapshot - * @return {?fb.core.snap.Node} A complete cache, if it exists - */ -fb.core.SyncPoint.prototype.getCompleteServerCache = function(path) { - var serverCache = null; - goog.object.forEach(this.views_, function(view) { - serverCache = serverCache || view.getCompleteServerCache(path); - }); - return serverCache; -}; - -/** - * @param {!fb.api.Query} query - * @return {?fb.core.view.View} - */ -fb.core.SyncPoint.prototype.viewForQuery = function(query) { - var params = query.getQueryParams(); - if (params.loadsAllData()) { - return this.getCompleteView(); - } else { - var queryId = query.queryIdentifier(); - return fb.util.obj.get(this.views_, queryId); - } -}; - -/** - * @param {!fb.api.Query} query - * @return {boolean} - */ -fb.core.SyncPoint.prototype.viewExistsForQuery = function(query) { - return this.viewForQuery(query) != null; -}; - -/** - * @return {boolean} - */ -fb.core.SyncPoint.prototype.hasCompleteView = function() { - return this.getCompleteView() != null; -}; - -/** - * @return {?fb.core.view.View} - */ -fb.core.SyncPoint.prototype.getCompleteView = function() { - var completeView = goog.object.findValue(this.views_, function(view) { - return view.getQuery().getQueryParams().loadsAllData(); - }); - return completeView || null; -}; diff --git a/src/database/js-client/core/SyncTree.js b/src/database/js-client/core/SyncTree.js deleted file mode 100644 index 017a653fb42..00000000000 --- a/src/database/js-client/core/SyncTree.js +++ /dev/null @@ -1,749 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.SyncTree'); -goog.require('fb.core.Operation'); -goog.require('fb.core.SyncPoint'); -goog.require('fb.core.WriteTree'); -goog.require('fb.core.util'); - -/** - * @typedef {{ - * startListening: function( - * !fb.api.Query, - * ?number, - * function():string, - * function(!string, *):!Array. - * ):!Array., - * - * stopListening: function(!fb.api.Query, ?number) - * }} - */ -fb.core.ListenProvider; - -/** - * SyncTree is the central class for managing event callback registration, data caching, views - * (query processing), and event generation. There are typically two SyncTree instances for - * each Repo, one for the normal Firebase data, and one for the .info data. - * - * It has a number of responsibilities, including: - * - Tracking all user event callbacks (registered via addEventRegistration() and removeEventRegistration()). - * - Applying and caching data changes for user set(), transaction(), and update() calls - * (applyUserOverwrite(), applyUserMerge()). - * - Applying and caching data changes for server data changes (applyServerOverwrite(), - * applyServerMerge()). - * - Generating user-facing events for server and user changes (all of the apply* methods - * return the set of events that need to be raised as a result). - * - Maintaining the appropriate set of server listens to ensure we are always subscribed - * to the correct set of paths and queries to satisfy the current set of user event - * callbacks (listens are started/stopped using the provided listenProvider). - * - * NOTE: Although SyncTree tracks event callbacks and calculates events to raise, the actual - * events are returned to the caller rather than raised synchronously. - * - * @constructor - * @param {!fb.core.ListenProvider} listenProvider Used by SyncTree to start / stop listening - * to server data. - */ -fb.core.SyncTree = function(listenProvider) { - /** - * Tree of SyncPoints. There's a SyncPoint at any location that has 1 or more views. - * @type {!fb.core.util.ImmutableTree.} - * @private - */ - this.syncPointTree_ = fb.core.util.ImmutableTree.Empty; - - /** - * A tree of all pending user writes (user-initiated set()'s, transaction()'s, update()'s, etc.). - * @type {!fb.core.WriteTree} - * @private - */ - this.pendingWriteTree_ = new fb.core.WriteTree(); - this.tagToQueryMap_ = {}; - this.queryToTagMap_ = {}; - this.listenProvider_ = listenProvider; -}; - - -/** - * Apply the data changes for a user-generated set() or transaction() call. - * - * @param {!fb.core.util.Path} path - * @param {!fb.core.snap.Node} newData - * @param {number} writeId - * @param {boolean=} visible - * @return {!Array.} Events to raise. - */ -fb.core.SyncTree.prototype.applyUserOverwrite = function(path, newData, writeId, visible) { - // Record pending write. - this.pendingWriteTree_.addOverwrite(path, newData, writeId, visible); - - if (!visible) { - return []; - } else { - return this.applyOperationToSyncPoints_( - new fb.core.operation.Overwrite(fb.core.OperationSource.User, path, newData)); - } -}; - -/** - * Apply the data from a user-generated update() call - * - * @param {!fb.core.util.Path} path - * @param {!Object.} changedChildren - * @param {!number} writeId - * @return {!Array.} Events to raise. - */ -fb.core.SyncTree.prototype.applyUserMerge = function(path, changedChildren, writeId) { - // Record pending merge. - this.pendingWriteTree_.addMerge(path, changedChildren, writeId); - - var changeTree = fb.core.util.ImmutableTree.fromObject(changedChildren); - - return this.applyOperationToSyncPoints_( - new fb.core.operation.Merge(fb.core.OperationSource.User, path, changeTree)); -}; - -/** - * Acknowledge a pending user write that was previously registered with applyUserOverwrite() or applyUserMerge(). - * - * @param {!number} writeId - * @param {boolean=} revert True if the given write failed and needs to be reverted - * @return {!Array.} Events to raise. - */ -fb.core.SyncTree.prototype.ackUserWrite = function(writeId, revert) { - revert = revert || false; - - var write = this.pendingWriteTree_.getWrite(writeId); - var needToReevaluate = this.pendingWriteTree_.removeWrite(writeId); - if (!needToReevaluate) { - return []; - } else { - var affectedTree = fb.core.util.ImmutableTree.Empty; - if (write.snap != null) { // overwrite - affectedTree = affectedTree.set(fb.core.util.Path.Empty, true); - } else { - fb.util.obj.foreach(write.children, function(pathString, node) { - affectedTree = affectedTree.set(new fb.core.util.Path(pathString), node); - }); - } - return this.applyOperationToSyncPoints_(new fb.core.operation.AckUserWrite(write.path, affectedTree, revert)); - } -}; - -/** - * Apply new server data for the specified path.. - * - * @param {!fb.core.util.Path} path - * @param {!fb.core.snap.Node} newData - * @return {!Array.} Events to raise. - */ -fb.core.SyncTree.prototype.applyServerOverwrite = function(path, newData) { - return this.applyOperationToSyncPoints_( - new fb.core.operation.Overwrite(fb.core.OperationSource.Server, path, newData)); -}; - -/** - * Apply new server data to be merged in at the specified path. - * - * @param {!fb.core.util.Path} path - * @param {!Object.} changedChildren - * @return {!Array.} Events to raise. - */ -fb.core.SyncTree.prototype.applyServerMerge = function(path, changedChildren) { - var changeTree = fb.core.util.ImmutableTree.fromObject(changedChildren); - - return this.applyOperationToSyncPoints_( - new fb.core.operation.Merge(fb.core.OperationSource.Server, path, changeTree)); -}; - -/** - * Apply a listen complete for a query - * - * @param {!fb.core.util.Path} path - * @return {!Array.} Events to raise. - */ -fb.core.SyncTree.prototype.applyListenComplete = function(path) { - return this.applyOperationToSyncPoints_( - new fb.core.operation.ListenComplete(fb.core.OperationSource.Server, path)); -}; - -/** - * Apply new server data for the specified tagged query. - * - * @param {!fb.core.util.Path} path - * @param {!fb.core.snap.Node} snap - * @param {!number} tag - * @return {!Array.} Events to raise. - */ -fb.core.SyncTree.prototype.applyTaggedQueryOverwrite = function(path, snap, tag) { - var queryKey = this.queryKeyForTag_(tag); - if (queryKey != null) { - var r = this.parseQueryKey_(queryKey); - var queryPath = r.path, queryId = r.queryId; - var relativePath = fb.core.util.Path.relativePath(queryPath, path); - var op = new fb.core.operation.Overwrite(fb.core.OperationSource.forServerTaggedQuery(queryId), - relativePath, snap); - return this.applyTaggedOperation_(queryPath, queryId, op); - } else { - // Query must have been removed already - return []; - } -}; - -/** - * Apply server data to be merged in for the specified tagged query. - * - * @param {!fb.core.util.Path} path - * @param {!Object.} changedChildren - * @param {!number} tag - * @return {!Array.} Events to raise. - */ -fb.core.SyncTree.prototype.applyTaggedQueryMerge = function(path, changedChildren, tag) { - var queryKey = this.queryKeyForTag_(tag); - if (queryKey) { - var r = this.parseQueryKey_(queryKey); - var queryPath = r.path, queryId = r.queryId; - var relativePath = fb.core.util.Path.relativePath(queryPath, path); - var changeTree = fb.core.util.ImmutableTree.fromObject(changedChildren); - var op = new fb.core.operation.Merge(fb.core.OperationSource.forServerTaggedQuery(queryId), - relativePath, changeTree); - return this.applyTaggedOperation_(queryPath, queryId, op); - } else { - // We've already removed the query. No big deal, ignore the update - return []; - } -}; - -/** - * Apply a listen complete for a tagged query - * - * @param {!fb.core.util.Path} path - * @param {!number} tag - * @return {!Array.} Events to raise. - */ -fb.core.SyncTree.prototype.applyTaggedListenComplete = function(path, tag) { - var queryKey = this.queryKeyForTag_(tag); - if (queryKey) { - var r = this.parseQueryKey_(queryKey); - var queryPath = r.path, queryId = r.queryId; - var relativePath = fb.core.util.Path.relativePath(queryPath, path); - var op = new fb.core.operation.ListenComplete(fb.core.OperationSource.forServerTaggedQuery(queryId), - relativePath); - return this.applyTaggedOperation_(queryPath, queryId, op); - } else { - // We've already removed the query. No big deal, ignore the update - return []; - } -}; - -/** - * Add an event callback for the specified query. - * - * @param {!fb.api.Query} query - * @param {!fb.core.view.EventRegistration} eventRegistration - * @return {!Array.} Events to raise. - */ -fb.core.SyncTree.prototype.addEventRegistration = function(query, eventRegistration) { - var path = query.path; - - var serverCache = null; - var foundAncestorDefaultView = false; - // Any covering writes will necessarily be at the root, so really all we need to find is the server cache. - // Consider optimizing this once there's a better understanding of what actual behavior will be. - this.syncPointTree_.foreachOnPath(path, function(pathToSyncPoint, sp) { - var relativePath = fb.core.util.Path.relativePath(pathToSyncPoint, path); - serverCache = serverCache || sp.getCompleteServerCache(relativePath); - foundAncestorDefaultView = foundAncestorDefaultView || sp.hasCompleteView(); - }); - var syncPoint = this.syncPointTree_.get(path); - if (!syncPoint) { - syncPoint = new fb.core.SyncPoint(); - this.syncPointTree_ = this.syncPointTree_.set(path, syncPoint); - } else { - foundAncestorDefaultView = foundAncestorDefaultView || syncPoint.hasCompleteView(); - serverCache = serverCache || syncPoint.getCompleteServerCache(fb.core.util.Path.Empty); - } - - var serverCacheComplete; - if (serverCache != null) { - serverCacheComplete = true; - } else { - serverCacheComplete = false; - serverCache = fb.core.snap.EMPTY_NODE; - var subtree = this.syncPointTree_.subtree(path); - subtree.foreachChild(function(childName, childSyncPoint) { - var completeCache = childSyncPoint.getCompleteServerCache(fb.core.util.Path.Empty); - if (completeCache) { - serverCache = serverCache.updateImmediateChild(childName, completeCache); - } - }); - } - - var viewAlreadyExists = syncPoint.viewExistsForQuery(query); - if (!viewAlreadyExists && !query.getQueryParams().loadsAllData()) { - // We need to track a tag for this query - var queryKey = this.makeQueryKey_(query); - fb.core.util.assert(!goog.object.containsKey(this.queryToTagMap_, queryKey), - 'View does not exist, but we have a tag'); - var tag = fb.core.SyncTree.getNextQueryTag_(); - this.queryToTagMap_[queryKey] = tag; - // Coerce to string to avoid sparse arrays. - this.tagToQueryMap_['_' + tag] = queryKey; - } - var writesCache = this.pendingWriteTree_.childWrites(path); - var events = syncPoint.addEventRegistration(query, eventRegistration, writesCache, serverCache, serverCacheComplete); - if (!viewAlreadyExists && !foundAncestorDefaultView) { - var view = /** @type !fb.core.view.View */ (syncPoint.viewForQuery(query)); - events = events.concat(this.setupListener_(query, view)); - } - return events; -}; - -/** - * Remove event callback(s). - * - * If query is the default query, we'll check all queries for the specified eventRegistration. - * If eventRegistration is null, we'll remove all callbacks for the specified query/queries. - * - * @param {!fb.api.Query} query - * @param {?fb.core.view.EventRegistration} eventRegistration If null, all callbacks are removed. - * @param {Error=} cancelError If a cancelError is provided, appropriate cancel events will be returned. - * @return {!Array.} Cancel events, if cancelError was provided. - */ -fb.core.SyncTree.prototype.removeEventRegistration = function(query, eventRegistration, cancelError) { - // Find the syncPoint first. Then deal with whether or not it has matching listeners - var path = query.path; - var maybeSyncPoint = this.syncPointTree_.get(path); - var cancelEvents = []; - // A removal on a default query affects all queries at that location. A removal on an indexed query, even one without - // other query constraints, does *not* affect all queries at that location. So this check must be for 'default', and - // not loadsAllData(). - if (maybeSyncPoint && (query.queryIdentifier() === 'default' || maybeSyncPoint.viewExistsForQuery(query))) { - /** - * @type {{removed: !Array., events: !Array.}} - */ - var removedAndEvents = maybeSyncPoint.removeEventRegistration(query, eventRegistration, cancelError); - if (maybeSyncPoint.isEmpty()) { - this.syncPointTree_ = this.syncPointTree_.remove(path); - } - var removed = removedAndEvents.removed; - cancelEvents = removedAndEvents.events; - // We may have just removed one of many listeners and can short-circuit this whole process - // We may also not have removed a default listener, in which case all of the descendant listeners should already be - // properly set up. - // - // Since indexed queries can shadow if they don't have other query constraints, check for loadsAllData(), instead of - // queryId === 'default' - var removingDefault = -1 !== goog.array.findIndex(removed, function(query) { - return query.getQueryParams().loadsAllData(); - }); - var covered = this.syncPointTree_.findOnPath(path, function(relativePath, parentSyncPoint) { - return parentSyncPoint.hasCompleteView(); - }); - - if (removingDefault && !covered) { - var subtree = this.syncPointTree_.subtree(path); - // There are potentially child listeners. Determine what if any listens we need to send before executing the - // removal - if (!subtree.isEmpty()) { - // We need to fold over our subtree and collect the listeners to send - var newViews = this.collectDistinctViewsForSubTree_(subtree); - - // Ok, we've collected all the listens we need. Set them up. - for (var i = 0; i < newViews.length; ++i) { - var view = newViews[i], newQuery = view.getQuery(); - var listener = this.createListenerForView_(view); - this.listenProvider_.startListening(this.queryForListening_(newQuery), this.tagForQuery_(newQuery), - listener.hashFn, listener.onComplete); - } - } else { - // There's nothing below us, so nothing we need to start listening on - } - } - // If we removed anything and we're not covered by a higher up listen, we need to stop listening on this query - // The above block has us covered in terms of making sure we're set up on listens lower in the tree. - // Also, note that if we have a cancelError, it's already been removed at the provider level. - if (!covered && removed.length > 0 && !cancelError) { - // If we removed a default, then we weren't listening on any of the other queries here. Just cancel the one - // default. Otherwise, we need to iterate through and cancel each individual query - if (removingDefault) { - // We don't tag default listeners - var defaultTag = null; - this.listenProvider_.stopListening(this.queryForListening_(query), defaultTag); - } else { - var self = this; - goog.array.forEach(removed, function(queryToRemove) { - var queryIdToRemove = queryToRemove.queryIdentifier(); - var tagToRemove = self.queryToTagMap_[self.makeQueryKey_(queryToRemove)]; - self.listenProvider_.stopListening(self.queryForListening_(queryToRemove), tagToRemove); - }); - } - } - // Now, clear all of the tags we're tracking for the removed listens - this.removeTags_(removed); - } else { - // No-op, this listener must've been already removed - } - return cancelEvents; -}; - -/** - * Returns a complete cache, if we have one, of the data at a particular path. The location must have a listener above - * it, but as this is only used by transaction code, that should always be the case anyways. - * - * Note: this method will *include* hidden writes from transaction with applyLocally set to false. - * @param {!fb.core.util.Path} path The path to the data we want - * @param {Array.=} writeIdsToExclude A specific set to be excluded - * @return {?fb.core.snap.Node} - */ -fb.core.SyncTree.prototype.calcCompleteEventCache = function(path, writeIdsToExclude) { - var includeHiddenSets = true; - var writeTree = this.pendingWriteTree_; - var serverCache = this.syncPointTree_.findOnPath(path, function(pathSoFar, syncPoint) { - var relativePath = fb.core.util.Path.relativePath(pathSoFar, path); - var serverCache = syncPoint.getCompleteServerCache(relativePath); - if (serverCache) { - return serverCache; - } - }); - return writeTree.calcCompleteEventCache(path, serverCache, writeIdsToExclude, includeHiddenSets); -}; - -/** - * This collapses multiple unfiltered views into a single view, since we only need a single - * listener for them. - * - * @param {!fb.core.util.ImmutableTree.} subtree - * @return {!Array.} - * @private - */ -fb.core.SyncTree.prototype.collectDistinctViewsForSubTree_ = function(subtree) { - return subtree.fold(function(relativePath, maybeChildSyncPoint, childMap) { - if (maybeChildSyncPoint && maybeChildSyncPoint.hasCompleteView()) { - var completeView = maybeChildSyncPoint.getCompleteView(); - return [completeView]; - } else { - // No complete view here, flatten any deeper listens into an array - var views = []; - if (maybeChildSyncPoint) { - views = maybeChildSyncPoint.getQueryViews(); - } - goog.object.forEach(childMap, function(childViews) { - views = views.concat(childViews); - }); - return views; - } - }); -}; - -/** - * @param {!Array.} queries - * @private - */ -fb.core.SyncTree.prototype.removeTags_ = function(queries) { - for (var j = 0; j < queries.length; ++j) { - var removedQuery = queries[j]; - if (!removedQuery.getQueryParams().loadsAllData()) { - // We should have a tag for this - var removedQueryKey = this.makeQueryKey_(removedQuery); - var removedQueryTag = this.queryToTagMap_[removedQueryKey]; - delete this.queryToTagMap_[removedQueryKey]; - delete this.tagToQueryMap_['_' + removedQueryTag]; - } - } -}; - - -/** - * Normalizes a query to a query we send the server for listening - * @param {!fb.api.Query} query - * @return {!fb.api.Query} The normalized query - * @private - */ -fb.core.SyncTree.prototype.queryForListening_ = function(query) { - if (query.getQueryParams().loadsAllData() && !query.getQueryParams().isDefault()) { - // We treat queries that load all data as default queries - // Cast is necessary because ref() technically returns Firebase which is actually fb.api.Firebase which inherits - // from fb.api.Query - return /** @type {!fb.api.Query} */(query.getRef()); - } else { - return query; - } -}; - - -/** - * For a given new listen, manage the de-duplication of outstanding subscriptions. - * - * @param {!fb.api.Query} query - * @param {!fb.core.view.View} view - * @return {!Array.} This method can return events to support synchronous data sources - * @private - */ -fb.core.SyncTree.prototype.setupListener_ = function(query, view) { - var path = query.path; - var tag = this.tagForQuery_(query); - var listener = this.createListenerForView_(view); - - var events = this.listenProvider_.startListening(this.queryForListening_(query), tag, listener.hashFn, - listener.onComplete); - - var subtree = this.syncPointTree_.subtree(path); - // The root of this subtree has our query. We're here because we definitely need to send a listen for that, but we - // may need to shadow other listens as well. - if (tag) { - fb.core.util.assert(!subtree.value.hasCompleteView(), "If we're adding a query, it shouldn't be shadowed"); - } else { - // Shadow everything at or below this location, this is a default listener. - var queriesToStop = subtree.fold(function(relativePath, maybeChildSyncPoint, childMap) { - if (!relativePath.isEmpty() && maybeChildSyncPoint && maybeChildSyncPoint.hasCompleteView()) { - return [maybeChildSyncPoint.getCompleteView().getQuery()]; - } else { - // No default listener here, flatten any deeper queries into an array - var queries = []; - if (maybeChildSyncPoint) { - queries = queries.concat( - goog.array.map(maybeChildSyncPoint.getQueryViews(), function(view) { - return view.getQuery(); - }) - ); - } - goog.object.forEach(childMap, function(childQueries) { - queries = queries.concat(childQueries); - }); - return queries; - } - }); - for (var i = 0; i < queriesToStop.length; ++i) { - var queryToStop = queriesToStop[i]; - this.listenProvider_.stopListening(this.queryForListening_(queryToStop), this.tagForQuery_(queryToStop)); - } - } - return events; -}; - -/** - * - * @param {!fb.core.view.View} view - * @return {{hashFn: function(), onComplete: function(!string, *)}} - * @private - */ -fb.core.SyncTree.prototype.createListenerForView_ = function(view) { - var self = this; - var query = view.getQuery(); - var tag = this.tagForQuery_(query); - - return { - hashFn: function() { - var cache = view.getServerCache() || fb.core.snap.EMPTY_NODE; - return cache.hash(); - }, - onComplete: function(status, data) { - if (status === 'ok') { - if (tag) { - return self.applyTaggedListenComplete(query.path, tag); - } else { - return self.applyListenComplete(query.path); - } - } else { - // If a listen failed, kill all of the listeners here, not just the one that triggered the error. - // Note that this may need to be scoped to just this listener if we change permissions on filtered children - var error = fb.core.util.errorForServerCode(status, query); - return self.removeEventRegistration(query, /*eventRegistration*/null, error); - } - } - }; -}; - -/** - * Given a query, computes a "queryKey" suitable for use in our queryToTagMap_. - * @private - * @param {!fb.api.Query} query - * @return {string} - */ -fb.core.SyncTree.prototype.makeQueryKey_ = function(query) { - return query.path.toString() + '$' + query.queryIdentifier(); -}; - -/** - * Given a queryKey (created by makeQueryKey), parse it back into a path and queryId. - * @private - * @param {!string} queryKey - * @return {{queryId: !string, path: !fb.core.util.Path}} - */ -fb.core.SyncTree.prototype.parseQueryKey_ = function(queryKey) { - var splitIndex = queryKey.indexOf('$'); - fb.core.util.assert(splitIndex !== -1 && splitIndex < queryKey.length - 1, 'Bad queryKey.'); - return { - queryId: queryKey.substr(splitIndex + 1), - path: new fb.core.util.Path(queryKey.substr(0, splitIndex)) - }; -}; - -/** - * Return the query associated with the given tag, if we have one - * @param {!number} tag - * @return {?string} - * @private - */ -fb.core.SyncTree.prototype.queryKeyForTag_ = function(tag) { - return goog.object.get(this.tagToQueryMap_, '_' + tag); -}; - -/** - * Return the tag associated with the given query. - * @param {!fb.api.Query} query - * @return {?number} - * @private - */ -fb.core.SyncTree.prototype.tagForQuery_ = function(query) { - var queryKey = this.makeQueryKey_(query); - return fb.util.obj.get(this.queryToTagMap_, queryKey); -}; - -/** - * Static tracker for next query tag. - * @type {number} - * @private - */ -fb.core.SyncTree.nextQueryTag_ = 1; - -/** - * Static accessor for query tags. - * @return {number} - * @private - */ -fb.core.SyncTree.getNextQueryTag_ = function() { - return fb.core.SyncTree.nextQueryTag_++; -}; - -/** - * A helper method to apply tagged operations - * - * @param {!fb.core.util.Path} queryPath - * @param {!string} queryId - * @param {!fb.core.Operation} operation - * @return {!Array.} - * @private - */ -fb.core.SyncTree.prototype.applyTaggedOperation_ = function(queryPath, queryId, operation) { - var syncPoint = this.syncPointTree_.get(queryPath); - fb.core.util.assert(syncPoint, "Missing sync point for query tag that we're tracking"); - var writesCache = this.pendingWriteTree_.childWrites(queryPath); - return syncPoint.applyOperation(operation, writesCache, /*serverCache=*/null); -} - -/** - * A helper method that visits all descendant and ancestor SyncPoints, applying the operation. - * - * NOTES: - * - Descendant SyncPoints will be visited first (since we raise events depth-first). - - * - We call applyOperation() on each SyncPoint passing three things: - * 1. A version of the Operation that has been made relative to the SyncPoint location. - * 2. A WriteTreeRef of any writes we have cached at the SyncPoint location. - * 3. A snapshot Node with cached server data, if we have it. - - * - We concatenate all of the events returned by each SyncPoint and return the result. - * - * @param {!fb.core.Operation} operation - * @return {!Array.} - * @private - */ -fb.core.SyncTree.prototype.applyOperationToSyncPoints_ = function(operation) { - return this.applyOperationHelper_(operation, this.syncPointTree_, /*serverCache=*/ null, - this.pendingWriteTree_.childWrites(fb.core.util.Path.Empty)); - -}; - -/** - * Recursive helper for applyOperationToSyncPoints_ - * - * @private - * @param {!fb.core.Operation} operation - * @param {fb.core.util.ImmutableTree.} syncPointTree - * @param {?fb.core.snap.Node} serverCache - * @param {!fb.core.WriteTreeRef} writesCache - * @return {!Array.} - */ -fb.core.SyncTree.prototype.applyOperationHelper_ = function(operation, syncPointTree, serverCache, writesCache) { - - if (operation.path.isEmpty()) { - return this.applyOperationDescendantsHelper_(operation, syncPointTree, serverCache, writesCache); - } else { - var syncPoint = syncPointTree.get(fb.core.util.Path.Empty); - - // If we don't have cached server data, see if we can get it from this SyncPoint. - if (serverCache == null && syncPoint != null) { - serverCache = syncPoint.getCompleteServerCache(fb.core.util.Path.Empty); - } - - var events = []; - var childName = operation.path.getFront(); - var childOperation = operation.operationForChild(childName); - var childTree = syncPointTree.children.get(childName); - if (childTree && childOperation) { - var childServerCache = serverCache ? serverCache.getImmediateChild(childName) : null; - var childWritesCache = writesCache.child(childName); - events = events.concat( - this.applyOperationHelper_(childOperation, childTree, childServerCache, childWritesCache)); - } - - if (syncPoint) { - events = events.concat(syncPoint.applyOperation(operation, writesCache, serverCache)); - } - - return events; - } -}; - -/** - * Recursive helper for applyOperationToSyncPoints_ - * - * @private - * @param {!fb.core.Operation} operation - * @param {fb.core.util.ImmutableTree.} syncPointTree - * @param {?fb.core.snap.Node} serverCache - * @param {!fb.core.WriteTreeRef} writesCache - * @return {!Array.} - */ -fb.core.SyncTree.prototype.applyOperationDescendantsHelper_ = function(operation, syncPointTree, - serverCache, writesCache) { - var syncPoint = syncPointTree.get(fb.core.util.Path.Empty); - - // If we don't have cached server data, see if we can get it from this SyncPoint. - if (serverCache == null && syncPoint != null) { - serverCache = syncPoint.getCompleteServerCache(fb.core.util.Path.Empty); - } - - var events = []; - var self = this; - syncPointTree.children.inorderTraversal(function(childName, childTree) { - var childServerCache = serverCache ? serverCache.getImmediateChild(childName) : null; - var childWritesCache = writesCache.child(childName); - var childOperation = operation.operationForChild(childName); - if (childOperation) { - events = events.concat( - self.applyOperationDescendantsHelper_(childOperation, childTree, childServerCache, childWritesCache)); - } - }); - - if (syncPoint) { - events = events.concat(syncPoint.applyOperation(operation, writesCache, serverCache)); - } - - return events; -}; diff --git a/src/database/js-client/core/WriteTree.js b/src/database/js-client/core/WriteTree.js deleted file mode 100644 index 215539375c2..00000000000 --- a/src/database/js-client/core/WriteTree.js +++ /dev/null @@ -1,645 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.WriteTree'); -goog.require('fb.core.CompoundWrite'); -goog.require('fb.core.util'); -goog.require('fb.core.view.CacheNode'); - -/** - * Defines a single user-initiated write operation. May be the result of a set(), transaction(), or update() call. In - * the case of a set() or transaction, snap wil be non-null. In the case of an update(), children will be non-null. - * - * @typedef {{ - * writeId: number, - * path: !fb.core.util.Path, - * snap: ?fb.core.snap.Node, - * children: ?Object., - * visible: boolean - * }} - */ -fb.core.WriteRecord; - -/** - * WriteTree tracks all pending user-initiated writes and has methods to calculate the result of merging them - * with underlying server data (to create "event cache" data). Pending writes are added with addOverwrite() - * and addMerge(), and removed with removeWrite(). - * - * @constructor - */ -fb.core.WriteTree = function() { - /** - * A tree tracking the result of applying all visible writes. This does not include transactions with - * applyLocally=false or writes that are completely shadowed by other writes. - * - * @type {!fb.core.CompoundWrite} - * @private - */ - this.visibleWrites_ = /** @type {!fb.core.CompoundWrite} */ - (fb.core.CompoundWrite.Empty); - - /** - * A list of all pending writes, regardless of visibility and shadowed-ness. Used to calculate arbitrary - * sets of the changed data, such as hidden writes (from transactions) or changes with certain writes excluded (also - * used by transactions). - * - * @type {!Array.} - * @private - */ - this.allWrites_ = []; - this.lastWriteId_ = -1; -}; - -/** - * Create a new WriteTreeRef for the given path. For use with a new sync point at the given path. - * - * @param {!fb.core.util.Path} path - * @return {!fb.core.WriteTreeRef} - */ -fb.core.WriteTree.prototype.childWrites = function(path) { - return new fb.core.WriteTreeRef(path, this); -}; - -/** - * Record a new overwrite from user code. - * - * @param {!fb.core.util.Path} path - * @param {!fb.core.snap.Node} snap - * @param {!number} writeId - * @param {boolean=} visible This is set to false by some transactions. It should be excluded from event caches - */ -fb.core.WriteTree.prototype.addOverwrite = function(path, snap, writeId, visible) { - fb.core.util.assert(writeId > this.lastWriteId_, 'Stacking an older write on top of newer ones'); - if (!goog.isDef(visible)) { - visible = true; - } - this.allWrites_.push({path: path, snap: snap, writeId: writeId, visible: visible}); - - if (visible) { - this.visibleWrites_ = this.visibleWrites_.addWrite(path, snap); - } - this.lastWriteId_ = writeId; -}; - -/** - * Record a new merge from user code. - * - * @param {!fb.core.util.Path} path - * @param {!Object.} changedChildren - * @param {!number} writeId - */ -fb.core.WriteTree.prototype.addMerge = function(path, changedChildren, writeId) { - fb.core.util.assert(writeId > this.lastWriteId_, 'Stacking an older merge on top of newer ones'); - this.allWrites_.push({path: path, children: changedChildren, writeId: writeId, visible: true}); - - this.visibleWrites_ = this.visibleWrites_.addWrites(path, changedChildren); - this.lastWriteId_ = writeId; -}; - - -/** - * @param {!number} writeId - * @return {?fb.core.WriteRecord} - */ -fb.core.WriteTree.prototype.getWrite = function(writeId) { - for (var i = 0; i < this.allWrites_.length; i++) { - var record = this.allWrites_[i]; - if (record.writeId === writeId) { - return record; - } - } - return null; -}; - - -/** - * Remove a write (either an overwrite or merge) that has been successfully acknowledge by the server. Recalculates - * the tree if necessary. We return true if it may have been visible, meaning views need to reevaluate. - * - * @param {!number} writeId - * @return {boolean} true if the write may have been visible (meaning we'll need to reevaluate / raise - * events as a result). - */ -fb.core.WriteTree.prototype.removeWrite = function(writeId) { - // Note: disabling this check. It could be a transaction that preempted another transaction, and thus was applied - // out of order. - //var validClear = revert || this.allWrites_.length === 0 || writeId <= this.allWrites_[0].writeId; - //fb.core.util.assert(validClear, "Either we don't have this write, or it's the first one in the queue"); - - var idx = goog.array.findIndex(this.allWrites_, function(s) { return s.writeId === writeId; }); - fb.core.util.assert(idx >= 0, 'removeWrite called with nonexistent writeId.'); - var writeToRemove = this.allWrites_[idx]; - this.allWrites_.splice(idx, 1); - - var removedWriteWasVisible = writeToRemove.visible; - var removedWriteOverlapsWithOtherWrites = false; - - var i = this.allWrites_.length - 1; - - while (removedWriteWasVisible && i >= 0) { - var currentWrite = this.allWrites_[i]; - if (currentWrite.visible) { - if (i >= idx && this.recordContainsPath_(currentWrite, writeToRemove.path)) { - // The removed write was completely shadowed by a subsequent write. - removedWriteWasVisible = false; - } else if (writeToRemove.path.contains(currentWrite.path)) { - // Either we're covering some writes or they're covering part of us (depending on which came first). - removedWriteOverlapsWithOtherWrites = true; - } - } - i--; - } - - if (!removedWriteWasVisible) { - return false; - } else if (removedWriteOverlapsWithOtherWrites) { - // There's some shadowing going on. Just rebuild the visible writes from scratch. - this.resetTree_(); - return true; - } else { - // There's no shadowing. We can safely just remove the write(s) from visibleWrites. - if (writeToRemove.snap) { - this.visibleWrites_ = this.visibleWrites_.removeWrite(writeToRemove.path); - } else { - var children = writeToRemove.children; - var self = this; - goog.object.forEach(children, function(childSnap, childName) { - self.visibleWrites_ = self.visibleWrites_.removeWrite(writeToRemove.path.child(childName)); - }); - } - return true; - } -}; - -/** - * Return a complete snapshot for the given path if there's visible write data at that path, else null. - * No server data is considered. - * - * @param {!fb.core.util.Path} path - * @return {?fb.core.snap.Node} - */ -fb.core.WriteTree.prototype.getCompleteWriteData = function(path) { - return this.visibleWrites_.getCompleteNode(path); -}; - -/** - * Given optional, underlying server data, and an optional set of constraints (exclude some sets, include hidden - * writes), attempt to calculate a complete snapshot for the given path - * - * @param {!fb.core.util.Path} treePath - * @param {?fb.core.snap.Node} completeServerCache - * @param {Array.=} writeIdsToExclude An optional set to be excluded - * @param {boolean=} includeHiddenWrites Defaults to false, whether or not to layer on writes with visible set to false - * @return {?fb.core.snap.Node} - */ -fb.core.WriteTree.prototype.calcCompleteEventCache = function(treePath, completeServerCache, writeIdsToExclude, - includeHiddenWrites) { - if (!writeIdsToExclude && !includeHiddenWrites) { - var shadowingNode = this.visibleWrites_.getCompleteNode(treePath); - if (shadowingNode != null) { - return shadowingNode; - } else { - var subMerge = this.visibleWrites_.childCompoundWrite(treePath); - if (subMerge.isEmpty()) { - return completeServerCache; - } else if (completeServerCache == null && !subMerge.hasCompleteWrite(fb.core.util.Path.Empty)) { - // We wouldn't have a complete snapshot, since there's no underlying data and no complete shadow - return null; - } else { - var layeredCache = completeServerCache || fb.core.snap.EMPTY_NODE; - return subMerge.apply(layeredCache); - } - } - } else { - var merge = this.visibleWrites_.childCompoundWrite(treePath); - if (!includeHiddenWrites && merge.isEmpty()) { - return completeServerCache; - } else { - // If the server cache is null, and we don't have a complete cache, we need to return null - if (!includeHiddenWrites && completeServerCache == null && !merge.hasCompleteWrite(fb.core.util.Path.Empty)) { - return null; - } else { - var filter = function(write) { - return (write.visible || includeHiddenWrites) && - (!writeIdsToExclude || !goog.array.contains(writeIdsToExclude, write.writeId)) && - (write.path.contains(treePath) || treePath.contains(write.path)); - }; - var mergeAtPath = fb.core.WriteTree.layerTree_(this.allWrites_, filter, treePath); - layeredCache = completeServerCache || fb.core.snap.EMPTY_NODE; - return mergeAtPath.apply(layeredCache); - } - } - } -}; - -/** - * With optional, underlying server data, attempt to return a children node of children that we have complete data for. - * Used when creating new views, to pre-fill their complete event children snapshot. - * - * @param {!fb.core.util.Path} treePath - * @param {?fb.core.snap.ChildrenNode} completeServerChildren - * @return {!fb.core.snap.ChildrenNode} - */ -fb.core.WriteTree.prototype.calcCompleteEventChildren = function(treePath, completeServerChildren) { - var completeChildren = fb.core.snap.EMPTY_NODE; - var topLevelSet = this.visibleWrites_.getCompleteNode(treePath); - if (topLevelSet) { - if (!topLevelSet.isLeafNode()) { - // we're shadowing everything. Return the children. - topLevelSet.forEachChild(fb.core.snap.PriorityIndex, function(childName, childSnap) { - completeChildren = completeChildren.updateImmediateChild(childName, childSnap); - }); - } - return completeChildren; - } else if (completeServerChildren) { - // Layer any children we have on top of this - // We know we don't have a top-level set, so just enumerate existing children - var merge = this.visibleWrites_.childCompoundWrite(treePath); - completeServerChildren.forEachChild(fb.core.snap.PriorityIndex, function(childName, childNode) { - var node = merge.childCompoundWrite(new fb.core.util.Path(childName)).apply(childNode); - completeChildren = completeChildren.updateImmediateChild(childName, node); - }); - // Add any complete children we have from the set - goog.array.forEach(merge.getCompleteChildren(), function(namedNode) { - completeChildren = completeChildren.updateImmediateChild(namedNode.name, namedNode.node); - }); - return completeChildren; - } else { - // We don't have anything to layer on top of. Layer on any children we have - // Note that we can return an empty snap if we have a defined delete - merge = this.visibleWrites_.childCompoundWrite(treePath); - goog.array.forEach(merge.getCompleteChildren(), function(namedNode) { - completeChildren = completeChildren.updateImmediateChild(namedNode.name, namedNode.node); - }); - return completeChildren; - } -}; - -/** - * Given that the underlying server data has updated, determine what, if anything, needs to be - * applied to the event cache. - * - * Possibilities: - * - * 1. No writes are shadowing. Events should be raised, the snap to be applied comes from the server data - * - * 2. Some write is completely shadowing. No events to be raised - * - * 3. Is partially shadowed. Events - * - * Either existingEventSnap or existingServerSnap must exist - * - * @param {!fb.core.util.Path} treePath - * @param {!fb.core.util.Path} childPath - * @param {?fb.core.snap.Node} existingEventSnap - * @param {?fb.core.snap.Node} existingServerSnap - * @return {?fb.core.snap.Node} - */ -fb.core.WriteTree.prototype.calcEventCacheAfterServerOverwrite = function(treePath, childPath, existingEventSnap, - existingServerSnap) { - fb.core.util.assert(existingEventSnap || existingServerSnap, - 'Either existingEventSnap or existingServerSnap must exist'); - var path = treePath.child(childPath); - if (this.visibleWrites_.hasCompleteWrite(path)) { - // At this point we can probably guarantee that we're in case 2, meaning no events - // May need to check visibility while doing the findRootMostValueAndPath call - return null; - } else { - // No complete shadowing. We're either partially shadowing or not shadowing at all. - var childMerge = this.visibleWrites_.childCompoundWrite(path); - if (childMerge.isEmpty()) { - // We're not shadowing at all. Case 1 - return existingServerSnap.getChild(childPath); - } else { - // This could be more efficient if the serverNode + updates doesn't change the eventSnap - // However this is tricky to find out, since user updates don't necessary change the server - // snap, e.g. priority updates on empty nodes, or deep deletes. Another special case is if the server - // adds nodes, but doesn't change any existing writes. It is therefore not enough to - // only check if the updates change the serverNode. - // Maybe check if the merge tree contains these special cases and only do a full overwrite in that case? - return childMerge.apply(existingServerSnap.getChild(childPath)); - } - } -}; - -/** - * Returns a complete child for a given server snap after applying all user writes or null if there is no - * complete child for this ChildKey. - * - * @param {!fb.core.util.Path} treePath - * @param {!string} childKey - * @param {!fb.core.view.CacheNode} existingServerSnap - * @return {?fb.core.snap.Node} - */ -fb.core.WriteTree.prototype.calcCompleteChild = function(treePath, childKey, existingServerSnap) { - var path = treePath.child(childKey); - var shadowingNode = this.visibleWrites_.getCompleteNode(path); - if (shadowingNode != null) { - return shadowingNode; - } else { - if (existingServerSnap.isCompleteForChild(childKey)) { - var childMerge = this.visibleWrites_.childCompoundWrite(path); - return childMerge.apply(existingServerSnap.getNode().getImmediateChild(childKey)); - } else { - return null; - } - } -}; - -/** - * Returns a node if there is a complete overwrite for this path. More specifically, if there is a write at - * a higher path, this will return the child of that write relative to the write and this path. - * Returns null if there is no write at this path. - * - * @param {!fb.core.util.Path} path - * @return {?fb.core.snap.Node} - */ -fb.core.WriteTree.prototype.shadowingWrite = function(path) { - return this.visibleWrites_.getCompleteNode(path); -}; - -/** - * This method is used when processing child remove events on a query. If we can, we pull in children that were outside - * the window, but may now be in the window. - * - * @param {!fb.core.util.Path} treePath - * @param {?fb.core.snap.Node} completeServerData - * @param {!fb.core.snap.NamedNode} startPost - * @param {!number} count - * @param {boolean} reverse - * @param {!fb.core.snap.Index} index - * @return {!Array.} - */ -fb.core.WriteTree.prototype.calcIndexedSlice = function(treePath, completeServerData, startPost, count, reverse, - index) { - var toIterate; - var merge = this.visibleWrites_.childCompoundWrite(treePath); - var shadowingNode = merge.getCompleteNode(fb.core.util.Path.Empty); - if (shadowingNode != null) { - toIterate = shadowingNode; - } else if (completeServerData != null) { - toIterate = merge.apply(completeServerData); - } else { - // no children to iterate on - return []; - } - toIterate = toIterate.withIndex(index); - if (!toIterate.isEmpty() && !toIterate.isLeafNode()) { - var nodes = []; - var cmp = index.getCompare(); - var iter = reverse ? toIterate.getReverseIteratorFrom(startPost, index) : - toIterate.getIteratorFrom(startPost, index); - var next = iter.getNext(); - while (next && nodes.length < count) { - if (cmp(next, startPost) !== 0) { - nodes.push(next); - } - next = iter.getNext(); - } - return nodes; - } else { - return []; - } -}; - -/** - * @param {!fb.core.WriteRecord} writeRecord - * @param {!fb.core.util.Path} path - * @return {boolean} - * @private - */ -fb.core.WriteTree.prototype.recordContainsPath_ = function(writeRecord, path) { - if (writeRecord.snap) { - return writeRecord.path.contains(path); - } else { - // findKey can return undefined, so use !! to coerce to boolean - return !!goog.object.findKey(writeRecord.children, function(childSnap, childName) { - return writeRecord.path.child(childName).contains(path); - }); - } -}; - -/** - * Re-layer the writes and merges into a tree so we can efficiently calculate event snapshots - * @private - */ -fb.core.WriteTree.prototype.resetTree_ = function() { - this.visibleWrites_ = fb.core.WriteTree.layerTree_(this.allWrites_, fb.core.WriteTree.DefaultFilter_, - fb.core.util.Path.Empty); - if (this.allWrites_.length > 0) { - this.lastWriteId_ = this.allWrites_[this.allWrites_.length - 1].writeId; - } else { - this.lastWriteId_ = -1; - } -}; - -/** - * The default filter used when constructing the tree. Keep everything that's visible. - * - * @param {!fb.core.WriteRecord} write - * @return {boolean} - * @private - * @const - */ -fb.core.WriteTree.DefaultFilter_ = function(write) { return write.visible; }; - -/** - * Static method. Given an array of WriteRecords, a filter for which ones to include, and a path, construct the tree of - * event data at that path. - * - * @param {!Array.} writes - * @param {!function(!fb.core.WriteRecord):boolean} filter - * @param {!fb.core.util.Path} treeRoot - * @return {!fb.core.CompoundWrite} - * @private - */ -fb.core.WriteTree.layerTree_ = function(writes, filter, treeRoot) { - var compoundWrite = fb.core.CompoundWrite.Empty; - for (var i = 0; i < writes.length; ++i) { - var write = writes[i]; - // Theory, a later set will either: - // a) abort a relevant transaction, so no need to worry about excluding it from calculating that transaction - // b) not be relevant to a transaction (separate branch), so again will not affect the data for that transaction - if (filter(write)) { - var writePath = write.path; - var relativePath; - if (write.snap) { - if (treeRoot.contains(writePath)) { - relativePath = fb.core.util.Path.relativePath(treeRoot, writePath); - compoundWrite = compoundWrite.addWrite(relativePath, write.snap); - } else if (writePath.contains(treeRoot)) { - relativePath = fb.core.util.Path.relativePath(writePath, treeRoot); - compoundWrite = compoundWrite.addWrite(fb.core.util.Path.Empty, write.snap.getChild(relativePath)); - } else { - // There is no overlap between root path and write path, ignore write - } - } else if (write.children) { - if (treeRoot.contains(writePath)) { - relativePath = fb.core.util.Path.relativePath(treeRoot, writePath); - compoundWrite = compoundWrite.addWrites(relativePath, write.children); - } else if (writePath.contains(treeRoot)) { - relativePath = fb.core.util.Path.relativePath(writePath, treeRoot); - if (relativePath.isEmpty()) { - compoundWrite = compoundWrite.addWrites(fb.core.util.Path.Empty, write.children); - } else { - var child = fb.util.obj.get(write.children, relativePath.getFront()); - if (child) { - // There exists a child in this node that matches the root path - var deepNode = child.getChild(relativePath.popFront()); - compoundWrite = compoundWrite.addWrite(fb.core.util.Path.Empty, deepNode); - } - } - } else { - // There is no overlap between root path and write path, ignore write - } - } else { - throw fb.core.util.assertionError('WriteRecord should have .snap or .children'); - } - } - } - return compoundWrite; -}; - -/** - * A WriteTreeRef wraps a WriteTree and a path, for convenient access to a particular subtree. All of the methods - * just proxy to the underlying WriteTree. - * - * @param {!fb.core.util.Path} path - * @param {!fb.core.WriteTree} writeTree - * @constructor - */ -fb.core.WriteTreeRef = function(path, writeTree) { - /** - * The path to this particular write tree ref. Used for calling methods on writeTree_ while exposing a simpler - * interface to callers. - * - * @type {!fb.core.util.Path} - * @private - * @const - */ - this.treePath_ = path; - - /** - * * A reference to the actual tree of write data. All methods are pass-through to the tree, but with the appropriate - * path prefixed. - * - * This lets us make cheap references to points in the tree for sync points without having to copy and maintain all of - * the data. - * - * @type {!fb.core.WriteTree} - * @private - * @const - */ - this.writeTree_ = writeTree; -}; - -/** - * If possible, returns a complete event cache, using the underlying server data if possible. In addition, can be used - * to get a cache that includes hidden writes, and excludes arbitrary writes. Note that customizing the returned node - * can lead to a more expensive calculation. - * - * @param {?fb.core.snap.Node} completeServerCache - * @param {Array.=} writeIdsToExclude Optional writes to exclude. - * @param {boolean=} includeHiddenWrites Defaults to false, whether or not to layer on writes with visible set to false - * @return {?fb.core.snap.Node} - */ -fb.core.WriteTreeRef.prototype.calcCompleteEventCache = function(completeServerCache, writeIdsToExclude, - includeHiddenWrites) { - return this.writeTree_.calcCompleteEventCache(this.treePath_, completeServerCache, writeIdsToExclude, - includeHiddenWrites); -}; - -/** - * If possible, returns a children node containing all of the complete children we have data for. The returned data is a - * mix of the given server data and write data. - * - * @param {?fb.core.snap.ChildrenNode} completeServerChildren - * @return {!fb.core.snap.ChildrenNode} - */ -fb.core.WriteTreeRef.prototype.calcCompleteEventChildren = function(completeServerChildren) { - return this.writeTree_.calcCompleteEventChildren(this.treePath_, completeServerChildren); -}; - -/** - * Given that either the underlying server data has updated or the outstanding writes have updated, determine what, - * if anything, needs to be applied to the event cache. - * - * Possibilities: - * - * 1. No writes are shadowing. Events should be raised, the snap to be applied comes from the server data - * - * 2. Some write is completely shadowing. No events to be raised - * - * 3. Is partially shadowed. Events should be raised - * - * Either existingEventSnap or existingServerSnap must exist, this is validated via an assert - * - * @param {!fb.core.util.Path} path - * @param {?fb.core.snap.Node} existingEventSnap - * @param {?fb.core.snap.Node} existingServerSnap - * @return {?fb.core.snap.Node} - */ -fb.core.WriteTreeRef.prototype.calcEventCacheAfterServerOverwrite = function(path, existingEventSnap, existingServerSnap) { - return this.writeTree_.calcEventCacheAfterServerOverwrite(this.treePath_, path, existingEventSnap, existingServerSnap); -}; - -/** - * Returns a node if there is a complete overwrite for this path. More specifically, if there is a write at - * a higher path, this will return the child of that write relative to the write and this path. - * Returns null if there is no write at this path. - * - * @param {!fb.core.util.Path} path - * @return {?fb.core.snap.Node} - */ -fb.core.WriteTreeRef.prototype.shadowingWrite = function(path) { - return this.writeTree_.shadowingWrite(this.treePath_.child(path)); -}; - -/** - * This method is used when processing child remove events on a query. If we can, we pull in children that were outside - * the window, but may now be in the window - * - * @param {?fb.core.snap.Node} completeServerData - * @param {!fb.core.snap.NamedNode} startPost - * @param {!number} count - * @param {boolean} reverse - * @param {!fb.core.snap.Index} index - * @return {!Array.} - */ -fb.core.WriteTreeRef.prototype.calcIndexedSlice = function(completeServerData, startPost, count, reverse, index) { - return this.writeTree_.calcIndexedSlice(this.treePath_, completeServerData, startPost, count, reverse, index); -}; - -/** - * Returns a complete child for a given server snap after applying all user writes or null if there is no - * complete child for this ChildKey. - * - * @param {!string} childKey - * @param {!fb.core.view.CacheNode} existingServerCache - * @return {?fb.core.snap.Node} - */ -fb.core.WriteTreeRef.prototype.calcCompleteChild = function(childKey, existingServerCache) { - return this.writeTree_.calcCompleteChild(this.treePath_, childKey, existingServerCache); -}; - -/** - * Return a WriteTreeRef for a child. - * - * @param {string} childName - * @return {!fb.core.WriteTreeRef} - */ -fb.core.WriteTreeRef.prototype.child = function(childName) { - return new fb.core.WriteTreeRef(this.treePath_.child(childName), this.writeTree_); -}; diff --git a/src/database/js-client/core/operation/AckUserWrite.js b/src/database/js-client/core/operation/AckUserWrite.js deleted file mode 100644 index 239e35c2f88..00000000000 --- a/src/database/js-client/core/operation/AckUserWrite.js +++ /dev/null @@ -1,75 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.operation.AckUserWrite'); -goog.require('fb.core.util.ImmutableTree'); - -/** - * - * @param {!fb.core.util.Path} path - * @param {!fb.core.util.ImmutableTree} affectedTree - * @param {!boolean} revert - * @constructor - * @implements {fb.core.Operation} - */ -fb.core.operation.AckUserWrite = function(path, affectedTree, revert) { - /** @inheritDoc */ - this.type = fb.core.OperationType.ACK_USER_WRITE; - - /** @inheritDoc */ - this.source = fb.core.OperationSource.User; - - /** @inheritDoc */ - this.path = path; - - /** - * A tree containing true for each affected path. Affected paths can't overlap. - * @type {!fb.core.util.ImmutableTree.} - */ - this.affectedTree = affectedTree; - - /** - * @type {boolean} - */ - this.revert = revert; -}; - -/** - * @inheritDoc - */ -fb.core.operation.AckUserWrite.prototype.operationForChild = function(childName) { - if (!this.path.isEmpty()) { - fb.core.util.assert(this.path.getFront() === childName, 'operationForChild called for unrelated child.'); - return new fb.core.operation.AckUserWrite(this.path.popFront(), this.affectedTree, this.revert); - } else if (this.affectedTree.value != null) { - fb.core.util.assert(this.affectedTree.children.isEmpty(), - 'affectedTree should not have overlapping affected paths.'); - // All child locations are affected as well; just return same operation. - return this; - } else { - var childTree = this.affectedTree.subtree(new fb.core.util.Path(childName)); - return new fb.core.operation.AckUserWrite(fb.core.util.Path.Empty, childTree, this.revert); - } -}; - -if (goog.DEBUG) { - /** - * @inheritDoc - */ - fb.core.operation.AckUserWrite.prototype.toString = function() { - return 'Operation(' + this.path + ': ' + this.source.toString() + ' ack write revert=' + this.revert + - ' affectedTree=' + this.affectedTree + ')'; - }; -} diff --git a/src/database/js-client/core/operation/ListenComplete.js b/src/database/js-client/core/operation/ListenComplete.js deleted file mode 100644 index 7b59e1530f0..00000000000 --- a/src/database/js-client/core/operation/ListenComplete.js +++ /dev/null @@ -1,53 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.operation.ListenComplete'); - -/** - * @param {!fb.core.OperationSource} source - * @param {!fb.core.util.Path} path - * @constructor - * @implements {fb.core.Operation} - */ -fb.core.operation.ListenComplete = function(source, path) { - /** @inheritDoc */ - this.type = fb.core.OperationType.LISTEN_COMPLETE; - - /** @inheritDoc */ - this.source = source; - - /** @inheritDoc */ - this.path = path; -}; - -/** - * @inheritDoc - */ -fb.core.operation.ListenComplete.prototype.operationForChild = function(childName) { - if (this.path.isEmpty()) { - return new fb.core.operation.ListenComplete(this.source, fb.core.util.Path.Empty); - } else { - return new fb.core.operation.ListenComplete(this.source, this.path.popFront()); - } -}; - -if (goog.DEBUG) { - /** - * @inheritDoc - */ - fb.core.operation.ListenComplete.prototype.toString = function() { - return 'Operation(' + this.path + ': ' + this.source.toString() + ' listen_complete)'; - }; -} diff --git a/src/database/js-client/core/operation/Merge.js b/src/database/js-client/core/operation/Merge.js deleted file mode 100644 index 2f54a4ab22b..00000000000 --- a/src/database/js-client/core/operation/Merge.js +++ /dev/null @@ -1,72 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.operation.Merge'); -goog.require('fb.core.util'); - -/** - * @param {!fb.core.OperationSource} source - * @param {!fb.core.util.Path} path - * @param {!fb.core.util.ImmutableTree.} children - * @constructor - * @implements {fb.core.Operation} - */ -fb.core.operation.Merge = function(source, path, children) { - /** @inheritDoc */ - this.type = fb.core.OperationType.MERGE; - - /** @inheritDoc */ - this.source = source; - - /** @inheritDoc */ - this.path = path; - - /** - * @type {!fb.core.util.ImmutableTree.} - */ - this.children = children; -}; - -/** - * @inheritDoc - */ -fb.core.operation.Merge.prototype.operationForChild = function(childName) { - if (this.path.isEmpty()) { - var childTree = this.children.subtree(new fb.core.util.Path(childName)); - if (childTree.isEmpty()) { - // This child is unaffected - return null; - } else if (childTree.value) { - // We have a snapshot for the child in question. This becomes an overwrite of the child. - return new fb.core.operation.Overwrite(this.source, fb.core.util.Path.Empty, childTree.value); - } else { - // This is a merge at a deeper level - return new fb.core.operation.Merge(this.source, fb.core.util.Path.Empty, childTree); - } - } else { - fb.core.util.assert(this.path.getFront() === childName, - 'Can\'t get a merge for a child not on the path of the operation'); - return new fb.core.operation.Merge(this.source, this.path.popFront(), this.children); - } -}; - -if (goog.DEBUG) { - /** - * @inheritDoc - */ - fb.core.operation.Merge.prototype.toString = function() { - return 'Operation(' + this.path + ': ' + this.source.toString() + ' merge: ' + this.children.toString() + ')'; - }; -} diff --git a/src/database/js-client/core/operation/Operation.js b/src/database/js-client/core/operation/Operation.js deleted file mode 100644 index e8a8431dcc6..00000000000 --- a/src/database/js-client/core/operation/Operation.js +++ /dev/null @@ -1,105 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.Operation'); -goog.require('fb.core.operation.AckUserWrite'); -goog.require('fb.core.operation.Merge'); -goog.require('fb.core.operation.Overwrite'); -goog.require('fb.core.operation.ListenComplete'); -goog.require('fb.core.util'); - -/** - * - * @enum - */ -fb.core.OperationType = { - OVERWRITE: 0, - MERGE: 1, - ACK_USER_WRITE: 2, - LISTEN_COMPLETE: 3 -}; - -/** - * @interface - */ -fb.core.Operation = function() { }; - -/** - * @type {!fb.core.OperationSource} - */ -fb.core.Operation.prototype.source; - -/** - * @type {!fb.core.OperationType} - */ -fb.core.Operation.prototype.type; - -/** - * @type {!fb.core.util.Path} - */ -fb.core.Operation.prototype.path; - -/** - * @param {string} childName - * @return {?fb.core.Operation} - */ -fb.core.Operation.prototype.operationForChild = goog.abstractMethod; - - -/** - * @param {boolean} fromUser - * @param {boolean} fromServer - * @param {?string} queryId - * @param {boolean} tagged - * @constructor - */ -fb.core.OperationSource = function(fromUser, fromServer, queryId, tagged) { - this.fromUser = fromUser; - this.fromServer = fromServer; - this.queryId = queryId; - this.tagged = tagged; - fb.core.util.assert(!tagged || fromServer, 'Tagged queries must be from server.'); -}; - -/** - * @const - * @type {!fb.core.OperationSource} - */ -fb.core.OperationSource.User = new fb.core.OperationSource(/*fromUser=*/true, false, null, /*tagged=*/false); - -/** - * @const - * @type {!fb.core.OperationSource} - */ -fb.core.OperationSource.Server = new fb.core.OperationSource(false, /*fromServer=*/true, null, /*tagged=*/false); - -/** - * @param {string} queryId - * @return {!fb.core.OperationSource} - */ -fb.core.OperationSource.forServerTaggedQuery = function(queryId) { - return new fb.core.OperationSource(false, /*fromServer=*/true, queryId, /*tagged=*/true); -}; - -if (goog.DEBUG) { - /** - * @inheritDoc - */ - fb.core.OperationSource.prototype.toString = function() { - return this.fromUser ? 'user' : - this.tagged ? 'server(queryID=' + this.queryId + ')' : - 'server'; - }; -} diff --git a/src/database/js-client/core/operation/Overwrite.js b/src/database/js-client/core/operation/Overwrite.js deleted file mode 100644 index 0dcd6edb052..00000000000 --- a/src/database/js-client/core/operation/Overwrite.js +++ /dev/null @@ -1,60 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.operation.Overwrite'); - -/** - * @param {!fb.core.OperationSource} source - * @param {!fb.core.util.Path} path - * @param {!fb.core.snap.Node} snap - * @constructor - * @implements {fb.core.Operation} - */ -fb.core.operation.Overwrite = function(source, path, snap) { - /** @inheritDoc */ - this.type = fb.core.OperationType.OVERWRITE; - - /** @inheritDoc */ - this.source = source; - - /** @inheritDoc */ - this.path = path; - - /** - * @type {!fb.core.snap.Node} - */ - this.snap = snap; -}; - -/** - * @inheritDoc - */ -fb.core.operation.Overwrite.prototype.operationForChild = function(childName) { - if (this.path.isEmpty()) { - return new fb.core.operation.Overwrite(this.source, fb.core.util.Path.Empty, - this.snap.getImmediateChild(childName)); - } else { - return new fb.core.operation.Overwrite(this.source, this.path.popFront(), this.snap); - } -}; - -if (goog.DEBUG) { - /** - * @inheritDoc - */ - fb.core.operation.Overwrite.prototype.toString = function() { - return 'Operation(' + this.path + ': ' + this.source.toString() + ' overwrite: ' + this.snap.toString() + ')'; - }; -} diff --git a/src/database/js-client/core/registerService.js b/src/database/js-client/core/registerService.js deleted file mode 100644 index 13f06e9b08c..00000000000 --- a/src/database/js-client/core/registerService.js +++ /dev/null @@ -1,58 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.registerService'); -goog.provide('fb.core.exportPropGetter'); - -goog.require('Firebase'); -goog.require('fb.api.Database'); -goog.require('fb.api.INTERNAL'); -goog.require('fb.api.Query'); -goog.require('fb.api.TEST_ACCESS'); -goog.require('fb.constants'); -goog.require('fb.core.RepoManager'); -goog.require('fb.core.util.enableLogging'); - -if (typeof firebase === 'undefined') { - throw new Error("Cannot install Firebase Database - " + - "be sure to load firebase-app.js first."); -} - -// Register the Database Service with the 'firebase' namespace. -try { - var databaseNamespace = firebase.INTERNAL.registerService( - 'database', - function(app) { - return fb.core.RepoManager.getInstance().databaseFromApp(app); - }, - // firebase.database namespace properties - { - 'Reference': Firebase, - 'Query': fb.api.Query, - 'Database': fb.api.Database, - - 'enableLogging': fb.core.util.enableLogging, - 'INTERNAL': fb.api.INTERNAL, - 'TEST_ACCESS': fb.api.TEST_ACCESS, - - 'ServerValue': fb.api.Database.ServerValue, - } - ); - if (fb.login.util.environment.isNodeSdk()) { - module.exports = databaseNamespace; - } -} catch (e) { - fb.core.util.fatal("Failed to register the Firebase Database Service (" + e + ")"); -} diff --git a/src/database/js-client/core/snap/ChildrenNode.js b/src/database/js-client/core/snap/ChildrenNode.js deleted file mode 100644 index 7e8b9788937..00000000000 --- a/src/database/js-client/core/snap/ChildrenNode.js +++ /dev/null @@ -1,476 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.snap.ChildrenNode'); -goog.require('fb.core.snap.IndexMap'); -goog.require('fb.core.snap.LeafNode'); -goog.require('fb.core.snap.NamedNode'); -goog.require('fb.core.snap.Node'); -goog.require('fb.core.snap.PriorityIndex'); -goog.require('fb.core.snap.comparators'); -goog.require('fb.core.util'); -goog.require('fb.core.util.SortedMap'); - -// TODO: For memory savings, don't store priorityNode_ if it's empty. - -/** - * ChildrenNode is a class for storing internal nodes in a DataSnapshot - * (i.e. nodes with children). It implements Node and stores the - * list of children in the children property, sorted by child name. - * - * @constructor - * @implements {fb.core.snap.Node} - * @param {!fb.core.util.SortedMap.} children List of children - * of this node.. - * @param {?fb.core.snap.Node} priorityNode The priority of this node (as a snapshot node). - * @param {!fb.core.snap.IndexMap} indexMap - */ -fb.core.snap.ChildrenNode = function(children, priorityNode, indexMap) { - /** - * @private - * @const - * @type {!fb.core.util.SortedMap.} - */ - this.children_ = children; - - /** - * Note: The only reason we allow null priority is to for EMPTY_NODE, since we can't use - * EMPTY_NODE as the priority of EMPTY_NODE. We might want to consider making EMPTY_NODE its own - * class instead of an empty ChildrenNode. - * - * @private - * @const - * @type {?fb.core.snap.Node} - */ - this.priorityNode_ = priorityNode; - if (this.priorityNode_) { - fb.core.snap.validatePriorityNode(this.priorityNode_); - } - - if (children.isEmpty()) { - fb.core.util.assert(!this.priorityNode_ || this.priorityNode_.isEmpty(), 'An empty node cannot have a priority'); - } - - /** - * - * @type {!fb.core.snap.IndexMap} - * @private - */ - this.indexMap_ = indexMap; - - /** - * - * @type {?string} - * @private - */ - this.lazyHash_ = null; -}; - - -/** @inheritDoc */ -fb.core.snap.ChildrenNode.prototype.isLeafNode = function() { - return false; -}; - - -/** @inheritDoc */ -fb.core.snap.ChildrenNode.prototype.getPriority = function() { - return this.priorityNode_ || fb.core.snap.EMPTY_NODE; -}; - - -/** @inheritDoc */ -fb.core.snap.ChildrenNode.prototype.updatePriority = function(newPriorityNode) { - if (this.children_.isEmpty()) { - // Don't allow priorities on empty nodes - return this; - } else { - return new fb.core.snap.ChildrenNode(this.children_, newPriorityNode, this.indexMap_); - } -}; - -/** @inheritDoc */ -fb.core.snap.ChildrenNode.prototype.getImmediateChild = function(childName) { - // Hack to treat priority as a regular child - if (childName === '.priority') { - return this.getPriority(); - } else { - var child = this.children_.get(childName); - return child === null ? fb.core.snap.EMPTY_NODE : child; - } -}; - - -/** @inheritDoc */ -fb.core.snap.ChildrenNode.prototype.getChild = function(path) { - var front = path.getFront(); - if (front === null) - return this; - - return this.getImmediateChild(front).getChild(path.popFront()); -}; - -/** @inheritDoc */ -fb.core.snap.ChildrenNode.prototype.hasChild = function(childName) { - return this.children_.get(childName) !== null; -}; - -/** @inheritDoc */ -fb.core.snap.ChildrenNode.prototype.updateImmediateChild = function(childName, newChildNode) { - fb.core.util.assert(newChildNode, 'We should always be passing snapshot nodes'); - if (childName === '.priority') { - return this.updatePriority(newChildNode); - } else { - var namedNode = new fb.core.snap.NamedNode(childName, newChildNode); - var newChildren, newIndexMap, newPriority; - if (newChildNode.isEmpty()) { - newChildren = this.children_.remove(childName); - newIndexMap = this.indexMap_.removeFromIndexes(namedNode, this.children_ - ); - } else { - newChildren = this.children_.insert(childName, newChildNode); - newIndexMap = this.indexMap_.addToIndexes(namedNode, this.children_); - } - - newPriority = newChildren.isEmpty() ? fb.core.snap.EMPTY_NODE : this.priorityNode_; - return new fb.core.snap.ChildrenNode(newChildren, newPriority, newIndexMap); - } -}; - - -/** @inheritDoc */ -fb.core.snap.ChildrenNode.prototype.updateChild = function(path, newChildNode) { - var front = path.getFront(); - if (front === null) { - return newChildNode; - } else { - fb.core.util.assert(path.getFront() !== '.priority' || path.getLength() === 1, - '.priority must be the last token in a path'); - var newImmediateChild = this.getImmediateChild(front). - updateChild(path.popFront(), newChildNode); - return this.updateImmediateChild(front, newImmediateChild); - } -}; - -/** @inheritDoc */ -fb.core.snap.ChildrenNode.prototype.isEmpty = function() { - return this.children_.isEmpty(); -}; - - -/** @inheritDoc */ -fb.core.snap.ChildrenNode.prototype.numChildren = function() { - return this.children_.count(); -}; - - -/** - * @private - * @type {RegExp} - */ -fb.core.snap.ChildrenNode.INTEGER_REGEXP_ = /^(0|[1-9]\d*)$/; - -/** @inheritDoc */ -fb.core.snap.ChildrenNode.prototype.val = function(opt_exportFormat) { - if (this.isEmpty()) - return null; - - var obj = { }; - var numKeys = 0, maxKey = 0, allIntegerKeys = true; - this.forEachChild(fb.core.snap.PriorityIndex, function(key, childNode) { - obj[key] = childNode.val(opt_exportFormat); - - numKeys++; - if (allIntegerKeys && fb.core.snap.ChildrenNode.INTEGER_REGEXP_.test(key)) { - maxKey = Math.max(maxKey, Number(key)); - } else { - allIntegerKeys = false; - } - }); - - if (!opt_exportFormat && allIntegerKeys && maxKey < 2 * numKeys) { - // convert to array. - var array = []; - for (var key in obj) - array[key] = obj[key]; - - return array; - } else { - if (opt_exportFormat && !this.getPriority().isEmpty()) { - obj['.priority'] = this.getPriority().val(); - } - return obj; - } -}; - - -/** @inheritDoc */ -fb.core.snap.ChildrenNode.prototype.hash = function() { - if (this.lazyHash_ === null) { - var toHash = ''; - if (!this.getPriority().isEmpty()) - toHash += 'priority:' + fb.core.snap.priorityHashText( - /**@type {(!string|!number)} */ (this.getPriority().val())) + ':'; - - this.forEachChild(fb.core.snap.PriorityIndex, function(key, childNode) { - var childHash = childNode.hash(); - if (childHash !== '') - toHash += ':' + key + ':' + childHash; - }); - - this.lazyHash_ = (toHash === '') ? '' : fb.core.util.sha1(toHash); - } - return this.lazyHash_; -}; - - -/** @inheritDoc */ -fb.core.snap.ChildrenNode.prototype.getPredecessorChildName = function(childName, childNode, index) { - var idx = this.resolveIndex_(index); - if (idx) { - var predecessor = idx.getPredecessorKey(new fb.core.snap.NamedNode(childName, childNode)); - return predecessor ? predecessor.name : null; - } else { - return this.children_.getPredecessorKey(childName); - } -}; - -/** - * @param {!fb.core.snap.Index} indexDefinition - * @return {?string} - */ -fb.core.snap.ChildrenNode.prototype.getFirstChildName = function(indexDefinition) { - var idx = this.resolveIndex_(indexDefinition); - if (idx) { - var minKey = idx.minKey(); - return minKey && minKey.name; - } else { - return this.children_.minKey(); - } -}; - -/** - * @param {!fb.core.snap.Index} indexDefinition - * @return {?fb.core.snap.NamedNode} - */ -fb.core.snap.ChildrenNode.prototype.getFirstChild = function(indexDefinition) { - var minKey = this.getFirstChildName(indexDefinition); - if (minKey) { - return new fb.core.snap.NamedNode(minKey, this.children_.get(minKey)); - } else { - return null; - } -}; - -/** - * Given an index, return the key name of the largest value we have, according to that index - * @param {!fb.core.snap.Index} indexDefinition - * @return {?string} - */ -fb.core.snap.ChildrenNode.prototype.getLastChildName = function(indexDefinition) { - var idx = this.resolveIndex_(indexDefinition); - if (idx) { - var maxKey = idx.maxKey(); - return maxKey && maxKey.name; - } else { - return this.children_.maxKey(); - } -}; - -/** - * @param {!fb.core.snap.Index} indexDefinition - * @return {?fb.core.snap.NamedNode} - */ -fb.core.snap.ChildrenNode.prototype.getLastChild = function(indexDefinition) { - var maxKey = this.getLastChildName(indexDefinition); - if (maxKey) { - return new fb.core.snap.NamedNode(maxKey, this.children_.get(maxKey)); - } else { - return null; - } -}; - - -/** - * @inheritDoc - */ -fb.core.snap.ChildrenNode.prototype.forEachChild = function(index, action) { - var idx = this.resolveIndex_(index); - if (idx) { - return idx.inorderTraversal(function(wrappedNode) { - return action(wrappedNode.name, wrappedNode.node); - }); - } else { - return this.children_.inorderTraversal(action); - } -}; - -/** - * @param {!fb.core.snap.Index} indexDefinition - * @return {fb.core.util.SortedMapIterator} - */ -fb.core.snap.ChildrenNode.prototype.getIterator = function(indexDefinition) { - return this.getIteratorFrom(indexDefinition.minPost(), indexDefinition); -}; - -/** - * - * @param {!fb.core.snap.NamedNode} startPost - * @param {!fb.core.snap.Index} indexDefinition - * @return {!fb.core.util.SortedMapIterator} - */ -fb.core.snap.ChildrenNode.prototype.getIteratorFrom = function(startPost, indexDefinition) { - var idx = this.resolveIndex_(indexDefinition); - if (idx) { - return idx.getIteratorFrom(startPost, function(key) { return key; }); - } else { - var iterator = this.children_.getIteratorFrom(startPost.name, fb.core.snap.NamedNode.Wrap); - var next = iterator.peek(); - while (next != null && indexDefinition.compare(next, startPost) < 0) { - iterator.getNext(); - next = iterator.peek(); - } - return iterator; - } -}; - -/** - * @param {!fb.core.snap.Index} indexDefinition - * @return {!fb.core.util.SortedMapIterator} - */ -fb.core.snap.ChildrenNode.prototype.getReverseIterator = function(indexDefinition) { - return this.getReverseIteratorFrom(indexDefinition.maxPost(), indexDefinition); -}; - -/** - * @param {!fb.core.snap.NamedNode} endPost - * @param {!fb.core.snap.Index} indexDefinition - * @return {!fb.core.util.SortedMapIterator} - */ -fb.core.snap.ChildrenNode.prototype.getReverseIteratorFrom = function(endPost, indexDefinition) { - var idx = this.resolveIndex_(indexDefinition); - if (idx) { - return idx.getReverseIteratorFrom(endPost, function(key) { return key; }); - } else { - var iterator = this.children_.getReverseIteratorFrom(endPost.name, fb.core.snap.NamedNode.Wrap); - var next = iterator.peek(); - while (next != null && indexDefinition.compare(next, endPost) > 0) { - iterator.getNext(); - next = iterator.peek(); - } - return iterator; - } -}; - -/** - * @inheritDoc - */ -fb.core.snap.ChildrenNode.prototype.compareTo = function(other) { - if (this.isEmpty()) { - if (other.isEmpty()) { - return 0; - } else { - return -1; - } - } else if (other.isLeafNode() || other.isEmpty()) { - return 1; - } else if (other === fb.core.snap.MAX_NODE) { - return -1; - } else { - // Must be another node with children. - return 0; - } -}; - -/** - * @inheritDoc - */ -fb.core.snap.ChildrenNode.prototype.withIndex = function(indexDefinition) { - if (indexDefinition === fb.core.snap.KeyIndex || this.indexMap_.hasIndex(indexDefinition)) { - return this; - } else { - var newIndexMap = this.indexMap_.addIndex(indexDefinition, this.children_); - return new fb.core.snap.ChildrenNode(this.children_, this.priorityNode_, newIndexMap); - } -}; - -/** - * @inheritDoc - */ -fb.core.snap.ChildrenNode.prototype.isIndexed = function(index) { - return index === fb.core.snap.KeyIndex || this.indexMap_.hasIndex(index); -}; - -/** - * @inheritDoc - */ -fb.core.snap.ChildrenNode.prototype.equals = function(other) { - if (other === this) { - return true; - } - else if (other.isLeafNode()) { - return false; - } else { - var otherChildrenNode = /** @type {!fb.core.snap.ChildrenNode} */ (other); - if (!this.getPriority().equals(otherChildrenNode.getPriority())) { - return false; - } else if (this.children_.count() === otherChildrenNode.children_.count()) { - var thisIter = this.getIterator(fb.core.snap.PriorityIndex); - var otherIter = otherChildrenNode.getIterator(fb.core.snap.PriorityIndex); - var thisCurrent = thisIter.getNext(); - var otherCurrent = otherIter.getNext(); - while (thisCurrent && otherCurrent) { - if (thisCurrent.name !== otherCurrent.name || !thisCurrent.node.equals(otherCurrent.node)) { - return false; - } - thisCurrent = thisIter.getNext(); - otherCurrent = otherIter.getNext(); - } - return thisCurrent === null && otherCurrent === null; - } else { - return false; - } - } -}; - - -/** - * Returns a SortedMap ordered by index, or null if the default (by-key) ordering can be used - * instead. - * - * @private - * @param {!fb.core.snap.Index} indexDefinition - * @return {?fb.core.util.SortedMap.} - */ -fb.core.snap.ChildrenNode.prototype.resolveIndex_ = function(indexDefinition) { - if (indexDefinition === fb.core.snap.KeyIndex) { - return null; - } else { - return this.indexMap_.get(indexDefinition.toString()); - } -}; - - -if (goog.DEBUG) { - /** - * Returns a string representation of the node. - * @return {string} String representation. - */ - fb.core.snap.ChildrenNode.prototype.toString = function() { - return fb.util.json.stringify(this.val(true)); - }; -} - - diff --git a/src/database/js-client/core/snap/Index.js b/src/database/js-client/core/snap/Index.js deleted file mode 100644 index e1ebef89132..00000000000 --- a/src/database/js-client/core/snap/Index.js +++ /dev/null @@ -1,444 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.snap.Index'); -goog.provide('fb.core.snap.KeyIndex'); -goog.provide('fb.core.snap.PathIndex'); -goog.provide('fb.core.snap.PriorityIndex'); -goog.provide('fb.core.snap.ValueIndex'); -goog.require('fb.core.util'); - - - -/** - * - * @constructor - */ -fb.core.snap.Index = function() { }; - - -/** - * @typedef {!Object} - */ -fb.core.snap.Index.FallbackType; - - -/** - * @type {fb.core.snap.Index.FallbackType} - */ -fb.core.snap.Index.Fallback = {}; - - -/** - * @param {!fb.core.snap.NamedNode} a - * @param {!fb.core.snap.NamedNode} b - * @return {number} - */ -fb.core.snap.Index.prototype.compare = goog.abstractMethod; - - -/** - * @param {!fb.core.snap.Node} node - * @return {boolean} - */ -fb.core.snap.Index.prototype.isDefinedOn = goog.abstractMethod; - - -/** - * @return {function(!fb.core.snap.NamedNode, !fb.core.snap.NamedNode):number} A standalone comparison function for - * this index - */ -fb.core.snap.Index.prototype.getCompare = function() { - return goog.bind(this.compare, this); -}; - - -/** - * Given a before and after value for a node, determine if the indexed value has changed. Even if they are different, - * it's possible that the changes are isolated to parts of the snapshot that are not indexed. - * - * @param {!fb.core.snap.Node} oldNode - * @param {!fb.core.snap.Node} newNode - * @return {boolean} True if the portion of the snapshot being indexed changed between oldNode and newNode - */ -fb.core.snap.Index.prototype.indexedValueChanged = function(oldNode, newNode) { - var oldWrapped = new fb.core.snap.NamedNode(fb.core.util.MIN_NAME, oldNode); - var newWrapped = new fb.core.snap.NamedNode(fb.core.util.MIN_NAME, newNode); - return this.compare(oldWrapped, newWrapped) !== 0; -}; - - -/** - * @return {!fb.core.snap.NamedNode} a node wrapper that will sort equal to or less than - * any other node wrapper, using this index - */ -fb.core.snap.Index.prototype.minPost = function() { - return fb.core.snap.NamedNode.MIN; -}; - - -/** - * @return {!fb.core.snap.NamedNode} a node wrapper that will sort greater than or equal to - * any other node wrapper, using this index - */ -fb.core.snap.Index.prototype.maxPost = goog.abstractMethod; - - -/** - * @param {*} indexValue - * @param {string} name - * @return {!fb.core.snap.NamedNode} - */ -fb.core.snap.Index.prototype.makePost = goog.abstractMethod; - - -/** - * @return {!string} String representation for inclusion in a query spec - */ -fb.core.snap.Index.prototype.toString = goog.abstractMethod; - - - -/** - * @param {!fb.core.util.Path} indexPath - * @constructor - * @extends {fb.core.snap.Index} - */ -fb.core.snap.PathIndex = function(indexPath) { - fb.core.snap.Index.call(this); - - fb.core.util.assert(!indexPath.isEmpty() && indexPath.getFront() !== '.priority', - 'Can\'t create PathIndex with empty path or .priority key'); - /** - * - * @type {!fb.core.util.Path} - * @private - */ - this.indexPath_ = indexPath; -}; -goog.inherits(fb.core.snap.PathIndex, fb.core.snap.Index); - - -/** - * @param {!fb.core.snap.Node} snap - * @return {!fb.core.snap.Node} - * @protected - */ -fb.core.snap.PathIndex.prototype.extractChild = function(snap) { - return snap.getChild(this.indexPath_); -}; - - -/** - * @inheritDoc - */ -fb.core.snap.PathIndex.prototype.isDefinedOn = function(node) { - return !node.getChild(this.indexPath_).isEmpty(); -}; - - -/** - * @inheritDoc - */ -fb.core.snap.PathIndex.prototype.compare = function(a, b) { - var aChild = this.extractChild(a.node); - var bChild = this.extractChild(b.node); - var indexCmp = aChild.compareTo(bChild); - if (indexCmp === 0) { - return fb.core.util.nameCompare(a.name, b.name); - } else { - return indexCmp; - } -}; - - -/** - * @inheritDoc - */ -fb.core.snap.PathIndex.prototype.makePost = function(indexValue, name) { - var valueNode = fb.core.snap.NodeFromJSON(indexValue); - var node = fb.core.snap.EMPTY_NODE.updateChild(this.indexPath_, valueNode); - return new fb.core.snap.NamedNode(name, node); -}; - - -/** - * @inheritDoc - */ -fb.core.snap.PathIndex.prototype.maxPost = function() { - var node = fb.core.snap.EMPTY_NODE.updateChild(this.indexPath_, fb.core.snap.MAX_NODE); - return new fb.core.snap.NamedNode(fb.core.util.MAX_NAME, node); -}; - - -/** - * @inheritDoc - */ -fb.core.snap.PathIndex.prototype.toString = function() { - return this.indexPath_.slice().join('/'); -}; - - - -/** - * @constructor - * @extends {fb.core.snap.Index} - * @private - */ -fb.core.snap.PriorityIndex_ = function() { - fb.core.snap.Index.call(this); -}; -goog.inherits(fb.core.snap.PriorityIndex_, fb.core.snap.Index); - - -/** - * @inheritDoc - */ -fb.core.snap.PriorityIndex_.prototype.compare = function(a, b) { - var aPriority = a.node.getPriority(); - var bPriority = b.node.getPriority(); - var indexCmp = aPriority.compareTo(bPriority); - if (indexCmp === 0) { - return fb.core.util.nameCompare(a.name, b.name); - } else { - return indexCmp; - } -}; - - -/** - * @inheritDoc - */ -fb.core.snap.PriorityIndex_.prototype.isDefinedOn = function(node) { - return !node.getPriority().isEmpty(); -}; - - -/** - * @inheritDoc - */ -fb.core.snap.PriorityIndex_.prototype.indexedValueChanged = function(oldNode, newNode) { - return !oldNode.getPriority().equals(newNode.getPriority()); -}; - - -/** - * @inheritDoc - */ -fb.core.snap.PriorityIndex_.prototype.minPost = function() { - return fb.core.snap.NamedNode.MIN; -}; - - -/** - * @inheritDoc - */ -fb.core.snap.PriorityIndex_.prototype.maxPost = function() { - return new fb.core.snap.NamedNode(fb.core.util.MAX_NAME, - new fb.core.snap.LeafNode('[PRIORITY-POST]', fb.core.snap.MAX_NODE)); -}; - - -/** - * @param {*} indexValue - * @param {string} name - * @return {!fb.core.snap.NamedNode} - */ -fb.core.snap.PriorityIndex_.prototype.makePost = function(indexValue, name) { - var priorityNode = fb.core.snap.NodeFromJSON(indexValue); - return new fb.core.snap.NamedNode(name, new fb.core.snap.LeafNode('[PRIORITY-POST]', priorityNode)); -}; - - -/** - * @return {!string} String representation for inclusion in a query spec - */ -fb.core.snap.PriorityIndex_.prototype.toString = function() { - return '.priority'; -}; - - -/** - * @type {!fb.core.snap.Index} - */ -fb.core.snap.PriorityIndex = new fb.core.snap.PriorityIndex_(); - - - -/** - * @constructor - * @extends {fb.core.snap.Index} - * @private - */ -fb.core.snap.KeyIndex_ = function() { - fb.core.snap.Index.call(this); -}; -goog.inherits(fb.core.snap.KeyIndex_, fb.core.snap.Index); - - -/** - * @inheritDoc - */ -fb.core.snap.KeyIndex_.prototype.compare = function(a, b) { - return fb.core.util.nameCompare(a.name, b.name); -}; - - -/** - * @inheritDoc - */ -fb.core.snap.KeyIndex_.prototype.isDefinedOn = function(node) { - // We could probably return true here (since every node has a key), but it's never called - // so just leaving unimplemented for now. - throw fb.core.util.assertionError('KeyIndex.isDefinedOn not expected to be called.'); -}; - - -/** - * @inheritDoc - */ -fb.core.snap.KeyIndex_.prototype.indexedValueChanged = function(oldNode, newNode) { - return false; // The key for a node never changes. -}; - - -/** - * @inheritDoc - */ -fb.core.snap.KeyIndex_.prototype.minPost = function() { - return fb.core.snap.NamedNode.MIN; -}; - - -/** - * @inheritDoc - */ -fb.core.snap.KeyIndex_.prototype.maxPost = function() { - // TODO: This should really be created once and cached in a static property, but - // NamedNode isn't defined yet, so I can't use it in a static. Bleh. - return new fb.core.snap.NamedNode(fb.core.util.MAX_NAME, fb.core.snap.EMPTY_NODE); -}; - - -/** - * @param {*} indexValue - * @param {string} name - * @return {!fb.core.snap.NamedNode} - */ -fb.core.snap.KeyIndex_.prototype.makePost = function(indexValue, name) { - fb.core.util.assert(goog.isString(indexValue), 'KeyIndex indexValue must always be a string.'); - // We just use empty node, but it'll never be compared, since our comparator only looks at name. - return new fb.core.snap.NamedNode(/** @type {!string} */ (indexValue), fb.core.snap.EMPTY_NODE); -}; - - -/** - * @return {!string} String representation for inclusion in a query spec - */ -fb.core.snap.KeyIndex_.prototype.toString = function() { - return '.key'; -}; - - -/** - * KeyIndex singleton. - * - * @type {!fb.core.snap.Index} - */ -fb.core.snap.KeyIndex = new fb.core.snap.KeyIndex_(); - - - -/** - * @constructor - * @extends {fb.core.snap.Index} - * @private - */ -fb.core.snap.ValueIndex_ = function() { - fb.core.snap.Index.call(this); -}; -goog.inherits(fb.core.snap.ValueIndex_, fb.core.snap.Index); - - -/** - * @inheritDoc - */ -fb.core.snap.ValueIndex_.prototype.compare = function(a, b) { - var indexCmp = a.node.compareTo(b.node); - if (indexCmp === 0) { - return fb.core.util.nameCompare(a.name, b.name); - } else { - return indexCmp; - } -}; - - -/** - * @inheritDoc - */ -fb.core.snap.ValueIndex_.prototype.isDefinedOn = function(node) { - return true; -}; - - -/** - * @inheritDoc - */ -fb.core.snap.ValueIndex_.prototype.indexedValueChanged = function(oldNode, newNode) { - return !oldNode.equals(newNode); -}; - - -/** - * @inheritDoc - */ -fb.core.snap.ValueIndex_.prototype.minPost = function() { - return fb.core.snap.NamedNode.MIN; -}; - - -/** - * @inheritDoc - */ -fb.core.snap.ValueIndex_.prototype.maxPost = function() { - return fb.core.snap.NamedNode.MAX; -}; - - -/** - * @param {*} indexValue - * @param {string} name - * @return {!fb.core.snap.NamedNode} - */ -fb.core.snap.ValueIndex_.prototype.makePost = function(indexValue, name) { - var valueNode = fb.core.snap.NodeFromJSON(indexValue); - return new fb.core.snap.NamedNode(name, valueNode); -}; - - -/** - * @return {!string} String representation for inclusion in a query spec - */ -fb.core.snap.ValueIndex_.prototype.toString = function() { - return '.value'; -}; - - -/** - * ValueIndex singleton. - * - * @type {!fb.core.snap.Index} - */ -fb.core.snap.ValueIndex = new fb.core.snap.ValueIndex_(); diff --git a/src/database/js-client/core/snap/IndexMap.js b/src/database/js-client/core/snap/IndexMap.js deleted file mode 100644 index e89787986a2..00000000000 --- a/src/database/js-client/core/snap/IndexMap.js +++ /dev/null @@ -1,163 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.snap.IndexMap'); -goog.require('fb.core.snap.Index'); -goog.require('fb.core.util'); - -/** - * - * @param {Object.>} indexes - * @param {Object.} indexSet - * @constructor - */ -fb.core.snap.IndexMap = function(indexes, indexSet) { - this.indexes_ = indexes; - this.indexSet_ = indexSet; -}; - -/** - * - * @param {!string} indexKey - * @return {?fb.core.util.SortedMap.} - */ -fb.core.snap.IndexMap.prototype.get = function(indexKey) { - var sortedMap = fb.util.obj.get(this.indexes_, indexKey); - if (!sortedMap) throw new Error('No index defined for ' + indexKey); - - if (sortedMap === fb.core.snap.Index.Fallback) { - // The index exists, but it falls back to just name comparison. Return null so that the calling code uses the - // regular child map - return null; - } else { - return sortedMap; - } -}; - -/** - * @param {!fb.core.snap.Index} indexDefinition - * @return {boolean} - */ -fb.core.snap.IndexMap.prototype.hasIndex = function(indexDefinition) { - return goog.object.contains(this.indexSet_, indexDefinition.toString()); -}; - -/** - * @param {!fb.core.snap.Index} indexDefinition - * @param {!fb.core.util.SortedMap.} existingChildren - * @return {!fb.core.snap.IndexMap} - */ -fb.core.snap.IndexMap.prototype.addIndex = function(indexDefinition, existingChildren) { - fb.core.util.assert(indexDefinition !== fb.core.snap.KeyIndex, - "KeyIndex always exists and isn't meant to be added to the IndexMap."); - var childList = []; - var sawIndexedValue = false; - var iter = existingChildren.getIterator(fb.core.snap.NamedNode.Wrap); - var next = iter.getNext(); - while (next) { - sawIndexedValue = sawIndexedValue || indexDefinition.isDefinedOn(next.node); - childList.push(next); - next = iter.getNext(); - } - var newIndex; - if (sawIndexedValue) { - newIndex = fb.core.snap.buildChildSet(childList, indexDefinition.getCompare()); - } else { - newIndex = fb.core.snap.Index.Fallback; - } - var indexName = indexDefinition.toString(); - var newIndexSet = goog.object.clone(this.indexSet_); - newIndexSet[indexName] = indexDefinition; - var newIndexes = goog.object.clone(this.indexes_); - newIndexes[indexName] = newIndex; - return new fb.core.snap.IndexMap(newIndexes, newIndexSet); -}; - - -/** - * Ensure that this node is properly tracked in any indexes that we're maintaining - * @param {!fb.core.snap.NamedNode} namedNode - * @param {!fb.core.util.SortedMap.} existingChildren - * @return {!fb.core.snap.IndexMap} - */ -fb.core.snap.IndexMap.prototype.addToIndexes = function(namedNode, existingChildren) { - var self = this; - var newIndexes = goog.object.map(this.indexes_, function(indexedChildren, indexName) { - var index = fb.util.obj.get(self.indexSet_, indexName); - fb.core.util.assert(index, 'Missing index implementation for ' + indexName); - if (indexedChildren === fb.core.snap.Index.Fallback) { - // Check to see if we need to index everything - if (index.isDefinedOn(namedNode.node)) { - // We need to build this index - var childList = []; - var iter = existingChildren.getIterator(fb.core.snap.NamedNode.Wrap); - var next = iter.getNext(); - while (next) { - if (next.name != namedNode.name) { - childList.push(next); - } - next = iter.getNext(); - } - childList.push(namedNode); - return fb.core.snap.buildChildSet(childList, index.getCompare()); - } else { - // No change, this remains a fallback - return fb.core.snap.Index.Fallback; - } - } else { - var existingSnap = existingChildren.get(namedNode.name); - var newChildren = indexedChildren; - if (existingSnap) { - newChildren = newChildren.remove(new fb.core.snap.NamedNode(namedNode.name, existingSnap)); - } - return newChildren.insert(namedNode, namedNode.node); - } - }); - return new fb.core.snap.IndexMap(newIndexes, this.indexSet_); -}; - -/** - * Create a new IndexMap instance with the given value removed - * @param {!fb.core.snap.NamedNode} namedNode - * @param {!fb.core.util.SortedMap.} existingChildren - * @return {!fb.core.snap.IndexMap} - */ -fb.core.snap.IndexMap.prototype.removeFromIndexes = function(namedNode, existingChildren) { - var newIndexes = goog.object.map(this.indexes_, function(indexedChildren) { - if (indexedChildren === fb.core.snap.Index.Fallback) { - // This is the fallback. Just return it, nothing to do in this case - return indexedChildren; - } else { - var existingSnap = existingChildren.get(namedNode.name); - if (existingSnap) { - return indexedChildren.remove(new fb.core.snap.NamedNode(namedNode.name, existingSnap)); - } else { - // No record of this child - return indexedChildren; - } - } - }); - return new fb.core.snap.IndexMap(newIndexes, this.indexSet_); -}; - -/** - * The default IndexMap for nodes without a priority - * @type {!fb.core.snap.IndexMap} - * @const - */ -fb.core.snap.IndexMap.Default = new fb.core.snap.IndexMap( - {'.priority': fb.core.snap.Index.Fallback}, - {'.priority': fb.core.snap.PriorityIndex} -); diff --git a/src/database/js-client/core/snap/LeafNode.js b/src/database/js-client/core/snap/LeafNode.js deleted file mode 100644 index 72a2e2bb6b4..00000000000 --- a/src/database/js-client/core/snap/LeafNode.js +++ /dev/null @@ -1,284 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.snap.LeafNode'); -goog.require('fb.core.snap.Node'); -goog.require('fb.core.util'); - -// TODO: For memory savings, don't store priorityNode_ if it's null. - - -/** - * LeafNode is a class for storing leaf nodes in a DataSnapshot. It - * implements Node and stores the value of the node (a string, - * number, or boolean) accessible via getValue(). - */ -fb.core.snap.LeafNode = goog.defineClass(null, { - /** - * @implements {fb.core.snap.Node} - * @param {!(string|number|boolean|Object)} value The value to store in this leaf node. - * The object type is possible in the event of a deferred value - * @param {!fb.core.snap.Node=} opt_priorityNode The priority of this node. - */ - constructor: function(value, opt_priorityNode) { - /** - * @private - * @const - * @type {!(string|number|boolean|Object)} - */ - this.value_ = value; - fb.core.util.assert(goog.isDef(this.value_) && this.value_ !== null, - "LeafNode shouldn't be created with null/undefined value."); - - /** - * @private - * @const - * @type {!fb.core.snap.Node} - */ - this.priorityNode_ = opt_priorityNode || fb.core.snap.EMPTY_NODE; - fb.core.snap.validatePriorityNode(this.priorityNode_); - - this.lazyHash_ = null; - }, - - statics: { - /** - * The sort order for comparing leaf nodes of different types. If two leaf nodes have - * the same type, the comparison falls back to their value - * @type {Array.} - * @const - */ - VALUE_TYPE_ORDER: ['object', 'boolean', 'number', 'string'] - }, - - /** @inheritDoc */ - isLeafNode: function() { return true; }, - - /** @inheritDoc */ - getPriority: function() { - return this.priorityNode_; - }, - - /** @inheritDoc */ - updatePriority: function(newPriorityNode) { - return new fb.core.snap.LeafNode(this.value_, newPriorityNode); - }, - - /** @inheritDoc */ - getImmediateChild: function(childName) { - // Hack to treat priority as a regular child - if (childName === '.priority') { - return this.priorityNode_; - } else { - return fb.core.snap.EMPTY_NODE; - } - }, - - /** @inheritDoc */ - getChild: function(path) { - if (path.isEmpty()) { - return this; - } else if (path.getFront() === '.priority') { - return this.priorityNode_; - } else { - return fb.core.snap.EMPTY_NODE; - } - }, - - /** - * @inheritDoc - */ - hasChild: function() { - return false; - }, - - /** @inheritDoc */ - getPredecessorChildName: function(childName, childNode) { - return null; - }, - - /** @inheritDoc */ - updateImmediateChild: function(childName, newChildNode) { - if (childName === '.priority') { - return this.updatePriority(newChildNode); - } else if (newChildNode.isEmpty() && childName !== '.priority') { - return this; - } else { - return fb.core.snap.EMPTY_NODE - .updateImmediateChild(childName, newChildNode) - .updatePriority(this.priorityNode_); - } - }, - - /** @inheritDoc */ - updateChild: function(path, newChildNode) { - var front = path.getFront(); - if (front === null) { - return newChildNode; - } else if (newChildNode.isEmpty() && front !== '.priority') { - return this; - } else { - fb.core.util.assert(front !== '.priority' || path.getLength() === 1, - '.priority must be the last token in a path'); - - return this.updateImmediateChild(front, - fb.core.snap.EMPTY_NODE.updateChild(path.popFront(), - newChildNode)); - } - }, - - /** @inheritDoc */ - isEmpty: function() { - return false; - }, - - /** @inheritDoc */ - numChildren: function() { - return 0; - }, - - /** @inheritDoc */ - forEachChild: function(index, action) { - return false; - }, - - /** - * @inheritDoc - */ - val: function(opt_exportFormat) { - if (opt_exportFormat && !this.getPriority().isEmpty()) - return { '.value': this.getValue(), '.priority' : this.getPriority().val() }; - else - return this.getValue(); - }, - - /** @inheritDoc */ - hash: function() { - if (this.lazyHash_ === null) { - var toHash = ''; - if (!this.priorityNode_.isEmpty()) - toHash += 'priority:' + fb.core.snap.priorityHashText( - /** @type {(number|string)} */ (this.priorityNode_.val())) + ':'; - - var type = typeof this.value_; - toHash += type + ':'; - if (type === 'number') { - toHash += fb.core.util.doubleToIEEE754String(/** @type {number} */ (this.value_)); - } else { - toHash += this.value_; - } - this.lazyHash_ = fb.core.util.sha1(toHash); - } - return /**@type {!string} */ (this.lazyHash_); - }, - - /** - * Returns the value of the leaf node. - * @return {Object|string|number|boolean} The value of the node. - */ - getValue: function() { - return this.value_; - }, - - /** - * @inheritDoc - */ - compareTo: function(other) { - if (other === fb.core.snap.EMPTY_NODE) { - return 1; - } else if (other instanceof fb.core.snap.ChildrenNode) { - return -1; - } else { - fb.core.util.assert(other.isLeafNode(), 'Unknown node type'); - return this.compareToLeafNode_(/** @type {!fb.core.snap.LeafNode} */ (other)); - } - }, - - /** - * Comparison specifically for two leaf nodes - * @param {!fb.core.snap.LeafNode} otherLeaf - * @return {!number} - * @private - */ - compareToLeafNode_: function(otherLeaf) { - var otherLeafType = typeof otherLeaf.value_; - var thisLeafType = typeof this.value_; - var otherIndex = goog.array.indexOf(fb.core.snap.LeafNode.VALUE_TYPE_ORDER, otherLeafType); - var thisIndex = goog.array.indexOf(fb.core.snap.LeafNode.VALUE_TYPE_ORDER, thisLeafType); - fb.core.util.assert(otherIndex >= 0, 'Unknown leaf type: ' + otherLeafType); - fb.core.util.assert(thisIndex >= 0, 'Unknown leaf type: ' + thisLeafType); - if (otherIndex === thisIndex) { - // Same type, compare values - if (thisLeafType === 'object') { - // Deferred value nodes are all equal, but we should also never get to this point... - return 0; - } else { - // Note that this works because true > false, all others are number or string comparisons - if (this.value_ < otherLeaf.value_) { - return -1; - } else if (this.value_ === otherLeaf.value_) { - return 0; - } else { - return 1; - } - } - } else { - return thisIndex - otherIndex; - } - }, - - /** - * @inheritDoc - */ - withIndex: function() { - return this; - }, - - /** - * @inheritDoc - */ - isIndexed: function() { - return true; - }, - - /** - * @inheritDoc - */ - equals: function(other) { - /** - * @inheritDoc - */ - if (other === this) { - return true; - } - else if (other.isLeafNode()) { - var otherLeaf = /** @type {!fb.core.snap.LeafNode} */ (other); - return this.value_ === otherLeaf.value_ && this.priorityNode_.equals(otherLeaf.priorityNode_); - } else { - return false; - } - } -}); // end fb.core.snap.LeafNode - - -if (goog.DEBUG) { - /** - * Converts the leaf node to a string. - * @return {string} String representation of the node. - */ - fb.core.snap.LeafNode.prototype.toString = function() { - return fb.util.json.stringify(this.val(true)); - }; -} diff --git a/src/database/js-client/core/snap/Node.js b/src/database/js-client/core/snap/Node.js deleted file mode 100644 index b720d5afc41..00000000000 --- a/src/database/js-client/core/snap/Node.js +++ /dev/null @@ -1,179 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.snap.Node'); -goog.provide('fb.core.snap.NamedNode'); - -/** - * Node is an interface defining the common functionality for nodes in - * a DataSnapshot. - * - * @interface - */ -fb.core.snap.Node = function() { }; - - -/** - * Whether this node is a leaf node. - * @return {boolean} Whether this is a leaf node. - */ -fb.core.snap.Node.prototype.isLeafNode; - - -/** - * Gets the priority of the node. - * @return {!fb.core.snap.Node} The priority of the node. - */ -fb.core.snap.Node.prototype.getPriority; - - -/** - * Returns a duplicate node with the new priority. - * @param {!fb.core.snap.Node} newPriorityNode New priority to set for the node. - * @return {!fb.core.snap.Node} Node with new priority. - */ -fb.core.snap.Node.prototype.updatePriority; - - -/** - * Returns the specified immediate child, or null if it doesn't exist. - * @param {string} childName The name of the child to retrieve. - * @return {!fb.core.snap.Node} The retrieved child, or an empty node. - */ -fb.core.snap.Node.prototype.getImmediateChild; - - -/** - * Returns a child by path, or null if it doesn't exist. - * @param {!fb.core.util.Path} path The path of the child to retrieve. - * @return {!fb.core.snap.Node} The retrieved child or an empty node. - */ -fb.core.snap.Node.prototype.getChild; - - -/** - * Returns the name of the child immediately prior to the specified childNode, or null. - * @param {!string} childName The name of the child to find the predecessor of. - * @param {!fb.core.snap.Node} childNode The node to find the predecessor of. - * @param {!fb.core.snap.Index} index The index to use to determine the predecessor - * @return {?string} The name of the predecessor child, or null if childNode is the first child. - */ -fb.core.snap.Node.prototype.getPredecessorChildName; - -/** - * Returns a duplicate node, with the specified immediate child updated. - * Any value in the node will be removed. - * @param {string} childName The name of the child to update. - * @param {!fb.core.snap.Node} newChildNode The new child node - * @return {!fb.core.snap.Node} The updated node. - */ -fb.core.snap.Node.prototype.updateImmediateChild; - - -/** - * Returns a duplicate node, with the specified child updated. Any value will - * be removed. - * @param {!fb.core.util.Path} path The path of the child to update. - * @param {!fb.core.snap.Node} newChildNode The new child node, which may be an empty node - * @return {!fb.core.snap.Node} The updated node. - */ -fb.core.snap.Node.prototype.updateChild; - -/** - * True if the immediate child specified exists - * @param {!string} childName - * @return {boolean} - */ -fb.core.snap.Node.prototype.hasChild; - -/** - * @return {boolean} True if this node has no value or children. - */ -fb.core.snap.Node.prototype.isEmpty; - - -/** - * @return {number} The number of children of this node. - */ -fb.core.snap.Node.prototype.numChildren; - - -/** - * Calls action for each child. - * @param {!fb.core.snap.Index} index - * @param {function(string, !fb.core.snap.Node)} action Action to be called for - * each child. It's passed the child name and the child node. - * @return {*} The first truthy value return by action, or the last falsey one - */ -fb.core.snap.Node.prototype.forEachChild; - - -/** - * @param {boolean=} opt_exportFormat True for export format (also wire protocol format). - * @return {*} Value of this node as JSON. - */ -fb.core.snap.Node.prototype.val; - - -/** - * @return {string} hash representing the node contents. - */ -fb.core.snap.Node.prototype.hash; - -/** - * @param {!fb.core.snap.Node} other Another node - * @return {!number} -1 for less than, 0 for equal, 1 for greater than other - */ -fb.core.snap.Node.prototype.compareTo; - -/** - * @param {!fb.core.snap.Node} other - * @return {boolean} Whether or not this snapshot equals other - */ -fb.core.snap.Node.prototype.equals; - -/** - * @param {!fb.core.snap.Index} indexDefinition - * @return {!fb.core.snap.Node} This node, with the specified index now available - */ -fb.core.snap.Node.prototype.withIndex; - -/** - * @param {!fb.core.snap.Index} indexDefinition - * @return {boolean} - */ -fb.core.snap.Node.prototype.isIndexed; - -/** - * - * @param {!string} name - * @param {!fb.core.snap.Node} node - * @constructor - * @struct - */ -fb.core.snap.NamedNode = function(name, node) { - this.name = name; - this.node = node; -}; - -/** - * - * @param {!string} name - * @param {!fb.core.snap.Node} node - * @return {fb.core.snap.NamedNode} - */ -fb.core.snap.NamedNode.Wrap = function(name, node) { - return new fb.core.snap.NamedNode(name, node); -}; diff --git a/src/database/js-client/core/snap/comparators.js b/src/database/js-client/core/snap/comparators.js deleted file mode 100644 index 4bf3506f2b6..00000000000 --- a/src/database/js-client/core/snap/comparators.js +++ /dev/null @@ -1,24 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.snap.comparators'); - -fb.core.snap.NAME_ONLY_COMPARATOR = function(left, right) { - return fb.core.util.nameCompare(left.name, right.name); -}; - -fb.core.snap.NAME_COMPARATOR = function(left, right) { - return fb.core.util.nameCompare(left, right); -}; diff --git a/src/database/js-client/core/snap/snap.js b/src/database/js-client/core/snap/snap.js deleted file mode 100644 index bad0eb08689..00000000000 --- a/src/database/js-client/core/snap/snap.js +++ /dev/null @@ -1,324 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.snap'); -goog.require('fb.core.snap.ChildrenNode'); -goog.require('fb.core.snap.IndexMap'); -goog.require('fb.core.snap.LeafNode'); -goog.require('fb.core.util'); - - -var USE_HINZE = true; - -/** - * Constructs a snapshot node representing the passed JSON and returns it. - * @param {*} json JSON to create a node for. - * @param {?string|?number=} opt_priority Optional priority to use. This will be ignored if the - * passed JSON contains a .priority property. - * @return {!fb.core.snap.Node} - */ -fb.core.snap.NodeFromJSON = function(json, opt_priority) { - if (json === null) { - return fb.core.snap.EMPTY_NODE; - } - - var priority = null; - if (typeof json === 'object' && '.priority' in json) { - priority = json['.priority']; - } else if (typeof opt_priority !== 'undefined') { - priority = opt_priority; - } - fb.core.util.assert( - priority === null || - typeof priority === 'string' || - typeof priority === 'number' || - (typeof priority === 'object' && '.sv' in priority), - 'Invalid priority type found: ' + (typeof priority) - ); - - if (typeof json === 'object' && '.value' in json && json['.value'] !== null) { - json = json['.value']; - } - - // Valid leaf nodes include non-objects or server-value wrapper objects - if (typeof json !== 'object' || '.sv' in json) { - var jsonLeaf = /** @type {!(string|number|boolean|Object)} */ (json); - return new fb.core.snap.LeafNode(jsonLeaf, fb.core.snap.NodeFromJSON(priority)); - } - - if (!(json instanceof Array) && USE_HINZE) { - var children = []; - var childrenHavePriority = false; - var hinzeJsonObj = /** @type {!Object} */ (json); - fb.util.obj.foreach(hinzeJsonObj, function(key, child) { - if (typeof key !== 'string' || key.substring(0, 1) !== '.') { // Ignore metadata nodes - var childNode = fb.core.snap.NodeFromJSON(hinzeJsonObj[key]); - if (!childNode.isEmpty()) { - childrenHavePriority = childrenHavePriority || !childNode.getPriority().isEmpty(); - children.push(new fb.core.snap.NamedNode(key, childNode)); - } - } - }); - - if (children.length == 0) { - return fb.core.snap.EMPTY_NODE; - } - - var childSet = /**@type {!fb.core.util.SortedMap.} */ (fb.core.snap.buildChildSet( - children, fb.core.snap.NAME_ONLY_COMPARATOR, function(namedNode) { return namedNode.name; }, - fb.core.snap.NAME_COMPARATOR - )); - if (childrenHavePriority) { - var sortedChildSet = fb.core.snap.buildChildSet(children, fb.core.snap.PriorityIndex.getCompare()); - return new fb.core.snap.ChildrenNode(childSet, fb.core.snap.NodeFromJSON(priority), - new fb.core.snap.IndexMap({'.priority': sortedChildSet}, {'.priority': fb.core.snap.PriorityIndex})); - } else { - return new fb.core.snap.ChildrenNode(childSet, fb.core.snap.NodeFromJSON(priority), - fb.core.snap.IndexMap.Default); - } - } else { - var node = fb.core.snap.EMPTY_NODE; - var jsonObj = /** @type {!Object} */ (json); - goog.object.forEach(jsonObj, function(childData, key) { - if (fb.util.obj.contains(jsonObj, key)) { - if (key.substring(0, 1) !== '.') { // ignore metadata nodes. - var childNode = fb.core.snap.NodeFromJSON(childData); - if (childNode.isLeafNode() || !childNode.isEmpty()) - node = node.updateImmediateChild(key, childNode); - } - } - }); - - return node.updatePriority(fb.core.snap.NodeFromJSON(priority)); - } -}; - -var LOG_2 = Math.log(2); - -/** - * @param {number} length - * @constructor - */ -fb.core.snap.Base12Num = function(length) { - var logBase2 = function(num) { - return parseInt(Math.log(num) / LOG_2, 10); - }; - var bitMask = function(bits) { - return parseInt(Array(bits + 1).join('1'), 2); - }; - this.count = logBase2(length + 1); - this.current_ = this.count - 1; - var mask = bitMask(this.count); - this.bits_ = (length + 1) & mask; -}; - -/** - * @return {boolean} - */ -fb.core.snap.Base12Num.prototype.nextBitIsOne = function() { - //noinspection JSBitwiseOperatorUsage - var result = !(this.bits_ & (0x1 << this.current_)); - this.current_--; - return result; -}; - -/** - * Takes a list of child nodes and constructs a SortedSet using the given comparison - * function - * - * Uses the algorithm described in the paper linked here: - * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.46.1458 - * - * @template K, V - * @param {Array.} childList Unsorted list of children - * @param {function(!fb.core.snap.NamedNode, !fb.core.snap.NamedNode):number} cmp The comparison method to be used - * @param {(function(fb.core.snap.NamedNode):K)=} keyFn An optional function to extract K from a node wrapper, if K's - * type is not NamedNode - * @param {(function(K, K):number)=} mapSortFn An optional override for comparator used by the generated sorted map - * @return {fb.core.util.SortedMap.} - */ -fb.core.snap.buildChildSet = function(childList, cmp, keyFn, mapSortFn) { - childList.sort(cmp); - - var buildBalancedTree = function(low, high) { - var length = high - low; - if (length == 0) { - return null; - } else if (length == 1) { - var namedNode = childList[low]; - var key = keyFn ? keyFn(namedNode) : namedNode; - return new fb.LLRBNode(key, namedNode.node, fb.LLRBNode.BLACK, null, null); - } else { - var middle = parseInt(length / 2, 10) + low; - var left = buildBalancedTree(low, middle); - var right = buildBalancedTree(middle + 1, high); - namedNode = childList[middle]; - key = keyFn ? keyFn(namedNode) : namedNode; - return new fb.LLRBNode(key, namedNode.node, fb.LLRBNode.BLACK, left, right); - } - }; - - var buildFrom12Array = function(base12) { - var node = null; - var root = null; - var index = childList.length; - - var buildPennant = function(chunkSize, color) { - var low = index - chunkSize; - var high = index; - index -= chunkSize; - var childTree = buildBalancedTree(low + 1, high); - var namedNode = childList[low]; - var key = keyFn ? keyFn(namedNode) : namedNode; - attachPennant(new fb.LLRBNode(key, namedNode.node, color, null, childTree)); - }; - - var attachPennant = function(pennant) { - if (node) { - node.left = pennant; - node = pennant; - } else { - root = pennant; - node = pennant; - } - }; - - for (var i = 0; i < base12.count; ++i) { - var isOne = base12.nextBitIsOne(); - // The number of nodes taken in each slice is 2^(arr.length - (i + 1)) - var chunkSize = Math.pow(2, base12.count - (i + 1)); - if (isOne) { - buildPennant(chunkSize, fb.LLRBNode.BLACK); - } else { - // current == 2 - buildPennant(chunkSize, fb.LLRBNode.BLACK); - buildPennant(chunkSize, fb.LLRBNode.RED); - } - } - return root; - }; - - var base12 = new fb.core.snap.Base12Num(childList.length); - var root = buildFrom12Array(base12); - - if (root !== null) { - return new fb.core.util.SortedMap(mapSortFn || cmp, root); - } else { - return new fb.core.util.SortedMap(mapSortFn || cmp); - } -}; - -/** - * @param {(!string|!number)} priority - * @return {!string} - */ -fb.core.snap.priorityHashText = function(priority) { - if (typeof priority === 'number') - return 'number:' + fb.core.util.doubleToIEEE754String(priority); - else - return 'string:' + priority; -}; - -/** - * Validates that a priority snapshot Node is valid. - * - * @param {!fb.core.snap.Node} priorityNode - */ -fb.core.snap.validatePriorityNode = function(priorityNode) { - if (priorityNode.isLeafNode()) { - var val = priorityNode.val(); - fb.core.util.assert(typeof val === 'string' || typeof val === 'number' || - (typeof val === 'object' && fb.util.obj.contains(val, '.sv')), - 'Priority must be a string or number.'); - } else { - fb.core.util.assert(priorityNode === fb.core.snap.MAX_NODE || priorityNode.isEmpty(), - 'priority of unexpected type.'); - } - // Don't call getPriority() on MAX_NODE to avoid hitting assertion. - fb.core.util.assert(priorityNode === fb.core.snap.MAX_NODE || priorityNode.getPriority().isEmpty(), - "Priority nodes can't have a priority of their own."); -}; - -/** - * Constant EMPTY_NODE used whenever somebody needs an empty node. - * @const - */ -fb.core.snap.EMPTY_NODE = new fb.core.snap.ChildrenNode( - new fb.core.util.SortedMap(fb.core.snap.NAME_COMPARATOR), - null, - fb.core.snap.IndexMap.Default -); - -/** - * @constructor - * @extends {fb.core.snap.ChildrenNode} - * @private - */ -fb.core.snap.MAX_NODE_ = function() { - fb.core.snap.ChildrenNode.call(this, - new fb.core.util.SortedMap(fb.core.snap.NAME_COMPARATOR), - fb.core.snap.EMPTY_NODE, - fb.core.snap.IndexMap.Default); -}; -goog.inherits(fb.core.snap.MAX_NODE_, fb.core.snap.ChildrenNode); - -/** - * @inheritDoc - */ -fb.core.snap.MAX_NODE_.prototype.compareTo = function(other) { - if (other === this) { - return 0; - } else { - return 1; - } -}; - -/** - * @inheritDoc - */ -fb.core.snap.MAX_NODE_.prototype.equals = function(other) { - // Not that we every compare it, but MAX_NODE_ is only ever equal to itself - return other === this; -}; - -/** - * @inheritDoc - */ -fb.core.snap.MAX_NODE_.prototype.getPriority = function() { - return this; -}; - -/** - * @inheritDoc - */ -fb.core.snap.MAX_NODE_.prototype.getImmediateChild = function(childName) { - return fb.core.snap.EMPTY_NODE; -}; - -/** - * @inheritDoc - */ -fb.core.snap.MAX_NODE_.prototype.isEmpty = function() { - return false; -}; - -/** - * Marker that will sort higher than any other snapshot. - * @type {!fb.core.snap.MAX_NODE_} - * @const - */ -fb.core.snap.MAX_NODE = new fb.core.snap.MAX_NODE_(); -fb.core.snap.NamedNode.MIN = new fb.core.snap.NamedNode(fb.core.util.MIN_NAME, fb.core.snap.EMPTY_NODE); -fb.core.snap.NamedNode.MAX = new fb.core.snap.NamedNode(fb.core.util.MAX_NAME, fb.core.snap.MAX_NODE); diff --git a/src/database/js-client/core/stats/StatsCollection.js b/src/database/js-client/core/stats/StatsCollection.js deleted file mode 100644 index 5e89474535d..00000000000 --- a/src/database/js-client/core/stats/StatsCollection.js +++ /dev/null @@ -1,42 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.stats.StatsCollection'); -goog.require('fb.util.obj'); -goog.require('goog.array'); -goog.require('goog.object'); - -/** - * Tracks a collection of stats. - * - * @constructor - */ -fb.core.stats.StatsCollection = function() { - this.counters_ = { }; -}; - -fb.core.stats.StatsCollection.prototype.incrementCounter = function(name, amount) { - if (!goog.isDef(amount)) - amount = 1; - - if (!fb.util.obj.contains(this.counters_, name)) - this.counters_[name] = 0; - - this.counters_[name] += amount; -}; - -fb.core.stats.StatsCollection.prototype.get = function() { - return goog.object.clone(this.counters_); -}; diff --git a/src/database/js-client/core/stats/StatsListener.js b/src/database/js-client/core/stats/StatsListener.js deleted file mode 100644 index da06d4030a1..00000000000 --- a/src/database/js-client/core/stats/StatsListener.js +++ /dev/null @@ -1,41 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.stats.StatsListener'); - -/** - * Returns the delta from the previous call to get stats. - * - * @param collection The collection to "listen" to. - * @constructor - */ -fb.core.stats.StatsListener = function(collection) { - this.collection_ = collection; - this.last_ = null; -}; - -fb.core.stats.StatsListener.prototype.get = function() { - var newStats = this.collection_.get(); - - var delta = goog.object.clone(newStats); - if (this.last_) { - for (var stat in this.last_) { - delta[stat] = delta[stat] - this.last_[stat]; - } - } - this.last_ = newStats; - - return delta; -}; diff --git a/src/database/js-client/core/stats/StatsManager.js b/src/database/js-client/core/stats/StatsManager.js deleted file mode 100644 index ebb42589ed6..00000000000 --- a/src/database/js-client/core/stats/StatsManager.js +++ /dev/null @@ -1,41 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.stats.StatsManager'); -goog.require('fb.core.stats.StatsCollection'); -goog.require('fb.core.stats.StatsListener'); -goog.require('fb.core.stats.StatsReporter'); - -fb.core.stats.StatsManager = { }; - -fb.core.stats.StatsManager.collections_ = { }; -fb.core.stats.StatsManager.reporters_ = { }; - -fb.core.stats.StatsManager.getCollection = function(repoInfo) { - var hashString = repoInfo.toString(); - if (!fb.core.stats.StatsManager.collections_[hashString]) { - fb.core.stats.StatsManager.collections_[hashString] = new fb.core.stats.StatsCollection(); - } - return fb.core.stats.StatsManager.collections_[hashString]; -}; - -fb.core.stats.StatsManager.getOrCreateReporter = function(repoInfo, creatorFunction) { - var hashString = repoInfo.toString(); - if (!fb.core.stats.StatsManager.reporters_[hashString]) { - fb.core.stats.StatsManager.reporters_[hashString] = creatorFunction(); - } - - return fb.core.stats.StatsManager.reporters_[hashString]; -}; diff --git a/src/database/js-client/core/stats/StatsReporter.js b/src/database/js-client/core/stats/StatsReporter.js deleted file mode 100644 index 1eb586ffbee..00000000000 --- a/src/database/js-client/core/stats/StatsReporter.js +++ /dev/null @@ -1,64 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.stats.StatsReporter'); -goog.require('fb.core.util'); - -// Assuming some apps may have a short amount of time on page, and a bulk of firebase operations probably -// happen on page load, we try to report our first set of stats pretty quickly, but we wait at least 10 -// seconds to try to ensure the Firebase connection is established / settled. -var FIRST_STATS_MIN_TIME = 10 * 1000; -var FIRST_STATS_MAX_TIME = 30 * 1000; - -// We'll continue to report stats on average every 5 minutes. -var REPORT_STATS_INTERVAL = 5 * 60 * 1000; - -/** - * - * @param collection - * @param connection - * @constructor - */ -fb.core.stats.StatsReporter = function(collection, connection) { - this.statsToReport_ = {}; - this.statsListener_ = new fb.core.stats.StatsListener(collection); - this.server_ = connection; - - var timeout = FIRST_STATS_MIN_TIME + (FIRST_STATS_MAX_TIME - FIRST_STATS_MIN_TIME) * Math.random(); - fb.core.util.setTimeoutNonBlocking(goog.bind(this.reportStats_, this), Math.floor(timeout)); -}; - -fb.core.stats.StatsReporter.prototype.includeStat = function(stat) { - this.statsToReport_[stat] = true; -}; - -fb.core.stats.StatsReporter.prototype.reportStats_ = function() { - var stats = this.statsListener_.get(); - var reportedStats = { }; - var haveStatsToReport = false; - for (var stat in stats) { - if (stats[stat] > 0 && fb.util.obj.contains(this.statsToReport_, stat)) { - reportedStats[stat] = stats[stat]; - haveStatsToReport = true; - } - } - - if (haveStatsToReport) { - this.server_.reportStats(reportedStats); - } - - // queue our next run. - fb.core.util.setTimeoutNonBlocking(goog.bind(this.reportStats_, this), Math.floor(Math.random() * 2 * REPORT_STATS_INTERVAL)); -}; diff --git a/src/database/js-client/core/storage/DOMStorageWrapper.js b/src/database/js-client/core/storage/DOMStorageWrapper.js deleted file mode 100644 index 384144e9200..00000000000 --- a/src/database/js-client/core/storage/DOMStorageWrapper.js +++ /dev/null @@ -1,84 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.storage.DOMStorageWrapper'); -goog.require('fb.util.obj'); - -goog.scope(function() { - /** - * Wraps a DOM Storage object and: - * - automatically encode objects as JSON strings before storing them to allow us to store arbitrary types. - * - prefixes names with "firebase:" to avoid collisions with app data. - * - * We automatically (see storage.js) create two such wrappers, one for sessionStorage, - * and one for localStorage. - * - * @param {Storage} domStorage The underlying storage object (e.g. localStorage or sessionStorage) - * @constructor - */ - fb.core.storage.DOMStorageWrapper = function(domStorage) { - this.domStorage_ = domStorage; - - // Use a prefix to avoid collisions with other stuff saved by the app. - this.prefix_ = 'firebase:'; - }; - var DOMStorageWrapper = fb.core.storage.DOMStorageWrapper; - - /** - * @param {string} key The key to save the value under - * @param {?Object} value The value being stored, or null to remove the key. - */ - DOMStorageWrapper.prototype.set = function(key, value) { - if (value == null) { - this.domStorage_.removeItem(this.prefixedName_(key)); - } else { - this.domStorage_.setItem(this.prefixedName_(key), fb.util.json.stringify(value)); - } - }; - - /** - * @param {string} key - * @return {*} The value that was stored under this key, or null - */ - DOMStorageWrapper.prototype.get = function(key) { - var storedVal = this.domStorage_.getItem(this.prefixedName_(key)); - if (storedVal == null) { - return null; - } else { - return fb.util.json.eval(storedVal); - } - }; - - /** - * @param {string} key - */ - DOMStorageWrapper.prototype.remove = function(key) { - this.domStorage_.removeItem(this.prefixedName_(key)); - }; - - DOMStorageWrapper.prototype.isInMemoryStorage = false; - - /** - * @param {string} name - * @return {string} - */ - DOMStorageWrapper.prototype.prefixedName_ = function(name) { - return this.prefix_ + name; - }; - - DOMStorageWrapper.prototype.toString = function() { - return this.domStorage_.toString(); - }; -}); diff --git a/src/database/js-client/core/storage/MemoryStorage.js b/src/database/js-client/core/storage/MemoryStorage.js deleted file mode 100644 index c6e7e5e3ea2..00000000000 --- a/src/database/js-client/core/storage/MemoryStorage.js +++ /dev/null @@ -1,53 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.storage.MemoryStorage'); -goog.require('fb.util.obj'); - -goog.scope(function() { - var obj = fb.util.obj; - - /** - * An in-memory storage implementation that matches the API of DOMStorageWrapper - * (TODO: create interface for both to implement). - * - * @constructor - */ - fb.core.storage.MemoryStorage = function() { - this.cache_ = {}; - }; - var MemoryStorage = fb.core.storage.MemoryStorage; - - MemoryStorage.prototype.set = function(key, value) { - if (value == null) { - delete this.cache_[key]; - } else { - this.cache_[key] = value; - } - }; - - MemoryStorage.prototype.get = function(key) { - if (obj.contains(this.cache_, key)) { - return this.cache_[key]; - } - return null; - }; - - MemoryStorage.prototype.remove = function(key) { - delete this.cache_[key]; - }; - - MemoryStorage.prototype.isInMemoryStorage = true; -}); diff --git a/src/database/js-client/core/storage/storage.js b/src/database/js-client/core/storage/storage.js deleted file mode 100644 index e6b16681d95..00000000000 --- a/src/database/js-client/core/storage/storage.js +++ /dev/null @@ -1,61 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.storage'); -goog.provide('fb.core.storage.PersistentStorage'); -goog.provide('fb.core.storage.SessionStorage'); -goog.require('fb.core.storage.DOMStorageWrapper'); -goog.require('fb.core.storage.MemoryStorage'); - -// TODO: Investigate using goog.storage instead of all this. - - -/** - * Helper to create a DOMStorageWrapper or else fall back to MemoryStorage. - * TODO: Once MemoryStorage and DOMStorageWrapper have a shared interface this method annotation should change - * to reflect this type - * - * @param {string} domStorageName Name of the underlying storage object - * (e.g. 'localStorage' or 'sessionStorage'). - * @return {?} Turning off type information until a common interface is defined. - */ -fb.core.storage.createStoragefor = function(domStorageName) { - try { - // NOTE: just accessing "localStorage" or "window['localStorage']" may throw a security exception, - // so it must be inside the try/catch. - if (typeof window !== 'undefined' && typeof window[domStorageName] !== 'undefined') { - // Need to test cache. Just because it's here doesn't mean it works - var domStorage = window[domStorageName]; - domStorage.setItem('firebase:sentinel', 'cache'); - domStorage.removeItem('firebase:sentinel'); - return new fb.core.storage.DOMStorageWrapper(domStorage); - } - } catch (e) { - } - - // Failed to create wrapper. Just return in-memory storage. - // TODO: log? - return new fb.core.storage.MemoryStorage(); -}; - - -/** A storage object that lasts across sessions */ -fb.core.storage.PersistentStorage = - fb.core.storage.createStoragefor('localStorage'); - - -/** A storage object that only lasts one session */ -fb.core.storage.SessionStorage = - fb.core.storage.createStoragefor('sessionStorage'); diff --git a/src/database/js-client/core/util/CountedSet.js b/src/database/js-client/core/util/CountedSet.js deleted file mode 100644 index 94ceaea2a59..00000000000 --- a/src/database/js-client/core/util/CountedSet.js +++ /dev/null @@ -1,108 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.util.CountedSet'); -goog.require('fb.core.util'); -goog.require('fb.util.obj'); -goog.require('goog.object'); - - -/** - * Implements a set with a count of elements. - * - */ -fb.core.util.CountedSet = goog.defineClass(null, { - /** - * @template K, V - */ - constructor: function() { - this.set = {}; - }, - - /** - * @param {!K} item - * @param {V} val - */ - add: function(item, val) { - this.set[item] = val !== null ? val : true; - }, - - /** - * @param {!K} key - * @return {boolean} - */ - contains: function(key) { - return fb.util.obj.contains(this.set, key); - }, - - /** - * @param {!K} item - * @return {V} - */ - get: function(item) { - return this.contains(item) ? this.set[item] : undefined; - }, - - /** - * @param {!K} item - */ - remove: function(item) { - delete this.set[item]; - }, - - /** - * Deletes everything in the set - */ - clear: function() { - this.set = {}; - }, - - /** - * True if there's nothing in the set - * @return {boolean} - */ - isEmpty: function() { - return goog.object.isEmpty(this.set); - }, - - /** - * @return {number} The number of items in the set - */ - count: function() { - return goog.object.getCount(this.set); - }, - - /** - * Run a function on each k,v pair in the set - * @param {function(K, V)} fn - */ - each: function(fn) { - goog.object.forEach(this.set, function(v, k) { - fn(k, v); - }); - }, - - /** - * Mostly for debugging - * @return {Array.} The keys present in this CountedSet - */ - keys: function() { - var keys = []; - goog.object.forEach(this.set, function(v, k) { - keys.push(k); - }); - return keys; - } -}); // end fb.core.util.CountedSet diff --git a/src/database/js-client/core/util/EventEmitter.js b/src/database/js-client/core/util/EventEmitter.js deleted file mode 100644 index bcdf9b03da1..00000000000 --- a/src/database/js-client/core/util/EventEmitter.js +++ /dev/null @@ -1,88 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.util.EventEmitter'); -goog.require('fb.core.util'); -goog.require('goog.array'); - - -/** - * Base class to be used if you want to emit events. Call the constructor with - * the set of allowed event names. - */ -fb.core.util.EventEmitter = goog.defineClass(null, { - /** - * @param {!Array.} allowedEvents - */ - constructor: function(allowedEvents) { - fb.core.util.assert(goog.isArray(allowedEvents) && allowedEvents.length > 0, - 'Requires a non-empty array'); - this.allowedEvents_ = allowedEvents; - this.listeners_ = {}; - }, - - /** - * To be overridden by derived classes in order to fire an initial event when - * somebody subscribes for data. - * - * @param {!string} eventType - * @return {Array.<*>} Array of parameters to trigger initial event with. - */ - getInitialEvent: goog.abstractMethod, - - /** - * To be called by derived classes to trigger events. - * @param {!string} eventType - * @param {...*} var_args - */ - trigger: function(eventType, var_args) { - // Clone the list, since callbacks could add/remove listeners. - var listeners = goog.array.clone(this.listeners_[eventType] || []); - - for (var i = 0; i < listeners.length; i++) { - listeners[i].callback.apply(listeners[i].context, Array.prototype.slice.call(arguments, 1)); - } - }, - - on: function(eventType, callback, context) { - this.validateEventType_(eventType); - this.listeners_[eventType] = this.listeners_[eventType] || []; - this.listeners_[eventType].push({callback: callback, context: context }); - - var eventData = this.getInitialEvent(eventType); - if (eventData) { - callback.apply(context, eventData); - } - }, - - off: function(eventType, callback, context) { - this.validateEventType_(eventType); - var listeners = this.listeners_[eventType] || []; - for (var i = 0; i < listeners.length; i++) { - if (listeners[i].callback === callback && (!context || context === listeners[i].context)) { - listeners.splice(i, 1); - return; - } - } - }, - - validateEventType_: function(eventType) { - fb.core.util.assert(goog.array.find(this.allowedEvents_, - function(et) { - return et === eventType; - }), - 'Unknown event: ' + eventType); - } -}); // end fb.core.util.EventEmitter diff --git a/src/database/js-client/core/util/ImmutableTree.js b/src/database/js-client/core/util/ImmutableTree.js deleted file mode 100644 index 2dfe211a337..00000000000 --- a/src/database/js-client/core/util/ImmutableTree.js +++ /dev/null @@ -1,374 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.util.ImmutableTree'); - -goog.require('fb.core.util'); -goog.require('fb.core.util.Path'); -goog.require('fb.core.util.SortedMap'); -goog.require('fb.util.json'); -goog.require('fb.util.obj'); -goog.require('goog.object'); - - -/** - * A tree with immutable elements. - */ -fb.core.util.ImmutableTree = goog.defineClass(null, { - /** - * @template T - * @param {?T} value - * @param {fb.core.util.SortedMap.>=} opt_children - */ - constructor: function(value, opt_children) { - /** - * @const - * @type {?T} - */ - this.value = value; - - /** - * @const - * @type {!fb.core.util.SortedMap.>} - */ - this.children = opt_children || fb.core.util.ImmutableTree.EmptyChildren_; - }, - - statics: { - /** - * Singleton empty children collection. - * - * @const - * @type {!fb.core.util.SortedMap.>} - * @private - */ - EmptyChildren_: new fb.core.util.SortedMap(fb.core.util.stringCompare), - - /** - * @template T - * @param {!Object.} obj - * @return {!fb.core.util.ImmutableTree.} - */ - fromObject: function(obj) { - var tree = fb.core.util.ImmutableTree.Empty; - goog.object.forEach(obj, function(childSnap, childPath) { - tree = tree.set(new fb.core.util.Path(childPath), childSnap); - }); - return tree; - } - }, - - /** - * True if the value is empty and there are no children - * @return {boolean} - */ - isEmpty: function() { - return this.value === null && this.children.isEmpty(); - }, - - /** - * Given a path and predicate, return the first node and the path to that node - * where the predicate returns true. - * - * TODO Do a perf test -- If we're creating a bunch of {path: value:} objects - * on the way back out, it may be better to pass down a pathSoFar obj. - * - * @param {!fb.core.util.Path} relativePath The remainder of the path - * @param {function(T):boolean} predicate The predicate to satisfy to return a - * node - * @return {?{path:!fb.core.util.Path, value:!T}} - */ - findRootMostMatchingPathAndValue: function(relativePath, predicate) { - if (this.value != null && predicate(this.value)) { - return {path: fb.core.util.Path.Empty, value: this.value}; - } else { - if (relativePath.isEmpty()) { - return null; - } else { - var front = relativePath.getFront(); - var child = this.children.get(front); - if (child !== null) { - var childExistingPathAndValue = - child.findRootMostMatchingPathAndValue(relativePath.popFront(), - predicate); - if (childExistingPathAndValue != null) { - var fullPath = new fb.core.util.Path(front) - .child(childExistingPathAndValue.path); - return {path: fullPath, value: childExistingPathAndValue.value}; - } else { - return null; - } - } else { - return null; - } - } - } - }, - - /** - * Find, if it exists, the shortest subpath of the given path that points a defined - * value in the tree - * @param {!fb.core.util.Path} relativePath - * @return {?{path: !fb.core.util.Path, value: !T}} - */ - findRootMostValueAndPath: function(relativePath) { - return this.findRootMostMatchingPathAndValue(relativePath, function() { return true; }); - }, - - /** - * @param {!fb.core.util.Path} relativePath - * @return {!fb.core.util.ImmutableTree.} The subtree at the given path - */ - subtree: function(relativePath) { - if (relativePath.isEmpty()) { - return this; - } else { - var front = relativePath.getFront(); - var childTree = this.children.get(front); - if (childTree !== null) { - return childTree.subtree(relativePath.popFront()); - } else { - return fb.core.util.ImmutableTree.Empty; - } - } - }, - - /** - * Sets a value at the specified path. - * - * @param {!fb.core.util.Path} relativePath Path to set value at. - * @param {?T} toSet Value to set. - * @return {!fb.core.util.ImmutableTree.} Resulting tree. - */ - set: function(relativePath, toSet) { - if (relativePath.isEmpty()) { - return new fb.core.util.ImmutableTree(toSet, this.children); - } else { - var front = relativePath.getFront(); - var child = this.children.get(front) || fb.core.util.ImmutableTree.Empty; - var newChild = child.set(relativePath.popFront(), toSet); - var newChildren = this.children.insert(front, newChild); - return new fb.core.util.ImmutableTree(this.value, newChildren); - } - }, - - /** - * Removes the value at the specified path. - * - * @param {!fb.core.util.Path} relativePath Path to value to remove. - * @return {!fb.core.util.ImmutableTree.} Resulting tree. - */ - remove: function(relativePath) { - if (relativePath.isEmpty()) { - if (this.children.isEmpty()) { - return fb.core.util.ImmutableTree.Empty; - } else { - return new fb.core.util.ImmutableTree(null, this.children); - } - } else { - var front = relativePath.getFront(); - var child = this.children.get(front); - if (child) { - var newChild = child.remove(relativePath.popFront()); - var newChildren; - if (newChild.isEmpty()) { - newChildren = this.children.remove(front); - } else { - newChildren = this.children.insert(front, newChild); - } - if (this.value === null && newChildren.isEmpty()) { - return fb.core.util.ImmutableTree.Empty; - } else { - return new fb.core.util.ImmutableTree(this.value, newChildren); - } - } else { - return this; - } - } - }, - - /** - * Gets a value from the tree. - * - * @param {!fb.core.util.Path} relativePath Path to get value for. - * @return {?T} Value at path, or null. - */ - get: function(relativePath) { - if (relativePath.isEmpty()) { - return this.value; - } else { - var front = relativePath.getFront(); - var child = this.children.get(front); - if (child) { - return child.get(relativePath.popFront()); - } else { - return null; - } - } - }, - - /** - * Replace the subtree at the specified path with the given new tree. - * - * @param {!fb.core.util.Path} relativePath Path to replace subtree for. - * @param {!fb.core.util.ImmutableTree} newTree New tree. - * @return {!fb.core.util.ImmutableTree} Resulting tree. - */ - setTree: function(relativePath, newTree) { - if (relativePath.isEmpty()) { - return newTree; - } else { - var front = relativePath.getFront(); - var child = this.children.get(front) || fb.core.util.ImmutableTree.Empty; - var newChild = child.setTree(relativePath.popFront(), newTree); - var newChildren; - if (newChild.isEmpty()) { - newChildren = this.children.remove(front); - } else { - newChildren = this.children.insert(front, newChild); - } - return new fb.core.util.ImmutableTree(this.value, newChildren); - } - }, - - /** - * Performs a depth first fold on this tree. Transforms a tree into a single - * value, given a function that operates on the path to a node, an optional - * current value, and a map of child names to folded subtrees - * @template V - * @param {function(fb.core.util.Path, ?T, Object.):V} fn - * @return {V} - */ - fold: function(fn) { - return this.fold_(fb.core.util.Path.Empty, fn); - }, - - /** - * Recursive helper for public-facing fold() method - * @template V - * @param {!fb.core.util.Path} pathSoFar - * @param {function(fb.core.util.Path, ?T, Object.):V} fn - * @return {V} - * @private - */ - fold_: function(pathSoFar, fn) { - var accum = {}; - this.children.inorderTraversal(function(childKey, childTree) { - accum[childKey] = childTree.fold_(pathSoFar.child(childKey), fn); - }); - return fn(pathSoFar, this.value, accum); - }, - - /** - * Find the first matching value on the given path. Return the result of applying f to it. - * @template V - * @param {!fb.core.util.Path} path - * @param {!function(!fb.core.util.Path, !T):?V} f - * @return {?V} - */ - findOnPath: function(path, f) { - return this.findOnPath_(path, fb.core.util.Path.Empty, f); - }, - - findOnPath_: function(pathToFollow, pathSoFar, f) { - var result = this.value ? f(pathSoFar, this.value) : false; - if (result) { - return result; - } else { - if (pathToFollow.isEmpty()) { - return null; - } else { - var front = pathToFollow.getFront(); - var nextChild = this.children.get(front); - if (nextChild) { - return nextChild.findOnPath_(pathToFollow.popFront(), pathSoFar.child(front), f); - } else { - return null; - } - } - } - }, - - foreachOnPath: function(path, f) { - return this.foreachOnPath_(path, fb.core.util.Path.Empty, f); - }, - - foreachOnPath_: function(pathToFollow, currentRelativePath, f) { - if (pathToFollow.isEmpty()) { - return this; - } else { - if (this.value) { - f(currentRelativePath, this.value); - } - var front = pathToFollow.getFront(); - var nextChild = this.children.get(front); - if (nextChild) { - return nextChild.foreachOnPath_(pathToFollow.popFront(), - currentRelativePath.child(front), f); - } else { - return fb.core.util.ImmutableTree.Empty; - } - } - }, - - /** - * Calls the given function for each node in the tree that has a value. - * - * @param {function(!fb.core.util.Path, !T)} f A function to be called with - * the path from the root of the tree to a node, and the value at that node. - * Called in depth-first order. - */ - foreach: function(f) { - this.foreach_(fb.core.util.Path.Empty, f); - }, - - foreach_: function(currentRelativePath, f) { - this.children.inorderTraversal(function(childName, childTree) { - childTree.foreach_(currentRelativePath.child(childName), f); - }); - if (this.value) { - f(currentRelativePath, this.value); - } - }, - - foreachChild: function(f) { - this.children.inorderTraversal(function(childName, childTree) { - if (childTree.value) { - f(childName, childTree.value); - } - }); - } -}); // end fb.core.util.ImmutableTree - - -/** - * @const - */ -fb.core.util.ImmutableTree.Empty = new fb.core.util.ImmutableTree(null); - - -if (goog.DEBUG) { - /** - * @inheritDoc - */ - fb.core.util.ImmutableTree.prototype.toString = function() { - var json = {}; - this.foreach(function(relativePath, value) { - var pathString = relativePath.toString(); - json[pathString] = value.toString(); - }); - return fb.util.json.stringify(json); - }; -} diff --git a/src/database/js-client/core/util/NextPushId.js b/src/database/js-client/core/util/NextPushId.js deleted file mode 100644 index 2b63001850d..00000000000 --- a/src/database/js-client/core/util/NextPushId.js +++ /dev/null @@ -1,82 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.util.nextPushId'); -goog.require('fb.core.util'); - - -/** - * Fancy ID generator that creates 20-character string identifiers with the - * following properties: - * - * 1. They're based on timestamp so that they sort *after* any existing ids. - * 2. They contain 72-bits of random data after the timestamp so that IDs won't - * collide with other clients' IDs. - * 3. They sort *lexicographically* (so the timestamp is converted to characters - * that will sort properly). - * 4. They're monotonically increasing. Even if you generate more than one in - * the same timestamp, the latter ones will sort after the former ones. We do - * this by using the previous random bits but "incrementing" them by 1 (only - * in the case of a timestamp collision). - */ -fb.core.util.nextPushId = (function() { - // Modeled after base64 web-safe chars, but ordered by ASCII. - var PUSH_CHARS = '-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz'; - - // Timestamp of last push, used to prevent local collisions if you push twice - // in one ms. - var lastPushTime = 0; - - // We generate 72-bits of randomness which get turned into 12 characters and - // appended to the timestamp to prevent collisions with other clients. We - // store the last characters we generated because in the event of a collision, - // we'll use those same characters except "incremented" by one. - var lastRandChars = []; - - return function(now) { - var duplicateTime = (now === lastPushTime); - lastPushTime = now; - - var timeStampChars = new Array(8); - for (var i = 7; i >= 0; i--) { - timeStampChars[i] = PUSH_CHARS.charAt(now % 64); - // NOTE: Can't use << here because javascript will convert to int and lose - // the upper bits. - now = Math.floor(now / 64); - } - fb.core.util.assert(now === 0, 'Cannot push at time == 0'); - - var id = timeStampChars.join(''); - - if (!duplicateTime) { - for (i = 0; i < 12; i++) { - lastRandChars[i] = Math.floor(Math.random() * 64); - } - } else { - // If the timestamp hasn't changed since last push, use the same random - // number, except incremented by 1. - for (i = 11; i >= 0 && lastRandChars[i] === 63; i--) { - lastRandChars[i] = 0; - } - lastRandChars[i]++; - } - for (i = 0; i < 12; i++) { - id += PUSH_CHARS.charAt(lastRandChars[i]); - } - fb.core.util.assert(id.length === 20, 'nextPushId: Length should be 20.'); - - return id; - }; -})(); diff --git a/src/database/js-client/core/util/NodePatches.js b/src/database/js-client/core/util/NodePatches.js deleted file mode 100644 index a4425a5c3a6..00000000000 --- a/src/database/js-client/core/util/NodePatches.js +++ /dev/null @@ -1,138 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.util.NodePatches'); - - -/** - * @suppress {es5Strict} - */ -(function() { - if (fb.login.util.environment.isNodeSdk()) { - var version = process['version']; - if (version === 'v0.10.22' || version === 'v0.10.23' || version === 'v0.10.24') { - /** - * The following duplicates much of `/lib/_stream_writable.js` at - * b922b5e90d2c14dd332b95827c2533e083df7e55, applying the fix for - * https://github.com/joyent/node/issues/6506. Note that this fix also - * needs to be applied to `Duplex.prototype.write()` (in - * `/lib/_stream_duplex.js`) as well. - */ - var Writable = require('_stream_writable'); - - Writable['prototype']['write'] = function(chunk, encoding, cb) { - var state = this['_writableState']; - var ret = false; - - if (typeof encoding === 'function') { - cb = encoding; - encoding = null; - } - - if (Buffer['isBuffer'](chunk)) - encoding = 'buffer'; - else if (!encoding) - encoding = state['defaultEncoding']; - - if (typeof cb !== 'function') - cb = function() {}; - - if (state['ended']) - writeAfterEnd(this, state, cb); - else if (validChunk(this, state, chunk, cb)) - ret = writeOrBuffer(this, state, chunk, encoding, cb); - - return ret; - }; - - function writeAfterEnd(stream, state, cb) { - var er = new Error('write after end'); - // TODO: defer error events consistently everywhere, not just the cb - stream['emit']('error', er); - process['nextTick'](function() { - cb(er); - }); - } - - function validChunk(stream, state, chunk, cb) { - var valid = true; - if (!Buffer['isBuffer'](chunk) && - 'string' !== typeof chunk && - chunk !== null && - chunk !== undefined && - !state['objectMode']) { - var er = new TypeError('Invalid non-string/buffer chunk'); - stream['emit']('error', er); - process['nextTick'](function() { - cb(er); - }); - valid = false; - } - return valid; - } - - function writeOrBuffer(stream, state, chunk, encoding, cb) { - chunk = decodeChunk(state, chunk, encoding); - if (Buffer['isBuffer'](chunk)) - encoding = 'buffer'; - var len = state['objectMode'] ? 1 : chunk['length']; - - state['length'] += len; - - var ret = state['length'] < state['highWaterMark']; - // we must ensure that previous needDrain will not be reset to false. - if (!ret) - state['needDrain'] = true; - - if (state['writing']) - state['buffer']['push'](new WriteReq(chunk, encoding, cb)); - else - doWrite(stream, state, len, chunk, encoding, cb); - - return ret; - } - - function decodeChunk(state, chunk, encoding) { - if (!state['objectMode'] && - state['decodeStrings'] !== false && - typeof chunk === 'string') { - chunk = new Buffer(chunk, encoding); - } - return chunk; - } - - /** - * @constructor - */ - function WriteReq(chunk, encoding, cb) { - this['chunk'] = chunk; - this['encoding'] = encoding; - this['callback'] = cb; - } - - function doWrite(stream, state, len, chunk, encoding, cb) { - state['writelen'] = len; - state['writecb'] = cb; - state['writing'] = true; - state['sync'] = true; - stream['_write'](chunk, encoding, state['onwrite']); - state['sync'] = false; - } - - var Duplex = require('_stream_duplex'); - Duplex['prototype']['write'] = Writable['prototype']['write']; - } - } -})(); diff --git a/src/database/js-client/core/util/OnlineMonitor.js b/src/database/js-client/core/util/OnlineMonitor.js deleted file mode 100644 index 7ac6b8a21e4..00000000000 --- a/src/database/js-client/core/util/OnlineMonitor.js +++ /dev/null @@ -1,78 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.util.OnlineMonitor'); -goog.require('fb.core.util'); -goog.require('fb.core.util.EventEmitter'); -goog.require('fb.login.util.environment'); - - -/** - * Monitors online state (as reported by window.online/offline events). - * - * The expectation is that this could have many false positives (thinks we are online - * when we're not), but no false negatives. So we can safely use it to determine when - * we definitely cannot reach the internet. - * - * @extends {fb.core.util.EventEmitter} - */ -fb.core.util.OnlineMonitor = goog.defineClass(fb.core.util.EventEmitter, { - constructor: function() { - fb.core.util.EventEmitter.call(this, ['online']); - this.online_ = true; - - // We've had repeated complaints that Cordova apps can get stuck "offline", e.g. - // https://forum.ionicframework.com/t/firebase-connection-is-lost-and-never-come-back/43810 - // It would seem that the 'online' event does not always fire consistently. So we disable it - // for Cordova. - if (typeof window !== 'undefined' && - typeof window.addEventListener !== 'undefined' && - !fb.login.util.environment.isMobileCordova()) { - var self = this; - window.addEventListener('online', function() { - if (!self.online_) { - self.online_ = true; - self.trigger('online', true); - } - }, false); - - window.addEventListener('offline', function() { - if (self.online_) { - self.online_ = false; - self.trigger('online', false); - } - }, false); - } - }, - - /** - * @param {!string} eventType - * @return {Array.} - */ - getInitialEvent: function(eventType) { - fb.core.util.assert(eventType === 'online', 'Unknown event type: ' + eventType); - return [this.online_]; - }, - - /** - * @return {boolean} - */ - currentlyOnline: function() { - return this.online_; - } -}); // end fb.core.util.OnlineMonitor - - -goog.addSingletonGetter(fb.core.util.OnlineMonitor); diff --git a/src/database/js-client/core/util/Path.js b/src/database/js-client/core/util/Path.js deleted file mode 100644 index d4769c514a5..00000000000 --- a/src/database/js-client/core/util/Path.js +++ /dev/null @@ -1,333 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.util.Path'); -goog.provide('fb.core.util.ValidationPath'); - -goog.require('fb.core.util'); -goog.require('fb.util.utf8'); -goog.require('goog.string'); - - -/** - * An immutable object representing a parsed path. It's immutable so that you - * can pass them around to other functions without worrying about them changing - * it. - */ -fb.core.util.Path = goog.defineClass(null, { - /** - * @param {string|Array.} pathOrString Path string to parse, - * or another path, or the raw tokens array - * @param {number=} opt_pieceNum - */ - constructor: function(pathOrString, opt_pieceNum) { - if (arguments.length == 1) { - this.pieces_ = pathOrString.split('/'); - - // Remove empty pieces. - var copyTo = 0; - for (var i = 0; i < this.pieces_.length; i++) { - if (this.pieces_[i].length > 0) { - this.pieces_[copyTo] = this.pieces_[i]; - copyTo++; - } - } - this.pieces_.length = copyTo; - - this.pieceNum_ = 0; - } else { - this.pieces_ = pathOrString; - this.pieceNum_ = opt_pieceNum; - } - }, - - getFront: function() { - if (this.pieceNum_ >= this.pieces_.length) - return null; - - return this.pieces_[this.pieceNum_]; - }, - - /** - * @return {number} The number of segments in this path - */ - getLength: function() { - return this.pieces_.length - this.pieceNum_; - }, - - /** - * @return {!fb.core.util.Path} - */ - popFront: function() { - var pieceNum = this.pieceNum_; - if (pieceNum < this.pieces_.length) { - pieceNum++; - } - return new fb.core.util.Path(this.pieces_, pieceNum); - }, - - /** - * @return {?string} - */ - getBack: function() { - if (this.pieceNum_ < this.pieces_.length) - return this.pieces_[this.pieces_.length - 1]; - - return null; - }, - - toString: function() { - var pathString = ''; - for (var i = this.pieceNum_; i < this.pieces_.length; i++) { - if (this.pieces_[i] !== '') - pathString += '/' + this.pieces_[i]; - } - - return pathString || '/'; - }, - - toUrlEncodedString: function() { - var pathString = ''; - for (var i = this.pieceNum_; i < this.pieces_.length; i++) { - if (this.pieces_[i] !== '') - pathString += '/' + goog.string.urlEncode(this.pieces_[i]); - } - - return pathString || '/'; - }, - - /** - * Shallow copy of the parts of the path. - * - * @param {number=} opt_begin - * @return {!Array} - */ - slice: function(opt_begin) { - var begin = opt_begin || 0; - return this.pieces_.slice(this.pieceNum_ + begin); - }, - - /** - * @return {?fb.core.util.Path} - */ - parent: function() { - if (this.pieceNum_ >= this.pieces_.length) - return null; - - var pieces = []; - for (var i = this.pieceNum_; i < this.pieces_.length - 1; i++) - pieces.push(this.pieces_[i]); - - return new fb.core.util.Path(pieces, 0); - }, - - /** - * @param {string|!fb.core.util.Path} childPathObj - * @return {!fb.core.util.Path} - */ - child: function(childPathObj) { - var pieces = []; - for (var i = this.pieceNum_; i < this.pieces_.length; i++) - pieces.push(this.pieces_[i]); - - if (childPathObj instanceof fb.core.util.Path) { - for (i = childPathObj.pieceNum_; i < childPathObj.pieces_.length; i++) { - pieces.push(childPathObj.pieces_[i]); - } - } else { - var childPieces = childPathObj.split('/'); - for (i = 0; i < childPieces.length; i++) { - if (childPieces[i].length > 0) - pieces.push(childPieces[i]); - } - } - - return new fb.core.util.Path(pieces, 0); - }, - - /** - * @return {boolean} True if there are no segments in this path - */ - isEmpty: function() { - return this.pieceNum_ >= this.pieces_.length; - }, - - statics: { - /** - * @param {!fb.core.util.Path} outerPath - * @param {!fb.core.util.Path} innerPath - * @return {!fb.core.util.Path} The path from outerPath to innerPath - */ - relativePath: function(outerPath, innerPath) { - var outer = outerPath.getFront(), inner = innerPath.getFront(); - if (outer === null) { - return innerPath; - } else if (outer === inner) { - return fb.core.util.Path.relativePath(outerPath.popFront(), - innerPath.popFront()); - } else { - throw new Error('INTERNAL ERROR: innerPath (' + innerPath + ') is not within ' + - 'outerPath (' + outerPath + ')'); - } - }, - /** - * @param {!fb.core.util.Path} left - * @param {!fb.core.util.Path} right - * @return {number} -1, 0, 1 if left is less, equal, or greater than the right. - */ - comparePaths: function(left, right) { - var leftKeys = left.slice(); - var rightKeys = right.slice(); - for (var i = 0; i < leftKeys.length && i < rightKeys.length; i++) { - var cmp = fb.core.util.nameCompare(leftKeys[i], rightKeys[i]); - if (cmp !== 0) return cmp; - } - if (leftKeys.length === rightKeys.length) return 0; - return (leftKeys.length < rightKeys.length) ? -1 : 1; - } - }, - - /** - * - * @param {fb.core.util.Path} other - * @return {boolean} true if paths are the same. - */ - equals: function(other) { - if (this.getLength() !== other.getLength()) { - return false; - } - - for (var i = this.pieceNum_, j = other.pieceNum_; i <= this.pieces_.length; i++, j++) { - if (this.pieces_[i] !== other.pieces_[j]) { - return false; - } - } - - return true; - }, - - /** - * - * @param {!fb.core.util.Path} other - * @return {boolean} True if this path is a parent (or the same as) other - */ - contains: function(other) { - var i = this.pieceNum_; - var j = other.pieceNum_; - if (this.getLength() > other.getLength()) { - return false; - } - while (i < this.pieces_.length) { - if (this.pieces_[i] !== other.pieces_[j]) { - return false; - } - ++i; - ++j; - } - return true; - } -}); // end fb.core.util.Path - - -/** - * Singleton to represent an empty path - * - * @const - */ -fb.core.util.Path.Empty = new fb.core.util.Path(''); - - -/** - * Dynamic (mutable) path used to count path lengths. - * - * This class is used to efficiently check paths for valid - * length (in UTF8 bytes) and depth (used in path validation). - * - * Throws Error exception if path is ever invalid. - * - * The definition of a path always begins with '/'. - */ -fb.core.util.ValidationPath = goog.defineClass(null, { - /** - * @param {!fb.core.util.Path} path Initial Path. - * @param {string} errorPrefix Prefix for any error messages. - */ - constructor: function(path, errorPrefix) { - /** @type {!Array} */ - this.parts_ = path.slice(); - /** @type {number} Initialize to number of '/' chars needed in path. */ - this.byteLength_ = Math.max(1, this.parts_.length); - /** @type {string} */ - this.errorPrefix_ = errorPrefix; - - for (var i = 0; i < this.parts_.length; i++) { - this.byteLength_ += fb.util.utf8.stringLength(this.parts_[i]); - } - this.checkValid_(); - }, - - statics: { - /** @const {number} Maximum key depth. */ - MAX_PATH_DEPTH: 32, - /** @const {number} Maximum number of (UTF8) bytes in a Firebase path. */ - MAX_PATH_LENGTH_BYTES: 768 - }, - - /** @param {string} child */ - push: function(child) { - // Count the needed '/' - if (this.parts_.length > 0) { - this.byteLength_ += 1; - } - this.parts_.push(child); - this.byteLength_ += fb.util.utf8.stringLength(child); - this.checkValid_(); - }, - - pop: function() { - var last = this.parts_.pop(); - this.byteLength_ -= fb.util.utf8.stringLength(last); - // Un-count the previous '/' - if (this.parts_.length > 0) { - this.byteLength_ -= 1; - } - }, - - checkValid_: function() { - if (this.byteLength_ > fb.core.util.ValidationPath.MAX_PATH_LENGTH_BYTES) { - throw new Error(this.errorPrefix_ + 'has a key path longer than ' + - fb.core.util.ValidationPath.MAX_PATH_LENGTH_BYTES + ' bytes (' + - this.byteLength_ + ').'); - } - if (this.parts_.length > fb.core.util.ValidationPath.MAX_PATH_DEPTH) { - throw new Error(this.errorPrefix_ + 'path specified exceeds the maximum depth that can be written (' + - fb.core.util.ValidationPath.MAX_PATH_DEPTH + - ') or object contains a cycle ' + this.toErrorString()); - } - }, - - /** - * String for use in error messages - uses '.' notation for path. - * - * @return {string} - */ - toErrorString: function() { - if (this.parts_.length == 0) { - return ''; - } - return 'in property \'' + this.parts_.join('.') + '\''; - } - -}); // end fb.core.util.validation.ValidationPath diff --git a/src/database/js-client/core/util/ServerValues.js b/src/database/js-client/core/util/ServerValues.js deleted file mode 100644 index cefe1228be9..00000000000 --- a/src/database/js-client/core/util/ServerValues.js +++ /dev/null @@ -1,99 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.util.ServerValues'); - - -/** - * Generate placeholders for deferred values. - * @param {?Object} values - * @return {!Object} - */ -fb.core.util.ServerValues.generateWithValues = function(values) { - values = values || {}; - values['timestamp'] = values['timestamp'] || new Date().getTime(); - return values; -}; - - -/** - * Value to use when firing local events. When writing server values, fire - * local events with an approximate value, otherwise return value as-is. - * @param {(Object|string|number|boolean)} value - * @param {!Object} serverValues - * @return {!(string|number|boolean)} - */ -fb.core.util.ServerValues.resolveDeferredValue = function(value, serverValues) { - if (!value || (typeof value !== 'object')) { - return /** @type {(string|number|boolean)} */ (value); - } else { - fb.core.util.assert('.sv' in value, 'Unexpected leaf node or priority contents'); - return serverValues[value['.sv']]; - } -}; - - -/** - * Recursively replace all deferred values and priorities in the tree with the - * specified generated replacement values. - * @param {!fb.core.SparseSnapshotTree} tree - * @param {!Object} serverValues - * @return {!fb.core.SparseSnapshotTree} - */ -fb.core.util.ServerValues.resolveDeferredValueTree = function(tree, serverValues) { - var resolvedTree = new fb.core.SparseSnapshotTree(); - tree.forEachTree(new fb.core.util.Path(''), function(path, node) { - resolvedTree.remember(path, fb.core.util.ServerValues.resolveDeferredValueSnapshot(node, serverValues)); - }); - return resolvedTree; -}; - - -/** - * Recursively replace all deferred values and priorities in the node with the - * specified generated replacement values. If there are no server values in the node, - * it'll be returned as-is. - * @param {!fb.core.snap.Node} node - * @param {!Object} serverValues - * @return {!fb.core.snap.Node} - */ -fb.core.util.ServerValues.resolveDeferredValueSnapshot = function(node, serverValues) { - var rawPri = /** @type {Object|boolean|null|number|string} */ (node.getPriority().val()), - priority = fb.core.util.ServerValues.resolveDeferredValue(rawPri, serverValues), - newNode; - - if (node.isLeafNode()) { - var leafNode = /** @type {!fb.core.snap.LeafNode} */ (node); - var value = fb.core.util.ServerValues.resolveDeferredValue(leafNode.getValue(), serverValues); - if (value !== leafNode.getValue() || priority !== leafNode.getPriority().val()) { - return new fb.core.snap.LeafNode(value, fb.core.snap.NodeFromJSON(priority)); - } else { - return node; - } - } else { - var childrenNode = /** @type {!fb.core.snap.ChildrenNode} */ (node); - newNode = childrenNode; - if (priority !== childrenNode.getPriority().val()) { - newNode = newNode.updatePriority(new fb.core.snap.LeafNode(priority)); - } - childrenNode.forEachChild(fb.core.snap.PriorityIndex, function(childName, childNode) { - var newChildNode = fb.core.util.ServerValues.resolveDeferredValueSnapshot(childNode, serverValues); - if (newChildNode !== childNode) { - newNode = newNode.updateImmediateChild(childName, newChildNode); - } - }); - return newNode; - } -}; diff --git a/src/database/js-client/core/util/SortedMap.js b/src/database/js-client/core/util/SortedMap.js deleted file mode 100644 index 3a9108e02bd..00000000000 --- a/src/database/js-client/core/util/SortedMap.js +++ /dev/null @@ -1,764 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.util.SortedMap'); - -goog.require('goog.array'); - - -/** - * @fileoverview Implementation of an immutable SortedMap using a Left-leaning - * Red-Black Tree, adapted from the implementation in Mugs - * (http://mads379.github.com/mugs/) by Mads Hartmann Jensen - * (mads379@gmail.com). - * - * Original paper on Left-leaning Red-Black Trees: - * http://www.cs.princeton.edu/~rs/talks/LLRB/LLRB.pdf - * - * Invariant 1: No red node has a red child - * Invariant 2: Every leaf path has the same number of black nodes - * Invariant 3: Only the left child can be red (left leaning) - */ - - -// TODO: There are some improvements I'd like to make to improve memory / perf: -// * Create two prototypes, LLRedNode and LLBlackNode, instead of storing a -// color property in every node. -// TODO: It would also be good (and possibly necessary) to create a base -// interface for LLRBNode and LLRBEmptyNode. - - -/** @typedef {function(!Object, !Object)} */ -fb.Comparator; - - -/** - * An immutable sorted map implementation, based on a Left-leaning Red-Black - * tree. - */ -fb.core.util.SortedMap = goog.defineClass(null, { - /** - * @template K, V - * @param {function(K, K):number} comparator Key comparator. - * @param {fb.LLRBNode=} opt_root (Optional) Root node for the map. - */ - constructor: function(comparator, opt_root) { - /** @private */ - this.comparator_ = comparator; - - /** @private */ - this.root_ = opt_root ? opt_root : fb.core.util.SortedMap.EMPTY_NODE_; - }, - - /** - * Returns a copy of the map, with the specified key/value added or replaced. - * (TODO: We should perhaps rename this method to 'put') - * - * @param {!K} key Key to be added. - * @param {!V} value Value to be added. - * @return {!fb.core.util.SortedMap.} New map, with item added. - */ - insert: function(key, value) { - return new fb.core.util.SortedMap( - this.comparator_, - this.root_.insert(key, value, this.comparator_) - .copy(null, null, fb.LLRBNode.BLACK, null, null)); - }, - - /** - * Returns a copy of the map, with the specified key removed. - * - * @param {!K} key The key to remove. - * @return {!fb.core.util.SortedMap.} New map, with item removed. - */ - remove: function(key) { - return new fb.core.util.SortedMap( - this.comparator_, - this.root_.remove(key, this.comparator_) - .copy(null, null, fb.LLRBNode.BLACK, null, null)); - }, - - /** - * Returns the value of the node with the given key, or null. - * - * @param {!K} key The key to look up. - * @return {?V} The value of the node with the given key, or null if the - * key doesn't exist. - */ - get: function(key) { - var cmp; - var node = this.root_; - while (!node.isEmpty()) { - cmp = this.comparator_(key, node.key); - if (cmp === 0) { - return node.value; - } else if (cmp < 0) { - node = node.left; - } else if (cmp > 0) { - node = node.right; - } - } - return null; - }, - - /** - * Returns the key of the item *before* the specified key, or null if key is the first item. - * @param {K} key The key to find the predecessor of - * @return {?K} The predecessor key. - */ - getPredecessorKey: function(key) { - var cmp, node = this.root_, rightParent = null; - while (!node.isEmpty()) { - cmp = this.comparator_(key, node.key); - if (cmp === 0) { - if (!node.left.isEmpty()) { - node = node.left; - while (!node.right.isEmpty()) - node = node.right; - return node.key; - } else if (rightParent) { - return rightParent.key; - } else { - return null; // first item. - } - } else if (cmp < 0) { - node = node.left; - } else if (cmp > 0) { - rightParent = node; - node = node.right; - } - } - - throw new Error('Attempted to find predecessor key for a nonexistent key. What gives?'); - }, - - /** - * @return {boolean} True if the map is empty. - */ - isEmpty: function() { - return this.root_.isEmpty(); - }, - - /** - * @return {number} The total number of nodes in the map. - */ - count: function() { - return this.root_.count(); - }, - - /** - * @return {?K} The minimum key in the map. - */ - minKey: function() { - return this.root_.minKey(); - }, - - /** - * @return {?K} The maximum key in the map. - */ - maxKey: function() { - return this.root_.maxKey(); - }, - - /** - * Traverses the map in key order and calls the specified action function - * for each key/value pair. - * - * @param {function(!K, !V):*} action Callback function to be called - * for each key/value pair. If action returns true, traversal is aborted. - * @return {*} The first truthy value returned by action, or the last falsey - * value returned by action - */ - inorderTraversal: function(action) { - return this.root_.inorderTraversal(action); - }, - - /** - * Traverses the map in reverse key order and calls the specified action function - * for each key/value pair. - * - * @param {function(!Object, !Object)} action Callback function to be called - * for each key/value pair. If action returns true, traversal is aborted. - * @return {*} True if the traversal was aborted. - */ - reverseTraversal: function(action) { - return this.root_.reverseTraversal(action); - }, - - /** - * Returns an iterator over the SortedMap. - * @template T - * @param {(function(K, V):T)=} opt_resultGenerator - * @return {fb.core.util.SortedMapIterator.} The iterator. - */ - getIterator: function(opt_resultGenerator) { - return new fb.core.util.SortedMapIterator(this.root_, - null, - this.comparator_, - false, - opt_resultGenerator); - }, - - getIteratorFrom: function(key, opt_resultGenerator) { - return new fb.core.util.SortedMapIterator(this.root_, - key, - this.comparator_, - false, - opt_resultGenerator); - }, - - getReverseIteratorFrom: function(key, opt_resultGenerator) { - return new fb.core.util.SortedMapIterator(this.root_, - key, - this.comparator_, - true, - opt_resultGenerator); - }, - - getReverseIterator: function(opt_resultGenerator) { - return new fb.core.util.SortedMapIterator(this.root_, - null, - this.comparator_, - true, - opt_resultGenerator); - } -}); // end fb.core.util.SortedMap - - -/** - * An iterator over an LLRBNode. - */ -fb.core.util.SortedMapIterator = goog.defineClass(null, { - /** - * @template K, V, T - * @param {fb.LLRBNode|fb.LLRBEmptyNode} node Node to iterate. - * @param {?K} startKey - * @param {function(K, K): number} comparator - * @param {boolean} isReverse Whether or not to iterate in reverse - * @param {(function(K, V):T)=} opt_resultGenerator - */ - constructor: function(node, startKey, comparator, isReverse, opt_resultGenerator) { - /** @private - * @type {?function(!K, !V): T} - */ - this.resultGenerator_ = opt_resultGenerator || null; - this.isReverse_ = isReverse; - - /** @private - * @type {Array.} - */ - this.nodeStack_ = []; - - var cmp = 1; - while (!node.isEmpty()) { - cmp = startKey ? comparator(node.key, startKey) : 1; - // flip the comparison if we're going in reverse - if (isReverse) cmp *= -1; - - if (cmp < 0) { - // This node is less than our start key. ignore it - if (this.isReverse_) { - node = node.left; - } else { - node = node.right; - } - } else if (cmp === 0) { - // This node is exactly equal to our start key. Push it on the stack, but stop iterating; - this.nodeStack_.push(node); - break; - } else { - // This node is greater than our start key, add it to the stack and move to the next one - this.nodeStack_.push(node); - if (this.isReverse_) { - node = node.right; - } else { - node = node.left; - } - } - } - }, - - getNext: function() { - if (this.nodeStack_.length === 0) - return null; - - var node = this.nodeStack_.pop(), result; - if (this.resultGenerator_) - result = this.resultGenerator_(node.key, node.value); - else - result = {key: node.key, value: node.value}; - - if (this.isReverse_) { - node = node.left; - while (!node.isEmpty()) { - this.nodeStack_.push(node); - node = node.right; - } - } else { - node = node.right; - while (!node.isEmpty()) { - this.nodeStack_.push(node); - node = node.left; - } - } - - return result; - }, - - hasNext: function() { - return this.nodeStack_.length > 0; - }, - - peek: function() { - if (this.nodeStack_.length === 0) - return null; - - var node = goog.array.peek(this.nodeStack_); - if (this.resultGenerator_) { - return this.resultGenerator_(node.key, node.value); - } else { - return {key: node.key, value: node.value}; - } - } -}); // end fb.core.util.SortedMapIterator - - -/** - * Represents a node in a Left-leaning Red-Black tree. - */ -fb.LLRBNode = goog.defineClass(null, { - /** - * @template K, V - * @param {!K} key Key associated with this node. - * @param {!V} value Value associated with this node. - * @param {?boolean} color Whether this node is red. - * @param {?(fb.LLRBNode|fb.LLRBEmptyNode)=} opt_left Left child. - * @param {?(fb.LLRBNode|fb.LLRBEmptyNode)=} opt_right Right child. - */ - constructor: function(key, value, color, opt_left, opt_right) { - this.key = key; - this.value = value; - this.color = color != null ? color : fb.LLRBNode.RED; - this.left = opt_left != null ? opt_left : fb.core.util.SortedMap.EMPTY_NODE_; - this.right = opt_right != null ? opt_right : fb.core.util.SortedMap.EMPTY_NODE_; - }, - - statics: { - /** - * @const - * This constant and BLACK is visible only for the snap.js hinze construction. We - * should probably create a SortedMapBuilder like the java client at some point - * so that this can be better encapsulated and generic. - */ - RED: true, - - /** - * @const - */ - BLACK: false - }, - - /** - * Returns a copy of the current node, optionally replacing pieces of it. - * - * @param {?K} key New key for the node, or null. - * @param {?V} value New value for the node, or null. - * @param {?boolean} color New color for the node, or null. - * @param {?fb.LLRBNode|fb.LLRBEmptyNode} left New left child for the node, or null. - * @param {?fb.LLRBNode|fb.LLRBEmptyNode} right New right child for the node, or null. - * @return {!fb.LLRBNode} The node copy. - */ - copy: function(key, value, color, left, right) { - return new fb.LLRBNode( - (key != null) ? key : this.key, - (value != null) ? value : this.value, - (color != null) ? color : this.color, - (left != null) ? left : this.left, - (right != null) ? right : this.right); - }, - - /** - * @return {number} The total number of nodes in the tree. - */ - count: function() { - return this.left.count() + 1 + this.right.count(); - }, - - /** - * @return {boolean} True if the tree is empty. - */ - isEmpty: function() { - return false; - }, - - /** - * Traverses the tree in key order and calls the specified action function - * for each node. - * - * @param {function(!K, !V):*} action Callback function to be called for each - * node. If it returns true, traversal is aborted. - * @return {*} The first truthy value returned by action, or the last falsey - * value returned by action - */ - inorderTraversal: function(action) { - return this.left.inorderTraversal(action) || - action(this.key, this.value) || - this.right.inorderTraversal(action); - }, - - /** - * Traverses the tree in reverse key order and calls the specified action function - * for each node. - * - * @param {function(!Object, !Object)} action Callback function to be called for each - * node. If it returns true, traversal is aborted. - * @return {*} True if traversal was aborted. - */ - reverseTraversal: function(action) { - return this.right.reverseTraversal(action) || - action(this.key, this.value) || - this.left.reverseTraversal(action); - }, - - /** - * @return {!Object} The minimum node in the tree. - * @private - */ - min_: function() { - if (this.left.isEmpty()) { - return this; - } else { - return this.left.min_(); - } - }, - - /** - * @return {!K} The maximum key in the tree. - */ - minKey: function() { - return this.min_().key; - }, - - /** - * @return {!K} The maximum key in the tree. - */ - maxKey: function() { - if (this.right.isEmpty()) { - return this.key; - } else { - return this.right.maxKey(); - } - }, - - /** - * - * @param {!Object} key Key to insert. - * @param {!Object} value Value to insert. - * @param {fb.Comparator} comparator Comparator. - * @return {!fb.LLRBNode} New tree, with the key/value added. - */ - insert: function(key, value, comparator) { - var cmp, n; - n = this; - cmp = comparator(key, n.key); - if (cmp < 0) { - n = n.copy(null, null, null, n.left.insert(key, value, comparator), null); - } else if (cmp === 0) { - n = n.copy(null, value, null, null, null); - } else { - n = n.copy(null, null, null, null, n.right.insert(key, value, comparator)); - } - return n.fixUp_(); - }, - - /** - * @private - * @return {!fb.LLRBNode|fb.LLRBEmptyNode} New tree, with the minimum key removed. - */ - removeMin_: function() { - var n; - if (this.left.isEmpty()) { - return fb.core.util.SortedMap.EMPTY_NODE_; - } - n = this; - if (!n.left.isRed_() && !n.left.left.isRed_()) - n = n.moveRedLeft_(); - n = n.copy(null, null, null, n.left.removeMin_(), null); - return n.fixUp_(); - }, - - /** - * @param {!Object} key The key of the item to remove. - * @param {fb.Comparator} comparator Comparator. - * @return {!fb.LLRBNode|fb.LLRBEmptyNode} New tree, with the specified item removed. - */ - remove: function(key, comparator) { - var n, smallest; - n = this; - if (comparator(key, n.key) < 0) { - if (!n.left.isEmpty() && !n.left.isRed_() && !n.left.left.isRed_()) { - n = n.moveRedLeft_(); - } - n = n.copy(null, null, null, n.left.remove(key, comparator), null); - } else { - if (n.left.isRed_()) n = n.rotateRight_(); - if (!n.right.isEmpty() && !n.right.isRed_() && !n.right.left.isRed_()) { - n = n.moveRedRight_(); - } - if (comparator(key, n.key) === 0) { - if (n.right.isEmpty()) { - return fb.core.util.SortedMap.EMPTY_NODE_; - } else { - smallest = n.right.min_(); - n = n.copy(smallest.key, smallest.value, null, null, - n.right.removeMin_()); - } - } - n = n.copy(null, null, null, null, n.right.remove(key, comparator)); - } - return n.fixUp_(); - }, - - /** - * @private - * @return {boolean} Whether this is a RED node. - */ - isRed_: function() { - return this.color; - }, - - /** - * @private - * @return {!fb.LLRBNode} New tree after performing any needed rotations. - */ - fixUp_: function() { - var n = this; - if (n.right.isRed_() && !n.left.isRed_()) n = n.rotateLeft_(); - if (n.left.isRed_() && n.left.left.isRed_()) n = n.rotateRight_(); - if (n.left.isRed_() && n.right.isRed_()) n = n.colorFlip_(); - return n; - }, - - /** - * @private - * @return {!fb.LLRBNode} New tree, after moveRedLeft. - */ - moveRedLeft_: function() { - var n = this.colorFlip_(); - if (n.right.left.isRed_()) { - n = n.copy(null, null, null, null, n.right.rotateRight_()); - n = n.rotateLeft_(); - n = n.colorFlip_(); - } - return n; - }, - - /** - * @private - * @return {!fb.LLRBNode} New tree, after moveRedRight. - */ - moveRedRight_: function() { - var n = this.colorFlip_(); - if (n.left.left.isRed_()) { - n = n.rotateRight_(); - n = n.colorFlip_(); - } - return n; - }, - - /** - * @private - * @return {!fb.LLRBNode} New tree, after rotateLeft. - */ - rotateLeft_: function() { - var nl; - nl = this.copy(null, null, fb.LLRBNode.RED, null, this.right.left); - return this.right.copy(null, null, this.color, nl, null); - }, - - /** - * @private - * @return {!fb.LLRBNode} New tree, after rotateRight. - */ - rotateRight_: function() { - var nr; - nr = this.copy(null, null, fb.LLRBNode.RED, this.left.right, null); - return this.left.copy(null, null, this.color, null, nr); - }, - - /** - * @private - * @return {!fb.LLRBNode} New tree, after colorFlip. - */ - colorFlip_: function() { - var left, right; - left = this.left.copy(null, null, !this.left.color, null, null); - right = this.right.copy(null, null, !this.right.color, null, null); - return this.copy(null, null, !this.color, left, right); - }, - - /** - * For testing. - * - * @private - * @return {boolean} True if all is well. - */ - checkMaxDepth_: function() { - var blackDepth; - blackDepth = this.check_(); - if (Math.pow(2.0, blackDepth) <= this.count() + 1) { - return true; - } else { - return false; - } - }, - - /** - * @private - * @return {number} Not sure what this returns exactly. :-). - */ - check_: function() { - var blackDepth; - if (this.isRed_() && this.left.isRed_()) { - throw new Error('Red node has red child(' + this.key + ',' + - this.value + ')'); - } - if (this.right.isRed_()) { - throw new Error('Right child of (' + this.key + ',' + - this.value + ') is red'); - } - blackDepth = this.left.check_(); - if (blackDepth !== this.right.check_()) { - throw new Error('Black depths differ'); - } else { - return blackDepth + (this.isRed_() ? 0 : 1); - } - } -}); // end fb.LLRBNode - - -/** - * Represents an empty node (a leaf node in the Red-Black Tree). - */ -fb.LLRBEmptyNode = goog.defineClass(null, { - /** - * @template K, V - */ - constructor: function() { - }, - - /** - * Returns a copy of the current node. - * - * @return {!fb.LLRBEmptyNode} The node copy. - */ - copy: function() { - return this; - }, - - /** - * Returns a copy of the tree, with the specified key/value added. - * - * @param {!K} key Key to be added. - * @param {!V} value Value to be added. - * @param {fb.Comparator} comparator Comparator. - * @return {!fb.LLRBNode} New tree, with item added. - */ - insert: function(key, value, comparator) { - return new fb.LLRBNode(key, value, null); - }, - - /** - * Returns a copy of the tree, with the specified key removed. - * - * @param {!K} key The key to remove. - * @return {!fb.LLRBEmptyNode} New tree, with item removed. - */ - remove: function(key, comparator) { - return this; - }, - - /** - * @return {number} The total number of nodes in the tree. - */ - count: function() { - return 0; - }, - - /** - * @return {boolean} True if the tree is empty. - */ - isEmpty: function() { - return true; - }, - - /** - * Traverses the tree in key order and calls the specified action function - * for each node. - * - * @param {function(!K, !V)} action Callback function to be called for each - * node. If it returns true, traversal is aborted. - * @return {boolean} True if traversal was aborted. - */ - inorderTraversal: function(action) { - return false; - }, - - /** - * Traverses the tree in reverse key order and calls the specified action function - * for each node. - * - * @param {function(!K, !V)} action Callback function to be called for each - * node. If it returns true, traversal is aborted. - * @return {boolean} True if traversal was aborted. - */ - reverseTraversal: function(action) { - return false; - }, - - /** - * @return {null} - */ - minKey: function() { - return null; - }, - - /** - * @return {null} - */ - maxKey: function() { - return null; - }, - - /** - * @private - * @return {number} Not sure what this returns exactly. :-). - */ - check_: function() { return 0; }, - - /** - * @private - * @return {boolean} Whether this node is red. - */ - isRed_: function() { return false; } -}); // end fb.LLRBEmptyNode - - -/** - * Always use the same empty node, to reduce memory. - * @private - * @const - */ -fb.core.util.SortedMap.EMPTY_NODE_ = new fb.LLRBEmptyNode(); diff --git a/src/database/js-client/core/util/Tree.js b/src/database/js-client/core/util/Tree.js deleted file mode 100644 index cc4828f60bb..00000000000 --- a/src/database/js-client/core/util/Tree.js +++ /dev/null @@ -1,241 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.util.Tree'); - -goog.require('fb.core.util'); -goog.require('fb.core.util.Path'); -goog.require('fb.util.obj'); -goog.require('goog.object'); - - -/** - * Node in a Tree. - */ -fb.core.util.TreeNode = goog.defineClass(null, { - constructor: function() { - // TODO: Consider making accessors that create children and value lazily or - // separate Internal / Leaf 'types'. - this.children = { }; - this.childCount = 0; - this.value = null; - } -}); // end fb.core.util.TreeNode - - -/** - * A light-weight tree, traversable by path. Nodes can have both values and children. - * Nodes are not enumerated (by forEachChild) unless they have a value or non-empty - * children. - */ -fb.core.util.Tree = goog.defineClass(null, { - /** - * @template T - * @param {string=} opt_name Optional name of the node. - * @param {fb.core.util.Tree=} opt_parent Optional parent node. - * @param {fb.core.util.TreeNode=} opt_node Optional node to wrap. - */ - constructor: function(opt_name, opt_parent, opt_node) { - this.name_ = opt_name ? opt_name : ''; - this.parent_ = opt_parent ? opt_parent : null; - this.node_ = opt_node ? opt_node : new fb.core.util.TreeNode(); - }, - - /** - * Returns a sub-Tree for the given path. - * - * @param {!(string|fb.core.util.Path)} pathObj Path to look up. - * @return {!fb.core.util.Tree.} Tree for path. - */ - subTree: function(pathObj) { - // TODO: Require pathObj to be Path? - var path = (pathObj instanceof fb.core.util.Path) ? - pathObj : new fb.core.util.Path(pathObj); - var child = this, next; - while ((next = path.getFront()) !== null) { - var childNode = fb.util.obj.get(child.node_.children, next) || new fb.core.util.TreeNode(); - child = new fb.core.util.Tree(next, child, childNode); - path = path.popFront(); - } - - return child; - }, - - /** - * Returns the data associated with this tree node. - * - * @return {?T} The data or null if no data exists. - */ - getValue: function() { - return this.node_.value; - }, - - /** - * Sets data to this tree node. - * - * @param {!T} value Value to set. - */ - setValue: function(value) { - fb.core.util.assert(typeof value !== 'undefined', 'Cannot set value to undefined'); - this.node_.value = value; - this.updateParents_(); - }, - - /** - * Clears the contents of the tree node (its value and all children). - */ - clear: function() { - this.node_.value = null; - this.node_.children = { }; - this.node_.childCount = 0; - this.updateParents_(); - }, - - /** - * @return {boolean} Whether the tree has any children. - */ - hasChildren: function() { - return this.node_.childCount > 0; - }, - - /** - * @return {boolean} Whether the tree is empty (no value or children). - */ - isEmpty: function() { - return this.getValue() === null && !this.hasChildren(); - }, - - /** - * Calls action for each child of this tree node. - * - * @param {function(!fb.core.util.Tree.)} action Action to be called for each child. - */ - forEachChild: function(action) { - var self = this; - goog.object.forEach(this.node_.children, function(childTree, child) { - action(new fb.core.util.Tree(child, self, childTree)); - }); - }, - - /** - * Does a depth-first traversal of this node's descendants, calling action for each one. - * - * @param {function(!fb.core.util.Tree.)} action Action to be called for each child. - * @param {boolean=} opt_includeSelf Whether to call action on this node as well. Defaults to - * false. - * @param {boolean=} opt_childrenFirst Whether to call action on children before calling it on - * parent. - */ - forEachDescendant: function(action, opt_includeSelf, opt_childrenFirst) { - if (opt_includeSelf && !opt_childrenFirst) - action(this); - - this.forEachChild(function(child) { - child.forEachDescendant(action, /*opt_includeSelf=*/true, opt_childrenFirst); - }); - - if (opt_includeSelf && opt_childrenFirst) - action(this); - }, - - /** - * Calls action on each ancestor node. - * - * @param {function(!fb.core.util.Tree.)} action Action to be called on each parent; return - * true to abort. - * @param {boolean=} opt_includeSelf Whether to call action on this node as well. - * @return {boolean} true if the action callback returned true. - */ - forEachAncestor: function(action, opt_includeSelf) { - var node = opt_includeSelf ? this : this.parent(); - while (node !== null) { - if (action(node)) { - return true; - } - node = node.parent(); - } - return false; - }, - - /** - * Does a depth-first traversal of this node's descendants. When a descendant with a value - * is found, action is called on it and traversal does not continue inside the node. - * Action is *not* called on this node. - * - * @param {function(!fb.core.util.Tree.)} action Action to be called for each child. - */ - forEachImmediateDescendantWithValue: function(action) { - this.forEachChild(function(child) { - if (child.getValue() !== null) - action(child); - else - child.forEachImmediateDescendantWithValue(action); - }); - }, - - /** - * @return {!fb.core.util.Path} The path of this tree node, as a Path. - */ - path: function() { - return new fb.core.util.Path(this.parent_ === null ? - this.name_ : this.parent_.path() + '/' + this.name_); - }, - - /** - * @return {string} The name of the tree node. - */ - name: function() { - return this.name_; - }, - - /** - * @return {?fb.core.util.Tree} The parent tree node, or null if this is the root of the tree. - */ - parent: function() { - return this.parent_; - }, - - /** - * Adds or removes this child from its parent based on whether it's empty or not. - * - * @private - */ - updateParents_: function() { - if (this.parent_ !== null) - this.parent_.updateChild_(this.name_, this); - }, - - /** - * Adds or removes the passed child to this tree node, depending on whether it's empty. - * - * @param {string} childName The name of the child to update. - * @param {!fb.core.util.Tree.} child The child to update. - * @private - */ - updateChild_: function(childName, child) { - var childEmpty = child.isEmpty(); - var childExists = fb.util.obj.contains(this.node_.children, childName); - if (childEmpty && childExists) { - delete (this.node_.children[childName]); - this.node_.childCount--; - this.updateParents_(); - } - else if (!childEmpty && !childExists) { - this.node_.children[childName] = child.node_; - this.node_.childCount++; - this.updateParents_(); - } - } -}); // end fb.core.util.Tree diff --git a/src/database/js-client/core/util/VisibilityMonitor.js b/src/database/js-client/core/util/VisibilityMonitor.js deleted file mode 100644 index 463de781fc7..00000000000 --- a/src/database/js-client/core/util/VisibilityMonitor.js +++ /dev/null @@ -1,75 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.util.VisibilityMonitor'); - -goog.require('fb.core.util'); -goog.require('fb.core.util.EventEmitter'); - - -/** - * @extends {fb.core.util.EventEmitter} - */ -fb.core.util.VisibilityMonitor = goog.defineClass(fb.core.util.EventEmitter, { - constructor: function() { - fb.core.util.EventEmitter.call(this, ['visible']); - var hidden, visibilityChange; - if (typeof document !== 'undefined' && typeof document.addEventListener !== 'undefined') { - if (typeof document['hidden'] !== 'undefined') { - // Opera 12.10 and Firefox 18 and later support - visibilityChange = 'visibilitychange'; - hidden = 'hidden'; - } else if (typeof document['mozHidden'] !== 'undefined') { - visibilityChange = 'mozvisibilitychange'; - hidden = 'mozHidden'; - } else if (typeof document['msHidden'] !== 'undefined') { - visibilityChange = 'msvisibilitychange'; - hidden = 'msHidden'; - } else if (typeof document['webkitHidden'] !== 'undefined') { - visibilityChange = 'webkitvisibilitychange'; - hidden = 'webkitHidden'; - } - } - - // Initially, we always assume we are visible. This ensures that in browsers - // without page visibility support or in cases where we are never visible - // (e.g. chrome extension), we act as if we are visible, i.e. don't delay - // reconnects - this.visible_ = true; - - if (visibilityChange) { - var self = this; - document.addEventListener(visibilityChange, function() { - var visible = !document[hidden]; - if (visible !== self.visible_) { - self.visible_ = visible; - self.trigger('visible', visible); - } - }, false); - } - }, - - /** - * @param {!string} eventType - * @return {Array.} - */ - getInitialEvent: function(eventType) { - fb.core.util.assert(eventType === 'visible', 'Unknown event type: ' + eventType); - return [this.visible_]; - } -}); // end fb.core.util.VisibilityMonitor - - -goog.addSingletonGetter(fb.core.util.VisibilityMonitor); diff --git a/src/database/js-client/core/util/util.js b/src/database/js-client/core/util/util.js deleted file mode 100644 index 2e9587241b1..00000000000 --- a/src/database/js-client/core/util/util.js +++ /dev/null @@ -1,835 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.util'); -goog.provide('fb.core.util.LUIDGenerator'); -goog.provide('fb.core.util.ObjectToUniqueKey'); -goog.provide('fb.core.util.enableLogging'); - -goog.require('fb.constants'); -goog.require('fb.core.RepoInfo'); -goog.require('fb.core.storage.SessionStorage'); -goog.require('fb.util.assert'); -goog.require('fb.util.assertionError'); -goog.require('fb.util.json'); -goog.require('fb.util.utf8'); -goog.require('goog.crypt.Sha1'); -goog.require('goog.crypt.base64'); -goog.require('goog.object'); -goog.require('goog.string'); - -// Cannot require; introduces circular dependency -goog.forwardDeclare('fb.core.util.Path'); - - -/** - * Returns a locally-unique ID (generated by just incrementing up from 0 each time its called). - * @type {function(): number} Generated ID. - */ -fb.core.util.LUIDGenerator = (function() { - var id = 1; - return function() { - return id++; - }; -})(); - - -/** - * Throws an error if the provided assertion is falsy - * TODO(lint) move symbols in all files - */ -fb.core.util.assert = fb.util.assert; - - -/** - * Returns an Error object suitable for throwing. - * TODO(lint) move symbols in all files - */ -fb.core.util.assertionError = fb.util.assertionError; - - -/** - * Same as fb.util.assert(), but forcefully logs instead of throws. - * @param {*} assertion The assertion to be tested for falsiness - * @param {!string} message The message to be logged on failure - */ -fb.core.util.assertWeak = function(assertion, message) { - if (!assertion) { - fb.core.util.error(message); - } -}; - - -/** - * URL-safe base64 encoding - * @param {!string} str - * @return {!string} - */ -fb.core.util.base64Encode = function(str) { - var utf8Bytes = fb.util.utf8.stringToByteArray(str); - return goog.crypt.base64.encodeByteArray(utf8Bytes, /*useWebSafe=*/true); -}; - - -/** - * URL-safe base64 decoding - * - * NOTE: DO NOT use the global atob() function - it does NOT support the - * base64Url variant encoding. - * - * @param {string} str To be decoded - * @return {?string} Decoded result, if possible - */ -fb.core.util.base64Decode = function(str) { - try { - if (fb.login.util.environment.isNodeSdk()) { - return new Buffer(str, 'base64').toString('utf8'); - } else { - return goog.crypt.base64.decodeString(str, /*useWebSafe=*/true); - } - } catch (e) { - fb.core.util.log('base64Decode failed: ', e); - } - return null; -}; - - -/** - * Sha1 hash of the input string - * @param {!string} str The string to hash - * @return {!string} The resulting hash - */ -fb.core.util.sha1 = function(str) { - var utf8Bytes = fb.util.utf8.stringToByteArray(str); - var sha1 = new goog.crypt.Sha1(); - sha1.update(utf8Bytes); - var sha1Bytes = sha1.digest(); - return goog.crypt.base64.encodeByteArray(sha1Bytes); -}; - - -/** - * @param {...*} var_args - * @return {string} - * @private - */ -fb.core.util.buildLogMessage_ = function(var_args) { - var message = ''; - for (var i = 0; i < arguments.length; i++) { - if (goog.isArrayLike(arguments[i])) { - message += fb.core.util.buildLogMessage_.apply(null, arguments[i]); - } - else if (typeof arguments[i] === 'object') { - message += fb.util.json.stringify(arguments[i]); - } - else { - message += arguments[i]; - } - message += ' '; - } - - return message; -}; - - -/** - * Use this for all debug messages in Firebase. - * @type {?function(string)} - */ -fb.core.util.logger = null; - - -/** - * Flag to check for log availability on first log message - * @type {boolean} - * @private - */ -fb.core.util.firstLog_ = true; - - -/** - * The implementation of Firebase.enableLogging (defined here to break dependencies) - * @param {boolean|?function(string)} logger A flag to turn on logging, or a custom logger - * @param {boolean=} opt_persistent Whether or not to persist logging settings across refreshes - */ -fb.core.util.enableLogging = function(logger, opt_persistent) { - fb.util.assert(!opt_persistent || (logger === true || logger === false), - "Can't turn on custom loggers persistently."); - if (logger === true) { - if (typeof console !== 'undefined') { - if (typeof console.log === 'function') { - fb.core.util.logger = goog.bind(console.log, console); - } else if (typeof console.log === 'object') { - // IE does this. - fb.core.util.logger = function(message) { console.log(message); }; - } - } - if (opt_persistent) - fb.core.storage.SessionStorage.set('logging_enabled', true); - } - else if (goog.isFunction(logger)) { - fb.core.util.logger = logger; - } else { - fb.core.util.logger = null; - fb.core.storage.SessionStorage.remove('logging_enabled'); - } -}; - - -/** - * - * @param {...(string|Arguments)} var_args - */ -fb.core.util.log = function(var_args) { - if (fb.core.util.firstLog_ === true) { - fb.core.util.firstLog_ = false; - if (fb.core.util.logger === null && - fb.core.storage.SessionStorage.get('logging_enabled') === true) - fb.core.util.enableLogging(true); - } - - if (fb.core.util.logger) { - var message = fb.core.util.buildLogMessage_.apply(null, arguments); - fb.core.util.logger(message); - } -}; - - -/** - * @param {!string} prefix - * @return {function(...[*])} - */ -fb.core.util.logWrapper = function(prefix) { - return function() { - fb.core.util.log(prefix, arguments); - }; -}; - - -/** - * @param {...string} var_args - */ -fb.core.util.error = function(var_args) { - if (typeof console !== 'undefined') { - var message = 'FIREBASE INTERNAL ERROR: ' + - fb.core.util.buildLogMessage_.apply(null, arguments); - if (typeof console.error !== 'undefined') { - console.error(message); - } else { - console.log(message); - } - } -}; - - -/** - * @param {...string} var_args - */ -fb.core.util.fatal = function(var_args) { - var message = fb.core.util.buildLogMessage_.apply(null, arguments); - throw new Error('FIREBASE FATAL ERROR: ' + message); -}; - - -/** - * @param {...*} var_args - */ -fb.core.util.warn = function(var_args) { - if (typeof console !== 'undefined') { - var message = 'FIREBASE WARNING: ' + fb.core.util.buildLogMessage_.apply(null, arguments); - if (typeof console.warn !== 'undefined') { - console.warn(message); - } else { - console.log(message); - } - } -}; - - -/** - * Logs a warning if the containing page uses https. Called when a call to new Firebase - * does not use https. - */ -fb.core.util.warnIfPageIsSecure = function() { - // Be very careful accessing browser globals. Who knows what may or may not exist. - if (typeof window !== 'undefined' && window.location && window.location.protocol && - window.location.protocol.indexOf('https:') !== -1) { - fb.core.util.warn('Insecure Firebase access from a secure page. ' + - 'Please use https in calls to new Firebase().'); - } -}; - - -/** - * @param {!String} methodName - */ -fb.core.util.warnAboutUnsupportedMethod = function(methodName) { - fb.core.util.warn(methodName + - ' is unsupported and will likely change soon. ' + - 'Please do not use.'); -}; - - -/** - * - * @param {!string} dataURL - * @return {{repoInfo: !fb.core.RepoInfo, path: !fb.core.util.Path}} - */ -fb.core.util.parseRepoInfo = function(dataURL) { - var parsedUrl = fb.core.util.parseURL(dataURL), - namespace = parsedUrl.subdomain; - - if (parsedUrl.domain === 'firebase') { - fb.core.util.fatal(parsedUrl.host + - ' is no longer supported. ' + - 'Please use .firebaseio.com instead'); - } - - // Catch common error of uninitialized namespace value. - if (!namespace || namespace == 'undefined') { - fb.core.util.fatal('Cannot parse Firebase url. ' + - 'Please use https://.firebaseio.com'); - } - - if (!parsedUrl.secure) { - fb.core.util.warnIfPageIsSecure(); - } - - var webSocketOnly = (parsedUrl.scheme === 'ws') || (parsedUrl.scheme === 'wss'); - - return { - repoInfo: new fb.core.RepoInfo(parsedUrl.host, parsedUrl.secure, namespace, webSocketOnly), - path: new fb.core.util.Path(parsedUrl.pathString) - }; -}; - - -/** - * - * @param {!string} dataURL - * @return {{host: string, port: number, domain: string, subdomain: string, secure: boolean, scheme: string, pathString: string}} - */ -fb.core.util.parseURL = function(dataURL) { - // Default to empty strings in the event of a malformed string. - var host = '', domain = '', subdomain = '', pathString = ''; - - // Always default to SSL, unless otherwise specified. - var secure = true, scheme = 'https', port = 443; - - // Don't do any validation here. The caller is responsible for validating the result of parsing. - if (goog.isString(dataURL)) { - // Parse scheme. - var colonInd = dataURL.indexOf('//'); - if (colonInd >= 0) { - scheme = dataURL.substring(0, colonInd - 1); - dataURL = dataURL.substring(colonInd + 2); - } - - // Parse host and path. - var slashInd = dataURL.indexOf('/'); - if (slashInd === -1) { - slashInd = dataURL.length; - } - host = dataURL.substring(0, slashInd); - pathString = fb.core.util.decodePath(dataURL.substring(slashInd)); - - var parts = host.split('.'); - if (parts.length === 3) { - // Normalize namespaces to lowercase to share storage / connection. - domain = parts[1]; - subdomain = parts[0].toLowerCase(); - } else if (parts.length === 2) { - domain = parts[0]; - } - - // If we have a port, use scheme for determining if it's secure. - colonInd = host.indexOf(':'); - if (colonInd >= 0) { - secure = (scheme === 'https') || (scheme === 'wss'); - port = goog.string.parseInt(host.substring(colonInd + 1)); - } - } - - return { - host: host, - port: port, - domain: domain, - subdomain: subdomain, - secure: secure, - scheme: scheme, - pathString: pathString - }; -}; - - -/** - * @param {!string} pathString - * @return {string} - */ -fb.core.util.decodePath = function(pathString) { - var pathStringDecoded = ''; - var pieces = pathString.split('/'); - for (var i = 0; i < pieces.length; i++) { - if (pieces[i].length > 0) { - var piece = pieces[i]; - try { - piece = goog.string.urlDecode(piece); - } catch (e) {} - pathStringDecoded += '/' + piece; - } - } - return pathStringDecoded; -}; - - -/** - * Returns true if data is NaN, or +/- Infinity. - * @param {*} data - * @return {boolean} - */ -fb.core.util.isInvalidJSONNumber = function(data) { - return goog.isNumber(data) && - (data != data || // NaN - data == Number.POSITIVE_INFINITY || - data == Number.NEGATIVE_INFINITY); -}; - - -/** - * @param {function()} fn - */ -fb.core.util.executeWhenDOMReady = function(fn) { - if (fb.login.util.environment.isNodeSdk() || document.readyState === 'complete') { - fn(); - } else { - // Modeled after jQuery. Try DOMContentLoaded and onreadystatechange (which - // fire before onload), but fall back to onload. - - var called = false; - var wrappedFn = function() { - if (!document.body) { - setTimeout(wrappedFn, Math.floor(10)); - return; - } - - if (!called) { - called = true; - fn(); - } - }; - - if (document.addEventListener) { - document.addEventListener('DOMContentLoaded', wrappedFn, false); - // fallback to onload. - window.addEventListener('load', wrappedFn, false); - } else if (document.attachEvent) { - // IE. - document.attachEvent('onreadystatechange', - function() { - if (document.readyState === 'complete') - wrappedFn(); - } - ); - // fallback to onload. - window.attachEvent('onload', wrappedFn); - - // jQuery has an extra hack for IE that we could employ (based on - // http://javascript.nwbox.com/IEContentLoaded/) But it looks really old. - // I'm hoping we don't need it. - } - } -}; - - -/** - * Minimum key name. Invalid for actual data, used as a marker to sort before any valid names - * @type {!string} - */ -fb.core.util.MIN_NAME = '[MIN_NAME]'; - - -/** - * Maximum key name. Invalid for actual data, used as a marker to sort above any valid names - * @type {!string} - */ -fb.core.util.MAX_NAME = '[MAX_NAME]'; - - -/** - * Compares valid Firebase key names, plus min and max name - * @param {!string} a - * @param {!string} b - * @return {!number} - */ -fb.core.util.nameCompare = function(a, b) { - if (a === b) { - return 0; - } else if (a === fb.core.util.MIN_NAME || b === fb.core.util.MAX_NAME) { - return -1; - } else if (b === fb.core.util.MIN_NAME || a === fb.core.util.MAX_NAME) { - return 1; - } else { - var aAsInt = fb.core.util.tryParseInt(a), - bAsInt = fb.core.util.tryParseInt(b); - - if (aAsInt !== null) { - if (bAsInt !== null) { - return (aAsInt - bAsInt) == 0 ? (a.length - b.length) : (aAsInt - bAsInt); - } else { - return -1; - } - } else if (bAsInt !== null) { - return 1; - } else { - return (a < b) ? -1 : 1; - } - } -}; - - -/** - * @param {!string} a - * @param {!string} b - * @return {!number} comparison result. - */ -fb.core.util.stringCompare = function(a, b) { - if (a === b) { - return 0; - } else if (a < b) { - return -1; - } else { - return 1; - } -}; - - -/** - * @param {string} key - * @param {Object} obj - * @return {*} - */ -fb.core.util.requireKey = function(key, obj) { - if (obj && (key in obj)) { - return obj[key]; - } else { - throw new Error('Missing required key (' + key + ') in object: ' + fb.util.json.stringify(obj)); - } -}; - - -/** - * @param {*} obj - * @return {string} - */ -fb.core.util.ObjectToUniqueKey = function(obj) { - if (typeof obj !== 'object' || obj === null) - return fb.util.json.stringify(obj); - - var keys = []; - for (var k in obj) { - keys.push(k); - } - - // Export as json, but with the keys sorted. - keys.sort(); - var key = '{'; - for (var i = 0; i < keys.length; i++) { - if (i !== 0) - key += ','; - key += fb.util.json.stringify(keys[i]); - key += ':'; - key += fb.core.util.ObjectToUniqueKey(obj[keys[i]]); - } - - key += '}'; - return key; -}; - - -/** - * Splits a string into a number of smaller segments of maximum size - * @param {!string} str The string - * @param {!number} segsize The maximum number of chars in the string. - * @return {Array.} The string, split into appropriately-sized chunks - */ -fb.core.util.splitStringBySize = function(str, segsize) { - if (str.length <= segsize) { - return [str]; - } - - var dataSegs = []; - for (var c = 0; c < str.length; c += segsize) { - if (c + segsize > str) { - dataSegs.push(str.substring(c, str.length)); - } - else { - dataSegs.push(str.substring(c, c + segsize)); - } - } - return dataSegs; -}; - - -/** - * Apply a function to each (key, value) pair in an object or - * apply a function to each (index, value) pair in an array - * @param {!(Object|Array)} obj The object or array to iterate over - * @param {function(?, ?)} fn The function to apply - */ -fb.core.util.each = function(obj, fn) { - if (goog.isArray(obj)) { - for (var i = 0; i < obj.length; ++i) { - fn(i, obj[i]); - } - } else { - goog.object.forEach(obj, fn); - } -}; - - -/** - * Like goog.bind, but doesn't bother to create a closure if opt_context is null/undefined. - * @param {function(*)} callback Callback function. - * @param {?Object=} opt_context Optional context to bind to. - * @return {function(*)} - */ -fb.core.util.bindCallback = function(callback, opt_context) { - return opt_context ? goog.bind(callback, opt_context) : callback; -}; - - -/** - * Borrowed from http://hg.secondlife.com/llsd/src/tip/js/typedarray.js (MIT License) - * I made one modification at the end and removed the NaN / Infinity - * handling (since it seemed broken [caused an overflow] and we don't need it). See MJL comments. - * @param {!number} v A double - * @return {string} - */ -fb.core.util.doubleToIEEE754String = function(v) { - fb.core.util.assert(!fb.core.util.isInvalidJSONNumber(v), 'Invalid JSON number'); // MJL - - var ebits = 11, fbits = 52; - var bias = (1 << (ebits - 1)) - 1, - s, e, f, ln, - i, bits, str, bytes; - - // Compute sign, exponent, fraction - // Skip NaN / Infinity handling --MJL. - if (v === 0) { - e = 0; f = 0; s = (1 / v === -Infinity) ? 1 : 0; - } - else { - s = v < 0; - v = Math.abs(v); - - if (v >= Math.pow(2, 1 - bias)) { - // Normalized - ln = Math.min(Math.floor(Math.log(v) / Math.LN2), bias); - e = ln + bias; - f = Math.round(v * Math.pow(2, fbits - ln) - Math.pow(2, fbits)); - } - else { - // Denormalized - e = 0; - f = Math.round(v / Math.pow(2, 1 - bias - fbits)); - } - } - - // Pack sign, exponent, fraction - bits = []; - for (i = fbits; i; i -= 1) { bits.push(f % 2 ? 1 : 0); f = Math.floor(f / 2); } - for (i = ebits; i; i -= 1) { bits.push(e % 2 ? 1 : 0); e = Math.floor(e / 2); } - bits.push(s ? 1 : 0); - bits.reverse(); - str = bits.join(''); - - // Return the data as a hex string. --MJL - var hexByteString = ''; - for (i = 0; i < 64; i += 8) { - var hexByte = parseInt(str.substr(i, 8), 2).toString(16); - if (hexByte.length === 1) - hexByte = '0' + hexByte; - hexByteString = hexByteString + hexByte; - } - return hexByteString.toLowerCase(); -}; - - -/** - * Used to detect if we're in a Chrome content script (which executes in an - * isolated environment where long-polling doesn't work). - * @return {boolean} - */ -fb.core.util.isChromeExtensionContentScript = function() { - return !!(typeof window === 'object' && - window['chrome'] && - window['chrome']['extension'] && - !/^chrome/.test(window.location.href) - ); -}; - - -/** - * Used to detect if we're in a Windows 8 Store app. - * @return {boolean} - */ -fb.core.util.isWindowsStoreApp = function() { - // Check for the presence of a couple WinRT globals - return typeof Windows === 'object' && typeof Windows.UI === 'object'; -}; - - -/** - * Converts a server error code to a Javascript Error - * @param {!string} code - * @param {!fb.api.Query} query - * @return {Error} - */ -fb.core.util.errorForServerCode = function(code, query) { - var reason = 'Unknown Error'; - if (code === 'too_big') { - reason = 'The data requested exceeds the maximum size ' + - 'that can be accessed with a single request.'; - } else if (code == 'permission_denied') { - reason = "Client doesn't have permission to access the desired data."; - } else if (code == 'unavailable') { - reason = 'The service is unavailable'; - } - - var error = new Error(code + ' at ' + query.path.toString() + ': ' + reason); - error.code = code.toUpperCase(); - return error; -}; - - -/** - * Used to test for integer-looking strings - * @type {RegExp} - * @private - */ -fb.core.util.INTEGER_REGEXP_ = new RegExp('^-?\\d{1,10}$'); - - -/** - * If the string contains a 32-bit integer, return it. Else return null. - * @param {!string} str - * @return {?number} - */ -fb.core.util.tryParseInt = function(str) { - if (fb.core.util.INTEGER_REGEXP_.test(str)) { - var intVal = Number(str); - if (intVal >= -2147483648 && intVal <= 2147483647) { - return intVal; - } - } - return null; -}; - - -/** - * Helper to run some code but catch any exceptions and re-throw them later. - * Useful for preventing user callbacks from breaking internal code. - * - * Re-throwing the exception from a setTimeout is a little evil, but it's very - * convenient (we don't have to try to figure out when is a safe point to - * re-throw it), and the behavior seems reasonable: - * - * * If you aren't pausing on exceptions, you get an error in the console with - * the correct stack trace. - * * If you're pausing on all exceptions, the debugger will pause on your - * exception and then again when we rethrow it. - * * If you're only pausing on uncaught exceptions, the debugger will only pause - * on us re-throwing it. - * - * @param {!function()} fn The code to guard. - */ -fb.core.util.exceptionGuard = function(fn) { - try { - fn(); - } catch (e) { - // Re-throw exception when it's safe. - setTimeout(function() { - // It used to be that "throw e" would result in a good console error with - // relevant context, but as of Chrome 39, you just get the firebase.js - // file/line number where we re-throw it, which is useless. So we log - // e.stack explicitly. - var stack = e.stack || ''; - fb.core.util.warn('Exception was thrown by user callback.', stack); - throw e; - }, Math.floor(0)); - } -}; - - -/** - * Helper function to safely call opt_callback with the specified arguments. It: - * 1. Turns into a no-op if opt_callback is null or undefined. - * 2. Wraps the call inside exceptionGuard to prevent exceptions from breaking our state. - * - * @param {?Function=} opt_callback Optional onComplete callback. - * @param {...*} var_args Arbitrary args to be passed to opt_onComplete - */ -fb.core.util.callUserCallback = function(opt_callback, var_args) { - if (goog.isFunction(opt_callback)) { - var args = Array.prototype.slice.call(arguments, 1); - var newArgs = args.slice(); - fb.core.util.exceptionGuard(function() { - opt_callback.apply(null, newArgs); - }); - } -}; - - -/** - * @return {boolean} true if we think we're currently being crawled. -*/ -fb.core.util.beingCrawled = function() { - var userAgent = (typeof window === 'object' && window['navigator'] && window['navigator']['userAgent']) || ''; - - // For now we whitelist the most popular crawlers. We should refine this to be the set of crawlers we - // believe to support JavaScript/AJAX rendering. - // NOTE: Google Webmaster Tools doesn't really belong, but their "This is how a visitor to your website - // would have seen the page" is flaky if we don't treat it as a crawler. - return userAgent.search(/googlebot|google webmaster tools|bingbot|yahoo! slurp|baiduspider|yandexbot|duckduckbot/i) >= - 0; -}; - -/** - * Export a property of an object using a getter function. - * - * @param {!Object} object - * @param {string} name - * @param {!function(): *} fnGet - */ -fb.core.util.exportPropGetter = function(object, name, fnGet) { - Object.defineProperty(object, name, {get: fnGet}); -}; - -/** - * Same as setTimeout() except on Node.JS it will /not/ prevent the process from exiting. - * - * It is removed with clearTimeout() as normal. - * - * @param fn {Function} Function to run. - * @param time {number} Milliseconds to wait before running. - * @return {number|Object} The setTimeout() return value. - */ -fb.core.util.setTimeoutNonBlocking = function(fn, time) { - var timeout = setTimeout(fn, time); - if (typeof timeout === 'object' && timeout['unref']) { - timeout['unref'](); - } - return timeout; -}; diff --git a/src/database/js-client/core/util/validation.js b/src/database/js-client/core/util/validation.js deleted file mode 100644 index 924d96c207a..00000000000 --- a/src/database/js-client/core/util/validation.js +++ /dev/null @@ -1,404 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.util.validation'); - -goog.require('fb.core.util'); -goog.require('fb.core.util.Path'); -goog.require('fb.core.util.ValidationPath'); -goog.require('fb.util.obj'); -goog.require('fb.util.utf8'); -goog.require('fb.util.validation'); - - -/** - * Namespace of validation functions. - */ -fb.core.util.validation = { - /** - * True for invalid Firebase keys - * @type {RegExp} - * @private - */ - INVALID_KEY_REGEX_: /[\[\].#$\/\u0000-\u001F\u007F]/, - - /** - * True for invalid Firebase paths. - * Allows '/' in paths. - * @type {RegExp} - * @private - */ - INVALID_PATH_REGEX_: /[\[\].#$\u0000-\u001F\u007F]/, - - /** - * Maximum number of characters to allow in leaf value - * @type {number} - * @private - */ - MAX_LEAF_SIZE_: 10 * 1024 * 1024, - - - /** - * @param {*} key - * @return {boolean} - */ - isValidKey: function(key) { - return goog.isString(key) && key.length !== 0 && - !fb.core.util.validation.INVALID_KEY_REGEX_.test(key); - }, - - /** - * @param {string} pathString - * @return {boolean} - */ - isValidPathString: function(pathString) { - return goog.isString(pathString) && pathString.length !== 0 && - !fb.core.util.validation.INVALID_PATH_REGEX_.test(pathString); - }, - - /** - * @param {string} pathString - * @return {boolean} - */ - isValidRootPathString: function(pathString) { - if (pathString) { - // Allow '/.info/' at the beginning. - pathString = pathString.replace(/^\/*\.info(\/|$)/, '/'); - } - - return fb.core.util.validation.isValidPathString(pathString); - }, - - /** - * @param {*} priority - * @return {boolean} - */ - isValidPriority: function(priority) { - return priority === null || - goog.isString(priority) || - (goog.isNumber(priority) && !fb.core.util.isInvalidJSONNumber(priority)) || - (goog.isObject(priority) && fb.util.obj.contains(priority, '.sv')); - }, - - /** - * Pre-validate a datum passed as an argument to Firebase function. - * - * @param {string} fnName - * @param {number} argumentNumber - * @param {*} data - * @param {!fb.core.util.Path} path - * @param {boolean} optional - */ - validateFirebaseDataArg: function(fnName, argumentNumber, data, path, optional) { - if (optional && !goog.isDef(data)) - return; - - fb.core.util.validation.validateFirebaseData( - fb.util.validation.errorPrefix(fnName, argumentNumber, optional), - data, path - ); - }, - - /** - * Validate a data object client-side before sending to server. - * - * @param {string} errorPrefix - * @param {*} data - * @param {!fb.core.util.Path|!fb.core.util.ValidationPath} path - */ - validateFirebaseData: function(errorPrefix, data, path) { - if (path instanceof fb.core.util.Path) { - path = new fb.core.util.ValidationPath(path, errorPrefix); - } - - if (!goog.isDef(data)) { - throw new Error(errorPrefix + 'contains undefined ' + path.toErrorString()); - } - if (goog.isFunction(data)) { - throw new Error(errorPrefix + 'contains a function ' + path.toErrorString() + - ' with contents: ' + data.toString()); - } - if (fb.core.util.isInvalidJSONNumber(data)) { - throw new Error(errorPrefix + 'contains ' + data.toString() + ' ' + path.toErrorString()); - } - - // Check max leaf size, but try to avoid the utf8 conversion if we can. - if (goog.isString(data) && - data.length > fb.core.util.validation.MAX_LEAF_SIZE_ / 3 && - fb.util.utf8.stringLength(data) > fb.core.util.validation.MAX_LEAF_SIZE_) { - throw new Error(errorPrefix + 'contains a string greater than ' + - fb.core.util.validation.MAX_LEAF_SIZE_ + - ' utf8 bytes ' + path.toErrorString() + - " ('" + data.substring(0, 50) + "...')"); - } - - // TODO: Perf: Consider combining the recursive validation of keys into NodeFromJSON - // to save extra walking of large objects. - if (goog.isObject(data)) { - var hasDotValue = false, hasActualChild = false; - fb.util.obj.foreach(data, function(key, value) { - if (key === '.value') { - hasDotValue = true; - } - else if (key !== '.priority' && key !== '.sv') { - hasActualChild = true; - if (!fb.core.util.validation.isValidKey(key)) { - throw new Error(errorPrefix + ' contains an invalid key (' + key + ') ' + - path.toErrorString() + - '. Keys must be non-empty strings ' + - 'and can\'t contain ".", "#", "$", "/", "[", or "]"'); - } - } - - path.push(key); - fb.core.util.validation.validateFirebaseData(errorPrefix, value, path); - path.pop(); - }); - - if (hasDotValue && hasActualChild) { - throw new Error(errorPrefix + ' contains ".value" child ' + - path.toErrorString() + - ' in addition to actual children.'); - } - } - }, - - /** - * Pre-validate paths passed in the firebase function. - * - * @param {string} errorPrefix - * @param {Array} mergePaths - */ - validateFirebaseMergePaths: function(errorPrefix, mergePaths) { - var i, curPath; - for (i = 0; i < mergePaths.length; i++) { - curPath = mergePaths[i]; - var keys = curPath.slice(); - for (var j = 0; j < keys.length; j++) { - if (keys[j] === '.priority' && j === (keys.length - 1)) { - // .priority is OK - } else if (!fb.core.util.validation.isValidKey(keys[j])) { - throw new Error(errorPrefix + 'contains an invalid key (' + keys[j] + ') in path ' + - curPath.toString() + - '. Keys must be non-empty strings ' + - 'and can\'t contain ".", "#", "$", "/", "[", or "]"'); - } - } - } - - // Check that update keys are not descendants of each other. - // We rely on the property that sorting guarantees that ancestors come - // right before descendants. - mergePaths.sort(fb.core.util.Path.comparePaths); - var prevPath = null; - for (i = 0; i < mergePaths.length; i++) { - curPath = mergePaths[i]; - if (prevPath !== null && prevPath.contains(curPath)) { - throw new Error(errorPrefix + 'contains a path ' + prevPath.toString() + - ' that is ancestor of another path ' + curPath.toString()); - } - prevPath = curPath; - } - }, - - /** - * pre-validate an object passed as an argument to firebase function ( - * must be an object - e.g. for firebase.update()). - * - * @param {string} fnName - * @param {number} argumentNumber - * @param {*} data - * @param {!fb.core.util.Path} path - * @param {boolean} optional - */ - validateFirebaseMergeDataArg: function(fnName, argumentNumber, data, path, optional) { - if (optional && !goog.isDef(data)) - return; - - var errorPrefix = fb.util.validation.errorPrefix(fnName, argumentNumber, optional); - - if (!goog.isObject(data) || goog.isArray(data)) { - throw new Error(errorPrefix + ' must be an object containing the children to replace.'); - } - - var mergePaths = []; - fb.util.obj.foreach(data, function(key, value) { - var curPath = new fb.core.util.Path(key); - fb.core.util.validation.validateFirebaseData(errorPrefix, value, path.child(curPath)); - if (curPath.getBack() === '.priority') { - if (!fb.core.util.validation.isValidPriority(value)) { - throw new Error( - errorPrefix + 'contains an invalid value for \'' + curPath.toString() + '\', which must be a valid ' + - 'Firebase priority (a string, finite number, server value, or null).'); - } - } - mergePaths.push(curPath); - }); - fb.core.util.validation.validateFirebaseMergePaths(errorPrefix, mergePaths); - }, - - validatePriority: function(fnName, argumentNumber, priority, optional) { - if (optional && !goog.isDef(priority)) - return; - if (fb.core.util.isInvalidJSONNumber(priority)) - throw new Error( - fb.util.validation.errorPrefix(fnName, argumentNumber, optional) + - 'is ' + priority.toString() + - ', but must be a valid Firebase priority (a string, finite number, ' + - 'server value, or null).'); - // Special case to allow importing data with a .sv. - if (!fb.core.util.validation.isValidPriority(priority)) - throw new Error( - fb.util.validation.errorPrefix(fnName, argumentNumber, optional) + - 'must be a valid Firebase priority ' + - '(a string, finite number, server value, or null).'); - }, - - validateEventType: function(fnName, argumentNumber, eventType, optional) { - if (optional && !goog.isDef(eventType)) - return; - - switch (eventType) { - case 'value': - case 'child_added': - case 'child_removed': - case 'child_changed': - case 'child_moved': - break; - default: - throw new Error( - fb.util.validation.errorPrefix(fnName, argumentNumber, optional) + - 'must be a valid event type: "value", "child_added", "child_removed", ' + - '"child_changed", or "child_moved".'); - } - }, - - validateKey: function(fnName, argumentNumber, key, optional) { - if (optional && !goog.isDef(key)) - return; - if (!fb.core.util.validation.isValidKey(key)) - throw new Error(fb.util.validation.errorPrefix(fnName, argumentNumber, optional) + - 'was an invalid key: "' + key + - '". Firebase keys must be non-empty strings and ' + - 'can\'t contain ".", "#", "$", "/", "[", or "]").'); - }, - - validatePathString: function(fnName, argumentNumber, pathString, optional) { - if (optional && !goog.isDef(pathString)) - return; - - if (!fb.core.util.validation.isValidPathString(pathString)) - throw new Error(fb.util.validation.errorPrefix(fnName, argumentNumber, optional) + - 'was an invalid path: "' + - pathString + - '". Paths must be non-empty strings and ' + - 'can\'t contain ".", "#", "$", "[", or "]"'); - }, - - validateRootPathString: function(fnName, argumentNumber, pathString, optional) { - if (pathString) { - // Allow '/.info/' at the beginning. - pathString = pathString.replace(/^\/*\.info(\/|$)/, '/'); - } - - fb.core.util.validation.validatePathString(fnName, argumentNumber, pathString, optional); - }, - - validateWritablePath: function(fnName, path) { - if (path.getFront() === '.info') { - throw new Error(fnName + ' failed: Can\'t modify data under /.info/'); - } - }, - - validateUrl: function(fnName, argumentNumber, parsedUrl) { - // TODO: Validate server better. - var pathString = parsedUrl.path.toString(); - if (!goog.isString(parsedUrl.repoInfo.host) || parsedUrl.repoInfo.host.length === 0 || - !fb.core.util.validation.isValidKey(parsedUrl.repoInfo.namespace) || - (pathString.length !== 0 && !fb.core.util.validation.isValidRootPathString(pathString))) { - throw new Error(fb.util.validation.errorPrefix(fnName, argumentNumber, false) + - 'must be a valid firebase URL and ' + - 'the path can\'t contain ".", "#", "$", "[", or "]".'); - } - }, - - validateCredential: function(fnName, argumentNumber, cred, optional) { - if (optional && !goog.isDef(cred)) - return; - if (!goog.isString(cred)) - throw new Error( - fb.util.validation.errorPrefix(fnName, argumentNumber, optional) + - 'must be a valid credential (a string).'); - }, - - validateBoolean: function(fnName, argumentNumber, bool, optional) { - if (optional && !goog.isDef(bool)) - return; - if (!goog.isBoolean(bool)) - throw new Error(fb.util.validation.errorPrefix(fnName, argumentNumber, optional) + - 'must be a boolean.'); - }, - - validateString: function(fnName, argumentNumber, string, optional) { - if (optional && !goog.isDef(string)) - return; - if (!goog.isString(string)) { - throw new Error( - fb.util.validation.errorPrefix(fnName, argumentNumber, optional) + - 'must be a valid string.'); - } - }, - - validateObject: function(fnName, argumentNumber, obj, optional) { - if (optional && !goog.isDef(obj)) - return; - if (!goog.isObject(obj) || obj === null) { - throw new Error( - fb.util.validation.errorPrefix(fnName, argumentNumber, optional) + - 'must be a valid object.'); - } - }, - - validateObjectContainsKey: function(fnName, argumentNumber, obj, key, optional, opt_type) { - var objectContainsKey = (goog.isObject(obj) && fb.util.obj.contains(obj, key)); - - if (!objectContainsKey) { - if (optional) { - return; - } else { - throw new Error( - fb.util.validation.errorPrefix(fnName, argumentNumber, optional) + - 'must contain the key "' + key + '"'); - } - } - - if (opt_type) { - var val = fb.util.obj.get(obj, key); - if ((opt_type === 'number' && !goog.isNumber(val)) || - (opt_type === 'string' && !goog.isString(val)) || - (opt_type === 'boolean' && !goog.isBoolean(val)) || - (opt_type === 'function' && !goog.isFunction(val)) || - (opt_type === 'object' && !goog.isObject(val))) { - if (optional) { - throw new Error(fb.util.validation.errorPrefix(fnName, argumentNumber, optional) + - 'contains invalid value for key "' + key + '" (must be of type "' + opt_type + '")'); - } else { - throw new Error(fb.util.validation.errorPrefix(fnName, argumentNumber, optional) + - 'must contain the key "' + key + '" with type "' + opt_type + '"'); - } - } - } - } -}; // end fb.core.util.validation diff --git a/src/database/js-client/core/view/CacheNode.js b/src/database/js-client/core/view/CacheNode.js deleted file mode 100644 index 7fcfc156fa1..00000000000 --- a/src/database/js-client/core/view/CacheNode.js +++ /dev/null @@ -1,91 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.view.CacheNode'); - -/** - * A cache node only stores complete children. Additionally it holds a flag whether the node can be considered fully - * initialized in the sense that we know at one point in time this represented a valid state of the world, e.g. - * initialized with data from the server, or a complete overwrite by the client. The filtered flag also tracks - * whether a node potentially had children removed due to a filter. - * - * @param {!fb.core.snap.Node} node - * @param {boolean} fullyInitialized - * @param {boolean} filtered - * @constructor - */ -fb.core.view.CacheNode = function(node, fullyInitialized, filtered) { - /** - * @type {!fb.core.snap.Node} - * @private - */ - this.node_ = node; - - /** - * @type {boolean} - * @private - */ - this.fullyInitialized_ = fullyInitialized; - - /** - * @type {boolean} - * @private - */ - this.filtered_ = filtered; -}; - -/** - * Returns whether this node was fully initialized with either server data or a complete overwrite by the client - * @return {boolean} - */ -fb.core.view.CacheNode.prototype.isFullyInitialized = function() { - return this.fullyInitialized_; -}; - -/** - * Returns whether this node is potentially missing children due to a filter applied to the node - * @return {boolean} - */ -fb.core.view.CacheNode.prototype.isFiltered = function() { - return this.filtered_; -}; - -/** - * @param {!fb.core.util.Path} path - * @return {boolean} - */ -fb.core.view.CacheNode.prototype.isCompleteForPath = function(path) { - if (path.isEmpty()) { - return this.isFullyInitialized() && !this.filtered_; - } else { - var childKey = path.getFront(); - return this.isCompleteForChild(childKey); - } -}; - -/** - * @param {!string} key - * @return {boolean} - */ -fb.core.view.CacheNode.prototype.isCompleteForChild = function(key) { - return (this.isFullyInitialized() && !this.filtered_) || this.node_.hasChild(key); -}; - -/** - * @return {!fb.core.snap.Node} - */ -fb.core.view.CacheNode.prototype.getNode = function() { - return this.node_; -}; diff --git a/src/database/js-client/core/view/Change.js b/src/database/js-client/core/view/Change.js deleted file mode 100644 index c104350edb0..00000000000 --- a/src/database/js-client/core/view/Change.js +++ /dev/null @@ -1,120 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.view.Change'); -goog.provide('fb.core.view.Change.CHILD_ADDED'); -goog.provide('fb.core.view.Change.CHILD_CHANGED'); -goog.provide('fb.core.view.Change.CHILD_MOVED'); -goog.provide('fb.core.view.Change.CHILD_REMOVED'); -goog.provide('fb.core.view.Change.VALUE'); - - - -/** - * @constructor - * @struct - * @param {!string} type The event type - * @param {!fb.core.snap.Node} snapshotNode The data - * @param {string=} opt_childName The name for this child, if it's a child event - * @param {fb.core.snap.Node=} opt_oldSnap Used for intermediate processing of child changed events - * @param {string=} opt_prevName The name for the previous child, if applicable - */ -fb.core.view.Change = function(type, snapshotNode, opt_childName, opt_oldSnap, opt_prevName) { - this.type = type; - this.snapshotNode = snapshotNode; - this.childName = opt_childName; - this.oldSnap = opt_oldSnap; - this.prevName = opt_prevName; -}; - - -/** - * @param {!fb.core.snap.Node} snapshot - * @return {!fb.core.view.Change} - */ -fb.core.view.Change.valueChange = function(snapshot) { - return new fb.core.view.Change(fb.core.view.Change.VALUE, snapshot); -}; - - -/** - * @param {string} childKey - * @param {!fb.core.snap.Node} snapshot - * @return {!fb.core.view.Change} - */ -fb.core.view.Change.childAddedChange = function(childKey, snapshot) { - return new fb.core.view.Change(fb.core.view.Change.CHILD_ADDED, snapshot, childKey); -}; - - -/** - * @param {string} childKey - * @param {!fb.core.snap.Node} snapshot - * @return {!fb.core.view.Change} - */ -fb.core.view.Change.childRemovedChange = function(childKey, snapshot) { - return new fb.core.view.Change(fb.core.view.Change.CHILD_REMOVED, snapshot, childKey); -}; - - -/** - * @param {string} childKey - * @param {!fb.core.snap.Node} newSnapshot - * @param {!fb.core.snap.Node} oldSnapshot - * @return {!fb.core.view.Change} - */ -fb.core.view.Change.childChangedChange = function(childKey, newSnapshot, oldSnapshot) { - return new fb.core.view.Change(fb.core.view.Change.CHILD_CHANGED, newSnapshot, childKey, oldSnapshot); -}; - - -/** - * @param {string} childKey - * @param {!fb.core.snap.Node} snapshot - * @return {!fb.core.view.Change} - */ -fb.core.view.Change.childMovedChange = function(childKey, snapshot) { - return new fb.core.view.Change(fb.core.view.Change.CHILD_MOVED, snapshot, childKey); -}; - - -/** - * @param {string} prevName - * @return {!fb.core.view.Change} - */ -fb.core.view.Change.prototype.changeWithPrevName = function(prevName) { - return new fb.core.view.Change(this.type, this.snapshotNode, this.childName, this.oldSnap, prevName); -}; - - -//event types -/** Event type for a child added */ -fb.core.view.Change.CHILD_ADDED = 'child_added'; - - -/** Event type for a child removed */ -fb.core.view.Change.CHILD_REMOVED = 'child_removed'; - - -/** Event type for a child changed */ -fb.core.view.Change.CHILD_CHANGED = 'child_changed'; - - -/** Event type for a child moved */ -fb.core.view.Change.CHILD_MOVED = 'child_moved'; - - -/** Event type for a value change */ -fb.core.view.Change.VALUE = 'value'; diff --git a/src/database/js-client/core/view/ChildChangeAccumulator.js b/src/database/js-client/core/view/ChildChangeAccumulator.js deleted file mode 100644 index 28174a393c0..00000000000 --- a/src/database/js-client/core/view/ChildChangeAccumulator.js +++ /dev/null @@ -1,76 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.view.ChildChangeAccumulator'); -goog.require('fb.core.util'); -goog.require('fb.core.view.Change'); -goog.require('fb.util.obj'); -goog.require('goog.object'); - - - -/** - * @constructor - */ -fb.core.view.ChildChangeAccumulator = function() { - /** - * @type {!Object.} - * @private - */ - this.changeMap_ = { }; -}; - - -/** - * @param {!fb.core.view.Change} change - */ -fb.core.view.ChildChangeAccumulator.prototype.trackChildChange = function(change) { - var Change = fb.core.view.Change; - var type = change.type; - var childKey = /** @type {!string} */ (change.childName); - fb.core.util.assert(type == fb.core.view.Change.CHILD_ADDED || - type == fb.core.view.Change.CHILD_CHANGED || - type == fb.core.view.Change.CHILD_REMOVED, 'Only child changes supported for tracking'); - fb.core.util.assert(childKey !== '.priority', 'Only non-priority child changes can be tracked.'); - var oldChange = fb.util.obj.get(this.changeMap_, childKey); - if (oldChange) { - var oldType = oldChange.type; - if (type == Change.CHILD_ADDED && oldType == Change.CHILD_REMOVED) { - this.changeMap_[childKey] = Change.childChangedChange(childKey, change.snapshotNode, oldChange.snapshotNode); - } else if (type == Change.CHILD_REMOVED && oldType == Change.CHILD_ADDED) { - delete this.changeMap_[childKey]; - } else if (type == Change.CHILD_REMOVED && oldType == Change.CHILD_CHANGED) { - this.changeMap_[childKey] = Change.childRemovedChange(childKey, - /** @type {!fb.core.snap.Node} */ (oldChange.oldSnap)); - } else if (type == Change.CHILD_CHANGED && oldType == Change.CHILD_ADDED) { - this.changeMap_[childKey] = Change.childAddedChange(childKey, change.snapshotNode); - } else if (type == Change.CHILD_CHANGED && oldType == Change.CHILD_CHANGED) { - this.changeMap_[childKey] = Change.childChangedChange(childKey, change.snapshotNode, - /** @type {!fb.core.snap.Node} */ (oldChange.oldSnap)); - } else { - throw fb.core.util.assertionError('Illegal combination of changes: ' + change + ' occurred after ' + oldChange); - } - } else { - this.changeMap_[childKey] = change; - } -}; - - -/** - * @return {!Array.} - */ -fb.core.view.ChildChangeAccumulator.prototype.getChanges = function() { - return goog.object.getValues(this.changeMap_); -}; diff --git a/src/database/js-client/core/view/CompleteChildSource.js b/src/database/js-client/core/view/CompleteChildSource.js deleted file mode 100644 index fa0d329835d..00000000000 --- a/src/database/js-client/core/view/CompleteChildSource.js +++ /dev/null @@ -1,133 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.view.CompleteChildSource'); - - -/** - * Since updates to filtered nodes might require nodes to be pulled in from "outside" the node, this interface - * can help to get complete children that can be pulled in. - * A class implementing this interface takes potentially multiple sources (e.g. user writes, server data from - * other views etc.) to try it's best to get a complete child that might be useful in pulling into the view. - * - * @interface - */ -fb.core.view.CompleteChildSource = function() { }; - -/** - * @param {!string} childKey - * @return {?fb.core.snap.Node} - */ -fb.core.view.CompleteChildSource.prototype.getCompleteChild = function(childKey) { }; - -/** - * @param {!fb.core.snap.Index} index - * @param {!fb.core.snap.NamedNode} child - * @param {boolean} reverse - * @return {?fb.core.snap.NamedNode} - */ -fb.core.view.CompleteChildSource.prototype.getChildAfterChild = function(index, child, reverse) { }; - - -/** - * An implementation of CompleteChildSource that never returns any additional children - * - * @private - * @constructor - * @implements fb.core.view.CompleteChildSource - */ -fb.core.view.NoCompleteChildSource_ = function() { -}; - -/** - * @inheritDoc - */ -fb.core.view.NoCompleteChildSource_.prototype.getCompleteChild = function() { - return null; -}; - -/** - * @inheritDoc - */ -fb.core.view.NoCompleteChildSource_.prototype.getChildAfterChild = function() { - return null; -}; - -/** - * Singleton instance. - * @const - * @type {!fb.core.view.CompleteChildSource} - */ -fb.core.view.NO_COMPLETE_CHILD_SOURCE = new fb.core.view.NoCompleteChildSource_(); - - -/** - * An implementation of CompleteChildSource that uses a WriteTree in addition to any other server data or - * old event caches available to calculate complete children. - * - * @param {!fb.core.WriteTreeRef} writes - * @param {!fb.core.view.ViewCache} viewCache - * @param {?fb.core.snap.Node} optCompleteServerCache - * - * @constructor - * @implements fb.core.view.CompleteChildSource - */ -fb.core.view.WriteTreeCompleteChildSource = function(writes, viewCache, optCompleteServerCache) { - /** - * @type {!fb.core.WriteTreeRef} - * @private - */ - this.writes_ = writes; - - /** - * @type {!fb.core.view.ViewCache} - * @private - */ - this.viewCache_ = viewCache; - - /** - * @type {?fb.core.snap.Node} - * @private - */ - this.optCompleteServerCache_ = optCompleteServerCache; -}; - -/** - * @inheritDoc - */ -fb.core.view.WriteTreeCompleteChildSource.prototype.getCompleteChild = function(childKey) { - var node = this.viewCache_.getEventCache(); - if (node.isCompleteForChild(childKey)) { - return node.getNode().getImmediateChild(childKey); - } else { - var serverNode = this.optCompleteServerCache_ != null ? - new fb.core.view.CacheNode(this.optCompleteServerCache_, true, false) : this.viewCache_.getServerCache(); - return this.writes_.calcCompleteChild(childKey, serverNode); - } -}; - -/** - * @inheritDoc - */ -fb.core.view.WriteTreeCompleteChildSource.prototype.getChildAfterChild = function(index, child, reverse) { - var completeServerData = this.optCompleteServerCache_ != null ? this.optCompleteServerCache_ : - this.viewCache_.getCompleteServerSnap(); - var nodes = this.writes_.calcIndexedSlice(completeServerData, child, 1, reverse, index); - if (nodes.length === 0) { - return null; - } else { - return nodes[0]; - } -}; diff --git a/src/database/js-client/core/view/Event.js b/src/database/js-client/core/view/Event.js deleted file mode 100644 index ba4d52beca0..00000000000 --- a/src/database/js-client/core/view/Event.js +++ /dev/null @@ -1,155 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.view.CancelEvent'); -goog.provide('fb.core.view.DataEvent'); -goog.provide('fb.core.view.Event'); - -goog.require('fb.util.json'); - - - -/** - * Encapsulates the data needed to raise an event - * @interface - */ -fb.core.view.Event = function() {}; - - -/** - * @return {!fb.core.util.Path} - */ -fb.core.view.Event.prototype.getPath = goog.abstractMethod; - - -/** - * @return {!string} - */ -fb.core.view.Event.prototype.getEventType = goog.abstractMethod; - - -/** - * @return {!function()} - */ -fb.core.view.Event.prototype.getEventRunner = goog.abstractMethod; - - -/** - * @return {!string} - */ -fb.core.view.Event.prototype.toString = goog.abstractMethod; - - - -/** - * Encapsulates the data needed to raise an event - * @param {!string} eventType One of: value, child_added, child_changed, child_moved, child_removed - * @param {!fb.core.view.EventRegistration} eventRegistration The function to call to with the event data. User provided - * @param {!fb.api.DataSnapshot} snapshot The data backing the event - * @param {?string=} opt_prevName Optional, the name of the previous child for child_* events. - * @constructor - * @implements {fb.core.view.Event} - */ -fb.core.view.DataEvent = function(eventType, eventRegistration, snapshot, opt_prevName) { - this.eventRegistration = eventRegistration; - this.snapshot = snapshot; - this.prevName = opt_prevName; - this.eventType = eventType; -}; - - -/** - * @inheritDoc - */ -fb.core.view.DataEvent.prototype.getPath = function() { - var ref = this.snapshot.getRef(); - if (this.eventType === 'value') { - return ref.path; - } else { - return ref.getParent().path; - } -}; - - -/** - * @inheritDoc - */ -fb.core.view.DataEvent.prototype.getEventType = function() { - return this.eventType; -}; - - -/** - * @inheritDoc - */ -fb.core.view.DataEvent.prototype.getEventRunner = function() { - return this.eventRegistration.getEventRunner(this); -}; - - -/** - * @inheritDoc - */ -fb.core.view.DataEvent.prototype.toString = function() { - return this.getPath().toString() + ':' + this.eventType + ':' + - fb.util.json.stringify(this.snapshot.exportVal()); -}; - - - -/** - * @param {fb.core.view.EventRegistration} eventRegistration - * @param {Error} error - * @param {!fb.core.util.Path} path - * @constructor - * @implements {fb.core.view.Event} - */ -fb.core.view.CancelEvent = function(eventRegistration, error, path) { - this.eventRegistration = eventRegistration; - this.error = error; - this.path = path; -}; - - -/** - * @inheritDoc - */ -fb.core.view.CancelEvent.prototype.getPath = function() { - return this.path; -}; - - -/** - * @inheritDoc - */ -fb.core.view.CancelEvent.prototype.getEventType = function() { - return 'cancel'; -}; - - -/** - * @inheritDoc - */ -fb.core.view.CancelEvent.prototype.getEventRunner = function() { - return this.eventRegistration.getEventRunner(this); -}; - - -/** - * @inheritDoc - */ -fb.core.view.CancelEvent.prototype.toString = function() { - return this.path.toString() + ':cancel'; -}; diff --git a/src/database/js-client/core/view/EventGenerator.js b/src/database/js-client/core/view/EventGenerator.js deleted file mode 100644 index e862d3c2b36..00000000000 --- a/src/database/js-client/core/view/EventGenerator.js +++ /dev/null @@ -1,134 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.view.EventGenerator'); -goog.require('fb.core.snap.NamedNode'); -goog.require('fb.core.util'); - -/** - * An EventGenerator is used to convert "raw" changes (fb.core.view.Change) as computed by the - * CacheDiffer into actual events (fb.core.view.Event) that can be raised. See generateEventsForChanges() - * for details. - * - * @param {!fb.api.Query} query - * @constructor - */ -fb.core.view.EventGenerator = function(query) { - /** - * @private - * @type {!fb.api.Query} - */ - this.query_ = query; - - /** - * @private - * @type {!fb.core.snap.Index} - */ - this.index_ = query.getQueryParams().getIndex(); -}; - -/** - * Given a set of raw changes (no moved events and prevName not specified yet), and a set of - * EventRegistrations that should be notified of these changes, generate the actual events to be raised. - * - * Notes: - * - child_moved events will be synthesized at this time for any child_changed events that affect - * our index. - * - prevName will be calculated based on the index ordering. - * - * @param {!Array.} changes - * @param {!fb.core.snap.Node} eventCache - * @param {!Array.} eventRegistrations - * @return {!Array.} - */ -fb.core.view.EventGenerator.prototype.generateEventsForChanges = function(changes, eventCache, eventRegistrations) { - var events = [], self = this; - - var moves = []; - goog.array.forEach(changes, function(change) { - if (change.type === fb.core.view.Change.CHILD_CHANGED && - self.index_.indexedValueChanged(/** @type {!fb.core.snap.Node} */ (change.oldSnap), change.snapshotNode)) { - moves.push(fb.core.view.Change.childMovedChange(/** @type {!string} */ (change.childName), change.snapshotNode)); - } - }); - - this.generateEventsForType_(events, fb.core.view.Change.CHILD_REMOVED, changes, eventRegistrations, eventCache); - this.generateEventsForType_(events, fb.core.view.Change.CHILD_ADDED, changes, eventRegistrations, eventCache); - this.generateEventsForType_(events, fb.core.view.Change.CHILD_MOVED, moves, eventRegistrations, eventCache); - this.generateEventsForType_(events, fb.core.view.Change.CHILD_CHANGED, changes, eventRegistrations, eventCache); - this.generateEventsForType_(events, fb.core.view.Change.VALUE, changes, eventRegistrations, eventCache); - - return events; -}; - -/** - * Given changes of a single change type, generate the corresponding events. - * - * @param {!Array.} events - * @param {!string} eventType - * @param {!Array.} changes - * @param {!Array.} registrations - * @param {!fb.core.snap.Node} eventCache - * @private - */ -fb.core.view.EventGenerator.prototype.generateEventsForType_ = function(events, eventType, changes, registrations, - eventCache) { - var filteredChanges = goog.array.filter(changes, function(change) { - return change.type === eventType; - }); - - var self = this; - goog.array.sort(filteredChanges, goog.bind(this.compareChanges_, this)); - goog.array.forEach(filteredChanges, function(change) { - var materializedChange = self.materializeSingleChange_(change, eventCache); - goog.array.forEach(registrations, function(registration) { - if (registration.respondsTo(change.type)) { - events.push(registration.createEvent(materializedChange, self.query_)); - } - }); - }); -}; - - -/** - * @param {!fb.core.view.Change} change - * @param {!fb.core.snap.Node} eventCache - * @return {!fb.core.view.Change} - * @private - */ -fb.core.view.EventGenerator.prototype.materializeSingleChange_ = function(change, eventCache) { - if (change.type === 'value' || change.type === 'child_removed') { - return change; - } else { - change.prevName = eventCache.getPredecessorChildName(/** @type {!string} */ (change.childName), change.snapshotNode, - this.index_); - return change; - } -}; - -/** - * @param {!fb.core.view.Change} a - * @param {!fb.core.view.Change} b - * @return {number} - * @private - */ -fb.core.view.EventGenerator.prototype.compareChanges_ = function(a, b) { - if (a.childName == null || b.childName == null) { - throw fb.core.util.assertionError('Should only compare child_ events.'); - } - var aWrapped = new fb.core.snap.NamedNode(a.childName, a.snapshotNode); - var bWrapped = new fb.core.snap.NamedNode(b.childName, b.snapshotNode); - return this.index_.compare(aWrapped, bWrapped); -}; diff --git a/src/database/js-client/core/view/EventQueue.js b/src/database/js-client/core/view/EventQueue.js deleted file mode 100644 index eff978e436f..00000000000 --- a/src/database/js-client/core/view/EventQueue.js +++ /dev/null @@ -1,183 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.view.EventQueue'); - -/** - * The event queue serves a few purposes: - * 1. It ensures we maintain event order in the face of event callbacks doing operations that result in more - * events being queued. - * 2. raiseQueuedEvents() handles being called reentrantly nicely. That is, if in the course of raising events, - * raiseQueuedEvents() is called again, the "inner" call will pick up raising events where the "outer" call - * left off, ensuring that the events are still raised synchronously and in order. - * 3. You can use raiseEventsAtPath and raiseEventsForChangedPath to ensure only relevant previously-queued - * events are raised synchronously. - * - * NOTE: This can all go away if/when we move to async events. - * - * @constructor - */ -fb.core.view.EventQueue = function() { - /** - * @private - * @type {!Array.} - */ - this.eventLists_ = []; - - /** - * Tracks recursion depth of raiseQueuedEvents_, for debugging purposes. - * @private - * @type {!number} - */ - this.recursionDepth_ = 0; -}; - -/** - * @param {!Array.} eventDataList The new events to queue. - */ -fb.core.view.EventQueue.prototype.queueEvents = function(eventDataList) { - // We group events by path, storing them in a single EventList, to make it easier to skip over them quickly. - var currList = null; - for (var i = 0; i < eventDataList.length; i++) { - var eventData = eventDataList[i]; - var eventPath = eventData.getPath(); - if (currList !== null && !eventPath.equals(currList.getPath())) { - this.eventLists_.push(currList); - currList = null; - } - - if (currList === null) { - currList = new fb.core.view.EventList(eventPath); - } - - currList.add(eventData); - } - if (currList) { - this.eventLists_.push(currList); - } -}; - -/** - * Queues the specified events and synchronously raises all events (including previously queued ones) - * for the specified path. - * - * It is assumed that the new events are all for the specified path. - * - * @param {!fb.core.util.Path} path The path to raise events for. - * @param {!Array.} eventDataList The new events to raise. - */ -fb.core.view.EventQueue.prototype.raiseEventsAtPath = function(path, eventDataList) { - this.queueEvents(eventDataList); - - this.raiseQueuedEventsMatchingPredicate_(function(eventPath) { - return eventPath.equals(path); - }); -}; - -/** - * Queues the specified events and synchronously raises all events (including previously queued ones) for - * locations related to the specified change path (i.e. all ancestors and descendants). - * - * It is assumed that the new events are all related (ancestor or descendant) to the specified path. - * - * @param {!fb.core.util.Path} changedPath The path to raise events for. - * @param {!Array.} eventDataList The events to raise - */ -fb.core.view.EventQueue.prototype.raiseEventsForChangedPath = function(changedPath, eventDataList) { - this.queueEvents(eventDataList); - - this.raiseQueuedEventsMatchingPredicate_(function(eventPath) { - return eventPath.contains(changedPath) || changedPath.contains(eventPath); - }); -}; - -/** - * @param {!function(!fb.core.util.Path):boolean} predicate - * @private - */ -fb.core.view.EventQueue.prototype.raiseQueuedEventsMatchingPredicate_ = function(predicate) { - this.recursionDepth_++; - - var sentAll = true; - for (var i = 0; i < this.eventLists_.length; i++) { - var eventList = this.eventLists_[i]; - if (eventList) { - var eventPath = eventList.getPath(); - if (predicate(eventPath)) { - this.eventLists_[i].raise(); - this.eventLists_[i] = null; - } else { - sentAll = false; - } - } - } - - if (sentAll) { - this.eventLists_ = []; - } - - this.recursionDepth_--; -}; - - -/** - * @param {!fb.core.util.Path} path - * @constructor - */ -fb.core.view.EventList = function(path) { - /** - * @const - * @type {!fb.core.util.Path} - * @private - */ - this.path_ = path; - /** - * @type {!Array.} - * @private - */ - this.events_ = []; -}; - -/** - * @param {!fb.core.view.Event} eventData - */ -fb.core.view.EventList.prototype.add = function(eventData) { - this.events_.push(eventData); -}; - -/** - * Iterates through the list and raises each event - */ -fb.core.view.EventList.prototype.raise = function() { - for (var i = 0; i < this.events_.length; i++) { - var eventData = this.events_[i]; - if (eventData !== null) { - this.events_[i] = null; - var eventFn = eventData.getEventRunner(); - if (fb.core.util.logger) { - fb.core.util.log('event: ' + eventData.toString()); - } - fb.core.util.exceptionGuard(eventFn); - } - } -}; - -/** - * @return {!fb.core.util.Path} - */ -fb.core.view.EventList.prototype.getPath = function() { - return this.path_; -}; - diff --git a/src/database/js-client/core/view/EventRegistration.js b/src/database/js-client/core/view/EventRegistration.js deleted file mode 100644 index 3aa7be48ea1..00000000000 --- a/src/database/js-client/core/view/EventRegistration.js +++ /dev/null @@ -1,302 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.view.ChildEventRegistration'); -goog.provide('fb.core.view.EventRegistration'); -goog.provide('fb.core.view.ValueEventRegistration'); -goog.require('fb.api.DataSnapshot'); -goog.require('fb.core.util'); -goog.require('fb.core.view.CancelEvent'); -goog.require('fb.core.view.DataEvent'); -goog.require('goog.object'); - - - -/** - * An EventRegistration is basically an event type ('value', 'child_added', etc.) and a callback - * to be notified of that type of event. - * - * That said, it can also contain a cancel callback to be notified if the event is canceled. And - * currently, this code is organized around the idea that you would register multiple child_ callbacks - * together, as a single EventRegistration. Though currently we don't do that. - * - * @interface - */ -fb.core.view.EventRegistration = function() {}; - - -/** - * True if this container has a callback to trigger for this event type - * @param {!string} eventType - * @return {boolean} - */ -fb.core.view.EventRegistration.prototype.respondsTo; - - -/** - * @param {!fb.core.view.Change} change - * @param {!fb.api.Query} query - * @return {!fb.core.view.Event} - */ -fb.core.view.EventRegistration.prototype.createEvent; - - -/** - * Given event data, return a function to trigger the user's callback - * @param {!fb.core.view.Event} eventData - * @return {function()} - */ -fb.core.view.EventRegistration.prototype.getEventRunner; - - -/** - * @param {!Error} error - * @param {!fb.core.util.Path} path - * @return {?fb.core.view.CancelEvent} - */ -fb.core.view.EventRegistration.prototype.createCancelEvent; - - -/** - * @param {!fb.core.view.EventRegistration} other - * @return {boolean} - */ -fb.core.view.EventRegistration.prototype.matches; - - -/** - * False basically means this is a "dummy" callback container being used as a sentinel - * to remove all callback containers of a particular type. (e.g. if the user does - * ref.off('value') without specifying a specific callback). - * - * (TODO: Rework this, since it's hacky) - * - * @return {boolean} - */ -fb.core.view.EventRegistration.prototype.hasAnyCallback; - - - -/** - * Represents registration for 'value' events. - * - * @param {?function(!fb.api.DataSnapshot)} callback - * @param {?function(Error)} cancelCallback - * @param {?Object} context - * @constructor - * @implements {fb.core.view.EventRegistration} - */ -fb.core.view.ValueEventRegistration = function(callback, cancelCallback, context) { - this.callback_ = callback; - this.cancelCallback_ = cancelCallback; - this.context_ = context || null; -}; - - -/** - * @inheritDoc - */ -fb.core.view.ValueEventRegistration.prototype.respondsTo = function(eventType) { - return eventType === 'value'; -}; - - -/** - * @inheritDoc - */ -fb.core.view.ValueEventRegistration.prototype.createEvent = function(change, query) { - var index = query.getQueryParams().getIndex(); - return new fb.core.view.DataEvent('value', this, - new fb.api.DataSnapshot(change.snapshotNode, - query.getRef(), - index)); -}; - - -/** - * @inheritDoc - */ -fb.core.view.ValueEventRegistration.prototype.getEventRunner = function(eventData) { - var ctx = this.context_; - if (eventData.getEventType() === 'cancel') { - fb.core.util.assert(this.cancelCallback_, 'Raising a cancel event on a listener with no cancel callback'); - var cancelCB = this.cancelCallback_; - return function() { - // We know that error exists, we checked above that this is a cancel event - cancelCB.call(ctx, eventData.error); - }; - } else { - var cb = this.callback_; - return function() { - cb.call(ctx, eventData.snapshot); - }; - } -}; - - -/** - * @inheritDoc - */ -fb.core.view.ValueEventRegistration.prototype.createCancelEvent = function(error, path) { - if (this.cancelCallback_) { - return new fb.core.view.CancelEvent(this, error, path); - } else { - return null; - } -}; - - -/** - * @inheritDoc - */ -fb.core.view.ValueEventRegistration.prototype.matches = function(other) { - if (!(other instanceof fb.core.view.ValueEventRegistration)) { - return false; - } else if (!other.callback_ || !this.callback_) { - // If no callback specified, we consider it to match any callback. - return true; - } else { - return other.callback_ === this.callback_ && other.context_ === this.context_; - } -}; - - -/** - * @inheritDoc - */ -fb.core.view.ValueEventRegistration.prototype.hasAnyCallback = function() { - return this.callback_ !== null; -}; - - - -/** - * Represents the registration of 1 or more child_xxx events. - * - * Currently, it is always exactly 1 child_xxx event, but the idea is we might let you - * register a group of callbacks together in the future. - * - * @param {?Object.} callbacks - * @param {?function(Error)} cancelCallback - * @param {Object=} opt_context - * @constructor - * @implements {fb.core.view.EventRegistration} - */ -fb.core.view.ChildEventRegistration = function(callbacks, cancelCallback, opt_context) { - this.callbacks_ = callbacks; - this.cancelCallback_ = cancelCallback; - this.context_ = opt_context; -}; - - -/** - * @inheritDoc - */ -fb.core.view.ChildEventRegistration.prototype.respondsTo = function(eventType) { - var eventToCheck = eventType === 'children_added' ? 'child_added' : eventType; - eventToCheck = eventToCheck === 'children_removed' ? 'child_removed' : eventToCheck; - return goog.object.containsKey(this.callbacks_, eventToCheck); -}; - - -/** - * @inheritDoc - */ -fb.core.view.ChildEventRegistration.prototype.createCancelEvent = function(error, path) { - if (this.cancelCallback_) { - return new fb.core.view.CancelEvent(this, error, path); - } else { - return null; - } -}; - - -/** - * @inheritDoc - */ -fb.core.view.ChildEventRegistration.prototype.createEvent = function(change, query) { - fb.core.util.assert(change.childName != null, 'Child events should have a childName.'); - var ref = query.getRef().child(/** @type {!string} */ (change.childName)); - var index = query.getQueryParams().getIndex(); - return new fb.core.view.DataEvent(change.type, this, new fb.api.DataSnapshot(change.snapshotNode, ref, index), - change.prevName); -}; - - -/** - * @inheritDoc - */ -fb.core.view.ChildEventRegistration.prototype.getEventRunner = function(eventData) { - var ctx = this.context_; - if (eventData.getEventType() === 'cancel') { - fb.core.util.assert(this.cancelCallback_, 'Raising a cancel event on a listener with no cancel callback'); - var cancelCB = this.cancelCallback_; - return function() { - // We know that error exists, we checked above that this is a cancel event - cancelCB.call(ctx, eventData.error); - }; - } else { - var cb = this.callbacks_[eventData.eventType]; - return function() { - cb.call(ctx, eventData.snapshot, eventData.prevName); - } - } -}; - - -/** - * @inheritDoc - */ -fb.core.view.ChildEventRegistration.prototype.matches = function(other) { - if (other instanceof fb.core.view.ChildEventRegistration) { - if (!this.callbacks_ || !other.callbacks_) { - return true; - } else if (this.context_ === other.context_) { - var otherCount = goog.object.getCount(other.callbacks_); - var thisCount = goog.object.getCount(this.callbacks_); - if (otherCount === thisCount) { - // If count is 1, do an exact match on eventType, if either is defined but null, it's a match. - // If event types don't match, not a match - // If count is not 1, exact match across all - - if (otherCount === 1) { - var otherKey = /** @type {!string} */ (goog.object.getAnyKey(other.callbacks_)); - var thisKey = /** @type {!string} */ (goog.object.getAnyKey(this.callbacks_)); - return (thisKey === otherKey && ( - !other.callbacks_[otherKey] || - !this.callbacks_[thisKey] || - other.callbacks_[otherKey] === this.callbacks_[thisKey] - ) - ); - } else { - // Exact match on each key. - return goog.object.every(this.callbacks_, function(cb, eventType) { - return other.callbacks_[eventType] === cb; - }); - } - } - } - } - - return false; -}; - - -/** - * @inheritDoc - */ -fb.core.view.ChildEventRegistration.prototype.hasAnyCallback = function() { - return (this.callbacks_ !== null); -}; diff --git a/src/database/js-client/core/view/QueryParams.js b/src/database/js-client/core/view/QueryParams.js deleted file mode 100644 index e1ac75cad15..00000000000 --- a/src/database/js-client/core/view/QueryParams.js +++ /dev/null @@ -1,429 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.view.QueryParams'); -goog.require('fb.core.snap.Index'); -goog.require('fb.core.snap.PriorityIndex'); -goog.require('fb.core.util'); -goog.require('fb.core.view.filter.IndexedFilter'); -goog.require('fb.core.view.filter.LimitedFilter'); -goog.require('fb.core.view.filter.NodeFilter'); -goog.require('fb.core.view.filter.RangedFilter'); - -/** - * This class is an immutable-from-the-public-api struct containing a set of query parameters defining a - * range to be returned for a particular location. It is assumed that validation of parameters is done at the - * user-facing API level, so it is not done here. - * @constructor - */ -fb.core.view.QueryParams = function() { - this.limitSet_ = false; - this.startSet_ = false; - this.startNameSet_ = false; - this.endSet_ = false; - this.endNameSet_ = false; - - this.limit_ = 0; - this.viewFrom_ = ''; - this.indexStartValue_ = null; - this.indexStartName_ = ''; - this.indexEndValue_ = null; - this.indexEndName_ = ''; - - this.index_ = fb.core.snap.PriorityIndex; -}; - -/** - * Wire Protocol Constants - * @const - * @enum {string} - * @private - */ -fb.core.view.QueryParams.WIRE_PROTOCOL_CONSTANTS_ = { - INDEX_START_VALUE: 'sp', - INDEX_START_NAME: 'sn', - INDEX_END_VALUE: 'ep', - INDEX_END_NAME: 'en', - LIMIT: 'l', - VIEW_FROM: 'vf', - VIEW_FROM_LEFT: 'l', - VIEW_FROM_RIGHT: 'r', - INDEX: 'i' -}; - -/** - * REST Query Constants - * @const - * @enum {string} - * @private - */ -fb.core.view.QueryParams.REST_QUERY_CONSTANTS_ = { - ORDER_BY: 'orderBy', - PRIORITY_INDEX: '$priority', - VALUE_INDEX: '$value', - KEY_INDEX: '$key', - START_AT: 'startAt', - END_AT: 'endAt', - LIMIT_TO_FIRST: 'limitToFirst', - LIMIT_TO_LAST: 'limitToLast' -}; - -/** - * Default, empty query parameters - * @type {!fb.core.view.QueryParams} - * @const - */ -fb.core.view.QueryParams.DEFAULT = new fb.core.view.QueryParams(); - -/** - * @return {boolean} - */ -fb.core.view.QueryParams.prototype.hasStart = function() { - return this.startSet_; -}; - -/** - * @return {boolean} True if it would return from left. - */ -fb.core.view.QueryParams.prototype.isViewFromLeft = function() { - if (this.viewFrom_ === '') { - // limit(), rather than limitToFirst or limitToLast was called. - // This means that only one of startSet_ and endSet_ is true. Use them - // to calculate which side of the view to anchor to. If neither is set, - // anchor to the end. - return this.startSet_; - } else { - return this.viewFrom_ === fb.core.view.QueryParams.WIRE_PROTOCOL_CONSTANTS_.VIEW_FROM_LEFT; - } -}; - -/** - * Only valid to call if hasStart() returns true - * @return {*} - */ -fb.core.view.QueryParams.prototype.getIndexStartValue = function() { - fb.core.util.assert(this.startSet_, 'Only valid if start has been set'); - return this.indexStartValue_; -}; - -/** - * Only valid to call if hasStart() returns true. - * Returns the starting key name for the range defined by these query parameters - * @return {!string} - */ -fb.core.view.QueryParams.prototype.getIndexStartName = function() { - fb.core.util.assert(this.startSet_, 'Only valid if start has been set'); - if (this.startNameSet_) { - return this.indexStartName_; - } else { - return fb.core.util.MIN_NAME; - } -}; - -/** - * @return {boolean} - */ -fb.core.view.QueryParams.prototype.hasEnd = function() { - return this.endSet_; -}; - -/** - * Only valid to call if hasEnd() returns true. - * @return {*} - */ -fb.core.view.QueryParams.prototype.getIndexEndValue = function() { - fb.core.util.assert(this.endSet_, 'Only valid if end has been set'); - return this.indexEndValue_; -}; - -/** - * Only valid to call if hasEnd() returns true. - * Returns the end key name for the range defined by these query parameters - * @return {!string} - */ -fb.core.view.QueryParams.prototype.getIndexEndName = function() { - fb.core.util.assert(this.endSet_, 'Only valid if end has been set'); - if (this.endNameSet_) { - return this.indexEndName_; - } else { - return fb.core.util.MAX_NAME; - } -}; - -/** - * @return {boolean} - */ -fb.core.view.QueryParams.prototype.hasLimit = function() { - return this.limitSet_; -}; - -/** - * @return {boolean} True if a limit has been set and it has been explicitly anchored - */ -fb.core.view.QueryParams.prototype.hasAnchoredLimit = function() { - return this.limitSet_ && this.viewFrom_ !== ''; -}; - -/** - * Only valid to call if hasLimit() returns true - * @return {!number} - */ -fb.core.view.QueryParams.prototype.getLimit = function() { - fb.core.util.assert(this.limitSet_, 'Only valid if limit has been set'); - return this.limit_; -}; - -/** - * @return {!fb.core.snap.Index} - */ -fb.core.view.QueryParams.prototype.getIndex = function() { - return this.index_; -}; - -/** - * @return {!fb.core.view.QueryParams} - * @private - */ -fb.core.view.QueryParams.prototype.copy_ = function() { - var copy = new fb.core.view.QueryParams(); - copy.limitSet_ = this.limitSet_; - copy.limit_ = this.limit_; - copy.startSet_ = this.startSet_; - copy.indexStartValue_ = this.indexStartValue_; - copy.startNameSet_ = this.startNameSet_; - copy.indexStartName_ = this.indexStartName_; - copy.endSet_ = this.endSet_; - copy.indexEndValue_ = this.indexEndValue_; - copy.endNameSet_ = this.endNameSet_; - copy.indexEndName_ = this.indexEndName_; - copy.index_ = this.index_; - copy.viewFrom_ = this.viewFrom_; - return copy; -}; - -/** - * @param {!number} newLimit - * @return {!fb.core.view.QueryParams} - */ -fb.core.view.QueryParams.prototype.limit = function(newLimit) { - var newParams = this.copy_(); - newParams.limitSet_ = true; - newParams.limit_ = newLimit; - newParams.viewFrom_ = ''; - return newParams; -}; - -/** - * @param {!number} newLimit - * @return {!fb.core.view.QueryParams} - */ -fb.core.view.QueryParams.prototype.limitToFirst = function(newLimit) { - var newParams = this.copy_(); - newParams.limitSet_ = true; - newParams.limit_ = newLimit; - newParams.viewFrom_ = fb.core.view.QueryParams.WIRE_PROTOCOL_CONSTANTS_.VIEW_FROM_LEFT; - return newParams; -}; - -/** - * @param {!number} newLimit - * @return {!fb.core.view.QueryParams} - */ -fb.core.view.QueryParams.prototype.limitToLast = function(newLimit) { - var newParams = this.copy_(); - newParams.limitSet_ = true; - newParams.limit_ = newLimit; - newParams.viewFrom_ = fb.core.view.QueryParams.WIRE_PROTOCOL_CONSTANTS_.VIEW_FROM_RIGHT; - return newParams; -}; - -/** - * @param {*} indexValue - * @param {?string=} key - * @return {!fb.core.view.QueryParams} - */ -fb.core.view.QueryParams.prototype.startAt = function(indexValue, key) { - var newParams = this.copy_(); - newParams.startSet_ = true; - if (!goog.isDef(indexValue)) { - indexValue = null; - } - newParams.indexStartValue_ = indexValue; - if (key != null) { - newParams.startNameSet_ = true; - newParams.indexStartName_ = key; - } else { - newParams.startNameSet_ = false; - newParams.indexStartName_ = ''; - } - return newParams; -}; - -/** - * @param {*} indexValue - * @param {?string=} key - * @return {!fb.core.view.QueryParams} - */ -fb.core.view.QueryParams.prototype.endAt = function(indexValue, key) { - var newParams = this.copy_(); - newParams.endSet_ = true; - if (!goog.isDef(indexValue)) { - indexValue = null; - } - newParams.indexEndValue_ = indexValue; - if (goog.isDef(key)) { - newParams.endNameSet_ = true; - newParams.indexEndName_ = key; - } else { - newParams.startEndSet_ = false; - newParams.indexEndName_ = ''; - } - return newParams; -}; - -/** - * @param {!fb.core.snap.Index} index - * @return {!fb.core.view.QueryParams} - */ -fb.core.view.QueryParams.prototype.orderBy = function(index) { - var newParams = this.copy_(); - newParams.index_ = index; - return newParams; -}; - -/** - * @return {!Object} - */ -fb.core.view.QueryParams.prototype.getQueryObject = function() { - var WIRE_PROTOCOL_CONSTANTS = fb.core.view.QueryParams.WIRE_PROTOCOL_CONSTANTS_; - var obj = {}; - if (this.startSet_) { - obj[WIRE_PROTOCOL_CONSTANTS.INDEX_START_VALUE] = this.indexStartValue_; - if (this.startNameSet_) { - obj[WIRE_PROTOCOL_CONSTANTS.INDEX_START_NAME] = this.indexStartName_; - } - } - if (this.endSet_) { - obj[WIRE_PROTOCOL_CONSTANTS.INDEX_END_VALUE] = this.indexEndValue_; - if (this.endNameSet_) { - obj[WIRE_PROTOCOL_CONSTANTS.INDEX_END_NAME] = this.indexEndName_; - } - } - if (this.limitSet_) { - obj[WIRE_PROTOCOL_CONSTANTS.LIMIT] = this.limit_; - var viewFrom = this.viewFrom_; - if (viewFrom === '') { - if (this.isViewFromLeft()) { - viewFrom = WIRE_PROTOCOL_CONSTANTS.VIEW_FROM_LEFT; - } else { - viewFrom = WIRE_PROTOCOL_CONSTANTS.VIEW_FROM_RIGHT; - } - } - obj[WIRE_PROTOCOL_CONSTANTS.VIEW_FROM] = viewFrom; - } - // For now, priority index is the default, so we only specify if it's some other index - if (this.index_ !== fb.core.snap.PriorityIndex) { - obj[WIRE_PROTOCOL_CONSTANTS.INDEX] = this.index_.toString(); - } - return obj; -}; - -/** - * @return {boolean} - */ -fb.core.view.QueryParams.prototype.loadsAllData = function() { - return !(this.startSet_ || this.endSet_ || this.limitSet_); -}; - -/** - * @return {boolean} - */ -fb.core.view.QueryParams.prototype.isDefault = function() { - return this.loadsAllData() && this.index_ == fb.core.snap.PriorityIndex; -}; - -/** - * @return {!fb.core.view.filter.NodeFilter} - */ -fb.core.view.QueryParams.prototype.getNodeFilter = function() { - if (this.loadsAllData()) { - return new fb.core.view.filter.IndexedFilter(this.getIndex()); - } else if (this.hasLimit()) { - return new fb.core.view.filter.LimitedFilter(this); - } else { - return new fb.core.view.filter.RangedFilter(this); - } -}; - - -/** - * Returns a set of REST query string parameters representing this query. - * - * @return {!Object.} query string parameters - */ -fb.core.view.QueryParams.prototype.toRestQueryStringParameters = function() { - var REST_CONSTANTS = fb.core.view.QueryParams.REST_QUERY_CONSTANTS_; - var qs = { }; - - if (this.isDefault()) { - return qs; - } - - var orderBy; - if (this.index_ === fb.core.snap.PriorityIndex) { - orderBy = REST_CONSTANTS.PRIORITY_INDEX; - } else if (this.index_ === fb.core.snap.ValueIndex) { - orderBy = REST_CONSTANTS.VALUE_INDEX; - } else if (this.index_ === fb.core.snap.KeyIndex) { - orderBy = REST_CONSTANTS.KEY_INDEX; - } else { - fb.core.util.assert(this.index_ instanceof fb.core.snap.PathIndex, 'Unrecognized index type!'); - orderBy = this.index_.toString(); - } - qs[REST_CONSTANTS.ORDER_BY] = fb.util.json.stringify(orderBy); - - if (this.startSet_) { - qs[REST_CONSTANTS.START_AT] = fb.util.json.stringify(this.indexStartValue_); - if (this.startNameSet_) { - qs[REST_CONSTANTS.START_AT] += ',' + fb.util.json.stringify(this.indexStartName_); - } - } - - if (this.endSet_) { - qs[REST_CONSTANTS.END_AT] = fb.util.json.stringify(this.indexEndValue_); - if (this.endNameSet_) { - qs[REST_CONSTANTS.END_AT] += ',' + fb.util.json.stringify(this.indexEndName_); - } - } - - if (this.limitSet_) { - if (this.isViewFromLeft()) { - qs[REST_CONSTANTS.LIMIT_TO_FIRST] = this.limit_; - } else { - qs[REST_CONSTANTS.LIMIT_TO_LAST] = this.limit_; - } - } - - return qs; -}; - -if (goog.DEBUG) { - /** - * @inheritDoc - */ - fb.core.view.QueryParams.prototype.toString = function() { - return fb.util.json.stringify(this.getQueryObject()); - }; -} diff --git a/src/database/js-client/core/view/View.js b/src/database/js-client/core/view/View.js deleted file mode 100644 index 6c1a4420181..00000000000 --- a/src/database/js-client/core/view/View.js +++ /dev/null @@ -1,225 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.view.View'); -goog.require('fb.core.view.EventGenerator'); -goog.require('fb.core.view.ViewCache'); -goog.require('fb.core.view.ViewProcessor'); -goog.require('fb.core.util'); - -/** - * A view represents a specific location and query that has 1 or more event registrations. - * - * It does several things: - * - Maintains the list of event registrations for this location/query. - * - Maintains a cache of the data visible for this location/query. - * - Applies new operations (via applyOperation), updates the cache, and based on the event - * registrations returns the set of events to be raised. - * - * @param {!fb.api.Query} query - * @param {!fb.core.view.ViewCache} initialViewCache - * @constructor - */ -fb.core.view.View = function(query, initialViewCache) { - /** - * @type {!fb.api.Query} - * @private - */ - this.query_ = query; - var params = query.getQueryParams(); - - var indexFilter = new fb.core.view.filter.IndexedFilter(params.getIndex()); - var filter = params.getNodeFilter(); - - /** - * @type {fb.core.view.ViewProcessor} - * @private - */ - this.processor_ = new fb.core.view.ViewProcessor(filter); - - var initialServerCache = initialViewCache.getServerCache(); - var initialEventCache = initialViewCache.getEventCache(); - - // Don't filter server node with other filter than index, wait for tagged listen - var serverSnap = indexFilter.updateFullNode(fb.core.snap.EMPTY_NODE, initialServerCache.getNode(), null); - var eventSnap = filter.updateFullNode(fb.core.snap.EMPTY_NODE, initialEventCache.getNode(), null); - var newServerCache = new fb.core.view.CacheNode(serverSnap, initialServerCache.isFullyInitialized(), - indexFilter.filtersNodes()); - var newEventCache = new fb.core.view.CacheNode(eventSnap, initialEventCache.isFullyInitialized(), - filter.filtersNodes()); - - /** - * @type {!fb.core.view.ViewCache} - * @private - */ - this.viewCache_ = new fb.core.view.ViewCache(newEventCache, newServerCache); - - /** - * @type {!Array.} - * @private - */ - this.eventRegistrations_ = []; - - /** - * @type {!fb.core.view.EventGenerator} - * @private - */ - this.eventGenerator_ = new fb.core.view.EventGenerator(query); -}; - -/** - * @return {!fb.api.Query} - */ -fb.core.view.View.prototype.getQuery = function() { - return this.query_; -}; - -/** - * @return {?fb.core.snap.Node} - */ -fb.core.view.View.prototype.getServerCache = function() { - return this.viewCache_.getServerCache().getNode(); -}; - -/** - * @param {!fb.core.util.Path} path - * @return {?fb.core.snap.Node} - */ -fb.core.view.View.prototype.getCompleteServerCache = function(path) { - var cache = this.viewCache_.getCompleteServerSnap(); - if (cache) { - // If this isn't a "loadsAllData" view, then cache isn't actually a complete cache and - // we need to see if it contains the child we're interested in. - if (this.query_.getQueryParams().loadsAllData() || - (!path.isEmpty() && !cache.getImmediateChild(path.getFront()).isEmpty())) { - return cache.getChild(path); - } - } - return null; -}; - -/** - * @return {boolean} - */ -fb.core.view.View.prototype.isEmpty = function() { - return this.eventRegistrations_.length === 0; -}; - -/** - * @param {!fb.core.view.EventRegistration} eventRegistration - */ -fb.core.view.View.prototype.addEventRegistration = function(eventRegistration) { - this.eventRegistrations_.push(eventRegistration); -}; - -/** - * @param {?fb.core.view.EventRegistration} eventRegistration If null, remove all callbacks. - * @param {Error=} cancelError If a cancelError is provided, appropriate cancel events will be returned. - * @return {!Array.} Cancel events, if cancelError was provided. - */ -fb.core.view.View.prototype.removeEventRegistration = function(eventRegistration, cancelError) { - var cancelEvents = []; - if (cancelError) { - fb.core.util.assert(eventRegistration == null, 'A cancel should cancel all event registrations.'); - var path = this.query_.path; - goog.array.forEach(this.eventRegistrations_, function(registration) { - cancelError = /** @type {!Error} */ (cancelError); - var maybeEvent = registration.createCancelEvent(cancelError, path); - if (maybeEvent) { - cancelEvents.push(maybeEvent); - } - }); - } - - if (eventRegistration) { - var remaining = []; - for (var i = 0; i < this.eventRegistrations_.length; ++i) { - var existing = this.eventRegistrations_[i]; - if (!existing.matches(eventRegistration)) { - remaining.push(existing); - } else if (eventRegistration.hasAnyCallback()) { - // We're removing just this one - remaining = remaining.concat(this.eventRegistrations_.slice(i + 1)); - break; - } - } - this.eventRegistrations_ = remaining; - } else { - this.eventRegistrations_ = []; - } - return cancelEvents; -}; - -/** - * Applies the given Operation, updates our cache, and returns the appropriate events. - * - * @param {!fb.core.Operation} operation - * @param {!fb.core.WriteTreeRef} writesCache - * @param {?fb.core.snap.Node} optCompleteServerCache - * @return {!Array.} - */ -fb.core.view.View.prototype.applyOperation = function(operation, writesCache, optCompleteServerCache) { - if (operation.type === fb.core.OperationType.MERGE && - operation.source.queryId !== null) { - - fb.core.util.assert(this.viewCache_.getCompleteServerSnap(), - 'We should always have a full cache before handling merges'); - fb.core.util.assert(this.viewCache_.getCompleteEventSnap(), - 'Missing event cache, even though we have a server cache'); - } - - var oldViewCache = this.viewCache_; - var result = this.processor_.applyOperation(oldViewCache, operation, writesCache, optCompleteServerCache); - this.processor_.assertIndexed(result.viewCache); - - fb.core.util.assert(result.viewCache.getServerCache().isFullyInitialized() || - !oldViewCache.getServerCache().isFullyInitialized(), - 'Once a server snap is complete, it should never go back'); - - this.viewCache_ = result.viewCache; - - return this.generateEventsForChanges_(result.changes, result.viewCache.getEventCache().getNode(), null); -}; - -/** - * @param {!fb.core.view.EventRegistration} registration - * @return {!Array.} - */ -fb.core.view.View.prototype.getInitialEvents = function(registration) { - var eventSnap = this.viewCache_.getEventCache(); - var initialChanges = []; - if (!eventSnap.getNode().isLeafNode()) { - var eventNode = /** @type {!fb.core.snap.ChildrenNode} */ (eventSnap.getNode()); - eventNode.forEachChild(fb.core.snap.PriorityIndex, function(key, childNode) { - initialChanges.push(fb.core.view.Change.childAddedChange(key, childNode)); - }); - } - if (eventSnap.isFullyInitialized()) { - initialChanges.push(fb.core.view.Change.valueChange(eventSnap.getNode())); - } - return this.generateEventsForChanges_(initialChanges, eventSnap.getNode(), registration); -}; - -/** - * @private - * @param {!Array.} changes - * @param {!fb.core.snap.Node} eventCache - * @param {fb.core.view.EventRegistration=} opt_eventRegistration - * @return {!Array.} - */ -fb.core.view.View.prototype.generateEventsForChanges_ = function(changes, eventCache, opt_eventRegistration) { - var registrations = opt_eventRegistration ? [opt_eventRegistration] : this.eventRegistrations_; - return this.eventGenerator_.generateEventsForChanges(changes, eventCache, registrations); -}; diff --git a/src/database/js-client/core/view/ViewCache.js b/src/database/js-client/core/view/ViewCache.js deleted file mode 100644 index d90f9fd4464..00000000000 --- a/src/database/js-client/core/view/ViewCache.js +++ /dev/null @@ -1,100 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.view.ViewCache'); -goog.require('fb.core.view.CacheNode'); -goog.require('fb.core.snap'); - -/** - * Stores the data we have cached for a view. - * - * serverSnap is the cached server data, eventSnap is the cached event data (server data plus any local writes). - * - * @param {!fb.core.view.CacheNode} eventCache - * @param {!fb.core.view.CacheNode} serverCache - * @constructor - */ -fb.core.view.ViewCache = function(eventCache, serverCache) { - /** - * @const - * @type {!fb.core.view.CacheNode} - * @private - */ - this.eventCache_ = eventCache; - - /** - * @const - * @type {!fb.core.view.CacheNode} - * @private - */ - this.serverCache_ = serverCache; -}; - -/** - * @const - * @type {fb.core.view.ViewCache} - */ -fb.core.view.ViewCache.Empty = new fb.core.view.ViewCache( - new fb.core.view.CacheNode(fb.core.snap.EMPTY_NODE, /*fullyInitialized=*/false, /*filtered=*/false), - new fb.core.view.CacheNode(fb.core.snap.EMPTY_NODE, /*fullyInitialized=*/false, /*filtered=*/false) -); - -/** - * @param {!fb.core.snap.Node} eventSnap - * @param {boolean} complete - * @param {boolean} filtered - * @return {!fb.core.view.ViewCache} - */ -fb.core.view.ViewCache.prototype.updateEventSnap = function(eventSnap, complete, filtered) { - return new fb.core.view.ViewCache(new fb.core.view.CacheNode(eventSnap, complete, filtered), this.serverCache_); -}; - -/** - * @param {!fb.core.snap.Node} serverSnap - * @param {boolean} complete - * @param {boolean} filtered - * @return {!fb.core.view.ViewCache} - */ -fb.core.view.ViewCache.prototype.updateServerSnap = function(serverSnap, complete, filtered) { - return new fb.core.view.ViewCache(this.eventCache_, new fb.core.view.CacheNode(serverSnap, complete, filtered)); -}; - -/** - * @return {!fb.core.view.CacheNode} - */ -fb.core.view.ViewCache.prototype.getEventCache = function() { - return this.eventCache_; -}; - -/** - * @return {?fb.core.snap.Node} - */ -fb.core.view.ViewCache.prototype.getCompleteEventSnap = function() { - return (this.eventCache_.isFullyInitialized()) ? this.eventCache_.getNode() : null; -}; - -/** - * @return {!fb.core.view.CacheNode} - */ -fb.core.view.ViewCache.prototype.getServerCache = function() { - return this.serverCache_; -}; - -/** - * @return {?fb.core.snap.Node} - */ -fb.core.view.ViewCache.prototype.getCompleteServerSnap = function() { - return this.serverCache_.isFullyInitialized() ? this.serverCache_.getNode() : null; -}; diff --git a/src/database/js-client/core/view/ViewProcessor.js b/src/database/js-client/core/view/ViewProcessor.js deleted file mode 100644 index 5c8554c5130..00000000000 --- a/src/database/js-client/core/view/ViewProcessor.js +++ /dev/null @@ -1,575 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.view.ViewProcessor'); -goog.require('fb.core.view.CompleteChildSource'); -goog.require('fb.core.util'); - -/** - * @param {!fb.core.view.ViewCache} viewCache - * @param {!Array.} changes - * @constructor - * @struct - */ -fb.core.view.ProcessorResult = function(viewCache, changes) { - /** - * @const - * @type {!fb.core.view.ViewCache} - */ - this.viewCache = viewCache; - - /** - * @const - * @type {!Array.} - */ - this.changes = changes; -}; - - -/** - * @param {!fb.core.view.filter.NodeFilter} filter - * @constructor - */ -fb.core.view.ViewProcessor = function(filter) { - /** - * @type {!fb.core.view.filter.NodeFilter} - * @private - * @const - */ - this.filter_ = filter; -}; - -/** - * @param {!fb.core.view.ViewCache} viewCache - */ -fb.core.view.ViewProcessor.prototype.assertIndexed = function(viewCache) { - fb.core.util.assert(viewCache.getEventCache().getNode().isIndexed(this.filter_.getIndex()), 'Event snap not indexed'); - fb.core.util.assert(viewCache.getServerCache().getNode().isIndexed(this.filter_.getIndex()), - 'Server snap not indexed'); -}; - -/** - * @param {!fb.core.view.ViewCache} oldViewCache - * @param {!fb.core.Operation} operation - * @param {!fb.core.WriteTreeRef} writesCache - * @param {?fb.core.snap.Node} optCompleteCache - * @return {!fb.core.view.ProcessorResult} - */ -fb.core.view.ViewProcessor.prototype.applyOperation = function(oldViewCache, operation, writesCache, optCompleteCache) { - var accumulator = new fb.core.view.ChildChangeAccumulator(); - var newViewCache, filterServerNode; - if (operation.type === fb.core.OperationType.OVERWRITE) { - var overwrite = /** @type {!fb.core.operation.Overwrite} */ (operation); - if (overwrite.source.fromUser) { - newViewCache = this.applyUserOverwrite_(oldViewCache, overwrite.path, overwrite.snap, - writesCache, optCompleteCache, accumulator); - } else { - fb.core.util.assert(overwrite.source.fromServer, 'Unknown source.'); - // We filter the node if it's a tagged update or the node has been previously filtered and the - // update is not at the root in which case it is ok (and necessary) to mark the node unfiltered - // again - filterServerNode = overwrite.source.tagged || - (oldViewCache.getServerCache().isFiltered() && !overwrite.path.isEmpty()); - newViewCache = this.applyServerOverwrite_(oldViewCache, overwrite.path, overwrite.snap, writesCache, - optCompleteCache, filterServerNode, accumulator); - } - } else if (operation.type === fb.core.OperationType.MERGE) { - var merge = /** @type {!fb.core.operation.Merge} */ (operation); - if (merge.source.fromUser) { - newViewCache = this.applyUserMerge_(oldViewCache, merge.path, merge.children, writesCache, - optCompleteCache, accumulator); - } else { - fb.core.util.assert(merge.source.fromServer, 'Unknown source.'); - // We filter the node if it's a tagged update or the node has been previously filtered - filterServerNode = merge.source.tagged || oldViewCache.getServerCache().isFiltered(); - newViewCache = this.applyServerMerge_(oldViewCache, merge.path, merge.children, writesCache, optCompleteCache, - filterServerNode, accumulator); - } - } else if (operation.type === fb.core.OperationType.ACK_USER_WRITE) { - var ackUserWrite = /** @type {!fb.core.operation.AckUserWrite} */ (operation); - if (!ackUserWrite.revert) { - newViewCache = this.ackUserWrite_(oldViewCache, ackUserWrite.path, ackUserWrite.affectedTree, writesCache, - optCompleteCache, accumulator); - } else { - newViewCache = this.revertUserWrite_(oldViewCache, ackUserWrite.path, writesCache, optCompleteCache, accumulator); - } - } else if (operation.type === fb.core.OperationType.LISTEN_COMPLETE) { - newViewCache = this.listenComplete_(oldViewCache, operation.path, writesCache, optCompleteCache, accumulator); - } else { - throw fb.core.util.assertionError('Unknown operation type: ' + operation.type); - } - var changes = accumulator.getChanges(); - this.maybeAddValueEvent_(oldViewCache, newViewCache, changes); - return new fb.core.view.ProcessorResult(newViewCache, changes); -}; - -/** - * @param {!fb.core.view.ViewCache} oldViewCache - * @param {!fb.core.view.ViewCache} newViewCache - * @param {!Array.} accumulator - * @private - */ -fb.core.view.ViewProcessor.prototype.maybeAddValueEvent_ = function(oldViewCache, newViewCache, accumulator) { - var eventSnap = newViewCache.getEventCache(); - if (eventSnap.isFullyInitialized()) { - var isLeafOrEmpty = eventSnap.getNode().isLeafNode() || eventSnap.getNode().isEmpty(); - var oldCompleteSnap = oldViewCache.getCompleteEventSnap(); - if (accumulator.length > 0 || - !oldViewCache.getEventCache().isFullyInitialized() || - (isLeafOrEmpty && !eventSnap.getNode().equals(/** @type {!fb.core.snap.Node} */ (oldCompleteSnap))) || - !eventSnap.getNode().getPriority().equals(oldCompleteSnap.getPriority())) { - accumulator.push(fb.core.view.Change.valueChange( - /** @type {!fb.core.snap.Node} */ (newViewCache.getCompleteEventSnap()))); - } - } -}; - -/** - * @param {!fb.core.view.ViewCache} viewCache - * @param {!fb.core.util.Path} changePath - * @param {!fb.core.WriteTreeRef} writesCache - * @param {!fb.core.view.CompleteChildSource} source - * @param {!fb.core.view.ChildChangeAccumulator} accumulator - * @return {!fb.core.view.ViewCache} - * @private - */ -fb.core.view.ViewProcessor.prototype.generateEventCacheAfterServerEvent_ = function(viewCache, changePath, writesCache, - source, accumulator) { - var oldEventSnap = viewCache.getEventCache(); - if (writesCache.shadowingWrite(changePath) != null) { - // we have a shadowing write, ignore changes - return viewCache; - } else { - var newEventCache, serverNode; - if (changePath.isEmpty()) { - // TODO: figure out how this plays with "sliding ack windows" - fb.core.util.assert(viewCache.getServerCache().isFullyInitialized(), - 'If change path is empty, we must have complete server data'); - if (viewCache.getServerCache().isFiltered()) { - // We need to special case this, because we need to only apply writes to complete children, or - // we might end up raising events for incomplete children. If the server data is filtered deep - // writes cannot be guaranteed to be complete - var serverCache = viewCache.getCompleteServerSnap(); - var completeChildren = (serverCache instanceof fb.core.snap.ChildrenNode) ? serverCache : - fb.core.snap.EMPTY_NODE; - var completeEventChildren = writesCache.calcCompleteEventChildren(completeChildren); - newEventCache = this.filter_.updateFullNode(viewCache.getEventCache().getNode(), completeEventChildren, - accumulator); - } else { - var completeNode = /** @type {!fb.core.snap.Node} */ - (writesCache.calcCompleteEventCache(viewCache.getCompleteServerSnap())); - newEventCache = this.filter_.updateFullNode(viewCache.getEventCache().getNode(), completeNode, accumulator); - } - } else { - var childKey = changePath.getFront(); - if (childKey == '.priority') { - fb.core.util.assert(changePath.getLength() == 1, "Can't have a priority with additional path components"); - var oldEventNode = oldEventSnap.getNode(); - serverNode = viewCache.getServerCache().getNode(); - // we might have overwrites for this priority - var updatedPriority = writesCache.calcEventCacheAfterServerOverwrite(changePath, oldEventNode, serverNode); - if (updatedPriority != null) { - newEventCache = this.filter_.updatePriority(oldEventNode, updatedPriority); - } else { - // priority didn't change, keep old node - newEventCache = oldEventSnap.getNode(); - } - } else { - var childChangePath = changePath.popFront(); - // update child - var newEventChild; - if (oldEventSnap.isCompleteForChild(childKey)) { - serverNode = viewCache.getServerCache().getNode(); - var eventChildUpdate = writesCache.calcEventCacheAfterServerOverwrite(changePath, oldEventSnap.getNode(), - serverNode); - if (eventChildUpdate != null) { - newEventChild = oldEventSnap.getNode().getImmediateChild(childKey).updateChild(childChangePath, - eventChildUpdate); - } else { - // Nothing changed, just keep the old child - newEventChild = oldEventSnap.getNode().getImmediateChild(childKey); - } - } else { - newEventChild = writesCache.calcCompleteChild(childKey, viewCache.getServerCache()); - } - if (newEventChild != null) { - newEventCache = this.filter_.updateChild(oldEventSnap.getNode(), childKey, newEventChild, childChangePath, - source, accumulator); - } else { - // no complete child available or no change - newEventCache = oldEventSnap.getNode(); - } - } - } - return viewCache.updateEventSnap(newEventCache, oldEventSnap.isFullyInitialized() || changePath.isEmpty(), - this.filter_.filtersNodes()); - } -}; - -/** - * @param {!fb.core.view.ViewCache} oldViewCache - * @param {!fb.core.util.Path} changePath - * @param {!fb.core.snap.Node} changedSnap - * @param {!fb.core.WriteTreeRef} writesCache - * @param {?fb.core.snap.Node} optCompleteCache - * @param {boolean} filterServerNode - * @param {!fb.core.view.ChildChangeAccumulator} accumulator - * @return {!fb.core.view.ViewCache} - * @private - */ -fb.core.view.ViewProcessor.prototype.applyServerOverwrite_ = function(oldViewCache, changePath, changedSnap, - writesCache, optCompleteCache, filterServerNode, - accumulator) { - var oldServerSnap = oldViewCache.getServerCache(); - var newServerCache; - var serverFilter = filterServerNode ? this.filter_ : this.filter_.getIndexedFilter(); - if (changePath.isEmpty()) { - newServerCache = serverFilter.updateFullNode(oldServerSnap.getNode(), changedSnap, null); - } else if (serverFilter.filtersNodes() && !oldServerSnap.isFiltered()) { - // we want to filter the server node, but we didn't filter the server node yet, so simulate a full update - var newServerNode = oldServerSnap.getNode().updateChild(changePath, changedSnap); - newServerCache = serverFilter.updateFullNode(oldServerSnap.getNode(), newServerNode, null); - } else { - var childKey = changePath.getFront(); - if (!oldServerSnap.isCompleteForPath(changePath) && changePath.getLength() > 1) { - // We don't update incomplete nodes with updates intended for other listeners - return oldViewCache; - } - var childChangePath = changePath.popFront(); - var childNode = oldServerSnap.getNode().getImmediateChild(childKey); - var newChildNode = childNode.updateChild(childChangePath, changedSnap); - if (childKey == '.priority') { - newServerCache = serverFilter.updatePriority(oldServerSnap.getNode(), newChildNode); - } else { - newServerCache = serverFilter.updateChild(oldServerSnap.getNode(), childKey, newChildNode, childChangePath, - fb.core.view.NO_COMPLETE_CHILD_SOURCE, null); - } - } - var newViewCache = oldViewCache.updateServerSnap(newServerCache, - oldServerSnap.isFullyInitialized() || changePath.isEmpty(), serverFilter.filtersNodes()); - var source = new fb.core.view.WriteTreeCompleteChildSource(writesCache, newViewCache, optCompleteCache); - return this.generateEventCacheAfterServerEvent_(newViewCache, changePath, writesCache, source, accumulator); -}; - -/** - * @param {!fb.core.view.ViewCache} oldViewCache - * @param {!fb.core.util.Path} changePath - * @param {!fb.core.snap.Node} changedSnap - * @param {!fb.core.WriteTreeRef} writesCache - * @param {?fb.core.snap.Node} optCompleteCache - * @param {!fb.core.view.ChildChangeAccumulator} accumulator - * @return {!fb.core.view.ViewCache} - * @private - */ -fb.core.view.ViewProcessor.prototype.applyUserOverwrite_ = function(oldViewCache, changePath, changedSnap, writesCache, - optCompleteCache, accumulator) { - var oldEventSnap = oldViewCache.getEventCache(); - var newViewCache, newEventCache; - var source = new fb.core.view.WriteTreeCompleteChildSource(writesCache, oldViewCache, optCompleteCache); - if (changePath.isEmpty()) { - newEventCache = this.filter_.updateFullNode(oldViewCache.getEventCache().getNode(), changedSnap, accumulator); - newViewCache = oldViewCache.updateEventSnap(newEventCache, true, this.filter_.filtersNodes()); - } else { - var childKey = changePath.getFront(); - if (childKey === '.priority') { - newEventCache = this.filter_.updatePriority(oldViewCache.getEventCache().getNode(), changedSnap); - newViewCache = oldViewCache.updateEventSnap(newEventCache, oldEventSnap.isFullyInitialized(), - oldEventSnap.isFiltered()); - } else { - var childChangePath = changePath.popFront(); - var oldChild = oldEventSnap.getNode().getImmediateChild(childKey); - var newChild; - if (childChangePath.isEmpty()) { - // Child overwrite, we can replace the child - newChild = changedSnap; - } else { - var childNode = source.getCompleteChild(childKey); - if (childNode != null) { - if (childChangePath.getBack() === '.priority' && - childNode.getChild(/** @type {!fb.core.util.Path} */ (childChangePath.parent())).isEmpty()) { - // This is a priority update on an empty node. If this node exists on the server, the - // server will send down the priority in the update, so ignore for now - newChild = childNode; - } else { - newChild = childNode.updateChild(childChangePath, changedSnap); - } - } else { - // There is no complete child node available - newChild = fb.core.snap.EMPTY_NODE; - } - } - if (!oldChild.equals(newChild)) { - var newEventSnap = this.filter_.updateChild(oldEventSnap.getNode(), childKey, newChild, childChangePath, - source, accumulator); - newViewCache = oldViewCache.updateEventSnap(newEventSnap, oldEventSnap.isFullyInitialized(), - this.filter_.filtersNodes()); - } else { - newViewCache = oldViewCache; - } - } - } - return newViewCache; -}; - -/** - * @param {!fb.core.view.ViewCache} viewCache - * @param {string} childKey - * @return {boolean} - * @private - */ -fb.core.view.ViewProcessor.cacheHasChild_ = function(viewCache, childKey) { - return viewCache.getEventCache().isCompleteForChild(childKey); -}; - -/** - * @param {!fb.core.view.ViewCache} viewCache - * @param {!fb.core.util.Path} path - * @param {fb.core.util.ImmutableTree.} changedChildren - * @param {!fb.core.WriteTreeRef} writesCache - * @param {?fb.core.snap.Node} serverCache - * @param {!fb.core.view.ChildChangeAccumulator} accumulator - * @return {!fb.core.view.ViewCache} - * @private - */ -fb.core.view.ViewProcessor.prototype.applyUserMerge_ = function(viewCache, path, changedChildren, writesCache, - serverCache, accumulator) { - // HACK: In the case of a limit query, there may be some changes that bump things out of the - // window leaving room for new items. It's important we process these changes first, so we - // iterate the changes twice, first processing any that affect items currently in view. - // TODO: I consider an item "in view" if cacheHasChild is true, which checks both the server - // and event snap. I'm not sure if this will result in edge cases when a child is in one but - // not the other. - var self = this; - var curViewCache = viewCache; - changedChildren.foreach(function(relativePath, childNode) { - var writePath = path.child(relativePath); - if (fb.core.view.ViewProcessor.cacheHasChild_(viewCache, writePath.getFront())) { - curViewCache = self.applyUserOverwrite_(curViewCache, writePath, childNode, writesCache, - serverCache, accumulator); - } - }); - - changedChildren.foreach(function(relativePath, childNode) { - var writePath = path.child(relativePath); - if (!fb.core.view.ViewProcessor.cacheHasChild_(viewCache, writePath.getFront())) { - curViewCache = self.applyUserOverwrite_(curViewCache, writePath, childNode, writesCache, - serverCache, accumulator); - } - }); - - return curViewCache; -}; - -/** - * @param {!fb.core.snap.Node} node - * @param {fb.core.util.ImmutableTree.} merge - * @return {!fb.core.snap.Node} - * @private - */ -fb.core.view.ViewProcessor.prototype.applyMerge_ = function(node, merge) { - merge.foreach(function(relativePath, childNode) { - node = node.updateChild(relativePath, childNode); - }); - return node; -}; - -/** - * @param {!fb.core.view.ViewCache} viewCache - * @param {!fb.core.util.Path} path - * @param {!fb.core.util.ImmutableTree.} changedChildren - * @param {!fb.core.WriteTreeRef} writesCache - * @param {?fb.core.snap.Node} serverCache - * @param {boolean} filterServerNode - * @param {!fb.core.view.ChildChangeAccumulator} accumulator - * @return {!fb.core.view.ViewCache} - * @private - */ -fb.core.view.ViewProcessor.prototype.applyServerMerge_ = function(viewCache, path, changedChildren, - writesCache, serverCache, filterServerNode, - accumulator) { - // If we don't have a cache yet, this merge was intended for a previously listen in the same location. Ignore it and - // wait for the complete data update coming soon. - if (viewCache.getServerCache().getNode().isEmpty() && !viewCache.getServerCache().isFullyInitialized()) { - return viewCache; - } - - // HACK: In the case of a limit query, there may be some changes that bump things out of the - // window leaving room for new items. It's important we process these changes first, so we - // iterate the changes twice, first processing any that affect items currently in view. - // TODO: I consider an item "in view" if cacheHasChild is true, which checks both the server - // and event snap. I'm not sure if this will result in edge cases when a child is in one but - // not the other. - var curViewCache = viewCache; - var viewMergeTree; - if (path.isEmpty()) { - viewMergeTree = changedChildren; - } else { - viewMergeTree = fb.core.util.ImmutableTree.Empty.setTree(path, changedChildren); - } - var serverNode = viewCache.getServerCache().getNode(); - var self = this; - viewMergeTree.children.inorderTraversal(function(childKey, childTree) { - if (serverNode.hasChild(childKey)) { - var serverChild = viewCache.getServerCache().getNode().getImmediateChild(childKey); - var newChild = self.applyMerge_(serverChild, childTree); - curViewCache = self.applyServerOverwrite_(curViewCache, new fb.core.util.Path(childKey), newChild, - writesCache, serverCache, filterServerNode, accumulator); - } - }); - viewMergeTree.children.inorderTraversal(function(childKey, childMergeTree) { - var isUnknownDeepMerge = !viewCache.getServerCache().isCompleteForChild(childKey) && childMergeTree.value == null; - if (!serverNode.hasChild(childKey) && !isUnknownDeepMerge) { - var serverChild = viewCache.getServerCache().getNode().getImmediateChild(childKey); - var newChild = self.applyMerge_(serverChild, childMergeTree); - curViewCache = self.applyServerOverwrite_(curViewCache, new fb.core.util.Path(childKey), newChild, writesCache, - serverCache, filterServerNode, accumulator); - } - }); - - return curViewCache; -}; - -/** - * @param {!fb.core.view.ViewCache} viewCache - * @param {!fb.core.util.Path} ackPath - * @param {!fb.core.util.ImmutableTree} affectedTree - * @param {!fb.core.WriteTreeRef} writesCache - * @param {?fb.core.snap.Node} optCompleteCache - * @param {!fb.core.view.ChildChangeAccumulator} accumulator - * @return {!fb.core.view.ViewCache} - * @private - */ -fb.core.view.ViewProcessor.prototype.ackUserWrite_ = function(viewCache, ackPath, affectedTree, writesCache, - optCompleteCache, accumulator) { - if (writesCache.shadowingWrite(ackPath) != null) { - return viewCache; - } - - // Only filter server node if it is currently filtered - var filterServerNode = viewCache.getServerCache().isFiltered(); - - // Essentially we'll just get our existing server cache for the affected paths and re-apply it as a server update - // now that it won't be shadowed. - var serverCache = viewCache.getServerCache(); - if (affectedTree.value != null) { - // This is an overwrite. - if ((ackPath.isEmpty() && serverCache.isFullyInitialized()) || serverCache.isCompleteForPath(ackPath)) { - return this.applyServerOverwrite_(viewCache, ackPath, serverCache.getNode().getChild(ackPath), - writesCache, optCompleteCache, filterServerNode, accumulator); - } else if (ackPath.isEmpty()) { - // This is a goofy edge case where we are acking data at this location but don't have full data. We - // should just re-apply whatever we have in our cache as a merge. - var changedChildren = /** @type {fb.core.util.ImmutableTree} */ - (fb.core.util.ImmutableTree.Empty); - serverCache.getNode().forEachChild(fb.core.snap.KeyIndex, function(name, node) { - changedChildren = changedChildren.set(new fb.core.util.Path(name), node); - }); - return this.applyServerMerge_(viewCache, ackPath, changedChildren, writesCache, optCompleteCache, - filterServerNode, accumulator); - } else { - return viewCache; - } - } else { - // This is a merge. - var changedChildren = /** @type {fb.core.util.ImmutableTree} */ - (fb.core.util.ImmutableTree.Empty); - affectedTree.foreach(function(mergePath, value) { - var serverCachePath = ackPath.child(mergePath); - if (serverCache.isCompleteForPath(serverCachePath)) { - changedChildren = changedChildren.set(mergePath, serverCache.getNode().getChild(serverCachePath)); - } - }); - return this.applyServerMerge_(viewCache, ackPath, changedChildren, writesCache, optCompleteCache, - filterServerNode, accumulator); - } -}; - -/** - * @param {!fb.core.view.ViewCache} viewCache - * @param {!fb.core.util.Path} path - * @param {!fb.core.WriteTreeRef} writesCache - * @param {?fb.core.snap.Node} optCompleteServerCache - * @param {!fb.core.view.ChildChangeAccumulator} accumulator - * @return {!fb.core.view.ViewCache} - * @private - */ -fb.core.view.ViewProcessor.prototype.revertUserWrite_ = function(viewCache, path, writesCache, optCompleteServerCache, - accumulator) { - var complete; - if (writesCache.shadowingWrite(path) != null) { - return viewCache; - } else { - var source = new fb.core.view.WriteTreeCompleteChildSource(writesCache, viewCache, optCompleteServerCache); - var oldEventCache = viewCache.getEventCache().getNode(); - var newEventCache; - if (path.isEmpty() || path.getFront() === '.priority') { - var newNode; - if (viewCache.getServerCache().isFullyInitialized()) { - newNode = writesCache.calcCompleteEventCache(viewCache.getCompleteServerSnap()); - } else { - var serverChildren = viewCache.getServerCache().getNode(); - fb.core.util.assert(serverChildren instanceof fb.core.snap.ChildrenNode, - 'serverChildren would be complete if leaf node'); - newNode = writesCache.calcCompleteEventChildren(/** @type {!fb.core.snap.ChildrenNode} */ (serverChildren)); - } - newNode = /** @type {!fb.core.snap.Node} newNode */ (newNode); - newEventCache = this.filter_.updateFullNode(oldEventCache, newNode, accumulator); - } else { - var childKey = path.getFront(); - var newChild = writesCache.calcCompleteChild(childKey, viewCache.getServerCache()); - if (newChild == null && viewCache.getServerCache().isCompleteForChild(childKey)) { - newChild = oldEventCache.getImmediateChild(childKey); - } - if (newChild != null) { - newEventCache = this.filter_.updateChild(oldEventCache, childKey, newChild, path.popFront(), source, - accumulator); - } else if (viewCache.getEventCache().getNode().hasChild(childKey)) { - // No complete child available, delete the existing one, if any - newEventCache = this.filter_.updateChild(oldEventCache, childKey, fb.core.snap.EMPTY_NODE, path.popFront(), - source, accumulator); - } else { - newEventCache = oldEventCache; - } - if (newEventCache.isEmpty() && viewCache.getServerCache().isFullyInitialized()) { - // We might have reverted all child writes. Maybe the old event was a leaf node - complete = writesCache.calcCompleteEventCache(viewCache.getCompleteServerSnap()); - if (complete.isLeafNode()) { - newEventCache = this.filter_.updateFullNode(newEventCache, complete, accumulator); - } - } - } - complete = viewCache.getServerCache().isFullyInitialized() || - writesCache.shadowingWrite(fb.core.util.Path.Empty) != null; - return viewCache.updateEventSnap(newEventCache, complete, this.filter_.filtersNodes()); - } -}; - -/** - * @param {!fb.core.view.ViewCache} viewCache - * @param {!fb.core.util.Path} path - * @param {!fb.core.WriteTreeRef} writesCache - * @param {?fb.core.snap.Node} serverCache - * @param {!fb.core.view.ChildChangeAccumulator} accumulator - * @return {!fb.core.view.ViewCache} - * @private - */ -fb.core.view.ViewProcessor.prototype.listenComplete_ = function(viewCache, path, writesCache, serverCache, - accumulator) { - var oldServerNode = viewCache.getServerCache(); - var newViewCache = viewCache.updateServerSnap(oldServerNode.getNode(), - oldServerNode.isFullyInitialized() || path.isEmpty(), oldServerNode.isFiltered()); - return this.generateEventCacheAfterServerEvent_(newViewCache, path, writesCache, - fb.core.view.NO_COMPLETE_CHILD_SOURCE, accumulator); -}; diff --git a/src/database/js-client/core/view/filter/IndexedFilter.js b/src/database/js-client/core/view/filter/IndexedFilter.js deleted file mode 100644 index 8edebe9246e..00000000000 --- a/src/database/js-client/core/view/filter/IndexedFilter.js +++ /dev/null @@ -1,137 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.view.filter.IndexedFilter'); -goog.require('fb.core.util'); - -/** - * Doesn't really filter nodes but applies an index to the node and keeps track of any changes - * - * @constructor - * @implements {fb.core.view.filter.NodeFilter} - * @param {!fb.core.snap.Index} index - */ -fb.core.view.filter.IndexedFilter = function(index) { - /** - * @type {!fb.core.snap.Index} - * @const - * @private - */ - this.index_ = index; -}; - -/** - * @inheritDoc - */ -fb.core.view.filter.IndexedFilter.prototype.updateChild = function(snap, key, newChild, affectedPath, source, - optChangeAccumulator) { - var Change = fb.core.view.Change; - fb.core.util.assert(snap.isIndexed(this.index_), 'A node must be indexed if only a child is updated'); - var oldChild = snap.getImmediateChild(key); - // Check if anything actually changed. - if (oldChild.getChild(affectedPath).equals(newChild.getChild(affectedPath))) { - // There's an edge case where a child can enter or leave the view because affectedPath was set to null. - // In this case, affectedPath will appear null in both the old and new snapshots. So we need - // to avoid treating these cases as "nothing changed." - if (oldChild.isEmpty() == newChild.isEmpty()) { - // Nothing changed. - - // This assert should be valid, but it's expensive (can dominate perf testing) so don't actually do it. - //fb.core.util.assert(oldChild.equals(newChild), 'Old and new snapshots should be equal.'); - return snap; - } - } - - if (optChangeAccumulator != null) { - if (newChild.isEmpty()) { - if (snap.hasChild(key)) { - optChangeAccumulator.trackChildChange(Change.childRemovedChange(key, oldChild)); - } else { - fb.core.util.assert(snap.isLeafNode(), 'A child remove without an old child only makes sense on a leaf node'); - } - } else if (oldChild.isEmpty()) { - optChangeAccumulator.trackChildChange(Change.childAddedChange(key, newChild)); - } else { - optChangeAccumulator.trackChildChange(Change.childChangedChange(key, newChild, oldChild)); - } - } - if (snap.isLeafNode() && newChild.isEmpty()) { - return snap; - } else { - // Make sure the node is indexed - return snap.updateImmediateChild(key, newChild).withIndex(this.index_); - } -}; - -/** - * @inheritDoc - */ -fb.core.view.filter.IndexedFilter.prototype.updateFullNode = function(oldSnap, newSnap, optChangeAccumulator) { - var Change = fb.core.view.Change; - if (optChangeAccumulator != null) { - if (!oldSnap.isLeafNode()) { - oldSnap.forEachChild(fb.core.snap.PriorityIndex, function(key, childNode) { - if (!newSnap.hasChild(key)) { - optChangeAccumulator.trackChildChange(Change.childRemovedChange(key, childNode)); - } - }); - } - if (!newSnap.isLeafNode()) { - newSnap.forEachChild(fb.core.snap.PriorityIndex, function(key, childNode) { - if (oldSnap.hasChild(key)) { - var oldChild = oldSnap.getImmediateChild(key); - if (!oldChild.equals(childNode)) { - optChangeAccumulator.trackChildChange(Change.childChangedChange(key, childNode, oldChild)); - } - } else { - optChangeAccumulator.trackChildChange(Change.childAddedChange(key, childNode)); - } - }); - } - } - return newSnap.withIndex(this.index_); -}; - -/** - * @inheritDoc - */ -fb.core.view.filter.IndexedFilter.prototype.updatePriority = function(oldSnap, newPriority) { - if (oldSnap.isEmpty()) { - return fb.core.snap.EMPTY_NODE; - } else { - return oldSnap.updatePriority(newPriority); - } -}; - -/** - * @inheritDoc - */ -fb.core.view.filter.IndexedFilter.prototype.filtersNodes = function() { - return false; -}; - -/** - * @inheritDoc - */ -fb.core.view.filter.IndexedFilter.prototype.getIndexedFilter = function() { - return this; -}; - -/** - * @inheritDoc - */ -fb.core.view.filter.IndexedFilter.prototype.getIndex = function() { - return this.index_; -}; diff --git a/src/database/js-client/core/view/filter/LimitedFilter.js b/src/database/js-client/core/view/filter/LimitedFilter.js deleted file mode 100644 index dd3e13e1eff..00000000000 --- a/src/database/js-client/core/view/filter/LimitedFilter.js +++ /dev/null @@ -1,259 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.view.filter.LimitedFilter'); -goog.require('fb.core.snap.NamedNode'); -goog.require('fb.core.view.filter.RangedFilter'); -goog.require('fb.core.util'); - -/** - * Applies a limit and a range to a node and uses RangedFilter to do the heavy lifting where possible - * - * @constructor - * @implements {fb.core.view.filter.NodeFilter} - * @param {!fb.core.view.QueryParams} params - */ -fb.core.view.filter.LimitedFilter = function(params) { - /** - * @const - * @type {fb.core.view.filter.RangedFilter} - * @private - */ - this.rangedFilter_ = new fb.core.view.filter.RangedFilter(params); - - /** - * @const - * @type {!fb.core.snap.Index} - * @private - */ - this.index_ = params.getIndex(); - - /** - * @const - * @type {number} - * @private - */ - this.limit_ = params.getLimit(); - - /** - * @const - * @type {boolean} - * @private - */ - this.reverse_ = !params.isViewFromLeft(); -}; - -/** - * @inheritDoc - */ -fb.core.view.filter.LimitedFilter.prototype.updateChild = function(snap, key, newChild, affectedPath, source, - optChangeAccumulator) { - if (!this.rangedFilter_.matches(new fb.core.snap.NamedNode(key, newChild))) { - newChild = fb.core.snap.EMPTY_NODE; - } - if (snap.getImmediateChild(key).equals(newChild)) { - // No change - return snap; - } else if (snap.numChildren() < this.limit_) { - return this.rangedFilter_.getIndexedFilter().updateChild(snap, key, newChild, affectedPath, source, - optChangeAccumulator); - } else { - return this.fullLimitUpdateChild_(snap, key, newChild, source, optChangeAccumulator); - } -}; - -/** - * @inheritDoc - */ -fb.core.view.filter.LimitedFilter.prototype.updateFullNode = function(oldSnap, newSnap, optChangeAccumulator) { - var filtered; - if (newSnap.isLeafNode() || newSnap.isEmpty()) { - // Make sure we have a children node with the correct index, not a leaf node; - filtered = fb.core.snap.EMPTY_NODE.withIndex(this.index_); - } else { - if (this.limit_ * 2 < newSnap.numChildren() && newSnap.isIndexed(this.index_)) { - // Easier to build up a snapshot, since what we're given has more than twice the elements we want - filtered = fb.core.snap.EMPTY_NODE.withIndex(this.index_); - // anchor to the startPost, endPost, or last element as appropriate - var iterator; - newSnap = /** @type {!fb.core.snap.ChildrenNode} */ (newSnap); - if (this.reverse_) { - iterator = newSnap.getReverseIteratorFrom(this.rangedFilter_.getEndPost(), this.index_); - } else { - iterator = newSnap.getIteratorFrom(this.rangedFilter_.getStartPost(), this.index_); - } - var count = 0; - while (iterator.hasNext() && count < this.limit_) { - var next = iterator.getNext(); - var inRange; - if (this.reverse_) { - inRange = this.index_.compare(this.rangedFilter_.getStartPost(), next) <= 0; - } else { - inRange = this.index_.compare(next, this.rangedFilter_.getEndPost()) <= 0; - } - if (inRange) { - filtered = filtered.updateImmediateChild(next.name, next.node); - count++; - } else { - // if we have reached the end post, we cannot keep adding elemments - break; - } - } - } else { - // The snap contains less than twice the limit. Faster to delete from the snap than build up a new one - filtered = newSnap.withIndex(this.index_); - // Don't support priorities on queries - filtered = /** @type {!fb.core.snap.ChildrenNode} */ (filtered.updatePriority(fb.core.snap.EMPTY_NODE)); - var startPost; - var endPost; - var cmp; - if (this.reverse_) { - iterator = filtered.getReverseIterator(this.index_); - startPost = this.rangedFilter_.getEndPost(); - endPost = this.rangedFilter_.getStartPost(); - var indexCompare = this.index_.getCompare(); - cmp = function(a, b) { return indexCompare(b, a); }; - } else { - iterator = filtered.getIterator(this.index_); - startPost = this.rangedFilter_.getStartPost(); - endPost = this.rangedFilter_.getEndPost(); - cmp = this.index_.getCompare(); - } - - count = 0; - var foundStartPost = false; - while (iterator.hasNext()) { - next = iterator.getNext(); - if (!foundStartPost && cmp(startPost, next) <= 0) { - // start adding - foundStartPost = true; - } - inRange = foundStartPost && count < this.limit_ && cmp(next, endPost) <= 0; - if (inRange) { - count++; - } else { - filtered = filtered.updateImmediateChild(next.name, fb.core.snap.EMPTY_NODE); - } - } - } - } - return this.rangedFilter_.getIndexedFilter().updateFullNode(oldSnap, filtered, optChangeAccumulator); -}; - -/** - * @inheritDoc - */ -fb.core.view.filter.LimitedFilter.prototype.updatePriority = function(oldSnap, newPriority) { - // Don't support priorities on queries - return oldSnap; -}; - -/** - * @inheritDoc - */ -fb.core.view.filter.LimitedFilter.prototype.filtersNodes = function() { - return true; -}; - -/** - * @inheritDoc - */ -fb.core.view.filter.LimitedFilter.prototype.getIndexedFilter = function() { - return this.rangedFilter_.getIndexedFilter(); -}; - -/** - * @inheritDoc - */ -fb.core.view.filter.LimitedFilter.prototype.getIndex = function() { - return this.index_; -}; - -/** - * @param {!fb.core.snap.Node} snap - * @param {string} childKey - * @param {!fb.core.snap.Node} childSnap - * @param {!fb.core.view.CompleteChildSource} source - * @param {?fb.core.view.ChildChangeAccumulator} optChangeAccumulator - * @return {!fb.core.snap.Node} - * @private - */ -fb.core.view.filter.LimitedFilter.prototype.fullLimitUpdateChild_ = function(snap, childKey, childSnap, source, - optChangeAccumulator) { - // TODO: rename all cache stuff etc to general snap terminology - var Change = fb.core.view.Change; - var cmp; - if (this.reverse_) { - var indexCmp = this.index_.getCompare(); - cmp = function(a, b) { return indexCmp(b, a); }; - } else { - cmp = this.index_.getCompare(); - } - var oldEventCache = /** @type {!fb.core.snap.ChildrenNode} */ (snap); - fb.core.util.assert(oldEventCache.numChildren() == this.limit_, ''); - var newChildNamedNode = new fb.core.snap.NamedNode(childKey, childSnap); - var windowBoundary = /** @type {!fb.core.snap.NamedNode} */ - (this.reverse_ ? oldEventCache.getFirstChild(this.index_) : - oldEventCache.getLastChild(this.index_)); - var inRange = this.rangedFilter_.matches(newChildNamedNode); - if (oldEventCache.hasChild(childKey)) { - var oldChildSnap = oldEventCache.getImmediateChild(childKey); - var nextChild = source.getChildAfterChild(this.index_, windowBoundary, this.reverse_); - while (nextChild != null && (nextChild.name == childKey || oldEventCache.hasChild(nextChild.name))) { - // There is a weird edge case where a node is updated as part of a merge in the write tree, but hasn't - // been applied to the limited filter yet. Ignore this next child which will be updated later in - // the limited filter... - nextChild = source.getChildAfterChild(this.index_, nextChild, this.reverse_); - } - var compareNext = nextChild == null ? 1 : cmp(nextChild, newChildNamedNode); - var remainsInWindow = inRange && !childSnap.isEmpty() && compareNext >= 0; - if (remainsInWindow) { - if (optChangeAccumulator != null) { - optChangeAccumulator.trackChildChange(Change.childChangedChange(childKey, childSnap, oldChildSnap)); - } - return oldEventCache.updateImmediateChild(childKey, childSnap); - } else { - if (optChangeAccumulator != null) { - optChangeAccumulator.trackChildChange(Change.childRemovedChange(childKey, oldChildSnap)); - } - var newEventCache = oldEventCache.updateImmediateChild(childKey, fb.core.snap.EMPTY_NODE); - var nextChildInRange = nextChild != null && this.rangedFilter_.matches(nextChild); - if (nextChildInRange) { - if (optChangeAccumulator != null) { - optChangeAccumulator.trackChildChange(Change.childAddedChange(nextChild.name, nextChild.node)); - } - return newEventCache.updateImmediateChild(nextChild.name, nextChild.node); - } else { - return newEventCache; - } - } - } else if (childSnap.isEmpty()) { - // we're deleting a node, but it was not in the window, so ignore it - return snap; - } else if (inRange) { - if (cmp(windowBoundary, newChildNamedNode) >= 0) { - if (optChangeAccumulator != null) { - optChangeAccumulator.trackChildChange(Change.childRemovedChange(windowBoundary.name, windowBoundary.node)); - optChangeAccumulator.trackChildChange(Change.childAddedChange(childKey, childSnap)); - } - return oldEventCache.updateImmediateChild(childKey, childSnap).updateImmediateChild(windowBoundary.name, - fb.core.snap.EMPTY_NODE); - } else { - return snap; - } - } else { - return snap; - } -}; diff --git a/src/database/js-client/core/view/filter/NodeFilter.js b/src/database/js-client/core/view/filter/NodeFilter.js deleted file mode 100644 index 2a7bea0e7e3..00000000000 --- a/src/database/js-client/core/view/filter/NodeFilter.js +++ /dev/null @@ -1,79 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.view.filter.NodeFilter'); -goog.require('fb.core.view.ChildChangeAccumulator'); -goog.require('fb.core.view.CompleteChildSource'); - -/** - * NodeFilter is used to update nodes and complete children of nodes while applying queries on the fly and keeping - * track of any child changes. This class does not track value changes as value changes depend on more - * than just the node itself. Different kind of queries require different kind of implementations of this interface. - * @interface - */ -fb.core.view.filter.NodeFilter = function() { }; - -/** - * Update a single complete child in the snap. If the child equals the old child in the snap, this is a no-op. - * The method expects an indexed snap. - * - * @param {!fb.core.snap.Node} snap - * @param {string} key - * @param {!fb.core.snap.Node} newChild - * @param {!fb.core.util.Path} affectedPath - * @param {!fb.core.view.CompleteChildSource} source - * @param {?fb.core.view.ChildChangeAccumulator} optChangeAccumulator - * @return {!fb.core.snap.Node} - */ -fb.core.view.filter.NodeFilter.prototype.updateChild = function(snap, key, newChild, affectedPath, source, - optChangeAccumulator) {}; - -/** - * Update a node in full and output any resulting change from this complete update. - * - * @param {!fb.core.snap.Node} oldSnap - * @param {!fb.core.snap.Node} newSnap - * @param {?fb.core.view.ChildChangeAccumulator} optChangeAccumulator - * @return {!fb.core.snap.Node} - */ -fb.core.view.filter.NodeFilter.prototype.updateFullNode = function(oldSnap, newSnap, optChangeAccumulator) { }; - -/** - * Update the priority of the root node - * - * @param {!fb.core.snap.Node} oldSnap - * @param {!fb.core.snap.Node} newPriority - * @return {!fb.core.snap.Node} - */ -fb.core.view.filter.NodeFilter.prototype.updatePriority = function(oldSnap, newPriority) { }; - -/** - * Returns true if children might be filtered due to query criteria - * - * @return {boolean} - */ -fb.core.view.filter.NodeFilter.prototype.filtersNodes = function() { }; - -/** - * Returns the index filter that this filter uses to get a NodeFilter that doesn't filter any children. - * @return {!fb.core.view.filter.NodeFilter} - */ -fb.core.view.filter.NodeFilter.prototype.getIndexedFilter = function() { }; - -/** - * Returns the index that this filter uses - * @return {!fb.core.snap.Index} - */ -fb.core.view.filter.NodeFilter.prototype.getIndex = function() { }; diff --git a/src/database/js-client/core/view/filter/RangedFilter.js b/src/database/js-client/core/view/filter/RangedFilter.js deleted file mode 100644 index 774ac6478bf..00000000000 --- a/src/database/js-client/core/view/filter/RangedFilter.js +++ /dev/null @@ -1,164 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.core.view.filter.RangedFilter'); -goog.require('fb.core.view.filter.IndexedFilter'); - -/** - * Filters nodes by range and uses an IndexFilter to track any changes after filtering the node - * - * @constructor - * @implements {fb.core.view.filter.NodeFilter} - * @param {!fb.core.view.QueryParams} params - */ -fb.core.view.filter.RangedFilter = function(params) { - /** - * @type {!fb.core.view.filter.IndexedFilter} - * @const - * @private - */ - this.indexedFilter_ = new fb.core.view.filter.IndexedFilter(params.getIndex()); - - /** - * @const - * @type {!fb.core.snap.Index} - * @private - */ - this.index_ = params.getIndex(); - - /** - * @const - * @type {!fb.core.snap.NamedNode} - * @private - */ - this.startPost_ = this.getStartPost_(params); - - /** - * @const - * @type {!fb.core.snap.NamedNode} - * @private - */ - this.endPost_ = this.getEndPost_(params); -}; - -/** - * @return {!fb.core.snap.NamedNode} - */ -fb.core.view.filter.RangedFilter.prototype.getStartPost = function() { - return this.startPost_; -}; - -/** - * @return {!fb.core.snap.NamedNode} - */ -fb.core.view.filter.RangedFilter.prototype.getEndPost = function() { - return this.endPost_; -}; - -/** - * @param {!fb.core.snap.NamedNode} node - * @return {boolean} - */ -fb.core.view.filter.RangedFilter.prototype.matches = function(node) { - return (this.index_.compare(this.getStartPost(), node) <= 0 && this.index_.compare(node, this.getEndPost()) <= 0); -}; - -/** - * @inheritDoc - */ -fb.core.view.filter.RangedFilter.prototype.updateChild = function(snap, key, newChild, affectedPath, source, - optChangeAccumulator) { - if (!this.matches(new fb.core.snap.NamedNode(key, newChild))) { - newChild = fb.core.snap.EMPTY_NODE; - } - return this.indexedFilter_.updateChild(snap, key, newChild, affectedPath, source, optChangeAccumulator); -}; - -/** - * @inheritDoc - */ -fb.core.view.filter.RangedFilter.prototype.updateFullNode = function(oldSnap, newSnap, optChangeAccumulator) { - if (newSnap.isLeafNode()) { - // Make sure we have a children node with the correct index, not a leaf node; - newSnap = fb.core.snap.EMPTY_NODE; - } - var filtered = newSnap.withIndex(this.index_); - // Don't support priorities on queries - filtered = filtered.updatePriority(fb.core.snap.EMPTY_NODE); - var self = this; - newSnap.forEachChild(fb.core.snap.PriorityIndex, function(key, childNode) { - if (!self.matches(new fb.core.snap.NamedNode(key, childNode))) { - filtered = filtered.updateImmediateChild(key, fb.core.snap.EMPTY_NODE); - } - }); - return this.indexedFilter_.updateFullNode(oldSnap, filtered, optChangeAccumulator); -}; - -/** - * @inheritDoc - */ -fb.core.view.filter.RangedFilter.prototype.updatePriority = function(oldSnap, newPriority) { - // Don't support priorities on queries - return oldSnap; -}; - -/** - * @inheritDoc - */ -fb.core.view.filter.RangedFilter.prototype.filtersNodes = function() { - return true; -}; - -/** - * @inheritDoc - */ -fb.core.view.filter.RangedFilter.prototype.getIndexedFilter = function() { - return this.indexedFilter_; -}; - -/** - * @inheritDoc - */ -fb.core.view.filter.RangedFilter.prototype.getIndex = function() { - return this.index_; -}; - -/** - * @param {!fb.core.view.QueryParams} params - * @return {!fb.core.snap.NamedNode} - * @private - */ -fb.core.view.filter.RangedFilter.prototype.getStartPost_ = function(params) { - if (params.hasStart()) { - var startName = params.getIndexStartName(); - return params.getIndex().makePost(params.getIndexStartValue(), startName); - } else { - return params.getIndex().minPost(); - } -}; - -/** - * @param {!fb.core.view.QueryParams} params - * @return {!fb.core.snap.NamedNode} - * @private - */ -fb.core.view.filter.RangedFilter.prototype.getEndPost_ = function(params) { - if (params.hasEnd()) { - var endName = params.getIndexEndName(); - return params.getIndex().makePost(params.getIndexEndValue(), endName); - } else { - return params.getIndex().maxPost(); - } -}; diff --git a/src/database/js-client/firebase-app-externs.js b/src/database/js-client/firebase-app-externs.js deleted file mode 100644 index d7cee659d1c..00000000000 --- a/src/database/js-client/firebase-app-externs.js +++ /dev/null @@ -1,226 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -/** - * @fileoverview Firebase namespace and Firebase App API. - * Version: 3.5.2 - * - * Copyright 2016 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @externs - */ - -/** - * firebase is a global namespace from which all the Firebase - * services are accessed. - * - * @namespace - */ -var firebase = {}; - -/** - * Create (and intialize) a FirebaseApp. - * - * @example - * // Retrieve your own options values by adding a web app on - * // http://console.firebase.google.com - * var options = { - * apiKey: "AIza....", // Auth / General Use - * authDomain: "YOUR_APP.firebaseapp.com", // Auth with popup/redirect - * databaseURL: "https://YOUR_APP.firebaseio.com", // Realtime Database - * storageBucket: "YOUR_APP.appspot.com", // Storage - * messagingSenderId: "123456789" // Cloud Messaging - * }; - * // Initialize default application. - * firebase.initializeApp(options); - * - * @param {!Object} options Options to configure the services use in the App. - * @param {string=} name The optional name of the app to initialize ('[DEFAULT]' - * if none) - * @return {!firebase.app.App} - */ -firebase.initializeApp = function(options, name) {}; - -/** - * Retrieve an instance of a FirebaseApp. - * - * With no arguments, this returns the default App. With a single - * string argument, it returns the named App. - * - * This function throws an exception if the app you are trying to access - * does not exist. - * - * Usage: firebase.app() - * - * @namespace - * @param {string} name The optional name of the app to return ('[DEFAULT]' if - * none) - * @return {!firebase.app.App} - */ -firebase.app = function(name) {}; - -/** - * A (read-only) array of all the initialized Apps. - * @type {!Array} - */ -firebase.apps; - -/** - * The current SDK version ('3.5.2'). - * @type {string} - */ -firebase.SDK_VERSION; - -/** - * A Firebase App holds the initialization information for a collection of - * services. - * - * DO NOT call this constuctor directly (use - * firebase.initializeApp() to create an App). - * - * @interface - */ -firebase.app.App = function() {}; - -/** - * The (read-only) name (identifier) for this App. '[DEFAULT]' is the name of - * the default App. - * @type {string} - */ -firebase.app.App.prototype.name; - -/** - * The (read-only) configuration options (the original parameters given - * in firebase.initializeApp()). - * @type {!Object} - */ -firebase.app.App.prototype.options; - -/** - * Make the given App unusable and free the resources of all associated - * services. - * - * @return {!firebase.Promise} - */ -firebase.app.App.prototype.delete = function() {}; - -/** - * A Thenable is the standard interface returned by a Promise. - * - * @template T - * @interface - */ -firebase.Thenable = function() {}; - -/** - * Assign callback functions called when the Thenable value either - * resolves, or is rejected. - * - * @param {(function(T): *)=} onResolve Called when the Thenable resolves. - * @param {(function(!Error): *)=} onReject Called when the Thenable is rejected - * (with an error). - * @return {!firebase.Thenable<*>} - */ -firebase.Thenable.prototype.then = function(onResolve, onReject) {}; - -/** - * Assign a callback when the Thenable rejects. - * - * @param {(function(!Error): *)=} onReject Called when the Thenable is rejected - * (with an error). - * @return {!firebase.Thenable<*>} - */ -firebase.Thenable.prototype.catch = function(onReject) {}; - -/** - * A Promise represents an eventual (asynchronous) value. A Promise should - * (eventually) either resolve or reject. When it does, it will call all the - * callback functions that have been assigned via the .then() or - * .catch() methods. - * - * firebase.Promise is the same as the native Promise - * implementation when available in the current environment, otherwise it is a - * compatible implementation of the Promise/A+ spec. - * - * @template T - * @constructor - * @implements {firebase.Thenable} - * @param {function((function(T): void)=, - * (function(!Error): void)=)} resolver - */ -firebase.Promise = function(resolver) {}; - -/** - * Assign callback functions called when the Promise either resolves, or is - * rejected. - * - * @param {(function(T): *)=} onResolve Called when the Promise resolves. - * @param {(function(!Error): *)=} onReject Called when the Promise is rejected - * (with an error). - * @return {!firebase.Promise<*>} - * @override - */ -firebase.Promise.prototype.then = function(onResolve, onReject) {}; - -/** - * Assign a callback when the Promise rejects. - * - * @param {(function(!Error): *)=} onReject Called when the Promise is rejected - * (with an error). - * @override - */ -firebase.Promise.prototype.catch = function(onReject) {}; - -/** - * Return a resolved Promise. - * - * @template T - * @param {T=} value The value to be returned by the Promise. - * @return {!firebase.Promise} - */ -firebase.Promise.resolve = function(value) {}; - -/** - * Return (an immediately) rejected Promise. - * - * @param {!Error} error The reason for the Promise being rejected. - * @return {!firebase.Promise<*>} - */ -firebase.Promise.reject = function(error) {}; - -/** - * Convert an array of Promises, to a single array of values. - * Promise.all() resolves only after all the Promises in the array - * have resolved. - * - * Promise.all() rejects when any of the promises in the Array have - * rejected. - * - * @param {!Array>} values - * @return {!firebase.Promise>} - */ -firebase.Promise.all = function(values) {}; diff --git a/src/database/js-client/firebase-app-internal-externs.js b/src/database/js-client/firebase-app-internal-externs.js deleted file mode 100644 index 018b224d424..00000000000 --- a/src/database/js-client/firebase-app-internal-externs.js +++ /dev/null @@ -1,197 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -/** - * @fileoverview Firebase namespace and Firebase App API - INTERNAL methods. - * @externs - */ - -/** - * @param {string} name Service name - * @param {!firebase.ServiceFactory} createService - * @param {Object=} serviceProperties - * @param {(function(string, !firebase.app.App): void)=} appHook - * @return {firebase.ServiceNamespace} - */ -firebase.INTERNAL.registerService = function(name, - createService, - serviceProperties, - appHook) {}; - -/** @param {!Object} props */ -firebase.INTERNAL.extendNamespace = function(props) {}; - -firebase.INTERNAL.resetNamespace = function() {}; - -/** @interface */ -firebase.Observer = function() {}; -/** @param {*} value */ -firebase.Observer.prototype.next = function(value) {}; -/** @param {!Error} error */ -firebase.Observer.prototype.error = function(error) {}; -firebase.Observer.prototype.complete = function() {}; - -/** @typedef {function(*): void} */ -firebase.NextFn; -/** @typedef {function(!Error): void} */ -firebase.ErrorFn; -/** @typedef {function(): void} */ -firebase.CompleteFn; - -/** @typedef {function(): void} */ -firebase.Unsubscribe; - -/** - * @typedef {function((firebase.NextFn|firebase.Observer)=, - * firebase.ErrorFn=, - * firebase.CompleteFn=): firebase.Unsubscribe} - */ -firebase.Subscribe; - -/** - * @param {function (!firebase.Observer): void} executor - * @param {(function (!firebase.Observer): void)=} onNoObservers - * @return {!firebase.Subscribe} - */ -firebase.INTERNAL.createSubscribe = function(executor, onNoObservers) {}; - -/** - * @param {*} target - * @param {*} source - */ -firebase.INTERNAL.deepExtend = function(target, source) {}; - -/** @param {string} name */ -firebase.INTERNAL.removeApp = function(name) {}; - -/** - * @type {!Object} - */ -firebase.INTERNAL.factories = {}; - -/** - * @param {!firebase.app.App} app - * @param {string} serviceName - * @return {string|null} - */ -firebase.INTERNAL.useAsService = function(app, serviceName) {}; - -/** - * @constructor - * @param {string} service All lowercase service code (e.g., 'auth') - * @param {string} serviceName Display service name (e.g., 'Auth') - * @param {!Object} errors - */ -firebase.INTERNAL.ErrorFactory = function(service, serviceName, errors) {}; - -/** - * @param {string} code - * @param {Object=} data - * @return {!firebase.FirebaseError} - */ -firebase.INTERNAL.ErrorFactory.prototype.create = function(code, data) {}; - - -/** @interface */ -firebase.Service = function() {} - -/** @type {!firebase.app.App} */ -firebase.Service.prototype.app; - -/** @type {!Object} */ -firebase.Service.prototype.INTERNAL; - -/** @return {firebase.Promise} */ -firebase.Service.prototype.INTERNAL.delete = function() {}; - -/** - * @typedef {function(!firebase.app.App, - * !function(!Object): void): !firebase.Service} - */ -firebase.ServiceFactory; - - -/** @interface */ -firebase.ServiceNamespace = function() {}; - -/** - * Given an (optional) app, return the instance of the service - * associated with that app. - * - * @param {firebase.app.App=} app - * @return {!firebase.Service} - */ -firebase.ServiceNamespace.prototype.app = function(app) {} - -/** - * Firebase App.INTERNAL methods - default implementations in firebase-app, - * replaced by Auth ... - */ - -/** - * Listener for an access token. - * - * Should pass null when the user current user is no longer value (signed - * out or credentials become invalid). - * - * Firebear does not currently auto-refresh tokens, BTW - but this interface - * would support that in the future. - * - * @typedef {function(?string): void} - */ -firebase.AuthTokenListener; - -/** - * Returned from app.INTERNAL.getToken(). - * - * @typedef {{ - * accessToken: (?string), - * expirationTime: (number), - * refreshToken: (?string) - * }} - */ -firebase.AuthTokenData; - - -/** @type {!Object} */ -firebase.app.App.prototype.INTERNAL; - -/** - * app.INTERNAL.getToken() - * - * @param {boolean=} opt_forceRefresh Whether to force sts token refresh. - * @return {!Promise} - */ -firebase.app.App.prototype.INTERNAL.getToken = function(opt_forceRefresh) {}; - - -/** - * Adds an auth state listener. - * - * @param {!firebase.AuthTokenListener} listener The auth state listener. - */ -firebase.app.App.prototype.INTERNAL.addAuthTokenListener = - function(listener) {}; - - -/** - * Removes an auth state listener. - * - * @param {!firebase.AuthTokenListener} listener The auth state listener. - */ -firebase.app.App.prototype.INTERNAL.removeAuthTokenListener = - function(listener) {}; diff --git a/src/database/js-client/firebase-app.js b/src/database/js-client/firebase-app.js deleted file mode 100755 index 69a67a5008b..00000000000 --- a/src/database/js-client/firebase-app.js +++ /dev/null @@ -1,51 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -/*! @license Firebase v3.5.2 - Build: 3.5.2-rc.1 - Terms: https://developers.google.com/terms */ -var firebase = null; (function() { for(var aa="function"==typeof Object.defineProperties?Object.defineProperty:function(a,b,c){if(c.get||c.set)throw new TypeError("ES3 does not support getters and setters.");a!=Array.prototype&&a!=Object.prototype&&(a[b]=c.value)},h="undefined"!=typeof window&&window===this?this:"undefined"!=typeof global&&null!=global?global:this,ba=function(){ba=function(){};h.Symbol||(h.Symbol=ca)},da=0,ca=function(a){return"jscomp_symbol_"+(a||"")+da++},m=function(){ba();var a=h.Symbol.iterator;a||(a=h.Symbol.iterator= -h.Symbol("iterator"));"function"!=typeof Array.prototype[a]&&aa(Array.prototype,a,{configurable:!0,writable:!0,value:function(){return ea(this)}});m=function(){}},ea=function(a){var b=0;return fa(function(){return be?b:null===d?d=Object.getOwnPropertyDescriptor(b,c):d,g;g=C.Reflect;if("object"===typeof g&&"function"===typeof g.decorate)f=g.decorate(a,b,c,d);else for(var k=a.length-1;0<=k;k--)if(g=a[k])f=(3>e?g(f):3"}),c=this.ka+": "+c+" ("+a+").",c=new V(a,c),d;for(d in b)b.hasOwnProperty(d)&&"_"!==d.slice(-1)&&(c[d]=b[d]);return c};var W=S,X=function(a,b,c){var d=this;this.P=c;this.S=!1;this.l={};this.I=b;this.fa=R(void 0,a);Object.keys(c.INTERNAL.factories).forEach(function(a){var b=c.INTERNAL.useAsService(d,a);null!==b&&(b=d.da.bind(d,b),d[a]=b)})};X.prototype.delete=function(){var a=this;return(new W(function(b){Y(a);b()})).then(function(){a.P.INTERNAL.removeApp(a.I);return W.all(Object.keys(a.l).map(function(b){return a.l[b].INTERNAL.delete()}))}).then(function(){a.S=!0;a.l={}})}; -X.prototype.da=function(a){Y(this);void 0===this.l[a]&&(this.l[a]=this.P.INTERNAL.factories[a](this,this.ca.bind(this)));return this.l[a]};X.prototype.ca=function(a){R(this,a)};var Y=function(a){a.S&&Z(Ra("deleted",{name:a.I}))};h.Object.defineProperties(X.prototype,{name:{configurable:!0,enumerable:!0,get:function(){Y(this);return this.I}},options:{configurable:!0,enumerable:!0,get:function(){Y(this);return this.fa}}});X.prototype.name&&X.prototype.options||X.prototype.delete||console.log("dc"); -function Sa(){function a(a){a=a||"[DEFAULT]";var b=d[a];void 0===b&&Z("noApp",{name:a});return b}function b(a,b){Object.keys(e).forEach(function(d){d=c(a,d);if(null!==d&&f[d])f[d](b,a)})}function c(a,b){if("serverAuth"===b)return null;var c=b;a=a.options;"auth"===b&&(a.serviceAccount||a.credential)&&(c="serverAuth","serverAuth"in e||Z("serverAuthMissing"));return c}var d={},e={},f={},g={__esModule:!0,initializeApp:function(a,c){void 0===c?c="[DEFAULT]":"string"===typeof c&&""!==c||Z("bad-app-name", -{name:c+""});void 0!==d[c]&&Z("dupApp",{name:c});a=new X(a,c,g);d[c]=a;b(a,"create");void 0!=a.INTERNAL&&void 0!=a.INTERNAL.getToken||R(a,{INTERNAL:{getToken:function(){return W.resolve(null)},addAuthTokenListener:function(){},removeAuthTokenListener:function(){}}});return a},app:a,apps:null,Promise:W,SDK_VERSION:"0.0.0",INTERNAL:{registerService:function(b,c,d,v){e[b]&&Z("dupService",{name:b});e[b]=c;v&&(f[b]=v);c=function(c){void 0===c&&(c=a());return c[b]()};void 0!==d&&R(c,d);return g[b]=c},createFirebaseNamespace:Sa, -extendNamespace:function(a){R(g,a)},createSubscribe:La,ErrorFactory:Qa,removeApp:function(a){b(d[a],"delete");delete d[a]},factories:e,useAsService:c,Promise:Q,deepExtend:R}};g["default"]=g;Object.defineProperty(g,"apps",{get:function(){return Object.keys(d).map(function(a){return d[a]})}});a.App=X;return g}function Z(a,b){throw Error(Ra(a,b));} -function Ra(a,b){b=b||{};b={noApp:"No Firebase App '"+b.name+"' has been created - call Firebase App.initializeApp().","bad-app-name":"Illegal App name: '"+b.name+"'.",dupApp:"Firebase App named '"+b.name+"' already exists.",deleted:"Firebase App named '"+b.name+"' already deleted.",dupService:"Firebase Service named '"+b.name+"' already registered.",serverAuthMissing:"Initializing the Firebase SDK with a service account is only allowed in a Node.js environment. On client devices, you should instead initialize the SDK with an api key and auth domain."}[a]; -return void 0===b?"Application Error: ("+a+")":b};"undefined"!==typeof firebase&&(firebase=Sa()); })(); -firebase.SDK_VERSION = "3.5.2"; diff --git a/src/database/js-client/firebase-externs.js b/src/database/js-client/firebase-externs.js deleted file mode 100644 index 88df2a00c83..00000000000 --- a/src/database/js-client/firebase-externs.js +++ /dev/null @@ -1,58 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -// Node externs -var process; -/** - * @constructor - * @param {!string} a - * @param {!string} b - */ -var Buffer = function(a, b) {}; -/** - * @param {string=} encoding - * @return {!string} - */ -Buffer.prototype.toString = function(encoding) { return 'dummy'; }; - -// Browser externs -var MozWebSocket; -/** - * @param {!string} input - * @return {!string} - */ -var atob = function(input) { return ''; }; - -// WinRT -var Windows; - -// Long-polling -var jsonpCB; - -// -// CommonJS externs -// - -/** @const */ -var module = {}; - -/** @type {*} */ -module.exports = {}; - -/** - * @param {string} moduleName - * @return {*} - */ -var require = function(moduleName) {}; diff --git a/src/database/js-client/firebase-local.js b/src/database/js-client/firebase-local.js deleted file mode 100644 index 61de63bce00..00000000000 --- a/src/database/js-client/firebase-local.js +++ /dev/null @@ -1,32 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -/** - * @fileoverview Bootstrapper for local development. - * - * This script can be used during development instead of the compiled firebase.js. - * It pulls in the raw source files, so no compilation step is required (though if you - * change any dependencies, e.g. by adding goog.require statements, you'll need to - * run: - * - * $ build-client deps - * - * This script pulls in google closure's base.js and our generated-deps.js file - * automatically. All other required scripts will be pulled in based on goog.require - * statements. - */ -document.write(''); -document.write(''); -document.write(''); diff --git a/src/database/js-client/firebase-require.js b/src/database/js-client/firebase-require.js deleted file mode 100644 index 3ff03243ad1..00000000000 --- a/src/database/js-client/firebase-require.js +++ /dev/null @@ -1,19 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -// Pulled in by firebase-local.js. I used to inject this as an inline script, but IE would then -// execute it before the other scripts were loaded, so "goog" would be undefined. So now it's -// in its own script. -goog.require('fb.core.registerService'); diff --git a/src/database/js-client/login/util/environment.js b/src/database/js-client/login/util/environment.js deleted file mode 100644 index fb0bb82ec36..00000000000 --- a/src/database/js-client/login/util/environment.js +++ /dev/null @@ -1,64 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.login.util.environment'); - - -/** - * Returns navigator.userAgent string or '' if it's not defined. - * @return {string} user agent string - */ -fb.login.util.environment.getUA = function() { - if (typeof navigator !== 'undefined' && - typeof navigator['userAgent'] === 'string') { - return navigator['userAgent']; - } else { - return ''; - } -}; - -/** - * Detect Cordova / PhoneGap / Ionic frameworks on a mobile device. - * - * Deliberately does not rely on checking `file://` URLs (as this fails PhoneGap in the Ripple emulator) nor - * Cordova `onDeviceReady`, which would normally wait for a callback. - * - * @return {boolean} isMobileCordova - */ -fb.login.util.environment.isMobileCordova = function() { - return typeof window !== 'undefined' && - !!(window['cordova'] || window['phonegap'] || window['PhoneGap']) && - /ios|iphone|ipod|ipad|android|blackberry|iemobile/i.test(fb.login.util.environment.getUA()); -}; - - -/** - * Detect React Native. - * - * @return {boolean} True if ReactNative environment is detected. - */ -fb.login.util.environment.isReactNative = function() { - return typeof navigator === 'object' && navigator['product'] === 'ReactNative'; -}; - - -/** - * Detect Node.js. - * - * @return {boolean} True if Node.js environment is detected. - */ -fb.login.util.environment.isNodeSdk = function() { - return fb.constants.NODE_CLIENT === true || fb.constants.NODE_ADMIN === true; -}; diff --git a/src/database/js-client/node-local.js b/src/database/js-client/node-local.js deleted file mode 100644 index a4540951798..00000000000 --- a/src/database/js-client/node-local.js +++ /dev/null @@ -1,26 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -// Define a global firebase since our test files load as independent modules. -global.firebase = require('firebase/app'); - -require('../closure-library/closure/goog/bootstrap/nodejs.js'); -require('../generated-node-deps.js'); - -goog.require('fb.core.registerService'); - -// Magic stuff: I think our tests use the export of this -// module to be the Firebase variable. -module.exports = Firebase; diff --git a/src/database/js-client/realtime/BrowserPollConnection.js b/src/database/js-client/realtime/BrowserPollConnection.js deleted file mode 100644 index 6617cede329..00000000000 --- a/src/database/js-client/realtime/BrowserPollConnection.js +++ /dev/null @@ -1,680 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.realtime.BrowserPollConnection'); -goog.require('fb.constants'); -goog.require('fb.core.stats.StatsManager'); -goog.require('fb.core.util'); -goog.require('fb.core.util.CountedSet'); -goog.require('fb.realtime.Constants'); -goog.require('fb.realtime.Transport'); -goog.require('fb.realtime.polling.PacketReceiver'); -goog.require('fb.util.json'); - -// URL query parameters associated with longpolling -// TODO: move more of these out of the global namespace -var FIREBASE_LONGPOLL_START_PARAM = 'start'; -var FIREBASE_LONGPOLL_CLOSE_COMMAND = 'close'; -var FIREBASE_LONGPOLL_COMMAND_CB_NAME = 'pLPCommand'; -var FIREBASE_LONGPOLL_DATA_CB_NAME = 'pRTLPCB'; -var FIREBASE_LONGPOLL_ID_PARAM = 'id'; -var FIREBASE_LONGPOLL_PW_PARAM = 'pw'; -var FIREBASE_LONGPOLL_SERIAL_PARAM = 'ser'; -var FIREBASE_LONGPOLL_CALLBACK_ID_PARAM = 'cb'; -var FIREBASE_LONGPOLL_SEGMENT_NUM_PARAM = 'seg'; -var FIREBASE_LONGPOLL_SEGMENTS_IN_PACKET = 'ts'; -var FIREBASE_LONGPOLL_DATA_PARAM = 'd'; -var FIREBASE_LONGPOLL_DISCONN_FRAME_PARAM = 'disconn'; -var FIREBASE_LONGPOLL_DISCONN_FRAME_REQUEST_PARAM = 'dframe'; - -//Data size constants. -//TODO: Perf: the maximum length actually differs from browser to browser. -// We should check what browser we're on and set accordingly. -var MAX_URL_DATA_SIZE = 1870; -var SEG_HEADER_SIZE = 30; //ie: &seg=8299234&ts=982389123&d= -var MAX_PAYLOAD_SIZE = MAX_URL_DATA_SIZE - SEG_HEADER_SIZE; - -/** - * Keepalive period - * send a fresh request at minimum every 25 seconds. Opera has a maximum request - * length of 30 seconds that we can't exceed. - * @const - * @type {number} - */ -var KEEPALIVE_REQUEST_INTERVAL = 25000; - -/** - * How long to wait before aborting a long-polling connection attempt. - * @const - * @type {number} - */ -var LP_CONNECT_TIMEOUT = 30000; - -/** - * This class manages a single long-polling connection. - * - * @constructor - * @implements {fb.realtime.Transport} - * @param {string} connId An identifier for this connection, used for logging - * @param {fb.core.RepoInfo} repoInfo The info for the endpoint to send data to. - * @param {string=} opt_transportSessionId Optional transportSessionid if we are reconnecting for an existing - * transport session - * @param {string=} opt_lastSessionId Optional lastSessionId if the PersistentConnection has already created a - * connection previously - */ -fb.realtime.BrowserPollConnection = function(connId, repoInfo, opt_transportSessionId, opt_lastSessionId) { - this.connId = connId; - this.log_ = fb.core.util.logWrapper(connId); - this.repoInfo = repoInfo; - this.bytesSent = 0; - this.bytesReceived = 0; - this.stats_ = fb.core.stats.StatsManager.getCollection(repoInfo); - this.transportSessionId = opt_transportSessionId; - this.everConnected_ = false; - this.lastSessionId = opt_lastSessionId; - this.urlFn = function(params) { - return repoInfo.connectionURL(fb.realtime.Constants.LONG_POLLING, params); - }; -}; - -/** - * - * @param {function(Object)} onMessage Callback when messages arrive - * @param {function()} onDisconnect Callback with connection lost. - */ -fb.realtime.BrowserPollConnection.prototype.open = function(onMessage, onDisconnect) { - this.curSegmentNum = 0; - this.onDisconnect_ = onDisconnect; - this.myPacketOrderer = new fb.realtime.polling.PacketReceiver(onMessage); - this.isClosed_ = false; - var self = this; - - this.connectTimeoutTimer_ = setTimeout(function() { - self.log_('Timed out trying to connect.'); - // Make sure we clear the host cache - self.onClosed_(); - self.connectTimeoutTimer_ = null; - }, Math.floor(LP_CONNECT_TIMEOUT)); - - // Ensure we delay the creation of the iframe until the DOM is loaded. - fb.core.util.executeWhenDOMReady(function() { - if (self.isClosed_) - return; - - //Set up a callback that gets triggered once a connection is set up. - self.scriptTagHolder = new FirebaseIFrameScriptHolder(function(command, arg1, arg2, arg3, arg4) { - self.incrementIncomingBytes_(arguments); - if (!self.scriptTagHolder) - return; // we closed the connection. - - if (self.connectTimeoutTimer_) { - clearTimeout(self.connectTimeoutTimer_); - self.connectTimeoutTimer_ = null; - } - self.everConnected_ = true; - if (command == FIREBASE_LONGPOLL_START_PARAM) { - self.id = arg1; - self.password = arg2; - } else if (command === FIREBASE_LONGPOLL_CLOSE_COMMAND) { - // Don't clear the host cache. We got a response from the server, so we know it's reachable - if (arg1) { - // We aren't expecting any more data (other than what the server's already in the process of sending us - // through our already open polls), so don't send any more. - self.scriptTagHolder.sendNewPolls = false; - - // arg1 in this case is the last response number sent by the server. We should try to receive - // all of the responses up to this one before closing - self.myPacketOrderer.closeAfter(arg1, function() { self.onClosed_(); }); - } else { - self.onClosed_(); - } - } else { - throw new Error('Unrecognized command received: ' + command); - } - }, function(pN, data) { - self.incrementIncomingBytes_(arguments); - self.myPacketOrderer.handleResponse(pN, data); - }, function() { - self.onClosed_(); - }, self.urlFn); - - //Send the initial request to connect. The serial number is simply to keep the browser from pulling previous results - //from cache. - var urlParams = {}; - urlParams[FIREBASE_LONGPOLL_START_PARAM] = 't'; - urlParams[FIREBASE_LONGPOLL_SERIAL_PARAM] = Math.floor(Math.random() * 100000000); - if (self.scriptTagHolder.uniqueCallbackIdentifier) - urlParams[FIREBASE_LONGPOLL_CALLBACK_ID_PARAM] = self.scriptTagHolder.uniqueCallbackIdentifier; - urlParams[fb.realtime.Constants.VERSION_PARAM] = fb.realtime.Constants.PROTOCOL_VERSION; - if (self.transportSessionId) { - urlParams[fb.realtime.Constants.TRANSPORT_SESSION_PARAM] = self.transportSessionId; - } - if (self.lastSessionId) { - urlParams[fb.realtime.Constants.LAST_SESSION_PARAM] = self.lastSessionId; - } - if (!fb.login.util.environment.isNodeSdk() && - typeof location !== 'undefined' && - location.href && - location.href.indexOf(fb.realtime.Constants.FORGE_DOMAIN) !== -1) { - urlParams[fb.realtime.Constants.REFERER_PARAM] = fb.realtime.Constants.FORGE_REF; - } - var connectURL = self.urlFn(urlParams); - self.log_('Connecting via long-poll to ' + connectURL); - self.scriptTagHolder.addTag(connectURL, function() { /* do nothing */ }); - }); -}; - -/** - * Call this when a handshake has completed successfully and we want to consider the connection established - */ -fb.realtime.BrowserPollConnection.prototype.start = function() { - this.scriptTagHolder.startLongPoll(this.id, this.password); - this.addDisconnectPingFrame(this.id, this.password); -}; - -/** - * Forces long polling to be considered as a potential transport - */ -fb.realtime.BrowserPollConnection.forceAllow = function() { - fb.realtime.BrowserPollConnection.forceAllow_ = true; -}; - -/** - * Forces longpolling to not be considered as a potential transport - */ -fb.realtime.BrowserPollConnection.forceDisallow = function() { - fb.realtime.BrowserPollConnection.forceDisallow_ = true; -}; - -// Static method, use string literal so it can be accessed in a generic way -fb.realtime.BrowserPollConnection['isAvailable'] = function() { - // NOTE: In React-Native there's normally no 'document', but if you debug a React-Native app in - // the Chrome debugger, 'document' is defined, but document.createElement is null (2015/06/08). - return fb.realtime.BrowserPollConnection.forceAllow_ || ( - !fb.realtime.BrowserPollConnection.forceDisallow_ && - typeof document !== 'undefined' && goog.isDefAndNotNull(document.createElement) && - !fb.core.util.isChromeExtensionContentScript() && - !fb.core.util.isWindowsStoreApp() && - // Sometimes people define a global 'document' in node.js (e.g. with jsdom), but long-polling won't work. - !fb.login.util.environment.isNodeSdk() - ); -}; - -/** - * No-op for polling - */ -fb.realtime.BrowserPollConnection.prototype.markConnectionHealthy = function() { }; - -/** - * Stops polling and cleans up the iframe - * @private - */ -fb.realtime.BrowserPollConnection.prototype.shutdown_ = function() { - this.isClosed_ = true; - - if (this.scriptTagHolder) { - this.scriptTagHolder.close(); - this.scriptTagHolder = null; - } - - //remove the disconnect frame, which will trigger an XHR call to the server to tell it we're leaving. - if (this.myDisconnFrame) { - document.body.removeChild(this.myDisconnFrame); - this.myDisconnFrame = null; - } - - if (this.connectTimeoutTimer_) { - clearTimeout(this.connectTimeoutTimer_); - this.connectTimeoutTimer_ = null; - } -}; - -/** - * Triggered when this transport is closed - * @private - */ -fb.realtime.BrowserPollConnection.prototype.onClosed_ = function() { - if (!this.isClosed_) { - this.log_('Longpoll is closing itself'); - this.shutdown_(); - - if (this.onDisconnect_) { - this.onDisconnect_(this.everConnected_); - this.onDisconnect_ = null; - } - } -}; - -/** - * External-facing close handler. RealTime has requested we shut down. Kill our connection and tell the server - * that we've left. - */ -fb.realtime.BrowserPollConnection.prototype.close = function() { - if (!this.isClosed_) { - this.log_('Longpoll is being closed.'); - this.shutdown_(); - } -}; - -/** - * Send the JSON object down to the server. It will need to be stringified, base64 encoded, and then - * broken into chunks (since URLs have a small maximum length). - * @param {!Object} data The JSON data to transmit. - */ -fb.realtime.BrowserPollConnection.prototype.send = function(data) { - var dataStr = fb.util.json.stringify(data); - this.bytesSent += dataStr.length; - this.stats_.incrementCounter('bytes_sent', dataStr.length); - - //first, lets get the base64-encoded data - var base64data = fb.core.util.base64Encode(dataStr); - - //We can only fit a certain amount in each URL, so we need to split this request - //up into multiple pieces if it doesn't fit in one request. - var dataSegs = fb.core.util.splitStringBySize(base64data, MAX_PAYLOAD_SIZE); - - //Enqueue each segment for transmission. We assign each chunk a sequential ID and a total number - //of segments so that we can reassemble the packet on the server. - for (var i = 0; i < dataSegs.length; i++) { - this.scriptTagHolder.enqueueSegment(this.curSegmentNum, dataSegs.length, dataSegs[i]); - this.curSegmentNum++; - } -}; - -/** - * This is how we notify the server that we're leaving. - * We aren't able to send requests with DHTML on a window close event, but we can - * trigger XHR requests in some browsers (everything but Opera basically). - * @param {!string} id - * @param {!string} pw - */ -fb.realtime.BrowserPollConnection.prototype.addDisconnectPingFrame = function(id, pw) { - if (fb.login.util.environment.isNodeSdk()) - return; - this.myDisconnFrame = document.createElement('iframe'); - var urlParams = {}; - urlParams[FIREBASE_LONGPOLL_DISCONN_FRAME_REQUEST_PARAM] = 't'; - urlParams[FIREBASE_LONGPOLL_ID_PARAM] = id; - urlParams[FIREBASE_LONGPOLL_PW_PARAM] = pw; - this.myDisconnFrame.src = this.urlFn(urlParams); - this.myDisconnFrame.style.display = 'none'; - - document.body.appendChild(this.myDisconnFrame); -}; - -/** - * Used to track the bytes received by this client - * @param {*} args - * @private - */ -fb.realtime.BrowserPollConnection.prototype.incrementIncomingBytes_ = function(args) { - // TODO: This is an annoying perf hit just to track the number of incoming bytes. Maybe it should be opt-in. - var bytesReceived = fb.util.json.stringify(args).length; - this.bytesReceived += bytesReceived; - this.stats_.incrementCounter('bytes_received', bytesReceived); -}; - -/********************************************************************************************* - * A wrapper around an iframe that is used as a long-polling script holder. - * @constructor - * @param commandCB - The callback to be called when control commands are recevied from the server. - * @param onMessageCB - The callback to be triggered when responses arrive from the server. - * @param onDisconnectCB - The callback to be triggered when this tag holder is closed - * @param urlFn - A function that provides the URL of the endpoint to send data to. - *********************************************************************************************/ -function FirebaseIFrameScriptHolder(commandCB, onMessageCB, onDisconnectCB, urlFn) { - this.urlFn = urlFn; - this.onDisconnect = onDisconnectCB; - - //We maintain a count of all of the outstanding requests, because if we have too many active at once it can cause - //problems in some browsers. - /** - * @type {fb.core.util.CountedSet.} - */ - this.outstandingRequests = new fb.core.util.CountedSet(); - - //A queue of the pending segments waiting for transmission to the server. - this.pendingSegs = []; - - //A serial number. We use this for two things: - // 1) A way to ensure the browser doesn't cache responses to polls - // 2) A way to make the server aware when long-polls arrive in a different order than we started them. The - // server needs to release both polls in this case or it will cause problems in Opera since Opera can only execute - // JSONP code in the order it was added to the iframe. - this.currentSerial = Math.floor(Math.random() * 100000000); - - // This gets set to false when we're "closing down" the connection (e.g. we're switching transports but there's still - // incoming data from the server that we're waiting for). - this.sendNewPolls = true; - - if (!fb.login.util.environment.isNodeSdk()) { - //Each script holder registers a couple of uniquely named callbacks with the window. These are called from the - //iframes where we put the long-polling script tags. We have two callbacks: - // 1) Command Callback - Triggered for control issues, like starting a connection. - // 2) Message Callback - Triggered when new data arrives. - this.uniqueCallbackIdentifier = fb.core.util.LUIDGenerator(); - window[FIREBASE_LONGPOLL_COMMAND_CB_NAME + this.uniqueCallbackIdentifier] = commandCB; - window[FIREBASE_LONGPOLL_DATA_CB_NAME + this.uniqueCallbackIdentifier] = onMessageCB; - - //Create an iframe for us to add script tags to. - this.myIFrame = this.createIFrame_(); - - // Set the iframe's contents. - var script = ''; - // if we set a javascript url, it's IE and we need to set the document domain. The javascript url is sufficient - // for ie9, but ie8 needs to do it again in the document itself. - if (this.myIFrame.src && this.myIFrame.src.substr(0, 'javascript:'.length) === 'javascript:') { - var currentDomain = document.domain; - script = ''; - } - var iframeContents = '' + script + ''; - try { - this.myIFrame.doc.open(); - this.myIFrame.doc.write(iframeContents); - this.myIFrame.doc.close(); - } catch (e) { - fb.core.util.log('frame writing exception'); - if (e.stack) { - fb.core.util.log(e.stack); - } - fb.core.util.log(e); - } - } else { - this.commandCB = commandCB; - this.onMessageCB = onMessageCB; - } -} - -/** - * Each browser has its own funny way to handle iframes. Here we mush them all together into one object that I can - * actually use. - * @private - * @return {Element} - */ -FirebaseIFrameScriptHolder.prototype.createIFrame_ = function() { - var iframe = document.createElement('iframe'); - iframe.style.display = 'none'; - - // This is necessary in order to initialize the document inside the iframe - if (document.body) { - document.body.appendChild(iframe); - try { - // If document.domain has been modified in IE, this will throw an error, and we need to set the - // domain of the iframe's document manually. We can do this via a javascript: url as the src attribute - // Also note that we must do this *after* the iframe has been appended to the page. Otherwise it doesn't work. - var a = iframe.contentWindow.document; - if (!a) { - // Apologies for the log-spam, I need to do something to keep closure from optimizing out the assignment above. - fb.core.util.log('No IE domain setting required'); - } - } catch (e) { - var domain = document.domain; - iframe.src = 'javascript:void((function(){document.open();document.domain=\'' + domain + - '\';document.close();})())'; - } - } else { - // LongPollConnection attempts to delay initialization until the document is ready, so hopefully this - // never gets hit. - throw 'Document body has not initialized. Wait to initialize Firebase until after the document is ready.'; - } - - // Get the document of the iframe in a browser-specific way. - if (iframe.contentDocument) { - iframe.doc = iframe.contentDocument; // Firefox, Opera, Safari - } else if (iframe.contentWindow) { - iframe.doc = iframe.contentWindow.document; // Internet Explorer - } else if (iframe.document) { - iframe.doc = iframe.document; //others? - } - return iframe; -}; - -/** - * Cancel all outstanding queries and remove the frame. - */ -FirebaseIFrameScriptHolder.prototype.close = function() { - //Mark this iframe as dead, so no new requests are sent. - this.alive = false; - - if (this.myIFrame) { - //We have to actually remove all of the html inside this iframe before removing it from the - //window, or IE will continue loading and executing the script tags we've already added, which - //can lead to some errors being thrown. Setting innerHTML seems to be the easiest way to do this. - this.myIFrame.doc.body.innerHTML = ''; - var self = this; - setTimeout(function() { - if (self.myIFrame !== null) { - document.body.removeChild(self.myIFrame); - self.myIFrame = null; - } - }, Math.floor(0)); - } - - if (fb.login.util.environment.isNodeSdk() && this.myID) { - var urlParams = {}; - urlParams[FIREBASE_LONGPOLL_DISCONN_FRAME_PARAM] = 't'; - urlParams[FIREBASE_LONGPOLL_ID_PARAM] = this.myID; - urlParams[FIREBASE_LONGPOLL_PW_PARAM] = this.myPW; - var theURL = this.urlFn(urlParams); - FirebaseIFrameScriptHolder.nodeRestRequest(theURL); - } - - // Protect from being called recursively. - var onDisconnect = this.onDisconnect; - if (onDisconnect) { - this.onDisconnect = null; - onDisconnect(); - } -}; - -/** - * Actually start the long-polling session by adding the first script tag(s) to the iframe. - * @param {!string} id - The ID of this connection - * @param {!string} pw - The password for this connection - */ -FirebaseIFrameScriptHolder.prototype.startLongPoll = function(id, pw) { - this.myID = id; - this.myPW = pw; - this.alive = true; - - //send the initial request. If there are requests queued, make sure that we transmit as many as we are currently able to. - while (this.newRequest_()) {} -}; - -/** - * This is called any time someone might want a script tag to be added. It adds a script tag when there aren't - * too many outstanding requests and we are still alive. - * - * If there are outstanding packet segments to send, it sends one. If there aren't, it sends a long-poll anyways if - * needed. - */ -FirebaseIFrameScriptHolder.prototype.newRequest_ = function() { - // We keep one outstanding request open all the time to receive data, but if we need to send data - // (pendingSegs.length > 0) then we create a new request to send the data. The server will automatically - // close the old request. - if (this.alive && this.sendNewPolls && this.outstandingRequests.count() < (this.pendingSegs.length > 0 ? 2 : 1)) { - //construct our url - this.currentSerial++; - var urlParams = {}; - urlParams[FIREBASE_LONGPOLL_ID_PARAM] = this.myID; - urlParams[FIREBASE_LONGPOLL_PW_PARAM] = this.myPW; - urlParams[FIREBASE_LONGPOLL_SERIAL_PARAM] = this.currentSerial; - var theURL = this.urlFn(urlParams); - //Now add as much data as we can. - var curDataString = ''; - var i = 0; - - while (this.pendingSegs.length > 0) { - //first, lets see if the next segment will fit. - var nextSeg = this.pendingSegs[0]; - if (nextSeg.d.length + SEG_HEADER_SIZE + curDataString.length <= MAX_URL_DATA_SIZE) { - //great, the segment will fit. Lets append it. - var theSeg = this.pendingSegs.shift(); - curDataString = curDataString + '&' + FIREBASE_LONGPOLL_SEGMENT_NUM_PARAM + i + '=' + theSeg.seg + - '&' + FIREBASE_LONGPOLL_SEGMENTS_IN_PACKET + i + '=' + theSeg.ts + '&' + FIREBASE_LONGPOLL_DATA_PARAM + i + '=' + theSeg.d; - i++; - } else { - break; - } - } - - theURL = theURL + curDataString; - this.addLongPollTag_(theURL, this.currentSerial); - - return true; - } else { - return false; - } -}; - -/** - * Queue a packet for transmission to the server. - * @param segnum - A sequential id for this packet segment used for reassembly - * @param totalsegs - The total number of segments in this packet - * @param data - The data for this segment. - */ -FirebaseIFrameScriptHolder.prototype.enqueueSegment = function(segnum, totalsegs, data) { - //add this to the queue of segments to send. - this.pendingSegs.push({seg: segnum, ts: totalsegs, d: data}); - - //send the data immediately if there isn't already data being transmitted, unless - //startLongPoll hasn't been called yet. - if (this.alive) { - this.newRequest_(); - } -}; - -/** - * Add a script tag for a regular long-poll request. - * @param {!string} url - The URL of the script tag. - * @param {!number} serial - The serial number of the request. - * @private - */ -FirebaseIFrameScriptHolder.prototype.addLongPollTag_ = function(url, serial) { - var self = this; - //remember that we sent this request. - self.outstandingRequests.add(serial, 1); - - var doNewRequest = function() { - self.outstandingRequests.remove(serial); - self.newRequest_(); - }; - - // If this request doesn't return on its own accord (by the server sending us some data), we'll - // create a new one after the KEEPALIVE interval to make sure we always keep a fresh request open. - var keepaliveTimeout = setTimeout(doNewRequest, Math.floor(KEEPALIVE_REQUEST_INTERVAL)); - - var readyStateCB = function() { - // Request completed. Cancel the keepalive. - clearTimeout(keepaliveTimeout); - - // Trigger a new request so we can continue receiving data. - doNewRequest(); - }; - - this.addTag(url, readyStateCB); -}; - -/** - * Add an arbitrary script tag to the iframe. - * @param {!string} url - The URL for the script tag source. - * @param {!function()} loadCB - A callback to be triggered once the script has loaded. - */ -FirebaseIFrameScriptHolder.prototype.addTag = function(url, loadCB) { - if (fb.login.util.environment.isNodeSdk()) { - this.doNodeLongPoll(url, loadCB); - } else { - - var self = this; - setTimeout(function() { - try { - // if we're already closed, don't add this poll - if (!self.sendNewPolls) return; - var newScript = self.myIFrame.doc.createElement('script'); - newScript.type = 'text/javascript'; - newScript.async = true; - newScript.src = url; - newScript.onload = newScript.onreadystatechange = function() { - var rstate = newScript.readyState; - if (!rstate || rstate === 'loaded' || rstate === 'complete') { - newScript.onload = newScript.onreadystatechange = null; - if (newScript.parentNode) { - newScript.parentNode.removeChild(newScript); - } - loadCB(); - } - }; - newScript.onerror = function() { - fb.core.util.log('Long-poll script failed to load: ' + url); - self.sendNewPolls = false; - self.close(); - }; - self.myIFrame.doc.body.appendChild(newScript); - } catch (e) { - // TODO: we should make this error visible somehow - } - }, Math.floor(1)); - } -}; - -if (fb.login.util.environment.isNodeSdk()) { - - /** - * @type {?function({url: string, forever: boolean}, function(Error, number, string))} - */ - FirebaseIFrameScriptHolder.request = null; - - /** - * @param {{url: string, forever: boolean}} req - * @param {function(string)=} onComplete - */ - FirebaseIFrameScriptHolder.nodeRestRequest = function(req, onComplete) { - if (!FirebaseIFrameScriptHolder.request) - FirebaseIFrameScriptHolder.request = - /** @type {function({url: string, forever: boolean}, function(Error, number, string))} */ (require('request')); - - FirebaseIFrameScriptHolder.request(req, function(error, response, body) { - if (error) - throw 'Rest request for ' + req.url + ' failed.'; - - if (onComplete) - onComplete(body); - }); - }; - - /** - * @param {!string} url - * @param {function()} loadCB - */ - FirebaseIFrameScriptHolder.prototype.doNodeLongPoll = function(url, loadCB) { - var self = this; - FirebaseIFrameScriptHolder.nodeRestRequest({ url: url, forever: true }, function(body) { - self.evalBody(body); - loadCB(); - }); - }; - - /** - * Evaluates the string contents of a jsonp response. - * @param {!string} body - */ - FirebaseIFrameScriptHolder.prototype.evalBody = function(body) { - //jsonpCB is externed in firebase-extern.js - eval('var jsonpCB = function(' + FIREBASE_LONGPOLL_COMMAND_CB_NAME + ', ' + FIREBASE_LONGPOLL_DATA_CB_NAME + ') {' + - body + - '}'); - jsonpCB(this.commandCB, this.onMessageCB); - }; -} diff --git a/src/database/js-client/realtime/Connection.js b/src/database/js-client/realtime/Connection.js deleted file mode 100644 index f482796a890..00000000000 --- a/src/database/js-client/realtime/Connection.js +++ /dev/null @@ -1,518 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.realtime.Connection'); -goog.require('fb.core.storage'); -goog.require('fb.core.util'); -goog.require('fb.realtime.Constants'); -goog.require('fb.realtime.TransportManager'); - -// Abort upgrade attempt if it takes longer than 60s. -var UPGRADE_TIMEOUT = 60000; - -// For some transports (WebSockets), we need to "validate" the transport by exchanging a few requests and responses. -// If we haven't sent enough requests within 5s, we'll start sending noop ping requests. -var DELAY_BEFORE_SENDING_EXTRA_REQUESTS = 5000; - -// If the initial data sent triggers a lot of bandwidth (i.e. it's a large put or a listen for a large amount of data) -// then we may not be able to exchange our ping/pong requests within the healthy timeout. So if we reach the timeout -// but we've sent/received enough bytes, we don't cancel the connection. -var BYTES_SENT_HEALTHY_OVERRIDE = 10 * 1024; -var BYTES_RECEIVED_HEALTHY_OVERRIDE = 100 * 1024; - - -var REALTIME_STATE_CONNECTING = 0; -var REALTIME_STATE_CONNECTED = 1; -var REALTIME_STATE_DISCONNECTED = 2; - -var MESSAGE_TYPE = 't'; -var MESSAGE_DATA = 'd'; -var CONTROL_SHUTDOWN = 's'; -var CONTROL_RESET = 'r'; -var CONTROL_ERROR = 'e'; -var CONTROL_PONG = 'o'; -var SWITCH_ACK = 'a'; -var END_TRANSMISSION = 'n'; -var PING = 'p'; - -var SERVER_HELLO = 'h'; - -/** - * Creates a new real-time connection to the server using whichever method works - * best in the current browser. - * - * @constructor - * @param {!string} connId - an id for this connection - * @param {!fb.core.RepoInfo} repoInfo - the info for the endpoint to connect to - * @param {function(Object)} onMessage - the callback to be triggered when a server-push message arrives - * @param {function(number, string)} onReady - the callback to be triggered when this connection is ready to send messages. - * @param {function()} onDisconnect - the callback to be triggered when a connection was lost - * @param {function(string)} onKill - the callback to be triggered when this connection has permanently shut down. - * @param {string=} lastSessionId - last session id in persistent connection. is used to clean up old session in real-time server - - */ -fb.realtime.Connection = function(connId, repoInfo, onMessage, onReady, onDisconnect, onKill, lastSessionId) { - this.id = connId; - this.log_ = fb.core.util.logWrapper('c:' + this.id + ':'); - this.onMessage_ = onMessage; - this.onReady_ = onReady; - this.onDisconnect_ = onDisconnect; - this.onKill_ = onKill; - this.repoInfo_ = repoInfo; - this.pendingDataMessages = []; - this.connectionCount = 0; - this.transportManager_ = new fb.realtime.TransportManager(repoInfo); - this.state_ = REALTIME_STATE_CONNECTING; - this.lastSessionId = lastSessionId; - this.log_('Connection created'); - this.start_(); -}; - -/** - * Starts a connection attempt - * @private - */ -fb.realtime.Connection.prototype.start_ = function() { - var conn = this.transportManager_.initialTransport(); - this.conn_ = new conn(this.nextTransportId_(), this.repoInfo_, /*transportSessionId=*/undefined, this.lastSessionId); - - // For certain transports (WebSockets), we need to send and receive several messages back and forth before we - // can consider the transport healthy. - this.primaryResponsesRequired_ = conn['responsesRequiredToBeHealthy'] || 0; - - var onMessageReceived = this.connReceiver_(this.conn_); - var onConnectionLost = this.disconnReceiver_(this.conn_); - this.tx_ = this.conn_; - this.rx_ = this.conn_; - this.secondaryConn_ = null; - this.isHealthy_ = false; - - var self = this; - /* - * Firefox doesn't like when code from one iframe tries to create another iframe by way of the parent frame. - * This can occur in the case of a redirect, i.e. we guessed wrong on what server to connect to and received a reset. - * Somehow, setTimeout seems to make this ok. That doesn't make sense from a security perspective, since you should - * still have the context of your originating frame. - */ - setTimeout(function() { - // self.conn_ gets set to null in some of the tests. Check to make sure it still exists before using it - self.conn_ && self.conn_.open(onMessageReceived, onConnectionLost); - }, Math.floor(0)); - - - var healthyTimeout_ms = conn['healthyTimeout'] || 0; - if (healthyTimeout_ms > 0) { - this.healthyTimeout_ = fb.core.util.setTimeoutNonBlocking(function() { - self.healthyTimeout_ = null; - if (!self.isHealthy_) { - if (self.conn_ && self.conn_.bytesReceived > BYTES_RECEIVED_HEALTHY_OVERRIDE) { - self.log_('Connection exceeded healthy timeout but has received ' + self.conn_.bytesReceived + - ' bytes. Marking connection healthy.'); - self.isHealthy_ = true; - self.conn_.markConnectionHealthy(); - } else if (self.conn_ && self.conn_.bytesSent > BYTES_SENT_HEALTHY_OVERRIDE) { - self.log_('Connection exceeded healthy timeout but has sent ' + self.conn_.bytesSent + - ' bytes. Leaving connection alive.'); - // NOTE: We don't want to mark it healthy, since we have no guarantee that the bytes have made it to - // the server. - } else { - self.log_('Closing unhealthy connection after timeout.'); - self.close(); - } - } - }, Math.floor(healthyTimeout_ms)); - } -}; - -/** - * @return {!string} - * @private - */ -fb.realtime.Connection.prototype.nextTransportId_ = function() { - return 'c:' + this.id + ':' + this.connectionCount++; -}; - -fb.realtime.Connection.prototype.disconnReceiver_ = function(conn) { - var self = this; - return function(everConnected) { - if (conn === self.conn_) { - self.onConnectionLost_(everConnected); - } else if (conn === self.secondaryConn_) { - self.log_('Secondary connection lost.'); - self.onSecondaryConnectionLost_(); - } else { - self.log_('closing an old connection'); - } - } -}; - -fb.realtime.Connection.prototype.connReceiver_ = function(conn) { - var self = this; - return function(message) { - if (self.state_ != REALTIME_STATE_DISCONNECTED) { - if (conn === self.rx_) { - self.onPrimaryMessageReceived_(message); - } else if (conn === self.secondaryConn_) { - self.onSecondaryMessageReceived_(message); - } else { - self.log_('message on old connection'); - } - } - }; -}; - -/** - * - * @param {Object} dataMsg An arbitrary data message to be sent to the server - */ -fb.realtime.Connection.prototype.sendRequest = function(dataMsg) { - // wrap in a data message envelope and send it on - var msg = {'t': 'd', 'd': dataMsg}; - this.sendData_(msg); -}; - -fb.realtime.Connection.prototype.tryCleanupConnection = function() { - if (this.tx_ === this.secondaryConn_ && this.rx_ === this.secondaryConn_) { - this.log_('cleaning up and promoting a connection: ' + this.secondaryConn_.connId); - this.conn_ = this.secondaryConn_; - this.secondaryConn_ = null; - // the server will shutdown the old connection - } -}; - -fb.realtime.Connection.prototype.onSecondaryControl_ = function(controlData) { - if (MESSAGE_TYPE in controlData) { - var cmd = controlData[MESSAGE_TYPE]; - if (cmd === SWITCH_ACK) { - this.upgradeIfSecondaryHealthy_(); - } else if (cmd === CONTROL_RESET) { - // Most likely the session wasn't valid. Abandon the switch attempt - this.log_('Got a reset on secondary, closing it'); - this.secondaryConn_.close(); - // If we were already using this connection for something, than we need to fully close - if (this.tx_ === this.secondaryConn_ || this.rx_ === this.secondaryConn_) { - this.close(); - } - } else if (cmd === CONTROL_PONG) { - this.log_('got pong on secondary.'); - this.secondaryResponsesRequired_--; - this.upgradeIfSecondaryHealthy_(); - } - } -}; - -fb.realtime.Connection.prototype.onSecondaryMessageReceived_ = function(parsedData) { - var layer = fb.core.util.requireKey('t', parsedData); - var data = fb.core.util.requireKey('d', parsedData); - if (layer == 'c') { - this.onSecondaryControl_(data); - } else if (layer == 'd') { - // got a data message, but we're still second connection. Need to buffer it up - this.pendingDataMessages.push(data); - } else { - throw new Error('Unknown protocol layer: ' + layer); - } -}; - -fb.realtime.Connection.prototype.upgradeIfSecondaryHealthy_ = function() { - if (this.secondaryResponsesRequired_ <= 0) { - this.log_('Secondary connection is healthy.'); - this.isHealthy_ = true; - this.secondaryConn_.markConnectionHealthy(); - this.proceedWithUpgrade_(); - } else { - // Send a ping to make sure the connection is healthy. - this.log_('sending ping on secondary.'); - this.secondaryConn_.send({'t': 'c', 'd': {'t': PING, 'd': { } }}); - } -}; - -fb.realtime.Connection.prototype.proceedWithUpgrade_ = function() { - // tell this connection to consider itself open - this.secondaryConn_.start(); - // send ack - this.log_('sending client ack on secondary'); - this.secondaryConn_.send({'t': 'c', 'd': {'t': SWITCH_ACK, 'd': {}}}); - - // send end packet on primary transport, switch to sending on this one - // can receive on this one, buffer responses until end received on primary transport - this.log_('Ending transmission on primary'); - this.conn_.send({'t': 'c', 'd': {'t': END_TRANSMISSION, 'd': {}}}); - this.tx_ = this.secondaryConn_; - - this.tryCleanupConnection(); -}; - -fb.realtime.Connection.prototype.onPrimaryMessageReceived_ = function(parsedData) { - // Must refer to parsedData properties in quotes, so closure doesn't touch them. - var layer = fb.core.util.requireKey('t', parsedData); - var data = fb.core.util.requireKey('d', parsedData); - if (layer == 'c') { - this.onControl_(data); - } else if (layer == 'd') { - this.onDataMessage_(data); - } -}; - -fb.realtime.Connection.prototype.onDataMessage_ = function(message) { - this.onPrimaryResponse_(); - - // We don't do anything with data messages, just kick them up a level - this.onMessage_(message); -}; - -fb.realtime.Connection.prototype.onPrimaryResponse_ = function() { - if (!this.isHealthy_) { - this.primaryResponsesRequired_--; - if (this.primaryResponsesRequired_ <= 0) { - this.log_('Primary connection is healthy.'); - this.isHealthy_ = true; - this.conn_.markConnectionHealthy(); - } - } -}; - -fb.realtime.Connection.prototype.onControl_ = function(controlData) { - var cmd = fb.core.util.requireKey(MESSAGE_TYPE, controlData); - if (MESSAGE_DATA in controlData) { - var payload = controlData[MESSAGE_DATA]; - if (cmd === SERVER_HELLO) { - this.onHandshake_(payload); - } else if (cmd === END_TRANSMISSION) { - this.log_('recvd end transmission on primary'); - this.rx_ = this.secondaryConn_; - for (var i = 0; i < this.pendingDataMessages.length; ++i) { - this.onDataMessage_(this.pendingDataMessages[i]); - } - this.pendingDataMessages = []; - this.tryCleanupConnection(); - } else if (cmd === CONTROL_SHUTDOWN) { - // This was previously the 'onKill' callback passed to the lower-level connection - // payload in this case is the reason for the shutdown. Generally a human-readable error - this.onConnectionShutdown_(payload); - } else if (cmd === CONTROL_RESET) { - // payload in this case is the host we should contact - this.onReset_(payload); - } else if (cmd === CONTROL_ERROR) { - fb.core.util.error('Server Error: ' + payload); - } else if (cmd === CONTROL_PONG) { - this.log_('got pong on primary.'); - this.onPrimaryResponse_(); - this.sendPingOnPrimaryIfNecessary_(); - } else { - fb.core.util.error('Unknown control packet command: ' + cmd); - } - } -}; - -/** - * - * @param {Object} handshake The handshake data returned from the server - * @private - */ -fb.realtime.Connection.prototype.onHandshake_ = function(handshake) { - var timestamp = handshake['ts']; - var version = handshake['v']; - var host = handshake['h']; - this.sessionId = handshake['s']; - this.repoInfo_.updateHost(host); - // if we've already closed the connection, then don't bother trying to progress further - if (this.state_ == REALTIME_STATE_CONNECTING) { - this.conn_.start(); - this.onConnectionEstablished_(this.conn_, timestamp); - if (fb.realtime.Constants.PROTOCOL_VERSION !== version) { - fb.core.util.warn('Protocol version mismatch detected'); - } - // TODO: do we want to upgrade? when? maybe a delay? - this.tryStartUpgrade_(); - } -}; - -fb.realtime.Connection.prototype.tryStartUpgrade_ = function() { - var conn = this.transportManager_.upgradeTransport(); - if (conn) { - this.startUpgrade_(conn); - } -}; - -fb.realtime.Connection.prototype.startUpgrade_ = function(conn) { - this.secondaryConn_ = new conn(this.nextTransportId_(), - this.repoInfo_, this.sessionId); - // For certain transports (WebSockets), we need to send and receive several messages back and forth before we - // can consider the transport healthy. - this.secondaryResponsesRequired_ = conn['responsesRequiredToBeHealthy'] || 0; - - var onMessage = this.connReceiver_(this.secondaryConn_); - var onDisconnect = this.disconnReceiver_(this.secondaryConn_); - this.secondaryConn_.open(onMessage, onDisconnect); - - // If we haven't successfully upgraded after UPGRADE_TIMEOUT, give up and kill the secondary. - var self = this; - fb.core.util.setTimeoutNonBlocking(function() { - if (self.secondaryConn_) { - self.log_('Timed out trying to upgrade.'); - self.secondaryConn_.close(); - } - }, Math.floor(UPGRADE_TIMEOUT)); -}; - -fb.realtime.Connection.prototype.onReset_ = function(host) { - this.log_('Reset packet received. New host: ' + host); - this.repoInfo_.updateHost(host); - // TODO: if we're already "connected", we need to trigger a disconnect at the next layer up. - // We don't currently support resets after the connection has already been established - if (this.state_ === REALTIME_STATE_CONNECTED) { - this.close(); - } else { - // Close whatever connections we have open and start again. - this.closeConnections_(); - this.start_(); - } -}; - -fb.realtime.Connection.prototype.onConnectionEstablished_ = function(conn, timestamp) { - this.log_('Realtime connection established.'); - this.conn_ = conn; - this.state_ = REALTIME_STATE_CONNECTED; - - if (this.onReady_) { - this.onReady_(timestamp, this.sessionId); - this.onReady_ = null; - } - - var self = this; - // If after 5 seconds we haven't sent enough requests to the server to get the connection healthy, - // send some pings. - if (this.primaryResponsesRequired_ === 0) { - this.log_('Primary connection is healthy.'); - this.isHealthy_ = true; - } else { - fb.core.util.setTimeoutNonBlocking(function() { - self.sendPingOnPrimaryIfNecessary_(); - }, Math.floor(DELAY_BEFORE_SENDING_EXTRA_REQUESTS)); - } -}; - -fb.realtime.Connection.prototype.sendPingOnPrimaryIfNecessary_ = function() { - // If the connection isn't considered healthy yet, we'll send a noop ping packet request. - if (!this.isHealthy_ && this.state_ === REALTIME_STATE_CONNECTED) - { - this.log_('sending ping on primary.'); - this.sendData_({'t': 'c', 'd': {'t': PING, 'd': {} }}); - } -}; - -fb.realtime.Connection.prototype.onSecondaryConnectionLost_ = function() { - var conn = this.secondaryConn_; - this.secondaryConn_ = null; - if (this.tx_ === conn || this.rx_ === conn) { - // we are relying on this connection already in some capacity. Therefore, a failure is real - this.close(); - } -}; - -/** - * - * @param {boolean} everConnected Whether or not the connection ever reached a server. Used to determine if - * we should flush the host cache - * @private - */ -fb.realtime.Connection.prototype.onConnectionLost_ = function(everConnected) { - this.conn_ = null; - - // NOTE: IF you're seeing a Firefox error for this line, I think it might be because it's getting - // called on window close and REALTIME_STATE_CONNECTING is no longer defined. Just a guess. - if (!everConnected && this.state_ === REALTIME_STATE_CONNECTING) { - this.log_('Realtime connection failed.'); - // Since we failed to connect at all, clear any cached entry for this namespace in case the machine went away - if (this.repoInfo_.isCacheableHost()) { - fb.core.storage.PersistentStorage.remove('host:' + this.repoInfo_.host); - // reset the internal host to what we would show the user, i.e. .firebaseio.com - this.repoInfo_.internalHost = this.repoInfo_.host; - } - } else if (this.state_ === REALTIME_STATE_CONNECTED) { - this.log_('Realtime connection lost.'); - } - - this.close(); -}; - -/** - * - * @param {string} reason - * @private - */ -fb.realtime.Connection.prototype.onConnectionShutdown_ = function(reason) { - this.log_('Connection shutdown command received. Shutting down...'); - - if (this.onKill_) { - this.onKill_(reason); - this.onKill_ = null; - } - - // We intentionally don't want to fire onDisconnect (kill is a different case), - // so clear the callback. - this.onDisconnect_ = null; - - this.close(); -}; - - -fb.realtime.Connection.prototype.sendData_ = function(data) { - if (this.state_ !== REALTIME_STATE_CONNECTED) { - throw 'Connection is not connected'; - } else { - this.tx_.send(data); - } -}; - -/** - * Cleans up this connection, calling the appropriate callbacks - */ -fb.realtime.Connection.prototype.close = function() { - if (this.state_ !== REALTIME_STATE_DISCONNECTED) { - this.log_('Closing realtime connection.'); - this.state_ = REALTIME_STATE_DISCONNECTED; - - this.closeConnections_(); - - if (this.onDisconnect_) { - this.onDisconnect_(); - this.onDisconnect_ = null; - } - } -}; - -/** - * - * @private - */ -fb.realtime.Connection.prototype.closeConnections_ = function() { - this.log_('Shutting down all connections'); - if (this.conn_) { - this.conn_.close(); - this.conn_ = null; - } - - if (this.secondaryConn_) { - this.secondaryConn_.close(); - this.secondaryConn_ = null; - } - - if (this.healthyTimeout_) { - clearTimeout(this.healthyTimeout_); - this.healthyTimeout_ = null; - } -}; diff --git a/src/database/js-client/realtime/Constants.js b/src/database/js-client/realtime/Constants.js deleted file mode 100644 index 754a1430756..00000000000 --- a/src/database/js-client/realtime/Constants.js +++ /dev/null @@ -1,37 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.realtime.Constants'); - -/** @const */ fb.realtime.Constants = { - - /** @const */ PROTOCOL_VERSION: '5', - - /** @const */ VERSION_PARAM: 'v', - - /** @const */ TRANSPORT_SESSION_PARAM: 's', - - /** @const */ REFERER_PARAM: 'r', - - /** @const */ FORGE_REF: 'f', - - /** @const */ FORGE_DOMAIN: 'firebaseio.com', - - /** @const */ LAST_SESSION_PARAM: 'ls', - - /** @const */ WEBSOCKET: 'websocket', - - /** @const */ LONG_POLLING: 'long_polling' -}; diff --git a/src/database/js-client/realtime/Transport.js b/src/database/js-client/realtime/Transport.js deleted file mode 100644 index e104cdd4290..00000000000 --- a/src/database/js-client/realtime/Transport.js +++ /dev/null @@ -1,53 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.realtime.Transport'); -goog.require('fb.core.RepoInfo'); - -/** - * - * @param {string} connId An identifier for this connection, used for logging - * @param {fb.core.RepoInfo} repoInfo The info for the endpoint to send data to. - * @param {string=} sessionId Optional sessionId if we're connecting to an existing session - * @interface - */ -fb.realtime.Transport = function(connId, repoInfo, sessionId) {}; - -/** - * @param {function(Object)} onMessage Callback when messages arrive - * @param {function()} onDisconnect Callback with connection lost. - */ -fb.realtime.Transport.prototype.open = function(onMessage, onDisconnect) {}; - -fb.realtime.Transport.prototype.start = function() {}; - -fb.realtime.Transport.prototype.close = function() {}; - -/** - * @param {!Object} data The JSON data to transmit - */ -fb.realtime.Transport.prototype.send = function(data) {}; - -/** - * Bytes received since connection started. - * @type {number} - */ -fb.realtime.Transport.prototype.bytesReceived; - -/** - * Bytes sent since connection started. - * @type {number} - */ -fb.realtime.Transport.prototype.bytesSent; diff --git a/src/database/js-client/realtime/TransportManager.js b/src/database/js-client/realtime/TransportManager.js deleted file mode 100644 index f03972574d6..00000000000 --- a/src/database/js-client/realtime/TransportManager.js +++ /dev/null @@ -1,93 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.require('fb.constants'); -goog.require('fb.realtime.BrowserPollConnection'); -goog.require('fb.realtime.Transport'); -goog.provide('fb.realtime.TransportManager'); -goog.require('fb.realtime.WebSocketConnection'); - -/** - * Currently simplistic, this class manages what transport a Connection should use at various stages of its - * lifecycle. - * - * It starts with longpolling in a browser, and httppolling on node. It then upgrades to websockets if - * they are available. - * @constructor - * @param {!fb.core.RepoInfo} repoInfo Metadata around the namespace we're connecting to - */ -fb.realtime.TransportManager = function(repoInfo) { - this.initTransports_(repoInfo); -}; - -/** - * @const - * @type {!Array.} - */ -fb.realtime.TransportManager.ALL_TRANSPORTS = [ - fb.realtime.BrowserPollConnection, - fb.realtime.WebSocketConnection -]; - -/** - * @param {!fb.core.RepoInfo} repoInfo - * @private - */ -fb.realtime.TransportManager.prototype.initTransports_ = function(repoInfo) { - var isWebSocketsAvailable = fb.realtime.WebSocketConnection && fb.realtime.WebSocketConnection['isAvailable'](); - var isSkipPollConnection = isWebSocketsAvailable && !fb.realtime.WebSocketConnection.previouslyFailed(); - - if (repoInfo.webSocketOnly) { - if (!isWebSocketsAvailable) - fb.core.util.warn('wss:// URL used, but browser isn\'t known to support websockets. Trying anyway.'); - - isSkipPollConnection = true; - } - - if (isSkipPollConnection) { - this.transports_ = [fb.realtime.WebSocketConnection]; - } else { - var transports = this.transports_ = []; - fb.core.util.each(fb.realtime.TransportManager.ALL_TRANSPORTS, function(i, transport) { - if (transport && transport['isAvailable']()) { - transports.push(transport); - } - }); - } -}; - -/** - * @return {function(new:fb.realtime.Transport, !string, !fb.core.RepoInfo, string=, string=)} The constructor for the - * initial transport to use - */ -fb.realtime.TransportManager.prototype.initialTransport = function() { - if (this.transports_.length > 0) { - return this.transports_[0]; - } else { - throw new Error('No transports available'); - } -}; - -/** - * @return {?function(new:fb.realtime.Transport, function(),function(), string=)} The constructor for the next - * transport, or null - */ -fb.realtime.TransportManager.prototype.upgradeTransport = function() { - if (this.transports_.length > 1) { - return this.transports_[1]; - } else { - return null; - } -}; diff --git a/src/database/js-client/realtime/WebSocketConnection.js b/src/database/js-client/realtime/WebSocketConnection.js deleted file mode 100644 index 26d8a26fb13..00000000000 --- a/src/database/js-client/realtime/WebSocketConnection.js +++ /dev/null @@ -1,387 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.realtime.WebSocketConnection'); -goog.require('fb.constants'); -goog.require('fb.core.stats.StatsManager'); -goog.require('fb.core.storage'); -goog.require('fb.core.util'); -goog.require('fb.realtime.Constants'); -goog.require('fb.realtime.Transport'); -goog.require('fb.util.json'); - -var WEBSOCKET_MAX_FRAME_SIZE = 16384; -var WEBSOCKET_KEEPALIVE_INTERVAL = 45000; - -fb.WebSocket = null; -if (fb.login.util.environment.isNodeSdk()) { - goog.require('fb.core.util.NodePatches'); - fb.WebSocket = require('faye-websocket')['Client']; -} else if (typeof MozWebSocket !== 'undefined') { - fb.WebSocket = MozWebSocket; -} else if (typeof WebSocket !== 'undefined') { - fb.WebSocket = WebSocket; -} - -/** - * Create a new websocket connection with the given callbacks. - * @constructor - * @implements {fb.realtime.Transport} - * @param {string} connId identifier for this transport - * @param {fb.core.RepoInfo} repoInfo The info for the websocket endpoint. - * @param {string=} opt_transportSessionId Optional transportSessionId if this is connecting to an existing transport - * session - * @param {string=} opt_lastSessionId Optional lastSessionId if there was a previous connection - */ -fb.realtime.WebSocketConnection = function(connId, repoInfo, opt_transportSessionId, opt_lastSessionId) { - this.connId = connId; - this.log_ = fb.core.util.logWrapper(this.connId); - this.keepaliveTimer = null; - this.frames = null; - this.totalFrames = 0; - this.bytesSent = 0; - this.bytesReceived = 0; - this.stats_ = fb.core.stats.StatsManager.getCollection(repoInfo); - this.connURL = this.connectionURL_(repoInfo, opt_transportSessionId, opt_lastSessionId); -}; - - -/** - * @param {fb.core.RepoInfo} repoInfo The info for the websocket endpoint. - * @param {string=} opt_transportSessionId Optional transportSessionId if this is connecting to an existing transport - * session - * @param {string=} opt_lastSessionId Optional lastSessionId if there was a previous connection - * @return {string} connection url - * @private - */ -fb.realtime.WebSocketConnection.prototype.connectionURL_ = function(repoInfo, opt_transportSessionId, - opt_lastSessionId) { - var urlParams = {}; - urlParams[fb.realtime.Constants.VERSION_PARAM] = fb.realtime.Constants.PROTOCOL_VERSION; - - if (!fb.login.util.environment.isNodeSdk() && - typeof location !== 'undefined' && - location.href && - location.href.indexOf(fb.realtime.Constants.FORGE_DOMAIN) !== -1) { - urlParams[fb.realtime.Constants.REFERER_PARAM] = fb.realtime.Constants.FORGE_REF; - } - if (opt_transportSessionId) { - urlParams[fb.realtime.Constants.TRANSPORT_SESSION_PARAM] = opt_transportSessionId; - } - if (opt_lastSessionId) { - urlParams[fb.realtime.Constants.LAST_SESSION_PARAM] = opt_lastSessionId; - } - return repoInfo.connectionURL(fb.realtime.Constants.WEBSOCKET, urlParams); -}; - - -/** - * - * @param onMess Callback when messages arrive - * @param onDisconn Callback with connection lost. - */ -fb.realtime.WebSocketConnection.prototype.open = function(onMess, onDisconn) { - this.onDisconnect = onDisconn; - this.onMessage = onMess; - - this.log_('Websocket connecting to ' + this.connURL); - - this.everConnected_ = false; - // Assume failure until proven otherwise. - fb.core.storage.PersistentStorage.set('previous_websocket_failure', true); - - try { - if (fb.login.util.environment.isNodeSdk()) { - var device = fb.constants.NODE_ADMIN ? 'AdminNode' : 'Node'; - // UA Format: Firebase//// - var options = { - 'headers': { - 'User-Agent': 'Firebase/' + fb.realtime.Constants.PROTOCOL_VERSION + '/' + firebase.SDK_VERSION + '/' + process.platform + '/' + device - }}; - - // Plumb appropriate http_proxy environment variable into faye-websocket if it exists. - var env = process['env']; - var proxy = (this.connURL.indexOf("wss://") == 0) - ? (env['HTTPS_PROXY'] || env['https_proxy']) - : (env['HTTP_PROXY'] || env['http_proxy']); - - if (proxy) { - options['proxy'] = { origin: proxy }; - } - - this.mySock = new fb.WebSocket(this.connURL, [], options); - } - else { - this.mySock = new fb.WebSocket(this.connURL); - } - } catch (e) { - this.log_('Error instantiating WebSocket.'); - var error = e.message || e.data; - if (error) { - this.log_(error); - } - this.onClosed_(); - return; - } - - var self = this; - - this.mySock.onopen = function() { - self.log_('Websocket connected.'); - self.everConnected_ = true; - }; - - this.mySock.onclose = function() { - self.log_('Websocket connection was disconnected.'); - self.mySock = null; - self.onClosed_(); - }; - - this.mySock.onmessage = function(m) { - self.handleIncomingFrame(m); - }; - - this.mySock.onerror = function(e) { - self.log_('WebSocket error. Closing connection.'); - var error = e.message || e.data; - if (error) { - self.log_(error); - } - self.onClosed_(); - }; -}; - -/** - * No-op for websockets, we don't need to do anything once the connection is confirmed as open - */ -fb.realtime.WebSocketConnection.prototype.start = function() {}; - - -fb.realtime.WebSocketConnection.forceDisallow = function() { - fb.realtime.WebSocketConnection.forceDisallow_ = true; -}; - - -fb.realtime.WebSocketConnection['isAvailable'] = function() { - var isOldAndroid = false; - if (typeof navigator !== 'undefined' && navigator.userAgent) { - var oldAndroidRegex = /Android ([0-9]{0,}\.[0-9]{0,})/; - var oldAndroidMatch = navigator.userAgent.match(oldAndroidRegex); - if (oldAndroidMatch && oldAndroidMatch.length > 1) { - if (parseFloat(oldAndroidMatch[1]) < 4.4) { - isOldAndroid = true; - } - } - } - - return !isOldAndroid && fb.WebSocket !== null && !fb.realtime.WebSocketConnection.forceDisallow_; -}; - -/** - * Number of response before we consider the connection "healthy." - * @type {number} - * - * NOTE: 'responsesRequiredToBeHealthy' shouldn't need to be quoted, but closure removed it for some reason otherwise! - */ -fb.realtime.WebSocketConnection['responsesRequiredToBeHealthy'] = 2; - -/** - * Time to wait for the connection te become healthy before giving up. - * @type {number} - * - * NOTE: 'healthyTimeout' shouldn't need to be quoted, but closure removed it for some reason otherwise! - */ -fb.realtime.WebSocketConnection['healthyTimeout'] = 30000; - -/** - * Returns true if we previously failed to connect with this transport. - * @return {boolean} - */ -fb.realtime.WebSocketConnection.previouslyFailed = function() { - // If our persistent storage is actually only in-memory storage, - // we default to assuming that it previously failed to be safe. - return fb.core.storage.PersistentStorage.isInMemoryStorage || - fb.core.storage.PersistentStorage.get('previous_websocket_failure') === true; -}; - -fb.realtime.WebSocketConnection.prototype.markConnectionHealthy = function() { - fb.core.storage.PersistentStorage.remove('previous_websocket_failure'); -}; - -fb.realtime.WebSocketConnection.prototype.appendFrame_ = function(data) { - this.frames.push(data); - if (this.frames.length == this.totalFrames) { - var fullMess = this.frames.join(''); - this.frames = null; - var jsonMess = fb.util.json.eval(fullMess); - - //handle the message - this.onMessage(jsonMess); - } -}; - -/** - * @param {number} frameCount The number of frames we are expecting from the server - * @private - */ -fb.realtime.WebSocketConnection.prototype.handleNewFrameCount_ = function(frameCount) { - this.totalFrames = frameCount; - this.frames = []; -}; - -/** - * Attempts to parse a frame count out of some text. If it can't, assumes a value of 1 - * @param {!String} data - * @return {?String} Any remaining data to be process, or null if there is none - * @private - */ -fb.realtime.WebSocketConnection.prototype.extractFrameCount_ = function(data) { - fb.core.util.assert(this.frames === null, 'We already have a frame buffer'); - // TODO: The server is only supposed to send up to 9999 frames (i.e. length <= 4), but that isn't being enforced - // currently. So allowing larger frame counts (length <= 6). See https://app.asana.com/0/search/8688598998380/8237608042508 - if (data.length <= 6) { - var frameCount = Number(data); - if (!isNaN(frameCount)) { - this.handleNewFrameCount_(frameCount); - return null; - } - } - this.handleNewFrameCount_(1); - return data; -}; - -/** - * Process a websocket frame that has arrived from the server. - * @param mess The frame data - */ -fb.realtime.WebSocketConnection.prototype.handleIncomingFrame = function(mess) { - if (this.mySock === null) - return; // Chrome apparently delivers incoming packets even after we .close() the connection sometimes. - var data = mess['data']; - this.bytesReceived += data.length; - this.stats_.incrementCounter('bytes_received', data.length); - - this.resetKeepAlive(); - - if (this.frames !== null) { - // we're buffering - this.appendFrame_(data); - } else { - // try to parse out a frame count, otherwise, assume 1 and process it - var remainingData = this.extractFrameCount_(data); - if (remainingData !== null) { - this.appendFrame_(remainingData); - } - } -}; - -/** - * Send a message to the server - * @param {Object} data The JSON object to transmit - */ -fb.realtime.WebSocketConnection.prototype.send = function(data) { - - this.resetKeepAlive(); - - var dataStr = fb.util.json.stringify(data); - this.bytesSent += dataStr.length; - this.stats_.incrementCounter('bytes_sent', dataStr.length); - - //We can only fit a certain amount in each websocket frame, so we need to split this request - //up into multiple pieces if it doesn't fit in one request. - - var dataSegs = fb.core.util.splitStringBySize(dataStr, WEBSOCKET_MAX_FRAME_SIZE); - - //Send the length header - if (dataSegs.length > 1) { - this.sendString_(String(dataSegs.length)); - } - - //Send the actual data in segments. - for (var i = 0; i < dataSegs.length; i++) { - this.sendString_(dataSegs[i]); - } -}; - -fb.realtime.WebSocketConnection.prototype.shutdown_ = function() { - this.isClosed_ = true; - if (this.keepaliveTimer) { - clearInterval(this.keepaliveTimer); - this.keepaliveTimer = null; - } - - if (this.mySock) { - this.mySock.close(); - this.mySock = null; - } -}; - -fb.realtime.WebSocketConnection.prototype.onClosed_ = function() { - if (!this.isClosed_) { - this.log_('WebSocket is closing itself'); - this.shutdown_(); - - // since this is an internal close, trigger the close listener - if (this.onDisconnect) { - this.onDisconnect(this.everConnected_); - this.onDisconnect = null; - } - } -}; - -/** - * External-facing close handler. - * Close the websocket and kill the connection. - */ -fb.realtime.WebSocketConnection.prototype.close = function() { - if (!this.isClosed_) { - this.log_('WebSocket is being closed'); - this.shutdown_(); - } -}; - -/** - * Kill the current keepalive timer and start a new one, to ensure that it always fires N seconds after - * the last activity. - */ -fb.realtime.WebSocketConnection.prototype.resetKeepAlive = function() { - var self = this; - clearInterval(this.keepaliveTimer); - this.keepaliveTimer = setInterval(function() { - //If there has been no websocket activity for a while, send a no-op - if (self.mySock) { - self.sendString_('0'); - } - self.resetKeepAlive(); - }, Math.floor(WEBSOCKET_KEEPALIVE_INTERVAL)); -}; - -/** - * Send a string over the websocket. - * - * @param {string} str String to send. - * @private - */ -fb.realtime.WebSocketConnection.prototype.sendString_ = function(str) { - // Firefox seems to sometimes throw exceptions (NS_ERROR_UNEXPECTED) from websocket .send() - // calls for some unknown reason. We treat these as an error and disconnect. - // See https://app.asana.com/0/58926111402292/68021340250410 - try { - this.mySock.send(str); - } catch (e) { - this.log_('Exception thrown from WebSocket.send():', e.message || e.data, 'Closing connection.'); - setTimeout(goog.bind(this.onClosed_, this), 0); - } -}; diff --git a/src/database/js-client/realtime/polling/PacketReceiver.js b/src/database/js-client/realtime/polling/PacketReceiver.js deleted file mode 100644 index 750ebbe2e91..00000000000 --- a/src/database/js-client/realtime/polling/PacketReceiver.js +++ /dev/null @@ -1,72 +0,0 @@ -/** -* Copyright 2017 Google Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -goog.provide('fb.realtime.polling.PacketReceiver'); - -/** - * This class ensures the packets from the server arrive in order - * This class takes data from the server and ensures it gets passed into the callbacks in order. - * @param onMessage - * @constructor - */ -fb.realtime.polling.PacketReceiver = function(onMessage) { - this.onMessage_ = onMessage; - this.pendingResponses = []; - this.currentResponseNum = 0; - this.closeAfterResponse = -1; - this.onClose = null; -}; - -fb.realtime.polling.PacketReceiver.prototype.closeAfter = function(responseNum, callback) { - this.closeAfterResponse = responseNum; - this.onClose = callback; - if (this.closeAfterResponse < this.currentResponseNum) { - this.onClose(); - this.onClose = null; - } -}; - -/** - * Each message from the server comes with a response number, and an array of data. The responseNumber - * allows us to ensure that we process them in the right order, since we can't be guaranteed that all - * browsers will respond in the same order as the requests we sent - * @param {number} requestNum - * @param {Array} data - */ -fb.realtime.polling.PacketReceiver.prototype.handleResponse = function(requestNum, data) { - this.pendingResponses[requestNum] = data; - while (this.pendingResponses[this.currentResponseNum]) { - var toProcess = this.pendingResponses[this.currentResponseNum]; - delete this.pendingResponses[this.currentResponseNum]; - for (var i = 0; i < toProcess.length; ++i) { - if (toProcess[i]) { - var self = this; - fb.core.util.exceptionGuard(function() { - self.onMessage_(toProcess[i]); - }); - } - } - if (this.currentResponseNum === this.closeAfterResponse) { - if (this.onClose) { - clearTimeout(this.onClose); - this.onClose(); - this.onClose = null; - } - break; - } - this.currentResponseNum++; - } -}; - diff --git a/src/database/realtime/BrowserPollConnection.ts b/src/database/realtime/BrowserPollConnection.ts new file mode 100644 index 00000000000..4a7d84cb8d1 --- /dev/null +++ b/src/database/realtime/BrowserPollConnection.ts @@ -0,0 +1,652 @@ +import { + base64Encode, + executeWhenDOMReady, + isChromeExtensionContentScript, + isWindowsStoreApp, + log, + logWrapper, + LUIDGenerator, + splitStringBySize +} from "../core/util/util"; +import { CountedSet } from "../core/util/CountedSet"; +import { StatsManager } from "../core/stats/StatsManager"; +import { PacketReceiver } from "./polling/PacketReceiver"; +import { CONSTANTS } from "./Constants"; +import { stringify } from "../../utils/json"; +import { isNodeSdk } from "../../utils/environment"; +import { Transport } from './Transport'; +import { RepoInfo } from '../core/RepoInfo'; + +// URL query parameters associated with longpolling +export const FIREBASE_LONGPOLL_START_PARAM = 'start'; +export const FIREBASE_LONGPOLL_CLOSE_COMMAND = 'close'; +export const FIREBASE_LONGPOLL_COMMAND_CB_NAME = 'pLPCommand'; +export const FIREBASE_LONGPOLL_DATA_CB_NAME = 'pRTLPCB'; +export const FIREBASE_LONGPOLL_ID_PARAM = 'id'; +export const FIREBASE_LONGPOLL_PW_PARAM = 'pw'; +export const FIREBASE_LONGPOLL_SERIAL_PARAM = 'ser'; +export const FIREBASE_LONGPOLL_CALLBACK_ID_PARAM = 'cb'; +export const FIREBASE_LONGPOLL_SEGMENT_NUM_PARAM = 'seg'; +export const FIREBASE_LONGPOLL_SEGMENTS_IN_PACKET = 'ts'; +export const FIREBASE_LONGPOLL_DATA_PARAM = 'd'; +export const FIREBASE_LONGPOLL_DISCONN_FRAME_PARAM = 'disconn'; +export const FIREBASE_LONGPOLL_DISCONN_FRAME_REQUEST_PARAM = 'dframe'; + +//Data size constants. +//TODO: Perf: the maximum length actually differs from browser to browser. +// We should check what browser we're on and set accordingly. +const MAX_URL_DATA_SIZE = 1870; +const SEG_HEADER_SIZE = 30; //ie: &seg=8299234&ts=982389123&d= +const MAX_PAYLOAD_SIZE = MAX_URL_DATA_SIZE - SEG_HEADER_SIZE; + +/** + * Keepalive period + * send a fresh request at minimum every 25 seconds. Opera has a maximum request + * length of 30 seconds that we can't exceed. + * @const + * @type {number} + */ +const KEEPALIVE_REQUEST_INTERVAL = 25000; + +/** + * How long to wait before aborting a long-polling connection attempt. + * @const + * @type {number} + */ +const LP_CONNECT_TIMEOUT = 30000; + +/** + * This class manages a single long-polling connection. + * + * @constructor + * @implements {Transport} + * @param {string} connId An identifier for this connection, used for logging + * @param {RepoInfo} repoInfo The info for the endpoint to send data to. + * @param {string=} opt_transportSessionId Optional transportSessionid if we are reconnecting for an existing + * transport session + * @param {string=} opt_lastSessionId Optional lastSessionId if the PersistentConnection has already created a + * connection previously + */ +export class BrowserPollConnection implements Transport { + repoInfo; + bytesSent; + bytesReceived; + transportSessionId; + lastSessionId; + urlFn; + scriptTagHolder; + myDisconnFrame; + curSegmentNum; + myPacketOrderer; + id; + password; + private log_; + private stats_; + private everConnected_; + private connectTimeoutTimer_; + private onDisconnect_; + private isClosed_; + + constructor(public connId: string, repoInfo: RepoInfo, transportSessionId?: string, lastSessionId?: string) { + this.log_ = logWrapper(connId); + this.repoInfo = repoInfo; + this.bytesSent = 0; + this.bytesReceived = 0; + this.stats_ = StatsManager.getCollection(repoInfo); + this.transportSessionId = transportSessionId; + this.everConnected_ = false; + this.lastSessionId = lastSessionId; + this.urlFn = (params) => repoInfo.connectionURL(CONSTANTS.LONG_POLLING, params); + }; + + /** + * + * @param {function(Object)} onMessage Callback when messages arrive + * @param {function()} onDisconnect Callback with connection lost. + */ + open(onMessage: (msg: Object) => any, onDisconnect: () => any) { + this.curSegmentNum = 0; + this.onDisconnect_ = onDisconnect; + this.myPacketOrderer = new PacketReceiver(onMessage); + this.isClosed_ = false; + + this.connectTimeoutTimer_ = setTimeout(() => { + this.log_('Timed out trying to connect.'); + // Make sure we clear the host cache + this.onClosed_(); + this.connectTimeoutTimer_ = null; + }, Math.floor(LP_CONNECT_TIMEOUT)); + + // Ensure we delay the creation of the iframe until the DOM is loaded. + executeWhenDOMReady(() => { + if (this.isClosed_) + return; + + //Set up a callback that gets triggered once a connection is set up. + this.scriptTagHolder = new FirebaseIFrameScriptHolder((...args) => { + const [command, arg1, arg2, arg3, arg4] = args; + this.incrementIncomingBytes_(args); + if (!this.scriptTagHolder) + return; // we closed the connection. + + if (this.connectTimeoutTimer_) { + clearTimeout(this.connectTimeoutTimer_); + this.connectTimeoutTimer_ = null; + } + this.everConnected_ = true; + if (command == FIREBASE_LONGPOLL_START_PARAM) { + this.id = arg1; + this.password = arg2; + } else if (command === FIREBASE_LONGPOLL_CLOSE_COMMAND) { + // Don't clear the host cache. We got a response from the server, so we know it's reachable + if (arg1) { + // We aren't expecting any more data (other than what the server's already in the process of sending us + // through our already open polls), so don't send any more. + this.scriptTagHolder.sendNewPolls = false; + + // arg1 in this case is the last response number sent by the server. We should try to receive + // all of the responses up to this one before closing + this.myPacketOrderer.closeAfter(arg1, () => { this.onClosed_(); }); + } else { + this.onClosed_(); + } + } else { + throw new Error('Unrecognized command received: ' + command); + } + }, (...args) => { + const [pN, data] = args; + this.incrementIncomingBytes_(args); + this.myPacketOrderer.handleResponse(pN, data); + }, () => { + this.onClosed_(); + }, this.urlFn); + + //Send the initial request to connect. The serial number is simply to keep the browser from pulling previous results + //from cache. + const urlParams = {}; + urlParams[FIREBASE_LONGPOLL_START_PARAM] = 't'; + urlParams[FIREBASE_LONGPOLL_SERIAL_PARAM] = Math.floor(Math.random() * 100000000); + if (this.scriptTagHolder.uniqueCallbackIdentifier) + urlParams[FIREBASE_LONGPOLL_CALLBACK_ID_PARAM] = this.scriptTagHolder.uniqueCallbackIdentifier; + urlParams[CONSTANTS.VERSION_PARAM] = CONSTANTS.PROTOCOL_VERSION; + if (this.transportSessionId) { + urlParams[CONSTANTS.TRANSPORT_SESSION_PARAM] = this.transportSessionId; + } + if (this.lastSessionId) { + urlParams[CONSTANTS.LAST_SESSION_PARAM] = this.lastSessionId; + } + if (!isNodeSdk() && + typeof location !== 'undefined' && + location.href && + location.href.indexOf(CONSTANTS.FORGE_DOMAIN) !== -1) { + urlParams[CONSTANTS.REFERER_PARAM] = CONSTANTS.FORGE_REF; + } + const connectURL = this.urlFn(urlParams); + this.log_('Connecting via long-poll to ' + connectURL); + this.scriptTagHolder.addTag(connectURL, () => { /* do nothing */ }); + }); + }; + + /** + * Call this when a handshake has completed successfully and we want to consider the connection established + */ + start() { + this.scriptTagHolder.startLongPoll(this.id, this.password); + this.addDisconnectPingFrame(this.id, this.password); + }; + + private static forceAllow_; + + /** + * Forces long polling to be considered as a potential transport + */ + static forceAllow() { + BrowserPollConnection.forceAllow_ = true; + }; + + private static forceDisallow_; + + /** + * Forces longpolling to not be considered as a potential transport + */ + static forceDisallow() { + BrowserPollConnection.forceDisallow_ = true; + }; + + // Static method, use string literal so it can be accessed in a generic way + static isAvailable() { + // NOTE: In React-Native there's normally no 'document', but if you debug a React-Native app in + // the Chrome debugger, 'document' is defined, but document.createElement is null (2015/06/08). + return BrowserPollConnection.forceAllow_ || ( + !BrowserPollConnection.forceDisallow_ && + typeof document !== 'undefined' && document.createElement != null && + !isChromeExtensionContentScript() && + !isWindowsStoreApp() && + !isNodeSdk() + ); + }; + + /** + * No-op for polling + */ + markConnectionHealthy() { }; + + /** + * Stops polling and cleans up the iframe + * @private + */ + private shutdown_() { + this.isClosed_ = true; + + if (this.scriptTagHolder) { + this.scriptTagHolder.close(); + this.scriptTagHolder = null; + } + + //remove the disconnect frame, which will trigger an XHR call to the server to tell it we're leaving. + if (this.myDisconnFrame) { + document.body.removeChild(this.myDisconnFrame); + this.myDisconnFrame = null; + } + + if (this.connectTimeoutTimer_) { + clearTimeout(this.connectTimeoutTimer_); + this.connectTimeoutTimer_ = null; + } + }; + + /** + * Triggered when this transport is closed + * @private + */ + private onClosed_() { + if (!this.isClosed_) { + this.log_('Longpoll is closing itself'); + this.shutdown_(); + + if (this.onDisconnect_) { + this.onDisconnect_(this.everConnected_); + this.onDisconnect_ = null; + } + } + }; + + /** + * External-facing close handler. RealTime has requested we shut down. Kill our connection and tell the server + * that we've left. + */ + close() { + if (!this.isClosed_) { + this.log_('Longpoll is being closed.'); + this.shutdown_(); + } + }; + + /** + * Send the JSON object down to the server. It will need to be stringified, base64 encoded, and then + * broken into chunks (since URLs have a small maximum length). + * @param {!Object} data The JSON data to transmit. + */ + send(data: Object) { + const dataStr = stringify(data); + this.bytesSent += dataStr.length; + this.stats_.incrementCounter('bytes_sent', dataStr.length); + + //first, lets get the base64-encoded data + const base64data = base64Encode(dataStr); + + //We can only fit a certain amount in each URL, so we need to split this request + //up into multiple pieces if it doesn't fit in one request. + const dataSegs = splitStringBySize(base64data, MAX_PAYLOAD_SIZE); + + //Enqueue each segment for transmission. We assign each chunk a sequential ID and a total number + //of segments so that we can reassemble the packet on the server. + for (let i = 0; i < dataSegs.length; i++) { + this.scriptTagHolder.enqueueSegment(this.curSegmentNum, dataSegs.length, dataSegs[i]); + this.curSegmentNum++; + } + }; + + /** + * This is how we notify the server that we're leaving. + * We aren't able to send requests with DHTML on a window close event, but we can + * trigger XHR requests in some browsers (everything but Opera basically). + * @param {!string} id + * @param {!string} pw + */ + addDisconnectPingFrame(id: string, pw: string) { + if (isNodeSdk()) return; + this.myDisconnFrame = document.createElement('iframe'); + const urlParams = {}; + urlParams[FIREBASE_LONGPOLL_DISCONN_FRAME_REQUEST_PARAM] = 't'; + urlParams[FIREBASE_LONGPOLL_ID_PARAM] = id; + urlParams[FIREBASE_LONGPOLL_PW_PARAM] = pw; + this.myDisconnFrame.src = this.urlFn(urlParams); + this.myDisconnFrame.style.display = 'none'; + + document.body.appendChild(this.myDisconnFrame); + }; + + /** + * Used to track the bytes received by this client + * @param {*} args + * @private + */ + private incrementIncomingBytes_(args: any) { + // TODO: This is an annoying perf hit just to track the number of incoming bytes. Maybe it should be opt-in. + const bytesReceived = stringify(args).length; + this.bytesReceived += bytesReceived; + this.stats_.incrementCounter('bytes_received', bytesReceived); + }; +} + +export interface IFrameElement extends HTMLIFrameElement { + doc: Document; +} + +/********************************************************************************************* + * A wrapper around an iframe that is used as a long-polling script holder. + * @constructor + * @param commandCB - The callback to be called when control commands are recevied from the server. + * @param onMessageCB - The callback to be triggered when responses arrive from the server. + * @param onDisconnect - The callback to be triggered when this tag holder is closed + * @param urlFn - A function that provides the URL of the endpoint to send data to. + *********************************************************************************************/ +export class FirebaseIFrameScriptHolder { + //We maintain a count of all of the outstanding requests, because if we have too many active at once it can cause + //problems in some browsers. + /** + * @type {CountedSet.} + */ + outstandingRequests = new CountedSet(); + + //A queue of the pending segments waiting for transmission to the server. + pendingSegs = []; + + //A serial number. We use this for two things: + // 1) A way to ensure the browser doesn't cache responses to polls + // 2) A way to make the server aware when long-polls arrive in a different order than we started them. The + // server needs to release both polls in this case or it will cause problems in Opera since Opera can only execute + // JSONP code in the order it was added to the iframe. + currentSerial = Math.floor(Math.random() * 100000000); + + // This gets set to false when we're "closing down" the connection (e.g. we're switching transports but there's still + // incoming data from the server that we're waiting for). + sendNewPolls = true; + + uniqueCallbackIdentifier: number; + myIFrame: IFrameElement; + alive: boolean; + myID: string; + myPW: string; + commandCB; + onMessageCB; + + constructor(commandCB, onMessageCB, public onDisconnect, public urlFn) { + if (!isNodeSdk()) { + //Each script holder registers a couple of uniquely named callbacks with the window. These are called from the + //iframes where we put the long-polling script tags. We have two callbacks: + // 1) Command Callback - Triggered for control issues, like starting a connection. + // 2) Message Callback - Triggered when new data arrives. + this.uniqueCallbackIdentifier = LUIDGenerator(); + window[FIREBASE_LONGPOLL_COMMAND_CB_NAME + this.uniqueCallbackIdentifier] = commandCB; + window[FIREBASE_LONGPOLL_DATA_CB_NAME + this.uniqueCallbackIdentifier] = onMessageCB; + + //Create an iframe for us to add script tags to. + this.myIFrame = FirebaseIFrameScriptHolder.createIFrame_(); + + // Set the iframe's contents. + let script = ''; + // if we set a javascript url, it's IE and we need to set the document domain. The javascript url is sufficient + // for ie9, but ie8 needs to do it again in the document itself. + if (this.myIFrame.src && this.myIFrame.src.substr(0, 'javascript:'.length) === 'javascript:') { + const currentDomain = document.domain; + script = ''; + } + const iframeContents = '' + script + ''; + try { + this.myIFrame.doc.open(); + this.myIFrame.doc.write(iframeContents); + this.myIFrame.doc.close(); + } catch (e) { + log('frame writing exception'); + if (e.stack) { + log(e.stack); + } + log(e); + } + } else { + this.commandCB = commandCB; + this.onMessageCB = onMessageCB; + } + } + + /** + * Each browser has its own funny way to handle iframes. Here we mush them all together into one object that I can + * actually use. + * @private + * @return {Element} + */ + private static createIFrame_(): IFrameElement { + const iframe = document.createElement('iframe'); + iframe.style.display = 'none'; + + // This is necessary in order to initialize the document inside the iframe + if (document.body) { + document.body.appendChild(iframe); + try { + // If document.domain has been modified in IE, this will throw an error, and we need to set the + // domain of the iframe's document manually. We can do this via a javascript: url as the src attribute + // Also note that we must do this *after* the iframe has been appended to the page. Otherwise it doesn't work. + const a = iframe.contentWindow.document; + if (!a) { + // Apologies for the log-spam, I need to do something to keep closure from optimizing out the assignment above. + log('No IE domain setting required'); + } + } catch (e) { + const domain = document.domain; + iframe.src = 'javascript:void((function(){document.open();document.domain=\'' + domain + + '\';document.close();})())'; + } + } else { + // LongPollConnection attempts to delay initialization until the document is ready, so hopefully this + // never gets hit. + throw 'Document body has not initialized. Wait to initialize Firebase until after the document is ready.'; + } + + // Get the document of the iframe in a browser-specific way. + if (iframe.contentDocument) { + (iframe as any).doc = iframe.contentDocument; // Firefox, Opera, Safari + } else if (iframe.contentWindow) { + (iframe as any).doc = iframe.contentWindow.document; // Internet Explorer + } else if ((iframe as any).document) { + (iframe as any).doc = (iframe as any).document; //others? + } + + return iframe; + } + + /** + * Cancel all outstanding queries and remove the frame. + */ + close() { + //Mark this iframe as dead, so no new requests are sent. + this.alive = false; + + if (this.myIFrame) { + //We have to actually remove all of the html inside this iframe before removing it from the + //window, or IE will continue loading and executing the script tags we've already added, which + //can lead to some errors being thrown. Setting innerHTML seems to be the easiest way to do this. + this.myIFrame.doc.body.innerHTML = ''; + setTimeout(() => { + if (this.myIFrame !== null) { + document.body.removeChild(this.myIFrame); + this.myIFrame = null; + } + }, Math.floor(0)); + } + + if (isNodeSdk() && this.myID) { + var urlParams = {}; + urlParams[FIREBASE_LONGPOLL_DISCONN_FRAME_PARAM] = 't'; + urlParams[FIREBASE_LONGPOLL_ID_PARAM] = this.myID; + urlParams[FIREBASE_LONGPOLL_PW_PARAM] = this.myPW; + var theURL = this.urlFn(urlParams); + (FirebaseIFrameScriptHolder).nodeRestRequest(theURL); + } + + // Protect from being called recursively. + const onDisconnect = this.onDisconnect; + if (onDisconnect) { + this.onDisconnect = null; + onDisconnect(); + } + } + + /** + * Actually start the long-polling session by adding the first script tag(s) to the iframe. + * @param {!string} id - The ID of this connection + * @param {!string} pw - The password for this connection + */ + startLongPoll(id: string, pw: string) { + this.myID = id; + this.myPW = pw; + this.alive = true; + + //send the initial request. If there are requests queued, make sure that we transmit as many as we are currently able to. + while (this.newRequest_()) {} + }; + + /** + * This is called any time someone might want a script tag to be added. It adds a script tag when there aren't + * too many outstanding requests and we are still alive. + * + * If there are outstanding packet segments to send, it sends one. If there aren't, it sends a long-poll anyways if + * needed. + */ + private newRequest_() { + // We keep one outstanding request open all the time to receive data, but if we need to send data + // (pendingSegs.length > 0) then we create a new request to send the data. The server will automatically + // close the old request. + if (this.alive && this.sendNewPolls && this.outstandingRequests.count() < (this.pendingSegs.length > 0 ? 2 : 1)) { + //construct our url + this.currentSerial++; + const urlParams = {}; + urlParams[FIREBASE_LONGPOLL_ID_PARAM] = this.myID; + urlParams[FIREBASE_LONGPOLL_PW_PARAM] = this.myPW; + urlParams[FIREBASE_LONGPOLL_SERIAL_PARAM] = this.currentSerial; + let theURL = this.urlFn(urlParams); + //Now add as much data as we can. + let curDataString = ''; + let i = 0; + + while (this.pendingSegs.length > 0) { + //first, lets see if the next segment will fit. + const nextSeg = this.pendingSegs[0]; + if (nextSeg.d.length + SEG_HEADER_SIZE + curDataString.length <= MAX_URL_DATA_SIZE) { + //great, the segment will fit. Lets append it. + const theSeg = this.pendingSegs.shift(); + curDataString = curDataString + '&' + FIREBASE_LONGPOLL_SEGMENT_NUM_PARAM + i + '=' + theSeg.seg + + '&' + FIREBASE_LONGPOLL_SEGMENTS_IN_PACKET + i + '=' + theSeg.ts + '&' + FIREBASE_LONGPOLL_DATA_PARAM + i + '=' + theSeg.d; + i++; + } else { + break; + } + } + + theURL = theURL + curDataString; + this.addLongPollTag_(theURL, this.currentSerial); + + return true; + } else { + return false; + } + }; + + /** + * Queue a packet for transmission to the server. + * @param segnum - A sequential id for this packet segment used for reassembly + * @param totalsegs - The total number of segments in this packet + * @param data - The data for this segment. + */ + enqueueSegment(segnum, totalsegs, data) { + //add this to the queue of segments to send. + this.pendingSegs.push({seg: segnum, ts: totalsegs, d: data}); + + //send the data immediately if there isn't already data being transmitted, unless + //startLongPoll hasn't been called yet. + if (this.alive) { + this.newRequest_(); + } + }; + + /** + * Add a script tag for a regular long-poll request. + * @param {!string} url - The URL of the script tag. + * @param {!number} serial - The serial number of the request. + * @private + */ + private addLongPollTag_(url: string, serial: number) { + //remember that we sent this request. + this.outstandingRequests.add(serial, 1); + + const doNewRequest = () => { + this.outstandingRequests.remove(serial); + this.newRequest_(); + }; + + // If this request doesn't return on its own accord (by the server sending us some data), we'll + // create a new one after the KEEPALIVE interval to make sure we always keep a fresh request open. + const keepaliveTimeout = setTimeout(doNewRequest, Math.floor(KEEPALIVE_REQUEST_INTERVAL)); + + const readyStateCB = () => { + // Request completed. Cancel the keepalive. + clearTimeout(keepaliveTimeout); + + // Trigger a new request so we can continue receiving data. + doNewRequest(); + }; + + this.addTag(url, readyStateCB); + }; + + /** + * Add an arbitrary script tag to the iframe. + * @param {!string} url - The URL for the script tag source. + * @param {!function()} loadCB - A callback to be triggered once the script has loaded. + */ + addTag(url: string, loadCB: () => any) { + if (isNodeSdk()) { + (this).doNodeLongPoll(url, loadCB); + } else { + setTimeout(() => { + try { + // if we're already closed, don't add this poll + if (!this.sendNewPolls) return; + const newScript = this.myIFrame.doc.createElement('script'); + newScript.type = 'text/javascript'; + newScript.async = true; + newScript.src = url; + newScript.onload = (newScript).onreadystatechange = function () { + const rstate = (newScript).readyState; + if (!rstate || rstate === 'loaded' || rstate === 'complete') { + newScript.onload = (newScript).onreadystatechange = null; + if (newScript.parentNode) { + newScript.parentNode.removeChild(newScript); + } + loadCB(); + } + }; + newScript.onerror = () => { + log('Long-poll script failed to load: ' + url); + this.sendNewPolls = false; + this.close(); + }; + this.myIFrame.doc.body.appendChild(newScript); + } catch (e) { + // TODO: we should make this error visible somehow + } + }, Math.floor(1)); + } + } +} diff --git a/src/database/realtime/Connection.ts b/src/database/realtime/Connection.ts new file mode 100644 index 00000000000..cffd9aafd02 --- /dev/null +++ b/src/database/realtime/Connection.ts @@ -0,0 +1,538 @@ +import { + error, + logWrapper, + requireKey, + setTimeoutNonBlocking, + warn, +} from '../core/util/util'; +import { PersistentStorage } from '../core/storage/storage'; +import { CONSTANTS } from './Constants'; +import { TransportManager } from './TransportManager'; +import { RepoInfo } from '../core/RepoInfo'; + +// Abort upgrade attempt if it takes longer than 60s. +const UPGRADE_TIMEOUT = 60000; + +// For some transports (WebSockets), we need to "validate" the transport by exchanging a few requests and responses. +// If we haven't sent enough requests within 5s, we'll start sending noop ping requests. +const DELAY_BEFORE_SENDING_EXTRA_REQUESTS = 5000; + +// If the initial data sent triggers a lot of bandwidth (i.e. it's a large put or a listen for a large amount of data) +// then we may not be able to exchange our ping/pong requests within the healthy timeout. So if we reach the timeout +// but we've sent/received enough bytes, we don't cancel the connection. +const BYTES_SENT_HEALTHY_OVERRIDE = 10 * 1024; +const BYTES_RECEIVED_HEALTHY_OVERRIDE = 100 * 1024; + + +const REALTIME_STATE_CONNECTING = 0; +const REALTIME_STATE_CONNECTED = 1; +const REALTIME_STATE_DISCONNECTED = 2; + +const MESSAGE_TYPE = 't'; +const MESSAGE_DATA = 'd'; +const CONTROL_SHUTDOWN = 's'; +const CONTROL_RESET = 'r'; +const CONTROL_ERROR = 'e'; +const CONTROL_PONG = 'o'; +const SWITCH_ACK = 'a'; +const END_TRANSMISSION = 'n'; +const PING = 'p'; + +const SERVER_HELLO = 'h'; + +/** + * Creates a new real-time connection to the server using whichever method works + * best in the current browser. + * + * @constructor + * @param {!string} connId - an id for this connection + * @param {!RepoInfo} repoInfo - the info for the endpoint to connect to + * @param {function(Object)} onMessage - the callback to be triggered when a server-push message arrives + * @param {function(number, string)} onReady - the callback to be triggered when this connection is ready to send messages. + * @param {function()} onDisconnect - the callback to be triggered when a connection was lost + * @param {function(string)} onKill - the callback to be triggered when this connection has permanently shut down. + * @param {string=} lastSessionId - last session id in persistent connection. is used to clean up old session in real-time server + + */ +export class Connection { + connectionCount; + id; + lastSessionId; + pendingDataMessages; + sessionId; + + private conn_; + private healthyTimeout_; + private isHealthy_; + private log_; + private onDisconnect_; + private onKill_; + private onMessage_; + private onReady_; + private primaryResponsesRequired_; + private repoInfo_; + private rx_; + private secondaryConn_; + private secondaryResponsesRequired_; + private state_; + private transportManager_; + private tx_; + + constructor(connId: string, + repoInfo: RepoInfo, + onMessage: (a: Object) => any, + onReady: (a: number, b: string) => any, + onDisconnect: () => any, + onKill: (a: string) => any, + lastSessionId?: string) { + this.id = connId; + this.log_ = logWrapper('c:' + this.id + ':'); + this.onMessage_ = onMessage; + this.onReady_ = onReady; + this.onDisconnect_ = onDisconnect; + this.onKill_ = onKill; + this.repoInfo_ = repoInfo; + this.pendingDataMessages = []; + this.connectionCount = 0; + this.transportManager_ = new TransportManager(repoInfo); + this.state_ = REALTIME_STATE_CONNECTING; + this.lastSessionId = lastSessionId; + this.log_('Connection created'); + this.start_(); + } + + /** + * Starts a connection attempt + * @private + */ + private start_() { + const conn = this.transportManager_.initialTransport(); + this.conn_ = new conn(this.nextTransportId_(), this.repoInfo_, undefined, this.lastSessionId); + + // For certain transports (WebSockets), we need to send and receive several messages back and forth before we + // can consider the transport healthy. + this.primaryResponsesRequired_ = conn['responsesRequiredToBeHealthy'] || 0; + + const onMessageReceived = this.connReceiver_(this.conn_); + const onConnectionLost = this.disconnReceiver_(this.conn_); + this.tx_ = this.conn_; + this.rx_ = this.conn_; + this.secondaryConn_ = null; + this.isHealthy_ = false; + + /* + * Firefox doesn't like when code from one iframe tries to create another iframe by way of the parent frame. + * This can occur in the case of a redirect, i.e. we guessed wrong on what server to connect to and received a reset. + * Somehow, setTimeout seems to make this ok. That doesn't make sense from a security perspective, since you should + * still have the context of your originating frame. + */ + setTimeout(() => { + // self.conn_ gets set to null in some of the tests. Check to make sure it still exists before using it + this.conn_ && this.conn_.open(onMessageReceived, onConnectionLost); + }, Math.floor(0)); + + + const healthyTimeout_ms = conn['healthyTimeout'] || 0; + if (healthyTimeout_ms > 0) { + this.healthyTimeout_ = setTimeoutNonBlocking(() => { + this.healthyTimeout_ = null; + if (!this.isHealthy_) { + if (this.conn_ && this.conn_.bytesReceived > BYTES_RECEIVED_HEALTHY_OVERRIDE) { + this.log_('Connection exceeded healthy timeout but has received ' + this.conn_.bytesReceived + + ' bytes. Marking connection healthy.'); + this.isHealthy_ = true; + this.conn_.markConnectionHealthy(); + } else if (this.conn_ && this.conn_.bytesSent > BYTES_SENT_HEALTHY_OVERRIDE) { + this.log_('Connection exceeded healthy timeout but has sent ' + this.conn_.bytesSent + + ' bytes. Leaving connection alive.'); + // NOTE: We don't want to mark it healthy, since we have no guarantee that the bytes have made it to + // the server. + } else { + this.log_('Closing unhealthy connection after timeout.'); + this.close(); + } + } + }, Math.floor(healthyTimeout_ms)); + } + }; + + /** + * @return {!string} + * @private + */ + private nextTransportId_() { + return 'c:' + this.id + ':' + this.connectionCount++; + }; + + private disconnReceiver_(conn) { + return everConnected => { + if (conn === this.conn_) { + this.onConnectionLost_(everConnected); + } else if (conn === this.secondaryConn_) { + this.log_('Secondary connection lost.'); + this.onSecondaryConnectionLost_(); + } else { + this.log_('closing an old connection'); + } + } + }; + + private connReceiver_(conn) { + return message => { + if (this.state_ != REALTIME_STATE_DISCONNECTED) { + if (conn === this.rx_) { + this.onPrimaryMessageReceived_(message); + } else if (conn === this.secondaryConn_) { + this.onSecondaryMessageReceived_(message); + } else { + this.log_('message on old connection'); + } + } + }; + }; + + /** + * + * @param {Object} dataMsg An arbitrary data message to be sent to the server + */ + sendRequest(dataMsg) { + // wrap in a data message envelope and send it on + const msg = {'t': 'd', 'd': dataMsg}; + this.sendData_(msg); + }; + + tryCleanupConnection() { + if (this.tx_ === this.secondaryConn_ && this.rx_ === this.secondaryConn_) { + this.log_('cleaning up and promoting a connection: ' + this.secondaryConn_.connId); + this.conn_ = this.secondaryConn_; + this.secondaryConn_ = null; + // the server will shutdown the old connection + } + }; + + private onSecondaryControl_(controlData) { + if (MESSAGE_TYPE in controlData) { + const cmd = controlData[MESSAGE_TYPE]; + if (cmd === SWITCH_ACK) { + this.upgradeIfSecondaryHealthy_(); + } else if (cmd === CONTROL_RESET) { + // Most likely the session wasn't valid. Abandon the switch attempt + this.log_('Got a reset on secondary, closing it'); + this.secondaryConn_.close(); + // If we were already using this connection for something, than we need to fully close + if (this.tx_ === this.secondaryConn_ || this.rx_ === this.secondaryConn_) { + this.close(); + } + } else if (cmd === CONTROL_PONG) { + this.log_('got pong on secondary.'); + this.secondaryResponsesRequired_--; + this.upgradeIfSecondaryHealthy_(); + } + } + }; + + private onSecondaryMessageReceived_(parsedData) { + const layer = requireKey('t', parsedData); + const data = requireKey('d', parsedData); + if (layer == 'c') { + this.onSecondaryControl_(data); + } else if (layer == 'd') { + // got a data message, but we're still second connection. Need to buffer it up + this.pendingDataMessages.push(data); + } else { + throw new Error('Unknown protocol layer: ' + layer); + } + }; + + private upgradeIfSecondaryHealthy_() { + if (this.secondaryResponsesRequired_ <= 0) { + this.log_('Secondary connection is healthy.'); + this.isHealthy_ = true; + this.secondaryConn_.markConnectionHealthy(); + this.proceedWithUpgrade_(); + } else { + // Send a ping to make sure the connection is healthy. + this.log_('sending ping on secondary.'); + this.secondaryConn_.send({'t': 'c', 'd': {'t': PING, 'd': {}}}); + } + }; + + private proceedWithUpgrade_() { + // tell this connection to consider itself open + this.secondaryConn_.start(); + // send ack + this.log_('sending client ack on secondary'); + this.secondaryConn_.send({'t': 'c', 'd': {'t': SWITCH_ACK, 'd': {}}}); + + // send end packet on primary transport, switch to sending on this one + // can receive on this one, buffer responses until end received on primary transport + this.log_('Ending transmission on primary'); + this.conn_.send({'t': 'c', 'd': {'t': END_TRANSMISSION, 'd': {}}}); + this.tx_ = this.secondaryConn_; + + this.tryCleanupConnection(); + }; + + private onPrimaryMessageReceived_(parsedData) { + // Must refer to parsedData properties in quotes, so closure doesn't touch them. + const layer = requireKey('t', parsedData); + const data = requireKey('d', parsedData); + if (layer == 'c') { + this.onControl_(data); + } else if (layer == 'd') { + this.onDataMessage_(data); + } + }; + + private onDataMessage_(message) { + this.onPrimaryResponse_(); + + // We don't do anything with data messages, just kick them up a level + this.onMessage_(message); + }; + + private onPrimaryResponse_() { + if (!this.isHealthy_) { + this.primaryResponsesRequired_--; + if (this.primaryResponsesRequired_ <= 0) { + this.log_('Primary connection is healthy.'); + this.isHealthy_ = true; + this.conn_.markConnectionHealthy(); + } + } + }; + + private onControl_(controlData) { + const cmd = requireKey(MESSAGE_TYPE, controlData); + if (MESSAGE_DATA in controlData) { + const payload = controlData[MESSAGE_DATA]; + if (cmd === SERVER_HELLO) { + this.onHandshake_(payload); + } else if (cmd === END_TRANSMISSION) { + this.log_('recvd end transmission on primary'); + this.rx_ = this.secondaryConn_; + for (let i = 0; i < this.pendingDataMessages.length; ++i) { + this.onDataMessage_(this.pendingDataMessages[i]); + } + this.pendingDataMessages = []; + this.tryCleanupConnection(); + } else if (cmd === CONTROL_SHUTDOWN) { + // This was previously the 'onKill' callback passed to the lower-level connection + // payload in this case is the reason for the shutdown. Generally a human-readable error + this.onConnectionShutdown_(payload); + } else if (cmd === CONTROL_RESET) { + // payload in this case is the host we should contact + this.onReset_(payload); + } else if (cmd === CONTROL_ERROR) { + error('Server Error: ' + payload); + } else if (cmd === CONTROL_PONG) { + this.log_('got pong on primary.'); + this.onPrimaryResponse_(); + this.sendPingOnPrimaryIfNecessary_(); + } else { + error('Unknown control packet command: ' + cmd); + } + } + }; + + /** + * + * @param {Object} handshake The handshake data returned from the server + * @private + */ + private onHandshake_(handshake) { + const timestamp = handshake['ts']; + const version = handshake['v']; + const host = handshake['h']; + this.sessionId = handshake['s']; + this.repoInfo_.updateHost(host); + // if we've already closed the connection, then don't bother trying to progress further + if (this.state_ == REALTIME_STATE_CONNECTING) { + this.conn_.start(); + this.onConnectionEstablished_(this.conn_, timestamp); + if (CONSTANTS.PROTOCOL_VERSION !== version) { + warn('Protocol version mismatch detected'); + } + // TODO: do we want to upgrade? when? maybe a delay? + this.tryStartUpgrade_(); + } + }; + + private tryStartUpgrade_() { + const conn = this.transportManager_.upgradeTransport(); + if (conn) { + this.startUpgrade_(conn); + } + }; + + private startUpgrade_(conn) { + this.secondaryConn_ = new conn(this.nextTransportId_(), + this.repoInfo_, this.sessionId); + // For certain transports (WebSockets), we need to send and receive several messages back and forth before we + // can consider the transport healthy. + this.secondaryResponsesRequired_ = conn['responsesRequiredToBeHealthy'] || 0; + + const onMessage = this.connReceiver_(this.secondaryConn_); + const onDisconnect = this.disconnReceiver_(this.secondaryConn_); + this.secondaryConn_.open(onMessage, onDisconnect); + + // If we haven't successfully upgraded after UPGRADE_TIMEOUT, give up and kill the secondary. + const self = this; + setTimeoutNonBlocking(function () { + if (self.secondaryConn_) { + self.log_('Timed out trying to upgrade.'); + self.secondaryConn_.close(); + } + }, Math.floor(UPGRADE_TIMEOUT)); + }; + + private onReset_(host) { + this.log_('Reset packet received. New host: ' + host); + this.repoInfo_.updateHost(host); + // TODO: if we're already "connected", we need to trigger a disconnect at the next layer up. + // We don't currently support resets after the connection has already been established + if (this.state_ === REALTIME_STATE_CONNECTED) { + this.close(); + } else { + // Close whatever connections we have open and start again. + this.closeConnections_(); + this.start_(); + } + }; + + private onConnectionEstablished_(conn, timestamp) { + this.log_('Realtime connection established.'); + this.conn_ = conn; + this.state_ = REALTIME_STATE_CONNECTED; + + if (this.onReady_) { + this.onReady_(timestamp, this.sessionId); + this.onReady_ = null; + } + + const self = this; + // If after 5 seconds we haven't sent enough requests to the server to get the connection healthy, + // send some pings. + if (this.primaryResponsesRequired_ === 0) { + this.log_('Primary connection is healthy.'); + this.isHealthy_ = true; + } else { + setTimeoutNonBlocking(function () { + self.sendPingOnPrimaryIfNecessary_(); + }, Math.floor(DELAY_BEFORE_SENDING_EXTRA_REQUESTS)); + } + }; + + private sendPingOnPrimaryIfNecessary_() { + // If the connection isn't considered healthy yet, we'll send a noop ping packet request. + if (!this.isHealthy_ && this.state_ === REALTIME_STATE_CONNECTED) { + this.log_('sending ping on primary.'); + this.sendData_({'t': 'c', 'd': {'t': PING, 'd': {}}}); + } + }; + + private onSecondaryConnectionLost_() { + const conn = this.secondaryConn_; + this.secondaryConn_ = null; + if (this.tx_ === conn || this.rx_ === conn) { + // we are relying on this connection already in some capacity. Therefore, a failure is real + this.close(); + } + }; + + /** + * + * @param {boolean} everConnected Whether or not the connection ever reached a server. Used to determine if + * we should flush the host cache + * @private + */ + private onConnectionLost_(everConnected) { + this.conn_ = null; + + // NOTE: IF you're seeing a Firefox error for this line, I think it might be because it's getting + // called on window close and REALTIME_STATE_CONNECTING is no longer defined. Just a guess. + if (!everConnected && this.state_ === REALTIME_STATE_CONNECTING) { + this.log_('Realtime connection failed.'); + // Since we failed to connect at all, clear any cached entry for this namespace in case the machine went away + if (this.repoInfo_.isCacheableHost()) { + PersistentStorage.remove('host:' + this.repoInfo_.host); + // reset the internal host to what we would show the user, i.e. .firebaseio.com + this.repoInfo_.internalHost = this.repoInfo_.host; + } + } else if (this.state_ === REALTIME_STATE_CONNECTED) { + this.log_('Realtime connection lost.'); + } + + this.close(); + }; + + /** + * + * @param {string} reason + * @private + */ + private onConnectionShutdown_(reason) { + this.log_('Connection shutdown command received. Shutting down...'); + + if (this.onKill_) { + this.onKill_(reason); + this.onKill_ = null; + } + + // We intentionally don't want to fire onDisconnect (kill is a different case), + // so clear the callback. + this.onDisconnect_ = null; + + this.close(); + }; + + + private sendData_(data) { + if (this.state_ !== REALTIME_STATE_CONNECTED) { + throw 'Connection is not connected'; + } else { + this.tx_.send(data); + } + }; + + /** + * Cleans up this connection, calling the appropriate callbacks + */ + close() { + if (this.state_ !== REALTIME_STATE_DISCONNECTED) { + this.log_('Closing realtime connection.'); + this.state_ = REALTIME_STATE_DISCONNECTED; + + this.closeConnections_(); + + if (this.onDisconnect_) { + this.onDisconnect_(); + this.onDisconnect_ = null; + } + } + }; + + /** + * + * @private + */ + private closeConnections_() { + this.log_('Shutting down all connections'); + if (this.conn_) { + this.conn_.close(); + this.conn_ = null; + } + + if (this.secondaryConn_) { + this.secondaryConn_.close(); + this.secondaryConn_ = null; + } + + if (this.healthyTimeout_) { + clearTimeout(this.healthyTimeout_); + this.healthyTimeout_ = null; + } + }; +} + + diff --git a/src/database/realtime/Constants.ts b/src/database/realtime/Constants.ts new file mode 100644 index 00000000000..650ead1001c --- /dev/null +++ b/src/database/realtime/Constants.ts @@ -0,0 +1,20 @@ +export const CONSTANTS = { + + /** @const */ PROTOCOL_VERSION: '5', + + /** @const */ VERSION_PARAM: 'v', + + /** @const */ TRANSPORT_SESSION_PARAM: 's', + + /** @const */ REFERER_PARAM: 'r', + + /** @const */ FORGE_REF: 'f', + + /** @const */ FORGE_DOMAIN: 'firebaseio.com', + + /** @const */ LAST_SESSION_PARAM: 'ls', + + /** @const */ WEBSOCKET: 'websocket', + + /** @const */ LONG_POLLING: 'long_polling' +}; diff --git a/src/database/realtime/Transport.ts b/src/database/realtime/Transport.ts new file mode 100644 index 00000000000..b0d0b066738 --- /dev/null +++ b/src/database/realtime/Transport.ts @@ -0,0 +1,40 @@ +import { RepoInfo } from '../core/RepoInfo'; + +export abstract class Transport { + /** + * Bytes received since connection started. + * @type {number} + */ + abstract bytesReceived: number; + + /** + * Bytes sent since connection started. + * @type {number} + */ + abstract bytesSent: number; + + /** + * + * @param {string} connId An identifier for this connection, used for logging + * @param {RepoInfo} repoInfo The info for the endpoint to send data to. + * @param {string=} transportSessionId Optional transportSessionId if this is connecting to an existing transport session + * @param {string=} lastSessionId Optional lastSessionId if there was a previous connection + * @interface + */ + constructor(connId: string, repoInfo: RepoInfo, transportSessionId?: string, lastSessionId?: string) {} + + /** + * @param {function(Object)} onMessage Callback when messages arrive + * @param {function()} onDisconnect Callback with connection lost. + */ + abstract open(onMessage: (a: Object) => any, onDisconnect: () => any); + + abstract start(); + + abstract close(); + + /** + * @param {!Object} data The JSON data to transmit + */ + abstract send(data: Object); +} \ No newline at end of file diff --git a/src/database/realtime/TransportManager.ts b/src/database/realtime/TransportManager.ts new file mode 100644 index 00000000000..f9c7096488e --- /dev/null +++ b/src/database/realtime/TransportManager.ts @@ -0,0 +1,81 @@ +import { BrowserPollConnection } from "./BrowserPollConnection"; +import { WebSocketConnection } from "./WebSocketConnection"; +import { warn, each } from "../core/util/util"; + +/** + * Currently simplistic, this class manages what transport a Connection should use at various stages of its + * lifecycle. + * + * It starts with longpolling in a browser, and httppolling on node. It then upgrades to websockets if + * they are available. + * @constructor + * @param {!RepoInfo} repoInfo Metadata around the namespace we're connecting to + */ +export class TransportManager { + transports_: Array; + /** + * @const + * @type {!Array.} + */ + static get ALL_TRANSPORTS() { + return [ + BrowserPollConnection, + WebSocketConnection + ]; + } + constructor(repoInfo) { + this.initTransports_(repoInfo); + }; + + /** + * @param {!RepoInfo} repoInfo + * @private + */ + initTransports_(repoInfo) { + const isWebSocketsAvailable = WebSocketConnection && WebSocketConnection['isAvailable'](); + let isSkipPollConnection = isWebSocketsAvailable && !WebSocketConnection.previouslyFailed(); + + if (repoInfo.webSocketOnly) { + if (!isWebSocketsAvailable) + warn('wss:// URL used, but browser isn\'t known to support websockets. Trying anyway.'); + + isSkipPollConnection = true; + } + + if (isSkipPollConnection) { + this.transports_ = [WebSocketConnection]; + } else { + const transports = this.transports_ = []; + each(TransportManager.ALL_TRANSPORTS, function(i, transport) { + if (transport && transport['isAvailable']()) { + transports.push(transport); + } + }); + } + } + + /** + * @return {function(new:Transport, !string, !RepoInfo, string=, string=)} The constructor for the + * initial transport to use + */ + initialTransport() { + if (this.transports_.length > 0) { + return this.transports_[0]; + } else { + throw new Error('No transports available'); + } + } + + /** + * @return {?function(new:Transport, function(),function(), string=)} The constructor for the next + * transport, or null + */ + upgradeTransport() { + if (this.transports_.length > 1) { + return this.transports_[1]; + } else { + return null; + } + } +} + diff --git a/src/database/realtime/WebSocketConnection.ts b/src/database/realtime/WebSocketConnection.ts new file mode 100644 index 00000000000..304432c7a01 --- /dev/null +++ b/src/database/realtime/WebSocketConnection.ts @@ -0,0 +1,388 @@ +import { RepoInfo } from '../core/RepoInfo'; +declare const MozWebSocket; + +import firebase from "../../app"; +import { assert } from '../../utils/assert'; +import { logWrapper, splitStringBySize } from '../core/util/util'; +import { StatsManager } from '../core/stats/StatsManager'; +import { CONSTANTS } from './Constants'; +import { CONSTANTS as ENV_CONSTANTS } from "../../utils/constants"; +import { PersistentStorage } from '../core/storage/storage'; +import { jsonEval, stringify } from '../../utils/json'; +import { isNodeSdk } from "../../utils/environment"; +import { Transport } from './Transport'; + +const WEBSOCKET_MAX_FRAME_SIZE = 16384; +const WEBSOCKET_KEEPALIVE_INTERVAL = 45000; + +let WebSocketImpl = null; +if (typeof MozWebSocket !== 'undefined') { + WebSocketImpl = MozWebSocket; +} else if (typeof WebSocket !== 'undefined') { + WebSocketImpl = WebSocket; +} + +export function setWebSocketImpl(impl) { + WebSocketImpl = impl; +} + +/** + * Create a new websocket connection with the given callbacks. + * @constructor + * @implements {Transport} + * @param {string} connId identifier for this transport + * @param {RepoInfo} repoInfo The info for the websocket endpoint. + * @param {string=} opt_transportSessionId Optional transportSessionId if this is connecting to an existing transport + * session + * @param {string=} opt_lastSessionId Optional lastSessionId if there was a previous connection + */ +export class WebSocketConnection implements Transport { + keepaliveTimer; + frames; + totalFrames: number; + bytesSent: number; + bytesReceived: number; + connURL; + onDisconnect; + onMessage; + mySock; + private log_; + private stats_; + private everConnected_: boolean; + private isClosed_: boolean; + + constructor(public connId: string, repoInfo: RepoInfo, transportSessionId?: string, lastSessionId?: string) { + this.log_ = logWrapper(this.connId); + this.keepaliveTimer = null; + this.frames = null; + this.totalFrames = 0; + this.bytesSent = 0; + this.bytesReceived = 0; + this.stats_ = StatsManager.getCollection(repoInfo); + this.connURL = WebSocketConnection.connectionURL_(repoInfo, transportSessionId, lastSessionId); + } + + /** + * @param {RepoInfo} repoInfo The info for the websocket endpoint. + * @param {string=} transportSessionId Optional transportSessionId if this is connecting to an existing transport + * session + * @param {string=} lastSessionId Optional lastSessionId if there was a previous connection + * @return {string} connection url + * @private + */ + private static connectionURL_(repoInfo: RepoInfo, transportSessionId?: string, lastSessionId?: string): string { + const urlParams = {}; + urlParams[CONSTANTS.VERSION_PARAM] = CONSTANTS.PROTOCOL_VERSION; + + if (!isNodeSdk() && + typeof location !== 'undefined' && + location.href && + location.href.indexOf(CONSTANTS.FORGE_DOMAIN) !== -1) { + urlParams[CONSTANTS.REFERER_PARAM] = CONSTANTS.FORGE_REF; + } + if (transportSessionId) { + urlParams[CONSTANTS.TRANSPORT_SESSION_PARAM] = transportSessionId; + } + if (lastSessionId) { + urlParams[CONSTANTS.LAST_SESSION_PARAM] = lastSessionId; + } + return repoInfo.connectionURL(CONSTANTS.WEBSOCKET, urlParams); + } + + /** + * + * @param onMessage Callback when messages arrive + * @param onDisconnect Callback with connection lost. + */ + open(onMessage: (msg: Object) => any, onDisconnect: () => any) { + this.onDisconnect = onDisconnect; + this.onMessage = onMessage; + + this.log_('Websocket connecting to ' + this.connURL); + + this.everConnected_ = false; + // Assume failure until proven otherwise. + PersistentStorage.set('previous_websocket_failure', true); + + try { + if (isNodeSdk()) { + const device = ENV_CONSTANTS.NODE_ADMIN ? 'AdminNode' : 'Node'; + // UA Format: Firebase//// + const options = { + 'headers': { + 'User-Agent': `Firebase/${CONSTANTS.PROTOCOL_VERSION}/${firebase.SDK_VERSION}/${process.platform}/${device}` + }}; + + // Plumb appropriate http_proxy environment variable into faye-websocket if it exists. + const env = process['env']; + const proxy = (this.connURL.indexOf("wss://") == 0) + ? (env['HTTPS_PROXY'] || env['https_proxy']) + : (env['HTTP_PROXY'] || env['http_proxy']); + + if (proxy) { + options['proxy'] = { origin: proxy }; + } + + this.mySock = new WebSocketImpl(this.connURL, [], options); + } else { + this.mySock = new WebSocketImpl(this.connURL); + } + } catch (e) { + this.log_('Error instantiating WebSocket.'); + const error = e.message || e.data; + if (error) { + this.log_(error); + } + this.onClosed_(); + return; + } + + this.mySock.onopen = () => { + this.log_('Websocket connected.'); + this.everConnected_ = true; + }; + + this.mySock.onclose = () => { + this.log_('Websocket connection was disconnected.'); + this.mySock = null; + this.onClosed_(); + }; + + this.mySock.onmessage = (m) => { + this.handleIncomingFrame(m); + }; + + this.mySock.onerror = (e) => { + this.log_('WebSocket error. Closing connection.'); + const error = e.message || e.data; + if (error) { + this.log_(error); + } + this.onClosed_(); + }; + } + + /** + * No-op for websockets, we don't need to do anything once the connection is confirmed as open + */ + start() {}; + + static forceDisallow_: Boolean; + + static forceDisallow() { + WebSocketConnection.forceDisallow_ = true; + } + + static isAvailable(): boolean { + let isOldAndroid = false; + if (typeof navigator !== 'undefined' && navigator.userAgent) { + const oldAndroidRegex = /Android ([0-9]{0,}\.[0-9]{0,})/; + const oldAndroidMatch = navigator.userAgent.match(oldAndroidRegex); + if (oldAndroidMatch && oldAndroidMatch.length > 1) { + if (parseFloat(oldAndroidMatch[1]) < 4.4) { + isOldAndroid = true; + } + } + } + + return !isOldAndroid && WebSocketImpl !== null && !WebSocketConnection.forceDisallow_; + } + + /** + * Number of response before we consider the connection "healthy." + * @type {number} + * + * NOTE: 'responsesRequiredToBeHealthy' shouldn't need to be quoted, but closure removed it for some reason otherwise! + */ + static responsesRequiredToBeHealthy = 2; + + /** + * Time to wait for the connection te become healthy before giving up. + * @type {number} + * + * NOTE: 'healthyTimeout' shouldn't need to be quoted, but closure removed it for some reason otherwise! + */ + static healthyTimeout = 30000; + + /** + * Returns true if we previously failed to connect with this transport. + * @return {boolean} + */ + static previouslyFailed(): boolean { + // If our persistent storage is actually only in-memory storage, + // we default to assuming that it previously failed to be safe. + return PersistentStorage.isInMemoryStorage || + PersistentStorage.get('previous_websocket_failure') === true; + }; + + markConnectionHealthy() { + PersistentStorage.remove('previous_websocket_failure'); + }; + + private appendFrame_(data) { + this.frames.push(data); + if (this.frames.length == this.totalFrames) { + const fullMess = this.frames.join(''); + this.frames = null; + const jsonMess = jsonEval(fullMess); + + //handle the message + this.onMessage(jsonMess); + } + } + + /** + * @param {number} frameCount The number of frames we are expecting from the server + * @private + */ + private handleNewFrameCount_(frameCount: number) { + this.totalFrames = frameCount; + this.frames = []; + } + + /** + * Attempts to parse a frame count out of some text. If it can't, assumes a value of 1 + * @param {!String} data + * @return {?String} Any remaining data to be process, or null if there is none + * @private + */ + private extractFrameCount_(data: string): string | null { + assert(this.frames === null, 'We already have a frame buffer'); + // TODO: The server is only supposed to send up to 9999 frames (i.e. length <= 4), but that isn't being enforced + // currently. So allowing larger frame counts (length <= 6). See https://app.asana.com/0/search/8688598998380/8237608042508 + if (data.length <= 6) { + const frameCount = Number(data); + if (!isNaN(frameCount)) { + this.handleNewFrameCount_(frameCount); + return null; + } + } + this.handleNewFrameCount_(1); + return data; + }; + + /** + * Process a websocket frame that has arrived from the server. + * @param mess The frame data + */ + handleIncomingFrame(mess) { + if (this.mySock === null) + return; // Chrome apparently delivers incoming packets even after we .close() the connection sometimes. + const data = mess['data']; + this.bytesReceived += data.length; + this.stats_.incrementCounter('bytes_received', data.length); + + this.resetKeepAlive(); + + if (this.frames !== null) { + // we're buffering + this.appendFrame_(data); + } else { + // try to parse out a frame count, otherwise, assume 1 and process it + const remainingData = this.extractFrameCount_(data); + if (remainingData !== null) { + this.appendFrame_(remainingData); + } + } + }; + + /** + * Send a message to the server + * @param {Object} data The JSON object to transmit + */ + send(data: Object) { + + this.resetKeepAlive(); + + const dataStr = stringify(data); + this.bytesSent += dataStr.length; + this.stats_.incrementCounter('bytes_sent', dataStr.length); + + //We can only fit a certain amount in each websocket frame, so we need to split this request + //up into multiple pieces if it doesn't fit in one request. + + const dataSegs = splitStringBySize(dataStr, WEBSOCKET_MAX_FRAME_SIZE); + + //Send the length header + if (dataSegs.length > 1) { + this.sendString_(String(dataSegs.length)); + } + + //Send the actual data in segments. + for (let i = 0; i < dataSegs.length; i++) { + this.sendString_(dataSegs[i]); + } + }; + + private shutdown_() { + this.isClosed_ = true; + if (this.keepaliveTimer) { + clearInterval(this.keepaliveTimer); + this.keepaliveTimer = null; + } + + if (this.mySock) { + this.mySock.close(); + this.mySock = null; + } + }; + + private onClosed_() { + if (!this.isClosed_) { + this.log_('WebSocket is closing itself'); + this.shutdown_(); + + // since this is an internal close, trigger the close listener + if (this.onDisconnect) { + this.onDisconnect(this.everConnected_); + this.onDisconnect = null; + } + } + }; + + /** + * External-facing close handler. + * Close the websocket and kill the connection. + */ + close() { + if (!this.isClosed_) { + this.log_('WebSocket is being closed'); + this.shutdown_(); + } + }; + + /** + * Kill the current keepalive timer and start a new one, to ensure that it always fires N seconds after + * the last activity. + */ + resetKeepAlive() { + clearInterval(this.keepaliveTimer); + this.keepaliveTimer = setInterval(() => { + //If there has been no websocket activity for a while, send a no-op + if (this.mySock) { + this.sendString_('0'); + } + this.resetKeepAlive(); + }, Math.floor(WEBSOCKET_KEEPALIVE_INTERVAL)); + }; + + /** + * Send a string over the websocket. + * + * @param {string} str String to send. + * @private + */ + private sendString_(str: string) { + // Firefox seems to sometimes throw exceptions (NS_ERROR_UNEXPECTED) from websocket .send() + // calls for some unknown reason. We treat these as an error and disconnect. + // See https://app.asana.com/0/58926111402292/68021340250410 + try { + this.mySock.send(str); + } catch (e) { + this.log_('Exception thrown from WebSocket.send():', e.message || e.data, 'Closing connection.'); + setTimeout(this.onClosed_.bind(this), 0); + } + }; +} + + diff --git a/src/database/realtime/polling/PacketReceiver.ts b/src/database/realtime/polling/PacketReceiver.ts new file mode 100644 index 00000000000..ab23a83a967 --- /dev/null +++ b/src/database/realtime/polling/PacketReceiver.ts @@ -0,0 +1,58 @@ +import { exceptionGuard } from '../../core/util/util'; + +/** + * This class ensures the packets from the server arrive in order + * This class takes data from the server and ensures it gets passed into the callbacks in order. + * @param onMessage + * @constructor + */ +export class PacketReceiver { + pendingResponses = []; + currentResponseNum = 0; + closeAfterResponse = -1; + onClose = null; + + constructor(private onMessage_: any) { + } + + closeAfter(responseNum, callback) { + this.closeAfterResponse = responseNum; + this.onClose = callback; + if (this.closeAfterResponse < this.currentResponseNum) { + this.onClose(); + this.onClose = null; + } + }; + + /** + * Each message from the server comes with a response number, and an array of data. The responseNumber + * allows us to ensure that we process them in the right order, since we can't be guaranteed that all + * browsers will respond in the same order as the requests we sent + * @param {number} requestNum + * @param {Array} data + */ + handleResponse(requestNum, data) { + this.pendingResponses[requestNum] = data; + while (this.pendingResponses[this.currentResponseNum]) { + const toProcess = this.pendingResponses[this.currentResponseNum]; + delete this.pendingResponses[this.currentResponseNum]; + for (let i = 0; i < toProcess.length; ++i) { + if (toProcess[i]) { + exceptionGuard(() => { + this.onMessage_(toProcess[i]); + }); + } + } + if (this.currentResponseNum === this.closeAfterResponse) { + if (this.onClose) { + clearTimeout(this.onClose); + this.onClose(); + this.onClose = null; + } + break; + } + this.currentResponseNum++; + } + } +} + diff --git a/src/database/third_party/closure-library/LICENSE b/src/database/third_party/closure-library/LICENSE deleted file mode 100644 index 2bb9ad240fa..00000000000 --- a/src/database/third_party/closure-library/LICENSE +++ /dev/null @@ -1,176 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/src/database/third_party/closure-library/closure/goog/a11y/aria/announcer.js b/src/database/third_party/closure-library/closure/goog/a11y/aria/announcer.js deleted file mode 100644 index 5bdfa0c8c10..00000000000 --- a/src/database/third_party/closure-library/closure/goog/a11y/aria/announcer.js +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - - -/** - * @fileoverview Announcer that allows messages to be spoken by assistive - * technologies. - */ - -goog.provide('goog.a11y.aria.Announcer'); - -goog.require('goog.Disposable'); -goog.require('goog.Timer'); -goog.require('goog.a11y.aria'); -goog.require('goog.a11y.aria.LivePriority'); -goog.require('goog.a11y.aria.State'); -goog.require('goog.dom'); -goog.require('goog.object'); - - - -/** - * Class that allows messages to be spoken by assistive technologies that the - * user may have active. - * - * @param {goog.dom.DomHelper=} opt_domHelper DOM helper. - * @constructor - * @extends {goog.Disposable} - * @final - */ -goog.a11y.aria.Announcer = function(opt_domHelper) { - goog.a11y.aria.Announcer.base(this, 'constructor'); - - /** - * @type {goog.dom.DomHelper} - * @private - */ - this.domHelper_ = opt_domHelper || goog.dom.getDomHelper(); - - /** - * Map of priority to live region elements to use for communicating updates. - * Elements are created on demand. - * @type {Object} - * @private - */ - this.liveRegions_ = {}; -}; -goog.inherits(goog.a11y.aria.Announcer, goog.Disposable); - - -/** @override */ -goog.a11y.aria.Announcer.prototype.disposeInternal = function() { - goog.object.forEach( - this.liveRegions_, this.domHelper_.removeNode, this.domHelper_); - this.liveRegions_ = null; - this.domHelper_ = null; - goog.a11y.aria.Announcer.base(this, 'disposeInternal'); -}; - - -/** - * Announce a message to be read by any assistive technologies the user may - * have active. - * @param {string} message The message to announce to screen readers. - * @param {goog.a11y.aria.LivePriority=} opt_priority The priority of the - * message. Defaults to POLITE. - */ -goog.a11y.aria.Announcer.prototype.say = function(message, opt_priority) { - var priority = opt_priority || goog.a11y.aria.LivePriority.POLITE; - var liveRegion = this.getLiveRegion_(priority); - // Resets text content to force a DOM mutation (so that the setTextContent - // post-timeout function will be noticed by the screen reader). This is to - // avoid the problem of when the same message is "said" twice, which doesn't - // trigger a DOM mutation. - goog.dom.setTextContent(liveRegion, ''); - // Uses non-zero timer to make VoiceOver and NVDA work - goog.Timer.callOnce(function() { - goog.dom.setTextContent(liveRegion, message); - }, 1); -}; - - -/** - * Returns an aria-live region that can be used to communicate announcements. - * @param {!goog.a11y.aria.LivePriority} priority The required priority. - * @return {!Element} A live region of the requested priority. - * @private - */ -goog.a11y.aria.Announcer.prototype.getLiveRegion_ = function(priority) { - var liveRegion = this.liveRegions_[priority]; - if (liveRegion) { - // Make sure the live region is not aria-hidden. - goog.a11y.aria.removeState(liveRegion, goog.a11y.aria.State.HIDDEN); - return liveRegion; - } - - liveRegion = this.domHelper_.createElement('div'); - // Note that IE has a habit of declaring things that aren't display:none as - // invisible to third-party tools like JAWs, so we can't just use height:0. - liveRegion.style.position = 'absolute'; - liveRegion.style.top = '-1000px'; - liveRegion.style.height = '1px'; - liveRegion.style.overflow = 'hidden'; - goog.a11y.aria.setState(liveRegion, goog.a11y.aria.State.LIVE, - priority); - goog.a11y.aria.setState(liveRegion, goog.a11y.aria.State.ATOMIC, - 'true'); - this.domHelper_.getDocument().body.appendChild(liveRegion); - this.liveRegions_[priority] = liveRegion; - return liveRegion; -}; diff --git a/src/database/third_party/closure-library/closure/goog/a11y/aria/announcer_test.html b/src/database/third_party/closure-library/closure/goog/a11y/aria/announcer_test.html deleted file mode 100644 index 095fe46f8c7..00000000000 --- a/src/database/third_party/closure-library/closure/goog/a11y/aria/announcer_test.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - Closure Unit Tests - goog.a11y.aria announcer - - - - - -
-
- - diff --git a/src/database/third_party/closure-library/closure/goog/a11y/aria/announcer_test.js b/src/database/third_party/closure-library/closure/goog/a11y/aria/announcer_test.js deleted file mode 100644 index 6062cacb1fd..00000000000 --- a/src/database/third_party/closure-library/closure/goog/a11y/aria/announcer_test.js +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.a11y.aria.AnnouncerTest'); -goog.setTestOnly('goog.a11y.aria.AnnouncerTest'); - -goog.require('goog.a11y.aria'); -goog.require('goog.a11y.aria.Announcer'); -goog.require('goog.a11y.aria.LivePriority'); -goog.require('goog.a11y.aria.State'); -goog.require('goog.array'); -goog.require('goog.dom'); -goog.require('goog.dom.iframe'); -goog.require('goog.testing.MockClock'); -goog.require('goog.testing.jsunit'); - -var sandbox; -var someDiv; -var someSpan; -var mockClock; - -function setUp() { - sandbox = goog.dom.getElement('sandbox'); - someDiv = goog.dom.createDom('div', {id: 'someDiv'}, 'DIV'); - someSpan = goog.dom.createDom('span', {id: 'someSpan'}, 'SPAN'); - sandbox.appendChild(someDiv); - someDiv.appendChild(someSpan); - - mockClock = new goog.testing.MockClock(true); -} - -function tearDown() { - sandbox.innerHTML = ''; - someDiv = null; - someSpan = null; - - goog.dispose(mockClock); -} - -function testAnnouncerAndDispose() { - var text = 'test content'; - var announcer = new goog.a11y.aria.Announcer(goog.dom.getDomHelper()); - announcer.say(text); - checkLiveRegionContains(text, 'polite'); - goog.dispose(announcer); -} - -function testAnnouncerTwice() { - var text = 'test content1'; - var text2 = 'test content2'; - var announcer = new goog.a11y.aria.Announcer(goog.dom.getDomHelper()); - announcer.say(text); - announcer.say(text2); - checkLiveRegionContains(text2, 'polite'); - goog.dispose(announcer); -} - -function testAnnouncerTwiceSameMessage() { - var text = 'test content'; - var announcer = new goog.a11y.aria.Announcer(goog.dom.getDomHelper()); - announcer.say(text); - var firstLiveRegion = getLiveRegion('polite'); - announcer.say(text, undefined); - var secondLiveRegion = getLiveRegion('polite'); - assertEquals(firstLiveRegion, secondLiveRegion); - checkLiveRegionContains(text, 'polite'); - goog.dispose(announcer); -} - -function testAnnouncerAssertive() { - var text = 'test content'; - var announcer = new goog.a11y.aria.Announcer(goog.dom.getDomHelper()); - announcer.say(text, goog.a11y.aria.LivePriority.ASSERTIVE); - checkLiveRegionContains(text, 'assertive'); - goog.dispose(announcer); -} - -function testAnnouncerInIframe() { - var text = 'test content'; - var frame = goog.dom.iframe.createWithContent(sandbox); - var helper = goog.dom.getDomHelper( - goog.dom.getFrameContentDocument(frame).body); - var announcer = new goog.a11y.aria.Announcer(helper); - announcer.say(text, 'polite', helper); - checkLiveRegionContains(text, 'polite', helper); - goog.dispose(announcer); -} - -function testAnnouncerWithAriaHidden() { - var text = 'test content1'; - var text2 = 'test content2'; - var announcer = new goog.a11y.aria.Announcer(goog.dom.getDomHelper()); - announcer.say(text); - // Set aria-hidden attribute on the live region (simulates a modal dialog - // being opened). - var liveRegion = getLiveRegion('polite'); - goog.a11y.aria.setState(liveRegion, goog.a11y.aria.State.HIDDEN, true); - - // Announce a new message and make sure that the aria-hidden was removed. - announcer.say(text2); - checkLiveRegionContains(text2, 'polite'); - assertEquals('', - goog.a11y.aria.getState(liveRegion, goog.a11y.aria.State.HIDDEN)); - goog.dispose(announcer); -} - -function getLiveRegion(priority, opt_domHelper) { - var dom = opt_domHelper || goog.dom.getDomHelper(); - var divs = dom.getElementsByTagNameAndClass('div', null); - var liveRegions = []; - goog.array.forEach(divs, function(div) { - if (goog.a11y.aria.getState(div, 'live') == priority) { - liveRegions.push(div); - } - }); - assertEquals(1, liveRegions.length); - return liveRegions[0]; -} - -function checkLiveRegionContains(text, priority, opt_domHelper) { - var liveRegion = getLiveRegion(priority, opt_domHelper); - mockClock.tick(1); - assertEquals(text, goog.dom.getTextContent(liveRegion)); -} diff --git a/src/database/third_party/closure-library/closure/goog/a11y/aria/aria.js b/src/database/third_party/closure-library/closure/goog/a11y/aria/aria.js deleted file mode 100644 index 1220d238285..00000000000 --- a/src/database/third_party/closure-library/closure/goog/a11y/aria/aria.js +++ /dev/null @@ -1,386 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - - -/** - * @fileoverview Utilities for adding, removing and setting ARIA roles and - * states as defined by W3C ARIA standard: http://www.w3.org/TR/wai-aria/ - * All modern browsers have some form of ARIA support, so no browser checks are - * performed when adding ARIA to components. - * - */ - -goog.provide('goog.a11y.aria'); - -goog.require('goog.a11y.aria.Role'); -goog.require('goog.a11y.aria.State'); -goog.require('goog.a11y.aria.datatables'); -goog.require('goog.array'); -goog.require('goog.asserts'); -goog.require('goog.dom'); -goog.require('goog.dom.TagName'); -goog.require('goog.object'); -goog.require('goog.string'); - - -/** - * ARIA states/properties prefix. - * @private - */ -goog.a11y.aria.ARIA_PREFIX_ = 'aria-'; - - -/** - * ARIA role attribute. - * @private - */ -goog.a11y.aria.ROLE_ATTRIBUTE_ = 'role'; - - -/** - * A list of tag names for which we don't need to set ARIA role and states - * because they have well supported semantics for screen readers or because - * they don't contain content to be made accessible. - * @private - */ -goog.a11y.aria.TAGS_WITH_ASSUMED_ROLES_ = [ - goog.dom.TagName.A, - goog.dom.TagName.AREA, - goog.dom.TagName.BUTTON, - goog.dom.TagName.HEAD, - goog.dom.TagName.INPUT, - goog.dom.TagName.LINK, - goog.dom.TagName.MENU, - goog.dom.TagName.META, - goog.dom.TagName.OPTGROUP, - goog.dom.TagName.OPTION, - goog.dom.TagName.PROGRESS, - goog.dom.TagName.STYLE, - goog.dom.TagName.SELECT, - goog.dom.TagName.SOURCE, - goog.dom.TagName.TEXTAREA, - goog.dom.TagName.TITLE, - goog.dom.TagName.TRACK -]; - - -/** - * Sets the role of an element. If the roleName is - * empty string or null, the role for the element is removed. - * We encourage clients to call the goog.a11y.aria.removeRole - * method instead of setting null and empty string values. - * Special handling for this case is added to ensure - * backword compatibility with existing code. - * - * @param {!Element} element DOM node to set role of. - * @param {!goog.a11y.aria.Role|string} roleName role name(s). - */ -goog.a11y.aria.setRole = function(element, roleName) { - if (!roleName) { - // Setting the ARIA role to empty string is not allowed - // by the ARIA standard. - goog.a11y.aria.removeRole(element); - } else { - if (goog.asserts.ENABLE_ASSERTS) { - goog.asserts.assert(goog.object.containsValue( - goog.a11y.aria.Role, roleName), 'No such ARIA role ' + roleName); - } - element.setAttribute(goog.a11y.aria.ROLE_ATTRIBUTE_, roleName); - } -}; - - -/** - * Gets role of an element. - * @param {!Element} element DOM element to get role of. - * @return {goog.a11y.aria.Role} ARIA Role name. - */ -goog.a11y.aria.getRole = function(element) { - var role = element.getAttribute(goog.a11y.aria.ROLE_ATTRIBUTE_); - return /** @type {goog.a11y.aria.Role} */ (role) || null; -}; - - -/** - * Removes role of an element. - * @param {!Element} element DOM element to remove the role from. - */ -goog.a11y.aria.removeRole = function(element) { - element.removeAttribute(goog.a11y.aria.ROLE_ATTRIBUTE_); -}; - - -/** - * Sets the state or property of an element. - * @param {!Element} element DOM node where we set state. - * @param {!(goog.a11y.aria.State|string)} stateName State attribute being set. - * Automatically adds prefix 'aria-' to the state name if the attribute is - * not an extra attribute. - * @param {string|boolean|number|!Array} value Value - * for the state attribute. - */ -goog.a11y.aria.setState = function(element, stateName, value) { - if (goog.isArray(value)) { - value = value.join(' '); - } - var attrStateName = goog.a11y.aria.getAriaAttributeName_(stateName); - if (value === '' || value == undefined) { - var defaultValueMap = goog.a11y.aria.datatables.getDefaultValuesMap(); - // Work around for browsers that don't properly support ARIA. - // According to the ARIA W3C standard, user agents should allow - // setting empty value which results in setting the default value - // for the ARIA state if such exists. The exact text from the ARIA W3C - // standard (http://www.w3.org/TR/wai-aria/states_and_properties): - // "When a value is indicated as the default, the user agent - // MUST follow the behavior prescribed by this value when the state or - // property is empty or undefined." - // The defaultValueMap contains the default values for the ARIA states - // and has as a key the goog.a11y.aria.State constant for the state. - if (stateName in defaultValueMap) { - element.setAttribute(attrStateName, defaultValueMap[stateName]); - } else { - element.removeAttribute(attrStateName); - } - } else { - element.setAttribute(attrStateName, value); - } -}; - - -/** - * Toggles the ARIA attribute of an element. - * Meant for attributes with a true/false value, but works with any attribute. - * If the attribute does not have a true/false value, the following rules apply: - * A not empty attribute will be removed. - * An empty attribute will be set to true. - * @param {!Element} el DOM node for which to set attribute. - * @param {!(goog.a11y.aria.State|string)} attr ARIA attribute being set. - * Automatically adds prefix 'aria-' to the attribute name if the attribute - * is not an extra attribute. - */ -goog.a11y.aria.toggleState = function(el, attr) { - var val = goog.a11y.aria.getState(el, attr); - if (!goog.string.isEmptyOrWhitespace(goog.string.makeSafe(val)) && - !(val == 'true' || val == 'false')) { - goog.a11y.aria.removeState(el, /** @type {!goog.a11y.aria.State} */ (attr)); - return; - } - goog.a11y.aria.setState(el, attr, val == 'true' ? 'false' : 'true'); -}; - - -/** - * Remove the state or property for the element. - * @param {!Element} element DOM node where we set state. - * @param {!goog.a11y.aria.State} stateName State name. - */ -goog.a11y.aria.removeState = function(element, stateName) { - element.removeAttribute(goog.a11y.aria.getAriaAttributeName_(stateName)); -}; - - -/** - * Gets value of specified state or property. - * @param {!Element} element DOM node to get state from. - * @param {!goog.a11y.aria.State|string} stateName State name. - * @return {string} Value of the state attribute. - */ -goog.a11y.aria.getState = function(element, stateName) { - // TODO(user): return properly typed value result -- - // boolean, number, string, null. We should be able to chain - // getState(...) and setState(...) methods. - - var attr = - /** @type {string|number|boolean} */ (element.getAttribute( - goog.a11y.aria.getAriaAttributeName_(stateName))); - var isNullOrUndefined = attr == null || attr == undefined; - return isNullOrUndefined ? '' : String(attr); -}; - - -/** - * Returns the activedescendant element for the input element by - * using the activedescendant ARIA property of the given element. - * @param {!Element} element DOM node to get activedescendant - * element for. - * @return {?Element} DOM node of the activedescendant, if found. - */ -goog.a11y.aria.getActiveDescendant = function(element) { - var id = goog.a11y.aria.getState( - element, goog.a11y.aria.State.ACTIVEDESCENDANT); - return goog.dom.getOwnerDocument(element).getElementById(id); -}; - - -/** - * Sets the activedescendant ARIA property value for an element. - * If the activeElement is not null, it should have an id set. - * @param {!Element} element DOM node to set activedescendant ARIA property to. - * @param {?Element} activeElement DOM node being set as activedescendant. - */ -goog.a11y.aria.setActiveDescendant = function(element, activeElement) { - var id = ''; - if (activeElement) { - id = activeElement.id; - goog.asserts.assert(id, 'The active element should have an id.'); - } - - goog.a11y.aria.setState(element, goog.a11y.aria.State.ACTIVEDESCENDANT, id); -}; - - -/** - * Gets the label of the given element. - * @param {!Element} element DOM node to get label from. - * @return {string} label The label. - */ -goog.a11y.aria.getLabel = function(element) { - return goog.a11y.aria.getState(element, goog.a11y.aria.State.LABEL); -}; - - -/** - * Sets the label of the given element. - * @param {!Element} element DOM node to set label to. - * @param {string} label The label to set. - */ -goog.a11y.aria.setLabel = function(element, label) { - goog.a11y.aria.setState(element, goog.a11y.aria.State.LABEL, label); -}; - - -/** - * Asserts that the element has a role set if it's not an HTML element whose - * semantics is well supported by most screen readers. - * Only to be used internally by the ARIA library in goog.a11y.aria.*. - * @param {!Element} element The element to assert an ARIA role set. - * @param {!goog.array.ArrayLike} allowedRoles The child roles of - * the roles. - */ -goog.a11y.aria.assertRoleIsSetInternalUtil = function(element, allowedRoles) { - if (goog.array.contains(goog.a11y.aria.TAGS_WITH_ASSUMED_ROLES_, - element.tagName)) { - return; - } - var elementRole = /** @type {string}*/ (goog.a11y.aria.getRole(element)); - goog.asserts.assert(elementRole != null, - 'The element ARIA role cannot be null.'); - - goog.asserts.assert(goog.array.contains(allowedRoles, elementRole), - 'Non existing or incorrect role set for element.' + - 'The role set is "' + elementRole + - '". The role should be any of "' + allowedRoles + - '". Check the ARIA specification for more details ' + - 'http://www.w3.org/TR/wai-aria/roles.'); -}; - - -/** - * Gets the boolean value of an ARIA state/property. - * @param {!Element} element The element to get the ARIA state for. - * @param {!goog.a11y.aria.State|string} stateName the ARIA state name. - * @return {?boolean} Boolean value for the ARIA state value or null if - * the state value is not 'true', not 'false', or not set. - */ -goog.a11y.aria.getStateBoolean = function(element, stateName) { - var attr = - /** @type {string|boolean} */ (element.getAttribute( - goog.a11y.aria.getAriaAttributeName_(stateName))); - goog.asserts.assert( - goog.isBoolean(attr) || attr == null || attr == 'true' || - attr == 'false'); - if (attr == null) { - return attr; - } - return goog.isBoolean(attr) ? attr : attr == 'true'; -}; - - -/** - * Gets the number value of an ARIA state/property. - * @param {!Element} element The element to get the ARIA state for. - * @param {!goog.a11y.aria.State|string} stateName the ARIA state name. - * @return {?number} Number value for the ARIA state value or null if - * the state value is not a number or not set. - */ -goog.a11y.aria.getStateNumber = function(element, stateName) { - var attr = - /** @type {string|number} */ (element.getAttribute( - goog.a11y.aria.getAriaAttributeName_(stateName))); - goog.asserts.assert((attr == null || !isNaN(Number(attr))) && - !goog.isBoolean(attr)); - return attr == null ? null : Number(attr); -}; - - -/** - * Gets the string value of an ARIA state/property. - * @param {!Element} element The element to get the ARIA state for. - * @param {!goog.a11y.aria.State|string} stateName the ARIA state name. - * @return {?string} String value for the ARIA state value or null if - * the state value is empty string or not set. - */ -goog.a11y.aria.getStateString = function(element, stateName) { - var attr = element.getAttribute( - goog.a11y.aria.getAriaAttributeName_(stateName)); - goog.asserts.assert((attr == null || goog.isString(attr)) && - isNaN(Number(attr)) && attr != 'true' && attr != 'false'); - return attr == null ? null : attr; -}; - - -/** - * Gets array of strings value of the specified state or - * property for the element. - * Only to be used internally by the ARIA library in goog.a11y.aria.*. - * @param {!Element} element DOM node to get state from. - * @param {!goog.a11y.aria.State} stateName State name. - * @return {!goog.array.ArrayLike} string Array - * value of the state attribute. - */ -goog.a11y.aria.getStringArrayStateInternalUtil = function(element, stateName) { - var attrValue = element.getAttribute( - goog.a11y.aria.getAriaAttributeName_(stateName)); - return goog.a11y.aria.splitStringOnWhitespace_(attrValue); -}; - - -/** - * Splits the input stringValue on whitespace. - * @param {string} stringValue The value of the string to split. - * @return {!goog.array.ArrayLike} string Array - * value as result of the split. - * @private - */ -goog.a11y.aria.splitStringOnWhitespace_ = function(stringValue) { - return stringValue ? stringValue.split(/\s+/) : []; -}; - - -/** - * Adds the 'aria-' prefix to ariaName. - * @param {string} ariaName ARIA state/property name. - * @private - * @return {string} The ARIA attribute name with added 'aria-' prefix. - * @throws {Error} If no such attribute exists. - */ -goog.a11y.aria.getAriaAttributeName_ = function(ariaName) { - if (goog.asserts.ENABLE_ASSERTS) { - goog.asserts.assert(ariaName, 'ARIA attribute cannot be empty.'); - goog.asserts.assert(goog.object.containsValue( - goog.a11y.aria.State, ariaName), - 'No such ARIA attribute ' + ariaName); - } - return goog.a11y.aria.ARIA_PREFIX_ + ariaName; -}; diff --git a/src/database/third_party/closure-library/closure/goog/a11y/aria/aria_test.html b/src/database/third_party/closure-library/closure/goog/a11y/aria/aria_test.html deleted file mode 100644 index d8e6286ad9c..00000000000 --- a/src/database/third_party/closure-library/closure/goog/a11y/aria/aria_test.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - Closure Unit Tests - goog.a11y.aria - - - - - -
-
- - diff --git a/src/database/third_party/closure-library/closure/goog/a11y/aria/aria_test.js b/src/database/third_party/closure-library/closure/goog/a11y/aria/aria_test.js deleted file mode 100644 index c208aa147e1..00000000000 --- a/src/database/third_party/closure-library/closure/goog/a11y/aria/aria_test.js +++ /dev/null @@ -1,269 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License.goog.provide('goog.a11y.ariaTest'); - -goog.provide('goog.a11y.ariaTest'); -goog.setTestOnly('goog.a11y.ariaTest'); - -goog.require('goog.a11y.aria'); -goog.require('goog.a11y.aria.Role'); -goog.require('goog.a11y.aria.State'); -goog.require('goog.dom'); -goog.require('goog.dom.TagName'); -goog.require('goog.testing.jsunit'); - -var aria = goog.a11y.aria; -var Role = goog.a11y.aria.Role; -var State = goog.a11y.aria.State; -var sandbox; -var someDiv; -var someSpan; -var htmlButton; - -function setUp() { - sandbox = goog.dom.getElement('sandbox'); - someDiv = goog.dom.createDom( - goog.dom.TagName.DIV, {id: 'someDiv'}, 'DIV'); - someSpan = goog.dom.createDom( - goog.dom.TagName.SPAN, {id: 'someSpan'}, 'SPAN'); - htmlButton = goog.dom.createDom( - goog.dom.TagName.BUTTON, {id: 'someButton'}, 'BUTTON'); - goog.dom.appendChild(sandbox, someDiv); - goog.dom.appendChild(someDiv, someSpan); -} - -function tearDown() { - goog.dom.removeChildren(sandbox); - someDiv = null; - someSpan = null; - htmlButton = null; -} - -function testGetSetRole() { - assertNull('someDiv\'s role should be null', aria.getRole(someDiv)); - assertNull('someSpan\'s role should be null', aria.getRole(someSpan)); - - aria.setRole(someDiv, Role.MENU); - aria.setRole(someSpan, Role.MENU_ITEM); - - assertEquals('someDiv\'s role should be MENU', - Role.MENU, aria.getRole(someDiv)); - assertEquals('someSpan\'s role should be MENU_ITEM', - Role.MENU_ITEM, aria.getRole(someSpan)); - - var div = goog.dom.createElement(goog.dom.TagName.DIV); - goog.dom.appendChild(sandbox, div); - goog.dom.appendChild(div, goog.dom.createDom(goog.dom.TagName.SPAN, - {id: 'anotherSpan', role: Role.CHECKBOX})); - assertEquals('anotherSpan\'s role should be CHECKBOX', - Role.CHECKBOX, aria.getRole(goog.dom.getElement('anotherSpan'))); -} - -function testGetSetToggleState() { - assertThrows('Should throw because no state is specified.', - function() { - aria.getState(someDiv); - }); - assertThrows('Should throw because no state is specified.', - function() { - aria.getState(someDiv); - }); - aria.setState(someDiv, State.LABELLEDBY, 'someSpan'); - - assertEquals('someDiv\'s labelledby state should be "someSpan"', - 'someSpan', aria.getState(someDiv, State.LABELLEDBY)); - - // Test setting for aria-activedescendant with empty value. - assertFalse(someDiv.hasAttribute ? - someDiv.hasAttribute('aria-activedescendant') : - !!someDiv.getAttribute('aria-activedescendant')); - aria.setState(someDiv, State.ACTIVEDESCENDANT, 'someSpan'); - assertEquals('someSpan', aria.getState(someDiv, State.ACTIVEDESCENDANT)); - aria.setState(someDiv, State.ACTIVEDESCENDANT, ''); - assertFalse(someDiv.hasAttribute ? - someDiv.hasAttribute('aria-activedescendant') : - !!someDiv.getAttribute('aria-activedescendant')); - - // Test setting state that has a default value to empty value. - assertFalse(someDiv.hasAttribute ? - someDiv.hasAttribute('aria-relevant') : - !!someDiv.getAttribute('aria-relevant')); - aria.setState(someDiv, State.RELEVANT, aria.RelevantValues.TEXT); - assertEquals( - aria.RelevantValues.TEXT, aria.getState(someDiv, State.RELEVANT)); - aria.setState(someDiv, State.RELEVANT, ''); - assertEquals( - aria.RelevantValues.ADDITIONS + ' ' + aria.RelevantValues.TEXT, - aria.getState(someDiv, State.RELEVANT)); - - // Test toggling an attribute that has a true/false value. - aria.setState(someDiv, State.EXPANDED, false); - assertEquals('false', aria.getState(someDiv, State.EXPANDED)); - aria.toggleState(someDiv, State.EXPANDED); - assertEquals('true', aria.getState(someDiv, State.EXPANDED)); - aria.setState(someDiv, State.EXPANDED, true); - assertEquals('true', aria.getState(someDiv, State.EXPANDED)); - aria.toggleState(someDiv, State.EXPANDED); - assertEquals('false', aria.getState(someDiv, State.EXPANDED)); - - // Test toggling an attribute that does not have a true/false value. - aria.setState(someDiv, State.RELEVANT, aria.RelevantValues.TEXT); - assertEquals( - aria.RelevantValues.TEXT, aria.getState(someDiv, State.RELEVANT)); - aria.toggleState(someDiv, State.RELEVANT); - assertEquals('', aria.getState(someDiv, State.RELEVANT)); - aria.removeState(someDiv, State.RELEVANT); - assertEquals('', aria.getState(someDiv, State.RELEVANT)); - // This is not a valid value, but this is what happens if toggle is misused. - aria.toggleState(someDiv, State.RELEVANT); - assertEquals('true', aria.getState(someDiv, State.RELEVANT)); -} - -function testGetStateString() { - aria.setState(someDiv, State.LABEL, 'test_label'); - aria.setState( - someSpan, State.LABEL, aria.getStateString(someDiv, State.LABEL)); - assertEquals(aria.getState(someDiv, State.LABEL), - aria.getState(someSpan, State.LABEL)); - assertEquals('The someDiv\'s enum value should be "test_label".', - 'test_label', aria.getState(someDiv, State.LABEL)); - assertEquals('The someSpan\'s enum value should be "copy move".', - 'test_label', aria.getStateString(someSpan, State.LABEL)); - aria.setState(someDiv, State.MULTILINE, true); - var thrown = false; - try { - aria.getStateString(someDiv, State.MULTILINE); - } catch (e) { - thrown = true; - } - assertTrue('invalid use of getStateString on boolean.', thrown); - aria.setState(someDiv, State.LIVE, aria.LivePriority.ASSERTIVE); - thrown = false; - aria.setState(someDiv, State.LEVEL, 1); - try { - aria.getStateString(someDiv, State.LEVEL); - } catch (e) { - thrown = true; - } - assertTrue('invalid use of getStateString on numbers.', thrown); -} - - -function testGetStateStringArray() { - aria.setState(someDiv, State.LABELLEDBY, ['1', '2']); - aria.setState(someSpan, State.LABELLEDBY, - aria.getStringArrayStateInternalUtil(someDiv, State.LABELLEDBY)); - assertEquals(aria.getState(someDiv, State.LABELLEDBY), - aria.getState(someSpan, State.LABELLEDBY)); - - assertEquals('The someDiv\'s enum value should be "1 2".', '1 2', - aria.getState(someDiv, State.LABELLEDBY)); - assertEquals('The someSpan\'s enum value should be "1 2".', '1 2', - aria.getState(someSpan, State.LABELLEDBY)); - - assertSameElements('The someDiv\'s enum value should be "1 2".', - ['1', '2'], - aria.getStringArrayStateInternalUtil(someDiv, State.LABELLEDBY)); - assertSameElements('The someSpan\'s enum value should be "1 2".', - ['1', '2'], - aria.getStringArrayStateInternalUtil(someSpan, State.LABELLEDBY)); -} - - -function testGetStateNumber() { - aria.setState(someDiv, State.LEVEL, 1); - aria.setState( - someSpan, State.LEVEL, aria.getStateNumber(someDiv, State.LEVEL)); - assertEquals(aria.getState(someDiv, State.LEVEL), - aria.getState(someSpan, State.LEVEL)); - assertEquals('The someDiv\'s enum value should be "1".', '1', - aria.getState(someDiv, State.LEVEL)); - assertEquals('The someSpan\'s enum value should be "1".', '1', - aria.getState(someSpan, State.LEVEL)); - assertEquals('The someDiv\'s enum value should be "1".', 1, - aria.getStateNumber(someDiv, State.LEVEL)); - assertEquals('The someSpan\'s enum value should be "1".', 1, - aria.getStateNumber(someSpan, State.LEVEL)); - aria.setState(someDiv, State.MULTILINE, true); - var thrown = false; - try { - aria.getStateNumber(someDiv, State.MULTILINE); - } catch (e) { - thrown = true; - } - assertTrue('invalid use of getStateNumber on boolean.', thrown); - aria.setState(someDiv, State.LIVE, aria.LivePriority.ASSERTIVE); - thrown = false; - try { - aria.getStateBoolean(someDiv, State.LIVE); - } catch (e) { - thrown = true; - } - assertTrue('invalid use of getStateNumber on strings.', thrown); -} - -function testGetStateBoolean() { - assertNull(aria.getStateBoolean(someDiv, State.MULTILINE)); - - aria.setState(someDiv, State.MULTILINE, false); - assertFalse(aria.getStateBoolean(someDiv, State.MULTILINE)); - - aria.setState(someDiv, State.MULTILINE, true); - aria.setState(someSpan, State.MULTILINE, - aria.getStateBoolean(someDiv, State.MULTILINE)); - assertEquals(aria.getState(someDiv, State.MULTILINE), - aria.getState(someSpan, State.MULTILINE)); - assertEquals('The someDiv\'s enum value should be "true".', 'true', - aria.getState(someDiv, State.MULTILINE)); - assertEquals('The someSpan\'s enum value should be "true".', 'true', - aria.getState(someSpan, State.MULTILINE)); - assertEquals('The someDiv\'s enum value should be "true".', true, - aria.getStateBoolean(someDiv, State.MULTILINE)); - assertEquals('The someSpan\'s enum value should be "true".', true, - aria.getStateBoolean(someSpan, State.MULTILINE)); - aria.setState(someDiv, State.LEVEL, 1); - var thrown = false; - try { - aria.getStateBoolean(someDiv, State.LEVEL); - } catch (e) { - thrown = true; - } - assertTrue('invalid use of getStateBoolean on numbers.', thrown); - aria.setState(someDiv, State.LIVE, aria.LivePriority.ASSERTIVE); - thrown = false; - try { - aria.getStateBoolean(someDiv, State.LIVE); - } catch (e) { - thrown = true; - } - assertTrue('invalid use of getStateBoolean on strings.', thrown); -} - -function testGetSetActiveDescendant() { - aria.setActiveDescendant(someDiv, null); - assertNull('someDiv\'s activedescendant should be null', - aria.getActiveDescendant(someDiv)); - - aria.setActiveDescendant(someDiv, someSpan); - - assertEquals('someDiv\'s active descendant should be "someSpan"', - someSpan, aria.getActiveDescendant(someDiv)); -} - -function testGetSetLabel() { - assertEquals('someDiv\'s label should be ""', '', aria.getLabel(someDiv)); - - aria.setLabel(someDiv, 'somelabel'); - assertEquals('someDiv\'s label should be "somelabel"', 'somelabel', - aria.getLabel(someDiv)); -} diff --git a/src/database/third_party/closure-library/closure/goog/a11y/aria/attributes.js b/src/database/third_party/closure-library/closure/goog/a11y/aria/attributes.js deleted file mode 100644 index f4e0a3d0746..00000000000 --- a/src/database/third_party/closure-library/closure/goog/a11y/aria/attributes.js +++ /dev/null @@ -1,389 +0,0 @@ -// Copyright 2013 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - - -/** - * @fileoverview The file contains generated enumerations for ARIA states - * and properties as defined by W3C ARIA standard: - * http://www.w3.org/TR/wai-aria/. - * - * This is auto-generated code. Do not manually edit! For more details - * about how to edit it via the generator check go/closure-ariagen. - */ - -goog.provide('goog.a11y.aria.AutoCompleteValues'); -goog.provide('goog.a11y.aria.CheckedValues'); -goog.provide('goog.a11y.aria.DropEffectValues'); -goog.provide('goog.a11y.aria.ExpandedValues'); -goog.provide('goog.a11y.aria.GrabbedValues'); -goog.provide('goog.a11y.aria.InvalidValues'); -goog.provide('goog.a11y.aria.LivePriority'); -goog.provide('goog.a11y.aria.OrientationValues'); -goog.provide('goog.a11y.aria.PressedValues'); -goog.provide('goog.a11y.aria.RelevantValues'); -goog.provide('goog.a11y.aria.SelectedValues'); -goog.provide('goog.a11y.aria.SortValues'); -goog.provide('goog.a11y.aria.State'); - - -/** - * ARIA states and properties. - * @enum {string} - */ -goog.a11y.aria.State = { - // ARIA property for setting the currently active descendant of an element, - // for example the selected item in a list box. Value: ID of an element. - ACTIVEDESCENDANT: 'activedescendant', - - // ARIA property that, if true, indicates that all of a changed region should - // be presented, instead of only parts. Value: one of {true, false}. - ATOMIC: 'atomic', - - // ARIA property to specify that input completion is provided. Value: - // one of {'inline', 'list', 'both', 'none'}. - AUTOCOMPLETE: 'autocomplete', - - // ARIA state to indicate that an element and its subtree are being updated. - // Value: one of {true, false}. - BUSY: 'busy', - - // ARIA state for a checked item. Value: one of {'true', 'false', 'mixed', - // undefined}. - CHECKED: 'checked', - - // ARIA property that identifies the element or elements whose contents or - // presence are controlled by this element. - // Value: space-separated IDs of other elements. - CONTROLS: 'controls', - - // ARIA property that identifies the element or elements that describe - // this element. Value: space-separated IDs of other elements. - DESCRIBEDBY: 'describedby', - - // ARIA state for a disabled item. Value: one of {true, false}. - DISABLED: 'disabled', - - // ARIA property that indicates what functions can be performed when a - // dragged object is released on the drop target. Value: one of - // {'copy', 'move', 'link', 'execute', 'popup', 'none'}. - DROPEFFECT: 'dropeffect', - - // ARIA state for setting whether the element like a tree node is expanded. - // Value: one of {true, false, undefined}. - EXPANDED: 'expanded', - - // ARIA property that identifies the next element (or elements) in the - // recommended reading order of content. Value: space-separated ids of - // elements to flow to. - FLOWTO: 'flowto', - - // ARIA state that indicates an element's "grabbed" state in drag-and-drop. - // Value: one of {true, false, undefined}. - GRABBED: 'grabbed', - - // ARIA property indicating whether the element has a popup. - // Value: one of {true, false}. - HASPOPUP: 'haspopup', - - // ARIA state indicating that the element is not visible or perceivable - // to any user. Value: one of {true, false}. - HIDDEN: 'hidden', - - // ARIA state indicating that the entered value does not conform. Value: - // one of {false, true, 'grammar', 'spelling'} - INVALID: 'invalid', - - // ARIA property that provides a label to override any other text, value, or - // contents used to describe this element. Value: string. - LABEL: 'label', - - // ARIA property for setting the element which labels another element. - // Value: space-separated IDs of elements. - LABELLEDBY: 'labelledby', - - // ARIA property for setting the level of an element in the hierarchy. - // Value: integer. - LEVEL: 'level', - - // ARIA property indicating that an element will be updated, and - // describes the types of updates the user agents, assistive technologies, - // and user can expect from the live region. Value: one of {'off', 'polite', - // 'assertive'}. - LIVE: 'live', - - // ARIA property indicating whether a text box can accept multiline input. - // Value: one of {true, false}. - MULTILINE: 'multiline', - - // ARIA property indicating if the user may select more than one item. - // Value: one of {true, false}. - MULTISELECTABLE: 'multiselectable', - - // ARIA property indicating if the element is horizontal or vertical. - // Value: one of {'vertical', 'horizontal'}. - ORIENTATION: 'orientation', - - // ARIA property creating a visual, functional, or contextual parent/child - // relationship when the DOM hierarchy can't be used to represent it. - // Value: Space-separated IDs of elements. - OWNS: 'owns', - - // ARIA property that defines an element's number of position in a list. - // Value: integer. - POSINSET: 'posinset', - - // ARIA state for a pressed item. - // Value: one of {true, false, undefined, 'mixed'}. - PRESSED: 'pressed', - - // ARIA property indicating that an element is not editable. - // Value: one of {true, false}. - READONLY: 'readonly', - - // ARIA property indicating that change notifications within this subtree - // of a live region should be announced. Value: one of {'additions', - // 'removals', 'text', 'all', 'additions text'}. - RELEVANT: 'relevant', - - // ARIA property indicating that user input is required on this element - // before a form may be submitted. Value: one of {true, false}. - REQUIRED: 'required', - - // ARIA state for setting the currently selected item in the list. - // Value: one of {true, false, undefined}. - SELECTED: 'selected', - - // ARIA property defining the number of items in a list. Value: integer. - SETSIZE: 'setsize', - - // ARIA property indicating if items are sorted. Value: one of {'ascending', - // 'descending', 'none', 'other'}. - SORT: 'sort', - - // ARIA property for slider maximum value. Value: number. - VALUEMAX: 'valuemax', - - // ARIA property for slider minimum value. Value: number. - VALUEMIN: 'valuemin', - - // ARIA property for slider active value. Value: number. - VALUENOW: 'valuenow', - - // ARIA property for slider active value represented as text. - // Value: string. - VALUETEXT: 'valuetext' -}; - - -/** - * ARIA state values for AutoCompleteValues. - * @enum {string} - */ -goog.a11y.aria.AutoCompleteValues = { - // The system provides text after the caret as a suggestion - // for how to complete the field. - INLINE: 'inline', - // A list of choices appears from which the user can choose, - // but the edit box retains focus. - LIST: 'list', - // A list of choices appears and the currently selected suggestion - // also appears inline. - BOTH: 'both', - // No input completion suggestions are provided. - NONE: 'none' -}; - - -/** - * ARIA state values for DropEffectValues. - * @enum {string} - */ -goog.a11y.aria.DropEffectValues = { - // A duplicate of the source object will be dropped into the target. - COPY: 'copy', - // The source object will be removed from its current location - // and dropped into the target. - MOVE: 'move', - // A reference or shortcut to the dragged object - // will be created in the target object. - LINK: 'link', - // A function supported by the drop target is - // executed, using the drag source as an input. - EXECUTE: 'execute', - // There is a popup menu or dialog that allows the user to choose - // one of the drag operations (copy, move, link, execute) and any other - // drag functionality, such as cancel. - POPUP: 'popup', - // No operation can be performed; effectively - // cancels the drag operation if an attempt is made to drop on this object. - NONE: 'none' -}; - - -/** - * ARIA state values for LivePriority. - * @enum {string} - */ -goog.a11y.aria.LivePriority = { - // Updates to the region will not be presented to the user - // unless the assitive technology is currently focused on that region. - OFF: 'off', - // (Background change) Assistive technologies SHOULD announce - // updates at the next graceful opportunity, such as at the end of - // speaking the current sentence or when the user pauses typing. - POLITE: 'polite', - // This information has the highest priority and assistive - // technologies SHOULD notify the user immediately. - // Because an interruption may disorient users or cause them to not complete - // their current task, authors SHOULD NOT use the assertive value unless the - // interruption is imperative. - ASSERTIVE: 'assertive' -}; - - -/** - * ARIA state values for OrientationValues. - * @enum {string} - */ -goog.a11y.aria.OrientationValues = { - // The element is oriented vertically. - VERTICAL: 'vertical', - // The element is oriented horizontally. - HORIZONTAL: 'horizontal' -}; - - -/** - * ARIA state values for RelevantValues. - * @enum {string} - */ -goog.a11y.aria.RelevantValues = { - // Element nodes are added to the DOM within the live region. - ADDITIONS: 'additions', - // Text or element nodes within the live region are removed from the DOM. - REMOVALS: 'removals', - // Text is added to any DOM descendant nodes of the live region. - TEXT: 'text', - // Equivalent to the combination of all values, "additions removals text". - ALL: 'all' -}; - - -/** - * ARIA state values for SortValues. - * @enum {string} - */ -goog.a11y.aria.SortValues = { - // Items are sorted in ascending order by this column. - ASCENDING: 'ascending', - // Items are sorted in descending order by this column. - DESCENDING: 'descending', - // There is no defined sort applied to the column. - NONE: 'none', - // A sort algorithm other than ascending or descending has been applied. - OTHER: 'other' -}; - - -/** - * ARIA state values for CheckedValues. - * @enum {string} - */ -goog.a11y.aria.CheckedValues = { - // The selectable element is checked. - TRUE: 'true', - // The selectable element is not checked. - FALSE: 'false', - // Indicates a mixed mode value for a tri-state - // checkbox or menuitemcheckbox. - MIXED: 'mixed', - // The element does not support being checked. - UNDEFINED: 'undefined' -}; - - -/** - * ARIA state values for ExpandedValues. - * @enum {string} - */ -goog.a11y.aria.ExpandedValues = { - // The element, or another grouping element it controls, is expanded. - TRUE: 'true', - // The element, or another grouping element it controls, is collapsed. - FALSE: 'false', - // The element, or another grouping element - // it controls, is neither expandable nor collapsible; all its - // child elements are shown or there are no child elements. - UNDEFINED: 'undefined' -}; - - -/** - * ARIA state values for GrabbedValues. - * @enum {string} - */ -goog.a11y.aria.GrabbedValues = { - // Indicates that the element has been "grabbed" for dragging. - TRUE: 'true', - // Indicates that the element supports being dragged. - FALSE: 'false', - // Indicates that the element does not support being dragged. - UNDEFINED: 'undefined' -}; - - -/** - * ARIA state values for InvalidValues. - * @enum {string} - */ -goog.a11y.aria.InvalidValues = { - // There are no detected errors in the value. - FALSE: 'false', - // The value entered by the user has failed validation. - TRUE: 'true', - // A grammatical error was detected. - GRAMMAR: 'grammar', - // A spelling error was detected. - SPELLING: 'spelling' -}; - - -/** - * ARIA state values for PressedValues. - * @enum {string} - */ -goog.a11y.aria.PressedValues = { - // The element is pressed. - TRUE: 'true', - // The element supports being pressed but is not currently pressed. - FALSE: 'false', - // Indicates a mixed mode value for a tri-state toggle button. - MIXED: 'mixed', - // The element does not support being pressed. - UNDEFINED: 'undefined' -}; - - -/** - * ARIA state values for SelectedValues. - * @enum {string} - */ -goog.a11y.aria.SelectedValues = { - // The selectable element is selected. - TRUE: 'true', - // The selectable element is not selected. - FALSE: 'false', - // The element is not selectable. - UNDEFINED: 'undefined' -}; diff --git a/src/database/third_party/closure-library/closure/goog/a11y/aria/datatables.js b/src/database/third_party/closure-library/closure/goog/a11y/aria/datatables.js deleted file mode 100644 index f1ba566df8b..00000000000 --- a/src/database/third_party/closure-library/closure/goog/a11y/aria/datatables.js +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2013 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - - - -/** - * @fileoverview The file contains data tables generated from the ARIA - * standard schema http://www.w3.org/TR/wai-aria/. - * - * This is auto-generated code. Do not manually edit! - */ - -goog.provide('goog.a11y.aria.datatables'); - -goog.require('goog.a11y.aria.State'); -goog.require('goog.object'); - - -/** - * A map that contains mapping between an ARIA state and the default value - * for it. Note that not all ARIA states have default values. - * - * @type {Object} - */ -goog.a11y.aria.DefaultStateValueMap_; - - -/** - * A method that creates a map that contains mapping between an ARIA state and - * the default value for it. Note that not all ARIA states have default values. - * - * @return {!Object} - * The names for each of the notification methods. - */ -goog.a11y.aria.datatables.getDefaultValuesMap = function() { - if (!goog.a11y.aria.DefaultStateValueMap_) { - goog.a11y.aria.DefaultStateValueMap_ = goog.object.create( - goog.a11y.aria.State.ATOMIC, false, - goog.a11y.aria.State.AUTOCOMPLETE, 'none', - goog.a11y.aria.State.DROPEFFECT, 'none', - goog.a11y.aria.State.HASPOPUP, false, - goog.a11y.aria.State.LIVE, 'off', - goog.a11y.aria.State.MULTILINE, false, - goog.a11y.aria.State.MULTISELECTABLE, false, - goog.a11y.aria.State.ORIENTATION, 'vertical', - goog.a11y.aria.State.READONLY, false, - goog.a11y.aria.State.RELEVANT, 'additions text', - goog.a11y.aria.State.REQUIRED, false, - goog.a11y.aria.State.SORT, 'none', - goog.a11y.aria.State.BUSY, false, - goog.a11y.aria.State.DISABLED, false, - goog.a11y.aria.State.HIDDEN, false, - goog.a11y.aria.State.INVALID, 'false'); - } - - return goog.a11y.aria.DefaultStateValueMap_; -}; diff --git a/src/database/third_party/closure-library/closure/goog/a11y/aria/roles.js b/src/database/third_party/closure-library/closure/goog/a11y/aria/roles.js deleted file mode 100644 index a282cc2d861..00000000000 --- a/src/database/third_party/closure-library/closure/goog/a11y/aria/roles.js +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright 2013 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - - -/** - * @fileoverview The file contains generated enumerations for ARIA roles - * as defined by W3C ARIA standard: http://www.w3.org/TR/wai-aria/. - * - * This is auto-generated code. Do not manually edit! For more details - * about how to edit it via the generator check go/closure-ariagen. - */ - -goog.provide('goog.a11y.aria.Role'); - - -/** - * ARIA role values. - * @enum {string} - */ -goog.a11y.aria.Role = { - // ARIA role for an alert element that doesn't need to be explicitly closed. - ALERT: 'alert', - - // ARIA role for an alert dialog element that takes focus and must be closed. - ALERTDIALOG: 'alertdialog', - - // ARIA role for an application that implements its own keyboard navigation. - APPLICATION: 'application', - - // ARIA role for an article. - ARTICLE: 'article', - - // ARIA role for a banner containing mostly site content, not page content. - BANNER: 'banner', - - // ARIA role for a button element. - BUTTON: 'button', - - // ARIA role for a checkbox button element; use with the CHECKED state. - CHECKBOX: 'checkbox', - - // ARIA role for a column header of a table or grid. - COLUMNHEADER: 'columnheader', - - // ARIA role for a combo box element. - COMBOBOX: 'combobox', - - // ARIA role for a supporting section of the document. - COMPLEMENTARY: 'complementary', - - // ARIA role for a large perceivable region that contains information - // about the parent document. - CONTENTINFO: 'contentinfo', - - // ARIA role for a definition of a term or concept. - DEFINITION: 'definition', - - // ARIA role for a dialog, some descendant must take initial focus. - DIALOG: 'dialog', - - // ARIA role for a directory, like a table of contents. - DIRECTORY: 'directory', - - // ARIA role for a part of a page that's a document, not a web application. - DOCUMENT: 'document', - - // ARIA role for a landmark region logically considered one form. - FORM: 'form', - - // ARIA role for an interactive control of tabular data. - GRID: 'grid', - - // ARIA role for a cell in a grid. - GRIDCELL: 'gridcell', - - // ARIA role for a group of related elements like tree item siblings. - GROUP: 'group', - - // ARIA role for a heading element. - HEADING: 'heading', - - // ARIA role for a container of elements that together comprise one image. - IMG: 'img', - - // ARIA role for a link. - LINK: 'link', - - // ARIA role for a list of non-interactive list items. - LIST: 'list', - - // ARIA role for a listbox. - LISTBOX: 'listbox', - - // ARIA role for a list item. - LISTITEM: 'listitem', - - // ARIA role for a live region where new information is added. - LOG: 'log', - - // ARIA landmark role for the main content in a document. Use only once. - MAIN: 'main', - - // ARIA role for a live region of non-essential information that changes. - MARQUEE: 'marquee', - - // ARIA role for a mathematical expression. - MATH: 'math', - - // ARIA role for a popup menu. - MENU: 'menu', - - // ARIA role for a menubar element containing menu elements. - MENUBAR: 'menubar', - - // ARIA role for menu item elements. - MENU_ITEM: 'menuitem', - - // ARIA role for a checkbox box element inside a menu. - MENU_ITEM_CHECKBOX: 'menuitemcheckbox', - - // ARIA role for a radio button element inside a menu. - MENU_ITEM_RADIO: 'menuitemradio', - - // ARIA landmark role for a collection of navigation links. - NAVIGATION: 'navigation', - - // ARIA role for a section ancillary to the main content. - NOTE: 'note', - - // ARIA role for option items that are children of combobox, listbox, menu, - // radiogroup, or tree elements. - OPTION: 'option', - - // ARIA role for ignorable cosmetic elements with no semantic significance. - PRESENTATION: 'presentation', - - // ARIA role for a progress bar element. - PROGRESSBAR: 'progressbar', - - // ARIA role for a radio button element. - RADIO: 'radio', - - // ARIA role for a group of connected radio button elements. - RADIOGROUP: 'radiogroup', - - // ARIA role for an important region of the page. - REGION: 'region', - - // ARIA role for a row of cells in a grid. - ROW: 'row', - - // ARIA role for a group of one or more rows in a grid. - ROWGROUP: 'rowgroup', - - // ARIA role for a row header of a table or grid. - ROWHEADER: 'rowheader', - - // ARIA role for a scrollbar element. - SCROLLBAR: 'scrollbar', - - // ARIA landmark role for a part of the page providing search functionality. - SEARCH: 'search', - - // ARIA role for a menu separator. - SEPARATOR: 'separator', - - // ARIA role for a slider. - SLIDER: 'slider', - - // ARIA role for a spin button. - SPINBUTTON: 'spinbutton', - - // ARIA role for a live region with advisory info less severe than an alert. - STATUS: 'status', - - // ARIA role for a tab button. - TAB: 'tab', - - // ARIA role for a tab bar (i.e. a list of tab buttons). - TAB_LIST: 'tablist', - - // ARIA role for a tab page (i.e. the element holding tab contents). - TAB_PANEL: 'tabpanel', - - // ARIA role for a textbox element. - TEXTBOX: 'textbox', - - // ARIA role for an element displaying elapsed time or time remaining. - TIMER: 'timer', - - // ARIA role for a toolbar element. - TOOLBAR: 'toolbar', - - // ARIA role for a tooltip element. - TOOLTIP: 'tooltip', - - // ARIA role for a tree. - TREE: 'tree', - - // ARIA role for a grid whose rows can be expanded and collapsed like a tree. - TREEGRID: 'treegrid', - - // ARIA role for a tree item that sometimes may be expanded or collapsed. - TREEITEM: 'treeitem' -}; diff --git a/src/database/third_party/closure-library/closure/goog/array/array.js b/src/database/third_party/closure-library/closure/goog/array/array.js deleted file mode 100644 index 03653c065bf..00000000000 --- a/src/database/third_party/closure-library/closure/goog/array/array.js +++ /dev/null @@ -1,1659 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utilities for manipulating arrays. - * - * @author arv@google.com (Erik Arvidsson) - */ - - -goog.provide('goog.array'); -goog.provide('goog.array.ArrayLike'); - -goog.require('goog.asserts'); - - -/** - * @define {boolean} NATIVE_ARRAY_PROTOTYPES indicates whether the code should - * rely on Array.prototype functions, if available. - * - * The Array.prototype functions can be defined by external libraries like - * Prototype and setting this flag to false forces closure to use its own - * goog.array implementation. - * - * If your javascript can be loaded by a third party site and you are wary about - * relying on the prototype functions, specify - * "--define goog.NATIVE_ARRAY_PROTOTYPES=false" to the JSCompiler. - * - * Setting goog.TRUSTED_SITE to false will automatically set - * NATIVE_ARRAY_PROTOTYPES to false. - */ -goog.define('goog.NATIVE_ARRAY_PROTOTYPES', goog.TRUSTED_SITE); - - -/** - * @define {boolean} If true, JSCompiler will use the native implementation of - * array functions where appropriate (e.g., {@code Array#filter}) and remove the - * unused pure JS implementation. - */ -goog.define('goog.array.ASSUME_NATIVE_FUNCTIONS', false); - - -/** - * @typedef {Array|NodeList|Arguments|{length: number}} - */ -goog.array.ArrayLike; - - -/** - * Returns the last element in an array without removing it. - * Same as goog.array.last. - * @param {Array|goog.array.ArrayLike} array The array. - * @return {T} Last item in array. - * @template T - */ -goog.array.peek = function(array) { - return array[array.length - 1]; -}; - - -/** - * Returns the last element in an array without removing it. - * Same as goog.array.peek. - * @param {Array|goog.array.ArrayLike} array The array. - * @return {T} Last item in array. - * @template T - */ -goog.array.last = goog.array.peek; - - -/** - * Reference to the original {@code Array.prototype}. - * @private - */ -goog.array.ARRAY_PROTOTYPE_ = Array.prototype; - - -// NOTE(arv): Since most of the array functions are generic it allows you to -// pass an array-like object. Strings have a length and are considered array- -// like. However, the 'in' operator does not work on strings so we cannot just -// use the array path even if the browser supports indexing into strings. We -// therefore end up splitting the string. - - -/** - * Returns the index of the first element of an array with a specified value, or - * -1 if the element is not present in the array. - * - * See {@link http://tinyurl.com/developer-mozilla-org-array-indexof} - * - * @param {Array|goog.array.ArrayLike} arr The array to be searched. - * @param {T} obj The object for which we are searching. - * @param {number=} opt_fromIndex The index at which to start the search. If - * omitted the search starts at index 0. - * @return {number} The index of the first matching array element. - * @template T - */ -goog.array.indexOf = goog.NATIVE_ARRAY_PROTOTYPES && - (goog.array.ASSUME_NATIVE_FUNCTIONS || - goog.array.ARRAY_PROTOTYPE_.indexOf) ? - function(arr, obj, opt_fromIndex) { - goog.asserts.assert(arr.length != null); - - return goog.array.ARRAY_PROTOTYPE_.indexOf.call(arr, obj, opt_fromIndex); - } : - function(arr, obj, opt_fromIndex) { - var fromIndex = opt_fromIndex == null ? - 0 : (opt_fromIndex < 0 ? - Math.max(0, arr.length + opt_fromIndex) : opt_fromIndex); - - if (goog.isString(arr)) { - // Array.prototype.indexOf uses === so only strings should be found. - if (!goog.isString(obj) || obj.length != 1) { - return -1; - } - return arr.indexOf(obj, fromIndex); - } - - for (var i = fromIndex; i < arr.length; i++) { - if (i in arr && arr[i] === obj) - return i; - } - return -1; - }; - - -/** - * Returns the index of the last element of an array with a specified value, or - * -1 if the element is not present in the array. - * - * See {@link http://tinyurl.com/developer-mozilla-org-array-lastindexof} - * - * @param {!Array|!goog.array.ArrayLike} arr The array to be searched. - * @param {T} obj The object for which we are searching. - * @param {?number=} opt_fromIndex The index at which to start the search. If - * omitted the search starts at the end of the array. - * @return {number} The index of the last matching array element. - * @template T - */ -goog.array.lastIndexOf = goog.NATIVE_ARRAY_PROTOTYPES && - (goog.array.ASSUME_NATIVE_FUNCTIONS || - goog.array.ARRAY_PROTOTYPE_.lastIndexOf) ? - function(arr, obj, opt_fromIndex) { - goog.asserts.assert(arr.length != null); - - // Firefox treats undefined and null as 0 in the fromIndex argument which - // leads it to always return -1 - var fromIndex = opt_fromIndex == null ? arr.length - 1 : opt_fromIndex; - return goog.array.ARRAY_PROTOTYPE_.lastIndexOf.call(arr, obj, fromIndex); - } : - function(arr, obj, opt_fromIndex) { - var fromIndex = opt_fromIndex == null ? arr.length - 1 : opt_fromIndex; - - if (fromIndex < 0) { - fromIndex = Math.max(0, arr.length + fromIndex); - } - - if (goog.isString(arr)) { - // Array.prototype.lastIndexOf uses === so only strings should be found. - if (!goog.isString(obj) || obj.length != 1) { - return -1; - } - return arr.lastIndexOf(obj, fromIndex); - } - - for (var i = fromIndex; i >= 0; i--) { - if (i in arr && arr[i] === obj) - return i; - } - return -1; - }; - - -/** - * Calls a function for each element in an array. Skips holes in the array. - * See {@link http://tinyurl.com/developer-mozilla-org-array-foreach} - * - * @param {Array|goog.array.ArrayLike} arr Array or array like object over - * which to iterate. - * @param {?function(this: S, T, number, ?): ?} f The function to call for every - * element. This function takes 3 arguments (the element, the index and the - * array). The return value is ignored. - * @param {S=} opt_obj The object to be used as the value of 'this' within f. - * @template T,S - */ -goog.array.forEach = goog.NATIVE_ARRAY_PROTOTYPES && - (goog.array.ASSUME_NATIVE_FUNCTIONS || - goog.array.ARRAY_PROTOTYPE_.forEach) ? - function(arr, f, opt_obj) { - goog.asserts.assert(arr.length != null); - - goog.array.ARRAY_PROTOTYPE_.forEach.call(arr, f, opt_obj); - } : - function(arr, f, opt_obj) { - var l = arr.length; // must be fixed during loop... see docs - var arr2 = goog.isString(arr) ? arr.split('') : arr; - for (var i = 0; i < l; i++) { - if (i in arr2) { - f.call(opt_obj, arr2[i], i, arr); - } - } - }; - - -/** - * Calls a function for each element in an array, starting from the last - * element rather than the first. - * - * @param {Array|goog.array.ArrayLike} arr Array or array - * like object over which to iterate. - * @param {?function(this: S, T, number, ?): ?} f The function to call for every - * element. This function - * takes 3 arguments (the element, the index and the array). The return - * value is ignored. - * @param {S=} opt_obj The object to be used as the value of 'this' - * within f. - * @template T,S - */ -goog.array.forEachRight = function(arr, f, opt_obj) { - var l = arr.length; // must be fixed during loop... see docs - var arr2 = goog.isString(arr) ? arr.split('') : arr; - for (var i = l - 1; i >= 0; --i) { - if (i in arr2) { - f.call(opt_obj, arr2[i], i, arr); - } - } -}; - - -/** - * Calls a function for each element in an array, and if the function returns - * true adds the element to a new array. - * - * See {@link http://tinyurl.com/developer-mozilla-org-array-filter} - * - * @param {Array|goog.array.ArrayLike} arr Array or array - * like object over which to iterate. - * @param {?function(this:S, T, number, ?):boolean} f The function to call for - * every element. This function - * takes 3 arguments (the element, the index and the array) and must - * return a Boolean. If the return value is true the element is added to the - * result array. If it is false the element is not included. - * @param {S=} opt_obj The object to be used as the value of 'this' - * within f. - * @return {!Array} a new array in which only elements that passed the test - * are present. - * @template T,S - */ -goog.array.filter = goog.NATIVE_ARRAY_PROTOTYPES && - (goog.array.ASSUME_NATIVE_FUNCTIONS || - goog.array.ARRAY_PROTOTYPE_.filter) ? - function(arr, f, opt_obj) { - goog.asserts.assert(arr.length != null); - - return goog.array.ARRAY_PROTOTYPE_.filter.call(arr, f, opt_obj); - } : - function(arr, f, opt_obj) { - var l = arr.length; // must be fixed during loop... see docs - var res = []; - var resLength = 0; - var arr2 = goog.isString(arr) ? arr.split('') : arr; - for (var i = 0; i < l; i++) { - if (i in arr2) { - var val = arr2[i]; // in case f mutates arr2 - if (f.call(opt_obj, val, i, arr)) { - res[resLength++] = val; - } - } - } - return res; - }; - - -/** - * Calls a function for each element in an array and inserts the result into a - * new array. - * - * See {@link http://tinyurl.com/developer-mozilla-org-array-map} - * - * @param {Array|goog.array.ArrayLike} arr Array or array like object - * over which to iterate. - * @param {function(this:THIS, VALUE, number, ?): RESULT} f The function to call - * for every element. This function takes 3 arguments (the element, - * the index and the array) and should return something. The result will be - * inserted into a new array. - * @param {THIS=} opt_obj The object to be used as the value of 'this' within f. - * @return {!Array} a new array with the results from f. - * @template THIS, VALUE, RESULT - */ -goog.array.map = goog.NATIVE_ARRAY_PROTOTYPES && - (goog.array.ASSUME_NATIVE_FUNCTIONS || - goog.array.ARRAY_PROTOTYPE_.map) ? - function(arr, f, opt_obj) { - goog.asserts.assert(arr.length != null); - - return goog.array.ARRAY_PROTOTYPE_.map.call(arr, f, opt_obj); - } : - function(arr, f, opt_obj) { - var l = arr.length; // must be fixed during loop... see docs - var res = new Array(l); - var arr2 = goog.isString(arr) ? arr.split('') : arr; - for (var i = 0; i < l; i++) { - if (i in arr2) { - res[i] = f.call(opt_obj, arr2[i], i, arr); - } - } - return res; - }; - - -/** - * Passes every element of an array into a function and accumulates the result. - * - * See {@link http://tinyurl.com/developer-mozilla-org-array-reduce} - * - * For example: - * var a = [1, 2, 3, 4]; - * goog.array.reduce(a, function(r, v, i, arr) {return r + v;}, 0); - * returns 10 - * - * @param {Array|goog.array.ArrayLike} arr Array or array - * like object over which to iterate. - * @param {function(this:S, R, T, number, ?) : R} f The function to call for - * every element. This function - * takes 4 arguments (the function's previous result or the initial value, - * the value of the current array element, the current array index, and the - * array itself) - * function(previousValue, currentValue, index, array). - * @param {?} val The initial value to pass into the function on the first call. - * @param {S=} opt_obj The object to be used as the value of 'this' - * within f. - * @return {R} Result of evaluating f repeatedly across the values of the array. - * @template T,S,R - */ -goog.array.reduce = goog.NATIVE_ARRAY_PROTOTYPES && - (goog.array.ASSUME_NATIVE_FUNCTIONS || - goog.array.ARRAY_PROTOTYPE_.reduce) ? - function(arr, f, val, opt_obj) { - goog.asserts.assert(arr.length != null); - var params = []; - for(var i = 1, l = arguments.length; i < l; i++){ - params.push(arguments[i]); - } - if (opt_obj) { - params[0] = goog.bind(f, opt_obj); - } - return goog.array.ARRAY_PROTOTYPE_.reduce.apply(arr, params); - } : - function(arr, f, val, opt_obj) { - var rval = val; - goog.array.forEach(arr, function(val, index) { - rval = f.call(opt_obj, rval, val, index, arr); - }); - return rval; - }; - - -/** - * Passes every element of an array into a function and accumulates the result, - * starting from the last element and working towards the first. - * - * See {@link http://tinyurl.com/developer-mozilla-org-array-reduceright} - * - * For example: - * var a = ['a', 'b', 'c']; - * goog.array.reduceRight(a, function(r, v, i, arr) {return r + v;}, ''); - * returns 'cba' - * - * @param {Array|goog.array.ArrayLike} arr Array or array - * like object over which to iterate. - * @param {?function(this:S, R, T, number, ?) : R} f The function to call for - * every element. This function - * takes 4 arguments (the function's previous result or the initial value, - * the value of the current array element, the current array index, and the - * array itself) - * function(previousValue, currentValue, index, array). - * @param {?} val The initial value to pass into the function on the first call. - * @param {S=} opt_obj The object to be used as the value of 'this' - * within f. - * @return {R} Object returned as a result of evaluating f repeatedly across the - * values of the array. - * @template T,S,R - */ -goog.array.reduceRight = goog.NATIVE_ARRAY_PROTOTYPES && - (goog.array.ASSUME_NATIVE_FUNCTIONS || - goog.array.ARRAY_PROTOTYPE_.reduceRight) ? - function(arr, f, val, opt_obj) { - goog.asserts.assert(arr.length != null); - if (opt_obj) { - f = goog.bind(f, opt_obj); - } - return goog.array.ARRAY_PROTOTYPE_.reduceRight.call(arr, f, val); - } : - function(arr, f, val, opt_obj) { - var rval = val; - goog.array.forEachRight(arr, function(val, index) { - rval = f.call(opt_obj, rval, val, index, arr); - }); - return rval; - }; - - -/** - * Calls f for each element of an array. If any call returns true, some() - * returns true (without checking the remaining elements). If all calls - * return false, some() returns false. - * - * See {@link http://tinyurl.com/developer-mozilla-org-array-some} - * - * @param {Array|goog.array.ArrayLike} arr Array or array - * like object over which to iterate. - * @param {?function(this:S, T, number, ?) : boolean} f The function to call for - * for every element. This function takes 3 arguments (the element, the - * index and the array) and should return a boolean. - * @param {S=} opt_obj The object to be used as the value of 'this' - * within f. - * @return {boolean} true if any element passes the test. - * @template T,S - */ -goog.array.some = goog.NATIVE_ARRAY_PROTOTYPES && - (goog.array.ASSUME_NATIVE_FUNCTIONS || - goog.array.ARRAY_PROTOTYPE_.some) ? - function(arr, f, opt_obj) { - goog.asserts.assert(arr.length != null); - - return goog.array.ARRAY_PROTOTYPE_.some.call(arr, f, opt_obj); - } : - function(arr, f, opt_obj) { - var l = arr.length; // must be fixed during loop... see docs - var arr2 = goog.isString(arr) ? arr.split('') : arr; - for (var i = 0; i < l; i++) { - if (i in arr2 && f.call(opt_obj, arr2[i], i, arr)) { - return true; - } - } - return false; - }; - - -/** - * Call f for each element of an array. If all calls return true, every() - * returns true. If any call returns false, every() returns false and - * does not continue to check the remaining elements. - * - * See {@link http://tinyurl.com/developer-mozilla-org-array-every} - * - * @param {Array|goog.array.ArrayLike} arr Array or array - * like object over which to iterate. - * @param {?function(this:S, T, number, ?) : boolean} f The function to call for - * for every element. This function takes 3 arguments (the element, the - * index and the array) and should return a boolean. - * @param {S=} opt_obj The object to be used as the value of 'this' - * within f. - * @return {boolean} false if any element fails the test. - * @template T,S - */ -goog.array.every = goog.NATIVE_ARRAY_PROTOTYPES && - (goog.array.ASSUME_NATIVE_FUNCTIONS || - goog.array.ARRAY_PROTOTYPE_.every) ? - function(arr, f, opt_obj) { - goog.asserts.assert(arr.length != null); - - return goog.array.ARRAY_PROTOTYPE_.every.call(arr, f, opt_obj); - } : - function(arr, f, opt_obj) { - var l = arr.length; // must be fixed during loop... see docs - var arr2 = goog.isString(arr) ? arr.split('') : arr; - for (var i = 0; i < l; i++) { - if (i in arr2 && !f.call(opt_obj, arr2[i], i, arr)) { - return false; - } - } - return true; - }; - - -/** - * Counts the array elements that fulfill the predicate, i.e. for which the - * callback function returns true. Skips holes in the array. - * - * @param {!(Array|goog.array.ArrayLike)} arr Array or array like object - * over which to iterate. - * @param {function(this: S, T, number, ?): boolean} f The function to call for - * every element. Takes 3 arguments (the element, the index and the array). - * @param {S=} opt_obj The object to be used as the value of 'this' within f. - * @return {number} The number of the matching elements. - * @template T,S - */ -goog.array.count = function(arr, f, opt_obj) { - var count = 0; - goog.array.forEach(arr, function(element, index, arr) { - if (f.call(opt_obj, element, index, arr)) { - ++count; - } - }, opt_obj); - return count; -}; - - -/** - * Search an array for the first element that satisfies a given condition and - * return that element. - * @param {Array|goog.array.ArrayLike} arr Array or array - * like object over which to iterate. - * @param {?function(this:S, T, number, ?) : boolean} f The function to call - * for every element. This function takes 3 arguments (the element, the - * index and the array) and should return a boolean. - * @param {S=} opt_obj An optional "this" context for the function. - * @return {T|null} The first array element that passes the test, or null if no - * element is found. - * @template T,S - */ -goog.array.find = function(arr, f, opt_obj) { - var i = goog.array.findIndex(arr, f, opt_obj); - return i < 0 ? null : goog.isString(arr) ? arr.charAt(i) : arr[i]; -}; - - -/** - * Search an array for the first element that satisfies a given condition and - * return its index. - * @param {Array|goog.array.ArrayLike} arr Array or array - * like object over which to iterate. - * @param {?function(this:S, T, number, ?) : boolean} f The function to call for - * every element. This function - * takes 3 arguments (the element, the index and the array) and should - * return a boolean. - * @param {S=} opt_obj An optional "this" context for the function. - * @return {number} The index of the first array element that passes the test, - * or -1 if no element is found. - * @template T,S - */ -goog.array.findIndex = function(arr, f, opt_obj) { - var l = arr.length; // must be fixed during loop... see docs - var arr2 = goog.isString(arr) ? arr.split('') : arr; - for (var i = 0; i < l; i++) { - if (i in arr2 && f.call(opt_obj, arr2[i], i, arr)) { - return i; - } - } - return -1; -}; - - -/** - * Search an array (in reverse order) for the last element that satisfies a - * given condition and return that element. - * @param {Array|goog.array.ArrayLike} arr Array or array - * like object over which to iterate. - * @param {?function(this:S, T, number, ?) : boolean} f The function to call - * for every element. This function - * takes 3 arguments (the element, the index and the array) and should - * return a boolean. - * @param {S=} opt_obj An optional "this" context for the function. - * @return {T|null} The last array element that passes the test, or null if no - * element is found. - * @template T,S - */ -goog.array.findRight = function(arr, f, opt_obj) { - var i = goog.array.findIndexRight(arr, f, opt_obj); - return i < 0 ? null : goog.isString(arr) ? arr.charAt(i) : arr[i]; -}; - - -/** - * Search an array (in reverse order) for the last element that satisfies a - * given condition and return its index. - * @param {Array|goog.array.ArrayLike} arr Array or array - * like object over which to iterate. - * @param {?function(this:S, T, number, ?) : boolean} f The function to call - * for every element. This function - * takes 3 arguments (the element, the index and the array) and should - * return a boolean. - * @param {S=} opt_obj An optional "this" context for the function. - * @return {number} The index of the last array element that passes the test, - * or -1 if no element is found. - * @template T,S - */ -goog.array.findIndexRight = function(arr, f, opt_obj) { - var l = arr.length; // must be fixed during loop... see docs - var arr2 = goog.isString(arr) ? arr.split('') : arr; - for (var i = l - 1; i >= 0; i--) { - if (i in arr2 && f.call(opt_obj, arr2[i], i, arr)) { - return i; - } - } - return -1; -}; - - -/** - * Whether the array contains the given object. - * @param {goog.array.ArrayLike} arr The array to test for the presence of the - * element. - * @param {*} obj The object for which to test. - * @return {boolean} true if obj is present. - */ -goog.array.contains = function(arr, obj) { - return goog.array.indexOf(arr, obj) >= 0; -}; - - -/** - * Whether the array is empty. - * @param {goog.array.ArrayLike} arr The array to test. - * @return {boolean} true if empty. - */ -goog.array.isEmpty = function(arr) { - return arr.length == 0; -}; - - -/** - * Clears the array. - * @param {goog.array.ArrayLike} arr Array or array like object to clear. - */ -goog.array.clear = function(arr) { - // For non real arrays we don't have the magic length so we delete the - // indices. - if (!goog.isArray(arr)) { - for (var i = arr.length - 1; i >= 0; i--) { - delete arr[i]; - } - } - arr.length = 0; -}; - - -/** - * Pushes an item into an array, if it's not already in the array. - * @param {Array} arr Array into which to insert the item. - * @param {T} obj Value to add. - * @template T - */ -goog.array.insert = function(arr, obj) { - if (!goog.array.contains(arr, obj)) { - arr.push(obj); - } -}; - - -/** - * Inserts an object at the given index of the array. - * @param {goog.array.ArrayLike} arr The array to modify. - * @param {*} obj The object to insert. - * @param {number=} opt_i The index at which to insert the object. If omitted, - * treated as 0. A negative index is counted from the end of the array. - */ -goog.array.insertAt = function(arr, obj, opt_i) { - goog.array.splice(arr, opt_i, 0, obj); -}; - - -/** - * Inserts at the given index of the array, all elements of another array. - * @param {goog.array.ArrayLike} arr The array to modify. - * @param {goog.array.ArrayLike} elementsToAdd The array of elements to add. - * @param {number=} opt_i The index at which to insert the object. If omitted, - * treated as 0. A negative index is counted from the end of the array. - */ -goog.array.insertArrayAt = function(arr, elementsToAdd, opt_i) { - goog.partial(goog.array.splice, arr, opt_i, 0).apply(null, elementsToAdd); -}; - - -/** - * Inserts an object into an array before a specified object. - * @param {Array} arr The array to modify. - * @param {T} obj The object to insert. - * @param {T=} opt_obj2 The object before which obj should be inserted. If obj2 - * is omitted or not found, obj is inserted at the end of the array. - * @template T - */ -goog.array.insertBefore = function(arr, obj, opt_obj2) { - var i; - if (arguments.length == 2 || (i = goog.array.indexOf(arr, opt_obj2)) < 0) { - arr.push(obj); - } else { - goog.array.insertAt(arr, obj, i); - } -}; - - -/** - * Removes the first occurrence of a particular value from an array. - * @param {Array|goog.array.ArrayLike} arr Array from which to remove - * value. - * @param {T} obj Object to remove. - * @return {boolean} True if an element was removed. - * @template T - */ -goog.array.remove = function(arr, obj) { - var i = goog.array.indexOf(arr, obj); - var rv; - if ((rv = i >= 0)) { - goog.array.removeAt(arr, i); - } - return rv; -}; - - -/** - * Removes from an array the element at index i - * @param {goog.array.ArrayLike} arr Array or array like object from which to - * remove value. - * @param {number} i The index to remove. - * @return {boolean} True if an element was removed. - */ -goog.array.removeAt = function(arr, i) { - goog.asserts.assert(arr.length != null); - - // use generic form of splice - // splice returns the removed items and if successful the length of that - // will be 1 - return goog.array.ARRAY_PROTOTYPE_.splice.call(arr, i, 1).length == 1; -}; - - -/** - * Removes the first value that satisfies the given condition. - * @param {Array|goog.array.ArrayLike} arr Array or array - * like object over which to iterate. - * @param {?function(this:S, T, number, ?) : boolean} f The function to call - * for every element. This function - * takes 3 arguments (the element, the index and the array) and should - * return a boolean. - * @param {S=} opt_obj An optional "this" context for the function. - * @return {boolean} True if an element was removed. - * @template T,S - */ -goog.array.removeIf = function(arr, f, opt_obj) { - var i = goog.array.findIndex(arr, f, opt_obj); - if (i >= 0) { - goog.array.removeAt(arr, i); - return true; - } - return false; -}; - - -/** - * Removes all values that satisfy the given condition. - * @param {Array|goog.array.ArrayLike} arr Array or array - * like object over which to iterate. - * @param {?function(this:S, T, number, ?) : boolean} f The function to call - * for every element. This function - * takes 3 arguments (the element, the index and the array) and should - * return a boolean. - * @param {S=} opt_obj An optional "this" context for the function. - * @return {number} The number of items removed - * @template T,S - */ -goog.array.removeAllIf = function(arr, f, opt_obj) { - var removedCount = 0; - goog.array.forEachRight(arr, function(val, index) { - if (f.call(opt_obj, val, index, arr)) { - if (goog.array.removeAt(arr, index)) { - removedCount++; - } - } - }); - return removedCount; -}; - - -/** - * Returns a new array that is the result of joining the arguments. If arrays - * are passed then their items are added, however, if non-arrays are passed they - * will be added to the return array as is. - * - * Note that ArrayLike objects will be added as is, rather than having their - * items added. - * - * goog.array.concat([1, 2], [3, 4]) -> [1, 2, 3, 4] - * goog.array.concat(0, [1, 2]) -> [0, 1, 2] - * goog.array.concat([1, 2], null) -> [1, 2, null] - * - * There is bug in all current versions of IE (6, 7 and 8) where arrays created - * in an iframe become corrupted soon (not immediately) after the iframe is - * destroyed. This is common if loading data via goog.net.IframeIo, for example. - * This corruption only affects the concat method which will start throwing - * Catastrophic Errors (#-2147418113). - * - * See http://endoflow.com/scratch/corrupted-arrays.html for a test case. - * - * Internally goog.array should use this, so that all methods will continue to - * work on these broken array objects. - * - * @param {...*} var_args Items to concatenate. Arrays will have each item - * added, while primitives and objects will be added as is. - * @return {!Array} The new resultant array. - */ -goog.array.concat = function(var_args) { - return goog.array.ARRAY_PROTOTYPE_.concat.apply( - goog.array.ARRAY_PROTOTYPE_, arguments); -}; - - -/** - * Returns a new array that contains the contents of all the arrays passed. - * @param {...!Array} var_args - * @return {!Array} - * @template T - */ -goog.array.join = function(var_args) { - return goog.array.ARRAY_PROTOTYPE_.concat.apply( - goog.array.ARRAY_PROTOTYPE_, arguments); -}; - - -/** - * Converts an object to an array. - * @param {Array|goog.array.ArrayLike} object The object to convert to an - * array. - * @return {!Array} The object converted into an array. If object has a - * length property, every property indexed with a non-negative number - * less than length will be included in the result. If object does not - * have a length property, an empty array will be returned. - * @template T - */ -goog.array.toArray = function(object) { - var length = object.length; - - // If length is not a number the following it false. This case is kept for - // backwards compatibility since there are callers that pass objects that are - // not array like. - if (length > 0) { - var rv = new Array(length); - for (var i = 0; i < length; i++) { - rv[i] = object[i]; - } - return rv; - } - return []; -}; - - -/** - * Does a shallow copy of an array. - * @param {Array|goog.array.ArrayLike} arr Array or array-like object to - * clone. - * @return {!Array} Clone of the input array. - * @template T - */ -goog.array.clone = goog.array.toArray; - - -/** - * Extends an array with another array, element, or "array like" object. - * This function operates 'in-place', it does not create a new Array. - * - * Example: - * var a = []; - * goog.array.extend(a, [0, 1]); - * a; // [0, 1] - * goog.array.extend(a, 2); - * a; // [0, 1, 2] - * - * @param {Array} arr1 The array to modify. - * @param {...(Array|VALUE)} var_args The elements or arrays of elements - * to add to arr1. - * @template VALUE - */ -goog.array.extend = function(arr1, var_args) { - for (var i = 1; i < arguments.length; i++) { - var arr2 = arguments[i]; - if (goog.isArrayLike(arr2)) { - var len1 = arr1.length || 0; - var len2 = arr2.length || 0; - arr1.length = len1 + len2; - for (var j = 0; j < len2; j++) { - arr1[len1 + j] = arr2[j]; - } - } else { - arr1.push(arr2); - } - } -}; - - -/** - * Adds or removes elements from an array. This is a generic version of Array - * splice. This means that it might work on other objects similar to arrays, - * such as the arguments object. - * - * @param {Array|goog.array.ArrayLike} arr The array to modify. - * @param {number|undefined} index The index at which to start changing the - * array. If not defined, treated as 0. - * @param {number} howMany How many elements to remove (0 means no removal. A - * value below 0 is treated as zero and so is any other non number. Numbers - * are floored). - * @param {...T} var_args Optional, additional elements to insert into the - * array. - * @return {!Array} the removed elements. - * @template T - */ -goog.array.splice = function(arr, index, howMany, var_args) { - goog.asserts.assert(arr.length != null); - - return goog.array.ARRAY_PROTOTYPE_.splice.apply( - arr, goog.array.slice(arguments, 1)); -}; - - -/** - * Returns a new array from a segment of an array. This is a generic version of - * Array slice. This means that it might work on other objects similar to - * arrays, such as the arguments object. - * - * @param {Array|goog.array.ArrayLike} arr The array from - * which to copy a segment. - * @param {number} start The index of the first element to copy. - * @param {number=} opt_end The index after the last element to copy. - * @return {!Array} A new array containing the specified segment of the - * original array. - * @template T - */ -goog.array.slice = function(arr, start, opt_end) { - goog.asserts.assert(arr.length != null); - - // passing 1 arg to slice is not the same as passing 2 where the second is - // null or undefined (in that case the second argument is treated as 0). - // we could use slice on the arguments object and then use apply instead of - // testing the length - if (arguments.length <= 2) { - return goog.array.ARRAY_PROTOTYPE_.slice.call(arr, start); - } else { - return goog.array.ARRAY_PROTOTYPE_.slice.call(arr, start, opt_end); - } -}; - - -/** - * Removes all duplicates from an array (retaining only the first - * occurrence of each array element). This function modifies the - * array in place and doesn't change the order of the non-duplicate items. - * - * For objects, duplicates are identified as having the same unique ID as - * defined by {@link goog.getUid}. - * - * Alternatively you can specify a custom hash function that returns a unique - * value for each item in the array it should consider unique. - * - * Runtime: N, - * Worstcase space: 2N (no dupes) - * - * @param {Array|goog.array.ArrayLike} arr The array from which to remove - * duplicates. - * @param {Array=} opt_rv An optional array in which to return the results, - * instead of performing the removal inplace. If specified, the original - * array will remain unchanged. - * @param {function(T):string=} opt_hashFn An optional function to use to - * apply to every item in the array. This function should return a unique - * value for each item in the array it should consider unique. - * @template T - */ -goog.array.removeDuplicates = function(arr, opt_rv, opt_hashFn) { - var returnArray = opt_rv || arr; - var defaultHashFn = function(item) { - // Prefix each type with a single character representing the type to - // prevent conflicting keys (e.g. true and 'true'). - return goog.isObject(current) ? 'o' + goog.getUid(current) : - (typeof current).charAt(0) + current; - }; - var hashFn = opt_hashFn || defaultHashFn; - - var seen = {}, cursorInsert = 0, cursorRead = 0; - while (cursorRead < arr.length) { - var current = arr[cursorRead++]; - var key = hashFn(current); - if (!Object.prototype.hasOwnProperty.call(seen, key)) { - seen[key] = true; - returnArray[cursorInsert++] = current; - } - } - returnArray.length = cursorInsert; -}; - - -/** - * Searches the specified array for the specified target using the binary - * search algorithm. If no opt_compareFn is specified, elements are compared - * using goog.array.defaultCompare, which compares the elements - * using the built in < and > operators. This will produce the expected - * behavior for homogeneous arrays of String(s) and Number(s). The array - * specified must be sorted in ascending order (as defined by the - * comparison function). If the array is not sorted, results are undefined. - * If the array contains multiple instances of the specified target value, any - * of these instances may be found. - * - * Runtime: O(log n) - * - * @param {Array|goog.array.ArrayLike} arr The array to be searched. - * @param {TARGET} target The sought value. - * @param {function(TARGET, VALUE): number=} opt_compareFn Optional comparison - * function by which the array is ordered. Should take 2 arguments to - * compare, and return a negative number, zero, or a positive number - * depending on whether the first argument is less than, equal to, or - * greater than the second. - * @return {number} Lowest index of the target value if found, otherwise - * (-(insertion point) - 1). The insertion point is where the value should - * be inserted into arr to preserve the sorted property. Return value >= 0 - * iff target is found. - * @template TARGET, VALUE - */ -goog.array.binarySearch = function(arr, target, opt_compareFn) { - return goog.array.binarySearch_(arr, - opt_compareFn || goog.array.defaultCompare, false /* isEvaluator */, - target); -}; - - -/** - * Selects an index in the specified array using the binary search algorithm. - * The evaluator receives an element and determines whether the desired index - * is before, at, or after it. The evaluator must be consistent (formally, - * goog.array.map(goog.array.map(arr, evaluator, opt_obj), goog.math.sign) - * must be monotonically non-increasing). - * - * Runtime: O(log n) - * - * @param {Array|goog.array.ArrayLike} arr The array to be searched. - * @param {function(this:THIS, VALUE, number, ?): number} evaluator - * Evaluator function that receives 3 arguments (the element, the index and - * the array). Should return a negative number, zero, or a positive number - * depending on whether the desired index is before, at, or after the - * element passed to it. - * @param {THIS=} opt_obj The object to be used as the value of 'this' - * within evaluator. - * @return {number} Index of the leftmost element matched by the evaluator, if - * such exists; otherwise (-(insertion point) - 1). The insertion point is - * the index of the first element for which the evaluator returns negative, - * or arr.length if no such element exists. The return value is non-negative - * iff a match is found. - * @template THIS, VALUE - */ -goog.array.binarySelect = function(arr, evaluator, opt_obj) { - return goog.array.binarySearch_(arr, evaluator, true /* isEvaluator */, - undefined /* opt_target */, opt_obj); -}; - - -/** - * Implementation of a binary search algorithm which knows how to use both - * comparison functions and evaluators. If an evaluator is provided, will call - * the evaluator with the given optional data object, conforming to the - * interface defined in binarySelect. Otherwise, if a comparison function is - * provided, will call the comparison function against the given data object. - * - * This implementation purposefully does not use goog.bind or goog.partial for - * performance reasons. - * - * Runtime: O(log n) - * - * @param {Array|goog.array.ArrayLike} arr The array to be searched. - * @param {function(TARGET, VALUE): number| - * function(this:THIS, VALUE, number, ?): number} compareFn Either an - * evaluator or a comparison function, as defined by binarySearch - * and binarySelect above. - * @param {boolean} isEvaluator Whether the function is an evaluator or a - * comparison function. - * @param {TARGET=} opt_target If the function is a comparison function, then - * this is the target to binary search for. - * @param {THIS=} opt_selfObj If the function is an evaluator, this is an - * optional this object for the evaluator. - * @return {number} Lowest index of the target value if found, otherwise - * (-(insertion point) - 1). The insertion point is where the value should - * be inserted into arr to preserve the sorted property. Return value >= 0 - * iff target is found. - * @template THIS, VALUE, TARGET - * @private - */ -goog.array.binarySearch_ = function(arr, compareFn, isEvaluator, opt_target, - opt_selfObj) { - var left = 0; // inclusive - var right = arr.length; // exclusive - var found; - while (left < right) { - var middle = (left + right) >> 1; - var compareResult; - if (isEvaluator) { - compareResult = compareFn.call(opt_selfObj, arr[middle], middle, arr); - } else { - compareResult = compareFn(opt_target, arr[middle]); - } - if (compareResult > 0) { - left = middle + 1; - } else { - right = middle; - // We are looking for the lowest index so we can't return immediately. - found = !compareResult; - } - } - // left is the index if found, or the insertion point otherwise. - // ~left is a shorthand for -left - 1. - return found ? left : ~left; -}; - - -/** - * Sorts the specified array into ascending order. If no opt_compareFn is - * specified, elements are compared using - * goog.array.defaultCompare, which compares the elements using - * the built in < and > operators. This will produce the expected behavior - * for homogeneous arrays of String(s) and Number(s), unlike the native sort, - * but will give unpredictable results for heterogenous lists of strings and - * numbers with different numbers of digits. - * - * This sort is not guaranteed to be stable. - * - * Runtime: Same as Array.prototype.sort - * - * @param {Array} arr The array to be sorted. - * @param {?function(T,T):number=} opt_compareFn Optional comparison - * function by which the - * array is to be ordered. Should take 2 arguments to compare, and return a - * negative number, zero, or a positive number depending on whether the - * first argument is less than, equal to, or greater than the second. - * @template T - */ -goog.array.sort = function(arr, opt_compareFn) { - // TODO(arv): Update type annotation since null is not accepted. - arr.sort(opt_compareFn || goog.array.defaultCompare); -}; - - -/** - * Sorts the specified array into ascending order in a stable way. If no - * opt_compareFn is specified, elements are compared using - * goog.array.defaultCompare, which compares the elements using - * the built in < and > operators. This will produce the expected behavior - * for homogeneous arrays of String(s) and Number(s). - * - * Runtime: Same as Array.prototype.sort, plus an additional - * O(n) overhead of copying the array twice. - * - * @param {Array} arr The array to be sorted. - * @param {?function(T, T): number=} opt_compareFn Optional comparison function - * by which the array is to be ordered. Should take 2 arguments to compare, - * and return a negative number, zero, or a positive number depending on - * whether the first argument is less than, equal to, or greater than the - * second. - * @template T - */ -goog.array.stableSort = function(arr, opt_compareFn) { - for (var i = 0; i < arr.length; i++) { - arr[i] = {index: i, value: arr[i]}; - } - var valueCompareFn = opt_compareFn || goog.array.defaultCompare; - function stableCompareFn(obj1, obj2) { - return valueCompareFn(obj1.value, obj2.value) || obj1.index - obj2.index; - }; - goog.array.sort(arr, stableCompareFn); - for (var i = 0; i < arr.length; i++) { - arr[i] = arr[i].value; - } -}; - - -/** - * Sort the specified array into ascending order based on item keys - * returned by the specified key function. - * If no opt_compareFn is specified, the keys are compared in ascending order - * using goog.array.defaultCompare. - * - * Runtime: O(S(f(n)), where S is runtime of goog.array.sort - * and f(n) is runtime of the key function. - * - * @param {Array} arr The array to be sorted. - * @param {function(T): K} keyFn Function taking array element and returning - * a key used for sorting this element. - * @param {?function(K, K): number=} opt_compareFn Optional comparison function - * by which the keys are to be ordered. Should take 2 arguments to compare, - * and return a negative number, zero, or a positive number depending on - * whether the first argument is less than, equal to, or greater than the - * second. - * @template T - * @template K - */ -goog.array.sortByKey = function(arr, keyFn, opt_compareFn) { - var keyCompareFn = opt_compareFn || goog.array.defaultCompare; - goog.array.sort(arr, function(a, b) { - return keyCompareFn(keyFn(a), keyFn(b)); - }); -}; - - -/** - * Sorts an array of objects by the specified object key and compare - * function. If no compare function is provided, the key values are - * compared in ascending order using goog.array.defaultCompare. - * This won't work for keys that get renamed by the compiler. So use - * {'foo': 1, 'bar': 2} rather than {foo: 1, bar: 2}. - * @param {Array} arr An array of objects to sort. - * @param {string} key The object key to sort by. - * @param {Function=} opt_compareFn The function to use to compare key - * values. - */ -goog.array.sortObjectsByKey = function(arr, key, opt_compareFn) { - goog.array.sortByKey(arr, - function(obj) { return obj[key]; }, - opt_compareFn); -}; - - -/** - * Tells if the array is sorted. - * @param {!Array} arr The array. - * @param {?function(T,T):number=} opt_compareFn Function to compare the - * array elements. - * Should take 2 arguments to compare, and return a negative number, zero, - * or a positive number depending on whether the first argument is less - * than, equal to, or greater than the second. - * @param {boolean=} opt_strict If true no equal elements are allowed. - * @return {boolean} Whether the array is sorted. - * @template T - */ -goog.array.isSorted = function(arr, opt_compareFn, opt_strict) { - var compare = opt_compareFn || goog.array.defaultCompare; - for (var i = 1; i < arr.length; i++) { - var compareResult = compare(arr[i - 1], arr[i]); - if (compareResult > 0 || compareResult == 0 && opt_strict) { - return false; - } - } - return true; -}; - - -/** - * Compares two arrays for equality. Two arrays are considered equal if they - * have the same length and their corresponding elements are equal according to - * the comparison function. - * - * @param {goog.array.ArrayLike} arr1 The first array to compare. - * @param {goog.array.ArrayLike} arr2 The second array to compare. - * @param {Function=} opt_equalsFn Optional comparison function. - * Should take 2 arguments to compare, and return true if the arguments - * are equal. Defaults to {@link goog.array.defaultCompareEquality} which - * compares the elements using the built-in '===' operator. - * @return {boolean} Whether the two arrays are equal. - */ -goog.array.equals = function(arr1, arr2, opt_equalsFn) { - if (!goog.isArrayLike(arr1) || !goog.isArrayLike(arr2) || - arr1.length != arr2.length) { - return false; - } - var l = arr1.length; - var equalsFn = opt_equalsFn || goog.array.defaultCompareEquality; - for (var i = 0; i < l; i++) { - if (!equalsFn(arr1[i], arr2[i])) { - return false; - } - } - return true; -}; - - -/** - * 3-way array compare function. - * @param {!Array|!goog.array.ArrayLike} arr1 The first array to - * compare. - * @param {!Array|!goog.array.ArrayLike} arr2 The second array to - * compare. - * @param {function(VALUE, VALUE): number=} opt_compareFn Optional comparison - * function by which the array is to be ordered. Should take 2 arguments to - * compare, and return a negative number, zero, or a positive number - * depending on whether the first argument is less than, equal to, or - * greater than the second. - * @return {number} Negative number, zero, or a positive number depending on - * whether the first argument is less than, equal to, or greater than the - * second. - * @template VALUE - */ -goog.array.compare3 = function(arr1, arr2, opt_compareFn) { - var compare = opt_compareFn || goog.array.defaultCompare; - var l = Math.min(arr1.length, arr2.length); - for (var i = 0; i < l; i++) { - var result = compare(arr1[i], arr2[i]); - if (result != 0) { - return result; - } - } - return goog.array.defaultCompare(arr1.length, arr2.length); -}; - - -/** - * Compares its two arguments for order, using the built in < and > - * operators. - * @param {VALUE} a The first object to be compared. - * @param {VALUE} b The second object to be compared. - * @return {number} A negative number, zero, or a positive number as the first - * argument is less than, equal to, or greater than the second, - * respectively. - * @template VALUE - */ -goog.array.defaultCompare = function(a, b) { - return a > b ? 1 : a < b ? -1 : 0; -}; - - -/** - * Compares its two arguments for inverse order, using the built in < and > - * operators. - * @param {VALUE} a The first object to be compared. - * @param {VALUE} b The second object to be compared. - * @return {number} A negative number, zero, or a positive number as the first - * argument is greater than, equal to, or less than the second, - * respectively. - * @template VALUE - */ -goog.array.inverseDefaultCompare = function(a, b) { - return -goog.array.defaultCompare(a, b); -}; - - -/** - * Compares its two arguments for equality, using the built in === operator. - * @param {*} a The first object to compare. - * @param {*} b The second object to compare. - * @return {boolean} True if the two arguments are equal, false otherwise. - */ -goog.array.defaultCompareEquality = function(a, b) { - return a === b; -}; - - -/** - * Inserts a value into a sorted array. The array is not modified if the - * value is already present. - * @param {Array|goog.array.ArrayLike} array The array to modify. - * @param {VALUE} value The object to insert. - * @param {function(VALUE, VALUE): number=} opt_compareFn Optional comparison - * function by which the array is ordered. Should take 2 arguments to - * compare, and return a negative number, zero, or a positive number - * depending on whether the first argument is less than, equal to, or - * greater than the second. - * @return {boolean} True if an element was inserted. - * @template VALUE - */ -goog.array.binaryInsert = function(array, value, opt_compareFn) { - var index = goog.array.binarySearch(array, value, opt_compareFn); - if (index < 0) { - goog.array.insertAt(array, value, -(index + 1)); - return true; - } - return false; -}; - - -/** - * Removes a value from a sorted array. - * @param {!Array|!goog.array.ArrayLike} array The array to modify. - * @param {VALUE} value The object to remove. - * @param {function(VALUE, VALUE): number=} opt_compareFn Optional comparison - * function by which the array is ordered. Should take 2 arguments to - * compare, and return a negative number, zero, or a positive number - * depending on whether the first argument is less than, equal to, or - * greater than the second. - * @return {boolean} True if an element was removed. - * @template VALUE - */ -goog.array.binaryRemove = function(array, value, opt_compareFn) { - var index = goog.array.binarySearch(array, value, opt_compareFn); - return (index >= 0) ? goog.array.removeAt(array, index) : false; -}; - - -/** - * Splits an array into disjoint buckets according to a splitting function. - * @param {Array} array The array. - * @param {function(this:S, T,number,Array):?} sorter Function to call for - * every element. This takes 3 arguments (the element, the index and the - * array) and must return a valid object key (a string, number, etc), or - * undefined, if that object should not be placed in a bucket. - * @param {S=} opt_obj The object to be used as the value of 'this' within - * sorter. - * @return {!Object} An object, with keys being all of the unique return values - * of sorter, and values being arrays containing the items for - * which the splitter returned that key. - * @template T,S - */ -goog.array.bucket = function(array, sorter, opt_obj) { - var buckets = {}; - - for (var i = 0; i < array.length; i++) { - var value = array[i]; - var key = sorter.call(opt_obj, value, i, array); - if (goog.isDef(key)) { - // Push the value to the right bucket, creating it if necessary. - var bucket = buckets[key] || (buckets[key] = []); - bucket.push(value); - } - } - - return buckets; -}; - - -/** - * Creates a new object built from the provided array and the key-generation - * function. - * @param {Array|goog.array.ArrayLike} arr Array or array like object over - * which to iterate whose elements will be the values in the new object. - * @param {?function(this:S, T, number, ?) : string} keyFunc The function to - * call for every element. This function takes 3 arguments (the element, the - * index and the array) and should return a string that will be used as the - * key for the element in the new object. If the function returns the same - * key for more than one element, the value for that key is - * implementation-defined. - * @param {S=} opt_obj The object to be used as the value of 'this' - * within keyFunc. - * @return {!Object} The new object. - * @template T,S - */ -goog.array.toObject = function(arr, keyFunc, opt_obj) { - var ret = {}; - goog.array.forEach(arr, function(element, index) { - ret[keyFunc.call(opt_obj, element, index, arr)] = element; - }); - return ret; -}; - - -/** - * Creates a range of numbers in an arithmetic progression. - * - * Range takes 1, 2, or 3 arguments: - *
- * range(5) is the same as range(0, 5, 1) and produces [0, 1, 2, 3, 4]
- * range(2, 5) is the same as range(2, 5, 1) and produces [2, 3, 4]
- * range(-2, -5, -1) produces [-2, -3, -4]
- * range(-2, -5, 1) produces [], since stepping by 1 wouldn't ever reach -5.
- * 
- * - * @param {number} startOrEnd The starting value of the range if an end argument - * is provided. Otherwise, the start value is 0, and this is the end value. - * @param {number=} opt_end The optional end value of the range. - * @param {number=} opt_step The step size between range values. Defaults to 1 - * if opt_step is undefined or 0. - * @return {!Array} An array of numbers for the requested range. May be - * an empty array if adding the step would not converge toward the end - * value. - */ -goog.array.range = function(startOrEnd, opt_end, opt_step) { - var array = []; - var start = 0; - var end = startOrEnd; - var step = opt_step || 1; - if (opt_end !== undefined) { - start = startOrEnd; - end = opt_end; - } - - if (step * (end - start) < 0) { - // Sign mismatch: start + step will never reach the end value. - return []; - } - - if (step > 0) { - for (var i = start; i < end; i += step) { - array.push(i); - } - } else { - for (var i = start; i > end; i += step) { - array.push(i); - } - } - return array; -}; - - -/** - * Returns an array consisting of the given value repeated N times. - * - * @param {VALUE} value The value to repeat. - * @param {number} n The repeat count. - * @return {!Array} An array with the repeated value. - * @template VALUE - */ -goog.array.repeat = function(value, n) { - var array = []; - for (var i = 0; i < n; i++) { - array[i] = value; - } - return array; -}; - - -/** - * Returns an array consisting of every argument with all arrays - * expanded in-place recursively. - * - * @param {...*} var_args The values to flatten. - * @return {!Array} An array containing the flattened values. - */ -goog.array.flatten = function(var_args) { - var CHUNK_SIZE = 8192; - - var result = []; - for (var i = 0; i < arguments.length; i++) { - var element = arguments[i]; - if (goog.isArray(element)) { - for (var c = 0; c < element.length; c += CHUNK_SIZE) { - var chunk = goog.array.slice(element, c, c + CHUNK_SIZE); - var recurseResult = goog.array.flatten.apply(null, chunk); - for (var r = 0; r < recurseResult.length; r++) { - result.push(recurseResult[r]); - } - } - } else { - result.push(element); - } - } - return result; -}; - - -/** - * Rotates an array in-place. After calling this method, the element at - * index i will be the element previously at index (i - n) % - * array.length, for all values of i between 0 and array.length - 1, - * inclusive. - * - * For example, suppose list comprises [t, a, n, k, s]. After invoking - * rotate(array, 1) (or rotate(array, -4)), array will comprise [s, t, a, n, k]. - * - * @param {!Array} array The array to rotate. - * @param {number} n The amount to rotate. - * @return {!Array} The array. - * @template T - */ -goog.array.rotate = function(array, n) { - goog.asserts.assert(array.length != null); - - if (array.length) { - n %= array.length; - if (n > 0) { - goog.array.ARRAY_PROTOTYPE_.unshift.apply(array, array.splice(-n, n)); - } else if (n < 0) { - goog.array.ARRAY_PROTOTYPE_.push.apply(array, array.splice(0, -n)); - } - } - return array; -}; - - -/** - * Moves one item of an array to a new position keeping the order of the rest - * of the items. Example use case: keeping a list of JavaScript objects - * synchronized with the corresponding list of DOM elements after one of the - * elements has been dragged to a new position. - * @param {!(Array|Arguments|{length:number})} arr The array to modify. - * @param {number} fromIndex Index of the item to move between 0 and - * {@code arr.length - 1}. - * @param {number} toIndex Target index between 0 and {@code arr.length - 1}. - */ -goog.array.moveItem = function(arr, fromIndex, toIndex) { - goog.asserts.assert(fromIndex >= 0 && fromIndex < arr.length); - goog.asserts.assert(toIndex >= 0 && toIndex < arr.length); - // Remove 1 item at fromIndex. - var removedItems = goog.array.ARRAY_PROTOTYPE_.splice.call(arr, fromIndex, 1); - // Insert the removed item at toIndex. - goog.array.ARRAY_PROTOTYPE_.splice.call(arr, toIndex, 0, removedItems[0]); - // We don't use goog.array.insertAt and goog.array.removeAt, because they're - // significantly slower than splice. -}; - - -/** - * Creates a new array for which the element at position i is an array of the - * ith element of the provided arrays. The returned array will only be as long - * as the shortest array provided; additional values are ignored. For example, - * the result of zipping [1, 2] and [3, 4, 5] is [[1,3], [2, 4]]. - * - * This is similar to the zip() function in Python. See {@link - * http://docs.python.org/library/functions.html#zip} - * - * @param {...!goog.array.ArrayLike} var_args Arrays to be combined. - * @return {!Array>} A new array of arrays created from - * provided arrays. - */ -goog.array.zip = function(var_args) { - if (!arguments.length) { - return []; - } - var result = []; - for (var i = 0; true; i++) { - var value = []; - for (var j = 0; j < arguments.length; j++) { - var arr = arguments[j]; - // If i is larger than the array length, this is the shortest array. - if (i >= arr.length) { - return result; - } - value.push(arr[i]); - } - result.push(value); - } -}; - - -/** - * Shuffles the values in the specified array using the Fisher-Yates in-place - * shuffle (also known as the Knuth Shuffle). By default, calls Math.random() - * and so resets the state of that random number generator. Similarly, may reset - * the state of the any other specified random number generator. - * - * Runtime: O(n) - * - * @param {!Array} arr The array to be shuffled. - * @param {function():number=} opt_randFn Optional random function to use for - * shuffling. - * Takes no arguments, and returns a random number on the interval [0, 1). - * Defaults to Math.random() using JavaScript's built-in Math library. - */ -goog.array.shuffle = function(arr, opt_randFn) { - var randFn = opt_randFn || Math.random; - - for (var i = arr.length - 1; i > 0; i--) { - // Choose a random array index in [0, i] (inclusive with i). - var j = Math.floor(randFn() * (i + 1)); - - var tmp = arr[i]; - arr[i] = arr[j]; - arr[j] = tmp; - } -}; - - -/** - * Returns a new array of elements from arr, based on the indexes of elements - * provided by index_arr. For example, the result of index copying - * ['a', 'b', 'c'] with index_arr [1,0,0,2] is ['b', 'a', 'a', 'c']. - * - * @param {!Array} arr The array to get a indexed copy from. - * @param {!Array} index_arr An array of indexes to get from arr. - * @return {!Array} A new array of elements from arr in index_arr order. - * @template T - */ -goog.array.copyByIndex = function(arr, index_arr) { - var result = []; - goog.array.forEach(index_arr, function(index) { - result.push(arr[index]); - }); - return result; -}; diff --git a/src/database/third_party/closure-library/closure/goog/array/array_test.html b/src/database/third_party/closure-library/closure/goog/array/array_test.html deleted file mode 100644 index 654d8f3da73..00000000000 --- a/src/database/third_party/closure-library/closure/goog/array/array_test.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - Closure Unit Tests - goog.array - - - - - -
-
- - diff --git a/src/database/third_party/closure-library/closure/goog/array/array_test.js b/src/database/third_party/closure-library/closure/goog/array/array_test.js deleted file mode 100644 index 3ec9ef229b6..00000000000 --- a/src/database/third_party/closure-library/closure/goog/array/array_test.js +++ /dev/null @@ -1,1792 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.arrayTest'); -goog.setTestOnly('goog.arrayTest'); - -goog.require('goog.array'); -goog.require('goog.dom'); -goog.require('goog.testing.PropertyReplacer'); -goog.require('goog.testing.jsunit'); -goog.require('goog.testing.recordFunction'); - -function testArrayLast() { - assertEquals(goog.array.last([1, 2, 3]), 3); - assertEquals(goog.array.last([1]), 1); - assertUndefined(goog.array.last([])); -} - -function testArrayLastWhenDeleted() { - var a = [1, 2, 3]; - delete a[2]; - assertUndefined(goog.array.last(a)); -} - -function testArrayIndexOf() { - assertEquals(goog.array.indexOf([0, 1, 2, 3], 1), 1); - assertEquals(goog.array.indexOf([0, 1, 1, 1], 1), 1); - assertEquals(goog.array.indexOf([0, 1, 2, 3], 4), -1); - assertEquals(goog.array.indexOf([0, 1, 2, 3], 1, 1), 1); - assertEquals(goog.array.indexOf([0, 1, 2, 3], 1, 2), -1); - assertEquals(goog.array.indexOf([0, 1, 2, 3], 1, -3), 1); - assertEquals(goog.array.indexOf([0, 1, 2, 3], 1, -2), -1); -} - -function testArrayIndexOfOmitsDeleted() { - var a = [0, 1, 2, 3]; - delete a[1]; - delete a[3]; - assertEquals(goog.array.indexOf(a, undefined), -1); -} - -function testArrayIndexOfString() { - assertEquals(goog.array.indexOf('abcd', 'd'), 3); - assertEquals(goog.array.indexOf('abbb', 'b', 2), 2); - assertEquals(goog.array.indexOf('abcd', 'e'), -1); - assertEquals(goog.array.indexOf('abcd', 'cd'), -1); - assertEquals(goog.array.indexOf('0123', 1), -1); -} - -function testArrayLastIndexOf() { - assertEquals(goog.array.lastIndexOf([0, 1, 2, 3], 1), 1); - assertEquals(goog.array.lastIndexOf([0, 1, 1, 1], 1), 3); - assertEquals(goog.array.lastIndexOf([0, 1, 1, 1], 1, 2), 2); -} - -function testArrayLastIndexOfOmitsDeleted() { - var a = [0, 1, 2, 3]; - delete a[1]; - delete a[3]; - assertEquals(goog.array.lastIndexOf(a, undefined), -1); -} - -function testArrayLastIndexOfString() { - assertEquals(goog.array.lastIndexOf('abcd', 'b'), 1); - assertEquals(goog.array.lastIndexOf('abbb', 'b'), 3); - assertEquals(goog.array.lastIndexOf('abbb', 'b', 2), 2); - assertEquals(goog.array.lastIndexOf('abcd', 'cd'), -1); - assertEquals(goog.array.lastIndexOf('0123', 1), -1); -} - -function testArrayForEachBasic() { - var s = ''; - var a = ['a', 'b', 'c', 'd']; - goog.array.forEach(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('Index is not a number', 'number', typeof index); - s += val + index; - }); - assertEquals('a0b1c2d3', s); -} - -function testArrayForEachWithEmptyArray() { - var a = new Array(100); - goog.array.forEach(a, function(val, index, a2) { - fail('The function should not be called since no values were assigned.'); - }); -} - -function testArrayForEachWithOnlySomeValuesAsigned() { - var count = 0; - var a = new Array(1000); - a[100] = undefined; - goog.array.forEach(a, function(val, index, a2) { - assertEquals(100, index); - count++; - }); - assertEquals('Should only call function when a value of array was assigned.', - 1, count); -} - -function testArrayForEachWithArrayLikeObject() { - var counter = goog.testing.recordFunction(); - var a = { - 'length': 1, - '0': 0, - '100': 100, - '101': 102 - }; - goog.array.forEach(a, counter); - assertEquals('Number of calls should not exceed the value of its length', 1, - counter.getCallCount()); -} - -function testArrayForEachOmitsDeleted() { - var s = ''; - var a = ['a', 'b', 'c', 'd']; - delete a[1]; - delete a[3]; - goog.array.forEach(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('number', typeof index); - s += val + index; - }); - assertEquals('a0c2', s); -} - -function testArrayForEachScope() { - var scope = {}; - var a = ['a', 'b', 'c', 'd']; - goog.array.forEach(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('number', typeof index); - assertEquals(this, scope); - }, scope); -} - -function testArrayForEachRight() { - var s = ''; - var a = ['a', 'b', 'c', 'd']; - goog.array.forEachRight(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('number', typeof index); - s += val + String(index); - }); - assertEquals('d3c2b1a0', s); -} - -function testArrayForEachRightOmitsDeleted() { - var s = ''; - var a = ['a', 'b', 'c', 'd']; - delete a[1]; - delete a[3]; - goog.array.forEachRight(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('number', typeof index); - assertEquals('string', typeof val); - s += val + String(index); - }); - assertEquals('c2a0', s); -} - -function testArrayFilter() { - var a = [0, 1, 2, 3]; - a = goog.array.filter(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val > 1; - }); - assertArrayEquals([2, 3], a); -} - -function testArrayFilterOmitsDeleted() { - var a = [0, 1, 2, 3]; - delete a[1]; - delete a[3]; - a = goog.array.filter(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('number', typeof val); - assertEquals('index is not a number', 'number', typeof index); - return val > 1; - }); - assertArrayEquals([2], a); -} - -function testArrayFilterPreservesValues() { - var a = [0, 1, 2, 3]; - a = goog.array.filter(a, function(val, index, a2) { - assertEquals(a, a2); - // sometimes functions might be evil and do something like this, but we - // should still use the original values when returning the filtered array - a2[index] = a2[index] - 1; - return a2[index] >= 1; - }); - assertArrayEquals([2, 3], a); -} - -function testArrayMap() { - var a = [0, 1, 2, 3]; - var result = goog.array.map(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val * val; - }); - assertArrayEquals([0, 1, 4, 9], result); -} - -function testArrayMapOmitsDeleted() { - var a = [0, 1, 2, 3]; - delete a[1]; - delete a[3]; - var result = goog.array.map(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('number', typeof val); - assertEquals('index is not a number', 'number', typeof index); - return val * val; - }); - var expected = [0, 1, 4, 9]; - delete expected[1]; - delete expected[3]; - - assertArrayEquals(expected, result); - assertFalse('1' in result); - assertFalse('3' in result); -} - -function testArrayReduce() { - var a = [0, 1, 2, 3]; - assertEquals(6, goog.array.reduce(a, function(rval, val, i, arr) { - assertEquals('number', typeof i); - assertEquals(a, arr); - return rval + val; - }, 0)); - - var scope = { - last: 0, - testFn: function(r, v, i, arr) { - assertEquals('number', typeof i); - assertEquals(a, arr); - var l = this.last; - this.last = r + v; - return this.last + l; - } - }; - - assertEquals(10, goog.array.reduce(a, scope.testFn, 0, scope)); -} - -function testArrayReduceOmitDeleted() { - var a = [0, 1, 2, 3]; - delete a[1]; - delete a[3]; - assertEquals(2, goog.array.reduce(a, function(rval, val, i, arr) { - assertEquals('number', typeof i); - assertEquals(a, arr); - return rval + val; - }, 0)); - - var scope = { - last: 0, - testFn: function(r, v, i, arr) { - assertEquals('number', typeof i); - assertEquals(a, arr); - var l = this.last; - this.last = r + v; - return this.last + l; - } - }; - - assertEquals(2, goog.array.reduce(a, scope.testFn, 0, scope)); -} - -function testArrayReducePreviousValuePatch(){ - assertEquals(3, goog.array.reduce([1,2], function(p, c){ - return p + c; - })); -} - -function testArrayReduceRight() { - var a = [0, 1, 2, 3, 4]; - assertEquals('43210', goog.array.reduceRight(a, function(rval, val, i, arr) { - assertEquals('number', typeof i); - assertEquals(a, arr); - return rval + val; - }, '')); - - var scope = { - last: '', - testFn: function(r, v, i, arr) { - assertEquals('number', typeof i); - assertEquals(a, arr); - var l = this.last; - this.last = v; - return r + v + l; - } - }; - - a = ['a', 'b', 'c']; - assertEquals('_cbcab', goog.array.reduceRight(a, scope.testFn, '_', scope)); -} - -function testArrayReduceRightOmitsDeleted() { - var a = [0, 1, 2, 3, 4]; - delete a[1]; - delete a[4]; - assertEquals('320', goog.array.reduceRight(a, function(rval, val, i, arr) { - assertEquals('number', typeof i); - assertEquals(a, arr); - return rval + val; - }, '')); - - scope = { - last: '', - testFn: function(r, v, i, arr) { - assertEquals('number', typeof i); - assertEquals(a, arr); - var l = this.last; - this.last = v; - return r + v + l; - } - }; - - a = ['a', 'b', 'c', 'd']; - delete a[1]; - delete a[3]; - assertEquals('_cac', goog.array.reduceRight(a, scope.testFn, '_', scope)); -} - -function testArrayFind() { - var a = [0, 1, 2, 3]; - var b = goog.array.find(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val > 1; - }); - assertEquals(2, b); - - b = goog.array.find(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val > 100; - }); - assertNull(b); - - a = 'abCD'; - b = goog.array.find(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val >= 'A' && val <= 'Z'; - }); - assertEquals('C', b); - - a = 'abcd'; - b = goog.array.find(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val >= 'A' && val <= 'Z'; - }); - assertNull(b); -} - -function testArrayFindOmitsDeleted() { - var a = [0, 1, 2, 3]; - delete a[1]; - delete a[3]; - var b = goog.array.find(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val > 1; - }); - - assertEquals(2, b); - b = goog.array.find(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val > 100; - }); - assertNull(b); -} - -function testArrayFindIndex() { - var a = [0, 1, 2, 3]; - var b = goog.array.findIndex(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val > 1; - }); - assertEquals(2, b); - - b = goog.array.findIndex(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val > 100; - }); - assertEquals(-1, b); - - a = 'abCD'; - b = goog.array.findIndex(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val >= 'A' && val <= 'Z'; - }); - assertEquals(2, b); - - a = 'abcd'; - b = goog.array.findIndex(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val >= 'A' && val <= 'Z'; - }); - assertEquals(-1, b); -} - -function testArrayFindIndexOmitsDeleted() { - var a = [0, 1, 2, 3]; - delete a[1]; - delete a[3]; - var b = goog.array.findIndex(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val > 1; - }); - assertEquals(2, b); - - b = goog.array.findIndex(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val > 100; - }); - assertEquals(-1, b); -} - -function testArrayFindRight() { - var a = [0, 1, 2, 3]; - var b = goog.array.findRight(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val < 3; - }); - assertEquals(2, b); - b = goog.array.findRight(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val > 100; - }); - assertNull(b); -} - -function testArrayFindRightOmitsDeleted() { - var a = [0, 1, 2, 3]; - delete a[1]; - delete a[3]; - var b = goog.array.findRight(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val < 3; - }); - assertEquals(2, b); - b = goog.array.findRight(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val > 100; - }); - assertNull(b); -} - -function testArrayFindIndexRight() { - var a = [0, 1, 2, 3]; - var b = goog.array.findIndexRight(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val < 3; - }); - assertEquals(2, b); - - b = goog.array.findIndexRight(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val > 100; - }); - assertEquals(-1, b); - - a = 'abCD'; - b = goog.array.findIndexRight(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val >= 'a' && val <= 'z'; - }); - assertEquals(1, b); - - a = 'abcd'; - b = goog.array.findIndexRight(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val >= 'A' && val <= 'Z'; - }); - assertEquals(-1, b); -} - -function testArrayFindIndexRightOmitsDeleted() { - var a = [0, 1, 2, 3]; - delete a[1]; - delete a[3]; - var b = goog.array.findIndexRight(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val < 3; - }); - assertEquals(2, b); - b = goog.array.findIndexRight(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val > 100; - }); - assertEquals(-1, b); -} - -function testArraySome() { - var a = [0, 1, 2, 3]; - var b = goog.array.some(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val > 1; - }); - assertTrue(b); - b = goog.array.some(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val > 100; - }); - assertFalse(b); -} - -function testArraySomeOmitsDeleted() { - var a = [0, 1, 2, 3]; - delete a[1]; - delete a[3]; - var b = goog.array.some(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('number', typeof val); - assertEquals('index is not a number', 'number', typeof index); - return val > 1; - }); - assertTrue(b); - b = goog.array.some(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('number', typeof val); - assertEquals('index is not a number', 'number', typeof index); - return val > 100; - }); - assertFalse(b); -} - -function testArrayEvery() { - var a = [0, 1, 2, 3]; - var b = goog.array.every(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val >= 0; - }); - assertTrue(b); - b = goog.array.every(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val > 1; - }); - assertFalse(b); -} - -function testArrayEveryOmitsDeleted() { - var a = [0, 1, 2, 3]; - delete a[1]; - delete a[3]; - var b = goog.array.every(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('number', typeof val); - assertEquals('index is not a number', 'number', typeof index); - return val >= 0; - }); - assertTrue(b); - b = goog.array.every(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('number', typeof val); - assertEquals('index is not a number', 'number', typeof index); - return val > 1; - }); - assertFalse(b); -} - -function testArrayCount() { - var a = [0, 1, 2, 3, 4]; - var context = {}; - assertEquals(3, goog.array.count(a, function(element, index, array) { - assertTrue(goog.isNumber(index)); - assertEquals(a, array); - assertEquals(context, this); - return element % 2 == 0; - }, context)); - - delete a[2]; - assertEquals('deleted element is ignored', 4, - goog.array.count(a, function() { - return true; - })); -} - -function testArrayContains() { - var a = [0, 1, 2, 3]; - assertTrue('contain, Should contain 3', goog.array.contains(a, 3)); - assertFalse('contain, Should not contain 4', goog.array.contains(a, 4)); - - var s = 'abcd'; - assertTrue('contain, Should contain d', goog.array.contains(s, 'd')); - assertFalse('contain, Should not contain e', goog.array.contains(s, 'e')); -} - -function testArrayContainsOmitsDeleted() { - var a = [0, 1, 2, 3]; - delete a[1]; - delete a[3]; - assertFalse('should not contain undefined', - goog.array.contains(a, undefined)); -} - -function testArrayInsert() { - var a = [0, 1, 2, 3]; - - goog.array.insert(a, 4); - assertEquals('insert, Should append 4', a[4], 4); - goog.array.insert(a, 3); - assertEquals('insert, Should not append 3', a.length, 5); - assertNotEquals('insert, Should not append 3', a[a.length - 1], 3); -} - -function testArrayInsertAt() { - var a = [0, 1, 2, 3]; - - goog.array.insertAt(a, 4, 2); - assertArrayEquals('insertAt, insert in middle', [0, 1, 4, 2, 3], a); - goog.array.insertAt(a, 5, 10); - assertArrayEquals('insertAt, too large value should append', - [0, 1, 4, 2, 3, 5], a); - goog.array.insertAt(a, 6); - assertArrayEquals('insertAt, null/undefined value should insert at 0', - [6, 0, 1, 4, 2, 3, 5], a); - goog.array.insertAt(a, 7, -2); - assertArrayEquals('insertAt, negative values start from end', - [6, 0, 1, 4, 2, 7, 3, 5], a); -} - -function testArrayInsertArrayAt() { - var a = [2, 5]; - goog.array.insertArrayAt(a, [3, 4], 1); - assertArrayEquals('insertArrayAt, insert in middle', [2, 3, 4, 5], a); - goog.array.insertArrayAt(a, [0, 1], 0); - assertArrayEquals('insertArrayAt, insert at beginning', - [0, 1, 2, 3, 4, 5], a); - goog.array.insertArrayAt(a, [6, 7], 6); - assertArrayEquals('insertArrayAt, insert at end', - [0, 1, 2, 3, 4, 5, 6, 7], a); - goog.array.insertArrayAt(a, ['x'], 4); - assertArrayEquals('insertArrayAt, insert one element', - [0, 1, 2, 3, 'x', 4, 5, 6, 7], a); - goog.array.insertArrayAt(a, [], 4); - assertArrayEquals('insertArrayAt, insert 0 elements', - [0, 1, 2, 3, 'x', 4, 5, 6, 7], a); - goog.array.insertArrayAt(a, ['y', 'z']); - assertArrayEquals('insertArrayAt, undefined value should insert at 0', - ['y', 'z', 0, 1, 2, 3, 'x', 4, 5, 6, 7], a); - goog.array.insertArrayAt(a, ['a'], null); - assertArrayEquals('insertArrayAt, null value should insert at 0', - ['a', 'y', 'z', 0, 1, 2, 3, 'x', 4, 5, 6, 7], a); - goog.array.insertArrayAt(a, ['b'], 100); - assertArrayEquals('insertArrayAt, too large value should append', - ['a', 'y', 'z', 0, 1, 2, 3, 'x', 4, 5, 6, 7, 'b'], a); - goog.array.insertArrayAt(a, ['c', 'd'], -2); - assertArrayEquals('insertArrayAt, negative values start from end', - ['a', 'y', 'z', 0, 1, 2, 3, 'x', 4, 5, 6, 'c', 'd', 7, 'b'], a); -} - -function testArrayInsertBefore() { - var a = ['a', 'b', 'c', 'd']; - goog.array.insertBefore(a, 'e', 'b'); - assertArrayEquals('insertBefore, with existing element', - ['a', 'e', 'b', 'c', 'd'], a); - goog.array.insertBefore(a, 'f', 'x'); - assertArrayEquals('insertBefore, with non existing element', - ['a', 'e', 'b', 'c', 'd', 'f'], a); -} - -function testArrayRemove() { - var a = ['a', 'b', 'c', 'd']; - goog.array.remove(a, 'c'); - assertArrayEquals('remove, remove existing element', ['a', 'b', 'd'], a); - goog.array.remove(a, 'x'); - assertArrayEquals('remove, remove non existing element', ['a', 'b', 'd'], a); -} - -function testArrayRemoveAt() { - var a = [0, 1, 2, 3]; - goog.array.removeAt(a, 2); - assertArrayEquals('removeAt, remove existing index', [0, 1, 3], a); - a = [0, 1, 2, 3]; - goog.array.removeAt(a, 10); - assertArrayEquals('removeAt, remove non existing index', [0, 1, 2, 3], a); - a = [0, 1, 2, 3]; - goog.array.removeAt(a, -2); - assertArrayEquals('removeAt, remove with negative index', [0, 1, 3], a); -} - -function testArrayRemoveIf() { - var a = [0, 1, 2, 3]; - var b = goog.array.removeIf(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val > 1; - }); - assertArrayEquals('removeIf, remove existing element', [0, 1, 3], a); - - a = [0, 1, 2, 3]; - var b = goog.array.removeIf(a, function(val, index, a2) { - assertEquals(a, a2); - assertEquals('index is not a number', 'number', typeof index); - return val > 100; - }); - assertArrayEquals('removeIf, remove non-existing element', [0, 1, 2, 3], a); -} - -function testArrayClone() { - var a = [0, 1, 2, 3]; - var a2 = goog.array.clone(a); - assertArrayEquals('clone, should be equal', a, a2); - - var b = {0: 0, 1: 1, 2: 2, 3: 3, length: 4}; - var b2 = goog.array.clone(b); - for (var i = 0; i < b.length; i++) { - assertEquals('clone, should be equal', b[i], b2[i]); - } -} - -function testToArray() { - var a = [0, 1, 2, 3]; - var a2 = goog.array.toArray(a); - assertArrayEquals('toArray, should be equal', a, a2); - - var b = {0: 0, 1: 1, 2: 2, 3: 3, length: 4}; - var b2 = goog.array.toArray(b); - for (var i = 0; i < b.length; i++) { - assertEquals('toArray, should be equal', b[i], b2[i]); - } -} - -function testToArrayOnNonArrayLike() { - var nonArrayLike = {}; - assertArrayEquals('toArray on non ArrayLike should return an empty array', - [], goog.array.toArray(nonArrayLike)); - - var nonArrayLike2 = {length: 'hello world'}; - assertArrayEquals('toArray on non ArrayLike should return an empty array', - [], goog.array.toArray(nonArrayLike2)); -} - -function testExtend() { - var a = [0, 1]; - goog.array.extend(a, [2, 3]); - var a2 = [0, 1, 2, 3]; - assertArrayEquals('extend, should be equal', a, a2); - - var b = [0, 1]; - goog.array.extend(b, 2); - var b2 = [0, 1, 2]; - assertArrayEquals('extend, should be equal', b, b2); - - a = [0, 1]; - goog.array.extend(a, [2, 3], [4, 5]); - a2 = [0, 1, 2, 3, 4, 5]; - assertArrayEquals('extend, should be equal', a, a2); - - b = [0, 1]; - goog.array.extend(b, 2, 3); - b2 = [0, 1, 2, 3]; - assertArrayEquals('extend, should be equal', b, b2); - - var c = [0, 1]; - goog.array.extend(c, 2, [3, 4], 5, [6]); - var c2 = [0, 1, 2, 3, 4, 5, 6]; - assertArrayEquals('extend, should be equal', c, c2); - - var d = [0, 1]; - var arrayLikeObject = {0: 2, 1: 3, length: 2}; - goog.array.extend(d, arrayLikeObject); - var d2 = [0, 1, 2, 3]; - assertArrayEquals('extend, should be equal', d, d2); - - var e = [0, 1]; - var emptyArrayLikeObject = {length: 0}; - goog.array.extend(e, emptyArrayLikeObject); - assertArrayEquals('extend, should be equal', e, e); - - var f = [0, 1]; - var length3ArrayLikeObject = {0: 2, 1: 4, 2: 8, length: 3}; - goog.array.extend(f, length3ArrayLikeObject, length3ArrayLikeObject); - var f2 = [0, 1, 2, 4, 8, 2, 4, 8]; - assertArrayEquals('extend, should be equal', f2, f); - - var result = []; - var i = 1000000; - var bigArray = Array(i); - while (i--) { - bigArray[i] = i; - } - goog.array.extend(result, bigArray); - assertArrayEquals(bigArray, result); -} - -function testExtendWithArguments() { - function f() { - return arguments; - } - var a = [0]; - var a2 = [0, 1, 2, 3, 4, 5]; - goog.array.extend(a, f(1, 2, 3), f(4, 5)); - assertArrayEquals('extend, should be equal', a, a2); -} - -function testExtendWithQuerySelector() { - var a = [0]; - var d = goog.dom.getElementsByTagNameAndClass('div', 'foo'); - goog.array.extend(a, d); - assertEquals(2, a.length); -} - -function testArraySplice() { - var a = [0, 1, 2, 3]; - goog.array.splice(a, 1, 0, 4); - assertArrayEquals([0, 4, 1, 2, 3], a); - goog.array.splice(a, 1, 1, 5); - assertArrayEquals([0, 5, 1, 2, 3], a); - goog.array.splice(a, 1, 1); - assertArrayEquals([0, 1, 2, 3], a); - // var args - goog.array.splice(a, 1, 1, 4, 5, 6); - assertArrayEquals([0, 4, 5, 6, 2, 3], a); -} - -function testArraySlice() { - var a = [0, 1, 2, 3]; - a = goog.array.slice(a, 1, 3); - assertArrayEquals([1, 2], a); - a = [0, 1, 2, 3]; - a = goog.array.slice(a, 1, 6); - assertArrayEquals('slice, with too large end', [1, 2, 3], a); - a = [0, 1, 2, 3]; - a = goog.array.slice(a, 1, -1); - assertArrayEquals('slice, with negative end', [1, 2], a); - a = [0, 1, 2, 3]; - a = goog.array.slice(a, -2, 3); - assertArrayEquals('slice, with negative start', [2], a); -} - -function assertRemovedDuplicates(expected, original) { - var tempArr = goog.array.clone(original); - goog.array.removeDuplicates(tempArr); - assertArrayEquals(expected, tempArr); -} - -function testRemoveDuplicates() { - assertRemovedDuplicates([1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6]); - assertRemovedDuplicates([9, 4, 2, 1, 3, 6, 0, -9], - [9, 4, 2, 4, 4, 2, 9, 1, 3, 6, 0, -9]); - assertRemovedDuplicates(['four', 'one', 'two', 'three', 'THREE'], - ['four', 'one', 'two', 'one', 'three', 'THREE', 'four', 'two']); - assertRemovedDuplicates([], []); - assertRemovedDuplicates( - ['abc', 'hasOwnProperty', 'toString'], - ['abc', 'hasOwnProperty', 'toString', 'abc']); - - var o1 = {}, o2 = {}, o3 = {}, o4 = {}; - assertRemovedDuplicates([o1, o2, o3, o4], [o1, o1, o2, o3, o2, o4]); - - // Mixed object types. - assertRemovedDuplicates([1, '1', 2, '2'], [1, '1', 2, '2']); - assertRemovedDuplicates([true, 'true', false, 'false'], - [true, 'true', false, 'false']); - assertRemovedDuplicates(['foo'], [String('foo'), 'foo']); - assertRemovedDuplicates([12], [Number(12), 12]); - - var obj = {}; - var uid = goog.getUid(obj); - assertRemovedDuplicates([obj, uid], [obj, uid]); -} - -function testRemoveDuplicates_customHashFn() { - var object1 = {key: 'foo'}; - var object2 = {key: 'bar'}; - var dupeObject = {key: 'foo'}; - var array = [object1, object2, dupeObject, 'bar']; - var hashFn = function(object) { - return goog.isObject(object) ? object.key : - (typeof object).charAt(0) + object; - }; - goog.array.removeDuplicates(array, /* opt_rv */ undefined, hashFn); - assertArrayEquals([object1, object2, 'bar'], array); -} - -function testBinaryInsertRemove() { - var makeChecker = function(array, fn, opt_compareFn) { - return function(value, expectResult, expectArray) { - var result = fn(array, value, opt_compareFn); - assertEquals(expectResult, result); - assertArrayEquals(expectArray, array); - } - }; - - var a = []; - var check = makeChecker(a, goog.array.binaryInsert); - check(3, true, [3]); - check(3, false, [3]); - check(1, true, [1, 3]); - check(5, true, [1, 3, 5]); - check(2, true, [1, 2, 3, 5]); - check(2, false, [1, 2, 3, 5]); - - check = makeChecker(a, goog.array.binaryRemove); - check(0, false, [1, 2, 3, 5]); - check(3, true, [1, 2, 5]); - check(1, true, [2, 5]); - check(5, true, [2]); - check(2, true, []); - check(2, false, []); - - // test with custom comparison function, which reverse orders numbers - var revNumCompare = function(a, b) { return b - a; }; - - check = makeChecker(a, goog.array.binaryInsert, revNumCompare); - check(3, true, [3]); - check(3, false, [3]); - check(1, true, [3, 1]); - check(5, true, [5, 3, 1]); - check(2, true, [5, 3, 2, 1]); - check(2, false, [5, 3, 2, 1]); - - check = makeChecker(a, goog.array.binaryRemove, revNumCompare); - check(0, false, [5, 3, 2, 1]); - check(3, true, [5, 2, 1]); - check(1, true, [5, 2]); - check(5, true, [2]); - check(2, true, []); - check(2, false, []); -} - -function testBinarySearch() { - var insertionPoint = function(position) { return -(position + 1)}; - var pos; - - // test default comparison on array of String(s) - var a = ['1000', '9', 'AB', 'ABC', 'ABCABC', 'ABD', 'ABDA', 'B', 'B', 'B', - 'C', 'CA', 'CC', 'ZZZ', 'ab', 'abc', 'abcabc', 'abd', 'abda', 'b', - 'c', 'ca', 'cc', 'zzz']; - - assertEquals('\'1000\' should be found at index 0', 0, - goog.array.binarySearch(a, '1000')); - assertEquals('\'zzz\' should be found at index ' + (a.length - 1), - a.length - 1, goog.array.binarySearch(a, 'zzz')); - assertEquals('\'C\' should be found at index 10', 10, - goog.array.binarySearch(a, 'C')); - pos = goog.array.binarySearch(a, 'B'); - assertTrue('\'B\' should be found at index 7 || 8 || 9', pos == 7 || - pos == 8 || pos == 9); - pos = goog.array.binarySearch(a, '100'); - assertTrue('\'100\' should not be found', pos < 0); - assertEquals('\'100\' should have an insertion point of 0', 0, - insertionPoint(pos)); - pos = goog.array.binarySearch(a, 'zzz0'); - assertTrue('\'zzz0\' should not be found', pos < 0); - assertEquals('\'zzz0\' should have an insertion point of ' + (a.length), - a.length, insertionPoint(pos)); - pos = goog.array.binarySearch(a, 'BA'); - assertTrue('\'BA\' should not be found', pos < 0); - assertEquals('\'BA\' should have an insertion point of 10', 10, - insertionPoint(pos)); - - // test 0 length array with default comparison - var b = []; - - pos = goog.array.binarySearch(b, 'a'); - assertTrue('\'a\' should not be found', pos < 0); - assertEquals('\'a\' should have an insertion point of 0', 0, - insertionPoint(pos)); - - // test single element array with default lexiographical comparison - var c = ['only item']; - - assertEquals('\'only item\' should be found at index 0', 0, - goog.array.binarySearch(c, 'only item')); - pos = goog.array.binarySearch(c, 'a'); - assertTrue('\'a\' should not be found', pos < 0); - assertEquals('\'a\' should have an insertion point of 0', 0, - insertionPoint(pos)); - pos = goog.array.binarySearch(c, 'z'); - assertTrue('\'z\' should not be found', pos < 0); - assertEquals('\'z\' should have an insertion point of 1', 1, - insertionPoint(pos)); - - // test default comparison on array of Number(s) - var d = [-897123.9, -321434.58758, -1321.3124, -324, -9, -3, 0, 0, 0, - 0.31255, 5, 142.88888708, 334, 342, 453, 54254]; - - assertEquals('-897123.9 should be found at index 0', 0, - goog.array.binarySearch(d, -897123.9)); - assertEquals('54254 should be found at index ' + (a.length - 1), - d.length - 1, goog.array.binarySearch(d, 54254)); - assertEquals( - '-3 should be found at index 5', 5, goog.array.binarySearch(d, -3)); - pos = goog.array.binarySearch(d, 0); - assertTrue('0 should be found at index 6 || 7 || 8', pos == 6 || - pos == 7 || pos == 8); - pos = goog.array.binarySearch(d, -900000); - assertTrue('-900000 should not be found', pos < 0); - assertEquals('-900000 should have an insertion point of 0', 0, - insertionPoint(pos)); - pos = goog.array.binarySearch(d, '54255'); - assertTrue('54255 should not be found', pos < 0); - assertEquals('54255 should have an insertion point of ' + (d.length), - d.length, insertionPoint(pos)); - pos = goog.array.binarySearch(d, 1.1); - assertTrue('1.1 should not be found', pos < 0); - assertEquals('1.1 should have an insertion point of 10', 10, - insertionPoint(pos)); - - // test with custom comparison function, which reverse orders numbers - var revNumCompare = function(a, b) { return b - a; }; - - var e = [54254, 453, 342, 334, 142.88888708, 5, 0.31255, 0, 0, 0, -3, - -9, -324, -1321.3124, -321434.58758, -897123.9]; - - assertEquals('54254 should be found at index 0', 0, - goog.array.binarySearch(e, 54254, revNumCompare)); - assertEquals('-897123.9 should be found at index ' + (e.length - 1), - e.length - 1, goog.array.binarySearch(e, -897123.9, revNumCompare)); - assertEquals('-3 should be found at index 10', 10, - goog.array.binarySearch(e, -3, revNumCompare)); - pos = goog.array.binarySearch(e, 0, revNumCompare); - assertTrue('0 should be found at index || 10', pos == 7 || - pos == 9 || pos == 10); - pos = goog.array.binarySearch(e, 54254.1, revNumCompare); - assertTrue('54254.1 should not be found', pos < 0); - assertEquals('54254.1 should have an insertion point of 0', 0, - insertionPoint(pos)); - pos = goog.array.binarySearch(e, -897124, revNumCompare); - assertTrue('-897124 should not be found', pos < 0); - assertEquals('-897124 should have an insertion point of ' + (e.length), - e.length, insertionPoint(pos)); - pos = goog.array.binarySearch(e, 1.1, revNumCompare); - assertTrue('1.1 should not be found', pos < 0); - assertEquals('1.1 should have an insertion point of 6', 6, - insertionPoint(pos)); - - // test 0 length array with custom comparison function - var f = []; - - pos = goog.array.binarySearch(f, 0, revNumCompare); - assertTrue('0 should not be found', pos < 0); - assertEquals('0 should have an insertion point of 0', 0, - insertionPoint(pos)); - - // test single element array with custom comparison function - var g = [1]; - - assertEquals('1 should be found at index 0', 0, goog.array.binarySearch(g, 1, - revNumCompare)); - pos = goog.array.binarySearch(g, 2, revNumCompare); - assertTrue('2 should not be found', pos < 0); - assertEquals('2 should have an insertion point of 0', 0, - insertionPoint(pos)); - pos = goog.array.binarySearch(g, 0, revNumCompare); - assertTrue('0 should not be found', pos < 0); - assertEquals('0 should have an insertion point of 1', 1, - insertionPoint(pos)); - - assertEquals('binarySearch should find the index of the first 0', - 0, goog.array.binarySearch([0, 0, 1], 0)); - assertEquals('binarySearch should find the index of the first 1', - 1, goog.array.binarySearch([0, 1, 1], 1)); -} - - -function testBinarySearchPerformance() { - // Ensure that Array#slice, Function#apply and Function#call are not called - // from within binarySearch, since they have performance implications in IE. - - var propertyReplacer = new goog.testing.PropertyReplacer(); - propertyReplacer.replace(Array.prototype, 'slice', function() { - fail('Should not call Array#slice from binary search.'); - }); - propertyReplacer.replace(Function.prototype, 'apply', function() { - fail('Should not call Function#apply from binary search.'); - }); - propertyReplacer.replace(Function.prototype, 'call', function() { - fail('Should not call Function#call from binary search.'); - }); - - try { - var array = [1, 5, 7, 11, 13, 16, 19, 24, 28, 31, 33, 36, 40, 50, 52, 55]; - // Test with the default comparison function. - goog.array.binarySearch(array, 48); - // Test with a custom comparison function. - goog.array.binarySearch(array, 13, function(a, b) { - return a > b ? 1 : a < b ? -1 : 0; - }); - } finally { - // The test runner uses Function.prototype.apply to call tearDown in the - // global context so it has to be reset here. - propertyReplacer.reset(); - } -} - - -function testBinarySelect() { - var insertionPoint = function(position) { return -(position + 1)}; - var numbers = [-897123.9, -321434.58758, -1321.3124, -324, -9, -3, 0, 0, 0, - 0.31255, 5, 142.88888708, 334, 342, 453, 54254]; - var objects = goog.array.map(numbers, function(n) {return {n: n};}); - function makeEvaluator(target) { - return function(obj, i, arr) { - assertEquals(objects, arr); - assertEquals(obj, arr[i]); - return target - obj.n; - }; - } - assertEquals('{n:-897123.9} should be found at index 0', 0, - goog.array.binarySelect(objects, makeEvaluator(-897123.9))); - assertEquals('{n:54254} should be found at index ' + (objects.length - 1), - objects.length - 1, - goog.array.binarySelect(objects, makeEvaluator(54254))); - assertEquals('{n:-3} should be found at index 5', 5, - goog.array.binarySelect(objects, makeEvaluator(-3))); - pos = goog.array.binarySelect(objects, makeEvaluator(0)); - assertTrue('{n:0} should be found at index 6 || 7 || 8', pos == 6 || - pos == 7 || pos == 8); - pos = goog.array.binarySelect(objects, makeEvaluator(-900000)); - assertTrue('{n:-900000} should not be found', pos < 0); - assertEquals('{n:-900000} should have an insertion point of 0', 0, - insertionPoint(pos)); - pos = goog.array.binarySelect(objects, makeEvaluator('54255')); - assertTrue('{n:54255} should not be found', pos < 0); - assertEquals('{n:54255} should have an insertion point of ' + - (objects.length), objects.length, insertionPoint(pos)); - pos = goog.array.binarySelect(objects, makeEvaluator(1.1)); - assertTrue('{n:1.1} should not be found', pos < 0); - assertEquals('{n:1.1} should have an insertion point of 10', 10, - insertionPoint(pos)); -} - - -function testArrayEquals() { - // Test argument types. - assertFalse('array == not array', goog.array.equals([], null)); - assertFalse('not array == array', goog.array.equals(null, [])); - assertFalse('not array == not array', goog.array.equals(null, null)); - - // Test with default comparison function. - assertTrue('[] == []', goog.array.equals([], [])); - assertTrue('[1] == [1]', goog.array.equals([1], [1])); - assertTrue('["1"] == ["1"]', goog.array.equals(['1'], ['1'])); - assertFalse('[1] == ["1"]', goog.array.equals([1], ['1'])); - assertTrue('[null] == [null]', goog.array.equals([null], [null])); - assertFalse('[null] == [undefined]', goog.array.equals([null], [undefined])); - assertTrue('[1, 2] == [1, 2]', goog.array.equals([1, 2], [1, 2])); - assertFalse('[1, 2] == [2, 1]', goog.array.equals([1, 2], [2, 1])); - assertFalse('[1, 2] == [1]', goog.array.equals([1, 2], [1])); - assertFalse('[1] == [1, 2]', goog.array.equals([1], [1, 2])); - assertFalse('[{}] == [{}]', goog.array.equals([{}], [{}])); - - // Test with custom comparison function. - var cmp = function(a, b) { return typeof a == typeof b; }; - assertTrue('[] cmp []', goog.array.equals([], [], cmp)); - assertTrue('[1] cmp [1]', goog.array.equals([1], [1], cmp)); - assertTrue('[1] cmp [2]', goog.array.equals([1], [2], cmp)); - assertTrue('["1"] cmp ["1"]', goog.array.equals(['1'], ['1'], cmp)); - assertTrue('["1"] cmp ["2"]', goog.array.equals(['1'], ['2'], cmp)); - assertFalse('[1] cmp ["1"]', goog.array.equals([1], ['1'], cmp)); - assertTrue('[1, 2] cmp [3, 4]', goog.array.equals([1, 2], [3, 4], cmp)); - assertFalse('[1] cmp [2, 3]', goog.array.equals([1], [2, 3], cmp)); - assertTrue('[{}] cmp [{}]', goog.array.equals([{}], [{}], cmp)); - assertTrue('[{}] cmp [{a: 1}]', goog.array.equals([{}], [{a: 1}], cmp)); - - // Test with array-like objects. - assertTrue('[5] == obj [5]', - goog.array.equals([5], {0: 5, length: 1})); - assertTrue('obj [5] == [5]', - goog.array.equals({0: 5, length: 1}, [5])); - assertTrue('["x"] == obj ["x"]', - goog.array.equals(['x'], {0: 'x', length: 1})); - assertTrue('obj ["x"] == ["x"]', - goog.array.equals({0: 'x', length: 1}, ['x'])); - assertTrue('[5] == {0: 5, 1: 6, length: 1}', - goog.array.equals([5], {0: 5, 1: 6, length: 1})); - assertTrue('{0: 5, 1: 6, length: 1} == [5]', - goog.array.equals({0: 5, 1: 6, length: 1}, [5])); - assertFalse('[5, 6] == {0: 5, 1: 6, length: 1}', - goog.array.equals([5, 6], {0: 5, 1: 6, length: 1})); - assertFalse('{0: 5, 1: 6, length: 1}, [5, 6]', - goog.array.equals({0: 5, 1: 6, length: 1}, [5, 6])); - assertTrue('[5, 6] == obj [5, 6]', - goog.array.equals([5, 6], {0: 5, 1: 6, length: 2})); - assertTrue('obj [5, 6] == [5, 6]', - goog.array.equals({0: 5, 1: 6, length: 2}, [5, 6])); - assertFalse('{0: 5, 1: 6} == [5, 6]', - goog.array.equals({0: 5, 1: 6}, [5, 6])); -} - - -function testArrayCompare3Basic() { - assertEquals(0, goog.array.compare3([], [])); - assertEquals(0, goog.array.compare3(['111', '222'], ['111', '222'])); - assertEquals(-1, goog.array.compare3(['111', '222'], ['1111', ''])); - assertEquals(1, goog.array.compare3(['111', '222'], ['111'])); - assertEquals(1, goog.array.compare3(['11', '222', '333'], [])); - assertEquals(-1, goog.array.compare3([], ['11', '222', '333'])); -} - - -function testArrayCompare3ComparatorFn() { - function cmp(a, b) { - return a - b; - }; - assertEquals(0, goog.array.compare3([], [], cmp)); - assertEquals(0, goog.array.compare3([8, 4], [8, 4], cmp)); - assertEquals(-1, goog.array.compare3([4, 3], [5, 0])); - assertEquals(1, goog.array.compare3([6, 2], [6])); - assertEquals(1, goog.array.compare3([1, 2, 3], [])); - assertEquals(-1, goog.array.compare3([], [1, 2, 3])); -} - - -function testSort() { - // Test sorting empty array - var a = []; - goog.array.sort(a); - assertEquals('Sorted empty array is still an empty array (length 0)', 0, - a.length); - - // Test sorting homogenous array of String(s) of length > 1 - var b = ['JUST', '1', 'test', 'Array', 'to', 'test', 'array', 'Sort', - 'about', 'NOW', '!!']; - var bSorted = ['!!', '1', 'Array', 'JUST', 'NOW', 'Sort', 'about', 'array', - 'test', 'test', 'to']; - goog.array.sort(b); - assertArrayEquals(bSorted, b); - - // Test sorting already sorted array of String(s) of length > 1 - goog.array.sort(b); - assertArrayEquals(bSorted, b); - - // Test sorting homogenous array of integer Number(s) of length > 1 - var c = [100, 1, 2000, -1, 0, 1000023, 12312512, -12331, 123, 54325, - -38104783, 93708, 908, -213, -4, 5423, 0]; - var cSorted = [-38104783, -12331, -213, -4, -1, 0, 0, 1, 100, 123, 908, - 2000, 5423, 54325, 93708, 1000023, 12312512]; - goog.array.sort(c); - assertArrayEquals(cSorted, c); - - // Test sorting already sorted array of integer Number(s) of length > 1 - goog.array.sort(c); - assertArrayEquals(cSorted, c); - - // Test sorting homogenous array of Number(s) of length > 1 - var e = [-1321.3124, 0.31255, 54254, 0, 142.88888708, -321434.58758, -324, - 453, 334, -3, 5, -9, 342, -897123.9]; - var eSorted = [-897123.9, -321434.58758, -1321.3124, -324, -9, -3, 0, - 0.31255, 5, 142.88888708, 334, 342, 453, 54254]; - goog.array.sort(e); - assertArrayEquals(eSorted, e); - - // Test sorting already sorted array of Number(s) of length > 1 - goog.array.sort(e); - assertArrayEquals(eSorted, e); - - // Test sorting array of Number(s) of length > 1, - // using custom comparison function which does reverse ordering - var f = [-1321.3124, 0.31255, 54254, 0, 142.88888708, -321434.58758, - -324, 453, 334, -3, 5, -9, 342, -897123.9]; - var fSorted = [54254, 453, 342, 334, 142.88888708, 5, 0.31255, 0, -3, -9, - -324, -1321.3124, -321434.58758, -897123.9]; - goog.array.sort(f, function(a, b) { return b - a; }); - assertArrayEquals(fSorted, f); - - // Test sorting already sorted array of Number(s) of length > 1 - // using custom comparison function which does reverse ordering - goog.array.sort(f, function(a, b) {return b - a; }); - assertArrayEquals(fSorted, f); - - // Test sorting array of custom Object(s) of length > 1 that have - // an overriden toString - function ComparedObject(value) { - this.value = value; - }; - - ComparedObject.prototype.toString = function() { - return this.value; - }; - - var co1 = new ComparedObject('a'); - var co2 = new ComparedObject('b'); - var co3 = new ComparedObject('c'); - var co4 = new ComparedObject('d'); - - var g = [co3, co4, co2, co1]; - var gSorted = [co1, co2, co3, co4]; - goog.array.sort(g); - assertArrayEquals(gSorted, g); - - // Test sorting already sorted array of custom Object(s) of length > 1 - // that have an overriden toString - goog.array.sort(g); - assertArrayEquals(gSorted, g); - - // Test sorting an array of custom Object(s) of length > 1 using - // a custom comparison function - var h = [co4, co2, co1, co3]; - var hSorted = [co1, co2, co3, co4]; - goog.array.sort(h, function(a, b) { - return a.value > b.value ? 1 : a.value < b.value ? -1 : 0; - }); - assertArrayEquals(hSorted, h); - - // Test sorting already sorted array of custom Object(s) of length > 1 - // using a custom comparison function - goog.array.sort(h); - assertArrayEquals(hSorted, h); - - // Test sorting arrays of length 1 - var i = ['one']; - var iSorted = ['one']; - goog.array.sort(i); - assertArrayEquals(iSorted, i); - - var j = [1]; - var jSorted = [1]; - goog.array.sort(j); - assertArrayEquals(jSorted, j); - - var k = [1.1]; - var kSorted = [1.1]; - goog.array.sort(k); - assertArrayEquals(kSorted, k); - - var l = [co3]; - var lSorted = [co3]; - goog.array.sort(l); - assertArrayEquals(lSorted, l); - - var m = [co2]; - var mSorted = [co2]; - goog.array.sort(m, function(a, b) { - return a.value > b.value ? 1 : a.value < b.value ? -1 : 0; - }); - assertArrayEquals(mSorted, m); -} - -function testStableSort() { - // Test array with custom comparison function - var arr = [{key: 3, val: 'a'}, {key: 2, val: 'b'}, {key: 3, val: 'c'}, - {key: 4, val: 'd'}, {key: 3, val: 'e'}]; - var arrClone = goog.array.clone(arr); - - function comparisonFn(obj1, obj2) { - return obj1.key - obj2.key; - } - goog.array.stableSort(arr, comparisonFn); - var sortedValues = []; - for (var i = 0; i < arr.length; i++) { - sortedValues.push(arr[i].val); - } - var wantedSortedValues = ['b', 'a', 'c', 'e', 'd']; - assertArrayEquals(wantedSortedValues, sortedValues); - - // Test array without custom comparison function - var arr2 = []; - for (var i = 0; i < arrClone.length; i++) { - arr2.push({val: arrClone[i].val, toString: - goog.partial(function(index) { - return arrClone[index].key; - }, i)}); - } - goog.array.stableSort(arr2); - var sortedValues2 = []; - for (var i = 0; i < arr2.length; i++) { - sortedValues2.push(arr2[i].val); - } - assertArrayEquals(wantedSortedValues, sortedValues2); -} - -function testSortByKey() { - function Item(value) { - this.getValue = function() { - return value; - }; - } - var keyFn = function(item) { - return item.getValue(); - }; - - // Test without custom key comparison function - var arr1 = [new Item(3), new Item(2), new Item(1), new Item(5), new Item(4)]; - goog.array.sortByKey(arr1, keyFn); - var wantedSortedValues1 = [1, 2, 3, 4, 5]; - for (var i = 0; i < arr1.length; i++) { - assertEquals(wantedSortedValues1[i], arr1[i].getValue()); - } - - // Test with custom key comparison function - var arr2 = [new Item(3), new Item(2), new Item(1), new Item(5), new Item(4)]; - function comparisonFn(key1, key2) { - return -(key1 - key2); - } - goog.array.sortByKey(arr2, keyFn, comparisonFn); - var wantedSortedValues2 = [5, 4, 3, 2, 1]; - for (var i = 0; i < arr2.length; i++) { - assertEquals(wantedSortedValues2[i], arr2[i].getValue()); - } -} - -function testArrayBucketModulus() { - // bucket things by modulus - var a = {}; - var b = []; - - function modFive(num) { - return num % 5; - } - - for (var i = 0; i < 20; i++) { - var mod = modFive(i); - a[mod] = a[mod] || []; - a[mod].push(i); - b.push(i); - } - - var buckets = goog.array.bucket(b, modFive); - - for (var i = 0; i < 5; i++) { - // The order isn't defined, but they should be the same sorted. - goog.array.sort(a[i]); - goog.array.sort(buckets[i]); - assertArrayEquals(a[i], buckets[i]); - } -} - -function testArrayBucketEvenOdd() { - var a = [1, 2, 3, 4, 5, 6, 7, 8, 9]; - - // test even/odd - function isEven(value, index, array) { - assertEquals(value, array[index]); - assertEquals('number', typeof index); - assertEquals(a, array); - return value % 2 == 0; - } - - var b = goog.array.bucket(a, isEven); - - assertArrayEquals(b[true], [2, 4, 6, 8]); - assertArrayEquals(b[false], [1, 3, 5, 7, 9]); -} - -function testArrayBucketUsingThisObject() { - var a = [1, 2, 3, 4, 5]; - - var obj = { - specialValue: 2 - }; - - function isSpecialValue(value, index, array) { - return value == this.specialValue ? 1 : 0; - } - - var b = goog.array.bucket(a, isSpecialValue, obj); - assertArrayEquals(b[0], [1, 3, 4, 5]); - assertArrayEquals(b[1], [2]); -} - -function testArrayToObject() { - var a = [ - {name: 'a'}, - {name: 'b'}, - {name: 'c'}, - {name: 'd'}]; - - function getName(value, index, array) { - assertEquals(value, array[index]); - assertEquals('number', typeof index); - assertEquals(a, array); - return value.name; - } - - var b = goog.array.toObject(a, getName); - - for (var i = 0; i < a.length; i++) { - assertEquals(a[i], b[a[i].name]); - } -} - -function testRange() { - assertArrayEquals([], goog.array.range(0)); - assertArrayEquals([], goog.array.range(5, 5, 5)); - assertArrayEquals([], goog.array.range(-3, -3)); - assertArrayEquals([], goog.array.range(10, undefined, -1)); - assertArrayEquals([], goog.array.range(8, 0)); - assertArrayEquals([], goog.array.range(-5, -10, 3)); - - assertArrayEquals([0], goog.array.range(1)); - assertArrayEquals([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], goog.array.range(10)); - - assertArrayEquals([1], goog.array.range(1, 2)); - assertArrayEquals([-3, -2, -1, 0, 1, 2], goog.array.range(-3, 3)); - - assertArrayEquals([4], goog.array.range(4, 40, 400)); - assertArrayEquals([5, 8, 11, 14], goog.array.range(5, 15, 3)); - assertArrayEquals([1, -1, -3], goog.array.range(1, -5, -2)); - assertElementsRoughlyEqual([.2, .3, .4], goog.array.range(.2, .5, .1), 0.001); - - assertArrayEquals([0], goog.array.range(7, undefined, 9)); - assertArrayEquals([0, 2, 4, 6], goog.array.range(8, undefined, 2)); -} - -function testArrayRepeat() { - assertArrayEquals([], goog.array.repeat(3, 0)); - assertArrayEquals([], goog.array.repeat(3, -1)); - assertArrayEquals([3], goog.array.repeat(3, 1)); - assertArrayEquals([3, 3, 3], goog.array.repeat(3, 3)); - assertArrayEquals([null, null], goog.array.repeat(null, 2)); -} - -function testArrayFlatten() { - assertArrayEquals([1, 2, 3, 4, 5], goog.array.flatten(1, 2, 3, 4, 5)); - assertArrayEquals([1, 2, 3, 4, 5], goog.array.flatten(1, [2, [3, [4, 5]]])); - assertArrayEquals([1, 2, 3, 4], goog.array.flatten(1, [2, [3, [4]]])); - assertArrayEquals([1, 2, 3, 4], goog.array.flatten([[[1], 2], 3], 4)); - assertArrayEquals([1], goog.array.flatten([[1]])); - assertArrayEquals([], goog.array.flatten()); - assertArrayEquals([], goog.array.flatten([])); - assertArrayEquals(goog.array.repeat(3, 180002), - goog.array.flatten(3, goog.array.repeat(3, 180000), 3)); - assertArrayEquals(goog.array.repeat(3, 180000), - goog.array.flatten([goog.array.repeat(3, 180000)])); -} - -function testSortObjectsByKey() { - var sortedArray = buildSortedObjectArray(4); - var objects = - [sortedArray[1], sortedArray[2], sortedArray[0], sortedArray[3]]; - - goog.array.sortObjectsByKey(objects, 'name'); - validateObjectArray(sortedArray, objects); -} - -function testSortObjectsByKeyWithCompareFunction() { - var sortedArray = buildSortedObjectArray(4); - var objects = - [sortedArray[1], sortedArray[2], sortedArray[0], sortedArray[3]]; - var descSortedArray = - [sortedArray[3], sortedArray[2], sortedArray[1], sortedArray[0]]; - - function descCompare(a, b) { - return a < b ? 1 : a > b ? -1 : 0; - }; - - goog.array.sortObjectsByKey(objects, 'name', descCompare); - validateObjectArray(descSortedArray, objects); -} - -function buildSortedObjectArray(size) { - var objectArray = []; - for (var i = 0; i < size; i++) { - objectArray.push({ - 'name': 'name_' + i, - 'id': 'id_' + (size - i) - }); - } - - return objectArray; -} - -function validateObjectArray(expected, actual) { - assertEquals(expected.length, actual.length); - for (var i = 0; i < expected.length; i++) { - assertEquals(expected[i].name, actual[i].name); - assertEquals(expected[i].id, actual[i].id); - } -} - -function testIsSorted() { - assertTrue(goog.array.isSorted([1, 2, 3])); - assertTrue(goog.array.isSorted([1, 2, 2])); - assertFalse(goog.array.isSorted([1, 2, 1])); - - assertTrue(goog.array.isSorted([1, 2, 3], null, true)); - assertFalse(goog.array.isSorted([1, 2, 2], null, true)); - assertFalse(goog.array.isSorted([1, 2, 1], null, true)); - - function compare(a, b) { - return b - a; - } - - assertFalse(goog.array.isSorted([1, 2, 3], compare)); - assertTrue(goog.array.isSorted([3, 2, 2], compare)); -} - -function assertRotated(expect, array, rotate) { - assertArrayEquals(expect, goog.array.rotate(array, rotate)); -} - -function testRotate() { - assertRotated([], [], 3); - assertRotated([1], [1], 3); - assertRotated([1, 2, 3, 4, 0], [0, 1, 2, 3, 4], -6); - assertRotated([0, 1, 2, 3, 4], [0, 1, 2, 3, 4], -5); - assertRotated([4, 0, 1, 2, 3], [0, 1, 2, 3, 4], -4); - assertRotated([3, 4, 0, 1, 2], [0, 1, 2, 3, 4], -3); - assertRotated([2, 3, 4, 0, 1], [0, 1, 2, 3, 4], -2); - assertRotated([1, 2, 3, 4, 0], [0, 1, 2, 3, 4], -1); - assertRotated([0, 1, 2, 3, 4], [0, 1, 2, 3, 4], 0); - assertRotated([4, 0, 1, 2, 3], [0, 1, 2, 3, 4], 1); - assertRotated([3, 4, 0, 1, 2], [0, 1, 2, 3, 4], 2); - assertRotated([2, 3, 4, 0, 1], [0, 1, 2, 3, 4], 3); - assertRotated([1, 2, 3, 4, 0], [0, 1, 2, 3, 4], 4); - assertRotated([0, 1, 2, 3, 4], [0, 1, 2, 3, 4], 5); - assertRotated([4, 0, 1, 2, 3], [0, 1, 2, 3, 4], 6); -} - -function testMoveItemWithArray() { - var arr = [0, 1, 2, 3]; - goog.array.moveItem(arr, 1, 3); // toIndex > fromIndex - assertArrayEquals([0, 2, 3, 1], arr); - goog.array.moveItem(arr, 2, 0); // toIndex < fromIndex - assertArrayEquals([3, 0, 2, 1], arr); - goog.array.moveItem(arr, 1, 1); // toIndex == fromIndex - assertArrayEquals([3, 0, 2, 1], arr); - // Out-of-bounds indexes throw assertion errors. - assertThrows(function() { - goog.array.moveItem(arr, -1, 1); - }); - assertThrows(function() { - goog.array.moveItem(arr, 4, 1); - }); - assertThrows(function() { - goog.array.moveItem(arr, 1, -1); - }); - assertThrows(function() { - goog.array.moveItem(arr, 1, 4); - }); - // The array should not be modified by the out-of-bound calls. - assertArrayEquals([3, 0, 2, 1], arr); -} - -function testMoveItemWithArgumentsObject() { - var f = function() { - goog.array.moveItem(arguments, 0, 1); - return arguments; - }; - assertArrayEquals([1, 0], goog.array.toArray(f(0, 1))); -} - -function testConcat() { - var a1 = [1, 2, 3]; - var a2 = [4, 5, 6]; - var a3 = goog.array.concat(a1, a2); - a1.push(1); - a2.push(5); - assertArrayEquals([1, 2, 3, 4, 5, 6], a3); -} - -function testConcatWithNoSecondArg() { - var a1 = [1, 2, 3, 4]; - var a2 = goog.array.concat(a1); - a1.push(5); - assertArrayEquals([1, 2, 3, 4], a2); -} - -function testConcatWithNonArrayArgs() { - var a1 = [1, 2, 3, 4]; - var o = {0: 'a', 1: 'b', length: 2}; - var a2 = goog.array.concat(a1, 5, '10', o); - assertArrayEquals([1, 2, 3, 4, 5, '10', o], a2); -} - -function testConcatWithNull() { - var a1 = goog.array.concat(null, [1, 2, 3]); - var a2 = goog.array.concat([1, 2, 3], null); - assertArrayEquals([null, 1, 2, 3], a1); - assertArrayEquals([1, 2, 3, null], a2); -} - -function testZip() { - var a1 = goog.array.zip([1, 2, 3], [3, 2, 1]); - var a2 = goog.array.zip([1, 2], [3, 2, 1]); - var a3 = goog.array.zip(); - assertArrayEquals([[1, 3], [2, 2], [3, 1]], a1); - assertArrayEquals([[1, 3], [2, 2]], a2); - assertArrayEquals([], a3); -} - -function testShuffle() { - // Test array. This array should have unique values for the purposes of this - // test case. - var testArray = [1, 2, 3, 4, 5]; - var testArrayCopy = goog.array.clone(testArray); - - // Custom random function, which always returns a value approaching 1, - // resulting in a "shuffle" that preserves the order of original array - // (for array sizes that we work with here). - var noChangeShuffleFunction = function() { - return .999999; - }; - goog.array.shuffle(testArray, noChangeShuffleFunction); - assertArrayEquals(testArrayCopy, testArray); - - // Custom random function, which always returns 0, resulting in a - // deterministic "shuffle" that is predictable but differs from the - // original order of the array. - var testShuffleFunction = function() { - return 0; - }; - goog.array.shuffle(testArray, testShuffleFunction); - assertArrayEquals([2, 3, 4, 5, 1], testArray); - - // Test the use of a real random function(no optional RNG is specified). - goog.array.shuffle(testArray); - - // Ensure the shuffled array comprises the same elements (without regard to - // order). - assertSameElements(testArrayCopy, testArray); -} - -function testRemoveAllIf() { - var testArray = [9, 1, 9, 2, 9, 3, 4, 9, 9, 9, 5]; - var expectedArray = [1, 2, 3, 4, 5]; - - var actualOutput = goog.array.removeAllIf(testArray, function(el) { - return el == 9; - }); - - assertEquals(6, actualOutput); - assertArrayEquals(expectedArray, testArray); -} - -function testRemoveAllIf_noMatches() { - var testArray = [1]; - var expectedArray = [1]; - - var actualOutput = goog.array.removeAllIf(testArray, function(el) { - return false; - }); - - assertEquals(0, actualOutput); - assertArrayEquals(expectedArray, testArray); -} - -function testCopyByIndex() { - var testArray = [1, 2, 'a', 'b', 'c', 'd']; - var copyIndexes = [1, 3, 0, 0, 2]; - var expectedArray = [2, 'b', 1, 1, 'a']; - - var actualOutput = goog.array.copyByIndex(testArray, copyIndexes); - - assertArrayEquals(expectedArray, actualOutput); -} - -function testComparators() { - var greater = 42; - var smaller = 13; - - assertTrue(goog.array.defaultCompare(smaller, greater) < 0); - assertEquals(0, goog.array.defaultCompare(smaller, smaller)); - assertTrue(goog.array.defaultCompare(greater, smaller) > 0); - - assertTrue(goog.array.inverseDefaultCompare(greater, smaller) < 0); - assertEquals(0, goog.array.inverseDefaultCompare(greater, greater)); - assertTrue(goog.array.inverseDefaultCompare(smaller, greater) > 0); -} diff --git a/src/database/third_party/closure-library/closure/goog/asserts/asserts.js b/src/database/third_party/closure-library/closure/goog/asserts/asserts.js deleted file mode 100644 index 95513d15491..00000000000 --- a/src/database/third_party/closure-library/closure/goog/asserts/asserts.js +++ /dev/null @@ -1,365 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utilities to check the preconditions, postconditions and - * invariants runtime. - * - * Methods in this package should be given special treatment by the compiler - * for type-inference. For example, goog.asserts.assert(foo) - * will restrict foo to a truthy value. - * - * The compiler has an option to disable asserts. So code like: - * - * var x = goog.asserts.assert(foo()); goog.asserts.assert(bar()); - * - * will be transformed into: - * - * var x = foo(); - * - * The compiler will leave in foo() (because its return value is used), - * but it will remove bar() because it assumes it does not have side-effects. - * - * @author agrieve@google.com (Andrew Grieve) - */ - -goog.provide('goog.asserts'); -goog.provide('goog.asserts.AssertionError'); - -goog.require('goog.debug.Error'); -goog.require('goog.dom.NodeType'); -goog.require('goog.string'); - - -/** - * @define {boolean} Whether to strip out asserts or to leave them in. - */ -goog.define('goog.asserts.ENABLE_ASSERTS', goog.DEBUG); - - - -/** - * Error object for failed assertions. - * @param {string} messagePattern The pattern that was used to form message. - * @param {!Array<*>} messageArgs The items to substitute into the pattern. - * @constructor - * @extends {goog.debug.Error} - * @final - */ -goog.asserts.AssertionError = function(messagePattern, messageArgs) { - messageArgs.unshift(messagePattern); - goog.debug.Error.call(this, goog.string.subs.apply(null, messageArgs)); - // Remove the messagePattern afterwards to avoid permenantly modifying the - // passed in array. - messageArgs.shift(); - - /** - * The message pattern used to format the error message. Error handlers can - * use this to uniquely identify the assertion. - * @type {string} - */ - this.messagePattern = messagePattern; -}; -goog.inherits(goog.asserts.AssertionError, goog.debug.Error); - - -/** @override */ -goog.asserts.AssertionError.prototype.name = 'AssertionError'; - - -/** - * The default error handler. - * @param {!goog.asserts.AssertionError} e The exception to be handled. - */ -goog.asserts.DEFAULT_ERROR_HANDLER = function(e) { throw e; }; - - -/** - * The handler responsible for throwing or logging assertion errors. - * @private {function(!goog.asserts.AssertionError)} - */ -goog.asserts.errorHandler_ = goog.asserts.DEFAULT_ERROR_HANDLER; - - -/** - * Throws an exception with the given message and "Assertion failed" prefixed - * onto it. - * @param {string} defaultMessage The message to use if givenMessage is empty. - * @param {Array<*>} defaultArgs The substitution arguments for defaultMessage. - * @param {string|undefined} givenMessage Message supplied by the caller. - * @param {Array<*>} givenArgs The substitution arguments for givenMessage. - * @throws {goog.asserts.AssertionError} When the value is not a number. - * @private - */ -goog.asserts.doAssertFailure_ = - function(defaultMessage, defaultArgs, givenMessage, givenArgs) { - var message = 'Assertion failed'; - if (givenMessage) { - message += ': ' + givenMessage; - var args = givenArgs; - } else if (defaultMessage) { - message += ': ' + defaultMessage; - args = defaultArgs; - } - // The '' + works around an Opera 10 bug in the unit tests. Without it, - // a stack trace is added to var message above. With this, a stack trace is - // not added until this line (it causes the extra garbage to be added after - // the assertion message instead of in the middle of it). - var e = new goog.asserts.AssertionError('' + message, args || []); - goog.asserts.errorHandler_(e); -}; - - -/** - * Sets a custom error handler that can be used to customize the behavior of - * assertion failures, for example by turning all assertion failures into log - * messages. - * @param {function(!goog.asserts.AssertionError)} errorHandler - */ -goog.asserts.setErrorHandler = function(errorHandler) { - if (goog.asserts.ENABLE_ASSERTS) { - goog.asserts.errorHandler_ = errorHandler; - } -}; - - -/** - * Checks if the condition evaluates to true if goog.asserts.ENABLE_ASSERTS is - * true. - * @template T - * @param {T} condition The condition to check. - * @param {string=} opt_message Error message in case of failure. - * @param {...*} var_args The items to substitute into the failure message. - * @return {T} The value of the condition. - * @throws {goog.asserts.AssertionError} When the condition evaluates to false. - */ -goog.asserts.assert = function(condition, opt_message, var_args) { - if (goog.asserts.ENABLE_ASSERTS && !condition) { - goog.asserts.doAssertFailure_('', null, opt_message, - Array.prototype.slice.call(arguments, 2)); - } - return condition; -}; - - -/** - * Fails if goog.asserts.ENABLE_ASSERTS is true. This function is useful in case - * when we want to add a check in the unreachable area like switch-case - * statement: - * - *
- *  switch(type) {
- *    case FOO: doSomething(); break;
- *    case BAR: doSomethingElse(); break;
- *    default: goog.assert.fail('Unrecognized type: ' + type);
- *      // We have only 2 types - "default:" section is unreachable code.
- *  }
- * 
- * - * @param {string=} opt_message Error message in case of failure. - * @param {...*} var_args The items to substitute into the failure message. - * @throws {goog.asserts.AssertionError} Failure. - */ -goog.asserts.fail = function(opt_message, var_args) { - if (goog.asserts.ENABLE_ASSERTS) { - goog.asserts.errorHandler_(new goog.asserts.AssertionError( - 'Failure' + (opt_message ? ': ' + opt_message : ''), - Array.prototype.slice.call(arguments, 1))); - } -}; - - -/** - * Checks if the value is a number if goog.asserts.ENABLE_ASSERTS is true. - * @param {*} value The value to check. - * @param {string=} opt_message Error message in case of failure. - * @param {...*} var_args The items to substitute into the failure message. - * @return {number} The value, guaranteed to be a number when asserts enabled. - * @throws {goog.asserts.AssertionError} When the value is not a number. - */ -goog.asserts.assertNumber = function(value, opt_message, var_args) { - if (goog.asserts.ENABLE_ASSERTS && !goog.isNumber(value)) { - goog.asserts.doAssertFailure_('Expected number but got %s: %s.', - [goog.typeOf(value), value], opt_message, - Array.prototype.slice.call(arguments, 2)); - } - return /** @type {number} */ (value); -}; - - -/** - * Checks if the value is a string if goog.asserts.ENABLE_ASSERTS is true. - * @param {*} value The value to check. - * @param {string=} opt_message Error message in case of failure. - * @param {...*} var_args The items to substitute into the failure message. - * @return {string} The value, guaranteed to be a string when asserts enabled. - * @throws {goog.asserts.AssertionError} When the value is not a string. - */ -goog.asserts.assertString = function(value, opt_message, var_args) { - if (goog.asserts.ENABLE_ASSERTS && !goog.isString(value)) { - goog.asserts.doAssertFailure_('Expected string but got %s: %s.', - [goog.typeOf(value), value], opt_message, - Array.prototype.slice.call(arguments, 2)); - } - return /** @type {string} */ (value); -}; - - -/** - * Checks if the value is a function if goog.asserts.ENABLE_ASSERTS is true. - * @param {*} value The value to check. - * @param {string=} opt_message Error message in case of failure. - * @param {...*} var_args The items to substitute into the failure message. - * @return {!Function} The value, guaranteed to be a function when asserts - * enabled. - * @throws {goog.asserts.AssertionError} When the value is not a function. - */ -goog.asserts.assertFunction = function(value, opt_message, var_args) { - if (goog.asserts.ENABLE_ASSERTS && !goog.isFunction(value)) { - goog.asserts.doAssertFailure_('Expected function but got %s: %s.', - [goog.typeOf(value), value], opt_message, - Array.prototype.slice.call(arguments, 2)); - } - return /** @type {!Function} */ (value); -}; - - -/** - * Checks if the value is an Object if goog.asserts.ENABLE_ASSERTS is true. - * @param {*} value The value to check. - * @param {string=} opt_message Error message in case of failure. - * @param {...*} var_args The items to substitute into the failure message. - * @return {!Object} The value, guaranteed to be a non-null object. - * @throws {goog.asserts.AssertionError} When the value is not an object. - */ -goog.asserts.assertObject = function(value, opt_message, var_args) { - if (goog.asserts.ENABLE_ASSERTS && !goog.isObject(value)) { - goog.asserts.doAssertFailure_('Expected object but got %s: %s.', - [goog.typeOf(value), value], - opt_message, Array.prototype.slice.call(arguments, 2)); - } - return /** @type {!Object} */ (value); -}; - - -/** - * Checks if the value is an Array if goog.asserts.ENABLE_ASSERTS is true. - * @param {*} value The value to check. - * @param {string=} opt_message Error message in case of failure. - * @param {...*} var_args The items to substitute into the failure message. - * @return {!Array} The value, guaranteed to be a non-null array. - * @throws {goog.asserts.AssertionError} When the value is not an array. - */ -goog.asserts.assertArray = function(value, opt_message, var_args) { - if (goog.asserts.ENABLE_ASSERTS && !goog.isArray(value)) { - goog.asserts.doAssertFailure_('Expected array but got %s: %s.', - [goog.typeOf(value), value], opt_message, - Array.prototype.slice.call(arguments, 2)); - } - return /** @type {!Array} */ (value); -}; - - -/** - * Checks if the value is a boolean if goog.asserts.ENABLE_ASSERTS is true. - * @param {*} value The value to check. - * @param {string=} opt_message Error message in case of failure. - * @param {...*} var_args The items to substitute into the failure message. - * @return {boolean} The value, guaranteed to be a boolean when asserts are - * enabled. - * @throws {goog.asserts.AssertionError} When the value is not a boolean. - */ -goog.asserts.assertBoolean = function(value, opt_message, var_args) { - if (goog.asserts.ENABLE_ASSERTS && !goog.isBoolean(value)) { - goog.asserts.doAssertFailure_('Expected boolean but got %s: %s.', - [goog.typeOf(value), value], opt_message, - Array.prototype.slice.call(arguments, 2)); - } - return /** @type {boolean} */ (value); -}; - - -/** - * Checks if the value is a DOM Element if goog.asserts.ENABLE_ASSERTS is true. - * @param {*} value The value to check. - * @param {string=} opt_message Error message in case of failure. - * @param {...*} var_args The items to substitute into the failure message. - * @return {!Element} The value, likely to be a DOM Element when asserts are - * enabled. - * @throws {goog.asserts.AssertionError} When the value is not an Element. - */ -goog.asserts.assertElement = function(value, opt_message, var_args) { - if (goog.asserts.ENABLE_ASSERTS && (!goog.isObject(value) || - value.nodeType != goog.dom.NodeType.ELEMENT)) { - goog.asserts.doAssertFailure_('Expected Element but got %s: %s.', - [goog.typeOf(value), value], opt_message, - Array.prototype.slice.call(arguments, 2)); - } - return /** @type {!Element} */ (value); -}; - - -/** - * Checks if the value is an instance of the user-defined type if - * goog.asserts.ENABLE_ASSERTS is true. - * - * The compiler may tighten the type returned by this function. - * - * @param {*} value The value to check. - * @param {function(new: T, ...)} type A user-defined constructor. - * @param {string=} opt_message Error message in case of failure. - * @param {...*} var_args The items to substitute into the failure message. - * @throws {goog.asserts.AssertionError} When the value is not an instance of - * type. - * @return {T} - * @template T - */ -goog.asserts.assertInstanceof = function(value, type, opt_message, var_args) { - if (goog.asserts.ENABLE_ASSERTS && !(value instanceof type)) { - goog.asserts.doAssertFailure_('Expected instanceof %s but got %s.', - [goog.asserts.getType_(type), goog.asserts.getType_(value)], - opt_message, Array.prototype.slice.call(arguments, 3)); - } - return value; -}; - - -/** - * Checks that no enumerable keys are present in Object.prototype. Such keys - * would break most code that use {@code for (var ... in ...)} loops. - */ -goog.asserts.assertObjectPrototypeIsIntact = function() { - for (var key in Object.prototype) { - goog.asserts.fail(key + ' should not be enumerable in Object.prototype.'); - } -}; - - -/** - * Returns the type of a value. If a constructor is passed, and a suitable - * string cannot be found, 'unknown type name' will be returned. - * @param {*} value A constructor, object, or primitive. - * @return {string} The best display name for the value, or 'unknown type name'. - * @private - */ -goog.asserts.getType_ = function(value) { - if (value instanceof Function) { - return value.displayName || value.name || 'unknown type name'; - } else if (value instanceof Object) { - return value.constructor.displayName || value.constructor.name || - Object.prototype.toString.call(value); - } else { - return value === null ? 'null' : typeof value; - } -}; diff --git a/src/database/third_party/closure-library/closure/goog/asserts/asserts_test.html b/src/database/third_party/closure-library/closure/goog/asserts/asserts_test.html deleted file mode 100644 index ab575071235..00000000000 --- a/src/database/third_party/closure-library/closure/goog/asserts/asserts_test.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - Closure Unit Tests - goog.asserts.assert - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/asserts/asserts_test.js b/src/database/third_party/closure-library/closure/goog/asserts/asserts_test.js deleted file mode 100644 index f2fa268f227..00000000000 --- a/src/database/third_party/closure-library/closure/goog/asserts/asserts_test.js +++ /dev/null @@ -1,242 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.assertsTest'); -goog.setTestOnly('goog.assertsTest'); - -goog.require('goog.asserts'); -goog.require('goog.asserts.AssertionError'); -goog.require('goog.dom'); -goog.require('goog.string'); -goog.require('goog.testing.jsunit'); -goog.require('goog.userAgent'); - -function doTestMessage(failFunc, expectedMsg) { - var error = assertThrows('failFunc should throw.', failFunc); - // Test error message. - // Opera 10 adds cruft to the end of the message, so do a startsWith check. - assertTrue('Message check failed. Expected: ' + expectedMsg + ' Actual: ' + - error.message, goog.string.startsWith(error.message, expectedMsg)); -} - -function testAssert() { - // None of them may throw exception - goog.asserts.assert(true); - goog.asserts.assert(1); - goog.asserts.assert([]); - goog.asserts.assert({}); - - assertThrows('assert(false)', goog.partial(goog.asserts.assert, false)); - assertThrows('assert(0)', goog.partial(goog.asserts.assert, 0)); - assertThrows('assert(null)', goog.partial(goog.asserts.assert, null)); - assertThrows('assert(undefined)', - goog.partial(goog.asserts.assert, undefined)); - - // Test error messages. - doTestMessage(goog.partial(goog.asserts.assert, false), 'Assertion failed'); - doTestMessage(goog.partial(goog.asserts.assert, false, 'ouch %s', 1), - 'Assertion failed: ouch 1'); -} - - -function testFail() { - assertThrows('fail()', goog.asserts.fail); - // Test error messages. - doTestMessage(goog.partial(goog.asserts.fail, false), 'Failure'); - doTestMessage(goog.partial(goog.asserts.fail, 'ouch %s', 1), - 'Failure: ouch 1'); -} - -function testNumber() { - goog.asserts.assertNumber(1); - assertThrows('assertNumber(null)', - goog.partial(goog.asserts.assertNumber, null)); - // Test error messages. - doTestMessage(goog.partial(goog.asserts.assertNumber, null), - 'Assertion failed: Expected number but got null: null.'); - doTestMessage(goog.partial(goog.asserts.assertNumber, '1234'), - 'Assertion failed: Expected number but got string: 1234.'); - doTestMessage(goog.partial(goog.asserts.assertNumber, null, 'ouch %s', 1), - 'Assertion failed: ouch 1'); -} - -function testString() { - assertEquals('1', goog.asserts.assertString('1')); - assertThrows('assertString(null)', - goog.partial(goog.asserts.assertString, null)); - // Test error messages. - doTestMessage(goog.partial(goog.asserts.assertString, null), - 'Assertion failed: Expected string but got null: null.'); - doTestMessage(goog.partial(goog.asserts.assertString, 1234), - 'Assertion failed: Expected string but got number: 1234.'); - doTestMessage(goog.partial(goog.asserts.assertString, null, 'ouch %s', 1), - 'Assertion failed: ouch 1'); -} - -function testFunction() { - function f() {}; - assertEquals(f, goog.asserts.assertFunction(f)); - assertThrows('assertFunction(null)', - goog.partial(goog.asserts.assertFunction, null)); - // Test error messages. - doTestMessage(goog.partial(goog.asserts.assertFunction, null), - 'Assertion failed: Expected function but got null: null.'); - doTestMessage(goog.partial(goog.asserts.assertFunction, 1234), - 'Assertion failed: Expected function but got number: 1234.'); - doTestMessage(goog.partial(goog.asserts.assertFunction, null, 'ouch %s', 1), - 'Assertion failed: ouch 1'); -} - -function testObject() { - var o = {}; - assertEquals(o, goog.asserts.assertObject(o)); - assertThrows('assertObject(null)', - goog.partial(goog.asserts.assertObject, null)); - // Test error messages. - doTestMessage(goog.partial(goog.asserts.assertObject, null), - 'Assertion failed: Expected object but got null: null.'); - doTestMessage(goog.partial(goog.asserts.assertObject, 1234), - 'Assertion failed: Expected object but got number: 1234.'); - doTestMessage(goog.partial(goog.asserts.assertObject, null, 'ouch %s', 1), - 'Assertion failed: ouch 1'); -} - -function testArray() { - var a = []; - assertEquals(a, goog.asserts.assertArray(a)); - assertThrows('assertArray({})', - goog.partial(goog.asserts.assertArray, {})); - // Test error messages. - doTestMessage(goog.partial(goog.asserts.assertArray, null), - 'Assertion failed: Expected array but got null: null.'); - doTestMessage(goog.partial(goog.asserts.assertArray, 1234), - 'Assertion failed: Expected array but got number: 1234.'); - doTestMessage(goog.partial(goog.asserts.assertArray, null, 'ouch %s', 1), - 'Assertion failed: ouch 1'); -} - -function testBoolean() { - assertEquals(true, goog.asserts.assertBoolean(true)); - assertEquals(false, goog.asserts.assertBoolean(false)); - assertThrows(goog.partial(goog.asserts.assertBoolean, null)); - assertThrows(goog.partial(goog.asserts.assertBoolean, 'foo')); - - // Test error messages. - doTestMessage(goog.partial(goog.asserts.assertBoolean, null), - 'Assertion failed: Expected boolean but got null: null.'); - doTestMessage(goog.partial(goog.asserts.assertBoolean, 1234), - 'Assertion failed: Expected boolean but got number: 1234.'); - doTestMessage(goog.partial(goog.asserts.assertBoolean, null, 'ouch %s', 1), - 'Assertion failed: ouch 1'); -} - -function testElement() { - assertThrows(goog.partial(goog.asserts.assertElement, null)); - assertThrows(goog.partial(goog.asserts.assertElement, 'foo')); - assertThrows(goog.partial(goog.asserts.assertElement, - goog.dom.createTextNode('foo'))); - var elem = goog.dom.createElement('div'); - assertEquals(elem, goog.asserts.assertElement(elem)); -} - -function testInstanceof() { - /** @constructor */ - var F = function() {}; - goog.asserts.assertInstanceof(new F(), F); - assertThrows('assertInstanceof({}, F)', - goog.partial(goog.asserts.assertInstanceof, {}, F)); - // IE lacks support for function.name and will fallback to toString(). - var object = goog.userAgent.IE ? '[object Object]' : 'Object'; - - // Test error messages. - doTestMessage(goog.partial(goog.asserts.assertInstanceof, {}, F), - 'Assertion failed: Expected instanceof unknown type name but got ' + - object + '.'); - doTestMessage(goog.partial(goog.asserts.assertInstanceof, {}, F, 'a %s', 1), - 'Assertion failed: a 1'); - doTestMessage(goog.partial(goog.asserts.assertInstanceof, null, F), - 'Assertion failed: Expected instanceof unknown type name but got null.'); - doTestMessage(goog.partial(goog.asserts.assertInstanceof, 5, F), - 'Assertion failed: ' + - 'Expected instanceof unknown type name but got number.'); - - // Test a constructor a with a name (IE does not support function.name). - if (!goog.userAgent.IE) { - F = function foo() {}; - doTestMessage(goog.partial(goog.asserts.assertInstanceof, {}, F), - 'Assertion failed: Expected instanceof foo but got ' + object + '.'); - } - - // Test a constructor with a displayName. - F.displayName = 'bar'; - doTestMessage(goog.partial(goog.asserts.assertInstanceof, {}, F), - 'Assertion failed: Expected instanceof bar but got ' + object + '.'); -} - -function testObjectPrototypeIsIntact() { - goog.asserts.assertObjectPrototypeIsIntact(); - var originalToString = Object.prototype.toString; - Object.prototype.toString = goog.nullFunction; - try { - goog.asserts.assertObjectPrototypeIsIntact(); - Object.prototype.foo = 1; - doTestMessage(goog.asserts.assertObjectPrototypeIsIntact, - 'Failure: foo should not be enumerable in Object.prototype.'); - } finally { - Object.prototype.toString = originalToString; - delete Object.prototype.foo; - } -} - -function testAssertionError() { - var error = new goog.asserts.AssertionError('foo %s %s', [1, 'two']); - assertEquals('Wrong message', 'foo 1 two', error.message); - assertEquals('Wrong messagePattern', 'foo %s %s', error.messagePattern); -} - -function testFailWithCustomErrorHandler() { - try { - var handledException; - goog.asserts.setErrorHandler( - function(e) { handledException = e; }); - - var expectedMessage = 'Failure: Gevalt!'; - - goog.asserts.fail('Gevalt!'); - assertTrue('handledException is null.', handledException != null); - assertTrue('Message check failed. Expected: ' + expectedMessage + - ' Actual: ' + handledException.message, - goog.string.startsWith(expectedMessage, handledException.message)); - } finally { - goog.asserts.setErrorHandler(goog.asserts.DEFAULT_ERROR_HANDLER); - } -} - -function testAssertWithCustomErrorHandler() { - try { - var handledException; - goog.asserts.setErrorHandler( - function(e) { handledException = e; }); - - var expectedMessage = 'Assertion failed: Gevalt!'; - - goog.asserts.assert(false, 'Gevalt!'); - assertTrue('handledException is null.', handledException != null); - assertTrue('Message check failed. Expected: ' + expectedMessage + - ' Actual: ' + handledException.message, - goog.string.startsWith(expectedMessage, handledException.message)); - } finally { - goog.asserts.setErrorHandler(goog.asserts.DEFAULT_ERROR_HANDLER); - } -} diff --git a/src/database/third_party/closure-library/closure/goog/async/animationdelay.js b/src/database/third_party/closure-library/closure/goog/async/animationdelay.js deleted file mode 100644 index 545cfb0cffe..00000000000 --- a/src/database/third_party/closure-library/closure/goog/async/animationdelay.js +++ /dev/null @@ -1,273 +0,0 @@ -// Copyright 2012 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview A delayed callback that pegs to the next animation frame - * instead of a user-configurable timeout. - * - * @author nicksantos@google.com (Nick Santos) - */ - -goog.provide('goog.async.AnimationDelay'); - -goog.require('goog.Disposable'); -goog.require('goog.events'); -goog.require('goog.functions'); - - - -// TODO(nicksantos): Should we factor out the common code between this and -// goog.async.Delay? I'm not sure if there's enough code for this to really -// make sense. Subclassing seems like the wrong approach for a variety of -// reasons. Maybe there should be a common interface? - - - -/** - * A delayed callback that pegs to the next animation frame - * instead of a user configurable timeout. By design, this should have - * the same interface as goog.async.Delay. - * - * Uses requestAnimationFrame and friends when available, but falls - * back to a timeout of goog.async.AnimationDelay.TIMEOUT. - * - * For more on requestAnimationFrame and how you can use it to create smoother - * animations, see: - * @see http://paulirish.com/2011/requestanimationframe-for-smart-animating/ - * - * @param {function(number)} listener Function to call when the delay completes. - * Will be passed the timestamp when it's called, in unix ms. - * @param {Window=} opt_window The window object to execute the delay in. - * Defaults to the global object. - * @param {Object=} opt_handler The object scope to invoke the function in. - * @constructor - * @extends {goog.Disposable} - * @final - */ -goog.async.AnimationDelay = function(listener, opt_window, opt_handler) { - goog.async.AnimationDelay.base(this, 'constructor'); - - /** - * The function that will be invoked after a delay. - * @type {function(number)} - * @private - */ - this.listener_ = listener; - - /** - * The object context to invoke the callback in. - * @type {Object|undefined} - * @private - */ - this.handler_ = opt_handler; - - /** - * @type {Window} - * @private - */ - this.win_ = opt_window || window; - - /** - * Cached callback function invoked when the delay finishes. - * @type {function()} - * @private - */ - this.callback_ = goog.bind(this.doAction_, this); -}; -goog.inherits(goog.async.AnimationDelay, goog.Disposable); - - -/** - * Identifier of the active delay timeout, or event listener, - * or null when inactive. - * @type {goog.events.Key|number|null} - * @private - */ -goog.async.AnimationDelay.prototype.id_ = null; - - -/** - * If we're using dom listeners. - * @type {?boolean} - * @private - */ -goog.async.AnimationDelay.prototype.usingListeners_ = false; - - -/** - * Default wait timeout for animations (in milliseconds). Only used for timed - * animation, which uses a timer (setTimeout) to schedule animation. - * - * @type {number} - * @const - */ -goog.async.AnimationDelay.TIMEOUT = 20; - - -/** - * Name of event received from the requestAnimationFrame in Firefox. - * - * @type {string} - * @const - * @private - */ -goog.async.AnimationDelay.MOZ_BEFORE_PAINT_EVENT_ = 'MozBeforePaint'; - - -/** - * Starts the delay timer. The provided listener function will be called - * before the next animation frame. - */ -goog.async.AnimationDelay.prototype.start = function() { - this.stop(); - this.usingListeners_ = false; - - var raf = this.getRaf_(); - var cancelRaf = this.getCancelRaf_(); - if (raf && !cancelRaf && this.win_.mozRequestAnimationFrame) { - // Because Firefox (Gecko) runs animation in separate threads, it also saves - // time by running the requestAnimationFrame callbacks in that same thread. - // Sadly this breaks the assumption of implicit thread-safety in JS, and can - // thus create thread-based inconsistencies on counters etc. - // - // Calling cycleAnimations_ using the MozBeforePaint event instead of as - // callback fixes this. - // - // Trigger this condition only if the mozRequestAnimationFrame is available, - // but not the W3C requestAnimationFrame function (as in draft) or the - // equivalent cancel functions. - this.id_ = goog.events.listen( - this.win_, - goog.async.AnimationDelay.MOZ_BEFORE_PAINT_EVENT_, - this.callback_); - this.win_.mozRequestAnimationFrame(null); - this.usingListeners_ = true; - } else if (raf && cancelRaf) { - this.id_ = raf.call(this.win_, this.callback_); - } else { - this.id_ = this.win_.setTimeout( - // Prior to Firefox 13, Gecko passed a non-standard parameter - // to the callback that we want to ignore. - goog.functions.lock(this.callback_), - goog.async.AnimationDelay.TIMEOUT); - } -}; - - -/** - * Stops the delay timer if it is active. No action is taken if the timer is not - * in use. - */ -goog.async.AnimationDelay.prototype.stop = function() { - if (this.isActive()) { - var raf = this.getRaf_(); - var cancelRaf = this.getCancelRaf_(); - if (raf && !cancelRaf && this.win_.mozRequestAnimationFrame) { - goog.events.unlistenByKey(this.id_); - } else if (raf && cancelRaf) { - cancelRaf.call(this.win_, /** @type {number} */ (this.id_)); - } else { - this.win_.clearTimeout(/** @type {number} */ (this.id_)); - } - } - this.id_ = null; -}; - - -/** - * Fires delay's action even if timer has already gone off or has not been - * started yet; guarantees action firing. Stops the delay timer. - */ -goog.async.AnimationDelay.prototype.fire = function() { - this.stop(); - this.doAction_(); -}; - - -/** - * Fires delay's action only if timer is currently active. Stops the delay - * timer. - */ -goog.async.AnimationDelay.prototype.fireIfActive = function() { - if (this.isActive()) { - this.fire(); - } -}; - - -/** - * @return {boolean} True if the delay is currently active, false otherwise. - */ -goog.async.AnimationDelay.prototype.isActive = function() { - return this.id_ != null; -}; - - -/** - * Invokes the callback function after the delay successfully completes. - * @private - */ -goog.async.AnimationDelay.prototype.doAction_ = function() { - if (this.usingListeners_ && this.id_) { - goog.events.unlistenByKey(this.id_); - } - this.id_ = null; - - // We are not using the timestamp returned by requestAnimationFrame - // because it may be either a Date.now-style time or a - // high-resolution time (depending on browser implementation). Using - // goog.now() will ensure that the timestamp used is consistent and - // compatible with goog.fx.Animation. - this.listener_.call(this.handler_, goog.now()); -}; - - -/** @override */ -goog.async.AnimationDelay.prototype.disposeInternal = function() { - this.stop(); - goog.async.AnimationDelay.base(this, 'disposeInternal'); -}; - - -/** - * @return {?function(function(number)): number} The requestAnimationFrame - * function, or null if not available on this browser. - * @private - */ -goog.async.AnimationDelay.prototype.getRaf_ = function() { - var win = this.win_; - return win.requestAnimationFrame || - win.webkitRequestAnimationFrame || - win.mozRequestAnimationFrame || - win.oRequestAnimationFrame || - win.msRequestAnimationFrame || - null; -}; - - -/** - * @return {?function(number): number} The cancelAnimationFrame function, - * or null if not available on this browser. - * @private - */ -goog.async.AnimationDelay.prototype.getCancelRaf_ = function() { - var win = this.win_; - return win.cancelAnimationFrame || - win.cancelRequestAnimationFrame || - win.webkitCancelRequestAnimationFrame || - win.mozCancelRequestAnimationFrame || - win.oCancelRequestAnimationFrame || - win.msCancelRequestAnimationFrame || - null; -}; diff --git a/src/database/third_party/closure-library/closure/goog/async/animationdelay_test.html b/src/database/third_party/closure-library/closure/goog/async/animationdelay_test.html deleted file mode 100644 index 49c027567e0..00000000000 --- a/src/database/third_party/closure-library/closure/goog/async/animationdelay_test.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - JsUnit tests for goog.async.AnimationDelay - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/async/animationdelay_test.js b/src/database/third_party/closure-library/closure/goog/async/animationdelay_test.js deleted file mode 100644 index 820ee586d04..00000000000 --- a/src/database/third_party/closure-library/closure/goog/async/animationdelay_test.js +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2012 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -goog.provide('goog.async.AnimationDelayTest'); -goog.setTestOnly('goog.async.AnimationDelayTest'); - -goog.require('goog.async.AnimationDelay'); -goog.require('goog.testing.AsyncTestCase'); -goog.require('goog.testing.PropertyReplacer'); -goog.require('goog.testing.jsunit'); -goog.require('goog.testing.recordFunction'); - -var testCase = goog.testing.AsyncTestCase.createAndInstall(); -var stubs = new goog.testing.PropertyReplacer(); - -function tearDown() { - stubs.reset(); -} - -function testStart() { - var callCount = 0; - var start = goog.now(); - var delay = new goog.async.AnimationDelay(function(end) { - callCount++; - }); - - delay.start(); - testCase.waitForAsync('waiting for delay'); - - window.setTimeout(function() { - testCase.continueTesting(); - assertEquals(1, callCount); - }, 500); -} - -function testStop() { - var callCount = 0; - var start = goog.now(); - var delay = new goog.async.AnimationDelay(function(end) { - callCount++; - }); - - delay.start(); - testCase.waitForAsync('waiting for delay'); - delay.stop(); - - window.setTimeout(function() { - testCase.continueTesting(); - assertEquals(0, callCount); - }, 500); -} - -function testAlwaysUseGoogNowForHandlerTimestamp() { - var expectedValue = 12345.1; - stubs.set(goog, 'now', function() { - return expectedValue; - }); - - var handler = goog.testing.recordFunction(function(timestamp) { - assertEquals(expectedValue, timestamp); - }); - var delay = new goog.async.AnimationDelay(handler); - - delay.start(); - testCase.waitForAsync('waiting for delay'); - - window.setTimeout(function() { - testCase.continueTesting(); - assertEquals(1, handler.getCallCount()); - }, 500); -} diff --git a/src/database/third_party/closure-library/closure/goog/async/conditionaldelay.js b/src/database/third_party/closure-library/closure/goog/async/conditionaldelay.js deleted file mode 100644 index 1e3897579fd..00000000000 --- a/src/database/third_party/closure-library/closure/goog/async/conditionaldelay.js +++ /dev/null @@ -1,235 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Defines a class useful for handling functions that must be - * invoked later when some condition holds. Examples include deferred function - * calls that return a boolean flag whether it succedeed or not. - * - * Example: - * - * function deferred() { - * var succeeded = false; - * // ... custom code - * return succeeded; - * } - * - * var deferredCall = new goog.async.ConditionalDelay(deferred); - * deferredCall.onSuccess = function() { - * alert('Success: The deferred function has been successfully executed.'); - * } - * deferredCall.onFailure = function() { - * alert('Failure: Time limit exceeded.'); - * } - * - * // Call the deferred() every 100 msec until it returns true, - * // or 5 seconds pass. - * deferredCall.start(100, 5000); - * - * // Stop the deferred function call (does nothing if it's not active). - * deferredCall.stop(); - * - */ - - -goog.provide('goog.async.ConditionalDelay'); - -goog.require('goog.Disposable'); -goog.require('goog.async.Delay'); - - - -/** - * A ConditionalDelay object invokes the associated function after a specified - * interval delay and checks its return value. If the function returns - * {@code true} the conditional delay is cancelled and {@see #onSuccess} - * is called. Otherwise this object keeps to invoke the deferred function until - * either it returns {@code true} or the timeout is exceeded. In the latter case - * the {@see #onFailure} method will be called. - * - * The interval duration and timeout can be specified each time the delay is - * started. Calling start on an active delay will reset the timer. - * - * @param {function():boolean} listener Function to call when the delay - * completes. Should return a value that type-converts to {@code true} if - * the call succeeded and this delay should be stopped. - * @param {Object=} opt_handler The object scope to invoke the function in. - * @constructor - * @extends {goog.Disposable} - */ -goog.async.ConditionalDelay = function(listener, opt_handler) { - goog.Disposable.call(this); - - /** - * The function that will be invoked after a delay. - * @type {function():boolean} - * @private - */ - this.listener_ = listener; - - /** - * The object context to invoke the callback in. - * @type {Object|undefined} - * @private - */ - this.handler_ = opt_handler; - - /** - * The underlying goog.async.Delay delegate object. - * @type {goog.async.Delay} - * @private - */ - this.delay_ = new goog.async.Delay( - goog.bind(this.onTick_, this), 0 /*interval*/, this /*scope*/); -}; -goog.inherits(goog.async.ConditionalDelay, goog.Disposable); - - -/** - * The delay interval in milliseconds to between the calls to the callback. - * Note, that the callback may be invoked earlier than this interval if the - * timeout is exceeded. - * @type {number} - * @private - */ -goog.async.ConditionalDelay.prototype.interval_ = 0; - - -/** - * The timeout timestamp until which the delay is to be executed. - * A negative value means no timeout. - * @type {number} - * @private - */ -goog.async.ConditionalDelay.prototype.runUntil_ = 0; - - -/** - * True if the listener has been executed, and it returned {@code true}. - * @type {boolean} - * @private - */ -goog.async.ConditionalDelay.prototype.isDone_ = false; - - -/** @override */ -goog.async.ConditionalDelay.prototype.disposeInternal = function() { - this.delay_.dispose(); - delete this.listener_; - delete this.handler_; - goog.async.ConditionalDelay.superClass_.disposeInternal.call(this); -}; - - -/** - * Starts the delay timer. The provided listener function will be called - * repeatedly after the specified interval until the function returns - * {@code true} or the timeout is exceeded. Calling start on an active timer - * will stop the timer first. - * @param {number=} opt_interval The time interval between the function - * invocations (in milliseconds). Default is 0. - * @param {number=} opt_timeout The timeout interval (in milliseconds). Takes - * precedence over the {@code opt_interval}, i.e. if the timeout is less - * than the invocation interval, the function will be called when the - * timeout is exceeded. A negative value means no timeout. Default is 0. - */ -goog.async.ConditionalDelay.prototype.start = function(opt_interval, - opt_timeout) { - this.stop(); - this.isDone_ = false; - - var timeout = opt_timeout || 0; - this.interval_ = Math.max(opt_interval || 0, 0); - this.runUntil_ = timeout < 0 ? -1 : (goog.now() + timeout); - this.delay_.start( - timeout < 0 ? this.interval_ : Math.min(this.interval_, timeout)); -}; - - -/** - * Stops the delay timer if it is active. No action is taken if the timer is not - * in use. - */ -goog.async.ConditionalDelay.prototype.stop = function() { - this.delay_.stop(); -}; - - -/** - * @return {boolean} True if the delay is currently active, false otherwise. - */ -goog.async.ConditionalDelay.prototype.isActive = function() { - return this.delay_.isActive(); -}; - - -/** - * @return {boolean} True if the listener has been executed and returned - * {@code true} since the last call to {@see #start}. - */ -goog.async.ConditionalDelay.prototype.isDone = function() { - return this.isDone_; -}; - - -/** - * Called when the listener has been successfully executed and returned - * {@code true}. The {@see #isDone} method should return {@code true} by now. - * Designed for inheritance, should be overridden by subclasses or on the - * instances if they care. - */ -goog.async.ConditionalDelay.prototype.onSuccess = function() { - // Do nothing by default. -}; - - -/** - * Called when this delayed call is cancelled because the timeout has been - * exceeded, and the listener has never returned {@code true}. - * Designed for inheritance, should be overridden by subclasses or on the - * instances if they care. - */ -goog.async.ConditionalDelay.prototype.onFailure = function() { - // Do nothing by default. -}; - - -/** - * A callback function for the underlying {@code goog.async.Delay} object. When - * executed the listener function is called, and if it returns {@code true} - * the delay is stopped and the {@see #onSuccess} method is invoked. - * If the timeout is exceeded the delay is stopped and the - * {@see #onFailure} method is called. - * @private - */ -goog.async.ConditionalDelay.prototype.onTick_ = function() { - var successful = this.listener_.call(this.handler_); - if (successful) { - this.isDone_ = true; - this.onSuccess(); - } else { - // Try to reschedule the task. - if (this.runUntil_ < 0) { - // No timeout. - this.delay_.start(this.interval_); - } else { - var timeLeft = this.runUntil_ - goog.now(); - if (timeLeft <= 0) { - this.onFailure(); - } else { - this.delay_.start(Math.min(this.interval_, timeLeft)); - } - } - } -}; diff --git a/src/database/third_party/closure-library/closure/goog/async/conditionaldelay_test.html b/src/database/third_party/closure-library/closure/goog/async/conditionaldelay_test.html deleted file mode 100644 index d0086443ae8..00000000000 --- a/src/database/third_party/closure-library/closure/goog/async/conditionaldelay_test.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - Closure Unit Tests - goog.async.ConditionalDelay - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/async/conditionaldelay_test.js b/src/database/third_party/closure-library/closure/goog/async/conditionaldelay_test.js deleted file mode 100644 index 6bd105bcdfc..00000000000 --- a/src/database/third_party/closure-library/closure/goog/async/conditionaldelay_test.js +++ /dev/null @@ -1,222 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -goog.provide('goog.async.ConditionalDelayTest'); -goog.setTestOnly('goog.async.ConditionalDelayTest'); - -goog.require('goog.async.ConditionalDelay'); -goog.require('goog.testing.MockClock'); -goog.require('goog.testing.jsunit'); - -var invoked = false; -var delay = null; -var clock = null; -var returnValue = true; -var onSuccessCalled = false; -var onFailureCalled = false; - - -function callback() { - invoked = true; - return returnValue; -} - - -function setUp() { - clock = new goog.testing.MockClock(true); - invoked = false; - returnValue = true; - onSuccessCalled = false; - onFailureCalled = false; - delay = new goog.async.ConditionalDelay(callback); - delay.onSuccess = function() { - onSuccessCalled = true; - }; - delay.onFailure = function() { - onFailureCalled = true; - }; -} - - -function tearDown() { - clock.dispose(); - delay.dispose(); -} - - -function testDelay() { - delay.start(200, 200); - assertFalse(invoked); - - clock.tick(100); - assertFalse(invoked); - - clock.tick(100); - assertTrue(invoked); -} - - -function testStop() { - delay.start(200, 500); - assertTrue(delay.isActive()); - - clock.tick(100); - assertFalse(invoked); - - delay.stop(); - clock.tick(100); - assertFalse(invoked); - - assertFalse(delay.isActive()); -} - - -function testIsActive() { - assertFalse(delay.isActive()); - delay.start(200, 200); - assertTrue(delay.isActive()); - clock.tick(200); - assertFalse(delay.isActive()); -} - - -function testRestart() { - delay.start(200, 50000); - clock.tick(100); - - delay.stop(); - assertFalse(invoked); - - delay.start(200, 50000); - clock.tick(199); - assertFalse(invoked); - - clock.tick(1); - assertTrue(invoked); - - invoked = false; - delay.start(200, 200); - clock.tick(200); - assertTrue(invoked); - - assertFalse(delay.isActive()); -} - - -function testDispose() { - delay.start(200, 200); - delay.dispose(); - assertTrue(delay.isDisposed()); - - clock.tick(500); - assertFalse(invoked); -} - - -function testConditionalDelay_Success() { - returnValue = false; - delay.start(100, 300); - - clock.tick(99); - assertFalse(invoked); - clock.tick(1); - assertTrue(invoked); - - assertTrue(delay.isActive()); - assertFalse(delay.isDone()); - assertFalse(onSuccessCalled); - assertFalse(onFailureCalled); - - returnValue = true; - - invoked = false; - clock.tick(100); - assertTrue(invoked); - - assertFalse(delay.isActive()); - assertTrue(delay.isDone()); - assertTrue(onSuccessCalled); - assertFalse(onFailureCalled); - - invoked = false; - clock.tick(200); - assertFalse(invoked); -} - - -function testConditionalDelay_Failure() { - returnValue = false; - delay.start(100, 300); - - clock.tick(99); - assertFalse(invoked); - clock.tick(1); - assertTrue(invoked); - - assertTrue(delay.isActive()); - assertFalse(delay.isDone()); - assertFalse(onSuccessCalled); - assertFalse(onFailureCalled); - - invoked = false; - clock.tick(100); - assertTrue(invoked); - assertFalse(onSuccessCalled); - assertFalse(onFailureCalled); - - invoked = false; - clock.tick(90); - assertFalse(invoked); - clock.tick(10); - assertTrue(invoked); - - assertFalse(delay.isActive()); - assertFalse(delay.isDone()); - assertFalse(onSuccessCalled); - assertTrue(onFailureCalled); -} - - -function testInfiniteDelay() { - returnValue = false; - delay.start(100, -1); - - // Test in a big enough loop. - for (var i = 0; i < 1000; ++i) { - clock.tick(80); - assertTrue(delay.isActive()); - assertFalse(delay.isDone()); - assertFalse(onSuccessCalled); - assertFalse(onFailureCalled); - } - - delay.stop(); - assertFalse(delay.isActive()); - assertFalse(delay.isDone()); - assertFalse(onSuccessCalled); - assertFalse(onFailureCalled); -} - -function testCallbackScope() { - var callbackCalled = false; - var scopeObject = {}; - function internalCallback() { - assertEquals(this, scopeObject); - callbackCalled = true; - return true; - } - delay = new goog.async.ConditionalDelay(internalCallback, scopeObject); - delay.start(200, 200); - clock.tick(201); - assertTrue(callbackCalled); -} diff --git a/src/database/third_party/closure-library/closure/goog/async/delay.js b/src/database/third_party/closure-library/closure/goog/async/delay.js deleted file mode 100644 index 175e0761f06..00000000000 --- a/src/database/third_party/closure-library/closure/goog/async/delay.js +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Defines a class useful for handling functions that must be - * invoked after a delay, especially when that delay is frequently restarted. - * Examples include delaying before displaying a tooltip, menu hysteresis, - * idle timers, etc. - * @author brenneman@google.com (Shawn Brenneman) - * @see ../demos/timers.html - */ - - -goog.provide('goog.Delay'); -goog.provide('goog.async.Delay'); - -goog.require('goog.Disposable'); -goog.require('goog.Timer'); - - - -/** - * A Delay object invokes the associated function after a specified delay. The - * interval duration can be specified once in the constructor, or can be defined - * each time the delay is started. Calling start on an active delay will reset - * the timer. - * - * @param {function(this:THIS)} listener Function to call when the - * delay completes. - * @param {number=} opt_interval The default length of the invocation delay (in - * milliseconds). - * @param {THIS=} opt_handler The object scope to invoke the function in. - * @template THIS - * @constructor - * @extends {goog.Disposable} - * @final - */ -goog.async.Delay = function(listener, opt_interval, opt_handler) { - goog.Disposable.call(this); - - /** - * The function that will be invoked after a delay. - * @private {function(this:THIS)} - */ - this.listener_ = listener; - - /** - * The default amount of time to delay before invoking the callback. - * @type {number} - * @private - */ - this.interval_ = opt_interval || 0; - - /** - * The object context to invoke the callback in. - * @type {Object|undefined} - * @private - */ - this.handler_ = opt_handler; - - - /** - * Cached callback function invoked when the delay finishes. - * @type {Function} - * @private - */ - this.callback_ = goog.bind(this.doAction_, this); -}; -goog.inherits(goog.async.Delay, goog.Disposable); - - - -/** - * A deprecated alias. - * @deprecated Use goog.async.Delay instead. - * @constructor - * @final - */ -goog.Delay = goog.async.Delay; - - -/** - * Identifier of the active delay timeout, or 0 when inactive. - * @type {number} - * @private - */ -goog.async.Delay.prototype.id_ = 0; - - -/** - * Disposes of the object, cancelling the timeout if it is still outstanding and - * removing all object references. - * @override - * @protected - */ -goog.async.Delay.prototype.disposeInternal = function() { - goog.async.Delay.superClass_.disposeInternal.call(this); - this.stop(); - delete this.listener_; - delete this.handler_; -}; - - -/** - * Starts the delay timer. The provided listener function will be called after - * the specified interval. Calling start on an active timer will reset the - * delay interval. - * @param {number=} opt_interval If specified, overrides the object's default - * interval with this one (in milliseconds). - */ -goog.async.Delay.prototype.start = function(opt_interval) { - this.stop(); - this.id_ = goog.Timer.callOnce( - this.callback_, - goog.isDef(opt_interval) ? opt_interval : this.interval_); -}; - - -/** - * Stops the delay timer if it is active. No action is taken if the timer is not - * in use. - */ -goog.async.Delay.prototype.stop = function() { - if (this.isActive()) { - goog.Timer.clear(this.id_); - } - this.id_ = 0; -}; - - -/** - * Fires delay's action even if timer has already gone off or has not been - * started yet; guarantees action firing. Stops the delay timer. - */ -goog.async.Delay.prototype.fire = function() { - this.stop(); - this.doAction_(); -}; - - -/** - * Fires delay's action only if timer is currently active. Stops the delay - * timer. - */ -goog.async.Delay.prototype.fireIfActive = function() { - if (this.isActive()) { - this.fire(); - } -}; - - -/** - * @return {boolean} True if the delay is currently active, false otherwise. - */ -goog.async.Delay.prototype.isActive = function() { - return this.id_ != 0; -}; - - -/** - * Invokes the callback function after the delay successfully completes. - * @private - */ -goog.async.Delay.prototype.doAction_ = function() { - this.id_ = 0; - if (this.listener_) { - this.listener_.call(this.handler_); - } -}; diff --git a/src/database/third_party/closure-library/closure/goog/async/delay_test.html b/src/database/third_party/closure-library/closure/goog/async/delay_test.html deleted file mode 100644 index 3042a366fe9..00000000000 --- a/src/database/third_party/closure-library/closure/goog/async/delay_test.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - Closure Unit Tests - goog.async.Delay - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/async/delay_test.js b/src/database/third_party/closure-library/closure/goog/async/delay_test.js deleted file mode 100644 index f97b74c9001..00000000000 --- a/src/database/third_party/closure-library/closure/goog/async/delay_test.js +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -goog.provide('goog.async.DelayTest'); -goog.setTestOnly('goog.async.DelayTest'); - -goog.require('goog.async.Delay'); -goog.require('goog.testing.MockClock'); -goog.require('goog.testing.jsunit'); - -var invoked = false; -var delay = null; -var clock = null; - - -function callback() { - invoked = true; -} - - -function setUp() { - clock = new goog.testing.MockClock(true); - invoked = false; - delay = new goog.async.Delay(callback, 200); -} - -function tearDown() { - clock.dispose(); - delay.dispose(); -} - - -function testDelay() { - delay.start(); - assertFalse(invoked); - - clock.tick(100); - assertFalse(invoked); - - clock.tick(100); - assertTrue(invoked); -} - - -function testStop() { - delay.start(); - - clock.tick(100); - assertFalse(invoked); - - delay.stop(); - clock.tick(100); - assertFalse(invoked); -} - - -function testIsActive() { - assertFalse(delay.isActive()); - delay.start(); - assertTrue(delay.isActive()); - clock.tick(200); - assertFalse(delay.isActive()); -} - - -function testRestart() { - delay.start(); - clock.tick(100); - - delay.stop(); - assertFalse(invoked); - - delay.start(); - clock.tick(199); - assertFalse(invoked); - - clock.tick(1); - assertTrue(invoked); - - invoked = false; - delay.start(); - clock.tick(200); - assertTrue(invoked); -} - - -function testOverride() { - delay.start(50); - clock.tick(49); - assertFalse(invoked); - - clock.tick(1); - assertTrue(invoked); -} - - -function testDispose() { - delay.start(); - delay.dispose(); - assertTrue(delay.isDisposed()); - - clock.tick(500); - assertFalse(invoked); -} - - -function testFire() { - delay.start(); - - clock.tick(50); - delay.fire(); - assertTrue(invoked); - assertFalse(delay.isActive()); - - invoked = false; - clock.tick(200); - assertFalse('Delay fired early with fire call, timeout should have been ' + - 'cleared', invoked); -} - -function testFireIfActive() { - delay.fireIfActive(); - assertFalse(invoked); - - delay.start(); - delay.fireIfActive(); - assertTrue(invoked); - invoked = false; - clock.tick(300); - assertFalse('Delay fired early with fireIfActive, timeout should have been ' + - 'cleared', invoked); -} diff --git a/src/database/third_party/closure-library/closure/goog/async/nexttick.js b/src/database/third_party/closure-library/closure/goog/async/nexttick.js deleted file mode 100644 index c5715bc193d..00000000000 --- a/src/database/third_party/closure-library/closure/goog/async/nexttick.js +++ /dev/null @@ -1,240 +0,0 @@ -// Copyright 2013 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Provides a function to schedule running a function as soon - * as possible after the current JS execution stops and yields to the event - * loop. - * - */ - -goog.provide('goog.async.nextTick'); -goog.provide('goog.async.throwException'); - -goog.require('goog.debug.entryPointRegistry'); -goog.require('goog.functions'); -goog.require('goog.labs.userAgent.browser'); -goog.require('goog.labs.userAgent.engine'); - - -/** - * Throw an item without interrupting the current execution context. For - * example, if processing a group of items in a loop, sometimes it is useful - * to report an error while still allowing the rest of the batch to be - * processed. - * @param {*} exception - */ -goog.async.throwException = function(exception) { - // Each throw needs to be in its own context. - goog.global.setTimeout(function() { throw exception; }, 0); -}; - - -/** - * Fires the provided callbacks as soon as possible after the current JS - * execution context. setTimeout(…, 0) takes at least 4ms when called from - * within another setTimeout(…, 0) for legacy reasons. - * - * This will not schedule the callback as a microtask (i.e. a task that can - * preempt user input or networking callbacks). It is meant to emulate what - * setTimeout(_, 0) would do if it were not throttled. If you desire microtask - * behavior, use {@see goog.Promise} instead. - * - * @param {function(this:SCOPE)} callback Callback function to fire as soon as - * possible. - * @param {SCOPE=} opt_context Object in whose scope to call the listener. - * @param {boolean=} opt_useSetImmediate Avoid the IE workaround that - * ensures correctness at the cost of speed. See comments for details. - * @template SCOPE - */ -goog.async.nextTick = function(callback, opt_context, opt_useSetImmediate) { - var cb = callback; - if (opt_context) { - cb = goog.bind(callback, opt_context); - } - cb = goog.async.nextTick.wrapCallback_(cb); - // window.setImmediate was introduced and currently only supported by IE10+, - // but due to a bug in the implementation it is not guaranteed that - // setImmediate is faster than setTimeout nor that setImmediate N is before - // setImmediate N+1. That is why we do not use the native version if - // available. We do, however, call setImmediate if it is a normal function - // because that indicates that it has been replaced by goog.testing.MockClock - // which we do want to support. - // See - // http://connect.microsoft.com/IE/feedback/details/801823/setimmediate-and-messagechannel-are-broken-in-ie10 - // - // Note we do allow callers to also request setImmediate if they are willing - // to accept the possible tradeoffs of incorrectness in exchange for speed. - // The IE fallback of readystate change is much slower. - if (goog.isFunction(goog.global.setImmediate) && - // Opt in. - (opt_useSetImmediate || - // or it isn't a browser or the environment is weird - !goog.global.Window || !goog.global.Window.prototype || - // or something redefined setImmediate in which case we (YOLO) decide - // to use it (This is so that we use the mockClock setImmediate. sigh). - goog.global.Window.prototype.setImmediate != goog.global.setImmediate)) { - goog.global.setImmediate(cb); - return; - } - - // Look for and cache the custom fallback version of setImmediate. - if (!goog.async.nextTick.setImmediate_) { - goog.async.nextTick.setImmediate_ = - goog.async.nextTick.getSetImmediateEmulator_(); - } - goog.async.nextTick.setImmediate_(cb); -}; - - -/** - * Cache for the setImmediate implementation. - * @type {function(function())} - * @private - */ -goog.async.nextTick.setImmediate_; - - -/** - * Determines the best possible implementation to run a function as soon as - * the JS event loop is idle. - * @return {function(function())} The "setImmediate" implementation. - * @private - */ -goog.async.nextTick.getSetImmediateEmulator_ = function() { - // Create a private message channel and use it to postMessage empty messages - // to ourselves. - var Channel = goog.global['MessageChannel']; - // If MessageChannel is not available and we are in a browser, implement - // an iframe based polyfill in browsers that have postMessage and - // document.addEventListener. The latter excludes IE8 because it has a - // synchronous postMessage implementation. - if (typeof Channel === 'undefined' && typeof window !== 'undefined' && - window.postMessage && window.addEventListener && - // Presto (The old pre-blink Opera engine) has problems with iframes - // and contentWindow. - !goog.labs.userAgent.engine.isPresto()) { - /** @constructor */ - Channel = function() { - // Make an empty, invisible iframe. - var iframe = document.createElement('iframe'); - iframe.style.display = 'none'; - iframe.src = ''; - document.documentElement.appendChild(iframe); - var win = iframe.contentWindow; - var doc = win.document; - doc.open(); - doc.write(''); - doc.close(); - // Do not post anything sensitive over this channel, as the workaround for - // pages with file: origin could allow that information to be modified or - // intercepted. - var message = 'callImmediate' + Math.random(); - // The same origin policy rejects attempts to postMessage from file: urls - // unless the origin is '*'. - // TODO(b/16335441): Use '*' origin for data: and other similar protocols. - var origin = win.location.protocol == 'file:' ? - '*' : win.location.protocol + '//' + win.location.host; - var onmessage = goog.bind(function(e) { - // Validate origin and message to make sure that this message was - // intended for us. If the origin is set to '*' (see above) only the - // message needs to match since, for example, '*' != 'file://'. Allowing - // the wildcard is ok, as we are not concerned with security here. - if ((origin != '*' && e.origin != origin) || e.data != message) { - return; - } - this['port1'].onmessage(); - }, this); - win.addEventListener('message', onmessage, false); - this['port1'] = {}; - this['port2'] = { - postMessage: function() { - win.postMessage(message, origin); - } - }; - }; - } - if (typeof Channel !== 'undefined' && - (!goog.labs.userAgent.browser.isIE())) { - // Exclude all of IE due to - // http://codeforhire.com/2013/09/21/setimmediate-and-messagechannel-broken-on-internet-explorer-10/ - // which allows starving postMessage with a busy setTimeout loop. - // This currently affects IE10 and IE11 which would otherwise be able - // to use the postMessage based fallbacks. - var channel = new Channel(); - // Use a fifo linked list to call callbacks in the right order. - var head = {}; - var tail = head; - channel['port1'].onmessage = function() { - if (goog.isDef(head.next)) { - head = head.next; - var cb = head.cb; - head.cb = null; - cb(); - } - }; - return function(cb) { - tail.next = { - cb: cb - }; - tail = tail.next; - channel['port2'].postMessage(0); - }; - } - // Implementation for IE6+: Script elements fire an asynchronous - // onreadystatechange event when inserted into the DOM. - if (typeof document !== 'undefined' && 'onreadystatechange' in - document.createElement('script')) { - return function(cb) { - var script = document.createElement('script'); - script.onreadystatechange = function() { - // Clean up and call the callback. - script.onreadystatechange = null; - script.parentNode.removeChild(script); - script = null; - cb(); - cb = null; - }; - document.documentElement.appendChild(script); - }; - } - // Fall back to setTimeout with 0. In browsers this creates a delay of 5ms - // or more. - return function(cb) { - goog.global.setTimeout(cb, 0); - }; -}; - - -/** - * Helper function that is overrided to protect callbacks with entry point - * monitor if the application monitors entry points. - * @param {function()} callback Callback function to fire as soon as possible. - * @return {function()} The wrapped callback. - * @private - */ -goog.async.nextTick.wrapCallback_ = goog.functions.identity; - - -// Register the callback function as an entry point, so that it can be -// monitored for exception handling, etc. This has to be done in this file -// since it requires special code to handle all browsers. -goog.debug.entryPointRegistry.register( - /** - * @param {function(!Function): !Function} transformer The transforming - * function. - */ - function(transformer) { - goog.async.nextTick.wrapCallback_ = transformer; - }); diff --git a/src/database/third_party/closure-library/closure/goog/async/nexttick_test.html b/src/database/third_party/closure-library/closure/goog/async/nexttick_test.html deleted file mode 100644 index 556f4c123d3..00000000000 --- a/src/database/third_party/closure-library/closure/goog/async/nexttick_test.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - Closure Unit Tests - goog.async.nextTick - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/async/nexttick_test.js b/src/database/third_party/closure-library/closure/goog/async/nexttick_test.js deleted file mode 100644 index 353f4b680c8..00000000000 --- a/src/database/third_party/closure-library/closure/goog/async/nexttick_test.js +++ /dev/null @@ -1,250 +0,0 @@ -// Copyright 2013 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -goog.provide('goog.async.nextTickTest'); -goog.setTestOnly('goog.async.nextTickTest'); - -goog.require('goog.async.nextTick'); -goog.require('goog.debug.ErrorHandler'); -goog.require('goog.debug.entryPointRegistry'); -goog.require('goog.dom'); -goog.require('goog.labs.userAgent.browser'); -goog.require('goog.testing.AsyncTestCase'); -goog.require('goog.testing.MockClock'); -goog.require('goog.testing.PropertyReplacer'); -goog.require('goog.testing.jsunit'); - -var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall( - 'asyncNextTickTest'); - -var clock; -var propertyReplacer = new goog.testing.PropertyReplacer(); - -function setUp() { - clock = null; -} - -function tearDown() { - if (clock) { - clock.uninstall(); - } - goog.async.nextTick.setImmediate_ = undefined; - propertyReplacer.reset(); -} - - -function testNextTick() { - var c = 0; - var max = 100; - var async = true; - var counterStep = function(i) { - async = false; - assertEquals('Order correct', i, c); - c++; - if (c === max) { - asyncTestCase.continueTesting(); - } - }; - for (var i = 0; i < max; i++) { - goog.async.nextTick(goog.partial(counterStep, i)); - } - assertTrue(async); - asyncTestCase.waitForAsync('Wait for callback'); -} - - -function testNextTickSetImmediate() { - var c = 0; - var max = 100; - var async = true; - var counterStep = function(i) { - async = false; - assertEquals('Order correct', i, c); - c++; - if (c === max) { - asyncTestCase.continueTesting(); - } - }; - for (var i = 0; i < max; i++) { - goog.async.nextTick(goog.partial(counterStep, i), undefined, - /* opt_useSetImmediate */ true); - } - assertTrue(async); - asyncTestCase.waitForAsync('Wait for callback'); -} - -function testNextTickContext() { - var context = {}; - var c = 0; - var max = 10; - var async = true; - var counterStep = function(i) { - async = false; - assertEquals('Order correct', i, c); - assertEquals(context, this); - c++; - if (c === max) { - asyncTestCase.continueTesting(); - } - }; - for (var i = 0; i < max; i++) { - goog.async.nextTick(goog.partial(counterStep, i), context); - } - assertTrue(async); - asyncTestCase.waitForAsync('Wait for callback'); -} - - -function testNextTickMockClock() { - clock = new goog.testing.MockClock(true); - var result = ''; - goog.async.nextTick(function() { - result += 'a'; - }); - goog.async.nextTick(function() { - result += 'b'; - }); - goog.async.nextTick(function() { - result += 'c'; - }); - assertEquals('', result); - clock.tick(0); - assertEquals('abc', result); -} - - -function testNextTickDoesntSwallowError() { - var before = window.onerror; - var sentinel = 'sentinel'; - window.onerror = function(e) { - e = '' + e; - // Don't test for contents in IE7, which does not preserve the exception - // message. - if (e.indexOf('Exception thrown and not caught') == -1) { - assertContains(sentinel, e); - } - window.onerror = before; - asyncTestCase.continueTesting(); - return false; - }; - goog.async.nextTick(function() { - throw sentinel; - }); - asyncTestCase.waitForAsync('Wait for error'); -} - - -function testNextTickProtectEntryPoint() { - var errorHandlerCallbackCalled = false; - var errorHandler = new goog.debug.ErrorHandler(function() { - errorHandlerCallbackCalled = true; - }); - - // This is only testing wrapping the callback with the protected entry point, - // so it's okay to replace this function with a fake. - goog.async.nextTick.setImmediate_ = function(cb) { - try { - cb(); - fail('The callback should have thrown an error.'); - } catch (e) { - assertTrue( - e instanceof goog.debug.ErrorHandler.ProtectedFunctionError); - } - asyncTestCase.continueTesting(); - }; - var origSetImmediate; - if (window.setImmediate) { - origSetImmediate = window.setImmediate; - window.setImmediate = goog.async.nextTick.setImmediate_; - } - goog.debug.entryPointRegistry.monitorAll(errorHandler); - - function thrower() { - throw Error('This should be caught by the protected function.'); - } - asyncTestCase.waitForAsync('Wait for callback'); - goog.async.nextTick(thrower); - window.setImmediate = origSetImmediate; -} - - -function testNextTick_notStarvedBySetTimeout() { - // This test will timeout when affected by - // http://codeforhire.com/2013/09/21/setimmediate-and-messagechannel-broken-on-internet-explorer-10/ - // This test would fail without the fix introduced in cl/72472221 - // It keeps scheduling 0 timeouts and a single nextTick. If the nextTick - // ever fires, the IE specific problem does not occur. - var timeout; - function busy() { - timeout = setTimeout(function() { - busy(); - }, 0); - } - busy(); - goog.async.nextTick(function() { - if (timeout) { - clearTimeout(timeout); - } - asyncTestCase.continueTesting(); - }); - asyncTestCase.waitForAsync('Waiting not to starve'); -} - - -/** - * Test a scenario in which the iframe used by the postMessage polyfill gets a - * message that does not have match what is expected. In this case, the polyfill - * should not try to invoke a callback (which would result in an error because - * there would be no callbacks in the linked list). - */ -function testPostMessagePolyfillDoesNotPumpCallbackQueueIfMessageIsIncorrect() { - // IE does not use the postMessage polyfill. - if (goog.labs.userAgent.browser.isIE()) { - return; - } - - // Force postMessage pollyfill for setImmediate. - propertyReplacer.set(window, 'setImmediate', undefined); - propertyReplacer.set(window, 'MessageChannel', undefined); - - var callbackCalled = false; - goog.async.nextTick(function() { - callbackCalled = true; - }); - - var frame = document.getElementsByTagName('iframe')[0]; - frame.contentWindow.postMessage('bogus message', - window.location.protocol + '//' + window.location.host); - - var error = null; - frame.contentWindow.onerror = function(e) { - error = e; - }; - - setTimeout(function() { - assert('Callback should have been called.', callbackCalled); - assertNull('An unexpected error was thrown.', error); - goog.dom.removeNode(frame); - asyncTestCase.continueTesting(); - }, 0); - - asyncTestCase.waitForAsync('Waiting for callbacks to be invoked.'); -} - - -function testBehaviorOnPagesWithOverriddenWindowConstructor() { - propertyReplacer.set(goog.global, 'Window', {}); - testNextTick(); - testNextTickSetImmediate(); - testNextTickMockClock(); -} diff --git a/src/database/third_party/closure-library/closure/goog/async/run.js b/src/database/third_party/closure-library/closure/goog/async/run.js deleted file mode 100644 index 4dbd3323fc0..00000000000 --- a/src/database/third_party/closure-library/closure/goog/async/run.js +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2013 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.async.run'); - -goog.require('goog.async.nextTick'); -goog.require('goog.async.throwException'); -goog.require('goog.testing.watchers'); - - -/** - * Fires the provided callback just before the current callstack unwinds, or as - * soon as possible after the current JS execution context. - * @param {function(this:THIS)} callback - * @param {THIS=} opt_context Object to use as the "this value" when calling - * the provided function. - * @template THIS - */ -goog.async.run = function(callback, opt_context) { - if (!goog.async.run.schedule_) { - goog.async.run.initializeRunner_(); - } - if (!goog.async.run.workQueueScheduled_) { - // Nothing is currently scheduled, schedule it now. - goog.async.run.schedule_(); - goog.async.run.workQueueScheduled_ = true; - } - - goog.async.run.workQueue_.push( - new goog.async.run.WorkItem_(callback, opt_context)); -}; - - -/** - * Initializes the function to use to process the work queue. - * @private - */ -goog.async.run.initializeRunner_ = function() { - // If native Promises are available in the browser, just schedule the callback - // on a fulfilled promise, which is specified to be async, but as fast as - // possible. - if (goog.global.Promise && goog.global.Promise.resolve) { - var promise = goog.global.Promise.resolve(); - goog.async.run.schedule_ = function() { - promise.then(goog.async.run.processWorkQueue); - }; - } else { - goog.async.run.schedule_ = function() { - goog.async.nextTick(goog.async.run.processWorkQueue); - }; - } -}; - - -/** - * Forces goog.async.run to use nextTick instead of Promise. - * - * This should only be done in unit tests. It's useful because MockClock - * replaces nextTick, but not the browser Promise implementation, so it allows - * Promise-based code to be tested with MockClock. - */ -goog.async.run.forceNextTick = function() { - goog.async.run.schedule_ = function() { - goog.async.nextTick(goog.async.run.processWorkQueue); - }; -}; - - -/** - * The function used to schedule work asynchronousely. - * @private {function()} - */ -goog.async.run.schedule_; - - -/** @private {boolean} */ -goog.async.run.workQueueScheduled_ = false; - - -/** @private {!Array} */ -goog.async.run.workQueue_ = []; - - -if (goog.DEBUG) { - /** - * Reset the event queue. - * @private - */ - goog.async.run.resetQueue_ = function() { - goog.async.run.workQueueScheduled_ = false; - goog.async.run.workQueue_ = []; - }; - - // If there is a clock implemenation in use for testing - // and it is reset, reset the queue. - goog.testing.watchers.watchClockReset(goog.async.run.resetQueue_); -} - - -/** - * Run any pending goog.async.run work items. This function is not intended - * for general use, but for use by entry point handlers to run items ahead of - * goog.async.nextTick. - */ -goog.async.run.processWorkQueue = function() { - // NOTE: additional work queue items may be pushed while processing. - while (goog.async.run.workQueue_.length) { - // Don't let the work queue grow indefinitely. - var workItems = goog.async.run.workQueue_; - goog.async.run.workQueue_ = []; - for (var i = 0; i < workItems.length; i++) { - var workItem = workItems[i]; - try { - workItem.fn.call(workItem.scope); - } catch (e) { - goog.async.throwException(e); - } - } - } - - // There are no more work items, reset the work queue. - goog.async.run.workQueueScheduled_ = false; -}; - - - -/** - * @constructor - * @final - * @struct - * @private - * - * @param {function()} fn - * @param {Object|null|undefined} scope - */ -goog.async.run.WorkItem_ = function(fn, scope) { - /** @const */ this.fn = fn; - /** @const */ this.scope = scope; -}; diff --git a/src/database/third_party/closure-library/closure/goog/async/run_test.js b/src/database/third_party/closure-library/closure/goog/async/run_test.js deleted file mode 100644 index 56d20526fa4..00000000000 --- a/src/database/third_party/closure-library/closure/goog/async/run_test.js +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright 2013 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.async.runTest'); - -goog.require('goog.async.run'); -goog.require('goog.testing.MockClock'); -goog.require('goog.testing.jsunit'); -goog.require('goog.testing.recordFunction'); - -goog.setTestOnly('goog.async.runTest'); - - -var mockClock; -var futureCallback1, futureCallback2; - -function setUpPage() { - mockClock = new goog.testing.MockClock(); - mockClock.install(); -} - -function setUp() { - mockClock.reset(); - futureCallback1 = new goog.testing.recordFunction(); - futureCallback2 = new goog.testing.recordFunction(); -} - -function tearDown() { - futureCallback1 = null; - futureCallback2 = null; -} - -function tearDownPage() { - mockClock.uninstall(); - goog.dispose(mockClock); -} - -function testCalledAsync() { - goog.async.run(futureCallback1); - goog.async.run(futureCallback2); - - assertEquals(0, futureCallback1.getCallCount()); - assertEquals(0, futureCallback2.getCallCount()); - - // but the callbacks are scheduled... - mockClock.tick(); - - // and called. - assertEquals(1, futureCallback1.getCallCount()); - assertEquals(1, futureCallback2.getCallCount()); - - // and aren't called a second time. - assertEquals(1, futureCallback1.getCallCount()); - assertEquals(1, futureCallback2.getCallCount()); -} - -function testSequenceCalledInOrder() { - futureCallback1 = new goog.testing.recordFunction( - function() { - // called before futureCallback2 - assertEquals(0, futureCallback2.getCallCount()); - }); - futureCallback2 = new goog.testing.recordFunction( - function() { - // called after futureCallback1 - assertEquals(1, futureCallback1.getCallCount()); - }); - goog.async.run(futureCallback1); - goog.async.run(futureCallback2); - - // goog.async.run doesn't call the top callback immediately. - assertEquals(0, futureCallback1.getCallCount()); - - // but the callbacks are scheduled... - mockClock.tick(); - - // and called during the same "tick". - assertEquals(1, futureCallback1.getCallCount()); - assertEquals(1, futureCallback2.getCallCount()); -} - -function testSequenceScheduledTwice() { - goog.async.run(futureCallback1); - goog.async.run(futureCallback1); - - // goog.async.run doesn't call the top callback immediately. - assertEquals(0, futureCallback1.getCallCount()); - - // but the callbacks are scheduled... - mockClock.tick(); - - // and called twice during the same "tick". - assertEquals(2, futureCallback1.getCallCount()); -} - -function testSequenceCalledSync() { - futureCallback1 = new goog.testing.recordFunction( - function() { - goog.async.run(futureCallback2); - // goog.async.run doesn't call the inner callback immediately. - assertEquals(0, futureCallback2.getCallCount()); - }); - goog.async.run(futureCallback1); - - // goog.async.run doesn't call the top callback immediately. - assertEquals(0, futureCallback1.getCallCount()); - - // but the callbacks are scheduled... - mockClock.tick(); - - // and called during the same "tick". - assertEquals(1, futureCallback1.getCallCount()); - assertEquals(1, futureCallback2.getCallCount()); -} - -function testScope() { - var aScope = {}; - goog.async.run(futureCallback1); - goog.async.run(futureCallback2, aScope); - - // the callbacks are scheduled... - mockClock.tick(); - - // and called. - assertEquals(1, futureCallback1.getCallCount()); - assertEquals(1, futureCallback2.getCallCount()); - - // and get the correct scope. - var last1 = futureCallback1.popLastCall(); - assertEquals(0, last1.getArguments().length); - assertEquals(goog.global, last1.getThis()); - - var last2 = futureCallback2.popLastCall(); - assertEquals(0, last2.getArguments().length); - assertEquals(aScope, last2.getThis()); -} diff --git a/src/database/third_party/closure-library/closure/goog/async/throttle.js b/src/database/third_party/closure-library/closure/goog/async/throttle.js deleted file mode 100644 index 939738eea41..00000000000 --- a/src/database/third_party/closure-library/closure/goog/async/throttle.js +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Definition of the goog.async.Throttle class. - * - * @see ../demos/timers.html - */ - -goog.provide('goog.Throttle'); -goog.provide('goog.async.Throttle'); - -goog.require('goog.Disposable'); -goog.require('goog.Timer'); - - - -/** - * Throttle will perform an action that is passed in no more than once - * per interval (specified in milliseconds). If it gets multiple signals - * to perform the action while it is waiting, it will only perform the action - * once at the end of the interval. - * @param {function(this: T)} listener Function to callback when the action is - * triggered. - * @param {number} interval Interval over which to throttle. The listener can - * only be called once per interval. - * @param {T=} opt_handler Object in whose scope to call the listener. - * @constructor - * @extends {goog.Disposable} - * @final - * @template T - */ -goog.async.Throttle = function(listener, interval, opt_handler) { - goog.Disposable.call(this); - - /** - * Function to callback - * @type {function(this: T)} - * @private - */ - this.listener_ = listener; - - /** - * Interval for the throttle time - * @type {number} - * @private - */ - this.interval_ = interval; - - /** - * "this" context for the listener - * @type {Object|undefined} - * @private - */ - this.handler_ = opt_handler; - - /** - * Cached callback function invoked after the throttle timeout completes - * @type {Function} - * @private - */ - this.callback_ = goog.bind(this.onTimer_, this); -}; -goog.inherits(goog.async.Throttle, goog.Disposable); - - - -/** - * A deprecated alias. - * @deprecated Use goog.async.Throttle instead. - * @constructor - * @final - */ -goog.Throttle = goog.async.Throttle; - - -/** - * Indicates that the action is pending and needs to be fired. - * @type {boolean} - * @private - */ -goog.async.Throttle.prototype.shouldFire_ = false; - - -/** - * Indicates the count of nested pauses currently in effect on the throttle. - * When this count is not zero, fired actions will be postponed until the - * throttle is resumed enough times to drop the pause count to zero. - * @type {number} - * @private - */ -goog.async.Throttle.prototype.pauseCount_ = 0; - - -/** - * Timer for scheduling the next callback - * @type {?number} - * @private - */ -goog.async.Throttle.prototype.timer_ = null; - - -/** - * Notifies the throttle that the action has happened. It will throttle the call - * so that the callback is not called too often according to the interval - * parameter passed to the constructor. - */ -goog.async.Throttle.prototype.fire = function() { - if (!this.timer_ && !this.pauseCount_) { - this.doAction_(); - } else { - this.shouldFire_ = true; - } -}; - - -/** - * Cancels any pending action callback. The throttle can be restarted by - * calling {@link #fire}. - */ -goog.async.Throttle.prototype.stop = function() { - if (this.timer_) { - goog.Timer.clear(this.timer_); - this.timer_ = null; - this.shouldFire_ = false; - } -}; - - -/** - * Pauses the throttle. All pending and future action callbacks will be - * delayed until the throttle is resumed. Pauses can be nested. - */ -goog.async.Throttle.prototype.pause = function() { - this.pauseCount_++; -}; - - -/** - * Resumes the throttle. If doing so drops the pausing count to zero, pending - * action callbacks will be executed as soon as possible, but still no sooner - * than an interval's delay after the previous call. Future action callbacks - * will be executed as normal. - */ -goog.async.Throttle.prototype.resume = function() { - this.pauseCount_--; - if (!this.pauseCount_ && this.shouldFire_ && !this.timer_) { - this.shouldFire_ = false; - this.doAction_(); - } -}; - - -/** @override */ -goog.async.Throttle.prototype.disposeInternal = function() { - goog.async.Throttle.superClass_.disposeInternal.call(this); - this.stop(); -}; - - -/** - * Handler for the timer to fire the throttle - * @private - */ -goog.async.Throttle.prototype.onTimer_ = function() { - this.timer_ = null; - - if (this.shouldFire_ && !this.pauseCount_) { - this.shouldFire_ = false; - this.doAction_(); - } -}; - - -/** - * Calls the callback - * @private - */ -goog.async.Throttle.prototype.doAction_ = function() { - this.timer_ = goog.Timer.callOnce(this.callback_, this.interval_); - this.listener_.call(this.handler_); -}; diff --git a/src/database/third_party/closure-library/closure/goog/async/throttle_test.html b/src/database/third_party/closure-library/closure/goog/async/throttle_test.html deleted file mode 100644 index 2b300b92f15..00000000000 --- a/src/database/third_party/closure-library/closure/goog/async/throttle_test.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - Closure Unit Tests - goog.async.Throttle - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/async/throttle_test.js b/src/database/third_party/closure-library/closure/goog/async/throttle_test.js deleted file mode 100644 index a508f23178c..00000000000 --- a/src/database/third_party/closure-library/closure/goog/async/throttle_test.js +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -goog.provide('goog.async.ThrottleTest'); -goog.setTestOnly('goog.async.ThrottleTest'); - -goog.require('goog.async.Throttle'); -goog.require('goog.testing.MockClock'); -goog.require('goog.testing.jsunit'); - -function testThrottle() { - var clock = new goog.testing.MockClock(true); - - var callBackCount = 0; - var callBackFunction = function() { - callBackCount++; - }; - - var throttle = new goog.async.Throttle(callBackFunction, 100); - assertEquals(0, callBackCount); - throttle.fire(); - assertEquals(1, callBackCount); - throttle.fire(); - assertEquals(1, callBackCount); - throttle.fire(); - throttle.fire(); - assertEquals(1, callBackCount); - clock.tick(101); - assertEquals(2, callBackCount); - clock.tick(101); - assertEquals(2, callBackCount); - - throttle.fire(); - assertEquals(3, callBackCount); - throttle.fire(); - assertEquals(3, callBackCount); - throttle.stop(); - clock.tick(101); - assertEquals(3, callBackCount); - throttle.fire(); - assertEquals(4, callBackCount); - clock.tick(101); - assertEquals(4, callBackCount); - - throttle.fire(); - throttle.fire(); - assertEquals(5, callBackCount); - throttle.pause(); - throttle.resume(); - assertEquals(5, callBackCount); - throttle.pause(); - clock.tick(101); - assertEquals(5, callBackCount); - throttle.resume(); - assertEquals(6, callBackCount); - clock.tick(101); - assertEquals(6, callBackCount); - throttle.pause(); - throttle.fire(); - assertEquals(6, callBackCount); - clock.tick(101); - assertEquals(6, callBackCount); - throttle.resume(); - assertEquals(7, callBackCount); - - throttle.pause(); - throttle.pause(); - clock.tick(101); - throttle.fire(); - throttle.resume(); - assertEquals(7, callBackCount); - throttle.resume(); - assertEquals(8, callBackCount); - - throttle.pause(); - throttle.pause(); - throttle.fire(); - throttle.resume(); - clock.tick(101); - assertEquals(8, callBackCount); - throttle.resume(); - assertEquals(9, callBackCount); - - clock.uninstall(); -} diff --git a/src/database/third_party/closure-library/closure/goog/base.js b/src/database/third_party/closure-library/closure/goog/base.js deleted file mode 100644 index 6b4d291dbb1..00000000000 --- a/src/database/third_party/closure-library/closure/goog/base.js +++ /dev/null @@ -1,2496 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Bootstrap for the Google JS Library (Closure). - * - * In uncompiled mode base.js will write out Closure's deps file, unless the - * global CLOSURE_NO_DEPS is set to true. This allows projects to - * include their own deps file(s) from different locations. - * - * @author arv@google.com (Erik Arvidsson) - * - * @provideGoog - */ - - -/** - * @define {boolean} Overridden to true by the compiler when --closure_pass - * or --mark_as_compiled is specified. - */ -var COMPILED = false; - - -/** - * Base namespace for the Closure library. Checks to see goog is already - * defined in the current scope before assigning to prevent clobbering if - * base.js is loaded more than once. - * - * @const - */ -var goog = goog || {}; - - -/** - * Reference to the global context. In most cases this will be 'window'. - */ -goog.global = this; - - -/** - * A hook for overriding the define values in uncompiled mode. - * - * In uncompiled mode, {@code CLOSURE_UNCOMPILED_DEFINES} may be defined before - * loading base.js. If a key is defined in {@code CLOSURE_UNCOMPILED_DEFINES}, - * {@code goog.define} will use the value instead of the default value. This - * allows flags to be overwritten without compilation (this is normally - * accomplished with the compiler's "define" flag). - * - * Example: - *
- *   var CLOSURE_UNCOMPILED_DEFINES = {'goog.DEBUG': false};
- * 
- * - * @type {Object|undefined} - */ -goog.global.CLOSURE_UNCOMPILED_DEFINES; - - -/** - * A hook for overriding the define values in uncompiled or compiled mode, - * like CLOSURE_UNCOMPILED_DEFINES but effective in compiled code. In - * uncompiled code CLOSURE_UNCOMPILED_DEFINES takes precedence. - * - * Also unlike CLOSURE_UNCOMPILED_DEFINES the values must be number, boolean or - * string literals or the compiler will emit an error. - * - * While any @define value may be set, only those set with goog.define will be - * effective for uncompiled code. - * - * Example: - *
- *   var CLOSURE_DEFINES = {'goog.DEBUG': false} ;
- * 
- * - * @type {Object|undefined} - */ -goog.global.CLOSURE_DEFINES; - - -/** - * Returns true if the specified value is not undefined. - * WARNING: Do not use this to test if an object has a property. Use the in - * operator instead. - * - * @param {?} val Variable to test. - * @return {boolean} Whether variable is defined. - */ -goog.isDef = function(val) { - // void 0 always evaluates to undefined and hence we do not need to depend on - // the definition of the global variable named 'undefined'. - return val !== void 0; -}; - - -/** - * Builds an object structure for the provided namespace path, ensuring that - * names that already exist are not overwritten. For example: - * "a.b.c" -> a = {};a.b={};a.b.c={}; - * Used by goog.provide and goog.exportSymbol. - * @param {string} name name of the object that this file defines. - * @param {*=} opt_object the object to expose at the end of the path. - * @param {Object=} opt_objectToExportTo The object to add the path to; default - * is |goog.global|. - * @private - */ -goog.exportPath_ = function(name, opt_object, opt_objectToExportTo) { - var parts = name.split('.'); - var cur = opt_objectToExportTo || goog.global; - - // Internet Explorer exhibits strange behavior when throwing errors from - // methods externed in this manner. See the testExportSymbolExceptions in - // base_test.html for an example. - if (!(parts[0] in cur) && cur.execScript) { - cur.execScript('var ' + parts[0]); - } - - // Certain browsers cannot parse code in the form for((a in b); c;); - // This pattern is produced by the JSCompiler when it collapses the - // statement above into the conditional loop below. To prevent this from - // happening, use a for-loop and reserve the init logic as below. - - // Parentheses added to eliminate strict JS warning in Firefox. - for (var part; parts.length && (part = parts.shift());) { - if (!parts.length && goog.isDef(opt_object)) { - // last part and we have an object; use it - cur[part] = opt_object; - } else if (cur[part]) { - cur = cur[part]; - } else { - cur = cur[part] = {}; - } - } -}; - - -/** - * Defines a named value. In uncompiled mode, the value is retrieved from - * CLOSURE_DEFINES or CLOSURE_UNCOMPILED_DEFINES if the object is defined and - * has the property specified, and otherwise used the defined defaultValue. - * When compiled the default can be overridden using the compiler - * options or the value set in the CLOSURE_DEFINES object. - * - * @param {string} name The distinguished name to provide. - * @param {string|number|boolean} defaultValue - */ -goog.define = function(name, defaultValue) { - var value = defaultValue; - if (!COMPILED) { - if (goog.global.CLOSURE_UNCOMPILED_DEFINES && - Object.prototype.hasOwnProperty.call( - goog.global.CLOSURE_UNCOMPILED_DEFINES, name)) { - value = goog.global.CLOSURE_UNCOMPILED_DEFINES[name]; - } else if (goog.global.CLOSURE_DEFINES && - Object.prototype.hasOwnProperty.call( - goog.global.CLOSURE_DEFINES, name)) { - value = goog.global.CLOSURE_DEFINES[name]; - } - } - goog.exportPath_(name, value); -}; - - -/** - * @define {boolean} DEBUG is provided as a convenience so that debugging code - * that should not be included in a production js_binary can be easily stripped - * by specifying --define goog.DEBUG=false to the JSCompiler. For example, most - * toString() methods should be declared inside an "if (goog.DEBUG)" conditional - * because they are generally used for debugging purposes and it is difficult - * for the JSCompiler to statically determine whether they are used. - */ -goog.define('goog.DEBUG', true); - - -/** - * @define {string} LOCALE defines the locale being used for compilation. It is - * used to select locale specific data to be compiled in js binary. BUILD rule - * can specify this value by "--define goog.LOCALE=" as JSCompiler - * option. - * - * Take into account that the locale code format is important. You should use - * the canonical Unicode format with hyphen as a delimiter. Language must be - * lowercase, Language Script - Capitalized, Region - UPPERCASE. - * There are few examples: pt-BR, en, en-US, sr-Latin-BO, zh-Hans-CN. - * - * See more info about locale codes here: - * http://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers - * - * For language codes you should use values defined by ISO 693-1. See it here - * http://www.w3.org/WAI/ER/IG/ert/iso639.htm. There is only one exception from - * this rule: the Hebrew language. For legacy reasons the old code (iw) should - * be used instead of the new code (he), see http://wiki/Main/IIISynonyms. - */ -goog.define('goog.LOCALE', 'en'); // default to en - - -/** - * @define {boolean} Whether this code is running on trusted sites. - * - * On untrusted sites, several native functions can be defined or overridden by - * external libraries like Prototype, Datejs, and JQuery and setting this flag - * to false forces closure to use its own implementations when possible. - * - * If your JavaScript can be loaded by a third party site and you are wary about - * relying on non-standard implementations, specify - * "--define goog.TRUSTED_SITE=false" to the JSCompiler. - */ -goog.define('goog.TRUSTED_SITE', true); - - -/** - * @define {boolean} Whether a project is expected to be running in strict mode. - * - * This define can be used to trigger alternate implementations compatible with - * running in EcmaScript Strict mode or warn about unavailable functionality. - * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode - * - */ -goog.define('goog.STRICT_MODE_COMPATIBLE', false); - - -/** - * @define {boolean} Whether code that calls {@link goog.setTestOnly} should - * be disallowed in the compilation unit. - */ -goog.define('goog.DISALLOW_TEST_ONLY_CODE', COMPILED && !goog.DEBUG); - - -/** - * Defines a namespace in Closure. - * - * A namespace may only be defined once in a codebase. It may be defined using - * goog.provide() or goog.module(). - * - * The presence of one or more goog.provide() calls in a file indicates - * that the file defines the given objects/namespaces. - * Provided symbols must not be null or undefined. - * - * In addition, goog.provide() creates the object stubs for a namespace - * (for example, goog.provide("goog.foo.bar") will create the object - * goog.foo.bar if it does not already exist). - * - * Build tools also scan for provide/require/module statements - * to discern dependencies, build dependency files (see deps.js), etc. - * - * @see goog.require - * @see goog.module - * @param {string} name Namespace provided by this file in the form - * "goog.package.part". - */ -goog.provide = function(name) { - if (!COMPILED) { - // Ensure that the same namespace isn't provided twice. - // A goog.module/goog.provide maps a goog.require to a specific file - if (goog.isProvided_(name)) { - throw Error('Namespace "' + name + '" already declared.'); - } - } - - goog.constructNamespace_(name); -}; - - -/** - * @param {string} name Namespace provided by this file in the form - * "goog.package.part". - * @param {Object=} opt_obj The object to embed in the namespace. - * @private - */ -goog.constructNamespace_ = function(name, opt_obj) { - if (!COMPILED) { - delete goog.implicitNamespaces_[name]; - - var namespace = name; - while ((namespace = namespace.substring(0, namespace.lastIndexOf('.')))) { - if (goog.getObjectByName(namespace)) { - break; - } - goog.implicitNamespaces_[namespace] = true; - } - } - - goog.exportPath_(name, opt_obj); -}; - - -/** - * Module identifier validation regexp. - * Note: This is a conservative check, it is very possible to be more lenient, - * the primary exclusion here is "/" and "\" and a leading ".", these - * restrictions are intended to leave the door open for using goog.require - * with relative file paths rather than module identifiers. - * @private - */ -goog.VALID_MODULE_RE_ = /^[a-zA-Z_$][a-zA-Z0-9._$]*$/; - - -/** - * Defines a module in Closure. - * - * Marks that this file must be loaded as a module and claims the namespace. - * - * A namespace may only be defined once in a codebase. It may be defined using - * goog.provide() or goog.module(). - * - * goog.module() has three requirements: - * - goog.module may not be used in the same file as goog.provide. - * - goog.module must be the first statement in the file. - * - only one goog.module is allowed per file. - * - * When a goog.module annotated file is loaded, it is enclosed in - * a strict function closure. This means that: - * - any variables declared in a goog.module file are private to the file - * (not global), though the compiler is expected to inline the module. - * - The code must obey all the rules of "strict" JavaScript. - * - the file will be marked as "use strict" - * - * NOTE: unlike goog.provide, goog.module does not declare any symbols by - * itself. If declared symbols are desired, use - * goog.module.declareLegacyNamespace(). - * - * - * See the public goog.module proposal: http://goo.gl/Va1hin - * - * @param {string} name Namespace provided by this file in the form - * "goog.package.part", is expected but not required. - */ -goog.module = function(name) { - if (!goog.isString(name) || - !name || - name.search(goog.VALID_MODULE_RE_) == -1) { - throw Error('Invalid module identifier'); - } - if (!goog.isInModuleLoader_()) { - throw Error('Module ' + name + ' has been loaded incorrectly.'); - } - if (goog.moduleLoaderState_.moduleName) { - throw Error('goog.module may only be called once per module.'); - } - - // Store the module name for the loader. - goog.moduleLoaderState_.moduleName = name; - if (!COMPILED) { - // Ensure that the same namespace isn't provided twice. - // A goog.module/goog.provide maps a goog.require to a specific file - if (goog.isProvided_(name)) { - throw Error('Namespace "' + name + '" already declared.'); - } - delete goog.implicitNamespaces_[name]; - } -}; - - -/** - * @param {string} name The module identifier. - * @return {?} The module exports for an already loaded module or null. - * - * Note: This is not an alternative to goog.require, it does not - * indicate a hard dependency, instead it is used to indicate - * an optional dependency or to access the exports of a module - * that has already been loaded. - * @suppress {missingProvide} - */ -goog.module.get = function(name) { - return goog.module.getInternal_(name); -}; - - -/** - * @param {string} name The module identifier. - * @return {?} The module exports for an already loaded module or null. - * @private - */ -goog.module.getInternal_ = function(name) { - if (!COMPILED) { - if (goog.isProvided_(name)) { - // goog.require only return a value with-in goog.module files. - return name in goog.loadedModules_ ? - goog.loadedModules_[name] : - goog.getObjectByName(name); - } else { - return null; - } - } -}; - - -/** - * @private {?{ - * moduleName: (string|undefined), - * declareTestMethods: boolean - * }} - */ -goog.moduleLoaderState_ = null; - - -/** - * @private - * @return {boolean} Whether a goog.module is currently being initialized. - */ -goog.isInModuleLoader_ = function() { - return goog.moduleLoaderState_ != null; -}; - - -/** - * Indicate that a module's exports that are known test methods should - * be copied to the global object. This makes the test methods visible to - * test runners that inspect the global object. - * - * TODO(johnlenz): Make the test framework aware of goog.module so - * that this isn't necessary. Alternately combine this with goog.setTestOnly - * to minimize boiler plate. - * @suppress {missingProvide} - */ -goog.module.declareTestMethods = function() { - if (!goog.isInModuleLoader_()) { - throw new Error('goog.module.declareTestMethods must be called from ' + - 'within a goog.module'); - } - goog.moduleLoaderState_.declareTestMethods = true; -}; - - -/** - * Provide the module's exports as a globally accessible object under the - * module's declared name. This is intended to ease migration to goog.module - * for files that have existing usages. - * @suppress {missingProvide} - */ -goog.module.declareLegacyNamespace = function() { - if (!COMPILED && !goog.isInModuleLoader_()) { - throw new Error('goog.module.declareLegacyNamespace must be called from ' + - 'within a goog.module'); - } - if (!COMPILED && !goog.moduleLoaderState_.moduleName) { - throw Error('goog.module must be called prior to ' + - 'goog.module.declareLegacyNamespace.'); - } - goog.moduleLoaderState_.declareLegacyNamespace = true; -}; - - -/** - * Marks that the current file should only be used for testing, and never for - * live code in production. - * - * In the case of unit tests, the message may optionally be an exact namespace - * for the test (e.g. 'goog.stringTest'). The linter will then ignore the extra - * provide (if not explicitly defined in the code). - * - * @param {string=} opt_message Optional message to add to the error that's - * raised when used in production code. - */ -goog.setTestOnly = function(opt_message) { - if (goog.DISALLOW_TEST_ONLY_CODE) { - opt_message = opt_message || ''; - throw Error('Importing test-only code into non-debug environment' + - (opt_message ? ': ' + opt_message : '.')); - } -}; - - -/** - * Forward declares a symbol. This is an indication to the compiler that the - * symbol may be used in the source yet is not required and may not be provided - * in compilation. - * - * The most common usage of forward declaration is code that takes a type as a - * function parameter but does not need to require it. By forward declaring - * instead of requiring, no hard dependency is made, and (if not required - * elsewhere) the namespace may never be required and thus, not be pulled - * into the JavaScript binary. If it is required elsewhere, it will be type - * checked as normal. - * - * - * @param {string} name The namespace to forward declare in the form of - * "goog.package.part". - */ -goog.forwardDeclare = function(name) {}; - - -if (!COMPILED) { - - /** - * Check if the given name has been goog.provided. This will return false for - * names that are available only as implicit namespaces. - * @param {string} name name of the object to look for. - * @return {boolean} Whether the name has been provided. - * @private - */ - goog.isProvided_ = function(name) { - return (name in goog.loadedModules_) || - (!goog.implicitNamespaces_[name] && - goog.isDefAndNotNull(goog.getObjectByName(name))); - }; - - /** - * Namespaces implicitly defined by goog.provide. For example, - * goog.provide('goog.events.Event') implicitly declares that 'goog' and - * 'goog.events' must be namespaces. - * - * @type {!Object} - * @private - */ - goog.implicitNamespaces_ = {'goog.module': true}; - - // NOTE: We add goog.module as an implicit namespace as goog.module is defined - // here and because the existing module package has not been moved yet out of - // the goog.module namespace. This satisifies both the debug loader and - // ahead-of-time dependency management. -} - - -/** - * Returns an object based on its fully qualified external name. The object - * is not found if null or undefined. If you are using a compilation pass that - * renames property names beware that using this function will not find renamed - * properties. - * - * @param {string} name The fully qualified name. - * @param {Object=} opt_obj The object within which to look; default is - * |goog.global|. - * @return {?} The value (object or primitive) or, if not found, null. - */ -goog.getObjectByName = function(name, opt_obj) { - var parts = name.split('.'); - var cur = opt_obj || goog.global; - for (var part; part = parts.shift(); ) { - if (goog.isDefAndNotNull(cur[part])) { - cur = cur[part]; - } else { - return null; - } - } - return cur; -}; - - -/** - * Globalizes a whole namespace, such as goog or goog.lang. - * - * @param {!Object} obj The namespace to globalize. - * @param {Object=} opt_global The object to add the properties to. - * @deprecated Properties may be explicitly exported to the global scope, but - * this should no longer be done in bulk. - */ -goog.globalize = function(obj, opt_global) { - var global = opt_global || goog.global; - for (var x in obj) { - global[x] = obj[x]; - } -}; - - -/** - * Adds a dependency from a file to the files it requires. - * @param {string} relPath The path to the js file. - * @param {!Array} provides An array of strings with - * the names of the objects this file provides. - * @param {!Array} requires An array of strings with - * the names of the objects this file requires. - * @param {boolean=} opt_isModule Whether this dependency must be loaded as - * a module as declared by goog.module. - */ -goog.addDependency = function(relPath, provides, requires, opt_isModule) { - if (goog.DEPENDENCIES_ENABLED) { - var provide, require; - var path = relPath.replace(/\\/g, '/'); - var deps = goog.dependencies_; - for (var i = 0; provide = provides[i]; i++) { - deps.nameToPath[provide] = path; - deps.pathIsModule[path] = !!opt_isModule; - } - for (var j = 0; require = requires[j]; j++) { - if (!(path in deps.requires)) { - deps.requires[path] = {}; - } - deps.requires[path][require] = true; - } - } -}; - - - - -// NOTE(nnaze): The debug DOM loader was included in base.js as an original way -// to do "debug-mode" development. The dependency system can sometimes be -// confusing, as can the debug DOM loader's asynchronous nature. -// -// With the DOM loader, a call to goog.require() is not blocking -- the script -// will not load until some point after the current script. If a namespace is -// needed at runtime, it needs to be defined in a previous script, or loaded via -// require() with its registered dependencies. -// User-defined namespaces may need their own deps file. See http://go/js_deps, -// http://go/genjsdeps, or, externally, DepsWriter. -// https://developers.google.com/closure/library/docs/depswriter -// -// Because of legacy clients, the DOM loader can't be easily removed from -// base.js. Work is being done to make it disableable or replaceable for -// different environments (DOM-less JavaScript interpreters like Rhino or V8, -// for example). See bootstrap/ for more information. - - -/** - * @define {boolean} Whether to enable the debug loader. - * - * If enabled, a call to goog.require() will attempt to load the namespace by - * appending a script tag to the DOM (if the namespace has been registered). - * - * If disabled, goog.require() will simply assert that the namespace has been - * provided (and depend on the fact that some outside tool correctly ordered - * the script). - */ -goog.define('goog.ENABLE_DEBUG_LOADER', true); - - -/** - * @param {string} msg - * @private - */ -goog.logToConsole_ = function(msg) { - if (goog.global.console) { - goog.global.console['error'](msg); - } -}; - - -/** - * Implements a system for the dynamic resolution of dependencies that works in - * parallel with the BUILD system. Note that all calls to goog.require will be - * stripped by the JSCompiler when the --closure_pass option is used. - * @see goog.provide - * @param {string} name Namespace to include (as was given in goog.provide()) in - * the form "goog.package.part". - * @return {?} If called within a goog.module file, the associated namespace or - * module otherwise null. - */ -goog.require = function(name) { - - // If the object already exists we do not need do do anything. - if (!COMPILED) { - if (goog.ENABLE_DEBUG_LOADER && goog.IS_OLD_IE_) { - goog.maybeProcessDeferredDep_(name); - } - - if (goog.isProvided_(name)) { - if (goog.isInModuleLoader_()) { - return goog.module.getInternal_(name); - } else { - return null; - } - } - - if (goog.ENABLE_DEBUG_LOADER) { - var path = goog.getPathFromDeps_(name); - if (path) { - goog.included_[path] = true; - goog.writeScripts_(); - return null; - } - } - - var errorMessage = 'goog.require could not find: ' + name; - goog.logToConsole_(errorMessage); - - throw Error(errorMessage); - } -}; - - -/** - * Path for included scripts. - * @type {string} - */ -goog.basePath = ''; - - -/** - * A hook for overriding the base path. - * @type {string|undefined} - */ -goog.global.CLOSURE_BASE_PATH; - - -/** - * Whether to write out Closure's deps file. By default, the deps are written. - * @type {boolean|undefined} - */ -goog.global.CLOSURE_NO_DEPS; - - -/** - * A function to import a single script. This is meant to be overridden when - * Closure is being run in non-HTML contexts, such as web workers. It's defined - * in the global scope so that it can be set before base.js is loaded, which - * allows deps.js to be imported properly. - * - * The function is passed the script source, which is a relative URI. It should - * return true if the script was imported, false otherwise. - * @type {(function(string): boolean)|undefined} - */ -goog.global.CLOSURE_IMPORT_SCRIPT; - - -/** - * Null function used for default values of callbacks, etc. - * @return {void} Nothing. - */ -goog.nullFunction = function() {}; - - -/** - * The identity function. Returns its first argument. - * - * @param {*=} opt_returnValue The single value that will be returned. - * @param {...*} var_args Optional trailing arguments. These are ignored. - * @return {?} The first argument. We can't know the type -- just pass it along - * without type. - * @deprecated Use goog.functions.identity instead. - */ -goog.identityFunction = function(opt_returnValue, var_args) { - return opt_returnValue; -}; - - -/** - * When defining a class Foo with an abstract method bar(), you can do: - * Foo.prototype.bar = goog.abstractMethod - * - * Now if a subclass of Foo fails to override bar(), an error will be thrown - * when bar() is invoked. - * - * Note: This does not take the name of the function to override as an argument - * because that would make it more difficult to obfuscate our JavaScript code. - * - * @type {!Function} - * @throws {Error} when invoked to indicate the method should be overridden. - */ -goog.abstractMethod = function() { - throw Error('unimplemented abstract method'); -}; - - -/** - * Adds a {@code getInstance} static method that always returns the same - * instance object. - * @param {!Function} ctor The constructor for the class to add the static - * method to. - */ -goog.addSingletonGetter = function(ctor) { - ctor.getInstance = function() { - if (ctor.instance_) { - return ctor.instance_; - } - if (goog.DEBUG) { - // NOTE: JSCompiler can't optimize away Array#push. - goog.instantiatedSingletons_[goog.instantiatedSingletons_.length] = ctor; - } - return ctor.instance_ = new ctor; - }; -}; - - -/** - * All singleton classes that have been instantiated, for testing. Don't read - * it directly, use the {@code goog.testing.singleton} module. The compiler - * removes this variable if unused. - * @type {!Array} - * @private - */ -goog.instantiatedSingletons_ = []; - - -/** - * @define {boolean} Whether to load goog.modules using {@code eval} when using - * the debug loader. This provides a better debugging experience as the - * source is unmodified and can be edited using Chrome Workspaces or similar. - * However in some environments the use of {@code eval} is banned - * so we provide an alternative. - */ -goog.define('goog.LOAD_MODULE_USING_EVAL', true); - - -/** - * @define {boolean} Whether the exports of goog.modules should be sealed when - * possible. - */ -goog.define('goog.SEAL_MODULE_EXPORTS', goog.DEBUG); - - -/** - * The registry of initialized modules: - * the module identifier to module exports map. - * @private @const {!Object} - */ -goog.loadedModules_ = {}; - - -/** - * True if goog.dependencies_ is available. - * @const {boolean} - */ -goog.DEPENDENCIES_ENABLED = !COMPILED && goog.ENABLE_DEBUG_LOADER; - - -if (goog.DEPENDENCIES_ENABLED) { - /** - * Object used to keep track of urls that have already been added. This record - * allows the prevention of circular dependencies. - * @private {!Object} - */ - goog.included_ = {}; - - - /** - * This object is used to keep track of dependencies and other data that is - * used for loading scripts. - * @private - * @type {{ - * pathIsModule: !Object, - * nameToPath: !Object, - * requires: !Object>, - * visited: !Object, - * written: !Object, - * deferred: !Object - * }} - */ - goog.dependencies_ = { - pathIsModule: {}, // 1 to 1 - - nameToPath: {}, // 1 to 1 - - requires: {}, // 1 to many - - // Used when resolving dependencies to prevent us from visiting file twice. - visited: {}, - - written: {}, // Used to keep track of script files we have written. - - deferred: {} // Used to track deferred module evaluations in old IEs - }; - - - /** - * Tries to detect whether is in the context of an HTML document. - * @return {boolean} True if it looks like HTML document. - * @private - */ - goog.inHtmlDocument_ = function() { - var doc = goog.global.document; - return typeof doc != 'undefined' && - 'write' in doc; // XULDocument misses write. - }; - - - /** - * Tries to detect the base path of base.js script that bootstraps Closure. - * @private - */ - goog.findBasePath_ = function() { - if (goog.global.CLOSURE_BASE_PATH) { - goog.basePath = goog.global.CLOSURE_BASE_PATH; - return; - } else if (!goog.inHtmlDocument_()) { - return; - } - var doc = goog.global.document; - var scripts = doc.getElementsByTagName('script'); - // Search backwards since the current script is in almost all cases the one - // that has base.js. - for (var i = scripts.length - 1; i >= 0; --i) { - var script = /** @type {!HTMLScriptElement} */ (scripts[i]); - var src = script.src; - var qmark = src.lastIndexOf('?'); - var l = qmark == -1 ? src.length : qmark; - if (src.substr(l - 7, 7) == 'base.js') { - goog.basePath = src.substr(0, l - 7); - return; - } - } - }; - - - /** - * Imports a script if, and only if, that script hasn't already been imported. - * (Must be called at execution time) - * @param {string} src Script source. - * @param {string=} opt_sourceText The optionally source text to evaluate - * @private - */ - goog.importScript_ = function(src, opt_sourceText) { - var importScript = goog.global.CLOSURE_IMPORT_SCRIPT || - goog.writeScriptTag_; - if (importScript(src, opt_sourceText)) { - goog.dependencies_.written[src] = true; - } - }; - - - /** @const @private {boolean} */ - goog.IS_OLD_IE_ = !goog.global.atob && goog.global.document && - goog.global.document.all; - - - /** - * Given a URL initiate retrieval and execution of the module. - * @param {string} src Script source URL. - * @private - */ - goog.importModule_ = function(src) { - // In an attempt to keep browsers from timing out loading scripts using - // synchronous XHRs, put each load in its own script block. - var bootstrap = 'goog.retrieveAndExecModule_("' + src + '");'; - - if (goog.importScript_('', bootstrap)) { - goog.dependencies_.written[src] = true; - } - }; - - - /** @private {!Array} */ - goog.queuedModules_ = []; - - - /** - * Return an appropriate module text. Suitable to insert into - * a script tag (that is unescaped). - * @param {string} srcUrl - * @param {string} scriptText - * @return {string} - * @private - */ - goog.wrapModule_ = function(srcUrl, scriptText) { - if (!goog.LOAD_MODULE_USING_EVAL || !goog.isDef(goog.global.JSON)) { - return '' + - 'goog.loadModule(function(exports) {' + - '"use strict";' + - scriptText + - '\n' + // terminate any trailing single line comment. - ';return exports' + - '});' + - '\n//# sourceURL=' + srcUrl + '\n'; - } else { - return '' + - 'goog.loadModule(' + - goog.global.JSON.stringify( - scriptText + '\n//# sourceURL=' + srcUrl + '\n') + - ');'; - } - }; - - // On IE9 and earlier, it is necessary to handle - // deferred module loads. In later browsers, the - // code to be evaluated is simply inserted as a script - // block in the correct order. To eval deferred - // code at the right time, we piggy back on goog.require to call - // goog.maybeProcessDeferredDep_. - // - // The goog.requires are used both to bootstrap - // the loading process (when no deps are available) and - // declare that they should be available. - // - // Here we eval the sources, if all the deps are available - // either already eval'd or goog.require'd. This will - // be the case when all the dependencies have already - // been loaded, and the dependent module is loaded. - // - // But this alone isn't sufficient because it is also - // necessary to handle the case where there is no root - // that is not deferred. For that there we register for an event - // and trigger goog.loadQueuedModules_ handle any remaining deferred - // evaluations. - - /** - * Handle any remaining deferred goog.module evals. - * @private - */ - goog.loadQueuedModules_ = function() { - var count = goog.queuedModules_.length; - if (count > 0) { - var queue = goog.queuedModules_; - goog.queuedModules_ = []; - for (var i = 0; i < count; i++) { - var path = queue[i]; - goog.maybeProcessDeferredPath_(path); - } - } - }; - - - /** - * Eval the named module if its dependencies are - * available. - * @param {string} name The module to load. - * @private - */ - goog.maybeProcessDeferredDep_ = function(name) { - if (goog.isDeferredModule_(name) && - goog.allDepsAreAvailable_(name)) { - var path = goog.getPathFromDeps_(name); - goog.maybeProcessDeferredPath_(goog.basePath + path); - } - }; - - /** - * @param {string} name The module to check. - * @return {boolean} Whether the name represents a - * module whose evaluation has been deferred. - * @private - */ - goog.isDeferredModule_ = function(name) { - var path = goog.getPathFromDeps_(name); - if (path && goog.dependencies_.pathIsModule[path]) { - var abspath = goog.basePath + path; - return (abspath) in goog.dependencies_.deferred; - } - return false; - }; - - /** - * @param {string} name The module to check. - * @return {boolean} Whether the name represents a - * module whose declared dependencies have all been loaded - * (eval'd or a deferred module load) - * @private - */ - goog.allDepsAreAvailable_ = function(name) { - var path = goog.getPathFromDeps_(name); - if (path && (path in goog.dependencies_.requires)) { - for (var requireName in goog.dependencies_.requires[path]) { - if (!goog.isProvided_(requireName) && - !goog.isDeferredModule_(requireName)) { - return false; - } - } - } - return true; - }; - - - /** - * @param {string} abspath - * @private - */ - goog.maybeProcessDeferredPath_ = function(abspath) { - if (abspath in goog.dependencies_.deferred) { - var src = goog.dependencies_.deferred[abspath]; - delete goog.dependencies_.deferred[abspath]; - goog.globalEval(src); - } - }; - - - /** - * @param {function(?):?|string} moduleDef The module definition. - */ - goog.loadModule = function(moduleDef) { - // NOTE: we allow function definitions to be either in the from - // of a string to eval (which keeps the original source intact) or - // in a eval forbidden environment (CSP) we allow a function definition - // which in its body must call {@code goog.module}, and return the exports - // of the module. - var previousState = goog.moduleLoaderState_; - try { - goog.moduleLoaderState_ = { - moduleName: undefined, declareTestMethods: false}; - var exports; - if (goog.isFunction(moduleDef)) { - exports = moduleDef.call(goog.global, {}); - } else if (goog.isString(moduleDef)) { - exports = goog.loadModuleFromSource_.call(goog.global, moduleDef); - } else { - throw Error('Invalid module definition'); - } - - var moduleName = goog.moduleLoaderState_.moduleName; - if (!goog.isString(moduleName) || !moduleName) { - throw Error('Invalid module name \"' + moduleName + '\"'); - } - - // Don't seal legacy namespaces as they may be uses as a parent of - // another namespace - if (goog.moduleLoaderState_.declareLegacyNamespace) { - goog.constructNamespace_(moduleName, exports); - } else if (goog.SEAL_MODULE_EXPORTS && Object.seal) { - Object.seal(exports); - } - - goog.loadedModules_[moduleName] = exports; - if (goog.moduleLoaderState_.declareTestMethods) { - for (var entry in exports) { - if (entry.indexOf('test', 0) === 0 || - entry == 'tearDown' || - entry == 'setUp' || - entry == 'setUpPage' || - entry == 'tearDownPage') { - goog.global[entry] = exports[entry]; - } - } - } - } finally { - goog.moduleLoaderState_ = previousState; - } - }; - - - /** - * @param {string} source - * @return {!Object} - * @private - */ - goog.loadModuleFromSource_ = function(source) { - // NOTE: we avoid declaring parameters or local variables here to avoid - // masking globals or leaking values into the module definition. - 'use strict'; - var exports = {}; - eval(arguments[0]); - return exports; - }; - - - /** - * The default implementation of the import function. Writes a script tag to - * import the script. - * - * @param {string} src The script url. - * @param {string=} opt_sourceText The optionally source text to evaluate - * @return {boolean} True if the script was imported, false otherwise. - * @private - */ - goog.writeScriptTag_ = function(src, opt_sourceText) { - if (goog.inHtmlDocument_()) { - var doc = goog.global.document; - - // If the user tries to require a new symbol after document load, - // something has gone terribly wrong. Doing a document.write would - // wipe out the page. - if (doc.readyState == 'complete') { - // Certain test frameworks load base.js multiple times, which tries - // to write deps.js each time. If that happens, just fail silently. - // These frameworks wipe the page between each load of base.js, so this - // is OK. - var isDeps = /\bdeps.js$/.test(src); - if (isDeps) { - return false; - } else { - throw Error('Cannot write "' + src + '" after document load'); - } - } - - var isOldIE = goog.IS_OLD_IE_; - - if (opt_sourceText === undefined) { - if (!isOldIE) { - doc.write( - ' - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/base_module_test.js b/src/database/third_party/closure-library/closure/goog/base_module_test.js deleted file mode 100644 index 3678b48ab44..00000000000 --- a/src/database/third_party/closure-library/closure/goog/base_module_test.js +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - - -/** - * @fileoverview Unit tests for Closure's base.js's goog.module support. - */ - -goog.module('goog.baseModuleTest'); -goog.module.declareTestMethods(); -goog.setTestOnly('goog.baseModuleTest'); - - -// Used to test dynamic loading works, see testRequire* -var Timer = goog.require('goog.Timer'); -var Replacer = goog.require('goog.testing.PropertyReplacer'); -var jsunit = goog.require('goog.testing.jsunit'); - -var testModule = goog.require('goog.test_module'); - -var stubs = new Replacer(); - -function assertProvideFails(namespace) { - assertThrows('goog.provide(' + namespace + ') should have failed', - goog.partial(goog.provide, namespace)); -} - -function assertModuleFails(namespace) { - assertThrows('goog.module(' + namespace + ') should have failed', - goog.partial(goog.module, namespace)); -} - -exports = { - teardown: function() { - stubs.reset(); - }, - - testModuleDecl: function() { - // assert that goog.module doesn't modify the global namespace - assertUndefined('module failed to protect global namespace: ' + - 'goog.baseModuleTest', goog.baseModuleTest); - }, - - testModuleScoping: function() { - // assert test functions are exported to the global namespace - assertNotUndefined('module failed: testModule', testModule); - assertTrue('module failed: testModule', - goog.isFunction(goog.global.testModuleScoping)); - }, - - testProvideStrictness1: function() { - assertModuleFails('goog.xy'); // not in goog.loadModule - - assertProvideFails('goog.baseModuleTest'); // this file. - }, - - testProvideStrictness2: function() { - // goog.module "provides" a namespace - assertTrue(goog.isProvided_('goog.baseModuleTest')); - }, - - testExportSymbol: function() { - // Assert that export symbol works from within a goog.module. - var date = new Date(); - - assertTrue(typeof nodots == 'undefined'); - goog.exportSymbol('nodots', date); - assertEquals(date, nodots); // globals are accessible from within a module. - nodots = undefined; - }, - - //=== tests for Require logic === - - testLegacyRequire: function() { - // goog.Timer is a legacy module loaded above - assertNotUndefined('goog.Timer should be available', goog.Timer); - - // Verify that a legacy module can be aliases with goog.require - assertTrue('Timer should be the goog.Timer namespace object', - goog.Timer === Timer); - - // and its dependencies - assertNotUndefined( - 'goog.events.EventTarget should be available', - /** @suppress {missingRequire} */ goog.events.EventTarget); - }, - - testRequireModule: function() { - assertEquals('module failed to export legacy namespace: ' + - 'goog.test_module', testModule, goog.test_module); - assertUndefined('module failed to protect global namespace: ' + - 'goog.test_module_dep', goog.test_module_dep); - - // The test module is available under its alias - assertNotUndefined('testModule is loaded', testModule); - assertTrue('module failed: testModule', goog.isFunction(testModule)); - } -}; - -exports.testThisInModule = (function() { - assertEquals(this, goog.global); -}).bind(this); diff --git a/src/database/third_party/closure-library/closure/goog/base_test.html b/src/database/third_party/closure-library/closure/goog/base_test.html deleted file mode 100644 index f6814e457f9..00000000000 --- a/src/database/third_party/closure-library/closure/goog/base_test.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - - -Closure Unit Tests - goog.* - - - - -
- One - Two - Three -
- - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/base_test.js b/src/database/third_party/closure-library/closure/goog/base_test.js deleted file mode 100644 index 31c2ebace82..00000000000 --- a/src/database/third_party/closure-library/closure/goog/base_test.js +++ /dev/null @@ -1,1495 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - - -/** - * @fileoverview Unit tests for Closure's base.js. - * - * @nocompile - */ - -goog.provide('goog.baseTest'); - -goog.setTestOnly('goog.baseTest'); - -// Used to test dynamic loading works, see testRequire* -goog.require('goog.Timer'); -goog.require('goog.functions'); -goog.require('goog.testing.PropertyReplacer'); -goog.require('goog.testing.jsunit'); -goog.require('goog.testing.recordFunction'); -goog.require('goog.userAgent'); - -goog.require('goog.test_module'); -var earlyTestModuleGet = goog.module.get('goog.test_module'); - -function getFramedVars(name) { - var w = window.frames[name]; - var doc = w.document; - doc.open(); - doc.write(' - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/color/alpha_test.js b/src/database/third_party/closure-library/closure/goog/color/alpha_test.js deleted file mode 100644 index f9ed1a8011b..00000000000 --- a/src/database/third_party/closure-library/closure/goog/color/alpha_test.js +++ /dev/null @@ -1,321 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -goog.provide('goog.color.alphaTest'); -goog.setTestOnly('goog.color.alphaTest'); - -goog.require('goog.array'); -goog.require('goog.color'); -goog.require('goog.color.alpha'); -goog.require('goog.testing.jsunit'); - -function testIsValidAlphaHexColor() { - var goodAlphaHexColors = ['#ffffffff', '#ff781259', '#01234567', '#Ff003DaB', - '#3CAF', '#abcdefab', '#3CAB']; - var badAlphaHexColors = ['#xxxxxxxx', '88990077', 'not_color', '#123456789', - 'fffffgfg']; - for (var i = 0; i < goodAlphaHexColors.length; i++) { - assertTrue(goodAlphaHexColors[i], - goog.color.alpha.isValidAlphaHexColor_(goodAlphaHexColors[i])); - } - for (var i = 0; i < badAlphaHexColors.length; i++) { - assertFalse(badAlphaHexColors[i], - goog.color.alpha.isValidAlphaHexColor_(badAlphaHexColors[i])); - } -} - -function testIsValidRgbaColor() { - var goodRgbaColors = ['rgba(255, 0, 0, 1)', 'rgba(255,127,0,1)', - 'rgba(0,0,255,0.5)', '(255, 26, 75, 0.2)', - 'RGBA(0, 55, 0, 0.6)', 'rgba(0, 200, 0, 0.123456789)']; - var badRgbaColors = ['(255, 0, 0)', '(2555,0,0, 0)', '(1,2,3,4,5)', - 'rgba(1,20,)', 'RGBA(20,20,20,)', 'RGBA', - 'rgba(255, 0, 0, 1.1)']; - for (var i = 0; i < goodRgbaColors.length; i++) { - assertEquals(goodRgbaColors[i], 4, - goog.color.alpha.isValidRgbaColor_(goodRgbaColors[i]).length); - } - for (var i = 0; i < badRgbaColors.length; i++) { - assertEquals(badRgbaColors[i], 0, - goog.color.alpha.isValidRgbaColor_(badRgbaColors[i]).length); - } -} - -function testIsValidHslaColor() { - var goodHslaColors = ['hsla(120, 0%, 0%, 1)', 'hsla(360,20%,0%,1)', - 'hsla(0,0%,50%,0.5)', 'HSLA(0, 55%, 0%, 0.6)', - 'hsla(0, 85%, 0%, 0.123456789)']; - var badHslaColors = ['(255, 0, 0, 0)', 'hsla(2555,0,0, 0)', 'hsla(1,2,3,4,5)', - 'hsla(1,20,)', 'HSLA(20,20,20,)', - 'hsla(255, 0, 0, 1.1)', 'HSLA']; - for (var i = 0; i < goodHslaColors.length; i++) { - assertEquals(goodHslaColors[i], 4, - goog.color.alpha.isValidHslaColor_(goodHslaColors[i]).length); - } - for (var i = 0; i < badHslaColors.length; i++) { - assertEquals(badHslaColors[i], 0, - goog.color.alpha.isValidHslaColor_(badHslaColors[i]).length); - } -} - -function testParse() { - var colors = ['rgba(15, 250, 77, 0.5)', '(127, 127, 127, 0.8)', '#ffeeddaa', - '12345678', 'hsla(160, 50%, 90%, 0.2)']; - var parsed = goog.array.map(colors, goog.color.alpha.parse); - assertEquals('rgba', parsed[0].type); - assertEquals(goog.color.alpha.rgbaToHex(15, 250, 77, 0.5), parsed[0].hex); - assertEquals('rgba', parsed[1].type); - assertEquals(goog.color.alpha.rgbaToHex(127, 127, 127, 0.8), parsed[1].hex); - assertEquals('hex', parsed[2].type); - assertEquals('#ffeeddaa', parsed[2].hex); - assertEquals('hex', parsed[3].type); - assertEquals('#12345678', parsed[3].hex); - assertEquals('hsla', parsed[4].type); - assertEquals('#d9f2ea33', parsed[4].hex); - - var badColors = ['rgb(01, 1, 23)', '(256, 256, 256)', '#ffeeddaa']; - for (var i = 0; i < badColors.length; i++) { - var e = assertThrows(badColors[i] + ' is not a valid color string', - goog.partial(goog.color.parse, badColors[i])); - assertContains('Error processing ' + badColors[i], - 'is not a valid color string', e.message); - } -} - -function testHexToRgba() { - var testColors = [['#B0FF2D66', [176, 255, 45, 0.4]], - ['#b26e5fcc', [178, 110, 95, 0.8]], - ['#66f3', [102, 102, 255, 0.2]]]; - - for (var i = 0; i < testColors.length; i++) { - var r = goog.color.alpha.hexToRgba(testColors[i][0]); - var t = testColors[i][1]; - - assertEquals('Red channel should match.', t[0], r[0]); - assertEquals('Green channel should match.', t[1], r[1]); - assertEquals('Blue channel should match.', t[2], r[2]); - assertEquals('Alpha channel should match.', t[3], r[3]); - } - - var badColors = ['', '#g00', 'some words']; - for (var i = 0; i < badColors.length; i++) { - var e = assertThrows( - goog.partial(goog.color.alpha.hexToRgba, badColors[i])); - assertEquals("'" + badColors[i] + "' is not a valid alpha hex color", - e.message); - } -} - -function testHexToRgbaStyle() { - assertEquals('rgba(255,0,0,1)', - goog.color.alpha.hexToRgbaStyle('#ff0000ff')); - assertEquals('rgba(206,206,206,0.8)', - goog.color.alpha.hexToRgbaStyle('#cecececc')); - assertEquals('rgba(51,204,170,0.2)', - goog.color.alpha.hexToRgbaStyle('#3CA3')); - assertEquals('rgba(1,2,3,0.016)', - goog.color.alpha.hexToRgbaStyle('#01020304')); - assertEquals('rgba(255,255,0,0.333)', - goog.color.alpha.hexToRgbaStyle('#FFFF0055')); - - var badHexColors = ['#12345', null, undefined, '#.1234567890']; - for (var i = 0; i < badHexColors.length; ++i) { - var e = assertThrows(badHexColors[i] + ' is an invalid hex color', - goog.partial(goog.color.alpha.hexToRgbaStyle, badHexColors[i])); - assertEquals("'" + badHexColors[i] + "' is not a valid alpha hex color", - e.message); - } -} - -function testRgbaToHex() { - assertEquals('#af13ffff', goog.color.alpha.rgbaToHex(175, 19, 255, 1)); - assertEquals('#357cf099', goog.color.alpha.rgbaToHex(53, 124, 240, 0.6)); - var badRgba = [[-1, -1, -1, -1], [0, 0, 0, 2], ['a', 'b', 'c', 'd'], - [undefined, 5, 5, 5]]; - for (var i = 0; i < badRgba.length; ++i) { - var e = assertThrows(badRgba[i] + ' is not a valid rgba color', - goog.partial(goog.color.alpha.rgbaArrayToHex, badRgba[i])); - assertContains('is not a valid RGBA color', e.message); - } -} - -function testRgbaToRgbaStyle() { - var testColors = [[[175, 19, 255, 1], 'rgba(175,19,255,1)'], - [[53, 124, 240, .6], 'rgba(53,124,240,0.6)'], - [[10, 20, 30, .1234567], 'rgba(10,20,30,0.123)'], - [[20, 30, 40, 1 / 3], 'rgba(20,30,40,0.333)']]; - - for (var i = 0; i < testColors.length; ++i) { - var r = goog.color.alpha.rgbaToRgbaStyle(testColors[i][0][0], - testColors[i][0][1], - testColors[i][0][2], - testColors[i][0][3]); - assertEquals(testColors[i][1], r); - } - - var badColors = [[0, 0, 0, 2]]; - for (var i = 0; i < badColors.length; ++i) { - var e = assertThrows(goog.partial(goog.color.alpha.rgbaToRgbaStyle, - badColors[i][0], badColors[i][1], badColors[i][2], badColors[i][3])); - - assertContains('is not a valid RGBA color', e.message); - } - - // Loop through all bad color values and ensure they fail in each channel. - var badValues = [-1, 300, 'a', undefined, null, NaN]; - var color = [0, 0, 0, 0]; - for (var i = 0; i < badValues.length; ++i) { - for (var channel = 0; channel < color.length; ++channel) { - color[channel] = badValues[i]; - var e = assertThrows(color + ' is not a valid rgba color', - goog.partial(goog.color.alpha.rgbaToRgbaStyle, color)); - assertContains('is not a valid RGBA color', e.message); - - color[channel] = 0; - } - } -} - -function testRgbaArrayToRgbaStyle() { - var testColors = [[[175, 19, 255, 1], 'rgba(175,19,255,1)'], - [[53, 124, 240, .6], 'rgba(53,124,240,0.6)']]; - - for (var i = 0; i < testColors.length; ++i) { - var r = goog.color.alpha.rgbaArrayToRgbaStyle(testColors[i][0]); - assertEquals(testColors[i][1], r); - } - - var badColors = [[0, 0, 0, 2]]; - for (var i = 0; i < badColors.length; ++i) { - var e = assertThrows(goog.partial(goog.color.alpha.rgbaArrayToRgbaStyle, - badColors[i])); - - assertContains('is not a valid RGBA color', e.message); - } - - // Loop through all bad color values and ensure they fail in each channel. - var badValues = [-1, 300, 'a', undefined, null, NaN]; - var color = [0, 0, 0, 0]; - for (var i = 0; i < badValues.length; ++i) { - for (var channel = 0; channel < color.length; ++channel) { - color[channel] = badValues[i]; - var e = assertThrows(color + ' is not a valid rgba color', - goog.partial(goog.color.alpha.rgbaToRgbaStyle, color)); - assertContains('is not a valid RGBA color', e.message); - - color[channel] = 0; - } - } -} - -function testRgbaArrayToHsla() { - var opaqueBlueRgb = [0, 0, 255, 1]; - var opaqueBlueHsl = goog.color.alpha.rgbaArrayToHsla(opaqueBlueRgb); - assertArrayEquals('Conversion from RGBA to HSLA should be as expected', - [240, 1, 0.5, 1], opaqueBlueHsl); - - var nearlyOpaqueYellowRgb = [255, 190, 0, 0.7]; - var nearlyOpaqueYellowHsl = - goog.color.alpha.rgbaArrayToHsla(nearlyOpaqueYellowRgb); - assertArrayEquals('Conversion from RGBA to HSLA should be as expected', - [45, 1, 0.5, 0.7], nearlyOpaqueYellowHsl); - - var transparentPurpleRgb = [180, 0, 255, 0]; - var transparentPurpleHsl = - goog.color.alpha.rgbaArrayToHsla(transparentPurpleRgb); - assertArrayEquals('Conversion from RGBA to HSLA should be as expected', - [282, 1, 0.5, 0], transparentPurpleHsl); -} - -function testNormalizeAlphaHex() { - var compactColor = '#abcd'; - var normalizedCompactColor = - goog.color.alpha.normalizeAlphaHex_(compactColor); - assertEquals('The color should have been normalized to the right length', - '#aabbccdd', normalizedCompactColor); - - var uppercaseColor = '#ABCDEF01'; - var normalizedUppercaseColor = - goog.color.alpha.normalizeAlphaHex_(uppercaseColor); - assertEquals('The color should have been normalized to lowercase', - '#abcdef01', normalizedUppercaseColor); -} - -function testHsvaArrayToHex() { - var opaqueSkyBlueHsv = [190, 1, 255, 1]; - var opaqueSkyBlueHex = goog.color.alpha.hsvaArrayToHex(opaqueSkyBlueHsv); - assertEquals('The HSVA array should have been properly converted to hex', - '#00d4ffff', opaqueSkyBlueHex); - - var halfTransparentPinkHsv = [300, 1, 255, 0.5]; - var halfTransparentPinkHex = - goog.color.alpha.hsvaArrayToHex(halfTransparentPinkHsv); - assertEquals('The HSVA array should have been properly converted to hex', - '#ff00ff7f', halfTransparentPinkHex); - - var transparentDarkTurquoiseHsv = [175, 1, 127, 0.5]; - var transparentDarkTurquoiseHex = - goog.color.alpha.hsvaArrayToHex(transparentDarkTurquoiseHsv); - assertEquals('The HSVA array should have been properly converted to hex', - '#007f747f', transparentDarkTurquoiseHex); -} - -function testExtractHexColor() { - var opaqueRed = '#ff0000ff'; - var red = goog.color.alpha.extractHexColor(opaqueRed); - assertEquals('The hex part of the color should have been extracted correctly', - '#ff0000', red); - - var halfOpaqueDarkGreenCompact = '#0507'; - var darkGreen = - goog.color.alpha.extractHexColor(halfOpaqueDarkGreenCompact); - assertEquals('The hex part of the color should have been extracted correctly', - '#005500', darkGreen); - -} - -function testExtractAlpha() { - var colors = ['#ff0000ff', '#0507', '#ff000005']; - var expectedOpacities = ['ff', '77', '05']; - - for (var i = 0; i < colors.length; i++) { - var opacity = goog.color.alpha.extractAlpha(colors[i]); - assertEquals('The alpha transparency should have been extracted correctly', - expectedOpacities[i], opacity); - } -} - -function testHslaArrayToRgbaStyle() { - assertEquals('rgba(102,255,102,0.5)', - goog.color.alpha.hslaArrayToRgbaStyle([120, 100, 70, 0.5])); - assertEquals('rgba(28,23,23,0.9)', - goog.color.alpha.hslaArrayToRgbaStyle([0, 10, 10, 0.9])); -} - -function testRgbaStyleParsableResult() { - var testColors = [[175, 19, 255, 1], - [53, 124, 240, .6], - [20, 30, 40, 0.3333333], - [255, 255, 255, 0.7071067811865476]]; - - for (var i = 0, testColor; testColor = testColors[i]; i++) { - var rgbaStyle = goog.color.alpha.rgbaStyle_(testColor); - var parsedColor = goog.color.alpha.hexToRgba( - goog.color.alpha.parse(rgbaStyle).hex); - assertEquals(testColor[0], parsedColor[0]); - assertEquals(testColor[1], parsedColor[1]); - assertEquals(testColor[2], parsedColor[2]); - // Parsing keeps a 1/255 accuracy on the alpha channel. - assertRoughlyEquals(testColor[3], parsedColor[3], 0.005); - } -} diff --git a/src/database/third_party/closure-library/closure/goog/color/color.js b/src/database/third_party/closure-library/closure/goog/color/color.js deleted file mode 100644 index 8220532b9f1..00000000000 --- a/src/database/third_party/closure-library/closure/goog/color/color.js +++ /dev/null @@ -1,776 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utilities related to color and color conversion. - */ - -goog.provide('goog.color'); -goog.provide('goog.color.Hsl'); -goog.provide('goog.color.Hsv'); -goog.provide('goog.color.Rgb'); - -goog.require('goog.color.names'); -goog.require('goog.math'); - - -/** - * RGB color representation. An array containing three elements [r, g, b], - * each an integer in [0, 255], representing the red, green, and blue components - * of the color respectively. - * @typedef {Array} - */ -goog.color.Rgb; - - -/** - * HSV color representation. An array containing three elements [h, s, v]: - * h (hue) must be an integer in [0, 360], cyclic. - * s (saturation) must be a number in [0, 1]. - * v (value/brightness) must be an integer in [0, 255]. - * @typedef {Array} - */ -goog.color.Hsv; - - -/** - * HSL color representation. An array containing three elements [h, s, l]: - * h (hue) must be an integer in [0, 360], cyclic. - * s (saturation) must be a number in [0, 1]. - * l (lightness) must be a number in [0, 1]. - * @typedef {Array} - */ -goog.color.Hsl; - - -/** - * Parses a color out of a string. - * @param {string} str Color in some format. - * @return {{hex: string, type: string}} 'hex' is a string containing a hex - * representation of the color, 'type' is a string containing the type - * of color format passed in ('hex', 'rgb', 'named'). - */ -goog.color.parse = function(str) { - var result = {}; - str = String(str); - - var maybeHex = goog.color.prependHashIfNecessaryHelper(str); - if (goog.color.isValidHexColor_(maybeHex)) { - result.hex = goog.color.normalizeHex(maybeHex); - result.type = 'hex'; - return result; - } else { - var rgb = goog.color.isValidRgbColor_(str); - if (rgb.length) { - result.hex = goog.color.rgbArrayToHex(rgb); - result.type = 'rgb'; - return result; - } else if (goog.color.names) { - var hex = goog.color.names[str.toLowerCase()]; - if (hex) { - result.hex = hex; - result.type = 'named'; - return result; - } - } - } - throw Error(str + ' is not a valid color string'); -}; - - -/** - * Determines if the given string can be parsed as a color. - * {@see goog.color.parse}. - * @param {string} str Potential color string. - * @return {boolean} True if str is in a format that can be parsed to a color. - */ -goog.color.isValidColor = function(str) { - var maybeHex = goog.color.prependHashIfNecessaryHelper(str); - return !!(goog.color.isValidHexColor_(maybeHex) || - goog.color.isValidRgbColor_(str).length || - goog.color.names && goog.color.names[str.toLowerCase()]); -}; - - -/** - * Parses red, green, blue components out of a valid rgb color string. - * Throws Error if the color string is invalid. - * @param {string} str RGB representation of a color. - * {@see goog.color.isValidRgbColor_}. - * @return {!goog.color.Rgb} rgb representation of the color. - */ -goog.color.parseRgb = function(str) { - var rgb = goog.color.isValidRgbColor_(str); - if (!rgb.length) { - throw Error(str + ' is not a valid RGB color'); - } - return rgb; -}; - - -/** - * Converts a hex representation of a color to RGB. - * @param {string} hexColor Color to convert. - * @return {string} string of the form 'rgb(R,G,B)' which can be used in - * styles. - */ -goog.color.hexToRgbStyle = function(hexColor) { - return goog.color.rgbStyle_(goog.color.hexToRgb(hexColor)); -}; - - -/** - * Regular expression for extracting the digits in a hex color triplet. - * @type {RegExp} - * @private - */ -goog.color.hexTripletRe_ = /#(.)(.)(.)/; - - -/** - * Normalize an hex representation of a color - * @param {string} hexColor an hex color string. - * @return {string} hex color in the format '#rrggbb' with all lowercase - * literals. - */ -goog.color.normalizeHex = function(hexColor) { - if (!goog.color.isValidHexColor_(hexColor)) { - throw Error("'" + hexColor + "' is not a valid hex color"); - } - if (hexColor.length == 4) { // of the form #RGB - hexColor = hexColor.replace(goog.color.hexTripletRe_, '#$1$1$2$2$3$3'); - } - return hexColor.toLowerCase(); -}; - - -/** - * Converts a hex representation of a color to RGB. - * @param {string} hexColor Color to convert. - * @return {!goog.color.Rgb} rgb representation of the color. - */ -goog.color.hexToRgb = function(hexColor) { - hexColor = goog.color.normalizeHex(hexColor); - var r = parseInt(hexColor.substr(1, 2), 16); - var g = parseInt(hexColor.substr(3, 2), 16); - var b = parseInt(hexColor.substr(5, 2), 16); - - return [r, g, b]; -}; - - -/** - * Converts a color from RGB to hex representation. - * @param {number} r Amount of red, int between 0 and 255. - * @param {number} g Amount of green, int between 0 and 255. - * @param {number} b Amount of blue, int between 0 and 255. - * @return {string} hex representation of the color. - */ -goog.color.rgbToHex = function(r, g, b) { - r = Number(r); - g = Number(g); - b = Number(b); - if (isNaN(r) || r < 0 || r > 255 || - isNaN(g) || g < 0 || g > 255 || - isNaN(b) || b < 0 || b > 255) { - throw Error('"(' + r + ',' + g + ',' + b + '") is not a valid RGB color'); - } - var hexR = goog.color.prependZeroIfNecessaryHelper(r.toString(16)); - var hexG = goog.color.prependZeroIfNecessaryHelper(g.toString(16)); - var hexB = goog.color.prependZeroIfNecessaryHelper(b.toString(16)); - return '#' + hexR + hexG + hexB; -}; - - -/** - * Converts a color from RGB to hex representation. - * @param {goog.color.Rgb} rgb rgb representation of the color. - * @return {string} hex representation of the color. - */ -goog.color.rgbArrayToHex = function(rgb) { - return goog.color.rgbToHex(rgb[0], rgb[1], rgb[2]); -}; - - -/** - * Converts a color from RGB color space to HSL color space. - * Modified from {@link http://en.wikipedia.org/wiki/HLS_color_space}. - * @param {number} r Value of red, in [0, 255]. - * @param {number} g Value of green, in [0, 255]. - * @param {number} b Value of blue, in [0, 255]. - * @return {!goog.color.Hsl} hsl representation of the color. - */ -goog.color.rgbToHsl = function(r, g, b) { - // First must normalize r, g, b to be between 0 and 1. - var normR = r / 255; - var normG = g / 255; - var normB = b / 255; - var max = Math.max(normR, normG, normB); - var min = Math.min(normR, normG, normB); - var h = 0; - var s = 0; - - // Luminosity is the average of the max and min rgb color intensities. - var l = 0.5 * (max + min); - - // The hue and saturation are dependent on which color intensity is the max. - // If max and min are equal, the color is gray and h and s should be 0. - if (max != min) { - if (max == normR) { - h = 60 * (normG - normB) / (max - min); - } else if (max == normG) { - h = 60 * (normB - normR) / (max - min) + 120; - } else if (max == normB) { - h = 60 * (normR - normG) / (max - min) + 240; - } - - if (0 < l && l <= 0.5) { - s = (max - min) / (2 * l); - } else { - s = (max - min) / (2 - 2 * l); - } - } - - // Make sure the hue falls between 0 and 360. - return [Math.round(h + 360) % 360, s, l]; -}; - - -/** - * Converts a color from RGB color space to HSL color space. - * @param {goog.color.Rgb} rgb rgb representation of the color. - * @return {!goog.color.Hsl} hsl representation of the color. - */ -goog.color.rgbArrayToHsl = function(rgb) { - return goog.color.rgbToHsl(rgb[0], rgb[1], rgb[2]); -}; - - -/** - * Helper for hslToRgb. - * @param {number} v1 Helper variable 1. - * @param {number} v2 Helper variable 2. - * @param {number} vH Helper variable 3. - * @return {number} Appropriate RGB value, given the above. - * @private - */ -goog.color.hueToRgb_ = function(v1, v2, vH) { - if (vH < 0) { - vH += 1; - } else if (vH > 1) { - vH -= 1; - } - if ((6 * vH) < 1) { - return (v1 + (v2 - v1) * 6 * vH); - } else if (2 * vH < 1) { - return v2; - } else if (3 * vH < 2) { - return (v1 + (v2 - v1) * ((2 / 3) - vH) * 6); - } - return v1; -}; - - -/** - * Converts a color from HSL color space to RGB color space. - * Modified from {@link http://www.easyrgb.com/math.html} - * @param {number} h Hue, in [0, 360]. - * @param {number} s Saturation, in [0, 1]. - * @param {number} l Luminosity, in [0, 1]. - * @return {!goog.color.Rgb} rgb representation of the color. - */ -goog.color.hslToRgb = function(h, s, l) { - var r = 0; - var g = 0; - var b = 0; - var normH = h / 360; // normalize h to fall in [0, 1] - - if (s == 0) { - r = g = b = l * 255; - } else { - var temp1 = 0; - var temp2 = 0; - if (l < 0.5) { - temp2 = l * (1 + s); - } else { - temp2 = l + s - (s * l); - } - temp1 = 2 * l - temp2; - r = 255 * goog.color.hueToRgb_(temp1, temp2, normH + (1 / 3)); - g = 255 * goog.color.hueToRgb_(temp1, temp2, normH); - b = 255 * goog.color.hueToRgb_(temp1, temp2, normH - (1 / 3)); - } - - return [Math.round(r), Math.round(g), Math.round(b)]; -}; - - -/** - * Converts a color from HSL color space to RGB color space. - * @param {goog.color.Hsl} hsl hsl representation of the color. - * @return {!goog.color.Rgb} rgb representation of the color. - */ -goog.color.hslArrayToRgb = function(hsl) { - return goog.color.hslToRgb(hsl[0], hsl[1], hsl[2]); -}; - - -/** - * Helper for isValidHexColor_. - * @type {RegExp} - * @private - */ -goog.color.validHexColorRe_ = /^#(?:[0-9a-f]{3}){1,2}$/i; - - -/** - * Checks if a string is a valid hex color. We expect strings of the format - * #RRGGBB (ex: #1b3d5f) or #RGB (ex: #3CA == #33CCAA). - * @param {string} str String to check. - * @return {boolean} Whether the string is a valid hex color. - * @private - */ -goog.color.isValidHexColor_ = function(str) { - return goog.color.validHexColorRe_.test(str); -}; - - -/** - * Helper for isNormalizedHexColor_. - * @type {RegExp} - * @private - */ -goog.color.normalizedHexColorRe_ = /^#[0-9a-f]{6}$/; - - -/** - * Checks if a string is a normalized hex color. - * We expect strings of the format #RRGGBB (ex: #1b3d5f) - * using only lowercase letters. - * @param {string} str String to check. - * @return {boolean} Whether the string is a normalized hex color. - * @private - */ -goog.color.isNormalizedHexColor_ = function(str) { - return goog.color.normalizedHexColorRe_.test(str); -}; - - -/** - * Regular expression for matching and capturing RGB style strings. Helper for - * isValidRgbColor_. - * @type {RegExp} - * @private - */ -goog.color.rgbColorRe_ = - /^(?:rgb)?\((0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2})\)$/i; - - -/** - * Checks if a string is a valid rgb color. We expect strings of the format - * '(r, g, b)', or 'rgb(r, g, b)', where each color component is an int in - * [0, 255]. - * @param {string} str String to check. - * @return {!goog.color.Rgb} the rgb representation of the color if it is - * a valid color, or the empty array otherwise. - * @private - */ -goog.color.isValidRgbColor_ = function(str) { - // Each component is separate (rather than using a repeater) so we can - // capture the match. Also, we explicitly set each component to be either 0, - // or start with a non-zero, to prevent octal numbers from slipping through. - var regExpResultArray = str.match(goog.color.rgbColorRe_); - if (regExpResultArray) { - var r = Number(regExpResultArray[1]); - var g = Number(regExpResultArray[2]); - var b = Number(regExpResultArray[3]); - if (r >= 0 && r <= 255 && - g >= 0 && g <= 255 && - b >= 0 && b <= 255) { - return [r, g, b]; - } - } - return []; -}; - - -/** - * Takes a hex value and prepends a zero if it's a single digit. - * Small helper method for use by goog.color and friends. - * @param {string} hex Hex value to prepend if single digit. - * @return {string} hex value prepended with zero if it was single digit, - * otherwise the same value that was passed in. - */ -goog.color.prependZeroIfNecessaryHelper = function(hex) { - return hex.length == 1 ? '0' + hex : hex; -}; - - -/** - * Takes a string a prepends a '#' sign if one doesn't exist. - * Small helper method for use by goog.color and friends. - * @param {string} str String to check. - * @return {string} The value passed in, prepended with a '#' if it didn't - * already have one. - */ -goog.color.prependHashIfNecessaryHelper = function(str) { - return str.charAt(0) == '#' ? str : '#' + str; -}; - - -/** - * Takes an array of [r, g, b] and converts it into a string appropriate for - * CSS styles. - * @param {goog.color.Rgb} rgb rgb representation of the color. - * @return {string} string of the form 'rgb(r,g,b)'. - * @private - */ -goog.color.rgbStyle_ = function(rgb) { - return 'rgb(' + rgb.join(',') + ')'; -}; - - -/** - * Converts an HSV triplet to an RGB array. V is brightness because b is - * reserved for blue in RGB. - * @param {number} h Hue value in [0, 360]. - * @param {number} s Saturation value in [0, 1]. - * @param {number} brightness brightness in [0, 255]. - * @return {!goog.color.Rgb} rgb representation of the color. - */ -goog.color.hsvToRgb = function(h, s, brightness) { - var red = 0; - var green = 0; - var blue = 0; - if (s == 0) { - red = brightness; - green = brightness; - blue = brightness; - } else { - var sextant = Math.floor(h / 60); - var remainder = (h / 60) - sextant; - var val1 = brightness * (1 - s); - var val2 = brightness * (1 - (s * remainder)); - var val3 = brightness * (1 - (s * (1 - remainder))); - switch (sextant) { - case 1: - red = val2; - green = brightness; - blue = val1; - break; - case 2: - red = val1; - green = brightness; - blue = val3; - break; - case 3: - red = val1; - green = val2; - blue = brightness; - break; - case 4: - red = val3; - green = val1; - blue = brightness; - break; - case 5: - red = brightness; - green = val1; - blue = val2; - break; - case 6: - case 0: - red = brightness; - green = val3; - blue = val1; - break; - } - } - - return [Math.floor(red), Math.floor(green), Math.floor(blue)]; -}; - - -/** - * Converts from RGB values to an array of HSV values. - * @param {number} red Red value in [0, 255]. - * @param {number} green Green value in [0, 255]. - * @param {number} blue Blue value in [0, 255]. - * @return {!goog.color.Hsv} hsv representation of the color. - */ -goog.color.rgbToHsv = function(red, green, blue) { - - var max = Math.max(Math.max(red, green), blue); - var min = Math.min(Math.min(red, green), blue); - var hue; - var saturation; - var value = max; - if (min == max) { - hue = 0; - saturation = 0; - } else { - var delta = (max - min); - saturation = delta / max; - - if (red == max) { - hue = (green - blue) / delta; - } else if (green == max) { - hue = 2 + ((blue - red) / delta); - } else { - hue = 4 + ((red - green) / delta); - } - hue *= 60; - if (hue < 0) { - hue += 360; - } - if (hue > 360) { - hue -= 360; - } - } - - return [hue, saturation, value]; -}; - - -/** - * Converts from an array of RGB values to an array of HSV values. - * @param {goog.color.Rgb} rgb rgb representation of the color. - * @return {!goog.color.Hsv} hsv representation of the color. - */ -goog.color.rgbArrayToHsv = function(rgb) { - return goog.color.rgbToHsv(rgb[0], rgb[1], rgb[2]); -}; - - -/** - * Converts an HSV triplet to an RGB array. - * @param {goog.color.Hsv} hsv hsv representation of the color. - * @return {!goog.color.Rgb} rgb representation of the color. - */ -goog.color.hsvArrayToRgb = function(hsv) { - return goog.color.hsvToRgb(hsv[0], hsv[1], hsv[2]); -}; - - -/** - * Converts a hex representation of a color to HSL. - * @param {string} hex Color to convert. - * @return {!goog.color.Hsv} hsv representation of the color. - */ -goog.color.hexToHsl = function(hex) { - var rgb = goog.color.hexToRgb(hex); - return goog.color.rgbToHsl(rgb[0], rgb[1], rgb[2]); -}; - - -/** - * Converts from h,s,l values to a hex string - * @param {number} h Hue, in [0, 360]. - * @param {number} s Saturation, in [0, 1]. - * @param {number} l Luminosity, in [0, 1]. - * @return {string} hex representation of the color. - */ -goog.color.hslToHex = function(h, s, l) { - return goog.color.rgbArrayToHex(goog.color.hslToRgb(h, s, l)); -}; - - -/** - * Converts from an hsl array to a hex string - * @param {goog.color.Hsl} hsl hsl representation of the color. - * @return {string} hex representation of the color. - */ -goog.color.hslArrayToHex = function(hsl) { - return goog.color.rgbArrayToHex(goog.color.hslToRgb(hsl[0], hsl[1], hsl[2])); -}; - - -/** - * Converts a hex representation of a color to HSV - * @param {string} hex Color to convert. - * @return {!goog.color.Hsv} hsv representation of the color. - */ -goog.color.hexToHsv = function(hex) { - return goog.color.rgbArrayToHsv(goog.color.hexToRgb(hex)); -}; - - -/** - * Converts from h,s,v values to a hex string - * @param {number} h Hue, in [0, 360]. - * @param {number} s Saturation, in [0, 1]. - * @param {number} v Value, in [0, 255]. - * @return {string} hex representation of the color. - */ -goog.color.hsvToHex = function(h, s, v) { - return goog.color.rgbArrayToHex(goog.color.hsvToRgb(h, s, v)); -}; - - -/** - * Converts from an HSV array to a hex string - * @param {goog.color.Hsv} hsv hsv representation of the color. - * @return {string} hex representation of the color. - */ -goog.color.hsvArrayToHex = function(hsv) { - return goog.color.hsvToHex(hsv[0], hsv[1], hsv[2]); -}; - - -/** - * Calculates the Euclidean distance between two color vectors on an HSL sphere. - * A demo of the sphere can be found at: - * http://en.wikipedia.org/wiki/HSL_color_space - * In short, a vector for color (H, S, L) in this system can be expressed as - * (S*L'*cos(2*PI*H), S*L'*sin(2*PI*H), L), where L' = abs(L - 0.5), and we - * simply calculate the 1-2 distance using these coordinates - * @param {goog.color.Hsl} hsl1 First color in hsl representation. - * @param {goog.color.Hsl} hsl2 Second color in hsl representation. - * @return {number} Distance between the two colors, in the range [0, 1]. - */ -goog.color.hslDistance = function(hsl1, hsl2) { - var sl1, sl2; - if (hsl1[2] <= 0.5) { - sl1 = hsl1[1] * hsl1[2]; - } else { - sl1 = hsl1[1] * (1.0 - hsl1[2]); - } - - if (hsl2[2] <= 0.5) { - sl2 = hsl2[1] * hsl2[2]; - } else { - sl2 = hsl2[1] * (1.0 - hsl2[2]); - } - - var h1 = hsl1[0] / 360.0; - var h2 = hsl2[0] / 360.0; - var dh = (h1 - h2) * 2.0 * Math.PI; - return (hsl1[2] - hsl2[2]) * (hsl1[2] - hsl2[2]) + - sl1 * sl1 + sl2 * sl2 - 2 * sl1 * sl2 * Math.cos(dh); -}; - - -/** - * Blend two colors together, using the specified factor to indicate the weight - * given to the first color - * @param {goog.color.Rgb} rgb1 First color represented in rgb. - * @param {goog.color.Rgb} rgb2 Second color represented in rgb. - * @param {number} factor The weight to be given to rgb1 over rgb2. Values - * should be in the range [0, 1]. If less than 0, factor will be set to 0. - * If greater than 1, factor will be set to 1. - * @return {!goog.color.Rgb} Combined color represented in rgb. - */ -goog.color.blend = function(rgb1, rgb2, factor) { - factor = goog.math.clamp(factor, 0, 1); - - return [ - Math.round(factor * rgb1[0] + (1.0 - factor) * rgb2[0]), - Math.round(factor * rgb1[1] + (1.0 - factor) * rgb2[1]), - Math.round(factor * rgb1[2] + (1.0 - factor) * rgb2[2]) - ]; -}; - - -/** - * Adds black to the specified color, darkening it - * @param {goog.color.Rgb} rgb rgb representation of the color. - * @param {number} factor Number in the range [0, 1]. 0 will do nothing, while - * 1 will return black. If less than 0, factor will be set to 0. If greater - * than 1, factor will be set to 1. - * @return {!goog.color.Rgb} Combined rgb color. - */ -goog.color.darken = function(rgb, factor) { - var black = [0, 0, 0]; - return goog.color.blend(black, rgb, factor); -}; - - -/** - * Adds white to the specified color, lightening it - * @param {goog.color.Rgb} rgb rgb representation of the color. - * @param {number} factor Number in the range [0, 1]. 0 will do nothing, while - * 1 will return white. If less than 0, factor will be set to 0. If greater - * than 1, factor will be set to 1. - * @return {!goog.color.Rgb} Combined rgb color. - */ -goog.color.lighten = function(rgb, factor) { - var white = [255, 255, 255]; - return goog.color.blend(white, rgb, factor); -}; - - -/** - * Find the "best" (highest-contrast) of the suggested colors for the prime - * color. Uses W3C formula for judging readability and visual accessibility: - * http://www.w3.org/TR/AERT#color-contrast - * @param {goog.color.Rgb} prime Color represented as a rgb array. - * @param {Array} suggestions Array of colors, - * each representing a rgb array. - * @return {!goog.color.Rgb} Highest-contrast color represented by an array.. - */ -goog.color.highContrast = function(prime, suggestions) { - var suggestionsWithDiff = []; - for (var i = 0; i < suggestions.length; i++) { - suggestionsWithDiff.push({ - color: suggestions[i], - diff: goog.color.yiqBrightnessDiff_(suggestions[i], prime) + - goog.color.colorDiff_(suggestions[i], prime) - }); - } - suggestionsWithDiff.sort(function(a, b) { - return b.diff - a.diff; - }); - return suggestionsWithDiff[0].color; -}; - - -/** - * Calculate brightness of a color according to YIQ formula (brightness is Y). - * More info on YIQ here: http://en.wikipedia.org/wiki/YIQ. Helper method for - * goog.color.highContrast() - * @param {goog.color.Rgb} rgb Color represented by a rgb array. - * @return {number} brightness (Y). - * @private - */ -goog.color.yiqBrightness_ = function(rgb) { - return Math.round((rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000); -}; - - -/** - * Calculate difference in brightness of two colors. Helper method for - * goog.color.highContrast() - * @param {goog.color.Rgb} rgb1 Color represented by a rgb array. - * @param {goog.color.Rgb} rgb2 Color represented by a rgb array. - * @return {number} Brightness difference. - * @private - */ -goog.color.yiqBrightnessDiff_ = function(rgb1, rgb2) { - return Math.abs(goog.color.yiqBrightness_(rgb1) - - goog.color.yiqBrightness_(rgb2)); -}; - - -/** - * Calculate color difference between two colors. Helper method for - * goog.color.highContrast() - * @param {goog.color.Rgb} rgb1 Color represented by a rgb array. - * @param {goog.color.Rgb} rgb2 Color represented by a rgb array. - * @return {number} Color difference. - * @private - */ -goog.color.colorDiff_ = function(rgb1, rgb2) { - return Math.abs(rgb1[0] - rgb2[0]) + Math.abs(rgb1[1] - rgb2[1]) + - Math.abs(rgb1[2] - rgb2[2]); -}; diff --git a/src/database/third_party/closure-library/closure/goog/color/color_test.html b/src/database/third_party/closure-library/closure/goog/color/color_test.html deleted file mode 100644 index e8c37088da1..00000000000 --- a/src/database/third_party/closure-library/closure/goog/color/color_test.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - Closure Unit Tests - goog.color - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/color/color_test.js b/src/database/third_party/closure-library/closure/goog/color/color_test.js deleted file mode 100644 index 8da740ac34a..00000000000 --- a/src/database/third_party/closure-library/closure/goog/color/color_test.js +++ /dev/null @@ -1,667 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -goog.provide('goog.colorTest'); -goog.setTestOnly('goog.colorTest'); - -goog.require('goog.array'); -goog.require('goog.color'); -goog.require('goog.color.names'); -goog.require('goog.testing.jsunit'); - -function testIsValidColor() { - var goodColors = ['#ffffff', '#ff7812', '#012345', '#Ff003D', '#3CA', - '(255, 26, 75)', 'RGB(2, 3, 4)', '(0,0,0)', 'white', - 'blue']; - var badColors = ['#xxxxxx', '8899000', 'not_color', '#1234567', 'fffffg', - '(2555,0,0)', '(1,2,3,4)', 'rgb(1,20,)', 'RGB(20,20,20,)', - 'omgwtfbbq']; - for (var i = 0; i < goodColors.length; i++) { - assertTrue(goodColors[i], goog.color.isValidColor(goodColors[i])); - } - for (var i = 0; i < badColors.length; i++) { - assertFalse(badColors[i], goog.color.isValidColor(badColors[i])); - } -} - - -function testIsValidHexColor() { - var goodHexColors = ['#ffffff', '#ff7812', '#012345', '#Ff003D', '#3CA']; - var badHexColors = ['#xxxxxx', '889900', 'not_color', '#1234567', 'fffffg']; - for (var i = 0; i < goodHexColors.length; i++) { - assertTrue(goodHexColors[i], goog.color.isValidHexColor_(goodHexColors[i])); - } - for (var i = 0; i < badHexColors.length; i++) { - assertFalse(badHexColors[i], goog.color.isValidHexColor_(badHexColors[i])); - } -} - - -function testIsValidRgbColor() { - var goodRgbColors = ['(255, 26, 75)', 'RGB(2, 3, 4)', '(0,0,0)', - 'rgb(255,255,255)']; - var badRgbColors = ['(2555,0,0)', '(1,2,3,4)', 'rgb(1,20,)', - 'RGB(20,20,20,)']; - for (var i = 0; i < goodRgbColors.length; i++) { - assertEquals(goodRgbColors[i], - goog.color.isValidRgbColor_(goodRgbColors[i]).length, 3); - } - for (var i = 0; i < badRgbColors.length; i++) { - assertEquals(badRgbColors[i], - goog.color.isValidRgbColor_(badRgbColors[i]).length, 0); - } -} - - -function testParse() { - var colors = ['rgb(15, 250, 77)', '(127, 127, 127)', '#ffeedd', '123456', - 'magenta']; - var parsed = goog.array.map(colors, goog.color.parse); - assertEquals('rgb', parsed[0].type); - assertEquals(goog.color.rgbToHex(15, 250, 77), parsed[0].hex); - assertEquals('rgb', parsed[1].type); - assertEquals(goog.color.rgbToHex(127, 127, 127), parsed[1].hex); - assertEquals('hex', parsed[2].type); - assertEquals('#ffeedd', parsed[2].hex); - assertEquals('hex', parsed[3].type); - assertEquals('#123456', parsed[3].hex); - assertEquals('named', parsed[4].type); - assertEquals('#ff00ff', parsed[4].hex); - - var badColors = ['rgb(01, 1, 23)', '(256, 256, 256)', '#ffeeddaa']; - for (var i = 0; i < badColors.length; i++) { - var e = assertThrows(goog.partial(goog.color.parse, badColors[i])); - assertContains('is not a valid color string', e.message); - } -} - - -function testHexToRgb() { - var testColors = [['#B0FF2D', [176, 255, 45]], - ['#b26e5f', [178, 110, 95]], - ['#66f', [102, 102, 255]]]; - - for (var i = 0; i < testColors.length; i++) { - var r = goog.color.hexToRgb(testColors[i][0]); - var t = testColors[i][1]; - - assertEquals('Red channel should match.', t[0], r[0]); - assertEquals('Green channel should match.', t[1], r[1]); - assertEquals('Blue channel should match.', t[2], r[2]); - } - - var badColors = ['', '#g00', 'some words']; - for (var i = 0; i < badColors.length; i++) { - var e = assertThrows(goog.partial(goog.color.hexToRgb, badColors[i])); - assertEquals("'" + badColors[i] + "' is not a valid hex color", e.message); - } -} - - -function testHexToRgbStyle() { - assertEquals('rgb(255,0,0)', goog.color.hexToRgbStyle(goog.color.names.red)); - assertEquals('rgb(206,206,206)', goog.color.hexToRgbStyle('#cecece')); - assertEquals('rgb(51,204,170)', goog.color.hexToRgbStyle('#3CA')); - var badHexColors = ['#1234', null, undefined, '#.1234567890']; - for (var i = 0; i < badHexColors.length; ++i) { - var badHexColor = badHexColors[i]; - var e = assertThrows(goog.partial(goog.color.hexToRgbStyle, badHexColor)); - assertEquals("'" + badHexColor + "' is not a valid hex color", e.message); - } -} - - -function testRgbToHex() { - assertEquals(goog.color.names.red, goog.color.rgbToHex(255, 0, 0)); - assertEquals('#af13ff', goog.color.rgbToHex(175, 19, 255)); - var badRgb = [[-1, -1, -1], [256, 0, 0], ['a', 'b', 'c'], [undefined, 5, 5]]; - for (var i = 0; i < badRgb.length; ++i) { - var e = assertThrows(goog.partial(goog.color.rgbArrayToHex, badRgb[i])); - assertContains('is not a valid RGB color', e.message); - } -} - - -function testRgbToHsl() { - var rgb = [255, 171, 32]; - var hsl = goog.color.rgbArrayToHsl(rgb); - assertEquals(37, hsl[0]); - assertTrue(1.0 - hsl[1] < 0.01); - assertTrue(hsl[2] - .5625 < 0.01); -} - - -function testHslToRgb() { - var hsl = [60, 0.5, 0.1]; - var rgb = goog.color.hslArrayToRgb(hsl); - assertEquals(38, rgb[0]); - assertEquals(38, rgb[1]); - assertEquals(13, rgb[2]); -} - - -// Tests accuracy of HSL to RGB conversion -function testHSLBidiToRGB() { - var DELTA = 1; - - var color = [[100, 56, 200], - [255, 0, 0], - [0, 0, 255], - [0, 255, 0], - [255, 255, 255], - [0, 0, 0]]; - - for (var i = 0; i < color.length; i++) { - colorConversionTestHelper( - function(color) { - return goog.color.rgbToHsl(color[0], color[1], color[2]); - }, - function(color) { - return goog.color.hslToRgb(color[0], color[1], color[2]); - }, - color[i], DELTA); - - colorConversionTestHelper( - function(color) { return goog.color.rgbArrayToHsl(color); }, - function(color) { return goog.color.hslArrayToRgb(color); }, - color[i], DELTA); - } -} - - -// Tests HSV to RGB conversion -function testHSVToRGB() { - var DELTA = 1; - - var color = [[100, 56, 200], - [255, 0, 0], - [0, 0, 255], - [0, 255, 0], - [255, 255, 255], - [0, 0, 0]]; - - for (var i = 0; i < color.length; i++) { - colorConversionTestHelper( - function(color) { - return goog.color.rgbToHsv(color[0], color[1], color[2]); - }, - function(color) { - return goog.color.hsvToRgb(color[0], color[1], color[2]); - }, - color[i], DELTA); - - colorConversionTestHelper( - function(color) { return goog.color.rgbArrayToHsv(color); }, - function(color) { return goog.color.hsvArrayToRgb(color); }, - color[i], DELTA); - } -} - -// Tests that HSV space is (0-360) for hue -function testHSVSpecRangeIsCorrect() { - var color = [0, 0, 255]; // Blue is in the middle of hue range - - var hsv = goog.color.rgbToHsv(color[0], color[1], color[2]); - - assertTrue("H in HSV space looks like it's not 0-360", hsv[0] > 1); -} - -// Tests conversion between HSL and Hex -function testHslToHex() { - var DELTA = 1; - - var color = [[0, 0, 0], - [20, 0.5, 0.5], - [0, 0, 1], - [255, .45, .76]]; - - for (var i = 0; i < color.length; i++) { - colorConversionTestHelper( - function(hsl) { return goog.color.hslToHex(hsl[0], hsl[1], hsl[2]); }, - function(hex) { return goog.color.hexToHsl(hex); }, - color[i], DELTA); - - colorConversionTestHelper( - function(hsl) { return goog.color.hslArrayToHex(hsl); }, - function(hex) { return goog.color.hexToHsl(hex); }, - color[i], DELTA); - } -} - -// Tests conversion between HSV and Hex -function testHsvToHex() { - var DELTA = 1; - - var color = [[0, 0, 0], - [.5, 0.5, 155], - [0, 0, 255], - [.7, .45, 21]]; - - for (var i = 0; i < color.length; i++) { - colorConversionTestHelper( - function(hsl) { return goog.color.hsvToHex(hsl[0], hsl[1], hsl[2]); }, - function(hex) { return goog.color.hexToHsv(hex); }, - color[i], DELTA); - - colorConversionTestHelper( - function(hsl) { return goog.color.hsvArrayToHex(hsl); }, - function(hex) { return goog.color.hexToHsv(hex); }, - color[i], DELTA); - } -} - - -/** - * This helper method compares two RGB colors, checking that each color - * component is the same. - * @param {Array} rgb1 Color represented by a 3-element array with - * red, green, and blue values respectively, in the range [0, 255]. - * @param {Array} rgb2 Color represented by a 3-element array with - * red, green, and blue values respectively, in the range [0, 255]. - * @return {boolean} True if the colors are the same, false otherwise. - */ -function rgbColorsAreEqual(rgb1, rgb2) { - return (rgb1[0] == rgb2[0] && - rgb1[1] == rgb2[1] && - rgb1[2] == rgb2[2]); -} - - -/** - * This method runs unit tests against goog.color.blend(). Test cases include: - * blending arbitrary colors with factors of 0 and 1, blending the same colors - * using arbitrary factors, blending different colors of varying factors, - * and blending colors using factors outside the expected range. - */ -function testColorBlend() { - // Define some RGB colors for our tests. - var black = [0, 0, 0]; - var blue = [0, 0, 255]; - var gray = [128, 128, 128]; - var green = [0, 255, 0]; - var purple = [128, 0, 128]; - var red = [255, 0, 0]; - var yellow = [255, 255, 0]; - var white = [255, 255, 255]; - - // Blend arbitrary colors, using 0 and 1 for factors. Using 0 should return - // the first color, while using 1 should return the second color. - var redWithNoGreen = goog.color.blend(red, green, 1); - assertTrue('red + 0 * green = red', - rgbColorsAreEqual(red, redWithNoGreen)); - var whiteWithAllBlue = goog.color.blend(white, blue, 0); - assertTrue('white + 1 * blue = blue', - rgbColorsAreEqual(blue, whiteWithAllBlue)); - - // Blend the same colors using arbitrary factors. This should return the - // same colors. - var greenWithGreen = goog.color.blend(green, green, .25); - assertTrue('green + .25 * green = green', - rgbColorsAreEqual(green, greenWithGreen)); - - // Blend different colors using varying factors. - var blackWithWhite = goog.color.blend(black, white, .5); - assertTrue('black + .5 * white = gray', - rgbColorsAreEqual(gray, blackWithWhite)); - var redAndBlue = goog.color.blend(red, blue, .5); - assertTrue('red + .5 * blue = purple', - rgbColorsAreEqual(purple, redAndBlue)); - var lightGreen = goog.color.blend(green, white, .75); - assertTrue('green + .25 * white = a lighter shade of white', - lightGreen[0] > 0 && - lightGreen[1] == 255 && - lightGreen[2] > 0); - - // Blend arbitrary colors using factors outside the expected range. - var noGreenAllPurple = goog.color.blend(green, purple, -0.5); - assertTrue('green * -0.5 + purple = purple.', - rgbColorsAreEqual(purple, noGreenAllPurple)); - var allBlueNoYellow = goog.color.blend(blue, yellow, 1.37); - assertTrue('blue * 1.37 + yellow = blue.', - rgbColorsAreEqual(blue, allBlueNoYellow)); -} - - -/** - * This method runs unit tests against goog.color.darken(). Test cases - * include darkening black with arbitrary factors, edge cases (using 0 and 1), - * darkening colors using various factors, and darkening colors using factors - * outside the expected range. - */ -function testColorDarken() { - // Define some RGB colors - var black = [0, 0, 0]; - var green = [0, 255, 0]; - var darkGray = [68, 68, 68]; - var olive = [128, 128, 0]; - var purple = [128, 0, 128]; - var white = [255, 255, 255]; - - // Darken black by an arbitrary factor, which should still return black. - var darkBlack = goog.color.darken(black, .63); - assertTrue('black darkened by .63 is still black.', - rgbColorsAreEqual(black, darkBlack)); - - // Call darken() with edge-case factors (0 and 1). - var greenNotDarkened = goog.color.darken(green, 0); - assertTrue('green darkened by 0 is still green.', - rgbColorsAreEqual(green, greenNotDarkened)); - var whiteFullyDarkened = goog.color.darken(white, 1); - assertTrue('white darkened by 1 is black.', - rgbColorsAreEqual(black, whiteFullyDarkened)); - - // Call darken() with various colors and factors. The result should be - // a color with less luminance. - var whiteHsl = goog.color.rgbToHsl(white[0], - white[1], - white[2]); - var whiteDarkened = goog.color.darken(white, .43); - var whiteDarkenedHsl = goog.color.rgbToHsl(whiteDarkened[0], - whiteDarkened[1], - whiteDarkened[2]); - assertTrue('White that\'s darkened has less luminance than white.', - whiteDarkenedHsl[2] < whiteHsl[2]); - var purpleHsl = goog.color.rgbToHsl(purple[0], - purple[1], - purple[2]); - var purpleDarkened = goog.color.darken(purple, .1); - var purpleDarkenedHsl = goog.color.rgbToHsl(purpleDarkened[0], - purpleDarkened[1], - purpleDarkened[2]); - assertTrue('Purple that\'s darkened has less luminance than purple.', - purpleDarkenedHsl[2] < purpleHsl[2]); - - // Call darken() with factors outside the expected range. - var darkGrayTurnedBlack = goog.color.darken(darkGray, 2.1); - assertTrue('Darkening dark gray by 2.1 returns black.', - rgbColorsAreEqual(black, darkGrayTurnedBlack)); - var whiteNotDarkened = goog.color.darken(white, -0.62); - assertTrue('Darkening white by -0.62 returns white.', - rgbColorsAreEqual(white, whiteNotDarkened)); -} - - -/** - * This method runs unit tests against goog.color.lighten(). Test cases - * include lightening white with arbitrary factors, edge cases (using 0 and 1), - * lightening colors using various factors, and lightening colors using factors - * outside the expected range. - */ -function testColorLighten() { - // Define some RGB colors - var black = [0, 0, 0]; - var brown = [165, 42, 42]; - var navy = [0, 0, 128]; - var orange = [255, 165, 0]; - var white = [255, 255, 255]; - - // Lighten white by an arbitrary factor, which should still return white. - var lightWhite = goog.color.lighten(white, .41); - assertTrue('white lightened by .41 is still white.', - rgbColorsAreEqual(white, lightWhite)); - - // Call lighten() with edge-case factors(0 and 1). - var navyNotLightened = goog.color.lighten(navy, 0); - assertTrue('navy lightened by 0 is still navy.', - rgbColorsAreEqual(navy, navyNotLightened)); - var orangeFullyLightened = goog.color.lighten(orange, 1); - assertTrue('orange lightened by 1 is white.', - rgbColorsAreEqual(white, orangeFullyLightened)); - - // Call lighten() with various colors and factors. The result should be - // a color with greater luminance. - var blackHsl = goog.color.rgbToHsl(black[0], - black[1], - black[2]); - var blackLightened = goog.color.lighten(black, .33); - var blackLightenedHsl = goog.color.rgbToHsl(blackLightened[0], - blackLightened[1], - blackLightened[2]); - assertTrue('Black that\'s lightened has more luminance than black.', - blackLightenedHsl[2] >= blackHsl[2]); - var orangeHsl = goog.color.rgbToHsl(orange[0], - orange[1], - orange[2]); - var orangeLightened = goog.color.lighten(orange, .91); - var orangeLightenedHsl = goog.color.rgbToHsl(orangeLightened[0], - orangeLightened[1], - orangeLightened[2]); - assertTrue('Orange that\'s lightened has more luminance than orange.', - orangeLightenedHsl[2] >= orangeHsl[2]); - - // Call lighten() with factors outside the expected range. - var navyTurnedWhite = goog.color.lighten(navy, 1.01); - assertTrue('Lightening navy by 1.01 returns white.', - rgbColorsAreEqual(white, navyTurnedWhite)); - var brownNotLightened = goog.color.lighten(brown, -0.0000001); - assertTrue('Lightening brown by -0.0000001 returns brown.', - rgbColorsAreEqual(brown, brownNotLightened)); -} - - -/** - * This method runs unit tests against goog.color.hslDistance(). - */ -function testHslDistance() { - // Define some HSL colors - var aliceBlueHsl = goog.color.rgbToHsl(240, 248, 255); - var blackHsl = goog.color.rgbToHsl(0, 0, 0); - var ghostWhiteHsl = goog.color.rgbToHsl(248, 248, 255); - var navyHsl = goog.color.rgbToHsl(0, 0, 128); - var redHsl = goog.color.rgbToHsl(255, 0, 0); - var whiteHsl = goog.color.rgbToHsl(255, 255, 255); - - // The distance between the same colors should be 0. - assertTrue('There is no HSL distance between white and white.', - goog.color.hslDistance(whiteHsl, whiteHsl) == 0); - assertTrue('There is no HSL distance between red and red.', - goog.color.hslDistance(redHsl, redHsl) == 0); - - // The distance between various colors should be within certain thresholds. - var hslDistance = goog.color.hslDistance(whiteHsl, ghostWhiteHsl); - assertTrue('The HSL distance between white and ghost white is > 0.', - hslDistance > 0); - assertTrue('The HSL distance between white and ghost white is <= 0.02.', - hslDistance <= 0.02); - hslDistance = goog.color.hslDistance(whiteHsl, redHsl); - assertTrue('The HSL distance betwen white and red is > 0.02.', - hslDistance > 0.02); - hslDistance = goog.color.hslDistance(navyHsl, aliceBlueHsl); - assertTrue('The HSL distance between navy and alice blue is > 0.02.', - hslDistance > 0.02); - hslDistance = goog.color.hslDistance(blackHsl, whiteHsl); - assertTrue('The HSL distance between white and black is 1.', - hslDistance == 1); -} - - -/** - * This method runs unit tests against goog.color.yiqBrightness_(). - */ -function testYiqBrightness() { - var white = [255, 255, 255]; - var black = [0, 0, 0]; - var coral = [255, 127, 80]; - var lightgreen = [144, 238, 144]; - - var whiteBrightness = goog.color.yiqBrightness_(white); - var blackBrightness = goog.color.yiqBrightness_(black); - var coralBrightness = goog.color.yiqBrightness_(coral); - var lightgreenBrightness = goog.color.yiqBrightness_(lightgreen); - - // brightness should be a number - assertTrue('White brightness is a number.', - typeof whiteBrightness == 'number'); - assertTrue('Coral brightness is a number.', - typeof coralBrightness == 'number'); - - // brightness for known colors should match known values - assertEquals('White brightness is 255', whiteBrightness, 255); - assertEquals('Black brightness is 0', blackBrightness, 0); - assertEquals('Coral brightness is 160', coralBrightness, 160); - assertEquals('Lightgreen brightness is 199', lightgreenBrightness, 199); -} - - -/** - * This method runs unit tests against goog.color.yiqBrightnessDiff_(). - */ -function testYiqBrightnessDiff() { - var colors = { - 'deeppink': [255, 20, 147], - 'indigo': [75, 0, 130], - 'saddlebrown': [139, 69, 19] - }; - - var diffs = new Object(); - for (name1 in colors) { - for (name2 in colors) { - diffs[name1 + '-' + name2] = - goog.color.yiqBrightnessDiff_(colors[name1], colors[name2]); - } - } - - for (pair in diffs) { - // each brightness diff should be a number - assertTrue(pair + ' diff is a number.', typeof diffs[pair] == 'number'); - // each brightness diff should be greater than or equal to 0 - assertTrue(pair + ' diff is greater than or equal to 0.', diffs[pair] >= 0); - } - - // brightness diff for same-color pairs should be 0 - assertEquals('deeppink-deeppink is 0.', diffs['deeppink-deeppink'], 0); - assertEquals('indigo-indigo is 0.', diffs['indigo-indigo'], 0); - - // brightness diff for known pairs should match known values - assertEquals('deeppink-indigo is 68.', diffs['deeppink-indigo'], 68); - assertEquals('saddlebrown-deeppink is 21.', - diffs['saddlebrown-deeppink'], 21); - - // reversed pairs should have equal values - assertEquals('indigo-saddlebrown is 47.', diffs['indigo-saddlebrown'], 47); - assertEquals('saddlebrown-indigo is also 47.', - diffs['saddlebrown-indigo'], 47); -} - - -/** - * This method runs unit tests against goog.color.colorDiff_(). - */ -function testColorDiff() { - var colors = { - 'mediumblue': [0, 0, 205], - 'oldlace': [253, 245, 230], - 'orchid': [218, 112, 214] - }; - - var diffs = new Object(); - for (name1 in colors) { - for (name2 in colors) { - diffs[name1 + '-' + name2] = - goog.color.colorDiff_(colors[name1], colors[name2]); - } - } - - for (pair in diffs) { - // each color diff should be a number - assertTrue(pair + ' diff is a number.', typeof diffs[pair] == 'number'); - // each color diff should be greater than or equal to 0 - assertTrue(pair + ' diff is greater than or equal to 0.', diffs[pair] >= 0); - } - - // color diff for same-color pairs should be 0 - assertEquals('mediumblue-mediumblue is 0.', - diffs['mediumblue-mediumblue'], 0); - assertEquals('oldlace-oldlace is 0.', diffs['oldlace-oldlace'], 0); - - // color diff for known pairs should match known values - assertEquals('mediumblue-oldlace is 523.', diffs['mediumblue-oldlace'], 523); - assertEquals('oldlace-orchid is 184.', diffs['oldlace-orchid'], 184); - - // reversed pairs should have equal values - assertEquals('orchid-mediumblue is 339.', diffs['orchid-mediumblue'], 339); - assertEquals('mediumblue-orchid is also 339.', - diffs['mediumblue-orchid'], 339); -} - - -/** - * This method runs unit tests against goog.color.highContrast(). - */ -function testHighContrast() { - white = [255, 255, 255]; - black = [0, 0, 0]; - lemonchiffron = [255, 250, 205]; - sienna = [160, 82, 45]; - - var suggestion = goog.color.highContrast( - black, [white, black, sienna, lemonchiffron]); - - // should return an array of three numbers - assertTrue('Return value is an array.', typeof suggestion == 'object'); - assertTrue('Return value is 3 long.', suggestion.length == 3); - - // known color combos should return a known (i.e. human-verified) suggestion - assertArrayEquals('White is best on sienna.', - goog.color.highContrast( - sienna, [white, black, sienna, lemonchiffron]), white); - assertArrayEquals('Black is best on lemonchiffron.', - goog.color.highContrast( - white, [white, black, sienna, lemonchiffron]), black); -} - - -/** - * Helper function for color conversion functions between two colorspaces. - * @param {Function} funcOne Function that converts from 1st colorspace to 2nd - * @param {Function} funcTwo Function that converts from 2nd colorspace to 2nd - * @param {Array} color The color array passed to funcOne - * @param {number} DELTA Margin of error for each element in color - */ -function colorConversionTestHelper(funcOne, funcTwo, color, DELTA) { - - var temp = funcOne(color); - - if (!goog.color.isValidHexColor_(temp)) { - assertTrue('First conversion had a NaN: ' + temp, !isNaN(temp[0])); - assertTrue('First conversion had a NaN: ' + temp, !isNaN(temp[1])); - assertTrue('First conversion had a NaN: ' + temp, !isNaN(temp[2])); - } - - var back = funcTwo(temp); - - if (!goog.color.isValidHexColor_(temp)) { - assertTrue('Second conversion had a NaN: ' + back, !isNaN(back[0])); - assertTrue('Second conversion had a NaN: ' + back, !isNaN(back[1])); - assertTrue('Second conversion had a NaN: ' + back, !isNaN(back[2])); - } - - assertColorFuzzyEquals('Color was off', color, back, DELTA); -} - - -/** - * Checks equivalence between two colors' respective values. Accepts +- delta - * for each pair of values - * @param {string} Str - * @param {Array} expected - * @param {Array} actual - * @param {number} delta Margin of error for each element in color array - */ -function assertColorFuzzyEquals(str, expected, actual, delta) { - assertTrue(str + ' Expected: ' + expected + ' and got: ' + actual + - ' w/ delta: ' + delta, - (Math.abs(expected[0] - actual[0]) <= delta) && - (Math.abs(expected[1] - actual[1]) <= delta) && - (Math.abs(expected[2] - actual[2]) <= delta)); -} diff --git a/src/database/third_party/closure-library/closure/goog/color/names.js b/src/database/third_party/closure-library/closure/goog/color/names.js deleted file mode 100644 index c4b3ac8d461..00000000000 --- a/src/database/third_party/closure-library/closure/goog/color/names.js +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Names of standard colors with their associated hex values. - */ - -goog.provide('goog.color.names'); - - -/** - * A map that contains a lot of colors that are recognised by various browsers. - * This list is way larger than the minimal one dictated by W3C. - * The keys of this map are the lowercase "readable" names of the colors, while - * the values are the "hex" values. - */ -goog.color.names = { - 'aliceblue': '#f0f8ff', - 'antiquewhite': '#faebd7', - 'aqua': '#00ffff', - 'aquamarine': '#7fffd4', - 'azure': '#f0ffff', - 'beige': '#f5f5dc', - 'bisque': '#ffe4c4', - 'black': '#000000', - 'blanchedalmond': '#ffebcd', - 'blue': '#0000ff', - 'blueviolet': '#8a2be2', - 'brown': '#a52a2a', - 'burlywood': '#deb887', - 'cadetblue': '#5f9ea0', - 'chartreuse': '#7fff00', - 'chocolate': '#d2691e', - 'coral': '#ff7f50', - 'cornflowerblue': '#6495ed', - 'cornsilk': '#fff8dc', - 'crimson': '#dc143c', - 'cyan': '#00ffff', - 'darkblue': '#00008b', - 'darkcyan': '#008b8b', - 'darkgoldenrod': '#b8860b', - 'darkgray': '#a9a9a9', - 'darkgreen': '#006400', - 'darkgrey': '#a9a9a9', - 'darkkhaki': '#bdb76b', - 'darkmagenta': '#8b008b', - 'darkolivegreen': '#556b2f', - 'darkorange': '#ff8c00', - 'darkorchid': '#9932cc', - 'darkred': '#8b0000', - 'darksalmon': '#e9967a', - 'darkseagreen': '#8fbc8f', - 'darkslateblue': '#483d8b', - 'darkslategray': '#2f4f4f', - 'darkslategrey': '#2f4f4f', - 'darkturquoise': '#00ced1', - 'darkviolet': '#9400d3', - 'deeppink': '#ff1493', - 'deepskyblue': '#00bfff', - 'dimgray': '#696969', - 'dimgrey': '#696969', - 'dodgerblue': '#1e90ff', - 'firebrick': '#b22222', - 'floralwhite': '#fffaf0', - 'forestgreen': '#228b22', - 'fuchsia': '#ff00ff', - 'gainsboro': '#dcdcdc', - 'ghostwhite': '#f8f8ff', - 'gold': '#ffd700', - 'goldenrod': '#daa520', - 'gray': '#808080', - 'green': '#008000', - 'greenyellow': '#adff2f', - 'grey': '#808080', - 'honeydew': '#f0fff0', - 'hotpink': '#ff69b4', - 'indianred': '#cd5c5c', - 'indigo': '#4b0082', - 'ivory': '#fffff0', - 'khaki': '#f0e68c', - 'lavender': '#e6e6fa', - 'lavenderblush': '#fff0f5', - 'lawngreen': '#7cfc00', - 'lemonchiffon': '#fffacd', - 'lightblue': '#add8e6', - 'lightcoral': '#f08080', - 'lightcyan': '#e0ffff', - 'lightgoldenrodyellow': '#fafad2', - 'lightgray': '#d3d3d3', - 'lightgreen': '#90ee90', - 'lightgrey': '#d3d3d3', - 'lightpink': '#ffb6c1', - 'lightsalmon': '#ffa07a', - 'lightseagreen': '#20b2aa', - 'lightskyblue': '#87cefa', - 'lightslategray': '#778899', - 'lightslategrey': '#778899', - 'lightsteelblue': '#b0c4de', - 'lightyellow': '#ffffe0', - 'lime': '#00ff00', - 'limegreen': '#32cd32', - 'linen': '#faf0e6', - 'magenta': '#ff00ff', - 'maroon': '#800000', - 'mediumaquamarine': '#66cdaa', - 'mediumblue': '#0000cd', - 'mediumorchid': '#ba55d3', - 'mediumpurple': '#9370db', - 'mediumseagreen': '#3cb371', - 'mediumslateblue': '#7b68ee', - 'mediumspringgreen': '#00fa9a', - 'mediumturquoise': '#48d1cc', - 'mediumvioletred': '#c71585', - 'midnightblue': '#191970', - 'mintcream': '#f5fffa', - 'mistyrose': '#ffe4e1', - 'moccasin': '#ffe4b5', - 'navajowhite': '#ffdead', - 'navy': '#000080', - 'oldlace': '#fdf5e6', - 'olive': '#808000', - 'olivedrab': '#6b8e23', - 'orange': '#ffa500', - 'orangered': '#ff4500', - 'orchid': '#da70d6', - 'palegoldenrod': '#eee8aa', - 'palegreen': '#98fb98', - 'paleturquoise': '#afeeee', - 'palevioletred': '#db7093', - 'papayawhip': '#ffefd5', - 'peachpuff': '#ffdab9', - 'peru': '#cd853f', - 'pink': '#ffc0cb', - 'plum': '#dda0dd', - 'powderblue': '#b0e0e6', - 'purple': '#800080', - 'red': '#ff0000', - 'rosybrown': '#bc8f8f', - 'royalblue': '#4169e1', - 'saddlebrown': '#8b4513', - 'salmon': '#fa8072', - 'sandybrown': '#f4a460', - 'seagreen': '#2e8b57', - 'seashell': '#fff5ee', - 'sienna': '#a0522d', - 'silver': '#c0c0c0', - 'skyblue': '#87ceeb', - 'slateblue': '#6a5acd', - 'slategray': '#708090', - 'slategrey': '#708090', - 'snow': '#fffafa', - 'springgreen': '#00ff7f', - 'steelblue': '#4682b4', - 'tan': '#d2b48c', - 'teal': '#008080', - 'thistle': '#d8bfd8', - 'tomato': '#ff6347', - 'turquoise': '#40e0d0', - 'violet': '#ee82ee', - 'wheat': '#f5deb3', - 'white': '#ffffff', - 'whitesmoke': '#f5f5f5', - 'yellow': '#ffff00', - 'yellowgreen': '#9acd32' -}; diff --git a/src/database/third_party/closure-library/closure/goog/crypt/aes.js b/src/database/third_party/closure-library/closure/goog/crypt/aes.js deleted file mode 100644 index 050e644c31f..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/aes.js +++ /dev/null @@ -1,1030 +0,0 @@ -// Copyright 2012 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Implementation of AES in JavaScript. - * @see http://en.wikipedia.org/wiki/Advanced_Encryption_Standard - * - * @author nnaze@google.com (Nathan Naze) - port to Closure - */ - -goog.provide('goog.crypt.Aes'); - -goog.require('goog.asserts'); -goog.require('goog.crypt.BlockCipher'); - - - -/** - * Implementation of AES in JavaScript. - * See http://en.wikipedia.org/wiki/Advanced_Encryption_Standard - * - * WARNING: This is ECB mode only. If you are encrypting something - * longer than 16 bytes, or encrypting more than one value with the same key - * (so basically, always) you need to use this with a block cipher mode of - * operation. See goog.crypt.Cbc. - * - * See http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation for more - * information. - * - * @constructor - * @implements {goog.crypt.BlockCipher} - * @param {!Array} key The key as an array of integers in {0, 255}. - * The key must have lengths of 16, 24, or 32 integers for 128-, - * 192-, or 256-bit encryption, respectively. - * @final - * @struct - */ -goog.crypt.Aes = function(key) { - goog.crypt.Aes.assertKeyArray_(key); - - /** - * The AES key. - * @type {!Array} - * @private - */ - this.key_ = key; - - /** - * Key length, in words. - * @type {number} - * @private - */ - this.keyLength_ = this.key_.length / 4; - - /** - * Number of rounds. Based on key length per AES spec. - * @type {number} - * @private - */ - this.numberOfRounds_ = this.keyLength_ + 6; - - /** - * 4x4 byte array containing the current state. - * @type {!Array>} - * @private - */ - this.state_ = [[], [], [], []]; - - /** - * Scratch temporary array for calculation. - * @type {!Array>} - * @private - */ - this.temp_ = [[], [], [], []]; - - this.keyExpansion_(); -}; - - -/** - * @define {boolean} Whether to call test method stubs. This can be enabled - * for unit testing. - */ -goog.define('goog.crypt.Aes.ENABLE_TEST_MODE', false); - - -/** - * @override - */ -goog.crypt.Aes.prototype.encrypt = function(input) { - - if (goog.crypt.Aes.ENABLE_TEST_MODE) { - this.testKeySchedule_(0, this.keySchedule_, 0); - } - - this.copyInput_(input); - this.addRoundKey_(0); - - for (var round = 1; round < this.numberOfRounds_; ++round) { - if (goog.crypt.Aes.ENABLE_TEST_MODE) { - this.testKeySchedule_(round, this.keySchedule_, round); - this.testStartRound_(round, this.state_); - } - - this.subBytes_(goog.crypt.Aes.SBOX_); - if (goog.crypt.Aes.ENABLE_TEST_MODE) { - this.testAfterSubBytes_(round, this.state_); - } - - this.shiftRows_(); - if (goog.crypt.Aes.ENABLE_TEST_MODE) { - this.testAfterShiftRows_(round, this.state_); - } - - this.mixColumns_(); - if (goog.crypt.Aes.ENABLE_TEST_MODE) { - this.testAfterMixColumns_(round, this.state_); - } - - this.addRoundKey_(round); - } - - this.subBytes_(goog.crypt.Aes.SBOX_); - if (goog.crypt.Aes.ENABLE_TEST_MODE) { - this.testAfterSubBytes_(round, this.state_); - } - - this.shiftRows_(); - if (goog.crypt.Aes.ENABLE_TEST_MODE) { - this.testAfterShiftRows_(round, this.state_); - } - - this.addRoundKey_(this.numberOfRounds_); - - return this.generateOutput_(); -}; - - -/** - * @override - */ -goog.crypt.Aes.prototype.decrypt = function(input) { - - if (goog.crypt.Aes.ENABLE_TEST_MODE) { - this.testKeySchedule_(0, this.keySchedule_, this.numberOfRounds_); - } - - this.copyInput_(input); - this.addRoundKey_(this.numberOfRounds_); - - for (var round = 1; round < this.numberOfRounds_; ++round) { - if (goog.crypt.Aes.ENABLE_TEST_MODE) { - this.testKeySchedule_(round, this.keySchedule_, - this.numberOfRounds_ - round); - this.testStartRound_(round, this.state_); - } - - this.invShiftRows_(); - if (goog.crypt.Aes.ENABLE_TEST_MODE) { - this.testAfterShiftRows_(round, this.state_); - } - - this.subBytes_(goog.crypt.Aes.INV_SBOX_); - if (goog.crypt.Aes.ENABLE_TEST_MODE) { - this.testAfterSubBytes_(round, this.state_); - } - - this.addRoundKey_(this.numberOfRounds_ - round); - if (goog.crypt.Aes.ENABLE_TEST_MODE) { - this.testAfterAddRoundKey_(round, this.state_); - } - - this.invMixColumns_(); - } - - this.invShiftRows_(); - if (goog.crypt.Aes.ENABLE_TEST_MODE) { - this.testAfterShiftRows_(round, this.state_); - } - - this.subBytes_(goog.crypt.Aes.INV_SBOX_); - if (goog.crypt.Aes.ENABLE_TEST_MODE) { - this.testAfterSubBytes_(this.numberOfRounds_, this.state_); - } - - if (goog.crypt.Aes.ENABLE_TEST_MODE) { - this.testKeySchedule_(this.numberOfRounds_, this.keySchedule_, 0); - } - - this.addRoundKey_(0); - - return this.generateOutput_(); -}; - - -/** - * Block size, in words. Fixed at 4 per AES spec. - * @type {number} - * @private - */ -goog.crypt.Aes.BLOCK_SIZE_ = 4; - - -/** - * Asserts that the key's array of integers is in the correct format. - * @param {!Array} arr AES key as array of integers. - * @private - */ -goog.crypt.Aes.assertKeyArray_ = function(arr) { - if (goog.asserts.ENABLE_ASSERTS) { - goog.asserts.assert(arr.length == 16 || arr.length == 24 || - arr.length == 32, - 'Key must have length 16, 24, or 32.'); - for (var i = 0; i < arr.length; i++) { - goog.asserts.assertNumber(arr[i]); - goog.asserts.assert(arr[i] >= 0 && arr[i] <= 255); - } - } -}; - - -/** - * Tests can populate this with a callback, and that callback will get called - * at the start of each round *in both functions encrypt() and decrypt()*. - * @param {number} roundNum Round number. - * @param {!Array>} Current state. - * @private - */ -goog.crypt.Aes.prototype.testStartRound_ = goog.nullFunction; - - -/** - * Tests can populate this with a callback, and that callback will get called - * each round right after the SubBytes step gets executed *in both functions - * encrypt() and decrypt()*. - * @param {number} roundNum Round number. - * @param {!Array>} Current state. - * @private - */ -goog.crypt.Aes.prototype.testAfterSubBytes_ = goog.nullFunction; - - -/** - * Tests can populate this with a callback, and that callback will get called - * each round right after the ShiftRows step gets executed *in both functions - * encrypt() and decrypt()*. - * @param {number} roundNum Round number. - * @param {!Array>} Current state. - * @private - */ -goog.crypt.Aes.prototype.testAfterShiftRows_ = goog.nullFunction; - - -/** - * Tests can populate this with a callback, and that callback will get called - * each round right after the MixColumns step gets executed *but only in the - * decrypt() function*. - * @param {number} roundNum Round number. - * @param {!Array>} Current state. - * @private - */ -goog.crypt.Aes.prototype.testAfterMixColumns_ = goog.nullFunction; - - -/** - * Tests can populate this with a callback, and that callback will get called - * each round right after the AddRoundKey step gets executed encrypt(). - * @param {number} roundNum Round number. - * @param {!Array>} Current state. - * @private - */ -goog.crypt.Aes.prototype.testAfterAddRoundKey_ = goog.nullFunction; - - -/** - * Tests can populate this with a callback, and that callback will get called - * before each round on the round key. *Gets called in both the encrypt() and - * decrypt() functions.* - * @param {number} roundNum Round number. - * @param {!Array} Computed key schedule. - * @param {number} index The index into the key schedule to test. This is not - * necessarily roundNum because the key schedule is used in reverse - * in the case of decryption. - * @private - */ -goog.crypt.Aes.prototype.testKeySchedule_ = goog.nullFunction; - - -/** - * Helper to copy input into the AES state matrix. - * @param {!Array} input Byte array to copy into the state matrix. - * @private - */ -goog.crypt.Aes.prototype.copyInput_ = function(input) { - var v, p; - - goog.asserts.assert(input.length == goog.crypt.Aes.BLOCK_SIZE_ * 4, - 'Expecting input of 4 times block size.'); - - for (var r = 0; r < goog.crypt.Aes.BLOCK_SIZE_; r++) { - for (var c = 0; c < 4; c++) { - p = c * 4 + r; - v = input[p]; - - goog.asserts.assert( - v <= 255 && v >= 0, - 'Invalid input. Value %s at position %s is not a byte.', v, p); - - this.state_[r][c] = v; - } - } -}; - - -/** - * Helper to copy the state matrix into an output array. - * @return {!Array} Output byte array. - * @private - */ -goog.crypt.Aes.prototype.generateOutput_ = function() { - var output = []; - for (var r = 0; r < goog.crypt.Aes.BLOCK_SIZE_; r++) { - for (var c = 0; c < 4; c++) { - output[c * 4 + r] = this.state_[r][c]; - } - } - return output; -}; - - -/** - * AES's AddRoundKey procedure. Add the current round key to the state. - * @param {number} round The current round. - * @private - */ -goog.crypt.Aes.prototype.addRoundKey_ = function(round) { - for (var r = 0; r < 4; r++) { - for (var c = 0; c < 4; c++) { - this.state_[r][c] ^= this.keySchedule_[round * 4 + c][r]; - } - } -}; - - -/** - * AES's SubBytes procedure. Substitute bytes from the precomputed SBox lookup - * into the state. - * @param {!Array} box The SBox or invSBox. - * @private - */ -goog.crypt.Aes.prototype.subBytes_ = function(box) { - for (var r = 0; r < 4; r++) { - for (var c = 0; c < 4; c++) { - this.state_[r][c] = box[this.state_[r][c]]; - } - } -}; - - -/** - * AES's ShiftRows procedure. Shift the values in each row to the right. Each - * row is shifted one more slot than the one above it. - * @private - */ -goog.crypt.Aes.prototype.shiftRows_ = function() { - for (var r = 1; r < 4; r++) { - for (var c = 0; c < 4; c++) { - this.temp_[r][c] = this.state_[r][c]; - } - } - - for (var r = 1; r < 4; r++) { - for (var c = 0; c < 4; c++) { - this.state_[r][c] = this.temp_[r][(c + r) % - goog.crypt.Aes.BLOCK_SIZE_]; - } - } -}; - - -/** - * AES's InvShiftRows procedure. Shift the values in each row to the right. - * @private - */ -goog.crypt.Aes.prototype.invShiftRows_ = function() { - for (var r = 1; r < 4; r++) { - for (var c = 0; c < 4; c++) { - this.temp_[r][(c + r) % goog.crypt.Aes.BLOCK_SIZE_] = - this.state_[r][c]; - } - } - - for (var r = 1; r < 4; r++) { - for (var c = 0; c < 4; c++) { - this.state_[r][c] = this.temp_[r][c]; - } - } -}; - - -/** - * AES's MixColumns procedure. Mix the columns of the state using magic. - * @private - */ -goog.crypt.Aes.prototype.mixColumns_ = function() { - var s = this.state_; - var t = this.temp_[0]; - - for (var c = 0; c < 4; c++) { - t[0] = s[0][c]; - t[1] = s[1][c]; - t[2] = s[2][c]; - t[3] = s[3][c]; - - s[0][c] = (goog.crypt.Aes.MULT_2_[t[0]] ^ - goog.crypt.Aes.MULT_3_[t[1]] ^ t[2] ^ t[3]); - s[1][c] = (t[0] ^ goog.crypt.Aes.MULT_2_[t[1]] ^ - goog.crypt.Aes.MULT_3_[t[2]] ^ t[3]); - s[2][c] = (t[0] ^ t[1] ^ goog.crypt.Aes.MULT_2_[t[2]] ^ - goog.crypt.Aes.MULT_3_[t[3]]); - s[3][c] = (goog.crypt.Aes.MULT_3_[t[0]] ^ t[1] ^ t[2] ^ - goog.crypt.Aes.MULT_2_[t[3]]); - } -}; - - -/** - * AES's InvMixColumns procedure. - * @private - */ -goog.crypt.Aes.prototype.invMixColumns_ = function() { - var s = this.state_; - var t = this.temp_[0]; - - for (var c = 0; c < 4; c++) { - t[0] = s[0][c]; - t[1] = s[1][c]; - t[2] = s[2][c]; - t[3] = s[3][c]; - - s[0][c] = ( - goog.crypt.Aes.MULT_E_[t[0]] ^ goog.crypt.Aes.MULT_B_[t[1]] ^ - goog.crypt.Aes.MULT_D_[t[2]] ^ goog.crypt.Aes.MULT_9_[t[3]]); - - s[1][c] = ( - goog.crypt.Aes.MULT_9_[t[0]] ^ goog.crypt.Aes.MULT_E_[t[1]] ^ - goog.crypt.Aes.MULT_B_[t[2]] ^ goog.crypt.Aes.MULT_D_[t[3]]); - - s[2][c] = ( - goog.crypt.Aes.MULT_D_[t[0]] ^ goog.crypt.Aes.MULT_9_[t[1]] ^ - goog.crypt.Aes.MULT_E_[t[2]] ^ goog.crypt.Aes.MULT_B_[t[3]]); - - s[3][c] = ( - goog.crypt.Aes.MULT_B_[t[0]] ^ goog.crypt.Aes.MULT_D_[t[1]] ^ - goog.crypt.Aes.MULT_9_[t[2]] ^ goog.crypt.Aes.MULT_E_[t[3]]); - } -}; - - -/** - * AES's KeyExpansion procedure. Create the key schedule from the initial key. - * @private - */ -goog.crypt.Aes.prototype.keyExpansion_ = function() { - this.keySchedule_ = new Array(goog.crypt.Aes.BLOCK_SIZE_ * ( - this.numberOfRounds_ + 1)); - - for (var rowNum = 0; rowNum < this.keyLength_; rowNum++) { - this.keySchedule_[rowNum] = [ - this.key_[4 * rowNum], - this.key_[4 * rowNum + 1], - this.key_[4 * rowNum + 2], - this.key_[4 * rowNum + 3] - ]; - } - - var temp = new Array(4); - - for (var rowNum = this.keyLength_; - rowNum < (goog.crypt.Aes.BLOCK_SIZE_ * (this.numberOfRounds_ + 1)); - rowNum++) { - temp[0] = this.keySchedule_[rowNum - 1][0]; - temp[1] = this.keySchedule_[rowNum - 1][1]; - temp[2] = this.keySchedule_[rowNum - 1][2]; - temp[3] = this.keySchedule_[rowNum - 1][3]; - - if (rowNum % this.keyLength_ == 0) { - this.rotWord_(temp); - this.subWord_(temp); - - temp[0] ^= goog.crypt.Aes.RCON_[rowNum / this.keyLength_][0]; - temp[1] ^= goog.crypt.Aes.RCON_[rowNum / this.keyLength_][1]; - temp[2] ^= goog.crypt.Aes.RCON_[rowNum / this.keyLength_][2]; - temp[3] ^= goog.crypt.Aes.RCON_[rowNum / this.keyLength_][3]; - } else if (this.keyLength_ > 6 && rowNum % this.keyLength_ == 4) { - this.subWord_(temp); - } - - this.keySchedule_[rowNum] = new Array(4); - this.keySchedule_[rowNum][0] = - this.keySchedule_[rowNum - this.keyLength_][0] ^ temp[0]; - this.keySchedule_[rowNum][1] = - this.keySchedule_[rowNum - this.keyLength_][1] ^ temp[1]; - this.keySchedule_[rowNum][2] = - this.keySchedule_[rowNum - this.keyLength_][2] ^ temp[2]; - this.keySchedule_[rowNum][3] = - this.keySchedule_[rowNum - this.keyLength_][3] ^ temp[3]; - } -}; - - -/** - * AES's SubWord procedure. - * @param {!Array} w Bytes to find the SBox substitution for. - * @return {!Array} The substituted bytes. - * @private - */ -goog.crypt.Aes.prototype.subWord_ = function(w) { - w[0] = goog.crypt.Aes.SBOX_[w[0]]; - w[1] = goog.crypt.Aes.SBOX_[w[1]]; - w[2] = goog.crypt.Aes.SBOX_[w[2]]; - w[3] = goog.crypt.Aes.SBOX_[w[3]]; - - return w; -}; - - -/** - * AES's RotWord procedure. - * @param {!Array} w Array of bytes to rotate. - * @return {!Array} The rotated bytes. - * @private - */ -goog.crypt.Aes.prototype.rotWord_ = function(w) { - var temp = w[0]; - - w[0] = w[1]; - w[1] = w[2]; - w[2] = w[3]; - w[3] = temp; - - return w; -}; - - -/** - * The key schedule. - * @type {!Array} - * @private - */ -goog.crypt.Aes.prototype.keySchedule_; - - -/** - * Precomputed SBox lookup. - * @type {!Array} - * @private - */ -goog.crypt.Aes.SBOX_ = [ - 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, - 0xd7, 0xab, 0x76, - - 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, - 0xa4, 0x72, 0xc0, - - 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, - 0xd8, 0x31, 0x15, - - 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, - 0x27, 0xb2, 0x75, - - 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, - 0xe3, 0x2f, 0x84, - - 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, - 0x4c, 0x58, 0xcf, - - 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, - 0x3c, 0x9f, 0xa8, - - 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, - 0xff, 0xf3, 0xd2, - - 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, - 0x5d, 0x19, 0x73, - - 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, - 0x5e, 0x0b, 0xdb, - - 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, - 0x95, 0xe4, 0x79, - - 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, - 0x7a, 0xae, 0x08, - - 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, - 0xbd, 0x8b, 0x8a, - - 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, - 0xc1, 0x1d, 0x9e, - - 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, - 0x55, 0x28, 0xdf, - - 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, - 0x54, 0xbb, 0x16 -]; - - -/** - * Precomputed InvSBox lookup. - * @type {!Array} - * @private - */ -goog.crypt.Aes.INV_SBOX_ = [ - 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, - 0xf3, 0xd7, 0xfb, - - 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, - 0xde, 0xe9, 0xcb, - - 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, - 0xfa, 0xc3, 0x4e, - - 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, - 0x8b, 0xd1, 0x25, - - 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, - 0x65, 0xb6, 0x92, - - 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, - 0x8d, 0x9d, 0x84, - - 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, - 0xb3, 0x45, 0x06, - - 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, - 0x13, 0x8a, 0x6b, - - 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, - 0xb4, 0xe6, 0x73, - - 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, - 0x75, 0xdf, 0x6e, - - 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, - 0x18, 0xbe, 0x1b, - - 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, - 0xcd, 0x5a, 0xf4, - - 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, - 0x80, 0xec, 0x5f, - - 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, - 0xc9, 0x9c, 0xef, - - 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, - 0x53, 0x99, 0x61, - - 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, - 0x21, 0x0c, 0x7d -]; - - -/** - * Precomputed RCon lookup. - * @type {!Array} - * @private - */ -goog.crypt.Aes.RCON_ = [ - [0x00, 0x00, 0x00, 0x00], - [0x01, 0x00, 0x00, 0x00], - [0x02, 0x00, 0x00, 0x00], - [0x04, 0x00, 0x00, 0x00], - [0x08, 0x00, 0x00, 0x00], - [0x10, 0x00, 0x00, 0x00], - [0x20, 0x00, 0x00, 0x00], - [0x40, 0x00, 0x00, 0x00], - [0x80, 0x00, 0x00, 0x00], - [0x1b, 0x00, 0x00, 0x00], - [0x36, 0x00, 0x00, 0x00] -]; - - -/** - * Precomputed lookup of multiplication by 2 in GF(2^8) - * @type {!Array} - * @private - */ -goog.crypt.Aes.MULT_2_ = [ - 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10, 0x12, 0x14, 0x16, - 0x18, 0x1A, 0x1C, 0x1E, - - 0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x2C, 0x2E, 0x30, 0x32, 0x34, 0x36, - 0x38, 0x3A, 0x3C, 0x3E, - - 0x40, 0x42, 0x44, 0x46, 0x48, 0x4A, 0x4C, 0x4E, 0x50, 0x52, 0x54, 0x56, - 0x58, 0x5A, 0x5C, 0x5E, - - 0x60, 0x62, 0x64, 0x66, 0x68, 0x6A, 0x6C, 0x6E, 0x70, 0x72, 0x74, 0x76, - 0x78, 0x7A, 0x7C, 0x7E, - - 0x80, 0x82, 0x84, 0x86, 0x88, 0x8A, 0x8C, 0x8E, 0x90, 0x92, 0x94, 0x96, - 0x98, 0x9A, 0x9C, 0x9E, - - 0xA0, 0xA2, 0xA4, 0xA6, 0xA8, 0xAA, 0xAC, 0xAE, 0xB0, 0xB2, 0xB4, 0xB6, - 0xB8, 0xBA, 0xBC, 0xBE, - - 0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE, 0xD0, 0xD2, 0xD4, 0xD6, - 0xD8, 0xDA, 0xDC, 0xDE, - - 0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE, 0xF0, 0xF2, 0xF4, 0xF6, - 0xF8, 0xFA, 0xFC, 0xFE, - - 0x1B, 0x19, 0x1F, 0x1D, 0x13, 0x11, 0x17, 0x15, 0x0B, 0x09, 0x0F, 0x0D, - 0x03, 0x01, 0x07, 0x05, - - 0x3B, 0x39, 0x3F, 0x3D, 0x33, 0x31, 0x37, 0x35, 0x2B, 0x29, 0x2F, 0x2D, - 0x23, 0x21, 0x27, 0x25, - - 0x5B, 0x59, 0x5F, 0x5D, 0x53, 0x51, 0x57, 0x55, 0x4B, 0x49, 0x4F, 0x4D, - 0x43, 0x41, 0x47, 0x45, - - 0x7B, 0x79, 0x7F, 0x7D, 0x73, 0x71, 0x77, 0x75, 0x6B, 0x69, 0x6F, 0x6D, - 0x63, 0x61, 0x67, 0x65, - - 0x9B, 0x99, 0x9F, 0x9D, 0x93, 0x91, 0x97, 0x95, 0x8B, 0x89, 0x8F, 0x8D, - 0x83, 0x81, 0x87, 0x85, - - 0xBB, 0xB9, 0xBF, 0xBD, 0xB3, 0xB1, 0xB7, 0xB5, 0xAB, 0xA9, 0xAF, 0xAD, - 0xA3, 0xA1, 0xA7, 0xA5, - - 0xDB, 0xD9, 0xDF, 0xDD, 0xD3, 0xD1, 0xD7, 0xD5, 0xCB, 0xC9, 0xCF, 0xCD, - 0xC3, 0xC1, 0xC7, 0xC5, - - 0xFB, 0xF9, 0xFF, 0xFD, 0xF3, 0xF1, 0xF7, 0xF5, 0xEB, 0xE9, 0xEF, 0xED, - 0xE3, 0xE1, 0xE7, 0xE5 -]; - - -/** - * Precomputed lookup of multiplication by 3 in GF(2^8) - * @type {!Array} - * @private - */ -goog.crypt.Aes.MULT_3_ = [ - 0x00, 0x03, 0x06, 0x05, 0x0C, 0x0F, 0x0A, 0x09, 0x18, 0x1B, 0x1E, 0x1D, - 0x14, 0x17, 0x12, 0x11, - - 0x30, 0x33, 0x36, 0x35, 0x3C, 0x3F, 0x3A, 0x39, 0x28, 0x2B, 0x2E, 0x2D, - 0x24, 0x27, 0x22, 0x21, - - 0x60, 0x63, 0x66, 0x65, 0x6C, 0x6F, 0x6A, 0x69, 0x78, 0x7B, 0x7E, 0x7D, - 0x74, 0x77, 0x72, 0x71, - - 0x50, 0x53, 0x56, 0x55, 0x5C, 0x5F, 0x5A, 0x59, 0x48, 0x4B, 0x4E, 0x4D, - 0x44, 0x47, 0x42, 0x41, - - 0xC0, 0xC3, 0xC6, 0xC5, 0xCC, 0xCF, 0xCA, 0xC9, 0xD8, 0xDB, 0xDE, 0xDD, - 0xD4, 0xD7, 0xD2, 0xD1, - - 0xF0, 0xF3, 0xF6, 0xF5, 0xFC, 0xFF, 0xFA, 0xF9, 0xE8, 0xEB, 0xEE, 0xED, - 0xE4, 0xE7, 0xE2, 0xE1, - - 0xA0, 0xA3, 0xA6, 0xA5, 0xAC, 0xAF, 0xAA, 0xA9, 0xB8, 0xBB, 0xBE, 0xBD, - 0xB4, 0xB7, 0xB2, 0xB1, - - 0x90, 0x93, 0x96, 0x95, 0x9C, 0x9F, 0x9A, 0x99, 0x88, 0x8B, 0x8E, 0x8D, - 0x84, 0x87, 0x82, 0x81, - - 0x9B, 0x98, 0x9D, 0x9E, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, - 0x8F, 0x8C, 0x89, 0x8A, - - 0xAB, 0xA8, 0xAD, 0xAE, 0xA7, 0xA4, 0xA1, 0xA2, 0xB3, 0xB0, 0xB5, 0xB6, - 0xBF, 0xBC, 0xB9, 0xBA, - - 0xFB, 0xF8, 0xFD, 0xFE, 0xF7, 0xF4, 0xF1, 0xF2, 0xE3, 0xE0, 0xE5, 0xE6, - 0xEF, 0xEC, 0xE9, 0xEA, - - 0xCB, 0xC8, 0xCD, 0xCE, 0xC7, 0xC4, 0xC1, 0xC2, 0xD3, 0xD0, 0xD5, 0xD6, - 0xDF, 0xDC, 0xD9, 0xDA, - - 0x5B, 0x58, 0x5D, 0x5E, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, - 0x4F, 0x4C, 0x49, 0x4A, - - 0x6B, 0x68, 0x6D, 0x6E, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, - 0x7F, 0x7C, 0x79, 0x7A, - - 0x3B, 0x38, 0x3D, 0x3E, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, - 0x2F, 0x2C, 0x29, 0x2A, - - 0x0B, 0x08, 0x0D, 0x0E, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, - 0x1F, 0x1C, 0x19, 0x1A -]; - - -/** - * Precomputed lookup of multiplication by 9 in GF(2^8) - * @type {!Array} - * @private - */ -goog.crypt.Aes.MULT_9_ = [ - 0x00, 0x09, 0x12, 0x1B, 0x24, 0x2D, 0x36, 0x3F, 0x48, 0x41, 0x5A, 0x53, - 0x6C, 0x65, 0x7E, 0x77, - - 0x90, 0x99, 0x82, 0x8B, 0xB4, 0xBD, 0xA6, 0xAF, 0xD8, 0xD1, 0xCA, 0xC3, - 0xFC, 0xF5, 0xEE, 0xE7, - - 0x3B, 0x32, 0x29, 0x20, 0x1F, 0x16, 0x0D, 0x04, 0x73, 0x7A, 0x61, 0x68, - 0x57, 0x5E, 0x45, 0x4C, - - 0xAB, 0xA2, 0xB9, 0xB0, 0x8F, 0x86, 0x9D, 0x94, 0xE3, 0xEA, 0xF1, 0xF8, - 0xC7, 0xCE, 0xD5, 0xDC, - - 0x76, 0x7F, 0x64, 0x6D, 0x52, 0x5B, 0x40, 0x49, 0x3E, 0x37, 0x2C, 0x25, - 0x1A, 0x13, 0x08, 0x01, - - 0xE6, 0xEF, 0xF4, 0xFD, 0xC2, 0xCB, 0xD0, 0xD9, 0xAE, 0xA7, 0xBC, 0xB5, - 0x8A, 0x83, 0x98, 0x91, - - 0x4D, 0x44, 0x5F, 0x56, 0x69, 0x60, 0x7B, 0x72, 0x05, 0x0C, 0x17, 0x1E, - 0x21, 0x28, 0x33, 0x3A, - - 0xDD, 0xD4, 0xCF, 0xC6, 0xF9, 0xF0, 0xEB, 0xE2, 0x95, 0x9C, 0x87, 0x8E, - 0xB1, 0xB8, 0xA3, 0xAA, - - 0xEC, 0xE5, 0xFE, 0xF7, 0xC8, 0xC1, 0xDA, 0xD3, 0xA4, 0xAD, 0xB6, 0xBF, - 0x80, 0x89, 0x92, 0x9B, - - 0x7C, 0x75, 0x6E, 0x67, 0x58, 0x51, 0x4A, 0x43, 0x34, 0x3D, 0x26, 0x2F, - 0x10, 0x19, 0x02, 0x0B, - - 0xD7, 0xDE, 0xC5, 0xCC, 0xF3, 0xFA, 0xE1, 0xE8, 0x9F, 0x96, 0x8D, 0x84, - 0xBB, 0xB2, 0xA9, 0xA0, - - 0x47, 0x4E, 0x55, 0x5C, 0x63, 0x6A, 0x71, 0x78, 0x0F, 0x06, 0x1D, 0x14, - 0x2B, 0x22, 0x39, 0x30, - - 0x9A, 0x93, 0x88, 0x81, 0xBE, 0xB7, 0xAC, 0xA5, 0xD2, 0xDB, 0xC0, 0xC9, - 0xF6, 0xFF, 0xE4, 0xED, - - 0x0A, 0x03, 0x18, 0x11, 0x2E, 0x27, 0x3C, 0x35, 0x42, 0x4B, 0x50, 0x59, - 0x66, 0x6F, 0x74, 0x7D, - - 0xA1, 0xA8, 0xB3, 0xBA, 0x85, 0x8C, 0x97, 0x9E, 0xE9, 0xE0, 0xFB, 0xF2, - 0xCD, 0xC4, 0xDF, 0xD6, - - 0x31, 0x38, 0x23, 0x2A, 0x15, 0x1C, 0x07, 0x0E, 0x79, 0x70, 0x6B, 0x62, - 0x5D, 0x54, 0x4F, 0x46 -]; - - -/** - * Precomputed lookup of multiplication by 11 in GF(2^8) - * @type {!Array} - * @private - */ -goog.crypt.Aes.MULT_B_ = [ - 0x00, 0x0B, 0x16, 0x1D, 0x2C, 0x27, 0x3A, 0x31, 0x58, 0x53, 0x4E, 0x45, - 0x74, 0x7F, 0x62, 0x69, - - 0xB0, 0xBB, 0xA6, 0xAD, 0x9C, 0x97, 0x8A, 0x81, 0xE8, 0xE3, 0xFE, 0xF5, - 0xC4, 0xCF, 0xD2, 0xD9, - - 0x7B, 0x70, 0x6D, 0x66, 0x57, 0x5C, 0x41, 0x4A, 0x23, 0x28, 0x35, 0x3E, - 0x0F, 0x04, 0x19, 0x12, - - 0xCB, 0xC0, 0xDD, 0xD6, 0xE7, 0xEC, 0xF1, 0xFA, 0x93, 0x98, 0x85, 0x8E, - 0xBF, 0xB4, 0xA9, 0xA2, - - 0xF6, 0xFD, 0xE0, 0xEB, 0xDA, 0xD1, 0xCC, 0xC7, 0xAE, 0xA5, 0xB8, 0xB3, - 0x82, 0x89, 0x94, 0x9F, - - 0x46, 0x4D, 0x50, 0x5B, 0x6A, 0x61, 0x7C, 0x77, 0x1E, 0x15, 0x08, 0x03, - 0x32, 0x39, 0x24, 0x2F, - - 0x8D, 0x86, 0x9B, 0x90, 0xA1, 0xAA, 0xB7, 0xBC, 0xD5, 0xDE, 0xC3, 0xC8, - 0xF9, 0xF2, 0xEF, 0xE4, - - 0x3D, 0x36, 0x2B, 0x20, 0x11, 0x1A, 0x07, 0x0C, 0x65, 0x6E, 0x73, 0x78, - 0x49, 0x42, 0x5F, 0x54, - - 0xF7, 0xFC, 0xE1, 0xEA, 0xDB, 0xD0, 0xCD, 0xC6, 0xAF, 0xA4, 0xB9, 0xB2, - 0x83, 0x88, 0x95, 0x9E, - - 0x47, 0x4C, 0x51, 0x5A, 0x6B, 0x60, 0x7D, 0x76, 0x1F, 0x14, 0x09, 0x02, - 0x33, 0x38, 0x25, 0x2E, - - 0x8C, 0x87, 0x9A, 0x91, 0xA0, 0xAB, 0xB6, 0xBD, 0xD4, 0xDF, 0xC2, 0xC9, - 0xF8, 0xF3, 0xEE, 0xE5, - - 0x3C, 0x37, 0x2A, 0x21, 0x10, 0x1B, 0x06, 0x0D, 0x64, 0x6F, 0x72, 0x79, - 0x48, 0x43, 0x5E, 0x55, - - 0x01, 0x0A, 0x17, 0x1C, 0x2D, 0x26, 0x3B, 0x30, 0x59, 0x52, 0x4F, 0x44, - 0x75, 0x7E, 0x63, 0x68, - - 0xB1, 0xBA, 0xA7, 0xAC, 0x9D, 0x96, 0x8B, 0x80, 0xE9, 0xE2, 0xFF, 0xF4, - 0xC5, 0xCE, 0xD3, 0xD8, - - 0x7A, 0x71, 0x6C, 0x67, 0x56, 0x5D, 0x40, 0x4B, 0x22, 0x29, 0x34, 0x3F, - 0x0E, 0x05, 0x18, 0x13, - - 0xCA, 0xC1, 0xDC, 0xD7, 0xE6, 0xED, 0xF0, 0xFB, 0x92, 0x99, 0x84, 0x8F, - 0xBE, 0xB5, 0xA8, 0xA3 -]; - - -/** - * Precomputed lookup of multiplication by 13 in GF(2^8) - * @type {!Array} - * @private - */ -goog.crypt.Aes.MULT_D_ = [ - 0x00, 0x0D, 0x1A, 0x17, 0x34, 0x39, 0x2E, 0x23, 0x68, 0x65, 0x72, 0x7F, - 0x5C, 0x51, 0x46, 0x4B, - - 0xD0, 0xDD, 0xCA, 0xC7, 0xE4, 0xE9, 0xFE, 0xF3, 0xB8, 0xB5, 0xA2, 0xAF, - 0x8C, 0x81, 0x96, 0x9B, - - 0xBB, 0xB6, 0xA1, 0xAC, 0x8F, 0x82, 0x95, 0x98, 0xD3, 0xDE, 0xC9, 0xC4, - 0xE7, 0xEA, 0xFD, 0xF0, - - 0x6B, 0x66, 0x71, 0x7C, 0x5F, 0x52, 0x45, 0x48, 0x03, 0x0E, 0x19, 0x14, - 0x37, 0x3A, 0x2D, 0x20, - - 0x6D, 0x60, 0x77, 0x7A, 0x59, 0x54, 0x43, 0x4E, 0x05, 0x08, 0x1F, 0x12, - 0x31, 0x3C, 0x2B, 0x26, - - 0xBD, 0xB0, 0xA7, 0xAA, 0x89, 0x84, 0x93, 0x9E, 0xD5, 0xD8, 0xCF, 0xC2, - 0xE1, 0xEC, 0xFB, 0xF6, - - 0xD6, 0xDB, 0xCC, 0xC1, 0xE2, 0xEF, 0xF8, 0xF5, 0xBE, 0xB3, 0xA4, 0xA9, - 0x8A, 0x87, 0x90, 0x9D, - - 0x06, 0x0B, 0x1C, 0x11, 0x32, 0x3F, 0x28, 0x25, 0x6E, 0x63, 0x74, 0x79, - 0x5A, 0x57, 0x40, 0x4D, - - 0xDA, 0xD7, 0xC0, 0xCD, 0xEE, 0xE3, 0xF4, 0xF9, 0xB2, 0xBF, 0xA8, 0xA5, - 0x86, 0x8B, 0x9C, 0x91, - - 0x0A, 0x07, 0x10, 0x1D, 0x3E, 0x33, 0x24, 0x29, 0x62, 0x6F, 0x78, 0x75, - 0x56, 0x5B, 0x4C, 0x41, - - 0x61, 0x6C, 0x7B, 0x76, 0x55, 0x58, 0x4F, 0x42, 0x09, 0x04, 0x13, 0x1E, - 0x3D, 0x30, 0x27, 0x2A, - - 0xB1, 0xBC, 0xAB, 0xA6, 0x85, 0x88, 0x9F, 0x92, 0xD9, 0xD4, 0xC3, 0xCE, - 0xED, 0xE0, 0xF7, 0xFA, - - 0xB7, 0xBA, 0xAD, 0xA0, 0x83, 0x8E, 0x99, 0x94, 0xDF, 0xD2, 0xC5, 0xC8, - 0xEB, 0xE6, 0xF1, 0xFC, - - 0x67, 0x6A, 0x7D, 0x70, 0x53, 0x5E, 0x49, 0x44, 0x0F, 0x02, 0x15, 0x18, - 0x3B, 0x36, 0x21, 0x2C, - - 0x0C, 0x01, 0x16, 0x1B, 0x38, 0x35, 0x22, 0x2F, 0x64, 0x69, 0x7E, 0x73, - 0x50, 0x5D, 0x4A, 0x47, - - 0xDC, 0xD1, 0xC6, 0xCB, 0xE8, 0xE5, 0xF2, 0xFF, 0xB4, 0xB9, 0xAE, 0xA3, - 0x80, 0x8D, 0x9A, 0x97 -]; - - -/** - * Precomputed lookup of multiplication by 14 in GF(2^8) - * @type {!Array} - * @private - */ -goog.crypt.Aes.MULT_E_ = [ - 0x00, 0x0E, 0x1C, 0x12, 0x38, 0x36, 0x24, 0x2A, 0x70, 0x7E, 0x6C, 0x62, - 0x48, 0x46, 0x54, 0x5A, - - 0xE0, 0xEE, 0xFC, 0xF2, 0xD8, 0xD6, 0xC4, 0xCA, 0x90, 0x9E, 0x8C, 0x82, - 0xA8, 0xA6, 0xB4, 0xBA, - - 0xDB, 0xD5, 0xC7, 0xC9, 0xE3, 0xED, 0xFF, 0xF1, 0xAB, 0xA5, 0xB7, 0xB9, - 0x93, 0x9D, 0x8F, 0x81, - - 0x3B, 0x35, 0x27, 0x29, 0x03, 0x0D, 0x1F, 0x11, 0x4B, 0x45, 0x57, 0x59, - 0x73, 0x7D, 0x6F, 0x61, - - 0xAD, 0xA3, 0xB1, 0xBF, 0x95, 0x9B, 0x89, 0x87, 0xDD, 0xD3, 0xC1, 0xCF, - 0xE5, 0xEB, 0xF9, 0xF7, - - 0x4D, 0x43, 0x51, 0x5F, 0x75, 0x7B, 0x69, 0x67, 0x3D, 0x33, 0x21, 0x2F, - 0x05, 0x0B, 0x19, 0x17, - - 0x76, 0x78, 0x6A, 0x64, 0x4E, 0x40, 0x52, 0x5C, 0x06, 0x08, 0x1A, 0x14, - 0x3E, 0x30, 0x22, 0x2C, - - 0x96, 0x98, 0x8A, 0x84, 0xAE, 0xA0, 0xB2, 0xBC, 0xE6, 0xE8, 0xFA, 0xF4, - 0xDE, 0xD0, 0xC2, 0xCC, - - 0x41, 0x4F, 0x5D, 0x53, 0x79, 0x77, 0x65, 0x6B, 0x31, 0x3F, 0x2D, 0x23, - 0x09, 0x07, 0x15, 0x1B, - - 0xA1, 0xAF, 0xBD, 0xB3, 0x99, 0x97, 0x85, 0x8B, 0xD1, 0xDF, 0xCD, 0xC3, - 0xE9, 0xE7, 0xF5, 0xFB, - - 0x9A, 0x94, 0x86, 0x88, 0xA2, 0xAC, 0xBE, 0xB0, 0xEA, 0xE4, 0xF6, 0xF8, - 0xD2, 0xDC, 0xCE, 0xC0, - - 0x7A, 0x74, 0x66, 0x68, 0x42, 0x4C, 0x5E, 0x50, 0x0A, 0x04, 0x16, 0x18, - 0x32, 0x3C, 0x2E, 0x20, - - 0xEC, 0xE2, 0xF0, 0xFE, 0xD4, 0xDA, 0xC8, 0xC6, 0x9C, 0x92, 0x80, 0x8E, - 0xA4, 0xAA, 0xB8, 0xB6, - - 0x0C, 0x02, 0x10, 0x1E, 0x34, 0x3A, 0x28, 0x26, 0x7C, 0x72, 0x60, 0x6E, - 0x44, 0x4A, 0x58, 0x56, - - 0x37, 0x39, 0x2B, 0x25, 0x0F, 0x01, 0x13, 0x1D, 0x47, 0x49, 0x5B, 0x55, - 0x7F, 0x71, 0x63, 0x6D, - - 0xD7, 0xD9, 0xCB, 0xC5, 0xEF, 0xE1, 0xF3, 0xFD, 0xA7, 0xA9, 0xBB, 0xB5, - 0x9F, 0x91, 0x83, 0x8D -]; diff --git a/src/database/third_party/closure-library/closure/goog/crypt/aes_test.html b/src/database/third_party/closure-library/closure/goog/crypt/aes_test.html deleted file mode 100644 index 8643067cf27..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/aes_test.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - goog.crypt.Aes unit test - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/crypt/aes_test.js b/src/database/third_party/closure-library/closure/goog/crypt/aes_test.js deleted file mode 100644 index b34ed416c1a..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/aes_test.js +++ /dev/null @@ -1,586 +0,0 @@ -// Copyright 2012 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.crypt.AesTest'); -goog.setTestOnly('goog.crypt.AesTest'); - -goog.require('goog.crypt'); -goog.require('goog.crypt.Aes'); -goog.require('goog.testing.jsunit'); -goog.crypt.Aes.ENABLE_TEST_MODE = true; - -/* - * Unit test for goog.crypt.Aes using the test vectors from the spec: - * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf - */ - -var testData = null; - -function test128() { - doTest('000102030405060708090a0b0c0d0e0f', - '00112233445566778899aabbccddeeff', - v128, - true /* encrypt */); -} - -function test192() { - doTest('000102030405060708090a0b0c0d0e0f1011121314151617', - '00112233445566778899aabbccddeeff', - v192, - true /* encrypt */); -} - -function test256() { - doTest('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', - '00112233445566778899aabbccddeeff', - v256, - true /* encrypt */); -} - -function test128d() { - doTest('000102030405060708090a0b0c0d0e0f', - '69c4e0d86a7b0430d8cdb78070b4c55a', - v128d, - false /* decrypt */); -} - -function test192d() { - doTest('000102030405060708090a0b0c0d0e0f1011121314151617', - 'dda97ca4864cdfe06eaf70a0ec0d7191', - v192d, - false /* decrypt */); -} - -function test256d() { - doTest('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', - '8ea2b7ca516745bfeafc49904b496089', - v256d, - false /* decrypt */); -} - -function doTest(key, input, values, dir) { - testData = values; - var keyArray = goog.crypt.hexToByteArray(key); - var aes = new goog.crypt.Aes(keyArray); - - aes.testKeySchedule_ = onTestKeySchedule; - aes.testStartRound_ = onTestStartRound; - aes.testAfterSubBytes_ = onTestAfterSubBytes; - aes.testAfterShiftRows_ = onTestAfterShiftRows; - aes.testAfterMixColumns_ = onTestAfterMixColumns; - aes.testAfterAddRoundKey_ = onTestAfterAddRoundKey; - - var inputArr = goog.crypt.hexToByteArray(input); - var keyArr = goog.crypt.hexToByteArray(key); - var outputArr = []; - - var outputArr; - if (dir) { - outputArr = aes.encrypt(inputArr); - } else { - outputArr = aes.decrypt(inputArr); - } - - assertEquals('Incorrect output for test ' + testData.name, - testData[testData.length - 1].output, - encodeHex(outputArr)); -} - -function onTestKeySchedule(roundNum, keySchedule, keyScheduleIndex) { - assertEquals( - 'Incorrect key for round ' + roundNum, - testData[roundNum].k_sch, encodeKey(keySchedule, keyScheduleIndex)); -} - -function onTestStartRound(roundNum, state) { - assertEquals('Incorrect state for test ' + testData.name + - ' at start round ' + roundNum, - testData[roundNum].start, encodeState(state)); -} - -function onTestAfterSubBytes(roundNum, state) { - assertEquals('Incorrect state for test ' + testData.name + - ' after sub bytes in round ' + roundNum, - testData[roundNum].s_box, encodeState(state)); -} - -function onTestAfterShiftRows(roundNum, state) { - assertEquals('Incorrect state for test ' + testData.name + - ' after shift rows in round ' + roundNum, - testData[roundNum].s_row, encodeState(state)); -} - -function onTestAfterMixColumns(roundNum, state) { - assertEquals('Incorrect state for test ' + testData.name + - ' after mix columns in round ' + roundNum, - testData[roundNum].m_col, encodeState(state)); -} - -function onTestAfterAddRoundKey(roundNum, state) { - assertEquals('Incorrect state for test ' + testData.name + - ' after adding round key in round ' + roundNum, - testData[roundNum].k_add, encodeState(state)); -} - -function encodeHex(arr) { - var str = []; - - for (var i = 0; i < arr.length; i++) { - str.push(encodeByte(arr[i])); - } - - return str.join(''); -} - -function encodeState(state) { - var s = []; - - for (var c = 0; c < 4; c++) { - for (var r = 0; r < 4; r++) { - s.push(encodeByte(state[r][c])); - } - } - - return s.join(''); -} - -function encodeKey(key, round) { - var s = []; - - for (var r = round * 4; r < (round * 4 + 4); r++) { - for (var c = 0; c < 4; c++) { - s.push(encodeByte(key[r][c])); - } - } - - return s.join(''); -} - -function encodeByte(val) { - val = Number(val).toString(16); - - if (val.length == 1) { - val = '0' + val; - } - - return val; -} - -var v128 = []; -(function v128_init() { - for (var i = 0; i <= 10; i++) v128[i] = {}; - v128.name = '128'; - v128[0].input = '00112233445566778899aabbccddeeff'; - v128[0].k_sch = '000102030405060708090a0b0c0d0e0f'; - v128[1].start = '00102030405060708090a0b0c0d0e0f0'; - v128[1].s_box = '63cab7040953d051cd60e0e7ba70e18c'; - v128[1].s_row = '6353e08c0960e104cd70b751bacad0e7'; - v128[1].m_col = '5f72641557f5bc92f7be3b291db9f91a'; - v128[1].k_sch = 'd6aa74fdd2af72fadaa678f1d6ab76fe'; - v128[2].start = '89d810e8855ace682d1843d8cb128fe4'; - v128[2].s_box = 'a761ca9b97be8b45d8ad1a611fc97369'; - v128[2].s_row = 'a7be1a6997ad739bd8c9ca451f618b61'; - v128[2].m_col = 'ff87968431d86a51645151fa773ad009'; - v128[2].k_sch = 'b692cf0b643dbdf1be9bc5006830b3fe'; - v128[3].start = '4915598f55e5d7a0daca94fa1f0a63f7'; - v128[3].s_box = '3b59cb73fcd90ee05774222dc067fb68'; - v128[3].s_row = '3bd92268fc74fb735767cbe0c0590e2d'; - v128[3].m_col = '4c9c1e66f771f0762c3f868e534df256'; - v128[3].k_sch = 'b6ff744ed2c2c9bf6c590cbf0469bf41'; - v128[4].start = 'fa636a2825b339c940668a3157244d17'; - v128[4].s_box = '2dfb02343f6d12dd09337ec75b36e3f0'; - v128[4].s_row = '2d6d7ef03f33e334093602dd5bfb12c7'; - v128[4].m_col = '6385b79ffc538df997be478e7547d691'; - v128[4].k_sch = '47f7f7bc95353e03f96c32bcfd058dfd'; - v128[5].start = '247240236966b3fa6ed2753288425b6c'; - v128[5].s_box = '36400926f9336d2d9fb59d23c42c3950'; - v128[5].s_row = '36339d50f9b539269f2c092dc4406d23'; - v128[5].m_col = 'f4bcd45432e554d075f1d6c51dd03b3c'; - v128[5].k_sch = '3caaa3e8a99f9deb50f3af57adf622aa'; - v128[6].start = 'c81677bc9b7ac93b25027992b0261996'; - v128[6].s_box = 'e847f56514dadde23f77b64fe7f7d490'; - v128[6].s_row = 'e8dab6901477d4653ff7f5e2e747dd4f'; - v128[6].m_col = '9816ee7400f87f556b2c049c8e5ad036'; - v128[6].k_sch = '5e390f7df7a69296a7553dc10aa31f6b'; - v128[7].start = 'c62fe109f75eedc3cc79395d84f9cf5d'; - v128[7].s_box = 'b415f8016858552e4bb6124c5f998a4c'; - v128[7].s_row = 'b458124c68b68a014b99f82e5f15554c'; - v128[7].m_col = 'c57e1c159a9bd286f05f4be098c63439'; - v128[7].k_sch = '14f9701ae35fe28c440adf4d4ea9c026'; - v128[8].start = 'd1876c0f79c4300ab45594add66ff41f'; - v128[8].s_box = '3e175076b61c04678dfc2295f6a8bfc0'; - v128[8].s_row = '3e1c22c0b6fcbf768da85067f6170495'; - v128[8].m_col = 'baa03de7a1f9b56ed5512cba5f414d23'; - v128[8].k_sch = '47438735a41c65b9e016baf4aebf7ad2'; - v128[9].start = 'fde3bad205e5d0d73547964ef1fe37f1'; - v128[9].s_box = '5411f4b56bd9700e96a0902fa1bb9aa1'; - v128[9].s_row = '54d990a16ba09ab596bbf40ea111702f'; - v128[9].m_col = 'e9f74eec023020f61bf2ccf2353c21c7'; - v128[9].k_sch = '549932d1f08557681093ed9cbe2c974e'; - v128[10].start = 'bd6e7c3df2b5779e0b61216e8b10b689'; - v128[10].s_box = '7a9f102789d5f50b2beffd9f3dca4ea7'; - v128[10].s_row = '7ad5fda789ef4e272bca100b3d9ff59f'; - v128[10].k_sch = '13111d7fe3944a17f307a78b4d2b30c5'; - v128[10].output = '69c4e0d86a7b0430d8cdb78070b4c55a'; -})(); - -var v128d = []; -(function v128d_init() { - for (var i = 0; i <= 10; i++) v128d[i] = {}; - v128d.name = '128d'; - v128d[0].input = '69c4e0d86a7b0430d8cdb78070b4c55a'; - v128d[0].k_sch = '13111d7fe3944a17f307a78b4d2b30c5'; - v128d[1].start = '7ad5fda789ef4e272bca100b3d9ff59f'; - v128d[1].s_row = '7a9f102789d5f50b2beffd9f3dca4ea7'; - v128d[1].s_box = 'bd6e7c3df2b5779e0b61216e8b10b689'; - v128d[1].k_sch = '549932d1f08557681093ed9cbe2c974e'; - v128d[1].k_add = 'e9f74eec023020f61bf2ccf2353c21c7'; - v128d[2].start = '54d990a16ba09ab596bbf40ea111702f'; - v128d[2].s_row = '5411f4b56bd9700e96a0902fa1bb9aa1'; - v128d[2].s_box = 'fde3bad205e5d0d73547964ef1fe37f1'; - v128d[2].k_sch = '47438735a41c65b9e016baf4aebf7ad2'; - v128d[2].k_add = 'baa03de7a1f9b56ed5512cba5f414d23'; - v128d[3].start = '3e1c22c0b6fcbf768da85067f6170495'; - v128d[3].s_row = '3e175076b61c04678dfc2295f6a8bfc0'; - v128d[3].s_box = 'd1876c0f79c4300ab45594add66ff41f'; - v128d[3].k_sch = '14f9701ae35fe28c440adf4d4ea9c026'; - v128d[3].k_add = 'c57e1c159a9bd286f05f4be098c63439'; - v128d[4].start = 'b458124c68b68a014b99f82e5f15554c'; - v128d[4].s_row = 'b415f8016858552e4bb6124c5f998a4c'; - v128d[4].s_box = 'c62fe109f75eedc3cc79395d84f9cf5d'; - v128d[4].k_sch = '5e390f7df7a69296a7553dc10aa31f6b'; - v128d[4].k_add = '9816ee7400f87f556b2c049c8e5ad036'; - v128d[5].start = 'e8dab6901477d4653ff7f5e2e747dd4f'; - v128d[5].s_row = 'e847f56514dadde23f77b64fe7f7d490'; - v128d[5].s_box = 'c81677bc9b7ac93b25027992b0261996'; - v128d[5].k_sch = '3caaa3e8a99f9deb50f3af57adf622aa'; - v128d[5].k_add = 'f4bcd45432e554d075f1d6c51dd03b3c'; - v128d[6].start = '36339d50f9b539269f2c092dc4406d23'; - v128d[6].s_row = '36400926f9336d2d9fb59d23c42c3950'; - v128d[6].s_box = '247240236966b3fa6ed2753288425b6c'; - v128d[6].k_sch = '47f7f7bc95353e03f96c32bcfd058dfd'; - v128d[6].k_add = '6385b79ffc538df997be478e7547d691'; - v128d[7].start = '2d6d7ef03f33e334093602dd5bfb12c7'; - v128d[7].s_row = '2dfb02343f6d12dd09337ec75b36e3f0'; - v128d[7].s_box = 'fa636a2825b339c940668a3157244d17'; - v128d[7].k_sch = 'b6ff744ed2c2c9bf6c590cbf0469bf41'; - v128d[7].k_add = '4c9c1e66f771f0762c3f868e534df256'; - v128d[8].start = '3bd92268fc74fb735767cbe0c0590e2d'; - v128d[8].s_row = '3b59cb73fcd90ee05774222dc067fb68'; - v128d[8].s_box = '4915598f55e5d7a0daca94fa1f0a63f7'; - v128d[8].k_sch = 'b692cf0b643dbdf1be9bc5006830b3fe'; - v128d[8].k_add = 'ff87968431d86a51645151fa773ad009'; - v128d[9].start = 'a7be1a6997ad739bd8c9ca451f618b61'; - v128d[9].s_row = 'a761ca9b97be8b45d8ad1a611fc97369'; - v128d[9].s_box = '89d810e8855ace682d1843d8cb128fe4'; - v128d[9].k_sch = 'd6aa74fdd2af72fadaa678f1d6ab76fe'; - v128d[9].k_add = '5f72641557f5bc92f7be3b291db9f91a'; - v128d[10].start = '6353e08c0960e104cd70b751bacad0e7'; - v128d[10].s_row = '63cab7040953d051cd60e0e7ba70e18c'; - v128d[10].s_box = '00102030405060708090a0b0c0d0e0f0'; - v128d[10].k_sch = '000102030405060708090a0b0c0d0e0f'; - v128d[10].output = '00112233445566778899aabbccddeeff'; -})(); - -var v192 = []; -(function v192_init() { - for (var i = 0; i <= 12; i++) v192[i] = {}; - v192.name = '192'; - v192[0].input = '00112233445566778899aabbccddeeff'; - v192[0].k_sch = '000102030405060708090a0b0c0d0e0f'; - v192[1].start = '00102030405060708090a0b0c0d0e0f0'; - v192[1].s_box = '63cab7040953d051cd60e0e7ba70e18c'; - v192[1].s_row = '6353e08c0960e104cd70b751bacad0e7'; - v192[1].m_col = '5f72641557f5bc92f7be3b291db9f91a'; - v192[1].k_sch = '10111213141516175846f2f95c43f4fe'; - v192[2].start = '4f63760643e0aa85aff8c9d041fa0de4'; - v192[2].s_box = '84fb386f1ae1ac977941dd70832dd769'; - v192[2].s_row = '84e1dd691a41d76f792d389783fbac70'; - v192[2].m_col = '9f487f794f955f662afc86abd7f1ab29'; - v192[2].k_sch = '544afef55847f0fa4856e2e95c43f4fe'; - v192[3].start = 'cb02818c17d2af9c62aa64428bb25fd7'; - v192[3].s_box = '1f770c64f0b579deaaac432c3d37cf0e'; - v192[3].s_row = '1fb5430ef0accf64aa370cde3d77792c'; - v192[3].m_col = 'b7a53ecbbf9d75a0c40efc79b674cc11'; - v192[3].k_sch = '40f949b31cbabd4d48f043b810b7b342'; - v192[4].start = 'f75c7778a327c8ed8cfebfc1a6c37f53'; - v192[4].s_box = '684af5bc0acce85564bb0878242ed2ed'; - v192[4].s_row = '68cc08ed0abbd2bc642ef555244ae878'; - v192[4].m_col = '7a1e98bdacb6d1141a6944dd06eb2d3e'; - v192[4].k_sch = '58e151ab04a2a5557effb5416245080c'; - v192[5].start = '22ffc916a81474416496f19c64ae2532'; - v192[5].s_box = '9316dd47c2fa92834390a1de43e43f23'; - v192[5].s_row = '93faa123c2903f4743e4dd83431692de'; - v192[5].m_col = 'aaa755b34cffe57cef6f98e1f01c13e6'; - v192[5].k_sch = '2ab54bb43a02f8f662e3a95d66410c08'; - v192[6].start = '80121e0776fd1d8a8d8c31bc965d1fee'; - v192[6].s_box = 'cdc972c53854a47e5d64c765904cc028'; - v192[6].s_row = 'cd54c7283864c0c55d4c727e90c9a465'; - v192[6].m_col = '921f748fd96e937d622d7725ba8ba50c'; - v192[6].k_sch = 'f501857297448d7ebdf1c6ca87f33e3c'; - v192[7].start = '671ef1fd4e2a1e03dfdcb1ef3d789b30'; - v192[7].s_box = '8572a1542fe5727b9e86c8df27bc1404'; - v192[7].s_row = '85e5c8042f8614549ebca17b277272df'; - v192[7].m_col = 'e913e7b18f507d4b227ef652758acbcc'; - v192[7].k_sch = 'e510976183519b6934157c9ea351f1e0'; - v192[8].start = '0c0370d00c01e622166b8accd6db3a2c'; - v192[8].s_box = 'fe7b5170fe7c8e93477f7e4bf6b98071'; - v192[8].s_row = 'fe7c7e71fe7f807047b95193f67b8e4b'; - v192[8].m_col = '6cf5edf996eb0a069c4ef21cbfc25762'; - v192[8].k_sch = '1ea0372a995309167c439e77ff12051e'; - v192[9].start = '7255dad30fb80310e00d6c6b40d0527c'; - v192[9].s_box = '40fc5766766c7bcae1d7507f09700010'; - v192[9].s_row = '406c501076d70066e17057ca09fc7b7f'; - v192[9].m_col = '7478bcdce8a50b81d4327a9009188262'; - v192[9].k_sch = 'dd7e0e887e2fff68608fc842f9dcc154'; - v192[10].start = 'a906b254968af4e9b4bdb2d2f0c44336'; - v192[10].s_box = 'd36f3720907ebf1e8d7a37b58c1c1a05'; - v192[10].s_row = 'd37e3705907a1a208d1c371e8c6fbfb5'; - v192[10].m_col = '0d73cc2d8f6abe8b0cf2dd9bb83d422e'; - v192[10].k_sch = '859f5f237a8d5a3dc0c02952beefd63a'; - v192[11].start = '88ec930ef5e7e4b6cc32f4c906d29414'; - v192[11].s_box = 'c4cedcabe694694e4b23bfdd6fb522fa'; - v192[11].s_row = 'c494bffae62322ab4bb5dc4e6fce69dd'; - v192[11].m_col = '71d720933b6d677dc00b8f28238e0fb7'; - v192[11].k_sch = 'de601e7827bcdf2ca223800fd8aeda32'; - v192[12].start = 'afb73eeb1cd1b85162280f27fb20d585'; - v192[12].s_box = '79a9b2e99c3e6cd1aa3476cc0fb70397'; - v192[12].s_row = '793e76979c3403e9aab7b2d10fa96ccc'; - v192[12].k_sch = 'a4970a331a78dc09c418c271e3a41d5d'; - v192[12].output = 'dda97ca4864cdfe06eaf70a0ec0d7191'; -})(); - -var v192d = []; -(function v192d_init() { - for (var i = 0; i <= 12; i++) v192d[i] = {}; - v192d.name = '192d'; - v192d[0].input = 'dda97ca4864cdfe06eaf70a0ec0d7191'; - v192d[0].k_sch = 'a4970a331a78dc09c418c271e3a41d5d'; - v192d[1].start = '793e76979c3403e9aab7b2d10fa96ccc'; - v192d[1].s_row = '79a9b2e99c3e6cd1aa3476cc0fb70397'; - v192d[1].s_box = 'afb73eeb1cd1b85162280f27fb20d585'; - v192d[1].k_sch = 'de601e7827bcdf2ca223800fd8aeda32'; - v192d[1].k_add = '71d720933b6d677dc00b8f28238e0fb7'; - v192d[2].start = 'c494bffae62322ab4bb5dc4e6fce69dd'; - v192d[2].s_row = 'c4cedcabe694694e4b23bfdd6fb522fa'; - v192d[2].s_box = '88ec930ef5e7e4b6cc32f4c906d29414'; - v192d[2].k_sch = '859f5f237a8d5a3dc0c02952beefd63a'; - v192d[2].k_add = '0d73cc2d8f6abe8b0cf2dd9bb83d422e'; - v192d[3].start = 'd37e3705907a1a208d1c371e8c6fbfb5'; - v192d[3].s_row = 'd36f3720907ebf1e8d7a37b58c1c1a05'; - v192d[3].s_box = 'a906b254968af4e9b4bdb2d2f0c44336'; - v192d[3].k_sch = 'dd7e0e887e2fff68608fc842f9dcc154'; - v192d[3].k_add = '7478bcdce8a50b81d4327a9009188262'; - v192d[4].start = '406c501076d70066e17057ca09fc7b7f'; - v192d[4].s_row = '40fc5766766c7bcae1d7507f09700010'; - v192d[4].s_box = '7255dad30fb80310e00d6c6b40d0527c'; - v192d[4].k_sch = '1ea0372a995309167c439e77ff12051e'; - v192d[4].k_add = '6cf5edf996eb0a069c4ef21cbfc25762'; - v192d[5].start = 'fe7c7e71fe7f807047b95193f67b8e4b'; - v192d[5].s_row = 'fe7b5170fe7c8e93477f7e4bf6b98071'; - v192d[5].s_box = '0c0370d00c01e622166b8accd6db3a2c'; - v192d[5].k_sch = 'e510976183519b6934157c9ea351f1e0'; - v192d[5].k_add = 'e913e7b18f507d4b227ef652758acbcc'; - v192d[6].start = '85e5c8042f8614549ebca17b277272df'; - v192d[6].s_row = '8572a1542fe5727b9e86c8df27bc1404'; - v192d[6].s_box = '671ef1fd4e2a1e03dfdcb1ef3d789b30'; - v192d[6].k_sch = 'f501857297448d7ebdf1c6ca87f33e3c'; - v192d[6].k_add = '921f748fd96e937d622d7725ba8ba50c'; - v192d[7].start = 'cd54c7283864c0c55d4c727e90c9a465'; - v192d[7].s_row = 'cdc972c53854a47e5d64c765904cc028'; - v192d[7].s_box = '80121e0776fd1d8a8d8c31bc965d1fee'; - v192d[7].k_sch = '2ab54bb43a02f8f662e3a95d66410c08'; - v192d[7].k_add = 'aaa755b34cffe57cef6f98e1f01c13e6'; - v192d[8].start = '93faa123c2903f4743e4dd83431692de'; - v192d[8].s_row = '9316dd47c2fa92834390a1de43e43f23'; - v192d[8].s_box = '22ffc916a81474416496f19c64ae2532'; - v192d[8].k_sch = '58e151ab04a2a5557effb5416245080c'; - v192d[8].k_add = '7a1e98bdacb6d1141a6944dd06eb2d3e'; - v192d[9].start = '68cc08ed0abbd2bc642ef555244ae878'; - v192d[9].s_row = '684af5bc0acce85564bb0878242ed2ed'; - v192d[9].s_box = 'f75c7778a327c8ed8cfebfc1a6c37f53'; - v192d[9].k_sch = '40f949b31cbabd4d48f043b810b7b342'; - v192d[9].k_add = 'b7a53ecbbf9d75a0c40efc79b674cc11'; - v192d[10].start = '1fb5430ef0accf64aa370cde3d77792c'; - v192d[10].s_row = '1f770c64f0b579deaaac432c3d37cf0e'; - v192d[10].s_box = 'cb02818c17d2af9c62aa64428bb25fd7'; - v192d[10].k_sch = '544afef55847f0fa4856e2e95c43f4fe'; - v192d[10].k_add = '9f487f794f955f662afc86abd7f1ab29'; - v192d[11].start = '84e1dd691a41d76f792d389783fbac70'; - v192d[11].s_row = '84fb386f1ae1ac977941dd70832dd769'; - v192d[11].s_box = '4f63760643e0aa85aff8c9d041fa0de4'; - v192d[11].k_sch = '10111213141516175846f2f95c43f4fe'; - v192d[11].k_add = '5f72641557f5bc92f7be3b291db9f91a'; - v192d[12].start = '6353e08c0960e104cd70b751bacad0e7'; - v192d[12].s_row = '63cab7040953d051cd60e0e7ba70e18c'; - v192d[12].s_box = '00102030405060708090a0b0c0d0e0f0'; - v192d[12].k_sch = '000102030405060708090a0b0c0d0e0f'; - v192d[12].output = '00112233445566778899aabbccddeeff'; -})(); - -var v256 = []; -(function v256_init() { - for (var i = 0; i <= 14; i++) v256[i] = {}; - v256.name = '256'; - v256[0].input = '00112233445566778899aabbccddeeff'; - v256[0].k_sch = '000102030405060708090a0b0c0d0e0f'; - v256[1].start = '00102030405060708090a0b0c0d0e0f0'; - v256[1].s_box = '63cab7040953d051cd60e0e7ba70e18c'; - v256[1].s_row = '6353e08c0960e104cd70b751bacad0e7'; - v256[1].m_col = '5f72641557f5bc92f7be3b291db9f91a'; - v256[1].k_sch = '101112131415161718191a1b1c1d1e1f'; - v256[2].start = '4f63760643e0aa85efa7213201a4e705'; - v256[2].s_box = '84fb386f1ae1ac97df5cfd237c49946b'; - v256[2].s_row = '84e1fd6b1a5c946fdf4938977cfbac23'; - v256[2].m_col = 'bd2a395d2b6ac438d192443e615da195'; - v256[2].k_sch = 'a573c29fa176c498a97fce93a572c09c'; - v256[3].start = '1859fbc28a1c00a078ed8aadc42f6109'; - v256[3].s_box = 'adcb0f257e9c63e0bc557e951c15ef01'; - v256[3].s_row = 'ad9c7e017e55ef25bc150fe01ccb6395'; - v256[3].m_col = '810dce0cc9db8172b3678c1e88a1b5bd'; - v256[3].k_sch = '1651a8cd0244beda1a5da4c10640bade'; - v256[4].start = '975c66c1cb9f3fa8a93a28df8ee10f63'; - v256[4].s_box = '884a33781fdb75c2d380349e19f876fb'; - v256[4].s_row = '88db34fb1f807678d3f833c2194a759e'; - v256[4].m_col = 'b2822d81abe6fb275faf103a078c0033'; - v256[4].k_sch = 'ae87dff00ff11b68a68ed5fb03fc1567'; - v256[5].start = '1c05f271a417e04ff921c5c104701554'; - v256[5].s_box = '9c6b89a349f0e18499fda678f2515920'; - v256[5].s_row = '9cf0a62049fd59a399518984f26be178'; - v256[5].m_col = 'aeb65ba974e0f822d73f567bdb64c877'; - v256[5].k_sch = '6de1f1486fa54f9275f8eb5373b8518d'; - v256[6].start = 'c357aae11b45b7b0a2c7bd28a8dc99fa'; - v256[6].s_box = '2e5bacf8af6ea9e73ac67a34c286ee2d'; - v256[6].s_row = '2e6e7a2dafc6eef83a86ace7c25ba934'; - v256[6].m_col = 'b951c33c02e9bd29ae25cdb1efa08cc7'; - v256[6].k_sch = 'c656827fc9a799176f294cec6cd5598b'; - v256[7].start = '7f074143cb4e243ec10c815d8375d54c'; - v256[7].s_box = 'd2c5831a1f2f36b278fe0c4cec9d0329'; - v256[7].s_row = 'd22f0c291ffe031a789d83b2ecc5364c'; - v256[7].m_col = 'ebb19e1c3ee7c9e87d7535e9ed6b9144'; - v256[7].k_sch = '3de23a75524775e727bf9eb45407cf39'; - v256[8].start = 'd653a4696ca0bc0f5acaab5db96c5e7d'; - v256[8].s_box = 'f6ed49f950e06576be74624c565058ff'; - v256[8].s_row = 'f6e062ff507458f9be50497656ed654c'; - v256[8].m_col = '5174c8669da98435a8b3e62ca974a5ea'; - v256[8].k_sch = '0bdc905fc27b0948ad5245a4c1871c2f'; - v256[9].start = '5aa858395fd28d7d05e1a38868f3b9c5'; - v256[9].s_box = 'bec26a12cfb55dff6bf80ac4450d56a6'; - v256[9].s_row = 'beb50aa6cff856126b0d6aff45c25dc4'; - v256[9].m_col = '0f77ee31d2ccadc05430a83f4ef96ac3'; - v256[9].k_sch = '45f5a66017b2d387300d4d33640a820a'; - v256[10].start = '4a824851c57e7e47643de50c2af3e8c9'; - v256[10].s_box = 'd61352d1a6f3f3a04327d9fee50d9bdd'; - v256[10].s_row = 'd6f3d9dda6279bd1430d52a0e513f3fe'; - v256[10].m_col = 'bd86f0ea748fc4f4630f11c1e9331233'; - v256[10].k_sch = '7ccff71cbeb4fe5413e6bbf0d261a7df'; - v256[11].start = 'c14907f6ca3b3aa070e9aa313b52b5ec'; - v256[11].s_box = '783bc54274e280e0511eacc7e200d5ce'; - v256[11].s_row = '78e2acce741ed5425100c5e0e23b80c7'; - v256[11].m_col = 'af8690415d6e1dd387e5fbedd5c89013'; - v256[11].k_sch = 'f01afafee7a82979d7a5644ab3afe640'; - v256[12].start = '5f9c6abfbac634aa50409fa766677653'; - v256[12].s_box = 'cfde0208f4b418ac5309db5c338538ed'; - v256[12].s_row = 'cfb4dbedf4093808538502ac33de185c'; - v256[12].m_col = '7427fae4d8a695269ce83d315be0392b'; - v256[12].k_sch = '2541fe719bf500258813bbd55a721c0a'; - v256[13].start = '516604954353950314fb86e401922521'; - v256[13].s_box = 'd133f22a1aed2a7bfa0f44697c4f3ffd'; - v256[13].s_row = 'd1ed44fd1a0f3f2afa4ff27b7c332a69'; - v256[13].m_col = '2c21a820306f154ab712c75eee0da04f'; - v256[13].k_sch = '4e5a6699a9f24fe07e572baacdf8cdea'; - v256[14].start = '627bceb9999d5aaac945ecf423f56da5'; - v256[14].s_box = 'aa218b56ee5ebeacdd6ecebf26e63c06'; - v256[14].s_row = 'aa5ece06ee6e3c56dde68bac2621bebf'; - v256[14].k_sch = '24fc79ccbf0979e9371ac23c6d68de36'; - v256[14].output = '8ea2b7ca516745bfeafc49904b496089'; -})(); - -var v256d = []; -(function v256d_init() { - for (var i = 0; i <= 14; i++) v256d[i] = {}; - v256d.name = '256d'; - v256d[0].input = '8ea2b7ca516745bfeafc49904b496089'; - v256d[0].k_sch = '24fc79ccbf0979e9371ac23c6d68de36'; - v256d[1].start = 'aa5ece06ee6e3c56dde68bac2621bebf'; - v256d[1].s_row = 'aa218b56ee5ebeacdd6ecebf26e63c06'; - v256d[1].s_box = '627bceb9999d5aaac945ecf423f56da5'; - v256d[1].k_sch = '4e5a6699a9f24fe07e572baacdf8cdea'; - v256d[1].k_add = '2c21a820306f154ab712c75eee0da04f'; - v256d[2].start = 'd1ed44fd1a0f3f2afa4ff27b7c332a69'; - v256d[2].s_row = 'd133f22a1aed2a7bfa0f44697c4f3ffd'; - v256d[2].s_box = '516604954353950314fb86e401922521'; - v256d[2].k_sch = '2541fe719bf500258813bbd55a721c0a'; - v256d[2].k_add = '7427fae4d8a695269ce83d315be0392b'; - v256d[3].start = 'cfb4dbedf4093808538502ac33de185c'; - v256d[3].s_row = 'cfde0208f4b418ac5309db5c338538ed'; - v256d[3].s_box = '5f9c6abfbac634aa50409fa766677653'; - v256d[3].k_sch = 'f01afafee7a82979d7a5644ab3afe640'; - v256d[3].k_add = 'af8690415d6e1dd387e5fbedd5c89013'; - v256d[4].start = '78e2acce741ed5425100c5e0e23b80c7'; - v256d[4].s_row = '783bc54274e280e0511eacc7e200d5ce'; - v256d[4].s_box = 'c14907f6ca3b3aa070e9aa313b52b5ec'; - v256d[4].k_sch = '7ccff71cbeb4fe5413e6bbf0d261a7df'; - v256d[4].k_add = 'bd86f0ea748fc4f4630f11c1e9331233'; - v256d[5].start = 'd6f3d9dda6279bd1430d52a0e513f3fe'; - v256d[5].s_row = 'd61352d1a6f3f3a04327d9fee50d9bdd'; - v256d[5].s_box = '4a824851c57e7e47643de50c2af3e8c9'; - v256d[5].k_sch = '45f5a66017b2d387300d4d33640a820a'; - v256d[5].k_add = '0f77ee31d2ccadc05430a83f4ef96ac3'; - v256d[6].start = 'beb50aa6cff856126b0d6aff45c25dc4'; - v256d[6].s_row = 'bec26a12cfb55dff6bf80ac4450d56a6'; - v256d[6].s_box = '5aa858395fd28d7d05e1a38868f3b9c5'; - v256d[6].k_sch = '0bdc905fc27b0948ad5245a4c1871c2f'; - v256d[6].k_add = '5174c8669da98435a8b3e62ca974a5ea'; - v256d[7].start = 'f6e062ff507458f9be50497656ed654c'; - v256d[7].s_row = 'f6ed49f950e06576be74624c565058ff'; - v256d[7].s_box = 'd653a4696ca0bc0f5acaab5db96c5e7d'; - v256d[7].k_sch = '3de23a75524775e727bf9eb45407cf39'; - v256d[7].k_add = 'ebb19e1c3ee7c9e87d7535e9ed6b9144'; - v256d[8].start = 'd22f0c291ffe031a789d83b2ecc5364c'; - v256d[8].s_row = 'd2c5831a1f2f36b278fe0c4cec9d0329'; - v256d[8].s_box = '7f074143cb4e243ec10c815d8375d54c'; - v256d[8].k_sch = 'c656827fc9a799176f294cec6cd5598b'; - v256d[8].k_add = 'b951c33c02e9bd29ae25cdb1efa08cc7'; - v256d[9].start = '2e6e7a2dafc6eef83a86ace7c25ba934'; - v256d[9].s_row = '2e5bacf8af6ea9e73ac67a34c286ee2d'; - v256d[9].s_box = 'c357aae11b45b7b0a2c7bd28a8dc99fa'; - v256d[9].k_sch = '6de1f1486fa54f9275f8eb5373b8518d'; - v256d[9].k_add = 'aeb65ba974e0f822d73f567bdb64c877'; - v256d[10].start = '9cf0a62049fd59a399518984f26be178'; - v256d[10].s_row = '9c6b89a349f0e18499fda678f2515920'; - v256d[10].s_box = '1c05f271a417e04ff921c5c104701554'; - v256d[10].k_sch = 'ae87dff00ff11b68a68ed5fb03fc1567'; - v256d[10].k_add = 'b2822d81abe6fb275faf103a078c0033'; - v256d[11].start = '88db34fb1f807678d3f833c2194a759e'; - v256d[11].s_row = '884a33781fdb75c2d380349e19f876fb'; - v256d[11].s_box = '975c66c1cb9f3fa8a93a28df8ee10f63'; - v256d[11].k_sch = '1651a8cd0244beda1a5da4c10640bade'; - v256d[11].k_add = '810dce0cc9db8172b3678c1e88a1b5bd'; - v256d[12].start = 'ad9c7e017e55ef25bc150fe01ccb6395'; - v256d[12].s_row = 'adcb0f257e9c63e0bc557e951c15ef01'; - v256d[12].s_box = '1859fbc28a1c00a078ed8aadc42f6109'; - v256d[12].k_sch = 'a573c29fa176c498a97fce93a572c09c'; - v256d[12].k_add = 'bd2a395d2b6ac438d192443e615da195'; - v256d[13].start = '84e1fd6b1a5c946fdf4938977cfbac23'; - v256d[13].s_row = '84fb386f1ae1ac97df5cfd237c49946b'; - v256d[13].s_box = '4f63760643e0aa85efa7213201a4e705'; - v256d[13].k_sch = '101112131415161718191a1b1c1d1e1f'; - v256d[13].k_add = '5f72641557f5bc92f7be3b291db9f91a'; - v256d[14].start = '6353e08c0960e104cd70b751bacad0e7'; - v256d[14].s_row = '63cab7040953d051cd60e0e7ba70e18c'; - v256d[14].s_box = '00102030405060708090a0b0c0d0e0f0'; - v256d[14].k_sch = '000102030405060708090a0b0c0d0e0f'; - v256d[14].output = '00112233445566778899aabbccddeeff'; -})(); diff --git a/src/database/third_party/closure-library/closure/goog/crypt/arc4.js b/src/database/third_party/closure-library/closure/goog/crypt/arc4.js deleted file mode 100644 index 73c67582633..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/arc4.js +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright 2005 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview ARC4 streamcipher implementation. A description of the - * algorithm can be found at: - * http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt. - * - * Usage: - * - * var arc4 = new goog.crypt.Arc4(); - * arc4.setKey(key); - * arc4.discard(1536); - * arc4.crypt(bytes); - * - * - * Note: For converting between strings and byte arrays, goog.crypt.base64 may - * be useful. - * - */ - -goog.provide('goog.crypt.Arc4'); - -goog.require('goog.asserts'); - - - -/** - * ARC4 streamcipher implementation. - * @constructor - * @final - * @struct - */ -goog.crypt.Arc4 = function() { - /** - * A permutation of all 256 possible bytes. - * @type {Array} - * @private - */ - this.state_ = []; - - /** - * 8 bit index pointer into this.state_. - * @type {number} - * @private - */ - this.index1_ = 0; - - /** - * 8 bit index pointer into this.state_. - * @type {number} - * @private - */ - this.index2_ = 0; -}; - - -/** - * Initialize the cipher for use with new key. - * @param {Array} key A byte array containing the key. - * @param {number=} opt_length Indicates # of bytes to take from the key. - */ -goog.crypt.Arc4.prototype.setKey = function(key, opt_length) { - goog.asserts.assertArray(key, 'Key parameter must be a byte array'); - - if (!opt_length) { - opt_length = key.length; - } - - var state = this.state_; - - for (var i = 0; i < 256; ++i) { - state[i] = i; - } - - var j = 0; - for (var i = 0; i < 256; ++i) { - j = (j + state[i] + key[i % opt_length]) & 255; - - var tmp = state[i]; - state[i] = state[j]; - state[j] = tmp; - } - - this.index1_ = 0; - this.index2_ = 0; -}; - - -/** - * Discards n bytes of the keystream. - * These days 1536 is considered a decent amount to drop to get the key state - * warmed-up enough for secure usage. This is not done in the constructor to - * preserve efficiency for use cases that do not need this. - * NOTE: Discard is identical to crypt without actually xoring any data. It's - * unfortunate to have this code duplicated, but this was done for performance - * reasons. Alternatives which were attempted: - * 1. Create a temp array of the correct length and pass it to crypt. This - * works but needlessly allocates an array. But more importantly this - * requires choosing an array type (Array or Uint8Array) in discard, and - * choosing a different type than will be passed to crypt by the client - * code hurts the javascript engines ability to optimize crypt (7x hit in - * v8). - * 2. Make data option in crypt so discard can pass null, this has a huge - * perf hit for crypt. - * @param {number} length Number of bytes to disregard from the stream. - */ -goog.crypt.Arc4.prototype.discard = function(length) { - var i = this.index1_; - var j = this.index2_; - var state = this.state_; - - for (var n = 0; n < length; ++n) { - i = (i + 1) & 255; - j = (j + state[i]) & 255; - - var tmp = state[i]; - state[i] = state[j]; - state[j] = tmp; - } - - this.index1_ = i; - this.index2_ = j; -}; - - -/** - * En- or decrypt (same operation for streamciphers like ARC4) - * @param {Array|Uint8Array} data The data to be xor-ed in place. - * @param {number=} opt_length The number of bytes to crypt. - */ -goog.crypt.Arc4.prototype.crypt = function(data, opt_length) { - if (!opt_length) { - opt_length = data.length; - } - var i = this.index1_; - var j = this.index2_; - var state = this.state_; - - for (var n = 0; n < opt_length; ++n) { - i = (i + 1) & 255; - j = (j + state[i]) & 255; - - var tmp = state[i]; - state[i] = state[j]; - state[j] = tmp; - - data[n] ^= state[(state[i] + state[j]) & 255]; - } - - this.index1_ = i; - this.index2_ = j; -}; diff --git a/src/database/third_party/closure-library/closure/goog/crypt/arc4_test.html b/src/database/third_party/closure-library/closure/goog/crypt/arc4_test.html deleted file mode 100644 index 33953163934..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/arc4_test.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - Closure Unit Tests - goog.crypt.arc4 - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/crypt/arc4_test.js b/src/database/third_party/closure-library/closure/goog/crypt/arc4_test.js deleted file mode 100644 index 856f4f93325..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/arc4_test.js +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2010 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.crypt.Arc4Test'); -goog.setTestOnly('goog.crypt.Arc4Test'); - -goog.require('goog.array'); -goog.require('goog.crypt.Arc4'); -goog.require('goog.testing.jsunit'); - -function testEncryptionDecryption() { - var key = [0x25, 0x26, 0x27, 0x28]; - var startArray = [0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67]; - var byteArray = [0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67]; - - var arc4 = new goog.crypt.Arc4(); - arc4.setKey(key); - arc4.crypt(byteArray); - - assertArrayEquals(byteArray, [0x51, 0xBB, 0xDD, 0x95, 0x9B, 0x42, 0x34]); - - // The same key and crypt call should unencrypt the data back to its original - // state - arc4 = new goog.crypt.Arc4(); - arc4.setKey(key); - arc4.crypt(byteArray); - assertArrayEquals(byteArray, startArray); -} - -function testDiscard() { - var key = [0x25, 0x26, 0x27, 0x28]; - var data = [0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67]; - - var arc4 = new goog.crypt.Arc4(); - arc4.setKey(key); - arc4.discard(256); - var withDiscard = goog.array.clone(data); - arc4.crypt(withDiscard); - - // First encrypting a dummy array should give the same result as - // discarding. - arc4 = new goog.crypt.Arc4(); - arc4.setKey(key); - var withCrypt = goog.array.clone(data); - arc4.crypt(new Array(256)); - arc4.crypt(withCrypt); - assertArrayEquals(withDiscard, withCrypt); -} diff --git a/src/database/third_party/closure-library/closure/goog/crypt/base64.js b/src/database/third_party/closure-library/closure/goog/crypt/base64.js deleted file mode 100644 index 9103fa177e8..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/base64.js +++ /dev/null @@ -1,286 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Base64 en/decoding. Not much to say here except that we - * work with decoded values in arrays of bytes. By "byte" I mean a number - * in [0, 255]. - * - * @author doughtie@google.com (Gavin Doughtie) - */ - -goog.provide('goog.crypt.base64'); -goog.require('goog.crypt'); -goog.require('goog.userAgent'); - -// Static lookup maps, lazily populated by init_() - - -/** - * Maps bytes to characters. - * @type {Object} - * @private - */ -goog.crypt.base64.byteToCharMap_ = null; - - -/** - * Maps characters to bytes. - * @type {Object} - * @private - */ -goog.crypt.base64.charToByteMap_ = null; - - -/** - * Maps bytes to websafe characters. - * @type {Object} - * @private - */ -goog.crypt.base64.byteToCharMapWebSafe_ = null; - - -/** - * Maps websafe characters to bytes. - * @type {Object} - * @private - */ -goog.crypt.base64.charToByteMapWebSafe_ = null; - - -/** - * Our default alphabet, shared between - * ENCODED_VALS and ENCODED_VALS_WEBSAFE - * @type {string} - */ -goog.crypt.base64.ENCODED_VALS_BASE = - 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + - 'abcdefghijklmnopqrstuvwxyz' + - '0123456789'; - - -/** - * Our default alphabet. Value 64 (=) is special; it means "nothing." - * @type {string} - */ -goog.crypt.base64.ENCODED_VALS = - goog.crypt.base64.ENCODED_VALS_BASE + '+/='; - - -/** - * Our websafe alphabet. - * @type {string} - */ -goog.crypt.base64.ENCODED_VALS_WEBSAFE = - goog.crypt.base64.ENCODED_VALS_BASE + '-_.'; - - -/** - * Whether this browser supports the atob and btoa functions. This extension - * started at Mozilla but is now implemented by many browsers. We use the - * ASSUME_* variables to avoid pulling in the full useragent detection library - * but still allowing the standard per-browser compilations. - * - * @type {boolean} - */ -goog.crypt.base64.HAS_NATIVE_SUPPORT = goog.userAgent.GECKO || - goog.userAgent.WEBKIT || - goog.userAgent.OPERA || - typeof(goog.global.atob) == 'function'; - - -/** - * Base64-encode an array of bytes. - * - * @param {Array|Uint8Array} input An array of bytes (numbers with - * value in [0, 255]) to encode. - * @param {boolean=} opt_webSafe Boolean indicating we should use the - * alternative alphabet. - * @return {string} The base64 encoded string. - */ -goog.crypt.base64.encodeByteArray = function(input, opt_webSafe) { - if (!goog.isArrayLike(input)) { - throw Error('encodeByteArray takes an array as a parameter'); - } - - goog.crypt.base64.init_(); - - var byteToCharMap = opt_webSafe ? - goog.crypt.base64.byteToCharMapWebSafe_ : - goog.crypt.base64.byteToCharMap_; - - var output = []; - - for (var i = 0; i < input.length; i += 3) { - var byte1 = input[i]; - var haveByte2 = i + 1 < input.length; - var byte2 = haveByte2 ? input[i + 1] : 0; - var haveByte3 = i + 2 < input.length; - var byte3 = haveByte3 ? input[i + 2] : 0; - - var outByte1 = byte1 >> 2; - var outByte2 = ((byte1 & 0x03) << 4) | (byte2 >> 4); - var outByte3 = ((byte2 & 0x0F) << 2) | (byte3 >> 6); - var outByte4 = byte3 & 0x3F; - - if (!haveByte3) { - outByte4 = 64; - - if (!haveByte2) { - outByte3 = 64; - } - } - - output.push(byteToCharMap[outByte1], - byteToCharMap[outByte2], - byteToCharMap[outByte3], - byteToCharMap[outByte4]); - } - - return output.join(''); -}; - - -/** - * Base64-encode a string. - * - * @param {string} input A string to encode. - * @param {boolean=} opt_webSafe If true, we should use the - * alternative alphabet. - * @return {string} The base64 encoded string. - */ -goog.crypt.base64.encodeString = function(input, opt_webSafe) { - // Shortcut for Mozilla browsers that implement - // a native base64 encoder in the form of "btoa/atob" - if (goog.crypt.base64.HAS_NATIVE_SUPPORT && !opt_webSafe) { - return goog.global.btoa(input); - } - return goog.crypt.base64.encodeByteArray( - goog.crypt.stringToByteArray(input), opt_webSafe); -}; - - -/** - * Base64-decode a string. - * - * @param {string} input to decode. - * @param {boolean=} opt_webSafe True if we should use the - * alternative alphabet. - * @return {string} string representing the decoded value. - */ -goog.crypt.base64.decodeString = function(input, opt_webSafe) { - // Shortcut for Mozilla browsers that implement - // a native base64 encoder in the form of "btoa/atob" - if (goog.crypt.base64.HAS_NATIVE_SUPPORT && !opt_webSafe) { - return goog.global.atob(input); - } - return goog.crypt.byteArrayToString( - goog.crypt.base64.decodeStringToByteArray(input, opt_webSafe)); -}; - - -/** - * Base64-decode a string. - * - * In base-64 decoding, groups of four characters are converted into three - * bytes. If the encoder did not apply padding, the input length may not - * be a multiple of 4. - * - * In this case, the last group will have fewer than 4 characters, and - * padding will be inferred. If the group has one or two characters, it decodes - * to one byte. If the group has three characters, it decodes to two bytes. - * - * @param {string} input Input to decode. - * @param {boolean=} opt_webSafe True if we should use the web-safe alphabet. - * @return {!Array} bytes representing the decoded value. - */ -goog.crypt.base64.decodeStringToByteArray = function(input, opt_webSafe) { - goog.crypt.base64.init_(); - - var charToByteMap = opt_webSafe ? - goog.crypt.base64.charToByteMapWebSafe_ : - goog.crypt.base64.charToByteMap_; - - var output = []; - - for (var i = 0; i < input.length; ) { - var byte1 = charToByteMap[input.charAt(i++)]; - - var haveByte2 = i < input.length; - var byte2 = haveByte2 ? charToByteMap[input.charAt(i)] : 0; - ++i; - - var haveByte3 = i < input.length; - var byte3 = haveByte3 ? charToByteMap[input.charAt(i)] : 64; - ++i; - - var haveByte4 = i < input.length; - var byte4 = haveByte4 ? charToByteMap[input.charAt(i)] : 64; - ++i; - - if (byte1 == null || byte2 == null || - byte3 == null || byte4 == null) { - throw Error(); - } - - var outByte1 = (byte1 << 2) | (byte2 >> 4); - output.push(outByte1); - - if (byte3 != 64) { - var outByte2 = ((byte2 << 4) & 0xF0) | (byte3 >> 2); - output.push(outByte2); - - if (byte4 != 64) { - var outByte3 = ((byte3 << 6) & 0xC0) | byte4; - output.push(outByte3); - } - } - } - - return output; -}; - - -/** - * Lazy static initialization function. Called before - * accessing any of the static map variables. - * @private - */ -goog.crypt.base64.init_ = function() { - if (!goog.crypt.base64.byteToCharMap_) { - goog.crypt.base64.byteToCharMap_ = {}; - goog.crypt.base64.charToByteMap_ = {}; - goog.crypt.base64.byteToCharMapWebSafe_ = {}; - goog.crypt.base64.charToByteMapWebSafe_ = {}; - - // We want quick mappings back and forth, so we precompute two maps. - for (var i = 0; i < goog.crypt.base64.ENCODED_VALS.length; i++) { - goog.crypt.base64.byteToCharMap_[i] = - goog.crypt.base64.ENCODED_VALS.charAt(i); - goog.crypt.base64.charToByteMap_[goog.crypt.base64.byteToCharMap_[i]] = i; - goog.crypt.base64.byteToCharMapWebSafe_[i] = - goog.crypt.base64.ENCODED_VALS_WEBSAFE.charAt(i); - goog.crypt.base64.charToByteMapWebSafe_[ - goog.crypt.base64.byteToCharMapWebSafe_[i]] = i; - - // Be forgiving when decoding and correctly decode both encodings. - if (i >= goog.crypt.base64.ENCODED_VALS_BASE.length) { - goog.crypt.base64.charToByteMap_[ - goog.crypt.base64.ENCODED_VALS_WEBSAFE.charAt(i)] = i; - goog.crypt.base64.charToByteMapWebSafe_[ - goog.crypt.base64.ENCODED_VALS.charAt(i)] = i; - } - } - } -}; diff --git a/src/database/third_party/closure-library/closure/goog/crypt/base64_test.html b/src/database/third_party/closure-library/closure/goog/crypt/base64_test.html deleted file mode 100644 index 27db42c38e5..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/base64_test.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - Closure Unit Tests - goog.crypt.base64 - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/crypt/base64_test.js b/src/database/third_party/closure-library/closure/goog/crypt/base64_test.js deleted file mode 100644 index c4946884e0f..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/base64_test.js +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.crypt.base64Test'); -goog.setTestOnly('goog.crypt.base64Test'); - -goog.require('goog.crypt'); -goog.require('goog.crypt.base64'); -goog.require('goog.testing.jsunit'); - -// Static test data -var tests = [ - '', '', - 'f', 'Zg==', - 'fo', 'Zm8=', - 'foo', 'Zm9v', - 'foob', 'Zm9vYg==', - 'fooba', 'Zm9vYmE=', - 'foobar', 'Zm9vYmFy', - - // Testing non-ascii characters (1-10 in chinese) - '\xe4\xb8\x80\xe4\xba\x8c\xe4\xb8\x89\xe5\x9b\x9b\xe4\xba\x94\xe5' + - '\x85\xad\xe4\xb8\x83\xe5\x85\xab\xe4\xb9\x9d\xe5\x8d\x81', - '5LiA5LqM5LiJ5Zub5LqU5YWt5LiD5YWr5Lmd5Y2B']; - -function testByteArrayEncoding() { - // Let's see if it's sane by feeding it some well-known values. Index i - // has the input and index i+1 has the expected value. - for (var i = 0; i < tests.length; i += 2) { - var enc = goog.crypt.base64.encodeByteArray( - goog.crypt.stringToByteArray(tests[i])); - assertEquals(tests[i + 1], enc); - var dec = goog.crypt.byteArrayToString( - goog.crypt.base64.decodeStringToByteArray(enc)); - assertEquals(tests[i], dec); - - // Check that websafe decoding accepts non-websafe codes. - dec = goog.crypt.byteArrayToString( - goog.crypt.base64.decodeStringToByteArray(enc, true /* websafe */)); - assertEquals(tests[i], dec); - - // Re-encode as websafe. - enc = goog.crypt.base64.encodeByteArray( - goog.crypt.stringToByteArray(tests[i], true /* websafe */)); - - // Check that non-websafe decoding accepts websafe codes. - dec = goog.crypt.byteArrayToString( - goog.crypt.base64.decodeStringToByteArray(enc)); - assertEquals(tests[i], dec); - - // Check that websafe decoding accepts websafe codes. - dec = goog.crypt.byteArrayToString( - goog.crypt.base64.decodeStringToByteArray(enc, true /* websafe */)); - assertEquals(tests[i], dec); - } -} - -function testOddLengthByteArrayEncoding() { - var buffer = [0, 0, 0]; - var encodedBuffer = goog.crypt.base64.encodeByteArray(buffer); - assertEquals('AAAA', encodedBuffer); - - var decodedBuffer = goog.crypt.base64.decodeStringToByteArray(encodedBuffer); - assertEquals(decodedBuffer.length, buffer.length); - for (i = 0; i < buffer.length; i++) { - assertEquals(buffer[i], decodedBuffer[i]); - } -} - -// Tests that decoding a string where the length is not a multiple of 4 does -// not produce spurious trailing zeroes. This is a regression test for -// cl/65120705, which fixes a bug that was introduced when support for -// non-padded base64 encoding was added in cl/20209336. -function testOddLengthByteArrayDecoding() { - // The base-64 encoding of the bytes [97, 98, 99, 100], with no padding. - // The padded version would be "YWJjZA==" (length 8), or "YWJjZA.." if - // web-safe. - var encodedBuffer = 'YWJjZA'; - var decodedBuffer1 = goog.crypt.base64.decodeStringToByteArray(encodedBuffer); - assertEquals(4, decodedBuffer1.length); - // Note that byteArrayToString ignores any trailing zeroes because - // String.fromCharCode(0) is ''. - assertEquals('abcd', goog.crypt.byteArrayToString(decodedBuffer1)); - - // Repeat the test in web-safe decoding mode. - var decodedBuffer2 = goog.crypt.base64.decodeStringToByteArray(encodedBuffer, - true /* web-safe */); - assertEquals(4, decodedBuffer2.length); - assertEquals('abcd', goog.crypt.byteArrayToString(decodedBuffer2)); -} - -function testShortcutPathEncoding() { - // Test the higher-level API (tests the btoa/atob shortcut path) - for (var i = 0; i < tests.length; i += 2) { - var enc = goog.crypt.base64.encodeString(tests[i]); - assertEquals(tests[i + 1], enc); - var dec = goog.crypt.base64.decodeString(enc); - assertEquals(tests[i], dec); - } -} - -function testMultipleIterations() { - // Now run it through its paces - - var numIterations = 100; - for (var i = 0; i < numIterations; i++) { - - var input = []; - for (var j = 0; j < i; j++) - input[j] = j % 256; - - var encoded = goog.crypt.base64.encodeByteArray(input); - var decoded = goog.crypt.base64.decodeStringToByteArray(encoded); - assertEquals('Decoded length not equal to input length?', - input.length, decoded.length); - - for (var j = 0; j < i; j++) - assertEquals('Values differ at position ' + j, input[j], decoded[j]); - } -} - -function testWebSafeEncoding() { - // Test non-websafe / websafe difference - var test = '>>>???>>>???=/+'; - var enc = goog.crypt.base64.encodeByteArray( - goog.crypt.stringToByteArray(test)); - assertEquals('Non-websafe broken?', 'Pj4+Pz8/Pj4+Pz8/PS8r', enc); - enc = goog.crypt.base64.encodeString(test); - assertEquals('Non-websafe broken?', 'Pj4+Pz8/Pj4+Pz8/PS8r', enc); - enc = goog.crypt.base64.encodeByteArray( - goog.crypt.stringToByteArray(test), true /* websafe */); - assertEquals('Websafe encoding broken', 'Pj4-Pz8_Pj4-Pz8_PS8r', enc); - enc = goog.crypt.base64.encodeString(test, true); - assertEquals('Non-websafe broken?', 'Pj4-Pz8_Pj4-Pz8_PS8r', enc); - var dec = goog.crypt.byteArrayToString( - goog.crypt.base64.decodeStringToByteArray(enc, true /* websafe */)); - assertEquals('Websafe decoding broken', test, dec); - dec = goog.crypt.base64.decodeString(enc, true /* websafe */); - assertEquals('Websafe decoding broken', test, dec); - - // Test parsing malformed characters - assertThrows('Didn\'t throw on malformed input', function() { - goog.crypt.base64.decodeStringToByteArray('foooooo)oooo', true /*websafe*/); - }); -} diff --git a/src/database/third_party/closure-library/closure/goog/crypt/basen.js b/src/database/third_party/closure-library/closure/goog/crypt/basen.js deleted file mode 100644 index 2bac248f8db..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/basen.js +++ /dev/null @@ -1,242 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Numeric base conversion library. Works for arbitrary bases and - * arbitrary length numbers. - * - * For base-64 conversion use base64.js because it is optimized for the specific - * conversion to base-64 while this module is generic. Base-64 is defined here - * mostly for demonstration purpose. - * - * TODO: Make base64 and baseN classes that have common interface. (Perhaps...) - * - */ - -goog.provide('goog.crypt.baseN'); - - -/** - * Base-2, i.e. '01'. - * @type {string} - */ -goog.crypt.baseN.BASE_BINARY = '01'; - - -/** - * Base-8, i.e. '01234567'. - * @type {string} - */ -goog.crypt.baseN.BASE_OCTAL = '01234567'; - - -/** - * Base-10, i.e. '0123456789'. - * @type {string} - */ -goog.crypt.baseN.BASE_DECIMAL = '0123456789'; - - -/** - * Base-16 using lower case, i.e. '0123456789abcdef'. - * @type {string} - */ -goog.crypt.baseN.BASE_LOWERCASE_HEXADECIMAL = '0123456789abcdef'; - - -/** - * Base-16 using upper case, i.e. '0123456789ABCDEF'. - * @type {string} - */ -goog.crypt.baseN.BASE_UPPERCASE_HEXADECIMAL = '0123456789ABCDEF'; - - -/** - * The more-known version of the BASE-64 encoding. Uses + and / characters. - * @type {string} - */ -goog.crypt.baseN.BASE_64 = - 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; - - -/** - * URL-safe version of the BASE-64 encoding. - * @type {string} - */ -goog.crypt.baseN.BASE_64_URL_SAFE = - 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'; - - -/** - * Converts a number from one numeric base to another. - * - * The bases are represented as strings, which list allowed digits. Each digit - * should be unique. The bases can either be user defined, or any of - * goog.crypt.baseN.BASE_xxx. - * - * The number is in human-readable format, most significant digit first, and is - * a non-negative integer. Base designators such as $, 0x, d, b or h (at end) - * will be interpreted as digits, so avoid them. Leading zeros will be trimmed. - * - * Note: for huge bases the result may be inaccurate because of overflowing - * 64-bit doubles used by JavaScript for integer calculus. This may happen - * if the product of the number of digits in the input and output bases comes - * close to 10^16, which is VERY unlikely (100M digits in each base), but - * may be possible in the future unicode world. (Unicode 3.2 has less than 100K - * characters. However, it reserves some more, close to 1M.) - * - * @param {string} number The number to convert. - * @param {string} inputBase The numeric base the number is in (all digits). - * @param {string} outputBase Requested numeric base. - * @return {string} The converted number. - */ -goog.crypt.baseN.recodeString = function(number, inputBase, outputBase) { - if (outputBase == '') { - throw Error('Empty output base'); - } - - // Check if number is 0 (special case when we don't want to return ''). - var isZero = true; - for (var i = 0, n = number.length; i < n; i++) { - if (number.charAt(i) != inputBase.charAt(0)) { - isZero = false; - break; - } - } - if (isZero) { - return outputBase.charAt(0); - } - - var numberDigits = goog.crypt.baseN.stringToArray_(number, inputBase); - - var inputBaseSize = inputBase.length; - var outputBaseSize = outputBase.length; - - // result = 0. - var result = []; - - // For all digits of number, starting with the most significant ... - for (var i = numberDigits.length - 1; i >= 0; i--) { - - // result *= number.base. - var carry = 0; - for (var j = 0, n = result.length; j < n; j++) { - var digit = result[j]; - // This may overflow for huge bases. See function comment. - digit = digit * inputBaseSize + carry; - if (digit >= outputBaseSize) { - var remainder = digit % outputBaseSize; - carry = (digit - remainder) / outputBaseSize; - digit = remainder; - } else { - carry = 0; - } - result[j] = digit; - } - while (carry) { - var remainder = carry % outputBaseSize; - result.push(remainder); - carry = (carry - remainder) / outputBaseSize; - } - - // result += number[i]. - carry = numberDigits[i]; - var j = 0; - while (carry) { - if (j >= result.length) { - // Extend result with a leading zero which will be overwritten below. - result.push(0); - } - var digit = result[j]; - digit += carry; - if (digit >= outputBaseSize) { - var remainder = digit % outputBaseSize; - carry = (digit - remainder) / outputBaseSize; - digit = remainder; - } else { - carry = 0; - } - result[j] = digit; - j++; - } - } - - return goog.crypt.baseN.arrayToString_(result, outputBase); -}; - - -/** - * Converts a string representation of a number to an array of digit values. - * - * More precisely, the digit values are indices into the number base, which - * is represented as a string, which can either be user defined or one of the - * BASE_xxx constants. - * - * Throws an Error if the number contains a digit not found in the base. - * - * @param {string} number The string to convert, most significant digit first. - * @param {string} base Digits in the base. - * @return {!Array} Array of digit values, least significant digit - * first. - * @private - */ -goog.crypt.baseN.stringToArray_ = function(number, base) { - var index = {}; - for (var i = 0, n = base.length; i < n; i++) { - index[base.charAt(i)] = i; - } - var result = []; - for (var i = number.length - 1; i >= 0; i--) { - var character = number.charAt(i); - var digit = index[character]; - if (typeof digit == 'undefined') { - throw Error('Number ' + number + - ' contains a character not found in base ' + - base + ', which is ' + character); - } - result.push(digit); - } - return result; -}; - - -/** - * Converts an array representation of a number to a string. - * - * More precisely, the elements of the input array are indices into the base, - * which is represented as a string, which can either be user defined or one of - * the BASE_xxx constants. - * - * Throws an Error if the number contains a digit which is outside the range - * 0 ... base.length - 1. - * - * @param {Array} number Array of digit values, least significant - * first. - * @param {string} base Digits in the base. - * @return {string} Number as a string, most significant digit first. - * @private - */ -goog.crypt.baseN.arrayToString_ = function(number, base) { - var n = number.length; - var chars = []; - var baseSize = base.length; - for (var i = n - 1; i >= 0; i--) { - var digit = number[i]; - if (digit >= baseSize || digit < 0) { - throw Error('Number ' + number + ' contains an invalid digit: ' + digit); - } - chars.push(base.charAt(digit)); - } - return chars.join(''); -}; diff --git a/src/database/third_party/closure-library/closure/goog/crypt/basen_test.html b/src/database/third_party/closure-library/closure/goog/crypt/basen_test.html deleted file mode 100644 index c29a7cd4354..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/basen_test.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - Closure Unit Tests - goog.crypt.baseN - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/crypt/basen_test.js b/src/database/third_party/closure-library/closure/goog/crypt/basen_test.js deleted file mode 100644 index bf6339787fd..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/basen_test.js +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Tests for arbitrary base conversion library baseconversion.js. - */ - -goog.provide('goog.crypt.baseNTest'); -goog.setTestOnly('goog.crypt.baseNTest'); - -goog.require('goog.crypt.baseN'); -goog.require('goog.testing.jsunit'); - -function testDecToHex() { - verifyConversion(goog.crypt.baseN.BASE_DECIMAL, '0', - goog.crypt.baseN.BASE_LOWERCASE_HEXADECIMAL, '0'); - verifyConversion(goog.crypt.baseN.BASE_DECIMAL, '9', - goog.crypt.baseN.BASE_UPPERCASE_HEXADECIMAL, '9'); - verifyConversion(goog.crypt.baseN.BASE_DECIMAL, '13', - goog.crypt.baseN.BASE_LOWERCASE_HEXADECIMAL, 'd'); - verifyConversion(goog.crypt.baseN.BASE_DECIMAL, '255', - goog.crypt.baseN.BASE_UPPERCASE_HEXADECIMAL, 'FF'); - verifyConversion(goog.crypt.baseN.BASE_DECIMAL, - '53425987345897', - goog.crypt.baseN.BASE_LOWERCASE_HEXADECIMAL, - '309734ff5de9'); - verifyConversion(goog.crypt.baseN.BASE_DECIMAL, - '987080888', - goog.crypt.baseN.BASE_UPPERCASE_HEXADECIMAL, - '3AD5A8B8'); - verifyConversion(goog.crypt.baseN.BASE_DECIMAL, - '009341587237', - goog.crypt.baseN.BASE_LOWERCASE_HEXADECIMAL, - '22ccd4f25'); -} - -function testBinToDec() { - verifyConversion( - goog.crypt.baseN.BASE_BINARY, - '11101010101000100010010000010010010000111101000100110111000000100001' + - '01100100111110110010000010110100111101000010010100001011111011111100' + - '00000010000010000101010101000000000101100000000100011111011101111001' + - '10000001000000000100101110001001001101101001101111010101111100010001' + - '11011100000110111000000100111011100100010010011001111011001111001011' + - '10001000101111001010011101101100110110011110010000011100101011110010' + - '11010001001111110011000000001001011011111011010000110011010000010111' + - '10111100000001100010111100000100000000110001011101011110100000011010' + - '0110000100011111', - goog.crypt.baseN.BASE_DECIMAL, - '34589745906769047354795784390596748934723904739085568907689045723489' + - '05745789789078907890789023447892365623589745678902348976234598723459' + - '087523496723486089723459078349087'); -} - -function testDecToBin() { - verifyConversion( - goog.crypt.baseN.BASE_DECIMAL, - '00342589674590347859734908573490568347534805468907960579056785605496' + - '83475873465859072390486756098742380573908572390463805745656623475234' + - '82345670247851902784123897349486238502378940637925807378946358964328' + - '57906148572346857346409823758034763928401296023947234784623765456367' + - '764623627623574', - goog.crypt.baseN.BASE_BINARY, - '10010011011100101010001111100111001100110000110111111110010110101000' + - '01010110110010000111000001100110100101010000101001100001011000101111' + - '01011101111100101101010010000111011110011110010101111001110010100100' + - '10111110000101111011010000000111111011110010011110101011100101000001' + - '00011000101010011001101000011101001010001101011110101001011011100101' + - '11100000101000010010101001011001100100101110111101010000011010001010' + - '01011100100111110001100111100100011001001001100011011100100111011111' + - '01000100101001000100110001011010010000011010111101111111111111110100' + - '01100101001111001111100110101000001100100000111111100101110010111011' + - '10110110001100100011101010110110100001001000101011001001100011010110' + - '10110100000110000110010111110100000100110110010010010101111001001111' + - '11100100000010101111110100011010011101011010001101110011100110111111' + - '11000100001111010000000101011011000010010000000100111111010110111100' + - '00101111010011011010011010010001000101100001111001110010010110'); -} - -function test7To9() { - verifyConversion( - '0123456', // Base 7. - '60625646056660665666066534602566346056634560665606666656465634265434' + - '66563465664566346406366534664656650660665623456663456654360665', - '012345678', // Base 9. - '11451222686557606458341381287142358175337801548087003804852781764284' + - '273762357630423116743334671762638240652740158536'); -} - -function testZeros() { - verifyConversion(goog.crypt.baseN.BASE_DECIMAL, '0', - goog.crypt.baseN.BASE_LOWERCASE_HEXADECIMAL, '0'); - verifyConversion(goog.crypt.baseN.BASE_DECIMAL, '000', - goog.crypt.baseN.BASE_LOWERCASE_HEXADECIMAL, '0'); - verifyConversion(goog.crypt.baseN.BASE_DECIMAL, '0000007', - goog.crypt.baseN.BASE_LOWERCASE_HEXADECIMAL, '7'); -} - -function testArbitraryBases() { - verifyConversion('X9(', // Base 3. - '9(XX((9X(XX9(9X9(X9(', - 'a:*o9', // Base 5. - ':oa**:9o9**9oo'); -} - -function testEmptyBases() { - var e = assertThrows(function() { - goog.crypt.baseN.recodeString('1230', '', '0123'); - }); - assertEquals('Exception message', 'Number 1230 contains a character ' + - 'not found in base , which is 0', e.message); - - e = assertThrows(function() { - goog.crypt.baseN.recodeString('1230', '0123', ''); - }); - assertEquals('Exception message', 'Empty output base', e.message); -} - -function testInvalidDigits() { - var e = assertThrows(function() { - goog.crypt.baseN.recodeString('123x456', '01234567', '01234567'); - }); - assertEquals('Exception message', 'Number 123x456 contains a character ' + - 'not found in base 01234567, which is x', e.message); -} - -function makeHugeBase() { - // Number of digits in the base. - // Tests break if this is set to 200'000. The reason for that is - // String.fromCharCode(196609) == String.fromCharCode(1). - var baseSize = 20000; - var tab = []; - for (var i = 0; i < baseSize; i++) { - tab.push(String.fromCharCode(i)); - } - return tab.join(''); -} - -function testHugeInputBase() { - verifyConversion(makeHugeBase(), String.fromCharCode(12345), - goog.crypt.baseN.BASE_DECIMAL, '12345'); -} - -function testHugeOutputBase() { - verifyConversion(goog.crypt.baseN.BASE_DECIMAL, '12345', - makeHugeBase(), String.fromCharCode(12345)); -} - -function verifyConversion(inputBase, inputNumber, outputBase, outputNumber) { - assertEquals(outputNumber, - goog.crypt.baseN.recodeString(inputNumber, - inputBase, - outputBase)); -} diff --git a/src/database/third_party/closure-library/closure/goog/crypt/blobhasher.js b/src/database/third_party/closure-library/closure/goog/crypt/blobhasher.js deleted file mode 100644 index 2f2613696c2..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/blobhasher.js +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright 2011 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Asynchronous hash computer for the Blob interface. - * - * The Blob interface, part of the HTML5 File API, is supported on Chrome 7+, - * Firefox 4.0 and Opera 11. No Blob interface implementation is expected on - * Internet Explorer 10. Chrome 11, Firefox 5.0 and the subsequent release of - * Opera are supposed to use vendor prefixes due to evolving API, see - * http://dev.w3.org/2006/webapi/FileAPI/ for details. - * - * This implementation currently uses upcoming Chrome and Firefox prefixes, - * plus the original Blob.slice specification, as implemented on Chrome 10 - * and Firefox 4.0. - * - */ - -goog.provide('goog.crypt.BlobHasher'); -goog.provide('goog.crypt.BlobHasher.EventType'); - -goog.require('goog.asserts'); -goog.require('goog.events.EventTarget'); -goog.require('goog.fs'); -goog.require('goog.log'); - - - -/** - * Construct the hash computer. - * - * @param {!goog.crypt.Hash} hashFn The hash function to use. - * @param {number=} opt_blockSize Processing block size. - * @constructor - * @extends {goog.events.EventTarget} - * @final - */ -goog.crypt.BlobHasher = function(hashFn, opt_blockSize) { - goog.crypt.BlobHasher.base(this, 'constructor'); - - /** - * The actual hash function. - * @type {!goog.crypt.Hash} - * @private - */ - this.hashFn_ = hashFn; - - /** - * The blob being processed or null if no blob is being processed. - * @type {Blob} - * @private - */ - this.blob_ = null; - - /** - * Computed hash value. - * @type {Array} - * @private - */ - this.hashVal_ = null; - - /** - * Number of bytes already processed. - * @type {number} - * @private - */ - this.bytesProcessed_ = 0; - - /** - * The number of bytes to hash or Infinity for no limit. - * @type {number} - * @private - */ - this.hashingLimit_ = Infinity; - - /** - * Processing block size. - * @type {number} - * @private - */ - this.blockSize_ = opt_blockSize || 5000000; - - /** - * File reader object. Will be null if no chunk is currently being read. - * @type {FileReader} - * @private - */ - this.fileReader_ = null; - - /** - * The logger used by this object. - * @type {goog.log.Logger} - * @private - */ - this.logger_ = goog.log.getLogger('goog.crypt.BlobHasher'); -}; -goog.inherits(goog.crypt.BlobHasher, goog.events.EventTarget); - - -/** - * Event names for hash computation events - * @enum {string} - */ -goog.crypt.BlobHasher.EventType = { - STARTED: 'started', - PROGRESS: 'progress', - THROTTLED: 'throttled', - COMPLETE: 'complete', - ABORT: 'abort', - ERROR: 'error' -}; - - -/** - * Start the hash computation. - * @param {!Blob} blob The blob of data to compute the hash for. - */ -goog.crypt.BlobHasher.prototype.hash = function(blob) { - this.abort(); - this.hashFn_.reset(); - this.blob_ = blob; - this.hashVal_ = null; - this.bytesProcessed_ = 0; - this.dispatchEvent(goog.crypt.BlobHasher.EventType.STARTED); - - this.processNextBlock_(); -}; - - -/** - * Sets the maximum number of bytes to hash or Infinity for no limit. Can be - * called before hash() to throttle the hash computation. The hash computation - * can then be continued by repeatedly calling setHashingLimit() with greater - * byte offsets. This is useful if you don't need the hash until some time in - * the future, for example when uploading a file and you don't need the hash - * until the transfer is complete. - * @param {number} byteOffset The byte offset to compute the hash up to. - * Should be a non-negative integer or Infinity for no limit. Negative - * values are not allowed. - */ -goog.crypt.BlobHasher.prototype.setHashingLimit = function(byteOffset) { - goog.asserts.assert(byteOffset >= 0, 'Hashing limit must be non-negative.'); - this.hashingLimit_ = byteOffset; - - // Resume processing if a blob is currently being hashed, but no block read - // is currently in progress. - if (this.blob_ && !this.fileReader_) { - this.processNextBlock_(); - } -}; - - -/** - * Abort hash computation. - */ -goog.crypt.BlobHasher.prototype.abort = function() { - if (this.fileReader_) { - this.fileReader_.abort(); - this.fileReader_ = null; - } - - if (this.blob_) { - this.blob_ = null; - this.dispatchEvent(goog.crypt.BlobHasher.EventType.ABORT); - } -}; - - -/** - * @return {number} Number of bytes processed so far. - */ -goog.crypt.BlobHasher.prototype.getBytesProcessed = function() { - return this.bytesProcessed_; -}; - - -/** - * @return {Array} The computed hash value or null if not ready. - */ -goog.crypt.BlobHasher.prototype.getHash = function() { - return this.hashVal_; -}; - - -/** - * Helper function setting up the processing for the next block, or finalizing - * the computation if all blocks were processed. - * @private - */ -goog.crypt.BlobHasher.prototype.processNextBlock_ = function() { - goog.asserts.assert(this.blob_, 'A hash computation must be in progress.'); - - if (this.bytesProcessed_ < this.blob_.size) { - - if (this.hashingLimit_ <= this.bytesProcessed_) { - // Throttle limit reached. Wait until we are allowed to hash more bytes. - this.dispatchEvent(goog.crypt.BlobHasher.EventType.THROTTLED); - return; - } - - // We have to reset the FileReader every time, otherwise it fails on - // Chrome, including the latest Chrome 12 beta. - // http://code.google.com/p/chromium/issues/detail?id=82346 - this.fileReader_ = new FileReader(); - this.fileReader_.onload = goog.bind(this.onLoad_, this); - this.fileReader_.onerror = goog.bind(this.onError_, this); - - var endOffset = Math.min(this.hashingLimit_, this.blob_.size); - var size = Math.min(endOffset - this.bytesProcessed_, this.blockSize_); - var chunk = goog.fs.sliceBlob(this.blob_, this.bytesProcessed_, - this.bytesProcessed_ + size); - if (!chunk || chunk.size != size) { - goog.log.error(this.logger_, 'Failed slicing the blob'); - this.onError_(); - return; - } - - if (this.fileReader_.readAsArrayBuffer) { - this.fileReader_.readAsArrayBuffer(chunk); - } else if (this.fileReader_.readAsBinaryString) { - this.fileReader_.readAsBinaryString(chunk); - } else { - goog.log.error(this.logger_, 'Failed calling the chunk reader'); - this.onError_(); - } - } else { - this.hashVal_ = this.hashFn_.digest(); - this.blob_ = null; - this.dispatchEvent(goog.crypt.BlobHasher.EventType.COMPLETE); - } -}; - - -/** - * Handle processing block loaded. - * @private - */ -goog.crypt.BlobHasher.prototype.onLoad_ = function() { - goog.log.info(this.logger_, 'Successfully loaded a chunk'); - - var array = null; - if (this.fileReader_.result instanceof Array || - goog.isString(this.fileReader_.result)) { - array = this.fileReader_.result; - } else if (goog.global['ArrayBuffer'] && goog.global['Uint8Array'] && - this.fileReader_.result instanceof ArrayBuffer) { - array = new Uint8Array(this.fileReader_.result); - } - if (!array) { - goog.log.error(this.logger_, 'Failed reading the chunk'); - this.onError_(); - return; - } - - this.hashFn_.update(array); - this.bytesProcessed_ += array.length; - this.fileReader_ = null; - this.dispatchEvent(goog.crypt.BlobHasher.EventType.PROGRESS); - - this.processNextBlock_(); -}; - - -/** - * Handles error. - * @private - */ -goog.crypt.BlobHasher.prototype.onError_ = function() { - this.fileReader_ = null; - this.blob_ = null; - this.dispatchEvent(goog.crypt.BlobHasher.EventType.ERROR); -}; diff --git a/src/database/third_party/closure-library/closure/goog/crypt/blobhasher_test.html b/src/database/third_party/closure-library/closure/goog/crypt/blobhasher_test.html deleted file mode 100644 index d680f81adbf..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/blobhasher_test.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - Closure Unit Tests - goog.crypt.BlobHasher - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/crypt/blobhasher_test.js b/src/database/third_party/closure-library/closure/goog/crypt/blobhasher_test.js deleted file mode 100644 index a9641c50b32..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/blobhasher_test.js +++ /dev/null @@ -1,382 +0,0 @@ -// Copyright 2011 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.crypt.BlobHasherTest'); -goog.setTestOnly('goog.crypt.BlobHasherTest'); - -goog.require('goog.crypt'); -goog.require('goog.crypt.BlobHasher'); -goog.require('goog.crypt.Md5'); -goog.require('goog.events'); -goog.require('goog.testing.PropertyReplacer'); -goog.require('goog.testing.jsunit'); - -// A browser-independent mock of goog.fs.sliceBlob. The actual implementation -// calls the underlying slice method differently based on browser version. -// This mock does not support negative opt_end. -var fsSliceBlobMock = function(blob, start, opt_end) { - if (!goog.isNumber(opt_end)) { - opt_end = blob.size; - } - return blob.slice(start, opt_end); -}; - -// Mock out the Blob using a string. -BlobMock = function(string) { - this.data = string; - this.size = this.data.length; -}; - -BlobMock.prototype.slice = function(start, end) { - return new BlobMock(this.data.substr(start, end - start)); -}; - - -// Mock out the FileReader to have control over the flow. -FileReaderMock = function() { - this.array_ = []; - this.result = null; - this.readyState = this.EMPTY; - - this.onload = null; - this.onabort = null; - this.onerror = null; -}; - -FileReaderMock.prototype.EMPTY = 0; -FileReaderMock.prototype.LOADING = 1; -FileReaderMock.prototype.DONE = 2; - -FileReaderMock.prototype.mockLoad = function() { - this.readyState = this.DONE; - this.result = this.array_; - if (this.onload) { - this.onload.call(); - } -}; - -FileReaderMock.prototype.abort = function() { - this.readyState = this.DONE; - if (this.onabort) { - this.onabort.call(); - } -}; - -FileReaderMock.prototype.mockError = function() { - this.readyState = this.DONE; - if (this.onerror) { - this.onerror.call(); - } -}; - -FileReaderMock.prototype.readAsArrayBuffer = function(blobMock) { - this.readyState = this.LOADING; - this.array_ = []; - for (var i = 0; i < blobMock.size; ++i) { - this.array_[i] = blobMock.data.charCodeAt(i); - } -}; - -FileReaderMock.prototype.isLoading = function() { - return this.readyState == this.LOADING; -}; - -var stubs = new goog.testing.PropertyReplacer(); -function setUp() { - stubs.set(goog.global, 'FileReader', FileReaderMock); - stubs.set(goog.fs, 'sliceBlob', fsSliceBlobMock); -} - -function tearDown() { - stubs.reset(); -} - - -/** - * Makes the blobHasher read chunks from the blob and hash it. The number of - * reads shall not exceed a pre-determined number (typically blob size / chunk - * size) for computing hash. This function fails fast (after maxReads is - * reached), assuming that the hasher failed to generate hashes. This prevents - * the test suite from going into infinite loop. - * @param {!goog.crypt.BlobHasher} blobHasher Hasher in action. - * @param {number} maxReads Max number of read attempts. - */ -function readFromBlob(blobHasher, maxReads) { - var counter = 0; - while (blobHasher.fileReader_ && blobHasher.fileReader_.isLoading() && - counter <= maxReads) { - blobHasher.fileReader_.mockLoad(); - counter++; - } - assertTrue(counter <= maxReads); - return counter; -} - -function testBasicOperations() { - if (!window.Blob) { - return; - } - - // Test hashing with one chunk. - var hashFn = new goog.crypt.Md5(); - var blobHasher = new goog.crypt.BlobHasher(hashFn); - var blob = new BlobMock('The quick brown fox jumps over the lazy dog'); - blobHasher.hash(blob); - readFromBlob(blobHasher, 1); - assertEquals('9e107d9d372bb6826bd81d3542a419d6', - goog.crypt.byteArrayToHex(blobHasher.getHash())); - - // Test hashing with multiple chunks. - blobHasher = new goog.crypt.BlobHasher(hashFn, 7); - blobHasher.hash(blob); - readFromBlob(blobHasher, Math.ceil(blob.size / 7)); - assertEquals('9e107d9d372bb6826bd81d3542a419d6', - goog.crypt.byteArrayToHex(blobHasher.getHash())); - - // Test hashing with no chunks. - blob = new BlobMock(''); - blobHasher.hash(blob); - readFromBlob(blobHasher, 1); - assertEquals('d41d8cd98f00b204e9800998ecf8427e', - goog.crypt.byteArrayToHex(blobHasher.getHash())); - -} - -function testNormalFlow() { - if (!window.Blob) { - return; - } - - // Test the flow with one chunk. - var hashFn = new goog.crypt.Md5(); - var blobHasher = new goog.crypt.BlobHasher(hashFn, 13); - var blob = new BlobMock('short'); - var startedEvents = 0; - var progressEvents = 0; - var completeEvents = 0; - goog.events.listen(blobHasher, goog.crypt.BlobHasher.EventType.STARTED, - function() { ++startedEvents; }); - goog.events.listen(blobHasher, goog.crypt.BlobHasher.EventType.PROGRESS, - function() { ++progressEvents; }); - goog.events.listen(blobHasher, goog.crypt.BlobHasher.EventType.COMPLETE, - function() { ++completeEvents; }); - blobHasher.hash(blob); - assertEquals(1, startedEvents); - assertEquals(0, progressEvents); - assertEquals(0, completeEvents); - readFromBlob(blobHasher, 1); - assertEquals(1, startedEvents); - assertEquals(1, progressEvents); - assertEquals(1, completeEvents); - - // Test the flow with multiple chunks. - blob = new BlobMock('The quick brown fox jumps over the lazy dog'); - startedEvents = 0; - progressEvents = 0; - completeEvents = 0; - var progressLoops = 0; - blobHasher.hash(blob); - assertEquals(1, startedEvents); - assertEquals(0, progressEvents); - assertEquals(0, completeEvents); - progressLoops = readFromBlob(blobHasher, Math.ceil(blob.size / 13)); - assertEquals(1, startedEvents); - assertEquals(progressLoops, progressEvents); - assertEquals(1, completeEvents); -} - -function testAbortsAndErrors() { - if (!window.Blob) { - return; - } - - var hashFn = new goog.crypt.Md5(); - var blobHasher = new goog.crypt.BlobHasher(hashFn, 13); - var blob = new BlobMock('The quick brown fox jumps over the lazy dog'); - var abortEvents = 0; - var errorEvents = 0; - var completeEvents = 0; - goog.events.listen(blobHasher, goog.crypt.BlobHasher.EventType.ABORT, - function() { ++abortEvents; }); - goog.events.listen(blobHasher, goog.crypt.BlobHasher.EventType.ERROR, - function() { ++errorEvents; }); - goog.events.listen(blobHasher, goog.crypt.BlobHasher.EventType.COMPLETE, - function() { ++completeEvents; }); - - // Immediate abort. - blobHasher.hash(blob); - assertEquals(0, abortEvents); - assertEquals(0, errorEvents); - assertEquals(0, completeEvents); - blobHasher.abort(); - blobHasher.abort(); - assertEquals(1, abortEvents); - assertEquals(0, errorEvents); - assertEquals(0, completeEvents); - abortEvents = 0; - - // Delayed abort. - blobHasher.hash(blob); - blobHasher.fileReader_.mockLoad(); - assertEquals(0, abortEvents); - assertEquals(0, errorEvents); - assertEquals(0, completeEvents); - blobHasher.abort(); - blobHasher.abort(); - assertEquals(1, abortEvents); - assertEquals(0, errorEvents); - assertEquals(0, completeEvents); - abortEvents = 0; - - // Immediate error. - blobHasher.hash(blob); - blobHasher.fileReader_.mockError(); - assertEquals(0, abortEvents); - assertEquals(1, errorEvents); - assertEquals(0, completeEvents); - errorEvents = 0; - - // Delayed error. - blobHasher.hash(blob); - blobHasher.fileReader_.mockLoad(); - blobHasher.fileReader_.mockError(); - assertEquals(0, abortEvents); - assertEquals(1, errorEvents); - assertEquals(0, completeEvents); - abortEvents = 0; - -} - -function testBasicThrottling() { - if (!window.Blob) { - return; - } - - var hashFn = new goog.crypt.Md5(); - var blobHasher = new goog.crypt.BlobHasher(hashFn, 5); - var blob = new BlobMock('The quick brown fox jumps over the lazy dog'); - var throttledEvents = 0; - var completeEvents = 0; - goog.events.listen(blobHasher, goog.crypt.BlobHasher.EventType.THROTTLED, - function() { ++throttledEvents; }); - goog.events.listen(blobHasher, goog.crypt.BlobHasher.EventType.COMPLETE, - function() { ++completeEvents; }); - - // Start a throttled hash. No chunks should be processed yet. - blobHasher.setHashingLimit(0); - assertEquals(0, throttledEvents); - blobHasher.hash(blob); - assertEquals(1, throttledEvents); - assertEquals(0, blobHasher.getBytesProcessed()); - assertNull(blobHasher.fileReader_); - - // One chunk should be processed. - blobHasher.setHashingLimit(4); - assertEquals(1, throttledEvents); - assertEquals(1, readFromBlob(blobHasher, 1)); - assertEquals(2, throttledEvents); - assertEquals(4, blobHasher.getBytesProcessed()); - - // One more chunk should be processed. - blobHasher.setHashingLimit(5); - assertEquals(2, throttledEvents); - assertEquals(1, readFromBlob(blobHasher, 1)); - assertEquals(3, throttledEvents); - assertEquals(5, blobHasher.getBytesProcessed()); - - // Two more chunks should be processed. - blobHasher.setHashingLimit(15); - assertEquals(3, throttledEvents); - assertEquals(2, readFromBlob(blobHasher, 2)); - assertEquals(4, throttledEvents); - assertEquals(15, blobHasher.getBytesProcessed()); - - // The entire blob should be processed. - blobHasher.setHashingLimit(Infinity); - var expectedChunks = Math.ceil(blob.size / 5) - 3; - assertEquals(expectedChunks, readFromBlob(blobHasher, expectedChunks)); - assertEquals(4, throttledEvents); - assertEquals(1, completeEvents); - assertEquals('9e107d9d372bb6826bd81d3542a419d6', - goog.crypt.byteArrayToHex(blobHasher.getHash())); -} - -function testLengthZeroThrottling() { - if (!window.Blob) { - return; - } - - var hashFn = new goog.crypt.Md5(); - var blobHasher = new goog.crypt.BlobHasher(hashFn); - var throttledEvents = 0; - var completeEvents = 0; - goog.events.listen(blobHasher, goog.crypt.BlobHasher.EventType.THROTTLED, - function() { ++throttledEvents; }); - goog.events.listen(blobHasher, goog.crypt.BlobHasher.EventType.COMPLETE, - function() { ++completeEvents; }); - - // Test throttling with length 0 blob. - var blob = new BlobMock(''); - blobHasher.setHashingLimit(0); - blobHasher.hash(blob); - assertEquals(0, throttledEvents); - assertEquals(1, completeEvents); - assertEquals('d41d8cd98f00b204e9800998ecf8427e', - goog.crypt.byteArrayToHex(blobHasher.getHash())); -} - -function testAbortsAndErrorsWhileThrottling() { - if (!window.Blob) { - return; - } - - var hashFn = new goog.crypt.Md5(); - var blobHasher = new goog.crypt.BlobHasher(hashFn, 5); - var blob = new BlobMock('The quick brown fox jumps over the lazy dog'); - var abortEvents = 0; - var errorEvents = 0; - var throttledEvents = 0; - var completeEvents = 0; - goog.events.listen(blobHasher, goog.crypt.BlobHasher.EventType.ABORT, - function() { ++abortEvents; }); - goog.events.listen(blobHasher, goog.crypt.BlobHasher.EventType.ERROR, - function() { ++errorEvents; }); - goog.events.listen(blobHasher, goog.crypt.BlobHasher.EventType.THROTTLED, - function() { ++throttledEvents; }); - goog.events.listen(blobHasher, goog.crypt.BlobHasher.EventType.COMPLETE, - function() { ++completeEvents; }); - - // Test that processing cannot be continued after abort. - blobHasher.setHashingLimit(0); - blobHasher.hash(blob); - assertEquals(1, throttledEvents); - blobHasher.abort(); - assertEquals(1, abortEvents); - blobHasher.setHashingLimit(10); - assertNull(blobHasher.fileReader_); - assertEquals(1, throttledEvents); - assertEquals(0, completeEvents); - assertNull(blobHasher.getHash()); - - // Test that processing cannot be continued after error. - blobHasher.hash(blob); - assertEquals(1, throttledEvents); - blobHasher.fileReader_.mockError(); - assertEquals(1, errorEvents); - blobHasher.setHashingLimit(100); - assertNull(blobHasher.fileReader_); - assertEquals(1, throttledEvents); - assertEquals(0, completeEvents); - assertNull(blobHasher.getHash()); -} diff --git a/src/database/third_party/closure-library/closure/goog/crypt/blockcipher.js b/src/database/third_party/closure-library/closure/goog/crypt/blockcipher.js deleted file mode 100644 index be766f0e000..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/blockcipher.js +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2012 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Interface definition of a block cipher. A block cipher is a - * pair of algorithms that implement encryption and decryption of input bytes. - * - * @see http://en.wikipedia.org/wiki/Block_cipher - * - * @author nnaze@google.com (Nathan Naze) - */ - -goog.provide('goog.crypt.BlockCipher'); - - - -/** - * Interface definition for a block cipher. - * @interface - */ -goog.crypt.BlockCipher = function() {}; - - -/** - * Encrypt a plaintext block. The implementation may expect (and assert) - * a particular block length. - * @param {!Array} input Plaintext array of input bytes. - * @return {!Array} Encrypted ciphertext array of bytes. Should be the - * same length as input. - */ -goog.crypt.BlockCipher.prototype.encrypt; - - -/** - * Decrypt a plaintext block. The implementation may expect (and assert) - * a particular block length. - * @param {!Array} input Ciphertext. Array of input bytes. - * @return {!Array} Decrypted plaintext array of bytes. Should be the - * same length as input. - */ -goog.crypt.BlockCipher.prototype.decrypt; diff --git a/src/database/third_party/closure-library/closure/goog/crypt/bytestring_perf.html b/src/database/third_party/closure-library/closure/goog/crypt/bytestring_perf.html deleted file mode 100644 index cf1be84ef65..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/bytestring_perf.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - Closure Performance Tests - byteArrayToString - - - - -

Closure Performance Tests - byteArrayToString

-
-
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/crypt/bytestring_perf.js b/src/database/third_party/closure-library/closure/goog/crypt/bytestring_perf.js deleted file mode 100644 index 3e5e86a1290..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/bytestring_perf.js +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2014 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Performance test for different implementations of - * byteArrayToString. - */ - - -goog.provide('goog.crypt.byteArrayToStringPerf'); - -goog.require('goog.array'); -goog.require('goog.dom'); -goog.require('goog.testing.PerformanceTable'); - -goog.setTestOnly('goog.crypt.byteArrayToStringPerf'); - - -var table = new goog.testing.PerformanceTable( - goog.dom.getElement('perfTable')); - - -var BYTES_LENGTH = Math.pow(2, 20); -var CHUNK_SIZE = 8192; - -function getBytes() { - var bytes = []; - for (var i = 0; i < BYTES_LENGTH; i++) { - bytes.push('A'.charCodeAt(0)); - } - return bytes; -} - -function copyAndSpliceByteArray(bytes) { - - // Copy the passed byte array since we're going to destroy it. - var remainingBytes = goog.array.clone(bytes); - var strings = []; - - // Convert each chunk to a string. - while (remainingBytes.length) { - var chunk = goog.array.splice(remainingBytes, 0, CHUNK_SIZE); - strings.push(String.fromCharCode.apply(null, chunk)); - } - return strings.join(''); -} - -function sliceByteArrayConcat(bytes) { - var str = ''; - for (var i = 0; i < bytes.length; i += CHUNK_SIZE) { - var chunk = goog.array.slice(bytes, i, i + CHUNK_SIZE); - str += String.fromCharCode.apply(null, chunk); - } - return str; -} - - -function sliceByteArrayJoin(bytes) { - var strings = []; - for (var i = 0; i < bytes.length; i += CHUNK_SIZE) { - var chunk = goog.array.slice(bytes, i, i + CHUNK_SIZE); - strings.push(String.fromCharCode.apply(null, chunk)); - } - return strings.join(''); -} - -function mapByteArray(bytes) { - var strings = goog.array.map(bytes, String.fromCharCode); - return strings.join(''); -} - -function forLoopByteArrayConcat(bytes) { - var str = ''; - for (var i = 0; i < bytes.length; i++) { - str += String.fromCharCode(bytes[i]); - } - return str; -} - -function forLoopByteArrayJoin(bytes) { - var strs = []; - for (var i = 0; i < bytes.length; i++) { - strs.push(String.fromCharCode(bytes[i])); - } - return strs.join(''); -} - - -function run() { - var bytes = getBytes(); - table.run(goog.partial(copyAndSpliceByteArray, getBytes()), - 'Copy array and splice out chunks.'); - - table.run(goog.partial(sliceByteArrayConcat, getBytes()), - 'Slice out copies of the byte array, concatenating results'); - - table.run(goog.partial(sliceByteArrayJoin, getBytes()), - 'Slice out copies of the byte array, joining results'); - - table.run(goog.partial(forLoopByteArrayConcat, getBytes()), - 'Use for loop with concat.'); - - table.run(goog.partial(forLoopByteArrayJoin, getBytes()), - 'Use for loop with join.'); - - // Purposefully commented out. This ends up being tremendously expensive. - // table.run(goog.partial(mapByteArray, getBytes()), - // 'Use goog.array.map and fromCharCode.'); - -} - -run(); - diff --git a/src/database/third_party/closure-library/closure/goog/crypt/cbc.js b/src/database/third_party/closure-library/closure/goog/crypt/cbc.js deleted file mode 100644 index 68a265615c9..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/cbc.js +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright 2012 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Implementation of CBC mode for block ciphers. See - * http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation - * #Cipher-block_chaining_.28CBC.29. for description. - * - * @author nnaze@google.com (Nathan Naze) - */ - -goog.provide('goog.crypt.Cbc'); - -goog.require('goog.array'); -goog.require('goog.asserts'); -goog.require('goog.crypt'); - - - -/** - * Implements the CBC mode for block ciphers. See - * http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation - * #Cipher-block_chaining_.28CBC.29 - * - * @param {!goog.crypt.BlockCipher} cipher The block cipher to use. - * @param {number=} opt_blockSize The block size of the cipher in bytes. - * Defaults to 16 bytes. - * @constructor - * @final - * @struct - */ -goog.crypt.Cbc = function(cipher, opt_blockSize) { - - /** - * Block cipher. - * @type {!goog.crypt.BlockCipher} - * @private - */ - this.cipher_ = cipher; - - /** - * Block size in bytes. - * @type {number} - * @private - */ - this.blockSize_ = opt_blockSize || 16; -}; - - -/** - * Encrypt a message. - * - * @param {!Array} plainText Message to encrypt. An array of bytes. - * The length should be a multiple of the block size. - * @param {!Array} initialVector Initial vector for the CBC mode. - * An array of bytes with the same length as the block size. - * @return {!Array} Encrypted message. - */ -goog.crypt.Cbc.prototype.encrypt = function(plainText, initialVector) { - - goog.asserts.assert( - plainText.length % this.blockSize_ == 0, - 'Data\'s length must be multiple of block size.'); - - goog.asserts.assert( - initialVector.length == this.blockSize_, - 'Initial vector must be size of one block.'); - - // Implementation of - // http://en.wikipedia.org/wiki/File:Cbc_encryption.png - - var cipherText = []; - var vector = initialVector; - - // Generate each block of the encrypted cypher text. - for (var blockStartIndex = 0; - blockStartIndex < plainText.length; - blockStartIndex += this.blockSize_) { - - // Takes one block from the input message. - var plainTextBlock = goog.array.slice( - plainText, - blockStartIndex, - blockStartIndex + this.blockSize_); - - var input = goog.crypt.xorByteArray(plainTextBlock, vector); - var resultBlock = this.cipher_.encrypt(input); - - goog.array.extend(cipherText, resultBlock); - vector = resultBlock; - } - - return cipherText; -}; - - -/** - * Decrypt a message. - * - * @param {!Array} cipherText Message to decrypt. An array of bytes. - * The length should be a multiple of the block size. - * @param {!Array} initialVector Initial vector for the CBC mode. - * An array of bytes with the same length as the block size. - * @return {!Array} Decrypted message. - */ -goog.crypt.Cbc.prototype.decrypt = function(cipherText, initialVector) { - - goog.asserts.assert( - cipherText.length % this.blockSize_ == 0, - 'Data\'s length must be multiple of block size.'); - - goog.asserts.assert( - initialVector.length == this.blockSize_, - 'Initial vector must be size of one block.'); - - // Implementation of - // http://en.wikipedia.org/wiki/File:Cbc_decryption.png - - var plainText = []; - var blockStartIndex = 0; - var vector = initialVector; - - // Generate each block of the decrypted plain text. - while (blockStartIndex < cipherText.length) { - - // Takes one block. - var cipherTextBlock = goog.array.slice( - cipherText, - blockStartIndex, - blockStartIndex + this.blockSize_); - - var resultBlock = this.cipher_.decrypt(cipherTextBlock); - var plainTextBlock = goog.crypt.xorByteArray(vector, resultBlock); - - goog.array.extend(plainText, plainTextBlock); - vector = cipherTextBlock; - - blockStartIndex += this.blockSize_; - } - - return plainText; -}; diff --git a/src/database/third_party/closure-library/closure/goog/crypt/cbc_test.html b/src/database/third_party/closure-library/closure/goog/crypt/cbc_test.html deleted file mode 100644 index f722ff4d78e..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/cbc_test.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - -Closure Unit Tests - goog.crypt.Cbc - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/crypt/cbc_test.js b/src/database/third_party/closure-library/closure/goog/crypt/cbc_test.js deleted file mode 100644 index ef56a1ee067..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/cbc_test.js +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2012 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Unit tests for CBC mode for block ciphers. - * - * @author nnaze@google.com (Nathan Naze) - */ - -/** @suppress {extraProvide} */ -goog.provide('goog.crypt.CbcTest'); - -goog.require('goog.crypt'); -goog.require('goog.crypt.Aes'); -goog.require('goog.crypt.Cbc'); -goog.require('goog.testing.jsunit'); - -goog.setTestOnly('goog.crypt.CbcTest'); - -function stringToBytes(s) { - var bytes = new Array(s.length); - for (var i = 0; i < s.length; ++i) - bytes[i] = s.charCodeAt(i) & 255; - return bytes; -} - -function runCbcAesTest(keyBytes, initialVectorBytes, plainTextBytes, - cipherTextBytes) { - - var aes = new goog.crypt.Aes(keyBytes); - var cbc = new goog.crypt.Cbc(aes); - - var encryptedBytes = cbc.encrypt(plainTextBytes, initialVectorBytes); - assertEquals('Encrypted bytes should match cipher text.', - goog.crypt.byteArrayToHex(cipherTextBytes), - goog.crypt.byteArrayToHex(encryptedBytes)); - - var decryptedBytes = cbc.decrypt(cipherTextBytes, initialVectorBytes); - assertEquals('Decrypted bytes should match plain text.', - goog.crypt.byteArrayToHex(plainTextBytes), - goog.crypt.byteArrayToHex(decryptedBytes)); -} - -function testAesCbcCipherAlgorithm() { - // Test values from http://www.ietf.org/rfc/rfc3602.txt - - // Case #1 - runCbcAesTest( - goog.crypt.hexToByteArray('06a9214036b8a15b512e03d534120006'), - goog.crypt.hexToByteArray('3dafba429d9eb430b422da802c9fac41'), - stringToBytes('Single block msg'), - goog.crypt.hexToByteArray('e353779c1079aeb82708942dbe77181a')); - - // Case #2 - runCbcAesTest( - goog.crypt.hexToByteArray('c286696d887c9aa0611bbb3e2025a45a'), - goog.crypt.hexToByteArray('562e17996d093d28ddb3ba695a2e6f58'), - goog.crypt.hexToByteArray( - '000102030405060708090a0b0c0d0e0f' + - '101112131415161718191a1b1c1d1e1f'), - goog.crypt.hexToByteArray( - 'd296cd94c2cccf8a3a863028b5e1dc0a' + - '7586602d253cfff91b8266bea6d61ab1')); - - // Case #3 - runCbcAesTest( - goog.crypt.hexToByteArray('6c3ea0477630ce21a2ce334aa746c2cd'), - goog.crypt.hexToByteArray('c782dc4c098c66cbd9cd27d825682c81'), - stringToBytes('This is a 48-byte message (exactly 3 AES blocks)'), - goog.crypt.hexToByteArray( - 'd0a02b3836451753d493665d33f0e886' + - '2dea54cdb293abc7506939276772f8d5' + - '021c19216bad525c8579695d83ba2684')); - - // Case #4 - runCbcAesTest( - goog.crypt.hexToByteArray('56e47a38c5598974bc46903dba290349'), - goog.crypt.hexToByteArray('8ce82eefbea0da3c44699ed7db51b7d9'), - goog.crypt.hexToByteArray( - 'a0a1a2a3a4a5a6a7a8a9aaabacadaeaf' + - 'b0b1b2b3b4b5b6b7b8b9babbbcbdbebf' + - 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf' + - 'd0d1d2d3d4d5d6d7d8d9dadbdcdddedf'), - goog.crypt.hexToByteArray( - 'c30e32ffedc0774e6aff6af0869f71aa' + - '0f3af07a9a31a9c684db207eb0ef8e4e' + - '35907aa632c3ffdf868bb7b29d3d46ad' + - '83ce9f9a102ee99d49a53e87f4c3da55')); -} diff --git a/src/database/third_party/closure-library/closure/goog/crypt/crypt.js b/src/database/third_party/closure-library/closure/goog/crypt/crypt.js deleted file mode 100644 index e8f722aeebc..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/crypt.js +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Namespace with crypto related helper functions. - */ - -goog.provide('goog.crypt'); - -goog.require('goog.array'); -goog.require('goog.asserts'); - - -/** - * Turns a string into an array of bytes; a "byte" being a JS number in the - * range 0-255. - * @param {string} str String value to arrify. - * @return {!Array} Array of numbers corresponding to the - * UCS character codes of each character in str. - */ -goog.crypt.stringToByteArray = function(str) { - var output = [], p = 0; - for (var i = 0; i < str.length; i++) { - var c = str.charCodeAt(i); - while (c > 0xff) { - output[p++] = c & 0xff; - c >>= 8; - } - output[p++] = c; - } - return output; -}; - - -/** - * Turns an array of numbers into the string given by the concatenation of the - * characters to which the numbers correspond. - * @param {Array} bytes Array of numbers representing characters. - * @return {string} Stringification of the array. - */ -goog.crypt.byteArrayToString = function(bytes) { - var CHUNK_SIZE = 8192; - - // Special-case the simple case for speed's sake. - if (bytes.length < CHUNK_SIZE) { - return String.fromCharCode.apply(null, bytes); - } - - // The remaining logic splits conversion by chunks since - // Function#apply() has a maximum parameter count. - // See discussion: http://goo.gl/LrWmZ9 - - var str = ''; - for (var i = 0; i < bytes.length; i += CHUNK_SIZE) { - var chunk = goog.array.slice(bytes, i, i + CHUNK_SIZE); - str += String.fromCharCode.apply(null, chunk); - } - return str; -}; - - -/** - * Turns an array of numbers into the hex string given by the concatenation of - * the hex values to which the numbers correspond. - * @param {Uint8Array|Array} array Array of numbers representing - * characters. - * @return {string} Hex string. - */ -goog.crypt.byteArrayToHex = function(array) { - return goog.array.map(array, function(numByte) { - var hexByte = numByte.toString(16); - return hexByte.length > 1 ? hexByte : '0' + hexByte; - }).join(''); -}; - - -/** - * Converts a hex string into an integer array. - * @param {string} hexString Hex string of 16-bit integers (two characters - * per integer). - * @return {!Array} Array of {0,255} integers for the given string. - */ -goog.crypt.hexToByteArray = function(hexString) { - goog.asserts.assert(hexString.length % 2 == 0, - 'Key string length must be multiple of 2'); - var arr = []; - for (var i = 0; i < hexString.length; i += 2) { - arr.push(parseInt(hexString.substring(i, i + 2), 16)); - } - return arr; -}; - - -/** - * Converts a JS string to a UTF-8 "byte" array. - * @param {string} str 16-bit unicode string. - * @return {!Array} UTF-8 byte array. - */ -goog.crypt.stringToUtf8ByteArray = function(str) { - // TODO(user): Use native implementations if/when available - str = str.replace(/\r\n/g, '\n'); - var out = [], p = 0; - for (var i = 0; i < str.length; i++) { - var c = str.charCodeAt(i); - if (c < 128) { - out[p++] = c; - } else if (c < 2048) { - out[p++] = (c >> 6) | 192; - out[p++] = (c & 63) | 128; - } else { - out[p++] = (c >> 12) | 224; - out[p++] = ((c >> 6) & 63) | 128; - out[p++] = (c & 63) | 128; - } - } - return out; -}; - - -/** - * Converts a UTF-8 byte array to JavaScript's 16-bit Unicode. - * @param {Uint8Array|Array} bytes UTF-8 byte array. - * @return {string} 16-bit Unicode string. - */ -goog.crypt.utf8ByteArrayToString = function(bytes) { - // TODO(user): Use native implementations if/when available - var out = [], pos = 0, c = 0; - while (pos < bytes.length) { - var c1 = bytes[pos++]; - if (c1 < 128) { - out[c++] = String.fromCharCode(c1); - } else if (c1 > 191 && c1 < 224) { - var c2 = bytes[pos++]; - out[c++] = String.fromCharCode((c1 & 31) << 6 | c2 & 63); - } else { - var c2 = bytes[pos++]; - var c3 = bytes[pos++]; - out[c++] = String.fromCharCode( - (c1 & 15) << 12 | (c2 & 63) << 6 | c3 & 63); - } - } - return out.join(''); -}; - - -/** - * XOR two byte arrays. - * @param {!ArrayBufferView|!Array} bytes1 Byte array 1. - * @param {!ArrayBufferView|!Array} bytes2 Byte array 2. - * @return {!Array} Resulting XOR of the two byte arrays. - */ -goog.crypt.xorByteArray = function(bytes1, bytes2) { - goog.asserts.assert( - bytes1.length == bytes2.length, - 'XOR array lengths must match'); - - var result = []; - for (var i = 0; i < bytes1.length; i++) { - result.push(bytes1[i] ^ bytes2[i]); - } - return result; -}; diff --git a/src/database/third_party/closure-library/closure/goog/crypt/crypt_perf.html b/src/database/third_party/closure-library/closure/goog/crypt/crypt_perf.html deleted file mode 100644 index 5f073759f5a..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/crypt_perf.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - Closure Performance Tests - UTF8 encoding and decoding - - - - - -

Closure Performance Tests - UTF8 encoding and decoding

-

- User-agent: - -

-
-
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/crypt/crypt_test.html b/src/database/third_party/closure-library/closure/goog/crypt/crypt_test.html deleted file mode 100644 index 5a119fc2fd9..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/crypt_test.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - Closure Unit Tests - goog.crypt - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/crypt/crypt_test.js b/src/database/third_party/closure-library/closure/goog/crypt/crypt_test.js deleted file mode 100644 index deb8451aa43..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/crypt_test.js +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.cryptTest'); -goog.setTestOnly('goog.cryptTest'); - -goog.require('goog.crypt'); -goog.require('goog.string'); -goog.require('goog.testing.jsunit'); - -var UTF8_RANGES_BYTE_ARRAY = [ - 0x00, - 0x7F, - 0xC2, 0x80, - 0xDF, 0xBF, - 0xE0, 0xA0, 0x80, - 0xEF, 0xBF, 0xBF]; - -var UTF8_RANGES_STRING = '\u0000\u007F\u0080\u07FF\u0800\uFFFF'; - -function testStringToUtf8ByteArray() { - // Known encodings taken from Java's String.getBytes("UTF8") - - assertArrayEquals('ASCII', - [72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100], - goog.crypt.stringToUtf8ByteArray('Hello, world')); - - assertArrayEquals('Latin', - [83, 99, 104, 195, 182, 110], - goog.crypt.stringToUtf8ByteArray('Sch\u00f6n')); - - assertArrayEquals('limits of the first 3 UTF-8 character ranges', - UTF8_RANGES_BYTE_ARRAY, - goog.crypt.stringToUtf8ByteArray(UTF8_RANGES_STRING)); -} - -function testUtf8ByteArrayToString() { - // Known encodings taken from Java's String.getBytes("UTF8") - - assertEquals('ASCII', 'Hello, world', goog.crypt.utf8ByteArrayToString( - [72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100])); - - assertEquals('Latin', 'Sch\u00f6n', goog.crypt.utf8ByteArrayToString( - [83, 99, 104, 195, 182, 110])); - - assertEquals('limits of the first 3 UTF-8 character ranges', - UTF8_RANGES_STRING, - goog.crypt.utf8ByteArrayToString(UTF8_RANGES_BYTE_ARRAY)); -} - - -/** - * Same as testUtf8ByteArrayToString but with Uint8Array instead of - * Array. - */ -function testUint8ArrayToString() { - if (!goog.global.Uint8Array) { - // Uint8Array not supported. - return; - } - - var arr = new Uint8Array( - [72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100]); - assertEquals('ASCII', 'Hello, world', goog.crypt.utf8ByteArrayToString(arr)); - - arr = new Uint8Array([83, 99, 104, 195, 182, 110]); - assertEquals('Latin', 'Sch\u00f6n', goog.crypt.utf8ByteArrayToString(arr)); - - arr = new Uint8Array(UTF8_RANGES_BYTE_ARRAY); - assertEquals('limits of the first 3 UTF-8 character ranges', - UTF8_RANGES_STRING, - goog.crypt.utf8ByteArrayToString(arr)); -} - -function testByteArrayToString() { - assertEquals('', goog.crypt.byteArrayToString([])); - assertEquals('abc', goog.crypt.byteArrayToString([97, 98, 99])); -} - -function testHexToByteArray() { - assertElementsEquals( - [202, 254, 222, 173], - // Java magic number - goog.crypt.hexToByteArray('cafedead')); - - assertElementsEquals( - [222, 173, 190, 239], - // IBM magic number - goog.crypt.hexToByteArray('DEADBEEF')); -} - -function testByteArrayToHex() { - assertEquals( - // Java magic number - 'cafedead', - goog.crypt.byteArrayToHex([202, 254, 222, 173])); - - assertEquals( - // IBM magic number - 'deadbeef', - goog.crypt.byteArrayToHex([222, 173, 190, 239])); -} - - -/** Same as testByteArrayToHex but with Uint8Array instead of Array. */ -function testUint8ArrayToHex() { - if (!goog.isDef(goog.global.Uint8Array)) { - // Uint8Array not supported. - return; - } - - assertEquals( - // Java magic number - 'cafedead', - goog.crypt.byteArrayToHex(new Uint8Array([202, 254, 222, 173]))); - - assertEquals( - // IBM magic number - 'deadbeef', - goog.crypt.byteArrayToHex(new Uint8Array([222, 173, 190, 239]))); -} - -function testXorByteArray() { - assertElementsEquals( - [20, 83, 96, 66], - goog.crypt.xorByteArray([202, 254, 222, 173], [222, 173, 190, 239])); -} - - -/** Same as testXorByteArray but with Uint8Array instead of Array. */ -function testXorUint8Array() { - if (!goog.isDef(goog.global.Uint8Array)) { - // Uint8Array not supported. - return; - } - - assertElementsEquals( - [20, 83, 96, 66], - goog.crypt.xorByteArray( - new Uint8Array([202, 254, 222, 173]), - new Uint8Array([222, 173, 190, 239]))); -} - - -// Tests a one-megabyte byte array conversion to string. -// This would break on many JS implementations unless byteArrayToString -// split the input up. -// See discussion and bug report: http://goo.gl/LrWmZ9 -function testByteArrayToStringCallStack() { - // One megabyte is 2 to the 20th. - var count = Math.pow(2, 20); - var bytes = []; - for (var i = 0; i < count; i++) { - bytes.push('A'.charCodeAt(0)); - } - var str = goog.crypt.byteArrayToString(bytes); - assertEquals(goog.string.repeat('A', count), str); -} diff --git a/src/database/third_party/closure-library/closure/goog/crypt/hash.js b/src/database/third_party/closure-library/closure/goog/crypt/hash.js deleted file mode 100644 index 51209be61d5..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/hash.js +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2011 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Abstract cryptographic hash interface. - * - * See goog.crypt.Sha1 and goog.crypt.Md5 for sample implementations. - * - */ - -goog.provide('goog.crypt.Hash'); - - - -/** - * Create a cryptographic hash instance. - * - * @constructor - * @struct - */ -goog.crypt.Hash = function() { - /** - * The block size for the hasher. - * @type {number} - */ - this.blockSize = -1; -}; - - -/** - * Resets the internal accumulator. - */ -goog.crypt.Hash.prototype.reset = goog.abstractMethod; - - -/** - * Adds a byte array (array with values in [0-255] range) or a string (might - * only contain 8-bit, i.e., Latin1 characters) to the internal accumulator. - * - * Many hash functions operate on blocks of data and implement optimizations - * when a full chunk of data is readily available. Hence it is often preferable - * to provide large chunks of data (a kilobyte or more) than to repeatedly - * call the update method with few tens of bytes. If this is not possible, or - * not feasible, it might be good to provide data in multiplies of hash block - * size (often 64 bytes). Please see the implementation and performance tests - * of your favourite hash. - * - * @param {Array|Uint8Array|string} bytes Data used for the update. - * @param {number=} opt_length Number of bytes to use. - */ -goog.crypt.Hash.prototype.update = goog.abstractMethod; - - -/** - * @return {!Array} The finalized hash computed - * from the internal accumulator. - */ -goog.crypt.Hash.prototype.digest = goog.abstractMethod; diff --git a/src/database/third_party/closure-library/closure/goog/crypt/hash32.js b/src/database/third_party/closure-library/closure/goog/crypt/hash32.js deleted file mode 100644 index fa24ccf43e9..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/hash32.js +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Implementation of 32-bit hashing functions. - * - * This is a direct port from the Google Java Hash class - * - */ - -goog.provide('goog.crypt.hash32'); - -goog.require('goog.crypt'); - - -/** - * Default seed used during hashing, digits of pie. - * See SEED32 in http://go/base.hash.java - * @type {number} - */ -goog.crypt.hash32.SEED32 = 314159265; - - -/** - * Arbitrary constant used during hashing. - * See CONSTANT32 in http://go/base.hash.java - * @type {number} - */ -goog.crypt.hash32.CONSTANT32 = -1640531527; - - -/** - * Hashes a string to a 32-bit value. - * @param {string} str String to hash. - * @return {number} 32-bit hash. - */ -goog.crypt.hash32.encodeString = function(str) { - return goog.crypt.hash32.encodeByteArray(goog.crypt.stringToByteArray(str)); -}; - - -/** - * Hashes a string to a 32-bit value, converting the string to UTF-8 before - * doing the encoding. - * @param {string} str String to hash. - * @return {number} 32-bit hash. - */ -goog.crypt.hash32.encodeStringUtf8 = function(str) { - return goog.crypt.hash32.encodeByteArray( - goog.crypt.stringToUtf8ByteArray(str)); -}; - - -/** - * Hashes an integer to a 32-bit value. - * @param {number} value Number to hash. - * @return {number} 32-bit hash. - */ -goog.crypt.hash32.encodeInteger = function(value) { - // TODO(user): Does this make sense in JavaScript with doubles? Should we - // force the value to be in the correct range? - return goog.crypt.hash32.mix32_({ - a: value, - b: goog.crypt.hash32.CONSTANT32, - c: goog.crypt.hash32.SEED32 - }); -}; - - -/** - * Hashes a "byte" array to a 32-bit value using the supplied seed. - * @param {Array} bytes Array of bytes. - * @param {number=} opt_offset The starting position to use for hash - * computation. - * @param {number=} opt_length Number of bytes that are used for hashing. - * @param {number=} opt_seed The seed. - * @return {number} 32-bit hash. - */ -goog.crypt.hash32.encodeByteArray = function( - bytes, opt_offset, opt_length, opt_seed) { - var offset = opt_offset || 0; - var length = opt_length || bytes.length; - var seed = opt_seed || goog.crypt.hash32.SEED32; - - var mix = { - a: goog.crypt.hash32.CONSTANT32, - b: goog.crypt.hash32.CONSTANT32, - c: seed - }; - - var keylen; - for (keylen = length; keylen >= 12; keylen -= 12, offset += 12) { - mix.a += goog.crypt.hash32.wordAt_(bytes, offset); - mix.b += goog.crypt.hash32.wordAt_(bytes, offset + 4); - mix.c += goog.crypt.hash32.wordAt_(bytes, offset + 8); - goog.crypt.hash32.mix32_(mix); - } - // Hash any remaining bytes - mix.c += length; - switch (keylen) { // deal with rest. Some cases fall through - case 11: mix.c += (bytes[offset + 10]) << 24; - case 10: mix.c += (bytes[offset + 9] & 0xff) << 16; - case 9 : mix.c += (bytes[offset + 8] & 0xff) << 8; - // the first byte of c is reserved for the length - case 8 : - mix.b += goog.crypt.hash32.wordAt_(bytes, offset + 4); - mix.a += goog.crypt.hash32.wordAt_(bytes, offset); - break; - case 7 : mix.b += (bytes[offset + 6] & 0xff) << 16; - case 6 : mix.b += (bytes[offset + 5] & 0xff) << 8; - case 5 : mix.b += (bytes[offset + 4] & 0xff); - case 4 : - mix.a += goog.crypt.hash32.wordAt_(bytes, offset); - break; - case 3 : mix.a += (bytes[offset + 2] & 0xff) << 16; - case 2 : mix.a += (bytes[offset + 1] & 0xff) << 8; - case 1 : mix.a += (bytes[offset + 0] & 0xff); - // case 0 : nothing left to add - } - return goog.crypt.hash32.mix32_(mix); -}; - - -/** - * Performs an inplace mix of an object with the integer properties (a, b, c) - * and returns the final value of c. - * @param {Object} mix Object with properties, a, b, and c. - * @return {number} The end c-value for the mixing. - * @private - */ -goog.crypt.hash32.mix32_ = function(mix) { - var a = mix.a, b = mix.b, c = mix.c; - a -= b; a -= c; a ^= c >>> 13; - b -= c; b -= a; b ^= a << 8; - c -= a; c -= b; c ^= b >>> 13; - a -= b; a -= c; a ^= c >>> 12; - b -= c; b -= a; b ^= a << 16; - c -= a; c -= b; c ^= b >>> 5; - a -= b; a -= c; a ^= c >>> 3; - b -= c; b -= a; b ^= a << 10; - c -= a; c -= b; c ^= b >>> 15; - mix.a = a; mix.b = b; mix.c = c; - return c; -}; - - -/** - * Returns the word at a given offset. Treating an array of bytes a word at a - * time is far more efficient than byte-by-byte. - * @param {Array} bytes Array of bytes. - * @param {number} offset Offset in the byte array. - * @return {number} Integer value for the word. - * @private - */ -goog.crypt.hash32.wordAt_ = function(bytes, offset) { - var a = goog.crypt.hash32.toSigned_(bytes[offset + 0]); - var b = goog.crypt.hash32.toSigned_(bytes[offset + 1]); - var c = goog.crypt.hash32.toSigned_(bytes[offset + 2]); - var d = goog.crypt.hash32.toSigned_(bytes[offset + 3]); - return a + (b << 8) + (c << 16) + (d << 24); -}; - - -/** - * Converts an unsigned "byte" to signed, that is, convert a value in the range - * (0, 2^8-1) to (-2^7, 2^7-1) in order to be compatible with Java's byte type. - * @param {number} n Unsigned "byte" value. - * @return {number} Signed "byte" value. - * @private - */ -goog.crypt.hash32.toSigned_ = function(n) { - return n > 127 ? n - 256 : n; -}; diff --git a/src/database/third_party/closure-library/closure/goog/crypt/hash32_test.html b/src/database/third_party/closure-library/closure/goog/crypt/hash32_test.html deleted file mode 100644 index 48406169dff..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/hash32_test.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - Closure Unit Tests - goog.crypt.hash32 - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/crypt/hash32_test.js b/src/database/third_party/closure-library/closure/goog/crypt/hash32_test.js deleted file mode 100644 index 6230629bc91..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/hash32_test.js +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.crypt.hash32Test'); -goog.setTestOnly('goog.crypt.hash32Test'); - -goog.require('goog.crypt.hash32'); -goog.require('goog.testing.TestCase'); -goog.require('goog.testing.jsunit'); - -// NOTE: This test uses a custom test case, see end of script block - -// Test data based on known input/output pairs generated using -// http://go/hash.java - -function testEncodeInteger() { - assertEquals(898813988, goog.crypt.hash32.encodeInteger(305419896)); -} - -function testEncodeByteArray() { - assertEquals(-1497024495, - goog.crypt.hash32.encodeByteArray([10, 20, 30, 40])); - assertEquals(-961586214, - goog.crypt.hash32.encodeByteArray([3, 1, 4, 1, 5, 9])); - assertEquals(-1482202299, - goog.crypt.hash32.encodeByteArray([127, 0, 0, 0, 123, 45])); - assertEquals(170907881, - goog.crypt.hash32.encodeByteArray([9, 1, 1])); -} - -function testKnownByteArrays() { - for (var i = 0; i < byteArrays.length; i++) { - assertEquals(byteArrays[i], - goog.crypt.hash32.encodeByteArray(createByteArray(i))); - } -} - -function testEncodeString() { - assertEquals(-937588052, goog.crypt.hash32.encodeString('Hello, world')); - assertEquals(62382810, goog.crypt.hash32.encodeString('Sch\xF6n')); -} - -function testEncodeStringUtf8() { - assertEquals(-937588052, - goog.crypt.hash32.encodeStringUtf8('Hello, world')); - assertEquals(-833263351, goog.crypt.hash32.encodeStringUtf8('Sch\xF6n')); - - assertEquals(-1771620293, goog.crypt.hash32.encodeStringUtf8( - '\u043A\u0440')); -} - -function testEncodeString_ascii() { - assertEquals('For ascii characters UTF8 should be the same', - goog.crypt.hash32.encodeStringUtf8('abc123'), - goog.crypt.hash32.encodeString('abc123')); - - assertEquals('For ascii characters UTF8 should be the same', - goog.crypt.hash32.encodeStringUtf8('The,quick.brown-fox'), - goog.crypt.hash32.encodeString('The,quick.brown-fox')); - - assertNotEquals('For non-ascii characters UTF-8 encoding is different', - goog.crypt.hash32.encodeStringUtf8('Sch\xF6n'), - goog.crypt.hash32.encodeString('Sch\xF6n')); -} - -function testEncodeString_poe() { - var poe = "Once upon a midnight dreary, while I pondered weak and weary," + - "Over many a quaint and curious volume of forgotten lore," + - "While I nodded, nearly napping, suddenly there came a tapping," + - "As of some one gently rapping, rapping at my chamber door." + - "`'Tis some visitor,' I muttered, `tapping at my chamber door -" + - "Only this, and nothing more.'" + - "Ah, distinctly I remember it was in the bleak December," + - "And each separate dying ember wrought its ghost upon the floor." + - "Eagerly I wished the morrow; - vainly I had sought to borrow" + - "From my books surcease of sorrow - sorrow for the lost Lenore -" + - "For the rare and radiant maiden whom the angels named Lenore -" + - "Nameless here for evermore." + - "And the silken sad uncertain rustling of each purple curtain" + - "Thrilled me - filled me with fantastic terrors never felt before;" + - "So that now, to still the beating of my heart, I stood repeating" + - "`'Tis some visitor entreating entrance at my chamber door -" + - "Some late visitor entreating entrance at my chamber door; -" + - "This it is, and nothing more,'" + - "Presently my soul grew stronger; hesitating then no longer," + - "`Sir,' said I, `or Madam, truly your forgiveness I implore;" + - "But the fact is I was napping, and so gently you came rapping," + - "And so faintly you came tapping, tapping at my chamber door," + - "That I scarce was sure I heard you' - here I opened wide the door; -" + - "Darkness there, and nothing more." + - "Deep into that darkness peering, long I stood there wondering, " + - "fearing," + - "Doubting, dreaming dreams no mortal ever dared to dream before" + - "But the silence was unbroken, and the darkness gave no token," + - "And the only word there spoken was the whispered word, `Lenore!'" + - "This I whispered, and an echo murmured back the word, `Lenore!'" + - "Merely this and nothing more." + - "Back into the chamber turning, all my soul within me burning," + - "Soon again I heard a tapping somewhat louder than before." + - "`Surely,\' said I, `surely that is something at my window lattice;" + - "Let me see then, what thereat is, and this mystery explore -" + - "Let my heart be still a moment and this mystery explore; -" + - "'Tis the wind and nothing more!'"; - - assertEquals(147608747, goog.crypt.hash32.encodeString(poe)); - assertEquals(147608747, goog.crypt.hash32.encodeStringUtf8(poe)); -} - -function testBenchmarking() { - if (!testCase) return; - // Not a real test, just outputs some timing - function makeString(n) { - var str = []; - for (var i = 0; i < n; i++) { - str.push(String.fromCharCode(Math.round(Math.random() * 500))); - } - return str.join(''); - } - for (var i = 0; i < 50000; i += 10000) { - var str = makeString(i); - var start = goog.now(); - var hash = goog.crypt.hash32.encodeString(str); - var diff = goog.now() - start; - testCase.saveMessage( - 'testBenchmarking : hashing ' + i + ' chars in ' + diff + 'ms'); - } -} - -function createByteArray(n) { - var arr = []; - for (var i = 0; i < n; i++) { - arr.push(i); - } - return arr; -} - -var byteArrays = { - 0: 1539411136, - 1: 1773524747, - 2: -254958930, - 3: 1532114172, - 4: 1923165449, - 5: 1611874589, - 6: 1502126780, - 7: -751745251, - 8: -292491321, - 9: 1106193218, - 10: -722791438, - 11: -2130666060, - 12: -259304553, - 13: 871461192, - 14: 865773084, - 15: 1615738330, - 16: -1836636447, - 17: -485722519, - 18: -120832227, - 19: 1954449704, - 20: 491312921, - 21: -1955462668, - 22: 168565425, - 23: -105893922, - 24: 620486614, - 25: -1789602428, - 26: 1765793554, - 27: 1723370948, - 28: -1275405721, - 29: 140421019, - 30: -1438726307, - 31: 538438903, - 32: -729123980, - 33: 1213490939, - 34: -1814248478, - 35: 1943703398, - 36: 1603073219, - 37: -2139639543, - 38: -694153941, - 39: 137511516, - 40: -249943726, - 41: -1166126060, - 42: 53464833, - 43: -915350862, - 44: 1306585409, - 45: 1064798289, - 46: 335555913, - 47: 224485496, - 48: 275599760, - 49: 409559869, - 50: 673770580, - 51: -2113819879, - 52: -791338727, - 53: -1716479479, - 54: 1795018816, - 55: 2020139343, - 56: -1652827750, - 57: -1509632558, - 58: 751641995, - 59: -217881377, - 60: -476546900, - 61: -1893349644, - 62: -729290332, - 63: 1359899321, - 64: 1811814306, - 65: 2100363086, - 66: -794920327, - 67: -1667555017, - 68: -549980099, - 69: -21170740, - 70: -1324143722, - 71: 1406730195, - 72: 2111381574, - 73: -1667480052, - 74: 1071811178, - 75: -1080194099, - 76: -181186882, - 77: 268677507, - 78: -546766334, - 79: 555953522, - 80: -981311675, - 81: 1988867392, - 82: 773172547, - 83: 1160806722, - 84: -1455460187, - 85: 83493600, - 86: 155365142, - 87: 1714618071, - 88: 1487712615, - 89: -810670278, - 90: 2031655097, - 91: 1286349470, - 92: -1873594211, - 93: 1875867480, - 94: -1096259787, - 95: -1054968610, - 96: -1723043458, - 97: 1278708307, - 98: -601104085, - 99: 1497928579, - 100: 1329732615, - 101: -1281696190, - 102: 1471511953, - 103: -62666299, - 104: 807569747, - 105: -1927974759, - 106: 1462243717, - 107: -862975602, - 108: 824369927, - 109: -1448816781, - 110: 1434162022, - 111: -881501413, - 112: -1554381107, - 113: -1730883204, - 114: 431236217, - 115: 1877278608, - 116: -673864625, - 117: 143000665, - 118: -596902829, - 119: 1038860559, - 120: 805884326, - 121: -1536181710, - 122: -1357373256, - 123: 1405134250, - 124: -860816481, - 125: 1393578269, - 126: -810682545, - 127: -635515639 -}; - -var testCase; -if (G_testRunner) { - testCase = new goog.testing.TestCase(document.title); - testCase.autoDiscoverTests(); - G_testRunner.initialize(testCase); -} diff --git a/src/database/third_party/closure-library/closure/goog/crypt/hashtester.js b/src/database/third_party/closure-library/closure/goog/crypt/hashtester.js deleted file mode 100644 index e4e804c5782..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/hashtester.js +++ /dev/null @@ -1,244 +0,0 @@ -// Copyright 2011 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Unit tests for the abstract cryptographic hash interface. - * - */ - -goog.provide('goog.crypt.hashTester'); - -goog.require('goog.array'); -goog.require('goog.crypt'); -goog.require('goog.dom'); -goog.require('goog.testing.PerformanceTable'); -goog.require('goog.testing.PseudoRandom'); -goog.require('goog.testing.asserts'); -goog.setTestOnly('hashTester'); - - -/** - * Runs basic tests. - * - * @param {!goog.crypt.Hash} hash A hash instance. - */ -goog.crypt.hashTester.runBasicTests = function(hash) { - // Compute first hash. - hash.update([97, 158]); - var golden1 = hash.digest(); - - // Compute second hash. - hash.reset(); - hash.update('aB'); - var golden2 = hash.digest(); - assertTrue('Two different inputs resulted in a hash collision', - !!goog.testing.asserts.findDifferences(golden1, golden2)); - - // Empty hash. - hash.reset(); - var empty = hash.digest(); - assertTrue('Empty hash collided with a non-trivial one', - !!goog.testing.asserts.findDifferences(golden1, empty) && - !!goog.testing.asserts.findDifferences(golden2, empty)); - - // Zero-length array update. - hash.reset(); - hash.update([]); - assertArrayEquals('Updating with an empty array did not give an empty hash', - empty, hash.digest()); - - // Zero-length string update. - hash.reset(); - hash.update(''); - assertArrayEquals('Updating with an empty string did not give an empty hash', - empty, hash.digest()); - - // Recompute the first hash. - hash.reset(); - hash.update([97, 158]); - assertArrayEquals('The reset did not produce the initial state', - golden1, hash.digest()); - - // Check for a trivial collision. - hash.reset(); - hash.update([158, 97]); - assertTrue('Swapping bytes resulted in a hash collision', - !!goog.testing.asserts.findDifferences(golden1, hash.digest())); - - // Compare array and string input. - hash.reset(); - hash.update([97, 66]); - assertArrayEquals('String and array inputs should give the same result', - golden2, hash.digest()); - - // Compute in parts. - hash.reset(); - hash.update('a'); - hash.update([158]); - assertArrayEquals('Partial updates resulted in a different hash', - golden1, hash.digest()); - - // Test update with specified length. - hash.reset(); - hash.update('aB', 0); - hash.update([97, 158, 32], 2); - assertArrayEquals('Updating with an explicit buffer length did not work', - golden1, hash.digest()); -}; - - -/** - * Runs block tests. - * - * @param {!goog.crypt.Hash} hash A hash instance. - * @param {number} blockBytes Size of the hash block. - */ -goog.crypt.hashTester.runBlockTests = function(hash, blockBytes) { - // Compute a message which is 1 byte shorter than hash block size. - var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - var message = ''; - for (var i = 0; i < blockBytes - 1; i++) { - message += chars.charAt(i % chars.length); - } - - // Compute golden hash for 1 block + 2 bytes. - hash.update(message + '123'); - var golden1 = hash.digest(); - - // Compute golden hash for 2 blocks + 1 byte. - hash.reset(); - hash.update(message + message + '123'); - var golden2 = hash.digest(); - - // Almost fill a block, then overflow. - hash.reset(); - hash.update(message); - hash.update('123'); - assertArrayEquals(golden1, hash.digest()); - - // Fill a block. - hash.reset(); - hash.update(message + '1'); - hash.update('23'); - assertArrayEquals(golden1, hash.digest()); - - // Overflow a block. - hash.reset(); - hash.update(message + '12'); - hash.update('3'); - assertArrayEquals(golden1, hash.digest()); - - // Test single overflow with an array. - hash.reset(); - hash.update(goog.crypt.stringToByteArray(message + '123')); - assertArrayEquals(golden1, hash.digest()); - - // Almost fill a block, then overflow this and the next block. - hash.reset(); - hash.update(message); - hash.update(message + '123'); - assertArrayEquals(golden2, hash.digest()); - - // Fill two blocks. - hash.reset(); - hash.update(message + message + '12'); - hash.update('3'); - assertArrayEquals(golden2, hash.digest()); - - // Test double overflow with an array. - hash.reset(); - hash.update(goog.crypt.stringToByteArray(message)); - hash.update(goog.crypt.stringToByteArray(message + '123')); - assertArrayEquals(golden2, hash.digest()); -}; - - -/** - * Runs performance tests. - * - * @param {function():!goog.crypt.Hash} hashFactory A hash factory. - * @param {string} hashName Name of the hashing function. - */ -goog.crypt.hashTester.runPerfTests = function(hashFactory, hashName) { - var body = goog.dom.getDocument().body; - var perfTable = goog.dom.createElement('div'); - goog.dom.appendChild(body, perfTable); - - var table = new goog.testing.PerformanceTable(perfTable); - - function runPerfTest(byteLength, updateCount) { - var label = (hashName + ': ' + updateCount + ' update(s) of ' + byteLength + - ' bytes'); - - function run(data, dataType) { - table.run(function() { - var hash = hashFactory(); - for (var i = 0; i < updateCount; i++) { - hash.update(data, byteLength); - } - var digest = hash.digest(); - }, label + ' (' + dataType + ')'); - } - - var byteArray = goog.crypt.hashTester.createRandomByteArray_(byteLength); - var byteString = goog.crypt.hashTester.createByteString_(byteArray); - - run(byteArray, 'byte array'); - run(byteString, 'byte string'); - } - - var MESSAGE_LENGTH_LONG = 10000000; // 10 Mbytes - var MESSAGE_LENGTH_SHORT = 10; // 10 bytes - var MESSAGE_COUNT_SHORT = MESSAGE_LENGTH_LONG / MESSAGE_LENGTH_SHORT; - - runPerfTest(MESSAGE_LENGTH_LONG, 1); - runPerfTest(MESSAGE_LENGTH_SHORT, MESSAGE_COUNT_SHORT); -}; - - -/** - * Creates and returns a random byte array. - * - * @param {number} length Length of the byte array. - * @return {!Array} An array of bytes. - * @private - */ -goog.crypt.hashTester.createRandomByteArray_ = function(length) { - var random = new goog.testing.PseudoRandom(0); - var bytes = []; - - for (var i = 0; i < length; ++i) { - // Generates an integer from 0 to 255. - var b = Math.floor(random.random() * 0x100); - bytes.push(b); - } - - return bytes; -}; - - -/** - * Creates a string from an array of bytes. - * - * @param {!Array} bytes An array of bytes. - * @return {string} The string encoded by the bytes. - * @private - */ -goog.crypt.hashTester.createByteString_ = function(bytes) { - var str = ''; - goog.array.forEach(bytes, function(b) { - str += String.fromCharCode(b); - }); - return str; -}; diff --git a/src/database/third_party/closure-library/closure/goog/crypt/hmac.js b/src/database/third_party/closure-library/closure/goog/crypt/hmac.js deleted file mode 100644 index 15e0e1dffb5..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/hmac.js +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2011 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Implementation of HMAC in JavaScript. - * - * Usage: - * var hmac = new goog.crypt.Hmac(new goog.crypt.sha1(), key, 64); - * var digest = hmac.getHmac(bytes); - * - * @author benyu@google.com (Jige Yu) - port to closure - */ - - -goog.provide('goog.crypt.Hmac'); - -goog.require('goog.crypt.Hash'); - - - -/** - * @constructor - * @param {!goog.crypt.Hash} hasher An object to serve as a hash function. - * @param {Array} key The secret key to use to calculate the hmac. - * Should be an array of not more than {@code blockSize} integers in - {0, 255}. - * @param {number=} opt_blockSize Optional. The block size {@code hasher} uses. - * If not specified, uses the block size from the hasher, or 16 if it is - * not specified. - * @extends {goog.crypt.Hash} - * @final - * @struct - */ -goog.crypt.Hmac = function(hasher, key, opt_blockSize) { - goog.crypt.Hmac.base(this, 'constructor'); - - /** - * The underlying hasher to calculate hash. - * - * @type {!goog.crypt.Hash} - * @private - */ - this.hasher_ = hasher; - - this.blockSize = opt_blockSize || hasher.blockSize || 16; - - /** - * The outer padding array of hmac - * - * @type {!Array} - * @private - */ - this.keyO_ = new Array(this.blockSize); - - /** - * The inner padding array of hmac - * - * @type {!Array} - * @private - */ - this.keyI_ = new Array(this.blockSize); - - this.initialize_(key); -}; -goog.inherits(goog.crypt.Hmac, goog.crypt.Hash); - - -/** - * Outer padding byte of HMAC algorith, per http://en.wikipedia.org/wiki/HMAC - * - * @type {number} - * @private - */ -goog.crypt.Hmac.OPAD_ = 0x5c; - - -/** - * Inner padding byte of HMAC algorith, per http://en.wikipedia.org/wiki/HMAC - * - * @type {number} - * @private - */ -goog.crypt.Hmac.IPAD_ = 0x36; - - -/** - * Initializes Hmac by precalculating the inner and outer paddings. - * - * @param {Array} key The secret key to use to calculate the hmac. - * Should be an array of not more than {@code blockSize} integers in - {0, 255}. - * @private - */ -goog.crypt.Hmac.prototype.initialize_ = function(key) { - if (key.length > this.blockSize) { - this.hasher_.update(key); - key = this.hasher_.digest(); - this.hasher_.reset(); - } - // Precalculate padded and xor'd keys. - var keyByte; - for (var i = 0; i < this.blockSize; i++) { - if (i < key.length) { - keyByte = key[i]; - } else { - keyByte = 0; - } - this.keyO_[i] = keyByte ^ goog.crypt.Hmac.OPAD_; - this.keyI_[i] = keyByte ^ goog.crypt.Hmac.IPAD_; - } - // Be ready for an immediate update. - this.hasher_.update(this.keyI_); -}; - - -/** @override */ -goog.crypt.Hmac.prototype.reset = function() { - this.hasher_.reset(); - this.hasher_.update(this.keyI_); -}; - - -/** @override */ -goog.crypt.Hmac.prototype.update = function(bytes, opt_length) { - this.hasher_.update(bytes, opt_length); -}; - - -/** @override */ -goog.crypt.Hmac.prototype.digest = function() { - var temp = this.hasher_.digest(); - this.hasher_.reset(); - this.hasher_.update(this.keyO_); - this.hasher_.update(temp); - return this.hasher_.digest(); -}; - - -/** - * Calculates an HMAC for a given message. - * - * @param {Array|Uint8Array|string} message Data to Hmac. - * @return {!Array} the digest of the given message. - */ -goog.crypt.Hmac.prototype.getHmac = function(message) { - this.reset(); - this.update(message); - return this.digest(); -}; diff --git a/src/database/third_party/closure-library/closure/goog/crypt/hmac_test.html b/src/database/third_party/closure-library/closure/goog/crypt/hmac_test.html deleted file mode 100644 index c612ece76bf..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/hmac_test.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - Closure Unit Tests - goog.crypt.sha1 - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/crypt/hmac_test.js b/src/database/third_party/closure-library/closure/goog/crypt/hmac_test.js deleted file mode 100644 index 8f1046abc94..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/hmac_test.js +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2011 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.crypt.HmacTest'); -goog.setTestOnly('goog.crypt.HmacTest'); - -goog.require('goog.crypt.Hmac'); -goog.require('goog.crypt.Sha1'); -goog.require('goog.crypt.hashTester'); -goog.require('goog.testing.jsunit'); - -function stringToBytes(s) { - var bytes = new Array(s.length); - - for (var i = 0; i < s.length; ++i) { - bytes[i] = s.charCodeAt(i) & 255; - } - return bytes; -} - -function hexToBytes(str) { - var arr = []; - - for (var i = 0; i < str.length; i += 2) { - arr.push(parseInt(str.substring(i, i + 2), 16)); - } - - return arr; -} - -function bytesToHex(b) { - var hexchars = '0123456789abcdef'; - var hexrep = new Array(b.length * 2); - - for (var i = 0; i < b.length; ++i) { - hexrep[i * 2] = hexchars.charAt((b[i] >> 4) & 15); - hexrep[i * 2 + 1] = hexchars.charAt(b[i] & 15); - } - return hexrep.join(''); -} - - -/** - * helper to get an hmac of the given message with the given key. - */ -function getHmac(key, message, opt_blockSize) { - var hasher = new goog.crypt.Sha1(); - var hmacer = new goog.crypt.Hmac(hasher, key, opt_blockSize); - return bytesToHex(hmacer.getHmac(message)); -} - -function testBasicOperations() { - var hmac = new goog.crypt.Hmac(new goog.crypt.Sha1(), 'key', 64); - goog.crypt.hashTester.runBasicTests(hmac); -} - -function testBasicOperationsWithNoBlockSize() { - var hmac = new goog.crypt.Hmac(new goog.crypt.Sha1(), 'key'); - goog.crypt.hashTester.runBasicTests(hmac); -} - -function testHmac() { - // HMAC test vectors from: - // http://tools.ietf.org/html/2202 - - assertEquals('test 1 failed', - 'b617318655057264e28bc0b6fb378c8ef146be00', - getHmac(hexToBytes('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b'), - stringToBytes('Hi There'))); - - assertEquals('test 2 failed', - 'effcdf6ae5eb2fa2d27416d5f184df9c259a7c79', - getHmac(stringToBytes('Jefe'), - stringToBytes('what do ya want for nothing?'))); - - assertEquals('test 3 failed', - '125d7342b9ac11cd91a39af48aa17b4f63f175d3', - getHmac(hexToBytes('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'), - hexToBytes('dddddddddddddddddddddddddddddddddddddddd' + - 'dddddddddddddddddddddddddddddddddddddddd' + - 'dddddddddddddddddddd'))); - - assertEquals('test 4 failed', - '4c9007f4026250c6bc8414f9bf50c86c2d7235da', - getHmac(hexToBytes('0102030405060708090a0b0c0d0e0f10111213141516171819'), - hexToBytes('cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd' + - 'cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd' + - 'cdcdcdcdcdcdcdcdcdcd'))); - - assertEquals('test 5 failed', - '4c1a03424b55e07fe7f27be1d58bb9324a9a5a04', - getHmac(hexToBytes('0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c'), - stringToBytes('Test With Truncation'))); - - assertEquals('test 6 failed', - 'aa4ae5e15272d00e95705637ce8a3b55ed402112', - getHmac(hexToBytes('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + - 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + - 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + - 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'), - stringToBytes( - 'Test Using Larger Than Block-Size Key - Hash Key First'))); - - assertEquals('test 7 failed', - 'b617318655057264e28bc0b6fb378c8ef146be00', - getHmac(hexToBytes('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b'), - stringToBytes('Hi There'), 64)); - - assertEquals('test 8 failed', - '941f806707826395dc510add6a45ce9933db976e', - getHmac(hexToBytes('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b'), - stringToBytes('Hi There'), 32)); -} - - -/** Regression test for Bug 12863104 */ -function testUpdateWithLongKey() { - // Calling update() then digest() should give the same result as just - // calling getHmac() - var key = hexToBytes('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + - 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + - 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + - 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'); - var message = 'Secret Message'; - var hmac = new goog.crypt.Hmac(new goog.crypt.Sha1(), key); - hmac.update(message); - var result1 = bytesToHex(hmac.digest()); - hmac.reset(); - var result2 = bytesToHex(hmac.getHmac(message)); - assertEquals('Results must be the same', result1, result2); -} diff --git a/src/database/third_party/closure-library/closure/goog/crypt/md5.js b/src/database/third_party/closure-library/closure/goog/crypt/md5.js deleted file mode 100644 index 56335e152d7..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/md5.js +++ /dev/null @@ -1,435 +0,0 @@ -// Copyright 2011 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview MD5 cryptographic hash. - * Implementation of http://tools.ietf.org/html/rfc1321 with common - * optimizations and tweaks (see http://en.wikipedia.org/wiki/MD5). - * - * Usage: - * var md5 = new goog.crypt.Md5(); - * md5.update(bytes); - * var hash = md5.digest(); - * - * Performance: - * Chrome 23 ~680 Mbit/s - * Chrome 13 (in a VM) ~250 Mbit/s - * Firefox 6.0 (in a VM) ~100 Mbit/s - * IE9 (in a VM) ~27 Mbit/s - * Firefox 3.6 ~15 Mbit/s - * IE8 (in a VM) ~13 Mbit/s - * - */ - -goog.provide('goog.crypt.Md5'); - -goog.require('goog.crypt.Hash'); - - - -/** - * MD5 cryptographic hash constructor. - * @constructor - * @extends {goog.crypt.Hash} - * @final - * @struct - */ -goog.crypt.Md5 = function() { - goog.crypt.Md5.base(this, 'constructor'); - - this.blockSize = 512 / 8; - - /** - * Holds the current values of accumulated A-D variables (MD buffer). - * @type {!Array} - * @private - */ - this.chain_ = new Array(4); - - /** - * A buffer holding the data until the whole block can be processed. - * @type {!Array} - * @private - */ - this.block_ = new Array(this.blockSize); - - /** - * The length of yet-unprocessed data as collected in the block. - * @type {number} - * @private - */ - this.blockLength_ = 0; - - /** - * The total length of the message so far. - * @type {number} - * @private - */ - this.totalLength_ = 0; - - this.reset(); -}; -goog.inherits(goog.crypt.Md5, goog.crypt.Hash); - - -/** - * Integer rotation constants used by the abbreviated implementation. - * They are hardcoded in the unrolled implementation, so it is left - * here commented out. - * @type {Array} - * @private - * -goog.crypt.Md5.S_ = [ - 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, - 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, - 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, - 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 -]; - */ - -/** - * Sine function constants used by the abbreviated implementation. - * They are hardcoded in the unrolled implementation, so it is left - * here commented out. - * @type {Array} - * @private - * -goog.crypt.Md5.T_ = [ - 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, - 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, - 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, - 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, - 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, - 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, - 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, - 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, - 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, - 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, - 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, - 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, - 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, - 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, - 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, - 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 -]; - */ - - -/** @override */ -goog.crypt.Md5.prototype.reset = function() { - this.chain_[0] = 0x67452301; - this.chain_[1] = 0xefcdab89; - this.chain_[2] = 0x98badcfe; - this.chain_[3] = 0x10325476; - - this.blockLength_ = 0; - this.totalLength_ = 0; -}; - - -/** - * Internal compress helper function. It takes a block of data (64 bytes) - * and updates the accumulator. - * @param {Array|Uint8Array|string} buf The block to compress. - * @param {number=} opt_offset Offset of the block in the buffer. - * @private - */ -goog.crypt.Md5.prototype.compress_ = function(buf, opt_offset) { - if (!opt_offset) { - opt_offset = 0; - } - - // We allocate the array every time, but it's cheap in practice. - var X = new Array(16); - - // Get 16 little endian words. It is not worth unrolling this for Chrome 11. - if (goog.isString(buf)) { - for (var i = 0; i < 16; ++i) { - X[i] = (buf.charCodeAt(opt_offset++)) | - (buf.charCodeAt(opt_offset++) << 8) | - (buf.charCodeAt(opt_offset++) << 16) | - (buf.charCodeAt(opt_offset++) << 24); - } - } else { - for (var i = 0; i < 16; ++i) { - X[i] = (buf[opt_offset++]) | - (buf[opt_offset++] << 8) | - (buf[opt_offset++] << 16) | - (buf[opt_offset++] << 24); - } - } - - var A = this.chain_[0]; - var B = this.chain_[1]; - var C = this.chain_[2]; - var D = this.chain_[3]; - var sum = 0; - - /* - * This is an abbreviated implementation, it is left here commented out for - * reference purposes. See below for an unrolled version in use. - * - var f, n, tmp; - for (var i = 0; i < 64; ++i) { - - if (i < 16) { - f = (D ^ (B & (C ^ D))); - n = i; - } else if (i < 32) { - f = (C ^ (D & (B ^ C))); - n = (5 * i + 1) % 16; - } else if (i < 48) { - f = (B ^ C ^ D); - n = (3 * i + 5) % 16; - } else { - f = (C ^ (B | (~D))); - n = (7 * i) % 16; - } - - tmp = D; - D = C; - C = B; - sum = (A + f + goog.crypt.Md5.T_[i] + X[n]) & 0xffffffff; - B += ((sum << goog.crypt.Md5.S_[i]) & 0xffffffff) | - (sum >>> (32 - goog.crypt.Md5.S_[i])); - A = tmp; - } - */ - - /* - * This is an unrolled MD5 implementation, which gives ~30% speedup compared - * to the abbreviated implementation above, as measured on Chrome 11. It is - * important to keep 32-bit croppings to minimum and inline the integer - * rotation. - */ - sum = (A + (D ^ (B & (C ^ D))) + X[0] + 0xd76aa478) & 0xffffffff; - A = B + (((sum << 7) & 0xffffffff) | (sum >>> 25)); - sum = (D + (C ^ (A & (B ^ C))) + X[1] + 0xe8c7b756) & 0xffffffff; - D = A + (((sum << 12) & 0xffffffff) | (sum >>> 20)); - sum = (C + (B ^ (D & (A ^ B))) + X[2] + 0x242070db) & 0xffffffff; - C = D + (((sum << 17) & 0xffffffff) | (sum >>> 15)); - sum = (B + (A ^ (C & (D ^ A))) + X[3] + 0xc1bdceee) & 0xffffffff; - B = C + (((sum << 22) & 0xffffffff) | (sum >>> 10)); - sum = (A + (D ^ (B & (C ^ D))) + X[4] + 0xf57c0faf) & 0xffffffff; - A = B + (((sum << 7) & 0xffffffff) | (sum >>> 25)); - sum = (D + (C ^ (A & (B ^ C))) + X[5] + 0x4787c62a) & 0xffffffff; - D = A + (((sum << 12) & 0xffffffff) | (sum >>> 20)); - sum = (C + (B ^ (D & (A ^ B))) + X[6] + 0xa8304613) & 0xffffffff; - C = D + (((sum << 17) & 0xffffffff) | (sum >>> 15)); - sum = (B + (A ^ (C & (D ^ A))) + X[7] + 0xfd469501) & 0xffffffff; - B = C + (((sum << 22) & 0xffffffff) | (sum >>> 10)); - sum = (A + (D ^ (B & (C ^ D))) + X[8] + 0x698098d8) & 0xffffffff; - A = B + (((sum << 7) & 0xffffffff) | (sum >>> 25)); - sum = (D + (C ^ (A & (B ^ C))) + X[9] + 0x8b44f7af) & 0xffffffff; - D = A + (((sum << 12) & 0xffffffff) | (sum >>> 20)); - sum = (C + (B ^ (D & (A ^ B))) + X[10] + 0xffff5bb1) & 0xffffffff; - C = D + (((sum << 17) & 0xffffffff) | (sum >>> 15)); - sum = (B + (A ^ (C & (D ^ A))) + X[11] + 0x895cd7be) & 0xffffffff; - B = C + (((sum << 22) & 0xffffffff) | (sum >>> 10)); - sum = (A + (D ^ (B & (C ^ D))) + X[12] + 0x6b901122) & 0xffffffff; - A = B + (((sum << 7) & 0xffffffff) | (sum >>> 25)); - sum = (D + (C ^ (A & (B ^ C))) + X[13] + 0xfd987193) & 0xffffffff; - D = A + (((sum << 12) & 0xffffffff) | (sum >>> 20)); - sum = (C + (B ^ (D & (A ^ B))) + X[14] + 0xa679438e) & 0xffffffff; - C = D + (((sum << 17) & 0xffffffff) | (sum >>> 15)); - sum = (B + (A ^ (C & (D ^ A))) + X[15] + 0x49b40821) & 0xffffffff; - B = C + (((sum << 22) & 0xffffffff) | (sum >>> 10)); - sum = (A + (C ^ (D & (B ^ C))) + X[1] + 0xf61e2562) & 0xffffffff; - A = B + (((sum << 5) & 0xffffffff) | (sum >>> 27)); - sum = (D + (B ^ (C & (A ^ B))) + X[6] + 0xc040b340) & 0xffffffff; - D = A + (((sum << 9) & 0xffffffff) | (sum >>> 23)); - sum = (C + (A ^ (B & (D ^ A))) + X[11] + 0x265e5a51) & 0xffffffff; - C = D + (((sum << 14) & 0xffffffff) | (sum >>> 18)); - sum = (B + (D ^ (A & (C ^ D))) + X[0] + 0xe9b6c7aa) & 0xffffffff; - B = C + (((sum << 20) & 0xffffffff) | (sum >>> 12)); - sum = (A + (C ^ (D & (B ^ C))) + X[5] + 0xd62f105d) & 0xffffffff; - A = B + (((sum << 5) & 0xffffffff) | (sum >>> 27)); - sum = (D + (B ^ (C & (A ^ B))) + X[10] + 0x02441453) & 0xffffffff; - D = A + (((sum << 9) & 0xffffffff) | (sum >>> 23)); - sum = (C + (A ^ (B & (D ^ A))) + X[15] + 0xd8a1e681) & 0xffffffff; - C = D + (((sum << 14) & 0xffffffff) | (sum >>> 18)); - sum = (B + (D ^ (A & (C ^ D))) + X[4] + 0xe7d3fbc8) & 0xffffffff; - B = C + (((sum << 20) & 0xffffffff) | (sum >>> 12)); - sum = (A + (C ^ (D & (B ^ C))) + X[9] + 0x21e1cde6) & 0xffffffff; - A = B + (((sum << 5) & 0xffffffff) | (sum >>> 27)); - sum = (D + (B ^ (C & (A ^ B))) + X[14] + 0xc33707d6) & 0xffffffff; - D = A + (((sum << 9) & 0xffffffff) | (sum >>> 23)); - sum = (C + (A ^ (B & (D ^ A))) + X[3] + 0xf4d50d87) & 0xffffffff; - C = D + (((sum << 14) & 0xffffffff) | (sum >>> 18)); - sum = (B + (D ^ (A & (C ^ D))) + X[8] + 0x455a14ed) & 0xffffffff; - B = C + (((sum << 20) & 0xffffffff) | (sum >>> 12)); - sum = (A + (C ^ (D & (B ^ C))) + X[13] + 0xa9e3e905) & 0xffffffff; - A = B + (((sum << 5) & 0xffffffff) | (sum >>> 27)); - sum = (D + (B ^ (C & (A ^ B))) + X[2] + 0xfcefa3f8) & 0xffffffff; - D = A + (((sum << 9) & 0xffffffff) | (sum >>> 23)); - sum = (C + (A ^ (B & (D ^ A))) + X[7] + 0x676f02d9) & 0xffffffff; - C = D + (((sum << 14) & 0xffffffff) | (sum >>> 18)); - sum = (B + (D ^ (A & (C ^ D))) + X[12] + 0x8d2a4c8a) & 0xffffffff; - B = C + (((sum << 20) & 0xffffffff) | (sum >>> 12)); - sum = (A + (B ^ C ^ D) + X[5] + 0xfffa3942) & 0xffffffff; - A = B + (((sum << 4) & 0xffffffff) | (sum >>> 28)); - sum = (D + (A ^ B ^ C) + X[8] + 0x8771f681) & 0xffffffff; - D = A + (((sum << 11) & 0xffffffff) | (sum >>> 21)); - sum = (C + (D ^ A ^ B) + X[11] + 0x6d9d6122) & 0xffffffff; - C = D + (((sum << 16) & 0xffffffff) | (sum >>> 16)); - sum = (B + (C ^ D ^ A) + X[14] + 0xfde5380c) & 0xffffffff; - B = C + (((sum << 23) & 0xffffffff) | (sum >>> 9)); - sum = (A + (B ^ C ^ D) + X[1] + 0xa4beea44) & 0xffffffff; - A = B + (((sum << 4) & 0xffffffff) | (sum >>> 28)); - sum = (D + (A ^ B ^ C) + X[4] + 0x4bdecfa9) & 0xffffffff; - D = A + (((sum << 11) & 0xffffffff) | (sum >>> 21)); - sum = (C + (D ^ A ^ B) + X[7] + 0xf6bb4b60) & 0xffffffff; - C = D + (((sum << 16) & 0xffffffff) | (sum >>> 16)); - sum = (B + (C ^ D ^ A) + X[10] + 0xbebfbc70) & 0xffffffff; - B = C + (((sum << 23) & 0xffffffff) | (sum >>> 9)); - sum = (A + (B ^ C ^ D) + X[13] + 0x289b7ec6) & 0xffffffff; - A = B + (((sum << 4) & 0xffffffff) | (sum >>> 28)); - sum = (D + (A ^ B ^ C) + X[0] + 0xeaa127fa) & 0xffffffff; - D = A + (((sum << 11) & 0xffffffff) | (sum >>> 21)); - sum = (C + (D ^ A ^ B) + X[3] + 0xd4ef3085) & 0xffffffff; - C = D + (((sum << 16) & 0xffffffff) | (sum >>> 16)); - sum = (B + (C ^ D ^ A) + X[6] + 0x04881d05) & 0xffffffff; - B = C + (((sum << 23) & 0xffffffff) | (sum >>> 9)); - sum = (A + (B ^ C ^ D) + X[9] + 0xd9d4d039) & 0xffffffff; - A = B + (((sum << 4) & 0xffffffff) | (sum >>> 28)); - sum = (D + (A ^ B ^ C) + X[12] + 0xe6db99e5) & 0xffffffff; - D = A + (((sum << 11) & 0xffffffff) | (sum >>> 21)); - sum = (C + (D ^ A ^ B) + X[15] + 0x1fa27cf8) & 0xffffffff; - C = D + (((sum << 16) & 0xffffffff) | (sum >>> 16)); - sum = (B + (C ^ D ^ A) + X[2] + 0xc4ac5665) & 0xffffffff; - B = C + (((sum << 23) & 0xffffffff) | (sum >>> 9)); - sum = (A + (C ^ (B | (~D))) + X[0] + 0xf4292244) & 0xffffffff; - A = B + (((sum << 6) & 0xffffffff) | (sum >>> 26)); - sum = (D + (B ^ (A | (~C))) + X[7] + 0x432aff97) & 0xffffffff; - D = A + (((sum << 10) & 0xffffffff) | (sum >>> 22)); - sum = (C + (A ^ (D | (~B))) + X[14] + 0xab9423a7) & 0xffffffff; - C = D + (((sum << 15) & 0xffffffff) | (sum >>> 17)); - sum = (B + (D ^ (C | (~A))) + X[5] + 0xfc93a039) & 0xffffffff; - B = C + (((sum << 21) & 0xffffffff) | (sum >>> 11)); - sum = (A + (C ^ (B | (~D))) + X[12] + 0x655b59c3) & 0xffffffff; - A = B + (((sum << 6) & 0xffffffff) | (sum >>> 26)); - sum = (D + (B ^ (A | (~C))) + X[3] + 0x8f0ccc92) & 0xffffffff; - D = A + (((sum << 10) & 0xffffffff) | (sum >>> 22)); - sum = (C + (A ^ (D | (~B))) + X[10] + 0xffeff47d) & 0xffffffff; - C = D + (((sum << 15) & 0xffffffff) | (sum >>> 17)); - sum = (B + (D ^ (C | (~A))) + X[1] + 0x85845dd1) & 0xffffffff; - B = C + (((sum << 21) & 0xffffffff) | (sum >>> 11)); - sum = (A + (C ^ (B | (~D))) + X[8] + 0x6fa87e4f) & 0xffffffff; - A = B + (((sum << 6) & 0xffffffff) | (sum >>> 26)); - sum = (D + (B ^ (A | (~C))) + X[15] + 0xfe2ce6e0) & 0xffffffff; - D = A + (((sum << 10) & 0xffffffff) | (sum >>> 22)); - sum = (C + (A ^ (D | (~B))) + X[6] + 0xa3014314) & 0xffffffff; - C = D + (((sum << 15) & 0xffffffff) | (sum >>> 17)); - sum = (B + (D ^ (C | (~A))) + X[13] + 0x4e0811a1) & 0xffffffff; - B = C + (((sum << 21) & 0xffffffff) | (sum >>> 11)); - sum = (A + (C ^ (B | (~D))) + X[4] + 0xf7537e82) & 0xffffffff; - A = B + (((sum << 6) & 0xffffffff) | (sum >>> 26)); - sum = (D + (B ^ (A | (~C))) + X[11] + 0xbd3af235) & 0xffffffff; - D = A + (((sum << 10) & 0xffffffff) | (sum >>> 22)); - sum = (C + (A ^ (D | (~B))) + X[2] + 0x2ad7d2bb) & 0xffffffff; - C = D + (((sum << 15) & 0xffffffff) | (sum >>> 17)); - sum = (B + (D ^ (C | (~A))) + X[9] + 0xeb86d391) & 0xffffffff; - B = C + (((sum << 21) & 0xffffffff) | (sum >>> 11)); - - this.chain_[0] = (this.chain_[0] + A) & 0xffffffff; - this.chain_[1] = (this.chain_[1] + B) & 0xffffffff; - this.chain_[2] = (this.chain_[2] + C) & 0xffffffff; - this.chain_[3] = (this.chain_[3] + D) & 0xffffffff; -}; - - -/** @override */ -goog.crypt.Md5.prototype.update = function(bytes, opt_length) { - if (!goog.isDef(opt_length)) { - opt_length = bytes.length; - } - var lengthMinusBlock = opt_length - this.blockSize; - - // Copy some object properties to local variables in order to save on access - // time from inside the loop (~10% speedup was observed on Chrome 11). - var block = this.block_; - var blockLength = this.blockLength_; - var i = 0; - - // The outer while loop should execute at most twice. - while (i < opt_length) { - // When we have no data in the block to top up, we can directly process the - // input buffer (assuming it contains sufficient data). This gives ~30% - // speedup on Chrome 14 and ~70% speedup on Firefox 6.0, but requires that - // the data is provided in large chunks (or in multiples of 64 bytes). - if (blockLength == 0) { - while (i <= lengthMinusBlock) { - this.compress_(bytes, i); - i += this.blockSize; - } - } - - if (goog.isString(bytes)) { - while (i < opt_length) { - block[blockLength++] = bytes.charCodeAt(i++); - if (blockLength == this.blockSize) { - this.compress_(block); - blockLength = 0; - // Jump to the outer loop so we use the full-block optimization. - break; - } - } - } else { - while (i < opt_length) { - block[blockLength++] = bytes[i++]; - if (blockLength == this.blockSize) { - this.compress_(block); - blockLength = 0; - // Jump to the outer loop so we use the full-block optimization. - break; - } - } - } - } - - this.blockLength_ = blockLength; - this.totalLength_ += opt_length; -}; - - -/** @override */ -goog.crypt.Md5.prototype.digest = function() { - // This must accommodate at least 1 padding byte (0x80), 8 bytes of - // total bitlength, and must end at a 64-byte boundary. - var pad = new Array((this.blockLength_ < 56 ? - this.blockSize : - this.blockSize * 2) - this.blockLength_); - - // Add padding: 0x80 0x00* - pad[0] = 0x80; - for (var i = 1; i < pad.length - 8; ++i) { - pad[i] = 0; - } - // Add the total number of bits, little endian 64-bit integer. - var totalBits = this.totalLength_ * 8; - for (var i = pad.length - 8; i < pad.length; ++i) { - pad[i] = totalBits & 0xff; - totalBits /= 0x100; // Don't use bit-shifting here! - } - this.update(pad); - - var digest = new Array(16); - var n = 0; - for (var i = 0; i < 4; ++i) { - for (var j = 0; j < 32; j += 8) { - digest[n++] = (this.chain_[i] >>> j) & 0xff; - } - } - return digest; -}; diff --git a/src/database/third_party/closure-library/closure/goog/crypt/md5_perf.html b/src/database/third_party/closure-library/closure/goog/crypt/md5_perf.html deleted file mode 100644 index 57aa8c88f87..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/md5_perf.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - - -Closure Performance Tests - goog.crypt.Md5 - - - - - -

Closure Performance Tests - goog.crypt.Md5

-

-User-agent: - -

- - - diff --git a/src/database/third_party/closure-library/closure/goog/crypt/md5_test.html b/src/database/third_party/closure-library/closure/goog/crypt/md5_test.html deleted file mode 100644 index b37e301e8bd..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/md5_test.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - Closure Unit Tests - goog.crypt.Md5 - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/crypt/md5_test.js b/src/database/third_party/closure-library/closure/goog/crypt/md5_test.js deleted file mode 100644 index ac1ab8370e0..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/md5_test.js +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright 2011 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.crypt.Md5Test'); -goog.setTestOnly('goog.crypt.Md5Test'); - -goog.require('goog.crypt'); -goog.require('goog.crypt.Md5'); -goog.require('goog.crypt.hashTester'); -goog.require('goog.testing.jsunit'); - -var sixty = '123456789012345678901234567890123456789012345678901234567890'; - -function testBasicOperations() { - var md5 = new goog.crypt.Md5(); - goog.crypt.hashTester.runBasicTests(md5); -} - -function testBlockOperations() { - var md5 = new goog.crypt.Md5(); - goog.crypt.hashTester.runBlockTests(md5, 64); -} - -function testHashing() { - // Empty stream. - var md5 = new goog.crypt.Md5(); - assertEquals('d41d8cd98f00b204e9800998ecf8427e', - goog.crypt.byteArrayToHex(md5.digest())); - - // Simple stream. - md5.reset(); - md5.update([97]); - assertEquals('0cc175b9c0f1b6a831c399e269772661', - goog.crypt.byteArrayToHex(md5.digest())); - - // Simple stream with two updates. - md5.reset(); - md5.update([97]); - md5.update('bc'); - assertEquals('900150983cd24fb0d6963f7d28e17f72', - goog.crypt.byteArrayToHex(md5.digest())); - - // RFC 1321 standard test. - md5.reset(); - md5.update('abcdefghijklmnopqrstuvwxyz'); - assertEquals('c3fcd3d76192e4007dfb496cca67e13b', - goog.crypt.byteArrayToHex(md5.digest())); - - // RFC 1321 standard test with two updates. - md5.reset(); - md5.update('message '); - md5.update('digest'); - assertEquals('f96b697d7cb7938d525a2f31aaf161d0', - goog.crypt.byteArrayToHex(md5.digest())); - - // RFC 1321 standard test with three updates. - md5.reset(); - md5.update('ABCDEFGHIJKLMNOPQRSTUVWXYZ'); - md5.update('abcdefghijklmnopqrstuvwxyz'); - md5.update('0123456789'); - assertEquals('d174ab98d277d9f5a5611c2c9f419d9f', - goog.crypt.byteArrayToHex(md5.digest())); -} - -function testPadding() { - // Message + padding fits in two 64-byte blocks. - var md5 = new goog.crypt.Md5(); - md5.update(sixty); - md5.update(sixty.substr(0, 59)); - assertEquals('6261005311809757906e04c0d670492d', - goog.crypt.byteArrayToHex(md5.digest())); - - // Message + padding does not fit in two 64-byte blocks. - md5.reset(); - md5.update(sixty); - md5.update(sixty); - assertEquals('1d453b96d48d5e0cec4a20a71fecaa81', - goog.crypt.byteArrayToHex(md5.digest())); -} - -function testTwoAccumulators() { - // Two accumulators in parallel. - var md5_A = new goog.crypt.Md5(); - var md5_B = new goog.crypt.Md5(); - md5_A.update(sixty); - md5_B.update(sixty); - md5_A.update(sixty + '1'); - md5_B.update(sixty + '2'); - assertEquals('0801d688cc107d4789ec8b9a4519f01f', - goog.crypt.byteArrayToHex(md5_A.digest())); - assertEquals('6e1a35ffc185d1e684d6ed281c0d4bd2', - goog.crypt.byteArrayToHex(md5_B.digest())); -} - -function testCollision() { - // Check a known collision. - var A = [0xd1, 0x31, 0xdd, 0x02, 0xc5, 0xe6, 0xee, 0xc4, - 0x69, 0x3d, 0x9a, 0x06, 0x98, 0xaf, 0xf9, 0x5c, - 0x2f, 0xca, 0xb5, 0x87, 0x12, 0x46, 0x7e, 0xab, - 0x40, 0x04, 0x58, 0x3e, 0xb8, 0xfb, 0x7f, 0x89, - 0x55, 0xad, 0x34, 0x06, 0x09, 0xf4, 0xb3, 0x02, - 0x83, 0xe4, 0x88, 0x83, 0x25, 0x71, 0x41, 0x5a, - 0x08, 0x51, 0x25, 0xe8, 0xf7, 0xcd, 0xc9, 0x9f, - 0xd9, 0x1d, 0xbd, 0xf2, 0x80, 0x37, 0x3c, 0x5b, - 0xd8, 0x82, 0x3e, 0x31, 0x56, 0x34, 0x8f, 0x5b, - 0xae, 0x6d, 0xac, 0xd4, 0x36, 0xc9, 0x19, 0xc6, - 0xdd, 0x53, 0xe2, 0xb4, 0x87, 0xda, 0x03, 0xfd, - 0x02, 0x39, 0x63, 0x06, 0xd2, 0x48, 0xcd, 0xa0, - 0xe9, 0x9f, 0x33, 0x42, 0x0f, 0x57, 0x7e, 0xe8, - 0xce, 0x54, 0xb6, 0x70, 0x80, 0xa8, 0x0d, 0x1e, - 0xc6, 0x98, 0x21, 0xbc, 0xb6, 0xa8, 0x83, 0x93, - 0x96, 0xf9, 0x65, 0x2b, 0x6f, 0xf7, 0x2a, 0x70]; - var B = [0xd1, 0x31, 0xdd, 0x02, 0xc5, 0xe6, 0xee, 0xc4, - 0x69, 0x3d, 0x9a, 0x06, 0x98, 0xaf, 0xf9, 0x5c, - 0x2f, 0xca, 0xb5, 0x07, 0x12, 0x46, 0x7e, 0xab, - 0x40, 0x04, 0x58, 0x3e, 0xb8, 0xfb, 0x7f, 0x89, - 0x55, 0xad, 0x34, 0x06, 0x09, 0xf4, 0xb3, 0x02, - 0x83, 0xe4, 0x88, 0x83, 0x25, 0xf1, 0x41, 0x5a, - 0x08, 0x51, 0x25, 0xe8, 0xf7, 0xcd, 0xc9, 0x9f, - 0xd9, 0x1d, 0xbd, 0x72, 0x80, 0x37, 0x3c, 0x5b, - 0xd8, 0x82, 0x3e, 0x31, 0x56, 0x34, 0x8f, 0x5b, - 0xae, 0x6d, 0xac, 0xd4, 0x36, 0xc9, 0x19, 0xc6, - 0xdd, 0x53, 0xe2, 0x34, 0x87, 0xda, 0x03, 0xfd, - 0x02, 0x39, 0x63, 0x06, 0xd2, 0x48, 0xcd, 0xa0, - 0xe9, 0x9f, 0x33, 0x42, 0x0f, 0x57, 0x7e, 0xe8, - 0xce, 0x54, 0xb6, 0x70, 0x80, 0x28, 0x0d, 0x1e, - 0xc6, 0x98, 0x21, 0xbc, 0xb6, 0xa8, 0x83, 0x93, - 0x96, 0xf9, 0x65, 0xab, 0x6f, 0xf7, 0x2a, 0x70]; - var digest = '79054025255fb1a26e4bc422aef54eb4'; - var md5_A = new goog.crypt.Md5(); - var md5_B = new goog.crypt.Md5(); - md5_A.update(A); - md5_B.update(B); - assertEquals(digest, goog.crypt.byteArrayToHex(md5_A.digest())); - assertEquals(digest, goog.crypt.byteArrayToHex(md5_B.digest())); -} diff --git a/src/database/third_party/closure-library/closure/goog/crypt/pbkdf2.js b/src/database/third_party/closure-library/closure/goog/crypt/pbkdf2.js deleted file mode 100644 index 2fd1807e7dc..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/pbkdf2.js +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2012 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Implementation of PBKDF2 in JavaScript. - * @see http://en.wikipedia.org/wiki/PBKDF2 - * - * Currently we only support HMAC-SHA1 as the underlying hash function. To add a - * new hash function, add a static method similar to deriveKeyFromPasswordSha1() - * and implement the specific computeBlockCallback() using the hash function. - * - * Usage: - * var key = pbkdf2.deriveKeySha1( - * stringToByteArray('password'), stringToByteArray('salt'), 1000, 128); - * - */ - -goog.provide('goog.crypt.pbkdf2'); - -goog.require('goog.array'); -goog.require('goog.asserts'); -goog.require('goog.crypt'); -goog.require('goog.crypt.Hmac'); -goog.require('goog.crypt.Sha1'); - - -/** - * Derives key from password using PBKDF2-SHA1 - * @param {!Array} password Byte array representation of the password - * from which the key is derived. - * @param {!Array} initialSalt Byte array representation of the salt. - * @param {number} iterations Number of interations when computing the key. - * @param {number} keyLength Length of the output key in bits. - * Must be multiple of 8. - * @return {!Array} Byte array representation of the output key. - */ -goog.crypt.pbkdf2.deriveKeySha1 = function( - password, initialSalt, iterations, keyLength) { - // Length of the HMAC-SHA1 output in bits. - var HASH_LENGTH = 160; - - /** - * Compute each block of the key using HMAC-SHA1. - * @param {!Array} index Byte array representation of the index of - * the block to be computed. - * @return {!Array} Byte array representation of the output block. - */ - var computeBlock = function(index) { - // Initialize the result to be array of 0 such that its xor with the first - // block would be the first block. - var result = goog.array.repeat(0, HASH_LENGTH / 8); - // Initialize the salt of the first iteration to initialSalt || i. - var salt = initialSalt.concat(index); - var hmac = new goog.crypt.Hmac(new goog.crypt.Sha1(), password, 64); - // Compute and XOR each iteration. - for (var i = 0; i < iterations; i++) { - // The salt of the next iteration is the result of the current iteration. - salt = hmac.getHmac(salt); - result = goog.crypt.xorByteArray(result, salt); - } - return result; - }; - - return goog.crypt.pbkdf2.deriveKeyFromPassword_( - computeBlock, HASH_LENGTH, keyLength); -}; - - -/** - * Compute each block of the key using PBKDF2. - * @param {Function} computeBlock Function to compute each block of the output - * key. - * @param {number} hashLength Length of each block in bits. This is determined - * by the specific hash function used. Must be multiple of 8. - * @param {number} keyLength Length of the output key in bits. - * Must be multiple of 8. - * @return {!Array} Byte array representation of the output key. - * @private - */ -goog.crypt.pbkdf2.deriveKeyFromPassword_ = - function(computeBlock, hashLength, keyLength) { - goog.asserts.assert(keyLength % 8 == 0, 'invalid output key length'); - - // Compute and concactate each block of the output key. - var numBlocks = Math.ceil(keyLength / hashLength); - goog.asserts.assert(numBlocks >= 1, 'invalid number of blocks'); - var result = []; - for (var i = 1; i <= numBlocks; i++) { - var indexBytes = goog.crypt.pbkdf2.integerToByteArray_(i); - result = result.concat(computeBlock(indexBytes)); - } - - // Trim the last block if needed. - var lastBlockSize = keyLength % hashLength; - if (lastBlockSize != 0) { - var desiredBytes = ((numBlocks - 1) * hashLength + lastBlockSize) / 8; - result.splice(desiredBytes, (hashLength - lastBlockSize) / 8); - } - return result; -}; - - -/** - * Converts an integer number to a 32-bit big endian byte array. - * @param {number} n Integer number to be converted. - * @return {!Array} Byte Array representation of the 32-bit big endian - * encoding of n. - * @private - */ -goog.crypt.pbkdf2.integerToByteArray_ = function(n) { - var result = new Array(4); - result[0] = n >> 24 & 0xFF; - result[1] = n >> 16 & 0xFF; - result[2] = n >> 8 & 0xFF; - result[3] = n & 0xFF; - return result; -}; diff --git a/src/database/third_party/closure-library/closure/goog/crypt/pbkdf2_test.html b/src/database/third_party/closure-library/closure/goog/crypt/pbkdf2_test.html deleted file mode 100644 index de6d1bd9dac..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/pbkdf2_test.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - Closure Unit Tests - goog.crypt.pbkdf2 - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/crypt/pbkdf2_test.js b/src/database/third_party/closure-library/closure/goog/crypt/pbkdf2_test.js deleted file mode 100644 index 8aee360244d..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/pbkdf2_test.js +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2012 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.crypt.pbkdf2Test'); -goog.setTestOnly('goog.crypt.pbkdf2Test'); - -goog.require('goog.crypt'); -goog.require('goog.crypt.pbkdf2'); -goog.require('goog.testing.jsunit'); -goog.require('goog.userAgent'); - -function testPBKDF2() { - // PBKDF2 test vectors from: - // http://tools.ietf.org/html/rfc6070 - - if (goog.userAgent.IE && goog.userAgent.isVersionOrHigher('7')) { - return; - } - - var testPassword = goog.crypt.stringToByteArray('password'); - var testSalt = goog.crypt.stringToByteArray('salt'); - - assertElementsEquals( - goog.crypt.hexToByteArray('0c60c80f961f0e71f3a9b524af6012062fe037a6'), - goog.crypt.pbkdf2.deriveKeySha1(testPassword, testSalt, 1, 160)); - - assertElementsEquals( - goog.crypt.hexToByteArray('ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957'), - goog.crypt.pbkdf2.deriveKeySha1(testPassword, testSalt, 2, 160)); - - assertElementsEquals( - goog.crypt.hexToByteArray('4b007901b765489abead49d926f721d065a429c1'), - goog.crypt.pbkdf2.deriveKeySha1(testPassword, testSalt, 4096, 160)); - - testPassword = goog.crypt.stringToByteArray('passwordPASSWORDpassword'); - testSalt = - goog.crypt.stringToByteArray('saltSALTsaltSALTsaltSALTsaltSALTsalt'); - - assertElementsEquals( - goog.crypt.hexToByteArray( - '3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038'), - goog.crypt.pbkdf2.deriveKeySha1(testPassword, testSalt, 4096, 200)); - - testPassword = goog.crypt.stringToByteArray('pass\0word'); - testSalt = goog.crypt.stringToByteArray('sa\0lt'); - - assertElementsEquals( - goog.crypt.hexToByteArray('56fa6aa75548099dcc37d7f03425e0c3'), - goog.crypt.pbkdf2.deriveKeySha1(testPassword, testSalt, 4096, 128)); -} diff --git a/src/database/third_party/closure-library/closure/goog/crypt/sha1.js b/src/database/third_party/closure-library/closure/goog/crypt/sha1.js deleted file mode 100644 index b1a52193dd8..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/sha1.js +++ /dev/null @@ -1,294 +0,0 @@ -// Copyright 2005 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview SHA-1 cryptographic hash. - * Variable names follow the notation in FIPS PUB 180-3: - * http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf. - * - * Usage: - * var sha1 = new goog.crypt.sha1(); - * sha1.update(bytes); - * var hash = sha1.digest(); - * - * Performance: - * Chrome 23: ~400 Mbit/s - * Firefox 16: ~250 Mbit/s - * - */ - -goog.provide('goog.crypt.Sha1'); - -goog.require('goog.crypt.Hash'); - - - -/** - * SHA-1 cryptographic hash constructor. - * - * The properties declared here are discussed in the above algorithm document. - * @constructor - * @extends {goog.crypt.Hash} - * @final - * @struct - */ -goog.crypt.Sha1 = function() { - goog.crypt.Sha1.base(this, 'constructor'); - - this.blockSize = 512 / 8; - - /** - * Holds the previous values of accumulated variables a-e in the compress_ - * function. - * @type {!Array} - * @private - */ - this.chain_ = []; - - /** - * A buffer holding the partially computed hash result. - * @type {!Array} - * @private - */ - this.buf_ = []; - - /** - * An array of 80 bytes, each a part of the message to be hashed. Referred to - * as the message schedule in the docs. - * @type {!Array} - * @private - */ - this.W_ = []; - - /** - * Contains data needed to pad messages less than 64 bytes. - * @type {!Array} - * @private - */ - this.pad_ = []; - - this.pad_[0] = 128; - for (var i = 1; i < this.blockSize; ++i) { - this.pad_[i] = 0; - } - - /** - * @private {number} - */ - this.inbuf_ = 0; - - /** - * @private {number} - */ - this.total_ = 0; - - this.reset(); -}; -goog.inherits(goog.crypt.Sha1, goog.crypt.Hash); - - -/** @override */ -goog.crypt.Sha1.prototype.reset = function() { - this.chain_[0] = 0x67452301; - this.chain_[1] = 0xefcdab89; - this.chain_[2] = 0x98badcfe; - this.chain_[3] = 0x10325476; - this.chain_[4] = 0xc3d2e1f0; - - this.inbuf_ = 0; - this.total_ = 0; -}; - - -/** - * Internal compress helper function. - * @param {!Array|!Uint8Array|string} buf Block to compress. - * @param {number=} opt_offset Offset of the block in the buffer. - * @private - */ -goog.crypt.Sha1.prototype.compress_ = function(buf, opt_offset) { - if (!opt_offset) { - opt_offset = 0; - } - - var W = this.W_; - - // get 16 big endian words - if (goog.isString(buf)) { - for (var i = 0; i < 16; i++) { - // TODO(user): [bug 8140122] Recent versions of Safari for Mac OS and iOS - // have a bug that turns the post-increment ++ operator into pre-increment - // during JIT compilation. We have code that depends heavily on SHA-1 for - // correctness and which is affected by this bug, so I've removed all uses - // of post-increment ++ in which the result value is used. We can revert - // this change once the Safari bug - // (https://bugs.webkit.org/show_bug.cgi?id=109036) has been fixed and - // most clients have been updated. - W[i] = (buf.charCodeAt(opt_offset) << 24) | - (buf.charCodeAt(opt_offset + 1) << 16) | - (buf.charCodeAt(opt_offset + 2) << 8) | - (buf.charCodeAt(opt_offset + 3)); - opt_offset += 4; - } - } else { - for (var i = 0; i < 16; i++) { - W[i] = (buf[opt_offset] << 24) | - (buf[opt_offset + 1] << 16) | - (buf[opt_offset + 2] << 8) | - (buf[opt_offset + 3]); - opt_offset += 4; - } - } - - // expand to 80 words - for (var i = 16; i < 80; i++) { - var t = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16]; - W[i] = ((t << 1) | (t >>> 31)) & 0xffffffff; - } - - var a = this.chain_[0]; - var b = this.chain_[1]; - var c = this.chain_[2]; - var d = this.chain_[3]; - var e = this.chain_[4]; - var f, k; - - // TODO(user): Try to unroll this loop to speed up the computation. - for (var i = 0; i < 80; i++) { - if (i < 40) { - if (i < 20) { - f = d ^ (b & (c ^ d)); - k = 0x5a827999; - } else { - f = b ^ c ^ d; - k = 0x6ed9eba1; - } - } else { - if (i < 60) { - f = (b & c) | (d & (b | c)); - k = 0x8f1bbcdc; - } else { - f = b ^ c ^ d; - k = 0xca62c1d6; - } - } - - var t = (((a << 5) | (a >>> 27)) + f + e + k + W[i]) & 0xffffffff; - e = d; - d = c; - c = ((b << 30) | (b >>> 2)) & 0xffffffff; - b = a; - a = t; - } - - this.chain_[0] = (this.chain_[0] + a) & 0xffffffff; - this.chain_[1] = (this.chain_[1] + b) & 0xffffffff; - this.chain_[2] = (this.chain_[2] + c) & 0xffffffff; - this.chain_[3] = (this.chain_[3] + d) & 0xffffffff; - this.chain_[4] = (this.chain_[4] + e) & 0xffffffff; -}; - - -/** @override */ -goog.crypt.Sha1.prototype.update = function(bytes, opt_length) { - // TODO(johnlenz): tighten the function signature and remove this check - if (bytes == null) { - return; - } - - if (!goog.isDef(opt_length)) { - opt_length = bytes.length; - } - - var lengthMinusBlock = opt_length - this.blockSize; - var n = 0; - // Using local instead of member variables gives ~5% speedup on Firefox 16. - var buf = this.buf_; - var inbuf = this.inbuf_; - - // The outer while loop should execute at most twice. - while (n < opt_length) { - // When we have no data in the block to top up, we can directly process the - // input buffer (assuming it contains sufficient data). This gives ~25% - // speedup on Chrome 23 and ~15% speedup on Firefox 16, but requires that - // the data is provided in large chunks (or in multiples of 64 bytes). - if (inbuf == 0) { - while (n <= lengthMinusBlock) { - this.compress_(bytes, n); - n += this.blockSize; - } - } - - if (goog.isString(bytes)) { - while (n < opt_length) { - buf[inbuf] = bytes.charCodeAt(n); - ++inbuf; - ++n; - if (inbuf == this.blockSize) { - this.compress_(buf); - inbuf = 0; - // Jump to the outer loop so we use the full-block optimization. - break; - } - } - } else { - while (n < opt_length) { - buf[inbuf] = bytes[n]; - ++inbuf; - ++n; - if (inbuf == this.blockSize) { - this.compress_(buf); - inbuf = 0; - // Jump to the outer loop so we use the full-block optimization. - break; - } - } - } - } - - this.inbuf_ = inbuf; - this.total_ += opt_length; -}; - - -/** @override */ -goog.crypt.Sha1.prototype.digest = function() { - var digest = []; - var totalBits = this.total_ * 8; - - // Add pad 0x80 0x00*. - if (this.inbuf_ < 56) { - this.update(this.pad_, 56 - this.inbuf_); - } else { - this.update(this.pad_, this.blockSize - (this.inbuf_ - 56)); - } - - // Add # bits. - for (var i = this.blockSize - 1; i >= 56; i--) { - this.buf_[i] = totalBits & 255; - totalBits /= 256; // Don't use bit-shifting here! - } - - this.compress_(this.buf_); - - var n = 0; - for (var i = 0; i < 5; i++) { - for (var j = 24; j >= 0; j -= 8) { - digest[n] = (this.chain_[i] >> j) & 255; - ++n; - } - } - - return digest; -}; diff --git a/src/database/third_party/closure-library/closure/goog/crypt/sha1_perf.html b/src/database/third_party/closure-library/closure/goog/crypt/sha1_perf.html deleted file mode 100644 index b26c155340d..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/sha1_perf.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - -Closure Performance Tests - goog.crypt.Sha1 - - - - - -

Closure Performance Tests - goog.crypt.Sha1

-

-User-agent: - -

- - - - diff --git a/src/database/third_party/closure-library/closure/goog/crypt/sha1_test.html b/src/database/third_party/closure-library/closure/goog/crypt/sha1_test.html deleted file mode 100644 index e679016dbfa..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/sha1_test.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - Closure Unit Tests - goog.crypt.sha1 - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/crypt/sha1_test.js b/src/database/third_party/closure-library/closure/goog/crypt/sha1_test.js deleted file mode 100644 index f6d5ea89f9f..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/sha1_test.js +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2010 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.crypt.Sha1Test'); -goog.setTestOnly('goog.crypt.Sha1Test'); - -goog.require('goog.crypt'); -goog.require('goog.crypt.Sha1'); -goog.require('goog.crypt.hashTester'); -goog.require('goog.testing.jsunit'); -goog.require('goog.userAgent'); - -function testBasicOperations() { - var sha1 = new goog.crypt.Sha1(); - goog.crypt.hashTester.runBasicTests(sha1); -} - -function testBlockOperations() { - var sha1 = new goog.crypt.Sha1(); - goog.crypt.hashTester.runBlockTests(sha1, 64); -} - -function testHashing() { - // Test vectors from: - // csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf - - // Empty stream. - var sha1 = new goog.crypt.Sha1(); - assertEquals('da39a3ee5e6b4b0d3255bfef95601890afd80709', - goog.crypt.byteArrayToHex(sha1.digest())); - - // Test one-block message. - sha1.reset(); - sha1.update([0x61, 0x62, 0x63]); - assertEquals('a9993e364706816aba3e25717850c26c9cd0d89d', - goog.crypt.byteArrayToHex(sha1.digest())); - - // Test multi-block message. - sha1.reset(); - sha1.update('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'); - assertEquals('84983e441c3bd26ebaae4aa1f95129e5e54670f1', - goog.crypt.byteArrayToHex(sha1.digest())); - - // The following test might cause timeouts on IE7. - if (!goog.userAgent.IE || goog.userAgent.isVersionOrHigher('8')) { - // Test long message. - var thousandAs = []; - for (var i = 0; i < 1000; ++i) { - thousandAs[i] = 0x61; - } - sha1.reset(); - for (var i = 0; i < 1000; ++i) { - sha1.update(thousandAs); - } - assertEquals('34aa973cd4c4daa4f61eeb2bdbad27316534016f', - goog.crypt.byteArrayToHex(sha1.digest())); - } - - // Test standard message. - sha1.reset(); - sha1.update('The quick brown fox jumps over the lazy dog'); - assertEquals('2fd4e1c67a2d28fced849ee1bb76e7391b93eb12', - goog.crypt.byteArrayToHex(sha1.digest())); -} diff --git a/src/database/third_party/closure-library/closure/goog/crypt/sha2.js b/src/database/third_party/closure-library/closure/goog/crypt/sha2.js deleted file mode 100644 index eae5b142652..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/sha2.js +++ /dev/null @@ -1,338 +0,0 @@ -// Copyright 2012 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Base class for SHA-2 cryptographic hash. - * - * Variable names follow the notation in FIPS PUB 180-3: - * http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf. - * - * Some code similar to SHA1 are borrowed from sha1.js written by mschilder@. - * - */ - -goog.provide('goog.crypt.Sha2'); - -goog.require('goog.array'); -goog.require('goog.asserts'); -goog.require('goog.crypt.Hash'); - - - -/** - * SHA-2 cryptographic hash constructor. - * This constructor should not be used directly to create the object. Rather, - * one should use the constructor of the sub-classes. - * @param {number} numHashBlocks The size of output in 16-byte blocks. - * @param {!Array} initHashBlocks The hash-specific initialization - * @constructor - * @extends {goog.crypt.Hash} - * @struct - */ -goog.crypt.Sha2 = function(numHashBlocks, initHashBlocks) { - goog.crypt.Sha2.base(this, 'constructor'); - - this.blockSize = goog.crypt.Sha2.BLOCKSIZE_; - - /** - * A chunk holding the currently processed message bytes. Once the chunk has - * 64 bytes, we feed it into computeChunk_ function and reset this.chunk_. - * @private {!Array|!Uint8Array} - */ - this.chunk_ = goog.global['Uint8Array'] ? - new Uint8Array(this.blockSize) : new Array(this.blockSize); - - /** - * Current number of bytes in this.chunk_. - * @private {number} - */ - this.inChunk_ = 0; - - /** - * Total number of bytes in currently processed message. - * @private {number} - */ - this.total_ = 0; - - - /** - * Holds the previous values of accumulated hash a-h in the computeChunk_ - * function. - * @private {!Array|!Int32Array} - */ - this.hash_ = []; - - /** - * The number of output hash blocks (each block is 4 bytes long). - * @private {number} - */ - this.numHashBlocks_ = numHashBlocks; - - /** - * @private {!Array} initHashBlocks - */ - this.initHashBlocks_ = initHashBlocks; - - /** - * Temporary array used in chunk computation. Allocate here as a - * member rather than as a local within computeChunk_() as a - * performance optimization to reduce the number of allocations and - * reduce garbage collection. - * @private {!Int32Array|!Array} - */ - this.w_ = goog.global['Int32Array'] ? new Int32Array(64) : new Array(64); - - if (!goog.isDef(goog.crypt.Sha2.Kx_)) { - // This is the first time this constructor has been called. - if (goog.global['Int32Array']) { - // Typed arrays exist - goog.crypt.Sha2.Kx_ = new Int32Array(goog.crypt.Sha2.K_); - } else { - // Typed arrays do not exist - goog.crypt.Sha2.Kx_ = goog.crypt.Sha2.K_; - } - } - - this.reset(); -}; -goog.inherits(goog.crypt.Sha2, goog.crypt.Hash); - - -/** - * The block size - * @private {number} - */ -goog.crypt.Sha2.BLOCKSIZE_ = 512 / 8; - - -/** - * Contains data needed to pad messages less than BLOCK_SIZE_ bytes. - * @private {!Array} - */ -goog.crypt.Sha2.PADDING_ = goog.array.concat(128, - goog.array.repeat(0, goog.crypt.Sha2.BLOCKSIZE_ - 1)); - - -/** @override */ -goog.crypt.Sha2.prototype.reset = function() { - this.inChunk_ = 0; - this.total_ = 0; - this.hash_ = goog.global['Int32Array'] ? - new Int32Array(this.initHashBlocks_) : - goog.array.clone(this.initHashBlocks_); -}; - - -/** - * Helper function to compute the hashes for a given 512-bit message chunk. - * @private - */ -goog.crypt.Sha2.prototype.computeChunk_ = function() { - var chunk = this.chunk_; - goog.asserts.assert(chunk.length == this.blockSize); - var rounds = 64; - - // Divide the chunk into 16 32-bit-words. - var w = this.w_; - var index = 0; - var offset = 0; - while (offset < chunk.length) { - w[index++] = (chunk[offset] << 24) | - (chunk[offset + 1] << 16) | - (chunk[offset + 2] << 8) | - (chunk[offset + 3]); - offset = index * 4; - } - - // Extend the w[] array to be the number of rounds. - for (var i = 16; i < rounds; i++) { - var w_15 = w[i - 15] | 0; - var s0 = ((w_15 >>> 7) | (w_15 << 25)) ^ - ((w_15 >>> 18) | (w_15 << 14)) ^ - (w_15 >>> 3); - var w_2 = w[i - 2] | 0; - var s1 = ((w_2 >>> 17) | (w_2 << 15)) ^ - ((w_2 >>> 19) | (w_2 << 13)) ^ - (w_2 >>> 10); - - // As a performance optimization, construct the sum a pair at a time - // with casting to integer (bitwise OR) to eliminate unnecessary - // double<->integer conversions. - var partialSum1 = ((w[i - 16] | 0) + s0) | 0; - var partialSum2 = ((w[i - 7] | 0) + s1) | 0; - w[i] = (partialSum1 + partialSum2) | 0; - } - - var a = this.hash_[0] | 0; - var b = this.hash_[1] | 0; - var c = this.hash_[2] | 0; - var d = this.hash_[3] | 0; - var e = this.hash_[4] | 0; - var f = this.hash_[5] | 0; - var g = this.hash_[6] | 0; - var h = this.hash_[7] | 0; - for (var i = 0; i < rounds; i++) { - var S0 = ((a >>> 2) | (a << 30)) ^ - ((a >>> 13) | (a << 19)) ^ - ((a >>> 22) | (a << 10)); - var maj = ((a & b) ^ (a & c) ^ (b & c)); - var t2 = (S0 + maj) | 0; - var S1 = ((e >>> 6) | (e << 26)) ^ - ((e >>> 11) | (e << 21)) ^ - ((e >>> 25) | (e << 7)); - var ch = ((e & f) ^ ((~ e) & g)); - - // As a performance optimization, construct the sum a pair at a time - // with casting to integer (bitwise OR) to eliminate unnecessary - // double<->integer conversions. - var partialSum1 = (h + S1) | 0; - var partialSum2 = (ch + (goog.crypt.Sha2.Kx_[i] | 0)) | 0; - var partialSum3 = (partialSum2 + (w[i] | 0)) | 0; - var t1 = (partialSum1 + partialSum3) | 0; - - h = g; - g = f; - f = e; - e = (d + t1) | 0; - d = c; - c = b; - b = a; - a = (t1 + t2) | 0; - } - - this.hash_[0] = (this.hash_[0] + a) | 0; - this.hash_[1] = (this.hash_[1] + b) | 0; - this.hash_[2] = (this.hash_[2] + c) | 0; - this.hash_[3] = (this.hash_[3] + d) | 0; - this.hash_[4] = (this.hash_[4] + e) | 0; - this.hash_[5] = (this.hash_[5] + f) | 0; - this.hash_[6] = (this.hash_[6] + g) | 0; - this.hash_[7] = (this.hash_[7] + h) | 0; -}; - - -/** @override */ -goog.crypt.Sha2.prototype.update = function(message, opt_length) { - if (!goog.isDef(opt_length)) { - opt_length = message.length; - } - // Process the message from left to right up to |opt_length| bytes. - // When we get a 512-bit chunk, compute the hash of it and reset - // this.chunk_. The message might not be multiple of 512 bits so we - // might end up with a chunk that is less than 512 bits. We store - // such partial chunk in this.chunk_ and it will be filled up later - // in digest(). - var n = 0; - var inChunk = this.inChunk_; - - // The input message could be either byte array of string. - if (goog.isString(message)) { - while (n < opt_length) { - this.chunk_[inChunk++] = message.charCodeAt(n++); - if (inChunk == this.blockSize) { - this.computeChunk_(); - inChunk = 0; - } - } - } else if (goog.isArray(message)) { - while (n < opt_length) { - var b = message[n++]; - if (!('number' == typeof b && 0 <= b && 255 >= b && b == (b | 0))) { - throw Error('message must be a byte array'); - } - this.chunk_[inChunk++] = b; - if (inChunk == this.blockSize) { - this.computeChunk_(); - inChunk = 0; - } - } - } else { - throw Error('message must be string or array'); - } - - // Record the current bytes in chunk to support partial update. - this.inChunk_ = inChunk; - - // Record total message bytes we have processed so far. - this.total_ += opt_length; -}; - - -/** @override */ -goog.crypt.Sha2.prototype.digest = function() { - var digest = []; - var totalBits = this.total_ * 8; - - // Append pad 0x80 0x00*. - if (this.inChunk_ < 56) { - this.update(goog.crypt.Sha2.PADDING_, 56 - this.inChunk_); - } else { - this.update(goog.crypt.Sha2.PADDING_, - this.blockSize - (this.inChunk_ - 56)); - } - - // Append # bits in the 64-bit big-endian format. - for (var i = 63; i >= 56; i--) { - this.chunk_[i] = totalBits & 255; - totalBits /= 256; // Don't use bit-shifting here! - } - this.computeChunk_(); - - // Finally, output the result digest. - var n = 0; - for (var i = 0; i < this.numHashBlocks_; i++) { - for (var j = 24; j >= 0; j -= 8) { - digest[n++] = ((this.hash_[i] >> j) & 255); - } - } - return digest; -}; - - -/** - * Constants used in SHA-2. - * @const - * @private {!Array} - */ -goog.crypt.Sha2.K_ = [ - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -]; - - -/** - * Sha2.K as an Int32Array if this JS supports typed arrays; otherwise, - * the same array as Sha2.K. - * - * The compiler cannot remove an Int32Array, even if it is not needed - * (There are certain cases where creating an Int32Array is not - * side-effect free). Instead, the first time we construct a Sha2 - * instance, we convert or assign Sha2.K as appropriate. - * @private {undefined|!Array|!Int32Array} - */ -goog.crypt.Sha2.Kx_; diff --git a/src/database/third_party/closure-library/closure/goog/crypt/sha224.js b/src/database/third_party/closure-library/closure/goog/crypt/sha224.js deleted file mode 100644 index 40c59e9013b..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/sha224.js +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2012 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview SHA-224 cryptographic hash. - * - * Usage: - * var sha224 = new goog.crypt.Sha224(); - * sha224.update(bytes); - * var hash = sha224.digest(); - * - */ - -goog.provide('goog.crypt.Sha224'); - -goog.require('goog.crypt.Sha2'); - - - -/** - * SHA-224 cryptographic hash constructor. - * - * @constructor - * @extends {goog.crypt.Sha2} - * @final - * @struct - */ -goog.crypt.Sha224 = function() { - goog.crypt.Sha224.base(this, 'constructor', - 7, goog.crypt.Sha224.INIT_HASH_BLOCK_); -}; -goog.inherits(goog.crypt.Sha224, goog.crypt.Sha2); - - -/** @private {!Array} */ -goog.crypt.Sha224.INIT_HASH_BLOCK_ = [ - 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, - 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4]; - diff --git a/src/database/third_party/closure-library/closure/goog/crypt/sha224_perf.html b/src/database/third_party/closure-library/closure/goog/crypt/sha224_perf.html deleted file mode 100644 index 4c39e6440a5..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/sha224_perf.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - -Closure Performance Tests - goog.crypt.Sha224 - - - - - -

Closure Performance Tests - goog.crypt.Sha224

-

-User-agent: - -

- - - - diff --git a/src/database/third_party/closure-library/closure/goog/crypt/sha224_test.html b/src/database/third_party/closure-library/closure/goog/crypt/sha224_test.html deleted file mode 100644 index 1a76672c6c7..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/sha224_test.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - Closure Unit Tests - goog.crypt.sha224 - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/crypt/sha224_test.js b/src/database/third_party/closure-library/closure/goog/crypt/sha224_test.js deleted file mode 100644 index 65f1ce2229e..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/sha224_test.js +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2012 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.crypt.Sha224Test'); -goog.setTestOnly('goog.crypt.Sha224Test'); - -goog.require('goog.crypt'); -goog.require('goog.crypt.Sha224'); -goog.require('goog.crypt.hashTester'); -goog.require('goog.testing.jsunit'); - -function testBasicOperations() { - var sha224 = new goog.crypt.Sha224(); - goog.crypt.hashTester.runBasicTests(sha224); -} - -function testHashing() { - // Some test vectors from: - // csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf - - var sha224 = new goog.crypt.Sha224(); - - // NIST one block test vector. - sha224.update(goog.crypt.stringToByteArray('abc')); - assertEquals( - '23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7', - goog.crypt.byteArrayToHex(sha224.digest())); - - // NIST multi-block test vector. - sha224.reset(); - sha224.update( - goog.crypt.stringToByteArray( - 'abcdbcdecdefdefgefghfghighij' + - 'hijkijkljklmklmnlmnomnopnopq')); - assertEquals( - '75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525', - goog.crypt.byteArrayToHex(sha224.digest())); - - // Message larger than one block (but less than two). - sha224.reset(); - var biggerThanOneBlock = 'abcdbcdecdefdefgefghfghighij' + - 'hijkijkljklmklmnlmnomnopnopq' + - 'asdfljhr78yasdfljh45opa78sdf' + - '120839414104897aavnasdfafasd'; - assertTrue(biggerThanOneBlock.length > goog.crypt.Sha2.BLOCKSIZE_ && - biggerThanOneBlock.length < 2 * goog.crypt.Sha2.BLOCKSIZE_); - sha224.update(goog.crypt.stringToByteArray(biggerThanOneBlock)); - assertEquals( - '27c9b678012becd6891bac653f355b2d26f63132e840644d565f5dac', - goog.crypt.byteArrayToHex(sha224.digest())); - - // Message larger than two blocks. - sha224.reset(); - var biggerThanTwoBlocks = 'abcdbcdecdefdefgefghfghighij' + - 'hijkijkljklmklmnlmnomnopnopq' + - 'asdfljhr78yasdfljh45opa78sdf' + - '120839414104897aavnasdfafasd' + - 'laasdouvhalacbnalalseryalcla'; - assertTrue(biggerThanTwoBlocks.length > 2 * goog.crypt.Sha2.BLOCKSIZE_); - sha224.update(goog.crypt.stringToByteArray(biggerThanTwoBlocks)); - assertEquals( - '1c2c1455cc984eef6f25ec9d79b1c661b3794887c3d0b24111ed9803', - goog.crypt.byteArrayToHex(sha224.digest())); -} diff --git a/src/database/third_party/closure-library/closure/goog/crypt/sha256.js b/src/database/third_party/closure-library/closure/goog/crypt/sha256.js deleted file mode 100644 index 38dafb07100..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/sha256.js +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2012 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview SHA-256 cryptographic hash. - * - * Usage: - * var sha256 = new goog.crypt.Sha256(); - * sha256.update(bytes); - * var hash = sha256.digest(); - * - */ - -goog.provide('goog.crypt.Sha256'); - -goog.require('goog.crypt.Sha2'); - - - -/** - * SHA-256 cryptographic hash constructor. - * - * @constructor - * @extends {goog.crypt.Sha2} - * @final - * @struct - */ -goog.crypt.Sha256 = function() { - goog.crypt.Sha256.base(this, 'constructor', - 8, goog.crypt.Sha256.INIT_HASH_BLOCK_); -}; -goog.inherits(goog.crypt.Sha256, goog.crypt.Sha2); - - -/** @private {!Array} */ -goog.crypt.Sha256.INIT_HASH_BLOCK_ = [ - 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, - 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19]; diff --git a/src/database/third_party/closure-library/closure/goog/crypt/sha256_perf.html b/src/database/third_party/closure-library/closure/goog/crypt/sha256_perf.html deleted file mode 100644 index 0b7922b3f23..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/sha256_perf.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - -Closure Performance Tests - goog.crypt.Sha256 - - - - - -

Closure Performance Tests - goog.crypt.Sha256

-

-User-agent: - -

- - - - diff --git a/src/database/third_party/closure-library/closure/goog/crypt/sha256_test.html b/src/database/third_party/closure-library/closure/goog/crypt/sha256_test.html deleted file mode 100644 index 60a5738c45a..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/sha256_test.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - Closure Unit Tests - goog.crypt.sha256 - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/crypt/sha256_test.js b/src/database/third_party/closure-library/closure/goog/crypt/sha256_test.js deleted file mode 100644 index eac5a88cb08..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/sha256_test.js +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2012 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.crypt.Sha256Test'); -goog.setTestOnly('goog.crypt.Sha256Test'); - -goog.require('goog.crypt'); -goog.require('goog.crypt.Sha256'); -goog.require('goog.crypt.hashTester'); -goog.require('goog.testing.jsunit'); - -function testBasicOperations() { - var sha256 = new goog.crypt.Sha256(); - goog.crypt.hashTester.runBasicTests(sha256); -} - -function testHashing() { - // Some test vectors from: - // csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf - - var sha256 = new goog.crypt.Sha256(); - - // Empty message. - sha256.update([]); - assertEquals( - 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', - goog.crypt.byteArrayToHex(sha256.digest())); - - // NIST one block test vector. - sha256.reset(); - sha256.update(goog.crypt.stringToByteArray('abc')); - assertEquals( - 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad', - goog.crypt.byteArrayToHex(sha256.digest())); - - // NIST multi-block test vector. - sha256.reset(); - sha256.update( - goog.crypt.stringToByteArray( - 'abcdbcdecdefdefgefghfghighij' + - 'hijkijkljklmklmnlmnomnopnopq')); - assertEquals( - '248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1', - goog.crypt.byteArrayToHex(sha256.digest())); - - // Message larger than one block (but less than two). - sha256.reset(); - var biggerThanOneBlock = 'abcdbcdecdefdefgefghfghighij' + - 'hijkijkljklmklmnlmnomnopnopq' + - 'asdfljhr78yasdfljh45opa78sdf' + - '120839414104897aavnasdfafasd'; - assertTrue(biggerThanOneBlock.length > goog.crypt.Sha2.BLOCKSIZE_ && - biggerThanOneBlock.length < 2 * goog.crypt.Sha2.BLOCKSIZE_); - sha256.update(goog.crypt.stringToByteArray(biggerThanOneBlock)); - assertEquals( - '390a5035433e46b740600f3117d11ece3c64706dc889106666ac04fe4f458abc', - goog.crypt.byteArrayToHex(sha256.digest())); - - // Message larger than two blocks. - sha256.reset(); - var biggerThanTwoBlocks = 'abcdbcdecdefdefgefghfghighij' + - 'hijkijkljklmklmnlmnomnopnopq' + - 'asdfljhr78yasdfljh45opa78sdf' + - '120839414104897aavnasdfafasd' + - 'laasdouvhalacbnalalseryalcla'; - assertTrue(biggerThanTwoBlocks.length > 2 * goog.crypt.Sha2.BLOCKSIZE_); - sha256.update(goog.crypt.stringToByteArray(biggerThanTwoBlocks)); - assertEquals( - 'd655c513fd347e9be372d891f8bb42895ca310fabf6ead6681ebc66a04e84db5', - goog.crypt.byteArrayToHex(sha256.digest())); -} - - -/** Check that the code checks for bad input */ -function testBadInput() { - assertThrows('Bad input', function() { - new goog.crypt.Sha256().update({}); - }); - assertThrows('Floating point not allows', function() { - new goog.crypt.Sha256().update([1, 2, 3, 4, 4.5]); - }); - assertThrows('Negative not allowed', function() { - new goog.crypt.Sha256().update([1, 2, 3, 4, -10]); - }); - assertThrows('Must be byte array', function() { - new goog.crypt.Sha256().update([1, 2, 3, 4, {}]); - }); -} diff --git a/src/database/third_party/closure-library/closure/goog/crypt/sha2_64bit.js b/src/database/third_party/closure-library/closure/goog/crypt/sha2_64bit.js deleted file mode 100644 index 077b9c43429..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/sha2_64bit.js +++ /dev/null @@ -1,550 +0,0 @@ -// Copyright 2014 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Base class for the 64-bit SHA-2 cryptographic hashes. - * - * Variable names follow the notation in FIPS PUB 180-3: - * http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf. - * - * This code borrows heavily from the 32-bit SHA2 implementation written by - * Yue Zhang (zysxqn@). - * - * @author fy@google.com (Frank Yellin) - */ - -goog.provide('goog.crypt.Sha2_64bit'); - -goog.require('goog.array'); -goog.require('goog.asserts'); -goog.require('goog.crypt.Hash'); -goog.require('goog.math.Long'); - - - -/** - * Constructs a SHA-2 64-bit cryptographic hash. - * This class should not be used. Rather, one should use one of its - * subclasses. - * @constructor - * @param {number} numHashBlocks The size of the output in 16-byte blocks - * @param {!Array} initHashBlocks The hash-specific initialization - * vector, as a sequence of sixteen 32-bit numbers. - * @extends {goog.crypt.Hash} - * @struct - */ -goog.crypt.Sha2_64bit = function(numHashBlocks, initHashBlocks) { - goog.crypt.Sha2_64bit.base(this, 'constructor'); - - /** - * The number of bytes that are digested in each pass of this hasher. - * @const {number} - */ - this.blockSize = goog.crypt.Sha2_64bit.BLOCK_SIZE_; - - /** - * A chunk holding the currently processed message bytes. Once the chunk has - * {@code this.blocksize} bytes, we feed it into [@code computeChunk_}. - * @private {!Uint8Array|!Array} - */ - this.chunk_ = goog.isDef(goog.global.Uint8Array) ? - new Uint8Array(goog.crypt.Sha2_64bit.BLOCK_SIZE_) : - new Array(goog.crypt.Sha2_64bit.BLOCK_SIZE_); - - /** - * Current number of bytes in {@code this.chunk_}. - * @private {number} - */ - this.chunkBytes_ = 0; - - /** - * Total number of bytes in currently processed message. - * @private {number} - */ - this.total_ = 0; - - /** - * Holds the previous values of accumulated hash a-h in the - * {@code computeChunk_} function. - * @private {!Array} - */ - this.hash_ = []; - - /** - * The number of blocks of output produced by this hash function, where each - * block is eight bytes long. - * @private {number} - */ - this.numHashBlocks_ = numHashBlocks; - - /** - * Temporary array used in chunk computation. Allocate here as a - * member rather than as a local within computeChunk_() as a - * performance optimization to reduce the number of allocations and - * reduce garbage collection. - * @type {!Array} - * @private - */ - this.w_ = []; - - /** - * The value to which {@code this.hash_} should be reset when this - * Hasher is reset. - * @private @const {!Array} - */ - this.initHashBlocks_ = goog.crypt.Sha2_64bit.toLongArray_(initHashBlocks); - - /** - * If true, we have taken the digest from this hasher, but we have not - * yet reset it. - * - * @private {boolean} - */ - this.needsReset_ = false; - - this.reset(); -}; -goog.inherits(goog.crypt.Sha2_64bit, goog.crypt.Hash); - - -/** - * The number of bytes that are digested in each pass of this hasher. - * @private @const {number} - */ -goog.crypt.Sha2_64bit.BLOCK_SIZE_ = 1024 / 8; - - -/** - * Contains data needed to pad messages less than {@code blocksize} bytes. - * @private {!Array} - */ -goog.crypt.Sha2_64bit.PADDING_ = goog.array.concat( - [0x80], goog.array.repeat(0, goog.crypt.Sha2_64bit.BLOCK_SIZE_ - 1)); - - -/** - * Resets this hash function. - * @override - */ -goog.crypt.Sha2_64bit.prototype.reset = function() { - this.chunkBytes_ = 0; - this.total_ = 0; - this.hash_ = goog.array.clone(this.initHashBlocks_); - this.needsReset_ = false; -}; - - -/** @override */ -goog.crypt.Sha2_64bit.prototype.update = function(message, opt_length) { - var length = goog.isDef(opt_length) ? opt_length : message.length; - - // Make sure this hasher is usable. - if (this.needsReset_) { - throw Error('this hasher needs to be reset'); - } - // Process the message from left to right up to |length| bytes. - // When we get a 512-bit chunk, compute the hash of it and reset - // this.chunk_. The message might not be multiple of 512 bits so we - // might end up with a chunk that is less than 512 bits. We store - // such partial chunk in chunk_ and it will be filled up later - // in digest(). - var chunkBytes = this.chunkBytes_; - - // The input message could be either byte array or string. - if (goog.isString(message)) { - for (var i = 0; i < length; i++) { - var b = message.charCodeAt(i); - if (b > 255) { - throw Error('Characters must be in range [0,255]'); - } - this.chunk_[chunkBytes++] = b; - if (chunkBytes == this.blockSize) { - this.computeChunk_(); - chunkBytes = 0; - } - } - } else if (goog.isArray(message)) { - for (var i = 0; i < length; i++) { - var b = message[i]; - // Hack: b|0 coerces b to an integer, so the last part confirms that - // b has no fractional part. - if (!goog.isNumber(b) || b < 0 || b > 255 || b != (b | 0)) { - throw Error('message must be a byte array'); - } - this.chunk_[chunkBytes++] = b; - if (chunkBytes == this.blockSize) { - this.computeChunk_(); - chunkBytes = 0; - } - } - } else { - throw Error('message must be string or array'); - } - - // Record the current bytes in chunk to support partial update. - this.chunkBytes_ = chunkBytes; - - // Record total message bytes we have processed so far. - this.total_ += length; -}; - - -/** @override */ -goog.crypt.Sha2_64bit.prototype.digest = function() { - if (this.needsReset_) { - throw Error('this hasher needs to be reset'); - } - var totalBits = this.total_ * 8; - - // Append pad 0x80 0x00* until this.chunkBytes_ == 112 - if (this.chunkBytes_ < 112) { - this.update(goog.crypt.Sha2_64bit.PADDING_, 112 - this.chunkBytes_); - } else { - // the rest of this block, plus 112 bytes of next block - this.update(goog.crypt.Sha2_64bit.PADDING_, - this.blockSize - this.chunkBytes_ + 112); - } - - // Append # bits in the 64-bit big-endian format. - for (var i = 127; i >= 112; i--) { - this.chunk_[i] = totalBits & 255; - totalBits /= 256; // Don't use bit-shifting here! - } - this.computeChunk_(); - - // Finally, output the result digest. - var n = 0; - var digest = new Array(8 * this.numHashBlocks_); - for (var i = 0; i < this.numHashBlocks_; i++) { - var block = this.hash_[i]; - var high = block.getHighBits(); - var low = block.getLowBits(); - for (var j = 24; j >= 0; j -= 8) { - digest[n++] = ((high >> j) & 255); - } - for (var j = 24; j >= 0; j -= 8) { - digest[n++] = ((low >> j) & 255); - } - } - - // The next call to this hasher must be a reset - this.needsReset_ = true; - return digest; -}; - - -/** - * Updates this hash by processing the 1024-bit message chunk in this.chunk_. - * @private - */ -goog.crypt.Sha2_64bit.prototype.computeChunk_ = function() { - var chunk = this.chunk_; - var K_ = goog.crypt.Sha2_64bit.K_; - - // Divide the chunk into 16 64-bit-words. - var w = this.w_; - for (var i = 0; i < 16; i++) { - var offset = i * 8; - w[i] = new goog.math.Long( - (chunk[offset + 4] << 24) | (chunk[offset + 5] << 16) | - (chunk[offset + 6] << 8) | (chunk[offset + 7]), - (chunk[offset] << 24) | (chunk[offset + 1] << 16) | - (chunk[offset + 2] << 8) | (chunk[offset + 3])); - - } - - // Extend the w[] array to be the number of rounds. - for (var i = 16; i < 80; i++) { - var s0 = this.sigma0_(w[i - 15]); - var s1 = this.sigma1_(w[i - 2]); - w[i] = this.sum_(w[i - 16], w[i - 7], s0, s1); - } - - var a = this.hash_[0]; - var b = this.hash_[1]; - var c = this.hash_[2]; - var d = this.hash_[3]; - var e = this.hash_[4]; - var f = this.hash_[5]; - var g = this.hash_[6]; - var h = this.hash_[7]; - for (var i = 0; i < 80; i++) { - var S0 = this.Sigma0_(a); - var maj = this.majority_(a, b, c); - var t2 = S0.add(maj); - var S1 = this.Sigma1_(e); - var ch = this.choose_(e, f, g); - var t1 = this.sum_(h, S1, ch, K_[i], w[i]); - h = g; - g = f; - f = e; - e = d.add(t1); - d = c; - c = b; - b = a; - a = t1.add(t2); - } - - this.hash_[0] = this.hash_[0].add(a); - this.hash_[1] = this.hash_[1].add(b); - this.hash_[2] = this.hash_[2].add(c); - this.hash_[3] = this.hash_[3].add(d); - this.hash_[4] = this.hash_[4].add(e); - this.hash_[5] = this.hash_[5].add(f); - this.hash_[6] = this.hash_[6].add(g); - this.hash_[7] = this.hash_[7].add(h); -}; - - -/** - * Calculates the SHA2 64-bit sigma0 function. - * rotateRight(value, 1) ^ rotateRight(value, 8) ^ (value >>> 7) - * - * @private - * @param {!goog.math.Long} value - * @return {!goog.math.Long} - */ -goog.crypt.Sha2_64bit.prototype.sigma0_ = function(value) { - var valueLow = value.getLowBits(); - var valueHigh = value.getHighBits(); - // Implementation note: We purposely do not use the shift operations defined - // in goog.math.Long. Inlining the code for specific values of shifting and - // not generating the intermediate results doubles the speed of this code. - var low = (valueLow >>> 1) ^ (valueHigh << 31) ^ - (valueLow >>> 8) ^ (valueHigh << 24) ^ - (valueLow >>> 7) ^ (valueHigh << 25); - var high = (valueHigh >>> 1) ^ (valueLow << 31) ^ - (valueHigh >>> 8) ^ (valueLow << 24) ^ - (valueHigh >>> 7); - return new goog.math.Long(low, high); -}; - - -/** - * Calculates the SHA2 64-bit sigma1 function. - * rotateRight(value, 19) ^ rotateRight(value, 61) ^ (value >>> 6) - * - * @private - * @param {!goog.math.Long} value - * @return {!goog.math.Long} - */ -goog.crypt.Sha2_64bit.prototype.sigma1_ = function(value) { - var valueLow = value.getLowBits(); - var valueHigh = value.getHighBits(); - // Implementation note: See _sigma0() above - var low = (valueLow >>> 19) ^ (valueHigh << 13) ^ - (valueHigh >>> 29) ^ (valueLow << 3) ^ - (valueLow >>> 6) ^ (valueHigh << 26); - var high = (valueHigh >>> 19) ^ (valueLow << 13) ^ - (valueLow >>> 29) ^ (valueHigh << 3) ^ - (valueHigh >>> 6); - return new goog.math.Long(low, high); -}; - - -/** - * Calculates the SHA2 64-bit Sigma0 function. - * rotateRight(value, 28) ^ rotateRight(value, 34) ^ rotateRight(value, 39) - * - * @private - * @param {!goog.math.Long} value - * @return {!goog.math.Long} - */ -goog.crypt.Sha2_64bit.prototype.Sigma0_ = function(value) { - var valueLow = value.getLowBits(); - var valueHigh = value.getHighBits(); - // Implementation note: See _sigma0() above - var low = (valueLow >>> 28) ^ (valueHigh << 4) ^ - (valueHigh >>> 2) ^ (valueLow << 30) ^ - (valueHigh >>> 7) ^ (valueLow << 25); - var high = (valueHigh >>> 28) ^ (valueLow << 4) ^ - (valueLow >>> 2) ^ (valueHigh << 30) ^ - (valueLow >>> 7) ^ (valueHigh << 25); - return new goog.math.Long(low, high); -}; - - -/** - * Calculates the SHA2 64-bit Sigma1 function. - * rotateRight(value, 14) ^ rotateRight(value, 18) ^ rotateRight(value, 41) - * - * @private - * @param {!goog.math.Long} value - * @return {!goog.math.Long} - */ -goog.crypt.Sha2_64bit.prototype.Sigma1_ = function(value) { - var valueLow = value.getLowBits(); - var valueHigh = value.getHighBits(); - // Implementation note: See _sigma0() above - var low = (valueLow >>> 14) ^ (valueHigh << 18) ^ - (valueLow >>> 18) ^ (valueHigh << 14) ^ - (valueHigh >>> 9) ^ (valueLow << 23); - var high = (valueHigh >>> 14) ^ (valueLow << 18) ^ - (valueHigh >>> 18) ^ (valueLow << 14) ^ - (valueLow >>> 9) ^ (valueHigh << 23); - return new goog.math.Long(low, high); -}; - - -/** - * Calculates the SHA-2 64-bit choose function. - * - * This function uses {@code value} as a mask to choose bits from either - * {@code one} if the bit is set or {@code two} if the bit is not set. - * - * @private - * @param {!goog.math.Long} value - * @param {!goog.math.Long} one - * @param {!goog.math.Long} two - * @return {!goog.math.Long} - */ -goog.crypt.Sha2_64bit.prototype.choose_ = function(value, one, two) { - var valueLow = value.getLowBits(); - var valueHigh = value.getHighBits(); - return new goog.math.Long( - (valueLow & one.getLowBits()) | (~valueLow & two.getLowBits()), - (valueHigh & one.getHighBits()) | (~valueHigh & two.getHighBits())); -}; - - -/** - * Calculates the SHA-2 64-bit majority function. - * This function returns, for each bit position, the bit held by the majority - * of its three arguments. - * - * @private - * @param {!goog.math.Long} one - * @param {!goog.math.Long} two - * @param {!goog.math.Long} three - * @return {!goog.math.Long} - */ -goog.crypt.Sha2_64bit.prototype.majority_ = function(one, two, three) { - return new goog.math.Long( - (one.getLowBits() & two.getLowBits()) | - (two.getLowBits() & three.getLowBits()) | - (one.getLowBits() & three.getLowBits()), - (one.getHighBits() & two.getHighBits()) | - (two.getHighBits() & three.getHighBits()) | - (one.getHighBits() & three.getHighBits())); -}; - - -/** - * Adds two or more goog.math.Long values. - * - * @private - * @param {!goog.math.Long} one first summand - * @param {!goog.math.Long} two second summand - * @param {...goog.math.Long} var_args more arguments to sum - * @return {!goog.math.Long} The resulting sum. - */ -goog.crypt.Sha2_64bit.prototype.sum_ = function(one, two, var_args) { - // The low bits may be signed, but they represent a 32-bit unsigned quantity. - // We must be careful to normalize them. - // This doesn't matter for the high bits. - // Implementation note: Performance testing shows that this method runs - // fastest when the first two arguments are pulled out of the loop. - var low = (one.getLowBits() ^ 0x80000000) + (two.getLowBits() ^ 0x80000000); - var high = one.getHighBits() + two.getHighBits(); - for (var i = arguments.length - 1; i >= 2; --i) { - low += arguments[i].getLowBits() ^ 0x80000000; - high += arguments[i].getHighBits(); - } - // Because of the ^0x80000000, each value we added is 0x80000000 too small. - // Add arguments.length * 0x80000000 to the current sum. We can do this - // quickly by adding 0x80000000 to low when the number of arguments is - // odd, and adding (number of arguments) >> 1 to high. - if (arguments.length & 1) { - low += 0x80000000; - } - high += arguments.length >> 1; - - // If low is outside the range [0, 0xFFFFFFFF], its overflow or underflow - // should be added to high. We don't actually need to modify low or - // normalize high because the goog.math.Long constructor already does that. - high += Math.floor(low / 0x100000000); - return new goog.math.Long(low, high); -}; - - -/** - * Converts an array of 32-bit integers into an array of goog.math.Long - * elements. - * - * @private - * @param {!Array} values An array of 32-bit numbers. Its length - * must be even. Each pair of numbers represents a 64-bit integer - * in big-endian order - * @return {!Array} - */ -goog.crypt.Sha2_64bit.toLongArray_ = function(values) { - goog.asserts.assert(values.length % 2 == 0); - var result = []; - for (var i = 0; i < values.length; i += 2) { - result.push(new goog.math.Long(values[i + 1], values[i])); - } - return result; -}; - - -/** - * Fixed constants used in SHA-512 variants. - * - * These values are from Section 4.2.3 of - * http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf - * @const - * @private {!Array} - */ -goog.crypt.Sha2_64bit.K_ = goog.crypt.Sha2_64bit.toLongArray_([ - 0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd, - 0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc, - 0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019, - 0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118, - 0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe, - 0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2, - 0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1, - 0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694, - 0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3, - 0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65, - 0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483, - 0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5, - 0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210, - 0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4, - 0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725, - 0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70, - 0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926, - 0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df, - 0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8, - 0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b, - 0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001, - 0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30, - 0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910, - 0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8, - 0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53, - 0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8, - 0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb, - 0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3, - 0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60, - 0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec, - 0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9, - 0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b, - 0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207, - 0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178, - 0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6, - 0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b, - 0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493, - 0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c, - 0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a, - 0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817 -]); diff --git a/src/database/third_party/closure-library/closure/goog/crypt/sha2_64bit_test.html b/src/database/third_party/closure-library/closure/goog/crypt/sha2_64bit_test.html deleted file mode 100644 index 1637e8a24ca..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/sha2_64bit_test.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - Closure Unit Tests - goog.crypt.sha2 64-bit hashes - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/crypt/sha2_64bit_test.js b/src/database/third_party/closure-library/closure/goog/crypt/sha2_64bit_test.js deleted file mode 100644 index 23209468713..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/sha2_64bit_test.js +++ /dev/null @@ -1,278 +0,0 @@ -// Copyright 2014 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.crypt.Sha2_64bit_test'); -goog.setTestOnly('goog.crypt.Sha2_64bit_test'); - -goog.require('goog.array'); -goog.require('goog.crypt'); -goog.require('goog.crypt.Sha384'); -goog.require('goog.crypt.Sha512'); -goog.require('goog.crypt.Sha512_256'); -goog.require('goog.crypt.hashTester'); -goog.require('goog.testing.jsunit'); -goog.require('goog.userAgent'); - - -/** - * Each object in the test vector array is a source text and one or more - * hashes of that source text. The source text is either a string or a - * byte array. - *

- * All hash values, except for the empty string, are from public sources: - * csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf - * csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA384.pdf - * csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA512_256.pdf - * csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA2_Additional.pdf - * en.wikipedia.org/wiki/SHA-2#Examples_of_SHA-2_variants - */ -var TEST_VECTOR = [ - { - // Make sure the algorithm correctly handles the empty string - source: - '', - 512: - 'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce' + - '47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e' - }, - { - source: - 'abc', - 512: - 'ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a' + - '2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f', - 384: - 'cb00753f45a35e8bb5a03d699ac65007272c32ab0eded163' + - '1a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7', - 256: - '53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23' - }, - { - source: - 'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn' + - 'hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu', - 512: - '8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018' + - '501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909', - 384: - '09330c33f71147e83d192fc782cd1b4753111b173b3b05d2' + - '2fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039', - 256: - '3928e184fb8690f840da3988121d31be65cb9d3ef83ee6146feac861e19b563a' - }, - { - source: - 'The quick brown fox jumps over the lazy dog', - 512: - '07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb64' + - '2e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6', - 384: - 'ca737f1014a48f4c0b6dd43cb177b0afd9e5169367544c49' + - '4011e3317dbf9a509cb1e5dc1e85a941bbee3d7f2afbc9b1', - 256: - 'dd9d67b371519c339ed8dbd25af90e976a1eeefd4ad3d889005e532fc5bef04d' - } -]; - - -/** - * For each integer key N, the value is the SHA-512 value of a string - * consisting of N repetitions of the character 'a'. - */ -var TEST_FENCEPOST_VECTOR = { - 110: - 'c825949632e509824543f7eaf159fb6041722fce3c1cdcbb613b3d37ff107c51' + - '9417baac32f8e74fe29d7f4823bf6886956603dca5354a6ed6e4a542e06b7d28', - 111: - 'fa9121c7b32b9e01733d034cfc78cbf67f926c7ed83e82200ef8681819692176' + - '0b4beff48404df811b953828274461673c68d04e297b0eb7b2b4d60fc6b566a2', - 112: - 'c01d080efd492776a1c43bd23dd99d0a2e626d481e16782e75d54c2503b5dc32' + - 'bd05f0f1ba33e568b88fd2d970929b719ecbb152f58f130a407c8830604b70ca', - 113: - '55ddd8ac210a6e18ba1ee055af84c966e0dbff091c43580ae1be703bdb85da31' + - 'acf6948cf5bd90c55a20e5450f22fb89bd8d0085e39f85a86cc46abbca75e24d' -}; - - -/** - * Simple sanity tests for hash functions. - */ -function testBasicOperations() { - var sha512 = new goog.crypt.Sha512(); - goog.crypt.hashTester.runBasicTests(sha512); - - var sha384 = new goog.crypt.Sha384(); - goog.crypt.hashTester.runBasicTests(sha384); - - var sha256 = new goog.crypt.Sha512_256(); - goog.crypt.hashTester.runBasicTests(sha256); -} - - -/** - * Function called by the actual testers to ensure that specific strings - * hash to specific published values. - * - * Each item in the vector has a "source" and one or more additional keys. - * If the item has a key matching the key argument passed to this - * function, it is the expected value of the hash function. - * - * @param {!goog.crypt.Sha2_64bit} hasher The hasher to test - * @param {number} length The length of the resulting hash, in bits. - * Also the key to use in TEST_VECTOR for the expected hash value - */ -function hashGoldenTester(hasher, length) { - goog.array.forEach(TEST_VECTOR, function(data) { - hasher.update(data.source); - var digest = hasher.digest(); - assertEquals('Hash digest has the wrong length', length, digest.length * 8); - if (data[length]) { - // We're given an expected value - var expected = goog.crypt.hexToByteArray(data[length]); - assertElementsEquals( - 'Wrong result for hash' + length + '(\'' + data.source + '\')', - expected, digest); - } - hasher.reset(); - }); -} - - -/** Test that Sha512() returns the published values */ -function testHashing512() { - hashGoldenTester(new goog.crypt.Sha512(), 512); -} - - -/** Test that Sha384 returns the published values */ -function testHashing384() { - hashGoldenTester(new goog.crypt.Sha384(), 384); -} - - -/** Test that Sha512_256 returns the published values */ -function testHashing256() { - hashGoldenTester(new goog.crypt.Sha512_256(), 256); -} - - -/** Test that the opt_length works */ -function testHashing_optLength() { - var hasher = new goog.crypt.Sha512(); - hasher.update('1234567890'); - var digest1 = hasher.digest(); - hasher.reset(); - hasher.update('12345678901234567890', 10); - var digest2 = hasher.digest(); - assertElementsEquals(digest1, digest2); -} - - -/** - * Make sure that we correctly handle strings whose length is 110-113. - * This is the area where we are likely to hit fencepost errors in the padding - * code. - */ -function testFencepostErrors() { - var hasher = new goog.crypt.Sha512(); - A64 = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; - A128 = A64 + A64; - for (var i = 110; i <= 113; i++) { - hasher.update(A128, i); - var digest = hasher.digest(); - var expected = goog.crypt.hexToByteArray(TEST_FENCEPOST_VECTOR[i]); - assertElementsEquals('Fencepost ' + i, expected, digest); - hasher.reset(); - } -} - - -/** Test one really large string using SHA512 */ -function testHashing512Large() { - // This test tends to time out on IE7. - if (!goog.userAgent.IE || goog.userAgent.isVersionOrHigher('8')) { - var hasher = new goog.crypt.Sha512(); - hasher.update(goog.array.repeat(0, 1000000)); - var digest = hasher.digest(); - var expected = goog.crypt.hexToByteArray( - 'ce044bc9fd43269d5bbc946cbebc3bb711341115cc4abdf2edbc3ff2c57ad4b1' + - '5deb699bda257fea5aef9c6e55fcf4cf9dc25a8c3ce25f2efe90908379bff7ed'); - assertElementsEquals(expected, digest); - } -} - - -/** Check that the code throws an error for bad input */ -function testBadInput_nullNotAllowed() { - var hasher = new goog.crypt.Sha512(); - assertThrows('Null input not allowed', function() { - hasher.update({}); - }); -} - -function testBadInput_noFloatingPoint() { - var hasher = new goog.crypt.Sha512(); - assertThrows('Floating point not allows', function() { - hasher.update([1, 2, 3, 4, 4.5]); - }); -} - -function testBadInput_negativeNotAllowed() { - var hasher = new goog.crypt.Sha512(); - assertThrows('Negative not allowed', function() { - hasher.update([1, 2, 3, 4, -10]); - }); -} - -function testBadInput_mustBeByteArray() { - var hasher = new goog.crypt.Sha512(); - assertThrows('Must be byte array', function() { - hasher.update([1, 2, 3, 4, {}]); - }); -} - -function testBadInput_byteTooLarge() { - var hasher = new goog.crypt.Sha512(); - assertThrows('>255 not allowed', function() { - hasher.update([1, 2, 3, 4, 256]); - }); -} - -function testBadInput_characterTooLarge() { - var hasher = new goog.crypt.Sha512(); - assertThrows('>255 not allowed', function() { - hasher.update('abc' + String.fromCharCode(256)); - }); -} - - -function testHasherNeedsReset_beforeDigest() { - var hasher = new goog.crypt.Sha512(); - hasher.update('abc'); - hasher.digest(); - assertThrows('Need reset after digest', function() { - hasher.digest(); - }); -} - - -function testHasherNeedsReset_beforeUpdate() { - var hasher = new goog.crypt.Sha512(); - hasher.update('abc'); - hasher.digest(); - assertThrows('Need reset after digest', function() { - hasher.update('abc'); - }); -} diff --git a/src/database/third_party/closure-library/closure/goog/crypt/sha384.js b/src/database/third_party/closure-library/closure/goog/crypt/sha384.js deleted file mode 100644 index 08ad94630bb..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/sha384.js +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2014 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview SHA-384 cryptographic hash. - * - * Usage: - * var sha384 = new goog.crypt.Sha384(); - * sha384.update(bytes); - * var hash = sha384.digest(); - * - * @author fy@google.com (Frank Yellin) - */ - -goog.provide('goog.crypt.Sha384'); - -goog.require('goog.crypt.Sha2_64bit'); - - - -/** - * Constructs a SHA-384 cryptographic hash. - * - * @constructor - * @extends {goog.crypt.Sha2_64bit} - * @final - * @struct - */ -goog.crypt.Sha384 = function() { - goog.crypt.Sha384.base(this, 'constructor', 6 /* numHashBlocks */, - goog.crypt.Sha384.INIT_HASH_BLOCK_); -}; -goog.inherits(goog.crypt.Sha384, goog.crypt.Sha2_64bit); - - -/** @private {!Array} */ -goog.crypt.Sha384.INIT_HASH_BLOCK_ = [ - // Section 5.3.4 of - // csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf - 0xcbbb9d5d, 0xc1059ed8, // H0 - 0x629a292a, 0x367cd507, // H1 - 0x9159015a, 0x3070dd17, // H2 - 0x152fecd8, 0xf70e5939, // H3 - 0x67332667, 0xffc00b31, // H4 - 0x8eb44a87, 0x68581511, // H5 - 0xdb0c2e0d, 0x64f98fa7, // H6 - 0x47b5481d, 0xbefa4fa4 // H7 -]; diff --git a/src/database/third_party/closure-library/closure/goog/crypt/sha512.js b/src/database/third_party/closure-library/closure/goog/crypt/sha512.js deleted file mode 100644 index 9ac228057d9..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/sha512.js +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2014 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview SHA-512 cryptographic hash. - * - * Usage: - * var sha512 = new goog.crypt.Sha512(); - * sha512.update(bytes); - * var hash = sha512.digest(); - * - * @author fy@google.com (Frank Yellin) - */ - -goog.provide('goog.crypt.Sha512'); - -goog.require('goog.crypt.Sha2_64bit'); - - - -/** - * Constructs a SHA-512 cryptographic hash. - * - * @constructor - * @extends {goog.crypt.Sha2_64bit} - * @final - * @struct - */ -goog.crypt.Sha512 = function() { - goog.crypt.Sha512.base(this, 'constructor', 8 /* numHashBlocks */, - goog.crypt.Sha512.INIT_HASH_BLOCK_); -}; -goog.inherits(goog.crypt.Sha512, goog.crypt.Sha2_64bit); - - -/** @private {!Array} */ -goog.crypt.Sha512.INIT_HASH_BLOCK_ = [ - // Section 5.3.5 of - // csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf - 0x6a09e667, 0xf3bcc908, // H0 - 0xbb67ae85, 0x84caa73b, // H1 - 0x3c6ef372, 0xfe94f82b, // H2 - 0xa54ff53a, 0x5f1d36f1, // H3 - 0x510e527f, 0xade682d1, // H4 - 0x9b05688c, 0x2b3e6c1f, // H5 - 0x1f83d9ab, 0xfb41bd6b, // H6 - 0x5be0cd19, 0x137e2179 // H7 -]; diff --git a/src/database/third_party/closure-library/closure/goog/crypt/sha512_256.js b/src/database/third_party/closure-library/closure/goog/crypt/sha512_256.js deleted file mode 100644 index 75a4256fb93..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/sha512_256.js +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2014 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview SHA-512/256 cryptographic hash. - * - * WARNING: SHA-256 and SHA-512/256 are different members of the SHA-2 - * family of hashes. Although both give 32-byte results, the two results - * should bear no relationship to each other. - * - * Please be careful before using this hash function. - *

- * Usage: - * var sha512_256 = new goog.crypt.Sha512_256(); - * sha512_256.update(bytes); - * var hash = sha512_256.digest(); - * - * @author fy@google.com (Frank Yellin) - */ - -goog.provide('goog.crypt.Sha512_256'); - -goog.require('goog.crypt.Sha2_64bit'); - - - -/** - * Constructs a SHA-512/256 cryptographic hash. - * - * @constructor - * @extends {goog.crypt.Sha2_64bit} - * @final - * @struct - */ -goog.crypt.Sha512_256 = function() { - goog.crypt.Sha512_256.base(this, 'constructor', 4 /* numHashBlocks */, - goog.crypt.Sha512_256.INIT_HASH_BLOCK_); -}; -goog.inherits(goog.crypt.Sha512_256, goog.crypt.Sha2_64bit); - - -/** @private {!Array} */ -goog.crypt.Sha512_256.INIT_HASH_BLOCK_ = [ - // Section 5.3.6.2 of - // csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf - 0x22312194, 0xFC2BF72C, // H0 - 0x9F555FA3, 0xC84C64C2, // H1 - 0x2393B86B, 0x6F53B151, // H2 - 0x96387719, 0x5940EABD, // H3 - 0x96283EE2, 0xA88EFFE3, // H4 - 0xBE5E1E25, 0x53863992, // H5 - 0x2B0199FC, 0x2C85B8AA, // H6 - 0x0EB72DDC, 0x81C52CA2 // H7 -]; diff --git a/src/database/third_party/closure-library/closure/goog/crypt/sha512_perf.html b/src/database/third_party/closure-library/closure/goog/crypt/sha512_perf.html deleted file mode 100644 index e7cf5d21acc..00000000000 --- a/src/database/third_party/closure-library/closure/goog/crypt/sha512_perf.html +++ /dev/null @@ -1,41 +0,0 @@ - - - - - -Closure Performance Tests - goog.crypt.Sha512 - - - - - -

Closure Performance Tests - goog.crypt.Sha512

-

-User-agent: - -

- - - - diff --git a/src/database/third_party/closure-library/closure/goog/css/autocomplete.css b/src/database/third_party/closure-library/closure/goog/css/autocomplete.css deleted file mode 100644 index 033ceba4275..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/autocomplete.css +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2009 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * Styles for goog.ui.ac.AutoComplete and its derivatives. - * Note: these styles need some work to get them working properly at various - * font sizes other than the default. - * - * @author pupius@google.com (Daniel Pupius) - * @author annams@google.com (Srinivas Annam) - */ - - -/* - * TODO(annams): Rename (here and in renderer.js) to specify class name as - * goog-autocomplete-renderer - */ -.ac-renderer { - font: normal 13px Arial, sans-serif; - position: absolute; - background: #fff; - border: 1px solid #666; - -moz-box-shadow: 2px 2px 2px rgba(102, 102, 102, .4); - -webkit-box-shadow: 2px 2px 2px rgba(102, 102, 102, .4); - width: 300px; -} - -.ac-row { - cursor: pointer; - padding: .4em; -} - -.ac-highlighted { - font-weight: bold; -} - -.ac-active { - background-color: #b2b4bf; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/bubble.css b/src/database/third_party/closure-library/closure/goog/css/bubble.css deleted file mode 100644 index 4e8d612bffb..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/bubble.css +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2010 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -.goog-bubble-font { - font-size: 80%; - color: #888888; -} - -.goog-bubble-close-button { - background-image:url(//ssl.gstatic.com/closure/bubble_close.jpg); - background-color: white; - background-position: top right; - background-repeat: no-repeat; - width: 16px; - height: 16px; -} - -.goog-bubble-left { - background-image:url(//ssl.gstatic.com/closure/bubble_left.gif); - background-position:left; - background-repeat:repeat-y; - width: 4px; -} - -.goog-bubble-right { - background-image:url(//ssl.gstatic.com/closure/bubble_right.gif); - background-position: right; - background-repeat: repeat-y; - width: 4px; -} - -.goog-bubble-top-right-anchor { - background-image:url(//ssl.gstatic.com/closure/right_anchor_bubble_top.gif); - background-position: center; - background-repeat: no-repeat; - width: 147px; - height: 16px; -} - -.goog-bubble-top-left-anchor { - background-image:url(//ssl.gstatic.com/closure/left_anchor_bubble_top.gif); - background-position: center; - background-repeat: no-repeat; - width: 147px; - height: 16px; -} - -.goog-bubble-top-no-anchor { - background-image:url(//ssl.gstatic.com/closure/no_anchor_bubble_top.gif); - background-position: center; - background-repeat: no-repeat; - width: 147px; - height: 6px; -} - -.goog-bubble-bottom-right-anchor { - background-image:url(//ssl.gstatic.com/closure/right_anchor_bubble_bot.gif); - background-position: center; - background-repeat: no-repeat; - width: 147px; - height: 16px; -} - -.goog-bubble-bottom-left-anchor { - background-image:url(//ssl.gstatic.com/closure/left_anchor_bubble_bot.gif); - background-position: center; - background-repeat: no-repeat; - width: 147px; - height: 16px; -} - -.goog-bubble-bottom-no-anchor { - background-image:url(//ssl.gstatic.com/closure/no_anchor_bubble_bot.gif); - background-position: center; - background-repeat: no-repeat; - width: 147px; - height: 8px; -} - - diff --git a/src/database/third_party/closure-library/closure/goog/css/button.css b/src/database/third_party/closure-library/closure/goog/css/button.css deleted file mode 100644 index b80a92f142d..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/button.css +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2009 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * Styling for buttons rendered by goog.ui.ButtonRenderer. - * - * @author attila@google.com (Attila Bodis) - */ - -.goog-button { - color: #036; - border-color: #036; - background-color: #69c; -} - -/* State: disabled. */ -.goog-button-disabled { - border-color: #333; - color: #333; - background-color: #999; -} - -/* State: hover. */ -.goog-button-hover { - color: #369; - border-color: #369; - background-color: #9cf; -} - -/* State: active. */ -.goog-button-active { - color: #69c; - border-color: #69c; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/charpicker.css b/src/database/third_party/closure-library/closure/goog/css/charpicker.css deleted file mode 100644 index fb33447746c..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/charpicker.css +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright 2009 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* Author: pupius@google.com (Daniel Pupius) */ -/* Author: cibu@google.com (Cibu Johny) */ - -.goog-char-picker { - background-color: #ddd; - padding: 16px; - border: 1px solid #777; -} - -/* goog.ui.HoverCard */ -.goog-char-picker-hovercard { - border: solid 5px #ffcc33; - min-width: 64px; - max-width: 160px; - padding: 16px; - background-color: white; - text-align: center; - position: absolute; - visibility: hidden; -} - -.goog-char-picker-name { - font-size: x-small; -} - -.goog-char-picker-unicode { - font-size: x-small; - color: GrayText; -} - -.goog-char-picker-char-zoom { - font-size: xx-large; -} - -/* - * grid - */ -.goog-char-picker-grid-container { - border: 1px solid #777; - background-color: #fff; - width: 272px; -} - -.goog-char-picker-grid { - overflow: hidden; - height: 250px; - width: 250px; - position: relative; -} - -.goog-stick { - width: 1px; - overflow: hidden; -} -.goog-stickwrap { - width: 17px; - height: 250px; - float: right; - overflow: auto; -} - -.goog-char-picker-recents { - border: 1px solid #777; - background-color: #fff; - height: 25px; - width: 275px; - margin: 0 0 16px 0; - position: relative; -} - -.goog-char-picker-notice { - font-size: x-small; - height: 16px; - color: GrayText; - margin: 0 0 16px 0; -} - -/* - * Hex entry - */ - -.goog-char-picker-uplus { -} - -.goog-char-picker-input-box { - width: 96px; -} - -.label-input-label { - color: GrayText; -} - -.goog-char-picker-okbutton { -} - -/* - * Grid buttons - */ -.goog-char-picker-grid .goog-flat-button { - position: relative; - width: 24px; - height: 24px; - line-height: 24px; - border-bottom: 1px solid #ddd; - border-right: 1px solid #ddd; - text-align: center; - cursor: pointer; - outline: none; -} - -.goog-char-picker-grid .goog-flat-button-hover, -.goog-char-picker-grid .goog-flat-button-focus { - background-color: #ffcc33; -} - -/* - * goog.ui.Menu - */ - -/* State: resting. */ -.goog-char-picker-button { - border-width: 0px; - margin: 0; - padding: 0; - position: absolute; - background-position: center left; -} - -/* State: resting. */ -.goog-char-picker-menu { - background-color: #fff; - border-color: #ccc #666 #666 #ccc; - border-style: solid; - border-width: 1px; - cursor: default; - margin: 0; - outline: none; - padding: 0; - position: absolute; - max-height: 400px; - overflow-y: auto; - overflow-x: hide; -} - -/* - * goog.ui.MenuItem - */ - -/* State: resting. */ -.goog-char-picker-menu .goog-menuitem { - color: #000; - list-style: none; - margin: 0; - /* 28px on the left for icon or checkbox; 10ex on the right for shortcut. */ - padding: 1px 32px 1px 8px; - white-space: nowrap; -} - -.goog-char-picker-menu2 .goog-menuitem { - color: #000; - list-style: none; - margin: 0; - /* 28px on the left for icon or checkbox; 10ex on the right for shortcut. */ - padding: 1px 32px 1px 8px; - white-space: nowrap; -} - -.goog-char-picker-menu .goog-subtitle { - color: #fff !important; - background-color: #666; - font-weight: bold; - list-style: none; - margin: 0; - /* 28px on the left for icon or checkbox; 10ex on the right for shortcut. */ - padding: 3px 32px 3px 8px; - white-space: nowrap; -} - -/* BiDi override for the resting state. */ -.goog-char-picker-menu .goog-menuitem-rtl { - /* Flip left/right padding for BiDi. */ - padding: 2px 16px 2px 32px !important; -} - -/* State: hover. */ -.goog-char-picker-menu .goog-menuitem-highlight { - background-color: #d6e9f8; -} -/* - * goog.ui.MenuSeparator - */ - -/* State: resting. */ -.goog-char-picker-menu .goog-menuseparator { - border-top: 1px solid #ccc; - margin: 2px 0; - padding: 0; -} - diff --git a/src/database/third_party/closure-library/closure/goog/css/checkbox.css b/src/database/third_party/closure-library/closure/goog/css/checkbox.css deleted file mode 100644 index 2aed8b5188c..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/checkbox.css +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2009 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* Author: pallosp@google.com (Peter Pallos) */ - -/* Sample 3-state checkbox styles. */ - -.goog-checkbox { - border: 1px solid #1C5180; - display: -moz-inline-box; - display: inline-block; - font-size: 1px; /* Fixes the height in IE6 */ - height: 11px; - margin: 0 4px 0 1px; - vertical-align: text-bottom; - width: 11px; -} - -.goog-checkbox-checked { - background: #fff url(//ssl.gstatic.com/closure/check-sprite.gif) no-repeat 2px center; -} - -.goog-checkbox-undetermined { - background: #bbb url(//ssl.gstatic.com/closure/check-sprite.gif) no-repeat 2px center; -} - -.goog-checkbox-unchecked { - background: #fff; -} - -.goog-checkbox-disabled { - border: 1px solid lightgray; - background-position: -7px; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/colormenubutton.css b/src/database/third_party/closure-library/closure/goog/css/colormenubutton.css deleted file mode 100644 index 83655ddb15f..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/colormenubutton.css +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2009 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * Standard styling for buttons created by goog.ui.ColorMenuButtonRenderer. - * - * @author attila@google.com (Attila Bodis) - */ - - -/* Color indicator. */ -.goog-color-menu-button-indicator { - border-bottom: 4px solid #f0f0f0; -} - -/* Thinner padding for color picker buttons, to leave room for the indicator. */ -.goog-color-menu-button .goog-menu-button-inner-box, -.goog-toolbar-color-menu-button .goog-toolbar-menu-button-inner-box { - padding-top: 2px !important; - padding-bottom: 2px !important; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/colorpalette.css b/src/database/third_party/closure-library/closure/goog/css/colorpalette.css deleted file mode 100644 index 17bed426f68..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/colorpalette.css +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2009 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * Standard styling for color palettes. - * - * @author pupius@google.com (Daniel Pupius) - * @author attila@google.com (Attila Bodis) - */ - - -.goog-palette-cell .goog-palette-colorswatch { - border: none; - font-size: x-small; - height: 18px; - position: relative; - width: 18px; -} - -.goog-palette-cell-hover .goog-palette-colorswatch { - border: 1px solid #fff; - height: 16px; - width: 16px; -} - -.goog-palette-cell-selected .goog-palette-colorswatch { - /* Client apps may override the URL at which they serve the sprite. */ - background: url(//ssl.gstatic.com/editor/editortoolbar.png) no-repeat -368px 0; - border: 1px solid #333; - color: #fff; - font-weight: bold; - height: 16px; - width: 16px; -} - -.goog-palette-customcolor { - background-color: #fafafa; - border: 1px solid #eee; - color: #666; - font-size: x-small; - height: 15px; - position: relative; - width: 15px; -} - -.goog-palette-cell-hover .goog-palette-customcolor { - background-color: #fee; - border: 1px solid #f66; - color: #f66; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/colorpicker-simplegrid.css b/src/database/third_party/closure-library/closure/goog/css/colorpicker-simplegrid.css deleted file mode 100644 index b98f5dccf6d..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/colorpicker-simplegrid.css +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2007 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* Author: pupius@google.com (Daniel Pupius) */ - -/* - Styles to make the colorpicker look like the old gmail color picker - NOTE: without CSS scoping this will override styles defined in palette.css -*/ -.goog-palette { - outline: none; - cursor: default; -} - -.goog-palette-table { - border: 1px solid #666; - border-collapse: collapse; -} - -.goog-palette-cell { - height: 13px; - width: 15px; - margin: 0; - border: 0; - text-align: center; - vertical-align: middle; - border-right: 1px solid #666; - font-size: 1px; -} - -.goog-palette-colorswatch { - position: relative; - height: 13px; - width: 15px; - border: 1px solid #666; -} - -.goog-palette-cell-hover .goog-palette-colorswatch { - border: 1px solid #FFF; -} - -.goog-palette-cell-selected .goog-palette-colorswatch { - border: 1px solid #000; - color: #fff; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/combobox.css b/src/database/third_party/closure-library/closure/goog/css/combobox.css deleted file mode 100644 index dd1571ab453..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/combobox.css +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2007 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* Author: pupius@google.com (Daniel Pupius) */ -/* Author: pallosp@google.com (Peter Pallos) */ - -/* Styles for goog.ui.ComboBox and its derivatives. */ - - -.goog-combobox { - background: #ddd url(//ssl.gstatic.com/closure/button-bg.gif) repeat-x scroll left top; - border: 1px solid #b5b6b5; - font: normal small arial, sans-serif; -} - -.goog-combobox input { - background-color: #fff; - border: 0; - border-right: 1px solid #b5b6b5; - color: #000; - font: normal small arial, sans-serif; - margin: 0; - padding: 0 0 0 2px; - vertical-align: bottom; /* override demo.css */ - width: 200px; -} - -.goog-combobox input.label-input-label { - background-color: #fff; - color: #aaa; -} - -.goog-combobox .goog-menu { - margin-top: -1px; - width: 219px; /* input width + button width + 3 * 1px border */ - z-index: 1000; -} - -.goog-combobox-button { - cursor: pointer; - display: inline-block; - font-size: 10px; - text-align: center; - width: 16px; -} - -/* IE6 only hack */ -* html .goog-combobox-button { - padding: 0 3px; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/common.css b/src/database/third_party/closure-library/closure/goog/css/common.css deleted file mode 100644 index de140b88eed..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/common.css +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2009 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * Cross-browser implementation of the "display: inline-block" CSS property. - * See http://www.w3.org/TR/CSS21/visuren.html#propdef-display for details. - * Tested on IE 6 & 7, FF 1.5 & 2.0, Safari 2 & 3, Webkit, and Opera 9. - * - * @author attila@google.com (Attila Bodis) - */ - -/* - * Default rule; only Safari, Webkit, and Opera handle it without hacks. - */ -.goog-inline-block { - position: relative; - display: -moz-inline-box; /* Ignored by FF3 and later. */ - display: inline-block; -} - -/* - * Pre-IE7 IE hack. On IE, "display: inline-block" only gives the element - * layout, but doesn't give it inline behavior. Subsequently setting display - * to inline does the trick. - */ -* html .goog-inline-block { - display: inline; -} - -/* - * IE7-only hack. On IE, "display: inline-block" only gives the element - * layout, but doesn't give it inline behavior. Subsequently setting display - * to inline does the trick. - */ -*:first-child+html .goog-inline-block { - display: inline; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/css3button.css b/src/database/third_party/closure-library/closure/goog/css/css3button.css deleted file mode 100644 index a26306f397b..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/css3button.css +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2010 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* Author: slightlyoff@google.com (Alex Russell) */ -/* Author: eae@google.com (Emil A Eklund) */ - -/* Imageless button styles. */ -.goog-css3-button { - margin: 0 2px; - padding: 3px 6px; - text-align: center; - vertical-align: middle; - white-space: nowrap; - cursor: default; - outline: none; - font-family: Arial, sans-serif; - color: #000; - border: 1px solid #bbb; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - /* TODO(eae): Change this to -webkit-linear-gradient once - https://bugs.webkit.org/show_bug.cgi?id=28152 is resolved. */ - background: -webkit-gradient(linear, 0% 40%, 0% 70%, from(#f9f9f9), - to(#e3e3e3)); - /* @alternate */ background: -moz-linear-gradient(top, #f9f9f9, #e3e3e3); -} - - -/* Styles for different states (hover, active, focused, open, checked). */ -.goog-css3-button-hover { - border-color: #939393 !important; -} - -.goog-css3-button-focused { - border-color: #444; -} - -.goog-css3-button-active, .goog-css3-button-open, .goog-css3-button-checked { - border-color: #444 !important; - background: -webkit-gradient(linear, 0% 40%, 0% 70%, from(#e3e3e3), - to(#f9f9f9)); - /* @alternate */ background: -moz-linear-gradient(top, #e3e3e3, #f9f9f9); -} - -.goog-css3-button-disabled { - color: #888; -} - -.goog-css3-button-primary { - font-weight: bold; -} - - -/* - * Pill (collapsed border) styles. - */ -.goog-css3-button-collapse-right { - margin-right: 0 !important; - border-right: 1px solid #bbb; - -webkit-border-top-right-radius: 0px; - -webkit-border-bottom-right-radius: 0px; - -moz-border-radius-topright: 0px; - -moz-border-radius-bottomright: 0px; -} - -.goog-css3-button-collapse-left { - border-left: 1px solid #f9f9f9; - margin-left: 0 !important; - -webkit-border-top-left-radius: 0px; - -webkit-border-bottom-left-radius: 0px; - -moz-border-radius-topleft: 0px; - -moz-border-radius-bottomleft: 0px; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/css3menubutton.css b/src/database/third_party/closure-library/closure/goog/css/css3menubutton.css deleted file mode 100644 index a02070067e5..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/css3menubutton.css +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2010 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * Standard styling for buttons created by goog.ui.Css3MenuButtonRenderer. - * - * @author attila@google.com (Attila Bodis) - * @author dalewis@google.com (Darren Lewis) - */ - -/* Dropdown arrow style. */ -.goog-css3-button-dropdown { - height: 16px; - width: 7px; - /* Client apps may override the URL at which they serve the sprite. */ - background: url(//ssl.gstatic.com/editor/editortoolbar.png) no-repeat -388px 0; - vertical-align: top; - margin-left: 3px; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/custombutton.css b/src/database/third_party/closure-library/closure/goog/css/custombutton.css deleted file mode 100644 index 1f170527082..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/custombutton.css +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright 2009 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * Styling for custom buttons rendered by goog.ui.CustomButtonRenderer. - * - * @author attila@google.com (Attila Bodis) - */ - -.goog-custom-button { - margin: 2px; - border: 0; - padding: 0; - font-family: Arial, sans-serif; - color: #000; - /* Client apps may override the URL at which they serve the image. */ - background: #ddd url(//ssl.gstatic.com/editor/button-bg.png) repeat-x top left; - text-decoration: none; - list-style: none; - vertical-align: middle; - cursor: default; - outline: none; -} - -/* Pseudo-rounded corners. */ -.goog-custom-button-outer-box, -.goog-custom-button-inner-box { - border-style: solid; - border-color: #aaa; - vertical-align: top; -} - -.goog-custom-button-outer-box { - margin: 0; - border-width: 1px 0; - padding: 0; -} - -.goog-custom-button-inner-box { - margin: 0 -1px; - border-width: 0 1px; - padding: 3px 4px; - white-space: nowrap; /* Prevents buttons from line breaking on android. */ -} - -/* Pre-IE7 IE hack; ignored by IE7 and all non-IE browsers. */ -* html .goog-custom-button-inner-box { - /* IE6 needs to have the box shifted to make the borders line up. */ - left: -1px; -} -/* Pre-IE7 BiDi fixes. */ -* html .goog-custom-button-rtl .goog-custom-button-outer-box { - /* @noflip */ left: -1px; -} -* html .goog-custom-button-rtl .goog-custom-button-inner-box { - /* @noflip */ right: auto; -} - -/* IE7-only hack; ignored by all other browsers. */ -*:first-child+html .goog-custom-button-inner-box { - /* IE7 needs to have the box shifted to make the borders line up. */ - left: -1px; -} -/* IE7 BiDi fix. */ -*:first-child+html .goog-custom-button-rtl .goog-custom-button-inner-box { - /* @noflip */ left: 1px; -} - -/* Safari-only hacks. */ -::root .goog-custom-button, -::root .goog-custom-button-outer-box { - /* Required to make pseudo-rounded corners work on Safari. */ - line-height: 0; -} - -::root .goog-custom-button-inner-box { - /* Required to make pseudo-rounded corners work on Safari. */ - line-height: normal; -} - -/* State: disabled. */ -.goog-custom-button-disabled { - background-image: none !important; - opacity: 0.3; - -moz-opacity: 0.3; - filter: alpha(opacity=30); -} - -.goog-custom-button-disabled .goog-custom-button-outer-box, -.goog-custom-button-disabled .goog-custom-button-inner-box { - color: #333 !important; - border-color: #999 !important; -} - -/* Pre-IE7 IE hack; ignored by IE7 and all non-IE browsers. */ -* html .goog-custom-button-disabled { - margin: 2px 1px !important; - padding: 0 1px !important; -} - -/* IE7-only hack; ignored by all other browsers. */ -*:first-child+html .goog-custom-button-disabled { - margin: 2px 1px !important; - padding: 0 1px !important; -} - -/* State: hover. */ -.goog-custom-button-hover .goog-custom-button-outer-box, -.goog-custom-button-hover .goog-custom-button-inner-box { - border-color: #9cf #69e #69e #7af !important; /* Hover border wins. */ -} - -/* State: active, checked. */ -.goog-custom-button-active, -.goog-custom-button-checked { - background-color: #bbb; - background-position: bottom left; -} - -/* State: focused. */ -.goog-custom-button-focused .goog-custom-button-outer-box, -.goog-custom-button-focused .goog-custom-button-inner-box { - border-color: orange; -} - -/* Pill (collapsed border) styles. */ -.goog-custom-button-collapse-right, -.goog-custom-button-collapse-right .goog-custom-button-outer-box, -.goog-custom-button-collapse-right .goog-custom-button-inner-box { - margin-right: 0; -} - -.goog-custom-button-collapse-left, -.goog-custom-button-collapse-left .goog-custom-button-outer-box, -.goog-custom-button-collapse-left .goog-custom-button-inner-box { - margin-left: 0; -} - -.goog-custom-button-collapse-left .goog-custom-button-inner-box { - border-left: 1px solid #fff; -} - -.goog-custom-button-collapse-left.goog-custom-button-checked -.goog-custom-button-inner-box { - border-left: 1px solid #ddd; -} - -/* Pre-IE7 IE hack; ignored by IE7 and all non-IE browsers. */ -* html .goog-custom-button-collapse-left .goog-custom-button-inner-box { - left: 0; -} - -/* IE7-only hack; ignored by all other browsers. */ -*:first-child+html .goog-custom-button-collapse-left -.goog-custom-button-inner-box { - left: 0; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/datepicker.css b/src/database/third_party/closure-library/closure/goog/css/datepicker.css deleted file mode 100644 index 6d5b914d035..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/datepicker.css +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright 2009 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * Standard styling for a goog.ui.DatePicker. - * - * @author arv@google.com (Erik Arvidsson) - */ - -.goog-date-picker, -.goog-date-picker th, -.goog-date-picker td { - font: 13px Arial, sans-serif; -} - -.goog-date-picker { - -moz-user-focus: normal; - -moz-user-select: none; - position: relative; - border: 1px solid #000; - float: left; - padding: 2px; - color: #000; - background: #c3d9ff; - cursor: default; -} - -.goog-date-picker th { - text-align: center; -} - -.goog-date-picker td { - text-align: center; - vertical-align: middle; - padding: 1px 3px; -} - - -.goog-date-picker-menu { - position: absolute; - background: threedface; - border: 1px solid gray; - -moz-user-focus: normal; - z-index: 1; - outline: none; -} - -.goog-date-picker-menu ul { - list-style: none; - margin: 0px; - padding: 0px; -} - -.goog-date-picker-menu ul li { - cursor: default; -} - -.goog-date-picker-menu-selected { - background: #ccf; -} - -.goog-date-picker th { - font-size: .9em; -} - -.goog-date-picker td div { - float: left; -} - -.goog-date-picker button { - padding: 0px; - margin: 1px 0; - border: 0; - color: #20c; - font-weight: bold; - background: transparent; -} - -.goog-date-picker-date { - background: #fff; -} - -.goog-date-picker-week, -.goog-date-picker-wday { - padding: 1px 3px; - border: 0; - border-color: #a2bbdd; - border-style: solid; -} - -.goog-date-picker-week { - border-right-width: 1px; -} - -.goog-date-picker-wday { - border-bottom-width: 1px; -} - -.goog-date-picker-head td { - text-align: center; -} - -/** Use td.className instead of !important */ -td.goog-date-picker-today-cont { - text-align: center; -} - -/** Use td.className instead of !important */ -td.goog-date-picker-none-cont { - text-align: center; -} - -.goog-date-picker-month { - min-width: 11ex; - white-space: nowrap; -} - -.goog-date-picker-year { - min-width: 6ex; - white-space: nowrap; -} - -.goog-date-picker-monthyear { - white-space: nowrap; -} - -.goog-date-picker table { - border-collapse: collapse; -} - -.goog-date-picker-other-month { - color: #888; -} - -.goog-date-picker-wkend-start, -.goog-date-picker-wkend-end { - background: #eee; -} - -/** Use td.className instead of !important */ -td.goog-date-picker-selected { - background: #c3d9ff; -} - -.goog-date-picker-today { - background: #9ab; - font-weight: bold !important; - border-color: #246 #9bd #9bd #246; - color: #fff; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/dialog.css b/src/database/third_party/closure-library/closure/goog/css/dialog.css deleted file mode 100644 index 6bf9020ab1b..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/dialog.css +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2009 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * Standard styling for goog.ui.Dialog. - * - * @author ssaviano@google.com (Steven Saviano) - * @author attila@google.com (Attila Bodis) - */ - - -.modal-dialog { - background: #c1d9ff; - border: 1px solid #3a5774; - color: #000; - padding: 4px; - position: absolute; -} - -.modal-dialog a, -.modal-dialog a:link, -.modal-dialog a:visited { - color: #06c; - cursor: pointer; -} - -.modal-dialog-bg { - background: #666; - left: 0; - position: absolute; - top: 0; -} - -.modal-dialog-title { - background: #e0edfe; - color: #000; - cursor: pointer; - font-size: 120%; - font-weight: bold; - - /* Add padding on the right to ensure the close button has room. */ - padding: 8px 31px 8px 8px; - - position: relative; - _zoom: 1; /* Ensures proper width in IE6 RTL. */ -} - -.modal-dialog-title-close { - /* Client apps may override the URL at which they serve the sprite. */ - background: #e0edfe url(//ssl.gstatic.com/editor/editortoolbar.png) no-repeat -528px 0; - cursor: default; - height: 15px; - position: absolute; - right: 10px; - top: 8px; - width: 15px; - vertical-align: middle; -} - -.modal-dialog-buttons, -.modal-dialog-content { - background-color: #fff; - padding: 8px; -} - -.goog-buttonset-default { - font-weight: bold; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/dimensionpicker.css b/src/database/third_party/closure-library/closure/goog/css/dimensionpicker.css deleted file mode 100644 index 5c51ab85f62..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/dimensionpicker.css +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2008 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * Styling for dimension pickers rendered by goog.ui.DimensionPickerRenderer. - * - * Author: robbyw@google.com (Robby Walker) - * Author: abefettig@google.com (Abe Fettig) - */ - -.goog-dimension-picker { - font-size: 18px; - padding: 4px; -} - -.goog-dimension-picker div { - position: relative; -} - -.goog-dimension-picker div.goog-dimension-picker-highlighted { -/* Client apps must provide the URL at which they serve the image. */ - /* background: url(dimension-highlighted.png); */ - left: 0; - overflow: hidden; - position: absolute; - top: 0; -} - -.goog-dimension-picker-unhighlighted { - /* Client apps must provide the URL at which they serve the image. */ - /* background: url(dimension-unhighlighted.png); */ -} - -.goog-dimension-picker-status { - font-size: 10pt; - text-align: center; -} - -.goog-dimension-picker div.goog-dimension-picker-mousecatcher { - left: 0; - position: absolute !important; - top: 0; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/dragdropdetector.css b/src/database/third_party/closure-library/closure/goog/css/dragdropdetector.css deleted file mode 100644 index 88266d6ccff..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/dragdropdetector.css +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2007 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * Styling for the drag drop detector. - * - * Author: robbyw@google.com (Robby Walker) - * Author: wcrosby@google.com (Wayne Crosby) - */ - -.goog-dragdrop-w3c-editable-iframe { - position: absolute; - width: 100%; - height: 10px; - top: -150px; - left: 0; - z-index: 10000; - padding: 0; - overflow: hidden; - opacity: 0; - -moz-opacity: 0; -} - -.goog-dragdrop-ie-editable-iframe { - width: 100%; - height: 5000px; -} - -.goog-dragdrop-ie-input { - width: 100%; - height: 5000px; -} - -.goog-dragdrop-ie-div { - position: absolute; - top: -5000px; - left: 0; - width: 100%; - height: 5000px; - z-index: 10000; - background-color: white; - filter: alpha(opacity=0); - overflow: hidden; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/editor/bubble.css b/src/database/third_party/closure-library/closure/goog/css/editor/bubble.css deleted file mode 100644 index c76f98f77c3..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/editor/bubble.css +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2005 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * Bubble styles. - * - * @author robbyw@google.com (Robby Walker) - * @author nicksantos@google.com (Nick Santos) - * @author jparent@google.com (Julie Parent) - */ - -div.tr_bubble { - position: absolute; - - background-color: #e0ecff; - border: 1px solid #99c0ff; - border-radius: 2px; - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - font-size: 83%; - font-family: Arial, Helvetica, sans-serif; - padding: 2px 19px 6px 6px; - white-space: nowrap; -} - -.tr_bubble_link { - color: #00c; - text-decoration: underline; - cursor: pointer; - font-size: 100%; -} - -.tr_bubble .tr_option-link, -.tr_bubble #tr_delete-image, -.tr_bubble #tr_module-options-link { - font-size: 83%; -} - -.tr_bubble_closebox { - position: absolute; - cursor: default; - background: url(//ssl.gstatic.com/editor/bubble_closebox.gif) top left no-repeat; - padding: 0; - margin: 0; - width: 10px; - height: 10px; - top: 3px; - right: 5px; -} - -div.tr_bubble_panel { - padding: 2px 0 1px; -} - -div.tr_bubble_panel_title { - display: none; -} - -div.tr_multi_bubble div.tr_bubble_panel_title { - margin-right: 1px; - display: block; - float: left; - width: 50px; -} - -div.tr_multi_bubble div.tr_bubble_panel { - padding: 2px 0 1px; - margin-right: 50px; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/editor/dialog.css b/src/database/third_party/closure-library/closure/goog/css/editor/dialog.css deleted file mode 100644 index 8868a1054c5..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/editor/dialog.css +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2007 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * Styles for Editor dialogs and their sub-components. - * - * @author marcosalmeida@google.com (Marcos Almeida) - */ - - -.tr-dialog { - width: 475px; -} - -.tr-dialog .goog-tab-content { - margin: 0; - border: 1px solid #6b90da; - padding: 4px 8px; - background: #fff; - overflow: auto; -} - -.tr-tabpane { - font-size: 10pt; - padding: 1.3ex 0; -} - -.tr-tabpane-caption { - font-size: 10pt; - margin-bottom: 0.7ex; - background-color: #fffaf5; - line-height: 1.3em; -} - -.tr-tabpane .goog-tab-content { - border: none; - padding: 5px 7px 1px; -} - -.tr-tabpane .goog-tab { - background-color: #fff; - border: none; - width: 136px; - line-height: 1.3em; - margin-bottom: 0.7ex; -} - -.tr-tabpane .goog-tab { - text-decoration: underline; - color: blue; - cursor: pointer; -} - -.tr-tabpane .goog-tab-selected { - font-weight: bold; - text-decoration: none; - color: black; -} - -.tr-tabpane .goog-tab input { - margin: -2px 5px 0 0; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/editor/equationeditor.css b/src/database/third_party/closure-library/closure/goog/css/editor/equationeditor.css deleted file mode 100644 index b6aff348b36..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/editor/equationeditor.css +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2009 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * The CSS definition for everything inside equation editor dialog. - * - * Author: yoah@google.com (Yoah Bar-David) - * Author: kfk@google.com (Ming Zhang) - */ - -.ee-modal-dialog { - width: 475px; -} - -.ee-content { - background: #FFF; - border: 1px solid #369; - overflow: auto; - padding: 4px 8px; -} - -.ee-tex { - border: 1px solid #000; - display: block; - height: 7.5em; - margin: 4px 0 10px 0; - width: 100%; -} - -.ee-section-title { - font-weight: bold; -} - -.ee-section-title-floating { - float: left; -} - -#ee-section-learn-more { - float: right; -} - -.ee-preview-container { - border: 1px dashed #ccc; - height: 80px; - margin: 4px 0 10px 0; - width: 100%; - overflow: auto; -} - -.ee-warning { - color: #F00; -} - -.ee-palette { - border: 1px solid #aaa; - left: 0; - outline: none; - position: absolute; -} - -.ee-palette-table { - border: 0; - border-collapse: separate; -} - -.ee-palette-cell { - background: #F0F0F0; - border: 1px solid #FFF; - margin: 0; - padding: 1px; -} - -.ee-palette-cell-hover { - background: #E2ECF9 !important; - border: 1px solid #000; - padding: 1px; -} - -.ee-palette-cell-selected { - background: #F0F0F0; - border: 1px solid #CCC !important; - padding: 1px; -} - -.ee-menu-palette-table { - margin-right: 10px; -} - -.ee-menu-palette { - outline: none; - padding-top: 2px; -} - -.ee-menu-palette-cell { - background: #F0F0F0 none repeat scroll 0 0; - border-color: #888 #AAA #AAA #888; - border-style: solid; - border-width: 1px; -} -.ee-menu-palette-cell-hover, -.ee-menu-palette-cell-selected { - background: #F0F0F0; -} - -.ee-palette-item, -.ee-menu-palette-item { - background-image: url(//ssl.gstatic.com/editor/ee-palettes.gif); -} - diff --git a/src/database/third_party/closure-library/closure/goog/css/editor/linkdialog.css b/src/database/third_party/closure-library/closure/goog/css/editor/linkdialog.css deleted file mode 100644 index a58a4b2a222..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/editor/linkdialog.css +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2007 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/** - * Styles for the Editor's Edit Link dialog. - * - * @author marcosalmeida@google.com (Marcos Almeida) - */ - - -.tr-link-dialog-explanation-text { - font-size: 83%; - margin-top: 15px; -} - -.tr-link-dialog-target-input { - width: 98%; /* 98% prevents scroll bars in standards mode. */ - /* Input boxes for URLs and email address should always be LTR. */ - direction: ltr; -} - -.tr-link-dialog-email-warning { - text-align: center; - color: #c00; - font-weight: bold; -} - -.tr_pseudo-link { - color: #00c; - text-decoration: underline; - cursor: pointer; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/editortoolbar.css b/src/database/third_party/closure-library/closure/goog/css/editortoolbar.css deleted file mode 100644 index 1e26f4fe0d5..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/editortoolbar.css +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright 2008 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - - -/* - * Editor toolbar styles. - * - * @author attila@google.com (Attila Bodis) - */ - -/* Common base style for all icons. */ -.tr-icon { - width: 16px; - height: 16px; - background: url(//ssl.gstatic.com/editor/editortoolbar.png) no-repeat; - vertical-align: middle; -} - -.goog-color-menu-button-indicator .tr-icon { - height: 14px; -} - -/* Undo (redo when the chrome is right-to-left). */ -.tr-undo, -.goog-toolbar-button-rtl .tr-redo { - background-position: 0; -} - -/* Redo (undo when the chrome is right-to-left). */ -.tr-redo, -.goog-toolbar-button-rtl .tr-undo { - background-position: -16px; -} - -/* Font name. */ -.tr-fontName .goog-toolbar-menu-button-caption { - color: #246; - width: 16ex; - height: 16px; - overflow: hidden; -} - -/* Font size. */ -.tr-fontSize .goog-toolbar-menu-button-caption { - color: #246; - width: 8ex; - height: 16px; - overflow: hidden; -} - -/* Bold. */ -.tr-bold { - background-position: -32px; -} - -/* Italic. */ -.tr-italic { - background-position: -48px; -} - -/* Underline. */ -.tr-underline { - background-position: -64px; -} - -/* Foreground color. */ -.tr-foreColor { - height: 14px; - background-position: -80px; -} - -/* Background color. */ -.tr-backColor { - height: 14px; - background-position: -96px; -} - -/* Link. */ -.tr-link { - font-weight: bold; - color: #009; - text-decoration: underline; -} - -/* Insert image. */ -.tr-image { - background-position: -112px; -} - -/* Insert drawing. */ -.tr-newDrawing { - background-position: -592px; -} - -/* Insert special character. */ -.tr-spChar { - font-weight: bold; - color: #900; -} - -/* Increase indent. */ -.tr-indent { - background-position: -128px; -} - -/* Increase ident in right-to-left text mode, regardless of chrome direction. */ -.tr-rtl-mode .tr-indent { - background-position: -400px; -} - -/* Decrease indent. */ -.tr-outdent { - background-position: -144px; -} - -/* Decrease indent in right-to-left text mode, regardless of chrome direction. */ -.tr-rtl-mode .tr-outdent { - background-position: -416px; -} - -/* Bullet (unordered) list. */ -.tr-insertUnorderedList { - background-position: -160px; -} - -/* Bullet list in right-to-left text mode, regardless of chrome direction. */ -.tr-rtl-mode .tr-insertUnorderedList { - background-position: -432px; -} - -/* Number (ordered) list. */ -.tr-insertOrderedList { - background-position: -176px; -} - -/* Number list in right-to-left text mode, regardless of chrome direction. */ -.tr-rtl-mode .tr-insertOrderedList { - background-position: -448px; -} - -/* Text alignment buttons. */ -.tr-justifyLeft { - background-position: -192px; -} -.tr-justifyCenter { - background-position: -208px; -} -.tr-justifyRight { - background-position: -224px; -} -.tr-justifyFull { - background-position: -480px; -} - -/* Blockquote. */ -.tr-BLOCKQUOTE { - background-position: -240px; -} - -/* Blockquote in right-to-left text mode, regardless of chrome direction. */ -.tr-rtl-mode .tr-BLOCKQUOTE { - background-position: -464px; -} - -/* Remove formatting. */ -.tr-removeFormat { - background-position: -256px; -} - -/* Spellcheck. */ -.tr-spell { - background-position: -272px; -} - -/* Left-to-right text direction. */ -.tr-ltr { - background-position: -288px; -} - -/* Right-to-left text direction. */ -.tr-rtl { - background-position: -304px; -} - -/* Insert iGoogle module. */ -.tr-insertModule { - background-position: -496px; -} - -/* Strike through text */ -.tr-strikeThrough { - background-position: -544px; -} - -/* Subscript */ -.tr-subscript { - background-position: -560px; -} - -/* Superscript */ -.tr-superscript { - background-position: -576px; -} - -/* Insert drawing. */ -.tr-equation { - background-position: -608px; -} - -/* Edit HTML. */ -.tr-editHtml { - color: #009; -} - -/* "Format block" menu. */ -.tr-formatBlock .goog-toolbar-menu-button-caption { - color: #246; - width: 12ex; - height: 16px; - overflow: hidden; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/filteredmenu.css b/src/database/third_party/closure-library/closure/goog/css/filteredmenu.css deleted file mode 100644 index b43a113253a..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/filteredmenu.css +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2007 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* Author: pupius@google.com (Daniel Pupius) */ - -/* goog.ui.FilteredMenu */ - -.goog-menu-filter { - margin: 2px; - border: 1px solid silver; - background: white; - overflow: hidden; -} - -.goog-menu-filter div { - color: gray; - position: absolute; - padding: 1px; -} - -.goog-menu-filter input { - margin: 0; - border: 0; - background: transparent; - width: 100%; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/filterobservingmenuitem.css b/src/database/third_party/closure-library/closure/goog/css/filterobservingmenuitem.css deleted file mode 100644 index d48a609ac48..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/filterobservingmenuitem.css +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2007 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* Author: pupius@google.com (Daniel Pupius) */ - -/* goog.ui.FilterObservingMenuItem */ - -.goog-filterobsmenuitem { - padding: 2px 5px; - margin: 0; - list-style: none; -} - -.goog-filterobsmenuitem-highlight { - background-color: #4279A5; - color: #FFF; -} - -.goog-filterobsmenuitem-disabled { - color: #999; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/flatbutton.css b/src/database/third_party/closure-library/closure/goog/css/flatbutton.css deleted file mode 100644 index 1cc39b69162..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/flatbutton.css +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2009 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * Styling for flat buttons created by goog.ui.FlatButtonRenderer. - * - * @author brianp@google.com (Brian Peterson) - */ - -.goog-flat-button { - position: relative; - /*width: 20ex;*/ - margin: 2px; - border: 1px solid #000; - padding: 2px 6px; - font: normal 13px "Trebuchet MS", Tahoma, Arial, sans-serif; - color: #fff; - background-color: #8c2425; - cursor: pointer; - outline: none; -} - -/* State: disabled. */ -.goog-flat-button-disabled { - border-color: #888; - color: #888; - background-color: #ccc; - cursor: default; -} - -/* State: hover. */ -.goog-flat-button-hover { - border-color: #8c2425; - color: #8c2425; - background-color: #eaa4a5; -} - -/* State: active, selected, checked. */ -.goog-flat-button-active, -.goog-flat-button-selected, -.goog-flat-button-checked { - border-color: #5b4169; - color: #5b4169; - background-color: #d1a8ea; -} - -/* State: focused. */ -.goog-flat-button-focused { - border-color: #5b4169; -} - -/* Pill (collapsed border) styles. */ -.goog-flat-button-collapse-right { - margin-right: 0; -} - -.goog-flat-button-collapse-left { - margin-left: 0; - border-left: none; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/flatmenubutton.css b/src/database/third_party/closure-library/closure/goog/css/flatmenubutton.css deleted file mode 100644 index 577821782c4..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/flatmenubutton.css +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2009 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * Standard styling for buttons created by goog.ui.FlatMenuButtonRenderer. - * - * @author attila@google.com (Attila Bodis) - * @author tlb@google.com (Thierry Le Boulenge) - */ - - -.goog-flat-menu-button { - background-color: #fff; - border: 1px solid #c9c9c9; - color: #333; - cursor: pointer; - font: normal 95%; - list-style: none; - margin: 0 2px; - outline: none; - padding: 1px 4px; - position: relative; - text-decoration: none; - vertical-align: middle; -} - -.goog-flat-menu-button-disabled * { - border-color: #ccc; - color: #999; - cursor: default; -} - -.goog-flat-menu-button-hover { - border-color: #9cf #69e #69e #7af !important; /* Hover border wins. */ -} - -.goog-flat-menu-button-active { - background-color: #bbb; - background-position: bottom left; -} - -.goog-flat-menu-button-focused { - border-color: #bbb; -} - -.goog-flat-menu-button-caption { - padding-right: 10px; - vertical-align: top; -} - -.goog-flat-menu-button-dropdown { - /* Client apps may override the URL at which they serve the sprite. */ - background: url(//ssl.gstatic.com/editor/editortoolbar.png) no-repeat -388px 0; - position: absolute; - right: 2px; - top: 0; - vertical-align: top; - width: 7px; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/hovercard.css b/src/database/third_party/closure-library/closure/goog/css/hovercard.css deleted file mode 100644 index 2d64e4fbf01..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/hovercard.css +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2008 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* Author: larrypo@google.com (Larry Powelson) */ - -.goog-hovercard div { - border: solid 5px #69748C; - width: 300px; - height: 115px; - background-color: white; - font-family: arial, sans-serif; -} - -.goog-hovercard .goog-shadow { - border: transparent; - background-color: black; - filter: alpha(Opacity=1); - opacity: 0.01; - -moz-opacity: 0.01; -} - -.goog-hovercard table { - border-collapse: collapse; - border-spacing: 0px; -} - -.goog-hovercard-icons td { - border-bottom: 1px solid #ccc; - padding: 0px; - margin: 0px; - text-align: center; - height: 19px; - width: 100px; - font-size: 90%; -} - -.goog-hovercard-icons td + td { - border-left: 1px solid #ccc; -} - -.goog-hovercard-content { - border-collapse: collapse; -} - -.goog-hovercard-content td { - padding-left: 15px; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/hsvapalette.css b/src/database/third_party/closure-library/closure/goog/css/hsvapalette.css deleted file mode 100644 index ec52e3927ee..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/hsvapalette.css +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright 2008 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * All Rights Reserved. - * - * Styles for the HSV color palette. - * - * @author smcbride@google.com (Sean McBride) - * @author arv@google.com (Erik Arvidsson) - * @author manucornet@google.com (Manu Cornet) - */ - -.goog-hsva-palette, -.goog-hsva-palette-sm { - position: relative; - border: 1px solid #999; - border-color: #ccc #999 #999 #ccc; - width: 442px; - height: 276px; -} - -.goog-hsva-palette-sm { - width: 205px; - height: 185px; -} - -.goog-hsva-palette label span, -.goog-hsva-palette-sm label span { - display: none; -} - -.goog-hsva-palette-hs-backdrop, -.goog-hsva-palette-sm-hs-backdrop, -.goog-hsva-palette-hs-image, -.goog-hsva-palette-sm-hs-image { - position: absolute; - top: 10px; - left: 10px; - width: 256px; - height: 256px; - border: 1px solid #999; -} - -.goog-hsva-palette-sm-hs-backdrop, -.goog-hsva-palette-sm-hs-image { - top: 45px; - width: 128px; - height: 128px; -} - -.goog-hsva-palette-hs-backdrop, -.goog-hsva-palette-sm-hs-backdrop { - background-color: #000; -} - -.goog-hsva-palette-hs-image, -.goog-hsva-palette-v-image, -.goog-hsva-palette-a-image, -.goog-hsva-palette-hs-handle, -.goog-hsva-palette-v-handle, -.goog-hsva-palette-a-handle, -.goog-hsva-palette-swatch-backdrop { - background-image: url(//ssl.gstatic.com/closure/hsva-sprite.png); -} - -.goog-hsva-palette-noalpha .goog-hsva-palette-hs-image, -.goog-hsva-palette-noalpha .goog-hsva-palette-v-image, -.goog-hsva-palette-noalpha .goog-hsva-palette-a-image, -.goog-hsva-palette-noalpha .goog-hsva-palette-hs-handle, -.goog-hsva-palette-noalpha .goog-hsva-palette-v-handle, -.goog-hsva-palette-noalpha .goog-hsva-palette-a-handle, -.goog-hsva-palette-noalpha .goog-hsva-palette-swatch-backdrop { - background-image: url(//ssl.gstatic.com/closure/hsva-sprite.gif); -} - -.goog-hsva-palette-sm-hs-image, -.goog-hsva-palette-sm-v-image, -.goog-hsva-palette-sm-a-image, -.goog-hsva-palette-sm-hs-handle, -.goog-hsva-palette-sm-v-handle, -.goog-hsva-palette-sm-a-handle, -.goog-hsva-palette-sm-swatch-backdrop { - background-image: url(//ssl.gstatic.com/closure/hsva-sprite-sm.png); -} - -.goog-hsva-palette-noalpha .goog-hsva-palette-sm-hs-image, -.goog-hsva-palette-noalpha .goog-hsva-palette-sm-v-image, -.goog-hsva-palette-noalpha .goog-hsva-palette-sm-a-image, -.goog-hsva-palette-noalpha .goog-hsva-palette-sm-hs-handle, -.goog-hsva-palette-noalpha .goog-hsva-palette-sm-v-handle, -.goog-hsva-palette-noalpha .goog-hsva-palette-sm-a-handle, -.goog-hsva-palette-noalpha .goog-hsva-palette-swatch-backdrop { - background-image: url(//ssl.gstatic.com/closure/hsva-sprite-sm.gif); -} - -.goog-hsva-palette-hs-image, -.goog-hsva-palette-sm-hs-image { - background-position: 0 0; -} - -.goog-hsva-palette-hs-handle, -.goog-hsva-palette-sm-hs-handle { - position: absolute; - left: 5px; - top: 5px; - width: 11px; - height: 11px; - overflow: hidden; - background-position: 0 -256px; -} - -.goog-hsva-palette-sm-hs-handle { - top: 40px; - background-position: 0 -128px; -} - -.goog-hsva-palette-v-image, -.goog-hsva-palette-a-image, -.goog-hsva-palette-sm-v-image, -.goog-hsva-palette-sm-a-image { - position: absolute; - top: 10px; - left: 286px; - width: 19px; - height: 256px; - border: 1px solid #999; - background-color: #fff; - background-position: -256px 0; -} - -.goog-hsva-palette-a-image { - left: 325px; - background-position: -275px 0; -} - -.goog-hsva-palette-sm-v-image, -.goog-hsva-palette-sm-a-image { - top: 45px; - left: 155px; - width: 9px; - height: 128px; - background-position: -128px 0; -} - -.goog-hsva-palette-sm-a-image { - left: 182px; - background-position: -137px 0; -} - -.goog-hsva-palette-v-handle, -.goog-hsva-palette-a-handle, -.goog-hsva-palette-sm-v-handle, -.goog-hsva-palette-sm-a-handle { - position: absolute; - top: 5px; - left: 279px; - width: 35px; - height: 11px; - background-position: -11px -256px; - overflow: hidden; -} - -.goog-hsva-palette-a-handle { - left: 318px; -} - -.goog-hsva-palette-sm-v-handle, -.goog-hsva-palette-sm-a-handle { - top: 40px; - left: 148px; - width: 25px; - background-position: -11px -128px; -} - -.goog-hsva-palette-sm-a-handle { - left: 175px; -} - -.goog-hsva-palette-swatch, -.goog-hsva-palette-swatch-backdrop, -.goog-hsva-palette-sm-swatch, -.goog-hsva-palette-sm-swatch-backdrop { - position: absolute; - top: 10px; - right: 10px; - width: 65px; - height: 65px; - border: 1px solid #999; - background-color: #fff; - background-position: -294px 0; -} - -.goog-hsva-palette-sm-swatch, -.goog-hsva-palette-sm-swatch-backdrop { - top: 10px; - right: auto; - left: 10px; - width: 30px; - height: 22px; - background-position: -36px -128px; -} - -.goog-hsva-palette-swatch, -.goog-hsva-palette-sm-swatch { - z-index: 5; -} - -.goog-hsva-palette-swatch-backdrop, -.goog-hsva-palette-sm-swatch-backdrop { - z-index: 1; -} - -.goog-hsva-palette-input, -.goog-hsva-palette-sm-input { - position: absolute; - top: 85px; - right: 10px; - width: 65px; - font-size: 80%; -} - -.goog-hsva-palette-sm-input { - top: 10px; - right: auto; - left: 50px; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/hsvpalette.css b/src/database/third_party/closure-library/closure/goog/css/hsvpalette.css deleted file mode 100644 index 8449ed59aa4..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/hsvpalette.css +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright 2008 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * All Rights Reserved. - * - * Styles for the HSV color palette. - * - * @author smcbride@google.com (Sean McBride) - * @author arv@google.com (Erik Arvidsson) - * @author manucornet@google.com (Manu Cornet) - */ - -.goog-hsv-palette, -.goog-hsv-palette-sm { - position: relative; - border: 1px solid #999; - border-color: #ccc #999 #999 #ccc; - width: 400px; - height: 276px; -} - -.goog-hsv-palette-sm { - width: 182px; - height: 185px; -} - -.goog-hsv-palette label span, -.goog-hsv-palette-sm label span { - display: none; -} - -.goog-hsv-palette-hs-backdrop, -.goog-hsv-palette-sm-hs-backdrop, -.goog-hsv-palette-hs-image, -.goog-hsv-palette-sm-hs-image { - position: absolute; - top: 10px; - left: 10px; - width: 256px; - height: 256px; - border: 1px solid #999; -} - -.goog-hsv-palette-sm-hs-backdrop, -.goog-hsv-palette-sm-hs-image { - top: 45px; - width: 128px; - height: 128px; -} - -.goog-hsv-palette-hs-backdrop, -.goog-hsv-palette-sm-hs-backdrop { - background-color: #000; -} - -.goog-hsv-palette-hs-image, -.goog-hsv-palette-v-image, -.goog-hsv-palette-hs-handle, -.goog-hsv-palette-v-handle { - background-image: url(//ssl.gstatic.com/closure/hsv-sprite.png); -} - -.goog-hsv-palette-noalpha .goog-hsv-palette-hs-image, -.goog-hsv-palette-noalpha .goog-hsv-palette-v-image, -.goog-hsv-palette-noalpha .goog-hsv-palette-hs-handle, -.goog-hsv-palette-noalpha .goog-hsv-palette-v-handle { - background-image: url(//ssl.gstatic.com/closure/hsv-sprite.gif); -} - -.goog-hsv-palette-sm-hs-image, -.goog-hsv-palette-sm-v-image, -.goog-hsv-palette-sm-hs-handle, -.goog-hsv-palette-sm-v-handle { - background-image: url(//ssl.gstatic.com/closure/hsv-sprite-sm.png); -} - -.goog-hsv-palette-noalpha .goog-hsv-palette-sm-hs-image, -.goog-hsv-palette-noalpha .goog-hsv-palette-sm-v-image, -.goog-hsv-palette-noalpha .goog-hsv-palette-sm-hs-handle, -.goog-hsv-palette-noalpha .goog-hsv-palette-sm-v-handle { - background-image: url(//ssl.gstatic.com/closure/hsv-sprite-sm.gif); -} - -.goog-hsv-palette-hs-image, -.goog-hsv-palette-sm-hs-image { - background-position: 0 0; -} - -.goog-hsv-palette-hs-handle, -.goog-hsv-palette-sm-hs-handle { - position: absolute; - left: 5px; - top: 5px; - width: 11px; - height: 11px; - overflow: hidden; - background-position: 0 -256px; -} - -.goog-hsv-palette-sm-hs-handle { - top: 40px; - background-position: 0 -128px; -} - -.goog-hsv-palette-v-image, -.goog-hsv-palette-sm-v-image { - position: absolute; - top: 10px; - left: 286px; - width: 19px; - height: 256px; - border: 1px solid #999; - background-color: #fff; - background-position: -256px 0; -} - -.goog-hsv-palette-sm-v-image { - top: 45px; - left: 155px; - width: 9px; - height: 128px; - background-position: -128px 0; -} - -.goog-hsv-palette-v-handle, -.goog-hsv-palette-sm-v-handle { - position: absolute; - top: 5px; - left: 279px; - width: 35px; - height: 11px; - background-position: -11px -256px; - overflow: hidden; -} - -.goog-hsv-palette-sm-v-handle { - top: 40px; - left: 148px; - width: 25px; - background-position: -11px -128px; -} - -.goog-hsv-palette-swatch, -.goog-hsv-palette-sm-swatch { - position: absolute; - top: 10px; - right: 10px; - width: 65px; - height: 65px; - border: 1px solid #999; - background-color: #fff; -} - -.goog-hsv-palette-sm-swatch { - top: 10px; - right: auto; - left: 10px; - width: 30px; - height: 22px; -} - -.goog-hsv-palette-input, -.goog-hsv-palette-sm-input { - position: absolute; - top: 85px; - right: 10px; - width: 65px; -} - -.goog-hsv-palette-sm-input { - top: 10px; - right: auto; - left: 50px; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/imagelessbutton.css b/src/database/third_party/closure-library/closure/goog/css/imagelessbutton.css deleted file mode 100644 index 23c7fee6b27..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/imagelessbutton.css +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright 2008 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * Styling for buttons created by goog.ui.ImagelessButtonRenderer. - * - * WARNING: This file uses some ineffecient selectors and it may be - * best to avoid using this file in extremely large, or performance - * critical applications. - * - * @author: eae@google.com (Emil A Eklund) - * @author: gboyer@google.com (Garrett Boyer) - */ - - -/* Imageless button styles. */ - -/* The base element of the button. */ -.goog-imageless-button { - /* Set the background color at the outermost level. */ - background: #e3e3e3; - /* Place a top and bottom border. Do it on this outermost div so that - * it is easier to make pill buttons work properly. */ - border-color: #bbb; - border-style: solid; - border-width: 1px 0; - color: #222; /* Text content color. */ - cursor: default; - font-family: Arial, sans-serif; - line-height: 0; /* For Opera and old WebKit. */ - list-style: none; - /* Built-in margin for the component. Because of the negative margins - * used to simulate corner rounding, the effective left and right margin is - * actually only 1px. */ - margin: 2px; - outline: none; - padding: 0; - text-decoration: none; - vertical-align: middle; -} - -/* - * Pseudo-rounded corners. Works by pulling the left and right sides slightly - * outside of the parent bounding box before drawing the left and right - * borders. - */ -.goog-imageless-button-outer-box { - /* Left and right border that protrude outside the parent. */ - border-color: #bbb; - border-style: solid; - border-width: 0 1px; - /* Same as margin: 0 -1px, except works better cross browser. These are - * intended to be RTL flipped to work better in IE7. */ - left: -1px; - margin-right: -2px; -} - -/* - * A div to give the light and medium shades of the button that takes up no - * vertical space. - */ -.goog-imageless-button-top-shadow { - /* Light top color in the content. */ - background: #f9f9f9; - /* Thin medium shade. */ - border-bottom: 3px solid #eee; - /* Control height with line-height, since height: will trigger hasLayout. - * Specified in pixels, as a compromise to avoid rounding errors. */ - line-height: 9px; - /* Undo all space this takes up. */ - margin-bottom: -12px; -} - -/* Actual content area for the button. */ -.goog-imageless-button-content { - line-height: 1.5em; - padding: 0px 4px; - text-align: center; -} - - -/* Pill (collapsed border) styles. */ -.goog-imageless-button-collapse-right { - /* Draw a border on the root element to square the button off. The border - * on the outer-box element remains, but gets obscured by the next button. */ - border-right-width: 1px; - margin-right: -2px; /* Undoes the margins between the two buttons. */ -} - -.goog-imageless-button-collapse-left .goog-imageless-button-outer-box { - /* Don't bleed to the left -- keep the border self contained in the box. */ - border-left-color: #eee; - left: 0; - margin-right: -1px; /* Versus the default of -2px. */ -} - - -/* Disabled styles. */ -.goog-imageless-button-disabled, -.goog-imageless-button-disabled .goog-imageless-button-outer-box { - background: #eee; - border-color: #ccc; - color: #666; /* For text */ -} - -.goog-imageless-button-disabled .goog-imageless-button-top-shadow { - /* Just hide the shadow instead of setting individual colors. */ - visibility: hidden; -} - - -/* - * Active and checked styles. - * Identical except for text color according to GUIG. - */ -.goog-imageless-button-active, .goog-imageless-button-checked { - background: #f9f9f9; -} - -.goog-imageless-button-active .goog-imageless-button-top-shadow, -.goog-imageless-button-checked .goog-imageless-button-top-shadow { - background: #e3e3e3; -} - -.goog-imageless-button-active { - color: #000; -} - - -/* Hover styles. Higher priority to override other border styles. */ -.goog-imageless-button-hover, -.goog-imageless-button-hover .goog-imageless-button-outer-box, -.goog-imageless-button-focused, -.goog-imageless-button-focused .goog-imageless-button-outer-box { - border-color: #000; -} - - -/* IE6 hacks. This is the only place inner-box is used. */ -* html .goog-imageless-button-inner-box { - /* Give the element inline-block behavior so that the shadow appears. - * The main requirement is to give the element layout without having the side - * effect of taking up a full line. */ - display: inline; - /* Allow the shadow to show through, overriding position:relative from the - * goog-inline-block styles. */ - position: static; - zoom: 1; -} - -* html .goog-imageless-button-outer-box { - /* In RTL mode, IE is off by one pixel. To fix, override the left: -1px - * (which was flipped to right) without having any effect on LTR mode - * (where IE ignores right when left is specified). */ - /* @noflip */ right: 0; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/imagelessmenubutton.css b/src/database/third_party/closure-library/closure/goog/css/imagelessmenubutton.css deleted file mode 100644 index 0c8b6fdcc9f..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/imagelessmenubutton.css +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2010 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * Standard styling for buttons created by goog.ui.ImagelessMenuButtonRenderer. - * - * @author attila@google.com (Attila Bodis) - * @author dalewis@google.com (Darren Lewis) - */ - -/* Dropdown arrow style. */ -.goog-imageless-button-dropdown { - height: 16px; - width: 7px; - /* Client apps may override the URL at which they serve the sprite. */ - background: url(//ssl.gstatic.com/editor/editortoolbar.png) no-repeat -388px 0; - vertical-align: top; - margin-right: 2px; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/inputdatepicker.css b/src/database/third_party/closure-library/closure/goog/css/inputdatepicker.css deleted file mode 100644 index 4f93182196d..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/inputdatepicker.css +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright 2008 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* Author: arv@google.com (Erik Arvidsson) */ - -/* goog.ui.InputDatePicker */ - -@import url(popupdatepicker.css); diff --git a/src/database/third_party/closure-library/closure/goog/css/linkbutton.css b/src/database/third_party/closure-library/closure/goog/css/linkbutton.css deleted file mode 100644 index 9f9ec3a3f94..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/linkbutton.css +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2010 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * Styling for link buttons created by goog.ui.LinkButtonRenderer. - * - * @author robbyw@google.com (Robby Walker) - */ - -.goog-link-button { - position: relative; - color: #00f; - text-decoration: underline; - cursor: pointer; -} - -/* State: disabled. */ -.goog-link-button-disabled { - color: #888; - text-decoration: none; - cursor: default; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/menu.css b/src/database/third_party/closure-library/closure/goog/css/menu.css deleted file mode 100644 index da66222d72d..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/menu.css +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2009 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * Standard styling for menus created by goog.ui.MenuRenderer. - * - * @author attila@google.com (Attila Bodis) - */ - - -.goog-menu { - background: #fff; - border-color: #ccc #666 #666 #ccc; - border-style: solid; - border-width: 1px; - cursor: default; - font: normal 13px Arial, sans-serif; - margin: 0; - outline: none; - padding: 4px 0; - position: absolute; - z-index: 20000; /* Arbitrary, but some apps depend on it... */ -} diff --git a/src/database/third_party/closure-library/closure/goog/css/menubar.css b/src/database/third_party/closure-library/closure/goog/css/menubar.css deleted file mode 100644 index 6f69b4664c0..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/menubar.css +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2012 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * styling for goog.ui.menuBar and child buttons. - * - * @author tvykruta@google.com (Tomas Vykruta) - */ - - -.goog-menubar { - cursor: default; - outline: none; - position: relative; - white-space: nowrap; - background: #fff; -} - -.goog-menubar .goog-menu-button { - padding: 1px 1px; - margin: 0px 0px; - outline: none; - border: none; - background: #fff; - /* @alternate */ border: 1px solid #fff; -} - -.goog-menubar .goog-menu-button-dropdown { - display: none; -} - -.goog-menubar .goog-menu-button-outer-box { - border: none; -} - -.goog-menubar .goog-menu-button-inner-box { - border: none; -} - -.goog-menubar .goog-menu-button-hover { - background: #eee; - border: 1px solid #eee; -} - -.goog-menubar .goog-menu-button-open { - background: #fff; - border-left: 1px solid #ccc; - border-right: 1px solid #ccc; -} - -.goog-menubar .goog-menu-button-disabled { - color: #ccc; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/menubutton.css b/src/database/third_party/closure-library/closure/goog/css/menubutton.css deleted file mode 100644 index 82c94b248a4..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/menubutton.css +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright 2009 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * Standard styling for buttons created by goog.ui.MenuButtonRenderer. - * - * @author attila@google.com (Attila Bodis) - */ - - -/* State: resting. */ -.goog-menu-button { - /* Client apps may override the URL at which they serve the image. */ - background: #ddd url(//ssl.gstatic.com/editor/button-bg.png) repeat-x top left; - border: 0; - color: #000; - cursor: pointer; - list-style: none; - margin: 2px; - outline: none; - padding: 0; - text-decoration: none; - vertical-align: middle; -} - -/* Pseudo-rounded corners. */ -.goog-menu-button-outer-box, -.goog-menu-button-inner-box { - border-style: solid; - border-color: #aaa; - vertical-align: top; -} -.goog-menu-button-outer-box { - margin: 0; - border-width: 1px 0; - padding: 0; -} -.goog-menu-button-inner-box { - margin: 0 -1px; - border-width: 0 1px; - padding: 3px 4px; -} - -/* Pre-IE7 IE hack; ignored by IE7 and all non-IE browsers. */ -* html .goog-menu-button-inner-box { - /* IE6 needs to have the box shifted to make the borders line up. */ - left: -1px; -} - -/* Pre-IE7 BiDi fixes. */ -* html .goog-menu-button-rtl .goog-menu-button-outer-box { - /* @noflip */ left: -1px; - /* @noflip */ right: auto; -} -* html .goog-menu-button-rtl .goog-menu-button-inner-box { - /* @noflip */ right: auto; -} - -/* IE7-only hack; ignored by all other browsers. */ -*:first-child+html .goog-menu-button-inner-box { - /* IE7 needs to have the box shifted to make the borders line up. */ - left: -1px; -} -/* IE7 BiDi fix. */ -*:first-child+html .goog-menu-button-rtl .goog-menu-button-inner-box { - /* @noflip */ left: 1px; - /* @noflip */ right: auto; -} - -/* Safari-only hacks. */ -::root .goog-menu-button, -::root .goog-menu-button-outer-box, -::root .goog-menu-button-inner-box { - /* Required to make pseudo-rounded corners work on Safari. */ - line-height: 0; -} -::root .goog-menu-button-caption, -::root .goog-menu-button-dropdown { - /* Required to make pseudo-rounded corners work on Safari. */ - line-height: normal; -} - -/* State: disabled. */ -.goog-menu-button-disabled { - background-image: none !important; - opacity: 0.3; - -moz-opacity: 0.3; - filter: alpha(opacity=30); -} -.goog-menu-button-disabled .goog-menu-button-outer-box, -.goog-menu-button-disabled .goog-menu-button-inner-box, -.goog-menu-button-disabled .goog-menu-button-caption, -.goog-menu-button-disabled .goog-menu-button-dropdown { - color: #333 !important; - border-color: #999 !important; -} - -/* Pre-IE7 IE hack; ignored by IE7 and all non-IE browsers. */ -* html .goog-menu-button-disabled { - margin: 2px 1px !important; - padding: 0 1px !important; -} - -/* IE7-only hack; ignored by all other browsers. */ -*:first-child+html .goog-menu-button-disabled { - margin: 2px 1px !important; - padding: 0 1px !important; -} - -/* State: hover. */ -.goog-menu-button-hover .goog-menu-button-outer-box, -.goog-menu-button-hover .goog-menu-button-inner-box { - border-color: #9cf #69e #69e #7af !important; /* Hover border wins. */ -} - -/* State: active, open. */ -.goog-menu-button-active, -.goog-menu-button-open { - background-color: #bbb; - background-position: bottom left; -} - -/* State: focused. */ -.goog-menu-button-focused .goog-menu-button-outer-box, -.goog-menu-button-focused .goog-menu-button-inner-box { - border-color: orange; -} - -/* Caption style. */ -.goog-menu-button-caption { - padding: 0 4px 0 0; - vertical-align: top; -} - -/* Dropdown arrow style. */ -.goog-menu-button-dropdown { - height: 15px; - width: 7px; - /* Client apps may override the URL at which they serve the sprite. */ - background: url(//ssl.gstatic.com/editor/editortoolbar.png) no-repeat -388px 0; - vertical-align: top; -} - -/* Pill (collapsed border) styles. */ -/* TODO(gboyer): Remove specific menu button styles and have any button support being a menu button. */ -.goog-menu-button-collapse-right, -.goog-menu-button-collapse-right .goog-menu-button-outer-box, -.goog-menu-button-collapse-right .goog-menu-button-inner-box { - margin-right: 0; -} - -.goog-menu-button-collapse-left, -.goog-menu-button-collapse-left .goog-menu-button-outer-box, -.goog-menu-button-collapse-left .goog-menu-button-inner-box { - margin-left: 0; -} - -.goog-menu-button-collapse-left .goog-menu-button-inner-box { - border-left: 1px solid #fff; -} - -.goog-menu-button-collapse-left.goog-menu-button-checked -.goog-menu-button-inner-box { - border-left: 1px solid #ddd; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/menuitem.css b/src/database/third_party/closure-library/closure/goog/css/menuitem.css deleted file mode 100644 index cea9de68015..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/menuitem.css +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright 2009 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * Standard styling for menus created by goog.ui.MenuItemRenderer. - * - * @author attila@google.com (Attila Bodis) - */ - - -/** - * State: resting. - * - * NOTE(mleibman,chrishenry): - * The RTL support in Closure is provided via two mechanisms -- "rtl" CSS - * classes and BiDi flipping done by the CSS compiler. Closure supports RTL - * with or without the use of the CSS compiler. In order for them not - * to conflict with each other, the "rtl" CSS classes need to have the @noflip - * annotation. The non-rtl counterparts should ideally have them as well, but, - * since .goog-menuitem existed without .goog-menuitem-rtl for so long before - * being added, there is a risk of people having templates where they are not - * rendering the .goog-menuitem-rtl class when in RTL and instead rely solely - * on the BiDi flipping by the CSS compiler. That's why we're not adding the - * @noflip to .goog-menuitem. - */ -.goog-menuitem { - color: #000; - font: normal 13px Arial, sans-serif; - list-style: none; - margin: 0; - /* 28px on the left for icon or checkbox; 7em on the right for shortcut. */ - padding: 4px 7em 4px 28px; - white-space: nowrap; -} - -/* BiDi override for the resting state. */ -/* @noflip */ -.goog-menuitem.goog-menuitem-rtl { - /* Flip left/right padding for BiDi. */ - padding-left: 7em; - padding-right: 28px; -} - -/* If a menu doesn't have checkable items or items with icons, remove padding. */ -.goog-menu-nocheckbox .goog-menuitem, -.goog-menu-noicon .goog-menuitem { - padding-left: 12px; -} - -/* - * If a menu doesn't have items with shortcuts, leave just enough room for - * submenu arrows, if they are rendered. - */ -.goog-menu-noaccel .goog-menuitem { - padding-right: 20px; -} - -.goog-menuitem-content { - color: #000; - font: normal 13px Arial, sans-serif; -} - -/* State: disabled. */ -.goog-menuitem-disabled .goog-menuitem-accel, -.goog-menuitem-disabled .goog-menuitem-content { - color: #ccc !important; -} -.goog-menuitem-disabled .goog-menuitem-icon { - opacity: 0.3; - -moz-opacity: 0.3; - filter: alpha(opacity=30); -} - -/* State: hover. */ -.goog-menuitem-highlight, -.goog-menuitem-hover { - background-color: #d6e9f8; - /* Use an explicit top and bottom border so that the selection is visible - * in high contrast mode. */ - border-color: #d6e9f8; - border-style: dotted; - border-width: 1px 0; - padding-bottom: 3px; - padding-top: 3px; -} - -/* State: selected/checked. */ -.goog-menuitem-checkbox, -.goog-menuitem-icon { - background-repeat: no-repeat; - height: 16px; - left: 6px; - position: absolute; - right: auto; - vertical-align: middle; - width: 16px; -} - -/* BiDi override for the selected/checked state. */ -/* @noflip */ -.goog-menuitem-rtl .goog-menuitem-checkbox, -.goog-menuitem-rtl .goog-menuitem-icon { - /* Flip left/right positioning. */ - left: auto; - right: 6px; -} - -.goog-option-selected .goog-menuitem-checkbox, -.goog-option-selected .goog-menuitem-icon { - /* Client apps may override the URL at which they serve the sprite. */ - background: url(//ssl.gstatic.com/editor/editortoolbar.png) no-repeat -512px 0; -} - -/* Keyboard shortcut ("accelerator") style. */ -.goog-menuitem-accel { - color: #999; - /* Keyboard shortcuts are untranslated; always left-to-right. */ - /* @noflip */ direction: ltr; - left: auto; - padding: 0 6px; - position: absolute; - right: 0; - text-align: right; -} - -/* BiDi override for shortcut style. */ -/* @noflip */ -.goog-menuitem-rtl .goog-menuitem-accel { - /* Flip left/right positioning and text alignment. */ - left: 0; - right: auto; - text-align: left; -} - -/* Mnemonic styles. */ -.goog-menuitem-mnemonic-hint { - text-decoration: underline; -} - -.goog-menuitem-mnemonic-separator { - color: #999; - font-size: 12px; - padding-left: 4px; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/menuseparator.css b/src/database/third_party/closure-library/closure/goog/css/menuseparator.css deleted file mode 100644 index de1354f70dd..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/menuseparator.css +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2009 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * Standard styling for menus created by goog.ui.MenuSeparatorRenderer. - * - * @author attila@google.com (Attila Bodis) - */ - - -.goog-menuseparator { - border-top: 1px solid #ccc; - margin: 4px 0; - padding: 0; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/multitestrunner.css b/src/database/third_party/closure-library/closure/goog/css/multitestrunner.css deleted file mode 100644 index 2cdffeac304..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/multitestrunner.css +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2008 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* Author: pupius@google.com (Daniel Pupius) */ - -.goog-testrunner { - background-color: #EEE; - border: 1px solid #999; - padding: 10px; - padding-bottom: 25px; -} - -.goog-testrunner-progress { - width: auto; - height: 20px; - background-color: #FFF; - border: 1px solid #999; -} - -.goog-testrunner-progress table { - width: 100%; - height: 20px; - border-collapse: collapse; -} - -.goog-testrunner-buttons { - margin-top: 7px; -} - -.goog-testrunner-buttons button { - width: 75px; -} - -.goog-testrunner-log, -.goog-testrunner-report, -.goog-testrunner-stats { - margin-top: 7px; - width: auto; - height: 400px; - background-color: #FFF; - border: 1px solid #999; - font: normal medium monospace; - padding: 5px; - overflow: auto; /* Opera doesn't support overflow-y. */ - overflow-y: scroll; - overflow-x: auto; -} - -.goog-testrunner-report div { - margin-bottom: 6px; - border-bottom: 1px solid #999; -} - -.goog-testrunner-stats table { - margin-top: 20px; - border-collapse: collapse; - border: 1px solid #EEE; -} - -.goog-testrunner-stats td, -.goog-testrunner-stats th { - padding: 2px 6px; - border: 1px solid #F0F0F0; -} - -.goog-testrunner-stats th { - font-weight: bold; -} - -.goog-testrunner-stats .center { - text-align: center; -} - -.goog-testrunner-progress-summary { - font: bold small sans-serif; -} - -.goog-testrunner iframe { - position: absolute; - left: -640px; - top: -480px; - width: 640px; - height: 480px; - margin: 0; - border: 0; - padding: 0; -} - -.goog-testrunner-report-failure { - color: #900; -} - -.goog-testrunner-reporttab, -.goog-testrunner-logtab, -.goog-testrunner-statstab { - float: left; - width: 50px; - height: 16px; - text-align: center; - font: normal small arial, helvetica, sans-serif; - color: #666; - background-color: #DDD; - border: 1px solid #999; - border-top: 0; - cursor: pointer; -} - -.goog-testrunner-reporttab, -.goog-testrunner-logtab { - border-right: 0; -} - -.goog-testrunner-activetab { - font-weight: bold; - color: #000; - background-color: #CCC; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/palette.css b/src/database/third_party/closure-library/closure/goog/css/palette.css deleted file mode 100644 index 8360afc16b1..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/palette.css +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2009 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * Standard styling for palettes created by goog.ui.PaletteRenderer. - * - * @author pupius@google.com (Daniel Pupius) - * @author attila@google.com (Attila Bodis) - */ - - -.goog-palette { - cursor: default; - outline: none; -} - -.goog-palette-table { - border: 1px solid #666; - border-collapse: collapse; - margin: 5px; -} - -.goog-palette-cell { - border: 0; - border-right: 1px solid #666; - cursor: pointer; - height: 18px; - margin: 0; - text-align: center; - vertical-align: middle; - width: 18px; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/popupdatepicker.css b/src/database/third_party/closure-library/closure/goog/css/popupdatepicker.css deleted file mode 100644 index 133173ab53b..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/popupdatepicker.css +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2009 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * Standard styling for a goog.ui.PopupDatePicker. - * - * @author arv@google.com (Erik Arvidsson) - */ - -.goog-date-picker { - position: absolute; -} - diff --git a/src/database/third_party/closure-library/closure/goog/css/roundedpanel.css b/src/database/third_party/closure-library/closure/goog/css/roundedpanel.css deleted file mode 100644 index d931e41d1f7..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/roundedpanel.css +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2010 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * Standard styles for RoundedPanel. - * - * @author pallosp@google.com (Peter Pallos) - */ - -.goog-roundedpanel { - position: relative; - z-index: 0; -} - -.goog-roundedpanel-background { - position: absolute; - left: 0; - top: 0; - width: 100%; - height: 100%; - z-index: -1; -} - -.goog-roundedpanel-content { -} diff --git a/src/database/third_party/closure-library/closure/goog/css/roundedtab.css b/src/database/third_party/closure-library/closure/goog/css/roundedtab.css deleted file mode 100644 index 17fe155f565..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/roundedtab.css +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2008 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* Author: attila@google.com (Attila Bodis) */ - - -/* - * Styles used by goog.ui.RoundedTabRenderer. - */ -.goog-rounded-tab { - border: 0; - cursor: default; - padding: 0; -} - -.goog-tab-bar-top .goog-rounded-tab, -.goog-tab-bar-bottom .goog-rounded-tab { - float: left; - margin: 0 4px 0 0; -} - -.goog-tab-bar-start .goog-rounded-tab, -.goog-tab-bar-end .goog-rounded-tab { - margin: 0 0 4px 0; -} - -.goog-rounded-tab-caption { - border: 0; - color: #fff; - margin: 0; - padding: 4px 8px; -} - -.goog-rounded-tab-caption, -.goog-rounded-tab-inner-edge, -.goog-rounded-tab-outer-edge { - background: #036; - border-right: 1px solid #003; -} - -.goog-rounded-tab-inner-edge, -.goog-rounded-tab-outer-edge { - font-size: 1px; - height: 1px; - overflow: hidden; -} - -/* State: Hover */ -.goog-rounded-tab-hover .goog-rounded-tab-caption, -.goog-rounded-tab-hover .goog-rounded-tab-inner-edge, -.goog-rounded-tab-hover .goog-rounded-tab-outer-edge { - background-color: #69c; - border-right: 1px solid #369; -} - -/* State: Disabled */ -.goog-rounded-tab-disabled .goog-rounded-tab-caption, -.goog-rounded-tab-disabled .goog-rounded-tab-inner-edge, -.goog-rounded-tab-disabled .goog-rounded-tab-outer-edge { - background: #ccc; - border-right: 1px solid #ccc; -} - -/* State: Selected */ -.goog-rounded-tab-selected .goog-rounded-tab-caption, -.goog-rounded-tab-selected .goog-rounded-tab-inner-edge, -.goog-rounded-tab-selected .goog-rounded-tab-outer-edge { - background: #369 !important; /* Selected trumps hover. */ - border-right: 1px solid #036 !important; -} - - -/* - * Styles for horizontal (top or bottom) tabs. - */ -.goog-tab-bar-top .goog-rounded-tab { - vertical-align: bottom; -} - -.goog-tab-bar-bottom .goog-rounded-tab { - vertical-align: top; -} - -.goog-tab-bar-top .goog-rounded-tab-outer-edge, -.goog-tab-bar-bottom .goog-rounded-tab-outer-edge { - margin: 0 3px; -} - -.goog-tab-bar-top .goog-rounded-tab-inner-edge, -.goog-tab-bar-bottom .goog-rounded-tab-inner-edge { - margin: 0 1px; -} - - -/* - * Styles for vertical (start or end) tabs. - */ -.goog-tab-bar-start .goog-rounded-tab-table, -.goog-tab-bar-end .goog-rounded-tab-table { - width: 100%; -} - -.goog-tab-bar-start .goog-rounded-tab-inner-edge { - margin-left: 1px; -} - -.goog-tab-bar-start .goog-rounded-tab-outer-edge { - margin-left: 3px; -} - -.goog-tab-bar-end .goog-rounded-tab-inner-edge { - margin-right: 1px; -} - -.goog-tab-bar-end .goog-rounded-tab-outer-edge { - margin-right: 3px; -} - - -/* - * Overrides for start tabs. - */ -.goog-tab-bar-start .goog-rounded-tab-table, -.goog-tab-bar-end .goog-rounded-tab-table { - width: 12ex; /* TODO(attila): Make this work for variable width. */ -} - -.goog-tab-bar-start .goog-rounded-tab-caption, -.goog-tab-bar-start .goog-rounded-tab-inner-edge, -.goog-tab-bar-start .goog-rounded-tab-outer-edge { - border-left: 1px solid #003; - border-right: 0; -} - -.goog-tab-bar-start .goog-rounded-tab-hover .goog-rounded-tab-caption, -.goog-tab-bar-start .goog-rounded-tab-hover .goog-rounded-tab-inner-edge, -.goog-tab-bar-start .goog-rounded-tab-hover .goog-rounded-tab-outer-edge { - border-left: 1px solid #369 !important; - border-right: 0 !important; -} - -.goog-tab-bar-start .goog-rounded-tab-selected .goog-rounded-tab-outer-edge, -.goog-tab-bar-start .goog-rounded-tab-selected .goog-rounded-tab-inner-edge, -.goog-tab-bar-start .goog-rounded-tab-selected .goog-rounded-tab-caption { - border-left: 1px solid #036 !important; - border-right: 0 !important; -} - -.goog-tab-bar-start .goog-rounded-tab-disabled .goog-rounded-tab-outer-edge, -.goog-tab-bar-start .goog-rounded-tab-disabled .goog-rounded-tab-inner-edge, -.goog-tab-bar-start .goog-rounded-tab-disabled .goog-rounded-tab-caption { - border-left: 1px solid #ccc !important; - border-right: 0 !important; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/submenu.css b/src/database/third_party/closure-library/closure/goog/css/submenu.css deleted file mode 100644 index 1159b289cf3..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/submenu.css +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2009 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * Standard styling for menus created by goog.ui.SubMenuRenderer. - * - * @author attila@google.com (Attila Bodis) - */ - - -/* State: resting. */ -/* @noflip */ -.goog-submenu-arrow { - color: #000; - left: auto; - padding-right: 6px; - position: absolute; - right: 0; - text-align: right; -} - -/* BiDi override. */ -/* @noflip */ -.goog-menuitem-rtl .goog-submenu-arrow { - text-align: left; - left: 0; - right: auto; - padding-left: 6px; -} - -/* State: disabled. */ -.goog-menuitem-disabled .goog-submenu-arrow { - color: #ccc; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/tab.css b/src/database/third_party/closure-library/closure/goog/css/tab.css deleted file mode 100644 index 6c7dfe2ef07..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/tab.css +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2008 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* Author: attila@google.com (Attila Bodis) */ -/* Author: eae@google.com (Emil A. Eklund) */ - - -/* - * Styles used by goog.ui.TabRenderer. - */ -.goog-tab { - position: relative; - padding: 4px 8px; - color: #00c; - text-decoration: underline; - cursor: default; -} - -.goog-tab-bar-top .goog-tab { - margin: 1px 4px 0 0; - border-bottom: 0; - float: left; -} - -.goog-tab-bar-top:after, -.goog-tab-bar-bottom:after { - content: " "; - display: block; - height: 0; - clear: both; - visibility: hidden; -} - -.goog-tab-bar-bottom .goog-tab { - margin: 0 4px 1px 0; - border-top: 0; - float: left; -} - -.goog-tab-bar-start .goog-tab { - margin: 0 0 4px 1px; - border-right: 0; -} - -.goog-tab-bar-end .goog-tab { - margin: 0 1px 4px 0; - border-left: 0; -} - -/* State: Hover */ -.goog-tab-hover { - background: #eee; -} - -/* State: Disabled */ -.goog-tab-disabled { - color: #666; -} - -/* State: Selected */ -.goog-tab-selected { - color: #000; - background: #fff; - text-decoration: none; - font-weight: bold; - border: 1px solid #6b90da; -} - -.goog-tab-bar-top { - padding-top: 5px !important; - padding-left: 5px !important; - border-bottom: 1px solid #6b90da !important; -} -/* - * Shift selected tabs 1px towards the contents (and compensate via margin and - * padding) to visually merge the borders of the tab with the borders of the - * content area. - */ -.goog-tab-bar-top .goog-tab-selected { - top: 1px; - margin-top: 0; - padding-bottom: 5px; -} - -.goog-tab-bar-bottom .goog-tab-selected { - top: -1px; - margin-bottom: 0; - padding-top: 5px; -} - -.goog-tab-bar-start .goog-tab-selected { - left: 1px; - margin-left: 0; - padding-right: 9px; -} - -.goog-tab-bar-end .goog-tab-selected { - left: -1px; - margin-right: 0; - padding-left: 9px; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/tabbar.css b/src/database/third_party/closure-library/closure/goog/css/tabbar.css deleted file mode 100644 index 514aa9bacd2..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/tabbar.css +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2008 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* Author: attila@google.com (Attila Bodis) */ -/* Author: eae@google.com (Emil A. Eklund) */ - - -/* - * Styles used by goog.ui.TabBarRenderer. - */ -.goog-tab-bar { - margin: 0; - border: 0; - padding: 0; - list-style: none; - cursor: default; - outline: none; - background: #ebeff9; -} - -.goog-tab-bar-clear { - clear: both; - height: 0; - overflow: hidden; -} - -.goog-tab-bar-start { - float: left; -} - -.goog-tab-bar-end { - float: right; -} - - -/* - * IE6-only hacks to fix the gap between the floated tabs and the content. - * IE7 and later will ignore these. - */ -/* @if user.agent ie6 */ -* html .goog-tab-bar-start { - margin-right: -3px; -} - -* html .goog-tab-bar-end { - margin-left: -3px; -} -/* @endif */ diff --git a/src/database/third_party/closure-library/closure/goog/css/tablesorter.css b/src/database/third_party/closure-library/closure/goog/css/tablesorter.css deleted file mode 100644 index 126f007ffbe..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/tablesorter.css +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright 2008 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* Author: robbyw@google.com (Robby Walker) */ - -/* Styles for goog.ui.TableSorter. */ - -.goog-tablesorter-header { - cursor: pointer -} diff --git a/src/database/third_party/closure-library/closure/goog/css/toolbar.css b/src/database/third_party/closure-library/closure/goog/css/toolbar.css deleted file mode 100644 index 5c39ddedafe..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/toolbar.css +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Copyright 2009 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* - * Standard styling for toolbars and toolbar items. - * - * @author attila@google.com (Attila Bodis) - */ - - -/* - * Styles used by goog.ui.ToolbarRenderer. - */ - -.goog-toolbar { - /* Client apps may override the URL at which they serve the image. */ - background: #fafafa url(//ssl.gstatic.com/editor/toolbar-bg.png) repeat-x bottom left; - border-bottom: 1px solid #d5d5d5; - cursor: default; - font: normal 12px Arial, sans-serif; - margin: 0; - outline: none; - padding: 2px; - position: relative; - zoom: 1; /* The toolbar element must have layout on IE. */ -} - -/* - * Styles used by goog.ui.ToolbarButtonRenderer. - */ - -.goog-toolbar-button { - margin: 0 2px; - border: 0; - padding: 0; - font-family: Arial, sans-serif; - color: #333; - text-decoration: none; - list-style: none; - vertical-align: middle; - cursor: default; - outline: none; -} - -/* Pseudo-rounded corners. */ -.goog-toolbar-button-outer-box, -.goog-toolbar-button-inner-box { - border: 0; - vertical-align: top; -} - -.goog-toolbar-button-outer-box { - margin: 0; - padding: 1px 0; -} - -.goog-toolbar-button-inner-box { - margin: 0 -1px; - padding: 3px 4px; -} - -/* Pre-IE7 IE hack; ignored by IE7 and all non-IE browsers. */ -* html .goog-toolbar-button-inner-box { - /* IE6 needs to have the box shifted to make the borders line up. */ - left: -1px; -} - -/* Pre-IE7 BiDi fixes. */ -* html .goog-toolbar-button-rtl .goog-toolbar-button-outer-box { - /* @noflip */ left: -1px; -} -* html .goog-toolbar-button-rtl .goog-toolbar-button-inner-box { - /* @noflip */ right: auto; -} - - -/* IE7-only hack; ignored by all other browsers. */ -*:first-child+html .goog-toolbar-button-inner-box { - /* IE7 needs to have the box shifted to make the borders line up. */ - left: -1px; -} - -/* IE7 BiDi fix. */ -*:first-child+html .goog-toolbar-button-rtl .goog-toolbar-button-inner-box { - /* @noflip */ left: 1px; - /* @noflip */ right: auto; -} - -/* Safari-only hacks. */ -::root .goog-toolbar-button, -::root .goog-toolbar-button-outer-box { - /* Required to make pseudo-rounded corners work on Safari. */ - line-height: 0; -} - -::root .goog-toolbar-button-inner-box { - /* Required to make pseudo-rounded corners work on Safari. */ - line-height: normal; -} - -/* Disabled styles. */ -.goog-toolbar-button-disabled { - opacity: 0.3; - -moz-opacity: 0.3; - filter: alpha(opacity=30); -} - -.goog-toolbar-button-disabled .goog-toolbar-button-outer-box, -.goog-toolbar-button-disabled .goog-toolbar-button-inner-box { - /* Disabled text/border color trumps everything else. */ - color: #333 !important; - border-color: #999 !important; -} - -/* Pre-IE7 IE hack; ignored by IE7 and all non-IE browsers. */ -* html .goog-toolbar-button-disabled { - /* IE can't apply alpha to an element with a transparent background... */ - background-color: #f0f0f0; - margin: 0 1px; - padding: 0 1px; -} - -/* IE7-only hack; ignored by all other browsers. */ -*:first-child+html .goog-toolbar-button-disabled { - /* IE can't apply alpha to an element with a transparent background... */ - background-color: #f0f0f0; - margin: 0 1px; - padding: 0 1px; -} - -/* Only draw borders when in a non-default state. */ -.goog-toolbar-button-hover .goog-toolbar-button-outer-box, -.goog-toolbar-button-active .goog-toolbar-button-outer-box, -.goog-toolbar-button-checked .goog-toolbar-button-outer-box, -.goog-toolbar-button-selected .goog-toolbar-button-outer-box { - border-width: 1px 0; - border-style: solid; - padding: 0; -} - -.goog-toolbar-button-hover .goog-toolbar-button-inner-box, -.goog-toolbar-button-active .goog-toolbar-button-inner-box, -.goog-toolbar-button-checked .goog-toolbar-button-inner-box, -.goog-toolbar-button-selected .goog-toolbar-button-inner-box { - border-width: 0 1px; - border-style: solid; - padding: 3px; -} - -/* Hover styles. */ -.goog-toolbar-button-hover .goog-toolbar-button-outer-box, -.goog-toolbar-button-hover .goog-toolbar-button-inner-box { - /* Hover border style wins over active/checked/selected. */ - border-color: #a1badf !important; -} - -/* Active/checked/selected styles. */ -.goog-toolbar-button-active, -.goog-toolbar-button-checked, -.goog-toolbar-button-selected { - /* Active/checked/selected background color always wins. */ - background-color: #dde1eb !important; -} - -.goog-toolbar-button-active .goog-toolbar-button-outer-box, -.goog-toolbar-button-active .goog-toolbar-button-inner-box, -.goog-toolbar-button-checked .goog-toolbar-button-outer-box, -.goog-toolbar-button-checked .goog-toolbar-button-inner-box, -.goog-toolbar-button-selected .goog-toolbar-button-outer-box, -.goog-toolbar-button-selected .goog-toolbar-button-inner-box { - border-color: #729bd1; -} - -/* Pill (collapsed border) styles. */ -.goog-toolbar-button-collapse-right, -.goog-toolbar-button-collapse-right .goog-toolbar-button-outer-box, -.goog-toolbar-button-collapse-right .goog-toolbar-button-inner-box { - margin-right: 0; -} - -.goog-toolbar-button-collapse-left, -.goog-toolbar-button-collapse-left .goog-toolbar-button-outer-box, -.goog-toolbar-button-collapse-left .goog-toolbar-button-inner-box { - margin-left: 0; -} - -/* Pre-IE7 IE hack; ignored by IE7 and all non-IE browsers. */ -* html .goog-toolbar-button-collapse-left .goog-toolbar-button-inner-box { - left: 0; -} - -/* IE7-only hack; ignored by all other browsers. */ -*:first-child+html .goog-toolbar-button-collapse-left -.goog-toolbar-button-inner-box { - left: 0; -} - - -/* - * Styles used by goog.ui.ToolbarMenuButtonRenderer. - */ - -.goog-toolbar-menu-button { - margin: 0 2px; - border: 0; - padding: 0; - font-family: Arial, sans-serif; - color: #333; - text-decoration: none; - list-style: none; - vertical-align: middle; - cursor: default; - outline: none; -} - -/* Pseudo-rounded corners. */ -.goog-toolbar-menu-button-outer-box, -.goog-toolbar-menu-button-inner-box { - border: 0; - vertical-align: top; -} - -.goog-toolbar-menu-button-outer-box { - margin: 0; - padding: 1px 0; -} - -.goog-toolbar-menu-button-inner-box { - margin: 0 -1px; - padding: 3px 4px; -} - -/* Pre-IE7 IE hack; ignored by IE7 and all non-IE browsers. */ -* html .goog-toolbar-menu-button-inner-box { - /* IE6 needs to have the box shifted to make the borders line up. */ - left: -1px; -} - -/* Pre-IE7 BiDi fixes. */ -* html .goog-toolbar-menu-button-rtl .goog-toolbar-menu-button-outer-box { - /* @noflip */ left: -1px; -} -* html .goog-toolbar-menu-button-rtl .goog-toolbar-menu-button-inner-box { - /* @noflip */ right: auto; -} - -/* IE7-only hack; ignored by all other browsers. */ -*:first-child+html .goog-toolbar-menu-button-inner-box { - /* IE7 needs to have the box shifted to make the borders line up. */ - left: -1px; -} - -/* IE7 BiDi fix. */ -*:first-child+html .goog-toolbar-menu-button-rtl - .goog-toolbar-menu-button-inner-box { - /* @noflip */ left: 1px; - /* @noflip */ right: auto; -} - -/* Safari-only hacks. */ -::root .goog-toolbar-menu-button, -::root .goog-toolbar-menu-button-outer-box, -::root .goog-toolbar-menu-button-inner-box { - /* Required to make pseudo-rounded corners work on Safari. */ - line-height: 0; -} - -::root .goog-toolbar-menu-button-caption, -::root .goog-toolbar-menu-button-dropdown { - /* Required to make pseudo-rounded corners work on Safari. */ - line-height: normal; -} - -/* Disabled styles. */ -.goog-toolbar-menu-button-disabled { - opacity: 0.3; - -moz-opacity: 0.3; - filter: alpha(opacity=30); -} - -.goog-toolbar-menu-button-disabled .goog-toolbar-menu-button-outer-box, -.goog-toolbar-menu-button-disabled .goog-toolbar-menu-button-inner-box { - /* Disabled text/border color trumps everything else. */ - color: #333 !important; - border-color: #999 !important; -} - -/* Pre-IE7 IE hack; ignored by IE7 and all non-IE browsers. */ -* html .goog-toolbar-menu-button-disabled { - /* IE can't apply alpha to an element with a transparent background... */ - background-color: #f0f0f0; - margin: 0 1px; - padding: 0 1px; -} - -/* IE7-only hack; ignored by all other browsers. */ -*:first-child+html .goog-toolbar-menu-button-disabled { - /* IE can't apply alpha to an element with a transparent background... */ - background-color: #f0f0f0; - margin: 0 1px; - padding: 0 1px; -} - -/* Only draw borders when in a non-default state. */ -.goog-toolbar-menu-button-hover .goog-toolbar-menu-button-outer-box, -.goog-toolbar-menu-button-active .goog-toolbar-menu-button-outer-box, -.goog-toolbar-menu-button-open .goog-toolbar-menu-button-outer-box { - border-width: 1px 0; - border-style: solid; - padding: 0; -} - -.goog-toolbar-menu-button-hover .goog-toolbar-menu-button-inner-box, -.goog-toolbar-menu-button-active .goog-toolbar-menu-button-inner-box, -.goog-toolbar-menu-button-open .goog-toolbar-menu-button-inner-box { - border-width: 0 1px; - border-style: solid; - padding: 3px; -} - -/* Hover styles. */ -.goog-toolbar-menu-button-hover .goog-toolbar-menu-button-outer-box, -.goog-toolbar-menu-button-hover .goog-toolbar-menu-button-inner-box { - /* Hover border color trumps active/open style. */ - border-color: #a1badf !important; -} - -/* Active/open styles. */ -.goog-toolbar-menu-button-active, -.goog-toolbar-menu-button-open { - /* Active/open background color wins. */ - background-color: #dde1eb !important; -} - -.goog-toolbar-menu-button-active .goog-toolbar-menu-button-outer-box, -.goog-toolbar-menu-button-active .goog-toolbar-menu-button-inner-box, -.goog-toolbar-menu-button-open .goog-toolbar-menu-button-outer-box, -.goog-toolbar-menu-button-open .goog-toolbar-menu-button-inner-box { - border-color: #729bd1; -} - -/* Menu button caption style. */ -.goog-toolbar-menu-button-caption { - padding: 0 4px 0 0; - vertical-align: middle; -} - -/* Dropdown style. */ -.goog-toolbar-menu-button-dropdown { - width: 7px; - /* Client apps may override the URL at which they serve the sprite. */ - background: url(//ssl.gstatic.com/editor/editortoolbar.png) no-repeat -388px 0; - vertical-align: middle; -} - - -/* - * Styles used by goog.ui.ToolbarSeparatorRenderer. - */ - -.goog-toolbar-separator { - margin: 0 2px; - border-left: 1px solid #d6d6d6; - border-right: 1px solid #f7f7f7; - padding: 0; - width: 0; - text-decoration: none; - list-style: none; - outline: none; - vertical-align: middle; - line-height: normal; - font-size: 120%; - overflow: hidden; -} - - -/* - * Additional styling for toolbar select controls, which always have borders. - */ - -.goog-toolbar-select .goog-toolbar-menu-button-outer-box { - border-width: 1px 0; - border-style: solid; - padding: 0; -} - -.goog-toolbar-select .goog-toolbar-menu-button-inner-box { - border-width: 0 1px; - border-style: solid; - padding: 3px; -} - -.goog-toolbar-select .goog-toolbar-menu-button-outer-box, -.goog-toolbar-select .goog-toolbar-menu-button-inner-box { - border-color: #bfcbdf; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/tooltip.css b/src/database/third_party/closure-library/closure/goog/css/tooltip.css deleted file mode 100644 index 026458327af..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/tooltip.css +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright 2010 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -.goog-tooltip { - background: #ffe; - border: 1px solid #999; - border-width: 1px 2px 2px 1px; - padding: 6px; - z-index: 30000; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/tree.css b/src/database/third_party/closure-library/closure/goog/css/tree.css deleted file mode 100644 index aeb1d0b3d43..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/tree.css +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2007 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* Author: arv@google.com (Erik Arvidsson) */ -/* Author: eae@google.com (Emil A Eklund) */ -/* Author: jonp@google.com (Jon Perlow) */ - -/* - TODO(arv): Currently the sprite image has the height 16px. We should make the - image taller which would allow better flexibility when it comes to the height - of a tree row. -*/ - -.goog-tree-root:focus { - outline: none; -} - -.goog-tree-row { - white-space: nowrap; - font: icon; - line-height: 16px; - height: 16px; -} - -.goog-tree-row span { - overflow: hidden; - text-overflow: ellipsis; -} - -.goog-tree-children { - background-repeat: repeat-y; - background-image: url(//ssl.gstatic.com/closure/tree/I.png) !important; - background-position-y: 1px !important; /* IE only */ - font: icon; -} - -.goog-tree-children-nolines { - font: icon; -} - -.goog-tree-icon { - background-image: url(//ssl.gstatic.com/closure/tree/tree.png); -} - -.goog-tree-expand-icon { - vertical-align: middle; - height: 16px; - width: 16px; - cursor: default; -} - -.goog-tree-expand-icon-plus { - width: 19px; - background-position: 0 0; -} - -.goog-tree-expand-icon-minus { - width: 19px; - background-position: -24px 0; -} - -.goog-tree-expand-icon-tplus { - width: 19px; - background-position: -48px 0; -} - -.goog-tree-expand-icon-tminus { - width: 19px; - background-position: -72px 0; -} - -.goog-tree-expand-icon-lplus { - width: 19px; - background-position: -96px 0; -} - -.goog-tree-expand-icon-lminus { - width: 19px; - background-position: -120px 0; -} - -.goog-tree-expand-icon-t { - width: 19px; - background-position: -144px 0; -} - -.goog-tree-expand-icon-l { - width: 19px; - background-position: -168px 0; -} - -.goog-tree-expand-icon-blank { - width: 19px; - background-position: -168px -24px; -} - -.goog-tree-collapsed-folder-icon { - vertical-align: middle; - height: 16px; - width: 16px; - background-position: -0px -24px; -} - -.goog-tree-expanded-folder-icon { - vertical-align: middle; - height: 16px; - width: 16px; - background-position: -24px -24px; -} - -.goog-tree-file-icon { - vertical-align: middle; - height: 16px; - width: 16px; - background-position: -48px -24px; -} - -.goog-tree-item-label { - margin-left: 3px; - padding: 1px 2px 1px 2px; - text-decoration: none; - color: WindowText; - cursor: default; -} - -.goog-tree-item-label:hover { - text-decoration: underline; -} - -.selected .goog-tree-item-label { - background-color: ButtonFace; - color: ButtonText; -} - -.focused .selected .goog-tree-item-label { - background-color: Highlight; - color: HighlightText; -} - -.goog-tree-hide-root { - display: none; -} diff --git a/src/database/third_party/closure-library/closure/goog/css/tristatemenuitem.css b/src/database/third_party/closure-library/closure/goog/css/tristatemenuitem.css deleted file mode 100644 index 8c98448afba..00000000000 --- a/src/database/third_party/closure-library/closure/goog/css/tristatemenuitem.css +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2007 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* Author: pupius@google.com (Daniel Pupius) */ - -/* goog.ui.TriStateMenuItem */ - -.goog-tristatemenuitem { - padding: 2px 5px; - margin: 0; - list-style: none; -} - -.goog-tristatemenuitem-highlight { - background-color: #4279A5; - color: #FFF; -} - -.goog-tristatemenuitem-disabled { - color: #999; -} - -.goog-tristatemenuitem-checkbox { - float: left; - width: 10px; - height: 1.1em; -} - -.goog-tristatemenuitem-partially-checked { - background-image: url(//ssl.gstatic.com/closure/check-outline.gif); - background-position: 4px 50%; - background-repeat: no-repeat; -} - -.goog-tristatemenuitem-fully-checked { - background-image: url(//ssl.gstatic.com/closure/check.gif); - background-position: 4px 50%; - background-repeat: no-repeat; -} diff --git a/src/database/third_party/closure-library/closure/goog/cssom/cssom.js b/src/database/third_party/closure-library/closure/goog/cssom/cssom.js deleted file mode 100644 index 0be1b5add99..00000000000 --- a/src/database/third_party/closure-library/closure/goog/cssom/cssom.js +++ /dev/null @@ -1,454 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview CSS Object Model helper functions. - * References: - * - W3C: http://dev.w3.org/csswg/cssom/ - * - MSDN: http://msdn.microsoft.com/en-us/library/ms531209(VS.85).aspx. - * @supported in FF3, IE6, IE7, Safari 3.1.2, Chrome - * TODO(user): Fix in Opera. - * TODO(user): Consider hacking page, media, etc.. to work. - * This would be pretty challenging. IE returns the text for any rule - * regardless of whether or not the media is correct or not. Firefox at - * least supports CSSRule.type to figure out if it's a media type and then - * we could do something interesting, but IE offers no way for us to tell. - */ - -goog.provide('goog.cssom'); -goog.provide('goog.cssom.CssRuleType'); - -goog.require('goog.array'); -goog.require('goog.dom'); - - -/** - * Enumeration of {@code CSSRule} types. - * @enum {number} - */ -goog.cssom.CssRuleType = { - STYLE: 1, - IMPORT: 3, - MEDIA: 4, - FONT_FACE: 5, - PAGE: 6, - NAMESPACE: 7 -}; - - -/** - * Recursively gets all CSS as text, optionally starting from a given - * CSSStyleSheet. - * @param {(CSSStyleSheet|StyleSheetList)=} opt_styleSheet The CSSStyleSheet. - * @return {string} css text. - */ -goog.cssom.getAllCssText = function(opt_styleSheet) { - var styleSheet = opt_styleSheet || document.styleSheets; - return /** @type {string} */ (goog.cssom.getAllCss_(styleSheet, true)); -}; - - -/** - * Recursively gets all CSSStyleRules, optionally starting from a given - * CSSStyleSheet. - * Note that this excludes any CSSImportRules, CSSMediaRules, etc.. - * @param {(CSSStyleSheet|StyleSheetList)=} opt_styleSheet The CSSStyleSheet. - * @return {Array} A list of CSSStyleRules. - */ -goog.cssom.getAllCssStyleRules = function(opt_styleSheet) { - var styleSheet = opt_styleSheet || document.styleSheets; - return /** @type {!Array} */ ( - goog.cssom.getAllCss_(styleSheet, false)); -}; - - -/** - * Returns the CSSRules from a styleSheet. - * Worth noting here is that IE and FF differ in terms of what they will return. - * Firefox will return styleSheet.cssRules, which includes ImportRules and - * anything which implements the CSSRules interface. IE returns simply a list of - * CSSRules. - * @param {CSSStyleSheet} styleSheet The CSSStyleSheet. - * @throws {Error} If we cannot access the rules on a stylesheet object - this - * can happen if a stylesheet object's rules are accessed before the rules - * have been downloaded and parsed and are "ready". - * @return {CSSRuleList} An array of CSSRules or null. - */ -goog.cssom.getCssRulesFromStyleSheet = function(styleSheet) { - var cssRuleList = null; - try { - // Select cssRules unless it isn't present. For pre-IE9 IE, use the rules - // collection instead. - // It's important to be consistent in using only the W3C or IE apis on - // IE9+ where both are present to ensure that there is no indexing - // mismatches - the collections are subtly different in what the include or - // exclude which can lead to one collection being longer than the other - // depending on the page's construction. - cssRuleList = styleSheet.cssRules /* W3C */ || styleSheet.rules /* IE */; - } catch (e) { - // This can happen if we try to access the CSSOM before it's "ready". - if (e.code == 15) { - // Firefox throws an NS_ERROR_DOM_INVALID_ACCESS_ERR error if a stylesheet - // is read before it has been fully parsed. Let the caller know which - // stylesheet failed. - e.styleSheet = styleSheet; - throw e; - } - } - return cssRuleList; -}; - - -/** - * Gets all CSSStyleSheet objects starting from some CSSStyleSheet. Note that we - * want to return the sheets in the order of the cascade, therefore if we - * encounter an import, we will splice that CSSStyleSheet object in front of - * the CSSStyleSheet that contains it in the returned array of CSSStyleSheets. - * @param {(CSSStyleSheet|StyleSheetList)=} opt_styleSheet A CSSStyleSheet. - * @param {boolean=} opt_includeDisabled If true, includes disabled stylesheets, - * defaults to false. - * @return {!Array} A list of CSSStyleSheet objects. - */ -goog.cssom.getAllCssStyleSheets = function(opt_styleSheet, - opt_includeDisabled) { - var styleSheetsOutput = []; - var styleSheet = opt_styleSheet || document.styleSheets; - var includeDisabled = goog.isDef(opt_includeDisabled) ? opt_includeDisabled : - false; - - // Imports need to go first. - if (styleSheet.imports && styleSheet.imports.length) { - for (var i = 0, n = styleSheet.imports.length; i < n; i++) { - goog.array.extend(styleSheetsOutput, - goog.cssom.getAllCssStyleSheets(styleSheet.imports[i])); - } - - } else if (styleSheet.length) { - // In case we get a StyleSheetList object. - // http://dev.w3.org/csswg/cssom/#the-stylesheetlist - for (var i = 0, n = styleSheet.length; i < n; i++) { - goog.array.extend(styleSheetsOutput, - goog.cssom.getAllCssStyleSheets(styleSheet[i])); - } - } else { - // We need to walk through rules in browsers which implement .cssRules - // to see if there are styleSheets buried in there. - // If we have a CSSStyleSheet within CssRules. - var cssRuleList = goog.cssom.getCssRulesFromStyleSheet( - /** @type {!CSSStyleSheet} */ (styleSheet)); - if (cssRuleList && cssRuleList.length) { - // Chrome does not evaluate cssRuleList[i] to undefined when i >=n; - // so we use a (i < n) check instead of cssRuleList[i] in the loop below - // and in other places where we iterate over a rules list. - // See issue # 5917 in Chromium. - for (var i = 0, n = cssRuleList.length, cssRule; i < n; i++) { - cssRule = cssRuleList[i]; - // There are more stylesheets to get on this object.. - if (cssRule.styleSheet) { - goog.array.extend(styleSheetsOutput, - goog.cssom.getAllCssStyleSheets(cssRule.styleSheet)); - } - } - } - } - - // This is a CSSStyleSheet. (IE uses .rules, W3c and Opera cssRules.) - if ((styleSheet.type || styleSheet.rules || styleSheet.cssRules) && - (!styleSheet.disabled || includeDisabled)) { - styleSheetsOutput.push(styleSheet); - } - - return styleSheetsOutput; -}; - - -/** - * Gets the cssText from a CSSRule object cross-browserly. - * @param {CSSRule} cssRule A CSSRule. - * @return {string} cssText The text for the rule, including the selector. - */ -goog.cssom.getCssTextFromCssRule = function(cssRule) { - var cssText = ''; - - if (cssRule.cssText) { - // W3C. - cssText = cssRule.cssText; - } else if (cssRule.style && cssRule.style.cssText && cssRule.selectorText) { - // IE: The spacing here is intended to make the result consistent with - // FF and Webkit. - // We also remove the special properties that we may have added in - // getAllCssStyleRules since IE includes those in the cssText. - var styleCssText = cssRule.style.cssText. - replace(/\s*-closure-parent-stylesheet:\s*\[object\];?\s*/gi, ''). - replace(/\s*-closure-rule-index:\s*[\d]+;?\s*/gi, ''); - var thisCssText = cssRule.selectorText + ' { ' + styleCssText + ' }'; - cssText = thisCssText; - } - - return cssText; -}; - - -/** - * Get the index of the CSSRule in it's CSSStyleSheet. - * @param {CSSRule} cssRule A CSSRule. - * @param {CSSStyleSheet=} opt_parentStyleSheet A reference to the stylesheet - * object this cssRule belongs to. - * @throws {Error} When we cannot get the parentStyleSheet. - * @return {number} The index of the CSSRule, or -1. - */ -goog.cssom.getCssRuleIndexInParentStyleSheet = function(cssRule, - opt_parentStyleSheet) { - // Look for our special style.ruleIndex property from getAllCss. - if (cssRule.style && cssRule.style['-closure-rule-index']) { - return cssRule.style['-closure-rule-index']; - } - - var parentStyleSheet = opt_parentStyleSheet || - goog.cssom.getParentStyleSheet(cssRule); - - if (!parentStyleSheet) { - // We could call getAllCssStyleRules() here to get our special indexes on - // the style object, but that seems like it could be wasteful. - throw Error('Cannot find a parentStyleSheet.'); - } - - var cssRuleList = goog.cssom.getCssRulesFromStyleSheet(parentStyleSheet); - if (cssRuleList && cssRuleList.length) { - for (var i = 0, n = cssRuleList.length, thisCssRule; i < n; i++) { - thisCssRule = cssRuleList[i]; - if (thisCssRule == cssRule) { - return i; - } - } - } - return -1; -}; - - -/** - * We do some trickery in getAllCssStyleRules that hacks this in for IE. - * If the cssRule object isn't coming from a result of that function call, this - * method will return undefined in IE. - * @param {CSSRule} cssRule The CSSRule. - * @return {CSSStyleSheet} A styleSheet object. - */ -goog.cssom.getParentStyleSheet = function(cssRule) { - return cssRule.parentStyleSheet || - cssRule.style && - cssRule.style['-closure-parent-stylesheet']; -}; - - -/** - * Replace a cssRule with some cssText for a new rule. - * If the cssRule object is not one of objects returned by - * getAllCssStyleRules, then you'll need to provide both the styleSheet and - * possibly the index, since we can't infer them from the standard cssRule - * object in IE. We do some trickery in getAllCssStyleRules to hack this in. - * @param {CSSRule} cssRule A CSSRule. - * @param {string} cssText The text for the new CSSRule. - * @param {CSSStyleSheet=} opt_parentStyleSheet A reference to the stylesheet - * object this cssRule belongs to. - * @param {number=} opt_index The index of the cssRule in its parentStylesheet. - * @throws {Error} If we cannot find a parentStyleSheet. - * @throws {Error} If we cannot find a css rule index. - */ -goog.cssom.replaceCssRule = function(cssRule, cssText, opt_parentStyleSheet, - opt_index) { - var parentStyleSheet = opt_parentStyleSheet || - goog.cssom.getParentStyleSheet(cssRule); - if (parentStyleSheet) { - var index = opt_index >= 0 ? opt_index : - goog.cssom.getCssRuleIndexInParentStyleSheet(cssRule, parentStyleSheet); - if (index >= 0) { - goog.cssom.removeCssRule(parentStyleSheet, index); - goog.cssom.addCssRule(parentStyleSheet, cssText, index); - } else { - throw Error('Cannot proceed without the index of the cssRule.'); - } - } else { - throw Error('Cannot proceed without the parentStyleSheet.'); - } -}; - - -/** - * Cross browser function to add a CSSRule into a CSSStyleSheet, optionally - * at a given index. - * @param {CSSStyleSheet} cssStyleSheet The CSSRule's parentStyleSheet. - * @param {string} cssText The text for the new CSSRule. - * @param {number=} opt_index The index of the cssRule in its parentStylesheet. - * @throws {Error} If the css rule text appears to be ill-formatted. - * TODO(bowdidge): Inserting at index 0 fails on Firefox 2 and 3 with an - * exception warning "Node cannot be inserted at the specified point in - * the hierarchy." - */ -goog.cssom.addCssRule = function(cssStyleSheet, cssText, opt_index) { - var index = opt_index; - if (index < 0 || index == undefined) { - // If no index specified, insert at the end of the current list - // of rules. - var rules = goog.cssom.getCssRulesFromStyleSheet(cssStyleSheet); - index = rules.length; - } - if (cssStyleSheet.insertRule) { - // W3C (including IE9+). - cssStyleSheet.insertRule(cssText, index); - - } else { - // IE, pre 9: We have to parse the cssRule text to get the selector - // separated from the style text. - // aka Everything that isn't a colon, followed by a colon, then - // the rest is the style part. - var matches = /^([^\{]+)\{([^\{]+)\}/.exec(cssText); - if (matches.length == 3) { - var selector = matches[1]; - var style = matches[2]; - cssStyleSheet.addRule(selector, style, index); - } else { - throw Error('Your CSSRule appears to be ill-formatted.'); - } - } -}; - - -/** - * Cross browser function to remove a CSSRule in a CSSStyleSheet at an index. - * @param {CSSStyleSheet} cssStyleSheet The CSSRule's parentStyleSheet. - * @param {number} index The CSSRule's index in the parentStyleSheet. - */ -goog.cssom.removeCssRule = function(cssStyleSheet, index) { - if (cssStyleSheet.deleteRule) { - // W3C. - cssStyleSheet.deleteRule(index); - - } else { - // IE. - cssStyleSheet.removeRule(index); - } -}; - - -/** - * Appends a DOM node to HEAD containing the css text that's passed in. - * @param {string} cssText CSS to add to the end of the document. - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper user for - * document interactions. - * @return {!Element} The newly created STYLE element. - */ -goog.cssom.addCssText = function(cssText, opt_domHelper) { - var document = opt_domHelper ? opt_domHelper.getDocument() : - goog.dom.getDocument(); - var cssNode = document.createElement('style'); - cssNode.type = 'text/css'; - var head = document.getElementsByTagName('head')[0]; - head.appendChild(cssNode); - if (cssNode.styleSheet) { - // IE. - cssNode.styleSheet.cssText = cssText; - } else { - // W3C. - var cssTextNode = document.createTextNode(cssText); - cssNode.appendChild(cssTextNode); - } - return cssNode; -}; - - -/** - * Cross browser method to get the filename from the StyleSheet's href. - * Explorer only returns the filename in the href, while other agents return - * the full path. - * @param {!StyleSheet} styleSheet Any valid StyleSheet object with an href. - * @throws {Error} When there's no href property found. - * @return {?string} filename The filename, or null if not an external - * styleSheet. - */ -goog.cssom.getFileNameFromStyleSheet = function(styleSheet) { - var href = styleSheet.href; - - // Another IE/FF difference. IE returns an empty string, while FF and others - // return null for CSSStyleSheets not from an external file. - if (!href) { - return null; - } - - // We need the regexp to ensure we get the filename minus any query params. - var matches = /([^\/\?]+)[^\/]*$/.exec(href); - var filename = matches[1]; - return filename; -}; - - -/** - * Recursively gets all CSS text or rules. - * @param {CSSStyleSheet|StyleSheetList} styleSheet The CSSStyleSheet. - * @param {boolean} isTextOutput If true, output is cssText, otherwise cssRules. - * @return {string|!Array} cssText or cssRules. - * @private - */ -goog.cssom.getAllCss_ = function(styleSheet, isTextOutput) { - var cssOut = []; - var styleSheets = goog.cssom.getAllCssStyleSheets(styleSheet); - - for (var i = 0; styleSheet = styleSheets[i]; i++) { - var cssRuleList = goog.cssom.getCssRulesFromStyleSheet(styleSheet); - - if (cssRuleList && cssRuleList.length) { - - // We're going to track cssRule index if we want rule output. - if (!isTextOutput) { - var ruleIndex = 0; - } - - for (var j = 0, n = cssRuleList.length, cssRule; j < n; j++) { - cssRule = cssRuleList[j]; - // Gets cssText output, ignoring CSSImportRules. - if (isTextOutput && !cssRule.href) { - var res = goog.cssom.getCssTextFromCssRule(cssRule); - cssOut.push(res); - - } else if (!cssRule.href) { - // Gets cssRules output, ignoring CSSImportRules. - if (cssRule.style) { - // This is a fun little hack to get parentStyleSheet into the rule - // object for IE since it failed to implement rule.parentStyleSheet. - // We can later read this property when doing things like hunting - // for indexes in order to delete a given CSSRule. - // Unfortunately we have to use the style object to store these - // pieces of info since the rule object is read-only. - if (!cssRule.parentStyleSheet) { - cssRule.style['-closure-parent-stylesheet'] = styleSheet; - } - - // This is a hack to help with possible removal of the rule later, - // where we just append the rule's index in its parentStyleSheet - // onto the style object as a property. - // Unfortunately we have to use the style object to store these - // pieces of info since the rule object is read-only. - cssRule.style['-closure-rule-index'] = ruleIndex; - } - cssOut.push(cssRule); - } - - if (!isTextOutput) { - ruleIndex++; - } - } - } - } - return isTextOutput ? cssOut.join(' ') : cssOut; -}; - diff --git a/src/database/third_party/closure-library/closure/goog/cssom/cssom_test.html b/src/database/third_party/closure-library/closure/goog/cssom/cssom_test.html deleted file mode 100644 index cdd18a1980f..00000000000 --- a/src/database/third_party/closure-library/closure/goog/cssom/cssom_test.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - Closure Unit Tests - CSS Object Model helper - - - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/cssom/cssom_test.js b/src/database/third_party/closure-library/closure/goog/cssom/cssom_test.js deleted file mode 100644 index 80b5002ff1c..00000000000 --- a/src/database/third_party/closure-library/closure/goog/cssom/cssom_test.js +++ /dev/null @@ -1,323 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.cssomTest'); -goog.setTestOnly('goog.cssomTest'); - -goog.require('goog.array'); -goog.require('goog.cssom'); -goog.require('goog.cssom.CssRuleType'); -goog.require('goog.testing.jsunit'); -goog.require('goog.userAgent'); - -// Since sheet cssom_test1.css's first line is to import -// cssom_test2.css, we should get 2 before one in the string. -var cssText = '.css-link-1 { display: block; } ' + - '.css-import-2 { display: block; } ' + - '.css-import-1 { display: block; } ' + - '.css-style-1 { display: block; } ' + - '.css-style-2 { display: block; } ' + - '.css-style-3 { display: block; }'; - -var replacementCssText = '.css-repl-1 { display: block; }'; - -var isIe7 = goog.userAgent.IE && - (goog.userAgent.compare(goog.userAgent.VERSION, '7.0') == 0); - -// We're going to toLowerCase cssText before testing, because IE returns -// CSS property names in UPPERCASE, and the function shouldn't -// "fix" the text as it would be expensive and rarely of use. -// Same goes for the trailing whitespace in IE. -// Same goes for fixing the optimized removal of trailing ; in rules. -// Also needed for Opera. -function fixCssTextForIe(cssText) { - cssText = cssText.toLowerCase().replace(/\s*$/, ''); - if (cssText.match(/[^;] \}/)) { - cssText = cssText.replace(/([^;]) \}/g, '$1; }'); - } - return cssText; -} - -function testGetFileNameFromStyleSheet() { - var styleSheet = {'href': 'http://foo.com/something/filename.css'}; - assertEquals('filename.css', - goog.cssom.getFileNameFromStyleSheet(styleSheet)); - - styleSheet = {'href': 'https://foo.com:123/something/filename.css'}; - assertEquals('filename.css', - goog.cssom.getFileNameFromStyleSheet(styleSheet)); - - styleSheet = {'href': 'http://foo.com/something/filename.css?bar=bas'}; - assertEquals('filename.css', - goog.cssom.getFileNameFromStyleSheet(styleSheet)); - - styleSheet = {'href': 'filename.css?bar=bas'}; - assertEquals('filename.css', - goog.cssom.getFileNameFromStyleSheet(styleSheet)); - - styleSheet = {'href': 'filename.css'}; - assertEquals('filename.css', - goog.cssom.getFileNameFromStyleSheet(styleSheet)); -} - -function testGetAllCssStyleSheets() { - var styleSheets = goog.cssom.getAllCssStyleSheets(); - assertEquals(4, styleSheets.length); - // Makes sure they're in the right cascade order. - assertEquals('cssom_test_link_1.css', - goog.cssom.getFileNameFromStyleSheet(styleSheets[0])); - assertEquals('cssom_test_import_2.css', - goog.cssom.getFileNameFromStyleSheet(styleSheets[1])); - assertEquals('cssom_test_import_1.css', - goog.cssom.getFileNameFromStyleSheet(styleSheets[2])); - // Not an external styleSheet - assertNull(goog.cssom.getFileNameFromStyleSheet(styleSheets[3])); -} - -function testGetAllCssText() { - var allCssText = goog.cssom.getAllCssText(); - // In IE7, a CSSRule object gets included twice and replaces another - // existing CSSRule object. We aren't using - // goog.testing.ExpectedFailures since it brings in additional CSS - // which breaks a lot of our expectations about the number of rules - // present in a style sheet. - if (!isIe7) { - assertEquals(cssText, fixCssTextForIe(allCssText)); - } -} - -function testGetAllCssStyleRules() { - var allCssRules = goog.cssom.getAllCssStyleRules(); - assertEquals(6, allCssRules.length); -} - - -function testAddCssText() { - var newCssText = '.css-add-1 { display: block; }'; - var newCssNode = goog.cssom.addCssText(newCssText); - - assertEquals(document.styleSheets.length, 3); - - var allCssText = goog.cssom.getAllCssText(); - - // In IE7, a CSSRule object gets included twice and replaces another - // existing CSSRule object. We aren't using - // goog.testing.ExpectedFailures since it brings in additional CSS - // which breaks a lot of our expectations about the number of rules - // present in a style sheet. - if (!isIe7) { - // Opera inserts the CSSRule to the first position. And fixCssText - // is also needed to clean up whitespace. - if (goog.userAgent.OPERA) { - assertEquals(newCssText + ' ' + cssText, - fixCssTextForIe(allCssText)); - } else { - assertEquals(cssText + ' ' + newCssText, - fixCssTextForIe(allCssText)); - } - } - - var cssRules = goog.cssom.getAllCssStyleRules(); - assertEquals(7, cssRules.length); - - // Remove the new stylesheet now so it doesn't interfere with other - // tests. - newCssNode.parentNode.removeChild(newCssNode); - // Sanity check. - cssRules = goog.cssom.getAllCssStyleRules(); - assertEquals(6, cssRules.length); -} - -function testAddCssRule() { - // test that addCssRule correctly adds the rule to the style - // sheet. - var styleSheets = goog.cssom.getAllCssStyleSheets(); - var styleSheet = styleSheets[3]; - var newCssRule = '.css-addCssRule { display: block; }'; - var rules = styleSheet.rules || styleSheet.cssRules; - var origNumberOfRules = rules.length; - - goog.cssom.addCssRule(styleSheet, newCssRule, 1); - - rules = styleSheet.rules || styleSheet.cssRules; - var newNumberOfRules = rules.length; - assertEquals(newNumberOfRules, origNumberOfRules + 1); - - // Remove the added rule so we don't mess up other tests. - goog.cssom.removeCssRule(styleSheet, 1); -} - -function testAddCssRuleAtPos() { - // test that addCssRule correctly adds the rule to the style - // sheet at the specified position. - var styleSheets = goog.cssom.getAllCssStyleSheets(); - var styleSheet = styleSheets[3]; - var newCssRule = '.css-addCssRulePos { display: block; }'; - var rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet); - var origNumberOfRules = rules.length; - - // Firefox croaks if we try to insert a CSSRule at an index that - // contains a CSSImport Rule. Since we deal only with CSSStyleRule - // objects, we find the first CSSStyleRule and return its index. - // - // NOTE(user): We could have unified the code block below for all - // browsers but IE6 horribly mangled up the stylesheet by creating - // duplicate instances of a rule when removeCssRule was invoked - // just after addCssRule with the looping construct in. This is - // perfectly fine since IE's styleSheet.rules does not contain - // references to anything but CSSStyleRules. - var pos = 0; - if (styleSheet.cssRules) { - pos = goog.array.findIndex(rules, function(rule) { - return rule.type == goog.cssom.CssRuleType.STYLE; - }); - } - goog.cssom.addCssRule(styleSheet, newCssRule, pos); - - rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet); - var newNumberOfRules = rules.length; - assertEquals(newNumberOfRules, origNumberOfRules + 1); - - // Remove the added rule so we don't mess up other tests. - goog.cssom.removeCssRule(styleSheet, pos); - - rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet); - assertEquals(origNumberOfRules, rules.length); -} - -function testAddCssRuleNoIndex() { - // How well do we handle cases where the optional index is - // not passed in? - var styleSheets = goog.cssom.getAllCssStyleSheets(); - var styleSheet = styleSheets[3]; - var rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet); - var origNumberOfRules = rules.length; - var newCssRule = '.css-addCssRuleNoIndex { display: block; }'; - - // Try inserting the rule without specifying an index. - // Make sure we don't throw an exception, and that we added - // the entry. - goog.cssom.addCssRule(styleSheet, newCssRule); - - rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet); - var newNumberOfRules = rules.length; - assertEquals(newNumberOfRules, origNumberOfRules + 1); - - // Remove the added rule so we don't mess up the other tests. - goog.cssom.removeCssRule(styleSheet, newNumberOfRules - 1); - - rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet); - assertEquals(origNumberOfRules, rules.length); -} - - -function testGetParentStyleSheetAfterGetAllCssStyleRules() { - var cssRules = goog.cssom.getAllCssStyleRules(); - var cssRule = cssRules[4]; - var parentStyleSheet = goog.cssom.getParentStyleSheet(cssRule); - var styleSheets = goog.cssom.getAllCssStyleSheets(); - var styleSheet = styleSheets[3]; - assertEquals(styleSheet, parentStyleSheet); -} - -function testGetCssRuleIndexInParentStyleSheetAfterGetAllCssStyleRules() { - var cssRules = goog.cssom.getAllCssStyleRules(); - var cssRule = cssRules[4]; - // Note here that this is correct - IE's styleSheet.rules does not - // contain references to anything but CSSStyleRules while FF and others - // include anything that inherits from the CSSRule interface. - // See http://dev.w3.org/csswg/cssom/#cssrule. - var parentStyleSheet = goog.cssom.getParentStyleSheet(cssRule); - var ruleIndex = goog.isDefAndNotNull(parentStyleSheet.cssRules) ? 2 : 1; - assertEquals(ruleIndex, - goog.cssom.getCssRuleIndexInParentStyleSheet(cssRule)); -} - -function testGetCssRuleIndexInParentStyleSheetNonStyleRule() { - // IE's styleSheet.rules only contain CSSStyleRules. - if (!goog.userAgent.IE) { - var styleSheets = goog.cssom.getAllCssStyleSheets(); - var styleSheet = styleSheets[3]; - var newCssRule = '@media print { .css-nonStyle { display: block; } }'; - goog.cssom.addCssRule(styleSheet, newCssRule); - var rules = styleSheet.rules || styleSheet.cssRules; - var cssRule = rules[rules.length - 1]; - assertEquals(goog.cssom.CssRuleType.MEDIA, cssRule.type); - // Make sure we don't throw an exception. - goog.cssom.getCssRuleIndexInParentStyleSheet(cssRule, styleSheet); - // Remove the added rule. - goog.cssom.removeCssRule(styleSheet, rules.length - 1); - } -} - -// Tests the scenario where we have a known stylesheet and index. -function testReplaceCssRuleWithStyleSheetAndIndex() { - var styleSheets = goog.cssom.getAllCssStyleSheets(); - var styleSheet = styleSheets[3]; - var rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet); - var index = 2; - var origCssRule = rules[index]; - var origCssText = - fixCssTextForIe(goog.cssom.getCssTextFromCssRule(origCssRule)); - - goog.cssom.replaceCssRule(origCssRule, replacementCssText, styleSheet, - index); - - var rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet); - var newCssRule = rules[index]; - var newCssText = goog.cssom.getCssTextFromCssRule(newCssRule); - assertEquals(replacementCssText, fixCssTextForIe(newCssText)); - - // Now we need to re-replace our rule, to preserve parity for the other - // tests. - goog.cssom.replaceCssRule(newCssRule, origCssText, styleSheet, index); - var rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet); - var nowCssRule = rules[index]; - var nowCssText = goog.cssom.getCssTextFromCssRule(nowCssRule); - assertEquals(origCssText, fixCssTextForIe(nowCssText)); -} - -function testReplaceCssRuleUsingGetAllCssStyleRules() { - var cssRules = goog.cssom.getAllCssStyleRules(); - var origCssRule = cssRules[4]; - var origCssText = - fixCssTextForIe(goog.cssom.getCssTextFromCssRule(origCssRule)); - // notice we don't pass in the stylesheet or index. - goog.cssom.replaceCssRule(origCssRule, replacementCssText); - - var styleSheets = goog.cssom.getAllCssStyleSheets(); - var styleSheet = styleSheets[3]; - var rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet); - var index = goog.isDefAndNotNull(styleSheet.cssRules) ? 2 : 1; - var newCssRule = rules[index]; - var newCssText = - fixCssTextForIe(goog.cssom.getCssTextFromCssRule(newCssRule)); - assertEquals(replacementCssText, newCssText); - - // try getting it the other way around too. - var cssRules = goog.cssom.getAllCssStyleRules(); - var newCssRule = cssRules[4]; - var newCssText = - fixCssTextForIe(goog.cssom.getCssTextFromCssRule(newCssRule)); - assertEquals(replacementCssText, newCssText); - - // Now we need to re-replace our rule, to preserve parity for the other - // tests. - goog.cssom.replaceCssRule(newCssRule, origCssText); - var cssRules = goog.cssom.getAllCssStyleRules(); - var nowCssRule = cssRules[4]; - var nowCssText = - fixCssTextForIe(goog.cssom.getCssTextFromCssRule(nowCssRule)); - assertEquals(origCssText, nowCssText); -} diff --git a/src/database/third_party/closure-library/closure/goog/cssom/cssom_test_import_1.css b/src/database/third_party/closure-library/closure/goog/cssom/cssom_test_import_1.css deleted file mode 100644 index 566f907ff81..00000000000 --- a/src/database/third_party/closure-library/closure/goog/cssom/cssom_test_import_1.css +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright 2010 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -@import "cssom_test_import_2.css"; -.css-import-1 { - display: block; -} diff --git a/src/database/third_party/closure-library/closure/goog/cssom/cssom_test_import_2.css b/src/database/third_party/closure-library/closure/goog/cssom/cssom_test_import_2.css deleted file mode 100644 index dc31c9620a4..00000000000 --- a/src/database/third_party/closure-library/closure/goog/cssom/cssom_test_import_2.css +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright 2010 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -.css-import-2 { - display: block; -} diff --git a/src/database/third_party/closure-library/closure/goog/cssom/cssom_test_link_1.css b/src/database/third_party/closure-library/closure/goog/cssom/cssom_test_link_1.css deleted file mode 100644 index 832a8e31ce9..00000000000 --- a/src/database/third_party/closure-library/closure/goog/cssom/cssom_test_link_1.css +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright 2010 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -.css-link-1 { - display: block; -} diff --git a/src/database/third_party/closure-library/closure/goog/cssom/iframe/style.js b/src/database/third_party/closure-library/closure/goog/cssom/iframe/style.js deleted file mode 100644 index 24c8c057c98..00000000000 --- a/src/database/third_party/closure-library/closure/goog/cssom/iframe/style.js +++ /dev/null @@ -1,1016 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// All Rights Reserved. - -/** - * @fileoverview Provides utility routines for copying modified - * {@code CSSRule} objects from the parent document into iframes so that any - * content in the iframe will be styled as if it was inline in the parent - * document. - * - *

- * For example, you might have this CSS rule: - * - * #content .highlighted { background-color: yellow; } - * - * And this DOM structure: - * - *

- * - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/autocompleterichremotedata.js b/src/database/third_party/closure-library/closure/goog/demos/autocompleterichremotedata.js deleted file mode 100644 index 0fad7db1ecf..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/autocompleterichremotedata.js +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2010 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** @nocompile */ - -[ - ['apple', - {name: 'Fuji', url: 'http://www.google.com/images?q=fuji+apple'}, - {name: 'Gala', url: 'http://www.google.com/images?q=gala+apple'}, - {name: 'Golden Delicious', - url: 'http://www.google.com/images?q=golden delicious+apple'} - ], - ['citrus', - {name: 'Lemon', url: 'http://www.google.com/images?q=lemon+fruit'}, - {name: 'Orange', url: 'http://www.google.com/images?q=orange+fruit'} - ], - ['berry', - {name: 'Strawberry', url: 'http://www.google.com/images?q=strawberry+fruit'}, - {name: 'Blueberry', url: 'http://www.google.com/images?q=blueberry+fruit'}, - {name: 'Blackberry', url: 'http://www.google.com/images?q=blackberry+fruit'} - ] -] diff --git a/src/database/third_party/closure-library/closure/goog/demos/bidiinput.html b/src/database/third_party/closure-library/closure/goog/demos/bidiinput.html deleted file mode 100644 index 7cafe51de14..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/bidiinput.html +++ /dev/null @@ -1,72 +0,0 @@ - - - - - goog.ui.BidiInput - - - - - -

goog.ui.BidiInput

- -

- The direction of the input field changes automatically to RTL (right to left) - if the contents is in an RTL language (e.g. Hebrew or Arabic). -

- -
- A decorated input:  - Text: - -
- -
- -
- An input created programmatically:  - Text: ! - - -
- - -
- -
- A decorated textarea:  - - -
- -
- -
-
- Right to left div:  - - -
-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/blobhasher.html b/src/database/third_party/closure-library/closure/goog/demos/blobhasher.html deleted file mode 100644 index 2403f82652e..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/blobhasher.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - -goog.crypt.BlobHasher - - - - - -

goog.crypt.BlobHasher

- - - -
File: - - -
MD5:
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/bubble.html b/src/database/third_party/closure-library/closure/goog/demos/bubble.html deleted file mode 100644 index e10bb0e3fd8..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/bubble.html +++ /dev/null @@ -1,250 +0,0 @@ - - - - - - goog.ui.Bubble - - - - - - -

goog.ui.Bubble

- - - - - - - - - - - - - - - - - - -
-
-
- - -
-
-
-
-
- - -
-
-
-
-
- - -
-
-
-
-
- - -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - -
X:
Y:
Corner orientation(0-3):
Auto-hide (true or false):
Timeout (ms):
Decorated
- -
-
-
-
-
-
-
-
- - -
-
-
-
-
- - -
-
-
-
-
- - -
-
-
-
-
- - -
-
-
- - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/button.html b/src/database/third_party/closure-library/closure/goog/demos/button.html deleted file mode 100644 index 7d86c906de6..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/button.html +++ /dev/null @@ -1,395 +0,0 @@ - - - - - goog.ui.Button and goog.ui.ToggleButton - - - - - - - - - - -

goog.ui.Button

-
- - The first Button was created programmatically, - the second by decorating an <input> element:  - -
- -
-
-
- -
-
-
- -

goog.ui.FlatButtonRenderer

-
- - Buttons made with <div>'s instead of - <input>'s or <button>'s - The first rendered, the second decorated:  - -
- -
-
-
My Flat Button

- -
-
-
- Combined -
- Buttons -
-
-
-
- -

goog.ui.LinkButtonRenderer

-
- - Like FlatButtonRenderer, except the style makes the button appear to be a - link. - -
- -
- -

goog.ui.CustomButton & goog.ui.ToggleButton

-
- - These buttons were rendered using goog.ui.CustomButton: -   - -
- These buttons were created programmatically:
-
-
- These buttons were created by decorating some DIVs, and they dispatch - state transition events (watch the event log):
-
- -
- Decorated Button, yay! -
-
Decorated Disabled
-
Another Button
-
- Archive -
- Delete -
- Report Spam -
-
-
- Use these ToggleButtons to hide/show and enable/disable - the middle button:
-
Enable
-   -
Show
-

- Combined toggle buttons:
-
- Bold -
- Italics -
- Underlined -
-
-
- These buttons have icons, and the second one has an extra CSS class:
-
-
- - The button with the orange - outline has keyboard focus. Hit Enter to activate focused buttons. - -
-
-
- -
- Event Log -
-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/charcounter.html b/src/database/third_party/closure-library/closure/goog/demos/charcounter.html deleted file mode 100644 index a37c32148f2..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/charcounter.html +++ /dev/null @@ -1,57 +0,0 @@ - - - - - goog.ui.CharCounter - - - - - -

goog.ui.CharCounter

- -

- - character(s) remaining -

-

- - You have entered character(s) of a maximum 160. -

-

- - character(s) remaining - - -

-

- - character(s) remaining -

- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/charpicker.html b/src/database/third_party/closure-library/closure/goog/demos/charpicker.html deleted file mode 100644 index 7c769c8d02d..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/charpicker.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - - goog.ui.CharPicker - - - - - - - - - - - - - - - - - -

goog.ui.CharPicker

-

You have selected: none -

- - -

- -

- - diff --git a/src/database/third_party/closure-library/closure/goog/demos/checkbox.html b/src/database/third_party/closure-library/closure/goog/demos/checkbox.html deleted file mode 100644 index 7bfd59fdbc9..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/checkbox.html +++ /dev/null @@ -1,122 +0,0 @@ - - - - - goog.ui.Checkbox - - - - - - -

goog.ui.Checkbox

-

This is a tri-state checkbox.

-
- Enable/disable
-
-
root
-
-
leaf 1
-
leaf 2
-
-
-
- Created with render -
-
-
- Created with decorate - - - - -
-

- -
- Event Log for 'root', 'leaf1', 'leaf2' -
-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/color-contrast.html b/src/database/third_party/closure-library/closure/goog/demos/color-contrast.html deleted file mode 100644 index 58eeac78843..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/color-contrast.html +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - Color Contrast Test - - - - - -

- # - - This text should be readable -

-

(Only choosing from black and white.)

- - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/colormenubutton.html b/src/database/third_party/closure-library/closure/goog/demos/colormenubutton.html deleted file mode 100644 index ba68c0f264d..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/colormenubutton.html +++ /dev/null @@ -1,218 +0,0 @@ - - - - - goog.ui.ColorMenuButton - - - - - - - - - - - - - - - -

goog.ui.ColorMenuButton Demo

- - - - - - - -
-
- goog.ui.ColorMenuButton demo: -
This button was created programmatically: 
-
-
- This button decorates a DIV:  -
Color
-
-
-
This button has a custom color menu: 
-
-
-
-
- - goog.ui.ToolbarColorMenuButtonRenderer demo: - -
- This toolbar button was created programmatically:  -
-
-
- This toolbar button decorates a DIV:  -
Color
-
-
-
- This is what these would look like in an actual toolbar, with - icons instead of text captions: -
-
-
-
-
-
-
-
-
-
-
-
-
- BiDi is all the rage these days -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
- Event Log -
-
-
-
-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/colorpicker.html b/src/database/third_party/closure-library/closure/goog/demos/colorpicker.html deleted file mode 100644 index 863a598f4bf..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/colorpicker.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - - goog.ui.ColorPicker - - - - - - -

goog.ui.ColorPicker

- -

Simple Color Grid

-
-

- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/combobox.html b/src/database/third_party/closure-library/closure/goog/demos/combobox.html deleted file mode 100644 index d336b6ee27c..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/combobox.html +++ /dev/null @@ -1,160 +0,0 @@ - - - - - goog.ui.ComboBox - - - - - - - - - - -

goog.ui.ComboBox

-
cb.value = ''
- -
- LTR -
-
- -
- LTR -
-
- -
-
- LTR -
-
-
- -
- -
- RTL -
-
- -
- RTL -
-
- -
-
- RTL -
-
-
- - -
- - Clear Log -
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/container.html b/src/database/third_party/closure-library/closure/goog/demos/container.html deleted file mode 100644 index 2b39733307e..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/container.html +++ /dev/null @@ -1,670 +0,0 @@ - - - - - goog.ui.Container - - - - - - - - -

goog.ui.Container

-

goog.ui.Container is a base class for menus and toolbars.

-
- These containers were created programmatically: - - - - - - - - - - - -
- Vertical container example: - - Horizontal container example: -
- -   - -
- -   - -
- -
- -   - -
- -   - -
- -
- Try enabling and disabling containers with & without - state transition events, and compare performance! -
-
-
-
- Non-focusable container with focusable controls: - In this case, the container itself isn't focusable, but each control is:
-
-
-
-
-
- Another horizontal container: - -
-
-
-
-
- A decorated container: - -
-
- Select month -
-
January
-
February
-
March
-
April
-
May
-
June
-
July
-
August
-
September
-
October
-
November
-
December
-
-
-
- Year -
-
2001
-
2002
-
2003
-
2004
-
2005
-
2006
-
2007
-
2008
-
2009
-
2010
-
-
-
- Toggle Button -
-
-
Fancy Toggle Button
-
-
- Another Button -
-
-
-
-
-
- The same container, right-to-left: - - -
-
- Select month -
-
January
-
February
-
March
-
April
-
May
-
June
-
July
-
August
-
September
-
October
-
November
-
December
-
-
-
- Year -
-
2001
-
2002
-
2003
-
2004
-
2005
-
2006
-
2007
-
2008
-
2009
-
2010
-
-
-
- Toggle Button -
-
-
Fancy Toggle Button
-
-
- Another Button -
-
-
-
-
-
- A scrolling container: - -

- Put focus in the text box and use the arrow keys: - -

-

- Or quick jump to item: - - 0 1 2 3 - 4 5 6 7 - 8 9 10 11 - 12 13 14 15 - -

-
-
menuitem 0
-
menuitem 1
-
menuitem 2
-
menuitem 3
-
tog 4
-
tog 5
-
tog 6
-
toggley 7
-
toggley 8
-
toggley 9
-
toggley 10
-
toggley 11
-
toggley 12
-
toggley 13
-
menuitem 14
-
menuitem 15
-
-
-
-
- -
- Event Log -
-
-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/control.html b/src/database/third_party/closure-library/closure/goog/demos/control.html deleted file mode 100644 index 705ee3b87cc..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/control.html +++ /dev/null @@ -1,477 +0,0 @@ - - - - - goog.ui.Control Demo - - - - - - -

goog.ui.Control

- - - - - - - -
- -
- This control was created programmatically:  -
-
- This control dispatches ENTER, LEAVE, and ACTION events on - mouseover, mouseout, and mouseup, respectively. It supports - keyboard focus. -
-
-
- This was created by decorating a SPAN:  - - Decorated Example - -
- - You need to enable this component first. - -
-
- This control is configured to dispatch state transition events in - addition to ENTER, LEAVE, and ACTION. It also supports keyboard - focus. Watch the event log as you interact with this component. -
-
- -
- -
-
-

Custom Renderers

-
- - This control was created using a custom renderer:  - -
-
-
-
- - This was created by decorating a DIV via a custom renderer:  - -
- -   - - - Insert Picture - -
-
-
-

Extra CSS Styling

-
- - These controls have extra CSS classes applied:  - -
-
-
- Use the addClassName API to add additional CSS class names - to controls, before or after they're rendered or decorated. -
-
-

Right-to-Left Rendering

-
- - These controls are rendered right-to-left:  - -

These right-to-left controls were progammatically created:

-
-

These right-to-left controls were decorated:

-
-
- Hello, world -
- Sample control -
-
-

- On pre-FF3 Gecko, margin-left and margin-right are - ignored, so controls render right next to each other. - A workaround is to include some &nbsp;s in between - controls. -

-
-
- -
- Event Log -
-
-
- - The control with the - orange outline - has keyboard focus. - -
-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/css/demo.css b/src/database/third_party/closure-library/closure/goog/demos/css/demo.css deleted file mode 100644 index 6eb82e85b37..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/css/demo.css +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2007 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* Author: attila@google.com (Attila Bodis) */ - - -@import url(../../css/common.css); - - -body { - background-color: #ffe; - font: normal 10pt Arial, sans-serif; -} - - -/* Misc. styles used for logging and debugging. */ -fieldset { - padding: 4px 8px; - margin-bottom: 1em; -} - -fieldset legend { - font-weight: bold; - color: #036; -} - -label, input { - vertical-align: middle; -} - -.hint { - font-size: 90%; - color: #369; -} - -.goog-debug-panel { - border: 1px solid #369; -} - -.goog-debug-panel .logdiv { - position: relative; - width: 100%; - height: 8em; - overflow: scroll; - overflow-x: hidden; - overflow-y: scroll; -} - -.goog-debug-panel .logdiv .logmsg { - font: normal 10px "Lucida Sans Typewriter", "Courier New", Courier, fixed; -} - -.perf { - margin: 0; - border: 0; - padding: 4px; - font: italic 95% Arial, sans-serif; - color: #999; -} - -#perf { - position: absolute; - right: 0; - bottom: 0; - text-align: right; - margin: 0; - border: 0; - padding: 4px; - font: italic 95% Arial, sans-serif; - color: #999; -} diff --git a/src/database/third_party/closure-library/closure/goog/demos/css/emojipicker.css b/src/database/third_party/closure-library/closure/goog/demos/css/emojipicker.css deleted file mode 100644 index 826d5bd54ff..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/css/emojipicker.css +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2007 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* Author: dalewis@google.com (Darren Lewis) */ - -/* Styles used in the emojipicker demo */ -.goog-ui-popupemojipicker { - position: absolute; - -moz-outline: 0; - outline: 0; - visibility: hidden; -} - -.goog-palette-cell { - padding: 2px; - background: white; -} - -.goog-palette-cell div { - vertical-align: middle; - text-align: center; - margin: auto; -} - -.goog-palette-cell-wrapper { - width: 25px; - height: 25px; -} - -.goog-palette-cell-hover { - background: lightblue; -} diff --git a/src/database/third_party/closure-library/closure/goog/demos/css/emojisprite.css b/src/database/third_party/closure-library/closure/goog/demos/css/emojisprite.css deleted file mode 100644 index fe1a2cc1840..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/css/emojisprite.css +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2010 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - -/* This file is autogenerated. To regenerate, do: -cd google3/javascript/closure/demos/emoji -/home/build/static/projects/sitespeed optisprite *.gif - -This will generate an optimal sprite in /usr/local/google/tmp/bestsprite.tar.gz. - -Rename the optimal sprite to "sprite.png" (from sprite_XX.png), rename the css -to "sprite.css" (from sprite_XX.css), then change all the URLs in sprite.css to -point to sprite.png in google3/javascript/closure/demos/emoji, and cp the -sprite.png into that directory. -*/ - -.SPRITE_200{background:no-repeat url(../emoji/sprite.png) -18px 0;width:18px;height:18px} -.SPRITE_201{background:no-repeat url(../emoji/sprite.png) 0 -234px;width:18px;height:18px} -.SPRITE_202{background:no-repeat url(../emoji/sprite.png) -18px -338px;width:18px;height:18px} -.SPRITE_203{background:no-repeat url(../emoji/sprite.png) -36px 0;width:18px;height:18px} -.SPRITE_204{background:no-repeat url(../emoji/sprite.png) 0 -305px;width:18px;height:19px} -.SPRITE_205{background:no-repeat url(../emoji/sprite.png) -36px -126px;width:18px;height:18px} -.SPRITE_206{background:no-repeat url(../emoji/sprite.png) -36px -36px;width:18px;height:18px} -.SPRITE_2BC{background:no-repeat url(../emoji/sprite.png) -18px -144px;width:18px;height:18px} -.SPRITE_2BD{background:no-repeat url(../emoji/sprite.png) 0 -18px;width:18px;height:18px} -.SPRITE_2BE{background:no-repeat url(../emoji/sprite.png) -36px -54px;width:18px;height:18px} -.SPRITE_2BF{background:no-repeat url(../emoji/sprite.png) 0 -126px;width:18px;height:18px} -.SPRITE_2C0{background:no-repeat url(../emoji/sprite.png) -18px -305px;width:18px;height:18px} -.SPRITE_2C1{background:no-repeat url(../emoji/sprite.png) 0 -287px;width:18px;height:18px} -.SPRITE_2C2{background:no-repeat url(../emoji/sprite.png) -18px -126px;width:18px;height:18px} -.SPRITE_2C3{background:no-repeat url(../emoji/sprite.png) -36px -234px;width:18px;height:20px} -.SPRITE_2C4{background:no-repeat url(../emoji/sprite.png) -36px -72px;width:18px;height:18px} -.SPRITE_2C5{background:no-repeat url(../emoji/sprite.png) -54px -54px;width:18px;height:18px} -.SPRITE_2C6{background:no-repeat url(../emoji/sprite.png) 0 -72px;width:18px;height:18px} -.SPRITE_2C7{background:no-repeat url(../emoji/sprite.png) -18px -180px;width:18px;height:18px} -.SPRITE_2C8{background:no-repeat url(../emoji/sprite.png) -36px -198px;width:18px;height:18px} -.SPRITE_2C9{background:no-repeat url(../emoji/sprite.png) -36px -287px;width:18px;height:18px} -.SPRITE_2CB{background:no-repeat url(../emoji/sprite.png) -54px -252px;width:18px;height:18px} -.SPRITE_2CC{background:no-repeat url(../emoji/sprite.png) -54px -288px;width:18px;height:16px} -.SPRITE_2CD{background:no-repeat url(../emoji/sprite.png) -36px -162px;width:18px;height:18px} -.SPRITE_2CE{background:no-repeat url(../emoji/sprite.png) 0 -269px;width:18px;height:18px} -.SPRITE_2CF{background:no-repeat url(../emoji/sprite.png) -36px -108px;width:18px;height:18px} -.SPRITE_2D0{background:no-repeat url(../emoji/sprite.png) -36px -338px;width:18px;height:18px} -.SPRITE_2D1{background:no-repeat url(../emoji/sprite.png) 0 -338px;width:18px;height:18px} -.SPRITE_2D2{background:no-repeat url(../emoji/sprite.png) -54px -36px;width:18px;height:16px} -.SPRITE_2D3{background:no-repeat url(../emoji/sprite.png) -36px -305px;width:18px;height:18px} -.SPRITE_2D4{background:no-repeat url(../emoji/sprite.png) -36px -18px;width:18px;height:18px} -.SPRITE_2D5{background:no-repeat url(../emoji/sprite.png) -18px -108px;width:18px;height:18px} -.SPRITE_2D6{background:no-repeat url(../emoji/sprite.png) -36px -144px;width:18px;height:18px} -.SPRITE_2D7{background:no-repeat url(../emoji/sprite.png) 0 -36px;width:18px;height:18px} -.SPRITE_2D8{background:no-repeat url(../emoji/sprite.png) -54px -126px;width:18px;height:18px} -.SPRITE_2D9{background:no-repeat url(../emoji/sprite.png) -18px -287px;width:18px;height:18px} -.SPRITE_2DA{background:no-repeat url(../emoji/sprite.png) -54px -216px;width:18px;height:18px} -.SPRITE_2DB{background:no-repeat url(../emoji/sprite.png) -36px -180px;width:18px;height:18px} -.SPRITE_2DC{background:no-repeat url(../emoji/sprite.png) 0 -54px;width:18px;height:18px} -.SPRITE_2DD{background:no-repeat url(../emoji/sprite.png) -18px -72px;width:18px;height:18px} -.SPRITE_2DE{background:no-repeat url(../emoji/sprite.png) -36px -90px;width:18px;height:18px} -.SPRITE_2DF{background:no-repeat url(../emoji/sprite.png) -54px -108px;width:18px;height:18px} -.SPRITE_2E0{background:no-repeat url(../emoji/sprite.png) -18px -198px;width:18px;height:18px} -.SPRITE_2E1{background:no-repeat url(../emoji/sprite.png) 0 -180px;width:18px;height:18px} -.SPRITE_2E2{background:no-repeat url(../emoji/sprite.png) -54px -338px;width:18px;height:18px} -.SPRITE_2E4{background:no-repeat url(../emoji/sprite.png) -54px -198px;width:18px;height:18px} -.SPRITE_2E5{background:no-repeat url(../emoji/sprite.png) 0 -162px;width:18px;height:18px} -.SPRITE_2E6{background:no-repeat url(../emoji/sprite.png) -54px -270px;width:18px;height:18px} -.SPRITE_2E7{background:no-repeat url(../emoji/sprite.png) 0 -108px;width:18px;height:18px} -.SPRITE_2E8{background:no-repeat url(../emoji/sprite.png) 0 -198px;width:18px;height:18px} -.SPRITE_2E9{background:no-repeat url(../emoji/sprite.png) -54px 0;width:18px;height:18px} -.SPRITE_2EA{background:no-repeat url(../emoji/sprite.png) -54px -144px;width:18px;height:18px} -.SPRITE_2EB{background:no-repeat url(../emoji/sprite.png) -18px -36px;width:18px;height:18px} -.SPRITE_2EC{background:no-repeat url(../emoji/sprite.png) -18px -18px;width:18px;height:18px} -.SPRITE_2ED{background:no-repeat url(../emoji/sprite.png) -36px -269px;width:18px;height:18px} -.SPRITE_2EE{background:no-repeat url(../emoji/sprite.png) -18px -90px;width:18px;height:18px} -.SPRITE_2F0{background:no-repeat url(../emoji/sprite.png) 0 0;width:18px;height:18px} -.SPRITE_2F2{background:no-repeat url(../emoji/sprite.png) -54px -234px;width:18px;height:18px} -.SPRITE_2F3{background:no-repeat url(../emoji/sprite.png) 0 -144px;width:18px;height:18px} -.SPRITE_2F4{background:no-repeat url(../emoji/sprite.png) 0 -252px;width:18px;height:17px} -.SPRITE_2F5{background:no-repeat url(../emoji/sprite.png) -54px -321px;width:18px;height:14px} -.SPRITE_2F6{background:no-repeat url(../emoji/sprite.png) -36px -254px;width:18px;height:15px} -.SPRITE_2F7{background:no-repeat url(../emoji/sprite.png) -18px -54px;width:18px;height:18px} -.SPRITE_2F8{background:no-repeat url(../emoji/sprite.png) 0 -216px;width:18px;height:18px} -.SPRITE_2F9{background:no-repeat url(../emoji/sprite.png) -18px -234px;width:18px;height:18px} -.SPRITE_2FA{background:no-repeat url(../emoji/sprite.png) -18px -216px;width:18px;height:18px} -.SPRITE_2FB{background:no-repeat url(../emoji/sprite.png) -36px -216px;width:18px;height:18px} -.SPRITE_2FC{background:no-repeat url(../emoji/sprite.png) -54px -162px;width:18px;height:18px} -.SPRITE_2FD{background:no-repeat url(../emoji/sprite.png) 0 -90px;width:18px;height:18px} -.SPRITE_2FE{background:no-repeat url(../emoji/sprite.png) -54px -305px;width:18px;height:16px} -.SPRITE_2FF{background:no-repeat url(../emoji/sprite.png) -54px -72px;width:18px;height:16px} -.SPRITE_none{background:no-repeat url(../emoji/sprite.png) -54px -180px;width:18px;height:18px} -.SPRITE_unknown{background:no-repeat url(../emoji/sprite.png) -36px -323px;width:14px;height:15px} diff --git a/src/database/third_party/closure-library/closure/goog/demos/css3button.html b/src/database/third_party/closure-library/closure/goog/demos/css3button.html deleted file mode 100644 index 235d303dd8c..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/css3button.html +++ /dev/null @@ -1,166 +0,0 @@ - - - - - - goog.ui.Css3ButtonRenderer Demo - - - - - - - - -

Demo of goog.ui.Css3ButtonRenderer

-
- - These buttons were rendered using - goog.ui.Css3ButtonRenderer: - -
- These buttons were created programmatically:
-
-
- These buttons were created by decorating some DIVs, and they dispatch - state transition events (watch the event log):
-
-
- Decorated Button, yay! -
Decorated Disabled -
Another Button
- Archive -
- Delete -
- Report Spam -
-
-
- Use these ToggleButtons to hide/show and enable/disable - the middle button:
-
Enable
-
Show
-

- Combined toggle buttons
-
- Bold -
- Italics -
- Underlined -
-
-
-
- -
- Event Log -
-
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/css3menubutton.html b/src/database/third_party/closure-library/closure/goog/demos/css3menubutton.html deleted file mode 100644 index 915b9870906..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/css3menubutton.html +++ /dev/null @@ -1,285 +0,0 @@ - - - - - goog.ui.Css3MenuButtonRenderer Demo - - - - - - - - - - - - -

goog.ui.Css3MenuButtonRenderer

- - - - - - - -
-
- - These MenuButtons were created programmatically: -   - - - - - - - - -
- - - Enable first button: - -   - Show second button: - -   -
- -
-
-
- - This MenuButton decorates an element:  - - - - - - - - -
-
- -
- Format - -
-
Bold
-
Italic
-
Underline
-
-
- Strikethrough -
-
-
Font...
-
Color...
-
-
-
- Enable button: - -   - Show button: - -   -
- -
-
-
- -
- Event Log -
-
-
-
-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/cssspriteanimation.html b/src/database/third_party/closure-library/closure/goog/demos/cssspriteanimation.html deleted file mode 100644 index 5d46ab49242..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/cssspriteanimation.html +++ /dev/null @@ -1,80 +0,0 @@ - - - - -CssSpriteAnimation demo - - - - - - -

The following just runs and runs...

-
- -

The animation is just an ordinary animation so you can pause it etc. -

- -

- - -

- -

The animation can be played once by stopping it after it finishes for the -first time. - -

- - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/datepicker.html b/src/database/third_party/closure-library/closure/goog/demos/datepicker.html deleted file mode 100644 index 1e2b8db5950..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/datepicker.html +++ /dev/null @@ -1,311 +0,0 @@ - - - - - - goog.ui.DatePicker - - - - - - -

goog.ui.DatePicker

- - - -
-

Default: ISO 8601

-
-
 
- -

-

Custom

-
-
-
-
-
-
-
-
-
-
-
-
-
 
- -
- -

English (US)

-
-
 
- -

- -

German

-
-
 
- -

- -

Malayalam

-
-
 
- -

- -
- -

Arabic (Yemen)

-
-
 
- -

- -

Thai

-
-
 
- -

- -

Japanese

-
-
 
- -

- -
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/debug.html b/src/database/third_party/closure-library/closure/goog/demos/debug.html deleted file mode 100644 index a291e77ae9c..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/debug.html +++ /dev/null @@ -1,118 +0,0 @@ - - - - -Debug - - - - -Look in the log window for debugging examples. - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/depsgraph.html b/src/database/third_party/closure-library/closure/goog/demos/depsgraph.html deleted file mode 100644 index a1f596204c0..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/depsgraph.html +++ /dev/null @@ -1,220 +0,0 @@ - - - - -Deps Tree - - - - - -

Closure Dependency Graph

- - - -
selected item
-
...is in same file as the selected item
-
...is a dependency of the selected item
-
the selected item is a dependency of...
- - diff --git a/src/database/third_party/closure-library/closure/goog/demos/dialog.html b/src/database/third_party/closure-library/closure/goog/demos/dialog.html deleted file mode 100644 index e1118ef21e2..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/dialog.html +++ /dev/null @@ -1,152 +0,0 @@ - - - - - goog.ui.Dialog - - - - - - - - -

goog.ui.Dialog

-
- - (use "Space" to open dialog with no Iframe, "Enter" to open with Iframe - mask -
-
- -
- -
- - - -
- A sample web page -

- A World Beyond AJAX: Accessing Google's APIs from Flash and - Non-JavaScript Environments -

- Vadim Spivak (Google) - -

- AJAX isn't the only way to access Google APIs. Learn how to use Google's - services from Flash and other non-JavaScript programming environments. - We'll show you how easy it is to augment your site with dynamic search - and feed data from non-JavaScript environments. -

- -

- Participants should be familiar with general web application - development. -

- -

Select Element: - -

- -

- - - - - - -

-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/dimensionpicker.html b/src/database/third_party/closure-library/closure/goog/demos/dimensionpicker.html deleted file mode 100644 index 9146bee82b9..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/dimensionpicker.html +++ /dev/null @@ -1,104 +0,0 @@ - - - - - goog.ui.DimensionPicker - - - - - - - -

goog.ui.DimensionPicker

- - - - - - - -
-
- Demo of the goog.ui.DimensionPicker - component: - -
- -
- -
-
-
-
-
- -
- Event Log -
-
-
-
-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/dimensionpicker_rtl.html b/src/database/third_party/closure-library/closure/goog/demos/dimensionpicker_rtl.html deleted file mode 100644 index 173d4771ba9..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/dimensionpicker_rtl.html +++ /dev/null @@ -1,119 +0,0 @@ - - - - - goog.ui.DimensionPicker - - - - - - - - - -

goog.ui.DimensionPicker

- - - - - - - -
- -
- Event Log -
-
-
-
- Demo of the goog.ui.DimensionPicker - component: - -
-

- -
- -
-
-
-
-
-
-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/dom_selection.html b/src/database/third_party/closure-library/closure/goog/demos/dom_selection.html deleted file mode 100644 index 51cdd7400d1..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/dom_selection.html +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - - - - - - - - - - -
- - - - - - - -
- - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/drag.html b/src/database/third_party/closure-library/closure/goog/demos/drag.html deleted file mode 100644 index 8d4b5499ec4..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/drag.html +++ /dev/null @@ -1,191 +0,0 @@ - - - - goog.fx.Dragger - - - - - - - -

goog.fx.Dragger

-

Demonstrations of the drag utiities.

- -
- -
Drag Me...
-
Drag Me...
-
Drag Me...
- -
-
0
- - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/dragdrop.html b/src/database/third_party/closure-library/closure/goog/demos/dragdrop.html deleted file mode 100644 index 725c8f1da4e..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/dragdrop.html +++ /dev/null @@ -1,263 +0,0 @@ - - - - - goog.fx.DragDrop - - - - - - - -

goog.fx.DragDrop

- -List 1 (combined source/target, can be dropped on list 1, list 2, button 1 or -button 2). -
    -
  • Item 1.1
  • -
  • Item 1.2
  • -
  • Item 1.3
  • -
  • Item 1.4
  • -
  • Item 1.5
  • -
  • Item 1.6
  • -
  • Item 1.7
  • -
  • Item 1.8
  • -
  • Item 1.9
  • -
  • Item 1.10
  • -
  • Item 1.11
  • -
  • Item 1.12
  • -
  • Item 1.13
  • -
  • Item 1.14
  • -
  • Item 1.15
  • -
- -List 2 (source only, can be dropped on list 1 or button 2) -
    -
  • Item 2.1
  • -
  • Item 2.2
  • -
  • Item 2.3
  • -
  • Item 2.4
  • -
  • Item 2.5
  • -
  • Item 2.6
  • -
  • Item 2.7
  • -
  • Item 2.8
  • -
  • Item 2.9
  • -
  • Item 2.10
  • -
  • Item 2.11
  • -
  • Item 2.12
  • -
  • Item 2.13
  • -
  • Item 2.14
  • -
  • Item 2.15
  • -
- -
- Button 1 (combined source/target, can be dropped on list 1) -
- -
- Button 2 (target only) -
- - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/dragdropdetector.html b/src/database/third_party/closure-library/closure/goog/demos/dragdropdetector.html deleted file mode 100644 index 6787c0bc339..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/dragdropdetector.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - - goog.ui.DragDropDetector - - - - - - - -

goog.ui.DragDropDetector

-

Try dropping images from other web pages on this page.

- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/dragdropdetector_target.html b/src/database/third_party/closure-library/closure/goog/demos/dragdropdetector_target.html deleted file mode 100644 index fe09b48ebeb..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/dragdropdetector_target.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/dragger.html b/src/database/third_party/closure-library/closure/goog/demos/dragger.html deleted file mode 100644 index 90eb4d1819b..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/dragger.html +++ /dev/null @@ -1,83 +0,0 @@ - - - - -goog.fx.Dragger - - - - - - - -

goog.fx.Dragger

- -

This demo shows how to use a dragger to capture mouse move events. It tests -that you can drag things outside the window and that alerts ends the dragging. - -

Drag me

-
Status
- -
Drag over me to generate an -alert
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/draglistgroup.html b/src/database/third_party/closure-library/closure/goog/demos/draglistgroup.html deleted file mode 100644 index 7ac57337821..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/draglistgroup.html +++ /dev/null @@ -1,273 +0,0 @@ - - - - - goog.fx.DragListGroup - - - - - - - - -

goog.fx.DragListGroup

-

You can drag any squares into any of the first 4 lists.

-
- -

Horizontal list 1 (grows right):

-
-
1
-
2
-
3
-
4
-
-
- - - - - - - - - -
-

Vertical list 1:

-
-
1
-
2
-
3
-
4
-
-
-

Vertical list 2 (style changes on drag hover):

-
-
1
-
2
-
3
-
4
-
-
-
-

Horizontal list 3 (grows left):

-

Bug: drop position is off by one.

-
-
1
-
2
-
3
-
4
-
-
- -

Horizontal list 5 (grows right, has multiple rows, hysteresis is enabled):

-

Bug: can't drop into the last row.

-
-
11
-
22
-
33
-
44
-
55
-
66
-
77
-
88
-
99
-
-
- -

The items in this list can be moved around with shift-dragging:

-
-
1
-
2
-
3
-
4
-
-
- -

The items have different width:

-

- Bug: the drop positions are off. - For example try moving box 1 a bit to the left. -

-
-
1
-
2
-
3
-
4
-
-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/dragscrollsupport.html b/src/database/third_party/closure-library/closure/goog/demos/dragscrollsupport.html deleted file mode 100644 index 8d54a4da222..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/dragscrollsupport.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - - goog.fx.DragScrollSupport - - - - - - - -

goog.fx.DragScrollSupport

- -List 1 in a scrollable area. -
-
    -
  • Item 1.1 ----------
  • -
  • Item 1.2 ----------
  • -
  • Item 1.3 ----------
  • -
  • Item 1.4 ----------
  • -
  • Item 1.5 ----------
  • -
  • Item 1.6 ----------
  • -
  • Item 1.7 ----------
  • -
  • Item 1.8 ----------
  • -
  • Item 1.9 ----------
  • -
  • Item 1.10 ----------
  • -
  • Item 1.11 ----------
  • -
  • Item 1.12 ----------
  • -
  • Item 1.13 ----------
  • -
  • Item 1.14 ----------
  • -
  • Item 1.15 ----------
  • -
-
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/drilldownrow.html b/src/database/third_party/closure-library/closure/goog/demos/drilldownrow.html deleted file mode 100644 index cc8d87a1c92..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/drilldownrow.html +++ /dev/null @@ -1,78 +0,0 @@ - - - - -Demo of DrilldownRow - - - - - - - - - - - - - - - - -
Column HeadSecond Head
First rowSecond column
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/editor/deps.js b/src/database/third_party/closure-library/closure/goog/demos/editor/deps.js deleted file mode 100644 index 70b09735151..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/editor/deps.js +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2009 The Closure Library Authors. -// All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// This file has been auto-generated by GenJsDeps, please do not edit. - -goog.addDependency('demos/editor/equationeditor.js', ['goog.demos.editor.EquationEditor'], ['goog.ui.equation.EquationEditorDialog']); -goog.addDependency('demos/editor/helloworld.js', ['goog.demos.editor.HelloWorld'], ['goog.dom', 'goog.dom.TagName', 'goog.editor.Plugin']); -goog.addDependency('demos/editor/helloworlddialog.js', ['goog.demos.editor.HelloWorldDialog', 'goog.demos.editor.HelloWorldDialog.OkEvent'], ['goog.dom.TagName', 'goog.events.Event', 'goog.string', 'goog.ui.editor.AbstractDialog', 'goog.ui.editor.AbstractDialog.Builder', 'goog.ui.editor.AbstractDialog.EventType']); -goog.addDependency('demos/editor/helloworlddialogplugin.js', ['goog.demos.editor.HelloWorldDialogPlugin', 'goog.demos.editor.HelloWorldDialogPlugin.Command'], ['goog.demos.editor.HelloWorldDialog', 'goog.dom.TagName', 'goog.editor.plugins.AbstractDialogPlugin', 'goog.editor.range', 'goog.functions', 'goog.ui.editor.AbstractDialog.EventType']); diff --git a/src/database/third_party/closure-library/closure/goog/demos/editor/editor.html b/src/database/third_party/closure-library/closure/goog/demos/editor/editor.html deleted file mode 100644 index 24aba99e12d..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/editor/editor.html +++ /dev/null @@ -1,139 +0,0 @@ - - - - - - goog.editor Demo - - - - - - - - - - - - - - - - - - - - - - - - - - - -

goog.editor Demo

-

This is a demonstration of a editable field, with installed plugins, -hooked up to a toolbar.

-
-
-
-
-

Current field contents - (updates as contents of the editable field above change):
-
- - (Use to set contents of the editable field to the contents of this textarea) -

- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/editor/field_basic.html b/src/database/third_party/closure-library/closure/goog/demos/editor/field_basic.html deleted file mode 100644 index 69a46dc3435..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/editor/field_basic.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - goog.editor.Field - - - - - - -

goog.editor.Field

-

This is a very basic demonstration of how to make a region editable.

- - -

-
I am a regular div. Click "Make Editable" above to transform me into an editable region.
-
-

Current field contents - (updates as contents of the editable field above change):
-
- - (Use to set contents of the editable field to the contents of this textarea) -

- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/editor/helloworld.html b/src/database/third_party/closure-library/closure/goog/demos/editor/helloworld.html deleted file mode 100644 index 6ce5d99b16f..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/editor/helloworld.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - goog.editor Hello World plugins Demo - - - - - - - - -

goog.editor Hello World plugins Demo

-

This is a demonstration of an editable field with the two sample plugins - installed: goog.editor.plugins.HelloWorld and - goog.editor.plugins.HelloWorldDialogPlugin.

-
- -
-
    -
  • Click Hello World to insert "Hello World!".
  • -
  • Click Hello World Dialog to open a dialog where you can customize - your hello world message to be inserted.
  • -
The hello world message will be inserted at the cursor, or will replace - the selected text.
-
-

Current field contents - (updates as contents of the editable field above change):
-
- - (Use to set contents of the editable field to the contents of this textarea) -

- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/editor/helloworld.js b/src/database/third_party/closure-library/closure/goog/demos/editor/helloworld.js deleted file mode 100644 index 4b2f0c7a5ed..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/editor/helloworld.js +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview A simple plugin that inserts 'Hello World!' on command. This - * plugin is intended to be an example of a very simple plugin for plugin - * developers. - * - * @author gak@google.com (Gregory Kick) - * @see helloworld.html - */ - -goog.provide('goog.demos.editor.HelloWorld'); - -goog.require('goog.dom'); -goog.require('goog.dom.TagName'); -goog.require('goog.editor.Plugin'); - - - -/** - * Plugin to insert 'Hello World!' into an editable field. - * @constructor - * @extends {goog.editor.Plugin} - * @final - */ -goog.demos.editor.HelloWorld = function() { - goog.editor.Plugin.call(this); -}; -goog.inherits(goog.demos.editor.HelloWorld, goog.editor.Plugin); - - -/** @override */ -goog.demos.editor.HelloWorld.prototype.getTrogClassId = function() { - return 'HelloWorld'; -}; - - -/** - * Commands implemented by this plugin. - * @enum {string} - */ -goog.demos.editor.HelloWorld.COMMAND = { - HELLO_WORLD: '+helloWorld' -}; - - -/** @override */ -goog.demos.editor.HelloWorld.prototype.isSupportedCommand = function( - command) { - return command == goog.demos.editor.HelloWorld.COMMAND.HELLO_WORLD; -}; - - -/** - * Executes a command. Does not fire any BEFORECHANGE, CHANGE, or - * SELECTIONCHANGE events (these are handled by the super class implementation - * of {@code execCommand}. - * @param {string} command Command to execute. - * @override - * @protected - */ -goog.demos.editor.HelloWorld.prototype.execCommandInternal = function( - command) { - var domHelper = this.getFieldObject().getEditableDomHelper(); - var range = this.getFieldObject().getRange(); - range.removeContents(); - var newNode = - domHelper.createDom(goog.dom.TagName.SPAN, null, 'Hello World!'); - range.insertNode(newNode, false); -}; diff --git a/src/database/third_party/closure-library/closure/goog/demos/editor/helloworld_test.html b/src/database/third_party/closure-library/closure/goog/demos/editor/helloworld_test.html deleted file mode 100644 index f6f83542ff7..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/editor/helloworld_test.html +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - -Closure Unit Tests - goog.demos.editor.HelloWorld - - - - - - - -
 
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/editor/helloworlddialog.js b/src/database/third_party/closure-library/closure/goog/demos/editor/helloworlddialog.js deleted file mode 100644 index 5ab271e1614..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/editor/helloworlddialog.js +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview An example of how to write a dialog to be opened by a plugin. - * - */ - -goog.provide('goog.demos.editor.HelloWorldDialog'); -goog.provide('goog.demos.editor.HelloWorldDialog.OkEvent'); - -goog.require('goog.dom.TagName'); -goog.require('goog.events.Event'); -goog.require('goog.string'); -goog.require('goog.ui.editor.AbstractDialog'); - - -// *** Public interface ***************************************************** // - - - -/** - * Creates a dialog to let the user enter a customized hello world message. - * @param {goog.dom.DomHelper} domHelper DomHelper to be used to create the - * dialog's dom structure. - * @constructor - * @extends {goog.ui.editor.AbstractDialog} - * @final - */ -goog.demos.editor.HelloWorldDialog = function(domHelper) { - goog.ui.editor.AbstractDialog.call(this, domHelper); -}; -goog.inherits(goog.demos.editor.HelloWorldDialog, - goog.ui.editor.AbstractDialog); - - -// *** Event **************************************************************** // - - - -/** - * OK event object for the hello world dialog. - * @param {string} message Customized hello world message chosen by the user. - * @constructor - * @extends {goog.events.Event} - * @final - */ -goog.demos.editor.HelloWorldDialog.OkEvent = function(message) { - this.message = message; -}; -goog.inherits(goog.demos.editor.HelloWorldDialog.OkEvent, goog.events.Event); - - -/** - * Event type. - * @type {goog.ui.editor.AbstractDialog.EventType} - * @override - */ -goog.demos.editor.HelloWorldDialog.OkEvent.prototype.type = - goog.ui.editor.AbstractDialog.EventType.OK; - - -/** - * Customized hello world message chosen by the user. - * @type {string} - */ -goog.demos.editor.HelloWorldDialog.OkEvent.prototype.message; - - -// *** Protected interface ************************************************** // - - -/** @override */ -goog.demos.editor.HelloWorldDialog.prototype.createDialogControl = function() { - var builder = new goog.ui.editor.AbstractDialog.Builder(this); - /** @desc Title of the hello world dialog. */ - var MSG_HELLO_WORLD_DIALOG_TITLE = goog.getMsg('Add a Hello World message'); - builder.setTitle(MSG_HELLO_WORLD_DIALOG_TITLE). - setContent(this.createContent_()); - return builder.build(); -}; - - -/** - * Creates and returns the event object to be used when dispatching the OK - * event to listeners, or returns null to prevent the dialog from closing. - * @param {goog.events.Event} e The event object dispatched by the wrapped - * dialog. - * @return {goog.demos.editor.HelloWorldDialog.OkEvent} The event object to be - * used when dispatching the OK event to listeners. - * @protected - * @override - */ -goog.demos.editor.HelloWorldDialog.prototype.createOkEvent = function(e) { - var message = this.getMessage_(); - if (message && - goog.demos.editor.HelloWorldDialog.isValidHelloWorld_(message)) { - return new goog.demos.editor.HelloWorldDialog.OkEvent(message); - } else { - /** @desc Error message telling the user why their message was rejected. */ - var MSG_HELLO_WORLD_DIALOG_ERROR = - goog.getMsg('Your message must contain the words "hello" and "world".'); - this.dom.getWindow().alert(MSG_HELLO_WORLD_DIALOG_ERROR); - return null; // Prevents the dialog from closing. - } -}; - - -// *** Private implementation *********************************************** // - - -/** - * Input element where the user will type their hello world message. - * @type {Element} - * @private - */ -goog.demos.editor.HelloWorldDialog.prototype.input_; - - -/** - * Creates the DOM structure that makes up the dialog's content area. - * @return {Element} The DOM structure that makes up the dialog's content area. - * @private - */ -goog.demos.editor.HelloWorldDialog.prototype.createContent_ = function() { - /** @desc Sample hello world message to prepopulate the dialog with. */ - var MSG_HELLO_WORLD_DIALOG_SAMPLE = goog.getMsg('Hello, world!'); - this.input_ = this.dom.createDom(goog.dom.TagName.INPUT, - {size: 25, value: MSG_HELLO_WORLD_DIALOG_SAMPLE}); - /** @desc Prompt telling the user to enter a hello world message. */ - var MSG_HELLO_WORLD_DIALOG_PROMPT = - goog.getMsg('Enter your Hello World message'); - return this.dom.createDom(goog.dom.TagName.DIV, - null, - [MSG_HELLO_WORLD_DIALOG_PROMPT, this.input_]); -}; - - -/** - * Returns the hello world message currently typed into the dialog's input. - * @return {?string} The hello world message currently typed into the dialog's - * input, or null if called before the input is created. - * @private - */ -goog.demos.editor.HelloWorldDialog.prototype.getMessage_ = function() { - return this.input_ && this.input_.value; -}; - - -/** - * Returns whether or not the given message contains the strings "hello" and - * "world". Case-insensitive and order doesn't matter. - * @param {string} message The message to be checked. - * @return {boolean} Whether or not the given message contains the strings - * "hello" and "world". - * @private - */ -goog.demos.editor.HelloWorldDialog.isValidHelloWorld_ = function(message) { - message = message.toLowerCase(); - return goog.string.contains(message, 'hello') && - goog.string.contains(message, 'world'); -}; diff --git a/src/database/third_party/closure-library/closure/goog/demos/editor/helloworlddialog_test.html b/src/database/third_party/closure-library/closure/goog/demos/editor/helloworlddialog_test.html deleted file mode 100644 index 8f4d0dfb7d1..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/editor/helloworlddialog_test.html +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - -Closure Unit Tests - goog.demos.editor.HelloWorldDialog - - - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/editor/helloworlddialogplugin.js b/src/database/third_party/closure-library/closure/goog/demos/editor/helloworlddialogplugin.js deleted file mode 100644 index 56a65b67ad0..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/editor/helloworlddialogplugin.js +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview An example of how to write a dialog plugin. - * - */ - -goog.provide('goog.demos.editor.HelloWorldDialogPlugin'); -goog.provide('goog.demos.editor.HelloWorldDialogPlugin.Command'); - -goog.require('goog.demos.editor.HelloWorldDialog'); -goog.require('goog.dom.TagName'); -goog.require('goog.editor.plugins.AbstractDialogPlugin'); -goog.require('goog.editor.range'); -goog.require('goog.functions'); -goog.require('goog.ui.editor.AbstractDialog'); - - -// *** Public interface ***************************************************** // - - - -/** - * A plugin that opens the hello world dialog. - * @constructor - * @extends {goog.editor.plugins.AbstractDialogPlugin} - * @final - */ -goog.demos.editor.HelloWorldDialogPlugin = function() { - goog.editor.plugins.AbstractDialogPlugin.call(this, - goog.demos.editor.HelloWorldDialogPlugin.Command.HELLO_WORLD_DIALOG); -}; -goog.inherits(goog.demos.editor.HelloWorldDialogPlugin, - goog.editor.plugins.AbstractDialogPlugin); - - -/** - * Commands implemented by this plugin. - * @enum {string} - */ -goog.demos.editor.HelloWorldDialogPlugin.Command = { - HELLO_WORLD_DIALOG: 'helloWorldDialog' -}; - - -/** @override */ -goog.demos.editor.HelloWorldDialogPlugin.prototype.getTrogClassId = - goog.functions.constant('HelloWorldDialog'); - - -// *** Protected interface ************************************************** // - - -/** - * Creates a new instance of the dialog and registers for the relevant events. - * @param {goog.dom.DomHelper} dialogDomHelper The dom helper to be used to - * create the dialog. - * @return {goog.demos.editor.HelloWorldDialog} The dialog. - * @override - * @protected - */ -goog.demos.editor.HelloWorldDialogPlugin.prototype.createDialog = function( - dialogDomHelper) { - var dialog = new goog.demos.editor.HelloWorldDialog(dialogDomHelper); - dialog.addEventListener(goog.ui.editor.AbstractDialog.EventType.OK, - this.handleOk_, - false, - this); - return dialog; -}; - - -// *** Private implementation *********************************************** // - - -/** - * Handles the OK event from the dialog by inserting the hello world message - * into the field. - * @param {goog.demos.editor.HelloWorldDialog.OkEvent} e OK event object. - * @private - */ -goog.demos.editor.HelloWorldDialogPlugin.prototype.handleOk_ = function(e) { - // First restore the selection so we can manipulate the field's content - // according to what was selected. - this.restoreOriginalSelection(); - - // Notify listeners that the field's contents are about to change. - this.getFieldObject().dispatchBeforeChange(); - - // Now we can clear out what was previously selected (if anything). - var range = this.getFieldObject().getRange(); - range.removeContents(); - // And replace it with a span containing our hello world message. - var createdNode = this.getFieldDomHelper().createDom(goog.dom.TagName.SPAN, - null, - e.message); - createdNode = range.insertNode(createdNode, false); - // Place the cursor at the end of the new text node (false == to the right). - goog.editor.range.placeCursorNextTo(createdNode, false); - - // Notify listeners that the field's selection has changed. - this.getFieldObject().dispatchSelectionChangeEvent(); - // Notify listeners that the field's contents have changed. - this.getFieldObject().dispatchChange(); -}; diff --git a/src/database/third_party/closure-library/closure/goog/demos/editor/helloworlddialogplugin_test.html b/src/database/third_party/closure-library/closure/goog/demos/editor/helloworlddialogplugin_test.html deleted file mode 100644 index 3bcb29c1ac4..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/editor/helloworlddialogplugin_test.html +++ /dev/null @@ -1,198 +0,0 @@ - - - - - - -Closure Unit Tests - goog.demos.editor.HelloWorldDialogPlugin - - - - - - - -
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/editor/seamlessfield.html b/src/database/third_party/closure-library/closure/goog/demos/editor/seamlessfield.html deleted file mode 100644 index 64265dfd142..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/editor/seamlessfield.html +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - goog.editor.SeamlessField - - - - - - -

goog.editor.SeamlessField

-

This is a very basic demonstration of how to make a region editable, that - blends in with the surrounding page, even if the editable content is inside - an iframe.

- - -
-
-

-
I am a regular div. - Click "Make Editable" above to transform me into an editable region. - I'll grow and shrink with my content! - And I'll inherit styles from the parent document. - -

Heading styled by outer document.

-
    -
  1. And lists too! One!
  2. -
  3. Two!
  4. -
-

Paragraph 1

-
-

Inherited CSS works!

-
-
-

-
-
-

Current field contents - (updates as contents of the editable field above change):
-
- - (Use to set contents of the editable field to the contents of this textarea) -

- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/editor/tableeditor.html b/src/database/third_party/closure-library/closure/goog/demos/editor/tableeditor.html deleted file mode 100644 index 2eedbd56f2c..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/editor/tableeditor.html +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - goog.editor.plugins.TableEditor Demo - - - - - - - - - - - - - - - - - - - - -

goog.editor.plugins.TableEditor Demo

-

This is a demonstration of the table editor plugin for goog.editor.

-
-
-
-
-

Current field contents - (updates as contents of the editable field above change):
-
- - (Use to set contents of the editable field to the contents of this textarea) -

- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/effects.html b/src/database/third_party/closure-library/closure/goog/demos/effects.html deleted file mode 100644 index a9de5fee682..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/effects.html +++ /dev/null @@ -1,162 +0,0 @@ - - - - - goog.fx.dom - - - - - - -

goog.fx.dom

-

Demonstrations of the goog.fx.dom library

- -

-
-
-
- -

- -

-
-
-
-
- -

- -

-
- -

- -

-
-
-
- -

- -

- -

- - -

- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/200.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/200.gif deleted file mode 100644 index 6245f6968ce..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/200.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/201.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/201.gif deleted file mode 100644 index b740d39de4d..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/201.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/202.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/202.gif deleted file mode 100644 index 2bc9be6927d..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/202.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/203.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/203.gif deleted file mode 100644 index 1ce3f561442..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/203.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/204.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/204.gif deleted file mode 100644 index 2166ce8b3d0..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/204.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/205.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/205.gif deleted file mode 100644 index 363e045b336..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/205.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/206.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/206.gif deleted file mode 100644 index 5b95f4457ae..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/206.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2BC.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2BC.gif deleted file mode 100644 index aecbdc0d391..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2BC.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2BD.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2BD.gif deleted file mode 100644 index 0b352dd629e..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2BD.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2BE.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2BE.gif deleted file mode 100644 index 282c361d38d..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2BE.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2BF.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2BF.gif deleted file mode 100644 index 5b88ee7ea48..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2BF.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2C0.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2C0.gif deleted file mode 100644 index 17fa1a39ac7..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2C0.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2C1.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2C1.gif deleted file mode 100644 index a1f294a41cd..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2C1.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2C2.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2C2.gif deleted file mode 100644 index 01dadbeaf48..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2C2.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2C3.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2C3.gif deleted file mode 100644 index 69a6126957a..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2C3.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2C4.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2C4.gif deleted file mode 100644 index 224527b6a97..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2C4.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2C5.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2C5.gif deleted file mode 100644 index 2fe94b359ba..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2C5.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2C6.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2C6.gif deleted file mode 100644 index 8b1e7318d4c..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2C6.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2C7.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2C7.gif deleted file mode 100644 index 3d7c63a78b4..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2C7.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2C8.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2C8.gif deleted file mode 100644 index cb44d16dfb6..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2C8.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2C9.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2C9.gif deleted file mode 100644 index 69fe427b006..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2C9.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2CA.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2CA.gif deleted file mode 100644 index cba4c24ab0d..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2CA.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2CB.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2CB.gif deleted file mode 100644 index c1f035e14fb..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2CB.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2CC.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2CC.gif deleted file mode 100644 index bd757fab902..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2CC.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2CD.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2CD.gif deleted file mode 100644 index f42f5a15161..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2CD.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2CE.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2CE.gif deleted file mode 100644 index 3f6eff355e1..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2CE.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2CF.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2CF.gif deleted file mode 100644 index 2f7d40750ac..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2CF.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2D0.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2D0.gif deleted file mode 100644 index 37da48e468f..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2D0.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2D1.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2D1.gif deleted file mode 100644 index 2bc951d30a9..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2D1.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2D2.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2D2.gif deleted file mode 100644 index a7c50dbfb6b..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2D2.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2D3.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2D3.gif deleted file mode 100644 index 22ceddf19d1..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2D3.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2D4.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2D4.gif deleted file mode 100644 index 8e996524f5a..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2D4.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2D5.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2D5.gif deleted file mode 100644 index 4837a48f67f..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2D5.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2D6.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2D6.gif deleted file mode 100644 index bd7230fdf4c..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2D6.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2D7.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2D7.gif deleted file mode 100644 index 880829fe556..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2D7.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2D8.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2D8.gif deleted file mode 100644 index 7d727db91fb..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2D8.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2D9.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2D9.gif deleted file mode 100644 index 98a0fa20577..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2D9.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2DA.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2DA.gif deleted file mode 100644 index c8318163094..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2DA.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2DB.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2DB.gif deleted file mode 100644 index 301c931a9ef..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2DB.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2DC.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2DC.gif deleted file mode 100644 index 27ab40852b4..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2DC.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2DD.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2DD.gif deleted file mode 100644 index b5e6edfb16e..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2DD.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2DE.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2DE.gif deleted file mode 100644 index b9a7272dd85..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2DE.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2DF.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2DF.gif deleted file mode 100644 index 89fa1866630..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2DF.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2E0.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2E0.gif deleted file mode 100644 index 7fd754ab163..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2E0.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2E1.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2E1.gif deleted file mode 100644 index 6926e4e8723..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2E1.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2E2.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2E2.gif deleted file mode 100644 index 1718dae3ad7..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2E2.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2E3.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2E3.gif deleted file mode 100644 index 4f23b2b8f2d..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2E3.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2E4.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2E4.gif deleted file mode 100644 index ab2c9eb105b..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2E4.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2E5.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2E5.gif deleted file mode 100644 index ff8f45b5fa8..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2E5.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2E6.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2E6.gif deleted file mode 100644 index 56e75e8c51e..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2E6.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2E7.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2E7.gif deleted file mode 100644 index 157042d3479..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2E7.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2E8.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2E8.gif deleted file mode 100644 index 1eb1cc90a57..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2E8.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2E9.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2E9.gif deleted file mode 100644 index 5b9814905d4..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2E9.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2EA.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2EA.gif deleted file mode 100644 index 40d60a6dbe2..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2EA.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2EB.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2EB.gif deleted file mode 100644 index 8e2ca7d81b4..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2EB.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2EC.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2EC.gif deleted file mode 100644 index 884e2267a27..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2EC.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2ED.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2ED.gif deleted file mode 100644 index b50ba968ac0..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2ED.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2EE.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2EE.gif deleted file mode 100644 index a96fbd1bec4..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2EE.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2EF.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2EF.gif deleted file mode 100644 index 13a0d2b80c7..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2EF.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2F0.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2F0.gif deleted file mode 100644 index 1538221f7db..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2F0.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2F1.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2F1.gif deleted file mode 100644 index d04c68d0f14..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2F1.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2F2.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2F2.gif deleted file mode 100644 index 402dfce7324..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2F2.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2F3.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2F3.gif deleted file mode 100644 index 250271e3119..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2F3.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2F4.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2F4.gif deleted file mode 100644 index dec31af04f3..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2F4.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2F5.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2F5.gif deleted file mode 100644 index bed6e719167..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2F5.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2F6.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2F6.gif deleted file mode 100644 index e9b885f773f..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2F6.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2F7.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2F7.gif deleted file mode 100644 index 5bdcb643277..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2F7.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2F8.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2F8.gif deleted file mode 100644 index 629016b2bf2..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2F8.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2F9.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2F9.gif deleted file mode 100644 index f8b41da66e0..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2F9.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2FA.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2FA.gif deleted file mode 100644 index 0a4a5b3bd75..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2FA.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2FB.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2FB.gif deleted file mode 100644 index 620d898f844..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2FB.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2FC.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2FC.gif deleted file mode 100644 index 2171097d5f9..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2FC.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2FD.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2FD.gif deleted file mode 100644 index c6bcdb49ebe..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2FD.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2FE.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2FE.gif deleted file mode 100644 index a8888c57ca9..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2FE.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/2FF.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/2FF.gif deleted file mode 100644 index 6022c4ca60c..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/2FF.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/none.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/none.gif deleted file mode 100644 index 8e1f90ede58..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/none.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/sprite.png b/src/database/third_party/closure-library/closure/goog/demos/emoji/sprite.png deleted file mode 100644 index f16efa97584..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/sprite.png and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/sprite2.png b/src/database/third_party/closure-library/closure/goog/demos/emoji/sprite2.png deleted file mode 100644 index 399d5244dc4..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/sprite2.png and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/emoji/unknown.gif b/src/database/third_party/closure-library/closure/goog/demos/emoji/unknown.gif deleted file mode 100644 index 7f0b80459c6..00000000000 Binary files a/src/database/third_party/closure-library/closure/goog/demos/emoji/unknown.gif and /dev/null differ diff --git a/src/database/third_party/closure-library/closure/goog/demos/event-propagation.html b/src/database/third_party/closure-library/closure/goog/demos/event-propagation.html deleted file mode 100644 index 47eac153afa..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/event-propagation.html +++ /dev/null @@ -1,192 +0,0 @@ - - - - -goog.events - - - - - - - -

goog.events - Stop Propagation

-

Test the cancelling of capture and bubbling events. Click - one of the nodes to see the event trace, then use the check boxes to cancel the - capture or bubble at a given branch. - (Double click the text area to clear it)

- -
- -
- - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/events.html b/src/database/third_party/closure-library/closure/goog/demos/events.html deleted file mode 100644 index 314260db709..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/events.html +++ /dev/null @@ -1,94 +0,0 @@ - - - - Event Test - - - - -

- Link 1
- Link 2
- Link 3
- Link 4 -

-

- Listen | - UnListen | - Remove One | - Remove Two | - Remove Three | -

-

-
-  
- Test 1 -
-     Test 2 -
-         Test 3 -
-     Test 2 -
- Test 1 -
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/eventtarget.html b/src/database/third_party/closure-library/closure/goog/demos/eventtarget.html deleted file mode 100644 index b26250e385a..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/eventtarget.html +++ /dev/null @@ -1,70 +0,0 @@ - - - - Event Test - - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/filedrophandler.html b/src/database/third_party/closure-library/closure/goog/demos/filedrophandler.html deleted file mode 100644 index 1c14928e7df..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/filedrophandler.html +++ /dev/null @@ -1,65 +0,0 @@ - - - - - goog.events.FileDropHandler Demo - - - - - -

Demo of goog.events.FileDropHandler

- -
- Demo of the goog.events.FileDropHandler: - - -
- -
- Event Log -
-
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/filteredmenu.html b/src/database/third_party/closure-library/closure/goog/demos/filteredmenu.html deleted file mode 100644 index b07a58b946a..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/filteredmenu.html +++ /dev/null @@ -1,118 +0,0 @@ - - - - -goog.ui.FilteredMenu - - - - - - - - - - - - - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/focushandler.html b/src/database/third_party/closure-library/closure/goog/demos/focushandler.html deleted file mode 100644 index b29bc100bfc..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/focushandler.html +++ /dev/null @@ -1,58 +0,0 @@ - - - - -goog.events.FocusHandler - - - - - -

goog.events.FocusHandler

-

i1: - - -

i2 - - -

i3: - -

- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/fpsdisplay.html b/src/database/third_party/closure-library/closure/goog/demos/fpsdisplay.html deleted file mode 100644 index 65f9c5015ce..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/fpsdisplay.html +++ /dev/null @@ -1,50 +0,0 @@ - - - - -FPS Display - - - - -

- - - -
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/fx/css3/transition.html b/src/database/third_party/closure-library/closure/goog/demos/fx/css3/transition.html deleted file mode 100644 index 30d70c0cd24..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/fx/css3/transition.html +++ /dev/null @@ -1,223 +0,0 @@ - - - - - -Closure: CSS3 Transition Demo - - - - - - - - -
-
-
- CSS3 transition choices -
-
-
-
-
-
-
-
- -
- - -
-
-
-
-
-
Hi there!
-
- - -
- Event log for the transition object -
-
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/gauge.html b/src/database/third_party/closure-library/closure/goog/demos/gauge.html deleted file mode 100644 index cc7ac08fc3e..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/gauge.html +++ /dev/null @@ -1,158 +0,0 @@ - - - - - goog.ui.Gauge - - - - - - - - - -

goog.ui.Gauge

-

Note: This component requires vector graphics support

- - - - - - - - - - - - - -
- Basic - - Background colors, title. custom ticks - - Value change, formatted value, tick labels - - Custom colors -
- - - - - -
- - -
-
- -
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/graphics/advancedcoordinates.html b/src/database/third_party/closure-library/closure/goog/demos/graphics/advancedcoordinates.html deleted file mode 100644 index 6274fda2175..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/graphics/advancedcoordinates.html +++ /dev/null @@ -1,141 +0,0 @@ - - - - - Graphics Advanced Coordinates Demo Page - - - - - - - -
-

- W: - H: - R: -

- -

The front ellipse is sized based on absolute units. The back ellipse is - sized based on percentage of the parent.

- -
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/graphics/advancedcoordinates2.html b/src/database/third_party/closure-library/closure/goog/demos/graphics/advancedcoordinates2.html deleted file mode 100644 index f05323fe039..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/graphics/advancedcoordinates2.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - - Graphics Advanced Coordinates Demo Page - - Using Percentage Based Surface Size - - - - - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/graphics/basicelements.html b/src/database/third_party/closure-library/closure/goog/demos/graphics/basicelements.html deleted file mode 100644 index d55645af1c6..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/graphics/basicelements.html +++ /dev/null @@ -1,264 +0,0 @@ - - - - - - Graphics Basic Elements Demo Page - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Text: fonts, alignment, vertical-alignment, direction - - Basic shapes: Rectangle, Circle, Ellipses, Path, Clip to canvas -
- - - -
- Paths: Lines, arcs, curves - - Colors: solid, gradients, transparency -
- - - -
- Coordinate scaling + stroke types -
- -
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/graphics/events.html b/src/database/third_party/closure-library/closure/goog/demos/graphics/events.html deleted file mode 100644 index 40abb31073c..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/graphics/events.html +++ /dev/null @@ -1,114 +0,0 @@ - - - - - Graphics Basic events Demo Page - - - - - - - - -
- -
- -
- -
- -

- Clear Log -

- -
- -

Try to mouse over, mouse out, or click the ellipse and the group of - circles. The ellipse will be disposed in 10 sec. -

- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/graphics/modifyelements.html b/src/database/third_party/closure-library/closure/goog/demos/graphics/modifyelements.html deleted file mode 100644 index 1d21c583ba6..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/graphics/modifyelements.html +++ /dev/null @@ -1,195 +0,0 @@ - - - - - - Modifing Graphic Elements Demo - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Colors (stroke/fill): - - - - - -
Rectangle position: - - - -
Rectangle size: - - - -
Ellipse center: - - - -
Ellipse radius: - - - -
Path: - - -
Text: - -
- - -
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/graphics/subpixel.html b/src/database/third_party/closure-library/closure/goog/demos/graphics/subpixel.html deleted file mode 100644 index 947eae28204..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/graphics/subpixel.html +++ /dev/null @@ -1,80 +0,0 @@ - - - - -Sub pixel rendering - - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/graphics/tiger.html b/src/database/third_party/closure-library/closure/goog/demos/graphics/tiger.html deleted file mode 100644 index 64deebcdde2..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/graphics/tiger.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - -The SVG tiger drawn with goog.graphics - - - - - - - -
-
-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/graphics/tigerdata.js b/src/database/third_party/closure-library/closure/goog/demos/graphics/tigerdata.js deleted file mode 100644 index 633c55cfa6c..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/graphics/tigerdata.js +++ /dev/null @@ -1,2841 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview This data is generated from an SVG image of a tiger. - * - * @author arv@google.com (Erik Arvidsson) - */ - - -var tigerData = [{f: '#fff', s: {c: '#000', w: 0.172}, - p: [{t: 'M', p: [77.696, 284.285]}, - {t: 'C', p: [77.696, 284.285, 77.797, 286.179, 76.973, 286.16]}, - {t: 'C', p: [76.149, 286.141, 59.695, 238.066, 39.167, 240.309]}, - {t: 'C', p: [39.167, 240.309, 56.95, 232.956, 77.696, 284.285]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.172}, - p: [{t: 'M', p: [81.226, 281.262]}, - {t: 'C', p: [81.226, 281.262, 80.677, 283.078, 79.908, 282.779]}, - {t: 'C', p: [79.14, 282.481, 80.023, 231.675, 59.957, 226.801]}, - {t: 'C', p: [59.957, 226.801, 79.18, 225.937, 81.226, 281.262]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.172}, - p: [{t: 'M', p: [108.716, 323.59]}, - {t: 'C', p: [108.716, 323.59, 110.352, 324.55, 109.882, 325.227]}, - {t: 'C', p: [109.411, 325.904, 60.237, 313.102, 50.782, 331.459]}, - {t: 'C', p: [50.782, 331.459, 54.461, 312.572, 108.716, 323.59]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.172}, - p: [{t: 'M', p: [105.907, 333.801]}, - {t: 'C', p: [105.907, 333.801, 107.763, 334.197, 107.529, 334.988]}, - {t: 'C', p: [107.296, 335.779, 56.593, 339.121, 53.403, 359.522]}, - {t: 'C', p: [53.403, 359.522, 50.945, 340.437, 105.907, 333.801]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.172}, - p: [{t: 'M', p: [101.696, 328.276]}, - {t: 'C', p: [101.696, 328.276, 103.474, 328.939, 103.128, 329.687]}, - {t: 'C', p: [102.782, 330.435, 52.134, 326.346, 46.002, 346.064]}, - {t: 'C', p: [46.002, 346.064, 46.354, 326.825, 101.696, 328.276]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.172}, - p: [{t: 'M', p: [90.991, 310.072]}, - {t: 'C', p: [90.991, 310.072, 92.299, 311.446, 91.66, 311.967]}, - {t: 'C', p: [91.021, 312.488, 47.278, 286.634, 33.131, 301.676]}, - {t: 'C', p: [33.131, 301.676, 41.872, 284.533, 90.991, 310.072]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.172}, - p: [{t: 'M', p: [83.446, 314.263]}, - {t: 'C', p: [83.446, 314.263, 84.902, 315.48, 84.326, 316.071]}, - {t: 'C', p: [83.75, 316.661, 37.362, 295.922, 25.008, 312.469]}, - {t: 'C', p: [25.008, 312.469, 31.753, 294.447, 83.446, 314.263]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.172}, - p: [{t: 'M', p: [80.846, 318.335]}, - {t: 'C', p: [80.846, 318.335, 82.454, 319.343, 81.964, 320.006]}, - {t: 'C', p: [81.474, 320.669, 32.692, 306.446, 22.709, 324.522]}, - {t: 'C', p: [22.709, 324.522, 26.934, 305.749, 80.846, 318.335]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.172}, - p: [{t: 'M', p: [91.58, 318.949]}, - {t: 'C', p: [91.58, 318.949, 92.702, 320.48, 92.001, 320.915]}, - {t: 'C', p: [91.3, 321.35, 51.231, 290.102, 35.273, 303.207]}, - {t: 'C', p: [35.273, 303.207, 46.138, 287.326, 91.58, 318.949]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.172}, - p: [{t: 'M', p: [71.8, 290]}, - {t: 'C', p: [71.8, 290, 72.4, 291.8, 71.6, 292]}, - {t: 'C', p: [70.8, 292.2, 42.2, 250.2, 22.999, 257.8]}, - {t: 'C', p: [22.999, 257.8, 38.2, 246, 71.8, 290]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.172}, - p: [{t: 'M', p: [72.495, 296.979]}, - {t: 'C', p: [72.495, 296.979, 73.47, 298.608, 72.731, 298.975]}, - {t: 'C', p: [71.993, 299.343, 35.008, 264.499, 17.899, 276.061]}, - {t: 'C', p: [17.899, 276.061, 30.196, 261.261, 72.495, 296.979]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.172}, - p: [{t: 'M', p: [72.38, 301.349]}, - {t: 'C', p: [72.38, 301.349, 73.502, 302.88, 72.801, 303.315]}, - {t: 'C', p: [72.1, 303.749, 32.031, 272.502, 16.073, 285.607]}, - {t: 'C', p: [16.073, 285.607, 26.938, 269.726, 72.38, 301.349]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: '#000', p: [{t: 'M', p: [70.17, 303.065]}, - {t: 'C', p: [70.673, 309.113, 71.661, 315.682, 73.4, 318.801]}, - {t: 'C', p: [73.4, 318.801, 69.8, 331.201, 78.6, 344.401]}, - {t: 'C', p: [78.6, 344.401, 78.2, 351.601, 79.8, 354.801]}, - {t: 'C', p: [79.8, 354.801, 83.8, 363.201, 88.6, 364.001]}, - {t: 'C', p: [92.484, 364.648, 101.207, 367.717, 111.068, 369.121]}, - {t: 'C', p: [111.068, 369.121, 128.2, 383.201, 125, 396.001]}, - {t: 'C', p: [125, 396.001, 124.6, 412.401, 121, 414.001]}, - {t: 'C', p: [121, 414.001, 132.6, 402.801, 123, 419.601]}, - {t: 'L', p: [118.6, 438.401]}, - {t: 'C', p: [118.6, 438.401, 144.2, 416.801, 128.6, 435.201]}, - {t: 'L', p: [118.6, 461.201]}, - {t: 'C', p: [118.6, 461.201, 138.2, 442.801, 131, 451.201]}, - {t: 'L', p: [127.8, 460.001]}, - {t: 'C', p: [127.8, 460.001, 171, 432.801, 140.2, 462.401]}, - {t: 'C', p: [140.2, 462.401, 148.2, 458.801, 152.6, 461.601]}, - {t: 'C', p: [152.6, 461.601, 159.4, 460.401, 158.6, 462.001]}, - {t: 'C', p: [158.6, 462.001, 137.8, 472.401, 134.2, 490.801]}, - {t: 'C', p: [134.2, 490.801, 142.6, 480.801, 139.4, 491.601]}, - {t: 'L', p: [139.8, 503.201]}, - {t: 'C', p: [139.8, 503.201, 143.8, 481.601, 143.4, 519.201]}, - {t: 'C', p: [143.4, 519.201, 162.6, 501.201, 151, 522.001]}, - {t: 'L', p: [151, 538.801]}, - {t: 'C', p: [151, 538.801, 166.2, 522.401, 159.8, 535.201]}, - {t: 'C', p: [159.8, 535.201, 169.8, 526.401, 165.8, 541.601]}, - {t: 'C', p: [165.8, 541.601, 165, 552.001, 169.4, 540.801]}, - {t: 'C', p: [169.4, 540.801, 185.4, 510.201, 179.4, 536.401]}, - {t: 'C', p: [179.4, 536.401, 178.6, 555.601, 183.4, 540.801]}, - {t: 'C', p: [183.4, 540.801, 183.8, 551.201, 193, 558.401]}, - {t: 'C', p: [193, 558.401, 191.8, 507.601, 204.6, 543.601]}, - {t: 'L', p: [208.6, 560.001]}, - {t: 'C', p: [208.6, 560.001, 211.4, 550.801, 211, 545.601]}, - {t: 'C', p: [211, 545.601, 225.8, 529.201, 219, 553.601]}, - {t: 'C', p: [219, 553.601, 234.2, 530.801, 231, 544.001]}, - {t: 'C', p: [231, 544.001, 223.4, 560.001, 225, 564.801]}, - {t: 'C', p: [225, 564.801, 241.8, 530.001, 243, 528.401]}, - {t: 'C', p: [243, 528.401, 241, 570.802, 251.8, 534.801]}, - {t: 'C', p: [251.8, 534.801, 257.4, 546.801, 254.6, 551.201]}, - {t: 'C', p: [254.6, 551.201, 262.6, 543.201, 261.8, 540.001]}, - {t: 'C', p: [261.8, 540.001, 266.4, 531.801, 269.2, 545.401]}, - {t: 'C', p: [269.2, 545.401, 271, 554.801, 272.6, 551.601]}, - {t: 'C', p: [272.6, 551.601, 276.6, 575.602, 277.8, 552.801]}, - {t: 'C', p: [277.8, 552.801, 279.4, 539.201, 272.2, 527.601]}, - {t: 'C', p: [272.2, 527.601, 273, 524.401, 270.2, 520.401]}, - {t: 'C', p: [270.2, 520.401, 283.8, 542.001, 276.6, 513.201]}, - {t: 'C', p: [276.6, 513.201, 287.801, 521.201, 289.001, 521.201]}, - {t: 'C', p: [289.001, 521.201, 275.4, 498.001, 284.2, 502.801]}, - {t: 'C', p: [284.2, 502.801, 279, 492.401, 297.001, 504.401]}, - {t: 'C', p: [297.001, 504.401, 281, 488.401, 298.601, 498.001]}, - {t: 'C', p: [298.601, 498.001, 306.601, 504.401, 299.001, 494.401]}, - {t: 'C', p: [299.001, 494.401, 284.6, 478.401, 306.601, 496.401]}, - {t: 'C', p: [306.601, 496.401, 318.201, 512.801, 319.001, 515.601]}, - {t: 'C', p: [319.001, 515.601, 309.001, 486.401, 304.601, 483.601]}, - {t: 'C', p: [304.601, 483.601, 313.001, 447.201, 354.201, 462.801]}, - {t: 'C', p: [354.201, 462.801, 361.001, 480.001, 365.401, 461.601]}, - {t: 'C', p: [365.401, 461.601, 378.201, 455.201, 389.401, 482.801]}, - {t: 'C', p: [389.401, 482.801, 393.401, 469.201, 392.601, 466.401]}, - {t: 'C', p: [392.601, 466.401, 399.401, 467.601, 398.601, 466.401]}, - {t: 'C', p: [398.601, 466.401, 411.801, 470.801, 413.001, 470.001]}, - {t: 'C', p: [413.001, 470.001, 419.801, 476.801, 420.201, 473.201]}, - {t: 'C', p: [420.201, 473.201, 429.401, 476.001, 427.401, 472.401]}, - {t: 'C', p: [427.401, 472.401, 436.201, 488.001, 436.601, 491.601]}, - {t: 'L', p: [439.001, 477.601]}, - {t: 'L', p: [441.001, 480.401]}, - {t: 'C', p: [441.001, 480.401, 442.601, 472.801, 441.801, 471.601]}, - {t: 'C', p: [441.001, 470.401, 461.801, 478.401, 466.601, 499.201]}, - {t: 'L', p: [468.601, 507.601]}, - {t: 'C', p: [468.601, 507.601, 474.601, 492.801, 473.001, 488.801]}, - {t: 'C', p: [473.001, 488.801, 478.201, 489.601, 478.601, 494.001]}, - {t: 'C', p: [478.601, 494.001, 482.601, 470.801, 477.801, 464.801]}, - {t: 'C', p: [477.801, 464.801, 482.201, 464.001, 483.401, 467.601]}, - {t: 'L', p: [483.401, 460.401]}, - {t: 'C', p: [483.401, 460.401, 490.601, 461.201, 490.601, 458.801]}, - {t: 'C', p: [490.601, 458.801, 495.001, 454.801, 497.001, 459.601]}, - {t: 'C', p: [497.001, 459.601, 484.601, 424.401, 503.001, 443.601]}, - {t: 'C', p: [503.001, 443.601, 510.201, 454.401, 506.601, 435.601]}, - {t: 'C', p: [503.001, 416.801, 499.001, 415.201, 503.801, 414.801]}, - {t: 'C', p: [503.801, 414.801, 504.601, 411.201, 502.601, 409.601]}, - {t: 'C', p: [500.601, 408.001, 503.801, 409.601, 503.801, 409.601]}, - {t: 'C', p: [503.801, 409.601, 508.601, 413.601, 503.401, 391.601]}, - {t: 'C', p: [503.401, 391.601, 509.801, 393.201, 497.801, 364.001]}, - {t: 'C', p: [497.801, 364.001, 500.601, 361.601, 496.601, 353.201]}, - {t: 'C', p: [496.601, 353.201, 504.601, 357.601, 507.401, 356.001]}, - {t: 'C', p: [507.401, 356.001, 507.001, 354.401, 503.801, 350.401]}, - {t: 'C', p: [503.801, 350.401, 482.201, 295.6, 502.601, 317.601]}, - {t: 'C', p: [502.601, 317.601, 514.451, 331.151, 508.051, 308.351]}, - {t: 'C', p: [508.051, 308.351, 498.94, 284.341, 499.717, 280.045]}, - {t: 'L', p: [70.17, 303.065]}, - {t: 'z', p: []}]}, - -{f: '#cc7226', s: '#000', p: [{t: 'M', p: [499.717, 280.245]}, - {t: 'C', p: [500.345, 280.426, 502.551, 281.55, 503.801, 283.2]}, - {t: 'C', p: [503.801, 283.2, 510.601, 294, 505.401, 275.6]}, - {t: 'C', p: [505.401, 275.6, 496.201, 246.8, 505.001, 258]}, - {t: 'C', p: [505.001, 258, 511.001, 265.2, 507.801, 251.6]}, - {t: 'C', p: [503.936, 235.173, 501.401, 228.8, 501.401, 228.8]}, - {t: 'C', p: [501.401, 228.8, 513.001, 233.6, 486.201, 194]}, - {t: 'L', p: [495.001, 197.6]}, - {t: 'C', p: [495.001, 197.6, 475.401, 158, 453.801, 152.8]}, - {t: 'L', p: [445.801, 146.8]}, - {t: 'C', p: [445.801, 146.8, 484.201, 108.8, 471.401, 72]}, - {t: 'C', p: [471.401, 72, 464.601, 66.8, 455.001, 76]}, - {t: 'C', p: [455.001, 76, 448.601, 80.8, 442.601, 79.2]}, - {t: 'C', p: [442.601, 79.2, 411.801, 80.4, 409.801, 80.4]}, - {t: 'C', p: [407.801, 80.4, 373.001, 43.2, 307.401, 60.8]}, - {t: 'C', p: [307.401, 60.8, 302.201, 62.8, 297.801, 61.6]}, - {t: 'C', p: [297.801, 61.6, 279.4, 45.6, 230.6, 68.4]}, - {t: 'C', p: [230.6, 68.4, 220.6, 70.4, 219, 70.4]}, - {t: 'C', p: [217.4, 70.4, 214.6, 70.4, 206.6, 76.8]}, - {t: 'C', p: [198.6, 83.2, 198.2, 84, 196.2, 85.6]}, - {t: 'C', p: [196.2, 85.6, 179.8, 96.8, 175, 97.6]}, - {t: 'C', p: [175, 97.6, 163.4, 104, 159, 114]}, - {t: 'L', p: [155.4, 115.2]}, - {t: 'C', p: [155.4, 115.2, 153.8, 122.4, 153.4, 123.6]}, - {t: 'C', p: [153.4, 123.6, 148.6, 127.2, 147.8, 132.8]}, - {t: 'C', p: [147.8, 132.8, 139, 138.8, 139.4, 143.2]}, - {t: 'C', p: [139.4, 143.2, 137.8, 148.4, 137, 153.2]}, - {t: 'C', p: [137, 153.2, 129.8, 158, 130.6, 160.8]}, - {t: 'C', p: [130.6, 160.8, 123, 174.8, 124.2, 181.6]}, - {t: 'C', p: [124.2, 181.6, 117.8, 181.2, 115, 183.6]}, - {t: 'C', p: [115, 183.6, 114.2, 188.4, 112.6, 188.8]}, - {t: 'C', p: [112.6, 188.8, 109.8, 190, 112.2, 194]}, - {t: 'C', p: [112.2, 194, 110.6, 196.8, 110.2, 198.4]}, - {t: 'C', p: [110.2, 198.4, 111, 201.2, 106.6, 206.8]}, - {t: 'C', p: [106.6, 206.8, 100.2, 225.6, 102.2, 230.8]}, - {t: 'C', p: [102.2, 230.8, 102.6, 235.6, 99.8, 237.2]}, - {t: 'C', p: [99.8, 237.2, 96.2, 236.8, 104.6, 248.8]}, - {t: 'C', p: [104.6, 248.8, 105.4, 250, 102.2, 252.4]}, - {t: 'C', p: [102.2, 252.4, 85, 256, 82.6, 272.4]}, - {t: 'C', p: [82.6, 272.4, 69, 287.2, 69, 292.4]}, - {t: 'C', p: [69, 294.705, 69.271, 297.852, 69.97, 302.465]}, - {t: 'C', p: [69.97, 302.465, 69.4, 310.801, 97, 311.601]}, - {t: 'C', p: [124.6, 312.401, 499.717, 280.245, 499.717, 280.245]}, - {t: 'z', p: []}]}, - -{f: '#cc7226', s: null, p: [{t: 'M', p: [84.4, 302.6]}, - {t: 'C', p: [59.4, 263.2, 73.8, 319.601, 73.8, 319.601]}, - {t: 'C', p: [82.6, 354.001, 212.2, 316.401, 212.2, 316.401]}, - {t: 'C', p: [212.2, 316.401, 381.001, 286, 392.201, 282]}, - {t: 'C', p: [403.401, 278, 498.601, 284.4, 498.601, 284.4]}, - {t: 'L', p: [493.001, 267.6]}, - {t: 'C', p: [428.201, 221.2, 409.001, 244.4, 395.401, 240.4]}, - {t: 'C', p: [381.801, 236.4, 384.201, 246, 381.001, 246.8]}, - {t: 'C', p: [377.801, 247.6, 338.601, 222.8, 332.201, 223.6]}, - {t: 'C', p: [325.801, 224.4, 300.459, 200.649, 315.401, 232.4]}, - {t: 'C', p: [331.401, 266.4, 257, 271.6, 240.2, 260.4]}, - {t: 'C', p: [223.4, 249.2, 247.4, 278.8, 247.4, 278.8]}, - {t: 'C', p: [265.8, 298.8, 231.4, 282, 231.4, 282]}, - {t: 'C', p: [197, 269.2, 173, 294.8, 169.8, 295.6]}, - {t: 'C', p: [166.6, 296.4, 161.8, 299.6, 161, 293.2]}, - {t: 'C', p: [160.2, 286.8, 152.69, 270.099, 121, 296.4]}, - {t: 'C', p: [101, 313.001, 87.2, 291, 87.2, 291]}, - {t: 'L', p: [84.4, 302.6]}, - {t: 'z', p: []}]}, - -{f: '#e87f3a', s: null, p: [{t: 'M', p: [333.51, 225.346]}, - {t: 'C', p: [327.11, 226.146, 301.743, 202.407, 316.71, 234.146]}, - {t: 'C', p: [333.31, 269.346, 258.31, 273.346, 241.51, 262.146]}, - {t: 'C', p: [224.709, 250.946, 248.71, 280.546, 248.71, 280.546]}, - {t: 'C', p: [267.11, 300.546, 232.709, 283.746, 232.709, 283.746]}, - {t: 'C', p: [198.309, 270.946, 174.309, 296.546, 171.109, 297.346]}, - {t: 'C', p: [167.909, 298.146, 163.109, 301.346, 162.309, 294.946]}, - {t: 'C', p: [161.509, 288.546, 154.13, 272.012, 122.309, 298.146]}, - {t: 'C', p: [101.073, 315.492, 87.582, 294.037, 87.582, 294.037]}, - {t: 'L', p: [84.382, 304.146]}, - {t: 'C', p: [59.382, 264.346, 74.454, 322.655, 74.454, 322.655]}, - {t: 'C', p: [83.255, 357.056, 213.509, 318.146, 213.509, 318.146]}, - {t: 'C', p: [213.509, 318.146, 382.31, 287.746, 393.51, 283.746]}, - {t: 'C', p: [404.71, 279.746, 499.038, 286.073, 499.038, 286.073]}, - {t: 'L', p: [493.51, 268.764]}, - {t: 'C', p: [428.71, 222.364, 410.31, 246.146, 396.71, 242.146]}, - {t: 'C', p: [383.11, 238.146, 385.51, 247.746, 382.31, 248.546]}, - {t: 'C', p: [379.11, 249.346, 339.91, 224.546, 333.51, 225.346]}, - {t: 'z', p: []}]}, - -{f: '#ea8c4d', s: null, p: [{t: 'M', p: [334.819, 227.091]}, - {t: 'C', p: [328.419, 227.891, 303.685, 203.862, 318.019, 235.891]}, - {t: 'C', p: [334.219, 272.092, 259.619, 275.092, 242.819, 263.892]}, - {t: 'C', p: [226.019, 252.692, 250.019, 282.292, 250.019, 282.292]}, - {t: 'C', p: [268.419, 302.292, 234.019, 285.492, 234.019, 285.492]}, - {t: 'C', p: [199.619, 272.692, 175.618, 298.292, 172.418, 299.092]}, - {t: 'C', p: [169.218, 299.892, 164.418, 303.092, 163.618, 296.692]}, - {t: 'C', p: [162.818, 290.292, 155.57, 273.925, 123.618, 299.892]}, - {t: 'C', p: [101.145, 317.983, 87.964, 297.074, 87.964, 297.074]}, - {t: 'L', p: [84.364, 305.692]}, - {t: 'C', p: [60.564, 266.692, 75.109, 325.71, 75.109, 325.71]}, - {t: 'C', p: [83.909, 360.11, 214.819, 319.892, 214.819, 319.892]}, - {t: 'C', p: [214.819, 319.892, 383.619, 289.492, 394.819, 285.492]}, - {t: 'C', p: [406.019, 281.492, 499.474, 287.746, 499.474, 287.746]}, - {t: 'L', p: [494.02, 269.928]}, - {t: 'C', p: [429.219, 223.528, 411.619, 247.891, 398.019, 243.891]}, - {t: 'C', p: [384.419, 239.891, 386.819, 249.491, 383.619, 250.292]}, - {t: 'C', p: [380.419, 251.092, 341.219, 226.291, 334.819, 227.091]}, - {t: 'z', p: []}]}, - -{f: '#ec9961', s: null, p: [{t: 'M', p: [336.128, 228.837]}, - {t: 'C', p: [329.728, 229.637, 304.999, 205.605, 319.328, 237.637]}, - {t: 'C', p: [336.128, 275.193, 260.394, 276.482, 244.128, 265.637]}, - {t: 'C', p: [227.328, 254.437, 251.328, 284.037, 251.328, 284.037]}, - {t: 'C', p: [269.728, 304.037, 235.328, 287.237, 235.328, 287.237]}, - {t: 'C', p: [200.928, 274.437, 176.928, 300.037, 173.728, 300.837]}, - {t: 'C', p: [170.528, 301.637, 165.728, 304.837, 164.928, 298.437]}, - {t: 'C', p: [164.128, 292.037, 157.011, 275.839, 124.927, 301.637]}, - {t: 'C', p: [101.218, 320.474, 88.345, 300.11, 88.345, 300.11]}, - {t: 'L', p: [84.345, 307.237]}, - {t: 'C', p: [62.545, 270.437, 75.764, 328.765, 75.764, 328.765]}, - {t: 'C', p: [84.564, 363.165, 216.128, 321.637, 216.128, 321.637]}, - {t: 'C', p: [216.128, 321.637, 384.928, 291.237, 396.129, 287.237]}, - {t: 'C', p: [407.329, 283.237, 499.911, 289.419, 499.911, 289.419]}, - {t: 'L', p: [494.529, 271.092]}, - {t: 'C', p: [429.729, 224.691, 412.929, 249.637, 399.329, 245.637]}, - {t: 'C', p: [385.728, 241.637, 388.128, 251.237, 384.928, 252.037]}, - {t: 'C', p: [381.728, 252.837, 342.528, 228.037, 336.128, 228.837]}, - {t: 'z', p: []}]}, - -{f: '#eea575', s: null, p: [{t: 'M', p: [337.438, 230.583]}, - {t: 'C', p: [331.037, 231.383, 306.814, 207.129, 320.637, 239.383]}, - {t: 'C', p: [337.438, 278.583, 262.237, 278.583, 245.437, 267.383]}, - {t: 'C', p: [228.637, 256.183, 252.637, 285.783, 252.637, 285.783]}, - {t: 'C', p: [271.037, 305.783, 236.637, 288.983, 236.637, 288.983]}, - {t: 'C', p: [202.237, 276.183, 178.237, 301.783, 175.037, 302.583]}, - {t: 'C', p: [171.837, 303.383, 167.037, 306.583, 166.237, 300.183]}, - {t: 'C', p: [165.437, 293.783, 158.452, 277.752, 126.237, 303.383]}, - {t: 'C', p: [101.291, 322.965, 88.727, 303.146, 88.727, 303.146]}, - {t: 'L', p: [84.327, 308.783]}, - {t: 'C', p: [64.527, 273.982, 76.418, 331.819, 76.418, 331.819]}, - {t: 'C', p: [85.218, 366.22, 217.437, 323.383, 217.437, 323.383]}, - {t: 'C', p: [217.437, 323.383, 386.238, 292.983, 397.438, 288.983]}, - {t: 'C', p: [408.638, 284.983, 500.347, 291.092, 500.347, 291.092]}, - {t: 'L', p: [495.038, 272.255]}, - {t: 'C', p: [430.238, 225.855, 414.238, 251.383, 400.638, 247.383]}, - {t: 'C', p: [387.038, 243.383, 389.438, 252.983, 386.238, 253.783]}, - {t: 'C', p: [383.038, 254.583, 343.838, 229.783, 337.438, 230.583]}, - {t: 'z', p: []}]}, - -{f: '#f1b288', s: null, p: [{t: 'M', p: [338.747, 232.328]}, - {t: 'C', p: [332.347, 233.128, 306.383, 209.677, 321.947, 241.128]}, - {t: 'C', p: [341.147, 279.928, 263.546, 280.328, 246.746, 269.128]}, - {t: 'C', p: [229.946, 257.928, 253.946, 287.528, 253.946, 287.528]}, - {t: 'C', p: [272.346, 307.528, 237.946, 290.728, 237.946, 290.728]}, - {t: 'C', p: [203.546, 277.928, 179.546, 303.528, 176.346, 304.328]}, - {t: 'C', p: [173.146, 305.128, 168.346, 308.328, 167.546, 301.928]}, - {t: 'C', p: [166.746, 295.528, 159.892, 279.665, 127.546, 305.128]}, - {t: 'C', p: [101.364, 325.456, 89.109, 306.183, 89.109, 306.183]}, - {t: 'L', p: [84.309, 310.328]}, - {t: 'C', p: [66.309, 277.128, 77.073, 334.874, 77.073, 334.874]}, - {t: 'C', p: [85.873, 369.274, 218.746, 325.128, 218.746, 325.128]}, - {t: 'C', p: [218.746, 325.128, 387.547, 294.728, 398.747, 290.728]}, - {t: 'C', p: [409.947, 286.728, 500.783, 292.764, 500.783, 292.764]}, - {t: 'L', p: [495.547, 273.419]}, - {t: 'C', p: [430.747, 227.019, 415.547, 253.128, 401.947, 249.128]}, - {t: 'C', p: [388.347, 245.128, 390.747, 254.728, 387.547, 255.528]}, - {t: 'C', p: [384.347, 256.328, 345.147, 231.528, 338.747, 232.328]}, - {t: 'z', p: []}]}, - -{f: '#f3bf9c', s: null, p: [{t: 'M', p: [340.056, 234.073]}, - {t: 'C', p: [333.655, 234.873, 307.313, 211.613, 323.255, 242.873]}, - {t: 'C', p: [343.656, 282.874, 264.855, 282.074, 248.055, 270.874]}, - {t: 'C', p: [231.255, 259.674, 255.255, 289.274, 255.255, 289.274]}, - {t: 'C', p: [273.655, 309.274, 239.255, 292.474, 239.255, 292.474]}, - {t: 'C', p: [204.855, 279.674, 180.855, 305.274, 177.655, 306.074]}, - {t: 'C', p: [174.455, 306.874, 169.655, 310.074, 168.855, 303.674]}, - {t: 'C', p: [168.055, 297.274, 161.332, 281.578, 128.855, 306.874]}, - {t: 'C', p: [101.436, 327.947, 89.491, 309.219, 89.491, 309.219]}, - {t: 'L', p: [84.291, 311.874]}, - {t: 'C', p: [68.291, 281.674, 77.727, 337.929, 77.727, 337.929]}, - {t: 'C', p: [86.527, 372.329, 220.055, 326.874, 220.055, 326.874]}, - {t: 'C', p: [220.055, 326.874, 388.856, 296.474, 400.056, 292.474]}, - {t: 'C', p: [411.256, 288.474, 501.22, 294.437, 501.22, 294.437]}, - {t: 'L', p: [496.056, 274.583]}, - {t: 'C', p: [431.256, 228.183, 416.856, 254.874, 403.256, 250.874]}, - {t: 'C', p: [389.656, 246.873, 392.056, 256.474, 388.856, 257.274]}, - {t: 'C', p: [385.656, 258.074, 346.456, 233.273, 340.056, 234.073]}, - {t: 'z', p: []}]}, - -{f: '#f5ccb0', s: null, p: [{t: 'M', p: [341.365, 235.819]}, - {t: 'C', p: [334.965, 236.619, 307.523, 213.944, 324.565, 244.619]}, - {t: 'C', p: [346.565, 284.219, 266.164, 283.819, 249.364, 272.619]}, - {t: 'C', p: [232.564, 261.419, 256.564, 291.019, 256.564, 291.019]}, - {t: 'C', p: [274.964, 311.019, 240.564, 294.219, 240.564, 294.219]}, - {t: 'C', p: [206.164, 281.419, 182.164, 307.019, 178.964, 307.819]}, - {t: 'C', p: [175.764, 308.619, 170.964, 311.819, 170.164, 305.419]}, - {t: 'C', p: [169.364, 299.019, 162.773, 283.492, 130.164, 308.619]}, - {t: 'C', p: [101.509, 330.438, 89.873, 312.256, 89.873, 312.256]}, - {t: 'L', p: [84.273, 313.419]}, - {t: 'C', p: [69.872, 285.019, 78.382, 340.983, 78.382, 340.983]}, - {t: 'C', p: [87.182, 375.384, 221.364, 328.619, 221.364, 328.619]}, - {t: 'C', p: [221.364, 328.619, 390.165, 298.219, 401.365, 294.219]}, - {t: 'C', p: [412.565, 290.219, 501.656, 296.11, 501.656, 296.11]}, - {t: 'L', p: [496.565, 275.746]}, - {t: 'C', p: [431.765, 229.346, 418.165, 256.619, 404.565, 252.619]}, - {t: 'C', p: [390.965, 248.619, 393.365, 258.219, 390.165, 259.019]}, - {t: 'C', p: [386.965, 259.819, 347.765, 235.019, 341.365, 235.819]}, - {t: 'z', p: []}]}, - -{f: '#f8d8c4', s: null, p: [{t: 'M', p: [342.674, 237.565]}, - {t: 'C', p: [336.274, 238.365, 308.832, 215.689, 325.874, 246.365]}, - {t: 'C', p: [347.874, 285.965, 267.474, 285.565, 250.674, 274.365]}, - {t: 'C', p: [233.874, 263.165, 257.874, 292.765, 257.874, 292.765]}, - {t: 'C', p: [276.274, 312.765, 241.874, 295.965, 241.874, 295.965]}, - {t: 'C', p: [207.473, 283.165, 183.473, 308.765, 180.273, 309.565]}, - {t: 'C', p: [177.073, 310.365, 172.273, 313.565, 171.473, 307.165]}, - {t: 'C', p: [170.673, 300.765, 164.214, 285.405, 131.473, 310.365]}, - {t: 'C', p: [101.582, 332.929, 90.255, 315.293, 90.255, 315.293]}, - {t: 'L', p: [84.255, 314.965]}, - {t: 'C', p: [70.654, 288.564, 79.037, 344.038, 79.037, 344.038]}, - {t: 'C', p: [87.837, 378.438, 222.673, 330.365, 222.673, 330.365]}, - {t: 'C', p: [222.673, 330.365, 391.474, 299.965, 402.674, 295.965]}, - {t: 'C', p: [413.874, 291.965, 502.093, 297.783, 502.093, 297.783]}, - {t: 'L', p: [497.075, 276.91]}, - {t: 'C', p: [432.274, 230.51, 419.474, 258.365, 405.874, 254.365]}, - {t: 'C', p: [392.274, 250.365, 394.674, 259.965, 391.474, 260.765]}, - {t: 'C', p: [388.274, 261.565, 349.074, 236.765, 342.674, 237.565]}, - {t: 'z', p: []}]}, - -{f: '#fae5d7', s: null, p: [{t: 'M', p: [343.983, 239.31]}, - {t: 'C', p: [337.583, 240.11, 310.529, 217.223, 327.183, 248.11]}, - {t: 'C', p: [349.183, 288.91, 268.783, 287.31, 251.983, 276.11]}, - {t: 'C', p: [235.183, 264.91, 259.183, 294.51, 259.183, 294.51]}, - {t: 'C', p: [277.583, 314.51, 243.183, 297.71, 243.183, 297.71]}, - {t: 'C', p: [208.783, 284.91, 184.783, 310.51, 181.583, 311.31]}, - {t: 'C', p: [178.382, 312.11, 173.582, 315.31, 172.782, 308.91]}, - {t: 'C', p: [171.982, 302.51, 165.654, 287.318, 132.782, 312.11]}, - {t: 'C', p: [101.655, 335.42, 90.637, 318.329, 90.637, 318.329]}, - {t: 'L', p: [84.236, 316.51]}, - {t: 'C', p: [71.236, 292.51, 79.691, 347.093, 79.691, 347.093]}, - {t: 'C', p: [88.491, 381.493, 223.983, 332.11, 223.983, 332.11]}, - {t: 'C', p: [223.983, 332.11, 392.783, 301.71, 403.983, 297.71]}, - {t: 'C', p: [415.183, 293.71, 502.529, 299.456, 502.529, 299.456]}, - {t: 'L', p: [497.583, 278.074]}, - {t: 'C', p: [432.783, 231.673, 420.783, 260.11, 407.183, 256.11]}, - {t: 'C', p: [393.583, 252.11, 395.983, 261.71, 392.783, 262.51]}, - {t: 'C', p: [389.583, 263.31, 350.383, 238.51, 343.983, 239.31]}, - {t: 'z', p: []}]}, - -{f: '#fcf2eb', s: null, p: [{t: 'M', p: [345.292, 241.055]}, - {t: 'C', p: [338.892, 241.855, 312.917, 218.411, 328.492, 249.855]}, - {t: 'C', p: [349.692, 292.656, 270.092, 289.056, 253.292, 277.856]}, - {t: 'C', p: [236.492, 266.656, 260.492, 296.256, 260.492, 296.256]}, - {t: 'C', p: [278.892, 316.256, 244.492, 299.456, 244.492, 299.456]}, - {t: 'C', p: [210.092, 286.656, 186.092, 312.256, 182.892, 313.056]}, - {t: 'C', p: [179.692, 313.856, 174.892, 317.056, 174.092, 310.656]}, - {t: 'C', p: [173.292, 304.256, 167.095, 289.232, 134.092, 313.856]}, - {t: 'C', p: [101.727, 337.911, 91.018, 321.365, 91.018, 321.365]}, - {t: 'L', p: [84.218, 318.056]}, - {t: 'C', p: [71.418, 294.856, 80.346, 350.147, 80.346, 350.147]}, - {t: 'C', p: [89.146, 384.547, 225.292, 333.856, 225.292, 333.856]}, - {t: 'C', p: [225.292, 333.856, 394.093, 303.456, 405.293, 299.456]}, - {t: 'C', p: [416.493, 295.456, 502.965, 301.128, 502.965, 301.128]}, - {t: 'L', p: [498.093, 279.237]}, - {t: 'C', p: [433.292, 232.837, 422.093, 261.856, 408.493, 257.856]}, - {t: 'C', p: [394.893, 253.855, 397.293, 263.456, 394.093, 264.256]}, - {t: 'C', p: [390.892, 265.056, 351.692, 240.255, 345.292, 241.055]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: null, p: [{t: 'M', p: [84.2, 319.601]}, - {t: 'C', p: [71.4, 297.6, 81, 353.201, 81, 353.201]}, - {t: 'C', p: [89.8, 387.601, 226.6, 335.601, 226.6, 335.601]}, - {t: 'C', p: [226.6, 335.601, 395.401, 305.2, 406.601, 301.2]}, - {t: 'C', p: [417.801, 297.2, 503.401, 302.8, 503.401, 302.8]}, - {t: 'L', p: [498.601, 280.4]}, - {t: 'C', p: [433.801, 234, 423.401, 263.6, 409.801, 259.6]}, - {t: 'C', p: [396.201, 255.6, 398.601, 265.2, 395.401, 266]}, - {t: 'C', p: [392.201, 266.8, 353.001, 242, 346.601, 242.8]}, - {t: 'C', p: [340.201, 243.6, 314.981, 219.793, 329.801, 251.6]}, - {t: 'C', p: [352.028, 299.307, 269.041, 289.227, 254.6, 279.6]}, - {t: 'C', p: [237.8, 268.4, 261.8, 298, 261.8, 298]}, - {t: 'C', p: [280.2, 318.001, 245.8, 301.2, 245.8, 301.2]}, - {t: 'C', p: [211.4, 288.4, 187.4, 314.001, 184.2, 314.801]}, - {t: 'C', p: [181, 315.601, 176.2, 318.801, 175.4, 312.401]}, - {t: 'C', p: [174.6, 306, 168.535, 291.144, 135.4, 315.601]}, - {t: 'C', p: [101.8, 340.401, 91.4, 324.401, 91.4, 324.401]}, - {t: 'L', p: [84.2, 319.601]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [125.8, 349.601]}, - {t: 'C', p: [125.8, 349.601, 118.6, 361.201, 139.4, 374.401]}, - {t: 'C', p: [139.4, 374.401, 140.8, 375.801, 122.8, 371.601]}, - {t: 'C', p: [122.8, 371.601, 116.6, 369.601, 115, 359.201]}, - {t: 'C', p: [115, 359.201, 110.2, 354.801, 105.4, 349.201]}, - {t: 'C', p: [100.6, 343.601, 125.8, 349.601, 125.8, 349.601]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [265.8, 302]}, - {t: 'C', p: [265.8, 302, 283.498, 328.821, 282.9, 333.601]}, - {t: 'C', p: [281.6, 344.001, 281.4, 353.601, 284.6, 357.601]}, - {t: 'C', p: [287.801, 361.601, 296.601, 394.801, 296.601, 394.801]}, - {t: 'C', p: [296.601, 394.801, 296.201, 396.001, 308.601, 358.001]}, - {t: 'C', p: [308.601, 358.001, 320.201, 342.001, 300.201, 323.601]}, - {t: 'C', p: [300.201, 323.601, 265, 294.8, 265.8, 302]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [145.8, 376.401]}, - {t: 'C', p: [145.8, 376.401, 157, 383.601, 142.6, 414.801]}, - {t: 'L', p: [149, 412.401]}, - {t: 'C', p: [149, 412.401, 148.2, 423.601, 145, 426.001]}, - {t: 'L', p: [152.2, 422.801]}, - {t: 'C', p: [152.2, 422.801, 157, 430.801, 153, 435.601]}, - {t: 'C', p: [153, 435.601, 169.8, 443.601, 169, 450.001]}, - {t: 'C', p: [169, 450.001, 175.4, 442.001, 171.4, 435.601]}, - {t: 'C', p: [167.4, 429.201, 160.2, 433.201, 161, 414.801]}, - {t: 'L', p: [152.2, 418.001]}, - {t: 'C', p: [152.2, 418.001, 157.8, 409.201, 157.8, 402.801]}, - {t: 'L', p: [149.8, 405.201]}, - {t: 'C', p: [149.8, 405.201, 165.269, 378.623, 154.6, 377.201]}, - {t: 'C', p: [148.6, 376.401, 145.8, 376.401, 145.8, 376.401]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [178.2, 393.201]}, - {t: 'C', p: [178.2, 393.201, 181, 388.801, 178.2, 389.601]}, - {t: 'C', p: [175.4, 390.401, 144.2, 405.201, 138.2, 414.801]}, - {t: 'C', p: [138.2, 414.801, 172.6, 390.401, 178.2, 393.201]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [188.6, 401.201]}, - {t: 'C', p: [188.6, 401.201, 191.4, 396.801, 188.6, 397.601]}, - {t: 'C', p: [185.8, 398.401, 154.6, 413.201, 148.6, 422.801]}, - {t: 'C', p: [148.6, 422.801, 183, 398.401, 188.6, 401.201]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [201.8, 386.001]}, - {t: 'C', p: [201.8, 386.001, 204.6, 381.601, 201.8, 382.401]}, - {t: 'C', p: [199, 383.201, 167.8, 398.001, 161.8, 407.601]}, - {t: 'C', p: [161.8, 407.601, 196.2, 383.201, 201.8, 386.001]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [178.6, 429.601]}, - {t: 'C', p: [178.6, 429.601, 178.6, 423.601, 175.8, 424.401]}, - {t: 'C', p: [173, 425.201, 137, 442.801, 131, 452.401]}, - {t: 'C', p: [131, 452.401, 173, 426.801, 178.6, 429.601]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [179.8, 418.801]}, - {t: 'C', p: [179.8, 418.801, 181, 414.001, 178.2, 414.801]}, - {t: 'C', p: [176.2, 414.801, 149.8, 426.401, 143.8, 436.001]}, - {t: 'C', p: [143.8, 436.001, 173.4, 414.401, 179.8, 418.801]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [165.4, 466.401]}, - {t: 'L', p: [155.4, 474.001]}, - {t: 'C', p: [155.4, 474.001, 165.8, 466.401, 169.4, 467.601]}, - {t: 'C', p: [169.4, 467.601, 162.6, 478.801, 161.8, 484.001]}, - {t: 'C', p: [161.8, 484.001, 172.2, 471.201, 177.8, 471.601]}, - {t: 'C', p: [177.8, 471.601, 185.4, 472.001, 185.4, 482.801]}, - {t: 'C', p: [185.4, 482.801, 191, 472.401, 194.2, 472.801]}, - {t: 'C', p: [194.2, 472.801, 195.4, 479.201, 194.2, 486.001]}, - {t: 'C', p: [194.2, 486.001, 198.2, 478.401, 202.2, 480.001]}, - {t: 'C', p: [202.2, 480.001, 208.6, 478.001, 207.8, 489.601]}, - {t: 'C', p: [207.8, 489.601, 207.8, 500.001, 207, 502.801]}, - {t: 'C', p: [207, 502.801, 212.6, 476.401, 215, 476.001]}, - {t: 'C', p: [215, 476.001, 223, 474.801, 227.8, 483.601]}, - {t: 'C', p: [227.8, 483.601, 223.8, 476.001, 228.6, 478.001]}, - {t: 'C', p: [228.6, 478.001, 239.4, 479.601, 242.6, 486.401]}, - {t: 'C', p: [242.6, 486.401, 235.8, 474.401, 241.4, 477.601]}, - {t: 'C', p: [241.4, 477.601, 248.2, 477.601, 249.4, 484.001]}, - {t: 'C', p: [249.4, 484.001, 257.8, 505.201, 259.8, 506.801]}, - {t: 'C', p: [259.8, 506.801, 252.2, 485.201, 253.8, 485.201]}, - {t: 'C', p: [253.8, 485.201, 251.8, 473.201, 257, 488.001]}, - {t: 'C', p: [257, 488.001, 253.8, 474.001, 259.4, 474.801]}, - {t: 'C', p: [265, 475.601, 269.4, 485.601, 277.8, 483.201]}, - {t: 'C', p: [277.8, 483.201, 287.401, 488.801, 289.401, 419.601]}, - {t: 'L', p: [165.4, 466.401]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [170.2, 373.601]}, - {t: 'C', p: [170.2, 373.601, 185, 367.601, 225, 373.601]}, - {t: 'C', p: [225, 373.601, 232.2, 374.001, 239, 365.201]}, - {t: 'C', p: [245.8, 356.401, 272.6, 349.201, 279, 351.201]}, - {t: 'L', p: [288.601, 357.601]}, - {t: 'L', p: [289.401, 358.801]}, - {t: 'C', p: [289.401, 358.801, 301.801, 369.201, 302.201, 376.801]}, - {t: 'C', p: [302.601, 384.401, 287.801, 432.401, 278.2, 448.401]}, - {t: 'C', p: [268.6, 464.401, 259, 476.801, 239.8, 474.401]}, - {t: 'C', p: [239.8, 474.401, 219, 470.401, 193.4, 474.401]}, - {t: 'C', p: [193.4, 474.401, 164.2, 472.801, 161.4, 464.801]}, - {t: 'C', p: [158.6, 456.801, 172.6, 441.601, 172.6, 441.601]}, - {t: 'C', p: [172.6, 441.601, 177, 433.201, 175.8, 418.801]}, - {t: 'C', p: [174.6, 404.401, 175, 376.401, 170.2, 373.601]}, - {t: 'z', p: []}]}, - -{f: '#e5668c', s: null, p: [{t: 'M', p: [192.2, 375.601]}, - {t: 'C', p: [200.6, 394.001, 171, 459.201, 171, 459.201]}, - {t: 'C', p: [169, 460.801, 183.66, 466.846, 193.8, 464.401]}, - {t: 'C', p: [204.746, 461.763, 245, 466.001, 245, 466.001]}, - {t: 'C', p: [268.6, 450.401, 281.4, 406.001, 281.4, 406.001]}, - {t: 'C', p: [281.4, 406.001, 291.801, 382.001, 274.2, 378.801]}, - {t: 'C', p: [256.6, 375.601, 192.2, 375.601, 192.2, 375.601]}, - {t: 'z', p: []}]}, - -{f: '#b23259', s: null, p: [{t: 'M', p: [190.169, 406.497]}, - {t: 'C', p: [193.495, 393.707, 195.079, 381.906, 192.2, 375.601]}, - {t: 'C', p: [192.2, 375.601, 254.6, 382.001, 265.8, 361.201]}, - {t: 'C', p: [270.041, 353.326, 284.801, 384.001, 284.4, 393.601]}, - {t: 'C', p: [284.4, 393.601, 221.4, 408.001, 206.6, 396.801]}, - {t: 'L', p: [190.169, 406.497]}, - {t: 'z', p: []}]}, - -{f: '#a5264c', s: null, p: [{t: 'M', p: [194.6, 422.801]}, - {t: 'C', p: [194.6, 422.801, 196.6, 430.001, 194.2, 434.001]}, - {t: 'C', p: [194.2, 434.001, 192.6, 434.801, 191.4, 435.201]}, - {t: 'C', p: [191.4, 435.201, 192.6, 438.801, 198.6, 440.401]}, - {t: 'C', p: [198.6, 440.401, 200.6, 444.801, 203, 445.201]}, - {t: 'C', p: [205.4, 445.601, 210.2, 451.201, 214.2, 450.001]}, - {t: 'C', p: [218.2, 448.801, 229.4, 444.801, 229.4, 444.801]}, - {t: 'C', p: [229.4, 444.801, 235, 441.601, 243.8, 445.201]}, - {t: 'C', p: [243.8, 445.201, 246.175, 444.399, 246.6, 440.401]}, - {t: 'C', p: [247.1, 435.701, 250.2, 432.001, 252.2, 430.001]}, - {t: 'C', p: [254.2, 428.001, 263.8, 415.201, 262.6, 414.801]}, - {t: 'C', p: [261.4, 414.401, 194.6, 422.801, 194.6, 422.801]}, - {t: 'z', p: []}]}, - -{f: '#ff727f', s: '#000', p: [{t: 'M', p: [190.2, 374.401]}, - {t: 'C', p: [190.2, 374.401, 187.4, 396.801, 190.6, 405.201]}, - {t: 'C', p: [193.8, 413.601, 193, 415.601, 192.2, 419.601]}, - {t: 'C', p: [191.4, 423.601, 195.8, 433.601, 201.4, 439.601]}, - {t: 'L', p: [213.4, 441.201]}, - {t: 'C', p: [213.4, 441.201, 228.6, 437.601, 237.8, 440.401]}, - {t: 'C', p: [237.8, 440.401, 246.794, 441.744, 250.2, 426.801]}, - {t: 'C', p: [250.2, 426.801, 255, 420.401, 262.2, 417.601]}, - {t: 'C', p: [269.4, 414.801, 276.6, 373.201, 272.6, 365.201]}, - {t: 'C', p: [268.6, 357.201, 254.2, 352.801, 238.2, 368.401]}, - {t: 'C', p: [222.2, 384.001, 220.2, 367.201, 190.2, 374.401]}, - {t: 'z', p: []}]}, - -{f: '#ffc', s: {c: '#000', w: 0.5}, - p: [{t: 'M', p: [191.8, 449.201]}, - {t: 'C', p: [191.8, 449.201, 191, 447.201, 186.6, 446.801]}, - {t: 'C', p: [186.6, 446.801, 164.2, 443.201, 155.8, 430.801]}, - {t: 'C', p: [155.8, 430.801, 149, 425.201, 153.4, 436.801]}, - {t: 'C', p: [153.4, 436.801, 163.8, 457.201, 170.6, 460.001]}, - {t: 'C', p: [170.6, 460.001, 187, 464.001, 191.8, 449.201]}, - {t: 'z', p: []}]}, - -{f: '#cc3f4c', s: null, p: [{t: 'M', p: [271.742, 385.229]}, - {t: 'C', p: [272.401, 377.323, 274.354, 368.709, 272.6, 365.201]}, - {t: 'C', p: [266.154, 352.307, 249.181, 357.695, 238.2, 368.401]}, - {t: 'C', p: [222.2, 384.001, 220.2, 367.201, 190.2, 374.401]}, - {t: 'C', p: [190.2, 374.401, 188.455, 388.364, 189.295, 398.376]}, - {t: 'C', p: [189.295, 398.376, 226.6, 386.801, 227.4, 392.401]}, - {t: 'C', p: [227.4, 392.401, 229, 389.201, 238.2, 389.201]}, - {t: 'C', p: [247.4, 389.201, 270.142, 388.029, 271.742, 385.229]}, - {t: 'z', p: []}]}, - -{f: null, s: {c: '#a51926', w: 2}, - p: [{t: 'M', p: [228.6, 375.201]}, - {t: 'C', p: [228.6, 375.201, 233.4, 380.001, 229.8, 389.601]}, - {t: 'C', p: [229.8, 389.601, 215.4, 405.601, 217.4, 419.601]}]}, - -{f: '#ffc', s: {c: '#000', w: 0.5}, - p: [{t: 'M', p: [180.6, 460.001]}, - {t: 'C', p: [180.6, 460.001, 176.2, 447.201, 185, 454.001]}, - {t: 'C', p: [185, 454.001, 189.8, 456.001, 188.6, 457.601]}, - {t: 'C', p: [187.4, 459.201, 181.8, 463.201, 180.6, 460.001]}, - {t: 'z', p: []}]}, - -{f: '#ffc', s: {c: '#000', w: 0.5}, - p: [{t: 'M', p: [185.64, 461.201]}, - {t: 'C', p: [185.64, 461.201, 182.12, 450.961, 189.16, 456.401]}, - {t: 'C', p: [189.16, 456.401, 193.581, 458.849, 192.04, 459.281]}, - {t: 'C', p: [187.48, 460.561, 192.04, 463.121, 185.64, 461.201]}, - {t: 'z', p: []}]}, - -{f: '#ffc', s: {c: '#000', w: 0.5}, - p: [{t: 'M', p: [190.44, 461.201]}, - {t: 'C', p: [190.44, 461.201, 186.92, 450.961, 193.96, 456.401]}, - {t: 'C', p: [193.96, 456.401, 198.335, 458.711, 196.84, 459.281]}, - {t: 'C', p: [193.48, 460.561, 196.84, 463.121, 190.44, 461.201]}, - {t: 'z', p: []}]}, - -{f: '#ffc', s: {c: '#000', w: 0.5}, - p: [{t: 'M', p: [197.04, 461.401]}, - {t: 'C', p: [197.04, 461.401, 193.52, 451.161, 200.56, 456.601]}, - {t: 'C', p: [200.56, 456.601, 204.943, 458.933, 203.441, 459.481]}, - {t: 'C', p: [200.48, 460.561, 203.441, 463.321, 197.04, 461.401]}, - {t: 'z', p: []}]}, - -{f: '#ffc', s: {c: '#000', w: 0.5}, - p: [{t: 'M', p: [203.52, 461.321]}, - {t: 'C', p: [203.52, 461.321, 200, 451.081, 207.041, 456.521]}, - {t: 'C', p: [207.041, 456.521, 210.881, 458.121, 209.921, 459.401]}, - {t: 'C', p: [208.961, 460.681, 209.921, 463.241, 203.52, 461.321]}, - {t: 'z', p: []}]}, - -{f: '#ffc', s: {c: '#000', w: 0.5}, - p: [{t: 'M', p: [210.2, 462.001]}, - {t: 'C', p: [210.2, 462.001, 205.4, 449.601, 214.6, 456.001]}, - {t: 'C', p: [214.6, 456.001, 219.4, 458.001, 218.2, 459.601]}, - {t: 'C', p: [217, 461.201, 218.2, 464.401, 210.2, 462.001]}, - {t: 'z', p: []}]}, - -{f: null, s: {c: '#a5264c', w: 2}, - p: [{t: 'M', p: [181.8, 444.801]}, - {t: 'C', p: [181.8, 444.801, 195, 442.001, 201, 445.201]}, - {t: 'C', p: [201, 445.201, 207, 446.401, 208.2, 446.001]}, - {t: 'C', p: [209.4, 445.601, 212.6, 445.201, 212.6, 445.201]}]}, - -{f: null, s: {c: '#a5264c', w: 2}, - p: [{t: 'M', p: [215.8, 453.601]}, - {t: 'C', p: [215.8, 453.601, 227.8, 440.001, 239.8, 444.401]}, - {t: 'C', p: [246.816, 446.974, 245.8, 443.601, 246.6, 440.801]}, - {t: 'C', p: [247.4, 438.001, 247.6, 433.801, 252.6, 430.801]}]}, - -{f: '#ffc', s: {c: '#000', w: 0.5}, - p: [{t: 'M', p: [233, 437.601]}, - {t: 'C', p: [233, 437.601, 229, 426.801, 226.2, 439.601]}, - {t: 'C', p: [223.4, 452.401, 220.2, 456.001, 218.6, 458.801]}, - {t: 'C', p: [218.6, 458.801, 218.6, 464.001, 227, 463.601]}, - {t: 'C', p: [227, 463.601, 237.8, 463.201, 238.2, 460.401]}, - {t: 'C', p: [238.6, 457.601, 237, 446.001, 233, 437.601]}, - {t: 'z', p: []}]}, - -{f: null, s: {c: '#a5264c', w: 2}, - p: [{t: 'M', p: [247, 444.801]}, - {t: 'C', p: [247, 444.801, 250.6, 442.401, 253, 443.601]}]}, - -{f: null, s: {c: '#a5264c', w: 2}, - p: [{t: 'M', p: [253.5, 428.401]}, - {t: 'C', p: [253.5, 428.401, 256.4, 423.501, 261.2, 422.701]}]}, - -{f: '#b2b2b2', s: null, p: [{t: 'M', p: [174.2, 465.201]}, - {t: 'C', p: [174.2, 465.201, 192.2, 468.401, 196.6, 466.801]}, - {t: 'C', p: [196.6, 466.801, 205.4, 466.801, 197, 468.801]}, - {t: 'C', p: [197, 468.801, 184.2, 468.801, 176.2, 467.601]}, - {t: 'C', p: [176.2, 467.601, 164.6, 462.001, 174.2, 465.201]}, - {t: 'z', p: []}]}, - -{f: '#ffc', s: {c: '#000', w: 0.5}, - p: [{t: 'M', p: [188.2, 372.001]}, - {t: 'C', p: [188.2, 372.001, 205.8, 372.001, 207.8, 372.801]}, - {t: 'C', p: [207.8, 372.801, 215, 403.601, 211.4, 411.201]}, - {t: 'C', p: [211.4, 411.201, 210.2, 414.001, 207.4, 408.401]}, - {t: 'C', p: [207.4, 408.401, 189, 375.601, 185.8, 373.601]}, - {t: 'C', p: [182.6, 371.601, 187, 372.001, 188.2, 372.001]}, - {t: 'z', p: []}]}, - -{f: '#ffc', s: {c: '#000', w: 0.5}, - p: [{t: 'M', p: [111.1, 369.301]}, - {t: 'C', p: [111.1, 369.301, 120, 371.001, 132.6, 373.601]}, - {t: 'C', p: [132.6, 373.601, 137.4, 396.001, 140.6, 400.801]}, - {t: 'C', p: [143.8, 405.601, 140.2, 405.601, 136.6, 402.801]}, - {t: 'C', p: [133, 400.001, 118.2, 386.001, 116.2, 381.601]}, - {t: 'C', p: [114.2, 377.201, 111.1, 369.301, 111.1, 369.301]}, - {t: 'z', p: []}]}, - -{f: '#ffc', s: {c: '#000', w: 0.5}, - p: [{t: 'M', p: [132.961, 373.818]}, - {t: 'C', p: [132.961, 373.818, 138.761, 375.366, 139.77, 377.581]}, - {t: 'C', p: [140.778, 379.795, 138.568, 383.092, 138.568, 383.092]}, - {t: 'C', p: [138.568, 383.092, 137.568, 386.397, 136.366, 384.235]}, - {t: 'C', p: [135.164, 382.072, 132.292, 374.412, 132.961, 373.818]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [133, 373.601]}, - {t: 'C', p: [133, 373.601, 136.6, 378.801, 140.2, 378.801]}, - {t: 'C', p: [143.8, 378.801, 144.182, 378.388, 147, 379.001]}, - {t: 'C', p: [151.6, 380.001, 151.2, 378.001, 157.8, 379.201]}, - {t: 'C', p: [160.44, 379.681, 163, 378.801, 165.8, 380.001]}, - {t: 'C', p: [168.6, 381.201, 171.8, 380.401, 173, 378.401]}, - {t: 'C', p: [174.2, 376.401, 179, 372.201, 179, 372.201]}, - {t: 'C', p: [179, 372.201, 166.2, 374.001, 163.4, 374.801]}, - {t: 'C', p: [163.4, 374.801, 141, 376.001, 133, 373.601]}, - {t: 'z', p: []}]}, - -{f: '#ffc', s: {c: '#000', w: 0.5}, - p: [{t: 'M', p: [177.6, 373.801]}, - {t: 'C', p: [177.6, 373.801, 171.15, 377.301, 170.75, 379.701]}, - {t: 'C', p: [170.35, 382.101, 176, 385.801, 176, 385.801]}, - {t: 'C', p: [176, 385.801, 178.75, 390.401, 179.35, 388.001]}, - {t: 'C', p: [179.95, 385.601, 178.4, 374.201, 177.6, 373.801]}, - {t: 'z', p: []}]}, - -{f: '#ffc', s: {c: '#000', w: 0.5}, - p: [{t: 'M', p: [140.115, 379.265]}, - {t: 'C', p: [140.115, 379.265, 147.122, 390.453, 147.339, 379.242]}, - {t: 'C', p: [147.339, 379.242, 147.896, 377.984, 146.136, 377.962]}, - {t: 'C', p: [140.061, 377.886, 141.582, 373.784, 140.115, 379.265]}, - {t: 'z', p: []}]}, - -{f: '#ffc', s: {c: '#000', w: 0.5}, - p: [{t: 'M', p: [147.293, 379.514]}, - {t: 'C', p: [147.293, 379.514, 155.214, 390.701, 154.578, 379.421]}, - {t: 'C', p: [154.578, 379.421, 154.585, 379.089, 152.832, 378.936]}, - {t: 'C', p: [148.085, 378.522, 148.43, 374.004, 147.293, 379.514]}, - {t: 'z', p: []}]}, - -{f: '#ffc', s: {c: '#000', w: 0.5}, - p: [{t: 'M', p: [154.506, 379.522]}, - {t: 'C', p: [154.506, 379.522, 162.466, 390.15, 161.797, 380.484]}, - {t: 'C', p: [161.797, 380.484, 161.916, 379.251, 160.262, 378.95]}, - {t: 'C', p: [156.37, 378.244, 156.159, 374.995, 154.506, 379.522]}, - {t: 'z', p: []}]}, - -{f: '#ffc', s: {c: '#000', w: 0.5}, - p: [{t: 'M', p: [161.382, 379.602]}, - {t: 'C', p: [161.382, 379.602, 169.282, 391.163, 169.63, 381.382]}, - {t: 'C', p: [169.63, 381.382, 171.274, 380.004, 169.528, 379.782]}, - {t: 'C', p: [163.71, 379.042, 164.508, 374.588, 161.382, 379.602]}, - {t: 'z', p: []}]}, - -{f: '#e5e5b2', s: null, p: [{t: 'M', p: [125.208, 383.132]}, - {t: 'L', p: [117.55, 381.601]}, - {t: 'C', p: [114.95, 376.601, 112.85, 370.451, 112.85, 370.451]}, - {t: 'C', p: [112.85, 370.451, 119.2, 371.451, 131.7, 374.251]}, - {t: 'C', p: [131.7, 374.251, 132.576, 377.569, 134.048, 383.364]}, - {t: 'L', p: [125.208, 383.132]}, - {t: 'z', p: []}]}, - -{f: '#e5e5b2', s: null, p: [{t: 'M', p: [190.276, 378.47]}, - {t: 'C', p: [188.61, 375.964, 187.293, 374.206, 186.643, 373.8]}, - {t: 'C', p: [183.63, 371.917, 187.773, 372.294, 188.902, 372.294]}, - {t: 'C', p: [188.902, 372.294, 205.473, 372.294, 207.356, 373.047]}, - {t: 'C', p: [207.356, 373.047, 207.88, 375.289, 208.564, 378.68]}, - {t: 'C', p: [208.564, 378.68, 198.476, 376.67, 190.276, 378.47]}, - {t: 'z', p: []}]}, - -{f: '#cc7226', s: null, p: [{t: 'M', p: [243.88, 240.321]}, - {t: 'C', p: [271.601, 244.281, 297.121, 208.641, 298.881, 198.96]}, - {t: 'C', p: [300.641, 189.28, 290.521, 177.4, 290.521, 177.4]}, - {t: 'C', p: [291.841, 174.32, 287.001, 160.24, 281.721, 151]}, - {t: 'C', p: [276.441, 141.76, 260.54, 142.734, 243, 141.76]}, - {t: 'C', p: [227.16, 140.88, 208.68, 164.2, 207.36, 165.96]}, - {t: 'C', p: [206.04, 167.72, 212.2, 206.001, 213.52, 211.721]}, - {t: 'C', p: [214.84, 217.441, 212.2, 243.841, 212.2, 243.841]}, - {t: 'C', p: [246.44, 234.741, 216.16, 236.361, 243.88, 240.321]}, - {t: 'z', p: []}]}, - -{f: '#ea8e51', s: null, p: [{t: 'M', p: [208.088, 166.608]}, - {t: 'C', p: [206.792, 168.336, 212.84, 205.921, 214.136, 211.537]}, - {t: 'C', p: [215.432, 217.153, 212.84, 243.073, 212.84, 243.073]}, - {t: 'C', p: [245.512, 234.193, 216.728, 235.729, 243.944, 239.617]}, - {t: 'C', p: [271.161, 243.505, 296.217, 208.513, 297.945, 199.008]}, - {t: 'C', p: [299.673, 189.504, 289.737, 177.84, 289.737, 177.84]}, - {t: 'C', p: [291.033, 174.816, 286.281, 160.992, 281.097, 151.92]}, - {t: 'C', p: [275.913, 142.848, 260.302, 143.805, 243.08, 142.848]}, - {t: 'C', p: [227.528, 141.984, 209.384, 164.88, 208.088, 166.608]}, - {t: 'z', p: []}]}, - -{f: '#efaa7c', s: null, p: [{t: 'M', p: [208.816, 167.256]}, - {t: 'C', p: [207.544, 168.952, 213.48, 205.841, 214.752, 211.353]}, - {t: 'C', p: [216.024, 216.865, 213.48, 242.305, 213.48, 242.305]}, - {t: 'C', p: [244.884, 233.145, 217.296, 235.097, 244.008, 238.913]}, - {t: 'C', p: [270.721, 242.729, 295.313, 208.385, 297.009, 199.056]}, - {t: 'C', p: [298.705, 189.728, 288.953, 178.28, 288.953, 178.28]}, - {t: 'C', p: [290.225, 175.312, 285.561, 161.744, 280.473, 152.84]}, - {t: 'C', p: [275.385, 143.936, 260.063, 144.875, 243.16, 143.936]}, - {t: 'C', p: [227.896, 143.088, 210.088, 165.56, 208.816, 167.256]}, - {t: 'z', p: []}]}, - -{f: '#f4c6a8', s: null, p: [{t: 'M', p: [209.544, 167.904]}, - {t: 'C', p: [208.296, 169.568, 214.12, 205.761, 215.368, 211.169]}, - {t: 'C', p: [216.616, 216.577, 214.12, 241.537, 214.12, 241.537]}, - {t: 'C', p: [243.556, 232.497, 217.864, 234.465, 244.072, 238.209]}, - {t: 'C', p: [270.281, 241.953, 294.409, 208.257, 296.073, 199.105]}, - {t: 'C', p: [297.737, 189.952, 288.169, 178.72, 288.169, 178.72]}, - {t: 'C', p: [289.417, 175.808, 284.841, 162.496, 279.849, 153.76]}, - {t: 'C', p: [274.857, 145.024, 259.824, 145.945, 243.24, 145.024]}, - {t: 'C', p: [228.264, 144.192, 210.792, 166.24, 209.544, 167.904]}, - {t: 'z', p: []}]}, - -{f: '#f9e2d3', s: null, p: [{t: 'M', p: [210.272, 168.552]}, - {t: 'C', p: [209.048, 170.184, 214.76, 205.681, 215.984, 210.985]}, - {t: 'C', p: [217.208, 216.289, 214.76, 240.769, 214.76, 240.769]}, - {t: 'C', p: [242.628, 231.849, 218.432, 233.833, 244.136, 237.505]}, - {t: 'C', p: [269.841, 241.177, 293.505, 208.129, 295.137, 199.152]}, - {t: 'C', p: [296.769, 190.176, 287.385, 179.16, 287.385, 179.16]}, - {t: 'C', p: [288.609, 176.304, 284.121, 163.248, 279.225, 154.68]}, - {t: 'C', p: [274.329, 146.112, 259.585, 147.015, 243.32, 146.112]}, - {t: 'C', p: [228.632, 145.296, 211.496, 166.92, 210.272, 168.552]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: null, p: [{t: 'M', p: [244.2, 236.8]}, - {t: 'C', p: [269.4, 240.4, 292.601, 208, 294.201, 199.2]}, - {t: 'C', p: [295.801, 190.4, 286.601, 179.6, 286.601, 179.6]}, - {t: 'C', p: [287.801, 176.8, 283.4, 164, 278.6, 155.6]}, - {t: 'C', p: [273.8, 147.2, 259.346, 148.086, 243.4, 147.2]}, - {t: 'C', p: [229, 146.4, 212.2, 167.6, 211, 169.2]}, - {t: 'C', p: [209.8, 170.8, 215.4, 205.6, 216.6, 210.8]}, - {t: 'C', p: [217.8, 216, 215.4, 240, 215.4, 240]}, - {t: 'C', p: [240.9, 231.4, 219, 233.2, 244.2, 236.8]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [290.601, 202.8]}, - {t: 'C', p: [290.601, 202.8, 262.8, 210.4, 251.2, 208.8]}, - {t: 'C', p: [251.2, 208.8, 235.4, 202.2, 226.6, 224]}, - {t: 'C', p: [226.6, 224, 223, 231.2, 221, 233.2]}, - {t: 'C', p: [219, 235.2, 290.601, 202.8, 290.601, 202.8]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [294.401, 200.6]}, - {t: 'C', p: [294.401, 200.6, 265.4, 212.8, 255.4, 212.4]}, - {t: 'C', p: [255.4, 212.4, 239, 207.8, 230.6, 222.4]}, - {t: 'C', p: [230.6, 222.4, 222.2, 231.6, 219, 233.2]}, - {t: 'C', p: [219, 233.2, 218.6, 234.8, 225, 230.8]}, - {t: 'L', p: [235.4, 236]}, - {t: 'C', p: [235.4, 236, 250.2, 245.6, 259.8, 229.6]}, - {t: 'C', p: [259.8, 229.6, 263.8, 218.4, 263.8, 216.4]}, - {t: 'C', p: [263.8, 214.4, 285, 208.8, 286.601, 208.4]}, - {t: 'C', p: [288.201, 208, 294.801, 203.8, 294.401, 200.6]}, - {t: 'z', p: []}]}, - -{f: '#99cc32', s: null, p: [{t: 'M', p: [247, 236.514]}, - {t: 'C', p: [240.128, 236.514, 231.755, 232.649, 231.755, 226.4]}, - {t: 'C', p: [231.755, 220.152, 240.128, 213.887, 247, 213.887]}, - {t: 'C', p: [253.874, 213.887, 259.446, 218.952, 259.446, 225.2]}, - {t: 'C', p: [259.446, 231.449, 253.874, 236.514, 247, 236.514]}, - {t: 'z', p: []}]}, - -{f: '#659900', s: null, p: [{t: 'M', p: [243.377, 219.83]}, - {t: 'C', p: [238.531, 220.552, 233.442, 222.055, 233.514, 221.839]}, - {t: 'C', p: [235.054, 217.22, 241.415, 213.887, 247, 213.887]}, - {t: 'C', p: [251.296, 213.887, 255.084, 215.865, 257.32, 218.875]}, - {t: 'C', p: [257.32, 218.875, 252.004, 218.545, 243.377, 219.83]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: null, p: [{t: 'M', p: [255.4, 219.6]}, - {t: 'C', p: [255.4, 219.6, 251, 216.4, 251, 218.6]}, - {t: 'C', p: [251, 218.6, 254.6, 223, 255.4, 219.6]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [245.4, 227.726]}, - {t: 'C', p: [242.901, 227.726, 240.875, 225.7, 240.875, 223.2]}, - {t: 'C', p: [240.875, 220.701, 242.901, 218.675, 245.4, 218.675]}, - {t: 'C', p: [247.9, 218.675, 249.926, 220.701, 249.926, 223.2]}, - {t: 'C', p: [249.926, 225.7, 247.9, 227.726, 245.4, 227.726]}, - {t: 'z', p: []}]}, - -{f: '#cc7226', s: null, p: [{t: 'M', p: [141.4, 214.4]}, - {t: 'C', p: [141.4, 214.4, 138.2, 193.2, 140.6, 188.8]}, - {t: 'C', p: [140.6, 188.8, 151.4, 178.8, 151, 175.2]}, - {t: 'C', p: [151, 175.2, 150.6, 157.2, 149.4, 156.4]}, - {t: 'C', p: [148.2, 155.6, 140.6, 149.6, 134.6, 156]}, - {t: 'C', p: [134.6, 156, 124.2, 174, 125, 180.4]}, - {t: 'L', p: [125, 182.4]}, - {t: 'C', p: [125, 182.4, 117.4, 182, 115.8, 184]}, - {t: 'C', p: [115.8, 184, 114.6, 189.2, 113.4, 189.6]}, - {t: 'C', p: [113.4, 189.6, 110.6, 192, 112.6, 194.8]}, - {t: 'C', p: [112.6, 194.8, 110.6, 197.2, 111, 201.2]}, - {t: 'L', p: [118.6, 205.2]}, - {t: 'C', p: [118.6, 205.2, 120.6, 219.6, 131.4, 224.8]}, - {t: 'C', p: [136.236, 227.129, 139.4, 220.4, 141.4, 214.4]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: null, p: [{t: 'M', p: [140.4, 212.56]}, - {t: 'C', p: [140.4, 212.56, 137.52, 193.48, 139.68, 189.52]}, - {t: 'C', p: [139.68, 189.52, 149.4, 180.52, 149.04, 177.28]}, - {t: 'C', p: [149.04, 177.28, 148.68, 161.08, 147.6, 160.36]}, - {t: 'C', p: [146.52, 159.64, 139.68, 154.24, 134.28, 160]}, - {t: 'C', p: [134.28, 160, 124.92, 176.2, 125.64, 181.96]}, - {t: 'L', p: [125.64, 183.76]}, - {t: 'C', p: [125.64, 183.76, 118.8, 183.4, 117.36, 185.2]}, - {t: 'C', p: [117.36, 185.2, 116.28, 189.88, 115.2, 190.24]}, - {t: 'C', p: [115.2, 190.24, 112.68, 192.4, 114.48, 194.92]}, - {t: 'C', p: [114.48, 194.92, 112.68, 197.08, 113.04, 200.68]}, - {t: 'L', p: [119.88, 204.28]}, - {t: 'C', p: [119.88, 204.28, 121.68, 217.24, 131.4, 221.92]}, - {t: 'C', p: [135.752, 224.015, 138.6, 217.96, 140.4, 212.56]}, - {t: 'z', p: []}]}, - -{f: '#eb955c', s: null, p: [{t: 'M', p: [148.95, 157.39]}, - {t: 'C', p: [147.86, 156.53, 140.37, 150.76, 134.52, 157]}, - {t: 'C', p: [134.52, 157, 124.38, 174.55, 125.16, 180.79]}, - {t: 'L', p: [125.16, 182.74]}, - {t: 'C', p: [125.16, 182.74, 117.75, 182.35, 116.19, 184.3]}, - {t: 'C', p: [116.19, 184.3, 115.02, 189.37, 113.85, 189.76]}, - {t: 'C', p: [113.85, 189.76, 111.12, 192.1, 113.07, 194.83]}, - {t: 'C', p: [113.07, 194.83, 111.12, 197.17, 111.51, 201.07]}, - {t: 'L', p: [118.92, 204.97]}, - {t: 'C', p: [118.92, 204.97, 120.87, 219.01, 131.4, 224.08]}, - {t: 'C', p: [136.114, 226.35, 139.2, 219.79, 141.15, 213.94]}, - {t: 'C', p: [141.15, 213.94, 138.03, 193.27, 140.37, 188.98]}, - {t: 'C', p: [140.37, 188.98, 150.9, 179.23, 150.51, 175.72]}, - {t: 'C', p: [150.51, 175.72, 150.12, 158.17, 148.95, 157.39]}, - {t: 'z', p: []}]}, - -{f: '#f2b892', s: null, p: [{t: 'M', p: [148.5, 158.38]}, - {t: 'C', p: [147.52, 157.46, 140.14, 151.92, 134.44, 158]}, - {t: 'C', p: [134.44, 158, 124.56, 175.1, 125.32, 181.18]}, - {t: 'L', p: [125.32, 183.08]}, - {t: 'C', p: [125.32, 183.08, 118.1, 182.7, 116.58, 184.6]}, - {t: 'C', p: [116.58, 184.6, 115.44, 189.54, 114.3, 189.92]}, - {t: 'C', p: [114.3, 189.92, 111.64, 192.2, 113.54, 194.86]}, - {t: 'C', p: [113.54, 194.86, 111.64, 197.14, 112.02, 200.94]}, - {t: 'L', p: [119.24, 204.74]}, - {t: 'C', p: [119.24, 204.74, 121.14, 218.42, 131.4, 223.36]}, - {t: 'C', p: [135.994, 225.572, 139, 219.18, 140.9, 213.48]}, - {t: 'C', p: [140.9, 213.48, 137.86, 193.34, 140.14, 189.16]}, - {t: 'C', p: [140.14, 189.16, 150.4, 179.66, 150.02, 176.24]}, - {t: 'C', p: [150.02, 176.24, 149.64, 159.14, 148.5, 158.38]}, - {t: 'z', p: []}]}, - -{f: '#f8dcc8', s: null, p: [{t: 'M', p: [148.05, 159.37]}, - {t: 'C', p: [147.18, 158.39, 139.91, 153.08, 134.36, 159]}, - {t: 'C', p: [134.36, 159, 124.74, 175.65, 125.48, 181.57]}, - {t: 'L', p: [125.48, 183.42]}, - {t: 'C', p: [125.48, 183.42, 118.45, 183.05, 116.97, 184.9]}, - {t: 'C', p: [116.97, 184.9, 115.86, 189.71, 114.75, 190.08]}, - {t: 'C', p: [114.75, 190.08, 112.16, 192.3, 114.01, 194.89]}, - {t: 'C', p: [114.01, 194.89, 112.16, 197.11, 112.53, 200.81]}, - {t: 'L', p: [119.56, 204.51]}, - {t: 'C', p: [119.56, 204.51, 121.41, 217.83, 131.4, 222.64]}, - {t: 'C', p: [135.873, 224.794, 138.8, 218.57, 140.65, 213.02]}, - {t: 'C', p: [140.65, 213.02, 137.69, 193.41, 139.91, 189.34]}, - {t: 'C', p: [139.91, 189.34, 149.9, 180.09, 149.53, 176.76]}, - {t: 'C', p: [149.53, 176.76, 149.16, 160.11, 148.05, 159.37]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: null, p: [{t: 'M', p: [140.4, 212.46]}, - {t: 'C', p: [140.4, 212.46, 137.52, 193.48, 139.68, 189.52]}, - {t: 'C', p: [139.68, 189.52, 149.4, 180.52, 149.04, 177.28]}, - {t: 'C', p: [149.04, 177.28, 148.68, 161.08, 147.6, 160.36]}, - {t: 'C', p: [146.84, 159.32, 139.68, 154.24, 134.28, 160]}, - {t: 'C', p: [134.28, 160, 124.92, 176.2, 125.64, 181.96]}, - {t: 'L', p: [125.64, 183.76]}, - {t: 'C', p: [125.64, 183.76, 118.8, 183.4, 117.36, 185.2]}, - {t: 'C', p: [117.36, 185.2, 116.28, 189.88, 115.2, 190.24]}, - {t: 'C', p: [115.2, 190.24, 112.68, 192.4, 114.48, 194.92]}, - {t: 'C', p: [114.48, 194.92, 112.68, 197.08, 113.04, 200.68]}, - {t: 'L', p: [119.88, 204.28]}, - {t: 'C', p: [119.88, 204.28, 121.68, 217.24, 131.4, 221.92]}, - {t: 'C', p: [135.752, 224.015, 138.6, 217.86, 140.4, 212.46]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [137.3, 206.2]}, - {t: 'C', p: [137.3, 206.2, 115.7, 196, 114.8, 195.2]}, - {t: 'C', p: [114.8, 195.2, 123.9, 203.4, 124.7, 203.4]}, - {t: 'C', p: [125.5, 203.4, 137.3, 206.2, 137.3, 206.2]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [120.2, 200]}, - {t: 'C', p: [120.2, 200, 138.6, 203.6, 138.6, 208]}, - {t: 'C', p: [138.6, 210.912, 138.357, 224.331, 133, 222.8]}, - {t: 'C', p: [124.6, 220.4, 128.2, 206, 120.2, 200]}, - {t: 'z', p: []}]}, - -{f: '#99cc32', s: null, p: [{t: 'M', p: [128.6, 203.8]}, - {t: 'C', p: [128.6, 203.8, 137.578, 205.274, 138.6, 208]}, - {t: 'C', p: [139.2, 209.6, 139.863, 217.908, 134.4, 219]}, - {t: 'C', p: [129.848, 219.911, 127.618, 209.69, 128.6, 203.8]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [214.595, 246.349]}, - {t: 'C', p: [214.098, 244.607, 215.409, 244.738, 217.2, 244.2]}, - {t: 'C', p: [219.2, 243.6, 231.4, 239.8, 232.2, 237.2]}, - {t: 'C', p: [233, 234.6, 246.2, 239, 246.2, 239]}, - {t: 'C', p: [248, 239.8, 252.4, 242.4, 252.4, 242.4]}, - {t: 'C', p: [257.2, 243.6, 263.8, 244, 263.8, 244]}, - {t: 'C', p: [266.2, 245, 269.6, 247.8, 269.6, 247.8]}, - {t: 'C', p: [284.2, 258, 296.601, 250.8, 296.601, 250.8]}, - {t: 'C', p: [316.601, 244.2, 310.601, 227, 310.601, 227]}, - {t: 'C', p: [307.601, 218, 310.801, 214.6, 310.801, 214.6]}, - {t: 'C', p: [311.001, 210.8, 318.201, 217.2, 318.201, 217.2]}, - {t: 'C', p: [320.801, 221.4, 321.601, 226.4, 321.601, 226.4]}, - {t: 'C', p: [329.601, 237.6, 326.201, 219.8, 326.201, 219.8]}, - {t: 'C', p: [326.401, 218.8, 323.601, 215.2, 323.601, 214]}, - {t: 'C', p: [323.601, 212.8, 321.801, 209.4, 321.801, 209.4]}, - {t: 'C', p: [318.801, 206, 321.201, 199, 321.201, 199]}, - {t: 'C', p: [323.001, 185.2, 320.801, 187, 320.801, 187]}, - {t: 'C', p: [319.601, 185.2, 310.401, 195.2, 310.401, 195.2]}, - {t: 'C', p: [308.201, 198.6, 302.201, 200.2, 302.201, 200.2]}, - {t: 'C', p: [299.401, 202, 296.001, 200.6, 296.001, 200.6]}, - {t: 'C', p: [293.401, 200.2, 287.801, 207.2, 287.801, 207.2]}, - {t: 'C', p: [290.601, 207, 293.001, 211.4, 295.401, 211.6]}, - {t: 'C', p: [297.801, 211.8, 299.601, 209.2, 301.201, 208.6]}, - {t: 'C', p: [302.801, 208, 305.601, 213.8, 305.601, 213.8]}, - {t: 'C', p: [306.001, 216.4, 300.401, 221.2, 300.401, 221.2]}, - {t: 'C', p: [300.001, 225.8, 298.401, 224.2, 298.401, 224.2]}, - {t: 'C', p: [295.401, 223.6, 294.201, 227.4, 293.201, 232]}, - {t: 'C', p: [292.201, 236.6, 288.001, 237, 288.001, 237]}, - {t: 'C', p: [286.401, 244.4, 285.2, 241.4, 285.2, 241.4]}, - {t: 'C', p: [285, 235.8, 279, 241.6, 279, 241.6]}, - {t: 'C', p: [277.8, 243.6, 273.2, 241.4, 273.2, 241.4]}, - {t: 'C', p: [266.4, 239.4, 268.8, 237.4, 268.8, 237.4]}, - {t: 'C', p: [270.6, 235.2, 281.8, 237.4, 281.8, 237.4]}, - {t: 'C', p: [284, 235.8, 276, 231.8, 276, 231.8]}, - {t: 'C', p: [275.4, 230, 276.4, 225.6, 276.4, 225.6]}, - {t: 'C', p: [277.6, 222.4, 284.4, 216.8, 284.4, 216.8]}, - {t: 'C', p: [293.801, 215.6, 291.001, 214, 291.001, 214]}, - {t: 'C', p: [284.801, 208.8, 279, 216.4, 279, 216.4]}, - {t: 'C', p: [276.8, 222.6, 259.4, 237.6, 259.4, 237.6]}, - {t: 'C', p: [254.6, 241, 257.2, 234.2, 253.2, 237.6]}, - {t: 'C', p: [249.2, 241, 228.6, 232, 228.6, 232]}, - {t: 'C', p: [217.038, 230.807, 214.306, 246.549, 210.777, 243.429]}, - {t: 'C', p: [210.777, 243.429, 216.195, 251.949, 214.595, 246.349]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [409.401, 80]}, - {t: 'C', p: [409.401, 80, 383.801, 88, 381.001, 106.8]}, - {t: 'C', p: [381.001, 106.8, 378.601, 129.6, 399.001, 147.2]}, - {t: 'C', p: [399.001, 147.2, 399.401, 153.6, 401.401, 156.8]}, - {t: 'C', p: [401.401, 156.8, 399.801, 161.6, 418.601, 154]}, - {t: 'L', p: [445.801, 145.6]}, - {t: 'C', p: [445.801, 145.6, 452.201, 143.2, 457.401, 134.4]}, - {t: 'C', p: [462.601, 125.6, 477.801, 106.8, 474.201, 81.6]}, - {t: 'C', p: [474.201, 81.6, 475.401, 70.4, 469.401, 70]}, - {t: 'C', p: [469.401, 70, 461.001, 68.4, 453.801, 76]}, - {t: 'C', p: [453.801, 76, 447.001, 79.2, 444.601, 78.8]}, - {t: 'L', p: [409.401, 80]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [464.022, 79.01]}, - {t: 'C', p: [464.022, 79.01, 466.122, 70.08, 461.282, 74.92]}, - {t: 'C', p: [461.282, 74.92, 454.242, 80.64, 446.761, 80.64]}, - {t: 'C', p: [446.761, 80.64, 432.241, 82.84, 427.841, 96.04]}, - {t: 'C', p: [427.841, 96.04, 423.881, 122.88, 431.801, 128.6]}, - {t: 'C', p: [431.801, 128.6, 436.641, 136.08, 443.681, 129.48]}, - {t: 'C', p: [450.722, 122.88, 466.222, 92.65, 464.022, 79.01]}, - {t: 'z', p: []}]}, - -{f: '#323232', s: null, p: [{t: 'M', p: [463.648, 79.368]}, - {t: 'C', p: [463.648, 79.368, 465.738, 70.624, 460.986, 75.376]}, - {t: 'C', p: [460.986, 75.376, 454.074, 80.992, 446.729, 80.992]}, - {t: 'C', p: [446.729, 80.992, 432.473, 83.152, 428.153, 96.112]}, - {t: 'C', p: [428.153, 96.112, 424.265, 122.464, 432.041, 128.08]}, - {t: 'C', p: [432.041, 128.08, 436.793, 135.424, 443.705, 128.944]}, - {t: 'C', p: [450.618, 122.464, 465.808, 92.76, 463.648, 79.368]}, - {t: 'z', p: []}]}, - -{f: '#666', s: null, p: [{t: 'M', p: [463.274, 79.726]}, - {t: 'C', p: [463.274, 79.726, 465.354, 71.168, 460.69, 75.832]}, - {t: 'C', p: [460.69, 75.832, 453.906, 81.344, 446.697, 81.344]}, - {t: 'C', p: [446.697, 81.344, 432.705, 83.464, 428.465, 96.184]}, - {t: 'C', p: [428.465, 96.184, 424.649, 122.048, 432.281, 127.56]}, - {t: 'C', p: [432.281, 127.56, 436.945, 134.768, 443.729, 128.408]}, - {t: 'C', p: [450.514, 122.048, 465.394, 92.87, 463.274, 79.726]}, - {t: 'z', p: []}]}, - -{f: '#999', s: null, p: [{t: 'M', p: [462.9, 80.084]}, - {t: 'C', p: [462.9, 80.084, 464.97, 71.712, 460.394, 76.288]}, - {t: 'C', p: [460.394, 76.288, 453.738, 81.696, 446.665, 81.696]}, - {t: 'C', p: [446.665, 81.696, 432.937, 83.776, 428.777, 96.256]}, - {t: 'C', p: [428.777, 96.256, 425.033, 121.632, 432.521, 127.04]}, - {t: 'C', p: [432.521, 127.04, 437.097, 134.112, 443.753, 127.872]}, - {t: 'C', p: [450.41, 121.632, 464.98, 92.98, 462.9, 80.084]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [462.526, 80.442]}, - {t: 'C', p: [462.526, 80.442, 464.586, 72.256, 460.098, 76.744]}, - {t: 'C', p: [460.098, 76.744, 453.569, 82.048, 446.633, 82.048]}, - {t: 'C', p: [446.633, 82.048, 433.169, 84.088, 429.089, 96.328]}, - {t: 'C', p: [429.089, 96.328, 425.417, 121.216, 432.761, 126.52]}, - {t: 'C', p: [432.761, 126.52, 437.249, 133.456, 443.777, 127.336]}, - {t: 'C', p: [450.305, 121.216, 464.566, 93.09, 462.526, 80.442]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: null, p: [{t: 'M', p: [462.151, 80.8]}, - {t: 'C', p: [462.151, 80.8, 464.201, 72.8, 459.801, 77.2]}, - {t: 'C', p: [459.801, 77.2, 453.401, 82.4, 446.601, 82.4]}, - {t: 'C', p: [446.601, 82.4, 433.401, 84.4, 429.401, 96.4]}, - {t: 'C', p: [429.401, 96.4, 425.801, 120.8, 433.001, 126]}, - {t: 'C', p: [433.001, 126, 437.401, 132.8, 443.801, 126.8]}, - {t: 'C', p: [450.201, 120.8, 464.151, 93.2, 462.151, 80.8]}, - {t: 'z', p: []}]}, - -{f: '#992600', s: null, p: [{t: 'M', p: [250.6, 284]}, - {t: 'C', p: [250.6, 284, 230.2, 264.8, 222.2, 264]}, - {t: 'C', p: [222.2, 264, 187.8, 260, 173, 278]}, - {t: 'C', p: [173, 278, 190.6, 257.6, 218.2, 263.2]}, - {t: 'C', p: [218.2, 263.2, 196.6, 258.8, 184.2, 262]}, - {t: 'C', p: [184.2, 262, 167.4, 262, 157.8, 276]}, - {t: 'L', p: [155, 280.8]}, - {t: 'C', p: [155, 280.8, 159, 266, 177.4, 260]}, - {t: 'C', p: [177.4, 260, 200.2, 255.2, 211, 260]}, - {t: 'C', p: [211, 260, 189.4, 253.2, 179.4, 255.2]}, - {t: 'C', p: [179.4, 255.2, 149, 252.8, 136.2, 279.2]}, - {t: 'C', p: [136.2, 279.2, 140.2, 264.8, 155, 257.6]}, - {t: 'C', p: [155, 257.6, 168.6, 248.8, 189, 251.6]}, - {t: 'C', p: [189, 251.6, 203.4, 254.8, 208.6, 257.2]}, - {t: 'C', p: [213.8, 259.6, 212.6, 256.8, 204.2, 252]}, - {t: 'C', p: [204.2, 252, 198.6, 242, 184.6, 242.4]}, - {t: 'C', p: [184.6, 242.4, 141.8, 246, 131.4, 258]}, - {t: 'C', p: [131.4, 258, 145, 246.8, 155.4, 244]}, - {t: 'C', p: [155.4, 244, 177.8, 236, 186.2, 236.8]}, - {t: 'C', p: [186.2, 236.8, 211, 237.8, 218.6, 233.8]}, - {t: 'C', p: [218.6, 233.8, 207.4, 238.8, 210.6, 242]}, - {t: 'C', p: [213.8, 245.2, 220.6, 252.8, 220.6, 254]}, - {t: 'C', p: [220.6, 255.2, 244.8, 277.3, 248.4, 281.7]}, - {t: 'L', p: [250.6, 284]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [389, 478]}, - {t: 'C', p: [389, 478, 373.5, 441.5, 361, 432]}, - {t: 'C', p: [361, 432, 387, 448, 390.5, 466]}, - {t: 'C', p: [390.5, 466, 390.5, 476, 389, 478]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [436, 485.5]}, - {t: 'C', p: [436, 485.5, 409.5, 430.5, 391, 406.5]}, - {t: 'C', p: [391, 406.5, 434.5, 444, 439.5, 470.5]}, - {t: 'L', p: [440, 476]}, - {t: 'L', p: [437, 473.5]}, - {t: 'C', p: [437, 473.5, 436.5, 482.5, 436, 485.5]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [492.5, 437]}, - {t: 'C', p: [492.5, 437, 430, 377.5, 428.5, 375]}, - {t: 'C', p: [428.5, 375, 489, 441, 492, 448.5]}, - {t: 'C', p: [492, 448.5, 490, 439.5, 492.5, 437]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [304, 480.5]}, - {t: 'C', p: [304, 480.5, 323.5, 428.5, 342.5, 451]}, - {t: 'C', p: [342.5, 451, 357.5, 461, 357, 464]}, - {t: 'C', p: [357, 464, 353, 457.5, 335, 458]}, - {t: 'C', p: [335, 458, 316, 455, 304, 480.5]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [494.5, 353]}, - {t: 'C', p: [494.5, 353, 449.5, 324.5, 442, 323]}, - {t: 'C', p: [430.193, 320.639, 491.5, 352, 496.5, 362.5]}, - {t: 'C', p: [496.5, 362.5, 498.5, 360, 494.5, 353]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [343.801, 459.601]}, - {t: 'C', p: [343.801, 459.601, 364.201, 457.601, 371.001, 450.801]}, - {t: 'L', p: [375.401, 454.401]}, - {t: 'L', p: [393.001, 416.001]}, - {t: 'L', p: [396.601, 421.201]}, - {t: 'C', p: [396.601, 421.201, 411.001, 406.401, 410.201, 398.401]}, - {t: 'C', p: [409.401, 390.401, 423.001, 404.401, 423.001, 404.401]}, - {t: 'C', p: [423.001, 404.401, 422.201, 392.801, 429.401, 399.601]}, - {t: 'C', p: [429.401, 399.601, 427.001, 384.001, 435.401, 392.001]}, - {t: 'C', p: [435.401, 392.001, 424.864, 361.844, 447.401, 387.601]}, - {t: 'C', p: [453.001, 394.001, 448.601, 387.201, 448.601, 387.201]}, - {t: 'C', p: [448.601, 387.201, 422.601, 339.201, 444.201, 353.601]}, - {t: 'C', p: [444.201, 353.601, 446.201, 330.801, 445.001, 326.401]}, - {t: 'C', p: [443.801, 322.001, 441.801, 299.6, 437.001, 294.4]}, - {t: 'C', p: [432.201, 289.2, 437.401, 287.6, 443.001, 292.8]}, - {t: 'C', p: [443.001, 292.8, 431.801, 268.8, 445.001, 280.8]}, - {t: 'C', p: [445.001, 280.8, 441.401, 265.6, 437.001, 262.8]}, - {t: 'C', p: [437.001, 262.8, 431.401, 245.6, 446.601, 256.4]}, - {t: 'C', p: [446.601, 256.4, 442.201, 244, 439.001, 240.8]}, - {t: 'C', p: [439.001, 240.8, 427.401, 213.2, 434.601, 218]}, - {t: 'L', p: [439.001, 221.6]}, - {t: 'C', p: [439.001, 221.6, 432.201, 207.6, 438.601, 212]}, - {t: 'C', p: [445.001, 216.4, 445.001, 216, 445.001, 216]}, - {t: 'C', p: [445.001, 216, 423.801, 182.8, 444.201, 200.4]}, - {t: 'C', p: [444.201, 200.4, 436.042, 186.482, 432.601, 179.6]}, - {t: 'C', p: [432.601, 179.6, 413.801, 159.2, 428.201, 165.6]}, - {t: 'L', p: [433.001, 167.2]}, - {t: 'C', p: [433.001, 167.2, 424.201, 157.2, 416.201, 155.6]}, - {t: 'C', p: [408.201, 154, 418.601, 147.6, 425.001, 149.6]}, - {t: 'C', p: [431.401, 151.6, 447.001, 159.2, 447.001, 159.2]}, - {t: 'C', p: [447.001, 159.2, 459.801, 178, 463.801, 178.4]}, - {t: 'C', p: [463.801, 178.4, 443.801, 170.8, 449.801, 178.8]}, - {t: 'C', p: [449.801, 178.8, 464.201, 192.8, 457.001, 192.4]}, - {t: 'C', p: [457.001, 192.4, 451.001, 199.6, 455.801, 208.4]}, - {t: 'C', p: [455.801, 208.4, 437.342, 190.009, 452.201, 215.6]}, - {t: 'L', p: [459.001, 232]}, - {t: 'C', p: [459.001, 232, 434.601, 207.2, 445.801, 229.2]}, - {t: 'C', p: [445.801, 229.2, 463.001, 252.8, 465.001, 253.2]}, - {t: 'C', p: [467.001, 253.6, 471.401, 262.4, 471.401, 262.4]}, - {t: 'L', p: [467.001, 260.4]}, - {t: 'L', p: [472.201, 269.2]}, - {t: 'C', p: [472.201, 269.2, 461.001, 257.2, 467.001, 270.4]}, - {t: 'L', p: [472.601, 284.8]}, - {t: 'C', p: [472.601, 284.8, 452.201, 262.8, 465.801, 292.4]}, - {t: 'C', p: [465.801, 292.4, 449.401, 287.2, 458.201, 304.4]}, - {t: 'C', p: [458.201, 304.4, 456.601, 320.401, 457.001, 325.601]}, - {t: 'C', p: [457.401, 330.801, 458.601, 359.201, 454.201, 367.201]}, - {t: 'C', p: [449.801, 375.201, 460.201, 394.401, 462.201, 398.401]}, - {t: 'C', p: [464.201, 402.401, 467.801, 413.201, 459.001, 404.001]}, - {t: 'C', p: [450.201, 394.801, 454.601, 400.401, 456.601, 409.201]}, - {t: 'C', p: [458.601, 418.001, 464.601, 433.601, 463.801, 439.201]}, - {t: 'C', p: [463.801, 439.201, 462.601, 440.401, 459.401, 436.801]}, - {t: 'C', p: [459.401, 436.801, 444.601, 414.001, 446.201, 428.401]}, - {t: 'C', p: [446.201, 428.401, 445.001, 436.401, 441.801, 445.201]}, - {t: 'C', p: [441.801, 445.201, 438.601, 456.001, 438.601, 447.201]}, - {t: 'C', p: [438.601, 447.201, 435.401, 430.401, 432.601, 438.001]}, - {t: 'C', p: [429.801, 445.601, 426.201, 451.601, 423.401, 454.001]}, - {t: 'C', p: [420.601, 456.401, 415.401, 433.601, 414.201, 444.001]}, - {t: 'C', p: [414.201, 444.001, 402.201, 431.601, 397.401, 448.001]}, - {t: 'L', p: [385.801, 464.401]}, - {t: 'C', p: [385.801, 464.401, 385.401, 452.001, 384.201, 458.001]}, - {t: 'C', p: [384.201, 458.001, 354.201, 464.001, 343.801, 459.601]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [309.401, 102.8]}, - {t: 'C', p: [309.401, 102.8, 297.801, 94.8, 293.801, 95.2]}, - {t: 'C', p: [289.801, 95.6, 321.401, 86.4, 362.601, 114]}, - {t: 'C', p: [362.601, 114, 367.401, 116.8, 371.001, 116.4]}, - {t: 'C', p: [371.001, 116.4, 374.201, 118.8, 371.401, 122.4]}, - {t: 'C', p: [371.401, 122.4, 362.601, 132, 373.801, 143.2]}, - {t: 'C', p: [373.801, 143.2, 392.201, 150, 386.601, 141.2]}, - {t: 'C', p: [386.601, 141.2, 397.401, 145.2, 399.801, 149.2]}, - {t: 'C', p: [402.201, 153.2, 401.001, 149.2, 401.001, 149.2]}, - {t: 'C', p: [401.001, 149.2, 394.601, 142, 388.601, 136.8]}, - {t: 'C', p: [388.601, 136.8, 383.401, 134.8, 380.601, 126.4]}, - {t: 'C', p: [377.801, 118, 375.401, 108, 379.801, 104.8]}, - {t: 'C', p: [379.801, 104.8, 375.801, 109.2, 376.601, 105.2]}, - {t: 'C', p: [377.401, 101.2, 381.001, 97.6, 382.601, 97.2]}, - {t: 'C', p: [384.201, 96.8, 400.601, 81, 407.401, 80.6]}, - {t: 'C', p: [407.401, 80.6, 398.201, 82, 395.201, 81]}, - {t: 'C', p: [392.201, 80, 365.601, 68.6, 359.601, 67.4]}, - {t: 'C', p: [359.601, 67.4, 342.801, 60.8, 354.801, 62.8]}, - {t: 'C', p: [354.801, 62.8, 390.601, 66.6, 408.801, 79.8]}, - {t: 'C', p: [408.801, 79.8, 401.601, 71.4, 383.201, 64.4]}, - {t: 'C', p: [383.201, 64.4, 361.001, 51.8, 325.801, 56.8]}, - {t: 'C', p: [325.801, 56.8, 308.001, 60, 300.201, 61.8]}, - {t: 'C', p: [300.201, 61.8, 297.601, 61.2, 297.001, 60.8]}, - {t: 'C', p: [296.401, 60.4, 284.6, 51.4, 257, 58.4]}, - {t: 'C', p: [257, 58.4, 240, 63, 231.4, 67.8]}, - {t: 'C', p: [231.4, 67.8, 216.2, 69, 212.6, 72.2]}, - {t: 'C', p: [212.6, 72.2, 194, 86.8, 192, 87.6]}, - {t: 'C', p: [190, 88.4, 178.6, 96, 177.8, 96.4]}, - {t: 'C', p: [177.8, 96.4, 202.4, 89.8, 204.8, 87.4]}, - {t: 'C', p: [207.2, 85, 224.6, 82.4, 227, 83.8]}, - {t: 'C', p: [229.4, 85.2, 237.8, 84.6, 228.2, 85.2]}, - {t: 'C', p: [228.2, 85.2, 303.801, 100, 304.601, 102]}, - {t: 'C', p: [305.401, 104, 309.401, 102.8, 309.401, 102.8]}, - {t: 'z', p: []}]}, - -{f: '#cc7226', s: null, p: [{t: 'M', p: [380.801, 93.6]}, - {t: 'C', p: [380.801, 93.6, 370.601, 86.2, 368.601, 86.2]}, - {t: 'C', p: [366.601, 86.2, 354.201, 76, 350.001, 76.4]}, - {t: 'C', p: [345.801, 76.8, 333.601, 66.8, 306.201, 75]}, - {t: 'C', p: [306.201, 75, 305.601, 73, 309.201, 72.2]}, - {t: 'C', p: [309.201, 72.2, 315.601, 70, 316.001, 69.4]}, - {t: 'C', p: [316.001, 69.4, 336.201, 65.2, 343.401, 68.8]}, - {t: 'C', p: [343.401, 68.8, 352.601, 71.4, 358.801, 77.6]}, - {t: 'C', p: [358.801, 77.6, 370.001, 80.8, 373.201, 79.8]}, - {t: 'C', p: [373.201, 79.8, 382.001, 82, 382.401, 83.8]}, - {t: 'C', p: [382.401, 83.8, 388.201, 86.8, 386.401, 89.4]}, - {t: 'C', p: [386.401, 89.4, 386.801, 91, 380.801, 93.6]}, - {t: 'z', p: []}]}, - -{f: '#cc7226', s: null, p: [{t: 'M', p: [368.33, 91.491]}, - {t: 'C', p: [369.137, 92.123, 370.156, 92.221, 370.761, 93.03]}, - {t: 'C', p: [370.995, 93.344, 370.706, 93.67, 370.391, 93.767]}, - {t: 'C', p: [369.348, 94.084, 368.292, 93.514, 367.15, 94.102]}, - {t: 'C', p: [366.748, 94.309, 366.106, 94.127, 365.553, 93.978]}, - {t: 'C', p: [363.921, 93.537, 362.092, 93.512, 360.401, 94.2]}, - {t: 'C', p: [358.416, 93.071, 356.056, 93.655, 353.975, 92.654]}, - {t: 'C', p: [353.917, 92.627, 353.695, 92.973, 353.621, 92.946]}, - {t: 'C', p: [350.575, 91.801, 346.832, 92.084, 344.401, 89.8]}, - {t: 'C', p: [341.973, 89.388, 339.616, 88.926, 337.188, 88.246]}, - {t: 'C', p: [335.37, 87.737, 333.961, 86.748, 332.341, 85.916]}, - {t: 'C', p: [330.964, 85.208, 329.507, 84.686, 327.973, 84.314]}, - {t: 'C', p: [326.11, 83.862, 324.279, 83.974, 322.386, 83.454]}, - {t: 'C', p: [322.293, 83.429, 322.101, 83.773, 322.019, 83.746]}, - {t: 'C', p: [321.695, 83.638, 321.405, 83.055, 321.234, 83.108]}, - {t: 'C', p: [319.553, 83.63, 318.065, 82.658, 316.401, 83]}, - {t: 'C', p: [315.223, 81.776, 313.495, 82.021, 311.949, 81.579]}, - {t: 'C', p: [308.985, 80.731, 305.831, 82.001, 302.801, 81]}, - {t: 'C', p: [306.914, 79.158, 311.601, 80.39, 315.663, 78.321]}, - {t: 'C', p: [317.991, 77.135, 320.653, 78.237, 323.223, 77.477]}, - {t: 'C', p: [323.71, 77.333, 324.401, 77.131, 324.801, 77.8]}, - {t: 'C', p: [324.935, 77.665, 325.117, 77.426, 325.175, 77.454]}, - {t: 'C', p: [327.625, 78.611, 329.94, 79.885, 332.422, 80.951]}, - {t: 'C', p: [332.763, 81.097, 333.295, 80.865, 333.547, 81.067]}, - {t: 'C', p: [335.067, 82.283, 337.01, 82.18, 338.401, 83.4]}, - {t: 'C', p: [340.099, 82.898, 341.892, 83.278, 343.621, 82.654]}, - {t: 'C', p: [343.698, 82.627, 343.932, 82.968, 343.965, 82.946]}, - {t: 'C', p: [345.095, 82.198, 346.25, 82.469, 347.142, 82.773]}, - {t: 'C', p: [347.48, 82.888, 348.143, 83.135, 348.448, 83.209]}, - {t: 'C', p: [349.574, 83.485, 350.43, 83.965, 351.609, 84.148]}, - {t: 'C', p: [351.723, 84.166, 351.908, 83.826, 351.98, 83.854]}, - {t: 'C', p: [353.103, 84.292, 354.145, 84.236, 354.801, 85.4]}, - {t: 'C', p: [354.936, 85.265, 355.101, 85.027, 355.183, 85.054]}, - {t: 'C', p: [356.21, 85.392, 356.859, 86.147, 357.96, 86.388]}, - {t: 'C', p: [358.445, 86.494, 359.057, 87.12, 359.633, 87.296]}, - {t: 'C', p: [362.025, 88.027, 363.868, 89.556, 366.062, 90.451]}, - {t: 'C', p: [366.821, 90.761, 367.697, 90.995, 368.33, 91.491]}, - {t: 'z', p: []}]}, - -{f: '#cc7226', s: null, p: [{t: 'M', p: [291.696, 77.261]}, - {t: 'C', p: [289.178, 75.536, 286.81, 74.43, 284.368, 72.644]}, - {t: 'C', p: [284.187, 72.511, 283.827, 72.681, 283.625, 72.559]}, - {t: 'C', p: [282.618, 71.95, 281.73, 71.369, 280.748, 70.673]}, - {t: 'C', p: [280.209, 70.291, 279.388, 70.302, 278.88, 70.044]}, - {t: 'C', p: [276.336, 68.752, 273.707, 68.194, 271.2, 67]}, - {t: 'C', p: [271.882, 66.362, 273.004, 66.606, 273.6, 65.8]}, - {t: 'C', p: [273.795, 66.08, 274.033, 66.364, 274.386, 66.173]}, - {t: 'C', p: [276.064, 65.269, 277.914, 65.116, 279.59, 65.206]}, - {t: 'C', p: [281.294, 65.298, 283.014, 65.603, 284.789, 65.875]}, - {t: 'C', p: [285.096, 65.922, 285.295, 66.445, 285.618, 66.542]}, - {t: 'C', p: [287.846, 67.205, 290.235, 66.68, 292.354, 67.518]}, - {t: 'C', p: [293.945, 68.147, 295.515, 68.97, 296.754, 70.245]}, - {t: 'C', p: [297.006, 70.505, 296.681, 70.806, 296.401, 71]}, - {t: 'C', p: [296.789, 70.891, 297.062, 71.097, 297.173, 71.41]}, - {t: 'C', p: [297.257, 71.649, 297.257, 71.951, 297.173, 72.19]}, - {t: 'C', p: [297.061, 72.502, 296.782, 72.603, 296.408, 72.654]}, - {t: 'C', p: [295.001, 72.844, 296.773, 71.464, 296.073, 71.912]}, - {t: 'C', p: [294.8, 72.726, 295.546, 74.132, 294.801, 75.4]}, - {t: 'C', p: [294.521, 75.206, 294.291, 74.988, 294.401, 74.6]}, - {t: 'C', p: [294.635, 75.122, 294.033, 75.412, 293.865, 75.728]}, - {t: 'C', p: [293.48, 76.453, 292.581, 77.868, 291.696, 77.261]}, - {t: 'z', p: []}]}, - -{f: '#cc7226', s: null, p: [{t: 'M', p: [259.198, 84.609]}, - {t: 'C', p: [256.044, 83.815, 252.994, 83.93, 249.978, 82.654]}, - {t: 'C', p: [249.911, 82.626, 249.688, 82.973, 249.624, 82.946]}, - {t: 'C', p: [248.258, 82.352, 247.34, 81.386, 246.264, 80.34]}, - {t: 'C', p: [245.351, 79.452, 243.693, 79.839, 242.419, 79.352]}, - {t: 'C', p: [242.095, 79.228, 241.892, 78.716, 241.591, 78.677]}, - {t: 'C', p: [240.372, 78.52, 239.445, 77.571, 238.4, 77]}, - {t: 'C', p: [240.736, 76.205, 243.147, 76.236, 245.609, 75.852]}, - {t: 'C', p: [245.722, 75.834, 245.867, 76.155, 246, 76.155]}, - {t: 'C', p: [246.136, 76.155, 246.266, 75.934, 246.4, 75.8]}, - {t: 'C', p: [246.595, 76.08, 246.897, 76.406, 247.154, 76.152]}, - {t: 'C', p: [247.702, 75.612, 248.258, 75.802, 248.798, 75.842]}, - {t: 'C', p: [248.942, 75.852, 249.067, 76.155, 249.2, 76.155]}, - {t: 'C', p: [249.336, 76.155, 249.467, 75.844, 249.6, 75.844]}, - {t: 'C', p: [249.736, 75.845, 249.867, 76.155, 250, 76.155]}, - {t: 'C', p: [250.136, 76.155, 250.266, 75.934, 250.4, 75.8]}, - {t: 'C', p: [251.092, 76.582, 251.977, 76.028, 252.799, 76.207]}, - {t: 'C', p: [253.837, 76.434, 254.104, 77.582, 255.178, 77.88]}, - {t: 'C', p: [259.893, 79.184, 264.03, 81.329, 268.393, 83.416]}, - {t: 'C', p: [268.7, 83.563, 268.91, 83.811, 268.8, 84.2]}, - {t: 'C', p: [269.067, 84.2, 269.38, 84.112, 269.57, 84.244]}, - {t: 'C', p: [270.628, 84.976, 271.669, 85.524, 272.366, 86.622]}, - {t: 'C', p: [272.582, 86.961, 272.253, 87.368, 272.02, 87.316]}, - {t: 'C', p: [267.591, 86.321, 263.585, 85.713, 259.198, 84.609]}, - {t: 'z', p: []}]}, - -{f: '#cc7226', s: null, p: [{t: 'M', p: [245.338, 128.821]}, - {t: 'C', p: [243.746, 127.602, 243.162, 125.571, 242.034, 123.779]}, - {t: 'C', p: [241.82, 123.439, 242.094, 123.125, 242.411, 123.036]}, - {t: 'C', p: [242.971, 122.877, 243.514, 123.355, 243.923, 123.557]}, - {t: 'C', p: [245.668, 124.419, 247.203, 125.661, 249.2, 125.8]}, - {t: 'C', p: [251.19, 128.034, 255.45, 128.419, 255.457, 131.8]}, - {t: 'C', p: [255.458, 132.659, 254.03, 131.741, 253.6, 132.6]}, - {t: 'C', p: [251.149, 131.597, 248.76, 131.7, 246.38, 130.233]}, - {t: 'C', p: [245.763, 129.852, 246.093, 129.399, 245.338, 128.821]}, - {t: 'z', p: []}]}, - -{f: '#cc7226', s: null, p: [{t: 'M', p: [217.8, 76.244]}, - {t: 'C', p: [217.935, 76.245, 224.966, 76.478, 224.949, 76.592]}, - {t: 'C', p: [224.904, 76.901, 217.174, 77.95, 216.81, 77.78]}, - {t: 'C', p: [216.646, 77.704, 209.134, 80.134, 209, 80]}, - {t: 'C', p: [209.268, 79.865, 217.534, 76.244, 217.8, 76.244]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [233.2, 86]}, - {t: 'C', p: [233.2, 86, 218.4, 87.8, 214, 89]}, - {t: 'C', p: [209.6, 90.2, 191, 97.8, 188, 99.8]}, - {t: 'C', p: [188, 99.8, 174.6, 105.2, 157.6, 125.2]}, - {t: 'C', p: [157.6, 125.2, 165.2, 121.8, 167.4, 119]}, - {t: 'C', p: [167.4, 119, 181, 106.4, 180.8, 109]}, - {t: 'C', p: [180.8, 109, 193, 100.4, 192.4, 102.6]}, - {t: 'C', p: [192.4, 102.6, 216.8, 91.4, 214.8, 94.6]}, - {t: 'C', p: [214.8, 94.6, 236.4, 90, 235.4, 92]}, - {t: 'C', p: [235.4, 92, 254.2, 96.4, 251.4, 96.6]}, - {t: 'C', p: [251.4, 96.6, 245.6, 97.8, 252, 101.4]}, - {t: 'C', p: [252, 101.4, 248.6, 105.8, 243.2, 101.8]}, - {t: 'C', p: [237.8, 97.8, 240.8, 100, 235.8, 101]}, - {t: 'C', p: [235.8, 101, 233.2, 101.8, 228.6, 97.8]}, - {t: 'C', p: [228.6, 97.8, 223, 93.2, 214.2, 96.8]}, - {t: 'C', p: [214.2, 96.8, 183.6, 109.4, 181.6, 110]}, - {t: 'C', p: [181.6, 110, 178, 112.8, 175.6, 116.4]}, - {t: 'C', p: [175.6, 116.4, 169.8, 120.8, 166.8, 122.2]}, - {t: 'C', p: [166.8, 122.2, 154, 133.8, 152.8, 135.2]}, - {t: 'C', p: [152.8, 135.2, 149.4, 140.4, 148.6, 140.8]}, - {t: 'C', p: [148.6, 140.8, 155, 137, 157, 135]}, - {t: 'C', p: [157, 135, 171, 125, 176.4, 124.2]}, - {t: 'C', p: [176.4, 124.2, 180.8, 121.2, 181.6, 119.8]}, - {t: 'C', p: [181.6, 119.8, 196, 110.6, 200.2, 110.6]}, - {t: 'C', p: [200.2, 110.6, 209.4, 115.8, 211.8, 108.8]}, - {t: 'C', p: [211.8, 108.8, 217.6, 107, 223.2, 108.2]}, - {t: 'C', p: [223.2, 108.2, 226.4, 105.6, 225.6, 103.4]}, - {t: 'C', p: [225.6, 103.4, 227.2, 101.6, 228.2, 105.4]}, - {t: 'C', p: [228.2, 105.4, 231.6, 109, 236.4, 107]}, - {t: 'C', p: [236.4, 107, 240.4, 106.8, 238.4, 109.2]}, - {t: 'C', p: [238.4, 109.2, 234, 113, 222.2, 113.2]}, - {t: 'C', p: [222.2, 113.2, 209.8, 113.8, 193.4, 121.4]}, - {t: 'C', p: [193.4, 121.4, 163.6, 131.8, 154.4, 142.2]}, - {t: 'C', p: [154.4, 142.2, 148, 151, 142.6, 152.2]}, - {t: 'C', p: [142.6, 152.2, 136.8, 153, 130.8, 160.4]}, - {t: 'C', p: [130.8, 160.4, 140.6, 154.6, 149.6, 154.6]}, - {t: 'C', p: [149.6, 154.6, 153.6, 152.2, 149.8, 155.8]}, - {t: 'C', p: [149.8, 155.8, 146.2, 163.4, 147.8, 168.8]}, - {t: 'C', p: [147.8, 168.8, 147.2, 174, 146.4, 175.6]}, - {t: 'C', p: [146.4, 175.6, 138.6, 188.4, 138.6, 190.8]}, - {t: 'C', p: [138.6, 193.2, 139.8, 203, 140.2, 203.6]}, - {t: 'C', p: [140.6, 204.2, 139.2, 202, 143, 204.4]}, - {t: 'C', p: [146.8, 206.8, 149.6, 208.4, 150.4, 211.2]}, - {t: 'C', p: [151.2, 214, 148.4, 205.8, 148.2, 204]}, - {t: 'C', p: [148, 202.2, 143.8, 195, 144.6, 192.6]}, - {t: 'C', p: [144.6, 192.6, 145.6, 193.6, 146.4, 195]}, - {t: 'C', p: [146.4, 195, 145.8, 194.4, 146.4, 190.8]}, - {t: 'C', p: [146.4, 190.8, 147.2, 185.6, 148.6, 182.4]}, - {t: 'C', p: [150, 179.2, 152, 175.4, 152.4, 174.6]}, - {t: 'C', p: [152.8, 173.8, 152.8, 168, 154.2, 170.6]}, - {t: 'L', p: [157.6, 173.2]}, - {t: 'C', p: [157.6, 173.2, 154.8, 170.6, 157, 168.4]}, - {t: 'C', p: [157, 168.4, 156, 162.8, 157.8, 160.2]}, - {t: 'C', p: [157.8, 160.2, 164.8, 151.8, 166.4, 150.8]}, - {t: 'C', p: [168, 149.8, 166.6, 150.2, 166.6, 150.2]}, - {t: 'C', p: [166.6, 150.2, 172.6, 146, 166.8, 147.6]}, - {t: 'C', p: [166.8, 147.6, 162.8, 149.2, 159.8, 149.2]}, - {t: 'C', p: [159.8, 149.2, 152.2, 151.2, 156.2, 147]}, - {t: 'C', p: [160.2, 142.8, 170.2, 137.4, 174, 137.6]}, - {t: 'L', p: [174.8, 139.2]}, - {t: 'L', p: [186, 136.8]}, - {t: 'L', p: [184.8, 137.6]}, - {t: 'C', p: [184.8, 137.6, 184.6, 137.4, 188.8, 137]}, - {t: 'C', p: [193, 136.6, 198.8, 138, 200.2, 136.2]}, - {t: 'C', p: [201.6, 134.4, 205, 133.4, 204.6, 134.8]}, - {t: 'C', p: [204.2, 136.2, 204, 138.2, 204, 138.2]}, - {t: 'C', p: [204, 138.2, 209, 132.4, 208.4, 134.6]}, - {t: 'C', p: [207.8, 136.8, 199.6, 142, 198.2, 148.2]}, - {t: 'L', p: [208.6, 140]}, - {t: 'L', p: [212.2, 137]}, - {t: 'C', p: [212.2, 137, 215.8, 139.2, 216, 137.6]}, - {t: 'C', p: [216.2, 136, 220.8, 130.2, 222, 130.4]}, - {t: 'C', p: [223.2, 130.6, 225.2, 127.8, 225, 130.4]}, - {t: 'C', p: [224.8, 133, 232.4, 138.4, 232.4, 138.4]}, - {t: 'C', p: [232.4, 138.4, 235.6, 136.6, 237, 138]}, - {t: 'C', p: [238.4, 139.4, 242.6, 118.2, 242.6, 118.2]}, - {t: 'L', p: [267.6, 107.6]}, - {t: 'L', p: [311.201, 104.2]}, - {t: 'L', p: [294.201, 97.4]}, - {t: 'L', p: [233.2, 86]}, - {t: 'z', p: []}]}, - -{f: null, s: {c: '#4c0000', w: 2}, - p: [{t: 'M', p: [251.4, 285]}, - {t: 'C', p: [251.4, 285, 236.4, 268.2, 228, 265.6]}, - {t: 'C', p: [228, 265.6, 214.6, 258.8, 190, 266.6]}]}, - -{f: null, s: {c: '#4c0000', w: 2}, - p: [{t: 'M', p: [224.8, 264.2]}, - {t: 'C', p: [224.8, 264.2, 199.6, 256.2, 184.2, 260.4]}, - {t: 'C', p: [184.2, 260.4, 165.8, 262.4, 157.4, 276.2]}]}, - -{f: null, s: {c: '#4c0000', w: 2}, - p: [{t: 'M', p: [221.2, 263]}, - {t: 'C', p: [221.2, 263, 204.2, 255.8, 189.4, 253.6]}, - {t: 'C', p: [189.4, 253.6, 172.8, 251, 156.2, 258.2]}, - {t: 'C', p: [156.2, 258.2, 144, 264.2, 138.6, 274.4]}]}, - -{f: null, s: {c: '#4c0000', w: 2}, - p: [{t: 'M', p: [222.2, 263.4]}, - {t: 'C', p: [222.2, 263.4, 206.8, 252.4, 205.8, 251]}, - {t: 'C', p: [205.8, 251, 198.8, 240, 185.8, 239.6]}, - {t: 'C', p: [185.8, 239.6, 164.4, 240.4, 147.2, 248.4]}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [220.895, 254.407]}, - {t: 'C', p: [222.437, 255.87, 249.4, 284.8, 249.4, 284.8]}, - {t: 'C', p: [284.6, 321.401, 256.6, 287.2, 256.6, 287.2]}, - {t: 'C', p: [249, 282.4, 239.8, 263.6, 239.8, 263.6]}, - {t: 'C', p: [238.6, 260.8, 253.8, 270.8, 253.8, 270.8]}, - {t: 'C', p: [257.8, 271.6, 271.4, 290.8, 271.4, 290.8]}, - {t: 'C', p: [264.6, 288.4, 269.4, 295.6, 269.4, 295.6]}, - {t: 'C', p: [272.2, 297.6, 292.601, 313.201, 292.601, 313.201]}, - {t: 'C', p: [296.201, 317.201, 300.201, 318.801, 300.201, 318.801]}, - {t: 'C', p: [314.201, 313.601, 307.801, 326.801, 307.801, 326.801]}, - {t: 'C', p: [310.201, 333.601, 315.801, 322.001, 315.801, 322.001]}, - {t: 'C', p: [327.001, 305.2, 310.601, 307.601, 310.601, 307.601]}, - {t: 'C', p: [280.6, 310.401, 273.8, 294.4, 273.8, 294.4]}, - {t: 'C', p: [271.4, 292, 280.2, 294.4, 280.2, 294.4]}, - {t: 'C', p: [288.601, 296.4, 273, 282, 273, 282]}, - {t: 'C', p: [275.4, 282, 284.6, 288.8, 284.6, 288.8]}, - {t: 'C', p: [295.001, 298, 297.001, 296, 297.001, 296]}, - {t: 'C', p: [315.001, 287.2, 325.401, 294.8, 325.401, 294.8]}, - {t: 'C', p: [327.401, 296.4, 321.801, 303.2, 323.401, 308.401]}, - {t: 'C', p: [325.001, 313.601, 329.801, 326.001, 329.801, 326.001]}, - {t: 'C', p: [327.401, 327.601, 327.801, 338.401, 327.801, 338.401]}, - {t: 'C', p: [344.601, 361.601, 335.001, 359.601, 335.001, 359.601]}, - {t: 'C', p: [319.401, 359.201, 334.201, 366.801, 334.201, 366.801]}, - {t: 'C', p: [337.401, 368.801, 346.201, 376.001, 346.201, 376.001]}, - {t: 'C', p: [343.401, 374.801, 341.801, 380.001, 341.801, 380.001]}, - {t: 'C', p: [346.601, 384.001, 343.801, 388.801, 343.801, 388.801]}, - {t: 'C', p: [337.801, 390.001, 336.601, 394.001, 336.601, 394.001]}, - {t: 'C', p: [343.401, 402.001, 333.401, 402.401, 333.401, 402.401]}, - {t: 'C', p: [337.001, 406.801, 332.201, 418.801, 332.201, 418.801]}, - {t: 'C', p: [327.401, 418.801, 321.001, 424.401, 321.001, 424.401]}, - {t: 'C', p: [323.401, 429.201, 313.001, 434.801, 313.001, 434.801]}, - {t: 'C', p: [304.601, 436.401, 307.401, 443.201, 307.401, 443.201]}, - {t: 'C', p: [299.401, 449.201, 297.001, 465.201, 297.001, 465.201]}, - {t: 'C', p: [296.201, 475.601, 293.801, 478.801, 299.001, 476.801]}, - {t: 'C', p: [304.201, 474.801, 303.401, 462.401, 303.401, 462.401]}, - {t: 'C', p: [298.601, 446.801, 341.401, 430.801, 341.401, 430.801]}, - {t: 'C', p: [345.401, 429.201, 346.201, 424.001, 346.201, 424.001]}, - {t: 'C', p: [348.201, 424.401, 357.001, 432.001, 357.001, 432.001]}, - {t: 'C', p: [364.601, 443.201, 365.001, 434.001, 365.001, 434.001]}, - {t: 'C', p: [366.201, 430.401, 364.601, 424.401, 364.601, 424.401]}, - {t: 'C', p: [370.601, 402.801, 356.601, 396.401, 356.601, 396.401]}, - {t: 'C', p: [346.601, 362.801, 360.601, 371.201, 360.601, 371.201]}, - {t: 'C', p: [363.401, 376.801, 374.201, 382.001, 374.201, 382.001]}, - {t: 'L', p: [377.801, 379.601]}, - {t: 'C', p: [376.201, 374.801, 384.601, 368.801, 384.601, 368.801]}, - {t: 'C', p: [387.401, 375.201, 393.401, 367.201, 393.401, 367.201]}, - {t: 'C', p: [397.001, 342.801, 409.401, 357.201, 409.401, 357.201]}, - {t: 'C', p: [413.401, 358.401, 414.601, 351.601, 414.601, 351.601]}, - {t: 'C', p: [418.201, 341.201, 414.601, 327.601, 414.601, 327.601]}, - {t: 'C', p: [418.201, 327.201, 427.801, 333.201, 427.801, 333.201]}, - {t: 'C', p: [430.601, 329.601, 421.401, 312.801, 425.401, 315.201]}, - {t: 'C', p: [429.401, 317.601, 433.801, 319.201, 433.801, 319.201]}, - {t: 'C', p: [434.601, 317.201, 424.601, 304.801, 424.601, 304.801]}, - {t: 'C', p: [420.201, 302, 415.001, 281.6, 415.001, 281.6]}, - {t: 'C', p: [422.201, 285.2, 412.201, 270, 412.201, 270]}, - {t: 'C', p: [412.201, 266.8, 418.201, 255.6, 418.201, 255.6]}, - {t: 'C', p: [417.401, 248.8, 418.201, 249.2, 418.201, 249.2]}, - {t: 'C', p: [421.001, 250.4, 429.001, 252, 422.201, 245.6]}, - {t: 'C', p: [415.401, 239.2, 423.001, 234.4, 423.001, 234.4]}, - {t: 'C', p: [427.401, 231.6, 413.801, 232, 413.801, 232]}, - {t: 'C', p: [408.601, 227.6, 409.001, 223.6, 409.001, 223.6]}, - {t: 'C', p: [417.001, 225.6, 402.601, 211.2, 400.201, 207.6]}, - {t: 'C', p: [397.801, 204, 407.401, 198.8, 407.401, 198.8]}, - {t: 'C', p: [420.601, 195.2, 409.001, 192, 409.001, 192]}, - {t: 'C', p: [389.401, 192.4, 400.201, 181.6, 400.201, 181.6]}, - {t: 'C', p: [406.201, 182, 404.601, 179.6, 404.601, 179.6]}, - {t: 'C', p: [399.401, 178.4, 389.801, 172, 389.801, 172]}, - {t: 'C', p: [385.801, 168.4, 389.401, 169.2, 389.401, 169.2]}, - {t: 'C', p: [406.201, 170.4, 377.401, 159.2, 377.401, 159.2]}, - {t: 'C', p: [385.401, 159.2, 367.401, 148.8, 367.401, 148.8]}, - {t: 'C', p: [365.401, 147.2, 362.201, 139.6, 362.201, 139.6]}, - {t: 'C', p: [356.201, 134.4, 351.401, 127.6, 351.401, 127.6]}, - {t: 'C', p: [351.001, 123.2, 346.201, 118.4, 346.201, 118.4]}, - {t: 'C', p: [334.601, 104.8, 329.001, 105.2, 329.001, 105.2]}, - {t: 'C', p: [314.201, 101.6, 309.001, 102.4, 309.001, 102.4]}, - {t: 'L', p: [256.2, 106.8]}, - {t: 'C', p: [229.8, 119.6, 237.6, 140.6, 237.6, 140.6]}, - {t: 'C', p: [244, 149, 253.2, 145.2, 253.2, 145.2]}, - {t: 'C', p: [257.8, 139, 269.4, 141.2, 269.4, 141.2]}, - {t: 'C', p: [289.801, 144.4, 287.201, 140.8, 287.201, 140.8]}, - {t: 'C', p: [284.801, 136.2, 268.6, 130, 268.4, 129.4]}, - {t: 'C', p: [268.2, 128.8, 259.4, 125.4, 259.4, 125.4]}, - {t: 'C', p: [256.4, 124.2, 252, 115, 252, 115]}, - {t: 'C', p: [248.8, 111.6, 264.6, 117.4, 264.6, 117.4]}, - {t: 'C', p: [263.4, 118.4, 270.8, 122.4, 270.8, 122.4]}, - {t: 'C', p: [288.201, 121.4, 298.801, 132.2, 298.801, 132.2]}, - {t: 'C', p: [309.601, 148.8, 309.801, 140.6, 309.801, 140.6]}, - {t: 'C', p: [312.601, 131.2, 300.801, 110, 300.801, 110]}, - {t: 'C', p: [301.201, 108, 309.401, 114.6, 309.401, 114.6]}, - {t: 'C', p: [310.801, 112.6, 311.601, 118.4, 311.601, 118.4]}, - {t: 'C', p: [311.801, 120.8, 315.601, 128.8, 315.601, 128.8]}, - {t: 'C', p: [318.401, 141.8, 322.001, 134.4, 322.001, 134.4]}, - {t: 'L', p: [326.601, 143.8]}, - {t: 'C', p: [328.001, 146.4, 322.001, 154, 322.001, 154]}, - {t: 'C', p: [321.801, 156.8, 322.601, 156.6, 317.001, 164.2]}, - {t: 'C', p: [311.401, 171.8, 314.801, 176.2, 314.801, 176.2]}, - {t: 'C', p: [313.401, 182.8, 322.201, 182.4, 322.201, 182.4]}, - {t: 'C', p: [324.801, 184.6, 328.201, 184.6, 328.201, 184.6]}, - {t: 'C', p: [330.001, 186.6, 332.401, 186, 332.401, 186]}, - {t: 'C', p: [334.001, 182.2, 340.201, 184.2, 340.201, 184.2]}, - {t: 'C', p: [341.601, 181.8, 349.801, 181.4, 349.801, 181.4]}, - {t: 'C', p: [350.801, 178.8, 351.201, 177.2, 354.601, 176.6]}, - {t: 'C', p: [358.001, 176, 333.401, 133, 333.401, 133]}, - {t: 'C', p: [339.801, 132.2, 331.601, 119.8, 331.601, 119.8]}, - {t: 'C', p: [329.401, 113.2, 340.801, 127.8, 343.001, 129.2]}, - {t: 'C', p: [345.201, 130.6, 346.201, 132.8, 344.601, 132.6]}, - {t: 'C', p: [343.001, 132.4, 341.201, 134.6, 342.601, 134.8]}, - {t: 'C', p: [344.001, 135, 357.001, 150, 360.401, 160.2]}, - {t: 'C', p: [363.801, 170.4, 369.801, 174.4, 376.001, 180.4]}, - {t: 'C', p: [382.201, 186.4, 381.401, 210.6, 381.401, 210.6]}, - {t: 'C', p: [381.001, 219.4, 387.001, 230, 387.001, 230]}, - {t: 'C', p: [389.001, 233.8, 384.801, 252, 384.801, 252]}, - {t: 'C', p: [382.801, 254.2, 384.201, 255, 384.201, 255]}, - {t: 'C', p: [385.201, 256.2, 392.001, 269.4, 392.001, 269.4]}, - {t: 'C', p: [390.201, 269.2, 393.801, 272.8, 393.801, 272.8]}, - {t: 'C', p: [399.001, 278.8, 392.601, 275.8, 392.601, 275.8]}, - {t: 'C', p: [386.601, 274.2, 393.601, 284, 393.601, 284]}, - {t: 'C', p: [394.801, 285.8, 385.801, 281.2, 385.801, 281.2]}, - {t: 'C', p: [376.601, 280.6, 388.201, 287.8, 388.201, 287.8]}, - {t: 'C', p: [396.801, 295, 385.401, 290.6, 385.401, 290.6]}, - {t: 'C', p: [380.801, 288.8, 384.001, 295.6, 384.001, 295.6]}, - {t: 'C', p: [387.201, 297.2, 404.401, 304.2, 404.401, 304.2]}, - {t: 'C', p: [404.801, 308.001, 401.801, 313.001, 401.801, 313.001]}, - {t: 'C', p: [402.201, 317.001, 400.001, 320.401, 400.001, 320.401]}, - {t: 'C', p: [398.801, 328.601, 398.201, 329.401, 398.201, 329.401]}, - {t: 'C', p: [394.001, 329.601, 386.601, 343.401, 386.601, 343.401]}, - {t: 'C', p: [384.801, 346.001, 374.601, 358.001, 374.601, 358.001]}, - {t: 'C', p: [372.601, 365.001, 354.601, 357.801, 354.601, 357.801]}, - {t: 'C', p: [348.001, 361.201, 350.001, 357.801, 350.001, 357.801]}, - {t: 'C', p: [349.601, 355.601, 354.401, 349.601, 354.401, 349.601]}, - {t: 'C', p: [361.401, 347.001, 358.801, 336.201, 358.801, 336.201]}, - {t: 'C', p: [362.801, 334.801, 351.601, 332.001, 351.801, 330.801]}, - {t: 'C', p: [352.001, 329.601, 357.801, 328.201, 357.801, 328.201]}, - {t: 'C', p: [365.801, 326.201, 361.401, 323.801, 361.401, 323.801]}, - {t: 'C', p: [360.801, 319.801, 363.801, 314.201, 363.801, 314.201]}, - {t: 'C', p: [375.401, 313.401, 363.801, 297.2, 363.801, 297.2]}, - {t: 'C', p: [353.001, 289.6, 352.001, 283.8, 352.001, 283.8]}, - {t: 'C', p: [364.601, 275.6, 356.401, 263.2, 356.601, 259.6]}, - {t: 'C', p: [356.801, 256, 358.001, 234.4, 358.001, 234.4]}, - {t: 'C', p: [356.001, 228.2, 353.001, 214.6, 353.001, 214.6]}, - {t: 'C', p: [355.201, 209.4, 362.601, 196.8, 362.601, 196.8]}, - {t: 'C', p: [365.401, 192.6, 374.201, 187.8, 372.001, 184.8]}, - {t: 'C', p: [369.801, 181.8, 362.001, 183.6, 362.001, 183.6]}, - {t: 'C', p: [354.201, 182.2, 354.801, 187.4, 354.801, 187.4]}, - {t: 'C', p: [353.201, 188.4, 352.401, 193.4, 352.401, 193.4]}, - {t: 'C', p: [351.68, 201.333, 342.801, 207.6, 342.801, 207.6]}, - {t: 'C', p: [331.601, 213.8, 340.801, 217.8, 340.801, 217.8]}, - {t: 'C', p: [346.801, 224.4, 337.001, 224.6, 337.001, 224.6]}, - {t: 'C', p: [326.001, 222.8, 334.201, 233, 334.201, 233]}, - {t: 'C', p: [345.001, 245.8, 342.001, 248.6, 342.001, 248.6]}, - {t: 'C', p: [331.801, 249.6, 344.401, 258.8, 344.401, 258.8]}, - {t: 'C', p: [344.401, 258.8, 343.601, 256.8, 343.801, 258.6]}, - {t: 'C', p: [344.001, 260.4, 347.001, 264.6, 347.801, 266.6]}, - {t: 'C', p: [348.601, 268.6, 344.601, 268.8, 344.601, 268.8]}, - {t: 'C', p: [345.201, 278.4, 329.801, 274.2, 329.801, 274.2]}, - {t: 'C', p: [329.801, 274.2, 329.801, 274.2, 328.201, 274.4]}, - {t: 'C', p: [326.601, 274.6, 315.401, 273.8, 309.601, 271.6]}, - {t: 'C', p: [303.801, 269.4, 297.001, 269.4, 297.001, 269.4]}, - {t: 'C', p: [297.001, 269.4, 293.001, 271.2, 285.4, 271]}, - {t: 'C', p: [277.8, 270.8, 269.8, 273.6, 269.8, 273.6]}, - {t: 'C', p: [265.4, 273.2, 274, 268.8, 274.2, 269]}, - {t: 'C', p: [274.4, 269.2, 280, 263.6, 272, 264.2]}, - {t: 'C', p: [250.203, 265.835, 239.4, 255.6, 239.4, 255.6]}, - {t: 'C', p: [237.4, 254.2, 234.8, 251.4, 234.8, 251.4]}, - {t: 'C', p: [224.8, 249.4, 236.2, 263.8, 236.2, 263.8]}, - {t: 'C', p: [237.4, 265.2, 236, 266.2, 236, 266.2]}, - {t: 'C', p: [235.2, 264.6, 227.4, 259.2, 227.4, 259.2]}, - {t: 'C', p: [224.589, 258.227, 223.226, 256.893, 220.895, 254.407]}, - {t: 'z', p: []}]}, - -{f: '#4c0000', s: null, p: [{t: 'M', p: [197, 242.8]}, - {t: 'C', p: [197, 242.8, 208.6, 248.4, 211.2, 251.2]}, - {t: 'C', p: [213.8, 254, 227.8, 265.4, 227.8, 265.4]}, - {t: 'C', p: [227.8, 265.4, 222.4, 263.4, 219.8, 261.6]}, - {t: 'C', p: [217.2, 259.8, 206.4, 251.6, 206.4, 251.6]}, - {t: 'C', p: [206.4, 251.6, 202.6, 245.6, 197, 242.8]}, - {t: 'z', p: []}]}, - -{f: '#99cc32', s: null, p: [{t: 'M', p: [138.991, 211.603]}, - {t: 'C', p: [139.328, 211.455, 138.804, 208.743, 138.6, 208.2]}, - {t: 'C', p: [137.578, 205.474, 128.6, 204, 128.6, 204]}, - {t: 'C', p: [128.373, 205.365, 128.318, 206.961, 128.424, 208.599]}, - {t: 'C', p: [128.424, 208.599, 133.292, 214.118, 138.991, 211.603]}, - {t: 'z', p: []}]}, - -{f: '#659900', s: null, p: [{t: 'M', p: [138.991, 211.403]}, - {t: 'C', p: [138.542, 211.561, 138.976, 208.669, 138.8, 208.2]}, - {t: 'C', p: [137.778, 205.474, 128.6, 203.9, 128.6, 203.9]}, - {t: 'C', p: [128.373, 205.265, 128.318, 206.861, 128.424, 208.499]}, - {t: 'C', p: [128.424, 208.499, 132.692, 213.618, 138.991, 211.403]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [134.6, 211.546]}, - {t: 'C', p: [133.975, 211.546, 133.469, 210.406, 133.469, 209]}, - {t: 'C', p: [133.469, 207.595, 133.975, 206.455, 134.6, 206.455]}, - {t: 'C', p: [135.225, 206.455, 135.732, 207.595, 135.732, 209]}, - {t: 'C', p: [135.732, 210.406, 135.225, 211.546, 134.6, 211.546]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [134.6, 209]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [89, 309.601]}, - {t: 'C', p: [89, 309.601, 83.4, 319.601, 108.2, 313.601]}, - {t: 'C', p: [108.2, 313.601, 122.2, 312.401, 124.6, 310.001]}, - {t: 'C', p: [125.8, 310.801, 134.166, 313.734, 137, 314.401]}, - {t: 'C', p: [143.8, 316.001, 152.2, 306, 152.2, 306]}, - {t: 'C', p: [152.2, 306, 156.8, 295.5, 159.6, 295.5]}, - {t: 'C', p: [162.4, 295.5, 159.2, 297.1, 159.2, 297.1]}, - {t: 'C', p: [159.2, 297.1, 152.6, 307.201, 153, 308.801]}, - {t: 'C', p: [153, 308.801, 147.8, 328.801, 131.8, 329.601]}, - {t: 'C', p: [131.8, 329.601, 115.65, 330.551, 117, 336.401]}, - {t: 'C', p: [117, 336.401, 125.8, 334.001, 128.2, 336.401]}, - {t: 'C', p: [128.2, 336.401, 139, 336.001, 131, 342.401]}, - {t: 'L', p: [124.2, 354.001]}, - {t: 'C', p: [124.2, 354.001, 124.34, 357.919, 114.2, 354.401]}, - {t: 'C', p: [104.4, 351.001, 94.1, 338.101, 94.1, 338.101]}, - {t: 'C', p: [94.1, 338.101, 78.15, 323.551, 89, 309.601]}, - {t: 'z', p: []}]}, - -{f: '#e59999', s: null, p: [{t: 'M', p: [87.8, 313.601]}, - {t: 'C', p: [87.8, 313.601, 85.8, 323.201, 122.6, 312.801]}, - {t: 'C', p: [122.6, 312.801, 127, 312.801, 129.4, 313.601]}, - {t: 'C', p: [131.8, 314.401, 143.8, 317.201, 145.8, 316.001]}, - {t: 'C', p: [145.8, 316.001, 138.6, 329.601, 127, 328.001]}, - {t: 'C', p: [127, 328.001, 113.8, 329.601, 114.2, 334.401]}, - {t: 'C', p: [114.2, 334.401, 118.2, 341.601, 123, 344.001]}, - {t: 'C', p: [123, 344.001, 125.8, 346.401, 125.4, 349.601]}, - {t: 'C', p: [125, 352.801, 122.2, 354.401, 120.2, 355.201]}, - {t: 'C', p: [118.2, 356.001, 115, 352.801, 113.4, 352.801]}, - {t: 'C', p: [111.8, 352.801, 103.4, 346.401, 99, 341.601]}, - {t: 'C', p: [94.6, 336.801, 86.2, 324.801, 86.6, 322.001]}, - {t: 'C', p: [87, 319.201, 87.8, 313.601, 87.8, 313.601]}, - {t: 'z', p: []}]}, - -{f: '#b26565', s: null, p: [{t: 'M', p: [91, 331.051]}, - {t: 'C', p: [93.6, 335.001, 96.8, 339.201, 99, 341.601]}, - {t: 'C', p: [103.4, 346.401, 111.8, 352.801, 113.4, 352.801]}, - {t: 'C', p: [115, 352.801, 118.2, 356.001, 120.2, 355.201]}, - {t: 'C', p: [122.2, 354.401, 125, 352.801, 125.4, 349.601]}, - {t: 'C', p: [125.8, 346.401, 123, 344.001, 123, 344.001]}, - {t: 'C', p: [119.934, 342.468, 117.194, 338.976, 115.615, 336.653]}, - {t: 'C', p: [115.615, 336.653, 115.8, 339.201, 110.6, 338.401]}, - {t: 'C', p: [105.4, 337.601, 100.2, 334.801, 98.6, 331.601]}, - {t: 'C', p: [97, 328.401, 94.6, 326.001, 96.2, 329.601]}, - {t: 'C', p: [97.8, 333.201, 100.2, 336.801, 101.8, 337.201]}, - {t: 'C', p: [103.4, 337.601, 103, 338.801, 100.6, 338.401]}, - {t: 'C', p: [98.2, 338.001, 95.4, 337.601, 91, 332.401]}, - {t: 'z', p: []}]}, - -{f: '#992600', s: null, p: [{t: 'M', p: [88.4, 310.001]}, - {t: 'C', p: [88.4, 310.001, 90.2, 296.4, 91.4, 292.4]}, - {t: 'C', p: [91.4, 292.4, 90.6, 285.6, 93, 281.4]}, - {t: 'C', p: [95.4, 277.2, 97.4, 271, 100.4, 265.6]}, - {t: 'C', p: [103.4, 260.2, 103.6, 256.2, 107.6, 254.6]}, - {t: 'C', p: [111.6, 253, 117.6, 244.4, 120.4, 243.4]}, - {t: 'C', p: [123.2, 242.4, 123, 243.2, 123, 243.2]}, - {t: 'C', p: [123, 243.2, 129.8, 228.4, 143.4, 232.4]}, - {t: 'C', p: [143.4, 232.4, 127.2, 229.6, 143, 220.2]}, - {t: 'C', p: [143, 220.2, 138.2, 221.3, 141.5, 214.3]}, - {t: 'C', p: [143.701, 209.632, 143.2, 216.4, 132.2, 228.2]}, - {t: 'C', p: [132.2, 228.2, 127.2, 236.8, 122, 239.8]}, - {t: 'C', p: [116.8, 242.8, 104.8, 249.8, 103.6, 253.6]}, - {t: 'C', p: [102.4, 257.4, 99.2, 263.2, 97.2, 264.8]}, - {t: 'C', p: [95.2, 266.4, 92.4, 270.6, 92, 274]}, - {t: 'C', p: [92, 274, 90.8, 278, 89.4, 279.2]}, - {t: 'C', p: [88, 280.4, 87.8, 283.6, 87.8, 285.6]}, - {t: 'C', p: [87.8, 287.6, 85.8, 290.4, 86, 292.8]}, - {t: 'C', p: [86, 292.8, 86.8, 311.801, 86.4, 313.801]}, - {t: 'L', p: [88.4, 310.001]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: null, p: [{t: 'M', p: [79.8, 314.601]}, - {t: 'C', p: [79.8, 314.601, 77.8, 313.201, 73.4, 319.201]}, - {t: 'C', p: [73.4, 319.201, 80.7, 352.201, 80.7, 353.601]}, - {t: 'C', p: [80.7, 353.601, 81.8, 351.501, 80.5, 344.301]}, - {t: 'C', p: [79.2, 337.101, 78.3, 324.401, 78.3, 324.401]}, - {t: 'L', p: [79.8, 314.601]}, - {t: 'z', p: []}]}, - -{f: '#992600', s: null, p: [{t: 'M', p: [101.4, 254]}, - {t: 'C', p: [101.4, 254, 83.8, 257.2, 84.2, 286.4]}, - {t: 'L', p: [83.4, 311.201]}, - {t: 'C', p: [83.4, 311.201, 82.2, 285.6, 81, 284]}, - {t: 'C', p: [79.8, 282.4, 83.8, 271.2, 80.6, 277.2]}, - {t: 'C', p: [80.6, 277.2, 66.6, 291.2, 74.6, 312.401]}, - {t: 'C', p: [74.6, 312.401, 76.1, 315.701, 73.1, 311.101]}, - {t: 'C', p: [73.1, 311.101, 68.5, 298.5, 69.6, 292.1]}, - {t: 'C', p: [69.6, 292.1, 69.8, 289.9, 71.7, 287.1]}, - {t: 'C', p: [71.7, 287.1, 80.3, 275.4, 83, 273.1]}, - {t: 'C', p: [83, 273.1, 84.8, 258.7, 100.2, 253.5]}, - {t: 'C', p: [100.2, 253.5, 105.9, 251.2, 101.4, 254]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [240.8, 187.8]}, - {t: 'C', p: [241.46, 187.446, 241.451, 186.476, 242.031, 186.303]}, - {t: 'C', p: [243.18, 185.959, 243.344, 184.892, 243.862, 184.108]}, - {t: 'C', p: [244.735, 182.789, 244.928, 181.256, 245.51, 179.765]}, - {t: 'C', p: [245.782, 179.065, 245.809, 178.11, 245.496, 177.45]}, - {t: 'C', p: [244.322, 174.969, 243.62, 172.52, 242.178, 170.094]}, - {t: 'C', p: [241.91, 169.644, 241.648, 168.85, 241.447, 168.252]}, - {t: 'C', p: [240.984, 166.868, 239.727, 165.877, 238.867, 164.557]}, - {t: 'C', p: [238.579, 164.116, 239.104, 163.191, 238.388, 163.107]}, - {t: 'C', p: [237.491, 163.002, 236.042, 162.422, 235.809, 163.448]}, - {t: 'C', p: [235.221, 166.035, 236.232, 168.558, 237.2, 171]}, - {t: 'C', p: [236.418, 171.692, 236.752, 172.613, 236.904, 173.38]}, - {t: 'C', p: [237.614, 176.986, 236.416, 180.338, 235.655, 183.812]}, - {t: 'C', p: [235.632, 183.916, 235.974, 184.114, 235.946, 184.176]}, - {t: 'C', p: [234.724, 186.862, 233.272, 189.307, 231.453, 191.688]}, - {t: 'C', p: [230.695, 192.68, 229.823, 193.596, 229.326, 194.659]}, - {t: 'C', p: [228.958, 195.446, 228.55, 196.412, 228.8, 197.4]}, - {t: 'C', p: [225.365, 200.18, 223.115, 204.025, 220.504, 207.871]}, - {t: 'C', p: [220.042, 208.551, 220.333, 209.76, 220.884, 210.029]}, - {t: 'C', p: [221.697, 210.427, 222.653, 209.403, 223.123, 208.557]}, - {t: 'C', p: [223.512, 207.859, 223.865, 207.209, 224.356, 206.566]}, - {t: 'C', p: [224.489, 206.391, 224.31, 205.972, 224.445, 205.851]}, - {t: 'C', p: [227.078, 203.504, 228.747, 200.568, 231.2, 198.2]}, - {t: 'C', p: [233.15, 197.871, 234.687, 196.873, 236.435, 195.86]}, - {t: 'C', p: [236.743, 195.681, 237.267, 195.93, 237.557, 195.735]}, - {t: 'C', p: [239.31, 194.558, 239.308, 192.522, 239.414, 190.612]}, - {t: 'C', p: [239.464, 189.728, 239.66, 188.411, 240.8, 187.8]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [231.959, 183.334]}, - {t: 'C', p: [232.083, 183.257, 231.928, 182.834, 232.037, 182.618]}, - {t: 'C', p: [232.199, 182.294, 232.602, 182.106, 232.764, 181.782]}, - {t: 'C', p: [232.873, 181.566, 232.71, 181.186, 232.846, 181.044]}, - {t: 'C', p: [235.179, 178.597, 235.436, 175.573, 234.4, 172.6]}, - {t: 'C', p: [235.424, 171.98, 235.485, 170.718, 235.06, 169.871]}, - {t: 'C', p: [234.207, 168.171, 234.014, 166.245, 233.039, 164.702]}, - {t: 'C', p: [232.237, 163.433, 230.659, 162.189, 229.288, 163.492]}, - {t: 'C', p: [228.867, 163.892, 228.546, 164.679, 228.824, 165.391]}, - {t: 'C', p: [228.888, 165.554, 229.173, 165.7, 229.146, 165.782]}, - {t: 'C', p: [229.039, 166.106, 228.493, 166.33, 228.487, 166.602]}, - {t: 'C', p: [228.457, 168.098, 227.503, 169.609, 228.133, 170.938]}, - {t: 'C', p: [228.905, 172.567, 229.724, 174.424, 230.4, 176.2]}, - {t: 'C', p: [229.166, 178.316, 230.199, 180.765, 228.446, 182.642]}, - {t: 'C', p: [228.31, 182.788, 228.319, 183.174, 228.441, 183.376]}, - {t: 'C', p: [228.733, 183.862, 229.139, 184.268, 229.625, 184.56]}, - {t: 'C', p: [229.827, 184.681, 230.175, 184.683, 230.375, 184.559]}, - {t: 'C', p: [230.953, 184.197, 231.351, 183.71, 231.959, 183.334]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [294.771, 173.023]}, - {t: 'C', p: [296.16, 174.815, 296.45, 177.61, 294.401, 179]}, - {t: 'C', p: [294.951, 182.309, 298.302, 180.33, 300.401, 179.8]}, - {t: 'C', p: [300.292, 179.412, 300.519, 179.068, 300.802, 179.063]}, - {t: 'C', p: [301.859, 179.048, 302.539, 178.016, 303.601, 178.2]}, - {t: 'C', p: [304.035, 176.643, 305.673, 175.941, 306.317, 174.561]}, - {t: 'C', p: [308.043, 170.866, 307.452, 166.593, 304.868, 163.347]}, - {t: 'C', p: [304.666, 163.093, 304.883, 162.576, 304.759, 162.214]}, - {t: 'C', p: [304.003, 160.003, 301.935, 159.688, 300.001, 159]}, - {t: 'C', p: [298.824, 155.125, 298.163, 151.094, 296.401, 147.4]}, - {t: 'C', p: [294.787, 147.15, 294.089, 145.411, 292.752, 144.691]}, - {t: 'C', p: [291.419, 143.972, 290.851, 145.551, 290.892, 146.597]}, - {t: 'C', p: [290.899, 146.802, 291.351, 147.026, 291.181, 147.391]}, - {t: 'C', p: [291.105, 147.555, 290.845, 147.666, 290.845, 147.8]}, - {t: 'C', p: [290.846, 147.935, 291.067, 148.066, 291.201, 148.2]}, - {t: 'C', p: [290.283, 149.02, 288.86, 149.497, 288.565, 150.642]}, - {t: 'C', p: [287.611, 154.352, 290.184, 157.477, 291.852, 160.678]}, - {t: 'C', p: [292.443, 161.813, 291.707, 163.084, 290.947, 164.292]}, - {t: 'C', p: [290.509, 164.987, 290.617, 166.114, 290.893, 166.97]}, - {t: 'C', p: [291.645, 169.301, 293.236, 171.04, 294.771, 173.023]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [257.611, 191.409]}, - {t: 'C', p: [256.124, 193.26, 252.712, 195.829, 255.629, 197.757]}, - {t: 'C', p: [255.823, 197.886, 256.193, 197.89, 256.366, 197.756]}, - {t: 'C', p: [258.387, 196.191, 260.39, 195.288, 262.826, 194.706]}, - {t: 'C', p: [262.95, 194.677, 263.224, 195.144, 263.593, 194.983]}, - {t: 'C', p: [265.206, 194.28, 267.216, 194.338, 268.4, 193]}, - {t: 'C', p: [272.167, 193.224, 275.732, 192.108, 279.123, 190.8]}, - {t: 'C', p: [280.284, 190.352, 281.554, 189.793, 282.755, 189.291]}, - {t: 'C', p: [284.131, 188.715, 285.335, 187.787, 286.447, 186.646]}, - {t: 'C', p: [286.58, 186.51, 286.934, 186.6, 287.201, 186.6]}, - {t: 'C', p: [287.161, 185.737, 288.123, 185.61, 288.37, 184.988]}, - {t: 'C', p: [288.462, 184.756, 288.312, 184.36, 288.445, 184.258]}, - {t: 'C', p: [290.583, 182.628, 291.503, 180.61, 290.334, 178.233]}, - {t: 'C', p: [290.049, 177.655, 289.8, 177.037, 289.234, 176.561]}, - {t: 'C', p: [288.149, 175.65, 287.047, 176.504, 286, 176.2]}, - {t: 'C', p: [285.841, 176.828, 285.112, 176.656, 284.726, 176.854]}, - {t: 'C', p: [283.867, 177.293, 282.534, 176.708, 281.675, 177.146]}, - {t: 'C', p: [280.313, 177.841, 279.072, 178.01, 277.65, 178.387]}, - {t: 'C', p: [277.338, 178.469, 276.56, 178.373, 276.4, 179]}, - {t: 'C', p: [276.266, 178.866, 276.118, 178.632, 276.012, 178.654]}, - {t: 'C', p: [274.104, 179.05, 272.844, 179.264, 271.543, 180.956]}, - {t: 'C', p: [271.44, 181.089, 270.998, 180.91, 270.839, 181.045]}, - {t: 'C', p: [269.882, 181.853, 269.477, 183.087, 268.376, 183.759]}, - {t: 'C', p: [268.175, 183.882, 267.823, 183.714, 267.629, 183.843]}, - {t: 'C', p: [266.983, 184.274, 266.616, 184.915, 265.974, 185.362]}, - {t: 'C', p: [265.645, 185.591, 265.245, 185.266, 265.277, 185.01]}, - {t: 'C', p: [265.522, 183.063, 266.175, 181.276, 265.6, 179.4]}, - {t: 'C', p: [267.677, 176.88, 270.194, 174.931, 272, 172.2]}, - {t: 'C', p: [272.015, 170.034, 272.707, 167.888, 272.594, 165.811]}, - {t: 'C', p: [272.584, 165.618, 272.296, 164.885, 272.17, 164.538]}, - {t: 'C', p: [271.858, 163.684, 272.764, 162.618, 271.92, 161.894]}, - {t: 'C', p: [270.516, 160.691, 269.224, 161.567, 268.4, 163]}, - {t: 'C', p: [266.562, 163.39, 264.496, 164.083, 262.918, 162.849]}, - {t: 'C', p: [261.911, 162.062, 261.333, 161.156, 260.534, 160.1]}, - {t: 'C', p: [259.549, 158.798, 259.884, 157.362, 259.954, 155.798]}, - {t: 'C', p: [259.96, 155.67, 259.645, 155.534, 259.645, 155.4]}, - {t: 'C', p: [259.646, 155.265, 259.866, 155.134, 260, 155]}, - {t: 'C', p: [259.294, 154.374, 259.019, 153.316, 258, 153]}, - {t: 'C', p: [258.305, 151.908, 257.629, 151.024, 256.758, 150.722]}, - {t: 'C', p: [254.763, 150.031, 253.086, 151.943, 251.194, 152.016]}, - {t: 'C', p: [250.68, 152.035, 250.213, 150.997, 249.564, 150.672]}, - {t: 'C', p: [249.132, 150.456, 248.428, 150.423, 248.066, 150.689]}, - {t: 'C', p: [247.378, 151.193, 246.789, 151.307, 246.031, 151.512]}, - {t: 'C', p: [244.414, 151.948, 243.136, 153.042, 241.656, 153.897]}, - {t: 'C', p: [240.171, 154.754, 239.216, 156.191, 238.136, 157.511]}, - {t: 'C', p: [237.195, 158.663, 237.059, 161.077, 238.479, 161.577]}, - {t: 'C', p: [240.322, 162.227, 241.626, 159.524, 243.592, 159.85]}, - {t: 'C', p: [243.904, 159.901, 244.11, 160.212, 244, 160.6]}, - {t: 'C', p: [244.389, 160.709, 244.607, 160.48, 244.8, 160.2]}, - {t: 'C', p: [245.658, 161.219, 246.822, 161.556, 247.76, 162.429]}, - {t: 'C', p: [248.73, 163.333, 250.476, 162.915, 251.491, 163.912]}, - {t: 'C', p: [253.02, 165.414, 252.461, 168.095, 254.4, 169.4]}, - {t: 'C', p: [253.814, 170.713, 253.207, 171.99, 252.872, 173.417]}, - {t: 'C', p: [252.59, 174.623, 253.584, 175.82, 254.795, 175.729]}, - {t: 'C', p: [256.053, 175.635, 256.315, 174.876, 256.8, 173.8]}, - {t: 'C', p: [257.067, 174.067, 257.536, 174.364, 257.495, 174.58]}, - {t: 'C', p: [257.038, 176.967, 256.011, 178.96, 255.553, 181.391]}, - {t: 'C', p: [255.494, 181.708, 255.189, 181.91, 254.8, 181.8]}, - {t: 'C', p: [254.332, 185.949, 250.28, 188.343, 247.735, 191.508]}, - {t: 'C', p: [247.332, 192.01, 247.328, 193.259, 247.737, 193.662]}, - {t: 'C', p: [249.14, 195.049, 251.1, 193.503, 252.8, 193]}, - {t: 'C', p: [253.013, 191.794, 253.872, 190.852, 255.204, 190.908]}, - {t: 'C', p: [255.46, 190.918, 255.695, 190.376, 256.019, 190.246]}, - {t: 'C', p: [256.367, 190.108, 256.869, 190.332, 257.155, 190.134]}, - {t: 'C', p: [258.884, 188.939, 260.292, 187.833, 262.03, 186.644]}, - {t: 'C', p: [262.222, 186.513, 262.566, 186.672, 262.782, 186.564]}, - {t: 'C', p: [263.107, 186.402, 263.294, 186.015, 263.617, 185.83]}, - {t: 'C', p: [263.965, 185.63, 264.207, 185.92, 264.4, 186.2]}, - {t: 'C', p: [263.754, 186.549, 263.75, 187.506, 263.168, 187.708]}, - {t: 'C', p: [262.393, 187.976, 261.832, 188.489, 261.158, 188.936]}, - {t: 'C', p: [260.866, 189.129, 260.207, 188.881, 260.103, 189.06]}, - {t: 'C', p: [259.505, 190.088, 258.321, 190.526, 257.611, 191.409]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [202.2, 142]}, - {t: 'C', p: [202.2, 142, 192.962, 139.128, 181.8, 164.8]}, - {t: 'C', p: [181.8, 164.8, 179.4, 170, 177, 172]}, - {t: 'C', p: [174.6, 174, 163.4, 177.6, 161.4, 181.6]}, - {t: 'L', p: [151, 197.6]}, - {t: 'C', p: [151, 197.6, 165.8, 181.6, 169, 179.2]}, - {t: 'C', p: [169, 179.2, 177, 170.8, 173.8, 177.6]}, - {t: 'C', p: [173.8, 177.6, 159.8, 188.4, 161, 197.6]}, - {t: 'C', p: [161, 197.6, 155.4, 212, 154.6, 214]}, - {t: 'C', p: [154.6, 214, 170.6, 182, 173, 180.8]}, - {t: 'C', p: [175.4, 179.6, 176.6, 179.6, 175.4, 183.2]}, - {t: 'C', p: [174.2, 186.8, 173.8, 203.2, 171, 205.2]}, - {t: 'C', p: [171, 205.2, 179, 184.8, 178.2, 181.6]}, - {t: 'C', p: [178.2, 181.6, 181.4, 178, 183.8, 183.2]}, - {t: 'L', p: [182.6, 199.2]}, - {t: 'L', p: [187, 211.2]}, - {t: 'C', p: [187, 211.2, 184.6, 200, 186.2, 184.4]}, - {t: 'C', p: [186.2, 184.4, 184.2, 174, 188.2, 179.6]}, - {t: 'C', p: [192.2, 185.2, 201.8, 191.2, 201.8, 196]}, - {t: 'C', p: [201.8, 196, 196.6, 178.4, 187.4, 173.6]}, - {t: 'L', p: [183.4, 179.6]}, - {t: 'L', p: [182.2, 177.6]}, - {t: 'C', p: [182.2, 177.6, 178.6, 176.8, 183, 170]}, - {t: 'C', p: [187.4, 163.2, 187, 162.4, 187, 162.4]}, - {t: 'C', p: [187, 162.4, 193.4, 169.6, 195, 169.6]}, - {t: 'C', p: [195, 169.6, 208.2, 162, 209.4, 186.4]}, - {t: 'C', p: [209.4, 186.4, 216.2, 172, 207, 165.2]}, - {t: 'C', p: [207, 165.2, 192.2, 163.2, 193.4, 158]}, - {t: 'L', p: [200.6, 145.6]}, - {t: 'C', p: [204.2, 140.4, 202.6, 143.2, 202.6, 143.2]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [182.2, 158.4]}, - {t: 'C', p: [182.2, 158.4, 169.4, 158.4, 166.2, 163.6]}, - {t: 'L', p: [159, 173.2]}, - {t: 'C', p: [159, 173.2, 176.2, 163.2, 180.2, 162]}, - {t: 'C', p: [184.2, 160.8, 182.2, 158.4, 182.2, 158.4]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [142.2, 164.8]}, - {t: 'C', p: [142.2, 164.8, 140.2, 166, 139.8, 168.8]}, - {t: 'C', p: [139.4, 171.6, 137, 172, 137.8, 174.8]}, - {t: 'C', p: [138.6, 177.6, 140.6, 180, 140.6, 176]}, - {t: 'C', p: [140.6, 172, 142.2, 170, 143, 168.8]}, - {t: 'C', p: [143.8, 167.6, 145.4, 163.2, 142.2, 164.8]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [133.4, 226]}, - {t: 'C', p: [133.4, 226, 125, 222, 121.8, 218.4]}, - {t: 'C', p: [118.6, 214.8, 119.052, 219.966, 114.2, 219.6]}, - {t: 'C', p: [108.353, 219.159, 109.4, 203.2, 109.4, 203.2]}, - {t: 'L', p: [105.4, 210.8]}, - {t: 'C', p: [105.4, 210.8, 104.2, 225.2, 112.2, 222.8]}, - {t: 'C', p: [116.107, 221.628, 117.4, 223.2, 115.8, 224]}, - {t: 'C', p: [114.2, 224.8, 121.4, 225.2, 118.6, 226.8]}, - {t: 'C', p: [115.8, 228.4, 130.2, 223.2, 127.8, 233.6]}, - {t: 'L', p: [133.4, 226]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [120.8, 240.4]}, - {t: 'C', p: [120.8, 240.4, 105.4, 244.8, 101.8, 235.2]}, - {t: 'C', p: [101.8, 235.2, 97, 237.6, 99.2, 240.6]}, - {t: 'C', p: [101.4, 243.6, 102.6, 244, 102.6, 244]}, - {t: 'C', p: [102.6, 244, 108, 245.2, 107.4, 246]}, - {t: 'C', p: [106.8, 246.8, 104.4, 250.2, 104.4, 250.2]}, - {t: 'C', p: [104.4, 250.2, 114.6, 244.2, 120.8, 240.4]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: null, p: [{t: 'M', p: [349.201, 318.601]}, - {t: 'C', p: [348.774, 320.735, 347.103, 321.536, 345.201, 322.201]}, - {t: 'C', p: [343.284, 321.243, 340.686, 318.137, 338.801, 320.201]}, - {t: 'C', p: [338.327, 319.721, 337.548, 319.661, 337.204, 318.999]}, - {t: 'C', p: [336.739, 318.101, 337.011, 317.055, 336.669, 316.257]}, - {t: 'C', p: [336.124, 314.985, 335.415, 313.619, 335.601, 312.201]}, - {t: 'C', p: [337.407, 311.489, 338.002, 309.583, 337.528, 307.82]}, - {t: 'C', p: [337.459, 307.563, 337.03, 307.366, 337.23, 307.017]}, - {t: 'C', p: [337.416, 306.694, 337.734, 306.467, 338.001, 306.2]}, - {t: 'C', p: [337.866, 306.335, 337.721, 306.568, 337.61, 306.548]}, - {t: 'C', p: [337, 306.442, 337.124, 305.805, 337.254, 305.418]}, - {t: 'C', p: [337.839, 303.672, 339.853, 303.408, 341.201, 304.6]}, - {t: 'C', p: [341.457, 304.035, 341.966, 304.229, 342.401, 304.2]}, - {t: 'C', p: [342.351, 303.621, 342.759, 303.094, 342.957, 302.674]}, - {t: 'C', p: [343.475, 301.576, 345.104, 302.682, 345.901, 302.07]}, - {t: 'C', p: [346.977, 301.245, 348.04, 300.546, 349.118, 301.149]}, - {t: 'C', p: [350.927, 302.162, 352.636, 303.374, 353.835, 305.115]}, - {t: 'C', p: [354.41, 305.949, 354.65, 307.23, 354.592, 308.188]}, - {t: 'C', p: [354.554, 308.835, 353.173, 308.483, 352.83, 309.412]}, - {t: 'C', p: [352.185, 311.16, 354.016, 311.679, 354.772, 313.017]}, - {t: 'C', p: [354.97, 313.366, 354.706, 313.67, 354.391, 313.768]}, - {t: 'C', p: [353.98, 313.896, 353.196, 313.707, 353.334, 314.16]}, - {t: 'C', p: [354.306, 317.353, 351.55, 318.031, 349.201, 318.601]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: null, p: [{t: 'M', p: [339.6, 338.201]}, - {t: 'C', p: [339.593, 336.463, 337.992, 334.707, 339.201, 333.001]}, - {t: 'C', p: [339.336, 333.135, 339.467, 333.356, 339.601, 333.356]}, - {t: 'C', p: [339.736, 333.356, 339.867, 333.135, 340.001, 333.001]}, - {t: 'C', p: [341.496, 335.217, 345.148, 336.145, 345.006, 338.991]}, - {t: 'C', p: [344.984, 339.438, 343.897, 340.356, 344.801, 341.001]}, - {t: 'C', p: [342.988, 342.349, 342.933, 344.719, 342.001, 346.601]}, - {t: 'C', p: [340.763, 346.315, 339.551, 345.952, 338.401, 345.401]}, - {t: 'C', p: [338.753, 343.915, 338.636, 342.231, 339.456, 340.911]}, - {t: 'C', p: [339.89, 340.213, 339.603, 339.134, 339.6, 338.201]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [173.4, 329.201]}, - {t: 'C', p: [173.4, 329.201, 156.542, 339.337, 170.6, 324.001]}, - {t: 'C', p: [179.4, 314.401, 189.4, 308.801, 189.4, 308.801]}, - {t: 'C', p: [189.4, 308.801, 199.8, 304.4, 203.4, 303.2]}, - {t: 'C', p: [207, 302, 222.2, 296.8, 225.4, 296.4]}, - {t: 'C', p: [228.6, 296, 238.2, 292, 245, 296]}, - {t: 'C', p: [251.8, 300, 259.8, 304.4, 259.8, 304.4]}, - {t: 'C', p: [259.8, 304.4, 243.4, 296, 239.8, 298.4]}, - {t: 'C', p: [236.2, 300.8, 229, 300.4, 223, 303.6]}, - {t: 'C', p: [223, 303.6, 208.2, 308.001, 205, 310.001]}, - {t: 'C', p: [201.8, 312.001, 191.4, 323.601, 189.8, 322.801]}, - {t: 'C', p: [188.2, 322.001, 190.2, 321.601, 191.4, 318.801]}, - {t: 'C', p: [192.6, 316.001, 190.6, 314.401, 182.6, 320.801]}, - {t: 'C', p: [174.6, 327.201, 173.4, 329.201, 173.4, 329.201]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [180.805, 323.234]}, - {t: 'C', p: [180.805, 323.234, 182.215, 310.194, 190.693, 311.859]}, - {t: 'C', p: [190.693, 311.859, 198.919, 307.689, 201.641, 305.721]}, - {t: 'C', p: [201.641, 305.721, 209.78, 304.019, 211.09, 303.402]}, - {t: 'C', p: [229.569, 294.702, 244.288, 299.221, 244.835, 298.101]}, - {t: 'C', p: [245.381, 296.982, 265.006, 304.099, 268.615, 308.185]}, - {t: 'C', p: [269.006, 308.628, 258.384, 302.588, 248.686, 300.697]}, - {t: 'C', p: [240.413, 299.083, 218.811, 300.944, 207.905, 306.48]}, - {t: 'C', p: [204.932, 307.989, 195.987, 313.773, 193.456, 313.662]}, - {t: 'C', p: [190.925, 313.55, 180.805, 323.234, 180.805, 323.234]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [177, 348.801]}, - {t: 'C', p: [177, 348.801, 161.8, 346.401, 178.6, 344.801]}, - {t: 'C', p: [178.6, 344.801, 196.6, 342.801, 200.6, 337.601]}, - {t: 'C', p: [200.6, 337.601, 214.2, 328.401, 217, 328.001]}, - {t: 'C', p: [219.8, 327.601, 249.8, 320.401, 250.2, 318.001]}, - {t: 'C', p: [250.6, 315.601, 256.2, 315.601, 257.8, 316.401]}, - {t: 'C', p: [259.4, 317.201, 258.6, 318.401, 255.8, 319.201]}, - {t: 'C', p: [253, 320.001, 221.8, 336.401, 215.4, 337.601]}, - {t: 'C', p: [209, 338.801, 197.4, 346.401, 192.6, 347.601]}, - {t: 'C', p: [187.8, 348.801, 177, 348.801, 177, 348.801]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [196.52, 341.403]}, - {t: 'C', p: [196.52, 341.403, 187.938, 340.574, 196.539, 339.755]}, - {t: 'C', p: [196.539, 339.755, 205.355, 336.331, 207.403, 333.668]}, - {t: 'C', p: [207.403, 333.668, 214.367, 328.957, 215.8, 328.753]}, - {t: 'C', p: [217.234, 328.548, 231.194, 324.861, 231.399, 323.633]}, - {t: 'C', p: [231.604, 322.404, 265.67, 309.823, 270.09, 313.013]}, - {t: 'C', p: [273.001, 315.114, 263.1, 313.437, 253.466, 317.847]}, - {t: 'C', p: [252.111, 318.467, 218.258, 333.054, 214.981, 333.668]}, - {t: 'C', p: [211.704, 334.283, 205.765, 338.174, 203.307, 338.788]}, - {t: 'C', p: [200.85, 339.403, 196.52, 341.403, 196.52, 341.403]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [188.6, 343.601]}, - {t: 'C', p: [188.6, 343.601, 193.8, 343.201, 192.6, 344.801]}, - {t: 'C', p: [191.4, 346.401, 189, 345.601, 189, 345.601]}, - {t: 'L', p: [188.6, 343.601]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [181.4, 345.201]}, - {t: 'C', p: [181.4, 345.201, 186.6, 344.801, 185.4, 346.401]}, - {t: 'C', p: [184.2, 348.001, 181.8, 347.201, 181.8, 347.201]}, - {t: 'L', p: [181.4, 345.201]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [171, 346.801]}, - {t: 'C', p: [171, 346.801, 176.2, 346.401, 175, 348.001]}, - {t: 'C', p: [173.8, 349.601, 171.4, 348.801, 171.4, 348.801]}, - {t: 'L', p: [171, 346.801]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [163.4, 347.601]}, - {t: 'C', p: [163.4, 347.601, 168.6, 347.201, 167.4, 348.801]}, - {t: 'C', p: [166.2, 350.401, 163.8, 349.601, 163.8, 349.601]}, - {t: 'L', p: [163.4, 347.601]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [201.8, 308.001]}, - {t: 'C', p: [201.8, 308.001, 206.2, 308.001, 205, 309.601]}, - {t: 'C', p: [203.8, 311.201, 200.6, 310.801, 200.6, 310.801]}, - {t: 'L', p: [201.8, 308.001]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [191.8, 313.601]}, - {t: 'C', p: [191.8, 313.601, 198.306, 311.46, 195.8, 314.801]}, - {t: 'C', p: [194.6, 316.401, 192.2, 315.601, 192.2, 315.601]}, - {t: 'L', p: [191.8, 313.601]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [180.6, 318.401]}, - {t: 'C', p: [180.6, 318.401, 185.8, 318.001, 184.6, 319.601]}, - {t: 'C', p: [183.4, 321.201, 181, 320.401, 181, 320.401]}, - {t: 'L', p: [180.6, 318.401]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [173, 324.401]}, - {t: 'C', p: [173, 324.401, 178.2, 324.001, 177, 325.601]}, - {t: 'C', p: [175.8, 327.201, 173.4, 326.401, 173.4, 326.401]}, - {t: 'L', p: [173, 324.401]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [166.2, 329.201]}, - {t: 'C', p: [166.2, 329.201, 171.4, 328.801, 170.2, 330.401]}, - {t: 'C', p: [169, 332.001, 166.6, 331.201, 166.6, 331.201]}, - {t: 'L', p: [166.2, 329.201]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [205.282, 335.598]}, - {t: 'C', p: [205.282, 335.598, 212.203, 335.066, 210.606, 337.195]}, - {t: 'C', p: [209.009, 339.325, 205.814, 338.26, 205.814, 338.26]}, - {t: 'L', p: [205.282, 335.598]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [215.682, 330.798]}, - {t: 'C', p: [215.682, 330.798, 222.603, 330.266, 221.006, 332.395]}, - {t: 'C', p: [219.409, 334.525, 216.214, 333.46, 216.214, 333.46]}, - {t: 'L', p: [215.682, 330.798]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [226.482, 326.398]}, - {t: 'C', p: [226.482, 326.398, 233.403, 325.866, 231.806, 327.995]}, - {t: 'C', p: [230.209, 330.125, 227.014, 329.06, 227.014, 329.06]}, - {t: 'L', p: [226.482, 326.398]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [236.882, 321.598]}, - {t: 'C', p: [236.882, 321.598, 243.803, 321.066, 242.206, 323.195]}, - {t: 'C', p: [240.609, 325.325, 237.414, 324.26, 237.414, 324.26]}, - {t: 'L', p: [236.882, 321.598]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [209.282, 303.598]}, - {t: 'C', p: [209.282, 303.598, 216.203, 303.066, 214.606, 305.195]}, - {t: 'C', p: [213.009, 307.325, 209.014, 307.06, 209.014, 307.06]}, - {t: 'L', p: [209.282, 303.598]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [219.282, 300.398]}, - {t: 'C', p: [219.282, 300.398, 226.203, 299.866, 224.606, 301.995]}, - {t: 'C', p: [223.009, 304.125, 218.614, 303.86, 218.614, 303.86]}, - {t: 'L', p: [219.282, 300.398]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [196.6, 340.401]}, - {t: 'C', p: [196.6, 340.401, 201.8, 340.001, 200.6, 341.601]}, - {t: 'C', p: [199.4, 343.201, 197, 342.401, 197, 342.401]}, - {t: 'L', p: [196.6, 340.401]}, - {t: 'z', p: []}]}, - -{f: '#992600', s: null, p: [{t: 'M', p: [123.4, 241.2]}, - {t: 'C', p: [123.4, 241.2, 119, 250, 118.6, 253.2]}, - {t: 'C', p: [118.6, 253.2, 119.4, 244.4, 120.6, 242.4]}, - {t: 'C', p: [121.8, 240.4, 123.4, 241.2, 123.4, 241.2]}, - {t: 'z', p: []}]}, - -{f: '#992600', s: null, p: [{t: 'M', p: [105, 255.2]}, - {t: 'C', p: [105, 255.2, 101.8, 269.6, 102.2, 272.4]}, - {t: 'C', p: [102.2, 272.4, 101, 260.8, 101.4, 259.6]}, - {t: 'C', p: [101.8, 258.4, 105, 255.2, 105, 255.2]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [125.8, 180.6]}, - {t: 'L', p: [125.6, 183.8]}, - {t: 'L', p: [123.4, 184]}, - {t: 'C', p: [123.4, 184, 137.6, 196.6, 138.2, 204.2]}, - {t: 'C', p: [138.2, 204.2, 139, 196, 125.8, 180.6]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [129.784, 181.865]}, - {t: 'C', p: [129.353, 181.449, 129.572, 180.704, 129.164, 180.444]}, - {t: 'C', p: [128.355, 179.928, 130.462, 179.871, 130.234, 179.155]}, - {t: 'C', p: [129.851, 177.949, 130.038, 177.928, 129.916, 176.652]}, - {t: 'C', p: [129.859, 176.054, 130.447, 174.514, 130.832, 174.074]}, - {t: 'C', p: [132.278, 172.422, 130.954, 169.49, 132.594, 167.939]}, - {t: 'C', p: [132.898, 167.65, 133.274, 167.098, 133.559, 166.68]}, - {t: 'C', p: [134.218, 165.717, 135.402, 165.229, 136.352, 164.401]}, - {t: 'C', p: [136.67, 164.125, 136.469, 163.298, 137.038, 163.39]}, - {t: 'C', p: [137.752, 163.505, 138.993, 163.375, 138.948, 164.216]}, - {t: 'C', p: [138.835, 166.336, 137.506, 168.056, 136.226, 169.724]}, - {t: 'C', p: [136.677, 170.428, 136.219, 171.063, 135.935, 171.62]}, - {t: 'C', p: [134.6, 174.24, 134.789, 177.081, 134.615, 179.921]}, - {t: 'C', p: [134.61, 180.006, 134.303, 180.084, 134.311, 180.137]}, - {t: 'C', p: [134.664, 182.472, 135.248, 184.671, 136.127, 186.9]}, - {t: 'C', p: [136.493, 187.83, 136.964, 188.725, 137.114, 189.652]}, - {t: 'C', p: [137.225, 190.338, 137.328, 191.171, 136.92, 191.876]}, - {t: 'C', p: [138.955, 194.766, 137.646, 197.417, 138.815, 200.948]}, - {t: 'C', p: [139.022, 201.573, 140.714, 203.487, 140.251, 203.326]}, - {t: 'C', p: [137.738, 202.455, 137.626, 202.057, 137.449, 201.304]}, - {t: 'C', p: [137.303, 200.681, 136.973, 199.304, 136.736, 198.702]}, - {t: 'C', p: [136.672, 198.538, 136.501, 196.654, 136.423, 196.532]}, - {t: 'C', p: [134.91, 194.15, 136.268, 194.326, 134.898, 191.968]}, - {t: 'C', p: [133.47, 191.288, 132.504, 190.184, 131.381, 189.022]}, - {t: 'C', p: [131.183, 188.818, 132.326, 188.094, 132.145, 187.881]}, - {t: 'C', p: [131.053, 186.592, 129.9, 185.825, 130.236, 184.332]}, - {t: 'C', p: [130.391, 183.642, 130.528, 182.585, 129.784, 181.865]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [126.2, 183.6]}, - {t: 'C', p: [126.2, 183.6, 126.6, 190.4, 129, 192]}, - {t: 'C', p: [131.4, 193.6, 130.2, 192.8, 127, 191.6]}, - {t: 'C', p: [123.8, 190.4, 125, 189.6, 125, 189.6]}, - {t: 'C', p: [125, 189.6, 122.2, 190, 124.6, 192]}, - {t: 'C', p: [127, 194, 130.6, 196.4, 129, 196.4]}, - {t: 'C', p: [127.4, 196.4, 119.8, 192.4, 119.8, 189.6]}, - {t: 'C', p: [119.8, 186.8, 118.8, 182.7, 118.8, 182.7]}, - {t: 'C', p: [118.8, 182.7, 119.9, 181.9, 124.7, 182]}, - {t: 'C', p: [124.7, 182, 126.1, 182.7, 126.2, 183.6]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [125.4, 202.2]}, - {t: 'C', p: [125.4, 202.2, 116.88, 199.409, 98.4, 202.8]}, - {t: 'C', p: [98.4, 202.8, 107.431, 200.722, 126.2, 203]}, - {t: 'C', p: [136.5, 204.25, 125.4, 202.2, 125.4, 202.2]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [127.498, 202.129]}, - {t: 'C', p: [127.498, 202.129, 119.252, 198.611, 100.547, 200.392]}, - {t: 'C', p: [100.547, 200.392, 109.725, 199.103, 128.226, 202.995]}, - {t: 'C', p: [138.38, 205.131, 127.498, 202.129, 127.498, 202.129]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [129.286, 202.222]}, - {t: 'C', p: [129.286, 202.222, 121.324, 198.101, 102.539, 198.486]}, - {t: 'C', p: [102.539, 198.486, 111.787, 197.882, 129.948, 203.14]}, - {t: 'C', p: [139.914, 206.025, 129.286, 202.222, 129.286, 202.222]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [130.556, 202.445]}, - {t: 'C', p: [130.556, 202.445, 123.732, 198.138, 106.858, 197.04]}, - {t: 'C', p: [106.858, 197.04, 115.197, 197.21, 131.078, 203.319]}, - {t: 'C', p: [139.794, 206.672, 130.556, 202.445, 130.556, 202.445]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [245.84, 212.961]}, - {t: 'C', p: [245.84, 212.961, 244.91, 213.605, 245.124, 212.424]}, - {t: 'C', p: [245.339, 211.243, 273.547, 198.073, 277.161, 198.323]}, - {t: 'C', p: [277.161, 198.323, 246.913, 211.529, 245.84, 212.961]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [242.446, 213.6]}, - {t: 'C', p: [242.446, 213.6, 241.57, 214.315, 241.691, 213.121]}, - {t: 'C', p: [241.812, 211.927, 268.899, 196.582, 272.521, 196.548]}, - {t: 'C', p: [272.521, 196.548, 243.404, 212.089, 242.446, 213.6]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [239.16, 214.975]}, - {t: 'C', p: [239.16, 214.975, 238.332, 215.747, 238.374, 214.547]}, - {t: 'C', p: [238.416, 213.348, 258.233, 197.851, 268.045, 195.977]}, - {t: 'C', p: [268.045, 195.977, 250.015, 204.104, 239.16, 214.975]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [236.284, 216.838]}, - {t: 'C', p: [236.284, 216.838, 235.539, 217.532, 235.577, 216.453]}, - {t: 'C', p: [235.615, 215.373, 253.449, 201.426, 262.28, 199.74]}, - {t: 'C', p: [262.28, 199.74, 246.054, 207.054, 236.284, 216.838]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [204.6, 364.801]}, - {t: 'C', p: [204.6, 364.801, 189.4, 362.401, 206.2, 360.801]}, - {t: 'C', p: [206.2, 360.801, 224.2, 358.801, 228.2, 353.601]}, - {t: 'C', p: [228.2, 353.601, 241.8, 344.401, 244.6, 344.001]}, - {t: 'C', p: [247.4, 343.601, 263.8, 340.001, 264.2, 337.601]}, - {t: 'C', p: [264.6, 335.201, 270.6, 332.801, 272.2, 333.601]}, - {t: 'C', p: [273.8, 334.401, 273.8, 343.601, 271, 344.401]}, - {t: 'C', p: [268.2, 345.201, 249.4, 352.401, 243, 353.601]}, - {t: 'C', p: [236.6, 354.801, 225, 362.401, 220.2, 363.601]}, - {t: 'C', p: [215.4, 364.801, 204.6, 364.801, 204.6, 364.801]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [277.6, 327.401]}, - {t: 'C', p: [277.6, 327.401, 274.6, 329.001, 273.4, 331.601]}, - {t: 'C', p: [273.4, 331.601, 267, 342.201, 252.8, 345.401]}, - {t: 'C', p: [252.8, 345.401, 229.8, 354.401, 222, 356.401]}, - {t: 'C', p: [222, 356.401, 208.6, 361.401, 201.2, 360.601]}, - {t: 'C', p: [201.2, 360.601, 194.2, 360.801, 200.4, 362.401]}, - {t: 'C', p: [200.4, 362.401, 220.6, 360.401, 224, 358.601]}, - {t: 'C', p: [224, 358.601, 239.6, 353.401, 242.6, 350.801]}, - {t: 'C', p: [245.6, 348.201, 263.8, 343.201, 266, 341.201]}, - {t: 'C', p: [268.2, 339.201, 278, 330.801, 277.6, 327.401]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [218.882, 358.911]}, - {t: 'C', p: [218.882, 358.911, 224.111, 358.685, 222.958, 360.234]}, - {t: 'C', p: [221.805, 361.784, 219.357, 360.91, 219.357, 360.91]}, - {t: 'L', p: [218.882, 358.911]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [211.68, 360.263]}, - {t: 'C', p: [211.68, 360.263, 216.908, 360.037, 215.756, 361.586]}, - {t: 'C', p: [214.603, 363.136, 212.155, 362.263, 212.155, 362.263]}, - {t: 'L', p: [211.68, 360.263]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [201.251, 361.511]}, - {t: 'C', p: [201.251, 361.511, 206.48, 361.284, 205.327, 362.834]}, - {t: 'C', p: [204.174, 364.383, 201.726, 363.51, 201.726, 363.51]}, - {t: 'L', p: [201.251, 361.511]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [193.617, 362.055]}, - {t: 'C', p: [193.617, 362.055, 198.846, 361.829, 197.693, 363.378]}, - {t: 'C', p: [196.54, 364.928, 194.092, 364.054, 194.092, 364.054]}, - {t: 'L', p: [193.617, 362.055]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [235.415, 351.513]}, - {t: 'C', p: [235.415, 351.513, 242.375, 351.212, 240.84, 353.274]}, - {t: 'C', p: [239.306, 355.336, 236.047, 354.174, 236.047, 354.174]}, - {t: 'L', p: [235.415, 351.513]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [245.73, 347.088]}, - {t: 'C', p: [245.73, 347.088, 251.689, 343.787, 251.155, 348.849]}, - {t: 'C', p: [250.885, 351.405, 246.362, 349.749, 246.362, 349.749]}, - {t: 'L', p: [245.73, 347.088]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [254.862, 344.274]}, - {t: 'C', p: [254.862, 344.274, 262.021, 340.573, 260.287, 346.035]}, - {t: 'C', p: [259.509, 348.485, 255.493, 346.935, 255.493, 346.935]}, - {t: 'L', p: [254.862, 344.274]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [264.376, 339.449]}, - {t: 'C', p: [264.376, 339.449, 268.735, 334.548, 269.801, 341.21]}, - {t: 'C', p: [270.207, 343.748, 265.008, 342.11, 265.008, 342.11]}, - {t: 'L', p: [264.376, 339.449]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [226.834, 355.997]}, - {t: 'C', p: [226.834, 355.997, 232.062, 355.77, 230.91, 357.32]}, - {t: 'C', p: [229.757, 358.869, 227.308, 357.996, 227.308, 357.996]}, - {t: 'L', p: [226.834, 355.997]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [262.434, 234.603]}, - {t: 'C', p: [262.434, 234.603, 261.708, 235.268, 261.707, 234.197]}, - {t: 'C', p: [261.707, 233.127, 279.191, 219.863, 288.034, 218.479]}, - {t: 'C', p: [288.034, 218.479, 271.935, 225.208, 262.434, 234.603]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [265.4, 298.4]}, - {t: 'C', p: [265.4, 298.4, 287.401, 320.801, 296.601, 324.401]}, - {t: 'C', p: [296.601, 324.401, 305.801, 335.601, 301.801, 361.601]}, - {t: 'C', p: [301.801, 361.601, 298.601, 369.201, 295.401, 348.401]}, - {t: 'C', p: [295.401, 348.401, 298.601, 323.201, 287.401, 339.201]}, - {t: 'C', p: [287.401, 339.201, 279, 329.301, 285.4, 329.601]}, - {t: 'C', p: [285.4, 329.601, 288.601, 331.601, 289.001, 330.001]}, - {t: 'C', p: [289.401, 328.401, 281.4, 314.801, 264.2, 300.4]}, - {t: 'C', p: [247, 286, 265.4, 298.4, 265.4, 298.4]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [207, 337.201]}, - {t: 'C', p: [207, 337.201, 206.8, 335.401, 208.6, 336.201]}, - {t: 'C', p: [210.4, 337.001, 304.601, 343.201, 336.201, 367.201]}, - {t: 'C', p: [336.201, 367.201, 291.001, 344.001, 207, 337.201]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [217.4, 332.801]}, - {t: 'C', p: [217.4, 332.801, 217.2, 331.001, 219, 331.801]}, - {t: 'C', p: [220.8, 332.601, 357.401, 331.601, 381.001, 364.001]}, - {t: 'C', p: [381.001, 364.001, 359.001, 338.801, 217.4, 332.801]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [229, 328.801]}, - {t: 'C', p: [229, 328.801, 228.8, 327.001, 230.6, 327.801]}, - {t: 'C', p: [232.4, 328.601, 405.801, 315.601, 429.401, 348.001]}, - {t: 'C', p: [429.401, 348.001, 419.801, 322.401, 229, 328.801]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [239, 324.001]}, - {t: 'C', p: [239, 324.001, 238.8, 322.201, 240.6, 323.001]}, - {t: 'C', p: [242.4, 323.801, 364.601, 285.2, 388.201, 317.601]}, - {t: 'C', p: [388.201, 317.601, 374.801, 293, 239, 324.001]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [181, 346.801]}, - {t: 'C', p: [181, 346.801, 180.8, 345.001, 182.6, 345.801]}, - {t: 'C', p: [184.4, 346.601, 202.2, 348.801, 204.2, 387.601]}, - {t: 'C', p: [204.2, 387.601, 197, 345.601, 181, 346.801]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [172.2, 348.401]}, - {t: 'C', p: [172.2, 348.401, 172, 346.601, 173.8, 347.401]}, - {t: 'C', p: [175.6, 348.201, 189.8, 343.601, 187, 382.401]}, - {t: 'C', p: [187, 382.401, 188.2, 347.201, 172.2, 348.401]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [164.2, 348.801]}, - {t: 'C', p: [164.2, 348.801, 164, 347.001, 165.8, 347.801]}, - {t: 'C', p: [167.6, 348.601, 183, 349.201, 170.6, 371.601]}, - {t: 'C', p: [170.6, 371.601, 180.2, 347.601, 164.2, 348.801]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [211.526, 304.465]}, - {t: 'C', p: [211.526, 304.465, 211.082, 306.464, 212.631, 305.247]}, - {t: 'C', p: [228.699, 292.622, 261.141, 233.72, 316.826, 228.086]}, - {t: 'C', p: [316.826, 228.086, 278.518, 215.976, 211.526, 304.465]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [222.726, 302.665]}, - {t: 'C', p: [222.726, 302.665, 221.363, 301.472, 223.231, 300.847]}, - {t: 'C', p: [225.099, 300.222, 337.541, 227.72, 376.826, 235.686]}, - {t: 'C', p: [376.826, 235.686, 349.719, 228.176, 222.726, 302.665]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [201.885, 308.767]}, - {t: 'C', p: [201.885, 308.767, 201.376, 310.366, 203.087, 309.39]}, - {t: 'C', p: [212.062, 304.27, 215.677, 247.059, 259.254, 245.804]}, - {t: 'C', p: [259.254, 245.804, 226.843, 231.09, 201.885, 308.767]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [181.962, 319.793]}, - {t: 'C', p: [181.962, 319.793, 180.885, 321.079, 182.838, 320.825]}, - {t: 'C', p: [193.084, 319.493, 214.489, 278.222, 258.928, 283.301]}, - {t: 'C', p: [258.928, 283.301, 226.962, 268.955, 181.962, 319.793]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [193.2, 313.667]}, - {t: 'C', p: [193.2, 313.667, 192.389, 315.136, 194.258, 314.511]}, - {t: 'C', p: [204.057, 311.237, 217.141, 266.625, 261.729, 263.078]}, - {t: 'C', p: [261.729, 263.078, 227.603, 255.135, 193.2, 313.667]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [174.922, 324.912]}, - {t: 'C', p: [174.922, 324.912, 174.049, 325.954, 175.631, 325.748]}, - {t: 'C', p: [183.93, 324.669, 201.268, 291.24, 237.264, 295.354]}, - {t: 'C', p: [237.264, 295.354, 211.371, 283.734, 174.922, 324.912]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [167.323, 330.821]}, - {t: 'C', p: [167.323, 330.821, 166.318, 331.866, 167.909, 331.748]}, - {t: 'C', p: [172.077, 331.439, 202.715, 298.36, 221.183, 313.862]}, - {t: 'C', p: [221.183, 313.862, 209.168, 295.139, 167.323, 330.821]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [236.855, 298.898]}, - {t: 'C', p: [236.855, 298.898, 235.654, 297.543, 237.586, 297.158]}, - {t: 'C', p: [239.518, 296.774, 360.221, 239.061, 398.184, 251.927]}, - {t: 'C', p: [398.184, 251.927, 372.243, 241.053, 236.855, 298.898]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [203.4, 363.201]}, - {t: 'C', p: [203.4, 363.201, 203.2, 361.401, 205, 362.201]}, - {t: 'C', p: [206.8, 363.001, 222.2, 363.601, 209.8, 386.001]}, - {t: 'C', p: [209.8, 386.001, 219.4, 362.001, 203.4, 363.201]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [213.8, 361.601]}, - {t: 'C', p: [213.8, 361.601, 213.6, 359.801, 215.4, 360.601]}, - {t: 'C', p: [217.2, 361.401, 235, 363.601, 237, 402.401]}, - {t: 'C', p: [237, 402.401, 229.8, 360.401, 213.8, 361.601]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [220.6, 360.001]}, - {t: 'C', p: [220.6, 360.001, 220.4, 358.201, 222.2, 359.001]}, - {t: 'C', p: [224, 359.801, 248.6, 363.201, 272.2, 395.601]}, - {t: 'C', p: [272.2, 395.601, 236.6, 358.801, 220.6, 360.001]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [228.225, 357.972]}, - {t: 'C', p: [228.225, 357.972, 227.788, 356.214, 229.678, 356.768]}, - {t: 'C', p: [231.568, 357.322, 252.002, 355.423, 290.099, 389.599]}, - {t: 'C', p: [290.099, 389.599, 243.924, 354.656, 228.225, 357.972]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [238.625, 353.572]}, - {t: 'C', p: [238.625, 353.572, 238.188, 351.814, 240.078, 352.368]}, - {t: 'C', p: [241.968, 352.922, 276.802, 357.423, 328.499, 392.399]}, - {t: 'C', p: [328.499, 392.399, 254.324, 350.256, 238.625, 353.572]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [198.2, 342.001]}, - {t: 'C', p: [198.2, 342.001, 198, 340.201, 199.8, 341.001]}, - {t: 'C', p: [201.6, 341.801, 255, 344.401, 285.4, 371.201]}, - {t: 'C', p: [285.4, 371.201, 250.499, 346.426, 198.2, 342.001]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [188.2, 346.001]}, - {t: 'C', p: [188.2, 346.001, 188, 344.201, 189.8, 345.001]}, - {t: 'C', p: [191.6, 345.801, 216.2, 349.201, 239.8, 381.601]}, - {t: 'C', p: [239.8, 381.601, 204.2, 344.801, 188.2, 346.001]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [249.503, 348.962]}, - {t: 'C', p: [249.503, 348.962, 248.938, 347.241, 250.864, 347.655]}, - {t: 'C', p: [252.79, 348.068, 287.86, 350.004, 341.981, 381.098]}, - {t: 'C', p: [341.981, 381.098, 264.317, 346.704, 249.503, 348.962]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [257.903, 346.562]}, - {t: 'C', p: [257.903, 346.562, 257.338, 344.841, 259.264, 345.255]}, - {t: 'C', p: [261.19, 345.668, 296.26, 347.604, 350.381, 378.698]}, - {t: 'C', p: [350.381, 378.698, 273.317, 343.904, 257.903, 346.562]}, - {t: 'z', p: []}]}, - -{f: '#fff', s: {c: '#000', w: 0.1}, - p: [{t: 'M', p: [267.503, 341.562]}, - {t: 'C', p: [267.503, 341.562, 266.938, 339.841, 268.864, 340.255]}, - {t: 'C', p: [270.79, 340.668, 313.86, 345.004, 403.582, 379.298]}, - {t: 'C', p: [403.582, 379.298, 282.917, 338.904, 267.503, 341.562]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [156.2, 348.401]}, - {t: 'C', p: [156.2, 348.401, 161.4, 348.001, 160.2, 349.601]}, - {t: 'C', p: [159, 351.201, 156.6, 350.401, 156.6, 350.401]}, - {t: 'L', p: [156.2, 348.401]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [187, 362.401]}, - {t: 'C', p: [187, 362.401, 192.2, 362.001, 191, 363.601]}, - {t: 'C', p: [189.8, 365.201, 187.4, 364.401, 187.4, 364.401]}, - {t: 'L', p: [187, 362.401]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [178.2, 362.001]}, - {t: 'C', p: [178.2, 362.001, 183.4, 361.601, 182.2, 363.201]}, - {t: 'C', p: [181, 364.801, 178.6, 364.001, 178.6, 364.001]}, - {t: 'L', p: [178.2, 362.001]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [82.831, 350.182]}, - {t: 'C', p: [82.831, 350.182, 87.876, 351.505, 86.218, 352.624]}, - {t: 'C', p: [84.561, 353.744, 82.554, 352.202, 82.554, 352.202]}, - {t: 'L', p: [82.831, 350.182]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [84.831, 340.582]}, - {t: 'C', p: [84.831, 340.582, 89.876, 341.905, 88.218, 343.024]}, - {t: 'C', p: [86.561, 344.144, 84.554, 342.602, 84.554, 342.602]}, - {t: 'L', p: [84.831, 340.582]}, - {t: 'z', p: []}]}, - -{f: '#000', s: null, p: [{t: 'M', p: [77.631, 336.182]}, - {t: 'C', p: [77.631, 336.182, 82.676, 337.505, 81.018, 338.624]}, - {t: 'C', p: [79.361, 339.744, 77.354, 338.202, 77.354, 338.202]}, - {t: 'L', p: [77.631, 336.182]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [157.4, 411.201]}, - {t: 'C', p: [157.4, 411.201, 155.8, 411.201, 151.8, 413.201]}, - {t: 'C', p: [149.8, 413.201, 138.6, 416.801, 133, 426.801]}, - {t: 'C', p: [133, 426.801, 145.4, 417.201, 157.4, 411.201]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [245.116, 503.847]}, - {t: 'C', p: [245.257, 504.105, 245.312, 504.525, 245.604, 504.542]}, - {t: 'C', p: [246.262, 504.582, 247.495, 504.883, 247.37, 504.247]}, - {t: 'C', p: [246.522, 499.941, 245.648, 495.004, 241.515, 493.197]}, - {t: 'C', p: [240.876, 492.918, 239.434, 493.331, 239.36, 494.215]}, - {t: 'C', p: [239.233, 495.739, 239.116, 497.088, 239.425, 498.554]}, - {t: 'C', p: [239.725, 499.975, 241.883, 499.985, 242.8, 498.601]}, - {t: 'C', p: [243.736, 500.273, 244.168, 502.116, 245.116, 503.847]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [234.038, 508.581]}, - {t: 'C', p: [234.786, 509.994, 234.659, 511.853, 236.074, 512.416]}, - {t: 'C', p: [236.814, 512.71, 238.664, 511.735, 238.246, 510.661]}, - {t: 'C', p: [237.444, 508.6, 237.056, 506.361, 235.667, 504.55]}, - {t: 'C', p: [235.467, 504.288, 235.707, 503.755, 235.547, 503.427]}, - {t: 'C', p: [234.953, 502.207, 233.808, 501.472, 232.4, 501.801]}, - {t: 'C', p: [231.285, 504.004, 232.433, 506.133, 233.955, 507.842]}, - {t: 'C', p: [234.091, 507.994, 233.925, 508.37, 234.038, 508.581]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [194.436, 503.391]}, - {t: 'C', p: [194.328, 503.014, 194.29, 502.551, 194.455, 502.23]}, - {t: 'C', p: [194.986, 501.197, 195.779, 500.075, 195.442, 499.053]}, - {t: 'C', p: [195.094, 497.997, 193.978, 498.179, 193.328, 498.748]}, - {t: 'C', p: [192.193, 499.742, 192.144, 501.568, 191.453, 502.927]}, - {t: 'C', p: [191.257, 503.313, 191.308, 503.886, 190.867, 504.277]}, - {t: 'C', p: [190.393, 504.698, 189.953, 506.222, 190.049, 506.793]}, - {t: 'C', p: [190.102, 507.106, 189.919, 517.014, 190.141, 516.751]}, - {t: 'C', p: [190.76, 516.018, 193.81, 506.284, 193.879, 505.392]}, - {t: 'C', p: [193.936, 504.661, 194.668, 504.196, 194.436, 503.391]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [168.798, 496.599]}, - {t: 'C', p: [171.432, 494.1, 174.222, 491.139, 173.78, 487.427]}, - {t: 'C', p: [173.664, 486.451, 171.889, 486.978, 171.702, 487.824]}, - {t: 'C', p: [170.9, 491.449, 168.861, 494.11, 166.293, 496.502]}, - {t: 'C', p: [164.097, 498.549, 162.235, 504.893, 162, 505.401]}, - {t: 'C', p: [165.697, 500.145, 167.954, 497.399, 168.798, 496.599]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [155.224, 490.635]}, - {t: 'C', p: [155.747, 490.265, 155.445, 489.774, 155.662, 489.442]}, - {t: 'C', p: [156.615, 487.984, 157.916, 486.738, 157.934, 485]}, - {t: 'C', p: [157.937, 484.723, 157.559, 484.414, 157.224, 484.638]}, - {t: 'C', p: [156.947, 484.822, 156.605, 484.952, 156.497, 485.082]}, - {t: 'C', p: [154.467, 487.531, 153.067, 490.202, 151.624, 493.014]}, - {t: 'C', p: [151.441, 493.371, 150.297, 497.862, 150.61, 497.973]}, - {t: 'C', p: [150.849, 498.058, 152.569, 493.877, 152.779, 493.763]}, - {t: 'C', p: [154.042, 493.077, 154.054, 491.462, 155.224, 490.635]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [171.957, 510.179]}, - {t: 'C', p: [172.401, 509.31, 173.977, 508.108, 173.864, 507.219]}, - {t: 'C', p: [173.746, 506.291, 174.214, 504.848, 173.302, 505.536]}, - {t: 'C', p: [172.045, 506.484, 168.596, 507.833, 168.326, 513.641]}, - {t: 'C', p: [168.3, 514.212, 171.274, 511.519, 171.957, 510.179]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [186.4, 493.001]}, - {t: 'C', p: [186.8, 492.333, 187.508, 492.806, 187.967, 492.543]}, - {t: 'C', p: [188.615, 492.171, 189.226, 491.613, 189.518, 490.964]}, - {t: 'C', p: [190.488, 488.815, 192.257, 486.995, 192.4, 484.601]}, - {t: 'C', p: [190.909, 483.196, 190.23, 485.236, 189.6, 486.201]}, - {t: 'C', p: [188.277, 484.554, 187.278, 486.428, 185.978, 486.947]}, - {t: 'C', p: [185.908, 486.975, 185.695, 486.628, 185.62, 486.655]}, - {t: 'C', p: [184.443, 487.095, 183.763, 488.176, 182.765, 488.957]}, - {t: 'C', p: [182.594, 489.091, 182.189, 488.911, 182.042, 489.047]}, - {t: 'C', p: [181.39, 489.65, 180.417, 489.975, 180.137, 490.657]}, - {t: 'C', p: [179.027, 493.364, 175.887, 495.459, 174, 503.001]}, - {t: 'C', p: [174.381, 503.91, 178.512, 496.359, 178.999, 495.661]}, - {t: 'C', p: [179.835, 494.465, 179.953, 497.322, 181.229, 496.656]}, - {t: 'C', p: [181.28, 496.629, 181.466, 496.867, 181.6, 497.001]}, - {t: 'C', p: [181.794, 496.721, 182.012, 496.492, 182.4, 496.601]}, - {t: 'C', p: [182.4, 496.201, 182.266, 495.645, 182.467, 495.486]}, - {t: 'C', p: [183.704, 494.509, 183.62, 493.441, 184.4, 492.201]}, - {t: 'C', p: [184.858, 492.99, 185.919, 492.271, 186.4, 493.001]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [246.2, 547.401]}, - {t: 'C', p: [246.2, 547.401, 253.6, 527.001, 249.2, 515.801]}, - {t: 'C', p: [249.2, 515.801, 260.6, 537.401, 256, 548.601]}, - {t: 'C', p: [256, 548.601, 255.6, 538.201, 251.6, 533.201]}, - {t: 'C', p: [251.6, 533.201, 247.6, 546.001, 246.2, 547.401]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [231.4, 544.801]}, - {t: 'C', p: [231.4, 544.801, 236.8, 536.001, 228.8, 517.601]}, - {t: 'C', p: [228.8, 517.601, 228, 538.001, 221.2, 549.001]}, - {t: 'C', p: [221.2, 549.001, 235.4, 528.801, 231.4, 544.801]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [221.4, 542.801]}, - {t: 'C', p: [221.4, 542.801, 221.2, 522.801, 221.6, 519.801]}, - {t: 'C', p: [221.6, 519.801, 217.8, 536.401, 207.6, 546.001]}, - {t: 'C', p: [207.6, 546.001, 222, 534.001, 221.4, 542.801]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [211.8, 510.801]}, - {t: 'C', p: [211.8, 510.801, 217.8, 524.401, 207.8, 542.801]}, - {t: 'C', p: [207.8, 542.801, 214.2, 530.601, 209.4, 523.601]}, - {t: 'C', p: [209.4, 523.601, 212, 520.201, 211.8, 510.801]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [192.6, 542.401]}, - {t: 'C', p: [192.6, 542.401, 191.6, 526.801, 193.4, 524.601]}, - {t: 'C', p: [193.4, 524.601, 193.6, 518.201, 193.2, 517.201]}, - {t: 'C', p: [193.2, 517.201, 197.2, 511.001, 197.4, 518.401]}, - {t: 'C', p: [197.4, 518.401, 198.8, 526.201, 201.6, 530.801]}, - {t: 'C', p: [201.6, 530.801, 205.2, 536.201, 205, 542.601]}, - {t: 'C', p: [205, 542.601, 195, 512.401, 192.6, 542.401]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [189, 514.801]}, - {t: 'C', p: [189, 514.801, 182.4, 525.601, 180.6, 544.601]}, - {t: 'C', p: [180.6, 544.601, 179.2, 538.401, 183, 524.001]}, - {t: 'C', p: [183, 524.001, 187.2, 508.601, 189, 514.801]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [167.2, 534.601]}, - {t: 'C', p: [167.2, 534.601, 172.2, 529.201, 173.6, 524.201]}, - {t: 'C', p: [173.6, 524.201, 177.2, 508.401, 170.8, 517.001]}, - {t: 'C', p: [170.8, 517.001, 171, 525.001, 162.8, 532.401]}, - {t: 'C', p: [162.8, 532.401, 167.6, 530.001, 167.2, 534.601]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [161.4, 529.601]}, - {t: 'C', p: [161.4, 529.601, 164.8, 512.201, 165.6, 511.401]}, - {t: 'C', p: [165.6, 511.401, 167.4, 508.001, 164.6, 511.201]}, - {t: 'C', p: [164.6, 511.201, 155.8, 530.401, 151.8, 537.001]}, - {t: 'C', p: [151.8, 537.001, 159.8, 527.801, 161.4, 529.601]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [155.6, 513.001]}, - {t: 'C', p: [155.6, 513.001, 167.2, 490.601, 145.4, 516.401]}, - {t: 'C', p: [145.4, 516.401, 156.4, 506.601, 155.6, 513.001]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [140.2, 498.401]}, - {t: 'C', p: [140.2, 498.401, 145, 479.601, 147.6, 479.801]}, - {t: 'C', p: [147.6, 479.801, 155.8, 470.801, 149.2, 481.401]}, - {t: 'C', p: [149.2, 481.401, 143.2, 491.001, 143.8, 500.801]}, - {t: 'C', p: [143.8, 500.801, 143.2, 491.201, 140.2, 498.401]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [470.5, 487]}, - {t: 'C', p: [470.5, 487, 458.5, 477, 456, 473.5]}, - {t: 'C', p: [456, 473.5, 469.5, 492, 469.5, 499]}, - {t: 'C', p: [469.5, 499, 472, 491.5, 470.5, 487]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [476, 465]}, - {t: 'C', p: [476, 465, 455, 450, 451.5, 442.5]}, - {t: 'C', p: [451.5, 442.5, 478, 472, 478, 476.5]}, - {t: 'C', p: [478, 476.5, 478.5, 467.5, 476, 465]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [493, 311]}, - {t: 'C', p: [493, 311, 481, 303, 479.5, 305]}, - {t: 'C', p: [479.5, 305, 490, 311.5, 492.5, 320]}, - {t: 'C', p: [492.5, 320, 491, 311, 493, 311]}, - {t: 'z', p: []}]}, - -{f: '#ccc', s: null, p: [{t: 'M', p: [501.5, 391.5]}, - {t: 'L', p: [484, 379.5]}, - {t: 'C', p: [484, 379.5, 503, 396.5, 503.5, 400.5]}, - {t: 'L', p: [501.5, 391.5]}, - {t: 'z', p: []}]}, - -{f: null, s: '#000', p: [{t: 'M', p: [110.75, 369]}, - {t: 'L', p: [132.75, 373.75]}]}, - -{f: null, s: '#000', p: [{t: 'M', p: [161, 531]}, - {t: 'C', p: [161, 531, 160.5, 527.5, 151.5, 538]}]}, - -{f: null, s: '#000', p: [{t: 'M', p: [166.5, 536]}, - {t: 'C', p: [166.5, 536, 168.5, 529.5, 162, 534]}]}, - -{f: null, s: '#000', p: [{t: 'M', p: [220.5, 544.5]}, - {t: 'C', p: [220.5, 544.5, 222, 533.5, 210.5, 546.5]}]}] diff --git a/src/database/third_party/closure-library/closure/goog/demos/history1.html b/src/database/third_party/closure-library/closure/goog/demos/history1.html deleted file mode 100644 index 63b3a0c04cb..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/history1.html +++ /dev/null @@ -1,132 +0,0 @@ - - - - - goog.History - - - - - - - -

goog.History

-

This page demonstrates the goog.History object which can create new browser - history entries without leaving the page. This version uses the hash portion of - the URL to make the history state available to the user. These URLs can be - bookmarked, edited, pasted in emails, etc., just like normal URLs. The browser's - back and forward buttons will navigate between the visited history states.

- -

Try following the hash links below, or updating the location with your own - tokens. Replacing the token will update the page address without appending a - new history entry.

- -

- Set #fragment
- first
- second
- third -

- -

- Set Token
- - - - - -

- -

- - - -

- -
-

The current history state:

-
-
- -

The state should be correctly restored after you - leave the page and hit the back button.

- -

The history object can also be created so that the history state is not - user-visible/modifiable. - See history2.html for a demo. - To see visible/modifiable history work when the goog.History code itself is - loaded inside a hidden iframe, - see history3.html. -

- -
- Event Log -
-
- - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/history2.html b/src/database/third_party/closure-library/closure/goog/demos/history2.html deleted file mode 100644 index 01a166041cc..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/history2.html +++ /dev/null @@ -1,119 +0,0 @@ - - - - - goog.History #2 - - - - - - -

goog.History #2

-

This page demonstrates the goog.History object which can create new browser - history entries without leaving the page. This version maintains the history - state internally, so that states are not visible or editable by the user, but - the back and forward buttons can still be used to move between history states. -

- -

Try setting a few history tokens using the buttons and box below, then hit - the back and forward buttons to test if the tokens are correctly restored.

- - - - -
- - - - - - - -

- - - -

- -
-

The current history state:

-
-
- -

The state should be correctly restored after you - leave the page and hit the back button.

- -

The history object can also be created so that the history state is visible - and modifiable by the user. See history1.html for a - demo.

- -
- Event Log -
-
- - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/history3.html b/src/database/third_party/closure-library/closure/goog/demos/history3.html deleted file mode 100644 index d1466f80f98..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/history3.html +++ /dev/null @@ -1,116 +0,0 @@ - - - - -History Demo 3 - - - - - - -

This page demonstrates a goog.History object used in an iframe. Loading JS -code in an iframe is useful for large apps because the JS code can be sent in -bite-sized script blocks that browsers can evaluate incrementally, as they are -received over the wire.

- -

For an introduction to the goog.History object, see history1.html and history2.html. This demo uses visible history, like -the first demo.

- -

Try following the hash links below, or updating the location with your own -tokens. Replacing the token will update the page address without appending a -new history entry.

- -

- Set #fragment
- first
- second
- third -

- -

- Set Token
- - - - - -

- -

- - - -

- -
-

The current history state:

-
-
- -

The state should be correctly restored after you -leave the page and hit the back button.

- -
- Event Log -
-
- - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/history3js.html b/src/database/third_party/closure-library/closure/goog/demos/history3js.html deleted file mode 100644 index 072dfca6b69..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/history3js.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - -History Demo JavaScript Page - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/history_blank.html b/src/database/third_party/closure-library/closure/goog/demos/history_blank.html deleted file mode 100644 index 189d905626c..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/history_blank.html +++ /dev/null @@ -1,26 +0,0 @@ - - - -Intentionally left blank - - -This is a blank helper page for the goog.History demos. See -demo 1 and -demo 2. - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/hovercard.html b/src/database/third_party/closure-library/closure/goog/demos/hovercard.html deleted file mode 100644 index c36f6d314e2..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/hovercard.html +++ /dev/null @@ -1,177 +0,0 @@ - - - - - goog.ui.HoverCard - - - - - - - -

goog.ui.HoverCard

-

- Show by mouse position:


- Tom Smith - Dick Jones - Harry Brown - -


Show hovercard to the right:


- Tom Smith - Dick Jones - Harry Brown - -


Show hovercard below:


- Tom Smith - Dick Jones - Harry Brown - -


- -

- - - - -
- Event Log -
-
-
-
- - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/hsvapalette.html b/src/database/third_party/closure-library/closure/goog/demos/hsvapalette.html deleted file mode 100644 index ec60c75d568..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/hsvapalette.html +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - goog.ui.HsvaPalette - - - - - - - -

goog.ui.HsvaPalette

- -

Normal Size

- - - -

Smaller Size

- - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/hsvpalette.html b/src/database/third_party/closure-library/closure/goog/demos/hsvpalette.html deleted file mode 100644 index 2717ed18e57..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/hsvpalette.html +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - goog.ui.HsvPalette - - - - - - - -

goog.ui.HsvPalette

- -

Normal Size

- - - -

Smaller Size

- - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/html5history.html b/src/database/third_party/closure-library/closure/goog/demos/html5history.html deleted file mode 100644 index b8868462053..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/html5history.html +++ /dev/null @@ -1,87 +0,0 @@ - - - - - goog.history.Html5History Demo - - - - - - -

goog.history.Html5History

- - - -
- -
-
- -
-
- -
-
- -
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/imagelessbutton.html b/src/database/third_party/closure-library/closure/goog/demos/imagelessbutton.html deleted file mode 100644 index 86462d72e98..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/imagelessbutton.html +++ /dev/null @@ -1,221 +0,0 @@ - - - - - - goog.ui.ImagelessButtonRenderer Demo - - - - - - - - -

goog.ui.ImagelessButtonRenderer

-
- - These buttons were rendered using - goog.ui.ImagelessButtonRenderer: - -
- These buttons were created programmatically:
-
-
- These buttons were created by decorating some DIVs, and they dispatch - state transition events (watch the event log):
-
- -
- Decorated Button, yay! -
-
Decorated Disabled
-
Another Button
-
- Archive -
- Delete -
- Report Spam -
-
-
- Use these ToggleButtons to hide/show and enable/disable - the middle button:
-
Enable
- -
Show
- -

- Combined toggle buttons
-
- Bold -
- Italics -
- Underlined -
-

- These buttons have icons, and the second one has an extra CSS class:
-
-
-
-
-
- -
- Event Log -
-
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/imagelessmenubutton.html b/src/database/third_party/closure-library/closure/goog/demos/imagelessmenubutton.html deleted file mode 100644 index cdf18d605e1..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/imagelessmenubutton.html +++ /dev/null @@ -1,285 +0,0 @@ - - - - - goog.ui.ImagelessMenuButtonRenderer Demo - - - - - - - - - - - - -

goog.ui.ImagelessMenuButtonRenderer

- - - - - - - -
-
- - These MenuButtons were created programmatically: -   - - - - - - - - -
- - - Enable first button: - -   - Show second button: - -   -
- -
-
-
- - This MenuButton decorates an element:  - - - - - - - - -
-
- -
- Format - -
-
Bold
-
Italic
-
Underline
-
-
- Strikethrough -
-
-
Font...
-
Color...
-
-
-
- Enable button: - -   - Show button: - -   -
- -
-
-
- -
- Event Log -
-
-
-
-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/index.html b/src/database/third_party/closure-library/closure/goog/demos/index.html deleted file mode 100644 index 056c8938039..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/index.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - Closure Demos - - - - - - - Are you kidding me? No frames?!? - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/index_nav.html b/src/database/third_party/closure-library/closure/goog/demos/index_nav.html deleted file mode 100644 index 1002554e070..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/index_nav.html +++ /dev/null @@ -1,255 +0,0 @@ - - - - - Closure Demos - - - - - - - -

Index

-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/index_splash.html b/src/database/third_party/closure-library/closure/goog/demos/index_splash.html deleted file mode 100644 index 86397df9b82..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/index_splash.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - Closure Demos - - - - -

Welcome to Closure!

-

Use the tree in the navigation pane to view Closure demos.

-
-

New! Common UI Controls

-

Check out these widgets by clicking on the demo links on the left:

- Common UI controls - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/inline_block_quirks.html b/src/database/third_party/closure-library/closure/goog/demos/inline_block_quirks.html deleted file mode 100644 index 75202b8148d..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/inline_block_quirks.html +++ /dev/null @@ -1,125 +0,0 @@ - - - - goog.style.setInlineBlock in quirks mode - - - - - - - -

goog.style.setInlineBlock in quirks mode

-

- This is a demonstration of the goog-inline-block CSS style. - This page is in quirks mode. - Click here for standards mode. -

-
- Hey, are these really -
DIV
s - inlined in my text here? I mean, I thought -
DIV
s - were block-level elements, and you couldn't inline them... - Must be that new -
goog-inline-block
- style... (Hint: Try resizing the window to see the -
DIV
s - flow naturally.) - Arv asked for an inline-block DIV with more interesting contents, so here - goes: -
-
- blue dot - Lorem ipsum dolor sit amet, - consectetuer adipiscing elit. - Donec rhoncus neque ut - neque porta consequat. - In tincidunt tellus vehicula tellus. Etiam ornare nunc - vel lectus. Vivamus quis nibh. Sed nunc. - On FF1.5 and FF2.0, you need to wrap the contents of your - inline-block element in a DIV or P with fixed width to get line - wrapping. -
-
-
-
-

- These are - SPANs - with the - goog-inline-block - style applied, so you can style them like block-level elements. - For example, give them - 10px margin, a - 10px border, or - 10px padding. - I used - vertical-align: middle - to make them all line up reasonably well. - (Except on Safari 2. Go figure.) -

-

- This is what the same content looks like without goog-inline-block: -

-

- These are - SPANs - with the - goog-inline-block - style applied, so you can style them like block-level elements. - For example, give them - 10px margin, a - 10px border, or - 10px padding. - I used - vertical-align: middle - to make them all line up reasonably well. - (Except on Safari 2. Go figure.) -

-

- Click here to use goog.style.setInlineBlock() to apply the inline-block style to these SPANs. -

-
-

- Works on Internet Explorer 6 & 7, Firefox 1.5, 2.0 & 3.0 Beta, Safari 2 & 3, - Webkit nightlies, and Opera 9. - Note: DIVs nested in SPANs don't work on Opera. -

- - diff --git a/src/database/third_party/closure-library/closure/goog/demos/inline_block_standards.html b/src/database/third_party/closure-library/closure/goog/demos/inline_block_standards.html deleted file mode 100644 index 5f4304893fb..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/inline_block_standards.html +++ /dev/null @@ -1,126 +0,0 @@ - - - - - goog.style.setInlineBlock in standards mode - - - - - - - -

goog.style.setInlineBlock in standards mode

-

- This is a demonstration of the goog-inline-block CSS style. - This page is in standards mode. - Click here for quirks mode. -

-
- Hey, are these really -
DIV
s - inlined in my text here? I mean, I thought -
DIV
s - were block-level elements, and you couldn't inline them... - Must be that new -
goog-inline-block
- style... (Hint: Try resizing the window to see the -
DIV
s - flow naturally.) - Arv asked for an inline-block DIV with more interesting contents, so here - goes: -
-
- blue dot - Lorem ipsum dolor sit amet, - consectetuer adipiscing elit. - Donec rhoncus neque ut - neque porta consequat. - In tincidunt tellus vehicula tellus. Etiam ornare nunc - vel lectus. Vivamus quis nibh. Sed nunc. - On FF1.5 and FF2.0, you need to wrap the contents of your - inline-block element in a DIV or P with fixed width to get line - wrapping. -
-
-
-
-

- These are - SPANs - with the - goog-inline-block - style applied, so you can style them like block-level elements. - For example, give them - 10px margin, a - 10px border, or - 10px padding. - I used - vertical-align: middle - to make them all line up reasonably well. - (Except on Safari 2. Go figure.) -

-

- This is what the same content looks like without goog-inline-block: -

-

- These are - SPANs - with the - goog-inline-block - style applied, so you can style them like block-level elements. - For example, give them - 10px margin, a - 10px border, or - 10px padding. - I used - vertical-align: middle - to make them all line up reasonably well. - (Except on Safari 2. Go figure.) -

-

- Click here to use goog.style.setInlineBlock() to apply the inline-block style to these SPANs. -

-
-

- Works on Internet Explorer 6 & 7, Firefox 1.5, 2.0 & 3.0 Beta, Safari 2 & 3, - Webkit nightlies, and Opera 9. - Note: DIVs nested in SPANs don't work on Opera. -

- - diff --git a/src/database/third_party/closure-library/closure/goog/demos/inputdatepicker.html b/src/database/third_party/closure-library/closure/goog/demos/inputdatepicker.html deleted file mode 100644 index 1e6c25fe012..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/inputdatepicker.html +++ /dev/null @@ -1,60 +0,0 @@ - - - - - goog.ui.InputDatePicker - - - - - - - - -

goog.ui.InputDatePicker

- -
- -
-
- -
-
- - -
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/inputhandler.html b/src/database/third_party/closure-library/closure/goog/demos/inputhandler.html deleted file mode 100644 index 5559bfc345b..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/inputhandler.html +++ /dev/null @@ -1,84 +0,0 @@ - - - - -goog.events.InputHandler - - - - - -

goog.events.InputHandler

-

- - -

- - - -

- - -

-

- Event Log -
-
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/jsonprettyprinter.html b/src/database/third_party/closure-library/closure/goog/demos/jsonprettyprinter.html deleted file mode 100644 index 369d7483f3b..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/jsonprettyprinter.html +++ /dev/null @@ -1,80 +0,0 @@ - - - - -Demo - goog.format.JsonPrettyPrinter - - - - - - - -Pretty-printed JSON. -
-
- -Pretty-printed JSON (Formatted using CSS). -
-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/keyboardshortcuts.html b/src/database/third_party/closure-library/closure/goog/demos/keyboardshortcuts.html deleted file mode 100644 index 2baec7b813b..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/keyboardshortcuts.html +++ /dev/null @@ -1,112 +0,0 @@ - - - - - goog.ui.KeyboardShortcutHandler - - - - - - -

goog.ui.KeyboardShortcutHandler

-
- - - - - - -
-    Shortcuts:
-      A
-      T E S T
-      Shift+F12
-      Shift+F11 C
-      Ctrl+A
-      G O O G
-      B C
-      B D
-      Alt+Q A
-      Alt+Q Shift+A
-      Alt+Q Shift+B
-      Space
-      Home
-      Enter
-      G S
-      S
-      Meta+y
-  
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/keyhandler.html b/src/database/third_party/closure-library/closure/goog/demos/keyhandler.html deleted file mode 100644 index b76d7ad6adb..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/keyhandler.html +++ /dev/null @@ -1,118 +0,0 @@ - - - - -goog.events.KeyHandler - - - - - - -

goog.events.KeyHandler

-

- -
-
-
-
-
Focusable div
-
- -
- No Tab inside this

- -
-
-
-
Focusable div
-
- -
- - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/labelinput.html b/src/database/third_party/closure-library/closure/goog/demos/labelinput.html deleted file mode 100644 index a760b667f11..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/labelinput.html +++ /dev/null @@ -1,42 +0,0 @@ - - - - - goog.ui.LabelInput - - - - - - -

goog.ui.LabelInput

-

This component decorates an input with default text which disappears upon focus.

-
- -
- - -
- - diff --git a/src/database/third_party/closure-library/closure/goog/demos/menu.html b/src/database/third_party/closure-library/closure/goog/demos/menu.html deleted file mode 100644 index 39eafef4ae0..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/menu.html +++ /dev/null @@ -1,220 +0,0 @@ - - - - - goog.ui.Menu - - - - - - - - -

goog.ui.Menu

-
- This is a very basic menu class, it doesn't handle its display or - dismissal. It just exists, listens to keys and mouse events and can fire - events for selections or highlights. -
- -
-
- - - - - - - - - - - - - -
- - - - - -
- Here's a menu with checkbox items.
You checked:  - Bold
- -
- Here's a BiDi menu with checkbox items.
- -
- Here's a menu with an explicit content container.
- -
-
-
- -
- Event Log -
-
-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/menubar.html b/src/database/third_party/closure-library/closure/goog/demos/menubar.html deleted file mode 100644 index f559ea25180..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/menubar.html +++ /dev/null @@ -1,211 +0,0 @@ - - - - - goog.ui.menuBar Demo - - - - - - - - - - - - -

goog.ui.menuBar example

- - - - - - - - - - - -
-
- - This menu bar was created programmatically: -   - - - - - - - -
- -
-
-
-
-
- - This menu bar is decorated: -   - - - -
- - -
-
-
-
- -
- Event Log -
-
-
-
-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/menubutton.html b/src/database/third_party/closure-library/closure/goog/demos/menubutton.html deleted file mode 100644 index a15f2ec563a..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/menubutton.html +++ /dev/null @@ -1,380 +0,0 @@ - - - - - goog.ui.MenuButton Demo - - - - - - - - - - - -

goog.ui.MenuButton

- - - - - - - -
-
- - These MenuButtons were created programmatically: -   - - - - - - - - -
- - - Enable first button: - -   - Show second button: - -   -
- -
-
-
- - This MenuButton decorates an element:  - - - - - - - - -
-
- -
- Format - -
-
Bold
-
Italic
-
Underline
-
-
- Strikethrough -
-
-
Font...
-
Color...
-
-
-
- Enable button: - -   - Show button: - -   -
- -
-
-
- - This MenuButton accompanies a - CustomButton to form a combo button: -   - -
- -
-
-
- - These MenuButtons demonstrate - menu positioning options: -   - -
- - - - - -
-
-
- -
- Event Log -
-
-
-
-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/menubutton_frame.html b/src/database/third_party/closure-library/closure/goog/demos/menubutton_frame.html deleted file mode 100644 index 7f01363922a..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/menubutton_frame.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - goog.ui.MenuButton Positioning Frame Demo - - - - - - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/menuitem.html b/src/database/third_party/closure-library/closure/goog/demos/menuitem.html deleted file mode 100644 index 433d680c75d..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/menuitem.html +++ /dev/null @@ -1,164 +0,0 @@ - - - - - goog.ui.MenuItem Demo - - - - - - - - - - - -

goog.ui.MenuItem

- - - - - - -
-
- - Use the first letter of each menuitem to activate:   - - - - - - - -
- -
- -
-
-
- -
- Event Log -
-
-
-
-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/mousewheelhandler.html b/src/database/third_party/closure-library/closure/goog/demos/mousewheelhandler.html deleted file mode 100644 index ebbc6c42124..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/mousewheelhandler.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - -goog.events.MouseWheelHandler - - - - - - - -

goog.events.MouseWheelHandler

- -

Use your mousewheel on the gray box below to move the cross hair. - -

-
-
-
-
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/onlinehandler.html b/src/database/third_party/closure-library/closure/goog/demos/onlinehandler.html deleted file mode 100644 index 21bbcb5c6d1..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/onlinehandler.html +++ /dev/null @@ -1,79 +0,0 @@ - - - - - -goog.net.OnlineHandler - - - - - - -

This page reports whether your browser is online or offline. It will detect -changes to the reported state and fire events when this changes. The -OnlineHandler acts as a wrapper around the HTML5 events online and -offline and emulates these for older browsers.

- -

Try changing File -> Work Offline in your browser.

- -

- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/palette.html b/src/database/third_party/closure-library/closure/goog/demos/palette.html deleted file mode 100644 index 2c9ed5e48ab..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/palette.html +++ /dev/null @@ -1,299 +0,0 @@ - - - - - goog.ui.Palette & goog.ui.ColorPalette - - - - - - - -

goog.ui.Palette & goog.ui.ColorPalette

- - - - - - - -
-
- Demo of the goog.ui.Palette: -
- - -
- Note that if you don't specify any dimensions, the palette will auto-size - to fit your items in the smallest square.
-
-
-
-
- Demo of the goog.ui.ColorPalette: -
-

The color you selected was: - -   - - -

-
-
-
-
- Demo of the goog.ui.CustomColorPalette: -
-

The color you selected was: - -   - - -

-
-
- -
- Event Log -
-
-
-
-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/pastehandler.html b/src/database/third_party/closure-library/closure/goog/demos/pastehandler.html deleted file mode 100644 index ac42f411ce2..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/pastehandler.html +++ /dev/null @@ -1,54 +0,0 @@ - - - - - PasteHandler Test - - - - - -

Demo of goog.events.PasteHandler

- -
- Demo of the goog.events.PasteHandler: - - -
- -
- Event Log -
-
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/pixeldensitymonitor.html b/src/database/third_party/closure-library/closure/goog/demos/pixeldensitymonitor.html deleted file mode 100644 index 0cbe2a4922b..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/pixeldensitymonitor.html +++ /dev/null @@ -1,51 +0,0 @@ - - - - - goog.labs.style.PixelDensityMonitor - - - - - -

goog.labs.style.PixelDensityMonitor

-
- Move between high dpi and normal screens to see density change events. -
-
- Event log -
-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/plaintextspellchecker.html b/src/database/third_party/closure-library/closure/goog/demos/plaintextspellchecker.html deleted file mode 100644 index 88b23b94ea5..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/plaintextspellchecker.html +++ /dev/null @@ -1,118 +0,0 @@ - - - - -Plain Text Spell Checker - - - - - - -

Plain Text Spell Checker

-

- The words "test", "words", "a", and "few" are set to be valid words, - all others are considered spelling mistakes. -

-

- The following keyboard shortcuts can be used to navigate inside the editor: -

    -
  • Previous misspelled word: ctrl + left-arrow
  • -
  • next misspelled word: ctrl + right-arrow
  • -
  • Open suggestions menu: down arrow
  • -
-

-

- - - - -

- - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/popup.html b/src/database/third_party/closure-library/closure/goog/demos/popup.html deleted file mode 100644 index 91d286cdd59..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/popup.html +++ /dev/null @@ -1,206 +0,0 @@ - - - - - goog.ui.Popup - - - - - - - -

goog.ui.Popup

- - -

Positioning relative to an anchor element

-
- Button Corner - - - - -
- Popup Corner - - - - - -
- Margin - Top: - Right: - Bottom: - Left: - - -
-
-
-
- - - -
-
- -

Iframe to test cross frame dismissal

- - -
-
- -
-

Positioning at coordinates

-
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/popupcolorpicker.html b/src/database/third_party/closure-library/closure/goog/demos/popupcolorpicker.html deleted file mode 100644 index a52d8207e29..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/popupcolorpicker.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - - goog.ui.PopupColorPicker - - - - - - - -

goog.ui.PopupColorPicker

- Show 1 - Show 2 - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/popupdatepicker.html b/src/database/third_party/closure-library/closure/goog/demos/popupdatepicker.html deleted file mode 100644 index f83ea400b1c..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/popupdatepicker.html +++ /dev/null @@ -1,53 +0,0 @@ - - - - - goog.ui.PopupDatePicker - - - - - - - - -

goog.ui.PopupDatePicker

- - Show 1 - Show 2 - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/popupemojipicker.html b/src/database/third_party/closure-library/closure/goog/demos/popupemojipicker.html deleted file mode 100644 index ebf15212816..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/popupemojipicker.html +++ /dev/null @@ -1,408 +0,0 @@ - - - - - Popup Emoji Picker - - - - - - - - - -

Popup Emoji Picker Demo

-This is a demo of popupemojipickers and docked emoji pickers. Selecting an -emoji inserts a pseudo image tag into the text area with the id of that emoji. - -

Sprited Emojipicker (contains a mix of sprites and non-sprites):

-
- -

Sprited Progressively-rendered Emojipicker (contains a mix of sprites and - non-sprites):

-
-

Popup Emoji:

-Gimme some emoji -
- -

Fast-load Progressive Sprited Emojipicker

-
- -

Fast-load Non-progressive Sprited Emojipicker

-
- -
- -

Docked emoji:

-
- -

Single Page of Emoji

-
- -

Delayed load popup picker:

-More emoji - -

Delayed load docked picker:

- - Click to load - -
- - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/popupmenu.html b/src/database/third_party/closure-library/closure/goog/demos/popupmenu.html deleted file mode 100644 index 92f6a284003..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/popupmenu.html +++ /dev/null @@ -1,115 +0,0 @@ - - - - - goog.ui.PopupMenu - - - - - - - - - -

goog.ui.PopupMenu

-
- This shows a 2 popup menus, each menu has been attached to two targets. -

-
- -
- Event log -
-
-
-
- Hello there I'm italic! -
-
-
- - - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/progressbar.html b/src/database/third_party/closure-library/closure/goog/demos/progressbar.html deleted file mode 100644 index 246db3a379e..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/progressbar.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - goog.ui.ProgressBar - - - - - - -

goog.ui.ProgressBar

-
-
- -
-
-
- Decorated element -
-
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/prompt.html b/src/database/third_party/closure-library/closure/goog/demos/prompt.html deleted file mode 100644 index 700dccba0fe..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/prompt.html +++ /dev/null @@ -1,92 +0,0 @@ - - - - - goog.ui.Prompt - - - - - - - -

goog.ui.Prompt

- -

The default text is selected when the prompt displays

- -

You can use 'Enter' or 'Esc' to click 'Ok' or 'Cancel' respectively

- -

- - Prompt - -

- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/quadtree.html b/src/database/third_party/closure-library/closure/goog/demos/quadtree.html deleted file mode 100644 index e17e6dcf0fa..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/quadtree.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - -QuadTree Demo - - - - - -
-
-

Click on the area to the left to add a point to the quadtree, clicking on - a point will remove it from the tree.

-

-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/ratings.html b/src/database/third_party/closure-library/closure/goog/demos/ratings.html deleted file mode 100644 index c773674380f..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/ratings.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - -Ratings Widget - - - - - - -
- - -
-
-
-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/richtextspellchecker.html b/src/database/third_party/closure-library/closure/goog/demos/richtextspellchecker.html deleted file mode 100644 index e10036ca96b..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/richtextspellchecker.html +++ /dev/null @@ -1,101 +0,0 @@ - - - - - goog.ui.RichTextSpellChecker - - - - - - - -

goog.ui.RichTextSpellChecker

-

- The words "test", "words", "a", and "few" are set to be valid words, all others are considered spelling mistakes. -

-

- If keyboard navigation is enabled, then the following shortcuts can be used - inside the editor: -

    -
  • Previous misspelled word: ctrl + left-arrow
  • -
  • next misspelled word: ctrl + right-arrow
  • -
  • Open suggestions menu: down arrow
  • -
-

-

- -

- - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/roundedpanel.html b/src/database/third_party/closure-library/closure/goog/demos/roundedpanel.html deleted file mode 100644 index c11b111ee3b..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/roundedpanel.html +++ /dev/null @@ -1,139 +0,0 @@ - - - - - - goog.ui.RoundedPanel Demo - - - - - - - -
-
-
- Panel Width:
- -
-
- Panel Height:
- -
-
- Border Width:
- -
-
- Border Color:
- -
-
- Radius:
- -
-
- Background Color:
- -
-
- Corners:
- -
-
Rendering Time:
-
-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/samplecomponent.html b/src/database/third_party/closure-library/closure/goog/demos/samplecomponent.html deleted file mode 100644 index f5a8c51fa80..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/samplecomponent.html +++ /dev/null @@ -1,75 +0,0 @@ - - - - - goog.ui.Component - - - - - - - - - - -

goog.ui.Component

- - -
-

Click on this big, colored box:

-
- -
- -
-

Or this box:

- -
Label from decorated DIV.
-
- -
-

This box's label keeps changing:

- -
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/samplecomponent.js b/src/database/third_party/closure-library/closure/goog/demos/samplecomponent.js deleted file mode 100644 index d25d77deb84..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/samplecomponent.js +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview A simple, sample component. - * - */ -goog.provide('goog.demos.SampleComponent'); - -goog.require('goog.dom'); -goog.require('goog.dom.classlist'); -goog.require('goog.events.EventType'); -goog.require('goog.events.KeyCodes'); -goog.require('goog.events.KeyHandler'); -goog.require('goog.ui.Component'); - - - -/** - * A simple box that changes colour when clicked. This class demonstrates the - * goog.ui.Component API, and is keyboard accessible, as per - * http://wiki/Main/ClosureKeyboardAccessible - * - * @param {string=} opt_label A label to display. Defaults to "Click Me" if none - * provided. - * @param {goog.dom.DomHelper=} opt_domHelper DOM helper to use. - * - * @extends {goog.ui.Component} - * @constructor - * @final - */ -goog.demos.SampleComponent = function(opt_label, opt_domHelper) { - goog.base(this, opt_domHelper); - - /** - * The label to display. - * @type {string} - * @private - */ - this.initialLabel_ = opt_label || 'Click Me'; - - /** - * The current color. - * @type {string} - * @private - */ - this.color_ = 'red'; - - /** - * Keyboard handler for this object. This object is created once the - * component's DOM element is known. - * - * @type {goog.events.KeyHandler?} - * @private - */ - this.kh_ = null; -}; -goog.inherits(goog.demos.SampleComponent, goog.ui.Component); - - -/** - * Changes the color of the element. - * @private - */ -goog.demos.SampleComponent.prototype.changeColor_ = function() { - if (this.color_ == 'red') { - this.color_ = 'green'; - } else if (this.color_ == 'green') { - this.color_ = 'blue'; - } else { - this.color_ = 'red'; - } - this.getElement().style.backgroundColor = this.color_; -}; - - -/** - * Creates an initial DOM representation for the component. - * @override - */ -goog.demos.SampleComponent.prototype.createDom = function() { - this.decorateInternal(this.dom_.createElement('div')); -}; - - -/** - * Decorates an existing HTML DIV element as a SampleComponent. - * - * @param {Element} element The DIV element to decorate. The element's - * text, if any will be used as the component's label. - * @override - */ -goog.demos.SampleComponent.prototype.decorateInternal = function(element) { - goog.base(this, 'decorateInternal', element); - if (!this.getLabelText()) { - this.setLabelText(this.initialLabel_); - } - - var elem = this.getElement(); - goog.dom.classlist.add(elem, goog.getCssName('goog-sample-component')); - elem.style.backgroundColor = this.color_; - elem.tabIndex = 0; - - this.kh_ = new goog.events.KeyHandler(elem); - this.getHandler().listen(this.kh_, goog.events.KeyHandler.EventType.KEY, - this.onKey_); -}; - - -/** @override */ -goog.demos.SampleComponent.prototype.disposeInternal = function() { - goog.base(this, 'disposeInternal'); - if (this.kh_) { - this.kh_.dispose(); - } -}; - - -/** - * Called when component's element is known to be in the document. - * @override - */ -goog.demos.SampleComponent.prototype.enterDocument = function() { - goog.base(this, 'enterDocument'); - this.getHandler().listen(this.getElement(), goog.events.EventType.CLICK, - this.onDivClicked_); -}; - - -/** - * Called when component's element is known to have been removed from the - * document. - * @override - */ -goog.demos.SampleComponent.prototype.exitDocument = function() { - goog.base(this, 'exitDocument'); -}; - - -/** - * Gets the current label text. - * - * @return {string} The current text set into the label, or empty string if - * none set. - */ -goog.demos.SampleComponent.prototype.getLabelText = function() { - if (!this.getElement()) { - return ''; - } - return goog.dom.getTextContent(this.getElement()); -}; - - -/** - * Handles DIV element clicks, causing the DIV's colour to change. - * @param {goog.events.Event} event The click event. - * @private - */ -goog.demos.SampleComponent.prototype.onDivClicked_ = function(event) { - this.changeColor_(); -}; - - -/** - * Fired when user presses a key while the DIV has focus. If the user presses - * space or enter, the color will be changed. - * @param {goog.events.Event} event The key event. - * @private - */ -goog.demos.SampleComponent.prototype.onKey_ = function(event) { - var keyCodes = goog.events.KeyCodes; - if (event.keyCode == keyCodes.SPACE || event.keyCode == keyCodes.ENTER) { - this.changeColor_(); - } -}; - - -/** - * Sets the current label text. Has no effect if component is not rendered. - * - * @param {string} text The text to set as the label. - */ -goog.demos.SampleComponent.prototype.setLabelText = function(text) { - if (this.getElement()) { - goog.dom.setTextContent(this.getElement(), text); - } -}; diff --git a/src/database/third_party/closure-library/closure/goog/demos/scrollfloater.html b/src/database/third_party/closure-library/closure/goog/demos/scrollfloater.html deleted file mode 100644 index f06d21898fc..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/scrollfloater.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - -ScrollFloater - - - - - - - -
- - - - - - -
-
- This content does not float. -
-
- This content does not float. -
-
- This floater is constrained within a container and has a top offset of 50px. -
-
-
- This content does not float. -
-
-
-
-
- This content does not float. -
- -
-
- This floater is very tall. -

- This tall floater is pinned to the bottom of the window when - your window is shorter and floats at the top when it is taller. -

-
-
-
-

This is the bottom of the page.

-
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/select.html b/src/database/third_party/closure-library/closure/goog/demos/select.html deleted file mode 100644 index 80f5e0e1555..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/select.html +++ /dev/null @@ -1,324 +0,0 @@ - - - - - goog.ui.Select & goog.ui.Option - - - - - - - - - - - -

goog.ui.Select & goog.ui.Option

-
- Demo of the goog.ui.Select component: -
-   - -
-
-   - -
-
-  (This control doesn't auto-highlight; it only dispatches - ENTER and LEAVE events.) -
-
- Click here to add a new option for the best movie, - here - to hide/show the select component for the best movie, or - here - to set the worst movie of all time to "Catwoman." -
-
-
-
- This goog.ui.Select was decorated: -
-   - -
-
-
-
-
- -
- - Demo of goog.ui.Select using - goog.ui.FlatMenuButtonRenderer: - -
-   - -
-
-   - -
-
-  (This control doesn't auto-highlight; it only dispatches - ENTER and LEAVE events.) -
-
- Click here - to add a new option for the best Arnold movie, - here - to hide/show the select component for the best Arnold movie, or - here - to set the worst Arnold movie to "Jingle All the Way." -
-
-
-
- This Flat goog.ui.Select was decorated: -
-   - -
-
-
-
-
- - -
- Event Log -
-
-
-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/selectionmenubutton.html b/src/database/third_party/closure-library/closure/goog/demos/selectionmenubutton.html deleted file mode 100644 index 7d9894252c5..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/selectionmenubutton.html +++ /dev/null @@ -1,186 +0,0 @@ - - - - - goog.ui.SelectionMenuButton Demo - - - - - - - -

goog.ui.SelectionMenuButton

- - - - - - - -
-
- - This SelectionMenuButton was created programmatically: -   - - - - - - - - -
- - - Enable button: - -   -
- -
-
-
- - This SelectionMenuButton decorates an element:  - - - - - - - - -
-
- - - -
-
All
-
None
-
-
Starred
-
- Unstarred -
-
-
Read
-
Unread
-
-
-
- Enable button: - -   - Show button: - -   -
- -
-
-
- -
- Event Log -
-
-
-
-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/serverchart.html b/src/database/third_party/closure-library/closure/goog/demos/serverchart.html deleted file mode 100644 index 1684ec2dec7..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/serverchart.html +++ /dev/null @@ -1,122 +0,0 @@ - - - - - goog.ui.ServerChart - - - - - - -

goog.ui.ServerChart

-
-

Line Chart:

-
-
-

Finance Chart: Add a Line -

-
-
-

Pie Chart:

-
-
-

Filled Line Chart:

-
-
-

Bar Chart:

-
-
-

Venn Diagram:

-
- - diff --git a/src/database/third_party/closure-library/closure/goog/demos/slider.html b/src/database/third_party/closure-library/closure/goog/demos/slider.html deleted file mode 100644 index 1c85e67f765..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/slider.html +++ /dev/null @@ -1,128 +0,0 @@ - - - - - goog.ui.Slider - - - - - - - -

goog.ui.Slider

- -
- Horizontal Slider -
- -
-
-
- - MoveToPointEnabled - - Enable -
- - -
- -
- Vertical Slider, inserted w/ script - - - Enable -
- - -
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/splitbehavior.html b/src/database/third_party/closure-library/closure/goog/demos/splitbehavior.html deleted file mode 100644 index 60a9aecccfb..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/splitbehavior.html +++ /dev/null @@ -1,163 +0,0 @@ - - - - - goog.ui.SplitBehavior - - - - - - - - - - - - - - - - -

goog.ui.SplitBehavior

-
- - Split behavior - render - -
-
-
-
-
- -
- - Split behavior - decorate - -
-
- Bold -
-
-
-
- - Color Split behavior - -
-
-

goog.ui.ColorButton

-
- - These buttons were rendered using goog.ui.ColorButton: -   - -
- Rendered ColorButton: -
-
- Decorated ColorButton: -
-
Color2
-
-
- - -
- Event Log -
-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/splitpane.html b/src/database/third_party/closure-library/closure/goog/demos/splitpane.html deleted file mode 100644 index 366df638395..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/splitpane.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - - goog.ui.SplitPane - - - - - - - -

goog.ui.SplitPane

- Left Component Size: - Width: - Height: -
- First One - Second One - - -

-

-
- Left Frame -
-
- -
-
-
- First Component Width: - -
- -
-

- - -

-

- - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/stopevent.html b/src/database/third_party/closure-library/closure/goog/demos/stopevent.html deleted file mode 100644 index 83cbd7c85bb..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/stopevent.html +++ /dev/null @@ -1,171 +0,0 @@ - - - - Stop Event Propagation - - - - - - - - -

Stop Event

-

Test the cancelling of capture and bubbling events. Click - one of the nodes to see the event trace, then use the check boxes to cancel - the capture or bubble at a given branch. (Double click the text area to clear - it)

- -
- -
- - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/submenus.html b/src/database/third_party/closure-library/closure/goog/demos/submenus.html deleted file mode 100644 index 7f710679fb7..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/submenus.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - - goog.ui.SubMenu - - - - - - - - - -

goog.ui.SubMenu

-

Demonstration of different of hierarchical menus.

-

- -

- Here's a menu (with submenus) defined in markup: -

-
-
Open...
-
Open Recent -
-
Annual Report.pdf
-
Quarterly Update.pdf
-
Enemies List.txt
-
More -
-
Foo.txt
-
Bar.txt
-
-
-
-
-
- - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/submenus2.html b/src/database/third_party/closure-library/closure/goog/demos/submenus2.html deleted file mode 100644 index fd41b20e8c6..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/submenus2.html +++ /dev/null @@ -1,150 +0,0 @@ - - - - - goog.ui.SubMenu - - - - - - - - - -

goog.ui.SubMenu

-

Demonstration of different hierarchical menus which share its submenus. - A flyweight pattern demonstration for submenus.

-

- - -
-
Google
-
Yahoo
-
MSN
-
-
Bla...
-
- - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/tabbar.html b/src/database/third_party/closure-library/closure/goog/demos/tabbar.html deleted file mode 100644 index 845e6bc0a5a..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/tabbar.html +++ /dev/null @@ -1,289 +0,0 @@ - - - - - goog.ui.TabBar - - - - - - - - - -

goog.ui.TabBar

-

- A goog.ui.TabBar is a subclass of goog.ui.Container, - designed to host one or more goog.ui.Tabs. The tabs in the - first four tab bars on this demo page were decorated using the default - tab renderer. Tabs in the last two tab bars were decorated using the - rounded tab renderer (goog.ui.RoundedTabRenderer). -

- - - - - - - - - - - - - - - - - - -
- Above tab content:

-
-
Hello
-
Settings
-
More
-
Advanced
-
- -
-
- Use the keyboard or the mouse to switch tabs. -
- - -
- Below tab content:

-
- Use the keyboard or the mouse to switch tabs. -
- -
-
-
Hello
-
Settings
-
More
-
Advanced
-
- -
- - -
- Before tab content:

-
-
Hello
-
Settings
-
More
-
Advanced
-
-
- Use the keyboard or the mouse to switch tabs. -
- -
- - -
- After tab content:

-
-
Hello
-
Settings
-
More
-
Advanced
-
-
- Use the keyboard or the mouse to switch tabs. -
- -
- - -
- Above tab content (rounded corners):

-
-
Hello
-
Settings -
-
More
-
Advanced -
-
- -
-
- Use the keyboard or the mouse to switch tabs. -
- - -
- Before tab content (rounded corners):

-
-
Hello
-
Settings
-
More
-
Advanced -
-
-
- Use the keyboard or the mouse to switch tabs. -
- -
- - -
- -
- Event Log -
-
-
-
-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/tablesorter.html b/src/database/third_party/closure-library/closure/goog/demos/tablesorter.html deleted file mode 100644 index dcbcbff14f8..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/tablesorter.html +++ /dev/null @@ -1,116 +0,0 @@ - - - - - goog.ui.TableSorter - - - - - - - -

goog.ui.TableSorter

-

- Number sorts numerically, month sorts alphabetically, and days sorts - numerically in reverse. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NumberMonthDays (non-leap year)
1January31
2Februrary28
3March31
4April30
5May31
6June30
7July31
8August31
9September30
10October31
11November30
12December31
-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/tabpane.html b/src/database/third_party/closure-library/closure/goog/demos/tabpane.html deleted file mode 100644 index 20aaf5d769c..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/tabpane.html +++ /dev/null @@ -1,302 +0,0 @@ - - - - - goog.ui.TabPane - - - - - - - -

goog.ui.TabPane

- -
- selected in tab pane 1.

- -

Bottom tabs

-
-
-

Initial page

-

- Page created automatically from tab pane child node. -

-
-
- -

Left tabs

-
-
-

Front page!

-

- Page created automatically from tab pane child node. -

-
-
- -

Right tabs

-
-
-

Right 1

-

- Page created automatically from tab pane child node. -

-
-
-

Right 2

-

- So was this page. -

-
-
- -
-

Page 1

-

- Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis ac augue sed - massa placerat iaculis. Aliquam tempor dictum massa. Quisque vehicula justo - ut tellus. Integer urna. Aliquam libero justo, ornare at, pretium ac, - vulputate quis, ante. Sed arcu. Etiam sit amet turpis. Maecenas pede. Sed - turpis. Sed ultricies commodo nisl. Morbi eget magna quis nisi euismod - porttitor. Vivamus lacinia massa et sem. Donec consequat ligula sed tellus. - Suspendisse enim sapien, vestibulum nec, eleifend id, placerat sit amet, - risus. Mauris in pede ac lorem varius facilisis. Donec dui. Nam mollis nisi - eu neque. Cras luctus nisl at sapien. Ut eleifend, odio id luctus - pellentesque, lorem diam dictum velit, ac gravida lectus magna vel velit. -

-

- Etiam tempus, ante semper iaculis ultrices, ligula eros lobortis tellus, sit - amet luctus dolor nisl sit amet dolor. Donec in velit. Vivamus facilisis. - Proin nisi felis, commodo ut, porta dignissim, vestibulum quis, ligula. Ut - egestas porttitor tortor. Ut porttitor diam a est. Sed placerat. Aliquam - luctus est a risus. Aenean blandit nibh et justo. Phasellus vel lectus ut - leo dictum consequat. Nam tincidunt facilisis nulla. Nunc nonummy tempus - quam. Aliquam id enim. Sed rhoncus cursus lorem. Curabitur ultricies, enim - quis eleifend mattis, est velit dapibus dolor, quis laoreet arcu tortor - volutpat tortor. Pellentesque habitant morbi tristique senectus et netus et - malesuada fames ac turpis egestas. Curabitur nec mauris et purus aliquam - mattis. Cras rhoncus posuere sapien. Class aptent taciti sociosqu ad litora - torquent per conubia nostra, per inceptos hymenaeos. -

-

- Mauris lacinia ornare nunc. Donec molestie. Sed nulla libero, tincidunt vel, - porta sit amet, nonummy eget, augue. Class aptent taciti sociosqu ad litora - torquent per conubia nostra, per inceptos hymenaeos. Donec ac risus. Cras - euismod congue orci. Mauris mattis, ipsum at vestibulum bibendum, odio est - rhoncus nisi, vel aliquam ante velit quis neque. Duis nonummy tortor id - ante. Aenean auctor odio non nulla. Fusce hendrerit, mi et fringilla - venenatis, sem ipsum fermentum lorem, vel posuere urna eros eget massa. -

-

- Nulla nec sapien eget mauris pretium tempor. Phasellus scelerisque quam id - mauris. Cras erat ante, pretium ut, vestibulum ac, tincidunt ut, nunc. - Vivamus velit sapien, feugiat ac, elementum ac, viverra non, leo. Phasellus - imperdiet, magna at placerat consectetuer, enim urna aliquam augue, nec - tincidunt justo lectus nec lectus. Nam neque. Nullam ullamcorper euismod - augue. Maecenas arcu purus, sollicitudin nec, consequat a, gravida quis, - massa. Nullam bibendum viverra risus. Sed nibh. Morbi dapibus pellentesque - erat. -

-

- Cras non tellus. Maecenas nulla est, tincidunt sed, porta sit amet, placerat - sed, diam. Morbi pulvinar. Vestibulum ante ipsum primis in faucibus orci - luctus et ultrices posuere cubilia Curae; Praesent felis lacus, pretium at, - egestas sed, fermentum at, est. Pellentesque sagittis feugiat orci. Nam - augue. Sed eget dolor. Proin vitae metus scelerisque massa fermentum tempus. - Nulla facilisi. Pellentesque habitant morbi tristique senectus et netus et - malesuada fames ac turpis egestas. Aenean eleifend, leo gravida mollis - tempor, tellus ipsum porttitor leo, eget condimentum tellus neque sit amet - orci. Sed non lectus. Suspendisse nonummy purus ac massa. Sed quis elit - dapibus nunc semper porta. Maecenas risus eros, euismod quis, sagittis eget, - aliquet eget, dui. Donec vel nibh. Vivamus nunc purus, euismod in, feugiat - in, sodales vitae, nunc. Nulla lobortis. -

-
- -
-

- Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras et nisi id - lorem tempor semper. Suspendisse ante. Integer ligula urna, venenatis quis, - placerat vitae, commodo quis, sapien. Quisque nec lectus. Sed non dolor. Sed - congue, nisi in pharetra consequat, odio diam pulvinar arcu, in laoreet elit - risus id ipsum. Class aptent taciti sociosqu ad litora torquent per conubia - nostra, per inceptos hymenaeos. Praesent tellus enim, imperdiet a, sagittis - id, pulvinar vel, tortor. Integer nulla. Sed nulla augue, lacinia id, - vulputate eu, rhoncus non, ante. Integer lobortis eros vitae quam. Phasellus - sagittis, ipsum sollicitudin bibendum laoreet, arcu erat luctus lacus, vel - pharetra felis metus tincidunt diam. Cras ac augue in enim ultricies - aliquam. -

- - - -
- -
-

Page 5

-

- This is page 5. -

-
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/textarea.html b/src/database/third_party/closure-library/closure/goog/demos/textarea.html deleted file mode 100644 index a71a3c03688..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/textarea.html +++ /dev/null @@ -1,128 +0,0 @@ - - - - - goog.ui.Textarea - - - - - -

goog.ui.Textarea

-
- - The first Textarea was created programmatically, - the second by decorating a <textarea> - element:  - -
- -
-
- -
- -
-
- -
- - This is a textarea with a minHeight set to 200px. - - -
- -
-
- -
- - This is a textarea with a padding-bottom of 3em. - - -
- - -
- Event Log -
-
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/timers.html b/src/database/third_party/closure-library/closure/goog/demos/timers.html deleted file mode 100644 index 193817890bd..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/timers.html +++ /dev/null @@ -1,291 +0,0 @@ - - - - - goog.Timer, goog.async.Throttle goog.async.Delay - - - - - - - - -

A Collection of Time Based Utilities

-

goog.async.Delay

-

An action can be invoked after some delay.

- Delay (seconds): - - -
- Delay Status: Not Set - -

goog.async.Throttle

- A throttle prevents the action from being called more than once per time - interval. -
- 'Create' the Throttle, then hit the 'Do Throttle' button a lot - of times. Notice the number of 'Hits' increasing with each button press. -
- The action will be invoked no more than once per time interval. -

- Throttle interval (seconds): - - - -
- Throttle Hits: -
- Throttle Action Called: -

-

goog.Timer

- A timer can be set up to call a timeout function on every 'tick' of the timer. -

- Timer interval (seconds): - - - - -
- Timer Status: Not Set -

-

goog.Timer.callOnce

- Timer also has a useful utility function that can call an action after some - timeout. -
- This a shortcut/replacement for window.setTimeout, and has a - corresponding goog.Timer.clear as well, which stops the action. -

- Timeout (seconds): - - -
- Do Once Status: -

- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/toolbar.html b/src/database/third_party/closure-library/closure/goog/demos/toolbar.html deleted file mode 100644 index 267222e02ff..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/toolbar.html +++ /dev/null @@ -1,703 +0,0 @@ - - - - - goog.ui.Toolbar - - - - - - - - - - -

goog.ui.Toolbar

-
- These toolbars were created programmatically: - -   - -   - -
-
-
-
-
-
- -   - -   - -
-
-
-
-
-
-
-
-
- This toolbar was created by decorating a bunch of DIVs: - -   - -   - -
-
-
-
Button
-
- Fancy Button -
-
-
- Disabled Button -
- -
-
- Toggle Button -
-
-
-
-
-
-
-
- -   - -   - -
-
-
-
Button
-
-
Fancy Button
-
-
-
- Disabled Button -
-
- Menu Button -
-
Foo
-
Bar
-
????... - Ctrl+P
-
???? ?-HTML (????? ZIP)
-
-
Cake
-
-
-
-
- Toggle Button -
-
- -
 
-
-
-
-
-
-
-
-
- This is starting to look like an editor toolbar: - -   - -   - -   - -
-
-
-
- Select font -
-
Normal
-
Times
-
Courier New
-
Georgia
-
Trebuchet
-
Verdana
-
-
-
- Size -
-
7pt
-
10pt
-
14pt
-
18pt
-
24pt
-
36pt
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Red
-
Green
-
Blue
-
-
-
-
-
-
Red
-
Green
-
Blue
-
-
-
-
Style
-
-
Clear formatting
-
-
Normal paragraph text
-
Minor heading (H3)
-
Sub-heading (H2)
-
Heading (H1)
-
-
Indent more
-
Indent less
-
Blockquote
-
-
-
-
-
-   - Insert -
-
-
Picture
-
Drawing
-
Other...
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Check spelling
-
-
-
-
-
-
-
- -
- Event Log -
- Warning! On Gecko, the event log may cause - the page to flicker when mousing over toolbar items. This is a Gecko - issue triggered by scrolling in the event log; see - bug 756988.
-
- Enable logging: -
-
-
-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/tooltip.html b/src/database/third_party/closure-library/closure/goog/demos/tooltip.html deleted file mode 100644 index 7b6f743b4ed..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/tooltip.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - - goog.ui.Tooltip - - - - - - - -

goog.ui.Tooltip

-

- - - - -

- -

- Demo tooltips in text and and of nested - tooltips, where an element triggers - one tooltip and an element inside the first element triggers another - one. -

- -
-
- -
-
- - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/tracer.html b/src/database/third_party/closure-library/closure/goog/demos/tracer.html deleted file mode 100644 index b145353417f..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/tracer.html +++ /dev/null @@ -1,92 +0,0 @@ - - - - -goog.debug.Tracer - - - - - - -
- -
- - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/tree/demo.html b/src/database/third_party/closure-library/closure/goog/demos/tree/demo.html deleted file mode 100644 index d4581b473c8..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/tree/demo.html +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - goog.ui.tree.TreeControl - - - - - - - - -

goog.ui.tree.TreeControl

-
- -

- - - - - -

- - -

- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/tree/testdata.js b/src/database/third_party/closure-library/closure/goog/demos/tree/testdata.js deleted file mode 100644 index 0e578c727a7..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/tree/testdata.js +++ /dev/null @@ -1,260 +0,0 @@ -// Copyright 2010 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -var testData = -['Countries', [['A', [['Afghanistan'], -['Albania'], -['Algeria'], -['American Samoa'], -['Andorra'], -['Angola'], -['Anguilla'], -['Antarctica'], -['Antigua and Barbuda'], -['Argentina'], -['Armenia'], -['Aruba'], -['Australia'], -['Austria'], -['Azerbaijan']]], -['B', [['Bahamas'], -['Bahrain'], -['Bangladesh'], -['Barbados'], -['Belarus'], -['Belgium'], -['Belize'], -['Benin'], -['Bermuda'], -['Bhutan'], -['Bolivia'], -['Bosnia and Herzegovina'], -['Botswana'], -['Bouvet Island'], -['Brazil'], -['British Indian Ocean Territory'], -['Brunei Darussalam'], -['Bulgaria'], -['Burkina Faso'], -['Burundi']]], -['C', [['Cambodia'], -['Cameroon'], -['Canada'], -['Cape Verde'], -['Cayman Islands'], -['Central African Republic'], -['Chad'], -['Chile'], -['China'], -['Christmas Island'], -['Cocos (Keeling) Islands'], -['Colombia'], -['Comoros'], -['Congo'], -['Congo, the Democratic Republic of the'], -['Cook Islands'], -['Costa Rica'], -['Croatia'], -['Cuba'], -['Cyprus'], -['Czech Republic'], -['C\u00f4te d\u2019Ivoire']]], -['D', [['Denmark'], -['Djibouti'], -['Dominica'], -['Dominican Republic']]], -['E', [['Ecuador'], -['Egypt'], -['El Salvador'], -['Equatorial Guinea'], -['Eritrea'], -['Estonia'], -['Ethiopia']]], -['F', [['Falkland Islands (Malvinas)'], -['Faroe Islands'], -['Fiji'], -['Finland'], -['France'], -['French Guiana'], -['French Polynesia'], -['French Southern Territories']]], -['G', [['Gabon'], -['Gambia'], -['Georgia'], -['Germany'], -['Ghana'], -['Gibraltar'], -['Greece'], -['Greenland'], -['Grenada'], -['Guadeloupe'], -['Guam'], -['Guatemala'], -['Guernsey'], -['Guinea'], -['Guinea-Bissau'], -['Guyana']]], -['H', [['Haiti'], -['Heard Island and McDonald Islands'], -['Holy See (Vatican City State)'], -['Honduras'], -['Hong Kong'], -['Hungary']]], -['I', [['Iceland'], -['India'], -['Indonesia'], -['Iran, Islamic Republic of'], -['Iraq'], -['Ireland'], -['Isle of Man'], -['Israel'], -['Italy']]], -['J', [['Jamaica'], -['Japan'], -['Jersey'], -['Jordan']]], -['K', [['Kazakhstan'], -['Kenya'], -['Kiribati'], -['Korea, Democratic People\u2019s Republic of'], -['Korea, Republic of'], -['Kuwait'], -['Kyrgyzstan']]], -['L', [['Lao People\u2019s Democratic Republic'], -['Latvia'], -['Lebanon'], -['Lesotho'], -['Liberia'], -['Libyan Arab Jamahiriya'], -['Liechtenstein'], -['Lithuania'], -['Luxembourg']]], -['M', [['Macao'], -['Macedonia, the former Yugoslav Republic of'], -['Madagascar'], -['Malawi'], -['Malaysia'], -['Maldives'], -['Mali'], -['Malta'], -['Marshall Islands'], -['Martinique'], -['Mauritania'], -['Mauritius'], -['Mayotte'], -['Mexico'], -['Micronesia, Federated States of'], -['Moldova, Republic of'], -['Monaco'], -['Mongolia'], -['Montenegro'], -['Montserrat'], -['Morocco'], -['Mozambique'], -['Myanmar']]], -['N', [['Namibia'], -['Nauru'], -['Nepal'], -['Netherlands'], -['Netherlands Antilles'], -['New Caledonia'], -['New Zealand'], -['Nicaragua'], -['Niger'], -['Nigeria'], -['Niue'], -['Norfolk Island'], -['Northern Mariana Islands'], -['Norway']]], -['O', [['Oman']]], -['P', [['Pakistan'], -['Palau'], -['Palestinian Territory, Occupied'], -['Panama'], -['Papua New Guinea'], -['Paraguay'], -['Peru'], -['Philippines'], -['Pitcairn'], -['Poland'], -['Portugal'], -['Puerto Rico']]], -['Q', [['Qatar']]], -['R', [['Romania'], -['Russian Federation'], -['Rwanda'], -['R\u00e9union']]], -['S', [['Saint Barth\u00e9lemy'], -['Saint Helena'], -['Saint Kitts and Nevis'], -['Saint Lucia'], -['Saint Martin (French part)'], -['Saint Pierre and Miquelon'], -['Saint Vincent and the Grenadines'], -['Samoa'], -['San Marino'], -['Sao Tome and Principe'], -['Saudi Arabia'], -['Senegal'], -['Serbia'], -['Seychelles'], -['Sierra Leone'], -['Singapore'], -['Slovakia'], -['Slovenia'], -['Solomon Islands'], -['Somalia'], -['South Africa'], -['South Georgia and the South Sandwich Islands'], -['Spain'], -['Sri Lanka'], -['Sudan'], -['Suriname'], -['Svalbard and Jan Mayen'], -['Swaziland'], -['Sweden'], -['Switzerland'], -['Syrian Arab Republic']]], -['T', [['Taiwan, Province of China'], -['Tajikistan'], -['Tanzania, United Republic of'], -['Thailand'], -['Timor-Leste'], -['Togo'], -['Tokelau'], -['Tonga'], -['Trinidad and Tobago'], -['Tunisia'], -['Turkey'], -['Turkmenistan'], -['Turks and Caicos Islands'], -['Tuvalu']]], -['U', [['Uganda'], -['Ukraine'], -['United Arab Emirates'], -['United Kingdom'], -['United States'], -['United States Minor Outlying Islands'], -['Uruguay'], -['Uzbekistan']]], -['V', [['Vanuatu'], -['Venezuela'], -['Viet Nam'], -['Virgin Islands, British'], -['Virgin Islands, U.S.']]], -['W', [['Wallis and Futuna'], -['Western Sahara']]], -['Y', [['Yemen']]], -['Z', [['Zambia'], -['Zimbabwe']]], -['\u00c5', [['\u00c5land Islands']]]]] diff --git a/src/database/third_party/closure-library/closure/goog/demos/tweakui.html b/src/database/third_party/closure-library/closure/goog/demos/tweakui.html deleted file mode 100644 index 6a88e9331a8..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/tweakui.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - - goog.tweak.TweakUi - - - - - -

goog.ui.TweakUi

-The goog.tweak package provides a convenient and flexible way to add -configurable settings to an app. These settings: -
    -
  • can be set at compile time -
  • can be set in code (using goog.tweak.overrideDefaultValue) -
  • can be set by query parameters -
  • can be set through the TweakUi interface -
-Tweaks IDs are checked by the compiler and tweaks can be fully removed when -tweakProcessing=STRIP. Tweaks are great for toggling debugging facilities. - -

A collapsible menu

-

An expanded menu

-
    -
  • When "Apply Tweaks" is clicked, all non-default values are encoded into - query parameters and the page is refreshed. -
  • Blue entries are ones where the value of the tweak will change without - clicking apply tweaks (the value of goog.tweak.get*() will change) -
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/twothumbslider.html b/src/database/third_party/closure-library/closure/goog/demos/twothumbslider.html deleted file mode 100644 index 6c1d113eade..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/twothumbslider.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - - goog.ui.TwoThumbSlider - - - - - -

goog.ui.TwoThumbSlider

-
-
- -
-
-
-
- -
- -
- - -
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/useragent.html b/src/database/third_party/closure-library/closure/goog/demos/useragent.html deleted file mode 100644 index 85e29ac9d71..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/useragent.html +++ /dev/null @@ -1,205 +0,0 @@ - - - - - goog.userAgent - - - - - - - - -

goog.userAgent

- -
- - - -
-
- -
- - - -
-
- - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/viewportsizemonitor.html b/src/database/third_party/closure-library/closure/goog/demos/viewportsizemonitor.html deleted file mode 100644 index f958f5dac54..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/viewportsizemonitor.html +++ /dev/null @@ -1,71 +0,0 @@ - - - - - goog.dom.ViewportSizeMonitor - - - - - - -

goog.dom.ViewportSizeMonitor

-
- Current Size: Loading... -
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/wheelhandler.html b/src/database/third_party/closure-library/closure/goog/demos/wheelhandler.html deleted file mode 100644 index 586351a0252..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/wheelhandler.html +++ /dev/null @@ -1,144 +0,0 @@ - - - - -goog.events.WheelHandler - - - - - - - -

goog.events.WheelHandler

- -

Use your mousewheel on the gray box below to move the cross hair. - -

-
-
-
-
- -
-
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/xpc/blank.html b/src/database/third_party/closure-library/closure/goog/demos/xpc/blank.html deleted file mode 100644 index 5108baa3df5..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/xpc/blank.html +++ /dev/null @@ -1,7 +0,0 @@ - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/xpc/index.html b/src/database/third_party/closure-library/closure/goog/demos/xpc/index.html deleted file mode 100644 index e516ef26e6c..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/xpc/index.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - - - - - - - -
- - -

-this page: -

- -

See CrossPageChannel and -CrossDomainCommunication for details

- -

-select transport:
-Auto | -Native messaging | -Frame element method | -Iframe relay | -Iframe polling | - -Fragment URL -

- -

-
-
- - - -

-Out [clear]:
-
- - - -
- - -
- - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/xpc/inner.html b/src/database/third_party/closure-library/closure/goog/demos/xpc/inner.html deleted file mode 100644 index 02e17885c2f..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/xpc/inner.html +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - -

this page:

- - -
- -(n = )
- -mousemove-forwarding: - - -
Click me!
-
- - - -
-
- - - - -

-Out [clear]:
-
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/xpc/minimal/blank.html b/src/database/third_party/closure-library/closure/goog/demos/xpc/minimal/blank.html deleted file mode 100644 index 5108baa3df5..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/xpc/minimal/blank.html +++ /dev/null @@ -1,7 +0,0 @@ - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/xpc/minimal/index.html b/src/database/third_party/closure-library/closure/goog/demos/xpc/minimal/index.html deleted file mode 100644 index 75dfb36efd4..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/xpc/minimal/index.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - - - - - -
- -

- -

- - -

- -
-
- -
- - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/xpc/minimal/inner.html b/src/database/third_party/closure-library/closure/goog/demos/xpc/minimal/inner.html deleted file mode 100644 index b35773ae92b..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/xpc/minimal/inner.html +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - -

- -

- - -

- -
- - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/xpc/minimal/relay.html b/src/database/third_party/closure-library/closure/goog/demos/xpc/minimal/relay.html deleted file mode 100644 index 7cc700206a6..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/xpc/minimal/relay.html +++ /dev/null @@ -1,7 +0,0 @@ - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/xpc/relay.html b/src/database/third_party/closure-library/closure/goog/demos/xpc/relay.html deleted file mode 100644 index d2943357c04..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/xpc/relay.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/demos/xpc/xpcdemo.js b/src/database/third_party/closure-library/closure/goog/demos/xpc/xpcdemo.js deleted file mode 100644 index e3f722f31b2..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/xpc/xpcdemo.js +++ /dev/null @@ -1,307 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Contains application code for the XPC demo. - * This script is used in both the container page and the iframe. - * - */ - -goog.require('goog.Uri'); -goog.require('goog.dom'); -goog.require('goog.events'); -goog.require('goog.events.EventType'); -goog.require('goog.json'); -goog.require('goog.log'); -goog.require('goog.net.xpc.CfgFields'); -goog.require('goog.net.xpc.CrossPageChannel'); - - - -/** - * Namespace for the demo. We don't use goog.provide here because it's not a - * real module (cannot be required). - */ -var xpcdemo = {}; - - -/** - * Global function to kick off initialization in the containing document. - */ -goog.global.initOuter = function() { - goog.events.listen(window, 'load', function() { xpcdemo.initOuter(); }); -}; - - -/** - * Global function to kick off initialization in the iframe. - */ -goog.global.initInner = function() { - goog.events.listen(window, 'load', function() { xpcdemo.initInner(); }); -}; - - -/** - * Initializes XPC in the containing page. - */ -xpcdemo.initOuter = function() { - // Build the configuration object. - var cfg = {}; - - var ownUri = new goog.Uri(window.location.href); - var relayUri = ownUri.resolve(new goog.Uri('relay.html')); - var pollUri = ownUri.resolve(new goog.Uri('blank.html')); - - // Determine the peer domain. Uses the value of the URI-parameter - // 'peerdomain'. If that parameter is not present, it falls back to - // the own domain so that the demo will work out of the box (but - // communication will of course not cross domain-boundaries). For - // real cross-domain communication, the easiest way is to point two - // different host-names to the same webserver and then hit the - // following URI: - // http://host1.com/path/to/closure/demos/xpc/index.html?peerdomain=host2.com - var peerDomain = ownUri.getParameterValue('peerdomain') || ownUri.getDomain(); - - cfg[goog.net.xpc.CfgFields.LOCAL_RELAY_URI] = relayUri.toString(); - cfg[goog.net.xpc.CfgFields.PEER_RELAY_URI] = - relayUri.setDomain(peerDomain).toString(); - - cfg[goog.net.xpc.CfgFields.LOCAL_POLL_URI] = pollUri.toString(); - cfg[goog.net.xpc.CfgFields.PEER_POLL_URI] = - pollUri.setDomain(peerDomain).toString(); - - - // Force transport to be used if tp-parameter is set. - var tp = ownUri.getParameterValue('tp'); - if (tp) { - cfg[goog.net.xpc.CfgFields.TRANSPORT] = parseInt(tp, 10); - } - - - // Construct the URI of the peer page. - - var peerUri = ownUri.resolve( - new goog.Uri('inner.html')).setDomain(peerDomain); - // Passthrough of verbose and compiled flags. - if (goog.isDef(ownUri.getParameterValue('verbose'))) { - peerUri.setParameterValue('verbose', ''); - } - if (goog.isDef(ownUri.getParameterValue('compiled'))) { - peerUri.setParameterValue('compiled', ''); - } - - cfg[goog.net.xpc.CfgFields.PEER_URI] = peerUri; - - // Instantiate the channel. - xpcdemo.channel = new goog.net.xpc.CrossPageChannel(cfg); - - // Create the peer iframe. - xpcdemo.peerIframe = xpcdemo.channel.createPeerIframe( - goog.dom.getElement('iframeContainer')); - - xpcdemo.initCommon_(); - - goog.dom.getElement('inactive').style.display = 'none'; - goog.dom.getElement('active').style.display = ''; -}; - - -/** - * Initialization in the iframe. - */ -xpcdemo.initInner = function() { - // Get the channel configuration passed by the containing document. - var cfg = goog.json.parse( - (new goog.Uri(window.location.href)).getParameterValue('xpc')); - - xpcdemo.channel = new goog.net.xpc.CrossPageChannel(cfg); - - xpcdemo.initCommon_(); -}; - - -/** - * Initializes the demo. - * Registers service-handlers and connects the channel. - * @private - */ -xpcdemo.initCommon_ = function() { - var xpcLogger = goog.log.getLogger('goog.net.xpc'); - goog.log.addHandler(xpcLogger, function(logRecord) { - xpcdemo.log('[XPC] ' + logRecord.getMessage()); - }); - xpcLogger.setLevel(window.location.href.match(/verbose/) ? - goog.log.Level.ALL : goog.log.Level.INFO); - - // Register services. - xpcdemo.channel.registerService('log', xpcdemo.log); - xpcdemo.channel.registerService('ping', xpcdemo.pingHandler_); - xpcdemo.channel.registerService('events', xpcdemo.eventsMsgHandler_); - - // Connect the channel. - xpcdemo.channel.connect(function() { - xpcdemo.channel.send('log', 'Hi from ' + window.location.host); - goog.events.listen(goog.dom.getElement('clickfwd'), - 'click', xpcdemo.mouseEventHandler_); - }); -}; - - -/** - * Kills the peer iframe and the disposes the channel. - */ -xpcdemo.teardown = function() { - goog.events.unlisten(goog.dom.getElement('clickfwd'), - goog.events.EventType.CLICK, xpcdemo.mouseEventHandler_); - - xpcdemo.channel.dispose(); - delete xpcdemo.channel; - - goog.dom.removeNode(xpcdemo.peerIframe); - xpcdemo.peerIframe = null; - - goog.dom.getElement('inactive').style.display = ''; - goog.dom.getElement('active').style.display = 'none'; -}; - - -/** - * Logging function. Inserts log-message into element with it id 'console'. - * @param {string} msgString The log-message. - */ -xpcdemo.log = function(msgString) { - xpcdemo.consoleElm || (xpcdemo.consoleElm = goog.dom.getElement('console')); - var msgElm = goog.dom.createDom('div'); - msgElm.innerHTML = msgString; - xpcdemo.consoleElm.insertBefore(msgElm, xpcdemo.consoleElm.firstChild); -}; - - -/** - * Sends a ping request to the peer. - */ -xpcdemo.ping = function() { - // send current time - xpcdemo.channel.send('ping', goog.now() + ''); -}; - - -/** - * The handler function for incoming pings (messages sent to the service - * called 'ping'); - * @param {string} payload The message payload. - * @private - */ -xpcdemo.pingHandler_ = function(payload) { - // is the incoming message a response to a ping we sent? - if (payload.charAt(0) == '#') { - // calculate roundtrip time and log - var dt = goog.now() - parseInt(payload.substring(1), 10); - xpcdemo.log('roundtrip: ' + dt + 'ms'); - } else { - // incoming message is a ping initiated from peer - // -> prepend with '#' and send back - xpcdemo.channel.send('ping', '#' + payload); - xpcdemo.log('ping reply sent'); - } -}; - - -/** - * Counter for mousemove events. - * @type {number} - * @private - */ -xpcdemo.mmCount_ = 0; - - -/** - * Holds timestamp when the last mousemove rate has been logged. - * @type {number} - * @private - */ -xpcdemo.mmLastRateOutput_ = 0; - - -/** - * Start mousemove event forwarding. Registers a listener on the document which - * sends them over the channel. - */ -xpcdemo.startMousemoveForwarding = function() { - goog.events.listen(document, goog.events.EventType.MOUSEMOVE, - xpcdemo.mouseEventHandler_); - xpcdemo.mmLastRateOutput_ = goog.now(); -}; - - -/** - * Stop mousemove event forwarding. - */ -xpcdemo.stopMousemoveForwarding = function() { - goog.events.unlisten(document, goog.events.EventType.MOUSEMOVE, - xpcdemo.mouseEventHandler_); -}; - - -/** - * Function to be used as handler for mouse-events. - * @param {goog.events.BrowserEvent} e The mouse event. - * @private - */ -xpcdemo.mouseEventHandler_ = function(e) { - xpcdemo.channel.send('events', - [e.type, e.clientX, e.clientY, goog.now()].join(',')); -}; - - -/** - * Handler for the 'events' service. - * @param {string} payload The string returned from the xpcdemo. - * @private - */ -xpcdemo.eventsMsgHandler_ = function(payload) { - var now = goog.now(); - var args = payload.split(','); - var type = args[0]; - var pageX = args[1]; - var pageY = args[2]; - var time = parseInt(args[3], 10); - - var msg = type + ': (' + pageX + ',' + pageY + '), latency: ' + (now - time); - xpcdemo.log(msg); - - if (type == goog.events.EventType.MOUSEMOVE) { - xpcdemo.mmCount_++; - var dt = now - xpcdemo.mmLastRateOutput_; - if (dt > 1000) { - msg = 'RATE (mousemove/s): ' + (1000 * xpcdemo.mmCount_ / dt); - xpcdemo.log(msg); - xpcdemo.mmLastRateOutput_ = now; - xpcdemo.mmCount_ = 0; - } - } -}; - - -/** - * Send multiple messages. - * @param {number} n The number of messages to send. - */ -xpcdemo.sendN = function(n) { - xpcdemo.count_ || (xpcdemo.count_ = 1); - - for (var i = 0; i < n; i++) { - xpcdemo.channel.send('log', '' + xpcdemo.count_++); - } -}; diff --git a/src/database/third_party/closure-library/closure/goog/demos/zippy.html b/src/database/third_party/closure-library/closure/goog/demos/zippy.html deleted file mode 100644 index ae007c46243..00000000000 --- a/src/database/third_party/closure-library/closure/goog/demos/zippy.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - goog.ui.Zippy - - - - - - - -

goog.ui.Zippy

- -

Zippy 1

-

- Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras et nisi id - lorem tempor semper. Suspendisse ante. Integer ligula urna, venenatis quis, - placerat vitae, commodo quis, sapien. Quisque nec lectus. Sed non dolor. Sed - congue, nisi in pharetra consequat, odio diam pulvinar arcu, in laoreet elit - risus id ipsum. Class aptent taciti sociosqu ad litora torquent per conubia - nostra, per inceptos hymenaeos. Praesent tellus enim, imperdiet a, sagittis - id, pulvinar vel, tortor. Integer nulla. Sed nulla augue, lacinia id, - vulputate eu, rhoncus non, ante. Integer lobortis eros vitae quam. Phasellus - sagittis, ipsum sollicitudin bibendum laoreet, arcu erat luctus lacus, vel - pharetra felis metus tincidunt diam. Cras ac augue in enim ultricies aliquam. -

- -
-

Zippy 2

-

- Nunc et eros. Aliquam felis lectus, sagittis ac, sagittis eu, accumsan - vitae, leo. Maecenas suscipit, arcu eget elementum tincidunt, erat ligula - porttitor dui, quis ornare nisi turpis at ipsum. Vivamus magna tortor, - porttitor eu, cursus ut, vulputate in, nulla. Quisque nonummy feugiat - turpis. Cras lobortis lobortis elit. Aliquam congue, pede suscipit - condimentum convallis, diam purus dictum lacus, eu scelerisque mi est - molestie libero. Duis luctus dapibus nibh. Sed condimentum iaculis metus. - Pellentesque habitant morbi tristique senectus et netus et malesuada fames - ac turpis egestas. In pharetra dolor porta eros facilisis pellentesque. - Proin quam mi, sodales vel, tincidunt sit amet, convallis vel, eros. - Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere - cubilia Curae; Phasellus velit augue, rutrum sit amet, posuere nec, euismod - ac, elit. Etiam nisi. -

-
- -
-

Zippy 3

-

- Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas commodo - convallis nisi. Cras rhoncus elit non dolor. Vivamus gravida ultricies arcu. - Praesent ipsum erat, vehicula et, ultrices at, dignissim at, ipsum. Aenean - venenatis. Fusce blandit laoreet urna. Aliquam et pede condimentum lorem - posuere molestie. Pellentesque habitant morbi tristique senectus et netus et - malesuada fames ac turpis egestas. Fusce euismod, justo in feugiat feugiat, - urna metus sagittis felis, in varius neque mauris vitae dui. Nunc vel sapien - in diam laoreet euismod. Mauris quis felis ut ipsum auctor feugiat. Nulla - facilisi. Proin vitae urna. Quisque dignissim commodo nisl. Curabitur - bibendum. -

-
- -
- Zippy 2 sets the expanded state of zippy 3 to the inverted expanded state of - itself. Hence expanding zippy 2 collapses zippy 3 and vice verse. -
-
- Zippy 2 and 3 are animated, zippy 1 is not. -
- -
-
- - - diff --git a/src/database/third_party/closure-library/closure/goog/deps.js b/src/database/third_party/closure-library/closure/goog/deps.js deleted file mode 100644 index 7ee64800c7d..00000000000 --- a/src/database/third_party/closure-library/closure/goog/deps.js +++ /dev/null @@ -1,1456 +0,0 @@ -// Copyright 2015 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// This file has been auto-generated by GenJsDeps, please do not edit. - -goog.addDependency('../../third_party/closure/goog/caja/string/html/htmlparser.js', ['goog.string.html.HtmlParser', 'goog.string.html.HtmlParser.EFlags', 'goog.string.html.HtmlParser.Elements', 'goog.string.html.HtmlParser.Entities', 'goog.string.html.HtmlSaxHandler'], [], false); -goog.addDependency('../../third_party/closure/goog/caja/string/html/htmlsanitizer.js', ['goog.string.html.HtmlSanitizer', 'goog.string.html.HtmlSanitizer.AttributeType', 'goog.string.html.HtmlSanitizer.Attributes', 'goog.string.html.htmlSanitize'], ['goog.string.StringBuffer', 'goog.string.html.HtmlParser', 'goog.string.html.HtmlParser.EFlags', 'goog.string.html.HtmlParser.Elements', 'goog.string.html.HtmlSaxHandler'], false); -goog.addDependency('../../third_party/closure/goog/dojo/dom/query.js', ['goog.dom.query'], ['goog.array', 'goog.dom', 'goog.functions', 'goog.string', 'goog.userAgent'], false); -goog.addDependency('../../third_party/closure/goog/jpeg_encoder/jpeg_encoder_basic.js', ['goog.crypt.JpegEncoder'], ['goog.crypt.base64'], false); -goog.addDependency('../../third_party/closure/goog/loremipsum/text/loremipsum.js', ['goog.text.LoremIpsum'], ['goog.array', 'goog.math', 'goog.string', 'goog.structs.Map', 'goog.structs.Set'], false); -goog.addDependency('../../third_party/closure/goog/mochikit/async/deferred.js', ['goog.async.Deferred', 'goog.async.Deferred.AlreadyCalledError', 'goog.async.Deferred.CanceledError'], ['goog.Promise', 'goog.Thenable', 'goog.array', 'goog.asserts', 'goog.debug.Error'], false); -goog.addDependency('../../third_party/closure/goog/mochikit/async/deferredlist.js', ['goog.async.DeferredList'], ['goog.async.Deferred'], false); -goog.addDependency('../../third_party/closure/goog/osapi/osapi.js', ['goog.osapi'], [], false); -goog.addDependency('../../third_party/closure/goog/svgpan/svgpan.js', ['svgpan.SvgPan'], ['goog.Disposable', 'goog.events', 'goog.events.EventType', 'goog.events.MouseWheelHandler'], false); -goog.addDependency('a11y/aria/announcer.js', ['goog.a11y.aria.Announcer'], ['goog.Disposable', 'goog.Timer', 'goog.a11y.aria', 'goog.a11y.aria.LivePriority', 'goog.a11y.aria.State', 'goog.dom', 'goog.object'], false); -goog.addDependency('a11y/aria/announcer_test.js', ['goog.a11y.aria.AnnouncerTest'], ['goog.a11y.aria', 'goog.a11y.aria.Announcer', 'goog.a11y.aria.LivePriority', 'goog.a11y.aria.State', 'goog.array', 'goog.dom', 'goog.dom.iframe', 'goog.testing.MockClock', 'goog.testing.jsunit'], false); -goog.addDependency('a11y/aria/aria.js', ['goog.a11y.aria'], ['goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.a11y.aria.datatables', 'goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.object', 'goog.string'], false); -goog.addDependency('a11y/aria/aria_test.js', ['goog.a11y.ariaTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.TagName', 'goog.testing.jsunit'], false); -goog.addDependency('a11y/aria/attributes.js', ['goog.a11y.aria.AutoCompleteValues', 'goog.a11y.aria.CheckedValues', 'goog.a11y.aria.DropEffectValues', 'goog.a11y.aria.ExpandedValues', 'goog.a11y.aria.GrabbedValues', 'goog.a11y.aria.InvalidValues', 'goog.a11y.aria.LivePriority', 'goog.a11y.aria.OrientationValues', 'goog.a11y.aria.PressedValues', 'goog.a11y.aria.RelevantValues', 'goog.a11y.aria.SelectedValues', 'goog.a11y.aria.SortValues', 'goog.a11y.aria.State'], [], false); -goog.addDependency('a11y/aria/datatables.js', ['goog.a11y.aria.datatables'], ['goog.a11y.aria.State', 'goog.object'], false); -goog.addDependency('a11y/aria/roles.js', ['goog.a11y.aria.Role'], [], false); -goog.addDependency('array/array.js', ['goog.array', 'goog.array.ArrayLike'], ['goog.asserts'], false); -goog.addDependency('array/array_test.js', ['goog.arrayTest'], ['goog.array', 'goog.dom', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false); -goog.addDependency('asserts/asserts.js', ['goog.asserts', 'goog.asserts.AssertionError'], ['goog.debug.Error', 'goog.dom.NodeType', 'goog.string'], false); -goog.addDependency('asserts/asserts_test.js', ['goog.assertsTest'], ['goog.asserts', 'goog.asserts.AssertionError', 'goog.dom', 'goog.string', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('async/animationdelay.js', ['goog.async.AnimationDelay'], ['goog.Disposable', 'goog.events', 'goog.functions'], false); -goog.addDependency('async/animationdelay_test.js', ['goog.async.AnimationDelayTest'], ['goog.async.AnimationDelay', 'goog.testing.AsyncTestCase', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false); -goog.addDependency('async/conditionaldelay.js', ['goog.async.ConditionalDelay'], ['goog.Disposable', 'goog.async.Delay'], false); -goog.addDependency('async/conditionaldelay_test.js', ['goog.async.ConditionalDelayTest'], ['goog.async.ConditionalDelay', 'goog.testing.MockClock', 'goog.testing.jsunit'], false); -goog.addDependency('async/delay.js', ['goog.Delay', 'goog.async.Delay'], ['goog.Disposable', 'goog.Timer'], false); -goog.addDependency('async/delay_test.js', ['goog.async.DelayTest'], ['goog.async.Delay', 'goog.testing.MockClock', 'goog.testing.jsunit'], false); -goog.addDependency('async/nexttick.js', ['goog.async.nextTick', 'goog.async.throwException'], ['goog.debug.entryPointRegistry', 'goog.functions', 'goog.labs.userAgent.browser', 'goog.labs.userAgent.engine'], false); -goog.addDependency('async/nexttick_test.js', ['goog.async.nextTickTest'], ['goog.async.nextTick', 'goog.debug.ErrorHandler', 'goog.debug.entryPointRegistry', 'goog.dom', 'goog.labs.userAgent.browser', 'goog.testing.AsyncTestCase', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false); -goog.addDependency('async/run.js', ['goog.async.run'], ['goog.async.nextTick', 'goog.async.throwException', 'goog.testing.watchers'], false); -goog.addDependency('async/run_test.js', ['goog.async.runTest'], ['goog.async.run', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false); -goog.addDependency('async/throttle.js', ['goog.Throttle', 'goog.async.Throttle'], ['goog.Disposable', 'goog.Timer'], false); -goog.addDependency('async/throttle_test.js', ['goog.async.ThrottleTest'], ['goog.async.Throttle', 'goog.testing.MockClock', 'goog.testing.jsunit'], false); -goog.addDependency('base.js', ['goog'], [], false); -goog.addDependency('base_module_test.js', ['goog.baseModuleTest'], ['goog.Timer', 'goog.test_module', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], true); -goog.addDependency('base_test.js', ['an.existing.path', 'dup.base', 'far.out', 'goog.baseTest', 'goog.explicit', 'goog.implicit.explicit', 'goog.test', 'goog.test.name', 'goog.test.name.space', 'goog.xy', 'goog.xy.z', 'ns', 'testDep.bar'], ['goog.Timer', 'goog.functions', 'goog.test_module', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.userAgent'], false); -goog.addDependency('color/alpha.js', ['goog.color.alpha'], ['goog.color'], false); -goog.addDependency('color/alpha_test.js', ['goog.color.alphaTest'], ['goog.array', 'goog.color', 'goog.color.alpha', 'goog.testing.jsunit'], false); -goog.addDependency('color/color.js', ['goog.color', 'goog.color.Hsl', 'goog.color.Hsv', 'goog.color.Rgb'], ['goog.color.names', 'goog.math'], false); -goog.addDependency('color/color_test.js', ['goog.colorTest'], ['goog.array', 'goog.color', 'goog.color.names', 'goog.testing.jsunit'], false); -goog.addDependency('color/names.js', ['goog.color.names'], [], false); -goog.addDependency('crypt/aes.js', ['goog.crypt.Aes'], ['goog.asserts', 'goog.crypt.BlockCipher'], false); -goog.addDependency('crypt/aes_test.js', ['goog.crypt.AesTest'], ['goog.crypt', 'goog.crypt.Aes', 'goog.testing.jsunit'], false); -goog.addDependency('crypt/arc4.js', ['goog.crypt.Arc4'], ['goog.asserts'], false); -goog.addDependency('crypt/arc4_test.js', ['goog.crypt.Arc4Test'], ['goog.array', 'goog.crypt.Arc4', 'goog.testing.jsunit'], false); -goog.addDependency('crypt/base64.js', ['goog.crypt.base64'], ['goog.crypt', 'goog.userAgent'], false); -goog.addDependency('crypt/base64_test.js', ['goog.crypt.base64Test'], ['goog.crypt', 'goog.crypt.base64', 'goog.testing.jsunit'], false); -goog.addDependency('crypt/basen.js', ['goog.crypt.baseN'], [], false); -goog.addDependency('crypt/basen_test.js', ['goog.crypt.baseNTest'], ['goog.crypt.baseN', 'goog.testing.jsunit'], false); -goog.addDependency('crypt/blobhasher.js', ['goog.crypt.BlobHasher', 'goog.crypt.BlobHasher.EventType'], ['goog.asserts', 'goog.events.EventTarget', 'goog.fs', 'goog.log'], false); -goog.addDependency('crypt/blobhasher_test.js', ['goog.crypt.BlobHasherTest'], ['goog.crypt', 'goog.crypt.BlobHasher', 'goog.crypt.Md5', 'goog.events', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false); -goog.addDependency('crypt/blockcipher.js', ['goog.crypt.BlockCipher'], [], false); -goog.addDependency('crypt/bytestring_perf.js', ['goog.crypt.byteArrayToStringPerf'], ['goog.array', 'goog.dom', 'goog.testing.PerformanceTable'], false); -goog.addDependency('crypt/cbc.js', ['goog.crypt.Cbc'], ['goog.array', 'goog.asserts', 'goog.crypt'], false); -goog.addDependency('crypt/cbc_test.js', ['goog.crypt.CbcTest'], ['goog.crypt', 'goog.crypt.Aes', 'goog.crypt.Cbc', 'goog.testing.jsunit'], false); -goog.addDependency('crypt/crypt.js', ['goog.crypt'], ['goog.array', 'goog.asserts'], false); -goog.addDependency('crypt/crypt_test.js', ['goog.cryptTest'], ['goog.crypt', 'goog.string', 'goog.testing.jsunit'], false); -goog.addDependency('crypt/hash.js', ['goog.crypt.Hash'], [], false); -goog.addDependency('crypt/hash32.js', ['goog.crypt.hash32'], ['goog.crypt'], false); -goog.addDependency('crypt/hash32_test.js', ['goog.crypt.hash32Test'], ['goog.crypt.hash32', 'goog.testing.TestCase', 'goog.testing.jsunit'], false); -goog.addDependency('crypt/hashtester.js', ['goog.crypt.hashTester'], ['goog.array', 'goog.crypt', 'goog.dom', 'goog.testing.PerformanceTable', 'goog.testing.PseudoRandom', 'goog.testing.asserts'], false); -goog.addDependency('crypt/hmac.js', ['goog.crypt.Hmac'], ['goog.crypt.Hash'], false); -goog.addDependency('crypt/hmac_test.js', ['goog.crypt.HmacTest'], ['goog.crypt.Hmac', 'goog.crypt.Sha1', 'goog.crypt.hashTester', 'goog.testing.jsunit'], false); -goog.addDependency('crypt/md5.js', ['goog.crypt.Md5'], ['goog.crypt.Hash'], false); -goog.addDependency('crypt/md5_test.js', ['goog.crypt.Md5Test'], ['goog.crypt', 'goog.crypt.Md5', 'goog.crypt.hashTester', 'goog.testing.jsunit'], false); -goog.addDependency('crypt/pbkdf2.js', ['goog.crypt.pbkdf2'], ['goog.array', 'goog.asserts', 'goog.crypt', 'goog.crypt.Hmac', 'goog.crypt.Sha1'], false); -goog.addDependency('crypt/pbkdf2_test.js', ['goog.crypt.pbkdf2Test'], ['goog.crypt', 'goog.crypt.pbkdf2', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('crypt/sha1.js', ['goog.crypt.Sha1'], ['goog.crypt.Hash'], false); -goog.addDependency('crypt/sha1_test.js', ['goog.crypt.Sha1Test'], ['goog.crypt', 'goog.crypt.Sha1', 'goog.crypt.hashTester', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('crypt/sha2.js', ['goog.crypt.Sha2'], ['goog.array', 'goog.asserts', 'goog.crypt.Hash'], false); -goog.addDependency('crypt/sha224.js', ['goog.crypt.Sha224'], ['goog.crypt.Sha2'], false); -goog.addDependency('crypt/sha224_test.js', ['goog.crypt.Sha224Test'], ['goog.crypt', 'goog.crypt.Sha224', 'goog.crypt.hashTester', 'goog.testing.jsunit'], false); -goog.addDependency('crypt/sha256.js', ['goog.crypt.Sha256'], ['goog.crypt.Sha2'], false); -goog.addDependency('crypt/sha256_test.js', ['goog.crypt.Sha256Test'], ['goog.crypt', 'goog.crypt.Sha256', 'goog.crypt.hashTester', 'goog.testing.jsunit'], false); -goog.addDependency('crypt/sha2_64bit.js', ['goog.crypt.Sha2_64bit'], ['goog.array', 'goog.asserts', 'goog.crypt.Hash', 'goog.math.Long'], false); -goog.addDependency('crypt/sha2_64bit_test.js', ['goog.crypt.Sha2_64bit_test'], ['goog.array', 'goog.crypt', 'goog.crypt.Sha384', 'goog.crypt.Sha512', 'goog.crypt.Sha512_256', 'goog.crypt.hashTester', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('crypt/sha384.js', ['goog.crypt.Sha384'], ['goog.crypt.Sha2_64bit'], false); -goog.addDependency('crypt/sha512.js', ['goog.crypt.Sha512'], ['goog.crypt.Sha2_64bit'], false); -goog.addDependency('crypt/sha512_256.js', ['goog.crypt.Sha512_256'], ['goog.crypt.Sha2_64bit'], false); -goog.addDependency('cssom/cssom.js', ['goog.cssom', 'goog.cssom.CssRuleType'], ['goog.array', 'goog.dom'], false); -goog.addDependency('cssom/cssom_test.js', ['goog.cssomTest'], ['goog.array', 'goog.cssom', 'goog.cssom.CssRuleType', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('cssom/iframe/style.js', ['goog.cssom.iframe.style'], ['goog.asserts', 'goog.cssom', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.string', 'goog.style', 'goog.userAgent'], false); -goog.addDependency('cssom/iframe/style_test.js', ['goog.cssom.iframe.styleTest'], ['goog.cssom', 'goog.cssom.iframe.style', 'goog.dom', 'goog.dom.DomHelper', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('datasource/datamanager.js', ['goog.ds.DataManager'], ['goog.ds.BasicNodeList', 'goog.ds.DataNode', 'goog.ds.Expr', 'goog.object', 'goog.string', 'goog.structs', 'goog.structs.Map'], false); -goog.addDependency('datasource/datasource.js', ['goog.ds.BaseDataNode', 'goog.ds.BasicNodeList', 'goog.ds.DataNode', 'goog.ds.DataNodeList', 'goog.ds.EmptyNodeList', 'goog.ds.LoadState', 'goog.ds.SortedNodeList', 'goog.ds.Util', 'goog.ds.logger'], ['goog.array', 'goog.log'], false); -goog.addDependency('datasource/datasource_test.js', ['goog.ds.JsDataSourceTest'], ['goog.dom.xml', 'goog.ds.DataManager', 'goog.ds.JsDataSource', 'goog.ds.SortedNodeList', 'goog.ds.XmlDataSource', 'goog.testing.jsunit'], false); -goog.addDependency('datasource/expr.js', ['goog.ds.Expr'], ['goog.ds.BasicNodeList', 'goog.ds.EmptyNodeList', 'goog.string'], false); -goog.addDependency('datasource/expr_test.js', ['goog.ds.ExprTest'], ['goog.ds.DataManager', 'goog.ds.Expr', 'goog.ds.JsDataSource', 'goog.testing.jsunit'], false); -goog.addDependency('datasource/fastdatanode.js', ['goog.ds.AbstractFastDataNode', 'goog.ds.FastDataNode', 'goog.ds.FastListNode', 'goog.ds.PrimitiveFastDataNode'], ['goog.ds.DataManager', 'goog.ds.DataNodeList', 'goog.ds.EmptyNodeList', 'goog.string'], false); -goog.addDependency('datasource/fastdatanode_test.js', ['goog.ds.FastDataNodeTest'], ['goog.array', 'goog.ds.DataManager', 'goog.ds.Expr', 'goog.ds.FastDataNode', 'goog.testing.jsunit'], false); -goog.addDependency('datasource/jsdatasource.js', ['goog.ds.JsDataSource', 'goog.ds.JsPropertyDataSource'], ['goog.ds.BaseDataNode', 'goog.ds.BasicNodeList', 'goog.ds.DataManager', 'goog.ds.DataNode', 'goog.ds.EmptyNodeList', 'goog.ds.LoadState'], false); -goog.addDependency('datasource/jsondatasource.js', ['goog.ds.JsonDataSource'], ['goog.Uri', 'goog.dom', 'goog.ds.DataManager', 'goog.ds.JsDataSource', 'goog.ds.LoadState', 'goog.ds.logger'], false); -goog.addDependency('datasource/jsxmlhttpdatasource.js', ['goog.ds.JsXmlHttpDataSource'], ['goog.Uri', 'goog.ds.DataManager', 'goog.ds.FastDataNode', 'goog.ds.LoadState', 'goog.ds.logger', 'goog.events', 'goog.log', 'goog.net.EventType', 'goog.net.XhrIo'], false); -goog.addDependency('datasource/jsxmlhttpdatasource_test.js', ['goog.ds.JsXmlHttpDataSourceTest'], ['goog.ds.JsXmlHttpDataSource', 'goog.testing.TestQueue', 'goog.testing.jsunit', 'goog.testing.net.XhrIo'], false); -goog.addDependency('datasource/xmldatasource.js', ['goog.ds.XmlDataSource', 'goog.ds.XmlHttpDataSource'], ['goog.Uri', 'goog.dom.NodeType', 'goog.dom.xml', 'goog.ds.BasicNodeList', 'goog.ds.DataManager', 'goog.ds.DataNode', 'goog.ds.LoadState', 'goog.ds.logger', 'goog.net.XhrIo', 'goog.string'], false); -goog.addDependency('date/date.js', ['goog.date', 'goog.date.Date', 'goog.date.DateTime', 'goog.date.Interval', 'goog.date.month', 'goog.date.weekDay'], ['goog.asserts', 'goog.date.DateLike', 'goog.i18n.DateTimeSymbols', 'goog.string'], false); -goog.addDependency('date/date_test.js', ['goog.dateTest'], ['goog.array', 'goog.date', 'goog.date.Date', 'goog.date.DateTime', 'goog.date.Interval', 'goog.date.month', 'goog.date.weekDay', 'goog.i18n.DateTimeSymbols', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.platform', 'goog.userAgent.product', 'goog.userAgent.product.isVersion'], false); -goog.addDependency('date/datelike.js', ['goog.date.DateLike'], [], false); -goog.addDependency('date/daterange.js', ['goog.date.DateRange', 'goog.date.DateRange.Iterator', 'goog.date.DateRange.StandardDateRangeKeys'], ['goog.date.Date', 'goog.date.Interval', 'goog.iter.Iterator', 'goog.iter.StopIteration'], false); -goog.addDependency('date/daterange_test.js', ['goog.date.DateRangeTest'], ['goog.date.Date', 'goog.date.DateRange', 'goog.date.Interval', 'goog.i18n.DateTimeSymbols', 'goog.testing.jsunit'], false); -goog.addDependency('date/duration.js', ['goog.date.duration'], ['goog.i18n.DateTimeFormat', 'goog.i18n.MessageFormat'], false); -goog.addDependency('date/duration_test.js', ['goog.date.durationTest'], ['goog.date.duration', 'goog.i18n.DateTimeFormat', 'goog.i18n.DateTimeSymbols', 'goog.i18n.DateTimeSymbols_bn', 'goog.i18n.DateTimeSymbols_en', 'goog.i18n.DateTimeSymbols_fa', 'goog.testing.jsunit'], false); -goog.addDependency('date/relative.js', ['goog.date.relative', 'goog.date.relative.TimeDeltaFormatter', 'goog.date.relative.Unit'], ['goog.i18n.DateTimeFormat'], false); -goog.addDependency('date/relative_test.js', ['goog.date.relativeTest'], ['goog.date.DateTime', 'goog.date.relative', 'goog.i18n.DateTimeFormat', 'goog.testing.jsunit'], false); -goog.addDependency('date/relativewithplurals.js', ['goog.date.relativeWithPlurals'], ['goog.date.relative', 'goog.date.relative.Unit', 'goog.i18n.MessageFormat'], false); -goog.addDependency('date/relativewithplurals_test.js', ['goog.date.relativeWithPluralsTest'], ['goog.date.relative', 'goog.date.relativeTest', 'goog.date.relativeWithPlurals', 'goog.i18n.DateTimeFormat', 'goog.i18n.DateTimeSymbols', 'goog.i18n.DateTimeSymbols_bn', 'goog.i18n.DateTimeSymbols_en', 'goog.i18n.DateTimeSymbols_fa', 'goog.i18n.NumberFormatSymbols', 'goog.i18n.NumberFormatSymbols_bn', 'goog.i18n.NumberFormatSymbols_en', 'goog.i18n.NumberFormatSymbols_fa'], false); -goog.addDependency('date/utcdatetime.js', ['goog.date.UtcDateTime'], ['goog.date', 'goog.date.Date', 'goog.date.DateTime', 'goog.date.Interval'], false); -goog.addDependency('date/utcdatetime_test.js', ['goog.date.UtcDateTimeTest'], ['goog.date.Interval', 'goog.date.UtcDateTime', 'goog.date.month', 'goog.date.weekDay', 'goog.testing.jsunit'], false); -goog.addDependency('db/cursor.js', ['goog.db.Cursor'], ['goog.async.Deferred', 'goog.db.Error', 'goog.debug', 'goog.events.EventTarget'], false); -goog.addDependency('db/db.js', ['goog.db', 'goog.db.BlockedCallback', 'goog.db.UpgradeNeededCallback'], ['goog.asserts', 'goog.async.Deferred', 'goog.db.Error', 'goog.db.IndexedDb', 'goog.db.Transaction'], false); -goog.addDependency('db/db_test.js', ['goog.dbTest'], ['goog.Disposable', 'goog.array', 'goog.async.Deferred', 'goog.async.DeferredList', 'goog.db', 'goog.db.Cursor', 'goog.db.Error', 'goog.db.IndexedDb', 'goog.db.KeyRange', 'goog.db.Transaction', 'goog.events', 'goog.object', 'goog.testing.AsyncTestCase', 'goog.testing.PropertyReplacer', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.userAgent.product', 'goog.userAgent.product.isVersion'], false); -goog.addDependency('db/error.js', ['goog.db.Error', 'goog.db.Error.ErrorCode', 'goog.db.Error.ErrorName', 'goog.db.Error.VersionChangeBlockedError'], ['goog.debug.Error'], false); -goog.addDependency('db/index.js', ['goog.db.Index'], ['goog.async.Deferred', 'goog.db.Cursor', 'goog.db.Error', 'goog.debug'], false); -goog.addDependency('db/indexeddb.js', ['goog.db.IndexedDb'], ['goog.async.Deferred', 'goog.db.Error', 'goog.db.ObjectStore', 'goog.db.Transaction', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget'], false); -goog.addDependency('db/keyrange.js', ['goog.db.KeyRange'], [], false); -goog.addDependency('db/objectstore.js', ['goog.db.ObjectStore'], ['goog.async.Deferred', 'goog.db.Cursor', 'goog.db.Error', 'goog.db.Index', 'goog.debug', 'goog.events'], false); -goog.addDependency('db/old_db_test.js', ['goog.oldDbTest'], ['goog.async.Deferred', 'goog.db', 'goog.db.Cursor', 'goog.db.Error', 'goog.db.IndexedDb', 'goog.db.KeyRange', 'goog.db.Transaction', 'goog.events', 'goog.testing.AsyncTestCase', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.userAgent.product', 'goog.userAgent.product.isVersion'], false); -goog.addDependency('db/transaction.js', ['goog.db.Transaction', 'goog.db.Transaction.TransactionMode'], ['goog.async.Deferred', 'goog.db.Error', 'goog.db.ObjectStore', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventTarget'], false); -goog.addDependency('debug/console.js', ['goog.debug.Console'], ['goog.debug.LogManager', 'goog.debug.Logger', 'goog.debug.TextFormatter'], false); -goog.addDependency('debug/console_test.js', ['goog.debug.ConsoleTest'], ['goog.debug.Console', 'goog.debug.LogRecord', 'goog.debug.Logger', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false); -goog.addDependency('debug/debug.js', ['goog.debug'], ['goog.array', 'goog.html.SafeHtml', 'goog.html.SafeUrl', 'goog.html.uncheckedconversions', 'goog.string.Const', 'goog.structs.Set', 'goog.userAgent'], false); -goog.addDependency('debug/debug_test.js', ['goog.debugTest'], ['goog.debug', 'goog.html.SafeHtml', 'goog.structs.Set', 'goog.testing.jsunit'], false); -goog.addDependency('debug/debugwindow.js', ['goog.debug.DebugWindow'], ['goog.debug.HtmlFormatter', 'goog.debug.LogManager', 'goog.debug.Logger', 'goog.dom.safe', 'goog.html.SafeHtml', 'goog.html.SafeStyleSheet', 'goog.string.Const', 'goog.structs.CircularBuffer', 'goog.userAgent'], false); -goog.addDependency('debug/debugwindow_test.js', ['goog.debug.DebugWindowTest'], ['goog.debug.DebugWindow', 'goog.testing.jsunit'], false); -goog.addDependency('debug/devcss/devcss.js', ['goog.debug.DevCss', 'goog.debug.DevCss.UserAgent'], ['goog.asserts', 'goog.cssom', 'goog.dom.classlist', 'goog.events', 'goog.events.EventType', 'goog.string', 'goog.userAgent'], false); -goog.addDependency('debug/devcss/devcss_test.js', ['goog.debug.DevCssTest'], ['goog.debug.DevCss', 'goog.style', 'goog.testing.jsunit'], false); -goog.addDependency('debug/devcss/devcssrunner.js', ['goog.debug.devCssRunner'], ['goog.debug.DevCss'], false); -goog.addDependency('debug/divconsole.js', ['goog.debug.DivConsole'], ['goog.debug.HtmlFormatter', 'goog.debug.LogManager', 'goog.dom.safe', 'goog.html.SafeHtml', 'goog.style'], false); -goog.addDependency('debug/enhanceerror_test.js', ['goog.debugEnhanceErrorTest'], ['goog.debug', 'goog.testing.jsunit'], false); -goog.addDependency('debug/entrypointregistry.js', ['goog.debug.EntryPointMonitor', 'goog.debug.entryPointRegistry'], ['goog.asserts'], false); -goog.addDependency('debug/entrypointregistry_test.js', ['goog.debug.entryPointRegistryTest'], ['goog.debug.ErrorHandler', 'goog.debug.entryPointRegistry', 'goog.testing.jsunit'], false); -goog.addDependency('debug/error.js', ['goog.debug.Error'], [], false); -goog.addDependency('debug/error_test.js', ['goog.debug.ErrorTest'], ['goog.debug.Error', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.product'], false); -goog.addDependency('debug/errorhandler.js', ['goog.debug.ErrorHandler', 'goog.debug.ErrorHandler.ProtectedFunctionError'], ['goog.Disposable', 'goog.asserts', 'goog.debug', 'goog.debug.EntryPointMonitor', 'goog.debug.Error', 'goog.debug.Trace'], false); -goog.addDependency('debug/errorhandler_async_test.js', ['goog.debug.ErrorHandlerAsyncTest'], ['goog.debug.ErrorHandler', 'goog.testing.AsyncTestCase', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('debug/errorhandler_test.js', ['goog.debug.ErrorHandlerTest'], ['goog.debug.ErrorHandler', 'goog.testing.MockControl', 'goog.testing.jsunit'], false); -goog.addDependency('debug/errorhandlerweakdep.js', ['goog.debug.errorHandlerWeakDep'], [], false); -goog.addDependency('debug/errorreporter.js', ['goog.debug.ErrorReporter', 'goog.debug.ErrorReporter.ExceptionEvent'], ['goog.asserts', 'goog.debug', 'goog.debug.ErrorHandler', 'goog.debug.entryPointRegistry', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.log', 'goog.net.XhrIo', 'goog.object', 'goog.string', 'goog.uri.utils', 'goog.userAgent'], false); -goog.addDependency('debug/errorreporter_test.js', ['goog.debug.ErrorReporterTest'], ['goog.debug.ErrorReporter', 'goog.events', 'goog.functions', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('debug/fancywindow.js', ['goog.debug.FancyWindow'], ['goog.array', 'goog.debug.DebugWindow', 'goog.debug.LogManager', 'goog.debug.Logger', 'goog.dom.DomHelper', 'goog.dom.safe', 'goog.html.SafeHtml', 'goog.html.SafeStyleSheet', 'goog.object', 'goog.string', 'goog.string.Const', 'goog.userAgent'], false); -goog.addDependency('debug/formatter.js', ['goog.debug.Formatter', 'goog.debug.HtmlFormatter', 'goog.debug.TextFormatter'], ['goog.debug', 'goog.debug.Logger', 'goog.debug.RelativeTimeProvider', 'goog.html.SafeHtml'], false); -goog.addDependency('debug/formatter_test.js', ['goog.debug.FormatterTest'], ['goog.debug.HtmlFormatter', 'goog.debug.LogRecord', 'goog.debug.Logger', 'goog.html.SafeHtml', 'goog.testing.jsunit'], false); -goog.addDependency('debug/fpsdisplay.js', ['goog.debug.FpsDisplay'], ['goog.asserts', 'goog.async.AnimationDelay', 'goog.dom', 'goog.ui.Component'], false); -goog.addDependency('debug/fpsdisplay_test.js', ['goog.debug.FpsDisplayTest'], ['goog.debug.FpsDisplay', 'goog.testing.AsyncTestCase', 'goog.testing.jsunit'], false); -goog.addDependency('debug/gcdiagnostics.js', ['goog.debug.GcDiagnostics'], ['goog.debug.Trace', 'goog.log', 'goog.userAgent'], false); -goog.addDependency('debug/logbuffer.js', ['goog.debug.LogBuffer'], ['goog.asserts', 'goog.debug.LogRecord'], false); -goog.addDependency('debug/logbuffer_test.js', ['goog.debug.LogBufferTest'], ['goog.debug.LogBuffer', 'goog.debug.Logger', 'goog.testing.jsunit'], false); -goog.addDependency('debug/logger.js', ['goog.debug.LogManager', 'goog.debug.Loggable', 'goog.debug.Logger', 'goog.debug.Logger.Level'], ['goog.array', 'goog.asserts', 'goog.debug', 'goog.debug.LogBuffer', 'goog.debug.LogRecord'], false); -goog.addDependency('debug/logger_test.js', ['goog.debug.LoggerTest'], ['goog.debug.LogManager', 'goog.debug.Logger', 'goog.testing.jsunit'], false); -goog.addDependency('debug/logrecord.js', ['goog.debug.LogRecord'], [], false); -goog.addDependency('debug/logrecordserializer.js', ['goog.debug.logRecordSerializer'], ['goog.debug.LogRecord', 'goog.debug.Logger', 'goog.json', 'goog.object'], false); -goog.addDependency('debug/logrecordserializer_test.js', ['goog.debug.logRecordSerializerTest'], ['goog.debug.LogRecord', 'goog.debug.Logger', 'goog.debug.logRecordSerializer', 'goog.testing.jsunit'], false); -goog.addDependency('debug/relativetimeprovider.js', ['goog.debug.RelativeTimeProvider'], [], false); -goog.addDependency('debug/tracer.js', ['goog.debug.Trace'], ['goog.array', 'goog.debug.Logger', 'goog.iter', 'goog.log', 'goog.structs.Map', 'goog.structs.SimplePool'], false); -goog.addDependency('debug/tracer_test.js', ['goog.debug.TraceTest'], ['goog.debug.Trace', 'goog.testing.jsunit'], false); -goog.addDependency('defineclass_test.js', ['goog.defineClassTest'], ['goog.testing.jsunit'], false); -goog.addDependency('disposable/disposable.js', ['goog.Disposable', 'goog.dispose', 'goog.disposeAll'], ['goog.disposable.IDisposable'], false); -goog.addDependency('disposable/disposable_test.js', ['goog.DisposableTest'], ['goog.Disposable', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false); -goog.addDependency('disposable/idisposable.js', ['goog.disposable.IDisposable'], [], false); -goog.addDependency('dom/abstractmultirange.js', ['goog.dom.AbstractMultiRange'], ['goog.array', 'goog.dom', 'goog.dom.AbstractRange'], false); -goog.addDependency('dom/abstractrange.js', ['goog.dom.AbstractRange', 'goog.dom.RangeIterator', 'goog.dom.RangeType'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.SavedCaretRange', 'goog.dom.TagIterator', 'goog.userAgent'], false); -goog.addDependency('dom/abstractrange_test.js', ['goog.dom.AbstractRangeTest'], ['goog.dom', 'goog.dom.AbstractRange', 'goog.dom.Range', 'goog.testing.jsunit'], false); -goog.addDependency('dom/animationframe/animationframe.js', ['goog.dom.animationFrame', 'goog.dom.animationFrame.Spec', 'goog.dom.animationFrame.State'], ['goog.dom.animationFrame.polyfill'], false); -goog.addDependency('dom/animationframe/polyfill.js', ['goog.dom.animationFrame.polyfill'], [], false); -goog.addDependency('dom/annotate.js', ['goog.dom.annotate', 'goog.dom.annotate.AnnotateFn'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.safe', 'goog.html.SafeHtml'], false); -goog.addDependency('dom/annotate_test.js', ['goog.dom.annotateTest'], ['goog.dom', 'goog.dom.annotate', 'goog.html.SafeHtml', 'goog.testing.jsunit'], false); -goog.addDependency('dom/browserfeature.js', ['goog.dom.BrowserFeature'], ['goog.userAgent'], false); -goog.addDependency('dom/browserrange/abstractrange.js', ['goog.dom.browserrange.AbstractRange'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.RangeEndpoint', 'goog.dom.TagName', 'goog.dom.TextRangeIterator', 'goog.iter', 'goog.math.Coordinate', 'goog.string', 'goog.string.StringBuffer', 'goog.userAgent'], false); -goog.addDependency('dom/browserrange/browserrange.js', ['goog.dom.browserrange', 'goog.dom.browserrange.Error'], ['goog.dom', 'goog.dom.BrowserFeature', 'goog.dom.NodeType', 'goog.dom.browserrange.GeckoRange', 'goog.dom.browserrange.IeRange', 'goog.dom.browserrange.OperaRange', 'goog.dom.browserrange.W3cRange', 'goog.dom.browserrange.WebKitRange', 'goog.userAgent'], false); -goog.addDependency('dom/browserrange/browserrange_test.js', ['goog.dom.browserrangeTest'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.RangeEndpoint', 'goog.dom.TagName', 'goog.dom.browserrange', 'goog.testing.dom', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('dom/browserrange/geckorange.js', ['goog.dom.browserrange.GeckoRange'], ['goog.dom.browserrange.W3cRange'], false); -goog.addDependency('dom/browserrange/ierange.js', ['goog.dom.browserrange.IeRange'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.RangeEndpoint', 'goog.dom.TagName', 'goog.dom.browserrange.AbstractRange', 'goog.log', 'goog.string'], false); -goog.addDependency('dom/browserrange/operarange.js', ['goog.dom.browserrange.OperaRange'], ['goog.dom.browserrange.W3cRange'], false); -goog.addDependency('dom/browserrange/w3crange.js', ['goog.dom.browserrange.W3cRange'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.RangeEndpoint', 'goog.dom.browserrange.AbstractRange', 'goog.string', 'goog.userAgent'], false); -goog.addDependency('dom/browserrange/webkitrange.js', ['goog.dom.browserrange.WebKitRange'], ['goog.dom.RangeEndpoint', 'goog.dom.browserrange.W3cRange', 'goog.userAgent'], false); -goog.addDependency('dom/bufferedviewportsizemonitor.js', ['goog.dom.BufferedViewportSizeMonitor'], ['goog.asserts', 'goog.async.Delay', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType'], false); -goog.addDependency('dom/bufferedviewportsizemonitor_test.js', ['goog.dom.BufferedViewportSizeMonitorTest'], ['goog.dom.BufferedViewportSizeMonitor', 'goog.dom.ViewportSizeMonitor', 'goog.events', 'goog.events.EventType', 'goog.math.Size', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit'], false); -goog.addDependency('dom/classes.js', ['goog.dom.classes'], ['goog.array'], false); -goog.addDependency('dom/classes_test.js', ['goog.dom.classes_test'], ['goog.dom', 'goog.dom.classes', 'goog.testing.jsunit'], false); -goog.addDependency('dom/classlist.js', ['goog.dom.classlist'], ['goog.array'], false); -goog.addDependency('dom/classlist_test.js', ['goog.dom.classlist_test'], ['goog.dom', 'goog.dom.classlist', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit'], false); -goog.addDependency('dom/controlrange.js', ['goog.dom.ControlRange', 'goog.dom.ControlRangeIterator'], ['goog.array', 'goog.dom', 'goog.dom.AbstractMultiRange', 'goog.dom.AbstractRange', 'goog.dom.RangeIterator', 'goog.dom.RangeType', 'goog.dom.SavedRange', 'goog.dom.TagWalkType', 'goog.dom.TextRange', 'goog.iter.StopIteration', 'goog.userAgent'], false); -goog.addDependency('dom/controlrange_test.js', ['goog.dom.ControlRangeTest'], ['goog.dom', 'goog.dom.ControlRange', 'goog.dom.RangeType', 'goog.dom.TagName', 'goog.dom.TextRange', 'goog.testing.dom', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('dom/dataset.js', ['goog.dom.dataset'], ['goog.string', 'goog.userAgent.product'], false); -goog.addDependency('dom/dataset_test.js', ['goog.dom.datasetTest'], ['goog.dom', 'goog.dom.dataset', 'goog.testing.jsunit'], false); -goog.addDependency('dom/dom.js', ['goog.dom', 'goog.dom.Appendable', 'goog.dom.DomHelper'], ['goog.array', 'goog.asserts', 'goog.dom.BrowserFeature', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.safe', 'goog.html.SafeHtml', 'goog.math.Coordinate', 'goog.math.Size', 'goog.object', 'goog.string', 'goog.string.Unicode', 'goog.userAgent'], false); -goog.addDependency('dom/dom_test.js', ['goog.dom.dom_test'], ['goog.dom', 'goog.dom.BrowserFeature', 'goog.dom.DomHelper', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.functions', 'goog.html.testing', 'goog.object', 'goog.string.Unicode', 'goog.testing.PropertyReplacer', 'goog.testing.asserts', 'goog.userAgent', 'goog.userAgent.product', 'goog.userAgent.product.isVersion'], false); -goog.addDependency('dom/fontsizemonitor.js', ['goog.dom.FontSizeMonitor', 'goog.dom.FontSizeMonitor.EventType'], ['goog.dom', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.userAgent'], false); -goog.addDependency('dom/fontsizemonitor_test.js', ['goog.dom.FontSizeMonitorTest'], ['goog.dom', 'goog.dom.FontSizeMonitor', 'goog.events', 'goog.events.Event', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('dom/forms.js', ['goog.dom.forms'], ['goog.structs.Map'], false); -goog.addDependency('dom/forms_test.js', ['goog.dom.formsTest'], ['goog.dom', 'goog.dom.forms', 'goog.testing.jsunit'], false); -goog.addDependency('dom/fullscreen.js', ['goog.dom.fullscreen', 'goog.dom.fullscreen.EventType'], ['goog.dom', 'goog.userAgent'], false); -goog.addDependency('dom/iframe.js', ['goog.dom.iframe'], ['goog.dom', 'goog.dom.safe', 'goog.html.SafeHtml', 'goog.html.SafeStyle', 'goog.userAgent'], false); -goog.addDependency('dom/iframe_test.js', ['goog.dom.iframeTest'], ['goog.dom', 'goog.dom.iframe', 'goog.html.SafeHtml', 'goog.html.SafeStyle', 'goog.string.Const', 'goog.testing.jsunit'], false); -goog.addDependency('dom/iter.js', ['goog.dom.iter.AncestorIterator', 'goog.dom.iter.ChildIterator', 'goog.dom.iter.SiblingIterator'], ['goog.iter.Iterator', 'goog.iter.StopIteration'], false); -goog.addDependency('dom/iter_test.js', ['goog.dom.iterTest'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.iter.AncestorIterator', 'goog.dom.iter.ChildIterator', 'goog.dom.iter.SiblingIterator', 'goog.testing.dom', 'goog.testing.jsunit'], false); -goog.addDependency('dom/multirange.js', ['goog.dom.MultiRange', 'goog.dom.MultiRangeIterator'], ['goog.array', 'goog.dom.AbstractMultiRange', 'goog.dom.AbstractRange', 'goog.dom.RangeIterator', 'goog.dom.RangeType', 'goog.dom.SavedRange', 'goog.dom.TextRange', 'goog.iter.StopIteration', 'goog.log'], false); -goog.addDependency('dom/multirange_test.js', ['goog.dom.MultiRangeTest'], ['goog.dom', 'goog.dom.MultiRange', 'goog.dom.Range', 'goog.iter', 'goog.testing.jsunit'], false); -goog.addDependency('dom/nodeiterator.js', ['goog.dom.NodeIterator'], ['goog.dom.TagIterator'], false); -goog.addDependency('dom/nodeiterator_test.js', ['goog.dom.NodeIteratorTest'], ['goog.dom', 'goog.dom.NodeIterator', 'goog.testing.dom', 'goog.testing.jsunit'], false); -goog.addDependency('dom/nodeoffset.js', ['goog.dom.NodeOffset'], ['goog.Disposable', 'goog.dom.TagName'], false); -goog.addDependency('dom/nodeoffset_test.js', ['goog.dom.NodeOffsetTest'], ['goog.dom', 'goog.dom.NodeOffset', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.testing.jsunit'], false); -goog.addDependency('dom/nodetype.js', ['goog.dom.NodeType'], [], false); -goog.addDependency('dom/pattern/abstractpattern.js', ['goog.dom.pattern.AbstractPattern'], ['goog.dom.pattern.MatchType'], false); -goog.addDependency('dom/pattern/allchildren.js', ['goog.dom.pattern.AllChildren'], ['goog.dom.pattern.AbstractPattern', 'goog.dom.pattern.MatchType'], false); -goog.addDependency('dom/pattern/callback/callback.js', ['goog.dom.pattern.callback'], ['goog.dom', 'goog.dom.TagWalkType', 'goog.iter'], false); -goog.addDependency('dom/pattern/callback/counter.js', ['goog.dom.pattern.callback.Counter'], [], false); -goog.addDependency('dom/pattern/callback/test.js', ['goog.dom.pattern.callback.Test'], ['goog.iter.StopIteration'], false); -goog.addDependency('dom/pattern/childmatches.js', ['goog.dom.pattern.ChildMatches'], ['goog.dom.pattern.AllChildren', 'goog.dom.pattern.MatchType'], false); -goog.addDependency('dom/pattern/endtag.js', ['goog.dom.pattern.EndTag'], ['goog.dom.TagWalkType', 'goog.dom.pattern.Tag'], false); -goog.addDependency('dom/pattern/fulltag.js', ['goog.dom.pattern.FullTag'], ['goog.dom.pattern.MatchType', 'goog.dom.pattern.StartTag', 'goog.dom.pattern.Tag'], false); -goog.addDependency('dom/pattern/matcher.js', ['goog.dom.pattern.Matcher'], ['goog.dom.TagIterator', 'goog.dom.pattern.MatchType', 'goog.iter'], false); -goog.addDependency('dom/pattern/matcher_test.js', ['goog.dom.pattern.matcherTest'], ['goog.dom', 'goog.dom.pattern.EndTag', 'goog.dom.pattern.FullTag', 'goog.dom.pattern.Matcher', 'goog.dom.pattern.Repeat', 'goog.dom.pattern.Sequence', 'goog.dom.pattern.StartTag', 'goog.dom.pattern.callback.Counter', 'goog.dom.pattern.callback.Test', 'goog.iter.StopIteration', 'goog.testing.jsunit'], false); -goog.addDependency('dom/pattern/nodetype.js', ['goog.dom.pattern.NodeType'], ['goog.dom.pattern.AbstractPattern', 'goog.dom.pattern.MatchType'], false); -goog.addDependency('dom/pattern/pattern.js', ['goog.dom.pattern', 'goog.dom.pattern.MatchType'], [], false); -goog.addDependency('dom/pattern/pattern_test.js', ['goog.dom.patternTest'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.TagWalkType', 'goog.dom.pattern.AllChildren', 'goog.dom.pattern.ChildMatches', 'goog.dom.pattern.EndTag', 'goog.dom.pattern.FullTag', 'goog.dom.pattern.MatchType', 'goog.dom.pattern.NodeType', 'goog.dom.pattern.Repeat', 'goog.dom.pattern.Sequence', 'goog.dom.pattern.StartTag', 'goog.dom.pattern.Text', 'goog.testing.jsunit'], false); -goog.addDependency('dom/pattern/repeat.js', ['goog.dom.pattern.Repeat'], ['goog.dom.NodeType', 'goog.dom.pattern.AbstractPattern', 'goog.dom.pattern.MatchType'], false); -goog.addDependency('dom/pattern/sequence.js', ['goog.dom.pattern.Sequence'], ['goog.dom.NodeType', 'goog.dom.pattern', 'goog.dom.pattern.AbstractPattern', 'goog.dom.pattern.MatchType'], false); -goog.addDependency('dom/pattern/starttag.js', ['goog.dom.pattern.StartTag'], ['goog.dom.TagWalkType', 'goog.dom.pattern.Tag'], false); -goog.addDependency('dom/pattern/tag.js', ['goog.dom.pattern.Tag'], ['goog.dom.pattern', 'goog.dom.pattern.AbstractPattern', 'goog.dom.pattern.MatchType', 'goog.object'], false); -goog.addDependency('dom/pattern/text.js', ['goog.dom.pattern.Text'], ['goog.dom.NodeType', 'goog.dom.pattern', 'goog.dom.pattern.AbstractPattern', 'goog.dom.pattern.MatchType'], false); -goog.addDependency('dom/range.js', ['goog.dom.Range'], ['goog.dom', 'goog.dom.AbstractRange', 'goog.dom.BrowserFeature', 'goog.dom.ControlRange', 'goog.dom.MultiRange', 'goog.dom.NodeType', 'goog.dom.TextRange', 'goog.userAgent'], false); -goog.addDependency('dom/range_test.js', ['goog.dom.RangeTest'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.RangeType', 'goog.dom.TagName', 'goog.dom.TextRange', 'goog.dom.browserrange', 'goog.testing.dom', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('dom/rangeendpoint.js', ['goog.dom.RangeEndpoint'], [], false); -goog.addDependency('dom/safe.js', ['goog.dom.safe'], ['goog.html.SafeHtml', 'goog.html.SafeUrl'], false); -goog.addDependency('dom/safe_test.js', ['goog.dom.safeTest'], ['goog.dom.safe', 'goog.html.SafeUrl', 'goog.html.testing', 'goog.string.Const', 'goog.testing.jsunit'], false); -goog.addDependency('dom/savedcaretrange.js', ['goog.dom.SavedCaretRange'], ['goog.array', 'goog.dom', 'goog.dom.SavedRange', 'goog.dom.TagName', 'goog.string'], false); -goog.addDependency('dom/savedcaretrange_test.js', ['goog.dom.SavedCaretRangeTest'], ['goog.dom', 'goog.dom.Range', 'goog.dom.SavedCaretRange', 'goog.testing.dom', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('dom/savedrange.js', ['goog.dom.SavedRange'], ['goog.Disposable', 'goog.log'], false); -goog.addDependency('dom/savedrange_test.js', ['goog.dom.SavedRangeTest'], ['goog.dom', 'goog.dom.Range', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('dom/selection.js', ['goog.dom.selection'], ['goog.string', 'goog.userAgent'], false); -goog.addDependency('dom/selection_test.js', ['goog.dom.selectionTest'], ['goog.dom', 'goog.dom.selection', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('dom/tagiterator.js', ['goog.dom.TagIterator', 'goog.dom.TagWalkType'], ['goog.dom', 'goog.dom.NodeType', 'goog.iter.Iterator', 'goog.iter.StopIteration'], false); -goog.addDependency('dom/tagiterator_test.js', ['goog.dom.TagIteratorTest'], ['goog.dom', 'goog.dom.TagIterator', 'goog.dom.TagWalkType', 'goog.iter', 'goog.iter.StopIteration', 'goog.testing.dom', 'goog.testing.jsunit'], false); -goog.addDependency('dom/tagname.js', ['goog.dom.TagName'], [], false); -goog.addDependency('dom/tagname_test.js', ['goog.dom.TagNameTest'], ['goog.dom.TagName', 'goog.object', 'goog.testing.jsunit'], false); -goog.addDependency('dom/tags.js', ['goog.dom.tags'], ['goog.object'], false); -goog.addDependency('dom/tags_test.js', ['goog.dom.tagsTest'], ['goog.dom.tags', 'goog.testing.jsunit'], false); -goog.addDependency('dom/textrange.js', ['goog.dom.TextRange'], ['goog.array', 'goog.dom', 'goog.dom.AbstractRange', 'goog.dom.RangeType', 'goog.dom.SavedRange', 'goog.dom.TagName', 'goog.dom.TextRangeIterator', 'goog.dom.browserrange', 'goog.string', 'goog.userAgent'], false); -goog.addDependency('dom/textrange_test.js', ['goog.dom.TextRangeTest'], ['goog.dom', 'goog.dom.ControlRange', 'goog.dom.Range', 'goog.dom.TextRange', 'goog.math.Coordinate', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('dom/textrangeiterator.js', ['goog.dom.TextRangeIterator'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.RangeIterator', 'goog.dom.TagName', 'goog.iter.StopIteration'], false); -goog.addDependency('dom/textrangeiterator_test.js', ['goog.dom.TextRangeIteratorTest'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.TextRangeIterator', 'goog.iter.StopIteration', 'goog.testing.dom', 'goog.testing.jsunit'], false); -goog.addDependency('dom/vendor.js', ['goog.dom.vendor'], ['goog.string', 'goog.userAgent'], false); -goog.addDependency('dom/vendor_test.js', ['goog.dom.vendorTest'], ['goog.array', 'goog.dom.vendor', 'goog.labs.userAgent.util', 'goog.testing.MockUserAgent', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgentTestUtil'], false); -goog.addDependency('dom/viewportsizemonitor.js', ['goog.dom.ViewportSizeMonitor'], ['goog.dom', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.math.Size'], false); -goog.addDependency('dom/viewportsizemonitor_test.js', ['goog.dom.ViewportSizeMonitorTest'], ['goog.dom.ViewportSizeMonitor', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.math.Size', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false); -goog.addDependency('dom/xml.js', ['goog.dom.xml'], ['goog.dom', 'goog.dom.NodeType'], false); -goog.addDependency('dom/xml_test.js', ['goog.dom.xmlTest'], ['goog.dom.xml', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('editor/browserfeature.js', ['goog.editor.BrowserFeature'], ['goog.editor.defines', 'goog.userAgent', 'goog.userAgent.product', 'goog.userAgent.product.isVersion'], false); -goog.addDependency('editor/browserfeature_test.js', ['goog.editor.BrowserFeatureTest'], ['goog.dom', 'goog.dom.Range', 'goog.editor.BrowserFeature', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit'], false); -goog.addDependency('editor/clicktoeditwrapper.js', ['goog.editor.ClickToEditWrapper'], ['goog.Disposable', 'goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.Field', 'goog.editor.range', 'goog.events.BrowserEvent', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.log'], false); -goog.addDependency('editor/clicktoeditwrapper_test.js', ['goog.editor.ClickToEditWrapperTest'], ['goog.dom', 'goog.dom.Range', 'goog.editor.ClickToEditWrapper', 'goog.editor.SeamlessField', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.product'], false); -goog.addDependency('editor/command.js', ['goog.editor.Command'], [], false); -goog.addDependency('editor/contenteditablefield.js', ['goog.editor.ContentEditableField'], ['goog.asserts', 'goog.editor.Field', 'goog.log'], false); -goog.addDependency('editor/contenteditablefield_test.js', ['goog.editor.ContentEditableFieldTest'], ['goog.dom', 'goog.editor.ContentEditableField', 'goog.editor.field_test', 'goog.testing.jsunit'], false); -goog.addDependency('editor/defines.js', ['goog.editor.defines'], [], false); -goog.addDependency('editor/field.js', ['goog.editor.Field', 'goog.editor.Field.EventType'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.array', 'goog.asserts', 'goog.async.Delay', 'goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.Plugin', 'goog.editor.icontent', 'goog.editor.icontent.FieldFormatInfo', 'goog.editor.icontent.FieldStyleInfo', 'goog.editor.node', 'goog.editor.range', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.functions', 'goog.log', 'goog.log.Level', 'goog.string', 'goog.string.Unicode', 'goog.style', 'goog.userAgent', 'goog.userAgent.product'], false); -goog.addDependency('editor/field_test.js', ['goog.editor.field_test'], ['goog.dom', 'goog.dom.Range', 'goog.editor.BrowserFeature', 'goog.editor.Field', 'goog.editor.Plugin', 'goog.editor.range', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.functions', 'goog.testing.LooseMock', 'goog.testing.MockClock', 'goog.testing.dom', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.recordFunction', 'goog.userAgent'], false); -goog.addDependency('editor/focus.js', ['goog.editor.focus'], ['goog.dom.selection'], false); -goog.addDependency('editor/focus_test.js', ['goog.editor.focusTest'], ['goog.dom.selection', 'goog.editor.BrowserFeature', 'goog.editor.focus', 'goog.testing.jsunit'], false); -goog.addDependency('editor/icontent.js', ['goog.editor.icontent', 'goog.editor.icontent.FieldFormatInfo', 'goog.editor.icontent.FieldStyleInfo'], ['goog.dom', 'goog.editor.BrowserFeature', 'goog.style', 'goog.userAgent'], false); -goog.addDependency('editor/icontent_test.js', ['goog.editor.icontentTest'], ['goog.dom', 'goog.editor.BrowserFeature', 'goog.editor.icontent', 'goog.editor.icontent.FieldFormatInfo', 'goog.editor.icontent.FieldStyleInfo', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('editor/link.js', ['goog.editor.Link'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.node', 'goog.editor.range', 'goog.string', 'goog.string.Unicode', 'goog.uri.utils', 'goog.uri.utils.ComponentIndex'], false); -goog.addDependency('editor/link_test.js', ['goog.editor.LinkTest'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.Link', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('editor/node.js', ['goog.editor.node'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.iter.ChildIterator', 'goog.dom.iter.SiblingIterator', 'goog.iter', 'goog.object', 'goog.string', 'goog.string.Unicode', 'goog.userAgent'], false); -goog.addDependency('editor/node_test.js', ['goog.editor.nodeTest'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.editor.node', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.dom', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('editor/plugin.js', ['goog.editor.Plugin'], ['goog.events.EventTarget', 'goog.functions', 'goog.log', 'goog.object', 'goog.reflect', 'goog.userAgent'], false); -goog.addDependency('editor/plugin_test.js', ['goog.editor.PluginTest'], ['goog.editor.Field', 'goog.editor.Plugin', 'goog.functions', 'goog.testing.StrictMock', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('editor/plugins/abstractbubbleplugin.js', ['goog.editor.plugins.AbstractBubblePlugin'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.editor.Plugin', 'goog.editor.style', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.actionEventWrapper', 'goog.functions', 'goog.string.Unicode', 'goog.ui.Component', 'goog.ui.editor.Bubble', 'goog.userAgent'], false); -goog.addDependency('editor/plugins/abstractbubbleplugin_test.js', ['goog.editor.plugins.AbstractBubblePluginTest'], ['goog.dom', 'goog.editor.plugins.AbstractBubblePlugin', 'goog.events.BrowserEvent', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.functions', 'goog.style', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.ui.editor.Bubble', 'goog.userAgent'], false); -goog.addDependency('editor/plugins/abstractdialogplugin.js', ['goog.editor.plugins.AbstractDialogPlugin', 'goog.editor.plugins.AbstractDialogPlugin.EventType'], ['goog.dom', 'goog.dom.Range', 'goog.editor.Field', 'goog.editor.Plugin', 'goog.editor.range', 'goog.events', 'goog.ui.editor.AbstractDialog'], false); -goog.addDependency('editor/plugins/abstractdialogplugin_test.js', ['goog.editor.plugins.AbstractDialogPluginTest'], ['goog.dom.SavedRange', 'goog.editor.Field', 'goog.editor.plugins.AbstractDialogPlugin', 'goog.events.Event', 'goog.events.EventHandler', 'goog.functions', 'goog.testing.MockClock', 'goog.testing.MockControl', 'goog.testing.PropertyReplacer', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.mockmatchers.ArgumentMatcher', 'goog.ui.editor.AbstractDialog', 'goog.userAgent'], false); -goog.addDependency('editor/plugins/abstracttabhandler.js', ['goog.editor.plugins.AbstractTabHandler'], ['goog.editor.Plugin', 'goog.events.KeyCodes', 'goog.userAgent'], false); -goog.addDependency('editor/plugins/abstracttabhandler_test.js', ['goog.editor.plugins.AbstractTabHandlerTest'], ['goog.editor.Field', 'goog.editor.plugins.AbstractTabHandler', 'goog.events.BrowserEvent', 'goog.events.KeyCodes', 'goog.testing.StrictMock', 'goog.testing.editor.FieldMock', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('editor/plugins/basictextformatter.js', ['goog.editor.plugins.BasicTextFormatter', 'goog.editor.plugins.BasicTextFormatter.COMMAND'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.Link', 'goog.editor.Plugin', 'goog.editor.node', 'goog.editor.range', 'goog.editor.style', 'goog.iter', 'goog.iter.StopIteration', 'goog.log', 'goog.object', 'goog.string', 'goog.string.Unicode', 'goog.style', 'goog.ui.editor.messages', 'goog.userAgent'], false); -goog.addDependency('editor/plugins/basictextformatter_test.js', ['goog.editor.plugins.BasicTextFormatterTest'], ['goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.Field', 'goog.editor.Plugin', 'goog.editor.plugins.BasicTextFormatter', 'goog.object', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.LooseMock', 'goog.testing.PropertyReplacer', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.jsunit', 'goog.testing.mockmatchers', 'goog.userAgent'], false); -goog.addDependency('editor/plugins/blockquote.js', ['goog.editor.plugins.Blockquote'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.Plugin', 'goog.editor.node', 'goog.functions', 'goog.log'], false); -goog.addDependency('editor/plugins/blockquote_test.js', ['goog.editor.plugins.BlockquoteTest'], ['goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.plugins.Blockquote', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.jsunit'], false); -goog.addDependency('editor/plugins/emoticons.js', ['goog.editor.plugins.Emoticons'], ['goog.dom.TagName', 'goog.editor.Plugin', 'goog.editor.range', 'goog.functions', 'goog.ui.emoji.Emoji', 'goog.userAgent'], false); -goog.addDependency('editor/plugins/emoticons_test.js', ['goog.editor.plugins.EmoticonsTest'], ['goog.Uri', 'goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.editor.Field', 'goog.editor.plugins.Emoticons', 'goog.testing.jsunit', 'goog.ui.emoji.Emoji', 'goog.userAgent'], false); -goog.addDependency('editor/plugins/enterhandler.js', ['goog.editor.plugins.EnterHandler'], ['goog.dom', 'goog.dom.NodeOffset', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Plugin', 'goog.editor.node', 'goog.editor.plugins.Blockquote', 'goog.editor.range', 'goog.editor.style', 'goog.events.KeyCodes', 'goog.functions', 'goog.object', 'goog.string', 'goog.userAgent'], false); -goog.addDependency('editor/plugins/enterhandler_test.js', ['goog.editor.plugins.EnterHandlerTest'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Field', 'goog.editor.Plugin', 'goog.editor.plugins.Blockquote', 'goog.editor.plugins.EnterHandler', 'goog.editor.range', 'goog.events', 'goog.events.KeyCodes', 'goog.testing.ExpectedFailures', 'goog.testing.MockClock', 'goog.testing.dom', 'goog.testing.editor.TestHelper', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('editor/plugins/firststrong.js', ['goog.editor.plugins.FirstStrong'], ['goog.dom.NodeType', 'goog.dom.TagIterator', 'goog.dom.TagName', 'goog.editor.Command', 'goog.editor.Field', 'goog.editor.Plugin', 'goog.editor.node', 'goog.editor.range', 'goog.i18n.bidi', 'goog.i18n.uChar', 'goog.iter', 'goog.userAgent'], false); -goog.addDependency('editor/plugins/firststrong_test.js', ['goog.editor.plugins.FirstStrongTest'], ['goog.dom.Range', 'goog.editor.Command', 'goog.editor.Field', 'goog.editor.plugins.FirstStrong', 'goog.editor.range', 'goog.events.KeyCodes', 'goog.testing.MockClock', 'goog.testing.editor.TestHelper', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('editor/plugins/headerformatter.js', ['goog.editor.plugins.HeaderFormatter'], ['goog.editor.Command', 'goog.editor.Plugin', 'goog.userAgent'], false); -goog.addDependency('editor/plugins/headerformatter_test.js', ['goog.editor.plugins.HeaderFormatterTest'], ['goog.dom', 'goog.editor.Command', 'goog.editor.plugins.BasicTextFormatter', 'goog.editor.plugins.HeaderFormatter', 'goog.events.BrowserEvent', 'goog.testing.LooseMock', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('editor/plugins/linkbubble.js', ['goog.editor.plugins.LinkBubble', 'goog.editor.plugins.LinkBubble.Action'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.editor.Command', 'goog.editor.Link', 'goog.editor.plugins.AbstractBubblePlugin', 'goog.editor.range', 'goog.functions', 'goog.string', 'goog.style', 'goog.ui.editor.messages', 'goog.uri.utils', 'goog.window'], false); -goog.addDependency('editor/plugins/linkbubble_test.js', ['goog.editor.plugins.LinkBubbleTest'], ['goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.Command', 'goog.editor.Link', 'goog.editor.plugins.LinkBubble', 'goog.events.BrowserEvent', 'goog.events.Event', 'goog.events.EventType', 'goog.string', 'goog.style', 'goog.testing.FunctionMock', 'goog.testing.PropertyReplacer', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('editor/plugins/linkdialogplugin.js', ['goog.editor.plugins.LinkDialogPlugin'], ['goog.array', 'goog.dom', 'goog.editor.Command', 'goog.editor.plugins.AbstractDialogPlugin', 'goog.events.EventHandler', 'goog.functions', 'goog.ui.editor.AbstractDialog', 'goog.ui.editor.LinkDialog', 'goog.uri.utils'], false); -goog.addDependency('editor/plugins/linkdialogplugin_test.js', ['goog.ui.editor.plugins.LinkDialogTest'], ['goog.dom', 'goog.dom.DomHelper', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.Field', 'goog.editor.Link', 'goog.editor.plugins.LinkDialogPlugin', 'goog.string', 'goog.string.Unicode', 'goog.testing.MockControl', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.editor.dom', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.mockmatchers', 'goog.ui.editor.AbstractDialog', 'goog.ui.editor.LinkDialog', 'goog.userAgent'], false); -goog.addDependency('editor/plugins/linkshortcutplugin.js', ['goog.editor.plugins.LinkShortcutPlugin'], ['goog.editor.Command', 'goog.editor.Plugin'], false); -goog.addDependency('editor/plugins/linkshortcutplugin_test.js', ['goog.editor.plugins.LinkShortcutPluginTest'], ['goog.dom', 'goog.editor.Field', 'goog.editor.plugins.BasicTextFormatter', 'goog.editor.plugins.LinkBubble', 'goog.editor.plugins.LinkShortcutPlugin', 'goog.events.KeyCodes', 'goog.testing.PropertyReplacer', 'goog.testing.dom', 'goog.testing.events', 'goog.testing.jsunit'], false); -goog.addDependency('editor/plugins/listtabhandler.js', ['goog.editor.plugins.ListTabHandler'], ['goog.dom', 'goog.dom.TagName', 'goog.editor.Command', 'goog.editor.plugins.AbstractTabHandler', 'goog.iter'], false); -goog.addDependency('editor/plugins/listtabhandler_test.js', ['goog.editor.plugins.ListTabHandlerTest'], ['goog.dom', 'goog.editor.Command', 'goog.editor.plugins.ListTabHandler', 'goog.events.BrowserEvent', 'goog.events.KeyCodes', 'goog.functions', 'goog.testing.StrictMock', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.jsunit'], false); -goog.addDependency('editor/plugins/loremipsum.js', ['goog.editor.plugins.LoremIpsum'], ['goog.asserts', 'goog.dom', 'goog.editor.Command', 'goog.editor.Field', 'goog.editor.Plugin', 'goog.editor.node', 'goog.functions', 'goog.userAgent'], false); -goog.addDependency('editor/plugins/loremipsum_test.js', ['goog.editor.plugins.LoremIpsumTest'], ['goog.dom', 'goog.editor.Command', 'goog.editor.Field', 'goog.editor.plugins.LoremIpsum', 'goog.string.Unicode', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('editor/plugins/removeformatting.js', ['goog.editor.plugins.RemoveFormatting'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Plugin', 'goog.editor.node', 'goog.editor.range', 'goog.string', 'goog.userAgent'], false); -goog.addDependency('editor/plugins/removeformatting_test.js', ['goog.editor.plugins.RemoveFormattingTest'], ['goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.plugins.RemoveFormatting', 'goog.string', 'goog.testing.ExpectedFailures', 'goog.testing.dom', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('editor/plugins/spacestabhandler.js', ['goog.editor.plugins.SpacesTabHandler'], ['goog.dom.TagName', 'goog.editor.plugins.AbstractTabHandler', 'goog.editor.range'], false); -goog.addDependency('editor/plugins/spacestabhandler_test.js', ['goog.editor.plugins.SpacesTabHandlerTest'], ['goog.dom', 'goog.dom.Range', 'goog.editor.plugins.SpacesTabHandler', 'goog.events.BrowserEvent', 'goog.events.KeyCodes', 'goog.functions', 'goog.testing.StrictMock', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.jsunit'], false); -goog.addDependency('editor/plugins/tableeditor.js', ['goog.editor.plugins.TableEditor'], ['goog.array', 'goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.Plugin', 'goog.editor.Table', 'goog.editor.node', 'goog.editor.range', 'goog.object', 'goog.userAgent'], false); -goog.addDependency('editor/plugins/tableeditor_test.js', ['goog.editor.plugins.TableEditorTest'], ['goog.dom', 'goog.dom.Range', 'goog.editor.plugins.TableEditor', 'goog.object', 'goog.string', 'goog.testing.ExpectedFailures', 'goog.testing.JsUnitException', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('editor/plugins/tagonenterhandler.js', ['goog.editor.plugins.TagOnEnterHandler'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.Command', 'goog.editor.node', 'goog.editor.plugins.EnterHandler', 'goog.editor.range', 'goog.editor.style', 'goog.events.KeyCodes', 'goog.functions', 'goog.string.Unicode', 'goog.style', 'goog.userAgent'], false); -goog.addDependency('editor/plugins/tagonenterhandler_test.js', ['goog.editor.plugins.TagOnEnterHandlerTest'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Field', 'goog.editor.Plugin', 'goog.editor.plugins.TagOnEnterHandler', 'goog.events.KeyCodes', 'goog.string.Unicode', 'goog.testing.dom', 'goog.testing.editor.TestHelper', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('editor/plugins/undoredo.js', ['goog.editor.plugins.UndoRedo'], ['goog.dom', 'goog.dom.NodeOffset', 'goog.dom.Range', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.Field', 'goog.editor.Plugin', 'goog.editor.node', 'goog.editor.plugins.UndoRedoManager', 'goog.editor.plugins.UndoRedoState', 'goog.events', 'goog.events.EventHandler', 'goog.log', 'goog.object'], false); -goog.addDependency('editor/plugins/undoredo_test.js', ['goog.editor.plugins.UndoRedoTest'], ['goog.array', 'goog.dom', 'goog.dom.browserrange', 'goog.editor.Field', 'goog.editor.plugins.LoremIpsum', 'goog.editor.plugins.UndoRedo', 'goog.events', 'goog.functions', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.StrictMock', 'goog.testing.jsunit'], false); -goog.addDependency('editor/plugins/undoredomanager.js', ['goog.editor.plugins.UndoRedoManager', 'goog.editor.plugins.UndoRedoManager.EventType'], ['goog.editor.plugins.UndoRedoState', 'goog.events', 'goog.events.EventTarget'], false); -goog.addDependency('editor/plugins/undoredomanager_test.js', ['goog.editor.plugins.UndoRedoManagerTest'], ['goog.editor.plugins.UndoRedoManager', 'goog.editor.plugins.UndoRedoState', 'goog.events', 'goog.testing.StrictMock', 'goog.testing.jsunit'], false); -goog.addDependency('editor/plugins/undoredostate.js', ['goog.editor.plugins.UndoRedoState'], ['goog.events.EventTarget'], false); -goog.addDependency('editor/plugins/undoredostate_test.js', ['goog.editor.plugins.UndoRedoStateTest'], ['goog.editor.plugins.UndoRedoState', 'goog.testing.jsunit'], false); -goog.addDependency('editor/range.js', ['goog.editor.range', 'goog.editor.range.Point'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.RangeEndpoint', 'goog.dom.SavedCaretRange', 'goog.editor.node', 'goog.editor.style', 'goog.iter', 'goog.userAgent'], false); -goog.addDependency('editor/range_test.js', ['goog.editor.rangeTest'], ['goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.range', 'goog.editor.range.Point', 'goog.string', 'goog.testing.dom', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('editor/seamlessfield.js', ['goog.editor.SeamlessField'], ['goog.cssom.iframe.style', 'goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.dom.safe', 'goog.editor.BrowserFeature', 'goog.editor.Field', 'goog.editor.icontent', 'goog.editor.icontent.FieldFormatInfo', 'goog.editor.icontent.FieldStyleInfo', 'goog.editor.node', 'goog.events', 'goog.events.EventType', 'goog.html.uncheckedconversions', 'goog.log', 'goog.string.Const', 'goog.style'], false); -goog.addDependency('editor/seamlessfield_test.js', ['goog.editor.seamlessfield_test'], ['goog.dom', 'goog.dom.DomHelper', 'goog.dom.Range', 'goog.editor.BrowserFeature', 'goog.editor.Field', 'goog.editor.SeamlessField', 'goog.events', 'goog.functions', 'goog.style', 'goog.testing.MockClock', 'goog.testing.MockRange', 'goog.testing.jsunit'], false); -goog.addDependency('editor/style.js', ['goog.editor.style'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.events.EventType', 'goog.object', 'goog.style', 'goog.userAgent'], false); -goog.addDependency('editor/style_test.js', ['goog.editor.styleTest'], ['goog.dom', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.style', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.style', 'goog.testing.LooseMock', 'goog.testing.jsunit', 'goog.testing.mockmatchers'], false); -goog.addDependency('editor/table.js', ['goog.editor.Table', 'goog.editor.TableCell', 'goog.editor.TableRow'], ['goog.dom', 'goog.dom.DomHelper', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.log', 'goog.string.Unicode', 'goog.style'], false); -goog.addDependency('editor/table_test.js', ['goog.editor.TableTest'], ['goog.dom', 'goog.editor.Table', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('events/actioneventwrapper.js', ['goog.events.actionEventWrapper'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.dom', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.EventWrapper', 'goog.events.KeyCodes', 'goog.userAgent'], false); -goog.addDependency('events/actioneventwrapper_test.js', ['goog.events.actionEventWrapperTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.events', 'goog.events.EventHandler', 'goog.events.KeyCodes', 'goog.events.actionEventWrapper', 'goog.testing.events', 'goog.testing.jsunit'], false); -goog.addDependency('events/actionhandler.js', ['goog.events.ActionEvent', 'goog.events.ActionHandler', 'goog.events.ActionHandler.EventType', 'goog.events.BeforeActionEvent'], ['goog.events', 'goog.events.BrowserEvent', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.userAgent'], false); -goog.addDependency('events/actionhandler_test.js', ['goog.events.ActionHandlerTest'], ['goog.dom', 'goog.events', 'goog.events.ActionHandler', 'goog.testing.events', 'goog.testing.jsunit'], false); -goog.addDependency('events/browserevent.js', ['goog.events.BrowserEvent', 'goog.events.BrowserEvent.MouseButton'], ['goog.events.BrowserFeature', 'goog.events.Event', 'goog.events.EventType', 'goog.reflect', 'goog.userAgent'], false); -goog.addDependency('events/browserevent_test.js', ['goog.events.BrowserEventTest'], ['goog.events.BrowserEvent', 'goog.events.BrowserFeature', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('events/browserfeature.js', ['goog.events.BrowserFeature'], ['goog.userAgent'], false); -goog.addDependency('events/event.js', ['goog.events.Event', 'goog.events.EventLike'], ['goog.Disposable', 'goog.events.EventId'], false); -goog.addDependency('events/event_test.js', ['goog.events.EventTest'], ['goog.events.Event', 'goog.events.EventId', 'goog.events.EventTarget', 'goog.testing.jsunit'], false); -goog.addDependency('events/eventhandler.js', ['goog.events.EventHandler'], ['goog.Disposable', 'goog.events', 'goog.object'], false); -goog.addDependency('events/eventhandler_test.js', ['goog.events.EventHandlerTest'], ['goog.events', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false); -goog.addDependency('events/eventid.js', ['goog.events.EventId'], [], false); -goog.addDependency('events/events.js', ['goog.events', 'goog.events.CaptureSimulationMode', 'goog.events.Key', 'goog.events.ListenableType'], ['goog.asserts', 'goog.debug.entryPointRegistry', 'goog.events.BrowserEvent', 'goog.events.BrowserFeature', 'goog.events.Listenable', 'goog.events.ListenerMap'], false); -goog.addDependency('events/events_test.js', ['goog.eventsTest'], ['goog.asserts.AssertionError', 'goog.debug.EntryPointMonitor', 'goog.debug.ErrorHandler', 'goog.debug.entryPointRegistry', 'goog.dom', 'goog.events', 'goog.events.BrowserFeature', 'goog.events.CaptureSimulationMode', 'goog.events.Event', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.Listener', 'goog.functions', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false); -goog.addDependency('events/eventtarget.js', ['goog.events.EventTarget'], ['goog.Disposable', 'goog.asserts', 'goog.events', 'goog.events.Event', 'goog.events.Listenable', 'goog.events.ListenerMap', 'goog.object'], false); -goog.addDependency('events/eventtarget_test.js', ['goog.events.EventTargetTest'], ['goog.events.EventTarget', 'goog.events.Listenable', 'goog.events.eventTargetTester', 'goog.events.eventTargetTester.KeyType', 'goog.events.eventTargetTester.UnlistenReturnType', 'goog.testing.jsunit'], false); -goog.addDependency('events/eventtarget_via_googevents_test.js', ['goog.events.EventTargetGoogEventsTest'], ['goog.events', 'goog.events.EventTarget', 'goog.events.eventTargetTester', 'goog.events.eventTargetTester.KeyType', 'goog.events.eventTargetTester.UnlistenReturnType', 'goog.testing', 'goog.testing.jsunit'], false); -goog.addDependency('events/eventtarget_via_w3cinterface_test.js', ['goog.events.EventTargetW3CTest'], ['goog.events.EventTarget', 'goog.events.eventTargetTester', 'goog.events.eventTargetTester.KeyType', 'goog.events.eventTargetTester.UnlistenReturnType', 'goog.testing.jsunit'], false); -goog.addDependency('events/eventtargettester.js', ['goog.events.eventTargetTester', 'goog.events.eventTargetTester.KeyType', 'goog.events.eventTargetTester.UnlistenReturnType'], ['goog.array', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.testing.asserts', 'goog.testing.recordFunction'], false); -goog.addDependency('events/eventtype.js', ['goog.events.EventType'], ['goog.userAgent'], false); -goog.addDependency('events/eventwrapper.js', ['goog.events.EventWrapper'], [], false); -goog.addDependency('events/filedrophandler.js', ['goog.events.FileDropHandler', 'goog.events.FileDropHandler.EventType'], ['goog.array', 'goog.dom', 'goog.events.BrowserEvent', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.log', 'goog.log.Level'], false); -goog.addDependency('events/filedrophandler_test.js', ['goog.events.FileDropHandlerTest'], ['goog.events', 'goog.events.BrowserEvent', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.FileDropHandler', 'goog.testing.jsunit'], false); -goog.addDependency('events/focushandler.js', ['goog.events.FocusHandler', 'goog.events.FocusHandler.EventType'], ['goog.events', 'goog.events.BrowserEvent', 'goog.events.EventTarget', 'goog.userAgent'], false); -goog.addDependency('events/imehandler.js', ['goog.events.ImeHandler', 'goog.events.ImeHandler.Event', 'goog.events.ImeHandler.EventType'], ['goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.userAgent'], false); -goog.addDependency('events/imehandler_test.js', ['goog.events.ImeHandlerTest'], ['goog.array', 'goog.dom', 'goog.events', 'goog.events.ImeHandler', 'goog.events.KeyCodes', 'goog.object', 'goog.string', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('events/inputhandler.js', ['goog.events.InputHandler', 'goog.events.InputHandler.EventType'], ['goog.Timer', 'goog.dom', 'goog.events.BrowserEvent', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.KeyCodes', 'goog.userAgent'], false); -goog.addDependency('events/inputhandler_test.js', ['goog.events.InputHandlerTest'], ['goog.dom', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.InputHandler', 'goog.events.KeyCodes', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.userAgent'], false); -goog.addDependency('events/keycodes.js', ['goog.events.KeyCodes'], ['goog.userAgent'], false); -goog.addDependency('events/keycodes_test.js', ['goog.events.KeyCodesTest'], ['goog.events.BrowserEvent', 'goog.events.KeyCodes', 'goog.object', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('events/keyhandler.js', ['goog.events.KeyEvent', 'goog.events.KeyHandler', 'goog.events.KeyHandler.EventType'], ['goog.events', 'goog.events.BrowserEvent', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.userAgent'], false); -goog.addDependency('events/keyhandler_test.js', ['goog.events.KeyEventTest'], ['goog.dom', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('events/keynames.js', ['goog.events.KeyNames'], [], false); -goog.addDependency('events/listenable.js', ['goog.events.Listenable', 'goog.events.ListenableKey'], ['goog.events.EventId'], false); -goog.addDependency('events/listenable_test.js', ['goog.events.ListenableTest'], ['goog.events.Listenable', 'goog.testing.jsunit'], false); -goog.addDependency('events/listener.js', ['goog.events.Listener'], ['goog.events.ListenableKey'], false); -goog.addDependency('events/listenermap.js', ['goog.events.ListenerMap'], ['goog.array', 'goog.events.Listener', 'goog.object'], false); -goog.addDependency('events/listenermap_test.js', ['goog.events.ListenerMapTest'], ['goog.dispose', 'goog.events', 'goog.events.EventId', 'goog.events.EventTarget', 'goog.events.ListenerMap', 'goog.testing.jsunit'], false); -goog.addDependency('events/mousewheelhandler.js', ['goog.events.MouseWheelEvent', 'goog.events.MouseWheelHandler', 'goog.events.MouseWheelHandler.EventType'], ['goog.dom', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.EventTarget', 'goog.math', 'goog.style', 'goog.userAgent'], false); -goog.addDependency('events/mousewheelhandler_test.js', ['goog.events.MouseWheelHandlerTest'], ['goog.dom', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.MouseWheelEvent', 'goog.events.MouseWheelHandler', 'goog.functions', 'goog.string', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('events/onlinehandler.js', ['goog.events.OnlineHandler', 'goog.events.OnlineHandler.EventType'], ['goog.Timer', 'goog.events.BrowserFeature', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.net.NetworkStatusMonitor'], false); -goog.addDependency('events/onlinelistener_test.js', ['goog.events.OnlineHandlerTest'], ['goog.events', 'goog.events.BrowserFeature', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.OnlineHandler', 'goog.net.NetworkStatusMonitor', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false); -goog.addDependency('events/pastehandler.js', ['goog.events.PasteHandler', 'goog.events.PasteHandler.EventType', 'goog.events.PasteHandler.State'], ['goog.Timer', 'goog.async.ConditionalDelay', 'goog.events.BrowserEvent', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.log', 'goog.userAgent'], false); -goog.addDependency('events/pastehandler_test.js', ['goog.events.PasteHandlerTest'], ['goog.dom', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.PasteHandler', 'goog.testing.MockClock', 'goog.testing.MockUserAgent', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('events/wheelevent.js', ['goog.events.WheelEvent'], ['goog.asserts', 'goog.events.BrowserEvent'], false); -goog.addDependency('events/wheelhandler.js', ['goog.events.WheelHandler'], ['goog.dom', 'goog.events', 'goog.events.EventTarget', 'goog.events.WheelEvent', 'goog.style', 'goog.userAgent', 'goog.userAgent.product', 'goog.userAgent.product.isVersion'], false); -goog.addDependency('events/wheelhandler_test.js', ['goog.events.WheelHandlerTest'], ['goog.dom', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.WheelEvent', 'goog.events.WheelHandler', 'goog.string', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.product'], false); -goog.addDependency('format/emailaddress.js', ['goog.format.EmailAddress'], ['goog.string'], false); -goog.addDependency('format/emailaddress_test.js', ['goog.format.EmailAddressTest'], ['goog.array', 'goog.format.EmailAddress', 'goog.testing.jsunit'], false); -goog.addDependency('format/format.js', ['goog.format'], ['goog.i18n.GraphemeBreak', 'goog.string', 'goog.userAgent'], false); -goog.addDependency('format/format_test.js', ['goog.formatTest'], ['goog.dom', 'goog.format', 'goog.string', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false); -goog.addDependency('format/htmlprettyprinter.js', ['goog.format.HtmlPrettyPrinter', 'goog.format.HtmlPrettyPrinter.Buffer'], ['goog.object', 'goog.string.StringBuffer'], false); -goog.addDependency('format/htmlprettyprinter_test.js', ['goog.format.HtmlPrettyPrinterTest'], ['goog.format.HtmlPrettyPrinter', 'goog.testing.MockClock', 'goog.testing.jsunit'], false); -goog.addDependency('format/internationalizedemailaddress.js', ['goog.format.InternationalizedEmailAddress'], ['goog.format.EmailAddress', 'goog.string'], false); -goog.addDependency('format/internationalizedemailaddress_test.js', ['goog.format.InternationalizedEmailAddressTest'], ['goog.array', 'goog.format.InternationalizedEmailAddress', 'goog.testing.jsunit'], false); -goog.addDependency('format/jsonprettyprinter.js', ['goog.format.JsonPrettyPrinter', 'goog.format.JsonPrettyPrinter.HtmlDelimiters', 'goog.format.JsonPrettyPrinter.TextDelimiters'], ['goog.json', 'goog.json.Serializer', 'goog.string', 'goog.string.StringBuffer', 'goog.string.format'], false); -goog.addDependency('format/jsonprettyprinter_test.js', ['goog.format.JsonPrettyPrinterTest'], ['goog.format.JsonPrettyPrinter', 'goog.testing.jsunit'], false); -goog.addDependency('fs/entry.js', ['goog.fs.DirectoryEntry', 'goog.fs.DirectoryEntry.Behavior', 'goog.fs.Entry', 'goog.fs.FileEntry'], [], false); -goog.addDependency('fs/entryimpl.js', ['goog.fs.DirectoryEntryImpl', 'goog.fs.EntryImpl', 'goog.fs.FileEntryImpl'], ['goog.array', 'goog.async.Deferred', 'goog.fs.DirectoryEntry', 'goog.fs.Entry', 'goog.fs.Error', 'goog.fs.FileEntry', 'goog.fs.FileWriter', 'goog.functions', 'goog.string'], false); -goog.addDependency('fs/error.js', ['goog.fs.Error', 'goog.fs.Error.ErrorCode'], ['goog.debug.Error', 'goog.object', 'goog.string'], false); -goog.addDependency('fs/filereader.js', ['goog.fs.FileReader', 'goog.fs.FileReader.EventType', 'goog.fs.FileReader.ReadyState'], ['goog.async.Deferred', 'goog.events.EventTarget', 'goog.fs.Error', 'goog.fs.ProgressEvent'], false); -goog.addDependency('fs/filesaver.js', ['goog.fs.FileSaver', 'goog.fs.FileSaver.EventType', 'goog.fs.FileSaver.ReadyState'], ['goog.events.EventTarget', 'goog.fs.Error', 'goog.fs.ProgressEvent'], false); -goog.addDependency('fs/filesystem.js', ['goog.fs.FileSystem'], [], false); -goog.addDependency('fs/filesystemimpl.js', ['goog.fs.FileSystemImpl'], ['goog.fs.DirectoryEntryImpl', 'goog.fs.FileSystem'], false); -goog.addDependency('fs/filewriter.js', ['goog.fs.FileWriter'], ['goog.fs.Error', 'goog.fs.FileSaver'], false); -goog.addDependency('fs/fs.js', ['goog.fs'], ['goog.array', 'goog.async.Deferred', 'goog.fs.Error', 'goog.fs.FileReader', 'goog.fs.FileSystemImpl', 'goog.userAgent'], false); -goog.addDependency('fs/fs_test.js', ['goog.fsTest'], ['goog.Promise', 'goog.array', 'goog.dom', 'goog.events', 'goog.fs', 'goog.fs.DirectoryEntry', 'goog.fs.Error', 'goog.fs.FileReader', 'goog.fs.FileSaver', 'goog.string', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false); -goog.addDependency('fs/progressevent.js', ['goog.fs.ProgressEvent'], ['goog.events.Event'], false); -goog.addDependency('functions/functions.js', ['goog.functions'], [], false); -goog.addDependency('functions/functions_test.js', ['goog.functionsTest'], ['goog.functions', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false); -goog.addDependency('fx/abstractdragdrop.js', ['goog.fx.AbstractDragDrop', 'goog.fx.AbstractDragDrop.EventType', 'goog.fx.DragDropEvent', 'goog.fx.DragDropItem'], ['goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.fx.Dragger', 'goog.math.Box', 'goog.math.Coordinate', 'goog.style'], false); -goog.addDependency('fx/abstractdragdrop_test.js', ['goog.fx.AbstractDragDropTest'], ['goog.array', 'goog.events.EventType', 'goog.functions', 'goog.fx.AbstractDragDrop', 'goog.fx.DragDropItem', 'goog.math.Box', 'goog.math.Coordinate', 'goog.style', 'goog.testing.events', 'goog.testing.jsunit'], false); -goog.addDependency('fx/anim/anim.js', ['goog.fx.anim', 'goog.fx.anim.Animated'], ['goog.async.AnimationDelay', 'goog.async.Delay', 'goog.object'], false); -goog.addDependency('fx/anim/anim_test.js', ['goog.fx.animTest'], ['goog.async.AnimationDelay', 'goog.async.Delay', 'goog.events', 'goog.functions', 'goog.fx.Animation', 'goog.fx.anim', 'goog.object', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.userAgent'], false); -goog.addDependency('fx/animation.js', ['goog.fx.Animation', 'goog.fx.Animation.EventType', 'goog.fx.Animation.State', 'goog.fx.AnimationEvent'], ['goog.array', 'goog.events.Event', 'goog.fx.Transition', 'goog.fx.TransitionBase', 'goog.fx.anim', 'goog.fx.anim.Animated'], false); -goog.addDependency('fx/animation_test.js', ['goog.fx.AnimationTest'], ['goog.events', 'goog.fx.Animation', 'goog.testing.MockClock', 'goog.testing.jsunit'], false); -goog.addDependency('fx/animationqueue.js', ['goog.fx.AnimationParallelQueue', 'goog.fx.AnimationQueue', 'goog.fx.AnimationSerialQueue'], ['goog.array', 'goog.asserts', 'goog.events', 'goog.fx.Transition', 'goog.fx.TransitionBase'], false); -goog.addDependency('fx/animationqueue_test.js', ['goog.fx.AnimationQueueTest'], ['goog.events', 'goog.fx.Animation', 'goog.fx.AnimationParallelQueue', 'goog.fx.AnimationSerialQueue', 'goog.fx.Transition', 'goog.fx.anim', 'goog.testing.MockClock', 'goog.testing.jsunit'], false); -goog.addDependency('fx/css3/fx.js', ['goog.fx.css3'], ['goog.fx.css3.Transition'], false); -goog.addDependency('fx/css3/transition.js', ['goog.fx.css3.Transition'], ['goog.Timer', 'goog.asserts', 'goog.fx.TransitionBase', 'goog.style', 'goog.style.transition'], false); -goog.addDependency('fx/css3/transition_test.js', ['goog.fx.css3.TransitionTest'], ['goog.dispose', 'goog.dom', 'goog.events', 'goog.fx.Transition', 'goog.fx.css3.Transition', 'goog.style.transition', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false); -goog.addDependency('fx/cssspriteanimation.js', ['goog.fx.CssSpriteAnimation'], ['goog.fx.Animation'], false); -goog.addDependency('fx/cssspriteanimation_test.js', ['goog.fx.CssSpriteAnimationTest'], ['goog.fx.CssSpriteAnimation', 'goog.math.Box', 'goog.math.Size', 'goog.testing.MockClock', 'goog.testing.jsunit'], false); -goog.addDependency('fx/dom.js', ['goog.fx.dom', 'goog.fx.dom.BgColorTransform', 'goog.fx.dom.ColorTransform', 'goog.fx.dom.Fade', 'goog.fx.dom.FadeIn', 'goog.fx.dom.FadeInAndShow', 'goog.fx.dom.FadeOut', 'goog.fx.dom.FadeOutAndHide', 'goog.fx.dom.PredefinedEffect', 'goog.fx.dom.Resize', 'goog.fx.dom.ResizeHeight', 'goog.fx.dom.ResizeWidth', 'goog.fx.dom.Scroll', 'goog.fx.dom.Slide', 'goog.fx.dom.SlideFrom', 'goog.fx.dom.Swipe'], ['goog.color', 'goog.events', 'goog.fx.Animation', 'goog.fx.Transition', 'goog.style', 'goog.style.bidi'], false); -goog.addDependency('fx/dragdrop.js', ['goog.fx.DragDrop'], ['goog.fx.AbstractDragDrop', 'goog.fx.DragDropItem'], false); -goog.addDependency('fx/dragdropgroup.js', ['goog.fx.DragDropGroup'], ['goog.dom', 'goog.fx.AbstractDragDrop', 'goog.fx.DragDropItem'], false); -goog.addDependency('fx/dragdropgroup_test.js', ['goog.fx.DragDropGroupTest'], ['goog.events', 'goog.fx.DragDropGroup', 'goog.testing.jsunit'], false); -goog.addDependency('fx/dragger.js', ['goog.fx.DragEvent', 'goog.fx.Dragger', 'goog.fx.Dragger.EventType'], ['goog.dom', 'goog.events', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.math.Coordinate', 'goog.math.Rect', 'goog.style', 'goog.style.bidi', 'goog.userAgent'], false); -goog.addDependency('fx/dragger_test.js', ['goog.fx.DraggerTest'], ['goog.dom', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.Event', 'goog.events.EventType', 'goog.fx.Dragger', 'goog.math.Rect', 'goog.style.bidi', 'goog.testing.StrictMock', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('fx/draglistgroup.js', ['goog.fx.DragListDirection', 'goog.fx.DragListGroup', 'goog.fx.DragListGroup.EventType', 'goog.fx.DragListGroupEvent'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.fx.Dragger', 'goog.math.Coordinate', 'goog.string', 'goog.style'], false); -goog.addDependency('fx/draglistgroup_test.js', ['goog.fx.DragListGroupTest'], ['goog.array', 'goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.BrowserFeature', 'goog.events.Event', 'goog.events.EventType', 'goog.fx.DragEvent', 'goog.fx.DragListDirection', 'goog.fx.DragListGroup', 'goog.fx.Dragger', 'goog.math.Coordinate', 'goog.object', 'goog.testing.events', 'goog.testing.jsunit'], false); -goog.addDependency('fx/dragscrollsupport.js', ['goog.fx.DragScrollSupport'], ['goog.Disposable', 'goog.Timer', 'goog.dom', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.math.Coordinate', 'goog.style'], false); -goog.addDependency('fx/dragscrollsupport_test.js', ['goog.fx.DragScrollSupportTest'], ['goog.fx.DragScrollSupport', 'goog.math.Coordinate', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.jsunit'], false); -goog.addDependency('fx/easing.js', ['goog.fx.easing'], [], false); -goog.addDependency('fx/easing_test.js', ['goog.fx.easingTest'], ['goog.fx.easing', 'goog.testing.jsunit'], false); -goog.addDependency('fx/fx.js', ['goog.fx'], ['goog.asserts', 'goog.fx.Animation', 'goog.fx.Animation.EventType', 'goog.fx.Animation.State', 'goog.fx.AnimationEvent', 'goog.fx.Transition.EventType', 'goog.fx.easing'], false); -goog.addDependency('fx/fx_test.js', ['goog.fxTest'], ['goog.fx.Animation', 'goog.object', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false); -goog.addDependency('fx/transition.js', ['goog.fx.Transition', 'goog.fx.Transition.EventType'], [], false); -goog.addDependency('fx/transitionbase.js', ['goog.fx.TransitionBase', 'goog.fx.TransitionBase.State'], ['goog.events.EventTarget', 'goog.fx.Transition'], false); -goog.addDependency('graphics/abstractgraphics.js', ['goog.graphics.AbstractGraphics'], ['goog.dom', 'goog.graphics.Path', 'goog.math.Coordinate', 'goog.math.Size', 'goog.style', 'goog.ui.Component'], false); -goog.addDependency('graphics/affinetransform.js', ['goog.graphics.AffineTransform'], ['goog.math'], false); -goog.addDependency('graphics/canvaselement.js', ['goog.graphics.CanvasEllipseElement', 'goog.graphics.CanvasGroupElement', 'goog.graphics.CanvasImageElement', 'goog.graphics.CanvasPathElement', 'goog.graphics.CanvasRectElement', 'goog.graphics.CanvasTextElement'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.dom.safe', 'goog.graphics.EllipseElement', 'goog.graphics.GroupElement', 'goog.graphics.ImageElement', 'goog.graphics.Path', 'goog.graphics.PathElement', 'goog.graphics.RectElement', 'goog.graphics.TextElement', 'goog.html.SafeHtml', 'goog.html.uncheckedconversions', 'goog.math', 'goog.string', 'goog.string.Const'], false); -goog.addDependency('graphics/canvasgraphics.js', ['goog.graphics.CanvasGraphics'], ['goog.events.EventType', 'goog.graphics.AbstractGraphics', 'goog.graphics.CanvasEllipseElement', 'goog.graphics.CanvasGroupElement', 'goog.graphics.CanvasImageElement', 'goog.graphics.CanvasPathElement', 'goog.graphics.CanvasRectElement', 'goog.graphics.CanvasTextElement', 'goog.graphics.SolidFill', 'goog.math.Size', 'goog.style'], false); -goog.addDependency('graphics/element.js', ['goog.graphics.Element'], ['goog.asserts', 'goog.events', 'goog.events.EventTarget', 'goog.events.Listenable', 'goog.graphics.AffineTransform', 'goog.math'], false); -goog.addDependency('graphics/ellipseelement.js', ['goog.graphics.EllipseElement'], ['goog.graphics.StrokeAndFillElement'], false); -goog.addDependency('graphics/ext/coordinates.js', ['goog.graphics.ext.coordinates'], ['goog.string'], false); -goog.addDependency('graphics/ext/element.js', ['goog.graphics.ext.Element'], ['goog.events.EventTarget', 'goog.functions', 'goog.graphics.ext.coordinates'], false); -goog.addDependency('graphics/ext/ellipse.js', ['goog.graphics.ext.Ellipse'], ['goog.graphics.ext.StrokeAndFillElement'], false); -goog.addDependency('graphics/ext/ext.js', ['goog.graphics.ext'], ['goog.graphics.ext.Ellipse', 'goog.graphics.ext.Graphics', 'goog.graphics.ext.Group', 'goog.graphics.ext.Image', 'goog.graphics.ext.Rectangle', 'goog.graphics.ext.Shape', 'goog.graphics.ext.coordinates'], false); -goog.addDependency('graphics/ext/graphics.js', ['goog.graphics.ext.Graphics'], ['goog.events', 'goog.events.EventType', 'goog.graphics', 'goog.graphics.ext.Group'], false); -goog.addDependency('graphics/ext/group.js', ['goog.graphics.ext.Group'], ['goog.array', 'goog.graphics.ext.Element'], false); -goog.addDependency('graphics/ext/image.js', ['goog.graphics.ext.Image'], ['goog.graphics.ext.Element'], false); -goog.addDependency('graphics/ext/path.js', ['goog.graphics.ext.Path'], ['goog.graphics.AffineTransform', 'goog.graphics.Path', 'goog.math.Rect'], false); -goog.addDependency('graphics/ext/rectangle.js', ['goog.graphics.ext.Rectangle'], ['goog.graphics.ext.StrokeAndFillElement'], false); -goog.addDependency('graphics/ext/shape.js', ['goog.graphics.ext.Shape'], ['goog.graphics.ext.StrokeAndFillElement'], false); -goog.addDependency('graphics/ext/strokeandfillelement.js', ['goog.graphics.ext.StrokeAndFillElement'], ['goog.graphics.ext.Element'], false); -goog.addDependency('graphics/fill.js', ['goog.graphics.Fill'], [], false); -goog.addDependency('graphics/font.js', ['goog.graphics.Font'], [], false); -goog.addDependency('graphics/graphics.js', ['goog.graphics'], ['goog.dom', 'goog.graphics.CanvasGraphics', 'goog.graphics.SvgGraphics', 'goog.graphics.VmlGraphics', 'goog.userAgent'], false); -goog.addDependency('graphics/groupelement.js', ['goog.graphics.GroupElement'], ['goog.graphics.Element'], false); -goog.addDependency('graphics/imageelement.js', ['goog.graphics.ImageElement'], ['goog.graphics.Element'], false); -goog.addDependency('graphics/lineargradient.js', ['goog.graphics.LinearGradient'], ['goog.asserts', 'goog.graphics.Fill'], false); -goog.addDependency('graphics/path.js', ['goog.graphics.Path', 'goog.graphics.Path.Segment'], ['goog.array', 'goog.math'], false); -goog.addDependency('graphics/pathelement.js', ['goog.graphics.PathElement'], ['goog.graphics.StrokeAndFillElement'], false); -goog.addDependency('graphics/paths.js', ['goog.graphics.paths'], ['goog.graphics.Path', 'goog.math.Coordinate'], false); -goog.addDependency('graphics/rectelement.js', ['goog.graphics.RectElement'], ['goog.graphics.StrokeAndFillElement'], false); -goog.addDependency('graphics/solidfill.js', ['goog.graphics.SolidFill'], ['goog.graphics.Fill'], false); -goog.addDependency('graphics/stroke.js', ['goog.graphics.Stroke'], [], false); -goog.addDependency('graphics/strokeandfillelement.js', ['goog.graphics.StrokeAndFillElement'], ['goog.graphics.Element'], false); -goog.addDependency('graphics/svgelement.js', ['goog.graphics.SvgEllipseElement', 'goog.graphics.SvgGroupElement', 'goog.graphics.SvgImageElement', 'goog.graphics.SvgPathElement', 'goog.graphics.SvgRectElement', 'goog.graphics.SvgTextElement'], ['goog.dom', 'goog.graphics.EllipseElement', 'goog.graphics.GroupElement', 'goog.graphics.ImageElement', 'goog.graphics.PathElement', 'goog.graphics.RectElement', 'goog.graphics.TextElement'], false); -goog.addDependency('graphics/svggraphics.js', ['goog.graphics.SvgGraphics'], ['goog.Timer', 'goog.dom', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.graphics.AbstractGraphics', 'goog.graphics.LinearGradient', 'goog.graphics.Path', 'goog.graphics.SolidFill', 'goog.graphics.Stroke', 'goog.graphics.SvgEllipseElement', 'goog.graphics.SvgGroupElement', 'goog.graphics.SvgImageElement', 'goog.graphics.SvgPathElement', 'goog.graphics.SvgRectElement', 'goog.graphics.SvgTextElement', 'goog.math', 'goog.math.Size', 'goog.style', 'goog.userAgent'], false); -goog.addDependency('graphics/textelement.js', ['goog.graphics.TextElement'], ['goog.graphics.StrokeAndFillElement'], false); -goog.addDependency('graphics/vmlelement.js', ['goog.graphics.VmlEllipseElement', 'goog.graphics.VmlGroupElement', 'goog.graphics.VmlImageElement', 'goog.graphics.VmlPathElement', 'goog.graphics.VmlRectElement', 'goog.graphics.VmlTextElement'], ['goog.dom', 'goog.graphics.EllipseElement', 'goog.graphics.GroupElement', 'goog.graphics.ImageElement', 'goog.graphics.PathElement', 'goog.graphics.RectElement', 'goog.graphics.TextElement'], false); -goog.addDependency('graphics/vmlgraphics.js', ['goog.graphics.VmlGraphics'], ['goog.array', 'goog.dom.safe', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.graphics.AbstractGraphics', 'goog.graphics.LinearGradient', 'goog.graphics.Path', 'goog.graphics.SolidFill', 'goog.graphics.VmlEllipseElement', 'goog.graphics.VmlGroupElement', 'goog.graphics.VmlImageElement', 'goog.graphics.VmlPathElement', 'goog.graphics.VmlRectElement', 'goog.graphics.VmlTextElement', 'goog.html.uncheckedconversions', 'goog.math', 'goog.math.Size', 'goog.string', 'goog.string.Const', 'goog.style'], false); -goog.addDependency('history/event.js', ['goog.history.Event'], ['goog.events.Event', 'goog.history.EventType'], false); -goog.addDependency('history/eventtype.js', ['goog.history.EventType'], [], false); -goog.addDependency('history/history.js', ['goog.History', 'goog.History.Event', 'goog.History.EventType'], ['goog.Timer', 'goog.dom', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.history.Event', 'goog.history.EventType', 'goog.labs.userAgent.device', 'goog.memoize', 'goog.string', 'goog.userAgent'], false); -goog.addDependency('history/history_test.js', ['goog.HistoryTest'], ['goog.History', 'goog.dispose', 'goog.dom', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('history/html5history.js', ['goog.history.Html5History', 'goog.history.Html5History.TokenTransformer'], ['goog.asserts', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.history.Event'], false); -goog.addDependency('history/html5history_test.js', ['goog.history.Html5HistoryTest'], ['goog.history.Html5History', 'goog.testing.MockControl', 'goog.testing.jsunit', 'goog.testing.mockmatchers'], false); -goog.addDependency('html/flash.js', ['goog.html.flash'], ['goog.asserts', 'goog.html.SafeHtml'], false); -goog.addDependency('html/flash_test.js', ['goog.html.flashTest'], ['goog.html.SafeHtml', 'goog.html.TrustedResourceUrl', 'goog.html.flash', 'goog.string.Const', 'goog.testing.jsunit'], false); -goog.addDependency('html/legacyconversions.js', ['goog.html.legacyconversions'], ['goog.html.SafeHtml', 'goog.html.SafeStyle', 'goog.html.SafeUrl', 'goog.html.TrustedResourceUrl'], false); -goog.addDependency('html/legacyconversions_test.js', ['goog.html.legacyconversionsTest'], ['goog.html.SafeHtml', 'goog.html.SafeUrl', 'goog.html.TrustedResourceUrl', 'goog.html.legacyconversions', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false); -goog.addDependency('html/safehtml.js', ['goog.html.SafeHtml'], ['goog.array', 'goog.asserts', 'goog.dom.tags', 'goog.html.SafeStyle', 'goog.html.SafeStyleSheet', 'goog.html.SafeUrl', 'goog.html.TrustedResourceUrl', 'goog.i18n.bidi.Dir', 'goog.i18n.bidi.DirectionalString', 'goog.object', 'goog.string', 'goog.string.Const', 'goog.string.TypedString'], false); -goog.addDependency('html/safehtml_test.js', ['goog.html.safeHtmlTest'], ['goog.html.SafeHtml', 'goog.html.SafeStyle', 'goog.html.SafeStyleSheet', 'goog.html.SafeUrl', 'goog.html.TrustedResourceUrl', 'goog.html.testing', 'goog.i18n.bidi.Dir', 'goog.string.Const', 'goog.testing.jsunit'], false); -goog.addDependency('html/safescript.js', ['goog.html.SafeScript'], ['goog.asserts', 'goog.string.Const', 'goog.string.TypedString'], false); -goog.addDependency('html/safescript_test.js', ['goog.html.safeScriptTest'], ['goog.html.SafeScript', 'goog.string.Const', 'goog.testing.jsunit'], false); -goog.addDependency('html/safestyle.js', ['goog.html.SafeStyle'], ['goog.array', 'goog.asserts', 'goog.string', 'goog.string.Const', 'goog.string.TypedString'], false); -goog.addDependency('html/safestyle_test.js', ['goog.html.safeStyleTest'], ['goog.html.SafeStyle', 'goog.string.Const', 'goog.testing.jsunit'], false); -goog.addDependency('html/safestylesheet.js', ['goog.html.SafeStyleSheet'], ['goog.array', 'goog.asserts', 'goog.string', 'goog.string.Const', 'goog.string.TypedString'], false); -goog.addDependency('html/safestylesheet_test.js', ['goog.html.safeStyleSheetTest'], ['goog.html.SafeStyleSheet', 'goog.string', 'goog.string.Const', 'goog.testing.jsunit'], false); -goog.addDependency('html/safeurl.js', ['goog.html.SafeUrl'], ['goog.asserts', 'goog.i18n.bidi.Dir', 'goog.i18n.bidi.DirectionalString', 'goog.string.Const', 'goog.string.TypedString'], false); -goog.addDependency('html/safeurl_test.js', ['goog.html.safeUrlTest'], ['goog.html.SafeUrl', 'goog.i18n.bidi.Dir', 'goog.string.Const', 'goog.testing.jsunit'], false); -goog.addDependency('html/silverlight.js', ['goog.html.silverlight'], ['goog.html.SafeHtml', 'goog.html.TrustedResourceUrl', 'goog.html.flash', 'goog.string.Const'], false); -goog.addDependency('html/silverlight_test.js', ['goog.html.silverlightTest'], ['goog.html.SafeHtml', 'goog.html.TrustedResourceUrl', 'goog.html.silverlight', 'goog.string.Const', 'goog.testing.jsunit'], false); -goog.addDependency('html/testing.js', ['goog.html.testing'], ['goog.html.SafeHtml', 'goog.html.SafeScript', 'goog.html.SafeStyle', 'goog.html.SafeStyleSheet', 'goog.html.SafeUrl', 'goog.html.TrustedResourceUrl'], false); -goog.addDependency('html/trustedresourceurl.js', ['goog.html.TrustedResourceUrl'], ['goog.asserts', 'goog.i18n.bidi.Dir', 'goog.i18n.bidi.DirectionalString', 'goog.string.Const', 'goog.string.TypedString'], false); -goog.addDependency('html/trustedresourceurl_test.js', ['goog.html.trustedResourceUrlTest'], ['goog.html.TrustedResourceUrl', 'goog.i18n.bidi.Dir', 'goog.string.Const', 'goog.testing.jsunit'], false); -goog.addDependency('html/uncheckedconversions.js', ['goog.html.uncheckedconversions'], ['goog.asserts', 'goog.html.SafeHtml', 'goog.html.SafeScript', 'goog.html.SafeStyle', 'goog.html.SafeStyleSheet', 'goog.html.SafeUrl', 'goog.html.TrustedResourceUrl', 'goog.string', 'goog.string.Const'], false); -goog.addDependency('html/uncheckedconversions_test.js', ['goog.html.uncheckedconversionsTest'], ['goog.html.SafeHtml', 'goog.html.SafeScript', 'goog.html.SafeStyle', 'goog.html.SafeStyleSheet', 'goog.html.SafeUrl', 'goog.html.TrustedResourceUrl', 'goog.html.uncheckedconversions', 'goog.i18n.bidi.Dir', 'goog.string.Const', 'goog.testing.jsunit'], false); -goog.addDependency('html/utils.js', ['goog.html.utils'], ['goog.string'], false); -goog.addDependency('html/utils_test.js', ['goog.html.UtilsTest'], ['goog.array', 'goog.dom.TagName', 'goog.html.utils', 'goog.object', 'goog.testing.jsunit'], false); -goog.addDependency('i18n/bidi.js', ['goog.i18n.bidi', 'goog.i18n.bidi.Dir', 'goog.i18n.bidi.DirectionalString', 'goog.i18n.bidi.Format'], [], false); -goog.addDependency('i18n/bidi_test.js', ['goog.i18n.bidiTest'], ['goog.i18n.bidi', 'goog.i18n.bidi.Dir', 'goog.testing.jsunit'], false); -goog.addDependency('i18n/bidiformatter.js', ['goog.i18n.BidiFormatter'], ['goog.html.SafeHtml', 'goog.html.legacyconversions', 'goog.i18n.bidi', 'goog.i18n.bidi.Dir', 'goog.i18n.bidi.Format'], false); -goog.addDependency('i18n/bidiformatter_test.js', ['goog.i18n.BidiFormatterTest'], ['goog.html.SafeHtml', 'goog.i18n.BidiFormatter', 'goog.i18n.bidi.Dir', 'goog.i18n.bidi.Format', 'goog.testing.jsunit'], false); -goog.addDependency('i18n/charlistdecompressor.js', ['goog.i18n.CharListDecompressor'], ['goog.array', 'goog.i18n.uChar'], false); -goog.addDependency('i18n/charlistdecompressor_test.js', ['goog.i18n.CharListDecompressorTest'], ['goog.i18n.CharListDecompressor', 'goog.testing.jsunit'], false); -goog.addDependency('i18n/charpickerdata.js', ['goog.i18n.CharPickerData'], [], false); -goog.addDependency('i18n/collation.js', ['goog.i18n.collation'], [], false); -goog.addDependency('i18n/collation_test.js', ['goog.i18n.collationTest'], ['goog.i18n.collation', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('i18n/compactnumberformatsymbols.js', ['goog.i18n.CompactNumberFormatSymbols', 'goog.i18n.CompactNumberFormatSymbols_af', 'goog.i18n.CompactNumberFormatSymbols_af_ZA', 'goog.i18n.CompactNumberFormatSymbols_am', 'goog.i18n.CompactNumberFormatSymbols_am_ET', 'goog.i18n.CompactNumberFormatSymbols_ar', 'goog.i18n.CompactNumberFormatSymbols_ar_001', 'goog.i18n.CompactNumberFormatSymbols_az', 'goog.i18n.CompactNumberFormatSymbols_az_Latn_AZ', 'goog.i18n.CompactNumberFormatSymbols_bg', 'goog.i18n.CompactNumberFormatSymbols_bg_BG', 'goog.i18n.CompactNumberFormatSymbols_bn', 'goog.i18n.CompactNumberFormatSymbols_bn_BD', 'goog.i18n.CompactNumberFormatSymbols_br', 'goog.i18n.CompactNumberFormatSymbols_br_FR', 'goog.i18n.CompactNumberFormatSymbols_ca', 'goog.i18n.CompactNumberFormatSymbols_ca_AD', 'goog.i18n.CompactNumberFormatSymbols_ca_ES', 'goog.i18n.CompactNumberFormatSymbols_ca_ES_VALENCIA', 'goog.i18n.CompactNumberFormatSymbols_ca_FR', 'goog.i18n.CompactNumberFormatSymbols_ca_IT', 'goog.i18n.CompactNumberFormatSymbols_chr', 'goog.i18n.CompactNumberFormatSymbols_chr_US', 'goog.i18n.CompactNumberFormatSymbols_cs', 'goog.i18n.CompactNumberFormatSymbols_cs_CZ', 'goog.i18n.CompactNumberFormatSymbols_cy', 'goog.i18n.CompactNumberFormatSymbols_cy_GB', 'goog.i18n.CompactNumberFormatSymbols_da', 'goog.i18n.CompactNumberFormatSymbols_da_DK', 'goog.i18n.CompactNumberFormatSymbols_da_GL', 'goog.i18n.CompactNumberFormatSymbols_de', 'goog.i18n.CompactNumberFormatSymbols_de_AT', 'goog.i18n.CompactNumberFormatSymbols_de_BE', 'goog.i18n.CompactNumberFormatSymbols_de_CH', 'goog.i18n.CompactNumberFormatSymbols_de_DE', 'goog.i18n.CompactNumberFormatSymbols_de_LU', 'goog.i18n.CompactNumberFormatSymbols_el', 'goog.i18n.CompactNumberFormatSymbols_el_GR', 'goog.i18n.CompactNumberFormatSymbols_en', 'goog.i18n.CompactNumberFormatSymbols_en_001', 'goog.i18n.CompactNumberFormatSymbols_en_AS', 'goog.i18n.CompactNumberFormatSymbols_en_AU', 'goog.i18n.CompactNumberFormatSymbols_en_DG', 'goog.i18n.CompactNumberFormatSymbols_en_FM', 'goog.i18n.CompactNumberFormatSymbols_en_GB', 'goog.i18n.CompactNumberFormatSymbols_en_GU', 'goog.i18n.CompactNumberFormatSymbols_en_IE', 'goog.i18n.CompactNumberFormatSymbols_en_IN', 'goog.i18n.CompactNumberFormatSymbols_en_IO', 'goog.i18n.CompactNumberFormatSymbols_en_MH', 'goog.i18n.CompactNumberFormatSymbols_en_MP', 'goog.i18n.CompactNumberFormatSymbols_en_PR', 'goog.i18n.CompactNumberFormatSymbols_en_PW', 'goog.i18n.CompactNumberFormatSymbols_en_SG', 'goog.i18n.CompactNumberFormatSymbols_en_TC', 'goog.i18n.CompactNumberFormatSymbols_en_UM', 'goog.i18n.CompactNumberFormatSymbols_en_US', 'goog.i18n.CompactNumberFormatSymbols_en_VG', 'goog.i18n.CompactNumberFormatSymbols_en_VI', 'goog.i18n.CompactNumberFormatSymbols_en_ZA', 'goog.i18n.CompactNumberFormatSymbols_en_ZW', 'goog.i18n.CompactNumberFormatSymbols_es', 'goog.i18n.CompactNumberFormatSymbols_es_419', 'goog.i18n.CompactNumberFormatSymbols_es_EA', 'goog.i18n.CompactNumberFormatSymbols_es_ES', 'goog.i18n.CompactNumberFormatSymbols_es_IC', 'goog.i18n.CompactNumberFormatSymbols_et', 'goog.i18n.CompactNumberFormatSymbols_et_EE', 'goog.i18n.CompactNumberFormatSymbols_eu', 'goog.i18n.CompactNumberFormatSymbols_eu_ES', 'goog.i18n.CompactNumberFormatSymbols_fa', 'goog.i18n.CompactNumberFormatSymbols_fa_IR', 'goog.i18n.CompactNumberFormatSymbols_fi', 'goog.i18n.CompactNumberFormatSymbols_fi_FI', 'goog.i18n.CompactNumberFormatSymbols_fil', 'goog.i18n.CompactNumberFormatSymbols_fil_PH', 'goog.i18n.CompactNumberFormatSymbols_fr', 'goog.i18n.CompactNumberFormatSymbols_fr_BL', 'goog.i18n.CompactNumberFormatSymbols_fr_CA', 'goog.i18n.CompactNumberFormatSymbols_fr_FR', 'goog.i18n.CompactNumberFormatSymbols_fr_GF', 'goog.i18n.CompactNumberFormatSymbols_fr_GP', 'goog.i18n.CompactNumberFormatSymbols_fr_MC', 'goog.i18n.CompactNumberFormatSymbols_fr_MF', 'goog.i18n.CompactNumberFormatSymbols_fr_MQ', 'goog.i18n.CompactNumberFormatSymbols_fr_PM', 'goog.i18n.CompactNumberFormatSymbols_fr_RE', 'goog.i18n.CompactNumberFormatSymbols_fr_YT', 'goog.i18n.CompactNumberFormatSymbols_ga', 'goog.i18n.CompactNumberFormatSymbols_ga_IE', 'goog.i18n.CompactNumberFormatSymbols_gl', 'goog.i18n.CompactNumberFormatSymbols_gl_ES', 'goog.i18n.CompactNumberFormatSymbols_gsw', 'goog.i18n.CompactNumberFormatSymbols_gsw_CH', 'goog.i18n.CompactNumberFormatSymbols_gsw_LI', 'goog.i18n.CompactNumberFormatSymbols_gu', 'goog.i18n.CompactNumberFormatSymbols_gu_IN', 'goog.i18n.CompactNumberFormatSymbols_haw', 'goog.i18n.CompactNumberFormatSymbols_haw_US', 'goog.i18n.CompactNumberFormatSymbols_he', 'goog.i18n.CompactNumberFormatSymbols_he_IL', 'goog.i18n.CompactNumberFormatSymbols_hi', 'goog.i18n.CompactNumberFormatSymbols_hi_IN', 'goog.i18n.CompactNumberFormatSymbols_hr', 'goog.i18n.CompactNumberFormatSymbols_hr_HR', 'goog.i18n.CompactNumberFormatSymbols_hu', 'goog.i18n.CompactNumberFormatSymbols_hu_HU', 'goog.i18n.CompactNumberFormatSymbols_hy', 'goog.i18n.CompactNumberFormatSymbols_hy_AM', 'goog.i18n.CompactNumberFormatSymbols_id', 'goog.i18n.CompactNumberFormatSymbols_id_ID', 'goog.i18n.CompactNumberFormatSymbols_in', 'goog.i18n.CompactNumberFormatSymbols_is', 'goog.i18n.CompactNumberFormatSymbols_is_IS', 'goog.i18n.CompactNumberFormatSymbols_it', 'goog.i18n.CompactNumberFormatSymbols_it_IT', 'goog.i18n.CompactNumberFormatSymbols_it_SM', 'goog.i18n.CompactNumberFormatSymbols_iw', 'goog.i18n.CompactNumberFormatSymbols_ja', 'goog.i18n.CompactNumberFormatSymbols_ja_JP', 'goog.i18n.CompactNumberFormatSymbols_ka', 'goog.i18n.CompactNumberFormatSymbols_ka_GE', 'goog.i18n.CompactNumberFormatSymbols_kk', 'goog.i18n.CompactNumberFormatSymbols_kk_Cyrl_KZ', 'goog.i18n.CompactNumberFormatSymbols_km', 'goog.i18n.CompactNumberFormatSymbols_km_KH', 'goog.i18n.CompactNumberFormatSymbols_kn', 'goog.i18n.CompactNumberFormatSymbols_kn_IN', 'goog.i18n.CompactNumberFormatSymbols_ko', 'goog.i18n.CompactNumberFormatSymbols_ko_KR', 'goog.i18n.CompactNumberFormatSymbols_ky', 'goog.i18n.CompactNumberFormatSymbols_ky_Cyrl_KG', 'goog.i18n.CompactNumberFormatSymbols_ln', 'goog.i18n.CompactNumberFormatSymbols_ln_CD', 'goog.i18n.CompactNumberFormatSymbols_lo', 'goog.i18n.CompactNumberFormatSymbols_lo_LA', 'goog.i18n.CompactNumberFormatSymbols_lt', 'goog.i18n.CompactNumberFormatSymbols_lt_LT', 'goog.i18n.CompactNumberFormatSymbols_lv', 'goog.i18n.CompactNumberFormatSymbols_lv_LV', 'goog.i18n.CompactNumberFormatSymbols_mk', 'goog.i18n.CompactNumberFormatSymbols_mk_MK', 'goog.i18n.CompactNumberFormatSymbols_ml', 'goog.i18n.CompactNumberFormatSymbols_ml_IN', 'goog.i18n.CompactNumberFormatSymbols_mn', 'goog.i18n.CompactNumberFormatSymbols_mn_Cyrl_MN', 'goog.i18n.CompactNumberFormatSymbols_mr', 'goog.i18n.CompactNumberFormatSymbols_mr_IN', 'goog.i18n.CompactNumberFormatSymbols_ms', 'goog.i18n.CompactNumberFormatSymbols_ms_Latn_MY', 'goog.i18n.CompactNumberFormatSymbols_mt', 'goog.i18n.CompactNumberFormatSymbols_mt_MT', 'goog.i18n.CompactNumberFormatSymbols_my', 'goog.i18n.CompactNumberFormatSymbols_my_MM', 'goog.i18n.CompactNumberFormatSymbols_nb', 'goog.i18n.CompactNumberFormatSymbols_nb_NO', 'goog.i18n.CompactNumberFormatSymbols_nb_SJ', 'goog.i18n.CompactNumberFormatSymbols_ne', 'goog.i18n.CompactNumberFormatSymbols_ne_NP', 'goog.i18n.CompactNumberFormatSymbols_nl', 'goog.i18n.CompactNumberFormatSymbols_nl_NL', 'goog.i18n.CompactNumberFormatSymbols_no', 'goog.i18n.CompactNumberFormatSymbols_no_NO', 'goog.i18n.CompactNumberFormatSymbols_or', 'goog.i18n.CompactNumberFormatSymbols_or_IN', 'goog.i18n.CompactNumberFormatSymbols_pa', 'goog.i18n.CompactNumberFormatSymbols_pa_Guru_IN', 'goog.i18n.CompactNumberFormatSymbols_pl', 'goog.i18n.CompactNumberFormatSymbols_pl_PL', 'goog.i18n.CompactNumberFormatSymbols_pt', 'goog.i18n.CompactNumberFormatSymbols_pt_BR', 'goog.i18n.CompactNumberFormatSymbols_pt_PT', 'goog.i18n.CompactNumberFormatSymbols_ro', 'goog.i18n.CompactNumberFormatSymbols_ro_RO', 'goog.i18n.CompactNumberFormatSymbols_ru', 'goog.i18n.CompactNumberFormatSymbols_ru_RU', 'goog.i18n.CompactNumberFormatSymbols_si', 'goog.i18n.CompactNumberFormatSymbols_si_LK', 'goog.i18n.CompactNumberFormatSymbols_sk', 'goog.i18n.CompactNumberFormatSymbols_sk_SK', 'goog.i18n.CompactNumberFormatSymbols_sl', 'goog.i18n.CompactNumberFormatSymbols_sl_SI', 'goog.i18n.CompactNumberFormatSymbols_sq', 'goog.i18n.CompactNumberFormatSymbols_sq_AL', 'goog.i18n.CompactNumberFormatSymbols_sr', 'goog.i18n.CompactNumberFormatSymbols_sr_Cyrl_RS', 'goog.i18n.CompactNumberFormatSymbols_sv', 'goog.i18n.CompactNumberFormatSymbols_sv_SE', 'goog.i18n.CompactNumberFormatSymbols_sw', 'goog.i18n.CompactNumberFormatSymbols_sw_TZ', 'goog.i18n.CompactNumberFormatSymbols_ta', 'goog.i18n.CompactNumberFormatSymbols_ta_IN', 'goog.i18n.CompactNumberFormatSymbols_te', 'goog.i18n.CompactNumberFormatSymbols_te_IN', 'goog.i18n.CompactNumberFormatSymbols_th', 'goog.i18n.CompactNumberFormatSymbols_th_TH', 'goog.i18n.CompactNumberFormatSymbols_tl', 'goog.i18n.CompactNumberFormatSymbols_tr', 'goog.i18n.CompactNumberFormatSymbols_tr_TR', 'goog.i18n.CompactNumberFormatSymbols_uk', 'goog.i18n.CompactNumberFormatSymbols_uk_UA', 'goog.i18n.CompactNumberFormatSymbols_ur', 'goog.i18n.CompactNumberFormatSymbols_ur_PK', 'goog.i18n.CompactNumberFormatSymbols_uz', 'goog.i18n.CompactNumberFormatSymbols_uz_Latn_UZ', 'goog.i18n.CompactNumberFormatSymbols_vi', 'goog.i18n.CompactNumberFormatSymbols_vi_VN', 'goog.i18n.CompactNumberFormatSymbols_zh', 'goog.i18n.CompactNumberFormatSymbols_zh_CN', 'goog.i18n.CompactNumberFormatSymbols_zh_HK', 'goog.i18n.CompactNumberFormatSymbols_zh_Hans_CN', 'goog.i18n.CompactNumberFormatSymbols_zh_TW', 'goog.i18n.CompactNumberFormatSymbols_zu', 'goog.i18n.CompactNumberFormatSymbols_zu_ZA'], [], false); -goog.addDependency('i18n/compactnumberformatsymbols_ext.js', ['goog.i18n.CompactNumberFormatSymbolsExt', 'goog.i18n.CompactNumberFormatSymbols_aa', 'goog.i18n.CompactNumberFormatSymbols_aa_DJ', 'goog.i18n.CompactNumberFormatSymbols_aa_ER', 'goog.i18n.CompactNumberFormatSymbols_aa_ET', 'goog.i18n.CompactNumberFormatSymbols_af_NA', 'goog.i18n.CompactNumberFormatSymbols_agq', 'goog.i18n.CompactNumberFormatSymbols_agq_CM', 'goog.i18n.CompactNumberFormatSymbols_ak', 'goog.i18n.CompactNumberFormatSymbols_ak_GH', 'goog.i18n.CompactNumberFormatSymbols_ar_AE', 'goog.i18n.CompactNumberFormatSymbols_ar_BH', 'goog.i18n.CompactNumberFormatSymbols_ar_DJ', 'goog.i18n.CompactNumberFormatSymbols_ar_DZ', 'goog.i18n.CompactNumberFormatSymbols_ar_EG', 'goog.i18n.CompactNumberFormatSymbols_ar_EH', 'goog.i18n.CompactNumberFormatSymbols_ar_ER', 'goog.i18n.CompactNumberFormatSymbols_ar_IL', 'goog.i18n.CompactNumberFormatSymbols_ar_IQ', 'goog.i18n.CompactNumberFormatSymbols_ar_JO', 'goog.i18n.CompactNumberFormatSymbols_ar_KM', 'goog.i18n.CompactNumberFormatSymbols_ar_KW', 'goog.i18n.CompactNumberFormatSymbols_ar_LB', 'goog.i18n.CompactNumberFormatSymbols_ar_LY', 'goog.i18n.CompactNumberFormatSymbols_ar_MA', 'goog.i18n.CompactNumberFormatSymbols_ar_MR', 'goog.i18n.CompactNumberFormatSymbols_ar_OM', 'goog.i18n.CompactNumberFormatSymbols_ar_PS', 'goog.i18n.CompactNumberFormatSymbols_ar_QA', 'goog.i18n.CompactNumberFormatSymbols_ar_SA', 'goog.i18n.CompactNumberFormatSymbols_ar_SD', 'goog.i18n.CompactNumberFormatSymbols_ar_SO', 'goog.i18n.CompactNumberFormatSymbols_ar_SS', 'goog.i18n.CompactNumberFormatSymbols_ar_SY', 'goog.i18n.CompactNumberFormatSymbols_ar_TD', 'goog.i18n.CompactNumberFormatSymbols_ar_TN', 'goog.i18n.CompactNumberFormatSymbols_ar_YE', 'goog.i18n.CompactNumberFormatSymbols_as', 'goog.i18n.CompactNumberFormatSymbols_as_IN', 'goog.i18n.CompactNumberFormatSymbols_asa', 'goog.i18n.CompactNumberFormatSymbols_asa_TZ', 'goog.i18n.CompactNumberFormatSymbols_ast', 'goog.i18n.CompactNumberFormatSymbols_ast_ES', 'goog.i18n.CompactNumberFormatSymbols_az_Cyrl', 'goog.i18n.CompactNumberFormatSymbols_az_Cyrl_AZ', 'goog.i18n.CompactNumberFormatSymbols_az_Latn', 'goog.i18n.CompactNumberFormatSymbols_bas', 'goog.i18n.CompactNumberFormatSymbols_bas_CM', 'goog.i18n.CompactNumberFormatSymbols_be', 'goog.i18n.CompactNumberFormatSymbols_be_BY', 'goog.i18n.CompactNumberFormatSymbols_bem', 'goog.i18n.CompactNumberFormatSymbols_bem_ZM', 'goog.i18n.CompactNumberFormatSymbols_bez', 'goog.i18n.CompactNumberFormatSymbols_bez_TZ', 'goog.i18n.CompactNumberFormatSymbols_bm', 'goog.i18n.CompactNumberFormatSymbols_bm_Latn', 'goog.i18n.CompactNumberFormatSymbols_bm_Latn_ML', 'goog.i18n.CompactNumberFormatSymbols_bn_IN', 'goog.i18n.CompactNumberFormatSymbols_bo', 'goog.i18n.CompactNumberFormatSymbols_bo_CN', 'goog.i18n.CompactNumberFormatSymbols_bo_IN', 'goog.i18n.CompactNumberFormatSymbols_brx', 'goog.i18n.CompactNumberFormatSymbols_brx_IN', 'goog.i18n.CompactNumberFormatSymbols_bs', 'goog.i18n.CompactNumberFormatSymbols_bs_Cyrl', 'goog.i18n.CompactNumberFormatSymbols_bs_Cyrl_BA', 'goog.i18n.CompactNumberFormatSymbols_bs_Latn', 'goog.i18n.CompactNumberFormatSymbols_bs_Latn_BA', 'goog.i18n.CompactNumberFormatSymbols_cgg', 'goog.i18n.CompactNumberFormatSymbols_cgg_UG', 'goog.i18n.CompactNumberFormatSymbols_ckb', 'goog.i18n.CompactNumberFormatSymbols_ckb_Arab', 'goog.i18n.CompactNumberFormatSymbols_ckb_Arab_IQ', 'goog.i18n.CompactNumberFormatSymbols_ckb_Arab_IR', 'goog.i18n.CompactNumberFormatSymbols_ckb_IQ', 'goog.i18n.CompactNumberFormatSymbols_ckb_IR', 'goog.i18n.CompactNumberFormatSymbols_ckb_Latn', 'goog.i18n.CompactNumberFormatSymbols_ckb_Latn_IQ', 'goog.i18n.CompactNumberFormatSymbols_dav', 'goog.i18n.CompactNumberFormatSymbols_dav_KE', 'goog.i18n.CompactNumberFormatSymbols_de_LI', 'goog.i18n.CompactNumberFormatSymbols_dje', 'goog.i18n.CompactNumberFormatSymbols_dje_NE', 'goog.i18n.CompactNumberFormatSymbols_dsb', 'goog.i18n.CompactNumberFormatSymbols_dsb_DE', 'goog.i18n.CompactNumberFormatSymbols_dua', 'goog.i18n.CompactNumberFormatSymbols_dua_CM', 'goog.i18n.CompactNumberFormatSymbols_dyo', 'goog.i18n.CompactNumberFormatSymbols_dyo_SN', 'goog.i18n.CompactNumberFormatSymbols_dz', 'goog.i18n.CompactNumberFormatSymbols_dz_BT', 'goog.i18n.CompactNumberFormatSymbols_ebu', 'goog.i18n.CompactNumberFormatSymbols_ebu_KE', 'goog.i18n.CompactNumberFormatSymbols_ee', 'goog.i18n.CompactNumberFormatSymbols_ee_GH', 'goog.i18n.CompactNumberFormatSymbols_ee_TG', 'goog.i18n.CompactNumberFormatSymbols_el_CY', 'goog.i18n.CompactNumberFormatSymbols_en_150', 'goog.i18n.CompactNumberFormatSymbols_en_AG', 'goog.i18n.CompactNumberFormatSymbols_en_AI', 'goog.i18n.CompactNumberFormatSymbols_en_BB', 'goog.i18n.CompactNumberFormatSymbols_en_BE', 'goog.i18n.CompactNumberFormatSymbols_en_BM', 'goog.i18n.CompactNumberFormatSymbols_en_BS', 'goog.i18n.CompactNumberFormatSymbols_en_BW', 'goog.i18n.CompactNumberFormatSymbols_en_BZ', 'goog.i18n.CompactNumberFormatSymbols_en_CA', 'goog.i18n.CompactNumberFormatSymbols_en_CC', 'goog.i18n.CompactNumberFormatSymbols_en_CK', 'goog.i18n.CompactNumberFormatSymbols_en_CM', 'goog.i18n.CompactNumberFormatSymbols_en_CX', 'goog.i18n.CompactNumberFormatSymbols_en_DM', 'goog.i18n.CompactNumberFormatSymbols_en_ER', 'goog.i18n.CompactNumberFormatSymbols_en_FJ', 'goog.i18n.CompactNumberFormatSymbols_en_FK', 'goog.i18n.CompactNumberFormatSymbols_en_GD', 'goog.i18n.CompactNumberFormatSymbols_en_GG', 'goog.i18n.CompactNumberFormatSymbols_en_GH', 'goog.i18n.CompactNumberFormatSymbols_en_GI', 'goog.i18n.CompactNumberFormatSymbols_en_GM', 'goog.i18n.CompactNumberFormatSymbols_en_GY', 'goog.i18n.CompactNumberFormatSymbols_en_HK', 'goog.i18n.CompactNumberFormatSymbols_en_IM', 'goog.i18n.CompactNumberFormatSymbols_en_JE', 'goog.i18n.CompactNumberFormatSymbols_en_JM', 'goog.i18n.CompactNumberFormatSymbols_en_KE', 'goog.i18n.CompactNumberFormatSymbols_en_KI', 'goog.i18n.CompactNumberFormatSymbols_en_KN', 'goog.i18n.CompactNumberFormatSymbols_en_KY', 'goog.i18n.CompactNumberFormatSymbols_en_LC', 'goog.i18n.CompactNumberFormatSymbols_en_LR', 'goog.i18n.CompactNumberFormatSymbols_en_LS', 'goog.i18n.CompactNumberFormatSymbols_en_MG', 'goog.i18n.CompactNumberFormatSymbols_en_MO', 'goog.i18n.CompactNumberFormatSymbols_en_MS', 'goog.i18n.CompactNumberFormatSymbols_en_MT', 'goog.i18n.CompactNumberFormatSymbols_en_MU', 'goog.i18n.CompactNumberFormatSymbols_en_MW', 'goog.i18n.CompactNumberFormatSymbols_en_MY', 'goog.i18n.CompactNumberFormatSymbols_en_NA', 'goog.i18n.CompactNumberFormatSymbols_en_NF', 'goog.i18n.CompactNumberFormatSymbols_en_NG', 'goog.i18n.CompactNumberFormatSymbols_en_NR', 'goog.i18n.CompactNumberFormatSymbols_en_NU', 'goog.i18n.CompactNumberFormatSymbols_en_NZ', 'goog.i18n.CompactNumberFormatSymbols_en_PG', 'goog.i18n.CompactNumberFormatSymbols_en_PH', 'goog.i18n.CompactNumberFormatSymbols_en_PK', 'goog.i18n.CompactNumberFormatSymbols_en_PN', 'goog.i18n.CompactNumberFormatSymbols_en_RW', 'goog.i18n.CompactNumberFormatSymbols_en_SB', 'goog.i18n.CompactNumberFormatSymbols_en_SC', 'goog.i18n.CompactNumberFormatSymbols_en_SD', 'goog.i18n.CompactNumberFormatSymbols_en_SH', 'goog.i18n.CompactNumberFormatSymbols_en_SL', 'goog.i18n.CompactNumberFormatSymbols_en_SS', 'goog.i18n.CompactNumberFormatSymbols_en_SX', 'goog.i18n.CompactNumberFormatSymbols_en_SZ', 'goog.i18n.CompactNumberFormatSymbols_en_TK', 'goog.i18n.CompactNumberFormatSymbols_en_TO', 'goog.i18n.CompactNumberFormatSymbols_en_TT', 'goog.i18n.CompactNumberFormatSymbols_en_TV', 'goog.i18n.CompactNumberFormatSymbols_en_TZ', 'goog.i18n.CompactNumberFormatSymbols_en_UG', 'goog.i18n.CompactNumberFormatSymbols_en_VC', 'goog.i18n.CompactNumberFormatSymbols_en_VU', 'goog.i18n.CompactNumberFormatSymbols_en_WS', 'goog.i18n.CompactNumberFormatSymbols_en_ZM', 'goog.i18n.CompactNumberFormatSymbols_eo', 'goog.i18n.CompactNumberFormatSymbols_eo_001', 'goog.i18n.CompactNumberFormatSymbols_es_AR', 'goog.i18n.CompactNumberFormatSymbols_es_BO', 'goog.i18n.CompactNumberFormatSymbols_es_CL', 'goog.i18n.CompactNumberFormatSymbols_es_CO', 'goog.i18n.CompactNumberFormatSymbols_es_CR', 'goog.i18n.CompactNumberFormatSymbols_es_CU', 'goog.i18n.CompactNumberFormatSymbols_es_DO', 'goog.i18n.CompactNumberFormatSymbols_es_EC', 'goog.i18n.CompactNumberFormatSymbols_es_GQ', 'goog.i18n.CompactNumberFormatSymbols_es_GT', 'goog.i18n.CompactNumberFormatSymbols_es_HN', 'goog.i18n.CompactNumberFormatSymbols_es_MX', 'goog.i18n.CompactNumberFormatSymbols_es_NI', 'goog.i18n.CompactNumberFormatSymbols_es_PA', 'goog.i18n.CompactNumberFormatSymbols_es_PE', 'goog.i18n.CompactNumberFormatSymbols_es_PH', 'goog.i18n.CompactNumberFormatSymbols_es_PR', 'goog.i18n.CompactNumberFormatSymbols_es_PY', 'goog.i18n.CompactNumberFormatSymbols_es_SV', 'goog.i18n.CompactNumberFormatSymbols_es_US', 'goog.i18n.CompactNumberFormatSymbols_es_UY', 'goog.i18n.CompactNumberFormatSymbols_es_VE', 'goog.i18n.CompactNumberFormatSymbols_ewo', 'goog.i18n.CompactNumberFormatSymbols_ewo_CM', 'goog.i18n.CompactNumberFormatSymbols_fa_AF', 'goog.i18n.CompactNumberFormatSymbols_ff', 'goog.i18n.CompactNumberFormatSymbols_ff_CM', 'goog.i18n.CompactNumberFormatSymbols_ff_GN', 'goog.i18n.CompactNumberFormatSymbols_ff_MR', 'goog.i18n.CompactNumberFormatSymbols_ff_SN', 'goog.i18n.CompactNumberFormatSymbols_fo', 'goog.i18n.CompactNumberFormatSymbols_fo_FO', 'goog.i18n.CompactNumberFormatSymbols_fr_BE', 'goog.i18n.CompactNumberFormatSymbols_fr_BF', 'goog.i18n.CompactNumberFormatSymbols_fr_BI', 'goog.i18n.CompactNumberFormatSymbols_fr_BJ', 'goog.i18n.CompactNumberFormatSymbols_fr_CD', 'goog.i18n.CompactNumberFormatSymbols_fr_CF', 'goog.i18n.CompactNumberFormatSymbols_fr_CG', 'goog.i18n.CompactNumberFormatSymbols_fr_CH', 'goog.i18n.CompactNumberFormatSymbols_fr_CI', 'goog.i18n.CompactNumberFormatSymbols_fr_CM', 'goog.i18n.CompactNumberFormatSymbols_fr_DJ', 'goog.i18n.CompactNumberFormatSymbols_fr_DZ', 'goog.i18n.CompactNumberFormatSymbols_fr_GA', 'goog.i18n.CompactNumberFormatSymbols_fr_GN', 'goog.i18n.CompactNumberFormatSymbols_fr_GQ', 'goog.i18n.CompactNumberFormatSymbols_fr_HT', 'goog.i18n.CompactNumberFormatSymbols_fr_KM', 'goog.i18n.CompactNumberFormatSymbols_fr_LU', 'goog.i18n.CompactNumberFormatSymbols_fr_MA', 'goog.i18n.CompactNumberFormatSymbols_fr_MG', 'goog.i18n.CompactNumberFormatSymbols_fr_ML', 'goog.i18n.CompactNumberFormatSymbols_fr_MR', 'goog.i18n.CompactNumberFormatSymbols_fr_MU', 'goog.i18n.CompactNumberFormatSymbols_fr_NC', 'goog.i18n.CompactNumberFormatSymbols_fr_NE', 'goog.i18n.CompactNumberFormatSymbols_fr_PF', 'goog.i18n.CompactNumberFormatSymbols_fr_RW', 'goog.i18n.CompactNumberFormatSymbols_fr_SC', 'goog.i18n.CompactNumberFormatSymbols_fr_SN', 'goog.i18n.CompactNumberFormatSymbols_fr_SY', 'goog.i18n.CompactNumberFormatSymbols_fr_TD', 'goog.i18n.CompactNumberFormatSymbols_fr_TG', 'goog.i18n.CompactNumberFormatSymbols_fr_TN', 'goog.i18n.CompactNumberFormatSymbols_fr_VU', 'goog.i18n.CompactNumberFormatSymbols_fr_WF', 'goog.i18n.CompactNumberFormatSymbols_fur', 'goog.i18n.CompactNumberFormatSymbols_fur_IT', 'goog.i18n.CompactNumberFormatSymbols_fy', 'goog.i18n.CompactNumberFormatSymbols_fy_NL', 'goog.i18n.CompactNumberFormatSymbols_gd', 'goog.i18n.CompactNumberFormatSymbols_gd_GB', 'goog.i18n.CompactNumberFormatSymbols_gsw_FR', 'goog.i18n.CompactNumberFormatSymbols_guz', 'goog.i18n.CompactNumberFormatSymbols_guz_KE', 'goog.i18n.CompactNumberFormatSymbols_gv', 'goog.i18n.CompactNumberFormatSymbols_gv_IM', 'goog.i18n.CompactNumberFormatSymbols_ha', 'goog.i18n.CompactNumberFormatSymbols_ha_Latn', 'goog.i18n.CompactNumberFormatSymbols_ha_Latn_GH', 'goog.i18n.CompactNumberFormatSymbols_ha_Latn_NE', 'goog.i18n.CompactNumberFormatSymbols_ha_Latn_NG', 'goog.i18n.CompactNumberFormatSymbols_hr_BA', 'goog.i18n.CompactNumberFormatSymbols_hsb', 'goog.i18n.CompactNumberFormatSymbols_hsb_DE', 'goog.i18n.CompactNumberFormatSymbols_ia', 'goog.i18n.CompactNumberFormatSymbols_ia_FR', 'goog.i18n.CompactNumberFormatSymbols_ig', 'goog.i18n.CompactNumberFormatSymbols_ig_NG', 'goog.i18n.CompactNumberFormatSymbols_ii', 'goog.i18n.CompactNumberFormatSymbols_ii_CN', 'goog.i18n.CompactNumberFormatSymbols_it_CH', 'goog.i18n.CompactNumberFormatSymbols_jgo', 'goog.i18n.CompactNumberFormatSymbols_jgo_CM', 'goog.i18n.CompactNumberFormatSymbols_jmc', 'goog.i18n.CompactNumberFormatSymbols_jmc_TZ', 'goog.i18n.CompactNumberFormatSymbols_kab', 'goog.i18n.CompactNumberFormatSymbols_kab_DZ', 'goog.i18n.CompactNumberFormatSymbols_kam', 'goog.i18n.CompactNumberFormatSymbols_kam_KE', 'goog.i18n.CompactNumberFormatSymbols_kde', 'goog.i18n.CompactNumberFormatSymbols_kde_TZ', 'goog.i18n.CompactNumberFormatSymbols_kea', 'goog.i18n.CompactNumberFormatSymbols_kea_CV', 'goog.i18n.CompactNumberFormatSymbols_khq', 'goog.i18n.CompactNumberFormatSymbols_khq_ML', 'goog.i18n.CompactNumberFormatSymbols_ki', 'goog.i18n.CompactNumberFormatSymbols_ki_KE', 'goog.i18n.CompactNumberFormatSymbols_kk_Cyrl', 'goog.i18n.CompactNumberFormatSymbols_kkj', 'goog.i18n.CompactNumberFormatSymbols_kkj_CM', 'goog.i18n.CompactNumberFormatSymbols_kl', 'goog.i18n.CompactNumberFormatSymbols_kl_GL', 'goog.i18n.CompactNumberFormatSymbols_kln', 'goog.i18n.CompactNumberFormatSymbols_kln_KE', 'goog.i18n.CompactNumberFormatSymbols_ko_KP', 'goog.i18n.CompactNumberFormatSymbols_kok', 'goog.i18n.CompactNumberFormatSymbols_kok_IN', 'goog.i18n.CompactNumberFormatSymbols_ks', 'goog.i18n.CompactNumberFormatSymbols_ks_Arab', 'goog.i18n.CompactNumberFormatSymbols_ks_Arab_IN', 'goog.i18n.CompactNumberFormatSymbols_ksb', 'goog.i18n.CompactNumberFormatSymbols_ksb_TZ', 'goog.i18n.CompactNumberFormatSymbols_ksf', 'goog.i18n.CompactNumberFormatSymbols_ksf_CM', 'goog.i18n.CompactNumberFormatSymbols_ksh', 'goog.i18n.CompactNumberFormatSymbols_ksh_DE', 'goog.i18n.CompactNumberFormatSymbols_kw', 'goog.i18n.CompactNumberFormatSymbols_kw_GB', 'goog.i18n.CompactNumberFormatSymbols_ky_Cyrl', 'goog.i18n.CompactNumberFormatSymbols_lag', 'goog.i18n.CompactNumberFormatSymbols_lag_TZ', 'goog.i18n.CompactNumberFormatSymbols_lb', 'goog.i18n.CompactNumberFormatSymbols_lb_LU', 'goog.i18n.CompactNumberFormatSymbols_lg', 'goog.i18n.CompactNumberFormatSymbols_lg_UG', 'goog.i18n.CompactNumberFormatSymbols_lkt', 'goog.i18n.CompactNumberFormatSymbols_lkt_US', 'goog.i18n.CompactNumberFormatSymbols_ln_AO', 'goog.i18n.CompactNumberFormatSymbols_ln_CF', 'goog.i18n.CompactNumberFormatSymbols_ln_CG', 'goog.i18n.CompactNumberFormatSymbols_lu', 'goog.i18n.CompactNumberFormatSymbols_lu_CD', 'goog.i18n.CompactNumberFormatSymbols_luo', 'goog.i18n.CompactNumberFormatSymbols_luo_KE', 'goog.i18n.CompactNumberFormatSymbols_luy', 'goog.i18n.CompactNumberFormatSymbols_luy_KE', 'goog.i18n.CompactNumberFormatSymbols_mas', 'goog.i18n.CompactNumberFormatSymbols_mas_KE', 'goog.i18n.CompactNumberFormatSymbols_mas_TZ', 'goog.i18n.CompactNumberFormatSymbols_mer', 'goog.i18n.CompactNumberFormatSymbols_mer_KE', 'goog.i18n.CompactNumberFormatSymbols_mfe', 'goog.i18n.CompactNumberFormatSymbols_mfe_MU', 'goog.i18n.CompactNumberFormatSymbols_mg', 'goog.i18n.CompactNumberFormatSymbols_mg_MG', 'goog.i18n.CompactNumberFormatSymbols_mgh', 'goog.i18n.CompactNumberFormatSymbols_mgh_MZ', 'goog.i18n.CompactNumberFormatSymbols_mgo', 'goog.i18n.CompactNumberFormatSymbols_mgo_CM', 'goog.i18n.CompactNumberFormatSymbols_mn_Cyrl', 'goog.i18n.CompactNumberFormatSymbols_ms_Latn', 'goog.i18n.CompactNumberFormatSymbols_ms_Latn_BN', 'goog.i18n.CompactNumberFormatSymbols_ms_Latn_SG', 'goog.i18n.CompactNumberFormatSymbols_mua', 'goog.i18n.CompactNumberFormatSymbols_mua_CM', 'goog.i18n.CompactNumberFormatSymbols_naq', 'goog.i18n.CompactNumberFormatSymbols_naq_NA', 'goog.i18n.CompactNumberFormatSymbols_nd', 'goog.i18n.CompactNumberFormatSymbols_nd_ZW', 'goog.i18n.CompactNumberFormatSymbols_ne_IN', 'goog.i18n.CompactNumberFormatSymbols_nl_AW', 'goog.i18n.CompactNumberFormatSymbols_nl_BE', 'goog.i18n.CompactNumberFormatSymbols_nl_BQ', 'goog.i18n.CompactNumberFormatSymbols_nl_CW', 'goog.i18n.CompactNumberFormatSymbols_nl_SR', 'goog.i18n.CompactNumberFormatSymbols_nl_SX', 'goog.i18n.CompactNumberFormatSymbols_nmg', 'goog.i18n.CompactNumberFormatSymbols_nmg_CM', 'goog.i18n.CompactNumberFormatSymbols_nn', 'goog.i18n.CompactNumberFormatSymbols_nn_NO', 'goog.i18n.CompactNumberFormatSymbols_nnh', 'goog.i18n.CompactNumberFormatSymbols_nnh_CM', 'goog.i18n.CompactNumberFormatSymbols_nr', 'goog.i18n.CompactNumberFormatSymbols_nr_ZA', 'goog.i18n.CompactNumberFormatSymbols_nso', 'goog.i18n.CompactNumberFormatSymbols_nso_ZA', 'goog.i18n.CompactNumberFormatSymbols_nus', 'goog.i18n.CompactNumberFormatSymbols_nus_SD', 'goog.i18n.CompactNumberFormatSymbols_nyn', 'goog.i18n.CompactNumberFormatSymbols_nyn_UG', 'goog.i18n.CompactNumberFormatSymbols_om', 'goog.i18n.CompactNumberFormatSymbols_om_ET', 'goog.i18n.CompactNumberFormatSymbols_om_KE', 'goog.i18n.CompactNumberFormatSymbols_os', 'goog.i18n.CompactNumberFormatSymbols_os_GE', 'goog.i18n.CompactNumberFormatSymbols_os_RU', 'goog.i18n.CompactNumberFormatSymbols_pa_Arab', 'goog.i18n.CompactNumberFormatSymbols_pa_Arab_PK', 'goog.i18n.CompactNumberFormatSymbols_pa_Guru', 'goog.i18n.CompactNumberFormatSymbols_ps', 'goog.i18n.CompactNumberFormatSymbols_ps_AF', 'goog.i18n.CompactNumberFormatSymbols_pt_AO', 'goog.i18n.CompactNumberFormatSymbols_pt_CV', 'goog.i18n.CompactNumberFormatSymbols_pt_GW', 'goog.i18n.CompactNumberFormatSymbols_pt_MO', 'goog.i18n.CompactNumberFormatSymbols_pt_MZ', 'goog.i18n.CompactNumberFormatSymbols_pt_ST', 'goog.i18n.CompactNumberFormatSymbols_pt_TL', 'goog.i18n.CompactNumberFormatSymbols_qu', 'goog.i18n.CompactNumberFormatSymbols_qu_BO', 'goog.i18n.CompactNumberFormatSymbols_qu_EC', 'goog.i18n.CompactNumberFormatSymbols_qu_PE', 'goog.i18n.CompactNumberFormatSymbols_rm', 'goog.i18n.CompactNumberFormatSymbols_rm_CH', 'goog.i18n.CompactNumberFormatSymbols_rn', 'goog.i18n.CompactNumberFormatSymbols_rn_BI', 'goog.i18n.CompactNumberFormatSymbols_ro_MD', 'goog.i18n.CompactNumberFormatSymbols_rof', 'goog.i18n.CompactNumberFormatSymbols_rof_TZ', 'goog.i18n.CompactNumberFormatSymbols_ru_BY', 'goog.i18n.CompactNumberFormatSymbols_ru_KG', 'goog.i18n.CompactNumberFormatSymbols_ru_KZ', 'goog.i18n.CompactNumberFormatSymbols_ru_MD', 'goog.i18n.CompactNumberFormatSymbols_ru_UA', 'goog.i18n.CompactNumberFormatSymbols_rw', 'goog.i18n.CompactNumberFormatSymbols_rw_RW', 'goog.i18n.CompactNumberFormatSymbols_rwk', 'goog.i18n.CompactNumberFormatSymbols_rwk_TZ', 'goog.i18n.CompactNumberFormatSymbols_sah', 'goog.i18n.CompactNumberFormatSymbols_sah_RU', 'goog.i18n.CompactNumberFormatSymbols_saq', 'goog.i18n.CompactNumberFormatSymbols_saq_KE', 'goog.i18n.CompactNumberFormatSymbols_sbp', 'goog.i18n.CompactNumberFormatSymbols_sbp_TZ', 'goog.i18n.CompactNumberFormatSymbols_se', 'goog.i18n.CompactNumberFormatSymbols_se_FI', 'goog.i18n.CompactNumberFormatSymbols_se_NO', 'goog.i18n.CompactNumberFormatSymbols_se_SE', 'goog.i18n.CompactNumberFormatSymbols_seh', 'goog.i18n.CompactNumberFormatSymbols_seh_MZ', 'goog.i18n.CompactNumberFormatSymbols_ses', 'goog.i18n.CompactNumberFormatSymbols_ses_ML', 'goog.i18n.CompactNumberFormatSymbols_sg', 'goog.i18n.CompactNumberFormatSymbols_sg_CF', 'goog.i18n.CompactNumberFormatSymbols_shi', 'goog.i18n.CompactNumberFormatSymbols_shi_Latn', 'goog.i18n.CompactNumberFormatSymbols_shi_Latn_MA', 'goog.i18n.CompactNumberFormatSymbols_shi_Tfng', 'goog.i18n.CompactNumberFormatSymbols_shi_Tfng_MA', 'goog.i18n.CompactNumberFormatSymbols_smn', 'goog.i18n.CompactNumberFormatSymbols_smn_FI', 'goog.i18n.CompactNumberFormatSymbols_sn', 'goog.i18n.CompactNumberFormatSymbols_sn_ZW', 'goog.i18n.CompactNumberFormatSymbols_so', 'goog.i18n.CompactNumberFormatSymbols_so_DJ', 'goog.i18n.CompactNumberFormatSymbols_so_ET', 'goog.i18n.CompactNumberFormatSymbols_so_KE', 'goog.i18n.CompactNumberFormatSymbols_so_SO', 'goog.i18n.CompactNumberFormatSymbols_sq_MK', 'goog.i18n.CompactNumberFormatSymbols_sq_XK', 'goog.i18n.CompactNumberFormatSymbols_sr_Cyrl', 'goog.i18n.CompactNumberFormatSymbols_sr_Cyrl_BA', 'goog.i18n.CompactNumberFormatSymbols_sr_Cyrl_ME', 'goog.i18n.CompactNumberFormatSymbols_sr_Cyrl_XK', 'goog.i18n.CompactNumberFormatSymbols_sr_Latn', 'goog.i18n.CompactNumberFormatSymbols_sr_Latn_BA', 'goog.i18n.CompactNumberFormatSymbols_sr_Latn_ME', 'goog.i18n.CompactNumberFormatSymbols_sr_Latn_RS', 'goog.i18n.CompactNumberFormatSymbols_sr_Latn_XK', 'goog.i18n.CompactNumberFormatSymbols_ss', 'goog.i18n.CompactNumberFormatSymbols_ss_SZ', 'goog.i18n.CompactNumberFormatSymbols_ss_ZA', 'goog.i18n.CompactNumberFormatSymbols_ssy', 'goog.i18n.CompactNumberFormatSymbols_ssy_ER', 'goog.i18n.CompactNumberFormatSymbols_sv_AX', 'goog.i18n.CompactNumberFormatSymbols_sv_FI', 'goog.i18n.CompactNumberFormatSymbols_sw_KE', 'goog.i18n.CompactNumberFormatSymbols_sw_UG', 'goog.i18n.CompactNumberFormatSymbols_swc', 'goog.i18n.CompactNumberFormatSymbols_swc_CD', 'goog.i18n.CompactNumberFormatSymbols_ta_LK', 'goog.i18n.CompactNumberFormatSymbols_ta_MY', 'goog.i18n.CompactNumberFormatSymbols_ta_SG', 'goog.i18n.CompactNumberFormatSymbols_teo', 'goog.i18n.CompactNumberFormatSymbols_teo_KE', 'goog.i18n.CompactNumberFormatSymbols_teo_UG', 'goog.i18n.CompactNumberFormatSymbols_ti', 'goog.i18n.CompactNumberFormatSymbols_ti_ER', 'goog.i18n.CompactNumberFormatSymbols_ti_ET', 'goog.i18n.CompactNumberFormatSymbols_tn', 'goog.i18n.CompactNumberFormatSymbols_tn_BW', 'goog.i18n.CompactNumberFormatSymbols_tn_ZA', 'goog.i18n.CompactNumberFormatSymbols_to', 'goog.i18n.CompactNumberFormatSymbols_to_TO', 'goog.i18n.CompactNumberFormatSymbols_tr_CY', 'goog.i18n.CompactNumberFormatSymbols_ts', 'goog.i18n.CompactNumberFormatSymbols_ts_ZA', 'goog.i18n.CompactNumberFormatSymbols_twq', 'goog.i18n.CompactNumberFormatSymbols_twq_NE', 'goog.i18n.CompactNumberFormatSymbols_tzm', 'goog.i18n.CompactNumberFormatSymbols_tzm_Latn', 'goog.i18n.CompactNumberFormatSymbols_tzm_Latn_MA', 'goog.i18n.CompactNumberFormatSymbols_ug', 'goog.i18n.CompactNumberFormatSymbols_ug_Arab', 'goog.i18n.CompactNumberFormatSymbols_ug_Arab_CN', 'goog.i18n.CompactNumberFormatSymbols_ur_IN', 'goog.i18n.CompactNumberFormatSymbols_uz_Arab', 'goog.i18n.CompactNumberFormatSymbols_uz_Arab_AF', 'goog.i18n.CompactNumberFormatSymbols_uz_Cyrl', 'goog.i18n.CompactNumberFormatSymbols_uz_Cyrl_UZ', 'goog.i18n.CompactNumberFormatSymbols_uz_Latn', 'goog.i18n.CompactNumberFormatSymbols_vai', 'goog.i18n.CompactNumberFormatSymbols_vai_Latn', 'goog.i18n.CompactNumberFormatSymbols_vai_Latn_LR', 'goog.i18n.CompactNumberFormatSymbols_vai_Vaii', 'goog.i18n.CompactNumberFormatSymbols_vai_Vaii_LR', 'goog.i18n.CompactNumberFormatSymbols_ve', 'goog.i18n.CompactNumberFormatSymbols_ve_ZA', 'goog.i18n.CompactNumberFormatSymbols_vo', 'goog.i18n.CompactNumberFormatSymbols_vo_001', 'goog.i18n.CompactNumberFormatSymbols_vun', 'goog.i18n.CompactNumberFormatSymbols_vun_TZ', 'goog.i18n.CompactNumberFormatSymbols_wae', 'goog.i18n.CompactNumberFormatSymbols_wae_CH', 'goog.i18n.CompactNumberFormatSymbols_xog', 'goog.i18n.CompactNumberFormatSymbols_xog_UG', 'goog.i18n.CompactNumberFormatSymbols_yav', 'goog.i18n.CompactNumberFormatSymbols_yav_CM', 'goog.i18n.CompactNumberFormatSymbols_yi', 'goog.i18n.CompactNumberFormatSymbols_yi_001', 'goog.i18n.CompactNumberFormatSymbols_yo', 'goog.i18n.CompactNumberFormatSymbols_yo_BJ', 'goog.i18n.CompactNumberFormatSymbols_yo_NG', 'goog.i18n.CompactNumberFormatSymbols_zgh', 'goog.i18n.CompactNumberFormatSymbols_zgh_MA', 'goog.i18n.CompactNumberFormatSymbols_zh_Hans', 'goog.i18n.CompactNumberFormatSymbols_zh_Hans_HK', 'goog.i18n.CompactNumberFormatSymbols_zh_Hans_MO', 'goog.i18n.CompactNumberFormatSymbols_zh_Hans_SG', 'goog.i18n.CompactNumberFormatSymbols_zh_Hant', 'goog.i18n.CompactNumberFormatSymbols_zh_Hant_HK', 'goog.i18n.CompactNumberFormatSymbols_zh_Hant_MO', 'goog.i18n.CompactNumberFormatSymbols_zh_Hant_TW'], [], false); -goog.addDependency('i18n/currency.js', ['goog.i18n.currency', 'goog.i18n.currency.CurrencyInfo', 'goog.i18n.currency.CurrencyInfoTier2'], [], false); -goog.addDependency('i18n/currency_test.js', ['goog.i18n.currencyTest'], ['goog.i18n.NumberFormat', 'goog.i18n.currency', 'goog.i18n.currency.CurrencyInfo', 'goog.object', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false); -goog.addDependency('i18n/currencycodemap.js', ['goog.i18n.currencyCodeMap', 'goog.i18n.currencyCodeMapTier2'], [], false); -goog.addDependency('i18n/datetimeformat.js', ['goog.i18n.DateTimeFormat', 'goog.i18n.DateTimeFormat.Format'], ['goog.asserts', 'goog.date', 'goog.i18n.DateTimeSymbols', 'goog.i18n.TimeZone', 'goog.string'], false); -goog.addDependency('i18n/datetimeformat_test.js', ['goog.i18n.DateTimeFormatTest'], ['goog.date.Date', 'goog.date.DateTime', 'goog.i18n.DateTimeFormat', 'goog.i18n.DateTimePatterns', 'goog.i18n.DateTimePatterns_de', 'goog.i18n.DateTimePatterns_en', 'goog.i18n.DateTimePatterns_fa', 'goog.i18n.DateTimePatterns_fr', 'goog.i18n.DateTimePatterns_ja', 'goog.i18n.DateTimePatterns_sv', 'goog.i18n.DateTimeSymbols', 'goog.i18n.DateTimeSymbols_ar_AE', 'goog.i18n.DateTimeSymbols_ar_SA', 'goog.i18n.DateTimeSymbols_bn_BD', 'goog.i18n.DateTimeSymbols_de', 'goog.i18n.DateTimeSymbols_en', 'goog.i18n.DateTimeSymbols_en_GB', 'goog.i18n.DateTimeSymbols_en_IE', 'goog.i18n.DateTimeSymbols_en_IN', 'goog.i18n.DateTimeSymbols_en_US', 'goog.i18n.DateTimeSymbols_fa', 'goog.i18n.DateTimeSymbols_fr', 'goog.i18n.DateTimeSymbols_fr_DJ', 'goog.i18n.DateTimeSymbols_he_IL', 'goog.i18n.DateTimeSymbols_ja', 'goog.i18n.DateTimeSymbols_ro_RO', 'goog.i18n.DateTimeSymbols_sv', 'goog.i18n.TimeZone', 'goog.testing.jsunit'], false); -goog.addDependency('i18n/datetimeparse.js', ['goog.i18n.DateTimeParse'], ['goog.date', 'goog.i18n.DateTimeFormat', 'goog.i18n.DateTimeSymbols'], false); -goog.addDependency('i18n/datetimeparse_test.js', ['goog.i18n.DateTimeParseTest'], ['goog.date.Date', 'goog.i18n.DateTimeFormat', 'goog.i18n.DateTimeParse', 'goog.i18n.DateTimeSymbols', 'goog.i18n.DateTimeSymbols_en', 'goog.i18n.DateTimeSymbols_fa', 'goog.i18n.DateTimeSymbols_fr', 'goog.i18n.DateTimeSymbols_pl', 'goog.i18n.DateTimeSymbols_zh', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('i18n/datetimepatterns.js', ['goog.i18n.DateTimePatterns', 'goog.i18n.DateTimePatterns_af', 'goog.i18n.DateTimePatterns_am', 'goog.i18n.DateTimePatterns_ar', 'goog.i18n.DateTimePatterns_az', 'goog.i18n.DateTimePatterns_bg', 'goog.i18n.DateTimePatterns_bn', 'goog.i18n.DateTimePatterns_br', 'goog.i18n.DateTimePatterns_ca', 'goog.i18n.DateTimePatterns_chr', 'goog.i18n.DateTimePatterns_cs', 'goog.i18n.DateTimePatterns_cy', 'goog.i18n.DateTimePatterns_da', 'goog.i18n.DateTimePatterns_de', 'goog.i18n.DateTimePatterns_de_AT', 'goog.i18n.DateTimePatterns_de_CH', 'goog.i18n.DateTimePatterns_el', 'goog.i18n.DateTimePatterns_en', 'goog.i18n.DateTimePatterns_en_AU', 'goog.i18n.DateTimePatterns_en_GB', 'goog.i18n.DateTimePatterns_en_IE', 'goog.i18n.DateTimePatterns_en_IN', 'goog.i18n.DateTimePatterns_en_SG', 'goog.i18n.DateTimePatterns_en_US', 'goog.i18n.DateTimePatterns_en_ZA', 'goog.i18n.DateTimePatterns_es', 'goog.i18n.DateTimePatterns_es_419', 'goog.i18n.DateTimePatterns_es_ES', 'goog.i18n.DateTimePatterns_et', 'goog.i18n.DateTimePatterns_eu', 'goog.i18n.DateTimePatterns_fa', 'goog.i18n.DateTimePatterns_fi', 'goog.i18n.DateTimePatterns_fil', 'goog.i18n.DateTimePatterns_fr', 'goog.i18n.DateTimePatterns_fr_CA', 'goog.i18n.DateTimePatterns_ga', 'goog.i18n.DateTimePatterns_gl', 'goog.i18n.DateTimePatterns_gsw', 'goog.i18n.DateTimePatterns_gu', 'goog.i18n.DateTimePatterns_haw', 'goog.i18n.DateTimePatterns_he', 'goog.i18n.DateTimePatterns_hi', 'goog.i18n.DateTimePatterns_hr', 'goog.i18n.DateTimePatterns_hu', 'goog.i18n.DateTimePatterns_hy', 'goog.i18n.DateTimePatterns_id', 'goog.i18n.DateTimePatterns_in', 'goog.i18n.DateTimePatterns_is', 'goog.i18n.DateTimePatterns_it', 'goog.i18n.DateTimePatterns_iw', 'goog.i18n.DateTimePatterns_ja', 'goog.i18n.DateTimePatterns_ka', 'goog.i18n.DateTimePatterns_kk', 'goog.i18n.DateTimePatterns_km', 'goog.i18n.DateTimePatterns_kn', 'goog.i18n.DateTimePatterns_ko', 'goog.i18n.DateTimePatterns_ky', 'goog.i18n.DateTimePatterns_ln', 'goog.i18n.DateTimePatterns_lo', 'goog.i18n.DateTimePatterns_lt', 'goog.i18n.DateTimePatterns_lv', 'goog.i18n.DateTimePatterns_mk', 'goog.i18n.DateTimePatterns_ml', 'goog.i18n.DateTimePatterns_mn', 'goog.i18n.DateTimePatterns_mo', 'goog.i18n.DateTimePatterns_mr', 'goog.i18n.DateTimePatterns_ms', 'goog.i18n.DateTimePatterns_mt', 'goog.i18n.DateTimePatterns_my', 'goog.i18n.DateTimePatterns_nb', 'goog.i18n.DateTimePatterns_ne', 'goog.i18n.DateTimePatterns_nl', 'goog.i18n.DateTimePatterns_no', 'goog.i18n.DateTimePatterns_no_NO', 'goog.i18n.DateTimePatterns_or', 'goog.i18n.DateTimePatterns_pa', 'goog.i18n.DateTimePatterns_pl', 'goog.i18n.DateTimePatterns_pt', 'goog.i18n.DateTimePatterns_pt_BR', 'goog.i18n.DateTimePatterns_pt_PT', 'goog.i18n.DateTimePatterns_ro', 'goog.i18n.DateTimePatterns_ru', 'goog.i18n.DateTimePatterns_sh', 'goog.i18n.DateTimePatterns_si', 'goog.i18n.DateTimePatterns_sk', 'goog.i18n.DateTimePatterns_sl', 'goog.i18n.DateTimePatterns_sq', 'goog.i18n.DateTimePatterns_sr', 'goog.i18n.DateTimePatterns_sv', 'goog.i18n.DateTimePatterns_sw', 'goog.i18n.DateTimePatterns_ta', 'goog.i18n.DateTimePatterns_te', 'goog.i18n.DateTimePatterns_th', 'goog.i18n.DateTimePatterns_tl', 'goog.i18n.DateTimePatterns_tr', 'goog.i18n.DateTimePatterns_uk', 'goog.i18n.DateTimePatterns_ur', 'goog.i18n.DateTimePatterns_uz', 'goog.i18n.DateTimePatterns_vi', 'goog.i18n.DateTimePatterns_zh', 'goog.i18n.DateTimePatterns_zh_CN', 'goog.i18n.DateTimePatterns_zh_HK', 'goog.i18n.DateTimePatterns_zh_TW', 'goog.i18n.DateTimePatterns_zu'], [], false); -goog.addDependency('i18n/datetimepatternsext.js', ['goog.i18n.DateTimePatternsExt', 'goog.i18n.DateTimePatterns_af_NA', 'goog.i18n.DateTimePatterns_af_ZA', 'goog.i18n.DateTimePatterns_agq', 'goog.i18n.DateTimePatterns_agq_CM', 'goog.i18n.DateTimePatterns_ak', 'goog.i18n.DateTimePatterns_ak_GH', 'goog.i18n.DateTimePatterns_am_ET', 'goog.i18n.DateTimePatterns_ar_001', 'goog.i18n.DateTimePatterns_ar_AE', 'goog.i18n.DateTimePatterns_ar_BH', 'goog.i18n.DateTimePatterns_ar_DJ', 'goog.i18n.DateTimePatterns_ar_DZ', 'goog.i18n.DateTimePatterns_ar_EG', 'goog.i18n.DateTimePatterns_ar_EH', 'goog.i18n.DateTimePatterns_ar_ER', 'goog.i18n.DateTimePatterns_ar_IL', 'goog.i18n.DateTimePatterns_ar_IQ', 'goog.i18n.DateTimePatterns_ar_JO', 'goog.i18n.DateTimePatterns_ar_KM', 'goog.i18n.DateTimePatterns_ar_KW', 'goog.i18n.DateTimePatterns_ar_LB', 'goog.i18n.DateTimePatterns_ar_LY', 'goog.i18n.DateTimePatterns_ar_MA', 'goog.i18n.DateTimePatterns_ar_MR', 'goog.i18n.DateTimePatterns_ar_OM', 'goog.i18n.DateTimePatterns_ar_PS', 'goog.i18n.DateTimePatterns_ar_QA', 'goog.i18n.DateTimePatterns_ar_SA', 'goog.i18n.DateTimePatterns_ar_SD', 'goog.i18n.DateTimePatterns_ar_SO', 'goog.i18n.DateTimePatterns_ar_SS', 'goog.i18n.DateTimePatterns_ar_SY', 'goog.i18n.DateTimePatterns_ar_TD', 'goog.i18n.DateTimePatterns_ar_TN', 'goog.i18n.DateTimePatterns_ar_YE', 'goog.i18n.DateTimePatterns_as', 'goog.i18n.DateTimePatterns_as_IN', 'goog.i18n.DateTimePatterns_asa', 'goog.i18n.DateTimePatterns_asa_TZ', 'goog.i18n.DateTimePatterns_az_Cyrl', 'goog.i18n.DateTimePatterns_az_Cyrl_AZ', 'goog.i18n.DateTimePatterns_az_Latn', 'goog.i18n.DateTimePatterns_az_Latn_AZ', 'goog.i18n.DateTimePatterns_bas', 'goog.i18n.DateTimePatterns_bas_CM', 'goog.i18n.DateTimePatterns_be', 'goog.i18n.DateTimePatterns_be_BY', 'goog.i18n.DateTimePatterns_bem', 'goog.i18n.DateTimePatterns_bem_ZM', 'goog.i18n.DateTimePatterns_bez', 'goog.i18n.DateTimePatterns_bez_TZ', 'goog.i18n.DateTimePatterns_bg_BG', 'goog.i18n.DateTimePatterns_bm', 'goog.i18n.DateTimePatterns_bm_Latn', 'goog.i18n.DateTimePatterns_bm_Latn_ML', 'goog.i18n.DateTimePatterns_bn_BD', 'goog.i18n.DateTimePatterns_bn_IN', 'goog.i18n.DateTimePatterns_bo', 'goog.i18n.DateTimePatterns_bo_CN', 'goog.i18n.DateTimePatterns_bo_IN', 'goog.i18n.DateTimePatterns_br_FR', 'goog.i18n.DateTimePatterns_brx', 'goog.i18n.DateTimePatterns_brx_IN', 'goog.i18n.DateTimePatterns_bs', 'goog.i18n.DateTimePatterns_bs_Cyrl', 'goog.i18n.DateTimePatterns_bs_Cyrl_BA', 'goog.i18n.DateTimePatterns_bs_Latn', 'goog.i18n.DateTimePatterns_bs_Latn_BA', 'goog.i18n.DateTimePatterns_ca_AD', 'goog.i18n.DateTimePatterns_ca_ES', 'goog.i18n.DateTimePatterns_ca_FR', 'goog.i18n.DateTimePatterns_ca_IT', 'goog.i18n.DateTimePatterns_cgg', 'goog.i18n.DateTimePatterns_cgg_UG', 'goog.i18n.DateTimePatterns_chr_US', 'goog.i18n.DateTimePatterns_cs_CZ', 'goog.i18n.DateTimePatterns_cy_GB', 'goog.i18n.DateTimePatterns_da_DK', 'goog.i18n.DateTimePatterns_da_GL', 'goog.i18n.DateTimePatterns_dav', 'goog.i18n.DateTimePatterns_dav_KE', 'goog.i18n.DateTimePatterns_de_BE', 'goog.i18n.DateTimePatterns_de_DE', 'goog.i18n.DateTimePatterns_de_LI', 'goog.i18n.DateTimePatterns_de_LU', 'goog.i18n.DateTimePatterns_dje', 'goog.i18n.DateTimePatterns_dje_NE', 'goog.i18n.DateTimePatterns_dsb', 'goog.i18n.DateTimePatterns_dsb_DE', 'goog.i18n.DateTimePatterns_dua', 'goog.i18n.DateTimePatterns_dua_CM', 'goog.i18n.DateTimePatterns_dyo', 'goog.i18n.DateTimePatterns_dyo_SN', 'goog.i18n.DateTimePatterns_dz', 'goog.i18n.DateTimePatterns_dz_BT', 'goog.i18n.DateTimePatterns_ebu', 'goog.i18n.DateTimePatterns_ebu_KE', 'goog.i18n.DateTimePatterns_ee', 'goog.i18n.DateTimePatterns_ee_GH', 'goog.i18n.DateTimePatterns_ee_TG', 'goog.i18n.DateTimePatterns_el_CY', 'goog.i18n.DateTimePatterns_el_GR', 'goog.i18n.DateTimePatterns_en_001', 'goog.i18n.DateTimePatterns_en_150', 'goog.i18n.DateTimePatterns_en_AG', 'goog.i18n.DateTimePatterns_en_AI', 'goog.i18n.DateTimePatterns_en_AS', 'goog.i18n.DateTimePatterns_en_BB', 'goog.i18n.DateTimePatterns_en_BE', 'goog.i18n.DateTimePatterns_en_BM', 'goog.i18n.DateTimePatterns_en_BS', 'goog.i18n.DateTimePatterns_en_BW', 'goog.i18n.DateTimePatterns_en_BZ', 'goog.i18n.DateTimePatterns_en_CA', 'goog.i18n.DateTimePatterns_en_CC', 'goog.i18n.DateTimePatterns_en_CK', 'goog.i18n.DateTimePatterns_en_CM', 'goog.i18n.DateTimePatterns_en_CX', 'goog.i18n.DateTimePatterns_en_DG', 'goog.i18n.DateTimePatterns_en_DM', 'goog.i18n.DateTimePatterns_en_ER', 'goog.i18n.DateTimePatterns_en_FJ', 'goog.i18n.DateTimePatterns_en_FK', 'goog.i18n.DateTimePatterns_en_FM', 'goog.i18n.DateTimePatterns_en_GD', 'goog.i18n.DateTimePatterns_en_GG', 'goog.i18n.DateTimePatterns_en_GH', 'goog.i18n.DateTimePatterns_en_GI', 'goog.i18n.DateTimePatterns_en_GM', 'goog.i18n.DateTimePatterns_en_GU', 'goog.i18n.DateTimePatterns_en_GY', 'goog.i18n.DateTimePatterns_en_HK', 'goog.i18n.DateTimePatterns_en_IM', 'goog.i18n.DateTimePatterns_en_IO', 'goog.i18n.DateTimePatterns_en_JE', 'goog.i18n.DateTimePatterns_en_JM', 'goog.i18n.DateTimePatterns_en_KE', 'goog.i18n.DateTimePatterns_en_KI', 'goog.i18n.DateTimePatterns_en_KN', 'goog.i18n.DateTimePatterns_en_KY', 'goog.i18n.DateTimePatterns_en_LC', 'goog.i18n.DateTimePatterns_en_LR', 'goog.i18n.DateTimePatterns_en_LS', 'goog.i18n.DateTimePatterns_en_MG', 'goog.i18n.DateTimePatterns_en_MH', 'goog.i18n.DateTimePatterns_en_MO', 'goog.i18n.DateTimePatterns_en_MP', 'goog.i18n.DateTimePatterns_en_MS', 'goog.i18n.DateTimePatterns_en_MT', 'goog.i18n.DateTimePatterns_en_MU', 'goog.i18n.DateTimePatterns_en_MW', 'goog.i18n.DateTimePatterns_en_MY', 'goog.i18n.DateTimePatterns_en_NA', 'goog.i18n.DateTimePatterns_en_NF', 'goog.i18n.DateTimePatterns_en_NG', 'goog.i18n.DateTimePatterns_en_NR', 'goog.i18n.DateTimePatterns_en_NU', 'goog.i18n.DateTimePatterns_en_NZ', 'goog.i18n.DateTimePatterns_en_PG', 'goog.i18n.DateTimePatterns_en_PH', 'goog.i18n.DateTimePatterns_en_PK', 'goog.i18n.DateTimePatterns_en_PN', 'goog.i18n.DateTimePatterns_en_PR', 'goog.i18n.DateTimePatterns_en_PW', 'goog.i18n.DateTimePatterns_en_RW', 'goog.i18n.DateTimePatterns_en_SB', 'goog.i18n.DateTimePatterns_en_SC', 'goog.i18n.DateTimePatterns_en_SD', 'goog.i18n.DateTimePatterns_en_SH', 'goog.i18n.DateTimePatterns_en_SL', 'goog.i18n.DateTimePatterns_en_SS', 'goog.i18n.DateTimePatterns_en_SX', 'goog.i18n.DateTimePatterns_en_SZ', 'goog.i18n.DateTimePatterns_en_TC', 'goog.i18n.DateTimePatterns_en_TK', 'goog.i18n.DateTimePatterns_en_TO', 'goog.i18n.DateTimePatterns_en_TT', 'goog.i18n.DateTimePatterns_en_TV', 'goog.i18n.DateTimePatterns_en_TZ', 'goog.i18n.DateTimePatterns_en_UG', 'goog.i18n.DateTimePatterns_en_UM', 'goog.i18n.DateTimePatterns_en_US_POSIX', 'goog.i18n.DateTimePatterns_en_VC', 'goog.i18n.DateTimePatterns_en_VG', 'goog.i18n.DateTimePatterns_en_VI', 'goog.i18n.DateTimePatterns_en_VU', 'goog.i18n.DateTimePatterns_en_WS', 'goog.i18n.DateTimePatterns_en_ZM', 'goog.i18n.DateTimePatterns_en_ZW', 'goog.i18n.DateTimePatterns_eo', 'goog.i18n.DateTimePatterns_es_AR', 'goog.i18n.DateTimePatterns_es_BO', 'goog.i18n.DateTimePatterns_es_CL', 'goog.i18n.DateTimePatterns_es_CO', 'goog.i18n.DateTimePatterns_es_CR', 'goog.i18n.DateTimePatterns_es_CU', 'goog.i18n.DateTimePatterns_es_DO', 'goog.i18n.DateTimePatterns_es_EA', 'goog.i18n.DateTimePatterns_es_EC', 'goog.i18n.DateTimePatterns_es_GQ', 'goog.i18n.DateTimePatterns_es_GT', 'goog.i18n.DateTimePatterns_es_HN', 'goog.i18n.DateTimePatterns_es_IC', 'goog.i18n.DateTimePatterns_es_MX', 'goog.i18n.DateTimePatterns_es_NI', 'goog.i18n.DateTimePatterns_es_PA', 'goog.i18n.DateTimePatterns_es_PE', 'goog.i18n.DateTimePatterns_es_PH', 'goog.i18n.DateTimePatterns_es_PR', 'goog.i18n.DateTimePatterns_es_PY', 'goog.i18n.DateTimePatterns_es_SV', 'goog.i18n.DateTimePatterns_es_US', 'goog.i18n.DateTimePatterns_es_UY', 'goog.i18n.DateTimePatterns_es_VE', 'goog.i18n.DateTimePatterns_et_EE', 'goog.i18n.DateTimePatterns_eu_ES', 'goog.i18n.DateTimePatterns_ewo', 'goog.i18n.DateTimePatterns_ewo_CM', 'goog.i18n.DateTimePatterns_fa_AF', 'goog.i18n.DateTimePatterns_fa_IR', 'goog.i18n.DateTimePatterns_ff', 'goog.i18n.DateTimePatterns_ff_CM', 'goog.i18n.DateTimePatterns_ff_GN', 'goog.i18n.DateTimePatterns_ff_MR', 'goog.i18n.DateTimePatterns_ff_SN', 'goog.i18n.DateTimePatterns_fi_FI', 'goog.i18n.DateTimePatterns_fil_PH', 'goog.i18n.DateTimePatterns_fo', 'goog.i18n.DateTimePatterns_fo_FO', 'goog.i18n.DateTimePatterns_fr_BE', 'goog.i18n.DateTimePatterns_fr_BF', 'goog.i18n.DateTimePatterns_fr_BI', 'goog.i18n.DateTimePatterns_fr_BJ', 'goog.i18n.DateTimePatterns_fr_BL', 'goog.i18n.DateTimePatterns_fr_CD', 'goog.i18n.DateTimePatterns_fr_CF', 'goog.i18n.DateTimePatterns_fr_CG', 'goog.i18n.DateTimePatterns_fr_CH', 'goog.i18n.DateTimePatterns_fr_CI', 'goog.i18n.DateTimePatterns_fr_CM', 'goog.i18n.DateTimePatterns_fr_DJ', 'goog.i18n.DateTimePatterns_fr_DZ', 'goog.i18n.DateTimePatterns_fr_FR', 'goog.i18n.DateTimePatterns_fr_GA', 'goog.i18n.DateTimePatterns_fr_GF', 'goog.i18n.DateTimePatterns_fr_GN', 'goog.i18n.DateTimePatterns_fr_GP', 'goog.i18n.DateTimePatterns_fr_GQ', 'goog.i18n.DateTimePatterns_fr_HT', 'goog.i18n.DateTimePatterns_fr_KM', 'goog.i18n.DateTimePatterns_fr_LU', 'goog.i18n.DateTimePatterns_fr_MA', 'goog.i18n.DateTimePatterns_fr_MC', 'goog.i18n.DateTimePatterns_fr_MF', 'goog.i18n.DateTimePatterns_fr_MG', 'goog.i18n.DateTimePatterns_fr_ML', 'goog.i18n.DateTimePatterns_fr_MQ', 'goog.i18n.DateTimePatterns_fr_MR', 'goog.i18n.DateTimePatterns_fr_MU', 'goog.i18n.DateTimePatterns_fr_NC', 'goog.i18n.DateTimePatterns_fr_NE', 'goog.i18n.DateTimePatterns_fr_PF', 'goog.i18n.DateTimePatterns_fr_PM', 'goog.i18n.DateTimePatterns_fr_RE', 'goog.i18n.DateTimePatterns_fr_RW', 'goog.i18n.DateTimePatterns_fr_SC', 'goog.i18n.DateTimePatterns_fr_SN', 'goog.i18n.DateTimePatterns_fr_SY', 'goog.i18n.DateTimePatterns_fr_TD', 'goog.i18n.DateTimePatterns_fr_TG', 'goog.i18n.DateTimePatterns_fr_TN', 'goog.i18n.DateTimePatterns_fr_VU', 'goog.i18n.DateTimePatterns_fr_WF', 'goog.i18n.DateTimePatterns_fr_YT', 'goog.i18n.DateTimePatterns_fur', 'goog.i18n.DateTimePatterns_fur_IT', 'goog.i18n.DateTimePatterns_fy', 'goog.i18n.DateTimePatterns_fy_NL', 'goog.i18n.DateTimePatterns_ga_IE', 'goog.i18n.DateTimePatterns_gd', 'goog.i18n.DateTimePatterns_gd_GB', 'goog.i18n.DateTimePatterns_gl_ES', 'goog.i18n.DateTimePatterns_gsw_CH', 'goog.i18n.DateTimePatterns_gsw_FR', 'goog.i18n.DateTimePatterns_gsw_LI', 'goog.i18n.DateTimePatterns_gu_IN', 'goog.i18n.DateTimePatterns_guz', 'goog.i18n.DateTimePatterns_guz_KE', 'goog.i18n.DateTimePatterns_gv', 'goog.i18n.DateTimePatterns_gv_IM', 'goog.i18n.DateTimePatterns_ha', 'goog.i18n.DateTimePatterns_ha_Latn', 'goog.i18n.DateTimePatterns_ha_Latn_GH', 'goog.i18n.DateTimePatterns_ha_Latn_NE', 'goog.i18n.DateTimePatterns_ha_Latn_NG', 'goog.i18n.DateTimePatterns_haw_US', 'goog.i18n.DateTimePatterns_he_IL', 'goog.i18n.DateTimePatterns_hi_IN', 'goog.i18n.DateTimePatterns_hr_BA', 'goog.i18n.DateTimePatterns_hr_HR', 'goog.i18n.DateTimePatterns_hsb', 'goog.i18n.DateTimePatterns_hsb_DE', 'goog.i18n.DateTimePatterns_hu_HU', 'goog.i18n.DateTimePatterns_hy_AM', 'goog.i18n.DateTimePatterns_id_ID', 'goog.i18n.DateTimePatterns_ig', 'goog.i18n.DateTimePatterns_ig_NG', 'goog.i18n.DateTimePatterns_ii', 'goog.i18n.DateTimePatterns_ii_CN', 'goog.i18n.DateTimePatterns_is_IS', 'goog.i18n.DateTimePatterns_it_CH', 'goog.i18n.DateTimePatterns_it_IT', 'goog.i18n.DateTimePatterns_it_SM', 'goog.i18n.DateTimePatterns_ja_JP', 'goog.i18n.DateTimePatterns_jgo', 'goog.i18n.DateTimePatterns_jgo_CM', 'goog.i18n.DateTimePatterns_jmc', 'goog.i18n.DateTimePatterns_jmc_TZ', 'goog.i18n.DateTimePatterns_ka_GE', 'goog.i18n.DateTimePatterns_kab', 'goog.i18n.DateTimePatterns_kab_DZ', 'goog.i18n.DateTimePatterns_kam', 'goog.i18n.DateTimePatterns_kam_KE', 'goog.i18n.DateTimePatterns_kde', 'goog.i18n.DateTimePatterns_kde_TZ', 'goog.i18n.DateTimePatterns_kea', 'goog.i18n.DateTimePatterns_kea_CV', 'goog.i18n.DateTimePatterns_khq', 'goog.i18n.DateTimePatterns_khq_ML', 'goog.i18n.DateTimePatterns_ki', 'goog.i18n.DateTimePatterns_ki_KE', 'goog.i18n.DateTimePatterns_kk_Cyrl', 'goog.i18n.DateTimePatterns_kk_Cyrl_KZ', 'goog.i18n.DateTimePatterns_kkj', 'goog.i18n.DateTimePatterns_kkj_CM', 'goog.i18n.DateTimePatterns_kl', 'goog.i18n.DateTimePatterns_kl_GL', 'goog.i18n.DateTimePatterns_kln', 'goog.i18n.DateTimePatterns_kln_KE', 'goog.i18n.DateTimePatterns_km_KH', 'goog.i18n.DateTimePatterns_kn_IN', 'goog.i18n.DateTimePatterns_ko_KP', 'goog.i18n.DateTimePatterns_ko_KR', 'goog.i18n.DateTimePatterns_kok', 'goog.i18n.DateTimePatterns_kok_IN', 'goog.i18n.DateTimePatterns_ks', 'goog.i18n.DateTimePatterns_ks_Arab', 'goog.i18n.DateTimePatterns_ks_Arab_IN', 'goog.i18n.DateTimePatterns_ksb', 'goog.i18n.DateTimePatterns_ksb_TZ', 'goog.i18n.DateTimePatterns_ksf', 'goog.i18n.DateTimePatterns_ksf_CM', 'goog.i18n.DateTimePatterns_ksh', 'goog.i18n.DateTimePatterns_ksh_DE', 'goog.i18n.DateTimePatterns_kw', 'goog.i18n.DateTimePatterns_kw_GB', 'goog.i18n.DateTimePatterns_ky_Cyrl', 'goog.i18n.DateTimePatterns_ky_Cyrl_KG', 'goog.i18n.DateTimePatterns_lag', 'goog.i18n.DateTimePatterns_lag_TZ', 'goog.i18n.DateTimePatterns_lb', 'goog.i18n.DateTimePatterns_lb_LU', 'goog.i18n.DateTimePatterns_lg', 'goog.i18n.DateTimePatterns_lg_UG', 'goog.i18n.DateTimePatterns_lkt', 'goog.i18n.DateTimePatterns_lkt_US', 'goog.i18n.DateTimePatterns_ln_AO', 'goog.i18n.DateTimePatterns_ln_CD', 'goog.i18n.DateTimePatterns_ln_CF', 'goog.i18n.DateTimePatterns_ln_CG', 'goog.i18n.DateTimePatterns_lo_LA', 'goog.i18n.DateTimePatterns_lt_LT', 'goog.i18n.DateTimePatterns_lu', 'goog.i18n.DateTimePatterns_lu_CD', 'goog.i18n.DateTimePatterns_luo', 'goog.i18n.DateTimePatterns_luo_KE', 'goog.i18n.DateTimePatterns_luy', 'goog.i18n.DateTimePatterns_luy_KE', 'goog.i18n.DateTimePatterns_lv_LV', 'goog.i18n.DateTimePatterns_mas', 'goog.i18n.DateTimePatterns_mas_KE', 'goog.i18n.DateTimePatterns_mas_TZ', 'goog.i18n.DateTimePatterns_mer', 'goog.i18n.DateTimePatterns_mer_KE', 'goog.i18n.DateTimePatterns_mfe', 'goog.i18n.DateTimePatterns_mfe_MU', 'goog.i18n.DateTimePatterns_mg', 'goog.i18n.DateTimePatterns_mg_MG', 'goog.i18n.DateTimePatterns_mgh', 'goog.i18n.DateTimePatterns_mgh_MZ', 'goog.i18n.DateTimePatterns_mgo', 'goog.i18n.DateTimePatterns_mgo_CM', 'goog.i18n.DateTimePatterns_mk_MK', 'goog.i18n.DateTimePatterns_ml_IN', 'goog.i18n.DateTimePatterns_mn_Cyrl', 'goog.i18n.DateTimePatterns_mn_Cyrl_MN', 'goog.i18n.DateTimePatterns_mr_IN', 'goog.i18n.DateTimePatterns_ms_Latn', 'goog.i18n.DateTimePatterns_ms_Latn_BN', 'goog.i18n.DateTimePatterns_ms_Latn_MY', 'goog.i18n.DateTimePatterns_ms_Latn_SG', 'goog.i18n.DateTimePatterns_mt_MT', 'goog.i18n.DateTimePatterns_mua', 'goog.i18n.DateTimePatterns_mua_CM', 'goog.i18n.DateTimePatterns_my_MM', 'goog.i18n.DateTimePatterns_naq', 'goog.i18n.DateTimePatterns_naq_NA', 'goog.i18n.DateTimePatterns_nb_NO', 'goog.i18n.DateTimePatterns_nb_SJ', 'goog.i18n.DateTimePatterns_nd', 'goog.i18n.DateTimePatterns_nd_ZW', 'goog.i18n.DateTimePatterns_ne_IN', 'goog.i18n.DateTimePatterns_ne_NP', 'goog.i18n.DateTimePatterns_nl_AW', 'goog.i18n.DateTimePatterns_nl_BE', 'goog.i18n.DateTimePatterns_nl_BQ', 'goog.i18n.DateTimePatterns_nl_CW', 'goog.i18n.DateTimePatterns_nl_NL', 'goog.i18n.DateTimePatterns_nl_SR', 'goog.i18n.DateTimePatterns_nl_SX', 'goog.i18n.DateTimePatterns_nmg', 'goog.i18n.DateTimePatterns_nmg_CM', 'goog.i18n.DateTimePatterns_nn', 'goog.i18n.DateTimePatterns_nn_NO', 'goog.i18n.DateTimePatterns_nnh', 'goog.i18n.DateTimePatterns_nnh_CM', 'goog.i18n.DateTimePatterns_nus', 'goog.i18n.DateTimePatterns_nus_SD', 'goog.i18n.DateTimePatterns_nyn', 'goog.i18n.DateTimePatterns_nyn_UG', 'goog.i18n.DateTimePatterns_om', 'goog.i18n.DateTimePatterns_om_ET', 'goog.i18n.DateTimePatterns_om_KE', 'goog.i18n.DateTimePatterns_or_IN', 'goog.i18n.DateTimePatterns_os', 'goog.i18n.DateTimePatterns_os_GE', 'goog.i18n.DateTimePatterns_os_RU', 'goog.i18n.DateTimePatterns_pa_Arab', 'goog.i18n.DateTimePatterns_pa_Arab_PK', 'goog.i18n.DateTimePatterns_pa_Guru', 'goog.i18n.DateTimePatterns_pa_Guru_IN', 'goog.i18n.DateTimePatterns_pl_PL', 'goog.i18n.DateTimePatterns_ps', 'goog.i18n.DateTimePatterns_ps_AF', 'goog.i18n.DateTimePatterns_pt_AO', 'goog.i18n.DateTimePatterns_pt_CV', 'goog.i18n.DateTimePatterns_pt_GW', 'goog.i18n.DateTimePatterns_pt_MO', 'goog.i18n.DateTimePatterns_pt_MZ', 'goog.i18n.DateTimePatterns_pt_ST', 'goog.i18n.DateTimePatterns_pt_TL', 'goog.i18n.DateTimePatterns_qu', 'goog.i18n.DateTimePatterns_qu_BO', 'goog.i18n.DateTimePatterns_qu_EC', 'goog.i18n.DateTimePatterns_qu_PE', 'goog.i18n.DateTimePatterns_rm', 'goog.i18n.DateTimePatterns_rm_CH', 'goog.i18n.DateTimePatterns_rn', 'goog.i18n.DateTimePatterns_rn_BI', 'goog.i18n.DateTimePatterns_ro_MD', 'goog.i18n.DateTimePatterns_ro_RO', 'goog.i18n.DateTimePatterns_rof', 'goog.i18n.DateTimePatterns_rof_TZ', 'goog.i18n.DateTimePatterns_ru_BY', 'goog.i18n.DateTimePatterns_ru_KG', 'goog.i18n.DateTimePatterns_ru_KZ', 'goog.i18n.DateTimePatterns_ru_MD', 'goog.i18n.DateTimePatterns_ru_RU', 'goog.i18n.DateTimePatterns_ru_UA', 'goog.i18n.DateTimePatterns_rw', 'goog.i18n.DateTimePatterns_rw_RW', 'goog.i18n.DateTimePatterns_rwk', 'goog.i18n.DateTimePatterns_rwk_TZ', 'goog.i18n.DateTimePatterns_sah', 'goog.i18n.DateTimePatterns_sah_RU', 'goog.i18n.DateTimePatterns_saq', 'goog.i18n.DateTimePatterns_saq_KE', 'goog.i18n.DateTimePatterns_sbp', 'goog.i18n.DateTimePatterns_sbp_TZ', 'goog.i18n.DateTimePatterns_se', 'goog.i18n.DateTimePatterns_se_FI', 'goog.i18n.DateTimePatterns_se_NO', 'goog.i18n.DateTimePatterns_se_SE', 'goog.i18n.DateTimePatterns_seh', 'goog.i18n.DateTimePatterns_seh_MZ', 'goog.i18n.DateTimePatterns_ses', 'goog.i18n.DateTimePatterns_ses_ML', 'goog.i18n.DateTimePatterns_sg', 'goog.i18n.DateTimePatterns_sg_CF', 'goog.i18n.DateTimePatterns_shi', 'goog.i18n.DateTimePatterns_shi_Latn', 'goog.i18n.DateTimePatterns_shi_Latn_MA', 'goog.i18n.DateTimePatterns_shi_Tfng', 'goog.i18n.DateTimePatterns_shi_Tfng_MA', 'goog.i18n.DateTimePatterns_si_LK', 'goog.i18n.DateTimePatterns_sk_SK', 'goog.i18n.DateTimePatterns_sl_SI', 'goog.i18n.DateTimePatterns_smn', 'goog.i18n.DateTimePatterns_smn_FI', 'goog.i18n.DateTimePatterns_sn', 'goog.i18n.DateTimePatterns_sn_ZW', 'goog.i18n.DateTimePatterns_so', 'goog.i18n.DateTimePatterns_so_DJ', 'goog.i18n.DateTimePatterns_so_ET', 'goog.i18n.DateTimePatterns_so_KE', 'goog.i18n.DateTimePatterns_so_SO', 'goog.i18n.DateTimePatterns_sq_AL', 'goog.i18n.DateTimePatterns_sq_MK', 'goog.i18n.DateTimePatterns_sq_XK', 'goog.i18n.DateTimePatterns_sr_Cyrl', 'goog.i18n.DateTimePatterns_sr_Cyrl_BA', 'goog.i18n.DateTimePatterns_sr_Cyrl_ME', 'goog.i18n.DateTimePatterns_sr_Cyrl_RS', 'goog.i18n.DateTimePatterns_sr_Cyrl_XK', 'goog.i18n.DateTimePatterns_sr_Latn', 'goog.i18n.DateTimePatterns_sr_Latn_BA', 'goog.i18n.DateTimePatterns_sr_Latn_ME', 'goog.i18n.DateTimePatterns_sr_Latn_RS', 'goog.i18n.DateTimePatterns_sr_Latn_XK', 'goog.i18n.DateTimePatterns_sv_AX', 'goog.i18n.DateTimePatterns_sv_FI', 'goog.i18n.DateTimePatterns_sv_SE', 'goog.i18n.DateTimePatterns_sw_KE', 'goog.i18n.DateTimePatterns_sw_TZ', 'goog.i18n.DateTimePatterns_sw_UG', 'goog.i18n.DateTimePatterns_swc', 'goog.i18n.DateTimePatterns_swc_CD', 'goog.i18n.DateTimePatterns_ta_IN', 'goog.i18n.DateTimePatterns_ta_LK', 'goog.i18n.DateTimePatterns_ta_MY', 'goog.i18n.DateTimePatterns_ta_SG', 'goog.i18n.DateTimePatterns_te_IN', 'goog.i18n.DateTimePatterns_teo', 'goog.i18n.DateTimePatterns_teo_KE', 'goog.i18n.DateTimePatterns_teo_UG', 'goog.i18n.DateTimePatterns_th_TH', 'goog.i18n.DateTimePatterns_ti', 'goog.i18n.DateTimePatterns_ti_ER', 'goog.i18n.DateTimePatterns_ti_ET', 'goog.i18n.DateTimePatterns_to', 'goog.i18n.DateTimePatterns_to_TO', 'goog.i18n.DateTimePatterns_tr_CY', 'goog.i18n.DateTimePatterns_tr_TR', 'goog.i18n.DateTimePatterns_twq', 'goog.i18n.DateTimePatterns_twq_NE', 'goog.i18n.DateTimePatterns_tzm', 'goog.i18n.DateTimePatterns_tzm_Latn', 'goog.i18n.DateTimePatterns_tzm_Latn_MA', 'goog.i18n.DateTimePatterns_ug', 'goog.i18n.DateTimePatterns_ug_Arab', 'goog.i18n.DateTimePatterns_ug_Arab_CN', 'goog.i18n.DateTimePatterns_uk_UA', 'goog.i18n.DateTimePatterns_ur_IN', 'goog.i18n.DateTimePatterns_ur_PK', 'goog.i18n.DateTimePatterns_uz_Arab', 'goog.i18n.DateTimePatterns_uz_Arab_AF', 'goog.i18n.DateTimePatterns_uz_Cyrl', 'goog.i18n.DateTimePatterns_uz_Cyrl_UZ', 'goog.i18n.DateTimePatterns_uz_Latn', 'goog.i18n.DateTimePatterns_uz_Latn_UZ', 'goog.i18n.DateTimePatterns_vai', 'goog.i18n.DateTimePatterns_vai_Latn', 'goog.i18n.DateTimePatterns_vai_Latn_LR', 'goog.i18n.DateTimePatterns_vai_Vaii', 'goog.i18n.DateTimePatterns_vai_Vaii_LR', 'goog.i18n.DateTimePatterns_vi_VN', 'goog.i18n.DateTimePatterns_vun', 'goog.i18n.DateTimePatterns_vun_TZ', 'goog.i18n.DateTimePatterns_wae', 'goog.i18n.DateTimePatterns_wae_CH', 'goog.i18n.DateTimePatterns_xog', 'goog.i18n.DateTimePatterns_xog_UG', 'goog.i18n.DateTimePatterns_yav', 'goog.i18n.DateTimePatterns_yav_CM', 'goog.i18n.DateTimePatterns_yi', 'goog.i18n.DateTimePatterns_yi_001', 'goog.i18n.DateTimePatterns_yo', 'goog.i18n.DateTimePatterns_yo_BJ', 'goog.i18n.DateTimePatterns_yo_NG', 'goog.i18n.DateTimePatterns_zgh', 'goog.i18n.DateTimePatterns_zgh_MA', 'goog.i18n.DateTimePatterns_zh_Hans', 'goog.i18n.DateTimePatterns_zh_Hans_CN', 'goog.i18n.DateTimePatterns_zh_Hans_HK', 'goog.i18n.DateTimePatterns_zh_Hans_MO', 'goog.i18n.DateTimePatterns_zh_Hans_SG', 'goog.i18n.DateTimePatterns_zh_Hant', 'goog.i18n.DateTimePatterns_zh_Hant_HK', 'goog.i18n.DateTimePatterns_zh_Hant_MO', 'goog.i18n.DateTimePatterns_zh_Hant_TW', 'goog.i18n.DateTimePatterns_zu_ZA'], ['goog.i18n.DateTimePatterns'], false); -goog.addDependency('i18n/datetimesymbols.js', ['goog.i18n.DateTimeSymbols', 'goog.i18n.DateTimeSymbols_af', 'goog.i18n.DateTimeSymbols_am', 'goog.i18n.DateTimeSymbols_ar', 'goog.i18n.DateTimeSymbols_az', 'goog.i18n.DateTimeSymbols_bg', 'goog.i18n.DateTimeSymbols_bn', 'goog.i18n.DateTimeSymbols_br', 'goog.i18n.DateTimeSymbols_ca', 'goog.i18n.DateTimeSymbols_chr', 'goog.i18n.DateTimeSymbols_cs', 'goog.i18n.DateTimeSymbols_cy', 'goog.i18n.DateTimeSymbols_da', 'goog.i18n.DateTimeSymbols_de', 'goog.i18n.DateTimeSymbols_de_AT', 'goog.i18n.DateTimeSymbols_de_CH', 'goog.i18n.DateTimeSymbols_el', 'goog.i18n.DateTimeSymbols_en', 'goog.i18n.DateTimeSymbols_en_AU', 'goog.i18n.DateTimeSymbols_en_GB', 'goog.i18n.DateTimeSymbols_en_IE', 'goog.i18n.DateTimeSymbols_en_IN', 'goog.i18n.DateTimeSymbols_en_ISO', 'goog.i18n.DateTimeSymbols_en_SG', 'goog.i18n.DateTimeSymbols_en_US', 'goog.i18n.DateTimeSymbols_en_ZA', 'goog.i18n.DateTimeSymbols_es', 'goog.i18n.DateTimeSymbols_es_419', 'goog.i18n.DateTimeSymbols_es_ES', 'goog.i18n.DateTimeSymbols_et', 'goog.i18n.DateTimeSymbols_eu', 'goog.i18n.DateTimeSymbols_fa', 'goog.i18n.DateTimeSymbols_fi', 'goog.i18n.DateTimeSymbols_fil', 'goog.i18n.DateTimeSymbols_fr', 'goog.i18n.DateTimeSymbols_fr_CA', 'goog.i18n.DateTimeSymbols_ga', 'goog.i18n.DateTimeSymbols_gl', 'goog.i18n.DateTimeSymbols_gsw', 'goog.i18n.DateTimeSymbols_gu', 'goog.i18n.DateTimeSymbols_haw', 'goog.i18n.DateTimeSymbols_he', 'goog.i18n.DateTimeSymbols_hi', 'goog.i18n.DateTimeSymbols_hr', 'goog.i18n.DateTimeSymbols_hu', 'goog.i18n.DateTimeSymbols_hy', 'goog.i18n.DateTimeSymbols_id', 'goog.i18n.DateTimeSymbols_in', 'goog.i18n.DateTimeSymbols_is', 'goog.i18n.DateTimeSymbols_it', 'goog.i18n.DateTimeSymbols_iw', 'goog.i18n.DateTimeSymbols_ja', 'goog.i18n.DateTimeSymbols_ka', 'goog.i18n.DateTimeSymbols_kk', 'goog.i18n.DateTimeSymbols_km', 'goog.i18n.DateTimeSymbols_kn', 'goog.i18n.DateTimeSymbols_ko', 'goog.i18n.DateTimeSymbols_ky', 'goog.i18n.DateTimeSymbols_ln', 'goog.i18n.DateTimeSymbols_lo', 'goog.i18n.DateTimeSymbols_lt', 'goog.i18n.DateTimeSymbols_lv', 'goog.i18n.DateTimeSymbols_mk', 'goog.i18n.DateTimeSymbols_ml', 'goog.i18n.DateTimeSymbols_mn', 'goog.i18n.DateTimeSymbols_mr', 'goog.i18n.DateTimeSymbols_ms', 'goog.i18n.DateTimeSymbols_mt', 'goog.i18n.DateTimeSymbols_my', 'goog.i18n.DateTimeSymbols_nb', 'goog.i18n.DateTimeSymbols_ne', 'goog.i18n.DateTimeSymbols_nl', 'goog.i18n.DateTimeSymbols_no', 'goog.i18n.DateTimeSymbols_no_NO', 'goog.i18n.DateTimeSymbols_or', 'goog.i18n.DateTimeSymbols_pa', 'goog.i18n.DateTimeSymbols_pl', 'goog.i18n.DateTimeSymbols_pt', 'goog.i18n.DateTimeSymbols_pt_BR', 'goog.i18n.DateTimeSymbols_pt_PT', 'goog.i18n.DateTimeSymbols_ro', 'goog.i18n.DateTimeSymbols_ru', 'goog.i18n.DateTimeSymbols_si', 'goog.i18n.DateTimeSymbols_sk', 'goog.i18n.DateTimeSymbols_sl', 'goog.i18n.DateTimeSymbols_sq', 'goog.i18n.DateTimeSymbols_sr', 'goog.i18n.DateTimeSymbols_sv', 'goog.i18n.DateTimeSymbols_sw', 'goog.i18n.DateTimeSymbols_ta', 'goog.i18n.DateTimeSymbols_te', 'goog.i18n.DateTimeSymbols_th', 'goog.i18n.DateTimeSymbols_tl', 'goog.i18n.DateTimeSymbols_tr', 'goog.i18n.DateTimeSymbols_uk', 'goog.i18n.DateTimeSymbols_ur', 'goog.i18n.DateTimeSymbols_uz', 'goog.i18n.DateTimeSymbols_vi', 'goog.i18n.DateTimeSymbols_zh', 'goog.i18n.DateTimeSymbols_zh_CN', 'goog.i18n.DateTimeSymbols_zh_HK', 'goog.i18n.DateTimeSymbols_zh_TW', 'goog.i18n.DateTimeSymbols_zu'], [], false); -goog.addDependency('i18n/datetimesymbolsext.js', ['goog.i18n.DateTimeSymbolsExt', 'goog.i18n.DateTimeSymbols_aa', 'goog.i18n.DateTimeSymbols_aa_DJ', 'goog.i18n.DateTimeSymbols_aa_ER', 'goog.i18n.DateTimeSymbols_aa_ET', 'goog.i18n.DateTimeSymbols_af_NA', 'goog.i18n.DateTimeSymbols_af_ZA', 'goog.i18n.DateTimeSymbols_agq', 'goog.i18n.DateTimeSymbols_agq_CM', 'goog.i18n.DateTimeSymbols_ak', 'goog.i18n.DateTimeSymbols_ak_GH', 'goog.i18n.DateTimeSymbols_am_ET', 'goog.i18n.DateTimeSymbols_ar_001', 'goog.i18n.DateTimeSymbols_ar_AE', 'goog.i18n.DateTimeSymbols_ar_BH', 'goog.i18n.DateTimeSymbols_ar_DJ', 'goog.i18n.DateTimeSymbols_ar_DZ', 'goog.i18n.DateTimeSymbols_ar_EG', 'goog.i18n.DateTimeSymbols_ar_EH', 'goog.i18n.DateTimeSymbols_ar_ER', 'goog.i18n.DateTimeSymbols_ar_IL', 'goog.i18n.DateTimeSymbols_ar_IQ', 'goog.i18n.DateTimeSymbols_ar_JO', 'goog.i18n.DateTimeSymbols_ar_KM', 'goog.i18n.DateTimeSymbols_ar_KW', 'goog.i18n.DateTimeSymbols_ar_LB', 'goog.i18n.DateTimeSymbols_ar_LY', 'goog.i18n.DateTimeSymbols_ar_MA', 'goog.i18n.DateTimeSymbols_ar_MR', 'goog.i18n.DateTimeSymbols_ar_OM', 'goog.i18n.DateTimeSymbols_ar_PS', 'goog.i18n.DateTimeSymbols_ar_QA', 'goog.i18n.DateTimeSymbols_ar_SA', 'goog.i18n.DateTimeSymbols_ar_SD', 'goog.i18n.DateTimeSymbols_ar_SO', 'goog.i18n.DateTimeSymbols_ar_SS', 'goog.i18n.DateTimeSymbols_ar_SY', 'goog.i18n.DateTimeSymbols_ar_TD', 'goog.i18n.DateTimeSymbols_ar_TN', 'goog.i18n.DateTimeSymbols_ar_YE', 'goog.i18n.DateTimeSymbols_as', 'goog.i18n.DateTimeSymbols_as_IN', 'goog.i18n.DateTimeSymbols_asa', 'goog.i18n.DateTimeSymbols_asa_TZ', 'goog.i18n.DateTimeSymbols_ast', 'goog.i18n.DateTimeSymbols_ast_ES', 'goog.i18n.DateTimeSymbols_az_Cyrl', 'goog.i18n.DateTimeSymbols_az_Cyrl_AZ', 'goog.i18n.DateTimeSymbols_az_Latn', 'goog.i18n.DateTimeSymbols_az_Latn_AZ', 'goog.i18n.DateTimeSymbols_bas', 'goog.i18n.DateTimeSymbols_bas_CM', 'goog.i18n.DateTimeSymbols_be', 'goog.i18n.DateTimeSymbols_be_BY', 'goog.i18n.DateTimeSymbols_bem', 'goog.i18n.DateTimeSymbols_bem_ZM', 'goog.i18n.DateTimeSymbols_bez', 'goog.i18n.DateTimeSymbols_bez_TZ', 'goog.i18n.DateTimeSymbols_bg_BG', 'goog.i18n.DateTimeSymbols_bm', 'goog.i18n.DateTimeSymbols_bm_Latn', 'goog.i18n.DateTimeSymbols_bm_Latn_ML', 'goog.i18n.DateTimeSymbols_bn_BD', 'goog.i18n.DateTimeSymbols_bn_IN', 'goog.i18n.DateTimeSymbols_bo', 'goog.i18n.DateTimeSymbols_bo_CN', 'goog.i18n.DateTimeSymbols_bo_IN', 'goog.i18n.DateTimeSymbols_br_FR', 'goog.i18n.DateTimeSymbols_brx', 'goog.i18n.DateTimeSymbols_brx_IN', 'goog.i18n.DateTimeSymbols_bs', 'goog.i18n.DateTimeSymbols_bs_Cyrl', 'goog.i18n.DateTimeSymbols_bs_Cyrl_BA', 'goog.i18n.DateTimeSymbols_bs_Latn', 'goog.i18n.DateTimeSymbols_bs_Latn_BA', 'goog.i18n.DateTimeSymbols_ca_AD', 'goog.i18n.DateTimeSymbols_ca_ES', 'goog.i18n.DateTimeSymbols_ca_ES_VALENCIA', 'goog.i18n.DateTimeSymbols_ca_FR', 'goog.i18n.DateTimeSymbols_ca_IT', 'goog.i18n.DateTimeSymbols_cgg', 'goog.i18n.DateTimeSymbols_cgg_UG', 'goog.i18n.DateTimeSymbols_chr_US', 'goog.i18n.DateTimeSymbols_ckb', 'goog.i18n.DateTimeSymbols_ckb_Arab', 'goog.i18n.DateTimeSymbols_ckb_Arab_IQ', 'goog.i18n.DateTimeSymbols_ckb_Arab_IR', 'goog.i18n.DateTimeSymbols_ckb_IQ', 'goog.i18n.DateTimeSymbols_ckb_IR', 'goog.i18n.DateTimeSymbols_ckb_Latn', 'goog.i18n.DateTimeSymbols_ckb_Latn_IQ', 'goog.i18n.DateTimeSymbols_cs_CZ', 'goog.i18n.DateTimeSymbols_cy_GB', 'goog.i18n.DateTimeSymbols_da_DK', 'goog.i18n.DateTimeSymbols_da_GL', 'goog.i18n.DateTimeSymbols_dav', 'goog.i18n.DateTimeSymbols_dav_KE', 'goog.i18n.DateTimeSymbols_de_BE', 'goog.i18n.DateTimeSymbols_de_DE', 'goog.i18n.DateTimeSymbols_de_LI', 'goog.i18n.DateTimeSymbols_de_LU', 'goog.i18n.DateTimeSymbols_dje', 'goog.i18n.DateTimeSymbols_dje_NE', 'goog.i18n.DateTimeSymbols_dsb', 'goog.i18n.DateTimeSymbols_dsb_DE', 'goog.i18n.DateTimeSymbols_dua', 'goog.i18n.DateTimeSymbols_dua_CM', 'goog.i18n.DateTimeSymbols_dyo', 'goog.i18n.DateTimeSymbols_dyo_SN', 'goog.i18n.DateTimeSymbols_dz', 'goog.i18n.DateTimeSymbols_dz_BT', 'goog.i18n.DateTimeSymbols_ebu', 'goog.i18n.DateTimeSymbols_ebu_KE', 'goog.i18n.DateTimeSymbols_ee', 'goog.i18n.DateTimeSymbols_ee_GH', 'goog.i18n.DateTimeSymbols_ee_TG', 'goog.i18n.DateTimeSymbols_el_CY', 'goog.i18n.DateTimeSymbols_el_GR', 'goog.i18n.DateTimeSymbols_en_001', 'goog.i18n.DateTimeSymbols_en_150', 'goog.i18n.DateTimeSymbols_en_AG', 'goog.i18n.DateTimeSymbols_en_AI', 'goog.i18n.DateTimeSymbols_en_AS', 'goog.i18n.DateTimeSymbols_en_BB', 'goog.i18n.DateTimeSymbols_en_BE', 'goog.i18n.DateTimeSymbols_en_BM', 'goog.i18n.DateTimeSymbols_en_BS', 'goog.i18n.DateTimeSymbols_en_BW', 'goog.i18n.DateTimeSymbols_en_BZ', 'goog.i18n.DateTimeSymbols_en_CA', 'goog.i18n.DateTimeSymbols_en_CC', 'goog.i18n.DateTimeSymbols_en_CK', 'goog.i18n.DateTimeSymbols_en_CM', 'goog.i18n.DateTimeSymbols_en_CX', 'goog.i18n.DateTimeSymbols_en_DG', 'goog.i18n.DateTimeSymbols_en_DM', 'goog.i18n.DateTimeSymbols_en_ER', 'goog.i18n.DateTimeSymbols_en_FJ', 'goog.i18n.DateTimeSymbols_en_FK', 'goog.i18n.DateTimeSymbols_en_FM', 'goog.i18n.DateTimeSymbols_en_GD', 'goog.i18n.DateTimeSymbols_en_GG', 'goog.i18n.DateTimeSymbols_en_GH', 'goog.i18n.DateTimeSymbols_en_GI', 'goog.i18n.DateTimeSymbols_en_GM', 'goog.i18n.DateTimeSymbols_en_GU', 'goog.i18n.DateTimeSymbols_en_GY', 'goog.i18n.DateTimeSymbols_en_HK', 'goog.i18n.DateTimeSymbols_en_IM', 'goog.i18n.DateTimeSymbols_en_IO', 'goog.i18n.DateTimeSymbols_en_JE', 'goog.i18n.DateTimeSymbols_en_JM', 'goog.i18n.DateTimeSymbols_en_KE', 'goog.i18n.DateTimeSymbols_en_KI', 'goog.i18n.DateTimeSymbols_en_KN', 'goog.i18n.DateTimeSymbols_en_KY', 'goog.i18n.DateTimeSymbols_en_LC', 'goog.i18n.DateTimeSymbols_en_LR', 'goog.i18n.DateTimeSymbols_en_LS', 'goog.i18n.DateTimeSymbols_en_MG', 'goog.i18n.DateTimeSymbols_en_MH', 'goog.i18n.DateTimeSymbols_en_MO', 'goog.i18n.DateTimeSymbols_en_MP', 'goog.i18n.DateTimeSymbols_en_MS', 'goog.i18n.DateTimeSymbols_en_MT', 'goog.i18n.DateTimeSymbols_en_MU', 'goog.i18n.DateTimeSymbols_en_MW', 'goog.i18n.DateTimeSymbols_en_MY', 'goog.i18n.DateTimeSymbols_en_NA', 'goog.i18n.DateTimeSymbols_en_NF', 'goog.i18n.DateTimeSymbols_en_NG', 'goog.i18n.DateTimeSymbols_en_NR', 'goog.i18n.DateTimeSymbols_en_NU', 'goog.i18n.DateTimeSymbols_en_NZ', 'goog.i18n.DateTimeSymbols_en_PG', 'goog.i18n.DateTimeSymbols_en_PH', 'goog.i18n.DateTimeSymbols_en_PK', 'goog.i18n.DateTimeSymbols_en_PN', 'goog.i18n.DateTimeSymbols_en_PR', 'goog.i18n.DateTimeSymbols_en_PW', 'goog.i18n.DateTimeSymbols_en_RW', 'goog.i18n.DateTimeSymbols_en_SB', 'goog.i18n.DateTimeSymbols_en_SC', 'goog.i18n.DateTimeSymbols_en_SD', 'goog.i18n.DateTimeSymbols_en_SH', 'goog.i18n.DateTimeSymbols_en_SL', 'goog.i18n.DateTimeSymbols_en_SS', 'goog.i18n.DateTimeSymbols_en_SX', 'goog.i18n.DateTimeSymbols_en_SZ', 'goog.i18n.DateTimeSymbols_en_TC', 'goog.i18n.DateTimeSymbols_en_TK', 'goog.i18n.DateTimeSymbols_en_TO', 'goog.i18n.DateTimeSymbols_en_TT', 'goog.i18n.DateTimeSymbols_en_TV', 'goog.i18n.DateTimeSymbols_en_TZ', 'goog.i18n.DateTimeSymbols_en_UG', 'goog.i18n.DateTimeSymbols_en_UM', 'goog.i18n.DateTimeSymbols_en_VC', 'goog.i18n.DateTimeSymbols_en_VG', 'goog.i18n.DateTimeSymbols_en_VI', 'goog.i18n.DateTimeSymbols_en_VU', 'goog.i18n.DateTimeSymbols_en_WS', 'goog.i18n.DateTimeSymbols_en_ZM', 'goog.i18n.DateTimeSymbols_en_ZW', 'goog.i18n.DateTimeSymbols_eo', 'goog.i18n.DateTimeSymbols_eo_001', 'goog.i18n.DateTimeSymbols_es_AR', 'goog.i18n.DateTimeSymbols_es_BO', 'goog.i18n.DateTimeSymbols_es_CL', 'goog.i18n.DateTimeSymbols_es_CO', 'goog.i18n.DateTimeSymbols_es_CR', 'goog.i18n.DateTimeSymbols_es_CU', 'goog.i18n.DateTimeSymbols_es_DO', 'goog.i18n.DateTimeSymbols_es_EA', 'goog.i18n.DateTimeSymbols_es_EC', 'goog.i18n.DateTimeSymbols_es_GQ', 'goog.i18n.DateTimeSymbols_es_GT', 'goog.i18n.DateTimeSymbols_es_HN', 'goog.i18n.DateTimeSymbols_es_IC', 'goog.i18n.DateTimeSymbols_es_MX', 'goog.i18n.DateTimeSymbols_es_NI', 'goog.i18n.DateTimeSymbols_es_PA', 'goog.i18n.DateTimeSymbols_es_PE', 'goog.i18n.DateTimeSymbols_es_PH', 'goog.i18n.DateTimeSymbols_es_PR', 'goog.i18n.DateTimeSymbols_es_PY', 'goog.i18n.DateTimeSymbols_es_SV', 'goog.i18n.DateTimeSymbols_es_US', 'goog.i18n.DateTimeSymbols_es_UY', 'goog.i18n.DateTimeSymbols_es_VE', 'goog.i18n.DateTimeSymbols_et_EE', 'goog.i18n.DateTimeSymbols_eu_ES', 'goog.i18n.DateTimeSymbols_ewo', 'goog.i18n.DateTimeSymbols_ewo_CM', 'goog.i18n.DateTimeSymbols_fa_AF', 'goog.i18n.DateTimeSymbols_fa_IR', 'goog.i18n.DateTimeSymbols_ff', 'goog.i18n.DateTimeSymbols_ff_CM', 'goog.i18n.DateTimeSymbols_ff_GN', 'goog.i18n.DateTimeSymbols_ff_MR', 'goog.i18n.DateTimeSymbols_ff_SN', 'goog.i18n.DateTimeSymbols_fi_FI', 'goog.i18n.DateTimeSymbols_fil_PH', 'goog.i18n.DateTimeSymbols_fo', 'goog.i18n.DateTimeSymbols_fo_FO', 'goog.i18n.DateTimeSymbols_fr_BE', 'goog.i18n.DateTimeSymbols_fr_BF', 'goog.i18n.DateTimeSymbols_fr_BI', 'goog.i18n.DateTimeSymbols_fr_BJ', 'goog.i18n.DateTimeSymbols_fr_BL', 'goog.i18n.DateTimeSymbols_fr_CD', 'goog.i18n.DateTimeSymbols_fr_CF', 'goog.i18n.DateTimeSymbols_fr_CG', 'goog.i18n.DateTimeSymbols_fr_CH', 'goog.i18n.DateTimeSymbols_fr_CI', 'goog.i18n.DateTimeSymbols_fr_CM', 'goog.i18n.DateTimeSymbols_fr_DJ', 'goog.i18n.DateTimeSymbols_fr_DZ', 'goog.i18n.DateTimeSymbols_fr_FR', 'goog.i18n.DateTimeSymbols_fr_GA', 'goog.i18n.DateTimeSymbols_fr_GF', 'goog.i18n.DateTimeSymbols_fr_GN', 'goog.i18n.DateTimeSymbols_fr_GP', 'goog.i18n.DateTimeSymbols_fr_GQ', 'goog.i18n.DateTimeSymbols_fr_HT', 'goog.i18n.DateTimeSymbols_fr_KM', 'goog.i18n.DateTimeSymbols_fr_LU', 'goog.i18n.DateTimeSymbols_fr_MA', 'goog.i18n.DateTimeSymbols_fr_MC', 'goog.i18n.DateTimeSymbols_fr_MF', 'goog.i18n.DateTimeSymbols_fr_MG', 'goog.i18n.DateTimeSymbols_fr_ML', 'goog.i18n.DateTimeSymbols_fr_MQ', 'goog.i18n.DateTimeSymbols_fr_MR', 'goog.i18n.DateTimeSymbols_fr_MU', 'goog.i18n.DateTimeSymbols_fr_NC', 'goog.i18n.DateTimeSymbols_fr_NE', 'goog.i18n.DateTimeSymbols_fr_PF', 'goog.i18n.DateTimeSymbols_fr_PM', 'goog.i18n.DateTimeSymbols_fr_RE', 'goog.i18n.DateTimeSymbols_fr_RW', 'goog.i18n.DateTimeSymbols_fr_SC', 'goog.i18n.DateTimeSymbols_fr_SN', 'goog.i18n.DateTimeSymbols_fr_SY', 'goog.i18n.DateTimeSymbols_fr_TD', 'goog.i18n.DateTimeSymbols_fr_TG', 'goog.i18n.DateTimeSymbols_fr_TN', 'goog.i18n.DateTimeSymbols_fr_VU', 'goog.i18n.DateTimeSymbols_fr_WF', 'goog.i18n.DateTimeSymbols_fr_YT', 'goog.i18n.DateTimeSymbols_fur', 'goog.i18n.DateTimeSymbols_fur_IT', 'goog.i18n.DateTimeSymbols_fy', 'goog.i18n.DateTimeSymbols_fy_NL', 'goog.i18n.DateTimeSymbols_ga_IE', 'goog.i18n.DateTimeSymbols_gd', 'goog.i18n.DateTimeSymbols_gd_GB', 'goog.i18n.DateTimeSymbols_gl_ES', 'goog.i18n.DateTimeSymbols_gsw_CH', 'goog.i18n.DateTimeSymbols_gsw_FR', 'goog.i18n.DateTimeSymbols_gsw_LI', 'goog.i18n.DateTimeSymbols_gu_IN', 'goog.i18n.DateTimeSymbols_guz', 'goog.i18n.DateTimeSymbols_guz_KE', 'goog.i18n.DateTimeSymbols_gv', 'goog.i18n.DateTimeSymbols_gv_IM', 'goog.i18n.DateTimeSymbols_ha', 'goog.i18n.DateTimeSymbols_ha_Latn', 'goog.i18n.DateTimeSymbols_ha_Latn_GH', 'goog.i18n.DateTimeSymbols_ha_Latn_NE', 'goog.i18n.DateTimeSymbols_ha_Latn_NG', 'goog.i18n.DateTimeSymbols_haw_US', 'goog.i18n.DateTimeSymbols_he_IL', 'goog.i18n.DateTimeSymbols_hi_IN', 'goog.i18n.DateTimeSymbols_hr_BA', 'goog.i18n.DateTimeSymbols_hr_HR', 'goog.i18n.DateTimeSymbols_hsb', 'goog.i18n.DateTimeSymbols_hsb_DE', 'goog.i18n.DateTimeSymbols_hu_HU', 'goog.i18n.DateTimeSymbols_hy_AM', 'goog.i18n.DateTimeSymbols_ia', 'goog.i18n.DateTimeSymbols_ia_FR', 'goog.i18n.DateTimeSymbols_id_ID', 'goog.i18n.DateTimeSymbols_ig', 'goog.i18n.DateTimeSymbols_ig_NG', 'goog.i18n.DateTimeSymbols_ii', 'goog.i18n.DateTimeSymbols_ii_CN', 'goog.i18n.DateTimeSymbols_is_IS', 'goog.i18n.DateTimeSymbols_it_CH', 'goog.i18n.DateTimeSymbols_it_IT', 'goog.i18n.DateTimeSymbols_it_SM', 'goog.i18n.DateTimeSymbols_ja_JP', 'goog.i18n.DateTimeSymbols_jgo', 'goog.i18n.DateTimeSymbols_jgo_CM', 'goog.i18n.DateTimeSymbols_jmc', 'goog.i18n.DateTimeSymbols_jmc_TZ', 'goog.i18n.DateTimeSymbols_ka_GE', 'goog.i18n.DateTimeSymbols_kab', 'goog.i18n.DateTimeSymbols_kab_DZ', 'goog.i18n.DateTimeSymbols_kam', 'goog.i18n.DateTimeSymbols_kam_KE', 'goog.i18n.DateTimeSymbols_kde', 'goog.i18n.DateTimeSymbols_kde_TZ', 'goog.i18n.DateTimeSymbols_kea', 'goog.i18n.DateTimeSymbols_kea_CV', 'goog.i18n.DateTimeSymbols_khq', 'goog.i18n.DateTimeSymbols_khq_ML', 'goog.i18n.DateTimeSymbols_ki', 'goog.i18n.DateTimeSymbols_ki_KE', 'goog.i18n.DateTimeSymbols_kk_Cyrl', 'goog.i18n.DateTimeSymbols_kk_Cyrl_KZ', 'goog.i18n.DateTimeSymbols_kkj', 'goog.i18n.DateTimeSymbols_kkj_CM', 'goog.i18n.DateTimeSymbols_kl', 'goog.i18n.DateTimeSymbols_kl_GL', 'goog.i18n.DateTimeSymbols_kln', 'goog.i18n.DateTimeSymbols_kln_KE', 'goog.i18n.DateTimeSymbols_km_KH', 'goog.i18n.DateTimeSymbols_kn_IN', 'goog.i18n.DateTimeSymbols_ko_KP', 'goog.i18n.DateTimeSymbols_ko_KR', 'goog.i18n.DateTimeSymbols_kok', 'goog.i18n.DateTimeSymbols_kok_IN', 'goog.i18n.DateTimeSymbols_ks', 'goog.i18n.DateTimeSymbols_ks_Arab', 'goog.i18n.DateTimeSymbols_ks_Arab_IN', 'goog.i18n.DateTimeSymbols_ksb', 'goog.i18n.DateTimeSymbols_ksb_TZ', 'goog.i18n.DateTimeSymbols_ksf', 'goog.i18n.DateTimeSymbols_ksf_CM', 'goog.i18n.DateTimeSymbols_ksh', 'goog.i18n.DateTimeSymbols_ksh_DE', 'goog.i18n.DateTimeSymbols_kw', 'goog.i18n.DateTimeSymbols_kw_GB', 'goog.i18n.DateTimeSymbols_ky_Cyrl', 'goog.i18n.DateTimeSymbols_ky_Cyrl_KG', 'goog.i18n.DateTimeSymbols_lag', 'goog.i18n.DateTimeSymbols_lag_TZ', 'goog.i18n.DateTimeSymbols_lb', 'goog.i18n.DateTimeSymbols_lb_LU', 'goog.i18n.DateTimeSymbols_lg', 'goog.i18n.DateTimeSymbols_lg_UG', 'goog.i18n.DateTimeSymbols_lkt', 'goog.i18n.DateTimeSymbols_lkt_US', 'goog.i18n.DateTimeSymbols_ln_AO', 'goog.i18n.DateTimeSymbols_ln_CD', 'goog.i18n.DateTimeSymbols_ln_CF', 'goog.i18n.DateTimeSymbols_ln_CG', 'goog.i18n.DateTimeSymbols_lo_LA', 'goog.i18n.DateTimeSymbols_lt_LT', 'goog.i18n.DateTimeSymbols_lu', 'goog.i18n.DateTimeSymbols_lu_CD', 'goog.i18n.DateTimeSymbols_luo', 'goog.i18n.DateTimeSymbols_luo_KE', 'goog.i18n.DateTimeSymbols_luy', 'goog.i18n.DateTimeSymbols_luy_KE', 'goog.i18n.DateTimeSymbols_lv_LV', 'goog.i18n.DateTimeSymbols_mas', 'goog.i18n.DateTimeSymbols_mas_KE', 'goog.i18n.DateTimeSymbols_mas_TZ', 'goog.i18n.DateTimeSymbols_mer', 'goog.i18n.DateTimeSymbols_mer_KE', 'goog.i18n.DateTimeSymbols_mfe', 'goog.i18n.DateTimeSymbols_mfe_MU', 'goog.i18n.DateTimeSymbols_mg', 'goog.i18n.DateTimeSymbols_mg_MG', 'goog.i18n.DateTimeSymbols_mgh', 'goog.i18n.DateTimeSymbols_mgh_MZ', 'goog.i18n.DateTimeSymbols_mgo', 'goog.i18n.DateTimeSymbols_mgo_CM', 'goog.i18n.DateTimeSymbols_mk_MK', 'goog.i18n.DateTimeSymbols_ml_IN', 'goog.i18n.DateTimeSymbols_mn_Cyrl', 'goog.i18n.DateTimeSymbols_mn_Cyrl_MN', 'goog.i18n.DateTimeSymbols_mr_IN', 'goog.i18n.DateTimeSymbols_ms_Latn', 'goog.i18n.DateTimeSymbols_ms_Latn_BN', 'goog.i18n.DateTimeSymbols_ms_Latn_MY', 'goog.i18n.DateTimeSymbols_ms_Latn_SG', 'goog.i18n.DateTimeSymbols_mt_MT', 'goog.i18n.DateTimeSymbols_mua', 'goog.i18n.DateTimeSymbols_mua_CM', 'goog.i18n.DateTimeSymbols_my_MM', 'goog.i18n.DateTimeSymbols_naq', 'goog.i18n.DateTimeSymbols_naq_NA', 'goog.i18n.DateTimeSymbols_nb_NO', 'goog.i18n.DateTimeSymbols_nb_SJ', 'goog.i18n.DateTimeSymbols_nd', 'goog.i18n.DateTimeSymbols_nd_ZW', 'goog.i18n.DateTimeSymbols_ne_IN', 'goog.i18n.DateTimeSymbols_ne_NP', 'goog.i18n.DateTimeSymbols_nl_AW', 'goog.i18n.DateTimeSymbols_nl_BE', 'goog.i18n.DateTimeSymbols_nl_BQ', 'goog.i18n.DateTimeSymbols_nl_CW', 'goog.i18n.DateTimeSymbols_nl_NL', 'goog.i18n.DateTimeSymbols_nl_SR', 'goog.i18n.DateTimeSymbols_nl_SX', 'goog.i18n.DateTimeSymbols_nmg', 'goog.i18n.DateTimeSymbols_nmg_CM', 'goog.i18n.DateTimeSymbols_nn', 'goog.i18n.DateTimeSymbols_nn_NO', 'goog.i18n.DateTimeSymbols_nnh', 'goog.i18n.DateTimeSymbols_nnh_CM', 'goog.i18n.DateTimeSymbols_nr', 'goog.i18n.DateTimeSymbols_nr_ZA', 'goog.i18n.DateTimeSymbols_nso', 'goog.i18n.DateTimeSymbols_nso_ZA', 'goog.i18n.DateTimeSymbols_nus', 'goog.i18n.DateTimeSymbols_nus_SD', 'goog.i18n.DateTimeSymbols_nyn', 'goog.i18n.DateTimeSymbols_nyn_UG', 'goog.i18n.DateTimeSymbols_om', 'goog.i18n.DateTimeSymbols_om_ET', 'goog.i18n.DateTimeSymbols_om_KE', 'goog.i18n.DateTimeSymbols_or_IN', 'goog.i18n.DateTimeSymbols_os', 'goog.i18n.DateTimeSymbols_os_GE', 'goog.i18n.DateTimeSymbols_os_RU', 'goog.i18n.DateTimeSymbols_pa_Arab', 'goog.i18n.DateTimeSymbols_pa_Arab_PK', 'goog.i18n.DateTimeSymbols_pa_Guru', 'goog.i18n.DateTimeSymbols_pa_Guru_IN', 'goog.i18n.DateTimeSymbols_pl_PL', 'goog.i18n.DateTimeSymbols_ps', 'goog.i18n.DateTimeSymbols_ps_AF', 'goog.i18n.DateTimeSymbols_pt_AO', 'goog.i18n.DateTimeSymbols_pt_CV', 'goog.i18n.DateTimeSymbols_pt_GW', 'goog.i18n.DateTimeSymbols_pt_MO', 'goog.i18n.DateTimeSymbols_pt_MZ', 'goog.i18n.DateTimeSymbols_pt_ST', 'goog.i18n.DateTimeSymbols_pt_TL', 'goog.i18n.DateTimeSymbols_qu', 'goog.i18n.DateTimeSymbols_qu_BO', 'goog.i18n.DateTimeSymbols_qu_EC', 'goog.i18n.DateTimeSymbols_qu_PE', 'goog.i18n.DateTimeSymbols_rm', 'goog.i18n.DateTimeSymbols_rm_CH', 'goog.i18n.DateTimeSymbols_rn', 'goog.i18n.DateTimeSymbols_rn_BI', 'goog.i18n.DateTimeSymbols_ro_MD', 'goog.i18n.DateTimeSymbols_ro_RO', 'goog.i18n.DateTimeSymbols_rof', 'goog.i18n.DateTimeSymbols_rof_TZ', 'goog.i18n.DateTimeSymbols_ru_BY', 'goog.i18n.DateTimeSymbols_ru_KG', 'goog.i18n.DateTimeSymbols_ru_KZ', 'goog.i18n.DateTimeSymbols_ru_MD', 'goog.i18n.DateTimeSymbols_ru_RU', 'goog.i18n.DateTimeSymbols_ru_UA', 'goog.i18n.DateTimeSymbols_rw', 'goog.i18n.DateTimeSymbols_rw_RW', 'goog.i18n.DateTimeSymbols_rwk', 'goog.i18n.DateTimeSymbols_rwk_TZ', 'goog.i18n.DateTimeSymbols_sah', 'goog.i18n.DateTimeSymbols_sah_RU', 'goog.i18n.DateTimeSymbols_saq', 'goog.i18n.DateTimeSymbols_saq_KE', 'goog.i18n.DateTimeSymbols_sbp', 'goog.i18n.DateTimeSymbols_sbp_TZ', 'goog.i18n.DateTimeSymbols_se', 'goog.i18n.DateTimeSymbols_se_FI', 'goog.i18n.DateTimeSymbols_se_NO', 'goog.i18n.DateTimeSymbols_se_SE', 'goog.i18n.DateTimeSymbols_seh', 'goog.i18n.DateTimeSymbols_seh_MZ', 'goog.i18n.DateTimeSymbols_ses', 'goog.i18n.DateTimeSymbols_ses_ML', 'goog.i18n.DateTimeSymbols_sg', 'goog.i18n.DateTimeSymbols_sg_CF', 'goog.i18n.DateTimeSymbols_shi', 'goog.i18n.DateTimeSymbols_shi_Latn', 'goog.i18n.DateTimeSymbols_shi_Latn_MA', 'goog.i18n.DateTimeSymbols_shi_Tfng', 'goog.i18n.DateTimeSymbols_shi_Tfng_MA', 'goog.i18n.DateTimeSymbols_si_LK', 'goog.i18n.DateTimeSymbols_sk_SK', 'goog.i18n.DateTimeSymbols_sl_SI', 'goog.i18n.DateTimeSymbols_smn', 'goog.i18n.DateTimeSymbols_smn_FI', 'goog.i18n.DateTimeSymbols_sn', 'goog.i18n.DateTimeSymbols_sn_ZW', 'goog.i18n.DateTimeSymbols_so', 'goog.i18n.DateTimeSymbols_so_DJ', 'goog.i18n.DateTimeSymbols_so_ET', 'goog.i18n.DateTimeSymbols_so_KE', 'goog.i18n.DateTimeSymbols_so_SO', 'goog.i18n.DateTimeSymbols_sq_AL', 'goog.i18n.DateTimeSymbols_sq_MK', 'goog.i18n.DateTimeSymbols_sq_XK', 'goog.i18n.DateTimeSymbols_sr_Cyrl', 'goog.i18n.DateTimeSymbols_sr_Cyrl_BA', 'goog.i18n.DateTimeSymbols_sr_Cyrl_ME', 'goog.i18n.DateTimeSymbols_sr_Cyrl_RS', 'goog.i18n.DateTimeSymbols_sr_Cyrl_XK', 'goog.i18n.DateTimeSymbols_sr_Latn', 'goog.i18n.DateTimeSymbols_sr_Latn_BA', 'goog.i18n.DateTimeSymbols_sr_Latn_ME', 'goog.i18n.DateTimeSymbols_sr_Latn_RS', 'goog.i18n.DateTimeSymbols_sr_Latn_XK', 'goog.i18n.DateTimeSymbols_ss', 'goog.i18n.DateTimeSymbols_ss_SZ', 'goog.i18n.DateTimeSymbols_ss_ZA', 'goog.i18n.DateTimeSymbols_ssy', 'goog.i18n.DateTimeSymbols_ssy_ER', 'goog.i18n.DateTimeSymbols_sv_AX', 'goog.i18n.DateTimeSymbols_sv_FI', 'goog.i18n.DateTimeSymbols_sv_SE', 'goog.i18n.DateTimeSymbols_sw_KE', 'goog.i18n.DateTimeSymbols_sw_TZ', 'goog.i18n.DateTimeSymbols_sw_UG', 'goog.i18n.DateTimeSymbols_swc', 'goog.i18n.DateTimeSymbols_swc_CD', 'goog.i18n.DateTimeSymbols_ta_IN', 'goog.i18n.DateTimeSymbols_ta_LK', 'goog.i18n.DateTimeSymbols_ta_MY', 'goog.i18n.DateTimeSymbols_ta_SG', 'goog.i18n.DateTimeSymbols_te_IN', 'goog.i18n.DateTimeSymbols_teo', 'goog.i18n.DateTimeSymbols_teo_KE', 'goog.i18n.DateTimeSymbols_teo_UG', 'goog.i18n.DateTimeSymbols_th_TH', 'goog.i18n.DateTimeSymbols_ti', 'goog.i18n.DateTimeSymbols_ti_ER', 'goog.i18n.DateTimeSymbols_ti_ET', 'goog.i18n.DateTimeSymbols_tn', 'goog.i18n.DateTimeSymbols_tn_BW', 'goog.i18n.DateTimeSymbols_tn_ZA', 'goog.i18n.DateTimeSymbols_to', 'goog.i18n.DateTimeSymbols_to_TO', 'goog.i18n.DateTimeSymbols_tr_CY', 'goog.i18n.DateTimeSymbols_tr_TR', 'goog.i18n.DateTimeSymbols_ts', 'goog.i18n.DateTimeSymbols_ts_ZA', 'goog.i18n.DateTimeSymbols_twq', 'goog.i18n.DateTimeSymbols_twq_NE', 'goog.i18n.DateTimeSymbols_tzm', 'goog.i18n.DateTimeSymbols_tzm_Latn', 'goog.i18n.DateTimeSymbols_tzm_Latn_MA', 'goog.i18n.DateTimeSymbols_ug', 'goog.i18n.DateTimeSymbols_ug_Arab', 'goog.i18n.DateTimeSymbols_ug_Arab_CN', 'goog.i18n.DateTimeSymbols_uk_UA', 'goog.i18n.DateTimeSymbols_ur_IN', 'goog.i18n.DateTimeSymbols_ur_PK', 'goog.i18n.DateTimeSymbols_uz_Arab', 'goog.i18n.DateTimeSymbols_uz_Arab_AF', 'goog.i18n.DateTimeSymbols_uz_Cyrl', 'goog.i18n.DateTimeSymbols_uz_Cyrl_UZ', 'goog.i18n.DateTimeSymbols_uz_Latn', 'goog.i18n.DateTimeSymbols_uz_Latn_UZ', 'goog.i18n.DateTimeSymbols_vai', 'goog.i18n.DateTimeSymbols_vai_Latn', 'goog.i18n.DateTimeSymbols_vai_Latn_LR', 'goog.i18n.DateTimeSymbols_vai_Vaii', 'goog.i18n.DateTimeSymbols_vai_Vaii_LR', 'goog.i18n.DateTimeSymbols_ve', 'goog.i18n.DateTimeSymbols_ve_ZA', 'goog.i18n.DateTimeSymbols_vi_VN', 'goog.i18n.DateTimeSymbols_vo', 'goog.i18n.DateTimeSymbols_vo_001', 'goog.i18n.DateTimeSymbols_vun', 'goog.i18n.DateTimeSymbols_vun_TZ', 'goog.i18n.DateTimeSymbols_wae', 'goog.i18n.DateTimeSymbols_wae_CH', 'goog.i18n.DateTimeSymbols_xog', 'goog.i18n.DateTimeSymbols_xog_UG', 'goog.i18n.DateTimeSymbols_yav', 'goog.i18n.DateTimeSymbols_yav_CM', 'goog.i18n.DateTimeSymbols_yi', 'goog.i18n.DateTimeSymbols_yi_001', 'goog.i18n.DateTimeSymbols_yo', 'goog.i18n.DateTimeSymbols_yo_BJ', 'goog.i18n.DateTimeSymbols_yo_NG', 'goog.i18n.DateTimeSymbols_zgh', 'goog.i18n.DateTimeSymbols_zgh_MA', 'goog.i18n.DateTimeSymbols_zh_Hans', 'goog.i18n.DateTimeSymbols_zh_Hans_CN', 'goog.i18n.DateTimeSymbols_zh_Hans_HK', 'goog.i18n.DateTimeSymbols_zh_Hans_MO', 'goog.i18n.DateTimeSymbols_zh_Hans_SG', 'goog.i18n.DateTimeSymbols_zh_Hant', 'goog.i18n.DateTimeSymbols_zh_Hant_HK', 'goog.i18n.DateTimeSymbols_zh_Hant_MO', 'goog.i18n.DateTimeSymbols_zh_Hant_TW', 'goog.i18n.DateTimeSymbols_zu_ZA'], ['goog.i18n.DateTimeSymbols'], false); -goog.addDependency('i18n/graphemebreak.js', ['goog.i18n.GraphemeBreak'], ['goog.structs.InversionMap'], false); -goog.addDependency('i18n/graphemebreak_test.js', ['goog.i18n.GraphemeBreakTest'], ['goog.i18n.GraphemeBreak', 'goog.testing.jsunit'], false); -goog.addDependency('i18n/messageformat.js', ['goog.i18n.MessageFormat'], ['goog.asserts', 'goog.i18n.NumberFormat', 'goog.i18n.ordinalRules', 'goog.i18n.pluralRules'], false); -goog.addDependency('i18n/messageformat_test.js', ['goog.i18n.MessageFormatTest'], ['goog.i18n.MessageFormat', 'goog.i18n.NumberFormatSymbols_hr', 'goog.i18n.pluralRules', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false); -goog.addDependency('i18n/mime.js', ['goog.i18n.mime', 'goog.i18n.mime.encode'], ['goog.array'], false); -goog.addDependency('i18n/mime_test.js', ['goog.i18n.mime.encodeTest'], ['goog.i18n.mime.encode', 'goog.testing.jsunit'], false); -goog.addDependency('i18n/numberformat.js', ['goog.i18n.NumberFormat', 'goog.i18n.NumberFormat.CurrencyStyle', 'goog.i18n.NumberFormat.Format'], ['goog.asserts', 'goog.i18n.CompactNumberFormatSymbols', 'goog.i18n.NumberFormatSymbols', 'goog.i18n.currency', 'goog.math'], false); -goog.addDependency('i18n/numberformat_test.js', ['goog.i18n.NumberFormatTest'], ['goog.i18n.CompactNumberFormatSymbols', 'goog.i18n.CompactNumberFormatSymbols_de', 'goog.i18n.CompactNumberFormatSymbols_en', 'goog.i18n.CompactNumberFormatSymbols_fr', 'goog.i18n.NumberFormat', 'goog.i18n.NumberFormatSymbols', 'goog.i18n.NumberFormatSymbols_de', 'goog.i18n.NumberFormatSymbols_en', 'goog.i18n.NumberFormatSymbols_fr', 'goog.i18n.NumberFormatSymbols_pl', 'goog.i18n.NumberFormatSymbols_ro', 'goog.testing.ExpectedFailures', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.product', 'goog.userAgent.product.isVersion'], false); -goog.addDependency('i18n/numberformatsymbols.js', ['goog.i18n.NumberFormatSymbols', 'goog.i18n.NumberFormatSymbols_af', 'goog.i18n.NumberFormatSymbols_af_ZA', 'goog.i18n.NumberFormatSymbols_am', 'goog.i18n.NumberFormatSymbols_am_ET', 'goog.i18n.NumberFormatSymbols_ar', 'goog.i18n.NumberFormatSymbols_ar_001', 'goog.i18n.NumberFormatSymbols_az', 'goog.i18n.NumberFormatSymbols_az_Latn_AZ', 'goog.i18n.NumberFormatSymbols_bg', 'goog.i18n.NumberFormatSymbols_bg_BG', 'goog.i18n.NumberFormatSymbols_bn', 'goog.i18n.NumberFormatSymbols_bn_BD', 'goog.i18n.NumberFormatSymbols_br', 'goog.i18n.NumberFormatSymbols_br_FR', 'goog.i18n.NumberFormatSymbols_ca', 'goog.i18n.NumberFormatSymbols_ca_AD', 'goog.i18n.NumberFormatSymbols_ca_ES', 'goog.i18n.NumberFormatSymbols_ca_ES_VALENCIA', 'goog.i18n.NumberFormatSymbols_ca_FR', 'goog.i18n.NumberFormatSymbols_ca_IT', 'goog.i18n.NumberFormatSymbols_chr', 'goog.i18n.NumberFormatSymbols_chr_US', 'goog.i18n.NumberFormatSymbols_cs', 'goog.i18n.NumberFormatSymbols_cs_CZ', 'goog.i18n.NumberFormatSymbols_cy', 'goog.i18n.NumberFormatSymbols_cy_GB', 'goog.i18n.NumberFormatSymbols_da', 'goog.i18n.NumberFormatSymbols_da_DK', 'goog.i18n.NumberFormatSymbols_da_GL', 'goog.i18n.NumberFormatSymbols_de', 'goog.i18n.NumberFormatSymbols_de_AT', 'goog.i18n.NumberFormatSymbols_de_BE', 'goog.i18n.NumberFormatSymbols_de_CH', 'goog.i18n.NumberFormatSymbols_de_DE', 'goog.i18n.NumberFormatSymbols_de_LU', 'goog.i18n.NumberFormatSymbols_el', 'goog.i18n.NumberFormatSymbols_el_GR', 'goog.i18n.NumberFormatSymbols_en', 'goog.i18n.NumberFormatSymbols_en_001', 'goog.i18n.NumberFormatSymbols_en_AS', 'goog.i18n.NumberFormatSymbols_en_AU', 'goog.i18n.NumberFormatSymbols_en_DG', 'goog.i18n.NumberFormatSymbols_en_FM', 'goog.i18n.NumberFormatSymbols_en_GB', 'goog.i18n.NumberFormatSymbols_en_GU', 'goog.i18n.NumberFormatSymbols_en_IE', 'goog.i18n.NumberFormatSymbols_en_IN', 'goog.i18n.NumberFormatSymbols_en_IO', 'goog.i18n.NumberFormatSymbols_en_MH', 'goog.i18n.NumberFormatSymbols_en_MP', 'goog.i18n.NumberFormatSymbols_en_PR', 'goog.i18n.NumberFormatSymbols_en_PW', 'goog.i18n.NumberFormatSymbols_en_SG', 'goog.i18n.NumberFormatSymbols_en_TC', 'goog.i18n.NumberFormatSymbols_en_UM', 'goog.i18n.NumberFormatSymbols_en_US', 'goog.i18n.NumberFormatSymbols_en_VG', 'goog.i18n.NumberFormatSymbols_en_VI', 'goog.i18n.NumberFormatSymbols_en_ZA', 'goog.i18n.NumberFormatSymbols_en_ZW', 'goog.i18n.NumberFormatSymbols_es', 'goog.i18n.NumberFormatSymbols_es_419', 'goog.i18n.NumberFormatSymbols_es_EA', 'goog.i18n.NumberFormatSymbols_es_ES', 'goog.i18n.NumberFormatSymbols_es_IC', 'goog.i18n.NumberFormatSymbols_et', 'goog.i18n.NumberFormatSymbols_et_EE', 'goog.i18n.NumberFormatSymbols_eu', 'goog.i18n.NumberFormatSymbols_eu_ES', 'goog.i18n.NumberFormatSymbols_fa', 'goog.i18n.NumberFormatSymbols_fa_IR', 'goog.i18n.NumberFormatSymbols_fi', 'goog.i18n.NumberFormatSymbols_fi_FI', 'goog.i18n.NumberFormatSymbols_fil', 'goog.i18n.NumberFormatSymbols_fil_PH', 'goog.i18n.NumberFormatSymbols_fr', 'goog.i18n.NumberFormatSymbols_fr_BL', 'goog.i18n.NumberFormatSymbols_fr_CA', 'goog.i18n.NumberFormatSymbols_fr_FR', 'goog.i18n.NumberFormatSymbols_fr_GF', 'goog.i18n.NumberFormatSymbols_fr_GP', 'goog.i18n.NumberFormatSymbols_fr_MC', 'goog.i18n.NumberFormatSymbols_fr_MF', 'goog.i18n.NumberFormatSymbols_fr_MQ', 'goog.i18n.NumberFormatSymbols_fr_PM', 'goog.i18n.NumberFormatSymbols_fr_RE', 'goog.i18n.NumberFormatSymbols_fr_YT', 'goog.i18n.NumberFormatSymbols_ga', 'goog.i18n.NumberFormatSymbols_ga_IE', 'goog.i18n.NumberFormatSymbols_gl', 'goog.i18n.NumberFormatSymbols_gl_ES', 'goog.i18n.NumberFormatSymbols_gsw', 'goog.i18n.NumberFormatSymbols_gsw_CH', 'goog.i18n.NumberFormatSymbols_gsw_LI', 'goog.i18n.NumberFormatSymbols_gu', 'goog.i18n.NumberFormatSymbols_gu_IN', 'goog.i18n.NumberFormatSymbols_haw', 'goog.i18n.NumberFormatSymbols_haw_US', 'goog.i18n.NumberFormatSymbols_he', 'goog.i18n.NumberFormatSymbols_he_IL', 'goog.i18n.NumberFormatSymbols_hi', 'goog.i18n.NumberFormatSymbols_hi_IN', 'goog.i18n.NumberFormatSymbols_hr', 'goog.i18n.NumberFormatSymbols_hr_HR', 'goog.i18n.NumberFormatSymbols_hu', 'goog.i18n.NumberFormatSymbols_hu_HU', 'goog.i18n.NumberFormatSymbols_hy', 'goog.i18n.NumberFormatSymbols_hy_AM', 'goog.i18n.NumberFormatSymbols_id', 'goog.i18n.NumberFormatSymbols_id_ID', 'goog.i18n.NumberFormatSymbols_in', 'goog.i18n.NumberFormatSymbols_is', 'goog.i18n.NumberFormatSymbols_is_IS', 'goog.i18n.NumberFormatSymbols_it', 'goog.i18n.NumberFormatSymbols_it_IT', 'goog.i18n.NumberFormatSymbols_it_SM', 'goog.i18n.NumberFormatSymbols_iw', 'goog.i18n.NumberFormatSymbols_ja', 'goog.i18n.NumberFormatSymbols_ja_JP', 'goog.i18n.NumberFormatSymbols_ka', 'goog.i18n.NumberFormatSymbols_ka_GE', 'goog.i18n.NumberFormatSymbols_kk', 'goog.i18n.NumberFormatSymbols_kk_Cyrl_KZ', 'goog.i18n.NumberFormatSymbols_km', 'goog.i18n.NumberFormatSymbols_km_KH', 'goog.i18n.NumberFormatSymbols_kn', 'goog.i18n.NumberFormatSymbols_kn_IN', 'goog.i18n.NumberFormatSymbols_ko', 'goog.i18n.NumberFormatSymbols_ko_KR', 'goog.i18n.NumberFormatSymbols_ky', 'goog.i18n.NumberFormatSymbols_ky_Cyrl_KG', 'goog.i18n.NumberFormatSymbols_ln', 'goog.i18n.NumberFormatSymbols_ln_CD', 'goog.i18n.NumberFormatSymbols_lo', 'goog.i18n.NumberFormatSymbols_lo_LA', 'goog.i18n.NumberFormatSymbols_lt', 'goog.i18n.NumberFormatSymbols_lt_LT', 'goog.i18n.NumberFormatSymbols_lv', 'goog.i18n.NumberFormatSymbols_lv_LV', 'goog.i18n.NumberFormatSymbols_mk', 'goog.i18n.NumberFormatSymbols_mk_MK', 'goog.i18n.NumberFormatSymbols_ml', 'goog.i18n.NumberFormatSymbols_ml_IN', 'goog.i18n.NumberFormatSymbols_mn', 'goog.i18n.NumberFormatSymbols_mn_Cyrl_MN', 'goog.i18n.NumberFormatSymbols_mr', 'goog.i18n.NumberFormatSymbols_mr_IN', 'goog.i18n.NumberFormatSymbols_ms', 'goog.i18n.NumberFormatSymbols_ms_Latn_MY', 'goog.i18n.NumberFormatSymbols_mt', 'goog.i18n.NumberFormatSymbols_mt_MT', 'goog.i18n.NumberFormatSymbols_my', 'goog.i18n.NumberFormatSymbols_my_MM', 'goog.i18n.NumberFormatSymbols_nb', 'goog.i18n.NumberFormatSymbols_nb_NO', 'goog.i18n.NumberFormatSymbols_nb_SJ', 'goog.i18n.NumberFormatSymbols_ne', 'goog.i18n.NumberFormatSymbols_ne_NP', 'goog.i18n.NumberFormatSymbols_nl', 'goog.i18n.NumberFormatSymbols_nl_NL', 'goog.i18n.NumberFormatSymbols_no', 'goog.i18n.NumberFormatSymbols_no_NO', 'goog.i18n.NumberFormatSymbols_or', 'goog.i18n.NumberFormatSymbols_or_IN', 'goog.i18n.NumberFormatSymbols_pa', 'goog.i18n.NumberFormatSymbols_pa_Guru_IN', 'goog.i18n.NumberFormatSymbols_pl', 'goog.i18n.NumberFormatSymbols_pl_PL', 'goog.i18n.NumberFormatSymbols_pt', 'goog.i18n.NumberFormatSymbols_pt_BR', 'goog.i18n.NumberFormatSymbols_pt_PT', 'goog.i18n.NumberFormatSymbols_ro', 'goog.i18n.NumberFormatSymbols_ro_RO', 'goog.i18n.NumberFormatSymbols_ru', 'goog.i18n.NumberFormatSymbols_ru_RU', 'goog.i18n.NumberFormatSymbols_si', 'goog.i18n.NumberFormatSymbols_si_LK', 'goog.i18n.NumberFormatSymbols_sk', 'goog.i18n.NumberFormatSymbols_sk_SK', 'goog.i18n.NumberFormatSymbols_sl', 'goog.i18n.NumberFormatSymbols_sl_SI', 'goog.i18n.NumberFormatSymbols_sq', 'goog.i18n.NumberFormatSymbols_sq_AL', 'goog.i18n.NumberFormatSymbols_sr', 'goog.i18n.NumberFormatSymbols_sr_Cyrl_RS', 'goog.i18n.NumberFormatSymbols_sv', 'goog.i18n.NumberFormatSymbols_sv_SE', 'goog.i18n.NumberFormatSymbols_sw', 'goog.i18n.NumberFormatSymbols_sw_TZ', 'goog.i18n.NumberFormatSymbols_ta', 'goog.i18n.NumberFormatSymbols_ta_IN', 'goog.i18n.NumberFormatSymbols_te', 'goog.i18n.NumberFormatSymbols_te_IN', 'goog.i18n.NumberFormatSymbols_th', 'goog.i18n.NumberFormatSymbols_th_TH', 'goog.i18n.NumberFormatSymbols_tl', 'goog.i18n.NumberFormatSymbols_tr', 'goog.i18n.NumberFormatSymbols_tr_TR', 'goog.i18n.NumberFormatSymbols_uk', 'goog.i18n.NumberFormatSymbols_uk_UA', 'goog.i18n.NumberFormatSymbols_ur', 'goog.i18n.NumberFormatSymbols_ur_PK', 'goog.i18n.NumberFormatSymbols_uz', 'goog.i18n.NumberFormatSymbols_uz_Latn_UZ', 'goog.i18n.NumberFormatSymbols_vi', 'goog.i18n.NumberFormatSymbols_vi_VN', 'goog.i18n.NumberFormatSymbols_zh', 'goog.i18n.NumberFormatSymbols_zh_CN', 'goog.i18n.NumberFormatSymbols_zh_HK', 'goog.i18n.NumberFormatSymbols_zh_Hans_CN', 'goog.i18n.NumberFormatSymbols_zh_TW', 'goog.i18n.NumberFormatSymbols_zu', 'goog.i18n.NumberFormatSymbols_zu_ZA'], [], false); -goog.addDependency('i18n/numberformatsymbolsext.js', ['goog.i18n.NumberFormatSymbolsExt', 'goog.i18n.NumberFormatSymbols_aa', 'goog.i18n.NumberFormatSymbols_aa_DJ', 'goog.i18n.NumberFormatSymbols_aa_ER', 'goog.i18n.NumberFormatSymbols_aa_ET', 'goog.i18n.NumberFormatSymbols_af_NA', 'goog.i18n.NumberFormatSymbols_agq', 'goog.i18n.NumberFormatSymbols_agq_CM', 'goog.i18n.NumberFormatSymbols_ak', 'goog.i18n.NumberFormatSymbols_ak_GH', 'goog.i18n.NumberFormatSymbols_ar_AE', 'goog.i18n.NumberFormatSymbols_ar_BH', 'goog.i18n.NumberFormatSymbols_ar_DJ', 'goog.i18n.NumberFormatSymbols_ar_DZ', 'goog.i18n.NumberFormatSymbols_ar_EG', 'goog.i18n.NumberFormatSymbols_ar_EH', 'goog.i18n.NumberFormatSymbols_ar_ER', 'goog.i18n.NumberFormatSymbols_ar_IL', 'goog.i18n.NumberFormatSymbols_ar_IQ', 'goog.i18n.NumberFormatSymbols_ar_JO', 'goog.i18n.NumberFormatSymbols_ar_KM', 'goog.i18n.NumberFormatSymbols_ar_KW', 'goog.i18n.NumberFormatSymbols_ar_LB', 'goog.i18n.NumberFormatSymbols_ar_LY', 'goog.i18n.NumberFormatSymbols_ar_MA', 'goog.i18n.NumberFormatSymbols_ar_MR', 'goog.i18n.NumberFormatSymbols_ar_OM', 'goog.i18n.NumberFormatSymbols_ar_PS', 'goog.i18n.NumberFormatSymbols_ar_QA', 'goog.i18n.NumberFormatSymbols_ar_SA', 'goog.i18n.NumberFormatSymbols_ar_SD', 'goog.i18n.NumberFormatSymbols_ar_SO', 'goog.i18n.NumberFormatSymbols_ar_SS', 'goog.i18n.NumberFormatSymbols_ar_SY', 'goog.i18n.NumberFormatSymbols_ar_TD', 'goog.i18n.NumberFormatSymbols_ar_TN', 'goog.i18n.NumberFormatSymbols_ar_YE', 'goog.i18n.NumberFormatSymbols_as', 'goog.i18n.NumberFormatSymbols_as_IN', 'goog.i18n.NumberFormatSymbols_asa', 'goog.i18n.NumberFormatSymbols_asa_TZ', 'goog.i18n.NumberFormatSymbols_ast', 'goog.i18n.NumberFormatSymbols_ast_ES', 'goog.i18n.NumberFormatSymbols_az_Cyrl', 'goog.i18n.NumberFormatSymbols_az_Cyrl_AZ', 'goog.i18n.NumberFormatSymbols_az_Latn', 'goog.i18n.NumberFormatSymbols_bas', 'goog.i18n.NumberFormatSymbols_bas_CM', 'goog.i18n.NumberFormatSymbols_be', 'goog.i18n.NumberFormatSymbols_be_BY', 'goog.i18n.NumberFormatSymbols_bem', 'goog.i18n.NumberFormatSymbols_bem_ZM', 'goog.i18n.NumberFormatSymbols_bez', 'goog.i18n.NumberFormatSymbols_bez_TZ', 'goog.i18n.NumberFormatSymbols_bm', 'goog.i18n.NumberFormatSymbols_bm_Latn', 'goog.i18n.NumberFormatSymbols_bm_Latn_ML', 'goog.i18n.NumberFormatSymbols_bn_IN', 'goog.i18n.NumberFormatSymbols_bo', 'goog.i18n.NumberFormatSymbols_bo_CN', 'goog.i18n.NumberFormatSymbols_bo_IN', 'goog.i18n.NumberFormatSymbols_brx', 'goog.i18n.NumberFormatSymbols_brx_IN', 'goog.i18n.NumberFormatSymbols_bs', 'goog.i18n.NumberFormatSymbols_bs_Cyrl', 'goog.i18n.NumberFormatSymbols_bs_Cyrl_BA', 'goog.i18n.NumberFormatSymbols_bs_Latn', 'goog.i18n.NumberFormatSymbols_bs_Latn_BA', 'goog.i18n.NumberFormatSymbols_cgg', 'goog.i18n.NumberFormatSymbols_cgg_UG', 'goog.i18n.NumberFormatSymbols_ckb', 'goog.i18n.NumberFormatSymbols_ckb_Arab', 'goog.i18n.NumberFormatSymbols_ckb_Arab_IQ', 'goog.i18n.NumberFormatSymbols_ckb_Arab_IR', 'goog.i18n.NumberFormatSymbols_ckb_IQ', 'goog.i18n.NumberFormatSymbols_ckb_IR', 'goog.i18n.NumberFormatSymbols_ckb_Latn', 'goog.i18n.NumberFormatSymbols_ckb_Latn_IQ', 'goog.i18n.NumberFormatSymbols_dav', 'goog.i18n.NumberFormatSymbols_dav_KE', 'goog.i18n.NumberFormatSymbols_de_LI', 'goog.i18n.NumberFormatSymbols_dje', 'goog.i18n.NumberFormatSymbols_dje_NE', 'goog.i18n.NumberFormatSymbols_dsb', 'goog.i18n.NumberFormatSymbols_dsb_DE', 'goog.i18n.NumberFormatSymbols_dua', 'goog.i18n.NumberFormatSymbols_dua_CM', 'goog.i18n.NumberFormatSymbols_dyo', 'goog.i18n.NumberFormatSymbols_dyo_SN', 'goog.i18n.NumberFormatSymbols_dz', 'goog.i18n.NumberFormatSymbols_dz_BT', 'goog.i18n.NumberFormatSymbols_ebu', 'goog.i18n.NumberFormatSymbols_ebu_KE', 'goog.i18n.NumberFormatSymbols_ee', 'goog.i18n.NumberFormatSymbols_ee_GH', 'goog.i18n.NumberFormatSymbols_ee_TG', 'goog.i18n.NumberFormatSymbols_el_CY', 'goog.i18n.NumberFormatSymbols_en_150', 'goog.i18n.NumberFormatSymbols_en_AG', 'goog.i18n.NumberFormatSymbols_en_AI', 'goog.i18n.NumberFormatSymbols_en_BB', 'goog.i18n.NumberFormatSymbols_en_BE', 'goog.i18n.NumberFormatSymbols_en_BM', 'goog.i18n.NumberFormatSymbols_en_BS', 'goog.i18n.NumberFormatSymbols_en_BW', 'goog.i18n.NumberFormatSymbols_en_BZ', 'goog.i18n.NumberFormatSymbols_en_CA', 'goog.i18n.NumberFormatSymbols_en_CC', 'goog.i18n.NumberFormatSymbols_en_CK', 'goog.i18n.NumberFormatSymbols_en_CM', 'goog.i18n.NumberFormatSymbols_en_CX', 'goog.i18n.NumberFormatSymbols_en_DM', 'goog.i18n.NumberFormatSymbols_en_ER', 'goog.i18n.NumberFormatSymbols_en_FJ', 'goog.i18n.NumberFormatSymbols_en_FK', 'goog.i18n.NumberFormatSymbols_en_GD', 'goog.i18n.NumberFormatSymbols_en_GG', 'goog.i18n.NumberFormatSymbols_en_GH', 'goog.i18n.NumberFormatSymbols_en_GI', 'goog.i18n.NumberFormatSymbols_en_GM', 'goog.i18n.NumberFormatSymbols_en_GY', 'goog.i18n.NumberFormatSymbols_en_HK', 'goog.i18n.NumberFormatSymbols_en_IM', 'goog.i18n.NumberFormatSymbols_en_JE', 'goog.i18n.NumberFormatSymbols_en_JM', 'goog.i18n.NumberFormatSymbols_en_KE', 'goog.i18n.NumberFormatSymbols_en_KI', 'goog.i18n.NumberFormatSymbols_en_KN', 'goog.i18n.NumberFormatSymbols_en_KY', 'goog.i18n.NumberFormatSymbols_en_LC', 'goog.i18n.NumberFormatSymbols_en_LR', 'goog.i18n.NumberFormatSymbols_en_LS', 'goog.i18n.NumberFormatSymbols_en_MG', 'goog.i18n.NumberFormatSymbols_en_MO', 'goog.i18n.NumberFormatSymbols_en_MS', 'goog.i18n.NumberFormatSymbols_en_MT', 'goog.i18n.NumberFormatSymbols_en_MU', 'goog.i18n.NumberFormatSymbols_en_MW', 'goog.i18n.NumberFormatSymbols_en_MY', 'goog.i18n.NumberFormatSymbols_en_NA', 'goog.i18n.NumberFormatSymbols_en_NF', 'goog.i18n.NumberFormatSymbols_en_NG', 'goog.i18n.NumberFormatSymbols_en_NR', 'goog.i18n.NumberFormatSymbols_en_NU', 'goog.i18n.NumberFormatSymbols_en_NZ', 'goog.i18n.NumberFormatSymbols_en_PG', 'goog.i18n.NumberFormatSymbols_en_PH', 'goog.i18n.NumberFormatSymbols_en_PK', 'goog.i18n.NumberFormatSymbols_en_PN', 'goog.i18n.NumberFormatSymbols_en_RW', 'goog.i18n.NumberFormatSymbols_en_SB', 'goog.i18n.NumberFormatSymbols_en_SC', 'goog.i18n.NumberFormatSymbols_en_SD', 'goog.i18n.NumberFormatSymbols_en_SH', 'goog.i18n.NumberFormatSymbols_en_SL', 'goog.i18n.NumberFormatSymbols_en_SS', 'goog.i18n.NumberFormatSymbols_en_SX', 'goog.i18n.NumberFormatSymbols_en_SZ', 'goog.i18n.NumberFormatSymbols_en_TK', 'goog.i18n.NumberFormatSymbols_en_TO', 'goog.i18n.NumberFormatSymbols_en_TT', 'goog.i18n.NumberFormatSymbols_en_TV', 'goog.i18n.NumberFormatSymbols_en_TZ', 'goog.i18n.NumberFormatSymbols_en_UG', 'goog.i18n.NumberFormatSymbols_en_VC', 'goog.i18n.NumberFormatSymbols_en_VU', 'goog.i18n.NumberFormatSymbols_en_WS', 'goog.i18n.NumberFormatSymbols_en_ZM', 'goog.i18n.NumberFormatSymbols_eo', 'goog.i18n.NumberFormatSymbols_eo_001', 'goog.i18n.NumberFormatSymbols_es_AR', 'goog.i18n.NumberFormatSymbols_es_BO', 'goog.i18n.NumberFormatSymbols_es_CL', 'goog.i18n.NumberFormatSymbols_es_CO', 'goog.i18n.NumberFormatSymbols_es_CR', 'goog.i18n.NumberFormatSymbols_es_CU', 'goog.i18n.NumberFormatSymbols_es_DO', 'goog.i18n.NumberFormatSymbols_es_EC', 'goog.i18n.NumberFormatSymbols_es_GQ', 'goog.i18n.NumberFormatSymbols_es_GT', 'goog.i18n.NumberFormatSymbols_es_HN', 'goog.i18n.NumberFormatSymbols_es_MX', 'goog.i18n.NumberFormatSymbols_es_NI', 'goog.i18n.NumberFormatSymbols_es_PA', 'goog.i18n.NumberFormatSymbols_es_PE', 'goog.i18n.NumberFormatSymbols_es_PH', 'goog.i18n.NumberFormatSymbols_es_PR', 'goog.i18n.NumberFormatSymbols_es_PY', 'goog.i18n.NumberFormatSymbols_es_SV', 'goog.i18n.NumberFormatSymbols_es_US', 'goog.i18n.NumberFormatSymbols_es_UY', 'goog.i18n.NumberFormatSymbols_es_VE', 'goog.i18n.NumberFormatSymbols_ewo', 'goog.i18n.NumberFormatSymbols_ewo_CM', 'goog.i18n.NumberFormatSymbols_fa_AF', 'goog.i18n.NumberFormatSymbols_ff', 'goog.i18n.NumberFormatSymbols_ff_CM', 'goog.i18n.NumberFormatSymbols_ff_GN', 'goog.i18n.NumberFormatSymbols_ff_MR', 'goog.i18n.NumberFormatSymbols_ff_SN', 'goog.i18n.NumberFormatSymbols_fo', 'goog.i18n.NumberFormatSymbols_fo_FO', 'goog.i18n.NumberFormatSymbols_fr_BE', 'goog.i18n.NumberFormatSymbols_fr_BF', 'goog.i18n.NumberFormatSymbols_fr_BI', 'goog.i18n.NumberFormatSymbols_fr_BJ', 'goog.i18n.NumberFormatSymbols_fr_CD', 'goog.i18n.NumberFormatSymbols_fr_CF', 'goog.i18n.NumberFormatSymbols_fr_CG', 'goog.i18n.NumberFormatSymbols_fr_CH', 'goog.i18n.NumberFormatSymbols_fr_CI', 'goog.i18n.NumberFormatSymbols_fr_CM', 'goog.i18n.NumberFormatSymbols_fr_DJ', 'goog.i18n.NumberFormatSymbols_fr_DZ', 'goog.i18n.NumberFormatSymbols_fr_GA', 'goog.i18n.NumberFormatSymbols_fr_GN', 'goog.i18n.NumberFormatSymbols_fr_GQ', 'goog.i18n.NumberFormatSymbols_fr_HT', 'goog.i18n.NumberFormatSymbols_fr_KM', 'goog.i18n.NumberFormatSymbols_fr_LU', 'goog.i18n.NumberFormatSymbols_fr_MA', 'goog.i18n.NumberFormatSymbols_fr_MG', 'goog.i18n.NumberFormatSymbols_fr_ML', 'goog.i18n.NumberFormatSymbols_fr_MR', 'goog.i18n.NumberFormatSymbols_fr_MU', 'goog.i18n.NumberFormatSymbols_fr_NC', 'goog.i18n.NumberFormatSymbols_fr_NE', 'goog.i18n.NumberFormatSymbols_fr_PF', 'goog.i18n.NumberFormatSymbols_fr_RW', 'goog.i18n.NumberFormatSymbols_fr_SC', 'goog.i18n.NumberFormatSymbols_fr_SN', 'goog.i18n.NumberFormatSymbols_fr_SY', 'goog.i18n.NumberFormatSymbols_fr_TD', 'goog.i18n.NumberFormatSymbols_fr_TG', 'goog.i18n.NumberFormatSymbols_fr_TN', 'goog.i18n.NumberFormatSymbols_fr_VU', 'goog.i18n.NumberFormatSymbols_fr_WF', 'goog.i18n.NumberFormatSymbols_fur', 'goog.i18n.NumberFormatSymbols_fur_IT', 'goog.i18n.NumberFormatSymbols_fy', 'goog.i18n.NumberFormatSymbols_fy_NL', 'goog.i18n.NumberFormatSymbols_gd', 'goog.i18n.NumberFormatSymbols_gd_GB', 'goog.i18n.NumberFormatSymbols_gsw_FR', 'goog.i18n.NumberFormatSymbols_guz', 'goog.i18n.NumberFormatSymbols_guz_KE', 'goog.i18n.NumberFormatSymbols_gv', 'goog.i18n.NumberFormatSymbols_gv_IM', 'goog.i18n.NumberFormatSymbols_ha', 'goog.i18n.NumberFormatSymbols_ha_Latn', 'goog.i18n.NumberFormatSymbols_ha_Latn_GH', 'goog.i18n.NumberFormatSymbols_ha_Latn_NE', 'goog.i18n.NumberFormatSymbols_ha_Latn_NG', 'goog.i18n.NumberFormatSymbols_hr_BA', 'goog.i18n.NumberFormatSymbols_hsb', 'goog.i18n.NumberFormatSymbols_hsb_DE', 'goog.i18n.NumberFormatSymbols_ia', 'goog.i18n.NumberFormatSymbols_ia_FR', 'goog.i18n.NumberFormatSymbols_ig', 'goog.i18n.NumberFormatSymbols_ig_NG', 'goog.i18n.NumberFormatSymbols_ii', 'goog.i18n.NumberFormatSymbols_ii_CN', 'goog.i18n.NumberFormatSymbols_it_CH', 'goog.i18n.NumberFormatSymbols_jgo', 'goog.i18n.NumberFormatSymbols_jgo_CM', 'goog.i18n.NumberFormatSymbols_jmc', 'goog.i18n.NumberFormatSymbols_jmc_TZ', 'goog.i18n.NumberFormatSymbols_kab', 'goog.i18n.NumberFormatSymbols_kab_DZ', 'goog.i18n.NumberFormatSymbols_kam', 'goog.i18n.NumberFormatSymbols_kam_KE', 'goog.i18n.NumberFormatSymbols_kde', 'goog.i18n.NumberFormatSymbols_kde_TZ', 'goog.i18n.NumberFormatSymbols_kea', 'goog.i18n.NumberFormatSymbols_kea_CV', 'goog.i18n.NumberFormatSymbols_khq', 'goog.i18n.NumberFormatSymbols_khq_ML', 'goog.i18n.NumberFormatSymbols_ki', 'goog.i18n.NumberFormatSymbols_ki_KE', 'goog.i18n.NumberFormatSymbols_kk_Cyrl', 'goog.i18n.NumberFormatSymbols_kkj', 'goog.i18n.NumberFormatSymbols_kkj_CM', 'goog.i18n.NumberFormatSymbols_kl', 'goog.i18n.NumberFormatSymbols_kl_GL', 'goog.i18n.NumberFormatSymbols_kln', 'goog.i18n.NumberFormatSymbols_kln_KE', 'goog.i18n.NumberFormatSymbols_ko_KP', 'goog.i18n.NumberFormatSymbols_kok', 'goog.i18n.NumberFormatSymbols_kok_IN', 'goog.i18n.NumberFormatSymbols_ks', 'goog.i18n.NumberFormatSymbols_ks_Arab', 'goog.i18n.NumberFormatSymbols_ks_Arab_IN', 'goog.i18n.NumberFormatSymbols_ksb', 'goog.i18n.NumberFormatSymbols_ksb_TZ', 'goog.i18n.NumberFormatSymbols_ksf', 'goog.i18n.NumberFormatSymbols_ksf_CM', 'goog.i18n.NumberFormatSymbols_ksh', 'goog.i18n.NumberFormatSymbols_ksh_DE', 'goog.i18n.NumberFormatSymbols_kw', 'goog.i18n.NumberFormatSymbols_kw_GB', 'goog.i18n.NumberFormatSymbols_ky_Cyrl', 'goog.i18n.NumberFormatSymbols_lag', 'goog.i18n.NumberFormatSymbols_lag_TZ', 'goog.i18n.NumberFormatSymbols_lb', 'goog.i18n.NumberFormatSymbols_lb_LU', 'goog.i18n.NumberFormatSymbols_lg', 'goog.i18n.NumberFormatSymbols_lg_UG', 'goog.i18n.NumberFormatSymbols_lkt', 'goog.i18n.NumberFormatSymbols_lkt_US', 'goog.i18n.NumberFormatSymbols_ln_AO', 'goog.i18n.NumberFormatSymbols_ln_CF', 'goog.i18n.NumberFormatSymbols_ln_CG', 'goog.i18n.NumberFormatSymbols_lu', 'goog.i18n.NumberFormatSymbols_lu_CD', 'goog.i18n.NumberFormatSymbols_luo', 'goog.i18n.NumberFormatSymbols_luo_KE', 'goog.i18n.NumberFormatSymbols_luy', 'goog.i18n.NumberFormatSymbols_luy_KE', 'goog.i18n.NumberFormatSymbols_mas', 'goog.i18n.NumberFormatSymbols_mas_KE', 'goog.i18n.NumberFormatSymbols_mas_TZ', 'goog.i18n.NumberFormatSymbols_mer', 'goog.i18n.NumberFormatSymbols_mer_KE', 'goog.i18n.NumberFormatSymbols_mfe', 'goog.i18n.NumberFormatSymbols_mfe_MU', 'goog.i18n.NumberFormatSymbols_mg', 'goog.i18n.NumberFormatSymbols_mg_MG', 'goog.i18n.NumberFormatSymbols_mgh', 'goog.i18n.NumberFormatSymbols_mgh_MZ', 'goog.i18n.NumberFormatSymbols_mgo', 'goog.i18n.NumberFormatSymbols_mgo_CM', 'goog.i18n.NumberFormatSymbols_mn_Cyrl', 'goog.i18n.NumberFormatSymbols_ms_Latn', 'goog.i18n.NumberFormatSymbols_ms_Latn_BN', 'goog.i18n.NumberFormatSymbols_ms_Latn_SG', 'goog.i18n.NumberFormatSymbols_mua', 'goog.i18n.NumberFormatSymbols_mua_CM', 'goog.i18n.NumberFormatSymbols_naq', 'goog.i18n.NumberFormatSymbols_naq_NA', 'goog.i18n.NumberFormatSymbols_nd', 'goog.i18n.NumberFormatSymbols_nd_ZW', 'goog.i18n.NumberFormatSymbols_ne_IN', 'goog.i18n.NumberFormatSymbols_nl_AW', 'goog.i18n.NumberFormatSymbols_nl_BE', 'goog.i18n.NumberFormatSymbols_nl_BQ', 'goog.i18n.NumberFormatSymbols_nl_CW', 'goog.i18n.NumberFormatSymbols_nl_SR', 'goog.i18n.NumberFormatSymbols_nl_SX', 'goog.i18n.NumberFormatSymbols_nmg', 'goog.i18n.NumberFormatSymbols_nmg_CM', 'goog.i18n.NumberFormatSymbols_nn', 'goog.i18n.NumberFormatSymbols_nn_NO', 'goog.i18n.NumberFormatSymbols_nnh', 'goog.i18n.NumberFormatSymbols_nnh_CM', 'goog.i18n.NumberFormatSymbols_nr', 'goog.i18n.NumberFormatSymbols_nr_ZA', 'goog.i18n.NumberFormatSymbols_nso', 'goog.i18n.NumberFormatSymbols_nso_ZA', 'goog.i18n.NumberFormatSymbols_nus', 'goog.i18n.NumberFormatSymbols_nus_SD', 'goog.i18n.NumberFormatSymbols_nyn', 'goog.i18n.NumberFormatSymbols_nyn_UG', 'goog.i18n.NumberFormatSymbols_om', 'goog.i18n.NumberFormatSymbols_om_ET', 'goog.i18n.NumberFormatSymbols_om_KE', 'goog.i18n.NumberFormatSymbols_os', 'goog.i18n.NumberFormatSymbols_os_GE', 'goog.i18n.NumberFormatSymbols_os_RU', 'goog.i18n.NumberFormatSymbols_pa_Arab', 'goog.i18n.NumberFormatSymbols_pa_Arab_PK', 'goog.i18n.NumberFormatSymbols_pa_Guru', 'goog.i18n.NumberFormatSymbols_ps', 'goog.i18n.NumberFormatSymbols_ps_AF', 'goog.i18n.NumberFormatSymbols_pt_AO', 'goog.i18n.NumberFormatSymbols_pt_CV', 'goog.i18n.NumberFormatSymbols_pt_GW', 'goog.i18n.NumberFormatSymbols_pt_MO', 'goog.i18n.NumberFormatSymbols_pt_MZ', 'goog.i18n.NumberFormatSymbols_pt_ST', 'goog.i18n.NumberFormatSymbols_pt_TL', 'goog.i18n.NumberFormatSymbols_qu', 'goog.i18n.NumberFormatSymbols_qu_BO', 'goog.i18n.NumberFormatSymbols_qu_EC', 'goog.i18n.NumberFormatSymbols_qu_PE', 'goog.i18n.NumberFormatSymbols_rm', 'goog.i18n.NumberFormatSymbols_rm_CH', 'goog.i18n.NumberFormatSymbols_rn', 'goog.i18n.NumberFormatSymbols_rn_BI', 'goog.i18n.NumberFormatSymbols_ro_MD', 'goog.i18n.NumberFormatSymbols_rof', 'goog.i18n.NumberFormatSymbols_rof_TZ', 'goog.i18n.NumberFormatSymbols_ru_BY', 'goog.i18n.NumberFormatSymbols_ru_KG', 'goog.i18n.NumberFormatSymbols_ru_KZ', 'goog.i18n.NumberFormatSymbols_ru_MD', 'goog.i18n.NumberFormatSymbols_ru_UA', 'goog.i18n.NumberFormatSymbols_rw', 'goog.i18n.NumberFormatSymbols_rw_RW', 'goog.i18n.NumberFormatSymbols_rwk', 'goog.i18n.NumberFormatSymbols_rwk_TZ', 'goog.i18n.NumberFormatSymbols_sah', 'goog.i18n.NumberFormatSymbols_sah_RU', 'goog.i18n.NumberFormatSymbols_saq', 'goog.i18n.NumberFormatSymbols_saq_KE', 'goog.i18n.NumberFormatSymbols_sbp', 'goog.i18n.NumberFormatSymbols_sbp_TZ', 'goog.i18n.NumberFormatSymbols_se', 'goog.i18n.NumberFormatSymbols_se_FI', 'goog.i18n.NumberFormatSymbols_se_NO', 'goog.i18n.NumberFormatSymbols_se_SE', 'goog.i18n.NumberFormatSymbols_seh', 'goog.i18n.NumberFormatSymbols_seh_MZ', 'goog.i18n.NumberFormatSymbols_ses', 'goog.i18n.NumberFormatSymbols_ses_ML', 'goog.i18n.NumberFormatSymbols_sg', 'goog.i18n.NumberFormatSymbols_sg_CF', 'goog.i18n.NumberFormatSymbols_shi', 'goog.i18n.NumberFormatSymbols_shi_Latn', 'goog.i18n.NumberFormatSymbols_shi_Latn_MA', 'goog.i18n.NumberFormatSymbols_shi_Tfng', 'goog.i18n.NumberFormatSymbols_shi_Tfng_MA', 'goog.i18n.NumberFormatSymbols_smn', 'goog.i18n.NumberFormatSymbols_smn_FI', 'goog.i18n.NumberFormatSymbols_sn', 'goog.i18n.NumberFormatSymbols_sn_ZW', 'goog.i18n.NumberFormatSymbols_so', 'goog.i18n.NumberFormatSymbols_so_DJ', 'goog.i18n.NumberFormatSymbols_so_ET', 'goog.i18n.NumberFormatSymbols_so_KE', 'goog.i18n.NumberFormatSymbols_so_SO', 'goog.i18n.NumberFormatSymbols_sq_MK', 'goog.i18n.NumberFormatSymbols_sq_XK', 'goog.i18n.NumberFormatSymbols_sr_Cyrl', 'goog.i18n.NumberFormatSymbols_sr_Cyrl_BA', 'goog.i18n.NumberFormatSymbols_sr_Cyrl_ME', 'goog.i18n.NumberFormatSymbols_sr_Cyrl_XK', 'goog.i18n.NumberFormatSymbols_sr_Latn', 'goog.i18n.NumberFormatSymbols_sr_Latn_BA', 'goog.i18n.NumberFormatSymbols_sr_Latn_ME', 'goog.i18n.NumberFormatSymbols_sr_Latn_RS', 'goog.i18n.NumberFormatSymbols_sr_Latn_XK', 'goog.i18n.NumberFormatSymbols_ss', 'goog.i18n.NumberFormatSymbols_ss_SZ', 'goog.i18n.NumberFormatSymbols_ss_ZA', 'goog.i18n.NumberFormatSymbols_ssy', 'goog.i18n.NumberFormatSymbols_ssy_ER', 'goog.i18n.NumberFormatSymbols_sv_AX', 'goog.i18n.NumberFormatSymbols_sv_FI', 'goog.i18n.NumberFormatSymbols_sw_KE', 'goog.i18n.NumberFormatSymbols_sw_UG', 'goog.i18n.NumberFormatSymbols_swc', 'goog.i18n.NumberFormatSymbols_swc_CD', 'goog.i18n.NumberFormatSymbols_ta_LK', 'goog.i18n.NumberFormatSymbols_ta_MY', 'goog.i18n.NumberFormatSymbols_ta_SG', 'goog.i18n.NumberFormatSymbols_teo', 'goog.i18n.NumberFormatSymbols_teo_KE', 'goog.i18n.NumberFormatSymbols_teo_UG', 'goog.i18n.NumberFormatSymbols_ti', 'goog.i18n.NumberFormatSymbols_ti_ER', 'goog.i18n.NumberFormatSymbols_ti_ET', 'goog.i18n.NumberFormatSymbols_tn', 'goog.i18n.NumberFormatSymbols_tn_BW', 'goog.i18n.NumberFormatSymbols_tn_ZA', 'goog.i18n.NumberFormatSymbols_to', 'goog.i18n.NumberFormatSymbols_to_TO', 'goog.i18n.NumberFormatSymbols_tr_CY', 'goog.i18n.NumberFormatSymbols_ts', 'goog.i18n.NumberFormatSymbols_ts_ZA', 'goog.i18n.NumberFormatSymbols_twq', 'goog.i18n.NumberFormatSymbols_twq_NE', 'goog.i18n.NumberFormatSymbols_tzm', 'goog.i18n.NumberFormatSymbols_tzm_Latn', 'goog.i18n.NumberFormatSymbols_tzm_Latn_MA', 'goog.i18n.NumberFormatSymbols_ug', 'goog.i18n.NumberFormatSymbols_ug_Arab', 'goog.i18n.NumberFormatSymbols_ug_Arab_CN', 'goog.i18n.NumberFormatSymbols_ur_IN', 'goog.i18n.NumberFormatSymbols_uz_Arab', 'goog.i18n.NumberFormatSymbols_uz_Arab_AF', 'goog.i18n.NumberFormatSymbols_uz_Cyrl', 'goog.i18n.NumberFormatSymbols_uz_Cyrl_UZ', 'goog.i18n.NumberFormatSymbols_uz_Latn', 'goog.i18n.NumberFormatSymbols_vai', 'goog.i18n.NumberFormatSymbols_vai_Latn', 'goog.i18n.NumberFormatSymbols_vai_Latn_LR', 'goog.i18n.NumberFormatSymbols_vai_Vaii', 'goog.i18n.NumberFormatSymbols_vai_Vaii_LR', 'goog.i18n.NumberFormatSymbols_ve', 'goog.i18n.NumberFormatSymbols_ve_ZA', 'goog.i18n.NumberFormatSymbols_vo', 'goog.i18n.NumberFormatSymbols_vo_001', 'goog.i18n.NumberFormatSymbols_vun', 'goog.i18n.NumberFormatSymbols_vun_TZ', 'goog.i18n.NumberFormatSymbols_wae', 'goog.i18n.NumberFormatSymbols_wae_CH', 'goog.i18n.NumberFormatSymbols_xog', 'goog.i18n.NumberFormatSymbols_xog_UG', 'goog.i18n.NumberFormatSymbols_yav', 'goog.i18n.NumberFormatSymbols_yav_CM', 'goog.i18n.NumberFormatSymbols_yi', 'goog.i18n.NumberFormatSymbols_yi_001', 'goog.i18n.NumberFormatSymbols_yo', 'goog.i18n.NumberFormatSymbols_yo_BJ', 'goog.i18n.NumberFormatSymbols_yo_NG', 'goog.i18n.NumberFormatSymbols_zgh', 'goog.i18n.NumberFormatSymbols_zgh_MA', 'goog.i18n.NumberFormatSymbols_zh_Hans', 'goog.i18n.NumberFormatSymbols_zh_Hans_HK', 'goog.i18n.NumberFormatSymbols_zh_Hans_MO', 'goog.i18n.NumberFormatSymbols_zh_Hans_SG', 'goog.i18n.NumberFormatSymbols_zh_Hant', 'goog.i18n.NumberFormatSymbols_zh_Hant_HK', 'goog.i18n.NumberFormatSymbols_zh_Hant_MO', 'goog.i18n.NumberFormatSymbols_zh_Hant_TW'], ['goog.i18n.NumberFormatSymbols'], false); -goog.addDependency('i18n/ordinalrules.js', ['goog.i18n.ordinalRules'], [], false); -goog.addDependency('i18n/pluralrules.js', ['goog.i18n.pluralRules'], [], false); -goog.addDependency('i18n/pluralrules_test.js', ['goog.i18n.pluralRulesTest'], ['goog.i18n.pluralRules', 'goog.testing.jsunit'], false); -goog.addDependency('i18n/timezone.js', ['goog.i18n.TimeZone'], ['goog.array', 'goog.date.DateLike', 'goog.string'], false); -goog.addDependency('i18n/timezone_test.js', ['goog.i18n.TimeZoneTest'], ['goog.i18n.TimeZone', 'goog.testing.jsunit'], false); -goog.addDependency('i18n/uchar.js', ['goog.i18n.uChar'], [], false); -goog.addDependency('i18n/uchar/localnamefetcher.js', ['goog.i18n.uChar.LocalNameFetcher'], ['goog.i18n.uChar', 'goog.i18n.uChar.NameFetcher', 'goog.log'], false); -goog.addDependency('i18n/uchar/localnamefetcher_test.js', ['goog.i18n.uChar.LocalNameFetcherTest'], ['goog.i18n.uChar.LocalNameFetcher', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false); -goog.addDependency('i18n/uchar/namefetcher.js', ['goog.i18n.uChar.NameFetcher'], [], false); -goog.addDependency('i18n/uchar/remotenamefetcher.js', ['goog.i18n.uChar.RemoteNameFetcher'], ['goog.Disposable', 'goog.Uri', 'goog.i18n.uChar', 'goog.i18n.uChar.NameFetcher', 'goog.log', 'goog.net.XhrIo', 'goog.structs.Map'], false); -goog.addDependency('i18n/uchar/remotenamefetcher_test.js', ['goog.i18n.uChar.RemoteNameFetcherTest'], ['goog.i18n.uChar.RemoteNameFetcher', 'goog.net.XhrIo', 'goog.testing.jsunit', 'goog.testing.net.XhrIo', 'goog.testing.recordFunction'], false); -goog.addDependency('i18n/uchar_test.js', ['goog.i18n.uCharTest'], ['goog.i18n.uChar', 'goog.testing.jsunit'], false); -goog.addDependency('iter/iter.js', ['goog.iter', 'goog.iter.Iterable', 'goog.iter.Iterator', 'goog.iter.StopIteration'], ['goog.array', 'goog.asserts', 'goog.functions', 'goog.math'], false); -goog.addDependency('iter/iter_test.js', ['goog.iterTest'], ['goog.iter', 'goog.iter.Iterator', 'goog.iter.StopIteration', 'goog.testing.jsunit'], false); -goog.addDependency('json/evaljsonprocessor.js', ['goog.json.EvalJsonProcessor'], ['goog.json', 'goog.json.Processor', 'goog.json.Serializer'], false); -goog.addDependency('json/hybrid.js', ['goog.json.hybrid'], ['goog.asserts', 'goog.json'], false); -goog.addDependency('json/hybrid_test.js', ['goog.json.hybridTest'], ['goog.json', 'goog.json.hybrid', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.userAgent'], false); -goog.addDependency('json/hybridjsonprocessor.js', ['goog.json.HybridJsonProcessor'], ['goog.json.Processor', 'goog.json.hybrid'], false); -goog.addDependency('json/hybridjsonprocessor_test.js', ['goog.json.HybridJsonProcessorTest'], ['goog.json.HybridJsonProcessor', 'goog.json.hybrid', 'goog.testing.jsunit'], false); -goog.addDependency('json/json.js', ['goog.json', 'goog.json.Replacer', 'goog.json.Reviver', 'goog.json.Serializer'], [], false); -goog.addDependency('json/json_perf.js', ['goog.jsonPerf'], ['goog.dom', 'goog.json', 'goog.math', 'goog.string', 'goog.testing.PerformanceTable', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false); -goog.addDependency('json/json_test.js', ['goog.jsonTest'], ['goog.functions', 'goog.json', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('json/nativejsonprocessor.js', ['goog.json.NativeJsonProcessor'], ['goog.asserts', 'goog.json.Processor'], false); -goog.addDependency('json/processor.js', ['goog.json.Processor'], ['goog.string.Parser', 'goog.string.Stringifier'], false); -goog.addDependency('json/processor_test.js', ['goog.json.processorTest'], ['goog.json.EvalJsonProcessor', 'goog.json.NativeJsonProcessor', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('labs/dom/pagevisibilitymonitor.js', ['goog.labs.dom.PageVisibilityEvent', 'goog.labs.dom.PageVisibilityMonitor', 'goog.labs.dom.PageVisibilityState'], ['goog.dom', 'goog.dom.vendor', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.memoize'], false); -goog.addDependency('labs/dom/pagevisibilitymonitor_test.js', ['goog.labs.dom.PageVisibilityMonitorTest'], ['goog.events', 'goog.functions', 'goog.labs.dom.PageVisibilityMonitor', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false); -goog.addDependency('labs/events/nondisposableeventtarget.js', ['goog.labs.events.NonDisposableEventTarget'], ['goog.array', 'goog.asserts', 'goog.events.Event', 'goog.events.Listenable', 'goog.events.ListenerMap', 'goog.object'], false); -goog.addDependency('labs/events/nondisposableeventtarget_test.js', ['goog.labs.events.NonDisposableEventTargetTest'], ['goog.events.Listenable', 'goog.events.eventTargetTester', 'goog.events.eventTargetTester.KeyType', 'goog.events.eventTargetTester.UnlistenReturnType', 'goog.labs.events.NonDisposableEventTarget', 'goog.testing.jsunit'], false); -goog.addDependency('labs/events/nondisposableeventtarget_via_googevents_test.js', ['goog.labs.events.NonDisposableEventTargetGoogEventsTest'], ['goog.events', 'goog.events.eventTargetTester', 'goog.events.eventTargetTester.KeyType', 'goog.events.eventTargetTester.UnlistenReturnType', 'goog.labs.events.NonDisposableEventTarget', 'goog.testing', 'goog.testing.jsunit'], false); -goog.addDependency('labs/events/touch.js', ['goog.labs.events.touch', 'goog.labs.events.touch.TouchData'], ['goog.array', 'goog.asserts', 'goog.events.EventType', 'goog.string'], false); -goog.addDependency('labs/events/touch_test.js', ['goog.labs.events.touchTest'], ['goog.labs.events.touch', 'goog.testing.jsunit'], false); -goog.addDependency('labs/format/csv.js', ['goog.labs.format.csv', 'goog.labs.format.csv.ParseError', 'goog.labs.format.csv.Token'], ['goog.array', 'goog.asserts', 'goog.debug.Error', 'goog.object', 'goog.string', 'goog.string.newlines'], false); -goog.addDependency('labs/format/csv_test.js', ['goog.labs.format.csvTest'], ['goog.labs.format.csv', 'goog.labs.format.csv.ParseError', 'goog.object', 'goog.testing.asserts', 'goog.testing.jsunit'], false); -goog.addDependency('labs/html/attribute_rewriter.js', ['goog.labs.html.AttributeRewriter', 'goog.labs.html.AttributeValue', 'goog.labs.html.attributeRewriterPresubmitWorkaround'], [], false); -goog.addDependency('labs/html/sanitizer.js', ['goog.labs.html.Sanitizer'], ['goog.asserts', 'goog.html.SafeUrl', 'goog.labs.html.attributeRewriterPresubmitWorkaround', 'goog.labs.html.scrubber', 'goog.object', 'goog.string'], false); -goog.addDependency('labs/html/sanitizer_test.js', ['goog.labs.html.SanitizerTest'], ['goog.html.SafeUrl', 'goog.labs.html.Sanitizer', 'goog.string', 'goog.string.Const', 'goog.testing.jsunit'], false); -goog.addDependency('labs/html/scrubber.js', ['goog.labs.html.scrubber'], ['goog.array', 'goog.dom.tags', 'goog.labs.html.attributeRewriterPresubmitWorkaround', 'goog.string'], false); -goog.addDependency('labs/html/scrubber_test.js', ['goog.html.ScrubberTest'], ['goog.labs.html.scrubber', 'goog.object', 'goog.string', 'goog.testing.jsunit'], false); -goog.addDependency('labs/i18n/listformat.js', ['goog.labs.i18n.GenderInfo', 'goog.labs.i18n.GenderInfo.Gender', 'goog.labs.i18n.ListFormat'], ['goog.asserts', 'goog.labs.i18n.ListFormatSymbols'], false); -goog.addDependency('labs/i18n/listformat_test.js', ['goog.labs.i18n.ListFormatTest'], ['goog.labs.i18n.GenderInfo', 'goog.labs.i18n.ListFormat', 'goog.labs.i18n.ListFormatSymbols', 'goog.labs.i18n.ListFormatSymbols_el', 'goog.labs.i18n.ListFormatSymbols_en', 'goog.labs.i18n.ListFormatSymbols_fr', 'goog.labs.i18n.ListFormatSymbols_ml', 'goog.labs.i18n.ListFormatSymbols_zu', 'goog.testing.jsunit'], false); -goog.addDependency('labs/i18n/listsymbols.js', ['goog.labs.i18n.ListFormatSymbols', 'goog.labs.i18n.ListFormatSymbols_af', 'goog.labs.i18n.ListFormatSymbols_am', 'goog.labs.i18n.ListFormatSymbols_ar', 'goog.labs.i18n.ListFormatSymbols_az', 'goog.labs.i18n.ListFormatSymbols_bg', 'goog.labs.i18n.ListFormatSymbols_bn', 'goog.labs.i18n.ListFormatSymbols_br', 'goog.labs.i18n.ListFormatSymbols_ca', 'goog.labs.i18n.ListFormatSymbols_chr', 'goog.labs.i18n.ListFormatSymbols_cs', 'goog.labs.i18n.ListFormatSymbols_cy', 'goog.labs.i18n.ListFormatSymbols_da', 'goog.labs.i18n.ListFormatSymbols_de', 'goog.labs.i18n.ListFormatSymbols_de_AT', 'goog.labs.i18n.ListFormatSymbols_de_CH', 'goog.labs.i18n.ListFormatSymbols_el', 'goog.labs.i18n.ListFormatSymbols_en', 'goog.labs.i18n.ListFormatSymbols_en_AU', 'goog.labs.i18n.ListFormatSymbols_en_GB', 'goog.labs.i18n.ListFormatSymbols_en_IE', 'goog.labs.i18n.ListFormatSymbols_en_IN', 'goog.labs.i18n.ListFormatSymbols_en_SG', 'goog.labs.i18n.ListFormatSymbols_en_US', 'goog.labs.i18n.ListFormatSymbols_en_ZA', 'goog.labs.i18n.ListFormatSymbols_es', 'goog.labs.i18n.ListFormatSymbols_es_419', 'goog.labs.i18n.ListFormatSymbols_es_ES', 'goog.labs.i18n.ListFormatSymbols_et', 'goog.labs.i18n.ListFormatSymbols_eu', 'goog.labs.i18n.ListFormatSymbols_fa', 'goog.labs.i18n.ListFormatSymbols_fi', 'goog.labs.i18n.ListFormatSymbols_fil', 'goog.labs.i18n.ListFormatSymbols_fr', 'goog.labs.i18n.ListFormatSymbols_fr_CA', 'goog.labs.i18n.ListFormatSymbols_ga', 'goog.labs.i18n.ListFormatSymbols_gl', 'goog.labs.i18n.ListFormatSymbols_gsw', 'goog.labs.i18n.ListFormatSymbols_gu', 'goog.labs.i18n.ListFormatSymbols_haw', 'goog.labs.i18n.ListFormatSymbols_he', 'goog.labs.i18n.ListFormatSymbols_hi', 'goog.labs.i18n.ListFormatSymbols_hr', 'goog.labs.i18n.ListFormatSymbols_hu', 'goog.labs.i18n.ListFormatSymbols_hy', 'goog.labs.i18n.ListFormatSymbols_id', 'goog.labs.i18n.ListFormatSymbols_in', 'goog.labs.i18n.ListFormatSymbols_is', 'goog.labs.i18n.ListFormatSymbols_it', 'goog.labs.i18n.ListFormatSymbols_iw', 'goog.labs.i18n.ListFormatSymbols_ja', 'goog.labs.i18n.ListFormatSymbols_ka', 'goog.labs.i18n.ListFormatSymbols_kk', 'goog.labs.i18n.ListFormatSymbols_km', 'goog.labs.i18n.ListFormatSymbols_kn', 'goog.labs.i18n.ListFormatSymbols_ko', 'goog.labs.i18n.ListFormatSymbols_ky', 'goog.labs.i18n.ListFormatSymbols_ln', 'goog.labs.i18n.ListFormatSymbols_lo', 'goog.labs.i18n.ListFormatSymbols_lt', 'goog.labs.i18n.ListFormatSymbols_lv', 'goog.labs.i18n.ListFormatSymbols_mk', 'goog.labs.i18n.ListFormatSymbols_ml', 'goog.labs.i18n.ListFormatSymbols_mn', 'goog.labs.i18n.ListFormatSymbols_mo', 'goog.labs.i18n.ListFormatSymbols_mr', 'goog.labs.i18n.ListFormatSymbols_ms', 'goog.labs.i18n.ListFormatSymbols_mt', 'goog.labs.i18n.ListFormatSymbols_my', 'goog.labs.i18n.ListFormatSymbols_nb', 'goog.labs.i18n.ListFormatSymbols_ne', 'goog.labs.i18n.ListFormatSymbols_nl', 'goog.labs.i18n.ListFormatSymbols_no', 'goog.labs.i18n.ListFormatSymbols_no_NO', 'goog.labs.i18n.ListFormatSymbols_or', 'goog.labs.i18n.ListFormatSymbols_pa', 'goog.labs.i18n.ListFormatSymbols_pl', 'goog.labs.i18n.ListFormatSymbols_pt', 'goog.labs.i18n.ListFormatSymbols_pt_BR', 'goog.labs.i18n.ListFormatSymbols_pt_PT', 'goog.labs.i18n.ListFormatSymbols_ro', 'goog.labs.i18n.ListFormatSymbols_ru', 'goog.labs.i18n.ListFormatSymbols_sh', 'goog.labs.i18n.ListFormatSymbols_si', 'goog.labs.i18n.ListFormatSymbols_sk', 'goog.labs.i18n.ListFormatSymbols_sl', 'goog.labs.i18n.ListFormatSymbols_sq', 'goog.labs.i18n.ListFormatSymbols_sr', 'goog.labs.i18n.ListFormatSymbols_sv', 'goog.labs.i18n.ListFormatSymbols_sw', 'goog.labs.i18n.ListFormatSymbols_ta', 'goog.labs.i18n.ListFormatSymbols_te', 'goog.labs.i18n.ListFormatSymbols_th', 'goog.labs.i18n.ListFormatSymbols_tl', 'goog.labs.i18n.ListFormatSymbols_tr', 'goog.labs.i18n.ListFormatSymbols_uk', 'goog.labs.i18n.ListFormatSymbols_ur', 'goog.labs.i18n.ListFormatSymbols_uz', 'goog.labs.i18n.ListFormatSymbols_vi', 'goog.labs.i18n.ListFormatSymbols_zh', 'goog.labs.i18n.ListFormatSymbols_zh_CN', 'goog.labs.i18n.ListFormatSymbols_zh_HK', 'goog.labs.i18n.ListFormatSymbols_zh_TW', 'goog.labs.i18n.ListFormatSymbols_zu'], [], false); -goog.addDependency('labs/i18n/listsymbolsext.js', ['goog.labs.i18n.ListFormatSymbolsExt', 'goog.labs.i18n.ListFormatSymbols_af_NA', 'goog.labs.i18n.ListFormatSymbols_af_ZA', 'goog.labs.i18n.ListFormatSymbols_agq', 'goog.labs.i18n.ListFormatSymbols_agq_CM', 'goog.labs.i18n.ListFormatSymbols_ak', 'goog.labs.i18n.ListFormatSymbols_ak_GH', 'goog.labs.i18n.ListFormatSymbols_am_ET', 'goog.labs.i18n.ListFormatSymbols_ar_001', 'goog.labs.i18n.ListFormatSymbols_ar_AE', 'goog.labs.i18n.ListFormatSymbols_ar_BH', 'goog.labs.i18n.ListFormatSymbols_ar_DJ', 'goog.labs.i18n.ListFormatSymbols_ar_DZ', 'goog.labs.i18n.ListFormatSymbols_ar_EG', 'goog.labs.i18n.ListFormatSymbols_ar_EH', 'goog.labs.i18n.ListFormatSymbols_ar_ER', 'goog.labs.i18n.ListFormatSymbols_ar_IL', 'goog.labs.i18n.ListFormatSymbols_ar_IQ', 'goog.labs.i18n.ListFormatSymbols_ar_JO', 'goog.labs.i18n.ListFormatSymbols_ar_KM', 'goog.labs.i18n.ListFormatSymbols_ar_KW', 'goog.labs.i18n.ListFormatSymbols_ar_LB', 'goog.labs.i18n.ListFormatSymbols_ar_LY', 'goog.labs.i18n.ListFormatSymbols_ar_MA', 'goog.labs.i18n.ListFormatSymbols_ar_MR', 'goog.labs.i18n.ListFormatSymbols_ar_OM', 'goog.labs.i18n.ListFormatSymbols_ar_PS', 'goog.labs.i18n.ListFormatSymbols_ar_QA', 'goog.labs.i18n.ListFormatSymbols_ar_SA', 'goog.labs.i18n.ListFormatSymbols_ar_SD', 'goog.labs.i18n.ListFormatSymbols_ar_SO', 'goog.labs.i18n.ListFormatSymbols_ar_SS', 'goog.labs.i18n.ListFormatSymbols_ar_SY', 'goog.labs.i18n.ListFormatSymbols_ar_TD', 'goog.labs.i18n.ListFormatSymbols_ar_TN', 'goog.labs.i18n.ListFormatSymbols_ar_YE', 'goog.labs.i18n.ListFormatSymbols_as', 'goog.labs.i18n.ListFormatSymbols_as_IN', 'goog.labs.i18n.ListFormatSymbols_asa', 'goog.labs.i18n.ListFormatSymbols_asa_TZ', 'goog.labs.i18n.ListFormatSymbols_az_Cyrl', 'goog.labs.i18n.ListFormatSymbols_az_Cyrl_AZ', 'goog.labs.i18n.ListFormatSymbols_az_Latn', 'goog.labs.i18n.ListFormatSymbols_az_Latn_AZ', 'goog.labs.i18n.ListFormatSymbols_bas', 'goog.labs.i18n.ListFormatSymbols_bas_CM', 'goog.labs.i18n.ListFormatSymbols_be', 'goog.labs.i18n.ListFormatSymbols_be_BY', 'goog.labs.i18n.ListFormatSymbols_bem', 'goog.labs.i18n.ListFormatSymbols_bem_ZM', 'goog.labs.i18n.ListFormatSymbols_bez', 'goog.labs.i18n.ListFormatSymbols_bez_TZ', 'goog.labs.i18n.ListFormatSymbols_bg_BG', 'goog.labs.i18n.ListFormatSymbols_bm', 'goog.labs.i18n.ListFormatSymbols_bm_Latn', 'goog.labs.i18n.ListFormatSymbols_bm_Latn_ML', 'goog.labs.i18n.ListFormatSymbols_bn_BD', 'goog.labs.i18n.ListFormatSymbols_bn_IN', 'goog.labs.i18n.ListFormatSymbols_bo', 'goog.labs.i18n.ListFormatSymbols_bo_CN', 'goog.labs.i18n.ListFormatSymbols_bo_IN', 'goog.labs.i18n.ListFormatSymbols_br_FR', 'goog.labs.i18n.ListFormatSymbols_brx', 'goog.labs.i18n.ListFormatSymbols_brx_IN', 'goog.labs.i18n.ListFormatSymbols_bs', 'goog.labs.i18n.ListFormatSymbols_bs_Cyrl', 'goog.labs.i18n.ListFormatSymbols_bs_Cyrl_BA', 'goog.labs.i18n.ListFormatSymbols_bs_Latn', 'goog.labs.i18n.ListFormatSymbols_bs_Latn_BA', 'goog.labs.i18n.ListFormatSymbols_ca_AD', 'goog.labs.i18n.ListFormatSymbols_ca_ES', 'goog.labs.i18n.ListFormatSymbols_ca_FR', 'goog.labs.i18n.ListFormatSymbols_ca_IT', 'goog.labs.i18n.ListFormatSymbols_cgg', 'goog.labs.i18n.ListFormatSymbols_cgg_UG', 'goog.labs.i18n.ListFormatSymbols_chr_US', 'goog.labs.i18n.ListFormatSymbols_cs_CZ', 'goog.labs.i18n.ListFormatSymbols_cy_GB', 'goog.labs.i18n.ListFormatSymbols_da_DK', 'goog.labs.i18n.ListFormatSymbols_da_GL', 'goog.labs.i18n.ListFormatSymbols_dav', 'goog.labs.i18n.ListFormatSymbols_dav_KE', 'goog.labs.i18n.ListFormatSymbols_de_BE', 'goog.labs.i18n.ListFormatSymbols_de_DE', 'goog.labs.i18n.ListFormatSymbols_de_LI', 'goog.labs.i18n.ListFormatSymbols_de_LU', 'goog.labs.i18n.ListFormatSymbols_dje', 'goog.labs.i18n.ListFormatSymbols_dje_NE', 'goog.labs.i18n.ListFormatSymbols_dsb', 'goog.labs.i18n.ListFormatSymbols_dsb_DE', 'goog.labs.i18n.ListFormatSymbols_dua', 'goog.labs.i18n.ListFormatSymbols_dua_CM', 'goog.labs.i18n.ListFormatSymbols_dyo', 'goog.labs.i18n.ListFormatSymbols_dyo_SN', 'goog.labs.i18n.ListFormatSymbols_dz', 'goog.labs.i18n.ListFormatSymbols_dz_BT', 'goog.labs.i18n.ListFormatSymbols_ebu', 'goog.labs.i18n.ListFormatSymbols_ebu_KE', 'goog.labs.i18n.ListFormatSymbols_ee', 'goog.labs.i18n.ListFormatSymbols_ee_GH', 'goog.labs.i18n.ListFormatSymbols_ee_TG', 'goog.labs.i18n.ListFormatSymbols_el_CY', 'goog.labs.i18n.ListFormatSymbols_el_GR', 'goog.labs.i18n.ListFormatSymbols_en_001', 'goog.labs.i18n.ListFormatSymbols_en_150', 'goog.labs.i18n.ListFormatSymbols_en_AG', 'goog.labs.i18n.ListFormatSymbols_en_AI', 'goog.labs.i18n.ListFormatSymbols_en_AS', 'goog.labs.i18n.ListFormatSymbols_en_BB', 'goog.labs.i18n.ListFormatSymbols_en_BE', 'goog.labs.i18n.ListFormatSymbols_en_BM', 'goog.labs.i18n.ListFormatSymbols_en_BS', 'goog.labs.i18n.ListFormatSymbols_en_BW', 'goog.labs.i18n.ListFormatSymbols_en_BZ', 'goog.labs.i18n.ListFormatSymbols_en_CA', 'goog.labs.i18n.ListFormatSymbols_en_CC', 'goog.labs.i18n.ListFormatSymbols_en_CK', 'goog.labs.i18n.ListFormatSymbols_en_CM', 'goog.labs.i18n.ListFormatSymbols_en_CX', 'goog.labs.i18n.ListFormatSymbols_en_DG', 'goog.labs.i18n.ListFormatSymbols_en_DM', 'goog.labs.i18n.ListFormatSymbols_en_ER', 'goog.labs.i18n.ListFormatSymbols_en_FJ', 'goog.labs.i18n.ListFormatSymbols_en_FK', 'goog.labs.i18n.ListFormatSymbols_en_FM', 'goog.labs.i18n.ListFormatSymbols_en_GD', 'goog.labs.i18n.ListFormatSymbols_en_GG', 'goog.labs.i18n.ListFormatSymbols_en_GH', 'goog.labs.i18n.ListFormatSymbols_en_GI', 'goog.labs.i18n.ListFormatSymbols_en_GM', 'goog.labs.i18n.ListFormatSymbols_en_GU', 'goog.labs.i18n.ListFormatSymbols_en_GY', 'goog.labs.i18n.ListFormatSymbols_en_HK', 'goog.labs.i18n.ListFormatSymbols_en_IM', 'goog.labs.i18n.ListFormatSymbols_en_IO', 'goog.labs.i18n.ListFormatSymbols_en_JE', 'goog.labs.i18n.ListFormatSymbols_en_JM', 'goog.labs.i18n.ListFormatSymbols_en_KE', 'goog.labs.i18n.ListFormatSymbols_en_KI', 'goog.labs.i18n.ListFormatSymbols_en_KN', 'goog.labs.i18n.ListFormatSymbols_en_KY', 'goog.labs.i18n.ListFormatSymbols_en_LC', 'goog.labs.i18n.ListFormatSymbols_en_LR', 'goog.labs.i18n.ListFormatSymbols_en_LS', 'goog.labs.i18n.ListFormatSymbols_en_MG', 'goog.labs.i18n.ListFormatSymbols_en_MH', 'goog.labs.i18n.ListFormatSymbols_en_MO', 'goog.labs.i18n.ListFormatSymbols_en_MP', 'goog.labs.i18n.ListFormatSymbols_en_MS', 'goog.labs.i18n.ListFormatSymbols_en_MT', 'goog.labs.i18n.ListFormatSymbols_en_MU', 'goog.labs.i18n.ListFormatSymbols_en_MW', 'goog.labs.i18n.ListFormatSymbols_en_MY', 'goog.labs.i18n.ListFormatSymbols_en_NA', 'goog.labs.i18n.ListFormatSymbols_en_NF', 'goog.labs.i18n.ListFormatSymbols_en_NG', 'goog.labs.i18n.ListFormatSymbols_en_NR', 'goog.labs.i18n.ListFormatSymbols_en_NU', 'goog.labs.i18n.ListFormatSymbols_en_NZ', 'goog.labs.i18n.ListFormatSymbols_en_PG', 'goog.labs.i18n.ListFormatSymbols_en_PH', 'goog.labs.i18n.ListFormatSymbols_en_PK', 'goog.labs.i18n.ListFormatSymbols_en_PN', 'goog.labs.i18n.ListFormatSymbols_en_PR', 'goog.labs.i18n.ListFormatSymbols_en_PW', 'goog.labs.i18n.ListFormatSymbols_en_RW', 'goog.labs.i18n.ListFormatSymbols_en_SB', 'goog.labs.i18n.ListFormatSymbols_en_SC', 'goog.labs.i18n.ListFormatSymbols_en_SD', 'goog.labs.i18n.ListFormatSymbols_en_SH', 'goog.labs.i18n.ListFormatSymbols_en_SL', 'goog.labs.i18n.ListFormatSymbols_en_SS', 'goog.labs.i18n.ListFormatSymbols_en_SX', 'goog.labs.i18n.ListFormatSymbols_en_SZ', 'goog.labs.i18n.ListFormatSymbols_en_TC', 'goog.labs.i18n.ListFormatSymbols_en_TK', 'goog.labs.i18n.ListFormatSymbols_en_TO', 'goog.labs.i18n.ListFormatSymbols_en_TT', 'goog.labs.i18n.ListFormatSymbols_en_TV', 'goog.labs.i18n.ListFormatSymbols_en_TZ', 'goog.labs.i18n.ListFormatSymbols_en_UG', 'goog.labs.i18n.ListFormatSymbols_en_UM', 'goog.labs.i18n.ListFormatSymbols_en_US_POSIX', 'goog.labs.i18n.ListFormatSymbols_en_VC', 'goog.labs.i18n.ListFormatSymbols_en_VG', 'goog.labs.i18n.ListFormatSymbols_en_VI', 'goog.labs.i18n.ListFormatSymbols_en_VU', 'goog.labs.i18n.ListFormatSymbols_en_WS', 'goog.labs.i18n.ListFormatSymbols_en_ZM', 'goog.labs.i18n.ListFormatSymbols_en_ZW', 'goog.labs.i18n.ListFormatSymbols_eo', 'goog.labs.i18n.ListFormatSymbols_es_AR', 'goog.labs.i18n.ListFormatSymbols_es_BO', 'goog.labs.i18n.ListFormatSymbols_es_CL', 'goog.labs.i18n.ListFormatSymbols_es_CO', 'goog.labs.i18n.ListFormatSymbols_es_CR', 'goog.labs.i18n.ListFormatSymbols_es_CU', 'goog.labs.i18n.ListFormatSymbols_es_DO', 'goog.labs.i18n.ListFormatSymbols_es_EA', 'goog.labs.i18n.ListFormatSymbols_es_EC', 'goog.labs.i18n.ListFormatSymbols_es_GQ', 'goog.labs.i18n.ListFormatSymbols_es_GT', 'goog.labs.i18n.ListFormatSymbols_es_HN', 'goog.labs.i18n.ListFormatSymbols_es_IC', 'goog.labs.i18n.ListFormatSymbols_es_MX', 'goog.labs.i18n.ListFormatSymbols_es_NI', 'goog.labs.i18n.ListFormatSymbols_es_PA', 'goog.labs.i18n.ListFormatSymbols_es_PE', 'goog.labs.i18n.ListFormatSymbols_es_PH', 'goog.labs.i18n.ListFormatSymbols_es_PR', 'goog.labs.i18n.ListFormatSymbols_es_PY', 'goog.labs.i18n.ListFormatSymbols_es_SV', 'goog.labs.i18n.ListFormatSymbols_es_US', 'goog.labs.i18n.ListFormatSymbols_es_UY', 'goog.labs.i18n.ListFormatSymbols_es_VE', 'goog.labs.i18n.ListFormatSymbols_et_EE', 'goog.labs.i18n.ListFormatSymbols_eu_ES', 'goog.labs.i18n.ListFormatSymbols_ewo', 'goog.labs.i18n.ListFormatSymbols_ewo_CM', 'goog.labs.i18n.ListFormatSymbols_fa_AF', 'goog.labs.i18n.ListFormatSymbols_fa_IR', 'goog.labs.i18n.ListFormatSymbols_ff', 'goog.labs.i18n.ListFormatSymbols_ff_CM', 'goog.labs.i18n.ListFormatSymbols_ff_GN', 'goog.labs.i18n.ListFormatSymbols_ff_MR', 'goog.labs.i18n.ListFormatSymbols_ff_SN', 'goog.labs.i18n.ListFormatSymbols_fi_FI', 'goog.labs.i18n.ListFormatSymbols_fil_PH', 'goog.labs.i18n.ListFormatSymbols_fo', 'goog.labs.i18n.ListFormatSymbols_fo_FO', 'goog.labs.i18n.ListFormatSymbols_fr_BE', 'goog.labs.i18n.ListFormatSymbols_fr_BF', 'goog.labs.i18n.ListFormatSymbols_fr_BI', 'goog.labs.i18n.ListFormatSymbols_fr_BJ', 'goog.labs.i18n.ListFormatSymbols_fr_BL', 'goog.labs.i18n.ListFormatSymbols_fr_CD', 'goog.labs.i18n.ListFormatSymbols_fr_CF', 'goog.labs.i18n.ListFormatSymbols_fr_CG', 'goog.labs.i18n.ListFormatSymbols_fr_CH', 'goog.labs.i18n.ListFormatSymbols_fr_CI', 'goog.labs.i18n.ListFormatSymbols_fr_CM', 'goog.labs.i18n.ListFormatSymbols_fr_DJ', 'goog.labs.i18n.ListFormatSymbols_fr_DZ', 'goog.labs.i18n.ListFormatSymbols_fr_FR', 'goog.labs.i18n.ListFormatSymbols_fr_GA', 'goog.labs.i18n.ListFormatSymbols_fr_GF', 'goog.labs.i18n.ListFormatSymbols_fr_GN', 'goog.labs.i18n.ListFormatSymbols_fr_GP', 'goog.labs.i18n.ListFormatSymbols_fr_GQ', 'goog.labs.i18n.ListFormatSymbols_fr_HT', 'goog.labs.i18n.ListFormatSymbols_fr_KM', 'goog.labs.i18n.ListFormatSymbols_fr_LU', 'goog.labs.i18n.ListFormatSymbols_fr_MA', 'goog.labs.i18n.ListFormatSymbols_fr_MC', 'goog.labs.i18n.ListFormatSymbols_fr_MF', 'goog.labs.i18n.ListFormatSymbols_fr_MG', 'goog.labs.i18n.ListFormatSymbols_fr_ML', 'goog.labs.i18n.ListFormatSymbols_fr_MQ', 'goog.labs.i18n.ListFormatSymbols_fr_MR', 'goog.labs.i18n.ListFormatSymbols_fr_MU', 'goog.labs.i18n.ListFormatSymbols_fr_NC', 'goog.labs.i18n.ListFormatSymbols_fr_NE', 'goog.labs.i18n.ListFormatSymbols_fr_PF', 'goog.labs.i18n.ListFormatSymbols_fr_PM', 'goog.labs.i18n.ListFormatSymbols_fr_RE', 'goog.labs.i18n.ListFormatSymbols_fr_RW', 'goog.labs.i18n.ListFormatSymbols_fr_SC', 'goog.labs.i18n.ListFormatSymbols_fr_SN', 'goog.labs.i18n.ListFormatSymbols_fr_SY', 'goog.labs.i18n.ListFormatSymbols_fr_TD', 'goog.labs.i18n.ListFormatSymbols_fr_TG', 'goog.labs.i18n.ListFormatSymbols_fr_TN', 'goog.labs.i18n.ListFormatSymbols_fr_VU', 'goog.labs.i18n.ListFormatSymbols_fr_WF', 'goog.labs.i18n.ListFormatSymbols_fr_YT', 'goog.labs.i18n.ListFormatSymbols_fur', 'goog.labs.i18n.ListFormatSymbols_fur_IT', 'goog.labs.i18n.ListFormatSymbols_fy', 'goog.labs.i18n.ListFormatSymbols_fy_NL', 'goog.labs.i18n.ListFormatSymbols_ga_IE', 'goog.labs.i18n.ListFormatSymbols_gd', 'goog.labs.i18n.ListFormatSymbols_gd_GB', 'goog.labs.i18n.ListFormatSymbols_gl_ES', 'goog.labs.i18n.ListFormatSymbols_gsw_CH', 'goog.labs.i18n.ListFormatSymbols_gsw_FR', 'goog.labs.i18n.ListFormatSymbols_gsw_LI', 'goog.labs.i18n.ListFormatSymbols_gu_IN', 'goog.labs.i18n.ListFormatSymbols_guz', 'goog.labs.i18n.ListFormatSymbols_guz_KE', 'goog.labs.i18n.ListFormatSymbols_gv', 'goog.labs.i18n.ListFormatSymbols_gv_IM', 'goog.labs.i18n.ListFormatSymbols_ha', 'goog.labs.i18n.ListFormatSymbols_ha_Latn', 'goog.labs.i18n.ListFormatSymbols_ha_Latn_GH', 'goog.labs.i18n.ListFormatSymbols_ha_Latn_NE', 'goog.labs.i18n.ListFormatSymbols_ha_Latn_NG', 'goog.labs.i18n.ListFormatSymbols_haw_US', 'goog.labs.i18n.ListFormatSymbols_he_IL', 'goog.labs.i18n.ListFormatSymbols_hi_IN', 'goog.labs.i18n.ListFormatSymbols_hr_BA', 'goog.labs.i18n.ListFormatSymbols_hr_HR', 'goog.labs.i18n.ListFormatSymbols_hsb', 'goog.labs.i18n.ListFormatSymbols_hsb_DE', 'goog.labs.i18n.ListFormatSymbols_hu_HU', 'goog.labs.i18n.ListFormatSymbols_hy_AM', 'goog.labs.i18n.ListFormatSymbols_id_ID', 'goog.labs.i18n.ListFormatSymbols_ig', 'goog.labs.i18n.ListFormatSymbols_ig_NG', 'goog.labs.i18n.ListFormatSymbols_ii', 'goog.labs.i18n.ListFormatSymbols_ii_CN', 'goog.labs.i18n.ListFormatSymbols_is_IS', 'goog.labs.i18n.ListFormatSymbols_it_CH', 'goog.labs.i18n.ListFormatSymbols_it_IT', 'goog.labs.i18n.ListFormatSymbols_it_SM', 'goog.labs.i18n.ListFormatSymbols_ja_JP', 'goog.labs.i18n.ListFormatSymbols_jgo', 'goog.labs.i18n.ListFormatSymbols_jgo_CM', 'goog.labs.i18n.ListFormatSymbols_jmc', 'goog.labs.i18n.ListFormatSymbols_jmc_TZ', 'goog.labs.i18n.ListFormatSymbols_ka_GE', 'goog.labs.i18n.ListFormatSymbols_kab', 'goog.labs.i18n.ListFormatSymbols_kab_DZ', 'goog.labs.i18n.ListFormatSymbols_kam', 'goog.labs.i18n.ListFormatSymbols_kam_KE', 'goog.labs.i18n.ListFormatSymbols_kde', 'goog.labs.i18n.ListFormatSymbols_kde_TZ', 'goog.labs.i18n.ListFormatSymbols_kea', 'goog.labs.i18n.ListFormatSymbols_kea_CV', 'goog.labs.i18n.ListFormatSymbols_khq', 'goog.labs.i18n.ListFormatSymbols_khq_ML', 'goog.labs.i18n.ListFormatSymbols_ki', 'goog.labs.i18n.ListFormatSymbols_ki_KE', 'goog.labs.i18n.ListFormatSymbols_kk_Cyrl', 'goog.labs.i18n.ListFormatSymbols_kk_Cyrl_KZ', 'goog.labs.i18n.ListFormatSymbols_kkj', 'goog.labs.i18n.ListFormatSymbols_kkj_CM', 'goog.labs.i18n.ListFormatSymbols_kl', 'goog.labs.i18n.ListFormatSymbols_kl_GL', 'goog.labs.i18n.ListFormatSymbols_kln', 'goog.labs.i18n.ListFormatSymbols_kln_KE', 'goog.labs.i18n.ListFormatSymbols_km_KH', 'goog.labs.i18n.ListFormatSymbols_kn_IN', 'goog.labs.i18n.ListFormatSymbols_ko_KP', 'goog.labs.i18n.ListFormatSymbols_ko_KR', 'goog.labs.i18n.ListFormatSymbols_kok', 'goog.labs.i18n.ListFormatSymbols_kok_IN', 'goog.labs.i18n.ListFormatSymbols_ks', 'goog.labs.i18n.ListFormatSymbols_ks_Arab', 'goog.labs.i18n.ListFormatSymbols_ks_Arab_IN', 'goog.labs.i18n.ListFormatSymbols_ksb', 'goog.labs.i18n.ListFormatSymbols_ksb_TZ', 'goog.labs.i18n.ListFormatSymbols_ksf', 'goog.labs.i18n.ListFormatSymbols_ksf_CM', 'goog.labs.i18n.ListFormatSymbols_ksh', 'goog.labs.i18n.ListFormatSymbols_ksh_DE', 'goog.labs.i18n.ListFormatSymbols_kw', 'goog.labs.i18n.ListFormatSymbols_kw_GB', 'goog.labs.i18n.ListFormatSymbols_ky_Cyrl', 'goog.labs.i18n.ListFormatSymbols_ky_Cyrl_KG', 'goog.labs.i18n.ListFormatSymbols_lag', 'goog.labs.i18n.ListFormatSymbols_lag_TZ', 'goog.labs.i18n.ListFormatSymbols_lb', 'goog.labs.i18n.ListFormatSymbols_lb_LU', 'goog.labs.i18n.ListFormatSymbols_lg', 'goog.labs.i18n.ListFormatSymbols_lg_UG', 'goog.labs.i18n.ListFormatSymbols_lkt', 'goog.labs.i18n.ListFormatSymbols_lkt_US', 'goog.labs.i18n.ListFormatSymbols_ln_AO', 'goog.labs.i18n.ListFormatSymbols_ln_CD', 'goog.labs.i18n.ListFormatSymbols_ln_CF', 'goog.labs.i18n.ListFormatSymbols_ln_CG', 'goog.labs.i18n.ListFormatSymbols_lo_LA', 'goog.labs.i18n.ListFormatSymbols_lt_LT', 'goog.labs.i18n.ListFormatSymbols_lu', 'goog.labs.i18n.ListFormatSymbols_lu_CD', 'goog.labs.i18n.ListFormatSymbols_luo', 'goog.labs.i18n.ListFormatSymbols_luo_KE', 'goog.labs.i18n.ListFormatSymbols_luy', 'goog.labs.i18n.ListFormatSymbols_luy_KE', 'goog.labs.i18n.ListFormatSymbols_lv_LV', 'goog.labs.i18n.ListFormatSymbols_mas', 'goog.labs.i18n.ListFormatSymbols_mas_KE', 'goog.labs.i18n.ListFormatSymbols_mas_TZ', 'goog.labs.i18n.ListFormatSymbols_mer', 'goog.labs.i18n.ListFormatSymbols_mer_KE', 'goog.labs.i18n.ListFormatSymbols_mfe', 'goog.labs.i18n.ListFormatSymbols_mfe_MU', 'goog.labs.i18n.ListFormatSymbols_mg', 'goog.labs.i18n.ListFormatSymbols_mg_MG', 'goog.labs.i18n.ListFormatSymbols_mgh', 'goog.labs.i18n.ListFormatSymbols_mgh_MZ', 'goog.labs.i18n.ListFormatSymbols_mgo', 'goog.labs.i18n.ListFormatSymbols_mgo_CM', 'goog.labs.i18n.ListFormatSymbols_mk_MK', 'goog.labs.i18n.ListFormatSymbols_ml_IN', 'goog.labs.i18n.ListFormatSymbols_mn_Cyrl', 'goog.labs.i18n.ListFormatSymbols_mn_Cyrl_MN', 'goog.labs.i18n.ListFormatSymbols_mr_IN', 'goog.labs.i18n.ListFormatSymbols_ms_Latn', 'goog.labs.i18n.ListFormatSymbols_ms_Latn_BN', 'goog.labs.i18n.ListFormatSymbols_ms_Latn_MY', 'goog.labs.i18n.ListFormatSymbols_ms_Latn_SG', 'goog.labs.i18n.ListFormatSymbols_mt_MT', 'goog.labs.i18n.ListFormatSymbols_mua', 'goog.labs.i18n.ListFormatSymbols_mua_CM', 'goog.labs.i18n.ListFormatSymbols_my_MM', 'goog.labs.i18n.ListFormatSymbols_naq', 'goog.labs.i18n.ListFormatSymbols_naq_NA', 'goog.labs.i18n.ListFormatSymbols_nb_NO', 'goog.labs.i18n.ListFormatSymbols_nb_SJ', 'goog.labs.i18n.ListFormatSymbols_nd', 'goog.labs.i18n.ListFormatSymbols_nd_ZW', 'goog.labs.i18n.ListFormatSymbols_ne_IN', 'goog.labs.i18n.ListFormatSymbols_ne_NP', 'goog.labs.i18n.ListFormatSymbols_nl_AW', 'goog.labs.i18n.ListFormatSymbols_nl_BE', 'goog.labs.i18n.ListFormatSymbols_nl_BQ', 'goog.labs.i18n.ListFormatSymbols_nl_CW', 'goog.labs.i18n.ListFormatSymbols_nl_NL', 'goog.labs.i18n.ListFormatSymbols_nl_SR', 'goog.labs.i18n.ListFormatSymbols_nl_SX', 'goog.labs.i18n.ListFormatSymbols_nmg', 'goog.labs.i18n.ListFormatSymbols_nmg_CM', 'goog.labs.i18n.ListFormatSymbols_nn', 'goog.labs.i18n.ListFormatSymbols_nn_NO', 'goog.labs.i18n.ListFormatSymbols_nnh', 'goog.labs.i18n.ListFormatSymbols_nnh_CM', 'goog.labs.i18n.ListFormatSymbols_nus', 'goog.labs.i18n.ListFormatSymbols_nus_SD', 'goog.labs.i18n.ListFormatSymbols_nyn', 'goog.labs.i18n.ListFormatSymbols_nyn_UG', 'goog.labs.i18n.ListFormatSymbols_om', 'goog.labs.i18n.ListFormatSymbols_om_ET', 'goog.labs.i18n.ListFormatSymbols_om_KE', 'goog.labs.i18n.ListFormatSymbols_or_IN', 'goog.labs.i18n.ListFormatSymbols_os', 'goog.labs.i18n.ListFormatSymbols_os_GE', 'goog.labs.i18n.ListFormatSymbols_os_RU', 'goog.labs.i18n.ListFormatSymbols_pa_Arab', 'goog.labs.i18n.ListFormatSymbols_pa_Arab_PK', 'goog.labs.i18n.ListFormatSymbols_pa_Guru', 'goog.labs.i18n.ListFormatSymbols_pa_Guru_IN', 'goog.labs.i18n.ListFormatSymbols_pl_PL', 'goog.labs.i18n.ListFormatSymbols_ps', 'goog.labs.i18n.ListFormatSymbols_ps_AF', 'goog.labs.i18n.ListFormatSymbols_pt_AO', 'goog.labs.i18n.ListFormatSymbols_pt_CV', 'goog.labs.i18n.ListFormatSymbols_pt_GW', 'goog.labs.i18n.ListFormatSymbols_pt_MO', 'goog.labs.i18n.ListFormatSymbols_pt_MZ', 'goog.labs.i18n.ListFormatSymbols_pt_ST', 'goog.labs.i18n.ListFormatSymbols_pt_TL', 'goog.labs.i18n.ListFormatSymbols_qu', 'goog.labs.i18n.ListFormatSymbols_qu_BO', 'goog.labs.i18n.ListFormatSymbols_qu_EC', 'goog.labs.i18n.ListFormatSymbols_qu_PE', 'goog.labs.i18n.ListFormatSymbols_rm', 'goog.labs.i18n.ListFormatSymbols_rm_CH', 'goog.labs.i18n.ListFormatSymbols_rn', 'goog.labs.i18n.ListFormatSymbols_rn_BI', 'goog.labs.i18n.ListFormatSymbols_ro_MD', 'goog.labs.i18n.ListFormatSymbols_ro_RO', 'goog.labs.i18n.ListFormatSymbols_rof', 'goog.labs.i18n.ListFormatSymbols_rof_TZ', 'goog.labs.i18n.ListFormatSymbols_ru_BY', 'goog.labs.i18n.ListFormatSymbols_ru_KG', 'goog.labs.i18n.ListFormatSymbols_ru_KZ', 'goog.labs.i18n.ListFormatSymbols_ru_MD', 'goog.labs.i18n.ListFormatSymbols_ru_RU', 'goog.labs.i18n.ListFormatSymbols_ru_UA', 'goog.labs.i18n.ListFormatSymbols_rw', 'goog.labs.i18n.ListFormatSymbols_rw_RW', 'goog.labs.i18n.ListFormatSymbols_rwk', 'goog.labs.i18n.ListFormatSymbols_rwk_TZ', 'goog.labs.i18n.ListFormatSymbols_sah', 'goog.labs.i18n.ListFormatSymbols_sah_RU', 'goog.labs.i18n.ListFormatSymbols_saq', 'goog.labs.i18n.ListFormatSymbols_saq_KE', 'goog.labs.i18n.ListFormatSymbols_sbp', 'goog.labs.i18n.ListFormatSymbols_sbp_TZ', 'goog.labs.i18n.ListFormatSymbols_se', 'goog.labs.i18n.ListFormatSymbols_se_FI', 'goog.labs.i18n.ListFormatSymbols_se_NO', 'goog.labs.i18n.ListFormatSymbols_se_SE', 'goog.labs.i18n.ListFormatSymbols_seh', 'goog.labs.i18n.ListFormatSymbols_seh_MZ', 'goog.labs.i18n.ListFormatSymbols_ses', 'goog.labs.i18n.ListFormatSymbols_ses_ML', 'goog.labs.i18n.ListFormatSymbols_sg', 'goog.labs.i18n.ListFormatSymbols_sg_CF', 'goog.labs.i18n.ListFormatSymbols_shi', 'goog.labs.i18n.ListFormatSymbols_shi_Latn', 'goog.labs.i18n.ListFormatSymbols_shi_Latn_MA', 'goog.labs.i18n.ListFormatSymbols_shi_Tfng', 'goog.labs.i18n.ListFormatSymbols_shi_Tfng_MA', 'goog.labs.i18n.ListFormatSymbols_si_LK', 'goog.labs.i18n.ListFormatSymbols_sk_SK', 'goog.labs.i18n.ListFormatSymbols_sl_SI', 'goog.labs.i18n.ListFormatSymbols_smn', 'goog.labs.i18n.ListFormatSymbols_smn_FI', 'goog.labs.i18n.ListFormatSymbols_sn', 'goog.labs.i18n.ListFormatSymbols_sn_ZW', 'goog.labs.i18n.ListFormatSymbols_so', 'goog.labs.i18n.ListFormatSymbols_so_DJ', 'goog.labs.i18n.ListFormatSymbols_so_ET', 'goog.labs.i18n.ListFormatSymbols_so_KE', 'goog.labs.i18n.ListFormatSymbols_so_SO', 'goog.labs.i18n.ListFormatSymbols_sq_AL', 'goog.labs.i18n.ListFormatSymbols_sq_MK', 'goog.labs.i18n.ListFormatSymbols_sq_XK', 'goog.labs.i18n.ListFormatSymbols_sr_Cyrl', 'goog.labs.i18n.ListFormatSymbols_sr_Cyrl_BA', 'goog.labs.i18n.ListFormatSymbols_sr_Cyrl_ME', 'goog.labs.i18n.ListFormatSymbols_sr_Cyrl_RS', 'goog.labs.i18n.ListFormatSymbols_sr_Cyrl_XK', 'goog.labs.i18n.ListFormatSymbols_sr_Latn', 'goog.labs.i18n.ListFormatSymbols_sr_Latn_BA', 'goog.labs.i18n.ListFormatSymbols_sr_Latn_ME', 'goog.labs.i18n.ListFormatSymbols_sr_Latn_RS', 'goog.labs.i18n.ListFormatSymbols_sr_Latn_XK', 'goog.labs.i18n.ListFormatSymbols_sv_AX', 'goog.labs.i18n.ListFormatSymbols_sv_FI', 'goog.labs.i18n.ListFormatSymbols_sv_SE', 'goog.labs.i18n.ListFormatSymbols_sw_KE', 'goog.labs.i18n.ListFormatSymbols_sw_TZ', 'goog.labs.i18n.ListFormatSymbols_sw_UG', 'goog.labs.i18n.ListFormatSymbols_swc', 'goog.labs.i18n.ListFormatSymbols_swc_CD', 'goog.labs.i18n.ListFormatSymbols_ta_IN', 'goog.labs.i18n.ListFormatSymbols_ta_LK', 'goog.labs.i18n.ListFormatSymbols_ta_MY', 'goog.labs.i18n.ListFormatSymbols_ta_SG', 'goog.labs.i18n.ListFormatSymbols_te_IN', 'goog.labs.i18n.ListFormatSymbols_teo', 'goog.labs.i18n.ListFormatSymbols_teo_KE', 'goog.labs.i18n.ListFormatSymbols_teo_UG', 'goog.labs.i18n.ListFormatSymbols_th_TH', 'goog.labs.i18n.ListFormatSymbols_ti', 'goog.labs.i18n.ListFormatSymbols_ti_ER', 'goog.labs.i18n.ListFormatSymbols_ti_ET', 'goog.labs.i18n.ListFormatSymbols_to', 'goog.labs.i18n.ListFormatSymbols_to_TO', 'goog.labs.i18n.ListFormatSymbols_tr_CY', 'goog.labs.i18n.ListFormatSymbols_tr_TR', 'goog.labs.i18n.ListFormatSymbols_twq', 'goog.labs.i18n.ListFormatSymbols_twq_NE', 'goog.labs.i18n.ListFormatSymbols_tzm', 'goog.labs.i18n.ListFormatSymbols_tzm_Latn', 'goog.labs.i18n.ListFormatSymbols_tzm_Latn_MA', 'goog.labs.i18n.ListFormatSymbols_ug', 'goog.labs.i18n.ListFormatSymbols_ug_Arab', 'goog.labs.i18n.ListFormatSymbols_ug_Arab_CN', 'goog.labs.i18n.ListFormatSymbols_uk_UA', 'goog.labs.i18n.ListFormatSymbols_ur_IN', 'goog.labs.i18n.ListFormatSymbols_ur_PK', 'goog.labs.i18n.ListFormatSymbols_uz_Arab', 'goog.labs.i18n.ListFormatSymbols_uz_Arab_AF', 'goog.labs.i18n.ListFormatSymbols_uz_Cyrl', 'goog.labs.i18n.ListFormatSymbols_uz_Cyrl_UZ', 'goog.labs.i18n.ListFormatSymbols_uz_Latn', 'goog.labs.i18n.ListFormatSymbols_uz_Latn_UZ', 'goog.labs.i18n.ListFormatSymbols_vai', 'goog.labs.i18n.ListFormatSymbols_vai_Latn', 'goog.labs.i18n.ListFormatSymbols_vai_Latn_LR', 'goog.labs.i18n.ListFormatSymbols_vai_Vaii', 'goog.labs.i18n.ListFormatSymbols_vai_Vaii_LR', 'goog.labs.i18n.ListFormatSymbols_vi_VN', 'goog.labs.i18n.ListFormatSymbols_vun', 'goog.labs.i18n.ListFormatSymbols_vun_TZ', 'goog.labs.i18n.ListFormatSymbols_wae', 'goog.labs.i18n.ListFormatSymbols_wae_CH', 'goog.labs.i18n.ListFormatSymbols_xog', 'goog.labs.i18n.ListFormatSymbols_xog_UG', 'goog.labs.i18n.ListFormatSymbols_yav', 'goog.labs.i18n.ListFormatSymbols_yav_CM', 'goog.labs.i18n.ListFormatSymbols_yi', 'goog.labs.i18n.ListFormatSymbols_yi_001', 'goog.labs.i18n.ListFormatSymbols_yo', 'goog.labs.i18n.ListFormatSymbols_yo_BJ', 'goog.labs.i18n.ListFormatSymbols_yo_NG', 'goog.labs.i18n.ListFormatSymbols_zgh', 'goog.labs.i18n.ListFormatSymbols_zgh_MA', 'goog.labs.i18n.ListFormatSymbols_zh_Hans', 'goog.labs.i18n.ListFormatSymbols_zh_Hans_CN', 'goog.labs.i18n.ListFormatSymbols_zh_Hans_HK', 'goog.labs.i18n.ListFormatSymbols_zh_Hans_MO', 'goog.labs.i18n.ListFormatSymbols_zh_Hans_SG', 'goog.labs.i18n.ListFormatSymbols_zh_Hant', 'goog.labs.i18n.ListFormatSymbols_zh_Hant_HK', 'goog.labs.i18n.ListFormatSymbols_zh_Hant_MO', 'goog.labs.i18n.ListFormatSymbols_zh_Hant_TW', 'goog.labs.i18n.ListFormatSymbols_zu_ZA'], ['goog.labs.i18n.ListFormatSymbols'], false); -goog.addDependency('labs/iterable/iterable.js', ['goog.labs.iterable'], [], true); -goog.addDependency('labs/iterable/iterable_test.js', ['goog.labs.iterableTest'], ['goog.labs.iterable', 'goog.testing.jsunit', 'goog.testing.recordFunction'], true); -goog.addDependency('labs/mock/mock.js', ['goog.labs.mock', 'goog.labs.mock.VerificationError'], ['goog.array', 'goog.asserts', 'goog.debug', 'goog.debug.Error', 'goog.functions', 'goog.object'], false); -goog.addDependency('labs/mock/mock_test.js', ['goog.labs.mockTest'], ['goog.array', 'goog.labs.mock', 'goog.labs.mock.VerificationError', 'goog.labs.testing.AnythingMatcher', 'goog.labs.testing.GreaterThanMatcher', 'goog.string', 'goog.testing.jsunit'], false); -goog.addDependency('labs/net/image.js', ['goog.labs.net.image'], ['goog.Promise', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.net.EventType', 'goog.userAgent'], false); -goog.addDependency('labs/net/image_test.js', ['goog.labs.net.imageTest'], ['goog.labs.net.image', 'goog.string', 'goog.testing.AsyncTestCase', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false); -goog.addDependency('labs/net/webchannel.js', ['goog.net.WebChannel'], ['goog.events', 'goog.events.Event'], false); -goog.addDependency('labs/net/webchannel/basetestchannel.js', ['goog.labs.net.webChannel.BaseTestChannel'], ['goog.labs.net.webChannel.Channel', 'goog.labs.net.webChannel.ChannelRequest', 'goog.labs.net.webChannel.requestStats', 'goog.labs.net.webChannel.requestStats.Stat'], false); -goog.addDependency('labs/net/webchannel/channel.js', ['goog.labs.net.webChannel.Channel'], [], false); -goog.addDependency('labs/net/webchannel/channelrequest.js', ['goog.labs.net.webChannel.ChannelRequest'], ['goog.Timer', 'goog.async.Throttle', 'goog.events.EventHandler', 'goog.labs.net.webChannel.requestStats', 'goog.labs.net.webChannel.requestStats.ServerReachability', 'goog.labs.net.webChannel.requestStats.Stat', 'goog.net.ErrorCode', 'goog.net.EventType', 'goog.net.XmlHttp', 'goog.object', 'goog.uri.utils.StandardQueryParam', 'goog.userAgent'], false); -goog.addDependency('labs/net/webchannel/channelrequest_test.js', ['goog.labs.net.webChannel.channelRequestTest'], ['goog.Uri', 'goog.functions', 'goog.labs.net.webChannel.ChannelRequest', 'goog.labs.net.webChannel.WebChannelDebug', 'goog.labs.net.webChannel.requestStats', 'goog.labs.net.webChannel.requestStats.ServerReachability', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.net.XhrIo', 'goog.testing.recordFunction'], false); -goog.addDependency('labs/net/webchannel/connectionstate.js', ['goog.labs.net.webChannel.ConnectionState'], [], false); -goog.addDependency('labs/net/webchannel/forwardchannelrequestpool.js', ['goog.labs.net.webChannel.ForwardChannelRequestPool'], ['goog.array', 'goog.string', 'goog.structs.Set'], false); -goog.addDependency('labs/net/webchannel/forwardchannelrequestpool_test.js', ['goog.labs.net.webChannel.forwardChannelRequestPoolTest'], ['goog.labs.net.webChannel.ChannelRequest', 'goog.labs.net.webChannel.ForwardChannelRequestPool', 'goog.testing.PropertyReplacer', 'goog.testing.asserts', 'goog.testing.jsunit'], false); -goog.addDependency('labs/net/webchannel/netutils.js', ['goog.labs.net.webChannel.netUtils'], ['goog.Uri', 'goog.labs.net.webChannel.WebChannelDebug'], false); -goog.addDependency('labs/net/webchannel/requeststats.js', ['goog.labs.net.webChannel.requestStats', 'goog.labs.net.webChannel.requestStats.Event', 'goog.labs.net.webChannel.requestStats.ServerReachability', 'goog.labs.net.webChannel.requestStats.ServerReachabilityEvent', 'goog.labs.net.webChannel.requestStats.Stat', 'goog.labs.net.webChannel.requestStats.StatEvent', 'goog.labs.net.webChannel.requestStats.TimingEvent'], ['goog.events.Event', 'goog.events.EventTarget'], false); -goog.addDependency('labs/net/webchannel/webchannelbase.js', ['goog.labs.net.webChannel.WebChannelBase'], ['goog.Uri', 'goog.array', 'goog.asserts', 'goog.debug.TextFormatter', 'goog.json', 'goog.labs.net.webChannel.BaseTestChannel', 'goog.labs.net.webChannel.Channel', 'goog.labs.net.webChannel.ChannelRequest', 'goog.labs.net.webChannel.ConnectionState', 'goog.labs.net.webChannel.ForwardChannelRequestPool', 'goog.labs.net.webChannel.WebChannelDebug', 'goog.labs.net.webChannel.Wire', 'goog.labs.net.webChannel.WireV8', 'goog.labs.net.webChannel.netUtils', 'goog.labs.net.webChannel.requestStats', 'goog.labs.net.webChannel.requestStats.Stat', 'goog.log', 'goog.net.XhrIo', 'goog.object', 'goog.string', 'goog.structs', 'goog.structs.CircularBuffer'], false); -goog.addDependency('labs/net/webchannel/webchannelbase_test.js', ['goog.labs.net.webChannel.webChannelBaseTest'], ['goog.Timer', 'goog.array', 'goog.dom', 'goog.functions', 'goog.json', 'goog.labs.net.webChannel.ChannelRequest', 'goog.labs.net.webChannel.ForwardChannelRequestPool', 'goog.labs.net.webChannel.WebChannelBase', 'goog.labs.net.webChannel.WebChannelBaseTransport', 'goog.labs.net.webChannel.WebChannelDebug', 'goog.labs.net.webChannel.Wire', 'goog.labs.net.webChannel.netUtils', 'goog.labs.net.webChannel.requestStats', 'goog.labs.net.webChannel.requestStats.Stat', 'goog.structs.Map', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.asserts', 'goog.testing.jsunit'], false); -goog.addDependency('labs/net/webchannel/webchannelbasetransport.js', ['goog.labs.net.webChannel.WebChannelBaseTransport'], ['goog.asserts', 'goog.events.EventTarget', 'goog.labs.net.webChannel.ChannelRequest', 'goog.labs.net.webChannel.WebChannelBase', 'goog.log', 'goog.net.WebChannel', 'goog.net.WebChannelTransport', 'goog.object', 'goog.string.path'], false); -goog.addDependency('labs/net/webchannel/webchannelbasetransport_test.js', ['goog.labs.net.webChannel.webChannelBaseTransportTest'], ['goog.events', 'goog.functions', 'goog.labs.net.webChannel.ChannelRequest', 'goog.labs.net.webChannel.WebChannelBaseTransport', 'goog.net.WebChannel', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false); -goog.addDependency('labs/net/webchannel/webchanneldebug.js', ['goog.labs.net.webChannel.WebChannelDebug'], ['goog.json', 'goog.log'], false); -goog.addDependency('labs/net/webchannel/wire.js', ['goog.labs.net.webChannel.Wire'], [], false); -goog.addDependency('labs/net/webchannel/wirev8.js', ['goog.labs.net.webChannel.WireV8'], ['goog.asserts', 'goog.json', 'goog.json.NativeJsonProcessor', 'goog.structs'], false); -goog.addDependency('labs/net/webchannel/wirev8_test.js', ['goog.labs.net.webChannel.WireV8Test'], ['goog.labs.net.webChannel.WireV8', 'goog.testing.jsunit'], false); -goog.addDependency('labs/net/webchanneltransport.js', ['goog.net.WebChannelTransport'], [], false); -goog.addDependency('labs/net/webchanneltransportfactory.js', ['goog.net.createWebChannelTransport'], ['goog.functions', 'goog.labs.net.webChannel.WebChannelBaseTransport'], false); -goog.addDependency('labs/net/xhr.js', ['goog.labs.net.xhr', 'goog.labs.net.xhr.Error', 'goog.labs.net.xhr.HttpError', 'goog.labs.net.xhr.Options', 'goog.labs.net.xhr.PostData', 'goog.labs.net.xhr.ResponseType', 'goog.labs.net.xhr.TimeoutError'], ['goog.Promise', 'goog.debug.Error', 'goog.json', 'goog.net.HttpStatus', 'goog.net.XmlHttp', 'goog.string', 'goog.uri.utils', 'goog.userAgent'], false); -goog.addDependency('labs/net/xhr_test.js', ['goog.labs.net.xhrTest'], ['goog.Promise', 'goog.labs.net.xhr', 'goog.net.WrapperXmlHttpFactory', 'goog.net.XmlHttp', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('labs/object/object.js', ['goog.labs.object'], [], false); -goog.addDependency('labs/object/object_test.js', ['goog.labs.objectTest'], ['goog.labs.object', 'goog.testing.jsunit'], false); -goog.addDependency('labs/pubsub/broadcastpubsub.js', ['goog.labs.pubsub.BroadcastPubSub'], ['goog.Disposable', 'goog.Timer', 'goog.array', 'goog.async.run', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.json', 'goog.log', 'goog.math', 'goog.pubsub.PubSub', 'goog.storage.Storage', 'goog.storage.mechanism.HTML5LocalStorage', 'goog.string', 'goog.userAgent'], false); -goog.addDependency('labs/pubsub/broadcastpubsub_test.js', ['goog.labs.pubsub.BroadcastPubSubTest'], ['goog.array', 'goog.debug.Logger', 'goog.json', 'goog.labs.pubsub.BroadcastPubSub', 'goog.storage.Storage', 'goog.structs.Map', 'goog.testing.MockClock', 'goog.testing.MockControl', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.testing.mockmatchers', 'goog.testing.mockmatchers.ArgumentMatcher', 'goog.testing.recordFunction', 'goog.userAgent'], false); -goog.addDependency('labs/storage/boundedcollectablestorage.js', ['goog.labs.storage.BoundedCollectableStorage'], ['goog.array', 'goog.asserts', 'goog.iter', 'goog.storage.CollectableStorage', 'goog.storage.ErrorCode', 'goog.storage.ExpiringStorage'], false); -goog.addDependency('labs/storage/boundedcollectablestorage_test.js', ['goog.labs.storage.BoundedCollectableStorageTest'], ['goog.labs.storage.BoundedCollectableStorage', 'goog.storage.collectableStorageTester', 'goog.storage.storage_test', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.testing.storage.FakeMechanism'], false); -goog.addDependency('labs/structs/map.js', ['goog.labs.structs.Map'], ['goog.array', 'goog.asserts', 'goog.labs.object', 'goog.object'], false); -goog.addDependency('labs/structs/map_perf.js', ['goog.labs.structs.MapPerf'], ['goog.asserts', 'goog.dom', 'goog.labs.structs.Map', 'goog.structs.Map', 'goog.testing.PerformanceTable', 'goog.testing.jsunit'], false); -goog.addDependency('labs/structs/map_test.js', ['goog.labs.structs.MapTest'], ['goog.labs.structs.Map', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false); -goog.addDependency('labs/structs/multimap.js', ['goog.labs.structs.Multimap'], ['goog.array', 'goog.labs.object', 'goog.labs.structs.Map'], false); -goog.addDependency('labs/structs/multimap_test.js', ['goog.labs.structs.MultimapTest'], ['goog.labs.structs.Map', 'goog.labs.structs.Multimap', 'goog.testing.jsunit'], false); -goog.addDependency('labs/style/pixeldensitymonitor.js', ['goog.labs.style.PixelDensityMonitor', 'goog.labs.style.PixelDensityMonitor.Density', 'goog.labs.style.PixelDensityMonitor.EventType'], ['goog.events', 'goog.events.EventTarget'], false); -goog.addDependency('labs/style/pixeldensitymonitor_test.js', ['goog.labs.style.PixelDensityMonitorTest'], ['goog.array', 'goog.dom.DomHelper', 'goog.events', 'goog.labs.style.PixelDensityMonitor', 'goog.testing.MockControl', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false); -goog.addDependency('labs/testing/assertthat.js', ['goog.labs.testing.MatcherError', 'goog.labs.testing.assertThat'], ['goog.debug.Error'], false); -goog.addDependency('labs/testing/assertthat_test.js', ['goog.labs.testing.assertThatTest'], ['goog.labs.testing.MatcherError', 'goog.labs.testing.assertThat', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false); -goog.addDependency('labs/testing/decoratormatcher.js', ['goog.labs.testing.AnythingMatcher'], ['goog.labs.testing.Matcher'], false); -goog.addDependency('labs/testing/decoratormatcher_test.js', ['goog.labs.testing.decoratorMatcherTest'], ['goog.labs.testing.AnythingMatcher', 'goog.labs.testing.GreaterThanMatcher', 'goog.labs.testing.MatcherError', 'goog.labs.testing.assertThat', 'goog.testing.jsunit'], false); -goog.addDependency('labs/testing/dictionarymatcher.js', ['goog.labs.testing.HasEntriesMatcher', 'goog.labs.testing.HasEntryMatcher', 'goog.labs.testing.HasKeyMatcher', 'goog.labs.testing.HasValueMatcher'], ['goog.asserts', 'goog.labs.testing.Matcher', 'goog.object'], false); -goog.addDependency('labs/testing/dictionarymatcher_test.js', ['goog.labs.testing.dictionaryMatcherTest'], ['goog.labs.testing.HasEntryMatcher', 'goog.labs.testing.MatcherError', 'goog.labs.testing.assertThat', 'goog.testing.jsunit'], false); -goog.addDependency('labs/testing/environment.js', ['goog.labs.testing.Environment'], ['goog.array', 'goog.debug.Console', 'goog.testing.MockClock', 'goog.testing.MockControl', 'goog.testing.TestCase', 'goog.testing.jsunit'], false); -goog.addDependency('labs/testing/environment_test.js', ['goog.labs.testing.environmentTest'], ['goog.labs.testing.Environment', 'goog.testing.MockControl', 'goog.testing.TestCase', 'goog.testing.jsunit'], false); -goog.addDependency('labs/testing/environment_usage_test.js', ['goog.labs.testing.environmentUsageTest'], ['goog.labs.testing.Environment'], false); -goog.addDependency('labs/testing/logicmatcher.js', ['goog.labs.testing.AllOfMatcher', 'goog.labs.testing.AnyOfMatcher', 'goog.labs.testing.IsNotMatcher'], ['goog.array', 'goog.labs.testing.Matcher'], false); -goog.addDependency('labs/testing/logicmatcher_test.js', ['goog.labs.testing.logicMatcherTest'], ['goog.labs.testing.AllOfMatcher', 'goog.labs.testing.GreaterThanMatcher', 'goog.labs.testing.MatcherError', 'goog.labs.testing.assertThat', 'goog.testing.jsunit'], false); -goog.addDependency('labs/testing/matcher.js', ['goog.labs.testing.Matcher'], [], false); -goog.addDependency('labs/testing/numbermatcher.js', ['goog.labs.testing.CloseToMatcher', 'goog.labs.testing.EqualToMatcher', 'goog.labs.testing.GreaterThanEqualToMatcher', 'goog.labs.testing.GreaterThanMatcher', 'goog.labs.testing.LessThanEqualToMatcher', 'goog.labs.testing.LessThanMatcher'], ['goog.asserts', 'goog.labs.testing.Matcher'], false); -goog.addDependency('labs/testing/numbermatcher_test.js', ['goog.labs.testing.numberMatcherTest'], ['goog.labs.testing.LessThanMatcher', 'goog.labs.testing.MatcherError', 'goog.labs.testing.assertThat', 'goog.testing.jsunit'], false); -goog.addDependency('labs/testing/objectmatcher.js', ['goog.labs.testing.HasPropertyMatcher', 'goog.labs.testing.InstanceOfMatcher', 'goog.labs.testing.IsNullMatcher', 'goog.labs.testing.IsNullOrUndefinedMatcher', 'goog.labs.testing.IsUndefinedMatcher', 'goog.labs.testing.ObjectEqualsMatcher'], ['goog.labs.testing.Matcher'], false); -goog.addDependency('labs/testing/objectmatcher_test.js', ['goog.labs.testing.objectMatcherTest'], ['goog.labs.testing.MatcherError', 'goog.labs.testing.ObjectEqualsMatcher', 'goog.labs.testing.assertThat', 'goog.testing.jsunit'], false); -goog.addDependency('labs/testing/stringmatcher.js', ['goog.labs.testing.ContainsStringMatcher', 'goog.labs.testing.EndsWithMatcher', 'goog.labs.testing.EqualToIgnoringWhitespaceMatcher', 'goog.labs.testing.EqualsMatcher', 'goog.labs.testing.RegexMatcher', 'goog.labs.testing.StartsWithMatcher', 'goog.labs.testing.StringContainsInOrderMatcher'], ['goog.asserts', 'goog.labs.testing.Matcher', 'goog.string'], false); -goog.addDependency('labs/testing/stringmatcher_test.js', ['goog.labs.testing.stringMatcherTest'], ['goog.labs.testing.MatcherError', 'goog.labs.testing.StringContainsInOrderMatcher', 'goog.labs.testing.assertThat', 'goog.testing.jsunit'], false); -goog.addDependency('labs/useragent/browser.js', ['goog.labs.userAgent.browser'], ['goog.array', 'goog.labs.userAgent.util', 'goog.object', 'goog.string'], false); -goog.addDependency('labs/useragent/browser_test.js', ['goog.labs.userAgent.browserTest'], ['goog.labs.userAgent.browser', 'goog.labs.userAgent.testAgents', 'goog.labs.userAgent.util', 'goog.object', 'goog.testing.jsunit'], false); -goog.addDependency('labs/useragent/device.js', ['goog.labs.userAgent.device'], ['goog.labs.userAgent.util'], false); -goog.addDependency('labs/useragent/device_test.js', ['goog.labs.userAgent.deviceTest'], ['goog.labs.userAgent.device', 'goog.labs.userAgent.testAgents', 'goog.labs.userAgent.util', 'goog.testing.jsunit'], false); -goog.addDependency('labs/useragent/engine.js', ['goog.labs.userAgent.engine'], ['goog.array', 'goog.labs.userAgent.util', 'goog.string'], false); -goog.addDependency('labs/useragent/engine_test.js', ['goog.labs.userAgent.engineTest'], ['goog.labs.userAgent.engine', 'goog.labs.userAgent.testAgents', 'goog.labs.userAgent.util', 'goog.testing.jsunit'], false); -goog.addDependency('labs/useragent/platform.js', ['goog.labs.userAgent.platform'], ['goog.labs.userAgent.util', 'goog.string'], false); -goog.addDependency('labs/useragent/platform_test.js', ['goog.labs.userAgent.platformTest'], ['goog.labs.userAgent.platform', 'goog.labs.userAgent.testAgents', 'goog.labs.userAgent.util', 'goog.testing.jsunit'], false); -goog.addDependency('labs/useragent/test_agents.js', ['goog.labs.userAgent.testAgents'], [], false); -goog.addDependency('labs/useragent/util.js', ['goog.labs.userAgent.util'], ['goog.string'], false); -goog.addDependency('labs/useragent/util_test.js', ['goog.labs.userAgent.utilTest'], ['goog.functions', 'goog.labs.userAgent.testAgents', 'goog.labs.userAgent.util', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false); -goog.addDependency('locale/countries.js', ['goog.locale.countries'], [], false); -goog.addDependency('locale/countrylanguagenames_test.js', ['goog.locale.countryLanguageNamesTest'], ['goog.locale', 'goog.testing.jsunit'], false); -goog.addDependency('locale/defaultlocalenameconstants.js', ['goog.locale.defaultLocaleNameConstants'], [], false); -goog.addDependency('locale/genericfontnames.js', ['goog.locale.genericFontNames'], [], false); -goog.addDependency('locale/genericfontnames_test.js', ['goog.locale.genericFontNamesTest'], ['goog.locale.genericFontNames', 'goog.testing.jsunit'], false); -goog.addDependency('locale/genericfontnamesdata.js', ['goog.locale.genericFontNamesData'], [], false); -goog.addDependency('locale/locale.js', ['goog.locale'], ['goog.locale.nativeNameConstants'], false); -goog.addDependency('locale/nativenameconstants.js', ['goog.locale.nativeNameConstants'], [], false); -goog.addDependency('locale/scriptToLanguages.js', ['goog.locale.scriptToLanguages'], ['goog.locale'], false); -goog.addDependency('locale/timezonedetection.js', ['goog.locale.timeZoneDetection'], ['goog.locale.TimeZoneFingerprint'], false); -goog.addDependency('locale/timezonedetection_test.js', ['goog.locale.timeZoneDetectionTest'], ['goog.locale.timeZoneDetection', 'goog.testing.jsunit'], false); -goog.addDependency('locale/timezonefingerprint.js', ['goog.locale.TimeZoneFingerprint'], [], false); -goog.addDependency('locale/timezonelist.js', ['goog.locale.TimeZoneList'], ['goog.locale'], false); -goog.addDependency('locale/timezonelist_test.js', ['goog.locale.TimeZoneListTest'], ['goog.locale', 'goog.locale.TimeZoneList', 'goog.testing.jsunit'], false); -goog.addDependency('log/log.js', ['goog.log', 'goog.log.Level', 'goog.log.LogRecord', 'goog.log.Logger'], ['goog.debug', 'goog.debug.LogManager', 'goog.debug.LogRecord', 'goog.debug.Logger'], false); -goog.addDependency('log/log_test.js', ['goog.logTest'], ['goog.debug.LogManager', 'goog.log', 'goog.log.Level', 'goog.testing.jsunit'], false); -goog.addDependency('math/affinetransform.js', ['goog.math.AffineTransform'], ['goog.math'], false); -goog.addDependency('math/affinetransform_test.js', ['goog.math.AffineTransformTest'], ['goog.array', 'goog.math', 'goog.math.AffineTransform', 'goog.testing.jsunit'], false); -goog.addDependency('math/bezier.js', ['goog.math.Bezier'], ['goog.math', 'goog.math.Coordinate'], false); -goog.addDependency('math/bezier_test.js', ['goog.math.BezierTest'], ['goog.math', 'goog.math.Bezier', 'goog.math.Coordinate', 'goog.testing.jsunit'], false); -goog.addDependency('math/box.js', ['goog.math.Box'], ['goog.math.Coordinate'], false); -goog.addDependency('math/box_test.js', ['goog.math.BoxTest'], ['goog.math.Box', 'goog.math.Coordinate', 'goog.testing.jsunit'], false); -goog.addDependency('math/coordinate.js', ['goog.math.Coordinate'], ['goog.math'], false); -goog.addDependency('math/coordinate3.js', ['goog.math.Coordinate3'], [], false); -goog.addDependency('math/coordinate3_test.js', ['goog.math.Coordinate3Test'], ['goog.math.Coordinate3', 'goog.testing.jsunit'], false); -goog.addDependency('math/coordinate_test.js', ['goog.math.CoordinateTest'], ['goog.math.Coordinate', 'goog.testing.jsunit'], false); -goog.addDependency('math/exponentialbackoff.js', ['goog.math.ExponentialBackoff'], ['goog.asserts'], false); -goog.addDependency('math/exponentialbackoff_test.js', ['goog.math.ExponentialBackoffTest'], ['goog.math.ExponentialBackoff', 'goog.testing.jsunit'], false); -goog.addDependency('math/integer.js', ['goog.math.Integer'], [], false); -goog.addDependency('math/integer_test.js', ['goog.math.IntegerTest'], ['goog.math.Integer', 'goog.testing.jsunit'], false); -goog.addDependency('math/interpolator/interpolator1.js', ['goog.math.interpolator.Interpolator1'], [], false); -goog.addDependency('math/interpolator/linear1.js', ['goog.math.interpolator.Linear1'], ['goog.array', 'goog.asserts', 'goog.math', 'goog.math.interpolator.Interpolator1'], false); -goog.addDependency('math/interpolator/linear1_test.js', ['goog.math.interpolator.Linear1Test'], ['goog.math.interpolator.Linear1', 'goog.testing.jsunit'], false); -goog.addDependency('math/interpolator/pchip1.js', ['goog.math.interpolator.Pchip1'], ['goog.math', 'goog.math.interpolator.Spline1'], false); -goog.addDependency('math/interpolator/pchip1_test.js', ['goog.math.interpolator.Pchip1Test'], ['goog.math.interpolator.Pchip1', 'goog.testing.jsunit'], false); -goog.addDependency('math/interpolator/spline1.js', ['goog.math.interpolator.Spline1'], ['goog.array', 'goog.asserts', 'goog.math', 'goog.math.interpolator.Interpolator1', 'goog.math.tdma'], false); -goog.addDependency('math/interpolator/spline1_test.js', ['goog.math.interpolator.Spline1Test'], ['goog.math.interpolator.Spline1', 'goog.testing.jsunit'], false); -goog.addDependency('math/line.js', ['goog.math.Line'], ['goog.math', 'goog.math.Coordinate'], false); -goog.addDependency('math/line_test.js', ['goog.math.LineTest'], ['goog.math.Coordinate', 'goog.math.Line', 'goog.testing.jsunit'], false); -goog.addDependency('math/long.js', ['goog.math.Long'], [], false); -goog.addDependency('math/long_test.js', ['goog.math.LongTest'], ['goog.math.Long', 'goog.testing.jsunit'], false); -goog.addDependency('math/math.js', ['goog.math'], ['goog.array', 'goog.asserts'], false); -goog.addDependency('math/math_test.js', ['goog.mathTest'], ['goog.math', 'goog.testing.jsunit'], false); -goog.addDependency('math/matrix.js', ['goog.math.Matrix'], ['goog.array', 'goog.math', 'goog.math.Size', 'goog.string'], false); -goog.addDependency('math/matrix_test.js', ['goog.math.MatrixTest'], ['goog.math.Matrix', 'goog.testing.jsunit'], false); -goog.addDependency('math/path.js', ['goog.math.Path', 'goog.math.Path.Segment'], ['goog.array', 'goog.math'], false); -goog.addDependency('math/path_test.js', ['goog.math.PathTest'], ['goog.array', 'goog.math.AffineTransform', 'goog.math.Path', 'goog.testing.jsunit'], false); -goog.addDependency('math/paths.js', ['goog.math.paths'], ['goog.math.Coordinate', 'goog.math.Path'], false); -goog.addDependency('math/paths_test.js', ['goog.math.pathsTest'], ['goog.math.Coordinate', 'goog.math.paths', 'goog.testing.jsunit'], false); -goog.addDependency('math/range.js', ['goog.math.Range'], ['goog.asserts'], false); -goog.addDependency('math/range_test.js', ['goog.math.RangeTest'], ['goog.math.Range', 'goog.testing.jsunit'], false); -goog.addDependency('math/rangeset.js', ['goog.math.RangeSet'], ['goog.array', 'goog.iter.Iterator', 'goog.iter.StopIteration', 'goog.math.Range'], false); -goog.addDependency('math/rangeset_test.js', ['goog.math.RangeSetTest'], ['goog.iter', 'goog.math.Range', 'goog.math.RangeSet', 'goog.testing.jsunit'], false); -goog.addDependency('math/rect.js', ['goog.math.Rect'], ['goog.math.Box', 'goog.math.Coordinate', 'goog.math.Size'], false); -goog.addDependency('math/rect_test.js', ['goog.math.RectTest'], ['goog.math.Box', 'goog.math.Coordinate', 'goog.math.Rect', 'goog.math.Size', 'goog.testing.jsunit'], false); -goog.addDependency('math/size.js', ['goog.math.Size'], [], false); -goog.addDependency('math/size_test.js', ['goog.math.SizeTest'], ['goog.math.Size', 'goog.testing.jsunit'], false); -goog.addDependency('math/tdma.js', ['goog.math.tdma'], [], false); -goog.addDependency('math/tdma_test.js', ['goog.math.tdmaTest'], ['goog.math.tdma', 'goog.testing.jsunit'], false); -goog.addDependency('math/vec2.js', ['goog.math.Vec2'], ['goog.math', 'goog.math.Coordinate'], false); -goog.addDependency('math/vec2_test.js', ['goog.math.Vec2Test'], ['goog.math.Vec2', 'goog.testing.jsunit'], false); -goog.addDependency('math/vec3.js', ['goog.math.Vec3'], ['goog.math', 'goog.math.Coordinate3'], false); -goog.addDependency('math/vec3_test.js', ['goog.math.Vec3Test'], ['goog.math.Coordinate3', 'goog.math.Vec3', 'goog.testing.jsunit'], false); -goog.addDependency('memoize/memoize.js', ['goog.memoize'], [], false); -goog.addDependency('memoize/memoize_test.js', ['goog.memoizeTest'], ['goog.memoize', 'goog.testing.jsunit'], false); -goog.addDependency('messaging/abstractchannel.js', ['goog.messaging.AbstractChannel'], ['goog.Disposable', 'goog.json', 'goog.log', 'goog.messaging.MessageChannel'], false); -goog.addDependency('messaging/abstractchannel_test.js', ['goog.messaging.AbstractChannelTest'], ['goog.messaging.AbstractChannel', 'goog.testing.MockControl', 'goog.testing.async.MockControl', 'goog.testing.jsunit'], false); -goog.addDependency('messaging/bufferedchannel.js', ['goog.messaging.BufferedChannel'], ['goog.Disposable', 'goog.Timer', 'goog.events', 'goog.log', 'goog.messaging.MessageChannel', 'goog.messaging.MultiChannel'], false); -goog.addDependency('messaging/bufferedchannel_test.js', ['goog.messaging.BufferedChannelTest'], ['goog.debug.Console', 'goog.dom', 'goog.log', 'goog.log.Level', 'goog.messaging.BufferedChannel', 'goog.testing.MockClock', 'goog.testing.MockControl', 'goog.testing.async.MockControl', 'goog.testing.jsunit', 'goog.testing.messaging.MockMessageChannel'], false); -goog.addDependency('messaging/deferredchannel.js', ['goog.messaging.DeferredChannel'], ['goog.Disposable', 'goog.messaging.MessageChannel'], false); -goog.addDependency('messaging/deferredchannel_test.js', ['goog.messaging.DeferredChannelTest'], ['goog.async.Deferred', 'goog.messaging.DeferredChannel', 'goog.testing.MockControl', 'goog.testing.async.MockControl', 'goog.testing.jsunit', 'goog.testing.messaging.MockMessageChannel'], false); -goog.addDependency('messaging/loggerclient.js', ['goog.messaging.LoggerClient'], ['goog.Disposable', 'goog.debug', 'goog.debug.LogManager', 'goog.debug.Logger'], false); -goog.addDependency('messaging/loggerclient_test.js', ['goog.messaging.LoggerClientTest'], ['goog.debug', 'goog.debug.Logger', 'goog.messaging.LoggerClient', 'goog.testing.MockControl', 'goog.testing.jsunit', 'goog.testing.messaging.MockMessageChannel'], false); -goog.addDependency('messaging/loggerserver.js', ['goog.messaging.LoggerServer'], ['goog.Disposable', 'goog.log', 'goog.log.Level'], false); -goog.addDependency('messaging/loggerserver_test.js', ['goog.messaging.LoggerServerTest'], ['goog.debug.LogManager', 'goog.debug.Logger', 'goog.log', 'goog.log.Level', 'goog.messaging.LoggerServer', 'goog.testing.MockControl', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.messaging.MockMessageChannel'], false); -goog.addDependency('messaging/messagechannel.js', ['goog.messaging.MessageChannel'], [], false); -goog.addDependency('messaging/messaging.js', ['goog.messaging'], [], false); -goog.addDependency('messaging/messaging_test.js', ['goog.testing.messaging.MockMessageChannelTest'], ['goog.messaging', 'goog.testing.MockControl', 'goog.testing.jsunit', 'goog.testing.messaging.MockMessageChannel'], false); -goog.addDependency('messaging/multichannel.js', ['goog.messaging.MultiChannel', 'goog.messaging.MultiChannel.VirtualChannel'], ['goog.Disposable', 'goog.log', 'goog.messaging.MessageChannel', 'goog.object'], false); -goog.addDependency('messaging/multichannel_test.js', ['goog.messaging.MultiChannelTest'], ['goog.messaging.MultiChannel', 'goog.testing.MockControl', 'goog.testing.jsunit', 'goog.testing.messaging.MockMessageChannel', 'goog.testing.mockmatchers.IgnoreArgument'], false); -goog.addDependency('messaging/portcaller.js', ['goog.messaging.PortCaller'], ['goog.Disposable', 'goog.async.Deferred', 'goog.messaging.DeferredChannel', 'goog.messaging.PortChannel', 'goog.messaging.PortNetwork', 'goog.object'], false); -goog.addDependency('messaging/portcaller_test.js', ['goog.messaging.PortCallerTest'], ['goog.events.EventTarget', 'goog.messaging.PortCaller', 'goog.messaging.PortNetwork', 'goog.testing.MockControl', 'goog.testing.jsunit', 'goog.testing.messaging.MockMessageChannel'], false); -goog.addDependency('messaging/portchannel.js', ['goog.messaging.PortChannel'], ['goog.Timer', 'goog.array', 'goog.async.Deferred', 'goog.debug', 'goog.events', 'goog.events.EventType', 'goog.json', 'goog.log', 'goog.messaging.AbstractChannel', 'goog.messaging.DeferredChannel', 'goog.object', 'goog.string', 'goog.userAgent'], false); -goog.addDependency('messaging/portnetwork.js', ['goog.messaging.PortNetwork'], [], false); -goog.addDependency('messaging/portoperator.js', ['goog.messaging.PortOperator'], ['goog.Disposable', 'goog.asserts', 'goog.log', 'goog.messaging.PortChannel', 'goog.messaging.PortNetwork', 'goog.object'], false); -goog.addDependency('messaging/portoperator_test.js', ['goog.messaging.PortOperatorTest'], ['goog.messaging.PortNetwork', 'goog.messaging.PortOperator', 'goog.testing.MockControl', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.messaging.MockMessageChannel', 'goog.testing.messaging.MockMessagePort'], false); -goog.addDependency('messaging/respondingchannel.js', ['goog.messaging.RespondingChannel'], ['goog.Disposable', 'goog.log', 'goog.messaging.MultiChannel'], false); -goog.addDependency('messaging/respondingchannel_test.js', ['goog.messaging.RespondingChannelTest'], ['goog.messaging.RespondingChannel', 'goog.testing.MockControl', 'goog.testing.jsunit', 'goog.testing.messaging.MockMessageChannel'], false); -goog.addDependency('messaging/testdata/portchannel_worker.js', ['goog.messaging.testdata.portchannel_worker'], ['goog.messaging.PortChannel'], false); -goog.addDependency('messaging/testdata/portnetwork_worker1.js', ['goog.messaging.testdata.portnetwork_worker1'], ['goog.messaging.PortCaller', 'goog.messaging.PortChannel'], false); -goog.addDependency('messaging/testdata/portnetwork_worker2.js', ['goog.messaging.testdata.portnetwork_worker2'], ['goog.messaging.PortCaller', 'goog.messaging.PortChannel'], false); -goog.addDependency('module/abstractmoduleloader.js', ['goog.module.AbstractModuleLoader'], ['goog.module'], false); -goog.addDependency('module/basemodule.js', ['goog.module.BaseModule'], ['goog.Disposable', 'goog.module'], false); -goog.addDependency('module/loader.js', ['goog.module.Loader'], ['goog.Timer', 'goog.array', 'goog.dom', 'goog.module', 'goog.object'], false); -goog.addDependency('module/module.js', ['goog.module'], [], false); -goog.addDependency('module/moduleinfo.js', ['goog.module.ModuleInfo'], ['goog.Disposable', 'goog.async.throwException', 'goog.functions', 'goog.module', 'goog.module.BaseModule', 'goog.module.ModuleLoadCallback'], false); -goog.addDependency('module/moduleinfo_test.js', ['goog.module.ModuleInfoTest'], ['goog.module.BaseModule', 'goog.module.ModuleInfo', 'goog.testing.MockClock', 'goog.testing.jsunit'], false); -goog.addDependency('module/moduleloadcallback.js', ['goog.module.ModuleLoadCallback'], ['goog.debug.entryPointRegistry', 'goog.debug.errorHandlerWeakDep', 'goog.module'], false); -goog.addDependency('module/moduleloadcallback_test.js', ['goog.module.ModuleLoadCallbackTest'], ['goog.debug.ErrorHandler', 'goog.debug.entryPointRegistry', 'goog.functions', 'goog.module.ModuleLoadCallback', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false); -goog.addDependency('module/moduleloader.js', ['goog.module.ModuleLoader'], ['goog.Timer', 'goog.array', 'goog.events', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.log', 'goog.module.AbstractModuleLoader', 'goog.net.BulkLoader', 'goog.net.EventType', 'goog.net.jsloader', 'goog.userAgent', 'goog.userAgent.product'], false); -goog.addDependency('module/moduleloader_test.js', ['goog.module.ModuleLoaderTest'], ['goog.array', 'goog.dom', 'goog.events', 'goog.functions', 'goog.module.ModuleLoader', 'goog.module.ModuleManager', 'goog.net.BulkLoader', 'goog.net.XmlHttp', 'goog.object', 'goog.testing.AsyncTestCase', 'goog.testing.PropertyReplacer', 'goog.testing.events.EventObserver', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('module/modulemanager.js', ['goog.module.ModuleManager', 'goog.module.ModuleManager.CallbackType', 'goog.module.ModuleManager.FailureType'], ['goog.Disposable', 'goog.array', 'goog.asserts', 'goog.async.Deferred', 'goog.debug.Trace', 'goog.dispose', 'goog.log', 'goog.module', 'goog.module.ModuleInfo', 'goog.module.ModuleLoadCallback', 'goog.object'], false); -goog.addDependency('module/modulemanager_test.js', ['goog.module.ModuleManagerTest'], ['goog.array', 'goog.functions', 'goog.module.BaseModule', 'goog.module.ModuleManager', 'goog.testing', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false); -goog.addDependency('module/testdata/modA_1.js', ['goog.module.testdata.modA_1'], [], false); -goog.addDependency('module/testdata/modA_2.js', ['goog.module.testdata.modA_2'], ['goog.module.ModuleManager'], false); -goog.addDependency('module/testdata/modB_1.js', ['goog.module.testdata.modB_1'], ['goog.module.ModuleManager'], false); -goog.addDependency('net/browserchannel.js', ['goog.net.BrowserChannel', 'goog.net.BrowserChannel.Error', 'goog.net.BrowserChannel.Event', 'goog.net.BrowserChannel.Handler', 'goog.net.BrowserChannel.LogSaver', 'goog.net.BrowserChannel.QueuedMap', 'goog.net.BrowserChannel.ServerReachability', 'goog.net.BrowserChannel.ServerReachabilityEvent', 'goog.net.BrowserChannel.Stat', 'goog.net.BrowserChannel.StatEvent', 'goog.net.BrowserChannel.State', 'goog.net.BrowserChannel.TimingEvent'], ['goog.Uri', 'goog.array', 'goog.asserts', 'goog.debug.TextFormatter', 'goog.events.Event', 'goog.events.EventTarget', 'goog.json', 'goog.json.EvalJsonProcessor', 'goog.log', 'goog.net.BrowserTestChannel', 'goog.net.ChannelDebug', 'goog.net.ChannelRequest', 'goog.net.XhrIo', 'goog.net.tmpnetwork', 'goog.object', 'goog.string', 'goog.structs', 'goog.structs.CircularBuffer'], false); -goog.addDependency('net/browserchannel_test.js', ['goog.net.BrowserChannelTest'], ['goog.Timer', 'goog.array', 'goog.dom', 'goog.functions', 'goog.json', 'goog.net.BrowserChannel', 'goog.net.ChannelDebug', 'goog.net.ChannelRequest', 'goog.net.tmpnetwork', 'goog.structs.Map', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false); -goog.addDependency('net/browsertestchannel.js', ['goog.net.BrowserTestChannel'], ['goog.json.EvalJsonProcessor', 'goog.net.ChannelRequest', 'goog.net.ChannelRequest.Error', 'goog.net.tmpnetwork', 'goog.string.Parser', 'goog.userAgent'], false); -goog.addDependency('net/bulkloader.js', ['goog.net.BulkLoader'], ['goog.events.EventHandler', 'goog.events.EventTarget', 'goog.log', 'goog.net.BulkLoaderHelper', 'goog.net.EventType', 'goog.net.XhrIo'], false); -goog.addDependency('net/bulkloader_test.js', ['goog.net.BulkLoaderTest'], ['goog.events.Event', 'goog.events.EventHandler', 'goog.net.BulkLoader', 'goog.net.EventType', 'goog.testing.MockClock', 'goog.testing.jsunit'], false); -goog.addDependency('net/bulkloaderhelper.js', ['goog.net.BulkLoaderHelper'], ['goog.Disposable', 'goog.log'], false); -goog.addDependency('net/channeldebug.js', ['goog.net.ChannelDebug'], ['goog.json', 'goog.log'], false); -goog.addDependency('net/channelrequest.js', ['goog.net.ChannelRequest', 'goog.net.ChannelRequest.Error'], ['goog.Timer', 'goog.async.Throttle', 'goog.events.EventHandler', 'goog.net.ErrorCode', 'goog.net.EventType', 'goog.net.XmlHttp', 'goog.object', 'goog.userAgent'], false); -goog.addDependency('net/channelrequest_test.js', ['goog.net.ChannelRequestTest'], ['goog.Uri', 'goog.functions', 'goog.net.BrowserChannel', 'goog.net.ChannelDebug', 'goog.net.ChannelRequest', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.net.XhrIo', 'goog.testing.recordFunction'], false); -goog.addDependency('net/cookies.js', ['goog.net.Cookies', 'goog.net.cookies'], [], false); -goog.addDependency('net/cookies_test.js', ['goog.net.cookiesTest'], ['goog.array', 'goog.net.cookies', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false); -goog.addDependency('net/corsxmlhttpfactory.js', ['goog.net.CorsXmlHttpFactory', 'goog.net.IeCorsXhrAdapter'], ['goog.net.HttpStatus', 'goog.net.XhrLike', 'goog.net.XmlHttp', 'goog.net.XmlHttpFactory'], false); -goog.addDependency('net/corsxmlhttpfactory_test.js', ['goog.net.CorsXmlHttpFactoryTest'], ['goog.net.CorsXmlHttpFactory', 'goog.net.IeCorsXhrAdapter', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('net/crossdomainrpc.js', ['goog.net.CrossDomainRpc'], ['goog.Uri', 'goog.dom', 'goog.dom.safe', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.html.legacyconversions', 'goog.json', 'goog.log', 'goog.net.EventType', 'goog.net.HttpStatus', 'goog.string', 'goog.userAgent'], false); -goog.addDependency('net/crossdomainrpc_test.js', ['goog.net.CrossDomainRpcTest'], ['goog.log', 'goog.log.Level', 'goog.net.CrossDomainRpc', 'goog.testing.AsyncTestCase', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('net/errorcode.js', ['goog.net.ErrorCode'], [], false); -goog.addDependency('net/eventtype.js', ['goog.net.EventType'], [], false); -goog.addDependency('net/filedownloader.js', ['goog.net.FileDownloader', 'goog.net.FileDownloader.Error'], ['goog.Disposable', 'goog.asserts', 'goog.async.Deferred', 'goog.crypt.hash32', 'goog.debug.Error', 'goog.events', 'goog.events.EventHandler', 'goog.fs', 'goog.fs.DirectoryEntry', 'goog.fs.Error', 'goog.fs.FileSaver', 'goog.net.EventType', 'goog.net.XhrIo', 'goog.net.XhrIoPool', 'goog.object'], false); -goog.addDependency('net/filedownloader_test.js', ['goog.net.FileDownloaderTest'], ['goog.fs.Error', 'goog.net.ErrorCode', 'goog.net.FileDownloader', 'goog.net.XhrIo', 'goog.testing.AsyncTestCase', 'goog.testing.PropertyReplacer', 'goog.testing.fs', 'goog.testing.fs.FileSystem', 'goog.testing.jsunit', 'goog.testing.net.XhrIoPool'], false); -goog.addDependency('net/httpstatus.js', ['goog.net.HttpStatus'], [], false); -goog.addDependency('net/iframe_xhr_test.js', ['goog.net.iframeXhrTest'], ['goog.Timer', 'goog.debug.Console', 'goog.debug.LogManager', 'goog.debug.Logger', 'goog.events', 'goog.net.IframeIo', 'goog.net.XhrIo', 'goog.testing.AsyncTestCase', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('net/iframeio.js', ['goog.net.IframeIo', 'goog.net.IframeIo.IncrementalDataEvent'], ['goog.Timer', 'goog.Uri', 'goog.asserts', 'goog.debug', 'goog.dom', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.json', 'goog.log', 'goog.log.Level', 'goog.net.ErrorCode', 'goog.net.EventType', 'goog.reflect', 'goog.string', 'goog.structs', 'goog.userAgent'], false); -goog.addDependency('net/iframeio_different_base_test.js', ['goog.net.iframeIoDifferentBaseTest'], ['goog.events', 'goog.net.EventType', 'goog.net.IframeIo', 'goog.testing.AsyncTestCase', 'goog.testing.jsunit'], false); -goog.addDependency('net/iframeio_test.js', ['goog.net.IframeIoTest'], ['goog.debug', 'goog.debug.DivConsole', 'goog.debug.LogManager', 'goog.dom', 'goog.events', 'goog.events.EventType', 'goog.log', 'goog.log.Level', 'goog.net.IframeIo', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('net/iframeloadmonitor.js', ['goog.net.IframeLoadMonitor'], ['goog.dom', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.userAgent'], false); -goog.addDependency('net/iframeloadmonitor_test.js', ['goog.net.IframeLoadMonitorTest'], ['goog.dom', 'goog.events', 'goog.net.IframeLoadMonitor', 'goog.testing.AsyncTestCase', 'goog.testing.jsunit'], false); -goog.addDependency('net/imageloader.js', ['goog.net.ImageLoader'], ['goog.array', 'goog.dom', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.net.EventType', 'goog.object', 'goog.userAgent'], false); -goog.addDependency('net/imageloader_test.js', ['goog.net.ImageLoaderTest'], ['goog.Timer', 'goog.array', 'goog.dispose', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.net.EventType', 'goog.net.ImageLoader', 'goog.object', 'goog.string', 'goog.testing.AsyncTestCase', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false); -goog.addDependency('net/ipaddress.js', ['goog.net.IpAddress', 'goog.net.Ipv4Address', 'goog.net.Ipv6Address'], ['goog.array', 'goog.math.Integer', 'goog.object', 'goog.string'], false); -goog.addDependency('net/ipaddress_test.js', ['goog.net.IpAddressTest'], ['goog.math.Integer', 'goog.net.IpAddress', 'goog.net.Ipv4Address', 'goog.net.Ipv6Address', 'goog.testing.jsunit'], false); -goog.addDependency('net/jsloader.js', ['goog.net.jsloader', 'goog.net.jsloader.Error', 'goog.net.jsloader.ErrorCode', 'goog.net.jsloader.Options'], ['goog.array', 'goog.async.Deferred', 'goog.debug.Error', 'goog.dom', 'goog.dom.TagName'], false); -goog.addDependency('net/jsloader_test.js', ['goog.net.jsloaderTest'], ['goog.array', 'goog.dom', 'goog.net.jsloader', 'goog.net.jsloader.ErrorCode', 'goog.testing.AsyncTestCase', 'goog.testing.jsunit'], false); -goog.addDependency('net/jsonp.js', ['goog.net.Jsonp'], ['goog.Uri', 'goog.net.jsloader'], false); -goog.addDependency('net/jsonp_test.js', ['goog.net.JsonpTest'], ['goog.net.Jsonp', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.userAgent'], false); -goog.addDependency('net/mockiframeio.js', ['goog.net.MockIFrameIo'], ['goog.events.EventTarget', 'goog.json', 'goog.net.ErrorCode', 'goog.net.EventType', 'goog.net.IframeIo'], false); -goog.addDependency('net/multiiframeloadmonitor.js', ['goog.net.MultiIframeLoadMonitor'], ['goog.events', 'goog.net.IframeLoadMonitor'], false); -goog.addDependency('net/multiiframeloadmonitor_test.js', ['goog.net.MultiIframeLoadMonitorTest'], ['goog.dom', 'goog.net.IframeLoadMonitor', 'goog.net.MultiIframeLoadMonitor', 'goog.testing.AsyncTestCase', 'goog.testing.jsunit'], false); -goog.addDependency('net/networkstatusmonitor.js', ['goog.net.NetworkStatusMonitor'], ['goog.events.Listenable'], false); -goog.addDependency('net/networktester.js', ['goog.net.NetworkTester'], ['goog.Timer', 'goog.Uri', 'goog.log'], false); -goog.addDependency('net/networktester_test.js', ['goog.net.NetworkTesterTest'], ['goog.Uri', 'goog.net.NetworkTester', 'goog.testing.MockClock', 'goog.testing.jsunit'], false); -goog.addDependency('net/testdata/jsloader_test1.js', ['goog.net.testdata.jsloader_test1'], [], false); -goog.addDependency('net/testdata/jsloader_test2.js', ['goog.net.testdata.jsloader_test2'], [], false); -goog.addDependency('net/testdata/jsloader_test3.js', ['goog.net.testdata.jsloader_test3'], [], false); -goog.addDependency('net/testdata/jsloader_test4.js', ['goog.net.testdata.jsloader_test4'], [], false); -goog.addDependency('net/tmpnetwork.js', ['goog.net.tmpnetwork'], ['goog.Uri', 'goog.net.ChannelDebug'], false); -goog.addDependency('net/websocket.js', ['goog.net.WebSocket', 'goog.net.WebSocket.ErrorEvent', 'goog.net.WebSocket.EventType', 'goog.net.WebSocket.MessageEvent'], ['goog.Timer', 'goog.asserts', 'goog.debug.entryPointRegistry', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.log'], false); -goog.addDependency('net/websocket_test.js', ['goog.net.WebSocketTest'], ['goog.debug.EntryPointMonitor', 'goog.debug.ErrorHandler', 'goog.debug.entryPointRegistry', 'goog.events', 'goog.functions', 'goog.net.WebSocket', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false); -goog.addDependency('net/wrapperxmlhttpfactory.js', ['goog.net.WrapperXmlHttpFactory'], ['goog.net.XhrLike', 'goog.net.XmlHttpFactory'], false); -goog.addDependency('net/xhrio.js', ['goog.net.XhrIo', 'goog.net.XhrIo.ResponseType'], ['goog.Timer', 'goog.array', 'goog.debug.entryPointRegistry', 'goog.events.EventTarget', 'goog.json', 'goog.log', 'goog.net.ErrorCode', 'goog.net.EventType', 'goog.net.HttpStatus', 'goog.net.XmlHttp', 'goog.object', 'goog.string', 'goog.structs', 'goog.structs.Map', 'goog.uri.utils', 'goog.userAgent'], false); -goog.addDependency('net/xhrio_test.js', ['goog.net.XhrIoTest'], ['goog.Uri', 'goog.debug.EntryPointMonitor', 'goog.debug.ErrorHandler', 'goog.debug.entryPointRegistry', 'goog.events', 'goog.functions', 'goog.net.EventType', 'goog.net.WrapperXmlHttpFactory', 'goog.net.XhrIo', 'goog.net.XmlHttp', 'goog.object', 'goog.string', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.net.XhrIo', 'goog.testing.recordFunction'], false); -goog.addDependency('net/xhriopool.js', ['goog.net.XhrIoPool'], ['goog.net.XhrIo', 'goog.structs.PriorityPool'], false); -goog.addDependency('net/xhrlike.js', ['goog.net.XhrLike'], [], false); -goog.addDependency('net/xhrmanager.js', ['goog.net.XhrManager', 'goog.net.XhrManager.Event', 'goog.net.XhrManager.Request'], ['goog.events', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.net.ErrorCode', 'goog.net.EventType', 'goog.net.XhrIo', 'goog.net.XhrIoPool', 'goog.structs.Map'], false); -goog.addDependency('net/xhrmanager_test.js', ['goog.net.XhrManagerTest'], ['goog.events', 'goog.net.EventType', 'goog.net.XhrIo', 'goog.net.XhrManager', 'goog.testing.jsunit', 'goog.testing.net.XhrIoPool', 'goog.testing.recordFunction'], false); -goog.addDependency('net/xmlhttp.js', ['goog.net.DefaultXmlHttpFactory', 'goog.net.XmlHttp', 'goog.net.XmlHttp.OptionType', 'goog.net.XmlHttp.ReadyState', 'goog.net.XmlHttpDefines'], ['goog.asserts', 'goog.net.WrapperXmlHttpFactory', 'goog.net.XmlHttpFactory'], false); -goog.addDependency('net/xmlhttpfactory.js', ['goog.net.XmlHttpFactory'], ['goog.net.XhrLike'], false); -goog.addDependency('net/xpc/crosspagechannel.js', ['goog.net.xpc.CrossPageChannel'], ['goog.Uri', 'goog.async.Deferred', 'goog.async.Delay', 'goog.dispose', 'goog.dom', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.json', 'goog.log', 'goog.messaging.AbstractChannel', 'goog.net.xpc', 'goog.net.xpc.CfgFields', 'goog.net.xpc.ChannelStates', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.DirectTransport', 'goog.net.xpc.FrameElementMethodTransport', 'goog.net.xpc.IframePollingTransport', 'goog.net.xpc.IframeRelayTransport', 'goog.net.xpc.NativeMessagingTransport', 'goog.net.xpc.NixTransport', 'goog.net.xpc.TransportTypes', 'goog.net.xpc.UriCfgFields', 'goog.string', 'goog.uri.utils', 'goog.userAgent'], false); -goog.addDependency('net/xpc/crosspagechannel_test.js', ['goog.net.xpc.CrossPageChannelTest'], ['goog.Disposable', 'goog.Uri', 'goog.async.Deferred', 'goog.dom', 'goog.labs.userAgent.browser', 'goog.log', 'goog.log.Level', 'goog.net.xpc', 'goog.net.xpc.CfgFields', 'goog.net.xpc.CrossPageChannel', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.TransportTypes', 'goog.object', 'goog.testing.AsyncTestCase', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false); -goog.addDependency('net/xpc/crosspagechannelrole.js', ['goog.net.xpc.CrossPageChannelRole'], [], false); -goog.addDependency('net/xpc/directtransport.js', ['goog.net.xpc.DirectTransport'], ['goog.Timer', 'goog.async.Deferred', 'goog.events.EventHandler', 'goog.log', 'goog.net.xpc', 'goog.net.xpc.CfgFields', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.Transport', 'goog.net.xpc.TransportTypes', 'goog.object'], false); -goog.addDependency('net/xpc/directtransport_test.js', ['goog.net.xpc.DirectTransportTest'], ['goog.dom', 'goog.labs.userAgent.browser', 'goog.log', 'goog.log.Level', 'goog.net.xpc', 'goog.net.xpc.CfgFields', 'goog.net.xpc.CrossPageChannel', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.TransportTypes', 'goog.testing.AsyncTestCase', 'goog.testing.jsunit'], false); -goog.addDependency('net/xpc/frameelementmethodtransport.js', ['goog.net.xpc.FrameElementMethodTransport'], ['goog.log', 'goog.net.xpc', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.Transport', 'goog.net.xpc.TransportTypes'], false); -goog.addDependency('net/xpc/iframepollingtransport.js', ['goog.net.xpc.IframePollingTransport', 'goog.net.xpc.IframePollingTransport.Receiver', 'goog.net.xpc.IframePollingTransport.Sender'], ['goog.array', 'goog.dom', 'goog.log', 'goog.log.Level', 'goog.net.xpc', 'goog.net.xpc.CfgFields', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.Transport', 'goog.net.xpc.TransportTypes', 'goog.userAgent'], false); -goog.addDependency('net/xpc/iframepollingtransport_test.js', ['goog.net.xpc.IframePollingTransportTest'], ['goog.Timer', 'goog.dom', 'goog.dom.TagName', 'goog.functions', 'goog.net.xpc.CfgFields', 'goog.net.xpc.CrossPageChannel', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.TransportTypes', 'goog.object', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false); -goog.addDependency('net/xpc/iframerelaytransport.js', ['goog.net.xpc.IframeRelayTransport'], ['goog.dom', 'goog.dom.safe', 'goog.events', 'goog.html.SafeHtml', 'goog.log', 'goog.log.Level', 'goog.net.xpc', 'goog.net.xpc.CfgFields', 'goog.net.xpc.Transport', 'goog.net.xpc.TransportTypes', 'goog.string', 'goog.string.Const', 'goog.userAgent'], false); -goog.addDependency('net/xpc/nativemessagingtransport.js', ['goog.net.xpc.NativeMessagingTransport'], ['goog.Timer', 'goog.asserts', 'goog.async.Deferred', 'goog.events', 'goog.events.EventHandler', 'goog.log', 'goog.net.xpc', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.Transport', 'goog.net.xpc.TransportTypes'], false); -goog.addDependency('net/xpc/nativemessagingtransport_test.js', ['goog.net.xpc.NativeMessagingTransportTest'], ['goog.dom', 'goog.events', 'goog.net.xpc', 'goog.net.xpc.CfgFields', 'goog.net.xpc.CrossPageChannel', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.NativeMessagingTransport', 'goog.testing.jsunit'], false); -goog.addDependency('net/xpc/nixtransport.js', ['goog.net.xpc.NixTransport'], ['goog.log', 'goog.net.xpc', 'goog.net.xpc.CfgFields', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.Transport', 'goog.net.xpc.TransportTypes', 'goog.reflect'], false); -goog.addDependency('net/xpc/relay.js', ['goog.net.xpc.relay'], [], false); -goog.addDependency('net/xpc/transport.js', ['goog.net.xpc.Transport'], ['goog.Disposable', 'goog.dom', 'goog.net.xpc.TransportNames'], false); -goog.addDependency('net/xpc/xpc.js', ['goog.net.xpc', 'goog.net.xpc.CfgFields', 'goog.net.xpc.ChannelStates', 'goog.net.xpc.TransportNames', 'goog.net.xpc.TransportTypes', 'goog.net.xpc.UriCfgFields'], ['goog.log'], false); -goog.addDependency('object/object.js', ['goog.object'], [], false); -goog.addDependency('object/object_test.js', ['goog.objectTest'], ['goog.functions', 'goog.object', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false); -goog.addDependency('positioning/absoluteposition.js', ['goog.positioning.AbsolutePosition'], ['goog.math.Coordinate', 'goog.positioning', 'goog.positioning.AbstractPosition'], false); -goog.addDependency('positioning/abstractposition.js', ['goog.positioning.AbstractPosition'], [], false); -goog.addDependency('positioning/anchoredposition.js', ['goog.positioning.AnchoredPosition'], ['goog.positioning', 'goog.positioning.AbstractPosition'], false); -goog.addDependency('positioning/anchoredposition_test.js', ['goog.positioning.AnchoredPositionTest'], ['goog.dom', 'goog.positioning.AnchoredPosition', 'goog.positioning.Corner', 'goog.positioning.Overflow', 'goog.style', 'goog.testing.jsunit'], false); -goog.addDependency('positioning/anchoredviewportposition.js', ['goog.positioning.AnchoredViewportPosition'], ['goog.positioning', 'goog.positioning.AnchoredPosition', 'goog.positioning.Overflow', 'goog.positioning.OverflowStatus'], false); -goog.addDependency('positioning/anchoredviewportposition_test.js', ['goog.positioning.AnchoredViewportPositionTest'], ['goog.dom', 'goog.math.Box', 'goog.positioning.AnchoredViewportPosition', 'goog.positioning.Corner', 'goog.positioning.OverflowStatus', 'goog.style', 'goog.testing.jsunit'], false); -goog.addDependency('positioning/clientposition.js', ['goog.positioning.ClientPosition'], ['goog.asserts', 'goog.dom', 'goog.math.Coordinate', 'goog.positioning', 'goog.positioning.AbstractPosition', 'goog.style'], false); -goog.addDependency('positioning/clientposition_test.js', ['goog.positioning.clientPositionTest'], ['goog.dom', 'goog.positioning.ClientPosition', 'goog.positioning.Corner', 'goog.style', 'goog.testing.jsunit'], false); -goog.addDependency('positioning/menuanchoredposition.js', ['goog.positioning.MenuAnchoredPosition'], ['goog.positioning.AnchoredViewportPosition', 'goog.positioning.Overflow'], false); -goog.addDependency('positioning/menuanchoredposition_test.js', ['goog.positioning.MenuAnchoredPositionTest'], ['goog.dom', 'goog.positioning.Corner', 'goog.positioning.MenuAnchoredPosition', 'goog.testing.jsunit'], false); -goog.addDependency('positioning/positioning.js', ['goog.positioning', 'goog.positioning.Corner', 'goog.positioning.CornerBit', 'goog.positioning.Overflow', 'goog.positioning.OverflowStatus'], ['goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.math.Coordinate', 'goog.math.Rect', 'goog.math.Size', 'goog.style', 'goog.style.bidi'], false); -goog.addDependency('positioning/positioning_test.js', ['goog.positioningTest'], ['goog.dom', 'goog.dom.DomHelper', 'goog.math.Box', 'goog.math.Coordinate', 'goog.math.Size', 'goog.positioning', 'goog.positioning.Corner', 'goog.positioning.Overflow', 'goog.positioning.OverflowStatus', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.product'], false); -goog.addDependency('positioning/viewportclientposition.js', ['goog.positioning.ViewportClientPosition'], ['goog.dom', 'goog.math.Coordinate', 'goog.positioning', 'goog.positioning.ClientPosition', 'goog.positioning.Overflow', 'goog.positioning.OverflowStatus', 'goog.style'], false); -goog.addDependency('positioning/viewportclientposition_test.js', ['goog.positioning.ViewportClientPositionTest'], ['goog.dom', 'goog.positioning.Corner', 'goog.positioning.Overflow', 'goog.positioning.ViewportClientPosition', 'goog.style', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('positioning/viewportposition.js', ['goog.positioning.ViewportPosition'], ['goog.math.Coordinate', 'goog.positioning', 'goog.positioning.AbstractPosition', 'goog.positioning.Corner', 'goog.style'], false); -goog.addDependency('promise/promise.js', ['goog.Promise'], ['goog.Thenable', 'goog.asserts', 'goog.async.run', 'goog.async.throwException', 'goog.debug.Error', 'goog.promise.Resolver'], false); -goog.addDependency('promise/promise_test.js', ['goog.PromiseTest'], ['goog.Promise', 'goog.Thenable', 'goog.functions', 'goog.testing.AsyncTestCase', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false); -goog.addDependency('promise/resolver.js', ['goog.promise.Resolver'], [], false); -goog.addDependency('promise/testsuiteadapter.js', ['goog.promise.testSuiteAdapter'], ['goog.Promise'], false); -goog.addDependency('promise/thenable.js', ['goog.Thenable'], [], false); -goog.addDependency('proto/proto.js', ['goog.proto'], ['goog.proto.Serializer'], false); -goog.addDependency('proto/serializer.js', ['goog.proto.Serializer'], ['goog.json.Serializer', 'goog.string'], false); -goog.addDependency('proto/serializer_test.js', ['goog.protoTest'], ['goog.proto', 'goog.testing.jsunit'], false); -goog.addDependency('proto2/descriptor.js', ['goog.proto2.Descriptor', 'goog.proto2.Metadata'], ['goog.array', 'goog.asserts', 'goog.object', 'goog.string'], false); -goog.addDependency('proto2/descriptor_test.js', ['goog.proto2.DescriptorTest'], ['goog.proto2.Descriptor', 'goog.proto2.Message', 'goog.testing.jsunit'], false); -goog.addDependency('proto2/fielddescriptor.js', ['goog.proto2.FieldDescriptor'], ['goog.asserts', 'goog.string'], false); -goog.addDependency('proto2/fielddescriptor_test.js', ['goog.proto2.FieldDescriptorTest'], ['goog.proto2.FieldDescriptor', 'goog.proto2.Message', 'goog.testing.jsunit'], false); -goog.addDependency('proto2/lazydeserializer.js', ['goog.proto2.LazyDeserializer'], ['goog.asserts', 'goog.proto2.Message', 'goog.proto2.Serializer'], false); -goog.addDependency('proto2/message.js', ['goog.proto2.Message'], ['goog.asserts', 'goog.proto2.Descriptor', 'goog.proto2.FieldDescriptor'], false); -goog.addDependency('proto2/message_test.js', ['goog.proto2.MessageTest'], ['goog.testing.jsunit', 'proto2.TestAllTypes', 'proto2.TestAllTypes.NestedEnum', 'proto2.TestAllTypes.NestedMessage', 'proto2.TestAllTypes.OptionalGroup', 'proto2.TestAllTypes.RepeatedGroup'], false); -goog.addDependency('proto2/objectserializer.js', ['goog.proto2.ObjectSerializer'], ['goog.asserts', 'goog.proto2.FieldDescriptor', 'goog.proto2.Serializer', 'goog.string'], false); -goog.addDependency('proto2/objectserializer_test.js', ['goog.proto2.ObjectSerializerTest'], ['goog.proto2.ObjectSerializer', 'goog.proto2.Serializer', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'proto2.TestAllTypes'], false); -goog.addDependency('proto2/package_test.pb.js', ['someprotopackage.TestPackageTypes'], ['goog.proto2.Message', 'proto2.TestAllTypes'], false); -goog.addDependency('proto2/pbliteserializer.js', ['goog.proto2.PbLiteSerializer'], ['goog.asserts', 'goog.proto2.FieldDescriptor', 'goog.proto2.LazyDeserializer', 'goog.proto2.Serializer'], false); -goog.addDependency('proto2/pbliteserializer_test.js', ['goog.proto2.PbLiteSerializerTest'], ['goog.proto2.PbLiteSerializer', 'goog.testing.jsunit', 'proto2.TestAllTypes'], false); -goog.addDependency('proto2/proto_test.js', ['goog.proto2.messageTest'], ['goog.proto2.FieldDescriptor', 'goog.testing.jsunit', 'proto2.TestAllTypes', 'someprotopackage.TestPackageTypes'], false); -goog.addDependency('proto2/serializer.js', ['goog.proto2.Serializer'], ['goog.asserts', 'goog.proto2.FieldDescriptor', 'goog.proto2.Message'], false); -goog.addDependency('proto2/test.pb.js', ['proto2.TestAllTypes', 'proto2.TestAllTypes.NestedEnum', 'proto2.TestAllTypes.NestedMessage', 'proto2.TestAllTypes.OptionalGroup', 'proto2.TestAllTypes.RepeatedGroup', 'proto2.TestDefaultChild', 'proto2.TestDefaultParent'], ['goog.proto2.Message'], false); -goog.addDependency('proto2/textformatserializer.js', ['goog.proto2.TextFormatSerializer'], ['goog.array', 'goog.asserts', 'goog.json', 'goog.math', 'goog.object', 'goog.proto2.FieldDescriptor', 'goog.proto2.Message', 'goog.proto2.Serializer', 'goog.string'], false); -goog.addDependency('proto2/textformatserializer_test.js', ['goog.proto2.TextFormatSerializerTest'], ['goog.proto2.ObjectSerializer', 'goog.proto2.TextFormatSerializer', 'goog.testing.jsunit', 'proto2.TestAllTypes'], false); -goog.addDependency('proto2/util.js', ['goog.proto2.Util'], ['goog.asserts'], false); -goog.addDependency('pubsub/pubsub.js', ['goog.pubsub.PubSub'], ['goog.Disposable', 'goog.array'], false); -goog.addDependency('pubsub/pubsub_test.js', ['goog.pubsub.PubSubTest'], ['goog.array', 'goog.pubsub.PubSub', 'goog.testing.jsunit'], false); -goog.addDependency('pubsub/topicid.js', ['goog.pubsub.TopicId'], [], false); -goog.addDependency('pubsub/typedpubsub.js', ['goog.pubsub.TypedPubSub'], ['goog.Disposable', 'goog.pubsub.PubSub'], false); -goog.addDependency('pubsub/typedpubsub_test.js', ['goog.pubsub.TypedPubSubTest'], ['goog.array', 'goog.pubsub.TopicId', 'goog.pubsub.TypedPubSub', 'goog.testing.jsunit'], false); -goog.addDependency('reflect/reflect.js', ['goog.reflect'], [], false); -goog.addDependency('result/deferredadaptor.js', ['goog.result.DeferredAdaptor'], ['goog.async.Deferred', 'goog.result', 'goog.result.Result'], false); -goog.addDependency('result/dependentresult.js', ['goog.result.DependentResult'], ['goog.result.Result'], false); -goog.addDependency('result/result_interface.js', ['goog.result.Result'], ['goog.Thenable'], false); -goog.addDependency('result/resultutil.js', ['goog.result'], ['goog.array', 'goog.result.DependentResult', 'goog.result.Result', 'goog.result.SimpleResult'], false); -goog.addDependency('result/simpleresult.js', ['goog.result.SimpleResult', 'goog.result.SimpleResult.StateError'], ['goog.Promise', 'goog.Thenable', 'goog.debug.Error', 'goog.result.Result'], false); -goog.addDependency('soy/data.js', ['goog.soy.data.SanitizedContent', 'goog.soy.data.SanitizedContentKind'], ['goog.html.SafeHtml', 'goog.html.uncheckedconversions', 'goog.string.Const'], false); -goog.addDependency('soy/data_test.js', ['goog.soy.dataTest'], ['goog.html.SafeHtml', 'goog.soy.testHelper', 'goog.testing.jsunit'], false); -goog.addDependency('soy/renderer.js', ['goog.soy.InjectedDataSupplier', 'goog.soy.Renderer'], ['goog.asserts', 'goog.dom', 'goog.soy', 'goog.soy.data.SanitizedContent', 'goog.soy.data.SanitizedContentKind'], false); -goog.addDependency('soy/renderer_test.js', ['goog.soy.RendererTest'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.html.SafeHtml', 'goog.i18n.bidi.Dir', 'goog.soy.Renderer', 'goog.soy.data.SanitizedContentKind', 'goog.soy.testHelper', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false); -goog.addDependency('soy/soy.js', ['goog.soy'], ['goog.asserts', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.soy.data.SanitizedContent', 'goog.soy.data.SanitizedContentKind', 'goog.string'], false); -goog.addDependency('soy/soy_test.js', ['goog.soyTest'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.functions', 'goog.soy', 'goog.soy.testHelper', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false); -goog.addDependency('soy/soy_testhelper.js', ['goog.soy.testHelper'], ['goog.dom', 'goog.dom.TagName', 'goog.i18n.bidi.Dir', 'goog.soy.data.SanitizedContent', 'goog.soy.data.SanitizedContentKind', 'goog.string', 'goog.userAgent'], false); -goog.addDependency('spell/spellcheck.js', ['goog.spell.SpellCheck', 'goog.spell.SpellCheck.WordChangedEvent'], ['goog.Timer', 'goog.events.Event', 'goog.events.EventTarget', 'goog.structs.Set'], false); -goog.addDependency('spell/spellcheck_test.js', ['goog.spell.SpellCheckTest'], ['goog.spell.SpellCheck', 'goog.testing.jsunit'], false); -goog.addDependency('stats/basicstat.js', ['goog.stats.BasicStat'], ['goog.asserts', 'goog.log', 'goog.string.format', 'goog.structs.CircularBuffer'], false); -goog.addDependency('stats/basicstat_test.js', ['goog.stats.BasicStatTest'], ['goog.array', 'goog.stats.BasicStat', 'goog.string.format', 'goog.testing.PseudoRandom', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('storage/collectablestorage.js', ['goog.storage.CollectableStorage'], ['goog.array', 'goog.iter', 'goog.storage.ErrorCode', 'goog.storage.ExpiringStorage', 'goog.storage.RichStorage'], false); -goog.addDependency('storage/collectablestorage_test.js', ['goog.storage.CollectableStorageTest'], ['goog.storage.CollectableStorage', 'goog.storage.collectableStorageTester', 'goog.storage.storage_test', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.testing.storage.FakeMechanism'], false); -goog.addDependency('storage/collectablestoragetester.js', ['goog.storage.collectableStorageTester'], ['goog.testing.asserts'], false); -goog.addDependency('storage/encryptedstorage.js', ['goog.storage.EncryptedStorage'], ['goog.crypt', 'goog.crypt.Arc4', 'goog.crypt.Sha1', 'goog.crypt.base64', 'goog.json', 'goog.json.Serializer', 'goog.storage.CollectableStorage', 'goog.storage.ErrorCode', 'goog.storage.RichStorage'], false); -goog.addDependency('storage/encryptedstorage_test.js', ['goog.storage.EncryptedStorageTest'], ['goog.json', 'goog.storage.EncryptedStorage', 'goog.storage.ErrorCode', 'goog.storage.RichStorage', 'goog.storage.collectableStorageTester', 'goog.storage.storage_test', 'goog.testing.MockClock', 'goog.testing.PseudoRandom', 'goog.testing.jsunit', 'goog.testing.storage.FakeMechanism'], false); -goog.addDependency('storage/errorcode.js', ['goog.storage.ErrorCode'], [], false); -goog.addDependency('storage/expiringstorage.js', ['goog.storage.ExpiringStorage'], ['goog.storage.RichStorage'], false); -goog.addDependency('storage/expiringstorage_test.js', ['goog.storage.ExpiringStorageTest'], ['goog.storage.ExpiringStorage', 'goog.storage.storage_test', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.testing.storage.FakeMechanism'], false); -goog.addDependency('storage/mechanism/errorcode.js', ['goog.storage.mechanism.ErrorCode'], [], false); -goog.addDependency('storage/mechanism/errorhandlingmechanism.js', ['goog.storage.mechanism.ErrorHandlingMechanism'], ['goog.storage.mechanism.Mechanism'], false); -goog.addDependency('storage/mechanism/errorhandlingmechanism_test.js', ['goog.storage.mechanism.ErrorHandlingMechanismTest'], ['goog.storage.mechanism.ErrorHandlingMechanism', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false); -goog.addDependency('storage/mechanism/html5localstorage.js', ['goog.storage.mechanism.HTML5LocalStorage'], ['goog.storage.mechanism.HTML5WebStorage'], false); -goog.addDependency('storage/mechanism/html5localstorage_test.js', ['goog.storage.mechanism.HTML5LocalStorageTest'], ['goog.storage.mechanism.HTML5LocalStorage', 'goog.storage.mechanism.mechanismSeparationTester', 'goog.storage.mechanism.mechanismSharingTester', 'goog.storage.mechanism.mechanismTestDefinition', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('storage/mechanism/html5sessionstorage.js', ['goog.storage.mechanism.HTML5SessionStorage'], ['goog.storage.mechanism.HTML5WebStorage'], false); -goog.addDependency('storage/mechanism/html5sessionstorage_test.js', ['goog.storage.mechanism.HTML5SessionStorageTest'], ['goog.storage.mechanism.HTML5SessionStorage', 'goog.storage.mechanism.mechanismSeparationTester', 'goog.storage.mechanism.mechanismSharingTester', 'goog.storage.mechanism.mechanismTestDefinition', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('storage/mechanism/html5webstorage.js', ['goog.storage.mechanism.HTML5WebStorage'], ['goog.asserts', 'goog.iter.Iterator', 'goog.iter.StopIteration', 'goog.storage.mechanism.ErrorCode', 'goog.storage.mechanism.IterableMechanism'], false); -goog.addDependency('storage/mechanism/html5webstorage_test.js', ['goog.storage.mechanism.HTML5MockStorage', 'goog.storage.mechanism.HTML5WebStorageTest', 'goog.storage.mechanism.MockThrowableStorage'], ['goog.storage.mechanism.ErrorCode', 'goog.storage.mechanism.HTML5WebStorage', 'goog.testing.jsunit'], false); -goog.addDependency('storage/mechanism/ieuserdata.js', ['goog.storage.mechanism.IEUserData'], ['goog.asserts', 'goog.iter.Iterator', 'goog.iter.StopIteration', 'goog.storage.mechanism.ErrorCode', 'goog.storage.mechanism.IterableMechanism', 'goog.structs.Map', 'goog.userAgent'], false); -goog.addDependency('storage/mechanism/ieuserdata_test.js', ['goog.storage.mechanism.IEUserDataTest'], ['goog.storage.mechanism.IEUserData', 'goog.storage.mechanism.mechanismSeparationTester', 'goog.storage.mechanism.mechanismSharingTester', 'goog.storage.mechanism.mechanismTestDefinition', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('storage/mechanism/iterablemechanism.js', ['goog.storage.mechanism.IterableMechanism'], ['goog.array', 'goog.asserts', 'goog.iter', 'goog.storage.mechanism.Mechanism'], false); -goog.addDependency('storage/mechanism/iterablemechanismtester.js', ['goog.storage.mechanism.iterableMechanismTester'], ['goog.iter.Iterator', 'goog.storage.mechanism.IterableMechanism', 'goog.testing.asserts'], false); -goog.addDependency('storage/mechanism/mechanism.js', ['goog.storage.mechanism.Mechanism'], [], false); -goog.addDependency('storage/mechanism/mechanismfactory.js', ['goog.storage.mechanism.mechanismfactory'], ['goog.storage.mechanism.HTML5LocalStorage', 'goog.storage.mechanism.HTML5SessionStorage', 'goog.storage.mechanism.IEUserData', 'goog.storage.mechanism.PrefixedMechanism'], false); -goog.addDependency('storage/mechanism/mechanismfactory_test.js', ['goog.storage.mechanism.mechanismfactoryTest'], ['goog.storage.mechanism.mechanismfactory', 'goog.testing.jsunit'], false); -goog.addDependency('storage/mechanism/mechanismseparationtester.js', ['goog.storage.mechanism.mechanismSeparationTester'], ['goog.iter.StopIteration', 'goog.storage.mechanism.mechanismTestDefinition', 'goog.testing.asserts'], false); -goog.addDependency('storage/mechanism/mechanismsharingtester.js', ['goog.storage.mechanism.mechanismSharingTester'], ['goog.iter.StopIteration', 'goog.storage.mechanism.mechanismTestDefinition', 'goog.testing.asserts'], false); -goog.addDependency('storage/mechanism/mechanismtestdefinition.js', ['goog.storage.mechanism.mechanismTestDefinition'], [], false); -goog.addDependency('storage/mechanism/mechanismtester.js', ['goog.storage.mechanism.mechanismTester'], ['goog.storage.mechanism.ErrorCode', 'goog.testing.asserts', 'goog.userAgent', 'goog.userAgent.product', 'goog.userAgent.product.isVersion'], false); -goog.addDependency('storage/mechanism/prefixedmechanism.js', ['goog.storage.mechanism.PrefixedMechanism'], ['goog.iter.Iterator', 'goog.storage.mechanism.IterableMechanism'], false); -goog.addDependency('storage/mechanism/prefixedmechanism_test.js', ['goog.storage.mechanism.PrefixedMechanismTest'], ['goog.storage.mechanism.HTML5LocalStorage', 'goog.storage.mechanism.PrefixedMechanism', 'goog.storage.mechanism.mechanismSeparationTester', 'goog.storage.mechanism.mechanismSharingTester', 'goog.testing.jsunit'], false); -goog.addDependency('storage/richstorage.js', ['goog.storage.RichStorage', 'goog.storage.RichStorage.Wrapper'], ['goog.storage.ErrorCode', 'goog.storage.Storage'], false); -goog.addDependency('storage/richstorage_test.js', ['goog.storage.RichStorageTest'], ['goog.storage.ErrorCode', 'goog.storage.RichStorage', 'goog.storage.storage_test', 'goog.testing.jsunit', 'goog.testing.storage.FakeMechanism'], false); -goog.addDependency('storage/storage.js', ['goog.storage.Storage'], ['goog.json', 'goog.storage.ErrorCode'], false); -goog.addDependency('storage/storage_test.js', ['goog.storage.storage_test'], ['goog.structs.Map', 'goog.testing.asserts'], false); -goog.addDependency('string/const.js', ['goog.string.Const'], ['goog.asserts', 'goog.string.TypedString'], false); -goog.addDependency('string/const_test.js', ['goog.string.constTest'], ['goog.string.Const', 'goog.testing.jsunit'], false); -goog.addDependency('string/linkify.js', ['goog.string.linkify'], ['goog.string'], false); -goog.addDependency('string/linkify_test.js', ['goog.string.linkifyTest'], ['goog.string', 'goog.string.linkify', 'goog.testing.dom', 'goog.testing.jsunit'], false); -goog.addDependency('string/newlines.js', ['goog.string.newlines', 'goog.string.newlines.Line'], ['goog.array'], false); -goog.addDependency('string/newlines_test.js', ['goog.string.newlinesTest'], ['goog.string.newlines', 'goog.testing.jsunit'], false); -goog.addDependency('string/parser.js', ['goog.string.Parser'], [], false); -goog.addDependency('string/path.js', ['goog.string.path'], ['goog.array', 'goog.string'], false); -goog.addDependency('string/path_test.js', ['goog.string.pathTest'], ['goog.string.path', 'goog.testing.jsunit'], false); -goog.addDependency('string/string.js', ['goog.string', 'goog.string.Unicode'], [], false); -goog.addDependency('string/string_test.js', ['goog.stringTest'], ['goog.functions', 'goog.object', 'goog.string', 'goog.string.Unicode', 'goog.testing.MockControl', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit'], false); -goog.addDependency('string/stringbuffer.js', ['goog.string.StringBuffer'], [], false); -goog.addDependency('string/stringbuffer_test.js', ['goog.string.StringBufferTest'], ['goog.string.StringBuffer', 'goog.testing.jsunit'], false); -goog.addDependency('string/stringformat.js', ['goog.string.format'], ['goog.string'], false); -goog.addDependency('string/stringformat_test.js', ['goog.string.formatTest'], ['goog.string.format', 'goog.testing.jsunit'], false); -goog.addDependency('string/stringifier.js', ['goog.string.Stringifier'], [], false); -goog.addDependency('string/typedstring.js', ['goog.string.TypedString'], [], false); -goog.addDependency('structs/avltree.js', ['goog.structs.AvlTree', 'goog.structs.AvlTree.Node'], ['goog.structs.Collection'], false); -goog.addDependency('structs/avltree_test.js', ['goog.structs.AvlTreeTest'], ['goog.array', 'goog.structs.AvlTree', 'goog.testing.jsunit'], false); -goog.addDependency('structs/circularbuffer.js', ['goog.structs.CircularBuffer'], [], false); -goog.addDependency('structs/circularbuffer_test.js', ['goog.structs.CircularBufferTest'], ['goog.structs.CircularBuffer', 'goog.testing.jsunit'], false); -goog.addDependency('structs/collection.js', ['goog.structs.Collection'], [], false); -goog.addDependency('structs/collection_test.js', ['goog.structs.CollectionTest'], ['goog.structs.AvlTree', 'goog.structs.Set', 'goog.testing.jsunit'], false); -goog.addDependency('structs/heap.js', ['goog.structs.Heap'], ['goog.array', 'goog.object', 'goog.structs.Node'], false); -goog.addDependency('structs/heap_test.js', ['goog.structs.HeapTest'], ['goog.structs', 'goog.structs.Heap', 'goog.testing.jsunit'], false); -goog.addDependency('structs/inversionmap.js', ['goog.structs.InversionMap'], ['goog.array'], false); -goog.addDependency('structs/inversionmap_test.js', ['goog.structs.InversionMapTest'], ['goog.structs.InversionMap', 'goog.testing.jsunit'], false); -goog.addDependency('structs/linkedmap.js', ['goog.structs.LinkedMap'], ['goog.structs.Map'], false); -goog.addDependency('structs/linkedmap_test.js', ['goog.structs.LinkedMapTest'], ['goog.structs.LinkedMap', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false); -goog.addDependency('structs/map.js', ['goog.structs.Map'], ['goog.iter.Iterator', 'goog.iter.StopIteration', 'goog.object'], false); -goog.addDependency('structs/map_test.js', ['goog.structs.MapTest'], ['goog.iter', 'goog.structs', 'goog.structs.Map', 'goog.testing.jsunit'], false); -goog.addDependency('structs/node.js', ['goog.structs.Node'], [], false); -goog.addDependency('structs/pool.js', ['goog.structs.Pool'], ['goog.Disposable', 'goog.structs.Queue', 'goog.structs.Set'], false); -goog.addDependency('structs/pool_test.js', ['goog.structs.PoolTest'], ['goog.structs.Pool', 'goog.testing.MockClock', 'goog.testing.jsunit'], false); -goog.addDependency('structs/prioritypool.js', ['goog.structs.PriorityPool'], ['goog.structs.Pool', 'goog.structs.PriorityQueue'], false); -goog.addDependency('structs/prioritypool_test.js', ['goog.structs.PriorityPoolTest'], ['goog.structs.PriorityPool', 'goog.testing.MockClock', 'goog.testing.jsunit'], false); -goog.addDependency('structs/priorityqueue.js', ['goog.structs.PriorityQueue'], ['goog.structs.Heap'], false); -goog.addDependency('structs/priorityqueue_test.js', ['goog.structs.PriorityQueueTest'], ['goog.structs', 'goog.structs.PriorityQueue', 'goog.testing.jsunit'], false); -goog.addDependency('structs/quadtree.js', ['goog.structs.QuadTree', 'goog.structs.QuadTree.Node', 'goog.structs.QuadTree.Point'], ['goog.math.Coordinate'], false); -goog.addDependency('structs/quadtree_test.js', ['goog.structs.QuadTreeTest'], ['goog.structs', 'goog.structs.QuadTree', 'goog.testing.jsunit'], false); -goog.addDependency('structs/queue.js', ['goog.structs.Queue'], ['goog.array'], false); -goog.addDependency('structs/queue_test.js', ['goog.structs.QueueTest'], ['goog.structs.Queue', 'goog.testing.jsunit'], false); -goog.addDependency('structs/set.js', ['goog.structs.Set'], ['goog.structs', 'goog.structs.Collection', 'goog.structs.Map'], false); -goog.addDependency('structs/set_test.js', ['goog.structs.SetTest'], ['goog.iter', 'goog.structs', 'goog.structs.Set', 'goog.testing.jsunit'], false); -goog.addDependency('structs/simplepool.js', ['goog.structs.SimplePool'], ['goog.Disposable'], false); -goog.addDependency('structs/stringset.js', ['goog.structs.StringSet'], ['goog.asserts', 'goog.iter'], false); -goog.addDependency('structs/stringset_test.js', ['goog.structs.StringSetTest'], ['goog.array', 'goog.iter', 'goog.structs.StringSet', 'goog.testing.asserts', 'goog.testing.jsunit'], false); -goog.addDependency('structs/structs.js', ['goog.structs'], ['goog.array', 'goog.object'], false); -goog.addDependency('structs/structs_test.js', ['goog.structsTest'], ['goog.array', 'goog.structs', 'goog.structs.Map', 'goog.structs.Set', 'goog.testing.jsunit'], false); -goog.addDependency('structs/treenode.js', ['goog.structs.TreeNode'], ['goog.array', 'goog.asserts', 'goog.structs.Node'], false); -goog.addDependency('structs/treenode_test.js', ['goog.structs.TreeNodeTest'], ['goog.structs.TreeNode', 'goog.testing.jsunit'], false); -goog.addDependency('structs/trie.js', ['goog.structs.Trie'], ['goog.object', 'goog.structs'], false); -goog.addDependency('structs/trie_test.js', ['goog.structs.TrieTest'], ['goog.object', 'goog.structs', 'goog.structs.Trie', 'goog.testing.jsunit'], false); -goog.addDependency('structs/weak/weak.js', ['goog.structs.weak'], ['goog.userAgent'], false); -goog.addDependency('structs/weak/weak_test.js', ['goog.structs.weakTest'], ['goog.array', 'goog.structs.weak', 'goog.testing.jsunit'], false); -goog.addDependency('style/bidi.js', ['goog.style.bidi'], ['goog.dom', 'goog.style', 'goog.userAgent'], false); -goog.addDependency('style/bidi_test.js', ['goog.style.bidiTest'], ['goog.dom', 'goog.style', 'goog.style.bidi', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('style/cursor.js', ['goog.style.cursor'], ['goog.userAgent'], false); -goog.addDependency('style/cursor_test.js', ['goog.style.cursorTest'], ['goog.style.cursor', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('style/style.js', ['goog.style'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.vendor', 'goog.math.Box', 'goog.math.Coordinate', 'goog.math.Rect', 'goog.math.Size', 'goog.object', 'goog.string', 'goog.userAgent'], false); -goog.addDependency('style/style_document_scroll_test.js', ['goog.style.style_document_scroll_test'], ['goog.dom', 'goog.style', 'goog.testing.jsunit'], false); -goog.addDependency('style/style_test.js', ['goog.style_test'], ['goog.array', 'goog.color', 'goog.dom', 'goog.events.BrowserEvent', 'goog.labs.userAgent.util', 'goog.math.Box', 'goog.math.Coordinate', 'goog.math.Rect', 'goog.math.Size', 'goog.object', 'goog.string', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.MockUserAgent', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.product', 'goog.userAgentTestUtil', 'goog.userAgentTestUtil.UserAgents'], false); -goog.addDependency('style/style_webkit_scrollbars_test.js', ['goog.style.webkitScrollbarsTest'], ['goog.asserts', 'goog.style', 'goog.styleScrollbarTester', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('style/stylescrollbartester.js', ['goog.styleScrollbarTester'], ['goog.dom', 'goog.style', 'goog.testing.asserts'], false); -goog.addDependency('style/transform.js', ['goog.style.transform'], ['goog.functions', 'goog.math.Coordinate', 'goog.math.Coordinate3', 'goog.style', 'goog.userAgent', 'goog.userAgent.product.isVersion'], false); -goog.addDependency('style/transform_test.js', ['goog.style.transformTest'], ['goog.dom', 'goog.style.transform', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.product.isVersion'], false); -goog.addDependency('style/transition.js', ['goog.style.transition', 'goog.style.transition.Css3Property'], ['goog.array', 'goog.asserts', 'goog.dom.safe', 'goog.dom.vendor', 'goog.functions', 'goog.html.SafeHtml', 'goog.style', 'goog.userAgent'], false); -goog.addDependency('style/transition_test.js', ['goog.style.transitionTest'], ['goog.style', 'goog.style.transition', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('test_module.js', ['goog.test_module'], ['goog.test_module_dep'], true); -goog.addDependency('test_module_dep.js', ['goog.test_module_dep'], [], true); -goog.addDependency('testing/asserts.js', ['goog.testing.JsUnitException', 'goog.testing.asserts', 'goog.testing.asserts.ArrayLike'], ['goog.testing.stacktrace'], false); -goog.addDependency('testing/asserts_test.js', ['goog.testing.assertsTest'], ['goog.array', 'goog.dom', 'goog.iter.Iterator', 'goog.iter.StopIteration', 'goog.labs.userAgent.browser', 'goog.string', 'goog.structs.Map', 'goog.structs.Set', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('testing/async/mockcontrol.js', ['goog.testing.async.MockControl'], ['goog.asserts', 'goog.async.Deferred', 'goog.debug', 'goog.testing.asserts', 'goog.testing.mockmatchers.IgnoreArgument'], false); -goog.addDependency('testing/async/mockcontrol_test.js', ['goog.testing.async.MockControlTest'], ['goog.async.Deferred', 'goog.testing.MockControl', 'goog.testing.asserts', 'goog.testing.async.MockControl', 'goog.testing.jsunit'], false); -goog.addDependency('testing/asynctestcase.js', ['goog.testing.AsyncTestCase', 'goog.testing.AsyncTestCase.ControlBreakingException'], ['goog.testing.TestCase', 'goog.testing.asserts'], false); -goog.addDependency('testing/asynctestcase_async_test.js', ['goog.testing.AsyncTestCaseAsyncTest'], ['goog.testing.AsyncTestCase', 'goog.testing.jsunit'], false); -goog.addDependency('testing/asynctestcase_noasync_test.js', ['goog.testing.AsyncTestCaseSyncTest'], ['goog.testing.AsyncTestCase', 'goog.testing.jsunit'], false); -goog.addDependency('testing/asynctestcase_test.js', ['goog.testing.AsyncTestCaseTest'], ['goog.debug.Error', 'goog.testing.AsyncTestCase', 'goog.testing.asserts', 'goog.testing.jsunit'], false); -goog.addDependency('testing/benchmark.js', ['goog.testing.benchmark'], ['goog.dom', 'goog.dom.TagName', 'goog.testing.PerformanceTable', 'goog.testing.PerformanceTimer', 'goog.testing.TestCase'], false); -goog.addDependency('testing/continuationtestcase.js', ['goog.testing.ContinuationTestCase', 'goog.testing.ContinuationTestCase.Step', 'goog.testing.ContinuationTestCase.Test'], ['goog.array', 'goog.events.EventHandler', 'goog.testing.TestCase', 'goog.testing.asserts'], false); -goog.addDependency('testing/continuationtestcase_test.js', ['goog.testing.ContinuationTestCaseTest'], ['goog.events', 'goog.events.EventTarget', 'goog.testing.ContinuationTestCase', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.TestCase', 'goog.testing.jsunit'], false); -goog.addDependency('testing/deferredtestcase.js', ['goog.testing.DeferredTestCase'], ['goog.testing.AsyncTestCase', 'goog.testing.TestCase'], false); -goog.addDependency('testing/deferredtestcase_test.js', ['goog.testing.DeferredTestCaseTest'], ['goog.async.Deferred', 'goog.testing.DeferredTestCase', 'goog.testing.TestCase', 'goog.testing.TestRunner', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false); -goog.addDependency('testing/dom.js', ['goog.testing.dom'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.NodeIterator', 'goog.dom.NodeType', 'goog.dom.TagIterator', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.iter', 'goog.object', 'goog.string', 'goog.style', 'goog.testing.asserts', 'goog.userAgent'], false); -goog.addDependency('testing/dom_test.js', ['goog.testing.domTest'], ['goog.dom', 'goog.dom.TagName', 'goog.testing.dom', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('testing/editor/dom.js', ['goog.testing.editor.dom'], ['goog.dom.NodeType', 'goog.dom.TagIterator', 'goog.dom.TagWalkType', 'goog.iter', 'goog.string', 'goog.testing.asserts'], false); -goog.addDependency('testing/editor/dom_test.js', ['goog.testing.editor.domTest'], ['goog.dom', 'goog.dom.TagName', 'goog.functions', 'goog.testing.editor.dom', 'goog.testing.jsunit'], false); -goog.addDependency('testing/editor/fieldmock.js', ['goog.testing.editor.FieldMock'], ['goog.dom', 'goog.dom.Range', 'goog.editor.Field', 'goog.testing.LooseMock', 'goog.testing.mockmatchers'], false); -goog.addDependency('testing/editor/testhelper.js', ['goog.testing.editor.TestHelper'], ['goog.Disposable', 'goog.dom', 'goog.dom.Range', 'goog.editor.BrowserFeature', 'goog.editor.node', 'goog.editor.plugins.AbstractBubblePlugin', 'goog.testing.dom'], false); -goog.addDependency('testing/editor/testhelper_test.js', ['goog.testing.editor.TestHelperTest'], ['goog.dom', 'goog.dom.TagName', 'goog.editor.node', 'goog.testing.editor.TestHelper', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('testing/events/eventobserver.js', ['goog.testing.events.EventObserver'], ['goog.array'], false); -goog.addDependency('testing/events/eventobserver_test.js', ['goog.testing.events.EventObserverTest'], ['goog.array', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.testing.events.EventObserver', 'goog.testing.jsunit'], false); -goog.addDependency('testing/events/events.js', ['goog.testing.events', 'goog.testing.events.Event'], ['goog.Disposable', 'goog.asserts', 'goog.dom.NodeType', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.BrowserFeature', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.object', 'goog.style', 'goog.userAgent'], false); -goog.addDependency('testing/events/events_test.js', ['goog.testing.eventsTest'], ['goog.array', 'goog.dom', 'goog.events', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.math.Coordinate', 'goog.string', 'goog.style', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.userAgent'], false); -goog.addDependency('testing/events/matchers.js', ['goog.testing.events.EventMatcher'], ['goog.events.Event', 'goog.testing.mockmatchers.ArgumentMatcher'], false); -goog.addDependency('testing/events/matchers_test.js', ['goog.testing.events.EventMatcherTest'], ['goog.events.Event', 'goog.testing.events.EventMatcher', 'goog.testing.jsunit'], false); -goog.addDependency('testing/events/onlinehandler.js', ['goog.testing.events.OnlineHandler'], ['goog.events.EventTarget', 'goog.net.NetworkStatusMonitor'], false); -goog.addDependency('testing/events/onlinehandler_test.js', ['goog.testing.events.OnlineHandlerTest'], ['goog.events', 'goog.net.NetworkStatusMonitor', 'goog.testing.events.EventObserver', 'goog.testing.events.OnlineHandler', 'goog.testing.jsunit'], false); -goog.addDependency('testing/expectedfailures.js', ['goog.testing.ExpectedFailures'], ['goog.debug.DivConsole', 'goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.EventType', 'goog.log', 'goog.style', 'goog.testing.JsUnitException', 'goog.testing.TestCase', 'goog.testing.asserts'], false); -goog.addDependency('testing/expectedfailures_test.js', ['goog.testing.ExpectedFailuresTest'], ['goog.debug.Logger', 'goog.testing.ExpectedFailures', 'goog.testing.JsUnitException', 'goog.testing.jsunit'], false); -goog.addDependency('testing/fs/blob.js', ['goog.testing.fs.Blob'], ['goog.crypt.base64'], false); -goog.addDependency('testing/fs/blob_test.js', ['goog.testing.fs.BlobTest'], ['goog.testing.fs.Blob', 'goog.testing.jsunit'], false); -goog.addDependency('testing/fs/directoryentry_test.js', ['goog.testing.fs.DirectoryEntryTest'], ['goog.array', 'goog.fs.DirectoryEntry', 'goog.fs.Error', 'goog.testing.AsyncTestCase', 'goog.testing.MockClock', 'goog.testing.fs.FileSystem', 'goog.testing.jsunit'], false); -goog.addDependency('testing/fs/entry.js', ['goog.testing.fs.DirectoryEntry', 'goog.testing.fs.Entry', 'goog.testing.fs.FileEntry'], ['goog.Timer', 'goog.array', 'goog.asserts', 'goog.async.Deferred', 'goog.fs.DirectoryEntry', 'goog.fs.DirectoryEntryImpl', 'goog.fs.Entry', 'goog.fs.Error', 'goog.fs.FileEntry', 'goog.functions', 'goog.object', 'goog.string', 'goog.testing.fs.File', 'goog.testing.fs.FileWriter'], false); -goog.addDependency('testing/fs/entry_test.js', ['goog.testing.fs.EntryTest'], ['goog.fs.DirectoryEntry', 'goog.fs.Error', 'goog.testing.AsyncTestCase', 'goog.testing.MockClock', 'goog.testing.fs.FileSystem', 'goog.testing.jsunit'], false); -goog.addDependency('testing/fs/file.js', ['goog.testing.fs.File'], ['goog.testing.fs.Blob'], false); -goog.addDependency('testing/fs/fileentry_test.js', ['goog.testing.fs.FileEntryTest'], ['goog.testing.AsyncTestCase', 'goog.testing.MockClock', 'goog.testing.fs.FileEntry', 'goog.testing.fs.FileSystem', 'goog.testing.jsunit'], false); -goog.addDependency('testing/fs/filereader.js', ['goog.testing.fs.FileReader'], ['goog.Timer', 'goog.events.EventTarget', 'goog.fs.Error', 'goog.fs.FileReader', 'goog.testing.fs.ProgressEvent'], false); -goog.addDependency('testing/fs/filereader_test.js', ['goog.testing.fs.FileReaderTest'], ['goog.Timer', 'goog.async.Deferred', 'goog.events', 'goog.fs.Error', 'goog.fs.FileReader', 'goog.fs.FileSaver', 'goog.testing.AsyncTestCase', 'goog.testing.fs.FileReader', 'goog.testing.fs.FileSystem', 'goog.testing.jsunit'], false); -goog.addDependency('testing/fs/filesystem.js', ['goog.testing.fs.FileSystem'], ['goog.fs.FileSystem', 'goog.testing.fs.DirectoryEntry'], false); -goog.addDependency('testing/fs/filewriter.js', ['goog.testing.fs.FileWriter'], ['goog.Timer', 'goog.events.EventTarget', 'goog.fs.Error', 'goog.fs.FileSaver', 'goog.string', 'goog.testing.fs.ProgressEvent'], false); -goog.addDependency('testing/fs/filewriter_test.js', ['goog.testing.fs.FileWriterTest'], ['goog.async.Deferred', 'goog.events', 'goog.fs.Error', 'goog.fs.FileSaver', 'goog.testing.AsyncTestCase', 'goog.testing.MockClock', 'goog.testing.fs.Blob', 'goog.testing.fs.FileSystem', 'goog.testing.jsunit'], false); -goog.addDependency('testing/fs/fs.js', ['goog.testing.fs'], ['goog.Timer', 'goog.array', 'goog.async.Deferred', 'goog.fs', 'goog.testing.fs.Blob', 'goog.testing.fs.FileSystem'], false); -goog.addDependency('testing/fs/fs_test.js', ['goog.testing.fsTest'], ['goog.testing.AsyncTestCase', 'goog.testing.fs', 'goog.testing.fs.Blob', 'goog.testing.jsunit'], false); -goog.addDependency('testing/fs/integration_test.js', ['goog.testing.fs.integrationTest'], ['goog.async.Deferred', 'goog.async.DeferredList', 'goog.events', 'goog.fs', 'goog.fs.DirectoryEntry', 'goog.fs.Error', 'goog.fs.FileSaver', 'goog.testing.AsyncTestCase', 'goog.testing.PropertyReplacer', 'goog.testing.fs', 'goog.testing.jsunit'], false); -goog.addDependency('testing/fs/progressevent.js', ['goog.testing.fs.ProgressEvent'], ['goog.events.Event'], false); -goog.addDependency('testing/functionmock.js', ['goog.testing', 'goog.testing.FunctionMock', 'goog.testing.GlobalFunctionMock', 'goog.testing.MethodMock'], ['goog.object', 'goog.testing.LooseMock', 'goog.testing.Mock', 'goog.testing.PropertyReplacer', 'goog.testing.StrictMock'], false); -goog.addDependency('testing/functionmock_test.js', ['goog.testing.FunctionMockTest'], ['goog.array', 'goog.string', 'goog.testing', 'goog.testing.FunctionMock', 'goog.testing.Mock', 'goog.testing.StrictMock', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.testing.mockmatchers'], false); -goog.addDependency('testing/graphics.js', ['goog.testing.graphics'], ['goog.graphics.Path', 'goog.testing.asserts'], false); -goog.addDependency('testing/i18n/asserts.js', ['goog.testing.i18n.asserts'], ['goog.testing.jsunit'], false); -goog.addDependency('testing/i18n/asserts_test.js', ['goog.testing.i18n.assertsTest'], ['goog.testing.ExpectedFailures', 'goog.testing.i18n.asserts'], false); -goog.addDependency('testing/jsunit.js', ['goog.testing.jsunit'], ['goog.testing.TestCase', 'goog.testing.TestRunner'], false); -goog.addDependency('testing/loosemock.js', ['goog.testing.LooseExpectationCollection', 'goog.testing.LooseMock'], ['goog.array', 'goog.structs.Map', 'goog.testing.Mock'], false); -goog.addDependency('testing/loosemock_test.js', ['goog.testing.LooseMockTest'], ['goog.testing.LooseMock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.mockmatchers'], false); -goog.addDependency('testing/messaging/mockmessagechannel.js', ['goog.testing.messaging.MockMessageChannel'], ['goog.messaging.AbstractChannel', 'goog.testing.asserts'], false); -goog.addDependency('testing/messaging/mockmessageevent.js', ['goog.testing.messaging.MockMessageEvent'], ['goog.events.BrowserEvent', 'goog.events.EventType', 'goog.testing.events.Event'], false); -goog.addDependency('testing/messaging/mockmessageport.js', ['goog.testing.messaging.MockMessagePort'], ['goog.events.EventTarget'], false); -goog.addDependency('testing/messaging/mockportnetwork.js', ['goog.testing.messaging.MockPortNetwork'], ['goog.messaging.PortNetwork', 'goog.testing.messaging.MockMessageChannel'], false); -goog.addDependency('testing/mock.js', ['goog.testing.Mock', 'goog.testing.MockExpectation'], ['goog.array', 'goog.object', 'goog.testing.JsUnitException', 'goog.testing.MockInterface', 'goog.testing.mockmatchers'], false); -goog.addDependency('testing/mock_test.js', ['goog.testing.MockTest'], ['goog.array', 'goog.testing', 'goog.testing.Mock', 'goog.testing.MockControl', 'goog.testing.MockExpectation', 'goog.testing.jsunit'], false); -goog.addDependency('testing/mockclassfactory.js', ['goog.testing.MockClassFactory', 'goog.testing.MockClassRecord'], ['goog.array', 'goog.object', 'goog.testing.LooseMock', 'goog.testing.StrictMock', 'goog.testing.TestCase', 'goog.testing.mockmatchers'], false); -goog.addDependency('testing/mockclassfactory_test.js', ['fake.BaseClass', 'fake.ChildClass', 'goog.testing.MockClassFactoryTest'], ['goog.testing', 'goog.testing.MockClassFactory', 'goog.testing.jsunit'], false); -goog.addDependency('testing/mockclock.js', ['goog.testing.MockClock'], ['goog.Disposable', 'goog.async.run', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.watchers'], false); -goog.addDependency('testing/mockclock_test.js', ['goog.testing.MockClockTest'], ['goog.Promise', 'goog.Timer', 'goog.events', 'goog.functions', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction'], false); -goog.addDependency('testing/mockcontrol.js', ['goog.testing.MockControl'], ['goog.array', 'goog.testing', 'goog.testing.LooseMock', 'goog.testing.StrictMock'], false); -goog.addDependency('testing/mockcontrol_test.js', ['goog.testing.MockControlTest'], ['goog.testing.Mock', 'goog.testing.MockControl', 'goog.testing.jsunit'], false); -goog.addDependency('testing/mockinterface.js', ['goog.testing.MockInterface'], [], false); -goog.addDependency('testing/mockmatchers.js', ['goog.testing.mockmatchers', 'goog.testing.mockmatchers.ArgumentMatcher', 'goog.testing.mockmatchers.IgnoreArgument', 'goog.testing.mockmatchers.InstanceOf', 'goog.testing.mockmatchers.ObjectEquals', 'goog.testing.mockmatchers.RegexpMatch', 'goog.testing.mockmatchers.SaveArgument', 'goog.testing.mockmatchers.TypeOf'], ['goog.array', 'goog.dom', 'goog.testing.asserts'], false); -goog.addDependency('testing/mockmatchers_test.js', ['goog.testing.mockmatchersTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.testing.mockmatchers', 'goog.testing.mockmatchers.ArgumentMatcher'], false); -goog.addDependency('testing/mockrandom.js', ['goog.testing.MockRandom'], ['goog.Disposable'], false); -goog.addDependency('testing/mockrandom_test.js', ['goog.testing.MockRandomTest'], ['goog.testing.MockRandom', 'goog.testing.jsunit'], false); -goog.addDependency('testing/mockrange.js', ['goog.testing.MockRange'], ['goog.dom.AbstractRange', 'goog.testing.LooseMock'], false); -goog.addDependency('testing/mockrange_test.js', ['goog.testing.MockRangeTest'], ['goog.testing.MockRange', 'goog.testing.jsunit'], false); -goog.addDependency('testing/mockstorage.js', ['goog.testing.MockStorage'], ['goog.structs.Map'], false); -goog.addDependency('testing/mockstorage_test.js', ['goog.testing.MockStorageTest'], ['goog.testing.MockStorage', 'goog.testing.jsunit'], false); -goog.addDependency('testing/mockuseragent.js', ['goog.testing.MockUserAgent'], ['goog.Disposable', 'goog.labs.userAgent.util', 'goog.testing.PropertyReplacer', 'goog.userAgent'], false); -goog.addDependency('testing/mockuseragent_test.js', ['goog.testing.MockUserAgentTest'], ['goog.dispose', 'goog.testing.MockUserAgent', 'goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('testing/multitestrunner.js', ['goog.testing.MultiTestRunner', 'goog.testing.MultiTestRunner.TestFrame'], ['goog.Timer', 'goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.events.EventHandler', 'goog.functions', 'goog.string', 'goog.ui.Component', 'goog.ui.ServerChart', 'goog.ui.TableSorter'], false); -goog.addDependency('testing/net/xhrio.js', ['goog.testing.net.XhrIo'], ['goog.array', 'goog.dom.xml', 'goog.events', 'goog.events.EventTarget', 'goog.json', 'goog.net.ErrorCode', 'goog.net.EventType', 'goog.net.HttpStatus', 'goog.net.XhrIo', 'goog.net.XmlHttp', 'goog.object', 'goog.structs.Map'], false); -goog.addDependency('testing/net/xhrio_test.js', ['goog.testing.net.XhrIoTest'], ['goog.dom.xml', 'goog.events', 'goog.events.Event', 'goog.net.ErrorCode', 'goog.net.EventType', 'goog.net.XmlHttp', 'goog.object', 'goog.testing.MockControl', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.testing.mockmatchers.InstanceOf', 'goog.testing.net.XhrIo'], false); -goog.addDependency('testing/net/xhriopool.js', ['goog.testing.net.XhrIoPool'], ['goog.net.XhrIoPool', 'goog.testing.net.XhrIo'], false); -goog.addDependency('testing/objectpropertystring.js', ['goog.testing.ObjectPropertyString'], [], false); -goog.addDependency('testing/performancetable.js', ['goog.testing.PerformanceTable'], ['goog.dom', 'goog.dom.TagName', 'goog.testing.PerformanceTimer'], false); -goog.addDependency('testing/performancetimer.js', ['goog.testing.PerformanceTimer', 'goog.testing.PerformanceTimer.Task'], ['goog.array', 'goog.async.Deferred', 'goog.math'], false); -goog.addDependency('testing/performancetimer_test.js', ['goog.testing.PerformanceTimerTest'], ['goog.async.Deferred', 'goog.dom', 'goog.math', 'goog.testing.MockClock', 'goog.testing.PerformanceTimer', 'goog.testing.jsunit'], false); -goog.addDependency('testing/propertyreplacer.js', ['goog.testing.PropertyReplacer'], ['goog.testing.ObjectPropertyString', 'goog.userAgent'], false); -goog.addDependency('testing/propertyreplacer_test.js', ['goog.testing.PropertyReplacerTest'], ['goog.testing.PropertyReplacer', 'goog.testing.asserts', 'goog.testing.jsunit'], false); -goog.addDependency('testing/proto2/proto2.js', ['goog.testing.proto2'], ['goog.proto2.Message', 'goog.proto2.ObjectSerializer', 'goog.testing.asserts'], false); -goog.addDependency('testing/proto2/proto2_test.js', ['goog.testing.proto2Test'], ['goog.testing.jsunit', 'goog.testing.proto2', 'proto2.TestAllTypes'], false); -goog.addDependency('testing/pseudorandom.js', ['goog.testing.PseudoRandom'], ['goog.Disposable'], false); -goog.addDependency('testing/pseudorandom_test.js', ['goog.testing.PseudoRandomTest'], ['goog.testing.PseudoRandom', 'goog.testing.jsunit'], false); -goog.addDependency('testing/recordfunction.js', ['goog.testing.FunctionCall', 'goog.testing.recordConstructor', 'goog.testing.recordFunction'], ['goog.testing.asserts'], false); -goog.addDependency('testing/recordfunction_test.js', ['goog.testing.recordFunctionTest'], ['goog.functions', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordConstructor', 'goog.testing.recordFunction'], false); -goog.addDependency('testing/shardingtestcase.js', ['goog.testing.ShardingTestCase'], ['goog.asserts', 'goog.testing.TestCase'], false); -goog.addDependency('testing/shardingtestcase_test.js', ['goog.testing.ShardingTestCaseTest'], ['goog.testing.ShardingTestCase', 'goog.testing.TestCase', 'goog.testing.asserts', 'goog.testing.jsunit'], false); -goog.addDependency('testing/singleton.js', ['goog.testing.singleton'], [], false); -goog.addDependency('testing/singleton_test.js', ['goog.testing.singletonTest'], ['goog.testing.asserts', 'goog.testing.jsunit', 'goog.testing.singleton'], false); -goog.addDependency('testing/stacktrace.js', ['goog.testing.stacktrace', 'goog.testing.stacktrace.Frame'], [], false); -goog.addDependency('testing/stacktrace_test.js', ['goog.testing.stacktraceTest'], ['goog.functions', 'goog.string', 'goog.testing.ExpectedFailures', 'goog.testing.PropertyReplacer', 'goog.testing.StrictMock', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.testing.stacktrace', 'goog.testing.stacktrace.Frame', 'goog.userAgent'], false); -goog.addDependency('testing/storage/fakemechanism.js', ['goog.testing.storage.FakeMechanism'], ['goog.storage.mechanism.IterableMechanism', 'goog.structs.Map'], false); -goog.addDependency('testing/strictmock.js', ['goog.testing.StrictMock'], ['goog.array', 'goog.testing.Mock'], false); -goog.addDependency('testing/strictmock_test.js', ['goog.testing.StrictMockTest'], ['goog.testing.StrictMock', 'goog.testing.jsunit'], false); -goog.addDependency('testing/style/layoutasserts.js', ['goog.testing.style.layoutasserts'], ['goog.style', 'goog.testing.asserts', 'goog.testing.style'], false); -goog.addDependency('testing/style/layoutasserts_test.js', ['goog.testing.style.layoutassertsTest'], ['goog.dom', 'goog.style', 'goog.testing.jsunit', 'goog.testing.style.layoutasserts'], false); -goog.addDependency('testing/style/style.js', ['goog.testing.style'], ['goog.dom', 'goog.math.Rect', 'goog.style'], false); -goog.addDependency('testing/style/style_test.js', ['goog.testing.styleTest'], ['goog.dom', 'goog.style', 'goog.testing.jsunit', 'goog.testing.style'], false); -goog.addDependency('testing/testcase.js', ['goog.testing.TestCase', 'goog.testing.TestCase.Error', 'goog.testing.TestCase.Order', 'goog.testing.TestCase.Result', 'goog.testing.TestCase.Test'], ['goog.Promise', 'goog.Thenable', 'goog.object', 'goog.testing.asserts', 'goog.testing.stacktrace'], false); -goog.addDependency('testing/testcase_test.js', ['goog.testing.TestCaseTest'], ['goog.Promise', 'goog.testing.TestCase', 'goog.testing.jsunit'], false); -goog.addDependency('testing/testqueue.js', ['goog.testing.TestQueue'], [], false); -goog.addDependency('testing/testrunner.js', ['goog.testing.TestRunner'], ['goog.testing.TestCase'], false); -goog.addDependency('testing/ui/rendererasserts.js', ['goog.testing.ui.rendererasserts'], ['goog.testing.asserts', 'goog.ui.ControlRenderer'], false); -goog.addDependency('testing/ui/rendererasserts_test.js', ['goog.testing.ui.rendererassertsTest'], ['goog.testing.asserts', 'goog.testing.jsunit', 'goog.testing.ui.rendererasserts', 'goog.ui.ControlRenderer'], false); -goog.addDependency('testing/ui/rendererharness.js', ['goog.testing.ui.RendererHarness'], ['goog.Disposable', 'goog.dom.NodeType', 'goog.testing.asserts', 'goog.testing.dom'], false); -goog.addDependency('testing/ui/style.js', ['goog.testing.ui.style'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.testing.asserts'], false); -goog.addDependency('testing/ui/style_test.js', ['goog.testing.ui.styleTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.testing.ui.style'], false); -goog.addDependency('testing/watchers.js', ['goog.testing.watchers'], [], false); -goog.addDependency('timer/timer.js', ['goog.Timer'], ['goog.Promise', 'goog.events.EventTarget'], false); -goog.addDependency('timer/timer_test.js', ['goog.TimerTest'], ['goog.Promise', 'goog.Timer', 'goog.events', 'goog.testing.MockClock', 'goog.testing.jsunit'], false); -goog.addDependency('tweak/entries.js', ['goog.tweak.BaseEntry', 'goog.tweak.BasePrimitiveSetting', 'goog.tweak.BaseSetting', 'goog.tweak.BooleanGroup', 'goog.tweak.BooleanInGroupSetting', 'goog.tweak.BooleanSetting', 'goog.tweak.ButtonAction', 'goog.tweak.NumericSetting', 'goog.tweak.StringSetting'], ['goog.array', 'goog.asserts', 'goog.log', 'goog.object'], false); -goog.addDependency('tweak/entries_test.js', ['goog.tweak.BaseEntryTest'], ['goog.testing.MockControl', 'goog.testing.jsunit', 'goog.tweak.testhelpers'], false); -goog.addDependency('tweak/registry.js', ['goog.tweak.Registry'], ['goog.array', 'goog.asserts', 'goog.log', 'goog.string', 'goog.tweak.BasePrimitiveSetting', 'goog.tweak.BaseSetting', 'goog.tweak.BooleanSetting', 'goog.tweak.NumericSetting', 'goog.tweak.StringSetting', 'goog.uri.utils'], false); -goog.addDependency('tweak/registry_test.js', ['goog.tweak.RegistryTest'], ['goog.asserts.AssertionError', 'goog.testing.jsunit', 'goog.tweak', 'goog.tweak.testhelpers'], false); -goog.addDependency('tweak/testhelpers.js', ['goog.tweak.testhelpers'], ['goog.tweak', 'goog.tweak.BooleanGroup', 'goog.tweak.BooleanInGroupSetting', 'goog.tweak.BooleanSetting', 'goog.tweak.ButtonAction', 'goog.tweak.NumericSetting', 'goog.tweak.Registry', 'goog.tweak.StringSetting'], false); -goog.addDependency('tweak/tweak.js', ['goog.tweak', 'goog.tweak.ConfigParams'], ['goog.asserts', 'goog.tweak.BaseSetting', 'goog.tweak.BooleanGroup', 'goog.tweak.BooleanInGroupSetting', 'goog.tweak.BooleanSetting', 'goog.tweak.ButtonAction', 'goog.tweak.NumericSetting', 'goog.tweak.Registry', 'goog.tweak.StringSetting'], false); -goog.addDependency('tweak/tweakui.js', ['goog.tweak.EntriesPanel', 'goog.tweak.TweakUi'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.safe', 'goog.html.SafeHtml', 'goog.object', 'goog.string.Const', 'goog.style', 'goog.tweak', 'goog.tweak.BaseEntry', 'goog.tweak.BooleanGroup', 'goog.tweak.BooleanInGroupSetting', 'goog.tweak.BooleanSetting', 'goog.tweak.ButtonAction', 'goog.tweak.NumericSetting', 'goog.tweak.StringSetting', 'goog.ui.Zippy', 'goog.userAgent'], false); -goog.addDependency('tweak/tweakui_test.js', ['goog.tweak.TweakUiTest'], ['goog.dom', 'goog.string', 'goog.testing.jsunit', 'goog.tweak', 'goog.tweak.TweakUi', 'goog.tweak.testhelpers'], false); -goog.addDependency('ui/abstractspellchecker.js', ['goog.ui.AbstractSpellChecker', 'goog.ui.AbstractSpellChecker.AsyncResult'], ['goog.a11y.aria', 'goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.classlist', 'goog.dom.selection', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.math.Coordinate', 'goog.spell.SpellCheck', 'goog.structs.Set', 'goog.style', 'goog.ui.Component', 'goog.ui.MenuItem', 'goog.ui.MenuSeparator', 'goog.ui.PopupMenu'], false); -goog.addDependency('ui/ac/ac.js', ['goog.ui.ac'], ['goog.ui.ac.ArrayMatcher', 'goog.ui.ac.AutoComplete', 'goog.ui.ac.InputHandler', 'goog.ui.ac.Renderer'], false); -goog.addDependency('ui/ac/ac_test.js', ['goog.ui.acTest'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.classlist', 'goog.dom.selection', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.Event', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.style', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.ui.ac', 'goog.userAgent'], false); -goog.addDependency('ui/ac/arraymatcher.js', ['goog.ui.ac.ArrayMatcher'], ['goog.string'], false); -goog.addDependency('ui/ac/arraymatcher_test.js', ['goog.ui.ac.ArrayMatcherTest'], ['goog.testing.jsunit', 'goog.ui.ac.ArrayMatcher'], false); -goog.addDependency('ui/ac/autocomplete.js', ['goog.ui.ac.AutoComplete', 'goog.ui.ac.AutoComplete.EventType'], ['goog.array', 'goog.asserts', 'goog.events', 'goog.events.EventTarget', 'goog.object'], false); -goog.addDependency('ui/ac/autocomplete_test.js', ['goog.ui.ac.AutoCompleteTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.dom', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.string', 'goog.testing.MockControl', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.mockmatchers', 'goog.ui.ac.AutoComplete', 'goog.ui.ac.InputHandler', 'goog.ui.ac.RenderOptions', 'goog.ui.ac.Renderer'], false); -goog.addDependency('ui/ac/cachingmatcher.js', ['goog.ui.ac.CachingMatcher'], ['goog.array', 'goog.async.Throttle', 'goog.ui.ac.ArrayMatcher', 'goog.ui.ac.RenderOptions'], false); -goog.addDependency('ui/ac/cachingmatcher_test.js', ['goog.ui.ac.CachingMatcherTest'], ['goog.testing.MockControl', 'goog.testing.jsunit', 'goog.testing.mockmatchers', 'goog.ui.ac.CachingMatcher'], false); -goog.addDependency('ui/ac/inputhandler.js', ['goog.ui.ac.InputHandler'], ['goog.Disposable', 'goog.Timer', 'goog.a11y.aria', 'goog.dom', 'goog.dom.selection', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.string', 'goog.userAgent', 'goog.userAgent.product'], false); -goog.addDependency('ui/ac/inputhandler_test.js', ['goog.ui.ac.InputHandlerTest'], ['goog.dom.selection', 'goog.events.BrowserEvent', 'goog.events.Event', 'goog.events.EventTarget', 'goog.events.KeyCodes', 'goog.functions', 'goog.object', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.ui.ac.InputHandler', 'goog.userAgent'], false); -goog.addDependency('ui/ac/remote.js', ['goog.ui.ac.Remote'], ['goog.ui.ac.AutoComplete', 'goog.ui.ac.InputHandler', 'goog.ui.ac.RemoteArrayMatcher', 'goog.ui.ac.Renderer'], false); -goog.addDependency('ui/ac/remotearraymatcher.js', ['goog.ui.ac.RemoteArrayMatcher'], ['goog.Disposable', 'goog.Uri', 'goog.events', 'goog.json', 'goog.net.EventType', 'goog.net.XhrIo'], false); -goog.addDependency('ui/ac/remotearraymatcher_test.js', ['goog.ui.ac.RemoteArrayMatcherTest'], ['goog.json', 'goog.net.XhrIo', 'goog.testing.MockControl', 'goog.testing.jsunit', 'goog.testing.net.XhrIo', 'goog.ui.ac.RemoteArrayMatcher'], false); -goog.addDependency('ui/ac/renderer.js', ['goog.ui.ac.Renderer', 'goog.ui.ac.Renderer.CustomRenderer'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.array', 'goog.asserts', 'goog.dispose', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.classlist', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.fx.dom.FadeInAndShow', 'goog.fx.dom.FadeOutAndHide', 'goog.positioning', 'goog.positioning.Corner', 'goog.positioning.Overflow', 'goog.string', 'goog.style', 'goog.ui.IdGenerator', 'goog.ui.ac.AutoComplete'], false); -goog.addDependency('ui/ac/renderer_test.js', ['goog.ui.ac.RendererTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.fx.dom.FadeInAndShow', 'goog.fx.dom.FadeOutAndHide', 'goog.string', 'goog.style', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.ui.ac.AutoComplete', 'goog.ui.ac.Renderer'], false); -goog.addDependency('ui/ac/renderoptions.js', ['goog.ui.ac.RenderOptions'], [], false); -goog.addDependency('ui/ac/richinputhandler.js', ['goog.ui.ac.RichInputHandler'], ['goog.ui.ac.InputHandler'], false); -goog.addDependency('ui/ac/richremote.js', ['goog.ui.ac.RichRemote'], ['goog.ui.ac.AutoComplete', 'goog.ui.ac.Remote', 'goog.ui.ac.Renderer', 'goog.ui.ac.RichInputHandler', 'goog.ui.ac.RichRemoteArrayMatcher'], false); -goog.addDependency('ui/ac/richremotearraymatcher.js', ['goog.ui.ac.RichRemoteArrayMatcher'], ['goog.dom.safe', 'goog.html.legacyconversions', 'goog.json', 'goog.ui.ac.RemoteArrayMatcher'], false); -goog.addDependency('ui/activitymonitor.js', ['goog.ui.ActivityMonitor'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType'], false); -goog.addDependency('ui/activitymonitor_test.js', ['goog.ui.ActivityMonitorTest'], ['goog.dom', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.ActivityMonitor'], false); -goog.addDependency('ui/advancedtooltip.js', ['goog.ui.AdvancedTooltip'], ['goog.events', 'goog.events.EventType', 'goog.math.Box', 'goog.math.Coordinate', 'goog.style', 'goog.ui.Tooltip', 'goog.userAgent'], false); -goog.addDependency('ui/advancedtooltip_test.js', ['goog.ui.AdvancedTooltipTest'], ['goog.dom', 'goog.events.Event', 'goog.events.EventType', 'goog.math.Box', 'goog.math.Coordinate', 'goog.style', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.AdvancedTooltip', 'goog.ui.Tooltip', 'goog.userAgent'], false); -goog.addDependency('ui/animatedzippy.js', ['goog.ui.AnimatedZippy'], ['goog.dom', 'goog.events', 'goog.fx.Animation', 'goog.fx.Transition', 'goog.fx.easing', 'goog.ui.Zippy', 'goog.ui.ZippyEvent'], false); -goog.addDependency('ui/animatedzippy_test.js', ['goog.ui.AnimatedZippyTest'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.asserts', 'goog.dom', 'goog.events', 'goog.functions', 'goog.fx.Animation', 'goog.fx.Transition', 'goog.testing.PropertyReplacer', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.ui.AnimatedZippy', 'goog.ui.Zippy'], false); -goog.addDependency('ui/attachablemenu.js', ['goog.ui.AttachableMenu'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.events.Event', 'goog.events.KeyCodes', 'goog.string', 'goog.style', 'goog.ui.ItemEvent', 'goog.ui.MenuBase', 'goog.ui.PopupBase', 'goog.userAgent'], false); -goog.addDependency('ui/bidiinput.js', ['goog.ui.BidiInput'], ['goog.dom', 'goog.events', 'goog.events.InputHandler', 'goog.i18n.bidi', 'goog.i18n.bidi.Dir', 'goog.ui.Component'], false); -goog.addDependency('ui/bidiinput_test.js', ['goog.ui.BidiInputTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.ui.BidiInput'], false); -goog.addDependency('ui/bubble.js', ['goog.ui.Bubble'], ['goog.Timer', 'goog.dom.safe', 'goog.events', 'goog.events.EventType', 'goog.html.SafeHtml', 'goog.html.legacyconversions', 'goog.math.Box', 'goog.positioning', 'goog.positioning.AbsolutePosition', 'goog.positioning.AnchoredPosition', 'goog.positioning.Corner', 'goog.positioning.CornerBit', 'goog.string.Const', 'goog.style', 'goog.ui.Component', 'goog.ui.Popup'], false); -goog.addDependency('ui/button.js', ['goog.ui.Button', 'goog.ui.Button.Side'], ['goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.ui.ButtonRenderer', 'goog.ui.ButtonSide', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.NativeButtonRenderer', 'goog.ui.registry'], false); -goog.addDependency('ui/button_test.js', ['goog.ui.ButtonTest'], ['goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Button', 'goog.ui.ButtonRenderer', 'goog.ui.ButtonSide', 'goog.ui.Component', 'goog.ui.NativeButtonRenderer'], false); -goog.addDependency('ui/buttonrenderer.js', ['goog.ui.ButtonRenderer'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.asserts', 'goog.ui.ButtonSide', 'goog.ui.Component', 'goog.ui.ControlRenderer'], false); -goog.addDependency('ui/buttonrenderer_test.js', ['goog.ui.ButtonRendererTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.classlist', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit', 'goog.testing.ui.rendererasserts', 'goog.ui.Button', 'goog.ui.ButtonRenderer', 'goog.ui.ButtonSide', 'goog.ui.Component'], false); -goog.addDependency('ui/buttonside.js', ['goog.ui.ButtonSide'], [], false); -goog.addDependency('ui/charcounter.js', ['goog.ui.CharCounter', 'goog.ui.CharCounter.Display'], ['goog.dom', 'goog.events', 'goog.events.EventTarget', 'goog.events.InputHandler'], false); -goog.addDependency('ui/charcounter_test.js', ['goog.ui.CharCounterTest'], ['goog.dom', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.ui.CharCounter', 'goog.userAgent'], false); -goog.addDependency('ui/charpicker.js', ['goog.ui.CharPicker'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.InputHandler', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.i18n.CharListDecompressor', 'goog.i18n.uChar', 'goog.structs.Set', 'goog.style', 'goog.ui.Button', 'goog.ui.Component', 'goog.ui.ContainerScroller', 'goog.ui.FlatButtonRenderer', 'goog.ui.HoverCard', 'goog.ui.LabelInput', 'goog.ui.Menu', 'goog.ui.MenuButton', 'goog.ui.MenuItem', 'goog.ui.Tooltip'], false); -goog.addDependency('ui/charpicker_test.js', ['goog.ui.CharPickerTest'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.dispose', 'goog.dom', 'goog.events.Event', 'goog.events.EventType', 'goog.i18n.CharPickerData', 'goog.i18n.uChar.NameFetcher', 'goog.testing.MockControl', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.mockmatchers', 'goog.ui.CharPicker', 'goog.ui.FlatButtonRenderer'], false); -goog.addDependency('ui/checkbox.js', ['goog.ui.Checkbox', 'goog.ui.Checkbox.State'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.string', 'goog.ui.CheckboxRenderer', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.registry'], false); -goog.addDependency('ui/checkbox_test.js', ['goog.ui.CheckboxTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.events.KeyCodes', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Checkbox', 'goog.ui.CheckboxRenderer', 'goog.ui.Component', 'goog.ui.ControlRenderer', 'goog.ui.decorate'], false); -goog.addDependency('ui/checkboxmenuitem.js', ['goog.ui.CheckBoxMenuItem'], ['goog.ui.MenuItem', 'goog.ui.registry'], false); -goog.addDependency('ui/checkboxrenderer.js', ['goog.ui.CheckboxRenderer'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.array', 'goog.asserts', 'goog.dom.classlist', 'goog.object', 'goog.ui.ControlRenderer'], false); -goog.addDependency('ui/colorbutton.js', ['goog.ui.ColorButton'], ['goog.ui.Button', 'goog.ui.ColorButtonRenderer', 'goog.ui.registry'], false); -goog.addDependency('ui/colorbutton_test.js', ['goog.ui.ColorButtonTest'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.testing.jsunit', 'goog.ui.ColorButton', 'goog.ui.decorate'], false); -goog.addDependency('ui/colorbuttonrenderer.js', ['goog.ui.ColorButtonRenderer'], ['goog.asserts', 'goog.dom.classlist', 'goog.functions', 'goog.ui.ColorMenuButtonRenderer'], false); -goog.addDependency('ui/colormenubutton.js', ['goog.ui.ColorMenuButton'], ['goog.array', 'goog.object', 'goog.ui.ColorMenuButtonRenderer', 'goog.ui.ColorPalette', 'goog.ui.Component', 'goog.ui.Menu', 'goog.ui.MenuButton', 'goog.ui.registry'], false); -goog.addDependency('ui/colormenubuttonrenderer.js', ['goog.ui.ColorMenuButtonRenderer'], ['goog.asserts', 'goog.color', 'goog.dom.classlist', 'goog.ui.MenuButtonRenderer', 'goog.userAgent'], false); -goog.addDependency('ui/colormenubuttonrenderer_test.js', ['goog.ui.ColorMenuButtonTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.testing.ui.RendererHarness', 'goog.testing.ui.rendererasserts', 'goog.ui.ColorMenuButton', 'goog.ui.ColorMenuButtonRenderer', 'goog.userAgent'], false); -goog.addDependency('ui/colorpalette.js', ['goog.ui.ColorPalette'], ['goog.array', 'goog.color', 'goog.style', 'goog.ui.Palette', 'goog.ui.PaletteRenderer'], false); -goog.addDependency('ui/colorpalette_test.js', ['goog.ui.ColorPaletteTest'], ['goog.color', 'goog.testing.jsunit', 'goog.ui.ColorPalette'], false); -goog.addDependency('ui/colorpicker.js', ['goog.ui.ColorPicker', 'goog.ui.ColorPicker.EventType'], ['goog.ui.ColorPalette', 'goog.ui.Component'], false); -goog.addDependency('ui/colorsplitbehavior.js', ['goog.ui.ColorSplitBehavior'], ['goog.ui.ColorMenuButton', 'goog.ui.SplitBehavior'], false); -goog.addDependency('ui/combobox.js', ['goog.ui.ComboBox', 'goog.ui.ComboBoxItem'], ['goog.Timer', 'goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.events.EventType', 'goog.events.InputHandler', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.log', 'goog.positioning.Corner', 'goog.positioning.MenuAnchoredPosition', 'goog.string', 'goog.style', 'goog.ui.Component', 'goog.ui.ItemEvent', 'goog.ui.LabelInput', 'goog.ui.Menu', 'goog.ui.MenuItem', 'goog.ui.MenuSeparator', 'goog.ui.registry', 'goog.userAgent'], false); -goog.addDependency('ui/combobox_test.js', ['goog.ui.ComboBoxTest'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.KeyCodes', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.ComboBox', 'goog.ui.ComboBoxItem', 'goog.ui.Component', 'goog.ui.ControlRenderer', 'goog.ui.LabelInput', 'goog.ui.Menu', 'goog.ui.MenuItem'], false); -goog.addDependency('ui/component.js', ['goog.ui.Component', 'goog.ui.Component.Error', 'goog.ui.Component.EventType', 'goog.ui.Component.State'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.NodeType', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.object', 'goog.style', 'goog.ui.IdGenerator'], false); -goog.addDependency('ui/component_test.js', ['goog.ui.ComponentTest'], ['goog.dom', 'goog.dom.DomHelper', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.events.EventTarget', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.ui.Component'], false); -goog.addDependency('ui/container.js', ['goog.ui.Container', 'goog.ui.Container.EventType', 'goog.ui.Container.Orientation'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.asserts', 'goog.dom', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.object', 'goog.style', 'goog.ui.Component', 'goog.ui.ContainerRenderer', 'goog.ui.Control'], false); -goog.addDependency('ui/container_test.js', ['goog.ui.ContainerTest'], ['goog.a11y.aria', 'goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.events.Event', 'goog.events.KeyCodes', 'goog.events.KeyEvent', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.Container', 'goog.ui.Control'], false); -goog.addDependency('ui/containerrenderer.js', ['goog.ui.ContainerRenderer'], ['goog.a11y.aria', 'goog.array', 'goog.asserts', 'goog.dom.NodeType', 'goog.dom.classlist', 'goog.string', 'goog.style', 'goog.ui.registry', 'goog.userAgent'], false); -goog.addDependency('ui/containerrenderer_test.js', ['goog.ui.ContainerRendererTest'], ['goog.dom', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.ui.rendererasserts', 'goog.ui.Container', 'goog.ui.ContainerRenderer', 'goog.userAgent'], false); -goog.addDependency('ui/containerscroller.js', ['goog.ui.ContainerScroller'], ['goog.Disposable', 'goog.Timer', 'goog.events.EventHandler', 'goog.style', 'goog.ui.Component', 'goog.ui.Container'], false); -goog.addDependency('ui/containerscroller_test.js', ['goog.ui.ContainerScrollerTest'], ['goog.dom', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Container', 'goog.ui.ContainerScroller'], false); -goog.addDependency('ui/control.js', ['goog.ui.Control'], ['goog.array', 'goog.dom', 'goog.events.Event', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.string', 'goog.ui.Component', 'goog.ui.ControlContent', 'goog.ui.ControlRenderer', 'goog.ui.decorate', 'goog.ui.registry', 'goog.userAgent'], false); -goog.addDependency('ui/control_test.js', ['goog.ui.ControlTest'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.array', 'goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.KeyCodes', 'goog.object', 'goog.string', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.ControlRenderer', 'goog.ui.registry', 'goog.userAgent'], false); -goog.addDependency('ui/controlcontent.js', ['goog.ui.ControlContent'], [], false); -goog.addDependency('ui/controlrenderer.js', ['goog.ui.ControlRenderer'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.object', 'goog.string', 'goog.style', 'goog.ui.Component', 'goog.userAgent'], false); -goog.addDependency('ui/controlrenderer_test.js', ['goog.ui.ControlRendererTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.classlist', 'goog.object', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.ControlRenderer', 'goog.userAgent'], false); -goog.addDependency('ui/cookieeditor.js', ['goog.ui.CookieEditor'], ['goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.events.EventType', 'goog.net.cookies', 'goog.string', 'goog.style', 'goog.ui.Component'], false); -goog.addDependency('ui/cookieeditor_test.js', ['goog.ui.CookieEditorTest'], ['goog.dom', 'goog.events.Event', 'goog.events.EventType', 'goog.net.cookies', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.CookieEditor'], false); -goog.addDependency('ui/css3buttonrenderer.js', ['goog.ui.Css3ButtonRenderer'], ['goog.asserts', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.ui.Button', 'goog.ui.ButtonRenderer', 'goog.ui.Component', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.registry'], false); -goog.addDependency('ui/css3menubuttonrenderer.js', ['goog.ui.Css3MenuButtonRenderer'], ['goog.dom', 'goog.dom.TagName', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.MenuButton', 'goog.ui.MenuButtonRenderer', 'goog.ui.registry'], false); -goog.addDependency('ui/cssnames.js', ['goog.ui.INLINE_BLOCK_CLASSNAME'], [], false); -goog.addDependency('ui/custombutton.js', ['goog.ui.CustomButton'], ['goog.ui.Button', 'goog.ui.CustomButtonRenderer', 'goog.ui.registry'], false); -goog.addDependency('ui/custombuttonrenderer.js', ['goog.ui.CustomButtonRenderer'], ['goog.a11y.aria.Role', 'goog.asserts', 'goog.dom.NodeType', 'goog.dom.classlist', 'goog.string', 'goog.ui.ButtonRenderer', 'goog.ui.INLINE_BLOCK_CLASSNAME'], false); -goog.addDependency('ui/customcolorpalette.js', ['goog.ui.CustomColorPalette'], ['goog.color', 'goog.dom', 'goog.dom.classlist', 'goog.ui.ColorPalette', 'goog.ui.Component'], false); -goog.addDependency('ui/customcolorpalette_test.js', ['goog.ui.CustomColorPaletteTest'], ['goog.dom.TagName', 'goog.dom.classlist', 'goog.testing.jsunit', 'goog.ui.CustomColorPalette'], false); -goog.addDependency('ui/datepicker.js', ['goog.ui.DatePicker', 'goog.ui.DatePicker.Events', 'goog.ui.DatePickerEvent'], ['goog.a11y.aria', 'goog.asserts', 'goog.date.Date', 'goog.date.DateRange', 'goog.date.Interval', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.classlist', 'goog.events.Event', 'goog.events.EventType', 'goog.events.KeyHandler', 'goog.i18n.DateTimeFormat', 'goog.i18n.DateTimePatterns', 'goog.i18n.DateTimeSymbols', 'goog.style', 'goog.ui.Component', 'goog.ui.DefaultDatePickerRenderer', 'goog.ui.IdGenerator'], false); -goog.addDependency('ui/datepicker_test.js', ['goog.ui.DatePickerTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.date.Date', 'goog.date.DateRange', 'goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.i18n.DateTimeSymbols', 'goog.i18n.DateTimeSymbols_en_US', 'goog.i18n.DateTimeSymbols_zh_HK', 'goog.style', 'goog.testing.jsunit', 'goog.ui.DatePicker'], false); -goog.addDependency('ui/datepickerrenderer.js', ['goog.ui.DatePickerRenderer'], [], false); -goog.addDependency('ui/decorate.js', ['goog.ui.decorate'], ['goog.ui.registry'], false); -goog.addDependency('ui/decorate_test.js', ['goog.ui.decorateTest'], ['goog.testing.jsunit', 'goog.ui.decorate', 'goog.ui.registry'], false); -goog.addDependency('ui/defaultdatepickerrenderer.js', ['goog.ui.DefaultDatePickerRenderer'], ['goog.dom', 'goog.dom.TagName', 'goog.ui.DatePickerRenderer'], false); -goog.addDependency('ui/dialog.js', ['goog.ui.Dialog', 'goog.ui.Dialog.ButtonSet', 'goog.ui.Dialog.ButtonSet.DefaultButtons', 'goog.ui.Dialog.DefaultButtonCaptions', 'goog.ui.Dialog.DefaultButtonKeys', 'goog.ui.Dialog.Event', 'goog.ui.Dialog.EventType'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.asserts', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.dom.safe', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.fx.Dragger', 'goog.html.SafeHtml', 'goog.html.legacyconversions', 'goog.math.Rect', 'goog.string', 'goog.structs.Map', 'goog.style', 'goog.ui.ModalPopup'], false); -goog.addDependency('ui/dialog_test.js', ['goog.ui.DialogTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.fx.css3', 'goog.html.SafeHtml', 'goog.html.testing', 'goog.style', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.Dialog', 'goog.userAgent'], false); -goog.addDependency('ui/dimensionpicker.js', ['goog.ui.DimensionPicker'], ['goog.events.EventType', 'goog.events.KeyCodes', 'goog.math.Size', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.DimensionPickerRenderer', 'goog.ui.registry'], false); -goog.addDependency('ui/dimensionpicker_test.js', ['goog.ui.DimensionPickerTest'], ['goog.dom', 'goog.dom.TagName', 'goog.events.KeyCodes', 'goog.math.Size', 'goog.testing.jsunit', 'goog.testing.ui.rendererasserts', 'goog.ui.DimensionPicker', 'goog.ui.DimensionPickerRenderer'], false); -goog.addDependency('ui/dimensionpickerrenderer.js', ['goog.ui.DimensionPickerRenderer'], ['goog.a11y.aria.Announcer', 'goog.a11y.aria.LivePriority', 'goog.dom', 'goog.dom.TagName', 'goog.i18n.bidi', 'goog.style', 'goog.ui.ControlRenderer', 'goog.userAgent'], false); -goog.addDependency('ui/dimensionpickerrenderer_test.js', ['goog.ui.DimensionPickerRendererTest'], ['goog.a11y.aria.LivePriority', 'goog.array', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.DimensionPicker', 'goog.ui.DimensionPickerRenderer'], false); -goog.addDependency('ui/dragdropdetector.js', ['goog.ui.DragDropDetector', 'goog.ui.DragDropDetector.EventType', 'goog.ui.DragDropDetector.ImageDropEvent', 'goog.ui.DragDropDetector.LinkDropEvent'], ['goog.dom', 'goog.dom.TagName', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.math.Coordinate', 'goog.string', 'goog.style', 'goog.userAgent'], false); -goog.addDependency('ui/drilldownrow.js', ['goog.ui.DrilldownRow'], ['goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.ui.Component'], false); -goog.addDependency('ui/drilldownrow_test.js', ['goog.ui.DrilldownRowTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.ui.DrilldownRow'], false); -goog.addDependency('ui/editor/abstractdialog.js', ['goog.ui.editor.AbstractDialog', 'goog.ui.editor.AbstractDialog.Builder', 'goog.ui.editor.AbstractDialog.EventType'], ['goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.events.EventTarget', 'goog.string', 'goog.ui.Dialog', 'goog.ui.PopupBase'], false); -goog.addDependency('ui/editor/abstractdialog_test.js', ['goog.ui.editor.AbstractDialogTest'], ['goog.dom', 'goog.dom.DomHelper', 'goog.dom.classlist', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.KeyCodes', 'goog.testing.MockControl', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.mockmatchers.ArgumentMatcher', 'goog.ui.editor.AbstractDialog', 'goog.userAgent'], false); -goog.addDependency('ui/editor/bubble.js', ['goog.ui.editor.Bubble'], ['goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.ViewportSizeMonitor', 'goog.dom.classlist', 'goog.editor.style', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.functions', 'goog.log', 'goog.math.Box', 'goog.object', 'goog.positioning', 'goog.positioning.Corner', 'goog.positioning.Overflow', 'goog.positioning.OverflowStatus', 'goog.string', 'goog.style', 'goog.ui.Component', 'goog.ui.PopupBase', 'goog.userAgent'], false); -goog.addDependency('ui/editor/bubble_test.js', ['goog.ui.editor.BubbleTest'], ['goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.EventType', 'goog.positioning.Corner', 'goog.positioning.OverflowStatus', 'goog.string', 'goog.style', 'goog.testing.editor.TestHelper', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.editor.Bubble'], false); -goog.addDependency('ui/editor/defaulttoolbar.js', ['goog.ui.editor.ButtonDescriptor', 'goog.ui.editor.DefaultToolbar'], ['goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.editor.Command', 'goog.style', 'goog.ui.editor.ToolbarFactory', 'goog.ui.editor.messages', 'goog.userAgent'], false); -goog.addDependency('ui/editor/linkdialog.js', ['goog.ui.editor.LinkDialog', 'goog.ui.editor.LinkDialog.BeforeTestLinkEvent', 'goog.ui.editor.LinkDialog.EventType', 'goog.ui.editor.LinkDialog.OkEvent'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.TagName', 'goog.dom.safe', 'goog.editor.BrowserFeature', 'goog.editor.Link', 'goog.editor.focus', 'goog.editor.node', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.InputHandler', 'goog.html.SafeHtml', 'goog.string', 'goog.string.Unicode', 'goog.style', 'goog.ui.Button', 'goog.ui.Component', 'goog.ui.LinkButtonRenderer', 'goog.ui.editor.AbstractDialog', 'goog.ui.editor.TabPane', 'goog.ui.editor.messages', 'goog.userAgent', 'goog.window'], false); -goog.addDependency('ui/editor/linkdialog_test.js', ['goog.ui.editor.LinkDialogTest'], ['goog.dom', 'goog.dom.DomHelper', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Link', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.style', 'goog.testing.MockControl', 'goog.testing.PropertyReplacer', 'goog.testing.dom', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.testing.mockmatchers', 'goog.testing.mockmatchers.ArgumentMatcher', 'goog.ui.editor.AbstractDialog', 'goog.ui.editor.LinkDialog', 'goog.ui.editor.messages', 'goog.userAgent'], false); -goog.addDependency('ui/editor/messages.js', ['goog.ui.editor.messages'], ['goog.html.uncheckedconversions', 'goog.string.Const'], false); -goog.addDependency('ui/editor/tabpane.js', ['goog.ui.editor.TabPane'], ['goog.asserts', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.style', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.Tab', 'goog.ui.TabBar'], false); -goog.addDependency('ui/editor/toolbarcontroller.js', ['goog.ui.editor.ToolbarController'], ['goog.editor.Field', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.ui.Component'], false); -goog.addDependency('ui/editor/toolbarfactory.js', ['goog.ui.editor.ToolbarFactory'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.string', 'goog.string.Unicode', 'goog.style', 'goog.ui.Component', 'goog.ui.Container', 'goog.ui.Option', 'goog.ui.Toolbar', 'goog.ui.ToolbarButton', 'goog.ui.ToolbarColorMenuButton', 'goog.ui.ToolbarMenuButton', 'goog.ui.ToolbarRenderer', 'goog.ui.ToolbarSelect', 'goog.userAgent'], false); -goog.addDependency('ui/editor/toolbarfactory_test.js', ['goog.ui.editor.ToolbarFactoryTest'], ['goog.dom', 'goog.testing.ExpectedFailures', 'goog.testing.editor.TestHelper', 'goog.testing.jsunit', 'goog.ui.editor.ToolbarFactory', 'goog.userAgent'], false); -goog.addDependency('ui/emoji/emoji.js', ['goog.ui.emoji.Emoji'], [], false); -goog.addDependency('ui/emoji/emojipalette.js', ['goog.ui.emoji.EmojiPalette'], ['goog.events.EventType', 'goog.net.ImageLoader', 'goog.ui.Palette', 'goog.ui.emoji.Emoji', 'goog.ui.emoji.EmojiPaletteRenderer'], false); -goog.addDependency('ui/emoji/emojipaletterenderer.js', ['goog.ui.emoji.EmojiPaletteRenderer'], ['goog.a11y.aria', 'goog.asserts', 'goog.dom.NodeType', 'goog.dom.classlist', 'goog.style', 'goog.ui.PaletteRenderer', 'goog.ui.emoji.Emoji'], false); -goog.addDependency('ui/emoji/emojipicker.js', ['goog.ui.emoji.EmojiPicker'], ['goog.log', 'goog.style', 'goog.ui.Component', 'goog.ui.TabPane', 'goog.ui.emoji.Emoji', 'goog.ui.emoji.EmojiPalette', 'goog.ui.emoji.EmojiPaletteRenderer', 'goog.ui.emoji.ProgressiveEmojiPaletteRenderer'], false); -goog.addDependency('ui/emoji/emojipicker_test.js', ['goog.ui.emoji.EmojiPickerTest'], ['goog.dom.classlist', 'goog.events.EventHandler', 'goog.style', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.emoji.Emoji', 'goog.ui.emoji.EmojiPicker', 'goog.ui.emoji.SpriteInfo'], false); -goog.addDependency('ui/emoji/fast_nonprogressive_emojipicker_test.js', ['goog.ui.emoji.FastNonProgressiveEmojiPickerTest'], ['goog.dom.classlist', 'goog.events', 'goog.events.EventType', 'goog.net.EventType', 'goog.style', 'goog.testing.AsyncTestCase', 'goog.testing.jsunit', 'goog.ui.emoji.Emoji', 'goog.ui.emoji.EmojiPicker', 'goog.ui.emoji.SpriteInfo', 'goog.userAgent'], false); -goog.addDependency('ui/emoji/fast_progressive_emojipicker_test.js', ['goog.ui.emoji.FastProgressiveEmojiPickerTest'], ['goog.dom.classlist', 'goog.events', 'goog.events.EventType', 'goog.net.EventType', 'goog.style', 'goog.testing.AsyncTestCase', 'goog.testing.jsunit', 'goog.ui.emoji.Emoji', 'goog.ui.emoji.EmojiPicker', 'goog.ui.emoji.SpriteInfo'], false); -goog.addDependency('ui/emoji/popupemojipicker.js', ['goog.ui.emoji.PopupEmojiPicker'], ['goog.events.EventType', 'goog.positioning.AnchoredPosition', 'goog.positioning.Corner', 'goog.ui.Component', 'goog.ui.Popup', 'goog.ui.emoji.EmojiPicker'], false); -goog.addDependency('ui/emoji/popupemojipicker_test.js', ['goog.ui.emoji.PopupEmojiPickerTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.ui.emoji.PopupEmojiPicker'], false); -goog.addDependency('ui/emoji/progressiveemojipaletterenderer.js', ['goog.ui.emoji.ProgressiveEmojiPaletteRenderer'], ['goog.style', 'goog.ui.emoji.EmojiPaletteRenderer'], false); -goog.addDependency('ui/emoji/spriteinfo.js', ['goog.ui.emoji.SpriteInfo'], [], false); -goog.addDependency('ui/emoji/spriteinfo_test.js', ['goog.ui.emoji.SpriteInfoTest'], ['goog.testing.jsunit', 'goog.ui.emoji.SpriteInfo'], false); -goog.addDependency('ui/filteredmenu.js', ['goog.ui.FilteredMenu'], ['goog.a11y.aria', 'goog.a11y.aria.AutoCompleteValues', 'goog.a11y.aria.State', 'goog.dom', 'goog.events', 'goog.events.EventType', 'goog.events.InputHandler', 'goog.events.KeyCodes', 'goog.object', 'goog.string', 'goog.style', 'goog.ui.Component', 'goog.ui.FilterObservingMenuItem', 'goog.ui.Menu', 'goog.ui.MenuItem', 'goog.userAgent'], false); -goog.addDependency('ui/filteredmenu_test.js', ['goog.ui.FilteredMenuTest'], ['goog.a11y.aria', 'goog.a11y.aria.AutoCompleteValues', 'goog.a11y.aria.State', 'goog.dom', 'goog.events', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.math.Rect', 'goog.style', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.FilteredMenu', 'goog.ui.MenuItem'], false); -goog.addDependency('ui/filterobservingmenuitem.js', ['goog.ui.FilterObservingMenuItem'], ['goog.ui.FilterObservingMenuItemRenderer', 'goog.ui.MenuItem', 'goog.ui.registry'], false); -goog.addDependency('ui/filterobservingmenuitemrenderer.js', ['goog.ui.FilterObservingMenuItemRenderer'], ['goog.ui.MenuItemRenderer'], false); -goog.addDependency('ui/flatbuttonrenderer.js', ['goog.ui.FlatButtonRenderer'], ['goog.a11y.aria.Role', 'goog.asserts', 'goog.dom.classlist', 'goog.ui.Button', 'goog.ui.ButtonRenderer', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.registry'], false); -goog.addDependency('ui/flatmenubuttonrenderer.js', ['goog.ui.FlatMenuButtonRenderer'], ['goog.dom', 'goog.style', 'goog.ui.FlatButtonRenderer', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.Menu', 'goog.ui.MenuButton', 'goog.ui.MenuRenderer', 'goog.ui.registry'], false); -goog.addDependency('ui/formpost.js', ['goog.ui.FormPost'], ['goog.array', 'goog.dom.TagName', 'goog.dom.safe', 'goog.html.SafeHtml', 'goog.ui.Component'], false); -goog.addDependency('ui/formpost_test.js', ['goog.ui.FormPostTest'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.object', 'goog.testing.jsunit', 'goog.ui.FormPost', 'goog.userAgent.product', 'goog.userAgent.product.isVersion'], false); -goog.addDependency('ui/gauge.js', ['goog.ui.Gauge', 'goog.ui.GaugeColoredRange'], ['goog.a11y.aria', 'goog.asserts', 'goog.events', 'goog.fx.Animation', 'goog.fx.Transition', 'goog.fx.easing', 'goog.graphics', 'goog.graphics.Font', 'goog.graphics.Path', 'goog.graphics.SolidFill', 'goog.math', 'goog.ui.Component', 'goog.ui.GaugeTheme'], false); -goog.addDependency('ui/gaugetheme.js', ['goog.ui.GaugeTheme'], ['goog.graphics.LinearGradient', 'goog.graphics.SolidFill', 'goog.graphics.Stroke'], false); -goog.addDependency('ui/hovercard.js', ['goog.ui.HoverCard', 'goog.ui.HoverCard.EventType', 'goog.ui.HoverCard.TriggerEvent'], ['goog.array', 'goog.dom', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.ui.AdvancedTooltip', 'goog.ui.PopupBase', 'goog.ui.Tooltip'], false); -goog.addDependency('ui/hovercard_test.js', ['goog.ui.HoverCardTest'], ['goog.dom', 'goog.events', 'goog.math.Coordinate', 'goog.style', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.ui.HoverCard'], false); -goog.addDependency('ui/hsvapalette.js', ['goog.ui.HsvaPalette'], ['goog.array', 'goog.color.alpha', 'goog.dom.TagName', 'goog.events', 'goog.events.EventType', 'goog.style', 'goog.ui.Component', 'goog.ui.HsvPalette'], false); -goog.addDependency('ui/hsvapalette_test.js', ['goog.ui.HsvaPaletteTest'], ['goog.color.alpha', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.Event', 'goog.math.Coordinate', 'goog.style', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.ui.HsvaPalette', 'goog.userAgent'], false); -goog.addDependency('ui/hsvpalette.js', ['goog.ui.HsvPalette'], ['goog.color', 'goog.dom.TagName', 'goog.events', 'goog.events.EventType', 'goog.events.InputHandler', 'goog.style', 'goog.style.bidi', 'goog.ui.Component', 'goog.userAgent'], false); -goog.addDependency('ui/hsvpalette_test.js', ['goog.ui.HsvPaletteTest'], ['goog.color', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.events.Event', 'goog.math.Coordinate', 'goog.style', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.HsvPalette', 'goog.userAgent'], false); -goog.addDependency('ui/idgenerator.js', ['goog.ui.IdGenerator'], [], false); -goog.addDependency('ui/idletimer.js', ['goog.ui.IdleTimer'], ['goog.Timer', 'goog.events', 'goog.events.EventTarget', 'goog.structs.Set', 'goog.ui.ActivityMonitor'], false); -goog.addDependency('ui/idletimer_test.js', ['goog.ui.IdleTimerTest'], ['goog.events', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.ui.IdleTimer', 'goog.ui.MockActivityMonitor'], false); -goog.addDependency('ui/iframemask.js', ['goog.ui.IframeMask'], ['goog.Disposable', 'goog.Timer', 'goog.dom', 'goog.dom.iframe', 'goog.events.EventHandler', 'goog.style'], false); -goog.addDependency('ui/iframemask_test.js', ['goog.ui.IframeMaskTest'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.iframe', 'goog.structs.Pool', 'goog.style', 'goog.testing.MockClock', 'goog.testing.StrictMock', 'goog.testing.jsunit', 'goog.ui.IframeMask', 'goog.ui.Popup', 'goog.ui.PopupBase', 'goog.userAgent'], false); -goog.addDependency('ui/imagelessbuttonrenderer.js', ['goog.ui.ImagelessButtonRenderer'], ['goog.dom.classlist', 'goog.ui.Button', 'goog.ui.Component', 'goog.ui.CustomButtonRenderer', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.registry'], false); -goog.addDependency('ui/imagelessmenubuttonrenderer.js', ['goog.ui.ImagelessMenuButtonRenderer'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.MenuButton', 'goog.ui.MenuButtonRenderer', 'goog.ui.registry'], false); -goog.addDependency('ui/inputdatepicker.js', ['goog.ui.InputDatePicker'], ['goog.date.DateTime', 'goog.dom', 'goog.string', 'goog.ui.Component', 'goog.ui.DatePicker', 'goog.ui.PopupBase', 'goog.ui.PopupDatePicker'], false); -goog.addDependency('ui/inputdatepicker_test.js', ['goog.ui.InputDatePickerTest'], ['goog.dom', 'goog.i18n.DateTimeFormat', 'goog.i18n.DateTimeParse', 'goog.testing.jsunit', 'goog.ui.InputDatePicker'], false); -goog.addDependency('ui/itemevent.js', ['goog.ui.ItemEvent'], ['goog.events.Event'], false); -goog.addDependency('ui/keyboardshortcuthandler.js', ['goog.ui.KeyboardShortcutEvent', 'goog.ui.KeyboardShortcutHandler', 'goog.ui.KeyboardShortcutHandler.EventType'], ['goog.Timer', 'goog.array', 'goog.asserts', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyNames', 'goog.object', 'goog.userAgent'], false); -goog.addDependency('ui/keyboardshortcuthandler_test.js', ['goog.ui.KeyboardShortcutHandlerTest'], ['goog.dom', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.KeyCodes', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.StrictMock', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.KeyboardShortcutHandler', 'goog.userAgent'], false); -goog.addDependency('ui/labelinput.js', ['goog.ui.LabelInput'], ['goog.Timer', 'goog.a11y.aria', 'goog.a11y.aria.State', 'goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.ui.Component', 'goog.userAgent'], false); -goog.addDependency('ui/labelinput_test.js', ['goog.ui.LabelInputTest'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.classlist', 'goog.events.EventType', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.ui.LabelInput', 'goog.userAgent'], false); -goog.addDependency('ui/linkbuttonrenderer.js', ['goog.ui.LinkButtonRenderer'], ['goog.ui.Button', 'goog.ui.FlatButtonRenderer', 'goog.ui.registry'], false); -goog.addDependency('ui/media/flashobject.js', ['goog.ui.media.FlashObject', 'goog.ui.media.FlashObject.ScriptAccessLevel', 'goog.ui.media.FlashObject.Wmodes'], ['goog.asserts', 'goog.dom.safe', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.html.SafeUrl', 'goog.html.TrustedResourceUrl', 'goog.html.flash', 'goog.html.legacyconversions', 'goog.log', 'goog.object', 'goog.string', 'goog.structs.Map', 'goog.style', 'goog.ui.Component', 'goog.userAgent', 'goog.userAgent.flash'], false); -goog.addDependency('ui/media/flashobject_test.js', ['goog.ui.media.FlashObjectTest'], ['goog.dom', 'goog.dom.DomHelper', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.html.SafeUrl', 'goog.testing.MockControl', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.media.FlashObject', 'goog.userAgent'], false); -goog.addDependency('ui/media/flickr.js', ['goog.ui.media.FlickrSet', 'goog.ui.media.FlickrSetModel'], ['goog.html.TrustedResourceUrl', 'goog.string.Const', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.MediaModel', 'goog.ui.media.MediaRenderer'], false); -goog.addDependency('ui/media/flickr_test.js', ['goog.ui.media.FlickrSetTest'], ['goog.dom', 'goog.html.testing', 'goog.testing.jsunit', 'goog.ui.media.FlashObject', 'goog.ui.media.FlickrSet', 'goog.ui.media.FlickrSetModel', 'goog.ui.media.Media'], false); -goog.addDependency('ui/media/googlevideo.js', ['goog.ui.media.GoogleVideo', 'goog.ui.media.GoogleVideoModel'], ['goog.string', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.MediaModel', 'goog.ui.media.MediaRenderer'], false); -goog.addDependency('ui/media/googlevideo_test.js', ['goog.ui.media.GoogleVideoTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.ui.media.FlashObject', 'goog.ui.media.GoogleVideo', 'goog.ui.media.GoogleVideoModel', 'goog.ui.media.Media'], false); -goog.addDependency('ui/media/media.js', ['goog.ui.media.Media', 'goog.ui.media.MediaRenderer'], ['goog.asserts', 'goog.style', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.ControlRenderer'], false); -goog.addDependency('ui/media/media_test.js', ['goog.ui.media.MediaTest'], ['goog.dom', 'goog.math.Size', 'goog.testing.jsunit', 'goog.ui.ControlRenderer', 'goog.ui.media.Media', 'goog.ui.media.MediaModel', 'goog.ui.media.MediaRenderer'], false); -goog.addDependency('ui/media/mediamodel.js', ['goog.ui.media.MediaModel', 'goog.ui.media.MediaModel.Category', 'goog.ui.media.MediaModel.Credit', 'goog.ui.media.MediaModel.Credit.Role', 'goog.ui.media.MediaModel.Credit.Scheme', 'goog.ui.media.MediaModel.Medium', 'goog.ui.media.MediaModel.MimeType', 'goog.ui.media.MediaModel.Player', 'goog.ui.media.MediaModel.SubTitle', 'goog.ui.media.MediaModel.Thumbnail'], ['goog.array', 'goog.html.TrustedResourceUrl', 'goog.html.legacyconversions'], false); -goog.addDependency('ui/media/mediamodel_test.js', ['goog.ui.media.MediaModelTest'], ['goog.testing.jsunit', 'goog.ui.media.MediaModel'], false); -goog.addDependency('ui/media/mp3.js', ['goog.ui.media.Mp3'], ['goog.string', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.MediaRenderer'], false); -goog.addDependency('ui/media/mp3_test.js', ['goog.ui.media.Mp3Test'], ['goog.dom', 'goog.testing.jsunit', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.MediaModel', 'goog.ui.media.Mp3'], false); -goog.addDependency('ui/media/photo.js', ['goog.ui.media.Photo'], ['goog.ui.media.Media', 'goog.ui.media.MediaRenderer'], false); -goog.addDependency('ui/media/photo_test.js', ['goog.ui.media.PhotoTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.ui.media.MediaModel', 'goog.ui.media.Photo'], false); -goog.addDependency('ui/media/picasa.js', ['goog.ui.media.PicasaAlbum', 'goog.ui.media.PicasaAlbumModel'], ['goog.html.TrustedResourceUrl', 'goog.string.Const', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.MediaModel', 'goog.ui.media.MediaRenderer'], false); -goog.addDependency('ui/media/picasa_test.js', ['goog.ui.media.PicasaTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.PicasaAlbum', 'goog.ui.media.PicasaAlbumModel'], false); -goog.addDependency('ui/media/vimeo.js', ['goog.ui.media.Vimeo', 'goog.ui.media.VimeoModel'], ['goog.string', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.MediaModel', 'goog.ui.media.MediaRenderer'], false); -goog.addDependency('ui/media/vimeo_test.js', ['goog.ui.media.VimeoTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.Vimeo', 'goog.ui.media.VimeoModel'], false); -goog.addDependency('ui/media/youtube.js', ['goog.ui.media.Youtube', 'goog.ui.media.YoutubeModel'], ['goog.string', 'goog.ui.Component', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.MediaModel', 'goog.ui.media.MediaRenderer'], false); -goog.addDependency('ui/media/youtube_test.js', ['goog.ui.media.YoutubeTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.ui.media.FlashObject', 'goog.ui.media.Youtube', 'goog.ui.media.YoutubeModel'], false); -goog.addDependency('ui/menu.js', ['goog.ui.Menu', 'goog.ui.Menu.EventType'], ['goog.math.Coordinate', 'goog.string', 'goog.style', 'goog.ui.Component.EventType', 'goog.ui.Component.State', 'goog.ui.Container', 'goog.ui.Container.Orientation', 'goog.ui.MenuHeader', 'goog.ui.MenuItem', 'goog.ui.MenuRenderer', 'goog.ui.MenuSeparator'], false); -goog.addDependency('ui/menu_test.js', ['goog.ui.MenuTest'], ['goog.dom', 'goog.events', 'goog.math.Coordinate', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.Menu'], false); -goog.addDependency('ui/menubar.js', ['goog.ui.menuBar'], ['goog.ui.Container', 'goog.ui.MenuBarRenderer'], false); -goog.addDependency('ui/menubardecorator.js', ['goog.ui.menuBarDecorator'], ['goog.ui.MenuBarRenderer', 'goog.ui.menuBar', 'goog.ui.registry'], false); -goog.addDependency('ui/menubarrenderer.js', ['goog.ui.MenuBarRenderer'], ['goog.a11y.aria.Role', 'goog.ui.Container', 'goog.ui.ContainerRenderer'], false); -goog.addDependency('ui/menubase.js', ['goog.ui.MenuBase'], ['goog.events.EventHandler', 'goog.events.EventType', 'goog.events.KeyHandler', 'goog.ui.Popup'], false); -goog.addDependency('ui/menubutton.js', ['goog.ui.MenuButton'], ['goog.Timer', 'goog.a11y.aria', 'goog.a11y.aria.State', 'goog.asserts', 'goog.dom', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.math.Box', 'goog.math.Rect', 'goog.positioning', 'goog.positioning.Corner', 'goog.positioning.MenuAnchoredPosition', 'goog.positioning.Overflow', 'goog.style', 'goog.ui.Button', 'goog.ui.Component', 'goog.ui.IdGenerator', 'goog.ui.Menu', 'goog.ui.MenuButtonRenderer', 'goog.ui.MenuItem', 'goog.ui.MenuRenderer', 'goog.ui.registry', 'goog.userAgent', 'goog.userAgent.product'], false); -goog.addDependency('ui/menubutton_test.js', ['goog.ui.MenuButtonTest'], ['goog.Timer', 'goog.a11y.aria', 'goog.a11y.aria.State', 'goog.dom', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.positioning', 'goog.positioning.Corner', 'goog.positioning.MenuAnchoredPosition', 'goog.positioning.Overflow', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.Component', 'goog.ui.Menu', 'goog.ui.MenuButton', 'goog.ui.MenuItem', 'goog.ui.SubMenu', 'goog.userAgent', 'goog.userAgent.product', 'goog.userAgent.product.isVersion'], false); -goog.addDependency('ui/menubuttonrenderer.js', ['goog.ui.MenuButtonRenderer'], ['goog.dom', 'goog.style', 'goog.ui.CustomButtonRenderer', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.Menu', 'goog.ui.MenuRenderer'], false); -goog.addDependency('ui/menubuttonrenderer_test.js', ['goog.ui.MenuButtonRendererTest'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.classlist', 'goog.testing.jsunit', 'goog.testing.ui.rendererasserts', 'goog.ui.MenuButton', 'goog.ui.MenuButtonRenderer', 'goog.userAgent'], false); -goog.addDependency('ui/menuheader.js', ['goog.ui.MenuHeader'], ['goog.ui.Component', 'goog.ui.Control', 'goog.ui.MenuHeaderRenderer', 'goog.ui.registry'], false); -goog.addDependency('ui/menuheaderrenderer.js', ['goog.ui.MenuHeaderRenderer'], ['goog.ui.ControlRenderer'], false); -goog.addDependency('ui/menuitem.js', ['goog.ui.MenuItem'], ['goog.a11y.aria.Role', 'goog.array', 'goog.dom', 'goog.dom.classlist', 'goog.math.Coordinate', 'goog.string', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.MenuItemRenderer', 'goog.ui.registry'], false); -goog.addDependency('ui/menuitem_test.js', ['goog.ui.MenuItemTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.classlist', 'goog.events.KeyCodes', 'goog.math.Coordinate', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.Component', 'goog.ui.MenuItem', 'goog.ui.MenuItemRenderer'], false); -goog.addDependency('ui/menuitemrenderer.js', ['goog.ui.MenuItemRenderer'], ['goog.a11y.aria.Role', 'goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.ui.Component', 'goog.ui.ControlRenderer'], false); -goog.addDependency('ui/menuitemrenderer_test.js', ['goog.ui.MenuItemRendererTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.classlist', 'goog.testing.jsunit', 'goog.testing.ui.rendererasserts', 'goog.ui.Component', 'goog.ui.MenuItem', 'goog.ui.MenuItemRenderer'], false); -goog.addDependency('ui/menurenderer.js', ['goog.ui.MenuRenderer'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.asserts', 'goog.dom', 'goog.ui.ContainerRenderer', 'goog.ui.Separator'], false); -goog.addDependency('ui/menuseparator.js', ['goog.ui.MenuSeparator'], ['goog.ui.MenuSeparatorRenderer', 'goog.ui.Separator', 'goog.ui.registry'], false); -goog.addDependency('ui/menuseparatorrenderer.js', ['goog.ui.MenuSeparatorRenderer'], ['goog.dom', 'goog.dom.classlist', 'goog.ui.ControlRenderer'], false); -goog.addDependency('ui/menuseparatorrenderer_test.js', ['goog.ui.MenuSeparatorRendererTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.ui.MenuSeparator', 'goog.ui.MenuSeparatorRenderer'], false); -goog.addDependency('ui/mockactivitymonitor.js', ['goog.ui.MockActivityMonitor'], ['goog.events.EventType', 'goog.ui.ActivityMonitor'], false); -goog.addDependency('ui/mockactivitymonitor_test.js', ['goog.ui.MockActivityMonitorTest'], ['goog.events', 'goog.functions', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.ActivityMonitor', 'goog.ui.MockActivityMonitor'], false); -goog.addDependency('ui/modalpopup.js', ['goog.ui.ModalPopup'], ['goog.Timer', 'goog.a11y.aria', 'goog.a11y.aria.State', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.dom.iframe', 'goog.events', 'goog.events.EventType', 'goog.events.FocusHandler', 'goog.fx.Transition', 'goog.string', 'goog.style', 'goog.ui.Component', 'goog.ui.PopupBase', 'goog.userAgent'], false); -goog.addDependency('ui/modalpopup_test.js', ['goog.ui.ModalPopupTest'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.dispose', 'goog.dom', 'goog.events', 'goog.events.EventTarget', 'goog.fx.Transition', 'goog.fx.css3', 'goog.string', 'goog.style', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.ui.ModalPopup', 'goog.ui.PopupBase'], false); -goog.addDependency('ui/nativebuttonrenderer.js', ['goog.ui.NativeButtonRenderer'], ['goog.asserts', 'goog.dom.classlist', 'goog.events.EventType', 'goog.ui.ButtonRenderer', 'goog.ui.Component'], false); -goog.addDependency('ui/nativebuttonrenderer_test.js', ['goog.ui.NativeButtonRendererTest'], ['goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.testing.ExpectedFailures', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.ui.rendererasserts', 'goog.ui.Button', 'goog.ui.Component', 'goog.ui.NativeButtonRenderer', 'goog.userAgent'], false); -goog.addDependency('ui/option.js', ['goog.ui.Option'], ['goog.ui.Component', 'goog.ui.MenuItem', 'goog.ui.registry'], false); -goog.addDependency('ui/palette.js', ['goog.ui.Palette'], ['goog.array', 'goog.dom', 'goog.events', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.math.Size', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.PaletteRenderer', 'goog.ui.SelectionModel'], false); -goog.addDependency('ui/palette_test.js', ['goog.ui.PaletteTest'], ['goog.a11y.aria', 'goog.dom', 'goog.events', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyEvent', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.Component', 'goog.ui.Container', 'goog.ui.Palette'], false); -goog.addDependency('ui/paletterenderer.js', ['goog.ui.PaletteRenderer'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.NodeIterator', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.iter', 'goog.style', 'goog.ui.ControlRenderer', 'goog.userAgent'], false); -goog.addDependency('ui/paletterenderer_test.js', ['goog.ui.PaletteRendererTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.array', 'goog.dom', 'goog.testing.jsunit', 'goog.ui.Palette', 'goog.ui.PaletteRenderer'], false); -goog.addDependency('ui/plaintextspellchecker.js', ['goog.ui.PlainTextSpellChecker'], ['goog.Timer', 'goog.a11y.aria', 'goog.asserts', 'goog.dom', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.spell.SpellCheck', 'goog.style', 'goog.ui.AbstractSpellChecker', 'goog.ui.Component', 'goog.userAgent'], false); -goog.addDependency('ui/plaintextspellchecker_test.js', ['goog.ui.PlainTextSpellCheckerTest'], ['goog.Timer', 'goog.dom', 'goog.events.KeyCodes', 'goog.spell.SpellCheck', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.PlainTextSpellChecker'], false); -goog.addDependency('ui/popup.js', ['goog.ui.Popup', 'goog.ui.Popup.AbsolutePosition', 'goog.ui.Popup.AnchoredPosition', 'goog.ui.Popup.AnchoredViewPortPosition', 'goog.ui.Popup.ClientPosition', 'goog.ui.Popup.Overflow', 'goog.ui.Popup.ViewPortClientPosition', 'goog.ui.Popup.ViewPortPosition'], ['goog.math.Box', 'goog.positioning.AbsolutePosition', 'goog.positioning.AnchoredPosition', 'goog.positioning.AnchoredViewportPosition', 'goog.positioning.ClientPosition', 'goog.positioning.Corner', 'goog.positioning.Overflow', 'goog.positioning.ViewportClientPosition', 'goog.positioning.ViewportPosition', 'goog.style', 'goog.ui.PopupBase'], false); -goog.addDependency('ui/popup_test.js', ['goog.ui.PopupTest'], ['goog.positioning.AnchoredPosition', 'goog.positioning.Corner', 'goog.style', 'goog.testing.jsunit', 'goog.ui.Popup', 'goog.userAgent'], false); -goog.addDependency('ui/popupbase.js', ['goog.ui.PopupBase', 'goog.ui.PopupBase.EventType', 'goog.ui.PopupBase.Type'], ['goog.Timer', 'goog.array', 'goog.dom', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.fx.Transition', 'goog.style', 'goog.userAgent'], false); -goog.addDependency('ui/popupbase_test.js', ['goog.ui.PopupBaseTest'], ['goog.dom', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.fx.Transition', 'goog.fx.css3', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.ui.PopupBase'], false); -goog.addDependency('ui/popupcolorpicker.js', ['goog.ui.PopupColorPicker'], ['goog.asserts', 'goog.dom.classlist', 'goog.events.EventType', 'goog.positioning.AnchoredPosition', 'goog.positioning.Corner', 'goog.ui.ColorPicker', 'goog.ui.Component', 'goog.ui.Popup'], false); -goog.addDependency('ui/popupcolorpicker_test.js', ['goog.ui.PopupColorPickerTest'], ['goog.dom', 'goog.events', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.ColorPicker', 'goog.ui.PopupColorPicker'], false); -goog.addDependency('ui/popupdatepicker.js', ['goog.ui.PopupDatePicker'], ['goog.events.EventType', 'goog.positioning.AnchoredPosition', 'goog.positioning.Corner', 'goog.positioning.Overflow', 'goog.style', 'goog.ui.Component', 'goog.ui.DatePicker', 'goog.ui.Popup', 'goog.ui.PopupBase'], false); -goog.addDependency('ui/popupdatepicker_test.js', ['goog.ui.PopupDatePickerTest'], ['goog.events', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.PopupBase', 'goog.ui.PopupDatePicker'], false); -goog.addDependency('ui/popupmenu.js', ['goog.ui.PopupMenu'], ['goog.events.EventType', 'goog.positioning.AnchoredViewportPosition', 'goog.positioning.Corner', 'goog.positioning.MenuAnchoredPosition', 'goog.positioning.Overflow', 'goog.positioning.ViewportClientPosition', 'goog.structs.Map', 'goog.style', 'goog.ui.Component', 'goog.ui.Menu', 'goog.ui.PopupBase', 'goog.userAgent'], false); -goog.addDependency('ui/popupmenu_test.js', ['goog.ui.PopupMenuTest'], ['goog.dom', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.math.Box', 'goog.math.Coordinate', 'goog.positioning.Corner', 'goog.style', 'goog.testing.jsunit', 'goog.ui.Menu', 'goog.ui.MenuItem', 'goog.ui.PopupMenu'], false); -goog.addDependency('ui/progressbar.js', ['goog.ui.ProgressBar', 'goog.ui.ProgressBar.Orientation'], ['goog.a11y.aria', 'goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.events.EventType', 'goog.ui.Component', 'goog.ui.RangeModel', 'goog.userAgent'], false); -goog.addDependency('ui/prompt.js', ['goog.ui.Prompt'], ['goog.Timer', 'goog.dom', 'goog.events', 'goog.events.EventType', 'goog.functions', 'goog.html.SafeHtml', 'goog.html.legacyconversions', 'goog.ui.Component', 'goog.ui.Dialog', 'goog.userAgent'], false); -goog.addDependency('ui/prompt_test.js', ['goog.ui.PromptTest'], ['goog.dom.selection', 'goog.events.InputHandler', 'goog.events.KeyCodes', 'goog.functions', 'goog.string', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.BidiInput', 'goog.ui.Dialog', 'goog.ui.Prompt', 'goog.userAgent', 'goog.userAgent.product'], false); -goog.addDependency('ui/rangemodel.js', ['goog.ui.RangeModel'], ['goog.events.EventTarget', 'goog.ui.Component'], false); -goog.addDependency('ui/rangemodel_test.js', ['goog.ui.RangeModelTest'], ['goog.testing.jsunit', 'goog.ui.RangeModel'], false); -goog.addDependency('ui/ratings.js', ['goog.ui.Ratings', 'goog.ui.Ratings.EventType'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.asserts', 'goog.dom.classlist', 'goog.events.EventType', 'goog.ui.Component'], false); -goog.addDependency('ui/registry.js', ['goog.ui.registry'], ['goog.asserts', 'goog.dom.classlist'], false); -goog.addDependency('ui/registry_test.js', ['goog.ui.registryTest'], ['goog.object', 'goog.testing.jsunit', 'goog.ui.registry'], false); -goog.addDependency('ui/richtextspellchecker.js', ['goog.ui.RichTextSpellChecker'], ['goog.Timer', 'goog.asserts', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.math.Coordinate', 'goog.spell.SpellCheck', 'goog.string.StringBuffer', 'goog.style', 'goog.ui.AbstractSpellChecker', 'goog.ui.Component', 'goog.ui.PopupMenu'], false); -goog.addDependency('ui/richtextspellchecker_test.js', ['goog.ui.RichTextSpellCheckerTest'], ['goog.dom.Range', 'goog.dom.classlist', 'goog.events.KeyCodes', 'goog.object', 'goog.spell.SpellCheck', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.RichTextSpellChecker'], false); -goog.addDependency('ui/roundedpanel.js', ['goog.ui.BaseRoundedPanel', 'goog.ui.CssRoundedPanel', 'goog.ui.GraphicsRoundedPanel', 'goog.ui.RoundedPanel', 'goog.ui.RoundedPanel.Corner'], ['goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.graphics', 'goog.graphics.Path', 'goog.graphics.SolidFill', 'goog.graphics.Stroke', 'goog.math', 'goog.math.Coordinate', 'goog.style', 'goog.ui.Component', 'goog.userAgent'], false); -goog.addDependency('ui/roundedpanel_test.js', ['goog.ui.RoundedPanelTest'], ['goog.testing.jsunit', 'goog.ui.CssRoundedPanel', 'goog.ui.GraphicsRoundedPanel', 'goog.ui.RoundedPanel', 'goog.userAgent'], false); -goog.addDependency('ui/roundedtabrenderer.js', ['goog.ui.RoundedTabRenderer'], ['goog.dom', 'goog.ui.Tab', 'goog.ui.TabBar', 'goog.ui.TabRenderer', 'goog.ui.registry'], false); -goog.addDependency('ui/scrollfloater.js', ['goog.ui.ScrollFloater', 'goog.ui.ScrollFloater.EventType'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.events.EventType', 'goog.style', 'goog.ui.Component', 'goog.userAgent'], false); -goog.addDependency('ui/scrollfloater_test.js', ['goog.ui.ScrollFloaterTest'], ['goog.dom', 'goog.events', 'goog.style', 'goog.testing.jsunit', 'goog.ui.ScrollFloater'], false); -goog.addDependency('ui/select.js', ['goog.ui.Select'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.array', 'goog.events.EventType', 'goog.ui.Component', 'goog.ui.IdGenerator', 'goog.ui.MenuButton', 'goog.ui.MenuItem', 'goog.ui.MenuRenderer', 'goog.ui.SelectionModel', 'goog.ui.registry'], false); -goog.addDependency('ui/select_test.js', ['goog.ui.SelectTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.dom', 'goog.events', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.Component', 'goog.ui.CustomButtonRenderer', 'goog.ui.Menu', 'goog.ui.MenuItem', 'goog.ui.Select', 'goog.ui.Separator'], false); -goog.addDependency('ui/selectionmenubutton.js', ['goog.ui.SelectionMenuButton', 'goog.ui.SelectionMenuButton.SelectionState'], ['goog.events.EventType', 'goog.style', 'goog.ui.Component', 'goog.ui.MenuButton', 'goog.ui.MenuItem', 'goog.ui.registry'], false); -goog.addDependency('ui/selectionmenubutton_test.js', ['goog.ui.SelectionMenuButtonTest'], ['goog.dom', 'goog.events', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.SelectionMenuButton'], false); -goog.addDependency('ui/selectionmodel.js', ['goog.ui.SelectionModel'], ['goog.array', 'goog.events.EventTarget', 'goog.events.EventType'], false); -goog.addDependency('ui/selectionmodel_test.js', ['goog.ui.SelectionModelTest'], ['goog.array', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.SelectionModel'], false); -goog.addDependency('ui/separator.js', ['goog.ui.Separator'], ['goog.a11y.aria', 'goog.asserts', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.MenuSeparatorRenderer', 'goog.ui.registry'], false); -goog.addDependency('ui/serverchart.js', ['goog.ui.ServerChart', 'goog.ui.ServerChart.AxisDisplayType', 'goog.ui.ServerChart.ChartType', 'goog.ui.ServerChart.EncodingType', 'goog.ui.ServerChart.Event', 'goog.ui.ServerChart.LegendPosition', 'goog.ui.ServerChart.MaximumValue', 'goog.ui.ServerChart.MultiAxisAlignment', 'goog.ui.ServerChart.MultiAxisType', 'goog.ui.ServerChart.UriParam', 'goog.ui.ServerChart.UriTooLongEvent'], ['goog.Uri', 'goog.array', 'goog.asserts', 'goog.events.Event', 'goog.string', 'goog.ui.Component'], false); -goog.addDependency('ui/serverchart_test.js', ['goog.ui.ServerChartTest'], ['goog.Uri', 'goog.events', 'goog.testing.jsunit', 'goog.ui.ServerChart'], false); -goog.addDependency('ui/slider.js', ['goog.ui.Slider', 'goog.ui.Slider.Orientation'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.dom', 'goog.ui.SliderBase'], false); -goog.addDependency('ui/sliderbase.js', ['goog.ui.SliderBase', 'goog.ui.SliderBase.AnimationFactory', 'goog.ui.SliderBase.Orientation'], ['goog.Timer', 'goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.events.MouseWheelHandler', 'goog.functions', 'goog.fx.AnimationParallelQueue', 'goog.fx.Dragger', 'goog.fx.Transition', 'goog.fx.dom.ResizeHeight', 'goog.fx.dom.ResizeWidth', 'goog.fx.dom.Slide', 'goog.math', 'goog.math.Coordinate', 'goog.style', 'goog.style.bidi', 'goog.ui.Component', 'goog.ui.RangeModel'], false); -goog.addDependency('ui/sliderbase_test.js', ['goog.ui.SliderBaseTest'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.fx.Animation', 'goog.math.Coordinate', 'goog.style', 'goog.style.bidi', 'goog.testing.MockClock', 'goog.testing.MockControl', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.mockmatchers', 'goog.testing.recordFunction', 'goog.ui.Component', 'goog.ui.SliderBase', 'goog.userAgent'], false); -goog.addDependency('ui/splitbehavior.js', ['goog.ui.SplitBehavior', 'goog.ui.SplitBehavior.DefaultHandlers'], ['goog.Disposable', 'goog.asserts', 'goog.dispose', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.classlist', 'goog.events.EventHandler', 'goog.ui.ButtonSide', 'goog.ui.Component', 'goog.ui.decorate', 'goog.ui.registry'], false); -goog.addDependency('ui/splitbehavior_test.js', ['goog.ui.SplitBehaviorTest'], ['goog.array', 'goog.dom', 'goog.events', 'goog.events.Event', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.CustomButton', 'goog.ui.Menu', 'goog.ui.MenuButton', 'goog.ui.MenuItem', 'goog.ui.SplitBehavior', 'goog.ui.decorate'], false); -goog.addDependency('ui/splitpane.js', ['goog.ui.SplitPane', 'goog.ui.SplitPane.Orientation'], ['goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.events.EventType', 'goog.fx.Dragger', 'goog.math.Rect', 'goog.math.Size', 'goog.style', 'goog.ui.Component', 'goog.userAgent'], false); -goog.addDependency('ui/splitpane_test.js', ['goog.ui.SplitPaneTest'], ['goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.math.Size', 'goog.style', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.Component', 'goog.ui.SplitPane'], false); -goog.addDependency('ui/style/app/buttonrenderer.js', ['goog.ui.style.app.ButtonRenderer'], ['goog.dom.classlist', 'goog.ui.Button', 'goog.ui.CustomButtonRenderer', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.registry'], false); -goog.addDependency('ui/style/app/buttonrenderer_test.js', ['goog.ui.style.app.ButtonRendererTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.testing.ui.style', 'goog.ui.Button', 'goog.ui.Component', 'goog.ui.style.app.ButtonRenderer', 'goog.userAgent'], false); -goog.addDependency('ui/style/app/menubuttonrenderer.js', ['goog.ui.style.app.MenuButtonRenderer'], ['goog.a11y.aria.Role', 'goog.array', 'goog.dom', 'goog.style', 'goog.ui.Menu', 'goog.ui.MenuRenderer', 'goog.ui.style.app.ButtonRenderer'], false); -goog.addDependency('ui/style/app/menubuttonrenderer_test.js', ['goog.ui.style.app.MenuButtonRendererTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.testing.ui.style', 'goog.ui.Component', 'goog.ui.MenuButton', 'goog.ui.style.app.MenuButtonRenderer'], false); -goog.addDependency('ui/style/app/primaryactionbuttonrenderer.js', ['goog.ui.style.app.PrimaryActionButtonRenderer'], ['goog.ui.Button', 'goog.ui.registry', 'goog.ui.style.app.ButtonRenderer'], false); -goog.addDependency('ui/style/app/primaryactionbuttonrenderer_test.js', ['goog.ui.style.app.PrimaryActionButtonRendererTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.testing.ui.style', 'goog.ui.Button', 'goog.ui.Component', 'goog.ui.style.app.PrimaryActionButtonRenderer'], false); -goog.addDependency('ui/submenu.js', ['goog.ui.SubMenu'], ['goog.Timer', 'goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.events.KeyCodes', 'goog.positioning.AnchoredViewportPosition', 'goog.positioning.Corner', 'goog.style', 'goog.ui.Component', 'goog.ui.Menu', 'goog.ui.MenuItem', 'goog.ui.SubMenuRenderer', 'goog.ui.registry'], false); -goog.addDependency('ui/submenu_test.js', ['goog.ui.SubMenuTest'], ['goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.events.Event', 'goog.events.KeyCodes', 'goog.functions', 'goog.positioning', 'goog.positioning.Overflow', 'goog.style', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.Menu', 'goog.ui.MenuItem', 'goog.ui.SubMenu', 'goog.ui.SubMenuRenderer'], false); -goog.addDependency('ui/submenurenderer.js', ['goog.ui.SubMenuRenderer'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.style', 'goog.ui.Menu', 'goog.ui.MenuItemRenderer'], false); -goog.addDependency('ui/tab.js', ['goog.ui.Tab'], ['goog.ui.Component', 'goog.ui.Control', 'goog.ui.TabRenderer', 'goog.ui.registry'], false); -goog.addDependency('ui/tab_test.js', ['goog.ui.TabTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.Tab', 'goog.ui.TabRenderer'], false); -goog.addDependency('ui/tabbar.js', ['goog.ui.TabBar', 'goog.ui.TabBar.Location'], ['goog.ui.Component.EventType', 'goog.ui.Container', 'goog.ui.Container.Orientation', 'goog.ui.Tab', 'goog.ui.TabBarRenderer', 'goog.ui.registry'], false); -goog.addDependency('ui/tabbar_test.js', ['goog.ui.TabBarTest'], ['goog.dom', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.Container', 'goog.ui.Tab', 'goog.ui.TabBar', 'goog.ui.TabBarRenderer'], false); -goog.addDependency('ui/tabbarrenderer.js', ['goog.ui.TabBarRenderer'], ['goog.a11y.aria.Role', 'goog.object', 'goog.ui.ContainerRenderer'], false); -goog.addDependency('ui/tabbarrenderer_test.js', ['goog.ui.TabBarRendererTest'], ['goog.a11y.aria.Role', 'goog.dom', 'goog.dom.classlist', 'goog.testing.jsunit', 'goog.testing.ui.rendererasserts', 'goog.ui.Container', 'goog.ui.TabBar', 'goog.ui.TabBarRenderer'], false); -goog.addDependency('ui/tablesorter.js', ['goog.ui.TableSorter', 'goog.ui.TableSorter.EventType'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.EventType', 'goog.functions', 'goog.ui.Component'], false); -goog.addDependency('ui/tablesorter_test.js', ['goog.ui.TableSorterTest'], ['goog.array', 'goog.dom', 'goog.dom.classlist', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.TableSorter'], false); -goog.addDependency('ui/tabpane.js', ['goog.ui.TabPane', 'goog.ui.TabPane.Events', 'goog.ui.TabPane.TabLocation', 'goog.ui.TabPane.TabPage', 'goog.ui.TabPaneEvent'], ['goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.style'], false); -goog.addDependency('ui/tabpane_test.js', ['goog.ui.TabPaneTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.ui.TabPane'], false); -goog.addDependency('ui/tabrenderer.js', ['goog.ui.TabRenderer'], ['goog.a11y.aria.Role', 'goog.ui.Component', 'goog.ui.ControlRenderer'], false); -goog.addDependency('ui/tabrenderer_test.js', ['goog.ui.TabRendererTest'], ['goog.a11y.aria.Role', 'goog.dom', 'goog.dom.classlist', 'goog.testing.dom', 'goog.testing.jsunit', 'goog.testing.ui.rendererasserts', 'goog.ui.Tab', 'goog.ui.TabRenderer'], false); -goog.addDependency('ui/textarea.js', ['goog.ui.Textarea', 'goog.ui.Textarea.EventType'], ['goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.events.EventType', 'goog.style', 'goog.ui.Control', 'goog.ui.TextareaRenderer', 'goog.userAgent'], false); -goog.addDependency('ui/textarea_test.js', ['goog.ui.TextareaTest'], ['goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.events.EventObserver', 'goog.testing.jsunit', 'goog.ui.Textarea', 'goog.ui.TextareaRenderer', 'goog.userAgent', 'goog.userAgent.product'], false); -goog.addDependency('ui/textarearenderer.js', ['goog.ui.TextareaRenderer'], ['goog.dom.TagName', 'goog.ui.Component', 'goog.ui.ControlRenderer'], false); -goog.addDependency('ui/togglebutton.js', ['goog.ui.ToggleButton'], ['goog.ui.Button', 'goog.ui.Component', 'goog.ui.CustomButtonRenderer', 'goog.ui.registry'], false); -goog.addDependency('ui/toolbar.js', ['goog.ui.Toolbar'], ['goog.ui.Container', 'goog.ui.ToolbarRenderer'], false); -goog.addDependency('ui/toolbar_test.js', ['goog.ui.ToolbarTest'], ['goog.a11y.aria', 'goog.dom', 'goog.events.EventType', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.ui.Toolbar', 'goog.ui.ToolbarMenuButton'], false); -goog.addDependency('ui/toolbarbutton.js', ['goog.ui.ToolbarButton'], ['goog.ui.Button', 'goog.ui.ToolbarButtonRenderer', 'goog.ui.registry'], false); -goog.addDependency('ui/toolbarbuttonrenderer.js', ['goog.ui.ToolbarButtonRenderer'], ['goog.ui.CustomButtonRenderer'], false); -goog.addDependency('ui/toolbarcolormenubutton.js', ['goog.ui.ToolbarColorMenuButton'], ['goog.ui.ColorMenuButton', 'goog.ui.ToolbarColorMenuButtonRenderer', 'goog.ui.registry'], false); -goog.addDependency('ui/toolbarcolormenubuttonrenderer.js', ['goog.ui.ToolbarColorMenuButtonRenderer'], ['goog.asserts', 'goog.dom.classlist', 'goog.ui.ColorMenuButtonRenderer', 'goog.ui.MenuButtonRenderer', 'goog.ui.ToolbarMenuButtonRenderer'], false); -goog.addDependency('ui/toolbarcolormenubuttonrenderer_test.js', ['goog.ui.ToolbarColorMenuButtonRendererTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.testing.ui.RendererHarness', 'goog.testing.ui.rendererasserts', 'goog.ui.ToolbarColorMenuButton', 'goog.ui.ToolbarColorMenuButtonRenderer'], false); -goog.addDependency('ui/toolbarmenubutton.js', ['goog.ui.ToolbarMenuButton'], ['goog.ui.MenuButton', 'goog.ui.ToolbarMenuButtonRenderer', 'goog.ui.registry'], false); -goog.addDependency('ui/toolbarmenubuttonrenderer.js', ['goog.ui.ToolbarMenuButtonRenderer'], ['goog.ui.MenuButtonRenderer'], false); -goog.addDependency('ui/toolbarrenderer.js', ['goog.ui.ToolbarRenderer'], ['goog.a11y.aria.Role', 'goog.ui.Container', 'goog.ui.ContainerRenderer', 'goog.ui.Separator', 'goog.ui.ToolbarSeparatorRenderer'], false); -goog.addDependency('ui/toolbarselect.js', ['goog.ui.ToolbarSelect'], ['goog.ui.Select', 'goog.ui.ToolbarMenuButtonRenderer', 'goog.ui.registry'], false); -goog.addDependency('ui/toolbarseparator.js', ['goog.ui.ToolbarSeparator'], ['goog.ui.Separator', 'goog.ui.ToolbarSeparatorRenderer', 'goog.ui.registry'], false); -goog.addDependency('ui/toolbarseparatorrenderer.js', ['goog.ui.ToolbarSeparatorRenderer'], ['goog.asserts', 'goog.dom.classlist', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.MenuSeparatorRenderer'], false); -goog.addDependency('ui/toolbarseparatorrenderer_test.js', ['goog.ui.ToolbarSeparatorRendererTest'], ['goog.dom', 'goog.dom.classlist', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.ToolbarSeparator', 'goog.ui.ToolbarSeparatorRenderer'], false); -goog.addDependency('ui/toolbartogglebutton.js', ['goog.ui.ToolbarToggleButton'], ['goog.ui.ToggleButton', 'goog.ui.ToolbarButtonRenderer', 'goog.ui.registry'], false); -goog.addDependency('ui/tooltip.js', ['goog.ui.Tooltip', 'goog.ui.Tooltip.CursorTooltipPosition', 'goog.ui.Tooltip.ElementTooltipPosition', 'goog.ui.Tooltip.State'], ['goog.Timer', 'goog.array', 'goog.dom', 'goog.dom.safe', 'goog.events', 'goog.events.EventType', 'goog.html.legacyconversions', 'goog.math.Box', 'goog.math.Coordinate', 'goog.positioning', 'goog.positioning.AnchoredPosition', 'goog.positioning.Corner', 'goog.positioning.Overflow', 'goog.positioning.OverflowStatus', 'goog.positioning.ViewportPosition', 'goog.structs.Set', 'goog.style', 'goog.ui.Popup', 'goog.ui.PopupBase'], false); -goog.addDependency('ui/tooltip_test.js', ['goog.ui.TooltipTest'], ['goog.dom', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.html.testing', 'goog.math.Coordinate', 'goog.positioning.AbsolutePosition', 'goog.style', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.TestQueue', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.PopupBase', 'goog.ui.Tooltip', 'goog.userAgent'], false); -goog.addDependency('ui/tree/basenode.js', ['goog.ui.tree.BaseNode', 'goog.ui.tree.BaseNode.EventType'], ['goog.Timer', 'goog.a11y.aria', 'goog.asserts', 'goog.dom.safe', 'goog.events.Event', 'goog.events.KeyCodes', 'goog.html.SafeHtml', 'goog.html.SafeStyle', 'goog.html.legacyconversions', 'goog.string', 'goog.string.StringBuffer', 'goog.style', 'goog.ui.Component'], false); -goog.addDependency('ui/tree/basenode_test.js', ['goog.ui.tree.BaseNodeTest'], ['goog.dom', 'goog.dom.classlist', 'goog.html.legacyconversions', 'goog.html.testing', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.tree.BaseNode', 'goog.ui.tree.TreeControl', 'goog.ui.tree.TreeNode'], false); -goog.addDependency('ui/tree/treecontrol.js', ['goog.ui.tree.TreeControl'], ['goog.a11y.aria', 'goog.asserts', 'goog.dom.classlist', 'goog.events.EventType', 'goog.events.FocusHandler', 'goog.events.KeyHandler', 'goog.html.SafeHtml', 'goog.log', 'goog.ui.tree.BaseNode', 'goog.ui.tree.TreeNode', 'goog.ui.tree.TypeAhead', 'goog.userAgent'], false); -goog.addDependency('ui/tree/treecontrol_test.js', ['goog.ui.tree.TreeControlTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.ui.tree.TreeControl'], false); -goog.addDependency('ui/tree/treenode.js', ['goog.ui.tree.TreeNode'], ['goog.ui.tree.BaseNode'], false); -goog.addDependency('ui/tree/typeahead.js', ['goog.ui.tree.TypeAhead', 'goog.ui.tree.TypeAhead.Offset'], ['goog.array', 'goog.events.KeyCodes', 'goog.string', 'goog.structs.Trie'], false); -goog.addDependency('ui/tree/typeahead_test.js', ['goog.ui.tree.TypeAheadTest'], ['goog.dom', 'goog.events.KeyCodes', 'goog.testing.jsunit', 'goog.ui.tree.TreeControl', 'goog.ui.tree.TypeAhead'], false); -goog.addDependency('ui/tristatemenuitem.js', ['goog.ui.TriStateMenuItem', 'goog.ui.TriStateMenuItem.State'], ['goog.dom.classlist', 'goog.ui.Component', 'goog.ui.MenuItem', 'goog.ui.TriStateMenuItemRenderer', 'goog.ui.registry'], false); -goog.addDependency('ui/tristatemenuitemrenderer.js', ['goog.ui.TriStateMenuItemRenderer'], ['goog.asserts', 'goog.dom.classlist', 'goog.ui.MenuItemRenderer'], false); -goog.addDependency('ui/twothumbslider.js', ['goog.ui.TwoThumbSlider'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.dom', 'goog.ui.SliderBase'], false); -goog.addDependency('ui/twothumbslider_test.js', ['goog.ui.TwoThumbSliderTest'], ['goog.testing.jsunit', 'goog.ui.SliderBase', 'goog.ui.TwoThumbSlider'], false); -goog.addDependency('ui/zippy.js', ['goog.ui.Zippy', 'goog.ui.Zippy.Events', 'goog.ui.ZippyEvent'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.classlist', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.style'], false); -goog.addDependency('ui/zippy_test.js', ['goog.ui.ZippyTest'], ['goog.a11y.aria', 'goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.object', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Zippy'], false); -goog.addDependency('uri/uri.js', ['goog.Uri', 'goog.Uri.QueryData'], ['goog.array', 'goog.string', 'goog.structs', 'goog.structs.Map', 'goog.uri.utils', 'goog.uri.utils.ComponentIndex', 'goog.uri.utils.StandardQueryParam'], false); -goog.addDependency('uri/uri_test.js', ['goog.UriTest'], ['goog.Uri', 'goog.testing.jsunit'], false); -goog.addDependency('uri/utils.js', ['goog.uri.utils', 'goog.uri.utils.ComponentIndex', 'goog.uri.utils.QueryArray', 'goog.uri.utils.QueryValue', 'goog.uri.utils.StandardQueryParam'], ['goog.asserts', 'goog.string', 'goog.userAgent'], false); -goog.addDependency('uri/utils_test.js', ['goog.uri.utilsTest'], ['goog.functions', 'goog.string', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.uri.utils'], false); -goog.addDependency('useragent/adobereader.js', ['goog.userAgent.adobeReader'], ['goog.string', 'goog.userAgent'], false); -goog.addDependency('useragent/adobereader_test.js', ['goog.userAgent.adobeReaderTest'], ['goog.testing.jsunit', 'goog.userAgent.adobeReader'], false); -goog.addDependency('useragent/flash.js', ['goog.userAgent.flash'], ['goog.string'], false); -goog.addDependency('useragent/flash_test.js', ['goog.userAgent.flashTest'], ['goog.testing.jsunit', 'goog.userAgent.flash'], false); -goog.addDependency('useragent/iphoto.js', ['goog.userAgent.iphoto'], ['goog.string', 'goog.userAgent'], false); -goog.addDependency('useragent/jscript.js', ['goog.userAgent.jscript'], ['goog.string'], false); -goog.addDependency('useragent/jscript_test.js', ['goog.userAgent.jscriptTest'], ['goog.testing.jsunit', 'goog.userAgent.jscript'], false); -goog.addDependency('useragent/keyboard.js', ['goog.userAgent.keyboard'], ['goog.labs.userAgent.platform'], false); -goog.addDependency('useragent/keyboard_test.js', ['goog.userAgent.keyboardTest'], ['goog.labs.userAgent.testAgents', 'goog.labs.userAgent.util', 'goog.testing.MockUserAgent', 'goog.testing.jsunit', 'goog.userAgent.keyboard', 'goog.userAgentTestUtil'], false); -goog.addDependency('useragent/platform.js', ['goog.userAgent.platform'], ['goog.string', 'goog.userAgent'], false); -goog.addDependency('useragent/platform_test.js', ['goog.userAgent.platformTest'], ['goog.testing.MockUserAgent', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.platform', 'goog.userAgentTestUtil'], false); -goog.addDependency('useragent/product.js', ['goog.userAgent.product'], ['goog.labs.userAgent.browser', 'goog.labs.userAgent.platform', 'goog.userAgent'], false); -goog.addDependency('useragent/product_isversion.js', ['goog.userAgent.product.isVersion'], ['goog.labs.userAgent.platform', 'goog.string', 'goog.userAgent', 'goog.userAgent.product'], false); -goog.addDependency('useragent/product_test.js', ['goog.userAgent.productTest'], ['goog.array', 'goog.labs.userAgent.testAgents', 'goog.labs.userAgent.util', 'goog.testing.MockUserAgent', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.product', 'goog.userAgent.product.isVersion', 'goog.userAgentTestUtil'], false); -goog.addDependency('useragent/useragent.js', ['goog.userAgent'], ['goog.labs.userAgent.browser', 'goog.labs.userAgent.engine', 'goog.labs.userAgent.platform', 'goog.labs.userAgent.util', 'goog.string'], false); -goog.addDependency('useragent/useragent_quirks_test.js', ['goog.userAgentQuirksTest'], ['goog.testing.jsunit', 'goog.userAgent'], false); -goog.addDependency('useragent/useragent_test.js', ['goog.userAgentTest'], ['goog.array', 'goog.labs.userAgent.platform', 'goog.labs.userAgent.testAgents', 'goog.labs.userAgent.util', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgentTestUtil'], false); -goog.addDependency('useragent/useragenttestutil.js', ['goog.userAgentTestUtil', 'goog.userAgentTestUtil.UserAgents'], ['goog.labs.userAgent.browser', 'goog.labs.userAgent.engine', 'goog.labs.userAgent.platform', 'goog.userAgent', 'goog.userAgent.keyboard', 'goog.userAgent.platform', 'goog.userAgent.product', 'goog.userAgent.product.isVersion'], false); -goog.addDependency('vec/float32array.js', ['goog.vec.Float32Array'], [], false); -goog.addDependency('vec/float64array.js', ['goog.vec.Float64Array'], [], false); -goog.addDependency('vec/mat3.js', ['goog.vec.Mat3'], ['goog.vec'], false); -goog.addDependency('vec/mat3d.js', ['goog.vec.mat3d', 'goog.vec.mat3d.Type'], ['goog.vec'], false); -goog.addDependency('vec/mat3f.js', ['goog.vec.mat3f', 'goog.vec.mat3f.Type'], ['goog.vec'], false); -goog.addDependency('vec/mat4.js', ['goog.vec.Mat4'], ['goog.vec', 'goog.vec.Vec3', 'goog.vec.Vec4'], false); -goog.addDependency('vec/mat4d.js', ['goog.vec.mat4d', 'goog.vec.mat4d.Type'], ['goog.vec', 'goog.vec.vec3d', 'goog.vec.vec4d'], false); -goog.addDependency('vec/mat4f.js', ['goog.vec.mat4f', 'goog.vec.mat4f.Type'], ['goog.vec', 'goog.vec.vec3f', 'goog.vec.vec4f'], false); -goog.addDependency('vec/matrix3.js', ['goog.vec.Matrix3'], [], false); -goog.addDependency('vec/matrix4.js', ['goog.vec.Matrix4'], ['goog.vec', 'goog.vec.Vec3', 'goog.vec.Vec4'], false); -goog.addDependency('vec/quaternion.js', ['goog.vec.Quaternion'], ['goog.vec', 'goog.vec.Vec3', 'goog.vec.Vec4'], false); -goog.addDependency('vec/ray.js', ['goog.vec.Ray'], ['goog.vec.Vec3'], false); -goog.addDependency('vec/vec.js', ['goog.vec', 'goog.vec.AnyType', 'goog.vec.ArrayType', 'goog.vec.Float32', 'goog.vec.Float64', 'goog.vec.Number'], ['goog.vec.Float32Array', 'goog.vec.Float64Array'], false); -goog.addDependency('vec/vec2.js', ['goog.vec.Vec2'], ['goog.vec'], false); -goog.addDependency('vec/vec2d.js', ['goog.vec.vec2d', 'goog.vec.vec2d.Type'], ['goog.vec'], false); -goog.addDependency('vec/vec2f.js', ['goog.vec.vec2f', 'goog.vec.vec2f.Type'], ['goog.vec'], false); -goog.addDependency('vec/vec3.js', ['goog.vec.Vec3'], ['goog.vec'], false); -goog.addDependency('vec/vec3d.js', ['goog.vec.vec3d', 'goog.vec.vec3d.Type'], ['goog.vec'], false); -goog.addDependency('vec/vec3f.js', ['goog.vec.vec3f', 'goog.vec.vec3f.Type'], ['goog.vec'], false); -goog.addDependency('vec/vec4.js', ['goog.vec.Vec4'], ['goog.vec'], false); -goog.addDependency('vec/vec4d.js', ['goog.vec.vec4d', 'goog.vec.vec4d.Type'], ['goog.vec'], false); -goog.addDependency('vec/vec4f.js', ['goog.vec.vec4f', 'goog.vec.vec4f.Type'], ['goog.vec'], false); -goog.addDependency('webgl/webgl.js', ['goog.webgl'], [], false); -goog.addDependency('window/window.js', ['goog.window'], ['goog.string', 'goog.userAgent'], false); -goog.addDependency('window/window_test.js', ['goog.windowTest'], ['goog.dom', 'goog.events', 'goog.string', 'goog.testing.AsyncTestCase', 'goog.testing.jsunit', 'goog.window'], false); diff --git a/src/database/third_party/closure-library/closure/goog/disposable/disposable.js b/src/database/third_party/closure-library/closure/goog/disposable/disposable.js deleted file mode 100644 index d9c89d96e8b..00000000000 --- a/src/database/third_party/closure-library/closure/goog/disposable/disposable.js +++ /dev/null @@ -1,307 +0,0 @@ -// Copyright 2005 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Implements the disposable interface. The dispose method is used - * to clean up references and resources. - * @author arv@google.com (Erik Arvidsson) - */ - - -goog.provide('goog.Disposable'); -/** @suppress {extraProvide} */ -goog.provide('goog.dispose'); -/** @suppress {extraProvide} */ -goog.provide('goog.disposeAll'); - -goog.require('goog.disposable.IDisposable'); - - - -/** - * Class that provides the basic implementation for disposable objects. If your - * class holds one or more references to COM objects, DOM nodes, or other - * disposable objects, it should extend this class or implement the disposable - * interface (defined in goog.disposable.IDisposable). - * @constructor - * @implements {goog.disposable.IDisposable} - */ -goog.Disposable = function() { - if (goog.Disposable.MONITORING_MODE != goog.Disposable.MonitoringMode.OFF) { - if (goog.Disposable.INCLUDE_STACK_ON_CREATION) { - this.creationStack = new Error().stack; - } - goog.Disposable.instances_[goog.getUid(this)] = this; - } - // Support sealing - this.disposed_ = this.disposed_; - this.onDisposeCallbacks_ = this.onDisposeCallbacks_; -}; - - -/** - * @enum {number} Different monitoring modes for Disposable. - */ -goog.Disposable.MonitoringMode = { - /** - * No monitoring. - */ - OFF: 0, - /** - * Creating and disposing the goog.Disposable instances is monitored. All - * disposable objects need to call the {@code goog.Disposable} base - * constructor. The PERMANENT mode must be switched on before creating any - * goog.Disposable instances. - */ - PERMANENT: 1, - /** - * INTERACTIVE mode can be switched on and off on the fly without producing - * errors. It also doesn't warn if the disposable objects don't call the - * {@code goog.Disposable} base constructor. - */ - INTERACTIVE: 2 -}; - - -/** - * @define {number} The monitoring mode of the goog.Disposable - * instances. Default is OFF. Switching on the monitoring is only - * recommended for debugging because it has a significant impact on - * performance and memory usage. If switched off, the monitoring code - * compiles down to 0 bytes. - */ -goog.define('goog.Disposable.MONITORING_MODE', 0); - - -/** - * @define {boolean} Whether to attach creation stack to each created disposable - * instance; This is only relevant for when MonitoringMode != OFF. - */ -goog.define('goog.Disposable.INCLUDE_STACK_ON_CREATION', true); - - -/** - * Maps the unique ID of every undisposed {@code goog.Disposable} object to - * the object itself. - * @type {!Object} - * @private - */ -goog.Disposable.instances_ = {}; - - -/** - * @return {!Array} All {@code goog.Disposable} objects that - * haven't been disposed of. - */ -goog.Disposable.getUndisposedObjects = function() { - var ret = []; - for (var id in goog.Disposable.instances_) { - if (goog.Disposable.instances_.hasOwnProperty(id)) { - ret.push(goog.Disposable.instances_[Number(id)]); - } - } - return ret; -}; - - -/** - * Clears the registry of undisposed objects but doesn't dispose of them. - */ -goog.Disposable.clearUndisposedObjects = function() { - goog.Disposable.instances_ = {}; -}; - - -/** - * Whether the object has been disposed of. - * @type {boolean} - * @private - */ -goog.Disposable.prototype.disposed_ = false; - - -/** - * Callbacks to invoke when this object is disposed. - * @type {Array} - * @private - */ -goog.Disposable.prototype.onDisposeCallbacks_; - - -/** - * If monitoring the goog.Disposable instances is enabled, stores the creation - * stack trace of the Disposable instance. - * @const {string} - */ -goog.Disposable.prototype.creationStack; - - -/** - * @return {boolean} Whether the object has been disposed of. - * @override - */ -goog.Disposable.prototype.isDisposed = function() { - return this.disposed_; -}; - - -/** - * @return {boolean} Whether the object has been disposed of. - * @deprecated Use {@link #isDisposed} instead. - */ -goog.Disposable.prototype.getDisposed = goog.Disposable.prototype.isDisposed; - - -/** - * Disposes of the object. If the object hasn't already been disposed of, calls - * {@link #disposeInternal}. Classes that extend {@code goog.Disposable} should - * override {@link #disposeInternal} in order to delete references to COM - * objects, DOM nodes, and other disposable objects. Reentrant. - * - * @return {void} Nothing. - * @override - */ -goog.Disposable.prototype.dispose = function() { - if (!this.disposed_) { - // Set disposed_ to true first, in case during the chain of disposal this - // gets disposed recursively. - this.disposed_ = true; - this.disposeInternal(); - if (goog.Disposable.MONITORING_MODE != goog.Disposable.MonitoringMode.OFF) { - var uid = goog.getUid(this); - if (goog.Disposable.MONITORING_MODE == - goog.Disposable.MonitoringMode.PERMANENT && - !goog.Disposable.instances_.hasOwnProperty(uid)) { - throw Error(this + ' did not call the goog.Disposable base ' + - 'constructor or was disposed of after a clearUndisposedObjects ' + - 'call'); - } - delete goog.Disposable.instances_[uid]; - } - } -}; - - -/** - * Associates a disposable object with this object so that they will be disposed - * together. - * @param {goog.disposable.IDisposable} disposable that will be disposed when - * this object is disposed. - */ -goog.Disposable.prototype.registerDisposable = function(disposable) { - this.addOnDisposeCallback(goog.partial(goog.dispose, disposable)); -}; - - -/** - * Invokes a callback function when this object is disposed. Callbacks are - * invoked in the order in which they were added. If a callback is added to - * an already disposed Disposable, it will be called immediately. - * @param {function(this:T):?} callback The callback function. - * @param {T=} opt_scope An optional scope to call the callback in. - * @template T - */ -goog.Disposable.prototype.addOnDisposeCallback = function(callback, opt_scope) { - if (this.disposed_) { - callback.call(opt_scope); - return; - } - if (!this.onDisposeCallbacks_) { - this.onDisposeCallbacks_ = []; - } - - this.onDisposeCallbacks_.push( - goog.isDef(opt_scope) ? goog.bind(callback, opt_scope) : callback); -}; - - -/** - * Deletes or nulls out any references to COM objects, DOM nodes, or other - * disposable objects. Classes that extend {@code goog.Disposable} should - * override this method. - * Not reentrant. To avoid calling it twice, it must only be called from the - * subclass' {@code disposeInternal} method. Everywhere else the public - * {@code dispose} method must be used. - * For example: - *
- *   mypackage.MyClass = function() {
- *     mypackage.MyClass.base(this, 'constructor');
- *     // Constructor logic specific to MyClass.
- *     ...
- *   };
- *   goog.inherits(mypackage.MyClass, goog.Disposable);
- *
- *   mypackage.MyClass.prototype.disposeInternal = function() {
- *     // Dispose logic specific to MyClass.
- *     ...
- *     // Call superclass's disposeInternal at the end of the subclass's, like
- *     // in C++, to avoid hard-to-catch issues.
- *     mypackage.MyClass.base(this, 'disposeInternal');
- *   };
- * 
- * @protected - */ -goog.Disposable.prototype.disposeInternal = function() { - if (this.onDisposeCallbacks_) { - while (this.onDisposeCallbacks_.length) { - this.onDisposeCallbacks_.shift()(); - } - } -}; - - -/** - * Returns True if we can verify the object is disposed. - * Calls {@code isDisposed} on the argument if it supports it. If obj - * is not an object with an isDisposed() method, return false. - * @param {*} obj The object to investigate. - * @return {boolean} True if we can verify the object is disposed. - */ -goog.Disposable.isDisposed = function(obj) { - if (obj && typeof obj.isDisposed == 'function') { - return obj.isDisposed(); - } - return false; -}; - - -/** - * Calls {@code dispose} on the argument if it supports it. If obj is not an - * object with a dispose() method, this is a no-op. - * @param {*} obj The object to dispose of. - */ -goog.dispose = function(obj) { - if (obj && typeof obj.dispose == 'function') { - obj.dispose(); - } -}; - - -/** - * Calls {@code dispose} on each member of the list that supports it. (If the - * member is an ArrayLike, then {@code goog.disposeAll()} will be called - * recursively on each of its members.) If the member is not an object with a - * {@code dispose()} method, then it is ignored. - * @param {...*} var_args The list. - */ -goog.disposeAll = function(var_args) { - for (var i = 0, len = arguments.length; i < len; ++i) { - var disposable = arguments[i]; - if (goog.isArrayLike(disposable)) { - goog.disposeAll.apply(null, disposable); - } else { - goog.dispose(disposable); - } - } -}; diff --git a/src/database/third_party/closure-library/closure/goog/disposable/disposable_test.html b/src/database/third_party/closure-library/closure/goog/disposable/disposable_test.html deleted file mode 100644 index be73dbf1af9..00000000000 --- a/src/database/third_party/closure-library/closure/goog/disposable/disposable_test.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - Closure Unit Tests - goog.Disposable - - - - - -
- Hello! -
- - diff --git a/src/database/third_party/closure-library/closure/goog/disposable/disposable_test.js b/src/database/third_party/closure-library/closure/goog/disposable/disposable_test.js deleted file mode 100644 index e95db01b693..00000000000 --- a/src/database/third_party/closure-library/closure/goog/disposable/disposable_test.js +++ /dev/null @@ -1,313 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.DisposableTest'); -goog.setTestOnly('goog.DisposableTest'); - -goog.require('goog.Disposable'); -goog.require('goog.testing.jsunit'); -goog.require('goog.testing.recordFunction'); -var d1, d2; - -// Sample subclass of goog.Disposable. - -function DisposableTest() { - goog.Disposable.call(this); - this.element = document.getElementById('someElement'); -} -goog.inherits(DisposableTest, goog.Disposable); - -DisposableTest.prototype.disposeInternal = function() { - DisposableTest.superClass_.disposeInternal.call(this); - delete this.element; -}; - -// Class that doesn't inherit from goog.Disposable, but implements the -// disposable interface via duck typing. - -function DisposableDuck() { - this.element = document.getElementById('someElement'); -} - -DisposableDuck.prototype.dispose = function() { - delete this.element; -}; - -// Class which calls dispose recursively. - -function RecursiveDisposable() { - this.disposedCount = 0; -} -goog.inherits(RecursiveDisposable, goog.Disposable); - -RecursiveDisposable.prototype.disposeInternal = function() { - ++this.disposedCount; - assertEquals('Disposed too many times', 1, this.disposedCount); - this.dispose(); -}; - -// Test methods. - -function setUp() { - d1 = new goog.Disposable(); - d2 = new DisposableTest(); -} - -function tearDown() { - goog.Disposable.MONITORING_MODE = goog.Disposable.MonitoringMode.OFF; - goog.Disposable.INCLUDE_STACK_ON_CREATION = true; - goog.Disposable.instances_ = {}; - d1.dispose(); - d2.dispose(); -} - -function testConstructor() { - assertFalse(d1.isDisposed()); - assertFalse(d2.isDisposed()); - assertEquals(document.getElementById('someElement'), d2.element); -} - -function testDispose() { - assertFalse(d1.isDisposed()); - d1.dispose(); - assertTrue('goog.Disposable instance should have been disposed of', - d1.isDisposed()); - - assertFalse(d2.isDisposed()); - d2.dispose(); - assertTrue('goog.DisposableTest instance should have been disposed of', - d2.isDisposed()); -} - -function testDisposeInternal() { - assertNotUndefined(d2.element); - d2.dispose(); - assertUndefined('goog.DisposableTest.prototype.disposeInternal should ' + - 'have deleted the element reference', d2.element); -} - -function testDisposeAgain() { - d2.dispose(); - assertUndefined('goog.DisposableTest.prototype.disposeInternal should ' + - 'have deleted the element reference', d2.element); - // Manually reset the element to a non-null value, and call dispose(). - // Because the object is already marked disposed, disposeInternal won't - // be called again. - d2.element = document.getElementById('someElement'); - d2.dispose(); - assertNotUndefined('disposeInternal should not be called again if the ' + - 'object has already been marked disposed', d2.element); -} - -function testDisposeWorksRecursively() { - new RecursiveDisposable().dispose(); -} - -function testStaticDispose() { - assertFalse(d1.isDisposed()); - goog.dispose(d1); - assertTrue('goog.Disposable instance should have been disposed of', - d1.isDisposed()); - - assertFalse(d2.isDisposed()); - goog.dispose(d2); - assertTrue('goog.DisposableTest instance should have been disposed of', - d2.isDisposed()); - - var duck = new DisposableDuck(); - assertNotUndefined(duck.element); - goog.dispose(duck); - assertUndefined('goog.dispose should have disposed of object that ' + - 'implements the disposable interface', duck.element); -} - -function testStaticDisposeOnNonDisposableType() { - // Call goog.dispose() with various types and make sure no errors are - // thrown. - goog.dispose(true); - goog.dispose(false); - goog.dispose(null); - goog.dispose(undefined); - goog.dispose(''); - goog.dispose([]); - goog.dispose({}); - - function A() {} - goog.dispose(new A()); -} - -function testMonitoringFailure() { - function BadDisposable() {}; - goog.inherits(BadDisposable, goog.Disposable); - - goog.Disposable.MONITORING_MODE = - goog.Disposable.MonitoringMode.PERMANENT; - - var badDisposable = new BadDisposable; - assertArrayEquals('no disposable objects registered', [], - goog.Disposable.getUndisposedObjects()); - assertThrows('the base ctor should have been called', - goog.bind(badDisposable.dispose, badDisposable)); -} - -function testGetUndisposedObjects() { - goog.Disposable.MONITORING_MODE = - goog.Disposable.MonitoringMode.PERMANENT; - - var d1 = new DisposableTest(); - var d2 = new DisposableTest(); - assertSameElements('the undisposed instances', [d1, d2], - goog.Disposable.getUndisposedObjects()); - - d1.dispose(); - assertSameElements('1 undisposed instance left', [d2], - goog.Disposable.getUndisposedObjects()); - - d1.dispose(); - assertSameElements('second disposal of the same object is no-op', [d2], - goog.Disposable.getUndisposedObjects()); - - d2.dispose(); - assertSameElements('all objects have been disposed of', [], - goog.Disposable.getUndisposedObjects()); -} - -function testClearUndisposedObjects() { - goog.Disposable.MONITORING_MODE = - goog.Disposable.MonitoringMode.PERMANENT; - - var d1 = new DisposableTest(); - var d2 = new DisposableTest(); - d2.dispose(); - goog.Disposable.clearUndisposedObjects(); - assertSameElements('no undisposed object in the registry', [], - goog.Disposable.getUndisposedObjects()); - - assertThrows('disposal after clearUndisposedObjects()', function() { - d1.dispose(); - }); - - // d2 is already disposed of, the redisposal shouldn't throw error. - d2.dispose(); -} - -function testRegisterDisposable() { - var d1 = new DisposableTest(); - var d2 = new DisposableTest(); - - d1.registerDisposable(d2); - d1.dispose(); - - assertTrue('d2 should be disposed when d1 is disposed', d2.isDisposed()); -} - -function testDisposeAll() { - var d1 = new DisposableTest(); - var d2 = new DisposableTest(); - - goog.disposeAll(d1, d2); - - assertTrue('d1 should be disposed', d1.isDisposed()); - assertTrue('d2 should be disposed', d2.isDisposed()); -} - -function testDisposeAllRecursive() { - var d1 = new DisposableTest(); - var d2 = new DisposableTest(); - var d3 = new DisposableTest(); - var d4 = new DisposableTest(); - - goog.disposeAll(d1, [[d2], d3, d4]); - - assertTrue('d1 should be disposed', d1.isDisposed()); - assertTrue('d2 should be disposed', d2.isDisposed()); - assertTrue('d3 should be disposed', d3.isDisposed()); - assertTrue('d4 should be disposed', d4.isDisposed()); -} - -function testCreationStack() { - if (!new Error().stack) - return; - goog.Disposable.MONITORING_MODE = - goog.Disposable.MonitoringMode.PERMANENT; - var disposableStack = new DisposableTest().creationStack; - // Check that the name of this test function occurs in the stack trace. - assertNotEquals(-1, disposableStack.indexOf('testCreationStack')); -} - -function testMonitoredWithoutCreationStack() { - if (!new Error().stack) - return; - goog.Disposable.MONITORING_MODE = - goog.Disposable.MonitoringMode.PERMANENT; - goog.Disposable.INCLUDE_STACK_ON_CREATION = false; - var d1 = new DisposableTest(); - - // Check that it is tracked, but not with a creation stack. - assertUndefined(d1.creationStack); - assertSameElements('the undisposed instance', [d1], - goog.Disposable.getUndisposedObjects()); -} - -function testOnDisposeCallback() { - var callback = goog.testing.recordFunction(); - d1.addOnDisposeCallback(callback); - assertEquals('callback called too early', 0, callback.getCallCount()); - d1.dispose(); - assertEquals('callback should be called once on dispose', - 1, callback.getCallCount()); -} - -function testOnDisposeCallbackOrder() { - var invocations = []; - var callback = function(str) { - invocations.push(str); - }; - d1.addOnDisposeCallback(goog.partial(callback, 'a')); - d1.addOnDisposeCallback(goog.partial(callback, 'b')); - goog.dispose(d1); - assertArrayEquals('callbacks should be called in chronological order', - ['a', 'b'], invocations); -} - -function testAddOnDisposeCallbackAfterDispose() { - var callback = goog.testing.recordFunction(); - var scope = {}; - goog.dispose(d1); - d1.addOnDisposeCallback(callback, scope); - assertEquals('Callback should be immediately called if already disposed', 1, - callback.getCallCount()); - assertEquals('Callback scope should be respected', scope, - callback.getLastCall().getThis()); -} - -function testInteractiveMonitoring() { - var d1 = new DisposableTest(); - goog.Disposable.MONITORING_MODE = - goog.Disposable.MonitoringMode.INTERACTIVE; - var d2 = new DisposableTest(); - - assertSameElements('only 1 undisposed instance tracked', [d2], - goog.Disposable.getUndisposedObjects()); - - // No errors should be thrown. - d1.dispose(); - - assertSameElements('1 undisposed instance left', [d2], - goog.Disposable.getUndisposedObjects()); - - d2.dispose(); - assertSameElements('all disposed', [], - goog.Disposable.getUndisposedObjects()); -} diff --git a/src/database/third_party/closure-library/closure/goog/disposable/idisposable.js b/src/database/third_party/closure-library/closure/goog/disposable/idisposable.js deleted file mode 100644 index 917d17ed39f..00000000000 --- a/src/database/third_party/closure-library/closure/goog/disposable/idisposable.js +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2011 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Definition of the disposable interface. A disposable object - * has a dispose method to to clean up references and resources. - * @author nnaze@google.com (Nathan Naze) - */ - - -goog.provide('goog.disposable.IDisposable'); - - - -/** - * Interface for a disposable object. If a instance requires cleanup - * (references COM objects, DOM notes, or other disposable objects), it should - * implement this interface (it may subclass goog.Disposable). - * @interface - */ -goog.disposable.IDisposable = function() {}; - - -/** - * Disposes of the object and its resources. - * @return {void} Nothing. - */ -goog.disposable.IDisposable.prototype.dispose = goog.abstractMethod; - - -/** - * @return {boolean} Whether the object has been disposed of. - */ -goog.disposable.IDisposable.prototype.isDisposed = goog.abstractMethod; diff --git a/src/database/third_party/closure-library/closure/goog/dom/abstractmultirange.js b/src/database/third_party/closure-library/closure/goog/dom/abstractmultirange.js deleted file mode 100644 index d45d38d4983..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/abstractmultirange.js +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utilities for working with ranges comprised of multiple - * sub-ranges. - * - * @author robbyw@google.com (Robby Walker) - */ - - -goog.provide('goog.dom.AbstractMultiRange'); - -goog.require('goog.array'); -goog.require('goog.dom'); -goog.require('goog.dom.AbstractRange'); - - - -/** - * Creates a new multi range with no properties. Do not use this - * constructor: use one of the goog.dom.Range.createFrom* methods instead. - * @constructor - * @extends {goog.dom.AbstractRange} - */ -goog.dom.AbstractMultiRange = function() { -}; -goog.inherits(goog.dom.AbstractMultiRange, goog.dom.AbstractRange); - - -/** @override */ -goog.dom.AbstractMultiRange.prototype.containsRange = function( - otherRange, opt_allowPartial) { - // TODO(user): This will incorrectly return false if two (or more) adjacent - // elements are both in the control range, and are also in the text range - // being compared to. - var ranges = this.getTextRanges(); - var otherRanges = otherRange.getTextRanges(); - - var fn = opt_allowPartial ? goog.array.some : goog.array.every; - return fn(otherRanges, function(otherRange) { - return goog.array.some(ranges, function(range) { - return range.containsRange(otherRange, opt_allowPartial); - }); - }); -}; - - -/** @override */ -goog.dom.AbstractMultiRange.prototype.insertNode = function(node, before) { - if (before) { - goog.dom.insertSiblingBefore(node, this.getStartNode()); - } else { - goog.dom.insertSiblingAfter(node, this.getEndNode()); - } - return node; -}; - - -/** @override */ -goog.dom.AbstractMultiRange.prototype.surroundWithNodes = function(startNode, - endNode) { - this.insertNode(startNode, true); - this.insertNode(endNode, false); -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/abstractrange.js b/src/database/third_party/closure-library/closure/goog/dom/abstractrange.js deleted file mode 100644 index 7d66bfbdb8e..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/abstractrange.js +++ /dev/null @@ -1,529 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Interface definitions for working with ranges - * in HTML documents. - * - * @author robbyw@google.com (Robby Walker) - */ - - -goog.provide('goog.dom.AbstractRange'); -goog.provide('goog.dom.RangeIterator'); -goog.provide('goog.dom.RangeType'); - -goog.require('goog.dom'); -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.SavedCaretRange'); -goog.require('goog.dom.TagIterator'); -goog.require('goog.userAgent'); - - -/** - * Types of ranges. - * @enum {string} - */ -goog.dom.RangeType = { - TEXT: 'text', - CONTROL: 'control', - MULTI: 'mutli' -}; - - - -/** - * Creates a new selection with no properties. Do not use this constructor - - * use one of the goog.dom.Range.from* methods instead. - * @constructor - */ -goog.dom.AbstractRange = function() { -}; - - -/** - * Gets the browser native selection object from the given window. - * @param {Window} win The window to get the selection object from. - * @return {Object} The browser native selection object, or null if it could - * not be retrieved. - */ -goog.dom.AbstractRange.getBrowserSelectionForWindow = function(win) { - if (win.getSelection) { - // W3C - return win.getSelection(); - } else { - // IE - var doc = win.document; - var sel = doc.selection; - if (sel) { - // IE has a bug where it sometimes returns a selection from the wrong - // document. Catching these cases now helps us avoid problems later. - try { - var range = sel.createRange(); - // Only TextRanges have a parentElement method. - if (range.parentElement) { - if (range.parentElement().document != doc) { - return null; - } - } else if (!range.length || - /** @type {ControlRange} */ (range).item(0).document != doc) { - // For ControlRanges, check that the range has items, and that - // the first item in the range is in the correct document. - return null; - } - } catch (e) { - // If the selection is in the wrong document, and the wrong document is - // in a different domain, IE will throw an exception. - return null; - } - // TODO(user|robbyw) Sometimes IE 6 returns a selection instance - // when there is no selection. This object has a 'type' property equals - // to 'None' and a typeDetail property bound to undefined. Ideally this - // function should not return this instance. - return sel; - } - return null; - } -}; - - -/** - * Tests if the given Object is a controlRange. - * @param {Object} range The range object to test. - * @return {boolean} Whether the given Object is a controlRange. - */ -goog.dom.AbstractRange.isNativeControlRange = function(range) { - // For now, tests for presence of a control range function. - return !!range && !!range.addElement; -}; - - -/** - * @return {!goog.dom.AbstractRange} A clone of this range. - */ -goog.dom.AbstractRange.prototype.clone = goog.abstractMethod; - - -/** - * @return {goog.dom.RangeType} The type of range represented by this object. - */ -goog.dom.AbstractRange.prototype.getType = goog.abstractMethod; - - -/** - * @return {Range|TextRange} The native browser range object. - */ -goog.dom.AbstractRange.prototype.getBrowserRangeObject = goog.abstractMethod; - - -/** - * Sets the native browser range object, overwriting any state this range was - * storing. - * @param {Range|TextRange} nativeRange The native browser range object. - * @return {boolean} Whether the given range was accepted. If not, the caller - * will need to call goog.dom.Range.createFromBrowserRange to create a new - * range object. - */ -goog.dom.AbstractRange.prototype.setBrowserRangeObject = function(nativeRange) { - return false; -}; - - -/** - * @return {number} The number of text ranges in this range. - */ -goog.dom.AbstractRange.prototype.getTextRangeCount = goog.abstractMethod; - - -/** - * Get the i-th text range in this range. The behavior is undefined if - * i >= getTextRangeCount or i < 0. - * @param {number} i The range number to retrieve. - * @return {goog.dom.TextRange} The i-th text range. - */ -goog.dom.AbstractRange.prototype.getTextRange = goog.abstractMethod; - - -/** - * Gets an array of all text ranges this range is comprised of. For non-multi - * ranges, returns a single element array containing this. - * @return {!Array} Array of text ranges. - */ -goog.dom.AbstractRange.prototype.getTextRanges = function() { - var output = []; - for (var i = 0, len = this.getTextRangeCount(); i < len; i++) { - output.push(this.getTextRange(i)); - } - return output; -}; - - -/** - * @return {Node} The deepest node that contains the entire range. - */ -goog.dom.AbstractRange.prototype.getContainer = goog.abstractMethod; - - -/** - * Returns the deepest element in the tree that contains the entire range. - * @return {Element} The deepest element that contains the entire range. - */ -goog.dom.AbstractRange.prototype.getContainerElement = function() { - var node = this.getContainer(); - return /** @type {Element} */ ( - node.nodeType == goog.dom.NodeType.ELEMENT ? node : node.parentNode); -}; - - -/** - * @return {Node} The element or text node the range starts in. For text - * ranges, the range comprises all text between the start and end position. - * For other types of range, start and end give bounds of the range but - * do not imply all nodes in those bounds are selected. - */ -goog.dom.AbstractRange.prototype.getStartNode = goog.abstractMethod; - - -/** - * @return {number} The offset into the node the range starts in. For text - * nodes, this is an offset into the node value. For elements, this is - * an offset into the childNodes array. - */ -goog.dom.AbstractRange.prototype.getStartOffset = goog.abstractMethod; - - -/** - * @return {goog.math.Coordinate} The coordinate of the selection start node - * and offset. - */ -goog.dom.AbstractRange.prototype.getStartPosition = goog.abstractMethod; - - -/** - * @return {Node} The element or text node the range ends in. - */ -goog.dom.AbstractRange.prototype.getEndNode = goog.abstractMethod; - - -/** - * @return {number} The offset into the node the range ends in. For text - * nodes, this is an offset into the node value. For elements, this is - * an offset into the childNodes array. - */ -goog.dom.AbstractRange.prototype.getEndOffset = goog.abstractMethod; - - -/** - * @return {goog.math.Coordinate} The coordinate of the selection end - * node and offset. - */ -goog.dom.AbstractRange.prototype.getEndPosition = goog.abstractMethod; - - -/** - * @return {Node} The element or text node the range is anchored at. - */ -goog.dom.AbstractRange.prototype.getAnchorNode = function() { - return this.isReversed() ? this.getEndNode() : this.getStartNode(); -}; - - -/** - * @return {number} The offset into the node the range is anchored at. For - * text nodes, this is an offset into the node value. For elements, this - * is an offset into the childNodes array. - */ -goog.dom.AbstractRange.prototype.getAnchorOffset = function() { - return this.isReversed() ? this.getEndOffset() : this.getStartOffset(); -}; - - -/** - * @return {Node} The element or text node the range is focused at - i.e. where - * the cursor is. - */ -goog.dom.AbstractRange.prototype.getFocusNode = function() { - return this.isReversed() ? this.getStartNode() : this.getEndNode(); -}; - - -/** - * @return {number} The offset into the node the range is focused at - i.e. - * where the cursor is. For text nodes, this is an offset into the node - * value. For elements, this is an offset into the childNodes array. - */ -goog.dom.AbstractRange.prototype.getFocusOffset = function() { - return this.isReversed() ? this.getStartOffset() : this.getEndOffset(); -}; - - -/** - * @return {boolean} Whether the selection is reversed. - */ -goog.dom.AbstractRange.prototype.isReversed = function() { - return false; -}; - - -/** - * @return {!Document} The document this selection is a part of. - */ -goog.dom.AbstractRange.prototype.getDocument = function() { - // Using start node in IE was crashing the browser in some cases so use - // getContainer for that browser. It's also faster for IE, but still slower - // than start node for other browsers so we continue to use getStartNode when - // it is not problematic. See bug 1687309. - return goog.dom.getOwnerDocument(goog.userAgent.IE ? - this.getContainer() : this.getStartNode()); -}; - - -/** - * @return {!Window} The window this selection is a part of. - */ -goog.dom.AbstractRange.prototype.getWindow = function() { - return goog.dom.getWindow(this.getDocument()); -}; - - -/** - * Tests if this range contains the given range. - * @param {goog.dom.AbstractRange} range The range to test. - * @param {boolean=} opt_allowPartial If true, the range can be partially - * contained in the selection, otherwise the range must be entirely - * contained. - * @return {boolean} Whether this range contains the given range. - */ -goog.dom.AbstractRange.prototype.containsRange = goog.abstractMethod; - - -/** - * Tests if this range contains the given node. - * @param {Node} node The node to test for. - * @param {boolean=} opt_allowPartial If not set or false, the node must be - * entirely contained in the selection for this function to return true. - * @return {boolean} Whether this range contains the given node. - */ -goog.dom.AbstractRange.prototype.containsNode = function(node, - opt_allowPartial) { - return this.containsRange(goog.dom.Range.createFromNodeContents(node), - opt_allowPartial); -}; - - -/** - * Tests whether this range is valid (i.e. whether its endpoints are still in - * the document). A range becomes invalid when, after this object was created, - * either one or both of its endpoints are removed from the document. Use of - * an invalid range can lead to runtime errors, particularly in IE. - * @return {boolean} Whether the range is valid. - */ -goog.dom.AbstractRange.prototype.isRangeInDocument = goog.abstractMethod; - - -/** - * @return {boolean} Whether the range is collapsed. - */ -goog.dom.AbstractRange.prototype.isCollapsed = goog.abstractMethod; - - -/** - * @return {string} The text content of the range. - */ -goog.dom.AbstractRange.prototype.getText = goog.abstractMethod; - - -/** - * Returns the HTML fragment this range selects. This is slow on all browsers. - * The HTML fragment may not be valid HTML, for instance if the user selects - * from a to b inclusively in the following html: - * - * >div<a>/div<b - * - * This method will return - * - * a</div>b - * - * If you need valid HTML, use {@link #getValidHtml} instead. - * - * @return {string} HTML fragment of the range, does not include context - * containing elements. - */ -goog.dom.AbstractRange.prototype.getHtmlFragment = goog.abstractMethod; - - -/** - * Returns valid HTML for this range. This is fast on IE, and semi-fast on - * other browsers. - * @return {string} Valid HTML of the range, including context containing - * elements. - */ -goog.dom.AbstractRange.prototype.getValidHtml = goog.abstractMethod; - - -/** - * Returns pastable HTML for this range. This guarantees that any child items - * that must have specific ancestors will have them, for instance all TDs will - * be contained in a TR in a TBODY in a TABLE and all LIs will be contained in - * a UL or OL as appropriate. This is semi-fast on all browsers. - * @return {string} Pastable HTML of the range, including context containing - * elements. - */ -goog.dom.AbstractRange.prototype.getPastableHtml = goog.abstractMethod; - - -/** - * Returns a RangeIterator over the contents of the range. Regardless of the - * direction of the range, the iterator will move in document order. - * @param {boolean=} opt_keys Unused for this iterator. - * @return {!goog.dom.RangeIterator} An iterator over tags in the range. - */ -goog.dom.AbstractRange.prototype.__iterator__ = goog.abstractMethod; - - -// RANGE ACTIONS - - -/** - * Sets this range as the selection in its window. - */ -goog.dom.AbstractRange.prototype.select = goog.abstractMethod; - - -/** - * Removes the contents of the range from the document. - */ -goog.dom.AbstractRange.prototype.removeContents = goog.abstractMethod; - - -/** - * Inserts a node before (or after) the range. The range may be disrupted - * beyond recovery because of the way this splits nodes. - * @param {Node} node The node to insert. - * @param {boolean} before True to insert before, false to insert after. - * @return {Node} The node added to the document. This may be different - * than the node parameter because on IE we have to clone it. - */ -goog.dom.AbstractRange.prototype.insertNode = goog.abstractMethod; - - -/** - * Replaces the range contents with (possibly a copy of) the given node. The - * range may be disrupted beyond recovery because of the way this splits nodes. - * @param {Node} node The node to insert. - * @return {Node} The node added to the document. This may be different - * than the node parameter because on IE we have to clone it. - */ -goog.dom.AbstractRange.prototype.replaceContentsWithNode = function(node) { - if (!this.isCollapsed()) { - this.removeContents(); - } - - return this.insertNode(node, true); -}; - - -/** - * Surrounds this range with the two given nodes. The range may be disrupted - * beyond recovery because of the way this splits nodes. - * @param {Element} startNode The node to insert at the start. - * @param {Element} endNode The node to insert at the end. - */ -goog.dom.AbstractRange.prototype.surroundWithNodes = goog.abstractMethod; - - -// SAVE/RESTORE - - -/** - * Saves the range so that if the start and end nodes are left alone, it can - * be restored. - * @return {!goog.dom.SavedRange} A range representation that can be restored - * as long as the endpoint nodes of the selection are not modified. - */ -goog.dom.AbstractRange.prototype.saveUsingDom = goog.abstractMethod; - - -/** - * Saves the range using HTML carets. As long as the carets remained in the - * HTML, the range can be restored...even when the HTML is copied across - * documents. - * @return {goog.dom.SavedCaretRange?} A range representation that can be - * restored as long as carets are not removed. Returns null if carets - * could not be created. - */ -goog.dom.AbstractRange.prototype.saveUsingCarets = function() { - return (this.getStartNode() && this.getEndNode()) ? - new goog.dom.SavedCaretRange(this) : null; -}; - - -// RANGE MODIFICATION - - -/** - * Collapses the range to one of its boundary points. - * @param {boolean} toAnchor Whether to collapse to the anchor of the range. - */ -goog.dom.AbstractRange.prototype.collapse = goog.abstractMethod; - -// RANGE ITERATION - - - -/** - * Subclass of goog.dom.TagIterator that iterates over a DOM range. It - * adds functions to determine the portion of each text node that is selected. - * @param {Node} node The node to start traversal at. When null, creates an - * empty iterator. - * @param {boolean=} opt_reverse Whether to traverse nodes in reverse. - * @constructor - * @extends {goog.dom.TagIterator} - */ -goog.dom.RangeIterator = function(node, opt_reverse) { - goog.dom.TagIterator.call(this, node, opt_reverse, true); -}; -goog.inherits(goog.dom.RangeIterator, goog.dom.TagIterator); - - -/** - * @return {number} The offset into the current node, or -1 if the current node - * is not a text node. - */ -goog.dom.RangeIterator.prototype.getStartTextOffset = goog.abstractMethod; - - -/** - * @return {number} The end offset into the current node, or -1 if the current - * node is not a text node. - */ -goog.dom.RangeIterator.prototype.getEndTextOffset = goog.abstractMethod; - - -/** - * @return {Node} node The iterator's start node. - */ -goog.dom.RangeIterator.prototype.getStartNode = goog.abstractMethod; - - -/** - * @return {Node} The iterator's end node. - */ -goog.dom.RangeIterator.prototype.getEndNode = goog.abstractMethod; - - -/** - * @return {boolean} Whether a call to next will fail. - */ -goog.dom.RangeIterator.prototype.isLast = goog.abstractMethod; diff --git a/src/database/third_party/closure-library/closure/goog/dom/abstractrange_test.html b/src/database/third_party/closure-library/closure/goog/dom/abstractrange_test.html deleted file mode 100644 index c708ad95794..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/abstractrange_test.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - Closure Unit Tests - goog.dom.abstractrange - - - - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/abstractrange_test.js b/src/database/third_party/closure-library/closure/goog/dom/abstractrange_test.js deleted file mode 100644 index edd28ffe545..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/abstractrange_test.js +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2009 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.dom.AbstractRangeTest'); -goog.setTestOnly('goog.dom.AbstractRangeTest'); - -goog.require('goog.dom'); -goog.require('goog.dom.AbstractRange'); -goog.require('goog.dom.Range'); -goog.require('goog.testing.jsunit'); - -function testCorrectDocument() { - var a = goog.dom.getElement('a').contentWindow; - var b = goog.dom.getElement('b').contentWindow; - - a.document.body.focus(); - var selection = goog.dom.AbstractRange.getBrowserSelectionForWindow(a); - assertNotNull('Selection must not be null', selection); - var range = goog.dom.Range.createFromBrowserSelection(selection); - assertEquals('getBrowserSelectionForWindow must return selection in the ' + - 'correct document', a.document, range.getDocument()); - - // This is intended to trip up Internet Explorer -- - // see http://b/2048934 - b.document.body.focus(); - selection = goog.dom.AbstractRange.getBrowserSelectionForWindow(a); - // Some (non-IE) browsers keep a separate selection state for each document - // in the same browser window. That's fine, as long as the selection object - // requested from the window object is correctly associated with that - // window's document. - if (selection != null && selection.rangeCount != 0) { - range = goog.dom.Range.createFromBrowserSelection(selection); - assertEquals('getBrowserSelectionForWindow must return selection in ' + - 'the correct document', a.document, range.getDocument()); - } else { - assertTrue(selection == null || selection.rangeCount == 0); - } -} - -function testSelectionIsControlRange() { - var c = goog.dom.getElement('c').contentWindow; - // Only IE supports control ranges - if (c.document.body.createControlRange) { - var controlRange = c.document.body.createControlRange(); - controlRange.add(c.document.getElementsByTagName('img')[0]); - controlRange.select(); - var selection = goog.dom.AbstractRange.getBrowserSelectionForWindow(c); - assertNotNull('Selection must not be null', selection); - } -} diff --git a/src/database/third_party/closure-library/closure/goog/dom/animationframe/animationframe.js b/src/database/third_party/closure-library/closure/goog/dom/animationframe/animationframe.js deleted file mode 100644 index b9bccff37cf..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/animationframe/animationframe.js +++ /dev/null @@ -1,287 +0,0 @@ -// Copyright 2014 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview goog.dom.animationFrame permits work to be done in-sync with - * the render refresh rate of the browser and to divide work up globally based - * on whether the intent is to measure or to mutate the DOM. The latter avoids - * repeated style recalculation which can be really slow. - * - * Goals of the API: - *
    - *
  • Make it easy to schedule work for the next animation frame. - *
  • Make it easy to only do work once per animation frame, even if two - * events fire that trigger the same work. - *
  • Make it easy to do all work in two phases to avoid repeated style - * recalculation caused by interleaved reads and writes. - *
  • Avoid creating closures per schedule operation. - *
- * - * - * Programmatic: - *
- * var animationTask = goog.dom.animationFrame.createTask({
- *     measure: function(state) {
- *       state.width = goog.style.getSize(elem).width;
- *       this.animationTask();
- *     },
- *     mutate: function(state) {
- *       goog.style.setWidth(elem, Math.floor(state.width / 2));
- *     }
- *   }, this);
- * });
- * 
- * - * See also - * https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame - */ - -goog.provide('goog.dom.animationFrame'); -goog.provide('goog.dom.animationFrame.Spec'); -goog.provide('goog.dom.animationFrame.State'); - -goog.require('goog.dom.animationFrame.polyfill'); - -// Install the polyfill. -goog.dom.animationFrame.polyfill.install(); - - -/** - * @typedef {{ - * id: number, - * fn: !Function, - * context: (!Object|undefined) - * }} - * @private - */ -goog.dom.animationFrame.Task_; - - -/** - * @typedef {{ - * measureTask: goog.dom.animationFrame.Task_, - * mutateTask: goog.dom.animationFrame.Task_, - * state: (!Object|undefined), - * args: (!Array|undefined), - * isScheduled: boolean - * }} - * @private - */ -goog.dom.animationFrame.TaskSet_; - - -/** - * @typedef {{ - * measure: (!Function|undefined), - * mutate: (!Function|undefined) - * }} - */ -goog.dom.animationFrame.Spec; - - - -/** - * A type to represent state. Users may add properties as desired. - * @constructor - * @final - */ -goog.dom.animationFrame.State = function() {}; - - -/** - * Saves a set of tasks to be executed in the next requestAnimationFrame phase. - * This list is initialized once before any event firing occurs. It is not - * affected by the fired events or the requestAnimationFrame processing (unless - * a new event is created during the processing). - * @private {!Array>} - */ -goog.dom.animationFrame.tasks_ = [[], []]; - - -/** - * Values are 0 or 1, for whether the first or second array should be used to - * lookup or add tasks. - * @private {number} - */ -goog.dom.animationFrame.doubleBufferIndex_ = 0; - - -/** - * Whether we have already requested an animation frame that hasn't happened - * yet. - * @private {boolean} - */ -goog.dom.animationFrame.requestedFrame_ = false; - - -/** - * Counter to generate IDs for tasks. - * @private {number} - */ -goog.dom.animationFrame.taskId_ = 0; - - -/** - * Whether the animationframe runTasks_ loop is currently running. - * @private {boolean} - */ -goog.dom.animationFrame.running_ = false; - - -/** - * Returns a function that schedules the two passed-in functions to be run upon - * the next animation frame. Calling the function again during the same - * animation frame does nothing. - * - * The function under the "measure" key will run first and together with all - * other functions scheduled under this key and the function under "mutate" will - * run after that. - * - * @param {{ - * measure: (function(this:THIS, !goog.dom.animationFrame.State)|undefined), - * mutate: (function(this:THIS, !goog.dom.animationFrame.State)|undefined) - * }} spec - * @param {THIS=} opt_context Context in which to run the function. - * @return {function(...?)} - * @template THIS - */ -goog.dom.animationFrame.createTask = function(spec, opt_context) { - var id = goog.dom.animationFrame.taskId_++; - var measureTask = { - id: id, - fn: spec.measure, - context: opt_context - }; - var mutateTask = { - id: id, - fn: spec.mutate, - context: opt_context - }; - - var taskSet = { - measureTask: measureTask, - mutateTask: mutateTask, - state: {}, - args: undefined, - isScheduled: false - }; - - return function() { - // Default the context to the one that was used to call the tasks scheduler - // (this function). - if (!opt_context) { - measureTask.context = this; - mutateTask.context = this; - } - - // Save args and state. - if (arguments.length > 0) { - // The state argument goes last. That is kinda horrible but compatible - // with {@see wiz.async.method}. - if (!taskSet.args) { - taskSet.args = []; - } - taskSet.args.length = 0; - taskSet.args.push.apply(taskSet.args, arguments); - taskSet.args.push(taskSet.state); - } else { - if (!taskSet.args || taskSet.args.length == 0) { - taskSet.args = [taskSet.state]; - } else { - taskSet.args[0] = taskSet.state; - taskSet.args.length = 1; - } - } - if (!taskSet.isScheduled) { - taskSet.isScheduled = true; - var tasksArray = goog.dom.animationFrame.tasks_[ - goog.dom.animationFrame.doubleBufferIndex_]; - tasksArray.push(taskSet); - } - goog.dom.animationFrame.requestAnimationFrame_(); - }; -}; - - -/** - * Run scheduled tasks. - * @private - */ -goog.dom.animationFrame.runTasks_ = function() { - goog.dom.animationFrame.running_ = true; - goog.dom.animationFrame.requestedFrame_ = false; - var tasksArray = goog.dom.animationFrame - .tasks_[goog.dom.animationFrame.doubleBufferIndex_]; - var taskLength = tasksArray.length; - - // During the runTasks_, if there is a recursive call to queue up more - // task(s) for the next frame, we use double-buffering for that. - goog.dom.animationFrame.doubleBufferIndex_ = - (goog.dom.animationFrame.doubleBufferIndex_ + 1) % 2; - - var task; - - // Run all the measure tasks first. - for (var i = 0; i < taskLength; ++i) { - task = tasksArray[i]; - var measureTask = task.measureTask; - task.isScheduled = false; - if (measureTask.fn) { - // TODO (perumaal): Handle any exceptions thrown by the lambda. - measureTask.fn.apply(measureTask.context, task.args); - } - } - - // Run the mutate tasks next. - for (var i = 0; i < taskLength; ++i) { - task = tasksArray[i]; - var mutateTask = task.mutateTask; - task.isScheduled = false; - if (mutateTask.fn) { - // TODO (perumaal): Handle any exceptions thrown by the lambda. - mutateTask.fn.apply(mutateTask.context, task.args); - } - - // Clear state for next vsync. - task.state = {}; - } - - // Clear the tasks array as we have finished processing all the tasks. - tasksArray.length = 0; - goog.dom.animationFrame.running_ = false; -}; - - -/** - * @return {boolean} Whether the animationframe is currently running. For use - * by callers who need not to delay tasks scheduled during runTasks_ for an - * additional frame. - */ -goog.dom.animationFrame.isRunning = function() { - return goog.dom.animationFrame.running_; -}; - - -/** - * Request {@see goog.dom.animationFrame.runTasks_} to be called upon the - * next animation frame if we haven't done so already. - * @private - */ -goog.dom.animationFrame.requestAnimationFrame_ = function() { - if (goog.dom.animationFrame.requestedFrame_) { - return; - } - goog.dom.animationFrame.requestedFrame_ = true; - window.requestAnimationFrame(goog.dom.animationFrame.runTasks_); -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/animationframe/animationframe_test.js b/src/database/third_party/closure-library/closure/goog/dom/animationframe/animationframe_test.js deleted file mode 100644 index a716cc12632..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/animationframe/animationframe_test.js +++ /dev/null @@ -1,265 +0,0 @@ -// Copyright 2014 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Tests for goog.dom.animationFrame. - */ - -goog.setTestOnly(); - -goog.require('goog.dom.animationFrame'); -goog.require('goog.testing.MockClock'); -goog.require('goog.testing.jsunit'); - - -var NEXT_FRAME = goog.testing.MockClock.REQUEST_ANIMATION_FRAME_TIMEOUT; -var mockClock; -var t0, t1; -var result; - -function setUp() { - mockClock = new goog.testing.MockClock(true); - result = ''; - t0 = goog.dom.animationFrame.createTask({ - measure: function() { - result += 'me0'; - }, - mutate: function() { - result += 'mu0'; - } - }); - t1 = goog.dom.animationFrame.createTask({ - measure: function() { - result += 'me1'; - }, - mutate: function() { - result += 'mu1'; - } - }); - assertEquals('', result); -} - -function tearDown() { - mockClock.dispose(); -} - -function testCreateTask_one() { - t0(); - assertEquals('', result); - mockClock.tick(NEXT_FRAME); - assertEquals('me0mu0', result); - mockClock.tick(NEXT_FRAME); - assertEquals('me0mu0', result); - t0(); - t0(); // Should do nothing. - mockClock.tick(NEXT_FRAME); - assertEquals('me0mu0me0mu0', result); -} - -function testCreateTask_onlyMutate() { - t0 = goog.dom.animationFrame.createTask({ - mutate: function() { - result += 'mu0'; - } - }); - t0(); - assertEquals('', result); - mockClock.tick(NEXT_FRAME); - assertEquals('mu0', result); -} - -function testCreateTask_onlyMeasure() { - t0 = goog.dom.animationFrame.createTask({ - mutate: function() { - result += 'me0'; - } - }); - t0(); - assertEquals('', result); - mockClock.tick(NEXT_FRAME); - assertEquals('me0', result); -} - -function testCreateTask_two() { - t0(); - t1(); - assertEquals('', result); - mockClock.tick(NEXT_FRAME); - assertEquals('me0me1mu0mu1', result); - mockClock.tick(NEXT_FRAME); - assertEquals('me0me1mu0mu1', result); - t0(); - t1(); - t0(); - t1(); - mockClock.tick(NEXT_FRAME); - assertEquals('me0me1mu0mu1me0me1mu0mu1', result); -} - -function testCreateTask_recurse() { - var stop = false; - var recurse = goog.dom.animationFrame.createTask({ - measure: function() { - if (!stop) { - recurse(); - } - result += 're0'; - }, - mutate: function() { - result += 'ru0'; - } - }); - recurse(); - mockClock.tick(NEXT_FRAME); - assertEquals('re0ru0', result); - mockClock.tick(NEXT_FRAME); - assertEquals('re0ru0re0ru0', result); - mockClock.tick(NEXT_FRAME); - assertEquals('re0ru0re0ru0re0ru0', result); - t0(); - stop = true; - mockClock.tick(NEXT_FRAME); - assertEquals('re0ru0re0ru0re0ru0re0me0ru0mu0', result); - - // Recursion should have stopped now. - mockClock.tick(NEXT_FRAME); - assertEquals('re0ru0re0ru0re0ru0re0me0ru0mu0', result); - assertFalse(goog.dom.animationFrame.requestedFrame_); - mockClock.tick(NEXT_FRAME); - assertEquals('re0ru0re0ru0re0ru0re0me0ru0mu0', result); - assertFalse(goog.dom.animationFrame.requestedFrame_); -} - -function testCreateTask_recurseTwoMethodsWithState() { - var stop = false; - var recurse1 = goog.dom.animationFrame.createTask({ - measure: function(state) { - if (!stop) { - recurse2(); - } - result += 'r1e0'; - state.text = 'T0'; - }, - mutate: function(state) { - result += 'r1u0' + state.text; - } - }); - var recurse2 = goog.dom.animationFrame.createTask({ - measure: function(state) { - if (!stop) { - recurse1(); - } - result += 'r2e0'; - state.text = 'T1'; - }, - mutate: function(state) { - result += 'r2u0' + state.text; - } - }); - - var taskLength = goog.dom.animationFrame.tasks_[0].length; - - recurse1(); - mockClock.tick(NEXT_FRAME); - // Only recurse1 executed. - assertEquals('r1e0r1u0T0', result); - - mockClock.tick(NEXT_FRAME); - // Recurse2 executed and queueup recurse1. - assertEquals('r1e0r1u0T0r2e0r2u0T1', result); - - mockClock.tick(NEXT_FRAME); - // Recurse1 executed and queueup recurse2. - assertEquals('r1e0r1u0T0r2e0r2u0T1r1e0r1u0T0', result); - - stop = true; - mockClock.tick(NEXT_FRAME); - // Recurse2 executed and should have stopped. - assertEquals('r1e0r1u0T0r2e0r2u0T1r1e0r1u0T0r2e0r2u0T1', result); - assertFalse(goog.dom.animationFrame.requestedFrame_); - - mockClock.tick(NEXT_FRAME); - assertEquals('r1e0r1u0T0r2e0r2u0T1r1e0r1u0T0r2e0r2u0T1', result); - assertFalse(goog.dom.animationFrame.requestedFrame_); - - mockClock.tick(NEXT_FRAME); - assertEquals('r1e0r1u0T0r2e0r2u0T1r1e0r1u0T0r2e0r2u0T1', result); - assertFalse(goog.dom.animationFrame.requestedFrame_); -} - -function testCreateTask_args() { - var context = {context: true}; - var s = goog.dom.animationFrame.createTask({ - measure: function(state) { - assertEquals(context, this); - assertUndefined(state.foo); - state.foo = 'foo'; - }, - mutate: function(state) { - assertEquals(context, this); - result += state.foo; - } - }, context); - s(); - mockClock.tick(NEXT_FRAME); - assertEquals('foo', result); - - var dynamicContext = goog.dom.animationFrame.createTask({ - measure: function(state) { - assertEquals(context, this); - }, - mutate: function(state) { - assertEquals(context, this); - result += 'bar'; - } - }); - dynamicContext.call(context); - mockClock.tick(NEXT_FRAME); - assertEquals('foobar', result); - - var moreArgs = goog.dom.animationFrame.createTask({ - measure: function(event, state) { - assertEquals(context, this); - assertEquals('event', event); - state.baz = 'baz'; - }, - mutate: function(event, state) { - assertEquals('event', event); - assertEquals(context, this); - result += state.baz; - } - }); - moreArgs.call(context, 'event'); - mockClock.tick(NEXT_FRAME); - assertEquals('foobarbaz', result); -} - -function testIsRunning() { - var result = ''; - var task = goog.dom.animationFrame.createTask({ - measure: function() { - result += 'me'; - assertTrue(goog.dom.animationFrame.isRunning()); - }, - mutate: function() { - result += 'mu'; - assertTrue(goog.dom.animationFrame.isRunning()); - } - }); - task(); - assertFalse(goog.dom.animationFrame.isRunning()); - mockClock.tick(NEXT_FRAME); - assertFalse(goog.dom.animationFrame.isRunning()); - assertEquals('memu', result); -} diff --git a/src/database/third_party/closure-library/closure/goog/dom/animationframe/polyfill.js b/src/database/third_party/closure-library/closure/goog/dom/animationframe/polyfill.js deleted file mode 100644 index 19e88668a7d..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/animationframe/polyfill.js +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2014 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview A polyfill for window.requestAnimationFrame and - * window.cancelAnimationFrame. - * Code based on https://gist.github.com/paulirish/1579671 - */ - -goog.provide('goog.dom.animationFrame.polyfill'); - - -/** - * @define {boolean} If true, will install the requestAnimationFrame polyfill. - */ -goog.define('goog.dom.animationFrame.polyfill.ENABLED', true); - - -/** - * Installs the requestAnimationFrame (and cancelAnimationFrame) polyfill. - */ -goog.dom.animationFrame.polyfill.install = - goog.dom.animationFrame.polyfill.ENABLED ? function() { - var vendors = ['ms', 'moz', 'webkit', 'o']; - for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { - window.requestAnimationFrame = window[vendors[x] + - 'RequestAnimationFrame']; - window.cancelAnimationFrame = window[vendors[x] + - 'CancelAnimationFrame'] || - window[vendors[x] + 'CancelRequestAnimationFrame']; - } - - if (!window.requestAnimationFrame) { - var lastTime = 0; - window.requestAnimationFrame = function(callback, element) { - var currTime = new Date().getTime(); - var timeToCall = Math.max(0, 16 - (currTime - lastTime)); - lastTime = currTime + timeToCall; - return window.setTimeout(function() { - callback(currTime + timeToCall); - }, timeToCall); - }; - - if (!window.cancelAnimationFrame) { - window.cancelAnimationFrame = function(id) { - clearTimeout(id); - }; - } - } -} : goog.nullFunction; diff --git a/src/database/third_party/closure-library/closure/goog/dom/annotate.js b/src/database/third_party/closure-library/closure/goog/dom/annotate.js deleted file mode 100644 index 7ed867eafad..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/annotate.js +++ /dev/null @@ -1,354 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Methods for annotating occurrences of query terms in text or - * in a DOM tree. Adapted from Gmail code. - * - */ - -goog.provide('goog.dom.annotate'); -goog.provide('goog.dom.annotate.AnnotateFn'); - -goog.require('goog.array'); -goog.require('goog.asserts'); -goog.require('goog.dom'); -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.safe'); -goog.require('goog.html.SafeHtml'); - - -/** - * A function that takes: - * (1) the number of the term that is "hit", - * (2) the HTML (search term) to be annotated, - * and returns the annotated term as an HTML. - * @typedef {function(number, !goog.html.SafeHtml): !goog.html.SafeHtml} - */ -goog.dom.annotate.AnnotateFn; - - -/** - * Calls {@code annotateFn} for each occurrence of a search term in text nodes - * under {@code node}. Returns the number of hits. - * - * @param {Node} node A DOM node. - * @param {Array>} terms - * An array of [searchTerm, matchWholeWordOnly] tuples. - * The matchWholeWordOnly value is a per-term attribute because some terms - * may be CJK, while others are not. (For correctness, matchWholeWordOnly - * should always be false for CJK terms.). - * @param {goog.dom.annotate.AnnotateFn} annotateFn - * @param {*=} opt_ignoreCase Whether to ignore the case of the query - * terms when looking for matches. - * @param {Array=} opt_classesToSkip Nodes with one of these CSS class - * names (and its descendants) will be skipped. - * @param {number=} opt_maxMs Number of milliseconds after which this function, - * if still annotating, should stop and return. - * - * @return {boolean} Whether any terms were annotated. - */ -goog.dom.annotate.annotateTerms = function(node, terms, annotateFn, - opt_ignoreCase, - opt_classesToSkip, - opt_maxMs) { - if (opt_ignoreCase) { - terms = goog.dom.annotate.lowercaseTerms_(terms); - } - var stopTime = opt_maxMs > 0 ? goog.now() + opt_maxMs : 0; - - return goog.dom.annotate.annotateTermsInNode_( - node, terms, annotateFn, opt_ignoreCase, opt_classesToSkip || [], - stopTime, 0); -}; - - -/** - * The maximum recursion depth allowed. Any DOM nodes deeper than this are - * ignored. - * @type {number} - * @private - */ -goog.dom.annotate.MAX_RECURSION_ = 200; - - -/** - * The node types whose descendants should not be affected by annotation. - * @private {Array} - */ -goog.dom.annotate.NODES_TO_SKIP_ = ['SCRIPT', 'STYLE', 'TEXTAREA']; - - -/** - * Recursive helper function. - * - * @param {Node} node A DOM node. - * @param {Array>} terms - * An array of [searchTerm, matchWholeWordOnly] tuples. - * The matchWholeWordOnly value is a per-term attribute because some terms - * may be CJK, while others are not. (For correctness, matchWholeWordOnly - * should always be false for CJK terms.). - * @param {goog.dom.annotate.AnnotateFn} annotateFn - * @param {*} ignoreCase Whether to ignore the case of the query terms - * when looking for matches. - * @param {Array} classesToSkip Nodes with one of these CSS class - * names will be skipped (as will their descendants). - * @param {number} stopTime Deadline for annotation operation (ignored if 0). - * @param {number} recursionLevel How deep this recursive call is; pass the - * value 0 in the initial call. - * @return {boolean} Whether any terms were annotated. - * @private - */ -goog.dom.annotate.annotateTermsInNode_ = - function(node, terms, annotateFn, ignoreCase, classesToSkip, - stopTime, recursionLevel) { - if ((stopTime > 0 && goog.now() >= stopTime) || - recursionLevel > goog.dom.annotate.MAX_RECURSION_) { - return false; - } - - var annotated = false; - - if (node.nodeType == goog.dom.NodeType.TEXT) { - var html = goog.dom.annotate.helpAnnotateText_(node.nodeValue, terms, - annotateFn, ignoreCase); - if (html != null) { - // Replace the text with the annotated html. First we put the html into - // a temporary node, to get its DOM structure. To avoid adding a wrapper - // element as a side effect, we'll only actually use the temporary node's - // children. - var tempNode = goog.dom.getOwnerDocument(node).createElement('SPAN'); - goog.dom.safe.setInnerHtml(tempNode, html); - - var parentNode = node.parentNode; - var nodeToInsert; - while ((nodeToInsert = tempNode.firstChild) != null) { - // Each parentNode.insertBefore call removes the inserted node from - // tempNode's list of children. - parentNode.insertBefore(nodeToInsert, node); - } - - parentNode.removeChild(node); - annotated = true; - } - } else if (node.hasChildNodes() && - !goog.array.contains(goog.dom.annotate.NODES_TO_SKIP_, - node.tagName)) { - var classes = node.className.split(/\s+/); - var skip = goog.array.some(classes, function(className) { - return goog.array.contains(classesToSkip, className); - }); - - if (!skip) { - ++recursionLevel; - var curNode = node.firstChild; - while (curNode) { - var nextNode = curNode.nextSibling; - var curNodeAnnotated = goog.dom.annotate.annotateTermsInNode_( - curNode, terms, annotateFn, ignoreCase, classesToSkip, - stopTime, recursionLevel); - annotated = annotated || curNodeAnnotated; - curNode = nextNode; - } - } - } - - return annotated; -}; - - -/** - * Regular expression that matches non-word characters. - * - * Performance note: Testing a one-character string using this regex is as fast - * as the equivalent string test ("a-zA-Z0-9_".indexOf(c) < 0), give or take a - * few percent. (The regex is about 5% faster in IE 6 and about 4% slower in - * Firefox 1.5.) If performance becomes critical, it may be better to convert - * the character to a numerical char code and check whether it falls in the - * word character ranges. A quick test suggests that could be 33% faster. - * - * @type {RegExp} - * @private - */ -goog.dom.annotate.NONWORD_RE_ = /\W/; - - -/** - * Annotates occurrences of query terms in plain text. This process consists of - * identifying all occurrences of all query terms, calling a provided function - * to get the appropriate replacement HTML for each occurrence, and - * HTML-escaping all the text. - * - * @param {string} text The plain text to be searched. - * @param {Array>} terms An array of - * [{string} searchTerm, {boolean} matchWholeWordOnly] tuples. - * The matchWholeWordOnly value is a per-term attribute because some terms - * may be CJK, while others are not. (For correctness, matchWholeWordOnly - * should always be false for CJK terms.). - * @param {goog.dom.annotate.AnnotateFn} annotateFn - * @param {*=} opt_ignoreCase Whether to ignore the case of the query - * terms when looking for matches. - * @return {goog.html.SafeHtml} The HTML equivalent of {@code text} with terms - * annotated, or null if the text did not contain any of the terms. - */ -goog.dom.annotate.annotateText = function(text, terms, annotateFn, - opt_ignoreCase) { - if (opt_ignoreCase) { - terms = goog.dom.annotate.lowercaseTerms_(terms); - } - return goog.dom.annotate.helpAnnotateText_(text, terms, annotateFn, - opt_ignoreCase); -}; - - -/** - * Annotates occurrences of query terms in plain text. This process consists of - * identifying all occurrences of all query terms, calling a provided function - * to get the appropriate replacement HTML for each occurrence, and - * HTML-escaping all the text. - * - * @param {string} text The plain text to be searched. - * @param {Array>} terms An array of - * [{string} searchTerm, {boolean} matchWholeWordOnly] tuples. - * If {@code ignoreCase} is true, each search term must already be lowercase. - * The matchWholeWordOnly value is a per-term attribute because some terms - * may be CJK, while others are not. (For correctness, matchWholeWordOnly - * should always be false for CJK terms.). - * @param {goog.dom.annotate.AnnotateFn} annotateFn - * @param {*} ignoreCase Whether to ignore the case of the query terms - * when looking for matches. - * @return {goog.html.SafeHtml} The HTML equivalent of {@code text} with terms - * annotated, or null if the text did not contain any of the terms. - * @private - */ -goog.dom.annotate.helpAnnotateText_ = function(text, terms, annotateFn, - ignoreCase) { - var hit = false; - var textToSearch = ignoreCase ? text.toLowerCase() : text; - var textLen = textToSearch.length; - var numTerms = terms.length; - - // Each element will be an array of hit positions for the term. - var termHits = new Array(numTerms); - - // First collect all the hits into allHits. - for (var i = 0; i < numTerms; i++) { - var term = terms[i]; - var hits = []; - var termText = term[0]; - if (termText != '') { - var matchWholeWordOnly = term[1]; - var termLen = termText.length; - var pos = 0; - // Find each hit for term t and append to termHits. - while (pos < textLen) { - var hitPos = textToSearch.indexOf(termText, pos); - if (hitPos == -1) { - break; - } else { - var prevCharPos = hitPos - 1; - var nextCharPos = hitPos + termLen; - if (!matchWholeWordOnly || - ((prevCharPos < 0 || - goog.dom.annotate.NONWORD_RE_.test( - textToSearch.charAt(prevCharPos))) && - (nextCharPos >= textLen || - goog.dom.annotate.NONWORD_RE_.test( - textToSearch.charAt(nextCharPos))))) { - hits.push(hitPos); - hit = true; - } - pos = hitPos + termLen; - } - } - } - termHits[i] = hits; - } - - if (hit) { - var html = []; - var pos = 0; - - while (true) { - // First determine which of the n terms is the next hit. - var termIndexOfNextHit; - var posOfNextHit = -1; - - for (var i = 0; i < numTerms; i++) { - var hits = termHits[i]; - // pull off the position of the next hit of term t - // (it's always the first in the array because we're shifting - // hits off the front of the array as we process them) - // this is the next candidate to consider for the next overall hit - if (!goog.array.isEmpty(hits)) { - var hitPos = hits[0]; - - // Discard any hits embedded in the previous hit. - while (hitPos >= 0 && hitPos < pos) { - hits.shift(); - hitPos = goog.array.isEmpty(hits) ? -1 : hits[0]; - } - - if (hitPos >= 0 && (posOfNextHit < 0 || hitPos < posOfNextHit)) { - termIndexOfNextHit = i; - posOfNextHit = hitPos; - } - } - } - - // Quit if there are no more hits. - if (posOfNextHit < 0) break; - - // Remove the next hit from our hit list. - termHits[termIndexOfNextHit].shift(); - - // Append everything from the end of the last hit up to this one. - html.push(text.substr(pos, posOfNextHit - pos)); - - // Append the annotated term. - var termLen = terms[termIndexOfNextHit][0].length; - var termHtml = goog.html.SafeHtml.htmlEscape( - text.substr(posOfNextHit, termLen)); - html.push( - annotateFn(goog.asserts.assertNumber(termIndexOfNextHit), termHtml)); - - pos = posOfNextHit + termLen; - } - - // Append everything after the last hit. - html.push(text.substr(pos)); - return goog.html.SafeHtml.concat(html); - } else { - return null; - } -}; - - -/** - * Converts terms to lowercase. - * - * @param {Array>} terms An array of - * [{string} searchTerm, {boolean} matchWholeWordOnly] tuples. - * @return {!Array>} An array of - * [{string} searchTerm, {boolean} matchWholeWordOnly] tuples. - * @private - */ -goog.dom.annotate.lowercaseTerms_ = function(terms) { - var lowercaseTerms = []; - for (var i = 0; i < terms.length; ++i) { - var term = terms[i]; - lowercaseTerms[i] = [term[0].toLowerCase(), term[1]]; - } - return lowercaseTerms; -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/annotate_test.html b/src/database/third_party/closure-library/closure/goog/dom/annotate_test.html deleted file mode 100644 index 92bd82f6d29..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/annotate_test.html +++ /dev/null @@ -1,57 +0,0 @@ - - - - - -Closure Unit Tests - goog.dom.annotate - - - - - -Tom & Jerry - - - - - - - - - - - - - - - - - -
This little piggyThat little piggy
This little piggyThat little piggy
This little piggyThat little Piggy
This little piggyThat little Piggy
- -
- - - - - - - Your browser cannot display this object. - -
- - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/annotate_test.js b/src/database/third_party/closure-library/closure/goog/dom/annotate_test.js deleted file mode 100644 index 2c2dfa6a7e3..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/annotate_test.js +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.dom.annotateTest'); -goog.setTestOnly('goog.dom.annotateTest'); - -goog.require('goog.dom'); -goog.require('goog.dom.annotate'); -goog.require('goog.html.SafeHtml'); -goog.require('goog.testing.jsunit'); - -var $ = goog.dom.getElement; - -var TEXT = 'This little piggy cried "Wee! Wee! Wee!" all the way home.'; - -function doAnnotation(termIndex, termHtml) { - return goog.html.SafeHtml.create('span', {'class': 'c' + termIndex}, - termHtml); -} - -// goog.dom.annotate.annotateText tests - -function testAnnotateText() { - var terms = [['pig', true]]; - var html = goog.dom.annotate.annotateText(TEXT, terms, doAnnotation); - assertEquals(null, html); - - terms = [['pig', false]]; - html = goog.dom.annotate.annotateText(TEXT, terms, doAnnotation); - html = goog.html.SafeHtml.unwrap(html); - assertEquals('This little piggy cried ' + - '"Wee! Wee! Wee!" all the way home.', html); - - terms = [[' piggy ', true]]; - html = goog.dom.annotate.annotateText(TEXT, terms, doAnnotation); - assertEquals(null, html); - - terms = [[' piggy ', false]]; - html = goog.dom.annotate.annotateText(TEXT, terms, doAnnotation); - html = goog.html.SafeHtml.unwrap(html); - assertEquals('This little piggy cried ' + - '"Wee! Wee! Wee!" all the way home.', html); - - terms = [['goose', true], ['piggy', true]]; - html = goog.dom.annotate.annotateText(TEXT, terms, doAnnotation); - html = goog.html.SafeHtml.unwrap(html); - assertEquals('This little piggy cried ' + - '"Wee! Wee! Wee!" all the way home.', html); -} - -function testAnnotateTextHtmlEscaping() { - var terms = [['a', false]]; - var html = goog.dom.annotate.annotateText('&a', terms, doAnnotation); - html = goog.html.SafeHtml.unwrap(html); - assertEquals('&a', html); - - terms = [['a', false]]; - html = goog.dom.annotate.annotateText('a&', terms, doAnnotation); - html = goog.html.SafeHtml.unwrap(html); - assertEquals('a&', html); - - terms = [['&', false]]; - html = goog.dom.annotate.annotateText('&', terms, doAnnotation); - html = goog.html.SafeHtml.unwrap(html); - assertEquals('&', html); -} - -function testAnnotateTextIgnoreCase() { - var terms = [['wEe', true]]; - var html = goog.dom.annotate.annotateText(TEXT, terms, doAnnotation, true); - html = goog.html.SafeHtml.unwrap(html); - assertEquals('This little piggy cried "Wee! ' + - 'Wee! Wee!' + - '" all the way home.', html); - - terms = [['WEE!', true], ['HE', false]]; - html = goog.dom.annotate.annotateText(TEXT, terms, doAnnotation, true); - html = goog.html.SafeHtml.unwrap(html); - assertEquals('This little piggy cried "Wee! ' + - 'Wee! Wee!' + - '" all the way home.', html); -} - -function testAnnotateTextOverlappingTerms() { - var terms = [['tt', false], ['little', false]]; - var html = goog.dom.annotate.annotateText(TEXT, terms, doAnnotation); - html = goog.html.SafeHtml.unwrap(html); - assertEquals('This little piggy cried "Wee! ' + - 'Wee! Wee!" all the way home.', html); -} - -// goog.dom.annotate.annotateTerms tests - -function testAnnotateTerms() { - var terms = [['pig', true]]; - assertFalse(goog.dom.annotate.annotateTerms($('p'), terms, doAnnotation)); - assertEquals('Tom & Jerry', $('p').innerHTML); - - terms = [['Tom', true]]; - assertTrue(goog.dom.annotate.annotateTerms($('p'), terms, doAnnotation)); - var spans = goog.dom.getElementsByTagNameAndClass('SPAN', 'c0', $('p')); - assertEquals(1, spans.length); - assertEquals('Tom', spans[0].innerHTML); - assertEquals(' & Jerry', spans[0].nextSibling.nodeValue); -} - -function testAnnotateTermsInTable() { - var terms = [['pig', false]]; - assertTrue(goog.dom.annotate.annotateTerms($('q'), terms, doAnnotation)); - var spans = goog.dom.getElementsByTagNameAndClass('SPAN', 'c0', $('q')); - assertEquals(2, spans.length); - assertEquals('pig', spans[0].innerHTML); - assertEquals('gy', spans[0].nextSibling.nodeValue); - assertEquals('pig', spans[1].innerHTML); - assertEquals('I', spans[1].parentNode.tagName); -} - -function testAnnotateTermsWithClassExclusions() { - var terms = [['pig', false]]; - var classesToIgnore = ['s']; - assertTrue(goog.dom.annotate.annotateTerms($('r'), terms, doAnnotation, - false, classesToIgnore)); - var spans = goog.dom.getElementsByTagNameAndClass('SPAN', 'c0', $('r')); - assertEquals(1, spans.length); - assertEquals('pig', spans[0].innerHTML); - assertEquals('gy', spans[0].nextSibling.nodeValue); -} - -function testAnnotateTermsIgnoreCase() { - var terms1 = [['pig', false]]; - assertTrue(goog.dom.annotate.annotateTerms( - $('t'), terms1, doAnnotation, true)); - var spans = goog.dom.getElementsByTagNameAndClass('SPAN', 'c0', $('t')); - assertEquals(2, spans.length); - assertEquals('pig', spans[0].innerHTML); - assertEquals('gy', spans[0].nextSibling.nodeValue); - assertEquals('Pig', spans[1].innerHTML); - - var terms2 = [['Pig', false]]; - assertTrue(goog.dom.annotate.annotateTerms( - $('u'), terms2, doAnnotation, true)); - var spans = goog.dom.getElementsByTagNameAndClass('SPAN', 'c0', $('u')); - assertEquals(2, spans.length); - assertEquals('pig', spans[0].innerHTML); - assertEquals('gy', spans[0].nextSibling.nodeValue); - assertEquals('Pig', spans[1].innerHTML); -} - -function testAnnotateTermsInObject() { - var terms = [['object', true]]; - assertTrue(goog.dom.annotate.annotateTerms($('o'), terms, doAnnotation)); - var spans = goog.dom.getElementsByTagNameAndClass('SPAN', 'c0', $('o')); - assertEquals(1, spans.length); - assertEquals('object', spans[0].innerHTML); -} - -function testAnnotateTermsInScript() { - var terms = [['variable', true]]; - assertFalse(goog.dom.annotate.annotateTerms($('script'), terms, - doAnnotation)); -} - -function testAnnotateTermsInStyle() { - var terms = [['color', true]]; - assertFalse(goog.dom.annotate.annotateTerms($('style'), terms, - doAnnotation)); -} - -function testAnnotateTermsInHtmlComment() { - var terms = [['note', true]]; - assertFalse(goog.dom.annotate.annotateTerms($('comment'), terms, - doAnnotation)); -} diff --git a/src/database/third_party/closure-library/closure/goog/dom/browserfeature.js b/src/database/third_party/closure-library/closure/goog/dom/browserfeature.js deleted file mode 100644 index 2c70cda4b91..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/browserfeature.js +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2010 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Browser capability checks for the dom package. - * - */ - - -goog.provide('goog.dom.BrowserFeature'); - -goog.require('goog.userAgent'); - - -/** - * Enum of browser capabilities. - * @enum {boolean} - */ -goog.dom.BrowserFeature = { - /** - * Whether attributes 'name' and 'type' can be added to an element after it's - * created. False in Internet Explorer prior to version 9. - */ - CAN_ADD_NAME_OR_TYPE_ATTRIBUTES: !goog.userAgent.IE || - goog.userAgent.isDocumentModeOrHigher(9), - - /** - * Whether we can use element.children to access an element's Element - * children. Available since Gecko 1.9.1, IE 9. (IE<9 also includes comment - * nodes in the collection.) - */ - CAN_USE_CHILDREN_ATTRIBUTE: !goog.userAgent.GECKO && !goog.userAgent.IE || - goog.userAgent.IE && goog.userAgent.isDocumentModeOrHigher(9) || - goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.9.1'), - - /** - * Opera, Safari 3, and Internet Explorer 9 all support innerText but they - * include text nodes in script and style tags. Not document-mode-dependent. - */ - CAN_USE_INNER_TEXT: ( - goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9')), - - /** - * MSIE, Opera, and Safari>=4 support element.parentElement to access an - * element's parent if it is an Element. - */ - CAN_USE_PARENT_ELEMENT_PROPERTY: goog.userAgent.IE || goog.userAgent.OPERA || - goog.userAgent.WEBKIT, - - /** - * Whether NoScope elements need a scoped element written before them in - * innerHTML. - * MSDN: http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx#1 - */ - INNER_HTML_NEEDS_SCOPED_ELEMENT: goog.userAgent.IE, - - /** - * Whether we use legacy IE range API. - */ - LEGACY_IE_RANGES: goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9) -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/browserrange/abstractrange.js b/src/database/third_party/closure-library/closure/goog/dom/browserrange/abstractrange.js deleted file mode 100644 index 3956f3a5fc9..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/browserrange/abstractrange.js +++ /dev/null @@ -1,350 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Definition of the browser range interface. - * - * DO NOT USE THIS FILE DIRECTLY. Use goog.dom.Range instead. - * - * @author robbyw@google.com (Robby Walker) - */ - - -goog.provide('goog.dom.browserrange.AbstractRange'); - -goog.require('goog.array'); -goog.require('goog.asserts'); -goog.require('goog.dom'); -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.RangeEndpoint'); -goog.require('goog.dom.TagName'); -goog.require('goog.dom.TextRangeIterator'); -goog.require('goog.iter'); -goog.require('goog.math.Coordinate'); -goog.require('goog.string'); -goog.require('goog.string.StringBuffer'); -goog.require('goog.userAgent'); - - - -/** - * The constructor for abstract ranges. Don't call this from subclasses. - * @constructor - */ -goog.dom.browserrange.AbstractRange = function() { -}; - - -/** - * @return {goog.dom.browserrange.AbstractRange} A clone of this range. - */ -goog.dom.browserrange.AbstractRange.prototype.clone = goog.abstractMethod; - - -/** - * Returns the browser native implementation of the range. Please refrain from - * using this function - if you find you need the range please add wrappers for - * the functionality you need rather than just using the native range. - * @return {Range|TextRange} The browser native range object. - */ -goog.dom.browserrange.AbstractRange.prototype.getBrowserRange = - goog.abstractMethod; - - -/** - * Returns the deepest node in the tree that contains the entire range. - * @return {Node} The deepest node that contains the entire range. - */ -goog.dom.browserrange.AbstractRange.prototype.getContainer = - goog.abstractMethod; - - -/** - * Returns the node the range starts in. - * @return {Node} The element or text node the range starts in. - */ -goog.dom.browserrange.AbstractRange.prototype.getStartNode = - goog.abstractMethod; - - -/** - * Returns the offset into the node the range starts in. - * @return {number} The offset into the node the range starts in. For text - * nodes, this is an offset into the node value. For elements, this is - * an offset into the childNodes array. - */ -goog.dom.browserrange.AbstractRange.prototype.getStartOffset = - goog.abstractMethod; - - -/** - * @return {goog.math.Coordinate} The coordinate of the selection start node - * and offset. - */ -goog.dom.browserrange.AbstractRange.prototype.getStartPosition = function() { - goog.asserts.assert(this.range_.getClientRects, - 'Getting selection coordinates is not supported.'); - - var rects = this.range_.getClientRects(); - if (rects.length) { - return new goog.math.Coordinate(rects[0]['left'], rects[0]['top']); - } - return null; -}; - - -/** - * Returns the node the range ends in. - * @return {Node} The element or text node the range ends in. - */ -goog.dom.browserrange.AbstractRange.prototype.getEndNode = - goog.abstractMethod; - - -/** - * Returns the offset into the node the range ends in. - * @return {number} The offset into the node the range ends in. For text - * nodes, this is an offset into the node value. For elements, this is - * an offset into the childNodes array. - */ -goog.dom.browserrange.AbstractRange.prototype.getEndOffset = - goog.abstractMethod; - - -/** - * @return {goog.math.Coordinate} The coordinate of the selection end node - * and offset. - */ -goog.dom.browserrange.AbstractRange.prototype.getEndPosition = function() { - goog.asserts.assert(this.range_.getClientRects, - 'Getting selection coordinates is not supported.'); - - var rects = this.range_.getClientRects(); - if (rects.length) { - var lastRect = goog.array.peek(rects); - return new goog.math.Coordinate(lastRect['right'], lastRect['bottom']); - } - return null; -}; - - -/** - * Compares one endpoint of this range with the endpoint of another browser - * native range object. - * @param {Range|TextRange} range The browser native range to compare against. - * @param {goog.dom.RangeEndpoint} thisEndpoint The endpoint of this range - * to compare with. - * @param {goog.dom.RangeEndpoint} otherEndpoint The endpoint of the other - * range to compare with. - * @return {number} 0 if the endpoints are equal, negative if this range - * endpoint comes before the other range endpoint, and positive otherwise. - */ -goog.dom.browserrange.AbstractRange.prototype.compareBrowserRangeEndpoints = - goog.abstractMethod; - - -/** - * Tests if this range contains the given range. - * @param {goog.dom.browserrange.AbstractRange} abstractRange The range to test. - * @param {boolean=} opt_allowPartial If not set or false, the range must be - * entirely contained in the selection for this function to return true. - * @return {boolean} Whether this range contains the given range. - */ -goog.dom.browserrange.AbstractRange.prototype.containsRange = - function(abstractRange, opt_allowPartial) { - // IE sometimes misreports the boundaries for collapsed ranges. So if the - // other range is collapsed, make sure the whole range is contained. This is - // logically equivalent, and works around IE's bug. - var checkPartial = opt_allowPartial && !abstractRange.isCollapsed(); - - var range = abstractRange.getBrowserRange(); - var start = goog.dom.RangeEndpoint.START, end = goog.dom.RangeEndpoint.END; - /** @preserveTry */ - try { - if (checkPartial) { - // There are two ways to not overlap. Being before, and being after. - // Before is represented by this.end before range.start: comparison < 0. - // After is represented by this.start after range.end: comparison > 0. - // The below is the negation of not overlapping. - return this.compareBrowserRangeEndpoints(range, end, start) >= 0 && - this.compareBrowserRangeEndpoints(range, start, end) <= 0; - - } else { - // Return true if this range bounds the parameter range from both sides. - return this.compareBrowserRangeEndpoints(range, end, end) >= 0 && - this.compareBrowserRangeEndpoints(range, start, start) <= 0; - } - } catch (e) { - if (!goog.userAgent.IE) { - throw e; - } - // IE sometimes throws exceptions when one range is invalid, i.e. points - // to a node that has been removed from the document. Return false in this - // case. - return false; - } -}; - - -/** - * Tests if this range contains the given node. - * @param {Node} node The node to test. - * @param {boolean=} opt_allowPartial If not set or false, the node must be - * entirely contained in the selection for this function to return true. - * @return {boolean} Whether this range contains the given node. - */ -goog.dom.browserrange.AbstractRange.prototype.containsNode = function(node, - opt_allowPartial) { - return this.containsRange( - goog.dom.browserrange.createRangeFromNodeContents(node), - opt_allowPartial); -}; - - -/** - * Tests if the selection is collapsed - i.e. is just a caret. - * @return {boolean} Whether the range is collapsed. - */ -goog.dom.browserrange.AbstractRange.prototype.isCollapsed = - goog.abstractMethod; - - -/** - * @return {string} The text content of the range. - */ -goog.dom.browserrange.AbstractRange.prototype.getText = - goog.abstractMethod; - - -/** - * Returns the HTML fragment this range selects. This is slow on all browsers. - * @return {string} HTML fragment of the range, does not include context - * containing elements. - */ -goog.dom.browserrange.AbstractRange.prototype.getHtmlFragment = function() { - var output = new goog.string.StringBuffer(); - goog.iter.forEach(this, function(node, ignore, it) { - if (node.nodeType == goog.dom.NodeType.TEXT) { - output.append(goog.string.htmlEscape(node.nodeValue.substring( - it.getStartTextOffset(), it.getEndTextOffset()))); - } else if (node.nodeType == goog.dom.NodeType.ELEMENT) { - if (it.isEndTag()) { - if (goog.dom.canHaveChildren(node)) { - output.append(''); - } - } else { - var shallow = node.cloneNode(false); - var html = goog.dom.getOuterHtml(shallow); - if (goog.userAgent.IE && node.tagName == goog.dom.TagName.LI) { - // For an LI, IE just returns "
  • " with no closing tag - output.append(html); - } else { - var index = html.lastIndexOf('<'); - output.append(index ? html.substr(0, index) : html); - } - } - } - }, this); - - return output.toString(); -}; - - -/** - * Returns valid HTML for this range. This is fast on IE, and semi-fast on - * other browsers. - * @return {string} Valid HTML of the range, including context containing - * elements. - */ -goog.dom.browserrange.AbstractRange.prototype.getValidHtml = - goog.abstractMethod; - - -/** - * Returns a RangeIterator over the contents of the range. Regardless of the - * direction of the range, the iterator will move in document order. - * @param {boolean=} opt_keys Unused for this iterator. - * @return {!goog.dom.RangeIterator} An iterator over tags in the range. - */ -goog.dom.browserrange.AbstractRange.prototype.__iterator__ = function( - opt_keys) { - return new goog.dom.TextRangeIterator(this.getStartNode(), - this.getStartOffset(), this.getEndNode(), this.getEndOffset()); -}; - - -// SELECTION MODIFICATION - - -/** - * Set this range as the selection in its window. - * @param {boolean=} opt_reverse Whether to select the range in reverse, - * if possible. - */ -goog.dom.browserrange.AbstractRange.prototype.select = - goog.abstractMethod; - - -/** - * Removes the contents of the range from the document. As a side effect, the - * selection will be collapsed. The behavior of content removal is normalized - * across browsers. For instance, IE sometimes creates extra text nodes that - * a W3C browser does not. That behavior is corrected for. - */ -goog.dom.browserrange.AbstractRange.prototype.removeContents = - goog.abstractMethod; - - -/** - * Surrounds the text range with the specified element (on Mozilla) or with a - * clone of the specified element (on IE). Returns a reference to the - * surrounding element if the operation was successful; returns null if the - * operation failed. - * @param {Element} element The element with which the selection is to be - * surrounded. - * @return {Element} The surrounding element (same as the argument on Mozilla, - * but not on IE), or null if unsuccessful. - */ -goog.dom.browserrange.AbstractRange.prototype.surroundContents = - goog.abstractMethod; - - -/** - * Inserts a node before (or after) the range. The range may be disrupted - * beyond recovery because of the way this splits nodes. - * @param {Node} node The node to insert. - * @param {boolean} before True to insert before, false to insert after. - * @return {Node} The node added to the document. This may be different - * than the node parameter because on IE we have to clone it. - */ -goog.dom.browserrange.AbstractRange.prototype.insertNode = - goog.abstractMethod; - - -/** - * Surrounds this range with the two given nodes. The range may be disrupted - * beyond recovery because of the way this splits nodes. - * @param {Element} startNode The node to insert at the start. - * @param {Element} endNode The node to insert at the end. - */ -goog.dom.browserrange.AbstractRange.prototype.surroundWithNodes = - goog.abstractMethod; - - -/** - * Collapses the range to one of its boundary points. - * @param {boolean} toStart Whether to collapse to the start of the range. - */ -goog.dom.browserrange.AbstractRange.prototype.collapse = - goog.abstractMethod; diff --git a/src/database/third_party/closure-library/closure/goog/dom/browserrange/browserrange.js b/src/database/third_party/closure-library/closure/goog/dom/browserrange/browserrange.js deleted file mode 100644 index 0cd70e7cf9c..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/browserrange/browserrange.js +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Definition of the browser range namespace and interface, as - * well as several useful utility functions. - * - * DO NOT USE THIS FILE DIRECTLY. Use goog.dom.Range instead. - * - * @author robbyw@google.com (Robby Walker) - * - * @supported IE6, IE7, FF1.5+, Safari. - */ - - -goog.provide('goog.dom.browserrange'); -goog.provide('goog.dom.browserrange.Error'); - -goog.require('goog.dom'); -goog.require('goog.dom.BrowserFeature'); -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.browserrange.GeckoRange'); -goog.require('goog.dom.browserrange.IeRange'); -goog.require('goog.dom.browserrange.OperaRange'); -goog.require('goog.dom.browserrange.W3cRange'); -goog.require('goog.dom.browserrange.WebKitRange'); -goog.require('goog.userAgent'); - - -/** - * Common error constants. - * @enum {string} - */ -goog.dom.browserrange.Error = { - NOT_IMPLEMENTED: 'Not Implemented' -}; - - -// NOTE(robbyw): While it would be nice to eliminate the duplicate switches -// below, doing so uncovers bugs in the JsCompiler in which -// necessary code is stripped out. - - -/** - * Static method that returns the proper type of browser range. - * @param {Range|TextRange} range A browser range object. - * @return {!goog.dom.browserrange.AbstractRange} A wrapper object. - */ -goog.dom.browserrange.createRange = function(range) { - if (goog.dom.BrowserFeature.LEGACY_IE_RANGES) { - return new goog.dom.browserrange.IeRange( - /** @type {TextRange} */ (range), - goog.dom.getOwnerDocument(range.parentElement())); - } else if (goog.userAgent.WEBKIT) { - return new goog.dom.browserrange.WebKitRange( - /** @type {Range} */ (range)); - } else if (goog.userAgent.GECKO) { - return new goog.dom.browserrange.GeckoRange( - /** @type {Range} */ (range)); - } else if (goog.userAgent.OPERA) { - return new goog.dom.browserrange.OperaRange( - /** @type {Range} */ (range)); - } else { - // Default other browsers, including Opera, to W3c ranges. - return new goog.dom.browserrange.W3cRange( - /** @type {Range} */ (range)); - } -}; - - -/** - * Static method that returns the proper type of browser range. - * @param {Node} node The node to select. - * @return {!goog.dom.browserrange.AbstractRange} A wrapper object. - */ -goog.dom.browserrange.createRangeFromNodeContents = function(node) { - if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9)) { - return goog.dom.browserrange.IeRange.createFromNodeContents(node); - } else if (goog.userAgent.WEBKIT) { - return goog.dom.browserrange.WebKitRange.createFromNodeContents(node); - } else if (goog.userAgent.GECKO) { - return goog.dom.browserrange.GeckoRange.createFromNodeContents(node); - } else if (goog.userAgent.OPERA) { - return goog.dom.browserrange.OperaRange.createFromNodeContents(node); - } else { - // Default other browsers to W3c ranges. - return goog.dom.browserrange.W3cRange.createFromNodeContents(node); - } -}; - - -/** - * Static method that returns the proper type of browser range. - * @param {Node} startNode The node to start with. - * @param {number} startOffset The offset within the node to start. This is - * either the index into the childNodes array for element startNodes or - * the index into the character array for text startNodes. - * @param {Node} endNode The node to end with. - * @param {number} endOffset The offset within the node to end. This is - * either the index into the childNodes array for element endNodes or - * the index into the character array for text endNodes. - * @return {!goog.dom.browserrange.AbstractRange} A wrapper object. - */ -goog.dom.browserrange.createRangeFromNodes = function(startNode, startOffset, - endNode, endOffset) { - if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9)) { - return goog.dom.browserrange.IeRange.createFromNodes(startNode, startOffset, - endNode, endOffset); - } else if (goog.userAgent.WEBKIT) { - return goog.dom.browserrange.WebKitRange.createFromNodes(startNode, - startOffset, endNode, endOffset); - } else if (goog.userAgent.GECKO) { - return goog.dom.browserrange.GeckoRange.createFromNodes(startNode, - startOffset, endNode, endOffset); - } else if (goog.userAgent.OPERA) { - return goog.dom.browserrange.OperaRange.createFromNodes(startNode, - startOffset, endNode, endOffset); - } else { - // Default other browsers to W3c ranges. - return goog.dom.browserrange.W3cRange.createFromNodes(startNode, - startOffset, endNode, endOffset); - } -}; - - -/** - * Tests whether the given node can contain a range end point. - * @param {Node} node The node to check. - * @return {boolean} Whether the given node can contain a range end point. - */ -goog.dom.browserrange.canContainRangeEndpoint = function(node) { - // NOTE(user, bloom): This is not complete, as divs with style - - // 'display:inline-block' or 'position:absolute' can also not contain range - // endpoints. A more complete check is to see if that element can be partially - // selected (can be container) or not. - return goog.dom.canHaveChildren(node) || - node.nodeType == goog.dom.NodeType.TEXT; -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/browserrange/browserrange_test.html b/src/database/third_party/closure-library/closure/goog/dom/browserrange/browserrange_test.html deleted file mode 100644 index b96c9e9696a..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/browserrange/browserrange_test.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - - -Closure Unit Tests - goog.dom.browserrange - - - - -
    -
    Text
    abc
    def
    -
    abc
    -
    -
    Text that
    will be deleted
    -
    -
    Text Text
    -
    0123456789
    -
    0123456789
    0123456789
    -
    outer
    inner
    outer2
    -
    -

    - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/browserrange/browserrange_test.js b/src/database/third_party/closure-library/closure/goog/dom/browserrange/browserrange_test.js deleted file mode 100644 index 797b21dadeb..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/browserrange/browserrange_test.js +++ /dev/null @@ -1,633 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.dom.browserrangeTest'); -goog.setTestOnly('goog.dom.browserrangeTest'); - -goog.require('goog.dom'); -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.Range'); -goog.require('goog.dom.RangeEndpoint'); -goog.require('goog.dom.TagName'); -goog.require('goog.dom.browserrange'); -goog.require('goog.testing.dom'); -goog.require('goog.testing.jsunit'); -goog.require('goog.userAgent'); - -var test1; -var test2; -var cetest; -var empty; -var dynamic; -var onlybrdiv; - -function setUpPage() { - test1 = goog.dom.getElement('test1'); - test2 = goog.dom.getElement('test2'); - cetest = goog.dom.getElement('cetest'); - empty = goog.dom.getElement('empty'); - dynamic = goog.dom.getElement('dynamic'); - onlybrdiv = goog.dom.getElement('onlybr'); -} - -function testCreate() { - assertNotNull('Browser range object can be created for node', - goog.dom.browserrange.createRangeFromNodeContents(test1)); -} - -function testRangeEndPoints() { - var container = cetest.firstChild; - var range = goog.dom.browserrange.createRangeFromNodes( - container, 2, container, 2); - range.select(); - - var selRange = goog.dom.Range.createFromWindow(); - var startNode = selRange.getStartNode(); - var endNode = selRange.getEndNode(); - var startOffset = selRange.getStartOffset(); - var endOffset = selRange.getEndOffset(); - if (goog.userAgent.WEBKIT) { - assertEquals('Start node should have text: abc', - 'abc', startNode.nodeValue); - assertEquals('End node should have text: abc', 'abc', endNode.nodeValue); - assertEquals('Start offset should be 3', 3, startOffset); - assertEquals('End offset should be 3', 3, endOffset); - } else { - assertEquals('Start node should be the first div', container, startNode); - assertEquals('End node should be the first div', container, endNode); - assertEquals('Start offset should be 2', 2, startOffset); - assertEquals('End offset should be 2', 2, endOffset); - } -} - -function testCreateFromNodeContents() { - var range = goog.dom.Range.createFromNodeContents(onlybrdiv); - goog.testing.dom.assertRangeEquals(onlybrdiv, 0, onlybrdiv, 1, range); -} - -function normalizeHtml(str) { - return str.toLowerCase().replace(/[\n\r\f"]/g, ''); -} - -// TODO(robbyw): We really need tests for (and code fixes for) -// createRangeFromNodes in the following cases: -// * BR boundary (before + after) - -function testCreateFromNodes() { - var start = test1.firstChild; - var range = goog.dom.browserrange.createRangeFromNodes(start, 2, - test2.firstChild, 2); - assertNotNull('Browser range object can be created for W3C node range', - range); - - assertEquals('Start node should be selected at start endpoint', start, - range.getStartNode()); - assertEquals('Selection should start at offset 2', 2, - range.getStartOffset()); - - assertEquals('Text node should be selected at end endpoint', - test2.firstChild, range.getEndNode()); - assertEquals('Selection should end at offset 2', 2, range.getEndOffset()); - - assertTrue('Text content should be "xt\\s*ab"', - /xt\s*ab/.test(range.getText())); - assertFalse('Nodes range is not collapsed', range.isCollapsed()); - assertEquals('Should contain correct html fragment', - 'xt
  • ab', - normalizeHtml(range.getHtmlFragment())); - assertEquals('Should contain correct valid html', - '
    xt
    ab
    ', - normalizeHtml(range.getValidHtml())); -} - - -function testTextNode() { - var range = goog.dom.browserrange.createRangeFromNodeContents( - test1.firstChild); - - assertEquals('Text node should be selected at start endpoint', 'Text', - range.getStartNode().nodeValue); - assertEquals('Selection should start at offset 0', 0, - range.getStartOffset()); - - assertEquals('Text node should be selected at end endpoint', 'Text', - range.getEndNode().nodeValue); - assertEquals('Selection should end at offset 4', 'Text'.length, - range.getEndOffset()); - - assertEquals('Container should be text node', goog.dom.NodeType.TEXT, - range.getContainer().nodeType); - - assertEquals('Text content should be "Text"', 'Text', range.getText()); - assertFalse('Text range is not collapsed', range.isCollapsed()); - assertEquals('Should contain correct html fragment', 'Text', - range.getHtmlFragment()); - assertEquals('Should contain correct valid html', - 'Text', range.getValidHtml()); - -} - -function testTextNodes() { - goog.dom.removeChildren(dynamic); - dynamic.appendChild(goog.dom.createTextNode('Part1')); - dynamic.appendChild(goog.dom.createTextNode('Part2')); - var range = goog.dom.browserrange.createRangeFromNodes( - dynamic.firstChild, 0, dynamic.lastChild, 5); - - assertEquals('Text node 1 should be selected at start endpoint', 'Part1', - range.getStartNode().nodeValue); - assertEquals('Selection should start at offset 0', 0, - range.getStartOffset()); - - assertEquals('Text node 2 should be selected at end endpoint', 'Part2', - range.getEndNode().nodeValue); - assertEquals('Selection should end at offset 5', 'Part2'.length, - range.getEndOffset()); - - assertEquals('Container should be DIV', goog.dom.TagName.DIV, - range.getContainer().tagName); - - assertEquals('Text content should be "Part1Part2"', 'Part1Part2', - range.getText()); - assertFalse('Text range is not collapsed', range.isCollapsed()); - assertEquals('Should contain correct html fragment', 'Part1Part2', - range.getHtmlFragment()); - assertEquals('Should contain correct valid html', - 'part1part2', - normalizeHtml(range.getValidHtml())); - -} - -function testDiv() { - var range = goog.dom.browserrange.createRangeFromNodeContents(test2); - - assertEquals('Text node "abc" should be selected at start endpoint', 'abc', - range.getStartNode().nodeValue); - assertEquals('Selection should start at offset 0', 0, - range.getStartOffset()); - - assertEquals('Text node "def" should be selected at end endpoint', 'def', - range.getEndNode().nodeValue); - assertEquals('Selection should end at offset 3', 'def'.length, - range.getEndOffset()); - - assertEquals('Container should be DIV', 'DIV', - range.getContainer().tagName); - - assertTrue('Div text content should be "abc\\s*def"', - /abc\s*def/.test(range.getText())); - assertEquals('Should contain correct html fragment', 'abc
    def', - normalizeHtml(range.getHtmlFragment())); - assertEquals('Should contain correct valid html', - '
    abc
    def
    ', - normalizeHtml(range.getValidHtml())); - assertFalse('Div range is not collapsed', range.isCollapsed()); -} - -function testEmptyNodeHtmlInsert() { - var range = goog.dom.browserrange.createRangeFromNodeContents(empty); - var html = 'hello'; - range.insertNode(goog.dom.htmlToDocumentFragment(html)); - assertEquals('Html is not inserted correctly', html, - normalizeHtml(empty.innerHTML)); - goog.dom.removeChildren(empty); -} - -function testEmptyNode() { - var range = goog.dom.browserrange.createRangeFromNodeContents(empty); - - assertEquals('DIV be selected at start endpoint', 'DIV', - range.getStartNode().tagName); - assertEquals('Selection should start at offset 0', 0, - range.getStartOffset()); - - assertEquals('DIV should be selected at end endpoint', 'DIV', - range.getEndNode().tagName); - assertEquals('Selection should end at offset 0', 0, - range.getEndOffset()); - - assertEquals('Container should be DIV', 'DIV', - range.getContainer().tagName); - - assertEquals('Empty text content should be ""', '', range.getText()); - assertTrue('Empty range is collapsed', range.isCollapsed()); - assertEquals('Should contain correct valid html', '
    ', - normalizeHtml(range.getValidHtml())); - assertEquals('Should contain no html fragment', '', - range.getHtmlFragment()); -} - - -function testRemoveContents() { - var outer = goog.dom.getElement('removeTest'); - var range = goog.dom.browserrange.createRangeFromNodeContents( - outer.firstChild); - - range.removeContents(); - - assertEquals('Removed range content should be ""', '', range.getText()); - assertTrue('Removed range is now collapsed', range.isCollapsed()); - assertEquals('Outer div has 1 child now', 1, outer.childNodes.length); - assertEquals('Inner div is empty', 0, outer.firstChild.childNodes.length); -} - - -function testRemoveContentsEmptyNode() { - var outer = goog.dom.getElement('removeTestEmptyNode'); - var range = goog.dom.browserrange.createRangeFromNodeContents( - outer); - - range.removeContents(); - - assertEquals('Removed range content should be ""', '', range.getText()); - assertTrue('Removed range is now collapsed', range.isCollapsed()); - assertEquals('Outer div should have 0 children now', - 0, outer.childNodes.length); -} - - -function testRemoveContentsSingleNode() { - var outer = goog.dom.getElement('removeTestSingleNode'); - var range = goog.dom.browserrange.createRangeFromNodeContents( - outer.firstChild); - - range.removeContents(); - - assertEquals('Removed range content should be ""', '', range.getText()); - assertTrue('Removed range is now collapsed', range.isCollapsed()); - assertEquals('', goog.dom.getTextContent(outer)); -} - - -function testRemoveContentsMidNode() { - var outer = goog.dom.getElement('removeTestMidNode'); - var textNode = outer.firstChild.firstChild; - var range = goog.dom.browserrange.createRangeFromNodes( - textNode, 1, textNode, 4); - - assertEquals('Previous range content should be "123"', '123', - range.getText()); - range.removeContents(); - - assertEquals('Removed range content should be "0456789"', '0456789', - goog.dom.getTextContent(outer)); -} - - -function testRemoveContentsMidMultipleNodes() { - var outer = goog.dom.getElement('removeTestMidMultipleNodes'); - var firstTextNode = outer.firstChild.firstChild; - var lastTextNode = outer.lastChild.firstChild; - var range = goog.dom.browserrange.createRangeFromNodes( - firstTextNode, 1, lastTextNode, 4); - - assertEquals('Previous range content', '1234567890123', - range.getText().replace(/\s/g, '')); - range.removeContents(); - - assertEquals('Removed range content should be "0456789"', '0456789', - goog.dom.getTextContent(outer).replace(/\s/g, '')); -} - - -function testRemoveDivCaretRange() { - var outer = goog.dom.getElement('sandbox'); - outer.innerHTML = '
    Test1
    '; - var range = goog.dom.browserrange.createRangeFromNodes( - outer.lastChild, 0, outer.lastChild, 0); - - range.removeContents(); - range.insertNode(goog.dom.createDom('span', undefined, 'Hello'), true); - - assertEquals('Resulting contents', 'Test1Hello', - goog.dom.getTextContent(outer).replace(/\s/g, '')); -} - - -function testCollapse() { - var range = goog.dom.browserrange.createRangeFromNodeContents(test2); - assertFalse('Div range is not collapsed', range.isCollapsed()); - range.collapse(); - assertTrue('Div range is collapsed after call to empty()', - range.isCollapsed()); - - range = goog.dom.browserrange.createRangeFromNodeContents(empty); - assertTrue('Empty range is collapsed', range.isCollapsed()); - range.collapse(); - assertTrue('Empty range is still collapsed', range.isCollapsed()); -} - - -function testIdWithSpecialCharacters() { - goog.dom.removeChildren(dynamic); - dynamic.appendChild(goog.dom.createTextNode('1')); - dynamic.appendChild(goog.dom.createDom('div', {id: '<>'})); - dynamic.appendChild(goog.dom.createTextNode('2')); - var range = goog.dom.browserrange.createRangeFromNodes( - dynamic.firstChild, 0, dynamic.lastChild, 1); - - // Difference in special character handling is ok. - assertContains('Should have correct html fragment', - normalizeHtml(range.getHtmlFragment()), - [ - '1
    >
    2', // IE - '1
    >
    2', // WebKit - '1
    2' // Others - ]); -} - -function testEndOfChildren() { - dynamic.innerHTML = - '123
    456
    text'; - var range = goog.dom.browserrange.createRangeFromNodes( - goog.dom.getElement('a'), 3, goog.dom.getElement('b'), 1); - assertEquals('Should have correct text.', 'text', range.getText()); -} - -function testEndOfDiv() { - dynamic.innerHTML = '
    abc
    def
    '; - var a = goog.dom.getElement('a'); - var range = goog.dom.browserrange.createRangeFromNodes(a, 1, a, 1); - var expectedStartNode = a; - var expectedStartOffset = 1; - var expectedEndNode = a; - var expectedEndOffset = 1; - assertEquals('startNode is wrong', expectedStartNode, range.getStartNode()); - assertEquals('startOffset is wrong', - expectedStartOffset, range.getStartOffset()); - assertEquals('endNode is wrong', expectedEndNode, range.getEndNode()); - assertEquals('endOffset is wrong', expectedEndOffset, range.getEndOffset()); -} - -function testRangeEndingWithBR() { - dynamic.innerHTML = '123
    456
    '; - var spanElem = goog.dom.getElement('a'); - var range = goog.dom.browserrange.createRangeFromNodes( - spanElem, 0, spanElem, 2); - var htmlText = range.getValidHtml().toLowerCase(); - assertContains('Should include BR in HTML.', 'br', htmlText); - assertEquals('Should have correct text.', '123', range.getText()); - - range.select(); - - var selRange = goog.dom.Range.createFromWindow(); - var startNode = selRange.getStartNode(); - if (goog.userAgent.GECKO || - (goog.userAgent.IE && goog.userAgent.isDocumentModeOrHigher(9))) { - assertEquals('Start node should be span', spanElem, startNode); - } else { - assertEquals('Startnode should have text:123', - '123', startNode.nodeValue); - } - assertEquals('Startoffset should be 0', 0, selRange.getStartOffset()); - var endNode = selRange.getEndNode(); - assertEquals('Endnode should be span', spanElem, endNode); - assertEquals('Endoffset should be 2', 2, selRange.getEndOffset()); -} - -function testRangeEndingWithBR2() { - dynamic.innerHTML = '123
    '; - var spanElem = goog.dom.getElement('a'); - var range = goog.dom.browserrange.createRangeFromNodes( - spanElem, 0, spanElem, 2); - var htmlText = range.getValidHtml().toLowerCase(); - assertContains('Should include BR in HTML.', 'br', htmlText); - assertEquals('Should have correct text.', '123', range.getText()); - - range.select(); - - var selRange = goog.dom.Range.createFromWindow(); - var startNode = selRange.getStartNode(); - if (goog.userAgent.GECKO || - (goog.userAgent.IE && goog.userAgent.isDocumentModeOrHigher(9))) { - assertEquals('Start node should be span', spanElem, startNode); - } else { - assertEquals('Start node should have text:123', - '123', startNode.nodeValue); - } - assertEquals('Startoffset should be 0', 0, selRange.getStartOffset()); - var endNode = selRange.getEndNode(); - if (goog.userAgent.WEBKIT) { - assertEquals('Endnode should have text', '123', endNode.nodeValue); - assertEquals('Endoffset should be 3', 3, selRange.getEndOffset()); - } else { - assertEquals('Endnode should be span', spanElem, endNode); - assertEquals('Endoffset should be 2', 2, selRange.getEndOffset()); - } -} - -function testRangeEndingBeforeBR() { - dynamic.innerHTML = '123
    456
    '; - var spanElem = goog.dom.getElement('a'); - var range = goog.dom.browserrange.createRangeFromNodes( - spanElem, 0, spanElem, 1); - var htmlText = range.getValidHtml().toLowerCase(); - assertNotContains('Should not include BR in HTML.', 'br', htmlText); - assertEquals('Should have correct text.', '123', range.getText()); - range.select(); - - var selRange = goog.dom.Range.createFromWindow(); - var startNode = selRange.getStartNode(); - if (goog.userAgent.GECKO || - (goog.userAgent.IE && goog.userAgent.isDocumentModeOrHigher(9))) { - assertEquals('Start node should be span', spanElem, startNode); - } else { - assertEquals('Startnode should have text:123', - '123', startNode.nodeValue); - } - assertEquals('Startoffset should be 0', 0, selRange.getStartOffset()); - var endNode = selRange.getEndNode(); - if (goog.userAgent.GECKO || - (goog.userAgent.IE && goog.userAgent.isDocumentModeOrHigher(9))) { - assertEquals('Endnode should be span', spanElem, endNode); - assertEquals('Endoffset should be 1', 1, selRange.getEndOffset()); - } else { - assertEquals('Endnode should have text:123', '123', endNode.nodeValue); - assertEquals('Endoffset should be 3', 3, selRange.getEndOffset()); - } -} - -function testRangeStartingWithBR() { - dynamic.innerHTML = '123
    456
    '; - var spanElem = goog.dom.getElement('a'); - var range = goog.dom.browserrange.createRangeFromNodes( - spanElem, 1, spanElem, 3); - var htmlText = range.getValidHtml().toLowerCase(); - assertContains('Should include BR in HTML.', 'br', htmlText); - // Firefox returns '456' as the range text while IE returns '\r\n456'. - // Therefore skipping the text check. - - range.select(); - var selRange = goog.dom.Range.createFromWindow(); - var startNode = selRange.getStartNode(); - assertEquals('Start node should be span', spanElem, startNode); - assertEquals('Startoffset should be 1', 1, selRange.getStartOffset()); - var endNode = selRange.getEndNode(); - if (goog.userAgent.GECKO || - (goog.userAgent.IE && goog.userAgent.isDocumentModeOrHigher(9))) { - assertEquals('Endnode should be span', spanElem, endNode); - assertEquals('Endoffset should be 3', 3, selRange.getEndOffset()); - } else { - assertEquals('Endnode should have text:456', '456', endNode.nodeValue); - assertEquals('Endoffset should be 3', 3, selRange.getEndOffset()); - } -} - -function testRangeStartingAfterBR() { - dynamic.innerHTML = '123
    4567
    '; - var spanElem = goog.dom.getElement('a'); - var range = goog.dom.browserrange.createRangeFromNodes( - spanElem, 2, spanElem, 3); - var htmlText = range.getValidHtml().toLowerCase(); - assertNotContains('Should not include BR in HTML.', 'br', htmlText); - assertEquals('Should have correct text.', '4567', range.getText()); - - range.select(); - - var selRange = goog.dom.Range.createFromWindow(); - var startNode = selRange.getStartNode(); - if (goog.userAgent.GECKO || - (goog.userAgent.IE && goog.userAgent.isDocumentModeOrHigher(9))) { - assertEquals('Start node should be span', spanElem, startNode); - assertEquals('Startoffset should be 2', 2, selRange.getStartOffset()); - } else { - assertEquals('Startnode should have text:4567', - '4567', startNode.nodeValue); - assertEquals('Startoffset should be 0', 0, selRange.getStartOffset()); - } - var endNode = selRange.getEndNode(); - if (goog.userAgent.GECKO || - (goog.userAgent.IE && goog.userAgent.isDocumentModeOrHigher(9))) { - assertEquals('Endnode should be span', spanElem, endNode); - assertEquals('Endoffset should be 3', 3, selRange.getEndOffset()); - } else { - assertEquals('Endnode should have text:4567', '4567', endNode.nodeValue); - assertEquals('Endoffset should be 4', 4, selRange.getEndOffset()); - } - -} - -function testCollapsedRangeBeforeBR() { - dynamic.innerHTML = '123
    456
    '; - var range = goog.dom.browserrange.createRangeFromNodes( - goog.dom.getElement('a'), 1, goog.dom.getElement('a'), 1); - // Firefox returns as the range HTML while IE returns - // empty string. Therefore skipping the HTML check. - assertEquals('Should have no text.', '', range.getText()); -} - -function testCollapsedRangeAfterBR() { - dynamic.innerHTML = '123
    456
    '; - var range = goog.dom.browserrange.createRangeFromNodes( - goog.dom.getElement('a'), 2, goog.dom.getElement('a'), 2); - // Firefox returns as the range HTML while IE returns - // empty string. Therefore skipping the HTML check. - assertEquals('Should have no text.', '', range.getText()); -} - -function testCompareBrowserRangeEndpoints() { - var outer = goog.dom.getElement('outer'); - var inner = goog.dom.getElement('inner'); - var range_outer = goog.dom.browserrange.createRangeFromNodeContents(outer); - var range_inner = goog.dom.browserrange.createRangeFromNodeContents(inner); - - assertEquals( - 'The start of the inner selection should be after the outer.', - 1, - range_inner.compareBrowserRangeEndpoints( - range_outer.getBrowserRange(), - goog.dom.RangeEndpoint.START, - goog.dom.RangeEndpoint.START)); - - assertEquals( - "The start of the inner selection should be before the outer's end.", - -1, - range_inner.compareBrowserRangeEndpoints( - range_outer.getBrowserRange(), - goog.dom.RangeEndpoint.START, - goog.dom.RangeEndpoint.END)); - - assertEquals( - "The end of the inner selection should be after the outer's start.", - 1, - range_inner.compareBrowserRangeEndpoints( - range_outer.getBrowserRange(), - goog.dom.RangeEndpoint.END, - goog.dom.RangeEndpoint.START)); - - assertEquals( - "The end of the inner selection should be before the outer's end.", - -1, - range_inner.compareBrowserRangeEndpoints( - range_outer.getBrowserRange(), - goog.dom.RangeEndpoint.END, - goog.dom.RangeEndpoint.END)); - -} - - -/** - * Regression test for a bug in IeRange.insertNode_ where if the node to be - * inserted was not an element (e.g. a text node), it would clone the node - * in the inserting process but return the original node instead of the newly - * created and inserted node. - */ -function testInsertNodeNonElement() { - dynamic.innerHTML = 'beforeafter'; - var range = goog.dom.browserrange.createRangeFromNodes( - dynamic.firstChild, 6, dynamic.firstChild, 6); - var newNode = goog.dom.createTextNode('INSERTED'); - var inserted = range.insertNode(newNode, false); - - assertEquals('Text should be inserted between "before" and "after"', - 'beforeINSERTEDafter', - goog.dom.getRawTextContent(dynamic)); - assertEquals('Node returned by insertNode() should be a child of the div' + - ' containing the text', - dynamic, - inserted.parentNode); -} - -function testSelectOverwritesOldSelection() { - goog.dom.browserrange.createRangeFromNodes(test1, 0, test1, 1).select(); - goog.dom.browserrange.createRangeFromNodes(test2, 0, test2, 1).select(); - assertEquals('The old selection must be replaced with the new one', - 'abc', goog.dom.Range.createFromWindow().getText()); -} - -// Following testcase is special for IE. The comparison of ranges created in -// testcases with a range over empty span using native inRange fails. So the -// fallback mechanism is needed. -function testGetContainerInTextNodesAroundEmptySpan() { - dynamic.innerHTML = 'abcdef'; - var abc = dynamic.firstChild; - var def = dynamic.lastChild; - - var range; - range = goog.dom.browserrange.createRangeFromNodes(abc, 1, abc, 1); - assertEquals('textNode abc should be the range container', - abc, range.getContainer()); - assertEquals('textNode abc should be the range start node', - abc, range.getStartNode()); - assertEquals('textNode abc should be the range end node', - abc, range.getEndNode()); - - range = goog.dom.browserrange.createRangeFromNodes(def, 1, def, 1); - assertEquals('textNode def should be the range container', - def, range.getContainer()); - assertEquals('textNode def should be the range start node', - def, range.getStartNode()); - assertEquals('textNode def should be the range end node', - def, range.getEndNode()); -} diff --git a/src/database/third_party/closure-library/closure/goog/dom/browserrange/geckorange.js b/src/database/third_party/closure-library/closure/goog/dom/browserrange/geckorange.js deleted file mode 100644 index b01f2dd4368..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/browserrange/geckorange.js +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Definition of the Gecko specific range wrapper. Inherits most - * functionality from W3CRange, but adds exceptions as necessary. - * - * DO NOT USE THIS FILE DIRECTLY. Use goog.dom.Range instead. - * - * @author robbyw@google.com (Robby Walker) - */ - - -goog.provide('goog.dom.browserrange.GeckoRange'); - -goog.require('goog.dom.browserrange.W3cRange'); - - - -/** - * The constructor for Gecko specific browser ranges. - * @param {Range} range The range object. - * @constructor - * @extends {goog.dom.browserrange.W3cRange} - * @final - */ -goog.dom.browserrange.GeckoRange = function(range) { - goog.dom.browserrange.W3cRange.call(this, range); -}; -goog.inherits(goog.dom.browserrange.GeckoRange, goog.dom.browserrange.W3cRange); - - -/** - * Creates a range object that selects the given node's text. - * @param {Node} node The node to select. - * @return {!goog.dom.browserrange.GeckoRange} A Gecko range wrapper object. - */ -goog.dom.browserrange.GeckoRange.createFromNodeContents = function(node) { - return new goog.dom.browserrange.GeckoRange( - goog.dom.browserrange.W3cRange.getBrowserRangeForNode(node)); -}; - - -/** - * Creates a range object that selects between the given nodes. - * @param {Node} startNode The node to start with. - * @param {number} startOffset The offset within the node to start. - * @param {Node} endNode The node to end with. - * @param {number} endOffset The offset within the node to end. - * @return {!goog.dom.browserrange.GeckoRange} A wrapper object. - */ -goog.dom.browserrange.GeckoRange.createFromNodes = function(startNode, - startOffset, endNode, endOffset) { - return new goog.dom.browserrange.GeckoRange( - goog.dom.browserrange.W3cRange.getBrowserRangeForNodes(startNode, - startOffset, endNode, endOffset)); -}; - - -/** @override */ -goog.dom.browserrange.GeckoRange.prototype.selectInternal = function( - selection, reversed) { - if (!reversed || this.isCollapsed()) { - // The base implementation for select() is more robust, and works fine for - // collapsed and forward ranges. This works around - // https://bugzilla.mozilla.org/show_bug.cgi?id=773137, and is tested by - // range_test.html's testFocusedElementDisappears. - goog.dom.browserrange.GeckoRange.base( - this, 'selectInternal', selection, reversed); - } else { - // Reversed selection -- start with a caret on the end node, and extend it - // back to the start. Unfortunately, collapse() fails when focus is - // invalid. - selection.collapse(this.getEndNode(), this.getEndOffset()); - selection.extend(this.getStartNode(), this.getStartOffset()); - } -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/browserrange/ierange.js b/src/database/third_party/closure-library/closure/goog/dom/browserrange/ierange.js deleted file mode 100644 index 00e6bba2eeb..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/browserrange/ierange.js +++ /dev/null @@ -1,951 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Definition of the IE browser specific range wrapper. - * - * DO NOT USE THIS FILE DIRECTLY. Use goog.dom.Range instead. - * - * @author robbyw@google.com (Robby Walker) - */ - - -goog.provide('goog.dom.browserrange.IeRange'); - -goog.require('goog.array'); -goog.require('goog.dom'); -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.RangeEndpoint'); -goog.require('goog.dom.TagName'); -goog.require('goog.dom.browserrange.AbstractRange'); -goog.require('goog.log'); -goog.require('goog.string'); - - - -/** - * The constructor for IE specific browser ranges. - * @param {TextRange} range The range object. - * @param {Document} doc The document the range exists in. - * @constructor - * @extends {goog.dom.browserrange.AbstractRange} - * @final - */ -goog.dom.browserrange.IeRange = function(range, doc) { - /** - * The browser range object this class wraps. - * @type {TextRange} - * @private - */ - this.range_ = range; - - /** - * The document the range exists in. - * @type {Document} - * @private - */ - this.doc_ = doc; -}; -goog.inherits(goog.dom.browserrange.IeRange, - goog.dom.browserrange.AbstractRange); - - -/** - * Logging object. - * @type {goog.log.Logger} - * @private - */ -goog.dom.browserrange.IeRange.logger_ = - goog.log.getLogger('goog.dom.browserrange.IeRange'); - - -/** - * Returns a browser range spanning the given node's contents. - * @param {Node} node The node to select. - * @return {!TextRange} A browser range spanning the node's contents. - * @private - */ -goog.dom.browserrange.IeRange.getBrowserRangeForNode_ = function(node) { - var nodeRange = goog.dom.getOwnerDocument(node).body.createTextRange(); - if (node.nodeType == goog.dom.NodeType.ELEMENT) { - // Elements are easy. - nodeRange.moveToElementText(node); - // Note(user) : If there are no child nodes of the element, the - // range.htmlText includes the element's outerHTML. The range created above - // is not collapsed, and should be collapsed explicitly. - // Example : node =
    - // But if the node is sth like
    , it shouldnt be collapsed. - if (goog.dom.browserrange.canContainRangeEndpoint(node) && - !node.childNodes.length) { - nodeRange.collapse(false); - } - } else { - // Text nodes are hard. - // Compute the offset from the nearest element related position. - var offset = 0; - var sibling = node; - while (sibling = sibling.previousSibling) { - var nodeType = sibling.nodeType; - if (nodeType == goog.dom.NodeType.TEXT) { - offset += sibling.length; - } else if (nodeType == goog.dom.NodeType.ELEMENT) { - // Move to the space after this element. - nodeRange.moveToElementText(sibling); - break; - } - } - - if (!sibling) { - nodeRange.moveToElementText(node.parentNode); - } - - nodeRange.collapse(!sibling); - - if (offset) { - nodeRange.move('character', offset); - } - - nodeRange.moveEnd('character', node.length); - } - - return nodeRange; -}; - - -/** - * Returns a browser range spanning the given nodes. - * @param {Node} startNode The node to start with. - * @param {number} startOffset The offset within the start node. - * @param {Node} endNode The node to end with. - * @param {number} endOffset The offset within the end node. - * @return {!TextRange} A browser range spanning the node's contents. - * @private - */ -goog.dom.browserrange.IeRange.getBrowserRangeForNodes_ = function(startNode, - startOffset, endNode, endOffset) { - // Create a range starting at the correct start position. - var child, collapse = false; - if (startNode.nodeType == goog.dom.NodeType.ELEMENT) { - if (startOffset > startNode.childNodes.length) { - goog.log.error(goog.dom.browserrange.IeRange.logger_, - 'Cannot have startOffset > startNode child count'); - } - child = startNode.childNodes[startOffset]; - collapse = !child; - startNode = child || startNode.lastChild || startNode; - startOffset = 0; - } - var leftRange = goog.dom.browserrange.IeRange. - getBrowserRangeForNode_(startNode); - - // This happens only when startNode is a text node. - if (startOffset) { - leftRange.move('character', startOffset); - } - - - // The range movements in IE are still an approximation to the standard W3C - // behavior, and IE has its trickery when it comes to htmlText and text - // properties of the range. So we short-circuit computation whenever we can. - if (startNode == endNode && startOffset == endOffset) { - leftRange.collapse(true); - return leftRange; - } - - // This can happen only when the startNode is an element, and there is no node - // at the given offset. We start at the last point inside the startNode in - // that case. - if (collapse) { - leftRange.collapse(false); - } - - // Create a range that ends at the right position. - collapse = false; - if (endNode.nodeType == goog.dom.NodeType.ELEMENT) { - if (endOffset > endNode.childNodes.length) { - goog.log.error(goog.dom.browserrange.IeRange.logger_, - 'Cannot have endOffset > endNode child count'); - } - child = endNode.childNodes[endOffset]; - endNode = child || endNode.lastChild || endNode; - endOffset = 0; - collapse = !child; - } - var rightRange = goog.dom.browserrange.IeRange. - getBrowserRangeForNode_(endNode); - rightRange.collapse(!collapse); - if (endOffset) { - rightRange.moveEnd('character', endOffset); - } - - // Merge and return. - leftRange.setEndPoint('EndToEnd', rightRange); - return leftRange; -}; - - -/** - * Create a range object that selects the given node's text. - * @param {Node} node The node to select. - * @return {!goog.dom.browserrange.IeRange} An IE range wrapper object. - */ -goog.dom.browserrange.IeRange.createFromNodeContents = function(node) { - var range = new goog.dom.browserrange.IeRange( - goog.dom.browserrange.IeRange.getBrowserRangeForNode_(node), - goog.dom.getOwnerDocument(node)); - - if (!goog.dom.browserrange.canContainRangeEndpoint(node)) { - range.startNode_ = range.endNode_ = range.parentNode_ = node.parentNode; - range.startOffset_ = goog.array.indexOf(range.parentNode_.childNodes, node); - range.endOffset_ = range.startOffset_ + 1; - } else { - // Note(user) : Emulate the behavior of W3CRange - Go to deepest possible - // range containers on both edges. It seems W3CRange did this to match the - // IE behavior, and now it is a circle. Changing W3CRange may break clients - // in all sorts of ways. - var tempNode, leaf = node; - while ((tempNode = leaf.firstChild) && - goog.dom.browserrange.canContainRangeEndpoint(tempNode)) { - leaf = tempNode; - } - range.startNode_ = leaf; - range.startOffset_ = 0; - - leaf = node; - while ((tempNode = leaf.lastChild) && - goog.dom.browserrange.canContainRangeEndpoint(tempNode)) { - leaf = tempNode; - } - range.endNode_ = leaf; - range.endOffset_ = leaf.nodeType == goog.dom.NodeType.ELEMENT ? - leaf.childNodes.length : leaf.length; - range.parentNode_ = node; - } - return range; -}; - - -/** - * Static method that returns the proper type of browser range. - * @param {Node} startNode The node to start with. - * @param {number} startOffset The offset within the start node. - * @param {Node} endNode The node to end with. - * @param {number} endOffset The offset within the end node. - * @return {!goog.dom.browserrange.AbstractRange} A wrapper object. - */ -goog.dom.browserrange.IeRange.createFromNodes = function(startNode, - startOffset, endNode, endOffset) { - var range = new goog.dom.browserrange.IeRange( - goog.dom.browserrange.IeRange.getBrowserRangeForNodes_(startNode, - startOffset, endNode, endOffset), - goog.dom.getOwnerDocument(startNode)); - range.startNode_ = startNode; - range.startOffset_ = startOffset; - range.endNode_ = endNode; - range.endOffset_ = endOffset; - return range; -}; - - -// Even though goog.dom.TextRange does similar caching to below, keeping these -// caches allows for better performance in the get*Offset methods. - - -/** - * Lazy cache of the node containing the entire selection. - * @type {Node} - * @private - */ -goog.dom.browserrange.IeRange.prototype.parentNode_ = null; - - -/** - * Lazy cache of the node containing the start of the selection. - * @type {Node} - * @private - */ -goog.dom.browserrange.IeRange.prototype.startNode_ = null; - - -/** - * Lazy cache of the node containing the end of the selection. - * @type {Node} - * @private - */ -goog.dom.browserrange.IeRange.prototype.endNode_ = null; - - -/** - * Lazy cache of the offset in startNode_ where this range starts. - * @type {number} - * @private - */ -goog.dom.browserrange.IeRange.prototype.startOffset_ = -1; - - -/** - * Lazy cache of the offset in endNode_ where this range ends. - * @type {number} - * @private - */ -goog.dom.browserrange.IeRange.prototype.endOffset_ = -1; - - -/** - * @return {!goog.dom.browserrange.IeRange} A clone of this range. - * @override - */ -goog.dom.browserrange.IeRange.prototype.clone = function() { - var range = new goog.dom.browserrange.IeRange( - this.range_.duplicate(), this.doc_); - range.parentNode_ = this.parentNode_; - range.startNode_ = this.startNode_; - range.endNode_ = this.endNode_; - return range; -}; - - -/** @override */ -goog.dom.browserrange.IeRange.prototype.getBrowserRange = function() { - return this.range_; -}; - - -/** - * Clears the cached values for containers. - * @private - */ -goog.dom.browserrange.IeRange.prototype.clearCachedValues_ = function() { - this.parentNode_ = this.startNode_ = this.endNode_ = null; - this.startOffset_ = this.endOffset_ = -1; -}; - - -/** @override */ -goog.dom.browserrange.IeRange.prototype.getContainer = function() { - if (!this.parentNode_) { - var selectText = this.range_.text; - - // If the selection ends with spaces, we need to remove these to get the - // parent container of only the real contents. This is to get around IE's - // inconsistency where it selects the spaces after a word when you double - // click, but leaves out the spaces during execCommands. - var range = this.range_.duplicate(); - // We can't use goog.string.trimRight, as that will remove other whitespace - // too. - var rightTrimmedSelectText = selectText.replace(/ +$/, ''); - var numSpacesAtEnd = selectText.length - rightTrimmedSelectText.length; - if (numSpacesAtEnd) { - range.moveEnd('character', -numSpacesAtEnd); - } - - // Get the parent node. This should be the end, but alas, it is not. - var parent = range.parentElement(); - - var htmlText = range.htmlText; - var htmlTextLen = goog.string.stripNewlines(htmlText).length; - if (this.isCollapsed() && htmlTextLen > 0) { - return (this.parentNode_ = parent); - } - - // Deal with selection bug where IE thinks one of the selection's children - // is actually the selection's parent. Relies on the assumption that the - // HTML text of the parent container is longer than the length of the - // selection's HTML text. - - // Also note IE will sometimes insert \r and \n whitespace, which should be - // disregarded. Otherwise the loop may run too long and return wrong parent - while (htmlTextLen > goog.string.stripNewlines(parent.outerHTML).length) { - parent = parent.parentNode; - } - - // Deal with IE's selecting the outer tags when you double click - // If the innerText is the same, then we just want the inner node - while (parent.childNodes.length == 1 && - parent.innerText == goog.dom.browserrange.IeRange.getNodeText_( - parent.firstChild)) { - // A container should be an element which can have children or a text - // node. Elements like IMG, BR, etc. can not be containers. - if (!goog.dom.browserrange.canContainRangeEndpoint(parent.firstChild)) { - break; - } - parent = parent.firstChild; - } - - // If the selection is empty, we may need to do extra work to position it - // properly. - if (selectText.length == 0) { - parent = this.findDeepestContainer_(parent); - } - - this.parentNode_ = parent; - } - - return this.parentNode_; -}; - - -/** - * Helper method to find the deepest parent for this range, starting - * the search from {@code node}, which must contain the range. - * @param {Node} node The node to start the search from. - * @return {Node} The deepest parent for this range. - * @private - */ -goog.dom.browserrange.IeRange.prototype.findDeepestContainer_ = function(node) { - var childNodes = node.childNodes; - for (var i = 0, len = childNodes.length; i < len; i++) { - var child = childNodes[i]; - - if (goog.dom.browserrange.canContainRangeEndpoint(child)) { - var childRange = - goog.dom.browserrange.IeRange.getBrowserRangeForNode_(child); - var start = goog.dom.RangeEndpoint.START; - var end = goog.dom.RangeEndpoint.END; - - // There are two types of erratic nodes where the range over node has - // different htmlText than the node's outerHTML. - // Case 1 - A node with magic   child. In this case : - // nodeRange.htmlText shows   ('

     

    ), while - // node.outerHTML doesn't show the magic node (

    ). - // Case 2 - Empty span. In this case : - // node.outerHTML shows '' - // node.htmlText is just empty string ''. - var isChildRangeErratic = (childRange.htmlText != child.outerHTML); - - // Moreover the inRange comparison fails only when the - var isNativeInRangeErratic = this.isCollapsed() && isChildRangeErratic; - - // In case 2 mentioned above, childRange is also collapsed. So we need to - // compare start of this range with both start and end of child range. - var inChildRange = isNativeInRangeErratic ? - (this.compareBrowserRangeEndpoints(childRange, start, start) >= 0 && - this.compareBrowserRangeEndpoints(childRange, start, end) <= 0) : - this.range_.inRange(childRange); - if (inChildRange) { - return this.findDeepestContainer_(child); - } - } - } - - return node; -}; - - -/** @override */ -goog.dom.browserrange.IeRange.prototype.getStartNode = function() { - if (!this.startNode_) { - this.startNode_ = this.getEndpointNode_(goog.dom.RangeEndpoint.START); - if (this.isCollapsed()) { - this.endNode_ = this.startNode_; - } - } - return this.startNode_; -}; - - -/** @override */ -goog.dom.browserrange.IeRange.prototype.getStartOffset = function() { - if (this.startOffset_ < 0) { - this.startOffset_ = this.getOffset_(goog.dom.RangeEndpoint.START); - if (this.isCollapsed()) { - this.endOffset_ = this.startOffset_; - } - } - return this.startOffset_; -}; - - -/** @override */ -goog.dom.browserrange.IeRange.prototype.getEndNode = function() { - if (this.isCollapsed()) { - return this.getStartNode(); - } - if (!this.endNode_) { - this.endNode_ = this.getEndpointNode_(goog.dom.RangeEndpoint.END); - } - return this.endNode_; -}; - - -/** @override */ -goog.dom.browserrange.IeRange.prototype.getEndOffset = function() { - if (this.isCollapsed()) { - return this.getStartOffset(); - } - if (this.endOffset_ < 0) { - this.endOffset_ = this.getOffset_(goog.dom.RangeEndpoint.END); - if (this.isCollapsed()) { - this.startOffset_ = this.endOffset_; - } - } - return this.endOffset_; -}; - - -/** @override */ -goog.dom.browserrange.IeRange.prototype.compareBrowserRangeEndpoints = function( - range, thisEndpoint, otherEndpoint) { - return this.range_.compareEndPoints( - (thisEndpoint == goog.dom.RangeEndpoint.START ? 'Start' : 'End') + - 'To' + - (otherEndpoint == goog.dom.RangeEndpoint.START ? 'Start' : 'End'), - range); -}; - - -/** - * Recurses to find the correct node for the given endpoint. - * @param {goog.dom.RangeEndpoint} endpoint The endpoint to get the node for. - * @param {Node=} opt_node Optional node to start the search from. - * @return {Node} The deepest node containing the endpoint. - * @private - */ -goog.dom.browserrange.IeRange.prototype.getEndpointNode_ = function(endpoint, - opt_node) { - - /** @type {Node} */ - var node = opt_node || this.getContainer(); - - // If we're at a leaf in the DOM, we're done. - if (!node || !node.firstChild) { - return node; - } - - var start = goog.dom.RangeEndpoint.START, end = goog.dom.RangeEndpoint.END; - var isStartEndpoint = endpoint == start; - - // Find the first/last child that overlaps the selection. - // NOTE(user) : One of the children can be the magic   node. This - // node will have only nodeType property as valid and accessible. All other - // dom related properties like ownerDocument, parentNode, nextSibling etc - // cause error when accessed. Therefore use the for-loop on childNodes to - // iterate. - for (var j = 0, length = node.childNodes.length; j < length; j++) { - var i = isStartEndpoint ? j : length - j - 1; - var child = node.childNodes[i]; - var childRange; - try { - childRange = goog.dom.browserrange.createRangeFromNodeContents(child); - } catch (e) { - // If the child is the magic   node, then the above will throw - // error. The magic node exists only when editing using keyboard, so can - // not add any unit test. - continue; - } - var ieRange = childRange.getBrowserRange(); - - // Case 1 : Finding end points when this range is collapsed. - // Note that in case of collapsed range, getEnd{Node,Offset} call - // getStart{Node,Offset}. - if (this.isCollapsed()) { - // Handle situations where caret is not in a text node. In such cases, - // the adjacent child won't be a valid range endpoint container. - if (!goog.dom.browserrange.canContainRangeEndpoint(child)) { - // The following handles a scenario like

    [caret]
    , - // where point should be (div, 1). - if (this.compareBrowserRangeEndpoints(ieRange, start, start) == 0) { - this.startOffset_ = this.endOffset_ = i; - return node; - } - } else if (childRange.containsRange(this)) { - // For collapsed range, we should invert the containsRange check with - // childRange. - return this.getEndpointNode_(endpoint, child); - } - - // Case 2 - The first child encountered to have overlap this range is - // contained entirely in this range. - } else if (this.containsRange(childRange)) { - // If it is an element which can not be a range endpoint container, the - // current child offset can be used to deduce the endpoint offset. - if (!goog.dom.browserrange.canContainRangeEndpoint(child)) { - - // Container can't be any deeper, so current node is the container. - if (isStartEndpoint) { - this.startOffset_ = i; - } else { - this.endOffset_ = i + 1; - } - return node; - } - - // If child can contain range endpoints, recurse inside this child. - return this.getEndpointNode_(endpoint, child); - - // Case 3 - Partial non-adjacency overlap. - } else if (this.compareBrowserRangeEndpoints(ieRange, start, end) < 0 && - this.compareBrowserRangeEndpoints(ieRange, end, start) > 0) { - // If this child overlaps the selection partially, recurse down to find - // the first/last child the next level down that overlaps the selection - // completely. We do not consider edge-adjacency (== 0) as overlap. - return this.getEndpointNode_(endpoint, child); - } - - } - - // None of the children of this node overlapped the selection, that means - // the selection starts/ends in this node directly. - return node; -}; - - -/** - * Compares one endpoint of this range with the endpoint of a node. - * For internal methods, we should prefer this method to containsNode. - * containsNode has a lot of false negatives when we're dealing with - * {@code
    } tags. - * - * @param {Node} node The node to compare against. - * @param {goog.dom.RangeEndpoint} thisEndpoint The endpoint of this range - * to compare with. - * @param {goog.dom.RangeEndpoint} otherEndpoint The endpoint of the node - * to compare with. - * @return {number} 0 if the endpoints are equal, negative if this range - * endpoint comes before the other node endpoint, and positive otherwise. - * @private - */ -goog.dom.browserrange.IeRange.prototype.compareNodeEndpoints_ = - function(node, thisEndpoint, otherEndpoint) { - return this.range_.compareEndPoints( - (thisEndpoint == goog.dom.RangeEndpoint.START ? 'Start' : 'End') + - 'To' + - (otherEndpoint == goog.dom.RangeEndpoint.START ? 'Start' : 'End'), - goog.dom.browserrange.createRangeFromNodeContents(node). - getBrowserRange()); -}; - - -/** - * Returns the offset into the start/end container. - * @param {goog.dom.RangeEndpoint} endpoint The endpoint to get the offset for. - * @param {Node=} opt_container The container to get the offset relative to. - * Defaults to the value returned by getStartNode/getEndNode. - * @return {number} The offset. - * @private - */ -goog.dom.browserrange.IeRange.prototype.getOffset_ = function(endpoint, - opt_container) { - var isStartEndpoint = endpoint == goog.dom.RangeEndpoint.START; - var container = opt_container || - (isStartEndpoint ? this.getStartNode() : this.getEndNode()); - - if (container.nodeType == goog.dom.NodeType.ELEMENT) { - // Find the first/last child that overlaps the selection - var children = container.childNodes; - var len = children.length; - var edge = isStartEndpoint ? 0 : len - 1; - var sign = isStartEndpoint ? 1 : - 1; - - // We find the index in the child array of the endpoint of the selection. - for (var i = edge; i >= 0 && i < len; i += sign) { - var child = children[i]; - // Ignore the child nodes, which could be end point containers. - if (goog.dom.browserrange.canContainRangeEndpoint(child)) { - continue; - } - // Stop looping when we reach the edge of the selection. - var endPointCompare = - this.compareNodeEndpoints_(child, endpoint, endpoint); - if (endPointCompare == 0) { - return isStartEndpoint ? i : i + 1; - } - } - - // When starting from the end in an empty container, we erroneously return - // -1: fix this to return 0. - return i == -1 ? 0 : i; - } else { - // Get a temporary range object. - var range = this.range_.duplicate(); - - // Create a range that selects the entire container. - var nodeRange = goog.dom.browserrange.IeRange.getBrowserRangeForNode_( - container); - - // Now, intersect our range with the container range - this should give us - // the part of our selection that is in the container. - range.setEndPoint(isStartEndpoint ? 'EndToEnd' : 'StartToStart', nodeRange); - - var rangeLength = range.text.length; - return isStartEndpoint ? container.length - rangeLength : rangeLength; - } -}; - - -/** - * Returns the text of the given node. Uses IE specific properties. - * @param {Node} node The node to retrieve the text of. - * @return {string} The node's text. - * @private - */ -goog.dom.browserrange.IeRange.getNodeText_ = function(node) { - return node.nodeType == goog.dom.NodeType.TEXT ? - node.nodeValue : node.innerText; -}; - - -/** - * Tests whether this range is valid (i.e. whether its endpoints are still in - * the document). A range becomes invalid when, after this object was created, - * either one or both of its endpoints are removed from the document. Use of - * an invalid range can lead to runtime errors, particularly in IE. - * @return {boolean} Whether the range is valid. - */ -goog.dom.browserrange.IeRange.prototype.isRangeInDocument = function() { - var range = this.doc_.body.createTextRange(); - range.moveToElementText(this.doc_.body); - - return this.containsRange( - new goog.dom.browserrange.IeRange(range, this.doc_), true); -}; - - -/** @override */ -goog.dom.browserrange.IeRange.prototype.isCollapsed = function() { - // Note(user) : The earlier implementation used (range.text == ''), but this - // fails when (range.htmlText == '
    ') - // Alternative: this.range_.htmlText == ''; - return this.range_.compareEndPoints('StartToEnd', this.range_) == 0; -}; - - -/** @override */ -goog.dom.browserrange.IeRange.prototype.getText = function() { - return this.range_.text; -}; - - -/** @override */ -goog.dom.browserrange.IeRange.prototype.getValidHtml = function() { - return this.range_.htmlText; -}; - - -// SELECTION MODIFICATION - - -/** @override */ -goog.dom.browserrange.IeRange.prototype.select = function(opt_reverse) { - // IE doesn't support programmatic reversed selections. - this.range_.select(); -}; - - -/** @override */ -goog.dom.browserrange.IeRange.prototype.removeContents = function() { - // NOTE: Sometimes htmlText is non-empty, but the range is actually empty. - // TODO(gboyer): The htmlText check is probably unnecessary, but I left it in - // for paranoia. - if (!this.isCollapsed() && this.range_.htmlText) { - // Store some before-removal state. - var startNode = this.getStartNode(); - var endNode = this.getEndNode(); - var oldText = this.range_.text; - - // IE sometimes deletes nodes unrelated to the selection. This trick fixes - // that problem most of the time. Even though it looks like a no-op, it is - // somehow changing IE's internal state such that empty unrelated nodes are - // no longer deleted. - var clone = this.range_.duplicate(); - clone.moveStart('character', 1); - clone.moveStart('character', -1); - - // However, sometimes moving the start back and forth ends up changing the - // range. - // TODO(gboyer): This condition used to happen for empty ranges, but (1) - // never worked, and (2) the isCollapsed call should protect against empty - // ranges better than before. However, this is left for paranoia. - if (clone.text == oldText) { - this.range_ = clone; - } - - // Use the browser's native deletion code. - this.range_.text = ''; - this.clearCachedValues_(); - - // Unfortunately, when deleting a portion of a single text node, IE creates - // an extra text node unlike other browsers which just change the text in - // the node. We normalize for that behavior here, making IE behave like all - // the other browsers. - var newStartNode = this.getStartNode(); - var newStartOffset = this.getStartOffset(); - /** @preserveTry */ - try { - var sibling = startNode.nextSibling; - if (startNode == endNode && startNode.parentNode && - startNode.nodeType == goog.dom.NodeType.TEXT && - sibling && sibling.nodeType == goog.dom.NodeType.TEXT) { - startNode.nodeValue += sibling.nodeValue; - goog.dom.removeNode(sibling); - - // Make sure to reselect the appropriate position. - this.range_ = goog.dom.browserrange.IeRange.getBrowserRangeForNode_( - newStartNode); - this.range_.move('character', newStartOffset); - this.clearCachedValues_(); - } - } catch (e) { - // IE throws errors on orphaned nodes. - } - } -}; - - -/** - * @param {TextRange} range The range to get a dom helper for. - * @return {!goog.dom.DomHelper} A dom helper for the document the range - * resides in. - * @private - */ -goog.dom.browserrange.IeRange.getDomHelper_ = function(range) { - return goog.dom.getDomHelper(range.parentElement()); -}; - - -/** - * Pastes the given element into the given range, returning the resulting - * element. - * @param {TextRange} range The range to paste into. - * @param {Element} element The node to insert a copy of. - * @param {goog.dom.DomHelper=} opt_domHelper DOM helper object for the document - * the range resides in. - * @return {Element} The resulting copy of element. - * @private - */ -goog.dom.browserrange.IeRange.pasteElement_ = function(range, element, - opt_domHelper) { - opt_domHelper = opt_domHelper || goog.dom.browserrange.IeRange.getDomHelper_( - range); - - // Make sure the node has a unique id. - var id; - var originalId = id = element.id; - if (!id) { - id = element.id = goog.string.createUniqueString(); - } - - // Insert (a clone of) the node. - range.pasteHTML(element.outerHTML); - - // Pasting the outerHTML of the modified element into the document creates - // a clone of the element argument. We want to return a reference to the - // clone, not the original. However we need to remove the temporary ID - // first. - element = opt_domHelper.getElement(id); - - // If element is null here, we failed. - if (element) { - if (!originalId) { - element.removeAttribute('id'); - } - } - - return element; -}; - - -/** @override */ -goog.dom.browserrange.IeRange.prototype.surroundContents = function(element) { - // Make sure the element is detached from the document. - goog.dom.removeNode(element); - - // IE more or less guarantees that range.htmlText is well-formed & valid. - element.innerHTML = this.range_.htmlText; - element = goog.dom.browserrange.IeRange.pasteElement_(this.range_, element); - - // If element is null here, we failed. - if (element) { - this.range_.moveToElementText(element); - } - - this.clearCachedValues_(); - - return element; -}; - - -/** - * Internal handler for inserting a node. - * @param {TextRange} clone A clone of this range's browser range object. - * @param {Node} node The node to insert. - * @param {boolean} before Whether to insert the node before or after the range. - * @param {goog.dom.DomHelper=} opt_domHelper The dom helper to use. - * @return {Node} The resulting copy of node. - * @private - */ -goog.dom.browserrange.IeRange.insertNode_ = function(clone, node, - before, opt_domHelper) { - // Get a DOM helper. - opt_domHelper = opt_domHelper || goog.dom.browserrange.IeRange.getDomHelper_( - clone); - - // If it's not an element, wrap it in one. - var isNonElement; - if (node.nodeType != goog.dom.NodeType.ELEMENT) { - isNonElement = true; - node = opt_domHelper.createDom(goog.dom.TagName.DIV, null, node); - } - - clone.collapse(before); - node = goog.dom.browserrange.IeRange.pasteElement_(clone, - /** @type {!Element} */ (node), opt_domHelper); - - // If we didn't want an element, unwrap the element and return the node. - if (isNonElement) { - // pasteElement_() may have returned a copy of the wrapper div, and the - // node it wraps could also be a new copy. So we must extract that new - // node from the new wrapper. - var newNonElement = node.firstChild; - opt_domHelper.flattenElement(node); - node = newNonElement; - } - - return node; -}; - - -/** @override */ -goog.dom.browserrange.IeRange.prototype.insertNode = function(node, before) { - var output = goog.dom.browserrange.IeRange.insertNode_( - this.range_.duplicate(), node, before); - this.clearCachedValues_(); - return output; -}; - - -/** @override */ -goog.dom.browserrange.IeRange.prototype.surroundWithNodes = function( - startNode, endNode) { - var clone1 = this.range_.duplicate(); - var clone2 = this.range_.duplicate(); - goog.dom.browserrange.IeRange.insertNode_(clone1, startNode, true); - goog.dom.browserrange.IeRange.insertNode_(clone2, endNode, false); - - this.clearCachedValues_(); -}; - - -/** @override */ -goog.dom.browserrange.IeRange.prototype.collapse = function(toStart) { - this.range_.collapse(toStart); - - if (toStart) { - this.endNode_ = this.startNode_; - this.endOffset_ = this.startOffset_; - } else { - this.startNode_ = this.endNode_; - this.startOffset_ = this.endOffset_; - } -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/browserrange/operarange.js b/src/database/third_party/closure-library/closure/goog/dom/browserrange/operarange.js deleted file mode 100644 index f277dc1b94e..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/browserrange/operarange.js +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2009 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Definition of the Opera specific range wrapper. Inherits most - * functionality from W3CRange, but adds exceptions as necessary. - * - * DO NOT USE THIS FILE DIRECTLY. Use goog.dom.Range instead. - * - */ - - -goog.provide('goog.dom.browserrange.OperaRange'); - -goog.require('goog.dom.browserrange.W3cRange'); - - - -/** - * The constructor for Opera specific browser ranges. - * @param {Range} range The range object. - * @constructor - * @extends {goog.dom.browserrange.W3cRange} - * @final - */ -goog.dom.browserrange.OperaRange = function(range) { - goog.dom.browserrange.W3cRange.call(this, range); -}; -goog.inherits(goog.dom.browserrange.OperaRange, goog.dom.browserrange.W3cRange); - - -/** - * Creates a range object that selects the given node's text. - * @param {Node} node The node to select. - * @return {!goog.dom.browserrange.OperaRange} A Opera range wrapper object. - */ -goog.dom.browserrange.OperaRange.createFromNodeContents = function(node) { - return new goog.dom.browserrange.OperaRange( - goog.dom.browserrange.W3cRange.getBrowserRangeForNode(node)); -}; - - -/** - * Creates a range object that selects between the given nodes. - * @param {Node} startNode The node to start with. - * @param {number} startOffset The offset within the node to start. - * @param {Node} endNode The node to end with. - * @param {number} endOffset The offset within the node to end. - * @return {!goog.dom.browserrange.OperaRange} A wrapper object. - */ -goog.dom.browserrange.OperaRange.createFromNodes = function(startNode, - startOffset, endNode, endOffset) { - return new goog.dom.browserrange.OperaRange( - goog.dom.browserrange.W3cRange.getBrowserRangeForNodes(startNode, - startOffset, endNode, endOffset)); -}; - - -/** @override */ -goog.dom.browserrange.OperaRange.prototype.selectInternal = function( - selection, reversed) { - // Avoid using addRange as we have to removeAllRanges first, which - // blurs editable fields in Opera. - selection.collapse(this.getStartNode(), this.getStartOffset()); - if (this.getEndNode() != this.getStartNode() || - this.getEndOffset() != this.getStartOffset()) { - selection.extend(this.getEndNode(), this.getEndOffset()); - } - // This can happen if the range isn't in an editable field. - if (selection.rangeCount == 0) { - selection.addRange(this.range_); - } -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/browserrange/w3crange.js b/src/database/third_party/closure-library/closure/goog/dom/browserrange/w3crange.js deleted file mode 100644 index 599b50ca53e..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/browserrange/w3crange.js +++ /dev/null @@ -1,394 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Definition of the W3C spec following range wrapper. - * - * DO NOT USE THIS FILE DIRECTLY. Use goog.dom.Range instead. - * - * @author robbyw@google.com (Robby Walker) - */ - - -goog.provide('goog.dom.browserrange.W3cRange'); - -goog.require('goog.array'); -goog.require('goog.dom'); -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.RangeEndpoint'); -goog.require('goog.dom.browserrange.AbstractRange'); -goog.require('goog.string'); -goog.require('goog.userAgent'); - - - -/** - * The constructor for W3C specific browser ranges. - * @param {Range} range The range object. - * @constructor - * @extends {goog.dom.browserrange.AbstractRange} - */ -goog.dom.browserrange.W3cRange = function(range) { - this.range_ = range; -}; -goog.inherits(goog.dom.browserrange.W3cRange, - goog.dom.browserrange.AbstractRange); - - -/** - * Returns a browser range spanning the given node's contents. - * @param {Node} node The node to select. - * @return {!Range} A browser range spanning the node's contents. - * @protected - */ -goog.dom.browserrange.W3cRange.getBrowserRangeForNode = function(node) { - var nodeRange = goog.dom.getOwnerDocument(node).createRange(); - - if (node.nodeType == goog.dom.NodeType.TEXT) { - nodeRange.setStart(node, 0); - nodeRange.setEnd(node, node.length); - } else { - /** @suppress {missingRequire} */ - if (!goog.dom.browserrange.canContainRangeEndpoint(node)) { - var rangeParent = node.parentNode; - var rangeStartOffset = goog.array.indexOf(rangeParent.childNodes, node); - nodeRange.setStart(rangeParent, rangeStartOffset); - nodeRange.setEnd(rangeParent, rangeStartOffset + 1); - } else { - var tempNode, leaf = node; - while ((tempNode = leaf.firstChild) && - /** @suppress {missingRequire} */ - goog.dom.browserrange.canContainRangeEndpoint(tempNode)) { - leaf = tempNode; - } - nodeRange.setStart(leaf, 0); - - leaf = node; - while ((tempNode = leaf.lastChild) && - /** @suppress {missingRequire} */ - goog.dom.browserrange.canContainRangeEndpoint(tempNode)) { - leaf = tempNode; - } - nodeRange.setEnd(leaf, leaf.nodeType == goog.dom.NodeType.ELEMENT ? - leaf.childNodes.length : leaf.length); - } - } - - return nodeRange; -}; - - -/** - * Returns a browser range spanning the given nodes. - * @param {Node} startNode The node to start with - should not be a BR. - * @param {number} startOffset The offset within the start node. - * @param {Node} endNode The node to end with - should not be a BR. - * @param {number} endOffset The offset within the end node. - * @return {!Range} A browser range spanning the node's contents. - * @protected - */ -goog.dom.browserrange.W3cRange.getBrowserRangeForNodes = function(startNode, - startOffset, endNode, endOffset) { - // Create and return the range. - var nodeRange = goog.dom.getOwnerDocument(startNode).createRange(); - nodeRange.setStart(startNode, startOffset); - nodeRange.setEnd(endNode, endOffset); - return nodeRange; -}; - - -/** - * Creates a range object that selects the given node's text. - * @param {Node} node The node to select. - * @return {!goog.dom.browserrange.W3cRange} A Gecko range wrapper object. - */ -goog.dom.browserrange.W3cRange.createFromNodeContents = function(node) { - return new goog.dom.browserrange.W3cRange( - goog.dom.browserrange.W3cRange.getBrowserRangeForNode(node)); -}; - - -/** - * Creates a range object that selects between the given nodes. - * @param {Node} startNode The node to start with. - * @param {number} startOffset The offset within the start node. - * @param {Node} endNode The node to end with. - * @param {number} endOffset The offset within the end node. - * @return {!goog.dom.browserrange.W3cRange} A wrapper object. - */ -goog.dom.browserrange.W3cRange.createFromNodes = function(startNode, - startOffset, endNode, endOffset) { - return new goog.dom.browserrange.W3cRange( - goog.dom.browserrange.W3cRange.getBrowserRangeForNodes(startNode, - startOffset, endNode, endOffset)); -}; - - -/** - * @return {!goog.dom.browserrange.W3cRange} A clone of this range. - * @override - */ -goog.dom.browserrange.W3cRange.prototype.clone = function() { - return new this.constructor(this.range_.cloneRange()); -}; - - -/** @override */ -goog.dom.browserrange.W3cRange.prototype.getBrowserRange = function() { - return this.range_; -}; - - -/** @override */ -goog.dom.browserrange.W3cRange.prototype.getContainer = function() { - return this.range_.commonAncestorContainer; -}; - - -/** @override */ -goog.dom.browserrange.W3cRange.prototype.getStartNode = function() { - return this.range_.startContainer; -}; - - -/** @override */ -goog.dom.browserrange.W3cRange.prototype.getStartOffset = function() { - return this.range_.startOffset; -}; - - -/** @override */ -goog.dom.browserrange.W3cRange.prototype.getEndNode = function() { - return this.range_.endContainer; -}; - - -/** @override */ -goog.dom.browserrange.W3cRange.prototype.getEndOffset = function() { - return this.range_.endOffset; -}; - - -/** @override */ -goog.dom.browserrange.W3cRange.prototype.compareBrowserRangeEndpoints = - function(range, thisEndpoint, otherEndpoint) { - return this.range_.compareBoundaryPoints( - otherEndpoint == goog.dom.RangeEndpoint.START ? - (thisEndpoint == goog.dom.RangeEndpoint.START ? - goog.global['Range'].START_TO_START : - goog.global['Range'].START_TO_END) : - (thisEndpoint == goog.dom.RangeEndpoint.START ? - goog.global['Range'].END_TO_START : - goog.global['Range'].END_TO_END), - /** @type {Range} */ (range)); -}; - - -/** @override */ -goog.dom.browserrange.W3cRange.prototype.isCollapsed = function() { - return this.range_.collapsed; -}; - - -/** @override */ -goog.dom.browserrange.W3cRange.prototype.getText = function() { - return this.range_.toString(); -}; - - -/** @override */ -goog.dom.browserrange.W3cRange.prototype.getValidHtml = function() { - var div = goog.dom.getDomHelper(this.range_.startContainer).createDom('div'); - div.appendChild(this.range_.cloneContents()); - var result = div.innerHTML; - - if (goog.string.startsWith(result, '<') || - !this.isCollapsed() && !goog.string.contains(result, '<')) { - // We attempt to mimic IE, which returns no containing element when a - // only text nodes are selected, does return the containing element when - // the selection is empty, and does return the element when multiple nodes - // are selected. - return result; - } - - var container = this.getContainer(); - container = container.nodeType == goog.dom.NodeType.ELEMENT ? container : - container.parentNode; - - var html = goog.dom.getOuterHtml( - /** @type {!Element} */ (container.cloneNode(false))); - return html.replace('>', '>' + result); -}; - - -// SELECTION MODIFICATION - - -/** @override */ -goog.dom.browserrange.W3cRange.prototype.select = function(reverse) { - var win = goog.dom.getWindow(goog.dom.getOwnerDocument(this.getStartNode())); - this.selectInternal(win.getSelection(), reverse); -}; - - -/** - * Select this range. - * @param {Selection} selection Browser selection object. - * @param {*} reverse Whether to select this range in reverse. - * @protected - */ -goog.dom.browserrange.W3cRange.prototype.selectInternal = function(selection, - reverse) { - // Browser-specific tricks are needed to create reversed selections - // programatically. For this generic W3C codepath, ignore the reverse - // parameter. - selection.removeAllRanges(); - selection.addRange(this.range_); -}; - - -/** @override */ -goog.dom.browserrange.W3cRange.prototype.removeContents = function() { - var range = this.range_; - range.extractContents(); - - if (range.startContainer.hasChildNodes()) { - // Remove any now empty nodes surrounding the extracted contents. - var rangeStartContainer = - range.startContainer.childNodes[range.startOffset]; - if (rangeStartContainer) { - var rangePrevious = rangeStartContainer.previousSibling; - - if (goog.dom.getRawTextContent(rangeStartContainer) == '') { - goog.dom.removeNode(rangeStartContainer); - } - - if (rangePrevious && goog.dom.getRawTextContent(rangePrevious) == '') { - goog.dom.removeNode(rangePrevious); - } - } - } - - if (goog.userAgent.IE) { - // Unfortunately, when deleting a portion of a single text node, IE creates - // an extra text node instead of modifying the nodeValue of the start node. - // We normalize for that behavior here, similar to code in - // goog.dom.browserrange.IeRange#removeContents - // See https://connect.microsoft.com/IE/feedback/details/746591 - var startNode = this.getStartNode(); - var startOffset = this.getStartOffset(); - var endNode = this.getEndNode(); - var endOffset = this.getEndOffset(); - var sibling = startNode.nextSibling; - if (startNode == endNode && startNode.parentNode && - startNode.nodeType == goog.dom.NodeType.TEXT && - sibling && sibling.nodeType == goog.dom.NodeType.TEXT) { - startNode.nodeValue += sibling.nodeValue; - goog.dom.removeNode(sibling); - - // Modifying the node value clears the range offsets. Reselect the - // position in the modified start node. - range.setStart(startNode, startOffset); - range.setEnd(endNode, endOffset); - } - } -}; - - -/** @override */ -goog.dom.browserrange.W3cRange.prototype.surroundContents = function(element) { - this.range_.surroundContents(element); - return element; -}; - - -/** @override */ -goog.dom.browserrange.W3cRange.prototype.insertNode = function(node, before) { - var range = this.range_.cloneRange(); - range.collapse(before); - range.insertNode(node); - range.detach(); - - return node; -}; - - -/** @override */ -goog.dom.browserrange.W3cRange.prototype.surroundWithNodes = function( - startNode, endNode) { - var win = goog.dom.getWindow( - goog.dom.getOwnerDocument(this.getStartNode())); - /** @suppress {missingRequire} */ - var selectionRange = goog.dom.Range.createFromWindow(win); - if (selectionRange) { - var sNode = selectionRange.getStartNode(); - var eNode = selectionRange.getEndNode(); - var sOffset = selectionRange.getStartOffset(); - var eOffset = selectionRange.getEndOffset(); - } - - var clone1 = this.range_.cloneRange(); - var clone2 = this.range_.cloneRange(); - - clone1.collapse(false); - clone2.collapse(true); - - clone1.insertNode(endNode); - clone2.insertNode(startNode); - - clone1.detach(); - clone2.detach(); - - if (selectionRange) { - // There are 4 ways that surroundWithNodes can wreck the saved - // selection object. All of them happen when an inserted node splits - // a text node, and one of the end points of the selection was in the - // latter half of that text node. - // - // Clients of this library should use saveUsingCarets to avoid this - // problem. Unfortunately, saveUsingCarets uses this method, so that's - // not really an option for us. :( We just recompute the offsets. - var isInsertedNode = function(n) { - return n == startNode || n == endNode; - }; - if (sNode.nodeType == goog.dom.NodeType.TEXT) { - while (sOffset > sNode.length) { - sOffset -= sNode.length; - do { - sNode = sNode.nextSibling; - } while (isInsertedNode(sNode)); - } - } - - if (eNode.nodeType == goog.dom.NodeType.TEXT) { - while (eOffset > eNode.length) { - eOffset -= eNode.length; - do { - eNode = eNode.nextSibling; - } while (isInsertedNode(eNode)); - } - } - - /** @suppress {missingRequire} */ - goog.dom.Range.createFromNodes( - sNode, /** @type {number} */ (sOffset), - eNode, /** @type {number} */ (eOffset)).select(); - } -}; - - -/** @override */ -goog.dom.browserrange.W3cRange.prototype.collapse = function(toStart) { - this.range_.collapse(toStart); -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/browserrange/webkitrange.js b/src/database/third_party/closure-library/closure/goog/dom/browserrange/webkitrange.js deleted file mode 100644 index e572dd85fc4..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/browserrange/webkitrange.js +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Definition of the WebKit specific range wrapper. Inherits most - * functionality from W3CRange, but adds exceptions as necessary. - * - * DO NOT USE THIS FILE DIRECTLY. Use goog.dom.Range instead. - * - * @author robbyw@google.com (Robby Walker) - */ - - -goog.provide('goog.dom.browserrange.WebKitRange'); - -goog.require('goog.dom.RangeEndpoint'); -goog.require('goog.dom.browserrange.W3cRange'); -goog.require('goog.userAgent'); - - - -/** - * The constructor for WebKit specific browser ranges. - * @param {Range} range The range object. - * @constructor - * @extends {goog.dom.browserrange.W3cRange} - * @final - */ -goog.dom.browserrange.WebKitRange = function(range) { - goog.dom.browserrange.W3cRange.call(this, range); -}; -goog.inherits(goog.dom.browserrange.WebKitRange, - goog.dom.browserrange.W3cRange); - - -/** - * Creates a range object that selects the given node's text. - * @param {Node} node The node to select. - * @return {!goog.dom.browserrange.WebKitRange} A WebKit range wrapper object. - */ -goog.dom.browserrange.WebKitRange.createFromNodeContents = function(node) { - return new goog.dom.browserrange.WebKitRange( - goog.dom.browserrange.W3cRange.getBrowserRangeForNode(node)); -}; - - -/** - * Creates a range object that selects between the given nodes. - * @param {Node} startNode The node to start with. - * @param {number} startOffset The offset within the start node. - * @param {Node} endNode The node to end with. - * @param {number} endOffset The offset within the end node. - * @return {!goog.dom.browserrange.WebKitRange} A wrapper object. - */ -goog.dom.browserrange.WebKitRange.createFromNodes = function(startNode, - startOffset, endNode, endOffset) { - return new goog.dom.browserrange.WebKitRange( - goog.dom.browserrange.W3cRange.getBrowserRangeForNodes(startNode, - startOffset, endNode, endOffset)); -}; - - -/** @override */ -goog.dom.browserrange.WebKitRange.prototype.compareBrowserRangeEndpoints = - function(range, thisEndpoint, otherEndpoint) { - // Webkit pre-528 has some bugs where compareBoundaryPoints() doesn't work the - // way it is supposed to, but if we reverse the sense of two comparisons, - // it works fine. - // https://bugs.webkit.org/show_bug.cgi?id=20738 - if (goog.userAgent.isVersionOrHigher('528')) { - return (goog.dom.browserrange.WebKitRange.superClass_. - compareBrowserRangeEndpoints.call( - this, range, thisEndpoint, otherEndpoint)); - } - return this.range_.compareBoundaryPoints( - otherEndpoint == goog.dom.RangeEndpoint.START ? - (thisEndpoint == goog.dom.RangeEndpoint.START ? - goog.global['Range'].START_TO_START : - goog.global['Range'].END_TO_START) : // Sense reversed - (thisEndpoint == goog.dom.RangeEndpoint.START ? - goog.global['Range'].START_TO_END : // Sense reversed - goog.global['Range'].END_TO_END), - /** @type {Range} */ (range)); -}; - - -/** @override */ -goog.dom.browserrange.WebKitRange.prototype.selectInternal = function( - selection, reversed) { - // Unselect everything. This addresses a bug in Webkit where it sometimes - // caches the old selection. - // https://bugs.webkit.org/show_bug.cgi?id=20117 - selection.removeAllRanges(); - - if (reversed) { - selection.setBaseAndExtent(this.getEndNode(), this.getEndOffset(), - this.getStartNode(), this.getStartOffset()); - } else { - selection.setBaseAndExtent(this.getStartNode(), this.getStartOffset(), - this.getEndNode(), this.getEndOffset()); - } -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/bufferedviewportsizemonitor.js b/src/database/third_party/closure-library/closure/goog/dom/bufferedviewportsizemonitor.js deleted file mode 100644 index 01ab526c1d4..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/bufferedviewportsizemonitor.js +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright 2012 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview A viewport size monitor that buffers RESIZE events until the - * window size has stopped changing, within a specified period of time. For - * every RESIZE event dispatched, this will dispatch up to two *additional* - * events: - * - {@link #EventType.RESIZE_WIDTH} if the viewport's width has changed since - * the last buffered dispatch. - * - {@link #EventType.RESIZE_HEIGHT} if the viewport's height has changed since - * the last buffered dispatch. - * You likely only need to listen to one of the three events. But if you need - * more, just be cautious of duplicating effort. - * - */ - -goog.provide('goog.dom.BufferedViewportSizeMonitor'); - -goog.require('goog.asserts'); -goog.require('goog.async.Delay'); -goog.require('goog.events'); -goog.require('goog.events.EventTarget'); -goog.require('goog.events.EventType'); - - - -/** - * Creates a new BufferedViewportSizeMonitor. - * @param {!goog.dom.ViewportSizeMonitor} viewportSizeMonitor The - * underlying viewport size monitor. - * @param {number=} opt_bufferMs The buffer time, in ms. If not specified, this - * value defaults to {@link #RESIZE_EVENT_DELAY_MS_}. - * @constructor - * @extends {goog.events.EventTarget} - * @final - */ -goog.dom.BufferedViewportSizeMonitor = function( - viewportSizeMonitor, opt_bufferMs) { - goog.dom.BufferedViewportSizeMonitor.base(this, 'constructor'); - - /** - * The underlying viewport size monitor. - * @type {goog.dom.ViewportSizeMonitor} - * @private - */ - this.viewportSizeMonitor_ = viewportSizeMonitor; - - /** - * The current size of the viewport. - * @type {goog.math.Size} - * @private - */ - this.currentSize_ = this.viewportSizeMonitor_.getSize(); - - /** - * The resize buffer time in ms. - * @type {number} - * @private - */ - this.resizeBufferMs_ = opt_bufferMs || - goog.dom.BufferedViewportSizeMonitor.RESIZE_EVENT_DELAY_MS_; - - /** - * Listener key for the viewport size monitor. - * @type {goog.events.Key} - * @private - */ - this.listenerKey_ = goog.events.listen( - viewportSizeMonitor, - goog.events.EventType.RESIZE, - this.handleResize_, - false, - this); -}; -goog.inherits(goog.dom.BufferedViewportSizeMonitor, goog.events.EventTarget); - - -/** - * Additional events to dispatch. - * @enum {string} - */ -goog.dom.BufferedViewportSizeMonitor.EventType = { - RESIZE_HEIGHT: goog.events.getUniqueId('resizeheight'), - RESIZE_WIDTH: goog.events.getUniqueId('resizewidth') -}; - - -/** - * Delay for the resize event. - * @type {goog.async.Delay} - * @private - */ -goog.dom.BufferedViewportSizeMonitor.prototype.resizeDelay_; - - -/** - * Default number of milliseconds to wait after a resize event to relayout the - * page. - * @type {number} - * @const - * @private - */ -goog.dom.BufferedViewportSizeMonitor.RESIZE_EVENT_DELAY_MS_ = 100; - - -/** @override */ -goog.dom.BufferedViewportSizeMonitor.prototype.disposeInternal = - function() { - goog.events.unlistenByKey(this.listenerKey_); - goog.dom.BufferedViewportSizeMonitor.base(this, 'disposeInternal'); -}; - - -/** - * Handles resize events on the underlying ViewportMonitor. - * @private - */ -goog.dom.BufferedViewportSizeMonitor.prototype.handleResize_ = - function() { - // Lazily create when needed. - if (!this.resizeDelay_) { - this.resizeDelay_ = new goog.async.Delay( - this.onWindowResize_, - this.resizeBufferMs_, - this); - this.registerDisposable(this.resizeDelay_); - } - this.resizeDelay_.start(); -}; - - -/** - * Window resize callback that determines whether to reflow the view contents. - * @private - */ -goog.dom.BufferedViewportSizeMonitor.prototype.onWindowResize_ = - function() { - if (this.viewportSizeMonitor_.isDisposed()) { - return; - } - - var previousSize = this.currentSize_; - var currentSize = this.viewportSizeMonitor_.getSize(); - - goog.asserts.assert(currentSize, - 'Viewport size should be set at this point'); - - this.currentSize_ = currentSize; - - if (previousSize) { - - var resized = false; - - // Width has changed - if (previousSize.width != currentSize.width) { - this.dispatchEvent( - goog.dom.BufferedViewportSizeMonitor.EventType.RESIZE_WIDTH); - resized = true; - } - - // Height has changed - if (previousSize.height != currentSize.height) { - this.dispatchEvent( - goog.dom.BufferedViewportSizeMonitor.EventType.RESIZE_HEIGHT); - resized = true; - } - - // If either has changed, this is a resize event. - if (resized) { - this.dispatchEvent(goog.events.EventType.RESIZE); - } - - } else { - // If we didn't have a previous size, we consider all events to have - // changed. - this.dispatchEvent( - goog.dom.BufferedViewportSizeMonitor.EventType.RESIZE_HEIGHT); - this.dispatchEvent( - goog.dom.BufferedViewportSizeMonitor.EventType.RESIZE_WIDTH); - this.dispatchEvent(goog.events.EventType.RESIZE); - } -}; - - -/** - * Returns the current size of the viewport. - * @return {goog.math.Size?} The current viewport size. - */ -goog.dom.BufferedViewportSizeMonitor.prototype.getSize = function() { - return this.currentSize_ ? this.currentSize_.clone() : null; -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/bufferedviewportsizemonitor_test.html b/src/database/third_party/closure-library/closure/goog/dom/bufferedviewportsizemonitor_test.html deleted file mode 100644 index 7817389c977..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/bufferedviewportsizemonitor_test.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - -Tests for goog.dom.BufferedViewportSizeMonitor - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/bufferedviewportsizemonitor_test.js b/src/database/third_party/closure-library/closure/goog/dom/bufferedviewportsizemonitor_test.js deleted file mode 100644 index f2e6388b029..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/bufferedviewportsizemonitor_test.js +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2012 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Tests for goog.dom.BufferedViewportSizeMonitor. - * - */ - - -/** @suppress {extraProvide} */ -goog.provide('goog.dom.BufferedViewportSizeMonitorTest'); - -goog.require('goog.dom.BufferedViewportSizeMonitor'); -goog.require('goog.dom.ViewportSizeMonitor'); -goog.require('goog.events'); -goog.require('goog.events.EventType'); -goog.require('goog.math.Size'); -goog.require('goog.testing.MockClock'); -goog.require('goog.testing.events'); -goog.require('goog.testing.events.Event'); -goog.require('goog.testing.jsunit'); - -goog.setTestOnly('goog.dom.BufferedViewportSizeMonitorTest'); - -var RESIZE_DELAY = goog.dom.BufferedViewportSizeMonitor.RESIZE_EVENT_DELAY_MS_; -var INITIAL_SIZE = new goog.math.Size(111, 111); - -var mockControl; -var viewportSizeMonitor; -var bufferedVsm; -var timer = new goog.testing.MockClock(); -var resizeEventCount = 0; -var size; - -var resizeCallback = function() { - resizeEventCount++; -}; - -function setUp() { - timer.install(); - - size = INITIAL_SIZE; - viewportSizeMonitor = new goog.dom.ViewportSizeMonitor(); - viewportSizeMonitor.getSize = function() { return size; }; - bufferedVsm = new goog.dom.BufferedViewportSizeMonitor(viewportSizeMonitor); - - goog.events.listen(bufferedVsm, goog.events.EventType.RESIZE, resizeCallback); -} - -function tearDown() { - goog.events.unlisten( - bufferedVsm, goog.events.EventType.RESIZE, resizeCallback); - resizeEventCount = 0; - timer.uninstall(); -} - -function testInitialSizes() { - assertTrue(goog.math.Size.equals(INITIAL_SIZE, bufferedVsm.getSize())); -} - -function testWindowResize() { - assertEquals(0, resizeEventCount); - resize(100, 100); - timer.tick(RESIZE_DELAY - 1); - assertEquals( - 'No resize expected before the delay is fired', 0, resizeEventCount); - timer.tick(1); - assertEquals('Expected resize after delay', 1, resizeEventCount); - assertTrue(goog.math.Size.equals( - new goog.math.Size(100, 100), bufferedVsm.getSize())); -} - -function testWindowResize_eventBatching() { - assertEquals('No resize calls expected before resize events', - 0, resizeEventCount); - resize(100, 100); - timer.tick(RESIZE_DELAY - 1); - resize(200, 200); - assertEquals( - 'No resize expected before the delay is fired', 0, resizeEventCount); - timer.tick(1); - assertEquals( - 'No resize expected when delay is restarted', 0, resizeEventCount); - timer.tick(RESIZE_DELAY); - assertEquals('Expected resize after delay', 1, resizeEventCount); -} - -function testWindowResize_noChange() { - resize(100, 100); - timer.tick(RESIZE_DELAY); - assertEquals(1, resizeEventCount); - resize(100, 100); - timer.tick(RESIZE_DELAY); - assertEquals( - 'No resize expected when size doesn\'t change', 1, resizeEventCount); - assertTrue(goog.math.Size.equals( - new goog.math.Size(100, 100), bufferedVsm.getSize())); -} - -function testWindowResize_previousSize() { - resize(100, 100); - timer.tick(RESIZE_DELAY); - assertEquals(1, resizeEventCount); - assertTrue(goog.math.Size.equals( - new goog.math.Size(100, 100), bufferedVsm.getSize())); - - resize(200, 200); - timer.tick(RESIZE_DELAY); - assertEquals(2, resizeEventCount); - assertTrue(goog.math.Size.equals( - new goog.math.Size(200, 200), bufferedVsm.getSize())); -} - -function resize(width, height) { - size = new goog.math.Size(width, height); - goog.testing.events.fireBrowserEvent( - new goog.testing.events.Event( - goog.events.EventType.RESIZE, viewportSizeMonitor)); -} diff --git a/src/database/third_party/closure-library/closure/goog/dom/classes.js b/src/database/third_party/closure-library/closure/goog/dom/classes.js deleted file mode 100644 index 0f1db744339..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/classes.js +++ /dev/null @@ -1,239 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utilities for adding, removing and setting classes. Prefer - * {@link goog.dom.classlist} over these utilities since goog.dom.classlist - * conforms closer to the semantics of Element.classList, is faster (uses - * native methods rather than parsing strings on every call) and compiles - * to smaller code as a result. - * - * Note: these utilities are meant to operate on HTMLElements and - * will not work on elements with differing interfaces (such as SVGElements). - * - * @author arv@google.com (Erik Arvidsson) - */ - - -goog.provide('goog.dom.classes'); - -goog.require('goog.array'); - - -/** - * Sets the entire class name of an element. - * @param {Node} element DOM node to set class of. - * @param {string} className Class name(s) to apply to element. - * @deprecated Use goog.dom.classlist.set instead. - */ -goog.dom.classes.set = function(element, className) { - element.className = className; -}; - - -/** - * Gets an array of class names on an element - * @param {Node} element DOM node to get class of. - * @return {!Array} Class names on {@code element}. Some browsers add extra - * properties to the array. Do not depend on any of these! - * @deprecated Use goog.dom.classlist.get instead. - */ -goog.dom.classes.get = function(element) { - var className = element.className; - // Some types of elements don't have a className in IE (e.g. iframes). - // Furthermore, in Firefox, className is not a string when the element is - // an SVG element. - return goog.isString(className) && className.match(/\S+/g) || []; -}; - - -/** - * Adds a class or classes to an element. Does not add multiples of class names. - * @param {Node} element DOM node to add class to. - * @param {...string} var_args Class names to add. - * @return {boolean} Whether class was added (or all classes were added). - * @deprecated Use goog.dom.classlist.add or goog.dom.classlist.addAll instead. - */ -goog.dom.classes.add = function(element, var_args) { - var classes = goog.dom.classes.get(element); - var args = goog.array.slice(arguments, 1); - var expectedCount = classes.length + args.length; - goog.dom.classes.add_(classes, args); - goog.dom.classes.set(element, classes.join(' ')); - return classes.length == expectedCount; -}; - - -/** - * Removes a class or classes from an element. - * @param {Node} element DOM node to remove class from. - * @param {...string} var_args Class name(s) to remove. - * @return {boolean} Whether all classes in {@code var_args} were found and - * removed. - * @deprecated Use goog.dom.classlist.remove or goog.dom.classlist.removeAll - * instead. - */ -goog.dom.classes.remove = function(element, var_args) { - var classes = goog.dom.classes.get(element); - var args = goog.array.slice(arguments, 1); - var newClasses = goog.dom.classes.getDifference_(classes, args); - goog.dom.classes.set(element, newClasses.join(' ')); - return newClasses.length == classes.length - args.length; -}; - - -/** - * Helper method for {@link goog.dom.classes.add} and - * {@link goog.dom.classes.addRemove}. Adds one or more classes to the supplied - * classes array. - * @param {Array} classes All class names for the element, will be - * updated to have the classes supplied in {@code args} added. - * @param {Array} args Class names to add. - * @private - */ -goog.dom.classes.add_ = function(classes, args) { - for (var i = 0; i < args.length; i++) { - if (!goog.array.contains(classes, args[i])) { - classes.push(args[i]); - } - } -}; - - -/** - * Helper method for {@link goog.dom.classes.remove} and - * {@link goog.dom.classes.addRemove}. Calculates the difference of two arrays. - * @param {!Array} arr1 First array. - * @param {!Array} arr2 Second array. - * @return {!Array} The first array without the elements of the second - * array. - * @private - */ -goog.dom.classes.getDifference_ = function(arr1, arr2) { - return goog.array.filter(arr1, function(item) { - return !goog.array.contains(arr2, item); - }); -}; - - -/** - * Switches a class on an element from one to another without disturbing other - * classes. If the fromClass isn't removed, the toClass won't be added. - * @param {Node} element DOM node to swap classes on. - * @param {string} fromClass Class to remove. - * @param {string} toClass Class to add. - * @return {boolean} Whether classes were switched. - * @deprecated Use goog.dom.classlist.swap instead. - */ -goog.dom.classes.swap = function(element, fromClass, toClass) { - var classes = goog.dom.classes.get(element); - - var removed = false; - for (var i = 0; i < classes.length; i++) { - if (classes[i] == fromClass) { - goog.array.splice(classes, i--, 1); - removed = true; - } - } - - if (removed) { - classes.push(toClass); - goog.dom.classes.set(element, classes.join(' ')); - } - - return removed; -}; - - -/** - * Adds zero or more classes to an element and removes zero or more as a single - * operation. Unlike calling {@link goog.dom.classes.add} and - * {@link goog.dom.classes.remove} separately, this is more efficient as it only - * parses the class property once. - * - * If a class is in both the remove and add lists, it will be added. Thus, - * you can use this instead of {@link goog.dom.classes.swap} when you have - * more than two class names that you want to swap. - * - * @param {Node} element DOM node to swap classes on. - * @param {?(string|Array)} classesToRemove Class or classes to - * remove, if null no classes are removed. - * @param {?(string|Array)} classesToAdd Class or classes to add, if - * null no classes are added. - * @deprecated Use goog.dom.classlist.addRemove instead. - */ -goog.dom.classes.addRemove = function(element, classesToRemove, classesToAdd) { - var classes = goog.dom.classes.get(element); - if (goog.isString(classesToRemove)) { - goog.array.remove(classes, classesToRemove); - } else if (goog.isArray(classesToRemove)) { - classes = goog.dom.classes.getDifference_(classes, classesToRemove); - } - - if (goog.isString(classesToAdd) && - !goog.array.contains(classes, classesToAdd)) { - classes.push(classesToAdd); - } else if (goog.isArray(classesToAdd)) { - goog.dom.classes.add_(classes, classesToAdd); - } - - goog.dom.classes.set(element, classes.join(' ')); -}; - - -/** - * Returns true if an element has a class. - * @param {Node} element DOM node to test. - * @param {string} className Class name to test for. - * @return {boolean} Whether element has the class. - * @deprecated Use goog.dom.classlist.contains instead. - */ -goog.dom.classes.has = function(element, className) { - return goog.array.contains(goog.dom.classes.get(element), className); -}; - - -/** - * Adds or removes a class depending on the enabled argument. - * @param {Node} element DOM node to add or remove the class on. - * @param {string} className Class name to add or remove. - * @param {boolean} enabled Whether to add or remove the class (true adds, - * false removes). - * @deprecated Use goog.dom.classlist.enable or goog.dom.classlist.enableAll - * instead. - */ -goog.dom.classes.enable = function(element, className, enabled) { - if (enabled) { - goog.dom.classes.add(element, className); - } else { - goog.dom.classes.remove(element, className); - } -}; - - -/** - * Removes a class if an element has it, and adds it the element doesn't have - * it. Won't affect other classes on the node. - * @param {Node} element DOM node to toggle class on. - * @param {string} className Class to toggle. - * @return {boolean} True if class was added, false if it was removed - * (in other words, whether element has the class after this function has - * been called). - * @deprecated Use goog.dom.classlist.toggle instead. - */ -goog.dom.classes.toggle = function(element, className) { - var add = !goog.dom.classes.has(element, className); - goog.dom.classes.enable(element, className, add); - return add; -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/classes_quirks_test.html b/src/database/third_party/closure-library/closure/goog/dom/classes_quirks_test.html deleted file mode 100644 index dc9a81790c8..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/classes_quirks_test.html +++ /dev/null @@ -1,63 +0,0 @@ - - - - -Closure Unit Tests - goog.dom.classes= - - - - -
    - Test Element -
    - -
    - - - - - - - - -

    - -
    -
    -
    - - -

    - - a - c - d - - e - f - g - -

    -

    - h -

    - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/classes_test.html b/src/database/third_party/closure-library/closure/goog/dom/classes_test.html deleted file mode 100644 index bdde043f842..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/classes_test.html +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - -Closure Unit Tests - goog.dom.classes - - - - -
    - Test Element -
    - -
    - - - - - - - - -

    - -
    -
    -
    - - -

    - - a - c - d - - e - f - g - -

    -

    - h -

    - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/classes_test.js b/src/database/third_party/closure-library/closure/goog/dom/classes_test.js deleted file mode 100644 index 12f19d0846d..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/classes_test.js +++ /dev/null @@ -1,231 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Shared code for classes_test.html & classes_quirks_test.html. - */ - -goog.provide('goog.dom.classes_test'); -goog.setTestOnly('goog.dom.classes_test'); - -goog.require('goog.dom'); -goog.require('goog.dom.classes'); -goog.require('goog.testing.jsunit'); - - -var classes = goog.dom.classes; - -function testGet() { - var el = document.createElement('div'); - assertArrayEquals([], goog.dom.classes.get(el)); - el.className = 'C'; - assertArrayEquals(['C'], goog.dom.classes.get(el)); - el.className = 'C D'; - assertArrayEquals(['C', 'D'], goog.dom.classes.get(el)); - el.className = 'C\nD'; - assertArrayEquals(['C', 'D'], goog.dom.classes.get(el)); - el.className = ' C '; - assertArrayEquals(['C'], goog.dom.classes.get(el)); -} - -function testSetAddHasRemove() { - var el = goog.dom.getElement('p1'); - classes.set(el, 'SOMECLASS'); - assertTrue('Should have SOMECLASS', classes.has(el, 'SOMECLASS')); - - classes.set(el, 'OTHERCLASS'); - assertTrue('Should have OTHERCLASS', classes.has(el, 'OTHERCLASS')); - assertFalse('Should not have SOMECLASS', classes.has(el, 'SOMECLASS')); - - classes.add(el, 'WOOCLASS'); - assertTrue('Should have OTHERCLASS', classes.has(el, 'OTHERCLASS')); - assertTrue('Should have WOOCLASS', classes.has(el, 'WOOCLASS')); - - classes.add(el, 'ACLASS', 'BCLASS', 'CCLASS'); - assertTrue('Should have OTHERCLASS', classes.has(el, 'OTHERCLASS')); - assertTrue('Should have WOOCLASS', classes.has(el, 'WOOCLASS')); - assertTrue('Should have ACLASS', classes.has(el, 'ACLASS')); - assertTrue('Should have BCLASS', classes.has(el, 'BCLASS')); - assertTrue('Should have CCLASS', classes.has(el, 'CCLASS')); - - classes.remove(el, 'CCLASS'); - assertTrue('Should have OTHERCLASS', classes.has(el, 'OTHERCLASS')); - assertTrue('Should have WOOCLASS', classes.has(el, 'WOOCLASS')); - assertTrue('Should have ACLASS', classes.has(el, 'ACLASS')); - assertTrue('Should have BCLASS', classes.has(el, 'BCLASS')); - assertFalse('Should not have CCLASS', classes.has(el, 'CCLASS')); - - classes.remove(el, 'ACLASS', 'BCLASS'); - assertTrue('Should have OTHERCLASS', classes.has(el, 'OTHERCLASS')); - assertTrue('Should have WOOCLASS', classes.has(el, 'WOOCLASS')); - assertFalse('Should not have ACLASS', classes.has(el, 'ACLASS')); - assertFalse('Should not have BCLASS', classes.has(el, 'BCLASS')); -} - -// While support for this isn't implied in the method documentation, -// this is a frequently used pattern. -function testAddWithSpacesInClassName() { - var el = goog.dom.getElement('p1'); - classes.add(el, 'CLASS1 CLASS2', 'CLASS3 CLASS4'); - assertTrue('Should have CLASS1', classes.has(el, 'CLASS1')); - assertTrue('Should have CLASS2', classes.has(el, 'CLASS2')); - assertTrue('Should have CLASS3', classes.has(el, 'CLASS3')); - assertTrue('Should have CLASS4', classes.has(el, 'CLASS4')); -} - -function testSwap() { - var el = goog.dom.getElement('p1'); - classes.set(el, 'SOMECLASS FIRST'); - - assertTrue('Should have FIRST class', classes.has(el, 'FIRST')); - assertTrue('Should have FIRST class', classes.has(el, 'SOMECLASS')); - assertFalse('Should not have second class', classes.has(el, 'second')); - - classes.swap(el, 'FIRST', 'second'); - - assertFalse('Should not have FIRST class', classes.has(el, 'FIRST')); - assertTrue('Should have FIRST class', classes.has(el, 'SOMECLASS')); - assertTrue('Should have second class', classes.has(el, 'second')); - - classes.swap(el, 'second', 'FIRST'); - - assertTrue('Should have FIRST class', classes.has(el, 'FIRST')); - assertTrue('Should have FIRST class', classes.has(el, 'SOMECLASS')); - assertFalse('Should not have second class', classes.has(el, 'second')); -} - -function testEnable() { - var el = goog.dom.getElement('p1'); - classes.set(el, 'SOMECLASS FIRST'); - - assertTrue('Should have FIRST class', classes.has(el, 'FIRST')); - assertTrue('Should have SOMECLASS class', classes.has(el, 'SOMECLASS')); - - classes.enable(el, 'FIRST', false); - - assertFalse('Should not have FIRST class', classes.has(el, 'FIRST')); - assertTrue('Should have SOMECLASS class', classes.has(el, 'SOMECLASS')); - - classes.enable(el, 'FIRST', true); - - assertTrue('Should have FIRST class', classes.has(el, 'FIRST')); - assertTrue('Should have SOMECLASS class', classes.has(el, 'SOMECLASS')); -} - -function testToggle() { - var el = goog.dom.getElement('p1'); - classes.set(el, 'SOMECLASS FIRST'); - - assertTrue('Should have FIRST class', classes.has(el, 'FIRST')); - assertTrue('Should have SOMECLASS class', classes.has(el, 'SOMECLASS')); - - classes.toggle(el, 'FIRST'); - - assertFalse('Should not have FIRST class', classes.has(el, 'FIRST')); - assertTrue('Should have SOMECLASS class', classes.has(el, 'SOMECLASS')); - - classes.toggle(el, 'FIRST'); - - assertTrue('Should have FIRST class', classes.has(el, 'FIRST')); - assertTrue('Should have SOMECLASS class', classes.has(el, 'SOMECLASS')); -} - -function testAddNotAddingMultiples() { - var el = goog.dom.getElement('span6'); - assertTrue(classes.add(el, 'A')); - assertEquals('A', el.className); - assertFalse(classes.add(el, 'A')); - assertEquals('A', el.className); - assertFalse(classes.add(el, 'B', 'B')); - assertEquals('A B', el.className); -} - -function testAddRemoveString() { - var el = goog.dom.getElement('span6'); - el.className = 'A'; - - goog.dom.classes.addRemove(el, 'A', 'B'); - assertEquals('B', el.className); - - goog.dom.classes.addRemove(el, null, 'C'); - assertEquals('B C', el.className); - - goog.dom.classes.addRemove(el, 'C', 'D'); - assertEquals('B D', el.className); - - goog.dom.classes.addRemove(el, 'D', null); - assertEquals('B', el.className); -} - -function testAddRemoveArray() { - var el = goog.dom.getElement('span6'); - el.className = 'A'; - - goog.dom.classes.addRemove(el, ['A'], ['B']); - assertEquals('B', el.className); - - goog.dom.classes.addRemove(el, [], ['C']); - assertEquals('B C', el.className); - - goog.dom.classes.addRemove(el, ['C'], ['D']); - assertEquals('B D', el.className); - - goog.dom.classes.addRemove(el, ['D'], []); - assertEquals('B', el.className); -} - -function testAddRemoveMultiple() { - var el = goog.dom.getElement('span6'); - el.className = 'A'; - - goog.dom.classes.addRemove(el, ['A'], ['B', 'C', 'D']); - assertEquals('B C D', el.className); - - goog.dom.classes.addRemove(el, [], ['E', 'F']); - assertEquals('B C D E F', el.className); - - goog.dom.classes.addRemove(el, ['C', 'E'], []); - assertEquals('B D F', el.className); - - goog.dom.classes.addRemove(el, ['B'], ['G']); - assertEquals('D F G', el.className); -} - -// While support for this isn't implied in the method documentation, -// this is a frequently used pattern. -function testAddRemoveWithSpacesInClassName() { - var el = goog.dom.getElement('p1'); - classes.addRemove(el, '', 'CLASS1 CLASS2'); - assertTrue('Should have CLASS1', classes.has(el, 'CLASS1')); - assertTrue('Should have CLASS2', classes.has(el, 'CLASS2')); -} - -function testHasWithNewlines() { - var el = goog.dom.getElement('p3'); - assertTrue('Should have SOMECLASS', classes.has(el, 'SOMECLASS')); - assertTrue('Should also have OTHERCLASS', classes.has(el, 'OTHERCLASS')); - assertFalse('Should not have WEIRDCLASS', classes.has(el, 'WEIRDCLASS')); -} - -function testEmptyClassNames() { - var el = goog.dom.getElement('span1'); - // At the very least, make sure these do not error out. - assertFalse('Should not have an empty class', classes.has(el, '')); - classes.add(el, ''); - classes.toggle(el, ''); - assertFalse('Should not remove an empty class', classes.remove(el, '')); - classes.swap(el, '', 'OTHERCLASS'); - classes.swap(el, 'TEST1', ''); - classes.addRemove(el, '', ''); -} diff --git a/src/database/third_party/closure-library/closure/goog/dom/classlist.js b/src/database/third_party/closure-library/closure/goog/dom/classlist.js deleted file mode 100644 index dcbb7ed276c..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/classlist.js +++ /dev/null @@ -1,277 +0,0 @@ -// Copyright 2012 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utilities for detecting, adding and removing classes. Prefer - * this over goog.dom.classes for new code since it attempts to use classList - * (DOMTokenList: http://dom.spec.whatwg.org/#domtokenlist) which is faster - * and requires less code. - * - * Note: these utilities are meant to operate on HTMLElements - * and may have unexpected behavior on elements with differing interfaces - * (such as SVGElements). - */ - - -goog.provide('goog.dom.classlist'); - -goog.require('goog.array'); - - -/** - * Override this define at build-time if you know your target supports it. - * @define {boolean} Whether to use the classList property (DOMTokenList). - */ -goog.define('goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST', false); - - -/** - * Gets an array-like object of class names on an element. - * @param {Element} element DOM node to get the classes of. - * @return {!goog.array.ArrayLike} Class names on {@code element}. - */ -goog.dom.classlist.get = function(element) { - if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) { - return element.classList; - } - - var className = element.className; - // Some types of elements don't have a className in IE (e.g. iframes). - // Furthermore, in Firefox, className is not a string when the element is - // an SVG element. - return goog.isString(className) && className.match(/\S+/g) || []; -}; - - -/** - * Sets the entire class name of an element. - * @param {Element} element DOM node to set class of. - * @param {string} className Class name(s) to apply to element. - */ -goog.dom.classlist.set = function(element, className) { - element.className = className; -}; - - -/** - * Returns true if an element has a class. This method may throw a DOM - * exception for an invalid or empty class name if DOMTokenList is used. - * @param {Element} element DOM node to test. - * @param {string} className Class name to test for. - * @return {boolean} Whether element has the class. - */ -goog.dom.classlist.contains = function(element, className) { - if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) { - return element.classList.contains(className); - } - return goog.array.contains(goog.dom.classlist.get(element), className); -}; - - -/** - * Adds a class to an element. Does not add multiples of class names. This - * method may throw a DOM exception for an invalid or empty class name if - * DOMTokenList is used. - * @param {Element} element DOM node to add class to. - * @param {string} className Class name to add. - */ -goog.dom.classlist.add = function(element, className) { - if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) { - element.classList.add(className); - return; - } - - if (!goog.dom.classlist.contains(element, className)) { - // Ensure we add a space if this is not the first class name added. - element.className += element.className.length > 0 ? - (' ' + className) : className; - } -}; - - -/** - * Convenience method to add a number of class names at once. - * @param {Element} element The element to which to add classes. - * @param {goog.array.ArrayLike} classesToAdd An array-like object - * containing a collection of class names to add to the element. - * This method may throw a DOM exception if classesToAdd contains invalid - * or empty class names. - */ -goog.dom.classlist.addAll = function(element, classesToAdd) { - if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) { - goog.array.forEach(classesToAdd, function(className) { - goog.dom.classlist.add(element, className); - }); - return; - } - - var classMap = {}; - - // Get all current class names into a map. - goog.array.forEach(goog.dom.classlist.get(element), - function(className) { - classMap[className] = true; - }); - - // Add new class names to the map. - goog.array.forEach(classesToAdd, - function(className) { - classMap[className] = true; - }); - - // Flatten the keys of the map into the className. - element.className = ''; - for (var className in classMap) { - element.className += element.className.length > 0 ? - (' ' + className) : className; - } -}; - - -/** - * Removes a class from an element. This method may throw a DOM exception - * for an invalid or empty class name if DOMTokenList is used. - * @param {Element} element DOM node to remove class from. - * @param {string} className Class name to remove. - */ -goog.dom.classlist.remove = function(element, className) { - if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) { - element.classList.remove(className); - return; - } - - if (goog.dom.classlist.contains(element, className)) { - // Filter out the class name. - element.className = goog.array.filter( - goog.dom.classlist.get(element), - function(c) { - return c != className; - }).join(' '); - } -}; - - -/** - * Removes a set of classes from an element. Prefer this call to - * repeatedly calling {@code goog.dom.classlist.remove} if you want to remove - * a large set of class names at once. - * @param {Element} element The element from which to remove classes. - * @param {goog.array.ArrayLike} classesToRemove An array-like object - * containing a collection of class names to remove from the element. - * This method may throw a DOM exception if classesToRemove contains invalid - * or empty class names. - */ -goog.dom.classlist.removeAll = function(element, classesToRemove) { - if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) { - goog.array.forEach(classesToRemove, function(className) { - goog.dom.classlist.remove(element, className); - }); - return; - } - // Filter out those classes in classesToRemove. - element.className = goog.array.filter( - goog.dom.classlist.get(element), - function(className) { - // If this class is not one we are trying to remove, - // add it to the array of new class names. - return !goog.array.contains(classesToRemove, className); - }).join(' '); -}; - - -/** - * Adds or removes a class depending on the enabled argument. This method - * may throw a DOM exception for an invalid or empty class name if DOMTokenList - * is used. - * @param {Element} element DOM node to add or remove the class on. - * @param {string} className Class name to add or remove. - * @param {boolean} enabled Whether to add or remove the class (true adds, - * false removes). - */ -goog.dom.classlist.enable = function(element, className, enabled) { - if (enabled) { - goog.dom.classlist.add(element, className); - } else { - goog.dom.classlist.remove(element, className); - } -}; - - -/** - * Adds or removes a set of classes depending on the enabled argument. This - * method may throw a DOM exception for an invalid or empty class name if - * DOMTokenList is used. - * @param {!Element} element DOM node to add or remove the class on. - * @param {goog.array.ArrayLike} classesToEnable An array-like object - * containing a collection of class names to add or remove from the element. - * @param {boolean} enabled Whether to add or remove the classes (true adds, - * false removes). - */ -goog.dom.classlist.enableAll = function(element, classesToEnable, enabled) { - var f = enabled ? goog.dom.classlist.addAll : - goog.dom.classlist.removeAll; - f(element, classesToEnable); -}; - - -/** - * Switches a class on an element from one to another without disturbing other - * classes. If the fromClass isn't removed, the toClass won't be added. This - * method may throw a DOM exception if the class names are empty or invalid. - * @param {Element} element DOM node to swap classes on. - * @param {string} fromClass Class to remove. - * @param {string} toClass Class to add. - * @return {boolean} Whether classes were switched. - */ -goog.dom.classlist.swap = function(element, fromClass, toClass) { - if (goog.dom.classlist.contains(element, fromClass)) { - goog.dom.classlist.remove(element, fromClass); - goog.dom.classlist.add(element, toClass); - return true; - } - return false; -}; - - -/** - * Removes a class if an element has it, and adds it the element doesn't have - * it. Won't affect other classes on the node. This method may throw a DOM - * exception if the class name is empty or invalid. - * @param {Element} element DOM node to toggle class on. - * @param {string} className Class to toggle. - * @return {boolean} True if class was added, false if it was removed - * (in other words, whether element has the class after this function has - * been called). - */ -goog.dom.classlist.toggle = function(element, className) { - var add = !goog.dom.classlist.contains(element, className); - goog.dom.classlist.enable(element, className, add); - return add; -}; - - -/** - * Adds and removes a class of an element. Unlike - * {@link goog.dom.classlist.swap}, this method adds the classToAdd regardless - * of whether the classToRemove was present and had been removed. This method - * may throw a DOM exception if the class names are empty or invalid. - * - * @param {Element} element DOM node to swap classes on. - * @param {string} classToRemove Class to remove. - * @param {string} classToAdd Class to add. - */ -goog.dom.classlist.addRemove = function(element, classToRemove, classToAdd) { - goog.dom.classlist.remove(element, classToRemove); - goog.dom.classlist.add(element, classToAdd); -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/classlist_test.html b/src/database/third_party/closure-library/closure/goog/dom/classlist_test.html deleted file mode 100644 index 01df6537230..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/classlist_test.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - -Closure Unit Tests - goog.dom.classlist - - - - -

    -

    - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/classlist_test.js b/src/database/third_party/closure-library/closure/goog/dom/classlist_test.js deleted file mode 100644 index 927bd01ce2c..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/classlist_test.js +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright 2012 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Shared code for classlist_test.html. - */ - -goog.provide('goog.dom.classlist_test'); -goog.setTestOnly('goog.dom.classlist_test'); - -goog.require('goog.dom'); -goog.require('goog.dom.classlist'); -goog.require('goog.testing.ExpectedFailures'); -goog.require('goog.testing.jsunit'); - -var expectedFailures = new goog.testing.ExpectedFailures(); -var classlist = goog.dom.classlist; - -function tearDown() { - expectedFailures.handleTearDown(); -} - -function testGet() { - var el = document.createElement('div'); - assertTrue(classlist.get(el).length == 0); - el.className = 'C'; - assertElementsEquals(['C'], classlist.get(el)); - el.className = 'C D'; - assertElementsEquals(['C', 'D'], classlist.get(el)); - el.className = 'C\nD'; - assertElementsEquals(['C', 'D'], classlist.get(el)); - el.className = ' C '; - assertElementsEquals(['C'], classlist.get(el)); -} - -function testContainsWithNewlines() { - var el = goog.dom.getElement('p1'); - assertTrue('Should not have SOMECLASS', classlist.contains(el, 'SOMECLASS')); - assertTrue('Should also have OTHERCLASS', - classlist.contains(el, 'OTHERCLASS')); - assertFalse('Should not have WEIRDCLASS', - classlist.contains(el, 'WEIRDCLASS')); -} - -function testContainsCaseSensitive() { - var el = goog.dom.getElement('p2'); - assertFalse('Should not have camelcase', - classlist.contains(el, 'camelcase')); - assertFalse('Should not have CAMELCASE', - classlist.contains(el, 'CAMELCASE')); - assertTrue('Should have camelCase', - classlist.contains(el, 'camelCase')); -} - -function testAddNotAddingMultiples() { - var el = document.createElement('div'); - classlist.add(el, 'A'); - assertEquals('A', el.className); - classlist.add(el, 'A'); - assertEquals('A', el.className); - classlist.add(el, 'B', 'B'); - assertEquals('A B', el.className); -} - -function testAddCaseSensitive() { - var el = document.createElement('div'); - classlist.add(el, 'A'); - assertTrue(classlist.contains(el, 'A')); - assertFalse(classlist.contains(el, 'a')); - classlist.add(el, 'a'); - assertTrue(classlist.contains(el, 'A')); - assertTrue(classlist.contains(el, 'a')); - assertEquals('A a', el.className); -} - -function testAddAll() { - var elem = document.createElement('div'); - elem.className = 'foo goog-bar'; - - goog.dom.classlist.addAll(elem, ['goog-baz', 'foo']); - assertEquals(3, classlist.get(elem).length); - assertTrue(goog.dom.classlist.contains(elem, 'foo')); - assertTrue(goog.dom.classlist.contains(elem, 'goog-bar')); - assertTrue(goog.dom.classlist.contains(elem, 'goog-baz')); -} - -function testAddAllEmpty() { - var classes = 'foo bar'; - var elem = document.createElement('div'); - elem.className = classes; - - goog.dom.classlist.addAll(elem, []); - assertEquals(elem.className, classes); -} - -function testRemove() { - var el = document.createElement('div'); - el.className = 'A B C'; - classlist.remove(el, 'B'); - assertEquals('A C', el.className); -} - -function testRemoveCaseSensitive() { - var el = document.createElement('div'); - el.className = 'A B C'; - classlist.remove(el, 'b'); - assertEquals('A B C', el.className); -} - -function testRemoveAll() { - var elem = document.createElement('div'); - elem.className = 'foo bar baz'; - - goog.dom.classlist.removeAll(elem, ['bar', 'foo']); - assertFalse(goog.dom.classlist.contains(elem, 'foo')); - assertFalse(goog.dom.classlist.contains(elem, 'bar')); - assertTrue(goog.dom.classlist.contains(elem, 'baz')); -} - -function testRemoveAllOne() { - var elem = document.createElement('div'); - elem.className = 'foo bar baz'; - - goog.dom.classlist.removeAll(elem, ['bar']); - assertFalse(goog.dom.classlist.contains(elem, 'bar')); - assertTrue(goog.dom.classlist.contains(elem, 'foo')); - assertTrue(goog.dom.classlist.contains(elem, 'baz')); -} - -function testRemoveAllSomeNotPresent() { - var elem = document.createElement('div'); - elem.className = 'foo bar baz'; - - goog.dom.classlist.removeAll(elem, ['a', 'bar']); - assertTrue(goog.dom.classlist.contains(elem, 'foo')); - assertFalse(goog.dom.classlist.contains(elem, 'bar')); - assertTrue(goog.dom.classlist.contains(elem, 'baz')); -} - -function testRemoveAllCaseSensitive() { - var elem = document.createElement('div'); - elem.className = 'foo bar baz'; - - goog.dom.classlist.removeAll(elem, ['BAR', 'foo']); - assertFalse(goog.dom.classlist.contains(elem, 'foo')); - assertTrue(goog.dom.classlist.contains(elem, 'bar')); - assertTrue(goog.dom.classlist.contains(elem, 'baz')); -} - -function testEnable() { - var el = goog.dom.getElement('p1'); - classlist.set(el, 'SOMECLASS FIRST'); - - assertTrue('Should have FIRST class', classlist.contains(el, 'FIRST')); - assertTrue('Should have SOMECLASS class', - classlist.contains(el, 'SOMECLASS')); - - classlist.enable(el, 'FIRST', false); - - assertFalse('Should not have FIRST class', classlist.contains(el, 'FIRST')); - assertTrue('Should have SOMECLASS class', - classlist.contains(el, 'SOMECLASS')); - - classlist.enable(el, 'FIRST', true); - - assertTrue('Should have FIRST class', classlist.contains(el, 'FIRST')); - assertTrue('Should have SOMECLASS class', - classlist.contains(el, 'SOMECLASS')); -} - -function testEnableNotAddingMultiples() { - var el = document.createElement('div'); - classlist.enable(el, 'A', true); - assertEquals('A', el.className); - classlist.enable(el, 'A', true); - assertEquals('A', el.className); - classlist.enable(el, 'B', 'B', true); - assertEquals('A B', el.className); -} - -function testEnableAllRemove() { - var elem = document.createElement('div'); - elem.className = 'foo bar baz'; - - // Test removing some classes (some not present). - goog.dom.classlist.enableAll(elem, ['a', 'bar'], false /* enable */); - assertTrue(goog.dom.classlist.contains(elem, 'foo')); - assertFalse(goog.dom.classlist.contains(elem, 'bar')); - assertTrue(goog.dom.classlist.contains(elem, 'baz')); - assertFalse(goog.dom.classlist.contains(elem, 'a')); -} - -function testEnableAllAdd() { - var elem = document.createElement('div'); - elem.className = 'foo bar'; - - // Test adding some classes (some duplicate). - goog.dom.classlist.enableAll(elem, ['a', 'bar', 'baz'], true /* enable */); - assertTrue(goog.dom.classlist.contains(elem, 'foo')); - assertTrue(goog.dom.classlist.contains(elem, 'bar')); - assertTrue(goog.dom.classlist.contains(elem, 'baz')); - assertTrue(goog.dom.classlist.contains(elem, 'a')); -} - -function testSwap() { - var el = goog.dom.getElement('p1'); - classlist.set(el, 'SOMECLASS FIRST'); - - assertTrue('Should have FIRST class', classlist.contains(el, 'FIRST')); - assertTrue('Should have FIRST class', classlist.contains(el, 'SOMECLASS')); - assertFalse('Should not have second class', classlist.contains(el, 'second')); - - classlist.swap(el, 'FIRST', 'second'); - - assertFalse('Should not have FIRST class', classlist.contains(el, 'FIRST')); - assertTrue('Should have FIRST class', classlist.contains(el, 'SOMECLASS')); - assertTrue('Should have second class', classlist.contains(el, 'second')); - - classlist.swap(el, 'second', 'FIRST'); - - assertTrue('Should have FIRST class', classlist.contains(el, 'FIRST')); - assertTrue('Should have FIRST class', classlist.contains(el, 'SOMECLASS')); - assertFalse('Should not have second class', classlist.contains(el, 'second')); -} - -function testToggle() { - var el = goog.dom.getElement('p1'); - classlist.set(el, 'SOMECLASS FIRST'); - - assertTrue('Should have FIRST class', classlist.contains(el, 'FIRST')); - assertTrue('Should have SOMECLASS class', - classlist.contains(el, 'SOMECLASS')); - - var ret = classlist.toggle(el, 'FIRST'); - - assertFalse('Should not have FIRST class', classlist.contains(el, 'FIRST')); - assertTrue('Should have SOMECLASS class', - classlist.contains(el, 'SOMECLASS')); - assertFalse('Return value should have been false', ret); - - ret = classlist.toggle(el, 'FIRST'); - - assertTrue('Should have FIRST class', classlist.contains(el, 'FIRST')); - assertTrue('Should have SOMECLASS class', - classlist.contains(el, 'SOMECLASS')); - assertTrue('Return value should have been true', ret); -} - -function testAddRemoveString() { - var el = document.createElement('div'); - el.className = 'A'; - - classlist.addRemove(el, 'A', 'B'); - assertEquals('B', el.className); - - classlist.addRemove(el, 'Z', 'C'); - assertEquals('B C', el.className); - - classlist.addRemove(el, 'C', 'D'); - assertEquals('B D', el.className); - - classlist.addRemove(el, 'D', 'B'); - assertEquals('B', el.className); -} diff --git a/src/database/third_party/closure-library/closure/goog/dom/controlrange.js b/src/database/third_party/closure-library/closure/goog/dom/controlrange.js deleted file mode 100644 index cf3256adcba..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/controlrange.js +++ /dev/null @@ -1,506 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utilities for working with IE control ranges. - * - * @author robbyw@google.com (Robby Walker) - */ - - -goog.provide('goog.dom.ControlRange'); -goog.provide('goog.dom.ControlRangeIterator'); - -goog.require('goog.array'); -goog.require('goog.dom'); -goog.require('goog.dom.AbstractMultiRange'); -goog.require('goog.dom.AbstractRange'); -goog.require('goog.dom.RangeIterator'); -goog.require('goog.dom.RangeType'); -goog.require('goog.dom.SavedRange'); -goog.require('goog.dom.TagWalkType'); -goog.require('goog.dom.TextRange'); -goog.require('goog.iter.StopIteration'); -goog.require('goog.userAgent'); - - - -/** - * Create a new control selection with no properties. Do not use this - * constructor: use one of the goog.dom.Range.createFrom* methods instead. - * @constructor - * @extends {goog.dom.AbstractMultiRange} - * @final - */ -goog.dom.ControlRange = function() { -}; -goog.inherits(goog.dom.ControlRange, goog.dom.AbstractMultiRange); - - -/** - * Create a new range wrapper from the given browser range object. Do not use - * this method directly - please use goog.dom.Range.createFrom* instead. - * @param {Object} controlRange The browser range object. - * @return {!goog.dom.ControlRange} A range wrapper object. - */ -goog.dom.ControlRange.createFromBrowserRange = function(controlRange) { - var range = new goog.dom.ControlRange(); - range.range_ = controlRange; - return range; -}; - - -/** - * Create a new range wrapper that selects the given element. Do not use - * this method directly - please use goog.dom.Range.createFrom* instead. - * @param {...Element} var_args The element(s) to select. - * @return {!goog.dom.ControlRange} A range wrapper object. - */ -goog.dom.ControlRange.createFromElements = function(var_args) { - var range = goog.dom.getOwnerDocument(arguments[0]).body.createControlRange(); - for (var i = 0, len = arguments.length; i < len; i++) { - range.addElement(arguments[i]); - } - return goog.dom.ControlRange.createFromBrowserRange(range); -}; - - -/** - * The IE control range obejct. - * @type {Object} - * @private - */ -goog.dom.ControlRange.prototype.range_ = null; - - -/** - * Cached list of elements. - * @type {Array?} - * @private - */ -goog.dom.ControlRange.prototype.elements_ = null; - - -/** - * Cached sorted list of elements. - * @type {Array?} - * @private - */ -goog.dom.ControlRange.prototype.sortedElements_ = null; - - -// Method implementations - - -/** - * Clear cached values. - * @private - */ -goog.dom.ControlRange.prototype.clearCachedValues_ = function() { - this.elements_ = null; - this.sortedElements_ = null; -}; - - -/** @override */ -goog.dom.ControlRange.prototype.clone = function() { - return goog.dom.ControlRange.createFromElements.apply(this, - this.getElements()); -}; - - -/** @override */ -goog.dom.ControlRange.prototype.getType = function() { - return goog.dom.RangeType.CONTROL; -}; - - -/** @override */ -goog.dom.ControlRange.prototype.getBrowserRangeObject = function() { - return this.range_ || document.body.createControlRange(); -}; - - -/** @override */ -goog.dom.ControlRange.prototype.setBrowserRangeObject = function(nativeRange) { - if (!goog.dom.AbstractRange.isNativeControlRange(nativeRange)) { - return false; - } - this.range_ = nativeRange; - return true; -}; - - -/** @override */ -goog.dom.ControlRange.prototype.getTextRangeCount = function() { - return this.range_ ? this.range_.length : 0; -}; - - -/** @override */ -goog.dom.ControlRange.prototype.getTextRange = function(i) { - return goog.dom.TextRange.createFromNodeContents(this.range_.item(i)); -}; - - -/** @override */ -goog.dom.ControlRange.prototype.getContainer = function() { - return goog.dom.findCommonAncestor.apply(null, this.getElements()); -}; - - -/** @override */ -goog.dom.ControlRange.prototype.getStartNode = function() { - return this.getSortedElements()[0]; -}; - - -/** @override */ -goog.dom.ControlRange.prototype.getStartOffset = function() { - return 0; -}; - - -/** @override */ -goog.dom.ControlRange.prototype.getEndNode = function() { - var sorted = this.getSortedElements(); - var startsLast = /** @type {Node} */ (goog.array.peek(sorted)); - return /** @type {Node} */ (goog.array.find(sorted, function(el) { - return goog.dom.contains(el, startsLast); - })); -}; - - -/** @override */ -goog.dom.ControlRange.prototype.getEndOffset = function() { - return this.getEndNode().childNodes.length; -}; - - -// TODO(robbyw): Figure out how to unify getElements with TextRange API. -/** - * @return {!Array} Array of elements in the control range. - */ -goog.dom.ControlRange.prototype.getElements = function() { - if (!this.elements_) { - this.elements_ = []; - if (this.range_) { - for (var i = 0; i < this.range_.length; i++) { - this.elements_.push(this.range_.item(i)); - } - } - } - - return this.elements_; -}; - - -/** - * @return {!Array} Array of elements comprising the control range, - * sorted by document order. - */ -goog.dom.ControlRange.prototype.getSortedElements = function() { - if (!this.sortedElements_) { - this.sortedElements_ = this.getElements().concat(); - this.sortedElements_.sort(function(a, b) { - return a.sourceIndex - b.sourceIndex; - }); - } - - return this.sortedElements_; -}; - - -/** @override */ -goog.dom.ControlRange.prototype.isRangeInDocument = function() { - var returnValue = false; - - try { - returnValue = goog.array.every(this.getElements(), function(element) { - // On IE, this throws an exception when the range is detached. - return goog.userAgent.IE ? - !!element.parentNode : - goog.dom.contains(element.ownerDocument.body, element); - }); - } catch (e) { - // IE sometimes throws Invalid Argument errors for detached elements. - // Note: trying to return a value from the above try block can cause IE - // to crash. It is necessary to use the local returnValue. - } - - return returnValue; -}; - - -/** @override */ -goog.dom.ControlRange.prototype.isCollapsed = function() { - return !this.range_ || !this.range_.length; -}; - - -/** @override */ -goog.dom.ControlRange.prototype.getText = function() { - // TODO(robbyw): What about for table selections? Should those have text? - return ''; -}; - - -/** @override */ -goog.dom.ControlRange.prototype.getHtmlFragment = function() { - return goog.array.map(this.getSortedElements(), goog.dom.getOuterHtml). - join(''); -}; - - -/** @override */ -goog.dom.ControlRange.prototype.getValidHtml = function() { - return this.getHtmlFragment(); -}; - - -/** @override */ -goog.dom.ControlRange.prototype.getPastableHtml = - goog.dom.ControlRange.prototype.getValidHtml; - - -/** @override */ -goog.dom.ControlRange.prototype.__iterator__ = function(opt_keys) { - return new goog.dom.ControlRangeIterator(this); -}; - - -// RANGE ACTIONS - - -/** @override */ -goog.dom.ControlRange.prototype.select = function() { - if (this.range_) { - this.range_.select(); - } -}; - - -/** @override */ -goog.dom.ControlRange.prototype.removeContents = function() { - // TODO(robbyw): Test implementing with execCommand('Delete') - if (this.range_) { - var nodes = []; - for (var i = 0, len = this.range_.length; i < len; i++) { - nodes.push(this.range_.item(i)); - } - goog.array.forEach(nodes, goog.dom.removeNode); - - this.collapse(false); - } -}; - - -/** @override */ -goog.dom.ControlRange.prototype.replaceContentsWithNode = function(node) { - // Control selections have to have the node inserted before removing the - // selection contents because a collapsed control range doesn't have start or - // end nodes. - var result = this.insertNode(node, true); - - if (!this.isCollapsed()) { - this.removeContents(); - } - - return result; -}; - - -// SAVE/RESTORE - - -/** @override */ -goog.dom.ControlRange.prototype.saveUsingDom = function() { - return new goog.dom.DomSavedControlRange_(this); -}; - - -// RANGE MODIFICATION - - -/** @override */ -goog.dom.ControlRange.prototype.collapse = function(toAnchor) { - // TODO(robbyw): Should this return a text range? If so, API needs to change. - this.range_ = null; - this.clearCachedValues_(); -}; - - -// SAVED RANGE OBJECTS - - - -/** - * A SavedRange implementation using DOM endpoints. - * @param {goog.dom.ControlRange} range The range to save. - * @constructor - * @extends {goog.dom.SavedRange} - * @private - */ -goog.dom.DomSavedControlRange_ = function(range) { - /** - * The element list. - * @type {Array} - * @private - */ - this.elements_ = range.getElements(); -}; -goog.inherits(goog.dom.DomSavedControlRange_, goog.dom.SavedRange); - - -/** @override */ -goog.dom.DomSavedControlRange_.prototype.restoreInternal = function() { - var doc = this.elements_.length ? - goog.dom.getOwnerDocument(this.elements_[0]) : document; - var controlRange = doc.body.createControlRange(); - for (var i = 0, len = this.elements_.length; i < len; i++) { - controlRange.addElement(this.elements_[i]); - } - return goog.dom.ControlRange.createFromBrowserRange(controlRange); -}; - - -/** @override */ -goog.dom.DomSavedControlRange_.prototype.disposeInternal = function() { - goog.dom.DomSavedControlRange_.superClass_.disposeInternal.call(this); - delete this.elements_; -}; - - -// RANGE ITERATION - - - -/** - * Subclass of goog.dom.TagIterator that iterates over a DOM range. It - * adds functions to determine the portion of each text node that is selected. - * - * @param {goog.dom.ControlRange?} range The range to traverse. - * @constructor - * @extends {goog.dom.RangeIterator} - * @final - */ -goog.dom.ControlRangeIterator = function(range) { - if (range) { - this.elements_ = range.getSortedElements(); - this.startNode_ = this.elements_.shift(); - this.endNode_ = /** @type {Node} */ (goog.array.peek(this.elements_)) || - this.startNode_; - } - - goog.dom.RangeIterator.call(this, this.startNode_, false); -}; -goog.inherits(goog.dom.ControlRangeIterator, goog.dom.RangeIterator); - - -/** - * The first node in the selection. - * @type {Node} - * @private - */ -goog.dom.ControlRangeIterator.prototype.startNode_ = null; - - -/** - * The last node in the selection. - * @type {Node} - * @private - */ -goog.dom.ControlRangeIterator.prototype.endNode_ = null; - - -/** - * The list of elements left to traverse. - * @type {Array?} - * @private - */ -goog.dom.ControlRangeIterator.prototype.elements_ = null; - - -/** @override */ -goog.dom.ControlRangeIterator.prototype.getStartTextOffset = function() { - return 0; -}; - - -/** @override */ -goog.dom.ControlRangeIterator.prototype.getEndTextOffset = function() { - return 0; -}; - - -/** @override */ -goog.dom.ControlRangeIterator.prototype.getStartNode = function() { - return this.startNode_; -}; - - -/** @override */ -goog.dom.ControlRangeIterator.prototype.getEndNode = function() { - return this.endNode_; -}; - - -/** @override */ -goog.dom.ControlRangeIterator.prototype.isLast = function() { - return !this.depth && !this.elements_.length; -}; - - -/** - * Move to the next position in the selection. - * Throws {@code goog.iter.StopIteration} when it passes the end of the range. - * @return {Node} The node at the next position. - * @override - */ -goog.dom.ControlRangeIterator.prototype.next = function() { - // Iterate over each element in the range, and all of its children. - if (this.isLast()) { - throw goog.iter.StopIteration; - } else if (!this.depth) { - var el = this.elements_.shift(); - this.setPosition(el, - goog.dom.TagWalkType.START_TAG, - goog.dom.TagWalkType.START_TAG); - return el; - } - - // Call the super function. - return goog.dom.ControlRangeIterator.superClass_.next.call(this); -}; - - -/** @override */ -goog.dom.ControlRangeIterator.prototype.copyFrom = function(other) { - this.elements_ = other.elements_; - this.startNode_ = other.startNode_; - this.endNode_ = other.endNode_; - - goog.dom.ControlRangeIterator.superClass_.copyFrom.call(this, other); -}; - - -/** - * @return {!goog.dom.ControlRangeIterator} An identical iterator. - * @override - */ -goog.dom.ControlRangeIterator.prototype.clone = function() { - var copy = new goog.dom.ControlRangeIterator(null); - copy.copyFrom(this); - return copy; -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/controlrange_test.html b/src/database/third_party/closure-library/closure/goog/dom/controlrange_test.html deleted file mode 100644 index 4bd100fd220..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/controlrange_test.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - - -Closure Unit Tests - goog.dom.ControlRange - - - - -
    -
    - -
    - -
    ab
    cd
    - - - - - - - -
    moof
    - foo - - bar -
    - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/controlrange_test.js b/src/database/third_party/closure-library/closure/goog/dom/controlrange_test.js deleted file mode 100644 index 59b011d805b..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/controlrange_test.js +++ /dev/null @@ -1,228 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.dom.ControlRangeTest'); -goog.setTestOnly('goog.dom.ControlRangeTest'); - -goog.require('goog.dom'); -goog.require('goog.dom.ControlRange'); -goog.require('goog.dom.RangeType'); -goog.require('goog.dom.TagName'); -goog.require('goog.dom.TextRange'); -goog.require('goog.testing.dom'); -goog.require('goog.testing.jsunit'); -goog.require('goog.userAgent'); - -var logo; -var table; - -function setUpPage() { - logo = goog.dom.getElement('logo'); - table = goog.dom.getElement('table'); -} - -function testCreateFromElement() { - if (!goog.userAgent.IE) { - return; - } - assertNotNull('Control range object can be created for element', - goog.dom.ControlRange.createFromElements(logo)); -} - -function testCreateFromRange() { - if (!goog.userAgent.IE) { - return; - } - var range = document.body.createControlRange(); - range.addElement(table); - assertNotNull('Control range object can be created for element', - goog.dom.ControlRange.createFromBrowserRange(range)); -} - -function testSelect() { - if (!goog.userAgent.IE || goog.userAgent.isVersionOrHigher('11')) { - return; - } - - var range = goog.dom.ControlRange.createFromElements(table); - range.select(); - - assertEquals('Control range should be selected', 'Control', - document.selection.type); - assertEquals('Control range should have length 1', 1, - document.selection.createRange().length); - assertEquals('Control range should select table', table, - document.selection.createRange().item(0)); -} - -function testControlRangeIterator() { - if (!goog.userAgent.IE) { - return; - } - var range = goog.dom.ControlRange.createFromElements(logo, table); - // Each node is included twice - once as a start tag, once as an end. - goog.testing.dom.assertNodesMatch(range, ['#logo', '#logo', '#table', - '#tbody', '#tr1', '#td11', 'a', '#td11', '#td12', 'b', '#td12', '#tr1', - '#tr2', '#td21', 'c', '#td21', '#td22', 'd', '#td22', '#tr2', '#tbody', - '#table']); -} - -function testBounds() { - if (!goog.userAgent.IE) { - return; - } - - // Initialize in both orders. - helpTestBounds(goog.dom.ControlRange.createFromElements(logo, table)); - helpTestBounds(goog.dom.ControlRange.createFromElements(table, logo)); -} - -function helpTestBounds(range) { - assertEquals('Start node is logo', logo, range.getStartNode()); - assertEquals('Start offset is 0', 0, range.getStartOffset()); - assertEquals('End node is table', table, range.getEndNode()); - assertEquals('End offset is 1', 1, range.getEndOffset()); -} - -function testCollapse() { - if (!goog.userAgent.IE) { - return; - } - - var range = goog.dom.ControlRange.createFromElements(logo, table); - assertFalse('Not initially collapsed', range.isCollapsed()); - range.collapse(); - assertTrue('Successfully collapsed', range.isCollapsed()); -} - -function testGetContainer() { - if (!goog.userAgent.IE) { - return; - } - - var range = goog.dom.ControlRange.createFromElements(logo); - assertEquals('Single element range is contained by itself', logo, - range.getContainer()); - - range = goog.dom.ControlRange.createFromElements(logo, table); - assertEquals('Two element range is contained by body', document.body, - range.getContainer()); -} - -function testSave() { - if (!goog.userAgent.IE) { - return; - } - - var range = goog.dom.ControlRange.createFromElements(logo, table); - var savedRange = range.saveUsingDom(); - - range.collapse(); - assertTrue('Successfully collapsed', range.isCollapsed()); - - range = savedRange.restore(); - assertEquals('Restored a control range', goog.dom.RangeType.CONTROL, - range.getType()); - assertFalse('Not collapsed after restore', range.isCollapsed()); - helpTestBounds(range); -} - -function testRemoveContents() { - if (!goog.userAgent.IE) { - return; - } - - var img = goog.dom.createDom('IMG'); - img.src = logo.src; - - var div = goog.dom.getElement('test1'); - div.innerHTML = ''; - div.appendChild(img); - assertEquals('Div has 1 child', 1, div.childNodes.length); - - var range = goog.dom.ControlRange.createFromElements(img); - range.removeContents(); - assertEquals('Div has 0 children', 0, div.childNodes.length); - assertTrue('Range is collapsed', range.isCollapsed()); -} - -function testReplaceContents() { - // Test a control range. - if (!goog.userAgent.IE) { - return; - } - - var outer = goog.dom.getElement('test1'); - outer.innerHTML = - '
    ' + - 'Hello ' + - '
    '; - range = goog.dom.ControlRange.createFromElements( - outer.getElementsByTagName(goog.dom.TagName.INPUT)[0]); - goog.dom.ControlRange.createFromElements(table); - range.replaceContentsWithNode(goog.dom.createTextNode('World')); - assertEquals('Hello World', outer.firstChild.innerHTML); -} - -function testContainsRange() { - if (!goog.userAgent.IE) { - return; - } - - var table2 = goog.dom.getElement('table2'); - var table2td = goog.dom.getElement('table2td'); - var logo2 = goog.dom.getElement('logo2'); - - var range = goog.dom.ControlRange.createFromElements(logo, table); - var range2 = goog.dom.ControlRange.createFromElements(logo); - assertTrue('Control range contains the other control range', - range.containsRange(range2)); - assertTrue('Control range partially contains the other control range', - range2.containsRange(range, true)); - - range2 = goog.dom.ControlRange.createFromElements(table2); - assertFalse('Control range does not contain the other control range', - range.containsRange(range2)); - - range = goog.dom.ControlRange.createFromElements(table2); - range2 = goog.dom.TextRange.createFromNodeContents(table2td); - assertTrue('Control range contains text range', - range.containsRange(range2)); - - range2 = goog.dom.TextRange.createFromNodeContents(table); - assertFalse('Control range does not contain text range', - range.containsRange(range2)); - - range = goog.dom.ControlRange.createFromElements(logo2); - range2 = goog.dom.TextRange.createFromNodeContents(table2); - assertFalse('Control range does not fully contain text range', - range.containsRange(range2, false)); - - range2 = goog.dom.ControlRange.createFromElements(table2); - assertTrue('Control range contains the other control range (2)', - range2.containsRange(range)); -} - -function testCloneRange() { - if (!goog.userAgent.IE) { - return; - } - var range = goog.dom.ControlRange.createFromElements(logo); - assertNotNull('Control range object created for element', range); - - var cloneRange = range.clone(); - assertNotNull('Cloned control range object', cloneRange); - assertArrayEquals('Control range and clone have same elements', - range.getElements(), cloneRange.getElements()); -} diff --git a/src/database/third_party/closure-library/closure/goog/dom/dataset.js b/src/database/third_party/closure-library/closure/goog/dom/dataset.js deleted file mode 100644 index e7741d6fb6b..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/dataset.js +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright 2009 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utilities for adding, removing and setting values in - * an Element's dataset. - * See {@link http://www.w3.org/TR/html5/Overview.html#dom-dataset}. - * - */ - -goog.provide('goog.dom.dataset'); - -goog.require('goog.string'); -goog.require('goog.userAgent.product'); - - -/** - * Whether using the dataset property is allowed. In IE (up to and including - * IE 11), setting element.dataset in JS does not propagate values to CSS, - * breaking expressions such as `content: attr(data-content)` that would - * otherwise work. - * See {@link https://github.com/google/closure-library/issues/396}. - * @const - * @private - */ -goog.dom.dataset.ALLOWED_ = !goog.userAgent.product.IE; - - -/** - * The DOM attribute name prefix that must be present for it to be considered - * for a dataset. - * @type {string} - * @const - * @private - */ -goog.dom.dataset.PREFIX_ = 'data-'; - - -/** - * Sets a custom data attribute on an element. The key should be - * in camelCase format (e.g "keyName" for the "data-key-name" attribute). - * @param {Element} element DOM node to set the custom data attribute on. - * @param {string} key Key for the custom data attribute. - * @param {string} value Value for the custom data attribute. - */ -goog.dom.dataset.set = function(element, key, value) { - if (goog.dom.dataset.ALLOWED_ && element.dataset) { - element.dataset[key] = value; - } else { - element.setAttribute( - goog.dom.dataset.PREFIX_ + goog.string.toSelectorCase(key), - value); - } -}; - - -/** - * Gets a custom data attribute from an element. The key should be - * in camelCase format (e.g "keyName" for the "data-key-name" attribute). - * @param {Element} element DOM node to get the custom data attribute from. - * @param {string} key Key for the custom data attribute. - * @return {?string} The attribute value, if it exists. - */ -goog.dom.dataset.get = function(element, key) { - if (goog.dom.dataset.ALLOWED_ && element.dataset) { - // Android browser (non-chrome) returns the empty string for - // element.dataset['doesNotExist']. - if (!(key in element.dataset)) { - return null; - } - return element.dataset[key]; - } else { - return element.getAttribute(goog.dom.dataset.PREFIX_ + - goog.string.toSelectorCase(key)); - } -}; - - -/** - * Removes a custom data attribute from an element. The key should be - * in camelCase format (e.g "keyName" for the "data-key-name" attribute). - * @param {Element} element DOM node to get the custom data attribute from. - * @param {string} key Key for the custom data attribute. - */ -goog.dom.dataset.remove = function(element, key) { - if (goog.dom.dataset.ALLOWED_ && element.dataset) { - delete element.dataset[key]; - } else { - element.removeAttribute(goog.dom.dataset.PREFIX_ + - goog.string.toSelectorCase(key)); - } -}; - - -/** - * Checks whether custom data attribute exists on an element. The key should be - * in camelCase format (e.g "keyName" for the "data-key-name" attribute). - * - * @param {Element} element DOM node to get the custom data attribute from. - * @param {string} key Key for the custom data attribute. - * @return {boolean} Whether the attribute exists. - */ -goog.dom.dataset.has = function(element, key) { - if (goog.dom.dataset.ALLOWED_ && element.dataset) { - return key in element.dataset; - } else if (element.hasAttribute) { - return element.hasAttribute(goog.dom.dataset.PREFIX_ + - goog.string.toSelectorCase(key)); - } else { - return !!(element.getAttribute(goog.dom.dataset.PREFIX_ + - goog.string.toSelectorCase(key))); - } -}; - - -/** - * Gets all custom data attributes as a string map. The attribute names will be - * camel cased (e.g., data-foo-bar -> dataset['fooBar']). This operation is not - * safe for attributes having camel-cased names clashing with already existing - * properties (e.g., data-to-string -> dataset['toString']). - * @param {!Element} element DOM node to get the data attributes from. - * @return {!Object} The string map containing data attributes and their - * respective values. - */ -goog.dom.dataset.getAll = function(element) { - if (goog.dom.dataset.ALLOWED_ && element.dataset) { - return element.dataset; - } else { - var dataset = {}; - var attributes = element.attributes; - for (var i = 0; i < attributes.length; ++i) { - var attribute = attributes[i]; - if (goog.string.startsWith(attribute.name, - goog.dom.dataset.PREFIX_)) { - // We use substr(5), since it's faster than replacing 'data-' with ''. - var key = goog.string.toCamelCase(attribute.name.substr(5)); - dataset[key] = attribute.value; - } - } - return dataset; - } -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/dataset_test.html b/src/database/third_party/closure-library/closure/goog/dom/dataset_test.html deleted file mode 100644 index 8599bdf9ceb..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/dataset_test.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - -Closure Unit Tests - goog.dom.dataset - - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/dataset_test.js b/src/database/third_party/closure-library/closure/goog/dom/dataset_test.js deleted file mode 100644 index 83cc7699eb6..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/dataset_test.js +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2011 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.dom.datasetTest'); -goog.setTestOnly('goog.dom.datasetTest'); - -goog.require('goog.dom'); -goog.require('goog.dom.dataset'); -goog.require('goog.testing.jsunit'); - -var $ = goog.dom.getElement; -var dataset = goog.dom.dataset; - - -function setUp() { - var el = $('el2'); - el.setAttribute('data-dynamic-key', 'dynamic'); -} - - -function testHas() { - var el = $('el1'); - - assertTrue('Dataset should have an existing key', - dataset.has(el, 'basicKey')); - assertTrue('Dataset should have an existing (unusual) key', - dataset.has(el, 'UnusualKey1')); - assertTrue('Dataset should have an existing (unusual) key', - dataset.has(el, 'unusual-Key2')); - assertTrue('Dataset should have an existing (bizarre) key', - dataset.has(el, '-Bizarre--Key')); - assertFalse('Dataset should not have a non-existent key', - dataset.has(el, 'bogusKey')); -} - - -function testGet() { - var el = $('el1'); - - assertEquals('Dataset should return the proper value for an existing key', - dataset.get(el, 'basicKey'), 'basic'); - assertEquals('Dataset should have an existing (unusual) key', - dataset.get(el, 'UnusualKey1'), 'unusual1'); - assertEquals('Dataset should have an existing (unusual) key', - dataset.get(el, 'unusual-Key2'), 'unusual2'); - assertEquals('Dataset should have an existing (bizarre) key', - dataset.get(el, '-Bizarre--Key'), 'bizarre'); - assertFalse( - 'Dataset should return null or an empty string for a non-existent key', - !!dataset.get(el, 'bogusKey')); - - el = $('el2'); - assertEquals('Dataset should return the proper value for an existing key', - dataset.get(el, 'dynamicKey'), 'dynamic'); -} - - -function testSet() { - var el = $('el2'); - - dataset.set(el, 'newKey', 'newValue'); - assertTrue('Dataset should have a newly created key', - dataset.has(el, 'newKey')); - assertEquals('Dataset should return the proper value for a newly created key', - dataset.get(el, 'newKey'), 'newValue'); - - dataset.set(el, 'dynamicKey', 'customValue'); - assertTrue('Dataset should have a modified, existing key', - dataset.has(el, 'dynamicKey')); - assertEquals('Dataset should return the proper value for a modified key', - dataset.get(el, 'dynamicKey'), 'customValue'); -} - - -function testRemove() { - var el = $('el2'); - - dataset.remove(el, 'dynamicKey'); - assertFalse('Dataset should not have a removed key', - dataset.has(el, 'dynamicKey')); - assertFalse('Dataset should return null or an empty string for removed key', - !!dataset.get(el, 'dynamicKey')); -} - - -function testGetAll() { - var el = $('el1'); - var expectedDataset = { - 'basicKey': 'basic', - 'UnusualKey1': 'unusual1', - 'unusual-Key2': 'unusual2', - '-Bizarre--Key': 'bizarre' - }; - assertHashEquals('Dataset should have basicKey, UnusualKey1, ' + - 'unusual-Key2, and -Bizarre--Key', - expectedDataset, dataset.getAll(el)); -} diff --git a/src/database/third_party/closure-library/closure/goog/dom/dom.js b/src/database/third_party/closure-library/closure/goog/dom/dom.js deleted file mode 100644 index 9b9ec9eaa7b..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/dom.js +++ /dev/null @@ -1,2989 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utilities for manipulating the browser's Document Object Model - * Inspiration taken *heavily* from mochikit (http://mochikit.com/). - * - * You can use {@link goog.dom.DomHelper} to create new dom helpers that refer - * to a different document object. This is useful if you are working with - * frames or multiple windows. - * - * @author arv@google.com (Erik Arvidsson) - */ - - -// TODO(arv): Rename/refactor getTextContent and getRawTextContent. The problem -// is that getTextContent should mimic the DOM3 textContent. We should add a -// getInnerText (or getText) which tries to return the visible text, innerText. - - -goog.provide('goog.dom'); -goog.provide('goog.dom.Appendable'); -goog.provide('goog.dom.DomHelper'); - -goog.require('goog.array'); -goog.require('goog.asserts'); -goog.require('goog.dom.BrowserFeature'); -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.TagName'); -goog.require('goog.dom.safe'); -goog.require('goog.html.SafeHtml'); -goog.require('goog.math.Coordinate'); -goog.require('goog.math.Size'); -goog.require('goog.object'); -goog.require('goog.string'); -goog.require('goog.string.Unicode'); -goog.require('goog.userAgent'); - - -/** - * @define {boolean} Whether we know at compile time that the browser is in - * quirks mode. - */ -goog.define('goog.dom.ASSUME_QUIRKS_MODE', false); - - -/** - * @define {boolean} Whether we know at compile time that the browser is in - * standards compliance mode. - */ -goog.define('goog.dom.ASSUME_STANDARDS_MODE', false); - - -/** - * Whether we know the compatibility mode at compile time. - * @type {boolean} - * @private - */ -goog.dom.COMPAT_MODE_KNOWN_ = - goog.dom.ASSUME_QUIRKS_MODE || goog.dom.ASSUME_STANDARDS_MODE; - - -/** - * Gets the DomHelper object for the document where the element resides. - * @param {(Node|Window)=} opt_element If present, gets the DomHelper for this - * element. - * @return {!goog.dom.DomHelper} The DomHelper. - */ -goog.dom.getDomHelper = function(opt_element) { - return opt_element ? - new goog.dom.DomHelper(goog.dom.getOwnerDocument(opt_element)) : - (goog.dom.defaultDomHelper_ || - (goog.dom.defaultDomHelper_ = new goog.dom.DomHelper())); -}; - - -/** - * Cached default DOM helper. - * @type {goog.dom.DomHelper} - * @private - */ -goog.dom.defaultDomHelper_; - - -/** - * Gets the document object being used by the dom library. - * @return {!Document} Document object. - */ -goog.dom.getDocument = function() { - return document; -}; - - -/** - * Gets an element from the current document by element id. - * - * If an Element is passed in, it is returned. - * - * @param {string|Element} element Element ID or a DOM node. - * @return {Element} The element with the given ID, or the node passed in. - */ -goog.dom.getElement = function(element) { - return goog.dom.getElementHelper_(document, element); -}; - - -/** - * Gets an element by id from the given document (if present). - * If an element is given, it is returned. - * @param {!Document} doc - * @param {string|Element} element Element ID or a DOM node. - * @return {Element} The resulting element. - * @private - */ -goog.dom.getElementHelper_ = function(doc, element) { - return goog.isString(element) ? - doc.getElementById(element) : - element; -}; - - -/** - * Gets an element by id, asserting that the element is found. - * - * This is used when an element is expected to exist, and should fail with - * an assertion error if it does not (if assertions are enabled). - * - * @param {string} id Element ID. - * @return {!Element} The element with the given ID, if it exists. - */ -goog.dom.getRequiredElement = function(id) { - return goog.dom.getRequiredElementHelper_(document, id); -}; - - -/** - * Helper function for getRequiredElementHelper functions, both static and - * on DomHelper. Asserts the element with the given id exists. - * @param {!Document} doc - * @param {string} id - * @return {!Element} The element with the given ID, if it exists. - * @private - */ -goog.dom.getRequiredElementHelper_ = function(doc, id) { - // To prevent users passing in Elements as is permitted in getElement(). - goog.asserts.assertString(id); - var element = goog.dom.getElementHelper_(doc, id); - element = goog.asserts.assertElement(element, - 'No element found with id: ' + id); - return element; -}; - - -/** - * Alias for getElement. - * @param {string|Element} element Element ID or a DOM node. - * @return {Element} The element with the given ID, or the node passed in. - * @deprecated Use {@link goog.dom.getElement} instead. - */ -goog.dom.$ = goog.dom.getElement; - - -/** - * Looks up elements by both tag and class name, using browser native functions - * ({@code querySelectorAll}, {@code getElementsByTagName} or - * {@code getElementsByClassName}) where possible. This function - * is a useful, if limited, way of collecting a list of DOM elements - * with certain characteristics. {@code goog.dom.query} offers a - * more powerful and general solution which allows matching on CSS3 - * selector expressions, but at increased cost in code size. If all you - * need is particular tags belonging to a single class, this function - * is fast and sleek. - * - * Note that tag names are case sensitive in the SVG namespace, and this - * function converts opt_tag to uppercase for comparisons. For queries in the - * SVG namespace you should use querySelector or querySelectorAll instead. - * https://bugzilla.mozilla.org/show_bug.cgi?id=963870 - * https://bugs.webkit.org/show_bug.cgi?id=83438 - * - * @see {goog.dom.query} - * - * @param {?string=} opt_tag Element tag name. - * @param {?string=} opt_class Optional class name. - * @param {(Document|Element)=} opt_el Optional element to look in. - * @return { {length: number} } Array-like list of elements (only a length - * property and numerical indices are guaranteed to exist). - */ -goog.dom.getElementsByTagNameAndClass = function(opt_tag, opt_class, opt_el) { - return goog.dom.getElementsByTagNameAndClass_(document, opt_tag, opt_class, - opt_el); -}; - - -/** - * Returns a static, array-like list of the elements with the provided - * className. - * @see {goog.dom.query} - * @param {string} className the name of the class to look for. - * @param {(Document|Element)=} opt_el Optional element to look in. - * @return { {length: number} } The items found with the class name provided. - */ -goog.dom.getElementsByClass = function(className, opt_el) { - var parent = opt_el || document; - if (goog.dom.canUseQuerySelector_(parent)) { - return parent.querySelectorAll('.' + className); - } - return goog.dom.getElementsByTagNameAndClass_( - document, '*', className, opt_el); -}; - - -/** - * Returns the first element with the provided className. - * @see {goog.dom.query} - * @param {string} className the name of the class to look for. - * @param {Element|Document=} opt_el Optional element to look in. - * @return {Element} The first item with the class name provided. - */ -goog.dom.getElementByClass = function(className, opt_el) { - var parent = opt_el || document; - var retVal = null; - if (parent.getElementsByClassName) { - retVal = parent.getElementsByClassName(className)[0]; - } else if (goog.dom.canUseQuerySelector_(parent)) { - retVal = parent.querySelector('.' + className); - } else { - retVal = goog.dom.getElementsByTagNameAndClass_( - document, '*', className, opt_el)[0]; - } - return retVal || null; -}; - - -/** - * Ensures an element with the given className exists, and then returns the - * first element with the provided className. - * @see {goog.dom.query} - * @param {string} className the name of the class to look for. - * @param {!Element|!Document=} opt_root Optional element or document to look - * in. - * @return {!Element} The first item with the class name provided. - * @throws {goog.asserts.AssertionError} Thrown if no element is found. - */ -goog.dom.getRequiredElementByClass = function(className, opt_root) { - var retValue = goog.dom.getElementByClass(className, opt_root); - return goog.asserts.assert(retValue, - 'No element found with className: ' + className); -}; - - -/** - * Prefer the standardized (http://www.w3.org/TR/selectors-api/), native and - * fast W3C Selectors API. - * @param {!(Element|Document)} parent The parent document object. - * @return {boolean} whether or not we can use parent.querySelector* APIs. - * @private - */ -goog.dom.canUseQuerySelector_ = function(parent) { - return !!(parent.querySelectorAll && parent.querySelector); -}; - - -/** - * Helper for {@code getElementsByTagNameAndClass}. - * @param {!Document} doc The document to get the elements in. - * @param {?string=} opt_tag Element tag name. - * @param {?string=} opt_class Optional class name. - * @param {(Document|Element)=} opt_el Optional element to look in. - * @return { {length: number} } Array-like list of elements (only a length - * property and numerical indices are guaranteed to exist). - * @private - */ -goog.dom.getElementsByTagNameAndClass_ = function(doc, opt_tag, opt_class, - opt_el) { - var parent = opt_el || doc; - var tagName = (opt_tag && opt_tag != '*') ? opt_tag.toUpperCase() : ''; - - if (goog.dom.canUseQuerySelector_(parent) && - (tagName || opt_class)) { - var query = tagName + (opt_class ? '.' + opt_class : ''); - return parent.querySelectorAll(query); - } - - // Use the native getElementsByClassName if available, under the assumption - // that even when the tag name is specified, there will be fewer elements to - // filter through when going by class than by tag name - if (opt_class && parent.getElementsByClassName) { - var els = parent.getElementsByClassName(opt_class); - - if (tagName) { - var arrayLike = {}; - var len = 0; - - // Filter for specific tags if requested. - for (var i = 0, el; el = els[i]; i++) { - if (tagName == el.nodeName) { - arrayLike[len++] = el; - } - } - arrayLike.length = len; - - return arrayLike; - } else { - return els; - } - } - - var els = parent.getElementsByTagName(tagName || '*'); - - if (opt_class) { - var arrayLike = {}; - var len = 0; - for (var i = 0, el; el = els[i]; i++) { - var className = el.className; - // Check if className has a split function since SVG className does not. - if (typeof className.split == 'function' && - goog.array.contains(className.split(/\s+/), opt_class)) { - arrayLike[len++] = el; - } - } - arrayLike.length = len; - return arrayLike; - } else { - return els; - } -}; - - -/** - * Alias for {@code getElementsByTagNameAndClass}. - * @param {?string=} opt_tag Element tag name. - * @param {?string=} opt_class Optional class name. - * @param {Element=} opt_el Optional element to look in. - * @return { {length: number} } Array-like list of elements (only a length - * property and numerical indices are guaranteed to exist). - * @deprecated Use {@link goog.dom.getElementsByTagNameAndClass} instead. - */ -goog.dom.$$ = goog.dom.getElementsByTagNameAndClass; - - -/** - * Sets multiple properties on a node. - * @param {Element} element DOM node to set properties on. - * @param {Object} properties Hash of property:value pairs. - */ -goog.dom.setProperties = function(element, properties) { - goog.object.forEach(properties, function(val, key) { - if (key == 'style') { - element.style.cssText = val; - } else if (key == 'class') { - element.className = val; - } else if (key == 'for') { - element.htmlFor = val; - } else if (key in goog.dom.DIRECT_ATTRIBUTE_MAP_) { - element.setAttribute(goog.dom.DIRECT_ATTRIBUTE_MAP_[key], val); - } else if (goog.string.startsWith(key, 'aria-') || - goog.string.startsWith(key, 'data-')) { - element.setAttribute(key, val); - } else { - element[key] = val; - } - }); -}; - - -/** - * Map of attributes that should be set using - * element.setAttribute(key, val) instead of element[key] = val. Used - * by goog.dom.setProperties. - * - * @private {!Object} - * @const - */ -goog.dom.DIRECT_ATTRIBUTE_MAP_ = { - 'cellpadding': 'cellPadding', - 'cellspacing': 'cellSpacing', - 'colspan': 'colSpan', - 'frameborder': 'frameBorder', - 'height': 'height', - 'maxlength': 'maxLength', - 'role': 'role', - 'rowspan': 'rowSpan', - 'type': 'type', - 'usemap': 'useMap', - 'valign': 'vAlign', - 'width': 'width' -}; - - -/** - * Gets the dimensions of the viewport. - * - * Gecko Standards mode: - * docEl.clientWidth Width of viewport excluding scrollbar. - * win.innerWidth Width of viewport including scrollbar. - * body.clientWidth Width of body element. - * - * docEl.clientHeight Height of viewport excluding scrollbar. - * win.innerHeight Height of viewport including scrollbar. - * body.clientHeight Height of document. - * - * Gecko Backwards compatible mode: - * docEl.clientWidth Width of viewport excluding scrollbar. - * win.innerWidth Width of viewport including scrollbar. - * body.clientWidth Width of viewport excluding scrollbar. - * - * docEl.clientHeight Height of document. - * win.innerHeight Height of viewport including scrollbar. - * body.clientHeight Height of viewport excluding scrollbar. - * - * IE6/7 Standards mode: - * docEl.clientWidth Width of viewport excluding scrollbar. - * win.innerWidth Undefined. - * body.clientWidth Width of body element. - * - * docEl.clientHeight Height of viewport excluding scrollbar. - * win.innerHeight Undefined. - * body.clientHeight Height of document element. - * - * IE5 + IE6/7 Backwards compatible mode: - * docEl.clientWidth 0. - * win.innerWidth Undefined. - * body.clientWidth Width of viewport excluding scrollbar. - * - * docEl.clientHeight 0. - * win.innerHeight Undefined. - * body.clientHeight Height of viewport excluding scrollbar. - * - * Opera 9 Standards and backwards compatible mode: - * docEl.clientWidth Width of viewport excluding scrollbar. - * win.innerWidth Width of viewport including scrollbar. - * body.clientWidth Width of viewport excluding scrollbar. - * - * docEl.clientHeight Height of document. - * win.innerHeight Height of viewport including scrollbar. - * body.clientHeight Height of viewport excluding scrollbar. - * - * WebKit: - * Safari 2 - * docEl.clientHeight Same as scrollHeight. - * docEl.clientWidth Same as innerWidth. - * win.innerWidth Width of viewport excluding scrollbar. - * win.innerHeight Height of the viewport including scrollbar. - * frame.innerHeight Height of the viewport exluding scrollbar. - * - * Safari 3 (tested in 522) - * - * docEl.clientWidth Width of viewport excluding scrollbar. - * docEl.clientHeight Height of viewport excluding scrollbar in strict mode. - * body.clientHeight Height of viewport excluding scrollbar in quirks mode. - * - * @param {Window=} opt_window Optional window element to test. - * @return {!goog.math.Size} Object with values 'width' and 'height'. - */ -goog.dom.getViewportSize = function(opt_window) { - // TODO(arv): This should not take an argument - return goog.dom.getViewportSize_(opt_window || window); -}; - - -/** - * Helper for {@code getViewportSize}. - * @param {Window} win The window to get the view port size for. - * @return {!goog.math.Size} Object with values 'width' and 'height'. - * @private - */ -goog.dom.getViewportSize_ = function(win) { - var doc = win.document; - var el = goog.dom.isCss1CompatMode_(doc) ? doc.documentElement : doc.body; - return new goog.math.Size(el.clientWidth, el.clientHeight); -}; - - -/** - * Calculates the height of the document. - * - * @return {number} The height of the current document. - */ -goog.dom.getDocumentHeight = function() { - return goog.dom.getDocumentHeight_(window); -}; - - -/** - * Calculates the height of the document of the given window. - * - * Function code copied from the opensocial gadget api: - * gadgets.window.adjustHeight(opt_height) - * - * @private - * @param {!Window} win The window whose document height to retrieve. - * @return {number} The height of the document of the given window. - */ -goog.dom.getDocumentHeight_ = function(win) { - // NOTE(eae): This method will return the window size rather than the document - // size in webkit quirks mode. - var doc = win.document; - var height = 0; - - if (doc) { - // Calculating inner content height is hard and different between - // browsers rendering in Strict vs. Quirks mode. We use a combination of - // three properties within document.body and document.documentElement: - // - scrollHeight - // - offsetHeight - // - clientHeight - // These values differ significantly between browsers and rendering modes. - // But there are patterns. It just takes a lot of time and persistence - // to figure out. - - var body = doc.body; - var docEl = doc.documentElement; - if (!(docEl && body)) { - return 0; - } - - // Get the height of the viewport - var vh = goog.dom.getViewportSize_(win).height; - if (goog.dom.isCss1CompatMode_(doc) && docEl.scrollHeight) { - // In Strict mode: - // The inner content height is contained in either: - // document.documentElement.scrollHeight - // document.documentElement.offsetHeight - // Based on studying the values output by different browsers, - // use the value that's NOT equal to the viewport height found above. - height = docEl.scrollHeight != vh ? - docEl.scrollHeight : docEl.offsetHeight; - } else { - // In Quirks mode: - // documentElement.clientHeight is equal to documentElement.offsetHeight - // except in IE. In most browsers, document.documentElement can be used - // to calculate the inner content height. - // However, in other browsers (e.g. IE), document.body must be used - // instead. How do we know which one to use? - // If document.documentElement.clientHeight does NOT equal - // document.documentElement.offsetHeight, then use document.body. - var sh = docEl.scrollHeight; - var oh = docEl.offsetHeight; - if (docEl.clientHeight != oh) { - sh = body.scrollHeight; - oh = body.offsetHeight; - } - - // Detect whether the inner content height is bigger or smaller - // than the bounding box (viewport). If bigger, take the larger - // value. If smaller, take the smaller value. - if (sh > vh) { - // Content is larger - height = sh > oh ? sh : oh; - } else { - // Content is smaller - height = sh < oh ? sh : oh; - } - } - } - - return height; -}; - - -/** - * Gets the page scroll distance as a coordinate object. - * - * @param {Window=} opt_window Optional window element to test. - * @return {!goog.math.Coordinate} Object with values 'x' and 'y'. - * @deprecated Use {@link goog.dom.getDocumentScroll} instead. - */ -goog.dom.getPageScroll = function(opt_window) { - var win = opt_window || goog.global || window; - return goog.dom.getDomHelper(win.document).getDocumentScroll(); -}; - - -/** - * Gets the document scroll distance as a coordinate object. - * - * @return {!goog.math.Coordinate} Object with values 'x' and 'y'. - */ -goog.dom.getDocumentScroll = function() { - return goog.dom.getDocumentScroll_(document); -}; - - -/** - * Helper for {@code getDocumentScroll}. - * - * @param {!Document} doc The document to get the scroll for. - * @return {!goog.math.Coordinate} Object with values 'x' and 'y'. - * @private - */ -goog.dom.getDocumentScroll_ = function(doc) { - var el = goog.dom.getDocumentScrollElement_(doc); - var win = goog.dom.getWindow_(doc); - if (goog.userAgent.IE && goog.userAgent.isVersionOrHigher('10') && - win.pageYOffset != el.scrollTop) { - // The keyboard on IE10 touch devices shifts the page using the pageYOffset - // without modifying scrollTop. For this case, we want the body scroll - // offsets. - return new goog.math.Coordinate(el.scrollLeft, el.scrollTop); - } - return new goog.math.Coordinate(win.pageXOffset || el.scrollLeft, - win.pageYOffset || el.scrollTop); -}; - - -/** - * Gets the document scroll element. - * @return {!Element} Scrolling element. - */ -goog.dom.getDocumentScrollElement = function() { - return goog.dom.getDocumentScrollElement_(document); -}; - - -/** - * Helper for {@code getDocumentScrollElement}. - * @param {!Document} doc The document to get the scroll element for. - * @return {!Element} Scrolling element. - * @private - */ -goog.dom.getDocumentScrollElement_ = function(doc) { - // WebKit needs body.scrollLeft in both quirks mode and strict mode. We also - // default to the documentElement if the document does not have a body (e.g. - // a SVG document). - if (!goog.userAgent.WEBKIT && goog.dom.isCss1CompatMode_(doc)) { - return doc.documentElement; - } - return doc.body || doc.documentElement; -}; - - -/** - * Gets the window object associated with the given document. - * - * @param {Document=} opt_doc Document object to get window for. - * @return {!Window} The window associated with the given document. - */ -goog.dom.getWindow = function(opt_doc) { - // TODO(arv): This should not take an argument. - return opt_doc ? goog.dom.getWindow_(opt_doc) : window; -}; - - -/** - * Helper for {@code getWindow}. - * - * @param {!Document} doc Document object to get window for. - * @return {!Window} The window associated with the given document. - * @private - */ -goog.dom.getWindow_ = function(doc) { - return doc.parentWindow || doc.defaultView; -}; - - -/** - * Returns a dom node with a set of attributes. This function accepts varargs - * for subsequent nodes to be added. Subsequent nodes will be added to the - * first node as childNodes. - * - * So: - * createDom('div', null, createDom('p'), createDom('p')); - * would return a div with two child paragraphs - * - * @param {string} tagName Tag to create. - * @param {(Object|Array|string)=} opt_attributes If object, then a map - * of name-value pairs for attributes. If a string, then this is the - * className of the new element. If an array, the elements will be joined - * together as the className of the new element. - * @param {...(Object|string|Array|NodeList)} var_args Further DOM nodes or - * strings for text nodes. If one of the var_args is an array or NodeList,i - * its elements will be added as childNodes instead. - * @return {!Element} Reference to a DOM node. - */ -goog.dom.createDom = function(tagName, opt_attributes, var_args) { - return goog.dom.createDom_(document, arguments); -}; - - -/** - * Helper for {@code createDom}. - * @param {!Document} doc The document to create the DOM in. - * @param {!Arguments} args Argument object passed from the callers. See - * {@code goog.dom.createDom} for details. - * @return {!Element} Reference to a DOM node. - * @private - */ -goog.dom.createDom_ = function(doc, args) { - var tagName = args[0]; - var attributes = args[1]; - - // Internet Explorer is dumb: http://msdn.microsoft.com/workshop/author/ - // dhtml/reference/properties/name_2.asp - // Also does not allow setting of 'type' attribute on 'input' or 'button'. - if (!goog.dom.BrowserFeature.CAN_ADD_NAME_OR_TYPE_ATTRIBUTES && attributes && - (attributes.name || attributes.type)) { - var tagNameArr = ['<', tagName]; - if (attributes.name) { - tagNameArr.push(' name="', goog.string.htmlEscape(attributes.name), - '"'); - } - if (attributes.type) { - tagNameArr.push(' type="', goog.string.htmlEscape(attributes.type), - '"'); - - // Clone attributes map to remove 'type' without mutating the input. - var clone = {}; - goog.object.extend(clone, attributes); - - // JSCompiler can't see how goog.object.extend added this property, - // because it was essentially added by reflection. - // So it needs to be quoted. - delete clone['type']; - - attributes = clone; - } - tagNameArr.push('>'); - tagName = tagNameArr.join(''); - } - - var element = doc.createElement(tagName); - - if (attributes) { - if (goog.isString(attributes)) { - element.className = attributes; - } else if (goog.isArray(attributes)) { - element.className = attributes.join(' '); - } else { - goog.dom.setProperties(element, attributes); - } - } - - if (args.length > 2) { - goog.dom.append_(doc, element, args, 2); - } - - return element; -}; - - -/** - * Appends a node with text or other nodes. - * @param {!Document} doc The document to create new nodes in. - * @param {!Node} parent The node to append nodes to. - * @param {!Arguments} args The values to add. See {@code goog.dom.append}. - * @param {number} startIndex The index of the array to start from. - * @private - */ -goog.dom.append_ = function(doc, parent, args, startIndex) { - function childHandler(child) { - // TODO(user): More coercion, ala MochiKit? - if (child) { - parent.appendChild(goog.isString(child) ? - doc.createTextNode(child) : child); - } - } - - for (var i = startIndex; i < args.length; i++) { - var arg = args[i]; - // TODO(attila): Fix isArrayLike to return false for a text node. - if (goog.isArrayLike(arg) && !goog.dom.isNodeLike(arg)) { - // If the argument is a node list, not a real array, use a clone, - // because forEach can't be used to mutate a NodeList. - goog.array.forEach(goog.dom.isNodeList(arg) ? - goog.array.toArray(arg) : arg, - childHandler); - } else { - childHandler(arg); - } - } -}; - - -/** - * Alias for {@code createDom}. - * @param {string} tagName Tag to create. - * @param {(string|Object)=} opt_attributes If object, then a map of name-value - * pairs for attributes. If a string, then this is the className of the new - * element. - * @param {...(Object|string|Array|NodeList)} var_args Further DOM nodes or - * strings for text nodes. If one of the var_args is an array, its - * children will be added as childNodes instead. - * @return {!Element} Reference to a DOM node. - * @deprecated Use {@link goog.dom.createDom} instead. - */ -goog.dom.$dom = goog.dom.createDom; - - -/** - * Creates a new element. - * @param {string} name Tag name. - * @return {!Element} The new element. - */ -goog.dom.createElement = function(name) { - return document.createElement(name); -}; - - -/** - * Creates a new text node. - * @param {number|string} content Content. - * @return {!Text} The new text node. - */ -goog.dom.createTextNode = function(content) { - return document.createTextNode(String(content)); -}; - - -/** - * Create a table. - * @param {number} rows The number of rows in the table. Must be >= 1. - * @param {number} columns The number of columns in the table. Must be >= 1. - * @param {boolean=} opt_fillWithNbsp If true, fills table entries with - * {@code goog.string.Unicode.NBSP} characters. - * @return {!Element} The created table. - */ -goog.dom.createTable = function(rows, columns, opt_fillWithNbsp) { - // TODO(user): Return HTMLTableElement, also in prototype function. - // Callers need to be updated to e.g. not assign numbers to table.cellSpacing. - return goog.dom.createTable_(document, rows, columns, !!opt_fillWithNbsp); -}; - - -/** - * Create a table. - * @param {!Document} doc Document object to use to create the table. - * @param {number} rows The number of rows in the table. Must be >= 1. - * @param {number} columns The number of columns in the table. Must be >= 1. - * @param {boolean} fillWithNbsp If true, fills table entries with - * {@code goog.string.Unicode.NBSP} characters. - * @return {!HTMLTableElement} The created table. - * @private - */ -goog.dom.createTable_ = function(doc, rows, columns, fillWithNbsp) { - var table = /** @type {!HTMLTableElement} */ - (doc.createElement(goog.dom.TagName.TABLE)); - var tbody = table.appendChild(doc.createElement(goog.dom.TagName.TBODY)); - for (var i = 0; i < rows; i++) { - var tr = doc.createElement(goog.dom.TagName.TR); - for (var j = 0; j < columns; j++) { - var td = doc.createElement(goog.dom.TagName.TD); - // IE <= 9 will create a text node if we set text content to the empty - // string, so we avoid doing it unless necessary. This ensures that the - // same DOM tree is returned on all browsers. - if (fillWithNbsp) { - goog.dom.setTextContent(td, goog.string.Unicode.NBSP); - } - tr.appendChild(td); - } - tbody.appendChild(tr); - } - return table; -}; - - -/** - * Converts HTML markup into a node. - * @param {!goog.html.SafeHtml} html The HTML markup to convert. - * @return {!Node} The resulting node. - */ -goog.dom.safeHtmlToNode = function(html) { - return goog.dom.safeHtmlToNode_(document, html); -}; - - -/** - * Helper for {@code safeHtmlToNode}. - * @param {!Document} doc The document. - * @param {!goog.html.SafeHtml} html The HTML markup to convert. - * @return {!Node} The resulting node. - * @private - */ -goog.dom.safeHtmlToNode_ = function(doc, html) { - var tempDiv = doc.createElement('div'); - if (goog.dom.BrowserFeature.INNER_HTML_NEEDS_SCOPED_ELEMENT) { - goog.dom.safe.setInnerHtml(tempDiv, - goog.html.SafeHtml.concat(goog.html.SafeHtml.create('br'), html)); - tempDiv.removeChild(tempDiv.firstChild); - } else { - goog.dom.safe.setInnerHtml(tempDiv, html); - } - return goog.dom.childrenToNode_(doc, tempDiv); -}; - - -/** - * Converts an HTML string into a document fragment. The string must be - * sanitized in order to avoid cross-site scripting. For example - * {@code goog.dom.htmlToDocumentFragment('<img src=x onerror=alert(0)>')} - * triggers an alert in all browsers, even if the returned document fragment - * is thrown away immediately. - * - * @param {string} htmlString The HTML string to convert. - * @return {!Node} The resulting document fragment. - */ -goog.dom.htmlToDocumentFragment = function(htmlString) { - return goog.dom.htmlToDocumentFragment_(document, htmlString); -}; - - -// TODO(jakubvrana): Merge with {@code safeHtmlToNode_}. -/** - * Helper for {@code htmlToDocumentFragment}. - * - * @param {!Document} doc The document. - * @param {string} htmlString The HTML string to convert. - * @return {!Node} The resulting document fragment. - * @private - */ -goog.dom.htmlToDocumentFragment_ = function(doc, htmlString) { - var tempDiv = doc.createElement('div'); - if (goog.dom.BrowserFeature.INNER_HTML_NEEDS_SCOPED_ELEMENT) { - tempDiv.innerHTML = '
    ' + htmlString; - tempDiv.removeChild(tempDiv.firstChild); - } else { - tempDiv.innerHTML = htmlString; - } - return goog.dom.childrenToNode_(doc, tempDiv); -}; - - -/** - * Helper for {@code htmlToDocumentFragment_}. - * @param {!Document} doc The document. - * @param {!Node} tempDiv The input node. - * @return {!Node} The resulting node. - * @private - */ -goog.dom.childrenToNode_ = function(doc, tempDiv) { - if (tempDiv.childNodes.length == 1) { - return tempDiv.removeChild(tempDiv.firstChild); - } else { - var fragment = doc.createDocumentFragment(); - while (tempDiv.firstChild) { - fragment.appendChild(tempDiv.firstChild); - } - return fragment; - } -}; - - -/** - * Returns true if the browser is in "CSS1-compatible" (standards-compliant) - * mode, false otherwise. - * @return {boolean} True if in CSS1-compatible mode. - */ -goog.dom.isCss1CompatMode = function() { - return goog.dom.isCss1CompatMode_(document); -}; - - -/** - * Returns true if the browser is in "CSS1-compatible" (standards-compliant) - * mode, false otherwise. - * @param {!Document} doc The document to check. - * @return {boolean} True if in CSS1-compatible mode. - * @private - */ -goog.dom.isCss1CompatMode_ = function(doc) { - if (goog.dom.COMPAT_MODE_KNOWN_) { - return goog.dom.ASSUME_STANDARDS_MODE; - } - - return doc.compatMode == 'CSS1Compat'; -}; - - -/** - * Determines if the given node can contain children, intended to be used for - * HTML generation. - * - * IE natively supports node.canHaveChildren but has inconsistent behavior. - * Prior to IE8 the base tag allows children and in IE9 all nodes return true - * for canHaveChildren. - * - * In practice all non-IE browsers allow you to add children to any node, but - * the behavior is inconsistent: - * - *
    - *   var a = document.createElement('br');
    - *   a.appendChild(document.createTextNode('foo'));
    - *   a.appendChild(document.createTextNode('bar'));
    - *   console.log(a.childNodes.length);  // 2
    - *   console.log(a.innerHTML);  // Chrome: "", IE9: "foobar", FF3.5: "foobar"
    - * 
    - * - * For more information, see: - * http://dev.w3.org/html5/markup/syntax.html#syntax-elements - * - * TODO(user): Rename shouldAllowChildren() ? - * - * @param {Node} node The node to check. - * @return {boolean} Whether the node can contain children. - */ -goog.dom.canHaveChildren = function(node) { - if (node.nodeType != goog.dom.NodeType.ELEMENT) { - return false; - } - switch (node.tagName) { - case goog.dom.TagName.APPLET: - case goog.dom.TagName.AREA: - case goog.dom.TagName.BASE: - case goog.dom.TagName.BR: - case goog.dom.TagName.COL: - case goog.dom.TagName.COMMAND: - case goog.dom.TagName.EMBED: - case goog.dom.TagName.FRAME: - case goog.dom.TagName.HR: - case goog.dom.TagName.IMG: - case goog.dom.TagName.INPUT: - case goog.dom.TagName.IFRAME: - case goog.dom.TagName.ISINDEX: - case goog.dom.TagName.KEYGEN: - case goog.dom.TagName.LINK: - case goog.dom.TagName.NOFRAMES: - case goog.dom.TagName.NOSCRIPT: - case goog.dom.TagName.META: - case goog.dom.TagName.OBJECT: - case goog.dom.TagName.PARAM: - case goog.dom.TagName.SCRIPT: - case goog.dom.TagName.SOURCE: - case goog.dom.TagName.STYLE: - case goog.dom.TagName.TRACK: - case goog.dom.TagName.WBR: - return false; - } - return true; -}; - - -/** - * Appends a child to a node. - * @param {Node} parent Parent. - * @param {Node} child Child. - */ -goog.dom.appendChild = function(parent, child) { - parent.appendChild(child); -}; - - -/** - * Appends a node with text or other nodes. - * @param {!Node} parent The node to append nodes to. - * @param {...goog.dom.Appendable} var_args The things to append to the node. - * If this is a Node it is appended as is. - * If this is a string then a text node is appended. - * If this is an array like object then fields 0 to length - 1 are appended. - */ -goog.dom.append = function(parent, var_args) { - goog.dom.append_(goog.dom.getOwnerDocument(parent), parent, arguments, 1); -}; - - -/** - * Removes all the child nodes on a DOM node. - * @param {Node} node Node to remove children from. - */ -goog.dom.removeChildren = function(node) { - // Note: Iterations over live collections can be slow, this is the fastest - // we could find. The double parenthesis are used to prevent JsCompiler and - // strict warnings. - var child; - while ((child = node.firstChild)) { - node.removeChild(child); - } -}; - - -/** - * Inserts a new node before an existing reference node (i.e. as the previous - * sibling). If the reference node has no parent, then does nothing. - * @param {Node} newNode Node to insert. - * @param {Node} refNode Reference node to insert before. - */ -goog.dom.insertSiblingBefore = function(newNode, refNode) { - if (refNode.parentNode) { - refNode.parentNode.insertBefore(newNode, refNode); - } -}; - - -/** - * Inserts a new node after an existing reference node (i.e. as the next - * sibling). If the reference node has no parent, then does nothing. - * @param {Node} newNode Node to insert. - * @param {Node} refNode Reference node to insert after. - */ -goog.dom.insertSiblingAfter = function(newNode, refNode) { - if (refNode.parentNode) { - refNode.parentNode.insertBefore(newNode, refNode.nextSibling); - } -}; - - -/** - * Insert a child at a given index. If index is larger than the number of child - * nodes that the parent currently has, the node is inserted as the last child - * node. - * @param {Element} parent The element into which to insert the child. - * @param {Node} child The element to insert. - * @param {number} index The index at which to insert the new child node. Must - * not be negative. - */ -goog.dom.insertChildAt = function(parent, child, index) { - // Note that if the second argument is null, insertBefore - // will append the child at the end of the list of children. - parent.insertBefore(child, parent.childNodes[index] || null); -}; - - -/** - * Removes a node from its parent. - * @param {Node} node The node to remove. - * @return {Node} The node removed if removed; else, null. - */ -goog.dom.removeNode = function(node) { - return node && node.parentNode ? node.parentNode.removeChild(node) : null; -}; - - -/** - * Replaces a node in the DOM tree. Will do nothing if {@code oldNode} has no - * parent. - * @param {Node} newNode Node to insert. - * @param {Node} oldNode Node to replace. - */ -goog.dom.replaceNode = function(newNode, oldNode) { - var parent = oldNode.parentNode; - if (parent) { - parent.replaceChild(newNode, oldNode); - } -}; - - -/** - * Flattens an element. That is, removes it and replace it with its children. - * Does nothing if the element is not in the document. - * @param {Element} element The element to flatten. - * @return {Element|undefined} The original element, detached from the document - * tree, sans children; or undefined, if the element was not in the document - * to begin with. - */ -goog.dom.flattenElement = function(element) { - var child, parent = element.parentNode; - if (parent && parent.nodeType != goog.dom.NodeType.DOCUMENT_FRAGMENT) { - // Use IE DOM method (supported by Opera too) if available - if (element.removeNode) { - return /** @type {Element} */ (element.removeNode(false)); - } else { - // Move all children of the original node up one level. - while ((child = element.firstChild)) { - parent.insertBefore(child, element); - } - - // Detach the original element. - return /** @type {Element} */ (goog.dom.removeNode(element)); - } - } -}; - - -/** - * Returns an array containing just the element children of the given element. - * @param {Element} element The element whose element children we want. - * @return {!(Array|NodeList)} An array or array-like list of just the element - * children of the given element. - */ -goog.dom.getChildren = function(element) { - // We check if the children attribute is supported for child elements - // since IE8 misuses the attribute by also including comments. - if (goog.dom.BrowserFeature.CAN_USE_CHILDREN_ATTRIBUTE && - element.children != undefined) { - return element.children; - } - // Fall back to manually filtering the element's child nodes. - return goog.array.filter(element.childNodes, function(node) { - return node.nodeType == goog.dom.NodeType.ELEMENT; - }); -}; - - -/** - * Returns the first child node that is an element. - * @param {Node} node The node to get the first child element of. - * @return {Element} The first child node of {@code node} that is an element. - */ -goog.dom.getFirstElementChild = function(node) { - if (node.firstElementChild != undefined) { - return /** @type {!Element} */(node).firstElementChild; - } - return goog.dom.getNextElementNode_(node.firstChild, true); -}; - - -/** - * Returns the last child node that is an element. - * @param {Node} node The node to get the last child element of. - * @return {Element} The last child node of {@code node} that is an element. - */ -goog.dom.getLastElementChild = function(node) { - if (node.lastElementChild != undefined) { - return /** @type {!Element} */(node).lastElementChild; - } - return goog.dom.getNextElementNode_(node.lastChild, false); -}; - - -/** - * Returns the first next sibling that is an element. - * @param {Node} node The node to get the next sibling element of. - * @return {Element} The next sibling of {@code node} that is an element. - */ -goog.dom.getNextElementSibling = function(node) { - if (node.nextElementSibling != undefined) { - return /** @type {!Element} */(node).nextElementSibling; - } - return goog.dom.getNextElementNode_(node.nextSibling, true); -}; - - -/** - * Returns the first previous sibling that is an element. - * @param {Node} node The node to get the previous sibling element of. - * @return {Element} The first previous sibling of {@code node} that is - * an element. - */ -goog.dom.getPreviousElementSibling = function(node) { - if (node.previousElementSibling != undefined) { - return /** @type {!Element} */(node).previousElementSibling; - } - return goog.dom.getNextElementNode_(node.previousSibling, false); -}; - - -/** - * Returns the first node that is an element in the specified direction, - * starting with {@code node}. - * @param {Node} node The node to get the next element from. - * @param {boolean} forward Whether to look forwards or backwards. - * @return {Element} The first element. - * @private - */ -goog.dom.getNextElementNode_ = function(node, forward) { - while (node && node.nodeType != goog.dom.NodeType.ELEMENT) { - node = forward ? node.nextSibling : node.previousSibling; - } - - return /** @type {Element} */ (node); -}; - - -/** - * Returns the next node in source order from the given node. - * @param {Node} node The node. - * @return {Node} The next node in the DOM tree, or null if this was the last - * node. - */ -goog.dom.getNextNode = function(node) { - if (!node) { - return null; - } - - if (node.firstChild) { - return node.firstChild; - } - - while (node && !node.nextSibling) { - node = node.parentNode; - } - - return node ? node.nextSibling : null; -}; - - -/** - * Returns the previous node in source order from the given node. - * @param {Node} node The node. - * @return {Node} The previous node in the DOM tree, or null if this was the - * first node. - */ -goog.dom.getPreviousNode = function(node) { - if (!node) { - return null; - } - - if (!node.previousSibling) { - return node.parentNode; - } - - node = node.previousSibling; - while (node && node.lastChild) { - node = node.lastChild; - } - - return node; -}; - - -/** - * Whether the object looks like a DOM node. - * @param {?} obj The object being tested for node likeness. - * @return {boolean} Whether the object looks like a DOM node. - */ -goog.dom.isNodeLike = function(obj) { - return goog.isObject(obj) && obj.nodeType > 0; -}; - - -/** - * Whether the object looks like an Element. - * @param {?} obj The object being tested for Element likeness. - * @return {boolean} Whether the object looks like an Element. - */ -goog.dom.isElement = function(obj) { - return goog.isObject(obj) && obj.nodeType == goog.dom.NodeType.ELEMENT; -}; - - -/** - * Returns true if the specified value is a Window object. This includes the - * global window for HTML pages, and iframe windows. - * @param {?} obj Variable to test. - * @return {boolean} Whether the variable is a window. - */ -goog.dom.isWindow = function(obj) { - return goog.isObject(obj) && obj['window'] == obj; -}; - - -/** - * Returns an element's parent, if it's an Element. - * @param {Element} element The DOM element. - * @return {Element} The parent, or null if not an Element. - */ -goog.dom.getParentElement = function(element) { - var parent; - if (goog.dom.BrowserFeature.CAN_USE_PARENT_ELEMENT_PROPERTY) { - var isIe9 = goog.userAgent.IE && - goog.userAgent.isVersionOrHigher('9') && - !goog.userAgent.isVersionOrHigher('10'); - // SVG elements in IE9 can't use the parentElement property. - // goog.global['SVGElement'] is not defined in IE9 quirks mode. - if (!(isIe9 && goog.global['SVGElement'] && - element instanceof goog.global['SVGElement'])) { - parent = element.parentElement; - if (parent) { - return parent; - } - } - } - parent = element.parentNode; - return goog.dom.isElement(parent) ? /** @type {!Element} */ (parent) : null; -}; - - -/** - * Whether a node contains another node. - * @param {Node} parent The node that should contain the other node. - * @param {Node} descendant The node to test presence of. - * @return {boolean} Whether the parent node contains the descendent node. - */ -goog.dom.contains = function(parent, descendant) { - // We use browser specific methods for this if available since it is faster - // that way. - - // IE DOM - if (parent.contains && descendant.nodeType == goog.dom.NodeType.ELEMENT) { - return parent == descendant || parent.contains(descendant); - } - - // W3C DOM Level 3 - if (typeof parent.compareDocumentPosition != 'undefined') { - return parent == descendant || - Boolean(parent.compareDocumentPosition(descendant) & 16); - } - - // W3C DOM Level 1 - while (descendant && parent != descendant) { - descendant = descendant.parentNode; - } - return descendant == parent; -}; - - -/** - * Compares the document order of two nodes, returning 0 if they are the same - * node, a negative number if node1 is before node2, and a positive number if - * node2 is before node1. Note that we compare the order the tags appear in the - * document so in the tree text the B node is considered to be - * before the I node. - * - * @param {Node} node1 The first node to compare. - * @param {Node} node2 The second node to compare. - * @return {number} 0 if the nodes are the same node, a negative number if node1 - * is before node2, and a positive number if node2 is before node1. - */ -goog.dom.compareNodeOrder = function(node1, node2) { - // Fall out quickly for equality. - if (node1 == node2) { - return 0; - } - - // Use compareDocumentPosition where available - if (node1.compareDocumentPosition) { - // 4 is the bitmask for FOLLOWS. - return node1.compareDocumentPosition(node2) & 2 ? 1 : -1; - } - - // Special case for document nodes on IE 7 and 8. - if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9)) { - if (node1.nodeType == goog.dom.NodeType.DOCUMENT) { - return -1; - } - if (node2.nodeType == goog.dom.NodeType.DOCUMENT) { - return 1; - } - } - - // Process in IE using sourceIndex - we check to see if the first node has - // a source index or if its parent has one. - if ('sourceIndex' in node1 || - (node1.parentNode && 'sourceIndex' in node1.parentNode)) { - var isElement1 = node1.nodeType == goog.dom.NodeType.ELEMENT; - var isElement2 = node2.nodeType == goog.dom.NodeType.ELEMENT; - - if (isElement1 && isElement2) { - return node1.sourceIndex - node2.sourceIndex; - } else { - var parent1 = node1.parentNode; - var parent2 = node2.parentNode; - - if (parent1 == parent2) { - return goog.dom.compareSiblingOrder_(node1, node2); - } - - if (!isElement1 && goog.dom.contains(parent1, node2)) { - return -1 * goog.dom.compareParentsDescendantNodeIe_(node1, node2); - } - - - if (!isElement2 && goog.dom.contains(parent2, node1)) { - return goog.dom.compareParentsDescendantNodeIe_(node2, node1); - } - - return (isElement1 ? node1.sourceIndex : parent1.sourceIndex) - - (isElement2 ? node2.sourceIndex : parent2.sourceIndex); - } - } - - // For Safari, we compare ranges. - var doc = goog.dom.getOwnerDocument(node1); - - var range1, range2; - range1 = doc.createRange(); - range1.selectNode(node1); - range1.collapse(true); - - range2 = doc.createRange(); - range2.selectNode(node2); - range2.collapse(true); - - return range1.compareBoundaryPoints(goog.global['Range'].START_TO_END, - range2); -}; - - -/** - * Utility function to compare the position of two nodes, when - * {@code textNode}'s parent is an ancestor of {@code node}. If this entry - * condition is not met, this function will attempt to reference a null object. - * @param {!Node} textNode The textNode to compare. - * @param {Node} node The node to compare. - * @return {number} -1 if node is before textNode, +1 otherwise. - * @private - */ -goog.dom.compareParentsDescendantNodeIe_ = function(textNode, node) { - var parent = textNode.parentNode; - if (parent == node) { - // If textNode is a child of node, then node comes first. - return -1; - } - var sibling = node; - while (sibling.parentNode != parent) { - sibling = sibling.parentNode; - } - return goog.dom.compareSiblingOrder_(sibling, textNode); -}; - - -/** - * Utility function to compare the position of two nodes known to be non-equal - * siblings. - * @param {Node} node1 The first node to compare. - * @param {!Node} node2 The second node to compare. - * @return {number} -1 if node1 is before node2, +1 otherwise. - * @private - */ -goog.dom.compareSiblingOrder_ = function(node1, node2) { - var s = node2; - while ((s = s.previousSibling)) { - if (s == node1) { - // We just found node1 before node2. - return -1; - } - } - - // Since we didn't find it, node1 must be after node2. - return 1; -}; - - -/** - * Find the deepest common ancestor of the given nodes. - * @param {...Node} var_args The nodes to find a common ancestor of. - * @return {Node} The common ancestor of the nodes, or null if there is none. - * null will only be returned if two or more of the nodes are from different - * documents. - */ -goog.dom.findCommonAncestor = function(var_args) { - var i, count = arguments.length; - if (!count) { - return null; - } else if (count == 1) { - return arguments[0]; - } - - var paths = []; - var minLength = Infinity; - for (i = 0; i < count; i++) { - // Compute the list of ancestors. - var ancestors = []; - var node = arguments[i]; - while (node) { - ancestors.unshift(node); - node = node.parentNode; - } - - // Save the list for comparison. - paths.push(ancestors); - minLength = Math.min(minLength, ancestors.length); - } - var output = null; - for (i = 0; i < minLength; i++) { - var first = paths[0][i]; - for (var j = 1; j < count; j++) { - if (first != paths[j][i]) { - return output; - } - } - output = first; - } - return output; -}; - - -/** - * Returns the owner document for a node. - * @param {Node|Window} node The node to get the document for. - * @return {!Document} The document owning the node. - */ -goog.dom.getOwnerDocument = function(node) { - // TODO(nnaze): Update param signature to be non-nullable. - goog.asserts.assert(node, 'Node cannot be null or undefined.'); - return /** @type {!Document} */ ( - node.nodeType == goog.dom.NodeType.DOCUMENT ? node : - node.ownerDocument || node.document); -}; - - -/** - * Cross-browser function for getting the document element of a frame or iframe. - * @param {Element} frame Frame element. - * @return {!Document} The frame content document. - */ -goog.dom.getFrameContentDocument = function(frame) { - var doc = frame.contentDocument || frame.contentWindow.document; - return doc; -}; - - -/** - * Cross-browser function for getting the window of a frame or iframe. - * @param {Element} frame Frame element. - * @return {Window} The window associated with the given frame. - */ -goog.dom.getFrameContentWindow = function(frame) { - return frame.contentWindow || - goog.dom.getWindow(goog.dom.getFrameContentDocument(frame)); -}; - - -/** - * Sets the text content of a node, with cross-browser support. - * @param {Node} node The node to change the text content of. - * @param {string|number} text The value that should replace the node's content. - */ -goog.dom.setTextContent = function(node, text) { - goog.asserts.assert(node != null, - 'goog.dom.setTextContent expects a non-null value for node'); - - if ('textContent' in node) { - node.textContent = text; - } else if (node.nodeType == goog.dom.NodeType.TEXT) { - node.data = text; - } else if (node.firstChild && - node.firstChild.nodeType == goog.dom.NodeType.TEXT) { - // If the first child is a text node we just change its data and remove the - // rest of the children. - while (node.lastChild != node.firstChild) { - node.removeChild(node.lastChild); - } - node.firstChild.data = text; - } else { - goog.dom.removeChildren(node); - var doc = goog.dom.getOwnerDocument(node); - node.appendChild(doc.createTextNode(String(text))); - } -}; - - -/** - * Gets the outerHTML of a node, which islike innerHTML, except that it - * actually contains the HTML of the node itself. - * @param {Element} element The element to get the HTML of. - * @return {string} The outerHTML of the given element. - */ -goog.dom.getOuterHtml = function(element) { - // IE, Opera and WebKit all have outerHTML. - if ('outerHTML' in element) { - return element.outerHTML; - } else { - var doc = goog.dom.getOwnerDocument(element); - var div = doc.createElement('div'); - div.appendChild(element.cloneNode(true)); - return div.innerHTML; - } -}; - - -/** - * Finds the first descendant node that matches the filter function, using - * a depth first search. This function offers the most general purpose way - * of finding a matching element. You may also wish to consider - * {@code goog.dom.query} which can express many matching criteria using - * CSS selector expressions. These expressions often result in a more - * compact representation of the desired result. - * @see goog.dom.query - * - * @param {Node} root The root of the tree to search. - * @param {function(Node) : boolean} p The filter function. - * @return {Node|undefined} The found node or undefined if none is found. - */ -goog.dom.findNode = function(root, p) { - var rv = []; - var found = goog.dom.findNodes_(root, p, rv, true); - return found ? rv[0] : undefined; -}; - - -/** - * Finds all the descendant nodes that match the filter function, using a - * a depth first search. This function offers the most general-purpose way - * of finding a set of matching elements. You may also wish to consider - * {@code goog.dom.query} which can express many matching criteria using - * CSS selector expressions. These expressions often result in a more - * compact representation of the desired result. - - * @param {Node} root The root of the tree to search. - * @param {function(Node) : boolean} p The filter function. - * @return {!Array} The found nodes or an empty array if none are found. - */ -goog.dom.findNodes = function(root, p) { - var rv = []; - goog.dom.findNodes_(root, p, rv, false); - return rv; -}; - - -/** - * Finds the first or all the descendant nodes that match the filter function, - * using a depth first search. - * @param {Node} root The root of the tree to search. - * @param {function(Node) : boolean} p The filter function. - * @param {!Array} rv The found nodes are added to this array. - * @param {boolean} findOne If true we exit after the first found node. - * @return {boolean} Whether the search is complete or not. True in case findOne - * is true and the node is found. False otherwise. - * @private - */ -goog.dom.findNodes_ = function(root, p, rv, findOne) { - if (root != null) { - var child = root.firstChild; - while (child) { - if (p(child)) { - rv.push(child); - if (findOne) { - return true; - } - } - if (goog.dom.findNodes_(child, p, rv, findOne)) { - return true; - } - child = child.nextSibling; - } - } - return false; -}; - - -/** - * Map of tags whose content to ignore when calculating text length. - * @private {!Object} - * @const - */ -goog.dom.TAGS_TO_IGNORE_ = { - 'SCRIPT': 1, - 'STYLE': 1, - 'HEAD': 1, - 'IFRAME': 1, - 'OBJECT': 1 -}; - - -/** - * Map of tags which have predefined values with regard to whitespace. - * @private {!Object} - * @const - */ -goog.dom.PREDEFINED_TAG_VALUES_ = {'IMG': ' ', 'BR': '\n'}; - - -/** - * Returns true if the element has a tab index that allows it to receive - * keyboard focus (tabIndex >= 0), false otherwise. Note that some elements - * natively support keyboard focus, even if they have no tab index. - * @param {!Element} element Element to check. - * @return {boolean} Whether the element has a tab index that allows keyboard - * focus. - * @see http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ - */ -goog.dom.isFocusableTabIndex = function(element) { - return goog.dom.hasSpecifiedTabIndex_(element) && - goog.dom.isTabIndexFocusable_(element); -}; - - -/** - * Enables or disables keyboard focus support on the element via its tab index. - * Only elements for which {@link goog.dom.isFocusableTabIndex} returns true - * (or elements that natively support keyboard focus, like form elements) can - * receive keyboard focus. See http://go/tabindex for more info. - * @param {Element} element Element whose tab index is to be changed. - * @param {boolean} enable Whether to set or remove a tab index on the element - * that supports keyboard focus. - */ -goog.dom.setFocusableTabIndex = function(element, enable) { - if (enable) { - element.tabIndex = 0; - } else { - // Set tabIndex to -1 first, then remove it. This is a workaround for - // Safari (confirmed in version 4 on Windows). When removing the attribute - // without setting it to -1 first, the element remains keyboard focusable - // despite not having a tabIndex attribute anymore. - element.tabIndex = -1; - element.removeAttribute('tabIndex'); // Must be camelCase! - } -}; - - -/** - * Returns true if the element can be focused, i.e. it has a tab index that - * allows it to receive keyboard focus (tabIndex >= 0), or it is an element - * that natively supports keyboard focus. - * @param {!Element} element Element to check. - * @return {boolean} Whether the element allows keyboard focus. - */ -goog.dom.isFocusable = function(element) { - var focusable; - // Some elements can have unspecified tab index and still receive focus. - if (goog.dom.nativelySupportsFocus_(element)) { - // Make sure the element is not disabled ... - focusable = !element.disabled && - // ... and if a tab index is specified, it allows focus. - (!goog.dom.hasSpecifiedTabIndex_(element) || - goog.dom.isTabIndexFocusable_(element)); - } else { - focusable = goog.dom.isFocusableTabIndex(element); - } - - // IE requires elements to be visible in order to focus them. - return focusable && goog.userAgent.IE ? - goog.dom.hasNonZeroBoundingRect_(element) : focusable; -}; - - -/** - * Returns true if the element has a specified tab index. - * @param {!Element} element Element to check. - * @return {boolean} Whether the element has a specified tab index. - * @private - */ -goog.dom.hasSpecifiedTabIndex_ = function(element) { - // IE returns 0 for an unset tabIndex, so we must use getAttributeNode(), - // which returns an object with a 'specified' property if tabIndex is - // specified. This works on other browsers, too. - var attrNode = element.getAttributeNode('tabindex'); // Must be lowercase! - return goog.isDefAndNotNull(attrNode) && attrNode.specified; -}; - - -/** - * Returns true if the element's tab index allows the element to be focused. - * @param {!Element} element Element to check. - * @return {boolean} Whether the element's tab index allows focus. - * @private - */ -goog.dom.isTabIndexFocusable_ = function(element) { - var index = element.tabIndex; - // NOTE: IE9 puts tabIndex in 16-bit int, e.g. -2 is 65534. - return goog.isNumber(index) && index >= 0 && index < 32768; -}; - - -/** - * Returns true if the element is focusable even when tabIndex is not set. - * @param {!Element} element Element to check. - * @return {boolean} Whether the element natively supports focus. - * @private - */ -goog.dom.nativelySupportsFocus_ = function(element) { - return element.tagName == goog.dom.TagName.A || - element.tagName == goog.dom.TagName.INPUT || - element.tagName == goog.dom.TagName.TEXTAREA || - element.tagName == goog.dom.TagName.SELECT || - element.tagName == goog.dom.TagName.BUTTON; -}; - - -/** - * Returns true if the element has a bounding rectangle that would be visible - * (i.e. its width and height are greater than zero). - * @param {!Element} element Element to check. - * @return {boolean} Whether the element has a non-zero bounding rectangle. - * @private - */ -goog.dom.hasNonZeroBoundingRect_ = function(element) { - var rect = goog.isFunction(element['getBoundingClientRect']) ? - element.getBoundingClientRect() : - {'height': element.offsetHeight, 'width': element.offsetWidth}; - return goog.isDefAndNotNull(rect) && rect.height > 0 && rect.width > 0; -}; - - -/** - * Returns the text content of the current node, without markup and invisible - * symbols. New lines are stripped and whitespace is collapsed, - * such that each character would be visible. - * - * In browsers that support it, innerText is used. Other browsers attempt to - * simulate it via node traversal. Line breaks are canonicalized in IE. - * - * @param {Node} node The node from which we are getting content. - * @return {string} The text content. - */ -goog.dom.getTextContent = function(node) { - var textContent; - // Note(arv): IE9, Opera, and Safari 3 support innerText but they include - // text nodes in script tags. So we revert to use a user agent test here. - if (goog.dom.BrowserFeature.CAN_USE_INNER_TEXT && ('innerText' in node)) { - textContent = goog.string.canonicalizeNewlines(node.innerText); - // Unfortunately .innerText() returns text with ­ symbols - // We need to filter it out and then remove duplicate whitespaces - } else { - var buf = []; - goog.dom.getTextContent_(node, buf, true); - textContent = buf.join(''); - } - - // Strip ­ entities. goog.format.insertWordBreaks inserts them in Opera. - textContent = textContent.replace(/ \xAD /g, ' ').replace(/\xAD/g, ''); - // Strip ​ entities. goog.format.insertWordBreaks inserts them in IE8. - textContent = textContent.replace(/\u200B/g, ''); - - // Skip this replacement on old browsers with working innerText, which - // automatically turns   into ' ' and / +/ into ' ' when reading - // innerText. - if (!goog.dom.BrowserFeature.CAN_USE_INNER_TEXT) { - textContent = textContent.replace(/ +/g, ' '); - } - if (textContent != ' ') { - textContent = textContent.replace(/^\s*/, ''); - } - - return textContent; -}; - - -/** - * Returns the text content of the current node, without markup. - * - * Unlike {@code getTextContent} this method does not collapse whitespaces - * or normalize lines breaks. - * - * @param {Node} node The node from which we are getting content. - * @return {string} The raw text content. - */ -goog.dom.getRawTextContent = function(node) { - var buf = []; - goog.dom.getTextContent_(node, buf, false); - - return buf.join(''); -}; - - -/** - * Recursive support function for text content retrieval. - * - * @param {Node} node The node from which we are getting content. - * @param {Array} buf string buffer. - * @param {boolean} normalizeWhitespace Whether to normalize whitespace. - * @private - */ -goog.dom.getTextContent_ = function(node, buf, normalizeWhitespace) { - if (node.nodeName in goog.dom.TAGS_TO_IGNORE_) { - // ignore certain tags - } else if (node.nodeType == goog.dom.NodeType.TEXT) { - if (normalizeWhitespace) { - buf.push(String(node.nodeValue).replace(/(\r\n|\r|\n)/g, '')); - } else { - buf.push(node.nodeValue); - } - } else if (node.nodeName in goog.dom.PREDEFINED_TAG_VALUES_) { - buf.push(goog.dom.PREDEFINED_TAG_VALUES_[node.nodeName]); - } else { - var child = node.firstChild; - while (child) { - goog.dom.getTextContent_(child, buf, normalizeWhitespace); - child = child.nextSibling; - } - } -}; - - -/** - * Returns the text length of the text contained in a node, without markup. This - * is equivalent to the selection length if the node was selected, or the number - * of cursor movements to traverse the node. Images & BRs take one space. New - * lines are ignored. - * - * @param {Node} node The node whose text content length is being calculated. - * @return {number} The length of {@code node}'s text content. - */ -goog.dom.getNodeTextLength = function(node) { - return goog.dom.getTextContent(node).length; -}; - - -/** - * Returns the text offset of a node relative to one of its ancestors. The text - * length is the same as the length calculated by goog.dom.getNodeTextLength. - * - * @param {Node} node The node whose offset is being calculated. - * @param {Node=} opt_offsetParent The node relative to which the offset will - * be calculated. Defaults to the node's owner document's body. - * @return {number} The text offset. - */ -goog.dom.getNodeTextOffset = function(node, opt_offsetParent) { - var root = opt_offsetParent || goog.dom.getOwnerDocument(node).body; - var buf = []; - while (node && node != root) { - var cur = node; - while ((cur = cur.previousSibling)) { - buf.unshift(goog.dom.getTextContent(cur)); - } - node = node.parentNode; - } - // Trim left to deal with FF cases when there might be line breaks and empty - // nodes at the front of the text - return goog.string.trimLeft(buf.join('')).replace(/ +/g, ' ').length; -}; - - -/** - * Returns the node at a given offset in a parent node. If an object is - * provided for the optional third parameter, the node and the remainder of the - * offset will stored as properties of this object. - * @param {Node} parent The parent node. - * @param {number} offset The offset into the parent node. - * @param {Object=} opt_result Object to be used to store the return value. The - * return value will be stored in the form {node: Node, remainder: number} - * if this object is provided. - * @return {Node} The node at the given offset. - */ -goog.dom.getNodeAtOffset = function(parent, offset, opt_result) { - var stack = [parent], pos = 0, cur = null; - while (stack.length > 0 && pos < offset) { - cur = stack.pop(); - if (cur.nodeName in goog.dom.TAGS_TO_IGNORE_) { - // ignore certain tags - } else if (cur.nodeType == goog.dom.NodeType.TEXT) { - var text = cur.nodeValue.replace(/(\r\n|\r|\n)/g, '').replace(/ +/g, ' '); - pos += text.length; - } else if (cur.nodeName in goog.dom.PREDEFINED_TAG_VALUES_) { - pos += goog.dom.PREDEFINED_TAG_VALUES_[cur.nodeName].length; - } else { - for (var i = cur.childNodes.length - 1; i >= 0; i--) { - stack.push(cur.childNodes[i]); - } - } - } - if (goog.isObject(opt_result)) { - opt_result.remainder = cur ? cur.nodeValue.length + offset - pos - 1 : 0; - opt_result.node = cur; - } - - return cur; -}; - - -/** - * Returns true if the object is a {@code NodeList}. To qualify as a NodeList, - * the object must have a numeric length property and an item function (which - * has type 'string' on IE for some reason). - * @param {Object} val Object to test. - * @return {boolean} Whether the object is a NodeList. - */ -goog.dom.isNodeList = function(val) { - // TODO(attila): Now the isNodeList is part of goog.dom we can use - // goog.userAgent to make this simpler. - // A NodeList must have a length property of type 'number' on all platforms. - if (val && typeof val.length == 'number') { - // A NodeList is an object everywhere except Safari, where it's a function. - if (goog.isObject(val)) { - // A NodeList must have an item function (on non-IE platforms) or an item - // property of type 'string' (on IE). - return typeof val.item == 'function' || typeof val.item == 'string'; - } else if (goog.isFunction(val)) { - // On Safari, a NodeList is a function with an item property that is also - // a function. - return typeof val.item == 'function'; - } - } - - // Not a NodeList. - return false; -}; - - -/** - * Walks up the DOM hierarchy returning the first ancestor that has the passed - * tag name and/or class name. If the passed element matches the specified - * criteria, the element itself is returned. - * @param {Node} element The DOM node to start with. - * @param {?(goog.dom.TagName|string)=} opt_tag The tag name to match (or - * null/undefined to match only based on class name). - * @param {?string=} opt_class The class name to match (or null/undefined to - * match only based on tag name). - * @param {number=} opt_maxSearchSteps Maximum number of levels to search up the - * dom. - * @return {Element} The first ancestor that matches the passed criteria, or - * null if no match is found. - */ -goog.dom.getAncestorByTagNameAndClass = function(element, opt_tag, opt_class, - opt_maxSearchSteps) { - if (!opt_tag && !opt_class) { - return null; - } - var tagName = opt_tag ? opt_tag.toUpperCase() : null; - return /** @type {Element} */ (goog.dom.getAncestor(element, - function(node) { - return (!tagName || node.nodeName == tagName) && - (!opt_class || goog.isString(node.className) && - goog.array.contains(node.className.split(/\s+/), opt_class)); - }, true, opt_maxSearchSteps)); -}; - - -/** - * Walks up the DOM hierarchy returning the first ancestor that has the passed - * class name. If the passed element matches the specified criteria, the - * element itself is returned. - * @param {Node} element The DOM node to start with. - * @param {string} className The class name to match. - * @param {number=} opt_maxSearchSteps Maximum number of levels to search up the - * dom. - * @return {Element} The first ancestor that matches the passed criteria, or - * null if none match. - */ -goog.dom.getAncestorByClass = function(element, className, opt_maxSearchSteps) { - return goog.dom.getAncestorByTagNameAndClass(element, null, className, - opt_maxSearchSteps); -}; - - -/** - * Walks up the DOM hierarchy returning the first ancestor that passes the - * matcher function. - * @param {Node} element The DOM node to start with. - * @param {function(Node) : boolean} matcher A function that returns true if the - * passed node matches the desired criteria. - * @param {boolean=} opt_includeNode If true, the node itself is included in - * the search (the first call to the matcher will pass startElement as - * the node to test). - * @param {number=} opt_maxSearchSteps Maximum number of levels to search up the - * dom. - * @return {Node} DOM node that matched the matcher, or null if there was - * no match. - */ -goog.dom.getAncestor = function( - element, matcher, opt_includeNode, opt_maxSearchSteps) { - if (!opt_includeNode) { - element = element.parentNode; - } - var ignoreSearchSteps = opt_maxSearchSteps == null; - var steps = 0; - while (element && (ignoreSearchSteps || steps <= opt_maxSearchSteps)) { - if (matcher(element)) { - return element; - } - element = element.parentNode; - steps++; - } - // Reached the root of the DOM without a match - return null; -}; - - -/** - * Determines the active element in the given document. - * @param {Document} doc The document to look in. - * @return {Element} The active element. - */ -goog.dom.getActiveElement = function(doc) { - try { - return doc && doc.activeElement; - } catch (e) { - // NOTE(nicksantos): Sometimes, evaluating document.activeElement in IE - // throws an exception. I'm not 100% sure why, but I suspect it chokes - // on document.activeElement if the activeElement has been recently - // removed from the DOM by a JS operation. - // - // We assume that an exception here simply means - // "there is no active element." - } - - return null; -}; - - -/** - * Gives the current devicePixelRatio. - * - * By default, this is the value of window.devicePixelRatio (which should be - * preferred if present). - * - * If window.devicePixelRatio is not present, the ratio is calculated with - * window.matchMedia, if present. Otherwise, gives 1.0. - * - * Some browsers (including Chrome) consider the browser zoom level in the pixel - * ratio, so the value may change across multiple calls. - * - * @return {number} The number of actual pixels per virtual pixel. - */ -goog.dom.getPixelRatio = function() { - var win = goog.dom.getWindow(); - - // devicePixelRatio does not work on Mobile firefox. - // TODO(user): Enable this check on a known working mobile Gecko version. - // Filed a bug: https://bugzilla.mozilla.org/show_bug.cgi?id=896804 - var isFirefoxMobile = goog.userAgent.GECKO && goog.userAgent.MOBILE; - - if (goog.isDef(win.devicePixelRatio) && !isFirefoxMobile) { - return win.devicePixelRatio; - } else if (win.matchMedia) { - return goog.dom.matchesPixelRatio_(.75) || - goog.dom.matchesPixelRatio_(1.5) || - goog.dom.matchesPixelRatio_(2) || - goog.dom.matchesPixelRatio_(3) || 1; - } - return 1; -}; - - -/** - * Calculates a mediaQuery to check if the current device supports the - * given actual to virtual pixel ratio. - * @param {number} pixelRatio The ratio of actual pixels to virtual pixels. - * @return {number} pixelRatio if applicable, otherwise 0. - * @private - */ -goog.dom.matchesPixelRatio_ = function(pixelRatio) { - var win = goog.dom.getWindow(); - var query = ('(-webkit-min-device-pixel-ratio: ' + pixelRatio + '),' + - '(min--moz-device-pixel-ratio: ' + pixelRatio + '),' + - '(min-resolution: ' + pixelRatio + 'dppx)'); - return win.matchMedia(query).matches ? pixelRatio : 0; -}; - - - -/** - * Create an instance of a DOM helper with a new document object. - * @param {Document=} opt_document Document object to associate with this - * DOM helper. - * @constructor - */ -goog.dom.DomHelper = function(opt_document) { - /** - * Reference to the document object to use - * @type {!Document} - * @private - */ - this.document_ = opt_document || goog.global.document || document; -}; - - -/** - * Gets the dom helper object for the document where the element resides. - * @param {Node=} opt_node If present, gets the DomHelper for this node. - * @return {!goog.dom.DomHelper} The DomHelper. - */ -goog.dom.DomHelper.prototype.getDomHelper = goog.dom.getDomHelper; - - -/** - * Sets the document object. - * @param {!Document} document Document object. - */ -goog.dom.DomHelper.prototype.setDocument = function(document) { - this.document_ = document; -}; - - -/** - * Gets the document object being used by the dom library. - * @return {!Document} Document object. - */ -goog.dom.DomHelper.prototype.getDocument = function() { - return this.document_; -}; - - -/** - * Alias for {@code getElementById}. If a DOM node is passed in then we just - * return that. - * @param {string|Element} element Element ID or a DOM node. - * @return {Element} The element with the given ID, or the node passed in. - */ -goog.dom.DomHelper.prototype.getElement = function(element) { - return goog.dom.getElementHelper_(this.document_, element); -}; - - -/** - * Gets an element by id, asserting that the element is found. - * - * This is used when an element is expected to exist, and should fail with - * an assertion error if it does not (if assertions are enabled). - * - * @param {string} id Element ID. - * @return {!Element} The element with the given ID, if it exists. - */ -goog.dom.DomHelper.prototype.getRequiredElement = function(id) { - return goog.dom.getRequiredElementHelper_(this.document_, id); -}; - - -/** - * Alias for {@code getElement}. - * @param {string|Element} element Element ID or a DOM node. - * @return {Element} The element with the given ID, or the node passed in. - * @deprecated Use {@link goog.dom.DomHelper.prototype.getElement} instead. - */ -goog.dom.DomHelper.prototype.$ = goog.dom.DomHelper.prototype.getElement; - - -/** - * Looks up elements by both tag and class name, using browser native functions - * ({@code querySelectorAll}, {@code getElementsByTagName} or - * {@code getElementsByClassName}) where possible. The returned array is a live - * NodeList or a static list depending on the code path taken. - * - * @see goog.dom.query - * - * @param {?string=} opt_tag Element tag name or * for all tags. - * @param {?string=} opt_class Optional class name. - * @param {(Document|Element)=} opt_el Optional element to look in. - * @return { {length: number} } Array-like list of elements (only a length - * property and numerical indices are guaranteed to exist). - */ -goog.dom.DomHelper.prototype.getElementsByTagNameAndClass = function(opt_tag, - opt_class, - opt_el) { - return goog.dom.getElementsByTagNameAndClass_(this.document_, opt_tag, - opt_class, opt_el); -}; - - -/** - * Returns an array of all the elements with the provided className. - * @see {goog.dom.query} - * @param {string} className the name of the class to look for. - * @param {Element|Document=} opt_el Optional element to look in. - * @return { {length: number} } The items found with the class name provided. - */ -goog.dom.DomHelper.prototype.getElementsByClass = function(className, opt_el) { - var doc = opt_el || this.document_; - return goog.dom.getElementsByClass(className, doc); -}; - - -/** - * Returns the first element we find matching the provided class name. - * @see {goog.dom.query} - * @param {string} className the name of the class to look for. - * @param {(Element|Document)=} opt_el Optional element to look in. - * @return {Element} The first item found with the class name provided. - */ -goog.dom.DomHelper.prototype.getElementByClass = function(className, opt_el) { - var doc = opt_el || this.document_; - return goog.dom.getElementByClass(className, doc); -}; - - -/** - * Ensures an element with the given className exists, and then returns the - * first element with the provided className. - * @see {goog.dom.query} - * @param {string} className the name of the class to look for. - * @param {(!Element|!Document)=} opt_root Optional element or document to look - * in. - * @return {!Element} The first item found with the class name provided. - * @throws {goog.asserts.AssertionError} Thrown if no element is found. - */ -goog.dom.DomHelper.prototype.getRequiredElementByClass = function(className, - opt_root) { - var root = opt_root || this.document_; - return goog.dom.getRequiredElementByClass(className, root); -}; - - -/** - * Alias for {@code getElementsByTagNameAndClass}. - * @deprecated Use DomHelper getElementsByTagNameAndClass. - * @see goog.dom.query - * - * @param {?string=} opt_tag Element tag name. - * @param {?string=} opt_class Optional class name. - * @param {Element=} opt_el Optional element to look in. - * @return { {length: number} } Array-like list of elements (only a length - * property and numerical indices are guaranteed to exist). - */ -goog.dom.DomHelper.prototype.$$ = - goog.dom.DomHelper.prototype.getElementsByTagNameAndClass; - - -/** - * Sets a number of properties on a node. - * @param {Element} element DOM node to set properties on. - * @param {Object} properties Hash of property:value pairs. - */ -goog.dom.DomHelper.prototype.setProperties = goog.dom.setProperties; - - -/** - * Gets the dimensions of the viewport. - * @param {Window=} opt_window Optional window element to test. Defaults to - * the window of the Dom Helper. - * @return {!goog.math.Size} Object with values 'width' and 'height'. - */ -goog.dom.DomHelper.prototype.getViewportSize = function(opt_window) { - // TODO(arv): This should not take an argument. That breaks the rule of a - // a DomHelper representing a single frame/window/document. - return goog.dom.getViewportSize(opt_window || this.getWindow()); -}; - - -/** - * Calculates the height of the document. - * - * @return {number} The height of the document. - */ -goog.dom.DomHelper.prototype.getDocumentHeight = function() { - return goog.dom.getDocumentHeight_(this.getWindow()); -}; - - -/** - * Typedef for use with goog.dom.createDom and goog.dom.append. - * @typedef {Object|string|Array|NodeList} - */ -goog.dom.Appendable; - - -/** - * Returns a dom node with a set of attributes. This function accepts varargs - * for subsequent nodes to be added. Subsequent nodes will be added to the - * first node as childNodes. - * - * So: - * createDom('div', null, createDom('p'), createDom('p')); - * would return a div with two child paragraphs - * - * An easy way to move all child nodes of an existing element to a new parent - * element is: - * createDom('div', null, oldElement.childNodes); - * which will remove all child nodes from the old element and add them as - * child nodes of the new DIV. - * - * @param {string} tagName Tag to create. - * @param {Object|string=} opt_attributes If object, then a map of name-value - * pairs for attributes. If a string, then this is the className of the new - * element. - * @param {...goog.dom.Appendable} var_args Further DOM nodes or - * strings for text nodes. If one of the var_args is an array or - * NodeList, its elements will be added as childNodes instead. - * @return {!Element} Reference to a DOM node. - */ -goog.dom.DomHelper.prototype.createDom = function(tagName, - opt_attributes, - var_args) { - return goog.dom.createDom_(this.document_, arguments); -}; - - -/** - * Alias for {@code createDom}. - * @param {string} tagName Tag to create. - * @param {(Object|string)=} opt_attributes If object, then a map of name-value - * pairs for attributes. If a string, then this is the className of the new - * element. - * @param {...goog.dom.Appendable} var_args Further DOM nodes or strings for - * text nodes. If one of the var_args is an array, its children will be - * added as childNodes instead. - * @return {!Element} Reference to a DOM node. - * @deprecated Use {@link goog.dom.DomHelper.prototype.createDom} instead. - */ -goog.dom.DomHelper.prototype.$dom = goog.dom.DomHelper.prototype.createDom; - - -/** - * Creates a new element. - * @param {string} name Tag name. - * @return {!Element} The new element. - */ -goog.dom.DomHelper.prototype.createElement = function(name) { - return this.document_.createElement(name); -}; - - -/** - * Creates a new text node. - * @param {number|string} content Content. - * @return {!Text} The new text node. - */ -goog.dom.DomHelper.prototype.createTextNode = function(content) { - return this.document_.createTextNode(String(content)); -}; - - -/** - * Create a table. - * @param {number} rows The number of rows in the table. Must be >= 1. - * @param {number} columns The number of columns in the table. Must be >= 1. - * @param {boolean=} opt_fillWithNbsp If true, fills table entries with - * {@code goog.string.Unicode.NBSP} characters. - * @return {!HTMLElement} The created table. - */ -goog.dom.DomHelper.prototype.createTable = function(rows, columns, - opt_fillWithNbsp) { - return goog.dom.createTable_(this.document_, rows, columns, - !!opt_fillWithNbsp); -}; - - -/** - * Converts an HTML into a node or a document fragment. A single Node is used if - * {@code html} only generates a single node. If {@code html} generates multiple - * nodes then these are put inside a {@code DocumentFragment}. - * @param {!goog.html.SafeHtml} html The HTML markup to convert. - * @return {!Node} The resulting node. - */ -goog.dom.DomHelper.prototype.safeHtmlToNode = function(html) { - return goog.dom.safeHtmlToNode_(this.document_, html); -}; - - -/** - * Converts an HTML string into a node or a document fragment. A single Node - * is used if the {@code htmlString} only generates a single node. If the - * {@code htmlString} generates multiple nodes then these are put inside a - * {@code DocumentFragment}. - * - * @param {string} htmlString The HTML string to convert. - * @return {!Node} The resulting node. - */ -goog.dom.DomHelper.prototype.htmlToDocumentFragment = function(htmlString) { - return goog.dom.htmlToDocumentFragment_(this.document_, htmlString); -}; - - -/** - * Returns true if the browser is in "CSS1-compatible" (standards-compliant) - * mode, false otherwise. - * @return {boolean} True if in CSS1-compatible mode. - */ -goog.dom.DomHelper.prototype.isCss1CompatMode = function() { - return goog.dom.isCss1CompatMode_(this.document_); -}; - - -/** - * Gets the window object associated with the document. - * @return {!Window} The window associated with the given document. - */ -goog.dom.DomHelper.prototype.getWindow = function() { - return goog.dom.getWindow_(this.document_); -}; - - -/** - * Gets the document scroll element. - * @return {!Element} Scrolling element. - */ -goog.dom.DomHelper.prototype.getDocumentScrollElement = function() { - return goog.dom.getDocumentScrollElement_(this.document_); -}; - - -/** - * Gets the document scroll distance as a coordinate object. - * @return {!goog.math.Coordinate} Object with properties 'x' and 'y'. - */ -goog.dom.DomHelper.prototype.getDocumentScroll = function() { - return goog.dom.getDocumentScroll_(this.document_); -}; - - -/** - * Determines the active element in the given document. - * @param {Document=} opt_doc The document to look in. - * @return {Element} The active element. - */ -goog.dom.DomHelper.prototype.getActiveElement = function(opt_doc) { - return goog.dom.getActiveElement(opt_doc || this.document_); -}; - - -/** - * Appends a child to a node. - * @param {Node} parent Parent. - * @param {Node} child Child. - */ -goog.dom.DomHelper.prototype.appendChild = goog.dom.appendChild; - - -/** - * Appends a node with text or other nodes. - * @param {!Node} parent The node to append nodes to. - * @param {...goog.dom.Appendable} var_args The things to append to the node. - * If this is a Node it is appended as is. - * If this is a string then a text node is appended. - * If this is an array like object then fields 0 to length - 1 are appended. - */ -goog.dom.DomHelper.prototype.append = goog.dom.append; - - -/** - * Determines if the given node can contain children, intended to be used for - * HTML generation. - * - * @param {Node} node The node to check. - * @return {boolean} Whether the node can contain children. - */ -goog.dom.DomHelper.prototype.canHaveChildren = goog.dom.canHaveChildren; - - -/** - * Removes all the child nodes on a DOM node. - * @param {Node} node Node to remove children from. - */ -goog.dom.DomHelper.prototype.removeChildren = goog.dom.removeChildren; - - -/** - * Inserts a new node before an existing reference node (i.e., as the previous - * sibling). If the reference node has no parent, then does nothing. - * @param {Node} newNode Node to insert. - * @param {Node} refNode Reference node to insert before. - */ -goog.dom.DomHelper.prototype.insertSiblingBefore = goog.dom.insertSiblingBefore; - - -/** - * Inserts a new node after an existing reference node (i.e., as the next - * sibling). If the reference node has no parent, then does nothing. - * @param {Node} newNode Node to insert. - * @param {Node} refNode Reference node to insert after. - */ -goog.dom.DomHelper.prototype.insertSiblingAfter = goog.dom.insertSiblingAfter; - - -/** - * Insert a child at a given index. If index is larger than the number of child - * nodes that the parent currently has, the node is inserted as the last child - * node. - * @param {Element} parent The element into which to insert the child. - * @param {Node} child The element to insert. - * @param {number} index The index at which to insert the new child node. Must - * not be negative. - */ -goog.dom.DomHelper.prototype.insertChildAt = goog.dom.insertChildAt; - - -/** - * Removes a node from its parent. - * @param {Node} node The node to remove. - * @return {Node} The node removed if removed; else, null. - */ -goog.dom.DomHelper.prototype.removeNode = goog.dom.removeNode; - - -/** - * Replaces a node in the DOM tree. Will do nothing if {@code oldNode} has no - * parent. - * @param {Node} newNode Node to insert. - * @param {Node} oldNode Node to replace. - */ -goog.dom.DomHelper.prototype.replaceNode = goog.dom.replaceNode; - - -/** - * Flattens an element. That is, removes it and replace it with its children. - * @param {Element} element The element to flatten. - * @return {Element|undefined} The original element, detached from the document - * tree, sans children, or undefined if the element was already not in the - * document. - */ -goog.dom.DomHelper.prototype.flattenElement = goog.dom.flattenElement; - - -/** - * Returns an array containing just the element children of the given element. - * @param {Element} element The element whose element children we want. - * @return {!(Array|NodeList)} An array or array-like list of just the element - * children of the given element. - */ -goog.dom.DomHelper.prototype.getChildren = goog.dom.getChildren; - - -/** - * Returns the first child node that is an element. - * @param {Node} node The node to get the first child element of. - * @return {Element} The first child node of {@code node} that is an element. - */ -goog.dom.DomHelper.prototype.getFirstElementChild = - goog.dom.getFirstElementChild; - - -/** - * Returns the last child node that is an element. - * @param {Node} node The node to get the last child element of. - * @return {Element} The last child node of {@code node} that is an element. - */ -goog.dom.DomHelper.prototype.getLastElementChild = goog.dom.getLastElementChild; - - -/** - * Returns the first next sibling that is an element. - * @param {Node} node The node to get the next sibling element of. - * @return {Element} The next sibling of {@code node} that is an element. - */ -goog.dom.DomHelper.prototype.getNextElementSibling = - goog.dom.getNextElementSibling; - - -/** - * Returns the first previous sibling that is an element. - * @param {Node} node The node to get the previous sibling element of. - * @return {Element} The first previous sibling of {@code node} that is - * an element. - */ -goog.dom.DomHelper.prototype.getPreviousElementSibling = - goog.dom.getPreviousElementSibling; - - -/** - * Returns the next node in source order from the given node. - * @param {Node} node The node. - * @return {Node} The next node in the DOM tree, or null if this was the last - * node. - */ -goog.dom.DomHelper.prototype.getNextNode = goog.dom.getNextNode; - - -/** - * Returns the previous node in source order from the given node. - * @param {Node} node The node. - * @return {Node} The previous node in the DOM tree, or null if this was the - * first node. - */ -goog.dom.DomHelper.prototype.getPreviousNode = goog.dom.getPreviousNode; - - -/** - * Whether the object looks like a DOM node. - * @param {?} obj The object being tested for node likeness. - * @return {boolean} Whether the object looks like a DOM node. - */ -goog.dom.DomHelper.prototype.isNodeLike = goog.dom.isNodeLike; - - -/** - * Whether the object looks like an Element. - * @param {?} obj The object being tested for Element likeness. - * @return {boolean} Whether the object looks like an Element. - */ -goog.dom.DomHelper.prototype.isElement = goog.dom.isElement; - - -/** - * Returns true if the specified value is a Window object. This includes the - * global window for HTML pages, and iframe windows. - * @param {?} obj Variable to test. - * @return {boolean} Whether the variable is a window. - */ -goog.dom.DomHelper.prototype.isWindow = goog.dom.isWindow; - - -/** - * Returns an element's parent, if it's an Element. - * @param {Element} element The DOM element. - * @return {Element} The parent, or null if not an Element. - */ -goog.dom.DomHelper.prototype.getParentElement = goog.dom.getParentElement; - - -/** - * Whether a node contains another node. - * @param {Node} parent The node that should contain the other node. - * @param {Node} descendant The node to test presence of. - * @return {boolean} Whether the parent node contains the descendent node. - */ -goog.dom.DomHelper.prototype.contains = goog.dom.contains; - - -/** - * Compares the document order of two nodes, returning 0 if they are the same - * node, a negative number if node1 is before node2, and a positive number if - * node2 is before node1. Note that we compare the order the tags appear in the - * document so in the tree text the B node is considered to be - * before the I node. - * - * @param {Node} node1 The first node to compare. - * @param {Node} node2 The second node to compare. - * @return {number} 0 if the nodes are the same node, a negative number if node1 - * is before node2, and a positive number if node2 is before node1. - */ -goog.dom.DomHelper.prototype.compareNodeOrder = goog.dom.compareNodeOrder; - - -/** - * Find the deepest common ancestor of the given nodes. - * @param {...Node} var_args The nodes to find a common ancestor of. - * @return {Node} The common ancestor of the nodes, or null if there is none. - * null will only be returned if two or more of the nodes are from different - * documents. - */ -goog.dom.DomHelper.prototype.findCommonAncestor = goog.dom.findCommonAncestor; - - -/** - * Returns the owner document for a node. - * @param {Node} node The node to get the document for. - * @return {!Document} The document owning the node. - */ -goog.dom.DomHelper.prototype.getOwnerDocument = goog.dom.getOwnerDocument; - - -/** - * Cross browser function for getting the document element of an iframe. - * @param {Element} iframe Iframe element. - * @return {!Document} The frame content document. - */ -goog.dom.DomHelper.prototype.getFrameContentDocument = - goog.dom.getFrameContentDocument; - - -/** - * Cross browser function for getting the window of a frame or iframe. - * @param {Element} frame Frame element. - * @return {Window} The window associated with the given frame. - */ -goog.dom.DomHelper.prototype.getFrameContentWindow = - goog.dom.getFrameContentWindow; - - -/** - * Sets the text content of a node, with cross-browser support. - * @param {Node} node The node to change the text content of. - * @param {string|number} text The value that should replace the node's content. - */ -goog.dom.DomHelper.prototype.setTextContent = goog.dom.setTextContent; - - -/** - * Gets the outerHTML of a node, which islike innerHTML, except that it - * actually contains the HTML of the node itself. - * @param {Element} element The element to get the HTML of. - * @return {string} The outerHTML of the given element. - */ -goog.dom.DomHelper.prototype.getOuterHtml = goog.dom.getOuterHtml; - - -/** - * Finds the first descendant node that matches the filter function. This does - * a depth first search. - * @param {Node} root The root of the tree to search. - * @param {function(Node) : boolean} p The filter function. - * @return {Node|undefined} The found node or undefined if none is found. - */ -goog.dom.DomHelper.prototype.findNode = goog.dom.findNode; - - -/** - * Finds all the descendant nodes that matches the filter function. This does a - * depth first search. - * @param {Node} root The root of the tree to search. - * @param {function(Node) : boolean} p The filter function. - * @return {Array} The found nodes or an empty array if none are found. - */ -goog.dom.DomHelper.prototype.findNodes = goog.dom.findNodes; - - -/** - * Returns true if the element has a tab index that allows it to receive - * keyboard focus (tabIndex >= 0), false otherwise. Note that some elements - * natively support keyboard focus, even if they have no tab index. - * @param {!Element} element Element to check. - * @return {boolean} Whether the element has a tab index that allows keyboard - * focus. - */ -goog.dom.DomHelper.prototype.isFocusableTabIndex = goog.dom.isFocusableTabIndex; - - -/** - * Enables or disables keyboard focus support on the element via its tab index. - * Only elements for which {@link goog.dom.isFocusableTabIndex} returns true - * (or elements that natively support keyboard focus, like form elements) can - * receive keyboard focus. See http://go/tabindex for more info. - * @param {Element} element Element whose tab index is to be changed. - * @param {boolean} enable Whether to set or remove a tab index on the element - * that supports keyboard focus. - */ -goog.dom.DomHelper.prototype.setFocusableTabIndex = - goog.dom.setFocusableTabIndex; - - -/** - * Returns true if the element can be focused, i.e. it has a tab index that - * allows it to receive keyboard focus (tabIndex >= 0), or it is an element - * that natively supports keyboard focus. - * @param {!Element} element Element to check. - * @return {boolean} Whether the element allows keyboard focus. - */ -goog.dom.DomHelper.prototype.isFocusable = goog.dom.isFocusable; - - -/** - * Returns the text contents of the current node, without markup. New lines are - * stripped and whitespace is collapsed, such that each character would be - * visible. - * - * In browsers that support it, innerText is used. Other browsers attempt to - * simulate it via node traversal. Line breaks are canonicalized in IE. - * - * @param {Node} node The node from which we are getting content. - * @return {string} The text content. - */ -goog.dom.DomHelper.prototype.getTextContent = goog.dom.getTextContent; - - -/** - * Returns the text length of the text contained in a node, without markup. This - * is equivalent to the selection length if the node was selected, or the number - * of cursor movements to traverse the node. Images & BRs take one space. New - * lines are ignored. - * - * @param {Node} node The node whose text content length is being calculated. - * @return {number} The length of {@code node}'s text content. - */ -goog.dom.DomHelper.prototype.getNodeTextLength = goog.dom.getNodeTextLength; - - -/** - * Returns the text offset of a node relative to one of its ancestors. The text - * length is the same as the length calculated by - * {@code goog.dom.getNodeTextLength}. - * - * @param {Node} node The node whose offset is being calculated. - * @param {Node=} opt_offsetParent Defaults to the node's owner document's body. - * @return {number} The text offset. - */ -goog.dom.DomHelper.prototype.getNodeTextOffset = goog.dom.getNodeTextOffset; - - -/** - * Returns the node at a given offset in a parent node. If an object is - * provided for the optional third parameter, the node and the remainder of the - * offset will stored as properties of this object. - * @param {Node} parent The parent node. - * @param {number} offset The offset into the parent node. - * @param {Object=} opt_result Object to be used to store the return value. The - * return value will be stored in the form {node: Node, remainder: number} - * if this object is provided. - * @return {Node} The node at the given offset. - */ -goog.dom.DomHelper.prototype.getNodeAtOffset = goog.dom.getNodeAtOffset; - - -/** - * Returns true if the object is a {@code NodeList}. To qualify as a NodeList, - * the object must have a numeric length property and an item function (which - * has type 'string' on IE for some reason). - * @param {Object} val Object to test. - * @return {boolean} Whether the object is a NodeList. - */ -goog.dom.DomHelper.prototype.isNodeList = goog.dom.isNodeList; - - -/** - * Walks up the DOM hierarchy returning the first ancestor that has the passed - * tag name and/or class name. If the passed element matches the specified - * criteria, the element itself is returned. - * @param {Node} element The DOM node to start with. - * @param {?(goog.dom.TagName|string)=} opt_tag The tag name to match (or - * null/undefined to match only based on class name). - * @param {?string=} opt_class The class name to match (or null/undefined to - * match only based on tag name). - * @param {number=} opt_maxSearchSteps Maximum number of levels to search up the - * dom. - * @return {Element} The first ancestor that matches the passed criteria, or - * null if no match is found. - */ -goog.dom.DomHelper.prototype.getAncestorByTagNameAndClass = - goog.dom.getAncestorByTagNameAndClass; - - -/** - * Walks up the DOM hierarchy returning the first ancestor that has the passed - * class name. If the passed element matches the specified criteria, the - * element itself is returned. - * @param {Node} element The DOM node to start with. - * @param {string} class The class name to match. - * @param {number=} opt_maxSearchSteps Maximum number of levels to search up the - * dom. - * @return {Element} The first ancestor that matches the passed criteria, or - * null if none match. - */ -goog.dom.DomHelper.prototype.getAncestorByClass = - goog.dom.getAncestorByClass; - - -/** - * Walks up the DOM hierarchy returning the first ancestor that passes the - * matcher function. - * @param {Node} element The DOM node to start with. - * @param {function(Node) : boolean} matcher A function that returns true if the - * passed node matches the desired criteria. - * @param {boolean=} opt_includeNode If true, the node itself is included in - * the search (the first call to the matcher will pass startElement as - * the node to test). - * @param {number=} opt_maxSearchSteps Maximum number of levels to search up the - * dom. - * @return {Node} DOM node that matched the matcher, or null if there was - * no match. - */ -goog.dom.DomHelper.prototype.getAncestor = goog.dom.getAncestor; diff --git a/src/database/third_party/closure-library/closure/goog/dom/dom_quirks_test.html b/src/database/third_party/closure-library/closure/goog/dom/dom_quirks_test.html deleted file mode 100644 index 746d429b8b8..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/dom_quirks_test.html +++ /dev/null @@ -1,128 +0,0 @@ - - - - -Closure Unit Tests - goog.dom - - - - - -
    - abc def g h ij kl mn opq -
    - - -
    - Test Element -
    - -
    - - -
    - - - - - -
    - -
    - -

    - -
    -
    -
    - - -

    - - a - c - d - - e - f - g - -

    - - - - -
      -
    - - - -

    - -
    -

    - ancestorTest -

    -
    - -
    Test
    -
    Test
    -
    Test
    -
    Test
    -
    Test
    -
    Test
    - -
    - Test - - - - - - - - - - - -
    - -
    Replace Test
    - - - -
    hello world
    -
    hello world
    - - - - Foo - - - - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/dom_test.html b/src/database/third_party/closure-library/closure/goog/dom/dom_test.html deleted file mode 100644 index bf05d3ce134..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/dom_test.html +++ /dev/null @@ -1,128 +0,0 @@ - - - - - - -Closure Unit Tests - goog.dom - - - - - -
    - abc def g h ij kl mn opq -
    - - -
    - Test Element -
    - -
    - - -
    - - - - - -
    - -
    - -

    - -
    -
    -
    - - -

    - - a - c - d - - e - f - g - -

    - - - - -
      -
    - - - -

    - -
    -

    - ancestorTest -

    -
    - -
    Test
    -
    Test
    -
    Test
    -
    Test
    -
    Test
    -
    Test
    - -
    - Test - - - - - - - - - - - -
    - -
    Replace Test
    - - - -
    hello world
    -
    hello world
    - - - - Foo - - - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/dom_test.js b/src/database/third_party/closure-library/closure/goog/dom/dom_test.js deleted file mode 100644 index bfb6a904f5a..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/dom_test.js +++ /dev/null @@ -1,1641 +0,0 @@ -// Copyright 2009 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Shared code for dom_test.html and dom_quirks_test.html. - */ - -/** @suppress {extraProvide} */ -goog.provide('goog.dom.dom_test'); - -goog.require('goog.dom'); -goog.require('goog.dom.BrowserFeature'); -goog.require('goog.dom.DomHelper'); -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.TagName'); -goog.require('goog.functions'); -goog.require('goog.html.testing'); -goog.require('goog.object'); -goog.require('goog.string.Unicode'); -goog.require('goog.testing.PropertyReplacer'); -goog.require('goog.testing.asserts'); -goog.require('goog.userAgent'); -goog.require('goog.userAgent.product'); -goog.require('goog.userAgent.product.isVersion'); - -goog.setTestOnly('dom_test'); - -var $ = goog.dom.getElement; - -var divForTestingScrolling; -var myIframe; -var myIframeDoc; -var stubs; - -function setUpPage() { - - stubs = new goog.testing.PropertyReplacer(); - divForTestingScrolling = document.createElement('div'); - divForTestingScrolling.style.width = '5000px'; - divForTestingScrolling.style.height = '5000px'; - document.body.appendChild(divForTestingScrolling); - - // Setup for the iframe - myIframe = $('myIframe'); - myIframeDoc = goog.dom.getFrameContentDocument( - /** @type {HTMLIFrameElement} */ (myIframe)); - - // Set up document for iframe: total height of elements in document is 65 - // If the elements are not create like below, IE will get a wrong height for - // the document. - myIframeDoc.open(); - // Make sure we progate the compat mode - myIframeDoc.write((goog.dom.isCss1CompatMode() ? '' : '') + - '' + - '
    ' + - 'hello world
    ' + - '
    ' + - 'hello world
    '); - myIframeDoc.close(); -} - -function tearDownPage() { - document.body.removeChild(divForTestingScrolling); -} - -function tearDown() { - window.scrollTo(0, 0); - stubs.reset(); -} - -function testDom() { - assert('Dom library exists', typeof goog.dom != 'undefined'); -} - -function testGetElement() { - var el = $('testEl'); - assertEquals('Should be able to get id', el.id, 'testEl'); - - assertEquals($, goog.dom.getElement); - assertEquals(goog.dom.$, goog.dom.getElement); -} - -function testGetElementDomHelper() { - var domHelper = new goog.dom.DomHelper(); - var el = domHelper.getElement('testEl'); - assertEquals('Should be able to get id', el.id, 'testEl'); -} - -function testGetRequiredElement() { - var el = goog.dom.getRequiredElement('testEl'); - assertTrue(goog.isDefAndNotNull(el)); - assertEquals('testEl', el.id); - assertThrows(function() { - goog.dom.getRequiredElement('does_not_exist'); - }); -} - -function testGetRequiredElementDomHelper() { - var domHelper = new goog.dom.DomHelper(); - var el = domHelper.getRequiredElement('testEl'); - assertTrue(goog.isDefAndNotNull(el)); - assertEquals('testEl', el.id); - assertThrows(function() { - goog.dom.getRequiredElementByClass('does_not_exist', container); - }); -} - -function testGetRequiredElementByClassDomHelper() { - var domHelper = new goog.dom.DomHelper(); - assertNotNull(domHelper.getRequiredElementByClass('test1')); - assertNotNull(domHelper.getRequiredElementByClass('test2')); - - var container = domHelper.getElement('span-container'); - assertNotNull(domHelper.getElementByClass('test1', container)); - assertThrows(function() { - domHelper.getRequiredElementByClass('does_not_exist', container); - }); -} - -function testGetElementsByTagNameAndClass() { - assertEquals('Should get 6 spans', - goog.dom.getElementsByTagNameAndClass('span').length, 6); - assertEquals('Should get 6 spans', - goog.dom.getElementsByTagNameAndClass('SPAN').length, 6); - assertEquals('Should get 3 spans', - goog.dom.getElementsByTagNameAndClass('span', 'test1').length, 3); - assertEquals('Should get 1 span', - goog.dom.getElementsByTagNameAndClass('span', 'test2').length, 1); - assertEquals('Should get 1 span', - goog.dom.getElementsByTagNameAndClass('SPAN', 'test2').length, 1); - assertEquals('Should get lots of elements', - goog.dom.getElementsByTagNameAndClass().length, - document.getElementsByTagName('*').length); - - assertEquals('Should get 1 span', - goog.dom.getElementsByTagNameAndClass('span', null, $('testEl')).length, - 1); - - // '*' as the tag name should be equivalent to all tags - var container = goog.dom.getElement('span-container'); - assertEquals(5, - goog.dom.getElementsByTagNameAndClass('*', undefined, container).length); - assertEquals(3, - goog.dom.getElementsByTagNameAndClass('*', 'test1', container).length); - assertEquals(1, - goog.dom.getElementsByTagNameAndClass('*', 'test2', container).length); - - // Some version of WebKit have problems with mixed-case class names - assertEquals(1, - goog.dom.getElementsByTagNameAndClass( - undefined, 'mixedCaseClass').length); - - // Make sure that out of bounds indices are OK - assertUndefined( - goog.dom.getElementsByTagNameAndClass(undefined, 'noSuchClass')[0]); - - assertEquals(goog.dom.getElementsByTagNameAndClass, - goog.dom.getElementsByTagNameAndClass); -} - -function testGetElementsByClass() { - assertEquals(3, goog.dom.getElementsByClass('test1').length); - assertEquals(1, goog.dom.getElementsByClass('test2').length); - assertEquals(0, goog.dom.getElementsByClass('nonexistant').length); - - var container = goog.dom.getElement('span-container'); - assertEquals(3, goog.dom.getElementsByClass('test1', container).length); -} - -function testGetElementByClass() { - assertNotNull(goog.dom.getElementByClass('test1')); - assertNotNull(goog.dom.getElementByClass('test2')); - // assertNull(goog.dom.getElementByClass('nonexistant')); - - var container = goog.dom.getElement('span-container'); - assertNotNull(goog.dom.getElementByClass('test1', container)); -} - -function testSetProperties() { - var attrs = {'name': 'test3', 'title': 'A title', 'random': 'woop'}; - var el = $('testEl'); - - var res = goog.dom.setProperties(el, attrs); - assertEquals('Should be equal', el.name, 'test3'); - assertEquals('Should be equal', el.title, 'A title'); - assertEquals('Should be equal', el.random, 'woop'); -} - -function testSetPropertiesDirectAttributeMap() { - var attrs = {'usemap': '#myMap'}; - var el = goog.dom.createDom('img'); - - var res = goog.dom.setProperties(el, attrs); - assertEquals('Should be equal', '#myMap', el.getAttribute('usemap')); -} - -function testSetPropertiesAria() { - var attrs = { - 'aria-hidden': 'true', - 'aria-label': 'This is a label', - 'role': 'presentation' - }; - var el = goog.dom.createDom('div'); - - goog.dom.setProperties(el, attrs); - assertEquals('Should be equal', 'true', el.getAttribute('aria-hidden')); - assertEquals('Should be equal', - 'This is a label', el.getAttribute('aria-label')); - assertEquals('Should be equal', 'presentation', el.getAttribute('role')); -} - -function testSetPropertiesData() { - var attrs = { - 'data-tooltip': 'This is a tooltip', - 'data-tooltip-delay': '100' - }; - var el = goog.dom.createDom('div'); - - goog.dom.setProperties(el, attrs); - assertEquals('Should be equal', 'This is a tooltip', - el.getAttribute('data-tooltip')); - assertEquals('Should be equal', '100', - el.getAttribute('data-tooltip-delay')); -} - -function testSetTableProperties() { - var attrs = { - 'style': 'padding-left: 10px;', - 'class': 'mytestclass', - 'height': '101', - 'cellpadding': '15' - }; - var el = $('testTable1'); - - var res = goog.dom.setProperties(el, attrs); - assertEquals('Should be equal', el.style.paddingLeft, '10px'); - assertEquals('Should be equal', el.className, 'mytestclass'); - assertEquals('Should be equal', el.getAttribute('height'), '101'); - assertEquals('Should be equal', el.cellPadding, '15'); -} - -function testGetViewportSize() { - // TODO: This is failing in the test runner now, fix later. - //var dims = getViewportSize(); - //assertNotUndefined('Should be defined at least', dims.width); - //assertNotUndefined('Should be defined at least', dims.height); -} - -function testGetViewportSizeInIframe() { - var iframe = /** @type {HTMLIFrameElement} */ (goog.dom.getElement('iframe')); - var contentDoc = goog.dom.getFrameContentDocument(iframe); - contentDoc.write(''); - - var outerSize = goog.dom.getViewportSize(); - var innerSize = (new goog.dom.DomHelper(contentDoc)).getViewportSize(); - assert('Viewport sizes must not match', - innerSize.width != outerSize.width); -} - -function testGetDocumentHeightInIframe() { - var doc = goog.dom.getDomHelper(myIframeDoc).getDocument(); - var height = goog.dom.getDomHelper(myIframeDoc).getDocumentHeight(); - - // Broken in webkit quirks mode and in IE8+ - if ((goog.dom.isCss1CompatMode_(doc) || !goog.userAgent.WEBKIT) && - !isIE8OrHigher()) { - assertEquals('height should be 65', 42 + 23, height); - } -} - -function testCreateDom() { - var el = goog.dom.createDom('div', - { - style: 'border: 1px solid black; width: 50%; background-color: #EEE;', - onclick: "alert('woo')" - }, - goog.dom.createDom( - 'p', {style: 'font: normal 12px arial; color: red; '}, 'Para 1'), - goog.dom.createDom( - 'p', {style: 'font: bold 18px garamond; color: blue; '}, 'Para 2'), - goog.dom.createDom( - 'p', {style: 'font: normal 24px monospace; color: green'}, - 'Para 3 ', - goog.dom.createDom('a', { - name: 'link', href: 'http://bbc.co.uk' - }, - 'has a link'), - ', how cool is this?')); - - assertEquals('Tagname should be a DIV', 'DIV', el.tagName); - assertEquals('Style width should be 50%', '50%', el.style.width); - assertEquals('first child is a P tag', 'P', el.childNodes[0].tagName); - assertEquals('second child .innerHTML', 'Para 2', - el.childNodes[1].innerHTML); - - assertEquals(goog.dom.createDom, goog.dom.createDom); -} - -function testCreateDomNoChildren() { - var el; - - // Test unspecified children. - el = goog.dom.createDom('div'); - assertNull('firstChild should be null', el.firstChild); - - // Test null children. - el = goog.dom.createDom('div', null, null); - assertNull('firstChild should be null', el.firstChild); - - // Test empty array of children. - el = goog.dom.createDom('div', null, []); - assertNull('firstChild should be null', el.firstChild); -} - -function testCreateDomAcceptsArray() { - var items = [ - goog.dom.createDom('li', {}, 'Item 1'), - goog.dom.createDom('li', {}, 'Item 2') - ]; - var ul = goog.dom.createDom('ul', {}, items); - assertEquals('List should have two children', 2, ul.childNodes.length); - assertEquals('First child should be an LI tag', - 'LI', ul.firstChild.tagName); - assertEquals('Item 1', ul.childNodes[0].innerHTML); - assertEquals('Item 2', ul.childNodes[1].innerHTML); -} - -function testCreateDomStringArg() { - var el; - - // Test string arg. - el = goog.dom.createDom('div', null, 'Hello'); - assertEquals('firstChild should be a text node', goog.dom.NodeType.TEXT, - el.firstChild.nodeType); - assertEquals('firstChild should have node value "Hello"', 'Hello', - el.firstChild.nodeValue); - - // Test text node arg. - el = goog.dom.createDom('div', null, goog.dom.createTextNode('World')); - assertEquals('firstChild should be a text node', goog.dom.NodeType.TEXT, - el.firstChild.nodeType); - assertEquals('firstChild should have node value "World"', 'World', - el.firstChild.nodeValue); -} - -function testCreateDomNodeListArg() { - var el; - var emptyElem = goog.dom.createDom('div'); - var simpleElem = goog.dom.createDom('div', null, 'Hello, world!'); - var complexElem = goog.dom.createDom('div', null, 'Hello, ', - goog.dom.createDom('b', null, 'world'), goog.dom.createTextNode('!')); - - // Test empty node list. - el = goog.dom.createDom('div', null, emptyElem.childNodes); - assertNull('emptyElem.firstChild should be null', emptyElem.firstChild); - assertNull('firstChild should be null', el.firstChild); - - // Test simple node list. - el = goog.dom.createDom('div', null, simpleElem.childNodes); - assertNull('simpleElem.firstChild should be null', simpleElem.firstChild); - assertEquals('firstChild should be a text node with value "Hello, world!"', - 'Hello, world!', el.firstChild.nodeValue); - - // Test complex node list. - el = goog.dom.createDom('div', null, complexElem.childNodes); - assertNull('complexElem.firstChild should be null', complexElem.firstChild); - assertEquals('Element should have 3 child nodes', 3, el.childNodes.length); - assertEquals('childNodes[0] should be a text node with value "Hello, "', - 'Hello, ', el.childNodes[0].nodeValue); - assertEquals('childNodes[1] should be an element node with tagName "B"', - 'B', el.childNodes[1].tagName); - assertEquals('childNodes[2] should be a text node with value "!"', '!', - el.childNodes[2].nodeValue); -} - -function testCreateDomWithTypeAttribute() { - var el = goog.dom.createDom('button', {'type': 'reset', 'id': 'cool-button'}, - 'Cool button'); - assertNotNull('Button with type attribute was created successfully', el); - assertEquals('Button has correct type attribute', 'reset', el.type); - assertEquals('Button has correct id', 'cool-button', el.id); -} - -function testCreateDomWithClassList() { - var el = goog.dom.createDom('div', ['foo', 'bar']); - assertEquals('foo bar', el.className); -} - -function testContains() { - assertTrue('HTML should contain BODY', goog.dom.contains( - document.documentElement, document.body)); - assertTrue('Document should contain BODY', goog.dom.contains( - document, document.body)); - - var d = goog.dom.createDom('p', null, 'A paragraph'); - var t = d.firstChild; - assertTrue('Same element', goog.dom.contains(d, d)); - assertTrue('Same text', goog.dom.contains(t, t)); - assertTrue('Nested text', goog.dom.contains(d, t)); - assertFalse('Nested text, reversed', goog.dom.contains(t, d)); - assertFalse('Disconnected element', goog.dom.contains( - document, d)); - goog.dom.appendChild(document.body, d); - assertTrue('Connected element', goog.dom.contains( - document, d)); - goog.dom.removeNode(d); -} - -function testCreateDomWithClassName() { - var el = goog.dom.createDom('div', 'cls'); - assertNull('firstChild should be null', el.firstChild); - assertEquals('Tagname should be a DIV', 'DIV', el.tagName); - assertEquals('ClassName should be cls', 'cls', el.className); - - el = goog.dom.createDom('div', ''); - assertEquals('ClassName should be empty', '', el.className); -} - -function testCompareNodeOrder() { - var b1 = $('b1'); - var b2 = $('b2'); - var p2 = $('p2'); - - assertEquals('equal nodes should compare to 0', 0, - goog.dom.compareNodeOrder(b1, b1)); - - assertTrue('parent should come before child', - goog.dom.compareNodeOrder(p2, b1) < 0); - assertTrue('child should come after parent', - goog.dom.compareNodeOrder(b1, p2) > 0); - - assertTrue('parent should come before text child', - goog.dom.compareNodeOrder(b1, b1.firstChild) < 0); - assertTrue('text child should come after parent', goog.dom.compareNodeOrder( - b1.firstChild, b1) > 0); - - assertTrue('first sibling should come before second', - goog.dom.compareNodeOrder(b1, b2) < 0); - assertTrue('second sibling should come after first', - goog.dom.compareNodeOrder(b2, b1) > 0); - - assertTrue('text node after cousin element returns correct value', - goog.dom.compareNodeOrder(b1.nextSibling, b1) > 0); - assertTrue('text node before cousin element returns correct value', - goog.dom.compareNodeOrder(b1, b1.nextSibling) < 0); - - assertTrue('text node is before once removed cousin element', - goog.dom.compareNodeOrder(b1.firstChild, b2) < 0); - assertTrue('once removed cousin element is before text node', - goog.dom.compareNodeOrder(b2, b1.firstChild) > 0); - - assertTrue('text node is after once removed cousin text node', - goog.dom.compareNodeOrder(b1.nextSibling, b1.firstChild) > 0); - assertTrue('once removed cousin text node is before text node', - goog.dom.compareNodeOrder(b1.firstChild, b1.nextSibling) < 0); - - assertTrue('first text node is before second text node', - goog.dom.compareNodeOrder(b1.previousSibling, b1.nextSibling) < 0); - assertTrue('second text node is after first text node', - goog.dom.compareNodeOrder(b1.nextSibling, b1.previousSibling) > 0); - - assertTrue('grandchild is after grandparent', - goog.dom.compareNodeOrder(b1.firstChild, b1.parentNode) > 0); - assertTrue('grandparent is after grandchild', - goog.dom.compareNodeOrder(b1.parentNode, b1.firstChild) < 0); - - assertTrue('grandchild is after grandparent', - goog.dom.compareNodeOrder(b1.firstChild, b1.parentNode) > 0); - assertTrue('grandparent is after grandchild', - goog.dom.compareNodeOrder(b1.parentNode, b1.firstChild) < 0); - - assertTrue('second cousins compare correctly', - goog.dom.compareNodeOrder(b1.firstChild, b2.firstChild) < 0); - assertTrue('second cousins compare correctly in reverse', - goog.dom.compareNodeOrder(b2.firstChild, b1.firstChild) > 0); - - assertTrue('testEl2 is after testEl', - goog.dom.compareNodeOrder($('testEl2'), $('testEl')) > 0); - assertTrue('testEl is before testEl2', - goog.dom.compareNodeOrder($('testEl'), $('testEl2')) < 0); - - var p = $('order-test'); - var text1 = document.createTextNode('1'); - p.appendChild(text1); - var text2 = document.createTextNode('1'); - p.appendChild(text2); - - assertEquals('Equal text nodes should compare to 0', 0, - goog.dom.compareNodeOrder(text1, text1)); - assertTrue('First text node is before second', - goog.dom.compareNodeOrder(text1, text2) < 0); - assertTrue('Second text node is after first', - goog.dom.compareNodeOrder(text2, text1) > 0); - assertTrue('Late text node is after b1', - goog.dom.compareNodeOrder(text1, $('b1')) > 0); - - assertTrue('Document node is before non-document node', - goog.dom.compareNodeOrder(document, b1) < 0); - assertTrue('Non-document node is after document node', - goog.dom.compareNodeOrder(b1, document) > 0); -} - -function testFindCommonAncestor() { - var b1 = $('b1'); - var b2 = $('b2'); - var p1 = $('p1'); - var p2 = $('p2'); - var testEl2 = $('testEl2'); - - assertNull('findCommonAncestor() = null', goog.dom.findCommonAncestor()); - assertEquals('findCommonAncestor(b1) = b1', b1, - goog.dom.findCommonAncestor(b1)); - assertEquals('findCommonAncestor(b1, b1) = b1', b1, - goog.dom.findCommonAncestor(b1, b1)); - assertEquals('findCommonAncestor(b1, b2) = p2', p2, - goog.dom.findCommonAncestor(b1, b2)); - assertEquals('findCommonAncestor(p1, b2) = body', document.body, - goog.dom.findCommonAncestor(p1, b2)); - assertEquals('findCommonAncestor(testEl2, b1, b2, p1, p2) = body', - document.body, goog.dom.findCommonAncestor(testEl2, b1, b2, p1, p2)); - - var outOfDoc = document.createElement('div'); - assertNull('findCommonAncestor(outOfDoc, b1) = null', - goog.dom.findCommonAncestor(outOfDoc, b1)); -} - -function testRemoveNode() { - var b = document.createElement('b'); - var el = $('p1'); - el.appendChild(b); - goog.dom.removeNode(b); - assertTrue('b should have been removed', el.lastChild != b); -} - -function testReplaceNode() { - var n = $('toReplace'); - var previousSibling = n.previousSibling; - var goodNode = goog.dom.createDom('div', {'id': 'goodReplaceNode'}); - goog.dom.replaceNode(goodNode, n); - - assertEquals('n should have been replaced', previousSibling.nextSibling, - goodNode); - assertNull('n should no longer be in the DOM tree', $('toReplace')); - - var badNode = goog.dom.createDom('div', {'id': 'badReplaceNode'}); - goog.dom.replaceNode(badNode, n); - assertNull('badNode should not be in the DOM tree', $('badReplaceNode')); -} - -function testAppendChildAt() { - var parent = $('p2'); - var origNumChildren = parent.childNodes.length; - - var child1 = document.createElement('div'); - goog.dom.insertChildAt(parent, child1, origNumChildren); - assertEquals(origNumChildren + 1, parent.childNodes.length); - - var child2 = document.createElement('div'); - goog.dom.insertChildAt(parent, child2, origNumChildren + 42); - assertEquals(origNumChildren + 2, parent.childNodes.length); - - var child3 = document.createElement('div'); - goog.dom.insertChildAt(parent, child3, 0); - assertEquals(origNumChildren + 3, parent.childNodes.length); - - var child4 = document.createElement('div'); - goog.dom.insertChildAt(parent, child3, 2); - assertEquals(origNumChildren + 3, parent.childNodes.length); - - parent.removeChild(child1); - parent.removeChild(child2); - parent.removeChild(child3); - - var emptyParentNotInDocument = document.createElement('div'); - goog.dom.insertChildAt(emptyParentNotInDocument, child1, 0); - assertEquals(1, emptyParentNotInDocument.childNodes.length); -} - -function testFlattenElement() { - var text = document.createTextNode('Text'); - var br = document.createElement('br'); - var span = goog.dom.createDom('span', null, text, br); - assertEquals('span should have 2 children', 2, span.childNodes.length); - - var el = $('p1'); - el.appendChild(span); - - var ret = goog.dom.flattenElement(span); - - assertTrue('span should have been removed', el.lastChild != span); - assertFalse('span should have no parent', !!span.parentNode && - span.parentNode.nodeType != goog.dom.NodeType.DOCUMENT_FRAGMENT); - assertEquals('span should have no children', 0, span.childNodes.length); - assertEquals('Last child of p should be br', br, el.lastChild); - assertEquals('Previous sibling of br should be text', text, - br.previousSibling); - - var outOfDoc = goog.dom.createDom('span', null, '1 child'); - // Should do nothing. - goog.dom.flattenElement(outOfDoc); - assertEquals('outOfDoc should still have 1 child', 1, - outOfDoc.childNodes.length); -} - -function testIsNodeLike() { - assertTrue('document should be node like', goog.dom.isNodeLike(document)); - assertTrue('document.body should be node like', - goog.dom.isNodeLike(document.body)); - assertTrue('a text node should be node like', goog.dom.isNodeLike( - document.createTextNode(''))); - - assertFalse('null should not be node like', goog.dom.isNodeLike(null)); - assertFalse('a string should not be node like', goog.dom.isNodeLike('abcd')); - - assertTrue('custom object should be node like', - goog.dom.isNodeLike({nodeType: 1})); -} - -function testIsElement() { - assertFalse('document is not an element', goog.dom.isElement(document)); - assertTrue('document.body is an element', - goog.dom.isElement(document.body)); - assertFalse('a text node is not an element', goog.dom.isElement( - document.createTextNode(''))); - assertTrue('an element created with createElement() is an element', - goog.dom.isElement(document.createElement('a'))); - - assertFalse('null is not an element', goog.dom.isElement(null)); - assertFalse('a string is not an element', goog.dom.isElement('abcd')); - - assertTrue('custom object is an element', - goog.dom.isElement({nodeType: 1})); - assertFalse('custom non-element object is a not an element', - goog.dom.isElement({someProperty: 'somevalue'})); -} - -function testIsWindow() { - var global = goog.global; - var frame = window.frames['frame']; - var otherWindow = window.open('', 'blank'); - var object = {window: goog.global}; - var nullVar = null; - var notDefined; - - try { - // Use try/finally to ensure that we clean up the window we open, even if an - // assertion fails or something else goes wrong. - assertTrue('global object in HTML context should be a window', - goog.dom.isWindow(goog.global)); - assertTrue('iframe window should be a window', goog.dom.isWindow(frame)); - if (otherWindow) { - assertTrue('other window should be a window', - goog.dom.isWindow(otherWindow)); - } - assertFalse('object should not be a window', goog.dom.isWindow(object)); - assertFalse('null should not be a window', goog.dom.isWindow(nullVar)); - assertFalse('undefined should not be a window', - goog.dom.isWindow(notDefined)); - } finally { - if (otherWindow) { - otherWindow.close(); - } - } -} - -function testGetOwnerDocument() { - assertEquals(goog.dom.getOwnerDocument($('p1')), document); - assertEquals(goog.dom.getOwnerDocument(document.body), document); - assertEquals(goog.dom.getOwnerDocument(document.documentElement), document); -} - -// Tests the breakages resulting in rollback cl/64715474 -function testGetOwnerDocumentNonNodeInput() { - // We should fail on null. - assertThrows(function() { - goog.dom.getOwnerDocument(null); - }); - assertEquals(document, goog.dom.getOwnerDocument(window)); -} - -function testDomHelper() { - var x = new goog.dom.DomHelper(window.frames['frame'].document); - assertTrue('Should have some HTML', - x.getDocument().body.innerHTML.length > 0); -} - -function testGetFirstElementChild() { - var p2 = $('p2'); - var b1 = goog.dom.getFirstElementChild(p2); - assertNotNull('First element child of p2 should not be null', b1); - assertEquals('First element child is b1', 'b1', b1.id); - - var c = goog.dom.getFirstElementChild(b1); - assertNull('First element child of b1 should be null', c); - - // Test with an undefined firstElementChild attribute. - var b2 = $('b2'); - var mockP2 = { - childNodes: [b1, b2], - firstChild: b1, - firstElementChild: undefined - }; - - b1 = goog.dom.getFirstElementChild(mockP2); - assertNotNull('First element child of mockP2 should not be null', b1); - assertEquals('First element child is b1', 'b1', b1.id); -} - -function testGetLastElementChild() { - var p2 = $('p2'); - var b2 = goog.dom.getLastElementChild(p2); - assertNotNull('Last element child of p2 should not be null', b2); - assertEquals('Last element child is b2', 'b2', b2.id); - - var c = goog.dom.getLastElementChild(b2); - assertNull('Last element child of b2 should be null', c); - - // Test with an undefined lastElementChild attribute. - var b1 = $('b1'); - var mockP2 = { - childNodes: [b1, b2], - lastChild: b2, - lastElementChild: undefined - }; - - b2 = goog.dom.getLastElementChild(mockP2); - assertNotNull('Last element child of mockP2 should not be null', b2); - assertEquals('Last element child is b2', 'b2', b2.id); -} - -function testGetNextElementSibling() { - var b1 = $('b1'); - var b2 = goog.dom.getNextElementSibling(b1); - assertNotNull('Next element sibling of b1 should not be null', b1); - assertEquals('Next element sibling is b2', 'b2', b2.id); - - var c = goog.dom.getNextElementSibling(b2); - assertNull('Next element sibling of b2 should be null', c); - - // Test with an undefined nextElementSibling attribute. - var mockB1 = { - nextSibling: b2, - nextElementSibling: undefined - }; - - b2 = goog.dom.getNextElementSibling(mockB1); - assertNotNull('Next element sibling of mockB1 should not be null', b1); - assertEquals('Next element sibling is b2', 'b2', b2.id); -} - -function testGetPreviousElementSibling() { - var b2 = $('b2'); - var b1 = goog.dom.getPreviousElementSibling(b2); - assertNotNull('Previous element sibling of b2 should not be null', b1); - assertEquals('Previous element sibling is b1', 'b1', b1.id); - - var c = goog.dom.getPreviousElementSibling(b1); - assertNull('Previous element sibling of b1 should be null', c); - - // Test with an undefined previousElementSibling attribute. - var mockB2 = { - previousSibling: b1, - previousElementSibling: undefined - }; - - b1 = goog.dom.getPreviousElementSibling(mockB2); - assertNotNull('Previous element sibling of mockB2 should not be null', b1); - assertEquals('Previous element sibling is b1', 'b1', b1.id); -} - -function testGetChildren() { - var p2 = $('p2'); - var children = goog.dom.getChildren(p2); - assertNotNull('Elements array should not be null', children); - assertEquals('List of element children should be length two.', 2, - children.length); - - var b1 = $('b1'); - var b2 = $('b2'); - assertObjectEquals('First element child should be b1.', b1, children[0]); - assertObjectEquals('Second element child should be b2.', b2, children[1]); - - var noChildren = goog.dom.getChildren(b1); - assertNotNull('Element children array should not be null', noChildren); - assertEquals('List of element children should be length zero.', 0, - noChildren.length); - - // Test with an undefined children attribute. - var mockP2 = { - childNodes: [b1, b2], - children: undefined - }; - - children = goog.dom.getChildren(mockP2); - assertNotNull('Elements array should not be null', children); - assertEquals('List of element children should be length two.', 2, - children.length); - - assertObjectEquals('First element child should be b1.', b1, children[0]); - assertObjectEquals('Second element child should be b2.', b2, children[1]); -} - -function testGetNextNode() { - var tree = goog.dom.htmlToDocumentFragment( - '
    ' + - '

    Some text

    ' + - '
    Some special text
    ' + - '
    Foo
    ' + - '
    '); - - assertNull(goog.dom.getNextNode(null)); - - var node = tree; - var next = function() { - return node = goog.dom.getNextNode(node); - }; - - assertEquals('P', next().tagName); - assertEquals('Some text', next().nodeValue); - assertEquals('BLOCKQUOTE', next().tagName); - assertEquals('Some ', next().nodeValue); - assertEquals('I', next().tagName); - assertEquals('special', next().nodeValue); - assertEquals(' ', next().nodeValue); - assertEquals('B', next().tagName); - assertEquals('text', next().nodeValue); - assertEquals('ADDRESS', next().tagName); - assertEquals(goog.dom.NodeType.COMMENT, next().nodeType); - assertEquals('Foo', next().nodeValue); - - assertNull(next()); -} - -function testGetPreviousNode() { - var tree = goog.dom.htmlToDocumentFragment( - '
    ' + - '

    Some text

    ' + - '
    Some special text
    ' + - '
    Foo
    ' + - '
    '); - - assertNull(goog.dom.getPreviousNode(null)); - - var node = tree.lastChild.lastChild; - var previous = function() { - return node = goog.dom.getPreviousNode(node); - }; - - assertEquals(goog.dom.NodeType.COMMENT, previous().nodeType); - assertEquals('ADDRESS', previous().tagName); - assertEquals('text', previous().nodeValue); - assertEquals('B', previous().tagName); - assertEquals(' ', previous().nodeValue); - assertEquals('special', previous().nodeValue); - assertEquals('I', previous().tagName); - assertEquals('Some ', previous().nodeValue); - assertEquals('BLOCKQUOTE', previous().tagName); - assertEquals('Some text', previous().nodeValue); - assertEquals('P', previous().tagName); - assertEquals('DIV', previous().tagName); - - if (!goog.userAgent.IE) { - // Internet Explorer maintains a parentNode for Elements after they are - // removed from the hierarchy. Everyone else agrees on a null parentNode. - assertNull(previous()); - } -} - -function testSetTextContent() { - var p1 = $('p1'); - var s = 'hello world'; - goog.dom.setTextContent(p1, s); - assertEquals('We should have one childNode after setTextContent', 1, - p1.childNodes.length); - assertEquals(s, p1.firstChild.data); - assertEquals(s, p1.innerHTML); - - s = 'four elefants < five ants'; - var sHtml = 'four elefants < five ants'; - goog.dom.setTextContent(p1, s); - assertEquals('We should have one childNode after setTextContent', 1, - p1.childNodes.length); - assertEquals(s, p1.firstChild.data); - assertEquals(sHtml, p1.innerHTML); - - // ensure that we remove existing children - p1.innerHTML = 'abc'; - s = 'hello world'; - goog.dom.setTextContent(p1, s); - assertEquals('We should have one childNode after setTextContent', 1, - p1.childNodes.length); - assertEquals(s, p1.firstChild.data); - - // same but start with an element - p1.innerHTML = 'abc'; - s = 'hello world'; - goog.dom.setTextContent(p1, s); - assertEquals('We should have one childNode after setTextContent', 1, - p1.childNodes.length); - assertEquals(s, p1.firstChild.data); - - // Text/CharacterData - p1.innerHTML = 'before'; - s = 'after'; - goog.dom.setTextContent(p1.firstChild, s); - assertEquals('We should have one childNode after setTextContent', 1, - p1.childNodes.length); - assertEquals(s, p1.firstChild.data); - - // DocumentFragment - var df = document.createDocumentFragment(); - s = 'hello world'; - goog.dom.setTextContent(df, s); - assertEquals('We should have one childNode after setTextContent', 1, - df.childNodes.length); - assertEquals(s, df.firstChild.data); - - // clean up - p1.innerHTML = ''; -} - -function testFindNode() { - var expected = document.body; - var result = goog.dom.findNode(document, function(n) { - return n.nodeType == goog.dom.NodeType.ELEMENT && n.tagName == 'BODY'; - }); - assertEquals(expected, result); - - expected = document.getElementsByTagName('P')[0]; - result = goog.dom.findNode(document, function(n) { - return n.nodeType == goog.dom.NodeType.ELEMENT && n.tagName == 'P'; - }); - assertEquals(expected, result); - - result = goog.dom.findNode(document, function(n) { - return false; - }); - assertUndefined(result); -} - -function testFindNodes() { - var expected = document.getElementsByTagName('P'); - var result = goog.dom.findNodes(document, function(n) { - return n.nodeType == goog.dom.NodeType.ELEMENT && n.tagName == 'P'; - }); - assertEquals(expected.length, result.length); - assertEquals(expected[0], result[0]); - assertEquals(expected[1], result[1]); - - result = goog.dom.findNodes(document, function(n) { - return false; - }).length; - assertEquals(0, result); -} - -function createTestDom(txt) { - var dom = goog.dom.createDom('div'); - dom.innerHTML = txt; - return dom; -} - -function testIsFocusableTabIndex() { - assertFalse('isFocusableTabIndex() must be false for no tab index', - goog.dom.isFocusableTabIndex(goog.dom.getElement('noTabIndex'))); - assertFalse('isFocusableTabIndex() must be false for tab index -2', - goog.dom.isFocusableTabIndex(goog.dom.getElement('tabIndexNegative2'))); - assertFalse('isFocusableTabIndex() must be false for tab index -1', - goog.dom.isFocusableTabIndex(goog.dom.getElement('tabIndexNegative1'))); - - // WebKit on Mac doesn't support focusable DIVs until version 526 and later. - if (!goog.userAgent.WEBKIT || !goog.userAgent.MAC || - goog.userAgent.isVersionOrHigher('526')) { - assertTrue('isFocusableTabIndex() must be true for tab index 0', - goog.dom.isFocusableTabIndex(goog.dom.getElement('tabIndex0'))); - assertTrue('isFocusableTabIndex() must be true for tab index 1', - goog.dom.isFocusableTabIndex(goog.dom.getElement('tabIndex1'))); - assertTrue('isFocusableTabIndex() must be true for tab index 2', - goog.dom.isFocusableTabIndex(goog.dom.getElement('tabIndex2'))); - } -} - -function testSetFocusableTabIndex() { - // WebKit on Mac doesn't support focusable DIVs until version 526 and later. - if (!goog.userAgent.WEBKIT || !goog.userAgent.MAC || - goog.userAgent.isVersionOrHigher('526')) { - // Test enabling focusable tab index. - goog.dom.setFocusableTabIndex(goog.dom.getElement('noTabIndex'), true); - assertTrue('isFocusableTabIndex() must be true after enabling tab index', - goog.dom.isFocusableTabIndex(goog.dom.getElement('noTabIndex'))); - - // Test disabling focusable tab index that was added programmatically. - goog.dom.setFocusableTabIndex(goog.dom.getElement('noTabIndex'), false); - assertFalse('isFocusableTabIndex() must be false after disabling tab ' + - 'index that was programmatically added', - goog.dom.isFocusableTabIndex(goog.dom.getElement('noTabIndex'))); - - // Test disabling focusable tab index that was specified in markup. - goog.dom.setFocusableTabIndex(goog.dom.getElement('tabIndex0'), false); - assertFalse('isFocusableTabIndex() must be false after disabling tab ' + - 'index that was specified in markup', - goog.dom.isFocusableTabIndex(goog.dom.getElement('tabIndex0'))); - - // Test re-enabling focusable tab index. - goog.dom.setFocusableTabIndex(goog.dom.getElement('tabIndex0'), true); - assertTrue('isFocusableTabIndex() must be true after reenabling tabindex', - goog.dom.isFocusableTabIndex(goog.dom.getElement('tabIndex0'))); - } -} - -function testIsFocusable() { - // Test all types of form elements with no tab index specified are focusable. - assertTrue('isFocusable() must be true for anchor elements with ' + - 'no tab index', - goog.dom.isFocusable(goog.dom.getElement('noTabIndexAnchor'))); - assertTrue('isFocusable() must be true for input elements with ' + - 'no tab index', - goog.dom.isFocusable(goog.dom.getElement('noTabIndexInput'))); - assertTrue('isFocusable() must be true for textarea elements with ' + - 'no tab index', - goog.dom.isFocusable(goog.dom.getElement('noTabIndexTextArea'))); - assertTrue('isFocusable() must be true for select elements with ' + - 'no tab index', - goog.dom.isFocusable(goog.dom.getElement('noTabIndexSelect'))); - assertTrue('isFocusable() must be true for button elements with ' + - 'no tab index', - goog.dom.isFocusable(goog.dom.getElement('noTabIndexButton'))); - - // Test form element with negative tab index is not focusable. - assertFalse('isFocusable() must be false for form elements with ' + - 'negative tab index', - goog.dom.isFocusable(goog.dom.getElement('negTabIndexButton'))); - - // Test form element with zero tab index is focusable. - assertTrue('isFocusable() must be true for form elements with ' + - 'zero tab index', - goog.dom.isFocusable(goog.dom.getElement('zeroTabIndexButton'))); - - // Test form element with positive tab index is focusable. - assertTrue('isFocusable() must be true for form elements with ' + - 'positive tab index', - goog.dom.isFocusable(goog.dom.getElement('posTabIndexButton'))); - - // Test disabled form element with no tab index is not focusable. - assertFalse('isFocusable() must be false for disabled form elements with ' + - 'no tab index', - goog.dom.isFocusable(goog.dom.getElement('disabledNoTabIndexButton'))); - - // Test disabled form element with negative tab index is not focusable. - assertFalse('isFocusable() must be false for disabled form elements with ' + - 'negative tab index', - goog.dom.isFocusable(goog.dom.getElement('disabledNegTabIndexButton'))); - - // Test disabled form element with zero tab index is not focusable. - assertFalse('isFocusable() must be false for disabled form elements with ' + - 'zero tab index', - goog.dom.isFocusable(goog.dom.getElement('disabledZeroTabIndexButton'))); - - // Test disabled form element with positive tab index is not focusable. - assertFalse('isFocusable() must be false for disabled form elements with ' + - 'positive tab index', - goog.dom.isFocusable(goog.dom.getElement('disabledPosTabIndexButton'))); - - // Test non-form types should return same value as isFocusableTabIndex() - assertEquals('isFocusable() and isFocusableTabIndex() must agree for ' + - ' no tab index', - goog.dom.isFocusableTabIndex(goog.dom.getElement('noTabIndex')), - goog.dom.isFocusable(goog.dom.getElement('noTabIndex'))); - assertEquals('isFocusable() and isFocusableTabIndex() must agree for ' + - ' tab index -2', - goog.dom.isFocusableTabIndex(goog.dom.getElement('tabIndexNegative2')), - goog.dom.isFocusable(goog.dom.getElement('tabIndexNegative2'))); - assertEquals('isFocusable() and isFocusableTabIndex() must agree for ' + - ' tab index -1', - goog.dom.isFocusableTabIndex(goog.dom.getElement('tabIndexNegative1')), - goog.dom.isFocusable(goog.dom.getElement('tabIndexNegative1'))); - -} - -function testGetTextContent() { - function t(inp, out) { - assertEquals(out.replace(/ /g, '_'), - goog.dom.getTextContent( - createTestDom(inp)).replace(/ /g, '_')); - } - - t('abcde', 'abcde'); - t('abcdefgh', 'abcdefgh'); - t('a')); - assertEquals('SCRIPT', script.tagName); - - if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9)) { - // Removing an Element from a DOM tree in IE sets its parentNode to a new - // DocumentFragment. Bizarre! - assertEquals(goog.dom.NodeType.DOCUMENT_FRAGMENT, - goog.dom.removeNode(div).parentNode.nodeType); - } else { - assertNull(div.parentNode); - } -} - -function testHtmlToDocumentFragment() { - var docFragment = goog.dom.htmlToDocumentFragment('12'); - assertNull(docFragment.parentNode); - assertEquals(2, docFragment.childNodes.length); - - var div = goog.dom.htmlToDocumentFragment('
    3
    '); - assertEquals('DIV', div.tagName); - - var script = goog.dom.htmlToDocumentFragment(''); - assertEquals('SCRIPT', script.tagName); - - if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9)) { - // Removing an Element from a DOM tree in IE sets its parentNode to a new - // DocumentFragment. Bizarre! - assertEquals(goog.dom.NodeType.DOCUMENT_FRAGMENT, - goog.dom.removeNode(div).parentNode.nodeType); - } else { - assertNull(div.parentNode); - } -} - -function testAppend() { - var div = document.createElement('div'); - var b = document.createElement('b'); - var c = document.createTextNode('c'); - goog.dom.append(div, 'a', b, c); - assertEqualsCaseAndLeadingWhitespaceInsensitive('ac', div.innerHTML); -} - -function testAppend2() { - var div = myIframeDoc.createElement('div'); - var b = myIframeDoc.createElement('b'); - var c = myIframeDoc.createTextNode('c'); - goog.dom.append(div, 'a', b, c); - assertEqualsCaseAndLeadingWhitespaceInsensitive('ac', div.innerHTML); -} - -function testAppend3() { - var div = document.createElement('div'); - var b = document.createElement('b'); - var c = document.createTextNode('c'); - goog.dom.append(div, ['a', b, c]); - assertEqualsCaseAndLeadingWhitespaceInsensitive('ac', div.innerHTML); -} - -function testAppend4() { - var div = document.createElement('div'); - var div2 = document.createElement('div'); - div2.innerHTML = 'ac'; - goog.dom.append(div, div2.childNodes); - assertEqualsCaseAndLeadingWhitespaceInsensitive('ac', div.innerHTML); - assertFalse(div2.hasChildNodes()); -} - -function testGetDocumentScroll() { - // setUpPage added divForTestingScrolling to the DOM. It's not init'd here so - // it can be shared amonst other tests. - window.scrollTo(100, 100); - - assertEquals(100, goog.dom.getDocumentScroll().x); - assertEquals(100, goog.dom.getDocumentScroll().y); -} - -function testGetDocumentScrollOfFixedViewport() { - // iOS and perhaps other environments don't actually support scrolling. - // Instead, you view the document's fixed layout through a screen viewport. - // We need getDocumentScroll to handle this case though. - // In case of IE10 though, we do want to use scrollLeft/scrollTop - // because the rest of the positioning is done off the scrolled away origin. - var fakeDocumentScrollElement = {scrollLeft: 0, scrollTop: 0}; - var fakeDocument = { - defaultView: {pageXOffset: 100, pageYOffset: 100}, - documentElement: fakeDocumentScrollElement, - body: fakeDocumentScrollElement - }; - var dh = goog.dom.getDomHelper(document); - dh.setDocument(fakeDocument); - if (goog.userAgent.IE && goog.userAgent.isVersionOrHigher(10)) { - assertEquals(0, dh.getDocumentScroll().x); - assertEquals(0, dh.getDocumentScroll().y); - } else { - assertEquals(100, dh.getDocumentScroll().x); - assertEquals(100, dh.getDocumentScroll().y); - } -} - - -function testGetDocumentScrollFromDocumentWithoutABody() { - // Some documents, like SVG docs, do not have a body element. The document - // element should be used when computing the document scroll for these - // documents. - var fakeDocument = { - defaultView: {pageXOffset: 0, pageYOffset: 0}, - documentElement: {scrollLeft: 0, scrollTop: 0} - }; - - var dh = new goog.dom.DomHelper(fakeDocument); - assertEquals(fakeDocument.documentElement, dh.getDocumentScrollElement()); - assertEquals(0, dh.getDocumentScroll().x); - assertEquals(0, dh.getDocumentScroll().y); - // OK if this does not throw. -} - -function testActiveElementIE() { - if (!goog.userAgent.IE) { - return; - } - - var link = goog.dom.getElement('link'); - link.focus(); - - assertEquals(link.tagName, goog.dom.getActiveElement(document).tagName); - assertEquals(link, goog.dom.getActiveElement(document)); -} - -function testParentElement() { - var testEl = $('testEl'); - var bodyEl = goog.dom.getParentElement(testEl); - assertNotNull(bodyEl); - var htmlEl = goog.dom.getParentElement(bodyEl); - assertNotNull(htmlEl); - var documentNotAnElement = goog.dom.getParentElement(htmlEl); - assertNull(documentNotAnElement); - - var tree = goog.dom.htmlToDocumentFragment( - '
    ' + - '

    Some text

    ' + - '
    Some special text
    ' + - '
    Foo
    ' + - '
    '); - assertNull(goog.dom.getParentElement(tree)); - pEl = goog.dom.getNextNode(tree); - var fragmentRootEl = goog.dom.getParentElement(pEl); - assertEquals(tree, fragmentRootEl); - - var detachedEl = goog.dom.createDom('div'); - var detachedHasNoParent = goog.dom.getParentElement(detachedEl); - assertNull(detachedHasNoParent); - - // svg is not supported in IE8 and below or in IE9 quirks mode - var supported = !goog.userAgent.IE || - goog.userAgent.isDocumentModeOrHigher(10) || - (goog.dom.isCss1CompatMode() && goog.userAgent.isDocumentModeOrHigher(9)); - if (!supported) { - return; - } - - var svg = $('testSvg'); - assertNotNull(svg); - var rect = $('testRect'); - assertNotNull(rect); - var g = $('testG'); - assertNotNull(g); - - if (goog.userAgent.IE && goog.userAgent.isVersionOrHigher('9')) { - // test to make sure IE9 is returning undefined for .parentElement - assertUndefined(g.parentElement); - assertUndefined(rect.parentElement); - assertUndefined(svg.parentElement); - } - var shouldBeG = goog.dom.getParentElement(rect); - assertEquals(g, shouldBeG); - var shouldBeSvg = goog.dom.getParentElement(g); - assertEquals(svg, shouldBeSvg); - var shouldBeBody = goog.dom.getParentElement(svg); - assertEquals(bodyEl, shouldBeBody); -} - - -/** - * @return {boolean} Returns true if the userAgent is IE8 or higher. - */ -function isIE8OrHigher() { - return goog.userAgent.IE && goog.userAgent.product.isVersion('8'); -} - - -function testDevicePixelRatio() { - stubs.set(goog.dom, 'getWindow', goog.functions.constant( - { - matchMedia: function(query) { - return { - matches: query.indexOf('1.5') >= 0 - }; - } - })); - - stubs.set(goog.functions, 'CACHE_RETURN_VALUE', false); - - assertEquals(goog.dom.getPixelRatio(), 1.5); - - stubs.set(goog.dom, 'getWindow', goog.functions.constant( - {devicePixelRatio: 2.0})); - goog.dom.devicePixelRatio_ = null; - assertEquals(goog.dom.getPixelRatio(), 2); - - stubs.set(goog.dom, 'getWindow', goog.functions.constant({})); - goog.dom.devicePixelRatio_ = null; - assertEquals(goog.dom.getPixelRatio(), 1); -} - diff --git a/src/database/third_party/closure-library/closure/goog/dom/fontsizemonitor.js b/src/database/third_party/closure-library/closure/goog/dom/fontsizemonitor.js deleted file mode 100644 index 31fc783196a..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/fontsizemonitor.js +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright 2005 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview A class that can be used to listen to font size changes. - * @author arv@google.com (Erik Arvidsson) - */ - -goog.provide('goog.dom.FontSizeMonitor'); -goog.provide('goog.dom.FontSizeMonitor.EventType'); - -goog.require('goog.dom'); -goog.require('goog.events'); -goog.require('goog.events.EventTarget'); -goog.require('goog.events.EventType'); -goog.require('goog.userAgent'); - - -// TODO(arv): Move this to goog.events instead. - - - -/** - * This class can be used to monitor changes in font size. Instances will - * dispatch a {@code goog.dom.FontSizeMonitor.EventType.CHANGE} event. - * Example usage: - *
    - * var fms = new goog.dom.FontSizeMonitor();
    - * goog.events.listen(fms, goog.dom.FontSizeMonitor.EventType.CHANGE,
    - *     function(e) {
    - *       alert('Font size was changed');
    - *     });
    - * 
    - * @param {goog.dom.DomHelper=} opt_domHelper DOM helper object that is used to - * determine where to insert the DOM nodes used to determine when the font - * size changes. - * @constructor - * @extends {goog.events.EventTarget} - * @final - */ -goog.dom.FontSizeMonitor = function(opt_domHelper) { - goog.events.EventTarget.call(this); - - var dom = opt_domHelper || goog.dom.getDomHelper(); - - /** - * Offscreen iframe which we use to detect resize events. - * @type {Element} - * @private - */ - this.sizeElement_ = dom.createDom( - // The size of the iframe is expressed in em, which are font size relative - // which will cause the iframe to be resized when the font size changes. - // The actual values are not relevant as long as we can ensure that the - // iframe has a non zero size and is completely off screen. - goog.userAgent.IE ? 'div' : 'iframe', { - 'style': 'position:absolute;width:9em;height:9em;top:-99em', - 'tabIndex': -1, - 'aria-hidden': 'true' - }); - var p = dom.getDocument().body; - p.insertBefore(this.sizeElement_, p.firstChild); - - /** - * The object that we listen to resize events on. - * @type {Element|Window} - * @private - */ - var resizeTarget = this.resizeTarget_ = - goog.userAgent.IE ? this.sizeElement_ : - goog.dom.getFrameContentWindow( - /** @type {HTMLIFrameElement} */ (this.sizeElement_)); - - // We need to open and close the document to get Firefox 2 to work. We must - // not do this for IE in case we are using HTTPS since accessing the document - // on an about:blank iframe in IE using HTTPS raises a Permission Denied - // error. - if (goog.userAgent.GECKO) { - var doc = resizeTarget.document; - doc.open(); - doc.close(); - } - - // Listen to resize event on the window inside the iframe. - goog.events.listen(resizeTarget, goog.events.EventType.RESIZE, - this.handleResize_, false, this); - - /** - * Last measured width of the iframe element. - * @type {number} - * @private - */ - this.lastWidth_ = this.sizeElement_.offsetWidth; -}; -goog.inherits(goog.dom.FontSizeMonitor, goog.events.EventTarget); - - -/** - * The event types that the FontSizeMonitor fires. - * @enum {string} - */ -goog.dom.FontSizeMonitor.EventType = { - // TODO(arv): Change value to 'change' after updating the callers. - CHANGE: 'fontsizechange' -}; - - -/** - * Constant for the change event. - * @type {string} - * @deprecated Use {@code goog.dom.FontSizeMonitor.EventType.CHANGE} instead. - */ -goog.dom.FontSizeMonitor.CHANGE_EVENT = - goog.dom.FontSizeMonitor.EventType.CHANGE; - - -/** @override */ -goog.dom.FontSizeMonitor.prototype.disposeInternal = function() { - goog.dom.FontSizeMonitor.superClass_.disposeInternal.call(this); - - goog.events.unlisten(this.resizeTarget_, goog.events.EventType.RESIZE, - this.handleResize_, false, this); - this.resizeTarget_ = null; - - // Firefox 2 crashes if the iframe is removed during the unload phase. - if (!goog.userAgent.GECKO || - goog.userAgent.isVersionOrHigher('1.9')) { - goog.dom.removeNode(this.sizeElement_); - } - delete this.sizeElement_; -}; - - -/** - * Handles the onresize event of the iframe and dispatches a change event in - * case its size really changed. - * @param {goog.events.BrowserEvent} e The event object. - * @private - */ -goog.dom.FontSizeMonitor.prototype.handleResize_ = function(e) { - // Only dispatch the event if the size really changed. Some newer browsers do - // not really change the font-size, instead they zoom the whole page. This - // does trigger window resize events on the iframe but the logical pixel size - // remains the same (the device pixel size changes but that is irrelevant). - var currentWidth = this.sizeElement_.offsetWidth; - if (this.lastWidth_ != currentWidth) { - this.lastWidth_ = currentWidth; - this.dispatchEvent(goog.dom.FontSizeMonitor.EventType.CHANGE); - } -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/fontsizemonitor_test.html b/src/database/third_party/closure-library/closure/goog/dom/fontsizemonitor_test.html deleted file mode 100644 index acdb0faeafe..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/fontsizemonitor_test.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - -Closure Unit Tests - goog.dom.FontSizeMonitor - - - - - - - - - -
    - - -
    - - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/fontsizemonitor_test.js b/src/database/third_party/closure-library/closure/goog/dom/fontsizemonitor_test.js deleted file mode 100644 index 93fb2c7b29c..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/fontsizemonitor_test.js +++ /dev/null @@ -1,257 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.dom.FontSizeMonitorTest'); -goog.setTestOnly('goog.dom.FontSizeMonitorTest'); - -goog.require('goog.dom'); -goog.require('goog.dom.FontSizeMonitor'); -goog.require('goog.events'); -goog.require('goog.events.Event'); -goog.require('goog.testing.PropertyReplacer'); -goog.require('goog.testing.events'); -goog.require('goog.testing.jsunit'); -goog.require('goog.userAgent'); - -function isBuggyGecko() { - return goog.userAgent.GECKO && !goog.userAgent.isVersionOrHigher('1.9'); -} - -var monitor; - -function setUp() { - monitor = new goog.dom.FontSizeMonitor(); -} - -function tearDown() { - monitor.dispose(); -} - -function getResizeTarget() { - return goog.userAgent.IE ? monitor.sizeElement_ : - goog.dom.getFrameContentWindow(monitor.sizeElement_); -} - -function testFontSizeNoChange() { - // This tests that firing the resize event without changing the font-size - // does not trigger the event. - - var fired = false; - goog.events.listen(monitor, goog.dom.FontSizeMonitor.EventType.CHANGE, - function(e) { - fired = true; - }); - - var resizeEvent = new goog.events.Event('resize', getResizeTarget()); - goog.testing.events.fireBrowserEvent(resizeEvent); - - assertFalse('The font size should not have changed', fired); -} - -function testFontSizeChanged() { - // One can trigger the iframe resize by changing the - // document.body.style.fontSize but the event is fired asynchronously in - // Firefox. Instead, we just override the lastWidth_ to simulate that the - // size changed. - - var fired = false; - goog.events.listen(monitor, goog.dom.FontSizeMonitor.EventType.CHANGE, - function(e) { - fired = true; - }); - - monitor.lastWidth_--; - - var resizeEvent = new goog.events.Event('resize', getResizeTarget()); - goog.testing.events.fireBrowserEvent(resizeEvent); - - assertTrue('The font size should have changed', fired); -} - -function testCreateAndDispose() { - var frameCount = window.frames.length; - var iframeElementCount = document.getElementsByTagName('iframe').length; - var divElementCount = document.getElementsByTagName('div').length; - - var monitor = new goog.dom.FontSizeMonitor(); - monitor.dispose(); - - var newFrameCount = window.frames.length; - var newIframeElementCount = document.getElementsByTagName('iframe').length; - var newDivElementCount = document.getElementsByTagName('div').length; - - assertEquals('There should be no trailing frames', - frameCount + isBuggyGecko(), newFrameCount); - assertEquals('There should be no trailing iframe elements', - iframeElementCount + isBuggyGecko(), - newIframeElementCount); - assertEquals('There should be no trailing div elements', - divElementCount, newDivElementCount); -} - -function testWithDomHelper() { - var frameCount = window.frames.length; - var iframeElementCount = document.getElementsByTagName('iframe').length; - var divElementCount = document.getElementsByTagName('div').length; - - var monitor = new goog.dom.FontSizeMonitor(goog.dom.getDomHelper()); - - var newFrameCount = window.frames.length; - var newIframeElementCount = document.getElementsByTagName('iframe').length; - var newDivElementCount = document.getElementsByTagName('div').length; - - if (goog.userAgent.IE) { - assertEquals('There should be one new div element', - divElementCount + 1, newDivElementCount); - } else { - assertEquals('There should be one new frame', - frameCount + 1, newFrameCount); - assertEquals('There should be one new iframe element', - iframeElementCount + 1, newIframeElementCount); - } - - // Use the first iframe in the doc. This is added in the HTML markup. - var win = window.frames[0]; - var doc = win.document; - doc.open(); - doc.write(''); - doc.close(); - var domHelper = goog.dom.getDomHelper(doc); - - var frameCount2 = win.frames.length; - var iframeElementCount2 = doc.getElementsByTagName('iframe').length; - var divElementCount2 = doc.getElementsByTagName('div').length; - - var monitor2 = new goog.dom.FontSizeMonitor(domHelper); - - var newFrameCount2 = win.frames.length; - var newIframeElementCount2 = doc.getElementsByTagName('iframe').length; - var newDivElementCount2 = doc.getElementsByTagName('div').length; - - if (goog.userAgent.IE) { - assertEquals('There should be one new div element', - divElementCount2 + 1, newDivElementCount2); - } else { - assertEquals('There should be one new frame', frameCount2 + 1, - newFrameCount2); - assertEquals('There should be one new iframe element', - iframeElementCount2 + 1, newIframeElementCount2); - } - - monitor.dispose(); - monitor2.dispose(); -} - -function testEnsureThatDocIsOpenedForGecko() { - - var pr = new goog.testing.PropertyReplacer(); - pr.set(goog.userAgent, 'GECKO', true); - pr.set(goog.userAgent, 'IE', false); - - var openCalled = false; - var closeCalled = false; - var instance = { - document: { - open: function() { - openCalled = true; - }, - close: function() { - closeCalled = true; - } - }, - attachEvent: function() {} - }; - - pr.set(goog.dom, 'getFrameContentWindow', function() { - return instance; - }); - - try { - var monitor = new goog.dom.FontSizeMonitor(); - - assertTrue('doc.open should have been called', openCalled); - assertTrue('doc.close should have been called', closeCalled); - - monitor.dispose(); - } finally { - pr.reset(); - } -} - -function testFirefox2WorkAroundFirefox3() { - var pr = new goog.testing.PropertyReplacer(); - pr.set(goog.userAgent, 'GECKO', true); - pr.set(goog.userAgent, 'IE', false); - - try { - // 1.9 should clear iframes - pr.set(goog.userAgent, 'VERSION', '1.9'); - goog.userAgent.isVersionOrHigherCache_ = {}; - - var frameCount = window.frames.length; - var iframeElementCount = document.getElementsByTagName('iframe').length; - var divElementCount = document.getElementsByTagName('div').length; - - var monitor = new goog.dom.FontSizeMonitor(); - monitor.dispose(); - - var newFrameCount = window.frames.length; - var newIframeElementCount = document.getElementsByTagName('iframe').length; - var newDivElementCount = document.getElementsByTagName('div').length; - - assertEquals('There should be no trailing frames', - frameCount, newFrameCount); - assertEquals('There should be no trailing iframe elements', - iframeElementCount, - newIframeElementCount); - assertEquals('There should be no trailing div elements', - divElementCount, newDivElementCount); - } finally { - pr.reset(); - } -} - - -function testFirefox2WorkAroundFirefox2() { - var pr = new goog.testing.PropertyReplacer(); - pr.set(goog.userAgent, 'GECKO', true); - pr.set(goog.userAgent, 'IE', false); - - try { - // 1.8 should NOT clear iframes - pr.set(goog.userAgent, 'VERSION', '1.8'); - goog.userAgent.isVersionOrHigherCache_ = {}; - - var frameCount = window.frames.length; - var iframeElementCount = document.getElementsByTagName('iframe').length; - var divElementCount = document.getElementsByTagName('div').length; - - var monitor = new goog.dom.FontSizeMonitor(); - monitor.dispose(); - - var newFrameCount = window.frames.length; - var newIframeElementCount = document.getElementsByTagName('iframe').length; - var newDivElementCount = document.getElementsByTagName('div').length; - - assertEquals('There should be no trailing frames', - frameCount + 1, newFrameCount); - assertEquals('There should be no trailing iframe elements', - iframeElementCount + 1, - newIframeElementCount); - assertEquals('There should be no trailing div elements', - divElementCount, newDivElementCount); - } finally { - pr.reset(); - } -} diff --git a/src/database/third_party/closure-library/closure/goog/dom/forms.js b/src/database/third_party/closure-library/closure/goog/dom/forms.js deleted file mode 100644 index 53d686c6a27..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/forms.js +++ /dev/null @@ -1,413 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utilities for manipulating a form and elements. - * - * @author arv@google.com (Erik Arvidsson) - */ - -goog.provide('goog.dom.forms'); - -goog.require('goog.structs.Map'); - - -/** - * Returns form data as a map of name to value arrays. This doesn't - * support file inputs. - * @param {HTMLFormElement} form The form. - * @return {!goog.structs.Map.>} A map of the form data - * as field name to arrays of values. - */ -goog.dom.forms.getFormDataMap = function(form) { - var map = new goog.structs.Map(); - goog.dom.forms.getFormDataHelper_(form, map, - goog.dom.forms.addFormDataToMap_); - return map; -}; - - -/** - * Returns the form data as an application/x-www-url-encoded string. This - * doesn't support file inputs. - * @param {HTMLFormElement} form The form. - * @return {string} An application/x-www-url-encoded string. - */ -goog.dom.forms.getFormDataString = function(form) { - var sb = []; - goog.dom.forms.getFormDataHelper_(form, sb, - goog.dom.forms.addFormDataToStringBuffer_); - return sb.join('&'); -}; - - -/** - * Returns the form data as a map or an application/x-www-url-encoded - * string. This doesn't support file inputs. - * @param {HTMLFormElement} form The form. - * @param {Object} result The object form data is being put in. - * @param {Function} fnAppend Function that takes {@code result}, an element - * name, and an element value, and adds the name/value pair to the result - * object. - * @private - */ -goog.dom.forms.getFormDataHelper_ = function(form, result, fnAppend) { - var els = form.elements; - for (var el, i = 0; el = els[i]; i++) { - if (// Make sure we don't include elements that are not part of the form. - // Some browsers include non-form elements. Check for 'form' property. - // See http://code.google.com/p/closure-library/issues/detail?id=227 - // and - // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#the-input-element - (el.form != form) || - el.disabled || - // HTMLFieldSetElement has a form property but no value. - el.tagName.toLowerCase() == 'fieldset') { - continue; - } - - var name = el.name; - switch (el.type.toLowerCase()) { - case 'file': - // file inputs are not supported - case 'submit': - case 'reset': - case 'button': - // don't submit these - break; - case 'select-multiple': - var values = goog.dom.forms.getValue(el); - if (values != null) { - for (var value, j = 0; value = values[j]; j++) { - fnAppend(result, name, value); - } - } - break; - default: - var value = goog.dom.forms.getValue(el); - if (value != null) { - fnAppend(result, name, value); - } - } - } - - // input[type=image] are not included in the elements collection - var inputs = form.getElementsByTagName('input'); - for (var input, i = 0; input = inputs[i]; i++) { - if (input.form == form && input.type.toLowerCase() == 'image') { - name = input.name; - fnAppend(result, name, input.value); - fnAppend(result, name + '.x', '0'); - fnAppend(result, name + '.y', '0'); - } - } -}; - - -/** - * Adds the name/value pair to the map. - * @param {!goog.structs.Map.>} map The map to add to. - * @param {string} name The name. - * @param {string} value The value. - * @private - */ -goog.dom.forms.addFormDataToMap_ = function(map, name, value) { - var array = map.get(name); - if (!array) { - array = []; - map.set(name, array); - } - array.push(value); -}; - - -/** - * Adds a name/value pair to an string buffer array in the form 'name=value'. - * @param {Array} sb The string buffer array for storing data. - * @param {string} name The name. - * @param {string} value The value. - * @private - */ -goog.dom.forms.addFormDataToStringBuffer_ = function(sb, name, value) { - sb.push(encodeURIComponent(name) + '=' + encodeURIComponent(value)); -}; - - -/** - * Whether the form has a file input. - * @param {HTMLFormElement} form The form. - * @return {boolean} Whether the form has a file input. - */ -goog.dom.forms.hasFileInput = function(form) { - var els = form.elements; - for (var el, i = 0; el = els[i]; i++) { - if (!el.disabled && el.type && el.type.toLowerCase() == 'file') { - return true; - } - } - return false; -}; - - -/** - * Enables or disables either all elements in a form or a single form element. - * @param {Element} el The element, either a form or an element within a form. - * @param {boolean} disabled Whether the element should be disabled. - */ -goog.dom.forms.setDisabled = function(el, disabled) { - // disable all elements in a form - if (el.tagName == 'FORM') { - var els = el.elements; - for (var i = 0; el = els[i]; i++) { - goog.dom.forms.setDisabled(el, disabled); - } - } else { - // makes sure to blur buttons, multi-selects, and any elements which - // maintain keyboard/accessibility focus when disabled - if (disabled == true) { - el.blur(); - } - el.disabled = disabled; - } -}; - - -/** - * Focuses, and optionally selects the content of, a form element. - * @param {Element} el The form element. - */ -goog.dom.forms.focusAndSelect = function(el) { - el.focus(); - if (el.select) { - el.select(); - } -}; - - -/** - * Whether a form element has a value. - * @param {Element} el The element. - * @return {boolean} Whether the form has a value. - */ -goog.dom.forms.hasValue = function(el) { - var value = goog.dom.forms.getValue(el); - return !!value; -}; - - -/** - * Whether a named form field has a value. - * @param {HTMLFormElement} form The form element. - * @param {string} name Name of an input to the form. - * @return {boolean} Whether the form has a value. - */ -goog.dom.forms.hasValueByName = function(form, name) { - var value = goog.dom.forms.getValueByName(form, name); - return !!value; -}; - - -/** - * Gets the current value of any element with a type. - * @param {Element} el The element. - * @return {string|Array|null} The current value of the element - * (or null). - */ -goog.dom.forms.getValue = function(el) { - var type = el.type; - if (!goog.isDef(type)) { - return null; - } - switch (type.toLowerCase()) { - case 'checkbox': - case 'radio': - return goog.dom.forms.getInputChecked_(el); - case 'select-one': - return goog.dom.forms.getSelectSingle_(el); - case 'select-multiple': - return goog.dom.forms.getSelectMultiple_(el); - default: - return goog.isDef(el.value) ? el.value : null; - } -}; - - -/** - * Alias for goog.dom.form.element.getValue - * @type {Function} - * @deprecated Use {@link goog.dom.forms.getValue} instead. - * @suppress {missingProvide} - */ -goog.dom.$F = goog.dom.forms.getValue; - - -/** - * Returns the value of the named form field. In the case of radio buttons, - * returns the value of the checked button with the given name. - * - * @param {HTMLFormElement} form The form element. - * @param {string} name Name of an input to the form. - * - * @return {Array|string|null} The value of the form element, or - * null if the form element does not exist or has no value. - */ -goog.dom.forms.getValueByName = function(form, name) { - var els = form.elements[name]; - - if (els) { - if (els.type) { - return goog.dom.forms.getValue(els); - } else { - for (var i = 0; i < els.length; i++) { - var val = goog.dom.forms.getValue(els[i]); - if (val) { - return val; - } - } - } - } - return null; -}; - - -/** - * Gets the current value of a checkable input element. - * @param {Element} el The element. - * @return {?string} The value of the form element (or null). - * @private - */ -goog.dom.forms.getInputChecked_ = function(el) { - return el.checked ? el.value : null; -}; - - -/** - * Gets the current value of a select-one element. - * @param {Element} el The element. - * @return {?string} The value of the form element (or null). - * @private - */ -goog.dom.forms.getSelectSingle_ = function(el) { - var selectedIndex = el.selectedIndex; - return selectedIndex >= 0 ? el.options[selectedIndex].value : null; -}; - - -/** - * Gets the current value of a select-multiple element. - * @param {Element} el The element. - * @return {Array?} The value of the form element (or null). - * @private - */ -goog.dom.forms.getSelectMultiple_ = function(el) { - var values = []; - for (var option, i = 0; option = el.options[i]; i++) { - if (option.selected) { - values.push(option.value); - } - } - return values.length ? values : null; -}; - - -/** - * Sets the current value of any element with a type. - * @param {Element} el The element. - * @param {*=} opt_value The value to give to the element, which will be coerced - * by the browser in the default case using toString. This value should be - * an array for setting the value of select multiple elements. - */ -goog.dom.forms.setValue = function(el, opt_value) { - var type = el.type; - if (goog.isDef(type)) { - switch (type.toLowerCase()) { - case 'checkbox': - case 'radio': - goog.dom.forms.setInputChecked_(el, - /** @type {string} */ (opt_value)); - break; - case 'select-one': - goog.dom.forms.setSelectSingle_(el, - /** @type {string} */ (opt_value)); - break; - case 'select-multiple': - goog.dom.forms.setSelectMultiple_(el, - /** @type {Array} */ (opt_value)); - break; - default: - el.value = goog.isDefAndNotNull(opt_value) ? opt_value : ''; - } - } -}; - - -/** - * Sets a checkable input element's checked property. - * #TODO(user): This seems potentially unintuitive since it doesn't set - * the value property but my hunch is that the primary use case is to check a - * checkbox, not to reset its value property. - * @param {Element} el The element. - * @param {string|boolean=} opt_value The value, sets the element checked if - * val is set. - * @private - */ -goog.dom.forms.setInputChecked_ = function(el, opt_value) { - el.checked = opt_value; -}; - - -/** - * Sets the value of a select-one element. - * @param {Element} el The element. - * @param {string=} opt_value The value of the selected option element. - * @private - */ -goog.dom.forms.setSelectSingle_ = function(el, opt_value) { - // unset any prior selections - el.selectedIndex = -1; - if (goog.isString(opt_value)) { - for (var option, i = 0; option = el.options[i]; i++) { - if (option.value == opt_value) { - option.selected = true; - break; - } - } - } -}; - - -/** - * Sets the value of a select-multiple element. - * @param {Element} el The element. - * @param {Array|string=} opt_value The value of the selected option - * element(s). - * @private - */ -goog.dom.forms.setSelectMultiple_ = function(el, opt_value) { - // reset string opt_values as an array - if (goog.isString(opt_value)) { - opt_value = [opt_value]; - } - for (var option, i = 0; option = el.options[i]; i++) { - // we have to reset the other options to false for select-multiple - option.selected = false; - if (opt_value) { - for (var value, j = 0; value = opt_value[j]; j++) { - if (option.value == value) { - option.selected = true; - } - } - } - } -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/forms_test.html b/src/database/third_party/closure-library/closure/goog/dom/forms_test.html deleted file mode 100644 index 3e7b77715c2..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/forms_test.html +++ /dev/null @@ -1,142 +0,0 @@ - - - - - -Closure Unit Tests - goog.dom.forms - - - - - -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Checkboxes - - -
    - - -
    - Radio Buttons - - -
    - -
    - Radio Buttons - - -
    - - - - - - - - - - -
    - -
    - -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - -
    - -
    - - - -
    - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/forms_test.js b/src/database/third_party/closure-library/closure/goog/dom/forms_test.js deleted file mode 100644 index e444be5bf2b..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/forms_test.js +++ /dev/null @@ -1,377 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.dom.formsTest'); -goog.setTestOnly('goog.dom.formsTest'); - -goog.require('goog.dom'); -goog.require('goog.dom.forms'); -goog.require('goog.testing.jsunit'); - -function testGetFormDataString() { - var el = goog.dom.getElement('testform1'); - var result = goog.dom.forms.getFormDataString(el); - assertEquals( - 'in1=foo&in2=bar&in2=baaz&in3=&pass=bar&textarea=foo%20bar%20baz&' + - 'select1=1&select2=a&select2=c&select3=&checkbox1=on&radio=X&radio2=Y', - result); -} - -function testGetFormDataMap() { - var el = goog.dom.getElement('testform1'); - var result = goog.dom.forms.getFormDataMap(el); - - assertArrayEquals(['foo'], result.get('in1')); - assertArrayEquals(['bar', 'baaz'], result.get('in2')); - assertArrayEquals(['1'], result.get('select1')); - assertArrayEquals(['a', 'c'], result.get('select2')); - assertArrayEquals(['on'], result.get('checkbox1')); - assertUndefined(result.get('select6')); - assertUndefined(result.get('checkbox2')); - assertArrayEquals(['X'], result.get('radio')); - assertArrayEquals(['Y'], result.get('radio2')); -} - -function testHasFileInput() { - var el = goog.dom.getElement('testform1'); - assertFalse(goog.dom.forms.hasFileInput(el)); - el = goog.dom.getElement('testform2'); - assertTrue(goog.dom.forms.hasFileInput(el)); -} - - -function testGetValueOnAtypicalValueElements() { - var el = goog.dom.getElement('testdiv1'); - var result = goog.dom.forms.getValue(el); - assertNull(result); - var el = goog.dom.getElement('testfieldset1'); - var result = goog.dom.forms.getValue(el); - assertNull(result); - var el = goog.dom.getElement('testlegend1'); - var result = goog.dom.forms.getValue(el); - assertNull(result); -} - -function testHasValueInput() { - var el = goog.dom.getElement('in1'); - var result = goog.dom.forms.hasValue(el); - assertTrue(result); -} - -function testGetValueByNameForNonExistentElement() { - var form = goog.dom.getElement('testform1'); - var result = goog.dom.forms.getValueByName(form, 'non_existent'); - assertNull(result); -} - -function testHasValueByNameInput() { - var form = goog.dom.getElement('testform1'); - var result = goog.dom.forms.hasValueByName(form, 'in1'); - assertTrue(result); -} - -function testHasValueInputEmpty() { - var el = goog.dom.getElement('in3'); - var result = goog.dom.forms.hasValue(el); - assertFalse(result); -} - -function testHasValueByNameEmpty() { - var form = goog.dom.getElement('testform1'); - var result = goog.dom.forms.hasValueByName(form, 'in3'); - assertFalse(result); -} - -function testHasValueRadio() { - var el = goog.dom.getElement('radio1'); - var result = goog.dom.forms.hasValue(el); - assertTrue(result); -} - -function testHasValueByNameRadio() { - var form = goog.dom.getElement('testform1'); - var result = goog.dom.forms.hasValueByName(form, 'radio'); - assertTrue(result); -} - -function testHasValueRadioNotChecked() { - var el = goog.dom.getElement('radio2'); - var result = goog.dom.forms.hasValue(el); - assertFalse(result); -} - -function testHasValueByNameRadioNotChecked() { - var form = goog.dom.getElement('testform3'); - var result = goog.dom.forms.hasValueByName(form, 'radio3'); - assertFalse(result); -} - -function testHasValueSelectSingle() { - var el = goog.dom.getElement('select1'); - var result = goog.dom.forms.hasValue(el); - assertTrue(result); -} - -function testHasValueByNameSelectSingle() { - var form = goog.dom.getElement('testform1'); - var result = goog.dom.forms.hasValueByName(form, 'select1'); - assertTrue(result); -} - -function testHasValueSelectMultiple() { - var el = goog.dom.getElement('select2'); - var result = goog.dom.forms.hasValue(el); - assertTrue(result); -} - -function testHasValueByNameSelectMultiple() { - var form = goog.dom.getElement('testform1'); - var result = goog.dom.forms.hasValueByName(form, 'select2'); - assertTrue(result); -} - -function testHasValueSelectNotSelected() { - // select without value - var el = goog.dom.getElement('select3'); - var result = goog.dom.forms.hasValue(el); - assertFalse(result); -} - -function testHasValueByNameSelectNotSelected() { - var form = goog.dom.getElement('testform1'); - var result = goog.dom.forms.hasValueByName(form, 'select3'); - assertFalse(result); -} - -function testHasValueSelectMultipleNotSelected() { - var el = goog.dom.getElement('select6'); - var result = goog.dom.forms.hasValue(el); - assertFalse(result); -} - -function testHasValueByNameSelectMultipleNotSelected() { - var form = goog.dom.getElement('testform3'); - var result = goog.dom.forms.hasValueByName(form, 'select6'); - assertFalse(result); -} - -// TODO(user): make this a meaningful selenium test -function testSetDisabledFalse() { -} -function testSetDisabledTrue() { -} - -// TODO(user): make this a meaningful selenium test -function testFocusAndSelect() { - var el = goog.dom.getElement('in1'); - goog.dom.forms.focusAndSelect(el); -} - -function testGetValueInput() { - var el = goog.dom.getElement('in1'); - var result = goog.dom.forms.getValue(el); - assertEquals('foo', result); -} - -function testSetValueInput() { - var el = goog.dom.getElement('in3'); - goog.dom.forms.setValue(el, 'foo'); - assertEquals('foo', goog.dom.forms.getValue(el)); - - goog.dom.forms.setValue(el, 3500); - assertEquals('3500', goog.dom.forms.getValue(el)); - - goog.dom.forms.setValue(el, 0); - assertEquals('0', goog.dom.forms.getValue(el)); - - goog.dom.forms.setValue(el, null); - assertEquals('', goog.dom.forms.getValue(el)); - - goog.dom.forms.setValue(el, undefined); - assertEquals('', goog.dom.forms.getValue(el)); - - goog.dom.forms.setValue(el, false); - assertEquals('false', goog.dom.forms.getValue(el)); - - goog.dom.forms.setValue(el, {}); - assertEquals({}.toString(), goog.dom.forms.getValue(el)); - - goog.dom.forms.setValue(el, { - toString: function() { - return 'test'; - } - }); - assertEquals('test', goog.dom.forms.getValue(el)); - - // unset - goog.dom.forms.setValue(el); - assertEquals('', goog.dom.forms.getValue(el)); -} - -function testGetValuePassword() { - var el = goog.dom.getElement('pass'); - var result = goog.dom.forms.getValue(el); - assertEquals('bar', result); -} - -function testGetValueByNamePassword() { - var form = goog.dom.getElement('testform1'); - var result = goog.dom.forms.getValueByName(form, 'pass'); - assertEquals('bar', result); -} - -function testGetValueTextarea() { - var el = goog.dom.getElement('textarea1'); - var result = goog.dom.forms.getValue(el); - assertEquals('foo bar baz', result); -} - -function testGetValueByNameTextarea() { - var form = goog.dom.getElement('testform1'); - var result = goog.dom.forms.getValueByName(form, 'textarea1'); - assertEquals('foo bar baz', result); -} - -function testSetValueTextarea() { - var el = goog.dom.getElement('textarea2'); - goog.dom.forms.setValue(el, 'foo bar baz'); - var result = goog.dom.forms.getValue(el); - assertEquals('foo bar baz', result); -} - -function testGetValueSelectSingle() { - var el = goog.dom.getElement('select1'); - var result = goog.dom.forms.getValue(el); - assertEquals('1', result); -} - -function testGetValueByNameSelectSingle() { - var form = goog.dom.getElement('testform1'); - var result = goog.dom.forms.getValueByName(form, 'select1'); - assertEquals('1', result); -} - -function testSetValueSelectSingle() { - var el = goog.dom.getElement('select4'); - goog.dom.forms.setValue(el, '2'); - var result = goog.dom.forms.getValue(el); - assertEquals('2', result); - // unset - goog.dom.forms.setValue(el); - var result = goog.dom.forms.getValue(el); - assertNull(result); -} - -function testSetValueSelectSingleEmptyString() { - var el = goog.dom.getElement('select7'); - // unset - goog.dom.forms.setValue(el); - var result = goog.dom.forms.getValue(el); - assertNull(result); - goog.dom.forms.setValue(el, ''); - result = goog.dom.forms.getValue(el); - assertEquals('', result); -} - -function testGetValueSelectMultiple() { - var el = goog.dom.getElement('select2'); - var result = goog.dom.forms.getValue(el); - assertArrayEquals(['a', 'c'], result); -} - -function testGetValueSelectMultipleNotSelected() { - var el = goog.dom.getElement('select6'); - var result = goog.dom.forms.getValue(el); - assertNull(result); -} - -function testGetValueByNameSelectMultiple() { - var form = goog.dom.getElement('testform1'); - var result = goog.dom.forms.getValueByName(form, 'select2'); - assertArrayEquals(['a', 'c'], result); -} - -function testSetValueSelectMultiple() { - var el = goog.dom.getElement('select5'); - goog.dom.forms.setValue(el, ['a', 'c']); - var result = goog.dom.forms.getValue(el); - assertArrayEquals(['a', 'c'], result); - - goog.dom.forms.setValue(el, 'a'); - var result = goog.dom.forms.getValue(el); - assertArrayEquals(['a'], result); - - // unset - goog.dom.forms.setValue(el); - var result = goog.dom.forms.getValue(el); - assertNull(result); -} - -function testGetValueCheckbox() { - var el = goog.dom.getElement('checkbox1'); - var result = goog.dom.forms.getValue(el); - assertEquals('on', result); - var el = goog.dom.getElement('checkbox2'); - var result = goog.dom.forms.getValue(el); - assertNull(result); -} - -function testGetValueByNameCheckbox() { - var form = goog.dom.getElement('testform1'); - var result = goog.dom.forms.getValueByName(form, 'checkbox1'); - assertEquals('on', result); - result = goog.dom.forms.getValueByName(form, 'checkbox2'); - assertNull(result); -} - -function testGetValueRadio() { - var el = goog.dom.getElement('radio1'); - var result = goog.dom.forms.getValue(el); - assertEquals('X', result); - var el = goog.dom.getElement('radio2'); - var result = goog.dom.forms.getValue(el); - assertNull(result); -} - -function testGetValueByNameRadio() { - var form = goog.dom.getElement('testform1'); - var result = goog.dom.forms.getValueByName(form, 'radio'); - assertEquals('X', result); - - result = goog.dom.forms.getValueByName(form, 'radio2'); - assertEquals('Y', result); -} - -function testGetValueButton() { - var el = goog.dom.getElement('button'); - var result = goog.dom.forms.getValue(el); - assertEquals('button', result); -} - -function testGetValueSubmit() { - var el = goog.dom.getElement('submit'); - var result = goog.dom.forms.getValue(el); - assertEquals('submit', result); -} - -function testGetValueReset() { - var el = goog.dom.getElement('reset'); - var result = goog.dom.forms.getValue(el); - assertEquals('reset', result); -} - -function testGetFormDataHelperAndNonInputElements() { - var el = goog.dom.getElement('testform4'); - goog.dom.forms.getFormDataHelper_(el, {}, goog.nullFunction); -} diff --git a/src/database/third_party/closure-library/closure/goog/dom/fullscreen.js b/src/database/third_party/closure-library/closure/goog/dom/fullscreen.js deleted file mode 100644 index 195421350ed..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/fullscreen.js +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2012 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Functions for managing full screen status of the DOM. - * - */ - -goog.provide('goog.dom.fullscreen'); -goog.provide('goog.dom.fullscreen.EventType'); - -goog.require('goog.dom'); -goog.require('goog.userAgent'); - - -/** - * Event types for full screen. - * @enum {string} - */ -goog.dom.fullscreen.EventType = { - /** Dispatched by the Document when the fullscreen status changes. */ - CHANGE: (function() { - if (goog.userAgent.WEBKIT) { - return 'webkitfullscreenchange'; - } - if (goog.userAgent.GECKO) { - return 'mozfullscreenchange'; - } - if (goog.userAgent.IE) { - return 'MSFullscreenChange'; - } - // Opera 12-14, and W3C standard (Draft): - // https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html - return 'fullscreenchange'; - })() -}; - - -/** - * Determines if full screen is supported. - * @param {!goog.dom.DomHelper=} opt_domHelper The DomHelper for the DOM being - * queried. If not provided, use the current DOM. - * @return {boolean} True iff full screen is supported. - */ -goog.dom.fullscreen.isSupported = function(opt_domHelper) { - var doc = goog.dom.fullscreen.getDocument_(opt_domHelper); - var body = doc.body; - return !!(body.webkitRequestFullscreen || - (body.mozRequestFullScreen && doc.mozFullScreenEnabled) || - (body.msRequestFullscreen && doc.msFullscreenEnabled) || - (body.requestFullscreen && doc.fullscreenEnabled)); -}; - - -/** - * Requests putting the element in full screen. - * @param {!Element} element The element to put full screen. - */ -goog.dom.fullscreen.requestFullScreen = function(element) { - if (element.webkitRequestFullscreen) { - element.webkitRequestFullscreen(); - } else if (element.mozRequestFullScreen) { - element.mozRequestFullScreen(); - } else if (element.msRequestFullscreen) { - element.msRequestFullscreen(); - } else if (element.requestFullscreen) { - element.requestFullscreen(); - } -}; - - -/** - * Requests putting the element in full screen with full keyboard access. - * @param {!Element} element The element to put full screen. - */ -goog.dom.fullscreen.requestFullScreenWithKeys = function( - element) { - if (element.mozRequestFullScreenWithKeys) { - element.mozRequestFullScreenWithKeys(); - } else if (element.webkitRequestFullscreen) { - element.webkitRequestFullscreen(); - } else { - goog.dom.fullscreen.requestFullScreen(element); - } -}; - - -/** - * Exits full screen. - * @param {!goog.dom.DomHelper=} opt_domHelper The DomHelper for the DOM being - * queried. If not provided, use the current DOM. - */ -goog.dom.fullscreen.exitFullScreen = function(opt_domHelper) { - var doc = goog.dom.fullscreen.getDocument_(opt_domHelper); - if (doc.webkitCancelFullScreen) { - doc.webkitCancelFullScreen(); - } else if (doc.mozCancelFullScreen) { - doc.mozCancelFullScreen(); - } else if (doc.msExitFullscreen) { - doc.msExitFullscreen(); - } else if (doc.exitFullscreen) { - doc.exitFullscreen(); - } -}; - - -/** - * Determines if the document is full screen. - * @param {!goog.dom.DomHelper=} opt_domHelper The DomHelper for the DOM being - * queried. If not provided, use the current DOM. - * @return {boolean} Whether the document is full screen. - */ -goog.dom.fullscreen.isFullScreen = function(opt_domHelper) { - var doc = goog.dom.fullscreen.getDocument_(opt_domHelper); - // IE 11 doesn't have similar boolean property, so check whether - // document.msFullscreenElement is null instead. - return !!(doc.webkitIsFullScreen || doc.mozFullScreen || - doc.msFullscreenElement || doc.fullscreenElement); -}; - - -/** - * Gets the document object of the dom. - * @param {!goog.dom.DomHelper=} opt_domHelper The DomHelper for the DOM being - * queried. If not provided, use the current DOM. - * @return {!Document} The dom document. - * @private - */ -goog.dom.fullscreen.getDocument_ = function(opt_domHelper) { - return opt_domHelper ? - opt_domHelper.getDocument() : - goog.dom.getDomHelper().getDocument(); -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/iframe.js b/src/database/third_party/closure-library/closure/goog/dom/iframe.js deleted file mode 100644 index 11a37aa6c09..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/iframe.js +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utilities for creating and working with iframes - * cross-browser. - * @author gboyer@google.com (Garry Boyer) - */ - - -goog.provide('goog.dom.iframe'); - -goog.require('goog.dom'); -goog.require('goog.dom.safe'); -goog.require('goog.html.SafeHtml'); -goog.require('goog.html.SafeStyle'); -goog.require('goog.userAgent'); - - -/** - * Safe source for a blank iframe. - * - * Intentionally not about:blank, which gives mixed content warnings in IE6 - * over HTTPS. - * - * @type {string} - */ -goog.dom.iframe.BLANK_SOURCE = 'javascript:""'; - - -/** - * Safe source for a new blank iframe that may not cause a new load of the - * iframe. This is different from {@code goog.dom.iframe.BLANK_SOURCE} in that - * it will allow an iframe to be loaded synchronously in more browsers, notably - * Gecko, following the javascript protocol spec. - * - * NOTE: This should not be used to replace the source of an existing iframe. - * The new src value will be ignored, per the spec. - * - * Due to cross-browser differences, the load is not guaranteed to be - * synchronous. If code depends on the load of the iframe, - * then {@code goog.net.IframeLoadMonitor} or a similar technique should be - * used. - * - * According to - * http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#javascript-protocol - * the 'javascript:""' URL should trigger a new load of the iframe, which may be - * asynchronous. A void src, such as 'javascript:undefined', does not change - * the browsing context document's, and thus should not trigger another load. - * - * Intentionally not about:blank, which also triggers a load. - * - * NOTE: 'javascript:' URL handling spec compliance varies per browser. IE - * throws an error with 'javascript:undefined'. Webkit browsers will reload the - * iframe when setting this source on an existing iframe. - * - * @type {string} - */ -goog.dom.iframe.BLANK_SOURCE_NEW_FRAME = goog.userAgent.IE ? - 'javascript:""' : - 'javascript:undefined'; - - -/** - * Styles to help ensure an undecorated iframe. - * @type {string} - * @private - */ -goog.dom.iframe.STYLES_ = 'border:0;vertical-align:bottom;'; - - -// TODO(user): Introduce legacyconversion in createBlank, writeContent -// and createWithContent; update their docs. Create legacyconversions -// Conformance rules for these functions and remove iframe.js from Conformance -// document.write() whitelist. -/** - * Creates a completely blank iframe element. - * - * The iframe will not caused mixed-content warnings for IE6 under HTTPS. - * The iframe will also have no borders or padding, so that the styled width - * and height will be the actual width and height of the iframe. - * - * This function currently only attempts to create a blank iframe. There - * are no guarantees to the contents of the iframe or whether it is rendered - * in quirks mode. - * - * @param {goog.dom.DomHelper} domHelper The dom helper to use. - * @param {!goog.html.SafeStyle|string=} opt_styles CSS styles for the - * iframe. If possible pass a SafeStyle; string is supported for - * backwards-compatibility only. - * @return {!HTMLIFrameElement} A completely blank iframe. - */ -goog.dom.iframe.createBlank = function(domHelper, opt_styles) { - if (opt_styles instanceof goog.html.SafeStyle) { - opt_styles = goog.html.SafeStyle.unwrap(opt_styles); - } - return /** @type {!HTMLIFrameElement} */ (domHelper.createDom('iframe', { - 'frameborder': 0, - // Since iframes are inline elements, we must align to bottom to - // compensate for the line descent. - 'style': goog.dom.iframe.STYLES_ + (opt_styles || ''), - 'src': goog.dom.iframe.BLANK_SOURCE - })); -}; - - -/** - * Writes the contents of a blank iframe that has already been inserted - * into the document. If possible use {@link #writeSafeContent}, - * this function exists for backwards-compatibility only. - * @param {!HTMLIFrameElement} iframe An iframe with no contents, such as - * one created by goog.dom.iframe.createBlank, but already appended to - * a parent document. - * @param {string} content Content to write to the iframe, from doctype to - * the HTML close tag. - */ -goog.dom.iframe.writeContent = function(iframe, content) { - var doc = goog.dom.getFrameContentDocument(iframe); - doc.open(); - doc.write(content); - doc.close(); -}; - - -/** - * Writes the contents of a blank iframe that has already been inserted - * into the document. - * @param {!HTMLIFrameElement} iframe An iframe with no contents, such as - * one created by {@link #createBlank}, but already appended to - * a parent document. - * @param {!goog.html.SafeHtml} content Content to write to the iframe, - * from doctype to the HTML close tag. - */ -goog.dom.iframe.writeSafeContent = function(iframe, content) { - var doc = goog.dom.getFrameContentDocument(iframe); - doc.open(); - goog.dom.safe.documentWrite(doc, content); - doc.close(); -}; - - -// TODO(gboyer): Provide a higher-level API for the most common use case, so -// that you can just provide a list of stylesheets and some content HTML. -/** - * Creates a same-domain iframe containing preloaded content. - * - * This is primarily useful for DOM sandboxing. One use case is to embed - * a trusted Javascript app with potentially conflicting CSS styles. The - * second case is to reduce the cost of layout passes by the browser -- for - * example, you can perform sandbox sizing of characters in an iframe while - * manipulating a heavy DOM in the main window. The iframe and parent frame - * can access each others' properties and functions without restriction. - * - * @param {!Element} parentElement The parent element in which to append the - * iframe. - * @param {!goog.html.SafeHtml|string=} opt_headContents Contents to go into - * the iframe's head. If possible pass a SafeHtml; string is supported for - * backwards-compatibility only. - * @param {!goog.html.SafeHtml|string=} opt_bodyContents Contents to go into - * the iframe's body. If possible pass a SafeHtml; string is supported for - * backwards-compatibility only. - * @param {!goog.html.SafeStyle|string=} opt_styles CSS styles for the iframe - * itself, before adding to the parent element. If possible pass a - * SafeStyle; string is supported for backwards-compatibility only. - * @param {boolean=} opt_quirks Whether to use quirks mode (false by default). - * @return {!HTMLIFrameElement} An iframe that has the specified contents. - */ -goog.dom.iframe.createWithContent = function( - parentElement, opt_headContents, opt_bodyContents, opt_styles, opt_quirks) { - var domHelper = goog.dom.getDomHelper(parentElement); - - if (opt_headContents instanceof goog.html.SafeHtml) { - opt_headContents = goog.html.SafeHtml.unwrap(opt_headContents); - } - if (opt_bodyContents instanceof goog.html.SafeHtml) { - opt_bodyContents = goog.html.SafeHtml.unwrap(opt_bodyContents); - } - if (opt_styles instanceof goog.html.SafeStyle) { - opt_styles = goog.html.SafeStyle.unwrap(opt_styles); - } - - // Generate the HTML content. - var contentBuf = []; - - if (!opt_quirks) { - contentBuf.push(''); - } - contentBuf.push('', opt_headContents, '', - opt_bodyContents, ''); - - var iframe = goog.dom.iframe.createBlank(domHelper, opt_styles); - - // Cannot manipulate iframe content until it is in a document. - parentElement.appendChild(iframe); - goog.dom.iframe.writeContent(iframe, contentBuf.join('')); - - return iframe; -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/iframe_test.html b/src/database/third_party/closure-library/closure/goog/dom/iframe_test.html deleted file mode 100644 index 7c952af4351..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/iframe_test.html +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - -Closure Unit Tests - goog.dom.iframe - - - - - -
    -
    - Blank Iframe - The below area should be completely white. -
    - - - -
    -
    -
    -
    -
    - -
    - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/iframe_test.js b/src/database/third_party/closure-library/closure/goog/dom/iframe_test.js deleted file mode 100644 index 02851c02c4c..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/iframe_test.js +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.dom.iframeTest'); -goog.setTestOnly('goog.dom.iframeTest'); - -goog.require('goog.dom'); -goog.require('goog.dom.iframe'); -goog.require('goog.html.SafeHtml'); -goog.require('goog.html.SafeStyle'); -goog.require('goog.string.Const'); -goog.require('goog.testing.jsunit'); - -var domHelper; -var sandbox; - -function setUpPage() { - domHelper = goog.dom.getDomHelper(); - sandbox = domHelper.getElement('sandbox'); -} - -function setUp() { - goog.dom.removeChildren(sandbox); -} - -function testCreateWithContent() { - var iframe = goog.dom.iframe.createWithContent(sandbox, - 'Foo Title', '
    Test
    ', - 'position: absolute', - false /* opt_quirks */); - - var doc = goog.dom.getFrameContentDocument(iframe); - assertNotNull(doc.getElementById('blah')); - assertEquals('Foo Title', doc.title); - assertEquals('absolute', iframe.style.position); -} - -function testCreateWithContent_safeTypes() { - var head = goog.html.SafeHtml.create('title', {}, 'Foo Title'); - var body = goog.html.SafeHtml.create('div', {id: 'blah'}, 'Test'); - var style = goog.html.SafeStyle.fromConstant(goog.string.Const.from( - 'position: absolute;')); - var iframe = goog.dom.iframe.createWithContent(sandbox, - head, body, style, - false /* opt_quirks */); - - var doc = goog.dom.getFrameContentDocument(iframe); - assertNotNull(doc.getElementById('blah')); - assertEquals('Foo Title', doc.title); - assertEquals('absolute', iframe.style.position); -} - -function testCreateBlankYieldsIframeWithNoBorderOrPadding() { - var iframe = goog.dom.iframe.createBlank(domHelper); - iframe.style.width = '350px'; - iframe.style.height = '250px'; - var blankElement = domHelper.getElement('blank'); - blankElement.appendChild(iframe); - assertEquals( - 'Width should be as styled: no extra borders, padding, etc.', - 350, blankElement.offsetWidth); - assertEquals( - 'Height should be as styled: no extra borders, padding, etc.', - 250, blankElement.offsetHeight); -} - -function testCreateBlankWithStyles() { - var iframe = goog.dom.iframe.createBlank(domHelper, 'position:absolute;'); - assertEquals('absolute', iframe.style.position); - assertEquals('bottom', iframe.style.verticalAlign); -} - -function testCreateBlankWithSafeStyles() { - var iframe = goog.dom.iframe.createBlank( - domHelper, - goog.html.SafeStyle.fromConstant(goog.string.Const.from( - 'position:absolute;'))); - assertEquals('absolute', iframe.style.position); - assertEquals('bottom', iframe.style.verticalAlign); -} diff --git a/src/database/third_party/closure-library/closure/goog/dom/iter.js b/src/database/third_party/closure-library/closure/goog/dom/iter.js deleted file mode 100644 index 75164145006..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/iter.js +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Iterators over DOM nodes. - * - * @author robbyw@google.com (Robby Walker) - */ - -goog.provide('goog.dom.iter.AncestorIterator'); -goog.provide('goog.dom.iter.ChildIterator'); -goog.provide('goog.dom.iter.SiblingIterator'); - -goog.require('goog.iter.Iterator'); -goog.require('goog.iter.StopIteration'); - - - -/** - * Iterator over a Node's siblings. - * @param {Node} node The node to start with. - * @param {boolean=} opt_includeNode Whether to return the given node as the - * first return value from next. - * @param {boolean=} opt_reverse Whether to traverse siblings in reverse - * document order. - * @constructor - * @extends {goog.iter.Iterator} - */ -goog.dom.iter.SiblingIterator = function(node, opt_includeNode, opt_reverse) { - /** - * The current node, or null if iteration is finished. - * @type {Node} - * @private - */ - this.node_ = node; - - /** - * Whether to iterate in reverse. - * @type {boolean} - * @private - */ - this.reverse_ = !!opt_reverse; - - if (node && !opt_includeNode) { - this.next(); - } -}; -goog.inherits(goog.dom.iter.SiblingIterator, goog.iter.Iterator); - - -/** @override */ -goog.dom.iter.SiblingIterator.prototype.next = function() { - var node = this.node_; - if (!node) { - throw goog.iter.StopIteration; - } - this.node_ = this.reverse_ ? node.previousSibling : node.nextSibling; - return node; -}; - - - -/** - * Iterator over an Element's children. - * @param {Element} element The element to iterate over. - * @param {boolean=} opt_reverse Optionally traverse children from last to - * first. - * @param {number=} opt_startIndex Optional starting index. - * @constructor - * @extends {goog.dom.iter.SiblingIterator} - * @final - */ -goog.dom.iter.ChildIterator = function(element, opt_reverse, opt_startIndex) { - if (!goog.isDef(opt_startIndex)) { - opt_startIndex = opt_reverse && element.childNodes.length ? - element.childNodes.length - 1 : 0; - } - goog.dom.iter.SiblingIterator.call(this, element.childNodes[opt_startIndex], - true, opt_reverse); -}; -goog.inherits(goog.dom.iter.ChildIterator, goog.dom.iter.SiblingIterator); - - - -/** - * Iterator over a Node's ancestors, stopping after the document body. - * @param {Node} node The node to start with. - * @param {boolean=} opt_includeNode Whether to return the given node as the - * first return value from next. - * @constructor - * @extends {goog.iter.Iterator} - * @final - */ -goog.dom.iter.AncestorIterator = function(node, opt_includeNode) { - /** - * The current node, or null if iteration is finished. - * @type {Node} - * @private - */ - this.node_ = node; - - if (node && !opt_includeNode) { - this.next(); - } -}; -goog.inherits(goog.dom.iter.AncestorIterator, goog.iter.Iterator); - - -/** @override */ -goog.dom.iter.AncestorIterator.prototype.next = function() { - var node = this.node_; - if (!node) { - throw goog.iter.StopIteration; - } - this.node_ = node.parentNode; - return node; -}; - diff --git a/src/database/third_party/closure-library/closure/goog/dom/iter_test.html b/src/database/third_party/closure-library/closure/goog/dom/iter_test.html deleted file mode 100644 index 8936c0c78d4..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/iter_test.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - -Closure Unit Tests - goog.dom.iter - - - - -
    abc
    def
    - - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/iter_test.js b/src/database/third_party/closure-library/closure/goog/dom/iter_test.js deleted file mode 100644 index d141c0604a8..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/iter_test.js +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.dom.iterTest'); -goog.setTestOnly('goog.dom.iterTest'); - -goog.require('goog.dom'); -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.iter.AncestorIterator'); -goog.require('goog.dom.iter.ChildIterator'); -goog.require('goog.dom.iter.SiblingIterator'); -goog.require('goog.testing.dom'); -goog.require('goog.testing.jsunit'); - -var test; -var br; - -function setUpPage() { - test = goog.dom.getElement('test'); - br = goog.dom.getElement('br'); -} - -function testNextSibling() { - goog.testing.dom.assertNodesMatch( - new goog.dom.iter.SiblingIterator(test.firstChild), - ['#br', 'def']); -} - -function testNextSiblingInclusive() { - goog.testing.dom.assertNodesMatch( - new goog.dom.iter.SiblingIterator(test.firstChild, true), - ['abc', '#br', 'def']); -} - -function testPreviousSibling() { - goog.testing.dom.assertNodesMatch( - new goog.dom.iter.SiblingIterator(test.lastChild, false, true), - ['#br', 'abc']); -} - -function testPreviousSiblingInclusive() { - goog.testing.dom.assertNodesMatch( - new goog.dom.iter.SiblingIterator(test.lastChild, true, true), - ['def', '#br', 'abc']); -} - -function testChildIterator() { - goog.testing.dom.assertNodesMatch( - new goog.dom.iter.ChildIterator(test), - ['abc', '#br', 'def']); -} - -function testChildIteratorIndex() { - goog.testing.dom.assertNodesMatch( - new goog.dom.iter.ChildIterator(test, false, 1), - ['#br', 'def']); -} - -function testChildIteratorReverse() { - goog.testing.dom.assertNodesMatch( - new goog.dom.iter.ChildIterator(test, true), - ['def', '#br', 'abc']); -} - -function testEmptyChildIteratorReverse() { - goog.testing.dom.assertNodesMatch( - new goog.dom.iter.ChildIterator(br, true), []); -} - -function testChildIteratorIndexReverse() { - goog.testing.dom.assertNodesMatch( - new goog.dom.iter.ChildIterator(test, true, 1), - ['#br', 'abc']); -} - -function testAncestorIterator() { - goog.testing.dom.assertNodesMatch( - new goog.dom.iter.AncestorIterator(br), - ['#test', '#body', '#html', goog.dom.NodeType.DOCUMENT]); -} - -function testAncestorIteratorInclusive() { - goog.testing.dom.assertNodesMatch( - new goog.dom.iter.AncestorIterator(br, true), - ['#br', '#test', '#body', '#html', goog.dom.NodeType.DOCUMENT]); -} diff --git a/src/database/third_party/closure-library/closure/goog/dom/multirange.js b/src/database/third_party/closure-library/closure/goog/dom/multirange.js deleted file mode 100644 index 69e3b41b2d1..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/multirange.js +++ /dev/null @@ -1,521 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utilities for working with W3C multi-part ranges. - * - * @author robbyw@google.com (Robby Walker) - */ - - -goog.provide('goog.dom.MultiRange'); -goog.provide('goog.dom.MultiRangeIterator'); - -goog.require('goog.array'); -goog.require('goog.dom.AbstractMultiRange'); -goog.require('goog.dom.AbstractRange'); -goog.require('goog.dom.RangeIterator'); -goog.require('goog.dom.RangeType'); -goog.require('goog.dom.SavedRange'); -goog.require('goog.dom.TextRange'); -goog.require('goog.iter.StopIteration'); -goog.require('goog.log'); - - - -/** - * Creates a new multi part range with no properties. Do not use this - * constructor: use one of the goog.dom.Range.createFrom* methods instead. - * @constructor - * @extends {goog.dom.AbstractMultiRange} - * @final - */ -goog.dom.MultiRange = function() { - /** - * Array of browser sub-ranges comprising this multi-range. - * @type {Array} - * @private - */ - this.browserRanges_ = []; - - /** - * Lazily initialized array of range objects comprising this multi-range. - * @type {Array} - * @private - */ - this.ranges_ = []; - - /** - * Lazily computed sorted version of ranges_, sorted by start point. - * @type {Array?} - * @private - */ - this.sortedRanges_ = null; - - /** - * Lazily computed container node. - * @type {Node} - * @private - */ - this.container_ = null; -}; -goog.inherits(goog.dom.MultiRange, goog.dom.AbstractMultiRange); - - -/** - * Creates a new range wrapper from the given browser selection object. Do not - * use this method directly - please use goog.dom.Range.createFrom* instead. - * @param {Selection} selection The browser selection object. - * @return {!goog.dom.MultiRange} A range wrapper object. - */ -goog.dom.MultiRange.createFromBrowserSelection = function(selection) { - var range = new goog.dom.MultiRange(); - for (var i = 0, len = selection.rangeCount; i < len; i++) { - range.browserRanges_.push(selection.getRangeAt(i)); - } - return range; -}; - - -/** - * Creates a new range wrapper from the given browser ranges. Do not - * use this method directly - please use goog.dom.Range.createFrom* instead. - * @param {Array} browserRanges The browser ranges. - * @return {!goog.dom.MultiRange} A range wrapper object. - */ -goog.dom.MultiRange.createFromBrowserRanges = function(browserRanges) { - var range = new goog.dom.MultiRange(); - range.browserRanges_ = goog.array.clone(browserRanges); - return range; -}; - - -/** - * Creates a new range wrapper from the given goog.dom.TextRange objects. Do - * not use this method directly - please use goog.dom.Range.createFrom* instead. - * @param {Array} textRanges The text range objects. - * @return {!goog.dom.MultiRange} A range wrapper object. - */ -goog.dom.MultiRange.createFromTextRanges = function(textRanges) { - var range = new goog.dom.MultiRange(); - range.ranges_ = textRanges; - range.browserRanges_ = goog.array.map(textRanges, function(range) { - return range.getBrowserRangeObject(); - }); - return range; -}; - - -/** - * Logging object. - * @type {goog.log.Logger} - * @private - */ -goog.dom.MultiRange.prototype.logger_ = - goog.log.getLogger('goog.dom.MultiRange'); - - -// Method implementations - - -/** - * Clears cached values. Should be called whenever this.browserRanges_ is - * modified. - * @private - */ -goog.dom.MultiRange.prototype.clearCachedValues_ = function() { - this.ranges_ = []; - this.sortedRanges_ = null; - this.container_ = null; -}; - - -/** - * @return {!goog.dom.MultiRange} A clone of this range. - * @override - */ -goog.dom.MultiRange.prototype.clone = function() { - return goog.dom.MultiRange.createFromBrowserRanges(this.browserRanges_); -}; - - -/** @override */ -goog.dom.MultiRange.prototype.getType = function() { - return goog.dom.RangeType.MULTI; -}; - - -/** @override */ -goog.dom.MultiRange.prototype.getBrowserRangeObject = function() { - // NOTE(robbyw): This method does not make sense for multi-ranges. - if (this.browserRanges_.length > 1) { - goog.log.warning(this.logger_, - 'getBrowserRangeObject called on MultiRange with more than 1 range'); - } - return this.browserRanges_[0]; -}; - - -/** @override */ -goog.dom.MultiRange.prototype.setBrowserRangeObject = function(nativeRange) { - // TODO(robbyw): Look in to adding setBrowserSelectionObject. - return false; -}; - - -/** @override */ -goog.dom.MultiRange.prototype.getTextRangeCount = function() { - return this.browserRanges_.length; -}; - - -/** @override */ -goog.dom.MultiRange.prototype.getTextRange = function(i) { - if (!this.ranges_[i]) { - this.ranges_[i] = goog.dom.TextRange.createFromBrowserRange( - this.browserRanges_[i]); - } - return this.ranges_[i]; -}; - - -/** @override */ -goog.dom.MultiRange.prototype.getContainer = function() { - if (!this.container_) { - var nodes = []; - for (var i = 0, len = this.getTextRangeCount(); i < len; i++) { - nodes.push(this.getTextRange(i).getContainer()); - } - this.container_ = goog.dom.findCommonAncestor.apply(null, nodes); - } - return this.container_; -}; - - -/** - * @return {!Array} An array of sub-ranges, sorted by start - * point. - */ -goog.dom.MultiRange.prototype.getSortedRanges = function() { - if (!this.sortedRanges_) { - this.sortedRanges_ = this.getTextRanges(); - this.sortedRanges_.sort(function(a, b) { - var aStartNode = a.getStartNode(); - var aStartOffset = a.getStartOffset(); - var bStartNode = b.getStartNode(); - var bStartOffset = b.getStartOffset(); - - if (aStartNode == bStartNode && aStartOffset == bStartOffset) { - return 0; - } - - return goog.dom.Range.isReversed(aStartNode, aStartOffset, bStartNode, - bStartOffset) ? 1 : -1; - }); - } - return this.sortedRanges_; -}; - - -/** @override */ -goog.dom.MultiRange.prototype.getStartNode = function() { - return this.getSortedRanges()[0].getStartNode(); -}; - - -/** @override */ -goog.dom.MultiRange.prototype.getStartOffset = function() { - return this.getSortedRanges()[0].getStartOffset(); -}; - - -/** @override */ -goog.dom.MultiRange.prototype.getEndNode = function() { - // NOTE(robbyw): This may return the wrong node if any subranges overlap. - return goog.array.peek(this.getSortedRanges()).getEndNode(); -}; - - -/** @override */ -goog.dom.MultiRange.prototype.getEndOffset = function() { - // NOTE(robbyw): This may return the wrong value if any subranges overlap. - return goog.array.peek(this.getSortedRanges()).getEndOffset(); -}; - - -/** @override */ -goog.dom.MultiRange.prototype.isRangeInDocument = function() { - return goog.array.every(this.getTextRanges(), function(range) { - return range.isRangeInDocument(); - }); -}; - - -/** @override */ -goog.dom.MultiRange.prototype.isCollapsed = function() { - return this.browserRanges_.length == 0 || - this.browserRanges_.length == 1 && this.getTextRange(0).isCollapsed(); -}; - - -/** @override */ -goog.dom.MultiRange.prototype.getText = function() { - return goog.array.map(this.getTextRanges(), function(range) { - return range.getText(); - }).join(''); -}; - - -/** @override */ -goog.dom.MultiRange.prototype.getHtmlFragment = function() { - return this.getValidHtml(); -}; - - -/** @override */ -goog.dom.MultiRange.prototype.getValidHtml = function() { - // NOTE(robbyw): This does not behave well if the sub-ranges overlap. - return goog.array.map(this.getTextRanges(), function(range) { - return range.getValidHtml(); - }).join(''); -}; - - -/** @override */ -goog.dom.MultiRange.prototype.getPastableHtml = function() { - // TODO(robbyw): This should probably do something smart like group TR and TD - // selections in to the same table. - return this.getValidHtml(); -}; - - -/** @override */ -goog.dom.MultiRange.prototype.__iterator__ = function(opt_keys) { - return new goog.dom.MultiRangeIterator(this); -}; - - -// RANGE ACTIONS - - -/** @override */ -goog.dom.MultiRange.prototype.select = function() { - var selection = goog.dom.AbstractRange.getBrowserSelectionForWindow( - this.getWindow()); - selection.removeAllRanges(); - for (var i = 0, len = this.getTextRangeCount(); i < len; i++) { - selection.addRange(this.getTextRange(i).getBrowserRangeObject()); - } -}; - - -/** @override */ -goog.dom.MultiRange.prototype.removeContents = function() { - goog.array.forEach(this.getTextRanges(), function(range) { - range.removeContents(); - }); -}; - - -// SAVE/RESTORE - - -/** @override */ -goog.dom.MultiRange.prototype.saveUsingDom = function() { - return new goog.dom.DomSavedMultiRange_(this); -}; - - -// RANGE MODIFICATION - - -/** - * Collapses this range to a single point, either the first or last point - * depending on the parameter. This will result in the number of ranges in this - * multi range becoming 1. - * @param {boolean} toAnchor Whether to collapse to the anchor. - * @override - */ -goog.dom.MultiRange.prototype.collapse = function(toAnchor) { - if (!this.isCollapsed()) { - var range = toAnchor ? this.getTextRange(0) : this.getTextRange( - this.getTextRangeCount() - 1); - - this.clearCachedValues_(); - range.collapse(toAnchor); - this.ranges_ = [range]; - this.sortedRanges_ = [range]; - this.browserRanges_ = [range.getBrowserRangeObject()]; - } -}; - - -// SAVED RANGE OBJECTS - - - -/** - * A SavedRange implementation using DOM endpoints. - * @param {goog.dom.MultiRange} range The range to save. - * @constructor - * @extends {goog.dom.SavedRange} - * @private - */ -goog.dom.DomSavedMultiRange_ = function(range) { - /** - * Array of saved ranges. - * @type {Array} - * @private - */ - this.savedRanges_ = goog.array.map(range.getTextRanges(), function(range) { - return range.saveUsingDom(); - }); -}; -goog.inherits(goog.dom.DomSavedMultiRange_, goog.dom.SavedRange); - - -/** - * @return {!goog.dom.MultiRange} The restored range. - * @override - */ -goog.dom.DomSavedMultiRange_.prototype.restoreInternal = function() { - var ranges = goog.array.map(this.savedRanges_, function(savedRange) { - return savedRange.restore(); - }); - return goog.dom.MultiRange.createFromTextRanges(ranges); -}; - - -/** @override */ -goog.dom.DomSavedMultiRange_.prototype.disposeInternal = function() { - goog.dom.DomSavedMultiRange_.superClass_.disposeInternal.call(this); - - goog.array.forEach(this.savedRanges_, function(savedRange) { - savedRange.dispose(); - }); - delete this.savedRanges_; -}; - - -// RANGE ITERATION - - - -/** - * Subclass of goog.dom.TagIterator that iterates over a DOM range. It - * adds functions to determine the portion of each text node that is selected. - * - * @param {goog.dom.MultiRange} range The range to traverse. - * @constructor - * @extends {goog.dom.RangeIterator} - * @final - */ -goog.dom.MultiRangeIterator = function(range) { - if (range) { - this.iterators_ = goog.array.map( - range.getSortedRanges(), - function(r) { - return goog.iter.toIterator(r); - }); - } - - goog.dom.RangeIterator.call( - this, range ? this.getStartNode() : null, false); -}; -goog.inherits(goog.dom.MultiRangeIterator, goog.dom.RangeIterator); - - -/** - * The list of range iterators left to traverse. - * @type {Array?} - * @private - */ -goog.dom.MultiRangeIterator.prototype.iterators_ = null; - - -/** - * The index of the current sub-iterator being traversed. - * @type {number} - * @private - */ -goog.dom.MultiRangeIterator.prototype.currentIdx_ = 0; - - -/** @override */ -goog.dom.MultiRangeIterator.prototype.getStartTextOffset = function() { - return this.iterators_[this.currentIdx_].getStartTextOffset(); -}; - - -/** @override */ -goog.dom.MultiRangeIterator.prototype.getEndTextOffset = function() { - return this.iterators_[this.currentIdx_].getEndTextOffset(); -}; - - -/** @override */ -goog.dom.MultiRangeIterator.prototype.getStartNode = function() { - return this.iterators_[0].getStartNode(); -}; - - -/** @override */ -goog.dom.MultiRangeIterator.prototype.getEndNode = function() { - return goog.array.peek(this.iterators_).getEndNode(); -}; - - -/** @override */ -goog.dom.MultiRangeIterator.prototype.isLast = function() { - return this.iterators_[this.currentIdx_].isLast(); -}; - - -/** @override */ -goog.dom.MultiRangeIterator.prototype.next = function() { - /** @preserveTry */ - try { - var it = this.iterators_[this.currentIdx_]; - var next = it.next(); - this.setPosition(it.node, it.tagType, it.depth); - return next; - } catch (ex) { - if (ex !== goog.iter.StopIteration || - this.iterators_.length - 1 == this.currentIdx_) { - throw ex; - } else { - // In case we got a StopIteration, increment counter and try again. - this.currentIdx_++; - return this.next(); - } - } -}; - - -/** @override */ -goog.dom.MultiRangeIterator.prototype.copyFrom = function(other) { - this.iterators_ = goog.array.clone(other.iterators_); - goog.dom.MultiRangeIterator.superClass_.copyFrom.call(this, other); -}; - - -/** - * @return {!goog.dom.MultiRangeIterator} An identical iterator. - * @override - */ -goog.dom.MultiRangeIterator.prototype.clone = function() { - var copy = new goog.dom.MultiRangeIterator(null); - copy.copyFrom(this); - return copy; -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/multirange_test.html b/src/database/third_party/closure-library/closure/goog/dom/multirange_test.html deleted file mode 100644 index 191c9a903c1..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/multirange_test.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - -Closure Unit Tests - goog.dom.MultiRange - - - - -
    -
    abc
    -
    defghi
    -
    - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/multirange_test.js b/src/database/third_party/closure-library/closure/goog/dom/multirange_test.js deleted file mode 100644 index f9aeb757436..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/multirange_test.js +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.dom.MultiRangeTest'); -goog.setTestOnly('goog.dom.MultiRangeTest'); - -goog.require('goog.dom'); -goog.require('goog.dom.MultiRange'); -goog.require('goog.dom.Range'); -goog.require('goog.iter'); -goog.require('goog.testing.jsunit'); - -var range; -function setUp() { - range = new goog.dom.MultiRange.createFromTextRanges([ - goog.dom.Range.createFromNodeContents(goog.dom.getElement('test2')), - goog.dom.Range.createFromNodeContents(goog.dom.getElement('test1')) - ]); -} - -function testStartAndEnd() { - assertEquals(goog.dom.getElement('test1').firstChild, range.getStartNode()); - assertEquals(0, range.getStartOffset()); - assertEquals(goog.dom.getElement('test2').firstChild, range.getEndNode()); - assertEquals(6, range.getEndOffset()); -} - -function testStartAndEndIterator() { - var it = goog.iter.toIterator(range); - assertEquals(goog.dom.getElement('test1').firstChild, it.getStartNode()); - assertEquals(0, it.getStartTextOffset()); - assertEquals(goog.dom.getElement('test2').firstChild, it.getEndNode()); - assertEquals(3, it.getEndTextOffset()); - - it.next(); - it.next(); - assertEquals(6, it.getEndTextOffset()); -} - -function testIteration() { - var tags = goog.iter.toArray(range); - assertEquals(2, tags.length); - - assertEquals(goog.dom.getElement('test1').firstChild, tags[0]); - assertEquals(goog.dom.getElement('test2').firstChild, tags[1]); -} diff --git a/src/database/third_party/closure-library/closure/goog/dom/nodeiterator.js b/src/database/third_party/closure-library/closure/goog/dom/nodeiterator.js deleted file mode 100644 index bca563c3e33..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/nodeiterator.js +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Iterator subclass for DOM tree traversal. - * - * @author robbyw@google.com (Robby Walker) - */ - -goog.provide('goog.dom.NodeIterator'); - -goog.require('goog.dom.TagIterator'); - - - -/** - * A DOM tree traversal iterator. - * - * Starting with the given node, the iterator walks the DOM in order, reporting - * events for each node. The iterator acts as a prefix iterator: - * - *
    - * <div>1<span>2</span>3</div>
    - * 
    - * - * Will return the following nodes: - * - * [div, 1, span, 2, 3] - * - * With the following depths - * - * [1, 1, 2, 2, 1] - * - * Imagining | represents iterator position, the traversal stops at - * each of the following locations: - * - *
    <div>|1|<span>|2|</span>3|</div>
    - * - * The iterator can also be used in reverse mode, which will return the nodes - * and states in the opposite order. The depths will be slightly different - * since, like in normal mode, the depth is computed *after* the last move. - * - * Lastly, it is possible to create an iterator that is unconstrained, meaning - * that it will continue iterating until the end of the document instead of - * until exiting the start node. - * - * @param {Node=} opt_node The start node. Defaults to an empty iterator. - * @param {boolean=} opt_reversed Whether to traverse the tree in reverse. - * @param {boolean=} opt_unconstrained Whether the iterator is not constrained - * to the starting node and its children. - * @param {number=} opt_depth The starting tree depth. - * @constructor - * @extends {goog.dom.TagIterator} - * @final - */ -goog.dom.NodeIterator = function(opt_node, opt_reversed, - opt_unconstrained, opt_depth) { - goog.dom.TagIterator.call(this, opt_node, opt_reversed, opt_unconstrained, - null, opt_depth); -}; -goog.inherits(goog.dom.NodeIterator, goog.dom.TagIterator); - - -/** - * Moves to the next position in the DOM tree. - * @return {Node} Returns the next node, or throws a goog.iter.StopIteration - * exception if the end of the iterator's range has been reached. - * @override - */ -goog.dom.NodeIterator.prototype.next = function() { - do { - goog.dom.NodeIterator.superClass_.next.call(this); - } while (this.isEndTag()); - - return this.node; -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/nodeiterator_test.html b/src/database/third_party/closure-library/closure/goog/dom/nodeiterator_test.html deleted file mode 100644 index 23c6bc2657c..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/nodeiterator_test.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - -goog.dom.NodeIterator Tests - - - - - - -
    Text

    Text

    -
    • Not
    • Closed
    - - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/nodeiterator_test.js b/src/database/third_party/closure-library/closure/goog/dom/nodeiterator_test.js deleted file mode 100644 index bed98a3fd18..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/nodeiterator_test.js +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.dom.NodeIteratorTest'); -goog.setTestOnly('goog.dom.NodeIteratorTest'); - -goog.require('goog.dom'); -goog.require('goog.dom.NodeIterator'); -goog.require('goog.testing.dom'); -goog.require('goog.testing.jsunit'); - -function testBasic() { - goog.testing.dom.assertNodesMatch( - new goog.dom.NodeIterator(goog.dom.getElement('test')), - ['#test', '#a1', 'T', '#b1', 'e', 'xt', '#span1', '#p1', 'Text']); -} - -function testUnclosed() { - goog.testing.dom.assertNodesMatch( - new goog.dom.NodeIterator(goog.dom.getElement('test2')), - ['#test2', '#li1', 'Not', '#li2', 'Closed']); -} - -function testReverse() { - goog.testing.dom.assertNodesMatch( - new goog.dom.NodeIterator(goog.dom.getElement('test'), true), - ['Text', '#p1', '#span1', 'xt', 'e', '#b1', 'T', '#a1', '#test']); -} diff --git a/src/database/third_party/closure-library/closure/goog/dom/nodeoffset.js b/src/database/third_party/closure-library/closure/goog/dom/nodeoffset.js deleted file mode 100644 index 9a65dbea839..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/nodeoffset.js +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2005 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Object to store the offset from one node to another in a way - * that works on any similar DOM structure regardless of whether it is the same - * actual nodes. - * - * @author robbyw@google.com (Robby Walker) - */ - -goog.provide('goog.dom.NodeOffset'); - -goog.require('goog.Disposable'); -goog.require('goog.dom.TagName'); - - - -/** - * Object to store the offset from one node to another in a way that works on - * any similar DOM structure regardless of whether it is the same actual nodes. - * @param {Node} node The node to get the offset for. - * @param {Node} baseNode The node to calculate the offset from. - * @extends {goog.Disposable} - * @constructor - * @final - */ -goog.dom.NodeOffset = function(node, baseNode) { - goog.Disposable.call(this); - - /** - * A stack of childNode offsets. - * @type {Array} - * @private - */ - this.offsetStack_ = []; - - /** - * A stack of childNode names. - * @type {Array} - * @private - */ - this.nameStack_ = []; - - while (node && node.nodeName != goog.dom.TagName.BODY && node != baseNode) { - // Compute the sibling offset. - var siblingOffset = 0; - var sib = node.previousSibling; - while (sib) { - sib = sib.previousSibling; - ++siblingOffset; - } - this.offsetStack_.unshift(siblingOffset); - this.nameStack_.unshift(node.nodeName); - - node = node.parentNode; - } -}; -goog.inherits(goog.dom.NodeOffset, goog.Disposable); - - -/** - * @return {string} A string representation of this object. - * @override - */ -goog.dom.NodeOffset.prototype.toString = function() { - var strs = []; - var name; - for (var i = 0; name = this.nameStack_[i]; i++) { - strs.push(this.offsetStack_[i] + ',' + name); - } - return strs.join('\n'); -}; - - -/** - * Walk the dom and find the node relative to baseNode. Returns null on - * failure. - * @param {Node} baseNode The node to start walking from. Should be equivalent - * to the node passed in to the constructor, in that it should have the - * same contents. - * @return {Node} The node relative to baseNode, or null on failure. - */ -goog.dom.NodeOffset.prototype.findTargetNode = function(baseNode) { - var name; - var curNode = baseNode; - for (var i = 0; name = this.nameStack_[i]; ++i) { - curNode = curNode.childNodes[this.offsetStack_[i]]; - - // Sanity check and make sure the element names match. - if (!curNode || curNode.nodeName != name) { - return null; - } - } - return curNode; -}; - - -/** @override */ -goog.dom.NodeOffset.prototype.disposeInternal = function() { - delete this.offsetStack_; - delete this.nameStack_; -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/nodeoffset_test.html b/src/database/third_party/closure-library/closure/goog/dom/nodeoffset_test.html deleted file mode 100644 index 8d854965194..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/nodeoffset_test.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - -goog.dom.NodeOffset Tests - - - - - -
    Text
    and more text.
    -
    -
    - - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/nodeoffset_test.js b/src/database/third_party/closure-library/closure/goog/dom/nodeoffset_test.js deleted file mode 100644 index 0f1de76e4b0..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/nodeoffset_test.js +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.dom.NodeOffsetTest'); -goog.setTestOnly('goog.dom.NodeOffsetTest'); - -goog.require('goog.dom'); -goog.require('goog.dom.NodeOffset'); -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.TagName'); -goog.require('goog.testing.jsunit'); - -var test1; -var test2; -var i; -var empty; - -function setUpPage() { - test1 = goog.dom.getElement('test1'); - i = goog.dom.getElement('i'); - test2 = goog.dom.getElement('test2'); - test2.innerHTML = test1.innerHTML; - empty = goog.dom.getElement('empty'); -} - -function testElementOffset() { - var nodeOffset = new goog.dom.NodeOffset(i, test1); - - var recovered = nodeOffset.findTargetNode(test2); - assertNotNull('Should recover a node.', recovered); - assertEquals('Should recover an I node.', goog.dom.TagName.I, - recovered.tagName); - assertTrue('Should recover a child of test2', - goog.dom.contains(test2, recovered)); - assertFalse('Should not recover a child of test1', - goog.dom.contains(test1, recovered)); - - nodeOffset.dispose(); -} - -function testNodeOffset() { - var nodeOffset = new goog.dom.NodeOffset(i.firstChild, test1); - - var recovered = nodeOffset.findTargetNode(test2); - assertNotNull('Should recover a node.', recovered); - assertEquals('Should recover a text node.', goog.dom.NodeType.TEXT, - recovered.nodeType); - assertEquals('Should have correct contents.', 'text.', - recovered.nodeValue); - assertTrue('Should recover a child of test2', - goog.dom.contains(test2, recovered)); - assertFalse('Should not recover a child of test1', - goog.dom.contains(test1, recovered)); - - nodeOffset.dispose(); -} - -function testToString() { - var nodeOffset = new goog.dom.NodeOffset(i.firstChild, test1); - - assertEquals('Should have correct string representation', - '3,B\n1,I\n0,#text', nodeOffset.toString()); - - nodeOffset.dispose(); -} - -function testBadRecovery() { - var nodeOffset = new goog.dom.NodeOffset(i.firstChild, test1); - - var recovered = nodeOffset.findTargetNode(empty); - assertNull('Should recover nothing.', recovered); - - nodeOffset.dispose(); -} diff --git a/src/database/third_party/closure-library/closure/goog/dom/nodetype.js b/src/database/third_party/closure-library/closure/goog/dom/nodetype.js deleted file mode 100644 index cccb4706eca..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/nodetype.js +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Definition of goog.dom.NodeType. - */ - -goog.provide('goog.dom.NodeType'); - - -/** - * Constants for the nodeType attribute in the Node interface. - * - * These constants match those specified in the Node interface. These are - * usually present on the Node object in recent browsers, but not in older - * browsers (specifically, early IEs) and thus are given here. - * - * In some browsers (early IEs), these are not defined on the Node object, - * so they are provided here. - * - * See http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-1950641247 - * @enum {number} - */ -goog.dom.NodeType = { - ELEMENT: 1, - ATTRIBUTE: 2, - TEXT: 3, - CDATA_SECTION: 4, - ENTITY_REFERENCE: 5, - ENTITY: 6, - PROCESSING_INSTRUCTION: 7, - COMMENT: 8, - DOCUMENT: 9, - DOCUMENT_TYPE: 10, - DOCUMENT_FRAGMENT: 11, - NOTATION: 12 -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/pattern/abstractpattern.js b/src/database/third_party/closure-library/closure/goog/dom/pattern/abstractpattern.js deleted file mode 100644 index 6015b09c5ee..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/pattern/abstractpattern.js +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview DOM pattern base class. - * - * @author robbyw@google.com (Robby Walker) - */ - -goog.provide('goog.dom.pattern.AbstractPattern'); - -goog.require('goog.dom.pattern.MatchType'); - - - -/** - * Base pattern class for DOM matching. - * - * @constructor - */ -goog.dom.pattern.AbstractPattern = function() { -}; - - -/** - * The first node matched by this pattern. - * @type {Node} - */ -goog.dom.pattern.AbstractPattern.prototype.matchedNode = null; - - -/** - * Reset any internal state this pattern keeps. - */ -goog.dom.pattern.AbstractPattern.prototype.reset = function() { - // The base implementation does nothing. -}; - - -/** - * Test whether this pattern matches the given token. - * - * @param {Node} token Token to match against. - * @param {goog.dom.TagWalkType} type The type of token. - * @return {goog.dom.pattern.MatchType} {@code MATCH} if the pattern matches. - */ -goog.dom.pattern.AbstractPattern.prototype.matchToken = function(token, type) { - return goog.dom.pattern.MatchType.NO_MATCH; -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/pattern/allchildren.js b/src/database/third_party/closure-library/closure/goog/dom/pattern/allchildren.js deleted file mode 100644 index 86f8cdf9e35..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/pattern/allchildren.js +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview DOM pattern to match any children of a tag. - * - * @author robbyw@google.com (Robby Walker) - */ - -goog.provide('goog.dom.pattern.AllChildren'); - -goog.require('goog.dom.pattern.AbstractPattern'); -goog.require('goog.dom.pattern.MatchType'); - - - -/** - * Pattern object that matches any nodes at or below the current tree depth. - * - * @constructor - * @extends {goog.dom.pattern.AbstractPattern} - */ -goog.dom.pattern.AllChildren = function() { -}; -goog.inherits(goog.dom.pattern.AllChildren, goog.dom.pattern.AbstractPattern); - - -/** - * Tracks the matcher's depth to detect the end of the tag. - * - * @type {number} - * @private - */ -goog.dom.pattern.AllChildren.prototype.depth_ = 0; - - -/** - * Test whether the given token is on the same level. - * - * @param {Node} token Token to match against. - * @param {goog.dom.TagWalkType} type The type of token. - * @return {goog.dom.pattern.MatchType} {@code MATCHING} if the token is on the - * same level or deeper and {@code BACKTRACK_MATCH} if not. - * @override - */ -goog.dom.pattern.AllChildren.prototype.matchToken = function(token, type) { - this.depth_ += type; - - if (this.depth_ >= 0) { - return goog.dom.pattern.MatchType.MATCHING; - } else { - this.depth_ = 0; - return goog.dom.pattern.MatchType.BACKTRACK_MATCH; - } -}; - - -/** - * Reset any internal state this pattern keeps. - * @override - */ -goog.dom.pattern.AllChildren.prototype.reset = function() { - this.depth_ = 0; -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/pattern/callback/callback.js b/src/database/third_party/closure-library/closure/goog/dom/pattern/callback/callback.js deleted file mode 100644 index 7d7aa60c337..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/pattern/callback/callback.js +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Useful callback functions for the DOM matcher. - * - * @author robbyw@google.com (Robby Walker) - */ - -goog.provide('goog.dom.pattern.callback'); - -goog.require('goog.dom'); -goog.require('goog.dom.TagWalkType'); -goog.require('goog.iter'); - - -/** - * Callback function for use in {@link goog.dom.pattern.Matcher.addPattern} - * that removes the matched node from the tree. Should be used in conjunciton - * with a {@link goog.dom.pattern.StartTag} pattern. - * - * @param {Node} node The node matched by the pattern. - * @param {goog.dom.TagIterator} position The position where the match - * finished. - * @return {boolean} Returns true to indicate tree changes were made. - */ -goog.dom.pattern.callback.removeNode = function(node, position) { - // Find out which position would be next. - position.setPosition(node, goog.dom.TagWalkType.END_TAG); - - goog.iter.nextOrValue(position, null); - - // Remove the node. - goog.dom.removeNode(node); - - // Correct for the depth change. - position.depth -= 1; - - // Indicate that we made position/tree changes. - return true; -}; - - -/** - * Callback function for use in {@link goog.dom.pattern.Matcher.addPattern} - * that removes the matched node from the tree and replaces it with its - * children. Should be used in conjunction with a - * {@link goog.dom.pattern.StartTag} pattern. - * - * @param {Element} node The node matched by the pattern. - * @param {goog.dom.TagIterator} position The position where the match - * finished. - * @return {boolean} Returns true to indicate tree changes were made. - */ -goog.dom.pattern.callback.flattenElement = function(node, position) { - // Find out which position would be next. - position.setPosition(node, node.firstChild ? - goog.dom.TagWalkType.START_TAG : - goog.dom.TagWalkType.END_TAG); - - goog.iter.nextOrValue(position, null); - - // Flatten the node. - goog.dom.flattenElement(node); - - // Correct for the depth change. - position.depth -= 1; - - // Indicate that we made position/tree changes. - return true; -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/pattern/callback/counter.js b/src/database/third_party/closure-library/closure/goog/dom/pattern/callback/counter.js deleted file mode 100644 index 003c71a0add..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/pattern/callback/counter.js +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Callback object that counts matches. - * - * @author robbyw@google.com (Robby Walker) - */ - -goog.provide('goog.dom.pattern.callback.Counter'); - - - -/** - * Callback class for counting matches. - * @constructor - * @final - */ -goog.dom.pattern.callback.Counter = function() { -}; - - -/** - * The count of objects matched so far. - * - * @type {number} - */ -goog.dom.pattern.callback.Counter.prototype.count = 0; - - -/** - * The callback function. Suitable as a callback for - * {@link goog.dom.pattern.Matcher}. - * @type {Function} - * @private - */ -goog.dom.pattern.callback.Counter.prototype.callback_ = null; - - -/** - * Get a bound callback function that is suitable as a callback for - * {@link goog.dom.pattern.Matcher}. - * - * @return {!Function} A callback function. - */ -goog.dom.pattern.callback.Counter.prototype.getCallback = function() { - if (!this.callback_) { - this.callback_ = goog.bind(function() { - this.count++; - return false; - }, this); - } - return this.callback_; -}; - - -/** - * Reset the counter. - */ -goog.dom.pattern.callback.Counter.prototype.reset = function() { - this.count = 0; -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/pattern/callback/test.js b/src/database/third_party/closure-library/closure/goog/dom/pattern/callback/test.js deleted file mode 100644 index 1bfc923bcb5..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/pattern/callback/test.js +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Callback object that tests if a pattern matches at least once. - * - * @author robbyw@google.com (Robby Walker) - */ - -goog.provide('goog.dom.pattern.callback.Test'); - -goog.require('goog.iter.StopIteration'); - - - -/** - * Callback class for testing for at least one match. - * @constructor - * @final - */ -goog.dom.pattern.callback.Test = function() { -}; - - -/** - * Whether or not the pattern matched. - * - * @type {boolean} - */ -goog.dom.pattern.callback.Test.prototype.matched = false; - - -/** - * The callback function. Suitable as a callback for - * {@link goog.dom.pattern.Matcher}. - * @type {Function} - * @private - */ -goog.dom.pattern.callback.Test.prototype.callback_ = null; - - -/** - * Get a bound callback function that is suitable as a callback for - * {@link goog.dom.pattern.Matcher}. - * - * @return {!Function} A callback function. - */ -goog.dom.pattern.callback.Test.prototype.getCallback = function() { - if (!this.callback_) { - this.callback_ = goog.bind(function(node, position) { - // Mark our match. - this.matched = true; - - // Stop searching. - throw goog.iter.StopIteration; - }, this); - } - return this.callback_; -}; - - -/** - * Reset the counter. - */ -goog.dom.pattern.callback.Test.prototype.reset = function() { - this.matched = false; -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/pattern/childmatches.js b/src/database/third_party/closure-library/closure/goog/dom/pattern/childmatches.js deleted file mode 100644 index a2d8dc44d18..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/pattern/childmatches.js +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview DOM pattern to match any children of a tag, and - * specifically collect those that match a child pattern. - * - * @author robbyw@google.com (Robby Walker) - */ - -goog.provide('goog.dom.pattern.ChildMatches'); - -goog.require('goog.dom.pattern.AllChildren'); -goog.require('goog.dom.pattern.MatchType'); - - - -/** - * Pattern object that matches any nodes at or below the current tree depth. - * - * @param {goog.dom.pattern.AbstractPattern} childPattern Pattern to collect - * child matches of. - * @param {number=} opt_minimumMatches Enforce a minimum nuber of matches. - * Defaults to 0. - * @constructor - * @extends {goog.dom.pattern.AllChildren} - * @final - */ -goog.dom.pattern.ChildMatches = function(childPattern, opt_minimumMatches) { - this.childPattern_ = childPattern; - this.matches = []; - this.minimumMatches_ = opt_minimumMatches || 0; - goog.dom.pattern.AllChildren.call(this); -}; -goog.inherits(goog.dom.pattern.ChildMatches, goog.dom.pattern.AllChildren); - - -/** - * Array of matched child nodes. - * - * @type {Array} - */ -goog.dom.pattern.ChildMatches.prototype.matches; - - -/** - * Minimum number of matches. - * - * @type {number} - * @private - */ -goog.dom.pattern.ChildMatches.prototype.minimumMatches_ = 0; - - -/** - * The child pattern to collect matches from. - * - * @type {goog.dom.pattern.AbstractPattern} - * @private - */ -goog.dom.pattern.ChildMatches.prototype.childPattern_; - - -/** - * Whether the pattern has recently matched or failed to match and will need to - * be reset when starting a new round of matches. - * - * @type {boolean} - * @private - */ -goog.dom.pattern.ChildMatches.prototype.needsReset_ = false; - - -/** - * Test whether the given token is on the same level. - * - * @param {Node} token Token to match against. - * @param {goog.dom.TagWalkType} type The type of token. - * @return {goog.dom.pattern.MatchType} {@code MATCHING} if the token is on the - * same level or deeper and {@code BACKTRACK_MATCH} if not. - * @override - */ -goog.dom.pattern.ChildMatches.prototype.matchToken = function(token, type) { - // Defer resets so we maintain our matches array until the last possible time. - if (this.needsReset_) { - this.reset(); - } - - // Call the super-method to ensure we stay in the child tree. - var status = - goog.dom.pattern.AllChildren.prototype.matchToken.apply(this, arguments); - - switch (status) { - case goog.dom.pattern.MatchType.MATCHING: - var backtrack = false; - - switch (this.childPattern_.matchToken(token, type)) { - case goog.dom.pattern.MatchType.BACKTRACK_MATCH: - backtrack = true; - case goog.dom.pattern.MatchType.MATCH: - // Collect the match. - this.matches.push(this.childPattern_.matchedNode); - break; - - default: - // Keep trying if we haven't hit a terminal state. - break; - } - - if (backtrack) { - // The only interesting result is a MATCH, since BACKTRACK_MATCH means - // we are hitting an infinite loop on something like a Repeat(0). - if (this.childPattern_.matchToken(token, type) == - goog.dom.pattern.MatchType.MATCH) { - this.matches.push(this.childPattern_.matchedNode); - } - } - return goog.dom.pattern.MatchType.MATCHING; - - case goog.dom.pattern.MatchType.BACKTRACK_MATCH: - // TODO(robbyw): this should return something like BACKTRACK_NO_MATCH - // when we don't meet our minimum. - this.needsReset_ = true; - return (this.matches.length >= this.minimumMatches_) ? - goog.dom.pattern.MatchType.BACKTRACK_MATCH : - goog.dom.pattern.MatchType.NO_MATCH; - - default: - this.needsReset_ = true; - return status; - } -}; - - -/** - * Reset any internal state this pattern keeps. - * @override - */ -goog.dom.pattern.ChildMatches.prototype.reset = function() { - this.needsReset_ = false; - this.matches.length = 0; - this.childPattern_.reset(); - goog.dom.pattern.AllChildren.prototype.reset.call(this); -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/pattern/endtag.js b/src/database/third_party/closure-library/closure/goog/dom/pattern/endtag.js deleted file mode 100644 index 409f952dec2..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/pattern/endtag.js +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview DOM pattern to match the end of a tag. - * - * @author robbyw@google.com (Robby Walker) - */ - -goog.provide('goog.dom.pattern.EndTag'); - -goog.require('goog.dom.TagWalkType'); -goog.require('goog.dom.pattern.Tag'); - - - -/** - * Pattern object that matches a closing tag. - * - * @param {string|RegExp} tag Name of the tag. Also will accept a regular - * expression to match against the tag name. - * @param {Object=} opt_attrs Optional map of attribute names to desired values. - * This pattern will only match when all attributes are present and match - * the string or regular expression value provided here. - * @param {Object=} opt_styles Optional map of CSS style names to desired - * values. This pattern will only match when all styles are present and - * match the string or regular expression value provided here. - * @param {Function=} opt_test Optional function that takes the element as a - * parameter and returns true if this pattern should match it. - * @constructor - * @extends {goog.dom.pattern.Tag} - * @final - */ -goog.dom.pattern.EndTag = function(tag, opt_attrs, opt_styles, opt_test) { - goog.dom.pattern.Tag.call( - this, - tag, - goog.dom.TagWalkType.END_TAG, - opt_attrs, - opt_styles, - opt_test); -}; -goog.inherits(goog.dom.pattern.EndTag, goog.dom.pattern.Tag); diff --git a/src/database/third_party/closure-library/closure/goog/dom/pattern/fulltag.js b/src/database/third_party/closure-library/closure/goog/dom/pattern/fulltag.js deleted file mode 100644 index 16264e9ae90..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/pattern/fulltag.js +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview DOM pattern to match a tag and all of its children. - * - * @author robbyw@google.com (Robby Walker) - */ - -goog.provide('goog.dom.pattern.FullTag'); - -goog.require('goog.dom.pattern.MatchType'); -goog.require('goog.dom.pattern.StartTag'); -goog.require('goog.dom.pattern.Tag'); - - - -/** - * Pattern object that matches a full tag including all its children. - * - * @param {string|RegExp} tag Name of the tag. Also will accept a regular - * expression to match against the tag name. - * @param {Object=} opt_attrs Optional map of attribute names to desired values. - * This pattern will only match when all attributes are present and match - * the string or regular expression value provided here. - * @param {Object=} opt_styles Optional map of CSS style names to desired - * values. This pattern will only match when all styles are present and - * match the string or regular expression value provided here. - * @param {Function=} opt_test Optional function that takes the element as a - * parameter and returns true if this pattern should match it. - * @constructor - * @extends {goog.dom.pattern.StartTag} - * @final - */ -goog.dom.pattern.FullTag = function(tag, opt_attrs, opt_styles, opt_test) { - goog.dom.pattern.StartTag.call( - this, - tag, - opt_attrs, - opt_styles, - opt_test); -}; -goog.inherits(goog.dom.pattern.FullTag, goog.dom.pattern.StartTag); - - -/** - * Tracks the matcher's depth to detect the end of the tag. - * - * @type {number} - * @private - */ -goog.dom.pattern.FullTag.prototype.depth_ = 0; - - -/** - * Test whether the given token is a start tag token which matches the tag name, - * style, and attributes provided in the constructor. - * - * @param {Node} token Token to match against. - * @param {goog.dom.TagWalkType} type The type of token. - * @return {goog.dom.pattern.MatchType} MATCH at the end of our - * tag, MATCHING if we are within the tag, and - * NO_MATCH if the starting tag does not match. - * @override - */ -goog.dom.pattern.FullTag.prototype.matchToken = function(token, type) { - if (!this.depth_) { - // If we have not yet started, make sure we match as a StartTag. - if (goog.dom.pattern.Tag.prototype.matchToken.call(this, token, type)) { - this.depth_ = type; - return goog.dom.pattern.MatchType.MATCHING; - - } else { - return goog.dom.pattern.MatchType.NO_MATCH; - } - } else { - this.depth_ += type; - - return this.depth_ ? - goog.dom.pattern.MatchType.MATCHING : - goog.dom.pattern.MatchType.MATCH; - } -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/pattern/matcher.js b/src/database/third_party/closure-library/closure/goog/dom/pattern/matcher.js deleted file mode 100644 index fb3cc7d23e9..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/pattern/matcher.js +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview DOM pattern matcher. Allows for simple searching of DOM - * using patterns descended from {@link goog.dom.pattern.AbstractPattern}. - * - * @author robbyw@google.com (Robby Walker) - */ - -goog.provide('goog.dom.pattern.Matcher'); - -goog.require('goog.dom.TagIterator'); -goog.require('goog.dom.pattern.MatchType'); -goog.require('goog.iter'); - - -// TODO(robbyw): Allow for backtracks of size > 1. - - - -/** - * Given a set of patterns and a root node, this class tests the patterns in - * parallel. - * - * It is not (yet) a smart matcher - it doesn't do any advanced backtracking. - * Given the pattern DIV, SPAN the matcher will not match - * DIV, DIV, SPAN because it starts matching at the first - * DIV, fails to match SPAN at the second, and never - * backtracks to try again. - * - * It is also possible to have a set of complex patterns that when matched in - * parallel will miss some possible matches. Running multiple times will catch - * all matches eventually. - * - * @constructor - * @final - */ -goog.dom.pattern.Matcher = function() { - this.patterns_ = []; - this.callbacks_ = []; -}; - - -/** - * Array of patterns to attempt to match in parallel. - * - * @type {Array} - * @private - */ -goog.dom.pattern.Matcher.prototype.patterns_; - - -/** - * Array of callbacks to call when a pattern is matched. The indexing is the - * same as the {@link #patterns_} array. - * - * @type {Array} - * @private - */ -goog.dom.pattern.Matcher.prototype.callbacks_; - - -/** - * Adds a pattern to be matched. The callback can return an object whose keys - * are processing instructions. - * - * @param {goog.dom.pattern.AbstractPattern} pattern The pattern to add. - * @param {Function} callback Function to call when a match is found. Uses - * the above semantics. - */ -goog.dom.pattern.Matcher.prototype.addPattern = function(pattern, callback) { - this.patterns_.push(pattern); - this.callbacks_.push(callback); -}; - - -/** - * Resets all the patterns. - * - * @private - */ -goog.dom.pattern.Matcher.prototype.reset_ = function() { - for (var i = 0, len = this.patterns_.length; i < len; i++) { - this.patterns_[i].reset(); - } -}; - - -/** - * Test the given node against all patterns. - * - * @param {goog.dom.TagIterator} position A position in a node walk that is - * located at the token to process. - * @return {boolean} Whether a pattern modified the position or tree - * and its callback resulted in DOM structure or position modification. - * @private - */ -goog.dom.pattern.Matcher.prototype.matchToken_ = function(position) { - for (var i = 0, len = this.patterns_.length; i < len; i++) { - var pattern = this.patterns_[i]; - switch (pattern.matchToken(position.node, position.tagType)) { - case goog.dom.pattern.MatchType.MATCH: - case goog.dom.pattern.MatchType.BACKTRACK_MATCH: - var callback = this.callbacks_[i]; - - // Callbacks are allowed to modify the current position, but must - // return true if the do. - if (callback(pattern.matchedNode, position, pattern)) { - return true; - } - - default: - // Do nothing. - break; - } - } - - return false; -}; - - -/** - * Match the set of patterns against a match tree. - * - * @param {Node} node The root node of the tree to match. - */ -goog.dom.pattern.Matcher.prototype.match = function(node) { - var position = new goog.dom.TagIterator(node); - - this.reset_(); - - goog.iter.forEach(position, function() { - while (this.matchToken_(position)) { - // Since we've moved, our old pattern statuses don't make sense any more. - // Reset them. - this.reset_(); - } - }, this); -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/pattern/matcher_test.html b/src/database/third_party/closure-library/closure/goog/dom/pattern/matcher_test.html deleted file mode 100644 index b5ebdb3ae6a..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/pattern/matcher_test.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - -goog.dom.pattern.Matcher Tests - - - - -

    - -

    -

    - x -

    -

    Text

    -

    Other Text

    - - -
    xyz
    - -

    xyz

    - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/pattern/matcher_test.js b/src/database/third_party/closure-library/closure/goog/dom/pattern/matcher_test.js deleted file mode 100644 index 901f2d28a93..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/pattern/matcher_test.js +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.dom.pattern.matcherTest'); -goog.setTestOnly('goog.dom.pattern.matcherTest'); - -goog.require('goog.dom'); -goog.require('goog.dom.pattern.EndTag'); -goog.require('goog.dom.pattern.FullTag'); -goog.require('goog.dom.pattern.Matcher'); -goog.require('goog.dom.pattern.Repeat'); -goog.require('goog.dom.pattern.Sequence'); -goog.require('goog.dom.pattern.StartTag'); -goog.require('goog.dom.pattern.callback.Counter'); -goog.require('goog.dom.pattern.callback.Test'); -goog.require('goog.iter.StopIteration'); -goog.require('goog.testing.jsunit'); - -function testMatcherAndStartTag() { - var pattern = new goog.dom.pattern.StartTag('P'); - - var counter = new goog.dom.pattern.callback.Counter(); - var matcher = new goog.dom.pattern.Matcher(); - matcher.addPattern(pattern, counter.getCallback()); - matcher.match(document.body); - - assertEquals('StartTag(p) should match 5 times in body', 5, - counter.count); -} - -function testMatcherAndStartTagTwice() { - var pattern = new goog.dom.pattern.StartTag('P'); - - var counter = new goog.dom.pattern.callback.Counter(); - var matcher = new goog.dom.pattern.Matcher(); - matcher.addPattern(pattern, counter.getCallback()); - matcher.match(document.body); - - assertEquals('StartTag(p) should match 5 times in body', 5, - counter.count); - - // Make sure no state got mangled. - counter.reset(); - matcher.match(document.body); - - assertEquals('StartTag(p) should match 5 times in body again', 5, - counter.count); -} - -function testMatcherAndStartTagAttributes() { - var pattern = new goog.dom.pattern.StartTag('SPAN', {id: /./}); - - var counter = new goog.dom.pattern.callback.Counter(); - var matcher = new goog.dom.pattern.Matcher(); - matcher.addPattern(pattern, counter.getCallback()); - matcher.match(document.body); - - assertEquals('StartTag(span,id) should match 2 times in body', 2, - counter.count); -} - -function testMatcherWithTwoPatterns() { - var pattern1 = new goog.dom.pattern.StartTag('SPAN'); - var pattern2 = new goog.dom.pattern.StartTag('P'); - - var counter = new goog.dom.pattern.callback.Counter(); - - var matcher = new goog.dom.pattern.Matcher(); - matcher.addPattern(pattern1, counter.getCallback()); - matcher.addPattern(pattern2, counter.getCallback()); - - matcher.match(document.body); - - assertEquals('StartTag(span|p) should match 8 times in body', 8, - counter.count); -} - -function testMatcherWithQuit() { - var pattern1 = new goog.dom.pattern.StartTag('SPAN'); - var pattern2 = new goog.dom.pattern.StartTag('P'); - - var count = 0; - var callback = function(node, position) { - if (node.nodeName == 'SPAN') { - throw goog.iter.StopIteration; - return true; - } - count++; - }; - - var matcher = new goog.dom.pattern.Matcher(); - matcher.addPattern(pattern1, callback); - matcher.addPattern(pattern2, callback); - - matcher.match(document.body); - - assertEquals('Stopped span|p should match 1 time in body', 1, count); -} - -function testMatcherWithReplace() { - var pattern1 = new goog.dom.pattern.StartTag('B'); - var pattern2 = new goog.dom.pattern.StartTag('I'); - - var count = 0; - var callback = function(node, position) { - count++; - if (node.nodeName == 'B') { - var i = goog.dom.createDom('I'); - node.parentNode.insertBefore(i, node); - goog.dom.removeNode(node); - - position.setPosition(i); - - return true; - } - }; - - var matcher = new goog.dom.pattern.Matcher(); - matcher.addPattern(pattern1, callback); - matcher.addPattern(pattern2, callback); - - matcher.match(goog.dom.getElement('div1')); - - assertEquals('i|b->i should match 5 times in div1', 5, count); -} - -function testMatcherAndFullTag() { - var pattern = new goog.dom.pattern.FullTag('P'); - - var test = new goog.dom.pattern.callback.Test(); - - var matcher = new goog.dom.pattern.Matcher(); - matcher.addPattern(pattern, test.getCallback()); - - matcher.match(goog.dom.getElement('p1')); - - assert('FullTag(p) should match on p1', test.matched); - - test.reset(); - matcher.match(goog.dom.getElement('div1')); - - assert('FullTag(p) should not match on div1', !test.matched); -} - -function testMatcherAndSequence() { - var pattern = new goog.dom.pattern.Sequence([ - new goog.dom.pattern.StartTag('P'), - new goog.dom.pattern.StartTag('SPAN'), - new goog.dom.pattern.EndTag('SPAN'), - new goog.dom.pattern.EndTag('P') - ], true); - - var counter = new goog.dom.pattern.callback.Counter(); - var matcher = new goog.dom.pattern.Matcher(); - matcher.addPattern(pattern, counter.getCallback()); - matcher.match(document.body); - - assertEquals('Sequence should match 1 times in body', 1, counter.count); -} - -function testMatcherAndRepeatFullTag() { - var pattern = new goog.dom.pattern.Repeat( - new goog.dom.pattern.FullTag('P'), 1); - - var count = 0; - var tcount = 0; - var matcher = new goog.dom.pattern.Matcher(); - matcher.addPattern(pattern, function() { - count++; - tcount += pattern.count; - }); - matcher.match(document.body); - - assertEquals('Repeated p should match 2 times in body', 2, count); - assertEquals('Repeated p should match 5 total times in body', 5, tcount); -} diff --git a/src/database/third_party/closure-library/closure/goog/dom/pattern/nodetype.js b/src/database/third_party/closure-library/closure/goog/dom/pattern/nodetype.js deleted file mode 100644 index a12c9a1cf37..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/pattern/nodetype.js +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview DOM pattern to match a node of the given type. - * - * @author robbyw@google.com (Robby Walker) - */ - -goog.provide('goog.dom.pattern.NodeType'); - -goog.require('goog.dom.pattern.AbstractPattern'); -goog.require('goog.dom.pattern.MatchType'); - - - -/** - * Pattern object that matches any node of the given type. - * @param {goog.dom.NodeType} nodeType The node type to match. - * @constructor - * @extends {goog.dom.pattern.AbstractPattern} - * @final - */ -goog.dom.pattern.NodeType = function(nodeType) { - /** - * The node type to match. - * @type {goog.dom.NodeType} - * @private - */ - this.nodeType_ = nodeType; -}; -goog.inherits(goog.dom.pattern.NodeType, goog.dom.pattern.AbstractPattern); - - -/** - * Test whether the given token is a text token which matches the string or - * regular expression provided in the constructor. - * @param {Node} token Token to match against. - * @param {goog.dom.TagWalkType} type The type of token. - * @return {goog.dom.pattern.MatchType} MATCH if the pattern - * matches, NO_MATCH otherwise. - * @override - */ -goog.dom.pattern.NodeType.prototype.matchToken = function(token, type) { - return token.nodeType == this.nodeType_ ? - goog.dom.pattern.MatchType.MATCH : - goog.dom.pattern.MatchType.NO_MATCH; -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/pattern/pattern.js b/src/database/third_party/closure-library/closure/goog/dom/pattern/pattern.js deleted file mode 100644 index 19f4d1b7946..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/pattern/pattern.js +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview DOM patterns. Allows for description of complex DOM patterns - * using regular expression like constructs. - * - * @author robbyw@google.com (Robby Walker) - */ - -goog.provide('goog.dom.pattern'); -goog.provide('goog.dom.pattern.MatchType'); - - -/** - * Regular expression for breaking text nodes. - * @type {RegExp} - */ -goog.dom.pattern.BREAKING_TEXTNODE_RE = /^\s*$/; - - -/** - * Utility function to match a string against either a string or a regular - * expression. - * - * @param {string|RegExp} obj Either a string or a regular expression. - * @param {string} str The string to match. - * @return {boolean} Whether the strings are equal, or if the string matches - * the regular expression. - */ -goog.dom.pattern.matchStringOrRegex = function(obj, str) { - if (goog.isString(obj)) { - // Match a string - return str == obj; - } else { - // Match a regular expression - return !!(str && str.match(obj)); - } -}; - - -/** - * Utility function to match a DOM attribute against either a string or a - * regular expression. Conforms to the interface spec for - * {@link goog.object#every}. - * - * @param {string|RegExp} elem Either a string or a regular expression. - * @param {string} index The attribute name to match. - * @param {Object} orig The original map of matches to test. - * @return {boolean} Whether the strings are equal, or if the attribute matches - * the regular expression. - * @this {Element} Called using goog.object every on an Element. - */ -goog.dom.pattern.matchStringOrRegexMap = function(elem, index, orig) { - return goog.dom.pattern.matchStringOrRegex(elem, - index in this ? this[index] : - (this.getAttribute ? this.getAttribute(index) : null)); -}; - - -/** - * When matched to a token, a pattern may return any of the following statuses: - *
      - *
    1. NO_MATCH - The pattern does not match. This is the only - * value that evaluates to false in a boolean context. - *
    2. MATCHING - The token is part of an incomplete match. - *
    3. MATCH - The token completes a match. - *
    4. BACKTRACK_MATCH - The token does not match, but indicates - * the end of a repetitive match. For instance, in regular expressions, - * the pattern /a+/ would match 'aaaaaaaab'. - * Every 'a' token would give a status of - * MATCHING while the 'b' token would give a - * status of BACKTRACK_MATCH. - *
    - * @enum {number} - */ -goog.dom.pattern.MatchType = { - NO_MATCH: 0, - MATCHING: 1, - MATCH: 2, - BACKTRACK_MATCH: 3 -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/pattern/pattern_test.html b/src/database/third_party/closure-library/closure/goog/dom/pattern/pattern_test.html deleted file mode 100644 index 7a30c067f16..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/pattern/pattern_test.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - -goog.dom.pattern Tests - - - - -
    - -
    -
    - x -
    -
    Text
    -
    Other Text
    - - - -

    xyz

    - -
    xyz
    - - X - -
    Text
    - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/pattern/pattern_test.js b/src/database/third_party/closure-library/closure/goog/dom/pattern/pattern_test.js deleted file mode 100644 index dfa7e3a12aa..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/pattern/pattern_test.js +++ /dev/null @@ -1,592 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.dom.patternTest'); -goog.setTestOnly('goog.dom.patternTest'); - -goog.require('goog.dom'); -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.TagWalkType'); -goog.require('goog.dom.pattern.AllChildren'); -goog.require('goog.dom.pattern.ChildMatches'); -goog.require('goog.dom.pattern.EndTag'); -goog.require('goog.dom.pattern.FullTag'); -goog.require('goog.dom.pattern.MatchType'); -goog.require('goog.dom.pattern.NodeType'); -goog.require('goog.dom.pattern.Repeat'); -goog.require('goog.dom.pattern.Sequence'); -goog.require('goog.dom.pattern.StartTag'); -goog.require('goog.dom.pattern.Text'); -goog.require('goog.testing.jsunit'); - -// TODO(robbyw): write a test that checks if backtracking works in Sequence - -function testStartTag() { - var pattern = new goog.dom.pattern.StartTag('DIV'); - assertEquals( - 'StartTag(div) should match div', - goog.dom.pattern.MatchType.MATCH, - pattern.matchToken( - goog.dom.getElement('div1'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'StartTag(div) should not match span', - goog.dom.pattern.MatchType.NO_MATCH, - pattern.matchToken( - goog.dom.getElement('span1'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'StartTag(div) should not match /div', - goog.dom.pattern.MatchType.NO_MATCH, - pattern.matchToken( - goog.dom.getElement('div1'), - goog.dom.TagWalkType.END_TAG)); -} - -function testStartTagCase() { - var pattern = new goog.dom.pattern.StartTag('diV'); - assertEquals( - 'StartTag(diV) should match div', - goog.dom.pattern.MatchType.MATCH, - pattern.matchToken( - goog.dom.getElement('div1'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'StartTag(diV) should not match span', - goog.dom.pattern.MatchType.NO_MATCH, - pattern.matchToken( - goog.dom.getElement('span1'), - goog.dom.TagWalkType.START_TAG)); -} - -function testStartTagRegex() { - var pattern = new goog.dom.pattern.StartTag(/D/); - assertEquals( - 'StartTag(/D/) should match div', - goog.dom.pattern.MatchType.MATCH, - pattern.matchToken( - goog.dom.getElement('div1'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'StartTag(/D/) should not match span', - goog.dom.pattern.MatchType.NO_MATCH, - pattern.matchToken( - goog.dom.getElement('span1'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'StartTag(/D/) should not match /div', - goog.dom.pattern.MatchType.NO_MATCH, - pattern.matchToken( - goog.dom.getElement('div1'), - goog.dom.TagWalkType.END_TAG)); -} - -function testStartTagAttributes() { - var pattern = new goog.dom.pattern.StartTag('DIV', {id: 'div1'}); - assertEquals( - 'StartTag(div,id:div1) should match div1', - goog.dom.pattern.MatchType.MATCH, - pattern.matchToken( - goog.dom.getElement('div1'), - goog.dom.TagWalkType.START_TAG)); - assertEquals('StartTag(div,id:div2) should not match div1', - goog.dom.pattern.MatchType.NO_MATCH, - pattern.matchToken( - goog.dom.getElement('div2'), - goog.dom.TagWalkType.START_TAG)); -} - -function testStartTagStyle() { - var pattern = new goog.dom.pattern.StartTag('SPAN', null, {color: 'red'}); - assertEquals( - 'StartTag(span,null,color:red) should match span1', - goog.dom.pattern.MatchType.MATCH, - pattern.matchToken( - goog.dom.getElement('span1'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'StartTag(span,null,color:blue) should not match span1', - goog.dom.pattern.MatchType.NO_MATCH, - pattern.matchToken( - goog.dom.getElement('span2'), - goog.dom.TagWalkType.START_TAG)); -} - -function testStartTagAttributeRegex() { - var pattern = new goog.dom.pattern.StartTag('SPAN', {id: /span\d/}); - assertEquals( - 'StartTag(span,id:/span\\d/) should match span1', - goog.dom.pattern.MatchType.MATCH, - pattern.matchToken( - goog.dom.getElement('span1'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'StartTag(span,id:/span\\d/) should match span2', - goog.dom.pattern.MatchType.MATCH, - pattern.matchToken( - goog.dom.getElement('span1'), - goog.dom.TagWalkType.START_TAG)); -} - -function testEndTag() { - var pattern = new goog.dom.pattern.EndTag('DIV'); - assertEquals( - 'EndTag should match div', - goog.dom.pattern.MatchType.MATCH, - pattern.matchToken( - goog.dom.getElement('div1'), - goog.dom.TagWalkType.END_TAG)); -} - -function testEndTagRegex() { - var pattern = new goog.dom.pattern.EndTag(/D/); - assertEquals( - 'EndTag(/D/) should match /div', - goog.dom.pattern.MatchType.MATCH, - pattern.matchToken( - goog.dom.getElement('div1'), - goog.dom.TagWalkType.END_TAG)); - assertEquals( - 'EndTag(/D/) should not match /span', - goog.dom.pattern.MatchType.NO_MATCH, - pattern.matchToken( - goog.dom.getElement('span1'), - goog.dom.TagWalkType.END_TAG)); - assertEquals( - 'EndTag(/D/) should not match div', - goog.dom.pattern.MatchType.NO_MATCH, - pattern.matchToken( - goog.dom.getElement('div1'), - goog.dom.TagWalkType.START_TAG)); -} - -function testChildMatches() { - var pattern = new goog.dom.pattern.ChildMatches( - new goog.dom.pattern.StartTag('DIV'), 2); - - assertEquals( - 'ChildMatches should match div', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('div1'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'ChildMatches should match /div', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('div1'), - goog.dom.TagWalkType.END_TAG)); - assertEquals( - 'ChildMatches should match div', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('div2'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'ChildMatches should match /div', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('div2'), - goog.dom.TagWalkType.END_TAG)); - assertEquals( - 'ChildMatches should finish match at /body', - goog.dom.pattern.MatchType.BACKTRACK_MATCH, - pattern.matchToken( - document.body, - goog.dom.TagWalkType.END_TAG)); - - assertEquals( - 'ChildMatches should match div', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('div2'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'ChildMatches should match /div', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('div2'), - goog.dom.TagWalkType.END_TAG)); - assertEquals( - 'ChildMatches should fail to match at /body: not enough child matches', - goog.dom.pattern.MatchType.NO_MATCH, - pattern.matchToken( - document.body, - goog.dom.TagWalkType.END_TAG)); -} - -function testFullTag() { - var pattern = new goog.dom.pattern.FullTag('DIV'); - assertEquals( - 'FullTag(div) should match div', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('div1'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'FullTag(div) should match /div', - goog.dom.pattern.MatchType.MATCH, - pattern.matchToken( - goog.dom.getElement('div1'), - goog.dom.TagWalkType.END_TAG)); - - assertEquals( - 'FullTag(div) should start match at div', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('div1'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'FullTag(div) should continue to match span', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('span1'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'FullTag(div) should continue to match /span', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('span1'), - goog.dom.TagWalkType.END_TAG)); - assertEquals( - 'FullTag(div) should finish match at /div', - goog.dom.pattern.MatchType.MATCH, - pattern.matchToken( - goog.dom.getElement('div1'), - goog.dom.TagWalkType.END_TAG)); -} - -function testAllChildren() { - var pattern = new goog.dom.pattern.AllChildren(); - assertEquals( - 'AllChildren(div) should match div', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('div1'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'AllChildren(div) should match /div', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('div1'), - goog.dom.TagWalkType.END_TAG)); - assertEquals( - 'AllChildren(div) should match at /body', - goog.dom.pattern.MatchType.BACKTRACK_MATCH, - pattern.matchToken( - document.body, - goog.dom.TagWalkType.END_TAG)); - - assertEquals( - 'AllChildren(div) should start match at div', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('div1'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'AllChildren(div) should continue to match span', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('span1'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'AllChildren(div) should continue to match /span', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('span1'), - goog.dom.TagWalkType.END_TAG)); - assertEquals( - 'AllChildren(div) should continue to match at /div', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('div1'), - goog.dom.TagWalkType.END_TAG)); - assertEquals( - 'AllChildren(div) should finish match at /body', - goog.dom.pattern.MatchType.BACKTRACK_MATCH, - pattern.matchToken( - document.body, - goog.dom.TagWalkType.END_TAG)); -} - -function testText() { - var pattern = new goog.dom.pattern.Text('Text'); - assertEquals( - 'Text should match div3/text()', - goog.dom.pattern.MatchType.MATCH, - pattern.matchToken( - goog.dom.getElement('div3').firstChild, - goog.dom.TagWalkType.OTHER)); - assertEquals( - 'Text should not match div4/text()', - goog.dom.pattern.MatchType.NO_MATCH, - pattern.matchToken( - goog.dom.getElement('div4').firstChild, - goog.dom.TagWalkType.OTHER)); - assertEquals( - 'Text should not match div3', - goog.dom.pattern.MatchType.NO_MATCH, - pattern.matchToken( - goog.dom.getElement('div3'), - goog.dom.TagWalkType.START_TAG)); - -} - -function testTextRegex() { - var pattern = new goog.dom.pattern.Text(/Text/); - assertEquals( - 'Text(regex) should match div3/text()', - goog.dom.pattern.MatchType.MATCH, - pattern.matchToken( - goog.dom.getElement('div3').firstChild, - goog.dom.TagWalkType.OTHER)); - assertEquals( - 'Text(regex) should match div4/text()', - goog.dom.pattern.MatchType.MATCH, - pattern.matchToken( - goog.dom.getElement('div4').firstChild, - goog.dom.TagWalkType.OTHER)); -} - -function testNodeType() { - var pattern = new goog.dom.pattern.NodeType(goog.dom.NodeType.COMMENT); - assertEquals('Comment matcher should match a comment', - goog.dom.pattern.MatchType.MATCH, - pattern.matchToken( - goog.dom.getElement('nodeTypes').firstChild, - goog.dom.TagWalkType.OTHER)); - assertEquals('Comment matcher should not match a text node', - goog.dom.pattern.MatchType.NO_MATCH, - pattern.matchToken( - goog.dom.getElement('nodeTypes').lastChild, - goog.dom.TagWalkType.OTHER)); -} - -function testSequence() { - var pattern = new goog.dom.pattern.Sequence([ - new goog.dom.pattern.StartTag('DIV'), - new goog.dom.pattern.StartTag('SPAN'), - new goog.dom.pattern.EndTag('SPAN'), - new goog.dom.pattern.EndTag('DIV')]); - - assertEquals( - 'Sequence[0] should match div1', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('div1'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'Sequence[1] should match span1', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('span1'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'Sequence[2] should match /span1', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('span1'), - goog.dom.TagWalkType.END_TAG)); - assertEquals( - 'Sequence[3] should match /div1', - goog.dom.pattern.MatchType.MATCH, - pattern.matchToken( - goog.dom.getElement('div1'), - goog.dom.TagWalkType.END_TAG)); - - assertEquals( - 'Sequence[0] should match div1 again', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('div1'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'Sequence[1] should match span1 again', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('span1'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'Sequence[2] should match /span1 again', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('span1'), - goog.dom.TagWalkType.END_TAG)); - assertEquals( - 'Sequence[3] should match /div1 again', - goog.dom.pattern.MatchType.MATCH, - pattern.matchToken( - goog.dom.getElement('div1'), - goog.dom.TagWalkType.END_TAG)); - - assertEquals( - 'Sequence[0] should match div1', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('div1'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'Sequence[1] should not match div1', - goog.dom.pattern.MatchType.NO_MATCH, - pattern.matchToken( - goog.dom.getElement('div1'), - goog.dom.TagWalkType.START_TAG)); - - assertEquals( - 'Sequence[0] should match div1 after failure', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('div1'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'Sequence[1] should match span1 after failure', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('span1'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'Sequence[2] should match /span1 after failure', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('span1'), - goog.dom.TagWalkType.END_TAG)); - assertEquals( - 'Sequence[3] should match /div1 after failure', - goog.dom.pattern.MatchType.MATCH, - pattern.matchToken( - goog.dom.getElement('div1'), - goog.dom.TagWalkType.END_TAG)); -} - -function testRepeat() { - var pattern = new goog.dom.pattern.Repeat( - new goog.dom.pattern.StartTag('B')); - - // Note: this test does not mimic an actual matcher because it is only - // passing the START_TAG events. - - assertEquals( - 'Repeat[B] should match b1', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('b1'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'Repeat[B] should match b2', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('b2'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'Repeat[B] should backtrack match i1', - goog.dom.pattern.MatchType.BACKTRACK_MATCH, - pattern.matchToken( - goog.dom.getElement('i1'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'Repeat[B] should have match count of 2', - 2, - pattern.count); - - assertEquals( - 'Repeat[B] should backtrack match i1 even with no b matches', - goog.dom.pattern.MatchType.BACKTRACK_MATCH, - pattern.matchToken( - goog.dom.getElement('i1'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'Repeat[B] should have match count of 0', - 0, - pattern.count); -} - -function testRepeatWithMinimum() { - var pattern = new goog.dom.pattern.Repeat( - new goog.dom.pattern.StartTag('B'), 1); - - // Note: this test does not mimic an actual matcher because it is only - // passing the START_TAG events. - - assertEquals( - 'Repeat[B,1] should match b1', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('b1'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'Repeat[B,1] should match b2', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken( - goog.dom.getElement('b2'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'Repeat[B,1] should backtrack match i1', - goog.dom.pattern.MatchType.BACKTRACK_MATCH, - pattern.matchToken( - goog.dom.getElement('i1'), - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'Repeat[B,1] should have match count of 2', - 2, - pattern.count); - - assertEquals( - 'Repeat[B,1] should not match i1', - goog.dom.pattern.MatchType.NO_MATCH, - pattern.matchToken( - goog.dom.getElement('i1'), - goog.dom.TagWalkType.START_TAG)); -} - -function testRepeatWithMaximum() { - var pattern = new goog.dom.pattern.Repeat( - new goog.dom.pattern.StartTag('B'), 1, 1); - - // Note: this test does not mimic an actual matcher because it is only - // passing the START_TAG events. - - assertEquals( - 'Repeat[B,1] should match b1', - goog.dom.pattern.MatchType.MATCH, - pattern.matchToken( - goog.dom.getElement('b1'), - goog.dom.TagWalkType.START_TAG)); -} - -function testSequenceBacktrack() { - var pattern = new goog.dom.pattern.Sequence([ - new goog.dom.pattern.Repeat(new goog.dom.pattern.StartTag('SPAN')), - new goog.dom.pattern.Text('X')]); - - var root = goog.dom.getElement('span3'); - assertEquals( - 'Sequence[Repeat[SPAN],"X"] should match span3', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken(root, goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'Sequence[Repeat[SPAN],"X"] should match span3.firstChild', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken(root.firstChild, - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'Sequence[Repeat[SPAN],"X"] should match span3.firstChild.firstChild', - goog.dom.pattern.MatchType.MATCHING, - pattern.matchToken(root.firstChild.firstChild, - goog.dom.TagWalkType.START_TAG)); - assertEquals( - 'Sequence[Repeat[SPAN],"X"] should finish match text node', - goog.dom.pattern.MatchType.MATCH, - pattern.matchToken(root.firstChild.firstChild.firstChild, - goog.dom.TagWalkType.OTHER)); -} diff --git a/src/database/third_party/closure-library/closure/goog/dom/pattern/repeat.js b/src/database/third_party/closure-library/closure/goog/dom/pattern/repeat.js deleted file mode 100644 index 6872ca198c9..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/pattern/repeat.js +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview DOM pattern to match a tag and all of its children. - * - * @author robbyw@google.com (Robby Walker) - */ - -goog.provide('goog.dom.pattern.Repeat'); - -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.pattern.AbstractPattern'); -goog.require('goog.dom.pattern.MatchType'); - - - -/** - * Pattern object that matches a repetition of another pattern. - * @param {goog.dom.pattern.AbstractPattern} pattern The pattern to - * repetitively match. - * @param {number=} opt_minimum The minimum number of times to match. Defaults - * to 0. - * @param {number=} opt_maximum The maximum number of times to match. Defaults - * to unlimited. - * @constructor - * @extends {goog.dom.pattern.AbstractPattern} - * @final - */ -goog.dom.pattern.Repeat = function(pattern, - opt_minimum, - opt_maximum) { - this.pattern_ = pattern; - this.minimum_ = opt_minimum || 0; - this.maximum_ = opt_maximum || null; - this.matches = []; -}; -goog.inherits(goog.dom.pattern.Repeat, goog.dom.pattern.AbstractPattern); - - -/** - * Pattern to repetitively match. - * - * @type {goog.dom.pattern.AbstractPattern} - * @private - */ -goog.dom.pattern.Repeat.prototype.pattern_; - - -/** - * Minimum number of times to match the pattern. - * - * @private - */ -goog.dom.pattern.Repeat.prototype.minimum_ = 0; - - -/** - * Optional maximum number of times to match the pattern. A {@code null} value - * will be treated as infinity. - * - * @type {?number} - * @private - */ -goog.dom.pattern.Repeat.prototype.maximum_ = 0; - - -/** - * Number of times the pattern has matched. - * - * @type {number} - */ -goog.dom.pattern.Repeat.prototype.count = 0; - - -/** - * Whether the pattern has recently matched or failed to match and will need to - * be reset when starting a new round of matches. - * - * @type {boolean} - * @private - */ -goog.dom.pattern.Repeat.prototype.needsReset_ = false; - - -/** - * The matched nodes. - * - * @type {Array} - */ -goog.dom.pattern.Repeat.prototype.matches; - - -/** - * Test whether the given token continues a repeated series of matches of the - * pattern given in the constructor. - * - * @param {Node} token Token to match against. - * @param {goog.dom.TagWalkType} type The type of token. - * @return {goog.dom.pattern.MatchType} MATCH if the pattern - * matches, BACKTRACK_MATCH if the pattern does not match - * but already had accumulated matches, MATCHING if the pattern - * starts a match, and NO_MATCH if the pattern does not match. - * @suppress {missingProperties} See the broken line below. - * @override - */ -goog.dom.pattern.Repeat.prototype.matchToken = function(token, type) { - // Reset if we're starting a new match - if (this.needsReset_) { - this.reset(); - } - - // If the option is set, ignore any whitespace only text nodes - if (token.nodeType == goog.dom.NodeType.TEXT && - token.nodeValue.match(/^\s+$/)) { - return goog.dom.pattern.MatchType.MATCHING; - } - - switch (this.pattern_.matchToken(token, type)) { - case goog.dom.pattern.MatchType.MATCH: - // Record the first token we match. - if (this.count == 0) { - this.matchedNode = token; - } - - // Mark the match - this.count++; - - // Add to the list - this.matches.push(this.pattern_.matchedNode); - - // Check if this match hits our maximum - if (this.maximum_ !== null && this.count == this.maximum_) { - this.needsReset_ = true; - return goog.dom.pattern.MatchType.MATCH; - } else { - return goog.dom.pattern.MatchType.MATCHING; - } - - case goog.dom.pattern.MatchType.MATCHING: - // This can happen when our child pattern is a sequence or a repetition. - return goog.dom.pattern.MatchType.MATCHING; - - case goog.dom.pattern.MatchType.BACKTRACK_MATCH: - // This happens if our child pattern is repetitive too. - // TODO(robbyw): Backtrack further if necessary. - this.count++; - - // NOTE(nicksantos): This line of code is broken. this.patterns_ doesn't - // exist, and this.currentPosition_ doesn't exit. When this is fixed, - // remove the missingProperties suppression above. - if (this.currentPosition_ == this.patterns_.length) { - this.needsReset_ = true; - return goog.dom.pattern.MatchType.BACKTRACK_MATCH; - } else { - // Retry the same token on the next iteration of the child pattern. - return this.matchToken(token, type); - } - - default: - this.needsReset_ = true; - if (this.count >= this.minimum_) { - return goog.dom.pattern.MatchType.BACKTRACK_MATCH; - } else { - return goog.dom.pattern.MatchType.NO_MATCH; - } - } -}; - - -/** - * Reset any internal state this pattern keeps. - * @override - */ -goog.dom.pattern.Repeat.prototype.reset = function() { - this.pattern_.reset(); - this.count = 0; - this.needsReset_ = false; - this.matches.length = 0; -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/pattern/sequence.js b/src/database/third_party/closure-library/closure/goog/dom/pattern/sequence.js deleted file mode 100644 index 8fa0314d976..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/pattern/sequence.js +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview DOM pattern to match a sequence of other patterns. - * - * @author robbyw@google.com (Robby Walker) - */ - -goog.provide('goog.dom.pattern.Sequence'); - -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.pattern'); -goog.require('goog.dom.pattern.AbstractPattern'); -goog.require('goog.dom.pattern.MatchType'); - - - -/** - * Pattern object that matches a sequence of other patterns. - * - * @param {Array} patterns Ordered array of - * patterns to match. - * @param {boolean=} opt_ignoreWhitespace Optional flag to ignore text nodes - * consisting entirely of whitespace. The default is to not ignore them. - * @constructor - * @extends {goog.dom.pattern.AbstractPattern} - * @final - */ -goog.dom.pattern.Sequence = function(patterns, opt_ignoreWhitespace) { - this.patterns = patterns; - this.ignoreWhitespace_ = !!opt_ignoreWhitespace; -}; -goog.inherits(goog.dom.pattern.Sequence, goog.dom.pattern.AbstractPattern); - - -/** - * Ordered array of patterns to match. - * - * @type {Array} - */ -goog.dom.pattern.Sequence.prototype.patterns; - - -/** - * Position in the patterns array we have reached by successful matches. - * - * @type {number} - * @private - */ -goog.dom.pattern.Sequence.prototype.currentPosition_ = 0; - - -/** - * Whether or not to ignore whitespace only Text nodes. - * - * @type {boolean} - * @private - */ -goog.dom.pattern.Sequence.prototype.ignoreWhitespace_ = false; - - -/** - * Test whether the given token starts, continues, or finishes the sequence - * of patterns given in the constructor. - * - * @param {Node} token Token to match against. - * @param {goog.dom.TagWalkType} type The type of token. - * @return {goog.dom.pattern.MatchType} MATCH if the pattern - * matches, MATCHING if the pattern starts a match, and - * NO_MATCH if the pattern does not match. - * @override - */ -goog.dom.pattern.Sequence.prototype.matchToken = function(token, type) { - // If the option is set, ignore any whitespace only text nodes - if (this.ignoreWhitespace_ && token.nodeType == goog.dom.NodeType.TEXT && - goog.dom.pattern.BREAKING_TEXTNODE_RE.test(token.nodeValue)) { - return goog.dom.pattern.MatchType.MATCHING; - } - - switch (this.patterns[this.currentPosition_].matchToken(token, type)) { - case goog.dom.pattern.MatchType.MATCH: - // Record the first token we match. - if (this.currentPosition_ == 0) { - this.matchedNode = token; - } - - // Move forward one position. - this.currentPosition_++; - - // Check if this is the last position. - if (this.currentPosition_ == this.patterns.length) { - this.reset(); - return goog.dom.pattern.MatchType.MATCH; - } else { - return goog.dom.pattern.MatchType.MATCHING; - } - - case goog.dom.pattern.MatchType.MATCHING: - // This can happen when our child pattern is a sequence or a repetition. - return goog.dom.pattern.MatchType.MATCHING; - - case goog.dom.pattern.MatchType.BACKTRACK_MATCH: - // This means a repetitive match succeeded 1 token ago. - // TODO(robbyw): Backtrack further if necessary. - this.currentPosition_++; - - if (this.currentPosition_ == this.patterns.length) { - this.reset(); - return goog.dom.pattern.MatchType.BACKTRACK_MATCH; - } else { - // Retry the same token on the next pattern. - return this.matchToken(token, type); - } - - default: - this.reset(); - return goog.dom.pattern.MatchType.NO_MATCH; - } -}; - - -/** - * Reset any internal state this pattern keeps. - * @override - */ -goog.dom.pattern.Sequence.prototype.reset = function() { - if (this.patterns[this.currentPosition_]) { - this.patterns[this.currentPosition_].reset(); - } - this.currentPosition_ = 0; -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/pattern/starttag.js b/src/database/third_party/closure-library/closure/goog/dom/pattern/starttag.js deleted file mode 100644 index 4ce01135ea0..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/pattern/starttag.js +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview DOM pattern to match the start of a tag. - * - * @author robbyw@google.com (Robby Walker) - */ - -goog.provide('goog.dom.pattern.StartTag'); - -goog.require('goog.dom.TagWalkType'); -goog.require('goog.dom.pattern.Tag'); - - - -/** - * Pattern object that matches an opening tag. - * - * @param {string|RegExp} tag Name of the tag. Also will accept a regular - * expression to match against the tag name. - * @param {Object=} opt_attrs Optional map of attribute names to desired values. - * This pattern will only match when all attributes are present and match - * the string or regular expression value provided here. - * @param {Object=} opt_styles Optional map of CSS style names to desired - * values. This pattern will only match when all styles are present and - * match the string or regular expression value provided here. - * @param {Function=} opt_test Optional function that takes the element as a - * parameter and returns true if this pattern should match it. - * @constructor - * @extends {goog.dom.pattern.Tag} - */ -goog.dom.pattern.StartTag = function(tag, opt_attrs, opt_styles, opt_test) { - goog.dom.pattern.Tag.call( - this, - tag, - goog.dom.TagWalkType.START_TAG, - opt_attrs, - opt_styles, - opt_test); -}; -goog.inherits(goog.dom.pattern.StartTag, goog.dom.pattern.Tag); diff --git a/src/database/third_party/closure-library/closure/goog/dom/pattern/tag.js b/src/database/third_party/closure-library/closure/goog/dom/pattern/tag.js deleted file mode 100644 index d04ccd3a3f0..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/pattern/tag.js +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview DOM pattern to match a tag. - * - * @author robbyw@google.com (Robby Walker) - */ - -goog.provide('goog.dom.pattern.Tag'); - -goog.require('goog.dom.pattern'); -goog.require('goog.dom.pattern.AbstractPattern'); -goog.require('goog.dom.pattern.MatchType'); -goog.require('goog.object'); - - - -/** - * Pattern object that matches an tag. - * - * @param {string|RegExp} tag Name of the tag. Also will accept a regular - * expression to match against the tag name. - * @param {goog.dom.TagWalkType} type Type of token to match. - * @param {Object=} opt_attrs Optional map of attribute names to desired values. - * This pattern will only match when all attributes are present and match - * the string or regular expression value provided here. - * @param {Object=} opt_styles Optional map of CSS style names to desired - * values. This pattern will only match when all styles are present and - * match the string or regular expression value provided here. - * @param {Function=} opt_test Optional function that takes the element as a - * parameter and returns true if this pattern should match it. - * @constructor - * @extends {goog.dom.pattern.AbstractPattern} - */ -goog.dom.pattern.Tag = function(tag, type, opt_attrs, opt_styles, opt_test) { - if (goog.isString(tag)) { - this.tag_ = tag.toUpperCase(); - } else { - this.tag_ = tag; - } - - this.type_ = type; - - this.attrs_ = opt_attrs || null; - this.styles_ = opt_styles || null; - this.test_ = opt_test || null; -}; -goog.inherits(goog.dom.pattern.Tag, goog.dom.pattern.AbstractPattern); - - -/** - * The tag to match. - * - * @type {string|RegExp} - * @private - */ -goog.dom.pattern.Tag.prototype.tag_; - - -/** - * The type of token to match. - * - * @type {goog.dom.TagWalkType} - * @private - */ -goog.dom.pattern.Tag.prototype.type_; - - -/** - * The attributes to test for. - * - * @type {Object} - * @private - */ -goog.dom.pattern.Tag.prototype.attrs_ = null; - - -/** - * The styles to test for. - * - * @type {Object} - * @private - */ -goog.dom.pattern.Tag.prototype.styles_ = null; - - -/** - * Function that takes the element as a parameter and returns true if this - * pattern should match it. - * - * @type {Function} - * @private - */ -goog.dom.pattern.Tag.prototype.test_ = null; - - -/** - * Test whether the given token is a tag token which matches the tag name, - * style, and attributes provided in the constructor. - * - * @param {Node} token Token to match against. - * @param {goog.dom.TagWalkType} type The type of token. - * @return {goog.dom.pattern.MatchType} MATCH if the pattern - * matches, NO_MATCH otherwise. - * @override - */ -goog.dom.pattern.Tag.prototype.matchToken = function(token, type) { - // Check the direction and tag name. - if (type == this.type_ && - goog.dom.pattern.matchStringOrRegex(this.tag_, token.nodeName)) { - // Check the attributes. - if (this.attrs_ && - !goog.object.every( - this.attrs_, - goog.dom.pattern.matchStringOrRegexMap, - token)) { - return goog.dom.pattern.MatchType.NO_MATCH; - } - // Check the styles. - if (this.styles_ && - !goog.object.every( - this.styles_, - goog.dom.pattern.matchStringOrRegexMap, - token.style)) { - return goog.dom.pattern.MatchType.NO_MATCH; - } - - if (this.test_ && !this.test_(token)) { - return goog.dom.pattern.MatchType.NO_MATCH; - } - - // If we reach this point, we have a match and should save it. - this.matchedNode = token; - return goog.dom.pattern.MatchType.MATCH; - } - - return goog.dom.pattern.MatchType.NO_MATCH; -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/pattern/text.js b/src/database/third_party/closure-library/closure/goog/dom/pattern/text.js deleted file mode 100644 index c4519608c55..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/pattern/text.js +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview DOM pattern to match a text node. - * - * @author robbyw@google.com (Robby Walker) - */ - -goog.provide('goog.dom.pattern.Text'); - -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.pattern'); -goog.require('goog.dom.pattern.AbstractPattern'); -goog.require('goog.dom.pattern.MatchType'); - - - -/** - * Pattern object that matches text by exact matching or regular expressions. - * - * @param {string|RegExp} match String or regular expression to match against. - * @constructor - * @extends {goog.dom.pattern.AbstractPattern} - * @final - */ -goog.dom.pattern.Text = function(match) { - this.match_ = match; -}; -goog.inherits(goog.dom.pattern.Text, goog.dom.pattern.AbstractPattern); - - -/** - * The text or regular expression to match. - * - * @type {string|RegExp} - * @private - */ -goog.dom.pattern.Text.prototype.match_; - - -/** - * Test whether the given token is a text token which matches the string or - * regular expression provided in the constructor. - * - * @param {Node} token Token to match against. - * @param {goog.dom.TagWalkType} type The type of token. - * @return {goog.dom.pattern.MatchType} MATCH if the pattern - * matches, NO_MATCH otherwise. - * @override - */ -goog.dom.pattern.Text.prototype.matchToken = function(token, type) { - if (token.nodeType == goog.dom.NodeType.TEXT && - goog.dom.pattern.matchStringOrRegex(this.match_, token.nodeValue)) { - this.matchedNode = token; - return goog.dom.pattern.MatchType.MATCH; - } - - return goog.dom.pattern.MatchType.NO_MATCH; -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/range.js b/src/database/third_party/closure-library/closure/goog/dom/range.js deleted file mode 100644 index f71374cfc5e..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/range.js +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utilities for working with ranges in HTML documents. - * - * @author robbyw@google.com (Robby Walker) - */ - -goog.provide('goog.dom.Range'); - -goog.require('goog.dom'); -goog.require('goog.dom.AbstractRange'); -goog.require('goog.dom.BrowserFeature'); -goog.require('goog.dom.ControlRange'); -goog.require('goog.dom.MultiRange'); -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.TextRange'); -goog.require('goog.userAgent'); - - -/** - * Create a new selection from the given browser window's current selection. - * Note that this object does not auto-update if the user changes their - * selection and should be used as a snapshot. - * @param {Window=} opt_win The window to get the selection of. Defaults to the - * window this class was defined in. - * @return {goog.dom.AbstractRange?} A range wrapper object, or null if there - * was an error. - */ -goog.dom.Range.createFromWindow = function(opt_win) { - var sel = goog.dom.AbstractRange.getBrowserSelectionForWindow( - opt_win || window); - return sel && goog.dom.Range.createFromBrowserSelection(sel); -}; - - -/** - * Create a new range wrapper from the given browser selection object. Note - * that this object does not auto-update if the user changes their selection and - * should be used as a snapshot. - * @param {!Object} selection The browser selection object. - * @return {goog.dom.AbstractRange?} A range wrapper object or null if there - * was an error. - */ -goog.dom.Range.createFromBrowserSelection = function(selection) { - var range; - var isReversed = false; - if (selection.createRange) { - /** @preserveTry */ - try { - range = selection.createRange(); - } catch (e) { - // Access denied errors can be thrown here in IE if the selection was - // a flash obj or if there are cross domain issues - return null; - } - } else if (selection.rangeCount) { - if (selection.rangeCount > 1) { - return goog.dom.MultiRange.createFromBrowserSelection( - /** @type {!Selection} */ (selection)); - } else { - range = selection.getRangeAt(0); - isReversed = goog.dom.Range.isReversed(selection.anchorNode, - selection.anchorOffset, selection.focusNode, selection.focusOffset); - } - } else { - return null; - } - - return goog.dom.Range.createFromBrowserRange(range, isReversed); -}; - - -/** - * Create a new range wrapper from the given browser range object. - * @param {Range|TextRange} range The browser range object. - * @param {boolean=} opt_isReversed Whether the focus node is before the anchor - * node. - * @return {!goog.dom.AbstractRange} A range wrapper object. - */ -goog.dom.Range.createFromBrowserRange = function(range, opt_isReversed) { - // Create an IE control range when appropriate. - return goog.dom.AbstractRange.isNativeControlRange(range) ? - goog.dom.ControlRange.createFromBrowserRange(range) : - goog.dom.TextRange.createFromBrowserRange(range, opt_isReversed); -}; - - -/** - * Create a new range wrapper that selects the given node's text. - * @param {Node} node The node to select. - * @param {boolean=} opt_isReversed Whether the focus node is before the anchor - * node. - * @return {!goog.dom.AbstractRange} A range wrapper object. - */ -goog.dom.Range.createFromNodeContents = function(node, opt_isReversed) { - return goog.dom.TextRange.createFromNodeContents(node, opt_isReversed); -}; - - -/** - * Create a new range wrapper that represents a caret at the given node, - * accounting for the given offset. This always creates a TextRange, regardless - * of whether node is an image node or other control range type node. - * @param {Node} node The node to place a caret at. - * @param {number} offset The offset within the node to place the caret at. - * @return {!goog.dom.AbstractRange} A range wrapper object. - */ -goog.dom.Range.createCaret = function(node, offset) { - return goog.dom.TextRange.createFromNodes(node, offset, node, offset); -}; - - -/** - * Create a new range wrapper that selects the area between the given nodes, - * accounting for the given offsets. - * @param {Node} anchorNode The node to anchor on. - * @param {number} anchorOffset The offset within the node to anchor on. - * @param {Node} focusNode The node to focus on. - * @param {number} focusOffset The offset within the node to focus on. - * @return {!goog.dom.AbstractRange} A range wrapper object. - */ -goog.dom.Range.createFromNodes = function(anchorNode, anchorOffset, focusNode, - focusOffset) { - return goog.dom.TextRange.createFromNodes(anchorNode, anchorOffset, focusNode, - focusOffset); -}; - - -/** - * Clears the window's selection. - * @param {Window=} opt_win The window to get the selection of. Defaults to the - * window this class was defined in. - */ -goog.dom.Range.clearSelection = function(opt_win) { - var sel = goog.dom.AbstractRange.getBrowserSelectionForWindow( - opt_win || window); - if (!sel) { - return; - } - if (sel.empty) { - // We can't just check that the selection is empty, becuase IE - // sometimes gets confused. - try { - sel.empty(); - } catch (e) { - // Emptying an already empty selection throws an exception in IE - } - } else { - try { - sel.removeAllRanges(); - } catch (e) { - // This throws in IE9 if the range has been invalidated; for example, if - // the user clicked on an element which disappeared during the event - // handler. - } - } -}; - - -/** - * Tests if the window has a selection. - * @param {Window=} opt_win The window to check the selection of. Defaults to - * the window this class was defined in. - * @return {boolean} Whether the window has a selection. - */ -goog.dom.Range.hasSelection = function(opt_win) { - var sel = goog.dom.AbstractRange.getBrowserSelectionForWindow( - opt_win || window); - return !!sel && - (goog.dom.BrowserFeature.LEGACY_IE_RANGES ? - sel.type != 'None' : !!sel.rangeCount); -}; - - -/** - * Returns whether the focus position occurs before the anchor position. - * @param {Node} anchorNode The node to anchor on. - * @param {number} anchorOffset The offset within the node to anchor on. - * @param {Node} focusNode The node to focus on. - * @param {number} focusOffset The offset within the node to focus on. - * @return {boolean} Whether the focus position occurs before the anchor - * position. - */ -goog.dom.Range.isReversed = function(anchorNode, anchorOffset, focusNode, - focusOffset) { - if (anchorNode == focusNode) { - return focusOffset < anchorOffset; - } - var child; - if (anchorNode.nodeType == goog.dom.NodeType.ELEMENT && anchorOffset) { - child = anchorNode.childNodes[anchorOffset]; - if (child) { - anchorNode = child; - anchorOffset = 0; - } else if (goog.dom.contains(anchorNode, focusNode)) { - // If focus node is contained in anchorNode, it must be before the - // end of the node. Hence we are reversed. - return true; - } - } - if (focusNode.nodeType == goog.dom.NodeType.ELEMENT && focusOffset) { - child = focusNode.childNodes[focusOffset]; - if (child) { - focusNode = child; - focusOffset = 0; - } else if (goog.dom.contains(focusNode, anchorNode)) { - // If anchor node is contained in focusNode, it must be before the - // end of the node. Hence we are not reversed. - return false; - } - } - return (goog.dom.compareNodeOrder(anchorNode, focusNode) || - anchorOffset - focusOffset) > 0; -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/range_test.html b/src/database/third_party/closure-library/closure/goog/dom/range_test.html deleted file mode 100644 index 2612a6e68e0..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/range_test.html +++ /dev/null @@ -1,44 +0,0 @@ - - - - - -Closure Unit Tests - goog.dom.Range - - - - -
    Text
    -
    abc
    def
    -
    -
    -
    Text that
    will be deleted
    -
    -
    -
    -
    012345
    -
    12
    -
    • 1
    • 2
    -
    1. 1
    2. 2
    - -
    Will be removed
    - -
    -
    hello world !
    -
    -
    abcd
    e
    -

    abcde
    -
    - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/range_test.js b/src/database/third_party/closure-library/closure/goog/dom/range_test.js deleted file mode 100644 index 68f9df7dbed..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/range_test.js +++ /dev/null @@ -1,722 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.dom.RangeTest'); -goog.setTestOnly('goog.dom.RangeTest'); - -goog.require('goog.dom'); -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.Range'); -goog.require('goog.dom.RangeType'); -goog.require('goog.dom.TagName'); -goog.require('goog.dom.TextRange'); -goog.require('goog.dom.browserrange'); -goog.require('goog.testing.dom'); -goog.require('goog.testing.jsunit'); -goog.require('goog.userAgent'); - -var assertRangeEquals = goog.testing.dom.assertRangeEquals; - -function setUp() { - // Reset the focus; some tests may invalidate the focus to exercise various - // browser bugs. - var focusableElement = goog.dom.getElement('focusableElement'); - focusableElement.focus(); - focusableElement.blur(); -} - -function normalizeHtml(str) { - return str.toLowerCase().replace(/[\n\r\f"]/g, '') - .replace(/<\/li>/g, ''); // " for emacs -} - -function testCreate() { - assertNotNull('Browser range object can be created for node', - goog.dom.Range.createFromNodeContents(goog.dom.getElement('test1'))); -} - -function testTableRange() { - var tr = goog.dom.getElement('cell').parentNode; - var range = goog.dom.Range.createFromNodeContents(tr); - assertEquals('Selection should have correct text', '12', - range.getText()); - assertEquals('Selection should have correct html fragment', - '12', normalizeHtml(range.getHtmlFragment())); - - // TODO(robbyw): On IE the TR is included, on FF it is not. - //assertEquals('Selection should have correct valid html', - // '12', - // normalizeHtml(range.getValidHtml())); - - assertEquals('Selection should have correct pastable html', - '
    12
    ', - normalizeHtml(range.getPastableHtml())); -} - -function testUnorderedListRange() { - var ul = goog.dom.getElement('ulTest').firstChild; - var range = goog.dom.Range.createFromNodeContents(ul); - assertEquals('Selection should have correct html fragment', - '1
  • 2', normalizeHtml(range.getHtmlFragment())); - - // TODO(robbyw): On IE the UL is included, on FF it is not. - //assertEquals('Selection should have correct valid html', - // '
  • 1
  • 2
  • ', normalizeHtml(range.getValidHtml())); - - assertEquals('Selection should have correct pastable html', - '
    • 1
    • 2
    ', - normalizeHtml(range.getPastableHtml())); -} - -function testOrderedListRange() { - var ol = goog.dom.getElement('olTest').firstChild; - var range = goog.dom.Range.createFromNodeContents(ol); - assertEquals('Selection should have correct html fragment', - '1
  • 2', normalizeHtml(range.getHtmlFragment())); - - // TODO(robbyw): On IE the OL is included, on FF it is not. - //assertEquals('Selection should have correct valid html', - // '
  • 1
  • 2
  • ', normalizeHtml(range.getValidHtml())); - - assertEquals('Selection should have correct pastable html', - '
    1. 1
    2. 2
    ', - normalizeHtml(range.getPastableHtml())); -} - -function testCreateFromNodes() { - var start = goog.dom.getElement('test1').firstChild; - var end = goog.dom.getElement('br'); - var range = goog.dom.Range.createFromNodes(start, 2, end, 0); - assertNotNull('Browser range object can be created for W3C node range', - range); - - assertEquals('Start node should be selected at start endpoint', start, - range.getStartNode()); - assertEquals('Selection should start at offset 2', 2, - range.getStartOffset()); - assertEquals('Start node should be selected at anchor endpoint', start, - range.getAnchorNode()); - assertEquals('Selection should be anchored at offset 2', 2, - range.getAnchorOffset()); - - var div = goog.dom.getElement('test2'); - assertEquals('DIV node should be selected at end endpoint', div, - range.getEndNode()); - assertEquals('Selection should end at offset 1', 1, range.getEndOffset()); - assertEquals('DIV node should be selected at focus endpoint', div, - range.getFocusNode()); - assertEquals('Selection should be focused at offset 1', 1, - range.getFocusOffset()); - - - assertTrue('Text content should be "xt\\s*abc"', - /xt\s*abc/.test(range.getText())); - assertFalse('Nodes range is not collapsed', range.isCollapsed()); -} - - -function testCreateControlRange() { - if (!goog.userAgent.IE) { - return; - } - var cr = document.body.createControlRange(); - cr.addElement(goog.dom.getElement('logo')); - - var range = goog.dom.Range.createFromBrowserRange(cr); - assertNotNull('Control range object can be created from browser range', - range); - assertEquals('Created range is a control range', goog.dom.RangeType.CONTROL, - range.getType()); -} - - -function testTextNode() { - var range = goog.dom.Range.createFromNodeContents( - goog.dom.getElement('test1').firstChild); - - assertEquals('Created range is a text range', goog.dom.RangeType.TEXT, - range.getType()); - assertEquals('Text node should be selected at start endpoint', 'Text', - range.getStartNode().nodeValue); - assertEquals('Selection should start at offset 0', 0, - range.getStartOffset()); - - assertEquals('Text node should be selected at end endpoint', 'Text', - range.getEndNode().nodeValue); - assertEquals('Selection should end at offset 4', 'Text'.length, - range.getEndOffset()); - - assertEquals('Container should be text node', goog.dom.NodeType.TEXT, - range.getContainer().nodeType); - - assertEquals('Text content should be "Text"', 'Text', range.getText()); - assertFalse('Text range is not collapsed', range.isCollapsed()); -} - - -function testDiv() { - var range = goog.dom.Range.createFromNodeContents( - goog.dom.getElement('test2')); - - assertEquals('Text node "abc" should be selected at start endpoint', 'abc', - range.getStartNode().nodeValue); - assertEquals('Selection should start at offset 0', 0, - range.getStartOffset()); - - assertEquals('Text node "def" should be selected at end endpoint', 'def', - range.getEndNode().nodeValue); - assertEquals('Selection should end at offset 3', 'def'.length, - range.getEndOffset()); - - assertEquals('Container should be DIV', goog.dom.getElement('test2'), - range.getContainer()); - - assertTrue('Div text content should be "abc\\s*def"', - /abc\s*def/.test(range.getText())); - assertFalse('Div range is not collapsed', range.isCollapsed()); -} - - -function testEmptyNode() { - var range = goog.dom.Range.createFromNodeContents( - goog.dom.getElement('empty')); - - assertEquals('DIV be selected at start endpoint', - goog.dom.getElement('empty'), range.getStartNode()); - assertEquals('Selection should start at offset 0', 0, - range.getStartOffset()); - - assertEquals('DIV should be selected at end endpoint', - goog.dom.getElement('empty'), range.getEndNode()); - assertEquals('Selection should end at offset 0', 0, - range.getEndOffset()); - - assertEquals('Container should be DIV', goog.dom.getElement('empty'), - range.getContainer()); - - assertEquals('Empty text content should be ""', '', range.getText()); - assertTrue('Empty range is collapsed', range.isCollapsed()); -} - - -function testCollapse() { - var range = goog.dom.Range.createFromNodeContents( - goog.dom.getElement('test2')); - assertFalse('Div range is not collapsed', range.isCollapsed()); - range.collapse(); - assertTrue('Div range is collapsed after call to empty()', - range.isCollapsed()); - - range = goog.dom.Range.createFromNodeContents(goog.dom.getElement('empty')); - assertTrue('Empty range is collapsed', range.isCollapsed()); - range.collapse(); - assertTrue('Empty range is still collapsed', range.isCollapsed()); -} - -// TODO(robbyw): Test iteration over a strange document fragment. - -function testIterator() { - goog.testing.dom.assertNodesMatch(goog.dom.Range.createFromNodeContents( - goog.dom.getElement('test2')), ['abc', '#br', '#br', 'def']); -} - -function testReversedNodes() { - var node = goog.dom.getElement('test1').firstChild; - var range = goog.dom.Range.createFromNodes(node, 4, node, 0); - assertTrue('Range is reversed', range.isReversed()); - node = goog.dom.getElement('test3'); - range = goog.dom.Range.createFromNodes(node, 0, node, 1); - assertFalse('Range is not reversed', range.isReversed()); -} - -function testReversedContents() { - var range = goog.dom.Range.createFromNodeContents( - goog.dom.getElement('test1'), true); - assertTrue('Range is reversed', range.isReversed()); - assertEquals('Range should select "Text"', 'Text', - range.getText()); - assertEquals('Range start offset should be 0', 0, range.getStartOffset()); - assertEquals('Range end offset should be 4', 4, range.getEndOffset()); - assertEquals('Range anchor offset should be 4', 4, range.getAnchorOffset()); - assertEquals('Range focus offset should be 0', 0, range.getFocusOffset()); - - var range2 = range.clone(); - - range.collapse(true); - assertTrue('Range is collapsed', range.isCollapsed()); - assertFalse('Collapsed range is not reversed', range.isReversed()); - assertEquals('Post collapse start offset should be 4', 4, - range.getStartOffset()); - - range2.collapse(false); - assertTrue('Range 2 is collapsed', range2.isCollapsed()); - assertFalse('Collapsed range 2 is not reversed', range2.isReversed()); - assertEquals('Post collapse start offset 2 should be 0', 0, - range2.getStartOffset()); -} - -function testRemoveContents() { - var outer = goog.dom.getElement('removeTest'); - var range = goog.dom.Range.createFromNodeContents(outer.firstChild); - - range.removeContents(); - - assertEquals('Removed range content should be ""', '', range.getText()); - assertTrue('Removed range should be collapsed', range.isCollapsed()); - assertEquals('Outer div should have 1 child now', 1, - outer.childNodes.length); - assertEquals('Inner div should be empty', 0, - outer.firstChild.childNodes.length); -} - -function testRemovePartialContents() { - var outer = goog.dom.getElement('removePartialTest'); - var originalText = goog.dom.getTextContent(outer); - - try { - var range = goog.dom.Range.createFromNodes(outer.firstChild, 2, - outer.firstChild, 4); - removeHelper(1, range, outer, 1, '0145'); - - range = goog.dom.Range.createFromNodes(outer.firstChild, 0, - outer.firstChild, 1); - removeHelper(2, range, outer, 1, '145'); - - range = goog.dom.Range.createFromNodes(outer.firstChild, 2, - outer.firstChild, 3); - removeHelper(3, range, outer, 1, '14'); - - var br = goog.dom.createDom('BR'); - outer.appendChild(br); - range = goog.dom.Range.createFromNodes(outer.firstChild, 1, - outer, 1); - removeHelper(4, range, outer, 2, '1
    '); - - outer.innerHTML = '
    123'; - range = goog.dom.Range.createFromNodes(outer, 0, outer.lastChild, 2); - removeHelper(5, range, outer, 1, '3'); - - outer.innerHTML = '123
    456'; - range = goog.dom.Range.createFromNodes(outer.firstChild, 1, outer.lastChild, - 2); - removeHelper(6, range, outer, 2, '16'); - - outer.innerHTML = '123
    456'; - range = goog.dom.Range.createFromNodes(outer.firstChild, 0, outer.lastChild, - 2); - removeHelper(7, range, outer, 1, '6'); - - outer.innerHTML = '
    '; - range = goog.dom.Range.createFromNodeContents(outer.firstChild); - removeHelper(8, range, outer, 1, '
    '); - } finally { - // Restore the original text state for repeated runs. - goog.dom.setTextContent(outer, originalText); - } - - // TODO(robbyw): Fix the following edge cases: - // * Selecting contents of a node containing multiply empty divs - // * Selecting via createFromNodes(x, 0, x, x.childNodes.length) - // * Consistent handling of nodeContents(
    ).remove -} - -function removeHelper(testNumber, range, outer, expectedChildCount, - expectedContent) { - range.removeContents(); - assertTrue(testNumber + ': Removed range should now be collapsed', - range.isCollapsed()); - assertEquals(testNumber + ': Removed range content should be ""', '', - range.getText()); - assertEquals(testNumber + ': Outer div should contain correct text', - expectedContent, outer.innerHTML.toLowerCase()); - assertEquals(testNumber + ': Outer div should have ' + expectedChildCount + - ' children now', expectedChildCount, outer.childNodes.length); - assertNotNull(testNumber + ': Empty node should still exist', - goog.dom.getElement('empty')); -} - -function testSurroundContents() { - var outer = goog.dom.getElement('surroundTest'); - outer.innerHTML = '---Text that
    will be surrounded---'; - var range = goog.dom.Range.createFromNodes(outer.firstChild, 3, - outer.lastChild, outer.lastChild.nodeValue.length - 3); - - var div = goog.dom.createDom(goog.dom.TagName.DIV, {'style': 'color: red'}); - var output = range.surroundContents(div); - - assertEquals('Outer element should contain new element', outer, - output.parentNode); - assertFalse('New element should have no id', !!output.id); - assertEquals('New element should be red', 'red', output.style.color); - assertEquals('Outer element should have three children', 3, - outer.childNodes.length); - assertEquals('New element should have three children', 3, - output.childNodes.length); - - // TODO(robbyw): Ensure the range stays in a reasonable state. -} - - -/** - * Given two offsets into the 'foobar' node, make sure that inserting - * nodes at those offsets doesn't change a selection of 'oba'. - * @bug 1480638 - */ -function assertSurroundDoesntChangeSelectionWithOffsets( - offset1, offset2, expectedHtml) { - var div = goog.dom.getElement('bug1480638'); - div.innerHTML = 'foobar'; - var rangeToSelect = goog.dom.Range.createFromNodes( - div.firstChild, 2, div.firstChild, 5); - rangeToSelect.select(); - - var rangeToSurround = goog.dom.Range.createFromNodes( - div.firstChild, offset1, div.firstChild, offset2); - rangeToSurround.surroundWithNodes(goog.dom.createDom('span'), - goog.dom.createDom('span')); - - // Make sure that the selection didn't change. - assertHTMLEquals('Selection must not change when contents are surrounded.', - expectedHtml, goog.dom.Range.createFromWindow().getHtmlFragment()); -} - -function testSurroundWithNodesDoesntChangeSelection1() { - assertSurroundDoesntChangeSelectionWithOffsets(3, 4, - 'oba'); -} - -function testSurroundWithNodesDoesntChangeSelection2() { - assertSurroundDoesntChangeSelectionWithOffsets(3, 6, - 'oba'); -} - -function testSurroundWithNodesDoesntChangeSelection3() { - assertSurroundDoesntChangeSelectionWithOffsets(1, 3, - 'oba'); -} - -function testSurroundWithNodesDoesntChangeSelection4() { - assertSurroundDoesntChangeSelectionWithOffsets(1, 6, - 'oba'); -} - -function testInsertNode() { - var outer = goog.dom.getElement('insertTest'); - outer.innerHTML = 'ACD'; - - var range = goog.dom.Range.createFromNodes(outer.firstChild, 1, - outer.firstChild, 2); - range.insertNode(goog.dom.createTextNode('B'), true); - assertEquals('Element should have correct innerHTML', 'ABCD', - outer.innerHTML); - - outer.innerHTML = '12'; - range = goog.dom.Range.createFromNodes(outer.firstChild, 0, - outer.firstChild, 1); - var br = range.insertNode(goog.dom.createDom(goog.dom.TagName.BR), false); - assertEquals('New element should have correct innerHTML', '1
    2', - outer.innerHTML.toLowerCase()); - assertEquals('BR should be in outer', outer, br.parentNode); -} - -function testReplaceContentsWithNode() { - var outer = goog.dom.getElement('insertTest'); - outer.innerHTML = 'AXC'; - - var range = goog.dom.Range.createFromNodes(outer.firstChild, 1, - outer.firstChild, 2); - range.replaceContentsWithNode(goog.dom.createTextNode('B')); - assertEquals('Element should have correct innerHTML', 'ABC', - outer.innerHTML); - - outer.innerHTML = 'ABC'; - range = goog.dom.Range.createFromNodes(outer.firstChild, 3, - outer.firstChild, 3); - range.replaceContentsWithNode(goog.dom.createTextNode('D')); - assertEquals( - 'Element should have correct innerHTML after collapsed replace', - 'ABCD', outer.innerHTML); - - outer.innerHTML = 'AXXXC'; - range = goog.dom.Range.createFromNodes(outer.firstChild, 1, - outer.lastChild, 1); - range.replaceContentsWithNode(goog.dom.createTextNode('B')); - goog.testing.dom.assertHtmlContentsMatch('ABC', outer); -} - -function testSurroundWithNodes() { - var outer = goog.dom.getElement('insertTest'); - outer.innerHTML = 'ACE'; - var range = goog.dom.Range.createFromNodes(outer.firstChild, 1, - outer.firstChild, 2); - - range.surroundWithNodes(goog.dom.createTextNode('B'), - goog.dom.createTextNode('D')); - - assertEquals('New element should have correct innerHTML', 'ABCDE', - outer.innerHTML); -} - -function testIsRangeInDocument() { - var outer = goog.dom.getElement('insertTest'); - outer.innerHTML = '
    ABC'; - var range = goog.dom.Range.createCaret(outer.lastChild, 1); - - assertEquals('Should get correct start element', 'ABC', - range.getStartNode().nodeValue); - assertTrue('Should be considered in document', range.isRangeInDocument()); - - outer.innerHTML = 'DEF'; - - assertFalse('Should be marked as out of document', - range.isRangeInDocument()); -} - -function testRemovedNode() { - var node = goog.dom.getElement('removeNodeTest'); - var range = goog.dom.browserrange.createRangeFromNodeContents(node); - range.select(); - goog.dom.removeNode(node); - - var newRange = goog.dom.Range.createFromWindow(window); - - // In Chrome 14 and below (<= Webkit 535.1), newRange will be null. - // In Chrome 16 and above (>= Webkit 535.7), newRange will be collapsed - // like on other browsers. - // We didn't bother testing in between. - if (goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher('535.7')) { - assertNull('Webkit supports rangeCount == 0', newRange); - } else { - assertTrue('The other browsers will just have an empty range.', - newRange.isCollapsed()); - } -} - -function testReversedRange() { - goog.dom.Range.createFromNodes(goog.dom.getElement('test2'), 0, - goog.dom.getElement('test1'), 0).select(); - - var range = goog.dom.Range.createFromWindow(window); - assertTrue('Range should be reversed', - goog.userAgent.IE || range.isReversed()); -} - -function testUnreversedRange() { - goog.dom.Range.createFromNodes(goog.dom.getElement('test1'), 0, - goog.dom.getElement('test2'), 0).select(); - - var range = goog.dom.Range.createFromWindow(window); - assertFalse('Range should not be reversed', range.isReversed()); -} - -function testReversedThenUnreversedRange() { - // This tests a workaround for a webkit bug where webkit caches selections - // incorrectly. - goog.dom.Range.createFromNodes(goog.dom.getElement('test2'), 0, - goog.dom.getElement('test1'), 0).select(); - goog.dom.Range.createFromNodes(goog.dom.getElement('test1'), 0, - goog.dom.getElement('test2'), 0).select(); - - var range = goog.dom.Range.createFromWindow(window); - assertFalse('Range should not be reversed', range.isReversed()); -} - -function testHasAndClearSelection() { - goog.dom.Range.createFromNodeContents( - goog.dom.getElement('test1')).select(); - - assertTrue('Selection should exist', goog.dom.Range.hasSelection()); - - goog.dom.Range.clearSelection(); - - assertFalse('Selection should not exist', goog.dom.Range.hasSelection()); -} - -function assertForward(string, startNode, startOffset, endNode, endOffset) { - var root = goog.dom.getElement('test2'); - var originalInnerHtml = root.innerHTML; - - assertFalse(string, goog.dom.Range.isReversed(startNode, startOffset, - endNode, endOffset)); - assertTrue(string, goog.dom.Range.isReversed(endNode, endOffset, - startNode, startOffset)); - assertEquals('Contents should be unaffected after: ' + string, - root.innerHTML, originalInnerHtml); -} - -function testIsReversed() { - var root = goog.dom.getElement('test2'); - var text1 = root.firstChild; // Text content: 'abc'. - var br = root.childNodes[1]; - var text2 = root.lastChild; // Text content: 'def'. - - assertFalse('Same element position gives false', goog.dom.Range.isReversed( - root, 0, root, 0)); - assertFalse('Same text position gives false', goog.dom.Range.isReversed( - text1, 0, text2, 0)); - assertForward('Element offsets should compare against each other', - root, 0, root, 2); - assertForward('Text node offsets should compare against each other', - text1, 0, text2, 2); - assertForward('Text nodes should compare correctly', - text1, 0, text2, 0); - assertForward('Text nodes should compare to later elements', - text1, 0, br, 0); - assertForward('Text nodes should compare to earlier elements', - br, 0, text2, 0); - assertForward('Parent is before element child', root, 0, br, 0); - assertForward('Parent is before text child', root, 0, text1, 0); - assertFalse('Equivalent position gives false', goog.dom.Range.isReversed( - root, 0, text1, 0)); - assertFalse('Equivalent position gives false', goog.dom.Range.isReversed( - root, 1, br, 0)); - assertForward('End of element is after children', text1, 0, root, 3); - assertForward('End of element is after children', br, 0, root, 3); - assertForward('End of element is after children', text2, 0, root, 3); - assertForward('End of element is after end of last child', - text2, 3, root, 3); -} - -function testSelectAroundSpaces() { - // set the selection - var textNode = goog.dom.getElement('textWithSpaces').firstChild; - goog.dom.TextRange.createFromNodes( - textNode, 5, textNode, 12).select(); - - // get the selection and check that it matches what we set it to - var range = goog.dom.Range.createFromWindow(); - assertEquals(' world ', range.getText()); - assertEquals(5, range.getStartOffset()); - assertEquals(12, range.getEndOffset()); - assertEquals(textNode, range.getContainer()); - - // Check the contents again, because there used to be a bug where - // it changed after calling getContainer(). - assertEquals(' world ', range.getText()); -} - -function testSelectInsideSpaces() { - // set the selection - var textNode = goog.dom.getElement('textWithSpaces').firstChild; - goog.dom.TextRange.createFromNodes( - textNode, 6, textNode, 11).select(); - - // get the selection and check that it matches what we set it to - var range = goog.dom.Range.createFromWindow(); - assertEquals('world', range.getText()); - assertEquals(6, range.getStartOffset()); - assertEquals(11, range.getEndOffset()); - assertEquals(textNode, range.getContainer()); - - // Check the contents again, because there used to be a bug where - // it changed after calling getContainer(). - assertEquals('world', range.getText()); -} - -function testRangeBeforeBreak() { - var container = goog.dom.getElement('rangeAroundBreaks'); - var text = container.firstChild; - var offset = text.length; - assertEquals(4, offset); - - var br = container.childNodes[1]; - var caret = goog.dom.Range.createCaret(text, offset); - caret.select(); - assertEquals(offset, caret.getStartOffset()); - - var range = goog.dom.Range.createFromWindow(); - assertFalse('Should not contain whole
    ', - range.containsNode(br, false)); - if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9)) { - assertTrue('Range over
    is adjacent to the immediate range before it', - range.containsNode(br, true)); - } else { - assertFalse('Should not contain partial
    ', - range.containsNode(br, true)); - } - - assertEquals(offset, range.getStartOffset()); - assertEquals(text, range.getStartNode()); -} - -function testRangeAfterBreak() { - var container = goog.dom.getElement('rangeAroundBreaks'); - var br = container.childNodes[1]; - var caret = goog.dom.Range.createCaret(container.lastChild, 0); - caret.select(); - assertEquals(0, caret.getStartOffset()); - - var range = goog.dom.Range.createFromWindow(); - assertFalse('Should not contain whole
    ', - range.containsNode(br, false)); - var isSafari3 = - goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher('528'); - - if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9) || - isSafari3) { - assertTrue('Range over
    is adjacent to the immediate range after it', - range.containsNode(br, true)); - } else { - assertFalse('Should not contain partial
    ', - range.containsNode(br, true)); - } - - if (isSafari3) { - assertEquals(2, range.getStartOffset()); - assertEquals(container, range.getStartNode()); - } else { - assertEquals(0, range.getStartOffset()); - assertEquals(container.lastChild, range.getStartNode()); - } -} - -function testRangeAtBreakAtStart() { - var container = goog.dom.getElement('breaksAroundNode'); - var br = container.firstChild; - var caret = goog.dom.Range.createCaret(container.firstChild, 0); - caret.select(); - assertEquals(0, caret.getStartOffset()); - - var range = goog.dom.Range.createFromWindow(); - assertTrue('Range over
    is adjacent to the immediate range before it', - range.containsNode(br, true)); - assertFalse('Should not contain whole
    ', - range.containsNode(br, false)); - - assertRangeEquals(container, 0, container, 0, range); -} - -function testFocusedElementDisappears() { - // This reproduces a failure case specific to Gecko, where an element is - // created, contentEditable is set, is focused, and removed. After that - // happens, calling selection.collapse fails. - // https://bugzilla.mozilla.org/show_bug.cgi?id=773137 - var disappearingElement = goog.dom.createDom('div'); - document.body.appendChild(disappearingElement); - disappearingElement.contentEditable = true; - disappearingElement.focus(); - document.body.removeChild(disappearingElement); - var container = goog.dom.getElement('empty'); - var caret = goog.dom.Range.createCaret(container, 0); - // This should not throw. - caret.select(); - assertEquals(0, caret.getStartOffset()); -} - -function assertNodeEquals(expected, actual) { - assertEquals( - 'Expected: ' + goog.testing.dom.exposeNode(expected) + - '\nActual: ' + goog.testing.dom.exposeNode(actual), - expected, actual); -} diff --git a/src/database/third_party/closure-library/closure/goog/dom/rangeendpoint.js b/src/database/third_party/closure-library/closure/goog/dom/rangeendpoint.js deleted file mode 100644 index f8d0fe446c9..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/rangeendpoint.js +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Simple struct for endpoints of a range. - * - * @author robbyw@google.com (Robby Walker) - */ - - -goog.provide('goog.dom.RangeEndpoint'); - - -/** - * Constants for selection endpoints. - * @enum {number} - */ -goog.dom.RangeEndpoint = { - START: 1, - END: 0 -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/safe.js b/src/database/third_party/closure-library/closure/goog/dom/safe.js deleted file mode 100644 index 0d236bdab74..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/safe.js +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright 2013 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Type-safe wrappers for unsafe DOM APIs. - * - * This file provides type-safe wrappers for DOM APIs that can result in - * cross-site scripting (XSS) vulnerabilities, if the API is supplied with - * untrusted (attacker-controlled) input. Instead of plain strings, the type - * safe wrappers consume values of types from the goog.html package whose - * contract promises that values are safe to use in the corresponding context. - * - * Hence, a program that exclusively uses the wrappers in this file (i.e., whose - * only reference to security-sensitive raw DOM APIs are in this file) is - * guaranteed to be free of XSS due to incorrect use of such DOM APIs (modulo - * correctness of code that produces values of the respective goog.html types, - * and absent code that violates type safety). - * - * For example, assigning to an element's .innerHTML property a string that is - * derived (even partially) from untrusted input typically results in an XSS - * vulnerability. The type-safe wrapper goog.html.setInnerHtml consumes a value - * of type goog.html.SafeHtml, whose contract states that using its values in a - * HTML context will not result in XSS. Hence a program that is free of direct - * assignments to any element's innerHTML property (with the exception of the - * assignment to .innerHTML in this file) is guaranteed to be free of XSS due to - * assignment of untrusted strings to the innerHTML property. - */ - -goog.provide('goog.dom.safe'); - -goog.require('goog.html.SafeHtml'); -goog.require('goog.html.SafeUrl'); - - -/** - * Assigns known-safe HTML to an element's innerHTML property. - * @param {!Element} elem The element whose innerHTML is to be assigned to. - * @param {!goog.html.SafeHtml} html The known-safe HTML to assign. - */ -goog.dom.safe.setInnerHtml = function(elem, html) { - elem.innerHTML = goog.html.SafeHtml.unwrap(html); -}; - - -/** - * Assigns known-safe HTML to an element's outerHTML property. - * @param {!Element} elem The element whose outerHTML is to be assigned to. - * @param {!goog.html.SafeHtml} html The known-safe HTML to assign. - */ -goog.dom.safe.setOuterHtml = function(elem, html) { - elem.outerHTML = goog.html.SafeHtml.unwrap(html); -}; - - -/** - * Writes known-safe HTML to a document. - * @param {!Document} doc The document to be written to. - * @param {!goog.html.SafeHtml} html The known-safe HTML to assign. - */ -goog.dom.safe.documentWrite = function(doc, html) { - doc.write(goog.html.SafeHtml.unwrap(html)); -}; - - -/** - * Safely assigns a URL to an anchor element's href property. - * - * If url is of type goog.html.SafeUrl, its value is unwrapped and assigned to - * anchor's href property. If url is of type string however, it is first - * sanitized using goog.html.SafeUrl.sanitize. - * - * Example usage: - * goog.dom.safe.setAnchorHref(anchorEl, url); - * which is a safe alternative to - * anchorEl.href = url; - * The latter can result in XSS vulnerabilities if url is a - * user-/attacker-controlled value. - * - * @param {!HTMLAnchorElement} anchor The anchor element whose href property - * is to be assigned to. - * @param {string|!goog.html.SafeUrl} url The URL to assign. - * @see goog.html.SafeUrl#sanitize - */ -goog.dom.safe.setAnchorHref = function(anchor, url) { - /** @type {!goog.html.SafeUrl} */ - var safeUrl; - if (url instanceof goog.html.SafeUrl) { - safeUrl = url; - } else { - safeUrl = goog.html.SafeUrl.sanitize(url); - } - anchor.href = goog.html.SafeUrl.unwrap(safeUrl); -}; - - -/** - * Safely assigns a URL to a Location object's href property. - * - * If url is of type goog.html.SafeUrl, its value is unwrapped and assigned to - * loc's href property. If url is of type string however, it is first sanitized - * using goog.html.SafeUrl.sanitize. - * - * Example usage: - * goog.dom.safe.setLocationHref(document.location, redirectUrl); - * which is a safe alternative to - * document.location.href = redirectUrl; - * The latter can result in XSS vulnerabilities if redirectUrl is a - * user-/attacker-controlled value. - * - * @param {!Location} loc The Location object whose href property is to be - * assigned to. - * @param {string|!goog.html.SafeUrl} url The URL to assign. - * @see goog.html.SafeUrl#sanitize - */ -goog.dom.safe.setLocationHref = function(loc, url) { - /** @type {!goog.html.SafeUrl} */ - var safeUrl; - if (url instanceof goog.html.SafeUrl) { - safeUrl = url; - } else { - safeUrl = goog.html.SafeUrl.sanitize(url); - } - loc.href = goog.html.SafeUrl.unwrap(safeUrl); -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/safe_test.html b/src/database/third_party/closure-library/closure/goog/dom/safe_test.html deleted file mode 100644 index 467f3dd3aa8..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/safe_test.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - -Closure Unit Tests - goog.dom.safe - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/safe_test.js b/src/database/third_party/closure-library/closure/goog/dom/safe_test.js deleted file mode 100644 index b96567d4d5a..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/safe_test.js +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2013 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.dom.safeTest'); -goog.setTestOnly('goog.dom.safeTest'); - -goog.require('goog.dom.safe'); -goog.require('goog.html.SafeUrl'); -goog.require('goog.html.testing'); -goog.require('goog.string.Const'); -goog.require('goog.testing.jsunit'); - -function testSetInnerHtml() { - var mockElement = { - 'innerHTML': 'blarg' - }; - var html = ' - - - -
    - abc -
    def
    - ghi -
    jkl
    - mno -
    pqr
    - stu -
    - -
    - abc -
    def
    - ghi -
    jkl
    - mno -
    pqr
    - stu -
    - -
    - abc -
    def
    - ghi -
    jkl
    - mno -
    pqr
    - stu -
    - -
    - abc -
    def
    - ghi -
    jkl
    - mno -
    pqr
    - stu -
    - -
    - abc -
    def
    - ghi -
    jkl
    - mno -
    pqr
    - stu -
    - -
    foo
    bar
    baz
    - - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/savedcaretrange_test.js b/src/database/third_party/closure-library/closure/goog/dom/savedcaretrange_test.js deleted file mode 100644 index 577d49741ef..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/savedcaretrange_test.js +++ /dev/null @@ -1,224 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.dom.SavedCaretRangeTest'); -goog.setTestOnly('goog.dom.SavedCaretRangeTest'); - -goog.require('goog.dom'); -goog.require('goog.dom.Range'); -goog.require('goog.dom.SavedCaretRange'); -goog.require('goog.testing.dom'); -goog.require('goog.testing.jsunit'); -goog.require('goog.userAgent'); - -function setUp() { - document.body.normalize(); -} - - -/** @bug 1480638 */ -function testSavedCaretRangeDoesntChangeSelection() { - // NOTE(nicksantos): We cannot detect this bug programatically. The only - // way to detect it is to run this test manually and look at the selection - // when it ends. - var div = goog.dom.getElement('bug1480638'); - var range = goog.dom.Range.createFromNodes( - div.firstChild, 0, div.lastChild, 1); - range.select(); - - // Observe visible selection. Then move to next line and see it change. - // If the bug exists, it starts with "foo" selected and ends with - // it not selected. - //debugger; - var saved = range.saveUsingCarets(); -} - -function testSavedCaretRange() { - if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(8)) { - // testSavedCaretRange fails in IE7 unless the source files are loaded in a - // certain order. Adding goog.require('goog.dom.classes') to dom.js or - // goog.require('goog.array') to savedcaretrange_test.js after the - // goog.require('goog.dom') line fixes the test, but it's better to not - // rely on such hacks without understanding the reason of the failure. - return; - } - - var parent = goog.dom.getElement('caretRangeTest'); - var def = goog.dom.getElement('def'); - var jkl = goog.dom.getElement('jkl'); - - var range = goog.dom.Range.createFromNodes( - def.firstChild, 1, jkl.firstChild, 2); - assertFalse(range.isReversed()); - range.select(); - - var saved = range.saveUsingCarets(); - assertHTMLEquals( - 'def', def.innerHTML); - assertHTMLEquals( - 'jkl', jkl.innerHTML); - - goog.testing.dom.assertRangeEquals( - def.childNodes[1], 0, jkl.childNodes[1], 0, - saved.toAbstractRange()); - - def = goog.dom.getElement('def'); - jkl = goog.dom.getElement('jkl'); - - var restoredRange = clearSelectionAndRestoreSaved(parent, saved); - assertFalse(restoredRange.isReversed()); - goog.testing.dom.assertRangeEquals(def, 1, jkl, 1, restoredRange); - - var selection = goog.dom.Range.createFromWindow(window); - assertHTMLEquals('def', def.innerHTML); - assertHTMLEquals('jkl', jkl.innerHTML); - - // def and jkl now contain fragmented text nodes. - if (goog.userAgent.WEBKIT || - (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9'))) { - goog.testing.dom.assertRangeEquals( - def.childNodes[1], 0, jkl.childNodes[0], 2, selection); - } else if (goog.userAgent.OPERA) { - goog.testing.dom.assertRangeEquals( - def.childNodes[1], 0, jkl.childNodes[1], 0, selection); - } else { - goog.testing.dom.assertRangeEquals( - def, 1, jkl, 1, selection); - } -} - -function testReversedSavedCaretRange() { - var parent = goog.dom.getElement('caretRangeTest'); - var def = goog.dom.getElement('def-5'); - var jkl = goog.dom.getElement('jkl-5'); - - var range = goog.dom.Range.createFromNodes( - jkl.firstChild, 1, def.firstChild, 2); - assertTrue(range.isReversed()); - range.select(); - - var saved = range.saveUsingCarets(); - var restoredRange = clearSelectionAndRestoreSaved(parent, saved); - assertTrue(restoredRange.isReversed()); - goog.testing.dom.assertRangeEquals(def, 1, jkl, 1, restoredRange); -} - -/* - TODO(user): Look into why removeCarets test doesn't pass. - function testRemoveCarets() { - var def = goog.dom.getElement('def'); - var jkl = goog.dom.getElement('jkl'); - - var range = goog.dom.Range.createFromNodes( - def.firstChild, 1, jkl.firstChild, 2); - range.select(); - - var saved = range.saveUsingCarets(); - assertHTMLEquals( - "def", def.innerHTML); - assertHTMLEquals( - "jkl", jkl.innerHTML); - - saved.removeCarets(); - assertHTMLEquals("def", def.innerHTML); - assertHTMLEquals("jkl", jkl.innerHTML); - - var selection = goog.dom.Range.createFromWindow(window); - - assertEquals('Wrong start node', def.firstChild, selection.getStartNode()); - assertEquals('Wrong end node', jkl.firstChild, selection.getEndNode()); - assertEquals('Wrong start offset', 1, selection.getStartOffset()); - assertEquals('Wrong end offset', 2, selection.getEndOffset()); - } - */ - -function testRemoveContents() { - var def = goog.dom.getElement('def-4'); - var jkl = goog.dom.getElement('jkl-4'); - - // Sanity check. - var container = goog.dom.getElement('removeContentsTest'); - assertEquals(7, container.childNodes.length); - assertEquals('def', def.innerHTML); - assertEquals('jkl', jkl.innerHTML); - - var range = goog.dom.Range.createFromNodes( - def.firstChild, 1, jkl.firstChild, 2); - range.select(); - - var saved = range.saveUsingCarets(); - var restored = saved.restore(); - restored.removeContents(); - - assertEquals(6, container.childNodes.length); - assertEquals('d', def.innerHTML); - assertEquals('l', jkl.innerHTML); -} - -function testHtmlEqual() { - var parent = goog.dom.getElement('caretRangeTest-2'); - var def = goog.dom.getElement('def-2'); - var jkl = goog.dom.getElement('jkl-2'); - - var range = goog.dom.Range.createFromNodes( - def.firstChild, 1, jkl.firstChild, 2); - range.select(); - var saved = range.saveUsingCarets(); - var html1 = parent.innerHTML; - saved.removeCarets(); - - var saved2 = range.saveUsingCarets(); - var html2 = parent.innerHTML; - saved2.removeCarets(); - - assertNotEquals('Same selection with different saved caret range carets ' + - 'must have different html.', html1, html2); - - assertTrue('Same selection with different saved caret range carets must ' + - 'be considered equal by htmlEqual', - goog.dom.SavedCaretRange.htmlEqual(html1, html2)); - - saved.dispose(); - saved2.dispose(); -} - -function testStartCaretIsAtEndOfParent() { - var parent = goog.dom.getElement('caretRangeTest-3'); - var def = goog.dom.getElement('def-3'); - var jkl = goog.dom.getElement('jkl-3'); - - var range = goog.dom.Range.createFromNodes( - def, 1, jkl, 1); - range.select(); - var saved = range.saveUsingCarets(); - clearSelectionAndRestoreSaved(parent, saved); - range = goog.dom.Range.createFromWindow(); - assertEquals('ghijkl', range.getText().replace(/\s/g, '')); -} - - -/** - * Clear the selection by re-parsing the DOM. Then restore the saved - * selection. - * @param {Node} parent The node containing the current selection. - * @param {goog.dom.SavedRange} saved The saved range. - * @return {goog.dom.AbstractRange} Restored range. - */ -function clearSelectionAndRestoreSaved(parent, saved) { - goog.dom.Range.clearSelection(); - assertFalse(goog.dom.Range.hasSelection(window)); - var range = saved.restore(); - assertTrue(goog.dom.Range.hasSelection(window)); - return range; -} diff --git a/src/database/third_party/closure-library/closure/goog/dom/savedrange.js b/src/database/third_party/closure-library/closure/goog/dom/savedrange.js deleted file mode 100644 index 5a7e9513472..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/savedrange.js +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview A generic interface for saving and restoring ranges. - * - * @author robbyw@google.com (Robby Walker) - */ - - -goog.provide('goog.dom.SavedRange'); - -goog.require('goog.Disposable'); -goog.require('goog.log'); - - - -/** - * Abstract interface for a saved range. - * @constructor - * @extends {goog.Disposable} - */ -goog.dom.SavedRange = function() { - goog.Disposable.call(this); -}; -goog.inherits(goog.dom.SavedRange, goog.Disposable); - - -/** - * Logging object. - * @type {goog.log.Logger} - * @private - */ -goog.dom.SavedRange.logger_ = - goog.log.getLogger('goog.dom.SavedRange'); - - -/** - * Restores the range and by default disposes of the saved copy. Take note: - * this means the by default SavedRange objects are single use objects. - * @param {boolean=} opt_stayAlive Whether this SavedRange should stay alive - * (not be disposed) after restoring the range. Defaults to false (dispose). - * @return {goog.dom.AbstractRange} The restored range. - */ -goog.dom.SavedRange.prototype.restore = function(opt_stayAlive) { - if (this.isDisposed()) { - goog.log.error(goog.dom.SavedRange.logger_, - 'Disposed SavedRange objects cannot be restored.'); - } - - var range = this.restoreInternal(); - if (!opt_stayAlive) { - this.dispose(); - } - return range; -}; - - -/** - * Internal method to restore the saved range. - * @return {goog.dom.AbstractRange} The restored range. - */ -goog.dom.SavedRange.prototype.restoreInternal = goog.abstractMethod; diff --git a/src/database/third_party/closure-library/closure/goog/dom/savedrange_test.html b/src/database/third_party/closure-library/closure/goog/dom/savedrange_test.html deleted file mode 100644 index 8856ae20bf0..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/savedrange_test.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - -Closure Unit Tests - goog.dom.SavedRange - - - - -
    Text
    - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/savedrange_test.js b/src/database/third_party/closure-library/closure/goog/dom/savedrange_test.js deleted file mode 100644 index bc9be67fbb1..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/savedrange_test.js +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.dom.SavedRangeTest'); -goog.setTestOnly('goog.dom.SavedRangeTest'); - -goog.require('goog.dom'); -goog.require('goog.dom.Range'); -goog.require('goog.testing.jsunit'); -goog.require('goog.userAgent'); - -function testSaved() { - var node = goog.dom.getElement('test1'); - var range = goog.dom.Range.createFromNodeContents(node); - var savedRange = range.saveUsingDom(); - - range = savedRange.restore(true); - assertEquals('Restored range should select "Text"', 'Text', - range.getText()); - assertFalse('Restored range should not be reversed.', range.isReversed()); - assertFalse('Range should not have disposed itself.', - savedRange.isDisposed()); - - goog.dom.Range.clearSelection(); - assertFalse(goog.dom.Range.hasSelection(window)); - - range = savedRange.restore(); - assertTrue('Range should have auto-disposed.', savedRange.isDisposed()); - assertEquals('Restored range should select "Text"', 'Text', - range.getText()); - assertFalse('Restored range should not be reversed.', range.isReversed()); -} - -function testReversedSave() { - var node = goog.dom.getElement('test1').firstChild; - var range = goog.dom.Range.createFromNodes(node, 4, node, 0); - var savedRange = range.saveUsingDom(); - - range = savedRange.restore(); - assertEquals('Restored range should select "Text"', 'Text', - range.getText()); - if (!goog.userAgent.IE) { - assertTrue('Restored range should be reversed.', range.isReversed()); - } -} diff --git a/src/database/third_party/closure-library/closure/goog/dom/selection.js b/src/database/third_party/closure-library/closure/goog/dom/selection.js deleted file mode 100644 index 85937e7a75b..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/selection.js +++ /dev/null @@ -1,471 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utilities for working with selections in input boxes and text - * areas. - * - * @author arv@google.com (Erik Arvidsson) - * @see ../demos/dom_selection.html - */ - - -goog.provide('goog.dom.selection'); - -goog.require('goog.string'); -goog.require('goog.userAgent'); - - -/** - * Sets the place where the selection should start inside a textarea or a text - * input - * @param {Element} textfield A textarea or text input. - * @param {number} pos The position to set the start of the selection at. - */ -goog.dom.selection.setStart = function(textfield, pos) { - if (goog.dom.selection.useSelectionProperties_(textfield)) { - textfield.selectionStart = pos; - } else if (goog.userAgent.IE) { - // destructuring assignment would have been sweet - var tmp = goog.dom.selection.getRangeIe_(textfield); - var range = tmp[0]; - var selectionRange = tmp[1]; - - if (range.inRange(selectionRange)) { - pos = goog.dom.selection.canonicalizePositionIe_(textfield, pos); - - range.collapse(true); - range.move('character', pos); - range.select(); - } - } -}; - - -/** - * Return the place where the selection starts inside a textarea or a text - * input - * @param {Element} textfield A textarea or text input. - * @return {number} The position where the selection starts or 0 if it was - * unable to find the position or no selection exists. Note that we can't - * reliably tell the difference between an element that has no selection and - * one where it starts at 0. - */ -goog.dom.selection.getStart = function(textfield) { - return goog.dom.selection.getEndPoints_(textfield, true)[0]; -}; - - -/** - * Returns the start and end points of the selection within a textarea in IE. - * IE treats newline characters as \r\n characters, and we need to check for - * these characters at the edge of our selection, to ensure that we return the - * right cursor position. - * @param {TextRange} range Complete range object, e.g., "Hello\r\n". - * @param {TextRange} selRange Selected range object. - * @param {boolean} getOnlyStart Value indicating if only start - * cursor position is to be returned. In IE, obtaining the end position - * involves extra work, hence we have this parameter for calls which need - * only start position. - * @return {!Array} An array with the start and end positions where the - * selection starts and ends or [0,0] if it was unable to find the - * positions or no selection exists. Note that we can't reliably tell the - * difference between an element that has no selection and one where - * it starts and ends at 0. If getOnlyStart was true, we return - * -1 as end offset. - * @private - */ -goog.dom.selection.getEndPointsTextareaIe_ = function( - range, selRange, getOnlyStart) { - // Create a duplicate of the selected range object to perform our actions - // against. Example of selectionRange = "" (assuming that the cursor is - // just after the \r\n combination) - var selectionRange = selRange.duplicate(); - - // Text before the selection start, e.g.,"Hello" (notice how range.text - // excludes the \r\n sequence) - var beforeSelectionText = range.text; - // Text before the selection start, e.g., "Hello" (this will later include - // the \r\n sequences also) - var untrimmedBeforeSelectionText = beforeSelectionText; - // Text within the selection , e.g. "" assuming that the cursor is just after - // the \r\n combination. - var selectionText = selectionRange.text; - // Text within the selection, e.g., "" (this will later include the \r\n - // sequences also) - var untrimmedSelectionText = selectionText; - - // Boolean indicating whether we are done dealing with the text before the - // selection's beginning. - var isRangeEndTrimmed = false; - // Go over the range until it becomes a 0-lengthed range or until the range - // text starts changing when we move the end back by one character. - // If after moving the end back by one character, the text remains the same, - // then we need to add a "\r\n" at the end to get the actual text. - while (!isRangeEndTrimmed) { - if (range.compareEndPoints('StartToEnd', range) == 0) { - isRangeEndTrimmed = true; - } else { - range.moveEnd('character', -1); - if (range.text == beforeSelectionText) { - // If the start position of the cursor was after a \r\n string, - // we would skip over it in one go with the moveEnd call, but - // range.text will still show "Hello" (because of the IE range.text - // bug) - this implies that we should add a \r\n to our - // untrimmedBeforeSelectionText string. - untrimmedBeforeSelectionText += '\r\n'; - } else { - isRangeEndTrimmed = true; - } - } - } - - if (getOnlyStart) { - // We return -1 as end, since the caller is only interested in the start - // value. - return [untrimmedBeforeSelectionText.length, -1]; - } - // Boolean indicating whether we are done dealing with the text inside the - // selection. - var isSelectionRangeEndTrimmed = false; - // Go over the selected range until it becomes a 0-lengthed range or until - // the range text starts changing when we move the end back by one character. - // If after moving the end back by one character, the text remains the same, - // then we need to add a "\r\n" at the end to get the actual text. - while (!isSelectionRangeEndTrimmed) { - if (selectionRange.compareEndPoints('StartToEnd', selectionRange) == 0) { - isSelectionRangeEndTrimmed = true; - } else { - selectionRange.moveEnd('character', -1); - if (selectionRange.text == selectionText) { - // If the selection was not empty, and the end point of the selection - // was just after a \r\n, we would have skipped it in one go with the - // moveEnd call, and this implies that we should add a \r\n to the - // untrimmedSelectionText string. - untrimmedSelectionText += '\r\n'; - } else { - isSelectionRangeEndTrimmed = true; - } - } - } - return [ - untrimmedBeforeSelectionText.length, - untrimmedBeforeSelectionText.length + untrimmedSelectionText.length]; -}; - - -/** - * Returns the start and end points of the selection inside a textarea or a - * text input. - * @param {Element} textfield A textarea or text input. - * @return {!Array} An array with the start and end positions where the - * selection starts and ends or [0,0] if it was unable to find the - * positions or no selection exists. Note that we can't reliably tell the - * difference between an element that has no selection and one where - * it starts and ends at 0. - */ -goog.dom.selection.getEndPoints = function(textfield) { - return goog.dom.selection.getEndPoints_(textfield, false); -}; - - -/** - * Returns the start and end points of the selection inside a textarea or a - * text input. - * @param {Element} textfield A textarea or text input. - * @param {boolean} getOnlyStart Value indicating if only start - * cursor position is to be returned. In IE, obtaining the end position - * involves extra work, hence we have this parameter. In FF, there is not - * much extra effort involved. - * @return {!Array} An array with the start and end positions where the - * selection starts and ends or [0,0] if it was unable to find the - * positions or no selection exists. Note that we can't reliably tell the - * difference between an element that has no selection and one where - * it starts and ends at 0. If getOnlyStart was true, we return - * -1 as end offset. - * @private - */ -goog.dom.selection.getEndPoints_ = function(textfield, getOnlyStart) { - var startPos = 0; - var endPos = 0; - if (goog.dom.selection.useSelectionProperties_(textfield)) { - startPos = textfield.selectionStart; - endPos = getOnlyStart ? -1 : textfield.selectionEnd; - } else if (goog.userAgent.IE) { - var tmp = goog.dom.selection.getRangeIe_(textfield); - var range = tmp[0]; - var selectionRange = tmp[1]; - - if (range.inRange(selectionRange)) { - range.setEndPoint('EndToStart', selectionRange); - if (textfield.type == 'textarea') { - return goog.dom.selection.getEndPointsTextareaIe_( - range, selectionRange, getOnlyStart); - } - startPos = range.text.length; - if (!getOnlyStart) { - endPos = range.text.length + selectionRange.text.length; - } else { - endPos = -1; // caller did not ask for end position - } - } - } - return [startPos, endPos]; -}; - - -/** - * Sets the place where the selection should end inside a text area or a text - * input - * @param {Element} textfield A textarea or text input. - * @param {number} pos The position to end the selection at. - */ -goog.dom.selection.setEnd = function(textfield, pos) { - if (goog.dom.selection.useSelectionProperties_(textfield)) { - textfield.selectionEnd = pos; - } else if (goog.userAgent.IE) { - var tmp = goog.dom.selection.getRangeIe_(textfield); - var range = tmp[0]; - var selectionRange = tmp[1]; - - if (range.inRange(selectionRange)) { - // Both the current position and the start cursor position need - // to be canonicalized to take care of possible \r\n miscounts. - pos = goog.dom.selection.canonicalizePositionIe_(textfield, pos); - var startCursorPos = goog.dom.selection.canonicalizePositionIe_( - textfield, goog.dom.selection.getStart(textfield)); - - selectionRange.collapse(true); - selectionRange.moveEnd('character', pos - startCursorPos); - selectionRange.select(); - } - } -}; - - -/** - * Returns the place where the selection ends inside a textarea or a text input - * @param {Element} textfield A textarea or text input. - * @return {number} The position where the selection ends or 0 if it was - * unable to find the position or no selection exists. - */ -goog.dom.selection.getEnd = function(textfield) { - return goog.dom.selection.getEndPoints_(textfield, false)[1]; -}; - - -/** - * Sets the cursor position within a textfield. - * @param {Element} textfield A textarea or text input. - * @param {number} pos The position within the text field. - */ -goog.dom.selection.setCursorPosition = function(textfield, pos) { - if (goog.dom.selection.useSelectionProperties_(textfield)) { - // Mozilla directly supports this - textfield.selectionStart = pos; - textfield.selectionEnd = pos; - - } else if (goog.userAgent.IE) { - pos = goog.dom.selection.canonicalizePositionIe_(textfield, pos); - - // IE has textranges. A textfield's textrange encompasses the - // entire textfield's text by default - var sel = textfield.createTextRange(); - - sel.collapse(true); - sel.move('character', pos); - sel.select(); - } -}; - - -/** - * Sets the selected text inside a textarea or a text input - * @param {Element} textfield A textarea or text input. - * @param {string} text The text to change the selection to. - */ -goog.dom.selection.setText = function(textfield, text) { - if (goog.dom.selection.useSelectionProperties_(textfield)) { - var value = textfield.value; - var oldSelectionStart = textfield.selectionStart; - var before = value.substr(0, oldSelectionStart); - var after = value.substr(textfield.selectionEnd); - textfield.value = before + text + after; - textfield.selectionStart = oldSelectionStart; - textfield.selectionEnd = oldSelectionStart + text.length; - } else if (goog.userAgent.IE) { - var tmp = goog.dom.selection.getRangeIe_(textfield); - var range = tmp[0]; - var selectionRange = tmp[1]; - - if (!range.inRange(selectionRange)) { - return; - } - // When we set the selection text the selection range is collapsed to the - // end. We therefore duplicate the current selection so we know where it - // started. Once we've set the selection text we move the start of the - // selection range to the old start - var range2 = selectionRange.duplicate(); - selectionRange.text = text; - selectionRange.setEndPoint('StartToStart', range2); - selectionRange.select(); - } else { - throw Error('Cannot set the selection end'); - } -}; - - -/** - * Returns the selected text inside a textarea or a text input - * @param {Element} textfield A textarea or text input. - * @return {string} The selected text. - */ -goog.dom.selection.getText = function(textfield) { - if (goog.dom.selection.useSelectionProperties_(textfield)) { - var s = textfield.value; - return s.substring(textfield.selectionStart, textfield.selectionEnd); - } - - if (goog.userAgent.IE) { - var tmp = goog.dom.selection.getRangeIe_(textfield); - var range = tmp[0]; - var selectionRange = tmp[1]; - - if (!range.inRange(selectionRange)) { - return ''; - } else if (textfield.type == 'textarea') { - return goog.dom.selection.getSelectionRangeText_(selectionRange); - } - return selectionRange.text; - } - - throw Error('Cannot get the selection text'); -}; - - -/** - * Returns the selected text within a textarea in IE. - * IE treats newline characters as \r\n characters, and we need to check for - * these characters at the edge of our selection, to ensure that we return the - * right string. - * @param {TextRange} selRange Selected range object. - * @return {string} Selected text in the textarea. - * @private - */ -goog.dom.selection.getSelectionRangeText_ = function(selRange) { - // Create a duplicate of the selected range object to perform our actions - // against. Suppose the text in the textarea is "Hello\r\nWorld" and the - // selection encompasses the "o\r\n" bit, initial selectionRange will be "o" - // (assuming that the cursor is just after the \r\n combination) - var selectionRange = selRange.duplicate(); - - // Text within the selection , e.g. "o" assuming that the cursor is just after - // the \r\n combination. - var selectionText = selectionRange.text; - // Text within the selection, e.g., "o" (this will later include the \r\n - // sequences also) - var untrimmedSelectionText = selectionText; - - // Boolean indicating whether we are done dealing with the text inside the - // selection. - var isSelectionRangeEndTrimmed = false; - // Go over the selected range until it becomes a 0-lengthed range or until - // the range text starts changing when we move the end back by one character. - // If after moving the end back by one character, the text remains the same, - // then we need to add a "\r\n" at the end to get the actual text. - while (!isSelectionRangeEndTrimmed) { - if (selectionRange.compareEndPoints('StartToEnd', selectionRange) == 0) { - isSelectionRangeEndTrimmed = true; - } else { - selectionRange.moveEnd('character', -1); - if (selectionRange.text == selectionText) { - // If the selection was not empty, and the end point of the selection - // was just after a \r\n, we would have skipped it in one go with the - // moveEnd call, and this implies that we should add a \r\n to the - // untrimmedSelectionText string. - untrimmedSelectionText += '\r\n'; - } else { - isSelectionRangeEndTrimmed = true; - } - } - } - return untrimmedSelectionText; -}; - - -/** - * Helper function for returning the range for an object as well as the - * selection range - * @private - * @param {Element} el The element to get the range for. - * @return {!Array} Range of object and selection range in two - * element array. - */ -goog.dom.selection.getRangeIe_ = function(el) { - var doc = el.ownerDocument || el.document; - - var selectionRange = doc.selection.createRange(); - // el.createTextRange() doesn't work on textareas - var range; - - if (el.type == 'textarea') { - range = doc.body.createTextRange(); - range.moveToElementText(el); - } else { - range = el.createTextRange(); - } - - return [range, selectionRange]; -}; - - -/** - * Helper function for canonicalizing a position inside a textfield in IE. - * Deals with the issue that \r\n counts as 2 characters, but - * move('character', n) passes over both characters in one move. - * @private - * @param {Element} textfield The text element. - * @param {number} pos The position desired in that element. - * @return {number} The canonicalized position that will work properly with - * move('character', pos). - */ -goog.dom.selection.canonicalizePositionIe_ = function(textfield, pos) { - if (textfield.type == 'textarea') { - // We do this only for textarea because it is the only one which can - // have a \r\n (input cannot have this). - var value = textfield.value.substring(0, pos); - pos = goog.string.canonicalizeNewlines(value).length; - } - return pos; -}; - - -/** - * Helper function to determine whether it's okay to use - * selectionStart/selectionEnd. - * - * @param {Element} el The element to check for. - * @return {boolean} Whether it's okay to use the selectionStart and - * selectionEnd properties on {@code el}. - * @private - */ -goog.dom.selection.useSelectionProperties_ = function(el) { - try { - return typeof el.selectionStart == 'number'; - } catch (e) { - // Firefox throws an exception if you try to access selectionStart - // on an element with display: none. - return false; - } -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/selection_test.html b/src/database/third_party/closure-library/closure/goog/dom/selection_test.html deleted file mode 100644 index 076e31bc265..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/selection_test.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - -Closure Unit Tests - goog.dom.selection - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/selection_test.js b/src/database/third_party/closure-library/closure/goog/dom/selection_test.js deleted file mode 100644 index 17f799aa857..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/selection_test.js +++ /dev/null @@ -1,343 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.dom.selectionTest'); -goog.setTestOnly('goog.dom.selectionTest'); - -goog.require('goog.dom'); -goog.require('goog.dom.selection'); -goog.require('goog.testing.jsunit'); -goog.require('goog.userAgent'); - -var input; -var hiddenInput; -var textarea; -var hiddenTextarea; - -function setUp() { - input = goog.dom.createDom('input', {type: 'text'}); - textarea = goog.dom.createDom('textarea'); - hiddenInput = goog.dom.createDom( - 'input', {type: 'text', style: 'display: none'}); - hiddenTextarea = goog.dom.createDom( - 'textarea', {style: 'display: none'}); - - document.body.appendChild(input); - document.body.appendChild(textarea); - document.body.appendChild(hiddenInput); - document.body.appendChild(hiddenTextarea); -} - -function tearDown() { - goog.dom.removeNode(input); - goog.dom.removeNode(textarea); - goog.dom.removeNode(hiddenInput); - goog.dom.removeNode(hiddenTextarea); -} - - -/** - * Tests getStart routine in both input and textarea. - */ -function testGetStartInput() { - getStartHelper(input, hiddenInput); -} - -function testGetStartTextarea() { - getStartHelper(textarea, hiddenTextarea); -} - -function getStartHelper(field, hiddenField) { - assertEquals(0, goog.dom.selection.getStart(field)); - assertEquals(0, goog.dom.selection.getStart(hiddenField)); - - field.focus(); - assertEquals(0, goog.dom.selection.getStart(field)); -} - - -/** - * Tests the setText routine for both input and textarea - * with a single line of text. - */ -function testSetTextInput() { - setTextHelper(input); -} - -function testSetTextTextarea() { - setTextHelper(textarea); -} - -function setTextHelper(field) { - // Test one line string only - select(field); - assertEquals('', goog.dom.selection.getText(field)); - - goog.dom.selection.setText(field, 'Get Behind Me Satan'); - assertEquals('Get Behind Me Satan', goog.dom.selection.getText(field)); -} - - -/** - * Tests the setText routine for textarea with multiple lines of text. - */ -function testSetTextMultipleLines() { - select(textarea); - assertEquals('', goog.dom.selection.getText(textarea)); - var isLegacyIE = goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9'); - var message = isLegacyIE ? - 'Get Behind Me\r\nSatan' : - 'Get Behind Me\nSatan'; - goog.dom.selection.setText(textarea, message); - assertEquals(message, goog.dom.selection.getText(textarea)); - - // Select the text upto the point just after the \r\n combination - // or \n in GECKO. - var endOfNewline = isLegacyIE ? 15 : 14; - var selectedMessage = message.substring(0, endOfNewline); - goog.dom.selection.setStart(textarea, 0); - goog.dom.selection.setEnd(textarea, endOfNewline); - assertEquals(selectedMessage, goog.dom.selection.getText(textarea)); - - selectedMessage = isLegacyIE ? '\r\n' : '\n'; - goog.dom.selection.setStart(textarea, 13); - goog.dom.selection.setEnd(textarea, endOfNewline); - assertEquals(selectedMessage, goog.dom.selection.getText(textarea)); -} - - -/** - * Tests the setCursor routine for both input and textarea. - */ -function testSetCursorInput() { - setCursorHelper(input); -} - -function testSetCursorTextarea() { - setCursorHelper(textarea); -} - -function setCursorHelper(field) { - select(field); - // try to set the cursor beyond the length of the content - goog.dom.selection.setStart(field, 5); - goog.dom.selection.setEnd(field, 15); - assertEquals(0, goog.dom.selection.getStart(field)); - assertEquals(0, goog.dom.selection.getEnd(field)); - - select(field); - var message = 'Get Behind Me Satan'; - goog.dom.selection.setText(field, message); - goog.dom.selection.setStart(field, 5); - goog.dom.selection.setEnd(field, message.length); - assertEquals(5, goog.dom.selection.getStart(field)); - assertEquals(message.length, goog.dom.selection.getEnd(field)); - - // Set the end before the start, and see if getEnd returns the start - // position itself. - goog.dom.selection.setStart(field, 5); - goog.dom.selection.setEnd(field, 3); - assertEquals(3, goog.dom.selection.getEnd(field)); -} - - -/** - * Tests the getText and setText routines acting on selected text in - * both input and textarea. - */ -function testGetAndSetSelectedTextInput() { - getAndSetSelectedTextHelper(input); -} - -function testGetAndSetSelectedTextTextarea() { - getAndSetSelectedTextHelper(textarea); -} - -function getAndSetSelectedTextHelper(field) { - select(field); - goog.dom.selection.setText(field, 'Get Behind Me Satan'); - - // select 'Behind' - goog.dom.selection.setStart(field, 4); - goog.dom.selection.setEnd(field, 10); - assertEquals('Behind', goog.dom.selection.getText(field)); - - goog.dom.selection.setText(field, 'In Front Of'); - goog.dom.selection.setStart(field, 0); - goog.dom.selection.setEnd(field, 100); - assertEquals('Get In Front Of Me Satan', goog.dom.selection.getText(field)); -} - - -/** - * Test setStart on hidden input and hidden textarea. - */ -function testSetCursorOnHiddenInput() { - setCursorOnHiddenInputHelper(hiddenInput); -} - -function testSetCursorOnHiddenTextarea() { - setCursorOnHiddenInputHelper(hiddenTextarea); -} - -function setCursorOnHiddenInputHelper(hiddenField) { - goog.dom.selection.setStart(hiddenField, 0); - assertEquals(0, goog.dom.selection.getStart(hiddenField)); -} - - -/** - * Test setStart, setEnd, getStart and getEnd in textarea with text - * containing line breaks. - */ -function testSetAndGetCursorWithLineBreaks() { - select(textarea); - var isLegacyIE = goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9'); - var newline = isLegacyIE ? '\r\n' : '\n'; - var message = 'Hello' + newline + 'World'; - goog.dom.selection.setText(textarea, message); - - // Test setEnd and getEnd, by setting the cursor somewhere after the - // \r\n combination. - goog.dom.selection.setEnd(textarea, 9); - assertEquals(9, goog.dom.selection.getEnd(textarea)); - - // Test basic setStart and getStart - goog.dom.selection.setStart(textarea, 10); - assertEquals(10, goog.dom.selection.getStart(textarea)); - - // Test setEnd and getEnd, by setting the cursor exactly after the - // \r\n combination in IE or after \n in GECKO. - var endOfNewline = isLegacyIE ? 7 : 6; - checkSetAndGetTextarea(endOfNewline, endOfNewline); - - // Select a \r\n combination in IE or \n in GECKO and see if - // getStart and getEnd work correctly. - clearField(textarea); - message = 'Hello' + newline + newline + 'World'; - goog.dom.selection.setText(textarea, message); - var startOfNewline = isLegacyIE ? 7 : 6; - endOfNewline = isLegacyIE ? 9 : 7; - checkSetAndGetTextarea(startOfNewline, endOfNewline); - - // Select 2 \r\n combinations in IE or 2 \ns in GECKO and see if getStart - // and getEnd work correctly. - checkSetAndGetTextarea(5, endOfNewline); - - // Position cursor b/w 2 \r\n combinations in IE or 2 \ns in GECKO and see - // if getStart and getEnd work correctly. - clearField(textarea); - message = 'Hello' + newline + newline + newline + newline + 'World'; - goog.dom.selection.setText(textarea, message); - var middleOfNewlines = isLegacyIE ? 9 : 7; - checkSetAndGetTextarea(middleOfNewlines, middleOfNewlines); - - // Position cursor at end of a textarea which ends with \r\n in IE or \n in - // GECKO. - if (!goog.userAgent.IE || !goog.userAgent.isVersionOrHigher('11')) { - // TODO(johnlenz): investigate why this fails in IE 11. - clearField(textarea); - message = 'Hello' + newline + newline; - goog.dom.selection.setText(textarea, message); - var endOfTextarea = message.length; - checkSetAndGetTextarea(endOfTextarea, endOfTextarea); - } - - // Position cursor at the end of the 2 starting \r\ns in IE or \ns in GECKO - // within a textarea. - clearField(textarea); - message = newline + newline + 'World'; - goog.dom.selection.setText(textarea, message); - var endOfTwoNewlines = isLegacyIE ? 4 : 2; - checkSetAndGetTextarea(endOfTwoNewlines, endOfTwoNewlines); - - // Position cursor at the end of the first \r\n in IE or \n in - // GECKO within a textarea. - endOfOneNewline = isLegacyIE ? 2 : 1; - checkSetAndGetTextarea(endOfOneNewline, endOfOneNewline); -} - - -/** - * Test to make sure there's no error when getting the range of an unselected - * textarea. See bug 1274027. - */ -function testGetStartOnUnfocusedTextarea() { - input.value = 'White Blood Cells'; - input.focus(); - goog.dom.selection.setCursorPosition(input, 5); - - assertEquals('getStart on input should return where we put the cursor', - 5, goog.dom.selection.getStart(input)); - - assertEquals('getStart on unfocused textarea should succeed without error', - 0, goog.dom.selection.getStart(textarea)); -} - - -/** - * Test to make sure there's no error setting cursor position within a - * textarea after a newline. This is problematic on IE because of the - * '\r\n' vs '\n' issue. - */ -function testSetCursorPositionTextareaWithNewlines() { - textarea.value = 'Hello\nWorld'; - textarea.focus(); - - // Set the selection point between 'W' and 'o'. Position is computed this - // way instead of being hard-coded because it's different in IE due to \r\n - // vs \n. - goog.dom.selection.setCursorPosition(textarea, textarea.value.length - 4); - - var isLegacyIE = goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9'); - var linebreak = isLegacyIE ? '\r\n' : '\n'; - var expectedLeftString = 'Hello' + linebreak + 'W'; - - assertEquals('getStart on input should return after the newline', - expectedLeftString.length, goog.dom.selection.getStart(textarea)); - assertEquals('getEnd on input should return after the newline', - expectedLeftString.length, goog.dom.selection.getEnd(textarea)); - - goog.dom.selection.setEnd(textarea, textarea.value.length); - assertEquals('orld', goog.dom.selection.getText(textarea)); -} - - -/** - * Helper function to clear the textfield contents. - */ -function clearField(field) { - field.value = ''; -} - - -/** - * Helper function to set the start and end and assert the getter values. - */ -function checkSetAndGetTextarea(start, end) { - goog.dom.selection.setStart(textarea, start); - goog.dom.selection.setEnd(textarea, end); - assertEquals(start, goog.dom.selection.getStart(textarea)); - assertEquals(end, goog.dom.selection.getEnd(textarea)); -} - - -/** - * Helper function to focus and select a field. In IE8, selected - * fields need focus. - */ -function select(field) { - field.focus(); - field.select(); -} diff --git a/src/database/third_party/closure-library/closure/goog/dom/tagiterator.js b/src/database/third_party/closure-library/closure/goog/dom/tagiterator.js deleted file mode 100644 index 212604d777b..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/tagiterator.js +++ /dev/null @@ -1,368 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Iterator subclass for DOM tree traversal. - * - * @author robbyw@google.com (Robby Walker) - */ - -goog.provide('goog.dom.TagIterator'); -goog.provide('goog.dom.TagWalkType'); - -goog.require('goog.dom'); -goog.require('goog.dom.NodeType'); -goog.require('goog.iter.Iterator'); -goog.require('goog.iter.StopIteration'); - - -/** - * There are three types of token: - *
      - *
    1. {@code START_TAG} - The beginning of a tag. - *
    2. {@code OTHER} - Any non-element node position. - *
    3. {@code END_TAG} - The end of a tag. - *
    - * Users of this enumeration can rely on {@code START_TAG + END_TAG = 0} and - * that {@code OTHER = 0}. - * - * @enum {number} - */ -goog.dom.TagWalkType = { - START_TAG: 1, - OTHER: 0, - END_TAG: -1 -}; - - - -/** - * A DOM tree traversal iterator. - * - * Starting with the given node, the iterator walks the DOM in order, reporting - * events for the start and end of Elements, and the presence of text nodes. For - * example: - * - *
    - * <div>1<span>2</span>3</div>
    - * 
    - * - * Will return the following nodes: - * - * [div, 1, span, 2, span, 3, div] - * - * With the following states: - * - * [START, OTHER, START, OTHER, END, OTHER, END] - * - * And the following depths - * - * [1, 1, 2, 2, 1, 1, 0] - * - * Imagining | represents iterator position, the traversal stops at - * each of the following locations: - * - *
    - * <div>|1|<span>|2|</span>|3|</div>|
    - * 
    - * - * The iterator can also be used in reverse mode, which will return the nodes - * and states in the opposite order. The depths will be slightly different - * since, like in normal mode, the depth is computed *after* the given node. - * - * Lastly, it is possible to create an iterator that is unconstrained, meaning - * that it will continue iterating until the end of the document instead of - * until exiting the start node. - * - * @param {Node=} opt_node The start node. If unspecified or null, defaults to - * an empty iterator. - * @param {boolean=} opt_reversed Whether to traverse the tree in reverse. - * @param {boolean=} opt_unconstrained Whether the iterator is not constrained - * to the starting node and its children. - * @param {goog.dom.TagWalkType?=} opt_tagType The type of the position. - * Defaults to the start of the given node for forward iterators, and - * the end of the node for reverse iterators. - * @param {number=} opt_depth The starting tree depth. - * @constructor - * @extends {goog.iter.Iterator} - */ -goog.dom.TagIterator = function(opt_node, opt_reversed, - opt_unconstrained, opt_tagType, opt_depth) { - this.reversed = !!opt_reversed; - if (opt_node) { - this.setPosition(opt_node, opt_tagType); - } - this.depth = opt_depth != undefined ? opt_depth : this.tagType || 0; - if (this.reversed) { - this.depth *= -1; - } - this.constrained = !opt_unconstrained; -}; -goog.inherits(goog.dom.TagIterator, goog.iter.Iterator); - - -/** - * The node this position is located on. - * @type {Node} - */ -goog.dom.TagIterator.prototype.node = null; - - -/** - * The type of this position. - * @type {goog.dom.TagWalkType} - */ -goog.dom.TagIterator.prototype.tagType = goog.dom.TagWalkType.OTHER; - - -/** - * The tree depth of this position relative to where the iterator started. The - * depth is considered to be the tree depth just past the current node, so if an - * iterator is at position
    - *     
    |
    - *
    - * (i.e. the node is the div and the type is START_TAG) its depth will be 1. - * @type {number} - */ -goog.dom.TagIterator.prototype.depth; - - -/** - * Whether the node iterator is moving in reverse. - * @type {boolean} - */ -goog.dom.TagIterator.prototype.reversed; - - -/** - * Whether the iterator is constrained to the starting node and its children. - * @type {boolean} - */ -goog.dom.TagIterator.prototype.constrained; - - -/** - * Whether iteration has started. - * @type {boolean} - * @private - */ -goog.dom.TagIterator.prototype.started_ = false; - - -/** - * Set the position of the iterator. Overwrite the tree node and the position - * type which can be one of the {@link goog.dom.TagWalkType} token types. - * Only overwrites the tree depth when the parameter is specified. - * @param {Node} node The node to set the position to. - * @param {goog.dom.TagWalkType?=} opt_tagType The type of the position - * Defaults to the start of the given node. - * @param {number=} opt_depth The tree depth. - */ -goog.dom.TagIterator.prototype.setPosition = function(node, - opt_tagType, opt_depth) { - this.node = node; - - if (node) { - if (goog.isNumber(opt_tagType)) { - this.tagType = opt_tagType; - } else { - // Auto-determine the proper type - this.tagType = this.node.nodeType != goog.dom.NodeType.ELEMENT ? - goog.dom.TagWalkType.OTHER : - this.reversed ? goog.dom.TagWalkType.END_TAG : - goog.dom.TagWalkType.START_TAG; - } - } - - if (goog.isNumber(opt_depth)) { - this.depth = opt_depth; - } -}; - - -/** - * Replace this iterator's values with values from another. The two iterators - * must be of the same type. - * @param {goog.dom.TagIterator} other The iterator to copy. - * @protected - */ -goog.dom.TagIterator.prototype.copyFrom = function(other) { - this.node = other.node; - this.tagType = other.tagType; - this.depth = other.depth; - this.reversed = other.reversed; - this.constrained = other.constrained; -}; - - -/** - * @return {!goog.dom.TagIterator} A copy of this iterator. - */ -goog.dom.TagIterator.prototype.clone = function() { - return new goog.dom.TagIterator(this.node, this.reversed, - !this.constrained, this.tagType, this.depth); -}; - - -/** - * Skip the current tag. - */ -goog.dom.TagIterator.prototype.skipTag = function() { - var check = this.reversed ? goog.dom.TagWalkType.END_TAG : - goog.dom.TagWalkType.START_TAG; - if (this.tagType == check) { - this.tagType = /** @type {goog.dom.TagWalkType} */ (check * -1); - this.depth += this.tagType * (this.reversed ? -1 : 1); - } -}; - - -/** - * Restart the current tag. - */ -goog.dom.TagIterator.prototype.restartTag = function() { - var check = this.reversed ? goog.dom.TagWalkType.START_TAG : - goog.dom.TagWalkType.END_TAG; - if (this.tagType == check) { - this.tagType = /** @type {goog.dom.TagWalkType} */ (check * -1); - this.depth += this.tagType * (this.reversed ? -1 : 1); - } -}; - - -/** - * Move to the next position in the DOM tree. - * @return {Node} Returns the next node, or throws a goog.iter.StopIteration - * exception if the end of the iterator's range has been reached. - * @override - */ -goog.dom.TagIterator.prototype.next = function() { - var node; - - if (this.started_) { - if (!this.node || this.constrained && this.depth == 0) { - throw goog.iter.StopIteration; - } - node = this.node; - - var startType = this.reversed ? goog.dom.TagWalkType.END_TAG : - goog.dom.TagWalkType.START_TAG; - - if (this.tagType == startType) { - // If we have entered the tag, test if there are any children to move to. - var child = this.reversed ? node.lastChild : node.firstChild; - if (child) { - this.setPosition(child); - } else { - // If not, move on to exiting this tag. - this.setPosition(node, - /** @type {goog.dom.TagWalkType} */ (startType * -1)); - } - } else { - var sibling = this.reversed ? node.previousSibling : node.nextSibling; - if (sibling) { - // Try to move to the next node. - this.setPosition(sibling); - } else { - // If no such node exists, exit our parent. - this.setPosition(node.parentNode, - /** @type {goog.dom.TagWalkType} */ (startType * -1)); - } - } - - this.depth += this.tagType * (this.reversed ? -1 : 1); - } else { - this.started_ = true; - } - - // Check the new position for being last, and return it if it's not. - node = this.node; - if (!this.node) { - throw goog.iter.StopIteration; - } - return node; -}; - - -/** - * @return {boolean} Whether next has ever been called on this iterator. - * @protected - */ -goog.dom.TagIterator.prototype.isStarted = function() { - return this.started_; -}; - - -/** - * @return {boolean} Whether this iterator's position is a start tag position. - */ -goog.dom.TagIterator.prototype.isStartTag = function() { - return this.tagType == goog.dom.TagWalkType.START_TAG; -}; - - -/** - * @return {boolean} Whether this iterator's position is an end tag position. - */ -goog.dom.TagIterator.prototype.isEndTag = function() { - return this.tagType == goog.dom.TagWalkType.END_TAG; -}; - - -/** - * @return {boolean} Whether this iterator's position is not at an element node. - */ -goog.dom.TagIterator.prototype.isNonElement = function() { - return this.tagType == goog.dom.TagWalkType.OTHER; -}; - - -/** - * Test if two iterators are at the same position - i.e. if the node and tagType - * is the same. This will still return true if the two iterators are moving in - * opposite directions or have different constraints. - * @param {goog.dom.TagIterator} other The iterator to compare to. - * @return {boolean} Whether the two iterators are at the same position. - */ -goog.dom.TagIterator.prototype.equals = function(other) { - // Nodes must be equal, and we must either have reached the end of our tree - // or be at the same position. - return other.node == this.node && (!this.node || - other.tagType == this.tagType); -}; - - -/** - * Replace the current node with the list of nodes. Reset the iterator so that - * it visits the first of the nodes next. - * @param {...Object} var_args A list of nodes to replace the current node with. - * If the first argument is array-like, it will be used, otherwise all the - * arguments are assumed to be nodes. - */ -goog.dom.TagIterator.prototype.splice = function(var_args) { - // Reset the iterator so that it iterates over the first replacement node in - // the arguments on the next iteration. - var node = this.node; - this.restartTag(); - this.reversed = !this.reversed; - goog.dom.TagIterator.prototype.next.call(this); - this.reversed = !this.reversed; - - // Replace the node with the arguments. - var arr = goog.isArrayLike(arguments[0]) ? arguments[0] : arguments; - for (var i = arr.length - 1; i >= 0; i--) { - goog.dom.insertSiblingAfter(arr[i], node); - } - goog.dom.removeNode(node); -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/tagiterator_test.html b/src/database/third_party/closure-library/closure/goog/dom/tagiterator_test.html deleted file mode 100644 index de3280daa59..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/tagiterator_test.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - -goog.dom.TagIterator Tests - - - - - -
    Text

    Text

    -
    • Not
    • Closed
    -
    text
    -
    - - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/tagiterator_test.js b/src/database/third_party/closure-library/closure/goog/dom/tagiterator_test.js deleted file mode 100644 index 6a625c02254..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/tagiterator_test.js +++ /dev/null @@ -1,584 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.dom.TagIteratorTest'); -goog.setTestOnly('goog.dom.TagIteratorTest'); - -goog.require('goog.dom'); -goog.require('goog.dom.TagIterator'); -goog.require('goog.dom.TagWalkType'); -goog.require('goog.iter'); -goog.require('goog.iter.StopIteration'); -goog.require('goog.testing.dom'); -goog.require('goog.testing.jsunit'); - -var it; -var pos; - -function assertStartTag(type) { - assertEquals('Position ' + pos + ' should be start tag', - goog.dom.TagWalkType.START_TAG, it.tagType); - assertTrue('isStartTag should return true', it.isStartTag()); - assertFalse('isEndTag should return false', it.isEndTag()); - assertFalse('isNonElement should return false', it.isNonElement()); - assertEquals('Position ' + pos + ' should be ' + type, type, - it.node.tagName); -} - -function assertEndTag(type) { - assertEquals('Position ' + pos + ' should be end tag', - goog.dom.TagWalkType.END_TAG, it.tagType); - assertFalse('isStartTag should return false', it.isStartTag()); - assertTrue('isEndTag should return true', it.isEndTag()); - assertFalse('isNonElement should return false', it.isNonElement()); - assertEquals('Position ' + pos + ' should be ' + type, type, - it.node.tagName); -} - -function assertTextNode(value) { - assertEquals('Position ' + pos + ' should be text node', - goog.dom.TagWalkType.OTHER, it.tagType); - assertFalse('isStartTag should return false', it.isStartTag()); - assertFalse('isEndTag should return false', it.isEndTag()); - assertTrue('isNonElement should return true', it.isNonElement()); - assertEquals('Position ' + pos + ' should be "' + value + '"', value, - it.node.nodeValue); -} - -function testBasicHTML() { - it = new goog.dom.TagIterator(goog.dom.getElement('test')); - pos = 0; - - goog.iter.forEach(it, function() { - pos++; - switch (pos) { - case 1: - assertStartTag('DIV'); - break; - case 2: - assertStartTag('A'); - break; - case 3: - assertTextNode('T'); - break; - case 4: - assertStartTag('B'); - assertEquals('Depth at should be 3', 3, it.depth); - break; - case 5: - assertTextNode('e'); - break; - case 6: - assertEndTag('B'); - break; - case 7: - assertTextNode('xt'); - break; - case 8: - assertEndTag('A'); - break; - case 9: - assertStartTag('SPAN'); - break; - case 10: - assertEndTag('SPAN'); - break; - case 11: - assertStartTag('P'); - break; - case 12: - assertTextNode('Text'); - break; - case 13: - assertEndTag('P'); - break; - case 14: - assertEndTag('DIV'); - assertEquals('Depth at end should be 0', 0, it.depth); - break; - default: - throw goog.iter.StopIteration; - } - }); -} - -function testSkipTag() { - it = new goog.dom.TagIterator(goog.dom.getElement('test')); - pos = 0; - - goog.iter.forEach(it, function() { - pos++; - switch (pos) { - case 1: - assertStartTag('DIV'); - break; - case 2: - assertStartTag('A'); - it.skipTag(); - break; - case 3: - assertStartTag('SPAN'); - break; - case 4: - assertEndTag('SPAN'); - break; - case 5: - assertStartTag('P'); - break; - case 6: - assertTextNode('Text'); - break; - case 7: - assertEndTag('P'); - break; - case 8: - assertEndTag('DIV'); - assertEquals('Depth at end should be 0', 0, it.depth); - break; - default: - throw goog.iter.StopIteration; - } - }); -} - -function testRestartTag() { - it = new goog.dom.TagIterator(goog.dom.getElement('test')); - pos = 0; - var done = false; - - goog.iter.forEach(it, function() { - pos++; - switch (pos) { - case 1: - assertStartTag('DIV'); - break; - case 2: - assertStartTag('A'); - it.skipTag(); - break; - case 3: - assertStartTag('SPAN'); - break; - case 4: - assertEndTag('SPAN'); - break; - case 5: - assertStartTag('P'); - break; - case 6: - assertTextNode('Text'); - break; - case 7: - assertEndTag('P'); - break; - case 8: - assertEndTag('DIV'); - assertEquals('Depth at end should be 0', 0, it.depth); - - // Do them all again, starting after this element. - if (!done) { - pos = 1; - it.restartTag(); - done = true; - } - break; - default: - throw goog.iter.StopIteration; - } - }); -} - - -function testSkipTagReverse() { - it = new goog.dom.TagIterator(goog.dom.getElement('test'), true); - pos = 9; - - goog.iter.forEach(it, function() { - pos--; - switch (pos) { - case 1: - assertStartTag('DIV'); - assertEquals('Depth at end should be 0', 0, it.depth); - break; - case 2: - assertEndTag('A'); - it.skipTag(); - break; - case 3: - assertStartTag('SPAN'); - break; - case 4: - assertEndTag('SPAN'); - break; - case 5: - assertStartTag('P'); - break; - case 6: - assertTextNode('Text'); - break; - case 7: - assertEndTag('P'); - break; - case 8: - assertEndTag('DIV'); - break; - default: - throw goog.iter.StopIteration; - } - }); -} - - -function testUnclosedLI() { - it = new goog.dom.TagIterator(goog.dom.getElement('test2')); - pos = 0; - - goog.iter.forEach(it, function() { - pos++; - switch (pos) { - case 1: - assertStartTag('UL'); - break; - case 2: - assertStartTag('LI'); - assertEquals('Depth at
  • should be 2', 2, it.depth); - break; - case 3: - assertTextNode('Not'); - break; - case 4: - assertEndTag('LI'); - break; - case 5: - assertStartTag('LI'); - assertEquals('Depth at second
  • should be 2', 2, it.depth); - break; - case 6: - assertTextNode('Closed'); - break; - case 7: - assertEndTag('LI'); - break; - case 8: - assertEndTag('UL'); - assertEquals('Depth at end should be 0', 0, it.depth); - break; - default: - throw goog.iter.StopIteration; - } - }); -} - -function testReversedUnclosedLI() { - it = new goog.dom.TagIterator(goog.dom.getElement('test2'), true); - pos = 9; - - goog.iter.forEach(it, function() { - pos--; - switch (pos) { - case 1: - assertStartTag('UL'); - assertEquals('Depth at start should be 0', 0, it.depth); - break; - case 2: - assertStartTag('LI'); - break; - case 3: - assertTextNode('Not'); - break; - case 4: - assertEndTag('LI'); - assertEquals('Depth at
  • should be 2', 2, it.depth); - break; - case 5: - assertStartTag('LI'); - break; - case 6: - assertTextNode('Closed'); - break; - case 7: - assertEndTag('LI'); - assertEquals('Depth at second
  • should be 2', 2, it.depth); - break; - case 8: - assertEndTag('UL'); - break; - default: - throw goog.iter.StopIteration; - } - }); -} - -function testConstrained() { - it = new goog.dom.TagIterator(goog.dom.getElement('test3'), false, false); - pos = 0; - - goog.iter.forEach(it, function() { - pos++; - switch (pos) { - case 1: - assertStartTag('DIV'); - break; - case 2: - assertTextNode('text'); - break; - case 3: - assertEndTag('DIV'); - break; - } - }); - - assertEquals('Constrained iterator should stop at position 3.', 3, pos); -} - -function testUnconstrained() { - it = new goog.dom.TagIterator(goog.dom.getElement('test3'), false, true); - pos = 0; - - goog.iter.forEach(it, function() { - pos++; - switch (pos) { - case 1: - assertStartTag('DIV'); - break; - case 2: - assertTextNode('text'); - break; - case 3: - assertEndTag('DIV'); - break; - } - }); - - assertNotEquals('Unonstrained iterator should not stop at position 3.', 3, - pos); -} - -function testConstrainedText() { - it = new goog.dom.TagIterator(goog.dom.getElement('test3').firstChild, - false, false); - pos = 0; - - goog.iter.forEach(it, function() { - pos++; - switch (pos) { - case 1: - assertTextNode('text'); - break; - } - }); - - assertEquals('Constrained text iterator should stop at position 1.', 1, - pos); -} - -function testReverseConstrained() { - it = new goog.dom.TagIterator(goog.dom.getElement('test3'), true, false); - pos = 4; - - goog.iter.forEach(it, function() { - pos--; - switch (pos) { - case 1: - assertStartTag('DIV'); - break; - case 2: - assertTextNode('text'); - break; - case 3: - assertEndTag('DIV'); - break; - } - }); - - assertEquals('Constrained reversed iterator should stop at position 1.', 1, - pos); -} - -function testSpliceRemoveSingleNode() { - var testDiv = goog.dom.getElement('testSplice'); - testDiv.innerHTML = '
    '; - it = new goog.dom.TagIterator(testDiv.firstChild); - - goog.iter.forEach(it, function(node, dummy, i) { - i.splice(); - }); - - assertEquals('Node not removed', 0, testDiv.childNodes.length); -} - -function testSpliceRemoveFirstTextNode() { - var testDiv = goog.dom.getElement('testSplice'); - testDiv.innerHTML = 'helloworldgoodbye'; - it = new goog.dom.TagIterator(testDiv.firstChild, false, true); - - goog.iter.forEach(it, function(node, dummy, i) { - if (node.nodeType == 3 && node.data == 'hello') { - i.splice(); - } - if (node.nodeName == 'EM') { - i.splice(goog.dom.createDom('I', null, node.childNodes)); - } - }); - - goog.testing.dom.assertHtmlMatches('worldgoodbye', - testDiv.innerHTML); -} - -function testSpliceReplaceFirstTextNode() { - var testDiv = goog.dom.getElement('testSplice'); - testDiv.innerHTML = 'helloworld'; - it = new goog.dom.TagIterator(testDiv.firstChild, false, true); - - goog.iter.forEach(it, function(node, dummy, i) { - if (node.nodeType == 3 && node.data == 'hello') { - i.splice(goog.dom.createDom('EM', null, 'HELLO')); - } else if (node.nodeName == 'EM') { - i.splice(goog.dom.createDom('I', null, node.childNodes)); - } - }); - - goog.testing.dom.assertHtmlMatches('HELLOworld', - testDiv.innerHTML); -} - -function testSpliceReplaceSingleNode() { - var testDiv = goog.dom.getElement('testSplice'); - testDiv.innerHTML = '
    '; - it = new goog.dom.TagIterator(testDiv.firstChild); - - goog.iter.forEach(it, function(node, dummy, i) { - i.splice(goog.dom.createDom('link'), goog.dom.createDom('img')); - }); - - goog.testing.dom.assertHtmlMatches('', testDiv.innerHTML); -} - -function testSpliceFlattenSingleNode() { - var testDiv = goog.dom.getElement('testSplice'); - testDiv.innerHTML = '
    onetwothree
    '; - it = new goog.dom.TagIterator(testDiv.firstChild); - - goog.iter.forEach(it, function(node, dummy, i) { - i.splice(node.childNodes); - }); - - goog.testing.dom.assertHtmlMatches('onetwothree', - testDiv.innerHTML); -} - -function testSpliceMiddleNode() { - var testDiv = goog.dom.getElement('testSplice'); - testDiv.innerHTML = 'ahelloworldc'; - it = new goog.dom.TagIterator(testDiv); - - goog.iter.forEach(it, function(node, dummy, i) { - if (node.nodeName == 'B') { - i.splice(goog.dom.createDom('IMG')); - } - }); - - goog.testing.dom.assertHtmlMatches('ac', testDiv.innerHTML); -} - -function testSpliceMiddleNodeReversed() { - var testDiv = goog.dom.getElement('testSplice'); - testDiv.innerHTML = 'ahelloworldc'; - it = new goog.dom.TagIterator(testDiv, true); - - goog.iter.forEach(it, function(node, dummy, i) { - if (node.nodeName == 'B') { - i.splice(goog.dom.createDom('IMG')); - } - }); - - goog.testing.dom.assertHtmlMatches('ac', testDiv.innerHTML); -} - -function testSpliceMiddleNodeAtEndTag() { - var testDiv = goog.dom.getElement('testSplice'); - testDiv.innerHTML = 'ahelloworldc'; - it = new goog.dom.TagIterator(testDiv); - - goog.iter.forEach(it, function(node, dummy, i) { - if (node.tagName == 'B' && i.isEndTag()) { - i.splice(goog.dom.createDom('IMG')); - } - }); - - goog.testing.dom.assertHtmlMatches('ac', testDiv.innerHTML); -} - -function testSpliceMultipleNodes() { - var testDiv = goog.dom.getElement('testSplice'); - testDiv.innerHTML = 'this is from IE'; - it = new goog.dom.TagIterator(testDiv); - - goog.iter.forEach(it, function(node, dummy, i) { - var replace = null; - if (node.nodeName == 'STRONG') { - replace = goog.dom.createDom('B', null, node.childNodes); - } else if (node.nodeName == 'EM') { - replace = goog.dom.createDom('I', null, node.childNodes); - } - if (replace) { - i.splice(replace); - } - }); - - goog.testing.dom.assertHtmlMatches('this is from IE', - testDiv.innerHTML); -} - -function testSpliceMultipleNodesAtEnd() { - var testDiv = goog.dom.getElement('testSplice'); - testDiv.innerHTML = 'this is from IE'; - it = new goog.dom.TagIterator(testDiv); - - goog.iter.forEach(it, function(node, dummy, i) { - var replace = null; - if (node.nodeName == 'STRONG' && i.isEndTag()) { - replace = goog.dom.createDom('B', null, node.childNodes); - } else if (node.nodeName == 'EM' && i.isEndTag()) { - replace = goog.dom.createDom('I', null, node.childNodes); - } - if (replace) { - i.splice(replace); - } - }); - - goog.testing.dom.assertHtmlMatches('this is from IE', - testDiv.innerHTML); -} - -function testSpliceMultipleNodesReversed() { - var testDiv = goog.dom.getElement('testSplice'); - testDiv.innerHTML = 'this is from IE'; - it = new goog.dom.TagIterator(testDiv, true); - - goog.iter.forEach(it, function(node, dummy, i) { - var replace = null; - if (node.nodeName == 'STRONG') { - replace = goog.dom.createDom('B', null, node.childNodes); - } else if (node.nodeName == 'EM') { - replace = goog.dom.createDom('I', null, node.childNodes); - } - if (replace) { - i.splice(replace); - } - }); - - goog.testing.dom.assertHtmlMatches('this is from IE', - testDiv.innerHTML); -} diff --git a/src/database/third_party/closure-library/closure/goog/dom/tagname.js b/src/database/third_party/closure-library/closure/goog/dom/tagname.js deleted file mode 100644 index 77a9b475a9b..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/tagname.js +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Defines the goog.dom.TagName enum. This enumerates - * all HTML tag names specified in either the the W3C HTML 4.01 index of - * elements or the HTML5 draft specification. - * - * References: - * http://www.w3.org/TR/html401/index/elements.html - * http://dev.w3.org/html5/spec/section-index.html - * - */ -goog.provide('goog.dom.TagName'); - - -/** - * Enum of all html tag names specified by the W3C HTML4.01 and HTML5 - * specifications. - * @enum {string} - */ -goog.dom.TagName = { - A: 'A', - ABBR: 'ABBR', - ACRONYM: 'ACRONYM', - ADDRESS: 'ADDRESS', - APPLET: 'APPLET', - AREA: 'AREA', - ARTICLE: 'ARTICLE', - ASIDE: 'ASIDE', - AUDIO: 'AUDIO', - B: 'B', - BASE: 'BASE', - BASEFONT: 'BASEFONT', - BDI: 'BDI', - BDO: 'BDO', - BIG: 'BIG', - BLOCKQUOTE: 'BLOCKQUOTE', - BODY: 'BODY', - BR: 'BR', - BUTTON: 'BUTTON', - CANVAS: 'CANVAS', - CAPTION: 'CAPTION', - CENTER: 'CENTER', - CITE: 'CITE', - CODE: 'CODE', - COL: 'COL', - COLGROUP: 'COLGROUP', - COMMAND: 'COMMAND', - DATA: 'DATA', - DATALIST: 'DATALIST', - DD: 'DD', - DEL: 'DEL', - DETAILS: 'DETAILS', - DFN: 'DFN', - DIALOG: 'DIALOG', - DIR: 'DIR', - DIV: 'DIV', - DL: 'DL', - DT: 'DT', - EM: 'EM', - EMBED: 'EMBED', - FIELDSET: 'FIELDSET', - FIGCAPTION: 'FIGCAPTION', - FIGURE: 'FIGURE', - FONT: 'FONT', - FOOTER: 'FOOTER', - FORM: 'FORM', - FRAME: 'FRAME', - FRAMESET: 'FRAMESET', - H1: 'H1', - H2: 'H2', - H3: 'H3', - H4: 'H4', - H5: 'H5', - H6: 'H6', - HEAD: 'HEAD', - HEADER: 'HEADER', - HGROUP: 'HGROUP', - HR: 'HR', - HTML: 'HTML', - I: 'I', - IFRAME: 'IFRAME', - IMG: 'IMG', - INPUT: 'INPUT', - INS: 'INS', - ISINDEX: 'ISINDEX', - KBD: 'KBD', - KEYGEN: 'KEYGEN', - LABEL: 'LABEL', - LEGEND: 'LEGEND', - LI: 'LI', - LINK: 'LINK', - MAP: 'MAP', - MARK: 'MARK', - MATH: 'MATH', - MENU: 'MENU', - META: 'META', - METER: 'METER', - NAV: 'NAV', - NOFRAMES: 'NOFRAMES', - NOSCRIPT: 'NOSCRIPT', - OBJECT: 'OBJECT', - OL: 'OL', - OPTGROUP: 'OPTGROUP', - OPTION: 'OPTION', - OUTPUT: 'OUTPUT', - P: 'P', - PARAM: 'PARAM', - PRE: 'PRE', - PROGRESS: 'PROGRESS', - Q: 'Q', - RP: 'RP', - RT: 'RT', - RUBY: 'RUBY', - S: 'S', - SAMP: 'SAMP', - SCRIPT: 'SCRIPT', - SECTION: 'SECTION', - SELECT: 'SELECT', - SMALL: 'SMALL', - SOURCE: 'SOURCE', - SPAN: 'SPAN', - STRIKE: 'STRIKE', - STRONG: 'STRONG', - STYLE: 'STYLE', - SUB: 'SUB', - SUMMARY: 'SUMMARY', - SUP: 'SUP', - SVG: 'SVG', - TABLE: 'TABLE', - TBODY: 'TBODY', - TD: 'TD', - TEXTAREA: 'TEXTAREA', - TFOOT: 'TFOOT', - TH: 'TH', - THEAD: 'THEAD', - TIME: 'TIME', - TITLE: 'TITLE', - TR: 'TR', - TRACK: 'TRACK', - TT: 'TT', - U: 'U', - UL: 'UL', - VAR: 'VAR', - VIDEO: 'VIDEO', - WBR: 'WBR' -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/tagname_test.html b/src/database/third_party/closure-library/closure/goog/dom/tagname_test.html deleted file mode 100644 index 5755806ce3b..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/tagname_test.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - -Closure Unit Tests - goog.dom.TagName - - - - - dom_test.html relies on this not being empty. - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/tagname_test.js b/src/database/third_party/closure-library/closure/goog/dom/tagname_test.js deleted file mode 100644 index f0578571f6d..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/tagname_test.js +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.dom.TagNameTest'); -goog.setTestOnly('goog.dom.TagNameTest'); - -goog.require('goog.dom.TagName'); -goog.require('goog.object'); -goog.require('goog.testing.jsunit'); - -function testCorrectNumberOfTagNames() { - assertEquals(125, goog.object.getCount(goog.dom.TagName)); -} - -function testPropertyNamesEqualValues() { - for (var propertyName in goog.dom.TagName) { - assertEquals(propertyName, goog.dom.TagName[propertyName]); - } -} diff --git a/src/database/third_party/closure-library/closure/goog/dom/tags.js b/src/database/third_party/closure-library/closure/goog/dom/tags.js deleted file mode 100644 index 159abe0ceeb..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/tags.js +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2014 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utilities for HTML element tag names. - */ -goog.provide('goog.dom.tags'); - -goog.require('goog.object'); - - -/** - * The void elements specified by - * http://www.w3.org/TR/html-markup/syntax.html#void-elements. - * @const - * @type {!Object} - * @private - */ -goog.dom.tags.VOID_TAGS_ = goog.object.createSet(('area,base,br,col,command,' + - 'embed,hr,img,input,keygen,link,meta,param,source,track,wbr').split(',')); - - -/** - * Checks whether the tag is void (with no contents allowed and no legal end - * tag), for example 'br'. - * @param {string} tagName The tag name in lower case. - * @return {boolean} - */ -goog.dom.tags.isVoidTag = function(tagName) { - return goog.dom.tags.VOID_TAGS_[tagName] === true; -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/tags_test.js b/src/database/third_party/closure-library/closure/goog/dom/tags_test.js deleted file mode 100644 index cf6b6244096..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/tags_test.js +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2014 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.dom.tagsTest'); -goog.setTestOnly('goog.dom.tagsTest'); - -goog.require('goog.dom.tags'); -goog.require('goog.testing.jsunit'); - - -function testIsVoidTag() { - assertTrue(goog.dom.tags.isVoidTag('br')); - assertFalse(goog.dom.tags.isVoidTag('a')); - assertFalse(goog.dom.tags.isVoidTag('constructor')); -} diff --git a/src/database/third_party/closure-library/closure/goog/dom/textrange.js b/src/database/third_party/closure-library/closure/goog/dom/textrange.js deleted file mode 100644 index 21ba2118de1..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/textrange.js +++ /dev/null @@ -1,634 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utilities for working with text ranges in HTML documents. - * - * @author robbyw@google.com (Robby Walker) - */ - - -goog.provide('goog.dom.TextRange'); - -goog.require('goog.array'); -goog.require('goog.dom'); -goog.require('goog.dom.AbstractRange'); -goog.require('goog.dom.RangeType'); -goog.require('goog.dom.SavedRange'); -goog.require('goog.dom.TagName'); -goog.require('goog.dom.TextRangeIterator'); -goog.require('goog.dom.browserrange'); -goog.require('goog.string'); -goog.require('goog.userAgent'); - - - -/** - * Create a new text selection with no properties. Do not use this constructor: - * use one of the goog.dom.Range.createFrom* methods instead. - * @constructor - * @extends {goog.dom.AbstractRange} - * @final - */ -goog.dom.TextRange = function() { -}; -goog.inherits(goog.dom.TextRange, goog.dom.AbstractRange); - - -/** - * Create a new range wrapper from the given browser range object. Do not use - * this method directly - please use goog.dom.Range.createFrom* instead. - * @param {Range|TextRange} range The browser range object. - * @param {boolean=} opt_isReversed Whether the focus node is before the anchor - * node. - * @return {!goog.dom.TextRange} A range wrapper object. - */ -goog.dom.TextRange.createFromBrowserRange = function(range, opt_isReversed) { - return goog.dom.TextRange.createFromBrowserRangeWrapper_( - goog.dom.browserrange.createRange(range), opt_isReversed); -}; - - -/** - * Create a new range wrapper from the given browser range wrapper. - * @param {goog.dom.browserrange.AbstractRange} browserRange The browser range - * wrapper. - * @param {boolean=} opt_isReversed Whether the focus node is before the anchor - * node. - * @return {!goog.dom.TextRange} A range wrapper object. - * @private - */ -goog.dom.TextRange.createFromBrowserRangeWrapper_ = function(browserRange, - opt_isReversed) { - var range = new goog.dom.TextRange(); - - // Initialize the range as a browser range wrapper type range. - range.browserRangeWrapper_ = browserRange; - range.isReversed_ = !!opt_isReversed; - - return range; -}; - - -/** - * Create a new range wrapper that selects the given node's text. Do not use - * this method directly - please use goog.dom.Range.createFrom* instead. - * @param {Node} node The node to select. - * @param {boolean=} opt_isReversed Whether the focus node is before the anchor - * node. - * @return {!goog.dom.TextRange} A range wrapper object. - */ -goog.dom.TextRange.createFromNodeContents = function(node, opt_isReversed) { - return goog.dom.TextRange.createFromBrowserRangeWrapper_( - goog.dom.browserrange.createRangeFromNodeContents(node), - opt_isReversed); -}; - - -/** - * Create a new range wrapper that selects the area between the given nodes, - * accounting for the given offsets. Do not use this method directly - please - * use goog.dom.Range.createFrom* instead. - * @param {Node} anchorNode The node to start with. - * @param {number} anchorOffset The offset within the node to start. - * @param {Node} focusNode The node to end with. - * @param {number} focusOffset The offset within the node to end. - * @return {!goog.dom.TextRange} A range wrapper object. - */ -goog.dom.TextRange.createFromNodes = function(anchorNode, anchorOffset, - focusNode, focusOffset) { - var range = new goog.dom.TextRange(); - range.isReversed_ = /** @suppress {missingRequire} */ ( - goog.dom.Range.isReversed(anchorNode, anchorOffset, - focusNode, focusOffset)); - - // Avoid selecting terminal elements directly - if (goog.dom.isElement(anchorNode) && !goog.dom.canHaveChildren(anchorNode)) { - var parent = anchorNode.parentNode; - anchorOffset = goog.array.indexOf(parent.childNodes, anchorNode); - anchorNode = parent; - } - - if (goog.dom.isElement(focusNode) && !goog.dom.canHaveChildren(focusNode)) { - var parent = focusNode.parentNode; - focusOffset = goog.array.indexOf(parent.childNodes, focusNode); - focusNode = parent; - } - - // Initialize the range as a W3C style range. - if (range.isReversed_) { - range.startNode_ = focusNode; - range.startOffset_ = focusOffset; - range.endNode_ = anchorNode; - range.endOffset_ = anchorOffset; - } else { - range.startNode_ = anchorNode; - range.startOffset_ = anchorOffset; - range.endNode_ = focusNode; - range.endOffset_ = focusOffset; - } - - return range; -}; - - -// Representation 1: a browser range wrapper. - - -/** - * The browser specific range wrapper. This can be null if one of the other - * representations of the range is specified. - * @type {goog.dom.browserrange.AbstractRange?} - * @private - */ -goog.dom.TextRange.prototype.browserRangeWrapper_ = null; - - -// Representation 2: two endpoints specified as nodes + offsets - - -/** - * The start node of the range. This can be null if one of the other - * representations of the range is specified. - * @type {Node} - * @private - */ -goog.dom.TextRange.prototype.startNode_ = null; - - -/** - * The start offset of the range. This can be null if one of the other - * representations of the range is specified. - * @type {?number} - * @private - */ -goog.dom.TextRange.prototype.startOffset_ = null; - - -/** - * The end node of the range. This can be null if one of the other - * representations of the range is specified. - * @type {Node} - * @private - */ -goog.dom.TextRange.prototype.endNode_ = null; - - -/** - * The end offset of the range. This can be null if one of the other - * representations of the range is specified. - * @type {?number} - * @private - */ -goog.dom.TextRange.prototype.endOffset_ = null; - - -/** - * Whether the focus node is before the anchor node. - * @type {boolean} - * @private - */ -goog.dom.TextRange.prototype.isReversed_ = false; - - -// Method implementations - - -/** - * @return {!goog.dom.TextRange} A clone of this range. - * @override - */ -goog.dom.TextRange.prototype.clone = function() { - var range = new goog.dom.TextRange(); - range.browserRangeWrapper_ = - this.browserRangeWrapper_ && this.browserRangeWrapper_.clone(); - range.startNode_ = this.startNode_; - range.startOffset_ = this.startOffset_; - range.endNode_ = this.endNode_; - range.endOffset_ = this.endOffset_; - range.isReversed_ = this.isReversed_; - - return range; -}; - - -/** @override */ -goog.dom.TextRange.prototype.getType = function() { - return goog.dom.RangeType.TEXT; -}; - - -/** @override */ -goog.dom.TextRange.prototype.getBrowserRangeObject = function() { - return this.getBrowserRangeWrapper_().getBrowserRange(); -}; - - -/** @override */ -goog.dom.TextRange.prototype.setBrowserRangeObject = function(nativeRange) { - // Test if it's a control range by seeing if a control range only method - // exists. - if (goog.dom.AbstractRange.isNativeControlRange(nativeRange)) { - return false; - } - this.browserRangeWrapper_ = goog.dom.browserrange.createRange( - nativeRange); - this.clearCachedValues_(); - return true; -}; - - -/** - * Clear all cached values. - * @private - */ -goog.dom.TextRange.prototype.clearCachedValues_ = function() { - this.startNode_ = this.startOffset_ = this.endNode_ = this.endOffset_ = null; -}; - - -/** @override */ -goog.dom.TextRange.prototype.getTextRangeCount = function() { - return 1; -}; - - -/** @override */ -goog.dom.TextRange.prototype.getTextRange = function(i) { - return this; -}; - - -/** - * @return {!goog.dom.browserrange.AbstractRange} The range wrapper object. - * @private - */ -goog.dom.TextRange.prototype.getBrowserRangeWrapper_ = function() { - return this.browserRangeWrapper_ || - (this.browserRangeWrapper_ = goog.dom.browserrange.createRangeFromNodes( - this.getStartNode(), this.getStartOffset(), - this.getEndNode(), this.getEndOffset())); -}; - - -/** @override */ -goog.dom.TextRange.prototype.getContainer = function() { - return this.getBrowserRangeWrapper_().getContainer(); -}; - - -/** @override */ -goog.dom.TextRange.prototype.getStartNode = function() { - return this.startNode_ || - (this.startNode_ = this.getBrowserRangeWrapper_().getStartNode()); -}; - - -/** @override */ -goog.dom.TextRange.prototype.getStartOffset = function() { - return this.startOffset_ != null ? this.startOffset_ : - (this.startOffset_ = this.getBrowserRangeWrapper_().getStartOffset()); -}; - - -/** @override */ -goog.dom.TextRange.prototype.getStartPosition = function() { - return this.isReversed() ? - this.getBrowserRangeWrapper_().getEndPosition() : - this.getBrowserRangeWrapper_().getStartPosition(); -}; - - -/** @override */ -goog.dom.TextRange.prototype.getEndNode = function() { - return this.endNode_ || - (this.endNode_ = this.getBrowserRangeWrapper_().getEndNode()); -}; - - -/** @override */ -goog.dom.TextRange.prototype.getEndOffset = function() { - return this.endOffset_ != null ? this.endOffset_ : - (this.endOffset_ = this.getBrowserRangeWrapper_().getEndOffset()); -}; - - -/** @override */ -goog.dom.TextRange.prototype.getEndPosition = function() { - return this.isReversed() ? - this.getBrowserRangeWrapper_().getStartPosition() : - this.getBrowserRangeWrapper_().getEndPosition(); -}; - - -/** - * Moves a TextRange to the provided nodes and offsets. - * @param {Node} startNode The node to start with. - * @param {number} startOffset The offset within the node to start. - * @param {Node} endNode The node to end with. - * @param {number} endOffset The offset within the node to end. - * @param {boolean} isReversed Whether the range is reversed. - */ -goog.dom.TextRange.prototype.moveToNodes = function(startNode, startOffset, - endNode, endOffset, - isReversed) { - this.startNode_ = startNode; - this.startOffset_ = startOffset; - this.endNode_ = endNode; - this.endOffset_ = endOffset; - this.isReversed_ = isReversed; - this.browserRangeWrapper_ = null; -}; - - -/** @override */ -goog.dom.TextRange.prototype.isReversed = function() { - return this.isReversed_; -}; - - -/** @override */ -goog.dom.TextRange.prototype.containsRange = function(otherRange, - opt_allowPartial) { - var otherRangeType = otherRange.getType(); - if (otherRangeType == goog.dom.RangeType.TEXT) { - return this.getBrowserRangeWrapper_().containsRange( - otherRange.getBrowserRangeWrapper_(), opt_allowPartial); - } else if (otherRangeType == goog.dom.RangeType.CONTROL) { - var elements = otherRange.getElements(); - var fn = opt_allowPartial ? goog.array.some : goog.array.every; - return fn(elements, function(el) { - return this.containsNode(el, opt_allowPartial); - }, this); - } - return false; -}; - - -/** - * Tests if the given node is in a document. - * @param {Node} node The node to check. - * @return {boolean} Whether the given node is in the given document. - */ -goog.dom.TextRange.isAttachedNode = function(node) { - if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9)) { - var returnValue = false; - /** @preserveTry */ - try { - returnValue = node.parentNode; - } catch (e) { - // IE sometimes throws Invalid Argument errors when a node is detached. - // Note: trying to return a value from the above try block can cause IE - // to crash. It is necessary to use the local returnValue - } - return !!returnValue; - } else { - return goog.dom.contains(node.ownerDocument.body, node); - } -}; - - -/** @override */ -goog.dom.TextRange.prototype.isRangeInDocument = function() { - // Ensure any cached nodes are in the document. IE also allows ranges to - // become detached, so we check if the range is still in the document as - // well for IE. - return (!this.startNode_ || - goog.dom.TextRange.isAttachedNode(this.startNode_)) && - (!this.endNode_ || - goog.dom.TextRange.isAttachedNode(this.endNode_)) && - (!(goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9)) || - this.getBrowserRangeWrapper_().isRangeInDocument()); -}; - - -/** @override */ -goog.dom.TextRange.prototype.isCollapsed = function() { - return this.getBrowserRangeWrapper_().isCollapsed(); -}; - - -/** @override */ -goog.dom.TextRange.prototype.getText = function() { - return this.getBrowserRangeWrapper_().getText(); -}; - - -/** @override */ -goog.dom.TextRange.prototype.getHtmlFragment = function() { - // TODO(robbyw): Generalize the code in browserrange so it is static and - // just takes an iterator. This would mean we don't always have to create a - // browser range. - return this.getBrowserRangeWrapper_().getHtmlFragment(); -}; - - -/** @override */ -goog.dom.TextRange.prototype.getValidHtml = function() { - return this.getBrowserRangeWrapper_().getValidHtml(); -}; - - -/** @override */ -goog.dom.TextRange.prototype.getPastableHtml = function() { - // TODO(robbyw): Get any attributes the table or tr has. - - var html = this.getValidHtml(); - - if (html.match(/^\s*'; - } else if (html.match(/^\s*'; - } else if (html.match(/^\s*'; - } else if (html.match(/^\s*', html, ''); - } - - return html; -}; - - -/** - * Returns a TextRangeIterator over the contents of the range. Regardless of - * the direction of the range, the iterator will move in document order. - * @param {boolean=} opt_keys Unused for this iterator. - * @return {!goog.dom.TextRangeIterator} An iterator over tags in the range. - * @override - */ -goog.dom.TextRange.prototype.__iterator__ = function(opt_keys) { - return new goog.dom.TextRangeIterator(this.getStartNode(), - this.getStartOffset(), this.getEndNode(), this.getEndOffset()); -}; - - -// RANGE ACTIONS - - -/** @override */ -goog.dom.TextRange.prototype.select = function() { - this.getBrowserRangeWrapper_().select(this.isReversed_); -}; - - -/** @override */ -goog.dom.TextRange.prototype.removeContents = function() { - this.getBrowserRangeWrapper_().removeContents(); - this.clearCachedValues_(); -}; - - -/** - * Surrounds the text range with the specified element (on Mozilla) or with a - * clone of the specified element (on IE). Returns a reference to the - * surrounding element if the operation was successful; returns null if the - * operation failed. - * @param {Element} element The element with which the selection is to be - * surrounded. - * @return {Element} The surrounding element (same as the argument on Mozilla, - * but not on IE), or null if unsuccessful. - */ -goog.dom.TextRange.prototype.surroundContents = function(element) { - var output = this.getBrowserRangeWrapper_().surroundContents(element); - this.clearCachedValues_(); - return output; -}; - - -/** @override */ -goog.dom.TextRange.prototype.insertNode = function(node, before) { - var output = this.getBrowserRangeWrapper_().insertNode(node, before); - this.clearCachedValues_(); - return output; -}; - - -/** @override */ -goog.dom.TextRange.prototype.surroundWithNodes = function(startNode, endNode) { - this.getBrowserRangeWrapper_().surroundWithNodes(startNode, endNode); - this.clearCachedValues_(); -}; - - -// SAVE/RESTORE - - -/** @override */ -goog.dom.TextRange.prototype.saveUsingDom = function() { - return new goog.dom.DomSavedTextRange_(this); -}; - - -// RANGE MODIFICATION - - -/** @override */ -goog.dom.TextRange.prototype.collapse = function(toAnchor) { - var toStart = this.isReversed() ? !toAnchor : toAnchor; - - if (this.browserRangeWrapper_) { - this.browserRangeWrapper_.collapse(toStart); - } - - if (toStart) { - this.endNode_ = this.startNode_; - this.endOffset_ = this.startOffset_; - } else { - this.startNode_ = this.endNode_; - this.startOffset_ = this.endOffset_; - } - - // Collapsed ranges can't be reversed - this.isReversed_ = false; -}; - - -// SAVED RANGE OBJECTS - - - -/** - * A SavedRange implementation using DOM endpoints. - * @param {goog.dom.AbstractRange} range The range to save. - * @constructor - * @extends {goog.dom.SavedRange} - * @private - */ -goog.dom.DomSavedTextRange_ = function(range) { - goog.dom.DomSavedTextRange_.base(this, 'constructor'); - - /** - * The anchor node. - * @type {Node} - * @private - */ - this.anchorNode_ = range.getAnchorNode(); - - /** - * The anchor node offset. - * @type {number} - * @private - */ - this.anchorOffset_ = range.getAnchorOffset(); - - /** - * The focus node. - * @type {Node} - * @private - */ - this.focusNode_ = range.getFocusNode(); - - /** - * The focus node offset. - * @type {number} - * @private - */ - this.focusOffset_ = range.getFocusOffset(); -}; -goog.inherits(goog.dom.DomSavedTextRange_, goog.dom.SavedRange); - - -/** - * @return {!goog.dom.AbstractRange} The restored range. - * @override - */ -goog.dom.DomSavedTextRange_.prototype.restoreInternal = function() { - return /** @suppress {missingRequire} */ ( - goog.dom.Range.createFromNodes(this.anchorNode_, this.anchorOffset_, - this.focusNode_, this.focusOffset_)); -}; - - -/** @override */ -goog.dom.DomSavedTextRange_.prototype.disposeInternal = function() { - goog.dom.DomSavedTextRange_.superClass_.disposeInternal.call(this); - - this.anchorNode_ = null; - this.focusNode_ = null; -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/textrange_test.html b/src/database/third_party/closure-library/closure/goog/dom/textrange_test.html deleted file mode 100644 index 0983555d6ef..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/textrange_test.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - - -Closure Unit Tests - goog.dom.TextRange - - - - -
    -
    - -
    - -
    ab
    cd
    - - - - - - - -
    moof
    -
    foobar
    -
    - -
    positiontest
    - -
    positiontest
    - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/textrange_test.js b/src/database/third_party/closure-library/closure/goog/dom/textrange_test.js deleted file mode 100644 index d0465b9bbe8..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/textrange_test.js +++ /dev/null @@ -1,333 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.dom.TextRangeTest'); -goog.setTestOnly('goog.dom.TextRangeTest'); - -goog.require('goog.dom'); -goog.require('goog.dom.ControlRange'); -goog.require('goog.dom.Range'); -goog.require('goog.dom.TextRange'); -goog.require('goog.math.Coordinate'); -goog.require('goog.style'); -goog.require('goog.testing.ExpectedFailures'); -goog.require('goog.testing.jsunit'); -goog.require('goog.userAgent'); - -var logo; -var logo2; -var logo3; -var logo3Rtl; -var table; -var table2; -var table2div; -var test3; -var test3Rtl; -var expectedFailures; - -function setUpPage() { - logo = goog.dom.getElement('logo'); - logo2 = goog.dom.getElement('logo2'); - logo3 = goog.dom.getElement('logo3'); - logo3Rtl = goog.dom.getElement('logo3Rtl'); - table = goog.dom.getElement('table'); - table2 = goog.dom.getElement('table2'); - table2div = goog.dom.getElement('table2div'); - test3 = goog.dom.getElement('test3'); - test3Rtl = goog.dom.getElement('test3Rtl'); - expectedFailures = new goog.testing.ExpectedFailures(); -} - -function tearDown() { - expectedFailures.handleTearDown(); -} - -function testCreateFromNodeContents() { - assertNotNull('Text range object can be created for element node', - goog.dom.TextRange.createFromNodeContents(logo)); - assertNotNull('Text range object can be created for text node', - goog.dom.TextRange.createFromNodeContents(logo2.previousSibling)); -} - -function testMoveToNodes() { - var range = goog.dom.TextRange.createFromNodeContents(table2); - range.moveToNodes(table2div, 0, table2div, 1, false); - assertEquals('Range should start in table2div', - table2div, - range.getStartNode()); - assertEquals('Range should end in table2div', - table2div, - range.getEndNode()); - assertEquals('Range start offset should be 0', - 0, - range.getStartOffset()); - assertEquals('Range end offset should be 0', - 1, - range.getEndOffset()); - assertFalse('Range should not be reversed', - range.isReversed()); - range.moveToNodes(table2div, 0, table2div, 1, true); - assertTrue('Range should be reversed', - range.isReversed()); - assertEquals('Range text should be "foo"', - 'foo', - range.getText()); -} - -function testContainsTextRange() { - var range = goog.dom.TextRange.createFromNodeContents(table2); - var range2 = goog.dom.TextRange.createFromNodeContents(table2div); - assertTrue('TextRange contains other TextRange', - range.containsRange(range2)); - assertFalse('TextRange does not contain other TextRange', - range2.containsRange(range)); - - range = goog.dom.Range.createFromNodes( - table2div.firstChild, 1, table2div.lastChild, 1); - range2 = goog.dom.TextRange.createFromNodes( - table2div.firstChild, 0, table2div.lastChild, 0); - assertTrue('TextRange partially contains other TextRange', - range2.containsRange(range, true)); - assertFalse('TextRange does not fully contain other TextRange', - range2.containsRange(range, false)); -} - -function testContainsControlRange() { - if (goog.userAgent.IE) { - var range = goog.dom.ControlRange.createFromElements(table2); - var range2 = goog.dom.TextRange.createFromNodeContents(table2div); - assertFalse('TextRange does not contain ControlRange', - range2.containsRange(range)); - range = goog.dom.ControlRange.createFromElements(logo2); - assertTrue('TextRange contains ControlRange', - range2.containsRange(range)); - range = goog.dom.TextRange.createFromNodeContents(table2); - range2 = goog.dom.ControlRange.createFromElements(logo, logo2); - assertTrue('TextRange partially contains ControlRange', - range2.containsRange(range, true)); - assertFalse('TextRange does not fully contain ControlRange', - range2.containsRange(range, false)); - } -} - -function testGetStartPosition() { - expectedFailures.expectFailureFor(goog.userAgent.GECKO && - !goog.userAgent.isVersionOrHigher('2')); - - // The start node is in the top left. - var range = goog.dom.TextRange.createFromNodeContents(test3); - var topLeft = goog.style.getPageOffset(test3.firstChild); - - if (goog.userAgent.IE) { - // On IE the selection is as tall as its tallest element. - var logoPosition = goog.style.getPageOffset(logo3); - topLeft.y = logoPosition.y; - - if (!goog.userAgent.isVersionOrHigher('8')) { - topLeft.x += 2; - topLeft.y += 2; - } - } - - try { - var result = assertNotThrows(goog.bind(range.getStartPosition, range)); - assertObjectEquals(topLeft, result); - } catch (e) { - expectedFailures.handleException(e); - } -} - -function testGetStartPositionNotInDocument() { - expectedFailures.expectFailureFor(goog.userAgent.GECKO && - !goog.userAgent.isVersionOrHigher('2')); - expectedFailures.expectFailureFor(goog.userAgent.IE && - !goog.userAgent.isVersionOrHigher('8')); - - var range = goog.dom.TextRange.createFromNodeContents(test3); - - goog.dom.removeNode(test3); - try { - var result = assertNotThrows(goog.bind(range.getStartPosition, range)); - assertNull(result); - } catch (e) { - expectedFailures.handleException(e); - } finally { - goog.dom.appendChild(document.body, test3); - } -} - -function testGetStartPositionReversed() { - expectedFailures.expectFailureFor(goog.userAgent.GECKO && - !goog.userAgent.isVersionOrHigher('2')); - - // Simulate the user selecting backwards from right-to-left. - // The start node is now in the bottom right. - var firstNode = test3.firstChild.firstChild; - var lastNode = test3.lastChild.lastChild; - var range = goog.dom.TextRange.createFromNodes( - lastNode, lastNode.nodeValue.length, firstNode, 0); - var pageOffset = goog.style.getPageOffset(test3.lastChild); - var bottomRight = new goog.math.Coordinate( - pageOffset.x + test3.lastChild.offsetWidth, - pageOffset.y + test3.lastChild.offsetHeight); - - if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('8')) { - bottomRight.x += 2; - bottomRight.y += 2; - } - - try { - var result = assertNotThrows(goog.bind(range.getStartPosition, range)); - assertObjectRoughlyEquals(bottomRight, result, 1); - } catch (e) { - expectedFailures.handleException(e); - } -} - -function testGetStartPositionRightToLeft() { - expectedFailures.expectFailureFor(goog.userAgent.GECKO && - !goog.userAgent.isVersionOrHigher('2')); - - // Even in RTL content the start node is still in the top left. - var range = goog.dom.TextRange.createFromNodeContents(test3Rtl); - var topLeft = goog.style.getPageOffset(test3Rtl.firstChild); - - if (goog.userAgent.IE) { - // On IE the selection is as tall as its tallest element. - var logoPosition = goog.style.getPageOffset(logo3Rtl); - topLeft.y = logoPosition.y; - - if (!goog.userAgent.isVersionOrHigher('8')) { - topLeft.x += 2; - topLeft.y += 2; - } - } - - try { - var result = assertNotThrows(goog.bind(range.getStartPosition, range)); - assertObjectRoughlyEquals(topLeft, result, 0.1); - } catch (e) { - expectedFailures.handleException(e); - } -} - -function testGetEndPosition() { - expectedFailures.expectFailureFor(goog.userAgent.GECKO && - !goog.userAgent.isVersionOrHigher('2')); - - // The end node is in the bottom right. - var range = goog.dom.TextRange.createFromNodeContents(test3); - var pageOffset = goog.style.getPageOffset(test3.lastChild); - var bottomRight = new goog.math.Coordinate( - pageOffset.x + test3.lastChild.offsetWidth, - pageOffset.y + test3.lastChild.offsetHeight); - - if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('8')) { - bottomRight.x += 6; - bottomRight.y += 2; - } - - try { - var result = assertNotThrows(goog.bind(range.getEndPosition, range)); - assertObjectRoughlyEquals(bottomRight, result, 1); - } catch (e) { - expectedFailures.handleException(e); - } -} - -function testGetEndPositionNotInDocument() { - expectedFailures.expectFailureFor(goog.userAgent.GECKO && - !goog.userAgent.isVersionOrHigher('2')); - expectedFailures.expectFailureFor(goog.userAgent.IE && - !goog.userAgent.isVersionOrHigher('8')); - - var range = goog.dom.TextRange.createFromNodeContents(test3); - - goog.dom.removeNode(test3); - try { - var result = assertNotThrows(goog.bind(range.getEndPosition, range)); - assertNull(result); - } catch (e) { - expectedFailures.handleException(e); - } finally { - goog.dom.appendChild(document.body, test3); - } -} - -function testGetEndPositionReversed() { - expectedFailures.expectFailureFor(goog.userAgent.GECKO && - !goog.userAgent.isVersionOrHigher('2')); - - // Simulate the user selecting backwards from right-to-left. - // The end node is now in the top left. - var firstNode = test3.firstChild.firstChild; - var lastNode = test3.lastChild.lastChild; - var range = goog.dom.TextRange.createFromNodes( - lastNode, lastNode.nodeValue.length, firstNode, 0); - var topLeft = goog.style.getPageOffset(test3.firstChild); - - if (goog.userAgent.IE) { - // On IE the selection is as tall as its tallest element. - var logoPosition = goog.style.getPageOffset(logo3); - topLeft.y = logoPosition.y; - - if (!goog.userAgent.isVersionOrHigher('8')) { - topLeft.x += 2; - topLeft.y += 2; - } - } - - try { - var result = assertNotThrows(goog.bind(range.getEndPosition, range)); - assertObjectEquals(topLeft, result); - } catch (e) { - expectedFailures.handleException(e); - } -} - -function testGetEndPositionRightToLeft() { - expectedFailures.expectFailureFor(goog.userAgent.GECKO && - !goog.userAgent.isVersionOrHigher('2')); - expectedFailures.expectFailureFor(goog.userAgent.IE && - !goog.userAgent.isVersionOrHigher('8')); - - // Even in RTL content the end node is still in the bottom right. - var range = goog.dom.TextRange.createFromNodeContents(test3Rtl); - var pageOffset = goog.style.getPageOffset(test3Rtl.lastChild); - var bottomRight = new goog.math.Coordinate( - pageOffset.x + test3Rtl.lastChild.offsetWidth, - pageOffset.y + test3Rtl.lastChild.offsetHeight); - - if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('8')) { - bottomRight.x += 2; - bottomRight.y += 2; - } - - try { - var result = assertNotThrows(goog.bind(range.getEndPosition, range)); - assertObjectRoughlyEquals(bottomRight, result, 1); - } catch (e) { - expectedFailures.handleException(e); - } -} - -function testCloneRangeDeep() { - var range = goog.dom.TextRange.createFromNodeContents(logo); - assertFalse(range.isCollapsed()); - - var cloned = range.clone(); - cloned.collapse(); - assertTrue(cloned.isCollapsed()); - assertFalse(range.isCollapsed()); -} diff --git a/src/database/third_party/closure-library/closure/goog/dom/textrangeiterator.js b/src/database/third_party/closure-library/closure/goog/dom/textrangeiterator.js deleted file mode 100644 index 7759b371740..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/textrangeiterator.js +++ /dev/null @@ -1,246 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Iterator between two DOM text range positions. - * - * @author robbyw@google.com (Robby Walker) - */ - -goog.provide('goog.dom.TextRangeIterator'); - -goog.require('goog.array'); -goog.require('goog.dom'); -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.RangeIterator'); -goog.require('goog.dom.TagName'); -goog.require('goog.iter.StopIteration'); - - - -/** - * Subclass of goog.dom.TagIterator that iterates over a DOM range. It - * adds functions to determine the portion of each text node that is selected. - * - * @param {Node} startNode The starting node position. - * @param {number} startOffset The offset in to startNode. If startNode is - * an element, indicates an offset in to childNodes. If startNode is a - * text node, indicates an offset in to nodeValue. - * @param {Node} endNode The ending node position. - * @param {number} endOffset The offset in to endNode. If endNode is - * an element, indicates an offset in to childNodes. If endNode is a - * text node, indicates an offset in to nodeValue. - * @param {boolean=} opt_reverse Whether to traverse nodes in reverse. - * @constructor - * @extends {goog.dom.RangeIterator} - * @final - */ -goog.dom.TextRangeIterator = function(startNode, startOffset, endNode, - endOffset, opt_reverse) { - var goNext; - - if (startNode) { - this.startNode_ = startNode; - this.startOffset_ = startOffset; - this.endNode_ = endNode; - this.endOffset_ = endOffset; - - // Skip to the offset nodes - being careful to special case BRs since these - // have no children but still can appear as the startContainer of a range. - if (startNode.nodeType == goog.dom.NodeType.ELEMENT && - startNode.tagName != goog.dom.TagName.BR) { - var startChildren = startNode.childNodes; - var candidate = startChildren[startOffset]; - if (candidate) { - this.startNode_ = candidate; - this.startOffset_ = 0; - } else { - if (startChildren.length) { - this.startNode_ = - /** @type {Node} */ (goog.array.peek(startChildren)); - } - goNext = true; - } - } - - if (endNode.nodeType == goog.dom.NodeType.ELEMENT) { - this.endNode_ = endNode.childNodes[endOffset]; - if (this.endNode_) { - this.endOffset_ = 0; - } else { - // The offset was past the last element. - this.endNode_ = endNode; - } - } - } - - goog.dom.RangeIterator.call(this, opt_reverse ? this.endNode_ : - this.startNode_, opt_reverse); - - if (goNext) { - try { - this.next(); - } catch (e) { - if (e != goog.iter.StopIteration) { - throw e; - } - } - } -}; -goog.inherits(goog.dom.TextRangeIterator, goog.dom.RangeIterator); - - -/** - * The first node in the selection. - * @type {Node} - * @private - */ -goog.dom.TextRangeIterator.prototype.startNode_ = null; - - -/** - * The last node in the selection. - * @type {Node} - * @private - */ -goog.dom.TextRangeIterator.prototype.endNode_ = null; - - -/** - * The offset within the first node in the selection. - * @type {number} - * @private - */ -goog.dom.TextRangeIterator.prototype.startOffset_ = 0; - - -/** - * The offset within the last node in the selection. - * @type {number} - * @private - */ -goog.dom.TextRangeIterator.prototype.endOffset_ = 0; - - -/** @override */ -goog.dom.TextRangeIterator.prototype.getStartTextOffset = function() { - // Offsets only apply to text nodes. If our current node is the start node, - // return the saved offset. Otherwise, return 0. - return this.node.nodeType != goog.dom.NodeType.TEXT ? -1 : - this.node == this.startNode_ ? this.startOffset_ : 0; -}; - - -/** @override */ -goog.dom.TextRangeIterator.prototype.getEndTextOffset = function() { - // Offsets only apply to text nodes. If our current node is the end node, - // return the saved offset. Otherwise, return the length of the node. - return this.node.nodeType != goog.dom.NodeType.TEXT ? -1 : - this.node == this.endNode_ ? this.endOffset_ : this.node.nodeValue.length; -}; - - -/** @override */ -goog.dom.TextRangeIterator.prototype.getStartNode = function() { - return this.startNode_; -}; - - -/** - * Change the start node of the iterator. - * @param {Node} node The new start node. - */ -goog.dom.TextRangeIterator.prototype.setStartNode = function(node) { - if (!this.isStarted()) { - this.setPosition(node); - } - - this.startNode_ = node; - this.startOffset_ = 0; -}; - - -/** @override */ -goog.dom.TextRangeIterator.prototype.getEndNode = function() { - return this.endNode_; -}; - - -/** - * Change the end node of the iterator. - * @param {Node} node The new end node. - */ -goog.dom.TextRangeIterator.prototype.setEndNode = function(node) { - this.endNode_ = node; - this.endOffset_ = 0; -}; - - -/** @override */ -goog.dom.TextRangeIterator.prototype.isLast = function() { - return this.isStarted() && this.node == this.endNode_ && - (!this.endOffset_ || !this.isStartTag()); -}; - - -/** - * Move to the next position in the selection. - * Throws {@code goog.iter.StopIteration} when it passes the end of the range. - * @return {Node} The node at the next position. - * @override - */ -goog.dom.TextRangeIterator.prototype.next = function() { - if (this.isLast()) { - throw goog.iter.StopIteration; - } - - // Call the super function. - return goog.dom.TextRangeIterator.superClass_.next.call(this); -}; - - -/** @override */ -goog.dom.TextRangeIterator.prototype.skipTag = function() { - goog.dom.TextRangeIterator.superClass_.skipTag.apply(this); - - // If the node we are skipping contains the end node, we just skipped past - // the end, so we stop the iteration. - if (goog.dom.contains(this.node, this.endNode_)) { - throw goog.iter.StopIteration; - } -}; - - -/** @override */ -goog.dom.TextRangeIterator.prototype.copyFrom = function(other) { - this.startNode_ = other.startNode_; - this.endNode_ = other.endNode_; - this.startOffset_ = other.startOffset_; - this.endOffset_ = other.endOffset_; - this.isReversed_ = other.isReversed_; - - goog.dom.TextRangeIterator.superClass_.copyFrom.call(this, other); -}; - - -/** - * @return {!goog.dom.TextRangeIterator} An identical iterator. - * @override - */ -goog.dom.TextRangeIterator.prototype.clone = function() { - var copy = new goog.dom.TextRangeIterator(this.startNode_, - this.startOffset_, this.endNode_, this.endOffset_, this.isReversed_); - copy.copyFrom(this); - return copy; -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/textrangeiterator_test.html b/src/database/third_party/closure-library/closure/goog/dom/textrangeiterator_test.html deleted file mode 100644 index 55469487295..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/textrangeiterator_test.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - -goog.dom.TextRangeIterator Tests - - - - - - -
    Text

    Text

    -
      foo
      bar
    - - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/textrangeiterator_test.js b/src/database/third_party/closure-library/closure/goog/dom/textrangeiterator_test.js deleted file mode 100644 index af4af6de790..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/textrangeiterator_test.js +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.dom.TextRangeIteratorTest'); -goog.setTestOnly('goog.dom.TextRangeIteratorTest'); - -goog.require('goog.dom'); -goog.require('goog.dom.TagName'); -goog.require('goog.dom.TextRangeIterator'); -goog.require('goog.iter.StopIteration'); -goog.require('goog.testing.dom'); -goog.require('goog.testing.jsunit'); - -var test; -var test2; - -function setUpPage() { - test = goog.dom.getElement('test'); - test2 = goog.dom.getElement('test2'); -} - -function testBasic() { - goog.testing.dom.assertNodesMatch( - new goog.dom.TextRangeIterator(test, 0, test, 2), - ['#a1', 'T', '#b1', 'e', '#b1', 'xt', '#a1', '#span1', - '#span1', '#p1']); -} - -function testAdjustStart() { - var iterator = new goog.dom.TextRangeIterator(test, 0, test, 2); - iterator.setStartNode(goog.dom.getElement('span1')); - - goog.testing.dom.assertNodesMatch(iterator, - ['#span1', '#span1', '#p1']); -} - -function testAdjustEnd() { - var iterator = new goog.dom.TextRangeIterator(test, 0, test, 2); - iterator.setEndNode(goog.dom.getElement('span1')); - - goog.testing.dom.assertNodesMatch(iterator, - ['#a1', 'T', '#b1', 'e', '#b1', 'xt', '#a1', '#span1']); -} - -function testOffsets() { - var iterator = new goog.dom.TextRangeIterator(test2.firstChild, 1, - test2.lastChild, 2); - - // foo - var node = iterator.next(); - assertEquals('Should have start offset at iteration step 1', 1, - iterator.getStartTextOffset()); - assertEquals('Should not have end offset at iteration step 1', - node.nodeValue.length, iterator.getEndTextOffset()); - - //
    - node = iterator.next(); - assertEquals('Should not have start offset at iteration step 2', -1, - iterator.getStartTextOffset()); - assertEquals('Should not have end offset at iteration step 2', -1, - iterator.getEndTextOffset()); - - //
    - node = iterator.next(); - assertEquals('Should not have start offset at iteration step 3', -1, - iterator.getStartTextOffset()); - assertEquals('Should not have end offset at iteration step 3', -1, - iterator.getEndTextOffset()); - - // bar - node = iterator.next(); - assertEquals('Should not have start offset at iteration step 4', 0, - iterator.getStartTextOffset()); - assertEquals('Should have end offset at iteration step 4', 2, - iterator.getEndTextOffset()); -} - -function testSingleNodeOffsets() { - var iterator = new goog.dom.TextRangeIterator(test2.firstChild, 1, - test2.firstChild, 2); - - iterator.next(); - assertEquals('Should have start offset', 1, iterator.getStartTextOffset()); - assertEquals('Should have end offset', 2, iterator.getEndTextOffset()); -} - -function testEndNodeOffsetAtEnd() { - var iterator = new goog.dom.TextRangeIterator( - goog.dom.getElement('b1').firstChild, 0, goog.dom.getElement('b1'), 1); - goog.testing.dom.assertNodesMatch(iterator, ['e', '#b1']); -} - -function testSkipTagDoesNotSkipEnd() { - // Iterate over 'Tex'. - var iterator = new goog.dom.TextRangeIterator( - test.firstChild.firstChild, 0, - test.firstChild.lastChild, 1); - - var node = iterator.next(); - assertEquals('T', node.nodeValue); - - node = iterator.next(); - assertEquals(goog.dom.TagName.B, node.tagName); - - iterator.skipTag(); - - node = iterator.next(); - assertEquals('xt', node.nodeValue); -} - -function testSkipTagSkipsEnd() { - // Iterate over 'Te'. - var iterator = new goog.dom.TextRangeIterator( - test.firstChild.firstChild, 0, - test.getElementsByTagName(goog.dom.TagName.B)[0].firstChild, 1); - - var node = iterator.next(); - assertEquals('T', node.nodeValue); - - node = iterator.next(); - assertEquals(goog.dom.TagName.B, node.tagName); - - var ex = assertThrows('Should stop iteration when skipping B', function() { - iterator.skipTag(); - }); - assertEquals(goog.iter.StopIteration, ex); -} diff --git a/src/database/third_party/closure-library/closure/goog/dom/vendor.js b/src/database/third_party/closure-library/closure/goog/dom/vendor.js deleted file mode 100644 index 7c1123ec4aa..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/vendor.js +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2012 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Vendor prefix getters. - */ - -goog.provide('goog.dom.vendor'); - -goog.require('goog.string'); -goog.require('goog.userAgent'); - - -/** - * Returns the JS vendor prefix used in CSS properties. Different vendors - * use different methods of changing the case of the property names. - * - * @return {?string} The JS vendor prefix or null if there is none. - */ -goog.dom.vendor.getVendorJsPrefix = function() { - if (goog.userAgent.WEBKIT) { - return 'Webkit'; - } else if (goog.userAgent.GECKO) { - return 'Moz'; - } else if (goog.userAgent.IE) { - return 'ms'; - } else if (goog.userAgent.OPERA) { - return 'O'; - } - - return null; -}; - - -/** - * Returns the vendor prefix used in CSS properties. - * - * @return {?string} The vendor prefix or null if there is none. - */ -goog.dom.vendor.getVendorPrefix = function() { - if (goog.userAgent.WEBKIT) { - return '-webkit'; - } else if (goog.userAgent.GECKO) { - return '-moz'; - } else if (goog.userAgent.IE) { - return '-ms'; - } else if (goog.userAgent.OPERA) { - return '-o'; - } - - return null; -}; - - -/** - * @param {string} propertyName A property name. - * @param {!Object=} opt_object If provided, we verify if the property exists in - * the object. - * @return {?string} A vendor prefixed property name, or null if it does not - * exist. - */ -goog.dom.vendor.getPrefixedPropertyName = function(propertyName, opt_object) { - // We first check for a non-prefixed property, if available. - if (opt_object && propertyName in opt_object) { - return propertyName; - } - var prefix = goog.dom.vendor.getVendorJsPrefix(); - if (prefix) { - prefix = prefix.toLowerCase(); - var prefixedPropertyName = prefix + goog.string.toTitleCase(propertyName); - return (!goog.isDef(opt_object) || prefixedPropertyName in opt_object) ? - prefixedPropertyName : null; - } - return null; -}; - - -/** - * @param {string} eventType An event type. - * @return {string} A lower-cased vendor prefixed event type. - */ -goog.dom.vendor.getPrefixedEventType = function(eventType) { - var prefix = goog.dom.vendor.getVendorJsPrefix() || ''; - return (prefix + eventType).toLowerCase(); -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/vendor_test.html b/src/database/third_party/closure-library/closure/goog/dom/vendor_test.html deleted file mode 100644 index a2df5f5b980..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/vendor_test.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - -Closure Unit Tests - goog.dom.vendor - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/vendor_test.js b/src/database/third_party/closure-library/closure/goog/dom/vendor_test.js deleted file mode 100644 index 00dddbfd4d7..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/vendor_test.js +++ /dev/null @@ -1,273 +0,0 @@ -// Copyright 2012 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.dom.vendorTest'); -goog.setTestOnly('goog.dom.vendorTest'); - -goog.require('goog.array'); -goog.require('goog.dom.vendor'); -goog.require('goog.labs.userAgent.util'); -goog.require('goog.testing.MockUserAgent'); -goog.require('goog.testing.PropertyReplacer'); -goog.require('goog.testing.jsunit'); -goog.require('goog.userAgent'); -goog.require('goog.userAgentTestUtil'); - -var documentMode; -var mockUserAgent; -var propertyReplacer = new goog.testing.PropertyReplacer(); - -function setUp() { - mockUserAgent = new goog.testing.MockUserAgent(); - mockUserAgent.install(); -} - -function tearDown() { - goog.dispose(mockUserAgent); - documentMode = undefined; - propertyReplacer.reset(); -} - -goog.userAgent.getDocumentMode_ = function() { - return documentMode; -}; - - -var UserAgents = { - GECKO: 'GECKO', - IE: 'IE', - OPERA: 'OPERA', - WEBKIT: 'WEBKIT' -}; - - -/** - * Return whether a given user agent has been detected. - * @param {number} agent Value in UserAgents. - * @return {boolean} Whether the user agent has been detected. - */ -function getUserAgentDetected_(agent) { - switch (agent) { - case UserAgents.GECKO: - return goog.userAgent.GECKO; - case UserAgents.IE: - return goog.userAgent.IE; - case UserAgents.OPERA: - return goog.userAgent.OPERA; - case UserAgents.WEBKIT: - return goog.userAgent.WEBKIT; - } - return null; -} - - -/** - * Test browser detection for a user agent configuration. - * @param {Array} expectedAgents Array of expected userAgents. - * @param {string} uaString User agent string. - * @param {string=} opt_product Navigator product string. - * @param {string=} opt_vendor Navigator vendor string. - */ -function assertUserAgent(expectedAgents, uaString, opt_product, opt_vendor) { - var mockNavigator = { - 'userAgent': uaString, - 'product': opt_product, - 'vendor': opt_vendor - }; - - mockUserAgent.setNavigator(mockNavigator); - mockUserAgent.setUserAgentString(uaString); - - // Force reread of navigator.userAgent; - goog.labs.userAgent.util.setUserAgent(null); - goog.userAgentTestUtil.reinitializeUserAgent(); - for (var ua in UserAgents) { - var isExpected = goog.array.contains(expectedAgents, UserAgents[ua]); - assertEquals(isExpected, getUserAgentDetected_(UserAgents[ua])); - } -} - - -/** - * Tests for the vendor prefix for Webkit. - */ -function testVendorPrefixWebkit() { - assertUserAgent([UserAgents.WEBKIT], 'WebKit'); - assertEquals('-webkit', goog.dom.vendor.getVendorPrefix()); -} - - -/** - * Tests for the vendor prefix for Mozilla/Gecko. - */ -function testVendorPrefixGecko() { - assertUserAgent([UserAgents.GECKO], 'Gecko', 'Gecko'); - assertEquals('-moz', goog.dom.vendor.getVendorPrefix()); -} - - -/** - * Tests for the vendor prefix for Opera. - */ -function testVendorPrefixOpera() { - assertUserAgent([UserAgents.OPERA], 'Opera'); - assertEquals('-o', goog.dom.vendor.getVendorPrefix()); -} - - -/** - * Tests for the vendor prefix for IE. - */ -function testVendorPrefixIE() { - assertUserAgent([UserAgents.IE], 'MSIE'); - assertEquals('-ms', goog.dom.vendor.getVendorPrefix()); -} - - -/** - * Tests for the vendor Js prefix for Webkit. - */ -function testVendorJsPrefixWebkit() { - assertUserAgent([UserAgents.WEBKIT], 'WebKit'); - assertEquals('Webkit', goog.dom.vendor.getVendorJsPrefix()); -} - - -/** - * Tests for the vendor Js prefix for Mozilla/Gecko. - */ -function testVendorJsPrefixGecko() { - assertUserAgent([UserAgents.GECKO], 'Gecko', 'Gecko'); - assertEquals('Moz', goog.dom.vendor.getVendorJsPrefix()); -} - - -/** - * Tests for the vendor Js prefix for Opera. - */ -function testVendorJsPrefixOpera() { - assertUserAgent([UserAgents.OPERA], 'Opera'); - assertEquals('O', goog.dom.vendor.getVendorJsPrefix()); -} - - -/** - * Tests for the vendor Js prefix for IE. - */ -function testVendorJsPrefixIE() { - assertUserAgent([UserAgents.IE], 'MSIE'); - assertEquals('ms', goog.dom.vendor.getVendorJsPrefix()); -} - - -/** - * Tests for the vendor Js prefix if no UA detected. - */ -function testVendorJsPrefixNone() { - assertUserAgent([], ''); - assertNull(goog.dom.vendor.getVendorJsPrefix()); -} - - -/** - * Tests for the prefixed property name on Webkit. - */ -function testPrefixedPropertyNameWebkit() { - assertUserAgent([UserAgents.WEBKIT], 'WebKit'); - assertEquals('webkitFoobar', - goog.dom.vendor.getPrefixedPropertyName('foobar')); -} - - -/** - * Tests for the prefixed property name on Webkit in an object. - */ -function testPrefixedPropertyNameWebkitAndObject() { - var mockDocument = { - // setting a value of 0 on purpose, to ensure we only look for property - // names, not their values. - 'webkitFoobar': 0 - }; - assertUserAgent([UserAgents.WEBKIT], 'WebKit'); - assertEquals('webkitFoobar', - goog.dom.vendor.getPrefixedPropertyName('foobar', mockDocument)); -} - - -/** - * Tests for the prefixed property name. - */ -function testPrefixedPropertyName() { - assertUserAgent([], ''); - assertNull(goog.dom.vendor.getPrefixedPropertyName('foobar')); -} - - -/** - * Tests for the prefixed property name in an object. - */ -function testPrefixedPropertyNameAndObject() { - var mockDocument = { - 'foobar': 0 - }; - assertUserAgent([], ''); - assertEquals('foobar', - goog.dom.vendor.getPrefixedPropertyName('foobar', mockDocument)); -} - - -/** - * Tests for the prefixed property name when it doesn't exist. - */ -function testPrefixedPropertyNameAndObjectIsEmpty() { - var mockDocument = {}; - assertUserAgent([], ''); - assertNull(goog.dom.vendor.getPrefixedPropertyName('foobar', mockDocument)); -} - - -/** - * Test for prefixed event type. - */ -function testPrefixedEventType() { - assertUserAgent([], ''); - assertEquals('foobar', goog.dom.vendor.getPrefixedEventType('foobar')); -} - - -/** - * Test for browser-specific prefixed event type. - */ -function testPrefixedEventTypeForBrowser() { - assertUserAgent([UserAgents.WEBKIT], 'WebKit'); - assertEquals('webkitfoobar', goog.dom.vendor.getPrefixedEventType('foobar')); -} - - -function assertIe(uaString, expectedVersion) { - assertUserAgent([UserAgents.IE], uaString); - assertEquals('User agent ' + uaString + ' should have had version ' + - expectedVersion + ' but had ' + goog.userAgent.VERSION, - expectedVersion, - goog.userAgent.VERSION); -} - - -function assertGecko(uaString, expectedVersion) { - assertUserAgent([UserAgents.GECKO], uaString, 'Gecko'); - assertEquals('User agent ' + uaString + ' should have had version ' + - expectedVersion + ' but had ' + goog.userAgent.VERSION, - expectedVersion, - goog.userAgent.VERSION); -} diff --git a/src/database/third_party/closure-library/closure/goog/dom/viewportsizemonitor.js b/src/database/third_party/closure-library/closure/goog/dom/viewportsizemonitor.js deleted file mode 100644 index 8e0aedca8f9..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/viewportsizemonitor.js +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utility class that monitors viewport size changes. - * - * @author attila@google.com (Attila Bodis) - * @see ../demos/viewportsizemonitor.html - */ - -goog.provide('goog.dom.ViewportSizeMonitor'); - -goog.require('goog.dom'); -goog.require('goog.events'); -goog.require('goog.events.EventTarget'); -goog.require('goog.events.EventType'); -goog.require('goog.math.Size'); - - - -/** - * This class can be used to monitor changes in the viewport size. Instances - * dispatch a {@link goog.events.EventType.RESIZE} event when the viewport size - * changes. Handlers can call {@link goog.dom.ViewportSizeMonitor#getSize} to - * get the new viewport size. - * - * Use this class if you want to execute resize/reflow logic each time the - * user resizes the browser window. This class is guaranteed to only dispatch - * {@code RESIZE} events when the pixel dimensions of the viewport change. - * (Internet Explorer fires resize events if any element on the page is resized, - * even if the viewport dimensions are unchanged, which can lead to infinite - * resize loops.) - * - * Example usage: - *
    - *    var vsm = new goog.dom.ViewportSizeMonitor();
    - *    goog.events.listen(vsm, goog.events.EventType.RESIZE, function(e) {
    - *      alert('Viewport size changed to ' + vsm.getSize());
    - *    });
    - *  
    - * - * Manually verified on IE6, IE7, FF2, Opera 11, Safari 4 and Chrome. - * - * @param {Window=} opt_window The window to monitor; defaults to the window in - * which this code is executing. - * @constructor - * @extends {goog.events.EventTarget} - */ -goog.dom.ViewportSizeMonitor = function(opt_window) { - goog.events.EventTarget.call(this); - - // Default the window to the current window if unspecified. - this.window_ = opt_window || window; - - // Listen for window resize events. - this.listenerKey_ = goog.events.listen(this.window_, - goog.events.EventType.RESIZE, this.handleResize_, false, this); - - // Set the initial size. - this.size_ = goog.dom.getViewportSize(this.window_); -}; -goog.inherits(goog.dom.ViewportSizeMonitor, goog.events.EventTarget); - - -/** - * Returns a viewport size monitor for the given window. A new one is created - * if it doesn't exist already. This prevents the unnecessary creation of - * multiple spooling monitors for a window. - * @param {Window=} opt_window The window to monitor; defaults to the window in - * which this code is executing. - * @return {!goog.dom.ViewportSizeMonitor} Monitor for the given window. - */ -goog.dom.ViewportSizeMonitor.getInstanceForWindow = function(opt_window) { - var currentWindow = opt_window || window; - var uid = goog.getUid(currentWindow); - - return goog.dom.ViewportSizeMonitor.windowInstanceMap_[uid] = - goog.dom.ViewportSizeMonitor.windowInstanceMap_[uid] || - new goog.dom.ViewportSizeMonitor(currentWindow); -}; - - -/** - * Removes and disposes a viewport size monitor for the given window if one - * exists. - * @param {Window=} opt_window The window whose monitor should be removed; - * defaults to the window in which this code is executing. - */ -goog.dom.ViewportSizeMonitor.removeInstanceForWindow = function(opt_window) { - var uid = goog.getUid(opt_window || window); - - goog.dispose(goog.dom.ViewportSizeMonitor.windowInstanceMap_[uid]); - delete goog.dom.ViewportSizeMonitor.windowInstanceMap_[uid]; -}; - - -/** - * Map of window hash code to viewport size monitor for that window, if - * created. - * @type {Object} - * @private - */ -goog.dom.ViewportSizeMonitor.windowInstanceMap_ = {}; - - -/** - * Event listener key for window the window resize handler, as returned by - * {@link goog.events.listen}. - * @type {goog.events.Key} - * @private - */ -goog.dom.ViewportSizeMonitor.prototype.listenerKey_ = null; - - -/** - * The window to monitor. Defaults to the window in which the code is running. - * @type {Window} - * @private - */ -goog.dom.ViewportSizeMonitor.prototype.window_ = null; - - -/** - * The most recently recorded size of the viewport, in pixels. - * @type {goog.math.Size?} - * @private - */ -goog.dom.ViewportSizeMonitor.prototype.size_ = null; - - -/** - * Returns the most recently recorded size of the viewport, in pixels. May - * return null if no window resize event has been handled yet. - * @return {goog.math.Size} The viewport dimensions, in pixels. - */ -goog.dom.ViewportSizeMonitor.prototype.getSize = function() { - // Return a clone instead of the original to preserve encapsulation. - return this.size_ ? this.size_.clone() : null; -}; - - -/** @override */ -goog.dom.ViewportSizeMonitor.prototype.disposeInternal = function() { - goog.dom.ViewportSizeMonitor.superClass_.disposeInternal.call(this); - - if (this.listenerKey_) { - goog.events.unlistenByKey(this.listenerKey_); - this.listenerKey_ = null; - } - - this.window_ = null; - this.size_ = null; -}; - - -/** - * Handles window resize events by measuring the dimensions of the - * viewport and dispatching a {@link goog.events.EventType.RESIZE} event if the - * current dimensions are different from the previous ones. - * @param {goog.events.Event} event The window resize event to handle. - * @private - */ -goog.dom.ViewportSizeMonitor.prototype.handleResize_ = function(event) { - var size = goog.dom.getViewportSize(this.window_); - if (!goog.math.Size.equals(size, this.size_)) { - this.size_ = size; - this.dispatchEvent(goog.events.EventType.RESIZE); - } -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/viewportsizemonitor_test.html b/src/database/third_party/closure-library/closure/goog/dom/viewportsizemonitor_test.html deleted file mode 100644 index 5ec740bc34b..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/viewportsizemonitor_test.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - -Closure Unit Tests - goog.dom.ViewportSizeMonitor - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/viewportsizemonitor_test.js b/src/database/third_party/closure-library/closure/goog/dom/viewportsizemonitor_test.js deleted file mode 100644 index aba768ab176..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/viewportsizemonitor_test.js +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.dom.ViewportSizeMonitorTest'); -goog.setTestOnly('goog.dom.ViewportSizeMonitorTest'); - -goog.require('goog.dom.ViewportSizeMonitor'); -goog.require('goog.events'); -goog.require('goog.events.Event'); -goog.require('goog.events.EventTarget'); -goog.require('goog.events.EventType'); -goog.require('goog.math.Size'); -goog.require('goog.testing.MockClock'); -goog.require('goog.testing.PropertyReplacer'); -goog.require('goog.testing.jsunit'); - -var propertyReplacer, fakeWindow, viewportSizeMonitor, mockClock; - - -function FakeWindow() { - goog.base(this); -} -goog.inherits(FakeWindow, goog.events.EventTarget); - - -FakeWindow.prototype.fireResize = function() { - return this.dispatchEvent(new FakeResizeEvent()); -}; - - -function FakeResizeEvent(obj) { - this.type = goog.events.EventType.RESIZE; -} -goog.inherits(FakeResizeEvent, goog.events.Event); - - -function getViewportSize() { - return viewportSize; -} - - -function setViewportSize(w, h, fireEvent) { - this.viewportSize = new goog.math.Size(w, h); - if (fireEvent) { - fakeWindow.fireResize(); - } -} - - -var eventWasFired = {}; -function getListenerFn(id) { - return function() { - propertyReplacer.set(eventWasFired, id, true); - }; -} - - -function listenerWasCalled(id) { - return !!eventWasFired[id]; -} - - -function setUp() { - propertyReplacer = new goog.testing.PropertyReplacer(); - propertyReplacer.set(goog.dom, 'getViewportSize', getViewportSize); - mockClock = new goog.testing.MockClock(); - mockClock.install(); - fakeWindow = new FakeWindow(); - setViewportSize(300, 300); - viewportSizeMonitor = new goog.dom.ViewportSizeMonitor(fakeWindow); -} - - -function tearDown() { - propertyReplacer.reset(); - mockClock.uninstall(); -} - - -function testResizeEvent() { - goog.events.listen(viewportSizeMonitor, goog.events.EventType.RESIZE, - getListenerFn(1)); - assertFalse('Listener should not be called if window was not resized', - listenerWasCalled(1)); - setViewportSize(300, 300, true); - assertFalse('Listener should not be called for bogus resize event', - listenerWasCalled(1)); - setViewportSize(301, 301, true); - assertTrue('Listener should be called for valid resize event', - listenerWasCalled(1)); -} - - -function testInstanceGetter() { - var fakeWindow1 = new FakeWindow(); - var monitor1 = goog.dom.ViewportSizeMonitor.getInstanceForWindow( - fakeWindow1); - var monitor2 = goog.dom.ViewportSizeMonitor.getInstanceForWindow( - fakeWindow1); - assertEquals('The same window should give us the same instance monitor', - monitor1, monitor2); - - var fakeWindow2 = new FakeWindow(); - var monitor3 = goog.dom.ViewportSizeMonitor.getInstanceForWindow( - fakeWindow2); - assertNotEquals('Different windows should give different instances', - monitor1, monitor3); - - assertEquals('Monitors should match if opt_window is not provided', - goog.dom.ViewportSizeMonitor.getInstanceForWindow(), - goog.dom.ViewportSizeMonitor.getInstanceForWindow()); -} - - -function testRemoveInstanceForWindow() { - var fakeWindow1 = new FakeWindow(); - var monitor1 = goog.dom.ViewportSizeMonitor.getInstanceForWindow( - fakeWindow1); - - goog.dom.ViewportSizeMonitor.removeInstanceForWindow(fakeWindow1); - assertTrue(monitor1.isDisposed()); - - var monitor2 = goog.dom.ViewportSizeMonitor.getInstanceForWindow( - fakeWindow1); - assertNotEquals(monitor1, monitor2); -} diff --git a/src/database/third_party/closure-library/closure/goog/dom/xml.js b/src/database/third_party/closure-library/closure/goog/dom/xml.js deleted file mode 100644 index 59f123aff2c..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/xml.js +++ /dev/null @@ -1,204 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview - * XML utilities. - * - */ - -goog.provide('goog.dom.xml'); - -goog.require('goog.dom'); -goog.require('goog.dom.NodeType'); - - -/** - * Max XML size for MSXML2. Used to prevent potential DoS attacks. - * @type {number} - */ -goog.dom.xml.MAX_XML_SIZE_KB = 2 * 1024; // In kB - - -/** - * Max XML size for MSXML2. Used to prevent potential DoS attacks. - * @type {number} - */ -goog.dom.xml.MAX_ELEMENT_DEPTH = 256; // Same default as MSXML6. - - -/** - * Creates an XML document appropriate for the current JS runtime - * @param {string=} opt_rootTagName The root tag name. - * @param {string=} opt_namespaceUri Namespace URI of the document element. - * @return {Document} The new document. - */ -goog.dom.xml.createDocument = function(opt_rootTagName, opt_namespaceUri) { - if (opt_namespaceUri && !opt_rootTagName) { - throw Error("Can't create document with namespace and no root tag"); - } - if (document.implementation && document.implementation.createDocument) { - return document.implementation.createDocument(opt_namespaceUri || '', - opt_rootTagName || '', - null); - } else if (typeof ActiveXObject != 'undefined') { - var doc = goog.dom.xml.createMsXmlDocument_(); - if (doc) { - if (opt_rootTagName) { - doc.appendChild(doc.createNode(goog.dom.NodeType.ELEMENT, - opt_rootTagName, - opt_namespaceUri || '')); - } - return doc; - } - } - throw Error('Your browser does not support creating new documents'); -}; - - -/** - * Creates an XML document from a string - * @param {string} xml The text. - * @return {Document} XML document from the text. - */ -goog.dom.xml.loadXml = function(xml) { - if (typeof DOMParser != 'undefined') { - return new DOMParser().parseFromString(xml, 'application/xml'); - } else if (typeof ActiveXObject != 'undefined') { - var doc = goog.dom.xml.createMsXmlDocument_(); - doc.loadXML(xml); - return doc; - } - throw Error('Your browser does not support loading xml documents'); -}; - - -/** - * Serializes an XML document or subtree to string. - * @param {Document|Element} xml The document or the root node of the subtree. - * @return {string} The serialized XML. - */ -goog.dom.xml.serialize = function(xml) { - // Compatible with Firefox, Opera and WebKit. - if (typeof XMLSerializer != 'undefined') { - return new XMLSerializer().serializeToString(xml); - } - // Compatible with Internet Explorer. - var text = xml.xml; - if (text) { - return text; - } - throw Error('Your browser does not support serializing XML documents'); -}; - - -/** - * Selects a single node using an Xpath expression and a root node - * @param {Node} node The root node. - * @param {string} path Xpath selector. - * @return {Node} The selected node, or null if no matching node. - */ -goog.dom.xml.selectSingleNode = function(node, path) { - if (typeof node.selectSingleNode != 'undefined') { - var doc = goog.dom.getOwnerDocument(node); - if (typeof doc.setProperty != 'undefined') { - doc.setProperty('SelectionLanguage', 'XPath'); - } - return node.selectSingleNode(path); - } else if (document.implementation.hasFeature('XPath', '3.0')) { - var doc = goog.dom.getOwnerDocument(node); - var resolver = doc.createNSResolver(doc.documentElement); - var result = doc.evaluate(path, node, resolver, - XPathResult.FIRST_ORDERED_NODE_TYPE, null); - return result.singleNodeValue; - } - return null; -}; - - -/** - * Selects multiple nodes using an Xpath expression and a root node - * @param {Node} node The root node. - * @param {string} path Xpath selector. - * @return {(NodeList|Array)} The selected nodes, or empty array if no - * matching nodes. - */ -goog.dom.xml.selectNodes = function(node, path) { - if (typeof node.selectNodes != 'undefined') { - var doc = goog.dom.getOwnerDocument(node); - if (typeof doc.setProperty != 'undefined') { - doc.setProperty('SelectionLanguage', 'XPath'); - } - return node.selectNodes(path); - } else if (document.implementation.hasFeature('XPath', '3.0')) { - var doc = goog.dom.getOwnerDocument(node); - var resolver = doc.createNSResolver(doc.documentElement); - var nodes = doc.evaluate(path, node, resolver, - XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); - var results = []; - var count = nodes.snapshotLength; - for (var i = 0; i < count; i++) { - results.push(nodes.snapshotItem(i)); - } - return results; - } else { - return []; - } -}; - - -/** - * Sets multiple attributes on an element. Differs from goog.dom.setProperties - * in that it exclusively uses the element's setAttributes method. Use this - * when you need to ensure that the exact property is available as an attribute - * and can be read later by the native getAttribute method. - * @param {!Element} element XML or DOM element to set attributes on. - * @param {!Object} attributes Map of property:value pairs. - */ -goog.dom.xml.setAttributes = function(element, attributes) { - for (var key in attributes) { - if (attributes.hasOwnProperty(key)) { - element.setAttribute(key, attributes[key]); - } - } -}; - - -/** - * Creates an instance of the MSXML2.DOMDocument. - * @return {Document} The new document. - * @private - */ -goog.dom.xml.createMsXmlDocument_ = function() { - var doc = new ActiveXObject('MSXML2.DOMDocument'); - if (doc) { - // Prevent potential vulnerabilities exposed by MSXML2, see - // http://b/1707300 and http://wiki/Main/ISETeamXMLAttacks for details. - doc.resolveExternals = false; - doc.validateOnParse = false; - // Add a try catch block because accessing these properties will throw an - // error on unsupported MSXML versions. This affects Windows machines - // running IE6 or IE7 that are on XP SP2 or earlier without MSXML updates. - // See http://msdn.microsoft.com/en-us/library/ms766391(VS.85).aspx for - // specific details on which MSXML versions support these properties. - try { - doc.setProperty('ProhibitDTD', true); - doc.setProperty('MaxXMLSize', goog.dom.xml.MAX_XML_SIZE_KB); - doc.setProperty('MaxElementDepth', goog.dom.xml.MAX_ELEMENT_DEPTH); - } catch (e) { - // No-op. - } - } - return doc; -}; diff --git a/src/database/third_party/closure-library/closure/goog/dom/xml_test.html b/src/database/third_party/closure-library/closure/goog/dom/xml_test.html deleted file mode 100644 index 254371b8638..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/xml_test.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - -Closure Unit Tests - goog.dom.xml - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/dom/xml_test.js b/src/database/third_party/closure-library/closure/goog/dom/xml_test.js deleted file mode 100644 index 918a2574e40..00000000000 --- a/src/database/third_party/closure-library/closure/goog/dom/xml_test.js +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.dom.xmlTest'); -goog.setTestOnly('goog.dom.xmlTest'); - -goog.require('goog.dom.xml'); -goog.require('goog.testing.jsunit'); -goog.require('goog.userAgent'); - -function testSerialize() { - var doc = goog.dom.xml.createDocument(); - var node = doc.createElement('root'); - doc.appendChild(node); - - var serializedNode = goog.dom.xml.serialize(node); - assertTrue(//.test(serializedNode)); - - var serializedDoc = goog.dom.xml.serialize(doc); - assertTrue(/(<\?xml version="1.0"\?>)?/.test(serializedDoc)); -} - -function testBelowMaxDepthInIE() { - if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9')) { - // This value is only effective in IE8 and below - goog.dom.xml.MAX_ELEMENT_DEPTH = 5; - var junk = 'Hello'; - var doc = goog.dom.xml.loadXml(junk); - assertEquals('Should not have caused a parse error', 0, - Number(doc.parseError)); - } -} - -function testAboveMaxDepthInIE() { - if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9')) { - // This value is only effective in IE8 and below - goog.dom.xml.MAX_ELEMENT_DEPTH = 4; - var junk = 'Hello'; - var doc = goog.dom.xml.loadXml(junk); - assertNotEquals('Should have caused a parse error', 0, - Number(doc.parseError)); - } -} - -function testBelowMaxSizeInIE() { - if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9')) { - // This value is only effective in IE8 and below - goog.dom.xml.MAX_XML_SIZE_KB = 1; - var junk = '' + new Array(50).join('junk') + ''; - var doc = goog.dom.xml.loadXml(junk); - assertEquals('Should not have caused a parse error', - 0, Number(doc.parseError)); - } -} - -function testMaxSizeInIE() { - if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9')) { - // This value is only effective in IE8 and below - goog.dom.xml.MAX_XML_SIZE_KB = 1; - var junk = '' + new Array(1000).join('junk') + ''; - var doc = goog.dom.xml.loadXml(junk); - assertNotEquals('Should have caused a parse error', 0, - Number(doc.parseError)); - } -} - -function testSetAttributes() { - var xmlElement = goog.dom.xml.createDocument().createElement('root'); - var domElement = document.createElement('div'); - var attrs = { - name: 'test3', - title: 'A title', - random: 'woop', - cellpadding: '123' - }; - - goog.dom.xml.setAttributes(xmlElement, attrs); - goog.dom.xml.setAttributes(domElement, attrs); - - assertEquals('test3', xmlElement.getAttribute('name')); - assertEquals('test3', domElement.getAttribute('name')); - - assertEquals('A title', xmlElement.getAttribute('title')); - assertEquals('A title', domElement.getAttribute('title')); - - assertEquals('woop', xmlElement.getAttribute('random')); - assertEquals('woop', domElement.getAttribute('random')); - - assertEquals('123', xmlElement.getAttribute('cellpadding')); - assertEquals('123', domElement.getAttribute('cellpadding')); -} diff --git a/src/database/third_party/closure-library/closure/goog/editor/browserfeature.js b/src/database/third_party/closure-library/closure/goog/editor/browserfeature.js deleted file mode 100644 index 10ac05ee066..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/browserfeature.js +++ /dev/null @@ -1,273 +0,0 @@ -// Copyright 2005 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Trogedit constants for browser features and quirks that should - * be used by the rich text editor. - */ - -goog.provide('goog.editor.BrowserFeature'); - -goog.require('goog.editor.defines'); -goog.require('goog.userAgent'); -goog.require('goog.userAgent.product'); -goog.require('goog.userAgent.product.isVersion'); - - -/** - * Maps browser quirks to boolean values, detailing what the current - * browser supports. - * @const - */ -goog.editor.BrowserFeature = { - // Whether this browser uses the IE TextRange object. - HAS_IE_RANGES: goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9), - - // Whether this browser uses the W3C standard Range object. - // Assumes IE higher versions will be compliance with W3C standard. - HAS_W3C_RANGES: goog.userAgent.GECKO || goog.userAgent.WEBKIT || - goog.userAgent.OPERA || - (goog.userAgent.IE && goog.userAgent.isDocumentModeOrHigher(9)), - - // Has the contentEditable attribute, which makes nodes editable. - // - // NOTE(nicksantos): FF3 has contentEditable, but there are 3 major reasons - // why we don't use it: - // 1) In FF3, we listen for key events on the document, and we'd have to - // filter them properly. See TR_Browser.USE_DOCUMENT_FOR_KEY_EVENTS. - // 2) In FF3, we listen for focus/blur events on the document, which - // simply doesn't make sense in contentEditable. focus/blur - // on contentEditable elements still has some quirks, which we're - // talking to Firefox-team about. - // 3) We currently use Mutation events in FF3 to detect changes, - // and these are dispatched on the document only. - // If we ever hope to support FF3/contentEditable, all 3 of these issues - // will need answers. Most just involve refactoring at our end. - HAS_CONTENT_EDITABLE: goog.userAgent.IE || goog.userAgent.WEBKIT || - goog.userAgent.OPERA || - (goog.editor.defines.USE_CONTENTEDITABLE_IN_FIREFOX_3 && - goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.9')), - - // Whether to use mutation event types to detect changes - // in the field contents. - USE_MUTATION_EVENTS: goog.userAgent.GECKO, - - // Whether the browser has a functional DOMSubtreeModified event. - // TODO(user): Enable for all FF3 once we're confident this event fires - // reliably. Currently it's only enabled if using contentEditable in FF as - // we have no other choice in that case but to use this event. - HAS_DOM_SUBTREE_MODIFIED_EVENT: goog.userAgent.WEBKIT || - (goog.editor.defines.USE_CONTENTEDITABLE_IN_FIREFOX_3 && - goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.9')), - - // Whether nodes can be copied from one document to another - HAS_DOCUMENT_INDEPENDENT_NODES: goog.userAgent.GECKO, - - // Whether the cursor goes before or inside the first block element on - // focus, e.g.,

    foo

    . FF will put the cursor before the - // paragraph on focus, which is wrong. - PUTS_CURSOR_BEFORE_FIRST_BLOCK_ELEMENT_ON_FOCUS: goog.userAgent.GECKO, - - // Whether the selection of one frame is cleared when another frame - // is focused. - CLEARS_SELECTION_WHEN_FOCUS_LEAVES: - goog.userAgent.IE || goog.userAgent.WEBKIT || goog.userAgent.OPERA, - - // Whether "unselectable" is supported as an element style. - HAS_UNSELECTABLE_STYLE: goog.userAgent.GECKO || goog.userAgent.WEBKIT, - - // Whether this browser's "FormatBlock" command does not suck. - FORMAT_BLOCK_WORKS_FOR_BLOCKQUOTES: goog.userAgent.GECKO || - goog.userAgent.WEBKIT || goog.userAgent.OPERA, - - // Whether this browser's "FormatBlock" command may create multiple - // blockquotes. - CREATES_MULTIPLE_BLOCKQUOTES: - (goog.userAgent.WEBKIT && - !goog.userAgent.isVersionOrHigher('534.16')) || - goog.userAgent.OPERA, - - // Whether this browser's "FormatBlock" command will wrap blockquotes - // inside of divs, instead of replacing divs with blockquotes. - WRAPS_BLOCKQUOTE_IN_DIVS: goog.userAgent.OPERA, - - // Whether the readystatechange event is more reliable than load. - PREFERS_READY_STATE_CHANGE_EVENT: goog.userAgent.IE, - - // Whether hitting the tab key will fire a keypress event. - // see http://www.quirksmode.org/js/keys.html - TAB_FIRES_KEYPRESS: !goog.userAgent.IE, - - // Has a standards mode quirk where width=100% doesn't do the right thing, - // but width=99% does. - // TODO(user|user): This should be fixable by less hacky means - NEEDS_99_WIDTH_IN_STANDARDS_MODE: goog.userAgent.IE, - - // Whether keyboard events only reliably fire on the document. - // On Gecko without contentEditable, keyboard events only fire reliably on the - // document element. With contentEditable, the field itself is focusable, - // which means that it will fire key events. This does not apply if - // application is using ContentEditableField or otherwise overriding Field - // not to use an iframe. - USE_DOCUMENT_FOR_KEY_EVENTS: goog.userAgent.GECKO && - !goog.editor.defines.USE_CONTENTEDITABLE_IN_FIREFOX_3, - - // Whether this browser shows non-standard attributes in innerHTML. - SHOWS_CUSTOM_ATTRS_IN_INNER_HTML: goog.userAgent.IE, - - // Whether this browser shrinks empty nodes away to nothing. - // (If so, we need to insert some space characters into nodes that - // shouldn't be collapsed) - COLLAPSES_EMPTY_NODES: - goog.userAgent.GECKO || goog.userAgent.WEBKIT || goog.userAgent.OPERA, - - // Whether we must convert and tags to , . - CONVERT_TO_B_AND_I_TAGS: goog.userAgent.GECKO || goog.userAgent.OPERA, - - // Whether this browser likes to tab through images in contentEditable mode, - // and we like to disable this feature. - TABS_THROUGH_IMAGES: goog.userAgent.IE, - - // Whether this browser unescapes urls when you extract it from the href tag. - UNESCAPES_URLS_WITHOUT_ASKING: goog.userAgent.IE && - !goog.userAgent.isVersionOrHigher('7.0'), - - // Whether this browser supports execCommand("styleWithCSS") to toggle between - // inserting html tags or inline styling for things like bold, italic, etc. - HAS_STYLE_WITH_CSS: - goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.8') || - goog.userAgent.WEBKIT || goog.userAgent.OPERA, - - // Whether clicking on an editable link will take you to that site. - FOLLOWS_EDITABLE_LINKS: goog.userAgent.WEBKIT || - goog.userAgent.IE && goog.userAgent.isVersionOrHigher('9'), - - // Whether this browser has document.activeElement available. - HAS_ACTIVE_ELEMENT: - goog.userAgent.IE || goog.userAgent.OPERA || - goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.9'), - - // Whether this browser supports the setCapture method on DOM elements. - HAS_SET_CAPTURE: goog.userAgent.IE, - - // Whether this browser can't set background color when the selection - // is collapsed. - EATS_EMPTY_BACKGROUND_COLOR: goog.userAgent.GECKO || - goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher('527'), - - // Whether this browser supports the "focusin" or "DOMFocusIn" event - // consistently. - // NOTE(nicksantos): FF supports DOMFocusIn, but doesn't seem to do so - // consistently. - SUPPORTS_FOCUSIN: goog.userAgent.IE || goog.userAgent.OPERA, - - // Whether clicking on an image will cause the selection to move to the image. - // Note: Gecko moves the selection, but it won't always go to the image. - // For example, if the image is wrapped in a div, and you click on the img, - // anchorNode = focusNode = div, anchorOffset = 0, focusOffset = 1, so this - // is another way of "selecting" the image, but there are too many special - // cases like this so we will do the work manually. - SELECTS_IMAGES_ON_CLICK: goog.userAgent.IE || goog.userAgent.OPERA, - - // Whether this browser moves '); - - // - // Hidefocus is needed to ensure that IE7 doesn't show the dotted, focus - // border when you tab into the field. - html.push('', bodyHtml, ''); - - return html.join(''); -}; - - -/** - * Write the initial iframe content in normal mode. - * @param {goog.editor.icontent.FieldFormatInfo} info Formatting info about - * the field. - * @param {string} bodyHtml The HTML to insert as the iframe body. - * @param {goog.editor.icontent.FieldStyleInfo?} style Style info about - * the field, if needed. - * @param {HTMLIFrameElement} iframe The iframe. - */ -goog.editor.icontent.writeNormalInitialBlendedIframe = - function(info, bodyHtml, style, iframe) { - // Firefox blended needs to inherit all the css from the original page. - // Firefox standards mode needs to set extra style for images. - if (info.blended_) { - var field = style.wrapper_; - // If there is padding on the original field, then the iFrame will be - // positioned inside the padding by default. We don't want this, as it - // causes the contents to appear to shift, and also causes the - // scrollbars to appear inside the padding. - // - // To compensate, we set the iframe margins to offset the padding. - var paddingBox = goog.style.getPaddingBox(field); - if (paddingBox.top || paddingBox.left || - paddingBox.right || paddingBox.bottom) { - goog.style.setStyle(iframe, 'margin', - (-paddingBox.top) + 'px ' + - (-paddingBox.right) + 'px ' + - (-paddingBox.bottom) + 'px ' + - (-paddingBox.left) + 'px'); - } - } - - goog.editor.icontent.writeNormalInitialIframe( - info, bodyHtml, style, iframe); -}; - - -/** - * Write the initial iframe content in normal mode. - * @param {goog.editor.icontent.FieldFormatInfo} info Formatting info about - * the field. - * @param {string} bodyHtml The HTML to insert as the iframe body. - * @param {goog.editor.icontent.FieldStyleInfo?} style Style info about - * the field, if needed. - * @param {HTMLIFrameElement} iframe The iframe. - */ -goog.editor.icontent.writeNormalInitialIframe = - function(info, bodyHtml, style, iframe) { - - var html = goog.editor.icontent.getInitialIframeContent_( - info, bodyHtml, style); - - var doc = goog.dom.getFrameContentDocument(iframe); - doc.open(); - doc.write(html); - doc.close(); -}; - - -/** - * Write the initial iframe content in IE/HTTPS mode. - * @param {goog.editor.icontent.FieldFormatInfo} info Formatting info about - * the field. - * @param {Document} doc The iframe document. - * @param {string} bodyHtml The HTML to insert as the iframe body. - */ -goog.editor.icontent.writeHttpsInitialIframe = function(info, doc, bodyHtml) { - var body = doc.body; - - // For HTTPS we already have a document with a doc type and a body element - // and don't want to create a new history entry which can cause data loss if - // the user clicks the back button. - if (goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE) { - body.contentEditable = true; - } - body.className = 'editable'; - body.setAttribute('g_editable', true); - body.hideFocus = true; - body.id = info.fieldId_; - - goog.style.setStyle(body, info.extraStyles_); - body.innerHTML = bodyHtml; -}; - diff --git a/src/database/third_party/closure-library/closure/goog/editor/icontent_test.html b/src/database/third_party/closure-library/closure/goog/editor/icontent_test.html deleted file mode 100644 index 4cd0f89f0be..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/icontent_test.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - Trogedit Unit Tests - goog.editor.icontent - - - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/editor/icontent_test.js b/src/database/third_party/closure-library/closure/goog/editor/icontent_test.js deleted file mode 100644 index c767f3478e1..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/icontent_test.js +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.editor.icontentTest'); -goog.setTestOnly('goog.editor.icontentTest'); - -goog.require('goog.dom'); -goog.require('goog.editor.BrowserFeature'); -goog.require('goog.editor.icontent'); -goog.require('goog.editor.icontent.FieldFormatInfo'); -goog.require('goog.editor.icontent.FieldStyleInfo'); -goog.require('goog.testing.PropertyReplacer'); -goog.require('goog.testing.jsunit'); -goog.require('goog.userAgent'); - -var wrapperDiv; -var realIframe; -var realIframeDoc; -var propertyReplacer; - -function setUp() { - wrapperDiv = goog.dom.createDom('div', null, - realIframe = goog.dom.createDom('iframe')); - goog.dom.appendChild(document.body, wrapperDiv); - realIframeDoc = realIframe.contentWindow.document; - propertyReplacer = new goog.testing.PropertyReplacer(); -} - -function tearDown() { - goog.dom.removeNode(wrapperDiv); - propertyReplacer.reset(); -} - -function testWriteHttpsInitialIframeContent() { - // This is not a particularly useful test; it's just a sanity check to make - // sure nothing explodes - var info = - new goog.editor.icontent.FieldFormatInfo('id', false, false, false); - var doc = createMockDocument(); - goog.editor.icontent.writeHttpsInitialIframe(info, doc, 'some html'); - assertBodyCorrect(doc.body, 'id', 'some html'); -} - -function testWriteHttpsInitialIframeContentRtl() { - var info = new goog.editor.icontent.FieldFormatInfo('id', false, false, true); - var doc = createMockDocument(); - goog.editor.icontent.writeHttpsInitialIframe(info, doc, 'some html'); - assertBodyCorrect(doc.body, 'id', 'some html', true); -} - -function testWriteInitialIframeContentBlendedStandardsGrowing() { - if (goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE) { - return; // only executes when using an iframe - } - - var info = new goog.editor.icontent.FieldFormatInfo('id', true, true, false); - var styleInfo = new goog.editor.icontent.FieldStyleInfo(wrapperDiv, - '.MyClass { position: absolute; top: 500px; }'); - var doc = realIframeDoc; - var html = '
    Some Html
    '; - goog.editor.icontent.writeNormalInitialBlendedIframe(info, html, - styleInfo, realIframe); - - assertBodyCorrect(doc.body, 'id', html); - assertEquals('CSS1Compat', doc.compatMode); // standards - assertEquals('auto', doc.documentElement.style.height); // growing - assertEquals('100%', doc.body.style.height); // standards - assertEquals('hidden', doc.body.style.overflowY); // growing - assertEquals('', realIframe.style.position); // no padding on wrapper - - assertEquals(500, doc.body.firstChild.offsetTop); - assert(doc.getElementsByTagName('style')[0].innerHTML.indexOf( - '-moz-force-broken-image-icon') != -1); // standards -} - -function testWriteInitialIframeContentBlendedQuirksFixedRtl() { - if (goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE) { - return; // only executes when using an iframe - } - - var info = new goog.editor.icontent.FieldFormatInfo('id', false, true, true); - var styleInfo = new goog.editor.icontent.FieldStyleInfo(wrapperDiv, ''); - wrapperDiv.style.padding = '2px 5px'; - var doc = realIframeDoc; - var html = 'Some Html'; - goog.editor.icontent.writeNormalInitialBlendedIframe(info, html, - styleInfo, realIframe); - - assertBodyCorrect(doc.body, 'id', html, true); - assertEquals('BackCompat', doc.compatMode); // quirks - assertEquals('100%', doc.documentElement.style.height); // fixed height - assertEquals('auto', doc.body.style.height); // quirks - assertEquals('auto', doc.body.style.overflow); // fixed height - - assertEquals('-2px', realIframe.style.marginTop); - assertEquals('-5px', realIframe.style.marginLeft); - assert(doc.getElementsByTagName('style')[0].innerHTML.indexOf( - '-moz-force-broken-image-icon') == -1); // quirks -} - -function testWhiteboxStandardsFixedRtl() { - var info = new goog.editor.icontent.FieldFormatInfo('id', true, false, true); - var styleInfo = null; - var doc = realIframeDoc; - var html = 'Some Html'; - goog.editor.icontent.writeNormalInitialBlendedIframe(info, html, - styleInfo, realIframe); - assertBodyCorrect(doc.body, 'id', html, true); - - // TODO(nicksantos): on Safari, there's a bug where all written iframes - // are CSS1Compat. It's fixed in the nightlies as of 3/31/08, so remove - // this guard when the latest version of Safari is on the farm. - if (!goog.userAgent.WEBKIT) { - assertEquals('BackCompat', doc.compatMode); // always use quirks in whitebox - } -} - -function testGetInitialIframeContent() { - var info = new goog.editor.icontent.FieldFormatInfo( - 'id', true, false, false); - var styleInfo = null; - var html = 'Some Html'; - propertyReplacer.set(goog.editor.BrowserFeature, - 'HAS_CONTENT_EDITABLE', false); - var htmlOut = goog.editor.icontent.getInitialIframeContent_( - info, html, styleInfo); - assertEquals(/contentEditable/i.test(htmlOut), false); - propertyReplacer.set(goog.editor.BrowserFeature, - 'HAS_CONTENT_EDITABLE', true); - htmlOut = goog.editor.icontent.getInitialIframeContent_( - info, html, styleInfo); - assertEquals(/]+?contentEditable/i.test(htmlOut), true); - assertEquals(/]+?style="[^>"]*min-width:\s*0/i.test(htmlOut), true); - assertEquals(/]+?style="[^>"]*min-width:\s*0/i.test(htmlOut), true); -} - -function testIframeMinWidthOverride() { - if (goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE) { - return; // only executes when using an iframe - } - - var info = new goog.editor.icontent.FieldFormatInfo('id', true, true, false); - var styleInfo = new goog.editor.icontent.FieldStyleInfo(wrapperDiv, - '.MyClass { position: absolute; top: 500px; }'); - var doc = realIframeDoc; - var html = '
    Some Html
    '; - goog.editor.icontent.writeNormalInitialBlendedIframe(info, html, - styleInfo, realIframe); - - // Make sure that the minimum width isn't being inherited from the parent - // document's style. - assertTrue(doc.body.offsetWidth < 700); -} - -function testBlendedStandardsGrowingMatchesComparisonDiv() { - // TODO(nicksantos): If we ever move - // TR_EditableUtil.prototype.makeIframeField_ - // into goog.editor.icontent (and I think we should), we could actually run - // functional tests to ensure that the iframed field matches the dimensions - // of the equivalent uneditable div. Functional tests would help a lot here. -} - - -/** - * Check a given body for the most basic properties that all iframes must have. - * - * @param {Element} body The actual body element - * @param {string} id The expected id - * @param {string} bodyHTML The expected innerHTML - * @param {boolean=} opt_rtl If true, expect RTL directionality - */ -function assertBodyCorrect(body, id, bodyHTML, opt_rtl) { - assertEquals(bodyHTML, body.innerHTML); - // We can't just check - // assert(HAS_CONTENTE_EDITABLE, !!body.contentEditable) since in - // FF 3 we don't currently use contentEditable, but body.contentEditable - // = 'inherit' and !!'inherit' = true. - if (goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE) { - assertEquals('true', String(body.contentEditable)); - } else { - assertNotEquals('true', String(body.contentEditable)); - } - assertContains('editable', body.className.match(/\S+/g)); - assertEquals('true', String(body.getAttribute('g_editable'))); - assertEquals('true', - // IE has bugs with getAttribute('hideFocus'), and - // Webkit has bugs with normal .hideFocus access. - String(goog.userAgent.IE ? body.hideFocus : - body.getAttribute('hideFocus'))); - assertEquals(id, body.id); -} - - -/** - * @return {Object} A mock document - */ -function createMockDocument() { - return { - body: { - setAttribute: function(key, val) { this[key] = val; }, - getAttribute: function(key) { return this[key]; }, - style: { direction: '' } - } - }; -} diff --git a/src/database/third_party/closure-library/closure/goog/editor/link.js b/src/database/third_party/closure-library/closure/goog/editor/link.js deleted file mode 100644 index 72f6c52263a..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/link.js +++ /dev/null @@ -1,390 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview A utility class for managing editable links. - * - * @author nicksantos@google.com (Nick Santos) - */ - -goog.provide('goog.editor.Link'); - -goog.require('goog.array'); -goog.require('goog.dom'); -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.Range'); -goog.require('goog.dom.TagName'); -goog.require('goog.editor.BrowserFeature'); -goog.require('goog.editor.Command'); -goog.require('goog.editor.node'); -goog.require('goog.editor.range'); -goog.require('goog.string'); -goog.require('goog.string.Unicode'); -goog.require('goog.uri.utils'); -goog.require('goog.uri.utils.ComponentIndex'); - - - -/** - * Wrap an editable link. - * @param {HTMLAnchorElement} anchor The anchor element. - * @param {boolean} isNew Whether this is a new link. - * @constructor - * @final - */ -goog.editor.Link = function(anchor, isNew) { - /** - * The link DOM element. - * @type {HTMLAnchorElement} - * @private - */ - this.anchor_ = anchor; - - /** - * Whether this link represents a link just added to the document. - * @type {boolean} - * @private - */ - this.isNew_ = isNew; - - - /** - * Any extra anchors created by the browser from a selection in the same - * operation that created the primary link - * @type {!Array} - * @private - */ - this.extraAnchors_ = []; -}; - - -/** - * @return {HTMLAnchorElement} The anchor element. - */ -goog.editor.Link.prototype.getAnchor = function() { - return this.anchor_; -}; - - -/** - * @return {!Array} The extra anchor elements, if any, - * created by the browser from a selection. - */ -goog.editor.Link.prototype.getExtraAnchors = function() { - return this.extraAnchors_; -}; - - -/** - * @return {string} The inner text for the anchor. - */ -goog.editor.Link.prototype.getCurrentText = function() { - if (!this.currentText_) { - var anchor = this.getAnchor(); - - var leaf = goog.editor.node.getLeftMostLeaf(anchor); - if (leaf.tagName && leaf.tagName == goog.dom.TagName.IMG) { - this.currentText_ = leaf.getAttribute('alt'); - } else { - this.currentText_ = goog.dom.getRawTextContent(this.getAnchor()); - } - } - return this.currentText_; -}; - - -/** - * @return {boolean} Whether the link is new. - */ -goog.editor.Link.prototype.isNew = function() { - return this.isNew_; -}; - - -/** - * Set the url without affecting the isNew() status of the link. - * @param {string} url A URL. - */ -goog.editor.Link.prototype.initializeUrl = function(url) { - this.getAnchor().href = url; -}; - - -/** - * Removes the link, leaving its contents in the document. Note that this - * object will no longer be usable/useful after this call. - */ -goog.editor.Link.prototype.removeLink = function() { - goog.dom.flattenElement(this.anchor_); - this.anchor_ = null; - while (this.extraAnchors_.length) { - goog.dom.flattenElement(/** @type {Element} */(this.extraAnchors_.pop())); - } -}; - - -/** - * Change the link. - * @param {string} newText New text for the link. If the link contains all its - * text in one descendent, newText will only replace the text in that - * one node. Otherwise, we'll change the innerHTML of the whole - * link to newText. - * @param {string} newUrl A new URL. - */ -goog.editor.Link.prototype.setTextAndUrl = function(newText, newUrl) { - var anchor = this.getAnchor(); - anchor.href = newUrl; - - // If the text did not change, don't update link text. - var currentText = this.getCurrentText(); - if (newText != currentText) { - var leaf = goog.editor.node.getLeftMostLeaf(anchor); - - if (leaf.tagName && leaf.tagName == goog.dom.TagName.IMG) { - leaf.setAttribute('alt', newText ? newText : ''); - } else { - if (leaf.nodeType == goog.dom.NodeType.TEXT) { - leaf = leaf.parentNode; - } - - if (goog.dom.getRawTextContent(leaf) != currentText) { - leaf = anchor; - } - - goog.dom.removeChildren(leaf); - var domHelper = goog.dom.getDomHelper(leaf); - goog.dom.appendChild(leaf, domHelper.createTextNode(newText)); - } - - // The text changed, so force getCurrentText to recompute. - this.currentText_ = null; - } - - this.isNew_ = false; -}; - - -/** - * Places the cursor to the right of the anchor. - * Note that this is different from goog.editor.range's placeCursorNextTo - * in that it specifically handles the placement of a cursor in browsers - * that trap you in links, by adding a space when necessary and placing the - * cursor after that space. - */ -goog.editor.Link.prototype.placeCursorRightOf = function() { - var anchor = this.getAnchor(); - // If the browser gets stuck in a link if we place the cursor next to it, - // we'll place the cursor after a space instead. - if (goog.editor.BrowserFeature.GETS_STUCK_IN_LINKS) { - var spaceNode; - var nextSibling = anchor.nextSibling; - - // Check if there is already a space after the link. Only handle the - // simple case - the next node is a text node that starts with a space. - if (nextSibling && - nextSibling.nodeType == goog.dom.NodeType.TEXT && - (goog.string.startsWith(nextSibling.data, goog.string.Unicode.NBSP) || - goog.string.startsWith(nextSibling.data, ' '))) { - spaceNode = nextSibling; - } else { - // If there isn't an obvious space to use, create one after the link. - var dh = goog.dom.getDomHelper(anchor); - spaceNode = dh.createTextNode(goog.string.Unicode.NBSP); - goog.dom.insertSiblingAfter(spaceNode, anchor); - } - - // Move the selection after the space. - var range = goog.dom.Range.createCaret(spaceNode, 1); - range.select(); - } else { - goog.editor.range.placeCursorNextTo(anchor, false); - } -}; - - -/** - * Updates the cursor position and link bubble for this link. - * @param {goog.editor.Field} field The field in which the link is created. - * @param {string} url The link url. - * @private - */ -goog.editor.Link.prototype.updateLinkDisplay_ = function(field, url) { - this.initializeUrl(url); - this.placeCursorRightOf(); - field.execCommand(goog.editor.Command.UPDATE_LINK_BUBBLE); -}; - - -/** - * @return {string?} The modified string for the link if the link - * text appears to be a valid link. Returns null if this is not - * a valid link address. - */ -goog.editor.Link.prototype.getValidLinkFromText = function() { - var text = goog.string.trim(this.getCurrentText()); - if (goog.editor.Link.isLikelyUrl(text)) { - if (text.search(/:/) < 0) { - return 'http://' + goog.string.trimLeft(text); - } - return text; - } else if (goog.editor.Link.isLikelyEmailAddress(text)) { - return 'mailto:' + text; - } - return null; -}; - - -/** - * After link creation, finish creating the link depending on the type - * of link being created. - * @param {goog.editor.Field} field The field where this link is being created. - */ -goog.editor.Link.prototype.finishLinkCreation = function(field) { - var linkFromText = this.getValidLinkFromText(); - if (linkFromText) { - this.updateLinkDisplay_(field, linkFromText); - } else { - field.execCommand(goog.editor.Command.MODAL_LINK_EDITOR, this); - } -}; - - -/** - * Initialize a new link. - * @param {HTMLAnchorElement} anchor The anchor element. - * @param {string} url The initial URL. - * @param {string=} opt_target The target. - * @param {Array=} opt_extraAnchors Extra anchors created - * by the browser when parsing a selection. - * @return {!goog.editor.Link} The link. - */ -goog.editor.Link.createNewLink = function(anchor, url, opt_target, - opt_extraAnchors) { - var link = new goog.editor.Link(anchor, true); - link.initializeUrl(url); - - if (opt_target) { - anchor.target = opt_target; - } - if (opt_extraAnchors) { - link.extraAnchors_ = opt_extraAnchors; - } - - return link; -}; - - -/** - * Initialize a new link using text in anchor, or empty string if there is no - * likely url in the anchor. - * @param {HTMLAnchorElement} anchor The anchor element with likely url content. - * @param {string=} opt_target The target. - * @return {!goog.editor.Link} The link. - */ -goog.editor.Link.createNewLinkFromText = function(anchor, opt_target) { - var link = new goog.editor.Link(anchor, true); - var text = link.getValidLinkFromText(); - link.initializeUrl(text ? text : ''); - if (opt_target) { - anchor.target = opt_target; - } - return link; -}; - - -/** - * Returns true if str could be a URL, false otherwise - * - * Ex: TR_Util.isLikelyUrl_("http://www.google.com") == true - * TR_Util.isLikelyUrl_("www.google.com") == true - * - * @param {string} str String to check if it looks like a URL. - * @return {boolean} Whether str could be a URL. - */ -goog.editor.Link.isLikelyUrl = function(str) { - // Whitespace means this isn't a domain. - if (/\s/.test(str)) { - return false; - } - - if (goog.editor.Link.isLikelyEmailAddress(str)) { - return false; - } - - // Add a scheme if the url doesn't have one - this helps the parser. - var addedScheme = false; - if (!/^[^:\/?#.]+:/.test(str)) { - str = 'http://' + str; - addedScheme = true; - } - - // Parse the domain. - var parts = goog.uri.utils.split(str); - - // Relax the rules for special schemes. - var scheme = parts[goog.uri.utils.ComponentIndex.SCHEME]; - if (goog.array.indexOf(['mailto', 'aim'], scheme) != -1) { - return true; - } - - // Require domains to contain a '.', unless the domain is fully qualified and - // forbids domains from containing invalid characters. - var domain = parts[goog.uri.utils.ComponentIndex.DOMAIN]; - if (!domain || (addedScheme && domain.indexOf('.') == -1) || - (/[^\w\d\-\u0100-\uffff.%]/.test(domain))) { - return false; - } - - // Require http and ftp paths to start with '/'. - var path = parts[goog.uri.utils.ComponentIndex.PATH]; - return !path || path.indexOf('/') == 0; -}; - - -/** - * Regular expression that matches strings that could be an email address. - * @type {RegExp} - * @private - */ -goog.editor.Link.LIKELY_EMAIL_ADDRESS_ = new RegExp( - '^' + // Test from start of string - '[\\w-]+(\\.[\\w-]+)*' + // Dot-delimited alphanumerics and dashes (name) - '\\@' + // @ - '([\\w-]+\\.)+' + // Alphanumerics, dashes and dots (domain) - '(\\d+|\\w\\w+)$', // Domain ends in at least one number or 2 letters - 'i'); - - -/** - * Returns true if str could be an email address, false otherwise - * - * Ex: goog.editor.Link.isLikelyEmailAddress_("some word") == false - * goog.editor.Link.isLikelyEmailAddress_("foo@foo.com") == true - * - * @param {string} str String to test for being email address. - * @return {boolean} Whether "str" looks like an email address. - */ -goog.editor.Link.isLikelyEmailAddress = function(str) { - return goog.editor.Link.LIKELY_EMAIL_ADDRESS_.test(str); -}; - - -/** - * Determines whether or not a url is an email link. - * @param {string} url A url. - * @return {boolean} Whether the url is a mailto link. - */ -goog.editor.Link.isMailto = function(url) { - return !!url && goog.string.startsWith(url, 'mailto:'); -}; diff --git a/src/database/third_party/closure-library/closure/goog/editor/link_test.html b/src/database/third_party/closure-library/closure/goog/editor/link_test.html deleted file mode 100644 index 9d1f794c430..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/link_test.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - Editor Unit Tests - goog.editor.Link - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/editor/link_test.js b/src/database/third_party/closure-library/closure/goog/editor/link_test.js deleted file mode 100644 index 5362aeda195..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/link_test.js +++ /dev/null @@ -1,290 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.editor.LinkTest'); -goog.setTestOnly('goog.editor.LinkTest'); - -goog.require('goog.dom'); -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.Range'); -goog.require('goog.dom.TagName'); -goog.require('goog.editor.Link'); -goog.require('goog.testing.jsunit'); -goog.require('goog.userAgent'); - -var anchor; - -function setUp() { - anchor = goog.dom.createDom('A'); - document.body.appendChild(anchor); -} - -function tearDown() { - goog.dom.removeNode(anchor); -} - -function testCreateNew() { - var link = new goog.editor.Link(anchor, true); - assertNotNull('Should have created object', link); - assertTrue('Should be new', link.isNew()); - assertEquals('Should have correct anchor', anchor, link.getAnchor()); - assertEquals('Should be empty', '', link.getCurrentText()); -} - -function testCreateNotNew() { - var link = new goog.editor.Link(anchor, false); - assertNotNull('Should have created object', link); - assertFalse('Should not be new', link.isNew()); - assertEquals('Should have correct anchor', anchor, link.getAnchor()); - assertEquals('Should be empty', '', link.getCurrentText()); -} - -function testCreateNewLinkFromText() { - var url = 'http://www.google.com/'; - anchor.innerHTML = url; - var link = goog.editor.Link.createNewLinkFromText(anchor); - assertNotNull('Should have created object', link); - assertEquals('Should have url in anchor', url, anchor.href); -} - -function testCreateNewLinkFromTextLeadingTrailingWhitespace() { - var url = 'http://www.google.com/'; - var urlWithSpaces = ' ' + url + ' '; - anchor.innerHTML = urlWithSpaces; - var urlWithSpacesUpdatedByBrowser = anchor.innerHTML; - var link = goog.editor.Link.createNewLinkFromText(anchor); - assertNotNull('Should have created object', link); - assertEquals('Should have url in anchor', url, anchor.href); - assertEquals('The text should still have spaces', - urlWithSpacesUpdatedByBrowser, link.getCurrentText()); -} - -function testCreateNewLinkFromTextWithAnchor() { - var url = 'https://www.google.com/'; - anchor.innerHTML = url; - var link = goog.editor.Link.createNewLinkFromText(anchor, '_blank'); - assertNotNull('Should have created object', link); - assertEquals('Should have url in anchor', url, anchor.href); - assertEquals('Should have _blank target', '_blank', anchor.target); -} - -function testInitialize() { - var link = goog.editor.Link.createNewLink(anchor, 'http://www.google.com'); - assertNotNull('Should have created object', link); - assertTrue('Should be new', link.isNew()); - assertEquals('Should have correct anchor', anchor, link.getAnchor()); - assertEquals('Should be empty', '', link.getCurrentText()); -} - -function testInitializeWithTarget() { - var link = goog.editor.Link.createNewLink(anchor, 'http://www.google.com', - '_blank'); - assertNotNull('Should have created object', link); - assertTrue('Should be new', link.isNew()); - assertEquals('Should have correct anchor', anchor, link.getAnchor()); - assertEquals('Should be empty', '', link.getCurrentText()); - assertEquals('Should have _blank target', '_blank', anchor.target); -} - -function testSetText() { - var link = goog.editor.Link.createNewLink(anchor, 'http://www.google.com', - '_blank'); - assertEquals('Should be empty', '', link.getCurrentText()); - link.setTextAndUrl('Text', 'http://docs.google.com/'); - assertEquals('Should point to http://docs.google.com/', - 'http://docs.google.com/', anchor.href); - assertEquals('Should have correct text', 'Text', link.getCurrentText()); -} - -function testSetBoldText() { - anchor.innerHTML = ''; - var link = goog.editor.Link.createNewLink(anchor, 'http://www.google.com', - '_blank'); - assertEquals('Should be empty', '', link.getCurrentText()); - link.setTextAndUrl('Text', 'http://docs.google.com/'); - assertEquals('Should point to http://docs.google.com/', - 'http://docs.google.com/', anchor.href); - assertEquals('Should have correct text', 'Text', link.getCurrentText()); - assertEquals('Should still be bold', goog.dom.TagName.B, - anchor.firstChild.tagName); -} - -function testLinkImgTag() { - anchor.innerHTML = 'alt_txt'; - var link = goog.editor.Link.createNewLink(anchor, 'http://www.google.com', - '_blank'); - assertEquals('Test getCurrentText', 'alt_txt', link.getCurrentText()); - link.setTextAndUrl('newText', 'http://docs.google.com/'); - assertEquals('Test getCurrentText', 'newText', link.getCurrentText()); - assertEquals('Should point to http://docs.google.com/', - 'http://docs.google.com/', anchor.href); - - assertEquals('Should still have img tag', goog.dom.TagName.IMG, - anchor.firstChild.tagName); - - assertEquals('Alt should equal "newText"', 'newText', - anchor.firstChild.getAttribute('alt')); -} - -function testSetMixed() { - anchor.innerHTML = 'AB'; - var link = goog.editor.Link.createNewLink(anchor, 'http://www.google.com', - '_blank'); - assertEquals('Should have text: AB', 'AB', link.getCurrentText()); - link.setTextAndUrl('Text', 'http://docs.google.com/'); - assertEquals('Should point to http://docs.google.com/', - 'http://docs.google.com/', anchor.href); - assertEquals('Should have correct text', 'Text', link.getCurrentText()); - assertEquals('Should not be bold', goog.dom.NodeType.TEXT, - anchor.firstChild.nodeType); -} - -function testPlaceCursorRightOf() { - // IE can only do selections properly if the region is editable. - var ed = goog.dom.createDom('div'); - goog.dom.replaceNode(ed, anchor); - ed.contentEditable = true; - ed.appendChild(anchor); - - // In order to test the cursor placement properly, we need to have - // link text. See more details in the test below. - anchor.innerHTML = 'I am text'; - - var link = goog.editor.Link.createNewLink(anchor, 'http://www.google.com'); - link.placeCursorRightOf(); - - var range = goog.dom.Range.createFromWindow(); - assertTrue('Range should be collapsed', range.isCollapsed()); - var startNode = range.getStartNode(); - - if (goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher('528')) { - assertEquals('Selection should be to the right of the anchor', - anchor, startNode.previousSibling); - } else { - // Check that the selection is the "right" place. - // - // If you query the selection, it is actually still inside the anchor, - // but if you type, it types outside the anchor. - // - // Best we can do is test that it is at the end of the anchor text. - assertEquals('Selection should be in anchor text', - anchor.firstChild, startNode); - assertEquals('Selection should be at the end of the text', - anchor.firstChild.length, range.getStartOffset()); - } - - if (ed) { - goog.dom.removeNode(ed); - } -} - -function testIsLikelyUrl() { - var good = [ - // Proper URLs - 'http://google.com', 'http://google.com/', 'http://192.168.1.103', - 'http://www.google.com:8083', 'https://antoine', 'https://foo.foo.net', - 'ftp://google.com:22/', 'http://user@site.com', - 'ftp://user:pass@ftp.site.com', 'http://google.com/search?q=laser%20cats', - 'aim:goim?screenname=en2es', 'mailto:x@y.com', - - // Bad URLs a browser will accept - 'www.google.com', 'www.amazon.co.uk', 'amazon.co.uk', 'foo2.foo3.com', - 'pandora.tv', 'marketing.us', 'del.icio.us', 'bridge-line.com', - 'www.frigid.net:80', 'www.google.com?q=foo', 'www.foo.com/j%20.txt', - 'foodtv.net', 'google.com', 'slashdot.org', '192.168.1.1', - 'justin.edu?kumar something', 'google.com/search?q=hot%20pockets', - - // Due to TLD explosion, these could be URLs either now or soon. - 'ww.jester', 'juicer.fake', 'abs.nonsense.something', 'filename.txt' - ]; - for (var i = 0; i < good.length; i++) { - assertTrue(good[i] + ' should be good', - goog.editor.Link.isLikelyUrl(good[i])); - } - - var bad = [ - // Definitely not URLs - 'bananas', 'http google com', '', 'Sad :/', '*garbage!.123', - 'ftp', 'http', '/', 'https', 'this is', '*!&.banana!*&!', - 'www.jester is gone.com', 'ftp .nospaces.net', 'www_foo_net', - "www.'jester'.net", 'www:8080', - 'www . notnsense.com', 'email@address.com', - - // URL-ish but not quite - ' http://www.google.com', 'http://www.google.com:8081 ', - 'www.google.com foo bar', 'google.com/search?q=not quite' - ]; - - for (i = 0; i < bad.length; i++) { - assertFalse(bad[i] + ' should be bad', - goog.editor.Link.isLikelyUrl(bad[i])); - } -} - -function testIsLikelyEmailAddress() { - var good = [ - // Valid email addresses - 'foo@foo.com', 'foo1@foo2.foo3.com', 'f45_1@goog13.org', 'user@gmail.co.uk', - 'jon-smith@crazy.net', 'roland1@capuchino.gov', 'ernir@gshi.nl', - 'JOON@jno.COM', 'media@meDIa.fREnology.FR', 'john.mail4me@del.icio.us', - 'www9@wc3.madeup1.org', 'hi@192.168.1.103', 'hi@192.168.1.1' - ]; - for (var i = 0; i < good.length; i++) { - assertTrue(goog.editor.Link.isLikelyEmailAddress(good[i])); - } - - var bad = [ - // Malformed/incomplete email addresses - 'user', '@gmail.com', 'user@gmail', 'user@.com', 'user@gmail.c', - 'user@gmail.co.u', '@ya.com', '.@hi3.nl', 'jim.com', - 'ed:@gmail.com', '*!&.banana!*&!', ':jon@gmail.com', - '3g?@bil.com', 'adam be@hi.net', 'john\nsmith@test.com', - "www.'jester'.net", "'james'@covald.net", 'ftp://user@site.com/', - 'aim:goim?screenname=en2es', 'user:pass@site.com', 'user@site.com yay' - ]; - - for (i = 0; i < bad.length; i++) { - assertFalse(goog.editor.Link.isLikelyEmailAddress(bad[i])); - } -} - -function testIsMailToLink() { - assertFalse(goog.editor.Link.isMailto()); - assertFalse(goog.editor.Link.isMailto(null)); - assertFalse(goog.editor.Link.isMailto('')); - assertFalse(goog.editor.Link.isMailto('http://foo.com')); - assertFalse(goog.editor.Link.isMailto('http://mailto:80')); - - assertTrue(goog.editor.Link.isMailto('mailto:')); - assertTrue(goog.editor.Link.isMailto('mailto://')); - assertTrue(goog.editor.Link.isMailto('mailto://ptucker@gmail.com')); -} - -function testGetValidLinkFromText() { - var textLinkPairs = [ - // input text, expected link output - 'www.foo.com', 'http://www.foo.com', - 'user@gmail.com', 'mailto:user@gmail.com', - 'http://www.foo.com', 'http://www.foo.com', - 'https://this.that.edu', 'https://this.that.edu', - 'nothing to see here', null - ]; - var link = new goog.editor.Link(anchor, true); - - for (var i = 0; i < textLinkPairs.length; i += 2) { - link.currentText_ = textLinkPairs[i]; - var result = link.getValidLinkFromText(); - assertEquals(textLinkPairs[i + 1], result); - } -} diff --git a/src/database/third_party/closure-library/closure/goog/editor/node.js b/src/database/third_party/closure-library/closure/goog/editor/node.js deleted file mode 100644 index 006936d1c25..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/node.js +++ /dev/null @@ -1,484 +0,0 @@ -// Copyright 2005 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Utilties for working with DOM nodes related to rich text - * editing. Many of these are not general enough to go into goog.dom. - * - * @author nicksantos@google.com (Nick Santos) - */ - -goog.provide('goog.editor.node'); - -goog.require('goog.dom'); -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.TagName'); -goog.require('goog.dom.iter.ChildIterator'); -goog.require('goog.dom.iter.SiblingIterator'); -goog.require('goog.iter'); -goog.require('goog.object'); -goog.require('goog.string'); -goog.require('goog.string.Unicode'); -goog.require('goog.userAgent'); - - -/** - * Names of all block-level tags - * @type {Object} - * @private - */ -goog.editor.node.BLOCK_TAG_NAMES_ = goog.object.createSet( - goog.dom.TagName.ADDRESS, - goog.dom.TagName.ARTICLE, - goog.dom.TagName.ASIDE, - goog.dom.TagName.BLOCKQUOTE, - goog.dom.TagName.BODY, - goog.dom.TagName.CAPTION, - goog.dom.TagName.CENTER, - goog.dom.TagName.COL, - goog.dom.TagName.COLGROUP, - goog.dom.TagName.DETAILS, - goog.dom.TagName.DIR, - goog.dom.TagName.DIV, - goog.dom.TagName.DL, - goog.dom.TagName.DD, - goog.dom.TagName.DT, - goog.dom.TagName.FIELDSET, - goog.dom.TagName.FIGCAPTION, - goog.dom.TagName.FIGURE, - goog.dom.TagName.FOOTER, - goog.dom.TagName.FORM, - goog.dom.TagName.H1, - goog.dom.TagName.H2, - goog.dom.TagName.H3, - goog.dom.TagName.H4, - goog.dom.TagName.H5, - goog.dom.TagName.H6, - goog.dom.TagName.HEADER, - goog.dom.TagName.HGROUP, - goog.dom.TagName.HR, - goog.dom.TagName.ISINDEX, - goog.dom.TagName.OL, - goog.dom.TagName.LI, - goog.dom.TagName.MAP, - goog.dom.TagName.MENU, - goog.dom.TagName.NAV, - goog.dom.TagName.OPTGROUP, - goog.dom.TagName.OPTION, - goog.dom.TagName.P, - goog.dom.TagName.PRE, - goog.dom.TagName.SECTION, - goog.dom.TagName.SUMMARY, - goog.dom.TagName.TABLE, - goog.dom.TagName.TBODY, - goog.dom.TagName.TD, - goog.dom.TagName.TFOOT, - goog.dom.TagName.TH, - goog.dom.TagName.THEAD, - goog.dom.TagName.TR, - goog.dom.TagName.UL); - - -/** - * Names of tags that have intrinsic content. - * TODO(robbyw): What about object, br, input, textarea, button, isindex, - * hr, keygen, select, table, tr, td? - * @type {Object} - * @private - */ -goog.editor.node.NON_EMPTY_TAGS_ = goog.object.createSet( - goog.dom.TagName.IMG, goog.dom.TagName.IFRAME, goog.dom.TagName.EMBED); - - -/** - * Check if the node is in a standards mode document. - * @param {Node} node The node to test. - * @return {boolean} Whether the node is in a standards mode document. - */ -goog.editor.node.isStandardsMode = function(node) { - return goog.dom.getDomHelper(node).isCss1CompatMode(); -}; - - -/** - * Get the right-most non-ignorable leaf node of the given node. - * @param {Node} parent The parent ndoe. - * @return {Node} The right-most non-ignorable leaf node. - */ -goog.editor.node.getRightMostLeaf = function(parent) { - var temp; - while (temp = goog.editor.node.getLastChild(parent)) { - parent = temp; - } - return parent; -}; - - -/** - * Get the left-most non-ignorable leaf node of the given node. - * @param {Node} parent The parent ndoe. - * @return {Node} The left-most non-ignorable leaf node. - */ -goog.editor.node.getLeftMostLeaf = function(parent) { - var temp; - while (temp = goog.editor.node.getFirstChild(parent)) { - parent = temp; - } - return parent; -}; - - -/** - * Version of firstChild that skips nodes that are entirely - * whitespace and comments. - * @param {Node} parent The reference node. - * @return {Node} The first child of sibling that is important according to - * goog.editor.node.isImportant, or null if no such node exists. - */ -goog.editor.node.getFirstChild = function(parent) { - return goog.editor.node.getChildHelper_(parent, false); -}; - - -/** - * Version of lastChild that skips nodes that are entirely whitespace or - * comments. (Normally lastChild is a property of all DOM nodes that gives the - * last of the nodes contained directly in the reference node.) - * @param {Node} parent The reference node. - * @return {Node} The last child of sibling that is important according to - * goog.editor.node.isImportant, or null if no such node exists. - */ -goog.editor.node.getLastChild = function(parent) { - return goog.editor.node.getChildHelper_(parent, true); -}; - - -/** - * Version of previoussibling that skips nodes that are entirely - * whitespace or comments. (Normally previousSibling is a property - * of all DOM nodes that gives the sibling node, the node that is - * a child of the same parent, that occurs immediately before the - * reference node.) - * @param {Node} sibling The reference node. - * @return {Node} The closest previous sibling to sibling that is - * important according to goog.editor.node.isImportant, or null if no such - * node exists. - */ -goog.editor.node.getPreviousSibling = function(sibling) { - return /** @type {Node} */ (goog.editor.node.getFirstValue_( - goog.iter.filter(new goog.dom.iter.SiblingIterator(sibling, false, true), - goog.editor.node.isImportant))); -}; - - -/** - * Version of nextSibling that skips nodes that are entirely whitespace or - * comments. - * @param {Node} sibling The reference node. - * @return {Node} The closest next sibling to sibling that is important - * according to goog.editor.node.isImportant, or null if no - * such node exists. - */ -goog.editor.node.getNextSibling = function(sibling) { - return /** @type {Node} */ (goog.editor.node.getFirstValue_( - goog.iter.filter(new goog.dom.iter.SiblingIterator(sibling), - goog.editor.node.isImportant))); -}; - - -/** - * Internal helper for lastChild/firstChild that skips nodes that are entirely - * whitespace or comments. - * @param {Node} parent The reference node. - * @param {boolean} isReversed Whether children should be traversed forward - * or backward. - * @return {Node} The first/last child of sibling that is important according - * to goog.editor.node.isImportant, or null if no such node exists. - * @private - */ -goog.editor.node.getChildHelper_ = function(parent, isReversed) { - return (!parent || parent.nodeType != goog.dom.NodeType.ELEMENT) ? null : - /** @type {Node} */ (goog.editor.node.getFirstValue_(goog.iter.filter( - new goog.dom.iter.ChildIterator( - /** @type {!Element} */ (parent), isReversed), - goog.editor.node.isImportant))); -}; - - -/** - * Utility function that returns the first value from an iterator or null if - * the iterator is empty. - * @param {goog.iter.Iterator} iterator The iterator to get a value from. - * @return {*} The first value from the iterator. - * @private - */ -goog.editor.node.getFirstValue_ = function(iterator) { - /** @preserveTry */ - try { - return iterator.next(); - } catch (e) { - return null; - } -}; - - -/** - * Determine if a node should be returned by the iterator functions. - * @param {Node} node An object implementing the DOM1 Node interface. - * @return {boolean} Whether the node is an element, or a text node that - * is not all whitespace. - */ -goog.editor.node.isImportant = function(node) { - // Return true if the node is not either a TextNode or an ElementNode. - return node.nodeType == goog.dom.NodeType.ELEMENT || - node.nodeType == goog.dom.NodeType.TEXT && - !goog.editor.node.isAllNonNbspWhiteSpace(node); -}; - - -/** - * Determine whether a node's text content is entirely whitespace. - * @param {Node} textNode A node implementing the CharacterData interface (i.e., - * a Text, Comment, or CDATASection node. - * @return {boolean} Whether the text content of node is whitespace, - * otherwise false. - */ -goog.editor.node.isAllNonNbspWhiteSpace = function(textNode) { - return goog.string.isBreakingWhitespace(textNode.nodeValue); -}; - - -/** - * Returns true if the node contains only whitespace and is not and does not - * contain any images, iframes or embed tags. - * @param {Node} node The node to check. - * @param {boolean=} opt_prohibitSingleNbsp By default, this function treats a - * single nbsp as empty. Set this to true to treat this case as non-empty. - * @return {boolean} Whether the node contains only whitespace. - */ -goog.editor.node.isEmpty = function(node, opt_prohibitSingleNbsp) { - var nodeData = goog.dom.getRawTextContent(node); - - if (node.getElementsByTagName) { - for (var tag in goog.editor.node.NON_EMPTY_TAGS_) { - if (node.tagName == tag || node.getElementsByTagName(tag).length > 0) { - return false; - } - } - } - return (!opt_prohibitSingleNbsp && nodeData == goog.string.Unicode.NBSP) || - goog.string.isBreakingWhitespace(nodeData); -}; - - -/** - * Returns the length of the text in node if it is a text node, or the number - * of children of the node, if it is an element. Useful for range-manipulation - * code where you need to know the offset for the right side of the node. - * @param {Node} node The node to get the length of. - * @return {number} The length of the node. - */ -goog.editor.node.getLength = function(node) { - return node.length || node.childNodes.length; -}; - - -/** - * Search child nodes using a predicate function and return the first node that - * satisfies the condition. - * @param {Node} parent The parent node to search. - * @param {function(Node):boolean} hasProperty A function that takes a child - * node as a parameter and returns true if it meets the criteria. - * @return {?number} The index of the node found, or null if no node is found. - */ -goog.editor.node.findInChildren = function(parent, hasProperty) { - for (var i = 0, len = parent.childNodes.length; i < len; i++) { - if (hasProperty(parent.childNodes[i])) { - return i; - } - } - return null; -}; - - -/** - * Search ancestor nodes using a predicate function and returns the topmost - * ancestor in the chain of consecutive ancestors that satisfies the condition. - * - * @param {Node} node The node whose ancestors have to be searched. - * @param {function(Node): boolean} hasProperty A function that takes a parent - * node as a parameter and returns true if it meets the criteria. - * @return {Node} The topmost ancestor or null if no ancestor satisfies the - * predicate function. - */ -goog.editor.node.findHighestMatchingAncestor = function(node, hasProperty) { - var parent = node.parentNode; - var ancestor = null; - while (parent && hasProperty(parent)) { - ancestor = parent; - parent = parent.parentNode; - } - return ancestor; -}; - - -/** -* Checks if node is a block-level html element. The display css - * property is ignored. - * @param {Node} node The node to test. - * @return {boolean} Whether the node is a block-level node. - */ -goog.editor.node.isBlockTag = function(node) { - return !!goog.editor.node.BLOCK_TAG_NAMES_[node.tagName]; -}; - - -/** - * Skips siblings of a node that are empty text nodes. - * @param {Node} node A node. May be null. - * @return {Node} The node or the first sibling of the node that is not an - * empty text node. May be null. - */ -goog.editor.node.skipEmptyTextNodes = function(node) { - while (node && node.nodeType == goog.dom.NodeType.TEXT && - !node.nodeValue) { - node = node.nextSibling; - } - return node; -}; - - -/** - * Checks if an element is a top-level editable container (meaning that - * it itself is not editable, but all its child nodes are editable). - * @param {Node} element The element to test. - * @return {boolean} Whether the element is a top-level editable container. - */ -goog.editor.node.isEditableContainer = function(element) { - return element.getAttribute && - element.getAttribute('g_editable') == 'true'; -}; - - -/** - * Checks if a node is inside an editable container. - * @param {Node} node The node to test. - * @return {boolean} Whether the node is in an editable container. - */ -goog.editor.node.isEditable = function(node) { - return !!goog.dom.getAncestor(node, goog.editor.node.isEditableContainer); -}; - - -/** - * Finds the top-most DOM node inside an editable field that is an ancestor - * (or self) of a given DOM node and meets the specified criteria. - * @param {Node} node The DOM node where the search starts. - * @param {function(Node) : boolean} criteria A function that takes a DOM node - * as a parameter and returns a boolean to indicate whether the node meets - * the criteria or not. - * @return {Node} The DOM node if found, or null. - */ -goog.editor.node.findTopMostEditableAncestor = function(node, criteria) { - var targetNode = null; - while (node && !goog.editor.node.isEditableContainer(node)) { - if (criteria(node)) { - targetNode = node; - } - node = node.parentNode; - } - return targetNode; -}; - - -/** - * Splits off a subtree. - * @param {!Node} currentNode The starting splitting point. - * @param {Node=} opt_secondHalf The initial leftmost leaf the new subtree. - * If null, siblings after currentNode will be placed in the subtree, but - * no additional node will be. - * @param {Node=} opt_root The top of the tree where splitting stops at. - * @return {!Node} The new subtree. - */ -goog.editor.node.splitDomTreeAt = function(currentNode, - opt_secondHalf, opt_root) { - var parent; - while (currentNode != opt_root && (parent = currentNode.parentNode)) { - opt_secondHalf = goog.editor.node.getSecondHalfOfNode_(parent, currentNode, - opt_secondHalf); - currentNode = parent; - } - return /** @type {!Node} */(opt_secondHalf); -}; - - -/** - * Creates a clone of node, moving all children after startNode to it. - * When firstChild is not null or undefined, it is also appended to the clone - * as the first child. - * @param {!Node} node The node to clone. - * @param {!Node} startNode All siblings after this node will be moved to the - * clone. - * @param {Node|undefined} firstChild The first child of the new cloned element. - * @return {!Node} The cloned node that now contains the children after - * startNode. - * @private - */ -goog.editor.node.getSecondHalfOfNode_ = function(node, startNode, firstChild) { - var secondHalf = /** @type {!Node} */(node.cloneNode(false)); - while (startNode.nextSibling) { - goog.dom.appendChild(secondHalf, startNode.nextSibling); - } - if (firstChild) { - secondHalf.insertBefore(firstChild, secondHalf.firstChild); - } - return secondHalf; -}; - - -/** - * Appends all of oldNode's children to newNode. This removes all children from - * oldNode and appends them to newNode. oldNode is left with no children. - * @param {!Node} newNode Node to transfer children to. - * @param {Node} oldNode Node to transfer children from. - * @deprecated Use goog.dom.append directly instead. - */ -goog.editor.node.transferChildren = function(newNode, oldNode) { - goog.dom.append(newNode, oldNode.childNodes); -}; - - -/** - * Replaces the innerHTML of a node. - * - * IE has serious problems if you try to set innerHTML of an editable node with - * any selection. Early versions of IE tear up the old internal tree storage, to - * help avoid ref-counting loops. But this sometimes leaves the selection object - * in a bad state and leads to segfaults. - * - * Removing the nodes first prevents IE from tearing them up. This is not - * strictly necessary in nodes that do not have the selection. You should always - * use this function when setting innerHTML inside of a field. - * - * @param {Node} node A node. - * @param {string} html The innerHTML to set on the node. - */ -goog.editor.node.replaceInnerHtml = function(node, html) { - // Only do this IE. On gecko, we use element change events, and don't - // want to trigger spurious events. - if (goog.userAgent.IE) { - goog.dom.removeChildren(node); - } - node.innerHTML = html; -}; diff --git a/src/database/third_party/closure-library/closure/goog/editor/node_test.html b/src/database/third_party/closure-library/closure/goog/editor/node_test.html deleted file mode 100644 index 7f33878f423..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/node_test.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - Closure Unit Tests - goog.editor.Node - - - - - -
    - Foo -
    nodeelement
    - - diff --git a/src/database/third_party/closure-library/closure/goog/editor/node_test.js b/src/database/third_party/closure-library/closure/goog/editor/node_test.js deleted file mode 100644 index c260793bd11..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/node_test.js +++ /dev/null @@ -1,645 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.editor.nodeTest'); -goog.setTestOnly('goog.editor.nodeTest'); - -goog.require('goog.array'); -goog.require('goog.dom'); -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.TagName'); -goog.require('goog.editor.node'); -goog.require('goog.style'); -goog.require('goog.testing.ExpectedFailures'); -goog.require('goog.testing.dom'); -goog.require('goog.testing.jsunit'); -goog.require('goog.userAgent'); - -var expectedFailures; -var parentNode; -var childNode1; -var childNode2; -var childNode3; - -var gChildWsNode1 = null; -var gChildTextNode1 = null; -var gChildNbspNode1 = null; -var gChildMixedNode1 = null; -var gChildWsNode2a = null; -var gChildWsNode2b = null; -var gChildTextNode3a = null; -var gChildWsNode3 = null; -var gChildTextNode3b = null; - -function setUpPage() { - expectedFailures = new goog.testing.ExpectedFailures(); - parentNode = document.getElementById('parentNode'); - childNode1 = parentNode.childNodes[0]; - childNode2 = parentNode.childNodes[1]; - childNode3 = parentNode.childNodes[2]; -} - - -function tearDown() { - expectedFailures.handleTearDown(); -} - -function setUpDomTree() { - gChildWsNode1 = document.createTextNode(' \t\r\n'); - gChildTextNode1 = document.createTextNode('Child node'); - gChildNbspNode1 = document.createTextNode('\u00a0'); - gChildMixedNode1 = document.createTextNode('Text\n plus\u00a0'); - gChildWsNode2a = document.createTextNode(''); - gChildWsNode2b = document.createTextNode(' '); - gChildTextNode3a = document.createTextNode('I am a grand child'); - gChildWsNode3 = document.createTextNode(' \t \r \n'); - gChildTextNode3b = document.createTextNode('I am also a grand child'); - - childNode3.appendChild(gChildTextNode3a); - childNode3.appendChild(gChildWsNode3); - childNode3.appendChild(gChildTextNode3b); - - childNode1.appendChild(gChildMixedNode1); - childNode1.appendChild(gChildWsNode1); - childNode1.appendChild(gChildNbspNode1); - childNode1.appendChild(gChildTextNode1); - - childNode2.appendChild(gChildWsNode2a); - childNode2.appendChild(gChildWsNode2b); - document.body.appendChild(parentNode); -} - -function tearDownDomTree() { - childNode1.innerHTML = childNode2.innerHTML = childNode3.innerHTML = ''; - gChildWsNode1 = null; - gChildTextNode1 = null; - gChildNbspNode1 = null; - gChildMixedNode1 = null; - gChildWsNode2a = null; - gChildWsNode2b = null; - gChildTextNode3a = null; - gChildWsNode3 = null; - gChildTextNode3b = null; -} - -function testGetCompatModeQuirks() { - var quirksIfr = document.createElement('iframe'); - document.body.appendChild(quirksIfr); - // Webkit used to default to standards mode, but fixed this in - // Safari 4/Chrome 2, aka, WebKit 530. - // Also IE10 fails here. - // TODO(johnlenz): IE10+ inherit quirks mode from the owner document - // according to: - // http://msdn.microsoft.com/en-us/library/ff955402(v=vs.85).aspx - // but this test shows different behavior for IE10 and 11. If we discover - // that we care about quirks mode documents we should investigate - // this failure. - expectedFailures.expectFailureFor( - (goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher('530')) || - (goog.userAgent.IE && goog.userAgent.isVersionOrHigher('10') && - !goog.userAgent.isVersionOrHigher('11'))); - expectedFailures.run(function() { - assertFalse('Empty sourceless iframe is quirks mode, not standards mode', - goog.editor.node.isStandardsMode( - goog.dom.getFrameContentDocument(quirksIfr))); - }); - document.body.removeChild(quirksIfr); -} - -function testGetCompatModeStandards() { - var standardsIfr = document.createElement('iframe'); - document.body.appendChild(standardsIfr); - var doc = goog.dom.getFrameContentDocument(standardsIfr); - doc.open(); - doc.write(' '); - doc.close(); - assertTrue('Iframe with DOCTYPE written in is standards mode', - goog.editor.node.isStandardsMode(doc)); - document.body.removeChild(standardsIfr); -} - - -/** - * Creates a DOM tree and tests that getLeftMostLeaf returns proper node - */ -function testGetLeftMostLeaf() { - setUpDomTree(); - - assertEquals('Should skip ws node', gChildMixedNode1, - goog.editor.node.getLeftMostLeaf(parentNode)); - assertEquals('Should skip ws node', gChildMixedNode1, - goog.editor.node.getLeftMostLeaf(childNode1)); - assertEquals('Has no non ws leaves', childNode2, - goog.editor.node.getLeftMostLeaf(childNode2)); - assertEquals('Should return first child', gChildTextNode3a, - goog.editor.node.getLeftMostLeaf(childNode3)); - assertEquals('Has no children', gChildTextNode1, - goog.editor.node.getLeftMostLeaf(gChildTextNode1)); - - tearDownDomTree(); -} - - -/** - * Creates a DOM tree and tests that getRightMostLeaf returns proper node - */ -function testGetRightMostLeaf() { - setUpDomTree(); - - assertEquals("Should return child3's rightmost child", gChildTextNode3b, - goog.editor.node.getRightMostLeaf(parentNode)); - assertEquals('Should skip ws node', gChildTextNode1, - goog.editor.node.getRightMostLeaf(childNode1)); - assertEquals('Has no non ws leaves', childNode2, - goog.editor.node.getRightMostLeaf(childNode2)); - assertEquals('Should return last child', gChildTextNode3b, - goog.editor.node.getRightMostLeaf(childNode3)); - assertEquals('Has no children', gChildTextNode1, - goog.editor.node.getRightMostLeaf(gChildTextNode1)); - - tearDownDomTree(); -} - - -/** - * Creates a DOM tree and tests that getFirstChild properly ignores - * ignorable nodes - */ -function testGetFirstChild() { - setUpDomTree(); - - assertNull('Has no none ws children', - goog.editor.node.getFirstChild(childNode2)); - assertEquals('Should skip first child, as it is ws', gChildMixedNode1, - goog.editor.node.getFirstChild(childNode1)); - assertEquals('Should just return first child', gChildTextNode3a, - goog.editor.node.getFirstChild(childNode3)); - assertEquals('Should return first child', childNode1, - goog.editor.node.getFirstChild(parentNode)); - - assertNull('First child of a text node should return null', - goog.editor.node.getFirstChild(gChildTextNode1)); - assertNull('First child of null should return null', - goog.editor.node.getFirstChild(null)); - - tearDownDomTree(); -} - - -/** - * Create a DOM tree and test that getLastChild properly ignores - * ignorable nodes - */ -function testGetLastChild() { - setUpDomTree(); - - assertNull('Has no none ws children', - goog.editor.node.getLastChild(childNode2)); - assertEquals('Should skip last child, as it is ws', gChildTextNode1, - goog.editor.node.getLastChild(childNode1)); - assertEquals('Should just return last child', gChildTextNode3b, - goog.editor.node.getLastChild(childNode3)); - assertEquals('Should return last child', childNode3, - goog.editor.node.getLastChild(parentNode)); - - assertNull('Last child of a text node should return null', - goog.editor.node.getLastChild(gChildTextNode1)); - assertNull('Last child of null should return null', - goog.editor.node.getLastChild(gChildTextNode1)); - - tearDownDomTree(); -} - - -/** - * Test if nodes that should be ignorable return false and nodes that should - * not be ignored return true. - */ -function testIsImportant() { - var wsNode = document.createTextNode(' \t\r\n'); - assertFalse('White space node is ignorable', - goog.editor.node.isImportant(wsNode)); - var textNode = document.createTextNode('Hello'); - assertTrue('Text node is important', goog.editor.node.isImportant(textNode)); - var nbspNode = document.createTextNode('\u00a0'); - assertTrue('Node with nbsp is important', - goog.editor.node.isImportant(nbspNode)); - var imageNode = document.createElement('img'); - assertTrue('Image node is important', - goog.editor.node.isImportant(imageNode)); -} - - -/** - * Test that isAllNonNbspWhiteSpace returns true if node contains only - * whitespace that is not nbsp and false otherwise - */ -function testIsAllNonNbspWhiteSpace() { - var wsNode = document.createTextNode(' \t\r\n'); - assertTrue('String is all non nbsp', - goog.editor.node.isAllNonNbspWhiteSpace(wsNode)); - var textNode = document.createTextNode('Hello'); - assertFalse('String should not be whitespace', - goog.editor.node.isAllNonNbspWhiteSpace(textNode)); - var nbspNode = document.createTextNode('\u00a0'); - assertFalse('String has nbsp', - goog.editor.node.isAllNonNbspWhiteSpace(nbspNode)); -} - - -/** - * Creates a DOM tree and Test that getPreviousSibling properly ignores - * ignorable nodes - */ -function testGetPreviousSibling() { - setUpDomTree(); - - assertNull('No previous sibling', - goog.editor.node.getPreviousSibling(gChildTextNode3a)); - assertEquals('Should have text sibling', gChildTextNode3a, - goog.editor.node.getPreviousSibling(gChildWsNode3)); - assertEquals('Should skip over white space sibling', gChildTextNode3a, - goog.editor.node.getPreviousSibling(gChildTextNode3b)); - assertNull('No previous sibling', - goog.editor.node.getPreviousSibling(gChildMixedNode1)); - assertEquals('Should have mixed text sibling', gChildMixedNode1, - goog.editor.node.getPreviousSibling(gChildWsNode1)); - assertEquals('Should skip over white space sibling', gChildMixedNode1, - goog.editor.node.getPreviousSibling(gChildNbspNode1)); - assertNotEquals('Should not move past ws and nbsp', gChildMixedNode1, - goog.editor.node.getPreviousSibling(gChildTextNode1)); - assertEquals('Should go to child 2', childNode2, - goog.editor.node.getPreviousSibling(childNode3)); - assertEquals('Should go to child 1', childNode1, - goog.editor.node.getPreviousSibling(childNode2)); - assertNull('Only has white space siblings', - goog.editor.node.getPreviousSibling(gChildWsNode2b)); - - tearDownDomTree(); -} - - -/** - * Creates a DOM tree and tests that getNextSibling properly ignores igrnorable - * nodes when determining the next sibling - */ -function testGetNextSibling() { - setUpDomTree(); - - assertEquals('Child 1 should have Child 2', childNode2, - goog.editor.node.getNextSibling(childNode1)); - assertEquals('Child 2 should have child 3', childNode3, - goog.editor.node.getNextSibling(childNode2)); - assertNull('Child 3 has no next sibling', - goog.editor.node.getNextSibling(childNode3)); - assertNotEquals('Should not skip ws and nbsp nodes', gChildTextNode1, - goog.editor.node.getNextSibling(gChildMixedNode1)); - assertNotEquals('Should not skip nbsp node', gChildTextNode1, - goog.editor.node.getNextSibling(gChildWsNode1)); - assertEquals('Should have sibling', gChildTextNode1, - goog.editor.node.getNextSibling(gChildNbspNode1)); - assertNull('Should have no next sibling', - goog.editor.node.getNextSibling(gChildTextNode1)); - assertNull('Only has ws sibling', - goog.editor.node.getNextSibling(gChildWsNode2a)); - assertNull('Has no next sibling', - goog.editor.node.getNextSibling(gChildWsNode2b)); - assertEquals('Should skip ws node', gChildTextNode3b, - goog.editor.node.getNextSibling(gChildTextNode3a)); - - tearDownDomTree(); -} - - -function testIsEmpty() { - var textNode = document.createTextNode(''); - assertTrue('Text node with no content should be empty', - goog.editor.node.isEmpty(textNode)); - textNode.data = '\xa0'; - assertTrue('Text node with nbsp should be empty', - goog.editor.node.isEmpty(textNode)); - assertFalse('Text node with nbsp should not be empty when prohibited', - goog.editor.node.isEmpty(textNode, true)); - - textNode.data = ' '; - assertTrue('Text node with whitespace should be empty', - goog.editor.node.isEmpty(textNode)); - textNode.data = 'notEmpty'; - assertFalse('Text node with text should not be empty', - goog.editor.node.isEmpty(textNode)); - - var div = document.createElement('div'); - assertTrue('Empty div should be empty', - goog.editor.node.isEmpty(div)); - div.innerHTML = ''; - assertFalse('Div containing an iframe is not empty', - goog.editor.node.isEmpty(div)); - div.innerHTML = ''; - assertFalse('Div containing an image is not empty', - goog.editor.node.isEmpty(div)); - div.innerHTML = ''; - assertFalse('Div containing an embed is not empty', - goog.editor.node.isEmpty(div)); - div.innerHTML = '
    '; - assertTrue('Div containing other empty tags is empty', - goog.editor.node.isEmpty(div)); - div.innerHTML = '
    '; - assertTrue('Div containing other empty tags and whitespace is empty', - goog.editor.node.isEmpty(div)); - div.innerHTML = '
    Not empty
    '; - assertFalse('Div containing tags and text is not empty', - goog.editor.node.isEmpty(div)); - - var img = document.createElement(goog.dom.TagName.IMG); - assertFalse('Empty img should not be empty', - goog.editor.node.isEmpty(img)); - - var iframe = document.createElement(goog.dom.TagName.IFRAME); - assertFalse('Empty iframe should not be empty', - goog.editor.node.isEmpty(iframe)); - - var embed = document.createElement('embed'); - assertFalse('Empty embed should not be empty', - goog.editor.node.isEmpty(embed)); -} - - -/** - * Test that getLength returns 0 if the node has no length and no children, - * the # of children if the node has no length but does have children, - * and the length of the node if the node does have length - */ -function testGetLength() { - var parentNode = document.createElement('p'); - - assertEquals('Length 0 and no children', 0, - goog.editor.node.getLength(parentNode)); - - var childNode1 = document.createTextNode('node 1'); - var childNode2 = document.createTextNode('node number 2'); - var childNode3 = document.createTextNode(''); - parentNode.appendChild(childNode1); - parentNode.appendChild(childNode2); - parentNode.appendChild(childNode3); - assertEquals('Length 0 and 3 children', 3, - goog.editor.node.getLength(parentNode)); - assertEquals('Text node, length 6', 6, - goog.editor.node.getLength(childNode1)); - assertEquals('Text node, length 0', 0, - goog.editor.node.getLength(childNode3)); -} - -function testFindInChildrenSuccess() { - var parentNode = document.createElement('div'); - parentNode.innerHTML = '
    foo
    foo2'; - - var index = goog.editor.node.findInChildren(parentNode, - function(node) { - return node.tagName == 'B'; - }); - assertEquals('Should find second child', index, 1); -} - -function testFindInChildrenFailure() { - var parentNode = document.createElement('div'); - parentNode.innerHTML = '
    foo
    foo2'; - - var index = goog.editor.node.findInChildren(parentNode, - function(node) { - return false; - }); - assertNull("Shouldn't find a child", index); -} - -function testFindHighestMatchingAncestor() { - setUpDomTree(); - var predicateFunc = function(node) { - return node.tagName == 'DIV'; - }; - var node = goog.editor.node.findHighestMatchingAncestor( - gChildTextNode3a, predicateFunc); - assertNotNull('Should return an ancestor', node); - assertEquals('Should have found "parentNode" as the last ' + - 'ancestor matching the predicate', - parentNode, - node); - - predicateFunc = function(node) { - return node.childNodes.length == 1; - }; - node = goog.editor.node.findHighestMatchingAncestor(gChildTextNode3a, - predicateFunc); - assertNull("Shouldn't return an ancestor", node); - - tearDownDomTree(); -} - -function testIsBlock() { - var blockDisplays = ['block', 'list-item', 'table', 'table-caption', - 'table-cell', 'table-column', 'table-column-group', 'table-footer', - 'table-footer-group', 'table-header-group', 'table-row', - 'table-row-group']; - - var structuralTags = [ - goog.dom.TagName.BODY, - goog.dom.TagName.FRAME, - goog.dom.TagName.FRAMESET, - goog.dom.TagName.HEAD, - goog.dom.TagName.HTML - ]; - - // The following tags are considered inline in IE, except LEGEND which is - // only a block element in WEBKIT. - var ambiguousTags = [ - goog.dom.TagName.DETAILS, - goog.dom.TagName.HR, - goog.dom.TagName.ISINDEX, - goog.dom.TagName.LEGEND, - goog.dom.TagName.MAP, - goog.dom.TagName.NOFRAMES, - goog.dom.TagName.OPTGROUP, - goog.dom.TagName.OPTION, - goog.dom.TagName.SUMMARY - ]; - - // Older versions of IE and Gecko consider the following elements to be - // inline, but IE9+ and Gecko 2.0+ recognize the new elements. - var legacyAmbiguousTags = [ - goog.dom.TagName.ARTICLE, - goog.dom.TagName.ASIDE, - goog.dom.TagName.FIGCAPTION, - goog.dom.TagName.FIGURE, - goog.dom.TagName.FOOTER, - goog.dom.TagName.HEADER, - goog.dom.TagName.HGROUP, - goog.dom.TagName.NAV, - goog.dom.TagName.SECTION - ]; - - var tagsToIgnore = goog.array.flatten(structuralTags, ambiguousTags); - - if ((goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9)) || - (goog.userAgent.GECKO && !goog.userAgent.isVersionOrHigher('2'))) { - goog.array.extend(tagsToIgnore, legacyAmbiguousTags); - } - - // Appending an applet tag can cause the test to hang if Java is blocked on - // the system. - tagsToIgnore.push(goog.dom.TagName.APPLET); - - // Appending an embed tag to the page in IE brings up a warning dialog about - // loading Java content. - if (goog.userAgent.IE) { - tagsToIgnore.push(goog.dom.TagName.EMBED); - } - - for (var tag in goog.dom.TagName) { - if (goog.array.contains(tagsToIgnore, tag)) { - continue; - } - - var el = goog.dom.createElement(tag); - document.body.appendChild(el); - var display = goog.style.getCascadedStyle(el, 'display') || - goog.style.getComputedStyle(el, 'display'); - goog.dom.removeNode(el); - - if (goog.editor.node.isBlockTag(el)) { - assertContains('Display for ' + tag + ' should be block-like', - display, blockDisplays); - } else { - assertNotContains('Display for ' + tag + ' should not be block-like', - display, blockDisplays); - } - } -} - -function createDivWithTextNodes(var_args) { - var dom = goog.dom.createDom('div'); - for (var i = 0; i < arguments.length; i++) { - goog.dom.appendChild(dom, goog.dom.createTextNode(arguments[i])); - } - return dom; -} - -function testSkipEmptyTextNodes() { - assertNull('skipEmptyTextNodes should gracefully handle null', - goog.editor.node.skipEmptyTextNodes(null)); - - var dom1 = createDivWithTextNodes('abc', '', 'xyz', '', ''); - assertEquals('expected not to skip first child', dom1.firstChild, - goog.editor.node.skipEmptyTextNodes(dom1.firstChild)); - assertEquals('expected to skip second child', dom1.childNodes[2], - goog.editor.node.skipEmptyTextNodes(dom1.childNodes[1])); - assertNull('expected to skip all the rest of the children', - goog.editor.node.skipEmptyTextNodes(dom1.childNodes[3])); -} - -function testIsEditableContainer() { - var editableContainerElement = document.getElementById('editableTest'); - assertTrue('Container element should be considered editable container', - goog.editor.node.isEditableContainer(editableContainerElement)); - - var nonEditableContainerElement = document.getElementById('parentNode'); - assertFalse('Other element should not be considered editable container', - goog.editor.node.isEditableContainer(nonEditableContainerElement)); -} - -function testIsEditable() { - var editableContainerElement = document.getElementById('editableTest'); - var childNode = editableContainerElement.firstChild; - var childElement = editableContainerElement.getElementsByTagName('span')[0]; - - assertFalse('Container element should not be considered editable', - goog.editor.node.isEditable(editableContainerElement)); - assertTrue('Child text node should be considered editable', - goog.editor.node.isEditable(childNode)); - assertTrue('Child element should be considered editable', - goog.editor.node.isEditable(childElement)); - assertTrue('Grandchild node should be considered editable', - goog.editor.node.isEditable(childElement.firstChild)); - assertFalse('Other element should not be considered editable', - goog.editor.node.isEditable(document.getElementById('parentNode'))); -} - -function testFindTopMostEditableAncestor() { - var root = document.getElementById('editableTest'); - var span = root.getElementsByTagName(goog.dom.TagName.SPAN)[0]; - var textNode = span.firstChild; - - assertEquals('Should return self if self is matched.', - textNode, goog.editor.node.findTopMostEditableAncestor(textNode, - function(node) { - return node.nodeType == goog.dom.NodeType.TEXT; - })); - assertEquals('Should not walk out of editable node.', - null, goog.editor.node.findTopMostEditableAncestor(textNode, - function(node) { - return node.tagName == goog.dom.TagName.BODY; - })); - assertEquals('Should not match editable container.', - null, goog.editor.node.findTopMostEditableAncestor(textNode, - function(node) { - return node.tagName == goog.dom.TagName.DIV; - })); - assertEquals('Should find node in editable container.', - span, goog.editor.node.findTopMostEditableAncestor(textNode, - function(node) { - return node.tagName == goog.dom.TagName.SPAN; - })); -} - -function testSplitDomTreeAt() { - var innerHTML = '

    123

    '; - var root = goog.dom.createElement(goog.dom.TagName.DIV); - - root.innerHTML = innerHTML; - var result = goog.editor.node.splitDomTreeAt( - root.getElementsByTagName(goog.dom.TagName.B)[0], null, root); - goog.testing.dom.assertHtmlContentsMatch('

    12

    ', root); - goog.testing.dom.assertHtmlContentsMatch('

    3

    ', result); - - root.innerHTML = innerHTML; - result = goog.editor.node.splitDomTreeAt( - root.getElementsByTagName(goog.dom.TagName.B)[0], - goog.dom.createTextNode('and'), - root); - goog.testing.dom.assertHtmlContentsMatch('

    12

    ', root); - goog.testing.dom.assertHtmlContentsMatch('

    and3

    ', result); -} - -function testTransferChildren() { - var prefix = 'Bold 1'; - var innerHTML = 'Bold
    • Item 1
    • Item 2
    '; - - var root1 = goog.dom.createElement(goog.dom.TagName.DIV); - root1.innerHTML = innerHTML; - - var root2 = goog.dom.createElement(goog.dom.TagName.P); - root2.innerHTML = prefix; - - var b = root1.getElementsByTagName(goog.dom.TagName.B)[0]; - - // Transfer the children. - goog.editor.node.transferChildren(root2, root1); - assertEquals(0, root1.childNodes.length); - goog.testing.dom.assertHtmlContentsMatch(prefix + innerHTML, root2); - assertEquals(b, root2.getElementsByTagName(goog.dom.TagName.B)[1]); - - // Transfer them back. - goog.editor.node.transferChildren(root1, root2); - assertEquals(0, root2.childNodes.length); - goog.testing.dom.assertHtmlContentsMatch(prefix + innerHTML, root1); - assertEquals(b, root1.getElementsByTagName(goog.dom.TagName.B)[1]); -} diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugin.js b/src/database/third_party/closure-library/closure/goog/editor/plugin.js deleted file mode 100644 index d823ccb1d31..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugin.js +++ /dev/null @@ -1,463 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// All Rights Reserved. - -/** - * @fileoverview Abstract API for TrogEdit plugins. - * - * @see ../demos/editor/editor.html - */ - -goog.provide('goog.editor.Plugin'); - -// TODO(user): Remove the dependency on goog.editor.Command asap. Currently only -// needed for execCommand issues with links. -goog.require('goog.events.EventTarget'); -goog.require('goog.functions'); -goog.require('goog.log'); -goog.require('goog.object'); -goog.require('goog.reflect'); -goog.require('goog.userAgent'); - - - -/** - * Abstract API for trogedit plugins. - * @constructor - * @extends {goog.events.EventTarget} - */ -goog.editor.Plugin = function() { - goog.events.EventTarget.call(this); - - /** - * Whether this plugin is enabled for the registered field object. - * @type {boolean} - * @private - */ - this.enabled_ = this.activeOnUneditableFields(); -}; -goog.inherits(goog.editor.Plugin, goog.events.EventTarget); - - -/** - * The field object this plugin is attached to. - * @type {goog.editor.Field} - * @protected - * @deprecated Use goog.editor.Plugin.getFieldObject and - * goog.editor.Plugin.setFieldObject. - */ -goog.editor.Plugin.prototype.fieldObject = null; - - -/** - * @return {goog.dom.DomHelper?} The dom helper object associated with the - * currently active field. - */ -goog.editor.Plugin.prototype.getFieldDomHelper = function() { - return this.getFieldObject() && this.getFieldObject().getEditableDomHelper(); -}; - - -/** - * Indicates if this plugin should be automatically disposed when the - * registered field is disposed. This should be changed to false for - * plugins used as multi-field plugins. - * @type {boolean} - * @private - */ -goog.editor.Plugin.prototype.autoDispose_ = true; - - -/** - * The logger for this plugin. - * @type {goog.log.Logger} - * @protected - */ -goog.editor.Plugin.prototype.logger = - goog.log.getLogger('goog.editor.Plugin'); - - -/** - * Sets the field object for use with this plugin. - * @return {goog.editor.Field} The editable field object. - * @protected - * @suppress {deprecated} Until fieldObject can be made private. - */ -goog.editor.Plugin.prototype.getFieldObject = function() { - return this.fieldObject; -}; - - -/** - * Sets the field object for use with this plugin. - * @param {goog.editor.Field} fieldObject The editable field object. - * @protected - * @suppress {deprecated} Until fieldObject can be made private. - */ -goog.editor.Plugin.prototype.setFieldObject = function(fieldObject) { - this.fieldObject = fieldObject; -}; - - -/** - * Registers the field object for use with this plugin. - * @param {goog.editor.Field} fieldObject The editable field object. - */ -goog.editor.Plugin.prototype.registerFieldObject = function(fieldObject) { - this.setFieldObject(fieldObject); -}; - - -/** - * Unregisters and disables this plugin for the current field object. - * @param {goog.editor.Field} fieldObj The field object. For single-field - * plugins, this parameter is ignored. - */ -goog.editor.Plugin.prototype.unregisterFieldObject = function(fieldObj) { - if (this.getFieldObject()) { - this.disable(this.getFieldObject()); - this.setFieldObject(null); - } -}; - - -/** - * Enables this plugin for the specified, registered field object. A field - * object should only be enabled when it is loaded. - * @param {goog.editor.Field} fieldObject The field object. - */ -goog.editor.Plugin.prototype.enable = function(fieldObject) { - if (this.getFieldObject() == fieldObject) { - this.enabled_ = true; - } else { - goog.log.error(this.logger, 'Trying to enable an unregistered field with ' + - 'this plugin.'); - } -}; - - -/** - * Disables this plugin for the specified, registered field object. - * @param {goog.editor.Field} fieldObject The field object. - */ -goog.editor.Plugin.prototype.disable = function(fieldObject) { - if (this.getFieldObject() == fieldObject) { - this.enabled_ = false; - } else { - goog.log.error(this.logger, 'Trying to disable an unregistered field ' + - 'with this plugin.'); - } -}; - - -/** - * Returns whether this plugin is enabled for the field object. - * - * @param {goog.editor.Field} fieldObject The field object. - * @return {boolean} Whether this plugin is enabled for the field object. - */ -goog.editor.Plugin.prototype.isEnabled = function(fieldObject) { - return this.getFieldObject() == fieldObject ? this.enabled_ : false; -}; - - -/** - * Set if this plugin should automatically be disposed when the registered - * field is disposed. - * @param {boolean} autoDispose Whether to autoDispose. - */ -goog.editor.Plugin.prototype.setAutoDispose = function(autoDispose) { - this.autoDispose_ = autoDispose; -}; - - -/** - * @return {boolean} Whether or not this plugin should automatically be disposed - * when it's registered field is disposed. - */ -goog.editor.Plugin.prototype.isAutoDispose = function() { - return this.autoDispose_; -}; - - -/** - * @return {boolean} If true, field will not disable the command - * when the field becomes uneditable. - */ -goog.editor.Plugin.prototype.activeOnUneditableFields = goog.functions.FALSE; - - -/** - * @param {string} command The command to check. - * @return {boolean} If true, field will not dispatch change events - * for commands of this type. This is useful for "seamless" plugins like - * dialogs and lorem ipsum. - */ -goog.editor.Plugin.prototype.isSilentCommand = goog.functions.FALSE; - - -/** @override */ -goog.editor.Plugin.prototype.disposeInternal = function() { - if (this.getFieldObject()) { - this.unregisterFieldObject(this.getFieldObject()); - } - - goog.editor.Plugin.superClass_.disposeInternal.call(this); -}; - - -/** - * @return {string} The ID unique to this plugin class. Note that different - * instances off the plugin share the same classId. - */ -goog.editor.Plugin.prototype.getTrogClassId; - - -/** - * An enum of operations that plugins may support. - * @enum {number} - */ -goog.editor.Plugin.Op = { - KEYDOWN: 1, - KEYPRESS: 2, - KEYUP: 3, - SELECTION: 4, - SHORTCUT: 5, - EXEC_COMMAND: 6, - QUERY_COMMAND: 7, - PREPARE_CONTENTS_HTML: 8, - CLEAN_CONTENTS_HTML: 10, - CLEAN_CONTENTS_DOM: 11 -}; - - -/** - * A map from plugin operations to the names of the methods that - * invoke those operations. - */ -goog.editor.Plugin.OPCODE = goog.object.transpose( - goog.reflect.object(goog.editor.Plugin, { - handleKeyDown: goog.editor.Plugin.Op.KEYDOWN, - handleKeyPress: goog.editor.Plugin.Op.KEYPRESS, - handleKeyUp: goog.editor.Plugin.Op.KEYUP, - handleSelectionChange: goog.editor.Plugin.Op.SELECTION, - handleKeyboardShortcut: goog.editor.Plugin.Op.SHORTCUT, - execCommand: goog.editor.Plugin.Op.EXEC_COMMAND, - queryCommandValue: goog.editor.Plugin.Op.QUERY_COMMAND, - prepareContentsHtml: goog.editor.Plugin.Op.PREPARE_CONTENTS_HTML, - cleanContentsHtml: goog.editor.Plugin.Op.CLEAN_CONTENTS_HTML, - cleanContentsDom: goog.editor.Plugin.Op.CLEAN_CONTENTS_DOM - })); - - -/** - * A set of op codes that run even on disabled plugins. - */ -goog.editor.Plugin.IRREPRESSIBLE_OPS = goog.object.createSet( - goog.editor.Plugin.Op.PREPARE_CONTENTS_HTML, - goog.editor.Plugin.Op.CLEAN_CONTENTS_HTML, - goog.editor.Plugin.Op.CLEAN_CONTENTS_DOM); - - -/** - * Handles keydown. It is run before handleKeyboardShortcut and if it returns - * true handleKeyboardShortcut will not be called. - * @param {!goog.events.BrowserEvent} e The browser event. - * @return {boolean} Whether the event was handled and thus should *not* be - * propagated to other plugins or handleKeyboardShortcut. - */ -goog.editor.Plugin.prototype.handleKeyDown; - - -/** - * Handles keypress. It is run before handleKeyboardShortcut and if it returns - * true handleKeyboardShortcut will not be called. - * @param {!goog.events.BrowserEvent} e The browser event. - * @return {boolean} Whether the event was handled and thus should *not* be - * propagated to other plugins or handleKeyboardShortcut. - */ -goog.editor.Plugin.prototype.handleKeyPress; - - -/** - * Handles keyup. - * @param {!goog.events.BrowserEvent} e The browser event. - * @return {boolean} Whether the event was handled and thus should *not* be - * propagated to other plugins. - */ -goog.editor.Plugin.prototype.handleKeyUp; - - -/** - * Handles selection change. - * @param {!goog.events.BrowserEvent=} opt_e The browser event. - * @param {!Node=} opt_target The node the selection changed to. - * @return {boolean} Whether the event was handled and thus should *not* be - * propagated to other plugins. - */ -goog.editor.Plugin.prototype.handleSelectionChange; - - -/** - * Handles keyboard shortcuts. Preferred to using handleKey* as it will use - * the proper event based on browser and will be more performant. If - * handleKeyPress/handleKeyDown returns true, this will not be called. If the - * plugin handles the shortcut, it is responsible for dispatching appropriate - * events (change, selection change at the time of this comment). If the plugin - * calls execCommand on the editable field, then execCommand already takes care - * of dispatching events. - * NOTE: For performance reasons this is only called when any key is pressed - * in conjunction with ctrl/meta keys OR when a small subset of keys (defined - * in goog.editor.Field.POTENTIAL_SHORTCUT_KEYCODES_) are pressed without - * ctrl/meta keys. We specifically don't invoke it when altKey is pressed since - * alt key is used in many i8n UIs to enter certain characters. - * @param {!goog.events.BrowserEvent} e The browser event. - * @param {string} key The key pressed. - * @param {boolean} isModifierPressed Whether the ctrl/meta key was pressed or - * not. - * @return {boolean} Whether the event was handled and thus should *not* be - * propagated to other plugins. We also call preventDefault on the event if - * the return value is true. - */ -goog.editor.Plugin.prototype.handleKeyboardShortcut; - - -/** - * Handles execCommand. This default implementation handles dispatching - * BEFORECHANGE, CHANGE, and SELECTIONCHANGE events, and calls - * execCommandInternal to perform the actual command. Plugins that want to - * do their own event dispatching should override execCommand, otherwise - * it is preferred to only override execCommandInternal. - * - * This version of execCommand will only work for single field plugins. - * Multi-field plugins must override execCommand. - * - * @param {string} command The command to execute. - * @param {...*} var_args Any additional parameters needed to - * execute the command. - * @return {*} The result of the execCommand, if any. - */ -goog.editor.Plugin.prototype.execCommand = function(command, var_args) { - // TODO(user): Replace all uses of isSilentCommand with plugins that just - // override this base execCommand method. - var silent = this.isSilentCommand(command); - if (!silent) { - // Stop listening to mutation events in Firefox while text formatting - // is happening. This prevents us from trying to size the field in the - // middle of an execCommand, catching the field in a strange intermediary - // state where both replacement nodes and original nodes are appended to - // the dom. Note that change events get turned back on by - // fieldObj.dispatchChange. - if (goog.userAgent.GECKO) { - this.getFieldObject().stopChangeEvents(true, true); - } - - this.getFieldObject().dispatchBeforeChange(); - } - - try { - var result = this.execCommandInternal.apply(this, arguments); - } finally { - // If the above execCommandInternal call throws an exception, we still need - // to turn change events back on (see http://b/issue?id=1471355). - // NOTE: If if you add to or change the methods called in this finally - // block, please add them as expected calls to the unit test function - // testExecCommandException(). - if (!silent) { - // dispatchChange includes a call to startChangeEvents, which unwinds the - // call to stopChangeEvents made before the try block. - this.getFieldObject().dispatchChange(); - this.getFieldObject().dispatchSelectionChangeEvent(); - } - } - - return result; -}; - - -/** - * Handles execCommand. This default implementation does nothing, and is - * called by execCommand, which handles event dispatching. This method should - * be overriden by plugins that don't need to do their own event dispatching. - * If custom event dispatching is needed, execCommand shoul be overriden - * instead. - * - * @param {string} command The command to execute. - * @param {...*} var_args Any additional parameters needed to - * execute the command. - * @return {*} The result of the execCommand, if any. - * @protected - */ -goog.editor.Plugin.prototype.execCommandInternal; - - -/** - * Gets the state of this command if this plugin serves that command. - * @param {string} command The command to check. - * @return {*} The value of the command. - */ -goog.editor.Plugin.prototype.queryCommandValue; - - -/** - * Prepares the given HTML for editing. Strips out content that should not - * appear in an editor, and normalizes content as appropriate. The inverse - * of cleanContentsHtml. - * - * This op is invoked even on disabled plugins. - * - * @param {string} originalHtml The original HTML. - * @param {Object} styles A map of strings. If the plugin wants to add - * any styles to the field element, it should add them as key-value - * pairs to this object. - * @return {string} New HTML that's ok for editing. - */ -goog.editor.Plugin.prototype.prepareContentsHtml; - - -/** - * Cleans the contents of the node passed to it. The node contents are modified - * directly, and the modifications will subsequently be used, for operations - * such as saving the innerHTML of the editor etc. Since the plugins act on - * the DOM directly, this method can be very expensive. - * - * This op is invoked even on disabled plugins. - * - * @param {!Element} fieldCopy The copy of the editable field which - * needs to be cleaned up. - */ -goog.editor.Plugin.prototype.cleanContentsDom; - - -/** - * Cleans the html contents of Trogedit. Both cleanContentsDom and - * and cleanContentsHtml will be called on contents extracted from Trogedit. - * The inverse of prepareContentsHtml. - * - * This op is invoked even on disabled plugins. - * - * @param {string} originalHtml The trogedit HTML. - * @return {string} Cleaned-up HTML. - */ -goog.editor.Plugin.prototype.cleanContentsHtml; - - -/** - * Whether the string corresponds to a command this plugin handles. - * @param {string} command Command string to check. - * @return {boolean} Whether the plugin handles this type of command. - */ -goog.editor.Plugin.prototype.isSupportedCommand = function(command) { - return false; -}; diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugin_test.html b/src/database/third_party/closure-library/closure/goog/editor/plugin_test.html deleted file mode 100644 index 9e97402d6ea..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugin_test.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - Editor Unit Tests - goog.editor.Plugin - - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugin_test.js b/src/database/third_party/closure-library/closure/goog/editor/plugin_test.js deleted file mode 100644 index 6bac70049f0..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugin_test.js +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.editor.PluginTest'); -goog.setTestOnly('goog.editor.PluginTest'); - -goog.require('goog.editor.Field'); -goog.require('goog.editor.Plugin'); -goog.require('goog.functions'); -goog.require('goog.testing.StrictMock'); -goog.require('goog.testing.jsunit'); -goog.require('goog.userAgent'); - -var plugin; -var fieldObject; - - -function setUp() { - plugin = new goog.editor.Plugin(); - fieldObject = {}; -} - - -function tearDown() { - plugin.dispose(); -} - - -function testRegisterFieldObject() { - plugin.registerFieldObject(fieldObject); - assertEquals('Register field object must be stored in protected field.', - fieldObject, plugin.fieldObject); - - assertFalse('Newly registered plugin must not be enabled.', - plugin.isEnabled(fieldObject)); -} - - -function testUnregisterFieldObject() { - plugin.registerFieldObject(fieldObject); - plugin.enable(fieldObject); - plugin.unregisterFieldObject(fieldObject); - - assertNull('fieldObject property must be undefined after ' + - 'unregistering a field object.', plugin.fieldObject); - assertFalse('Unregistered field object must not be enabled', - plugin.isEnabled(fieldObject)); -} - - -function testEnable() { - plugin.registerFieldObject(fieldObject); - plugin.enable(fieldObject); - - assertTrue('Enabled field object must be enabled according to isEnabled().', - plugin.isEnabled(fieldObject)); -} - - -function testDisable() { - plugin.registerFieldObject(fieldObject); - plugin.enable(fieldObject); - plugin.disable(fieldObject); - - assertFalse('Disabled field object must be disabled according to ' + - 'isEnabled().', plugin.isEnabled(fieldObject)); -} - - -function testIsEnabled() { - // Other base cases covered while testing enable() and disable(). - - assertFalse('Unregistered field object must be disabled according ' + - 'to isEnabled().', plugin.isEnabled(fieldObject)); -} - - -function testIsSupportedCommand() { - assertFalse('Base plugin class must not support any commands.', - plugin.isSupportedCommand('+indent')); -} - -function testExecCommand() { - var mockField = new goog.testing.StrictMock(goog.editor.Field); - plugin.registerFieldObject(mockField); - - if (goog.userAgent.GECKO) { - mockField.stopChangeEvents(true, true); - } - mockField.dispatchBeforeChange(); - // Note(user): dispatch change turns back on (delayed) change events. - mockField.dispatchChange(); - mockField.dispatchSelectionChangeEvent(); - mockField.$replay(); - - var passedCommand, passedArg; - plugin.execCommandInternal = function(command, arg) { - passedCommand = command; - passedArg = arg; - }; - plugin.execCommand('+indent', true); - - // Verify that execCommand dispatched the expected events. - mockField.$verify(); - mockField.$reset(); - // Verify that execCommandInternal was called with the correct arguments. - assertEquals('+indent', passedCommand); - assertTrue(passedArg); - - plugin.isSilentCommand = goog.functions.constant(true); - mockField.$replay(); - plugin.execCommand('+outdent', false); - // Verify that execCommand on a silent plugin dispatched no events. - mockField.$verify(); - // Verify that execCommandInternal was called with the correct arguments. - assertEquals('+outdent', passedCommand); - assertFalse(passedArg); -} - - -/** - * Regression test for http://b/issue?id=1471355 . - */ -function testExecCommandException() { - var mockField = new goog.testing.StrictMock(goog.editor.Field); - plugin.registerFieldObject(mockField); - plugin.execCommandInternal = function() { - throw 1; - }; - - if (goog.userAgent.GECKO) { - mockField.stopChangeEvents(true, true); - } - mockField.dispatchBeforeChange(); - // Note(user): dispatch change turns back on (delayed) change events. - mockField.dispatchChange(); - mockField.dispatchSelectionChangeEvent(); - mockField.$replay(); - - assertThrows('Exception should not be swallowed', function() { - plugin.execCommand(); - }); - - // Verifies that cleanup is done despite the exception. - mockField.$verify(); -} - -function testDisposed() { - plugin.registerFieldObject(fieldObject); - plugin.dispose(); - assert(plugin.getDisposed()); - assertNull('Disposed plugin must not have a field object.', - plugin.fieldObject); - assertFalse('Disposed plugin must not have an enabled field object.', - plugin.isEnabled(fieldObject)); -} - -function testIsAndSetAutoDispose() { - assertTrue('Plugin must start auto-disposable', plugin.isAutoDispose()); - - plugin.setAutoDispose(false); - assertFalse(plugin.isAutoDispose()); - - plugin.setAutoDispose(true); - assertTrue(plugin.isAutoDispose()); -} diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/abstractbubbleplugin.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/abstractbubbleplugin.js deleted file mode 100644 index 4951ed68e08..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/abstractbubbleplugin.js +++ /dev/null @@ -1,712 +0,0 @@ -// Copyright 2005 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Base class for bubble plugins. - * @author robbyw@google.com (Robby Walker) - */ - -goog.provide('goog.editor.plugins.AbstractBubblePlugin'); - -goog.require('goog.array'); -goog.require('goog.dom'); -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.Range'); -goog.require('goog.dom.TagName'); -goog.require('goog.dom.classlist'); -goog.require('goog.editor.Plugin'); -goog.require('goog.editor.style'); -goog.require('goog.events'); -goog.require('goog.events.EventHandler'); -goog.require('goog.events.EventType'); -goog.require('goog.events.KeyCodes'); -goog.require('goog.events.actionEventWrapper'); -goog.require('goog.functions'); -goog.require('goog.string.Unicode'); -goog.require('goog.ui.Component'); -goog.require('goog.ui.editor.Bubble'); -goog.require('goog.userAgent'); - - - -/** - * Base class for bubble plugins. This is used for to connect user behavior - * in the editor to a goog.ui.editor.Bubble UI element that allows - * the user to modify the properties of an element on their page (e.g. the alt - * text of an image tag). - * - * Subclasses should override the abstract method getBubbleTargetFromSelection() - * with code to determine if the current selection should activate the bubble - * type. The other abstract method createBubbleContents() should be overriden - * with code to create the inside markup of the bubble. The base class creates - * the rest of the bubble. - * - * @constructor - * @extends {goog.editor.Plugin} - */ -goog.editor.plugins.AbstractBubblePlugin = function() { - goog.editor.plugins.AbstractBubblePlugin.base(this, 'constructor'); - - /** - * Place to register events the plugin listens to. - * @type {goog.events.EventHandler< - * !goog.editor.plugins.AbstractBubblePlugin>} - * @protected - */ - this.eventRegister = new goog.events.EventHandler(this); - - /** - * Instance factory function that creates a bubble UI component. If set to a - * non-null value, this function will be used to create a bubble instead of - * the global factory function. It takes as parameters the bubble parent - * element and the z index to draw the bubble at. - * @type {?function(!Element, number): !goog.ui.editor.Bubble} - * @private - */ - this.bubbleFactory_ = null; -}; -goog.inherits(goog.editor.plugins.AbstractBubblePlugin, goog.editor.Plugin); - - -/** - * The css class name of option link elements. - * @type {string} - * @private - */ -goog.editor.plugins.AbstractBubblePlugin.OPTION_LINK_CLASSNAME_ = - goog.getCssName('tr_option-link'); - - -/** - * The css class name of link elements. - * @type {string} - * @private - */ -goog.editor.plugins.AbstractBubblePlugin.LINK_CLASSNAME_ = - goog.getCssName('tr_bubble_link'); - - -/** - * A class name to mark elements that should be reachable by keyboard tabbing. - * @type {string} - * @private - */ -goog.editor.plugins.AbstractBubblePlugin.TABBABLE_CLASSNAME_ = - goog.getCssName('tr_bubble_tabbable'); - - -/** - * The constant string used to separate option links. - * @type {string} - * @protected - */ -goog.editor.plugins.AbstractBubblePlugin.DASH_NBSP_STRING = - goog.string.Unicode.NBSP + '-' + goog.string.Unicode.NBSP; - - -/** - * Default factory function for creating a bubble UI component. - * @param {!Element} parent The parent element for the bubble. - * @param {number} zIndex The z index to draw the bubble at. - * @return {!goog.ui.editor.Bubble} The new bubble component. - * @private - */ -goog.editor.plugins.AbstractBubblePlugin.defaultBubbleFactory_ = function( - parent, zIndex) { - return new goog.ui.editor.Bubble(parent, zIndex); -}; - - -/** - * Global factory function that creates a bubble UI component. It takes as - * parameters the bubble parent element and the z index to draw the bubble at. - * @type {function(!Element, number): !goog.ui.editor.Bubble} - * @private - */ -goog.editor.plugins.AbstractBubblePlugin.globalBubbleFactory_ = - goog.editor.plugins.AbstractBubblePlugin.defaultBubbleFactory_; - - -/** - * Sets the global bubble factory function. - * @param {function(!Element, number): !goog.ui.editor.Bubble} - * bubbleFactory Function that creates a bubble for the given bubble parent - * element and z index. - */ -goog.editor.plugins.AbstractBubblePlugin.setBubbleFactory = function( - bubbleFactory) { - goog.editor.plugins.AbstractBubblePlugin.globalBubbleFactory_ = bubbleFactory; -}; - - -/** - * Map from field id to shared bubble object. - * @type {!Object} - * @private - */ -goog.editor.plugins.AbstractBubblePlugin.bubbleMap_ = {}; - - -/** - * The optional parent of the bubble. If null or not set, we will use the - * application document. This is useful when you have an editor embedded in - * a scrolling DIV. - * @type {Element|undefined} - * @private - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.bubbleParent_; - - -/** - * The id of the panel this plugin added to the shared bubble. Null when - * this plugin doesn't currently have a panel in a bubble. - * @type {string?} - * @private - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.panelId_ = null; - - -/** - * Whether this bubble should support tabbing through elements. False - * by default. - * @type {boolean} - * @private - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.keyboardNavigationEnabled_ = - false; - - -/** - * Sets the instance bubble factory function. If set to a non-null value, this - * function will be used to create a bubble instead of the global factory - * function. - * @param {?function(!Element, number): !goog.ui.editor.Bubble} bubbleFactory - * Function that creates a bubble for the given bubble parent element and z - * index. Null to reset the factory function. - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.setBubbleFactory = function( - bubbleFactory) { - this.bubbleFactory_ = bubbleFactory; -}; - - -/** - * Sets whether the bubble should support tabbing through elements. - * @param {boolean} keyboardNavigationEnabled - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.enableKeyboardNavigation = - function(keyboardNavigationEnabled) { - this.keyboardNavigationEnabled_ = keyboardNavigationEnabled; -}; - - -/** - * Sets the bubble parent. - * @param {Element} bubbleParent An element where the bubble will be - * anchored. If null, we will use the application document. This - * is useful when you have an editor embedded in a scrolling div. - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.setBubbleParent = function( - bubbleParent) { - this.bubbleParent_ = bubbleParent; -}; - - -/** - * Returns the bubble map. Subclasses may override to use a separate map. - * @return {!Object} - * @protected - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.getBubbleMap = function() { - return goog.editor.plugins.AbstractBubblePlugin.bubbleMap_; -}; - - -/** - * @return {goog.dom.DomHelper} The dom helper for the bubble window. - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.getBubbleDom = function() { - return this.dom_; -}; - - -/** @override */ -goog.editor.plugins.AbstractBubblePlugin.prototype.getTrogClassId = - goog.functions.constant('AbstractBubblePlugin'); - - -/** - * Returns the element whose properties the bubble manipulates. - * @return {Element} The target element. - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.getTargetElement = - function() { - return this.targetElement_; -}; - - -/** @override */ -goog.editor.plugins.AbstractBubblePlugin.prototype.handleKeyUp = function(e) { - // For example, when an image is selected, pressing any key overwrites - // the image and the panel should be hidden. - // Therefore we need to track key presses when the bubble is showing. - if (this.isVisible()) { - this.handleSelectionChange(); - } - return false; -}; - - -/** - * Pops up a property bubble for the given selection if appropriate and closes - * open property bubbles if no longer needed. This should not be overridden. - * @override - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.handleSelectionChange = - function(opt_e, opt_target) { - var selectedElement; - if (opt_e) { - selectedElement = /** @type {Element} */ (opt_e.target); - } else if (opt_target) { - selectedElement = /** @type {Element} */ (opt_target); - } else { - var range = this.getFieldObject().getRange(); - if (range) { - var startNode = range.getStartNode(); - var endNode = range.getEndNode(); - var startOffset = range.getStartOffset(); - var endOffset = range.getEndOffset(); - // Sometimes in IE, the range will be collapsed, but think the end node - // and start node are different (although in the same visible position). - // In this case, favor the position IE thinks is the start node. - if (goog.userAgent.IE && range.isCollapsed() && startNode != endNode) { - range = goog.dom.Range.createCaret(startNode, startOffset); - } - if (startNode.nodeType == goog.dom.NodeType.ELEMENT && - startNode == endNode && startOffset == endOffset - 1) { - var element = startNode.childNodes[startOffset]; - if (element.nodeType == goog.dom.NodeType.ELEMENT) { - selectedElement = element; - } - } - } - selectedElement = selectedElement || range && range.getContainerElement(); - } - return this.handleSelectionChangeInternal(selectedElement); -}; - - -/** - * Pops up a property bubble for the given selection if appropriate and closes - * open property bubbles if no longer needed. - * @param {Element?} selectedElement The selected element. - * @return {boolean} Always false, allowing every bubble plugin to handle the - * event. - * @protected - */ -goog.editor.plugins.AbstractBubblePlugin.prototype. - handleSelectionChangeInternal = function(selectedElement) { - if (selectedElement) { - var bubbleTarget = this.getBubbleTargetFromSelection(selectedElement); - if (bubbleTarget) { - if (bubbleTarget != this.targetElement_ || !this.panelId_) { - // Make sure any existing panel of the same type is closed before - // creating a new one. - if (this.panelId_) { - this.closeBubble(); - } - this.createBubble(bubbleTarget); - } - return false; - } - } - - if (this.panelId_) { - this.closeBubble(); - } - - return false; -}; - - -/** - * Should be overriden by subclasses to return the bubble target element or - * null if an element of their required type isn't found. - * @param {Element} selectedElement The target of the selection change event or - * the parent container of the current entire selection. - * @return {Element?} The HTML bubble target element or null if no element of - * the required type is not found. - */ -goog.editor.plugins.AbstractBubblePlugin.prototype. - getBubbleTargetFromSelection = goog.abstractMethod; - - -/** @override */ -goog.editor.plugins.AbstractBubblePlugin.prototype.disable = function(field) { - // When the field is made uneditable, dispose of the bubble. We do this - // because the next time the field is made editable again it may be in - // a different document / iframe. - if (field.isUneditable()) { - var bubbleMap = this.getBubbleMap(); - var bubble = bubbleMap[field.id]; - if (bubble) { - if (field == this.getFieldObject()) { - this.closeBubble(); - } - bubble.dispose(); - delete bubbleMap[field.id]; - } - } -}; - - -/** - * @return {!goog.ui.editor.Bubble} The shared bubble object for the field this - * plugin is registered on. Creates it if necessary. - * @private - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.getSharedBubble_ = - function() { - var bubbleParent = /** @type {!Element} */ (this.bubbleParent_ || - this.getFieldObject().getAppWindow().document.body); - this.dom_ = goog.dom.getDomHelper(bubbleParent); - - var bubbleMap = this.getBubbleMap(); - var bubble = bubbleMap[this.getFieldObject().id]; - if (!bubble) { - var factory = this.bubbleFactory_ || - goog.editor.plugins.AbstractBubblePlugin.globalBubbleFactory_; - bubble = factory.call(null, bubbleParent, - this.getFieldObject().getBaseZindex()); - bubbleMap[this.getFieldObject().id] = bubble; - } - return bubble; -}; - - -/** - * Creates and shows the property bubble. - * @param {Element} targetElement The target element of the bubble. - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.createBubble = function( - targetElement) { - var bubble = this.getSharedBubble_(); - if (!bubble.hasPanelOfType(this.getBubbleType())) { - this.targetElement_ = targetElement; - - this.panelId_ = bubble.addPanel(this.getBubbleType(), this.getBubbleTitle(), - targetElement, - goog.bind(this.createBubbleContents, this), - this.shouldPreferBubbleAboveElement()); - this.eventRegister.listen(bubble, goog.ui.Component.EventType.HIDE, - this.handlePanelClosed_); - - this.onShow(); - - if (this.keyboardNavigationEnabled_) { - this.eventRegister.listen(bubble.getContentElement(), - goog.events.EventType.KEYDOWN, this.onBubbleKey_); - } - } -}; - - -/** - * @return {string} The type of bubble shown by this plugin. Usually the tag - * name of the element this bubble targets. - * @protected - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.getBubbleType = function() { - return ''; -}; - - -/** - * @return {string} The title for bubble shown by this plugin. Defaults to no - * title. Should be overridden by subclasses. - * @protected - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.getBubbleTitle = function() { - return ''; -}; - - -/** - * @return {boolean} Whether the bubble should prefer placement above the - * target element. - * @protected - */ -goog.editor.plugins.AbstractBubblePlugin.prototype. - shouldPreferBubbleAboveElement = goog.functions.FALSE; - - -/** - * Should be overriden by subclasses to add the type specific contents to the - * bubble. - * @param {Element} bubbleContainer The container element of the bubble to - * which the contents should be added. - * @protected - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.createBubbleContents = - goog.abstractMethod; - - -/** - * Register the handler for the target's CLICK event. - * @param {Element} target The event source element. - * @param {Function} handler The event handler. - * @protected - * @deprecated Use goog.editor.plugins.AbstractBubblePlugin. - * registerActionHandler to register click and enter events. - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.registerClickHandler = - function(target, handler) { - this.registerActionHandler(target, handler); -}; - - -/** - * Register the handler for the target's CLICK and ENTER key events. - * @param {Element} target The event source element. - * @param {Function} handler The event handler. - * @protected - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.registerActionHandler = - function(target, handler) { - this.eventRegister.listenWithWrapper(target, goog.events.actionEventWrapper, - handler); -}; - - -/** - * Closes the bubble. - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.closeBubble = function() { - if (this.panelId_) { - this.getSharedBubble_().removePanel(this.panelId_); - this.handlePanelClosed_(); - } -}; - - -/** - * Called after the bubble is shown. The default implementation does nothing. - * Override it to provide your own one. - * @protected - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.onShow = goog.nullFunction; - - -/** - * Called when the bubble is closed or hidden. The default implementation does - * nothing. - * @protected - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.cleanOnBubbleClose = - goog.nullFunction; - - -/** - * Handles when the bubble panel is closed. Invoked when the entire bubble is - * hidden and also directly when the panel is closed manually. - * @private - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.handlePanelClosed_ = - function() { - this.targetElement_ = null; - this.panelId_ = null; - this.eventRegister.removeAll(); - this.cleanOnBubbleClose(); -}; - - -/** - * In case the keyboard navigation is enabled, this will set focus on the first - * tabbable element in the bubble when TAB is clicked. - * @override - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.handleKeyDown = function(e) { - if (this.keyboardNavigationEnabled_ && - this.isVisible() && - e.keyCode == goog.events.KeyCodes.TAB && !e.shiftKey) { - var bubbleEl = this.getSharedBubble_().getContentElement(); - var tabbable = goog.dom.getElementByClass( - goog.editor.plugins.AbstractBubblePlugin.TABBABLE_CLASSNAME_, bubbleEl); - if (tabbable) { - tabbable.focus(); - e.preventDefault(); - return true; - } - } - return false; -}; - - -/** - * Handles a key event on the bubble. This ensures that the focus loops through - * the tabbable elements found in the bubble and then the focus is got by the - * field element. - * @param {goog.events.BrowserEvent} e The event. - * @private - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.onBubbleKey_ = function(e) { - if (this.isVisible() && - e.keyCode == goog.events.KeyCodes.TAB) { - var bubbleEl = this.getSharedBubble_().getContentElement(); - var tabbables = goog.dom.getElementsByClass( - goog.editor.plugins.AbstractBubblePlugin.TABBABLE_CLASSNAME_, bubbleEl); - var tabbable = e.shiftKey ? tabbables[0] : goog.array.peek(tabbables); - var tabbingOutOfBubble = tabbable == e.target; - if (tabbingOutOfBubble) { - this.getFieldObject().focus(); - e.preventDefault(); - } - } -}; - - -/** - * @return {boolean} Whether the bubble is visible. - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.isVisible = function() { - return !!this.panelId_; -}; - - -/** - * Reposition the property bubble. - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.reposition = function() { - var bubble = this.getSharedBubble_(); - if (bubble) { - bubble.reposition(); - } -}; - - -/** - * Helper method that creates option links (such as edit, test, remove) - * @param {string} id String id for the span id. - * @return {Element} The option link element. - * @protected - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.createLinkOption = function( - id) { - // Dash plus link are together in a span so we can hide/show them easily - return this.dom_.createDom(goog.dom.TagName.SPAN, - { - id: id, - className: - goog.editor.plugins.AbstractBubblePlugin.OPTION_LINK_CLASSNAME_ - }, - this.dom_.createTextNode( - goog.editor.plugins.AbstractBubblePlugin.DASH_NBSP_STRING)); -}; - - -/** - * Helper method that creates a link with text set to linkText and optionally - * wires up a listener for the CLICK event or the link. The link is navigable by - * tabs if {@code enableKeyboardNavigation(true)} was called. - * @param {string} linkId The id of the link. - * @param {string} linkText Text of the link. - * @param {Function=} opt_onClick Optional function to call when the link is - * clicked. - * @param {Element=} opt_container If specified, location to insert link. If no - * container is specified, the old link is removed and replaced. - * @return {Element} The link element. - * @protected - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.createLink = function( - linkId, linkText, opt_onClick, opt_container) { - var link = this.createLinkHelper(linkId, linkText, false, opt_container); - if (opt_onClick) { - this.registerActionHandler(link, opt_onClick); - } - return link; -}; - - -/** - * Helper method to create a link to insert into the bubble. The link is - * navigable by tabs if {@code enableKeyboardNavigation(true)} was called. - * @param {string} linkId The id of the link. - * @param {string} linkText Text of the link. - * @param {boolean} isAnchor Set to true to create an actual anchor tag - * instead of a span. Actual links are right clickable (e.g. to open in - * a new window) and also update window status on hover. - * @param {Element=} opt_container If specified, location to insert link. If no - * container is specified, the old link is removed and replaced. - * @return {Element} The link element. - * @protected - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.createLinkHelper = function( - linkId, linkText, isAnchor, opt_container) { - var link = this.dom_.createDom( - isAnchor ? goog.dom.TagName.A : goog.dom.TagName.SPAN, - {className: goog.editor.plugins.AbstractBubblePlugin.LINK_CLASSNAME_}, - linkText); - if (this.keyboardNavigationEnabled_) { - this.setTabbable(link); - } - link.setAttribute('role', 'link'); - this.setupLink(link, linkId, opt_container); - goog.editor.style.makeUnselectable(link, this.eventRegister); - return link; -}; - - -/** - * Makes the given element tabbable. - * - *

    Elements created by createLink[Helper] are tabbable even without - * calling this method. Call it for other elements if needed. - * - *

    If tabindex is not already set in the element, this function sets it to 0. - * You'll usually want to also call {@code enableKeyboardNavigation(true)}. - * - * @param {!Element} element - * @protected - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.setTabbable = - function(element) { - if (!element.hasAttribute('tabindex')) { - element.setAttribute('tabindex', 0); - } - goog.dom.classlist.add(element, - goog.editor.plugins.AbstractBubblePlugin.TABBABLE_CLASSNAME_); -}; - - -/** - * Inserts a link in the given container if it is specified or removes - * the old link with this id and replaces it with the new link - * @param {Element} link Html element to insert. - * @param {string} linkId Id of the link. - * @param {Element=} opt_container If specified, location to insert link. - * @protected - */ -goog.editor.plugins.AbstractBubblePlugin.prototype.setupLink = function( - link, linkId, opt_container) { - if (opt_container) { - opt_container.appendChild(link); - } else { - var oldLink = this.dom_.getElement(linkId); - if (oldLink) { - goog.dom.replaceNode(link, oldLink); - } - } - - link.id = linkId; -}; diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/abstractbubbleplugin_test.html b/src/database/third_party/closure-library/closure/goog/editor/plugins/abstractbubbleplugin_test.html deleted file mode 100644 index 80e552ca604..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/abstractbubbleplugin_test.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - Closure Unit Tests - goog.editor.plugins.AbstractBubblePlugin - - - - - - -

    -
    - - diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/abstractbubbleplugin_test.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/abstractbubbleplugin_test.js deleted file mode 100644 index 3073be40978..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/abstractbubbleplugin_test.js +++ /dev/null @@ -1,436 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.editor.plugins.AbstractBubblePluginTest'); -goog.setTestOnly('goog.editor.plugins.AbstractBubblePluginTest'); - -goog.require('goog.dom'); -goog.require('goog.editor.plugins.AbstractBubblePlugin'); -goog.require('goog.events.BrowserEvent'); -goog.require('goog.events.EventType'); -goog.require('goog.events.KeyCodes'); -goog.require('goog.functions'); -goog.require('goog.style'); -goog.require('goog.testing.editor.FieldMock'); -goog.require('goog.testing.editor.TestHelper'); -goog.require('goog.testing.events'); -goog.require('goog.testing.events.Event'); -goog.require('goog.testing.jsunit'); -goog.require('goog.ui.editor.Bubble'); -goog.require('goog.userAgent'); - -var testHelper; -var fieldDiv; -var COMMAND = 'base'; -var fieldMock; -var bubblePlugin; -var link; -var link2; - -function setUpPage() { - fieldDiv = goog.dom.getElement('field'); - var viewportSize = goog.dom.getViewportSize(); - // Some tests depends on enough size of viewport. - if (viewportSize.width < 600 || viewportSize.height < 440) { - window.moveTo(0, 0); - window.resizeTo(640, 480); - } -} - -function setUp() { - testHelper = new goog.testing.editor.TestHelper(fieldDiv); - testHelper.setUpEditableElement(); - fieldMock = new goog.testing.editor.FieldMock(); - - bubblePlugin = new goog.editor.plugins.AbstractBubblePlugin(COMMAND); - bubblePlugin.fieldObject = fieldMock; - - fieldDiv.innerHTML = 'Google' + - 'Google2'; - link = fieldDiv.firstChild; - link2 = fieldDiv.lastChild; - - window.scrollTo(0, 0); - goog.style.setStyle(document.body, 'direction', 'ltr'); - goog.style.setStyle(document.getElementById('field'), 'position', 'static'); -} - -function tearDown() { - bubblePlugin.closeBubble(); - testHelper.tearDownEditableElement(); -} - - -/** - * This is a helper function for setting up the targetElement with a - * given direction. - * - * @param {string} dir The direction of the targetElement, 'ltr' or 'rtl'. - */ -function prepareTargetWithGivenDirection(dir) { - goog.style.setStyle(document.body, 'direction', dir); - - fieldDiv.style.direction = dir; - fieldDiv.innerHTML = 'Google'; - link = fieldDiv.firstChild; - - fieldMock.$replay(); - bubblePlugin.createBubbleContents = function(bubbleContainer) { - bubbleContainer.innerHTML = '
    B
    '; - goog.style.setStyle(bubbleContainer, 'border', '1px solid white'); - }; - bubblePlugin.registerFieldObject(fieldMock); - bubblePlugin.enable(fieldMock); - bubblePlugin.createBubble(link); -} - - -/** - * Similar in intent to mock reset, but implemented by recreating the mock - * variable. $reset() can't work because it will reset general any-time - * expectations done in the fieldMock constructor. - */ -function resetFieldMock() { - fieldMock = new goog.testing.editor.FieldMock(); - bubblePlugin.fieldObject = fieldMock; -} - -function helpTestCreateBubble(opt_fn) { - fieldMock.$replay(); - var numCalled = 0; - bubblePlugin.createBubbleContents = function(bubbleContainer) { - numCalled++; - assertNotNull('bubbleContainer should not be null', bubbleContainer); - }; - if (opt_fn) { - opt_fn(); - } - bubblePlugin.createBubble(link); - assertEquals('createBubbleContents should be called', 1, numCalled); - fieldMock.$verify(); -} - -function testCreateBubble(opt_fn) { - helpTestCreateBubble(opt_fn); - assertTrue(bubblePlugin.getSharedBubble_() instanceof goog.ui.editor.Bubble); - - assertTrue('Bubble should be visible', bubblePlugin.isVisible()); -} - -function testOpeningBubbleCallsOnShow() { - var numCalled = 0; - testCreateBubble(function() { - bubblePlugin.onShow = function() { - numCalled++; - }; - }); - - assertEquals('onShow should be called', 1, numCalled); - fieldMock.$verify(); -} - -function testCloseBubble() { - testCreateBubble(); - - bubblePlugin.closeBubble(); - assertFalse('Bubble should not be visible', bubblePlugin.isVisible()); - fieldMock.$verify(); -} - -function testZindexBehavior() { - // Don't use the default return values. - fieldMock.$reset(); - fieldMock.getAppWindow().$anyTimes().$returns(window); - fieldMock.getEditableDomHelper().$anyTimes() - .$returns(goog.dom.getDomHelper(document)); - fieldMock.getBaseZindex().$returns(2); - bubblePlugin.createBubbleContents = goog.nullFunction; - fieldMock.$replay(); - - bubblePlugin.createBubble(link); - assertEquals('2', - '' + bubblePlugin.getSharedBubble_().bubbleContainer_.style.zIndex); - - fieldMock.$verify(); -} - -function testNoTwoBubblesOpenAtSameTime() { - fieldMock.$replay(); - var origClose = goog.bind(bubblePlugin.closeBubble, bubblePlugin); - var numTimesCloseCalled = 0; - bubblePlugin.closeBubble = function() { - numTimesCloseCalled++; - origClose(); - }; - bubblePlugin.getBubbleTargetFromSelection = goog.functions.identity; - bubblePlugin.createBubbleContents = goog.nullFunction; - - bubblePlugin.handleSelectionChangeInternal(link); - assertEquals(0, numTimesCloseCalled); - assertEquals(link, bubblePlugin.targetElement_); - fieldMock.$verify(); - - bubblePlugin.handleSelectionChangeInternal(link2); - assertEquals(1, numTimesCloseCalled); - assertEquals(link2, bubblePlugin.targetElement_); - fieldMock.$verify(); -} - -function testHandleSelectionChangeWithEvent() { - fieldMock.$replay(); - var fakeEvent = - new goog.events.BrowserEvent({type: 'mouseup', target: link}); - bubblePlugin.getBubbleTargetFromSelection = goog.functions.identity; - bubblePlugin.createBubbleContents = goog.nullFunction; - bubblePlugin.handleSelectionChange(fakeEvent); - assertTrue('Bubble should have been opened', bubblePlugin.isVisible()); - assertEquals('Bubble target should be provided event\'s target', - link, bubblePlugin.targetElement_); -} - -function testHandleSelectionChangeWithTarget() { - fieldMock.$replay(); - bubblePlugin.getBubbleTargetFromSelection = goog.functions.identity; - bubblePlugin.createBubbleContents = goog.nullFunction; - bubblePlugin.handleSelectionChange(undefined, link2); - assertTrue('Bubble should have been opened', bubblePlugin.isVisible()); - assertEquals('Bubble target should be provided target', - link2, bubblePlugin.targetElement_); -} - - -/** - * Regression test for @bug 2945341 - */ -function testSelectOneTextCharacterNoError() { - fieldMock.$replay(); - bubblePlugin.getBubbleTargetFromSelection = goog.functions.identity; - bubblePlugin.createBubbleContents = goog.nullFunction; - // Select first char of first link's text node. - testHelper.select(link.firstChild, 0, link.firstChild, 1); - // This should execute without js errors. - bubblePlugin.handleSelectionChange(); - assertTrue('Bubble should have been opened', bubblePlugin.isVisible()); - fieldMock.$verify(); -} - -function testTabKeyEvents() { - fieldMock.$replay(); - bubblePlugin.enableKeyboardNavigation(true); - bubblePlugin.getBubbleTargetFromSelection = goog.functions.identity; - var nonTabbable1, tabbable1, tabbable2, nonTabbable2; - bubblePlugin.createBubbleContents = function(container) { - nonTabbable1 = goog.dom.createDom('div'); - tabbable1 = goog.dom.createDom('div'); - tabbable2 = goog.dom.createDom('div'); - nonTabbable2 = goog.dom.createDom('div'); - goog.dom.append( - container, nonTabbable1, tabbable1, tabbable2, nonTabbable2); - bubblePlugin.setTabbable(tabbable1); - bubblePlugin.setTabbable(tabbable2); - }; - bubblePlugin.handleSelectionChangeInternal(link); - assertTrue('Bubble should be visible', bubblePlugin.isVisible()); - - var tabHandledByBubble = simulateTabKeyOnBubble(); - assertTrue('The action should be handled by the plugin', tabHandledByBubble); - assertFocused(tabbable1); - - // Tab on the first tabbable. The test framework doesn't easily let us verify - // the desired behavior - namely, that the second tabbable gets focused - but - // we verify that the field doesn't get the focus. - goog.testing.events.fireKeySequence(tabbable1, goog.events.KeyCodes.TAB); - - fieldMock.$verify(); - - // Tabbing on the last tabbable should trigger focus() of the target field. - resetFieldMock(); - fieldMock.focus(); - fieldMock.$replay(); - goog.testing.events.fireKeySequence(tabbable2, goog.events.KeyCodes.TAB); - fieldMock.$verify(); -} - -function testTabKeyEventsWithShiftKey() { - fieldMock.$replay(); - bubblePlugin.enableKeyboardNavigation(true); - bubblePlugin.getBubbleTargetFromSelection = goog.functions.identity; - var nonTabbable, tabbable1, tabbable2; - bubblePlugin.createBubbleContents = function(container) { - nonTabbable = goog.dom.createDom('div'); - tabbable1 = goog.dom.createDom('div'); - // The test acts only on one tabbable, but we give another one to make sure - // that the tabbable we act on is not also the last. - tabbable2 = goog.dom.createDom('div'); - goog.dom.append(container, nonTabbable, tabbable1, tabbable2); - bubblePlugin.setTabbable(tabbable1); - bubblePlugin.setTabbable(tabbable2); - }; - bubblePlugin.handleSelectionChangeInternal(link); - - assertTrue('Bubble should be visible', bubblePlugin.isVisible()); - - var tabHandledByBubble = simulateTabKeyOnBubble(); - assertTrue('The action should be handled by the plugin', tabHandledByBubble); - assertFocused(tabbable1); - fieldMock.$verify(); - - // Shift-tabbing on the first tabbable should trigger focus() of the target - // field. - resetFieldMock(); - fieldMock.focus(); - fieldMock.$replay(); - goog.testing.events.fireKeySequence( - tabbable1, goog.events.KeyCodes.TAB, {shiftKey: true}); - fieldMock.$verify(); -} - -function testLinksAreTabbable() { - fieldMock.$replay(); - bubblePlugin.enableKeyboardNavigation(true); - bubblePlugin.getBubbleTargetFromSelection = goog.functions.identity; - var nonTabbable1, link1, link2, nonTabbable2; - bubblePlugin.createBubbleContents = function(container) { - nonTabbable1 = goog.dom.createDom('div'); - goog.dom.appendChild(container, nonTabbable1); - bubbleLink1 = this.createLink('linkInBubble1', 'Foo', false, container); - bubbleLink2 = this.createLink('linkInBubble2', 'Bar', false, container); - nonTabbable2 = goog.dom.createDom('div'); - goog.dom.appendChild(container, nonTabbable2); - }; - bubblePlugin.handleSelectionChangeInternal(link); - assertTrue('Bubble should be visible', bubblePlugin.isVisible()); - - var tabHandledByBubble = simulateTabKeyOnBubble(); - assertTrue('The action should be handled by the plugin', tabHandledByBubble); - assertFocused(bubbleLink1); - - fieldMock.$verify(); - - // Tabbing on the last link should trigger focus() of the target field. - resetFieldMock(); - fieldMock.focus(); - fieldMock.$replay(); - goog.testing.events.fireKeySequence(bubbleLink2, goog.events.KeyCodes.TAB); - fieldMock.$verify(); -} - -function testTabKeyNoEffectKeyboardNavDisabled() { - fieldMock.$replay(); - bubblePlugin.getBubbleTargetFromSelection = goog.functions.identity; - var bubbleLink; - bubblePlugin.createBubbleContents = function(container) { - bubbleLink = this.createLink('linkInBubble', 'Foo', false, container); - }; - bubblePlugin.handleSelectionChangeInternal(link); - - assertTrue('Bubble should be visible', bubblePlugin.isVisible()); - - var tabHandledByBubble = simulateTabKeyOnBubble(); - assertFalse('The action should not be handled by the plugin', - tabHandledByBubble); - assertNotFocused(bubbleLink); - - // Verify that tabbing the link doesn't cause focus of the field. - goog.testing.events.fireKeySequence(bubbleLink, goog.events.KeyCodes.TAB); - - fieldMock.$verify(); -} - -function testOtherKeyEventNoEffectKeyboardNavEnabled() { - fieldMock.$replay(); - bubblePlugin.enableKeyboardNavigation(true); - bubblePlugin.getBubbleTargetFromSelection = goog.functions.identity; - var bubbleLink; - bubblePlugin.createBubbleContents = function(container) { - bubbleLink = this.createLink('linkInBubble', 'Foo', false, container); - }; - bubblePlugin.handleSelectionChangeInternal(link); - - assertTrue('Bubble should be visible', bubblePlugin.isVisible()); - - // Test pressing CTRL + B: this should not have any effect. - var keyHandledByBubble = - simulateKeyDownOnBubble(goog.events.KeyCodes.B, true); - - assertFalse('The action should not be handled by the plugin', - keyHandledByBubble); - assertNotFocused(bubbleLink); - - fieldMock.$verify(); -} - -function testSetTabbableSetsTabIndex() { - var element1 = goog.dom.createDom('div'); - var element2 = goog.dom.createDom('div'); - element1.setAttribute('tabIndex', '1'); - - bubblePlugin.setTabbable(element1); - bubblePlugin.setTabbable(element2); - - assertEquals('1', element1.getAttribute('tabIndex')); - assertEquals('0', element2.getAttribute('tabIndex')); -} - -function testDisable() { - testCreateBubble(); - fieldMock.setUneditable(true); - bubblePlugin.disable(fieldMock); - bubblePlugin.closeBubble(); -} - - -/** - * Sends a tab key event to the bubble. - * @return {boolean} whether the bubble hanlded the event. - */ -function simulateTabKeyOnBubble() { - return simulateKeyDownOnBubble(goog.events.KeyCodes.TAB, false); -} - - -/** - * Sends a key event to the bubble. - * @param {number} keyCode - * @param {boolean} isCtrl - * @return {boolean} whether the bubble hanlded the event. - */ -function simulateKeyDownOnBubble(keyCode, isCtrl) { - // In some browsers (e.g. FireFox) the editable field is marked with - // designMode on. In the test setting (and not in production setting), the - // bubble element shares the same window and hence the designMode. In this - // mode, activeElement remains the and isn't changed along with the - // focus as a result of tab key. - bubblePlugin.getSharedBubble_().getContentElement(). - ownerDocument.designMode = 'off'; - - var event = - new goog.testing.events.Event(goog.events.EventType.KEYDOWN, null); - event.keyCode = keyCode; - event.ctrlKey = isCtrl; - return bubblePlugin.handleKeyDown(event); -} - -function assertFocused(element) { - // The activeElement assertion below doesn't work in IE7. At this time IE7 is - // no longer supported by any client product, so we don't care. - if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher(8)) { - return; - } - assertEquals('unexpected focus', element, document.activeElement); -} - -function assertNotFocused(element) { - assertNotEquals('unexpected focus', element, document.activeElement); -} diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/abstractdialogplugin.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/abstractdialogplugin.js deleted file mode 100644 index 278277ee385..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/abstractdialogplugin.js +++ /dev/null @@ -1,333 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview An abstract superclass for TrogEdit dialog plugins. Each - * Trogedit dialog has its own plugin. - * - * @author nicksantos@google.com (Nick Santos) - */ - -goog.provide('goog.editor.plugins.AbstractDialogPlugin'); -goog.provide('goog.editor.plugins.AbstractDialogPlugin.EventType'); - -goog.require('goog.dom'); -goog.require('goog.dom.Range'); -goog.require('goog.editor.Field'); -goog.require('goog.editor.Plugin'); -goog.require('goog.editor.range'); -goog.require('goog.events'); -goog.require('goog.ui.editor.AbstractDialog'); - - -// *** Public interface ***************************************************** // - - - -/** - * An abstract superclass for a Trogedit plugin that creates exactly one - * dialog. By default dialogs are not reused -- each time execCommand is called, - * a new instance of the dialog object is created (and the old one disposed of). - * To enable reusing of the dialog object, subclasses should call - * setReuseDialog() after calling the superclass constructor. - * @param {string} command The command that this plugin handles. - * @constructor - * @extends {goog.editor.Plugin} - */ -goog.editor.plugins.AbstractDialogPlugin = function(command) { - goog.editor.Plugin.call(this); - this.command_ = command; -}; -goog.inherits(goog.editor.plugins.AbstractDialogPlugin, goog.editor.Plugin); - - -/** @override */ -goog.editor.plugins.AbstractDialogPlugin.prototype.isSupportedCommand = - function(command) { - return command == this.command_; -}; - - -/** - * Handles execCommand. Dialog plugins don't make any changes when they open a - * dialog, just when the dialog closes (because only modal dialogs are - * supported). Hence this method does not dispatch the change events that the - * superclass method does. - * @param {string} command The command to execute. - * @param {...*} var_args Any additional parameters needed to - * execute the command. - * @return {*} The result of the execCommand, if any. - * @override - */ -goog.editor.plugins.AbstractDialogPlugin.prototype.execCommand = function( - command, var_args) { - return this.execCommandInternal.apply(this, arguments); -}; - - -// *** Events *************************************************************** // - - -/** - * Event type constants for events the dialog plugins fire. - * @enum {string} - */ -goog.editor.plugins.AbstractDialogPlugin.EventType = { - // This event is fired when a dialog has been opened. - OPENED: 'dialogOpened', - // This event is fired when a dialog has been closed. - CLOSED: 'dialogClosed' -}; - - -// *** Protected interface ************************************************** // - - -/** - * Creates a new instance of this plugin's dialog. Must be overridden by - * subclasses. - * @param {!goog.dom.DomHelper} dialogDomHelper The dom helper to be used to - * create the dialog. - * @param {*=} opt_arg The dialog specific argument. Concrete subclasses should - * declare a specific type. - * @return {goog.ui.editor.AbstractDialog} The newly created dialog. - * @protected - */ -goog.editor.plugins.AbstractDialogPlugin.prototype.createDialog = - goog.abstractMethod; - - -/** - * Returns the current dialog that was created and opened by this plugin. - * @return {goog.ui.editor.AbstractDialog} The current dialog that was created - * and opened by this plugin. - * @protected - */ -goog.editor.plugins.AbstractDialogPlugin.prototype.getDialog = function() { - return this.dialog_; -}; - - -/** - * Sets whether this plugin should reuse the same instance of the dialog each - * time execCommand is called or create a new one. This is intended for use by - * subclasses only, hence protected. - * @param {boolean} reuse Whether to reuse the dialog. - * @protected - */ -goog.editor.plugins.AbstractDialogPlugin.prototype.setReuseDialog = - function(reuse) { - this.reuseDialog_ = reuse; -}; - - -/** - * Handles execCommand by opening the dialog. Dispatches - * {@link goog.editor.plugins.AbstractDialogPlugin.EventType.OPENED} after the - * dialog is shown. - * @param {string} command The command to execute. - * @param {*=} opt_arg The dialog specific argument. Should be the same as - * {@link createDialog}. - * @return {*} Always returns true, indicating the dialog was shown. - * @protected - * @override - */ -goog.editor.plugins.AbstractDialogPlugin.prototype.execCommandInternal = - function(command, opt_arg) { - // If this plugin should not reuse dialog instances, first dispose of the - // previous dialog. - if (!this.reuseDialog_) { - this.disposeDialog_(); - } - // If there is no dialog yet (or we aren't reusing the previous one), create - // one. - if (!this.dialog_) { - this.dialog_ = this.createDialog( - // TODO(user): Add Field.getAppDomHelper. (Note dom helper will - // need to be updated if setAppWindow is called by clients.) - goog.dom.getDomHelper(this.getFieldObject().getAppWindow()), - opt_arg); - } - - // Since we're opening a dialog, we need to clear the selection because the - // focus will be going to the dialog, and if we leave an selection in the - // editor while another selection is active in the dialog as the user is - // typing, some browsers will screw up the original selection. But first we - // save it so we can restore it when the dialog closes. - // getRange may return null if there is no selection in the field. - var tempRange = this.getFieldObject().getRange(); - // saveUsingDom() did not work as well as saveUsingNormalizedCarets(), - // not sure why. - this.savedRange_ = tempRange && goog.editor.range.saveUsingNormalizedCarets( - tempRange); - goog.dom.Range.clearSelection( - this.getFieldObject().getEditableDomHelper().getWindow()); - - // Listen for the dialog closing so we can clean up. - goog.events.listenOnce(this.dialog_, - goog.ui.editor.AbstractDialog.EventType.AFTER_HIDE, - this.handleAfterHide, - false, - this); - - this.getFieldObject().setModalMode(true); - this.dialog_.show(); - this.dispatchEvent(goog.editor.plugins.AbstractDialogPlugin.EventType.OPENED); - - // Since the selection has left the document, dispatch a selection - // change event. - this.getFieldObject().dispatchSelectionChangeEvent(); - - return true; -}; - - -/** - * Cleans up after the dialog has closed, including restoring the selection to - * what it was before the dialog was opened. If a subclass modifies the editable - * field's content such that the original selection is no longer valid (usually - * the case when the user clicks OK, and sometimes also on Cancel), it is that - * subclass' responsibility to place the selection in the desired place during - * the OK or Cancel (or other) handler. In that case, this method will leave the - * selection in place. - * @param {goog.events.Event} e The AFTER_HIDE event object. - * @protected - */ -goog.editor.plugins.AbstractDialogPlugin.prototype.handleAfterHide = function( - e) { - this.getFieldObject().setModalMode(false); - this.restoreOriginalSelection(); - - if (!this.reuseDialog_) { - this.disposeDialog_(); - } - - this.dispatchEvent(goog.editor.plugins.AbstractDialogPlugin.EventType.CLOSED); - - // Since the selection has returned to the document, dispatch a selection - // change event. - this.getFieldObject().dispatchSelectionChangeEvent(); - - // When the dialog closes due to pressing enter or escape, that happens on the - // keydown event. But the browser will still fire a keyup event after that, - // which is caught by the editable field and causes it to try to fire a - // selection change event. To avoid that, we "debounce" the selection change - // event, meaning the editable field will not fire that event if the keyup - // that caused it immediately after this dialog was hidden ("immediately" - // means a small number of milliseconds defined by the editable field). - this.getFieldObject().debounceEvent( - goog.editor.Field.EventType.SELECTIONCHANGE); -}; - - -/** - * Restores the selection in the editable field to what it was before the dialog - * was opened. This is not guaranteed to work if the contents of the field - * have changed. - * @protected - */ -goog.editor.plugins.AbstractDialogPlugin.prototype.restoreOriginalSelection = - function() { - this.getFieldObject().restoreSavedRange(this.savedRange_); - this.savedRange_ = null; -}; - - -/** - * Cleans up the structure used to save the original selection before the dialog - * was opened. Should be used by subclasses that don't restore the original - * selection via restoreOriginalSelection. - * @protected - */ -goog.editor.plugins.AbstractDialogPlugin.prototype.disposeOriginalSelection = - function() { - if (this.savedRange_) { - this.savedRange_.dispose(); - this.savedRange_ = null; - } -}; - - -/** @override */ -goog.editor.plugins.AbstractDialogPlugin.prototype.disposeInternal = - function() { - this.disposeDialog_(); - goog.editor.plugins.AbstractDialogPlugin.base(this, 'disposeInternal'); -}; - - -// *** Private implementation *********************************************** // - - -/** - * The command that this plugin handles. - * @type {string} - * @private - */ -goog.editor.plugins.AbstractDialogPlugin.prototype.command_; - - -/** - * The current dialog that was created and opened by this plugin. - * @type {goog.ui.editor.AbstractDialog} - * @private - */ -goog.editor.plugins.AbstractDialogPlugin.prototype.dialog_; - - -/** - * Whether this plugin should reuse the same instance of the dialog each time - * execCommand is called or create a new one. - * @type {boolean} - * @private - */ -goog.editor.plugins.AbstractDialogPlugin.prototype.reuseDialog_ = false; - - -/** - * Mutex to prevent recursive calls to disposeDialog_. - * @type {boolean} - * @private - */ -goog.editor.plugins.AbstractDialogPlugin.prototype.isDisposingDialog_ = false; - - -/** - * SavedRange representing the selection before the dialog was opened. - * @type {goog.dom.SavedRange} - * @private - */ -goog.editor.plugins.AbstractDialogPlugin.prototype.savedRange_; - - -/** - * Disposes of the dialog if needed. It is this abstract class' responsibility - * to dispose of the dialog. The "if needed" refers to the fact this method - * might be called twice (nested calls, not sequential) in the dispose flow, so - * if the dialog was already disposed once it should not be disposed again. - * @private - */ -goog.editor.plugins.AbstractDialogPlugin.prototype.disposeDialog_ = function() { - // Wrap disposing the dialog in a mutex. Otherwise disposing it would cause it - // to get hidden (if it is still open) and fire AFTER_HIDE, which in - // turn would cause the dialog to be disposed again (closure only flags an - // object as disposed after the dispose call chain completes, so it doesn't - // prevent recursive dispose calls). - if (this.dialog_ && !this.isDisposingDialog_) { - this.isDisposingDialog_ = true; - this.dialog_.dispose(); - this.dialog_ = null; - this.isDisposingDialog_ = false; - } -}; diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/abstractdialogplugin_test.html b/src/database/third_party/closure-library/closure/goog/editor/plugins/abstractdialogplugin_test.html deleted file mode 100644 index ef1415fc14f..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/abstractdialogplugin_test.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - Closure Unit Tests - goog.editor.plugins.AbstractDialogPlugin - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/abstractdialogplugin_test.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/abstractdialogplugin_test.js deleted file mode 100644 index 5bc4f339273..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/abstractdialogplugin_test.js +++ /dev/null @@ -1,403 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.editor.plugins.AbstractDialogPluginTest'); -goog.setTestOnly('goog.editor.plugins.AbstractDialogPluginTest'); - -goog.require('goog.dom.SavedRange'); -goog.require('goog.editor.Field'); -goog.require('goog.editor.plugins.AbstractDialogPlugin'); -goog.require('goog.events.Event'); -goog.require('goog.events.EventHandler'); -goog.require('goog.functions'); -goog.require('goog.testing.MockClock'); -goog.require('goog.testing.MockControl'); -goog.require('goog.testing.PropertyReplacer'); -goog.require('goog.testing.editor.FieldMock'); -goog.require('goog.testing.editor.TestHelper'); -goog.require('goog.testing.events'); -goog.require('goog.testing.jsunit'); -goog.require('goog.testing.mockmatchers.ArgumentMatcher'); -goog.require('goog.ui.editor.AbstractDialog'); -goog.require('goog.userAgent'); - -var plugin; -var mockCtrl; -var mockField; -var mockSavedRange; -var mockOpenedHandler; -var mockClosedHandler; - -var COMMAND = 'myCommand'; -var stubs = new goog.testing.PropertyReplacer(); - -var mockClock; -var fieldObj; -var fieldElem; -var mockHandler; - -function setUp() { - mockCtrl = new goog.testing.MockControl(); - mockOpenedHandler = mockCtrl.createLooseMock(goog.events.EventHandler); - mockClosedHandler = mockCtrl.createLooseMock(goog.events.EventHandler); - - mockField = new goog.testing.editor.FieldMock(undefined, undefined, {}); - mockCtrl.addMock(mockField); - mockField.focus(); - - plugin = createDialogPlugin(); -} - -function setUpMockRange() { - mockSavedRange = mockCtrl.createLooseMock(goog.dom.SavedRange); - mockSavedRange.restore(); - - stubs.setPath('goog.editor.range.saveUsingNormalizedCarets', - goog.functions.constant(mockSavedRange)); -} - -function tearDown() { - stubs.reset(); - tearDownRealEditableField(); - if (mockClock) { - // Crucial to letting time operations work normally in the rest of tests. - mockClock.dispose(); - } - if (plugin) { - mockField.$setIgnoreUnexpectedCalls(true); - plugin.dispose(); - } -} - - -/** - * Creates a concrete instance of goog.ui.editor.AbstractDialog by adding - * a plain implementation of createDialogControl(). - * @param {goog.dom.DomHelper} dialogDomHelper The dom helper to be used to - * create the dialog. - * @return {goog.ui.editor.AbstractDialog} The created dialog. - */ -function createDialog(domHelper) { - var dialog = new goog.ui.editor.AbstractDialog(domHelper); - dialog.createDialogControl = function() { - return new goog.ui.editor.AbstractDialog.Builder(dialog).build(); - }; - return dialog; -} - - -/** - * Creates a concrete instance of the abstract class - * goog.editor.plugins.AbstractDialogPlugin - * and registers it with the mock editable field being used. - * @return {goog.editor.plugins.AbstractDialogPlugin} The created plugin. - */ -function createDialogPlugin() { - var plugin = new goog.editor.plugins.AbstractDialogPlugin(COMMAND); - plugin.createDialog = createDialog; - plugin.returnControlToEditableField = plugin.restoreOriginalSelection; - plugin.registerFieldObject(mockField); - plugin.addEventListener( - goog.editor.plugins.AbstractDialogPlugin.EventType.OPENED, - mockOpenedHandler); - plugin.addEventListener( - goog.editor.plugins.AbstractDialogPlugin.EventType.CLOSED, - mockClosedHandler); - return plugin; -} - - -/** - * Sets up the mock event handler to expect an OPENED event. - */ -function expectOpened(opt_times) { - mockOpenedHandler.handleEvent(new goog.testing.mockmatchers.ArgumentMatcher( - function(arg) { - return arg.type == - goog.editor.plugins.AbstractDialogPlugin.EventType.OPENED; - })); - mockField.dispatchSelectionChangeEvent(); - if (opt_times) { - mockOpenedHandler.$times(opt_times); - mockField.$times(opt_times); - } -} - - -/** - * Sets up the mock event handler to expect a CLOSED event. - */ -function expectClosed(opt_times) { - mockClosedHandler.handleEvent(new goog.testing.mockmatchers.ArgumentMatcher( - function(arg) { - return arg.type == - goog.editor.plugins.AbstractDialogPlugin.EventType.CLOSED; - })); - mockField.dispatchSelectionChangeEvent(); - if (opt_times) { - mockClosedHandler.$times(opt_times); - mockField.$times(opt_times); - } -} - - -/** - * Tests the simple flow of calling execCommand (which opens the - * dialog) and immediately disposing of the plugin (which closes the dialog). - * @param {boolean=} opt_reuse Whether to set the plugin to reuse its dialog. - */ -function testExecAndDispose(opt_reuse) { - setUpMockRange(); - expectOpened(); - expectClosed(); - mockField.debounceEvent(goog.editor.Field.EventType.SELECTIONCHANGE); - mockCtrl.$replayAll(); - if (opt_reuse) { - plugin.setReuseDialog(true); - } - assertFalse('Dialog should not be open yet', - !!plugin.getDialog() && plugin.getDialog().isOpen()); - - plugin.execCommand(COMMAND); - assertTrue('Dialog should be open now', - !!plugin.getDialog() && plugin.getDialog().isOpen()); - - var tempDialog = plugin.getDialog(); - plugin.dispose(); - assertFalse('Dialog should not still be open after disposal', - tempDialog.isOpen()); - mockCtrl.$verifyAll(); -} - - -/** - * Tests execCommand and dispose while reusing the dialog. - */ -function testExecAndDisposeReuse() { - testExecAndDispose(true); -} - - -/** - * Tests the flow of calling execCommand (which opens the dialog) and - * then hiding it (simulating that a user did somthing to cause the dialog to - * close). - * @param {boolean} reuse Whether to set the plugin to reuse its dialog. - */ -function testExecAndHide(opt_reuse) { - setUpMockRange(); - expectOpened(); - expectClosed(); - mockField.debounceEvent(goog.editor.Field.EventType.SELECTIONCHANGE); - mockCtrl.$replayAll(); - if (opt_reuse) { - plugin.setReuseDialog(true); - } - assertFalse('Dialog should not be open yet', - !!plugin.getDialog() && plugin.getDialog().isOpen()); - - plugin.execCommand(COMMAND); - assertTrue('Dialog should be open now', - !!plugin.getDialog() && plugin.getDialog().isOpen()); - - var tempDialog = plugin.getDialog(); - plugin.getDialog().hide(); - assertFalse('Dialog should not still be open after hiding', - tempDialog.isOpen()); - if (opt_reuse) { - assertFalse('Dialog should not be disposed after hiding (will be reused)', - tempDialog.isDisposed()); - } else { - assertTrue('Dialog should be disposed after hiding', - tempDialog.isDisposed()); - } - plugin.dispose(); - mockCtrl.$verifyAll(); -} - - -/** - * Tests execCommand and hide while reusing the dialog. - */ -function testExecAndHideReuse() { - testExecAndHide(true); -} - - -/** - * Tests the flow of calling execCommand (which opens a dialog) and - * then calling it again before the first dialog is closed. This is not - * something anyone should be doing since dialogs are (usually?) modal so the - * user can't do another execCommand before closing the first dialog. But - * since the API makes it possible, I thought it would be good to guard - * against and unit test. - * @param {boolean} reuse Whether to set the plugin to reuse its dialog. - */ -function testExecTwice(opt_reuse) { - setUpMockRange(); - if (opt_reuse) { - expectOpened(2); // The second exec should cause a second OPENED event. - // But the dialog was not closed between exec calls, so only one CLOSED is - // expected. - expectClosed(); - plugin.setReuseDialog(true); - mockField.debounceEvent(goog.editor.Field.EventType.SELECTIONCHANGE); - } else { - expectOpened(2); // The second exec should cause a second OPENED event. - // The first dialog will be disposed so there should be two CLOSED events. - expectClosed(2); - mockSavedRange.restore(); // Expected 2x, once already recorded in setup. - mockField.focus(); // Expected 2x, once already recorded in setup. - mockField.debounceEvent(goog.editor.Field.EventType.SELECTIONCHANGE); - mockField.$times(2); - } - mockCtrl.$replayAll(); - - assertFalse('Dialog should not be open yet', - !!plugin.getDialog() && plugin.getDialog().isOpen()); - - plugin.execCommand(COMMAND); - assertTrue('Dialog should be open now', - !!plugin.getDialog() && plugin.getDialog().isOpen()); - - var tempDialog = plugin.getDialog(); - plugin.execCommand(COMMAND); - if (opt_reuse) { - assertTrue('Reused dialog should still be open after second exec', - tempDialog.isOpen()); - assertFalse('Reused dialog should not be disposed after second exec', - tempDialog.isDisposed()); - } else { - assertFalse('First dialog should not still be open after opening second', - tempDialog.isOpen()); - assertTrue('First dialog should be disposed after opening second', - tempDialog.isDisposed()); - } - plugin.dispose(); - mockCtrl.$verifyAll(); -} - - -/** - * Tests execCommand twice while reusing the dialog. - */ -function testExecTwiceReuse() { - // Test is failing with an out-of-memory error in IE7. - if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('8')) { - return; - } - - testExecTwice(true); -} - - -/** - * Tests that the selection is cleared when the dialog opens and is - * correctly restored after it closes. - */ -function testRestoreSelection() { - setUpRealEditableField(); - - fieldObj.setHtml(false, '12345'); - var elem = fieldObj.getElement(); - var helper = new goog.testing.editor.TestHelper(elem); - helper.select('12345', 1, '12345', 4); // Selects '234'. - - assertEquals('Incorrect text selected before dialog is opened', - '234', - fieldObj.getRange().getText()); - plugin.execCommand(COMMAND); - if (!goog.userAgent.IE && !goog.userAgent.OPERA) { - // IE returns some bogus range when field doesn't have selection. - // Opera can't remove the selection from a whitebox field. - assertNull('There should be no selection while dialog is open', - fieldObj.getRange()); - } - plugin.getDialog().hide(); - assertEquals('Incorrect text selected after dialog is closed', - '234', - fieldObj.getRange().getText()); -} - - -/** - * Setup a real editable field (instead of a mock) and register the plugin to - * it. - */ -function setUpRealEditableField() { - fieldElem = document.createElement('div'); - fieldElem.id = 'myField'; - document.body.appendChild(fieldElem); - fieldObj = new goog.editor.Field('myField', document); - fieldObj.makeEditable(); - // Register the plugin to that field. - plugin.getTrogClassId = goog.functions.constant('myClassId'); - fieldObj.registerPlugin(plugin); -} - - -/** - * Tear down the real editable field. - */ -function tearDownRealEditableField() { - if (fieldObj) { - fieldObj.makeUneditable(); - fieldObj.dispose(); - fieldObj = null; - } - if (fieldElem && fieldElem.parentNode == document.body) { - document.body.removeChild(fieldElem); - } -} - - -/** - * Tests that after the dialog is hidden via a keystroke, the editable field - * doesn't fire an extra SELECTIONCHANGE event due to the keyup from that - * keystroke. - * There is also a robot test in dialog_robot.html to test debouncing the - * SELECTIONCHANGE event when the dialog closes. - */ -function testDebounceSelectionChange() { - mockClock = new goog.testing.MockClock(true); - // Initial time is 0 which evaluates to false in debouncing implementation. - mockClock.tick(1); - - setUpRealEditableField(); - - // Set up a mock event handler to make sure selection change isn't fired - // more than once on close and a second time on close. - var count = 0; - fieldObj.addEventListener(goog.editor.Field.EventType.SELECTIONCHANGE, - function(e) { - count++; - }); - - assertEquals(0, count); - plugin.execCommand(COMMAND); - assertEquals(1, count); - plugin.getDialog().hide(); - assertEquals(2, count); - - // Fake the keyup event firing on the field after the dialog closes. - var e = new goog.events.Event('keyup', plugin.fieldObject.getElement()); - e.keyCode = 13; - goog.testing.events.fireBrowserEvent(e); - - // Tick the mock clock so that selection change tries to fire. - mockClock.tick(goog.editor.Field.SELECTION_CHANGE_FREQUENCY_ + 1); - - // Ensure the handler did not fire again. - assertEquals(2, count); -} diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/abstracttabhandler.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/abstracttabhandler.js deleted file mode 100644 index de1a13ad8b9..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/abstracttabhandler.js +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Abstract Editor plugin class to handle tab keys. Has one - * abstract method which should be overriden to handle a tab key press. - * - * @author robbyw@google.com (Robby Walker) - */ - -goog.provide('goog.editor.plugins.AbstractTabHandler'); - -goog.require('goog.editor.Plugin'); -goog.require('goog.events.KeyCodes'); -goog.require('goog.userAgent'); - - - -/** - * Plugin to handle tab keys. Specific tab behavior defined by subclasses. - * - * @constructor - * @extends {goog.editor.Plugin} - */ -goog.editor.plugins.AbstractTabHandler = function() { - goog.editor.Plugin.call(this); -}; -goog.inherits(goog.editor.plugins.AbstractTabHandler, goog.editor.Plugin); - - -/** @override */ -goog.editor.plugins.AbstractTabHandler.prototype.getTrogClassId = - goog.abstractMethod; - - -/** @override */ -goog.editor.plugins.AbstractTabHandler.prototype.handleKeyboardShortcut = - function(e, key, isModifierPressed) { - // If a dialog doesn't have selectable field, Moz grabs the event and - // performs actions in editor window. This solves that problem and allows - // the event to be passed on to proper handlers. - if (goog.userAgent.GECKO && this.getFieldObject().inModalMode()) { - return false; - } - - // Don't handle Ctrl+Tab since the user is most likely trying to switch - // browser tabs. See bug 1305086. - // FF3 on Mac sends Ctrl-Tab to trogedit and we end up inserting a tab, but - // then it also switches the tabs. See bug 1511681. Note that we don't use - // isModifierPressed here since isModifierPressed is true only if metaKey - // is true on Mac. - if (e.keyCode == goog.events.KeyCodes.TAB && !e.metaKey && !e.ctrlKey) { - return this.handleTabKey(e); - } - - return false; -}; - - -/** - * Handle a tab key press. - * @param {goog.events.Event} e The key event. - * @return {boolean} Whether this event was handled by this plugin. - * @protected - */ -goog.editor.plugins.AbstractTabHandler.prototype.handleTabKey = - goog.abstractMethod; diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/abstracttabhandler_test.html b/src/database/third_party/closure-library/closure/goog/editor/plugins/abstracttabhandler_test.html deleted file mode 100644 index c6cb94050b0..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/abstracttabhandler_test.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - Closure Unit Tests - goog.editor.plugins.AbstractTabHandler - - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/abstracttabhandler_test.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/abstracttabhandler_test.js deleted file mode 100644 index a02469f3586..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/abstracttabhandler_test.js +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.editor.plugins.AbstractTabHandlerTest'); -goog.setTestOnly('goog.editor.plugins.AbstractTabHandlerTest'); - -goog.require('goog.editor.Field'); -goog.require('goog.editor.plugins.AbstractTabHandler'); -goog.require('goog.events.BrowserEvent'); -goog.require('goog.events.KeyCodes'); -goog.require('goog.testing.StrictMock'); -goog.require('goog.testing.editor.FieldMock'); -goog.require('goog.testing.jsunit'); -goog.require('goog.userAgent'); - -var tabHandler; -var editableField; -var handleTabKeyCalled = false; - -function setUp() { - editableField = new goog.testing.editor.FieldMock(); - editableField.inModalMode = goog.editor.Field.prototype.inModalMode; - editableField.setModalMode = goog.editor.Field.prototype.setModalMode; - - tabHandler = new goog.editor.plugins.AbstractTabHandler(); - tabHandler.registerFieldObject(editableField); - tabHandler.handleTabKey = function(e) { - handleTabKeyCalled = true; - return true; - }; -} - -function tearDown() { - tabHandler.dispose(); -} - -function testHandleKey() { - var event = new goog.testing.StrictMock(goog.events.BrowserEvent); - event.keyCode = goog.events.KeyCodes.TAB; - event.ctrlKey = false; - event.metaKey = false; - - assertTrue('Event must be handled when no modifier keys are pressed.', - tabHandler.handleKeyboardShortcut(event, '', false)); - assertTrue(handleTabKeyCalled); - handleTabKeyCalled = false; - - editableField.setModalMode(true); - if (goog.userAgent.GECKO) { - assertFalse('Event must not be handled when in modal mode', - tabHandler.handleKeyboardShortcut(event, '', false)); - assertFalse(handleTabKeyCalled); - } else { - assertTrue('Event must be handled when in modal mode', - tabHandler.handleKeyboardShortcut(event, '', false)); - assertTrue(handleTabKeyCalled); - handleTabKeyCalled = false; - } - - event.ctrlKey = true; - assertFalse('Plugin must never handle tab key press when ctrlKey is pressed.', - tabHandler.handleKeyboardShortcut(event, '', false)); - assertFalse(handleTabKeyCalled); - - event.ctrlKey = false; - event.metaKey = true; - assertFalse('Plugin must never handle tab key press when metaKey is pressed.', - tabHandler.handleKeyboardShortcut(event, '', false)); - assertFalse(handleTabKeyCalled); -} diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/basictextformatter.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/basictextformatter.js deleted file mode 100644 index c19a660a39c..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/basictextformatter.js +++ /dev/null @@ -1,1769 +0,0 @@ -// Copyright 2006 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Functions to style text. - * - * @author nicksantos@google.com (Nick Santos) - */ - -goog.provide('goog.editor.plugins.BasicTextFormatter'); -goog.provide('goog.editor.plugins.BasicTextFormatter.COMMAND'); - -goog.require('goog.array'); -goog.require('goog.dom'); -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.Range'); -goog.require('goog.dom.TagName'); -goog.require('goog.editor.BrowserFeature'); -goog.require('goog.editor.Command'); -goog.require('goog.editor.Link'); -goog.require('goog.editor.Plugin'); -goog.require('goog.editor.node'); -goog.require('goog.editor.range'); -goog.require('goog.editor.style'); -goog.require('goog.iter'); -goog.require('goog.iter.StopIteration'); -goog.require('goog.log'); -goog.require('goog.object'); -goog.require('goog.string'); -goog.require('goog.string.Unicode'); -goog.require('goog.style'); -goog.require('goog.ui.editor.messages'); -goog.require('goog.userAgent'); - - - -/** - * Functions to style text (e.g. underline, make bold, etc.) - * @constructor - * @extends {goog.editor.Plugin} - */ -goog.editor.plugins.BasicTextFormatter = function() { - goog.editor.Plugin.call(this); -}; -goog.inherits(goog.editor.plugins.BasicTextFormatter, goog.editor.Plugin); - - -/** @override */ -goog.editor.plugins.BasicTextFormatter.prototype.getTrogClassId = function() { - return 'BTF'; -}; - - -/** - * Logging object. - * @type {goog.log.Logger} - * @protected - * @override - */ -goog.editor.plugins.BasicTextFormatter.prototype.logger = - goog.log.getLogger('goog.editor.plugins.BasicTextFormatter'); - - -/** - * Commands implemented by this plugin. - * @enum {string} - */ -goog.editor.plugins.BasicTextFormatter.COMMAND = { - LINK: '+link', - FORMAT_BLOCK: '+formatBlock', - INDENT: '+indent', - OUTDENT: '+outdent', - STRIKE_THROUGH: '+strikeThrough', - HORIZONTAL_RULE: '+insertHorizontalRule', - SUBSCRIPT: '+subscript', - SUPERSCRIPT: '+superscript', - UNDERLINE: '+underline', - BOLD: '+bold', - ITALIC: '+italic', - FONT_SIZE: '+fontSize', - FONT_FACE: '+fontName', - FONT_COLOR: '+foreColor', - BACKGROUND_COLOR: '+backColor', - ORDERED_LIST: '+insertOrderedList', - UNORDERED_LIST: '+insertUnorderedList', - JUSTIFY_CENTER: '+justifyCenter', - JUSTIFY_FULL: '+justifyFull', - JUSTIFY_RIGHT: '+justifyRight', - JUSTIFY_LEFT: '+justifyLeft' -}; - - -/** - * Inverse map of execCommand strings to - * {@link goog.editor.plugins.BasicTextFormatter.COMMAND} constants. Used to - * determine whether a string corresponds to a command this plugin - * handles in O(1) time. - * @type {Object} - * @private - */ -goog.editor.plugins.BasicTextFormatter.SUPPORTED_COMMANDS_ = - goog.object.transpose(goog.editor.plugins.BasicTextFormatter.COMMAND); - - -/** - * Whether the string corresponds to a command this plugin handles. - * @param {string} command Command string to check. - * @return {boolean} Whether the string corresponds to a command - * this plugin handles. - * @override - */ -goog.editor.plugins.BasicTextFormatter.prototype.isSupportedCommand = function( - command) { - // TODO(user): restore this to simple check once table editing - // is moved out into its own plugin - return command in goog.editor.plugins.BasicTextFormatter.SUPPORTED_COMMANDS_; -}; - - -/** - * @return {goog.dom.AbstractRange} The closure range object that wraps the - * current user selection. - * @private - */ -goog.editor.plugins.BasicTextFormatter.prototype.getRange_ = function() { - return this.getFieldObject().getRange(); -}; - - -/** - * @return {!Document} The document object associated with the currently active - * field. - * @private - */ -goog.editor.plugins.BasicTextFormatter.prototype.getDocument_ = function() { - return this.getFieldDomHelper().getDocument(); -}; - - -/** - * Execute a user-initiated command. - * @param {string} command Command to execute. - * @param {...*} var_args For color commands, this - * should be the hex color (with the #). For FORMAT_BLOCK, this should be - * the goog.editor.plugins.BasicTextFormatter.BLOCK_COMMAND. - * It will be unused for other commands. - * @return {Object|undefined} The result of the command. - * @override - */ -goog.editor.plugins.BasicTextFormatter.prototype.execCommandInternal = function( - command, var_args) { - var preserveDir, styleWithCss, needsFormatBlockDiv, hasDummySelection; - var result; - var opt_arg = arguments[1]; - - switch (command) { - case goog.editor.plugins.BasicTextFormatter.COMMAND.BACKGROUND_COLOR: - // Don't bother for no color selected, color picker is resetting itself. - if (!goog.isNull(opt_arg)) { - if (goog.editor.BrowserFeature.EATS_EMPTY_BACKGROUND_COLOR) { - this.applyBgColorManually_(opt_arg); - } else if (goog.userAgent.OPERA) { - // backColor will color the block level element instead of - // the selected span of text in Opera. - this.execCommandHelper_('hiliteColor', opt_arg); - } else { - this.execCommandHelper_(command, opt_arg); - } - } - break; - - case goog.editor.plugins.BasicTextFormatter.COMMAND.LINK: - result = this.toggleLink_(opt_arg); - break; - - case goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_CENTER: - case goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_FULL: - case goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_RIGHT: - case goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_LEFT: - this.justify_(command); - break; - - default: - if (goog.userAgent.IE && - command == - goog.editor.plugins.BasicTextFormatter.COMMAND.FORMAT_BLOCK && - opt_arg) { - // IE requires that the argument be in the form of an opening - // tag, like

    , including angle brackets. WebKit will accept - // the arguemnt with or without brackets, and Firefox pre-3 supports - // only a fixed subset of tags with brackets, and prefers without. - // So we only add them IE only. - opt_arg = '<' + opt_arg + '>'; - } - - if (command == - goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_COLOR && - goog.isNull(opt_arg)) { - // If we don't have a color, then FONT_COLOR is a no-op. - break; - } - - switch (command) { - case goog.editor.plugins.BasicTextFormatter.COMMAND.INDENT: - case goog.editor.plugins.BasicTextFormatter.COMMAND.OUTDENT: - if (goog.editor.BrowserFeature.HAS_STYLE_WITH_CSS) { - if (goog.userAgent.GECKO) { - styleWithCss = true; - } - if (goog.userAgent.OPERA) { - if (command == - goog.editor.plugins.BasicTextFormatter.COMMAND.OUTDENT) { - // styleWithCSS actually sets negative margins on
    - // to outdent them. If the command is enabled without - // styleWithCSS flipped on, then the caret is in a blockquote so - // styleWithCSS must not be used. But if the command is not - // enabled, styleWithCSS should be used so that elements such as - // a
    with a margin-left style can still be outdented. - // (Opera bug: CORE-21118) - styleWithCss = - !this.getDocument_().queryCommandEnabled('outdent'); - } else { - // Always use styleWithCSS for indenting. Otherwise, Opera will - // make separate
    s around *each* indented line, - // which adds big default
    margins between each - // indented line. - styleWithCss = true; - } - } - } - // Fall through. - - case goog.editor.plugins.BasicTextFormatter.COMMAND.ORDERED_LIST: - case goog.editor.plugins.BasicTextFormatter.COMMAND.UNORDERED_LIST: - if (goog.editor.BrowserFeature.LEAVES_P_WHEN_REMOVING_LISTS && - this.queryCommandStateInternal_(this.getDocument_(), - command)) { - // IE leaves behind P tags when unapplying lists. - // If we're not in P-mode, then we want divs - // So, unlistify, then convert the Ps into divs. - needsFormatBlockDiv = this.getFieldObject().queryCommandValue( - goog.editor.Command.DEFAULT_TAG) != goog.dom.TagName.P; - } else if (!goog.editor.BrowserFeature.CAN_LISTIFY_BR) { - // IE doesn't convert BRed line breaks into separate list items. - // So convert the BRs to divs, then do the listify. - this.convertBreaksToDivs_(); - } - - // This fix only works in Gecko. - if (goog.userAgent.GECKO && - goog.editor.BrowserFeature.FORGETS_FORMATTING_WHEN_LISTIFYING && - !this.queryCommandValue(command)) { - hasDummySelection |= this.beforeInsertListGecko_(); - } - // Fall through to preserveDir block - - case goog.editor.plugins.BasicTextFormatter.COMMAND.FORMAT_BLOCK: - // Both FF & IE may lose directionality info. Save/restore it. - // TODO(user): Does Safari also need this? - // TODO (gmark, jparent): This isn't ideal because it uses a string - // literal, so if the plugin name changes, it would break. We need a - // better solution. See also other places in code that use - // this.getPluginByClassId('Bidi'). - preserveDir = !!this.getFieldObject().getPluginByClassId('Bidi'); - break; - - case goog.editor.plugins.BasicTextFormatter.COMMAND.SUBSCRIPT: - case goog.editor.plugins.BasicTextFormatter.COMMAND.SUPERSCRIPT: - if (goog.editor.BrowserFeature.NESTS_SUBSCRIPT_SUPERSCRIPT) { - // This browser nests subscript and superscript when both are - // applied, instead of canceling out the first when applying the - // second. - this.applySubscriptSuperscriptWorkarounds_(command); - } - break; - - case goog.editor.plugins.BasicTextFormatter.COMMAND.UNDERLINE: - case goog.editor.plugins.BasicTextFormatter.COMMAND.BOLD: - case goog.editor.plugins.BasicTextFormatter.COMMAND.ITALIC: - // If we are applying the formatting, then we want to have - // styleWithCSS false so that we generate html tags (like ). If we - // are unformatting something, we want to have styleWithCSS true so - // that we can unformat both html tags and inline styling. - // TODO(user): What about WebKit and Opera? - styleWithCss = goog.userAgent.GECKO && - goog.editor.BrowserFeature.HAS_STYLE_WITH_CSS && - this.queryCommandValue(command); - break; - - case goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_COLOR: - case goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_FACE: - // It is very expensive in FF (order of magnitude difference) to use - // font tags instead of styled spans. Whenever possible, - // force FF to use spans. - // Font size is very expensive too, but FF always uses font tags, - // regardless of which styleWithCSS value you use. - styleWithCss = goog.editor.BrowserFeature.HAS_STYLE_WITH_CSS && - goog.userAgent.GECKO; - } - - /** - * Cases where we just use the default execCommand (in addition - * to the above fall-throughs) - * goog.editor.plugins.BasicTextFormatter.COMMAND.STRIKE_THROUGH: - * goog.editor.plugins.BasicTextFormatter.COMMAND.HORIZONTAL_RULE: - * goog.editor.plugins.BasicTextFormatter.COMMAND.SUBSCRIPT: - * goog.editor.plugins.BasicTextFormatter.COMMAND.SUPERSCRIPT: - * goog.editor.plugins.BasicTextFormatter.COMMAND.UNDERLINE: - * goog.editor.plugins.BasicTextFormatter.COMMAND.BOLD: - * goog.editor.plugins.BasicTextFormatter.COMMAND.ITALIC: - * goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_SIZE: - * goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_FACE: - */ - this.execCommandHelper_(command, opt_arg, preserveDir, !!styleWithCss); - - if (hasDummySelection) { - this.getDocument_().execCommand('Delete', false, true); - } - - if (needsFormatBlockDiv) { - this.getDocument_().execCommand('FormatBlock', false, '
    '); - } - } - // FF loses focus, so we have to set the focus back to the document or the - // user can't type after selecting from menu. In IE, focus is set correctly - // and resetting it here messes it up. - if (goog.userAgent.GECKO && !this.getFieldObject().inModalMode()) { - this.focusField_(); - } - return result; -}; - - -/** - * Focuses on the field. - * @private - */ -goog.editor.plugins.BasicTextFormatter.prototype.focusField_ = function() { - this.getFieldDomHelper().getWindow().focus(); -}; - - -/** - * Gets the command value. - * @param {string} command The command value to get. - * @return {string|boolean|null} The current value of the command in the given - * selection. NOTE: This return type list is not documented in MSDN or MDC - * and has been constructed from experience. Please update it - * if necessary. - * @override - */ -goog.editor.plugins.BasicTextFormatter.prototype.queryCommandValue = function( - command) { - var styleWithCss; - switch (command) { - case goog.editor.plugins.BasicTextFormatter.COMMAND.LINK: - return this.isNodeInState_(goog.dom.TagName.A); - - case goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_CENTER: - case goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_FULL: - case goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_RIGHT: - case goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_LEFT: - return this.isJustification_(command); - - case goog.editor.plugins.BasicTextFormatter.COMMAND.FORMAT_BLOCK: - // TODO(nicksantos): See if we can use queryCommandValue here. - return goog.editor.plugins.BasicTextFormatter.getSelectionBlockState_( - this.getFieldObject().getRange()); - - case goog.editor.plugins.BasicTextFormatter.COMMAND.INDENT: - case goog.editor.plugins.BasicTextFormatter.COMMAND.OUTDENT: - case goog.editor.plugins.BasicTextFormatter.COMMAND.HORIZONTAL_RULE: - // TODO: See if there are reasonable results to return for - // these commands. - return false; - - case goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_SIZE: - case goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_FACE: - case goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_COLOR: - case goog.editor.plugins.BasicTextFormatter.COMMAND.BACKGROUND_COLOR: - // We use queryCommandValue here since we don't just want to know if a - // color/fontface/fontsize is applied, we want to know WHICH one it is. - return this.queryCommandValueInternal_(this.getDocument_(), command, - goog.editor.BrowserFeature.HAS_STYLE_WITH_CSS && - goog.userAgent.GECKO); - - case goog.editor.plugins.BasicTextFormatter.COMMAND.UNDERLINE: - case goog.editor.plugins.BasicTextFormatter.COMMAND.BOLD: - case goog.editor.plugins.BasicTextFormatter.COMMAND.ITALIC: - styleWithCss = goog.editor.BrowserFeature.HAS_STYLE_WITH_CSS && - goog.userAgent.GECKO; - - default: - /** - * goog.editor.plugins.BasicTextFormatter.COMMAND.STRIKE_THROUGH - * goog.editor.plugins.BasicTextFormatter.COMMAND.SUBSCRIPT - * goog.editor.plugins.BasicTextFormatter.COMMAND.SUPERSCRIPT - * goog.editor.plugins.BasicTextFormatter.COMMAND.UNDERLINE - * goog.editor.plugins.BasicTextFormatter.COMMAND.BOLD - * goog.editor.plugins.BasicTextFormatter.COMMAND.ITALIC - * goog.editor.plugins.BasicTextFormatter.COMMAND.ORDERED_LIST - * goog.editor.plugins.BasicTextFormatter.COMMAND.UNORDERED_LIST - */ - // This only works for commands that use the default execCommand - return this.queryCommandStateInternal_(this.getDocument_(), command, - styleWithCss); - } -}; - - -/** - * @override - */ -goog.editor.plugins.BasicTextFormatter.prototype.prepareContentsHtml = - function(html) { - // If the browser collapses empty nodes and the field has only a script - // tag in it, then it will collapse this node. Which will mean the user - // can't click into it to edit it. - if (goog.editor.BrowserFeature.COLLAPSES_EMPTY_NODES && - html.match(/^\s* - - - - - - -
    -
      -
    • foo
    • -
        -
      • foo
      • -
      • bar
      • -
      • baz
      • -
      -
    • bar
    • -
    • baz
    • -
    - ... -
      -
    • foo
    • -
        -
      • foo
      • -
      • bar
      • -
      • baz
      • -
      -
        -
      • foo
      • -
      • bar
      • -
      • baz
      • -
      -
    • bar
    • -
    • baz
    • -
    - -
      -
    1. foo
    2. -
    3. bar
    4. -
    5. baz
    6. -
    - -
    -
      -
    1. switch
    2. -
    3. list
    4. -
    5. type
    6. -
    -
    - -

    before Foo. Bar, baz. after

    -

    before

    Foo.

    Bar,

    baz.

    after

    - -
    lorem
    ipsum
    dolor
    - -

    test

    - - - - - - - - - - -
    head1head2
    one two
    three four
    five
    - - -
    - -
    - -
    - - diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/basictextformatter_test.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/basictextformatter_test.js deleted file mode 100644 index c00a029b90e..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/basictextformatter_test.js +++ /dev/null @@ -1,1212 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.editor.plugins.BasicTextFormatterTest'); -goog.setTestOnly('goog.editor.plugins.BasicTextFormatterTest'); - -goog.require('goog.dom'); -goog.require('goog.dom.Range'); -goog.require('goog.dom.TagName'); -goog.require('goog.editor.BrowserFeature'); -goog.require('goog.editor.Command'); -goog.require('goog.editor.Field'); -goog.require('goog.editor.Plugin'); -goog.require('goog.editor.plugins.BasicTextFormatter'); -goog.require('goog.object'); -goog.require('goog.style'); -goog.require('goog.testing.ExpectedFailures'); -goog.require('goog.testing.LooseMock'); -goog.require('goog.testing.PropertyReplacer'); -goog.require('goog.testing.editor.FieldMock'); -goog.require('goog.testing.editor.TestHelper'); -goog.require('goog.testing.jsunit'); -goog.require('goog.testing.mockmatchers'); -goog.require('goog.userAgent'); - -var stubs; - -var SAVED_HTML; -var FIELDMOCK; -var FORMATTER; -var ROOT; -var HELPER; -var OPEN_SUB; -var CLOSE_SUB; -var OPEN_SUPER; -var CLOSE_SUPER; -var MOCK_BLOCKQUOTE_STYLE = 'border-left: 1px solid gray;'; -var MOCK_GET_BLOCKQUOTE_STYLES = function() { - return MOCK_BLOCKQUOTE_STYLE; -}; - -var REAL_FIELD; -var REAL_PLUGIN; - -var expectedFailures; - -function setUpPage() { - stubs = new goog.testing.PropertyReplacer(); - SAVED_HTML = goog.dom.getElement('html').innerHTML; - FIELDMOCK; - FORMATTER; - ROOT = goog.dom.getElement('root'); - HELPER; - OPEN_SUB = - goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher('530') ? - '' : - ''; - CLOSE_SUB = - goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher('530') ? - '' : ''; - OPEN_SUPER = - goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher('530') ? - '' : - ''; - CLOSE_SUPER = - goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher('530') ? - '' : ''; - expectedFailures = new goog.testing.ExpectedFailures(); -} - -function setUp() { - FIELDMOCK = new goog.testing.editor.FieldMock(); - - FORMATTER = new goog.editor.plugins.BasicTextFormatter(); - FORMATTER.fieldObject = FIELDMOCK; -} - -function setUpRealField() { - REAL_FIELD = new goog.editor.Field('real-field'); - REAL_PLUGIN = new goog.editor.plugins.BasicTextFormatter(); - REAL_FIELD.registerPlugin(REAL_PLUGIN); - REAL_FIELD.makeEditable(); -} - -function setUpRealFieldIframe() { - REAL_FIELD = new goog.editor.Field('iframe'); - FORMATTER = new goog.editor.plugins.BasicTextFormatter(); - REAL_FIELD.registerPlugin(FORMATTER); - REAL_FIELD.makeEditable(); -} - -function selectRealField() { - goog.dom.Range.createFromNodeContents(REAL_FIELD.getElement()).select(); - REAL_FIELD.dispatchSelectionChangeEvent(); -} - -function tearDown() { - tearDownFontSizeTests(); - - if (REAL_FIELD) { - REAL_FIELD.makeUneditable(); - REAL_FIELD.dispose(); - REAL_FIELD = null; - } - - expectedFailures.handleTearDown(); - stubs.reset(); - - goog.dom.getElement('html').innerHTML = SAVED_HTML; -} - -function setUpListAndBlockquoteTests() { - var htmlDiv = document.getElementById('html'); - HELPER = new goog.testing.editor.TestHelper(htmlDiv); - HELPER.setUpEditableElement(); - - FIELDMOCK.getElement(); - FIELDMOCK.$anyTimes(); - FIELDMOCK.$returns(htmlDiv); -} - -function tearDownHelper() { - HELPER.tearDownEditableElement(); - HELPER.dispose(); - HELPER = null; -} - -function tearDownListAndBlockquoteTests() { - tearDownHelper(); -} - -function testIEList() { - if (goog.userAgent.IE) { - setUpListAndBlockquoteTests(); - - FIELDMOCK.queryCommandValue('rtl').$returns(null); - - FIELDMOCK.$replay(); - var ul = goog.dom.getElement('outerUL'); - goog.dom.Range.createFromNodeContents( - goog.dom.getFirstElementChild(ul).firstChild).select(); - FORMATTER.fixIELists_(); - assertFalse('Unordered list must not have ordered type', ul.type == '1'); - var ol = goog.dom.getElement('ol'); - ol.type = 'disc'; - goog.dom.Range.createFromNodeContents( - goog.dom.getFirstElementChild(ul).firstChild).select(); - FORMATTER.fixIELists_(); - assertFalse('Ordered list must not have unordered type', - ol.type == 'disc'); - ol.type = '1'; - goog.dom.Range.createFromNodeContents( - goog.dom.getFirstElementChild(ul).firstChild).select(); - FORMATTER.fixIELists_(); - assertTrue('Ordered list must retain ordered list type', - ol.type == '1'); - tearDownListAndBlockquoteTests(); - } -} - -function testWebKitList() { - if (goog.userAgent.WEBKIT) { - setUpListAndBlockquoteTests(); - - FIELDMOCK.queryCommandValue('rtl').$returns(null); - - FIELDMOCK.$replay(); - var ul = document.getElementById('outerUL'); - var html = ul.innerHTML; - goog.dom.Range.createFromNodeContents(ul).select(); - - FORMATTER.fixSafariLists_(); - assertEquals('Contents of UL shouldn\'t change', - html, ul.innerHTML); - - ul = document.getElementById('outerUL2'); - goog.dom.Range.createFromNodeContents(ul).select(); - - FORMATTER.fixSafariLists_(); - var childULs = ul.getElementsByTagName('ul'); - assertEquals('UL should have one child UL', - 1, childULs.length); - tearDownListAndBlockquoteTests(); - } -} - -function testGeckoListFont() { - if (goog.userAgent.GECKO) { - setUpListAndBlockquoteTests(); - FIELDMOCK.queryCommandValue( - goog.editor.Command.DEFAULT_TAG).$returns('BR').$times(2); - - FIELDMOCK.$replay(); - var p = goog.dom.getElement('geckolist'); - var font = p.firstChild; - goog.dom.Range.createFromNodeContents(font).select(); - retVal = FORMATTER.beforeInsertListGecko_(); - assertFalse('Workaround shouldn\'t be applied when not needed', retVal); - - font.innerHTML = ''; - goog.dom.Range.createFromNodeContents(font).select(); - var retVal = FORMATTER.beforeInsertListGecko_(); - assertTrue('Workaround should be applied when needed', retVal); - document.execCommand('insertorderedlist', false, true); - assertTrue('Font should be Courier', - /courier/i.test(document.queryCommandValue('fontname'))); - tearDownListAndBlockquoteTests(); - } -} - -function testSwitchListType() { - if (!goog.userAgent.WEBKIT) { - return; - } - // Test that we're not seeing https://bugs.webkit.org/show_bug.cgi?id=19539, - // the type of multi-item lists. - setUpListAndBlockquoteTests(); - - FIELDMOCK.$replay(); - var list = goog.dom.getElement('switchListType'); - var parent = goog.dom.getParentElement(list); - - goog.dom.Range.createFromNodeContents(list).select(); - FORMATTER.execCommandInternal('insertunorderedlist'); - list = goog.dom.getFirstElementChild(parent); - assertEquals(goog.dom.TagName.UL, list.tagName); - assertEquals(3, goog.dom.getElementsByTagNameAndClass( - goog.dom.TagName.LI, null, list).length); - - goog.dom.Range.createFromNodeContents(list).select(); - FORMATTER.execCommandInternal('insertorderedlist'); - list = goog.dom.getFirstElementChild(parent); - assertEquals(goog.dom.TagName.OL, list.tagName); - assertEquals(3, goog.dom.getElementsByTagNameAndClass( - goog.dom.TagName.LI, null, list).length); - - tearDownListAndBlockquoteTests(); -} - -function setUpSubSuperTests() { - ROOT.innerHTML = '12345'; - HELPER = new goog.testing.editor.TestHelper(ROOT); - HELPER.setUpEditableElement(); -} - -function tearDownSubSuperTests() { - tearDownHelper(); -} - -function testSubscriptRemovesSuperscript() { - setUpSubSuperTests(); - FIELDMOCK.$replay(); - - HELPER.select('12345', 1, '12345', 4); // Selects '234'. - FORMATTER.execCommandInternal( - goog.editor.plugins.BasicTextFormatter.COMMAND.SUPERSCRIPT); - HELPER.assertHtmlMatches('1' + OPEN_SUPER + '234' + CLOSE_SUPER + '5'); - FORMATTER.execCommandInternal( - goog.editor.plugins.BasicTextFormatter.COMMAND.SUBSCRIPT); - HELPER.assertHtmlMatches('1' + OPEN_SUB + '234' + CLOSE_SUB + '5'); - - FIELDMOCK.$verify(); - tearDownSubSuperTests(); -} - -function testSuperscriptRemovesSubscript() { - setUpSubSuperTests(); - FIELDMOCK.$replay(); - - HELPER.select('12345', 1, '12345', 4); // Selects '234'. - FORMATTER.execCommandInternal( - goog.editor.plugins.BasicTextFormatter.COMMAND.SUBSCRIPT); - HELPER.assertHtmlMatches('1' + OPEN_SUB + '234' + CLOSE_SUB + '5'); - FORMATTER.execCommandInternal( - goog.editor.plugins.BasicTextFormatter.COMMAND.SUPERSCRIPT); - HELPER.assertHtmlMatches('1' + OPEN_SUPER + '234' + CLOSE_SUPER + '5'); - - FIELDMOCK.$verify(); - tearDownSubSuperTests(); -} - -function testSubscriptRemovesSuperscriptIntersecting() { - // Tests: 12345 , sup(23) , sub(34) ==> 1+sup(2)+sub(34)+5 - // This is more complex because the sub and sup calls are made on separate - // fields which intersect each other and queryCommandValue seems to return - // false if the command is only applied to part of the field. - setUpSubSuperTests(); - FIELDMOCK.$replay(); - - HELPER.select('12345', 1, '12345', 3); // Selects '23'. - FORMATTER.execCommandInternal( - goog.editor.plugins.BasicTextFormatter.COMMAND.SUPERSCRIPT); - HELPER.assertHtmlMatches('1' + OPEN_SUPER + '23' + CLOSE_SUPER + '45'); - HELPER.select('23', 1, '45', 1); // Selects '34'. - FORMATTER.execCommandInternal( - goog.editor.plugins.BasicTextFormatter.COMMAND.SUBSCRIPT); - HELPER.assertHtmlMatches('1' + OPEN_SUPER + '2' + CLOSE_SUPER + - OPEN_SUB + '34' + CLOSE_SUB + '5'); - - FIELDMOCK.$verify(); - tearDownSubSuperTests(); -} - -function testSuperscriptRemovesSubscriptIntersecting() { - // Tests: 12345 , sub(23) , sup(34) ==> 1+sub(2)+sup(34)+5 - setUpSubSuperTests(); - FIELDMOCK.$replay(); - - HELPER.select('12345', 1, '12345', 3); // Selects '23'. - FORMATTER.execCommandInternal( - goog.editor.plugins.BasicTextFormatter.COMMAND.SUBSCRIPT); - HELPER.assertHtmlMatches('1' + OPEN_SUB + '23' + CLOSE_SUB + '45'); - HELPER.select('23', 1, '45', 1); // Selects '34'. - FORMATTER.execCommandInternal( - goog.editor.plugins.BasicTextFormatter.COMMAND.SUPERSCRIPT); - HELPER.assertHtmlMatches('1' + OPEN_SUB + '2' + CLOSE_SUB + - OPEN_SUPER + '34' + CLOSE_SUPER + '5'); - - FIELDMOCK.$verify(); - tearDownSubSuperTests(); -} - -function setUpLinkTests(text, url, isEditable) { - stubs.set(window, 'prompt', function() { - return url; - }); - - ROOT.innerHTML = text; - HELPER = new goog.testing.editor.TestHelper(ROOT); - if (isEditable) { - HELPER.setUpEditableElement(); - FIELDMOCK.execCommand(goog.editor.Command.MODAL_LINK_EDITOR, - goog.testing.mockmatchers.isObject).$returns(undefined); - FORMATTER.focusField_ = function() { - throw 'Field should not be re-focused'; - }; - } - - FIELDMOCK.getElement().$anyTimes().$returns(ROOT); - - FIELDMOCK.setModalMode(true); - - FIELDMOCK.isSelectionEditable().$anyTimes().$returns(isEditable); -} - -function tearDownLinkTests() { - tearDownHelper(); -} - -function testLink() { - setUpLinkTests('12345', 'http://www.x.com/', true); - FIELDMOCK.$replay(); - - HELPER.select('12345', 3); - FORMATTER.execCommandInternal(goog.editor.Command.LINK); - HELPER.assertHtmlMatches( - goog.editor.BrowserFeature.GETS_STUCK_IN_LINKS ? - '123http://www.x.com/ 45' : - '123http://www.x.com/45'); - - FIELDMOCK.$verify(); - tearDownLinkTests(); -} - -function testLinks() { - var url1 = 'http://google.com/1'; - var url2 = 'http://google.com/2'; - var dialogUrl = 'http://google.com/3'; - var html = '

    ' + url1 + '

    ' + url2 + '

    '; - setUpLinkTests(html, dialogUrl, true); - FIELDMOCK.$replay(); - - HELPER.select(url1, 0, url2, url2.length); - FORMATTER.execCommandInternal(goog.editor.Command.LINK); - HELPER.assertHtmlMatches('

    ' + url1 + '

    ' + - '' + (goog.userAgent.IE ? dialogUrl : url2) + - '

    '); -} - -function testSelectedLink() { - setUpLinkTests('12345', 'http://www.x.com/', true); - FIELDMOCK.$replay(); - - HELPER.select('12345', 1, '12345', 4); - FORMATTER.execCommandInternal(goog.editor.Command.LINK); - HELPER.assertHtmlMatches( - goog.editor.BrowserFeature.GETS_STUCK_IN_LINKS ? - '1234 5' : - '12345'); - - FIELDMOCK.$verify(); - tearDownLinkTests(); -} - -function testCanceledLink() { - setUpLinkTests('12345', undefined, true); - FIELDMOCK.$replay(); - - HELPER.select('12345', 1, '12345', 4); - FORMATTER.execCommandInternal(goog.editor.Command.LINK); - HELPER.assertHtmlMatches('12345'); - - assertEquals('234', FIELDMOCK.getRange().getText()); - - FIELDMOCK.$verify(); - tearDownLinkTests(); -} - -function testUnfocusedLink() { - FIELDMOCK.$reset(); - FIELDMOCK.getEditableDomHelper(). - $anyTimes(). - $returns(goog.dom.getDomHelper(window.document)); - setUpLinkTests('12345', undefined, false); - FIELDMOCK.getRange().$anyTimes().$returns(null); - FIELDMOCK.$replay(); - - FORMATTER.execCommandInternal(goog.editor.Command.LINK); - HELPER.assertHtmlMatches('12345'); - - FIELDMOCK.$verify(); - tearDownLinkTests(); -} - -function setUpJustifyTests(html) { - ROOT.innerHTML = html; - HELPER = new goog.testing.editor.TestHelper(ROOT); - HELPER.setUpEditableElement(ROOT); - - FIELDMOCK.getElement(); - FIELDMOCK.$anyTimes(); - FIELDMOCK.$returns(ROOT); - - FIELDMOCK.getElement(); - FIELDMOCK.$anyTimes(); - FIELDMOCK.$returns(ROOT); -} - -function tearDownJustifyTests() { - tearDownHelper(); -} - -function testJustify() { - setUpJustifyTests('
    abc

    def

    ghi
    '); - FIELDMOCK.$replay(); - - HELPER.select('abc', 1, 'def', 1); // Selects 'bcd'. - FORMATTER.execCommandInternal( - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_CENTER); - HELPER.assertHtmlMatches( - '
    abc
    ' + - '

    def

    ' + - '
    ghi
    '); - - FIELDMOCK.$verify(); - tearDownJustifyTests(); -} - -function testJustifyInInline() { - setUpJustifyTests('
    abc
    d
    '); - FIELDMOCK.$replay(); - - HELPER.select('b', 0, 'b', 1); // Selects 'b'. - FORMATTER.execCommandInternal( - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_CENTER); - HELPER.assertHtmlMatches( - '
    abc
    d
    '); - - FIELDMOCK.$verify(); - tearDownJustifyTests(); -} - -function testJustifyInBlock() { - setUpJustifyTests('
    a
    b
    c
    '); - FIELDMOCK.$replay(); - - HELPER.select('b', 0, 'b', 1); // Selects 'h'. - FORMATTER.execCommandInternal( - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_CENTER); - HELPER.assertHtmlMatches( - '
    a
    b
    c
    '); - - FIELDMOCK.$verify(); - tearDownJustifyTests(); -} - -var isFontSizeTest = false; -var defaultFontSizeMap; - -function setUpFontSizeTests() { - isFontSizeTest = true; - ROOT.innerHTML = '1234' + - '567'; - HELPER = new goog.testing.editor.TestHelper(ROOT); - HELPER.setUpEditableElement(); - FIELDMOCK.getElement().$returns(ROOT).$anyTimes(); - - // Map representing the sizes of the text in the HTML snippet used in these - // tests. The key is the exact text content of each text node, and the value - // is the initial size of the font in pixels. Since tests may cause a text - // node to be split in two, this also contains keys that initially don't - // match any text node, but may match one later if an existing node is - // split. The value for these keys is null, signifying no text node should - // exist with that content. - defaultFontSizeMap = { - '1': 16, - '2': null, - '23': 2, - '3': null, - '4': 16, - '5': null, - '56': 5, - '6': null, - '7': 16 - }; - assertFontSizes('Assertion failed on default font sizes!', {}); -} - -function tearDownFontSizeTests() { - if (isFontSizeTest) { - tearDownHelper(); - isFontSizeTest = false; - } -} - - -/** - * Asserts that the text nodes set up by setUpFontSizeTests() have had their - * font sizes changed as described by sizeChangesMap. - * @param {string} msg Assertion error message. - * @param {Object} sizeChangesMap Maps the text content - * of a text node to be measured to its expected font size in pixels, or - * null if that text node should not be present in the document (i.e. - * because it was split into two). Only the text nodes that have changed - * from their default need to be specified. - */ -function assertFontSizes(msg, sizeChangesMap) { - goog.object.extend(defaultFontSizeMap, sizeChangesMap); - for (var k in defaultFontSizeMap) { - var node = HELPER.findTextNode(k); - var expected = defaultFontSizeMap[k]; - if (expected) { - assertNotNull(msg + ' [couldn\'t find text node "' + k + '"]', node); - assertEquals(msg + ' [incorrect font size for "' + k + '"]', - expected, goog.style.getFontSize(node.parentNode)); - } else { - assertNull(msg + ' [unexpected text node "' + k + '"]', node); - } - } -} - - -/** - * Regression test for {@bug 1286408}. Tests that when you change the font - * size of a selection, any font size styles that were nested inside are - * removed. - */ -function testFontSizeOverridesStyleAttr() { - setUpFontSizeTests(); - FIELDMOCK.$replay(); - - HELPER.select('1', 0, '4', 1); // Selects 1234. - FORMATTER.execCommandInternal( - goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_SIZE, 6); - - assertFontSizes('New font size should override existing font size', - {'1': 32, '23': 32, '4': 32}); - - if (goog.editor.BrowserFeature.DOESNT_OVERRIDE_FONT_SIZE_IN_STYLE_ATTR) { - var span = HELPER.findTextNode('23').parentNode; - assertFalse('Style attribute should be gone', - span.getAttributeNode('style') != null && - span.getAttributeNode('style').specified); - } - - FIELDMOCK.$verify(); -} - - -/** - * Make sure the style stripping works when the selection starts and stops in - * different nodes that both contain font size styles. - */ -function testFontSizeOverridesStyleAttrMultiNode() { - setUpFontSizeTests(); - FIELDMOCK.$replay(); - - HELPER.select('23', 0, '56', 2); // Selects 23456. - FORMATTER.execCommandInternal( - goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_SIZE, 6); - var span = HELPER.findTextNode('23').parentNode; - var span2 = HELPER.findTextNode('56').parentNode; - - assertFontSizes( - 'New font size should override existing font size in all spans', - {'23': 32, '4': 32, '56': 32}); - var whiteSpace = goog.userAgent.IE ? - goog.style.getCascadedStyle(span2, 'whiteSpace') : - goog.style.getComputedStyle(span2, 'whiteSpace'); - assertEquals('Whitespace style in last span should have been left', - 'pre', whiteSpace); - - if (goog.editor.BrowserFeature.DOESNT_OVERRIDE_FONT_SIZE_IN_STYLE_ATTR) { - assertFalse('Style attribute should be gone from first span', - span.getAttributeNode('style') != null && - span.getAttributeNode('style').specified); - assertTrue('Style attribute should not be gone from last span', - span2.getAttributeNode('style') != null && - span2.getAttributeNode('style').specified); - } - - FIELDMOCK.$verify(); -} - - -/** - * Makes sure the font size style is not removed when only a part of the - * element with font size style is selected during the font size command. - */ -function testFontSizeDoesntOverrideStyleAttr() { - setUpFontSizeTests(); - FIELDMOCK.$replay(); - - HELPER.select('23', 1, '4', 1); // Selects 34 (half of span with font size). - FORMATTER.execCommandInternal( - goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_SIZE, 6); - - assertFontSizes( - 'New font size shouldn\'t override existing font size before selection', - {'2': 2, '23': null, '3': 32, '4': 32}); - - FIELDMOCK.$verify(); -} - - -/** - * Makes sure the font size style is not removed when only a part of the - * element with font size style is selected during the font size command, but - * is removed for another element that is fully selected. - */ -function testFontSizeDoesntOverrideStyleAttrMultiNode() { - setUpFontSizeTests(); - FIELDMOCK.$replay(); - - HELPER.select('23', 1, '56', 2); // Selects 3456. - FORMATTER.execCommandInternal( - goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_SIZE, 6); - - assertFontSizes( - 'New font size shouldn\'t override existing font size before ' + - 'selection, but still override existing font size in last span', - {'2': 2, '23': null, '3': 32, '4': 32, '56': 32}); - - FIELDMOCK.$verify(); -} - - -/** - * Helper to make sure the precondition that executing the font size command - * wraps the content in font tags instead of modifying the style attribute is - * maintained by the browser even if the selection is already text that is - * wrapped in a tag with a font size style. We test this with several - * permutations of how the selection looks: selecting the text in the text - * node, selecting the whole text node as a unit, or selecting the whole span - * node as a unit. Sometimes the browser wraps the text node with the font - * tag, sometimes it wraps the span with the font tag. Either one is ok as - * long as a font tag is actually being used instead of just modifying the - * span's style, because our fix for {@bug 1286408} would remove that style. - * @param {function} doSelect Function to select the "23" text in the test - * content. - */ -function doTestFontSizeStyledSpan(doSelect) { - // Make sure no new browsers start getting this bad behavior. If they do, - // this test will unexpectedly pass. - expectedFailures.expectFailureFor( - !goog.editor.BrowserFeature.DOESNT_OVERRIDE_FONT_SIZE_IN_STYLE_ATTR); - - try { - setUpFontSizeTests(); - FIELDMOCK.$replay(); - - doSelect(); - FORMATTER.execCommandInternal( - goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_SIZE, 7); - var parentNode = HELPER.findTextNode('23').parentNode; - var grandparentNode = parentNode.parentNode; - var fontNode = goog.dom.getElementsByTagNameAndClass(goog.dom.TagName.FONT, - undefined, ROOT)[0]; - var spanNode = goog.dom.getElementsByTagNameAndClass(goog.dom.TagName.SPAN, - undefined, ROOT)[0]; - assertTrue('A font tag should have been added either outside or inside' + - ' the existing span', - parentNode == spanNode && grandparentNode == fontNode || - parentNode == fontNode && grandparentNode == spanNode); - - FIELDMOCK.$verify(); - } catch (e) { - expectedFailures.handleException(e); - } -} - -function testFontSizeStyledSpanSelectingText() { - doTestFontSizeStyledSpan(function() { - HELPER.select('23', 0, '23', 2); - }); -} - -function testFontSizeStyledSpanSelectingTextNode() { - doTestFontSizeStyledSpan(function() { - var textNode = HELPER.findTextNode('23'); - HELPER.select(textNode.parentNode, 0, textNode.parentNode, 1); - }); -} - -function testFontSizeStyledSpanSelectingSpanNode() { - doTestFontSizeStyledSpan(function() { - var spanNode = HELPER.findTextNode('23').parentNode; - HELPER.select(spanNode.parentNode, 1, spanNode.parentNode, 2); - }); -} - -function setUpIframeField(content) { - var ifr = document.getElementById('iframe'); - var body = ifr.contentWindow.document.body; - body.innerHTML = content; - - HELPER = new goog.testing.editor.TestHelper(body); - HELPER.setUpEditableElement(); - FIELDMOCK = new goog.testing.editor.FieldMock(ifr.contentWindow); - FIELDMOCK.getElement(); - FIELDMOCK.$anyTimes(); - FIELDMOCK.$returns(body); - FIELDMOCK.queryCommandValue('rtl'); - FIELDMOCK.$anyTimes(); - FIELDMOCK.$returns(null); - FORMATTER.fieldObject = FIELDMOCK; -} - -function tearDownIframeField() { - tearDownHelper(); -} - -function setUpConvertBreaksToDivTests() { - ROOT.innerHTML = '

    paragraph

    one
    two


    three'; - HELPER = new goog.testing.editor.TestHelper(ROOT); - HELPER.setUpEditableElement(); - - FIELDMOCK.getElement(); - FIELDMOCK.$anyTimes(); - FIELDMOCK.$returns(ROOT); -} - -function tearDownConvertBreaksToDivTests() { - tearDownHelper(); -} - - -/** @bug 1414941 */ -function testConvertBreaksToDivsKeepsP() { - if (goog.editor.BrowserFeature.CAN_LISTIFY_BR) { - return; - } - setUpConvertBreaksToDivTests(); - FIELDMOCK.$replay(); - - HELPER.select('three', 0); - FORMATTER.convertBreaksToDivs_(); - assertEquals('There should still be a

    tag', - 1, FIELDMOCK.getElement().getElementsByTagName('p').length); - var html = FIELDMOCK.getElement().innerHTML.toLowerCase(); - assertNotBadBrElements(html); - assertNotContains('There should not be empty

    elements', - '
    <\/div>', html); - - FIELDMOCK.$verify(); - tearDownConvertBreaksToDivTests(); -} - - -/** -* @bug 1414937 -* @bug 934535 -*/ -function testConvertBreaksToDivsDoesntCollapseBR() { - if (goog.editor.BrowserFeature.CAN_LISTIFY_BR) { - return; - } - setUpConvertBreaksToDivTests(); - FIELDMOCK.$replay(); - - HELPER.select('three', 0); - FORMATTER.convertBreaksToDivs_(); - var html = FIELDMOCK.getElement().innerHTML.toLowerCase(); - assertNotBadBrElements(html); - assertNotContains('There should not be empty
    elements', - '
    <\/div>', html); - if (goog.userAgent.IE) { - //

    misbehaves in IE - assertNotContains( - '
    should not be used to prevent
    from collapsing', - '

    <\/div>', html); - } - - FIELDMOCK.$verify(); - tearDownConvertBreaksToDivTests(); -} - -function testConvertBreaksToDivsSelection() { - if (goog.editor.BrowserFeature.CAN_LISTIFY_BR) { - return; - } - setUpConvertBreaksToDivTests(); - FIELDMOCK.$replay(); - - HELPER.select('two', 1, 'three', 3); - var before = FIELDMOCK.getRange().getText().replace(/\s/g, ''); - FORMATTER.convertBreaksToDivs_(); - assertEquals('Selection must not be changed', - before, FIELDMOCK.getRange().getText().replace(/\s/g, '')); - - FIELDMOCK.$verify(); - tearDownConvertBreaksToDivTests(); -} - - -/** @bug 1414937 */ -function testConvertBreaksToDivsInsertList() { - setUpConvertBreaksToDivTests(); - FIELDMOCK.$replay(); - - HELPER.select('three', 0); - FORMATTER.execCommandInternal('insertorderedlist'); - assertTrue('Ordered list must be inserted', - FIELDMOCK.getEditableDomHelper().getDocument().queryCommandState( - 'insertorderedlist')); - tearDownConvertBreaksToDivTests(); -} - - -/** - * Regression test for {@bug 1939883}, where if a br has an id, it causes - * the convert br code to throw a js error. This goes a step further and - * ensures that the id is preserved in the resulting div element. - */ -function testConvertBreaksToDivsKeepsId() { - if (goog.editor.BrowserFeature.CAN_LISTIFY_BR) { - return; - } - setUpConvertBreaksToDivTests(); - FIELDMOCK.$replay(); - - HELPER.select('one', 0, 'two', 0); - FORMATTER.convertBreaksToDivs_(); - var html = FIELDMOCK.getElement().innerHTML.toLowerCase(); - assertNotBadBrElements(html); - var idBr = document.getElementById('br1'); - assertNotNull('There should still be a tag with id="br1"', idBr); - assertEquals('The tag with id="br1" should be a
    now', - goog.dom.TagName.DIV, - idBr.tagName); - assertNull('There should not be any tag with id="temp_br"', - document.getElementById('temp_br')); - - FIELDMOCK.$verify(); - tearDownConvertBreaksToDivTests(); -} - - -/** - * @bug 2420054 - */ -var JUSTIFICATION_COMMANDS = [ - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_LEFT, - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_RIGHT, - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_CENTER, - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_FULL -]; -function doTestIsJustification(command) { - setUpRealField(); - REAL_FIELD.setHtml(false, 'foo'); - selectRealField(); - REAL_FIELD.execCommand(command); - - for (var i = 0; i < JUSTIFICATION_COMMANDS.length; i++) { - if (JUSTIFICATION_COMMANDS[i] == command) { - assertTrue('queryCommandValue(' + JUSTIFICATION_COMMANDS[i] + - ') should be true after execCommand(' + command + ')', - REAL_FIELD.queryCommandValue(JUSTIFICATION_COMMANDS[i])); - } else { - assertFalse('queryCommandValue(' + JUSTIFICATION_COMMANDS[i] + - ') should be false after execCommand(' + command + ')', - REAL_FIELD.queryCommandValue(JUSTIFICATION_COMMANDS[i])); - } - } -} -function testIsJustificationLeft() { - doTestIsJustification( - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_LEFT); -} -function testIsJustificationRight() { - doTestIsJustification( - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_RIGHT); -} -function testIsJustificationCenter() { - doTestIsJustification( - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_CENTER); -} -function testIsJustificationFull() { - doTestIsJustification( - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_FULL); -} - - -/** - * Regression test for {@bug 1414813}, where all 3 justification buttons are - * considered "on" when you first tab into the editable field. In this - * situation, when lorem ipsum is the only node in the editable field iframe - * body, mockField.getRange() returns an empty range. - */ -function testIsJustificationEmptySelection() { - var mockField = new goog.testing.LooseMock(goog.editor.Field); - - mockField.getRange(); - mockField.$anyTimes(); - mockField.$returns(null); - mockField.getPluginByClassId('Bidi'); - mockField.$anyTimes(); - mockField.$returns(null); - FORMATTER.fieldObject = mockField; - - mockField.$replay(); - - assertFalse('Empty selection should not be justified', - FORMATTER.isJustification_( - goog.editor.plugins.BasicTextFormatter. - COMMAND.JUSTIFY_CENTER)); - assertFalse('Empty selection should not be justified', - FORMATTER.isJustification_( - goog.editor.plugins.BasicTextFormatter. - COMMAND.JUSTIFY_FULL)); - assertFalse('Empty selection should not be justified', - FORMATTER.isJustification_( - goog.editor.plugins.BasicTextFormatter. - COMMAND.JUSTIFY_RIGHT)); - assertFalse('Empty selection should not be justified', - FORMATTER.isJustification_( - goog.editor.plugins.BasicTextFormatter. - COMMAND.JUSTIFY_LEFT)); - - mockField.$verify(); -} - -function testIsJustificationSimple1() { - setUpRealField(); - REAL_FIELD.setHtml(false, '
    foo
    '); - selectRealField(); - - assertFalse(REAL_FIELD.queryCommandValue( - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_LEFT)); - assertTrue(REAL_FIELD.queryCommandValue( - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_RIGHT)); -} - -function testIsJustificationSimple2() { - setUpRealField(); - REAL_FIELD.setHtml(false, '
    foo
    '); - selectRealField(); - - assertFalse(REAL_FIELD.queryCommandValue( - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_LEFT)); - assertTrue(REAL_FIELD.queryCommandValue( - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_RIGHT)); -} - -function testIsJustificationComplete1() { - setUpRealField(); - REAL_FIELD.setHtml(false, - '
    a
    b
    '); - selectRealField(); - - assertFalse(REAL_FIELD.queryCommandValue( - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_LEFT)); - assertFalse(REAL_FIELD.queryCommandValue( - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_RIGHT)); -} - -function testIsJustificationComplete2() { - setUpRealField(); - REAL_FIELD.setHtml(false, - '
    a
    b
    '); - selectRealField(); - - assertTrue(REAL_FIELD.queryCommandValue( - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_LEFT)); - assertFalse(REAL_FIELD.queryCommandValue( - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_RIGHT)); -} - -function testIsJustificationComplete3() { - setUpRealField(); - REAL_FIELD.setHtml(false, - '
    a
    b
    '); - selectRealField(); - - assertFalse(REAL_FIELD.queryCommandValue( - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_LEFT)); - assertTrue(REAL_FIELD.queryCommandValue( - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_RIGHT)); -} - -function testIsJustificationComplete4() { - setUpRealField(); - REAL_FIELD.setHtml(false, - '
    a
    ' + - '
    b
    '); - selectRealField(); - - assertFalse(REAL_FIELD.queryCommandValue( - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_LEFT)); - assertTrue(REAL_FIELD.queryCommandValue( - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_RIGHT)); -} - -function testIsJustificationComplete5() { - setUpRealField(); - REAL_FIELD.setHtml(false, - '
    a
    b' + - '
    c
    '); - selectRealField(); - - assertFalse(REAL_FIELD.queryCommandValue( - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_LEFT)); - assertFalse(REAL_FIELD.queryCommandValue( - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_RIGHT)); -} - - -/** @bug 2472589 */ -function doTestIsJustificationPInDiv(useCss, align, command) { - setUpRealField(); - var html = '

    foo

    '; - - REAL_FIELD.setHtml(false, html); - selectRealField(); - assertTrue( - 'P inside ' + align + ' aligned' + (useCss ? ' (using CSS)' : '') + - ' DIV should be considered ' + align + ' aligned', - REAL_FIELD.queryCommandValue(command)); -} -function testIsJustificationPInDivLeft() { - doTestIsJustificationPInDiv(false, 'left', - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_LEFT); -} -function testIsJustificationPInDivRight() { - doTestIsJustificationPInDiv(false, 'right', - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_RIGHT); -} -function testIsJustificationPInDivCenter() { - doTestIsJustificationPInDiv(false, 'center', - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_CENTER); -} -function testIsJustificationPInDivJustify() { - doTestIsJustificationPInDiv(false, 'justify', - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_FULL); -} -function testIsJustificationPInDivLeftCss() { - doTestIsJustificationPInDiv(true, 'left', - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_LEFT); -} -function testIsJustificationPInDivRightCss() { - doTestIsJustificationPInDiv(true, 'right', - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_RIGHT); -} -function testIsJustificationPInDivCenterCss() { - doTestIsJustificationPInDiv(true, 'center', - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_CENTER); -} -function testIsJustificationPInDivJustifyCss() { - doTestIsJustificationPInDiv(true, 'justify', - goog.editor.plugins.BasicTextFormatter.COMMAND.JUSTIFY_FULL); -} - - -function testPrepareContent() { - setUpRealField(); - assertPreparedContents('\n', '\n'); - - if (goog.editor.BrowserFeature.COLLAPSES_EMPTY_NODES) { - assertPreparedContents("  - - - -
    -
    - - diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/blockquote_test.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/blockquote_test.js deleted file mode 100644 index 4fa12681ba1..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/blockquote_test.js +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2009 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.editor.plugins.BlockquoteTest'); -goog.setTestOnly('goog.editor.plugins.BlockquoteTest'); - -goog.require('goog.dom'); -goog.require('goog.dom.Range'); -goog.require('goog.dom.TagName'); -goog.require('goog.editor.BrowserFeature'); -goog.require('goog.editor.plugins.Blockquote'); -goog.require('goog.testing.editor.FieldMock'); -goog.require('goog.testing.editor.TestHelper'); -goog.require('goog.testing.jsunit'); - -var SPLIT = ''; -var root, helper, field, plugin; - -function setUp() { - root = goog.dom.getElement('root'); - helper = new goog.testing.editor.TestHelper(root); - field = new goog.testing.editor.FieldMock(); - - helper.setUpEditableElement(); -} - -function tearDown() { - field.$verify(); - helper.tearDownEditableElement(); -} - -function createPlugin(requireClassname, opt_paragraphMode) { - field.queryCommandValue('+defaultTag').$anyTimes().$returns( - opt_paragraphMode ? goog.dom.TagName.P : undefined); - - plugin = new goog.editor.plugins.Blockquote(requireClassname); - plugin.registerFieldObject(field); - plugin.enable(field); -} - -function execCommand() { - field.$replay(); - - // With splitPoint we try to mimic the behavior of EnterHandler's - // deleteCursorSelection_. - var splitPoint = goog.dom.getElement('split-point'); - var position = goog.editor.BrowserFeature.HAS_W3C_RANGES ? - {node: splitPoint.nextSibling, offset: 0} : splitPoint; - if (goog.editor.BrowserFeature.HAS_W3C_RANGES) { - goog.dom.removeNode(splitPoint); - goog.dom.Range.createCaret(position.node, 0).select(); - } else { - goog.dom.Range.createCaret(position, 0).select(); - } - - var result = plugin.execCommand(goog.editor.plugins.Blockquote.SPLIT_COMMAND, - position); - if (!goog.editor.BrowserFeature.HAS_W3C_RANGES) { - goog.dom.removeNode(splitPoint); - } - - return result; -} - -function testSplitBlockquoteDoesNothingWhenNotInBlockquote() { - root.innerHTML = '
    Test' + SPLIT + 'ing
    '; - - createPlugin(false); - assertFalse(execCommand()); - helper.assertHtmlMatches('
    Testing
    '); -} - -function testSplitBlockquoteDoesNothingWhenNotInBlockquoteWithClass() { - root.innerHTML = '
    Test' + SPLIT + 'ing
    '; - - createPlugin(true); - assertFalse(execCommand()); - helper.assertHtmlMatches('
    Testing
    '); -} - -function testSplitBlockquoteInBlockquoteWithoutClass() { - root.innerHTML = '
    Test' + SPLIT + 'ing
    '; - - createPlugin(false); - assertTrue(execCommand()); - helper.assertHtmlMatches( - '
    Test
    ' + - '
    ' + - (goog.editor.BrowserFeature.HAS_W3C_RANGES ? ' ' : '') + - '
    ' + - '
    ing
    '); -} - -function testSplitBlockquoteInBlockquoteWithoutClassInParagraphMode() { - root.innerHTML = '
    Test' + SPLIT + 'ing
    '; - - createPlugin(false, true); - assertTrue(execCommand()); - helper.assertHtmlMatches( - '
    Test
    ' + - '

    ' + - (goog.editor.BrowserFeature.HAS_W3C_RANGES ? ' ' : '') + - '

    ' + - '
    ing
    '); -} - -function testSplitBlockquoteInBlockquoteWithClass() { - root.innerHTML = - '
    Test' + SPLIT + 'ing
    '; - - createPlugin(true); - assertTrue(execCommand()); - - helper.assertHtmlMatches( - '
    Test
    ' + - '
    ' + - (goog.editor.BrowserFeature.HAS_W3C_RANGES ? ' ' : '') + - '
    ' + - '
    ing
    '); -} - -function testSplitBlockquoteInBlockquoteWithClassInParagraphMode() { - root.innerHTML = - '
    Test' + SPLIT + 'ing
    '; - - createPlugin(true, true); - assertTrue(execCommand()); - helper.assertHtmlMatches( - '
    Test
    ' + - '

    ' + - (goog.editor.BrowserFeature.HAS_W3C_RANGES ? ' ' : '') + - '

    ' + - '
    ing
    '); -} - -function testIsSplittableBlockquoteWhenRequiresClassNameToSplit() { - createPlugin(true); - - var blockquoteWithClassName = goog.dom.createDom('blockquote', 'tr_bq'); - assertTrue('blockquote should be detected as splittable', - plugin.isSplittableBlockquote(blockquoteWithClassName)); - - var blockquoteWithoutClassName = goog.dom.createDom('blockquote', 'foo'); - assertFalse('blockquote should not be detected as splittable', - plugin.isSplittableBlockquote(blockquoteWithoutClassName)); - - var nonBlockquote = goog.dom.createDom('span', 'tr_bq'); - assertFalse('element should not be detected as splittable', - plugin.isSplittableBlockquote(nonBlockquote)); -} - -function testIsSplittableBlockquoteWhenNotRequiresClassNameToSplit() { - createPlugin(false); - - var blockquoteWithClassName = goog.dom.createDom('blockquote', 'tr_bq'); - assertTrue('blockquote should be detected as splittable', - plugin.isSplittableBlockquote(blockquoteWithClassName)); - - var blockquoteWithoutClassName = goog.dom.createDom('blockquote', 'foo'); - assertTrue('blockquote should be detected as splittable', - plugin.isSplittableBlockquote(blockquoteWithoutClassName)); - - var nonBlockquote = goog.dom.createDom('span', 'tr_bq'); - assertFalse('element should not be detected as splittable', - plugin.isSplittableBlockquote(nonBlockquote)); -} - -function testIsSetupBlockquote() { - createPlugin(false); - - var blockquoteWithClassName = goog.dom.createDom('blockquote', 'tr_bq'); - assertTrue('blockquote should be detected as setup', - plugin.isSetupBlockquote(blockquoteWithClassName)); - - var blockquoteWithoutClassName = goog.dom.createDom('blockquote', 'foo'); - assertFalse('blockquote should not be detected as setup', - plugin.isSetupBlockquote(blockquoteWithoutClassName)); - - var nonBlockquote = goog.dom.createDom('span', 'tr_bq'); - assertFalse('element should not be detected as setup', - plugin.isSetupBlockquote(nonBlockquote)); -} - -function testIsUnsetupBlockquote() { - createPlugin(false); - - var blockquoteWithClassName = goog.dom.createDom('blockquote', 'tr_bq'); - assertFalse('blockquote should not be detected as unsetup', - plugin.isUnsetupBlockquote(blockquoteWithClassName)); - - var blockquoteWithoutClassName = goog.dom.createDom('blockquote', 'foo'); - assertTrue('blockquote should be detected as unsetup', - plugin.isUnsetupBlockquote(blockquoteWithoutClassName)); - - var nonBlockquote = goog.dom.createDom('span', 'tr_bq'); - assertFalse('element should not be detected as unsetup', - plugin.isUnsetupBlockquote(nonBlockquote)); -} diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/emoticons.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/emoticons.js deleted file mode 100644 index 4d0c065812e..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/emoticons.js +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2009 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// All Rights Reserved - -/** - * @fileoverview Plugin for generating emoticons. - * - * @author nicksantos@google.com (Nick Santos) - */ - -goog.provide('goog.editor.plugins.Emoticons'); - -goog.require('goog.dom.TagName'); -goog.require('goog.editor.Plugin'); -goog.require('goog.editor.range'); -goog.require('goog.functions'); -goog.require('goog.ui.emoji.Emoji'); -goog.require('goog.userAgent'); - - - -/** - * Plugin for generating emoticons. - * - * @constructor - * @extends {goog.editor.Plugin} - * @final - */ -goog.editor.plugins.Emoticons = function() { - goog.editor.plugins.Emoticons.base(this, 'constructor'); -}; -goog.inherits(goog.editor.plugins.Emoticons, goog.editor.Plugin); - - -/** The emoticon command. */ -goog.editor.plugins.Emoticons.COMMAND = '+emoticon'; - - -/** @override */ -goog.editor.plugins.Emoticons.prototype.getTrogClassId = - goog.functions.constant(goog.editor.plugins.Emoticons.COMMAND); - - -/** @override */ -goog.editor.plugins.Emoticons.prototype.isSupportedCommand = function( - command) { - return command == goog.editor.plugins.Emoticons.COMMAND; -}; - - -/** - * Inserts an emoticon into the editor at the cursor location. Places the - * cursor to the right of the inserted emoticon. - * @param {string} command Command to execute. - * @param {*=} opt_arg Emoji to insert. - * @return {!Object|undefined} The result of the command. - * @override - */ -goog.editor.plugins.Emoticons.prototype.execCommandInternal = function( - command, opt_arg) { - var emoji = /** @type {goog.ui.emoji.Emoji} */ (opt_arg); - var dom = this.getFieldDomHelper(); - var img = dom.createDom(goog.dom.TagName.IMG, { - 'src': emoji.getUrl(), - 'style': 'margin:0 0.2ex;vertical-align:middle' - }); - img.setAttribute(goog.ui.emoji.Emoji.ATTRIBUTE, emoji.getId()); - - this.getFieldObject().getRange().replaceContentsWithNode(img); - - // IE8 does the right thing with the cursor, and has a js error when we try - // to place the cursor manually. - // IE9 loses the cursor when the window is focused, so focus first. - if (!goog.userAgent.IE || goog.userAgent.isDocumentModeOrHigher(9)) { - this.getFieldObject().focus(); - goog.editor.range.placeCursorNextTo(img, false); - } -}; diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/emoticons_test.html b/src/database/third_party/closure-library/closure/goog/editor/plugins/emoticons_test.html deleted file mode 100644 index d7e696dc410..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/emoticons_test.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - -
    -
    - I am text. -
    -
    - - - diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/emoticons_test.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/emoticons_test.js deleted file mode 100644 index 1ea8576fb38..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/emoticons_test.js +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2010 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.editor.plugins.EmoticonsTest'); -goog.setTestOnly('goog.editor.plugins.EmoticonsTest'); - -goog.require('goog.Uri'); -goog.require('goog.array'); -goog.require('goog.dom'); -goog.require('goog.dom.TagName'); -goog.require('goog.editor.Field'); -goog.require('goog.editor.plugins.Emoticons'); -goog.require('goog.testing.jsunit'); -goog.require('goog.ui.emoji.Emoji'); -goog.require('goog.userAgent'); - -var HTML; - -function setUp() { - HTML = goog.dom.getElement('parent').innerHTML; -} - -function tearDown() { - goog.dom.getElement('parent').innerHTML = HTML; -} - -function testEmojiWithEmoticonsPlugin() { - runEmojiTestWithPlugin(new goog.editor.plugins.Emoticons()); -} - -function runEmojiTestWithPlugin(plugin) { - var field = new goog.editor.Field('testField'); - field.registerPlugin(plugin); - field.makeEditable(); - field.focusAndPlaceCursorAtStart(); - - var src = 'testdata/emoji/4F4.gif'; - var id = '4F4'; - var emoji = new goog.ui.emoji.Emoji(src, id); - field.execCommand(goog.editor.plugins.Emoticons.COMMAND, emoji); - - // The url may be relative or absolute. - var imgs = field.getEditableDomHelper(). - getElementsByTagNameAndClass(goog.dom.TagName.IMG); - assertEquals(1, imgs.length); - - var img = imgs[0]; - assertUriEquals(src, img.getAttribute('src')); - assertEquals(id, img.getAttribute(goog.ui.emoji.Emoji.ATTRIBUTE)); - - var range = field.getRange(); - assertNotNull('must have a selection', range); - assertTrue('range must be a cursor', range.isCollapsed()); - if (goog.userAgent.WEBKIT) { - assertEquals('range starts after image', - 2, range.getStartOffset()); - } else if (goog.userAgent.GECKO) { - assertEquals('range starts after image', - 2, goog.array.indexOf(range.getContainerElement().childNodes, - range.getStartNode())); - } - // Firefox 3.6 is still tested, and would fail here - treitel December 2012 - if (!(goog.userAgent.GECKO && !goog.userAgent.isVersionOrHigher(2))) { - assertEquals('range must be around image', - img.parentElement, range.getContainerElement()); - } -} - -function assertUriEquals(expected, actual) { - var winUri = new goog.Uri(window.location); - assertEquals(winUri.resolve(new goog.Uri(expected)).toString(), - winUri.resolve(new goog.Uri(actual)).toString()); -} diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/enterhandler.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/enterhandler.js deleted file mode 100644 index b6ebc1db90d..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/enterhandler.js +++ /dev/null @@ -1,768 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Plugin to handle enter keys. - * - * @author robbyw@google.com (Robby Walker) - */ - -goog.provide('goog.editor.plugins.EnterHandler'); - -goog.require('goog.dom'); -goog.require('goog.dom.NodeOffset'); -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.Range'); -goog.require('goog.dom.TagName'); -goog.require('goog.editor.BrowserFeature'); -goog.require('goog.editor.Plugin'); -goog.require('goog.editor.node'); -goog.require('goog.editor.plugins.Blockquote'); -goog.require('goog.editor.range'); -goog.require('goog.editor.style'); -goog.require('goog.events.KeyCodes'); -goog.require('goog.functions'); -goog.require('goog.object'); -goog.require('goog.string'); -goog.require('goog.userAgent'); - - - -/** - * Plugin to handle enter keys. This does all the crazy to normalize (as much as - * is reasonable) what happens when you hit enter. This also handles the - * special casing of hitting enter in a blockquote. - * - * In IE, Webkit, and Opera, the resulting HTML uses one DIV tag per line. In - * Firefox, the resulting HTML uses BR tags at the end of each line. - * - * @constructor - * @extends {goog.editor.Plugin} - */ -goog.editor.plugins.EnterHandler = function() { - goog.editor.Plugin.call(this); -}; -goog.inherits(goog.editor.plugins.EnterHandler, goog.editor.Plugin); - - -/** - * The type of block level tag to add on enter, for browsers that support - * specifying the default block-level tag. Can be overriden by subclasses; must - * be either DIV or P. - * @type {goog.dom.TagName} - * @protected - */ -goog.editor.plugins.EnterHandler.prototype.tag = goog.dom.TagName.DIV; - - -/** @override */ -goog.editor.plugins.EnterHandler.prototype.getTrogClassId = function() { - return 'EnterHandler'; -}; - - -/** @override */ -goog.editor.plugins.EnterHandler.prototype.enable = function(fieldObject) { - goog.editor.plugins.EnterHandler.base(this, 'enable', fieldObject); - - if (goog.editor.BrowserFeature.SUPPORTS_OPERA_DEFAULTBLOCK_COMMAND && - (this.tag == goog.dom.TagName.P || this.tag == goog.dom.TagName.DIV)) { - var doc = this.getFieldDomHelper().getDocument(); - doc.execCommand('opera-defaultBlock', false, this.tag); - } -}; - - -/** - * If the contents are empty, return the 'default' html for the field. - * The 'default' contents depend on the enter handling mode, so it - * makes the most sense in this plugin. - * @param {string} html The html to prepare. - * @return {string} The original HTML, or default contents if that - * html is empty. - * @override - */ -goog.editor.plugins.EnterHandler.prototype.prepareContentsHtml = function( - html) { - if (!html || goog.string.isBreakingWhitespace(html)) { - return goog.editor.BrowserFeature.COLLAPSES_EMPTY_NODES ? - this.getNonCollapsingBlankHtml() : ''; - } - return html; -}; - - -/** - * Gets HTML with no contents that won't collapse, for browsers that - * collapse the empty string. - * @return {string} Blank html. - * @protected - */ -goog.editor.plugins.EnterHandler.prototype.getNonCollapsingBlankHtml = - goog.functions.constant('
    '); - - -/** - * Internal backspace handler. - * @param {goog.events.Event} e The keypress event. - * @param {goog.dom.AbstractRange} range The closure range object. - * @protected - */ -goog.editor.plugins.EnterHandler.prototype.handleBackspaceInternal = function(e, - range) { - var field = this.getFieldObject().getElement(); - var container = range && range.getStartNode(); - - if (field.firstChild == container && goog.editor.node.isEmpty(container)) { - e.preventDefault(); - // TODO(user): I think we probably don't need to stopPropagation here - e.stopPropagation(); - } -}; - - -/** - * Fix paragraphs to be the correct type of node. - * @param {goog.events.Event} e The key event. - * @param {boolean} split Whether we already split up a blockquote by - * manually inserting elements. - * @protected - */ -goog.editor.plugins.EnterHandler.prototype.processParagraphTagsInternal = - function(e, split) { - // Force IE to turn the node we are leaving into a DIV. If we do turn - // it into a DIV, the node IE creates in response to ENTER will also be - // a DIV. If we don't, it will be a P. We handle that case - // in handleKeyUpIE_ - if (goog.userAgent.IE || goog.userAgent.OPERA) { - this.ensureBlockIeOpera(goog.dom.TagName.DIV); - } else if (!split && goog.userAgent.WEBKIT) { - // WebKit duplicates a blockquote when the user hits enter. Let's cancel - // this and insert a BR instead, to make it more consistent with the other - // browsers. - var range = this.getFieldObject().getRange(); - if (!range || !goog.editor.plugins.EnterHandler.isDirectlyInBlockquote( - range.getContainerElement())) { - return; - } - - var dh = this.getFieldDomHelper(); - var br = dh.createElement(goog.dom.TagName.BR); - range.insertNode(br, true); - - // If the BR is at the end of a block element, Safari still thinks there is - // only one line instead of two, so we need to add another BR in that case. - if (goog.editor.node.isBlockTag(br.parentNode) && - !goog.editor.node.skipEmptyTextNodes(br.nextSibling)) { - goog.dom.insertSiblingBefore( - dh.createElement(goog.dom.TagName.BR), br); - } - - goog.editor.range.placeCursorNextTo(br, false); - e.preventDefault(); - } -}; - - -/** - * Determines whether the lowest containing block node is a blockquote. - * @param {Node} n The node. - * @return {boolean} Whether the deepest block ancestor of n is a blockquote. - */ -goog.editor.plugins.EnterHandler.isDirectlyInBlockquote = function(n) { - for (var current = n; current; current = current.parentNode) { - if (goog.editor.node.isBlockTag(current)) { - return current.tagName == goog.dom.TagName.BLOCKQUOTE; - } - } - - return false; -}; - - -/** - * Internal delete key handler. - * @param {goog.events.Event} e The keypress event. - * @protected - */ -goog.editor.plugins.EnterHandler.prototype.handleDeleteGecko = function(e) { - this.deleteBrGecko(e); -}; - - -/** - * Deletes the element at the cursor if it is a BR node, and if it does, calls - * e.preventDefault to stop the browser from deleting. Only necessary in Gecko - * as a workaround for mozilla bug 205350 where deleting a BR that is followed - * by a block element doesn't work (the BR gets immediately replaced). We also - * need to account for an ill-formed cursor which occurs from us trying to - * stop the browser from deleting. - * - * @param {goog.events.Event} e The DELETE keypress event. - * @protected - */ -goog.editor.plugins.EnterHandler.prototype.deleteBrGecko = function(e) { - var range = this.getFieldObject().getRange(); - if (range.isCollapsed()) { - var container = range.getEndNode(); - if (container.nodeType == goog.dom.NodeType.ELEMENT) { - var nextNode = container.childNodes[range.getEndOffset()]; - if (nextNode && nextNode.tagName == goog.dom.TagName.BR) { - // We want to retrieve the first non-whitespace previous sibling - // as we could have added an empty text node below and want to - // properly handle deleting a sequence of BR's. - var previousSibling = goog.editor.node.getPreviousSibling(nextNode); - var nextSibling = nextNode.nextSibling; - - container.removeChild(nextNode); - e.preventDefault(); - - // When we delete a BR followed by a block level element, the cursor - // has a line-height which spans the height of the block level element. - // e.g. If we delete a BR followed by a UL, the resulting HTML will - // appear to the end user like:- - // - // | * one - // | * two - // | * three - // - // There are a couple of cases that we have to account for in order to - // properly conform to what the user expects when DELETE is pressed. - // - // 1. If the BR has a previous sibling and the previous sibling is - // not a block level element or a BR, we place the cursor at the - // end of that. - // 2. If the BR doesn't have a previous sibling or the previous sibling - // is a block level element or a BR, we place the cursor at the - // beginning of the leftmost leaf of its next sibling. - if (nextSibling && goog.editor.node.isBlockTag(nextSibling)) { - if (previousSibling && - !(previousSibling.tagName == goog.dom.TagName.BR || - goog.editor.node.isBlockTag(previousSibling))) { - goog.dom.Range.createCaret( - previousSibling, - goog.editor.node.getLength(previousSibling)).select(); - } else { - var leftMostLeaf = goog.editor.node.getLeftMostLeaf(nextSibling); - goog.dom.Range.createCaret(leftMostLeaf, 0).select(); - } - } - } - } - } -}; - - -/** @override */ -goog.editor.plugins.EnterHandler.prototype.handleKeyPress = function(e) { - // If a dialog doesn't have selectable field, Gecko grabs the event and - // performs actions in editor window. This solves that problem and allows - // the event to be passed on to proper handlers. - if (goog.userAgent.GECKO && this.getFieldObject().inModalMode()) { - return false; - } - - // Firefox will allow the first node in an iframe to be deleted - // on a backspace. Disallow it if the node is empty. - if (e.keyCode == goog.events.KeyCodes.BACKSPACE) { - this.handleBackspaceInternal(e, this.getFieldObject().getRange()); - - } else if (e.keyCode == goog.events.KeyCodes.ENTER) { - if (goog.userAgent.GECKO) { - if (!e.shiftKey) { - // Behave similarly to IE's content editable return carriage: - // If the shift key is down or specified by the application, insert a - // BR, otherwise split paragraphs - this.handleEnterGecko_(e); - } - } else { - // In Gecko-based browsers, this is handled in the handleEnterGecko_ - // method. - this.getFieldObject().dispatchBeforeChange(); - var cursorPosition = this.deleteCursorSelection_(); - - var split = !!this.getFieldObject().execCommand( - goog.editor.plugins.Blockquote.SPLIT_COMMAND, cursorPosition); - if (split) { - // TODO(user): I think we probably don't need to stopPropagation here - e.preventDefault(); - e.stopPropagation(); - } - - this.releasePositionObject_(cursorPosition); - - if (goog.userAgent.WEBKIT) { - this.handleEnterWebkitInternal(e); - } - - this.processParagraphTagsInternal(e, split); - this.getFieldObject().dispatchChange(); - } - - } else if (goog.userAgent.GECKO && e.keyCode == goog.events.KeyCodes.DELETE) { - this.handleDeleteGecko(e); - } - - return false; -}; - - -/** @override */ -goog.editor.plugins.EnterHandler.prototype.handleKeyUp = function(e) { - // If a dialog doesn't have selectable field, Gecko grabs the event and - // performs actions in editor window. This solves that problem and allows - // the event to be passed on to proper handlers. - if (goog.userAgent.GECKO && this.getFieldObject().inModalMode()) { - return false; - } - this.handleKeyUpInternal(e); - return false; -}; - - -/** - * Internal handler for keyup events. - * @param {goog.events.Event} e The key event. - * @protected - */ -goog.editor.plugins.EnterHandler.prototype.handleKeyUpInternal = function(e) { - if ((goog.userAgent.IE || goog.userAgent.OPERA) && - e.keyCode == goog.events.KeyCodes.ENTER) { - this.ensureBlockIeOpera(goog.dom.TagName.DIV, true); - } -}; - - -/** - * Handles an enter keypress event on fields in Gecko. - * @param {goog.events.BrowserEvent} e The key event. - * @private - */ -goog.editor.plugins.EnterHandler.prototype.handleEnterGecko_ = function(e) { - // Retrieve whether the selection is collapsed before we delete it. - var range = this.getFieldObject().getRange(); - var wasCollapsed = !range || range.isCollapsed(); - var cursorPosition = this.deleteCursorSelection_(); - - var handled = this.getFieldObject().execCommand( - goog.editor.plugins.Blockquote.SPLIT_COMMAND, cursorPosition); - if (handled) { - // TODO(user): I think we probably don't need to stopPropagation here - e.preventDefault(); - e.stopPropagation(); - } - - this.releasePositionObject_(cursorPosition); - if (!handled) { - this.handleEnterAtCursorGeckoInternal(e, wasCollapsed, range); - } -}; - - -/** - * Handle an enter key press in WebKit. - * @param {goog.events.BrowserEvent} e The key press event. - * @protected - */ -goog.editor.plugins.EnterHandler.prototype.handleEnterWebkitInternal = - goog.nullFunction; - - -/** - * Handle an enter key press on collapsed selection. handleEnterGecko_ ensures - * the selection is collapsed by deleting its contents if it is not. The - * default implementation does nothing. - * @param {goog.events.BrowserEvent} e The key press event. - * @param {boolean} wasCollapsed Whether the selection was collapsed before - * the key press. If it was not, code before this function has already - * cleared the contents of the selection. - * @param {goog.dom.AbstractRange} range Object representing the selection. - * @protected - */ -goog.editor.plugins.EnterHandler.prototype.handleEnterAtCursorGeckoInternal = - goog.nullFunction; - - -/** - * Names of all the nodes that we don't want to turn into block nodes in IE when - * the user hits enter. - * @type {Object} - * @private - */ -goog.editor.plugins.EnterHandler.DO_NOT_ENSURE_BLOCK_NODES_ = - goog.object.createSet( - goog.dom.TagName.LI, goog.dom.TagName.DIV, goog.dom.TagName.H1, - goog.dom.TagName.H2, goog.dom.TagName.H3, goog.dom.TagName.H4, - goog.dom.TagName.H5, goog.dom.TagName.H6); - - -/** - * Whether this is a node that contains a single BR tag and non-nbsp - * whitespace. - * @param {Node} node Node to check. - * @return {boolean} Whether this is an element that only contains a BR. - * @protected - */ -goog.editor.plugins.EnterHandler.isBrElem = function(node) { - return goog.editor.node.isEmpty(node) && - node.getElementsByTagName(goog.dom.TagName.BR).length == 1; -}; - - -/** - * Ensures all text in IE and Opera to be in the given tag in order to control - * Enter spacing. Call this when Enter is pressed if desired. - * - * We want to make sure the user is always inside of a block (or other nodes - * listed in goog.editor.plugins.EnterHandler.IGNORE_ENSURE_BLOCK_NODES_). We - * listen to keypress to force nodes that the user is leaving to turn into - * blocks, but we also need to listen to keyup to force nodes that the user is - * entering to turn into blocks. - * Example: html is: "

    foo[cursor]

    ", and the user hits enter. We - * don't want to format the h2, but we do want to format the P that is - * created on enter. The P node is not available until keyup. - * @param {goog.dom.TagName} tag The tag name to convert to. - * @param {boolean=} opt_keyUp Whether the function is being called on key up. - * When called on key up, the cursor is in the newly created node, so the - * semantics for when to change it to a block are different. Specifically, - * if the resulting node contains only a BR, it is converted to . - * @protected - */ -goog.editor.plugins.EnterHandler.prototype.ensureBlockIeOpera = function(tag, - opt_keyUp) { - var range = this.getFieldObject().getRange(); - var container = range.getContainer(); - var field = this.getFieldObject().getElement(); - - var paragraph; - while (container && container != field) { - // We don't need to ensure a block if we are already in the same block, or - // in another block level node that we don't want to change the format of - // (unless we're handling keyUp and that block node just contains a BR). - var nodeName = container.nodeName; - // Due to @bug 2455389, the call to isBrElem needs to be inlined in the if - // instead of done before and saved in a variable, so that it can be - // short-circuited and avoid a weird IE edge case. - if (nodeName == tag || - (goog.editor.plugins.EnterHandler. - DO_NOT_ENSURE_BLOCK_NODES_[nodeName] && !(opt_keyUp && - goog.editor.plugins.EnterHandler.isBrElem(container)))) { - // Opera can create a

    inside of a

    in some situations, - // such as when breaking out of a list that is contained in a
    . - if (goog.userAgent.OPERA && paragraph) { - if (nodeName == tag && - paragraph == container.lastChild && - goog.editor.node.isEmpty(paragraph)) { - goog.dom.insertSiblingAfter(paragraph, container); - goog.dom.Range.createFromNodeContents(paragraph).select(); - } - break; - } - return; - } - if (goog.userAgent.OPERA && opt_keyUp && nodeName == goog.dom.TagName.P && - nodeName != tag) { - paragraph = container; - } - - container = container.parentNode; - } - - - if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher(9)) { - // IE (before IE9) has a bug where if the cursor is directly before a block - // node (e.g., the content is "foo[cursor]
    bar
    "), - // the FormatBlock command actually formats the "bar" instead of the "foo". - // This is just wrong. To work-around this, we want to move the - // selection back one character, and then restore it to its prior position. - // NOTE: We use the following "range math" to detect this situation because - // using Closure ranges here triggers a bug in IE that causes a crash. - // parent2 != parent3 ensures moving the cursor forward one character - // crosses at least 1 element boundary, and therefore tests if the cursor is - // at such a boundary. The second check, parent3 != range.parentElement() - // weeds out some cases where the elements are siblings instead of cousins. - var needsHelp = false; - range = range.getBrowserRangeObject(); - var range2 = range.duplicate(); - range2.moveEnd('character', 1); - // In whitebox mode, when the cursor is at the end of the field, trying to - // move the end of the range will do nothing, and hence the range's text - // will be empty. In this case, the cursor clearly isn't sitting just - // before a block node, since it isn't before anything. - if (range2.text.length) { - var parent2 = range2.parentElement(); - - var range3 = range2.duplicate(); - range3.collapse(false); - var parent3 = range3.parentElement(); - - if ((needsHelp = parent2 != parent3 && - parent3 != range.parentElement())) { - range.move('character', -1); - range.select(); - } - } - } - - this.getFieldObject().getEditableDomHelper().getDocument().execCommand( - 'FormatBlock', false, '<' + tag + '>'); - - if (needsHelp) { - range.move('character', 1); - range.select(); - } -}; - - -/** - * Deletes the content at the current cursor position. - * @return {!Node|!Object} Something representing the current cursor position. - * See deleteCursorSelectionIE_ and deleteCursorSelectionW3C_ for details. - * Should be passed to releasePositionObject_ when no longer in use. - * @private - */ -goog.editor.plugins.EnterHandler.prototype.deleteCursorSelection_ = function() { - return goog.editor.BrowserFeature.HAS_W3C_RANGES ? - this.deleteCursorSelectionW3C_() : this.deleteCursorSelectionIE_(); -}; - - -/** - * Releases the object returned by deleteCursorSelection_. - * @param {Node|Object} position The object returned by deleteCursorSelection_. - * @private - */ -goog.editor.plugins.EnterHandler.prototype.releasePositionObject_ = - function(position) { - if (!goog.editor.BrowserFeature.HAS_W3C_RANGES) { - (/** @type {Node} */ (position)).removeNode(true); - } -}; - - -/** - * Delete the selection at the current cursor position, then returns a temporary - * node at the current position. - * @return {!Node} A temporary node marking the current cursor position. This - * node should eventually be removed from the DOM. - * @private - */ -goog.editor.plugins.EnterHandler.prototype.deleteCursorSelectionIE_ = - function() { - var doc = this.getFieldDomHelper().getDocument(); - var range = doc.selection.createRange(); - - var id = goog.string.createUniqueString(); - range.pasteHTML(''); - var splitNode = doc.getElementById(id); - splitNode.id = ''; - return splitNode; -}; - - -/** - * Delete the selection at the current cursor position, then returns the node - * at the current position. - * @return {!goog.editor.range.Point} The current cursor position. Note that - * unlike simulateEnterIE_, this should not be removed from the DOM. - * @private - */ -goog.editor.plugins.EnterHandler.prototype.deleteCursorSelectionW3C_ = - function() { - var range = this.getFieldObject().getRange(); - - // Delete the current selection if it's is non-collapsed. - // Although this is redundant in FF, it's necessary for Safari - if (!range.isCollapsed()) { - var shouldDelete = true; - // Opera selects the
    in an empty block if there is no text node - // preceding it. To preserve inline formatting when pressing [enter] inside - // an empty block, don't delete the selection if it only selects a
    at - // the end of the block. - // TODO(user): Move this into goog.dom.Range. It should detect this state - // when creating a range from the window selection and fix it in the created - // range. - if (goog.userAgent.OPERA) { - var startNode = range.getStartNode(); - var startOffset = range.getStartOffset(); - if (startNode == range.getEndNode() && - // This weeds out cases where startNode is a text node. - startNode.lastChild && - startNode.lastChild.tagName == goog.dom.TagName.BR && - // If this check is true, then endOffset is implied to be - // startOffset + 1, because the selection is not collapsed and - // it starts and ends within the same element. - startOffset == startNode.childNodes.length - 1) { - shouldDelete = false; - } - } - if (shouldDelete) { - goog.editor.plugins.EnterHandler.deleteW3cRange_(range); - } - } - - return goog.editor.range.getDeepEndPoint(range, true); -}; - - -/** - * Deletes the contents of the selection from the DOM. - * @param {goog.dom.AbstractRange} range The range to remove contents from. - * @return {goog.dom.AbstractRange} The resulting range. Used for testing. - * @private - */ -goog.editor.plugins.EnterHandler.deleteW3cRange_ = function(range) { - if (range && !range.isCollapsed()) { - var reselect = true; - var baseNode = range.getContainerElement(); - var nodeOffset = new goog.dom.NodeOffset(range.getStartNode(), baseNode); - var rangeOffset = range.getStartOffset(); - - // Whether the selection crosses no container boundaries. - var isInOneContainer = - goog.editor.plugins.EnterHandler.isInOneContainerW3c_(range); - - // Whether the selection ends in a container it doesn't fully select. - var isPartialEnd = !isInOneContainer && - goog.editor.plugins.EnterHandler.isPartialEndW3c_(range); - - // Remove The range contents, and ensure the correct content stays selected. - range.removeContents(); - var node = nodeOffset.findTargetNode(baseNode); - if (node) { - range = goog.dom.Range.createCaret(node, rangeOffset); - } else { - // This occurs when the node that would have been referenced has now been - // deleted and there are no other nodes in the baseNode. Thus need to - // set the caret to the end of the base node. - range = - goog.dom.Range.createCaret(baseNode, baseNode.childNodes.length); - reselect = false; - } - range.select(); - - // If we just deleted everything from the container, add an nbsp - // to the container, and leave the cursor inside of it - if (isInOneContainer) { - var container = goog.editor.style.getContainer(range.getStartNode()); - if (goog.editor.node.isEmpty(container, true)) { - var html = ' '; - if (goog.userAgent.OPERA && - container.tagName == goog.dom.TagName.LI) { - // Don't break Opera's native break-out-of-lists behavior. - html = '
    '; - } - goog.editor.node.replaceInnerHtml(container, html); - goog.editor.range.selectNodeStart(container.firstChild); - reselect = false; - } - } - - if (isPartialEnd) { - /* - This code handles the following, where | is the cursor: -
    a|b
    c|d
    - After removeContents, the remaining HTML is -
    a
    d
    - which means the line break between the two divs remains. This block - moves children of the second div in to the first div to get the correct - result: -
    ad
    - - TODO(robbyw): Should we wrap the second div's contents in a span if they - have inline style? - */ - var rangeStart = goog.editor.style.getContainer(range.getStartNode()); - var redundantContainer = goog.editor.node.getNextSibling(rangeStart); - if (rangeStart && redundantContainer) { - goog.dom.append(rangeStart, redundantContainer.childNodes); - goog.dom.removeNode(redundantContainer); - } - } - - if (reselect) { - // The contents of the original range are gone, so restore the cursor - // position at the start of where the range once was. - range = goog.dom.Range.createCaret(nodeOffset.findTargetNode(baseNode), - rangeOffset); - range.select(); - } - } - - return range; -}; - - -/** - * Checks whether the whole range is in a single block-level element. - * @param {goog.dom.AbstractRange} range The range to check. - * @return {boolean} Whether the whole range is in a single block-level element. - * @private - */ -goog.editor.plugins.EnterHandler.isInOneContainerW3c_ = function(range) { - // Find the block element containing the start of the selection. - var startContainer = range.getStartNode(); - if (goog.editor.style.isContainer(startContainer)) { - startContainer = startContainer.childNodes[range.getStartOffset()] || - startContainer; - } - startContainer = goog.editor.style.getContainer(startContainer); - - // Find the block element containing the end of the selection. - var endContainer = range.getEndNode(); - if (goog.editor.style.isContainer(endContainer)) { - endContainer = endContainer.childNodes[range.getEndOffset()] || - endContainer; - } - endContainer = goog.editor.style.getContainer(endContainer); - - // Compare the two. - return startContainer == endContainer; -}; - - -/** - * Checks whether the end of the range is not at the end of a block-level - * element. - * @param {goog.dom.AbstractRange} range The range to check. - * @return {boolean} Whether the end of the range is not at the end of a - * block-level element. - * @private - */ -goog.editor.plugins.EnterHandler.isPartialEndW3c_ = function(range) { - var endContainer = range.getEndNode(); - var endOffset = range.getEndOffset(); - var node = endContainer; - if (goog.editor.style.isContainer(node)) { - var child = node.childNodes[endOffset]; - // Child is null when end offset is >= length, which indicates the entire - // container is selected. Otherwise, we also know the entire container - // is selected if the selection ends at a new container. - if (!child || - child.nodeType == goog.dom.NodeType.ELEMENT && - goog.editor.style.isContainer(child)) { - return false; - } - } - - var container = goog.editor.style.getContainer(node); - while (container != node) { - if (goog.editor.node.getNextSibling(node)) { - return true; - } - node = node.parentNode; - } - - return endOffset != goog.editor.node.getLength(endContainer); -}; diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/enterhandler_test.html b/src/database/third_party/closure-library/closure/goog/editor/plugins/enterhandler_test.html deleted file mode 100644 index 5a25a19d9dd..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/enterhandler_test.html +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - Closure Unit Tests - goog.editor.plugins.EnterHandler - - - - - - - -

    -

    - This is used to test static utility functions. -
    -
    -
    -
    - This is an - - selection - - unsetup blockquote -
    -
    -

    -

    -
    - This is a - - selection - - setup blockquote -
    -
    -

    -

    -

    -
    -

    - - diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/enterhandler_test.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/enterhandler_test.js deleted file mode 100644 index 37b8967973e..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/enterhandler_test.js +++ /dev/null @@ -1,741 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.editor.plugins.EnterHandlerTest'); -goog.setTestOnly('goog.editor.plugins.EnterHandlerTest'); - -goog.require('goog.dom'); -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.Range'); -goog.require('goog.dom.TagName'); -goog.require('goog.editor.BrowserFeature'); -goog.require('goog.editor.Field'); -goog.require('goog.editor.Plugin'); -goog.require('goog.editor.plugins.Blockquote'); -goog.require('goog.editor.plugins.EnterHandler'); -goog.require('goog.editor.range'); -goog.require('goog.events'); -goog.require('goog.events.KeyCodes'); -goog.require('goog.testing.ExpectedFailures'); -goog.require('goog.testing.MockClock'); -goog.require('goog.testing.dom'); -goog.require('goog.testing.editor.TestHelper'); -goog.require('goog.testing.events'); -goog.require('goog.testing.jsunit'); -goog.require('goog.userAgent'); - -var savedHtml; - -var field1; -var field2; -var firedDelayedChange; -var firedBeforeChange; -var clock; -var container; -var EXPECTEDFAILURES; - -function setUpPage() { - container = goog.dom.getElement('container'); -} - -function setUp() { - EXPECTEDFAILURES = new goog.testing.ExpectedFailures(); - savedHtml = goog.dom.getElement('root').innerHTML; - clock = new goog.testing.MockClock(true); -} - -function setUpFields(classnameRequiredToSplitBlockquote) { - field1 = makeField('field1', classnameRequiredToSplitBlockquote); - field2 = makeField('field2', classnameRequiredToSplitBlockquote); - - field1.makeEditable(); - field2.makeEditable(); -} - -function tearDown() { - clock.dispose(); - - EXPECTEDFAILURES.handleTearDown(); - - goog.dom.getElement('root').innerHTML = savedHtml; -} - -function testEnterInNonSetupBlockquote() { - setUpFields(true); - resetChangeFlags(); - var prevented = !selectNodeAndHitEnter(field1, 'field1cursor'); - waitForChangeEvents(); - assertChangeFlags(); - - // make sure there's just one blockquote, and that the text has been deleted. - var elem = field1.getElement(); - var dom = field1.getEditableDomHelper(); - EXPECTEDFAILURES.expectFailureFor(goog.userAgent.OPERA, - 'The blockquote is overwritten with DIV due to CORE-22104 -- Opera ' + - 'overwrites the BLOCKQUOTE ancestor with DIV when doing FormatBlock ' + - 'for DIV'); - try { - assertEquals('Blockquote should not be split', - 1, dom.getElementsByTagNameAndClass('BLOCKQUOTE', null, elem).length); - } catch (e) { - EXPECTEDFAILURES.handleException(e); - } - assert('Selection should be deleted', - -1 == elem.innerHTML.indexOf('selection')); - - assertEquals('The event should have been prevented only on webkit', - prevented, goog.userAgent.WEBKIT); -} - -function testEnterInSetupBlockquote() { - setUpFields(true); - resetChangeFlags(); - var prevented = !selectNodeAndHitEnter(field2, 'field2cursor'); - waitForChangeEvents(); - assertChangeFlags(); - - // make sure there are two blockquotes, and a DIV with nbsp in the middle. - var elem = field2.getElement(); - var dom = field2.getEditableDomHelper(); - assertEquals('Blockquote should be split', 2, - dom.getElementsByTagNameAndClass('BLOCKQUOTE', null, elem).length); - assert('Selection should be deleted', - -1 == elem.innerHTML.indexOf('selection')); - - assert('should have div with  ', - -1 != elem.innerHTML.indexOf('>' + getNbsp() + '<')); - assert('event should have been prevented', prevented); -} - -function testEnterInNonSetupBlockquoteWhenClassnameIsNotRequired() { - setUpFields(false); - - resetChangeFlags(); - var prevented = !selectNodeAndHitEnter(field1, 'field1cursor'); - waitForChangeEvents(); - assertChangeFlags(); - - // make sure there are two blockquotes, and a DIV with nbsp in the middle. - var elem = field1.getElement(); - var dom = field1.getEditableDomHelper(); - assertEquals('Blockquote should be split', 2, - dom.getElementsByTagNameAndClass('BLOCKQUOTE', null, elem).length); - assert('Selection should be deleted', - -1 == elem.innerHTML.indexOf('selection')); - - assert('should have div with  ', - -1 != elem.innerHTML.indexOf('>' + getNbsp() + '<')); - assert('event should have been prevented', prevented); -} - -function testEnterInBlockquoteCreatesDivInBrMode() { - setUpFields(true); - selectNodeAndHitEnter(field2, 'field2cursor'); - var elem = field2.getElement(); - var dom = field2.getEditableDomHelper(); - - var firstBlockquote = - dom.getElementsByTagNameAndClass('BLOCKQUOTE', null, elem)[0]; - var div = dom.getNextElementSibling(firstBlockquote); - assertEquals('Element after blockquote should be a div', 'DIV', div.tagName); - assertEquals('Element after div should be second blockquote', - 'BLOCKQUOTE', dom.getNextElementSibling(div).tagName); -} - - -/** - * Tests that breaking after a BR doesn't result in unnecessary newlines. - * @bug 1471047 - */ -function testEnterInBlockquoteRemovesUnnecessaryBrWithCursorAfterBr() { - setUpFields(true); - - // Assume the following HTML snippet:- - //
    one
    |two
    - // - // After enter on the cursor position without the fix, the resulting HTML - // after the blockquote split was:- - //
    one
    - //
     
    - //

    two
    - // - // This creates the impression on an unnecessary newline. The resulting HTML - // after the fix is:- - // - //
    one
    - //
     
    - //
    two
    - field1.setHtml(false, - '
    one
    ' + - 'two
    '); - var dom = field1.getEditableDomHelper(); - goog.dom.Range.createCaret(dom.getElement('quote'), 2).select(); - goog.testing.events.fireKeySequence(field1.getElement(), - goog.events.KeyCodes.ENTER); - var elem = field1.getElement(); - var secondBlockquote = - dom.getElementsByTagNameAndClass('BLOCKQUOTE', null, elem)[1]; - assertHTMLEquals('two
    ', secondBlockquote.innerHTML); - - // Verifies that a blockquote split doesn't happen if it doesn't need to. - field1.setHtml(false, - '
    one
    '); - selectNodeAndHitEnter(field1, 'brcursor'); - assertEquals( - 1, dom.getElementsByTagNameAndClass('BLOCKQUOTE', null, elem).length); -} - - -/** - * Tests that breaking in a text node before a BR doesn't result in unnecessary - * newlines. - * @bug 1471047 - */ -function testEnterInBlockquoteRemovesUnnecessaryBrWithCursorBeforeBr() { - setUpFields(true); - - // Assume the following HTML snippet:- - //
    one|
    two
    - // - // After enter on the cursor position, the resulting HTML should be. - //
    one
    - //
     
    - //
    two
    - field1.setHtml(false, - '
    one
    ' + - 'two
    '); - var dom = field1.getEditableDomHelper(); - var cursor = dom.getElement('quote').firstChild; - goog.dom.Range.createCaret(cursor, 3).select(); - goog.testing.events.fireKeySequence(field1.getElement(), - goog.events.KeyCodes.ENTER); - var elem = field1.getElement(); - var secondBlockquote = - dom.getElementsByTagNameAndClass('BLOCKQUOTE', null, elem)[1]; - assertHTMLEquals('two
    ', secondBlockquote.innerHTML); - - // Ensures that standard text node split works as expected with the new - // change. - field1.setHtml(false, - '
    onetwo
    '); - cursor = dom.getElement('quote').firstChild; - goog.dom.Range.createCaret(cursor, 3).select(); - goog.testing.events.fireKeySequence(field1.getElement(), - goog.events.KeyCodes.ENTER); - secondBlockquote = - dom.getElementsByTagNameAndClass('BLOCKQUOTE', null, elem)[1]; - assertHTMLEquals('two
    ', secondBlockquote.innerHTML); -} - - -/** - * Tests that pressing enter in a blockquote doesn't create unnecessary - * DOM subtrees. - * - * @bug 1991539 - * @bug 1991392 - */ -function testEnterInBlockquoteRemovesExtraNodes() { - setUpFields(true); - - // Let's assume we have the following DOM structure and the - // cursor is placed after the first numbered list item "one". - // - //
    - //
    a
    1. one|
    - //
    two
    - //
    - // - // After pressing enter, we have the following structure. - // - //
    - //
    a
    1. one|
    - //
    - //
     
    - //
    - //
    - //
    two
    - //
    - // - // This appears to the user as an empty list. After the fix, the HTML - // will be - // - //
    - //
    a
    1. one|
    - //
    - //
     
    - //
    - //
    two
    - //
    - // - field1.setHtml(false, - '
    ' + - '
    a
    1. one
    ' + - '
    b
    ' + - '
    '); - var dom = field1.getEditableDomHelper(); - goog.dom.Range.createCaret(dom.getElement('cursor').firstChild, 3).select(); - goog.testing.events.fireKeySequence(field1.getElement(), - goog.events.KeyCodes.ENTER); - var elem = field1.getElement(); - var secondBlockquote = - dom.getElementsByTagNameAndClass('BLOCKQUOTE', null, elem)[1]; - assertHTMLEquals('
    b
    ', secondBlockquote.innerHTML); - - // Ensure that we remove only unnecessary subtrees. - field1.setHtml(false, - '
    ' + - '
    a
    one
    two
    ' + - '
    c
    ' + - '
    '); - goog.dom.Range.createCaret(dom.getElement('cursor').firstChild, 3).select(); - goog.testing.events.fireKeySequence(field1.getElement(), - goog.events.KeyCodes.ENTER); - secondBlockquote = - dom.getElementsByTagNameAndClass('BLOCKQUOTE', null, elem)[1]; - var expectedHTML = '
    two
    ' + - '
    c
    '; - assertHTMLEquals(expectedHTML, secondBlockquote.innerHTML); - - // Place the cursor in the middle of a line. - field1.setHtml(false, - '
    ' + - '
    one
    two
    ' + - '
    '); - goog.dom.Range.createCaret( - dom.getElement('quote').firstChild.firstChild, 1).select(); - goog.testing.events.fireKeySequence(field1.getElement(), - goog.events.KeyCodes.ENTER); - var blockquotes = dom.getElementsByTagNameAndClass('BLOCKQUOTE', null, elem); - assertEquals(2, blockquotes.length); - assertHTMLEquals('
    o
    ', blockquotes[0].innerHTML); - assertHTMLEquals('
    ne
    two
    ', blockquotes[1].innerHTML); -} - -function testEnterInList() { - setUpFields(true); - - // in a list should *never* be handled by custom code. Lists are - // just way too complicated to get right. - field1.setHtml(false, - '
    1. hi!
    '); - if (goog.userAgent.OPERA) { - // Opera doesn't actually place the selection in the empty span - // unless we add a text node first. - var dom = field1.getEditableDomHelper(); - dom.getElement('field1cursor').appendChild(dom.createTextNode('')); - } - var prevented = !selectNodeAndHitEnter(field1, 'field1cursor'); - assertFalse(' in a list should not be prevented', prevented); -} - -function testEnterAtEndOfBlockInWebkit() { - setUpFields(true); - - if (goog.userAgent.WEBKIT) { - field1.setHtml(false, - '
    hi!
    '); - - var cursor = field1.getEditableDomHelper().getElement('field1cursor'); - goog.editor.range.placeCursorNextTo(cursor, false); - goog.dom.removeNode(cursor); - - var prevented = !goog.testing.events.fireKeySequence( - field1.getElement(), goog.events.KeyCodes.ENTER); - waitForChangeEvents(); - assertChangeFlags(); - assert('event should have been prevented', prevented); - - // Make sure that the block now has two brs. - var elem = field1.getElement(); - assertEquals('should have inserted two br tags: ' + elem.innerHTML, - 2, goog.dom.getElementsByTagNameAndClass('BR', null, elem).length); - } -} - - -/** - * Tests that deleting a BR that comes right before a block element works. - * @bug 1471096 - * @bug 2056376 - */ -function testDeleteBrBeforeBlock() { - setUpFields(true); - - // This test only works on Gecko, because it's testing for manual deletion of - // BR tags, which is done only for Gecko. For other browsers we fall through - // and let the browser do the delete, which can only be tested with a robot - // test (see javascript/apps/editor/tests/delete_br_robot.html). - if (goog.userAgent.GECKO) { - field1.setHtml(false, 'one

    two
    '); - var helper = new goog.testing.editor.TestHelper(field1.getElement()); - helper.select(field1.getElement(), 2); // Between the two BR's. - goog.testing.events.fireKeySequence(field1.getElement(), - goog.events.KeyCodes.DELETE); - assertEquals('Should have deleted exactly one
    ', - 'one
    two
    ', - field1.getElement().innerHTML); - - // We test the case where the BR has a previous sibling which is not - // a block level element. - field1.setHtml(false, 'one
    • two
    '); - helper.select(field1.getElement(), 1); // Between one and BR. - goog.testing.events.fireKeySequence(field1.getElement(), - goog.events.KeyCodes.DELETE); - assertEquals('Should have deleted the
    ', - 'one
    • two
    ', - field1.getElement().innerHTML); - // Verify that the cursor is placed at the end of the text node "one". - var range = field1.getRange(); - var focusNode = range.getFocusNode(); - assertTrue('The selected range should be collapsed', range.isCollapsed()); - assertTrue('The focus node should be the text node "one"', - focusNode.nodeType == goog.dom.NodeType.TEXT && - focusNode.data == 'one'); - assertEquals('The focus offset should be at the end of the text node "one"', - focusNode.length, - range.getFocusOffset()); - assertTrue('The next sibling of the focus node should be the UL', - focusNode.nextSibling && - focusNode.nextSibling.tagName == goog.dom.TagName.UL); - - // We test the case where the previous sibling of the BR is a block - // level element. - field1.setHtml(false, '
    foo

    bar
    '); - helper.select(field1.getElement(), 1); // Before the BR. - goog.testing.events.fireKeySequence(field1.getElement(), - goog.events.KeyCodes.DELETE); - assertEquals('Should have deleted the
    ', - '
    foo
    bar
    ', - field1.getElement().innerHTML); - range = field1.getRange(); - assertEquals('The selected range should be contained within the ', - goog.dom.TagName.SPAN, - range.getContainerElement().tagName); - assertTrue('The selected range should be collapsed', range.isCollapsed()); - // Verify that the cursor is placed inside the span at the beginning of bar. - focusNode = range.getFocusNode(); - assertTrue('The focus node should be the text node "bar"', - focusNode.nodeType == goog.dom.NodeType.TEXT && - focusNode.data == 'bar'); - assertEquals('The focus offset should be at the beginning ' + - 'of the text node "bar"', - 0, - range.getFocusOffset()); - - // We test the case where the BR does not have a previous sibling. - field1.setHtml(false, '
    • one
    '); - helper.select(field1.getElement(), 0); // Before the BR. - goog.testing.events.fireKeySequence(field1.getElement(), - goog.events.KeyCodes.DELETE); - assertEquals('Should have deleted the
    ', - '
    • one
    ', - field1.getElement().innerHTML); - range = field1.getRange(); - // Verify that the cursor is placed inside the LI at the text node "one". - assertEquals('The selected range should be contained within the
  • ', - goog.dom.TagName.LI, - range.getContainerElement().tagName); - assertTrue('The selected range should be collapsed', range.isCollapsed()); - focusNode = range.getFocusNode(); - assertTrue('The focus node should be the text node "one"', - (focusNode.nodeType == goog.dom.NodeType.TEXT && - focusNode.data == 'one')); - assertEquals('The focus offset should be at the beginning of ' + - 'the text node "one"', - 0, - range.getFocusOffset()); - - // Testing deleting a BR followed by a block level element and preceded - // by a BR. - field1.setHtml(false, '

    • one
    '); - helper.select(field1.getElement(), 1); // Between the BR's. - goog.testing.events.fireKeySequence(field1.getElement(), - goog.events.KeyCodes.DELETE); - assertEquals('Should have deleted the
    ', - '
    • one
    ', - field1.getElement().innerHTML); - // Verify that the cursor is placed inside the LI at the text node "one". - range = field1.getRange(); - assertEquals('The selected range should be contained within the
  • ', - goog.dom.TagName.LI, - range.getContainerElement().tagName); - assertTrue('The selected range should be collapsed', range.isCollapsed()); - focusNode = range.getFocusNode(); - assertTrue('The focus node should be the text node "one"', - (focusNode.nodeType == goog.dom.NodeType.TEXT && - focusNode.data == 'one')); - assertEquals('The focus offset should be at the beginning of ' + - 'the text node "one"', - 0, - range.getFocusOffset()); - } // End if GECKO -} - - -/** - * Tests that deleting a BR before a blockquote doesn't remove quoted text. - * @bug 1471075 - */ -function testDeleteBeforeBlockquote() { - setUpFields(true); - - if (goog.userAgent.GECKO) { - field1.setHtml(false, - '


    foo
    '); - var helper = new goog.testing.editor.TestHelper(field1.getElement()); - helper.select(field1.getElement(), 0); // Before the first BR. - // Fire three deletes in quick succession. - goog.testing.events.fireKeySequence(field1.getElement(), - goog.events.KeyCodes.DELETE); - goog.testing.events.fireKeySequence(field1.getElement(), - goog.events.KeyCodes.DELETE); - goog.testing.events.fireKeySequence(field1.getElement(), - goog.events.KeyCodes.DELETE); - assertEquals('Should have deleted all the
    \'s and the blockquote ' + - 'isn\'t affected', - '
    foo
    ', - field1.getElement().innerHTML); - var range = field1.getRange(); - assertEquals('The selected range should be contained within the ' + - '
    ', - goog.dom.TagName.BLOCKQUOTE, - range.getContainerElement().tagName); - assertTrue('The selected range should be collapsed', range.isCollapsed()); - var focusNode = range.getFocusNode(); - assertTrue('The focus node should be the text node "foo"', - (focusNode.nodeType == goog.dom.NodeType.TEXT && - focusNode.data == 'foo')); - assertEquals('The focus offset should be at the ' + - 'beginning of the text node "foo"', - 0, - range.getFocusOffset()); - } -} - - -/** - * Tests that deleting a BR is working normally (that the workaround for the - * bug is not causing double deletes). - * @bug 1471096 - */ -function testDeleteBrNormal() { - setUpFields(true); - - // This test only works on Gecko, because it's testing for manual deletion of - // BR tags, which is done only for Gecko. For other browsers we fall through - // and let the browser do the delete, which can only be tested with a robot - // test (see javascript/apps/editor/tests/delete_br_robot.html). - if (goog.userAgent.GECKO) { - - field1.setHtml(false, 'one


    two'); - var helper = new goog.testing.editor.TestHelper(field1.getElement()); - helper.select(field1.getElement(), 2); // Between the first and second BR's. - field1.getElement().focus(); - goog.testing.events.fireKeySequence(field1.getElement(), - goog.events.KeyCodes.DELETE); - assertEquals('Should have deleted exactly one
    ', - 'one

    two', - field1.getElement().innerHTML); - - } // End if GECKO -} - - -/** - * Tests that deleteCursorSelectionW3C_ correctly recognizes visually - * collapsed selections in Opera even if they contain a
    . - * See the deleteCursorSelectionW3C_ comment in enterhandler.js. - */ -function testCollapsedSelectionKeepsBrOpera() { - setUpFields(true); - - if (goog.userAgent.OPERA) { - field1.setHtml(false, '

    '); - field1.focus(); - goog.testing.events.fireKeySequence(field1.getElement(), - goog.events.KeyCodes.ENTER); - assertNotNull('The
    must not have been deleted', - goog.dom.getElement('pleasedontdeleteme')); - } -} - - -/** - * Selects the node at the given id, and simulates an ENTER keypress. - * @param {goog.editor.Field} field The field with the node. - * @param {string} id A DOM id. - * @return {boolean} Whether preventDefault was called on the event. - */ -function selectNodeAndHitEnter(field, id) { - var dom = field.getEditableDomHelper(); - var cursor = dom.getElement(id); - goog.dom.Range.createFromNodeContents(cursor).select(); - return goog.testing.events.fireKeySequence( - cursor, goog.events.KeyCodes.ENTER); -} - - -/** - * Creates a field with only the enter handler plugged in, for testing. - * @param {string} id A DOM id. - * @return {goog.editor.Field} A field. - */ -function makeField(id, classnameRequiredToSplitBlockquote) { - var field = new goog.editor.Field(id); - field.registerPlugin(new goog.editor.plugins.EnterHandler()); - field.registerPlugin(new goog.editor.plugins.Blockquote( - classnameRequiredToSplitBlockquote)); - - goog.events.listen(field, goog.editor.Field.EventType.BEFORECHANGE, - function() { - // set the global flag that beforechange was fired. - firedBeforeChange = true; - }); - goog.events.listen(field, goog.editor.Field.EventType.DELAYEDCHANGE, - function() { - // set the global flag that delayed change was fired. - firedDelayedChange = true; - }); - - return field; -} - - -/** - * Reset all the global flags related to change events. - */ -function resetChangeFlags() { - waitForChangeEvents(); - firedBeforeChange = firedDelayedChange = false; -} - - -/** - * Asserts that both change flags were fired since the last reset. - */ -function assertChangeFlags() { - assert('Beforechange should have fired', firedBeforeChange); - assert('Delayedchange should have fired', firedDelayedChange); -} - - -/** - * Wait for delayedchange to propagate. - */ -function waitForChangeEvents() { - clock.tick(goog.editor.Field.DELAYED_CHANGE_FREQUENCY + - goog.editor.Field.CHANGE_FREQUENCY); -} - -function getNbsp() { - // On WebKit (pre-528) and Opera,   shows up as its unicode character in - // innerHTML under some circumstances. - return (goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher('528')) || - goog.userAgent.OPERA ? '\u00a0' : ' '; -} - - -function testPrepareContent() { - setUpFields(true); - assertPreparedContents('hi', 'hi'); - assertPreparedContents( - goog.editor.BrowserFeature.COLLAPSES_EMPTY_NODES ? '
    ' : '', ' '); -} - - -/** - * Assert that the prepared contents matches the expected. - */ -function assertPreparedContents(expected, original) { - assertEquals(expected, - field1.reduceOp_( - goog.editor.Plugin.Op.PREPARE_CONTENTS_HTML, original)); -} - -// UTILITY FUNCTION TESTS. - -function testDeleteW3CSimple() { - if (goog.editor.BrowserFeature.HAS_W3C_RANGES) { - container.innerHTML = '
    abcd
    '; - var range = goog.dom.Range.createFromNodes(container.firstChild.firstChild, - 1, container.firstChild.firstChild, 3); - range.select(); - goog.editor.plugins.EnterHandler.deleteW3cRange_(range); - - goog.testing.dom.assertHtmlContentsMatch('
    ad
    ', container); - } -} - -function testDeleteW3CAll() { - if (goog.editor.BrowserFeature.HAS_W3C_RANGES) { - container.innerHTML = '
    abcd
    '; - var range = goog.dom.Range.createFromNodes(container.firstChild.firstChild, - 0, container.firstChild.firstChild, 4); - range.select(); - goog.editor.plugins.EnterHandler.deleteW3cRange_(range); - - goog.testing.dom.assertHtmlContentsMatch('
     
    ', container); - } -} - -function testDeleteW3CPartialEnd() { - if (goog.editor.BrowserFeature.HAS_W3C_RANGES) { - container.innerHTML = '
    ab
    cd
    '; - var range = goog.dom.Range.createFromNodes(container.firstChild.firstChild, - 1, container.lastChild.firstChild, 1); - range.select(); - goog.editor.plugins.EnterHandler.deleteW3cRange_(range); - - goog.testing.dom.assertHtmlContentsMatch('
    ad
    ', container); - } -} - -function testDeleteW3CNonPartialEnd() { - if (goog.editor.BrowserFeature.HAS_W3C_RANGES) { - container.innerHTML = '
    ab
    cd
    '; - var range = goog.dom.Range.createFromNodes(container.firstChild.firstChild, - 1, container.lastChild.firstChild, 2); - range.select(); - goog.editor.plugins.EnterHandler.deleteW3cRange_(range); - - goog.testing.dom.assertHtmlContentsMatch('
    a
    ', container); - } -} - -function testIsInOneContainer() { - if (goog.editor.BrowserFeature.HAS_W3C_RANGES) { - container.innerHTML = '

    '; - var div = container.firstChild; - var range = goog.dom.Range.createFromNodes(div, 0, div, 1); - range.select(); - assertTrue('Selection must be recognized as being in one container', - goog.editor.plugins.EnterHandler.isInOneContainerW3c_(range)); - } -} - -function testDeletingEndNodesWithNoNewLine() { - if (goog.editor.BrowserFeature.HAS_W3C_RANGES) { - container.innerHTML = - 'a
    b

    c
    d
    '; - var range = goog.dom.Range.createFromNodes( - container.childNodes[2], 0, container.childNodes[4].childNodes[0], 1); - range.select(); - var newRange = goog.editor.plugins.EnterHandler.deleteW3cRange_(range); - goog.testing.dom.assertHtmlContentsMatch('a
    b
    ', container); - assertTrue(newRange.isCollapsed()); - assertEquals(container, newRange.getStartNode()); - assertEquals(2, newRange.getStartOffset()); - } -} diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/firststrong.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/firststrong.js deleted file mode 100644 index 7342badd34f..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/firststrong.js +++ /dev/null @@ -1,334 +0,0 @@ -// Copyright 2012 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview A plugin to enable the First Strong Bidi algorithm. The First - * Strong algorithm as a heuristic used to automatically set paragraph direction - * depending on its content. - * - * In the documentation below, a 'paragraph' is the local element which we - * evaluate as a whole for purposes of determining directionality. It may be a - * block-level element (e.g. <div>) or a whole list (e.g. <ul>). - * - * This implementation is based on, but is not identical to, the original - * First Strong algorithm defined in Unicode - * @see http://www.unicode.org/reports/tr9/ - * The central difference from the original First Strong algorithm is that this - * implementation decides the paragraph direction based on the first strong - * character that is typed into the paragraph, regardless of its - * location in the paragraph, as opposed to the original algorithm where it is - * the first character in the paragraph by location, regardless of - * whether other strong characters already appear in the paragraph, further its - * start. - * - * Please note that this plugin does not perform the direction change - * itself. Rather, it fires editor commands upon the key up event when a - * direction change needs to be performed; {@code goog.editor.Command.DIR_RTL} - * or {@code goog.editor.Command.DIR_RTL}. - * - */ - -goog.provide('goog.editor.plugins.FirstStrong'); - -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.TagIterator'); -goog.require('goog.dom.TagName'); -goog.require('goog.editor.Command'); -goog.require('goog.editor.Field'); -goog.require('goog.editor.Plugin'); -goog.require('goog.editor.node'); -goog.require('goog.editor.range'); -goog.require('goog.i18n.bidi'); -goog.require('goog.i18n.uChar'); -goog.require('goog.iter'); -goog.require('goog.userAgent'); - - - -/** - * First Strong plugin. - * @constructor - * @extends {goog.editor.Plugin} - * @final - */ -goog.editor.plugins.FirstStrong = function() { - goog.editor.plugins.FirstStrong.base(this, 'constructor'); - - /** - * Indicates whether or not the cursor is in a paragraph we have not yet - * finished evaluating for directionality. This is set to true whenever the - * cursor is moved, and set to false after seeing a strong character in the - * paragraph the cursor is currently in. - * - * @type {boolean} - * @private - */ - this.isNewBlock_ = true; - - /** - * Indicates whether or not the current paragraph the cursor is in should be - * set to Right-To-Left directionality. - * - * @type {boolean} - * @private - */ - this.switchToRtl_ = false; - - /** - * Indicates whether or not the current paragraph the cursor is in should be - * set to Left-To-Right directionality. - * - * @type {boolean} - * @private - */ - this.switchToLtr_ = false; -}; -goog.inherits(goog.editor.plugins.FirstStrong, goog.editor.Plugin); - - -/** @override */ -goog.editor.plugins.FirstStrong.prototype.getTrogClassId = function() { - return 'FirstStrong'; -}; - - -/** @override */ -goog.editor.plugins.FirstStrong.prototype.queryCommandValue = - function(command) { - return false; -}; - - -/** @override */ -goog.editor.plugins.FirstStrong.prototype.handleSelectionChange = - function(e, node) { - this.isNewBlock_ = true; - return false; -}; - - -/** - * The name of the attribute which records the input text. - * - * @type {string} - * @const - */ -goog.editor.plugins.FirstStrong.INPUT_ATTRIBUTE = 'fs-input'; - - -/** @override */ -goog.editor.plugins.FirstStrong.prototype.handleKeyPress = function(e) { - if (goog.editor.Field.SELECTION_CHANGE_KEYCODES[e.keyCode]) { - // Key triggered selection change event (e.g. on ENTER) is throttled and a - // later LTR/RTL strong keypress may come before it. Need to capture it. - this.isNewBlock_ = true; - return false; // A selection-changing key is not LTR/RTL strong. - } - if (!this.isNewBlock_) { - return false; // We've already determined this paragraph's direction. - } - // Ignore non-character key press events. - if (e.ctrlKey || e.metaKey) { - return false; - } - var newInput = goog.i18n.uChar.fromCharCode(e.charCode); - - // IME's may return 0 for the charCode, which is a legitimate, non-Strong - // charCode, or they may return an illegal charCode (for which newInput will - // be false). - if (!newInput || !e.charCode) { - var browserEvent = e.getBrowserEvent(); - if (browserEvent) { - if (goog.userAgent.IE && browserEvent['getAttribute']) { - newInput = browserEvent['getAttribute']( - goog.editor.plugins.FirstStrong.INPUT_ATTRIBUTE); - } else { - newInput = browserEvent[ - goog.editor.plugins.FirstStrong.INPUT_ATTRIBUTE]; - } - } - } - - if (!newInput) { - return false; // Unrecognized key. - } - - var isLtr = goog.i18n.bidi.isLtrChar(newInput); - var isRtl = !isLtr && goog.i18n.bidi.isRtlChar(newInput); - if (!isLtr && !isRtl) { - return false; // This character cannot change anything (it is not Strong). - } - // This character is Strongly LTR or Strongly RTL. We might switch direction - // on it now, but in any case we do not need to check any more characters in - // this paragraph after it. - this.isNewBlock_ = false; - - // Are there no Strong characters already in the paragraph? - if (this.isNeutralBlock_()) { - this.switchToRtl_ = isRtl; - this.switchToLtr_ = isLtr; - } - return false; -}; - - -/** - * Calls the flip directionality commands. This is done here so things go into - * the redo-undo stack at the expected order; fist enter the input, then flip - * directionality. - * @override - */ -goog.editor.plugins.FirstStrong.prototype.handleKeyUp = function(e) { - if (this.switchToRtl_) { - var field = this.getFieldObject(); - field.dispatchChange(true); - field.execCommand(goog.editor.Command.DIR_RTL); - this.switchToRtl_ = false; - } else if (this.switchToLtr_) { - var field = this.getFieldObject(); - field.dispatchChange(true); - field.execCommand(goog.editor.Command.DIR_LTR); - this.switchToLtr_ = false; - } - return false; -}; - - -/** - * @return {Element} The lowest Block element ancestor of the node where the - * next character will be placed. - * @private - */ -goog.editor.plugins.FirstStrong.prototype.getBlockAncestor_ = function() { - var start = this.getFieldObject().getRange().getStartNode(); - // Go up in the DOM until we reach a Block element. - while (!goog.editor.plugins.FirstStrong.isBlock_(start)) { - start = start.parentNode; - } - return /** @type {Element} */ (start); -}; - - -/** - * @return {boolean} Whether the paragraph where the next character will be - * entered contains only non-Strong characters. - * @private - */ -goog.editor.plugins.FirstStrong.prototype.isNeutralBlock_ = function() { - var root = this.getBlockAncestor_(); - // The exact node with the cursor location. Simply calling getStartNode() on - // the range only returns the containing block node. - var cursor = goog.editor.range.getDeepEndPoint( - this.getFieldObject().getRange(), false).node; - - // In FireFox the BR tag also represents a change in paragraph if not inside a - // list. So we need special handling to only look at the sub-block between - // BR elements. - var blockFunction = (goog.userAgent.GECKO && - !this.isList_(root)) ? - goog.editor.plugins.FirstStrong.isGeckoBlock_ : - goog.editor.plugins.FirstStrong.isBlock_; - var paragraph = this.getTextAround_(root, cursor, - blockFunction); - // Not using {@code goog.i18n.bidi.isNeutralText} as it contains additional, - // unwanted checks to the content. - return !goog.i18n.bidi.hasAnyLtr(paragraph) && - !goog.i18n.bidi.hasAnyRtl(paragraph); -}; - - -/** - * Checks if an element is a list element ('UL' or 'OL'). - * - * @param {Element} element The element to test. - * @return {boolean} Whether the element is a list element ('UL' or 'OL'). - * @private - */ -goog.editor.plugins.FirstStrong.prototype.isList_ = function(element) { - if (!element) { - return false; - } - var tagName = element.tagName; - return tagName == goog.dom.TagName.UL || tagName == goog.dom.TagName.OL; -}; - - -/** - * Returns the text within the local paragraph around the cursor. - * Notice that for GECKO a BR represents a pargraph change despite not being a - * block element. - * - * @param {Element} root The first block element ancestor of the node the cursor - * is in. - * @param {Node} cursorLocation Node where the cursor currently is, marking the - * paragraph whose text we will return. - * @param {function(Node): boolean} isParagraphBoundary The function to - * determine if a node represents the start or end of the paragraph. - * @return {string} the text in the paragraph around the cursor location. - * @private - */ -goog.editor.plugins.FirstStrong.prototype.getTextAround_ = function(root, - cursorLocation, isParagraphBoundary) { - // The buffer where we're collecting the text. - var buffer = []; - // Have we reached the cursor yet, or are we still before it? - var pastCursorLocation = false; - - if (root && cursorLocation) { - goog.iter.some(new goog.dom.TagIterator(root), function(node) { - if (node == cursorLocation) { - pastCursorLocation = true; - } else if (isParagraphBoundary(node)) { - if (pastCursorLocation) { - // This is the end of the paragraph containing the cursor. We're done. - return true; - } else { - // All we collected so far does not count; it was in a previous - // paragraph that did not contain the cursor. - buffer = []; - } - } - if (node.nodeType == goog.dom.NodeType.TEXT) { - buffer.push(node.nodeValue); - } - return false; // Keep going. - }); - } - return buffer.join(''); -}; - - -/** - * @param {Node} node Node to check. - * @return {boolean} Does the given node represent a Block element? Notice we do - * not consider list items as Block elements in the algorithm. - * @private - */ -goog.editor.plugins.FirstStrong.isBlock_ = function(node) { - return !!node && goog.editor.node.isBlockTag(node) && - node.tagName != goog.dom.TagName.LI; -}; - - -/** - * @param {Node} node Node to check. - * @return {boolean} Does the given node represent a Block element from the - * point of view of FireFox? Notice we do not consider list items as Block - * elements in the algorithm. - * @private - */ -goog.editor.plugins.FirstStrong.isGeckoBlock_ = function(node) { - return !!node && (node.tagName == goog.dom.TagName.BR || - goog.editor.plugins.FirstStrong.isBlock_(node)); -}; diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/firststrong_test.html b/src/database/third_party/closure-library/closure/goog/editor/plugins/firststrong_test.html deleted file mode 100644 index ad18959922f..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/firststrong_test.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - Trogedit Unit Tests - goog.editor.plugins.FirstStrong - - - - - -
    -
    -
    -
    - - diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/firststrong_test.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/firststrong_test.js deleted file mode 100644 index 9dc8530ab6c..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/firststrong_test.js +++ /dev/null @@ -1,450 +0,0 @@ -// Copyright 2012 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.editor.plugins.FirstStrongTest'); -goog.setTestOnly('goog.editor.plugins.FirstStrongTest'); - -goog.require('goog.dom.Range'); -goog.require('goog.editor.Command'); -goog.require('goog.editor.Field'); -goog.require('goog.editor.plugins.FirstStrong'); -goog.require('goog.editor.range'); -goog.require('goog.events.KeyCodes'); -goog.require('goog.testing.MockClock'); -goog.require('goog.testing.editor.TestHelper'); -goog.require('goog.testing.events'); -goog.require('goog.testing.jsunit'); -goog.require('goog.userAgent'); - -// The key code for the Hebrew א, a strongly RTL letter. -var ALEPH_KEYCODE = 1488; -var field; -var fieldElement; -var dom; -var helper; -var triggeredCommand = null; -var clock; - -function setUp() { - field = new goog.editor.Field('field'); - field.registerPlugin(new goog.editor.plugins.FirstStrong()); - field.makeEditable(); - - fieldElement = field.getElement(); - - helper = new goog.testing.editor.TestHelper(fieldElement); - - dom = field.getEditableDomHelper(); - - // Mock out execCommand to see if a direction change has been triggered. - field.execCommand = function(command) { - if (command == goog.editor.Command.DIR_LTR || - command == goog.editor.Command.DIR_RTL) - triggeredCommand = command; - }; -} - -function tearDown() { - goog.dispose(field); - goog.dispose(helper); - triggeredCommand = null; - goog.dispose(clock); // Make sure clock is disposed. - -} - -function testFirstCharacter_RTL() { - field.setHtml(false, '
     
    '); - field.focusAndPlaceCursorAtStart(); - goog.testing.events.fireNonAsciiKeySequence(fieldElement, - goog.events.KeyCodes.T, ALEPH_KEYCODE); - assertRTL(); -} - -function testFirstCharacter_LTR() { - field.setHtml(false, '
     
    '); - field.focusAndPlaceCursorAtStart(); - goog.testing.events.fireKeySequence(fieldElement, - goog.events.KeyCodes.A); - assertLTR(); -} - -function testFirstStrongCharacter_RTL() { - field.setHtml(false, '
    123.7 3121, <++{}> - $45
    '); - field.focusAndPlaceCursorAtStart(); - goog.testing.events.fireNonAsciiKeySequence(fieldElement, - goog.events.KeyCodes.T, ALEPH_KEYCODE); - assertRTL(); -} - -function testFirstStrongCharacter_LTR() { - field.setHtml(false, - '
    123.7 3121, <++{}> - $45
    '); - field.focusAndPlaceCursorAtStart(); - goog.testing.events.fireKeySequence(fieldElement, - goog.events.KeyCodes.A); - assertLTR(); -} - -function testNotStrongCharacter_RTL() { - field.setHtml(false, '
    123.7 3121, - $45
    '); - field.focusAndPlaceCursorAtStart(); - goog.testing.events.fireKeySequence(fieldElement, goog.events.KeyCodes.NINE); - assertNoCommand(); -} - -function testNotStrongCharacter_LTR() { - field.setHtml(false, '
    123.7 3121 $45
    '); - field.focusAndPlaceCursorAtStart(); - goog.testing.events.fireKeySequence(fieldElement, goog.events.KeyCodes.NINE); - assertNoCommand(); -} - -function testNotFirstStrongCharacter_RTL() { - field.setHtml(false, '
    123.7 3121, English - $45
    '); - field.focusAndPlaceCursorAtStart(); - goog.testing.events.fireNonAsciiKeySequence(fieldElement, - goog.events.KeyCodes.T, ALEPH_KEYCODE); - assertNoCommand(); -} - -function testNotFirstStrongCharacter_LTR() { - field.setHtml(false, - '
    123.7 3121, עברית - $45
    '); - field.focusAndPlaceCursorAtStart(); - goog.testing.events.fireKeySequence(fieldElement, - goog.events.KeyCodes.A); - assertNoCommand(); -} - -function testFirstStrongCharacterWithInnerDiv_RTL() { - field.setHtml(false, - '
    123.7 3121, <++{}>' + - '
    English
    ' + - '
    '); - field.focusAndPlaceCursorAtStart(); - goog.testing.events.fireNonAsciiKeySequence(fieldElement, - goog.events.KeyCodes.T, ALEPH_KEYCODE); - assertRTL(); -} - -function testFirstStrongCharacterWithInnerDiv_LTR() { - field.setHtml(false, - '
    123.7 3121, <++{}>' + - '
    English
    ' + - '
    '); - field.focusAndPlaceCursorAtStart(); - goog.testing.events.fireKeySequence(fieldElement, - goog.events.KeyCodes.A); - assertLTR(); -} - - -/** - * Regression test for {@link http://b/7549696} - */ -function testFirstStrongCharacterInNewLine_RTL() { - field.setHtml(false, '
    English
    1
    '); - goog.dom.Range.createCaret(dom.$('cur'), 2).select(); - - goog.testing.events.fireNonAsciiKeySequence(fieldElement, - goog.events.KeyCodes.T, ALEPH_KEYCODE); - // Only GECKO treats
    as a new paragraph. - if (goog.userAgent.GECKO) { - assertRTL(); - } else { - assertNoCommand(); - } -} - -function testFirstStrongCharacterInParagraph_RTL() { - field.setHtml(false, - '
    1> English
    ' + - '
    2>
    ' + - '
    3>
    '); - goog.dom.Range.createCaret(dom.$('text2'), 0).select(); - - goog.testing.events.fireNonAsciiKeySequence(fieldElement, - goog.events.KeyCodes.T, ALEPH_KEYCODE); - assertRTL(); -} - -function testFirstStrongCharacterInParagraph_LTR() { - field.setHtml(false, - '
    1> עברית
    ' + - '
    2>
    ' + - '
    3>
    '); - goog.dom.Range.createCaret(dom.$('text2'), 0).select(); - - goog.testing.events.fireKeySequence(fieldElement, - goog.events.KeyCodes.A); - assertLTR(); -} - -function testFirstStrongCharacterInList_RTL() { - field.setHtml(false, - '
    1> English
    ' + - '
      ' + - '
    • 10>
    • ' + - '
    • ' + - '
    • 30
    • ' + - '
    ' + - '
    3>
    '); - goog.editor.range.placeCursorNextTo(dom.$('li2'), true); - - goog.testing.events.fireNonAsciiKeySequence(fieldElement, - goog.events.KeyCodes.T, ALEPH_KEYCODE); - assertRTL(); -} - -function testFirstStrongCharacterInList_LTR() { - field.setHtml(false, - '
    1> English
    ' + - '
      ' + - '
    • 10>
    • ' + - '
    • ' + - '
    • 30
    • ' + - '
    ' + - '
    3>
    '); - goog.editor.range.placeCursorNextTo(dom.$('li2'), true); - - goog.testing.events.fireKeySequence(fieldElement, - goog.events.KeyCodes.A); - assertLTR(); -} - -function testNotFirstStrongCharacterInList_RTL() { - field.setHtml(false, - '
    1
    ' + - '
      ' + - '
    • 10>
    • ' + - '
    • ' + - '
    • 303Hidden English32
    • ' + - '
    ' + - '
    3>
    '); - goog.editor.range.placeCursorNextTo(dom.$('li2'), true); - - goog.testing.events.fireNonAsciiKeySequence(fieldElement, - goog.events.KeyCodes.T, ALEPH_KEYCODE); - assertNoCommand(); -} - -function testNotFirstStrongCharacterInList_LTR() { - field.setHtml(false, - '
    1> English
    ' + - '
      ' + - '
    • 10>
    • ' + - '
    • ' + - '
    • 303עברית סמויה32
    • ' + - '
    ' + - '
    3>
    '); - goog.editor.range.placeCursorNextTo(dom.$('li2'), true); - - goog.testing.events.fireKeySequence(fieldElement, - goog.events.KeyCodes.A); - assertNoCommand(); -} - -function testFirstStrongCharacterWithBR_RTL() { - field.setHtml(false, - '
    ' + - '
    ABC
    ' + - '
    ' + - '1
    ' + - '2345
    ' + - '6
    7
    89
    ' + - '10' + - '
    ' + - '
    11
    ' + - '
    '); - - goog.editor.range.placeCursorNextTo(dom.$('inner'), true); - goog.testing.events.fireNonAsciiKeySequence(fieldElement, - goog.events.KeyCodes.T, ALEPH_KEYCODE); - assertRTL(); -} - -function testFirstStrongCharacterWithBR_LTR() { - field.setHtml(false, - '
    ' + - '
    אבג
    ' + - '
    ' + - '1
    ' + - '2345
    ' + - '6
    7
    8
    9
    ' + - '10' + - '
    ' + - '
    11
    ' + - '
    '); - - goog.editor.range.placeCursorNextTo(dom.$('inner'), true); - goog.testing.events.fireKeySequence(fieldElement, - goog.events.KeyCodes.A); - assertLTR(); -} - -function testNotFirstStrongCharacterInBR_RTL() { - field.setHtml(false, - '
    ' + - '
    ABC
    ' + - '
    ' + - '1
    ' + - '234G5
    ' + - '6
    7
    89
    ' + - '10' + - '
    ' + - '
    11
    ' + - '
    '); - - goog.editor.range.placeCursorNextTo(dom.$('inner'), true); - goog.testing.events.fireNonAsciiKeySequence(fieldElement, - goog.events.KeyCodes.T, ALEPH_KEYCODE); - assertNoCommand(); -} - -function testNotFirstStrongCharacterInBR_LTR() { - field.setHtml(false, - '
    ' + - '
    ABC
    ' + - '
    ' + - '1
    ' + - '234G5
    ' + - '6
    7
    89
    ' + - '10' + - '
    ' + - '
    11
    ' + - '
    '); - - goog.editor.range.placeCursorNextTo(dom.$('inner'), true); - goog.testing.events.fireKeySequence(fieldElement, - goog.events.KeyCodes.A); - assertNoCommand(); -} - - -/** - * Regression test for {@link http://b/7530985} - */ -function testFirstStrongCharacterWithPreviousBlockSibling_RTL() { - field.setHtml(false, '
    Te
    xt
    123
    '); - goog.editor.range.placeCursorNextTo(dom.$('cur'), true); - goog.testing.events.fireNonAsciiKeySequence(fieldElement, - goog.events.KeyCodes.T, ALEPH_KEYCODE); - assertRTL(); -} - -function testFirstStrongCharacterWithPreviousBlockSibling_LTR() { - field.setHtml( - false, '
    טק
    סט
    123
    '); - goog.editor.range.placeCursorNextTo(dom.$('cur'), true); - goog.testing.events.fireKeySequence(fieldElement, goog.events.KeyCodes.A); - assertLTR(); -} - -function testFirstStrongCharacterWithFollowingBlockSibling_RTL() { - field.setHtml(false, '
    123
    Te
    xt
    '); - goog.editor.range.placeCursorNextTo(dom.$('cur'), true); - goog.testing.events.fireNonAsciiKeySequence(fieldElement, - goog.events.KeyCodes.T, ALEPH_KEYCODE); - assertRTL(); -} - -function testFirstStrongCharacterWithFollowingBlockSibling_RTL() { - field.setHtml(false, '
    123
    א
    ב
    '); - goog.editor.range.placeCursorNextTo(dom.$('cur'), true); - goog.testing.events.fireKeySequence(fieldElement, goog.events.KeyCodes.A); - assertLTR(); -} - -function testFirstStrongCharacterFromIME_RTL() { - field.setHtml(false, '
    123.7 3121,
    '); - field.focusAndPlaceCursorAtStart(); - var attributes = {}; - attributes[goog.editor.plugins.FirstStrong.INPUT_ATTRIBUTE] = 'אבג'; - goog.testing.events.fireNonAsciiKeySequence(fieldElement, 0, 0, attributes); - if (goog.userAgent.IE) { - // goog.testing.events.fireNonAsciiKeySequence doesn't send KEYPRESS event - // so no command is expected. - assertNoCommand(); - } else { - assertRTL(); - } -} - -function testFirstCharacterFromIME_LTR() { - field.setHtml(false, '
    1234
    '); - field.focusAndPlaceCursorAtStart(); - var attributes = {}; - attributes[goog.editor.plugins.FirstStrong.INPUT_ATTRIBUTE] = 'ABC'; - goog.testing.events.fireNonAsciiKeySequence(fieldElement, 0, 0, attributes); - if (goog.userAgent.IE) { - // goog.testing.events.fireNonAsciiKeySequence doesn't send KEYPRESS event - // so no command is expected. - assertNoCommand(); - } else { - assertLTR(); - } -} - - -/** - * Regression test for {@link http://b/19297723} - */ -function testLTRShortlyAfterRTLAndEnter() { - clock = new goog.testing.MockClock(); - field.focusAndPlaceCursorAtStart(); - goog.testing.events.fireNonAsciiKeySequence(fieldElement, - goog.events.KeyCodes.T, ALEPH_KEYCODE); - assertRTL(); - clock.tick(1000); // Make sure no pending selection change event. - goog.testing.events.fireKeySequence(fieldElement, goog.events.KeyCodes.ENTER); - assertRTL(); - goog.testing.events.fireKeySequence(fieldElement, goog.events.KeyCodes.A); - assertLTR(); - // Verify no RTL for first keypress on already-striong paragraph after - // delayed selection change event. - clock.tick(1000); // Let delayed selection change event fire. - goog.testing.events.fireNonAsciiKeySequence(fieldElement, - goog.events.KeyCodes.T, ALEPH_KEYCODE); - assertLTR(); -} - -function testRTLShortlyAfterLTRAndEnter() { - clock = new goog.testing.MockClock(); - field.focusAndPlaceCursorAtStart(); - goog.testing.events.fireKeySequence(fieldElement, goog.events.KeyCodes.A); - assertLTR(); - clock.tick(1000); // Make sure no pending selection change event. - goog.testing.events.fireKeySequence(fieldElement, goog.events.KeyCodes.ENTER); - assertLTR(); - goog.testing.events.fireNonAsciiKeySequence(fieldElement, - goog.events.KeyCodes.T, ALEPH_KEYCODE); - assertRTL(); - // Verify no LTR for first keypress on already-strong paragraph after - // delayed selection change event. - clock.tick(1000); // Let delayed selection change event fire. - goog.testing.events.fireKeySequence(fieldElement, goog.events.KeyCodes.A); - assertRTL(); -} - -function assertRTL() { - assertEquals(goog.editor.Command.DIR_RTL, triggeredCommand); -} - -function assertLTR() { - assertEquals(goog.editor.Command.DIR_LTR, triggeredCommand); -} - -function assertNoCommand() { - assertNull(triggeredCommand); -} diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/headerformatter.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/headerformatter.js deleted file mode 100644 index fa4bb1f76d7..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/headerformatter.js +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Handles applying header styles to text. - * - */ - -goog.provide('goog.editor.plugins.HeaderFormatter'); - -goog.require('goog.editor.Command'); -goog.require('goog.editor.Plugin'); -goog.require('goog.userAgent'); - - - -/** - * Applies header styles to text. - * @constructor - * @extends {goog.editor.Plugin} - * @final - */ -goog.editor.plugins.HeaderFormatter = function() { - goog.editor.Plugin.call(this); -}; -goog.inherits(goog.editor.plugins.HeaderFormatter, goog.editor.Plugin); - - -/** @override */ -goog.editor.plugins.HeaderFormatter.prototype.getTrogClassId = function() { - return 'HeaderFormatter'; -}; - -// TODO(user): Move execCommand functionality from basictextformatter into -// here for headers. I'm not doing this now because it depends on the -// switch statements in basictextformatter and we'll need to abstract that out -// in order to seperate out any of the functions from basictextformatter. - - -/** - * Commands that can be passed as the optional argument to execCommand. - * @enum {string} - */ -goog.editor.plugins.HeaderFormatter.HEADER_COMMAND = { - H1: 'H1', - H2: 'H2', - H3: 'H3', - H4: 'H4' -}; - - -/** - * @override - */ -goog.editor.plugins.HeaderFormatter.prototype.handleKeyboardShortcut = function( - e, key, isModifierPressed) { - if (!isModifierPressed) { - return false; - } - var command = null; - switch (key) { - case '1': - command = goog.editor.plugins.HeaderFormatter.HEADER_COMMAND.H1; - break; - case '2': - command = goog.editor.plugins.HeaderFormatter.HEADER_COMMAND.H2; - break; - case '3': - command = goog.editor.plugins.HeaderFormatter.HEADER_COMMAND.H3; - break; - case '4': - command = goog.editor.plugins.HeaderFormatter.HEADER_COMMAND.H4; - break; - } - if (command) { - this.getFieldObject().execCommand( - goog.editor.Command.FORMAT_BLOCK, command); - // Prevent default isn't enough to cancel tab navigation in FF. - if (goog.userAgent.GECKO) { - e.stopPropagation(); - } - return true; - } - return false; -}; diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/headerformatter_test.html b/src/database/third_party/closure-library/closure/goog/editor/plugins/headerformatter_test.html deleted file mode 100644 index 128dba4a7bd..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/headerformatter_test.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - goog.editor.plugins.HeaderFormatter Tests - - - - - -
    -
    - - diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/headerformatter_test.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/headerformatter_test.js deleted file mode 100644 index 71688ee2ed3..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/headerformatter_test.js +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.editor.plugins.HeaderFormatterTest'); -goog.setTestOnly('goog.editor.plugins.HeaderFormatterTest'); - -goog.require('goog.dom'); -goog.require('goog.editor.Command'); -goog.require('goog.editor.plugins.BasicTextFormatter'); -goog.require('goog.editor.plugins.HeaderFormatter'); -goog.require('goog.events.BrowserEvent'); -goog.require('goog.testing.LooseMock'); -goog.require('goog.testing.editor.FieldMock'); -goog.require('goog.testing.editor.TestHelper'); -goog.require('goog.testing.jsunit'); -goog.require('goog.userAgent'); - -var field; -var editableField; -var headerFormatter; -var btf; -var testHelper; - -function setUpPage() { - field = goog.dom.getElement('field'); - testHelper = new goog.testing.editor.TestHelper(field); -} - -function setUp() { - testHelper.setUpEditableElement(); - editableField = new goog.testing.editor.FieldMock(); - headerFormatter = new goog.editor.plugins.HeaderFormatter(); - headerFormatter.registerFieldObject(editableField); - btf = new goog.editor.plugins.BasicTextFormatter(); - btf.registerFieldObject(editableField); -} - -function tearDown() { - editableField = null; - headerFormatter.dispose(); - testHelper.tearDownEditableElement(); -} - - -function testHeaderShortcuts() { - field.innerHTML = 'myText'; - - var textNode = field.firstChild; - testHelper.select(textNode, 0, textNode, textNode.length); - - editableField.getElement(); - editableField.$anyTimes(); - editableField.$returns(field); - - editableField.getPluginByClassId('Bidi'); - editableField.$anyTimes(); - editableField.$returns(null); - - editableField.execCommand( - goog.editor.Command.FORMAT_BLOCK, - goog.editor.plugins.HeaderFormatter.HEADER_COMMAND.H1); - // Bypass EditableField's execCommand and directly call - // basicTextFormatter's. Future version of headerformatter will include - // that code in its own execCommand. - editableField.$does(function() { - btf.execCommandInternal( - goog.editor.plugins.BasicTextFormatter.COMMAND.FORMAT_BLOCK, - goog.editor.plugins.HeaderFormatter.HEADER_COMMAND.H1); }); - - var event = new goog.testing.LooseMock(goog.events.BrowserEvent); - if (goog.userAgent.GECKO) { - event.stopPropagation(); - } - - editableField.$replay(); - event.$replay(); - - assertTrue('Event handled', - headerFormatter.handleKeyboardShortcut(event, '1', true)); - assertEquals('Field contains a header', 'H1', field.firstChild.nodeName); - - editableField.$verify(); - event.$verify(); -} diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/linkbubble.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/linkbubble.js deleted file mode 100644 index 01c84f3f116..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/linkbubble.js +++ /dev/null @@ -1,585 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Base class for bubble plugins. - * - */ - -goog.provide('goog.editor.plugins.LinkBubble'); -goog.provide('goog.editor.plugins.LinkBubble.Action'); - -goog.require('goog.array'); -goog.require('goog.dom'); -goog.require('goog.dom.TagName'); -goog.require('goog.editor.Command'); -goog.require('goog.editor.Link'); -goog.require('goog.editor.plugins.AbstractBubblePlugin'); -goog.require('goog.editor.range'); -goog.require('goog.functions'); -goog.require('goog.string'); -goog.require('goog.style'); -goog.require('goog.ui.editor.messages'); -goog.require('goog.uri.utils'); -goog.require('goog.window'); - - - -/** - * Property bubble plugin for links. - * @param {...!goog.editor.plugins.LinkBubble.Action} var_args List of - * extra actions supported by the bubble. - * @constructor - * @extends {goog.editor.plugins.AbstractBubblePlugin} - */ -goog.editor.plugins.LinkBubble = function(var_args) { - goog.editor.plugins.LinkBubble.base(this, 'constructor'); - - /** - * List of extra actions supported by the bubble. - * @type {Array} - * @private - */ - this.extraActions_ = goog.array.toArray(arguments); - - /** - * List of spans corresponding to the extra actions. - * @type {Array} - * @private - */ - this.actionSpans_ = []; - - /** - * A list of whitelisted URL schemes which are safe to open. - * @type {Array} - * @private - */ - this.safeToOpenSchemes_ = ['http', 'https', 'ftp']; -}; -goog.inherits(goog.editor.plugins.LinkBubble, - goog.editor.plugins.AbstractBubblePlugin); - - -/** - * Element id for the link text. - * type {string} - * @private - */ -goog.editor.plugins.LinkBubble.LINK_TEXT_ID_ = 'tr_link-text'; - - -/** - * Element id for the test link span. - * type {string} - * @private - */ -goog.editor.plugins.LinkBubble.TEST_LINK_SPAN_ID_ = 'tr_test-link-span'; - - -/** - * Element id for the test link. - * type {string} - * @private - */ -goog.editor.plugins.LinkBubble.TEST_LINK_ID_ = 'tr_test-link'; - - -/** - * Element id for the change link span. - * type {string} - * @private - */ -goog.editor.plugins.LinkBubble.CHANGE_LINK_SPAN_ID_ = 'tr_change-link-span'; - - -/** - * Element id for the link. - * type {string} - * @private - */ -goog.editor.plugins.LinkBubble.CHANGE_LINK_ID_ = 'tr_change-link'; - - -/** - * Element id for the delete link span. - * type {string} - * @private - */ -goog.editor.plugins.LinkBubble.DELETE_LINK_SPAN_ID_ = 'tr_delete-link-span'; - - -/** - * Element id for the delete link. - * type {string} - * @private - */ -goog.editor.plugins.LinkBubble.DELETE_LINK_ID_ = 'tr_delete-link'; - - -/** - * Element id for the link bubble wrapper div. - * type {string} - * @private - */ -goog.editor.plugins.LinkBubble.LINK_DIV_ID_ = 'tr_link-div'; - - -/** - * @desc Text label for link that lets the user click it to see where the link - * this bubble is for point to. - */ -goog.editor.plugins.LinkBubble.MSG_LINK_BUBBLE_TEST_LINK = goog.getMsg( - 'Go to link: '); - - -/** - * @desc Label that pops up a dialog to change the link. - */ -goog.editor.plugins.LinkBubble.MSG_LINK_BUBBLE_CHANGE = goog.getMsg( - 'Change'); - - -/** - * @desc Label that allow the user to remove this link. - */ -goog.editor.plugins.LinkBubble.MSG_LINK_BUBBLE_REMOVE = goog.getMsg( - 'Remove'); - - -/** - * @desc Message shown in a link bubble when the link is not a valid url. - */ -goog.editor.plugins.LinkBubble.MSG_INVALID_URL_LINK_BUBBLE = goog.getMsg( - 'invalid url'); - - -/** - * Whether to stop leaking the page's url via the referrer header when the - * link text link is clicked. - * @type {boolean} - * @private - */ -goog.editor.plugins.LinkBubble.prototype.stopReferrerLeaks_ = false; - - -/** - * Whether to block opening links with a non-whitelisted URL scheme. - * @type {boolean} - * @private - */ -goog.editor.plugins.LinkBubble.prototype.blockOpeningUnsafeSchemes_ = - true; - - -/** - * Tells the plugin to stop leaking the page's url via the referrer header when - * the link text link is clicked. When the user clicks on a link, the - * browser makes a request for the link url, passing the url of the current page - * in the request headers. If the user wants the current url to be kept secret - * (e.g. an unpublished document), the owner of the url that was clicked will - * see the secret url in the request headers, and it will no longer be a secret. - * Calling this method will not send a referrer header in the request, just as - * if the user had opened a blank window and typed the url in themselves. - */ -goog.editor.plugins.LinkBubble.prototype.stopReferrerLeaks = function() { - // TODO(user): Right now only 2 plugins have this API to stop - // referrer leaks. If more plugins need to do this, come up with a way to - // enable the functionality in all plugins at once. Same thing for - // setBlockOpeningUnsafeSchemes and associated functionality. - this.stopReferrerLeaks_ = true; -}; - - -/** - * Tells the plugin whether to block URLs with schemes not in the whitelist. - * If blocking is enabled, this plugin will not linkify the link in the bubble - * popup. - * @param {boolean} blockOpeningUnsafeSchemes Whether to block non-whitelisted - * schemes. - */ -goog.editor.plugins.LinkBubble.prototype.setBlockOpeningUnsafeSchemes = - function(blockOpeningUnsafeSchemes) { - this.blockOpeningUnsafeSchemes_ = blockOpeningUnsafeSchemes; -}; - - -/** - * Sets a whitelist of allowed URL schemes that are safe to open. - * Schemes should all be in lowercase. If the plugin is set to block opening - * unsafe schemes, user-entered URLs will be converted to lowercase and checked - * against this list. The whitelist has no effect if blocking is not enabled. - * @param {Array} schemes String array of URL schemes to allow (http, - * https, etc.). - */ -goog.editor.plugins.LinkBubble.prototype.setSafeToOpenSchemes = - function(schemes) { - this.safeToOpenSchemes_ = schemes; -}; - - -/** @override */ -goog.editor.plugins.LinkBubble.prototype.getTrogClassId = function() { - return 'LinkBubble'; -}; - - -/** @override */ -goog.editor.plugins.LinkBubble.prototype.isSupportedCommand = - function(command) { - return command == goog.editor.Command.UPDATE_LINK_BUBBLE; -}; - - -/** @override */ -goog.editor.plugins.LinkBubble.prototype.execCommandInternal = - function(command, var_args) { - if (command == goog.editor.Command.UPDATE_LINK_BUBBLE) { - this.updateLink_(); - } -}; - - -/** - * Updates the href in the link bubble with a new link. - * @private - */ -goog.editor.plugins.LinkBubble.prototype.updateLink_ = function() { - var targetEl = this.getTargetElement(); - if (targetEl) { - this.closeBubble(); - this.createBubble(targetEl); - } -}; - - -/** @override */ -goog.editor.plugins.LinkBubble.prototype.getBubbleTargetFromSelection = - function(selectedElement) { - var bubbleTarget = goog.dom.getAncestorByTagNameAndClass(selectedElement, - goog.dom.TagName.A); - - if (!bubbleTarget) { - // See if the selection is touching the right side of a link, and if so, - // show a bubble for that link. The check for "touching" is very brittle, - // and currently only guarantees that it will pop up a bubble at the - // position the cursor is placed at after the link dialog is closed. - // NOTE(robbyw): This assumes this method is always called with - // selected element = range.getContainerElement(). Right now this is true, - // but attempts to re-use this method for other purposes could cause issues. - // TODO(robbyw): Refactor this method to also take a range, and use that. - var range = this.getFieldObject().getRange(); - if (range && range.isCollapsed() && range.getStartOffset() == 0) { - var startNode = range.getStartNode(); - var previous = startNode.previousSibling; - if (previous && previous.tagName == goog.dom.TagName.A) { - bubbleTarget = previous; - } - } - } - - return /** @type {Element} */ (bubbleTarget); -}; - - -/** - * Set the optional function for getting the "test" link of a url. - * @param {function(string) : string} func The function to use. - */ -goog.editor.plugins.LinkBubble.prototype.setTestLinkUrlFn = function(func) { - this.testLinkUrlFn_ = func; -}; - - -/** - * Returns the target element url for the bubble. - * @return {string} The url href. - * @protected - */ -goog.editor.plugins.LinkBubble.prototype.getTargetUrl = function() { - // Get the href-attribute through getAttribute() rather than the href property - // because Google-Toolbar on Firefox with "Send with Gmail" turned on - // modifies the href-property of 'mailto:' links but leaves the attribute - // untouched. - return this.getTargetElement().getAttribute('href') || ''; -}; - - -/** @override */ -goog.editor.plugins.LinkBubble.prototype.getBubbleType = function() { - return goog.dom.TagName.A; -}; - - -/** @override */ -goog.editor.plugins.LinkBubble.prototype.getBubbleTitle = function() { - return goog.ui.editor.messages.MSG_LINK_CAPTION; -}; - - -/** - * Returns the message to display for testing a link. - * @return {string} The message for testing a link. - * @protected - */ -goog.editor.plugins.LinkBubble.prototype.getTestLinkMessage = function() { - return goog.editor.plugins.LinkBubble.MSG_LINK_BUBBLE_TEST_LINK; -}; - - -/** @override */ -goog.editor.plugins.LinkBubble.prototype.createBubbleContents = function( - bubbleContainer) { - var linkObj = this.getLinkToTextObj_(); - - // Create linkTextSpan, show plain text for e-mail address or truncate the - // text to <= 48 characters so that property bubbles don't grow too wide and - // create a link if URL. Only linkify valid links. - // TODO(robbyw): Repalce this color with a CSS class. - var color = linkObj.valid ? 'black' : 'red'; - var shouldOpenUrl = this.shouldOpenUrl(linkObj.linkText); - var linkTextSpan; - if (goog.editor.Link.isLikelyEmailAddress(linkObj.linkText) || - !linkObj.valid || !shouldOpenUrl) { - linkTextSpan = this.dom_.createDom(goog.dom.TagName.SPAN, - { - id: goog.editor.plugins.LinkBubble.LINK_TEXT_ID_, - style: 'color:' + color - }, this.dom_.createTextNode(linkObj.linkText)); - } else { - var testMsgSpan = this.dom_.createDom(goog.dom.TagName.SPAN, - {id: goog.editor.plugins.LinkBubble.TEST_LINK_SPAN_ID_}, - this.getTestLinkMessage()); - linkTextSpan = this.dom_.createDom(goog.dom.TagName.SPAN, - { - id: goog.editor.plugins.LinkBubble.LINK_TEXT_ID_, - style: 'color:' + color - }, ''); - var linkText = goog.string.truncateMiddle(linkObj.linkText, 48); - // Actually creates a pseudo-link that can't be right-clicked to open in a - // new tab, because that would avoid the logic to stop referrer leaks. - this.createLink(goog.editor.plugins.LinkBubble.TEST_LINK_ID_, - this.dom_.createTextNode(linkText).data, - this.testLink, - linkTextSpan); - } - - var changeLinkSpan = this.createLinkOption( - goog.editor.plugins.LinkBubble.CHANGE_LINK_SPAN_ID_); - this.createLink(goog.editor.plugins.LinkBubble.CHANGE_LINK_ID_, - goog.editor.plugins.LinkBubble.MSG_LINK_BUBBLE_CHANGE, - this.showLinkDialog_, changeLinkSpan); - - // This function is called multiple times - we have to reset the array. - this.actionSpans_ = []; - for (var i = 0; i < this.extraActions_.length; i++) { - var action = this.extraActions_[i]; - var actionSpan = this.createLinkOption(action.spanId_); - this.actionSpans_.push(actionSpan); - this.createLink(action.linkId_, action.message_, - function() { - action.actionFn_(this.getTargetUrl()); - }, - actionSpan); - } - - var removeLinkSpan = this.createLinkOption( - goog.editor.plugins.LinkBubble.DELETE_LINK_SPAN_ID_); - this.createLink(goog.editor.plugins.LinkBubble.DELETE_LINK_ID_, - goog.editor.plugins.LinkBubble.MSG_LINK_BUBBLE_REMOVE, - this.deleteLink_, removeLinkSpan); - - this.onShow(); - - var bubbleContents = this.dom_.createDom(goog.dom.TagName.DIV, - {id: goog.editor.plugins.LinkBubble.LINK_DIV_ID_}, - testMsgSpan || '', linkTextSpan, changeLinkSpan); - - for (i = 0; i < this.actionSpans_.length; i++) { - bubbleContents.appendChild(this.actionSpans_[i]); - } - bubbleContents.appendChild(removeLinkSpan); - - goog.dom.appendChild(bubbleContainer, bubbleContents); -}; - - -/** - * Tests the link by opening it in a new tab/window. Should be used as the - * click event handler for the test pseudo-link. - * @protected - */ -goog.editor.plugins.LinkBubble.prototype.testLink = function() { - goog.window.open(this.getTestLinkAction_(), - { - 'target': '_blank', - 'noreferrer': this.stopReferrerLeaks_ - }, this.getFieldObject().getAppWindow()); -}; - - -/** - * Returns whether the URL should be considered invalid. This always returns - * false in the base class, and should be overridden by subclasses that wish - * to impose validity rules on URLs. - * @param {string} url The url to check. - * @return {boolean} Whether the URL should be considered invalid. - */ -goog.editor.plugins.LinkBubble.prototype.isInvalidUrl = goog.functions.FALSE; - - -/** - * Gets the text to display for a link, based on the type of link - * @return {!Object} Returns an object of the form: - * {linkText: displayTextForLinkTarget, valid: ifTheLinkIsValid}. - * @private - */ -goog.editor.plugins.LinkBubble.prototype.getLinkToTextObj_ = function() { - var isError; - var targetUrl = this.getTargetUrl(); - - if (this.isInvalidUrl(targetUrl)) { - - targetUrl = goog.editor.plugins.LinkBubble.MSG_INVALID_URL_LINK_BUBBLE; - isError = true; - } else if (goog.editor.Link.isMailto(targetUrl)) { - targetUrl = targetUrl.substring(7); // 7 == "mailto:".length - } - - return {linkText: targetUrl, valid: !isError}; -}; - - -/** - * Shows the link dialog. - * @param {goog.events.BrowserEvent} e The event. - * @private - */ -goog.editor.plugins.LinkBubble.prototype.showLinkDialog_ = function(e) { - // Needed when this occurs due to an ENTER key event, else the newly created - // dialog manages to have its OK button pressed, causing it to disappear. - e.preventDefault(); - - this.getFieldObject().execCommand(goog.editor.Command.MODAL_LINK_EDITOR, - new goog.editor.Link( - /** @type {HTMLAnchorElement} */ (this.getTargetElement()), - false)); - this.closeBubble(); -}; - - -/** - * Deletes the link associated with the bubble - * @private - */ -goog.editor.plugins.LinkBubble.prototype.deleteLink_ = function() { - this.getFieldObject().dispatchBeforeChange(); - - var link = this.getTargetElement(); - var child = link.lastChild; - goog.dom.flattenElement(link); - goog.editor.range.placeCursorNextTo(child, false); - - this.closeBubble(); - - this.getFieldObject().dispatchChange(); - this.getFieldObject().focus(); -}; - - -/** - * Sets the proper state for the action links. - * @protected - * @override - */ -goog.editor.plugins.LinkBubble.prototype.onShow = function() { - var linkDiv = this.dom_.getElement( - goog.editor.plugins.LinkBubble.LINK_DIV_ID_); - if (linkDiv) { - var testLinkSpan = this.dom_.getElement( - goog.editor.plugins.LinkBubble.TEST_LINK_SPAN_ID_); - if (testLinkSpan) { - var url = this.getTargetUrl(); - goog.style.setElementShown(testLinkSpan, !goog.editor.Link.isMailto(url)); - } - - for (var i = 0; i < this.extraActions_.length; i++) { - var action = this.extraActions_[i]; - var actionSpan = this.dom_.getElement(action.spanId_); - if (actionSpan) { - goog.style.setElementShown(actionSpan, action.toShowFn_( - this.getTargetUrl())); - } - } - } -}; - - -/** - * Gets the url for the bubble test link. The test link is the link in the - * bubble the user can click on to make sure the link they entered is correct. - * @return {string} The url for the bubble link href. - * @private - */ -goog.editor.plugins.LinkBubble.prototype.getTestLinkAction_ = function() { - var targetUrl = this.getTargetUrl(); - return this.testLinkUrlFn_ ? this.testLinkUrlFn_(targetUrl) : targetUrl; -}; - - -/** - * Checks whether the plugin should open the given url in a new window. - * @param {string} url The url to check. - * @return {boolean} If the plugin should open the given url in a new window. - * @protected - */ -goog.editor.plugins.LinkBubble.prototype.shouldOpenUrl = function(url) { - return !this.blockOpeningUnsafeSchemes_ || this.isSafeSchemeToOpen_(url); -}; - - -/** - * Determines whether or not a url has a scheme which is safe to open. - * Schemes like javascript are unsafe due to the possibility of XSS. - * @param {string} url A url. - * @return {boolean} Whether the url has a safe scheme. - * @private - */ -goog.editor.plugins.LinkBubble.prototype.isSafeSchemeToOpen_ = - function(url) { - var scheme = goog.uri.utils.getScheme(url) || 'http'; - return goog.array.contains(this.safeToOpenSchemes_, scheme.toLowerCase()); -}; - - - -/** - * Constructor for extra actions that can be added to the link bubble. - * @param {string} spanId The ID for the span showing the action. - * @param {string} linkId The ID for the link showing the action. - * @param {string} message The text for the link showing the action. - * @param {function(string):boolean} toShowFn Test function to determine whether - * to show the action for the given URL. - * @param {function(string):void} actionFn Action function to run when the - * action is clicked. Takes the current target URL as a parameter. - * @constructor - * @final - */ -goog.editor.plugins.LinkBubble.Action = function(spanId, linkId, message, - toShowFn, actionFn) { - this.spanId_ = spanId; - this.linkId_ = linkId; - this.message_ = message; - this.toShowFn_ = toShowFn; - this.actionFn_ = actionFn; -}; diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/linkbubble_test.html b/src/database/third_party/closure-library/closure/goog/editor/plugins/linkbubble_test.html deleted file mode 100644 index 7d413850814..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/linkbubble_test.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - goog.editor.plugins.LinkBubble Tests - - - - - - - - diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/linkbubble_test.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/linkbubble_test.js deleted file mode 100644 index c878c9bebf7..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/linkbubble_test.js +++ /dev/null @@ -1,396 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.editor.plugins.LinkBubbleTest'); -goog.setTestOnly('goog.editor.plugins.LinkBubbleTest'); - -goog.require('goog.dom'); -goog.require('goog.dom.Range'); -goog.require('goog.dom.TagName'); -goog.require('goog.editor.Command'); -goog.require('goog.editor.Link'); -goog.require('goog.editor.plugins.LinkBubble'); -goog.require('goog.events.BrowserEvent'); -goog.require('goog.events.Event'); -goog.require('goog.events.EventType'); -goog.require('goog.string'); -goog.require('goog.style'); -goog.require('goog.testing.FunctionMock'); -goog.require('goog.testing.PropertyReplacer'); -goog.require('goog.testing.editor.FieldMock'); -goog.require('goog.testing.editor.TestHelper'); -goog.require('goog.testing.events'); -goog.require('goog.testing.jsunit'); -goog.require('goog.userAgent'); - -var fieldDiv; -var FIELDMOCK; -var linkBubble; -var link; -var mockWindowOpen; -var stubs; -var testHelper; - -function setUpPage() { - fieldDiv = goog.dom.$('field'); - stubs = new goog.testing.PropertyReplacer(); - testHelper = new goog.testing.editor.TestHelper(goog.dom.getElement('field')); -} - -function setUp() { - testHelper.setUpEditableElement(); - FIELDMOCK = new goog.testing.editor.FieldMock(); - - linkBubble = new goog.editor.plugins.LinkBubble(); - linkBubble.fieldObject = FIELDMOCK; - - link = fieldDiv.firstChild; - - mockWindowOpen = new goog.testing.FunctionMock('open'); - stubs.set(window, 'open', mockWindowOpen); -} - -function tearDown() { - linkBubble.closeBubble(); - testHelper.tearDownEditableElement(); - stubs.reset(); -} - -function testLinkSelected() { - FIELDMOCK.$replay(); - linkBubble.enable(FIELDMOCK); - goog.dom.Range.createFromNodeContents(link).select(); - linkBubble.handleSelectionChange(); - assertBubble(); - FIELDMOCK.$verify(); -} - -function testLinkClicked() { - FIELDMOCK.$replay(); - linkBubble.enable(FIELDMOCK); - linkBubble.handleSelectionChange(createMouseEvent(link)); - assertBubble(); - FIELDMOCK.$verify(); -} - -function testImageLink() { - FIELDMOCK.$replay(); - linkBubble.enable(FIELDMOCK); - link.setAttribute('imageanchor', 1); - linkBubble.handleSelectionChange(createMouseEvent(link)); - assertBubble(); - FIELDMOCK.$verify(); -} - -function closeBox() { - var closeBox = goog.dom.getElementsByTagNameAndClass(goog.dom.TagName.DIV, - 'tr_bubble_closebox'); - assertEquals('Should find only one close box', 1, closeBox.length); - assertNotNull('Found close box', closeBox[0]); - goog.testing.events.fireClickSequence(closeBox[0]); -} - -function testCloseBox() { - testLinkClicked(); - closeBox(); - assertNoBubble(); - FIELDMOCK.$verify(); -} - -function testChangeClicked() { - FIELDMOCK.execCommand(goog.editor.Command.MODAL_LINK_EDITOR, - new goog.editor.Link(link, false)); - FIELDMOCK.$registerArgumentListVerifier('execCommand', function(arr1, arr2) { - return arr1.length == arr2.length && - arr1.length == 2 && - arr1[0] == goog.editor.Command.MODAL_LINK_EDITOR && - arr2[0] == goog.editor.Command.MODAL_LINK_EDITOR && - arr1[1] instanceof goog.editor.Link && - arr2[1] instanceof goog.editor.Link; - }); - FIELDMOCK.$times(1); - FIELDMOCK.$returns(true); - FIELDMOCK.$replay(); - linkBubble.enable(FIELDMOCK); - - linkBubble.handleSelectionChange(createMouseEvent(link)); - assertBubble(); - - goog.testing.events.fireClickSequence( - goog.dom.$(goog.editor.plugins.LinkBubble.CHANGE_LINK_ID_)); - assertNoBubble(); - FIELDMOCK.$verify(); -} - -function testDeleteClicked() { - FIELDMOCK.dispatchBeforeChange(); - FIELDMOCK.$times(1); - FIELDMOCK.dispatchChange(); - FIELDMOCK.$times(1); - FIELDMOCK.focus(); - FIELDMOCK.$times(1); - FIELDMOCK.$replay(); - - linkBubble.enable(FIELDMOCK); - - linkBubble.handleSelectionChange(createMouseEvent(link)); - assertBubble(); - - goog.testing.events.fireClickSequence( - goog.dom.$(goog.editor.plugins.LinkBubble.DELETE_LINK_ID_)); - var element = goog.userAgent.GECKO ? document.body : fieldDiv; - assertNotEquals('Link removed', element.firstChild.nodeName, - goog.dom.TagName.A); - assertNoBubble(); - FIELDMOCK.$verify(); -} - -function testActionClicked() { - var SPAN = 'actionSpanId'; - var LINK = 'actionLinkId'; - var toShowCount = 0; - var actionCount = 0; - - var linkAction = new goog.editor.plugins.LinkBubble.Action( - SPAN, LINK, 'message', - function() { - toShowCount++; - return toShowCount == 1; // Show it the first time. - }, - function() { - actionCount++; - }); - - linkBubble = new goog.editor.plugins.LinkBubble(linkAction); - linkBubble.fieldObject = FIELDMOCK; - FIELDMOCK.$replay(); - linkBubble.enable(FIELDMOCK); - - // The first time the bubble is shown, show our custom action. - linkBubble.handleSelectionChange(createMouseEvent(link)); - assertBubble(); - assertEquals('Should check showing the action', 1, toShowCount); - assertEquals('Action should not have fired yet', 0, actionCount); - - assertTrue('Action should be visible 1st time', goog.style.isElementShown( - goog.dom.$(SPAN))); - goog.testing.events.fireClickSequence(goog.dom.$(LINK)); - - assertEquals('Should not check showing again yet', 1, toShowCount); - assertEquals('Action should be fired', 1, actionCount); - - closeBox(); - assertNoBubble(); - - // The action won't be shown the second time around. - linkBubble.handleSelectionChange(createMouseEvent(link)); - assertBubble(); - assertEquals('Should check showing again', 2, toShowCount); - assertEquals('Action should not fire again', 1, actionCount); - assertFalse('Action should not be shown 2nd time', goog.style.isElementShown( - goog.dom.$(SPAN))); - - FIELDMOCK.$verify(); -} - -function testLinkTextClicked() { - mockWindowOpen('http://www.google.com/', '_blank', ''); - mockWindowOpen.$replay(); - FIELDMOCK.$replay(); - linkBubble.enable(FIELDMOCK); - - linkBubble.handleSelectionChange(createMouseEvent(link)); - assertBubble(); - - goog.testing.events.fireClickSequence( - goog.dom.$(goog.editor.plugins.LinkBubble.TEST_LINK_ID_)); - - assertBubble(); - mockWindowOpen.$verify(); - FIELDMOCK.$verify(); -} - -function testLinkTextClickedCustomUrlFn() { - mockWindowOpen('http://images.google.com/', '_blank', ''); - mockWindowOpen.$replay(); - FIELDMOCK.$replay(); - linkBubble.enable(FIELDMOCK); - - linkBubble.setTestLinkUrlFn(function(url) { - return url.replace('www', 'images'); - }); - - linkBubble.handleSelectionChange(createMouseEvent(link)); - assertBubble(); - - goog.testing.events.fireClickSequence( - goog.dom.$(goog.editor.plugins.LinkBubble.TEST_LINK_ID_)); - - assertBubble(); - mockWindowOpen.$verify(); - FIELDMOCK.$verify(); -} - - -/** - * Urls with invalid schemes shouldn't be linkified. - * @bug 2585360 - */ -function testDontLinkifyInvalidScheme() { - mockWindowOpen.$replay(); - FIELDMOCK.$replay(); - linkBubble.enable(FIELDMOCK); - - var badLink = document.createElement('a'); - badLink.href = 'javascript:alert(1)'; - badLink.innerHTML = 'bad link'; - - linkBubble.handleSelectionChange(createMouseEvent(badLink)); - assertBubble(); - - // The link shouldn't exist at all - assertNull(goog.dom.$(goog.editor.plugins.LinkBubble.TEST_LINK_ID_)); - - assertBubble(); - mockWindowOpen.$verify(); - FIELDMOCK.$verify(); -} - -function testIsSafeSchemeToOpen() { - // Urls with no scheme at all are ok too since 'http://' will be prepended. - var good = [ - 'http://google.com', 'http://google.com/', 'https://google.com', - 'null@google.com', 'http://www.google.com', 'http://site.com', - 'google.com', 'google', 'http://google', 'HTTP://GOOGLE.COM', - 'HtTp://www.google.com' - ]; - - var bad = [ - 'javascript:google.com', 'httpp://google.com', 'data:foo', - 'javascript:alert(\'hi\');', 'abc:def' - ]; - - for (var i = 0; i < good.length; i++) { - assertTrue(good[i] + ' should have a safe scheme', - linkBubble.isSafeSchemeToOpen_(good[i])); - } - - for (i = 0; i < bad.length; i++) { - assertFalse(bad[i] + ' should have an unsafe scheme', - linkBubble.isSafeSchemeToOpen_(bad[i])); - } -} - -function testShouldOpenWithWhitelist() { - linkBubble.setSafeToOpenSchemes(['abc']); - - assertTrue('Scheme should be safe', - linkBubble.shouldOpenUrl('abc://google.com')); - assertFalse('Scheme should be unsafe', - linkBubble.shouldOpenUrl('http://google.com')); - - linkBubble.setBlockOpeningUnsafeSchemes(false); - assertTrue('Non-whitelisted should now be safe after disabling blocking', - linkBubble.shouldOpenUrl('http://google.com')); -} - - -/** - * @bug 763211 - * @bug 2182147 - */ -function testLongUrlTestLinkAnchorTextCorrect() { - FIELDMOCK.$replay(); - linkBubble.enable(FIELDMOCK); - - var longUrl = 'http://www.reallylonglinkthatshouldbetruncated' + - 'becauseitistoolong.com'; - var truncatedLongUrl = goog.string.truncateMiddle(longUrl, 48); - - var longLink = document.createElement('a'); - longLink.href = longUrl; - longLink.innerHTML = 'Google'; - fieldDiv.appendChild(longLink); - - linkBubble.handleSelectionChange(createMouseEvent(longLink)); - assertBubble(); - - var testLinkEl = goog.dom.$(goog.editor.plugins.LinkBubble.TEST_LINK_ID_); - assertEquals( - 'The test link\'s anchor text should be the truncated URL.', - truncatedLongUrl, - testLinkEl.innerHTML); - - fieldDiv.removeChild(longLink); - FIELDMOCK.$verify(); -} - - -/** - * @bug 2416024 - */ -function testOverridingCreateBubbleContentsDoesntNpeGetTargetUrl() { - FIELDMOCK.$replay(); - linkBubble.enable(FIELDMOCK); - - stubs.set(linkBubble, 'createBubbleContents', - function(elem) { - // getTargetUrl would cause an NPE if urlUtil_ wasn't defined yet. - linkBubble.getTargetUrl(); - }); - assertNotThrows('Accessing this.urlUtil_ should not NPE', - goog.bind(linkBubble.handleSelectionChange, - linkBubble, createMouseEvent(link))); - - FIELDMOCK.$verify(); -} - - -/** - * @bug 15379294 - */ -function testUpdateLinkCommandDoesNotTriggerAnException() { - FIELDMOCK.$replay(); - linkBubble.enable(FIELDMOCK); - - // At this point, the bubble was not created yet using its createBubble - // public method. - assertNotThrows( - 'Executing goog.editor.Command.UPDATE_LINK_BUBBLE should not trigger ' + - 'an exception even if the bubble was not created yet using its ' + - 'createBubble method.', - goog.bind(linkBubble.execCommandInternal, linkBubble, - goog.editor.Command.UPDATE_LINK_BUBBLE)); - - FIELDMOCK.$verify(); -} - -function assertBubble() { - assertTrue('Link bubble visible', linkBubble.isVisible()); - assertNotNull('Link bubble created', - goog.dom.$(goog.editor.plugins.LinkBubble.LINK_DIV_ID_)); -} - -function assertNoBubble() { - assertFalse('Link bubble not visible', linkBubble.isVisible()); - assertNull('Link bubble not created', - goog.dom.$(goog.editor.plugins.LinkBubble.LINK_DIV_ID_)); -} - -function createMouseEvent(target) { - var eventObj = new goog.events.Event(goog.events.EventType.MOUSEUP, target); - eventObj.button = goog.events.BrowserEvent.MouseButton.LEFT; - - return new goog.events.BrowserEvent(eventObj, target); -} diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/linkdialogplugin.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/linkdialogplugin.js deleted file mode 100644 index 9c804a6fc1d..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/linkdialogplugin.js +++ /dev/null @@ -1,438 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview A plugin for the LinkDialog. - * - * @author nicksantos@google.com (Nick Santos) - * @author robbyw@google.com (Robby Walker) - */ - -goog.provide('goog.editor.plugins.LinkDialogPlugin'); - -goog.require('goog.array'); -goog.require('goog.dom'); -goog.require('goog.editor.Command'); -goog.require('goog.editor.plugins.AbstractDialogPlugin'); -goog.require('goog.events.EventHandler'); -goog.require('goog.functions'); -goog.require('goog.ui.editor.AbstractDialog'); -goog.require('goog.ui.editor.LinkDialog'); -goog.require('goog.uri.utils'); - - - -/** - * A plugin that opens the link dialog. - * @constructor - * @extends {goog.editor.plugins.AbstractDialogPlugin} - */ -goog.editor.plugins.LinkDialogPlugin = function() { - goog.editor.plugins.LinkDialogPlugin.base( - this, 'constructor', goog.editor.Command.MODAL_LINK_EDITOR); - - /** - * Event handler for this object. - * @type {goog.events.EventHandler} - * @private - */ - this.eventHandler_ = new goog.events.EventHandler(this); - - - /** - * A list of whitelisted URL schemes which are safe to open. - * @type {Array} - * @private - */ - this.safeToOpenSchemes_ = ['http', 'https', 'ftp']; -}; -goog.inherits(goog.editor.plugins.LinkDialogPlugin, - goog.editor.plugins.AbstractDialogPlugin); - - -/** - * Link object that the dialog is editing. - * @type {goog.editor.Link} - * @protected - */ -goog.editor.plugins.LinkDialogPlugin.prototype.currentLink_; - - -/** - * Optional warning to show about email addresses. - * @type {goog.html.SafeHtml} - * @private - */ -goog.editor.plugins.LinkDialogPlugin.prototype.emailWarning_; - - -/** - * Whether to show a checkbox where the user can choose to have the link open in - * a new window. - * @type {boolean} - * @private - */ -goog.editor.plugins.LinkDialogPlugin.prototype.showOpenLinkInNewWindow_ = false; - - -/** - * Whether the "open link in new window" checkbox should be checked when the - * dialog is shown, and also whether it was checked last time the dialog was - * closed. - * @type {boolean} - * @private - */ -goog.editor.plugins.LinkDialogPlugin.prototype.isOpenLinkInNewWindowChecked_ = - false; - - -/** - * Weather to show a checkbox where the user can choose to add 'rel=nofollow' - * attribute added to the link. - * @type {boolean} - * @private - */ -goog.editor.plugins.LinkDialogPlugin.prototype.showRelNoFollow_ = false; - - -/** - * Whether to stop referrer leaks. Defaults to false. - * @type {boolean} - * @private - */ -goog.editor.plugins.LinkDialogPlugin.prototype.stopReferrerLeaks_ = false; - - -/** - * Whether to block opening links with a non-whitelisted URL scheme. - * @type {boolean} - * @private - */ -goog.editor.plugins.LinkDialogPlugin.prototype.blockOpeningUnsafeSchemes_ = - true; - - -/** @override */ -goog.editor.plugins.LinkDialogPlugin.prototype.getTrogClassId = - goog.functions.constant('LinkDialogPlugin'); - - -/** - * Tells the plugin whether to block URLs with schemes not in the whitelist. - * If blocking is enabled, this plugin will stop the 'Test Link' popup - * window from being created. Blocking doesn't affect link creation--if the - * user clicks the 'OK' button with an unsafe URL, the link will still be - * created as normal. - * @param {boolean} blockOpeningUnsafeSchemes Whether to block non-whitelisted - * schemes. - */ -goog.editor.plugins.LinkDialogPlugin.prototype.setBlockOpeningUnsafeSchemes = - function(blockOpeningUnsafeSchemes) { - this.blockOpeningUnsafeSchemes_ = blockOpeningUnsafeSchemes; -}; - - -/** - * Sets a whitelist of allowed URL schemes that are safe to open. - * Schemes should all be in lowercase. If the plugin is set to block opening - * unsafe schemes, user-entered URLs will be converted to lowercase and checked - * against this list. The whitelist has no effect if blocking is not enabled. - * @param {Array} schemes String array of URL schemes to allow (http, - * https, etc.). - */ -goog.editor.plugins.LinkDialogPlugin.prototype.setSafeToOpenSchemes = - function(schemes) { - this.safeToOpenSchemes_ = schemes; -}; - - -/** - * Tells the dialog to show a checkbox where the user can choose to have the - * link open in a new window. - * @param {boolean} startChecked Whether to check the checkbox the first - * time the dialog is shown. Subesquent times the checkbox will remember its - * previous state. - */ -goog.editor.plugins.LinkDialogPlugin.prototype.showOpenLinkInNewWindow = - function(startChecked) { - this.showOpenLinkInNewWindow_ = true; - this.isOpenLinkInNewWindowChecked_ = startChecked; -}; - - -/** - * Tells the dialog to show a checkbox where the user can choose to have - * 'rel=nofollow' attribute added to the link. - */ -goog.editor.plugins.LinkDialogPlugin.prototype.showRelNoFollow = function() { - this.showRelNoFollow_ = true; -}; - - -/** - * Returns whether the"open link in new window" checkbox was checked last time - * the dialog was closed. - * @return {boolean} Whether the"open link in new window" checkbox was checked - * last time the dialog was closed. - */ -goog.editor.plugins.LinkDialogPlugin.prototype. - getOpenLinkInNewWindowCheckedState = function() { - return this.isOpenLinkInNewWindowChecked_; -}; - - -/** - * Tells the plugin to stop leaking the page's url via the referrer header when - * the "test this link" link is clicked. When the user clicks on a link, the - * browser makes a request for the link url, passing the url of the current page - * in the request headers. If the user wants the current url to be kept secret - * (e.g. an unpublished document), the owner of the url that was clicked will - * see the secret url in the request headers, and it will no longer be a secret. - * Calling this method will not send a referrer header in the request, just as - * if the user had opened a blank window and typed the url in themselves. - */ -goog.editor.plugins.LinkDialogPlugin.prototype.stopReferrerLeaks = function() { - this.stopReferrerLeaks_ = true; -}; - - -/** - * Sets the warning message to show to users about including email addresses on - * public web pages. - * @param {!goog.html.SafeHtml} emailWarning Warning message to show users about - * including email addresses on the web. - */ -goog.editor.plugins.LinkDialogPlugin.prototype.setEmailWarning = function( - emailWarning) { - this.emailWarning_ = emailWarning; -}; - - -/** - * Handles execCommand by opening the dialog. - * @param {string} command The command to execute. - * @param {*=} opt_arg {@link A goog.editor.Link} object representing the link - * being edited. - * @return {*} Always returns true, indicating the dialog was shown. - * @protected - * @override - */ -goog.editor.plugins.LinkDialogPlugin.prototype.execCommandInternal = function( - command, opt_arg) { - this.currentLink_ = /** @type {goog.editor.Link} */(opt_arg); - return goog.editor.plugins.LinkDialogPlugin.base( - this, 'execCommandInternal', command, opt_arg); -}; - - -/** - * Handles when the dialog closes. - * @param {goog.events.Event} e The AFTER_HIDE event object. - * @override - * @protected - */ -goog.editor.plugins.LinkDialogPlugin.prototype.handleAfterHide = function(e) { - goog.editor.plugins.LinkDialogPlugin.base(this, 'handleAfterHide', e); - this.currentLink_ = null; -}; - - -/** - * @return {goog.events.EventHandler} The event handler. - * @protected - * @this T - * @template T - */ -goog.editor.plugins.LinkDialogPlugin.prototype.getEventHandler = function() { - return this.eventHandler_; -}; - - -/** - * @return {goog.editor.Link} The link being edited. - * @protected - */ -goog.editor.plugins.LinkDialogPlugin.prototype.getCurrentLink = function() { - return this.currentLink_; -}; - - -/** - * Creates a new instance of the dialog and registers for the relevant events. - * @param {goog.dom.DomHelper} dialogDomHelper The dom helper to be used to - * create the dialog. - * @param {*=} opt_link The target link (should be a goog.editor.Link). - * @return {!goog.ui.editor.LinkDialog} The dialog. - * @override - * @protected - */ -goog.editor.plugins.LinkDialogPlugin.prototype.createDialog = function( - dialogDomHelper, opt_link) { - var dialog = new goog.ui.editor.LinkDialog(dialogDomHelper, - /** @type {goog.editor.Link} */ (opt_link)); - if (this.emailWarning_) { - dialog.setEmailWarning(this.emailWarning_); - } - if (this.showOpenLinkInNewWindow_) { - dialog.showOpenLinkInNewWindow(this.isOpenLinkInNewWindowChecked_); - } - if (this.showRelNoFollow_) { - dialog.showRelNoFollow(); - } - dialog.setStopReferrerLeaks(this.stopReferrerLeaks_); - this.eventHandler_. - listen(dialog, goog.ui.editor.AbstractDialog.EventType.OK, - this.handleOk). - listen(dialog, goog.ui.editor.AbstractDialog.EventType.CANCEL, - this.handleCancel_). - listen(dialog, goog.ui.editor.LinkDialog.EventType.BEFORE_TEST_LINK, - this.handleBeforeTestLink); - return dialog; -}; - - -/** @override */ -goog.editor.plugins.LinkDialogPlugin.prototype.disposeInternal = function() { - goog.editor.plugins.LinkDialogPlugin.base(this, 'disposeInternal'); - this.eventHandler_.dispose(); -}; - - -/** - * Handles the OK event from the dialog by updating the link in the field. - * @param {goog.ui.editor.LinkDialog.OkEvent} e OK event object. - * @protected - */ -goog.editor.plugins.LinkDialogPlugin.prototype.handleOk = function(e) { - // We're not restoring the original selection, so clear it out. - this.disposeOriginalSelection(); - - this.currentLink_.setTextAndUrl(e.linkText, e.linkUrl); - if (this.showOpenLinkInNewWindow_) { - // Save checkbox state for next time. - this.isOpenLinkInNewWindowChecked_ = e.openInNewWindow; - } - - var anchor = this.currentLink_.getAnchor(); - this.touchUpAnchorOnOk_(anchor, e); - var extraAnchors = this.currentLink_.getExtraAnchors(); - for (var i = 0; i < extraAnchors.length; ++i) { - extraAnchors[i].href = anchor.href; - this.touchUpAnchorOnOk_(extraAnchors[i], e); - } - - // Place cursor to the right of the modified link. - this.currentLink_.placeCursorRightOf(); - - this.getFieldObject().focus(); - - this.getFieldObject().dispatchSelectionChangeEvent(); - this.getFieldObject().dispatchChange(); - - this.eventHandler_.removeAll(); -}; - - -/** - * Apply the necessary properties to a link upon Ok being clicked in the dialog. - * @param {HTMLAnchorElement} anchor The anchor to set properties on. - * @param {goog.events.Event} e Event object. - * @private - */ -goog.editor.plugins.LinkDialogPlugin.prototype.touchUpAnchorOnOk_ = - function(anchor, e) { - if (this.showOpenLinkInNewWindow_) { - if (e.openInNewWindow) { - anchor.target = '_blank'; - } else { - if (anchor.target == '_blank') { - anchor.target = ''; - } - // If user didn't indicate to open in a new window but the link already - // had a target other than '_blank', let's leave what they had before. - } - } - - if (this.showRelNoFollow_) { - var alreadyPresent = goog.ui.editor.LinkDialog.hasNoFollow(anchor.rel); - if (alreadyPresent && !e.noFollow) { - anchor.rel = goog.ui.editor.LinkDialog.removeNoFollow(anchor.rel); - } else if (!alreadyPresent && e.noFollow) { - anchor.rel = anchor.rel ? anchor.rel + ' nofollow' : 'nofollow'; - } - } -}; - - -/** - * Handles the CANCEL event from the dialog by clearing the anchor if needed. - * @param {goog.events.Event} e Event object. - * @private - */ -goog.editor.plugins.LinkDialogPlugin.prototype.handleCancel_ = function(e) { - if (this.currentLink_.isNew()) { - goog.dom.flattenElement(this.currentLink_.getAnchor()); - var extraAnchors = this.currentLink_.getExtraAnchors(); - for (var i = 0; i < extraAnchors.length; ++i) { - goog.dom.flattenElement(extraAnchors[i]); - } - // Make sure listeners know the anchor was flattened out. - this.getFieldObject().dispatchChange(); - } - - this.eventHandler_.removeAll(); -}; - - -/** - * Handles the BeforeTestLink event fired when the 'test' link is clicked. - * @param {goog.ui.editor.LinkDialog.BeforeTestLinkEvent} e BeforeTestLink event - * object. - * @protected - */ -goog.editor.plugins.LinkDialogPlugin.prototype.handleBeforeTestLink = - function(e) { - if (!this.shouldOpenUrl(e.url)) { - /** @desc Message when the user tries to test (preview) a link, but the - * link cannot be tested. */ - var MSG_UNSAFE_LINK = goog.getMsg('This link cannot be tested.'); - alert(MSG_UNSAFE_LINK); - e.preventDefault(); - } -}; - - -/** - * Checks whether the plugin should open the given url in a new window. - * @param {string} url The url to check. - * @return {boolean} If the plugin should open the given url in a new window. - * @protected - */ -goog.editor.plugins.LinkDialogPlugin.prototype.shouldOpenUrl = function(url) { - return !this.blockOpeningUnsafeSchemes_ || this.isSafeSchemeToOpen_(url); -}; - - -/** - * Determines whether or not a url has a scheme which is safe to open. - * Schemes like javascript are unsafe due to the possibility of XSS. - * @param {string} url A url. - * @return {boolean} Whether the url has a safe scheme. - * @private - */ -goog.editor.plugins.LinkDialogPlugin.prototype.isSafeSchemeToOpen_ = - function(url) { - var scheme = goog.uri.utils.getScheme(url) || 'http'; - return goog.array.contains(this.safeToOpenSchemes_, scheme.toLowerCase()); -}; diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/linkdialogplugin_test.html b/src/database/third_party/closure-library/closure/goog/editor/plugins/linkdialogplugin_test.html deleted file mode 100644 index d8962fbccb0..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/linkdialogplugin_test.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - goog.editor.plugins.LinkDialogPlugin Tests - - - - - - - - -
    -
    - - diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/linkdialogplugin_test.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/linkdialogplugin_test.js deleted file mode 100644 index b7a2e875534..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/linkdialogplugin_test.js +++ /dev/null @@ -1,749 +0,0 @@ -// Copyright 2010 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.ui.editor.plugins.LinkDialogTest'); -goog.setTestOnly('goog.ui.editor.plugins.LinkDialogTest'); - -goog.require('goog.dom'); -goog.require('goog.dom.DomHelper'); -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.TagName'); -goog.require('goog.editor.BrowserFeature'); -goog.require('goog.editor.Command'); -goog.require('goog.editor.Field'); -goog.require('goog.editor.Link'); -goog.require('goog.editor.plugins.LinkDialogPlugin'); -goog.require('goog.string'); -goog.require('goog.string.Unicode'); -goog.require('goog.testing.MockControl'); -goog.require('goog.testing.editor.FieldMock'); -goog.require('goog.testing.editor.TestHelper'); -goog.require('goog.testing.editor.dom'); -goog.require('goog.testing.events'); -goog.require('goog.testing.jsunit'); -goog.require('goog.testing.mockmatchers'); -goog.require('goog.ui.editor.AbstractDialog'); -goog.require('goog.ui.editor.LinkDialog'); -goog.require('goog.userAgent'); - -var plugin; -var anchorElem; -var extraAnchors; -var isNew; -var testDiv; - -var mockCtrl; -var mockField; -var mockLink; -var mockAlert; - -var OLD_LINK_TEXT = 'old text'; -var OLD_LINK_URL = 'http://old.url/'; -var NEW_LINK_TEXT = 'My Link Text'; -var NEW_LINK_URL = 'http://my.link/url/'; - -var fieldElem; -var fieldObj; -var linkObj; - -function setUp() { - testDiv = goog.dom.getDocument().getElementById('test'); - testDiv.innerHTML = 'Some preceeding text'; - - anchorElem = goog.dom.createElement(goog.dom.TagName.A); - anchorElem.href = 'http://www.google.com/'; - anchorElem.innerHTML = 'anchor text'; - goog.dom.appendChild(testDiv, anchorElem); - extraAnchors = []; - - mockCtrl = new goog.testing.MockControl(); - mockField = new goog.testing.editor.FieldMock(); - mockCtrl.addMock(mockField); - mockLink = mockCtrl.createLooseMock(goog.editor.Link); - mockAlert = mockCtrl.createGlobalFunctionMock('alert'); - - isNew = false; - mockLink.isNew().$anyTimes().$does(function() { - return isNew; - }); - mockLink. - setTextAndUrl(goog.testing.mockmatchers.isString, - goog.testing.mockmatchers.isString). - $anyTimes(). - $does(function(text, url) { - anchorElem.innerHTML = text; - anchorElem.href = url; - }); - mockLink.getAnchor().$anyTimes().$returns(anchorElem); - mockLink.getExtraAnchors().$anyTimes().$returns(extraAnchors); -} - -function tearDown() { - plugin.dispose(); - tearDownRealEditableField(); - testDiv.innerHTML = ''; - mockCtrl.$tearDown(); -} - -function setUpAnchor(text, href, opt_isNew, opt_target, opt_rel) { - setUpGivenAnchor(anchorElem, text, href, opt_isNew, opt_target, opt_rel); -} - -function setUpGivenAnchor( - anchor, text, href, opt_isNew, opt_target, opt_rel) { - anchor.innerHTML = text; - anchor.href = href; - isNew = !!opt_isNew; - if (opt_target) { - anchor.target = opt_target; - } - if (opt_rel) { - anchor.rel = opt_rel; - } -} - - -/** - * Tests that the plugin's dialog is properly created. - */ -function testCreateDialog() { - // Note: this tests simply creating the dialog because that's the only - // functionality added to this class. Opening or closing effects (editing - // the actual link) is tested in linkdialog_test.html, but should be moved - // here if that functionality gets refactored from the dialog to the plugin. - mockCtrl.$replayAll(); - - plugin = new goog.editor.plugins.LinkDialogPlugin(); - plugin.registerFieldObject(mockField); - - var dialog = plugin.createDialog(new goog.dom.DomHelper(), mockLink); - assertTrue('Dialog should be of type goog.ui.editor.LinkDialog', - dialog instanceof goog.ui.editor.LinkDialog); - - mockCtrl.$verifyAll(); -} - - -/** - * Tests that when the OK event fires the link is properly updated. - */ -function testOk() { - mockLink.placeCursorRightOf(); - mockField.dispatchSelectionChangeEvent(); - mockField.dispatchChange(); - mockField.focus(); - mockCtrl.$replayAll(); - - setUpAnchor(OLD_LINK_TEXT, OLD_LINK_URL); - plugin = new goog.editor.plugins.LinkDialogPlugin(); - plugin.registerFieldObject(mockField); - var dialog = plugin.createDialog(new goog.dom.DomHelper(), mockLink); - - // Mock of execCommand + clicking OK without actually opening the dialog. - plugin.currentLink_ = mockLink; - dialog.dispatchEvent(new goog.ui.editor.LinkDialog.OkEvent(NEW_LINK_TEXT, - NEW_LINK_URL)); - - assertEquals('Display text incorrect', - NEW_LINK_TEXT, - anchorElem.innerHTML); - assertEquals('Anchor element href incorrect', - NEW_LINK_URL, - anchorElem.href); - - mockCtrl.$verifyAll(); -} - - -/** - * Tests that when the Cancel event fires the link is unchanged. - */ -function testCancel() { - mockCtrl.$replayAll(); - - setUpAnchor(OLD_LINK_TEXT, OLD_LINK_URL); - plugin = new goog.editor.plugins.LinkDialogPlugin(); - plugin.registerFieldObject(mockField); - var dialog = plugin.createDialog(new goog.dom.DomHelper(), mockLink); - - // Mock of execCommand + cancel without actually opening the dialog. - plugin.currentLink_ = mockLink; - dialog.dispatchEvent(goog.ui.editor.AbstractDialog.EventType.CANCEL); - - assertEquals('Display text should not be changed', - OLD_LINK_TEXT, - anchorElem.innerHTML); - assertEquals('Anchor element href should not be changed', - OLD_LINK_URL, - anchorElem.href); - - mockCtrl.$verifyAll(); -} - - -/** - * Tests that when the Cancel event fires for a new link it gets removed. - */ -function testCancelNew() { - mockField.dispatchChange(); // Should be fired because link was removed. - mockCtrl.$replayAll(); - - setUpAnchor(OLD_LINK_TEXT, OLD_LINK_URL, true); - var prevSib = anchorElem.previousSibling; - plugin = new goog.editor.plugins.LinkDialogPlugin(); - plugin.registerFieldObject(mockField); - var dialog = plugin.createDialog(new goog.dom.DomHelper(), mockLink); - - // Mock of execCommand + cancel without actually opening the dialog. - plugin.currentLink_ = mockLink; - dialog.dispatchEvent(goog.ui.editor.AbstractDialog.EventType.CANCEL); - - assertNotEquals('Anchor element should be removed from document body', - testDiv, - anchorElem.parentNode); - var newElem = prevSib.nextSibling; - assertEquals('Link should be replaced by text node', - goog.dom.NodeType.TEXT, - newElem.nodeType); - assertEquals('Original text should be left behind', - OLD_LINK_TEXT, - newElem.nodeValue); - - mockCtrl.$verifyAll(); -} - - -/** - * Tests that when the Cancel event fires for a new link it gets removed. - */ -function testCancelNewMultiple() { - mockField.dispatchChange(); // Should be fired because link was removed. - mockCtrl.$replayAll(); - - var anchorElem1 = anchorElem; - var parent1 = goog.dom.createDom(goog.dom.TagName.DIV, null, - anchorElem1); - goog.dom.appendChild(testDiv, parent1); - setUpGivenAnchor(anchorElem1, OLD_LINK_TEXT + '1', OLD_LINK_URL + '1', - true); - - anchorElem2 = goog.dom.createDom(goog.dom.TagName.A); - var parent2 = goog.dom.createDom(goog.dom.TagName.DIV, null, - anchorElem2); - goog.dom.appendChild(testDiv, parent2); - setUpGivenAnchor(anchorElem2, OLD_LINK_TEXT + '2', OLD_LINK_URL + '2', - true); - extraAnchors.push(anchorElem2); - - anchorElem3 = goog.dom.createDom(goog.dom.TagName.A); - var parent3 = goog.dom.createDom(goog.dom.TagName.DIV, null, - anchorElem3); - goog.dom.appendChild(testDiv, parent3); - setUpGivenAnchor(anchorElem3, OLD_LINK_TEXT + '3', OLD_LINK_URL + '3', - true); - extraAnchors.push(anchorElem3); - - plugin = new goog.editor.plugins.LinkDialogPlugin(); - plugin.registerFieldObject(mockField); - var dialog = plugin.createDialog(new goog.dom.DomHelper(), mockLink); - - // Mock of execCommand + cancel without actually opening the dialog. - plugin.currentLink_ = mockLink; - dialog.dispatchEvent(goog.ui.editor.AbstractDialog.EventType.CANCEL); - - assertNotEquals('Anchor 1 element should be removed from document body', - parent1, - anchorElem1.parentNode); - assertNotEquals('Anchor 2 element should be removed from document body', - parent2, - anchorElem2.parentNode); - assertNotEquals('Anchor 3 element should be removed from document body', - parent3, - anchorElem3.parentNode); - - assertEquals('Link 1 should be replaced by text node', - goog.dom.NodeType.TEXT, - parent1.firstChild.nodeType); - assertEquals('Link 2 should be replaced by text node', - goog.dom.NodeType.TEXT, - parent2.firstChild.nodeType); - assertEquals('Link 3 should be replaced by text node', - goog.dom.NodeType.TEXT, - parent3.firstChild.nodeType); - - assertEquals('Original text 1 should be left behind', - OLD_LINK_TEXT + '1', - parent1.firstChild.nodeValue); - assertEquals('Original text 2 should be left behind', - OLD_LINK_TEXT + '2', - parent2.firstChild.nodeValue); - assertEquals('Original text 3 should be left behind', - OLD_LINK_TEXT + '3', - parent3.firstChild.nodeValue); - - mockCtrl.$verifyAll(); -} - - -/** - * Tests that when the Cancel event fires for a new link it gets removed. - */ -function testOkNewMultiple() { - mockLink.placeCursorRightOf(); - mockField.dispatchSelectionChangeEvent(); - mockField.dispatchChange(); - mockField.focus(); - mockCtrl.$replayAll(); - - var anchorElem1 = anchorElem; - setUpGivenAnchor(anchorElem1, OLD_LINK_TEXT + '1', OLD_LINK_URL + '1', - true); - - anchorElem2 = goog.dom.createElement(goog.dom.TagName.A); - goog.dom.appendChild(testDiv, anchorElem2); - setUpGivenAnchor(anchorElem2, OLD_LINK_TEXT + '2', OLD_LINK_URL + '2', - true); - extraAnchors.push(anchorElem2); - - anchorElem3 = goog.dom.createElement(goog.dom.TagName.A); - goog.dom.appendChild(testDiv, anchorElem3); - setUpGivenAnchor(anchorElem3, OLD_LINK_TEXT + '3', OLD_LINK_URL + '3', - true); - extraAnchors.push(anchorElem3); - - var prevSib = anchorElem1.previousSibling; - plugin = new goog.editor.plugins.LinkDialogPlugin(); - plugin.registerFieldObject(mockField); - var dialog = plugin.createDialog(new goog.dom.DomHelper(), mockLink); - - // Mock of execCommand + clicking OK without actually opening the dialog. - plugin.currentLink_ = mockLink; - dialog.dispatchEvent(new goog.ui.editor.LinkDialog.OkEvent(NEW_LINK_TEXT, - NEW_LINK_URL)); - - assertEquals('Display text 1 must update', NEW_LINK_TEXT, - anchorElem1.innerHTML); - assertEquals('Display text 2 must not update', OLD_LINK_TEXT + '2', - anchorElem2.innerHTML); - assertEquals('Display text 3 must not update', OLD_LINK_TEXT + '3', - anchorElem3.innerHTML); - - assertEquals('Anchor element 1 href must update', NEW_LINK_URL, - anchorElem1.href); - assertEquals('Anchor element 2 href must update', NEW_LINK_URL, - anchorElem2.href); - assertEquals('Anchor element 3 href must update', NEW_LINK_URL, - anchorElem3.href); - - mockCtrl.$verifyAll(); -} - - -/** - * Tests the anchor's target is correctly modified with the "open in new - * window" feature on. - */ -function testOkOpenInNewWindow() { - mockLink.placeCursorRightOf().$anyTimes(); - mockField.dispatchSelectionChangeEvent().$anyTimes(); - mockField.dispatchChange().$anyTimes(); - mockField.focus().$anyTimes(); - mockCtrl.$replayAll(); - - plugin = new goog.editor.plugins.LinkDialogPlugin(); - plugin.registerFieldObject(mockField); - plugin.showOpenLinkInNewWindow(false); - plugin.currentLink_ = mockLink; - - // Edit a link that doesn't open in a new window and leave it as such. - setUpAnchor(OLD_LINK_TEXT, OLD_LINK_URL); - var dialog = plugin.createDialog(new goog.dom.DomHelper(), mockLink); - dialog.dispatchEvent(new goog.ui.editor.LinkDialog.OkEvent( - NEW_LINK_TEXT, NEW_LINK_URL, false, false)); - assertEquals( - 'Target should not be set for link that doesn\'t open in new window', - '', anchorElem.target); - assertFalse('Checked state should stay false', - plugin.getOpenLinkInNewWindowCheckedState()); - - // Edit a link that doesn't open in a new window and toggle it on. - setUpAnchor(OLD_LINK_TEXT, OLD_LINK_URL); - dialog = plugin.createDialog(new goog.dom.DomHelper(), mockLink); - dialog.dispatchEvent(new goog.ui.editor.LinkDialog.OkEvent( - NEW_LINK_TEXT, NEW_LINK_URL, true)); - assertEquals( - 'Target should be set to _blank for link that opens in new window', - '_blank', anchorElem.target); - assertTrue('Checked state should be true after toggling a link on', - plugin.getOpenLinkInNewWindowCheckedState()); - - // Edit a link that doesn't open in a named window and don't touch it. - setUpAnchor(OLD_LINK_TEXT, OLD_LINK_URL, false, 'named'); - dialog = plugin.createDialog(new goog.dom.DomHelper(), mockLink); - dialog.dispatchEvent(new goog.ui.editor.LinkDialog.OkEvent( - NEW_LINK_TEXT, NEW_LINK_URL, false)); - assertEquals( - 'Target should keep its original value', - 'named', anchorElem.target); - assertFalse('Checked state should be false again', - plugin.getOpenLinkInNewWindowCheckedState()); - - // Edit a link that opens in a new window and toggle it off. - setUpAnchor(OLD_LINK_TEXT, OLD_LINK_URL, false, '_blank'); - dialog = plugin.createDialog(new goog.dom.DomHelper(), mockLink); - dialog.dispatchEvent(new goog.ui.editor.LinkDialog.OkEvent( - NEW_LINK_TEXT, NEW_LINK_URL, false)); - assertEquals( - 'Target should not be set for link that doesn\'t open in new window', - '', anchorElem.target); - - mockCtrl.$verifyAll(); -} - -function testOkNoFollowEnabled() { - verifyRelNoFollow(true, null, 'nofollow'); -} - -function testOkNoFollowInUppercase() { - verifyRelNoFollow(true, 'NOFOLLOW', 'NOFOLLOW'); -} - -function testOkNoFollowEnabledHasMoreRelValues() { - verifyRelNoFollow(true, 'author', 'author nofollow'); -} - -function testOkNoFollowDisabled() { - verifyRelNoFollow(false, null, ''); -} - -function testOkNoFollowDisabledHasMoreRelValues() { - verifyRelNoFollow(false, 'author', 'author'); -} - -function testOkNoFollowDisabledHasMoreRelValues() { - verifyRelNoFollow(false, 'author nofollow', 'author '); -} - -function testOkNoFollowInUppercaseWithMoreValues() { - verifyRelNoFollow(true, 'NOFOLLOW author', 'NOFOLLOW author'); -} - -function verifyRelNoFollow(noFollow, originalRel, expectedRel) { - mockLink.placeCursorRightOf(); - mockField.dispatchSelectionChangeEvent(); - mockField.dispatchChange(); - mockField.focus(); - mockCtrl.$replayAll(); - - plugin = new goog.editor.plugins.LinkDialogPlugin(); - plugin.registerFieldObject(mockField); - plugin.showRelNoFollow(); - plugin.currentLink_ = mockLink; - - setUpAnchor(OLD_LINK_TEXT, OLD_LINK_URL, true, null, originalRel); - var dialog = plugin.createDialog(new goog.dom.DomHelper(), mockLink); - dialog.dispatchEvent(new goog.ui.editor.LinkDialog.OkEvent( - NEW_LINK_TEXT, NEW_LINK_URL, false, noFollow)); - assertEquals(expectedRel, anchorElem.rel); - - mockCtrl.$verifyAll(); -} - - -/** - * Tests that the selection is cleared when the dialog opens and is - * correctly restored after cancel is clicked. - */ -function testRestoreSelectionOnOk() { - setUpAnchor('12345', '/'); - setUpRealEditableField(); - - var elem = fieldObj.getElement(); - var helper = new goog.testing.editor.TestHelper(elem); - helper.select('12345', 1, '12345', 4); // Selects '234'. - - assertEquals('Incorrect text selected before dialog is opened', - '234', - fieldObj.getRange().getText()); - plugin.execCommand(goog.editor.Command.MODAL_LINK_EDITOR, linkObj); - if (!goog.userAgent.IE && !goog.userAgent.OPERA) { - // IE returns some bogus range when field doesn't have selection. - // You can't remove the selection from a whitebox field in Opera. - assertNull('There should be no selection while dialog is open', - fieldObj.getRange()); - } - goog.testing.events.fireClickSequence( - plugin.dialog_.getOkButtonElement()); - assertEquals('No text should be selected after clicking ok', - '', - fieldObj.getRange().getText()); - - // Test that the caret is placed at the end of the link text. - goog.testing.editor.dom.assertRangeBetweenText( - // If the browser gets stuck in links, an nbsp was added after the link - // to avoid that, otherwise we just look for the 5. - goog.editor.BrowserFeature.GETS_STUCK_IN_LINKS ? - goog.string.Unicode.NBSP : '5', - '', - fieldObj.getRange()); - - // NOTE(user): The functionality to avoid getting stuck in links is - // tested in editablelink_test.html::testPlaceCursorRightOf(). -} - - -/** - * Tests that the selection is cleared when the dialog opens and is - * correctly restored after cancel is clicked. - * @param {boolean=} opt_isNew Whether to test behavior when creating a new - * link (cancelling will flatten it). - */ -function testRestoreSelectionOnCancel(opt_isNew) { - setUpAnchor('12345', '/', opt_isNew); - setUpRealEditableField(); - - var elem = fieldObj.getElement(); - var helper = new goog.testing.editor.TestHelper(elem); - helper.select('12345', 1, '12345', 4); // Selects '234'. - - assertEquals('Incorrect text selected before dialog is opened', - '234', - fieldObj.getRange().getText()); - plugin.execCommand(goog.editor.Command.MODAL_LINK_EDITOR, linkObj); - if (!goog.userAgent.IE && !goog.userAgent.OPERA) { - // IE returns some bogus range when field doesn't have selection. - // You can't remove the selection from a whitebox field in Opera. - assertNull('There should be no selection while dialog is open', - fieldObj.getRange()); - } - goog.testing.events.fireClickSequence( - plugin.dialog_.getCancelButtonElement()); - assertEquals('Incorrect text selected after clicking cancel', - '234', - fieldObj.getRange().getText()); -} - - -/** - * Tests that the selection is cleared when the dialog opens and is - * correctly restored after cancel is clicked and the new link is removed. - */ -function testRestoreSelectionOnCancelNew() { - testRestoreSelectionOnCancel(true); -} - - -/** - * Tests that the BeforeTestLink event is suppressed for invalid url schemes. - */ -function testTestLinkDisabledForInvalidScheme() { - mockAlert(goog.testing.mockmatchers.isString); - mockCtrl.$replayAll(); - - var invalidUrl = 'javascript:document.write(\'hello\');'; - - plugin = new goog.editor.plugins.LinkDialogPlugin(); - var dialog = plugin.createDialog(new goog.dom.DomHelper(), mockLink); - - // Mock of execCommand + clicking test without actually opening the dialog. - var dispatched = dialog.dispatchEvent( - new goog.ui.editor.LinkDialog.BeforeTestLinkEvent(invalidUrl)); - - assertFalse(dispatched); - mockCtrl.$verifyAll(); -} - -function testIsSafeSchemeToOpen() { - plugin = new goog.editor.plugins.LinkDialogPlugin(); - // Urls with no scheme at all are ok too since 'http://' will be prepended. - var good = [ - 'http://google.com', 'http://google.com/', 'https://google.com', - 'null@google.com', 'http://www.google.com', 'http://site.com', - 'google.com', 'google', 'http://google', 'HTTP://GOOGLE.COM', - 'HtTp://www.google.com' - ]; - - var bad = [ - 'javascript:google.com', 'httpp://google.com', 'data:foo', - 'javascript:alert(\'hi\');', 'abc:def' - ]; - - for (var i = 0; i < good.length; i++) { - assertTrue(good[i] + ' should have a safe scheme', - plugin.isSafeSchemeToOpen_(good[i])); - } - - for (i = 0; i < bad.length; i++) { - assertFalse(bad[i] + ' should have an unsafe scheme', - plugin.isSafeSchemeToOpen_(bad[i])); - } -} - -function testShouldOpenWithWhitelist() { - plugin.setSafeToOpenSchemes(['abc']); - - assertTrue('Scheme should be safe', - plugin.shouldOpenUrl('abc://google.com')); - assertFalse('Scheme should be unsafe', - plugin.shouldOpenUrl('http://google.com')); - - plugin.setBlockOpeningUnsafeSchemes(false); - assertTrue('Non-whitelisted should now be safe after disabling blocking', - plugin.shouldOpenUrl('http://google.com')); -} - - -/** - * Regression test for http://b/issue?id=1607766 . Without the fix, this - * should give an Invalid Argument error in IE, because the editable field - * caches a selection util that has a reference to the node of the link text - * before it is edited (which gets replaced by a new node for the new text - * after editing). - */ -function testBug1607766() { - setUpAnchor('abc', 'def'); - setUpRealEditableField(); - - var elem = fieldObj.getElement(); - var helper = new goog.testing.editor.TestHelper(elem); - helper.select('abc', 1, 'abc', 2); // Selects 'b'. - // Dispatching a selection event causes the field to cache a selection - // util, which is the root of the bug. - plugin.fieldObject.dispatchSelectionChangeEvent(); - - plugin.execCommand(goog.editor.Command.MODAL_LINK_EDITOR, linkObj); - goog.dom.getElement( - goog.ui.editor.LinkDialog.Id_.TEXT_TO_DISPLAY).value = 'Abc'; - goog.testing.events.fireClickSequence(plugin.dialog_.getOkButtonElement()); - - // In IE the unit test somehow doesn't cause a browser focus event, so we - // need to manually invoke this, which is where the bug happens. - plugin.fieldObject.dispatchFocus_(); -} - - -/** - * Regression test for http://b/issue?id=2215546 . - */ -function testBug2215546() { - setUpRealEditableField(); - - var elem = fieldObj.getElement(); - fieldObj.setHtml(false, '
    '); - anchorElem = elem.firstChild.firstChild; - linkObj = new goog.editor.Link(anchorElem, true); - - var helper = new goog.testing.editor.TestHelper(elem); - // Select "" in a way, simulating what IE does if you hit enter twice, - // arrow up into the blank line and open the link dialog. - helper.select(anchorElem, 0, elem.firstChild, 1); - - plugin.execCommand(goog.editor.Command.MODAL_LINK_EDITOR, linkObj); - goog.dom.getElement( - goog.ui.editor.LinkDialog.Id_.TEXT_TO_DISPLAY).value = 'foo'; - goog.dom.getElement( - goog.ui.editor.LinkDialog.Id_.ON_WEB_INPUT).value = 'foo'; - var okButton = plugin.dialog_.getOkButtonElement(); - okButton.disabled = false; - goog.testing.events.fireClickSequence(okButton); - - assertEquals('Link text should have been inserted', - 'foo', anchorElem.innerHTML); -} - - -/** - * Test that link insertion doesn't scroll the field to the top - * after clicking Cancel or OK. - */ -function testBug7279077ScrollOnFocus() { - if (goog.userAgent.IE) { - return; // TODO(user): take this out once b/7279077 fixed for IE too. - } - setUpAnchor('12345', '/'); - setUpRealEditableField(); - - // Make the field scrollable and kinda small. - var elem = fieldObj.getElement(); - elem.style.overflow = 'auto'; - elem.style.height = '40px'; - elem.style.width = '200px'; - elem.style.contenteditable = 'true'; - - // Add a bunch of text before the anchor tag. - var longTextElem = document.createElement('span'); - longTextElem.innerHTML = goog.string.repeat('All work and no play.

    ', 20); - elem.insertBefore(longTextElem, elem.firstChild); - - var helper = new goog.testing.editor.TestHelper(elem); - helper.select('12345', 1, '12345', 4); // Selects '234'. - - // Scroll down. - elem.scrollTop = 60; - - // Bring up the link insertion dialog, then cancel. - plugin.execCommand(goog.editor.Command.MODAL_LINK_EDITOR, linkObj); - goog.dom.getElement( - goog.ui.editor.LinkDialog.Id_.TEXT_TO_DISPLAY).value = 'foo'; - goog.dom.getElement( - goog.ui.editor.LinkDialog.Id_.ON_WEB_INPUT).value = 'foo'; - var cancelButton = plugin.dialog_.getCancelButtonElement(); - goog.testing.events.fireClickSequence(cancelButton); - - assertEquals('Field should not have scrolled after cancel', - 60, elem.scrollTop); - - // Now let's try it with clicking the OK button. - plugin.execCommand(goog.editor.Command.MODAL_LINK_EDITOR, linkObj); - goog.dom.getElement( - goog.ui.editor.LinkDialog.Id_.TEXT_TO_DISPLAY).value = 'foo'; - goog.dom.getElement( - goog.ui.editor.LinkDialog.Id_.ON_WEB_INPUT).value = 'foo'; - var okButton = plugin.dialog_.getOkButtonElement(); - goog.testing.events.fireClickSequence(okButton); - - assertEquals('Field should not have scrolled after OK', - 60, elem.scrollTop); -} - - -/** - * Setup a real editable field (instead of a mock) and register the plugin to - * it. - */ -function setUpRealEditableField() { - fieldElem = document.createElement('div'); - fieldElem.id = 'myField'; - document.body.appendChild(fieldElem); - fieldElem.appendChild(anchorElem); - fieldObj = new goog.editor.Field('myField', document); - fieldObj.makeEditable(); - linkObj = new goog.editor.Link(fieldObj.getElement().firstChild, isNew); - // Register the plugin to that field. - plugin = new goog.editor.plugins.LinkDialogPlugin(); - fieldObj.registerPlugin(plugin); -} - - -/** - * Tear down the real editable field. - */ -function tearDownRealEditableField() { - if (fieldObj) { - fieldObj.makeUneditable(); - fieldObj.dispose(); - fieldObj = null; - } - goog.dom.removeNode(fieldElem); -} diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/linkshortcutplugin.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/linkshortcutplugin.js deleted file mode 100644 index b77910ce029..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/linkshortcutplugin.js +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2011 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Adds a keyboard shortcut for the link command. - * - */ - -goog.provide('goog.editor.plugins.LinkShortcutPlugin'); - -goog.require('goog.editor.Command'); -goog.require('goog.editor.Plugin'); - - - -/** - * Plugin to add a keyboard shortcut for the link command - * @constructor - * @extends {goog.editor.Plugin} - * @final - */ -goog.editor.plugins.LinkShortcutPlugin = function() { - goog.editor.plugins.LinkShortcutPlugin.base(this, 'constructor'); -}; -goog.inherits(goog.editor.plugins.LinkShortcutPlugin, goog.editor.Plugin); - - -/** @override */ -goog.editor.plugins.LinkShortcutPlugin.prototype.getTrogClassId = function() { - return 'LinkShortcutPlugin'; -}; - - -/** - * @override - */ -goog.editor.plugins.LinkShortcutPlugin.prototype.handleKeyboardShortcut = - function(e, key, isModifierPressed) { - if (isModifierPressed && key == 'k' && !e.shiftKey) { - var link = /** @type {goog.editor.Link?} */ ( - this.getFieldObject().execCommand(goog.editor.Command.LINK)); - if (link) { - link.finishLinkCreation(this.getFieldObject()); - } - return true; - } - - return false; -}; - diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/linkshortcutplugin_test.html b/src/database/third_party/closure-library/closure/goog/editor/plugins/linkshortcutplugin_test.html deleted file mode 100644 index af5c0049116..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/linkshortcutplugin_test.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - goog.editor.plugins.LinkShortcutPlugin Tests - - - - - -

    -
    - http://www.google.com/ -
    -
    - - diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/linkshortcutplugin_test.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/linkshortcutplugin_test.js deleted file mode 100644 index 273ef508de2..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/linkshortcutplugin_test.js +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2011 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.editor.plugins.LinkShortcutPluginTest'); -goog.setTestOnly('goog.editor.plugins.LinkShortcutPluginTest'); - -goog.require('goog.dom'); -goog.require('goog.editor.Field'); -goog.require('goog.editor.plugins.BasicTextFormatter'); -goog.require('goog.editor.plugins.LinkBubble'); -goog.require('goog.editor.plugins.LinkShortcutPlugin'); -goog.require('goog.events.KeyCodes'); -goog.require('goog.testing.PropertyReplacer'); -goog.require('goog.testing.dom'); -goog.require('goog.testing.events'); -goog.require('goog.testing.jsunit'); - -var propertyReplacer; - -function setUp() { - propertyReplacer = new goog.testing.PropertyReplacer(); -} - -function tearDown() { - propertyReplacer.reset(); - var field = document.getElementById('cleanup'); - goog.dom.removeChildren(field); - field.innerHTML = '
    http://www.google.com/
    '; -} - -function testShortcutCreatesALink() { - propertyReplacer.set(window, 'prompt', function() { - return 'http://www.google.com/'; }); - var linkBubble = new goog.editor.plugins.LinkBubble(); - var formatter = new goog.editor.plugins.BasicTextFormatter(); - var plugin = new goog.editor.plugins.LinkShortcutPlugin(); - var fieldEl = document.getElementById('field'); - var field = new goog.editor.Field('field'); - field.registerPlugin(formatter); - field.registerPlugin(linkBubble); - field.registerPlugin(plugin); - field.makeEditable(); - field.focusAndPlaceCursorAtStart(); - var textNode = goog.testing.dom.findTextNode('http://www.google.com/', - fieldEl); - goog.testing.events.fireKeySequence( - field.getElement(), goog.events.KeyCodes.K, { ctrlKey: true }); - - var href = field.getElement().getElementsByTagName('A')[0]; - assertEquals('http://www.google.com/', href.href); - var bubbleLink = - document.getElementById(goog.editor.plugins.LinkBubble.TEST_LINK_ID_); - assertEquals('http://www.google.com/', bubbleLink.innerHTML); -} diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/listtabhandler.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/listtabhandler.js deleted file mode 100644 index 03f78ca3d9a..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/listtabhandler.js +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Editor plugin to handle tab keys in lists to indent and - * outdent. - * - * @author robbyw@google.com (Robby Walker) - */ - -goog.provide('goog.editor.plugins.ListTabHandler'); - -goog.require('goog.dom'); -goog.require('goog.dom.TagName'); -goog.require('goog.editor.Command'); -goog.require('goog.editor.plugins.AbstractTabHandler'); -goog.require('goog.iter'); - - - -/** - * Plugin to handle tab keys in lists to indent and outdent. - * @constructor - * @extends {goog.editor.plugins.AbstractTabHandler} - * @final - */ -goog.editor.plugins.ListTabHandler = function() { - goog.editor.plugins.AbstractTabHandler.call(this); -}; -goog.inherits(goog.editor.plugins.ListTabHandler, - goog.editor.plugins.AbstractTabHandler); - - -/** @override */ -goog.editor.plugins.ListTabHandler.prototype.getTrogClassId = function() { - return 'ListTabHandler'; -}; - - -/** @override */ -goog.editor.plugins.ListTabHandler.prototype.handleTabKey = function(e) { - var range = this.getFieldObject().getRange(); - if (goog.dom.getAncestorByTagNameAndClass(range.getContainerElement(), - goog.dom.TagName.LI) || - goog.iter.some(range, function(node) { - return node.tagName == goog.dom.TagName.LI; - })) { - this.getFieldObject().execCommand(e.shiftKey ? - goog.editor.Command.OUTDENT : - goog.editor.Command.INDENT); - e.preventDefault(); - return true; - } - - return false; -}; - diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/listtabhandler_test.html b/src/database/third_party/closure-library/closure/goog/editor/plugins/listtabhandler_test.html deleted file mode 100644 index 90abef4803e..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/listtabhandler_test.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - Closure Unit Tests - goog.editor.plugins.ListTabHandler - - - - - - -
    -
    - - diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/listtabhandler_test.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/listtabhandler_test.js deleted file mode 100644 index 394a82ccd5f..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/listtabhandler_test.js +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.editor.plugins.ListTabHandlerTest'); -goog.setTestOnly('goog.editor.plugins.ListTabHandlerTest'); - -goog.require('goog.dom'); -goog.require('goog.editor.Command'); -goog.require('goog.editor.plugins.ListTabHandler'); -goog.require('goog.events.BrowserEvent'); -goog.require('goog.events.KeyCodes'); -goog.require('goog.functions'); -goog.require('goog.testing.StrictMock'); -goog.require('goog.testing.editor.FieldMock'); -goog.require('goog.testing.editor.TestHelper'); -goog.require('goog.testing.jsunit'); - -var field; -var editableField; -var tabHandler; -var testHelper; - -function setUpPage() { - field = goog.dom.getElement('field'); -} - -function setUp() { - editableField = new goog.testing.editor.FieldMock(); - // Modal mode behavior tested as part of AbstractTabHandler tests. - editableField.inModalMode = goog.functions.FALSE; - - tabHandler = new goog.editor.plugins.ListTabHandler(); - tabHandler.registerFieldObject(editableField); - - testHelper = new goog.testing.editor.TestHelper(field); - testHelper.setUpEditableElement(); -} - -function tearDown() { - editableField = null; - testHelper.tearDownEditableElement(); - tabHandler.dispose(); -} - -function testListIndentInLi() { - field.innerHTML = '
    • Text
    '; - - var testText = field.firstChild.firstChild.firstChild; // div ul li Test - testHelper.select(testText, 0, testText, 4); - - var event = new goog.testing.StrictMock(goog.events.BrowserEvent); - event.keyCode = goog.events.KeyCodes.TAB; - event.shiftKey = false; - - editableField.execCommand(goog.editor.Command.INDENT); - event.preventDefault(); - - editableField.$replay(); - event.$replay(); - - assertTrue('Event must be handled', - tabHandler.handleKeyboardShortcut(event, '', false)); - - editableField.$verify(); - event.$verify(); -} - -function testListIndentContainLi() { - field.innerHTML = '
    • Text
    '; - - var testText = field.firstChild.firstChild.firstChild; // div ul li Test - testHelper.select(field.firstChild, 0, testText, 4); - - var event = new goog.testing.StrictMock(goog.events.BrowserEvent); - event.keyCode = goog.events.KeyCodes.TAB; - event.shiftKey = false; - - editableField.execCommand(goog.editor.Command.INDENT); - event.preventDefault(); - - editableField.$replay(); - event.$replay(); - - assertTrue('Event must be handled', - tabHandler.handleKeyboardShortcut(event, '', false)); - - editableField.$verify(); - event.$verify(); -} - -function testListOutdentInLi() { - field.innerHTML = '
    • Text
    '; - - var testText = field.firstChild.firstChild.firstChild; // div ul li Test - testHelper.select(testText, 0, testText, 4); - - var event = new goog.testing.StrictMock(goog.events.BrowserEvent); - event.keyCode = goog.events.KeyCodes.TAB; - event.shiftKey = true; - - editableField.execCommand(goog.editor.Command.OUTDENT); - event.preventDefault(); - - editableField.$replay(); - event.$replay(); - - assertTrue('Event must be handled', - tabHandler.handleKeyboardShortcut(event, '', false)); - - editableField.$verify(); - event.$verify(); -} - -function testListOutdentContainLi() { - field.innerHTML = '
    • Text
    '; - - var testText = field.firstChild.firstChild.firstChild; // div ul li Test - testHelper.select(field.firstChild, 0, testText, 4); - - var event = new goog.testing.StrictMock(goog.events.BrowserEvent); - event.keyCode = goog.events.KeyCodes.TAB; - event.shiftKey = true; - - editableField.execCommand(goog.editor.Command.OUTDENT); - event.preventDefault(); - - editableField.$replay(); - event.$replay(); - - assertTrue('Event must be handled', - tabHandler.handleKeyboardShortcut(event, '', false)); - - editableField.$verify(); - event.$verify(); -} - - -function testNoOp() { - field.innerHTML = 'Text'; - - var testText = field.firstChild; - testHelper.select(testText, 0, testText, 4); - - var event = new goog.testing.StrictMock(goog.events.BrowserEvent); - event.keyCode = goog.events.KeyCodes.TAB; - event.shiftKey = true; - - editableField.$replay(); - event.$replay(); - - assertFalse('Event must not be handled', - tabHandler.handleKeyboardShortcut(event, '', false)); - - editableField.$verify(); - event.$verify(); -} diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/loremipsum.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/loremipsum.js deleted file mode 100644 index 90ba31dc946..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/loremipsum.js +++ /dev/null @@ -1,192 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview A plugin that fills the field with lorem ipsum text when it's - * empty and does not have the focus. Applies to both editable and uneditable - * fields. - * - * @author nicksantos@google.com (Nick Santos) - */ - -goog.provide('goog.editor.plugins.LoremIpsum'); - -goog.require('goog.asserts'); -goog.require('goog.dom'); -goog.require('goog.editor.Command'); -goog.require('goog.editor.Field'); -goog.require('goog.editor.Plugin'); -goog.require('goog.editor.node'); -goog.require('goog.functions'); -goog.require('goog.userAgent'); - - - -/** - * A plugin that manages lorem ipsum state of editable fields. - * @param {string} message The lorem ipsum message. - * @constructor - * @extends {goog.editor.Plugin} - * @final - */ -goog.editor.plugins.LoremIpsum = function(message) { - goog.editor.Plugin.call(this); - - /** - * The lorem ipsum message. - * @type {string} - * @private - */ - this.message_ = message; -}; -goog.inherits(goog.editor.plugins.LoremIpsum, goog.editor.Plugin); - - -/** @override */ -goog.editor.plugins.LoremIpsum.prototype.getTrogClassId = - goog.functions.constant('LoremIpsum'); - - -/** @override */ -goog.editor.plugins.LoremIpsum.prototype.activeOnUneditableFields = - goog.functions.TRUE; - - -/** - * Whether the field is currently filled with lorem ipsum text. - * @type {boolean} - * @private - */ -goog.editor.plugins.LoremIpsum.prototype.usingLorem_ = false; - - -/** - * Handles queryCommandValue. - * @param {string} command The command to query. - * @return {boolean} The result. - * @override - */ -goog.editor.plugins.LoremIpsum.prototype.queryCommandValue = function(command) { - return command == goog.editor.Command.USING_LOREM && this.usingLorem_; -}; - - -/** - * Handles execCommand. - * @param {string} command The command to execute. - * Should be CLEAR_LOREM or UPDATE_LOREM. - * @param {*=} opt_placeCursor Whether to place the cursor in the field - * after clearing lorem. Should be a boolean. - * @override - */ -goog.editor.plugins.LoremIpsum.prototype.execCommand = function(command, - opt_placeCursor) { - if (command == goog.editor.Command.CLEAR_LOREM) { - this.clearLorem_(!!opt_placeCursor); - } else if (command == goog.editor.Command.UPDATE_LOREM) { - this.updateLorem_(); - } -}; - - -/** @override */ -goog.editor.plugins.LoremIpsum.prototype.isSupportedCommand = - function(command) { - return command == goog.editor.Command.CLEAR_LOREM || - command == goog.editor.Command.UPDATE_LOREM || - command == goog.editor.Command.USING_LOREM; -}; - - -/** - * Set the lorem ipsum text in a goog.editor.Field if needed. - * @private - */ -goog.editor.plugins.LoremIpsum.prototype.updateLorem_ = function() { - // Try to apply lorem ipsum if: - // 1) We have lorem ipsum text - // 2) There's not a dialog open, as that screws - // with the dialog's ability to properly restore the selection - // on dialog close (since the DOM nodes would get clobbered in FF) - // 3) We're not using lorem already - // 4) The field is not currently active (doesn't have focus). - var fieldObj = this.getFieldObject(); - if (!this.usingLorem_ && - !fieldObj.inModalMode() && - goog.editor.Field.getActiveFieldId() != fieldObj.id) { - var field = fieldObj.getElement(); - if (!field) { - // Fallback on the original element. This is needed by - // fields managed by click-to-edit. - field = fieldObj.getOriginalElement(); - } - - goog.asserts.assert(field); - if (goog.editor.node.isEmpty(field)) { - this.usingLorem_ = true; - - // Save the old font style so it can be restored when we - // clear the lorem ipsum style. - this.oldFontStyle_ = field.style.fontStyle; - field.style.fontStyle = 'italic'; - fieldObj.setHtml(true, this.message_, true); - } - } -}; - - -/** - * Clear an EditableField's lorem ipsum and put in initial text if needed. - * - * If using click-to-edit mode (where Trogedit manages whether the field - * is editable), this works for both editable and uneditable fields. - * - * TODO(user): Is this really necessary? See TODO below. - * @param {boolean=} opt_placeCursor Whether to place the cursor in the field - * after clearing lorem. - * @private - */ -goog.editor.plugins.LoremIpsum.prototype.clearLorem_ = function( - opt_placeCursor) { - // Don't mess with lorem state when a dialog is open as that screws - // with the dialog's ability to properly restore the selection - // on dialog close (since the DOM nodes would get clobbered) - var fieldObj = this.getFieldObject(); - if (this.usingLorem_ && !fieldObj.inModalMode()) { - var field = fieldObj.getElement(); - if (!field) { - // Fallback on the original element. This is needed by - // fields managed by click-to-edit. - field = fieldObj.getOriginalElement(); - } - - goog.asserts.assert(field); - this.usingLorem_ = false; - field.style.fontStyle = this.oldFontStyle_; - fieldObj.setHtml(true, null, true); - - // TODO(nicksantos): I'm pretty sure that this is a hack, but talk to - // Julie about why this is necessary and what to do with it. Really, - // we need to figure out where it's necessary and remove it where it's - // not. Safari never places the cursor on its own willpower. - if (opt_placeCursor && fieldObj.isLoaded()) { - if (goog.userAgent.WEBKIT) { - goog.dom.getOwnerDocument(fieldObj.getElement()).body.focus(); - fieldObj.focusAndPlaceCursorAtStart(); - } else if (goog.userAgent.OPERA) { - fieldObj.placeCursorAtStart(); - } - } - } -}; diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/loremipsum_test.html b/src/database/third_party/closure-library/closure/goog/editor/plugins/loremipsum_test.html deleted file mode 100644 index 5e68271b178..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/loremipsum_test.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - goog.editor.plugins.LoremIpsum Tests - - - - - -
    -
    -
    -
    - - diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/loremipsum_test.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/loremipsum_test.js deleted file mode 100644 index ce2aa55d4ba..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/loremipsum_test.js +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('goog.editor.plugins.LoremIpsumTest'); -goog.setTestOnly('goog.editor.plugins.LoremIpsumTest'); - -goog.require('goog.dom'); -goog.require('goog.editor.Command'); -goog.require('goog.editor.Field'); -goog.require('goog.editor.plugins.LoremIpsum'); -goog.require('goog.string.Unicode'); -goog.require('goog.testing.jsunit'); -goog.require('goog.userAgent'); - -var FIELD; -var PLUGIN; -var HTML; -var UPPERCASE_CONTENTS = '

    THE OWLS ARE NOT WHAT THEY SEEM.

    '; - -function setUp() { - HTML = goog.dom.getElement('root').innerHTML; - - FIELD = new goog.editor.Field('field'); - - PLUGIN = new goog.editor.plugins.LoremIpsum( - 'The owls are not what they seem.'); - FIELD.registerPlugin(PLUGIN); -} - -function tearDown() { - FIELD.dispose(); - goog.dom.getElement('root').innerHTML = HTML; -} - -function testQueryUsingLorem() { - FIELD.makeEditable(); - - assertTrue(FIELD.queryCommandValue(goog.editor.Command.USING_LOREM)); - FIELD.setHtml(true, 'fresh content', false, true); - assertFalse(FIELD.queryCommandValue(goog.editor.Command.USING_LOREM)); -} - -function testUpdateLoremIpsum() { - goog.dom.getElement('field').innerHTML = 'stuff'; - - var loremPlugin = FIELD.getPluginByClassId('LoremIpsum'); - FIELD.makeEditable(); - var content = '
    foo
    '; - - FIELD.setHtml(false, '', false, /* Don't update lorem */ false); - assertFalse('Field started with content, lorem must not be enabled.', - FIELD.queryCommandValue(goog.editor.Command.USING_LOREM)); - FIELD.execCommand(goog.editor.Command.UPDATE_LOREM); - assertTrue('Field was set to empty, update must turn on lorem ipsum', - FIELD.queryCommandValue(goog.editor.Command.USING_LOREM)); - - FIELD.unregisterPlugin(loremPlugin); - FIELD.setHtml(false, content, false, - /* Update (turn off) lorem */ true); - FIELD.setHtml(false, '', false, /* Don't update lorem */ false); - FIELD.execCommand(goog.editor.Command.UPDATE_LOREM); - assertFalse('Field with no lorem message must not use lorem ipsum', - FIELD.queryCommandValue(goog.editor.Command.USING_LOREM)); - FIELD.registerPlugin(loremPlugin); - - FIELD.setHtml(false, content, false, true); - FIELD.setHtml(false, '', false, false); - goog.editor.Field.setActiveFieldId(FIELD.id); - FIELD.execCommand(goog.editor.Command.UPDATE_LOREM); - assertFalse('Active field must not use lorem ipsum', - FIELD.queryCommandValue(goog.editor.Command.USING_LOREM)); - goog.editor.Field.setActiveFieldId(null); - - FIELD.setHtml(false, content, false, true); - FIELD.setHtml(false, '', false, false); - FIELD.setModalMode(true); - FIELD.execCommand(goog.editor.Command.UPDATE_LOREM); - assertFalse('Must not turn on lorem ipsum while a dialog is open.', - FIELD.queryCommandValue(goog.editor.Command.USING_LOREM)); - FIELD.setModalMode(true); - - FIELD.dispose(); -} - -function testLoremIpsumAndGetCleanContents() { - goog.dom.getElement('field').innerHTML = 'This is a field'; - FIELD.makeEditable(); - - // test direct getCleanContents - assertEquals('field reported wrong contents', 'This is a field', - FIELD.getCleanContents()); - - // test indirect getCleanContents - var contents = FIELD.getCleanContents(); - assertEquals('field reported wrong contents', 'This is a field', contents); - - // set field html, but explicitly forbid converting to lorem ipsum text - FIELD.setHtml(false, ' ', true, false /* no lorem */); - assertEquals('field contains unexpected contents', getNbsp(), - FIELD.getElement().innerHTML); - assertEquals('field reported wrong contents', getNbsp(), - FIELD.getCleanContents()); - - // now set field html allowing lorem - FIELD.setHtml(false, ' ', true, true /* lorem */); - assertEquals('field reported wrong contents', goog.string.Unicode.NBSP, - FIELD.getCleanContents()); - assertEquals('field contains unexpected contents', UPPERCASE_CONTENTS, - FIELD.getElement().innerHTML.toUpperCase()); -} - -function testLoremIpsumAndGetCleanContents2() { - // make a field blank before we make it editable, and then check - // that making it editable activates lorem. - assert('field is editable', FIELD.isUneditable()); - goog.dom.getElement('field').innerHTML = ' '; - - FIELD.makeEditable(); - assertEquals('field contains unexpected contents', - UPPERCASE_CONTENTS, FIELD.getElement().innerHTML.toUpperCase()); - - FIELD.makeUneditable(); - assertEquals('field contains unexpected contents', - UPPERCASE_CONTENTS, goog.dom.getElement('field').innerHTML.toUpperCase()); -} - -function testLoremIpsumInClickToEditMode() { - // in click-to-edit mode, trogedit manages the editable state of the editor, - // so we must manage lorem ipsum in uneditable mode too. - FIELD.makeEditable(); - - assertEquals('field contains unexpected contents', - UPPERCASE_CONTENTS, FIELD.getElement().innerHTML.toUpperCase()); - - FIELD.makeUneditable(); - assertEquals('field contains unexpected contents', - UPPERCASE_CONTENTS, goog.dom.getElement('field').innerHTML.toUpperCase()); -} - -function getNbsp() { - // On WebKit (pre-528) and Opera,   shows up as its unicode character in - // innerHTML under some circumstances. - return (goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher('528')) || - goog.userAgent.OPERA ? '\u00a0' : ' '; -} diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/removeformatting.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/removeformatting.js deleted file mode 100644 index bbfb7604167..00000000000 --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/removeformatting.js +++ /dev/null @@ -1,780 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// All Rights Reserved. - -/** - * @fileoverview Plugin to handle Remove Formatting. - * - */ - -goog.provide('goog.editor.plugins.RemoveFormatting'); - -goog.require('goog.dom'); -goog.require('goog.dom.NodeType'); -goog.require('goog.dom.Range'); -goog.require('goog.dom.TagName'); -goog.require('goog.editor.BrowserFeature'); -goog.require('goog.editor.Plugin'); -goog.require('goog.editor.node'); -goog.require('goog.editor.range'); -goog.require('goog.string'); -goog.require('goog.userAgent'); - - - -/** - * A plugin to handle removing formatting from selected text. - * @constructor - * @extends {goog.editor.Plugin} - * @final - */ -goog.editor.plugins.RemoveFormatting = function() { - goog.editor.Plugin.call(this); - - /** - * Optional function to perform remove formatting in place of the - * provided removeFormattingWorker_. - * @type {?function(string): string} - * @private - */ - this.optRemoveFormattingFunc_ = null; -}; -goog.inherits(goog.editor.plugins.RemoveFormatting, goog.editor.Plugin); - - -/** - * The editor command this plugin in handling. - * @type {string} - */ -goog.editor.plugins.RemoveFormatting.REMOVE_FORMATTING_COMMAND = - '+removeFormat'; - - -/** - * Regular expression that matches a block tag name. - * @type {RegExp} - * @private - */ -goog.editor.plugins.RemoveFormatting.BLOCK_RE_ = - /^(DIV|TR|LI|BLOCKQUOTE|H\d|PRE|XMP)/; - - -/** - * Appends a new line to a string buffer. - * @param {Array} sb The string buffer to add to. - * @private - */ -goog.editor.plugins.RemoveFormatting.appendNewline_ = function(sb) { - sb.push('
    '); -}; - - -/** - * Create a new range delimited by the start point of the first range and - * the end point of the second range. - * @param {goog.dom.AbstractRange} startRange Use the start point of this - * range as the beginning of the new range. - * @param {goog.dom.AbstractRange} endRange Use the end point of this - * range as the end of the new range. - * @return {!goog.dom.AbstractRange} The new range. - * @private - */ -goog.editor.plugins.RemoveFormatting.createRangeDelimitedByRanges_ = function( - startRange, endRange) { - return goog.dom.Range.createFromNodes( - startRange.getStartNode(), startRange.getStartOffset(), - endRange.getEndNode(), endRange.getEndOffset()); -}; - - -/** @override */ -goog.editor.plugins.RemoveFormatting.prototype.getTrogClassId = function() { - return 'RemoveFormatting'; -}; - - -/** @override */ -goog.editor.plugins.RemoveFormatting.prototype.isSupportedCommand = function( - command) { - return command == - goog.editor.plugins.RemoveFormatting.REMOVE_FORMATTING_COMMAND; -}; - - -/** @override */ -goog.editor.plugins.RemoveFormatting.prototype.execCommandInternal = - function(command, var_args) { - if (command == - goog.editor.plugins.RemoveFormatting.REMOVE_FORMATTING_COMMAND) { - this.removeFormatting_(); - } -}; - - -/** @override */ -goog.editor.plugins.RemoveFormatting.prototype.handleKeyboardShortcut = - function(e, key, isModifierPressed) { - if (!isModifierPressed) { - return false; - } - - if (key == ' ') { - this.getFieldObject().execCommand( - goog.editor.plugins.RemoveFormatting.REMOVE_FORMATTING_COMMAND); - return true; - } - - return false; -}; - - -/** - * Removes formatting from the current selection. Removes basic formatting - * (B/I/U) using the browser's execCommand. Then extracts the html from the - * selection to convert, calls either a client's specified removeFormattingFunc - * callback or trogedit's general built-in removeFormattingWorker_, - * and then replaces the current selection with the converted text. - * @private - */ -goog.editor.plugins.RemoveFormatting.prototype.removeFormatting_ = function() { - var range = this.getFieldObject().getRange(); - if (range.isCollapsed()) { - return; - } - - // Get the html to format and send it off for formatting. Built in - // removeFormat only strips some inline elements and some inline CSS styles - var convFunc = this.optRemoveFormattingFunc_ || - goog.bind(this.removeFormattingWorker_, this); - this.convertSelectedHtmlText_(convFunc); - - // Do the execCommand last as it needs block elements removed to work - // properly on background/fontColor in FF. There are, unfortunately, still - // cases where background/fontColor are not removed here. - var doc = this.getFieldDomHelper().getDocument(); - doc.execCommand('RemoveFormat', false, undefined); - - if (goog.editor.BrowserFeature.ADDS_NBSPS_IN_REMOVE_FORMAT) { - // WebKit converts spaces to non-breaking spaces when doing a RemoveFormat. - // See: https://bugs.webkit.org/show_bug.cgi?id=14062 - this.convertSelectedHtmlText_(function(text) { - // This loses anything that might have legitimately been a non-breaking - // space, but that's better than the alternative of only having non- - // breaking spaces. - // Old versions of WebKit (Safari 3, Chrome 1) incorrectly match /u00A0 - // and newer versions properly match  . - var nbspRegExp = - goog.userAgent.isVersionOrHigher('528') ? / /g : /\u00A0/g; - return text.replace(nbspRegExp, ' '); - }); - } -}; - - -/** - * Finds the nearest ancestor of the node that is a table. - * @param {Node} nodeToCheck Node to search from. - * @return {Node} The table, or null if one was not found. - * @private - */ -goog.editor.plugins.RemoveFormatting.prototype.getTableAncestor_ = function( - nodeToCheck) { - var fieldElement = this.getFieldObject().getElement(); - while (nodeToCheck && nodeToCheck != fieldElement) { - if (nodeToCheck.tagName == goog.dom.TagName.TABLE) { - return nodeToCheck; - } - nodeToCheck = nodeToCheck.parentNode; - } - return null; -}; - - -/** - * Replaces the contents of the selection with html. Does its best to maintain - * the original selection. Also does its best to result in a valid DOM. - * - * TODO(user): See if there's any way to make this work on Ranges, and then - * move it into goog.editor.range. The Firefox implementation uses execCommand - * on the document, so must work on the actual selection. - * - * @param {string} html The html string to insert into the range. - * @private - */ -goog.editor.plugins.RemoveFormatting.prototype.pasteHtml_ = function(html) { - var range = this.getFieldObject().getRange(); - - var dh = this.getFieldDomHelper(); - // Use markers to set the extent of the selection so that we can reselect it - // afterwards. This works better than builtin range manipulation in FF and IE - // because their implementations are so self-inconsistent and buggy. - var startSpanId = goog.string.createUniqueString(); - var endSpanId = goog.string.createUniqueString(); - html = '' + html + - ''; - var dummyNodeId = goog.string.createUniqueString(); - var dummySpanText = ''; - - if (goog.editor.BrowserFeature.HAS_IE_RANGES) { - // IE's selection often doesn't include the outermost tags. - // We want to use pasteHTML to replace the range contents with the newly - // unformatted text, so we have to check to make sure we aren't just - // pasting into some stray tags. To do this, we first clear out the - // contents of the range and then delete all empty nodes parenting the now - // empty range. This way, the pasted contents are never re-embedded into - // formated nodes. Pasting purely empty html does not work, since IE moves - // the selection inside the next node, so we insert a dummy span. - var textRange = range.getTextRange(0).getBrowserRangeObject(); - textRange.pasteHTML(dummySpanText); - var parent; - while ((parent = textRange.parentElement()) && - goog.editor.node.isEmpty(parent) && - !goog.editor.node.isEditableContainer(parent)) { - var tag = parent.nodeName; - // We can't remove these table tags as it will invalidate the table dom. - if (tag == goog.dom.TagName.TD || - tag == goog.dom.TagName.TR || - tag == goog.dom.TagName.TH) { - break; - } - - goog.dom.removeNode(parent); - } - textRange.pasteHTML(html); - var dummySpan = dh.getElement(dummyNodeId); - // If we entered the while loop above, the node has already been removed - // since it was a child of parent and parent was removed. - if (dummySpan) { - goog.dom.removeNode(dummySpan); - } - } else if (goog.editor.BrowserFeature.HAS_W3C_RANGES) { - // insertHtml and range.insertNode don't merge blocks correctly. - // (e.g. if your selection spans two paragraphs) - dh.getDocument().execCommand('insertImage', false, dummyNodeId); - var dummyImageNodePattern = new RegExp('<[^<]*' + dummyNodeId + '[^>]*>'); - var parent = this.getFieldObject().getRange().getContainerElement(); - if (parent.nodeType == goog.dom.NodeType.TEXT) { - // Opera sometimes returns a text node here. - // TODO(user): perhaps we should modify getParentContainer? - parent = parent.parentNode; - } - - // We have to search up the DOM because in some cases, notably when - // selecting li's within a list, execCommand('insertImage') actually splits - // tags in such a way that parent that used to contain the selection does - // not contain inserted image. - while (!dummyImageNodePattern.test(parent.innerHTML)) { - parent = parent.parentNode; - } - - // Like the IE case above, sometimes the selection does not include the - // outermost tags. For Gecko, we have already expanded the range so that - // it does, so we can just replace the dummy image with the final html. - // For WebKit, we use the same approach as we do with IE - we - // inject a dummy span where we will eventually place the contents, and - // remove parentNodes of the span while they are empty. - - if (goog.userAgent.GECKO) { - goog.editor.node.replaceInnerHtml(parent, - parent.innerHTML.replace(dummyImageNodePattern, html)); - } else { - goog.editor.node.replaceInnerHtml(parent, - parent.innerHTML.replace(dummyImageNodePattern, dummySpanText)); - var dummySpan = dh.getElement(dummyNodeId); - parent = dummySpan; - while ((parent = dummySpan.parentNode) && - goog.editor.node.isEmpty(parent) && - !goog.editor.node.isEditableContainer(parent)) { - var tag = parent.nodeName; - // We can't remove these table tags as it will invalidate the table dom. - if (tag == goog.dom.TagName.TD || - tag == goog.dom.TagName.TR || - tag == goog.dom.TagName.TH) { - break; - } - - // We can't just remove parent since dummySpan is inside it, and we need - // to keep dummy span around for the replacement. So we move the - // dummySpan up as we go. - goog.dom.insertSiblingAfter(dummySpan, parent); - goog.dom.removeNode(parent); - } - goog.editor.node.replaceInnerHtml(parent, - parent.innerHTML.replace(new RegExp(dummySpanText, 'i'), html)); - } - } - - var startSpan = dh.getElement(startSpanId); - var endSpan = dh.getElement(endSpanId); - goog.dom.Range.createFromNodes(startSpan, 0, endSpan, - endSpan.childNodes.length).select(); - goog.dom.removeNode(startSpan); - goog.dom.removeNode(endSpan); -}; - - -/** - * Gets the html inside the selection to send off for further processing. - * - * TODO(user): Make this general so that it can be moved into - * goog.editor.range. The main reason it can't be moved is becuase we need to - * get the range before we do the execCommand and continue to operate on that - * same range (reasons are documented above). - * - * @param {goog.dom.AbstractRange} range The selection. - * @return {string} The html string to format. - * @private - */ -goog.editor.plugins.RemoveFormatting.prototype.getHtmlText_ = function(range) { - var div = this.getFieldDomHelper().createDom('div'); - var textRange = range.getBrowserRangeObject(); - - if (goog.editor.BrowserFeature.HAS_W3C_RANGES) { - // Get the text to convert. - div.appendChild(textRange.cloneContents()); - } else if (goog.editor.BrowserFeature.HAS_IE_RANGES) { - // Trim the whitespace on the ends of the range, so that it the container - // will be the container of only the text content that we are changing. - // This gets around issues in IE where the spaces are included in the - // selection, but ignored sometimes by execCommand, and left orphaned. - var rngText = range.getText(); - - // BRs get reported as \r\n, but only count as one character for moves. - // Adjust the string so our move counter is correct. - rngText = rngText.replace(/\r\n/g, '\r'); - - var rngTextLength = rngText.length; - var left = rngTextLength - goog.string.trimLeft(rngText).length; - var right = rngTextLength - goog.string.trimRight(rngText).length; - - textRange.moveStart('character', left); - textRange.moveEnd('character', -right); - - var htmlText = textRange.htmlText; - // Check if in pretag and fix up formatting so that new lines are preserved. - if (textRange.queryCommandValue('formatBlock') == 'Formatted') { - htmlText = goog.string.newLineToBr(textRange.htmlText); - } - div.innerHTML = htmlText; - } - - // Get the innerHTML of the node instead of just returning the text above - // so that its properly html escaped. - return div.innerHTML; -}; - - -/** - * Move the range so that it doesn't include any partially selected tables. - * @param {goog.dom.AbstractRange} range The range to adjust. - * @param {Node} startInTable Table node that the range starts in. - * @param {Node} endInTable Table node that the range ends in. - * @return {!goog.dom.SavedCaretRange} Range to use to restore the - * selection after we run our custom remove formatting. - * @private - */ -goog.editor.plugins.RemoveFormatting.prototype.adjustRangeForTables_ = - function(range, startInTable, endInTable) { - // Create placeholders for the current selection so we can restore it - // later. - var savedCaretRange = goog.editor.range.saveUsingNormalizedCarets(range); - - var startNode = range.getStartNode(); - var startOffset = range.getStartOffset(); - var endNode = range.getEndNode(); - var endOffset = range.getEndOffset(); - var dh = this.getFieldDomHelper(); - - // Move start after the table. - if (startInTable) { - var textNode = dh.createTextNode(''); - goog.dom.insertSiblingAfter(textNode, startInTable); - startNode = textNode; - startOffset = 0; - } - // Move end before the table. - if (endInTable) { - var textNode = dh.createTextNode(''); - goog.dom.insertSiblingBefore(textNode, endInTable); - endNode = textNode; - endOffset = 0; - } - - goog.dom.Range.createFromNodes(startNode, startOffset, - endNode, endOffset).select(); - - return savedCaretRange; -}; - - -/** - * Remove a caret from the dom and hide it in a safe place, so it can - * be restored later via restoreCaretsFromCave. - * @param {goog.dom.SavedCaretRange} caretRange The caret range to - * get the carets from. - * @param {boolean} isStart Whether this is the start or end caret. - * @private - */ -goog.editor.plugins.RemoveFormatting.prototype.putCaretInCave_ = function( - caretRange, isStart) { - var cavedCaret = goog.dom.removeNode(caretRange.getCaret(isStart)); - if (isStart) { - this.startCaretInCave_ = cavedCaret; - } else { - this.endCaretInCave_ = cavedCaret; - } -}; - - -/** - * Restore carets that were hidden away by adding them back into the dom. - * Note: this does not restore to the original dom location, as that - * will likely have been modified with remove formatting. The only - * guarentees here are that start will still be before end, and that - * they will be in the editable region. This should only be used when - * you don't actually intend to USE the caret again. - * @private - */ -goog.editor.plugins.RemoveFormatting.prototype.restoreCaretsFromCave_ = - function() { - // To keep start before end, we put the end caret at the bottom of the field - // and the start caret at the start of the field. - var field = this.getFieldObject().getElement(); - if (this.startCaretInCave_) { - field.insertBefore(this.startCaretInCave_, field.firstChild); - this.startCaretInCave_ = null; - } - if (this.endCaretInCave_) { - field.appendChild(this.endCaretInCave_); - this.endCaretInCave_ = null; - } -}; - - -/** - * Gets the html inside the current selection, passes it through the given - * conversion function, and puts it back into the selection. - * - * @param {function(string): string} convertFunc A conversion function that - * transforms an html string to new html string. - * @private - */ -goog.editor.plugins.RemoveFormatting.prototype.convertSelectedHtmlText_ = - function(convertFunc) { - var range = this.getFieldObject().getRange(); - - // For multiple ranges, it is really hard to do our custom remove formatting - // without invalidating other ranges. So instead of always losing the - // content, this solution at least lets the browser do its own remove - // formatting which works correctly most of the time. - if (range.getTextRangeCount() > 1) { - return; - } - - if (goog.userAgent.GECKO) { - // Determine if we need to handle tables, since they are special cases. - // If the selection is entirely within a table, there is no extra - // formatting removal we can do. If a table is fully selected, we will - // just blow it away. If a table is only partially selected, we can - // perform custom remove formatting only on the non table parts, since we - // we can't just remove the parts and paste back into it (eg. we can't - // inject html where a TR used to be). - // If the selection contains the table and more, this is automatically - // handled, but if just the table is selected, it can be tricky to figure - // this case out, because of the numerous ways selections can be formed - - // ex. if a table has a single tr with a single td with a single text node - // in it, and the selection is (textNode: 0), (textNode: nextNode.length) - // then the entire table is selected, even though the start and end aren't - // the table itself. We are truly inside a table if the expanded endpoints - // are still inside the table. - - // Expand the selection to include any outermost tags that weren't included - // in the selection, but have the same visible selection. Stop expanding - // if we reach the top level field. - var expandedRange = goog.editor.range.expand(range, - this.getFieldObject().getElement()); - - var startInTable = this.getTableAncestor_(expandedRange.getStartNode()); - var endInTable = this.getTableAncestor_(expandedRange.getEndNode()); - - if (startInTable || endInTable) { - if (startInTable == endInTable) { - // We are fully contained in the same table, there is no extra - // remove formatting that we can do, just return and run browser - // formatting only. - return; - } - - // Adjust the range to not contain any partially selected tables, since - // we don't want to run our custom remove formatting on them. - var savedCaretRange = this.adjustRangeForTables_(range, - startInTable, endInTable); - - // Hack alert!! - // If start is not in a table, then the saved caret will get sent out - // for uber remove formatting, and it will get blown away. This is - // fine, except that we need to be able to re-create a range from the - // savedCaretRange later on. So, we just remove it from the dom, and - // put it back later so we can create a range later (not exactly in the - // same spot, but don't worry we don't actually try to use it later) - // and then it will be removed when we dispose the range. - if (!startInTable) { - this.putCaretInCave_(savedCaretRange, true); - } - if (!endInTable) { - this.putCaretInCave_(savedCaretRange, false); - } - - // Re-fetch the range, and re-expand it, since we just modified it. - range = this.getFieldObject().getRange(); - expandedRange = goog.editor.range.expand(range, - this.getFieldObject().getElement()); - } - - expandedRange.select(); - range = expandedRange; - } - - // Convert the selected text to the format-less version, paste back into - // the selection. - var text = this.getHtmlText_(range); - this.pasteHtml_(convertFunc(text)); - - if (goog.userAgent.GECKO && savedCaretRange) { - // If we moved the selection, move it back so the user can't tell we did - // anything crazy and so the browser removeFormat that we call next - // will operate on the entire originally selected range. - range = this.getFieldObject().getRange(); - this.restoreCaretsFromCave_(); - var realSavedCaretRange = savedCaretRange.toAbstractRange(); - var startRange = startInTable ? realSavedCaretRange : range; - var endRange = endInTable ? realSavedCaretRange : range; - var restoredRange = - goog.editor.plugins.RemoveFormatting.createRangeDelimitedByRanges_( - startRange, endRange); - restoredRange.select(); - savedCaretRange.dispose(); - } -}; - - -/** - * Does a best-effort attempt at clobbering all formatting that the - * browser's execCommand couldn't clobber without being totally inefficient. - * Attempts to convert visual line breaks to BRs. Leaves anchors that contain an - * href and images. - * Adapted from Gmail's MessageUtil's htmlToPlainText. http://go/messageutil.js - * @param {string} html The original html of the message. - * @return {string} The unformatted html, which is just text, br's, anchors and - * images. - * @private - */ -goog.editor.plugins.RemoveFormatting.prototype.removeFormattingWorker_ = - function(html) { - var el = goog.dom.createElement('div'); - el.innerHTML = html; - - // Put everything into a string buffer to avoid lots of expensive string - // concatenation along the way. - var sb = []; - var stack = [el.childNodes, 0]; - - // Keep separate stacks for places where we need to keep track of - // how deeply embedded we are. These are analogous to the general stack. - var preTagStack = []; - var preTagLevel = 0; // Length of the prestack. - var tableStack = []; - var tableLevel = 0; - - // sp = stack pointer, pointing to the stack array. - // decrement by 2 since the stack alternates node lists and - // processed node counts - for (var sp = 0; sp >= 0; sp -= 2) { - // Check if we should pop the table level. - var changedLevel = false; - while (tableLevel > 0 && sp <= tableStack[tableLevel - 1]) { - tableLevel--; - changedLevel = true; - } - if (changedLevel) { - goog.editor.plugins.RemoveFormatting.appendNewline_(sb); - } - - - // Check if we should pop the
    / level.
    -    changedLevel = false;
    -    while (preTagLevel > 0 && sp <= preTagStack[preTagLevel - 1]) {
    -      preTagLevel--;
    -      changedLevel = true;
    -    }
    -    if (changedLevel) {
    -      goog.editor.plugins.RemoveFormatting.appendNewline_(sb);
    -    }
    -
    -    // The list of of nodes to process at the current stack level.
    -    var nodeList = stack[sp];
    -    // The number of nodes processed so far, stored in the stack immediately
    -    // following the node list for that stack level.
    -    var numNodesProcessed = stack[sp + 1];
    -
    -    while (numNodesProcessed < nodeList.length) {
    -      var node = nodeList[numNodesProcessed++];
    -      var nodeName = node.nodeName;
    -
    -      var formatted = this.getValueForNode(node);
    -      if (goog.isDefAndNotNull(formatted)) {
    -        sb.push(formatted);
    -        continue;
    -      }
    -
    -      // TODO(user): Handle case 'EMBED' and case 'OBJECT'.
    -      switch (nodeName) {
    -        case '#text':
    -          // Note that IE does not preserve whitespace in the dom
    -          // values, even in a pre tag, so this is useless for IE.
    -          var nodeValue = preTagLevel > 0 ?
    -              node.nodeValue :
    -              goog.string.stripNewlines(node.nodeValue);
    -          nodeValue = goog.string.htmlEscape(nodeValue);
    -          sb.push(nodeValue);
    -          continue;
    -
    -        case goog.dom.TagName.P:
    -          goog.editor.plugins.RemoveFormatting.appendNewline_(sb);
    -          goog.editor.plugins.RemoveFormatting.appendNewline_(sb);
    -          break;  // break (not continue) so that child nodes are processed.
    -
    -        case goog.dom.TagName.BR:
    -          goog.editor.plugins.RemoveFormatting.appendNewline_(sb);
    -          continue;
    -
    -        case goog.dom.TagName.TABLE:
    -          goog.editor.plugins.RemoveFormatting.appendNewline_(sb);
    -          tableStack[tableLevel++] = sp;
    -          break;
    -
    -        case goog.dom.TagName.PRE:
    -        case 'XMP':
    -          // This doesn't fully handle xmp, since
    -          // it doesn't actually ignore tags within the xmp tag.
    -          preTagStack[preTagLevel++] = sp;
    -          break;
    -
    -        case goog.dom.TagName.STYLE:
    -        case goog.dom.TagName.SCRIPT:
    -        case goog.dom.TagName.SELECT:
    -          continue;
    -
    -        case goog.dom.TagName.A:
    -          if (node.href && node.href != '') {
    -            sb.push("<a href='");
    -            sb.push(node.href);
    -            sb.push("'>");
    -            sb.push(this.removeFormattingWorker_(node.innerHTML));
    -            sb.push('</a>');
    -            continue; // Children taken care of.
    -          } else {
    -            break; // Take care of the children.
    -          }
    -
    -        case goog.dom.TagName.IMG:
    -          sb.push("<img src='");
    -          sb.push(node.src);
    -          sb.push("'");
    -          // border=0 is a common way to not show a blue border around an image
    -          // that is wrapped by a link. If we remove that, the blue border will
    -          // show up, which to the user looks like adding format, not removing.
    -          if (node.border == '0') {
    -            sb.push(" border='0'");
    -          }
    -          sb.push('>');
    -          continue;
    -
    -        case goog.dom.TagName.TD:
    -          // Don't add a space for the first TD, we only want spaces to
    -          // separate td's.
    -          if (node.previousSibling) {
    -            sb.push(' ');
    -          }
    -          break;
    -
    -        case goog.dom.TagName.TR:
    -          // Don't add a newline for the first TR.
    -          if (node.previousSibling) {
    -            goog.editor.plugins.RemoveFormatting.appendNewline_(sb);
    -          }
    -          break;
    -
    -        case goog.dom.TagName.DIV:
    -          var parent = node.parentNode;
    -          if (parent.firstChild == node &&
    -              goog.editor.plugins.RemoveFormatting.BLOCK_RE_.test(
    -                  parent.tagName)) {
    -            // If a DIV is the first child of another element that itself is a
    -            // block element, the DIV does not add a new line.
    -            break;
    -          }
    -          // Otherwise, the DIV does add a new line.  Fall through.
    -
    -        default:
    -          if (goog.editor.plugins.RemoveFormatting.BLOCK_RE_.test(nodeName)) {
    -            goog.editor.plugins.RemoveFormatting.appendNewline_(sb);
    -          }
    -      }
    -
    -      // Recurse down the node.
    -      var children = node.childNodes;
    -      if (children.length > 0) {
    -        // Push the current state on the stack.
    -        stack[sp++] = nodeList;
    -        stack[sp++] = numNodesProcessed;
    -
    -        // Iterate through the children nodes.
    -        nodeList = children;
    -        numNodesProcessed = 0;
    -      }
    -    }
    -  }
    -
    -  // Replace &nbsp; with white space.
    -  return goog.string.normalizeSpaces(sb.join(''));
    -};
    -
    -
    -/**
    - * Handle per node special processing if neccessary. If this function returns
    - * null then standard cleanup is applied. Otherwise this node and all children
    - * are assumed to be cleaned.
    - * NOTE(user): If an alternate RemoveFormatting processor is provided
    - * (setRemoveFormattingFunc()), this will no longer work.
    - * @param {Element} node The node to clean.
    - * @return {?string} The HTML strig representation of the cleaned data.
    - */
    -goog.editor.plugins.RemoveFormatting.prototype.getValueForNode = function(
    -    node) {
    -  return null;
    -};
    -
    -
    -/**
    - * Sets a function to be used for remove formatting.
    - * @param {function(string): string} removeFormattingFunc - A function that
    - *     takes  a string of html and returns a string of html that does any other
    - *     formatting changes desired.  Use this only if trogedit's behavior doesn't
    - *     meet your needs.
    - */
    -goog.editor.plugins.RemoveFormatting.prototype.setRemoveFormattingFunc =
    -    function(removeFormattingFunc) {
    -  this.optRemoveFormattingFunc_ = removeFormattingFunc;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/removeformatting_test.html b/src/database/third_party/closure-library/closure/goog/editor/plugins/removeformatting_test.html
    deleted file mode 100644
    index fc34c961bea..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/removeformatting_test.html
    +++ /dev/null
    @@ -1,42 +0,0 @@
    -<!DOCTYPE html>
    -<!--
    -  All Rights Reserved.
    --->
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <!--
    -This test has not yet been updated to run on IE8. See http://b/hotlist?id=36311
    --->
    -  <!--meta http-equiv="X-UA-Compatible" content="IE=edge"-->
    -  <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
    -  <title>
    -   goog.editor.plugins.RemoveFormatting Tests
    -  </title>
    -  <script type="text/javascript" src="../../base.js">
    -  </script>
    -  <script type="text/javascript">
    -    goog.require('goog.editor.plugins.RemoveFormattingTest');
    -  </script>
    - </head>
    - <body>
    -  <!--
    -This wrapper table is outside the mock editor and only used ensure that it is
    -ignored by the tests.
    --->
    -  <table>
    -   <tr>
    -    <td>
    -     <div id="html">
    -     </div>
    -    </td>
    -   </tr>
    -  </table>
    -  <div id="abcde">abcde</div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/removeformatting_test.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/removeformatting_test.js
    deleted file mode 100644
    index d0db24d1943..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/removeformatting_test.js
    +++ /dev/null
    @@ -1,955 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.editor.plugins.RemoveFormattingTest');
    -goog.setTestOnly('goog.editor.plugins.RemoveFormattingTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.Range');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.editor.BrowserFeature');
    -goog.require('goog.editor.plugins.RemoveFormatting');
    -goog.require('goog.string');
    -goog.require('goog.testing.ExpectedFailures');
    -goog.require('goog.testing.dom');
    -goog.require('goog.testing.editor.FieldMock');
    -goog.require('goog.testing.editor.TestHelper');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -var SAVED_HTML;
    -var FIELDMOCK;
    -var FORMATTER;
    -var testHelper;
    -var WEBKIT_BEFORE_CHROME_8;
    -var WEBKIT_AFTER_CHROME_16;
    -var WEBKIT_AFTER_CHROME_21;
    -var insertImageBoldGarbage = '';
    -var insertImageFontGarbage = '';
    -var controlHtml;
    -var controlCleanHtml;
    -var expectedFailures;
    -
    -function setUpPage() {
    -  WEBKIT_BEFORE_CHROME_8 = goog.userAgent.WEBKIT &&
    -      !goog.userAgent.isVersionOrHigher('534.10');
    -
    -  WEBKIT_AFTER_CHROME_16 = goog.userAgent.WEBKIT &&
    -      goog.userAgent.isVersionOrHigher('535.7');
    -
    -  WEBKIT_AFTER_CHROME_21 = goog.userAgent.WEBKIT &&
    -      goog.userAgent.isVersionOrHigher('537.1');
    -  // On Chrome 16, execCommand('insertImage') inserts a garbage BR
    -  // after the image that we insert. We use this command to paste HTML
    -  // in-place, because it has better paragraph-preserving semantics.
    -  //
    -  // TODO(nicksantos): Figure out if there are better chrome APIs that we
    -  // should be using, or if insertImage should just be fixed.
    -  if (WEBKIT_AFTER_CHROME_21) {
    -    insertImageBoldGarbage = '<br>';
    -    insertImageFontGarbage = '<br>';
    -  } else if (WEBKIT_AFTER_CHROME_16) {
    -    insertImageBoldGarbage = '<b><br/></b>';
    -    insertImageFontGarbage = '<font size="1"><br/></font>';
    -  }
    -  // Extra html to add to test html to make sure removeformatting is actually
    -  // getting called when you're testing if it leaves certain styles alone
    -  // (instead of not even running at all due to some other bug). However, adding
    -  // this extra text into the node to be selected screws up IE.
    -  // (e.g. <a><img></a><b>t</b> --> <a></a><a><img></a>t )
    -  // TODO(user): Remove this special casing once http://b/3131117 is
    -  // fixed.
    -  controlHtml = goog.userAgent.IE ? '' : '<u>control</u>';
    -  controlCleanHtml = goog.userAgent.IE ? '' : 'control';
    -  expectedFailures = new goog.testing.ExpectedFailures();
    -}
    -
    -function setUp() {
    -  testHelper = new goog.testing.editor.TestHelper(
    -      document.getElementById('html'));
    -  testHelper.setUpEditableElement();
    -
    -  FIELDMOCK = new goog.testing.editor.FieldMock();
    -  FIELDMOCK.getElement();
    -  FIELDMOCK.$anyTimes();
    -  FIELDMOCK.$returns(document.getElementById('html'));
    -
    -  FORMATTER = new goog.editor.plugins.RemoveFormatting();
    -  FORMATTER.fieldObject = FIELDMOCK;
    -
    -  FIELDMOCK.$replay();
    -}
    -
    -function tearDown() {
    -  expectedFailures.handleTearDown();
    -  testHelper.tearDownEditableElement();
    -}
    -
    -function setUpTableTests() {
    -  var div = document.getElementById('html');
    -  div.innerHTML = '<table><tr> <th> head1</th><th id= "outerTh">' +
    -      '<span id="emptyTh">head2</span></th> </tr><tr> <td> one </td> <td>' +
    -      'two </td> </tr><tr><td> three</td><td id="outerTd"> ' +
    -      '<span id="emptyTd"><strong>four</strong></span></td></tr>' +
    -      '<tr id="outerTr"><td><span id="emptyTr"> five </span></td></tr>' +
    -      '<tr id="outerTr2"><td id="cell1"><b>seven</b></td><td id="cell2">' +
    -      '<u>eight</u><span id="cellspan2"> foo</span></td></tr></table>';
    -}
    -
    -function testTableTagsAreNotRemoved() {
    -  setUpTableTests();
    -  var span;
    -
    -  // TD
    -  span = document.getElementById('emptyTd');
    -  goog.dom.Range.createFromNodeContents(span).select();
    -  FORMATTER.removeFormatting_();
    -
    -  var elem = document.getElementById('outerTd');
    -  assert('TD should not be removed', !!elem);
    -  if (!goog.userAgent.WEBKIT) {
    -    // webkit seems to have an Apple-style-span
    -    assertEquals('TD should be clean', 'four',
    -        goog.string.trim(elem.innerHTML));
    -  }
    -
    -  // TR
    -  span = document.getElementById('outerTr');
    -  goog.dom.Range.createFromNodeContents(span).select();
    -  FORMATTER.removeFormatting_();
    -
    -  var elem = document.getElementById('outerTr');
    -  assert('TR should not be removed', !!elem);
    -
    -  // TH
    -  span = document.getElementById('emptyTh');
    -  goog.dom.Range.createFromNodeContents(span).select();
    -  FORMATTER.removeFormatting_();
    -
    -  var elem = document.getElementById('outerTh');
    -  assert('TH should not be removed', !!elem);
    -  if (!goog.userAgent.WEBKIT) {
    -    // webkit seems to have an Apple-style-span
    -    assertEquals('TH should be clean', 'head2', elem.innerHTML);
    -  }
    -
    -}
    -
    -
    -/**
    - * We select two cells from the table and then make sure that there is no
    - * data loss and basic formatting is removed from each cell.
    - */
    -function testTableDataIsNotRemoved() {
    -  setUpTableTests();
    -  if (goog.userAgent.IE) {
    -    // IE returns an "unspecified error" which seems to be beyond
    -    // ExpectedFailures' ability to catch.
    -    return;
    -  }
    -
    -  expectedFailures.expectFailureFor(goog.userAgent.WEBKIT,
    -      'The content moves out of the table in WEBKIT.');
    -
    -  if (goog.userAgent.IE) {
    -    // Not used since we bail out early for IE, but this is there so that
    -    // developers can easily reproduce IE error.
    -    goog.dom.Range.createFromNodeContents(
    -        document.getElementById('outerTr2')).select();
    -  } else {
    -    var selection = window.getSelection();
    -    if (selection.rangeCount > 0) selection.removeAllRanges();
    -    var range = document.createRange();
    -    range.selectNode(document.getElementById('cell1'));
    -    selection.addRange(range);
    -    range = document.createRange();
    -    range.selectNode(document.getElementById('cell2'));
    -    selection.addRange(range);
    -  }
    -
    -  expectedFailures.run(function() {
    -    FORMATTER.removeFormatting_();
    -
    -    span = document.getElementById('outerTr2');
    -    assertEquals('Table data should not be removed',
    -        '<td id="cell1">seven</td><td id="cell2">eight foo</td>',
    -        span.innerHTML);
    -  });
    -}
    -
    -function testLinksAreNotRemoved() {
    -  expectedFailures.expectFailureFor(WEBKIT_BEFORE_CHROME_8,
    -      'WebKit\'s removeFormatting command removes links.');
    -
    -  var anchor;
    -  var div = document.getElementById('html');
    -  div.innerHTML = 'Foo<span id="link">Pre<a href="http://www.google.com">' +
    -      'Outside Span<span style="font-size:15pt">Inside Span' +
    -      '</span></a></span>';
    -
    -  anchor = document.getElementById('link');
    -  goog.dom.Range.createFromNodeContents(anchor).select();
    -
    -  expectedFailures.run(function() {
    -    FORMATTER.removeFormatting_();
    -    assertHTMLEquals('link should not be removed',
    -        'FooPre<a href="http://www.google.com/">Outside SpanInside Span</a>',
    -        div.innerHTML);
    -  });
    -}
    -
    -
    -/**
    - * A short formatting removal function for use with the RemoveFormatting
    - * plugin. Does enough that we can tell this function was run over the
    - * document.
    - * @param {string} text The HTML in from the document.
    - * @return {string} The "cleaned" HTML out.
    - */
    -function replacementFormattingFunc(text) {
    -  // Really basic so that we can just see this is executing.
    -  return text.replace(/Foo/gi, 'Bar').replace(/<[\/]*span[^>]*>/gi, '');
    -}
    -
    -function testAlternateRemoveFormattingFunction() {
    -  var div = document.getElementById('html');
    -  div.innerHTML = 'Start<span id="remFormat">Foo<pre>Bar</pre>Baz</span>';
    -
    -  FORMATTER.setRemoveFormattingFunc(replacementFormattingFunc);
    -  var area = document.getElementById('remFormat');
    -  goog.dom.Range.createFromNodeContents(area).select();
    -  FORMATTER.removeFormatting_();
    -  // Webkit will change all tags to non-formatted ones anyway.
    -  // Make sure 'Foo' was changed to 'Bar'
    -  if (WEBKIT_BEFORE_CHROME_8) {
    -    assertHTMLEquals('regular cleaner should not have run',
    -        'StartBar<br>Bar<br>Baz',
    -        div.innerHTML);
    -  } else {
    -    assertHTMLEquals('regular cleaner should not have run',
    -        'StartBar<pre>Bar</pre>Baz',
    -        div.innerHTML);
    -  }
    -}
    -
    -function testGetValueForNode() {
    -  // Override getValueForNode to keep bold tags.
    -  var oldGetValue =
    -      goog.editor.plugins.RemoveFormatting.prototype.getValueForNode;
    -  goog.editor.plugins.RemoveFormatting.prototype.getValueForNode =
    -      function(node) {
    -    if (node.nodeName == goog.dom.TagName.B) {
    -      return '<b>' + this.removeFormattingWorker_(node.innerHTML) + '</b>';
    -    }
    -    return null;
    -  };
    -
    -  var html = FORMATTER.removeFormattingWorker_('<div>foo<b>bar</b></div>');
    -  assertHTMLEquals('B tags should remain', 'foo<b>bar</b>', html);
    -
    -  // Override getValueForNode to throw out bold tags, and their contents.
    -  goog.editor.plugins.RemoveFormatting.prototype.getValueForNode =
    -      function(node) {
    -    if (node.nodeName == goog.dom.TagName.B) {
    -      return '';
    -    }
    -    return null;
    -  };
    -
    -  html = FORMATTER.removeFormattingWorker_('<div>foo<b>bar</b></div>');
    -  assertHTMLEquals('B tag and its contents should be removed', 'foo', html);
    -
    -  FIELDMOCK.$verify();
    -  goog.editor.plugins.RemoveFormatting.prototype.getValueForNode =
    -      oldGetValue;
    -}
    -
    -function testRemoveFormattingAddsNoNbsps() {
    -  var div = document.getElementById('html');
    -  div.innerHTML = '"<span id="toStrip">Twin <b>Cinema</b></span>"';
    -
    -  var span = document.getElementById('toStrip');
    -  goog.dom.Range.createFromNodeContents(span).select();
    -
    -  FORMATTER.removeFormatting_();
    -
    -  assertEquals('Text should be the same, with no non-breaking spaces',
    -      '"Twin Cinema"', div.innerHTML);
    -
    -  FIELDMOCK.$verify();
    -}
    -
    -
    -/**
    - * @bug 992795
    - */
    -function testRemoveFormattingNestedDivs() {
    -  var html = FORMATTER.removeFormattingWorker_(
    -      '<div>1</div><div><div>2</div></div>');
    -
    -  goog.testing.dom.assertHtmlMatches('1<br>2', html);
    -}
    -
    -
    -/**
    - * Test that when we perform remove formatting on an entire table,
    - * that the visual look is similiar to as if there was a table there.
    - */
    -function testRemoveFormattingForTableFormatting() {
    -  // We preserve the table formatting as much as possible.
    -  // Spaces separate TD's, <br>'s separate TR's.
    -  // <br>'s separate the start and end of a table.
    -  var html = '<table><tr><td>cell00</td><td>cell01</td></tr>' +
    -      '<tr><td>cell10</td><td>cell11</td></tr></table>';
    -  html = FORMATTER.removeFormattingWorker_(html);
    -  assertHTMLEquals('<br>cell00 cell01<br>cell10 cell11<br>', html);
    -}
    -
    -
    -/**
    - * @bug 1319715
    - */
    -function testRemoveFormattingDoesNotShrinkSelection() {
    -  var div = document.getElementById('html');
    -  div.innerHTML = '<div>l </div><div><br><b>a</b>foo bar</div>';
    -  var div2 = div.lastChild;
    -
    -  goog.dom.Range.createFromNodes(div2.firstChild, 0,
    -      div2.lastChild, 7).select();
    -
    -  FORMATTER.removeFormatting_();
    -
    -  var range = goog.dom.Range.createFromWindow();
    -  assertEquals('Correct text should be selected', 'afoo bar',
    -      range.getText());
    -
    -  // We have to trim out the leading BR in IE due to execCommand issues,
    -  // so it isn't sent off to the removeFormattingWorker.
    -  // Workaround for broken removeFormat in old webkit added an extra
    -  // <br> to the end of the html.
    -  var html = '<div>l </div><br class="GECKO WEBKIT">afoo bar' +
    -      (goog.editor.BrowserFeature.ADDS_NBSPS_IN_REMOVE_FORMAT ? '<br>' : '');
    -
    -  goog.testing.dom.assertHtmlContentsMatch(html, div);
    -  FIELDMOCK.$verify();
    -}
    -
    -
    -/**
    - *  @bug 1447374
    - */
    -function testInsideListRemoveFormat() {
    -  var div = document.getElementById('html');
    -  div.innerHTML = '<ul><li>one</li><li><b>two</b></li><li>three</li></ul>';
    -
    -  var twoLi = div.firstChild.childNodes[1];
    -  goog.dom.Range.createFromNodeContents(twoLi).select();
    -
    -  expectedFailures.expectFailureFor(goog.userAgent.IE,
    -      'IE adds the "two" to the "three" li, and leaves empty B tags.');
    -  expectedFailures.expectFailureFor(goog.userAgent.WEBKIT,
    -      'WebKit leave the "two" orphaned outside of an li but ' +
    -      'inside the ul (invalid HTML).');
    -
    -  expectedFailures.run(function() {
    -    FORMATTER.removeFormatting_();
    -    // Test that we split the list.
    -    assertHTMLEquals('<ul><li>one</li></ul><br>two<ul><li>three</li></ul>',
    -        div.innerHTML);
    -    FIELDMOCK.$verify();
    -  });
    -}
    -
    -function testFullListRemoveFormat() {
    -  var div = document.getElementById('html');
    -  div.innerHTML =
    -      '<ul><li>one</li><li><b>two</b></li><li>three</li></ul>after';
    -
    -  goog.dom.Range.createFromNodeContents(div.firstChild).select();
    -
    -  //  Note: This may just be a createFromNodeContents issue, as
    -  //  I can't ever make this happen with real user selection.
    -  expectedFailures.expectFailureFor(goog.userAgent.IE,
    -      'IE combines everything into a single LI and leaves the UL.');
    -
    -  expectedFailures.run(function() {
    -    FORMATTER.removeFormatting_();
    -    // Test that we completely remove the list.
    -    assertHTMLEquals('<br>one<br>two<br>threeafter',
    -        div.innerHTML);
    -    FIELDMOCK.$verify();
    -  });
    -}
    -
    -
    -/**
    - *  @bug 1440935
    - */
    -function testPartialListRemoveFormat() {
    -  var div = document.getElementById('html');
    -  div.innerHTML =
    -      '<ul><li>one</li><li>two</li><li>three</li></ul>after';
    -
    -  // Select "two three after".
    -  goog.dom.Range.createFromNodes(div.firstChild.childNodes[1], 0,
    -      div.lastChild, 5).select();
    -
    -  expectedFailures.expectFailureFor(goog.userAgent.IE,
    -      'IE leaves behind an empty LI.');
    -  expectedFailures.expectFailureFor(goog.userAgent.WEBKIT,
    -      'WebKit completely loses the "one".');
    -
    -  expectedFailures.run(function() {
    -    FORMATTER.removeFormatting_();
    -    // Test that we leave the list start alone.
    -    assertHTMLEquals('<ul><li>one</li></ul><br>two<br>threeafter',
    -        div.innerHTML);
    -    FIELDMOCK.$verify();
    -  });
    -}
    -
    -function testBasicRemoveFormatting() {
    -  // IE will clobber the editable div.
    -  // Note: I can't repro this using normal user selections.
    -  if (goog.userAgent.IE) {
    -    return;
    -  }
    -  var div = document.getElementById('html');
    -  div.innerHTML = '<b>bold<i>italic</i></b>';
    -
    -  goog.dom.Range.createFromNodeContents(div).select();
    -
    -  expectedFailures.expectFailureFor(
    -      goog.editor.BrowserFeature.ADDS_NBSPS_IN_REMOVE_FORMAT,
    -      'The workaround for the nbsp bug adds an extra br at the end.');
    -
    -  expectedFailures.run(function() {
    -    FORMATTER.removeFormatting_();
    -    assertHTMLEquals('bolditalic' + insertImageBoldGarbage,
    -        div.innerHTML);
    -    FIELDMOCK.$verify();
    -  });
    -}
    -
    -
    -/**
    - * @bug 1480260
    - */
    -function testPartialBasicRemoveFormatting() {
    -  var div = document.getElementById('html');
    -  div.innerHTML = '<b>bold<i>italic</i></b>';
    -
    -  goog.dom.Range.createFromNodes(div.firstChild.firstChild, 2,
    -      div.firstChild.lastChild.firstChild, 3).select();
    -
    -  expectedFailures.expectFailureFor(WEBKIT_BEFORE_CHROME_8,
    -      'WebKit just gets this all wrong.  Everything stays bold and ' +
    -      '"lditalic" gets italicised.');
    -
    -  expectedFailures.run(function() {
    -    FORMATTER.removeFormatting_();
    -    assertHTMLEquals('<b>bo</b>ldita<b><i>lic</i></b>',
    -        div.innerHTML);
    -    FIELDMOCK.$verify();
    -  });
    -}
    -
    -
    -/**
    - * @bug 3075557
    - */
    -function testRemoveFormattingLinkedImageBorderZero() {
    -  var testHtml = '<a href="http://www.google.com/">' +
    -      '<img src="http://www.google.com/images/logo.gif" border="0"></a>';
    -  var div = document.getElementById('html');
    -  div.innerHTML = testHtml + controlHtml;
    -  goog.dom.Range.createFromNodeContents(div).select();
    -  FORMATTER.removeFormatting_();
    -
    -  expectedFailures.expectFailureFor(goog.userAgent.WEBKIT,
    -      'WebKit removes the image entirely, see ' +
    -      'https://bugs.webkit.org/show_bug.cgi?id=13125 .');
    -
    -  expectedFailures.run(function() {
    -    assertHTMLEquals(
    -        'Image\'s border=0 should not be removed during remove formatting',
    -        testHtml + controlCleanHtml, div.innerHTML);
    -    FIELDMOCK.$verify();
    -  });
    -}
    -
    -
    -/**
    - * @bug 3075557
    - */
    -function testRemoveFormattingLinkedImageBorderNonzero() {
    -  var testHtml = '<a href="http://www.google.com/">' +
    -      '<img src="http://www.google.com/images/logo.gif" border="1"></a>';
    -  var div = document.getElementById('html');
    -  div.innerHTML = testHtml + controlHtml;
    -  goog.dom.Range.createFromNodeContents(div).select();
    -  FORMATTER.removeFormatting_();
    -
    -  expectedFailures.expectFailureFor(goog.userAgent.WEBKIT,
    -      'WebKit removes the image entirely, see ' +
    -      'https://bugs.webkit.org/show_bug.cgi?id=13125 .');
    -
    -  expectedFailures.run(function() {
    -    assertHTMLEquals(
    -        'Image\'s border should be removed during remove formatting' +
    -        ' if non-zero',
    -        testHtml.replace(' border="1"', '') + controlCleanHtml,
    -        div.innerHTML);
    -    FIELDMOCK.$verify();
    -  });
    -}
    -
    -
    -/**
    - * @bug 3075557
    - */
    -function testRemoveFormattingUnlinkedImage() {
    -  var testHtml =
    -      '<img src="http://www.google.com/images/logo.gif" border="0">';
    -  var div = document.getElementById('html');
    -  div.innerHTML = testHtml + controlHtml;
    -  goog.dom.Range.createFromNodeContents(div).select();
    -  FORMATTER.removeFormatting_();
    -
    -  expectedFailures.expectFailureFor(goog.userAgent.WEBKIT,
    -      'WebKit removes the image entirely, see ' +
    -      'https://bugs.webkit.org/show_bug.cgi?id=13125 .');
    -
    -  expectedFailures.run(function() {
    -    assertHTMLEquals(
    -        'Image\'s border=0 should not be removed during remove formatting' +
    -        ' even if not wrapped by a link',
    -        testHtml + controlCleanHtml, div.innerHTML);
    -    FIELDMOCK.$verify();
    -  });
    -}
    -
    -
    -/**
    - * @bug 3075557
    - */
    -function testRemoveFormattingLinkedImageDeep() {
    -  var testHtml = '<a href="http://www.google.com/"><b>hello' +
    -      '<img src="http://www.google.com/images/logo.gif" border="0">' +
    -      'world</b></a>';
    -  var div = document.getElementById('html');
    -  div.innerHTML = testHtml + controlHtml;
    -  goog.dom.Range.createFromNodeContents(div).select();
    -  FORMATTER.removeFormatting_();
    -
    -  expectedFailures.expectFailureFor(WEBKIT_BEFORE_CHROME_8,
    -      'WebKit removes the image entirely, see ' +
    -      'https://bugs.webkit.org/show_bug.cgi?id=13125 .');
    -
    -  expectedFailures.run(function() {
    -    assertHTMLEquals(
    -        'Image\'s border=0 should not be removed during remove formatting' +
    -        ' even if deep inside anchor tag',
    -        testHtml.replace(/<\/?b>/g, '') +
    -        controlCleanHtml + insertImageBoldGarbage,
    -        div.innerHTML);
    -    FIELDMOCK.$verify();
    -  });
    -}
    -
    -function testFullTableRemoveFormatting() {
    -  // Something goes horrible wrong in case 1 below.  It was crashing all
    -  // WebKit browsers, and now seems to be giving errors as it is trying
    -  // to perform remove formatting on the little expected failures window
    -  // instead of the dom we select.  WTF.  Since I'm gutting this code,
    -  // I'm not going to look into this anymore right now.  For what its worth,
    -  // I can't repro any issues in standalone TrogEdit.
    -  if (goog.userAgent.WEBKIT) {
    -    return;
    -  }
    -
    -  var div = document.getElementById('html');
    -
    -  // WebKit has an extra BR in case 2.
    -  expectedFailures.expectFailureFor(goog.userAgent.IE,
    -      'IE clobbers the editable node in case 2 (can\'t repro with real ' +
    -      'user selections). IE doesn\'t remove the table in case 1.');
    -
    -  expectedFailures.run(function() {
    -
    -    // When a full table is selected, we remove it completely.
    -    div.innerHTML = 'foo<table><tr><td>bar</td></tr></table>baz1';
    -    goog.dom.Range.createFromNodeContents(div.childNodes[1]).select();
    -    FORMATTER.removeFormatting_();
    -    assertHTMLEquals('foo<br>bar<br>baz1', div.innerHTML);
    -    FIELDMOCK.$verify();
    -
    -    // Remove the full table when it is selected with additional
    -    // contents too.
    -    div.innerHTML = 'foo<table><tr><td>bar</td></tr></table>baz2';
    -    goog.dom.Range.createFromNodes(div.firstChild, 0,
    -        div.lastChild, 1).select();
    -    FORMATTER.removeFormatting_();
    -    assertHTMLEquals('foo<br>bar<br>baz2', div.innerHTML);
    -    FIELDMOCK.$verify();
    -
    -    // We should still remove the table, even if the selection is inside the
    -    // table and it is fully selected.
    -    div.innerHTML = 'foo<table><tr><td id=\'td\'>bar</td></tr></table>baz3';
    -    goog.dom.Range.createFromNodeContents(
    -        goog.dom.getElement('td').firstChild).select();
    -    FORMATTER.removeFormatting_();
    -    assertHTMLEquals('foo<br>bar<br>baz3', div.innerHTML);
    -    FIELDMOCK.$verify();
    -  });
    -}
    -
    -function testInsideTableRemoveFormatting() {
    -  var div = document.getElementById('html');
    -  div.innerHTML =
    -      '<table><tr><td><b id="b">foo</b></td></tr><tr><td>ba</td></tr></table>';
    -
    -  goog.dom.Range.createFromNodeContents(goog.dom.getElement('b')).select();
    -
    -  // Webkit adds some apple style span crap during execCommand("removeFormat")
    -  // Our workaround for the nbsp bug removes these, but causes worse problems.
    -  // See bugs.webkit.org/show_bug.cgi?id=29164 for more details.
    -  expectedFailures.expectFailureFor(
    -      WEBKIT_BEFORE_CHROME_8 &&
    -      !goog.editor.BrowserFeature.ADDS_NBSPS_IN_REMOVE_FORMAT,
    -      'Extra apple-style-spans');
    -
    -  expectedFailures.run(function() {
    -    FORMATTER.removeFormatting_();
    -
    -    // Only remove styling from inside tables.
    -    assertHTMLEquals(
    -        '<table><tr><td>foo' + insertImageBoldGarbage +
    -        '</td></tr><tr><td>ba</td></tr></table>',
    -        div.innerHTML);
    -    FIELDMOCK.$verify();
    -  });
    -
    -}
    -
    -function testPartialTableRemoveFormatting() {
    -  if (goog.userAgent.IE) {
    -    // IE returns an "unspecified error" which seems to be beyond
    -    // ExpectedFailures' ability to catch.
    -    return;
    -  }
    -
    -  var div = document.getElementById('html');
    -  div.innerHTML = 'bar<table><tr><td><b id="b">foo</b></td></tr>' +
    -                  '<tr><td><i>banana</i></td></tr></table><div id="baz">' +
    -                  'baz</div>';
    -
    -  // Select from the "oo" inside the b tag to the end of "baz".
    -  goog.dom.Range.createFromNodes(goog.dom.getElement('b').firstChild, 1,
    -      goog.dom.getElement('baz').firstChild, 3).select();
    -
    -  // All browsers currently clobber the table cells that are selected.
    -  expectedFailures.expectFailureFor(goog.userAgent.WEBKIT);
    -
    -  expectedFailures.run(function() {
    -    FORMATTER.removeFormatting_();
    -    // Only remove styling from inside tables.
    -    assertHTMLEquals('bar<table><tr><td><b id="b">f</b>oo</td></tr>' +
    -                     '<tr><td>banana</td></tr></table>baz', div.innerHTML);
    -    FIELDMOCK.$verify();
    -  });
    -}
    -
    -// Runs tests knowing some browsers will fail, because the new
    -// table functionality hasn't been implemented in them yet.
    -function runExpectingFailuresForUnimplementedBrowsers(func) {
    -  if (goog.userAgent.IE) {
    -    // IE returns an "unspecified error" which seems to be beyond
    -    // ExpectedFailures' ability to catch.
    -    return;
    -  }
    -
    -  expectedFailures.expectFailureFor(goog.userAgent.IE,
    -      'Proper behavior not yet implemented for IE.');
    -  expectedFailures.expectFailureFor(goog.userAgent.WEBKIT,
    -      'Proper behavior not yet implemented for WebKit.');
    -
    -  expectedFailures.run(func);
    -}
    -
    -
    -function testTwoTablesSelectedFullyRemoveFormatting() {
    -  runExpectingFailuresForUnimplementedBrowsers(function() {
    -    var div = document.getElementById('html');
    -    // When two tables are fully selected, we remove them completely.
    -    div.innerHTML = '<table><tr><td>foo</td></tr></table>' +
    -                    '<table><tr><td>bar</td></tr></table>';
    -    goog.dom.Range.createFromNodes(div.firstChild, 0,
    -        div.lastChild, 1).select();
    -    FORMATTER.removeFormatting_();
    -    assertHTMLEquals('<br>foo<br><br>bar<br>', div.innerHTML);
    -    FIELDMOCK.$verify();
    -  });
    -}
    -
    -function testTwoTablesSelectedFullyInsideRemoveFormatting() {
    -  if (goog.userAgent.WEBKIT) {
    -    // Something goes very wrong here, but it did before
    -    // Julie started writing v2.  Will address when converting
    -    // safari to v2.
    -    return;
    -  }
    -
    -  runExpectingFailuresForUnimplementedBrowsers(function() {
    -    var div = document.getElementById('html');
    -    // When two tables are selected from inside but fully,
    -    // also remove them completely.
    -    div.innerHTML = '<table><tr><td id="td1">foo</td></tr></table>' +
    -                    '<table><tr><td id="td2">bar</td></tr></table>';
    -    goog.dom.Range.createFromNodes(goog.dom.getElement('td1').firstChild, 0,
    -        goog.dom.getElement('td2').firstChild, 3).select();
    -    FORMATTER.removeFormatting_();
    -    assertHTMLEquals('<br>foo<br><br>bar<br>', div.innerHTML);
    -    FIELDMOCK.$verify();
    -  });
    -}
    -
    -function testTwoTablesSelectedFullyAndPartiallyRemoveFormatting() {
    -  runExpectingFailuresForUnimplementedBrowsers(function() {
    -    var div = document.getElementById('html');
    -    // Two tables selected, one fully, one partially. Remove
    -    // only the fully selected one and remove styles only from
    -    // partially selected one.
    -    div.innerHTML = '<table><tr><td id="td1">foo</td></tr></table>' +
    -                    '<table><tr><td id="td2"><b>bar<b></td></tr></table>';
    -    goog.dom.Range.createFromNodes(goog.dom.getElement('td1').firstChild, 0,
    -        goog.dom.getElement('td2').firstChild.firstChild, 2).select();
    -    FORMATTER.removeFormatting_();
    -    assertHTMLEquals('<br>foo<br>' +
    -                     '<table><tr><td id="td2">ba<b>r</b></td></tr></table>',
    -        div.innerHTML);
    -    FIELDMOCK.$verify();
    -  });
    -}
    -
    -function testTwoTablesSelectedPartiallyRemoveFormatting() {
    -  runExpectingFailuresForUnimplementedBrowsers(function() {
    -    var div = document.getElementById('html');
    -    // Two tables selected, both partially.  Don't remove tables,
    -    // but remove styles.
    -    div.innerHTML = '<table><tr><td id="td1">f<i>o</i>o</td></tr></table>' +
    -                    '<table><tr><td id="td2">b<b>a</b>r</td></tr></table>';
    -    goog.dom.Range.createFromNodes(goog.dom.getElement('td1').firstChild, 1,
    -        goog.dom.getElement('td2').childNodes[1], 1).select();
    -    FORMATTER.removeFormatting_();
    -    assertHTMLEquals('<table><tr><td id="td1">foo</td></tr></table>' +
    -                     '<table><tr><td id="td2">bar</td></tr></table>',
    -                     div.innerHTML);
    -    FIELDMOCK.$verify();
    -  });
    -}
    -
    -
    -/**
    - * Test a random snippet from Google News (Google News has complicated
    - * dom structure, including tables, links, images, etc).
    - */
    -function testRandomGoogleNewsSnippetRemoveFormatting() {
    -  if (goog.userAgent.IE) {
    -    // IE returns an "unspecified error" which seems to be beyond
    -    // ExpectedFailures' ability to catch.
    -    return;
    -  }
    -
    -  var div = document.getElementById('html');
    -  div.innerHTML =
    -      '<font size="-3"><br></font><table align="right" border="0" ' +
    -      'cellpadding="0" cellspacing="0"><tbody><tr><td style="padding-left:' +
    -      '6px;" valign="top" width="80" align="center"><a href="http://www.wash' +
    -      'ingtonpost.com/wp-dyn/content/article/2008/11/11/AR2008111101090.htm' +
    -      'l" + id="s-skHRvWH7ryqkcA4caGv0QQ:u-AFQjCNG3vx1HJOxKxMQPzCvYOVRE0JUDe' +
    -      'Q:r-1-0i_1268233361_6_H0_MH20_PL60"><img src="http://news.google.com/' +
    -      'news?imgefp=4LFiNNP62TgJ&amp;imgurl=media3.washingtonpost.com/wp-dyn/' +
    -      'content/photo/2008/11/11/PH2008111101091.jpg" alt="" width="60" ' +
    -      'border="1" height="80"><br><font size="-2">Washington Post</font></a>' +
    -      '</td></tr></tbody></table><a href="http://www.nme.com/news/britney-' +
    -      'spears/40995" id="s-xZUO-t0c1IpsVjyJj0rgxw:u-AFQjCNEZAMQCseEW6uTgXI' +
    -      'iPvAMHe_0B4A:r-1-0_1268233361_6_H0_MH20_PL60"><b>Britney\'s son ' +
    -      'released from hospital</b></a><br><font size="-1"><b><font color=' +
    -      '"#6f6f6f">NME.com&nbsp;-</font> <nobr>53 minutes ago</nobr></b>' +
    -      '</font><br><font size="-1">Britney Spears� youngest son Jayden James ' +
    -      'has been released from hospital, having been admitted on Sunday after' +
    -      ' suffering a severe reaction to something he ingested.</font><br><fon' +
    -      'tsize="-1"><a href="http://www.celebrity-gossip.net/celebrities/holly' +
    -      'wood/britney-and-jamie-lynn-spears-alligator-alley-208944/" id="s-nM' +
    -      'PzHclcMG0J2WZkw9gnVQ:u-AFQjCNHal08usOQ5e5CAQsck2yGsTYeGVQ">Britney ' +
    -      'and Jamie Lynn Spears: Alligator Alley!</a> <font size="-1" color=' +
    -      '"#6f6f6f"><nobr>The Gossip Girls</nobr></font></font><br><font size=' +
    -      '"-1"><a href="http://foodconsumer.org/7777/8888/Other_N_ews_51/111101' +
    -      '362008_Allergy_incident_could_spell_custody_trouble_for_Britney_Spear' +
    -      's.shtml" id="s-2lMNDY4joOprVvkkY_b-6A:u-AFQjCNGAeFNutMEbSg5zAvrh5reBF' +
    -      'lqUmA">Allergy incident could spell trouble for Britney Spears</a> ' +
    -      '<font size="-1" color="#6f6f6f"><nobr>Food Consumer</nobr></font>' +
    -      '</font><br><font class="p" size="-1"><a href="http://www.people.com/' +
    -      'people/article/0,,20239458,00.html" id="s-x9thwVUYVET0ZJOnkkcsjw:u-A' +
    -      'FQjCNE99eijVIrezr9AFRjLkmo5j_Jr7A"><nobr>People Magazine</nobr></a>&nb' +
    -      'sp;- <a href="http://www.eonline.com/uberblog/b68226_hospital_run_cou' +
    -      'ld_cost_britney_custody.html" id="s-kYt5LHDhlDnhUL9kRLuuwA:u-AFQjCNF8' +
    -      '8eOy2utriYuF0icNrZQPzwK8gg"><nobr>E! Online</nobr></a>&nbsp;- <a href' +
    -      '="http://justjared.buzznet.com/2008/11/11/britney-spears-alligator-fa' +
    -      'rm/" id="s--VDy1fyacNvaRo_aXb02Dw:u-AFQjCNEn0Rz3wg0PMwDdzKTDug-9k5W6y' +
    -      'g"><nobr>Just Jared</nobr></a>&nbsp;- <a href="http://www.efluxmedia.' +
    -      'com/news_Britney_Spears_Son_Released_from_Hospital_28696.html" id="s-' +
    -      '8oX6hVDe4Qbcl1x5Rua_EA:u-AFQjCNEpn3nOHA8EB0pxJAPf6diOicMRDg"><nobr>eF' +
    -      'luxMedia</nobr></a></font><br><font class="p" size="-1"><a class="p" ' +
    -      'href="http://news.google.com/news?ncl=1268233361&amp;hl=en"><nobr><b>' +
    -      'all 950 news articles&nbsp;�</b></nobr></a></font>';
    -  // Select it all.
    -  goog.dom.Range.createFromNodeContents(div).select();
    -
    -  expectedFailures.expectFailureFor(WEBKIT_BEFORE_CHROME_8,
    -      'WebKit barfs apple-style-spans all over the place, and removes links.');
    -
    -  expectedFailures.run(function() {
    -    FORMATTER.removeFormatting_();
    -    // Leave links and images alone, remove all other formatting.
    -    assertHTMLEquals('<br><br><a href="http://www.washingtonpost.com/wp-dyn/' +
    -        'content/article/2008/11/11/AR2008111101090.html"><img src="http://n' +
    -        'ews.google.com/news?imgefp=4LFiNNP62TgJ&amp;imgurl=media3.washingto' +
    -        'npost.com/wp-dyn/content/photo/2008/11/11/PH2008111101091.jpg"><br>' +
    -        'Washington Post</a><br><a href="http://www.nme.com/news/britney-spe' +
    -        'ars/40995">Britney\'s son released from hospital</a><br>NME.com - 5' +
    -        '3 minutes ago<br>Britney Spears� youngest son Jayden James has been' +
    -        ' released from hospital, having been admitted on Sunday after suffe' +
    -        'ring a severe reaction to something he ingested.<br><a href="http:/' +
    -        '/www.celebrity-gossip.net/celebrities/hollywood/britney-and-jamie-l' +
    -        'ynn-spears-alligator-alley-208944/">Britney and Jamie Lynn Spears: ' +
    -        'Alligator Alley!</a> The Gossip Girls<br><a href="http://foodconsum' +
    -        'er.org/7777/8888/Other_N_ews_51/111101362008_Allergy_incident_could' +
    -        '_spell_custody_trouble_for_Britney_Spears.shtml">Allergy incident c' +
    -        'ould spell trouble for Britney Spears</a> Food Consumer<br><a href=' +
    -        '"http://www.people.com/people/article/0,,20239458,00.html">People M' +
    -        'agazine</a> - <a href="http://www.eonline.com/uberblog/b68226_hospi' +
    -        'tal_run_could_cost_britney_custody.html">E! Online</a> - <a href="h' +
    -        'ttp://justjared.buzznet.com/2008/11/11/britney-spears-alligator-far' +
    -        'm/">Just Jared</a> - <a href="http://www.efluxmedia.com/news_Britne' +
    -        'y_Spears_Son_Released_from_Hospital_28696.html">eFluxMedia</a><br><' +
    -        'a href="http://news.google.com/news?ncl=1268233361&amp;hl=en">all 9' +
    -        '50 news articles �</a>' +
    -        insertImageFontGarbage, div.innerHTML);
    -    FIELDMOCK.$verify();
    -  });
    -}
    -
    -function testRangeDelimitedByRanges() {
    -  var abcde = goog.dom.getElement('abcde').firstChild;
    -  var start = goog.dom.Range.createFromNodes(abcde, 1, abcde, 2);
    -  var end = goog.dom.Range.createFromNodes(abcde, 3, abcde, 4);
    -
    -  goog.testing.dom.assertRangeEquals(abcde, 1, abcde, 4,
    -      goog.editor.plugins.RemoveFormatting.createRangeDelimitedByRanges_(
    -          start, end));
    -}
    -
    -function testGetTableAncestor() {
    -  var div = document.getElementById('html');
    -
    -  div.innerHTML = 'foo<table><tr><td>foo</td></tr></table>bar';
    -  assertTrue('Full table is in table',
    -      !!FORMATTER.getTableAncestor_(div.childNodes[1]));
    -
    -  assertFalse('Outside of table',
    -      !!FORMATTER.getTableAncestor_(div.firstChild));
    -
    -  assertTrue('Table cell is in table',
    -      !!FORMATTER.getTableAncestor_(
    -          div.childNodes[1].firstChild.firstChild.firstChild));
    -
    -  div.innerHTML = 'foo';
    -  assertNull('No table inside field.',
    -      FORMATTER.getTableAncestor_(div.childNodes[0]));
    -}
    -
    -
    -/**
    - * @bug 1272905
    - */
    -function testHardReturnsInHeadersPreserved() {
    -  var div = document.getElementById('html');
    -  div.innerHTML = '<h1>abcd</h1><h2>efgh</h2><h3>ijkl</h3>';
    -
    -  // Select efgh.
    -  goog.dom.Range.createFromNodeContents(div.childNodes[1]).select();
    -  FORMATTER.removeFormatting_();
    -
    -  expectedFailures.expectFailureFor(goog.userAgent.IE,
    -      'Proper behavior not yet implemented for IE.');
    -  expectedFailures.expectFailureFor(goog.userAgent.WEBKIT,
    -      'Proper behavior not yet implemented for WebKit.');
    -  expectedFailures.run(function() {
    -    assertHTMLEquals('<h1>abcd</h1><br>efgh<h3>ijkl</h3>', div.innerHTML);
    -  });
    -
    -  // Select ijkl.
    -  goog.dom.Range.createFromNodeContents(div.lastChild).select();
    -  FORMATTER.removeFormatting_();
    -
    -  expectedFailures.expectFailureFor(goog.userAgent.IE,
    -      'Proper behavior not yet implemented for IE.');
    -  expectedFailures.expectFailureFor(goog.userAgent.WEBKIT,
    -      'Proper behavior not yet implemented for WebKit.');
    -  expectedFailures.run(function() {
    -    assertHTMLEquals('<h1>abcd</h1><br>efgh<br>ijkl', div.innerHTML);
    -  });
    -
    -  // Select abcd.
    -  goog.dom.Range.createFromNodeContents(div.firstChild).select();
    -  FORMATTER.removeFormatting_();
    -
    -  expectedFailures.expectFailureFor(goog.userAgent.IE,
    -      'Proper behavior not yet implemented for IE.');
    -  expectedFailures.expectFailureFor(goog.userAgent.WEBKIT,
    -      'Proper behavior not yet implemented for WebKit.');
    -  expectedFailures.run(function() {
    -    assertHTMLEquals('<br>abcd<br>efgh<br>ijkl', div.innerHTML);
    -  });
    -}
    -
    -function testKeyboardShortcut_space() {
    -  FIELDMOCK.$reset();
    -
    -  FIELDMOCK.execCommand(
    -      goog.editor.plugins.RemoveFormatting.REMOVE_FORMATTING_COMMAND);
    -
    -  FIELDMOCK.$replay();
    -
    -  var e = {};
    -  var key = ' ';
    -  var result = FORMATTER.handleKeyboardShortcut(e, key, true);
    -  assertTrue(result);
    -
    -  FIELDMOCK.$verify();
    -}
    -
    -function testKeyboardShortcut_other() {
    -  FIELDMOCK.$reset();
    -  FIELDMOCK.$replay();
    -
    -  var e = {};
    -  var key = 'a';
    -  var result = FORMATTER.handleKeyboardShortcut(e, key, true);
    -  assertFalse(result);
    -
    -  FIELDMOCK.$verify();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/spacestabhandler.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/spacestabhandler.js
    deleted file mode 100644
    index 3cb703e5f76..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/spacestabhandler.js
    +++ /dev/null
    @@ -1,92 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Editor plugin to handle tab keys not in lists to add 4 spaces.
    - *
    - * @author robbyw@google.com (Robby Walker)
    - */
    -
    -goog.provide('goog.editor.plugins.SpacesTabHandler');
    -
    -goog.require('goog.dom.TagName');
    -goog.require('goog.editor.plugins.AbstractTabHandler');
    -goog.require('goog.editor.range');
    -
    -
    -
    -/**
    - * Plugin to handle tab keys when not in lists to add 4 spaces.
    - * @constructor
    - * @extends {goog.editor.plugins.AbstractTabHandler}
    - * @final
    - */
    -goog.editor.plugins.SpacesTabHandler = function() {
    -  goog.editor.plugins.AbstractTabHandler.call(this);
    -};
    -goog.inherits(goog.editor.plugins.SpacesTabHandler,
    -    goog.editor.plugins.AbstractTabHandler);
    -
    -
    -/** @override */
    -goog.editor.plugins.SpacesTabHandler.prototype.getTrogClassId = function() {
    -  return 'SpacesTabHandler';
    -};
    -
    -
    -/** @override */
    -goog.editor.plugins.SpacesTabHandler.prototype.handleTabKey = function(e) {
    -  var dh = this.getFieldDomHelper();
    -  var range = this.getFieldObject().getRange();
    -  if (!goog.editor.range.intersectsTag(range, goog.dom.TagName.LI)) {
    -    // In the shift + tab case we don't want to insert spaces, but we don't
    -    // want focus to move either so skip the spacing logic and just prevent
    -    // default.
    -    if (!e.shiftKey) {
    -      // Not in a list but we want to insert 4 spaces.
    -
    -      // Stop change events while we make multiple field changes.
    -      this.getFieldObject().stopChangeEvents(true, true);
    -
    -      // Inserting nodes below completely messes up the selection, doing the
    -      // deletion here before it's messed up. Only delete if text is selected,
    -      // otherwise we would remove the character to the right of the cursor.
    -      if (!range.isCollapsed()) {
    -        dh.getDocument().execCommand('delete', false, null);
    -        // Safari 3 has some DOM exceptions if we don't reget the range here,
    -        // doing it all the time just to be safe.
    -        range = this.getFieldObject().getRange();
    -      }
    -
    -      // Emulate tab by removing selection and inserting 4 spaces
    -      // Two breaking spaces in a row can be collapsed by the browser into one
    -      // space. Inserting the string below because it is guaranteed to never
    -      // collapse to less than four spaces, regardless of what is adjacent to
    -      // the inserted spaces. This might make line wrapping slightly
    -      // sub-optimal around a grouping of non-breaking spaces.
    -      var elem = dh.createDom('span', null, '\u00a0\u00a0 \u00a0');
    -      elem = range.insertNode(elem, false);
    -
    -      this.getFieldObject().dispatchChange();
    -      goog.editor.range.placeCursorNextTo(elem, false);
    -      this.getFieldObject().dispatchSelectionChangeEvent();
    -    }
    -
    -    e.preventDefault();
    -    return true;
    -  }
    -
    -  return false;
    -};
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/spacestabhandler_test.html b/src/database/third_party/closure-library/closure/goog/editor/plugins/spacestabhandler_test.html
    deleted file mode 100644
    index f811ab72cc7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/spacestabhandler_test.html
    +++ /dev/null
    @@ -1,30 +0,0 @@
    -<!DOCTYPE html>
    -<!--
    -
    -  @author robbyw@google.com (Robby Walker)
    --->
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.editor.plugins.SpacesTabHandler
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script src="../../deps.js">
    -  </script>
    -  <script>
    -    goog.require('goog.editor.plugins.SpacesTabHandlerTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="field">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/spacestabhandler_test.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/spacestabhandler_test.js
    deleted file mode 100644
    index 79f744c0b3c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/spacestabhandler_test.js
    +++ /dev/null
    @@ -1,174 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.editor.plugins.SpacesTabHandlerTest');
    -goog.setTestOnly('goog.editor.plugins.SpacesTabHandlerTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.Range');
    -goog.require('goog.editor.plugins.SpacesTabHandler');
    -goog.require('goog.events.BrowserEvent');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.functions');
    -goog.require('goog.testing.StrictMock');
    -goog.require('goog.testing.editor.FieldMock');
    -goog.require('goog.testing.editor.TestHelper');
    -goog.require('goog.testing.jsunit');
    -
    -var field;
    -var editableField;
    -var tabHandler;
    -var testHelper;
    -
    -function setUp() {
    -  field = goog.dom.getElement('field');
    -  editableField = new goog.testing.editor.FieldMock();
    -  // Modal mode behavior tested in AbstractTabHandler.
    -  editableField.inModalMode = goog.functions.FALSE;
    -  testHelper = new goog.testing.editor.TestHelper(field);
    -  testHelper.setUpEditableElement();
    -
    -  tabHandler = new goog.editor.plugins.SpacesTabHandler();
    -  tabHandler.registerFieldObject(editableField);
    -}
    -
    -function tearDown() {
    -  editableField = null;
    -  testHelper.tearDownEditableElement();
    -  tabHandler.dispose();
    -}
    -
    -function testSelectedTextIndent() {
    -  field.innerHTML = 'Test';
    -
    -  var testText = field.firstChild;
    -  testHelper.select(testText, 0, testText, 4);
    -
    -  var event = new goog.testing.StrictMock(goog.events.BrowserEvent);
    -  event.keyCode = goog.events.KeyCodes.TAB;
    -  event.shiftKey = false;
    -
    -  editableField.stopChangeEvents(true, true);
    -  editableField.dispatchChange();
    -  editableField.dispatchSelectionChangeEvent();
    -  event.preventDefault();
    -
    -  editableField.$replay();
    -  event.$replay();
    -
    -  assertTrue('Event marked as handled',
    -      tabHandler.handleKeyboardShortcut(event, '', false));
    -  var contents = field.textContent || field.innerText;
    -  // Chrome doesn't treat \u00a0 as a space.
    -  assertTrue('Text should be replaced with 4 spaces but was: "' +
    -      contents + '"',
    -      /^(\s|\u00a0){4}$/.test(contents));
    -
    -  editableField.$verify();
    -  event.$verify();
    -}
    -
    -function testCursorIndent() {
    -  field.innerHTML = 'Test';
    -
    -  var testText = field.firstChild;
    -  testHelper.select(testText, 2, testText, 2);
    -
    -  var event = new goog.testing.StrictMock(goog.events.BrowserEvent);
    -  event.keyCode = goog.events.KeyCodes.TAB;
    -  event.shiftKey = false;
    -
    -  editableField.stopChangeEvents(true, true);
    -  editableField.dispatchChange();
    -  editableField.dispatchSelectionChangeEvent();
    -  event.preventDefault();
    -
    -  editableField.$replay();
    -  event.$replay();
    -
    -  assertTrue('Event marked as handled',
    -      tabHandler.handleKeyboardShortcut(event, '', false));
    -  var contents = field.textContent || field.innerText;
    -  assertTrue('Expected contents "Te    st" but was: "' + contents + '"',
    -      /Te[\s|\u00a0]{4}st/.test(contents));
    -
    -  editableField.$verify();
    -  event.$verify();
    -}
    -
    -function testShiftTabNoOp() {
    -  field.innerHTML = 'Test';
    -
    -  range = goog.dom.Range.createFromNodeContents(field);
    -  range.collapse();
    -  range.select();
    -
    -  var event = new goog.testing.StrictMock(goog.events.BrowserEvent);
    -  event.keyCode = goog.events.KeyCodes.TAB;
    -  event.shiftKey = true;
    -
    -  event.preventDefault();
    -  editableField.$replay();
    -  event.$replay();
    -
    -  assertTrue('Event marked as handled',
    -      tabHandler.handleKeyboardShortcut(event, '', false));
    -  var contents = field.textContent || field.innerText;
    -  assertEquals('Shift+tab should not change contents', 'Test', contents);
    -
    -  editableField.$verify();
    -  event.$verify();
    -}
    -
    -function testInListNoOp() {
    -  field.innerHTML = '<ul><li>Test</li></ul>';
    -
    -  var testText = field.firstChild.firstChild.firstChild; // div ul li Test
    -  testHelper.select(testText, 2, testText, 2);
    -
    -  var event = new goog.testing.StrictMock(goog.events.BrowserEvent);
    -  event.keyCode = goog.events.KeyCodes.TAB;
    -  event.shiftKey = false;
    -
    -  editableField.$replay();
    -  event.$replay();
    -
    -  assertFalse('Event must not be handled when selection inside list.',
    -      tabHandler.handleKeyboardShortcut(event, '', false));
    -  testHelper.assertHtmlMatches('<ul><li>Test</li></ul>');
    -
    -  editableField.$verify();
    -  event.$verify();
    -}
    -
    -function testContainsListNoOp() {
    -  field.innerHTML = '<ul><li>Test</li></ul>';
    -
    -  var testText = field.firstChild.firstChild.firstChild; // div ul li Test
    -  testHelper.select(field.firstChild, 0, testText, 2);
    -
    -  var event = new goog.testing.StrictMock(goog.events.BrowserEvent);
    -  event.keyCode = goog.events.KeyCodes.TAB;
    -  event.shiftKey = false;
    -
    -  editableField.$replay();
    -  event.$replay();
    -
    -  assertFalse('Event must not be handled when selection inside list.',
    -      tabHandler.handleKeyboardShortcut(event, '', false));
    -  testHelper.assertHtmlMatches('<ul><li>Test</li></ul>');
    -
    -  editableField.$verify();
    -  event.$verify();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/tableeditor.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/tableeditor.js
    deleted file mode 100644
    index f83cb9687ca..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/tableeditor.js
    +++ /dev/null
    @@ -1,475 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Plugin that enables table editing.
    - *
    - * @see ../../demos/editor/tableeditor.html
    - */
    -
    -goog.provide('goog.editor.plugins.TableEditor');
    -
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.dom.Range');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.editor.Plugin');
    -goog.require('goog.editor.Table');
    -goog.require('goog.editor.node');
    -goog.require('goog.editor.range');
    -goog.require('goog.object');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Plugin that adds support for table creation and editing commands.
    - * @constructor
    - * @extends {goog.editor.Plugin}
    - * @final
    - */
    -goog.editor.plugins.TableEditor = function() {
    -  goog.editor.plugins.TableEditor.base(this, 'constructor');
    -
    -  /**
    -   * The array of functions that decide whether a table element could be
    -   * editable by the user or not.
    -   * @type {Array<function(Element):boolean>}
    -   * @private
    -   */
    -  this.isTableEditableFunctions_ = [];
    -
    -  /**
    -   * The pre-bound function that decides whether a table element could be
    -   * editable by the user or not overall.
    -   * @type {function(Node):boolean}
    -   * @private
    -   */
    -  this.isUserEditableTableBound_ = goog.bind(this.isUserEditableTable_, this);
    -};
    -goog.inherits(goog.editor.plugins.TableEditor, goog.editor.Plugin);
    -
    -
    -/** @override */
    -// TODO(user): remove this once there's a sensible default
    -// implementation in the base Plugin.
    -goog.editor.plugins.TableEditor.prototype.getTrogClassId = function() {
    -  return String(goog.getUid(this.constructor));
    -};
    -
    -
    -/**
    - * Commands supported by goog.editor.plugins.TableEditor.
    - * @enum {string}
    - */
    -goog.editor.plugins.TableEditor.COMMAND = {
    -  TABLE: '+table',
    -  INSERT_ROW_AFTER: '+insertRowAfter',
    -  INSERT_ROW_BEFORE: '+insertRowBefore',
    -  INSERT_COLUMN_AFTER: '+insertColumnAfter',
    -  INSERT_COLUMN_BEFORE: '+insertColumnBefore',
    -  REMOVE_ROWS: '+removeRows',
    -  REMOVE_COLUMNS: '+removeColumns',
    -  SPLIT_CELL: '+splitCell',
    -  MERGE_CELLS: '+mergeCells',
    -  REMOVE_TABLE: '+removeTable'
    -};
    -
    -
    -/**
    - * Inverse map of execCommand strings to
    - * {@link goog.editor.plugins.TableEditor.COMMAND} constants. Used to
    - * determine whether a string corresponds to a command this plugin handles
    - * in O(1) time.
    - * @type {Object}
    - * @private
    - */
    -goog.editor.plugins.TableEditor.SUPPORTED_COMMANDS_ =
    -    goog.object.transpose(goog.editor.plugins.TableEditor.COMMAND);
    -
    -
    -/**
    - * Whether the string corresponds to a command this plugin handles.
    - * @param {string} command Command string to check.
    - * @return {boolean} Whether the string corresponds to a command
    - *     this plugin handles.
    - * @override
    - */
    -goog.editor.plugins.TableEditor.prototype.isSupportedCommand =
    -    function(command) {
    -  return command in goog.editor.plugins.TableEditor.SUPPORTED_COMMANDS_;
    -};
    -
    -
    -/** @override */
    -goog.editor.plugins.TableEditor.prototype.enable = function(fieldObject) {
    -  goog.editor.plugins.TableEditor.base(this, 'enable', fieldObject);
    -
    -  // enableObjectResizing is supported only for Gecko.
    -  // You can refer to http://qooxdoo.org/contrib/project/htmlarea/html_editing
    -  // for a compatibility chart.
    -  if (goog.userAgent.GECKO) {
    -    var doc = this.getFieldDomHelper().getDocument();
    -    doc.execCommand('enableObjectResizing', false, 'true');
    -  }
    -};
    -
    -
    -/**
    - * Returns the currently selected table.
    - * @return {Element?} The table in which the current selection is
    - *     contained, or null if there isn't such a table.
    - * @private
    - */
    -goog.editor.plugins.TableEditor.prototype.getCurrentTable_ = function() {
    -  var selectedElement = this.getFieldObject().getRange().getContainer();
    -  return this.getAncestorTable_(selectedElement);
    -};
    -
    -
    -/**
    - * Finds the first user-editable table element in the input node's ancestors.
    - * @param {Node?} node The node to start with.
    - * @return {Element?} The table element that is closest ancestor of the node.
    - * @private
    - */
    -goog.editor.plugins.TableEditor.prototype.getAncestorTable_ = function(node) {
    -  var ancestor = goog.dom.getAncestor(node, this.isUserEditableTableBound_,
    -      true);
    -  if (goog.editor.node.isEditable(ancestor)) {
    -    return /** @type {Element?} */(ancestor);
    -  } else {
    -    return null;
    -  }
    -};
    -
    -
    -/**
    - * Returns the current value of a given command. Currently this plugin
    - * only returns a value for goog.editor.plugins.TableEditor.COMMAND.TABLE.
    - * @override
    - */
    -goog.editor.plugins.TableEditor.prototype.queryCommandValue =
    -    function(command) {
    -  if (command == goog.editor.plugins.TableEditor.COMMAND.TABLE) {
    -    return !!this.getCurrentTable_();
    -  }
    -};
    -
    -
    -/** @override */
    -goog.editor.plugins.TableEditor.prototype.execCommandInternal = function(
    -    command, opt_arg) {
    -  var result = null;
    -  // TD/TH in which to place the cursor, if the command destroys the current
    -  // cursor position.
    -  var cursorCell = null;
    -  var range = this.getFieldObject().getRange();
    -  if (command == goog.editor.plugins.TableEditor.COMMAND.TABLE) {
    -    // Don't create a table if the cursor isn't in an editable region.
    -    if (!goog.editor.range.isEditable(range)) {
    -      return null;
    -    }
    -    // Create the table.
    -    var tableProps = opt_arg || {width: 4, height: 2};
    -    var doc = this.getFieldDomHelper().getDocument();
    -    var table = goog.editor.Table.createDomTable(
    -        doc, tableProps.width, tableProps.height);
    -    range.replaceContentsWithNode(table);
    -    // In IE, replaceContentsWithNode uses pasteHTML, so we lose our reference
    -    // to the inserted table.
    -    // TODO(user): use the reference to the table element returned from
    -    // replaceContentsWithNode.
    -    if (!goog.userAgent.IE) {
    -      cursorCell = table.getElementsByTagName('td')[0];
    -    }
    -  } else {
    -    var cellSelection = new goog.editor.plugins.TableEditor.CellSelection_(
    -        range, goog.bind(this.getAncestorTable_, this));
    -    var table = cellSelection.getTable();
    -    if (!table) {
    -      return null;
    -    }
    -    switch (command) {
    -      case goog.editor.plugins.TableEditor.COMMAND.INSERT_ROW_BEFORE:
    -        table.insertRow(cellSelection.getFirstRowIndex());
    -        break;
    -      case goog.editor.plugins.TableEditor.COMMAND.INSERT_ROW_AFTER:
    -        table.insertRow(cellSelection.getLastRowIndex() + 1);
    -        break;
    -      case goog.editor.plugins.TableEditor.COMMAND.INSERT_COLUMN_BEFORE:
    -        table.insertColumn(cellSelection.getFirstColumnIndex());
    -        break;
    -      case goog.editor.plugins.TableEditor.COMMAND.INSERT_COLUMN_AFTER:
    -        table.insertColumn(cellSelection.getLastColumnIndex() + 1);
    -        break;
    -      case goog.editor.plugins.TableEditor.COMMAND.REMOVE_ROWS:
    -        var startRow = cellSelection.getFirstRowIndex();
    -        var endRow = cellSelection.getLastRowIndex();
    -        if (startRow == 0 && endRow == (table.rows.length - 1)) {
    -          // Instead of deleting all rows, delete the entire table.
    -          return this.execCommandInternal(
    -              goog.editor.plugins.TableEditor.COMMAND.REMOVE_TABLE);
    -        }
    -        var startColumn = cellSelection.getFirstColumnIndex();
    -        var rowCount = (endRow - startRow) + 1;
    -        for (var i = 0; i < rowCount; i++) {
    -          table.removeRow(startRow);
    -        }
    -        if (table.rows.length > 0) {
    -          // Place cursor in the previous/first row.
    -          var closestRow = Math.min(startRow, table.rows.length - 1);
    -          cursorCell = table.rows[closestRow].columns[startColumn].element;
    -        }
    -        break;
    -      case goog.editor.plugins.TableEditor.COMMAND.REMOVE_COLUMNS:
    -        var startCol = cellSelection.getFirstColumnIndex();
    -        var endCol = cellSelection.getLastColumnIndex();
    -        if (startCol == 0 && endCol == (table.rows[0].columns.length - 1)) {
    -          // Instead of deleting all columns, delete the entire table.
    -          return this.execCommandInternal(
    -              goog.editor.plugins.TableEditor.COMMAND.REMOVE_TABLE);
    -        }
    -        var startRow = cellSelection.getFirstRowIndex();
    -        var removeCount = (endCol - startCol) + 1;
    -        for (var i = 0; i < removeCount; i++) {
    -          table.removeColumn(startCol);
    -        }
    -        var currentRow = table.rows[startRow];
    -        if (currentRow) {
    -          // Place cursor in the previous/first column.
    -          var closestCol = Math.min(startCol, currentRow.columns.length - 1);
    -          cursorCell = currentRow.columns[closestCol].element;
    -        }
    -        break;
    -      case goog.editor.plugins.TableEditor.COMMAND.MERGE_CELLS:
    -        if (cellSelection.isRectangle()) {
    -          table.mergeCells(cellSelection.getFirstRowIndex(),
    -                           cellSelection.getFirstColumnIndex(),
    -                           cellSelection.getLastRowIndex(),
    -                           cellSelection.getLastColumnIndex());
    -        }
    -        break;
    -      case goog.editor.plugins.TableEditor.COMMAND.SPLIT_CELL:
    -        if (cellSelection.containsSingleCell()) {
    -          table.splitCell(cellSelection.getFirstRowIndex(),
    -                          cellSelection.getFirstColumnIndex());
    -        }
    -        break;
    -      case goog.editor.plugins.TableEditor.COMMAND.REMOVE_TABLE:
    -        table.element.parentNode.removeChild(table.element);
    -        break;
    -      default:
    -    }
    -  }
    -  if (cursorCell) {
    -    range = goog.dom.Range.createFromNodeContents(cursorCell);
    -    range.collapse(false);
    -    range.select();
    -  }
    -  return result;
    -};
    -
    -
    -/**
    - * Checks whether the element is a table editable by the user.
    - * @param {Node} element The element in question.
    - * @return {boolean} Whether the element is a table editable by the user.
    - * @private
    - */
    -goog.editor.plugins.TableEditor.prototype.isUserEditableTable_ =
    -    function(element) {
    -  // Default implementation.
    -  if (element.tagName != goog.dom.TagName.TABLE) {
    -    return false;
    -  }
    -
    -  // Check for extra user-editable filters.
    -  return goog.array.every(this.isTableEditableFunctions_, function(func) {
    -    return func(/** @type {Element} */ (element));
    -  });
    -};
    -
    -
    -/**
    - * Adds a function to filter out non-user-editable tables.
    - * @param {function(Element):boolean} func A function to decide whether the
    - *   table element could be editable by the user or not.
    - */
    -goog.editor.plugins.TableEditor.prototype.addIsTableEditableFunction =
    -    function(func) {
    -  goog.array.insert(this.isTableEditableFunctions_, func);
    -};
    -
    -
    -
    -/**
    - * Class representing the selected cell objects within a single  table.
    - * @param {goog.dom.AbstractRange} range Selected range from which to calculate
    - *     selected cells.
    - * @param {function(Element):Element?} getParentTableFunction A function that
    - *     finds the user-editable table from a given element.
    - * @constructor
    - * @private
    - */
    -goog.editor.plugins.TableEditor.CellSelection_ =
    -    function(range, getParentTableFunction) {
    -  this.cells_ = [];
    -
    -  // Mozilla lets users select groups of cells, with each cell showing
    -  // up as a separate range in the selection. goog.dom.Range doesn't
    -  // currently support this.
    -  // TODO(user): support this case in range.js
    -  var selectionContainer = range.getContainerElement();
    -  var elementInSelection = function(node) {
    -    // TODO(user): revert to the more liberal containsNode(node, true),
    -    // which will match partially-selected cells. We're using
    -    // containsNode(node, false) at the moment because otherwise it's
    -    // broken in WebKit due to a closure range bug.
    -    return selectionContainer == node ||
    -        selectionContainer.parentNode == node ||
    -        range.containsNode(node, false);
    -  };
    -
    -  var parentTableElement = selectionContainer &&
    -      getParentTableFunction(selectionContainer);
    -  if (!parentTableElement) {
    -    return;
    -  }
    -
    -  var parentTable = new goog.editor.Table(parentTableElement);
    -  // It's probably not possible to select a table with no cells, but
    -  // do a sanity check anyway.
    -  if (!parentTable.rows.length || !parentTable.rows[0].columns.length) {
    -    return;
    -  }
    -  // Loop through cells to calculate dimensions for this CellSelection.
    -  for (var i = 0, row; row = parentTable.rows[i]; i++) {
    -    for (var j = 0, cell; cell = row.columns[j]; j++) {
    -      if (elementInSelection(cell.element)) {
    -        // Update dimensions based on cell.
    -        if (!this.cells_.length) {
    -          this.firstRowIndex_ = cell.startRow;
    -          this.lastRowIndex_ = cell.endRow;
    -          this.firstColIndex_ = cell.startCol;
    -          this.lastColIndex_ = cell.endCol;
    -        } else {
    -          this.firstRowIndex_ = Math.min(this.firstRowIndex_, cell.startRow);
    -          this.lastRowIndex_ = Math.max(this.lastRowIndex_, cell.endRow);
    -          this.firstColIndex_ = Math.min(this.firstColIndex_, cell.startCol);
    -          this.lastColIndex_ = Math.max(this.lastColIndex_, cell.endCol);
    -        }
    -        this.cells_.push(cell);
    -      }
    -    }
    -  }
    -  this.parentTable_ = parentTable;
    -};
    -
    -
    -/**
    - * Returns the EditableTable object of which this selection's cells are a
    - * subset.
    - * @return {!goog.editor.Table} the table.
    - */
    -goog.editor.plugins.TableEditor.CellSelection_.prototype.getTable =
    -    function() {
    -  return this.parentTable_;
    -};
    -
    -
    -/**
    - * Returns the row index of the uppermost cell in this selection.
    - * @return {number} The row index.
    - */
    -goog.editor.plugins.TableEditor.CellSelection_.prototype.getFirstRowIndex =
    -    function() {
    -  return this.firstRowIndex_;
    -};
    -
    -
    -/**
    - * Returns the row index of the lowermost cell in this selection.
    - * @return {number} The row index.
    - */
    -goog.editor.plugins.TableEditor.CellSelection_.prototype.getLastRowIndex =
    -    function() {
    -  return this.lastRowIndex_;
    -};
    -
    -
    -/**
    - * Returns the column index of the farthest left cell in this selection.
    - * @return {number} The column index.
    - */
    -goog.editor.plugins.TableEditor.CellSelection_.prototype.getFirstColumnIndex =
    -    function() {
    -  return this.firstColIndex_;
    -};
    -
    -
    -/**
    - * Returns the column index of the farthest right cell in this selection.
    - * @return {number} The column index.
    - */
    -goog.editor.plugins.TableEditor.CellSelection_.prototype.getLastColumnIndex =
    -    function() {
    -  return this.lastColIndex_;
    -};
    -
    -
    -/**
    - * Returns the cells in this selection.
    - * @return {!Array<Element>} Cells in this selection.
    - */
    -goog.editor.plugins.TableEditor.CellSelection_.prototype.getCells = function() {
    -  return this.cells_;
    -};
    -
    -
    -/**
    - * Returns a boolean value indicating whether or not the cells in this
    - * selection form a rectangle.
    - * @return {boolean} Whether the selection forms a rectangle.
    - */
    -goog.editor.plugins.TableEditor.CellSelection_.prototype.isRectangle =
    -    function() {
    -  // TODO(user): check for missing cells. Right now this returns
    -  // whether all cells in the selection are in the rectangle, but doesn't
    -  // verify that every expected cell is present.
    -  if (!this.cells_.length) {
    -    return false;
    -  }
    -  var firstCell = this.cells_[0];
    -  var lastCell = this.cells_[this.cells_.length - 1];
    -  return !(this.firstRowIndex_ < firstCell.startRow ||
    -           this.lastRowIndex_ > lastCell.endRow ||
    -           this.firstColIndex_ < firstCell.startCol ||
    -           this.lastColIndex_ > lastCell.endCol);
    -};
    -
    -
    -/**
    - * Returns a boolean value indicating whether or not there is exactly
    - * one cell in this selection. Note that this may not be the same as checking
    - * whether getCells().length == 1; if there is a single cell with
    - * rowSpan/colSpan set it will appear multiple times.
    - * @return {boolean} Whether there is exatly one cell in this selection.
    - */
    -goog.editor.plugins.TableEditor.CellSelection_.prototype.containsSingleCell =
    -    function() {
    -  var cellCount = this.cells_.length;
    -  return cellCount > 0 &&
    -      (this.cells_[0] == this.cells_[cellCount - 1]);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/tableeditor_test.html b/src/database/third_party/closure-library/closure/goog/editor/plugins/tableeditor_test.html
    deleted file mode 100644
    index 3d08ac16719..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/tableeditor_test.html
    +++ /dev/null
    @@ -1,30 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   goog.editor.plugins.TableEditor Tests
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.editor.plugins.TableEditorTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="field">
    -   <div>
    -    lorem ipsum
    -   </div>
    -   <div>
    -    ipsum lorem
    -   </div>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/tableeditor_test.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/tableeditor_test.js
    deleted file mode 100644
    index d9acf4bcfba..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/tableeditor_test.js
    +++ /dev/null
    @@ -1,303 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.editor.plugins.TableEditorTest');
    -goog.setTestOnly('goog.editor.plugins.TableEditorTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.Range');
    -goog.require('goog.editor.plugins.TableEditor');
    -goog.require('goog.object');
    -goog.require('goog.string');
    -goog.require('goog.testing.ExpectedFailures');
    -goog.require('goog.testing.JsUnitException');
    -goog.require('goog.testing.editor.FieldMock');
    -goog.require('goog.testing.editor.TestHelper');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -var field;
    -var plugin;
    -var fieldMock;
    -var expectedFailures;
    -var testHelper;
    -
    -function setUpPage() {
    -  field = goog.dom.getElement('field');
    -  expectedFailures = new goog.testing.ExpectedFailures();
    -}
    -
    -function setUp() {
    -  testHelper = new goog.testing.editor.TestHelper(
    -      goog.dom.getElement('field'));
    -  testHelper.setUpEditableElement();
    -  field.focus();
    -  plugin = new goog.editor.plugins.TableEditor();
    -  fieldMock = new goog.testing.editor.FieldMock();
    -  plugin.registerFieldObject(fieldMock);
    -  if (goog.userAgent.IE &&
    -      (goog.userAgent.compare(goog.userAgent.VERSION, '7.0') >= 0)) {
    -    goog.testing.TestCase.protectedTimeout_ = window.setTimeout;
    -  }
    -}
    -
    -function tearDown() {
    -  testHelper.tearDownEditableElement();
    -  expectedFailures.handleTearDown();
    -}
    -
    -function testEnable() {
    -  fieldMock.$replay();
    -
    -  plugin.enable(fieldMock);
    -  assertTrue('Plugin should be enabled', plugin.isEnabled(fieldMock));
    -
    -  if (goog.userAgent.GECKO) {
    -    // This code path is executed only for GECKO browsers but we can't
    -    // verify it because of a GECKO bug while reading the value of the
    -    // command "enableObjectResizing".
    -    // See https://bugzilla.mozilla.org/show_bug.cgi?id=506368
    -    expectedFailures.expectFailureFor(goog.userAgent.GECKO);
    -    try {
    -      var doc = plugin.getFieldDomHelper().getDocument();
    -      assertTrue('Object resizing should be enabled',
    -                 doc.queryCommandValue('enableObjectResizing'));
    -    } catch (e) {
    -      // We need to marshal our exception in order for it to be handled
    -      // properly.
    -      expectedFailures.handleException(new goog.testing.JsUnitException(e));
    -    }
    -  }
    -  fieldMock.$verify();
    -}
    -
    -function testIsSupportedCommand() {
    -  goog.object.forEach(goog.editor.plugins.TableEditor.COMMAND,
    -      function(command) {
    -        assertTrue(goog.string.subs('Plugin should support %s', command),
    -            plugin.isSupportedCommand(command));
    -      });
    -  assertFalse('Plugin shouldn\'t support a bogus command',
    -              plugin.isSupportedCommand('+fable'));
    -}
    -
    -function testCreateTable() {
    -  fieldMock.$replay();
    -  createTableAndSelectCell();
    -  var table = plugin.getCurrentTable_();
    -  assertNotNull('Table should not be null', table);
    -  assertEquals('Table should have the default number of rows',
    -               2,
    -               table.rows.length);
    -  assertEquals('Table should have the default number of cells',
    -               8,
    -               getCellCount(table));
    -  fieldMock.$verify();
    -}
    -
    -function testInsertRowBefore() {
    -  fieldMock.$replay();
    -  createTableAndSelectCell();
    -  var table = plugin.getCurrentTable_();
    -  var selectedRow = fieldMock.getRange().getContainerElement().parentNode;
    -  assertNull('Selected row shouldn\'t have a previous sibling',
    -             selectedRow.previousSibling);
    -  assertEquals('Table should have two rows', 2, table.rows.length);
    -  plugin.execCommandInternal(
    -      goog.editor.plugins.TableEditor.COMMAND.INSERT_ROW_BEFORE);
    -  assertEquals('A row should have been inserted', 3, table.rows.length);
    -
    -  // Assert that we inserted a row above the currently selected row.
    -  assertNotNull('Selected row should have a previous sibling',
    -                selectedRow.previousSibling);
    -  fieldMock.$verify();
    -}
    -
    -function testInsertRowAfter() {
    -  fieldMock.$replay();
    -  createTableAndSelectCell({width: 2, height: 1});
    -  var selectedRow = fieldMock.getRange().getContainerElement().parentNode;
    -  var table = plugin.getCurrentTable_();
    -  assertEquals('Table should have one row', 1, table.rows.length);
    -  assertNull('Selected row shouldn\'t have a next sibling',
    -             selectedRow.nextSibling);
    -  plugin.execCommandInternal(
    -      goog.editor.plugins.TableEditor.COMMAND.INSERT_ROW_AFTER);
    -  assertEquals('A row should have been inserted', 2, table.rows.length);
    -  // Assert that we inserted a row after the currently selected row.
    -  assertNotNull('Selected row should have a next sibling',
    -                selectedRow.nextSibling);
    -  fieldMock.$verify();
    -}
    -
    -function testInsertColumnBefore() {
    -  fieldMock.$replay();
    -  createTableAndSelectCell({width: 1, height: 1});
    -  var table = plugin.getCurrentTable_();
    -  var selectedCell = fieldMock.getRange().getContainerElement();
    -  assertEquals('Table should have one cell', 1, getCellCount(table));
    -  assertNull('Selected cell shouldn\'t have a previous sibling',
    -             selectedCell.previousSibling);
    -  plugin.execCommandInternal(
    -      goog.editor.plugins.TableEditor.COMMAND.INSERT_COLUMN_BEFORE);
    -  assertEquals('A cell should have been inserted', 2, getCellCount(table));
    -  assertNotNull('Selected cell should have a previous sibling',
    -                selectedCell.previousSibling);
    -  fieldMock.$verify();
    -}
    -
    -function testInsertColumnAfter() {
    -  fieldMock.$replay();
    -  createTableAndSelectCell({width: 1, height: 1});
    -  var table = plugin.getCurrentTable_();
    -  var selectedCell = fieldMock.getRange().getContainerElement();
    -  assertEquals('Table should have one cell', 1, getCellCount(table));
    -  assertNull('Selected cell shouldn\'t have a next sibling',
    -             selectedCell.nextSibling);
    -  plugin.execCommandInternal(
    -      goog.editor.plugins.TableEditor.COMMAND.INSERT_COLUMN_AFTER);
    -  assertEquals('A cell should have been inserted', 2, getCellCount(table));
    -  assertNotNull('Selected cell should have a next sibling',
    -                selectedCell.nextSibling);
    -  fieldMock.$verify();
    -}
    -
    -function testRemoveRows() {
    -  fieldMock.$replay();
    -  createTableAndSelectCell({width: 1, height: 2});
    -  var table = plugin.getCurrentTable_();
    -  var selectedCell = fieldMock.getRange().getContainerElement();
    -  selectedCell.id = 'selected';
    -  assertEquals('Table should have two rows', 2, table.rows.length);
    -  plugin.execCommandInternal(
    -      goog.editor.plugins.TableEditor.COMMAND.REMOVE_ROWS);
    -  assertEquals('A row should have been removed', 1, table.rows.length);
    -  assertNull('The correct row should have been removed',
    -             goog.dom.getElement('selected'));
    -
    -  // Verify that the table is removed if we don't have any rows.
    -  plugin.execCommandInternal(
    -      goog.editor.plugins.TableEditor.COMMAND.REMOVE_ROWS);
    -  assertEquals('The table should have been removed',
    -               0,
    -               field.getElementsByTagName('table').length);
    -  fieldMock.$verify();
    -}
    -
    -function testRemoveColumns() {
    -  fieldMock.$replay();
    -  createTableAndSelectCell({width: 2, height: 1});
    -  var table = plugin.getCurrentTable_();
    -  var selectedCell = fieldMock.getRange().getContainerElement();
    -  selectedCell.id = 'selected';
    -  assertEquals('Table should have two cells', 2, getCellCount(table));
    -  plugin.execCommandInternal(
    -      goog.editor.plugins.TableEditor.COMMAND.REMOVE_COLUMNS);
    -  assertEquals('A cell should have been removed', 1, getCellCount(table));
    -  assertNull('The correct cell should have been removed',
    -             goog.dom.getElement('selected'));
    -
    -  // Verify that the table is removed if we don't have any columns.
    -  plugin.execCommandInternal(
    -      goog.editor.plugins.TableEditor.COMMAND.REMOVE_COLUMNS);
    -  assertEquals('The table should have been removed',
    -               0,
    -               field.getElementsByTagName('table').length);
    -  fieldMock.$verify();
    -}
    -
    -function testSplitCell() {
    -  fieldMock.$replay();
    -  createTableAndSelectCell({width: 1, height: 1});
    -  var table = plugin.getCurrentTable_();
    -  var selectedCell = fieldMock.getRange().getContainerElement();
    -  // Splitting is only supported if we set these attributes.
    -  selectedCell.rowSpan = '1';
    -  selectedCell.colSpan = '2';
    -  selectedCell.innerHTML = 'foo';
    -  goog.dom.Range.createFromNodeContents(selectedCell).select();
    -  assertEquals('Table should have one cell', 1, getCellCount(table));
    -  plugin.execCommandInternal(
    -      goog.editor.plugins.TableEditor.COMMAND.SPLIT_CELL);
    -  assertEquals('The cell should have been split', 2, getCellCount(table));
    -  assertEquals('The cell content should be intact',
    -               'foo',
    -               selectedCell.innerHTML);
    -  assertNotNull('The new cell should be inserted before',
    -      selectedCell.previousSibling);
    -  fieldMock.$verify();
    -}
    -
    -function testMergeCells() {
    -  fieldMock.$replay();
    -  createTableAndSelectCell({width: 2, height: 1});
    -  var table = plugin.getCurrentTable_();
    -  var selectedCell = fieldMock.getRange().getContainerElement();
    -  selectedCell.innerHTML = 'foo';
    -  selectedCell.nextSibling.innerHTML = 'bar';
    -  var range = goog.dom.Range.createFromNodeContents(
    -      table.getElementsByTagName('tr')[0]);
    -  range.select();
    -  plugin.execCommandInternal(
    -      goog.editor.plugins.TableEditor.COMMAND.MERGE_CELLS);
    -  expectedFailures.expectFailureFor(
    -      goog.userAgent.IE &&
    -      goog.userAgent.isVersionOrHigher('8'));
    -  try {
    -    // In IE8, even after explicitly setting the range to span
    -    // multiple cells, the browser selection only contains the first TD
    -    // which causes the merge operation to fail.
    -    assertEquals('The cells should be merged', 1, getCellCount(table));
    -    assertEquals('The cell should have expected colspan',
    -                 2,
    -                 selectedCell.colSpan);
    -    assertHTMLEquals('The content should be merged',
    -                     'foo bar',
    -                     selectedCell.innerHTML);
    -  } catch (e) {
    -    expectedFailures.handleException(e);
    -  }
    -  fieldMock.$verify();
    -}
    -
    -
    -/**
    - * Helper routine which returns the number of cells in the table.
    - *
    - * @param {Element} table The table in question.
    - * @return {number} Number of cells.
    - */
    -function getCellCount(table) {
    -  return table.cells ? table.cells.length :
    -      table.rows[0].cells.length * table.rows.length;
    -}
    -
    -
    -/**
    - * Helper method which creates a table and puts the cursor on the first TD.
    - * In IE, the cursor isn't positioned in the first cell (TD) and we simulate
    - * that behavior explicitly to be consistent across all browsers.
    - *
    - * @param {Object} op_tableProps Optional table properties.
    - */
    -function createTableAndSelectCell(opt_tableProps) {
    -  goog.dom.Range.createCaret(field, 1).select();
    -  plugin.execCommandInternal(goog.editor.plugins.TableEditor.COMMAND.TABLE,
    -                             opt_tableProps);
    -  if (goog.userAgent.IE) {
    -    var range = goog.dom.Range.createFromNodeContents(
    -        field.getElementsByTagName('td')[0]);
    -    range.select();
    -  }
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/tagonenterhandler.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/tagonenterhandler.js
    deleted file mode 100644
    index e5776fdbb43..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/tagonenterhandler.js
    +++ /dev/null
    @@ -1,744 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview TrogEdit plugin to handle enter keys by inserting the
    - * specified block level tag.
    - *
    - * @author robbyw@google.com (Robby Walker)
    - */
    -
    -goog.provide('goog.editor.plugins.TagOnEnterHandler');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.NodeType');
    -goog.require('goog.dom.Range');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.editor.Command');
    -goog.require('goog.editor.node');
    -goog.require('goog.editor.plugins.EnterHandler');
    -goog.require('goog.editor.range');
    -goog.require('goog.editor.style');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.functions');
    -goog.require('goog.string.Unicode');
    -goog.require('goog.style');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Plugin to handle enter keys. This subclass normalizes all browsers to use
    - * the given block tag on enter.
    - * @param {goog.dom.TagName} tag The type of tag to add on enter.
    - * @constructor
    - * @extends {goog.editor.plugins.EnterHandler}
    - */
    -goog.editor.plugins.TagOnEnterHandler = function(tag) {
    -  this.tag = tag;
    -
    -  goog.editor.plugins.EnterHandler.call(this);
    -};
    -goog.inherits(goog.editor.plugins.TagOnEnterHandler,
    -    goog.editor.plugins.EnterHandler);
    -
    -
    -/** @override */
    -goog.editor.plugins.TagOnEnterHandler.prototype.getTrogClassId = function() {
    -  return 'TagOnEnterHandler';
    -};
    -
    -
    -/** @override */
    -goog.editor.plugins.TagOnEnterHandler.prototype.getNonCollapsingBlankHtml =
    -    function() {
    -  if (this.tag == goog.dom.TagName.P) {
    -    return '<p>&nbsp;</p>';
    -  } else if (this.tag == goog.dom.TagName.DIV) {
    -    return '<div><br></div>';
    -  }
    -  return '<br>';
    -};
    -
    -
    -/**
    - * This plugin is active on uneditable fields so it can provide a value for
    - * queryCommandValue calls asking for goog.editor.Command.BLOCKQUOTE.
    - * @return {boolean} True.
    - * @override
    - */
    -goog.editor.plugins.TagOnEnterHandler.prototype.activeOnUneditableFields =
    -    goog.functions.TRUE;
    -
    -
    -/** @override */
    -goog.editor.plugins.TagOnEnterHandler.prototype.isSupportedCommand = function(
    -    command) {
    -  return command == goog.editor.Command.DEFAULT_TAG;
    -};
    -
    -
    -/** @override */
    -goog.editor.plugins.TagOnEnterHandler.prototype.queryCommandValue = function(
    -    command) {
    -  return command == goog.editor.Command.DEFAULT_TAG ? this.tag : null;
    -};
    -
    -
    -/** @override */
    -goog.editor.plugins.TagOnEnterHandler.prototype.handleBackspaceInternal =
    -    function(e, range) {
    -  goog.editor.plugins.TagOnEnterHandler.superClass_.handleBackspaceInternal.
    -      call(this, e, range);
    -
    -  if (goog.userAgent.GECKO) {
    -    this.markBrToNotBeRemoved_(range, true);
    -  }
    -};
    -
    -
    -/** @override */
    -goog.editor.plugins.TagOnEnterHandler.prototype.processParagraphTagsInternal =
    -    function(e, split) {
    -  if ((goog.userAgent.OPERA || goog.userAgent.IE) &&
    -      this.tag != goog.dom.TagName.P) {
    -    this.ensureBlockIeOpera(this.tag);
    -  }
    -};
    -
    -
    -/** @override */
    -goog.editor.plugins.TagOnEnterHandler.prototype.handleDeleteGecko = function(
    -    e) {
    -  var range = this.getFieldObject().getRange();
    -  var container = goog.editor.style.getContainer(
    -      range && range.getContainerElement());
    -  if (this.getFieldObject().getElement().lastChild == container &&
    -      goog.editor.plugins.EnterHandler.isBrElem(container)) {
    -    // Don't delete if it's the last node in the field and just has a BR.
    -    e.preventDefault();
    -    // TODO(user): I think we probably don't need to stopPropagation here
    -    e.stopPropagation();
    -  } else {
    -    // Go ahead with deletion.
    -    // Prevent an existing BR immediately following the selection being deleted
    -    // from being removed in the keyup stage (as opposed to a BR added by FF
    -    // after deletion, which we do remove).
    -    this.markBrToNotBeRemoved_(range, false);
    -    // Manually delete the selection if it's at a BR.
    -    this.deleteBrGecko(e);
    -  }
    -};
    -
    -
    -/** @override */
    -goog.editor.plugins.TagOnEnterHandler.prototype.handleKeyUpInternal = function(
    -    e) {
    -  if (goog.userAgent.GECKO) {
    -    if (e.keyCode == goog.events.KeyCodes.DELETE) {
    -      this.removeBrIfNecessary_(false);
    -    } else if (e.keyCode == goog.events.KeyCodes.BACKSPACE) {
    -      this.removeBrIfNecessary_(true);
    -    }
    -  } else if ((goog.userAgent.IE || goog.userAgent.OPERA) &&
    -             e.keyCode == goog.events.KeyCodes.ENTER) {
    -    this.ensureBlockIeOpera(this.tag, true);
    -  }
    -  // Safari uses DIVs by default.
    -};
    -
    -
    -/**
    - * String that matches a single BR tag or NBSP surrounded by non-breaking
    - * whitespace
    - * @type {string}
    - * @private
    - */
    -goog.editor.plugins.TagOnEnterHandler.BrOrNbspSurroundedWithWhiteSpace_ =
    -    '[\t\n\r ]*(<br[^>]*\/?>|&nbsp;)[\t\n\r ]*';
    -
    -
    -/**
    - * String that matches a single BR tag or NBSP surrounded by non-breaking
    - * whitespace
    - * @type {RegExp}
    - * @private
    - */
    -goog.editor.plugins.TagOnEnterHandler.emptyLiRegExp_ = new RegExp('^' +
    -    goog.editor.plugins.TagOnEnterHandler.BrOrNbspSurroundedWithWhiteSpace_ +
    -    '$');
    -
    -
    -/**
    - * Ensures the current node is wrapped in the tag.
    - * @param {Node} node The node to ensure gets wrapped.
    - * @param {Element} container Element containing the selection.
    - * @return {Element} Element containing the selection, after the wrapping.
    -  * @private
    - */
    -goog.editor.plugins.TagOnEnterHandler.prototype.ensureNodeIsWrappedW3c_ =
    -    function(node, container) {
    -  if (container == this.getFieldObject().getElement()) {
    -    // If the first block-level ancestor of cursor is the field,
    -    // don't split the tree. Find all the text from the cursor
    -    // to both block-level elements surrounding it (if they exist)
    -    // and split the text into two elements.
    -    // This is the IE contentEditable behavior.
    -
    -    // The easy way to do this is to wrap all the text in an element
    -    // and then split the element as if the user had hit enter
    -    // in the paragraph
    -
    -    // However, simply wrapping the text into an element creates problems
    -    // if the text was already wrapped using some other element such as an
    -    // anchor.  For example, wrapping the text of
    -    //   <a href="">Text</a>
    -    // would produce
    -    //   <a href=""><p>Text</p></a>
    -    // which is not what we want.  What we really want is
    -    //   <p><a href="">Text</a></p>
    -    // So we need to search for an ancestor of position.node to be wrapped.
    -    // We do this by iterating up the hierarchy of postiion.node until we've
    -    // reached the node that's just under the container.
    -    var isChildOfFn = function(child) {
    -      return container == child.parentNode; };
    -    var nodeToWrap = goog.dom.getAncestor(node, isChildOfFn, true);
    -    container = goog.editor.plugins.TagOnEnterHandler.wrapInContainerW3c_(
    -        this.tag, {node: nodeToWrap, offset: 0}, container);
    -  }
    -  return container;
    -};
    -
    -
    -/** @override */
    -goog.editor.plugins.TagOnEnterHandler.prototype.handleEnterWebkitInternal =
    -    function(e) {
    -  if (this.tag == goog.dom.TagName.DIV) {
    -    var range = this.getFieldObject().getRange();
    -    var container =
    -        goog.editor.style.getContainer(range.getContainerElement());
    -
    -    var position = goog.editor.range.getDeepEndPoint(range, true);
    -    container = this.ensureNodeIsWrappedW3c_(position.node, container);
    -    goog.dom.Range.createCaret(position.node, position.offset).select();
    -  }
    -};
    -
    -
    -/** @override */
    -goog.editor.plugins.TagOnEnterHandler.prototype.
    -    handleEnterAtCursorGeckoInternal = function(e, wasCollapsed, range) {
    -  // We use this because there are a few cases where FF default
    -  // implementation doesn't follow IE's:
    -  //   -Inserts BRs into empty elements instead of NBSP which has nasty
    -  //    side effects w/ making/deleting selections
    -  //   -Hitting enter when your cursor is in the field itself. IE will
    -  //    create two elements. FF just inserts a BR.
    -  //   -Hitting enter inside an empty list-item doesn't create a block
    -  //    tag. It just splits the list and puts your cursor in the middle.
    -  var li = null;
    -  if (wasCollapsed) {
    -    // Only break out of lists for collapsed selections.
    -    li = goog.dom.getAncestorByTagNameAndClass(
    -        range && range.getContainerElement(), goog.dom.TagName.LI);
    -  }
    -  var isEmptyLi = (li &&
    -      li.innerHTML.match(
    -          goog.editor.plugins.TagOnEnterHandler.emptyLiRegExp_));
    -  var elementAfterCursor = isEmptyLi ?
    -      this.breakOutOfEmptyListItemGecko_(li) :
    -      this.handleRegularEnterGecko_();
    -
    -  // Move the cursor in front of "nodeAfterCursor", and make sure it
    -  // is visible
    -  this.scrollCursorIntoViewGecko_(elementAfterCursor);
    -
    -  // Fix for http://b/1991234 :
    -  if (goog.editor.plugins.EnterHandler.isBrElem(elementAfterCursor)) {
    -    // The first element in the new line is a line with just a BR and maybe some
    -    // whitespace.
    -    // Calling normalize() is needed because there might be empty text nodes
    -    // before BR and empty text nodes cause the cursor position bug in Firefox.
    -    // See http://b/5220858
    -    elementAfterCursor.normalize();
    -    var br = elementAfterCursor.getElementsByTagName(goog.dom.TagName.BR)[0];
    -    if (br.previousSibling &&
    -        br.previousSibling.nodeType == goog.dom.NodeType.TEXT) {
    -      // If there is some whitespace before the BR, don't put the selection on
    -      // the BR, put it in the text node that's there, otherwise when you type
    -      // it will create adjacent text nodes.
    -      elementAfterCursor = br.previousSibling;
    -    }
    -  }
    -
    -  goog.editor.range.selectNodeStart(elementAfterCursor);
    -
    -  e.preventDefault();
    -  // TODO(user): I think we probably don't need to stopPropagation here
    -  e.stopPropagation();
    -};
    -
    -
    -/**
    - * If The cursor is in an empty LI then break out of the list like in IE
    - * @param {Node} li LI to break out of.
    - * @return {!Element} Element to put the cursor after.
    - * @private
    - */
    -goog.editor.plugins.TagOnEnterHandler.prototype.breakOutOfEmptyListItemGecko_ =
    -    function(li) {
    -  // Do this as follows:
    -  // 1. <ul>...<li>&nbsp;</li>...</ul>
    -  // 2. <ul id='foo1'>...<li id='foo2'>&nbsp;</li>...</ul>
    -  // 3. <ul id='foo1'>...</ul><p id='foo3'>&nbsp;</p><ul id='foo2'>...</ul>
    -  // 4. <ul>...</ul><p>&nbsp;</p><ul>...</ul>
    -  //
    -  // There are a couple caveats to the above. If the UL is contained in
    -  // a list, then the new node inserted is an LI, not a P.
    -  // For an OL, it's all the same, except the tagname of course.
    -  // Finally, it's possible that with the LI at the beginning or the end
    -  // of the list that we'll end up with an empty list. So we special case
    -  // those cases.
    -
    -  var listNode = li.parentNode;
    -  var grandparent = listNode.parentNode;
    -  var inSubList = grandparent.tagName == goog.dom.TagName.OL ||
    -      grandparent.tagName == goog.dom.TagName.UL;
    -
    -  // TODO(robbyw): Should we apply the list or list item styles to the new node?
    -  var newNode = goog.dom.getDomHelper(li).createElement(
    -      inSubList ? goog.dom.TagName.LI : this.tag);
    -
    -  if (!li.previousSibling) {
    -    goog.dom.insertSiblingBefore(newNode, listNode);
    -  } else {
    -    if (li.nextSibling) {
    -      var listClone = listNode.cloneNode(false);
    -      while (li.nextSibling) {
    -        listClone.appendChild(li.nextSibling);
    -      }
    -      goog.dom.insertSiblingAfter(listClone, listNode);
    -    }
    -    goog.dom.insertSiblingAfter(newNode, listNode);
    -  }
    -  if (goog.editor.node.isEmpty(listNode)) {
    -    goog.dom.removeNode(listNode);
    -  }
    -  goog.dom.removeNode(li);
    -  newNode.innerHTML = '&nbsp;';
    -
    -  return newNode;
    -};
    -
    -
    -/**
    - * Wrap the text indicated by "position" in an HTML container of type
    - * "nodeName".
    - * @param {string} nodeName Type of container, e.g. "p" (paragraph).
    - * @param {Object} position The W3C cursor position object
    - *     (from getCursorPositionW3c).
    - * @param {Node} container The field containing position.
    - * @return {!Element} The container element that holds the contents from
    - *     position.
    - * @private
    - */
    -goog.editor.plugins.TagOnEnterHandler.wrapInContainerW3c_ = function(nodeName,
    -    position, container) {
    -  var start = position.node;
    -  while (start.previousSibling &&
    -         !goog.editor.style.isContainer(start.previousSibling)) {
    -    start = start.previousSibling;
    -  }
    -
    -  var end = position.node;
    -  while (end.nextSibling &&
    -         !goog.editor.style.isContainer(end.nextSibling)) {
    -    end = end.nextSibling;
    -  }
    -
    -  var para = container.ownerDocument.createElement(nodeName);
    -  while (start != end) {
    -    var newStart = start.nextSibling;
    -    goog.dom.appendChild(para, start);
    -    start = newStart;
    -  }
    -  var nextSibling = end.nextSibling;
    -  goog.dom.appendChild(para, end);
    -  container.insertBefore(para, nextSibling);
    -
    -  return para;
    -};
    -
    -
    -/**
    - * When we delete an element, FF inserts a BR. We want to strip that
    - * BR after the fact, but in the case where your cursor is at a character
    - * right before a BR and you delete that character, we don't want to
    - * strip it. So we detect this case on keydown and mark the BR as not needing
    - * removal.
    - * @param {goog.dom.AbstractRange} range The closure range object.
    - * @param {boolean} isBackspace Whether this is handling the backspace key.
    - * @private
    - */
    -goog.editor.plugins.TagOnEnterHandler.prototype.markBrToNotBeRemoved_ =
    -    function(range, isBackspace) {
    -  var focusNode = range.getFocusNode();
    -  var focusOffset = range.getFocusOffset();
    -  var newEndOffset = isBackspace ? focusOffset : focusOffset + 1;
    -
    -  if (goog.editor.node.getLength(focusNode) == newEndOffset) {
    -    var sibling = focusNode.nextSibling;
    -    if (sibling && sibling.tagName == goog.dom.TagName.BR) {
    -      this.brToKeep_ = sibling;
    -    }
    -  }
    -};
    -
    -
    -/**
    - * If we hit delete/backspace to merge elements, FF inserts a BR.
    - * We want to strip that BR. In markBrToNotBeRemoved, we detect if
    - * there was already a BR there before the delete/backspace so that
    - * we don't accidentally remove a user-inserted BR.
    - * @param {boolean} isBackSpace Whether this is handling the backspace key.
    - * @private
    - */
    -goog.editor.plugins.TagOnEnterHandler.prototype.removeBrIfNecessary_ = function(
    -    isBackSpace) {
    -  var range = this.getFieldObject().getRange();
    -  var focusNode = range.getFocusNode();
    -  var focusOffset = range.getFocusOffset();
    -
    -  var sibling;
    -  if (isBackSpace && focusNode.data == '') {
    -    // nasty hack. sometimes firefox will backspace a paragraph and put
    -    // the cursor before the BR. when it does this, the focusNode is
    -    // an empty textnode.
    -    sibling = focusNode.nextSibling;
    -  } else if (isBackSpace && focusOffset == 0) {
    -    var node = focusNode;
    -    while (node && !node.previousSibling &&
    -           node.parentNode != this.getFieldObject().getElement()) {
    -      node = node.parentNode;
    -    }
    -    sibling = node.previousSibling;
    -  } else if (focusNode.length == focusOffset) {
    -    sibling = focusNode.nextSibling;
    -  }
    -
    -  if (!sibling || sibling.tagName != goog.dom.TagName.BR ||
    -      this.brToKeep_ == sibling) {
    -    return;
    -  }
    -
    -  goog.dom.removeNode(sibling);
    -  if (focusNode.nodeType == goog.dom.NodeType.TEXT) {
    -    // Sometimes firefox inserts extra whitespace. Do our best to deal.
    -    // This is buggy though.
    -    focusNode.data =
    -        goog.editor.plugins.TagOnEnterHandler.trimTabsAndLineBreaks_(
    -            focusNode.data);
    -    // When we strip whitespace, make sure that our cursor is still at
    -    // the end of the textnode.
    -    goog.dom.Range.createCaret(focusNode,
    -        Math.min(focusOffset, focusNode.length)).select();
    -  }
    -};
    -
    -
    -/**
    - * Trim the tabs and line breaks from a string.
    - * @param {string} string String to trim.
    - * @return {string} Trimmed string.
    - * @private
    - */
    -goog.editor.plugins.TagOnEnterHandler.trimTabsAndLineBreaks_ = function(
    -    string) {
    -  return string.replace(/^[\t\n\r]|[\t\n\r]$/g, '');
    -};
    -
    -
    -/**
    - * Called in response to a normal enter keystroke. It has the action of
    - * splitting elements.
    - * @return {Element} The node that the cursor should be before.
    - * @private
    - */
    -goog.editor.plugins.TagOnEnterHandler.prototype.handleRegularEnterGecko_ =
    -    function() {
    -  var range = this.getFieldObject().getRange();
    -  var container =
    -      goog.editor.style.getContainer(range.getContainerElement());
    -  var newNode;
    -  if (goog.editor.plugins.EnterHandler.isBrElem(container)) {
    -    if (container.tagName == goog.dom.TagName.BODY) {
    -      // If the field contains only a single BR, this code ensures we don't
    -      // try to clone the body tag.
    -      container = this.ensureNodeIsWrappedW3c_(
    -          container.getElementsByTagName(goog.dom.TagName.BR)[0],
    -          container);
    -    }
    -
    -    newNode = container.cloneNode(true);
    -    goog.dom.insertSiblingAfter(newNode, container);
    -  } else {
    -    if (!container.firstChild) {
    -      container.innerHTML = '&nbsp;';
    -    }
    -
    -    var position = goog.editor.range.getDeepEndPoint(range, true);
    -    container = this.ensureNodeIsWrappedW3c_(position.node, container);
    -
    -    newNode = goog.editor.plugins.TagOnEnterHandler.splitDomAndAppend_(
    -        position.node, position.offset, container);
    -
    -    // If the left half and right half of the splitted node are anchors then
    -    // that means the user pressed enter while the caret was inside
    -    // an anchor tag and split it.  The left half is the first anchor
    -    // found while traversing the right branch of container.  The right half
    -    // is the first anchor found while traversing the left branch of newNode.
    -    var leftAnchor =
    -        goog.editor.plugins.TagOnEnterHandler.findAnchorInTraversal_(
    -            container);
    -    var rightAnchor =
    -        goog.editor.plugins.TagOnEnterHandler.findAnchorInTraversal_(
    -            newNode, true);
    -    if (leftAnchor && rightAnchor &&
    -        leftAnchor.tagName == goog.dom.TagName.A &&
    -        rightAnchor.tagName == goog.dom.TagName.A) {
    -      // If the original anchor (left anchor) is now empty, that means
    -      // the user pressed [Enter] at the beginning of the anchor,
    -      // in which case we we
    -      // want to replace that anchor with its child nodes
    -      // Otherwise, we take the second half of the splitted text and break
    -      // it out of the anchor.
    -      var anchorToRemove = goog.editor.node.isEmpty(leftAnchor, false) ?
    -          leftAnchor : rightAnchor;
    -      goog.dom.flattenElement(/** @type {!Element} */ (anchorToRemove));
    -    }
    -  }
    -  return /** @type {!Element} */ (newNode);
    -};
    -
    -
    -/**
    - * Scroll the cursor into view, resulting from splitting the paragraph/adding
    - * a br. It behaves differently than scrollIntoView
    - * @param {Element} element The element immediately following the cursor. Will
    - *     be used to determine how to scroll in order to make the cursor visible.
    - *     CANNOT be a BR, as they do not have offsetHeight/offsetTop.
    - * @private
    - */
    -goog.editor.plugins.TagOnEnterHandler.prototype.scrollCursorIntoViewGecko_ =
    -    function(element) {
    -  if (!this.getFieldObject().isFixedHeight()) {
    -    return; // Only need to scroll fixed height fields.
    -  }
    -
    -  var field = this.getFieldObject().getElement();
    -
    -  // Get the y position of the element we want to scroll to
    -  var elementY = goog.style.getPageOffsetTop(element);
    -
    -  // Determine the height of that element, since we want the bottom of the
    -  // element to be in view.
    -  var bottomOfNode = elementY + element.offsetHeight;
    -
    -  var dom = this.getFieldDomHelper();
    -  var win = this.getFieldDomHelper().getWindow();
    -  var scrollY = dom.getDocumentScroll().y;
    -  var viewportHeight = goog.dom.getViewportSize(win).height;
    -
    -  // If the botom of the element is outside the viewport, move it into view
    -  if (bottomOfNode > viewportHeight + scrollY) {
    -    // In standards mode, use the html element and not the body
    -    if (field.tagName == goog.dom.TagName.BODY &&
    -        goog.editor.node.isStandardsMode(field)) {
    -      field = field.parentNode;
    -    }
    -    field.scrollTop = bottomOfNode - viewportHeight;
    -  }
    -};
    -
    -
    -/**
    - * Splits the DOM tree around the given node and returns the node
    - * containing the second half of the tree. The first half of the tree
    - * is modified, but not removed from the DOM.
    - * @param {Node} positionNode Node to split at.
    - * @param {number} positionOffset Offset into positionNode to split at.  If
    - *     positionNode is a text node, this offset is an offset in to the text
    - *     content of that node.  Otherwise, positionOffset is an offset in to
    - *     the childNodes array.  All elements with child index of  positionOffset
    - *     or greater will be moved to the second half.  If positionNode is an
    - *     empty element, the dom will be split at that element, with positionNode
    - *     ending up in the second half.  positionOffset must be 0 in this case.
    - * @param {Node=} opt_root Node at which to stop splitting the dom (the root
    - *     is also split).
    - * @return {!Node} The node containing the second half of the tree.
    - * @private
    - */
    -goog.editor.plugins.TagOnEnterHandler.splitDom_ = function(
    -    positionNode, positionOffset, opt_root) {
    -  if (!opt_root) opt_root = positionNode.ownerDocument.body;
    -
    -  // Split the node.
    -  var textSplit = positionNode.nodeType == goog.dom.NodeType.TEXT;
    -  var secondHalfOfSplitNode;
    -  if (textSplit) {
    -    if (goog.userAgent.IE &&
    -        positionOffset == positionNode.nodeValue.length) {
    -      // Since splitText fails in IE at the end of a node, we split it manually.
    -      secondHalfOfSplitNode = goog.dom.getDomHelper(positionNode).
    -          createTextNode('');
    -      goog.dom.insertSiblingAfter(secondHalfOfSplitNode, positionNode);
    -    } else {
    -      secondHalfOfSplitNode = positionNode.splitText(positionOffset);
    -    }
    -  } else {
    -    // Here we ensure positionNode is the last node in the first half of the
    -    // resulting tree.
    -    if (positionOffset) {
    -      // Use offset as an index in to childNodes.
    -      positionNode = positionNode.childNodes[positionOffset - 1];
    -    } else {
    -      // In this case, positionNode would be the last node in the first half
    -      // of the tree, but we actually want to move it to the second half.
    -      // Therefore we set secondHalfOfSplitNode to the same node.
    -      positionNode = secondHalfOfSplitNode = positionNode.firstChild ||
    -          positionNode;
    -    }
    -  }
    -
    -  // Create second half of the tree.
    -  var secondHalf = goog.editor.node.splitDomTreeAt(
    -      positionNode, secondHalfOfSplitNode, opt_root);
    -
    -  if (textSplit) {
    -    // Join secondHalfOfSplitNode and its right text siblings together and
    -    // then replace leading NonNbspWhiteSpace with a Nbsp.  If
    -    // secondHalfOfSplitNode has a right sibling that isn't a text node,
    -    // then we can leave secondHalfOfSplitNode empty.
    -    secondHalfOfSplitNode =
    -        goog.editor.plugins.TagOnEnterHandler.joinTextNodes_(
    -            secondHalfOfSplitNode, true);
    -    goog.editor.plugins.TagOnEnterHandler.replaceWhiteSpaceWithNbsp_(
    -        secondHalfOfSplitNode, true, !!secondHalfOfSplitNode.nextSibling);
    -
    -    // Join positionNode and its left text siblings together and then replace
    -    // trailing NonNbspWhiteSpace with a Nbsp.
    -    var firstHalf = goog.editor.plugins.TagOnEnterHandler.joinTextNodes_(
    -        positionNode, false);
    -    goog.editor.plugins.TagOnEnterHandler.replaceWhiteSpaceWithNbsp_(
    -        firstHalf, false, false);
    -  }
    -
    -  return secondHalf;
    -};
    -
    -
    -/**
    - * Splits the DOM tree around the given node and returns the node containing
    - * second half of the tree, which is appended after the old node.  The first
    - * half of the tree is modified, but not removed from the DOM.
    - * @param {Node} positionNode Node to split at.
    - * @param {number} positionOffset Offset into positionNode to split at.  If
    - *     positionNode is a text node, this offset is an offset in to the text
    - *     content of that node.  Otherwise, positionOffset is an offset in to
    - *     the childNodes array.  All elements with child index of  positionOffset
    - *     or greater will be moved to the second half.  If positionNode is an
    - *     empty element, the dom will be split at that element, with positionNode
    - *     ending up in the second half.  positionOffset must be 0 in this case.
    - * @param {Node} node Node to split.
    - * @return {!Node} The node containing the second half of the tree.
    - * @private
    - */
    -goog.editor.plugins.TagOnEnterHandler.splitDomAndAppend_ = function(
    -    positionNode, positionOffset, node) {
    -  var newNode = goog.editor.plugins.TagOnEnterHandler.splitDom_(
    -      positionNode, positionOffset, node);
    -  goog.dom.insertSiblingAfter(newNode, node);
    -  return newNode;
    -};
    -
    -
    -/**
    - * Joins node and its adjacent text nodes together.
    - * @param {Node} node The node to start joining.
    - * @param {boolean} moveForward Determines whether to join left siblings (false)
    - *     or right siblings (true).
    - * @return {Node} The joined text node.
    - * @private
    - */
    -goog.editor.plugins.TagOnEnterHandler.joinTextNodes_ = function(node,
    -    moveForward) {
    -  if (node && node.nodeName == '#text') {
    -    var nextNodeFn = moveForward ? 'nextSibling' : 'previousSibling';
    -    var prevNodeFn = moveForward ? 'previousSibling' : 'nextSibling';
    -    var nodeValues = [node.nodeValue];
    -    while (node[nextNodeFn] &&
    -           node[nextNodeFn].nodeType == goog.dom.NodeType.TEXT) {
    -      node = node[nextNodeFn];
    -      nodeValues.push(node.nodeValue);
    -      goog.dom.removeNode(node[prevNodeFn]);
    -    }
    -    if (!moveForward) {
    -      nodeValues.reverse();
    -    }
    -    node.nodeValue = nodeValues.join('');
    -  }
    -  return node;
    -};
    -
    -
    -/**
    - * Replaces leading or trailing spaces of a text node to a single Nbsp.
    - * @param {Node} textNode The text node to search and replace white spaces.
    - * @param {boolean} fromStart Set to true to replace leading spaces, false to
    - *     replace trailing spaces.
    - * @param {boolean} isLeaveEmpty Set to true to leave the node empty if the
    - *     text node was empty in the first place, otherwise put a Nbsp into the
    - *     text node.
    - * @private
    - */
    -goog.editor.plugins.TagOnEnterHandler.replaceWhiteSpaceWithNbsp_ = function(
    -    textNode, fromStart, isLeaveEmpty) {
    -  var regExp = fromStart ? /^[ \t\r\n]+/ : /[ \t\r\n]+$/;
    -  textNode.nodeValue = textNode.nodeValue.replace(regExp,
    -                                                  goog.string.Unicode.NBSP);
    -
    -  if (!isLeaveEmpty && textNode.nodeValue == '') {
    -    textNode.nodeValue = goog.string.Unicode.NBSP;
    -  }
    -};
    -
    -
    -/**
    - * Finds the first A element in a traversal from the input node.  The input
    - * node itself is not included in the search.
    - * @param {Node} node The node to start searching from.
    - * @param {boolean=} opt_useFirstChild Whether to traverse along the first child
    - *     (true) or last child (false).
    - * @return {Node} The first anchor node found in the search, or null if none
    - *     was found.
    - * @private
    - */
    -goog.editor.plugins.TagOnEnterHandler.findAnchorInTraversal_ = function(node,
    -    opt_useFirstChild) {
    -  while ((node = opt_useFirstChild ? node.firstChild : node.lastChild) &&
    -         node.tagName != goog.dom.TagName.A) {
    -    // Do nothing - advancement is handled in the condition.
    -  }
    -  return node;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/tagonenterhandler_test.html b/src/database/third_party/closure-library/closure/goog/editor/plugins/tagonenterhandler_test.html
    deleted file mode 100644
    index 0b05f2c088f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/tagonenterhandler_test.html
    +++ /dev/null
    @@ -1,32 +0,0 @@
    -<!DOCTYPE html>
    -<!--
    -
    -  Tests for goog.editor.plugins.TagOnEnterHandler
    -
    -  @author marcosalmeida@google.com
    --->
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   goog.editor.plugins.TagOnEnterHandler jsunit tests
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.editor.plugins.TagOnEnterHandlerTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="root">
    -   <div id="field1" class="tr-field">
    -   </div>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/tagonenterhandler_test.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/tagonenterhandler_test.js
    deleted file mode 100644
    index 20f83972140..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/tagonenterhandler_test.js
    +++ /dev/null
    @@ -1,546 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.editor.plugins.TagOnEnterHandlerTest');
    -goog.setTestOnly('goog.editor.plugins.TagOnEnterHandlerTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.NodeType');
    -goog.require('goog.dom.Range');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.editor.BrowserFeature');
    -goog.require('goog.editor.Field');
    -goog.require('goog.editor.Plugin');
    -goog.require('goog.editor.plugins.TagOnEnterHandler');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.string.Unicode');
    -goog.require('goog.testing.dom');
    -goog.require('goog.testing.editor.TestHelper');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -var savedHtml;
    -
    -var editor;
    -var field1;
    -
    -function setUp() {
    -  field1 = makeField('field1');
    -  field1.makeEditable();
    -}
    -
    -
    -/**
    - * Tests that deleting a BR that comes right before a block element works.
    - * @bug 1471096
    - */
    -function testDeleteBrBeforeBlock() {
    -  // This test only works on Gecko, because it's testing for manual deletion of
    -  // BR tags, which is done only for Gecko. For other browsers we fall through
    -  // and let the browser do the delete, which can only be tested with a robot
    -  // test (see javascript/apps/editor/tests/delete_br_robot.html).
    -  if (goog.userAgent.GECKO) {
    -
    -    field1.setHtml(false, 'one<br><br><div>two</div>');
    -    var helper = new goog.testing.editor.TestHelper(field1.getElement());
    -    helper.select(field1.getElement(), 2); // Between the two BR's.
    -    goog.testing.events.fireKeySequence(field1.getElement(),
    -                                        goog.events.KeyCodes.DELETE);
    -    assertEquals('Should have deleted exactly one <br>',
    -                 'one<br><div>two</div>',
    -                 field1.getElement().innerHTML);
    -
    -  } // End if GECKO
    -}
    -
    -
    -/**
    - * Tests that deleting a BR is working normally (that the workaround for the
    - * bug is not causing double deletes).
    - * @bug 1471096
    - */
    -function testDeleteBrNormal() {
    -  // This test only works on Gecko, because it's testing for manual deletion of
    -  // BR tags, which is done only for Gecko. For other browsers we fall through
    -  // and let the browser do the delete, which can only be tested with a robot
    -  // test (see javascript/apps/editor/tests/delete_br_robot.html).
    -  if (goog.userAgent.GECKO) {
    -
    -    field1.setHtml(false, 'one<br><br><br>two');
    -    var helper = new goog.testing.editor.TestHelper(field1.getElement());
    -    helper.select(field1.getElement(), 2); // Between the first and second BR's.
    -    field1.getElement().focus();
    -    goog.testing.events.fireKeySequence(field1.getElement(),
    -                                        goog.events.KeyCodes.DELETE);
    -    assertEquals('Should have deleted exactly one <br>',
    -                 'one<br><br>two',
    -                 field1.getElement().innerHTML);
    -
    -  } // End if GECKO
    -}
    -
    -
    -/**
    - * Regression test for http://b/1991234 . Tests that when you hit enter and it
    - * creates a blank line with whitespace and a BR, the cursor is placed in the
    - * whitespace text node instead of the BR, otherwise continuing to type will
    - * create adjacent text nodes, which causes browsers to mess up some
    - * execcommands. Fix is in a Gecko-only codepath, thus test runs only for Gecko.
    - * A full test for the entire sequence that reproed the bug is in
    - * javascript/apps/editor/tests/ponenter_robot.html .
    - */
    -function testEnterCreatesBlankLine() {
    -  if (goog.userAgent.GECKO) {
    -    field1.setHtml(false, '<p>one <br></p>');
    -    var helper = new goog.testing.editor.TestHelper(field1.getElement());
    -    // Place caret after 'one' but keeping a space and a BR as FF does.
    -    helper.select('one ', 3);
    -    field1.getElement().focus();
    -    goog.testing.events.fireKeySequence(field1.getElement(),
    -                                        goog.events.KeyCodes.ENTER);
    -    var range = field1.getRange();
    -    assertFalse('Selection should not be in BR tag',
    -                range.getStartNode().nodeType == goog.dom.NodeType.ELEMENT &&
    -                range.getStartNode().tagName == goog.dom.TagName.BR);
    -    assertEquals('Selection should be in text node to avoid creating adjacent' +
    -                 ' text nodes',
    -        goog.dom.NodeType.TEXT, range.getStartNode().nodeType);
    -    var rangeStartNode =
    -        goog.dom.Range.createFromNodeContents(range.getStartNode());
    -    assertHTMLEquals('The value of selected text node should be replaced with' +
    -        '&nbsp;',
    -        '&nbsp;', rangeStartNode.getHtmlFragment());
    -  }
    -}
    -
    -
    -/**
    - * Regression test for http://b/3051179 . Tests that when you hit enter and it
    - * creates a blank line with a BR and the cursor is placed in P.
    - * Splitting DOM causes to make an empty text node. Then if the cursor is placed
    - * at the text node the cursor is shown at wrong location.
    - * Therefore this test checks that the cursor is not placed at an empty node.
    - * Fix is in a Gecko-only codepath, thus test runs only for Gecko.
    - */
    -function testEnterNormalizeNodes() {
    -  if (goog.userAgent.GECKO) {
    -    field1.setHtml(false, '<p>one<br></p>');
    -    var helper = new goog.testing.editor.TestHelper(field1.getElement());
    -    // Place caret after 'one' but keeping a BR as FF does.
    -    helper.select('one', 3);
    -    field1.getElement().focus();
    -    goog.testing.events.fireKeySequence(field1.getElement(),
    -                                        goog.events.KeyCodes.ENTER);
    -    var range = field1.getRange();
    -    assertTrue('Selection should be in P tag',
    -        range.getStartNode().nodeType == goog.dom.NodeType.ELEMENT &&
    -        range.getStartNode().tagName == goog.dom.TagName.P);
    -    assertTrue('Selection should be at the head and collapsed',
    -        range.getStartOffset() == 0 && range.isCollapsed());
    -  }
    -}
    -
    -
    -/**
    - * Verifies
    - * goog.editor.plugins.TagOnEnterHandler.prototype.handleRegularEnterGecko_
    - * when we explicitly split anchor elements. This test runs only for Gecko
    - * since this is a Gecko-only codepath.
    - */
    -function testEnterAtBeginningOfLink() {
    -  if (goog.userAgent.GECKO) {
    -    field1.setHtml(false, '<a href="/">b<br></a>');
    -    var helper = new goog.testing.editor.TestHelper(field1.getElement());
    -    field1.focusAndPlaceCursorAtStart();
    -    goog.testing.events.fireKeySequence(field1.getElement(),
    -                                        goog.events.KeyCodes.ENTER);
    -    helper.assertHtmlMatches(
    -        '<p>&nbsp;</p><p><a href="/">b<br></a></p>');
    -  }
    -}
    -
    -
    -/**
    - * Verifies correct handling of pressing enter in an empty list item.
    - */
    -function testEnterInEmptyListItemInEmptyList() {
    -  if (goog.userAgent.GECKO) {
    -    field1.setHtml(false, '<ul><li>&nbsp;</li></ul>');
    -    var helper = new goog.testing.editor.TestHelper(field1.getElement());
    -    var li = field1.getElement().getElementsByTagName(goog.dom.TagName.LI)[0];
    -    helper.select(li.firstChild, 0);
    -    goog.testing.events.fireKeySequence(field1.getElement(),
    -                                        goog.events.KeyCodes.ENTER);
    -    helper.assertHtmlMatches('<p>&nbsp;</p>');
    -  }
    -}
    -
    -
    -function testEnterInEmptyListItemAtBeginningOfList() {
    -  if (goog.userAgent.GECKO) {
    -    field1.setHtml(false,
    -        '<ul style="font-weight: bold">' +
    -            '<li>&nbsp;</li>' +
    -            '<li>1</li>' +
    -            '<li>2</li>' +
    -        '</ul>');
    -    var helper = new goog.testing.editor.TestHelper(field1.getElement());
    -    var li = field1.getElement().getElementsByTagName(goog.dom.TagName.LI)[0];
    -    helper.select(li.firstChild, 0);
    -    goog.testing.events.fireKeySequence(field1.getElement(),
    -                                        goog.events.KeyCodes.ENTER);
    -    helper.assertHtmlMatches(
    -        '<p>&nbsp;</p><ul style="font-weight: bold"><li>1</li><li>2</li></ul>');
    -  }
    -}
    -
    -
    -function testEnterInEmptyListItemAtEndOfList() {
    -  if (goog.userAgent.GECKO) {
    -    field1.setHtml(false,
    -        '<ul style="font-weight: bold">' +
    -            '<li>1</li>' +
    -            '<li>2</li>' +
    -            '<li>&nbsp;</li>' +
    -        '</ul>');
    -    var helper = new goog.testing.editor.TestHelper(field1.getElement());
    -    var li = field1.getElement().getElementsByTagName(goog.dom.TagName.LI)[2];
    -    helper.select(li.firstChild, 0);
    -    goog.testing.events.fireKeySequence(field1.getElement(),
    -                                        goog.events.KeyCodes.ENTER);
    -    helper.assertHtmlMatches(
    -        '<ul style="font-weight: bold"><li>1</li><li>2</li></ul><p>&nbsp;</p>');
    -  }
    -}
    -
    -
    -function testEnterInEmptyListItemInMiddleOfList() {
    -  if (goog.userAgent.GECKO) {
    -    field1.setHtml(false,
    -        '<ul style="font-weight: bold">' +
    -            '<li>1</li>' +
    -            '<li>&nbsp;</li>' +
    -            '<li>2</li>' +
    -        '</ul>');
    -    var helper = new goog.testing.editor.TestHelper(field1.getElement());
    -    var li = field1.getElement().getElementsByTagName(goog.dom.TagName.LI)[1];
    -    helper.select(li.firstChild, 0);
    -    goog.testing.events.fireKeySequence(field1.getElement(),
    -                                        goog.events.KeyCodes.ENTER);
    -    helper.assertHtmlMatches(
    -        '<ul style="font-weight: bold"><li>1</li></ul>' +
    -        '<p>&nbsp;</p>' +
    -        '<ul style="font-weight: bold"><li>2</li></ul>');
    -  }
    -}
    -
    -
    -function testEnterInEmptyListItemInSublist() {
    -  if (goog.userAgent.GECKO) {
    -    field1.setHtml(false,
    -        '<ul>' +
    -        '<li>A</li>' +
    -        '<ul style="font-weight: bold">' +
    -        '<li>1</li>' +
    -        '<li>&nbsp;</li>' +
    -        '<li>2</li>' +
    -        '</ul>' +
    -        '<li>B</li>' +
    -        '</ul>');
    -    var helper = new goog.testing.editor.TestHelper(field1.getElement());
    -    var li = field1.getElement().getElementsByTagName(goog.dom.TagName.LI)[2];
    -    helper.select(li.firstChild, 0);
    -    goog.testing.events.fireKeySequence(field1.getElement(),
    -                                        goog.events.KeyCodes.ENTER);
    -    helper.assertHtmlMatches(
    -        '<ul>' +
    -        '<li>A</li>' +
    -        '<ul style="font-weight: bold"><li>1</li></ul>' +
    -        '<li>&nbsp;</li>' +
    -        '<ul style="font-weight: bold"><li>2</li></ul>' +
    -        '<li>B</li>' +
    -        '</ul>');
    -  }
    -}
    -
    -
    -function testEnterInEmptyListItemAtBeginningOfSublist() {
    -  if (goog.userAgent.GECKO) {
    -    field1.setHtml(false,
    -        '<ul>' +
    -        '<li>A</li>' +
    -        '<ul style="font-weight: bold">' +
    -        '<li>&nbsp;</li>' +
    -        '<li>1</li>' +
    -        '<li>2</li>' +
    -        '</ul>' +
    -        '<li>B</li>' +
    -        '</ul>');
    -    var helper = new goog.testing.editor.TestHelper(field1.getElement());
    -    var li = field1.getElement().getElementsByTagName(goog.dom.TagName.LI)[1];
    -    helper.select(li.firstChild, 0);
    -    goog.testing.events.fireKeySequence(field1.getElement(),
    -                                        goog.events.KeyCodes.ENTER);
    -    helper.assertHtmlMatches(
    -        '<ul>' +
    -        '<li>A</li>' +
    -        '<li>&nbsp;</li>' +
    -        '<ul style="font-weight: bold"><li>1</li><li>2</li></ul>' +
    -        '<li>B</li>' +
    -        '</ul>');
    -  }
    -}
    -
    -
    -function testEnterInEmptyListItemAtEndOfSublist() {
    -  if (goog.userAgent.GECKO) {
    -    field1.setHtml(false,
    -        '<ul>' +
    -        '<li>A</li>' +
    -        '<ul style="font-weight: bold">' +
    -        '<li>1</li>' +
    -        '<li>2</li>' +
    -        '<li>&nbsp;</li>' +
    -        '</ul>' +
    -        '<li>B</li>' +
    -        '</ul>');
    -    var helper = new goog.testing.editor.TestHelper(field1.getElement());
    -    var li = field1.getElement().getElementsByTagName(goog.dom.TagName.LI)[3];
    -    helper.select(li.firstChild, 0);
    -    goog.testing.events.fireKeySequence(field1.getElement(),
    -                                        goog.events.KeyCodes.ENTER);
    -    helper.assertHtmlMatches(
    -        '<ul>' +
    -        '<li>A</li>' +
    -        '<ul style="font-weight: bold"><li>1</li><li>2</li></ul>' +
    -        '<li>&nbsp;</li>' +
    -        '<li>B</li>' +
    -        '</ul>');
    -  }
    -}
    -
    -
    -function testPrepareContentForPOnEnter() {
    -  assertPreparedContents('hi', 'hi');
    -  assertPreparedContents(
    -      goog.editor.BrowserFeature.COLLAPSES_EMPTY_NODES ? '<p>&nbsp;</p>' : '',
    -      '   ');
    -}
    -
    -
    -function testPrepareContentForDivOnEnter() {
    -  assertPreparedContents('hi', 'hi', goog.dom.TagName.DIV);
    -  assertPreparedContents(
    -      goog.editor.BrowserFeature.COLLAPSES_EMPTY_NODES ? '<div><br></div>' : '',
    -      '   ',
    -      goog.dom.TagName.DIV);
    -}
    -
    -
    -/**
    - * Assert that the prepared contents matches the expected.
    - */
    -function assertPreparedContents(expected, original, opt_tag) {
    -  var field = makeField('field1', opt_tag);
    -  field.makeEditable();
    -  assertEquals(expected,
    -      field.reduceOp_(
    -          goog.editor.Plugin.Op.PREPARE_CONTENTS_HTML, original));
    -}
    -
    -
    -/**
    - * Selects the node at the given id, and simulates an ENTER keypress.
    - * @param {googe.editor.Field} field The field with the node.
    - * @param {string} id A DOM id.
    - * @return {boolean} Whether preventDefault was called on the event.
    - */
    -function selectNodeAndHitEnter(field, id) {
    -  var cursor = field.getEditableDomHelper().getElement(id);
    -  goog.dom.Range.createFromNodeContents(cursor).select();
    -  return goog.testing.events.fireKeySequence(
    -      cursor, goog.events.KeyCodes.ENTER);
    -}
    -
    -
    -/**
    - * Creates a field with only the enter handler plugged in, for testing.
    - * @param {string} id A DOM id.
    - * @param {boolean=} opt_tag The block tag to use.  Defaults to P.
    - * @return {goog.editor.Field} A field.
    - */
    -function makeField(id, opt_tag) {
    -  var field = new goog.editor.Field(id);
    -  field.registerPlugin(
    -      new goog.editor.plugins.TagOnEnterHandler(opt_tag || goog.dom.TagName.P));
    -  return field;
    -}
    -
    -
    -/**
    - * Runs a test for splitting the dom.
    - * @param {number} offset Index into the text node to split.
    - * @param {string} firstHalfString What the html of the first half of the DOM
    - *     should be.
    - * @param {string} secondHalfString What the html of the 2nd half of the DOM
    - *     should be.
    - * @param {boolean} isAppend True if the second half should be appended to the
    - *     DOM.
    - * @param {boolean=} opt_goToRoot True if the root argument for splitDom should
    - *     be excluded.
    - */
    -function helpTestSplit_(offset, firstHalfString, secondHalfString, isAppend,
    -    opt_goToBody) {
    -  var node = document.createElement('div');
    -  node.innerHTML = '<b>begin bold<i>italic</i>end bold</b>';
    -  document.body.appendChild(node);
    -
    -  var italic = node.getElementsByTagName('i')[0].firstChild;
    -
    -  var splitFn = isAppend ?
    -      goog.editor.plugins.TagOnEnterHandler.splitDomAndAppend_ :
    -      goog.editor.plugins.TagOnEnterHandler.splitDom_;
    -  var secondHalf = splitFn(italic, offset, opt_goToBody ? undefined : node);
    -
    -  if (opt_goToBody) {
    -    secondHalfString = '<div>' + secondHalfString + '</div>';
    -  }
    -
    -  assertEquals('original node should have first half of the html',
    -               firstHalfString,
    -               node.innerHTML.toLowerCase().
    -      replace(goog.string.Unicode.NBSP, '&nbsp;'));
    -  assertEquals('new node should have second half of the html',
    -               secondHalfString,
    -               secondHalf.innerHTML.toLowerCase().
    -                   replace(goog.string.Unicode.NBSP, '&nbsp;'));
    -
    -  if (isAppend) {
    -    assertTrue('second half of dom should be the original node\'s next' +
    -               'sibling', node.nextSibling == secondHalf);
    -    goog.dom.removeNode(secondHalf);
    -  }
    -
    -  goog.dom.removeNode(node);
    -}
    -
    -
    -/**
    - * Runs different cases of splitting the DOM.
    - * @param {function(number, string, string)} testFn Function that takes an
    - *     offset, firstHalfString and secondHalfString as parameters.
    - */
    -function splitDomCases_(testFn) {
    -  testFn(3, '<b>begin bold<i>ita</i></b>', '<b><i>lic</i>end bold</b>');
    -  testFn(0, '<b>begin bold<i>&nbsp;</i></b>', '<b><i>italic</i>end bold</b>');
    -  testFn(6, '<b>begin bold<i>italic</i></b>', '<b><i>&nbsp;</i>end bold</b>');
    -}
    -
    -
    -function testSplitDom() {
    -  splitDomCases_(function(offset, firstHalfString, secondHalfString) {
    -    helpTestSplit_(offset, firstHalfString, secondHalfString, false, true);
    -    helpTestSplit_(offset, firstHalfString, secondHalfString, false, false);
    -  });
    -}
    -
    -
    -function testSplitDomAndAppend() {
    -  splitDomCases_(function(offset, firstHalfString, secondHalfString) {
    -    helpTestSplit_(offset, firstHalfString, secondHalfString, true, false);
    -  });
    -}
    -
    -
    -function testSplitDomAtElement() {
    -  var node = document.createElement('div');
    -  node.innerHTML = '<div>abc<br>def</div>';
    -  document.body.appendChild(node);
    -
    -  goog.editor.plugins.TagOnEnterHandler.splitDomAndAppend_(node.firstChild, 1,
    -      node.firstChild);
    -
    -  goog.testing.dom.assertHtmlContentsMatch('<div>abc</div><div><br>def</div>',
    -      node);
    -
    -  goog.dom.removeNode(node);
    -}
    -
    -
    -function testSplitDomAtElementStart() {
    -  var node = document.createElement('div');
    -  node.innerHTML = '<div>abc<br>def</div>';
    -  document.body.appendChild(node);
    -
    -  goog.editor.plugins.TagOnEnterHandler.splitDomAndAppend_(node.firstChild, 0,
    -      node.firstChild);
    -
    -  goog.testing.dom.assertHtmlContentsMatch('<div></div><div>abc<br>def</div>',
    -      node);
    -
    -  goog.dom.removeNode(node);
    -}
    -
    -
    -function testSplitDomAtChildlessElement() {
    -  var node = document.createElement('div');
    -  node.innerHTML = '<div>abc<br>def</div>';
    -  document.body.appendChild(node);
    -
    -  var br = node.getElementsByTagName(goog.dom.TagName.BR)[0];
    -  goog.editor.plugins.TagOnEnterHandler.splitDomAndAppend_(
    -      br, 0, node.firstChild);
    -
    -  goog.testing.dom.assertHtmlContentsMatch('<div>abc</div><div><br>def</div>',
    -      node);
    -
    -  goog.dom.removeNode(node);
    -}
    -
    -function testReplaceWhiteSpaceWithNbsp() {
    -  var node = document.createElement('div');
    -  var textNode = document.createTextNode('');
    -  node.appendChild(textNode);
    -
    -  textNode.nodeValue = ' test ';
    -  goog.editor.plugins.TagOnEnterHandler.replaceWhiteSpaceWithNbsp_(
    -      node.firstChild, true, false);
    -  assertHTMLEquals('&nbsp;test ', node.innerHTML);
    -
    -  textNode.nodeValue = '  test ';
    -  goog.editor.plugins.TagOnEnterHandler.replaceWhiteSpaceWithNbsp_(
    -      node.firstChild, true, false);
    -  assertHTMLEquals('&nbsp;test ', node.innerHTML);
    -
    -  textNode.nodeValue = ' test ';
    -  goog.editor.plugins.TagOnEnterHandler.replaceWhiteSpaceWithNbsp_(
    -      node.firstChild, false, false);
    -  assertHTMLEquals(' test&nbsp;', node.innerHTML);
    -
    -  textNode.nodeValue = ' test  ';
    -  goog.editor.plugins.TagOnEnterHandler.replaceWhiteSpaceWithNbsp_(
    -      node.firstChild, false, false);
    -  assertHTMLEquals(' test&nbsp;', node.innerHTML);
    -
    -  textNode.nodeValue = '';
    -  goog.editor.plugins.TagOnEnterHandler.replaceWhiteSpaceWithNbsp_(
    -      node.firstChild, false, false);
    -  assertHTMLEquals('&nbsp;', node.innerHTML);
    -
    -  textNode.nodeValue = '';
    -  goog.editor.plugins.TagOnEnterHandler.replaceWhiteSpaceWithNbsp_(
    -      node.firstChild, false, true);
    -  assertHTMLEquals('', node.innerHTML);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/undoredo.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/undoredo.js
    deleted file mode 100644
    index d273a4c153b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/undoredo.js
    +++ /dev/null
    @@ -1,1016 +0,0 @@
    -// Copyright 2005 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Code for handling edit history (undo/redo).
    - *
    - */
    -
    -
    -goog.provide('goog.editor.plugins.UndoRedo');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.NodeOffset');
    -goog.require('goog.dom.Range');
    -goog.require('goog.editor.BrowserFeature');
    -goog.require('goog.editor.Command');
    -goog.require('goog.editor.Field');
    -goog.require('goog.editor.Plugin');
    -goog.require('goog.editor.node');
    -goog.require('goog.editor.plugins.UndoRedoManager');
    -goog.require('goog.editor.plugins.UndoRedoState');
    -goog.require('goog.events');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.log');
    -goog.require('goog.object');
    -
    -
    -
    -/**
    - * Encapsulates undo/redo logic using a custom undo stack (i.e. not browser
    - * built-in). Browser built-in undo stacks are too flaky (e.g. IE's gets
    - * clobbered on DOM modifications). Also, this allows interleaving non-editing
    - * commands into the undo stack via the UndoRedoManager.
    - *
    - * @param {goog.editor.plugins.UndoRedoManager=} opt_manager An undo redo
    - *    manager to be used by this plugin. If none is provided one is created.
    - * @constructor
    - * @extends {goog.editor.Plugin}
    - */
    -goog.editor.plugins.UndoRedo = function(opt_manager) {
    -  goog.editor.Plugin.call(this);
    -
    -  this.setUndoRedoManager(opt_manager ||
    -      new goog.editor.plugins.UndoRedoManager());
    -
    -  // Map of goog.editor.Field hashcode to goog.events.EventHandler
    -  this.eventHandlers_ = {};
    -
    -  this.currentStates_ = {};
    -
    -  /**
    -   * @type {?string}
    -   * @private
    -   */
    -  this.initialFieldChange_ = null;
    -
    -  /**
    -   * A copy of {@code goog.editor.plugins.UndoRedo.restoreState} bound to this,
    -   * used by undo-redo state objects to restore the state of an editable field.
    -   * @type {Function}
    -   * @see goog.editor.plugins.UndoRedo#restoreState
    -   * @private
    -   */
    -  this.boundRestoreState_ = goog.bind(this.restoreState, this);
    -};
    -goog.inherits(goog.editor.plugins.UndoRedo, goog.editor.Plugin);
    -
    -
    -/**
    - * The logger for this class.
    - * @type {goog.log.Logger}
    - * @protected
    - * @override
    - */
    -goog.editor.plugins.UndoRedo.prototype.logger =
    -    goog.log.getLogger('goog.editor.plugins.UndoRedo');
    -
    -
    -/**
    - * The {@code UndoState_} whose change is in progress, null if an undo or redo
    - * is not in progress.
    - *
    - * @type {goog.editor.plugins.UndoRedo.UndoState_?}
    - * @private
    - */
    -goog.editor.plugins.UndoRedo.prototype.inProgressUndo_ = null;
    -
    -
    -/**
    - * The undo-redo stack manager used by this plugin.
    - * @type {goog.editor.plugins.UndoRedoManager}
    - * @private
    - */
    -goog.editor.plugins.UndoRedo.prototype.undoManager_;
    -
    -
    -/**
    - * The key for the event listener handling state change events from the
    - * undo-redo manager.
    - * @type {goog.events.Key}
    - * @private
    - */
    -goog.editor.plugins.UndoRedo.prototype.managerStateChangeKey_;
    -
    -
    -/**
    - * Commands implemented by this plugin.
    - * @enum {string}
    - */
    -goog.editor.plugins.UndoRedo.COMMAND = {
    -  UNDO: '+undo',
    -  REDO: '+redo'
    -};
    -
    -
    -/**
    - * Inverse map of execCommand strings to
    - * {@link goog.editor.plugins.UndoRedo.COMMAND} constants. Used to determine
    - * whether a string corresponds to a command this plugin handles in O(1) time.
    - * @type {Object}
    - * @private
    - */
    -goog.editor.plugins.UndoRedo.SUPPORTED_COMMANDS_ =
    -    goog.object.transpose(goog.editor.plugins.UndoRedo.COMMAND);
    -
    -
    -/**
    - * Set the max undo stack depth (not the real memory usage).
    - * @param {number} depth Depth of the stack.
    - */
    -goog.editor.plugins.UndoRedo.prototype.setMaxUndoDepth = function(depth) {
    -  this.undoManager_.setMaxUndoDepth(depth);
    -};
    -
    -
    -/**
    - * Set the undo-redo manager used by this plugin. Any state on a previous
    - * undo-redo manager is lost.
    - * @param {goog.editor.plugins.UndoRedoManager} manager The undo-redo manager.
    - */
    -goog.editor.plugins.UndoRedo.prototype.setUndoRedoManager = function(manager) {
    -  if (this.managerStateChangeKey_) {
    -    goog.events.unlistenByKey(this.managerStateChangeKey_);
    -  }
    -
    -  this.undoManager_ = manager;
    -  this.managerStateChangeKey_ =
    -      goog.events.listen(this.undoManager_,
    -          goog.editor.plugins.UndoRedoManager.EventType.STATE_CHANGE,
    -          this.dispatchCommandValueChange_,
    -          false,
    -          this);
    -};
    -
    -
    -/**
    - * Whether the string corresponds to a command this plugin handles.
    - * @param {string} command Command string to check.
    - * @return {boolean} Whether the string corresponds to a command
    - *     this plugin handles.
    - * @override
    - */
    -goog.editor.plugins.UndoRedo.prototype.isSupportedCommand = function(command) {
    -  return command in goog.editor.plugins.UndoRedo.SUPPORTED_COMMANDS_;
    -};
    -
    -
    -/**
    - * Unregisters and disables the fieldObject with this plugin. Thie does *not*
    - * clobber the undo stack for the fieldObject though.
    - * TODO(user): For the multifield version, we really should add a way to
    - * ignore undo actions on field's that have been made uneditable.
    - * This is probably as simple as skipping over entries in the undo stack
    - * that have a hashcode of an uneditable field.
    - * @param {goog.editor.Field} fieldObject The field to register with the plugin.
    - * @override
    - */
    -goog.editor.plugins.UndoRedo.prototype.unregisterFieldObject = function(
    -    fieldObject) {
    -  this.disable(fieldObject);
    -  this.setFieldObject(null);
    -};
    -
    -
    -/**
    - * This is so subclasses can deal with multifield undo-redo.
    - * @return {goog.editor.Field} The active field object for this field. This is
    - *     the one registered field object for the single-plugin case and the
    - *     focused field for the multi-field plugin case.
    - */
    -goog.editor.plugins.UndoRedo.prototype.getCurrentFieldObject = function() {
    -  return this.getFieldObject();
    -};
    -
    -
    -/**
    - * This is so subclasses can deal with multifield undo-redo.
    - * @param {string} fieldHashCode The Field's hashcode.
    - * @return {goog.editor.Field} The field object with the hashcode.
    - */
    -goog.editor.plugins.UndoRedo.prototype.getFieldObjectForHash = function(
    -    fieldHashCode) {
    -  // With single field undoredo, there's only one Field involved.
    -  return this.getFieldObject();
    -};
    -
    -
    -/**
    - * This is so subclasses can deal with multifield undo-redo.
    - * @return {goog.editor.Field} Target for COMMAND_VALUE_CHANGE events.
    - */
    -goog.editor.plugins.UndoRedo.prototype.getCurrentEventTarget = function() {
    -  return this.getFieldObject();
    -};
    -
    -
    -/** @override */
    -goog.editor.plugins.UndoRedo.prototype.enable = function(fieldObject) {
    -  if (this.isEnabled(fieldObject)) {
    -    return;
    -  }
    -
    -  // Don't want pending delayed changes from when undo-redo was disabled
    -  // firing after undo-redo is enabled since they might cause undo-redo stack
    -  // updates.
    -  fieldObject.clearDelayedChange();
    -
    -  var eventHandler = new goog.events.EventHandler(this);
    -
    -  // TODO(user): From ojan during a code review:
    -  // The beforechange handler is meant to be there so you can grab the cursor
    -  // position *before* the change is made as that's where you want the cursor to
    -  // be after an undo.
    -  //
    -  // It kinda looks like updateCurrentState_ doesn't do that correctly right
    -  // now, but it really should be fixed to do so. The cursor position stored in
    -  // the state should be the cursor position before any changes are made, not
    -  // the cursor position when the change finishes.
    -  //
    -  // It also seems like the if check below is just a bad one. We should do this
    -  // for browsers that use mutation events as well even though the beforechange
    -  // happens too late...maybe not. I don't know about this.
    -  if (!goog.editor.BrowserFeature.USE_MUTATION_EVENTS) {
    -    // We don't listen to beforechange in mutation-event browsers because
    -    // there we fire beforechange, then syncronously file change. The point
    -    // of before change is to capture before the user has changed anything.
    -    eventHandler.listen(fieldObject,
    -        goog.editor.Field.EventType.BEFORECHANGE, this.handleBeforeChange_);
    -  }
    -  eventHandler.listen(fieldObject,
    -      goog.editor.Field.EventType.DELAYEDCHANGE, this.handleDelayedChange_);
    -  eventHandler.listen(fieldObject, goog.editor.Field.EventType.BLUR,
    -      this.handleBlur_);
    -
    -  this.eventHandlers_[fieldObject.getHashCode()] = eventHandler;
    -
    -  // We want to capture the initial state of a Trogedit field before any
    -  // editing has happened. This is necessary so that we can undo the first
    -  // change to a field, even if we don't handle beforeChange.
    -  this.updateCurrentState_(fieldObject);
    -};
    -
    -
    -/** @override */
    -goog.editor.plugins.UndoRedo.prototype.disable = function(fieldObject) {
    -  // Process any pending changes so we don't lose any undo-redo states that we
    -  // want prior to disabling undo-redo.
    -  fieldObject.clearDelayedChange();
    -
    -  var eventHandler = this.eventHandlers_[fieldObject.getHashCode()];
    -  if (eventHandler) {
    -    eventHandler.dispose();
    -    delete this.eventHandlers_[fieldObject.getHashCode()];
    -  }
    -
    -  // We delete the current state of the field on disable. When we re-enable
    -  // the state will be re-fetched. In most cases the content will be the same,
    -  // but this allows us to pick up changes while not editable. That way, when
    -  // undoing after starting an editable session, you can always undo to the
    -  // state you started in. Given this sequence of events:
    -  // Make editable
    -  // Type 'anakin'
    -  // Make not editable
    -  // Set HTML to be 'padme'
    -  // Make editable
    -  // Type 'dark side'
    -  // Undo
    -  // Without re-snapshoting current state on enable, the undo would go from
    -  // 'dark-side' -> 'anakin', rather than 'dark-side' -> 'padme'. You couldn't
    -  // undo the field to the state that existed immediately after it was made
    -  // editable for the second time.
    -  if (this.currentStates_[fieldObject.getHashCode()]) {
    -    delete this.currentStates_[fieldObject.getHashCode()];
    -  }
    -};
    -
    -
    -/** @override */
    -goog.editor.plugins.UndoRedo.prototype.isEnabled = function(fieldObject) {
    -  // All enabled plugins have a eventHandler so reuse that map rather than
    -  // storing additional enabled state.
    -  return !!this.eventHandlers_[fieldObject.getHashCode()];
    -};
    -
    -
    -/** @override */
    -goog.editor.plugins.UndoRedo.prototype.disposeInternal = function() {
    -  goog.editor.plugins.UndoRedo.superClass_.disposeInternal.call(this);
    -
    -  for (var hashcode in this.eventHandlers_) {
    -    this.eventHandlers_[hashcode].dispose();
    -    delete this.eventHandlers_[hashcode];
    -  }
    -  this.setFieldObject(null);
    -
    -  if (this.undoManager_) {
    -    this.undoManager_.dispose();
    -    delete this.undoManager_;
    -  }
    -};
    -
    -
    -/** @override */
    -goog.editor.plugins.UndoRedo.prototype.getTrogClassId = function() {
    -  return 'UndoRedo';
    -};
    -
    -
    -/** @override */
    -goog.editor.plugins.UndoRedo.prototype.execCommand = function(command,
    -    var_args) {
    -  if (command == goog.editor.plugins.UndoRedo.COMMAND.UNDO) {
    -    this.undoManager_.undo();
    -  } else if (command == goog.editor.plugins.UndoRedo.COMMAND.REDO) {
    -    this.undoManager_.redo();
    -  }
    -};
    -
    -
    -/** @override */
    -goog.editor.plugins.UndoRedo.prototype.queryCommandValue = function(command) {
    -  var state = null;
    -  if (command == goog.editor.plugins.UndoRedo.COMMAND.UNDO) {
    -    state = this.undoManager_.hasUndoState();
    -  } else if (command == goog.editor.plugins.UndoRedo.COMMAND.REDO) {
    -    state = this.undoManager_.hasRedoState();
    -  }
    -  return state;
    -};
    -
    -
    -/**
    - * Dispatches the COMMAND_VALUE_CHANGE event on the editable field or the field
    - * manager, as appropriate.
    - * Note: Really, people using multi field mode should be listening directly
    - * to the undo-redo manager for events.
    - * @private
    - */
    -goog.editor.plugins.UndoRedo.prototype.dispatchCommandValueChange_ =
    -    function() {
    -  var eventTarget = this.getCurrentEventTarget();
    -  eventTarget.dispatchEvent({
    -    type: goog.editor.Field.EventType.COMMAND_VALUE_CHANGE,
    -    commands: [goog.editor.plugins.UndoRedo.COMMAND.REDO,
    -      goog.editor.plugins.UndoRedo.COMMAND.UNDO]});
    -};
    -
    -
    -/**
    - * Restores the state of the editable field.
    - * @param {goog.editor.plugins.UndoRedo.UndoState_} state The state initiating
    - *    the restore.
    - * @param {string} content The content to restore.
    - * @param {goog.editor.plugins.UndoRedo.CursorPosition_?} cursorPosition
    - *     The cursor position within the content.
    - */
    -goog.editor.plugins.UndoRedo.prototype.restoreState = function(
    -    state, content, cursorPosition) {
    -  // Fire any pending changes to get the current field state up to date and
    -  // then stop listening to changes while doing the undo/redo.
    -  var fieldObj = this.getFieldObjectForHash(state.fieldHashCode);
    -  if (!fieldObj) {
    -    return;
    -  }
    -
    -  // Fires any pending changes, and stops the change events. Still want to
    -  // dispatch before change, as a change is being made and the change event
    -  // will be manually dispatched below after the new content has been restored
    -  // (also restarting change events).
    -  fieldObj.stopChangeEvents(true, true);
    -
    -  // To prevent the situation where we stop change events and then an exception
    -  // happens before we can restart change events, the following code must be in
    -  // a try-finally block.
    -  try {
    -    fieldObj.dispatchBeforeChange();
    -
    -    // Restore the state
    -    fieldObj.execCommand(goog.editor.Command.CLEAR_LOREM, true);
    -
    -    // We specifically set the raw innerHTML of the field here as that's what
    -    // we get from the field when we save an undo/redo state. There's
    -    // no need to clean/unclean the contents in either direction.
    -    goog.editor.node.replaceInnerHtml(fieldObj.getElement(), content);
    -
    -    if (cursorPosition) {
    -      cursorPosition.select();
    -    }
    -
    -    var previousFieldObject = this.getCurrentFieldObject();
    -    fieldObj.focus();
    -
    -    // Apps that integrate their undo-redo with Trogedit may be
    -    // in a state where there is no previous field object (no field focused at
    -    // the time of undo), so check for existence first.
    -    if (previousFieldObject &&
    -        previousFieldObject.getHashCode() != state.fieldHashCode) {
    -      previousFieldObject.execCommand(goog.editor.Command.UPDATE_LOREM);
    -    }
    -
    -    // We need to update currentState_ to reflect the change.
    -    this.currentStates_[state.fieldHashCode].setUndoState(
    -        content, cursorPosition);
    -  } catch (e) {
    -    goog.log.error(this.logger, 'Error while restoring undo state', e);
    -  } finally {
    -    // Clear the delayed change event, set flag so we know not to act on it.
    -    this.inProgressUndo_ = state;
    -    // Notify the editor that we've changed (fire autosave).
    -    // Note that this starts up change events again, so we don't have to
    -    // manually do so even though we stopped change events above.
    -    fieldObj.dispatchChange();
    -    fieldObj.dispatchSelectionChangeEvent();
    -  }
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.editor.plugins.UndoRedo.prototype.handleKeyboardShortcut = function(e, key,
    -    isModifierPressed) {
    -  if (isModifierPressed) {
    -    var command;
    -    if (key == 'z') {
    -      command = e.shiftKey ? goog.editor.plugins.UndoRedo.COMMAND.REDO :
    -          goog.editor.plugins.UndoRedo.COMMAND.UNDO;
    -    } else if (key == 'y') {
    -      command = goog.editor.plugins.UndoRedo.COMMAND.REDO;
    -    }
    -
    -    if (command) {
    -      // In the case where Trogedit shares its undo redo stack with another
    -      // application it's possible that an undo or redo will not be for an
    -      // goog.editor.Field. In this case we don't want to go through the
    -      // goog.editor.Field execCommand flow which stops and restarts events on
    -      // the current field. Only Trogedit UndoState's have a fieldHashCode so
    -      // use that to distinguish between Trogedit and other states.
    -      var state = command == goog.editor.plugins.UndoRedo.COMMAND.UNDO ?
    -          this.undoManager_.undoPeek() : this.undoManager_.redoPeek();
    -      if (state && state.fieldHashCode) {
    -        this.getCurrentFieldObject().execCommand(command);
    -      } else {
    -        this.execCommand(command);
    -      }
    -
    -      return true;
    -    }
    -  }
    -
    -  return false;
    -};
    -
    -
    -/**
    - * Clear the undo/redo stack.
    - */
    -goog.editor.plugins.UndoRedo.prototype.clearHistory = function() {
    -  // Fire all pending change events, so that they don't come back
    -  // asynchronously to fill the queue.
    -  this.getFieldObject().stopChangeEvents(true, true);
    -  this.undoManager_.clearHistory();
    -  this.getFieldObject().startChangeEvents();
    -};
    -
    -
    -/**
    - * Refreshes the current state of the editable field as maintained by undo-redo,
    - * without adding any undo-redo states to the stack.
    - * @param {goog.editor.Field} fieldObject The editable field.
    - */
    -goog.editor.plugins.UndoRedo.prototype.refreshCurrentState = function(
    -    fieldObject) {
    -  if (this.isEnabled(fieldObject)) {
    -    if (this.currentStates_[fieldObject.getHashCode()]) {
    -      delete this.currentStates_[fieldObject.getHashCode()];
    -    }
    -    this.updateCurrentState_(fieldObject);
    -  }
    -};
    -
    -
    -/**
    - * Before the field changes, we want to save the state.
    - * @param {goog.events.Event} e The event.
    - * @private
    - */
    -goog.editor.plugins.UndoRedo.prototype.handleBeforeChange_ = function(e) {
    -  if (this.inProgressUndo_) {
    -    // We are in between a previous undo and its delayed change event.
    -    // Continuing here clobbers the redo stack.
    -    // This does mean that if you are trying to undo/redo really quickly, it
    -    // will be gated by the speed of delayed change events.
    -    return;
    -  }
    -
    -  var fieldObj = /** @type {goog.editor.Field} */ (e.target);
    -  var fieldHashCode = fieldObj.getHashCode();
    -
    -  if (this.initialFieldChange_ != fieldHashCode) {
    -    this.initialFieldChange_ = fieldHashCode;
    -    this.updateCurrentState_(fieldObj);
    -  }
    -};
    -
    -
    -/**
    - * After some idle time, we want to save the state.
    - * @param {goog.events.Event} e The event.
    - * @private
    - */
    -goog.editor.plugins.UndoRedo.prototype.handleDelayedChange_ = function(e) {
    -  // This was undo making a change, don't add it BACK into the history
    -  if (this.inProgressUndo_) {
    -    // Must clear this.inProgressUndo_ before dispatching event because the
    -    // dispatch can cause another, queued undo that should be allowed to go
    -    // through.
    -    var state = this.inProgressUndo_;
    -    this.inProgressUndo_ = null;
    -    state.dispatchEvent(goog.editor.plugins.UndoRedoState.ACTION_COMPLETED);
    -    return;
    -  }
    -
    -  this.updateCurrentState_(/** @type {goog.editor.Field} */ (e.target));
    -};
    -
    -
    -/**
    - * When the user blurs away, we need to save the state on that field.
    - * @param {goog.events.Event} e The event.
    - * @private
    - */
    -goog.editor.plugins.UndoRedo.prototype.handleBlur_ = function(e) {
    -  var fieldObj = /** @type {goog.editor.Field} */ (e.target);
    -  if (fieldObj) {
    -    fieldObj.clearDelayedChange();
    -  }
    -};
    -
    -
    -/**
    - * Returns the goog.editor.plugins.UndoRedo.CursorPosition_ for the current
    - * selection in the given Field.
    - * @param {goog.editor.Field} fieldObj The field object.
    - * @return {goog.editor.plugins.UndoRedo.CursorPosition_} The CursorPosition_ or
    - *    null if there is no valid selection.
    - * @private
    - */
    -goog.editor.plugins.UndoRedo.prototype.getCursorPosition_ = function(fieldObj) {
    -  var cursorPos = new goog.editor.plugins.UndoRedo.CursorPosition_(fieldObj);
    -  if (!cursorPos.isValid()) {
    -    return null;
    -  }
    -  return cursorPos;
    -};
    -
    -
    -/**
    - * Helper method for saving state.
    - * @param {goog.editor.Field} fieldObj The field object.
    - * @private
    - */
    -goog.editor.plugins.UndoRedo.prototype.updateCurrentState_ = function(
    -    fieldObj) {
    -  var fieldHashCode = fieldObj.getHashCode();
    -  // We specifically grab the raw innerHTML of the field here as that's what
    -  // we would set on the field in the case of an undo/redo operation. There's
    -  // no need to clean/unclean the contents in either direction. In the case of
    -  // lorem ipsum being used, we want to capture the effective state (empty, no
    -  // cursor position) rather than capturing the lorem html.
    -  var content, cursorPos;
    -  if (fieldObj.queryCommandValue(goog.editor.Command.USING_LOREM)) {
    -    content = '';
    -    cursorPos = null;
    -  } else {
    -    content = fieldObj.getElement().innerHTML;
    -    cursorPos = this.getCursorPosition_(fieldObj);
    -  }
    -
    -  var currentState = this.currentStates_[fieldHashCode];
    -  if (currentState) {
    -    // Don't create states if the content hasn't changed (spurious
    -    // delayed change). This can happen when lorem is cleared, for example.
    -    if (currentState.undoContent_ == content) {
    -      return;
    -    } else if (content == '' || currentState.undoContent_ == '') {
    -      // If lorem ipsum is on we say the contents are the empty string. However,
    -      // for an empty text shape with focus, the empty contents might not be
    -      // the same, depending on plugins. We want these two empty states to be
    -      // considered identical because to the user they are indistinguishable,
    -      // so we use fieldObj.getInjectableContents to map between them.
    -      // We cannot use getInjectableContents when first creating the undo
    -      // content for a field with lorem, because on enable when this is first
    -      // called we can't guarantee plugin registration order, so the
    -      // injectableContents at that time might not match the final
    -      // injectableContents.
    -      var emptyContents = fieldObj.getInjectableContents('', {});
    -      if (content == emptyContents && currentState.undoContent_ == '' ||
    -          currentState.undoContent_ == emptyContents && content == '') {
    -        return;
    -      }
    -    }
    -
    -    currentState.setRedoState(content, cursorPos);
    -    this.undoManager_.addState(currentState);
    -  }
    -
    -  this.currentStates_[fieldHashCode] =
    -      new goog.editor.plugins.UndoRedo.UndoState_(fieldHashCode, content,
    -          cursorPos, this.boundRestoreState_);
    -};
    -
    -
    -
    -/**
    - * This object encapsulates the state of an editable field.
    - *
    - * @param {string} fieldHashCode String the id of the field we're saving the
    - *     content of.
    - * @param {string} content String the actual text we're saving.
    - * @param {goog.editor.plugins.UndoRedo.CursorPosition_?} cursorPosition
    - *     CursorPosLite object for the cursor position in the field.
    - * @param {Function} restore The function used to restore editable field state.
    - * @private
    - * @constructor
    - * @extends {goog.editor.plugins.UndoRedoState}
    - */
    -goog.editor.plugins.UndoRedo.UndoState_ = function(fieldHashCode, content,
    -    cursorPosition, restore) {
    -  goog.editor.plugins.UndoRedoState.call(this, true);
    -
    -  /**
    -   * The hash code for the field whose content is being saved.
    -   * @type {string}
    -   */
    -  this.fieldHashCode = fieldHashCode;
    -
    -  /**
    -   * The bound copy of {@code goog.editor.plugins.UndoRedo.restoreState} used by
    -   * this state.
    -   * @type {Function}
    -   * @private
    -   */
    -  this.restore_ = restore;
    -
    -  this.setUndoState(content, cursorPosition);
    -};
    -goog.inherits(goog.editor.plugins.UndoRedo.UndoState_,
    -    goog.editor.plugins.UndoRedoState);
    -
    -
    -/**
    - * The content to restore on undo.
    - * @type {string}
    - * @private
    - */
    -goog.editor.plugins.UndoRedo.UndoState_.prototype.undoContent_;
    -
    -
    -/**
    - * The cursor position to restore on undo.
    - * @type {goog.editor.plugins.UndoRedo.CursorPosition_?}
    - * @private
    - */
    -goog.editor.plugins.UndoRedo.UndoState_.prototype.undoCursorPosition_;
    -
    -
    -/**
    - * The content to restore on redo, undefined until the state is pushed onto the
    - * undo stack.
    - * @type {string|undefined}
    - * @private
    - */
    -goog.editor.plugins.UndoRedo.UndoState_.prototype.redoContent_;
    -
    -
    -/**
    - * The cursor position to restore on redo, undefined until the state is pushed
    - * onto the undo stack.
    - * @type {goog.editor.plugins.UndoRedo.CursorPosition_|null|undefined}
    - * @private
    - */
    -goog.editor.plugins.UndoRedo.UndoState_.prototype.redoCursorPosition_;
    -
    -
    -/**
    - * Performs the undo operation represented by this state.
    - * @override
    - */
    -goog.editor.plugins.UndoRedo.UndoState_.prototype.undo = function() {
    -  this.restore_(this, this.undoContent_,
    -      this.undoCursorPosition_);
    -};
    -
    -
    -/**
    - * Performs the redo operation represented by this state.
    - * @override
    - */
    -goog.editor.plugins.UndoRedo.UndoState_.prototype.redo = function() {
    -  this.restore_(this, this.redoContent_,
    -      this.redoCursorPosition_);
    -};
    -
    -
    -/**
    - * Updates the undo portion of this state. Should only be used to update the
    - * current state of an editable field, which is not yet on the undo stack after
    - * an undo or redo operation. You should never be modifying states on the stack!
    - * @param {string} content The current content.
    - * @param {goog.editor.plugins.UndoRedo.CursorPosition_?} cursorPosition
    - *     The current cursor position.
    - */
    -goog.editor.plugins.UndoRedo.UndoState_.prototype.setUndoState = function(
    -    content, cursorPosition) {
    -  this.undoContent_ = content;
    -  this.undoCursorPosition_ = cursorPosition;
    -};
    -
    -
    -/**
    - * Adds redo information to this state. This method should be called before the
    - * state is added onto the undo stack.
    - *
    - * @param {string} content The content to restore on a redo.
    - * @param {goog.editor.plugins.UndoRedo.CursorPosition_?} cursorPosition
    - *     The cursor position to restore on a redo.
    - */
    -goog.editor.plugins.UndoRedo.UndoState_.prototype.setRedoState = function(
    -    content, cursorPosition) {
    -  this.redoContent_ = content;
    -  this.redoCursorPosition_ = cursorPosition;
    -};
    -
    -
    -/**
    - * Checks if the *contents* of two
    - * {@code goog.editor.plugins.UndoRedo.UndoState_}s are the same.  We don't
    - * bother checking the cursor position (that's not something we'd want to save
    - * anyway).
    - * @param {goog.editor.plugins.UndoRedoState} rhs The state to compare.
    - * @return {boolean} Whether the contents are the same.
    - * @override
    - */
    -goog.editor.plugins.UndoRedo.UndoState_.prototype.equals = function(rhs) {
    -  return this.fieldHashCode == rhs.fieldHashCode &&
    -      this.undoContent_ == rhs.undoContent_ &&
    -      this.redoContent_ == rhs.redoContent_;
    -};
    -
    -
    -
    -/**
    - * Stores the state of the selection in a way the survives DOM modifications
    - * that don't modify the user-interactable content (e.g. making something bold
    - * vs. typing a character).
    - *
    - * TODO(user): Completely get rid of this and use goog.dom.SavedCaretRange.
    - *
    - * @param {goog.editor.Field} field The field the selection is in.
    - * @private
    - * @constructor
    - */
    -goog.editor.plugins.UndoRedo.CursorPosition_ = function(field) {
    -  this.field_ = field;
    -
    -  var win = field.getEditableDomHelper().getWindow();
    -  var range = field.getRange();
    -  var isValidRange = !!range && range.isRangeInDocument() &&
    -      range.getWindow() == win;
    -  range = isValidRange ? range : null;
    -
    -  if (goog.editor.BrowserFeature.HAS_W3C_RANGES) {
    -    this.initW3C_(range);
    -  } else if (goog.editor.BrowserFeature.HAS_IE_RANGES) {
    -    this.initIE_(range);
    -  }
    -};
    -
    -
    -/**
    - * The standards compliant version keeps a list of childNode offsets.
    - * @param {goog.dom.AbstractRange?} range The range to save.
    - * @private
    - */
    -goog.editor.plugins.UndoRedo.CursorPosition_.prototype.initW3C_ = function(
    -    range) {
    -  this.isValid_ = false;
    -
    -  // TODO: Check if the range is in the field before trying to save it
    -  // for FF 3 contentEditable.
    -  if (!range) {
    -    return;
    -  }
    -
    -  var anchorNode = range.getAnchorNode();
    -  var focusNode = range.getFocusNode();
    -  if (!anchorNode || !focusNode) {
    -    return;
    -  }
    -
    -  var anchorOffset = range.getAnchorOffset();
    -  var anchor = new goog.dom.NodeOffset(anchorNode, this.field_.getElement());
    -
    -  var focusOffset = range.getFocusOffset();
    -  var focus = new goog.dom.NodeOffset(focusNode, this.field_.getElement());
    -
    -  // Test range direction.
    -  if (range.isReversed()) {
    -    this.startOffset_ = focus;
    -    this.startChildOffset_ = focusOffset;
    -    this.endOffset_ = anchor;
    -    this.endChildOffset_ = anchorOffset;
    -  } else {
    -    this.startOffset_ = anchor;
    -    this.startChildOffset_ = anchorOffset;
    -    this.endOffset_ = focus;
    -    this.endChildOffset_ = focusOffset;
    -  }
    -
    -  this.isValid_ = true;
    -};
    -
    -
    -/**
    - * In IE, we just keep track of the text offset (number of characters).
    - * @param {goog.dom.AbstractRange?} range The range to save.
    - * @private
    - */
    -goog.editor.plugins.UndoRedo.CursorPosition_.prototype.initIE_ = function(
    -    range) {
    -  this.isValid_ = false;
    -
    -  if (!range) {
    -    return;
    -  }
    -
    -  var ieRange = range.getTextRange(0).getBrowserRangeObject();
    -
    -  if (!goog.dom.contains(this.field_.getElement(), ieRange.parentElement())) {
    -    return;
    -  }
    -
    -  // Create a range that encompasses the contentEditable region to serve
    -  // as a reference to form ranges below.
    -  var contentEditableRange =
    -      this.field_.getEditableDomHelper().getDocument().body.createTextRange();
    -  contentEditableRange.moveToElementText(this.field_.getElement());
    -
    -  // startMarker is a range from the start of the contentEditable node to the
    -  // start of the current selection.
    -  var startMarker = ieRange.duplicate();
    -  startMarker.collapse(true);
    -  startMarker.setEndPoint('StartToStart', contentEditableRange);
    -  this.startOffset_ =
    -      goog.editor.plugins.UndoRedo.CursorPosition_.computeEndOffsetIE_(
    -          startMarker);
    -
    -  // endMarker is a range from the start of teh contentEditable node to the
    -  // end of the current selection.
    -  var endMarker = ieRange.duplicate();
    -  endMarker.setEndPoint('StartToStart', contentEditableRange);
    -  this.endOffset_ =
    -      goog.editor.plugins.UndoRedo.CursorPosition_.computeEndOffsetIE_(
    -          endMarker);
    -
    -  this.isValid_ = true;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether this object is valid.
    - */
    -goog.editor.plugins.UndoRedo.CursorPosition_.prototype.isValid = function() {
    -  return this.isValid_;
    -};
    -
    -
    -/**
    - * @return {string} A string representation of this object.
    - * @override
    - */
    -goog.editor.plugins.UndoRedo.CursorPosition_.prototype.toString = function() {
    -  if (goog.editor.BrowserFeature.HAS_W3C_RANGES) {
    -    return 'W3C:' + this.startOffset_.toString() + '\n' +
    -        this.startChildOffset_ + ':' + this.endOffset_.toString() + '\n' +
    -        this.endChildOffset_;
    -  }
    -  return 'IE:' + this.startOffset_ + ',' + this.endOffset_;
    -};
    -
    -
    -/**
    - * Makes the browser's selection match the cursor position.
    - */
    -goog.editor.plugins.UndoRedo.CursorPosition_.prototype.select = function() {
    -  var range = this.getRange_(this.field_.getElement());
    -  if (range) {
    -    if (goog.editor.BrowserFeature.HAS_IE_RANGES) {
    -      this.field_.getElement().focus();
    -    }
    -    goog.dom.Range.createFromBrowserRange(range).select();
    -  }
    -};
    -
    -
    -/**
    - * Get the range that encompases the the cursor position relative to a given
    - * base node.
    - * @param {Element} baseNode The node to get the cursor position relative to.
    - * @return {Range|TextRange|null} The browser range for this position.
    - * @private
    - */
    -goog.editor.plugins.UndoRedo.CursorPosition_.prototype.getRange_ =
    -    function(baseNode) {
    -  if (goog.editor.BrowserFeature.HAS_W3C_RANGES) {
    -    var startNode = this.startOffset_.findTargetNode(baseNode);
    -    var endNode = this.endOffset_.findTargetNode(baseNode);
    -    if (!startNode || !endNode) {
    -      return null;
    -    }
    -
    -    // Create range.
    -    return /** @type {Range} */ (
    -        goog.dom.Range.createFromNodes(startNode, this.startChildOffset_,
    -            endNode, this.endChildOffset_).getBrowserRangeObject());
    -  }
    -
    -  // Create a collapsed selection at the start of the contentEditable region,
    -  // which the offsets were calculated relative to before.  Note that we force
    -  // a text range here so we can use moveToElementText.
    -  var sel = baseNode.ownerDocument.body.createTextRange();
    -  sel.moveToElementText(baseNode);
    -  sel.collapse(true);
    -  sel.moveEnd('character', this.endOffset_);
    -  sel.moveStart('character', this.startOffset_);
    -  return sel;
    -};
    -
    -
    -/**
    - * Compute the number of characters to the end of the range in IE.
    - * @param {TextRange} range The range to compute an offset for.
    - * @return {number} The number of characters to the end of the range.
    - * @private
    - */
    -goog.editor.plugins.UndoRedo.CursorPosition_.computeEndOffsetIE_ =
    -    function(range) {
    -  var testRange = range.duplicate();
    -
    -  // The number of offset characters is a little off depending on
    -  // what type of block elements happen to be between the start of the
    -  // textedit and the cursor position.  We fudge the offset until the
    -  // two ranges match.
    -  var text = range.text;
    -  var guess = text.length;
    -
    -  testRange.collapse(true);
    -  testRange.moveEnd('character', guess);
    -
    -  // Adjust the range until the end points match.  This doesn't quite
    -  // work if we're at the end of the field so we give up after a few
    -  // iterations.
    -  var diff;
    -  var numTries = 10;
    -  while (diff = testRange.compareEndPoints('EndToEnd', range)) {
    -    guess -= diff;
    -    testRange.moveEnd('character', -diff);
    -    --numTries;
    -    if (0 == numTries) {
    -      break;
    -    }
    -  }
    -  // When we set innerHTML, blank lines become a single space, causing
    -  // the cursor position to be off by one.  So we accommodate for blank
    -  // lines.
    -  var offset = 0;
    -  var pos = text.indexOf('\n\r');
    -  while (pos != -1) {
    -    ++offset;
    -    pos = text.indexOf('\n\r', pos + 1);
    -  }
    -  return guess + offset;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/undoredo_test.html b/src/database/third_party/closure-library/closure/goog/editor/plugins/undoredo_test.html
    deleted file mode 100644
    index a83e108c16c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/undoredo_test.html
    +++ /dev/null
    @@ -1,30 +0,0 @@
    -goog.editor.plugins
    -<!DOCTYPE html>
    -<!--
    -  All Rights Reserved.
    -
    -  @author ajp@google.com (Andy Perelson)
    --->
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Trogedit Unit Tests - goog.editor.plugins.UndoRedo
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.editor.plugins.UndoRedoTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="testField">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/undoredo_test.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/undoredo_test.js
    deleted file mode 100644
    index 80f2111207b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/undoredo_test.js
    +++ /dev/null
    @@ -1,516 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.editor.plugins.UndoRedoTest');
    -goog.setTestOnly('goog.editor.plugins.UndoRedoTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.dom.browserrange');
    -goog.require('goog.editor.Field');
    -goog.require('goog.editor.plugins.LoremIpsum');
    -goog.require('goog.editor.plugins.UndoRedo');
    -goog.require('goog.events');
    -goog.require('goog.functions');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.StrictMock');
    -goog.require('goog.testing.jsunit');
    -
    -var mockEditableField;
    -var editableField;
    -var fieldHashCode;
    -var undoPlugin;
    -var state;
    -var mockState;
    -var commands;
    -var clock;
    -var stubs = new goog.testing.PropertyReplacer();
    -
    -
    -function setUp() {
    -  mockEditableField = new goog.testing.StrictMock(goog.editor.Field);
    -
    -  // Update the arg list verifier for dispatchCommandValueChange to
    -  // correctly compare arguments that are arrays (or other complex objects).
    -  mockEditableField.$registerArgumentListVerifier('dispatchEvent',
    -      function(expected, args) {
    -        return goog.array.equals(expected, args,
    -            function(a, b) { assertObjectEquals(a, b); return true; });
    -      });
    -  mockEditableField.getHashCode = function() {
    -    return 'fieldId';
    -  };
    -
    -  undoPlugin = new goog.editor.plugins.UndoRedo();
    -  undoPlugin.registerFieldObject(mockEditableField);
    -  mockState = new goog.testing.StrictMock(
    -      goog.editor.plugins.UndoRedo.UndoState_);
    -  mockState.fieldHashCode = 'fieldId';
    -  mockState.isAsynchronous = function() {
    -    return false;
    -  };
    -  // Don't bother mocking the inherited event target pieces of the state.
    -  // If we don't do this, then mocked asynchronous undos are a lot harder and
    -  // that behavior is tested as part of the UndoRedoManager tests.
    -  mockState.addEventListener = goog.nullFunction;
    -
    -  commands = [
    -    goog.editor.plugins.UndoRedo.COMMAND.REDO,
    -    goog.editor.plugins.UndoRedo.COMMAND.UNDO
    -  ];
    -  state = new goog.editor.plugins.UndoRedo.UndoState_('1', '', null,
    -      goog.nullFunction);
    -
    -  clock = new goog.testing.MockClock(true);
    -
    -  editableField = new goog.editor.Field('testField');
    -  fieldHashCode = editableField.getHashCode();
    -}
    -
    -
    -function tearDown() {
    -  // Reset field so any attempted access during disposes don't cause errors.
    -  mockEditableField.$reset();
    -  clock.dispose();
    -  undoPlugin.dispose();
    -
    -  // NOTE(nicksantos): I think IE is blowing up on this call because
    -  // it is lame. It manifests its lameness by throwing an exception.
    -  // Kudos to XT for helping me to figure this out.
    -  try {
    -  } catch (e) {}
    -
    -  if (!editableField.isUneditable()) {
    -    editableField.makeUneditable();
    -  }
    -  editableField.dispose();
    -  goog.dom.getElement('testField').innerHTML = '';
    -  stubs.reset();
    -}
    -
    -
    -// undo-redo plugin tests
    -
    -
    -function testQueryCommandValue() {
    -  assertFalse('Must return false for empty undo stack.',
    -      undoPlugin.queryCommandValue(goog.editor.plugins.UndoRedo.COMMAND.UNDO));
    -
    -  assertFalse('Must return false for empty redo stack.',
    -      undoPlugin.queryCommandValue(goog.editor.plugins.UndoRedo.COMMAND.REDO));
    -
    -  undoPlugin.undoManager_.addState(mockState);
    -
    -  assertTrue('Must return true for a non-empty undo stack.',
    -      undoPlugin.queryCommandValue(goog.editor.plugins.UndoRedo.COMMAND.UNDO));
    -}
    -
    -
    -function testExecCommand() {
    -  undoPlugin.undoManager_.addState(mockState);
    -
    -  mockState.undo();
    -  mockState.$replay();
    -
    -  undoPlugin.execCommand(goog.editor.plugins.UndoRedo.COMMAND.UNDO);
    -  // Second undo should do nothing since only one item on stack.
    -  undoPlugin.execCommand(goog.editor.plugins.UndoRedo.COMMAND.UNDO);
    -  mockState.$verify();
    -
    -  mockState.$reset();
    -  mockState.redo();
    -  mockState.$replay();
    -  undoPlugin.execCommand(goog.editor.plugins.UndoRedo.COMMAND.REDO);
    -  // Second redo should do nothing since only one item on stack.
    -  undoPlugin.execCommand(goog.editor.plugins.UndoRedo.COMMAND.REDO);
    -  mockState.$verify();
    -}
    -
    -function testHandleKeyboardShortcut_TrogStates() {
    -  undoPlugin.undoManager_.addState(mockState);
    -  undoPlugin.undoManager_.addState(state);
    -  undoPlugin.undoManager_.undo();
    -  mockEditableField.$reset();
    -
    -  var stubUndoEvent = {ctrlKey: true, altKey: false, shiftKey: false};
    -  var stubRedoEvent = {ctrlKey: true, altKey: false, shiftKey: true};
    -  var stubRedoEvent2 = {ctrlKey: true, altKey: false, shiftKey: false};
    -  var result;
    -
    -  // Test handling Trogedit undos. Should always call EditableField's
    -  // execCommand. Since EditableField is mocked, this will not result in a call
    -  // to the mockState's undo and redo methods.
    -  mockEditableField.execCommand(goog.editor.plugins.UndoRedo.COMMAND.UNDO);
    -  mockEditableField.$replay();
    -  result = undoPlugin.handleKeyboardShortcut(stubUndoEvent, 'z', true);
    -  assertTrue('Plugin must return true when it handles shortcut.', result);
    -  mockEditableField.$verify();
    -  mockEditableField.$reset();
    -
    -  mockEditableField.execCommand(goog.editor.plugins.UndoRedo.COMMAND.REDO);
    -  mockEditableField.$replay();
    -  result = undoPlugin.handleKeyboardShortcut(stubRedoEvent, 'z', true);
    -  assertTrue('Plugin must return true when it handles shortcut.', result);
    -  mockEditableField.$verify();
    -  mockEditableField.$reset();
    -
    -  mockEditableField.execCommand(goog.editor.plugins.UndoRedo.COMMAND.REDO);
    -  mockEditableField.$replay();
    -  result = undoPlugin.handleKeyboardShortcut(stubRedoEvent2, 'y', true);
    -  assertTrue('Plugin must return true when it handles shortcut.', result);
    -  mockEditableField.$verify();
    -  mockEditableField.$reset();
    -
    -  mockEditableField.$replay();
    -  result = undoPlugin.handleKeyboardShortcut(stubRedoEvent2, 'y', false);
    -  assertFalse('Plugin must return false when modifier is not pressed.', result);
    -  mockEditableField.$verify();
    -  mockEditableField.$reset();
    -
    -  mockEditableField.$replay();
    -  result = undoPlugin.handleKeyboardShortcut(stubUndoEvent, 'f', true);
    -  assertFalse('Plugin must return false when it doesn\'t handle shortcut.',
    -      result);
    -  mockEditableField.$verify();
    -}
    -
    -function testHandleKeyboardShortcut_NotTrogStates() {
    -  var stubUndoEvent = {ctrlKey: true, altKey: false, shiftKey: false};
    -
    -  // Trogedit undo states all have a fieldHashCode, nulling that out makes this
    -  // state be treated as a non-Trogedit undo-redo state.
    -  state.fieldHashCode = null;
    -  undoPlugin.undoManager_.addState(state);
    -  mockEditableField.$reset();
    -
    -  // Non-trog state shouldn't go through EditableField.execCommand, however,
    -  // we still exect command value change dispatch since undo-redo plugin
    -  // redispatches those anytime manager's state changes.
    -  mockEditableField.dispatchEvent({
    -    type: goog.editor.Field.EventType.COMMAND_VALUE_CHANGE,
    -    commands: commands});
    -  mockEditableField.$replay();
    -  var result = undoPlugin.handleKeyboardShortcut(stubUndoEvent, 'z', true);
    -  assertTrue('Plugin must return true when it handles shortcut.' , result);
    -  mockEditableField.$verify();
    -}
    -
    -function testEnable() {
    -  assertFalse('Plugin must start disabled.',
    -      undoPlugin.isEnabled(editableField));
    -
    -  editableField.makeEditable(editableField);
    -  editableField.setHtml(false, '<div>a</div>');
    -  undoPlugin.enable(editableField);
    -
    -  assertTrue(undoPlugin.isEnabled(editableField));
    -  assertNotNull('Must have an event handler for enabled field.',
    -      undoPlugin.eventHandlers_[fieldHashCode]);
    -
    -  var currentState = undoPlugin.currentStates_[fieldHashCode];
    -  assertNotNull('Enabled plugin must have a current state.', currentState);
    -  assertEquals('After enable, undo content must match the field content.',
    -      editableField.getElement().innerHTML, currentState.undoContent_);
    -
    -  assertTrue('After enable, undo cursorPosition must match the field cursor' +
    -      'position.', cursorPositionsEqual(getCurrentCursorPosition(),
    -          currentState.undoCursorPosition_));
    -
    -  assertUndefined('Current state must never have redo content.',
    -      currentState.redoContent_);
    -  assertUndefined('Current state must never have redo cursor position.',
    -      currentState.redoCursorPosition_);
    -}
    -
    -function testDisable() {
    -  editableField.makeEditable(editableField);
    -  undoPlugin.enable(editableField);
    -  assertTrue('Plugin must be enabled so we can test disabling.',
    -      undoPlugin.isEnabled(editableField));
    -
    -  var delayedChangeFired = false;
    -  goog.events.listenOnce(editableField,
    -      goog.editor.Field.EventType.DELAYEDCHANGE,
    -      function(e) {
    -        delayedChangeFired = true;
    -      });
    -  editableField.setHtml(false, 'foo');
    -
    -  undoPlugin.disable(editableField);
    -  assertTrue('disable must fire pending delayed changes.', delayedChangeFired);
    -  assertEquals('disable must add undo state from pending change.',
    -      1, undoPlugin.undoManager_.undoStack_.length);
    -
    -  assertFalse(undoPlugin.isEnabled(editableField));
    -  assertUndefined('Disabled plugin must not have current state.',
    -      undoPlugin.eventHandlers_[fieldHashCode]);
    -  assertUndefined('Disabled plugin must not have event handlers.',
    -      undoPlugin.eventHandlers_[fieldHashCode]);
    -}
    -
    -function testUpdateCurrentState_() {
    -  editableField.registerPlugin(new goog.editor.plugins.LoremIpsum('LOREM'));
    -  editableField.makeEditable(editableField);
    -  editableField.getPluginByClassId('LoremIpsum').usingLorem_ = true;
    -  undoPlugin.updateCurrentState_(editableField);
    -  var currentState = undoPlugin.currentStates_[fieldHashCode];
    -  assertNotUndefined('Must create empty states for field using lorem ipsum.',
    -      undoPlugin.currentStates_[fieldHashCode]);
    -  assertEquals('', currentState.undoContent_);
    -  assertNull(currentState.undoCursorPosition_);
    -
    -  editableField.getPluginByClassId('LoremIpsum').usingLorem_ = false;
    -
    -  // Pretend foo is the default contents to test '' == default contents
    -  // behavior.
    -  editableField.getInjectableContents = function(contents, styles) {
    -    return contents == '' ? 'foo' : contents;
    -  };
    -  editableField.setHtml(false, 'foo');
    -  undoPlugin.updateCurrentState_(editableField);
    -  assertEquals(currentState, undoPlugin.currentStates_[fieldHashCode]);
    -
    -  // NOTE(user): Because there is already a current state, this setHtml will add
    -  // a state to the undo stack.
    -  editableField.setHtml(false, '<div>a</div>');
    -  // Select some text so we have a valid selection that gets saved in the
    -  // UndoState.
    -  goog.dom.browserrange.createRangeFromNodeContents(
    -      editableField.getElement()).select();
    -
    -  undoPlugin.updateCurrentState_(editableField);
    -  currentState = undoPlugin.currentStates_[fieldHashCode];
    -  assertNotNull('Must create state for field not using lorem ipsum',
    -      currentState);
    -  assertEquals(fieldHashCode, currentState.fieldHashCode);
    -  var content = editableField.getElement().innerHTML;
    -  var cursorPosition = getCurrentCursorPosition();
    -  assertEquals(content, currentState.undoContent_);
    -  assertTrue(cursorPositionsEqual(
    -      cursorPosition, currentState.undoCursorPosition_));
    -  assertUndefined(currentState.redoContent_);
    -  assertUndefined(currentState.redoCursorPosition_);
    -
    -  undoPlugin.updateCurrentState_(editableField);
    -  assertEquals('Updating state when state has not changed must not add undo ' +
    -      'state to stack.', 1, undoPlugin.undoManager_.undoStack_.length);
    -  assertEquals('Updating state when state has not changed must not create ' +
    -      'a new state.', currentState, undoPlugin.currentStates_[fieldHashCode]);
    -  assertUndefined('Updating state when state has not changed must not add ' +
    -      'redo content.', currentState.redoContent_);
    -  assertUndefined('Updating state when state has not changed must not add ' +
    -      'redo cursor position.', currentState.redoCursorPosition_);
    -
    -  editableField.setHtml(false, '<div>b</div>');
    -  undoPlugin.updateCurrentState_(editableField);
    -  currentState = undoPlugin.currentStates_[fieldHashCode];
    -  assertNotNull('Must create state for field not using lorem ipsum',
    -      currentState);
    -  assertEquals(fieldHashCode, currentState.fieldHashCode);
    -  var newContent = editableField.getElement().innerHTML;
    -  var newCursorPosition = getCurrentCursorPosition();
    -  assertEquals(newContent, currentState.undoContent_);
    -  assertTrue(cursorPositionsEqual(
    -      newCursorPosition, currentState.undoCursorPosition_));
    -  assertUndefined(currentState.redoContent_);
    -  assertUndefined(currentState.redoCursorPosition_);
    -
    -  var undoState = goog.array.peek(undoPlugin.undoManager_.undoStack_);
    -  assertNotNull('Must create state for field not using lorem ipsum',
    -      currentState);
    -  assertEquals(fieldHashCode, currentState.fieldHashCode);
    -  assertEquals(content, undoState.undoContent_);
    -  assertTrue(cursorPositionsEqual(
    -      cursorPosition, undoState.undoCursorPosition_));
    -  assertEquals(newContent, undoState.redoContent_);
    -  assertTrue(cursorPositionsEqual(
    -      newCursorPosition, undoState.redoCursorPosition_));
    -}
    -
    -
    -/**
    - * Tests that change events get restarted properly after an undo call despite
    - * an exception being thrown in the process (see bug/1991234).
    - */
    -function testUndoRestartsChangeEvents() {
    -  undoPlugin.registerFieldObject(editableField);
    -  editableField.makeEditable(editableField);
    -  editableField.setHtml(false, '<div>a</div>');
    -  clock.tick(1000);
    -  undoPlugin.enable(editableField);
    -
    -  // Change content so we can undo it.
    -  editableField.setHtml(false, '<div>b</div>');
    -  clock.tick(1000);
    -
    -  var currentState = undoPlugin.currentStates_[fieldHashCode];
    -  stubs.set(editableField, 'setCursorPosition',
    -      goog.functions.error('Faking exception during setCursorPosition()'));
    -  try {
    -    currentState.undo();
    -  } catch (e) {
    -    fail('Exception should not have been thrown during undo()');
    -  }
    -  assertEquals('Change events should be on', 0,
    -      editableField.stoppedEvents_[goog.editor.Field.EventType.CHANGE]);
    -  assertEquals('Delayed change events should be on', 0,
    -      editableField.stoppedEvents_[goog.editor.Field.EventType.DELAYEDCHANGE]);
    -}
    -
    -function testRefreshCurrentState() {
    -  editableField.makeEditable(editableField);
    -  editableField.setHtml(false, '<div>a</div>');
    -  clock.tick(1000);
    -  undoPlugin.enable(editableField);
    -
    -  // Create current state and verify it.
    -  var currentState = undoPlugin.currentStates_[fieldHashCode];
    -  assertEquals(fieldHashCode, currentState.fieldHashCode);
    -  var content = editableField.getElement().innerHTML;
    -  var cursorPosition = getCurrentCursorPosition();
    -  assertEquals(content, currentState.undoContent_);
    -  assertTrue(cursorPositionsEqual(
    -      cursorPosition, currentState.undoCursorPosition_));
    -
    -  // Update the field w/o dispatching delayed change, and verify that the
    -  // current state hasn't changed to reflect new values.
    -  editableField.setHtml(false, '<div>b</div>', true);
    -  clock.tick(1000);
    -  currentState = undoPlugin.currentStates_[fieldHashCode];
    -  assertEquals('Content must match old state.',
    -      content, currentState.undoContent_);
    -  assertTrue('Cursor position must match old state.',
    -      cursorPositionsEqual(
    -      cursorPosition, currentState.undoCursorPosition_));
    -
    -  undoPlugin.refreshCurrentState(editableField);
    -  assertFalse('Refresh must not cause states to go on the undo-redo stack.',
    -      undoPlugin.undoManager_.hasUndoState());
    -  currentState = undoPlugin.currentStates_[fieldHashCode];
    -  content = editableField.getElement().innerHTML;
    -  cursorPosition = getCurrentCursorPosition();
    -  assertEquals('Content must match current field state.',
    -      content, currentState.undoContent_);
    -  assertTrue('Cursor position must match current field state.',
    -      cursorPositionsEqual(cursorPosition, currentState.undoCursorPosition_));
    -
    -  undoPlugin.disable(editableField);
    -  assertUndefined(undoPlugin.currentStates_[fieldHashCode]);
    -  undoPlugin.refreshCurrentState(editableField);
    -  assertUndefined('Must not refresh current state of fields that do not have ' +
    -      'undo-redo enabled.', undoPlugin.currentStates_[fieldHashCode]);
    -}
    -
    -
    -/**
    - * Returns the CursorPosition for the selection currently in the Field.
    - * @return {goog.editor.plugins.UndoRedo.CursorPosition_}
    - */
    -function getCurrentCursorPosition() {
    -  return undoPlugin.getCursorPosition_(editableField);
    -}
    -
    -
    -/**
    - * Compares two cursor positions and returns whether they are equal.
    - * @param {goog.editor.plugins.UndoRedo.CursorPosition_} a
    - *     A cursor position.
    - * @param {goog.editor.plugins.UndoRedo.CursorPosition_} b
    - *     A cursor position.
    - * @return {boolean} Whether the positions are equal.
    - */
    -function cursorPositionsEqual(a, b) {
    -  if (!a && !b) {
    -    return true;
    -  } else if (a && b) {
    -    return a.toString() == b.toString();
    -  }
    -  // Only one cursor position is an object, can't be equal.
    -  return false;
    -}
    -// Undo state tests
    -
    -
    -function testSetUndoState() {
    -  state.setUndoState('content', 'position');
    -  assertEquals('Undo content incorrectly set', 'content', state.undoContent_);
    -  assertEquals('Undo cursor position incorrectly set', 'position',
    -      state.undoCursorPosition_);
    -}
    -
    -function testSetRedoState() {
    -  state.setRedoState('content', 'position');
    -  assertEquals('Redo content incorrectly set', 'content', state.redoContent_);
    -  assertEquals('Redo cursor position incorrectly set', 'position',
    -      state.redoCursorPosition_);
    -}
    -
    -function testEquals() {
    -  assertTrue('A state must equal itself', state.equals(state));
    -
    -  var state2 = new goog.editor.plugins.UndoRedo.UndoState_('1', '', null);
    -  assertTrue('A state must equal a state with the same hash code and content.',
    -      state.equals(state2));
    -
    -  state2 = new goog.editor.plugins.UndoRedo.UndoState_('1', '', 'foo');
    -  assertTrue('States with different cursor positions must be equal',
    -      state.equals(state2));
    -
    -  state2.setRedoState('bar', null);
    -  assertFalse('States with different redo content must not be equal',
    -      state.equals(state2));
    -
    -  state2 = new goog.editor.plugins.UndoRedo.UndoState_('3', '', null);
    -  assertFalse('States with different field hash codes must not be equal',
    -      state.equals(state2));
    -
    -  state2 = new goog.editor.plugins.UndoRedo.UndoState_('1', 'baz', null);
    -  assertFalse('States with different undoContent must not be equal',
    -      state.equals(state2));
    -}
    -
    -
    -/** @bug 1359214 */
    -function testClearUndoHistory() {
    -  var undoRedoPlugin = new goog.editor.plugins.UndoRedo();
    -  editableField.registerPlugin(undoRedoPlugin);
    -  editableField.makeEditable(editableField);
    -
    -  editableField.dispatchChange();
    -  clock.tick(10000);
    -
    -  editableField.getElement().innerHTML = 'y';
    -  editableField.dispatchChange();
    -  assertFalse(undoRedoPlugin.undoManager_.hasUndoState());
    -
    -  clock.tick(10000);
    -  assertTrue(undoRedoPlugin.undoManager_.hasUndoState());
    -
    -  editableField.getElement().innerHTML = 'z';
    -  editableField.dispatchChange();
    -
    -  var numCalls = 0;
    -  goog.events.listen(editableField, goog.editor.Field.EventType.DELAYEDCHANGE,
    -      function() {
    -        numCalls++;
    -      });
    -  undoRedoPlugin.clearHistory();
    -  // 1 call from stopChangeEvents(). 0 calls from startChangeEvents().
    -  assertEquals('clearHistory must not cause delayed change when none pending',
    -      1, numCalls);
    -
    -  clock.tick(10000);
    -  assertFalse(undoRedoPlugin.undoManager_.hasUndoState());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/undoredomanager.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/undoredomanager.js
    deleted file mode 100644
    index 5e054fdbd4a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/undoredomanager.js
    +++ /dev/null
    @@ -1,338 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Code for managing series of undo-redo actions in the form of
    - * {@link goog.editor.plugins.UndoRedoState}s.
    - *
    - */
    -
    -
    -goog.provide('goog.editor.plugins.UndoRedoManager');
    -goog.provide('goog.editor.plugins.UndoRedoManager.EventType');
    -
    -goog.require('goog.editor.plugins.UndoRedoState');
    -goog.require('goog.events');
    -goog.require('goog.events.EventTarget');
    -
    -
    -
    -/**
    - * Manages undo and redo operations through a series of {@code UndoRedoState}s
    - * maintained on undo and redo stacks.
    - *
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - */
    -goog.editor.plugins.UndoRedoManager = function() {
    -  goog.events.EventTarget.call(this);
    -
    -  /**
    -   * The maximum number of states on the undo stack at any time. Used to limit
    -   * the memory footprint of the undo-redo stack.
    -   * TODO(user) have a separate memory size based limit.
    -   * @type {number}
    -   * @private
    -   */
    -  this.maxUndoDepth_ = 100;
    -
    -  /**
    -   * The undo stack.
    -   * @type {Array<goog.editor.plugins.UndoRedoState>}
    -   * @private
    -   */
    -  this.undoStack_ = [];
    -
    -  /**
    -   * The redo stack.
    -   * @type {Array<goog.editor.plugins.UndoRedoState>}
    -   * @private
    -   */
    -  this.redoStack_ = [];
    -
    -  /**
    -   * A queue of pending undo or redo actions. Stored as objects with two
    -   * properties: func and state. The func property stores the undo or redo
    -   * function to be called, the state property stores the state that method
    -   * came from.
    -   * @type {Array<Object>}
    -   * @private
    -   */
    -  this.pendingActions_ = [];
    -};
    -goog.inherits(goog.editor.plugins.UndoRedoManager, goog.events.EventTarget);
    -
    -
    -/**
    - * Event types for the events dispatched by undo-redo manager.
    - * @enum {string}
    - */
    -goog.editor.plugins.UndoRedoManager.EventType = {
    -  /**
    -   * Signifies that he undo or redo stack transitioned between 0 and 1 states,
    -   * meaning that the ability to peform undo or redo operations has changed.
    -   */
    -  STATE_CHANGE: 'state_change',
    -
    -  /**
    -   * Signifies that a state was just added to the undo stack. Events of this
    -   * type will have a {@code state} property whose value is the state that
    -   * was just added.
    -   */
    -  STATE_ADDED: 'state_added',
    -
    -  /**
    -   * Signifies that the undo method of a state is about to be called.
    -   * Events of this type will have a {@code state} property whose value is the
    -   * state whose undo action is about to be performed. If the event is cancelled
    -   * the action does not proceed, but the state will still transition between
    -   * stacks.
    -   */
    -  BEFORE_UNDO: 'before_undo',
    -
    -  /**
    -   * Signifies that the redo method of a state is about to be called.
    -   * Events of this type will have a {@code state} property whose value is the
    -   * state whose redo action is about to be performed. If the event is cancelled
    -   * the action does not proceed, but the state will still transition between
    -   * stacks.
    -   */
    -  BEFORE_REDO: 'before_redo'
    -};
    -
    -
    -/**
    - * The key for the listener for the completion of the asynchronous state whose
    - * undo or redo action is in progress. Null if no action is in progress.
    - * @type {goog.events.Key}
    - * @private
    - */
    -goog.editor.plugins.UndoRedoManager.prototype.inProgressActionKey_ = null;
    -
    -
    -/**
    - * Set the max undo stack depth (not the real memory usage).
    - * @param {number} depth Depth of the stack.
    - */
    -goog.editor.plugins.UndoRedoManager.prototype.setMaxUndoDepth =
    -    function(depth) {
    -  this.maxUndoDepth_ = depth;
    -};
    -
    -
    -/**
    - * Add state to the undo stack. This clears the redo stack.
    - *
    - * @param {goog.editor.plugins.UndoRedoState} state The state to add to the undo
    - *     stack.
    - */
    -goog.editor.plugins.UndoRedoManager.prototype.addState = function(state) {
    -  // TODO: is the state.equals check necessary?
    -  if (this.undoStack_.length == 0 ||
    -      !state.equals(this.undoStack_[this.undoStack_.length - 1])) {
    -    this.undoStack_.push(state);
    -    if (this.undoStack_.length > this.maxUndoDepth_) {
    -      this.undoStack_.shift();
    -    }
    -    // Clobber the redo stack.
    -    var redoLength = this.redoStack_.length;
    -    this.redoStack_.length = 0;
    -
    -    this.dispatchEvent({
    -      type: goog.editor.plugins.UndoRedoManager.EventType.STATE_ADDED,
    -      state: state
    -    });
    -
    -    // If the redo state had states on it, then clobbering the redo stack above
    -    // has caused a state change.
    -    if (this.undoStack_.length == 1 || redoLength) {
    -      this.dispatchStateChange_();
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Dispatches a STATE_CHANGE event with this manager as the target.
    - * @private
    - */
    -goog.editor.plugins.UndoRedoManager.prototype.dispatchStateChange_ =
    -    function() {
    -  this.dispatchEvent(
    -      goog.editor.plugins.UndoRedoManager.EventType.STATE_CHANGE);
    -};
    -
    -
    -/**
    - * Performs the undo operation of the state at the top of the undo stack, moving
    - * that state to the top of the redo stack. If the undo stack is empty, does
    - * nothing.
    - */
    -goog.editor.plugins.UndoRedoManager.prototype.undo = function() {
    -  this.shiftState_(this.undoStack_, this.redoStack_);
    -};
    -
    -
    -/**
    - * Performs the redo operation of the state at the top of the redo stack, moving
    - * that state to the top of the undo stack. If redo undo stack is empty, does
    - * nothing.
    - */
    -goog.editor.plugins.UndoRedoManager.prototype.redo = function() {
    -  this.shiftState_(this.redoStack_, this.undoStack_);
    -};
    -
    -
    -/**
    - * @return {boolean} Wether the undo stack has items on it, i.e., if it is
    - *     possible to perform an undo operation.
    - */
    -goog.editor.plugins.UndoRedoManager.prototype.hasUndoState = function() {
    -  return this.undoStack_.length > 0;
    -};
    -
    -
    -/**
    - * @return {boolean} Wether the redo stack has items on it, i.e., if it is
    - *     possible to perform a redo operation.
    - */
    -goog.editor.plugins.UndoRedoManager.prototype.hasRedoState = function() {
    -  return this.redoStack_.length > 0;
    -};
    -
    -
    -/**
    - * Move a state from one stack to the other, performing the appropriate undo
    - * or redo action.
    - *
    - * @param {Array<goog.editor.plugins.UndoRedoState>} fromStack Stack to move
    - *     the state from.
    - * @param {Array<goog.editor.plugins.UndoRedoState>} toStack Stack to move
    - *     the state to.
    - * @private
    - */
    -goog.editor.plugins.UndoRedoManager.prototype.shiftState_ = function(
    -    fromStack, toStack) {
    -  if (fromStack.length) {
    -    var state = fromStack.pop();
    -
    -    // Push the current state into the redo stack.
    -    toStack.push(state);
    -
    -    this.addAction_({
    -      type: fromStack == this.undoStack_ ?
    -          goog.editor.plugins.UndoRedoManager.EventType.BEFORE_UNDO :
    -          goog.editor.plugins.UndoRedoManager.EventType.BEFORE_REDO,
    -      func: fromStack == this.undoStack_ ? state.undo : state.redo,
    -      state: state
    -    });
    -
    -    // If either stack transitioned between 0 and 1 in size then the ability
    -    // to do an undo or redo has changed and we must dispatch a state change.
    -    if (fromStack.length == 0 || toStack.length == 1) {
    -      this.dispatchStateChange_();
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Adds an action to the queue of pending undo or redo actions. If no actions
    - * are pending, immediately performs the action.
    - *
    - * @param {Object} action An undo or redo action. Stored as an object with two
    - *     properties: func and state. The func property stores the undo or redo
    - *     function to be called, the state property stores the state that method
    - *     came from.
    - * @private
    - */
    -goog.editor.plugins.UndoRedoManager.prototype.addAction_ = function(action) {
    -  this.pendingActions_.push(action);
    -  if (this.pendingActions_.length == 1) {
    -    this.doAction_();
    -  }
    -};
    -
    -
    -/**
    - * Executes the action at the front of the pending actions queue. If an action
    - * is already in progress or the queue is empty, does nothing.
    - * @private
    - */
    -goog.editor.plugins.UndoRedoManager.prototype.doAction_ = function() {
    -  if (this.inProgressActionKey_ || this.pendingActions_.length == 0) {
    -    return;
    -  }
    -
    -  var action = this.pendingActions_.shift();
    -
    -  var e = {
    -    type: action.type,
    -    state: action.state
    -  };
    -
    -  if (this.dispatchEvent(e)) {
    -    if (action.state.isAsynchronous()) {
    -      this.inProgressActionKey_ = goog.events.listen(action.state,
    -          goog.editor.plugins.UndoRedoState.ACTION_COMPLETED,
    -          this.finishAction_, false, this);
    -      action.func.call(action.state);
    -    } else {
    -      action.func.call(action.state);
    -      this.doAction_();
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Finishes processing the current in progress action, starting the next queued
    - * action if one exists.
    - * @private
    - */
    -goog.editor.plugins.UndoRedoManager.prototype.finishAction_ = function() {
    -  goog.events.unlistenByKey(/** @type {number} */ (this.inProgressActionKey_));
    -  this.inProgressActionKey_ = null;
    -  this.doAction_();
    -};
    -
    -
    -/**
    - * Clears the undo and redo stacks.
    - */
    -goog.editor.plugins.UndoRedoManager.prototype.clearHistory = function() {
    -  if (this.undoStack_.length > 0 || this.redoStack_.length > 0) {
    -    this.undoStack_.length = 0;
    -    this.redoStack_.length = 0;
    -    this.dispatchStateChange_();
    -  }
    -};
    -
    -
    -/**
    - * @return {goog.editor.plugins.UndoRedoState|undefined} The state at the top of
    - *     the undo stack without removing it from the stack.
    - */
    -goog.editor.plugins.UndoRedoManager.prototype.undoPeek = function() {
    -  return this.undoStack_[this.undoStack_.length - 1];
    -};
    -
    -
    -/**
    - * @return {goog.editor.plugins.UndoRedoState|undefined} The state at the top of
    - *     the redo stack without removing it from the stack.
    - */
    -goog.editor.plugins.UndoRedoManager.prototype.redoPeek = function() {
    -  return this.redoStack_[this.redoStack_.length - 1];
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/undoredomanager_test.html b/src/database/third_party/closure-library/closure/goog/editor/plugins/undoredomanager_test.html
    deleted file mode 100644
    index b5cecbb0aa1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/undoredomanager_test.html
    +++ /dev/null
    @@ -1,27 +0,0 @@
    -<!DOCTYPE html>
    -<!--
    -  All Rights Reserved.
    -
    -  @author ajp@google.com (Andy Perelson)
    --->
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Trogedit Unit Tests - goog.editor.plugins.UndoRedoManager
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.editor.plugins.UndoRedoManagerTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/undoredomanager_test.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/undoredomanager_test.js
    deleted file mode 100644
    index 4ea8a28860b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/undoredomanager_test.js
    +++ /dev/null
    @@ -1,387 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.editor.plugins.UndoRedoManagerTest');
    -goog.setTestOnly('goog.editor.plugins.UndoRedoManagerTest');
    -
    -goog.require('goog.editor.plugins.UndoRedoManager');
    -goog.require('goog.editor.plugins.UndoRedoState');
    -goog.require('goog.events');
    -goog.require('goog.testing.StrictMock');
    -goog.require('goog.testing.jsunit');
    -
    -var mockState1;
    -var mockState2;
    -var mockState3;
    -var states;
    -var manager;
    -var stateChangeCount;
    -var beforeUndoCount;
    -var beforeRedoCount;
    -var preventDefault;
    -
    -function setUp() {
    -  manager = new goog.editor.plugins.UndoRedoManager();
    -  stateChangeCount = 0;
    -  goog.events.listen(manager,
    -      goog.editor.plugins.UndoRedoManager.EventType.STATE_CHANGE,
    -      function() {
    -        stateChangeCount++;
    -      });
    -
    -  beforeUndoCount = 0;
    -  preventDefault = false;
    -  goog.events.listen(manager,
    -      goog.editor.plugins.UndoRedoManager.EventType.BEFORE_UNDO,
    -      function(e) {
    -        beforeUndoCount++;
    -        if (preventDefault) {
    -          e.preventDefault();
    -        }
    -      });
    -
    -  beforeRedoCount = 0;
    -  goog.events.listen(manager,
    -      goog.editor.plugins.UndoRedoManager.EventType.BEFORE_REDO,
    -      function(e) {
    -        beforeRedoCount++;
    -        if (preventDefault) {
    -          e.preventDefault();
    -        }
    -      });
    -
    -  mockState1 = new goog.testing.StrictMock(goog.editor.plugins.UndoRedoState);
    -  mockState2 = new goog.testing.StrictMock(goog.editor.plugins.UndoRedoState);
    -  mockState3 = new goog.testing.StrictMock(goog.editor.plugins.UndoRedoState);
    -  states = [mockState1, mockState2, mockState3];
    -
    -  mockState1.equals = mockState2.equals = mockState3.equals = function(state) {
    -    return this == state;
    -  };
    -
    -  mockState1.isAsynchronous = mockState2.isAsynchronous =
    -      mockState3.isAsynchronous = function() {
    -    return false;
    -  };
    -}
    -
    -
    -function tearDown() {
    -  goog.events.removeAll(manager);
    -  manager.dispose();
    -}
    -
    -
    -/**
    - * Adds all the mock states to the undo-redo manager.
    - */
    -function addStatesToManager() {
    -  manager.addState(states[0]);
    -
    -  for (var i = 1; i < states.length; i++) {
    -    var state = states[i];
    -    manager.addState(state);
    -  }
    -
    -  stateChangeCount = 0;
    -}
    -
    -
    -/**
    - * Resets all mock states so that they are ready for testing.
    - */
    -function resetStates() {
    -  for (var i = 0; i < states.length; i++) {
    -    states[i].$reset();
    -  }
    -}
    -
    -
    -function testSetMaxUndoDepth() {
    -  manager.setMaxUndoDepth(2);
    -  addStatesToManager();
    -  assertArrayEquals('Undo stack must contain only the two most recent states.',
    -      [mockState2, mockState3], manager.undoStack_);
    -}
    -
    -
    -function testAddState() {
    -  var stateAddedCount = 0;
    -  goog.events.listen(manager,
    -      goog.editor.plugins.UndoRedoManager.EventType.STATE_ADDED,
    -      function() {
    -        stateAddedCount++;
    -      });
    -
    -  manager.addState(mockState1);
    -  assertArrayEquals('Undo stack must contain added state.',
    -      [mockState1], manager.undoStack_);
    -  assertEquals('Manager must dispatch one state change event on ' +
    -      'undo stack 0->1 transition.', 1, stateChangeCount);
    -  assertEquals('State added must have dispatched once.', 1, stateAddedCount);
    -  mockState1.$reset();
    -
    -  // Test adding same state twice.
    -  manager.addState(mockState1);
    -  assertArrayEquals('Undo stack must not contain two equal, sequential states.',
    -      [mockState1], manager.undoStack_);
    -  assertEquals('Manager must not dispatch state change event when nothing is ' +
    -      'added to the stack.', 1, stateChangeCount);
    -  assertEquals('State added must have dispatched once.', 1, stateAddedCount);
    -
    -  // Test adding a second state.
    -  manager.addState(mockState2);
    -  assertArrayEquals('Undo stack must contain both states.',
    -      [mockState1, mockState2], manager.undoStack_);
    -  assertEquals('Manager must not dispatch state change event when second ' +
    -      'state is added to the stack.', 1, stateChangeCount);
    -  assertEquals('State added must have dispatched twice.', 2, stateAddedCount);
    -
    -  // Test adding a state when there is state on the redo stack.
    -  manager.undo();
    -  assertEquals('Manager must dispatch state change when redo stack goes to 1.',
    -      2, stateChangeCount);
    -
    -  manager.addState(mockState3);
    -  assertArrayEquals('Undo stack must contain states 1 and 3.',
    -      [mockState1, mockState3], manager.undoStack_);
    -  assertEquals('Manager must dispatch state change event when redo stack ' +
    -      'goes to zero.', 3, stateChangeCount);
    -  assertEquals('State added must have dispatched three times.',
    -      3, stateAddedCount);
    -}
    -
    -
    -function testHasState() {
    -  assertFalse('New manager must have no undo state.', manager.hasUndoState());
    -  assertFalse('New manager must have no redo state.', manager.hasRedoState());
    -
    -  manager.addState(mockState1);
    -  assertTrue('Manager must have only undo state.', manager.hasUndoState());
    -  assertFalse('Manager must have no redo state.', manager.hasRedoState());
    -
    -  manager.undo();
    -  assertFalse('Manager must have no undo state.', manager.hasUndoState());
    -  assertTrue('Manager must have only redo state.', manager.hasRedoState());
    -}
    -
    -
    -function testClearHistory() {
    -  addStatesToManager();
    -  manager.undo();
    -  stateChangeCount = 0;
    -
    -  manager.clearHistory();
    -  assertFalse('Undo stack must be empty.', manager.hasUndoState());
    -  assertFalse('Redo stack must be empty.', manager.hasRedoState());
    -  assertEquals('State change count must be 1 after clear history.',
    -      1, stateChangeCount);
    -
    -  manager.clearHistory();
    -  assertEquals('Repeated clearHistory must not change state change count.',
    -      1, stateChangeCount);
    -}
    -
    -
    -function testUndo() {
    -  addStatesToManager();
    -
    -  mockState3.undo();
    -  mockState3.$replay();
    -  manager.undo();
    -  assertEquals('Adding first item to redo stack must dispatch state change.',
    -      1, stateChangeCount);
    -  assertEquals('Undo must cause before action to dispatch',
    -      1, beforeUndoCount);
    -  mockState3.$verify();
    -
    -  preventDefault = true;
    -  mockState2.$replay();
    -  manager.undo();
    -  assertEquals('No stack transitions between 0 and 1, must not dispatch ' +
    -      'state change.', 1, stateChangeCount);
    -  assertEquals('Undo must cause before action to dispatch',
    -      2, beforeUndoCount);
    -  mockState2.$verify(); // Verify that undo was prevented.
    -
    -  preventDefault = false;
    -  mockState1.undo();
    -  mockState1.$replay();
    -  manager.undo();
    -  assertEquals('Doing last undo operation must dispatch state change.',
    -      2, stateChangeCount);
    -  assertEquals('Undo must cause before action to dispatch',
    -      3, beforeUndoCount);
    -  mockState1.$verify();
    -}
    -
    -
    -function testUndo_Asynchronous() {
    -  // Using a stub instead of a mock here so that the state can behave as an
    -  // EventTarget and dispatch events.
    -  var stubState = new goog.editor.plugins.UndoRedoState(true);
    -  var undoCalled = false;
    -  stubState.undo = function() {
    -    undoCalled = true;
    -  };
    -  stubState.redo = goog.nullFunction;
    -  stubState.equals = function() {
    -    return false;
    -  };
    -
    -  manager.addState(mockState2);
    -  manager.addState(mockState1);
    -  manager.addState(stubState);
    -
    -  manager.undo();
    -  assertTrue('undoCalled must be true (undo must be called).', undoCalled);
    -  assertEquals('Undo must cause before action to dispatch',
    -      1, beforeUndoCount);
    -
    -  // Calling undo shouldn't actually undo since the first async undo hasn't
    -  // fired an event yet.
    -  mockState1.$replay();
    -  manager.undo();
    -  mockState1.$verify();
    -  assertEquals('Before action must not dispatch for pending undo.',
    -      1, beforeUndoCount);
    -
    -  // Dispatching undo completed on first undo, should cause the second pending
    -  // undo to happen.
    -  mockState1.$reset();
    -  mockState1.undo();
    -  mockState1.$replay();
    -  mockState2.$replay(); // Nothing should happen to mockState2.
    -  stubState.dispatchEvent(goog.editor.plugins.UndoRedoState.ACTION_COMPLETED);
    -  mockState1.$verify();
    -  mockState2.$verify();
    -  assertEquals('Second undo must cause before action to dispatch',
    -      2, beforeUndoCount);
    -
    -  // Test last undo.
    -  mockState2.$reset();
    -  mockState2.undo();
    -  mockState2.$replay();
    -  manager.undo();
    -  mockState2.$verify();
    -  assertEquals('Third undo must cause before action to dispatch',
    -      3, beforeUndoCount);
    -}
    -
    -
    -function testRedo() {
    -  addStatesToManager();
    -  manager.undo();
    -  manager.undo();
    -  manager.undo();
    -  resetStates();
    -  stateChangeCount = 0;
    -
    -  mockState1.redo();
    -  mockState1.$replay();
    -  manager.redo();
    -  assertEquals('Pushing first item onto undo stack during redo must dispatch ' +
    -               'state change.', 1, stateChangeCount);
    -  assertEquals('First redo must cause before action to dispatch',
    -      1, beforeRedoCount);
    -  mockState1.$verify();
    -
    -  preventDefault = true;
    -  mockState2.$replay();
    -  manager.redo();
    -  assertEquals('No stack transitions between 0 and 1, must not dispatch ' +
    -      'state change.', 1, stateChangeCount);
    -  assertEquals('Second redo must cause before action to dispatch',
    -      2, beforeRedoCount);
    -  mockState2.$verify(); // Verify that redo was prevented.
    -
    -  preventDefault = false;
    -  mockState3.redo();
    -  mockState3.$replay();
    -  manager.redo();
    -  assertEquals('Removing last item from redo stack must dispatch state change.',
    -      2, stateChangeCount);
    -  assertEquals('Third redo must cause before action to dispatch',
    -      3, beforeRedoCount);
    -  mockState3.$verify();
    -  mockState3.$reset();
    -
    -  mockState3.undo();
    -  mockState3.$replay();
    -  manager.undo();
    -  assertEquals('Putting item on redo stack must dispatch state change.',
    -      3, stateChangeCount);
    -  assertEquals('Undo must cause before action to dispatch',
    -      4, beforeUndoCount);
    -  mockState3.$verify();
    -}
    -
    -
    -function testRedo_Asynchronous() {
    -  var stubState = new goog.editor.plugins.UndoRedoState(true);
    -  var redoCalled = false;
    -  stubState.redo = function() {
    -    redoCalled = true;
    -  };
    -  stubState.undo = goog.nullFunction;
    -  stubState.equals = function() {
    -    return false;
    -  };
    -
    -  manager.addState(stubState);
    -  manager.addState(mockState1);
    -  manager.addState(mockState2);
    -
    -  manager.undo();
    -  manager.undo();
    -  manager.undo();
    -  stubState.dispatchEvent(goog.editor.plugins.UndoRedoState.ACTION_COMPLETED);
    -  resetStates();
    -
    -  manager.redo();
    -  assertTrue('redoCalled must be true (redo must be called).', redoCalled);
    -
    -  // Calling redo shouldn't actually redo since the first async redo hasn't
    -  // fired an event yet.
    -  mockState1.$replay();
    -  manager.redo();
    -  mockState1.$verify();
    -
    -  // Dispatching redo completed on first redo, should cause the second pending
    -  // redo to happen.
    -  mockState1.$reset();
    -  mockState1.redo();
    -  mockState1.$replay();
    -  mockState2.$replay(); // Nothing should happen to mockState1.
    -  stubState.dispatchEvent(goog.editor.plugins.UndoRedoState.ACTION_COMPLETED);
    -  mockState1.$verify();
    -  mockState2.$verify();
    -
    -  // Test last redo.
    -  mockState2.$reset();
    -  mockState2.redo();
    -  mockState2.$replay();
    -  manager.redo();
    -  mockState2.$verify();
    -}
    -
    -function testUndoAndRedoPeek() {
    -  addStatesToManager();
    -  manager.undo();
    -
    -  assertEquals('redoPeek must return the top of the redo stack.',
    -      manager.redoStack_[manager.redoStack_.length - 1], manager.redoPeek());
    -  assertEquals('undoPeek must return the top of the undo stack.',
    -      manager.undoStack_[manager.undoStack_.length - 1], manager.undoPeek());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/undoredostate.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/undoredostate.js
    deleted file mode 100644
    index 9a772dd4382..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/undoredostate.js
    +++ /dev/null
    @@ -1,86 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Code for an UndoRedoState interface representing an undo and
    - * redo action for a particular state change. To be used by
    - * {@link goog.editor.plugins.UndoRedoManager}.
    - *
    - */
    -
    -
    -goog.provide('goog.editor.plugins.UndoRedoState');
    -
    -goog.require('goog.events.EventTarget');
    -
    -
    -
    -/**
    - * Represents an undo and redo action for a particular state transition.
    - *
    - * @param {boolean} asynchronous Whether the undo or redo actions for this
    - *     state complete asynchronously. If true, then this state must fire
    - *     an ACTION_COMPLETED event when undo or redo is complete.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - */
    -goog.editor.plugins.UndoRedoState = function(asynchronous) {
    -  goog.editor.plugins.UndoRedoState.base(this, 'constructor');
    -
    -  /**
    -   * Indicates if the undo or redo actions for this state complete
    -   * asynchronously.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.asynchronous_ = asynchronous;
    -};
    -goog.inherits(goog.editor.plugins.UndoRedoState, goog.events.EventTarget);
    -
    -
    -/**
    - * Event type for events indicating that this state has completed an undo or
    - * redo operation.
    - */
    -goog.editor.plugins.UndoRedoState.ACTION_COMPLETED = 'action_completed';
    -
    -
    -/**
    - * @return {boolean} Whether or not the undo and redo actions of this state
    - *     complete asynchronously. If true, the state will fire an ACTION_COMPLETED
    - *     event when an undo or redo action is complete.
    - */
    -goog.editor.plugins.UndoRedoState.prototype.isAsynchronous = function() {
    -  return this.asynchronous_;
    -};
    -
    -
    -/**
    - * Undoes the action represented by this state.
    - */
    -goog.editor.plugins.UndoRedoState.prototype.undo = goog.abstractMethod;
    -
    -
    -/**
    - * Redoes the action represented by this state.
    - */
    -goog.editor.plugins.UndoRedoState.prototype.redo = goog.abstractMethod;
    -
    -
    -/**
    - * Checks if two undo-redo states are the same.
    - * @param {goog.editor.plugins.UndoRedoState} state The state to compare.
    - * @return {boolean} Wether the two states are equal.
    - */
    -goog.editor.plugins.UndoRedoState.prototype.equals = goog.abstractMethod;
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/undoredostate_test.html b/src/database/third_party/closure-library/closure/goog/editor/plugins/undoredostate_test.html
    deleted file mode 100644
    index 6c63cb67c00..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/undoredostate_test.html
    +++ /dev/null
    @@ -1,28 +0,0 @@
    -goog.editor.plugins
    -<!DOCTYPE html>
    -<!--
    -  All Rights Reserved.
    -
    -  @author ajp@google.com (Andy Perelson)
    --->
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Trogedit Unit Tests - goog.editor.plugins.UndoRedoState
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.editor.plugins.UndoRedoStateTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/plugins/undoredostate_test.js b/src/database/third_party/closure-library/closure/goog/editor/plugins/undoredostate_test.js
    deleted file mode 100644
    index 4026964cfb3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/plugins/undoredostate_test.js
    +++ /dev/null
    @@ -1,34 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.editor.plugins.UndoRedoStateTest');
    -goog.setTestOnly('goog.editor.plugins.UndoRedoStateTest');
    -
    -goog.require('goog.editor.plugins.UndoRedoState');
    -goog.require('goog.testing.jsunit');
    -
    -var asyncState;
    -var syncState;
    -
    -function setUp() {
    -  asyncState = new goog.editor.plugins.UndoRedoState(true);
    -  syncState = new goog.editor.plugins.UndoRedoState(false);
    -}
    -
    -function testIsAsynchronous() {
    -  assertTrue('Must return true for asynchronous state',
    -      asyncState.isAsynchronous());
    -  assertFalse('Must return false for synchronous state',
    -      syncState.isAsynchronous());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/range.js b/src/database/third_party/closure-library/closure/goog/editor/range.js
    deleted file mode 100644
    index ec1a6a706d0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/range.js
    +++ /dev/null
    @@ -1,632 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Utilties for working with ranges.
    - *
    - * @author nicksantos@google.com (Nick Santos)
    - */
    -
    -goog.provide('goog.editor.range');
    -goog.provide('goog.editor.range.Point');
    -
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.dom.NodeType');
    -goog.require('goog.dom.Range');
    -goog.require('goog.dom.RangeEndpoint');
    -goog.require('goog.dom.SavedCaretRange');
    -goog.require('goog.editor.node');
    -goog.require('goog.editor.style');
    -goog.require('goog.iter');
    -goog.require('goog.userAgent');
    -
    -
    -/**
    - * Given a range and an element, create a narrower range that is limited to the
    - * boundaries of the element. If the range starts (or ends) outside the
    - * element, the narrowed range's start point (or end point) will be the
    - * leftmost (or rightmost) leaf of the element.
    - * @param {goog.dom.AbstractRange} range The range.
    - * @param {Element} el The element to limit the range to.
    - * @return {goog.dom.AbstractRange} A new narrowed range, or null if the
    - *     element does not contain any part of the given range.
    - */
    -goog.editor.range.narrow = function(range, el) {
    -  var startContainer = range.getStartNode();
    -  var endContainer = range.getEndNode();
    -
    -  if (startContainer && endContainer) {
    -    var isElement = function(node) {
    -      return node == el;
    -    };
    -    var hasStart = goog.dom.getAncestor(startContainer, isElement, true);
    -    var hasEnd = goog.dom.getAncestor(endContainer, isElement, true);
    -
    -    if (hasStart && hasEnd) {
    -      // The range is contained entirely within this element.
    -      return range.clone();
    -    } else if (hasStart) {
    -      // The range starts inside the element, but ends outside it.
    -      var leaf = goog.editor.node.getRightMostLeaf(el);
    -      return goog.dom.Range.createFromNodes(
    -          range.getStartNode(), range.getStartOffset(),
    -          leaf, goog.editor.node.getLength(leaf));
    -    } else if (hasEnd) {
    -      // The range starts outside the element, but ends inside it.
    -      return goog.dom.Range.createFromNodes(
    -          goog.editor.node.getLeftMostLeaf(el), 0,
    -          range.getEndNode(), range.getEndOffset());
    -    }
    -  }
    -
    -  // The selection starts and ends outside the element.
    -  return null;
    -};
    -
    -
    -/**
    - * Given a range, expand the range to include outer tags if the full contents of
    - * those tags are entirely selected.  This essentially changes the dom position,
    - * but not the visible position of the range.
    - * Ex. <li>foo</li> if "foo" is selected, instead of returning start and end
    - * nodes as the foo text node, return the li.
    - * @param {goog.dom.AbstractRange} range The range.
    - * @param {Node=} opt_stopNode Optional node to stop expanding past.
    - * @return {!goog.dom.AbstractRange} The expanded range.
    - */
    -goog.editor.range.expand = function(range, opt_stopNode) {
    -  // Expand the start out to the common container.
    -  var expandedRange = goog.editor.range.expandEndPointToContainer_(
    -      range, goog.dom.RangeEndpoint.START, opt_stopNode);
    -  // Expand the end out to the common container.
    -  expandedRange = goog.editor.range.expandEndPointToContainer_(
    -      expandedRange, goog.dom.RangeEndpoint.END, opt_stopNode);
    -
    -  var startNode = expandedRange.getStartNode();
    -  var endNode = expandedRange.getEndNode();
    -  var startOffset = expandedRange.getStartOffset();
    -  var endOffset = expandedRange.getEndOffset();
    -
    -  // If we have reached a common container, now expand out.
    -  if (startNode == endNode) {
    -    while (endNode != opt_stopNode &&
    -           startOffset == 0 &&
    -           endOffset == goog.editor.node.getLength(endNode)) {
    -      // Select the parent instead.
    -      var parentNode = endNode.parentNode;
    -      startOffset = goog.array.indexOf(parentNode.childNodes, endNode);
    -      endOffset = startOffset + 1;
    -      endNode = parentNode;
    -    }
    -    startNode = endNode;
    -  }
    -
    -  return goog.dom.Range.createFromNodes(startNode, startOffset,
    -      endNode, endOffset);
    -};
    -
    -
    -/**
    - * Given a range, expands the start or end points as far out towards the
    - * range's common container (or stopNode, if provided) as possible, while
    - * perserving the same visible position.
    - *
    - * @param {goog.dom.AbstractRange} range The range to expand.
    - * @param {goog.dom.RangeEndpoint} endpoint The endpoint to expand.
    - * @param {Node=} opt_stopNode Optional node to stop expanding past.
    - * @return {!goog.dom.AbstractRange} The expanded range.
    - * @private
    - */
    -goog.editor.range.expandEndPointToContainer_ = function(range, endpoint,
    -                                                        opt_stopNode) {
    -  var expandStart = endpoint == goog.dom.RangeEndpoint.START;
    -  var node = expandStart ? range.getStartNode() : range.getEndNode();
    -  var offset = expandStart ? range.getStartOffset() : range.getEndOffset();
    -  var container = range.getContainerElement();
    -
    -  // Expand the node out until we reach the container or the stop node.
    -  while (node != container && node != opt_stopNode) {
    -    // It is only valid to expand the start if we are at the start of a node
    -    // (offset 0) or expand the end if we are at the end of a node
    -    // (offset length).
    -    if (expandStart && offset != 0 ||
    -        !expandStart && offset != goog.editor.node.getLength(node)) {
    -      break;
    -    }
    -
    -    var parentNode = node.parentNode;
    -    var index = goog.array.indexOf(parentNode.childNodes, node);
    -    offset = expandStart ? index : index + 1;
    -    node = parentNode;
    -  }
    -
    -  return goog.dom.Range.createFromNodes(
    -      expandStart ? node : range.getStartNode(),
    -      expandStart ? offset : range.getStartOffset(),
    -      expandStart ? range.getEndNode() : node,
    -      expandStart ? range.getEndOffset() : offset);
    -};
    -
    -
    -/**
    - * Cause the window's selection to be the start of this node.
    - * @param {Node} node The node to select the start of.
    - */
    -goog.editor.range.selectNodeStart = function(node) {
    -  goog.dom.Range.createCaret(goog.editor.node.getLeftMostLeaf(node), 0).
    -      select();
    -};
    -
    -
    -/**
    - * Position the cursor immediately to the left or right of "node".
    - * In Firefox, the selection parent is outside of "node", so the cursor can
    - * effectively be moved to the end of a link node, without being considered
    - * inside of it.
    - * Note: This does not always work in WebKit. In particular, if you try to
    - * place a cursor to the right of a link, typing still puts you in the link.
    - * Bug: http://bugs.webkit.org/show_bug.cgi?id=17697
    - * @param {Node} node The node to position the cursor relative to.
    - * @param {boolean} toLeft True to place it to the left, false to the right.
    - * @return {!goog.dom.AbstractRange} The newly selected range.
    - */
    -goog.editor.range.placeCursorNextTo = function(node, toLeft) {
    -  var parent = node.parentNode;
    -  var offset = goog.array.indexOf(parent.childNodes, node) +
    -      (toLeft ? 0 : 1);
    -  var point = goog.editor.range.Point.createDeepestPoint(
    -      parent, offset, toLeft, true);
    -  var range = goog.dom.Range.createCaret(point.node, point.offset);
    -  range.select();
    -  return range;
    -};
    -
    -
    -/**
    - * Normalizes the node, preserving the selection of the document.
    - *
    - * May also normalize things outside the node, if it is more efficient to do so.
    - *
    - * @param {Node} node The node to normalize.
    - */
    -goog.editor.range.selectionPreservingNormalize = function(node) {
    -  var doc = goog.dom.getOwnerDocument(node);
    -  var selection = goog.dom.Range.createFromWindow(goog.dom.getWindow(doc));
    -  var normalizedRange =
    -      goog.editor.range.rangePreservingNormalize(node, selection);
    -  if (normalizedRange) {
    -    normalizedRange.select();
    -  }
    -};
    -
    -
    -/**
    - * Manually normalizes the node in IE, since native normalize in IE causes
    - * transient problems.
    - * @param {Node} node The node to normalize.
    - * @private
    - */
    -goog.editor.range.normalizeNodeIe_ = function(node) {
    -  var lastText = null;
    -  var child = node.firstChild;
    -  while (child) {
    -    var next = child.nextSibling;
    -    if (child.nodeType == goog.dom.NodeType.TEXT) {
    -      if (child.nodeValue == '') {
    -        node.removeChild(child);
    -      } else if (lastText) {
    -        lastText.nodeValue += child.nodeValue;
    -        node.removeChild(child);
    -      } else {
    -        lastText = child;
    -      }
    -    } else {
    -      goog.editor.range.normalizeNodeIe_(child);
    -      lastText = null;
    -    }
    -    child = next;
    -  }
    -};
    -
    -
    -/**
    - * Normalizes the given node.
    - * @param {Node} node The node to normalize.
    - */
    -goog.editor.range.normalizeNode = function(node) {
    -  if (goog.userAgent.IE) {
    -    goog.editor.range.normalizeNodeIe_(node);
    -  } else {
    -    node.normalize();
    -  }
    -};
    -
    -
    -/**
    - * Normalizes the node, preserving a range of the document.
    - *
    - * May also normalize things outside the node, if it is more efficient to do so.
    - *
    - * @param {Node} node The node to normalize.
    - * @param {goog.dom.AbstractRange?} range The range to normalize.
    - * @return {goog.dom.AbstractRange?} The range, adjusted for normalization.
    - */
    -goog.editor.range.rangePreservingNormalize = function(node, range) {
    -  if (range) {
    -    var rangeFactory = goog.editor.range.normalize(range);
    -    // WebKit has broken selection affinity, so carets tend to jump out of the
    -    // beginning of inline elements. This means that if we're doing the
    -    // normalize as the result of a range that will later become the selection,
    -    // we might not normalize something in the range after it is read back from
    -    // the selection. We can't just normalize the parentNode here because WebKit
    -    // can move the selection range out of multiple inline parents.
    -    var container = goog.editor.style.getContainer(range.getContainerElement());
    -  }
    -
    -  if (container) {
    -    goog.editor.range.normalizeNode(
    -        goog.dom.findCommonAncestor(container, node));
    -  } else if (node) {
    -    goog.editor.range.normalizeNode(node);
    -  }
    -
    -  if (rangeFactory) {
    -    return rangeFactory();
    -  } else {
    -    return null;
    -  }
    -};
    -
    -
    -/**
    - * Get the deepest point in the DOM that's equivalent to the endpoint of the
    - * given range.
    - *
    - * @param {goog.dom.AbstractRange} range A range.
    - * @param {boolean} atStart True for the start point, false for the end point.
    - * @return {!goog.editor.range.Point} The end point, expressed as a node
    - *    and an offset.
    - */
    -goog.editor.range.getDeepEndPoint = function(range, atStart) {
    -  return atStart ?
    -      goog.editor.range.Point.createDeepestPoint(
    -          range.getStartNode(), range.getStartOffset()) :
    -      goog.editor.range.Point.createDeepestPoint(
    -          range.getEndNode(), range.getEndOffset());
    -};
    -
    -
    -/**
    - * Given a range in the current DOM, create a factory for a range that
    - * represents the same selection in a normalized DOM. The factory function
    - * should be invoked after the DOM is normalized.
    - *
    - * All browsers do a bad job preserving ranges across DOM normalization.
    - * The issue is best described in this 5-year-old bug report:
    - * https://bugzilla.mozilla.org/show_bug.cgi?id=191864
    - * For most applications, this isn't a problem. The browsers do a good job
    - * handling un-normalized text, so there's usually no reason to normalize.
    - *
    - * The exception to this rule is the rich text editing commands
    - * execCommand and queryCommandValue, which will fail often if there are
    - * un-normalized text nodes.
    - *
    - * The factory function creates new ranges so that we can normalize the DOM
    - * without problems. It must be created before any normalization happens,
    - * and invoked after normalization happens.
    - *
    - * @param {goog.dom.AbstractRange} range The range to normalize. It may
    - *    become invalid after body.normalize() is called.
    - * @return {function(): goog.dom.AbstractRange} A factory for a normalized
    - *    range. Should be called after body.normalize() is called.
    - */
    -goog.editor.range.normalize = function(range) {
    -  var isReversed = range.isReversed();
    -  var anchorPoint = goog.editor.range.normalizePoint_(
    -      goog.editor.range.getDeepEndPoint(range, !isReversed));
    -  var anchorParent = anchorPoint.getParentPoint();
    -  var anchorPreviousSibling = anchorPoint.node.previousSibling;
    -  if (anchorPoint.node.nodeType == goog.dom.NodeType.TEXT) {
    -    anchorPoint.node = null;
    -  }
    -
    -  var focusPoint = goog.editor.range.normalizePoint_(
    -      goog.editor.range.getDeepEndPoint(range, isReversed));
    -  var focusParent = focusPoint.getParentPoint();
    -  var focusPreviousSibling = focusPoint.node.previousSibling;
    -  if (focusPoint.node.nodeType == goog.dom.NodeType.TEXT) {
    -    focusPoint.node = null;
    -  }
    -
    -  return function() {
    -    if (!anchorPoint.node && anchorPreviousSibling) {
    -      // If anchorPoint.node was previously an empty text node with no siblings,
    -      // anchorPreviousSibling may not have a nextSibling since that node will
    -      // no longer exist.  Do our best and point to the end of the previous
    -      // element.
    -      anchorPoint.node = anchorPreviousSibling.nextSibling;
    -      if (!anchorPoint.node) {
    -        anchorPoint = goog.editor.range.Point.getPointAtEndOfNode(
    -            anchorPreviousSibling);
    -      }
    -    }
    -
    -    if (!focusPoint.node && focusPreviousSibling) {
    -      // If focusPoint.node was previously an empty text node with no siblings,
    -      // focusPreviousSibling may not have a nextSibling since that node will no
    -      // longer exist.  Do our best and point to the end of the previous
    -      // element.
    -      focusPoint.node = focusPreviousSibling.nextSibling;
    -      if (!focusPoint.node) {
    -        focusPoint = goog.editor.range.Point.getPointAtEndOfNode(
    -            focusPreviousSibling);
    -      }
    -    }
    -
    -    return goog.dom.Range.createFromNodes(
    -        anchorPoint.node || anchorParent.node.firstChild || anchorParent.node,
    -        anchorPoint.offset,
    -        focusPoint.node || focusParent.node.firstChild || focusParent.node,
    -        focusPoint.offset);
    -  };
    -};
    -
    -
    -/**
    - * Given a point in the current DOM, adjust it to represent the same point in
    - * a normalized DOM.
    - *
    - * See the comments on goog.editor.range.normalize for more context.
    - *
    - * @param {goog.editor.range.Point} point A point in the document.
    - * @return {!goog.editor.range.Point} The same point, for easy chaining.
    - * @private
    - */
    -goog.editor.range.normalizePoint_ = function(point) {
    -  var previous;
    -  if (point.node.nodeType == goog.dom.NodeType.TEXT) {
    -    // If the cursor position is in a text node,
    -    // look at all the previous text siblings of the text node,
    -    // and set the offset relative to the earliest text sibling.
    -    for (var current = point.node.previousSibling;
    -         current && current.nodeType == goog.dom.NodeType.TEXT;
    -         current = current.previousSibling) {
    -      point.offset += goog.editor.node.getLength(current);
    -    }
    -
    -    previous = current;
    -  } else {
    -    previous = point.node.previousSibling;
    -  }
    -
    -  var parent = point.node.parentNode;
    -  point.node = previous ? previous.nextSibling : parent.firstChild;
    -  return point;
    -};
    -
    -
    -/**
    - * Checks if a range is completely inside an editable region.
    - * @param {goog.dom.AbstractRange} range The range to test.
    - * @return {boolean} Whether the range is completely inside an editable region.
    - */
    -goog.editor.range.isEditable = function(range) {
    -  var rangeContainer = range.getContainerElement();
    -
    -  // Closure's implementation of getContainerElement() is a little too
    -  // smart in IE when exactly one element is contained in the range.
    -  // It assumes that there's a user whose intent was actually to select
    -  // all that element's children, so it returns the element itself as its
    -  // own containing element.
    -  // This little sanity check detects this condition so we can account for it.
    -  var rangeContainerIsOutsideRange =
    -      range.getStartNode() != rangeContainer.parentElement;
    -
    -  return (rangeContainerIsOutsideRange &&
    -          goog.editor.node.isEditableContainer(rangeContainer)) ||
    -      goog.editor.node.isEditable(rangeContainer);
    -};
    -
    -
    -/**
    - * Returns whether the given range intersects with any instance of the given
    - * tag.
    - * @param {goog.dom.AbstractRange} range The range to check.
    - * @param {goog.dom.TagName} tagName The name of the tag.
    - * @return {boolean} Whether the given range intersects with any instance of
    - *     the given tag.
    - */
    -goog.editor.range.intersectsTag = function(range, tagName) {
    -  if (goog.dom.getAncestorByTagNameAndClass(range.getContainerElement(),
    -                                            tagName)) {
    -    return true;
    -  }
    -
    -  return goog.iter.some(range, function(node) {
    -    return node.tagName == tagName;
    -  });
    -};
    -
    -
    -
    -/**
    - * One endpoint of a range, represented as a Node and and offset.
    - * @param {Node} node The node containing the point.
    - * @param {number} offset The offset of the point into the node.
    - * @constructor
    - * @final
    - */
    -goog.editor.range.Point = function(node, offset) {
    -  /**
    -   * The node containing the point.
    -   * @type {Node}
    -   */
    -  this.node = node;
    -
    -  /**
    -   * The offset of the point into the node.
    -   * @type {number}
    -   */
    -  this.offset = offset;
    -};
    -
    -
    -/**
    - * Gets the point of this point's node in the DOM.
    - * @return {!goog.editor.range.Point} The node's point.
    - */
    -goog.editor.range.Point.prototype.getParentPoint = function() {
    -  var parent = this.node.parentNode;
    -  return new goog.editor.range.Point(
    -      parent, goog.array.indexOf(parent.childNodes, this.node));
    -};
    -
    -
    -/**
    - * Construct the deepest possible point in the DOM that's equivalent
    - * to the given point, expressed as a node and an offset.
    - * @param {Node} node The node containing the point.
    - * @param {number} offset The offset of the point from the node.
    - * @param {boolean=} opt_trendLeft Notice that a (node, offset) pair may be
    - *     equivalent to more than one descendent (node, offset) pair in the DOM.
    - *     By default, we trend rightward. If this parameter is true, then we
    - *     trend leftward. The tendency to fall rightward by default is for
    - *     consistency with other range APIs (like placeCursorNextTo).
    - * @param {boolean=} opt_stopOnChildlessElement If true, and we encounter
    - *     a Node which is an Element that cannot have children, we return a Point
    - *     based on its parent rather than that Node itself.
    - * @return {!goog.editor.range.Point} A new point.
    - */
    -goog.editor.range.Point.createDeepestPoint =
    -    function(node, offset, opt_trendLeft, opt_stopOnChildlessElement) {
    -  while (node.nodeType == goog.dom.NodeType.ELEMENT) {
    -    var child = node.childNodes[offset];
    -    if (!child && !node.lastChild) {
    -      break;
    -    } else if (child) {
    -      var prevSibling = child.previousSibling;
    -      if (opt_trendLeft && prevSibling) {
    -        if (opt_stopOnChildlessElement &&
    -            goog.editor.range.Point.isTerminalElement_(prevSibling)) {
    -          break;
    -        }
    -        node = prevSibling;
    -        offset = goog.editor.node.getLength(node);
    -      } else {
    -        if (opt_stopOnChildlessElement &&
    -            goog.editor.range.Point.isTerminalElement_(child)) {
    -          break;
    -        }
    -        node = child;
    -        offset = 0;
    -      }
    -    } else {
    -      if (opt_stopOnChildlessElement &&
    -          goog.editor.range.Point.isTerminalElement_(node.lastChild)) {
    -        break;
    -      }
    -      node = node.lastChild;
    -      offset = goog.editor.node.getLength(node);
    -    }
    -  }
    -
    -  return new goog.editor.range.Point(node, offset);
    -};
    -
    -
    -/**
    - * Return true if the specified node is an Element that is not expected to have
    - * children. The createDeepestPoint() method should not traverse into
    - * such elements.
    - * @param {Node} node .
    - * @return {boolean} True if the node is an Element that does not contain
    - *     child nodes (e.g. BR, IMG).
    - * @private
    - */
    -goog.editor.range.Point.isTerminalElement_ = function(node) {
    -  return (node.nodeType == goog.dom.NodeType.ELEMENT &&
    -          !goog.dom.canHaveChildren(node));
    -};
    -
    -
    -/**
    - * Construct a point at the very end of the given node.
    - * @param {Node} node The node to create a point for.
    - * @return {!goog.editor.range.Point} A new point.
    - */
    -goog.editor.range.Point.getPointAtEndOfNode = function(node) {
    -  return new goog.editor.range.Point(node, goog.editor.node.getLength(node));
    -};
    -
    -
    -/**
    - * Saves the range by inserting carets into the HTML.
    - *
    - * Unlike the regular saveUsingCarets, this SavedRange normalizes text nodes.
    - * Browsers have other bugs where they don't handle split text nodes in
    - * contentEditable regions right.
    - *
    - * @param {goog.dom.AbstractRange} range The abstract range object.
    - * @return {!goog.dom.SavedCaretRange} A saved caret range that normalizes
    - *     text nodes.
    - */
    -goog.editor.range.saveUsingNormalizedCarets = function(range) {
    -  return new goog.editor.range.NormalizedCaretRange_(range);
    -};
    -
    -
    -
    -/**
    - * Saves the range using carets, but normalizes text nodes when carets
    - * are removed.
    - * @see goog.editor.range.saveUsingNormalizedCarets
    - * @param {goog.dom.AbstractRange} range The range being saved.
    - * @constructor
    - * @extends {goog.dom.SavedCaretRange}
    - * @private
    - */
    -goog.editor.range.NormalizedCaretRange_ = function(range) {
    -  goog.dom.SavedCaretRange.call(this, range);
    -};
    -goog.inherits(goog.editor.range.NormalizedCaretRange_,
    -    goog.dom.SavedCaretRange);
    -
    -
    -/**
    - * Normalizes text nodes whenever carets are removed from the document.
    - * @param {goog.dom.AbstractRange=} opt_range A range whose offsets have already
    - *     been adjusted for caret removal; it will be adjusted and returned if it
    - *     is also affected by post-removal operations, such as text node
    - *     normalization.
    - * @return {goog.dom.AbstractRange|undefined} The adjusted range, if opt_range
    - *     was provided.
    - * @override
    - */
    -goog.editor.range.NormalizedCaretRange_.prototype.removeCarets =
    -    function(opt_range) {
    -  var startCaret = this.getCaret(true);
    -  var endCaret = this.getCaret(false);
    -  var node = startCaret && endCaret ?
    -      goog.dom.findCommonAncestor(startCaret, endCaret) :
    -      startCaret || endCaret;
    -
    -  goog.editor.range.NormalizedCaretRange_.superClass_.removeCarets.call(this);
    -
    -  if (opt_range) {
    -    return goog.editor.range.rangePreservingNormalize(node, opt_range);
    -  } else if (node) {
    -    goog.editor.range.selectionPreservingNormalize(node);
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/range_test.html b/src/database/third_party/closure-library/closure/goog/editor/range_test.html
    deleted file mode 100644
    index 6a004adecaa..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/range_test.html
    +++ /dev/null
    @@ -1,92 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -
    -  @author nicksantos@google.com (Nick Santos)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.editor.range
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -  goog.require('goog.editor.rangeTest');
    -  </script>
    - </head>
    - <body>
    -  <div id='root'>
    -  <div id='parentNode'>
    -    abc
    -    <div id='def'>def</div>
    -    ghi
    -    <div id='jkl'>jkl</div>
    -    mno
    -    <div id='pqr'>pqr</div>
    -    stu
    -  </div>
    -
    -  <div id='caretRangeTest-1'>
    -    abc
    -    <div id='def-1'>def</div>
    -    ghi
    -    <div id='jkl-1'>jkl</div>
    -    mno
    -    <div id='pqr-1'>pqr</div>
    -    stu
    -  </div>
    -
    -  <div id='normalizeTest-with-br'>abc<br/>def</div>
    -  <div id='normalizeTest-with-div'><div>abc</div></div>
    -  <div id='normalizeTest-with-empty-text-nodes'></div>
    -
    -  <div id='normalizeTest-2'>
    -    abc
    -    <div id='def-2'>def</div>
    -    ghi
    -    <div id='jkl-2'>jkl</div>
    -    mno
    -    <div id='pqr-2'>pqr</div>
    -    stu
    -  </div>
    -
    -  <div id='normalizeTest-3'>
    -    abc
    -    <div id='def-3'>def</div>
    -    ghi
    -    <div id='jkl-3'>jkl</div>
    -    mno
    -    <div id='pqr-3'>pqr</div>
    -    stu
    -  </div>
    -
    -  <div id='normalizeTest-4'>
    -    abc
    -    <div id='def-4'>def</div>
    -    ghi
    -    <div id='jkl-4'>jkl</div>
    -    mno
    -    <div id='pqr-4'>pqr</div>
    -    stu
    -  </div>
    -
    -  <div id='editableTest' g_editable='true'>
    -    abc
    -    <div>def</div>
    -    ghi
    -    <div>jkl</div>
    -    mno
    -    <div>pqr</div>
    -    stu
    -  </div>
    -
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/range_test.js b/src/database/third_party/closure-library/closure/goog/editor/range_test.js
    deleted file mode 100644
    index e365997a98c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/range_test.js
    +++ /dev/null
    @@ -1,942 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.editor.rangeTest');
    -goog.setTestOnly('goog.editor.rangeTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.Range');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.editor.range');
    -goog.require('goog.editor.range.Point');
    -goog.require('goog.string');
    -goog.require('goog.testing.dom');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -var savedHtml;
    -var $;
    -
    -function setUpPage() {
    -  $ = goog.dom.getElement;
    -}
    -
    -function setUp() {
    -  savedHtml = $('root').innerHTML;
    -}
    -
    -function tearDown() {
    -  $('root').innerHTML = savedHtml;
    -}
    -
    -function testNoNarrow() {
    -  var def = $('def');
    -  var jkl = $('jkl');
    -  var range = goog.dom.Range.createFromNodes(
    -      def.firstChild, 1, jkl.firstChild, 2);
    -
    -  range = goog.editor.range.narrow(range, $('parentNode'));
    -  goog.testing.dom.assertRangeEquals(
    -      def.firstChild, 1, jkl.firstChild, 2, range);
    -}
    -
    -function testNarrowAtEndEdge() {
    -  var def = $('def');
    -  var jkl = $('jkl');
    -  var range = goog.dom.Range.createFromNodes(
    -      def.firstChild, 1, jkl.firstChild, 2);
    -
    -  range = goog.editor.range.narrow(range, def);
    -  goog.testing.dom.assertRangeEquals(
    -      def.firstChild, 1, def.firstChild, 3, range);
    -}
    -
    -function testNarrowAtStartEdge() {
    -  var def = $('def');
    -  var jkl = $('jkl');
    -  var range = goog.dom.Range.createFromNodes(
    -      def.firstChild, 1, jkl.firstChild, 2);
    -
    -  range = goog.editor.range.narrow(range, jkl);
    -
    -  goog.testing.dom.assertRangeEquals(
    -      jkl.firstChild, 0, jkl.firstChild, 2, range);
    -}
    -
    -function testNarrowOutsideElement() {
    -  var def = $('def');
    -  var jkl = $('jkl');
    -  var range = goog.dom.Range.createFromNodes(
    -      def.firstChild, 1, jkl.firstChild, 2);
    -
    -  range = goog.editor.range.narrow(range, $('pqr'));
    -  assertNull(range);
    -}
    -
    -function testNoExpand() {
    -  var div = $('parentNode');
    -  div.innerHTML = '<div>longword</div>';
    -  // Select "ongwo" and make sure we don't expand since this is not
    -  // a full container.
    -  var textNode = div.firstChild.firstChild;
    -  var range = goog.dom.Range.createFromNodes(textNode, 1, textNode, 6);
    -
    -  range = goog.editor.range.expand(range);
    -  goog.testing.dom.assertRangeEquals(textNode, 1, textNode, 6, range);
    -}
    -
    -function testSimpleExpand() {
    -  var div = $('parentNode');
    -  div.innerHTML = '<div>longword</div>foo';
    -  // Select "longword" and make sure we do expand to include the div since
    -  // the full container text is selected.
    -  var textNode = div.firstChild.firstChild;
    -  var range = goog.dom.Range.createFromNodes(textNode, 0, textNode, 8);
    -
    -  range = goog.editor.range.expand(range);
    -  goog.testing.dom.assertRangeEquals(div, 0, div, 1, range);
    -
    -  // Select "foo" and make sure we expand out to the parent div.
    -  var fooNode = div.lastChild;
    -  range = goog.dom.Range.createFromNodes(fooNode, 0, fooNode, 3);
    -
    -  range = goog.editor.range.expand(range);
    -  goog.testing.dom.assertRangeEquals(div, 1, div, 2, range);
    -}
    -
    -function testDoubleExpand() {
    -  var div = $('parentNode');
    -  div.innerHTML = '<div><span>longword</span></div>foo';
    -  // Select "longword" and make sure we do expand to include the span
    -  // and the div since both of their full contents are selected.
    -  var textNode = div.firstChild.firstChild.firstChild;
    -  var range = goog.dom.Range.createFromNodes(textNode, 0, textNode, 8);
    -
    -  range = goog.editor.range.expand(range);
    -  goog.testing.dom.assertRangeEquals(div, 0, div, 1, range);
    -
    -  // Same visible position, different dom position.
    -  // Start in text node, end in span.
    -  range = goog.dom.Range.createFromNodes(textNode, 0, textNode.parentNode, 1);
    -
    -  range = goog.editor.range.expand(range);
    -  goog.testing.dom.assertRangeEquals(div, 0, div, 1, range);
    -}
    -
    -function testMultipleChildrenExpand() {
    -  var div = $('parentNode');
    -  div.innerHTML = '<ol><li>one</li><li>two</li><li>three</li></ol>';
    -  // Select "two" and make sure we expand to the li, but not the ol.
    -  var li = div.firstChild.childNodes[1];
    -  var textNode = li.firstChild;
    -  var range = goog.dom.Range.createFromNodes(textNode, 0, textNode, 3);
    -
    -  range = goog.editor.range.expand(range);
    -  goog.testing.dom.assertRangeEquals(
    -      li.parentNode, 1, li.parentNode, 2, range);
    -
    -  // Make the same visible selection, only slightly different dom position.
    -  // Select starting from the text node, but ending in the li.
    -  range = goog.dom.Range.createFromNodes(textNode, 0, li, 1);
    -
    -  range = goog.editor.range.expand(range);
    -  goog.testing.dom.assertRangeEquals(
    -      li.parentNode, 1, li.parentNode, 2, range);
    -}
    -
    -function testSimpleDifferentContainersExpand() {
    -  var div = $('parentNode');
    -  div.innerHTML = '<ol><li>1</li><li><b>bold</b><i>italic</i></li></ol>';
    -  // Select all of "bold" and "italic" at the text node level, and
    -  // make sure we expand to the li.
    -  var li = div.firstChild.childNodes[1];
    -  var boldNode = li.childNodes[0];
    -  var italicNode = li.childNodes[1];
    -  var range = goog.dom.Range.createFromNodes(boldNode.firstChild, 0,
    -      italicNode.firstChild, 6);
    -
    -  range = goog.editor.range.expand(range);
    -  goog.testing.dom.assertRangeEquals(
    -      li.parentNode, 1, li.parentNode, 2, range);
    -
    -  // Make the same visible selection, only slightly different dom position.
    -  // Select "bold" at the b node level and "italic" at the text node level.
    -  range = goog.dom.Range.createFromNodes(boldNode, 0,
    -      italicNode.firstChild, 6);
    -
    -  range = goog.editor.range.expand(range);
    -  goog.testing.dom.assertRangeEquals(
    -      li.parentNode, 1, li.parentNode, 2, range);
    -}
    -
    -function testSimpleDifferentContainersSmallExpand() {
    -  var div = $('parentNode');
    -  div.innerHTML = '<ol><li>1</li><li><b>bold</b><i>italic</i>' +
    -      '<u>under</u></li></ol>';
    -  // Select all of "bold" and "italic", but we can't expand to the
    -  // entire li since we didn't select "under".
    -  var li = div.firstChild.childNodes[1];
    -  var boldNode = li.childNodes[0];
    -  var italicNode = li.childNodes[1];
    -  var range = goog.dom.Range.createFromNodes(boldNode.firstChild, 0,
    -      italicNode.firstChild, 6);
    -
    -  range = goog.editor.range.expand(range);
    -  goog.testing.dom.assertRangeEquals(li, 0, li, 2, range);
    -
    -  // Same visible position, different dom position.
    -  // Select "bold" starting in text node, "italic" at i node.
    -  range = goog.dom.Range.createFromNodes(boldNode.firstChild, 0,
    -      italicNode, 1);
    -
    -  range = goog.editor.range.expand(range);
    -  goog.testing.dom.assertRangeEquals(li, 0, li, 2, range);
    -}
    -
    -function testEmbeddedDifferentContainersExpand() {
    -  var div = $('parentNode');
    -  div.innerHTML = '<div><b><i>italic</i>after</b><u>under</u></div>foo';
    -  // Select "italic" "after" "under", should expand all the way to parent.
    -  var boldNode = div.firstChild.childNodes[0];
    -  var italicNode = boldNode.childNodes[0];
    -  var underNode = div.firstChild.childNodes[1];
    -  var range = goog.dom.Range.createFromNodes(italicNode.firstChild, 0,
    -      underNode.firstChild, 5);
    -
    -  range = goog.editor.range.expand(range);
    -  goog.testing.dom.assertRangeEquals(div, 0, div, 1, range);
    -}
    -
    -function testReverseSimpleExpand() {
    -  var div = $('parentNode');
    -  div.innerHTML = '<div>longword</div>foo';
    -  // Select "longword" and make sure we do expand to include the div since
    -  // the full container text is selected.
    -  var textNode = div.firstChild.firstChild;
    -  var range = goog.dom.Range.createFromNodes(textNode, 8, textNode, 0);
    -
    -  range = goog.editor.range.expand(range);
    -
    -  goog.testing.dom.assertRangeEquals(div, 0, div, 1, range);
    -}
    -
    -function testExpandWithStopNode() {
    -  var div = $('parentNode');
    -  div.innerHTML = '<div><span>word</span></div>foo';
    -  // Select "word".
    -  var span = div.firstChild.firstChild;
    -  var textNode = span.firstChild;
    -  var range = goog.dom.Range.createFromNodes(textNode, 0, textNode, 4);
    -
    -  range = goog.editor.range.expand(range);
    -
    -  goog.testing.dom.assertRangeEquals(div, 0, div, 1, range);
    -
    -  // Same selection, but force stop at the span.
    -  range = goog.dom.Range.createFromNodes(textNode, 0, textNode, 4);
    -
    -  range = goog.editor.range.expand(range, span);
    -
    -  goog.testing.dom.assertRangeEquals(span, 0, span, 1, range);
    -}
    -
    -// Ojan didn't believe this code worked, this was the case he
    -// thought was broken.  Keeping just as a regression test.
    -function testOjanCase() {
    -  var div = $('parentNode');
    -  div.innerHTML = '<em><i><b>foo</b>bar</i></em>';
    -  // Select "foo", at text node level.
    -  var iNode = div.firstChild.firstChild;
    -  var textNode = iNode.firstChild.firstChild;
    -  var range = goog.dom.Range.createFromNodes(textNode, 0, textNode, 3);
    -
    -  range = goog.editor.range.expand(range);
    -
    -  goog.testing.dom.assertRangeEquals(iNode, 0, iNode, 1, range);
    -
    -  // Same selection, at b node level.
    -  range = goog.dom.Range.createFromNodes(iNode.firstChild, 0,
    -      iNode.firstChild, 1);
    -  range = goog.editor.range.expand(range);
    -
    -  goog.testing.dom.assertRangeEquals(iNode, 0, iNode, 1, range);
    -}
    -
    -function testPlaceCursorNextToLeft() {
    -  var div = $('parentNode');
    -  div.innerHTML = 'foo<div id="bar">bar</div>baz';
    -  var node = $('bar');
    -  var range = goog.editor.range.placeCursorNextTo(node, true);
    -
    -  var expose = goog.testing.dom.exposeNode;
    -  assertEquals('Selection should be to the left of the node ' +
    -      expose(node) + ',' + expose(range.getStartNode().nextSibling),
    -      node, range.getStartNode().nextSibling);
    -  assertEquals('Selection should be collapsed',
    -      true, range.isCollapsed());
    -}
    -
    -
    -function testPlaceCursorNextToRight() {
    -  var div = $('parentNode');
    -  div.innerHTML = 'foo<div id="bar">bar</div>baz';
    -  var node = $('bar');
    -  var range = goog.editor.range.placeCursorNextTo(node, false);
    -
    -  assertEquals('Selection should be to the right of the node',
    -      node, range.getStartNode().previousSibling);
    -  assertEquals('Selection should be collapsed',
    -      true, range.isCollapsed());
    -}
    -
    -function testPlaceCursorNextTo_rightOfLineBreak() {
    -  var div = $('parentNode');
    -  div.innerHTML = '<div contentEditable="true">hhhh<br />h</div>';
    -  var children = div.firstChild.childNodes;
    -  assertEquals(3, children.length);
    -  var node = children[1];
    -  var range = goog.editor.range.placeCursorNextTo(node, false);
    -  assertEquals(node.nextSibling, range.getStartNode());
    -}
    -
    -function testPlaceCursorNextTo_leftOfHr() {
    -  var div = $('parentNode');
    -  div.innerHTML = '<hr />aaa';
    -  var children = div.childNodes;
    -  assertEquals(2, children.length);
    -  var node = children[0];
    -  var range = goog.editor.range.placeCursorNextTo(node, true);
    -
    -  assertEquals(div, range.getStartNode());
    -  assertEquals(0, range.getStartOffset());
    -}
    -
    -function testPlaceCursorNextTo_rightOfHr() {
    -  var div = $('parentNode');
    -  div.innerHTML = 'aaa<hr>';
    -  var children = div.childNodes;
    -  assertEquals(2, children.length);
    -  var node = children[1];
    -  var range = goog.editor.range.placeCursorNextTo(node, false);
    -
    -  assertEquals(div, range.getStartNode());
    -  assertEquals(2, range.getStartOffset());
    -}
    -
    -function testPlaceCursorNextTo_rightOfImg() {
    -  var div = $('parentNode');
    -  div.innerHTML =
    -      'aaa<img src="https://www.google.com/images/srpr/logo3w.png">bbb';
    -  var children = div.childNodes;
    -  assertEquals(3, children.length);
    -  var imgNode = children[1];
    -  var range = goog.editor.range.placeCursorNextTo(imgNode, false);
    -
    -  assertEquals('range node should be the right sibling of img tag',
    -      children[2], range.getStartNode());
    -  assertEquals(0, range.getStartOffset());
    -
    -}
    -
    -function testPlaceCursorNextTo_rightOfImgAtEnd() {
    -  var div = $('parentNode');
    -  div.innerHTML =
    -      'aaa<img src="https://www.google.com/images/srpr/logo3w.png">';
    -  var children = div.childNodes;
    -  assertEquals(2, children.length);
    -  var imgNode = children[1];
    -  var range = goog.editor.range.placeCursorNextTo(imgNode, false);
    -
    -  assertEquals('range node should be the parent of img',
    -      div, range.getStartNode());
    -  assertEquals('offset should be right after the img tag',
    -      2, range.getStartOffset());
    -
    -}
    -
    -function testPlaceCursorNextTo_leftOfImg() {
    -  var div = $('parentNode');
    -  div.innerHTML =
    -      '<img src="https://www.google.com/images/srpr/logo3w.png">xxx';
    -  var children = div.childNodes;
    -  assertEquals(2, children.length);
    -  var imgNode = children[0];
    -  var range = goog.editor.range.placeCursorNextTo(imgNode, true);
    -
    -  assertEquals('range node should be the parent of img',
    -      div, range.getStartNode());
    -  assertEquals('offset should point to the img tag',
    -      0, range.getStartOffset());
    -}
    -
    -function testPlaceCursorNextTo_rightOfFirstOfTwoImgTags() {
    -  var div = $('parentNode');
    -  div.innerHTML =
    -      'aaa<img src="https://www.google.com/images/srpr/logo3w.png">' +
    -      '<img src="https://www.google.com/images/srpr/logo3w.png">';
    -  var children = div.childNodes;
    -  assertEquals(3, children.length);
    -  var imgNode = children[1];  // First of two IMG nodes
    -  var range = goog.editor.range.placeCursorNextTo(imgNode, false);
    -
    -  assertEquals('range node should be the parent of img instead of ' +
    -      'node with innerHTML=' + range.getStartNode().innerHTML,
    -      div, range.getStartNode());
    -  assertEquals('offset should be right after the img tag',
    -      2, range.getStartOffset());
    -}
    -
    -function testGetDeepEndPoint() {
    -  var div = $('parentNode');
    -  var def = $('def');
    -  var jkl = $('jkl');
    -
    -  assertPointEquals(div.firstChild, 0,
    -      goog.editor.range.getDeepEndPoint(
    -          goog.dom.Range.createFromNodeContents(div), true));
    -  assertPointEquals(div.lastChild, div.lastChild.length,
    -      goog.editor.range.getDeepEndPoint(
    -          goog.dom.Range.createFromNodeContents(div), false));
    -
    -  assertPointEquals(def.firstChild, 0,
    -      goog.editor.range.getDeepEndPoint(
    -          goog.dom.Range.createCaret(div, 1), true));
    -  assertPointEquals(def.nextSibling, 0,
    -      goog.editor.range.getDeepEndPoint(
    -          goog.dom.Range.createCaret(div, 2), true));
    -
    -}
    -
    -function testNormalizeOnNormalizedDom() {
    -  var defText = $('def').firstChild;
    -  var jklText = $('jkl').firstChild;
    -  var range = goog.dom.Range.createFromNodes(defText, 1, jklText, 2);
    -
    -  var newRange = normalizeBody(range);
    -  goog.testing.dom.assertRangeEquals(defText, 1, jklText, 2, newRange);
    -}
    -
    -function testDeepPointFindingOnNormalizedDom() {
    -  var def = $('def');
    -  var jkl = $('jkl');
    -  var range = goog.dom.Range.createFromNodes(def, 0, jkl, 1);
    -
    -  var newRange = normalizeBody(range);
    -
    -  // Make sure that newRange is measured relative to the text nodes,
    -  // not the DIV elements.
    -  goog.testing.dom.assertRangeEquals(
    -      def.firstChild, 0, jkl.firstChild, 3, newRange);
    -}
    -
    -function testNormalizeOnVeryFragmentedDom() {
    -  var defText = $('def').firstChild;
    -  var jklText = $('jkl').firstChild;
    -  var range = goog.dom.Range.createFromNodes(defText, 1, jklText, 2);
    -
    -  // Fragment the DOM a bunch.
    -  fragmentText(defText);
    -  fragmentText(jklText);
    -
    -  var newRange = normalizeBody(range);
    -
    -  // our old text nodes may not be valid anymore. find new ones.
    -  defText = $('def').firstChild;
    -  jklText = $('jkl').firstChild;
    -
    -  goog.testing.dom.assertRangeEquals(defText, 1, jklText, 2, newRange);
    -}
    -
    -function testNormalizeOnDivWithEmptyTextNodes() {
    -  var emptyDiv = $('normalizeTest-with-empty-text-nodes');
    -
    -  // Append empty text nodes to the emptyDiv.
    -  var tnode1 = goog.dom.createTextNode('');
    -  var tnode2 = goog.dom.createTextNode('');
    -  var tnode3 = goog.dom.createTextNode('');
    -
    -  goog.dom.appendChild(emptyDiv, tnode1);
    -  goog.dom.appendChild(emptyDiv, tnode2);
    -  goog.dom.appendChild(emptyDiv, tnode3);
    -
    -  var range = goog.dom.Range.createFromNodes(emptyDiv, 1, emptyDiv, 2);
    -
    -  // Cannot use document.body.normalize() as it fails to normalize the div
    -  // (in IE) if it has nothing but empty text nodes.
    -  var newRange = goog.editor.range.rangePreservingNormalize(emptyDiv, range);
    -
    -  if (goog.userAgent.GECKO &&
    -      goog.string.compareVersions(goog.userAgent.VERSION, '1.9') == -1) {
    -    // In FF2, node.normalize() leaves an empty textNode in the div, unlike
    -    // other browsers where the div is left with no children.
    -    goog.testing.dom.assertRangeEquals(
    -        emptyDiv.firstChild, 0, emptyDiv.firstChild, 0, newRange);
    -  } else {
    -    goog.testing.dom.assertRangeEquals(emptyDiv, 0, emptyDiv, 0, newRange);
    -  }
    -}
    -
    -function testRangeCreatedInVeryFragmentedDom() {
    -  var def = $('def');
    -  var defText = def.firstChild;
    -  var jkl = $('jkl');
    -  var jklText = jkl.firstChild;
    -
    -  // Fragment the DOM a bunch.
    -  fragmentText(defText);
    -  fragmentText(jklText);
    -
    -  // Notice that there are two empty text nodes at the beginning of each
    -  // fragmented node.
    -  var range = goog.dom.Range.createFromNodes(def, 3, jkl, 4);
    -
    -  var newRange = normalizeBody(range);
    -
    -  // our old text nodes may not be valid anymore. find new ones.
    -  defText = $('def').firstChild;
    -  jklText = $('jkl').firstChild;
    -  goog.testing.dom.assertRangeEquals(defText, 1, jklText, 2, newRange);
    -}
    -
    -function testNormalizeInFragmentedDomWithPreviousSiblings() {
    -  var ghiText = $('def').nextSibling;
    -  var mnoText = $('jkl').nextSibling;
    -  var range = goog.dom.Range.createFromNodes(ghiText, 1, mnoText, 2);
    -
    -  // Fragment the DOM a bunch.
    -  fragmentText($('def').previousSibling); // fragment abc
    -  fragmentText(ghiText);
    -  fragmentText(mnoText);
    -
    -  var newRange = normalizeBody(range);
    -
    -  // our old text nodes may not be valid anymore. find new ones.
    -  ghiText = $('def').nextSibling;
    -  mnoText = $('jkl').nextSibling;
    -
    -  goog.testing.dom.assertRangeEquals(ghiText, 1, mnoText, 2, newRange);
    -}
    -
    -function testRangeCreatedInFragmentedDomWithPreviousSiblings() {
    -  var def = $('def');
    -  var ghiText = $('def').nextSibling;
    -  var jkl = $('jkl');
    -  var mnoText = $('jkl').nextSibling;
    -
    -  // Fragment the DOM a bunch.
    -  fragmentText($('def').previousSibling); // fragment abc
    -  fragmentText(ghiText);
    -  fragmentText(mnoText);
    -
    -  // Notice that there are two empty text nodes at the beginning of each
    -  // fragmented node.
    -  var root = $('parentNode');
    -  var range = goog.dom.Range.createFromNodes(root, 9, root, 16);
    -
    -  var newRange = normalizeBody(range);
    -
    -  // our old text nodes may not be valid anymore. find new ones.
    -  ghiText = $('def').nextSibling;
    -  mnoText = $('jkl').nextSibling;
    -  goog.testing.dom.assertRangeEquals(ghiText, 1, mnoText, 2, newRange);
    -}
    -
    -
    -/**
    - * Branched from the tests for goog.dom.SavedCaretRange.
    - */
    -function testSavedCaretRange() {
    -  var def = $('def-1');
    -  var jkl = $('jkl-1');
    -
    -  var range = goog.dom.Range.createFromNodes(
    -      def.firstChild, 1, jkl.firstChild, 2);
    -  range.select();
    -
    -  var saved = goog.editor.range.saveUsingNormalizedCarets(range);
    -  assertHTMLEquals(
    -      'd<span id="' + saved.startCaretId_ + '"></span>ef', def.innerHTML);
    -  assertHTMLEquals(
    -      'jk<span id="' + saved.endCaretId_ + '"></span>l', jkl.innerHTML);
    -
    -  clearSelectionAndRestoreSaved(saved);
    -
    -  var selection = goog.dom.Range.createFromWindow(window);
    -  def = $('def-1');
    -  jkl = $('jkl-1');
    -  assertHTMLEquals('def', def.innerHTML);
    -  assertHTMLEquals('jkl', jkl.innerHTML);
    -
    -  // Check that everything was normalized ok.
    -  assertEquals(1, def.childNodes.length);
    -  assertEquals(1, jkl.childNodes.length);
    -  goog.testing.dom.assertRangeEquals(
    -      def.firstChild, 1, jkl.firstChild, 2, selection);
    -}
    -
    -function testRangePreservingNormalize() {
    -  var parent = $('normalizeTest-4');
    -  var def = $('def-4');
    -  var jkl = $('jkl-4');
    -  fragmentText(def.firstChild);
    -  fragmentText(jkl.firstChild);
    -
    -  var range = goog.dom.Range.createFromNodes(def, 3, jkl, 4);
    -  var oldRangeDescription = goog.testing.dom.exposeRange(range);
    -  range = goog.editor.range.rangePreservingNormalize(parent, range);
    -
    -  // Check that everything was normalized ok.
    -  assertEquals('def should have 1 child; range is ' +
    -      goog.testing.dom.exposeRange(range) +
    -      ', range was ' + oldRangeDescription,
    -      1, def.childNodes.length);
    -  assertEquals('jkl should have 1 child; range is ' +
    -      goog.testing.dom.exposeRange(range) +
    -      ', range was ' + oldRangeDescription,
    -      1, jkl.childNodes.length);
    -  goog.testing.dom.assertRangeEquals(def.firstChild, 1, jkl.firstChild, 2,
    -                                     range);
    -}
    -
    -function testRangePreservingNormalizeWhereEndNodePreviousSiblingIsSplit() {
    -  var parent = $('normalizeTest-with-br');
    -  var br = parent.childNodes[1];
    -  fragmentText(parent.firstChild);
    -
    -  var range = goog.dom.Range.createFromNodes(parent, 3, br, 0);
    -  range = goog.editor.range.rangePreservingNormalize(parent, range);
    -
    -  // Code used to throw an error here.
    -
    -  assertEquals('parent should have 3 children', 3, parent.childNodes.length);
    -  goog.testing.dom.assertRangeEquals(parent.firstChild, 1, parent, 1, range);
    -}
    -
    -function testRangePreservingNormalizeWhereStartNodePreviousSiblingIsSplit() {
    -  var parent = $('normalizeTest-with-br');
    -  var br = parent.childNodes[1];
    -  fragmentText(parent.firstChild);
    -  fragmentText(parent.lastChild);
    -
    -  var range = goog.dom.Range.createFromNodes(br, 0, parent, 9);
    -  range = goog.editor.range.rangePreservingNormalize(parent, range);
    -
    -  // Code used to throw an error here.
    -
    -  assertEquals('parent should have 3 children', 3, parent.childNodes.length);
    -  goog.testing.dom.assertRangeEquals(parent, 1, parent.lastChild, 1, range);
    -}
    -
    -function testSelectionPreservingNormalize1() {
    -  var parent = $('normalizeTest-2');
    -  var def = $('def-2');
    -  var jkl = $('jkl-2');
    -  fragmentText(def.firstChild);
    -  fragmentText(jkl.firstChild);
    -
    -  goog.dom.Range.createFromNodes(def, 3, jkl, 4).select();
    -  assertFalse(goog.dom.Range.createFromWindow(window).isReversed());
    -
    -  var oldRangeDescription = goog.testing.dom.exposeRange(
    -      goog.dom.Range.createFromWindow(window));
    -  goog.editor.range.selectionPreservingNormalize(parent);
    -
    -  // Check that everything was normalized ok.
    -  var range = goog.dom.Range.createFromWindow(window);
    -  assertFalse(range.isReversed());
    -
    -  assertEquals('def should have 1 child; range is ' +
    -      goog.testing.dom.exposeRange(range) +
    -      ', range was ' + oldRangeDescription,
    -      1, def.childNodes.length);
    -  assertEquals('jkl should have 1 child; range is ' +
    -      goog.testing.dom.exposeRange(range) +
    -      ', range was ' + oldRangeDescription,
    -      1, jkl.childNodes.length);
    -  goog.testing.dom.assertRangeEquals(def.firstChild, 1, jkl.firstChild, 2,
    -      range);
    -}
    -
    -
    -/**
    - * Make sure that selectionPreservingNormalize doesn't explode with no
    - * selection in the document.
    - */
    -function testSelectionPreservingNormalize2() {
    -  var parent = $('normalizeTest-3');
    -  var def = $('def-3');
    -  var jkl = $('jkl-3');
    -  def.firstChild.splitText(1);
    -  jkl.firstChild.splitText(2);
    -
    -  goog.dom.Range.clearSelection(window);
    -  goog.editor.range.selectionPreservingNormalize(parent);
    -
    -  // Check that everything was normalized ok.
    -  assertEquals(1, def.childNodes.length);
    -  assertEquals(1, jkl.childNodes.length);
    -  assertFalse(goog.dom.Range.hasSelection(window));
    -}
    -
    -function testSelectionPreservingNormalize3() {
    -  if (goog.userAgent.IE) {
    -    return;
    -  }
    -  var parent = $('normalizeTest-2');
    -  var def = $('def-2');
    -  var jkl = $('jkl-2');
    -  fragmentText(def.firstChild);
    -  fragmentText(jkl.firstChild);
    -
    -  goog.dom.Range.createFromNodes(jkl, 4, def, 3).select();
    -  assertTrue(goog.dom.Range.createFromWindow(window).isReversed());
    -
    -  var oldRangeDescription = goog.testing.dom.exposeRange(
    -      goog.dom.Range.createFromWindow(window));
    -  goog.editor.range.selectionPreservingNormalize(parent);
    -
    -  // Check that everything was normalized ok.
    -  var range = goog.dom.Range.createFromWindow(window);
    -  assertTrue(range.isReversed());
    -
    -  assertEquals('def should have 1 child; range is ' +
    -      goog.testing.dom.exposeRange(range) +
    -      ', range was ' + oldRangeDescription,
    -      1, def.childNodes.length);
    -  assertEquals('jkl should have 1 child; range is ' +
    -      goog.testing.dom.exposeRange(range) +
    -      ', range was ' + oldRangeDescription,
    -      1, jkl.childNodes.length);
    -  goog.testing.dom.assertRangeEquals(def.firstChild, 1, jkl.firstChild, 2,
    -      range);
    -}
    -
    -function testSelectionPreservingNormalizeAfterPlaceCursorNextTo() {
    -  var parent = $('normalizeTest-with-div');
    -  goog.editor.range.placeCursorNextTo(parent.firstChild);
    -  goog.editor.range.selectionPreservingNormalize(parent);
    -
    -  // Code used to throw an exception here.
    -}
    -
    -
    -/** Normalize the body and return the normalized range. */
    -function normalizeBody(range) {
    -  var rangeFactory = goog.editor.range.normalize(range);
    -  document.body.normalize();
    -  return rangeFactory();
    -}
    -
    -
    -/** Break a text node up into lots of little fragments. */
    -function fragmentText(text) {
    -  // NOTE(nicksantos): For some reason, splitText makes IE deeply
    -  // unhappy to the point where normalize and other normal DOM operations
    -  // start failing. It's a useful test for Firefox though, because different
    -  // versions of FireFox handle empty text nodes differently.
    -  // See goog.editor.BrowserFeature.
    -  if (goog.userAgent.IE) {
    -    manualSplitText(text, 2);
    -    manualSplitText(text, 1);
    -    manualSplitText(text, 0);
    -    manualSplitText(text, 0);
    -  } else {
    -    text.splitText(2);
    -    text.splitText(1);
    -
    -    text.splitText(0);
    -    text.splitText(0);
    -  }
    -}
    -
    -
    -/**
    - * Clear the selection by re-parsing the DOM. Then restore the saved
    - * selection.
    - * @param {goog.dom.SavedRange} saved The saved range.
    - */
    -function clearSelectionAndRestoreSaved(saved) {
    -  goog.dom.Range.clearSelection(window);
    -  assertFalse(goog.dom.Range.hasSelection(window));
    -  saved.restore();
    -  assertTrue(goog.dom.Range.hasSelection(window));
    -}
    -
    -function manualSplitText(node, pos) {
    -  var newNodeString = node.nodeValue.substr(pos);
    -  node.nodeValue = node.nodeValue.substr(0, pos);
    -  goog.dom.insertSiblingAfter(document.createTextNode(newNodeString), node);
    -}
    -
    -function testSelectNodeStartSimple() {
    -  var div = $('parentNode');
    -  div.innerHTML = '<p>Cursor should go in here</p>';
    -
    -  goog.editor.range.selectNodeStart(div);
    -  var range = goog.dom.Range.createFromWindow(window);
    -  // Gotta love browsers and their inconsistencies with selection
    -  // representations.  What we are trying to achieve is that when we type
    -  // the text will go into the P node.  In Gecko, the selection is at the start
    -  // of the text node, as you'd expect, but in pre-530 Webkit, it has been
    -  // normalized to the visible position of P:0.
    -  if (goog.userAgent.GECKO || goog.userAgent.IE ||
    -      (goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher('530'))) {
    -    goog.testing.dom.assertRangeEquals(div.firstChild.firstChild, 0,
    -        div.firstChild.firstChild, 0, range);
    -  } else {
    -    goog.testing.dom.assertRangeEquals(div.firstChild, 0,
    -        div.firstChild, 0, range);
    -  }
    -}
    -
    -function testSelectNodeStartBr() {
    -  var div = $('parentNode');
    -  div.innerHTML = '<p><br>Cursor should go in here</p>';
    -
    -  goog.editor.range.selectNodeStart(div);
    -  var range = goog.dom.Range.createFromWindow(window);
    -  // We have to skip the BR since Gecko can't render a cursor at a BR.
    -  goog.testing.dom.assertRangeEquals(div.firstChild, 0,
    -      div.firstChild, 0, range);
    -}
    -
    -function testIsEditable() {
    -  var containerElement = document.getElementById('editableTest');
    -  // Find editable container element's index.
    -  var containerIndex = 0;
    -  var currentSibling = containerElement;
    -  while (currentSibling = currentSibling.previousSibling) {
    -    containerIndex++;
    -  }
    -
    -  var editableContainer = goog.dom.Range.createFromNodes(
    -      containerElement.parentNode, containerIndex,
    -      containerElement.parentNode, containerIndex + 1);
    -  assertFalse('Range containing container element not considered editable',
    -      goog.editor.range.isEditable(editableContainer));
    -
    -  var allEditableChildren = goog.dom.Range.createFromNodes(
    -      containerElement, 0, containerElement,
    -      containerElement.childNodes.length);
    -  assertTrue('Range of all of container element children considered editable',
    -      goog.editor.range.isEditable(allEditableChildren));
    -
    -  var someEditableChildren = goog.dom.Range.createFromNodes(
    -      containerElement, 2, containerElement, 6);
    -  assertTrue('Range of some container element children considered editable',
    -      goog.editor.range.isEditable(someEditableChildren));
    -
    -
    -  var mixedEditableNonEditable = goog.dom.Range.createFromNodes(
    -      containerElement.previousSibling, 0, containerElement, 2);
    -  assertFalse('Range overlapping some content not considered editable',
    -      goog.editor.range.isEditable(mixedEditableNonEditable));
    -}
    -
    -function testIntersectsTag() {
    -  var root = $('root');
    -  root.innerHTML =
    -      '<b>Bold</b><p><span><code>x</code></span></p><p>y</p><i>Italic</i>';
    -
    -  // Select the whole thing.
    -  var range = goog.dom.Range.createFromNodeContents(root);
    -  assertTrue(goog.editor.range.intersectsTag(range, goog.dom.TagName.DIV));
    -  assertTrue(goog.editor.range.intersectsTag(range, goog.dom.TagName.B));
    -  assertTrue(goog.editor.range.intersectsTag(range, goog.dom.TagName.I));
    -  assertTrue(goog.editor.range.intersectsTag(range, goog.dom.TagName.CODE));
    -  assertFalse(goog.editor.range.intersectsTag(range, goog.dom.TagName.U));
    -
    -  // Just select italic.
    -  range = goog.dom.Range.createFromNodes(root, 3, root, 4);
    -  assertTrue(goog.editor.range.intersectsTag(range, goog.dom.TagName.DIV));
    -  assertFalse(goog.editor.range.intersectsTag(range, goog.dom.TagName.B));
    -  assertTrue(goog.editor.range.intersectsTag(range, goog.dom.TagName.I));
    -  assertFalse(goog.editor.range.intersectsTag(range, goog.dom.TagName.CODE));
    -  assertFalse(goog.editor.range.intersectsTag(range, goog.dom.TagName.U));
    -
    -  // Select "ld x y".
    -  range = goog.dom.Range.createFromNodes(root.firstChild.firstChild, 2,
    -      root.childNodes[2], 1);
    -  assertTrue(goog.editor.range.intersectsTag(range, goog.dom.TagName.DIV));
    -  assertTrue(goog.editor.range.intersectsTag(range, goog.dom.TagName.B));
    -  assertFalse(goog.editor.range.intersectsTag(range, goog.dom.TagName.I));
    -  assertTrue(goog.editor.range.intersectsTag(range, goog.dom.TagName.CODE));
    -  assertFalse(goog.editor.range.intersectsTag(range, goog.dom.TagName.U));
    -
    -  // Select ol.
    -  range = goog.dom.Range.createFromNodes(root.firstChild.firstChild, 1,
    -      root.firstChild.firstChild, 3);
    -  assertTrue(goog.editor.range.intersectsTag(range, goog.dom.TagName.DIV));
    -  assertTrue(goog.editor.range.intersectsTag(range, goog.dom.TagName.B));
    -  assertFalse(goog.editor.range.intersectsTag(range, goog.dom.TagName.I));
    -  assertFalse(goog.editor.range.intersectsTag(range, goog.dom.TagName.CODE));
    -  assertFalse(goog.editor.range.intersectsTag(range, goog.dom.TagName.U));
    -}
    -
    -function testNormalizeNode() {
    -  var div = goog.dom.createDom('DIV', null, 'a', 'b', 'c');
    -  assertEquals(3, div.childNodes.length);
    -  goog.editor.range.normalizeNode(div);
    -  assertEquals(1, div.childNodes.length);
    -  assertEquals('abc', div.firstChild.nodeValue);
    -
    -  div = goog.dom.createDom('DIV', null,
    -      goog.dom.createDom('SPAN', null, '1', '2'),
    -      goog.dom.createTextNode(''),
    -      goog.dom.createDom('BR'),
    -      'b',
    -      'c');
    -  assertEquals(5, div.childNodes.length);
    -  assertEquals(2, div.firstChild.childNodes.length);
    -  goog.editor.range.normalizeNode(div);
    -  if (goog.userAgent.GECKO && !goog.userAgent.isVersionOrHigher(1.9) ||
    -      goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher(526)) {
    -    // Old Gecko and Webkit versions don't delete the empty node.
    -    assertEquals(4, div.childNodes.length);
    -  } else {
    -    assertEquals(3, div.childNodes.length);
    -  }
    -  assertEquals(1, div.firstChild.childNodes.length);
    -  assertEquals('12', div.firstChild.firstChild.nodeValue);
    -  assertEquals('bc', div.lastChild.nodeValue);
    -  assertEquals('BR', div.lastChild.previousSibling.tagName);
    -}
    -
    -function testDeepestPoint() {
    -  var parent = $('parentNode');
    -  var def = $('def');
    -
    -  assertEquals(def, parent.childNodes[1]);
    -
    -  var deepestPoint = goog.editor.range.Point.createDeepestPoint;
    -
    -  var defStartLeft = deepestPoint(parent, 1, true);
    -  assertPointEquals(def.previousSibling, def.previousSibling.nodeValue.length,
    -      defStartLeft);
    -
    -  var defStartRight = deepestPoint(parent, 1, false);
    -  assertPointEquals(def.firstChild, 0, defStartRight);
    -
    -  var defEndLeft = deepestPoint(parent, 2, true);
    -  assertPointEquals(def.firstChild, def.firstChild.nodeValue.length,
    -      defEndLeft);
    -
    -  var defEndRight = deepestPoint(parent, 2, false);
    -  assertPointEquals(def.nextSibling, 0, defEndRight);
    -}
    -
    -function assertPointEquals(node, offset, actualPoint) {
    -  assertEquals('Point has wrong node', node, actualPoint.node);
    -  assertEquals('Point has wrong offset', offset, actualPoint.offset);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/seamlessfield.js b/src/database/third_party/closure-library/closure/goog/editor/seamlessfield.js
    deleted file mode 100644
    index 14fbb1ea59a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/seamlessfield.js
    +++ /dev/null
    @@ -1,746 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Class to encapsulate an editable field that blends in with
    - * the style of the page. The field can be fixed height, grow with its
    - * contents, or have a min height after which it grows to its contents.
    - * This is a goog.editor.Field, but with blending and sizing capabilities,
    - * and avoids using an iframe whenever possible.
    - *
    - * @author nicksantos@google.com (Nick Santos)
    - * @see ../demos/editor/seamlessfield.html
    - */
    -
    -
    -goog.provide('goog.editor.SeamlessField');
    -
    -goog.require('goog.cssom.iframe.style');
    -goog.require('goog.dom');
    -goog.require('goog.dom.Range');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.dom.safe');
    -goog.require('goog.editor.BrowserFeature');
    -goog.require('goog.editor.Field');
    -goog.require('goog.editor.icontent');
    -goog.require('goog.editor.icontent.FieldFormatInfo');
    -goog.require('goog.editor.icontent.FieldStyleInfo');
    -goog.require('goog.editor.node');
    -goog.require('goog.events');
    -goog.require('goog.events.EventType');
    -goog.require('goog.html.uncheckedconversions');
    -goog.require('goog.log');
    -goog.require('goog.string.Const');
    -goog.require('goog.style');
    -
    -
    -
    -/**
    - * This class encapsulates an editable field that blends in with the
    - * surrounding page.
    - * To see events fired by this object, please see the base class.
    - *
    - * @param {string} id An identifer for the field. This is used to find the
    - *     field and the element associated with this field.
    - * @param {Document=} opt_doc The document that the element with the given
    - *     id can be found it.
    - * @constructor
    - * @extends {goog.editor.Field}
    - */
    -goog.editor.SeamlessField = function(id, opt_doc) {
    -  goog.editor.Field.call(this, id, opt_doc);
    -};
    -goog.inherits(goog.editor.SeamlessField, goog.editor.Field);
    -
    -
    -/**
    - * @override
    - */
    -goog.editor.SeamlessField.prototype.logger =
    -    goog.log.getLogger('goog.editor.SeamlessField');
    -
    -// Functions dealing with field sizing.
    -
    -
    -/**
    - * The key used for listening for the "dragover" event.
    - * @type {goog.events.Key}
    - * @private
    - */
    -goog.editor.SeamlessField.prototype.listenForDragOverEventKey_;
    -
    -
    -/**
    - * The key used for listening for the iframe "load" event.
    - * @type {goog.events.Key}
    - * @private
    - */
    -goog.editor.SeamlessField.prototype.listenForIframeLoadEventKey_;
    -
    -
    -/**
    - * Sets the min height of this editable field's iframe. Only used in growing
    - * mode when an iframe is used. This will cause an immediate field sizing to
    - * update the field if necessary based on the new min height.
    - * @param {number} height The min height specified as a number of pixels,
    - *    e.g., 75.
    - */
    -goog.editor.SeamlessField.prototype.setMinHeight = function(height) {
    -  if (height == this.minHeight_) {
    -    // Do nothing if the min height isn't changing.
    -    return;
    -  }
    -  this.minHeight_ = height;
    -  if (this.usesIframe()) {
    -    this.doFieldSizingGecko();
    -  }
    -};
    -
    -
    -/**
    - * Whether the field should be rendered with a fixed height, or should expand
    - * to fit its contents.
    - * @type {boolean}
    - * @private
    - */
    -goog.editor.SeamlessField.prototype.isFixedHeight_ = false;
    -
    -
    -/**
    - * Whether the fixed-height handling has been overridden manually.
    - * @type {boolean}
    - * @private
    - */
    -goog.editor.SeamlessField.prototype.isFixedHeightOverridden_ = false;
    -
    -
    -/**
    - * @return {boolean} Whether the field should be rendered with a fixed
    - *    height, or should expand to fit its contents.
    - * @override
    - */
    -goog.editor.SeamlessField.prototype.isFixedHeight = function() {
    -  return this.isFixedHeight_;
    -};
    -
    -
    -/**
    - * @param {boolean} newVal Explicitly set whether the field should be
    - *    of a fixed-height. This overrides auto-detection.
    - */
    -goog.editor.SeamlessField.prototype.overrideFixedHeight = function(newVal) {
    -  this.isFixedHeight_ = newVal;
    -  this.isFixedHeightOverridden_ = true;
    -};
    -
    -
    -/**
    - * Auto-detect whether the current field should have a fixed height.
    - * @private
    - */
    -goog.editor.SeamlessField.prototype.autoDetectFixedHeight_ = function() {
    -  if (!this.isFixedHeightOverridden_) {
    -    var originalElement = this.getOriginalElement();
    -    if (originalElement) {
    -      this.isFixedHeight_ =
    -          goog.style.getComputedOverflowY(originalElement) == 'auto';
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Resize the iframe in response to the wrapper div changing size.
    - * @private
    - */
    -goog.editor.SeamlessField.prototype.handleOuterDocChange_ = function() {
    -  if (this.isEventStopped(goog.editor.Field.EventType.CHANGE)) {
    -    return;
    -  }
    -  this.sizeIframeToWrapperGecko_();
    -};
    -
    -
    -/**
    - * Sizes the iframe to its body's height.
    - * @private
    - */
    -goog.editor.SeamlessField.prototype.sizeIframeToBodyHeightGecko_ = function() {
    -  if (this.acquireSizeIframeLockGecko_()) {
    -    var resized = false;
    -    var ifr = this.getEditableIframe();
    -    if (ifr) {
    -      var fieldHeight = this.getIframeBodyHeightGecko_();
    -
    -      if (this.minHeight_) {
    -        fieldHeight = Math.max(fieldHeight, this.minHeight_);
    -      }
    -      if (parseInt(goog.style.getStyle(ifr, 'height'), 10) != fieldHeight) {
    -        ifr.style.height = fieldHeight + 'px';
    -        resized = true;
    -      }
    -    }
    -    this.releaseSizeIframeLockGecko_();
    -    if (resized) {
    -      this.dispatchEvent(goog.editor.Field.EventType.IFRAME_RESIZED);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * @return {number} The height of the editable iframe's body.
    - * @private
    - */
    -goog.editor.SeamlessField.prototype.getIframeBodyHeightGecko_ = function() {
    -  var ifr = this.getEditableIframe();
    -  var body = ifr.contentDocument.body;
    -  var htmlElement = body.parentNode;
    -
    -
    -  // If the iframe's height is 0, then the offsetHeight/scrollHeight of the
    -  // HTML element in the iframe can be totally wack (i.e. too large
    -  // by 50-500px). Also, in standard's mode the clientHeight is 0.
    -  if (parseInt(goog.style.getStyle(ifr, 'height'), 10) === 0) {
    -    goog.style.setStyle(ifr, 'height', 1 + 'px');
    -  }
    -
    -  var fieldHeight;
    -  if (goog.editor.node.isStandardsMode(body)) {
    -
    -    // If in standards-mode,
    -    // grab the HTML element as it will contain all the field's
    -    // contents. The body's height, for example, will not include that of
    -    // floated images at the bottom in standards mode.
    -    // Note that this value include all scrollbars *except* for scrollbars
    -    // on the HTML element itself.
    -    fieldHeight = htmlElement.offsetHeight;
    -  } else {
    -    // In quirks-mode, the body-element always seems
    -    // to size to the containing window.  The html-element however,
    -    // sizes to the content, and can thus end up with a value smaller
    -    // than its child body-element if the content is shrinking.
    -    // We want to make the iframe shrink too when the content shrinks,
    -    // so rather than size the iframe to the body-element, size it to
    -    // the html-element.
    -    fieldHeight = htmlElement.scrollHeight;
    -
    -    // If there is a horizontal scroll, add in the thickness of the
    -    // scrollbar.
    -    if (htmlElement.clientHeight != htmlElement.offsetHeight) {
    -      fieldHeight += goog.editor.SeamlessField.getScrollbarWidth_();
    -    }
    -  }
    -
    -  return fieldHeight;
    -};
    -
    -
    -/**
    - * Grabs the width of a scrollbar from the browser and caches the result.
    - * @return {number} The scrollbar width in pixels.
    - * @private
    - */
    -goog.editor.SeamlessField.getScrollbarWidth_ = function() {
    -  return goog.editor.SeamlessField.scrollbarWidth_ ||
    -      (goog.editor.SeamlessField.scrollbarWidth_ =
    -          goog.style.getScrollbarWidth());
    -};
    -
    -
    -/**
    - * Sizes the iframe to its container div's width. The width of the div
    - * is controlled by its containing context, not by its contents.
    - * if it extends outside of it's contents, then it gets a horizontal scroll.
    - * @private
    - */
    -goog.editor.SeamlessField.prototype.sizeIframeToWrapperGecko_ = function() {
    -  if (this.acquireSizeIframeLockGecko_()) {
    -    var ifr = this.getEditableIframe();
    -    var field = this.getElement();
    -    var resized = false;
    -    if (ifr && field) {
    -      var fieldPaddingBox;
    -      var widthDiv = ifr.parentNode;
    -
    -      var width = widthDiv.offsetWidth;
    -      if (parseInt(goog.style.getStyle(ifr, 'width'), 10) != width) {
    -        fieldPaddingBox = goog.style.getPaddingBox(field);
    -        ifr.style.width = width + 'px';
    -        field.style.width =
    -            width - fieldPaddingBox.left - fieldPaddingBox.right + 'px';
    -        resized = true;
    -      }
    -
    -      var height = widthDiv.offsetHeight;
    -      if (this.isFixedHeight() &&
    -          parseInt(goog.style.getStyle(ifr, 'height'), 10) != height) {
    -        if (!fieldPaddingBox) {
    -          fieldPaddingBox = goog.style.getPaddingBox(field);
    -        }
    -        ifr.style.height = height + 'px';
    -        field.style.height =
    -            height - fieldPaddingBox.top - fieldPaddingBox.bottom + 'px';
    -        resized = true;
    -      }
    -
    -    }
    -    this.releaseSizeIframeLockGecko_();
    -    if (resized) {
    -      this.dispatchEvent(goog.editor.Field.EventType.IFRAME_RESIZED);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Perform all the sizing immediately.
    - */
    -goog.editor.SeamlessField.prototype.doFieldSizingGecko = function() {
    -  // Because doFieldSizingGecko can be called after a setTimeout
    -  // it is possible that the field has been destroyed before this call
    -  // to do the sizing is executed. Check for field existence and do nothing
    -  // if it has already been destroyed.
    -  if (this.getElement()) {
    -    // The order of operations is important here.  Sizing the iframe to the
    -    // wrapper could cause the width to change, which could change the line
    -    // wrapping, which could change the body height.  So we need to do that
    -    // first, then size the iframe to fit the body height.
    -    this.sizeIframeToWrapperGecko_();
    -    if (!this.isFixedHeight()) {
    -      this.sizeIframeToBodyHeightGecko_();
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Acquires a lock on resizing the field iframe. This is used to ensure that
    - * modifications we make while in a mutation event handler don't cause
    - * infinite loops.
    - * @return {boolean} False if the lock is already acquired.
    - * @private
    - */
    -goog.editor.SeamlessField.prototype.acquireSizeIframeLockGecko_ = function() {
    -  if (this.sizeIframeLock_) {
    -    return false;
    -  }
    -  return this.sizeIframeLock_ = true;
    -};
    -
    -
    -/**
    - * Releases a lock on resizing the field iframe. This is used to ensure that
    - * modifications we make while in a mutation event handler don't cause
    - * infinite loops.
    - * @private
    - */
    -goog.editor.SeamlessField.prototype.releaseSizeIframeLockGecko_ = function() {
    -  this.sizeIframeLock_ = false;
    -};
    -
    -
    -// Functions dealing with blending in with the surrounding page.
    -
    -
    -/**
    - * String containing the css rules that, if applied to a document's body,
    - * would style that body as if it were the original element we made editable.
    - * See goog.cssom.iframe.style.getElementContext for more details.
    - * @type {string}
    - * @private
    - */
    -goog.editor.SeamlessField.prototype.iframeableCss_ = '';
    -
    -
    -/**
    - * Gets the css rules that should be used to style an iframe's body as if it
    - * were the original element that we made editable.
    - * @param {boolean=} opt_forceRegeneration Set to true to not read the cached
    - * copy and instead completely regenerate the css rules.
    - * @return {string} The string containing the css rules to use.
    - */
    -goog.editor.SeamlessField.prototype.getIframeableCss = function(
    -    opt_forceRegeneration) {
    -  if (!this.iframeableCss_ || opt_forceRegeneration) {
    -    var originalElement = this.getOriginalElement();
    -    if (originalElement) {
    -      this.iframeableCss_ =
    -          goog.cssom.iframe.style.getElementContext(originalElement,
    -          opt_forceRegeneration);
    -    }
    -  }
    -  return this.iframeableCss_;
    -};
    -
    -
    -/**
    - * Sets the css rules that should be used inside the editable iframe.
    - * Note: to clear the css cache between makeNotEditable/makeEditable,
    - * call this with "" as iframeableCss.
    - * TODO(user): Unify all these css setting methods + Nick's open
    - * CL.  This is getting ridiculous.
    - * @param {string} iframeableCss String containing the css rules to use.
    - */
    -goog.editor.SeamlessField.prototype.setIframeableCss = function(iframeableCss) {
    -  this.iframeableCss_ = iframeableCss;
    -};
    -
    -
    -/**
    - * Used to ensure that CSS stylings are only installed once for none
    - * iframe seamless mode.
    - * TODO(user): Make it a formal part of the API that you can only
    - * set one set of styles globally.
    - * In seamless, non-iframe mode, all the stylings would go in the
    - * same document and conflict.
    - * @type {boolean}
    - * @private
    - */
    -goog.editor.SeamlessField.haveInstalledCss_ = false;
    -
    -
    -/**
    - * Applies CSS from the wrapper-div to the field iframe.
    - */
    -goog.editor.SeamlessField.prototype.inheritBlendedCSS = function() {
    -  // No-op if the field isn't using an iframe.
    -  if (!this.usesIframe()) {
    -    return;
    -  }
    -  var field = this.getElement();
    -  var head = goog.dom.getDomHelper(field).getElementsByTagNameAndClass(
    -      'head')[0];
    -  if (head) {
    -    // We created this <head>, and we know the only thing we put in there
    -    // is a <style> block.  So it's safe to blow away all the children
    -    // as part of rewriting the styles.
    -    goog.dom.removeChildren(head);
    -  }
    -
    -  // Force a cache-clearing in CssUtil - this function was called because
    -  // we're applying the 'blend' for the first time, or because we
    -  // *need* to recompute the blend.
    -  var newCSS = this.getIframeableCss(true);
    -  goog.style.installStyles(newCSS, field);
    -};
    -
    -
    -// Overridden methods.
    -
    -
    -/** @override */
    -goog.editor.SeamlessField.prototype.usesIframe = function() {
    -  // TODO(user): Switch Firefox to using contentEditable
    -  // rather than designMode iframe once contentEditable support
    -  // is less buggy.
    -  return !goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE;
    -};
    -
    -
    -/** @override */
    -goog.editor.SeamlessField.prototype.setupMutationEventHandlersGecko =
    -    function() {
    -  goog.editor.SeamlessField.superClass_.setupMutationEventHandlersGecko.call(
    -      this);
    -
    -  if (this.usesIframe()) {
    -    var iframe = this.getEditableIframe();
    -    var outerDoc = iframe.ownerDocument;
    -    this.eventRegister.listen(outerDoc,
    -        goog.editor.Field.MUTATION_EVENTS_GECKO,
    -        this.handleOuterDocChange_, true);
    -
    -    // If the images load after we do the initial sizing, then this will
    -    // force a field resize.
    -    this.listenForIframeLoadEventKey_ = goog.events.listenOnce(
    -        this.getEditableDomHelper().getWindow(),
    -        goog.events.EventType.LOAD, this.sizeIframeToBodyHeightGecko_,
    -        true, this);
    -
    -    this.eventRegister.listen(outerDoc,
    -        'DOMAttrModified',
    -        goog.bind(this.handleDomAttrChange, this, this.handleOuterDocChange_),
    -        true);
    -  }
    -};
    -
    -
    -/** @override */
    -goog.editor.SeamlessField.prototype.handleChange = function() {
    -  if (this.isEventStopped(goog.editor.Field.EventType.CHANGE)) {
    -    return;
    -  }
    -
    -  goog.editor.SeamlessField.superClass_.handleChange.call(this);
    -
    -  if (this.usesIframe()) {
    -    this.sizeIframeToBodyHeightGecko_();
    -  }
    -};
    -
    -
    -/** @override */
    -goog.editor.SeamlessField.prototype.dispatchBlur = function() {
    -  if (this.isEventStopped(goog.editor.Field.EventType.BLUR)) {
    -    return;
    -  }
    -
    -  goog.editor.SeamlessField.superClass_.dispatchBlur.call(this);
    -
    -  // Clear the selection and restore the current range back after collapsing
    -  // it. The ideal solution would have been to just leave the range intact; but
    -  // when there are multiple fields present on the page, its important that
    -  // the selection isn't retained when we switch between the fields. We also
    -  // have to make sure that the cursor position is retained when we tab in and
    -  // out of a field and our approach addresses both these issues.
    -  // Another point to note is that we do it on a setTimeout to allow for
    -  // DOM modifications on blur. Otherwise, something like setLoremIpsum will
    -  // leave a blinking cursor in the field even though it's blurred.
    -  if (!goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE &&
    -      !goog.editor.BrowserFeature.CLEARS_SELECTION_WHEN_FOCUS_LEAVES) {
    -    var win = this.getEditableDomHelper().getWindow();
    -    var dragging = false;
    -    goog.events.unlistenByKey(this.listenForDragOverEventKey_);
    -    this.listenForDragOverEventKey_ = goog.events.listenOnce(
    -        win.document.body, 'dragover',
    -        function() {
    -          dragging = true;
    -        });
    -    goog.global.setTimeout(goog.bind(function() {
    -      // Do not clear the selection if we're only dragging text.
    -      // This addresses a bug on FF1.5/linux where dragging fires a blur,
    -      // but clearing the selection confuses Firefox's drag-and-drop
    -      // implementation. For more info, see http://b/1061064
    -      if (!dragging) {
    -        if (this.editableDomHelper) {
    -          var rng = this.getRange();
    -
    -          // If there are multiple fields on a page, we need to make sure that
    -          // the selection isn't retained when we switch between fields. We
    -          // could have collapsed the range but there is a bug in GECKO where
    -          // the selection stays highlighted even though its backing range is
    -          // collapsed (http://b/1390115). To get around this, we clear the
    -          // selection and restore the collapsed range back in. Restoring the
    -          // range is important so that the cursor stays intact when we tab out
    -          // and into a field (See http://b/1790301 for additional details on
    -          // this).
    -          var iframeWindow = this.editableDomHelper.getWindow();
    -          goog.dom.Range.clearSelection(iframeWindow);
    -
    -          if (rng) {
    -            rng.collapse(true);
    -            rng.select();
    -          }
    -        }
    -      }
    -    }, this), 0);
    -  }
    -};
    -
    -
    -/** @override */
    -goog.editor.SeamlessField.prototype.turnOnDesignModeGecko = function() {
    -  goog.editor.SeamlessField.superClass_.turnOnDesignModeGecko.call(this);
    -  var doc = this.getEditableDomHelper().getDocument();
    -
    -  doc.execCommand('enableInlineTableEditing', false, 'false');
    -  doc.execCommand('enableObjectResizing', false, 'false');
    -};
    -
    -
    -/** @override */
    -goog.editor.SeamlessField.prototype.installStyles = function() {
    -  if (!this.usesIframe()) {
    -    if (!goog.editor.SeamlessField.haveInstalledCss_) {
    -      if (this.cssStyles) {
    -        goog.style.installStyles(this.cssStyles, this.getElement());
    -      }
    -
    -      // TODO(user): this should be reset to false when the editor is quit.
    -      // In non-iframe mode, CSS styles should only be instaled once.
    -      goog.editor.SeamlessField.haveInstalledCss_ = true;
    -    }
    -  }
    -};
    -
    -
    -/** @override */
    -goog.editor.SeamlessField.prototype.makeEditableInternal = function(
    -    opt_iframeSrc) {
    -  if (this.usesIframe()) {
    -    goog.editor.SeamlessField.superClass_.makeEditableInternal.call(this,
    -        opt_iframeSrc);
    -  } else {
    -    var field = this.getOriginalElement();
    -    if (field) {
    -      this.setupFieldObject(field);
    -      field.contentEditable = true;
    -
    -      this.injectContents(field.innerHTML, field);
    -
    -      this.handleFieldLoad();
    -    }
    -  }
    -};
    -
    -
    -/** @override */
    -goog.editor.SeamlessField.prototype.handleFieldLoad = function() {
    -  if (this.usesIframe()) {
    -    // If the CSS inheriting code screws up (e.g. makes fonts too large) and
    -    // the field is sized off in goog.editor.Field.makeIframeField, then we need
    -    // to size it correctly, but it needs to be visible for the browser
    -    // to have fully rendered it. We need to put this on a timeout to give
    -    // the browser time to render.
    -    var self = this;
    -    goog.global.setTimeout(function() {
    -      self.doFieldSizingGecko();
    -    }, 0);
    -  }
    -  goog.editor.SeamlessField.superClass_.handleFieldLoad.call(this);
    -};
    -
    -
    -/** @override */
    -goog.editor.SeamlessField.prototype.getIframeAttributes = function() {
    -  return { 'frameBorder': 0, 'style': 'padding:0;' };
    -};
    -
    -
    -/** @override */
    -goog.editor.SeamlessField.prototype.attachIframe = function(iframe) {
    -  this.autoDetectFixedHeight_();
    -  var field = this.getOriginalElement();
    -  var dh = goog.dom.getDomHelper(field);
    -
    -  // Grab the width/height values of the field before modifying any CSS
    -  // as some of the modifications affect its size (e.g. innerHTML='')
    -  // Here, we set the size of the field to fixed so there's not too much
    -  // jiggling when we set the innerHTML of the field.
    -  var oldWidth = field.style.width;
    -  var oldHeight = field.style.height;
    -  goog.style.setStyle(field, 'visibility', 'hidden');
    -
    -  // If there is a floated element at the bottom of the field,
    -  // then it needs a clearing div at the end to cause the clientHeight
    -  // to contain the entire field.
    -  // Also, with css re-writing, the margins of the first/last
    -  // paragraph don't seem to get included in the clientHeight. Specifically,
    -  // the extra divs below force the field's clientHeight to include the
    -  // margins on the first and last elements contained within it.
    -  var startDiv = dh.createDom(goog.dom.TagName.DIV,
    -      {'style': 'height:0;clear:both', 'innerHTML': '&nbsp;'});
    -  var endDiv = startDiv.cloneNode(true);
    -  field.insertBefore(startDiv, field.firstChild);
    -  goog.dom.appendChild(field, endDiv);
    -
    -  var contentBox = goog.style.getContentBoxSize(field);
    -  var width = contentBox.width;
    -  var height = contentBox.height;
    -
    -  var html = '';
    -  if (this.isFixedHeight()) {
    -    html = '&nbsp;';
    -
    -    goog.style.setStyle(field, 'position', 'relative');
    -    goog.style.setStyle(field, 'overflow', 'visible');
    -
    -    goog.style.setStyle(iframe, 'position', 'absolute');
    -    goog.style.setStyle(iframe, 'top', '0');
    -    goog.style.setStyle(iframe, 'left', '0');
    -  }
    -  goog.style.setSize(field, width, height);
    -
    -  // In strict mode, browsers put blank space at the bottom and right
    -  // if a field when it has an iframe child, to fill up the remaining line
    -  // height. So make the line height = 0.
    -  if (goog.editor.node.isStandardsMode(field)) {
    -    this.originalFieldLineHeight_ = field.style.lineHeight;
    -    goog.style.setStyle(field, 'lineHeight', '0');
    -  }
    -
    -  goog.editor.node.replaceInnerHtml(field, html);
    -  // Set the initial size
    -  goog.style.setSize(iframe, width, height);
    -  goog.style.setSize(field, oldWidth, oldHeight);
    -  goog.style.setStyle(field, 'visibility', '');
    -  goog.dom.appendChild(field, iframe);
    -
    -  // Only write if its not IE HTTPS in which case we're waiting for load.
    -  if (!this.shouldLoadAsynchronously()) {
    -    var doc = iframe.contentWindow.document;
    -    if (goog.editor.node.isStandardsMode(iframe.ownerDocument)) {
    -      doc.open();
    -      var emptyHtml = goog.html.uncheckedconversions
    -          .safeHtmlFromStringKnownToSatisfyTypeContract(
    -              goog.string.Const.from('HTML from constant string'),
    -              '<!DOCTYPE HTML><html></html>');
    -      goog.dom.safe.documentWrite(doc, emptyHtml);
    -      doc.close();
    -    }
    -  }
    -};
    -
    -
    -/** @override */
    -goog.editor.SeamlessField.prototype.getFieldFormatInfo = function(
    -    extraStyles) {
    -  var originalElement = this.getOriginalElement();
    -  if (originalElement) {
    -    return new goog.editor.icontent.FieldFormatInfo(
    -        this.id,
    -        goog.editor.node.isStandardsMode(originalElement),
    -        true,
    -        this.isFixedHeight(),
    -        extraStyles);
    -  }
    -  throw Error('no field');
    -};
    -
    -
    -/** @override */
    -goog.editor.SeamlessField.prototype.writeIframeContent = function(
    -    iframe, innerHtml, extraStyles) {
    -  // For seamless iframes, hide the iframe while we're laying it out to
    -  // prevent the flicker.
    -  goog.style.setStyle(iframe, 'visibility', 'hidden');
    -  var formatInfo = this.getFieldFormatInfo(extraStyles);
    -  var styleInfo = new goog.editor.icontent.FieldStyleInfo(
    -      this.getOriginalElement(),
    -      this.cssStyles + this.getIframeableCss());
    -  goog.editor.icontent.writeNormalInitialBlendedIframe(
    -      formatInfo, innerHtml, styleInfo, iframe);
    -  this.doFieldSizingGecko();
    -  goog.style.setStyle(iframe, 'visibility', 'visible');
    -};
    -
    -
    -/** @override */
    -goog.editor.SeamlessField.prototype.restoreDom = function() {
    -  // TODO(user): Consider only removing the iframe if we are
    -  // restoring the original node.
    -  if (this.usesIframe()) {
    -    goog.dom.removeNode(this.getEditableIframe());
    -  }
    -};
    -
    -
    -/** @override */
    -goog.editor.SeamlessField.prototype.clearListeners = function() {
    -  goog.events.unlistenByKey(this.listenForDragOverEventKey_);
    -  goog.events.unlistenByKey(this.listenForIframeLoadEventKey_);
    -
    -  goog.editor.SeamlessField.base(this, 'clearListeners');
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/seamlessfield_quirks_test.html b/src/database/third_party/closure-library/closure/goog/editor/seamlessfield_quirks_test.html
    deleted file mode 100644
    index 33ecea0efb0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/seamlessfield_quirks_test.html
    +++ /dev/null
    @@ -1,28 +0,0 @@
    -<!--
    -  All Rights Reserved.
    -
    -  NOTE: This file should be an exact copy of seamlessfield_test.html,
    -  except for this comment and that the <!DOCTYPE> tag should be removed from
    -  the top. If seamlessfield_test.html is changed, this file should be
    -  changed accordingly.
    -
    -  @author nicksantos@google.com (Nick Santos)
    ---><html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<title>Trogedit Unit Tests - goog.editor.SeamlessField</title>
    -<script src="../base.js"></script>
    -</head>
    -<body>
    -
    -<div id='field'>
    -</div>
    -
    -<script src="seamlessfield_test.js"></script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/seamlessfield_test.html b/src/database/third_party/closure-library/closure/goog/editor/seamlessfield_test.html
    deleted file mode 100644
    index 36d4e0fca52..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/seamlessfield_test.html
    +++ /dev/null
    @@ -1,32 +0,0 @@
    -<!DOCTYPE html>
    -<!--
    -  All Rights Reserved.
    -
    -  NOTE: If any changes are made to this file, please keep
    -  seamlessfield_quirks_test.html synced with this. That file should
    -  be an exact copy of this one, except for this comment and that the
    -  <!DOCTYPE> tag should be removed from the top. All tests should be added
    -  to seamlessfield_test.js so that they will be run by both
    -  seamlessfield*_test.html files.
    -  
    -  @author nicksantos@google.com (Nick Santos)
    ---><html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Trogedit Unit Tests - goog.editor.SeamlessField</title>
    -<script src="../base.js"></script>
    -</head>
    -<body>
    -
    -<div id='field'>
    -</div>
    -
    -<script src="seamlessfield_test.js"></script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/seamlessfield_test.js b/src/database/third_party/closure-library/closure/goog/editor/seamlessfield_test.js
    deleted file mode 100644
    index 65e5cdfaaf7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/seamlessfield_test.js
    +++ /dev/null
    @@ -1,469 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Trogedit unit tests for goog.editor.SeamlessField.
    - *
    - * @author nicksantos@google.com (Nick Santos)
    - * @suppress {missingProperties} There are many mocks in this unit test,
    - *     and the mocks don't fit well in the type system.
    - */
    -
    -/** @suppress {extraProvide} */
    -goog.provide('goog.editor.seamlessfield_test');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.DomHelper');
    -goog.require('goog.dom.Range');
    -goog.require('goog.editor.BrowserFeature');
    -goog.require('goog.editor.Field');
    -goog.require('goog.editor.SeamlessField');
    -goog.require('goog.events');
    -goog.require('goog.functions');
    -goog.require('goog.style');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.MockRange');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('seamlessfield_test');
    -
    -var fieldElem;
    -var fieldElemClone;
    -
    -function setUp() {
    -  fieldElem = goog.dom.getElement('field');
    -  fieldElemClone = fieldElem.cloneNode(true);
    -}
    -
    -function tearDown() {
    -  fieldElem.parentNode.replaceChild(fieldElemClone, fieldElem);
    -}
    -
    -// the following tests check for blended iframe positioning. They really
    -// only make sense on browsers without contentEditable.
    -function testBlankField() {
    -  if (!goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE) {
    -    assertAttachSeamlessIframeSizesCorrectly(
    -        initSeamlessField('&nbsp;', {}), createSeamlessIframe());
    -  }
    -}
    -
    -function testFieldWithContent() {
    -  if (!goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE) {
    -    assertAttachSeamlessIframeSizesCorrectly(
    -        initSeamlessField('Hi!', {}), createSeamlessIframe());
    -  }
    -}
    -
    -function testFieldWithPadding() {
    -  if (!goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE) {
    -    assertAttachSeamlessIframeSizesCorrectly(
    -        initSeamlessField('Hi!', {'padding': '2px 5px'}),
    -        createSeamlessIframe());
    -  }
    -}
    -
    -function testFieldWithMargin() {
    -  if (!goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE) {
    -    assertAttachSeamlessIframeSizesCorrectly(
    -        initSeamlessField('Hi!', {'margin': '2px 5px'}),
    -        createSeamlessIframe());
    -  }
    -}
    -
    -function testFieldWithBorder() {
    -  if (!goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE) {
    -    assertAttachSeamlessIframeSizesCorrectly(
    -        initSeamlessField('Hi!', {'border': '2px 5px'}),
    -        createSeamlessIframe());
    -  }
    -}
    -
    -function testFieldWithOverflow() {
    -  if (!goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE) {
    -    assertAttachSeamlessIframeSizesCorrectly(
    -        initSeamlessField(['1', '2', '3', '4', '5', '6', '7'].join('<p/>'),
    -        {'overflow': 'auto', 'position': 'relative', 'height': '20px'}),
    -        createSeamlessIframe());
    -    assertEquals(20, fieldElem.offsetHeight);
    -  }
    -}
    -
    -function testFieldWithOverflowAndPadding() {
    -  if (!goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE) {
    -    var blendedField = initSeamlessField(
    -        ['1', '2', '3', '4', '5', '6', '7'].join('<p/>'),
    -        {
    -          'overflow': 'auto',
    -          'position': 'relative',
    -          'height': '20px',
    -          'padding': '2px 3px'
    -        });
    -    var blendedIframe = createSeamlessIframe();
    -    assertAttachSeamlessIframeSizesCorrectly(blendedField, blendedIframe);
    -    assertEquals(24, fieldElem.offsetHeight);
    -  }
    -}
    -
    -function testIframeHeightGrowsOnWrap() {
    -  if (!goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE) {
    -    var clock = new goog.testing.MockClock(true);
    -    var blendedField;
    -    try {
    -      blendedField = initSeamlessField('',
    -          {'border': '1px solid black', 'height': '20px'});
    -      blendedField.makeEditable();
    -      blendedField.setHtml(false, 'Content that should wrap after resize.');
    -
    -      // Ensure that the field was fully loaded and sized before measuring.
    -      clock.tick(1);
    -
    -      // Capture starting heights.
    -      var unwrappedIframeHeight = blendedField.getEditableIframe().offsetHeight;
    -
    -      // Resize the field such that the text should wrap.
    -      fieldElem.style.width = '200px';
    -      blendedField.doFieldSizingGecko();
    -
    -      // Iframe should grow as a result.
    -      var wrappedIframeHeight = blendedField.getEditableIframe().offsetHeight;
    -      assertTrue('Wrapped text should cause iframe to grow - initial height: ' +
    -          unwrappedIframeHeight + ', wrapped height: ' + wrappedIframeHeight,
    -          wrappedIframeHeight > unwrappedIframeHeight);
    -    } finally {
    -      blendedField.dispose();
    -      clock.dispose();
    -    }
    -  }
    -}
    -
    -function testDispatchIframeResizedForWrapperHeight() {
    -  if (!goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE) {
    -    var clock = new goog.testing.MockClock(true);
    -    var blendedField = initSeamlessField('Hi!', {'border': '2px 5px'});
    -    var iframe = createSeamlessIframe();
    -    blendedField.attachIframe(iframe);
    -
    -    var resizeCalled = false;
    -    goog.events.listenOnce(
    -        blendedField,
    -        goog.editor.Field.EventType.IFRAME_RESIZED,
    -        function() {
    -          resizeCalled = true;
    -        });
    -
    -    try {
    -      blendedField.makeEditable();
    -      blendedField.setHtml(false, 'Content that should wrap after resize.');
    -
    -      // Ensure that the field was fully loaded and sized before measuring.
    -      clock.tick(1);
    -
    -      assertFalse('Iframe resize must not be dispatched yet', resizeCalled);
    -
    -      // Resize the field such that the text should wrap.
    -      fieldElem.style.width = '200px';
    -      blendedField.sizeIframeToWrapperGecko_();
    -      assertTrue('Iframe resize must be dispatched for Wrapper', resizeCalled);
    -    } finally {
    -      blendedField.dispose();
    -      clock.dispose();
    -    }
    -  }
    -}
    -
    -function testDispatchIframeResizedForBodyHeight() {
    -  if (!goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE) {
    -    var clock = new goog.testing.MockClock(true);
    -    var blendedField = initSeamlessField('Hi!', {'border': '2px 5px'});
    -    var iframe = createSeamlessIframe();
    -    blendedField.attachIframe(iframe);
    -
    -    var resizeCalled = false;
    -    goog.events.listenOnce(
    -        blendedField,
    -        goog.editor.Field.EventType.IFRAME_RESIZED,
    -        function() {
    -          resizeCalled = true;
    -        });
    -
    -    try {
    -      blendedField.makeEditable();
    -      blendedField.setHtml(false, 'Content that should wrap after resize.');
    -
    -      // Ensure that the field was fully loaded and sized before measuring.
    -      clock.tick(1);
    -
    -      assertFalse('Iframe resize must not be dispatched yet', resizeCalled);
    -
    -      // Resize the field to a different body height.
    -      var bodyHeight = blendedField.getIframeBodyHeightGecko_();
    -      blendedField.getIframeBodyHeightGecko_ = function() {
    -        return bodyHeight + 1;
    -      };
    -      blendedField.sizeIframeToBodyHeightGecko_();
    -      assertTrue('Iframe resize must be dispatched for Body', resizeCalled);
    -    } finally {
    -      blendedField.dispose();
    -      clock.dispose();
    -    }
    -  }
    -}
    -
    -function testDispatchBlur() {
    -  if (!goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE &&
    -      !goog.editor.BrowserFeature.CLEARS_SELECTION_WHEN_FOCUS_LEAVES) {
    -    var blendedField = initSeamlessField('Hi!', {'border': '2px 5px'});
    -    var iframe = createSeamlessIframe();
    -    blendedField.attachIframe(iframe);
    -
    -    var blurCalled = false;
    -    goog.events.listenOnce(blendedField, goog.editor.Field.EventType.BLUR,
    -        function() {
    -          blurCalled = true;
    -        });
    -
    -    var clearSelection = goog.dom.Range.clearSelection;
    -    var cleared = false;
    -    var clearedWindow;
    -    blendedField.editableDomHelper = new goog.dom.DomHelper();
    -    blendedField.editableDomHelper.getWindow =
    -        goog.functions.constant(iframe.contentWindow);
    -    var mockRange = new goog.testing.MockRange();
    -    blendedField.getRange = function() {
    -      return mockRange;
    -    };
    -    goog.dom.Range.clearSelection = function(opt_window) {
    -      clearSelection(opt_window);
    -      cleared = true;
    -      clearedWindow = opt_window;
    -    };
    -    var clock = new goog.testing.MockClock(true);
    -
    -    mockRange.collapse(true);
    -    mockRange.select();
    -    mockRange.$replay();
    -    blendedField.dispatchBlur();
    -    clock.tick(1);
    -
    -    assertTrue('Blur must be dispatched.', blurCalled);
    -    assertTrue('Selection must be cleared.', cleared);
    -    assertEquals('Selection must be cleared in iframe',
    -        iframe.contentWindow, clearedWindow);
    -    mockRange.$verify();
    -    clock.dispose();
    -  }
    -}
    -
    -function testSetMinHeight() {
    -  if (!goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE) {
    -    var clock = new goog.testing.MockClock(true);
    -    try {
    -      var field = initSeamlessField(
    -          ['1', '2', '3', '4', '5', '6', '7'].join('<p/>'),
    -          {'position': 'relative', 'height': '60px'});
    -
    -      // Initially create and size iframe.
    -      var iframe = createSeamlessIframe();
    -      field.attachIframe(iframe);
    -      field.iframeFieldLoadHandler(iframe, '', {});
    -      // Need to process timeouts set by load handlers.
    -      clock.tick(1000);
    -
    -      var normalHeight = goog.style.getSize(iframe).height;
    -
    -      var delayedChangeCalled = false;
    -      goog.events.listen(field, goog.editor.Field.EventType.DELAYEDCHANGE,
    -          function() {
    -            delayedChangeCalled = true;
    -          });
    -
    -      // Test that min height is obeyed.
    -      field.setMinHeight(30);
    -      clock.tick(1000);
    -      assertEquals('Iframe height must match min height.',
    -          30, goog.style.getSize(iframe).height);
    -      assertFalse('Setting min height must not cause delayed change event.',
    -          delayedChangeCalled);
    -
    -      // Test that min height doesn't shrink field.
    -      field.setMinHeight(0);
    -      clock.tick(1000);
    -      assertEquals(normalHeight, goog.style.getSize(iframe).height);
    -      assertFalse('Setting min height must not cause delayed change event.',
    -          delayedChangeCalled);
    -    } finally {
    -      field.dispose();
    -      clock.dispose();
    -    }
    -  }
    -}
    -
    -
    -/**
    - * @bug 1649967 This code used to throw a Javascript error.
    - */
    -function testSetMinHeightWithNoIframe() {
    -  if (goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE) {
    -    try {
    -      var field = initSeamlessField('&nbsp;', {});
    -      field.makeEditable();
    -      field.setMinHeight(30);
    -    } finally {
    -      field.dispose();
    -    }
    -  }
    -}
    -
    -function testStartChangeEvents() {
    -  if (goog.editor.BrowserFeature.USE_MUTATION_EVENTS) {
    -    var clock = new goog.testing.MockClock(true);
    -
    -    try {
    -      var field = initSeamlessField('&nbsp;', {});
    -      field.makeEditable();
    -
    -      var changeCalled = false;
    -      goog.events.listenOnce(field, goog.editor.Field.EventType.CHANGE,
    -          function() {
    -            changeCalled = true;
    -          });
    -
    -      var delayedChangeCalled = false;
    -      goog.events.listenOnce(field, goog.editor.Field.EventType.CHANGE,
    -          function() {
    -            delayedChangeCalled = true;
    -          });
    -
    -      field.stopChangeEvents(true, true);
    -      if (field.changeTimerGecko_) {
    -        field.changeTimerGecko_.start();
    -      }
    -
    -      field.startChangeEvents();
    -      clock.tick(1000);
    -
    -      assertFalse(changeCalled);
    -      assertFalse(delayedChangeCalled);
    -    } finally {
    -      clock.dispose();
    -      field.dispose();
    -    }
    -  }
    -}
    -
    -function testManipulateDom() {
    -  // Test in blended field since that is what fires change events.
    -  var editableField = initSeamlessField('&nbsp;', {});
    -  var clock = new goog.testing.MockClock(true);
    -
    -  var delayedChangeCalled = 0;
    -  goog.events.listen(editableField, goog.editor.Field.EventType.DELAYEDCHANGE,
    -      function() {
    -        delayedChangeCalled++;
    -      });
    -
    -  assertFalse(editableField.isLoaded());
    -  editableField.manipulateDom(goog.nullFunction);
    -  clock.tick(1000);
    -  assertEquals('Must not fire delayed change events if field is not loaded.',
    -      0, delayedChangeCalled);
    -
    -  editableField.makeEditable();
    -  var usesIframe = editableField.usesIframe();
    -
    -  try {
    -    editableField.manipulateDom(goog.nullFunction);
    -    clock.tick(1000); // Wait for delayed change to fire.
    -    assertEquals('By default must fire a single delayed change event.',
    -        1, delayedChangeCalled);
    -
    -    editableField.manipulateDom(goog.nullFunction, true);
    -    clock.tick(1000); // Wait for delayed change to fire.
    -    assertEquals('Must prevent all delayed change events.',
    -        1, delayedChangeCalled);
    -
    -    editableField.manipulateDom(function() {
    -      this.handleChange();
    -      this.handleChange();
    -      if (this.changeTimerGecko_) {
    -        this.changeTimerGecko_.fire();
    -      }
    -
    -      this.dispatchDelayedChange_();
    -      this.delayedChangeTimer_.fire();
    -    }, false, editableField);
    -    clock.tick(1000); // Wait for delayed change to fire.
    -    assertEquals('Must ignore dispatch delayed change called within func.',
    -        2, delayedChangeCalled);
    -  } finally {
    -    // Ensure we always uninstall the mock clock and dispose of everything.
    -    editableField.dispose();
    -    clock.dispose();
    -  }
    -}
    -
    -function testAttachIframe() {
    -  var blendedField = initSeamlessField('Hi!', {});
    -  var iframe = createSeamlessIframe();
    -  try {
    -    blendedField.attachIframe(iframe);
    -  } catch (err) {
    -    fail('Error occurred while attaching iframe.');
    -  }
    -}
    -
    -
    -function createSeamlessIframe() {
    -  // NOTE(nicksantos): This is a reimplementation of
    -  // TR_EditableUtil.getIframeAttributes, but untangled for tests, and
    -  // specifically with what we need for blended mode.
    -  return goog.dom.createDom('IFRAME',
    -      { 'frameBorder': '0', 'style': 'padding:0;' });
    -}
    -
    -
    -/**
    - * Initialize a new editable field for the field id 'field', with the given
    - * innerHTML and styles.
    - *
    - * @param {string} innerHTML html for the field contents.
    - * @param {Object} styles Key-value pairs for styles on the field.
    - * @return {goog.editor.SeamlessField} The field.
    - */
    -function initSeamlessField(innerHTML, styles) {
    -  var field = new goog.editor.SeamlessField('field');
    -  fieldElem.innerHTML = innerHTML;
    -  goog.style.setStyle(fieldElem, styles);
    -  return field;
    -}
    -
    -
    -/**
    - * Make sure that the original field element for the given goog.editor.Field has
    - * the same size before and after attaching the given iframe. If this is not
    - * true, then the field will fidget while we're initializing the field,
    - * and that's not what we want.
    - *
    - * @param {goog.editor.Field} fieldObj The field.
    - * @param {HTMLIFrameElement} iframe The iframe.
    - */
    -function assertAttachSeamlessIframeSizesCorrectly(fieldObj, iframe) {
    -  var size = goog.style.getSize(fieldObj.getOriginalElement());
    -  fieldObj.attachIframe(iframe);
    -  var newSize = goog.style.getSize(fieldObj.getOriginalElement());
    -
    -  assertEquals(size.width, newSize.width);
    -  assertEquals(size.height, newSize.height);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/style.js b/src/database/third_party/closure-library/closure/goog/editor/style.js
    deleted file mode 100644
    index 53a8b416131..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/style.js
    +++ /dev/null
    @@ -1,225 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Utilties for working with the styles of DOM nodes, and
    - * related to rich text editing.
    - *
    - * Many of these are not general enough to go into goog.style, and use
    - * constructs (like "isContainer") that only really make sense inside
    - * of an HTML editor.
    - *
    - * The API has been optimized for iterating over large, irregular DOM
    - * structures (with lots of text nodes), and so the API tends to be a bit
    - * more permissive than the goog.style API should be. For example,
    - * goog.style.getComputedStyle will throw an exception if you give it a
    - * text node.
    - *
    - * @author nicksantos@google.com (Nick Santos)
    - */
    -
    -goog.provide('goog.editor.style');
    -
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.dom.NodeType');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.editor.BrowserFeature');
    -goog.require('goog.events.EventType');
    -goog.require('goog.object');
    -goog.require('goog.style');
    -goog.require('goog.userAgent');
    -
    -
    -/**
    - * Gets the computed or cascaded style.
    - *
    - * This is different than goog.style.getStyle_ because it returns null
    - * for text nodes (instead of throwing an exception), and never reads
    - * inline style. These two functions may need to be reconciled.
    - *
    - * @param {!Node} node Node to get style of.
    - * @param {string} stylePropertyName Property to get (must be camelCase,
    - *     not css-style).
    - * @return {?string} Style value, or null if this is not an element node.
    - * @private
    - */
    -goog.editor.style.getComputedOrCascadedStyle_ = function(
    -    node, stylePropertyName) {
    -  if (node.nodeType != goog.dom.NodeType.ELEMENT) {
    -    // Only element nodes have style.
    -    return null;
    -  }
    -  return goog.userAgent.IE ?
    -      goog.style.getCascadedStyle(/** @type {!Element} */ (node),
    -          stylePropertyName) :
    -      goog.style.getComputedStyle(/** @type {!Element} */ (node),
    -          stylePropertyName);
    -};
    -
    -
    -/**
    - * Checks whether the given element inherits display: block.
    - * @param {!Node} node The Node to check.
    - * @return {boolean} Whether the element inherits CSS display: block.
    - */
    -goog.editor.style.isDisplayBlock = function(node) {
    -  return goog.editor.style.getComputedOrCascadedStyle_(
    -      node, 'display') == 'block';
    -};
    -
    -
    -/**
    - * Returns true if the element is a container of other non-inline HTML
    - * Note that span, strong and em tags, being inline can only contain
    - * other inline elements and are thus, not containers. Containers are elements
    - * that should not be broken up when wrapping selections with a node of an
    - * inline block styling.
    - * @param {Node} element The element to check.
    - * @return {boolean} Whether the element is a container.
    - */
    -goog.editor.style.isContainer = function(element) {
    -  var nodeName = element && element.nodeName.toLowerCase();
    -  return !!(element &&
    -      (goog.editor.style.isDisplayBlock(element) ||
    -          nodeName == 'td' ||
    -          nodeName == 'table' ||
    -          nodeName == 'li'));
    -};
    -
    -
    -/**
    - * Return the first ancestor of this node that is a container, inclusive.
    - * @see isContainer
    - * @param {Node} node Node to find the container of.
    - * @return {Element} The element which contains node.
    - */
    -goog.editor.style.getContainer = function(node) {
    -  // We assume that every node must have a container.
    -  return /** @type {Element} */ (
    -      goog.dom.getAncestor(node, goog.editor.style.isContainer, true));
    -};
    -
    -
    -/**
    - * Set of input types that should be kept selectable even when their ancestors
    - * are made unselectable.
    - * @type {Object}
    - * @private
    - */
    -goog.editor.style.SELECTABLE_INPUT_TYPES_ = goog.object.createSet(
    -    'text', 'file', 'url');
    -
    -
    -/**
    - * Prevent the default action on mousedown events.
    - * @param {goog.events.Event} e The mouse down event.
    - * @private
    - */
    -goog.editor.style.cancelMouseDownHelper_ = function(e) {
    -  var targetTagName = e.target.tagName;
    -  if (targetTagName != goog.dom.TagName.TEXTAREA &&
    -      targetTagName != goog.dom.TagName.INPUT) {
    -    e.preventDefault();
    -  }
    -};
    -
    -
    -/**
    - * Makes the given element unselectable, as well as all of its children, except
    - * for text areas, text, file and url inputs.
    - * @param {Element} element The element to make unselectable.
    - * @param {goog.events.EventHandler} eventHandler An EventHandler to register
    - *     the event with. Assumes when the node is destroyed, the eventHandler's
    - *     listeners are destroyed as well.
    - */
    -goog.editor.style.makeUnselectable = function(element, eventHandler) {
    -  if (goog.editor.BrowserFeature.HAS_UNSELECTABLE_STYLE) {
    -    // The mousing down on a node should not blur the focused node.
    -    // This is consistent with how IE works.
    -    // TODO: Consider using just the mousedown handler and not the css property.
    -    eventHandler.listen(element, goog.events.EventType.MOUSEDOWN,
    -        goog.editor.style.cancelMouseDownHelper_, true);
    -  }
    -
    -  goog.style.setUnselectable(element, true);
    -
    -  // Make inputs and text areas selectable.
    -  var inputs = element.getElementsByTagName(goog.dom.TagName.INPUT);
    -  for (var i = 0, len = inputs.length; i < len; i++) {
    -    var input = inputs[i];
    -    if (input.type in goog.editor.style.SELECTABLE_INPUT_TYPES_) {
    -      goog.editor.style.makeSelectable(input);
    -    }
    -  }
    -  goog.array.forEach(element.getElementsByTagName(goog.dom.TagName.TEXTAREA),
    -      goog.editor.style.makeSelectable);
    -};
    -
    -
    -/**
    - * Make the given element selectable.
    - *
    - * For IE this simply turns off the "unselectable" property.
    - *
    - * Under FF no descendent of an unselectable node can be selectable:
    - *
    - * https://bugzilla.mozilla.org/show_bug.cgi?id=203291
    - *
    - * So we make each ancestor of node selectable, while trying to preserve the
    - * unselectability of other nodes along that path
    - *
    - * This may cause certain text nodes which should be unselectable, to become
    - * selectable. For example:
    - *
    - * <div id=div1 style="-moz-user-select: none">
    - *   Text1
    - *   <span id=span1>Text2</span>
    - * </div>
    - *
    - * If we call makeSelectable on span1, then it will cause "Text1" to become
    - * selectable, since it had to make div1 selectable in order for span1 to be
    - * selectable.
    - *
    - * If "Text1" were enclosed within a <p> or <span>, then this problem would
    - * not arise.  Text nodes do not have styles, so its style can't be set to
    - * unselectable.
    - *
    - * @param {Element} element The element to make selectable.
    - */
    -goog.editor.style.makeSelectable = function(element) {
    -  goog.style.setUnselectable(element, false);
    -  if (goog.editor.BrowserFeature.HAS_UNSELECTABLE_STYLE) {
    -    // Go up ancestor chain, searching for nodes that are unselectable.
    -    // If such a node exists, mark it as selectable but mark its other children
    -    // as unselectable so the minimum set of nodes is changed.
    -    var child = element;
    -    var current = /** @type {Element} */ (element.parentNode);
    -    while (current && current.tagName != goog.dom.TagName.HTML) {
    -      if (goog.style.isUnselectable(current)) {
    -        goog.style.setUnselectable(current, false, true);
    -
    -        for (var i = 0, len = current.childNodes.length; i < len; i++) {
    -          var node = current.childNodes[i];
    -          if (node != child && node.nodeType == goog.dom.NodeType.ELEMENT) {
    -            goog.style.setUnselectable(current.childNodes[i], true);
    -          }
    -        }
    -      }
    -
    -      child = current;
    -      current = /** @type {Element} */ (current.parentNode);
    -    }
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/style_test.html b/src/database/third_party/closure-library/closure/goog/editor/style_test.html
    deleted file mode 100644
    index 98779546ef1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/style_test.html
    +++ /dev/null
    @@ -1,27 +0,0 @@
    -<!DOCTYPE html>
    -<!--
    -  All Rights Reserved.
    -
    -  Author: nicksantos@google.com (Nick Santos)
    --->
    -<html>
    - <!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.editor.style
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.editor.styleTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/style_test.js b/src/database/third_party/closure-library/closure/goog/editor/style_test.js
    deleted file mode 100644
    index 300795d37f9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/style_test.js
    +++ /dev/null
    @@ -1,174 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.editor.styleTest');
    -goog.setTestOnly('goog.editor.styleTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.editor.BrowserFeature');
    -goog.require('goog.editor.style');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventType');
    -goog.require('goog.style');
    -goog.require('goog.testing.LooseMock');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.mockmatchers');
    -
    -var parentNode = null;
    -var childNode1 = null;
    -var childNode2 = null;
    -var childNode3 = null;
    -var gChildWsNode1 = null;
    -var gChildTextNode1 = null;
    -var gChildNbspNode1 = null;
    -var gChildMixedNode1 = null;
    -var gChildWsNode2a = null;
    -var gChildWsNode2b = null;
    -var gChildTextNode3a = null;
    -var gChildWsNode3 = null;
    -var gChildTextNode3b = null;
    -
    -var $dom = goog.dom.createDom;
    -var $text = goog.dom.createTextNode;
    -
    -function setUpGetNodeFunctions() {
    -  parentNode = $dom(
    -      'p', {id: 'parentNode'},
    -      childNode1 = $dom('div', null,
    -          gChildWsNode1 = $text(' \t\r\n'),
    -          gChildTextNode1 = $text('Child node'),
    -          gChildNbspNode1 = $text('\u00a0'),
    -          gChildMixedNode1 = $text('Text\n plus\u00a0')),
    -      childNode2 = $dom('div', null,
    -          gChildWsNode2a = $text(''),
    -          gChildWsNode2b = $text(' ')),
    -      childNode3 = $dom('div', null,
    -          gChildTextNode3a = $text('I am a grand child'),
    -          gChildWsNode3 = $text('   \t  \r   \n'),
    -          gChildTextNode3b = $text('I am also a grand child')));
    -
    -  document.body.appendChild(parentNode);
    -}
    -
    -function tearDownGetNodeFunctions() {
    -  document.body.removeChild(parentNode);
    -
    -  parentNode = null;
    -  childNode1 = null;
    -  childNode2 = null;
    -  childNode3 = null;
    -  gChildWsNode1 = null;
    -  gChildTextNode1 = null;
    -  gChildNbspNode1 = null;
    -  gChildMixedNode1 = null;
    -  gChildWsNode2a = null;
    -  gChildWsNode2b = null;
    -  gChildTextNode3a = null;
    -  gChildWsNode3 = null;
    -  gChildTextNode3b = null;
    -}
    -
    -
    -/**
    - * Test isBlockLevel with a node that is block style and a node that is not
    - */
    -function testIsDisplayBlock() {
    -  assertTrue('Body is block style',
    -      goog.editor.style.isDisplayBlock(document.body));
    -  var tableNode = $dom('table');
    -  assertFalse('Table is not block style',
    -      goog.editor.style.isDisplayBlock(tableNode));
    -}
    -
    -
    -/**
    - * Test that isContainer returns true when the node is of non-inline HTML and
    - * false when it is not
    - */
    -function testIsContainer() {
    -  var tableNode = $dom('table');
    -  var liNode = $dom('li');
    -  var textNode = $text('I am text');
    -  document.body.appendChild(textNode);
    -
    -  assertTrue('Table is a container',
    -      goog.editor.style.isContainer(tableNode));
    -  assertTrue('Body is a container',
    -      goog.editor.style.isContainer(document.body));
    -  assertTrue('List item is a container',
    -      goog.editor.style.isContainer(liNode));
    -  assertFalse('Text node is not a container',
    -      goog.editor.style.isContainer(textNode));
    -}
    -
    -
    -/**
    - * Test that getContainer properly returns the node itself if it is a
    - * container, an ancestor node if it is a container, and null otherwise
    - */
    -function testGetContainer() {
    -  setUpGetNodeFunctions();
    -  assertEquals('Should return self', childNode1,
    -      goog.editor.style.getContainer(childNode1));
    -  assertEquals('Should return parent', childNode1,
    -      goog.editor.style.getContainer(gChildWsNode1));
    -  assertNull('Document has no ancestors',
    -      goog.editor.style.getContainer(document));
    -  tearDownGetNodeFunctions();
    -}
    -
    -
    -function testMakeUnselectable() {
    -  var div = goog.dom.createElement(goog.dom.TagName.DIV);
    -  div.innerHTML =
    -      '<div>No input</div>' +
    -      '<p><input type="checkbox">Checkbox</p>' +
    -      '<span><input type="text"></span>';
    -  document.body.appendChild(div);
    -
    -  var eventHandler = new goog.testing.LooseMock(goog.events.EventHandler);
    -  if (goog.editor.BrowserFeature.HAS_UNSELECTABLE_STYLE) {
    -    eventHandler.listen(div, goog.events.EventType.MOUSEDOWN,
    -        goog.testing.mockmatchers.isFunction, true);
    -  }
    -  eventHandler.$replay();
    -
    -
    -  var childDiv = div.firstChild;
    -  var p = div.childNodes[1];
    -  var span = div.lastChild;
    -  var checkbox = p.firstChild;
    -  var text = span.firstChild;
    -
    -  goog.editor.style.makeUnselectable(div, eventHandler);
    -
    -  assertEquals(
    -      'For browsers with non-overridable selectability, the root should be ' +
    -      'selectable.  Otherwise it should be unselectable.',
    -      !goog.editor.BrowserFeature.HAS_UNSELECTABLE_STYLE,
    -      goog.style.isUnselectable(div));
    -  assertTrue(goog.style.isUnselectable(childDiv));
    -  assertTrue(goog.style.isUnselectable(p));
    -  assertTrue(goog.style.isUnselectable(checkbox));
    -
    -  assertEquals(
    -      'For browsers with non-overridable selectability, the span will be ' +
    -      'selectable.  Otherwise it will be unselectable. ',
    -      !goog.editor.BrowserFeature.HAS_UNSELECTABLE_STYLE,
    -      goog.style.isUnselectable(span));
    -  assertFalse(goog.style.isUnselectable(text));
    -
    -  eventHandler.$verify();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/table.js b/src/database/third_party/closure-library/closure/goog/editor/table.js
    deleted file mode 100644
    index 602e5f1045b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/table.js
    +++ /dev/null
    @@ -1,570 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Table editing support.
    - * This file provides the class goog.editor.Table and two
    - * supporting classes, goog.editor.TableRow and
    - * goog.editor.TableCell. Together these provide support for
    - * high level table modifications: Adding and deleting rows and columns,
    - * and merging and splitting cells.
    - *
    - * @supported IE6+, WebKit 525+, Firefox 2+.
    - */
    -
    -goog.provide('goog.editor.Table');
    -goog.provide('goog.editor.TableCell');
    -goog.provide('goog.editor.TableRow');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.DomHelper');
    -goog.require('goog.dom.NodeType');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.log');
    -goog.require('goog.string.Unicode');
    -goog.require('goog.style');
    -
    -
    -
    -/**
    - * Class providing high level table editing functions.
    - * @param {Element} node Element that is a table or descendant of a table.
    - * @constructor
    - * @final
    - */
    -goog.editor.Table = function(node) {
    -  this.element = goog.dom.getAncestorByTagNameAndClass(node,
    -      goog.dom.TagName.TABLE);
    -  if (!this.element) {
    -    goog.log.error(this.logger_,
    -        "Can't create Table based on a node " +
    -        "that isn't a table, or descended from a table.");
    -  }
    -  this.dom_ = goog.dom.getDomHelper(this.element);
    -  this.refresh();
    -};
    -
    -
    -/**
    - * Logger object for debugging and error messages.
    - * @type {goog.log.Logger}
    - * @private
    - */
    -goog.editor.Table.prototype.logger_ =
    -    goog.log.getLogger('goog.editor.Table');
    -
    -
    -/**
    - * Walks the dom structure of this object's table element and populates
    - * this.rows with goog.editor.TableRow objects. This is done initially
    - * to populate the internal data structures, and also after each time the
    - * DOM structure is modified. Currently this means that the all existing
    - * information is discarded and re-read from the DOM.
    - */
    -// TODO(user): support partial refresh to save cost of full update
    -// every time there is a change to the DOM.
    -goog.editor.Table.prototype.refresh = function() {
    -  var rows = this.rows = [];
    -  var tbody = this.element.getElementsByTagName(goog.dom.TagName.TBODY)[0];
    -  if (!tbody) {
    -    return;
    -  }
    -  var trs = [];
    -  for (var child = tbody.firstChild; child; child = child.nextSibling) {
    -    if (child.nodeName == goog.dom.TagName.TR) {
    -      trs.push(child);
    -    }
    -  }
    -
    -  for (var rowNum = 0, tr; tr = trs[rowNum]; rowNum++) {
    -    var existingRow = rows[rowNum];
    -    var tds = goog.editor.Table.getChildCellElements(tr);
    -    var columnNum = 0;
    -    // A note on cellNum vs. columnNum: A cell is a td/th element. Cells may
    -    // use colspan/rowspan to extend over multiple rows/columns. cellNum
    -    // is the dom element number, columnNum is the logical column number.
    -    for (var cellNum = 0, td; td = tds[cellNum]; cellNum++) {
    -      // If there's already a cell extending into this column
    -      // (due to that cell's colspan/rowspan), increment the column counter.
    -      while (existingRow && existingRow.columns[columnNum]) {
    -        columnNum++;
    -      }
    -      var cell = new goog.editor.TableCell(td, rowNum, columnNum);
    -      // Place this cell in every row and column into which it extends.
    -      for (var i = 0; i < cell.rowSpan; i++) {
    -        var cellRowNum = rowNum + i;
    -        // Create TableRow objects in this.rows as needed.
    -        var cellRow = rows[cellRowNum];
    -        if (!cellRow) {
    -          // TODO(user): try to avoid second trs[] lookup.
    -          rows.push(
    -              cellRow = new goog.editor.TableRow(trs[cellRowNum], cellRowNum));
    -        }
    -        // Extend length of column array to make room for this cell.
    -        var minimumColumnLength = columnNum + cell.colSpan;
    -        if (cellRow.columns.length < minimumColumnLength) {
    -          cellRow.columns.length = minimumColumnLength;
    -        }
    -        for (var j = 0; j < cell.colSpan; j++) {
    -          var cellColumnNum = columnNum + j;
    -          cellRow.columns[cellColumnNum] = cell;
    -        }
    -      }
    -      columnNum += cell.colSpan;
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Returns all child elements of a TR element that are of type TD or TH.
    - * @param {Element} tr TR element in which to find children.
    - * @return {!Array<Element>} array of child cell elements.
    - */
    -goog.editor.Table.getChildCellElements = function(tr) {
    -  var cells = [];
    -  for (var i = 0, cell; cell = tr.childNodes[i]; i++) {
    -    if (cell.nodeName == goog.dom.TagName.TD ||
    -        cell.nodeName == goog.dom.TagName.TH) {
    -      cells.push(cell);
    -    }
    -  }
    -  return cells;
    -};
    -
    -
    -/**
    - * Inserts a new row in the table. The row will be populated with new
    - * cells, and existing rowspanned cells that overlap the new row will
    - * be extended.
    - * @param {number=} opt_rowIndex Index at which to insert the row. If
    - *     this is omitted the row will be appended to the end of the table.
    - * @return {!Element} The new row.
    - */
    -goog.editor.Table.prototype.insertRow = function(opt_rowIndex) {
    -  var rowIndex = goog.isDefAndNotNull(opt_rowIndex) ?
    -      opt_rowIndex : this.rows.length;
    -  var refRow;
    -  var insertAfter;
    -  if (rowIndex == 0) {
    -    refRow = this.rows[0];
    -    insertAfter = false;
    -  } else {
    -    refRow = this.rows[rowIndex - 1];
    -    insertAfter = true;
    -  }
    -  var newTr = this.dom_.createElement('tr');
    -  for (var i = 0, cell; cell = refRow.columns[i]; i += 1) {
    -    // Check whether the existing cell will span this new row.
    -    // If so, instead of creating a new cell, extend
    -    // the rowspan of the existing cell.
    -    if ((insertAfter && cell.endRow > rowIndex) ||
    -        (!insertAfter && cell.startRow < rowIndex)) {
    -      cell.setRowSpan(cell.rowSpan + 1);
    -      if (cell.colSpan > 1) {
    -        i += cell.colSpan - 1;
    -      }
    -    } else {
    -      newTr.appendChild(this.createEmptyTd());
    -    }
    -    if (insertAfter) {
    -      goog.dom.insertSiblingAfter(newTr, refRow.element);
    -    } else {
    -      goog.dom.insertSiblingBefore(newTr, refRow.element);
    -    }
    -  }
    -  this.refresh();
    -  return newTr;
    -};
    -
    -
    -/**
    - * Inserts a new column in the table. The column will be created by
    - * inserting new TD elements in each row, or extending the colspan
    - * of existing TD elements.
    - * @param {number=} opt_colIndex Index at which to insert the column. If
    - *     this is omitted the column will be appended to the right side of
    - *     the table.
    - * @return {!Array<Element>} Array of new cell elements that were created
    - *     to populate the new column.
    - */
    -goog.editor.Table.prototype.insertColumn = function(opt_colIndex) {
    -  // TODO(user): set column widths in a way that makes sense.
    -  var colIndex = goog.isDefAndNotNull(opt_colIndex) ?
    -      opt_colIndex :
    -      (this.rows[0] && this.rows[0].columns.length) || 0;
    -  var newTds = [];
    -  for (var rowNum = 0, row; row = this.rows[rowNum]; rowNum++) {
    -    var existingCell = row.columns[colIndex];
    -    if (existingCell && existingCell.endCol >= colIndex &&
    -        existingCell.startCol < colIndex) {
    -      existingCell.setColSpan(existingCell.colSpan + 1);
    -      rowNum += existingCell.rowSpan - 1;
    -    } else {
    -      var newTd = this.createEmptyTd();
    -      // TODO(user): figure out a way to intelligently size new columns.
    -      newTd.style.width = goog.editor.Table.OPTIMUM_EMPTY_CELL_WIDTH + 'px';
    -      this.insertCellElement(newTd, rowNum, colIndex);
    -      newTds.push(newTd);
    -    }
    -  }
    -  this.refresh();
    -  return newTds;
    -};
    -
    -
    -/**
    - * Removes a row from the table, removing the TR element and
    - * decrementing the rowspan of any cells in other rows that overlap the row.
    - * @param {number} rowIndex Index of the row to delete.
    - */
    -goog.editor.Table.prototype.removeRow = function(rowIndex) {
    -  var row = this.rows[rowIndex];
    -  if (!row) {
    -    goog.log.warning(this.logger_,
    -        "Can't remove row at position " + rowIndex + ': no such row.');
    -  }
    -  for (var i = 0, cell; cell = row.columns[i]; i += cell.colSpan) {
    -    if (cell.rowSpan > 1) {
    -      cell.setRowSpan(cell.rowSpan - 1);
    -      if (cell.startRow == rowIndex) {
    -        // Rowspanned cell started in this row - move it down to the next row.
    -        this.insertCellElement(cell.element, rowIndex + 1, cell.startCol);
    -      }
    -    }
    -  }
    -  row.element.parentNode.removeChild(row.element);
    -  this.refresh();
    -};
    -
    -
    -/**
    - * Removes a column from the table. This is done by removing cell elements,
    - * or shrinking the colspan of elements that span multiple columns.
    - * @param {number} colIndex Index of the column to delete.
    - */
    -goog.editor.Table.prototype.removeColumn = function(colIndex) {
    -  for (var i = 0, row; row = this.rows[i]; i++) {
    -    var cell = row.columns[colIndex];
    -    if (!cell) {
    -      goog.log.error(this.logger_,
    -          "Can't remove cell at position " + i + ', ' + colIndex +
    -          ': no such cell.');
    -    }
    -    if (cell.colSpan > 1) {
    -      cell.setColSpan(cell.colSpan - 1);
    -    } else {
    -      cell.element.parentNode.removeChild(cell.element);
    -    }
    -    // Skip over following rows that contain this same cell.
    -    i += cell.rowSpan - 1;
    -  }
    -  this.refresh();
    -};
    -
    -
    -/**
    - * Merges multiple cells into a single cell, and sets the rowSpan and colSpan
    - * attributes of the cell to take up the same space as the original cells.
    - * @param {number} startRowIndex Top coordinate of the cells to merge.
    - * @param {number} startColIndex Left coordinate of the cells to merge.
    - * @param {number} endRowIndex Bottom coordinate of the cells to merge.
    - * @param {number} endColIndex Right coordinate of the cells to merge.
    - * @return {boolean} Whether or not the merge was possible. If the cells
    - *     in the supplied coordinates can't be merged this will return false.
    - */
    -goog.editor.Table.prototype.mergeCells = function(
    -    startRowIndex, startColIndex, endRowIndex, endColIndex) {
    -  // TODO(user): take a single goog.math.Rect parameter instead?
    -  var cells = [];
    -  var cell;
    -  if (startRowIndex == endRowIndex && startColIndex == endColIndex) {
    -    goog.log.warning(this.logger_, "Can't merge single cell");
    -    return false;
    -  }
    -  // Gather cells and do sanity check.
    -  for (var i = startRowIndex; i <= endRowIndex; i++) {
    -    for (var j = startColIndex; j <= endColIndex; j++) {
    -      cell = this.rows[i].columns[j];
    -      if (cell.startRow < startRowIndex ||
    -          cell.endRow > endRowIndex ||
    -          cell.startCol < startColIndex ||
    -          cell.endCol > endColIndex) {
    -        goog.log.warning(this.logger_,
    -            "Can't merge cells: the cell in row " + i + ', column ' + j +
    -            'extends outside the supplied rectangle.');
    -        return false;
    -      }
    -      // TODO(user): this is somewhat inefficient, as we will add
    -      // a reference for a cell for each position, even if it's a single
    -      // cell with row/colspan.
    -      cells.push(cell);
    -    }
    -  }
    -  var targetCell = cells[0];
    -  var targetTd = targetCell.element;
    -  var doc = this.dom_.getDocument();
    -
    -  // Merge cell contents and discard other cells.
    -  for (var i = 1; cell = cells[i]; i++) {
    -    var td = cell.element;
    -    if (!td.parentNode || td == targetTd) {
    -      // We've already handled this cell at one of its previous positions.
    -      continue;
    -    }
    -    // Add a space if needed, to keep merged content from getting squished
    -    // together.
    -    if (targetTd.lastChild &&
    -        targetTd.lastChild.nodeType == goog.dom.NodeType.TEXT) {
    -      targetTd.appendChild(doc.createTextNode(' '));
    -    }
    -    var childNode;
    -    while ((childNode = td.firstChild)) {
    -      targetTd.appendChild(childNode);
    -    }
    -    td.parentNode.removeChild(td);
    -  }
    -  targetCell.setColSpan((endColIndex - startColIndex) + 1);
    -  targetCell.setRowSpan((endRowIndex - startRowIndex) + 1);
    -  if (endColIndex > startColIndex) {
    -    // Clear width on target cell.
    -    // TODO(user): instead of clearing width, calculate width
    -    // based on width of input cells
    -    targetTd.removeAttribute('width');
    -    targetTd.style.width = null;
    -  }
    -  this.refresh();
    -
    -  return true;
    -};
    -
    -
    -/**
    - * Splits a cell with colspans or rowspans into multiple descrete cells.
    - * @param {number} rowIndex y coordinate of the cell to split.
    - * @param {number} colIndex x coordinate of the cell to split.
    - * @return {!Array<Element>} Array of new cell elements created by splitting
    - *     the cell.
    - */
    -// TODO(user): support splitting only horizontally or vertically,
    -// support splitting cells that aren't already row/colspanned.
    -goog.editor.Table.prototype.splitCell = function(rowIndex, colIndex) {
    -  var row = this.rows[rowIndex];
    -  var cell = row.columns[colIndex];
    -  var newTds = [];
    -  for (var i = 0; i < cell.rowSpan; i++) {
    -    for (var j = 0; j < cell.colSpan; j++) {
    -      if (i > 0 || j > 0) {
    -        var newTd = this.createEmptyTd();
    -        this.insertCellElement(newTd, rowIndex + i, colIndex + j);
    -        newTds.push(newTd);
    -      }
    -    }
    -  }
    -  cell.setColSpan(1);
    -  cell.setRowSpan(1);
    -  this.refresh();
    -  return newTds;
    -};
    -
    -
    -/**
    - * Inserts a cell element at the given position. The colIndex is the logical
    - * column index, not the position in the dom. This takes into consideration
    - * that cells in a given logical  row may actually be children of a previous
    - * DOM row that have used rowSpan to extend into the row.
    - * @param {Element} td The new cell element to insert.
    - * @param {number} rowIndex Row in which to insert the element.
    - * @param {number} colIndex Column in which to insert the element.
    - */
    -goog.editor.Table.prototype.insertCellElement = function(
    -    td, rowIndex, colIndex) {
    -  var row = this.rows[rowIndex];
    -  var nextSiblingElement = null;
    -  for (var i = colIndex, cell; cell = row.columns[i]; i += cell.colSpan) {
    -    if (cell.startRow == rowIndex) {
    -      nextSiblingElement = cell.element;
    -      break;
    -    }
    -  }
    -  row.element.insertBefore(td, nextSiblingElement);
    -};
    -
    -
    -/**
    - * Creates an empty TD element and fill it with some empty content so it will
    - * show up with borders even in IE pre-7 or if empty-cells is set to 'hide'
    - * @return {!Element} a new TD element.
    - */
    -goog.editor.Table.prototype.createEmptyTd = function() {
    -  // TODO(user): more cross-browser testing to determine best
    -  // and least annoying filler content.
    -  return this.dom_.createDom(goog.dom.TagName.TD, {}, goog.string.Unicode.NBSP);
    -};
    -
    -
    -
    -/**
    - * Class representing a logical table row: a tr element and any cells
    - * that appear in that row.
    - * @param {Element} trElement This rows's underlying TR element.
    - * @param {number} rowIndex This row's index in its parent table.
    - * @constructor
    - * @final
    - */
    -goog.editor.TableRow = function(trElement, rowIndex) {
    -  this.index = rowIndex;
    -  this.element = trElement;
    -  this.columns = [];
    -};
    -
    -
    -
    -/**
    - * Class representing a table cell, which may span across multiple
    - * rows and columns
    - * @param {Element} td This cell's underlying TD or TH element.
    - * @param {number} startRow Index of the row where this cell begins.
    - * @param {number} startCol Index of the column where this cell begins.
    - * @constructor
    - * @final
    - */
    -goog.editor.TableCell = function(td, startRow, startCol) {
    -  this.element = td;
    -  this.colSpan = parseInt(td.colSpan, 10) || 1;
    -  this.rowSpan = parseInt(td.rowSpan, 10) || 1;
    -  this.startRow = startRow;
    -  this.startCol = startCol;
    -  this.updateCoordinates_();
    -};
    -
    -
    -/**
    - * Calculates this cell's endRow/endCol coordinates based on rowSpan/colSpan
    - * @private
    - */
    -goog.editor.TableCell.prototype.updateCoordinates_ = function() {
    -  this.endCol = this.startCol + this.colSpan - 1;
    -  this.endRow = this.startRow + this.rowSpan - 1;
    -};
    -
    -
    -/**
    - * Set this cell's colSpan, updating both its colSpan property and the
    - * underlying element's colSpan attribute.
    - * @param {number} colSpan The new colSpan.
    - */
    -goog.editor.TableCell.prototype.setColSpan = function(colSpan) {
    -  if (colSpan != this.colSpan) {
    -    if (colSpan > 1) {
    -      this.element.colSpan = colSpan;
    -    } else {
    -      this.element.colSpan = 1,
    -      this.element.removeAttribute('colSpan');
    -    }
    -    this.colSpan = colSpan;
    -    this.updateCoordinates_();
    -  }
    -};
    -
    -
    -/**
    - * Set this cell's rowSpan, updating both its rowSpan property and the
    - * underlying element's rowSpan attribute.
    - * @param {number} rowSpan The new rowSpan.
    - */
    -goog.editor.TableCell.prototype.setRowSpan = function(rowSpan) {
    -  if (rowSpan != this.rowSpan) {
    -    if (rowSpan > 1) {
    -      this.element.rowSpan = rowSpan.toString();
    -    } else {
    -      this.element.rowSpan = '1';
    -      this.element.removeAttribute('rowSpan');
    -    }
    -    this.rowSpan = rowSpan;
    -    this.updateCoordinates_();
    -  }
    -};
    -
    -
    -/**
    - * Optimum size of empty cells (in pixels), if possible.
    - * @type {number}
    - */
    -goog.editor.Table.OPTIMUM_EMPTY_CELL_WIDTH = 60;
    -
    -
    -/**
    - * Maximum width for new tables.
    - * @type {number}
    - */
    -goog.editor.Table.OPTIMUM_MAX_NEW_TABLE_WIDTH = 600;
    -
    -
    -/**
    - * Default color for table borders.
    - * @type {string}
    - */
    -goog.editor.Table.DEFAULT_BORDER_COLOR = '#888';
    -
    -
    -/**
    - * Creates a new table element, populated with cells and formatted.
    - * @param {Document} doc Document in which to create the table element.
    - * @param {number} columns Number of columns in the table.
    - * @param {number} rows Number of rows in the table.
    - * @param {Object=} opt_tableStyle Object containing borderWidth and borderColor
    - *    properties, used to set the inital style of the table.
    - * @return {!Element} a table element.
    - */
    -goog.editor.Table.createDomTable = function(
    -    doc, columns, rows, opt_tableStyle) {
    -  // TODO(user): define formatting properties as constants,
    -  // make separate formatTable() function
    -  var style = {
    -    borderWidth: '1',
    -    borderColor: goog.editor.Table.DEFAULT_BORDER_COLOR
    -  };
    -  for (var prop in opt_tableStyle) {
    -    style[prop] = opt_tableStyle[prop];
    -  }
    -  var dom = new goog.dom.DomHelper(doc);
    -  var tableElement = dom.createTable(rows, columns, true);
    -
    -  var minimumCellWidth = 10;
    -  // Calculate a good cell width.
    -  var cellWidth = Math.max(
    -      minimumCellWidth,
    -      Math.min(goog.editor.Table.OPTIMUM_EMPTY_CELL_WIDTH,
    -               goog.editor.Table.OPTIMUM_MAX_NEW_TABLE_WIDTH / columns));
    -
    -  var tds = tableElement.getElementsByTagName(goog.dom.TagName.TD);
    -  for (var i = 0, td; td = tds[i]; i++) {
    -    td.style.width = cellWidth + 'px';
    -  }
    -
    -  // Set border somewhat redundantly to make sure they show
    -  // up correctly in all browsers.
    -  goog.style.setStyle(
    -      tableElement, {
    -        'borderCollapse': 'collapse',
    -        'borderColor': style.borderColor,
    -        'borderWidth': style.borderWidth + 'px'
    -      });
    -  tableElement.border = style.borderWidth;
    -  tableElement.setAttribute('bordercolor', style.borderColor);
    -  tableElement.setAttribute('cellspacing', '0');
    -
    -  return tableElement;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/table_test.html b/src/database/third_party/closure-library/closure/goog/editor/table_test.html
    deleted file mode 100644
    index 936a78ca1cf..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/table_test.html
    +++ /dev/null
    @@ -1,185 +0,0 @@
    -<html>
    -</html>
    -<html>
    - <!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   table.js Tests
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.editor.TableTest');
    -  </script>
    -  <style>
    -   table {
    -      border:1px outset #777;
    -      margin-top: 1em;
    -      empty-cells: show;
    -    }
    -    td, th {
    -      border:1px inset #777;
    -    }
    -  </style>
    - </head>
    - <body>
    -  <table id="test-basic">
    -   <tr>
    -    <th>
    -     Number
    -    </th>
    -    <th>
    -     Color
    -    </th>
    -    <th>
    -     Speed
    -    </th>
    -   </tr>
    -   <tr>
    -    <td>
    -     One
    -    </td>
    -    <td>
    -     Red
    -    </td>
    -    <td>
    -     60
    -    </td>
    -   </tr>
    -   <tr>
    -    <td>
    -     Two
    -    </td>
    -    <td>
    -     Blue
    -    </td>
    -    <td>
    -     75
    -    </td>
    -   </tr>
    -   <tr>
    -    <td>
    -     Three
    -    </td>
    -    <td>
    -     Orange
    -    </td>
    -    <td>
    -     88
    -    </td>
    -   </tr>
    -  </table>
    -  <table id="test-torture">
    -   <tr>
    -    <th rowspan="2">
    -     Left 0+1
    -     <br />
    -     &nbsp;
    -    </th>
    -    <th colspan="2">
    -     Middle, Right 0
    -    </th>
    -   </tr>
    -   <tr>
    -    <td colspan="2" rowspan="2">
    -     Middle, Right 1 + 2
    -     <br />
    -     &nbsp;
    -    </td>
    -   </tr>
    -   <tr>
    -    <th>
    -     Left 2
    -    </th>
    -   </tr>
    -   <tr>
    -    <th>
    -     Left 3
    -    </th>
    -    <td>
    -     Middle 3
    -    </td>
    -    <td>
    -     Right 3
    -    </td>
    -   </tr>
    -   <tr>
    -    <th colspan="3">
    -     Left, Middle, Right 4
    -    </th>
    -   </tr>
    -   <tr>
    -    <th colspan="2" rowspan="2">
    -     Left, Middle 5+6
    -     <br />
    -     &nbsp;
    -    </th>
    -    <td rowspan="4">
    -     Right 5+6+7+8
    -    </td>
    -   </tr>
    -   <tr>
    -   </tr>
    -   <tr>
    -    <th rowspan="2">
    -     Left 7+8
    -    </th>
    -    <td>
    -     Middle 7
    -    </td>
    -   </tr>
    -   <tr>
    -    <td>
    -     Middle 8
    -    </td>
    -   </tr>
    -  </table>
    -  <table id="test-nested">
    -   <tr>
    -    <td>
    -     One
    -    </td>
    -    <td>
    -     Two
    -    </td>
    -    <td>
    -     <table>
    -      <tr>
    -       <td>
    -        Nested cell 1
    -       </td>
    -       <td>
    -        Nested cell 2
    -       </td>
    -      </tr>
    -      <tr>
    -       <td>
    -        Nested cell 2
    -       </td>
    -       <td>
    -        Nested cell 3
    -       </td>
    -      </tr>
    -     </table>
    -    </td>
    -   </tr>
    -   <tr>
    -    <td>
    -     Four
    -    </td>
    -    <td>
    -     Five
    -    </td>
    -    <td>
    -     Six
    -    </td>
    -   </tr>
    -  </table>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/editor/table_test.js b/src/database/third_party/closure-library/closure/goog/editor/table_test.js
    deleted file mode 100644
    index 52fc654601a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/editor/table_test.js
    +++ /dev/null
    @@ -1,482 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.editor.TableTest');
    -goog.setTestOnly('goog.editor.TableTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.editor.Table');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -function setUp() {
    -  var inputTables = document.getElementsByTagName('table');
    -  testElements = {};
    -  testObjects = {};
    -  for (var i = 0; i < inputTables.length; i++) {
    -    var originalTable = inputTables[i];
    -    if (originalTable.id.substring(0, 5) == 'test-') {
    -      var tableName = originalTable.id.substring(5);
    -      var testTable = originalTable.cloneNode(true);
    -      testTable.id = tableName;
    -      testElements[tableName] = testTable;
    -      document.body.appendChild(testTable);
    -      testObjects[tableName] = new goog.editor.Table(testTable);
    -    }
    -  }
    -}
    -
    -function tearDown() {
    -  for (var tableName in testElements) {
    -    document.body.removeChild(testElements[tableName]);
    -    delete testElements[tableName];
    -    delete testObjects[tableName];
    -  }
    -  testElements = null;
    -  testObjects = null;
    -}
    -
    -// These tests don't pass on Safari, because the table editor only works
    -// on IE and FF right now.
    -// TODO(nicksantos): Fix this.
    -if (!goog.userAgent.WEBKIT) {
    -
    -  function tableSanityCheck(editableTable, rowCount, colCount) {
    -    assertEquals('Table has expected number of rows',
    -        rowCount, editableTable.rows.length);
    -    for (var i = 0, row; row = editableTable.rows[i]; i++) {
    -      assertEquals('Row ' + i + ' has expected number of columns',
    -          colCount, row.columns.length);
    -    }
    -  }
    -
    -  function testBasicTable() {
    -    // Do some basic sanity checking on the editable table structure
    -    tableSanityCheck(testObjects.basic, 4, 3);
    -    var originalRows = testElements.basic.getElementsByTagName('tr');
    -    assertEquals('Basic table row count, compared to source',
    -        originalRows.length, testObjects.basic.rows.length);
    -    assertEquals('Basic table row count, known value',
    -        4, testObjects.basic.rows.length);
    -    assertEquals('Basic table first row element',
    -        originalRows[0], testObjects.basic.rows[0].element);
    -    assertEquals('Basic table last row element',
    -        originalRows[3], testObjects.basic.rows[3].element);
    -    assertEquals('Basic table first row length',
    -        3, testObjects.basic.rows[0].columns.length);
    -    assertEquals('Basic table last row length',
    -        3, testObjects.basic.rows[3].columns.length);
    -  }
    -
    -  function testTortureTable() {
    -    // Do basic sanity checking on torture table structure
    -    tableSanityCheck(testObjects.torture, 9, 3);
    -    var originalRows = testElements.torture.getElementsByTagName('tr');
    -    assertEquals('Torture table row count, compared to source',
    -        originalRows.length, testObjects.torture.rows.length);
    -    assertEquals('Torture table row count, known value',
    -        9, testObjects.torture.rows.length);
    -  }
    -
    -  function _testInsertRowResult(element, editableTable,  newTr, index) {
    -    if (element == testElements.basic) {
    -      originalRowCount = 4;
    -    } else if (element == testElements.torture) {
    -      originalRowCount = 9;
    -    }
    -
    -    assertEquals('Row was added to table',
    -        originalRowCount + 1, element.getElementsByTagName('tr').length);
    -    assertEquals('Row was added at position ' + index,
    -        element.getElementsByTagName('tr')[index], newTr);
    -    assertEquals('Row knows its own position',
    -        index, editableTable.rows[index].index);
    -    assertEquals('EditableTable shows row at position ' + index,
    -        newTr, editableTable.rows[index].element);
    -    assertEquals('New row has correct number of TDs',
    -        3, newTr.getElementsByTagName('td').length);
    -  }
    -
    -  function testInsertRowAtBeginning() {
    -    var tr = testObjects.basic.insertRow(0);
    -    _testInsertRowResult(testElements.basic, testObjects.basic, tr, 0);
    -  }
    -
    -  function testInsertRowInMiddle() {
    -    var tr = testObjects.basic.insertRow(2);
    -    _testInsertRowResult(testElements.basic, testObjects.basic, tr, 2);
    -  }
    -
    -  function testInsertRowAtEnd() {
    -    assertEquals('Table has expected number of existing rows',
    -        4, testObjects.basic.rows.length);
    -    var tr = testObjects.basic.insertRow(4);
    -    _testInsertRowResult(testElements.basic, testObjects.basic, tr, 4);
    -  }
    -
    -  function testInsertRowAtEndNoIndexArgument() {
    -    assertEquals('Table has expected number of existing rows',
    -        4, testObjects.basic.rows.length);
    -    var tr = testObjects.basic.insertRow();
    -    _testInsertRowResult(testElements.basic, testObjects.basic, tr, 4);
    -  }
    -
    -  function testInsertRowAtBeginningRowspan() {
    -    // Test inserting a row when the existing DOM row at that index has
    -    // a cell with a rowspan. This should be just like a regular insert -
    -    // the rowspan shouldn't have any effect.
    -    assertEquals('Cell has starting rowspan',
    -        2,
    -        goog.dom.getFirstElementChild(
    -        testElements.torture.getElementsByTagName('tr')[0]).rowSpan);
    -    var tr = testObjects.torture.insertRow(0);
    -    // Among other things this verifies that the new row has 3 child TDs.
    -    _testInsertRowResult(testElements.torture, testObjects.torture, tr, 0);
    -  }
    -
    -  function testInsertRowAtEndingRowspan() {
    -    // Test inserting a row when there's a cell in a previous DOM row
    -    // with a rowspan that extends into the row with the given index
    -    // and ends there. This should be just like a regular insert -
    -    // the rowspan shouldn't have any effect.
    -    assertEquals('Cell has ending rowspan',
    -        4,
    -        goog.dom.getLastElementChild(
    -        testElements.torture.getElementsByTagName('tr')[5]).rowSpan);
    -    var tr = testObjects.torture.insertRow();
    -    // Among other things this verifies that the new row has 3 child TDs.
    -    _testInsertRowResult(testElements.torture, testObjects.torture, tr, 9);
    -  }
    -
    -  function testInsertRowAtSpanningRowspan() {
    -    // Test inserting a row at an index where there's a cell with a rowspan
    -    // that begins in a previous row and continues into the next row. In this
    -    // case the existing cell's rowspan should be extended, and the new
    -    // tr should have one less child element.
    -    var rowSpannedCell = testObjects.torture.rows[7].columns[2];
    -    assertTrue('Existing cell has overlapping rowspan',
    -        rowSpannedCell.startRow == 5 && rowSpannedCell.endRow == 8);
    -    var tr = testObjects.torture.insertRow(7);
    -    assertEquals('New DOM row has one less cell',
    -        2, tr.getElementsByTagName('td').length);
    -    assertEquals('Rowspanned cell listed in new EditableRow\'s columns',
    -        testObjects.torture.rows[6].columns[2].element,
    -        testObjects.torture.rows[7].columns[2].element);
    -  }
    -
    -  function _testInsertColumnResult(newCells, element, editableTable, index) {
    -    for (var rowNo = 0, row; row = editableTable.rows[rowNo]; rowNo++) {
    -      assertEquals('Row includes new column',
    -          4, row.columns.length);
    -    }
    -    assertEquals('New cell in correct position',
    -        newCells[0], editableTable.rows[0].columns[index].element);
    -  }
    -
    -  function testInsertColumnAtBeginning() {
    -    var startColCount = testObjects.basic.rows[0].columns.length;
    -    var newCells = testObjects.basic.insertColumn(0);
    -    assertEquals('New cell added for each row',
    -        testObjects.basic.rows.length, newCells.length);
    -    assertEquals('Insert column incremented column length',
    -        startColCount + 1, testObjects.basic.rows[0].columns.length);
    -    _testInsertColumnResult(newCells, testElements.basic, testObjects.basic, 0);
    -  }
    -
    -  function testInsertColumnAtEnd() {
    -    var startColCount = testObjects.basic.rows[0].columns.length;
    -    var newCells = testObjects.basic.insertColumn(3);
    -    assertEquals('New cell added for each row',
    -        testObjects.basic.rows.length, newCells.length);
    -    assertEquals('Insert column incremented column length',
    -        startColCount + 1, testObjects.basic.rows[0].columns.length);
    -    _testInsertColumnResult(newCells, testElements.basic, testObjects.basic, 3);
    -  }
    -
    -  function testInsertColumnAtEndNoIndexArgument() {
    -    var startColCount = testObjects.basic.rows[0].columns.length;
    -    var newCells = testObjects.basic.insertColumn();
    -    assertEquals('New cell added for each row',
    -        testObjects.basic.rows.length, newCells.length);
    -    assertEquals('Insert column incremented column length',
    -        startColCount + 1, testObjects.basic.rows[0].columns.length);
    -    _testInsertColumnResult(newCells, testElements.basic, testObjects.basic, 3);
    -  }
    -
    -  function testInsertColumnInMiddle() {
    -    var startColCount = testObjects.basic.rows[0].columns.length;
    -    var newCells = testObjects.basic.insertColumn(2);
    -    assertEquals('New cell added for each row',
    -        testObjects.basic.rows.length, newCells.length);
    -    assertEquals('Insert column incremented column length',
    -        startColCount + 1, testObjects.basic.rows[0].columns.length);
    -    _testInsertColumnResult(newCells, testElements.basic, testObjects.basic, 2);
    -  }
    -
    -  function testInsertColumnAtBeginning() {
    -    var startColCount = testObjects.basic.rows[0].columns.length;
    -    var newCells = testObjects.basic.insertColumn(0);
    -    assertEquals('Insert column incremented column length',
    -        startColCount + 1, testObjects.basic.rows[0].columns.length);
    -    _testInsertColumnResult(newCells, testElements.basic, testObjects.basic, 0);
    -  }
    -
    -  function testInsertColumnAtBeginningColSpan() {
    -    var cells = testObjects.torture.insertColumn(0);
    -    tableSanityCheck(testObjects.torture, 9, 4);
    -    assertEquals('New cell was added before colspanned cell',
    -        1, testObjects.torture.rows[3].columns[0].colSpan);
    -    assertEquals('New cell was added and returned',
    -        testObjects.torture.rows[3].columns[0].element,
    -        cells[3]);
    -  }
    -
    -  function testInsertColumnAtEndingColSpan() {
    -    var cells = testObjects.torture.insertColumn();
    -    tableSanityCheck(testObjects.torture, 9, 4);
    -    assertEquals('New cell was added after colspanned cell',
    -        1, testObjects.torture.rows[0].columns[3].colSpan);
    -    assertEquals('New cell was added and returned',
    -        testObjects.torture.rows[0].columns[3].element,
    -        cells[0]);
    -  }
    -
    -  function testInsertColumnAtSpanningColSpan() {
    -    assertEquals('Existing cell has expected colspan',
    -        3, testObjects.torture.rows[4].columns[1].colSpan);
    -    var cells = testObjects.torture.insertColumn(1);
    -    tableSanityCheck(testObjects.torture, 9, 4);
    -    assertEquals('Existing cell increased colspan',
    -        4, testObjects.torture.rows[4].columns[1].colSpan);
    -    assertEquals('3 cells weren\'t created due to existing colspans',
    -        6, cells.length);
    -  }
    -
    -  function testRemoveFirstRow() {
    -    var originalRow = testElements.basic.getElementsByTagName('tr')[0];
    -    testObjects.basic.removeRow(0);
    -    tableSanityCheck(testObjects.basic, 3, 3);
    -    assertNotEquals('Row was removed from table element',
    -        originalRow, testElements.basic.getElementsByTagName('tr')[0]);
    -  }
    -
    -  function testRemoveLastRow() {
    -    var originalRow = testElements.basic.getElementsByTagName('tr')[3];
    -    testObjects.basic.removeRow(3);
    -    tableSanityCheck(testObjects.basic, 3, 3);
    -    assertNotEquals('Row was removed from table element',
    -        originalRow, testElements.basic.getElementsByTagName('tr')[3]);
    -  }
    -
    -  function testRemoveMiddleRow() {
    -    var originalRow = testElements.basic.getElementsByTagName('tr')[2];
    -    testObjects.basic.removeRow(2);
    -    tableSanityCheck(testObjects.basic, 3, 3);
    -    assertNotEquals('Row was removed from table element',
    -        originalRow, testElements.basic.getElementsByTagName('tr')[2]);
    -  }
    -
    -  function testRemoveRowAtBeginingRowSpan() {
    -    var originalRow = testObjects.torture.removeRow(0);
    -    tableSanityCheck(testObjects.torture, 8, 3);
    -    assertNotEquals('Row was removed from table element',
    -        originalRow, testElements.basic.getElementsByTagName('tr')[0]);
    -    assertEquals('Rowspan correctly adjusted',
    -        1, testObjects.torture.rows[0].columns[0].rowSpan);
    -  }
    -
    -  function testRemoveRowAtEndingRowSpan() {
    -    var originalRow = testElements.torture.getElementsByTagName('tr')[8];
    -    testObjects.torture.removeRow(8);
    -    tableSanityCheck(testObjects.torture, 8, 3);
    -    assertNotEquals('Row was removed from table element',
    -        originalRow, testElements.basic.getElementsByTagName('tr')[8]);
    -    assertEquals('Rowspan correctly adjusted',
    -        3, testObjects.torture.rows[7].columns[2].rowSpan);
    -  }
    -
    -  function testRemoveRowAtSpanningRowSpan() {
    -    var originalRow = testElements.torture.getElementsByTagName('tr')[7];
    -    testObjects.torture.removeRow(7);
    -    tableSanityCheck(testObjects.torture, 8, 3);
    -    assertNotEquals('Row was removed from table element',
    -        originalRow, testElements.basic.getElementsByTagName('tr')[7]);
    -    assertEquals('Rowspan correctly adjusted',
    -        3, testObjects.torture.rows[6].columns[2].rowSpan);
    -  }
    -
    -  function _testRemoveColumn(index) {
    -    var sampleCell = testElements.basic.getElementsByTagName(
    -        'tr')[0].getElementsByTagName('th')[index];
    -    testObjects.basic.removeColumn(index);
    -    tableSanityCheck(testObjects.basic, 4, 2);
    -    assertNotEquals(
    -        'Test cell removed from column',
    -        sampleCell,
    -        testElements.basic.getElementsByTagName(
    -        'tr')[0].getElementsByTagName('th')[index]);
    -  }
    -
    -  function testRemoveFirstColumn() {
    -    _testRemoveColumn(0);
    -  }
    -
    -  function testRemoveMiddleColumn() {
    -    _testRemoveColumn(1);
    -  }
    -
    -  function testRemoveLastColumn() {
    -    _testRemoveColumn(2);
    -  }
    -
    -  function testRemoveColumnAtStartingColSpan() {
    -    testObjects.torture.removeColumn(0);
    -    tableSanityCheck(testObjects.torture, 9, 2);
    -    assertEquals('Colspan was decremented correctly',
    -        1,
    -        testElements.torture.getElementsByTagName(
    -        'tr')[5].getElementsByTagName('th')[0].colSpan);
    -  }
    -
    -  function testRemoveColumnAtEndingColSpan() {
    -    testObjects.torture.removeColumn(2);
    -    tableSanityCheck(testObjects.torture, 9, 2);
    -    assertEquals('Colspan was decremented correctly',
    -        1,
    -        testElements.torture.getElementsByTagName(
    -        'tr')[1].getElementsByTagName('td')[0].colSpan);
    -  }
    -
    -  function testRemoveColumnAtSpanningColSpan() {
    -    testObjects.torture.removeColumn(2);
    -    tableSanityCheck(testObjects.torture, 9, 2);
    -    assertEquals('Colspan was decremented correctly',
    -        2,
    -        testElements.torture.getElementsByTagName(
    -        'tr')[4].getElementsByTagName('th')[0].colSpan);
    -  }
    -
    -  function testMergeCellsInRow() {
    -    testObjects.basic.mergeCells(0, 0, 0, 2);
    -    tableSanityCheck(testObjects.basic, 4, 3);
    -    var trs = testElements.basic.getElementsByTagName('tr');
    -    assertEquals('Cells merged',
    -        1, trs[0].getElementsByTagName('th').length);
    -    assertEquals('Merged cell has correct colspan',
    -        3, trs[0].getElementsByTagName('th')[0].colSpan);
    -    assertEquals('Merged cell has correct rowspan',
    -        1, trs[0].getElementsByTagName('th')[0].rowSpan);
    -  }
    -
    -  function testMergeCellsInColumn() {
    -    testObjects.basic.mergeCells(0, 0, 2, 0);
    -    tableSanityCheck(testObjects.basic, 4, 3);
    -    var trs = testElements.basic.getElementsByTagName('tr');
    -    assertEquals('Other cells still in row',
    -        3, trs[0].getElementsByTagName('th').length);
    -    assertEquals('Merged cell has correct colspan',
    -        1, trs[0].getElementsByTagName('th')[0].colSpan);
    -    assertEquals('Merged cell has correct rowspan',
    -        3, trs[0].getElementsByTagName('th')[0].rowSpan);
    -    assert('Cell appears in multiple rows after merge',
    -        testObjects.basic.rows[0].columns[0] ==
    -        testObjects.basic.rows[2].columns[0]);
    -  }
    -
    -  function testMergeCellsInRowAndColumn() {
    -    testObjects.basic.mergeCells(1, 1, 3, 2);
    -    tableSanityCheck(testObjects.basic, 4, 3);
    -    var trs = testElements.basic.getElementsByTagName('tr');
    -    var mergedCell = trs[1].getElementsByTagName('td')[1];
    -    assertEquals('Merged cell has correct rowspan',
    -        3, mergedCell.rowSpan);
    -    assertEquals('Merged cell has correct colspan',
    -        2, mergedCell.colSpan);
    -  }
    -
    -  function testMergeCellsAlreadyMerged() {
    -    testObjects.torture.mergeCells(5, 0, 8, 2);
    -    tableSanityCheck(testObjects.torture, 9, 3);
    -    var trs = testElements.torture.getElementsByTagName('tr');
    -    var mergedCell = trs[5].getElementsByTagName('th')[0];
    -    assertEquals('Merged cell has correct rowspan',
    -        4, mergedCell.rowSpan);
    -    assertEquals('Merged cell has correct colspan',
    -        3, mergedCell.colSpan);
    -  }
    -
    -  function testIllegalMergeNonRectangular() {
    -    // This should fail because it involves trying to merge two parts
    -    // of a 3-colspan cell with other cells
    -    var mergeSucceeded = testObjects.torture.mergeCells(3, 1, 5, 2);
    -    if (mergeSucceeded) {
    -      throw 'EditableTable allowed impossible merge!';
    -    }
    -    tableSanityCheck(testObjects.torture, 9, 3);
    -  }
    -
    -  function testIllegalMergeSingleCell() {
    -    // This should fail because it involves merging a single cell
    -    var mergeSucceeded = testObjects.torture.mergeCells(0, 1, 0, 1);
    -    if (mergeSucceeded) {
    -      throw 'EditableTable allowed impossible merge!';
    -    }
    -    tableSanityCheck(testObjects.torture, 9, 3);
    -  }
    -
    -  function testSplitCell() {
    -    testObjects.torture.splitCell(1, 1);
    -    tableSanityCheck(testObjects.torture, 9, 3);
    -    var trs = testElements.torture.getElementsByTagName('tr');
    -    assertEquals('Cell was split into multiple columns in row 1',
    -        3, trs[1].getElementsByTagName('*').length);
    -    assertEquals('Cell was split into multiple columns in row 2',
    -        3, trs[2].getElementsByTagName('*').length);
    -  }
    -
    -  function testChildTableRowsNotCountedInParentTable() {
    -    tableSanityCheck(testObjects.nested, 2, 3);
    -    for (var i = 0; i < testObjects.nested.rows.length; i++) {
    -      var tr = testObjects.nested.rows[i].element;
    -      // A tr's parent is tbody, parent of that is table - check to
    -      // make sure the ancestor table is as expected. This means
    -      // that none of the child table's rows have been erroneously
    -      // loaded into the EditableTable.
    -      assertEquals('Row is child of parent table',
    -          testElements.nested,
    -          tr.parentNode.parentNode);
    -    }
    -  }
    -
    -}
    -/*
    -  // TODO(user): write more unit tests for selection stuff.
    -  // The following code is left in here for reference in implementing
    -  // this TODO.
    -
    -    var tds = goog.dom.getElement('test1').getElementsByTagName('td');
    -    var range = goog.dom.Range.createFromNodes(tds[7], tds[9]);
    -    range.select();
    -    var cellSelection = new goog.editor.Table.CellSelection(range);
    -    assertEquals(0, cellSelection.getFirstColumnIndex());
    -    assertEquals(2, cellSelection.getLastColumnIndex());
    -    assertEquals(2, cellSelection.getFirstRowIndex());
    -    assertEquals(2, cellSelection.getLastRowIndex());
    -    assertTrue(cellSelection.isRectangle());
    -
    -    range = goog.dom.Range.createFromNodes(tds[7], tds[12]);
    -    range.select();
    -    var cellSelection2 = new goog.editor.Table.CellSelection(range);
    -    assertFalse(cellSelection2.isRectangle());
    -*/
    diff --git a/src/database/third_party/closure-library/closure/goog/events/actioneventwrapper.js b/src/database/third_party/closure-library/closure/goog/events/actioneventwrapper.js
    deleted file mode 100644
    index 779150f058b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/actioneventwrapper.js
    +++ /dev/null
    @@ -1,151 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Action event wrapper implementation.
    - * @author eae@google.com (Emil A Eklund)
    - */
    -
    -goog.provide('goog.events.actionEventWrapper');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -/** @suppress {extraRequire} */
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.EventWrapper');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Event wrapper for action handling. Fires when an element is activated either
    - * by clicking it or by focusing it and pressing Enter.
    - *
    - * @constructor
    - * @implements {goog.events.EventWrapper}
    - * @private
    - */
    -goog.events.ActionEventWrapper_ = function() {
    -};
    -
    -
    -/**
    - * Singleton instance of ActionEventWrapper_.
    - * @type {goog.events.ActionEventWrapper_}
    - */
    -goog.events.actionEventWrapper = new goog.events.ActionEventWrapper_();
    -
    -
    -/**
    - * Event types used by the wrapper.
    - *
    - * @type {Array<goog.events.EventType>}
    - * @private
    - */
    -goog.events.ActionEventWrapper_.EVENT_TYPES_ = [
    -  goog.events.EventType.CLICK,
    -  goog.userAgent.GECKO ?
    -      goog.events.EventType.KEYPRESS : goog.events.EventType.KEYDOWN,
    -  goog.events.EventType.KEYUP
    -];
    -
    -
    -/**
    - * Adds an event listener using the wrapper on a DOM Node or an object that has
    - * implemented {@link goog.events.EventTarget}. A listener can only be added
    - * once to an object.
    - *
    - * @param {goog.events.ListenableType} target The target to listen to events on.
    - * @param {function(?):?|{handleEvent:function(?):?}|null} listener Callback
    - *     method, or an object with a handleEvent function.
    - * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
    - *     false).
    - * @param {Object=} opt_scope Element in whose scope to call the listener.
    - * @param {goog.events.EventHandler=} opt_eventHandler Event handler to add
    - *     listener to.
    - * @override
    - */
    -goog.events.ActionEventWrapper_.prototype.listen = function(target, listener,
    -    opt_capt, opt_scope, opt_eventHandler) {
    -  var callback = function(e) {
    -    var listenerFn = goog.events.wrapListener(listener);
    -    var role = goog.dom.isElement(e.target) ?
    -        goog.a11y.aria.getRole(/** @type {!Element} */ (e.target)) : null;
    -    if (e.type == goog.events.EventType.CLICK && e.isMouseActionButton()) {
    -      listenerFn.call(opt_scope, e);
    -    } else if ((e.keyCode == goog.events.KeyCodes.ENTER ||
    -        e.keyCode == goog.events.KeyCodes.MAC_ENTER) &&
    -        e.type != goog.events.EventType.KEYUP) {
    -      // convert keydown to keypress for backward compatibility.
    -      e.type = goog.events.EventType.KEYPRESS;
    -      listenerFn.call(opt_scope, e);
    -    } else if (e.keyCode == goog.events.KeyCodes.SPACE &&
    -        e.type == goog.events.EventType.KEYUP &&
    -        (role == goog.a11y.aria.Role.BUTTON ||
    -            role == goog.a11y.aria.Role.TAB)) {
    -      listenerFn.call(opt_scope, e);
    -      e.preventDefault();
    -    }
    -  };
    -  callback.listener_ = listener;
    -  callback.scope_ = opt_scope;
    -
    -  if (opt_eventHandler) {
    -    opt_eventHandler.listen(target,
    -        goog.events.ActionEventWrapper_.EVENT_TYPES_,
    -        callback, opt_capt);
    -  } else {
    -    goog.events.listen(target,
    -        goog.events.ActionEventWrapper_.EVENT_TYPES_,
    -        callback, opt_capt);
    -  }
    -};
    -
    -
    -/**
    - * Removes an event listener added using goog.events.EventWrapper.listen.
    - *
    - * @param {goog.events.ListenableType} target The node to remove listener from.
    - * @param {function(?):?|{handleEvent:function(?):?}|null} listener Callback
    - *     method, or an object with a handleEvent function.
    - * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
    - *     false).
    - * @param {Object=} opt_scope Element in whose scope to call the listener.
    - * @param {goog.events.EventHandler=} opt_eventHandler Event handler to remove
    - *     listener from.
    - * @override
    - */
    -goog.events.ActionEventWrapper_.prototype.unlisten = function(target, listener,
    -    opt_capt, opt_scope, opt_eventHandler) {
    -  for (var type, j = 0; type = goog.events.ActionEventWrapper_.EVENT_TYPES_[j];
    -      j++) {
    -    var listeners = goog.events.getListeners(target, type, !!opt_capt);
    -    for (var obj, i = 0; obj = listeners[i]; i++) {
    -      if (obj.listener.listener_ == listener &&
    -          obj.listener.scope_ == opt_scope) {
    -        if (opt_eventHandler) {
    -          opt_eventHandler.unlisten(target, type, obj.listener, opt_capt,
    -              opt_scope);
    -        } else {
    -          goog.events.unlisten(target, type, obj.listener, opt_capt, opt_scope);
    -        }
    -        break;
    -      }
    -    }
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/events/actioneventwrapper_test.html b/src/database/third_party/closure-library/closure/goog/events/actioneventwrapper_test.html
    deleted file mode 100644
    index debe5e9480c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/actioneventwrapper_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.events.actionEventWrapper
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -  goog.require('goog.events.actionEventWrapperTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="a" tabindex="0">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/events/actioneventwrapper_test.js b/src/database/third_party/closure-library/closure/goog/events/actioneventwrapper_test.js
    deleted file mode 100644
    index 94c25b3472d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/actioneventwrapper_test.js
    +++ /dev/null
    @@ -1,270 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.events.actionEventWrapperTest');
    -goog.setTestOnly('goog.events.actionEventWrapperTest');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.events');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.events.actionEventWrapper');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -var a, eh, events;
    -
    -function setUpPage() {
    -  a = document.getElementById('a');
    -}
    -
    -function setUp() {
    -  events = [];
    -  eh = new goog.events.EventHandler();
    -
    -  assertEquals('No listeners registered yet', 0,
    -      goog.events.getListeners(a).length);
    -}
    -
    -
    -function tearDown() {
    -  eh.dispose();
    -}
    -
    -var Foo = function() {};
    -Foo.prototype.test = function(e) {
    -  events.push(e);
    -};
    -
    -function assertListenersExist(el, listenerCount, capt) {
    -  var EVENT_TYPES = goog.events.ActionEventWrapper_.EVENT_TYPES_;
    -  for (var i = 0; i < EVENT_TYPES.length; ++i) {
    -    assertEquals(listenerCount, goog.events.getListeners(
    -        el, EVENT_TYPES[i], capt).length);
    -  }
    -}
    -
    -function testAddActionListener() {
    -  var listener = function(e) { events.push(e);};
    -  goog.events.listenWithWrapper(a, goog.events.actionEventWrapper, listener);
    -
    -  assertListenersExist(a, 1, false);
    -
    -  goog.testing.events.fireClickSequence(a);
    -  assertEquals('1 event should have been dispatched', 1, events.length);
    -  assertEquals('Should be an click event', 'click', events[0].type);
    -
    -  goog.testing.events.fireKeySequence(a, goog.events.KeyCodes.ENTER);
    -  assertEquals('2 events should have been dispatched', 2, events.length);
    -  assertEquals('Should be a keypress event', 'keypress', events[1].type);
    -
    -  goog.a11y.aria.setRole(
    -      /** @type {!Element} */ (a), goog.a11y.aria.Role.BUTTON);
    -  goog.testing.events.fireKeySequence(a, goog.events.KeyCodes.SPACE);
    -  assertEquals('3 events should have been dispatched', 3, events.length);
    -  assertEquals('Should be a keyup event', 'keyup', events[2].type);
    -  assertTrue('Should be default prevented.', events[2].defaultPrevented);
    -  goog.a11y.aria.removeRole(/** @type {!Element} */ (a));
    -
    -  goog.testing.events.fireKeySequence(a, goog.events.KeyCodes.SPACE);
    -  assertEquals('3 events should have been dispatched', 3, events.length);
    -
    -  goog.testing.events.fireKeySequence(a, goog.events.KeyCodes.ESC);
    -  assertEquals('3 events should have been dispatched', 3, events.length);
    -
    -  goog.a11y.aria.setRole(
    -      /** @type {!Element} */ (a), goog.a11y.aria.Role.TAB);
    -  goog.testing.events.fireKeySequence(a, goog.events.KeyCodes.SPACE);
    -  assertEquals('4 events should have been dispatched', 4, events.length);
    -  assertEquals('Should be a keyup event', 'keyup', events[2].type);
    -  assertTrue('Should be default prevented.', events[2].defaultPrevented);
    -  goog.a11y.aria.removeRole(/** @type {!Element} */ (a));
    -
    -  goog.testing.events.fireKeySequence(a, goog.events.KeyCodes.SPACE);
    -  assertEquals('4 events should have been dispatched', 4, events.length);
    -
    -  goog.testing.events.fireKeySequence(a, goog.events.KeyCodes.ESC);
    -  assertEquals('4 events should have been dispatched', 4, events.length);
    -
    -  goog.events.unlistenWithWrapper(a, goog.events.actionEventWrapper,
    -      listener);
    -  assertListenersExist(a, 0, false);
    -}
    -
    -
    -function testAddActionListenerForHandleEvent() {
    -  var listener = {
    -    handleEvent: function(e) { events.push(e); }
    -  };
    -  goog.events.listenWithWrapper(a, goog.events.actionEventWrapper, listener);
    -
    -  assertListenersExist(a, 1, false);
    -
    -  goog.testing.events.fireClickSequence(a);
    -  assertEquals('1 event should have been dispatched', 1, events.length);
    -  assertEquals('Should be an click event', 'click', events[0].type);
    -
    -  goog.testing.events.fireKeySequence(a, goog.events.KeyCodes.ENTER);
    -  assertEquals('2 events should have been dispatched', 2, events.length);
    -  assertEquals('Should be a keypress event', 'keypress', events[1].type);
    -
    -  goog.a11y.aria.setRole(
    -      /** @type {!Element} */ (a), goog.a11y.aria.Role.BUTTON);
    -  goog.testing.events.fireKeySequence(a, goog.events.KeyCodes.SPACE);
    -  assertEquals('3 events should have been dispatched', 3, events.length);
    -  assertEquals('Should be a keyup event', 'keyup', events[2].type);
    -  assertTrue('Should be default prevented.', events[2].defaultPrevented);
    -  goog.a11y.aria.removeRole(/** @type {!Element} */ (a));
    -
    -  goog.testing.events.fireKeySequence(a, goog.events.KeyCodes.SPACE);
    -  assertEquals('3 events should have been dispatched', 3, events.length);
    -
    -  goog.testing.events.fireKeySequence(a, goog.events.KeyCodes.ESC);
    -  assertEquals('3 events should have been dispatched', 3, events.length);
    -
    -  goog.events.unlistenWithWrapper(a, goog.events.actionEventWrapper,
    -      listener);
    -  assertListenersExist(a, 0, false);
    -}
    -
    -
    -function testAddActionListenerInCaptPhase() {
    -  var count = 0;
    -  var captListener = function(e) {
    -    events.push(e);
    -    assertEquals(0, count);
    -    count++;
    -  };
    -
    -  var bubbleListener = function(e) {
    -    events.push(e);
    -    assertEquals(1, count);
    -    count = 0;
    -  };
    -
    -  goog.events.listenWithWrapper(a, goog.events.actionEventWrapper,
    -      captListener, true);
    -
    -  goog.events.listenWithWrapper(a, goog.events.actionEventWrapper,
    -      bubbleListener);
    -
    -  assertListenersExist(a, 1, false);
    -  assertListenersExist(a, 1, true);
    -
    -  goog.testing.events.fireClickSequence(a);
    -  assertEquals('2 event should have been dispatched', 2, events.length);
    -  assertEquals('Should be an click event', 'click', events[0].type);
    -
    -  goog.testing.events.fireKeySequence(a, goog.events.KeyCodes.ENTER);
    -  assertEquals('4 events should have been dispatched', 4, events.length);
    -  assertEquals('Should be a keypress event', 'keypress', events[2].type);
    -
    -  goog.testing.events.fireKeySequence(a, goog.events.KeyCodes.SPACE);
    -  assertEquals('4 events should have been dispatched', 4, events.length);
    -
    -  goog.testing.events.fireKeySequence(a, goog.events.KeyCodes.ESC);
    -  assertEquals('4 events should have been dispatched', 4, events.length);
    -
    -  goog.events.unlistenWithWrapper(a, goog.events.actionEventWrapper,
    -      captListener, true);
    -  goog.events.unlistenWithWrapper(a, goog.events.actionEventWrapper,
    -      bubbleListener);
    -
    -  assertListenersExist(a, 0, false);
    -  assertListenersExist(a, 0, true);
    -}
    -
    -
    -function testRemoveActionListener() {
    -  var listener1 = function(e) { events.push(e); };
    -  var listener2 = function(e) { events.push({type: 'err'}); };
    -
    -  goog.events.listenWithWrapper(a, goog.events.actionEventWrapper, listener1);
    -  assertListenersExist(a, 1, false);
    -
    -  goog.events.listenWithWrapper(a, goog.events.actionEventWrapper, listener2);
    -  assertListenersExist(a, 2, false);
    -
    -  goog.testing.events.fireKeySequence(a, goog.events.KeyCodes.ENTER);
    -  assertEquals('2 events should have been dispatched', 2, events.length);
    -  assertEquals('Should be a keypress event', 'keypress', events[0].type);
    -  assertEquals('Should be an err event', 'err', events[1].type);
    -
    -  goog.events.unlistenWithWrapper(a, goog.events.actionEventWrapper,
    -      listener2);
    -  assertListenersExist(a, 1, false);
    -
    -  events = [];
    -  goog.testing.events.fireKeySequence(a, goog.events.KeyCodes.ENTER);
    -  assertEquals('1 event should have been dispatched', 1, events.length);
    -  assertEquals('Should be a keypress event', 'keypress', events[0].type);
    -
    -  goog.events.unlistenWithWrapper(a, goog.events.actionEventWrapper,
    -      listener1);
    -  assertListenersExist(a, 0, false);
    -}
    -
    -
    -function testEventHandlerActionListener() {
    -  var listener = function(e) { events.push(e); };
    -  eh.listenWithWrapper(a, goog.events.actionEventWrapper, listener);
    -
    -  assertListenersExist(a, 1, false);
    -
    -  goog.testing.events.fireClickSequence(a);
    -  assertEquals('1 event should have been dispatched', 1, events.length);
    -  assertEquals('Should be an click event', 'click', events[0].type);
    -
    -  goog.testing.events.fireKeySequence(a, goog.events.KeyCodes.ENTER);
    -  assertEquals('2 events should have been dispatched', 2, events.length);
    -  assertEquals('Should be a keypress event', 'keypress', events[1].type);
    -
    -  goog.testing.events.fireKeySequence(a, goog.events.KeyCodes.SPACE);
    -  assertEquals('2 events should have been dispatched', 2, events.length);
    -
    -  goog.testing.events.fireKeySequence(a, goog.events.KeyCodes.ESC);
    -  assertEquals('2 events should have been dispatched', 2, events.length);
    -
    -  eh.unlistenWithWrapper(a, goog.events.actionEventWrapper,
    -      listener);
    -  assertListenersExist(a, 0, false);
    -}
    -
    -
    -function testEventHandlerActionListenerWithScope() {
    -  var foo = new Foo();
    -  var eh2 = new goog.events.EventHandler(foo);
    -
    -  eh2.listenWithWrapper(a, goog.events.actionEventWrapper, foo.test);
    -
    -  assertListenersExist(a, 1, false);
    -
    -  goog.testing.events.fireClickSequence(a);
    -  assertEquals('1 event should have been dispatched', 1, events.length);
    -  assertEquals('Should be an click event', 'click', events[0].type);
    -
    -  goog.testing.events.fireKeySequence(a, goog.events.KeyCodes.ENTER);
    -  assertEquals('2 events should have been dispatched', 2, events.length);
    -  assertEquals('Should be a keypress event', 'keypress', events[1].type);
    -
    -  goog.testing.events.fireKeySequence(a, goog.events.KeyCodes.SPACE);
    -  assertEquals('2 events should have been dispatched', 2, events.length);
    -
    -  goog.testing.events.fireKeySequence(a, goog.events.KeyCodes.ESC);
    -  assertEquals('2 events should have been dispatched', 2, events.length);
    -
    -  eh2.dispose();
    -  assertListenersExist(a, 0, false);
    -  delete foo;
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/events/actionhandler.js b/src/database/third_party/closure-library/closure/goog/events/actionhandler.js
    deleted file mode 100644
    index 190cc26046c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/actionhandler.js
    +++ /dev/null
    @@ -1,184 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview This file contains a class to provide a unified mechanism for
    - * CLICK and enter KEYDOWN events. This provides better accessibility by
    - * providing the given functionality to a keyboard user which is otherwise
    - * would be available only via a mouse click.
    - *
    - * If there is an existing CLICK listener or planning to be added as below -
    - *
    - * <code>this.eventHandler_.listen(el, CLICK, this.onClick_);<code>
    - *
    - * it can be replaced with an ACTION listener as follows:
    - *
    - * <code>this.eventHandler_.listen(
    - *    new goog.events.ActionHandler(el),
    - *    ACTION,
    - *    this.onAction_);<code>
    - *
    - */
    -
    -goog.provide('goog.events.ActionEvent');
    -goog.provide('goog.events.ActionHandler');
    -goog.provide('goog.events.ActionHandler.EventType');
    -goog.provide('goog.events.BeforeActionEvent');
    -
    -goog.require('goog.events');
    -goog.require('goog.events.BrowserEvent');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * A wrapper around an element that you want to listen to ACTION events on.
    - * @param {Element|Document} element The element or document to listen on.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - * @final
    - */
    -goog.events.ActionHandler = function(element) {
    -  goog.events.EventTarget.call(this);
    -
    -  /**
    -   * This is the element that we will listen to events on.
    -   * @type {Element|Document}
    -   * @private
    -   */
    -  this.element_ = element;
    -
    -  goog.events.listen(element, goog.events.ActionHandler.KEY_EVENT_TYPE_,
    -      this.handleKeyDown_, false, this);
    -  goog.events.listen(element, goog.events.EventType.CLICK,
    -      this.handleClick_, false, this);
    -};
    -goog.inherits(goog.events.ActionHandler, goog.events.EventTarget);
    -
    -
    -/**
    - * Enum type for the events fired by the action handler
    - * @enum {string}
    - */
    -goog.events.ActionHandler.EventType = {
    -  ACTION: 'action',
    -  BEFOREACTION: 'beforeaction'
    -};
    -
    -
    -/**
    - * Key event type to listen for.
    - * @type {string}
    - * @private
    - */
    -goog.events.ActionHandler.KEY_EVENT_TYPE_ = goog.userAgent.GECKO ?
    -    goog.events.EventType.KEYPRESS :
    -    goog.events.EventType.KEYDOWN;
    -
    -
    -/**
    - * Handles key press events.
    - * @param {!goog.events.BrowserEvent} e The key press event.
    - * @private
    - */
    -goog.events.ActionHandler.prototype.handleKeyDown_ = function(e) {
    -  if (e.keyCode == goog.events.KeyCodes.ENTER ||
    -      goog.userAgent.WEBKIT && e.keyCode == goog.events.KeyCodes.MAC_ENTER) {
    -    this.dispatchEvents_(e);
    -  }
    -};
    -
    -
    -/**
    - * Handles mouse events.
    - * @param {!goog.events.BrowserEvent} e The click event.
    - * @private
    - */
    -goog.events.ActionHandler.prototype.handleClick_ = function(e) {
    -  this.dispatchEvents_(e);
    -};
    -
    -
    -/**
    - * Dispatches BeforeAction and Action events to the element
    - * @param {!goog.events.BrowserEvent} e The event causing dispatches.
    - * @private
    - */
    -goog.events.ActionHandler.prototype.dispatchEvents_ = function(e) {
    -  var beforeActionEvent = new goog.events.BeforeActionEvent(e);
    -
    -  // Allow application specific logic here before the ACTION event.
    -  // For example, Gmail uses this event to restore keyboard focus
    -  if (!this.dispatchEvent(beforeActionEvent)) {
    -    // If the listener swallowed the BEFOREACTION event, don't dispatch the
    -    // ACTION event.
    -    return;
    -  }
    -
    -
    -  // Wrap up original event and send it off
    -  var actionEvent = new goog.events.ActionEvent(e);
    -  try {
    -    this.dispatchEvent(actionEvent);
    -  } finally {
    -    // Stop propagating the event
    -    e.stopPropagation();
    -  }
    -};
    -
    -
    -/** @override */
    -goog.events.ActionHandler.prototype.disposeInternal = function() {
    -  goog.events.ActionHandler.superClass_.disposeInternal.call(this);
    -  goog.events.unlisten(this.element_, goog.events.ActionHandler.KEY_EVENT_TYPE_,
    -      this.handleKeyDown_, false, this);
    -  goog.events.unlisten(this.element_, goog.events.EventType.CLICK,
    -      this.handleClick_, false, this);
    -  delete this.element_;
    -};
    -
    -
    -
    -/**
    - * This class is used for the goog.events.ActionHandler.EventType.ACTION event.
    - * @param {!goog.events.BrowserEvent} browserEvent Browser event object.
    - * @constructor
    - * @extends {goog.events.BrowserEvent}
    - * @final
    - */
    -goog.events.ActionEvent = function(browserEvent) {
    -  goog.events.BrowserEvent.call(this, browserEvent.getBrowserEvent());
    -  this.type = goog.events.ActionHandler.EventType.ACTION;
    -};
    -goog.inherits(goog.events.ActionEvent, goog.events.BrowserEvent);
    -
    -
    -
    -/**
    - * This class is used for the goog.events.ActionHandler.EventType.BEFOREACTION
    - * event. BEFOREACTION gives a chance to the application so the keyboard focus
    - * can be restored back, if required.
    - * @param {!goog.events.BrowserEvent} browserEvent Browser event object.
    - * @constructor
    - * @extends {goog.events.BrowserEvent}
    - * @final
    - */
    -goog.events.BeforeActionEvent = function(browserEvent) {
    -  goog.events.BrowserEvent.call(this, browserEvent.getBrowserEvent());
    -  this.type = goog.events.ActionHandler.EventType.BEFOREACTION;
    -};
    -goog.inherits(goog.events.BeforeActionEvent, goog.events.BrowserEvent);
    diff --git a/src/database/third_party/closure-library/closure/goog/events/actionhandler_test.html b/src/database/third_party/closure-library/closure/goog/events/actionhandler_test.html
    deleted file mode 100644
    index d0a35188d5a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/actionhandler_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.events.ActionHandler
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.events.ActionHandlerTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="actionDiv">
    -   action
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/events/actionhandler_test.js b/src/database/third_party/closure-library/closure/goog/events/actionhandler_test.js
    deleted file mode 100644
    index db76a5e358c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/actionhandler_test.js
    +++ /dev/null
    @@ -1,80 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.events.ActionHandlerTest');
    -goog.setTestOnly('goog.events.ActionHandlerTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.ActionHandler');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -
    -var actionHandler;
    -function setUp() {
    -  actionHandler = new goog.events.ActionHandler(
    -      goog.dom.getElement('actionDiv'));
    -}
    -function tearDown() {
    -  actionHandler.dispose();
    -}
    -
    -// Tests to see that both the BEFOREACTION and ACTION events are fired
    -function testActionHandlerWithBeforeActionHandler() {
    -  var actionEventFired = false;
    -  var beforeActionFired = false;
    -  goog.events.listen(actionHandler,
    -      goog.events.ActionHandler.EventType.ACTION,
    -      function(e) {
    -        actionEventFired = true;
    -      });
    -  goog.events.listen(actionHandler,
    -      goog.events.ActionHandler.EventType.BEFOREACTION,
    -      function(e) {
    -        beforeActionFired = true;
    -      });
    -  goog.testing.events.fireClickSequence(goog.dom.getElement('actionDiv'));
    -  assertTrue('BEFOREACTION event was not fired', beforeActionFired);
    -  assertTrue('ACTION event was not fired', actionEventFired);
    -}
    -
    -// Tests to see that the ACTION event is fired, even if there is no
    -// BEFOREACTION handler.
    -function testActionHandlerWithoutBeforeActionHandler() {
    -  var actionEventFired = false;
    -  goog.events.listen(actionHandler,
    -      goog.events.ActionHandler.EventType.ACTION,
    -      function(e) {actionEventFired = true;});
    -  goog.testing.events.fireClickSequence(goog.dom.getElement('actionDiv'));
    -  assertTrue('ACTION event was not fired', actionEventFired);
    -}
    -
    -// If the BEFOREACTION listener swallows the event, it should cancel the
    -// ACTION event.
    -function testBeforeActionCancel() {
    -  var actionEventFired = false;
    -  var beforeActionFired = false;
    -  goog.events.listen(actionHandler,
    -      goog.events.ActionHandler.EventType.ACTION,
    -      function(e) {actionEvent = e;});
    -  goog.events.listen(actionHandler,
    -      goog.events.ActionHandler.EventType.BEFOREACTION,
    -      function(e) {
    -        beforeActionFired = true;
    -        e.preventDefault();
    -      });
    -  goog.testing.events.fireClickSequence(goog.dom.getElement('actionDiv'));
    -  assertTrue(beforeActionFired);
    -  assertFalse(actionEventFired);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/events/browserevent.js b/src/database/third_party/closure-library/closure/goog/events/browserevent.js
    deleted file mode 100644
    index f0773ce57a0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/browserevent.js
    +++ /dev/null
    @@ -1,386 +0,0 @@
    -// Copyright 2005 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A patched, standardized event object for browser events.
    - *
    - * <pre>
    - * The patched event object contains the following members:
    - * - type           {string}    Event type, e.g. 'click'
    - * - target         {Object}    The element that actually triggered the event
    - * - currentTarget  {Object}    The element the listener is attached to
    - * - relatedTarget  {Object}    For mouseover and mouseout, the previous object
    - * - offsetX        {number}    X-coordinate relative to target
    - * - offsetY        {number}    Y-coordinate relative to target
    - * - clientX        {number}    X-coordinate relative to viewport
    - * - clientY        {number}    Y-coordinate relative to viewport
    - * - screenX        {number}    X-coordinate relative to the edge of the screen
    - * - screenY        {number}    Y-coordinate relative to the edge of the screen
    - * - button         {number}    Mouse button. Use isButton() to test.
    - * - keyCode        {number}    Key-code
    - * - ctrlKey        {boolean}   Was ctrl key depressed
    - * - altKey         {boolean}   Was alt key depressed
    - * - shiftKey       {boolean}   Was shift key depressed
    - * - metaKey        {boolean}   Was meta key depressed
    - * - defaultPrevented {boolean} Whether the default action has been prevented
    - * - state          {Object}    History state object
    - *
    - * NOTE: The keyCode member contains the raw browser keyCode. For normalized
    - * key and character code use {@link goog.events.KeyHandler}.
    - * </pre>
    - *
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -goog.provide('goog.events.BrowserEvent');
    -goog.provide('goog.events.BrowserEvent.MouseButton');
    -
    -goog.require('goog.events.BrowserFeature');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventType');
    -goog.require('goog.reflect');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Accepts a browser event object and creates a patched, cross browser event
    - * object.
    - * The content of this object will not be initialized if no event object is
    - * provided. If this is the case, init() needs to be invoked separately.
    - * @param {Event=} opt_e Browser event object.
    - * @param {EventTarget=} opt_currentTarget Current target for event.
    - * @constructor
    - * @extends {goog.events.Event}
    - */
    -goog.events.BrowserEvent = function(opt_e, opt_currentTarget) {
    -  goog.events.BrowserEvent.base(this, 'constructor', opt_e ? opt_e.type : '');
    -
    -  /**
    -   * Target that fired the event.
    -   * @override
    -   * @type {Node}
    -   */
    -  this.target = null;
    -
    -  /**
    -   * Node that had the listener attached.
    -   * @override
    -   * @type {Node|undefined}
    -   */
    -  this.currentTarget = null;
    -
    -  /**
    -   * For mouseover and mouseout events, the related object for the event.
    -   * @type {Node}
    -   */
    -  this.relatedTarget = null;
    -
    -  /**
    -   * X-coordinate relative to target.
    -   * @type {number}
    -   */
    -  this.offsetX = 0;
    -
    -  /**
    -   * Y-coordinate relative to target.
    -   * @type {number}
    -   */
    -  this.offsetY = 0;
    -
    -  /**
    -   * X-coordinate relative to the window.
    -   * @type {number}
    -   */
    -  this.clientX = 0;
    -
    -  /**
    -   * Y-coordinate relative to the window.
    -   * @type {number}
    -   */
    -  this.clientY = 0;
    -
    -  /**
    -   * X-coordinate relative to the monitor.
    -   * @type {number}
    -   */
    -  this.screenX = 0;
    -
    -  /**
    -   * Y-coordinate relative to the monitor.
    -   * @type {number}
    -   */
    -  this.screenY = 0;
    -
    -  /**
    -   * Which mouse button was pressed.
    -   * @type {number}
    -   */
    -  this.button = 0;
    -
    -  /**
    -   * Keycode of key press.
    -   * @type {number}
    -   */
    -  this.keyCode = 0;
    -
    -  /**
    -   * Keycode of key press.
    -   * @type {number}
    -   */
    -  this.charCode = 0;
    -
    -  /**
    -   * Whether control was pressed at time of event.
    -   * @type {boolean}
    -   */
    -  this.ctrlKey = false;
    -
    -  /**
    -   * Whether alt was pressed at time of event.
    -   * @type {boolean}
    -   */
    -  this.altKey = false;
    -
    -  /**
    -   * Whether shift was pressed at time of event.
    -   * @type {boolean}
    -   */
    -  this.shiftKey = false;
    -
    -  /**
    -   * Whether the meta key was pressed at time of event.
    -   * @type {boolean}
    -   */
    -  this.metaKey = false;
    -
    -  /**
    -   * History state object, only set for PopState events where it's a copy of the
    -   * state object provided to pushState or replaceState.
    -   * @type {Object}
    -   */
    -  this.state = null;
    -
    -  /**
    -   * Whether the default platform modifier key was pressed at time of event.
    -   * (This is control for all platforms except Mac, where it's Meta.)
    -   * @type {boolean}
    -   */
    -  this.platformModifierKey = false;
    -
    -  /**
    -   * The browser event object.
    -   * @private {Event}
    -   */
    -  this.event_ = null;
    -
    -  if (opt_e) {
    -    this.init(opt_e, opt_currentTarget);
    -  }
    -};
    -goog.inherits(goog.events.BrowserEvent, goog.events.Event);
    -
    -
    -/**
    - * Normalized button constants for the mouse.
    - * @enum {number}
    - */
    -goog.events.BrowserEvent.MouseButton = {
    -  LEFT: 0,
    -  MIDDLE: 1,
    -  RIGHT: 2
    -};
    -
    -
    -/**
    - * Static data for mapping mouse buttons.
    - * @type {!Array<number>}
    - */
    -goog.events.BrowserEvent.IEButtonMap = [
    -  1, // LEFT
    -  4, // MIDDLE
    -  2  // RIGHT
    -];
    -
    -
    -/**
    - * Accepts a browser event object and creates a patched, cross browser event
    - * object.
    - * @param {Event} e Browser event object.
    - * @param {EventTarget=} opt_currentTarget Current target for event.
    - */
    -goog.events.BrowserEvent.prototype.init = function(e, opt_currentTarget) {
    -  var type = this.type = e.type;
    -
    -  // TODO(nicksantos): Change this.target to type EventTarget.
    -  this.target = /** @type {Node} */ (e.target) || e.srcElement;
    -
    -  // TODO(nicksantos): Change this.currentTarget to type EventTarget.
    -  this.currentTarget = /** @type {Node} */ (opt_currentTarget);
    -
    -  var relatedTarget = /** @type {Node} */ (e.relatedTarget);
    -  if (relatedTarget) {
    -    // There's a bug in FireFox where sometimes, relatedTarget will be a
    -    // chrome element, and accessing any property of it will get a permission
    -    // denied exception. See:
    -    // https://bugzilla.mozilla.org/show_bug.cgi?id=497780
    -    if (goog.userAgent.GECKO) {
    -      if (!goog.reflect.canAccessProperty(relatedTarget, 'nodeName')) {
    -        relatedTarget = null;
    -      }
    -    }
    -    // TODO(arv): Use goog.events.EventType when it has been refactored into its
    -    // own file.
    -  } else if (type == goog.events.EventType.MOUSEOVER) {
    -    relatedTarget = e.fromElement;
    -  } else if (type == goog.events.EventType.MOUSEOUT) {
    -    relatedTarget = e.toElement;
    -  }
    -
    -  this.relatedTarget = relatedTarget;
    -
    -  // Webkit emits a lame warning whenever layerX/layerY is accessed.
    -  // http://code.google.com/p/chromium/issues/detail?id=101733
    -  this.offsetX = (goog.userAgent.WEBKIT || e.offsetX !== undefined) ?
    -      e.offsetX : e.layerX;
    -  this.offsetY = (goog.userAgent.WEBKIT || e.offsetY !== undefined) ?
    -      e.offsetY : e.layerY;
    -
    -  this.clientX = e.clientX !== undefined ? e.clientX : e.pageX;
    -  this.clientY = e.clientY !== undefined ? e.clientY : e.pageY;
    -  this.screenX = e.screenX || 0;
    -  this.screenY = e.screenY || 0;
    -
    -  this.button = e.button;
    -
    -  this.keyCode = e.keyCode || 0;
    -  this.charCode = e.charCode || (type == 'keypress' ? e.keyCode : 0);
    -  this.ctrlKey = e.ctrlKey;
    -  this.altKey = e.altKey;
    -  this.shiftKey = e.shiftKey;
    -  this.metaKey = e.metaKey;
    -  this.platformModifierKey = goog.userAgent.MAC ? e.metaKey : e.ctrlKey;
    -  this.state = e.state;
    -  this.event_ = e;
    -  if (e.defaultPrevented) {
    -    this.preventDefault();
    -  }
    -};
    -
    -
    -/**
    - * Tests to see which button was pressed during the event. This is really only
    - * useful in IE and Gecko browsers. And in IE, it's only useful for
    - * mousedown/mouseup events, because click only fires for the left mouse button.
    - *
    - * Safari 2 only reports the left button being clicked, and uses the value '1'
    - * instead of 0. Opera only reports a mousedown event for the middle button, and
    - * no mouse events for the right button. Opera has default behavior for left and
    - * middle click that can only be overridden via a configuration setting.
    - *
    - * There's a nice table of this mess at http://www.unixpapa.com/js/mouse.html.
    - *
    - * @param {goog.events.BrowserEvent.MouseButton} button The button
    - *     to test for.
    - * @return {boolean} True if button was pressed.
    - */
    -goog.events.BrowserEvent.prototype.isButton = function(button) {
    -  if (!goog.events.BrowserFeature.HAS_W3C_BUTTON) {
    -    if (this.type == 'click') {
    -      return button == goog.events.BrowserEvent.MouseButton.LEFT;
    -    } else {
    -      return !!(this.event_.button &
    -          goog.events.BrowserEvent.IEButtonMap[button]);
    -    }
    -  } else {
    -    return this.event_.button == button;
    -  }
    -};
    -
    -
    -/**
    - * Whether this has an "action"-producing mouse button.
    - *
    - * By definition, this includes left-click on windows/linux, and left-click
    - * without the ctrl key on Macs.
    - *
    - * @return {boolean} The result.
    - */
    -goog.events.BrowserEvent.prototype.isMouseActionButton = function() {
    -  // Webkit does not ctrl+click to be a right-click, so we
    -  // normalize it to behave like Gecko and Opera.
    -  return this.isButton(goog.events.BrowserEvent.MouseButton.LEFT) &&
    -      !(goog.userAgent.WEBKIT && goog.userAgent.MAC && this.ctrlKey);
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.events.BrowserEvent.prototype.stopPropagation = function() {
    -  goog.events.BrowserEvent.superClass_.stopPropagation.call(this);
    -  if (this.event_.stopPropagation) {
    -    this.event_.stopPropagation();
    -  } else {
    -    this.event_.cancelBubble = true;
    -  }
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.events.BrowserEvent.prototype.preventDefault = function() {
    -  goog.events.BrowserEvent.superClass_.preventDefault.call(this);
    -  var be = this.event_;
    -  if (!be.preventDefault) {
    -    be.returnValue = false;
    -    if (goog.events.BrowserFeature.SET_KEY_CODE_TO_PREVENT_DEFAULT) {
    -      /** @preserveTry */
    -      try {
    -        // Most keys can be prevented using returnValue. Some special keys
    -        // require setting the keyCode to -1 as well:
    -        //
    -        // In IE7:
    -        // F3, F5, F10, F11, Ctrl+P, Crtl+O, Ctrl+F (these are taken from IE6)
    -        //
    -        // In IE8:
    -        // Ctrl+P, Crtl+O, Ctrl+F (F1-F12 cannot be stopped through the event)
    -        //
    -        // We therefore do this for all function keys as well as when Ctrl key
    -        // is pressed.
    -        var VK_F1 = 112;
    -        var VK_F12 = 123;
    -        if (be.ctrlKey || be.keyCode >= VK_F1 && be.keyCode <= VK_F12) {
    -          be.keyCode = -1;
    -        }
    -      } catch (ex) {
    -        // IE throws an 'access denied' exception when trying to change
    -        // keyCode in some situations (e.g. srcElement is input[type=file],
    -        // or srcElement is an anchor tag rewritten by parent's innerHTML).
    -        // Do nothing in this case.
    -      }
    -    }
    -  } else {
    -    be.preventDefault();
    -  }
    -};
    -
    -
    -/**
    - * @return {Event} The underlying browser event object.
    - */
    -goog.events.BrowserEvent.prototype.getBrowserEvent = function() {
    -  return this.event_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/events/browserevent_test.html b/src/database/third_party/closure-library/closure/goog/events/browserevent_test.html
    deleted file mode 100644
    index 2c2c1f67096..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/browserevent_test.html
    +++ /dev/null
    @@ -1,26 +0,0 @@
    -<!DOCTYPE html>
    -<!--
    -
    -  Author: nicksantos@google.com (Nick Santos)
    --->
    -<html>
    - <!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   JsUnit tests for goog.events.BrowserEvent
    -  </title>
    -  <script type="text/javascript" src="../base.js">
    -  </script>
    -  <script type="text/javascript">
    -   goog.require('goog.events.BrowserEventTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/events/browserevent_test.js b/src/database/third_party/closure-library/closure/goog/events/browserevent_test.js
    deleted file mode 100644
    index 02d5311785f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/browserevent_test.js
    +++ /dev/null
    @@ -1,149 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.events.BrowserEventTest');
    -goog.setTestOnly('goog.events.BrowserEventTest');
    -
    -goog.require('goog.events.BrowserEvent');
    -goog.require('goog.events.BrowserFeature');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -var stubs = new goog.testing.PropertyReplacer();
    -var Button = goog.events.BrowserEvent.MouseButton;
    -
    -function setUp() {
    -  stubs.reset();
    -}
    -
    -
    -/**
    - * @see https://bugzilla.mozilla.org/show_bug.cgi?id=497780
    - */
    -function testInvalidNodeBug() {
    -  if (!goog.userAgent.GECKO) return;
    -
    -  var event = {};
    -  event.relatedTarget = {};
    -  event.relatedTarget.__defineGetter__(
    -      'nodeName',
    -      function() {
    -        throw Error('https://bugzilla.mozilla.org/show_bug.cgi?id=497780');
    -      });
    -  assertThrows(function() { return event.relatedTarget.nodeName; });
    -
    -  var bEvent = new goog.events.BrowserEvent(event);
    -  assertEquals(event, bEvent.event_);
    -  assertNull(bEvent.relatedTarget);
    -}
    -
    -function testPreventDefault() {
    -  var event = {};
    -  event.defaultPrevented = false;
    -  var bEvent = new goog.events.BrowserEvent(event);
    -  assertFalse(bEvent.defaultPrevented);
    -  bEvent.preventDefault();
    -  assertTrue(bEvent.defaultPrevented);
    -}
    -
    -function testDefaultPrevented() {
    -  var event = {};
    -  event.defaultPrevented = true;
    -  var bEvent = new goog.events.BrowserEvent(event);
    -  assertTrue(bEvent.defaultPrevented);
    -}
    -
    -function testIsButtonIe() {
    -  stubs.set(goog.events.BrowserFeature, 'HAS_W3C_BUTTON', false);
    -  assertIsButton(
    -      createBrowserEvent('mousedown', 1),
    -      Button.LEFT,
    -      true);
    -  assertIsButton(
    -      createBrowserEvent('click', 0),
    -      Button.LEFT,
    -      true);
    -  assertIsButton(
    -      createBrowserEvent('mousedown', 2),
    -      Button.RIGHT,
    -      false);
    -  assertIsButton(
    -      createBrowserEvent('mousedown', 4),
    -      Button.MIDDLE,
    -      false);
    -}
    -
    -function testIsButtonWebkitMac() {
    -  stubs.set(goog.events.BrowserFeature, 'HAS_W3C_BUTTON', true);
    -  stubs.set(goog.userAgent, 'WEBKIT', true);
    -  stubs.set(goog.userAgent, 'MAC', true);
    -  assertIsButton(
    -      createBrowserEvent('mousedown', 0),
    -      Button.LEFT,
    -      true);
    -  assertIsButton(
    -      createBrowserEvent('mousedown', 0, true),
    -      Button.LEFT,
    -      false);
    -  assertIsButton(
    -      createBrowserEvent('mousedown', 2),
    -      Button.RIGHT,
    -      false);
    -  assertIsButton(
    -      createBrowserEvent('mousedown', 2, true),
    -      Button.RIGHT,
    -      false);
    -  assertIsButton(
    -      createBrowserEvent('mousedown', 1),
    -      Button.MIDDLE,
    -      false);
    -  assertIsButton(
    -      createBrowserEvent('mousedown', 1, true),
    -      Button.MIDDLE,
    -      false);
    -}
    -
    -function testIsButtonGecko() {
    -  stubs.set(goog.events.BrowserFeature, 'HAS_W3C_BUTTON', true);
    -  stubs.set(goog.userAgent, 'GECKO', true);
    -  stubs.set(goog.userAgent, 'MAC', true);
    -  assertIsButton(
    -      createBrowserEvent('mousedown', 0),
    -      Button.LEFT,
    -      true);
    -  assertIsButton(
    -      createBrowserEvent('mousedown', 2, true),
    -      Button.RIGHT,
    -      false);
    -}
    -
    -function createBrowserEvent(type, button, opt_ctrlKey) {
    -  return new goog.events.BrowserEvent({
    -    type: type,
    -    button: button,
    -    ctrlKey: !!opt_ctrlKey
    -  });
    -}
    -
    -function assertIsButton(event, button, isActionButton) {
    -  for (var key in Button) {
    -    assertEquals(
    -        'Testing isButton(' + key + ') against ' +
    -        button + ' and type ' + event.type,
    -        Button[key] == button, event.isButton(Button[key]));
    -  }
    -
    -  assertEquals(isActionButton, event.isMouseActionButton());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/events/browserfeature.js b/src/database/third_party/closure-library/closure/goog/events/browserfeature.js
    deleted file mode 100644
    index 61b9d609a32..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/browserfeature.js
    +++ /dev/null
    @@ -1,85 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Browser capability checks for the events package.
    - *
    - */
    -
    -
    -goog.provide('goog.events.BrowserFeature');
    -
    -goog.require('goog.userAgent');
    -
    -
    -/**
    - * Enum of browser capabilities.
    - * @enum {boolean}
    - */
    -goog.events.BrowserFeature = {
    -  /**
    -   * Whether the button attribute of the event is W3C compliant.  False in
    -   * Internet Explorer prior to version 9; document-version dependent.
    -   */
    -  HAS_W3C_BUTTON: !goog.userAgent.IE ||
    -      goog.userAgent.isDocumentModeOrHigher(9),
    -
    -  /**
    -   * Whether the browser supports full W3C event model.
    -   */
    -  HAS_W3C_EVENT_SUPPORT: !goog.userAgent.IE ||
    -      goog.userAgent.isDocumentModeOrHigher(9),
    -
    -  /**
    -   * To prevent default in IE7-8 for certain keydown events we need set the
    -   * keyCode to -1.
    -   */
    -  SET_KEY_CODE_TO_PREVENT_DEFAULT: goog.userAgent.IE &&
    -      !goog.userAgent.isVersionOrHigher('9'),
    -
    -  /**
    -   * Whether the {@code navigator.onLine} property is supported.
    -   */
    -  HAS_NAVIGATOR_ONLINE_PROPERTY: !goog.userAgent.WEBKIT ||
    -      goog.userAgent.isVersionOrHigher('528'),
    -
    -  /**
    -   * Whether HTML5 network online/offline events are supported.
    -   */
    -  HAS_HTML5_NETWORK_EVENT_SUPPORT:
    -      goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.9b') ||
    -      goog.userAgent.IE && goog.userAgent.isVersionOrHigher('8') ||
    -      goog.userAgent.OPERA && goog.userAgent.isVersionOrHigher('9.5') ||
    -      goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher('528'),
    -
    -  /**
    -   * Whether HTML5 network events fire on document.body, or otherwise the
    -   * window.
    -   */
    -  HTML5_NETWORK_EVENTS_FIRE_ON_BODY:
    -      goog.userAgent.GECKO && !goog.userAgent.isVersionOrHigher('8') ||
    -      goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9'),
    -
    -  /**
    -   * Whether touch is enabled in the browser.
    -   */
    -  TOUCH_ENABLED:
    -      ('ontouchstart' in goog.global ||
    -          !!(goog.global['document'] &&
    -             document.documentElement &&
    -             'ontouchstart' in document.documentElement) ||
    -          // IE10 uses non-standard touch events, so it has a different check.
    -          !!(goog.global['navigator'] &&
    -              goog.global['navigator']['msMaxTouchPoints']))
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/events/event.js b/src/database/third_party/closure-library/closure/goog/events/event.js
    deleted file mode 100644
    index b671289c206..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/event.js
    +++ /dev/null
    @@ -1,143 +0,0 @@
    -// Copyright 2005 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A base class for event objects.
    - *
    - */
    -
    -
    -goog.provide('goog.events.Event');
    -goog.provide('goog.events.EventLike');
    -
    -/**
    - * goog.events.Event no longer depends on goog.Disposable. Keep requiring
    - * goog.Disposable here to not break projects which assume this dependency.
    - * @suppress {extraRequire}
    - */
    -goog.require('goog.Disposable');
    -goog.require('goog.events.EventId');
    -
    -
    -/**
    - * A typedef for event like objects that are dispatchable via the
    - * goog.events.dispatchEvent function. strings are treated as the type for a
    - * goog.events.Event. Objects are treated as an extension of a new
    - * goog.events.Event with the type property of the object being used as the type
    - * of the Event.
    - * @typedef {string|Object|goog.events.Event|goog.events.EventId}
    - */
    -goog.events.EventLike;
    -
    -
    -
    -/**
    - * A base class for event objects, so that they can support preventDefault and
    - * stopPropagation.
    - *
    - * @param {string|!goog.events.EventId} type Event Type.
    - * @param {Object=} opt_target Reference to the object that is the target of
    - *     this event. It has to implement the {@code EventTarget} interface
    - *     declared at {@link http://developer.mozilla.org/en/DOM/EventTarget}.
    - * @constructor
    - */
    -goog.events.Event = function(type, opt_target) {
    -  /**
    -   * Event type.
    -   * @type {string}
    -   */
    -  this.type = type instanceof goog.events.EventId ? String(type) : type;
    -
    -  /**
    -   * TODO(tbreisacher): The type should probably be
    -   * EventTarget|goog.events.EventTarget.
    -   *
    -   * Target of the event.
    -   * @type {Object|undefined}
    -   */
    -  this.target = opt_target;
    -
    -  /**
    -   * Object that had the listener attached.
    -   * @type {Object|undefined}
    -   */
    -  this.currentTarget = this.target;
    -
    -  /**
    -   * Whether to cancel the event in internal capture/bubble processing for IE.
    -   * @type {boolean}
    -   * @public
    -   * @suppress {underscore|visibility} Technically public, but referencing this
    -   *     outside this package is strongly discouraged.
    -   */
    -  this.propagationStopped_ = false;
    -
    -  /**
    -   * Whether the default action has been prevented.
    -   * This is a property to match the W3C specification at
    -   * {@link http://www.w3.org/TR/DOM-Level-3-Events/
    -   * #events-event-type-defaultPrevented}.
    -   * Must be treated as read-only outside the class.
    -   * @type {boolean}
    -   */
    -  this.defaultPrevented = false;
    -
    -  /**
    -   * Return value for in internal capture/bubble processing for IE.
    -   * @type {boolean}
    -   * @public
    -   * @suppress {underscore|visibility} Technically public, but referencing this
    -   *     outside this package is strongly discouraged.
    -   */
    -  this.returnValue_ = true;
    -};
    -
    -
    -/**
    - * Stops event propagation.
    - */
    -goog.events.Event.prototype.stopPropagation = function() {
    -  this.propagationStopped_ = true;
    -};
    -
    -
    -/**
    - * Prevents the default action, for example a link redirecting to a url.
    - */
    -goog.events.Event.prototype.preventDefault = function() {
    -  this.defaultPrevented = true;
    -  this.returnValue_ = false;
    -};
    -
    -
    -/**
    - * Stops the propagation of the event. It is equivalent to
    - * {@code e.stopPropagation()}, but can be used as the callback argument of
    - * {@link goog.events.listen} without declaring another function.
    - * @param {!goog.events.Event} e An event.
    - */
    -goog.events.Event.stopPropagation = function(e) {
    -  e.stopPropagation();
    -};
    -
    -
    -/**
    - * Prevents the default action. It is equivalent to
    - * {@code e.preventDefault()}, but can be used as the callback argument of
    - * {@link goog.events.listen} without declaring another function.
    - * @param {!goog.events.Event} e An event.
    - */
    -goog.events.Event.preventDefault = function(e) {
    -  e.preventDefault();
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/events/event_test.html b/src/database/third_party/closure-library/closure/goog/events/event_test.html
    deleted file mode 100644
    index 744fe8a2671..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/event_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!-- Author:  attila@google.com (Attila Bodis) -->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.events.Event
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.events.EventTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/events/event_test.js b/src/database/third_party/closure-library/closure/goog/events/event_test.js
    deleted file mode 100644
    index 826fe876ae0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/event_test.js
    +++ /dev/null
    @@ -1,68 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.events.EventTest');
    -goog.setTestOnly('goog.events.EventTest');
    -
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventId');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.testing.jsunit');
    -
    -var e, target;
    -
    -function setUp() {
    -  target = new goog.events.EventTarget();
    -  e = new goog.events.Event('eventType', target);
    -}
    -
    -function tearDown() {
    -  target.dispose();
    -}
    -
    -function testConstructor() {
    -  assertNotNull('Event must not be null', e);
    -  assertEquals('Event type must be as expected', 'eventType', e.type);
    -  assertEquals('Event target must be as expected', target, e.target);
    -  assertEquals('Current target must be as expected', target,
    -      e.currentTarget);
    -}
    -
    -function testStopPropagation() {
    -  // This test breaks encapsulation because there is no public getter for
    -  // propagationStopped_.
    -  assertFalse('Propagation must not have been stopped',
    -      e.propagationStopped_);
    -  e.stopPropagation();
    -  assertTrue('Propagation must have been stopped', e.propagationStopped_);
    -}
    -
    -function testPreventDefault() {
    -  // This test breaks encapsulation because there is no public getter for
    -  // returnValue_.
    -  assertTrue('Return value must be true', e.returnValue_);
    -  e.preventDefault();
    -  assertFalse('Return value must be false', e.returnValue_);
    -}
    -
    -function testDefaultPrevented() {
    -  assertFalse('Default action must not be prevented', e.defaultPrevented);
    -  e.preventDefault();
    -  assertTrue('Default action must be prevented', e.defaultPrevented);
    -}
    -
    -function testEventId() {
    -  e = new goog.events.Event(new goog.events.EventId('eventType'));
    -  assertEquals('Event type must be as expected', 'eventType', e.type);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/events/eventhandler.js b/src/database/third_party/closure-library/closure/goog/events/eventhandler.js
    deleted file mode 100644
    index 16b1ad0ff7a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/eventhandler.js
    +++ /dev/null
    @@ -1,459 +0,0 @@
    -// Copyright 2005 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Class to create objects which want to handle multiple events
    - * and have their listeners easily cleaned up via a dispose method.
    - *
    - * Example:
    - * <pre>
    - * function Something() {
    - *   Something.base(this);
    - *
    - *   ... set up object ...
    - *
    - *   // Add event listeners
    - *   this.listen(this.starEl, goog.events.EventType.CLICK, this.handleStar);
    - *   this.listen(this.headerEl, goog.events.EventType.CLICK, this.expand);
    - *   this.listen(this.collapseEl, goog.events.EventType.CLICK, this.collapse);
    - *   this.listen(this.infoEl, goog.events.EventType.MOUSEOVER, this.showHover);
    - *   this.listen(this.infoEl, goog.events.EventType.MOUSEOUT, this.hideHover);
    - * }
    - * goog.inherits(Something, goog.events.EventHandler);
    - *
    - * Something.prototype.disposeInternal = function() {
    - *   Something.base(this, 'disposeInternal');
    - *   goog.dom.removeNode(this.container);
    - * };
    - *
    - *
    - * // Then elsewhere:
    - *
    - * var activeSomething = null;
    - * function openSomething() {
    - *   activeSomething = new Something();
    - * }
    - *
    - * function closeSomething() {
    - *   if (activeSomething) {
    - *     activeSomething.dispose();  // Remove event listeners
    - *     activeSomething = null;
    - *   }
    - * }
    - * </pre>
    - *
    - */
    -
    -goog.provide('goog.events.EventHandler');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.events');
    -goog.require('goog.object');
    -
    -goog.forwardDeclare('goog.events.EventWrapper');
    -
    -
    -
    -/**
    - * Super class for objects that want to easily manage a number of event
    - * listeners.  It allows a short cut to listen and also provides a quick way
    - * to remove all events listeners belonging to this object.
    - * @param {SCOPE=} opt_scope Object in whose scope to call the listeners.
    - * @constructor
    - * @extends {goog.Disposable}
    - * @template SCOPE
    - */
    -goog.events.EventHandler = function(opt_scope) {
    -  goog.Disposable.call(this);
    -  // TODO(mknichel): Rename this to this.scope_ and fix the classes in google3
    -  // that access this private variable. :(
    -  this.handler_ = opt_scope;
    -
    -  /**
    -   * Keys for events that are being listened to.
    -   * @type {!Object<!goog.events.Key>}
    -   * @private
    -   */
    -  this.keys_ = {};
    -};
    -goog.inherits(goog.events.EventHandler, goog.Disposable);
    -
    -
    -/**
    - * Utility array used to unify the cases of listening for an array of types
    - * and listening for a single event, without using recursion or allocating
    - * an array each time.
    - * @type {!Array<string>}
    - * @const
    - * @private
    - */
    -goog.events.EventHandler.typeArray_ = [];
    -
    -
    -/**
    - * Listen to an event on a Listenable.  If the function is omitted then the
    - * EventHandler's handleEvent method will be used.
    - * @param {goog.events.ListenableType} src Event source.
    - * @param {string|Array<string>|
    - *     !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
    - *     type Event type to listen for or array of event types.
    - * @param {function(this:SCOPE, EVENTOBJ):?|{handleEvent:function(?):?}|null=}
    - *     opt_fn Optional callback function to be used as the listener or an object
    - *     with handleEvent function.
    - * @param {boolean=} opt_capture Optional whether to use capture phase.
    - * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
    - *     chaining of calls.
    - * @template EVENTOBJ
    - */
    -goog.events.EventHandler.prototype.listen = function(
    -    src, type, opt_fn, opt_capture) {
    -  return this.listen_(src, type, opt_fn, opt_capture);
    -};
    -
    -
    -/**
    - * Listen to an event on a Listenable.  If the function is omitted then the
    - * EventHandler's handleEvent method will be used.
    - * @param {goog.events.ListenableType} src Event source.
    - * @param {string|Array<string>|
    - *     !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
    - *     type Event type to listen for or array of event types.
    - * @param {function(this:T, EVENTOBJ):?|{handleEvent:function(this:T, ?):?}|
    - *     null|undefined} fn Optional callback function to be used as the
    - *     listener or an object with handleEvent function.
    - * @param {boolean|undefined} capture Optional whether to use capture phase.
    - * @param {T} scope Object in whose scope to call the listener.
    - * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
    - *     chaining of calls.
    - * @template T,EVENTOBJ
    - */
    -goog.events.EventHandler.prototype.listenWithScope = function(
    -    src, type, fn, capture, scope) {
    -  // TODO(mknichel): Deprecate this function.
    -  return this.listen_(src, type, fn, capture, scope);
    -};
    -
    -
    -/**
    - * Listen to an event on a Listenable.  If the function is omitted then the
    - * EventHandler's handleEvent method will be used.
    - * @param {goog.events.ListenableType} src Event source.
    - * @param {string|Array<string>|
    - *     !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
    - *     type Event type to listen for or array of event types.
    - * @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null=} opt_fn
    - *     Optional callback function to be used as the listener or an object with
    - *     handleEvent function.
    - * @param {boolean=} opt_capture Optional whether to use capture phase.
    - * @param {Object=} opt_scope Object in whose scope to call the listener.
    - * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
    - *     chaining of calls.
    - * @template EVENTOBJ
    - * @private
    - */
    -goog.events.EventHandler.prototype.listen_ = function(src, type, opt_fn,
    -                                                      opt_capture,
    -                                                      opt_scope) {
    -  if (!goog.isArray(type)) {
    -    if (type) {
    -      goog.events.EventHandler.typeArray_[0] = type.toString();
    -    }
    -    type = goog.events.EventHandler.typeArray_;
    -  }
    -  for (var i = 0; i < type.length; i++) {
    -    var listenerObj = goog.events.listen(
    -        src, type[i], opt_fn || this.handleEvent,
    -        opt_capture || false,
    -        opt_scope || this.handler_ || this);
    -
    -    if (!listenerObj) {
    -      // When goog.events.listen run on OFF_AND_FAIL or OFF_AND_SILENT
    -      // (goog.events.CaptureSimulationMode) in IE8-, it will return null
    -      // value.
    -      return this;
    -    }
    -
    -    var key = listenerObj.key;
    -    this.keys_[key] = listenerObj;
    -  }
    -
    -  return this;
    -};
    -
    -
    -/**
    - * Listen to an event on a Listenable.  If the function is omitted, then the
    - * EventHandler's handleEvent method will be used. After the event has fired the
    - * event listener is removed from the target. If an array of event types is
    - * provided, each event type will be listened to once.
    - * @param {goog.events.ListenableType} src Event source.
    - * @param {string|Array<string>|
    - *     !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
    - *     type Event type to listen for or array of event types.
    - * @param {function(this:SCOPE, EVENTOBJ):?|{handleEvent:function(?):?}|null=} opt_fn
    - *    Optional callback function to be used as the listener or an object with
    - *    handleEvent function.
    - * @param {boolean=} opt_capture Optional whether to use capture phase.
    - * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
    - *     chaining of calls.
    - * @template EVENTOBJ
    - */
    -goog.events.EventHandler.prototype.listenOnce = function(
    -    src, type, opt_fn, opt_capture) {
    -  return this.listenOnce_(src, type, opt_fn, opt_capture);
    -};
    -
    -
    -/**
    - * Listen to an event on a Listenable.  If the function is omitted, then the
    - * EventHandler's handleEvent method will be used. After the event has fired the
    - * event listener is removed from the target. If an array of event types is
    - * provided, each event type will be listened to once.
    - * @param {goog.events.ListenableType} src Event source.
    - * @param {string|Array<string>|
    - *     !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
    - *     type Event type to listen for or array of event types.
    - * @param {function(this:T, EVENTOBJ):?|{handleEvent:function(this:T, ?):?}|
    - *     null|undefined} fn Optional callback function to be used as the
    - *     listener or an object with handleEvent function.
    - * @param {boolean|undefined} capture Optional whether to use capture phase.
    - * @param {T} scope Object in whose scope to call the listener.
    - * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
    - *     chaining of calls.
    - * @template T,EVENTOBJ
    - */
    -goog.events.EventHandler.prototype.listenOnceWithScope = function(
    -    src, type, fn, capture, scope) {
    -  // TODO(mknichel): Deprecate this function.
    -  return this.listenOnce_(src, type, fn, capture, scope);
    -};
    -
    -
    -/**
    - * Listen to an event on a Listenable.  If the function is omitted, then the
    - * EventHandler's handleEvent method will be used. After the event has fired
    - * the event listener is removed from the target. If an array of event types is
    - * provided, each event type will be listened to once.
    - * @param {goog.events.ListenableType} src Event source.
    - * @param {string|Array<string>|
    - *     !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
    - *     type Event type to listen for or array of event types.
    - * @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null=} opt_fn
    - *    Optional callback function to be used as the listener or an object with
    - *    handleEvent function.
    - * @param {boolean=} opt_capture Optional whether to use capture phase.
    - * @param {Object=} opt_scope Object in whose scope to call the listener.
    - * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
    - *     chaining of calls.
    - * @template EVENTOBJ
    - * @private
    - */
    -goog.events.EventHandler.prototype.listenOnce_ = function(
    -    src, type, opt_fn, opt_capture, opt_scope) {
    -  if (goog.isArray(type)) {
    -    for (var i = 0; i < type.length; i++) {
    -      this.listenOnce_(src, type[i], opt_fn, opt_capture, opt_scope);
    -    }
    -  } else {
    -    var listenerObj = goog.events.listenOnce(
    -        src, type, opt_fn || this.handleEvent, opt_capture,
    -        opt_scope || this.handler_ || this);
    -    if (!listenerObj) {
    -      // When goog.events.listen run on OFF_AND_FAIL or OFF_AND_SILENT
    -      // (goog.events.CaptureSimulationMode) in IE8-, it will return null
    -      // value.
    -      return this;
    -    }
    -
    -    var key = listenerObj.key;
    -    this.keys_[key] = listenerObj;
    -  }
    -
    -  return this;
    -};
    -
    -
    -/**
    - * Adds an event listener with a specific event wrapper on a DOM Node or an
    - * object that has implemented {@link goog.events.EventTarget}. A listener can
    - * only be added once to an object.
    - *
    - * @param {EventTarget|goog.events.EventTarget} src The node to listen to
    - *     events on.
    - * @param {goog.events.EventWrapper} wrapper Event wrapper to use.
    - * @param {function(this:SCOPE, ?):?|{handleEvent:function(?):?}|null} listener
    - *     Callback method, or an object with a handleEvent function.
    - * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
    - *     false).
    - * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
    - *     chaining of calls.
    - */
    -goog.events.EventHandler.prototype.listenWithWrapper = function(
    -    src, wrapper, listener, opt_capt) {
    -  // TODO(mknichel): Remove the opt_scope from this function and then
    -  // templatize it.
    -  return this.listenWithWrapper_(src, wrapper, listener, opt_capt);
    -};
    -
    -
    -/**
    - * Adds an event listener with a specific event wrapper on a DOM Node or an
    - * object that has implemented {@link goog.events.EventTarget}. A listener can
    - * only be added once to an object.
    - *
    - * @param {EventTarget|goog.events.EventTarget} src The node to listen to
    - *     events on.
    - * @param {goog.events.EventWrapper} wrapper Event wrapper to use.
    - * @param {function(this:T, ?):?|{handleEvent:function(this:T, ?):?}|null}
    - *     listener Optional callback function to be used as the
    - *     listener or an object with handleEvent function.
    - * @param {boolean|undefined} capture Optional whether to use capture phase.
    - * @param {T} scope Object in whose scope to call the listener.
    - * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
    - *     chaining of calls.
    - * @template T
    - */
    -goog.events.EventHandler.prototype.listenWithWrapperAndScope = function(
    -    src, wrapper, listener, capture, scope) {
    -  // TODO(mknichel): Deprecate this function.
    -  return this.listenWithWrapper_(src, wrapper, listener, capture, scope);
    -};
    -
    -
    -/**
    - * Adds an event listener with a specific event wrapper on a DOM Node or an
    - * object that has implemented {@link goog.events.EventTarget}. A listener can
    - * only be added once to an object.
    - *
    - * @param {EventTarget|goog.events.EventTarget} src The node to listen to
    - *     events on.
    - * @param {goog.events.EventWrapper} wrapper Event wrapper to use.
    - * @param {function(?):?|{handleEvent:function(?):?}|null} listener Callback
    - *     method, or an object with a handleEvent function.
    - * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
    - *     false).
    - * @param {Object=} opt_scope Element in whose scope to call the listener.
    - * @return {!goog.events.EventHandler<SCOPE>} This object, allowing for
    - *     chaining of calls.
    - * @private
    - */
    -goog.events.EventHandler.prototype.listenWithWrapper_ = function(
    -    src, wrapper, listener, opt_capt, opt_scope) {
    -  wrapper.listen(src, listener, opt_capt, opt_scope || this.handler_ || this,
    -                 this);
    -  return this;
    -};
    -
    -
    -/**
    - * @return {number} Number of listeners registered by this handler.
    - */
    -goog.events.EventHandler.prototype.getListenerCount = function() {
    -  var count = 0;
    -  for (var key in this.keys_) {
    -    if (Object.prototype.hasOwnProperty.call(this.keys_, key)) {
    -      count++;
    -    }
    -  }
    -  return count;
    -};
    -
    -
    -/**
    - * Unlistens on an event.
    - * @param {goog.events.ListenableType} src Event source.
    - * @param {string|Array<string>|
    - *     !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
    - *     type Event type or array of event types to unlisten to.
    - * @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null=} opt_fn
    - *     Optional callback function to be used as the listener or an object with
    - *     handleEvent function.
    - * @param {boolean=} opt_capture Optional whether to use capture phase.
    - * @param {Object=} opt_scope Object in whose scope to call the listener.
    - * @return {!goog.events.EventHandler} This object, allowing for chaining of
    - *     calls.
    - * @template EVENTOBJ
    - */
    -goog.events.EventHandler.prototype.unlisten = function(src, type, opt_fn,
    -                                                       opt_capture,
    -                                                       opt_scope) {
    -  if (goog.isArray(type)) {
    -    for (var i = 0; i < type.length; i++) {
    -      this.unlisten(src, type[i], opt_fn, opt_capture, opt_scope);
    -    }
    -  } else {
    -    var listener = goog.events.getListener(src, type,
    -        opt_fn || this.handleEvent,
    -        opt_capture, opt_scope || this.handler_ || this);
    -
    -    if (listener) {
    -      goog.events.unlistenByKey(listener);
    -      delete this.keys_[listener.key];
    -    }
    -  }
    -
    -  return this;
    -};
    -
    -
    -/**
    - * Removes an event listener which was added with listenWithWrapper().
    - *
    - * @param {EventTarget|goog.events.EventTarget} src The target to stop
    - *     listening to events on.
    - * @param {goog.events.EventWrapper} wrapper Event wrapper to use.
    - * @param {function(?):?|{handleEvent:function(?):?}|null} listener The
    - *     listener function to remove.
    - * @param {boolean=} opt_capt In DOM-compliant browsers, this determines
    - *     whether the listener is fired during the capture or bubble phase of the
    - *     event.
    - * @param {Object=} opt_scope Element in whose scope to call the listener.
    - * @return {!goog.events.EventHandler} This object, allowing for chaining of
    - *     calls.
    - */
    -goog.events.EventHandler.prototype.unlistenWithWrapper = function(src, wrapper,
    -    listener, opt_capt, opt_scope) {
    -  wrapper.unlisten(src, listener, opt_capt,
    -                   opt_scope || this.handler_ || this, this);
    -  return this;
    -};
    -
    -
    -/**
    - * Unlistens to all events.
    - */
    -goog.events.EventHandler.prototype.removeAll = function() {
    -  goog.object.forEach(this.keys_, goog.events.unlistenByKey);
    -  this.keys_ = {};
    -};
    -
    -
    -/**
    - * Disposes of this EventHandler and removes all listeners that it registered.
    - * @override
    - * @protected
    - */
    -goog.events.EventHandler.prototype.disposeInternal = function() {
    -  goog.events.EventHandler.superClass_.disposeInternal.call(this);
    -  this.removeAll();
    -};
    -
    -
    -/**
    - * Default event handler
    - * @param {goog.events.Event} e Event object.
    - */
    -goog.events.EventHandler.prototype.handleEvent = function(e) {
    -  throw Error('EventHandler.handleEvent not implemented');
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/events/eventhandler_test.html b/src/database/third_party/closure-library/closure/goog/events/eventhandler_test.html
    deleted file mode 100644
    index eb470fc0311..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/eventhandler_test.html
    +++ /dev/null
    @@ -1,30 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.events.EventHandler
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.events.EventHandlerTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="a">
    -  </div>
    -  <div id="b">
    -  </div>
    -  <div id="c">
    -  </div>
    -  <div id="d">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/events/eventhandler_test.js b/src/database/third_party/closure-library/closure/goog/events/eventhandler_test.js
    deleted file mode 100644
    index f85aaea9293..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/eventhandler_test.js
    +++ /dev/null
    @@ -1,247 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.events.EventHandlerTest');
    -goog.setTestOnly('goog.events.EventHandlerTest');
    -
    -goog.require('goog.events');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -
    -var a, b, c, d, eh;
    -
    -function setUpPage() {
    -  a = document.getElementById('a');
    -  b = document.getElementById('b');
    -  c = document.getElementById('c');
    -  d = document.getElementById('d');
    -}
    -
    -
    -function tearDown() {
    -  goog.dispose(eh);
    -}
    -
    -function testEventHandlerClearsListeners() {
    -  function tmp() {}
    -
    -  goog.events.listen(a, 'click', tmp);
    -
    -  assertEquals(1, goog.events.getListeners(a, 'click', false).length);
    -
    -  eh = new goog.events.EventHandler();
    -  eh.listen(a, 'click');
    -  eh.listen(a, 'keypress');
    -  eh.listen(b, 'mouseover');
    -  eh.listen(c, 'mousedown');
    -  eh.listen(d, 'click');
    -  eh.listen(d, 'mousedown');
    -
    -  assertEquals(2, goog.events.getListeners(a, 'click', false).length);
    -  assertEquals(1, goog.events.getListeners(a, 'keypress', false).length);
    -  assertEquals(1, goog.events.getListeners(b, 'mouseover', false).length);
    -  assertEquals(1, goog.events.getListeners(c, 'mousedown', false).length);
    -  assertEquals(1, goog.events.getListeners(d, 'click', false).length);
    -  assertEquals(1, goog.events.getListeners(d, 'mousedown', false).length);
    -
    -  eh.unlisten(d, 'mousedown');
    -
    -  assertEquals(2, goog.events.getListeners(a, 'click', false).length);
    -  assertEquals(1, goog.events.getListeners(a, 'keypress', false).length);
    -  assertEquals(1, goog.events.getListeners(b, 'mouseover', false).length);
    -  assertEquals(1, goog.events.getListeners(c, 'mousedown', false).length);
    -  assertEquals(1, goog.events.getListeners(d, 'click', false).length);
    -  assertEquals(0, goog.events.getListeners(d, 'mousedown', false).length);
    -
    -  eh.dispose();
    -
    -  assertEquals(1, goog.events.getListeners(a, 'click', false).length);
    -  assertEquals(0, goog.events.getListeners(a, 'keypress', false).length);
    -  assertEquals(0, goog.events.getListeners(b, 'mouseover', false).length);
    -  assertEquals(0, goog.events.getListeners(c, 'mousedown', false).length);
    -  assertEquals(0, goog.events.getListeners(d, 'click', false).length);
    -  assertEquals(0, goog.events.getListeners(d, 'mousedown', false).length);
    -
    -  goog.events.unlisten(a, 'click', tmp);
    -  assertEquals(0, goog.events.getListeners(a, 'click', false).length);
    -}
    -
    -function testListenArray() {
    -  eh = new goog.events.EventHandler();
    -
    -  eh.listen(a, ['click', 'mousedown', 'mouseup']);
    -
    -  assertEquals(1, goog.events.getListeners(a, 'click', false).length);
    -  assertEquals(1, goog.events.getListeners(a, 'mousedown', false).length);
    -  assertEquals(1, goog.events.getListeners(a, 'mouseup', false).length);
    -
    -  eh.unlisten(a, ['click', 'mousedown', 'mouseup']);
    -
    -  assertEquals(0, goog.events.getListeners(a, 'click', false).length);
    -  assertEquals(0, goog.events.getListeners(a, 'mousedown', false).length);
    -  assertEquals(0, goog.events.getListeners(a, 'mouseup', false).length);
    -
    -  eh.listen(a, ['click', 'mousedown', 'mouseup']);
    -
    -  assertEquals(1, goog.events.getListeners(a, 'click', false).length);
    -  assertEquals(1, goog.events.getListeners(a, 'mousedown', false).length);
    -  assertEquals(1, goog.events.getListeners(a, 'mouseup', false).length);
    -
    -  eh.removeAll();
    -
    -  assertEquals(0, goog.events.getListeners(a, 'click', false).length);
    -  assertEquals(0, goog.events.getListeners(a, 'mousedown', false).length);
    -  assertEquals(0, goog.events.getListeners(a, 'mouseup', false).length);
    -}
    -
    -function testListenOnceRemovesListenerWhenFired() {
    -  var target = new goog.events.EventTarget();
    -  eh = new goog.events.EventHandler();
    -  var handler = goog.testing.recordFunction();
    -  eh.listenOnce(target, 'click', handler);
    -
    -  target.dispatchEvent('click');
    -  assertEquals('One event should have been dispatched',
    -      1, handler.getCallCount());
    -
    -  target.dispatchEvent('click');
    -  assertEquals('No event should have been dispatched',
    -      1, handler.getCallCount());
    -}
    -
    -function testListenOnceListenerIsCleanedUp() {
    -  var target = new goog.events.EventTarget();
    -  eh = new goog.events.EventHandler();
    -  var handler = goog.testing.recordFunction();
    -  eh.listenOnce(target, 'click', handler);
    -
    -  eh.removeAll();
    -
    -  target.dispatchEvent('click');
    -  assertEquals(0, handler.getCallCount());
    -}
    -
    -function testClearListenersWithListenOnceListenerRemoved() {
    -  var target = new goog.events.EventTarget();
    -  eh = new goog.events.EventHandler();
    -
    -  var handler = goog.testing.recordFunction();
    -  eh.listenOnce(target, 'click', handler);
    -
    -  assertNotNull(goog.events.getListener(target, 'click', handler, false, eh));
    -
    -  target.dispatchEvent('click');
    -  assertEquals('One event should have been dispatched',
    -      1, handler.getCallCount());
    -
    -  assertNull(goog.events.getListener(target, 'click', handler, false, eh));
    -
    -  eh.removeAll();
    -
    -  target.dispatchEvent('click');
    -  assertEquals('No event should have been dispatched',
    -      1, handler.getCallCount());
    -}
    -
    -function testListenOnceArray() {
    -  var target = new goog.events.EventTarget();
    -
    -  eh = new goog.events.EventHandler();
    -  var handler = goog.testing.recordFunction();
    -  eh.listenOnce(target, ['click', 'mousedown', 'mouseup'], handler);
    -
    -  target.dispatchEvent('click');
    -  assertEquals('1 event should have been dispatched',
    -      1, handler.getCallCount());
    -  assertEquals('Should be a click event',
    -      'click', handler.getLastCall().getArgument(0).type);
    -
    -  target.dispatchEvent('click');
    -  assertEquals('No event should be dispatched',
    -      1, handler.getCallCount());
    -
    -  target.dispatchEvent('mouseup');
    -  assertEquals('1 event should have been dispatched',
    -      2, handler.getCallCount());
    -  assertEquals('Should be a mouseup event',
    -      'mouseup', handler.getLastCall().getArgument(0).type);
    -
    -  target.dispatchEvent('mouseup');
    -  assertEquals('No event should be dispatched',
    -      2, handler.getCallCount());
    -
    -  target.dispatchEvent('mousedown');
    -  assertEquals('1 event should have been dispatched',
    -      3, handler.getCallCount());
    -  assertEquals('Should be a mousedown event',
    -      'mousedown', handler.getLastCall().getArgument(0).type);
    -
    -  target.dispatchEvent('mousedown');
    -  assertEquals('No event should be dispatched',
    -      3, handler.getCallCount());
    -}
    -
    -function testListenUnlistenWithObjectHandler() {
    -  var target = new goog.events.EventTarget();
    -  eh = new goog.events.EventHandler();
    -  var handlerObj = {
    -    handleEvent: goog.testing.recordFunction()
    -  };
    -  eh.listen(target, 'click', handlerObj);
    -
    -  target.dispatchEvent('click');
    -  assertEquals('One event should have been dispatched',
    -      1, handlerObj.handleEvent.getCallCount());
    -
    -  target.dispatchEvent('click');
    -  assertEquals('One event should have been dispatched',
    -      2, handlerObj.handleEvent.getCallCount());
    -
    -  eh.unlisten(target, 'click', handlerObj);
    -  target.dispatchEvent('click');
    -  assertEquals('No event should have been dispatched',
    -      2, handlerObj.handleEvent.getCallCount());
    -}
    -
    -function testListenOnceWithObjectHandler() {
    -  var target = new goog.events.EventTarget();
    -  eh = new goog.events.EventHandler();
    -  var handlerObj = {
    -    handleEvent: goog.testing.recordFunction()
    -  };
    -  eh.listenOnce(target, 'click', handlerObj);
    -
    -  target.dispatchEvent('click');
    -  assertEquals('One event should have been dispatched',
    -      1, handlerObj.handleEvent.getCallCount());
    -
    -  target.dispatchEvent('click');
    -  assertEquals('No event should have been dispatched',
    -      1, handlerObj.handleEvent.getCallCount());
    -}
    -
    -function testGetListenerCount() {
    -  eh = new goog.events.EventHandler();
    -  assertEquals('0 listeners registered initially', 0, eh.getListenerCount());
    -  var target = new goog.events.EventTarget();
    -  eh.listen(target, 'click', goog.nullFunction, false);
    -  eh.listen(target, 'click', goog.nullFunction, true);
    -  assertEquals('2 listeners registered', 2, eh.getListenerCount());
    -  eh.unlisten(target, 'click', goog.nullFunction, true);
    -  assertEquals('1 listener removed, 1 left', 1, eh.getListenerCount());
    -  eh.removeAll();
    -  assertEquals('all listeners removed', 0, eh.getListenerCount());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/events/eventid.js b/src/database/third_party/closure-library/closure/goog/events/eventid.js
    deleted file mode 100644
    index 9a4822e5f6d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/eventid.js
    +++ /dev/null
    @@ -1,47 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.events.EventId');
    -
    -
    -
    -/**
    - * A templated class that is used when registering for events. Typical usage:
    - * <code>
    - *   /** @type {goog.events.EventId<MyEventObj>}
    - *   var myEventId = new goog.events.EventId(
    - *       goog.events.getUniqueId(('someEvent'));
    - *
    - *   // No need to cast or declare here since the compiler knows the correct
    - *   // type of 'evt' (MyEventObj).
    - *   something.listen(myEventId, function(evt) {});
    - * </code>
    - *
    - * @param {string} eventId
    - * @template T
    - * @constructor
    - * @struct
    - * @final
    - */
    -goog.events.EventId = function(eventId) {
    -  /** @const */ this.id = eventId;
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.events.EventId.prototype.toString = function() {
    -  return this.id;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/events/events.js b/src/database/third_party/closure-library/closure/goog/events/events.js
    deleted file mode 100644
    index 39cc405ccf7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/events.js
    +++ /dev/null
    @@ -1,983 +0,0 @@
    -// Copyright 2005 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview An event manager for both native browser event
    - * targets and custom JavaScript event targets
    - * ({@code goog.events.Listenable}). This provides an abstraction
    - * over browsers' event systems.
    - *
    - * It also provides a simulation of W3C event model's capture phase in
    - * Internet Explorer (IE 8 and below). Caveat: the simulation does not
    - * interact well with listeners registered directly on the elements
    - * (bypassing goog.events) or even with listeners registered via
    - * goog.events in a separate JS binary. In these cases, we provide
    - * no ordering guarantees.
    - *
    - * The listeners will receive a "patched" event object. Such event object
    - * contains normalized values for certain event properties that differs in
    - * different browsers.
    - *
    - * Example usage:
    - * <pre>
    - * goog.events.listen(myNode, 'click', function(e) { alert('woo') });
    - * goog.events.listen(myNode, 'mouseover', mouseHandler, true);
    - * goog.events.unlisten(myNode, 'mouseover', mouseHandler, true);
    - * goog.events.removeAll(myNode);
    - * </pre>
    - *
    - *                                            in IE and event object patching]
    - * @author arv@google.com (Erik Arvidsson)
    - *
    - * @see ../demos/events.html
    - * @see ../demos/event-propagation.html
    - * @see ../demos/stopevent.html
    - */
    -
    -// IMPLEMENTATION NOTES:
    -// goog.events stores an auxiliary data structure on each EventTarget
    -// source being listened on. This allows us to take advantage of GC,
    -// having the data structure GC'd when the EventTarget is GC'd. This
    -// GC behavior is equivalent to using W3C DOM Events directly.
    -
    -goog.provide('goog.events');
    -goog.provide('goog.events.CaptureSimulationMode');
    -goog.provide('goog.events.Key');
    -goog.provide('goog.events.ListenableType');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.debug.entryPointRegistry');
    -goog.require('goog.events.BrowserEvent');
    -goog.require('goog.events.BrowserFeature');
    -goog.require('goog.events.Listenable');
    -goog.require('goog.events.ListenerMap');
    -
    -goog.forwardDeclare('goog.debug.ErrorHandler');
    -goog.forwardDeclare('goog.events.EventWrapper');
    -
    -
    -/**
    - * @typedef {number|goog.events.ListenableKey}
    - */
    -goog.events.Key;
    -
    -
    -/**
    - * @typedef {EventTarget|goog.events.Listenable}
    - */
    -goog.events.ListenableType;
    -
    -
    -/**
    - * Property name on a native event target for the listener map
    - * associated with the event target.
    - * @private @const {string}
    - */
    -goog.events.LISTENER_MAP_PROP_ = 'closure_lm_' + ((Math.random() * 1e6) | 0);
    -
    -
    -/**
    - * String used to prepend to IE event types.
    - * @const
    - * @private
    - */
    -goog.events.onString_ = 'on';
    -
    -
    -/**
    - * Map of computed "on<eventname>" strings for IE event types. Caching
    - * this removes an extra object allocation in goog.events.listen which
    - * improves IE6 performance.
    - * @const
    - * @dict
    - * @private
    - */
    -goog.events.onStringMap_ = {};
    -
    -
    -/**
    - * @enum {number} Different capture simulation mode for IE8-.
    - */
    -goog.events.CaptureSimulationMode = {
    -  /**
    -   * Does not perform capture simulation. Will asserts in IE8- when you
    -   * add capture listeners.
    -   */
    -  OFF_AND_FAIL: 0,
    -
    -  /**
    -   * Does not perform capture simulation, silently ignore capture
    -   * listeners.
    -   */
    -  OFF_AND_SILENT: 1,
    -
    -  /**
    -   * Performs capture simulation.
    -   */
    -  ON: 2
    -};
    -
    -
    -/**
    - * @define {number} The capture simulation mode for IE8-. By default,
    - *     this is ON.
    - */
    -goog.define('goog.events.CAPTURE_SIMULATION_MODE', 2);
    -
    -
    -/**
    - * Estimated count of total native listeners.
    - * @private {number}
    - */
    -goog.events.listenerCountEstimate_ = 0;
    -
    -
    -/**
    - * Adds an event listener for a specific event on a native event
    - * target (such as a DOM element) or an object that has implemented
    - * {@link goog.events.Listenable}. A listener can only be added once
    - * to an object and if it is added again the key for the listener is
    - * returned. Note that if the existing listener is a one-off listener
    - * (registered via listenOnce), it will no longer be a one-off
    - * listener after a call to listen().
    - *
    - * @param {EventTarget|goog.events.Listenable} src The node to listen
    - *     to events on.
    - * @param {string|Array<string>|
    - *     !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
    - *     type Event type or array of event types.
    - * @param {function(this:T, EVENTOBJ):?|{handleEvent:function(?):?}|null}
    - *     listener Callback method, or an object with a handleEvent function.
    - *     WARNING: passing an Object is now softly deprecated.
    - * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
    - *     false).
    - * @param {T=} opt_handler Element in whose scope to call the listener.
    - * @return {goog.events.Key} Unique key for the listener.
    - * @template T,EVENTOBJ
    - */
    -goog.events.listen = function(src, type, listener, opt_capt, opt_handler) {
    -  if (goog.isArray(type)) {
    -    for (var i = 0; i < type.length; i++) {
    -      goog.events.listen(src, type[i], listener, opt_capt, opt_handler);
    -    }
    -    return null;
    -  }
    -
    -  listener = goog.events.wrapListener(listener);
    -  if (goog.events.Listenable.isImplementedBy(src)) {
    -    return src.listen(
    -        /** @type {string|!goog.events.EventId} */ (type),
    -        listener, opt_capt, opt_handler);
    -  } else {
    -    return goog.events.listen_(
    -        /** @type {!EventTarget} */ (src),
    -        /** @type {string|!goog.events.EventId} */ (type),
    -        listener, /* callOnce */ false, opt_capt, opt_handler);
    -  }
    -};
    -
    -
    -/**
    - * Adds an event listener for a specific event on a native event
    - * target. A listener can only be added once to an object and if it
    - * is added again the key for the listener is returned.
    - *
    - * Note that a one-off listener will not change an existing listener,
    - * if any. On the other hand a normal listener will change existing
    - * one-off listener to become a normal listener.
    - *
    - * @param {EventTarget} src The node to listen to events on.
    - * @param {string|!goog.events.EventId} type Event type.
    - * @param {!Function} listener Callback function.
    - * @param {boolean} callOnce Whether the listener is a one-off
    - *     listener or otherwise.
    - * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
    - *     false).
    - * @param {Object=} opt_handler Element in whose scope to call the listener.
    - * @return {goog.events.ListenableKey} Unique key for the listener.
    - * @private
    - */
    -goog.events.listen_ = function(
    -    src, type, listener, callOnce, opt_capt, opt_handler) {
    -  if (!type) {
    -    throw Error('Invalid event type');
    -  }
    -
    -  var capture = !!opt_capt;
    -  if (capture && !goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT) {
    -    if (goog.events.CAPTURE_SIMULATION_MODE ==
    -        goog.events.CaptureSimulationMode.OFF_AND_FAIL) {
    -      goog.asserts.fail('Can not register capture listener in IE8-.');
    -      return null;
    -    } else if (goog.events.CAPTURE_SIMULATION_MODE ==
    -        goog.events.CaptureSimulationMode.OFF_AND_SILENT) {
    -      return null;
    -    }
    -  }
    -
    -  var listenerMap = goog.events.getListenerMap_(src);
    -  if (!listenerMap) {
    -    src[goog.events.LISTENER_MAP_PROP_] = listenerMap =
    -        new goog.events.ListenerMap(src);
    -  }
    -
    -  var listenerObj = listenerMap.add(
    -      type, listener, callOnce, opt_capt, opt_handler);
    -
    -  // If the listenerObj already has a proxy, it has been set up
    -  // previously. We simply return.
    -  if (listenerObj.proxy) {
    -    return listenerObj;
    -  }
    -
    -  var proxy = goog.events.getProxy();
    -  listenerObj.proxy = proxy;
    -
    -  proxy.src = src;
    -  proxy.listener = listenerObj;
    -
    -  // Attach the proxy through the browser's API
    -  if (src.addEventListener) {
    -    src.addEventListener(type.toString(), proxy, capture);
    -  } else {
    -    // The else above used to be else if (src.attachEvent) and then there was
    -    // another else statement that threw an exception warning the developer
    -    // they made a mistake. This resulted in an extra object allocation in IE6
    -    // due to a wrapper object that had to be implemented around the element
    -    // and so was removed.
    -    src.attachEvent(goog.events.getOnString_(type.toString()), proxy);
    -  }
    -
    -  goog.events.listenerCountEstimate_++;
    -  return listenerObj;
    -};
    -
    -
    -/**
    - * Helper function for returning a proxy function.
    - * @return {!Function} A new or reused function object.
    - */
    -goog.events.getProxy = function() {
    -  var proxyCallbackFunction = goog.events.handleBrowserEvent_;
    -  // Use a local var f to prevent one allocation.
    -  var f = goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT ?
    -      function(eventObject) {
    -        return proxyCallbackFunction.call(f.src, f.listener, eventObject);
    -      } :
    -      function(eventObject) {
    -        var v = proxyCallbackFunction.call(f.src, f.listener, eventObject);
    -        // NOTE(chrishenry): In IE, we hack in a capture phase. However, if
    -        // there is inline event handler which tries to prevent default (for
    -        // example <a href="..." onclick="return false">...</a>) in a
    -        // descendant element, the prevent default will be overridden
    -        // by this listener if this listener were to return true. Hence, we
    -        // return undefined.
    -        if (!v) return v;
    -      };
    -  return f;
    -};
    -
    -
    -/**
    - * Adds an event listener for a specific event on a native event
    - * target (such as a DOM element) or an object that has implemented
    - * {@link goog.events.Listenable}. After the event has fired the event
    - * listener is removed from the target.
    - *
    - * If an existing listener already exists, listenOnce will do
    - * nothing. In particular, if the listener was previously registered
    - * via listen(), listenOnce() will not turn the listener into a
    - * one-off listener. Similarly, if there is already an existing
    - * one-off listener, listenOnce does not modify the listeners (it is
    - * still a once listener).
    - *
    - * @param {EventTarget|goog.events.Listenable} src The node to listen
    - *     to events on.
    - * @param {string|Array<string>|
    - *     !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
    - *     type Event type or array of event types.
    - * @param {function(this:T, EVENTOBJ):?|{handleEvent:function(?):?}|null}
    - *     listener Callback method.
    - * @param {boolean=} opt_capt Fire in capture phase?.
    - * @param {T=} opt_handler Element in whose scope to call the listener.
    - * @return {goog.events.Key} Unique key for the listener.
    - * @template T,EVENTOBJ
    - */
    -goog.events.listenOnce = function(src, type, listener, opt_capt, opt_handler) {
    -  if (goog.isArray(type)) {
    -    for (var i = 0; i < type.length; i++) {
    -      goog.events.listenOnce(src, type[i], listener, opt_capt, opt_handler);
    -    }
    -    return null;
    -  }
    -
    -  listener = goog.events.wrapListener(listener);
    -  if (goog.events.Listenable.isImplementedBy(src)) {
    -    return src.listenOnce(
    -        /** @type {string|!goog.events.EventId} */ (type),
    -        listener, opt_capt, opt_handler);
    -  } else {
    -    return goog.events.listen_(
    -        /** @type {!EventTarget} */ (src),
    -        /** @type {string|!goog.events.EventId} */ (type),
    -        listener, /* callOnce */ true, opt_capt, opt_handler);
    -  }
    -};
    -
    -
    -/**
    - * Adds an event listener with a specific event wrapper on a DOM Node or an
    - * object that has implemented {@link goog.events.Listenable}. A listener can
    - * only be added once to an object.
    - *
    - * @param {EventTarget|goog.events.Listenable} src The target to
    - *     listen to events on.
    - * @param {goog.events.EventWrapper} wrapper Event wrapper to use.
    - * @param {function(this:T, ?):?|{handleEvent:function(?):?}|null} listener
    - *     Callback method, or an object with a handleEvent function.
    - * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
    - *     false).
    - * @param {T=} opt_handler Element in whose scope to call the listener.
    - * @template T
    - */
    -goog.events.listenWithWrapper = function(src, wrapper, listener, opt_capt,
    -    opt_handler) {
    -  wrapper.listen(src, listener, opt_capt, opt_handler);
    -};
    -
    -
    -/**
    - * Removes an event listener which was added with listen().
    - *
    - * @param {EventTarget|goog.events.Listenable} src The target to stop
    - *     listening to events on.
    - * @param {string|Array<string>|
    - *     !goog.events.EventId<EVENTOBJ>|!Array<!goog.events.EventId<EVENTOBJ>>}
    - *     type Event type or array of event types to unlisten to.
    - * @param {function(?):?|{handleEvent:function(?):?}|null} listener The
    - *     listener function to remove.
    - * @param {boolean=} opt_capt In DOM-compliant browsers, this determines
    - *     whether the listener is fired during the capture or bubble phase of the
    - *     event.
    - * @param {Object=} opt_handler Element in whose scope to call the listener.
    - * @return {?boolean} indicating whether the listener was there to remove.
    - * @template EVENTOBJ
    - */
    -goog.events.unlisten = function(src, type, listener, opt_capt, opt_handler) {
    -  if (goog.isArray(type)) {
    -    for (var i = 0; i < type.length; i++) {
    -      goog.events.unlisten(src, type[i], listener, opt_capt, opt_handler);
    -    }
    -    return null;
    -  }
    -
    -  listener = goog.events.wrapListener(listener);
    -  if (goog.events.Listenable.isImplementedBy(src)) {
    -    return src.unlisten(
    -        /** @type {string|!goog.events.EventId} */ (type),
    -        listener, opt_capt, opt_handler);
    -  }
    -
    -  if (!src) {
    -    // TODO(chrishenry): We should tighten the API to only accept
    -    // non-null objects, or add an assertion here.
    -    return false;
    -  }
    -
    -  var capture = !!opt_capt;
    -  var listenerMap = goog.events.getListenerMap_(
    -      /** @type {!EventTarget} */ (src));
    -  if (listenerMap) {
    -    var listenerObj = listenerMap.getListener(
    -        /** @type {string|!goog.events.EventId} */ (type),
    -        listener, capture, opt_handler);
    -    if (listenerObj) {
    -      return goog.events.unlistenByKey(listenerObj);
    -    }
    -  }
    -
    -  return false;
    -};
    -
    -
    -/**
    - * Removes an event listener which was added with listen() by the key
    - * returned by listen().
    - *
    - * @param {goog.events.Key} key The key returned by listen() for this
    - *     event listener.
    - * @return {boolean} indicating whether the listener was there to remove.
    - */
    -goog.events.unlistenByKey = function(key) {
    -  // TODO(chrishenry): Remove this check when tests that rely on this
    -  // are fixed.
    -  if (goog.isNumber(key)) {
    -    return false;
    -  }
    -
    -  var listener = /** @type {goog.events.ListenableKey} */ (key);
    -  if (!listener || listener.removed) {
    -    return false;
    -  }
    -
    -  var src = listener.src;
    -  if (goog.events.Listenable.isImplementedBy(src)) {
    -    return src.unlistenByKey(listener);
    -  }
    -
    -  var type = listener.type;
    -  var proxy = listener.proxy;
    -  if (src.removeEventListener) {
    -    src.removeEventListener(type, proxy, listener.capture);
    -  } else if (src.detachEvent) {
    -    src.detachEvent(goog.events.getOnString_(type), proxy);
    -  }
    -  goog.events.listenerCountEstimate_--;
    -
    -  var listenerMap = goog.events.getListenerMap_(
    -      /** @type {!EventTarget} */ (src));
    -  // TODO(chrishenry): Try to remove this conditional and execute the
    -  // first branch always. This should be safe.
    -  if (listenerMap) {
    -    listenerMap.removeByKey(listener);
    -    if (listenerMap.getTypeCount() == 0) {
    -      // Null the src, just because this is simple to do (and useful
    -      // for IE <= 7).
    -      listenerMap.src = null;
    -      // We don't use delete here because IE does not allow delete
    -      // on a window object.
    -      src[goog.events.LISTENER_MAP_PROP_] = null;
    -    }
    -  } else {
    -    listener.markAsRemoved();
    -  }
    -
    -  return true;
    -};
    -
    -
    -/**
    - * Removes an event listener which was added with listenWithWrapper().
    - *
    - * @param {EventTarget|goog.events.Listenable} src The target to stop
    - *     listening to events on.
    - * @param {goog.events.EventWrapper} wrapper Event wrapper to use.
    - * @param {function(?):?|{handleEvent:function(?):?}|null} listener The
    - *     listener function to remove.
    - * @param {boolean=} opt_capt In DOM-compliant browsers, this determines
    - *     whether the listener is fired during the capture or bubble phase of the
    - *     event.
    - * @param {Object=} opt_handler Element in whose scope to call the listener.
    - */
    -goog.events.unlistenWithWrapper = function(src, wrapper, listener, opt_capt,
    -    opt_handler) {
    -  wrapper.unlisten(src, listener, opt_capt, opt_handler);
    -};
    -
    -
    -/**
    - * Removes all listeners from an object. You can also optionally
    - * remove listeners of a particular type.
    - *
    - * @param {Object|undefined} obj Object to remove listeners from. Must be an
    - *     EventTarget or a goog.events.Listenable.
    - * @param {string|!goog.events.EventId=} opt_type Type of event to remove.
    - *     Default is all types.
    - * @return {number} Number of listeners removed.
    - */
    -goog.events.removeAll = function(obj, opt_type) {
    -  // TODO(chrishenry): Change the type of obj to
    -  // (!EventTarget|!goog.events.Listenable).
    -
    -  if (!obj) {
    -    return 0;
    -  }
    -
    -  if (goog.events.Listenable.isImplementedBy(obj)) {
    -    return obj.removeAllListeners(opt_type);
    -  }
    -
    -  var listenerMap = goog.events.getListenerMap_(
    -      /** @type {!EventTarget} */ (obj));
    -  if (!listenerMap) {
    -    return 0;
    -  }
    -
    -  var count = 0;
    -  var typeStr = opt_type && opt_type.toString();
    -  for (var type in listenerMap.listeners) {
    -    if (!typeStr || type == typeStr) {
    -      // Clone so that we don't need to worry about unlistenByKey
    -      // changing the content of the ListenerMap.
    -      var listeners = listenerMap.listeners[type].concat();
    -      for (var i = 0; i < listeners.length; ++i) {
    -        if (goog.events.unlistenByKey(listeners[i])) {
    -          ++count;
    -        }
    -      }
    -    }
    -  }
    -  return count;
    -};
    -
    -
    -/**
    - * Gets the listeners for a given object, type and capture phase.
    - *
    - * @param {Object} obj Object to get listeners for.
    - * @param {string|!goog.events.EventId} type Event type.
    - * @param {boolean} capture Capture phase?.
    - * @return {Array<goog.events.Listener>} Array of listener objects.
    - */
    -goog.events.getListeners = function(obj, type, capture) {
    -  if (goog.events.Listenable.isImplementedBy(obj)) {
    -    return obj.getListeners(type, capture);
    -  } else {
    -    if (!obj) {
    -      // TODO(chrishenry): We should tighten the API to accept
    -      // !EventTarget|goog.events.Listenable, and add an assertion here.
    -      return [];
    -    }
    -
    -    var listenerMap = goog.events.getListenerMap_(
    -        /** @type {!EventTarget} */ (obj));
    -    return listenerMap ? listenerMap.getListeners(type, capture) : [];
    -  }
    -};
    -
    -
    -/**
    - * Gets the goog.events.Listener for the event or null if no such listener is
    - * in use.
    - *
    - * @param {EventTarget|goog.events.Listenable} src The target from
    - *     which to get listeners.
    - * @param {?string|!goog.events.EventId<EVENTOBJ>} type The type of the event.
    - * @param {function(EVENTOBJ):?|{handleEvent:function(?):?}|null} listener The
    - *     listener function to get.
    - * @param {boolean=} opt_capt In DOM-compliant browsers, this determines
    - *                            whether the listener is fired during the
    - *                            capture or bubble phase of the event.
    - * @param {Object=} opt_handler Element in whose scope to call the listener.
    - * @return {goog.events.ListenableKey} the found listener or null if not found.
    - * @template EVENTOBJ
    - */
    -goog.events.getListener = function(src, type, listener, opt_capt, opt_handler) {
    -  // TODO(chrishenry): Change type from ?string to string, or add assertion.
    -  type = /** @type {string} */ (type);
    -  listener = goog.events.wrapListener(listener);
    -  var capture = !!opt_capt;
    -  if (goog.events.Listenable.isImplementedBy(src)) {
    -    return src.getListener(type, listener, capture, opt_handler);
    -  }
    -
    -  if (!src) {
    -    // TODO(chrishenry): We should tighten the API to only accept
    -    // non-null objects, or add an assertion here.
    -    return null;
    -  }
    -
    -  var listenerMap = goog.events.getListenerMap_(
    -      /** @type {!EventTarget} */ (src));
    -  if (listenerMap) {
    -    return listenerMap.getListener(type, listener, capture, opt_handler);
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * Returns whether an event target has any active listeners matching the
    - * specified signature. If either the type or capture parameters are
    - * unspecified, the function will match on the remaining criteria.
    - *
    - * @param {EventTarget|goog.events.Listenable} obj Target to get
    - *     listeners for.
    - * @param {string|!goog.events.EventId=} opt_type Event type.
    - * @param {boolean=} opt_capture Whether to check for capture or bubble-phase
    - *     listeners.
    - * @return {boolean} Whether an event target has one or more listeners matching
    - *     the requested type and/or capture phase.
    - */
    -goog.events.hasListener = function(obj, opt_type, opt_capture) {
    -  if (goog.events.Listenable.isImplementedBy(obj)) {
    -    return obj.hasListener(opt_type, opt_capture);
    -  }
    -
    -  var listenerMap = goog.events.getListenerMap_(
    -      /** @type {!EventTarget} */ (obj));
    -  return !!listenerMap && listenerMap.hasListener(opt_type, opt_capture);
    -};
    -
    -
    -/**
    - * Provides a nice string showing the normalized event objects public members
    - * @param {Object} e Event Object.
    - * @return {string} String of the public members of the normalized event object.
    - */
    -goog.events.expose = function(e) {
    -  var str = [];
    -  for (var key in e) {
    -    if (e[key] && e[key].id) {
    -      str.push(key + ' = ' + e[key] + ' (' + e[key].id + ')');
    -    } else {
    -      str.push(key + ' = ' + e[key]);
    -    }
    -  }
    -  return str.join('\n');
    -};
    -
    -
    -/**
    - * Returns a string with on prepended to the specified type. This is used for IE
    - * which expects "on" to be prepended. This function caches the string in order
    - * to avoid extra allocations in steady state.
    - * @param {string} type Event type.
    - * @return {string} The type string with 'on' prepended.
    - * @private
    - */
    -goog.events.getOnString_ = function(type) {
    -  if (type in goog.events.onStringMap_) {
    -    return goog.events.onStringMap_[type];
    -  }
    -  return goog.events.onStringMap_[type] = goog.events.onString_ + type;
    -};
    -
    -
    -/**
    - * Fires an object's listeners of a particular type and phase
    - *
    - * @param {Object} obj Object whose listeners to call.
    - * @param {string|!goog.events.EventId} type Event type.
    - * @param {boolean} capture Which event phase.
    - * @param {Object} eventObject Event object to be passed to listener.
    - * @return {boolean} True if all listeners returned true else false.
    - */
    -goog.events.fireListeners = function(obj, type, capture, eventObject) {
    -  if (goog.events.Listenable.isImplementedBy(obj)) {
    -    return obj.fireListeners(type, capture, eventObject);
    -  }
    -
    -  return goog.events.fireListeners_(obj, type, capture, eventObject);
    -};
    -
    -
    -/**
    - * Fires an object's listeners of a particular type and phase.
    - * @param {Object} obj Object whose listeners to call.
    - * @param {string|!goog.events.EventId} type Event type.
    - * @param {boolean} capture Which event phase.
    - * @param {Object} eventObject Event object to be passed to listener.
    - * @return {boolean} True if all listeners returned true else false.
    - * @private
    - */
    -goog.events.fireListeners_ = function(obj, type, capture, eventObject) {
    -  /** @type {boolean} */
    -  var retval = true;
    -
    -  var listenerMap = goog.events.getListenerMap_(
    -      /** @type {EventTarget} */ (obj));
    -  if (listenerMap) {
    -    // TODO(chrishenry): Original code avoids array creation when there
    -    // is no listener, so we do the same. If this optimization turns
    -    // out to be not required, we can replace this with
    -    // listenerMap.getListeners(type, capture) instead, which is simpler.
    -    var listenerArray = listenerMap.listeners[type.toString()];
    -    if (listenerArray) {
    -      listenerArray = listenerArray.concat();
    -      for (var i = 0; i < listenerArray.length; i++) {
    -        var listener = listenerArray[i];
    -        // We might not have a listener if the listener was removed.
    -        if (listener && listener.capture == capture && !listener.removed) {
    -          var result = goog.events.fireListener(listener, eventObject);
    -          retval = retval && (result !== false);
    -        }
    -      }
    -    }
    -  }
    -  return retval;
    -};
    -
    -
    -/**
    - * Fires a listener with a set of arguments
    - *
    - * @param {goog.events.Listener} listener The listener object to call.
    - * @param {Object} eventObject The event object to pass to the listener.
    - * @return {boolean} Result of listener.
    - */
    -goog.events.fireListener = function(listener, eventObject) {
    -  var listenerFn = listener.listener;
    -  var listenerHandler = listener.handler || listener.src;
    -
    -  if (listener.callOnce) {
    -    goog.events.unlistenByKey(listener);
    -  }
    -  return listenerFn.call(listenerHandler, eventObject);
    -};
    -
    -
    -/**
    - * Gets the total number of listeners currently in the system.
    - * @return {number} Number of listeners.
    - * @deprecated This returns estimated count, now that Closure no longer
    - * stores a central listener registry. We still return an estimation
    - * to keep existing listener-related tests passing. In the near future,
    - * this function will be removed.
    - */
    -goog.events.getTotalListenerCount = function() {
    -  return goog.events.listenerCountEstimate_;
    -};
    -
    -
    -/**
    - * Dispatches an event (or event like object) and calls all listeners
    - * listening for events of this type. The type of the event is decided by the
    - * type property on the event object.
    - *
    - * If any of the listeners returns false OR calls preventDefault then this
    - * function will return false.  If one of the capture listeners calls
    - * stopPropagation, then the bubble listeners won't fire.
    - *
    - * @param {goog.events.Listenable} src The event target.
    - * @param {goog.events.EventLike} e Event object.
    - * @return {boolean} If anyone called preventDefault on the event object (or
    - *     if any of the handlers returns false) this will also return false.
    - *     If there are no handlers, or if all handlers return true, this returns
    - *     true.
    - */
    -goog.events.dispatchEvent = function(src, e) {
    -  goog.asserts.assert(
    -      goog.events.Listenable.isImplementedBy(src),
    -      'Can not use goog.events.dispatchEvent with ' +
    -      'non-goog.events.Listenable instance.');
    -  return src.dispatchEvent(e);
    -};
    -
    -
    -/**
    - * Installs exception protection for the browser event entry point using the
    - * given error handler.
    - *
    - * @param {goog.debug.ErrorHandler} errorHandler Error handler with which to
    - *     protect the entry point.
    - */
    -goog.events.protectBrowserEventEntryPoint = function(errorHandler) {
    -  goog.events.handleBrowserEvent_ = errorHandler.protectEntryPoint(
    -      goog.events.handleBrowserEvent_);
    -};
    -
    -
    -/**
    - * Handles an event and dispatches it to the correct listeners. This
    - * function is a proxy for the real listener the user specified.
    - *
    - * @param {goog.events.Listener} listener The listener object.
    - * @param {Event=} opt_evt Optional event object that gets passed in via the
    - *     native event handlers.
    - * @return {boolean} Result of the event handler.
    - * @this {EventTarget} The object or Element that fired the event.
    - * @private
    - */
    -goog.events.handleBrowserEvent_ = function(listener, opt_evt) {
    -  if (listener.removed) {
    -    return true;
    -  }
    -
    -  // Synthesize event propagation if the browser does not support W3C
    -  // event model.
    -  if (!goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT) {
    -    var ieEvent = opt_evt ||
    -        /** @type {Event} */ (goog.getObjectByName('window.event'));
    -    var evt = new goog.events.BrowserEvent(ieEvent, this);
    -    /** @type {boolean} */
    -    var retval = true;
    -
    -    if (goog.events.CAPTURE_SIMULATION_MODE ==
    -            goog.events.CaptureSimulationMode.ON) {
    -      // If we have not marked this event yet, we should perform capture
    -      // simulation.
    -      if (!goog.events.isMarkedIeEvent_(ieEvent)) {
    -        goog.events.markIeEvent_(ieEvent);
    -
    -        var ancestors = [];
    -        for (var parent = evt.currentTarget; parent;
    -             parent = parent.parentNode) {
    -          ancestors.push(parent);
    -        }
    -
    -        // Fire capture listeners.
    -        var type = listener.type;
    -        for (var i = ancestors.length - 1; !evt.propagationStopped_ && i >= 0;
    -             i--) {
    -          evt.currentTarget = ancestors[i];
    -          var result = goog.events.fireListeners_(ancestors[i], type, true, evt);
    -          retval = retval && result;
    -        }
    -
    -        // Fire bubble listeners.
    -        //
    -        // We can technically rely on IE to perform bubble event
    -        // propagation. However, it turns out that IE fires events in
    -        // opposite order of attachEvent registration, which broke
    -        // some code and tests that rely on the order. (While W3C DOM
    -        // Level 2 Events TR leaves the event ordering unspecified,
    -        // modern browsers and W3C DOM Level 3 Events Working Draft
    -        // actually specify the order as the registration order.)
    -        for (var i = 0; !evt.propagationStopped_ && i < ancestors.length; i++) {
    -          evt.currentTarget = ancestors[i];
    -          var result = goog.events.fireListeners_(ancestors[i], type, false, evt);
    -          retval = retval && result;
    -        }
    -      }
    -    } else {
    -      retval = goog.events.fireListener(listener, evt);
    -    }
    -    return retval;
    -  }
    -
    -  // Otherwise, simply fire the listener.
    -  return goog.events.fireListener(
    -      listener, new goog.events.BrowserEvent(opt_evt, this));
    -};
    -
    -
    -/**
    - * This is used to mark the IE event object so we do not do the Closure pass
    - * twice for a bubbling event.
    - * @param {Event} e The IE browser event.
    - * @private
    - */
    -goog.events.markIeEvent_ = function(e) {
    -  // Only the keyCode and the returnValue can be changed. We use keyCode for
    -  // non keyboard events.
    -  // event.returnValue is a bit more tricky. It is undefined by default. A
    -  // boolean false prevents the default action. In a window.onbeforeunload and
    -  // the returnValue is non undefined it will be alerted. However, we will only
    -  // modify the returnValue for keyboard events. We can get a problem if non
    -  // closure events sets the keyCode or the returnValue
    -
    -  var useReturnValue = false;
    -
    -  if (e.keyCode == 0) {
    -    // We cannot change the keyCode in case that srcElement is input[type=file].
    -    // We could test that that is the case but that would allocate 3 objects.
    -    // If we use try/catch we will only allocate extra objects in the case of a
    -    // failure.
    -    /** @preserveTry */
    -    try {
    -      e.keyCode = -1;
    -      return;
    -    } catch (ex) {
    -      useReturnValue = true;
    -    }
    -  }
    -
    -  if (useReturnValue ||
    -      /** @type {boolean|undefined} */ (e.returnValue) == undefined) {
    -    e.returnValue = true;
    -  }
    -};
    -
    -
    -/**
    - * This is used to check if an IE event has already been handled by the Closure
    - * system so we do not do the Closure pass twice for a bubbling event.
    - * @param {Event} e  The IE browser event.
    - * @return {boolean} True if the event object has been marked.
    - * @private
    - */
    -goog.events.isMarkedIeEvent_ = function(e) {
    -  return e.keyCode < 0 || e.returnValue != undefined;
    -};
    -
    -
    -/**
    - * Counter to create unique event ids.
    - * @private {number}
    - */
    -goog.events.uniqueIdCounter_ = 0;
    -
    -
    -/**
    - * Creates a unique event id.
    - *
    - * @param {string} identifier The identifier.
    - * @return {string} A unique identifier.
    - * @idGenerator
    - */
    -goog.events.getUniqueId = function(identifier) {
    -  return identifier + '_' + goog.events.uniqueIdCounter_++;
    -};
    -
    -
    -/**
    - * @param {EventTarget} src The source object.
    - * @return {goog.events.ListenerMap} A listener map for the given
    - *     source object, or null if none exists.
    - * @private
    - */
    -goog.events.getListenerMap_ = function(src) {
    -  var listenerMap = src[goog.events.LISTENER_MAP_PROP_];
    -  // IE serializes the property as well (e.g. when serializing outer
    -  // HTML). So we must check that the value is of the correct type.
    -  return listenerMap instanceof goog.events.ListenerMap ? listenerMap : null;
    -};
    -
    -
    -/**
    - * Expando property for listener function wrapper for Object with
    - * handleEvent.
    - * @private @const {string}
    - */
    -goog.events.LISTENER_WRAPPER_PROP_ = '__closure_events_fn_' +
    -    ((Math.random() * 1e9) >>> 0);
    -
    -
    -/**
    - * @param {Object|Function} listener The listener function or an
    - *     object that contains handleEvent method.
    - * @return {!Function} Either the original function or a function that
    - *     calls obj.handleEvent. If the same listener is passed to this
    - *     function more than once, the same function is guaranteed to be
    - *     returned.
    - */
    -goog.events.wrapListener = function(listener) {
    -  goog.asserts.assert(listener, 'Listener can not be null.');
    -
    -  if (goog.isFunction(listener)) {
    -    return listener;
    -  }
    -
    -  goog.asserts.assert(
    -      listener.handleEvent, 'An object listener must have handleEvent method.');
    -  if (!listener[goog.events.LISTENER_WRAPPER_PROP_]) {
    -    listener[goog.events.LISTENER_WRAPPER_PROP_] =
    -        function(e) { return listener.handleEvent(e); };
    -  }
    -  return listener[goog.events.LISTENER_WRAPPER_PROP_];
    -};
    -
    -
    -// Register the browser event handler as an entry point, so that
    -// it can be monitored for exception handling, etc.
    -goog.debug.entryPointRegistry.register(
    -    /**
    -     * @param {function(!Function): !Function} transformer The transforming
    -     *     function.
    -     */
    -    function(transformer) {
    -      goog.events.handleBrowserEvent_ = transformer(
    -          goog.events.handleBrowserEvent_);
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/events/events_test.html b/src/database/third_party/closure-library/closure/goog/events/events_test.html
    deleted file mode 100644
    index a3d8e26fb01..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/events_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.events
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.eventsTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/events/events_test.js b/src/database/third_party/closure-library/closure/goog/events/events_test.js
    deleted file mode 100644
    index dde672990a3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/events_test.js
    +++ /dev/null
    @@ -1,745 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.eventsTest');
    -goog.setTestOnly('goog.eventsTest');
    -
    -goog.require('goog.asserts.AssertionError');
    -goog.require('goog.debug.EntryPointMonitor');
    -goog.require('goog.debug.ErrorHandler');
    -goog.require('goog.debug.entryPointRegistry');
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.BrowserFeature');
    -goog.require('goog.events.CaptureSimulationMode');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.Listener');
    -goog.require('goog.functions');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -
    -var originalHandleBrowserEvent = goog.events.handleBrowserEvent_;
    -var propertyReplacer;
    -var et1, et2, et3;
    -
    -function setUp() {
    -  et1 = new goog.events.EventTarget();
    -  et2 = new goog.events.EventTarget();
    -  et3 = new goog.events.EventTarget();
    -  propertyReplacer = new goog.testing.PropertyReplacer();
    -}
    -
    -function tearDown() {
    -  goog.events.CAPTURE_SIMULATION_MODE =
    -      goog.events.CaptureSimulationMode.ON;
    -  goog.events.handleBrowserEvent_ = originalHandleBrowserEvent;
    -  goog.disposeAll(et1, et2, et3);
    -  goog.events.removeAll(document.body);
    -  propertyReplacer.reset();
    -}
    -
    -function testProtectBrowserEventEntryPoint() {
    -  var errorHandlerFn = goog.testing.recordFunction();
    -  var errorHandler = new goog.debug.ErrorHandler(errorHandlerFn);
    -
    -  goog.events.protectBrowserEventEntryPoint(errorHandler);
    -
    -  var browserEventHandler =
    -      goog.testing.recordFunction(goog.events.handleBrowserEvent_);
    -  goog.events.handleBrowserEvent_ = function() {
    -    try {
    -      browserEventHandler.apply(this, arguments);
    -    } catch (e) {
    -      // Ignored.
    -    }
    -  };
    -
    -  var err = Error('test');
    -  var body = document.body;
    -  goog.events.listen(body, goog.events.EventType.CLICK, function() {
    -    throw err;
    -  });
    -
    -  dispatchClick(body);
    -
    -  assertEquals('Error handler callback should be called.',
    -      1, errorHandlerFn.getCallCount());
    -  assertEquals(err, errorHandlerFn.getLastCall().getArgument(0));
    -
    -  assertEquals(1, browserEventHandler.getCallCount());
    -  var err2 = browserEventHandler.getLastCall().getError();
    -  assertNotNull(err2);
    -  assertTrue(
    -      err2 instanceof goog.debug.ErrorHandler.ProtectedFunctionError);
    -}
    -
    -function testSelfRemove() {
    -  var callback = function() {
    -    // This listener removes itself during event dispatching, so it
    -    // is marked as 'removed' but not actually removed until after event
    -    // dispatching ends.
    -    goog.events.removeAll(et1, 'click');
    -
    -    // Test that goog.events.getListener ignores events marked as 'removed'.
    -    assertNull(goog.events.getListener(et1, 'click', callback));
    -  };
    -  var key = goog.events.listen(et1, 'click', callback);
    -  goog.events.dispatchEvent(et1, 'click');
    -}
    -
    -function testHasListener() {
    -  var div = document.createElement('div');
    -  assertFalse(goog.events.hasListener(div));
    -
    -  var key = goog.events.listen(div, 'click', function() {});
    -  assertTrue(goog.events.hasListener(div));
    -  assertTrue(goog.events.hasListener(div, 'click'));
    -  assertTrue(goog.events.hasListener(div, 'click', false));
    -  assertTrue(goog.events.hasListener(div, undefined, false));
    -
    -  assertFalse(goog.events.hasListener(div, 'click', true));
    -  assertFalse(goog.events.hasListener(div, undefined, true));
    -  assertFalse(goog.events.hasListener(div, 'mouseup'));
    -
    -  // Test that hasListener returns false when all listeners are removed.
    -  goog.events.unlistenByKey(key);
    -  assertFalse(goog.events.hasListener(div));
    -}
    -
    -function testHasListenerWithEventTarget() {
    -  assertFalse(goog.events.hasListener(et1));
    -
    -  function callback() {};
    -  goog.events.listen(et1, 'test', callback, true);
    -  assertTrue(goog.events.hasListener(et1));
    -  assertTrue(goog.events.hasListener(et1, 'test'));
    -  assertTrue(goog.events.hasListener(et1, 'test', true));
    -  assertTrue(goog.events.hasListener(et1, undefined, true));
    -
    -  assertFalse(goog.events.hasListener(et1, 'click'));
    -  assertFalse(goog.events.hasListener(et1, 'test', false));
    -
    -  goog.events.unlisten(et1, 'test', callback, true);
    -  assertFalse(goog.events.hasListener(et1));
    -}
    -
    -function testHasListenerWithMultipleTargets() {
    -  function callback() {};
    -
    -  goog.events.listen(et1, 'test1', callback, true);
    -  goog.events.listen(et2, 'test2', callback, true);
    -
    -  assertTrue(goog.events.hasListener(et1));
    -  assertTrue(goog.events.hasListener(et2));
    -  assertTrue(goog.events.hasListener(et1, 'test1'));
    -  assertTrue(goog.events.hasListener(et2, 'test2'));
    -
    -  assertFalse(goog.events.hasListener(et1, 'et2'));
    -  assertFalse(goog.events.hasListener(et2, 'et1'));
    -
    -  goog.events.removeAll(et1);
    -  goog.events.removeAll(et2);
    -}
    -
    -function testBubbleSingle() {
    -  et1.setParentEventTarget(et2);
    -  et2.setParentEventTarget(et3);
    -
    -  var count = 0;
    -  function callback() {
    -    count++;
    -  }
    -
    -  goog.events.listen(et3, 'test', callback, false);
    -
    -  et1.dispatchEvent('test');
    -
    -  assertEquals(1, count);
    -
    -  goog.events.removeAll(et1);
    -  goog.events.removeAll(et2);
    -  goog.events.removeAll(et3);
    -}
    -
    -function testCaptureSingle() {
    -  et1.setParentEventTarget(et2);
    -  et2.setParentEventTarget(et3);
    -
    -  var count = 0;
    -  function callback() {
    -    count++;
    -  }
    -
    -  goog.events.listen(et3, 'test', callback, true);
    -
    -  et1.dispatchEvent('test');
    -
    -  assertEquals(1, count);
    -
    -  goog.events.removeAll(et1);
    -  goog.events.removeAll(et2);
    -  goog.events.removeAll(et3);
    -}
    -
    -function testCaptureAndBubble() {
    -  et1.setParentEventTarget(et2);
    -  et2.setParentEventTarget(et3);
    -
    -  var count = 0;
    -  function callbackCapture1() {
    -    count++;
    -    assertEquals(3, count);
    -  }
    -  function callbackBubble1() {
    -    count++;
    -    assertEquals(4, count);
    -  }
    -
    -  function callbackCapture2() {
    -    count++;
    -    assertEquals(2, count);
    -  }
    -  function callbackBubble2() {
    -    count++;
    -    assertEquals(5, count);
    -  }
    -
    -  function callbackCapture3() {
    -    count++;
    -    assertEquals(1, count);
    -  }
    -  function callbackBubble3() {
    -    count++;
    -    assertEquals(6, count);
    -  }
    -
    -  goog.events.listen(et1, 'test', callbackCapture1, true);
    -  goog.events.listen(et1, 'test', callbackBubble1, false);
    -  goog.events.listen(et2, 'test', callbackCapture2, true);
    -  goog.events.listen(et2, 'test', callbackBubble2, false);
    -  goog.events.listen(et3, 'test', callbackCapture3, true);
    -  goog.events.listen(et3, 'test', callbackBubble3, false);
    -
    -  et1.dispatchEvent('test');
    -
    -  assertEquals(6, count);
    -
    -  goog.events.removeAll(et1);
    -  goog.events.removeAll(et2);
    -  goog.events.removeAll(et3);
    -}
    -
    -function testCapturingRemovesBubblingListener() {
    -  var bubbleCount = 0;
    -  function callbackBubble() {
    -    bubbleCount++;
    -  }
    -
    -  var captureCount = 0;
    -  function callbackCapture() {
    -    captureCount++;
    -    goog.events.removeAll(et1);
    -  }
    -
    -  goog.events.listen(et1, 'test', callbackCapture, true);
    -  goog.events.listen(et1, 'test', callbackBubble, false);
    -
    -  et1.dispatchEvent('test');
    -  assertEquals(1, captureCount);
    -  assertEquals(0, bubbleCount);
    -}
    -
    -function dispatchClick(target) {
    -  if (target.click) {
    -    target.click();
    -  } else {
    -    var e = document.createEvent('MouseEvents');
    -    e.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false,
    -        false, false, false, 0, null);
    -    target.dispatchEvent(e);
    -  }
    -}
    -
    -function testHandleBrowserEventBubblingListener() {
    -  var count = 0;
    -  var body = document.body;
    -  goog.events.listen(body, 'click', function() {
    -    count++;
    -  });
    -  dispatchClick(body);
    -  assertEquals(1, count);
    -}
    -
    -function testHandleBrowserEventCapturingListener() {
    -  var count = 0;
    -  var body = document.body;
    -  goog.events.listen(body, 'click', function() {
    -    count++;
    -  }, true);
    -  dispatchClick(body);
    -  assertEquals(1, count);
    -}
    -
    -function testHandleBrowserEventCapturingAndBubblingListener() {
    -  var count = 1;
    -  var body = document.body;
    -  goog.events.listen(body, 'click', function() {
    -    count += 3;
    -  }, true);
    -  goog.events.listen(body, 'click', function() {
    -    count *= 5;
    -  }, false);
    -  dispatchClick(body);
    -  assertEquals(20, count);
    -}
    -
    -function testHandleBrowserEventCapturingRemovesBubblingListener() {
    -  var body = document.body;
    -
    -  var bubbleCount = 0;
    -  function callbackBubble() {
    -    bubbleCount++;
    -  }
    -
    -  var captureCount = 0;
    -  function callbackCapture() {
    -    captureCount++;
    -    goog.events.removeAll(body);
    -  }
    -
    -  goog.events.listen(body, 'click', callbackCapture, true);
    -  goog.events.listen(body, 'click', callbackBubble, false);
    -
    -  dispatchClick(body);
    -  assertEquals(1, captureCount);
    -  assertEquals(0, bubbleCount);
    -}
    -
    -function testHandleEventPropagationOnParentElement() {
    -  var count = 1;
    -  goog.events.listen(document.documentElement, 'click', function() {
    -    count += 3;
    -  }, true);
    -  goog.events.listen(document.documentElement, 'click', function() {
    -    count *= 5;
    -  }, false);
    -  dispatchClick(document.body);
    -  assertEquals(20, count);
    -}
    -
    -function testEntryPointRegistry() {
    -  var monitor = new goog.debug.EntryPointMonitor();
    -  var replacement = function() {};
    -  monitor.wrap = goog.testing.recordFunction(
    -      goog.functions.constant(replacement));
    -
    -  goog.debug.entryPointRegistry.monitorAll(monitor);
    -  assertTrue(monitor.wrap.getCallCount() >= 1);
    -  assertEquals(replacement, goog.events.handleBrowserEvent_);
    -}
    -
    -// Fixes bug http://b/6434926
    -function testListenOnceHandlerDispatchCausingInfiniteLoop() {
    -  var handleFoo = goog.testing.recordFunction(function() {
    -    et1.dispatchEvent('foo');
    -  });
    -
    -  goog.events.listenOnce(et1, 'foo', handleFoo);
    -
    -  et1.dispatchEvent('foo');
    -
    -  assertEquals('Handler should be called only once.',
    -               1, handleFoo.getCallCount());
    -}
    -
    -function testCreationStack() {
    -  if (!new Error().stack)
    -    return;
    -  propertyReplacer.replace(goog.events.Listener, 'ENABLE_MONITORING', true);
    -
    -  var div = document.createElement('div');
    -  var key = goog.events.listen(
    -      div, goog.events.EventType.CLICK, goog.nullFunction);
    -  var listenerStack = key.creationStack;
    -
    -  // Check that the name of this test function occurs in the stack trace.
    -  assertContains('testCreationStack', listenerStack);
    -  goog.events.unlistenByKey(key);
    -}
    -
    -function testListenOnceAfterListenDoesNotChangeExistingListener() {
    -  var listener = goog.testing.recordFunction();
    -  goog.events.listen(document.body, 'click', listener);
    -  goog.events.listenOnce(document.body, 'click', listener);
    -
    -  dispatchClick(document.body);
    -  dispatchClick(document.body);
    -  dispatchClick(document.body);
    -
    -  assertEquals(3, listener.getCallCount());
    -}
    -
    -function testListenOnceAfterListenOnceDoesNotChangeExistingListener() {
    -  var listener = goog.testing.recordFunction();
    -  goog.events.listenOnce(document.body, 'click', listener);
    -  goog.events.listenOnce(document.body, 'click', listener);
    -
    -  dispatchClick(document.body);
    -  dispatchClick(document.body);
    -  dispatchClick(document.body);
    -
    -  assertEquals(1, listener.getCallCount());
    -}
    -
    -function testListenAfterListenOnceRemoveOnceness() {
    -  var listener = goog.testing.recordFunction();
    -  goog.events.listenOnce(document.body, 'click', listener);
    -  goog.events.listen(document.body, 'click', listener);
    -
    -  dispatchClick(document.body);
    -  dispatchClick(document.body);
    -  dispatchClick(document.body);
    -
    -  assertEquals(3, listener.getCallCount());
    -}
    -
    -function testUnlistenAfterListenOnce() {
    -  var listener = goog.testing.recordFunction();
    -
    -  goog.events.listenOnce(document.body, 'click', listener);
    -  goog.events.unlisten(document.body, 'click', listener);
    -  dispatchClick(document.body);
    -
    -  goog.events.listenOnce(document.body, 'click', listener);
    -  goog.events.listen(document.body, 'click', listener);
    -  goog.events.unlisten(document.body, 'click', listener);
    -  dispatchClick(document.body);
    -
    -  goog.events.listen(document.body, 'click', listener);
    -  goog.events.listenOnce(document.body, 'click', listener);
    -  goog.events.unlisten(document.body, 'click', listener);
    -  dispatchClick(document.body);
    -
    -  goog.events.listenOnce(document.body, 'click', listener);
    -  goog.events.listenOnce(document.body, 'click', listener);
    -  goog.events.unlisten(document.body, 'click', listener);
    -  dispatchClick(document.body);
    -
    -  assertEquals(0, listener.getCallCount());
    -}
    -
    -function testEventBubblingWithReentrantDispatch_bubbling() {
    -  runEventPropogationWithReentrantDispatch(false);
    -}
    -
    -function testEventBubblingWithReentrantDispatch_capture() {
    -  runEventPropogationWithReentrantDispatch(true);
    -}
    -
    -function runEventPropogationWithReentrantDispatch(useCapture) {
    -  var eventType = 'test-event-type';
    -
    -  var child = et1;
    -  var parent = et2;
    -  child.setParentEventTarget(parent);
    -
    -  var firstTarget = useCapture ? parent : child;
    -  var secondTarget = useCapture ? child : parent;
    -
    -  var firstListener = function(evt) {
    -    if (evt.isFirstEvent) {
    -      // Fires another event of the same type the first time it is invoked.
    -      child.dispatchEvent(new goog.events.Event(eventType));
    -    }
    -  };
    -  goog.events.listen(firstTarget, eventType, firstListener, useCapture);
    -
    -  var secondListener = goog.testing.recordFunction();
    -  goog.events.listen(secondTarget, eventType, secondListener, useCapture);
    -
    -  // Fire the first event.
    -  var firstEvent = new goog.events.Event(eventType);
    -  firstEvent.isFirstEvent = true;
    -  child.dispatchEvent(firstEvent);
    -
    -  assertEquals(2, secondListener.getCallCount());
    -}
    -
    -function testEventPropogationWhenListenerRemoved_bubbling() {
    -  runEventPropogationWhenListenerRemoved(false);
    -}
    -
    -function testEventPropogationWhenListenerRemoved_capture() {
    -  runEventPropogationWhenListenerRemoved(true);
    -}
    -
    -function runEventPropogationWhenListenerRemoved(useCapture) {
    -  var eventType = 'test-event-type';
    -
    -  var child = et1;
    -  var parent = et2;
    -  child.setParentEventTarget(parent);
    -
    -  var firstTarget = useCapture ? parent : child;
    -  var secondTarget = useCapture ? child : parent;
    -
    -  var firstListener = goog.testing.recordFunction();
    -  var secondListener = goog.testing.recordFunction();
    -  goog.events.listenOnce(firstTarget, eventType, firstListener, useCapture);
    -  goog.events.listen(secondTarget, eventType, secondListener, useCapture);
    -
    -  child.dispatchEvent(new goog.events.Event(eventType));
    -
    -  assertEquals(1, secondListener.getCallCount());
    -}
    -
    -function testEventPropogationWhenListenerAdded_bubbling() {
    -  runEventPropogationWhenListenerAdded(false);
    -}
    -
    -function testEventPropogationWhenListenerAdded_capture() {
    -  runEventPropogationWhenListenerAdded(true);
    -}
    -
    -function runEventPropogationWhenListenerAdded(useCapture) {
    -  var eventType = 'test-event-type';
    -
    -  var child = et1;
    -  var parent = et2;
    -  child.setParentEventTarget(parent);
    -
    -  var firstTarget = useCapture ? parent : child;
    -  var secondTarget = useCapture ? child : parent;
    -
    -  var firstListener = function() {
    -    goog.events.listen(secondTarget, eventType, secondListener, useCapture);
    -  };
    -  var secondListener = goog.testing.recordFunction();
    -  goog.events.listen(firstTarget, eventType, firstListener, useCapture);
    -
    -  child.dispatchEvent(new goog.events.Event(eventType));
    -
    -  assertEquals(1, secondListener.getCallCount());
    -}
    -
    -function testEventPropogationWhenListenerAddedAndRemoved_bubbling() {
    -  runEventPropogationWhenListenerAddedAndRemoved(false);
    -}
    -
    -function testEventPropogationWhenListenerAddedAndRemoved_capture() {
    -  runEventPropogationWhenListenerAddedAndRemoved(true);
    -}
    -
    -function runEventPropogationWhenListenerAddedAndRemoved(useCapture) {
    -  var eventType = 'test-event-type';
    -
    -  var child = et1;
    -  var parent = et2;
    -  child.setParentEventTarget(parent);
    -
    -  var firstTarget = useCapture ? parent : child;
    -  var secondTarget = useCapture ? child : parent;
    -
    -  var firstListener = function() {
    -    goog.events.listen(secondTarget, eventType, secondListener, useCapture);
    -  };
    -  var secondListener = goog.testing.recordFunction();
    -  goog.events.listenOnce(firstTarget, eventType, firstListener, useCapture);
    -
    -  child.dispatchEvent(new goog.events.Event(eventType));
    -
    -  assertEquals(1, secondListener.getCallCount());
    -}
    -
    -function testAssertWhenUsedWithUninitializedCustomEventTarget() {
    -  var SubClass = function() { /* does not call superclass ctor */ };
    -  goog.inherits(SubClass, goog.events.EventTarget);
    -
    -  var instance = new SubClass();
    -
    -  var e;
    -  e = assertThrows(function() {
    -    goog.events.listen(instance, 'test1', function() {});
    -  });
    -  assertTrue(e instanceof goog.asserts.AssertionError);
    -  e = assertThrows(function() {
    -    goog.events.dispatchEvent(instance, 'test1');
    -  });
    -  assertTrue(e instanceof goog.asserts.AssertionError);
    -  e = assertThrows(function() {
    -    instance.dispatchEvent('test1');
    -  });
    -  assertTrue(e instanceof goog.asserts.AssertionError);
    -}
    -
    -function testAssertWhenDispatchEventIsUsedWithNonCustomEventTarget() {
    -  var obj = {};
    -  e = assertThrows(function() {
    -    goog.events.dispatchEvent(obj, 'test1');
    -  });
    -  assertTrue(e instanceof goog.asserts.AssertionError);
    -}
    -
    -
    -function testPropagationStoppedDuringCapture() {
    -  var captureHandler = goog.testing.recordFunction(function(e) {
    -    e.stopPropagation();
    -  });
    -  var bubbleHandler = goog.testing.recordFunction();
    -
    -  var body = document.body;
    -  var div = document.createElement('div');
    -  body.appendChild(div);
    -  try {
    -    goog.events.listen(body, 'click', captureHandler, true);
    -    goog.events.listen(div, 'click', bubbleHandler, false);
    -    goog.events.listen(body, 'click', bubbleHandler, false);
    -
    -    dispatchClick(div);
    -    assertEquals(1, captureHandler.getCallCount());
    -    assertEquals(0, bubbleHandler.getCallCount());
    -
    -    goog.events.unlisten(body, 'click', captureHandler, true);
    -
    -    dispatchClick(div);
    -    assertEquals(2, bubbleHandler.getCallCount());
    -  } finally {
    -    goog.dom.removeNode(div);
    -    goog.events.removeAll(body);
    -    goog.events.removeAll(div);
    -  }
    -}
    -
    -function testPropagationStoppedDuringBubble() {
    -  var captureHandler = goog.testing.recordFunction();
    -  var bubbleHandler1 = goog.testing.recordFunction(function(e) {
    -    e.stopPropagation();
    -  });
    -  var bubbleHandler2 = goog.testing.recordFunction();
    -
    -  var body = document.body;
    -  var div = document.createElement('div');
    -  body.appendChild(div);
    -  try {
    -    goog.events.listen(body, 'click', captureHandler, true);
    -    goog.events.listen(div, 'click', bubbleHandler1, false);
    -    goog.events.listen(body, 'click', bubbleHandler2, false);
    -
    -    dispatchClick(div);
    -    assertEquals(1, captureHandler.getCallCount());
    -    assertEquals(1, bubbleHandler1.getCallCount());
    -    assertEquals(0, bubbleHandler2.getCallCount());
    -  } finally {
    -    goog.dom.removeNode(div);
    -    goog.events.removeAll(body);
    -    goog.events.removeAll(div);
    -  }
    -}
    -
    -function testAddingCaptureListenerDuringBubbleShouldNotFireTheListener() {
    -  var body = document.body;
    -  var div = document.createElement('div');
    -  body.appendChild(div);
    -
    -  var captureHandler1 = goog.testing.recordFunction();
    -  var captureHandler2 = goog.testing.recordFunction();
    -  var bubbleHandler = goog.testing.recordFunction(function(e) {
    -    goog.events.listen(body, 'click', captureHandler1, true);
    -    goog.events.listen(div, 'click', captureHandler2, true);
    -  });
    -
    -  try {
    -    goog.events.listen(div, 'click', bubbleHandler, false);
    -
    -    dispatchClick(div);
    -
    -    // These verify that the capture handlers registered in the bubble
    -    // handler is not invoked in the same event propagation phase.
    -    assertEquals(0, captureHandler1.getCallCount());
    -    assertEquals(0, captureHandler2.getCallCount());
    -    assertEquals(1, bubbleHandler.getCallCount());
    -  } finally {
    -    goog.dom.removeNode(div);
    -    goog.events.removeAll(body);
    -    goog.events.removeAll(div);
    -  }
    -}
    -
    -function testRemovingCaptureListenerDuringBubbleWouldNotFireListenerTwice() {
    -  var body = document.body;
    -  var div = document.createElement('div');
    -  body.appendChild(div);
    -
    -  var captureHandler = goog.testing.recordFunction();
    -  var bubbleHandler1 = goog.testing.recordFunction(function(e) {
    -    goog.events.unlisten(body, 'click', captureHandler, true);
    -  });
    -  var bubbleHandler2 = goog.testing.recordFunction();
    -
    -  try {
    -    goog.events.listen(body, 'click', captureHandler, true);
    -    goog.events.listen(div, 'click', bubbleHandler1, false);
    -    goog.events.listen(body, 'click', bubbleHandler2, false);
    -
    -    dispatchClick(div);
    -    assertEquals(1, captureHandler.getCallCount());
    -
    -    // Verify that neither of these handlers are called more than once.
    -    assertEquals(1, bubbleHandler1.getCallCount());
    -    assertEquals(1, bubbleHandler2.getCallCount());
    -  } finally {
    -    goog.dom.removeNode(div);
    -    goog.events.removeAll(body);
    -    goog.events.removeAll(div);
    -  }
    -}
    -
    -function testCaptureSimulationModeOffAndFail() {
    -  goog.events.CAPTURE_SIMULATION_MODE =
    -      goog.events.CaptureSimulationMode.OFF_AND_FAIL;
    -  var captureHandler = goog.testing.recordFunction();
    -
    -  if (!goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT) {
    -    var err = assertThrows(function() {
    -      goog.events.listen(document.body, 'click', captureHandler, true);
    -    });
    -    assertTrue(err instanceof goog.asserts.AssertionError);
    -
    -    // Sanity tests.
    -    dispatchClick(document.body);
    -    assertEquals(0, captureHandler.getCallCount());
    -  } else {
    -    goog.events.listen(document.body, 'click', captureHandler, true);
    -    dispatchClick(document.body);
    -    assertEquals(1, captureHandler.getCallCount());
    -  }
    -}
    -
    -function testCaptureSimulationModeOffAndSilent() {
    -  goog.events.CAPTURE_SIMULATION_MODE =
    -      goog.events.CaptureSimulationMode.OFF_AND_SILENT;
    -  var captureHandler = goog.testing.recordFunction();
    -
    -  goog.events.listen(document.body, 'click', captureHandler, true);
    -  if (!goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT) {
    -    dispatchClick(document.body);
    -    assertEquals(0, captureHandler.getCallCount());
    -  } else {
    -    dispatchClick(document.body);
    -    assertEquals(1, captureHandler.getCallCount());
    -  }
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/events/eventtarget.js b/src/database/third_party/closure-library/closure/goog/events/eventtarget.js
    deleted file mode 100644
    index 7408c7e0964..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/eventtarget.js
    +++ /dev/null
    @@ -1,394 +0,0 @@
    -// Copyright 2005 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A disposable implementation of a custom
    - * listenable/event target. See also: documentation for
    - * {@code goog.events.Listenable}.
    - *
    - * @author arv@google.com (Erik Arvidsson) [Original implementation]
    - * @see ../demos/eventtarget.html
    - * @see goog.events.Listenable
    - */
    -
    -goog.provide('goog.events.EventTarget');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.asserts');
    -goog.require('goog.events');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.Listenable');
    -goog.require('goog.events.ListenerMap');
    -goog.require('goog.object');
    -
    -
    -
    -/**
    - * An implementation of {@code goog.events.Listenable} with full W3C
    - * EventTarget-like support (capture/bubble mechanism, stopping event
    - * propagation, preventing default actions).
    - *
    - * You may subclass this class to turn your class into a Listenable.
    - *
    - * Unless propagation is stopped, an event dispatched by an
    - * EventTarget will bubble to the parent returned by
    - * {@code getParentEventTarget}. To set the parent, call
    - * {@code setParentEventTarget}. Subclasses that don't support
    - * changing the parent can override the setter to throw an error.
    - *
    - * Example usage:
    - * <pre>
    - *   var source = new goog.events.EventTarget();
    - *   function handleEvent(e) {
    - *     alert('Type: ' + e.type + '; Target: ' + e.target);
    - *   }
    - *   source.listen('foo', handleEvent);
    - *   // Or: goog.events.listen(source, 'foo', handleEvent);
    - *   ...
    - *   source.dispatchEvent('foo');  // will call handleEvent
    - *   ...
    - *   source.unlisten('foo', handleEvent);
    - *   // Or: goog.events.unlisten(source, 'foo', handleEvent);
    - * </pre>
    - *
    - * @constructor
    - * @extends {goog.Disposable}
    - * @implements {goog.events.Listenable}
    - */
    -goog.events.EventTarget = function() {
    -  goog.Disposable.call(this);
    -
    -  /**
    -   * Maps of event type to an array of listeners.
    -   * @private {!goog.events.ListenerMap}
    -   */
    -  this.eventTargetListeners_ = new goog.events.ListenerMap(this);
    -
    -  /**
    -   * The object to use for event.target. Useful when mixing in an
    -   * EventTarget to another object.
    -   * @private {!Object}
    -   */
    -  this.actualEventTarget_ = this;
    -
    -  /**
    -   * Parent event target, used during event bubbling.
    -   *
    -   * TODO(chrishenry): Change this to goog.events.Listenable. This
    -   * currently breaks people who expect getParentEventTarget to return
    -   * goog.events.EventTarget.
    -   *
    -   * @private {goog.events.EventTarget}
    -   */
    -  this.parentEventTarget_ = null;
    -};
    -goog.inherits(goog.events.EventTarget, goog.Disposable);
    -goog.events.Listenable.addImplementation(goog.events.EventTarget);
    -
    -
    -/**
    - * An artificial cap on the number of ancestors you can have. This is mainly
    - * for loop detection.
    - * @const {number}
    - * @private
    - */
    -goog.events.EventTarget.MAX_ANCESTORS_ = 1000;
    -
    -
    -/**
    - * Returns the parent of this event target to use for bubbling.
    - *
    - * @return {goog.events.EventTarget} The parent EventTarget or null if
    - *     there is no parent.
    - * @override
    - */
    -goog.events.EventTarget.prototype.getParentEventTarget = function() {
    -  return this.parentEventTarget_;
    -};
    -
    -
    -/**
    - * Sets the parent of this event target to use for capture/bubble
    - * mechanism.
    - * @param {goog.events.EventTarget} parent Parent listenable (null if none).
    - */
    -goog.events.EventTarget.prototype.setParentEventTarget = function(parent) {
    -  this.parentEventTarget_ = parent;
    -};
    -
    -
    -/**
    - * Adds an event listener to the event target. The same handler can only be
    - * added once per the type. Even if you add the same handler multiple times
    - * using the same type then it will only be called once when the event is
    - * dispatched.
    - *
    - * @param {string} type The type of the event to listen for.
    - * @param {function(?):?|{handleEvent:function(?):?}|null} handler The function
    - *     to handle the event. The handler can also be an object that implements
    - *     the handleEvent method which takes the event object as argument.
    - * @param {boolean=} opt_capture In DOM-compliant browsers, this determines
    - *     whether the listener is fired during the capture or bubble phase
    - *     of the event.
    - * @param {Object=} opt_handlerScope Object in whose scope to call
    - *     the listener.
    - * @deprecated Use {@code #listen} instead, when possible. Otherwise, use
    - *     {@code goog.events.listen} if you are passing Object
    - *     (instead of Function) as handler.
    - */
    -goog.events.EventTarget.prototype.addEventListener = function(
    -    type, handler, opt_capture, opt_handlerScope) {
    -  goog.events.listen(this, type, handler, opt_capture, opt_handlerScope);
    -};
    -
    -
    -/**
    - * Removes an event listener from the event target. The handler must be the
    - * same object as the one added. If the handler has not been added then
    - * nothing is done.
    - *
    - * @param {string} type The type of the event to listen for.
    - * @param {function(?):?|{handleEvent:function(?):?}|null} handler The function
    - *     to handle the event. The handler can also be an object that implements
    - *     the handleEvent method which takes the event object as argument.
    - * @param {boolean=} opt_capture In DOM-compliant browsers, this determines
    - *     whether the listener is fired during the capture or bubble phase
    - *     of the event.
    - * @param {Object=} opt_handlerScope Object in whose scope to call
    - *     the listener.
    - * @deprecated Use {@code #unlisten} instead, when possible. Otherwise, use
    - *     {@code goog.events.unlisten} if you are passing Object
    - *     (instead of Function) as handler.
    - */
    -goog.events.EventTarget.prototype.removeEventListener = function(
    -    type, handler, opt_capture, opt_handlerScope) {
    -  goog.events.unlisten(this, type, handler, opt_capture, opt_handlerScope);
    -};
    -
    -
    -/** @override */
    -goog.events.EventTarget.prototype.dispatchEvent = function(e) {
    -  this.assertInitialized_();
    -
    -  var ancestorsTree, ancestor = this.getParentEventTarget();
    -  if (ancestor) {
    -    ancestorsTree = [];
    -    var ancestorCount = 1;
    -    for (; ancestor; ancestor = ancestor.getParentEventTarget()) {
    -      ancestorsTree.push(ancestor);
    -      goog.asserts.assert(
    -          (++ancestorCount < goog.events.EventTarget.MAX_ANCESTORS_),
    -          'infinite loop');
    -    }
    -  }
    -
    -  return goog.events.EventTarget.dispatchEventInternal_(
    -      this.actualEventTarget_, e, ancestorsTree);
    -};
    -
    -
    -/**
    - * Removes listeners from this object.  Classes that extend EventTarget may
    - * need to override this method in order to remove references to DOM Elements
    - * and additional listeners.
    - * @override
    - */
    -goog.events.EventTarget.prototype.disposeInternal = function() {
    -  goog.events.EventTarget.superClass_.disposeInternal.call(this);
    -
    -  this.removeAllListeners();
    -  this.parentEventTarget_ = null;
    -};
    -
    -
    -/** @override */
    -goog.events.EventTarget.prototype.listen = function(
    -    type, listener, opt_useCapture, opt_listenerScope) {
    -  this.assertInitialized_();
    -  return this.eventTargetListeners_.add(
    -      String(type), listener, false /* callOnce */, opt_useCapture,
    -      opt_listenerScope);
    -};
    -
    -
    -/** @override */
    -goog.events.EventTarget.prototype.listenOnce = function(
    -    type, listener, opt_useCapture, opt_listenerScope) {
    -  return this.eventTargetListeners_.add(
    -      String(type), listener, true /* callOnce */, opt_useCapture,
    -      opt_listenerScope);
    -};
    -
    -
    -/** @override */
    -goog.events.EventTarget.prototype.unlisten = function(
    -    type, listener, opt_useCapture, opt_listenerScope) {
    -  return this.eventTargetListeners_.remove(
    -      String(type), listener, opt_useCapture, opt_listenerScope);
    -};
    -
    -
    -/** @override */
    -goog.events.EventTarget.prototype.unlistenByKey = function(key) {
    -  return this.eventTargetListeners_.removeByKey(key);
    -};
    -
    -
    -/** @override */
    -goog.events.EventTarget.prototype.removeAllListeners = function(opt_type) {
    -  // TODO(chrishenry): Previously, removeAllListeners can be called on
    -  // uninitialized EventTarget, so we preserve that behavior. We
    -  // should remove this when usages that rely on that fact are purged.
    -  if (!this.eventTargetListeners_) {
    -    return 0;
    -  }
    -  return this.eventTargetListeners_.removeAll(opt_type);
    -};
    -
    -
    -/** @override */
    -goog.events.EventTarget.prototype.fireListeners = function(
    -    type, capture, eventObject) {
    -  // TODO(chrishenry): Original code avoids array creation when there
    -  // is no listener, so we do the same. If this optimization turns
    -  // out to be not required, we can replace this with
    -  // getListeners(type, capture) instead, which is simpler.
    -  var listenerArray = this.eventTargetListeners_.listeners[String(type)];
    -  if (!listenerArray) {
    -    return true;
    -  }
    -  listenerArray = listenerArray.concat();
    -
    -  var rv = true;
    -  for (var i = 0; i < listenerArray.length; ++i) {
    -    var listener = listenerArray[i];
    -    // We might not have a listener if the listener was removed.
    -    if (listener && !listener.removed && listener.capture == capture) {
    -      var listenerFn = listener.listener;
    -      var listenerHandler = listener.handler || listener.src;
    -
    -      if (listener.callOnce) {
    -        this.unlistenByKey(listener);
    -      }
    -      rv = listenerFn.call(listenerHandler, eventObject) !== false && rv;
    -    }
    -  }
    -
    -  return rv && eventObject.returnValue_ != false;
    -};
    -
    -
    -/** @override */
    -goog.events.EventTarget.prototype.getListeners = function(type, capture) {
    -  return this.eventTargetListeners_.getListeners(String(type), capture);
    -};
    -
    -
    -/** @override */
    -goog.events.EventTarget.prototype.getListener = function(
    -    type, listener, capture, opt_listenerScope) {
    -  return this.eventTargetListeners_.getListener(
    -      String(type), listener, capture, opt_listenerScope);
    -};
    -
    -
    -/** @override */
    -goog.events.EventTarget.prototype.hasListener = function(
    -    opt_type, opt_capture) {
    -  var id = goog.isDef(opt_type) ? String(opt_type) : undefined;
    -  return this.eventTargetListeners_.hasListener(id, opt_capture);
    -};
    -
    -
    -/**
    - * Sets the target to be used for {@code event.target} when firing
    - * event. Mainly used for testing. For example, see
    - * {@code goog.testing.events.mixinListenable}.
    - * @param {!Object} target The target.
    - */
    -goog.events.EventTarget.prototype.setTargetForTesting = function(target) {
    -  this.actualEventTarget_ = target;
    -};
    -
    -
    -/**
    - * Asserts that the event target instance is initialized properly.
    - * @private
    - */
    -goog.events.EventTarget.prototype.assertInitialized_ = function() {
    -  goog.asserts.assert(
    -      this.eventTargetListeners_,
    -      'Event target is not initialized. Did you call the superclass ' +
    -      '(goog.events.EventTarget) constructor?');
    -};
    -
    -
    -/**
    - * Dispatches the given event on the ancestorsTree.
    - *
    - * @param {!Object} target The target to dispatch on.
    - * @param {goog.events.Event|Object|string} e The event object.
    - * @param {Array<goog.events.Listenable>=} opt_ancestorsTree The ancestors
    - *     tree of the target, in reverse order from the closest ancestor
    - *     to the root event target. May be null if the target has no ancestor.
    - * @return {boolean} If anyone called preventDefault on the event object (or
    - *     if any of the listeners returns false) this will also return false.
    - * @private
    - */
    -goog.events.EventTarget.dispatchEventInternal_ = function(
    -    target, e, opt_ancestorsTree) {
    -  var type = e.type || /** @type {string} */ (e);
    -
    -  // If accepting a string or object, create a custom event object so that
    -  // preventDefault and stopPropagation work with the event.
    -  if (goog.isString(e)) {
    -    e = new goog.events.Event(e, target);
    -  } else if (!(e instanceof goog.events.Event)) {
    -    var oldEvent = e;
    -    e = new goog.events.Event(type, target);
    -    goog.object.extend(e, oldEvent);
    -  } else {
    -    e.target = e.target || target;
    -  }
    -
    -  var rv = true, currentTarget;
    -
    -  // Executes all capture listeners on the ancestors, if any.
    -  if (opt_ancestorsTree) {
    -    for (var i = opt_ancestorsTree.length - 1; !e.propagationStopped_ && i >= 0;
    -         i--) {
    -      currentTarget = e.currentTarget = opt_ancestorsTree[i];
    -      rv = currentTarget.fireListeners(type, true, e) && rv;
    -    }
    -  }
    -
    -  // Executes capture and bubble listeners on the target.
    -  if (!e.propagationStopped_) {
    -    currentTarget = e.currentTarget = target;
    -    rv = currentTarget.fireListeners(type, true, e) && rv;
    -    if (!e.propagationStopped_) {
    -      rv = currentTarget.fireListeners(type, false, e) && rv;
    -    }
    -  }
    -
    -  // Executes all bubble listeners on the ancestors, if any.
    -  if (opt_ancestorsTree) {
    -    for (i = 0; !e.propagationStopped_ && i < opt_ancestorsTree.length; i++) {
    -      currentTarget = e.currentTarget = opt_ancestorsTree[i];
    -      rv = currentTarget.fireListeners(type, false, e) && rv;
    -    }
    -  }
    -
    -  return rv;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/events/eventtarget_test.html b/src/database/third_party/closure-library/closure/goog/events/eventtarget_test.html
    deleted file mode 100644
    index 190951ce9b5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/eventtarget_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.events.EventTarget
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.events.EventTargetTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/events/eventtarget_test.js b/src/database/third_party/closure-library/closure/goog/events/eventtarget_test.js
    deleted file mode 100644
    index bdb0bda2859..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/eventtarget_test.js
    +++ /dev/null
    @@ -1,72 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.events.EventTargetTest');
    -goog.setTestOnly('goog.events.EventTargetTest');
    -
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.Listenable');
    -goog.require('goog.events.eventTargetTester');
    -goog.require('goog.events.eventTargetTester.KeyType');
    -goog.require('goog.events.eventTargetTester.UnlistenReturnType');
    -goog.require('goog.testing.jsunit');
    -
    -function setUp() {
    -  var newListenableFn = function() {
    -    return new goog.events.EventTarget();
    -  };
    -  var listenFn = function(src, type, listener, opt_capt, opt_handler) {
    -    return src.listen(type, listener, opt_capt, opt_handler);
    -  };
    -  var unlistenFn = function(src, type, listener, opt_capt, opt_handler) {
    -    return src.unlisten(type, listener, opt_capt, opt_handler);
    -  };
    -  var unlistenByKeyFn = function(src, key) {
    -    return src.unlistenByKey(key);
    -  };
    -  var listenOnceFn = function(src, type, listener, opt_capt, opt_handler) {
    -    return src.listenOnce(type, listener, opt_capt, opt_handler);
    -  };
    -  var dispatchEventFn = function(src, e) {
    -    return src.dispatchEvent(e);
    -  };
    -  var removeAllFn = function(src, opt_type, opt_capture) {
    -    return src.removeAllListeners(opt_type, opt_capture);
    -  };
    -  var getListenersFn = function(src, type, capture) {
    -    return src.getListeners(type, capture);
    -  };
    -  var getListenerFn = function(src, type, listener, capture, opt_handler) {
    -    return src.getListener(type, listener, capture, opt_handler);
    -  };
    -  var hasListenerFn = function(src, opt_type, opt_capture) {
    -    return src.hasListener(opt_type, opt_capture);
    -  };
    -
    -  goog.events.eventTargetTester.setUp(
    -      newListenableFn, listenFn, unlistenFn, unlistenByKeyFn,
    -      listenOnceFn, dispatchEventFn,
    -      removeAllFn, getListenersFn, getListenerFn, hasListenerFn,
    -      goog.events.eventTargetTester.KeyType.NUMBER,
    -      goog.events.eventTargetTester.UnlistenReturnType.BOOLEAN, false);
    -}
    -
    -function tearDown() {
    -  goog.events.eventTargetTester.tearDown();
    -}
    -
    -function testRuntimeTypeIsCorrect() {
    -  var target = new goog.events.EventTarget();
    -  assertTrue(goog.events.Listenable.isImplementedBy(target));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/events/eventtarget_via_googevents_test.html b/src/database/third_party/closure-library/closure/goog/events/eventtarget_via_googevents_test.html
    deleted file mode 100644
    index c47655ff092..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/eventtarget_via_googevents_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.events.EventTarget
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.events.EventTargetGoogEventsTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/events/eventtarget_via_googevents_test.js b/src/database/third_party/closure-library/closure/goog/events/eventtarget_via_googevents_test.js
    deleted file mode 100644
    index dccad976416..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/eventtarget_via_googevents_test.js
    +++ /dev/null
    @@ -1,77 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.events.EventTargetGoogEventsTest');
    -goog.setTestOnly('goog.events.EventTargetGoogEventsTest');
    -
    -goog.require('goog.events');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.eventTargetTester');
    -goog.require('goog.events.eventTargetTester.KeyType');
    -goog.require('goog.events.eventTargetTester.UnlistenReturnType');
    -goog.require('goog.testing');
    -goog.require('goog.testing.jsunit');
    -
    -function setUp() {
    -  var newListenableFn = function() {
    -    return new goog.events.EventTarget();
    -  };
    -  var unlistenByKeyFn = function(src, key) {
    -    return goog.events.unlistenByKey(key);
    -  };
    -  goog.events.eventTargetTester.setUp(
    -      newListenableFn, goog.events.listen, goog.events.unlisten,
    -      unlistenByKeyFn, goog.events.listenOnce, goog.events.dispatchEvent,
    -      goog.events.removeAll, goog.events.getListeners,
    -      goog.events.getListener, goog.events.hasListener,
    -      goog.events.eventTargetTester.KeyType.NUMBER,
    -      goog.events.eventTargetTester.UnlistenReturnType.BOOLEAN, true);
    -}
    -
    -function tearDown() {
    -  goog.events.eventTargetTester.tearDown();
    -}
    -
    -function testUnlistenProperCleanup() {
    -  goog.events.listen(eventTargets[0], EventType.A, listeners[0]);
    -  goog.events.unlisten(eventTargets[0], EventType.A, listeners[0]);
    -
    -  goog.events.listen(eventTargets[0], EventType.A, listeners[0]);
    -  eventTargets[0].unlisten(EventType.A, listeners[0]);
    -}
    -
    -function testUnlistenByKeyProperCleanup() {
    -  var keyNum = goog.events.listen(eventTargets[0], EventType.A, listeners[0]);
    -  goog.events.unlistenByKey(keyNum);
    -}
    -
    -function testListenOnceProperCleanup() {
    -  goog.events.listenOnce(eventTargets[0], EventType.A, listeners[0]);
    -  eventTargets[0].dispatchEvent(EventType.A);
    -}
    -
    -function testListenWithObject() {
    -  var obj = {};
    -  obj.handleEvent = goog.testing.recordFunction();
    -  goog.events.listen(eventTargets[0], EventType.A, obj);
    -  eventTargets[0].dispatchEvent(EventType.A);
    -  assertEquals(1, obj.handleEvent.getCallCount());
    -}
    -
    -function testListenWithObjectHandleEventReturningFalse() {
    -  var obj = {};
    -  obj.handleEvent = function() { return false; };
    -  goog.events.listen(eventTargets[0], EventType.A, obj);
    -  assertFalse(eventTargets[0].dispatchEvent(EventType.A));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/events/eventtarget_via_w3cinterface_test.html b/src/database/third_party/closure-library/closure/goog/events/eventtarget_via_w3cinterface_test.html
    deleted file mode 100644
    index c908950ad39..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/eventtarget_via_w3cinterface_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.events.EventTarget
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.events.EventTargetW3CTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/events/eventtarget_via_w3cinterface_test.js b/src/database/third_party/closure-library/closure/goog/events/eventtarget_via_w3cinterface_test.js
    deleted file mode 100644
    index 3778b8653cd..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/eventtarget_via_w3cinterface_test.js
    +++ /dev/null
    @@ -1,49 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.events.EventTargetW3CTest');
    -goog.setTestOnly('goog.events.EventTargetW3CTest');
    -
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.eventTargetTester');
    -goog.require('goog.events.eventTargetTester.KeyType');
    -goog.require('goog.events.eventTargetTester.UnlistenReturnType');
    -goog.require('goog.testing.jsunit');
    -
    -function setUp() {
    -  var newListenableFn = function() {
    -    return new goog.events.EventTarget();
    -  };
    -  var listenFn = function(src, type, listener, opt_capt, opt_handler) {
    -    src.addEventListener(type, listener, opt_capt, opt_handler);
    -  };
    -  var unlistenFn = function(src, type, listener, opt_capt, opt_handler) {
    -    src.removeEventListener(type, listener, opt_capt, opt_handler);
    -  };
    -  var dispatchEventFn = function(src, e) {
    -    return src.dispatchEvent(e);
    -  };
    -
    -  goog.events.eventTargetTester.setUp(
    -      newListenableFn, listenFn, unlistenFn, null /* unlistenByKeyFn */,
    -      null /* listenOnceFn */, dispatchEventFn, null /* removeAllFn */,
    -      null /* getListenersFn */, null /* getListenerFn */,
    -      null /* hasListenerFn */,
    -      goog.events.eventTargetTester.KeyType.UNDEFINED,
    -      goog.events.eventTargetTester.UnlistenReturnType.UNDEFINED, true);
    -}
    -
    -function tearDown() {
    -  goog.events.eventTargetTester.tearDown();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/events/eventtargettester.js b/src/database/third_party/closure-library/closure/goog/events/eventtargettester.js
    deleted file mode 100644
    index f5bd41bffa2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/eventtargettester.js
    +++ /dev/null
    @@ -1,1063 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview goog.events.EventTarget tester.
    - * @author chrishenry@google.com (Chris Henry)
    - */
    -
    -goog.provide('goog.events.eventTargetTester');
    -goog.setTestOnly('goog.events.eventTargetTester');
    -goog.provide('goog.events.eventTargetTester.KeyType');
    -goog.setTestOnly('goog.events.eventTargetTester.KeyType');
    -goog.provide('goog.events.eventTargetTester.UnlistenReturnType');
    -goog.setTestOnly('goog.events.eventTargetTester.UnlistenReturnType');
    -
    -goog.require('goog.array');
    -goog.require('goog.events');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.testing.asserts');
    -goog.require('goog.testing.recordFunction');
    -
    -
    -/**
    - * Setup step for the test functions. This needs to be called from the
    - * test setUp.
    - * @param {function():!goog.events.Listenable} listenableFactoryFn Function
    - *     that will return a new Listenable instance each time it is called.
    - * @param {Function} listenFn Function that, given the same signature
    - *     as goog.events.listen, will add listener to the given event
    - *     target.
    - * @param {Function} unlistenFn Function that, given the same
    - *     signature as goog.events.unlisten, will remove listener from
    - *     the given event target.
    - * @param {Function} unlistenByKeyFn Function that, given 2
    - *     parameters: src and key, will remove the corresponding
    - *     listener.
    - * @param {Function} listenOnceFn Function that, given the same
    - *     signature as goog.events.listenOnce, will add a one-time
    - *     listener to the given event target.
    - * @param {Function} dispatchEventFn Function that, given the same
    - *     signature as goog.events.dispatchEvent, will dispatch the event
    - *     on the given event target.
    - * @param {Function} removeAllFn Function that, given the same
    - *     signature as goog.events.removeAll, will remove all listeners
    - *     according to the contract of goog.events.removeAll.
    - * @param {Function} getListenersFn Function that, given the same
    - *     signature as goog.events.getListeners, will retrieve listeners.
    - * @param {Function} getListenerFn Function that, given the same
    - *     signature as goog.events.getListener, will retrieve the
    - *     listener object.
    - * @param {Function} hasListenerFn Function that, given the same
    - *     signature as goog.events.hasListener, will determine whether
    - *     listeners exist.
    - * @param {goog.events.eventTargetTester.KeyType} listenKeyType The
    - *     key type returned by listen call.
    - * @param {goog.events.eventTargetTester.UnlistenReturnType}
    - *     unlistenFnReturnType
    - *     Whether we should check return value from
    - *     unlisten call. If unlisten does not return a value, this should
    - *     be set to false.
    - * @param {boolean} objectListenerSupported Whether listener of type
    - *     Object is supported.
    - */
    -goog.events.eventTargetTester.setUp = function(
    -    listenableFactoryFn,
    -    listenFn, unlistenFn, unlistenByKeyFn, listenOnceFn,
    -    dispatchEventFn, removeAllFn,
    -    getListenersFn, getListenerFn, hasListenerFn,
    -    listenKeyType, unlistenFnReturnType, objectListenerSupported) {
    -  listenableFactory = listenableFactoryFn;
    -  listen = listenFn;
    -  unlisten = unlistenFn;
    -  unlistenByKey = unlistenByKeyFn;
    -  listenOnce = listenOnceFn;
    -  dispatchEvent = dispatchEventFn;
    -  removeAll = removeAllFn;
    -  getListeners = getListenersFn;
    -  getListener = getListenerFn;
    -  hasListener = hasListenerFn;
    -  keyType = listenKeyType;
    -  unlistenReturnType = unlistenFnReturnType;
    -  objectTypeListenerSupported = objectListenerSupported;
    -
    -  listeners = [];
    -  for (var i = 0; i < goog.events.eventTargetTester.MAX_; i++) {
    -    listeners[i] = createListener();
    -  }
    -
    -  eventTargets = [];
    -  for (i = 0; i < goog.events.eventTargetTester.MAX_; i++) {
    -    eventTargets[i] = listenableFactory();
    -  }
    -};
    -
    -
    -/**
    - * Teardown step for the test functions. This needs to be called from
    - * test teardown.
    - */
    -goog.events.eventTargetTester.tearDown = function() {
    -  for (var i = 0; i < goog.events.eventTargetTester.MAX_; i++) {
    -    goog.dispose(eventTargets[i]);
    -  }
    -};
    -
    -
    -/**
    - * The type of key returned by key-returning functions (listen).
    - * @enum {number}
    - */
    -goog.events.eventTargetTester.KeyType = {
    -  /**
    -   * Returns number for key.
    -   */
    -  NUMBER: 0,
    -
    -  /**
    -   * Returns undefined (no return value).
    -   */
    -  UNDEFINED: 1
    -};
    -
    -
    -/**
    - * The type of unlisten function's return value.
    - */
    -goog.events.eventTargetTester.UnlistenReturnType = {
    -  /**
    -   * Returns boolean indicating whether unlisten is successful.
    -   */
    -  BOOLEAN: 0,
    -
    -  /**
    -   * Returns undefind (no return value).
    -   */
    -  UNDEFINED: 1
    -};
    -
    -
    -/**
    - * Expando property used on "listener" function to determine if a
    - * listener has already been checked. This is what allows us to
    - * implement assertNoOtherListenerIsCalled.
    - * @type {string}
    - */
    -goog.events.eventTargetTester.ALREADY_CHECKED_PROP = '__alreadyChecked';
    -
    -
    -/**
    - * Expando property used on "listener" function to record the number
    - * of times it has been called the last time assertListenerIsCalled is
    - * done. This allows us to verify that it has not been called more
    - * times in assertNoOtherListenerIsCalled.
    - */
    -goog.events.eventTargetTester.NUM_CALLED_PROP = '__numCalled';
    -
    -
    -/**
    - * The maximum number of initialized event targets (in eventTargets
    - * array) and listeners (in listeners array).
    - * @type {number}
    - * @private
    - */
    -goog.events.eventTargetTester.MAX_ = 10;
    -
    -
    -/**
    - * Contains test event types.
    - * @enum {string}
    - */
    -var EventType = {
    -  A: goog.events.getUniqueId('a'),
    -  B: goog.events.getUniqueId('b'),
    -  C: goog.events.getUniqueId('c')
    -};
    -
    -
    -var listenableFactory, listen, unlisten, unlistenByKey, listenOnce;
    -var dispatchEvent, removeAll, getListeners, getListener, hasListener;
    -var keyType, unlistenReturnType, objectTypeListenerSupported;
    -var eventTargets, listeners;
    -
    -
    -
    -/**
    - * Custom event object for testing.
    - * @constructor
    - * @extends {goog.events.Event}
    - * @final
    - */
    -var TestEvent = function() {
    -  TestEvent.base(this, 'constructor', EventType.A);
    -};
    -goog.inherits(TestEvent, goog.events.Event);
    -
    -
    -/**
    - * Creates a listener that executes the given function (optional).
    - * @param {!Function=} opt_listenerFn The optional function to execute.
    - * @return {!Function} The listener function.
    - */
    -function createListener(opt_listenerFn) {
    -  return goog.testing.recordFunction(opt_listenerFn);
    -}
    -
    -
    -/**
    - * Asserts that the given listener is called numCount number of times.
    - * @param {!Function} listener The listener to check.
    - * @param {number} numCount The number of times. See also the times()
    - *     function below.
    - */
    -function assertListenerIsCalled(listener, numCount) {
    -  assertEquals('Listeners is not called the correct number of times.',
    -               numCount, listener.getCallCount());
    -  listener[goog.events.eventTargetTester.ALREADY_CHECKED_PROP] = true;
    -  listener[goog.events.eventTargetTester.NUM_CALLED_PROP] = numCount;
    -}
    -
    -
    -/**
    - * Asserts that no other listeners, other than those verified via
    - * assertListenerIsCalled, have been called since the last
    - * resetListeners().
    - */
    -function assertNoOtherListenerIsCalled() {
    -  goog.array.forEach(listeners, function(l, index) {
    -    if (!l[goog.events.eventTargetTester.ALREADY_CHECKED_PROP]) {
    -      assertEquals(
    -          'Listeners ' + index + ' is unexpectedly called.',
    -          0, l.getCallCount());
    -    } else {
    -      assertEquals(
    -          'Listeners ' + index + ' is unexpectedly called.',
    -          l[goog.events.eventTargetTester.NUM_CALLED_PROP], l.getCallCount());
    -    }
    -  });
    -}
    -
    -
    -/**
    - * Resets all listeners call count to 0.
    - */
    -function resetListeners() {
    -  goog.array.forEach(listeners, function(l) {
    -    l.reset();
    -    l[goog.events.eventTargetTester.ALREADY_CHECKED_PROP] = false;
    -  });
    -}
    -
    -
    -/**
    - * The number of times a listener should have been executed. This
    - * exists to make assertListenerIsCalled more readable.  This is used
    - * like so: assertListenerIsCalled(listener, times(2));
    - * @param {number} n The number of times a listener should have been
    - *     executed.
    - * @return {number} The number n.
    - */
    -function times(n) {
    -  return n;
    -}
    -
    -
    -function testNoListener() {
    -  dispatchEvent(eventTargets[0], EventType.A);
    -  assertNoOtherListenerIsCalled();
    -}
    -
    -
    -function testOneListener() {
    -  listen(eventTargets[0], EventType.A, listeners[0]);
    -  dispatchEvent(eventTargets[0], EventType.A);
    -  assertListenerIsCalled(listeners[0], times(1));
    -  assertNoOtherListenerIsCalled();
    -
    -  resetListeners();
    -
    -  dispatchEvent(eventTargets[0], EventType.B);
    -  dispatchEvent(eventTargets[0], EventType.C);
    -  assertNoOtherListenerIsCalled();
    -}
    -
    -
    -function testTwoListenersOfSameType() {
    -  var key1 = listen(eventTargets[0], EventType.A, listeners[0]);
    -  var key2 = listen(eventTargets[0], EventType.A, listeners[1]);
    -
    -  if (keyType == goog.events.eventTargetTester.KeyType.NUMBER) {
    -    assertNotEquals(key1, key2);
    -  } else {
    -    assertUndefined(key1);
    -    assertUndefined(key2);
    -  }
    -
    -  dispatchEvent(eventTargets[0], EventType.A);
    -  assertListenerIsCalled(listeners[0], times(1));
    -  assertListenerIsCalled(listeners[1], times(1));
    -  assertNoOtherListenerIsCalled();
    -}
    -
    -
    -function testInstallingSameListeners() {
    -  var key1 = listen(eventTargets[0], EventType.A, listeners[0]);
    -  var key2 = listen(eventTargets[0], EventType.A, listeners[0]);
    -  var key3 = listen(eventTargets[0], EventType.B, listeners[0]);
    -
    -  if (keyType == goog.events.eventTargetTester.KeyType.NUMBER) {
    -    assertEquals(key1, key2);
    -    assertNotEquals(key1, key3);
    -  } else {
    -    assertUndefined(key1);
    -    assertUndefined(key2);
    -    assertUndefined(key3);
    -  }
    -
    -  dispatchEvent(eventTargets[0], EventType.A);
    -  assertListenerIsCalled(listeners[0], times(1));
    -
    -  dispatchEvent(eventTargets[0], EventType.B);
    -  assertListenerIsCalled(listeners[0], times(2));
    -
    -  assertNoOtherListenerIsCalled();
    -}
    -
    -
    -function testScope() {
    -  listeners[0] = createListener(function(e) {
    -    assertEquals('Wrong scope with undefined scope', eventTargets[0], this);
    -  });
    -  listeners[1] = createListener(function(e) {
    -    assertEquals('Wrong scope with null scope', eventTargets[0], this);
    -  });
    -  var scope = {};
    -  listeners[2] = createListener(function(e) {
    -    assertEquals('Wrong scope with specific scope object', scope, this);
    -  });
    -  listen(eventTargets[0], EventType.A, listeners[0]);
    -  listen(eventTargets[0], EventType.A, listeners[1], false, null);
    -  listen(eventTargets[0], EventType.A, listeners[2], false, scope);
    -
    -  dispatchEvent(eventTargets[0], EventType.A);
    -  assertListenerIsCalled(listeners[0], times(1));
    -  assertListenerIsCalled(listeners[1], times(1));
    -  assertListenerIsCalled(listeners[2], times(1));
    -}
    -
    -
    -function testDispatchEventDoesNotThrowWithDisposedEventTarget() {
    -  goog.dispose(eventTargets[0]);
    -  assertTrue(dispatchEvent(eventTargets[0], EventType.A));
    -}
    -
    -
    -function testDispatchEventWithObjectLiteral() {
    -  listen(eventTargets[0], EventType.A, listeners[0]);
    -
    -  assertTrue(dispatchEvent(eventTargets[0], {type: EventType.A}));
    -  assertListenerIsCalled(listeners[0], times(1));
    -  assertNoOtherListenerIsCalled();
    -}
    -
    -
    -function testDispatchEventWithCustomEventObject() {
    -  listen(eventTargets[0], EventType.A, listeners[0]);
    -
    -  var e = new TestEvent();
    -  assertTrue(dispatchEvent(eventTargets[0], e));
    -  assertListenerIsCalled(listeners[0], times(1));
    -  assertNoOtherListenerIsCalled();
    -
    -  var actualEvent = listeners[0].getLastCall().getArgument(0);
    -
    -  assertEquals(e, actualEvent);
    -  assertEquals(eventTargets[0], actualEvent.target);
    -}
    -
    -
    -function testDisposingEventTargetRemovesListeners() {
    -  if (!(listenableFactory() instanceof goog.events.EventTarget)) {
    -    return;
    -  }
    -  listen(eventTargets[0], EventType.A, listeners[0]);
    -  goog.dispose(eventTargets[0]);
    -  dispatchEvent(eventTargets[0], EventType.A);
    -
    -  assertNoOtherListenerIsCalled();
    -}
    -
    -
    -/**
    - * Unlisten/unlistenByKey should still work after disposal. There are
    - * many circumstances when this is actually necessary. For example, a
    - * user may have listened to an event target and stored the key
    - * (e.g. in a goog.events.EventHandler) and only unlisten after the
    - * target has been disposed.
    - */
    -function testUnlistenWorksAfterDisposal() {
    -  var key = listen(eventTargets[0], EventType.A, listeners[0]);
    -  goog.dispose(eventTargets[0]);
    -  unlisten(eventTargets[0], EventType.A, listeners[1]);
    -  if (unlistenByKey) {
    -    unlistenByKey(eventTargets[0], key);
    -  }
    -}
    -
    -
    -function testRemovingListener() {
    -  var ret1 = unlisten(eventTargets[0], EventType.A, listeners[0]);
    -  listen(eventTargets[0], EventType.A, listeners[0]);
    -  var ret2 = unlisten(eventTargets[0], EventType.A, listeners[1]);
    -  var ret3 = unlisten(eventTargets[0], EventType.B, listeners[0]);
    -  var ret4 = unlisten(eventTargets[1], EventType.A, listeners[0]);
    -
    -  dispatchEvent(eventTargets[0], EventType.A);
    -  assertListenerIsCalled(listeners[0], times(1));
    -
    -  var ret5 = unlisten(eventTargets[0], EventType.A, listeners[0]);
    -  var ret6 = unlisten(eventTargets[0], EventType.A, listeners[0]);
    -
    -  dispatchEvent(eventTargets[0], EventType.A);
    -  assertListenerIsCalled(listeners[0], times(1));
    -
    -  assertNoOtherListenerIsCalled();
    -
    -  if (unlistenReturnType ==
    -      goog.events.eventTargetTester.UnlistenReturnType.BOOLEAN) {
    -    assertFalse(ret1);
    -    assertFalse(ret2);
    -    assertFalse(ret3);
    -    assertFalse(ret4);
    -    assertTrue(ret5);
    -    assertFalse(ret6);
    -  } else {
    -    assertUndefined(ret1);
    -    assertUndefined(ret2);
    -    assertUndefined(ret3);
    -    assertUndefined(ret4);
    -    assertUndefined(ret5);
    -    assertUndefined(ret6);
    -  }
    -}
    -
    -
    -function testCapture() {
    -  eventTargets[0].setParentEventTarget(eventTargets[1]);
    -  eventTargets[1].setParentEventTarget(eventTargets[2]);
    -
    -  eventTargets[9].setParentEventTarget(eventTargets[0]);
    -
    -  var ordering = 0;
    -  listeners[0] = createListener(
    -      function(e) {
    -        assertEquals(eventTargets[2], e.currentTarget);
    -        assertEquals(eventTargets[0], e.target);
    -        assertEquals('First capture listener is not called first', 0, ordering);
    -        ordering++;
    -      });
    -  listeners[1] = createListener(
    -      function(e) {
    -        assertEquals(eventTargets[1], e.currentTarget);
    -        assertEquals(eventTargets[0], e.target);
    -        assertEquals('2nd capture listener is not called 2nd', 1, ordering);
    -        ordering++;
    -      });
    -  listeners[2] = createListener(
    -      function(e) {
    -        assertEquals(eventTargets[0], e.currentTarget);
    -        assertEquals(eventTargets[0], e.target);
    -        assertEquals('3rd capture listener is not called 3rd', 2, ordering);
    -        ordering++;
    -      });
    -
    -  listen(eventTargets[2], EventType.A, listeners[0], true);
    -  listen(eventTargets[1], EventType.A, listeners[1], true);
    -  listen(eventTargets[0], EventType.A, listeners[2], true);
    -
    -  // These should not be called.
    -  listen(eventTargets[3], EventType.A, listeners[3], true);
    -
    -  listen(eventTargets[0], EventType.B, listeners[4], true);
    -  listen(eventTargets[0], EventType.C, listeners[5], true);
    -  listen(eventTargets[1], EventType.B, listeners[6], true);
    -  listen(eventTargets[1], EventType.C, listeners[7], true);
    -  listen(eventTargets[2], EventType.B, listeners[8], true);
    -  listen(eventTargets[2], EventType.C, listeners[9], true);
    -
    -  dispatchEvent(eventTargets[0], EventType.A);
    -  assertListenerIsCalled(listeners[0], times(1));
    -  assertListenerIsCalled(listeners[1], times(1));
    -  assertListenerIsCalled(listeners[2], times(1));
    -  assertNoOtherListenerIsCalled();
    -}
    -
    -
    -function testBubble() {
    -  eventTargets[0].setParentEventTarget(eventTargets[1]);
    -  eventTargets[1].setParentEventTarget(eventTargets[2]);
    -
    -  eventTargets[9].setParentEventTarget(eventTargets[0]);
    -
    -  var ordering = 0;
    -  listeners[0] = createListener(
    -      function(e) {
    -        assertEquals(eventTargets[0], e.currentTarget);
    -        assertEquals(eventTargets[0], e.target);
    -        assertEquals('First bubble listener is not called first', 0, ordering);
    -        ordering++;
    -      });
    -  listeners[1] = createListener(
    -      function(e) {
    -        assertEquals(eventTargets[1], e.currentTarget);
    -        assertEquals(eventTargets[0], e.target);
    -        assertEquals('2nd bubble listener is not called 2nd', 1, ordering);
    -        ordering++;
    -      });
    -  listeners[2] = createListener(
    -      function(e) {
    -        assertEquals(eventTargets[2], e.currentTarget);
    -        assertEquals(eventTargets[0], e.target);
    -        assertEquals('3rd bubble listener is not called 3rd', 2, ordering);
    -        ordering++;
    -      });
    -
    -  listen(eventTargets[0], EventType.A, listeners[0]);
    -  listen(eventTargets[1], EventType.A, listeners[1]);
    -  listen(eventTargets[2], EventType.A, listeners[2]);
    -
    -  // These should not be called.
    -  listen(eventTargets[3], EventType.A, listeners[3]);
    -
    -  listen(eventTargets[0], EventType.B, listeners[4]);
    -  listen(eventTargets[0], EventType.C, listeners[5]);
    -  listen(eventTargets[1], EventType.B, listeners[6]);
    -  listen(eventTargets[1], EventType.C, listeners[7]);
    -  listen(eventTargets[2], EventType.B, listeners[8]);
    -  listen(eventTargets[2], EventType.C, listeners[9]);
    -
    -  dispatchEvent(eventTargets[0], EventType.A);
    -  assertListenerIsCalled(listeners[0], times(1));
    -  assertListenerIsCalled(listeners[1], times(1));
    -  assertListenerIsCalled(listeners[2], times(1));
    -  assertNoOtherListenerIsCalled();
    -}
    -
    -
    -function testCaptureAndBubble() {
    -  eventTargets[0].setParentEventTarget(eventTargets[1]);
    -  eventTargets[1].setParentEventTarget(eventTargets[2]);
    -
    -  listen(eventTargets[0], EventType.A, listeners[0], true);
    -  listen(eventTargets[1], EventType.A, listeners[1], true);
    -  listen(eventTargets[2], EventType.A, listeners[2], true);
    -
    -  listen(eventTargets[0], EventType.A, listeners[3]);
    -  listen(eventTargets[1], EventType.A, listeners[4]);
    -  listen(eventTargets[2], EventType.A, listeners[5]);
    -
    -  dispatchEvent(eventTargets[0], EventType.A);
    -  assertListenerIsCalled(listeners[0], times(1));
    -  assertListenerIsCalled(listeners[1], times(1));
    -  assertListenerIsCalled(listeners[2], times(1));
    -  assertListenerIsCalled(listeners[3], times(1));
    -  assertListenerIsCalled(listeners[4], times(1));
    -  assertListenerIsCalled(listeners[5], times(1));
    -  assertNoOtherListenerIsCalled();
    -}
    -
    -
    -function testPreventDefaultByReturningFalse() {
    -  listeners[0] = createListener(function(e) { return false; });
    -  listeners[1] = createListener(function(e) { return true; });
    -  listen(eventTargets[0], EventType.A, listeners[0]);
    -  listen(eventTargets[0], EventType.A, listeners[1]);
    -
    -  var result = dispatchEvent(eventTargets[0], EventType.A);
    -  assertFalse(result);
    -}
    -
    -
    -function testPreventDefault() {
    -  listeners[0] = createListener(function(e) { e.preventDefault(); });
    -  listeners[1] = createListener(function(e) { return true; });
    -  listen(eventTargets[0], EventType.A, listeners[0]);
    -  listen(eventTargets[0], EventType.A, listeners[1]);
    -
    -  var result = dispatchEvent(eventTargets[0], EventType.A);
    -  assertFalse(result);
    -}
    -
    -
    -function testPreventDefaultAtCapture() {
    -  listeners[0] = createListener(function(e) { e.preventDefault(); });
    -  listeners[1] = createListener(function(e) { return true; });
    -  listen(eventTargets[0], EventType.A, listeners[0], true);
    -  listen(eventTargets[0], EventType.A, listeners[1], true);
    -
    -  var result = dispatchEvent(eventTargets[0], EventType.A);
    -  assertFalse(result);
    -}
    -
    -
    -function testStopPropagation() {
    -  eventTargets[0].setParentEventTarget(eventTargets[1]);
    -  eventTargets[1].setParentEventTarget(eventTargets[2]);
    -
    -  listeners[0] = createListener(function(e) { e.stopPropagation(); });
    -  listen(eventTargets[0], EventType.A, listeners[0]);
    -  listen(eventTargets[0], EventType.A, listeners[1]);
    -  listen(eventTargets[1], EventType.A, listeners[2]);
    -  listen(eventTargets[2], EventType.A, listeners[3]);
    -
    -  dispatchEvent(eventTargets[0], EventType.A);
    -
    -  assertListenerIsCalled(listeners[0], times(1));
    -  assertListenerIsCalled(listeners[1], times(1));
    -  assertNoOtherListenerIsCalled();
    -}
    -
    -
    -function testStopPropagation2() {
    -  eventTargets[0].setParentEventTarget(eventTargets[1]);
    -  eventTargets[1].setParentEventTarget(eventTargets[2]);
    -
    -  listeners[1] = createListener(function(e) { e.stopPropagation(); });
    -  listen(eventTargets[0], EventType.A, listeners[0]);
    -  listen(eventTargets[0], EventType.A, listeners[1]);
    -  listen(eventTargets[1], EventType.A, listeners[2]);
    -  listen(eventTargets[2], EventType.A, listeners[3]);
    -
    -  dispatchEvent(eventTargets[0], EventType.A);
    -
    -  assertListenerIsCalled(listeners[0], times(1));
    -  assertListenerIsCalled(listeners[1], times(1));
    -  assertNoOtherListenerIsCalled();
    -}
    -
    -
    -function testStopPropagation3() {
    -  eventTargets[0].setParentEventTarget(eventTargets[1]);
    -  eventTargets[1].setParentEventTarget(eventTargets[2]);
    -
    -  listeners[2] = createListener(function(e) { e.stopPropagation(); });
    -  listen(eventTargets[0], EventType.A, listeners[0]);
    -  listen(eventTargets[0], EventType.A, listeners[1]);
    -  listen(eventTargets[1], EventType.A, listeners[2]);
    -  listen(eventTargets[2], EventType.A, listeners[3]);
    -
    -  dispatchEvent(eventTargets[0], EventType.A);
    -
    -  assertListenerIsCalled(listeners[0], times(1));
    -  assertListenerIsCalled(listeners[1], times(1));
    -  assertListenerIsCalled(listeners[2], times(1));
    -  assertNoOtherListenerIsCalled();
    -}
    -
    -
    -function testStopPropagationAtCapture() {
    -  eventTargets[0].setParentEventTarget(eventTargets[1]);
    -  eventTargets[1].setParentEventTarget(eventTargets[2]);
    -
    -  listeners[0] = createListener(function(e) { e.stopPropagation(); });
    -  listen(eventTargets[2], EventType.A, listeners[0], true);
    -  listen(eventTargets[1], EventType.A, listeners[1], true);
    -  listen(eventTargets[0], EventType.A, listeners[2], true);
    -  listen(eventTargets[0], EventType.A, listeners[3]);
    -  listen(eventTargets[1], EventType.A, listeners[4]);
    -  listen(eventTargets[2], EventType.A, listeners[5]);
    -
    -  dispatchEvent(eventTargets[0], EventType.A);
    -
    -  assertListenerIsCalled(listeners[0], times(1));
    -  assertNoOtherListenerIsCalled();
    -}
    -
    -
    -function testHandleEvent() {
    -  if (!objectTypeListenerSupported) {
    -    return;
    -  }
    -
    -  var obj = {};
    -  obj.handleEvent = goog.testing.recordFunction();
    -
    -  listen(eventTargets[0], EventType.A, obj);
    -  dispatchEvent(eventTargets[0], EventType.A);
    -
    -  assertEquals(1, obj.handleEvent.getCallCount());
    -}
    -
    -
    -function testListenOnce() {
    -  if (!listenOnce) {
    -    return;
    -  }
    -
    -  listenOnce(eventTargets[0], EventType.A, listeners[0], true);
    -  listenOnce(eventTargets[0], EventType.A, listeners[1]);
    -  listenOnce(eventTargets[0], EventType.B, listeners[2]);
    -
    -  dispatchEvent(eventTargets[0], EventType.A);
    -
    -  assertListenerIsCalled(listeners[0], times(1));
    -  assertListenerIsCalled(listeners[1], times(1));
    -  assertListenerIsCalled(listeners[2], times(0));
    -  assertNoOtherListenerIsCalled();
    -  resetListeners();
    -
    -  dispatchEvent(eventTargets[0], EventType.A);
    -
    -  assertListenerIsCalled(listeners[0], times(0));
    -  assertListenerIsCalled(listeners[1], times(0));
    -  assertListenerIsCalled(listeners[2], times(0));
    -
    -  dispatchEvent(eventTargets[0], EventType.B);
    -  assertListenerIsCalled(listeners[2], times(1));
    -  assertNoOtherListenerIsCalled();
    -}
    -
    -
    -function testUnlistenInListen() {
    -  listeners[1] = createListener(
    -      function(e) {
    -        unlisten(eventTargets[0], EventType.A, listeners[1]);
    -        unlisten(eventTargets[0], EventType.A, listeners[2]);
    -      });
    -  listen(eventTargets[0], EventType.A, listeners[0]);
    -  listen(eventTargets[0], EventType.A, listeners[1]);
    -  listen(eventTargets[0], EventType.A, listeners[2]);
    -  listen(eventTargets[0], EventType.A, listeners[3]);
    -
    -  dispatchEvent(eventTargets[0], EventType.A);
    -
    -  assertListenerIsCalled(listeners[0], times(1));
    -  assertListenerIsCalled(listeners[1], times(1));
    -  assertListenerIsCalled(listeners[2], times(0));
    -  assertListenerIsCalled(listeners[3], times(1));
    -  assertNoOtherListenerIsCalled();
    -  resetListeners();
    -
    -  dispatchEvent(eventTargets[0], EventType.A);
    -  assertListenerIsCalled(listeners[0], times(1));
    -  assertListenerIsCalled(listeners[1], times(0));
    -  assertListenerIsCalled(listeners[2], times(0));
    -  assertListenerIsCalled(listeners[3], times(1));
    -  assertNoOtherListenerIsCalled();
    -}
    -
    -
    -function testUnlistenByKeyInListen() {
    -  if (!unlistenByKey) {
    -    return;
    -  }
    -
    -  var key1, key2;
    -  listeners[1] = createListener(
    -      function(e) {
    -        unlistenByKey(eventTargets[0], key1);
    -        unlistenByKey(eventTargets[0], key2);
    -      });
    -  listen(eventTargets[0], EventType.A, listeners[0]);
    -  key1 = listen(eventTargets[0], EventType.A, listeners[1]);
    -  key2 = listen(eventTargets[0], EventType.A, listeners[2]);
    -  listen(eventTargets[0], EventType.A, listeners[3]);
    -
    -  dispatchEvent(eventTargets[0], EventType.A);
    -
    -  assertListenerIsCalled(listeners[0], times(1));
    -  assertListenerIsCalled(listeners[1], times(1));
    -  assertListenerIsCalled(listeners[2], times(0));
    -  assertListenerIsCalled(listeners[3], times(1));
    -  assertNoOtherListenerIsCalled();
    -  resetListeners();
    -
    -  dispatchEvent(eventTargets[0], EventType.A);
    -  assertListenerIsCalled(listeners[0], times(1));
    -  assertListenerIsCalled(listeners[1], times(0));
    -  assertListenerIsCalled(listeners[2], times(0));
    -  assertListenerIsCalled(listeners[3], times(1));
    -  assertNoOtherListenerIsCalled();
    -}
    -
    -
    -function testSetParentEventTarget() {
    -  assertNull(eventTargets[0].getParentEventTarget());
    -
    -  eventTargets[0].setParentEventTarget(eventTargets[1]);
    -  assertEquals(eventTargets[1], eventTargets[0].getParentEventTarget());
    -  assertNull(eventTargets[1].getParentEventTarget());
    -
    -  eventTargets[0].setParentEventTarget(null);
    -  assertNull(eventTargets[0].getParentEventTarget());
    -}
    -
    -
    -function testListenOnceAfterListenDoesNotChangeExistingListener() {
    -  if (!listenOnce) {
    -    return;
    -  }
    -
    -  listen(eventTargets[0], EventType.A, listeners[0]);
    -  listenOnce(eventTargets[0], EventType.A, listeners[0]);
    -
    -  dispatchEvent(eventTargets[0], EventType.A);
    -  dispatchEvent(eventTargets[0], EventType.A);
    -  dispatchEvent(eventTargets[0], EventType.A);
    -
    -  assertListenerIsCalled(listeners[0], times(3));
    -  assertNoOtherListenerIsCalled();
    -}
    -
    -
    -function testListenOnceAfterListenOnceDoesNotChangeExistingListener() {
    -  if (!listenOnce) {
    -    return;
    -  }
    -
    -  listenOnce(eventTargets[0], EventType.A, listeners[0]);
    -  listenOnce(eventTargets[0], EventType.A, listeners[0]);
    -
    -  dispatchEvent(eventTargets[0], EventType.A);
    -  dispatchEvent(eventTargets[0], EventType.A);
    -  dispatchEvent(eventTargets[0], EventType.A);
    -
    -  assertListenerIsCalled(listeners[0], times(1));
    -  assertNoOtherListenerIsCalled();
    -}
    -
    -
    -function testListenAfterListenOnceRemoveOnceness() {
    -  if (!listenOnce) {
    -    return;
    -  }
    -
    -  listenOnce(eventTargets[0], EventType.A, listeners[0]);
    -  listen(eventTargets[0], EventType.A, listeners[0]);
    -
    -  dispatchEvent(eventTargets[0], EventType.A);
    -  dispatchEvent(eventTargets[0], EventType.A);
    -  dispatchEvent(eventTargets[0], EventType.A);
    -
    -  assertListenerIsCalled(listeners[0], times(3));
    -  assertNoOtherListenerIsCalled();
    -}
    -
    -
    -function testUnlistenAfterListenOnce() {
    -  if (!listenOnce) {
    -    return;
    -  }
    -
    -  listenOnce(eventTargets[0], EventType.A, listeners[0]);
    -  unlisten(eventTargets[0], EventType.A, listeners[0]);
    -  dispatchEvent(eventTargets[0], EventType.A);
    -
    -  listen(eventTargets[0], EventType.A, listeners[0]);
    -  listenOnce(eventTargets[0], EventType.A, listeners[0]);
    -  unlisten(eventTargets[0], EventType.A, listeners[0]);
    -  dispatchEvent(eventTargets[0], EventType.A);
    -
    -  listenOnce(eventTargets[0], EventType.A, listeners[0]);
    -  listen(eventTargets[0], EventType.A, listeners[0]);
    -  unlisten(eventTargets[0], EventType.A, listeners[0]);
    -  dispatchEvent(eventTargets[0], EventType.A);
    -
    -  listenOnce(eventTargets[0], EventType.A, listeners[0]);
    -  listenOnce(eventTargets[0], EventType.A, listeners[0]);
    -  unlisten(eventTargets[0], EventType.A, listeners[0]);
    -  dispatchEvent(eventTargets[0], EventType.A);
    -
    -  assertNoOtherListenerIsCalled();
    -}
    -
    -
    -function testRemoveAllWithType() {
    -  if (!removeAll) {
    -    return;
    -  }
    -
    -  listen(eventTargets[0], EventType.A, listeners[0], true);
    -  listen(eventTargets[0], EventType.A, listeners[1]);
    -  listen(eventTargets[0], EventType.C, listeners[2], true);
    -  listen(eventTargets[0], EventType.C, listeners[3]);
    -  listen(eventTargets[0], EventType.B, listeners[4], true);
    -  listen(eventTargets[0], EventType.B, listeners[5], true);
    -  listen(eventTargets[0], EventType.B, listeners[6]);
    -  listen(eventTargets[0], EventType.B, listeners[7]);
    -
    -  assertEquals(4, removeAll(eventTargets[0], EventType.B));
    -
    -  dispatchEvent(eventTargets[0], EventType.A);
    -  dispatchEvent(eventTargets[0], EventType.B);
    -  dispatchEvent(eventTargets[0], EventType.C);
    -
    -  assertListenerIsCalled(listeners[0], times(1));
    -  assertListenerIsCalled(listeners[1], times(1));
    -  assertListenerIsCalled(listeners[2], times(1));
    -  assertListenerIsCalled(listeners[3], times(1));
    -  assertNoOtherListenerIsCalled();
    -}
    -
    -
    -function testRemoveAll() {
    -  if (!removeAll) {
    -    return;
    -  }
    -
    -  listen(eventTargets[0], EventType.A, listeners[0], true);
    -  listen(eventTargets[0], EventType.A, listeners[1]);
    -  listen(eventTargets[0], EventType.C, listeners[2], true);
    -  listen(eventTargets[0], EventType.C, listeners[3]);
    -  listen(eventTargets[0], EventType.B, listeners[4], true);
    -  listen(eventTargets[0], EventType.B, listeners[5], true);
    -  listen(eventTargets[0], EventType.B, listeners[6]);
    -  listen(eventTargets[0], EventType.B, listeners[7]);
    -
    -  assertEquals(8, removeAll(eventTargets[0]));
    -
    -  dispatchEvent(eventTargets[0], EventType.A);
    -  dispatchEvent(eventTargets[0], EventType.B);
    -  dispatchEvent(eventTargets[0], EventType.C);
    -
    -  assertNoOtherListenerIsCalled();
    -}
    -
    -
    -function testRemoveAllCallsMarkAsRemoved() {
    -  if (!removeAll) {
    -    return;
    -  }
    -
    -  var key0 = listen(eventTargets[0], EventType.A, listeners[0]);
    -  var key1 = listen(eventTargets[1], EventType.A, listeners[1]);
    -
    -  assertNotNullNorUndefined(key0.listener);
    -  assertFalse(key0.removed);
    -  assertNotNullNorUndefined(key1.listener);
    -  assertFalse(key1.removed);
    -
    -  assertEquals(1, removeAll(eventTargets[0]));
    -  assertNull(key0.listener);
    -  assertTrue(key0.removed);
    -  assertNotNullNorUndefined(key1.listener);
    -  assertFalse(key1.removed);
    -
    -  assertEquals(1, removeAll(eventTargets[1]));
    -  assertNull(key1.listener);
    -  assertTrue(key1.removed);
    -}
    -
    -
    -function testGetListeners() {
    -  if (!getListeners) {
    -    return;
    -  }
    -
    -  listen(eventTargets[0], EventType.A, listeners[0], true);
    -  listen(eventTargets[0], EventType.A, listeners[1], true);
    -  listen(eventTargets[0], EventType.A, listeners[2]);
    -  listen(eventTargets[0], EventType.A, listeners[3]);
    -
    -  var l = getListeners(eventTargets[0], EventType.A, true);
    -  assertEquals(2, l.length);
    -  assertEquals(listeners[0], l[0].listener);
    -  assertEquals(listeners[1], l[1].listener);
    -
    -  l = getListeners(eventTargets[0], EventType.A, false);
    -  assertEquals(2, l.length);
    -  assertEquals(listeners[2], l[0].listener);
    -  assertEquals(listeners[3], l[1].listener);
    -
    -  l = getListeners(eventTargets[0], EventType.B, true);
    -  assertEquals(0, l.length);
    -}
    -
    -
    -function testGetListener() {
    -  if (!getListener) {
    -    return;
    -  }
    -
    -  listen(eventTargets[0], EventType.A, listeners[0], true);
    -
    -  assertNotNull(getListener(eventTargets[0], EventType.A, listeners[0], true));
    -  assertNull(
    -      getListener(eventTargets[0], EventType.A, listeners[0], true, {}));
    -  assertNull(getListener(eventTargets[1], EventType.A, listeners[0], true));
    -  assertNull(getListener(eventTargets[0], EventType.B, listeners[0], true));
    -  assertNull(getListener(eventTargets[0], EventType.A, listeners[1], true));
    -}
    -
    -
    -function testHasListener() {
    -  if (!hasListener) {
    -    return;
    -  }
    -
    -  assertFalse(hasListener(eventTargets[0]));
    -
    -  listen(eventTargets[0], EventType.A, listeners[0], true);
    -
    -  assertTrue(hasListener(eventTargets[0]));
    -  assertTrue(hasListener(eventTargets[0], EventType.A));
    -  assertTrue(hasListener(eventTargets[0], EventType.A, true));
    -  assertTrue(hasListener(eventTargets[0], undefined, true));
    -  assertFalse(hasListener(eventTargets[0], EventType.A, false));
    -  assertFalse(hasListener(eventTargets[0], undefined, false));
    -  assertFalse(hasListener(eventTargets[0], EventType.B));
    -  assertFalse(hasListener(eventTargets[0], EventType.B, true));
    -  assertFalse(hasListener(eventTargets[1]));
    -}
    -
    -
    -function testFiringEventBeforeDisposeInternalWorks() {
    -  /**
    -   * @extends {goog.events.EventTarget}
    -   * @constructor
    -   * @final
    -   */
    -  var MockTarget = function() {
    -    MockTarget.base(this, 'constructor');
    -  };
    -  goog.inherits(MockTarget, goog.events.EventTarget);
    -
    -  MockTarget.prototype.disposeInternal = function() {
    -    dispatchEvent(this, EventType.A);
    -    MockTarget.base(this, 'disposeInternal');
    -  };
    -
    -  var t = new MockTarget();
    -  try {
    -    listen(t, EventType.A, listeners[0]);
    -    t.dispose();
    -    assertListenerIsCalled(listeners[0], times(1));
    -  } catch (e) {
    -    goog.dispose(t);
    -  }
    -}
    -
    -
    -function testLoopDetection() {
    -  var target = listenableFactory();
    -  target.setParentEventTarget(target);
    -
    -  try {
    -    target.dispatchEvent('string');
    -    fail('expected error');
    -  } catch (e) {
    -    assertContains('infinite', e.message);
    -  }
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/events/eventtype.js b/src/database/third_party/closure-library/closure/goog/events/eventtype.js
    deleted file mode 100644
    index 67c1da68378..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/eventtype.js
    +++ /dev/null
    @@ -1,232 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Event Types.
    - *
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -
    -goog.provide('goog.events.EventType');
    -
    -goog.require('goog.userAgent');
    -
    -
    -/**
    - * Returns a prefixed event name for the current browser.
    - * @param {string} eventName The name of the event.
    - * @return {string} The prefixed event name.
    - * @suppress {missingRequire|missingProvide}
    - * @private
    - */
    -goog.events.getVendorPrefixedName_ = function(eventName) {
    -  return goog.userAgent.WEBKIT ? 'webkit' + eventName :
    -      (goog.userAgent.OPERA ? 'o' + eventName.toLowerCase() :
    -          eventName.toLowerCase());
    -};
    -
    -
    -/**
    - * Constants for event names.
    - * @enum {string}
    - */
    -goog.events.EventType = {
    -  // Mouse events
    -  CLICK: 'click',
    -  RIGHTCLICK: 'rightclick',
    -  DBLCLICK: 'dblclick',
    -  MOUSEDOWN: 'mousedown',
    -  MOUSEUP: 'mouseup',
    -  MOUSEOVER: 'mouseover',
    -  MOUSEOUT: 'mouseout',
    -  MOUSEMOVE: 'mousemove',
    -  MOUSEENTER: 'mouseenter',
    -  MOUSELEAVE: 'mouseleave',
    -  // Select start is non-standard.
    -  // See http://msdn.microsoft.com/en-us/library/ie/ms536969(v=vs.85).aspx.
    -  SELECTSTART: 'selectstart', // IE, Safari, Chrome
    -
    -  // Wheel events
    -  // http://www.w3.org/TR/DOM-Level-3-Events/#events-wheelevents
    -  WHEEL: 'wheel',
    -
    -  // Key events
    -  KEYPRESS: 'keypress',
    -  KEYDOWN: 'keydown',
    -  KEYUP: 'keyup',
    -
    -  // Focus
    -  BLUR: 'blur',
    -  FOCUS: 'focus',
    -  DEACTIVATE: 'deactivate', // IE only
    -  // NOTE: The following two events are not stable in cross-browser usage.
    -  //     WebKit and Opera implement DOMFocusIn/Out.
    -  //     IE implements focusin/out.
    -  //     Gecko implements neither see bug at
    -  //     https://bugzilla.mozilla.org/show_bug.cgi?id=396927.
    -  // The DOM Events Level 3 Draft deprecates DOMFocusIn in favor of focusin:
    -  //     http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html
    -  // You can use FOCUS in Capture phase until implementations converge.
    -  FOCUSIN: goog.userAgent.IE ? 'focusin' : 'DOMFocusIn',
    -  FOCUSOUT: goog.userAgent.IE ? 'focusout' : 'DOMFocusOut',
    -
    -  // Forms
    -  CHANGE: 'change',
    -  SELECT: 'select',
    -  SUBMIT: 'submit',
    -  INPUT: 'input',
    -  PROPERTYCHANGE: 'propertychange', // IE only
    -
    -  // Drag and drop
    -  DRAGSTART: 'dragstart',
    -  DRAG: 'drag',
    -  DRAGENTER: 'dragenter',
    -  DRAGOVER: 'dragover',
    -  DRAGLEAVE: 'dragleave',
    -  DROP: 'drop',
    -  DRAGEND: 'dragend',
    -
    -  // Touch events
    -  // Note that other touch events exist, but we should follow the W3C list here.
    -  // http://www.w3.org/TR/touch-events/#list-of-touchevent-types
    -  TOUCHSTART: 'touchstart',
    -  TOUCHMOVE: 'touchmove',
    -  TOUCHEND: 'touchend',
    -  TOUCHCANCEL: 'touchcancel',
    -
    -  // Misc
    -  BEFOREUNLOAD: 'beforeunload',
    -  CONSOLEMESSAGE: 'consolemessage',
    -  CONTEXTMENU: 'contextmenu',
    -  DOMCONTENTLOADED: 'DOMContentLoaded',
    -  ERROR: 'error',
    -  HELP: 'help',
    -  LOAD: 'load',
    -  LOSECAPTURE: 'losecapture',
    -  ORIENTATIONCHANGE: 'orientationchange',
    -  READYSTATECHANGE: 'readystatechange',
    -  RESIZE: 'resize',
    -  SCROLL: 'scroll',
    -  UNLOAD: 'unload',
    -
    -  // HTML 5 History events
    -  // See http://www.w3.org/TR/html5/history.html#event-definitions
    -  HASHCHANGE: 'hashchange',
    -  PAGEHIDE: 'pagehide',
    -  PAGESHOW: 'pageshow',
    -  POPSTATE: 'popstate',
    -
    -  // Copy and Paste
    -  // Support is limited. Make sure it works on your favorite browser
    -  // before using.
    -  // http://www.quirksmode.org/dom/events/cutcopypaste.html
    -  COPY: 'copy',
    -  PASTE: 'paste',
    -  CUT: 'cut',
    -  BEFORECOPY: 'beforecopy',
    -  BEFORECUT: 'beforecut',
    -  BEFOREPASTE: 'beforepaste',
    -
    -  // HTML5 online/offline events.
    -  // http://www.w3.org/TR/offline-webapps/#related
    -  ONLINE: 'online',
    -  OFFLINE: 'offline',
    -
    -  // HTML 5 worker events
    -  MESSAGE: 'message',
    -  CONNECT: 'connect',
    -
    -  // CSS animation events.
    -  /** @suppress {missingRequire} */
    -  ANIMATIONSTART: goog.events.getVendorPrefixedName_('AnimationStart'),
    -  /** @suppress {missingRequire} */
    -  ANIMATIONEND: goog.events.getVendorPrefixedName_('AnimationEnd'),
    -  /** @suppress {missingRequire} */
    -  ANIMATIONITERATION: goog.events.getVendorPrefixedName_('AnimationIteration'),
    -
    -  // CSS transition events. Based on the browser support described at:
    -  // https://developer.mozilla.org/en/css/css_transitions#Browser_compatibility
    -  /** @suppress {missingRequire} */
    -  TRANSITIONEND: goog.events.getVendorPrefixedName_('TransitionEnd'),
    -
    -  // W3C Pointer Events
    -  // http://www.w3.org/TR/pointerevents/
    -  POINTERDOWN: 'pointerdown',
    -  POINTERUP: 'pointerup',
    -  POINTERCANCEL: 'pointercancel',
    -  POINTERMOVE: 'pointermove',
    -  POINTEROVER: 'pointerover',
    -  POINTEROUT: 'pointerout',
    -  POINTERENTER: 'pointerenter',
    -  POINTERLEAVE: 'pointerleave',
    -  GOTPOINTERCAPTURE: 'gotpointercapture',
    -  LOSTPOINTERCAPTURE: 'lostpointercapture',
    -
    -  // IE specific events.
    -  // See http://msdn.microsoft.com/en-us/library/ie/hh772103(v=vs.85).aspx
    -  // Note: these events will be supplanted in IE11.
    -  MSGESTURECHANGE: 'MSGestureChange',
    -  MSGESTUREEND: 'MSGestureEnd',
    -  MSGESTUREHOLD: 'MSGestureHold',
    -  MSGESTURESTART: 'MSGestureStart',
    -  MSGESTURETAP: 'MSGestureTap',
    -  MSGOTPOINTERCAPTURE: 'MSGotPointerCapture',
    -  MSINERTIASTART: 'MSInertiaStart',
    -  MSLOSTPOINTERCAPTURE: 'MSLostPointerCapture',
    -  MSPOINTERCANCEL: 'MSPointerCancel',
    -  MSPOINTERDOWN: 'MSPointerDown',
    -  MSPOINTERENTER: 'MSPointerEnter',
    -  MSPOINTERHOVER: 'MSPointerHover',
    -  MSPOINTERLEAVE: 'MSPointerLeave',
    -  MSPOINTERMOVE: 'MSPointerMove',
    -  MSPOINTEROUT: 'MSPointerOut',
    -  MSPOINTEROVER: 'MSPointerOver',
    -  MSPOINTERUP: 'MSPointerUp',
    -
    -  // Native IMEs/input tools events.
    -  TEXT: 'text',
    -  TEXTINPUT: 'textInput',
    -  COMPOSITIONSTART: 'compositionstart',
    -  COMPOSITIONUPDATE: 'compositionupdate',
    -  COMPOSITIONEND: 'compositionend',
    -
    -  // Webview tag events
    -  // See http://developer.chrome.com/dev/apps/webview_tag.html
    -  EXIT: 'exit',
    -  LOADABORT: 'loadabort',
    -  LOADCOMMIT: 'loadcommit',
    -  LOADREDIRECT: 'loadredirect',
    -  LOADSTART: 'loadstart',
    -  LOADSTOP: 'loadstop',
    -  RESPONSIVE: 'responsive',
    -  SIZECHANGED: 'sizechanged',
    -  UNRESPONSIVE: 'unresponsive',
    -
    -  // HTML5 Page Visibility API.  See details at
    -  // {@code goog.labs.dom.PageVisibilityMonitor}.
    -  VISIBILITYCHANGE: 'visibilitychange',
    -
    -  // LocalStorage event.
    -  STORAGE: 'storage',
    -
    -  // DOM Level 2 mutation events (deprecated).
    -  DOMSUBTREEMODIFIED: 'DOMSubtreeModified',
    -  DOMNODEINSERTED: 'DOMNodeInserted',
    -  DOMNODEREMOVED: 'DOMNodeRemoved',
    -  DOMNODEREMOVEDFROMDOCUMENT: 'DOMNodeRemovedFromDocument',
    -  DOMNODEINSERTEDINTODOCUMENT: 'DOMNodeInsertedIntoDocument',
    -  DOMATTRMODIFIED: 'DOMAttrModified',
    -  DOMCHARACTERDATAMODIFIED: 'DOMCharacterDataModified'
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/events/eventwrapper.js b/src/database/third_party/closure-library/closure/goog/events/eventwrapper.js
    deleted file mode 100644
    index 15817742543..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/eventwrapper.js
    +++ /dev/null
    @@ -1,66 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Definition of the goog.events.EventWrapper interface.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - */
    -
    -goog.provide('goog.events.EventWrapper');
    -
    -
    -
    -/**
    - * Interface for event wrappers.
    - * @interface
    - */
    -goog.events.EventWrapper = function() {
    -};
    -
    -
    -/**
    - * Adds an event listener using the wrapper on a DOM Node or an object that has
    - * implemented {@link goog.events.EventTarget}. A listener can only be added
    - * once to an object.
    - *
    - * @param {goog.events.ListenableType} src The node to listen to events on.
    - * @param {function(?):?|{handleEvent:function(?):?}|null} listener Callback
    - *     method, or an object with a handleEvent function.
    - * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
    - *     false).
    - * @param {Object=} opt_scope Element in whose scope to call the listener.
    - * @param {goog.events.EventHandler=} opt_eventHandler Event handler to add
    - *     listener to.
    - */
    -goog.events.EventWrapper.prototype.listen = function(src, listener, opt_capt,
    -    opt_scope, opt_eventHandler) {
    -};
    -
    -
    -/**
    - * Removes an event listener added using goog.events.EventWrapper.listen.
    - *
    - * @param {goog.events.ListenableType} src The node to remove listener from.
    - * @param {function(?):?|{handleEvent:function(?):?}|null} listener Callback
    - *     method, or an object with a handleEvent function.
    - * @param {boolean=} opt_capt Whether to fire in capture phase (defaults to
    - *     false).
    - * @param {Object=} opt_scope Element in whose scope to call the listener.
    - * @param {goog.events.EventHandler=} opt_eventHandler Event handler to remove
    - *     listener from.
    - */
    -goog.events.EventWrapper.prototype.unlisten = function(src, listener, opt_capt,
    -    opt_scope, opt_eventHandler) {
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/events/filedrophandler.js b/src/database/third_party/closure-library/closure/goog/events/filedrophandler.js
    deleted file mode 100644
    index 5678fe3ab5a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/filedrophandler.js
    +++ /dev/null
    @@ -1,222 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides a files drag and drop event detector. It works on
    - * HTML5 browsers.
    - *
    - * @see ../demos/filedrophandler.html
    - */
    -
    -goog.provide('goog.events.FileDropHandler');
    -goog.provide('goog.events.FileDropHandler.EventType');
    -
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.events.BrowserEvent');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -goog.require('goog.log');
    -goog.require('goog.log.Level');
    -
    -
    -
    -/**
    - * A files drag and drop event detector. Gets an {@code element} as parameter
    - * and fires {@code goog.events.FileDropHandler.EventType.DROP} event when files
    - * are dropped in the {@code element}.
    - *
    - * @param {Element|Document} element The element or document to listen on.
    - * @param {boolean=} opt_preventDropOutside Whether to prevent a drop on the
    - *     area outside the {@code element}. Default false.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - * @final
    - */
    -goog.events.FileDropHandler = function(element, opt_preventDropOutside) {
    -  goog.events.EventTarget.call(this);
    -
    -  /**
    -   * Handler for drag/drop events.
    -   * @type {!goog.events.EventHandler<!goog.events.FileDropHandler>}
    -   * @private
    -   */
    -  this.eventHandler_ = new goog.events.EventHandler(this);
    -
    -  var doc = element;
    -  if (opt_preventDropOutside) {
    -    doc = goog.dom.getOwnerDocument(element);
    -  }
    -
    -  // Add dragenter listener to the owner document of the element.
    -  this.eventHandler_.listen(doc,
    -                            goog.events.EventType.DRAGENTER,
    -                            this.onDocDragEnter_);
    -
    -  // Add dragover listener to the owner document of the element only if the
    -  // document is not the element itself.
    -  if (doc != element) {
    -    this.eventHandler_.listen(doc,
    -                              goog.events.EventType.DRAGOVER,
    -                              this.onDocDragOver_);
    -  }
    -
    -  // Add dragover and drop listeners to the element.
    -  this.eventHandler_.listen(element,
    -                            goog.events.EventType.DRAGOVER,
    -                            this.onElemDragOver_);
    -  this.eventHandler_.listen(element,
    -                            goog.events.EventType.DROP,
    -                            this.onElemDrop_);
    -};
    -goog.inherits(goog.events.FileDropHandler, goog.events.EventTarget);
    -
    -
    -/**
    - * Whether the drag event contains files. It is initialized only in the
    - * dragenter event. It is used in all the drag events to prevent default actions
    - * only if the drag contains files. Preventing default actions is necessary to
    - * go from dragenter to dragover and from dragover to drop. However we do not
    - * always want to prevent default actions, e.g. when the user drags text or
    - * links on a text area we should not prevent the browser default action that
    - * inserts the text in the text area. It is also necessary to stop propagation
    - * when handling drag events on the element to prevent them from propagating
    - * to the document.
    - * @private
    - * @type {boolean}
    - */
    -goog.events.FileDropHandler.prototype.dndContainsFiles_ = false;
    -
    -
    -/**
    - * A logger, used to help us debug the algorithm.
    - * @type {goog.log.Logger}
    - * @private
    - */
    -goog.events.FileDropHandler.prototype.logger_ =
    -    goog.log.getLogger('goog.events.FileDropHandler');
    -
    -
    -/**
    - * The types of events fired by this class.
    - * @enum {string}
    - */
    -goog.events.FileDropHandler.EventType = {
    -  DROP: goog.events.EventType.DROP
    -};
    -
    -
    -/** @override */
    -goog.events.FileDropHandler.prototype.disposeInternal = function() {
    -  goog.events.FileDropHandler.superClass_.disposeInternal.call(this);
    -  this.eventHandler_.dispose();
    -};
    -
    -
    -/**
    - * Dispatches the DROP event.
    - * @param {goog.events.BrowserEvent} e The underlying browser event.
    - * @private
    - */
    -goog.events.FileDropHandler.prototype.dispatch_ = function(e) {
    -  goog.log.fine(this.logger_, 'Firing DROP event...');
    -  var event = new goog.events.BrowserEvent(e.getBrowserEvent());
    -  event.type = goog.events.FileDropHandler.EventType.DROP;
    -  this.dispatchEvent(event);
    -};
    -
    -
    -/**
    - * Handles dragenter on the document.
    - * @param {goog.events.BrowserEvent} e The dragenter event.
    - * @private
    - */
    -goog.events.FileDropHandler.prototype.onDocDragEnter_ = function(e) {
    -  goog.log.log(this.logger_, goog.log.Level.FINER,
    -      '"' + e.target.id + '" (' + e.target + ') dispatched: ' + e.type);
    -  var dt = e.getBrowserEvent().dataTransfer;
    -  // Check whether the drag event contains files.
    -  this.dndContainsFiles_ = !!(dt &&
    -      ((dt.types &&
    -          (goog.array.contains(dt.types, 'Files') ||
    -          goog.array.contains(dt.types, 'public.file-url'))) ||
    -      (dt.files && dt.files.length > 0)));
    -  // If it does
    -  if (this.dndContainsFiles_) {
    -    // Prevent default actions.
    -    e.preventDefault();
    -  }
    -  goog.log.log(this.logger_, goog.log.Level.FINER,
    -      'dndContainsFiles_: ' + this.dndContainsFiles_);
    -};
    -
    -
    -/**
    - * Handles dragging something over the document.
    - * @param {goog.events.BrowserEvent} e The dragover event.
    - * @private
    - */
    -goog.events.FileDropHandler.prototype.onDocDragOver_ = function(e) {
    -  goog.log.log(this.logger_, goog.log.Level.FINEST,
    -      '"' + e.target.id + '" (' + e.target + ') dispatched: ' + e.type);
    -  if (this.dndContainsFiles_) {
    -    // Prevent default actions.
    -    e.preventDefault();
    -    // Disable the drop on the document outside the drop zone.
    -    var dt = e.getBrowserEvent().dataTransfer;
    -    dt.dropEffect = 'none';
    -  }
    -};
    -
    -
    -/**
    - * Handles dragging something over the element (drop zone).
    - * @param {goog.events.BrowserEvent} e The dragover event.
    - * @private
    - */
    -goog.events.FileDropHandler.prototype.onElemDragOver_ = function(e) {
    -  goog.log.log(this.logger_, goog.log.Level.FINEST,
    -      '"' + e.target.id + '" (' + e.target + ') dispatched: ' + e.type);
    -  if (this.dndContainsFiles_) {
    -    // Prevent default actions and stop the event from propagating further to
    -    // the document. Both lines are needed! (See comment above).
    -    e.preventDefault();
    -    e.stopPropagation();
    -    // Allow the drop on the drop zone.
    -    var dt = e.getBrowserEvent().dataTransfer;
    -    dt.effectAllowed = 'all';
    -    dt.dropEffect = 'copy';
    -  }
    -};
    -
    -
    -/**
    - * Handles dropping something onto the element (drop zone).
    - * @param {goog.events.BrowserEvent} e The drop event.
    - * @private
    - */
    -goog.events.FileDropHandler.prototype.onElemDrop_ = function(e) {
    -  goog.log.log(this.logger_, goog.log.Level.FINER,
    -      '"' + e.target.id + '" (' + e.target + ') dispatched: ' + e.type);
    -  // If the drag and drop event contains files.
    -  if (this.dndContainsFiles_) {
    -    // Prevent default actions and stop the event from propagating further to
    -    // the document. Both lines are needed! (See comment above).
    -    e.preventDefault();
    -    e.stopPropagation();
    -    // Dispatch DROP event.
    -    this.dispatch_(e);
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/events/filedrophandler_test.html b/src/database/third_party/closure-library/closure/goog/events/filedrophandler_test.html
    deleted file mode 100644
    index 14b94958842..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/filedrophandler_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.events.FileDropHandler
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.events.FileDropHandlerTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/events/filedrophandler_test.js b/src/database/third_party/closure-library/closure/goog/events/filedrophandler_test.js
    deleted file mode 100644
    index 80015c8d02b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/filedrophandler_test.js
    +++ /dev/null
    @@ -1,250 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.events.FileDropHandlerTest');
    -goog.setTestOnly('goog.events.FileDropHandlerTest');
    -
    -goog.require('goog.events');
    -goog.require('goog.events.BrowserEvent');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.FileDropHandler');
    -goog.require('goog.testing.jsunit');
    -
    -var textarea;
    -var doc;
    -var handler;
    -var dnd;
    -var files;
    -
    -function setUp() {
    -  textarea = new goog.events.EventTarget();
    -  doc = new goog.events.EventTarget();
    -  textarea.ownerDocument = doc;
    -  handler = new goog.events.FileDropHandler(textarea);
    -  dnd = false;
    -  files = null;
    -  goog.events.listen(handler, goog.events.FileDropHandler.EventType.DROP,
    -      function(e) {
    -        dnd = true;
    -        files =
    -            e.getBrowserEvent().dataTransfer.files;
    -      });
    -}
    -
    -function tearDown() {
    -  textarea.dispose();
    -  doc.dispose();
    -  handler.dispose();
    -}
    -
    -function testOneFile() {
    -  var preventDefault = false;
    -  var expectedfiles = [{ fileName: 'file1.jpg' }];
    -  var dt = { types: ['Files'], files: expectedfiles };
    -
    -  // Assert that default actions are prevented on dragenter.
    -  textarea.dispatchEvent(new goog.events.BrowserEvent({
    -    preventDefault: function() { preventDefault = true; },
    -    type: goog.events.EventType.DRAGENTER,
    -    dataTransfer: dt
    -  }));
    -  assertTrue(preventDefault);
    -  preventDefault = false;
    -
    -  // Assert that default actions are prevented on dragover.
    -  textarea.dispatchEvent(new goog.events.BrowserEvent({
    -    preventDefault: function() { preventDefault = true; },
    -    type: goog.events.EventType.DRAGOVER,
    -    dataTransfer: dt
    -  }));
    -  assertTrue(preventDefault);
    -  preventDefault = false;
    -  // Assert that the drop effect is set to 'copy'.
    -  assertEquals('copy', dt.dropEffect);
    -
    -  // Assert that default actions are prevented on drop.
    -  textarea.dispatchEvent(new goog.events.BrowserEvent({
    -    preventDefault: function() { preventDefault = true; },
    -    type: goog.events.EventType.DROP,
    -    dataTransfer: dt
    -  }));
    -  assertTrue(preventDefault);
    -
    -  // Assert that DROP has been fired.
    -  assertTrue(dnd);
    -  assertEquals(1, files.length);
    -  assertEquals(expectedfiles[0].fileName, files[0].fileName);
    -}
    -
    -function testMultipleFiles() {
    -  var preventDefault = false;
    -  var expectedfiles = [{ fileName: 'file1.jpg' }, { fileName: 'file2.jpg' }];
    -  var dt = { types: ['Files', 'text'], files: expectedfiles };
    -
    -  // Assert that default actions are prevented on dragenter.
    -  textarea.dispatchEvent(new goog.events.BrowserEvent({
    -    preventDefault: function() { preventDefault = true; },
    -    type: goog.events.EventType.DRAGENTER,
    -    dataTransfer: dt
    -  }));
    -  assertTrue(preventDefault);
    -  preventDefault = false;
    -
    -  // Assert that default actions are prevented on dragover.
    -  textarea.dispatchEvent(new goog.events.BrowserEvent({
    -    preventDefault: function() { preventDefault = true; },
    -    type: goog.events.EventType.DRAGOVER,
    -    dataTransfer: dt
    -  }));
    -  assertTrue(preventDefault);
    -  preventDefault = false;
    -  // Assert that the drop effect is set to 'copy'.
    -  assertEquals('copy', dt.dropEffect);
    -
    -  // Assert that default actions are prevented on drop.
    -  textarea.dispatchEvent(new goog.events.BrowserEvent({
    -    preventDefault: function() { preventDefault = true; },
    -    type: goog.events.EventType.DROP,
    -    dataTransfer: dt
    -  }));
    -  assertTrue(preventDefault);
    -
    -  // Assert that DROP has been fired.
    -  assertTrue(dnd);
    -  assertEquals(2, files.length);
    -  assertEquals(expectedfiles[0].fileName, files[0].fileName);
    -  assertEquals(expectedfiles[1].fileName, files[1].fileName);
    -}
    -
    -function testNoFiles() {
    -  var preventDefault = false;
    -  var dt = { types: ['text'] };
    -
    -  // Assert that default actions are not prevented on dragenter.
    -  textarea.dispatchEvent(new goog.events.BrowserEvent({
    -    preventDefault: function() { preventDefault = true; },
    -    type: goog.events.EventType.DRAGENTER,
    -    dataTransfer: dt
    -  }));
    -  assertFalse(preventDefault);
    -  preventDefault = false;
    -
    -  // Assert that default actions are not prevented on dragover.
    -  textarea.dispatchEvent(new goog.events.BrowserEvent({
    -    preventDefault: function() { preventDefault = true; },
    -    type: goog.events.EventType.DRAGOVER,
    -    dataTransfer: dt
    -  }));
    -  assertFalse(preventDefault);
    -  preventDefault = false;
    -
    -  // Assert that default actions are not prevented on drop.
    -  textarea.dispatchEvent(new goog.events.BrowserEvent({
    -    preventDefault: function() { preventDefault = true; },
    -    type: goog.events.EventType.DROP,
    -    dataTransfer: dt
    -  }));
    -  assertFalse(preventDefault);
    -
    -  // Assert that DROP has not been fired.
    -  assertFalse(dnd);
    -  assertNull(files);
    -}
    -
    -function testDragEnter() {
    -  var preventDefault = false;
    -
    -  // Assert that default actions are prevented on dragenter.
    -  // In Chrome the dragenter event has an empty file list and the types is
    -  // set to 'Files'.
    -  textarea.dispatchEvent(new goog.events.BrowserEvent({
    -    preventDefault: function() { preventDefault = true; },
    -    type: goog.events.EventType.DRAGENTER,
    -    dataTransfer: { types: ['Files'], files: [] }
    -  }));
    -  assertTrue(preventDefault);
    -  preventDefault = false;
    -
    -  // Assert that default actions are prevented on dragenter.
    -  // In Safari 4 the dragenter event has an empty file list and the types is
    -  // set to 'public.file-url'.
    -  textarea.dispatchEvent(new goog.events.BrowserEvent({
    -    preventDefault: function() { preventDefault = true; },
    -    type: goog.events.EventType.DRAGENTER,
    -    dataTransfer: { types: ['public.file-url'], files: [] }
    -  }));
    -  assertTrue(preventDefault);
    -  preventDefault = false;
    -
    -  // Assert that default actions are not prevented on dragenter
    -  // when the drag contains no files.
    -  textarea.dispatchEvent(new goog.events.BrowserEvent({
    -    preventDefault: function() { preventDefault = true; },
    -    type: goog.events.EventType.DRAGENTER,
    -    dataTransfer: { types: ['text'], files: [] }
    -  }));
    -  assertFalse(preventDefault);
    -}
    -
    -function testPreventDropOutside() {
    -  var preventDefault = false;
    -  var dt = { types: ['Files'], files: [{ fileName: 'file1.jpg' }] };
    -
    -  // Assert that default actions are not prevented on dragenter on the
    -  // document outside the text area.
    -  doc.dispatchEvent(new goog.events.BrowserEvent({
    -    preventDefault: function() { preventDefault = true; },
    -    type: goog.events.EventType.DRAGENTER,
    -    dataTransfer: dt
    -  }));
    -  assertFalse(preventDefault);
    -  preventDefault = false;
    -
    -  // Assert that default actions are not prevented on dragover on the
    -  // document outside the text area.
    -  doc.dispatchEvent(new goog.events.BrowserEvent({
    -    preventDefault: function() { preventDefault = true; },
    -    type: goog.events.EventType.DRAGOVER,
    -    dataTransfer: dt
    -  }));
    -  assertFalse(preventDefault);
    -  preventDefault = false;
    -
    -  handler.dispose();
    -  // Create a new FileDropHandler that prevents drops outside the text area.
    -  handler = new goog.events.FileDropHandler(textarea, true);
    -
    -  // Assert that default actions are now prevented on dragenter on the
    -  // document outside the text area.
    -  doc.dispatchEvent(new goog.events.BrowserEvent({
    -    preventDefault: function() { preventDefault = true; },
    -    type: goog.events.EventType.DRAGENTER,
    -    dataTransfer: dt
    -  }));
    -  assertTrue(preventDefault);
    -  preventDefault = false;
    -
    -  // Assert that default actions are now prevented on dragover on the
    -  // document outside the text area.
    -  doc.dispatchEvent(new goog.events.BrowserEvent({
    -    preventDefault: function() { preventDefault = true; },
    -    type: goog.events.EventType.DRAGOVER,
    -    dataTransfer: dt
    -  }));
    -  assertTrue(preventDefault);
    -  preventDefault = false;
    -  // Assert also that the drop effect is set to 'none'.
    -  assertEquals('none', dt.dropEffect);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/events/focushandler.js b/src/database/third_party/closure-library/closure/goog/events/focushandler.js
    deleted file mode 100644
    index f4e1000b3c7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/focushandler.js
    +++ /dev/null
    @@ -1,107 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview This event handler allows you to catch focusin and focusout
    - * events on  descendants. Unlike the "focus" and "blur" events which do not
    - * propagate consistently, and therefore must be added to the element that is
    - * focused, this allows you to attach one listener to an ancester and you will
    - * be notified when the focus state changes of ony of its descendants.
    - * @author arv@google.com (Erik Arvidsson)
    - * @see ../demos/focushandler.html
    - */
    -
    -goog.provide('goog.events.FocusHandler');
    -goog.provide('goog.events.FocusHandler.EventType');
    -
    -goog.require('goog.events');
    -goog.require('goog.events.BrowserEvent');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * This event handler allows you to catch focus events when descendants gain or
    - * loses focus.
    - * @param {Element|Document} element  The node to listen on.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - * @final
    - */
    -goog.events.FocusHandler = function(element) {
    -  goog.events.EventTarget.call(this);
    -
    -  /**
    -   * This is the element that we will listen to the real focus events on.
    -   * @type {Element|Document}
    -   * @private
    -   */
    -  this.element_ = element;
    -
    -  // In IE we use focusin/focusout and in other browsers we use a capturing
    -  // listner for focus/blur
    -  var typeIn = goog.userAgent.IE ? 'focusin' : 'focus';
    -  var typeOut = goog.userAgent.IE ? 'focusout' : 'blur';
    -
    -  /**
    -   * Store the listen key so it easier to unlisten in dispose.
    -   * @private
    -   * @type {goog.events.Key}
    -   */
    -  this.listenKeyIn_ =
    -      goog.events.listen(this.element_, typeIn, this, !goog.userAgent.IE);
    -
    -  /**
    -   * Store the listen key so it easier to unlisten in dispose.
    -   * @private
    -   * @type {goog.events.Key}
    -   */
    -  this.listenKeyOut_ =
    -      goog.events.listen(this.element_, typeOut, this, !goog.userAgent.IE);
    -};
    -goog.inherits(goog.events.FocusHandler, goog.events.EventTarget);
    -
    -
    -/**
    - * Enum type for the events fired by the focus handler
    - * @enum {string}
    - */
    -goog.events.FocusHandler.EventType = {
    -  FOCUSIN: 'focusin',
    -  FOCUSOUT: 'focusout'
    -};
    -
    -
    -/**
    - * This handles the underlying events and dispatches a new event.
    - * @param {goog.events.BrowserEvent} e  The underlying browser event.
    - */
    -goog.events.FocusHandler.prototype.handleEvent = function(e) {
    -  var be = e.getBrowserEvent();
    -  var event = new goog.events.BrowserEvent(be);
    -  event.type = e.type == 'focusin' || e.type == 'focus' ?
    -      goog.events.FocusHandler.EventType.FOCUSIN :
    -      goog.events.FocusHandler.EventType.FOCUSOUT;
    -  this.dispatchEvent(event);
    -};
    -
    -
    -/** @override */
    -goog.events.FocusHandler.prototype.disposeInternal = function() {
    -  goog.events.FocusHandler.superClass_.disposeInternal.call(this);
    -  goog.events.unlistenByKey(this.listenKeyIn_);
    -  goog.events.unlistenByKey(this.listenKeyOut_);
    -  delete this.element_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/events/imehandler.js b/src/database/third_party/closure-library/closure/goog/events/imehandler.js
    deleted file mode 100644
    index 661f91f7cb4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/imehandler.js
    +++ /dev/null
    @@ -1,369 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Input Method Editors (IMEs) are OS-level widgets that make
    - * it easier to type non-ascii characters on ascii keyboards (in particular,
    - * characters that require more than one keystroke).
    - *
    - * When the user wants to type such a character, a modal menu pops up and
    - * suggests possible "next" characters in the IME character sequence. After
    - * typing N characters, the user hits "enter" to commit the IME to the field.
    - * N differs from language to language.
    - *
    - * This class offers high-level events for how the user is interacting with the
    - * IME in editable regions.
    - *
    - * Known Issues:
    - *
    - * Firefox always fires an extra pair of compositionstart/compositionend events.
    - * We do not normalize for this.
    - *
    - * Opera does not fire any IME events.
    - *
    - * Spurious UPDATE events are common on all browsers.
    - *
    - * We currently do a bad job detecting when the IME closes on IE, and
    - * make a "best effort" guess on when we know it's closed.
    - *
    - * @author nicksantos@google.com (Nick Santos) (Ported to Closure)
    - */
    -
    -goog.provide('goog.events.ImeHandler');
    -goog.provide('goog.events.ImeHandler.Event');
    -goog.provide('goog.events.ImeHandler.EventType');
    -
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Dispatches high-level events for IMEs.
    - * @param {Element} el The element to listen on.
    - * @extends {goog.events.EventTarget}
    - * @constructor
    - * @final
    - */
    -goog.events.ImeHandler = function(el) {
    -  goog.events.ImeHandler.base(this, 'constructor');
    -
    -  /**
    -   * The element to listen on.
    -   * @type {Element}
    -   * @private
    -   */
    -  this.el_ = el;
    -
    -  /**
    -   * Tracks the keyup event only, because it has a different life-cycle from
    -   * other events.
    -   * @type {goog.events.EventHandler<!goog.events.ImeHandler>}
    -   * @private
    -   */
    -  this.keyUpHandler_ = new goog.events.EventHandler(this);
    -
    -  /**
    -   * Tracks all the browser events.
    -   * @type {goog.events.EventHandler<!goog.events.ImeHandler>}
    -   * @private
    -   */
    -  this.handler_ = new goog.events.EventHandler(this);
    -
    -  if (goog.events.ImeHandler.USES_COMPOSITION_EVENTS) {
    -    this.handler_.
    -        listen(el, goog.events.EventType.COMPOSITIONSTART,
    -            this.handleCompositionStart_).
    -        listen(el, goog.events.EventType.COMPOSITIONEND,
    -            this.handleCompositionEnd_).
    -        listen(el, goog.events.EventType.COMPOSITIONUPDATE,
    -            this.handleTextModifyingInput_);
    -  }
    -
    -  this.handler_.
    -      listen(el, goog.events.EventType.TEXTINPUT, this.handleTextInput_).
    -      listen(el, goog.events.EventType.TEXT, this.handleTextModifyingInput_).
    -      listen(el, goog.events.EventType.KEYDOWN, this.handleKeyDown_);
    -};
    -goog.inherits(goog.events.ImeHandler, goog.events.EventTarget);
    -
    -
    -/**
    - * Event types fired by ImeHandler. These events do not make any guarantees
    - * about whether they were fired before or after the event in question.
    - * @enum {string}
    - */
    -goog.events.ImeHandler.EventType = {
    -  // After the IME opens.
    -  START: 'startIme',
    -
    -  // An update to the state of the IME. An 'update' does not necessarily mean
    -  // that the text contents of the field were modified in any way.
    -  UPDATE: 'updateIme',
    -
    -  // After the IME closes.
    -  END: 'endIme'
    -};
    -
    -
    -
    -/**
    - * An event fired by ImeHandler.
    - * @param {goog.events.ImeHandler.EventType} type The type.
    - * @param {goog.events.BrowserEvent} reason The trigger for this event.
    - * @constructor
    - * @extends {goog.events.Event}
    - * @final
    - */
    -goog.events.ImeHandler.Event = function(type, reason) {
    -  goog.events.ImeHandler.Event.base(this, 'constructor', type);
    -
    -  /**
    -   * The event that triggered this.
    -   * @type {goog.events.BrowserEvent}
    -   */
    -  this.reason = reason;
    -};
    -goog.inherits(goog.events.ImeHandler.Event, goog.events.Event);
    -
    -
    -/**
    - * Whether to use the composition events.
    - * @type {boolean}
    - */
    -goog.events.ImeHandler.USES_COMPOSITION_EVENTS =
    -    goog.userAgent.GECKO ||
    -    (goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher(532));
    -
    -
    -/**
    - * Stores whether IME mode is active.
    - * @type {boolean}
    - * @private
    - */
    -goog.events.ImeHandler.prototype.imeMode_ = false;
    -
    -
    -/**
    - * The keyCode value of the last keyDown event. This value is used for
    - * identiying whether or not a textInput event is sent by an IME.
    - * @type {number}
    - * @private
    - */
    -goog.events.ImeHandler.prototype.lastKeyCode_ = 0;
    -
    -
    -/**
    - * @return {boolean} Whether an IME is active.
    - */
    -goog.events.ImeHandler.prototype.isImeMode = function() {
    -  return this.imeMode_;
    -};
    -
    -
    -/**
    - * Handles the compositionstart event.
    - * @param {goog.events.BrowserEvent} e The event.
    - * @private
    - */
    -goog.events.ImeHandler.prototype.handleCompositionStart_ =
    -    function(e) {
    -  this.handleImeActivate_(e);
    -};
    -
    -
    -/**
    - * Handles the compositionend event.
    - * @param {goog.events.BrowserEvent} e The event.
    - * @private
    - */
    -goog.events.ImeHandler.prototype.handleCompositionEnd_ = function(e) {
    -  this.handleImeDeactivate_(e);
    -};
    -
    -
    -/**
    - * Handles the compositionupdate and text events.
    - * @param {goog.events.BrowserEvent} e The event.
    - * @private
    - */
    -goog.events.ImeHandler.prototype.handleTextModifyingInput_ =
    -    function(e) {
    -  if (this.isImeMode()) {
    -    this.processImeComposition_(e);
    -  }
    -};
    -
    -
    -/**
    - * Handles IME activation.
    - * @param {goog.events.BrowserEvent} e The event.
    - * @private
    - */
    -goog.events.ImeHandler.prototype.handleImeActivate_ = function(e) {
    -  if (this.imeMode_) {
    -    return;
    -  }
    -
    -  // Listens for keyup events to handle unexpected IME keydown events on older
    -  // versions of webkit.
    -  //
    -  // In those versions, we currently use textInput events deactivate IME
    -  // (see handleTextInput_() for the reason). However,
    -  // Safari fires a keydown event (as a result of pressing keys to commit IME
    -  // text) with keyCode == WIN_IME after textInput event. This activates IME
    -  // mode again unnecessarily. To prevent this problem, listens keyup events
    -  // which can use to determine whether IME text has been committed.
    -  if (goog.userAgent.WEBKIT &&
    -      !goog.events.ImeHandler.USES_COMPOSITION_EVENTS) {
    -    this.keyUpHandler_.listen(this.el_,
    -        goog.events.EventType.KEYUP, this.handleKeyUpSafari4_);
    -  }
    -
    -  this.imeMode_ = true;
    -  this.dispatchEvent(
    -      new goog.events.ImeHandler.Event(
    -          goog.events.ImeHandler.EventType.START, e));
    -};
    -
    -
    -/**
    - * Handles the IME compose changes.
    - * @param {goog.events.BrowserEvent} e The event.
    - * @private
    - */
    -goog.events.ImeHandler.prototype.processImeComposition_ = function(e) {
    -  this.dispatchEvent(
    -      new goog.events.ImeHandler.Event(
    -          goog.events.ImeHandler.EventType.UPDATE, e));
    -};
    -
    -
    -/**
    - * Handles IME deactivation.
    - * @param {goog.events.BrowserEvent} e The event.
    - * @private
    - */
    -goog.events.ImeHandler.prototype.handleImeDeactivate_ = function(e) {
    -  this.imeMode_ = false;
    -  this.keyUpHandler_.removeAll();
    -  this.dispatchEvent(
    -      new goog.events.ImeHandler.Event(
    -          goog.events.ImeHandler.EventType.END, e));
    -};
    -
    -
    -/**
    - * Handles a key down event.
    - * @param {!goog.events.BrowserEvent} e The event.
    - * @private
    - */
    -goog.events.ImeHandler.prototype.handleKeyDown_ = function(e) {
    -  // Firefox and Chrome have a separate event for IME composition ('text'
    -  // and 'compositionupdate', respectively), other browsers do not.
    -  if (!goog.events.ImeHandler.USES_COMPOSITION_EVENTS) {
    -    var imeMode = this.isImeMode();
    -    // If we're in IE and we detect an IME input on keyDown then activate
    -    // the IME, otherwise if the imeMode was previously active, deactivate.
    -    if (!imeMode && e.keyCode == goog.events.KeyCodes.WIN_IME) {
    -      this.handleImeActivate_(e);
    -    } else if (imeMode && e.keyCode != goog.events.KeyCodes.WIN_IME) {
    -      if (goog.events.ImeHandler.isImeDeactivateKeyEvent_(e)) {
    -        this.handleImeDeactivate_(e);
    -      }
    -    } else if (imeMode) {
    -      this.processImeComposition_(e);
    -    }
    -  }
    -
    -  // Safari on Mac doesn't send IME events in the right order so that we must
    -  // ignore some modifier key events to insert IME text correctly.
    -  if (goog.events.ImeHandler.isImeDeactivateKeyEvent_(e)) {
    -    this.lastKeyCode_ = e.keyCode;
    -  }
    -};
    -
    -
    -/**
    - * Handles a textInput event.
    - * @param {!goog.events.BrowserEvent} e The event.
    - * @private
    - */
    -goog.events.ImeHandler.prototype.handleTextInput_ = function(e) {
    -  // Some WebKit-based browsers including Safari 4 don't send composition
    -  // events. So, we turn down IME mode when it's still there.
    -  if (!goog.events.ImeHandler.USES_COMPOSITION_EVENTS &&
    -      goog.userAgent.WEBKIT &&
    -      this.lastKeyCode_ == goog.events.KeyCodes.WIN_IME &&
    -      this.isImeMode()) {
    -    this.handleImeDeactivate_(e);
    -  }
    -};
    -
    -
    -/**
    - * Handles the key up event for any IME activity. This handler is just used to
    - * prevent activating IME unnecessary in Safari at this time.
    - * @param {!goog.events.BrowserEvent} e The event.
    - * @private
    - */
    -goog.events.ImeHandler.prototype.handleKeyUpSafari4_ = function(e) {
    -  if (this.isImeMode()) {
    -    switch (e.keyCode) {
    -      // These keyup events indicates that IME text has been committed or
    -      // cancelled. We should turn off IME mode when these keyup events
    -      // received.
    -      case goog.events.KeyCodes.ENTER:
    -      case goog.events.KeyCodes.TAB:
    -      case goog.events.KeyCodes.ESC:
    -        this.handleImeDeactivate_(e);
    -        break;
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Returns whether the given event should be treated as an IME
    - * deactivation trigger.
    - * @param {!goog.events.Event} e The event.
    - * @return {boolean} Whether the given event is an IME deactivate trigger.
    - * @private
    - */
    -goog.events.ImeHandler.isImeDeactivateKeyEvent_ = function(e) {
    -  // Which key events involve IME deactivation depends on the user's
    -  // environment (i.e. browsers, platforms, and IMEs). Usually Shift key
    -  // and Ctrl key does not involve IME deactivation, so we currently assume
    -  // that these keys are not IME deactivation trigger.
    -  switch (e.keyCode) {
    -    case goog.events.KeyCodes.SHIFT:
    -    case goog.events.KeyCodes.CTRL:
    -      return false;
    -    default:
    -      return true;
    -  }
    -};
    -
    -
    -/** @override */
    -goog.events.ImeHandler.prototype.disposeInternal = function() {
    -  this.handler_.dispose();
    -  this.keyUpHandler_.dispose();
    -  this.el_ = null;
    -  goog.events.ImeHandler.base(this, 'disposeInternal');
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/events/imehandler_test.html b/src/database/third_party/closure-library/closure/goog/events/imehandler_test.html
    deleted file mode 100644
    index b7985750740..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/imehandler_test.html
    +++ /dev/null
    @@ -1,33 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    -Author: nicksantos@google.com (Nick Santos) (Ported to Closure)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   JsUnit tests for goog.events.ImeHandler
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.events.ImeHandlerTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="sandbox">
    -  </div>
    -  <div>
    -   <b>
    -    Last 10 events:
    -   </b>
    -   <div id="logger" style="padding: 0.5em;">
    -   </div>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/events/imehandler_test.js b/src/database/third_party/closure-library/closure/goog/events/imehandler_test.js
    deleted file mode 100644
    index 4e770c8b1c3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/imehandler_test.js
    +++ /dev/null
    @@ -1,266 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.events.ImeHandlerTest');
    -goog.setTestOnly('goog.events.ImeHandlerTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.ImeHandler');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.object');
    -goog.require('goog.string');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.events.Event');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -var sandbox;
    -var imeHandler;
    -var eventsFired;
    -var stubs = new goog.testing.PropertyReplacer();
    -var eventTypes = goog.events.ImeHandler.EventType;
    -
    -function setUp() {
    -  sandbox = goog.dom.getElement('sandbox');
    -}
    -
    -function initImeHandler() {
    -  goog.events.ImeHandler.USES_COMPOSITION_EVENTS =
    -      goog.userAgent.GECKO ||
    -      (goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher(532));
    -  imeHandler = new goog.events.ImeHandler(sandbox);
    -  eventsFired = [];
    -  goog.events.listen(
    -      imeHandler,
    -      goog.object.getValues(goog.events.ImeHandler.EventType),
    -      function(e) {
    -        eventsFired.push(e.type);
    -      });
    -}
    -
    -function tearDown() {
    -  imeHandler.dispose();
    -  imeHandler = null;
    -
    -  stubs.reset();
    -}
    -
    -function tearDownPage() {
    -  // Set up a test bed.
    -  sandbox.innerHTML = '<div contentEditable="true">hello world</div>';
    -  initImeHandler();
    -
    -  function unshiftEvent(e) {
    -    last10Events.unshift(e.type + ':' + e.keyCode + ':' +
    -        goog.string.htmlEscape(goog.dom.getTextContent(sandbox)));
    -    last10Events.length = Math.min(last10Events.length, 10);
    -    goog.dom.getElement('logger').innerHTML = last10Events.join('<br>');
    -  }
    -
    -  var last10Events = [];
    -  goog.events.listen(
    -      imeHandler,
    -      goog.object.getValues(goog.events.ImeHandler.EventType),
    -      unshiftEvent);
    -  goog.events.listen(
    -      sandbox,
    -      ['keydown', 'textInput'],
    -      unshiftEvent);
    -}
    -
    -function assertEventsFired(var_args) {
    -  assertArrayEquals(
    -      goog.array.clone(arguments), eventsFired);
    -}
    -
    -function fireInputEvent(type) {
    -  return goog.testing.events.fireBrowserEvent(
    -      new goog.testing.events.Event(type, sandbox));
    -}
    -
    -function fireImeKeySequence() {
    -  return fireKeySequence(goog.events.KeyCodes.WIN_IME);
    -}
    -
    -function fireKeySequence(keyCode) {
    -  return (
    -      goog.testing.events.fireBrowserEvent(
    -          new goog.testing.events.Event('textInput', sandbox)) &
    -      goog.testing.events.fireKeySequence(
    -          sandbox, keyCode));
    -}
    -
    -function testHandleKeyDown_GeckoCompositionEvents() {
    -  // This test verifies that our IME functions can dispatch IME events to
    -  // InputHandler in the expected order on Gecko.
    -
    -  // Set the userAgent used for this test to Firefox.
    -  setUserAgent('GECKO');
    -  stubs.set(goog.userAgent, 'MAC', false);
    -  initImeHandler();
    -
    -  fireInputEvent('compositionstart');
    -  assertImeMode();
    -
    -  fireInputEvent('compositionupdate');
    -  fireInputEvent('compositionupdate');
    -
    -  fireInputEvent('compositionend');
    -
    -  assertEventsFired(
    -      eventTypes.START, eventTypes.UPDATE, eventTypes.UPDATE, eventTypes.END);
    -  assertNotImeMode();
    -}
    -
    -
    -/**
    - * Verifies that our IME functions can dispatch IME events to the input handler
    - * in the expected order on Chrome. jsUnitFarm does not have Linux Chrome or
    - * Mac Chrome. So, we manually change the platform and run this test three
    - * times.
    - */
    -function testChromeCompositionEventsLinux() {
    -  runChromeCompositionEvents('LINUX');
    -}
    -
    -function testChromeCompositionEventsMac() {
    -  runChromeCompositionEvents('MAC');
    -}
    -
    -function testChromeCompositionEventsWindows() {
    -  runChromeCompositionEvents('WINDOWS');
    -}
    -
    -function runChromeCompositionEvents(platform) {
    -  setUserAgent('WEBKIT');
    -  setVersion(532);
    -  stubs.set(goog.userAgent, platform, true);
    -  initImeHandler();
    -
    -  fireImeKeySequence();
    -
    -  fireInputEvent('compositionstart');
    -  assertImeMode();
    -
    -  fireInputEvent('compositionupdate');
    -  fireInputEvent('compositionupdate');
    -
    -  fireInputEvent('compositionend');
    -  assertEventsFired(
    -      eventTypes.START, eventTypes.UPDATE, eventTypes.UPDATE, eventTypes.END);
    -  assertNotImeMode();
    -}
    -
    -
    -/**
    - * Ensures that the IME mode turn on/off correctly.
    - */
    -function testHandlerKeyDownForIme_imeOnOff() {
    -  setUserAgent('IE');
    -  initImeHandler();
    -
    -  // Send a WIN_IME keyDown event and see whether IME mode turns on.
    -  fireImeKeySequence();
    -  assertImeMode();
    -
    -  // Send keyDown events which should not turn off IME mode and see whether
    -  // IME mode holds on.
    -  fireKeySequence(goog.events.KeyCodes.SHIFT);
    -  assertImeMode();
    -
    -  fireKeySequence(goog.events.KeyCodes.CTRL);
    -  assertImeMode();
    -
    -  // Send a keyDown event with keyCode = ENTER and see whether IME mode
    -  // turns off.
    -  fireKeySequence(goog.events.KeyCodes.ENTER);
    -  assertNotImeMode();
    -
    -  assertEventsFired(
    -      eventTypes.START, eventTypes.END);
    -}
    -
    -
    -/**
    - * Ensures that IME mode turns off when keyup events which are involved
    - * in commiting IME text occurred in Safari.
    - */
    -function testHandleKeyUpForSafari() {
    -  setUserAgent('WEBKIT');
    -  setVersion(531);
    -  initImeHandler();
    -
    -  fireImeKeySequence();
    -  assertImeMode();
    -
    -  fireKeySequence(goog.events.KeyCodes.ENTER);
    -  assertNotImeMode();
    -}
    -
    -
    -/**
    - * SCIM on Linux will fire WIN_IME keycodes for random characters.
    - * Fortunately, all Linux-based browsers use composition events.
    - * This test just verifies that we ignore the WIN_IME keycodes.
    - */
    -function testScimFiresWinImeKeycodesGeckoLinux() {
    -  setUserAgent('GECKO');
    -  assertScimInputIgnored();
    -}
    -
    -function testScimFiresWinImeKeycodesChromeLinux() {
    -  setUserAgent('WEBKIT');
    -  setVersion(532);
    -  assertScimInputIgnored();
    -}
    -
    -function assertScimInputIgnored() {
    -  initImeHandler();
    -
    -  fireImeKeySequence();
    -  assertNotImeMode();
    -
    -  fireInputEvent('compositionstart');
    -  assertImeMode();
    -
    -  fireImeKeySequence();
    -  assertImeMode();
    -
    -  fireInputEvent('compositionend');
    -  assertNotImeMode();
    -}
    -
    -var userAgents = ['IE', 'GECKO', 'WEBKIT'];
    -
    -function setUserAgent(userAgent) {
    -  for (var i = 0; i < userAgents.length; i++) {
    -    stubs.set(goog.userAgent, userAgents[i], userAgents[i] == userAgent);
    -  }
    -}
    -
    -function setVersion(version) {
    -  goog.userAgent.VERSION = version;
    -  goog.userAgent.isVersionOrHigherCache_ = {};
    -}
    -
    -function assertImeMode() {
    -  assertTrue('Should be in IME mode.', imeHandler.isImeMode());
    -}
    -
    -function assertNotImeMode() {
    -  assertFalse('Should not be in IME mode.', imeHandler.isImeMode());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/events/inputhandler.js b/src/database/third_party/closure-library/closure/goog/events/inputhandler.js
    deleted file mode 100644
    index 2c82c028447..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/inputhandler.js
    +++ /dev/null
    @@ -1,220 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview An object that encapsulates text changed events for textareas
    - * and input element of type text and password. The event occurs after the value
    - * has been changed. The event does not occur if value was changed
    - * programmatically.<br>
    - * <br>
    - * Note: this does not guarantee the correctness of {@code keyCode} or
    - * {@code charCode}, or attempt to unify them across browsers. See
    - * {@code goog.events.KeyHandler} for that functionality<br>
    - * <br>
    - * Known issues:
    - * <ul>
    - * <li>Does not trigger for drop events on Opera due to browser bug.
    - * <li>IE doesn't have native support for input event. WebKit before version 531
    - *     doesn't have support for textareas. For those browsers an emulation mode
    - *     based on key, clipboard and drop events is used. Thus this event won't
    - *     trigger in emulation mode if text was modified by context menu commands
    - *     such as 'Undo' and 'Delete'.
    - * </ul>
    - * @author arv@google.com (Erik Arvidsson)
    - * @see ../demos/inputhandler.html
    - */
    -
    -goog.provide('goog.events.InputHandler');
    -goog.provide('goog.events.InputHandler.EventType');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.dom');
    -goog.require('goog.events.BrowserEvent');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * This event handler will dispatch events when the user types into a text
    - * input, password input or a textarea
    - * @param {Element} element  The element that you want to listen for input
    - *     events on.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - */
    -goog.events.InputHandler = function(element) {
    -  goog.events.InputHandler.base(this, 'constructor');
    -
    -  /**
    -   * Id of a timer used to postpone firing input event in emulation mode.
    -   * @type {?number}
    -   * @private
    -   */
    -  this.timer_ = null;
    -
    -  /**
    -   * The element that you want to listen for input events on.
    -   * @type {Element}
    -   * @private
    -   */
    -  this.element_ = element;
    -
    -  // Determine whether input event should be emulated.
    -  // IE8 doesn't support input events. We could use property change events but
    -  // they are broken in many ways:
    -  // - Fire even if value was changed programmatically.
    -  // - Aren't always delivered. For example, if you change value or even width
    -  //   of input programmatically, next value change made by user won't fire an
    -  //   event.
    -  // IE9 supports input events when characters are inserted, but not deleted.
    -  // WebKit before version 531 did not support input events for textareas.
    -  var emulateInputEvents = goog.userAgent.IE ||
    -      (goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher('531') &&
    -          element.tagName == 'TEXTAREA');
    -
    -  /**
    -   * @type {goog.events.EventHandler<!goog.events.InputHandler>}
    -   * @private
    -   */
    -  this.eventHandler_ = new goog.events.EventHandler(this);
    -
    -  // Even if input event emulation is enabled, still listen for input events
    -  // since they may be partially supported by the browser (such as IE9).
    -  // If the input event does fire, we will be able to dispatch synchronously.
    -  // (InputHandler events being asynchronous for IE is a common issue for
    -  // cases like auto-grow textareas where they result in a quick flash of
    -  // scrollbars between the textarea content growing and it being resized to
    -  // fit.)
    -  this.eventHandler_.listen(
    -      this.element_,
    -      emulateInputEvents ?
    -          ['keydown', 'paste', 'cut', 'drop', 'input'] :
    -          'input',
    -      this);
    -};
    -goog.inherits(goog.events.InputHandler, goog.events.EventTarget);
    -
    -
    -/**
    - * Enum type for the events fired by the input handler
    - * @enum {string}
    - */
    -goog.events.InputHandler.EventType = {
    -  INPUT: 'input'
    -};
    -
    -
    -/**
    - * This handles the underlying events and dispatches a new event as needed.
    - * @param {goog.events.BrowserEvent} e The underlying browser event.
    - */
    -goog.events.InputHandler.prototype.handleEvent = function(e) {
    -  if (e.type == 'input') {
    -    // http://stackoverflow.com/questions/18389732/changing-placeholder-triggers-input-event-in-ie-10
    -    // IE 10+ fires an input event when there are inputs with placeholders.
    -    // It fires the event with keycode 0, so if we detect it we don't
    -    // propagate the input event.
    -    if (goog.userAgent.IE && goog.userAgent.isVersionOrHigher(10) &&
    -        e.keyCode == 0 && e.charCode == 0) {
    -      return;
    -    }
    -    // This event happens after all the other events we listen to, so cancel
    -    // an asynchronous event dispatch if we have it queued up.  Otherwise, we
    -    // will end up firing an extra event.
    -    this.cancelTimerIfSet_();
    -
    -    // Unlike other browsers, Opera fires an extra input event when an element
    -    // is blurred after the user has input into it. Since Opera doesn't fire
    -    // input event on drop, it's enough to check whether element still has focus
    -    // to suppress bogus notification.
    -    if (!goog.userAgent.OPERA || this.element_ ==
    -        goog.dom.getOwnerDocument(this.element_).activeElement) {
    -      this.dispatchEvent(this.createInputEvent_(e));
    -    }
    -  } else {
    -    // Filter out key events that don't modify text.
    -    if (e.type == 'keydown' &&
    -        !goog.events.KeyCodes.isTextModifyingKeyEvent(e)) {
    -      return;
    -    }
    -
    -    // It is still possible that pressed key won't modify the value of an
    -    // element. Storing old value will help us to detect modification but is
    -    // also a little bit dangerous. If value is changed programmatically in
    -    // another key down handler, we will detect it as user-initiated change.
    -    var valueBeforeKey = e.type == 'keydown' ? this.element_.value : null;
    -
    -    // In IE on XP, IME the element's value has already changed when we get
    -    // keydown events when the user is using an IME. In this case, we can't
    -    // check the current value normally, so we assume that it's a modifying key
    -    // event. This means that ENTER when used to commit will fire a spurious
    -    // input event, but it's better to have a false positive than let some input
    -    // slip through the cracks.
    -    if (goog.userAgent.IE && e.keyCode == goog.events.KeyCodes.WIN_IME) {
    -      valueBeforeKey = null;
    -    }
    -
    -    // Create an input event now, because when we fire it on timer, the
    -    // underlying event will already be disposed.
    -    var inputEvent = this.createInputEvent_(e);
    -
    -    // Since key down, paste, cut and drop events are fired before actual value
    -    // of the element has changed, we need to postpone dispatching input event
    -    // until value is updated.
    -    this.cancelTimerIfSet_();
    -    this.timer_ = goog.Timer.callOnce(function() {
    -      this.timer_ = null;
    -      if (this.element_.value != valueBeforeKey) {
    -        this.dispatchEvent(inputEvent);
    -      }
    -    }, 0, this);
    -  }
    -};
    -
    -
    -/**
    - * Cancels timer if it is set, does nothing otherwise.
    - * @private
    - */
    -goog.events.InputHandler.prototype.cancelTimerIfSet_ = function() {
    -  if (this.timer_ != null) {
    -    goog.Timer.clear(this.timer_);
    -    this.timer_ = null;
    -  }
    -};
    -
    -
    -/**
    - * Creates an input event from the browser event.
    - * @param {goog.events.BrowserEvent} be A browser event.
    - * @return {!goog.events.BrowserEvent} An input event.
    - * @private
    - */
    -goog.events.InputHandler.prototype.createInputEvent_ = function(be) {
    -  var e = new goog.events.BrowserEvent(be.getBrowserEvent());
    -  e.type = goog.events.InputHandler.EventType.INPUT;
    -  return e;
    -};
    -
    -
    -/** @override */
    -goog.events.InputHandler.prototype.disposeInternal = function() {
    -  goog.events.InputHandler.base(this, 'disposeInternal');
    -  this.eventHandler_.dispose();
    -  this.cancelTimerIfSet_();
    -  delete this.element_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/events/inputhandler_test.html b/src/database/third_party/closure-library/closure/goog/events/inputhandler_test.html
    deleted file mode 100644
    index a03bcf9eb53..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/inputhandler_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <title>
    -   Input Handler Test
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.events.InputHandlerTest');
    -  </script>
    - </head>
    - <body>
    -  <input type="text" placeholder="Foo" id="input-w-placeholder" />
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/events/inputhandler_test.js b/src/database/third_party/closure-library/closure/goog/events/inputhandler_test.js
    deleted file mode 100644
    index 067d407e2a2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/inputhandler_test.js
    +++ /dev/null
    @@ -1,95 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.events.InputHandlerTest');
    -goog.setTestOnly('goog.events.InputHandlerTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.InputHandler');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.events.Event');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -goog.require('goog.userAgent');
    -
    -var inputHandler;
    -var eventHandler;
    -
    -function setUp() {
    -  eventHandler = new goog.events.EventHandler();
    -}
    -
    -function tearDown() {
    -  goog.dispose(inputHandler);
    -  goog.dispose(eventHandler);
    -}
    -
    -function testInputWithPlaceholder() {
    -  var input = goog.dom.getElement('input-w-placeholder');
    -  inputHandler = new goog.events.InputHandler(input);
    -  var callback = listenToInput(inputHandler);
    -  fireFakeInputEvent(input);
    -  assertEquals(0, callback.getCallCount());
    -}
    -
    -function testInputWithPlaceholder_withValue() {
    -  var input = goog.dom.getElement('input-w-placeholder');
    -  inputHandler = new goog.events.InputHandler(input);
    -  var callback = listenToInput(inputHandler);
    -  input.value = 'foo';
    -  fireFakeInputEvent(input);
    -  assertEquals(0, callback.getCallCount());
    -}
    -
    -function testInputWithPlaceholder_someKeys() {
    -  var input = goog.dom.getElement('input-w-placeholder');
    -  inputHandler = new goog.events.InputHandler(input);
    -  var callback = listenToInput(inputHandler);
    -  input.focus();
    -  input.value = 'foo';
    -
    -  fireInputEvent(input, goog.events.KeyCodes.M);
    -  assertEquals(1, callback.getCallCount());
    -}
    -
    -function listenToInput(inputHandler) {
    -  var callback = goog.testing.recordFunction();
    -  eventHandler.listen(
    -      inputHandler,
    -      goog.events.InputHandler.EventType.INPUT,
    -      callback);
    -  return callback;
    -}
    -
    -function fireFakeInputEvent(input) {
    -  // Simulate the input event that IE fires on focus when a placeholder
    -  // is present.
    -  input.focus();
    -  if (goog.userAgent.IE && goog.userAgent.isVersionOrHigher(10)) {
    -    // IE fires an input event with keycode 0
    -    fireInputEvent(input, 0);
    -  }
    -}
    -
    -function fireInputEvent(input, keyCode) {
    -  var inputEvent = new goog.testing.events.Event(
    -      goog.events.EventType.INPUT,
    -      input);
    -  inputEvent.keyCode = keyCode;
    -  inputEvent.charCode = keyCode;
    -  goog.testing.events.fireBrowserEvent(inputEvent);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/events/keycodes.js b/src/database/third_party/closure-library/closure/goog/events/keycodes.js
    deleted file mode 100644
    index ec269ae23d3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/keycodes.js
    +++ /dev/null
    @@ -1,420 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Constant declarations for common key codes.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - * @see ../demos/keyhandler.html
    - */
    -
    -goog.provide('goog.events.KeyCodes');
    -
    -goog.require('goog.userAgent');
    -
    -
    -/**
    - * Key codes for common characters.
    - *
    - * This list is not localized and therefore some of the key codes are not
    - * correct for non US keyboard layouts. See comments below.
    - *
    - * @enum {number}
    - */
    -goog.events.KeyCodes = {
    -  WIN_KEY_FF_LINUX: 0,
    -  MAC_ENTER: 3,
    -  BACKSPACE: 8,
    -  TAB: 9,
    -  NUM_CENTER: 12,  // NUMLOCK on FF/Safari Mac
    -  ENTER: 13,
    -  SHIFT: 16,
    -  CTRL: 17,
    -  ALT: 18,
    -  PAUSE: 19,
    -  CAPS_LOCK: 20,
    -  ESC: 27,
    -  SPACE: 32,
    -  PAGE_UP: 33,     // also NUM_NORTH_EAST
    -  PAGE_DOWN: 34,   // also NUM_SOUTH_EAST
    -  END: 35,         // also NUM_SOUTH_WEST
    -  HOME: 36,        // also NUM_NORTH_WEST
    -  LEFT: 37,        // also NUM_WEST
    -  UP: 38,          // also NUM_NORTH
    -  RIGHT: 39,       // also NUM_EAST
    -  DOWN: 40,        // also NUM_SOUTH
    -  PRINT_SCREEN: 44,
    -  INSERT: 45,      // also NUM_INSERT
    -  DELETE: 46,      // also NUM_DELETE
    -  ZERO: 48,
    -  ONE: 49,
    -  TWO: 50,
    -  THREE: 51,
    -  FOUR: 52,
    -  FIVE: 53,
    -  SIX: 54,
    -  SEVEN: 55,
    -  EIGHT: 56,
    -  NINE: 57,
    -  FF_SEMICOLON: 59, // Firefox (Gecko) fires this for semicolon instead of 186
    -  FF_EQUALS: 61, // Firefox (Gecko) fires this for equals instead of 187
    -  FF_DASH: 173, // Firefox (Gecko) fires this for dash instead of 189
    -  QUESTION_MARK: 63, // needs localization
    -  A: 65,
    -  B: 66,
    -  C: 67,
    -  D: 68,
    -  E: 69,
    -  F: 70,
    -  G: 71,
    -  H: 72,
    -  I: 73,
    -  J: 74,
    -  K: 75,
    -  L: 76,
    -  M: 77,
    -  N: 78,
    -  O: 79,
    -  P: 80,
    -  Q: 81,
    -  R: 82,
    -  S: 83,
    -  T: 84,
    -  U: 85,
    -  V: 86,
    -  W: 87,
    -  X: 88,
    -  Y: 89,
    -  Z: 90,
    -  META: 91, // WIN_KEY_LEFT
    -  WIN_KEY_RIGHT: 92,
    -  CONTEXT_MENU: 93,
    -  NUM_ZERO: 96,
    -  NUM_ONE: 97,
    -  NUM_TWO: 98,
    -  NUM_THREE: 99,
    -  NUM_FOUR: 100,
    -  NUM_FIVE: 101,
    -  NUM_SIX: 102,
    -  NUM_SEVEN: 103,
    -  NUM_EIGHT: 104,
    -  NUM_NINE: 105,
    -  NUM_MULTIPLY: 106,
    -  NUM_PLUS: 107,
    -  NUM_MINUS: 109,
    -  NUM_PERIOD: 110,
    -  NUM_DIVISION: 111,
    -  F1: 112,
    -  F2: 113,
    -  F3: 114,
    -  F4: 115,
    -  F5: 116,
    -  F6: 117,
    -  F7: 118,
    -  F8: 119,
    -  F9: 120,
    -  F10: 121,
    -  F11: 122,
    -  F12: 123,
    -  NUMLOCK: 144,
    -  SCROLL_LOCK: 145,
    -
    -  // OS-specific media keys like volume controls and browser controls.
    -  FIRST_MEDIA_KEY: 166,
    -  LAST_MEDIA_KEY: 183,
    -
    -  SEMICOLON: 186,            // needs localization
    -  DASH: 189,                 // needs localization
    -  EQUALS: 187,               // needs localization
    -  COMMA: 188,                // needs localization
    -  PERIOD: 190,               // needs localization
    -  SLASH: 191,                // needs localization
    -  APOSTROPHE: 192,           // needs localization
    -  TILDE: 192,                // needs localization
    -  SINGLE_QUOTE: 222,         // needs localization
    -  OPEN_SQUARE_BRACKET: 219,  // needs localization
    -  BACKSLASH: 220,            // needs localization
    -  CLOSE_SQUARE_BRACKET: 221, // needs localization
    -  WIN_KEY: 224,
    -  MAC_FF_META: 224, // Firefox (Gecko) fires this for the meta key instead of 91
    -  MAC_WK_CMD_LEFT: 91,  // WebKit Left Command key fired, same as META
    -  MAC_WK_CMD_RIGHT: 93, // WebKit Right Command key fired, different from META
    -  WIN_IME: 229,
    -
    -  // "Reserved for future use". Some programs (e.g. the SlingPlayer 2.4 ActiveX
    -  // control) fire this as a hacky way to disable screensavers.
    -  VK_NONAME: 252,
    -
    -  // We've seen users whose machines fire this keycode at regular one
    -  // second intervals. The common thread among these users is that
    -  // they're all using Dell Inspiron laptops, so we suspect that this
    -  // indicates a hardware/bios problem.
    -  // http://en.community.dell.com/support-forums/laptop/f/3518/p/19285957/19523128.aspx
    -  PHANTOM: 255
    -};
    -
    -
    -/**
    - * Returns true if the event contains a text modifying key.
    - * @param {goog.events.BrowserEvent} e A key event.
    - * @return {boolean} Whether it's a text modifying key.
    - */
    -goog.events.KeyCodes.isTextModifyingKeyEvent = function(e) {
    -  if (e.altKey && !e.ctrlKey ||
    -      e.metaKey ||
    -      // Function keys don't generate text
    -      e.keyCode >= goog.events.KeyCodes.F1 &&
    -      e.keyCode <= goog.events.KeyCodes.F12) {
    -    return false;
    -  }
    -
    -  // The following keys are quite harmless, even in combination with
    -  // CTRL, ALT or SHIFT.
    -  switch (e.keyCode) {
    -    case goog.events.KeyCodes.ALT:
    -    case goog.events.KeyCodes.CAPS_LOCK:
    -    case goog.events.KeyCodes.CONTEXT_MENU:
    -    case goog.events.KeyCodes.CTRL:
    -    case goog.events.KeyCodes.DOWN:
    -    case goog.events.KeyCodes.END:
    -    case goog.events.KeyCodes.ESC:
    -    case goog.events.KeyCodes.HOME:
    -    case goog.events.KeyCodes.INSERT:
    -    case goog.events.KeyCodes.LEFT:
    -    case goog.events.KeyCodes.MAC_FF_META:
    -    case goog.events.KeyCodes.META:
    -    case goog.events.KeyCodes.NUMLOCK:
    -    case goog.events.KeyCodes.NUM_CENTER:
    -    case goog.events.KeyCodes.PAGE_DOWN:
    -    case goog.events.KeyCodes.PAGE_UP:
    -    case goog.events.KeyCodes.PAUSE:
    -    case goog.events.KeyCodes.PHANTOM:
    -    case goog.events.KeyCodes.PRINT_SCREEN:
    -    case goog.events.KeyCodes.RIGHT:
    -    case goog.events.KeyCodes.SCROLL_LOCK:
    -    case goog.events.KeyCodes.SHIFT:
    -    case goog.events.KeyCodes.UP:
    -    case goog.events.KeyCodes.VK_NONAME:
    -    case goog.events.KeyCodes.WIN_KEY:
    -    case goog.events.KeyCodes.WIN_KEY_RIGHT:
    -      return false;
    -    case goog.events.KeyCodes.WIN_KEY_FF_LINUX:
    -      return !goog.userAgent.GECKO;
    -    default:
    -      return e.keyCode < goog.events.KeyCodes.FIRST_MEDIA_KEY ||
    -          e.keyCode > goog.events.KeyCodes.LAST_MEDIA_KEY;
    -  }
    -};
    -
    -
    -/**
    - * Returns true if the key fires a keypress event in the current browser.
    - *
    - * Accoridng to MSDN [1] IE only fires keypress events for the following keys:
    - * - Letters: A - Z (uppercase and lowercase)
    - * - Numerals: 0 - 9
    - * - Symbols: ! @ # $ % ^ & * ( ) _ - + = < [ ] { } , . / ? \ | ' ` " ~
    - * - System: ESC, SPACEBAR, ENTER
    - *
    - * That's not entirely correct though, for instance there's no distinction
    - * between upper and lower case letters.
    - *
    - * [1] http://msdn2.microsoft.com/en-us/library/ms536939(VS.85).aspx)
    - *
    - * Safari is similar to IE, but does not fire keypress for ESC.
    - *
    - * Additionally, IE6 does not fire keydown or keypress events for letters when
    - * the control or alt keys are held down and the shift key is not. IE7 does
    - * fire keydown in these cases, though, but not keypress.
    - *
    - * @param {number} keyCode A key code.
    - * @param {number=} opt_heldKeyCode Key code of a currently-held key.
    - * @param {boolean=} opt_shiftKey Whether the shift key is held down.
    - * @param {boolean=} opt_ctrlKey Whether the control key is held down.
    - * @param {boolean=} opt_altKey Whether the alt key is held down.
    - * @return {boolean} Whether it's a key that fires a keypress event.
    - */
    -goog.events.KeyCodes.firesKeyPressEvent = function(keyCode, opt_heldKeyCode,
    -    opt_shiftKey, opt_ctrlKey, opt_altKey) {
    -  if (!goog.userAgent.IE &&
    -      !(goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher('525'))) {
    -    return true;
    -  }
    -
    -  if (goog.userAgent.MAC && opt_altKey) {
    -    return goog.events.KeyCodes.isCharacterKey(keyCode);
    -  }
    -
    -  // Alt but not AltGr which is represented as Alt+Ctrl.
    -  if (opt_altKey && !opt_ctrlKey) {
    -    return false;
    -  }
    -
    -  // Saves Ctrl or Alt + key for IE and WebKit 525+, which won't fire keypress.
    -  // Non-IE browsers and WebKit prior to 525 won't get this far so no need to
    -  // check the user agent.
    -  if (goog.isNumber(opt_heldKeyCode)) {
    -    opt_heldKeyCode = goog.events.KeyCodes.normalizeKeyCode(opt_heldKeyCode);
    -  }
    -  if (!opt_shiftKey &&
    -      (opt_heldKeyCode == goog.events.KeyCodes.CTRL ||
    -       opt_heldKeyCode == goog.events.KeyCodes.ALT ||
    -       goog.userAgent.MAC &&
    -       opt_heldKeyCode == goog.events.KeyCodes.META)) {
    -    return false;
    -  }
    -
    -  // Some keys with Ctrl/Shift do not issue keypress in WEBKIT.
    -  if (goog.userAgent.WEBKIT && opt_ctrlKey && opt_shiftKey) {
    -    switch (keyCode) {
    -      case goog.events.KeyCodes.BACKSLASH:
    -      case goog.events.KeyCodes.OPEN_SQUARE_BRACKET:
    -      case goog.events.KeyCodes.CLOSE_SQUARE_BRACKET:
    -      case goog.events.KeyCodes.TILDE:
    -      case goog.events.KeyCodes.SEMICOLON:
    -      case goog.events.KeyCodes.DASH:
    -      case goog.events.KeyCodes.EQUALS:
    -      case goog.events.KeyCodes.COMMA:
    -      case goog.events.KeyCodes.PERIOD:
    -      case goog.events.KeyCodes.SLASH:
    -      case goog.events.KeyCodes.APOSTROPHE:
    -      case goog.events.KeyCodes.SINGLE_QUOTE:
    -        return false;
    -    }
    -  }
    -
    -  // When Ctrl+<somekey> is held in IE, it only fires a keypress once, but it
    -  // continues to fire keydown events as the event repeats.
    -  if (goog.userAgent.IE && opt_ctrlKey && opt_heldKeyCode == keyCode) {
    -    return false;
    -  }
    -
    -  switch (keyCode) {
    -    case goog.events.KeyCodes.ENTER:
    -      return true;
    -    case goog.events.KeyCodes.ESC:
    -      return !goog.userAgent.WEBKIT;
    -  }
    -
    -  return goog.events.KeyCodes.isCharacterKey(keyCode);
    -};
    -
    -
    -/**
    - * Returns true if the key produces a character.
    - * This does not cover characters on non-US keyboards (Russian, Hebrew, etc.).
    - *
    - * @param {number} keyCode A key code.
    - * @return {boolean} Whether it's a character key.
    - */
    -goog.events.KeyCodes.isCharacterKey = function(keyCode) {
    -  if (keyCode >= goog.events.KeyCodes.ZERO &&
    -      keyCode <= goog.events.KeyCodes.NINE) {
    -    return true;
    -  }
    -
    -  if (keyCode >= goog.events.KeyCodes.NUM_ZERO &&
    -      keyCode <= goog.events.KeyCodes.NUM_MULTIPLY) {
    -    return true;
    -  }
    -
    -  if (keyCode >= goog.events.KeyCodes.A &&
    -      keyCode <= goog.events.KeyCodes.Z) {
    -    return true;
    -  }
    -
    -  // Safari sends zero key code for non-latin characters.
    -  if (goog.userAgent.WEBKIT && keyCode == 0) {
    -    return true;
    -  }
    -
    -  switch (keyCode) {
    -    case goog.events.KeyCodes.SPACE:
    -    case goog.events.KeyCodes.QUESTION_MARK:
    -    case goog.events.KeyCodes.NUM_PLUS:
    -    case goog.events.KeyCodes.NUM_MINUS:
    -    case goog.events.KeyCodes.NUM_PERIOD:
    -    case goog.events.KeyCodes.NUM_DIVISION:
    -    case goog.events.KeyCodes.SEMICOLON:
    -    case goog.events.KeyCodes.FF_SEMICOLON:
    -    case goog.events.KeyCodes.DASH:
    -    case goog.events.KeyCodes.EQUALS:
    -    case goog.events.KeyCodes.FF_EQUALS:
    -    case goog.events.KeyCodes.COMMA:
    -    case goog.events.KeyCodes.PERIOD:
    -    case goog.events.KeyCodes.SLASH:
    -    case goog.events.KeyCodes.APOSTROPHE:
    -    case goog.events.KeyCodes.SINGLE_QUOTE:
    -    case goog.events.KeyCodes.OPEN_SQUARE_BRACKET:
    -    case goog.events.KeyCodes.BACKSLASH:
    -    case goog.events.KeyCodes.CLOSE_SQUARE_BRACKET:
    -      return true;
    -    default:
    -      return false;
    -  }
    -};
    -
    -
    -/**
    - * Normalizes key codes from OS/Browser-specific value to the general one.
    - * @param {number} keyCode The native key code.
    - * @return {number} The normalized key code.
    - */
    -goog.events.KeyCodes.normalizeKeyCode = function(keyCode) {
    -  if (goog.userAgent.GECKO) {
    -    return goog.events.KeyCodes.normalizeGeckoKeyCode(keyCode);
    -  } else if (goog.userAgent.MAC && goog.userAgent.WEBKIT) {
    -    return goog.events.KeyCodes.normalizeMacWebKitKeyCode(keyCode);
    -  } else {
    -    return keyCode;
    -  }
    -};
    -
    -
    -/**
    - * Normalizes key codes from their Gecko-specific value to the general one.
    - * @param {number} keyCode The native key code.
    - * @return {number} The normalized key code.
    - */
    -goog.events.KeyCodes.normalizeGeckoKeyCode = function(keyCode) {
    -  switch (keyCode) {
    -    case goog.events.KeyCodes.FF_EQUALS:
    -      return goog.events.KeyCodes.EQUALS;
    -    case goog.events.KeyCodes.FF_SEMICOLON:
    -      return goog.events.KeyCodes.SEMICOLON;
    -    case goog.events.KeyCodes.FF_DASH:
    -      return goog.events.KeyCodes.DASH;
    -    case goog.events.KeyCodes.MAC_FF_META:
    -      return goog.events.KeyCodes.META;
    -    case goog.events.KeyCodes.WIN_KEY_FF_LINUX:
    -      return goog.events.KeyCodes.WIN_KEY;
    -    default:
    -      return keyCode;
    -  }
    -};
    -
    -
    -/**
    - * Normalizes key codes from their Mac WebKit-specific value to the general one.
    - * @param {number} keyCode The native key code.
    - * @return {number} The normalized key code.
    - */
    -goog.events.KeyCodes.normalizeMacWebKitKeyCode = function(keyCode) {
    -  switch (keyCode) {
    -    case goog.events.KeyCodes.MAC_WK_CMD_RIGHT:  // 93
    -      return goog.events.KeyCodes.META;          // 91
    -    default:
    -      return keyCode;
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/events/keycodes_test.html b/src/database/third_party/closure-library/closure/goog/events/keycodes_test.html
    deleted file mode 100644
    index c377d44d253..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/keycodes_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    -Author: nicksantos@google.com (Nick Santos)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   JsUnit tests for goog.events.KeyCodes
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.events.KeyCodesTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/events/keycodes_test.js b/src/database/third_party/closure-library/closure/goog/events/keycodes_test.js
    deleted file mode 100644
    index ad26c25b848..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/keycodes_test.js
    +++ /dev/null
    @@ -1,174 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.events.KeyCodesTest');
    -goog.setTestOnly('goog.events.KeyCodesTest');
    -
    -goog.require('goog.events.BrowserEvent');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.object');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -var KeyCodes;
    -var stubs;
    -
    -function setUpPage() {
    -  KeyCodes = goog.events.KeyCodes;
    -  stubs = new goog.testing.PropertyReplacer();
    -}
    -
    -function tearDown() {
    -  stubs.reset();
    -}
    -
    -function testTextModifyingKeys() {
    -  var specialTextModifiers = goog.object.createSet(
    -      KeyCodes.BACKSPACE,
    -      KeyCodes.DELETE,
    -      KeyCodes.ENTER,
    -      KeyCodes.MAC_ENTER,
    -      KeyCodes.TAB,
    -      KeyCodes.WIN_IME);
    -
    -  if (!goog.userAgent.GECKO) {
    -    specialTextModifiers[KeyCodes.WIN_KEY_FF_LINUX] = 1;
    -  }
    -
    -  for (var keyId in KeyCodes) {
    -    var key = KeyCodes[keyId];
    -    if (goog.isFunction(key)) {
    -      // skip static methods
    -      continue;
    -    }
    -
    -    var fakeEvent = createEventWithKeyCode(key);
    -
    -    if (KeyCodes.isCharacterKey(key) || (key in specialTextModifiers)) {
    -      assertTrue('Expected key to modify text: ' + keyId,
    -          KeyCodes.isTextModifyingKeyEvent(fakeEvent));
    -    } else {
    -      assertFalse('Expected key to not modify text: ' + keyId,
    -          KeyCodes.isTextModifyingKeyEvent(fakeEvent));
    -    }
    -  }
    -
    -  for (var i = KeyCodes.FIRST_MEDIA_KEY; i <= KeyCodes.LAST_MEDIA_KEY; i++) {
    -    var fakeEvent = createEventWithKeyCode(i);
    -    assertFalse('Expected key to not modify text: ' + i,
    -        KeyCodes.isTextModifyingKeyEvent(fakeEvent));
    -  }
    -}
    -
    -function testKeyCodeZero() {
    -  var zeroEvent = createEventWithKeyCode(0);
    -  assertEquals(
    -      !goog.userAgent.GECKO,
    -      KeyCodes.isTextModifyingKeyEvent(zeroEvent));
    -  assertEquals(
    -      goog.userAgent.WEBKIT,
    -      KeyCodes.isCharacterKey(0));
    -}
    -
    -function testPhantomKey() {
    -  // KeyCode 255 deserves its own test to make sure this does not regress,
    -  // because it's so weird. See the comments in the KeyCode enum.
    -  var fakeEvent = createEventWithKeyCode(goog.events.KeyCodes.PHANTOM);
    -  assertFalse('Expected phantom key to not modify text',
    -      KeyCodes.isTextModifyingKeyEvent(fakeEvent));
    -  assertFalse(KeyCodes.isCharacterKey(fakeEvent));
    -}
    -
    -function testNonUsKeyboards() {
    -  var fakeEvent = createEventWithKeyCode(1092 /* Russian a */);
    -  assertTrue('Expected key to not modify text: 1092',
    -      KeyCodes.isTextModifyingKeyEvent(fakeEvent));
    -}
    -
    -function createEventWithKeyCode(i) {
    -  var fakeEvent = new goog.events.BrowserEvent('keydown');
    -  fakeEvent.keyCode = i;
    -  return fakeEvent;
    -}
    -
    -function testNormalizeGeckoKeyCode() {
    -  stubs.set(goog.userAgent, 'GECKO', true);
    -
    -  // Test Gecko-specific key codes.
    -  assertEquals(
    -      goog.events.KeyCodes.normalizeGeckoKeyCode(KeyCodes.FF_EQUALS),
    -      KeyCodes.EQUALS);
    -  assertEquals(
    -      goog.events.KeyCodes.normalizeKeyCode(KeyCodes.FF_EQUALS),
    -      KeyCodes.EQUALS);
    -
    -  assertEquals(
    -      goog.events.KeyCodes.normalizeGeckoKeyCode(KeyCodes.FF_SEMICOLON),
    -      KeyCodes.SEMICOLON);
    -  assertEquals(
    -      goog.events.KeyCodes.normalizeKeyCode(KeyCodes.FF_SEMICOLON),
    -      KeyCodes.SEMICOLON);
    -
    -  assertEquals(
    -      goog.events.KeyCodes.normalizeGeckoKeyCode(KeyCodes.MAC_FF_META),
    -      KeyCodes.META);
    -  assertEquals(
    -      goog.events.KeyCodes.normalizeKeyCode(KeyCodes.MAC_FF_META),
    -      KeyCodes.META);
    -
    -  assertEquals(
    -      goog.events.KeyCodes.normalizeGeckoKeyCode(KeyCodes.WIN_KEY_FF_LINUX),
    -      KeyCodes.WIN_KEY);
    -  assertEquals(
    -      goog.events.KeyCodes.normalizeKeyCode(KeyCodes.WIN_KEY_FF_LINUX),
    -      KeyCodes.WIN_KEY);
    -
    -  // Test general key codes.
    -  assertEquals(
    -      goog.events.KeyCodes.normalizeGeckoKeyCode(KeyCodes.COMMA),
    -      KeyCodes.COMMA);
    -  assertEquals(
    -      goog.events.KeyCodes.normalizeKeyCode(KeyCodes.COMMA),
    -      KeyCodes.COMMA);
    -}
    -
    -function testNormalizeMacWebKitKeyCode() {
    -  stubs.set(goog.userAgent, 'GECKO', false);
    -  stubs.set(goog.userAgent, 'MAC', true);
    -  stubs.set(goog.userAgent, 'WEBKIT', true);
    -
    -  // Test Mac WebKit specific key codes.
    -  assertEquals(
    -      goog.events.KeyCodes.normalizeMacWebKitKeyCode(KeyCodes.MAC_WK_CMD_LEFT),
    -      KeyCodes.META);
    -  assertEquals(
    -      goog.events.KeyCodes.normalizeKeyCode(KeyCodes.MAC_WK_CMD_LEFT),
    -      KeyCodes.META);
    -
    -  assertEquals(
    -      goog.events.KeyCodes.normalizeMacWebKitKeyCode(KeyCodes.MAC_WK_CMD_RIGHT),
    -      KeyCodes.META);
    -  assertEquals(
    -      goog.events.KeyCodes.normalizeKeyCode(KeyCodes.MAC_WK_CMD_RIGHT),
    -      KeyCodes.META);
    -
    -  // Test general key codes.
    -  assertEquals(
    -      goog.events.KeyCodes.normalizeMacWebKitKeyCode(KeyCodes.COMMA),
    -      KeyCodes.COMMA);
    -  assertEquals(
    -      goog.events.KeyCodes.normalizeKeyCode(KeyCodes.COMMA),
    -      KeyCodes.COMMA);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/events/keyhandler.js b/src/database/third_party/closure-library/closure/goog/events/keyhandler.js
    deleted file mode 100644
    index 6a7662f539e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/keyhandler.js
    +++ /dev/null
    @@ -1,556 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview This file contains a class for working with keyboard events
    - * that repeat consistently across browsers and platforms. It also unifies the
    - * key code so that it is the same in all browsers and platforms.
    - *
    - * Different web browsers have very different keyboard event handling. Most
    - * importantly is that only certain browsers repeat keydown events:
    - * IE, Opera, FF/Win32, and Safari 3 repeat keydown events.
    - * FF/Mac and Safari 2 do not.
    - *
    - * For the purposes of this code, "Safari 3" means WebKit 525+, when WebKit
    - * decided that they should try to match IE's key handling behavior.
    - * Safari 3.0.4, which shipped with Leopard (WebKit 523), has the
    - * Safari 2 behavior.
    - *
    - * Firefox, Safari, Opera prevent on keypress
    - *
    - * IE prevents on keydown
    - *
    - * Firefox does not fire keypress for shift, ctrl, alt
    - * Firefox does fire keydown for shift, ctrl, alt, meta
    - * Firefox does not repeat keydown for shift, ctrl, alt, meta
    - *
    - * Firefox does not fire keypress for up and down in an input
    - *
    - * Opera fires keypress for shift, ctrl, alt, meta
    - * Opera does not repeat keypress for shift, ctrl, alt, meta
    - *
    - * Safari 2 and 3 do not fire keypress for shift, ctrl, alt
    - * Safari 2 does not fire keydown for shift, ctrl, alt
    - * Safari 3 *does* fire keydown for shift, ctrl, alt
    - *
    - * IE provides the keycode for keyup/down events and the charcode (in the
    - * keycode field) for keypress.
    - *
    - * Mozilla provides the keycode for keyup/down and the charcode for keypress
    - * unless it's a non text modifying key in which case the keycode is provided.
    - *
    - * Safari 3 provides the keycode and charcode for all events.
    - *
    - * Opera provides the keycode for keyup/down event and either the charcode or
    - * the keycode (in the keycode field) for keypress events.
    - *
    - * Firefox x11 doesn't fire keydown events if a another key is already held down
    - * until the first key is released. This can cause a key event to be fired with
    - * a keyCode for the first key and a charCode for the second key.
    - *
    - * Safari in keypress
    - *
    - *        charCode keyCode which
    - * ENTER:       13      13    13
    - * F1:       63236   63236 63236
    - * F8:       63243   63243 63243
    - * ...
    - * p:          112     112   112
    - * P:           80      80    80
    - *
    - * Firefox, keypress:
    - *
    - *        charCode keyCode which
    - * ENTER:        0      13    13
    - * F1:           0     112     0
    - * F8:           0     119     0
    - * ...
    - * p:          112       0   112
    - * P:           80       0    80
    - *
    - * Opera, Mac+Win32, keypress:
    - *
    - *         charCode keyCode which
    - * ENTER: undefined      13    13
    - * F1:    undefined     112     0
    - * F8:    undefined     119     0
    - * ...
    - * p:     undefined     112   112
    - * P:     undefined      80    80
    - *
    - * IE7, keydown
    - *
    - *         charCode keyCode     which
    - * ENTER: undefined      13 undefined
    - * F1:    undefined     112 undefined
    - * F8:    undefined     119 undefined
    - * ...
    - * p:     undefined      80 undefined
    - * P:     undefined      80 undefined
    - *
    - * @author arv@google.com (Erik Arvidsson)
    - * @author eae@google.com (Emil A Eklund)
    - * @see ../demos/keyhandler.html
    - */
    -
    -goog.provide('goog.events.KeyEvent');
    -goog.provide('goog.events.KeyHandler');
    -goog.provide('goog.events.KeyHandler.EventType');
    -
    -goog.require('goog.events');
    -goog.require('goog.events.BrowserEvent');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * A wrapper around an element that you want to listen to keyboard events on.
    - * @param {Element|Document=} opt_element The element or document to listen on.
    - * @param {boolean=} opt_capture Whether to listen for browser events in
    - *     capture phase (defaults to false).
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - * @final
    - */
    -goog.events.KeyHandler = function(opt_element, opt_capture) {
    -  goog.events.EventTarget.call(this);
    -
    -  if (opt_element) {
    -    this.attach(opt_element, opt_capture);
    -  }
    -};
    -goog.inherits(goog.events.KeyHandler, goog.events.EventTarget);
    -
    -
    -/**
    - * This is the element that we will listen to the real keyboard events on.
    - * @type {Element|Document|null}
    - * @private
    - */
    -goog.events.KeyHandler.prototype.element_ = null;
    -
    -
    -/**
    - * The key for the key press listener.
    - * @type {goog.events.Key}
    - * @private
    - */
    -goog.events.KeyHandler.prototype.keyPressKey_ = null;
    -
    -
    -/**
    - * The key for the key down listener.
    - * @type {goog.events.Key}
    - * @private
    - */
    -goog.events.KeyHandler.prototype.keyDownKey_ = null;
    -
    -
    -/**
    - * The key for the key up listener.
    - * @type {goog.events.Key}
    - * @private
    - */
    -goog.events.KeyHandler.prototype.keyUpKey_ = null;
    -
    -
    -/**
    - * Used to detect keyboard repeat events.
    - * @private
    - * @type {number}
    - */
    -goog.events.KeyHandler.prototype.lastKey_ = -1;
    -
    -
    -/**
    - * Keycode recorded for key down events. As most browsers don't report the
    - * keycode in the key press event we need to record it in the key down phase.
    - * @private
    - * @type {number}
    - */
    -goog.events.KeyHandler.prototype.keyCode_ = -1;
    -
    -
    -/**
    - * Alt key recorded for key down events. FF on Mac does not report the alt key
    - * flag in the key press event, we need to record it in the key down phase.
    - * @type {boolean}
    - * @private
    - */
    -goog.events.KeyHandler.prototype.altKey_ = false;
    -
    -
    -/**
    - * Enum type for the events fired by the key handler
    - * @enum {string}
    - */
    -goog.events.KeyHandler.EventType = {
    -  KEY: 'key'
    -};
    -
    -
    -/**
    - * An enumeration of key codes that Safari 2 does incorrectly
    - * @type {Object}
    - * @private
    - */
    -goog.events.KeyHandler.safariKey_ = {
    -  '3': goog.events.KeyCodes.ENTER, // 13
    -  '12': goog.events.KeyCodes.NUMLOCK, // 144
    -  '63232': goog.events.KeyCodes.UP, // 38
    -  '63233': goog.events.KeyCodes.DOWN, // 40
    -  '63234': goog.events.KeyCodes.LEFT, // 37
    -  '63235': goog.events.KeyCodes.RIGHT, // 39
    -  '63236': goog.events.KeyCodes.F1, // 112
    -  '63237': goog.events.KeyCodes.F2, // 113
    -  '63238': goog.events.KeyCodes.F3, // 114
    -  '63239': goog.events.KeyCodes.F4, // 115
    -  '63240': goog.events.KeyCodes.F5, // 116
    -  '63241': goog.events.KeyCodes.F6, // 117
    -  '63242': goog.events.KeyCodes.F7, // 118
    -  '63243': goog.events.KeyCodes.F8, // 119
    -  '63244': goog.events.KeyCodes.F9, // 120
    -  '63245': goog.events.KeyCodes.F10, // 121
    -  '63246': goog.events.KeyCodes.F11, // 122
    -  '63247': goog.events.KeyCodes.F12, // 123
    -  '63248': goog.events.KeyCodes.PRINT_SCREEN, // 44
    -  '63272': goog.events.KeyCodes.DELETE, // 46
    -  '63273': goog.events.KeyCodes.HOME, // 36
    -  '63275': goog.events.KeyCodes.END, // 35
    -  '63276': goog.events.KeyCodes.PAGE_UP, // 33
    -  '63277': goog.events.KeyCodes.PAGE_DOWN, // 34
    -  '63289': goog.events.KeyCodes.NUMLOCK, // 144
    -  '63302': goog.events.KeyCodes.INSERT // 45
    -};
    -
    -
    -/**
    - * An enumeration of key identifiers currently part of the W3C draft for DOM3
    - * and their mappings to keyCodes.
    - * http://www.w3.org/TR/DOM-Level-3-Events/keyset.html#KeySet-Set
    - * This is currently supported in Safari and should be platform independent.
    - * @type {Object}
    - * @private
    - */
    -goog.events.KeyHandler.keyIdentifier_ = {
    -  'Up': goog.events.KeyCodes.UP, // 38
    -  'Down': goog.events.KeyCodes.DOWN, // 40
    -  'Left': goog.events.KeyCodes.LEFT, // 37
    -  'Right': goog.events.KeyCodes.RIGHT, // 39
    -  'Enter': goog.events.KeyCodes.ENTER, // 13
    -  'F1': goog.events.KeyCodes.F1, // 112
    -  'F2': goog.events.KeyCodes.F2, // 113
    -  'F3': goog.events.KeyCodes.F3, // 114
    -  'F4': goog.events.KeyCodes.F4, // 115
    -  'F5': goog.events.KeyCodes.F5, // 116
    -  'F6': goog.events.KeyCodes.F6, // 117
    -  'F7': goog.events.KeyCodes.F7, // 118
    -  'F8': goog.events.KeyCodes.F8, // 119
    -  'F9': goog.events.KeyCodes.F9, // 120
    -  'F10': goog.events.KeyCodes.F10, // 121
    -  'F11': goog.events.KeyCodes.F11, // 122
    -  'F12': goog.events.KeyCodes.F12, // 123
    -  'U+007F': goog.events.KeyCodes.DELETE, // 46
    -  'Home': goog.events.KeyCodes.HOME, // 36
    -  'End': goog.events.KeyCodes.END, // 35
    -  'PageUp': goog.events.KeyCodes.PAGE_UP, // 33
    -  'PageDown': goog.events.KeyCodes.PAGE_DOWN, // 34
    -  'Insert': goog.events.KeyCodes.INSERT // 45
    -};
    -
    -
    -/**
    - * If true, the KeyEvent fires on keydown. Otherwise, it fires on keypress.
    - *
    - * @type {boolean}
    - * @private
    - */
    -goog.events.KeyHandler.USES_KEYDOWN_ = goog.userAgent.IE ||
    -    goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher('525');
    -
    -
    -/**
    - * If true, the alt key flag is saved during the key down and reused when
    - * handling the key press. FF on Mac does not set the alt flag in the key press
    - * event.
    - * @type {boolean}
    - * @private
    - */
    -goog.events.KeyHandler.SAVE_ALT_FOR_KEYPRESS_ = goog.userAgent.MAC &&
    -    goog.userAgent.GECKO;
    -
    -
    -/**
    - * Records the keycode for browsers that only returns the keycode for key up/
    - * down events. For browser/key combinations that doesn't trigger a key pressed
    - * event it also fires the patched key event.
    - * @param {goog.events.BrowserEvent} e The key down event.
    - * @private
    - */
    -goog.events.KeyHandler.prototype.handleKeyDown_ = function(e) {
    -  // Ctrl-Tab and Alt-Tab can cause the focus to be moved to another window
    -  // before we've caught a key-up event.  If the last-key was one of these we
    -  // reset the state.
    -  if (goog.userAgent.WEBKIT) {
    -    if (this.lastKey_ == goog.events.KeyCodes.CTRL && !e.ctrlKey ||
    -        this.lastKey_ == goog.events.KeyCodes.ALT && !e.altKey ||
    -        goog.userAgent.MAC &&
    -        this.lastKey_ == goog.events.KeyCodes.META && !e.metaKey) {
    -      this.lastKey_ = -1;
    -      this.keyCode_ = -1;
    -    }
    -  }
    -
    -  if (this.lastKey_ == -1) {
    -    if (e.ctrlKey && e.keyCode != goog.events.KeyCodes.CTRL) {
    -      this.lastKey_ = goog.events.KeyCodes.CTRL;
    -    } else if (e.altKey && e.keyCode != goog.events.KeyCodes.ALT) {
    -      this.lastKey_ = goog.events.KeyCodes.ALT;
    -    } else if (e.metaKey && e.keyCode != goog.events.KeyCodes.META) {
    -      this.lastKey_ = goog.events.KeyCodes.META;
    -    }
    -  }
    -
    -  if (goog.events.KeyHandler.USES_KEYDOWN_ &&
    -      !goog.events.KeyCodes.firesKeyPressEvent(e.keyCode,
    -          this.lastKey_, e.shiftKey, e.ctrlKey, e.altKey)) {
    -    this.handleEvent(e);
    -  } else {
    -    this.keyCode_ = goog.events.KeyCodes.normalizeKeyCode(e.keyCode);
    -    if (goog.events.KeyHandler.SAVE_ALT_FOR_KEYPRESS_) {
    -      this.altKey_ = e.altKey;
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Resets the stored previous values. Needed to be called for webkit which will
    - * not generate a key up for meta key operations. This should only be called
    - * when having finished with repeat key possiblities.
    - */
    -goog.events.KeyHandler.prototype.resetState = function() {
    -  this.lastKey_ = -1;
    -  this.keyCode_ = -1;
    -};
    -
    -
    -/**
    - * Clears the stored previous key value, resetting the key repeat status. Uses
    - * -1 because the Safari 3 Windows beta reports 0 for certain keys (like Home
    - * and End.)
    - * @param {goog.events.BrowserEvent} e The keyup event.
    - * @private
    - */
    -goog.events.KeyHandler.prototype.handleKeyup_ = function(e) {
    -  this.resetState();
    -  this.altKey_ = e.altKey;
    -};
    -
    -
    -/**
    - * Handles the events on the element.
    - * @param {goog.events.BrowserEvent} e  The keyboard event sent from the
    - *     browser.
    - */
    -goog.events.KeyHandler.prototype.handleEvent = function(e) {
    -  var be = e.getBrowserEvent();
    -  var keyCode, charCode;
    -  var altKey = be.altKey;
    -
    -  // IE reports the character code in the keyCode field for keypress events.
    -  // There are two exceptions however, Enter and Escape.
    -  if (goog.userAgent.IE && e.type == goog.events.EventType.KEYPRESS) {
    -    keyCode = this.keyCode_;
    -    charCode = keyCode != goog.events.KeyCodes.ENTER &&
    -        keyCode != goog.events.KeyCodes.ESC ?
    -            be.keyCode : 0;
    -
    -  // Safari reports the character code in the keyCode field for keypress
    -  // events but also has a charCode field.
    -  } else if (goog.userAgent.WEBKIT &&
    -      e.type == goog.events.EventType.KEYPRESS) {
    -    keyCode = this.keyCode_;
    -    charCode = be.charCode >= 0 && be.charCode < 63232 &&
    -        goog.events.KeyCodes.isCharacterKey(keyCode) ?
    -            be.charCode : 0;
    -
    -  // Opera reports the keycode or the character code in the keyCode field.
    -  } else if (goog.userAgent.OPERA) {
    -    keyCode = this.keyCode_;
    -    charCode = goog.events.KeyCodes.isCharacterKey(keyCode) ?
    -        be.keyCode : 0;
    -
    -  // Mozilla reports the character code in the charCode field.
    -  } else {
    -    keyCode = be.keyCode || this.keyCode_;
    -    charCode = be.charCode || 0;
    -    if (goog.events.KeyHandler.SAVE_ALT_FOR_KEYPRESS_) {
    -      altKey = this.altKey_;
    -    }
    -    // On the Mac, shift-/ triggers a question mark char code and no key code
    -    // (normalized to WIN_KEY), so we synthesize the latter.
    -    if (goog.userAgent.MAC &&
    -        charCode == goog.events.KeyCodes.QUESTION_MARK &&
    -        keyCode == goog.events.KeyCodes.WIN_KEY) {
    -      keyCode = goog.events.KeyCodes.SLASH;
    -    }
    -  }
    -
    -  keyCode = goog.events.KeyCodes.normalizeKeyCode(keyCode);
    -  var key = keyCode;
    -  var keyIdentifier = be.keyIdentifier;
    -
    -  // Correct the key value for certain browser-specific quirks.
    -  if (keyCode) {
    -    if (keyCode >= 63232 && keyCode in goog.events.KeyHandler.safariKey_) {
    -      // NOTE(nicksantos): Safari 3 has fixed this problem,
    -      // this is only needed for Safari 2.
    -      key = goog.events.KeyHandler.safariKey_[keyCode];
    -    } else {
    -
    -      // Safari returns 25 for Shift+Tab instead of 9.
    -      if (keyCode == 25 && e.shiftKey) {
    -        key = 9;
    -      }
    -    }
    -  } else if (keyIdentifier &&
    -             keyIdentifier in goog.events.KeyHandler.keyIdentifier_) {
    -    // This is needed for Safari Windows because it currently doesn't give a
    -    // keyCode/which for non printable keys.
    -    key = goog.events.KeyHandler.keyIdentifier_[keyIdentifier];
    -  }
    -
    -  // If we get the same keycode as a keydown/keypress without having seen a
    -  // keyup event, then this event was caused by key repeat.
    -  var repeat = key == this.lastKey_;
    -  this.lastKey_ = key;
    -
    -  var event = new goog.events.KeyEvent(key, charCode, repeat, be);
    -  event.altKey = altKey;
    -  this.dispatchEvent(event);
    -};
    -
    -
    -/**
    - * Returns the element listened on for the real keyboard events.
    - * @return {Element|Document|null} The element listened on for the real
    - *     keyboard events.
    - */
    -goog.events.KeyHandler.prototype.getElement = function() {
    -  return this.element_;
    -};
    -
    -
    -/**
    - * Adds the proper key event listeners to the element.
    - * @param {Element|Document} element The element to listen on.
    - * @param {boolean=} opt_capture Whether to listen for browser events in
    - *     capture phase (defaults to false).
    - */
    -goog.events.KeyHandler.prototype.attach = function(element, opt_capture) {
    -  if (this.keyUpKey_) {
    -    this.detach();
    -  }
    -
    -  this.element_ = element;
    -
    -  this.keyPressKey_ = goog.events.listen(this.element_,
    -                                         goog.events.EventType.KEYPRESS,
    -                                         this,
    -                                         opt_capture);
    -
    -  // Most browsers (Safari 2 being the notable exception) doesn't include the
    -  // keyCode in keypress events (IE has the char code in the keyCode field and
    -  // Mozilla only included the keyCode if there's no charCode). Thus we have to
    -  // listen for keydown to capture the keycode.
    -  this.keyDownKey_ = goog.events.listen(this.element_,
    -                                        goog.events.EventType.KEYDOWN,
    -                                        this.handleKeyDown_,
    -                                        opt_capture,
    -                                        this);
    -
    -
    -  this.keyUpKey_ = goog.events.listen(this.element_,
    -                                      goog.events.EventType.KEYUP,
    -                                      this.handleKeyup_,
    -                                      opt_capture,
    -                                      this);
    -};
    -
    -
    -/**
    - * Removes the listeners that may exist.
    - */
    -goog.events.KeyHandler.prototype.detach = function() {
    -  if (this.keyPressKey_) {
    -    goog.events.unlistenByKey(this.keyPressKey_);
    -    goog.events.unlistenByKey(this.keyDownKey_);
    -    goog.events.unlistenByKey(this.keyUpKey_);
    -    this.keyPressKey_ = null;
    -    this.keyDownKey_ = null;
    -    this.keyUpKey_ = null;
    -  }
    -  this.element_ = null;
    -  this.lastKey_ = -1;
    -  this.keyCode_ = -1;
    -};
    -
    -
    -/** @override */
    -goog.events.KeyHandler.prototype.disposeInternal = function() {
    -  goog.events.KeyHandler.superClass_.disposeInternal.call(this);
    -  this.detach();
    -};
    -
    -
    -
    -/**
    - * This class is used for the goog.events.KeyHandler.EventType.KEY event and
    - * it overrides the key code with the fixed key code.
    - * @param {number} keyCode The adjusted key code.
    - * @param {number} charCode The unicode character code.
    - * @param {boolean} repeat Whether this event was generated by keyboard repeat.
    - * @param {Event} browserEvent Browser event object.
    - * @constructor
    - * @extends {goog.events.BrowserEvent}
    - * @final
    - */
    -goog.events.KeyEvent = function(keyCode, charCode, repeat, browserEvent) {
    -  goog.events.BrowserEvent.call(this, browserEvent);
    -  this.type = goog.events.KeyHandler.EventType.KEY;
    -
    -  /**
    -   * Keycode of key press.
    -   * @type {number}
    -   */
    -  this.keyCode = keyCode;
    -
    -  /**
    -   * Unicode character code.
    -   * @type {number}
    -   */
    -  this.charCode = charCode;
    -
    -  /**
    -   * True if this event was generated by keyboard auto-repeat (i.e., the user is
    -   * holding the key down.)
    -   * @type {boolean}
    -   */
    -  this.repeat = repeat;
    -};
    -goog.inherits(goog.events.KeyEvent, goog.events.BrowserEvent);
    diff --git a/src/database/third_party/closure-library/closure/goog/events/keyhandler_test.html b/src/database/third_party/closure-library/closure/goog/events/keyhandler_test.html
    deleted file mode 100644
    index 08ef05a1e93..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/keyhandler_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.events.KeyHandler
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.events.KeyEventTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/events/keyhandler_test.js b/src/database/third_party/closure-library/closure/goog/events/keyhandler_test.js
    deleted file mode 100644
    index b31d8848704..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/keyhandler_test.js
    +++ /dev/null
    @@ -1,719 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.events.KeyEventTest');
    -goog.setTestOnly('goog.events.KeyEventTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.BrowserEvent');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.events.KeyHandler');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -function setUp() {
    -  // Have this based on a fictitious DOCUMENT_MODE constant.
    -  goog.userAgent.isDocumentMode = function(mode) {
    -    return mode <= goog.userAgent.DOCUMENT_MODE;
    -  };
    -}
    -
    -
    -/**
    - * Tests the key handler for the IE 8 and lower behavior.
    - */
    -function testIe8StyleKeyHandling() {
    -  goog.userAgent.OPERA = false;
    -  goog.userAgent.IE = true;
    -  goog.userAgent.GECKO = false;
    -  goog.userAgent.WEBKIT = false;
    -  goog.userAgent.MAC = false;
    -  goog.userAgent.WINDOWS = true;
    -  goog.userAgent.LINUX = false;
    -  goog.userAgent.VERSION = 8;
    -  goog.userAgent.DOCUMENT_MODE = 8;
    -  goog.events.KeyHandler.USES_KEYDOWN_ = true;
    -
    -  assertIe8StyleKeyHandling();
    -}
    -
    -
    -/**
    - * Tests the key handler for the IE 8 and lower behavior.
    - */
    -function testIe8StyleKeyHandlingInIe9DocumentMode() {
    -  goog.userAgent.OPERA = false;
    -  goog.userAgent.IE = true;
    -  goog.userAgent.GECKO = false;
    -  goog.userAgent.WEBKIT = false;
    -  goog.userAgent.MAC = false;
    -  goog.userAgent.WINDOWS = true;
    -  goog.userAgent.LINUX = false;
    -  goog.userAgent.VERSION = 9; // Try IE9 in IE8 document mode.
    -  goog.userAgent.DOCUMENT_MODE = 8;
    -  goog.events.KeyHandler.USES_KEYDOWN_ = true;
    -
    -  assertIe8StyleKeyHandling();
    -}
    -
    -function assertIe8StyleKeyHandling() {
    -  var keyEvent, keyHandler = new goog.events.KeyHandler();
    -  goog.events.listen(keyHandler, goog.events.KeyHandler.EventType.KEY,
    -      function(e) { keyEvent = e; });
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.ENTER);
    -  fireKeyPress(keyHandler, goog.events.KeyCodes.ENTER);
    -  assertEquals('Enter should fire a key event with the keycode 13',
    -               goog.events.KeyCodes.ENTER,
    -               keyEvent.keyCode);
    -  assertEquals('Enter should fire a key event with the charcode 0',
    -               0,
    -               keyEvent.charCode);
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.ESC);
    -  fireKeyPress(keyHandler, goog.events.KeyCodes.ESC);
    -  assertEquals('Esc should fire a key event with the keycode 27',
    -               goog.events.KeyCodes.ESC,
    -               keyEvent.keyCode);
    -  assertEquals('Esc should fire a key event with the charcode 0',
    -               0,
    -               keyEvent.charCode);
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.UP);
    -  assertEquals('Up should fire a key event with the keycode 38',
    -               goog.events.KeyCodes.UP,
    -               keyEvent.keyCode);
    -  assertEquals('Up should fire a key event with the charcode 0',
    -               0,
    -               keyEvent.charCode);
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.SEVEN, undefined, undefined,
    -      undefined, undefined, true);
    -  fireKeyPress(keyHandler, 38, undefined, undefined, undefined, undefined,
    -      true);
    -  assertEquals('Shift+7 should fire a key event with the keycode 55',
    -               goog.events.KeyCodes.SEVEN,
    -               keyEvent.keyCode);
    -  assertEquals('Shift+7 should fire a key event with the charcode 38',
    -               38,
    -               keyEvent.charCode);
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.A);
    -  fireKeyPress(keyHandler, 97);
    -  assertEquals('Lower case a should fire a key event with the keycode 65',
    -               goog.events.KeyCodes.A,
    -               keyEvent.keyCode);
    -  assertEquals('Lower case a should fire a key event with the charcode 97',
    -               97,
    -               keyEvent.charCode);
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.A);
    -  fireKeyPress(keyHandler, 65);
    -  assertEquals('Upper case A should fire a key event with the keycode 65',
    -               goog.events.KeyCodes.A,
    -               keyEvent.keyCode);
    -  assertEquals('Upper case A should fire a key event with the charcode 65',
    -               65,
    -               keyEvent.charCode);
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.DELETE);
    -  assertEquals('Delete should fire a key event with the keycode 46',
    -               goog.events.KeyCodes.DELETE,
    -               keyEvent.keyCode);
    -  assertEquals('Delete should fire a key event with the charcode 0',
    -               0,
    -               keyEvent.charCode);
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.PERIOD);
    -  fireKeyPress(keyHandler, 46);
    -  assertEquals('Period should fire a key event with the keycode 190',
    -               goog.events.KeyCodes.PERIOD,
    -               keyEvent.keyCode);
    -  assertEquals('Period should fire a key event with the charcode 46',
    -               46,
    -               keyEvent.charCode);
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.CTRL);
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.A);
    -  assertEquals('A with control down should fire a key event',
    -               goog.events.KeyCodes.A,
    -               keyEvent.keyCode);
    -
    -  // On IE, when Ctrl+<key> is held down, there is a KEYDOWN, a KEYPRESS, and
    -  // then a series of KEYDOWN events for each repeat.
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.B, undefined, undefined, true);
    -  fireKeyPress(keyHandler, goog.events.KeyCodes.B, undefined, undefined,
    -      true);
    -  assertEquals('B with control down should fire a key event',
    -               goog.events.KeyCodes.B,
    -               keyEvent.keyCode);
    -  assertTrue('Ctrl should be down.', keyEvent.ctrlKey);
    -  assertFalse('Should not have repeat=true on the first key press.',
    -      keyEvent.repeat);
    -  // Fire one repeated keydown event.
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.B, undefined, undefined, true);
    -  assertEquals('A with control down should fire a key event',
    -               goog.events.KeyCodes.B,
    -               keyEvent.keyCode);
    -  assertTrue('Should have repeat=true on key repeat.',
    -      keyEvent.repeat);
    -  assertTrue('Ctrl should be down.', keyEvent.ctrlKey);
    -}
    -
    -
    -/**
    - * Tests special cases for IE9.
    - */
    -function testIe9StyleKeyHandling() {
    -  goog.userAgent.OPERA = false;
    -  goog.userAgent.IE = true;
    -  goog.userAgent.GECKO = false;
    -  goog.userAgent.WEBKIT = false;
    -  goog.userAgent.MAC = false;
    -  goog.userAgent.WINDOWS = true;
    -  goog.userAgent.LINUX = false;
    -  goog.userAgent.VERSION = 9;
    -  goog.userAgent.DOCUMENT_MODE = 9;
    -  goog.events.KeyHandler.USES_KEYDOWN_ = true;
    -
    -  var keyEvent, keyHandler = new goog.events.KeyHandler();
    -  goog.events.listen(keyHandler, goog.events.KeyHandler.EventType.KEY,
    -      function(e) { keyEvent = e; });
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.ENTER);
    -  fireKeyPress(keyHandler, goog.events.KeyCodes.ENTER);
    -  assertEquals('Enter should fire a key event with the keycode 13',
    -               goog.events.KeyCodes.ENTER,
    -               keyEvent.keyCode);
    -  assertEquals('Enter should fire a key event with the charcode 0',
    -               0,
    -               keyEvent.charCode);
    -}
    -
    -
    -/**
    - * Tests the key handler for the Gecko behavior.
    - */
    -function testGeckoStyleKeyHandling() {
    -  goog.userAgent.OPERA = false;
    -  goog.userAgent.IE = false;
    -  goog.userAgent.GECKO = true;
    -  goog.userAgent.WEBKIT = false;
    -  goog.userAgent.MAC = false;
    -  goog.userAgent.WINDOWS = true;
    -  goog.userAgent.LINUX = false;
    -  goog.events.KeyHandler.USES_KEYDOWN_ = false;
    -
    -  var keyEvent, keyHandler = new goog.events.KeyHandler();
    -  goog.events.listen(keyHandler, goog.events.KeyHandler.EventType.KEY,
    -      function(e) { keyEvent = e; });
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.ENTER);
    -  fireKeyPress(keyHandler, goog.events.KeyCodes.ENTER);
    -  assertEquals('Enter should fire a key event with the keycode 13',
    -               goog.events.KeyCodes.ENTER,
    -               keyEvent.keyCode);
    -  assertEquals('Enter should fire a key event with the charcode 0',
    -               0,
    -               keyEvent.charCode);
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.ESC);
    -  fireKeyPress(keyHandler, goog.events.KeyCodes.ESC);
    -  assertEquals('Esc should fire a key event with the keycode 27',
    -               goog.events.KeyCodes.ESC,
    -               keyEvent.keyCode);
    -  assertEquals('Esc should fire a key event with the charcode 0',
    -               0,
    -               keyEvent.charCode);
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.UP);
    -  fireKeyPress(keyHandler, goog.events.KeyCodes.UP);
    -  assertEquals('Up should fire a key event with the keycode 38',
    -               goog.events.KeyCodes.UP,
    -               keyEvent.keyCode);
    -  assertEquals('Up should fire a key event with the charcode 0',
    -               0,
    -               keyEvent.charCode);
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.SEVEN, undefined, undefined,
    -      undefined, undefined, true);
    -  fireKeyPress(keyHandler, undefined, 38, undefined, undefined, undefined,
    -      true);
    -  assertEquals('Shift+7 should fire a key event with the keycode 55',
    -               goog.events.KeyCodes.SEVEN,
    -               keyEvent.keyCode);
    -  assertEquals('Shift+7 should fire a key event with the charcode 38',
    -               38,
    -               keyEvent.charCode);
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.A);
    -  fireKeyPress(keyHandler, undefined, 97);
    -  assertEquals('Lower case a should fire a key event with the keycode 65',
    -               goog.events.KeyCodes.A,
    -               keyEvent.keyCode);
    -  assertEquals('Lower case a should fire a key event with the charcode 97',
    -               97,
    -               keyEvent.charCode);
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.A);
    -  fireKeyPress(keyHandler, undefined, 65);
    -  assertEquals('Upper case A should fire a key event with the keycode 65',
    -               goog.events.KeyCodes.A,
    -               keyEvent.keyCode);
    -  assertEquals('Upper case A should fire a key event with the charcode 65',
    -               65,
    -               keyEvent.charCode);
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.DELETE);
    -  fireKeyPress(keyHandler, goog.events.KeyCodes.DELETE);
    -  assertEquals('Delete should fire a key event with the keycode 46',
    -               goog.events.KeyCodes.DELETE,
    -               keyEvent.keyCode);
    -  assertEquals('Delete should fire a key event with the charcode 0',
    -               0,
    -               keyEvent.charCode);
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.PERIOD);
    -  fireKeyPress(keyHandler, undefined, 46);
    -  assertEquals('Period should fire a key event with the keycode 190',
    -               goog.events.KeyCodes.PERIOD,
    -               keyEvent.keyCode);
    -  assertEquals('Period should fire a key event with the charcode 46',
    -               46,
    -               keyEvent.charCode);
    -}
    -
    -
    -/**
    - * Tests the key handler for the Safari 3 behavior.
    - */
    -function testSafari3StyleKeyHandling() {
    -  goog.userAgent.OPERA = false;
    -  goog.userAgent.IE = false;
    -  goog.userAgent.GECKO = false;
    -  goog.userAgent.WEBKIT = true;
    -  goog.userAgent.MAC = true;
    -  goog.userAgent.WINDOWS = false;
    -  goog.userAgent.LINUX = false;
    -  goog.events.KeyHandler.USES_KEYDOWN_ = true;
    -  goog.userAgent.VERSION = 525.3;
    -
    -  var keyEvent, keyHandler = new goog.events.KeyHandler();
    -  // Make sure all events are caught while testing
    -  goog.events.listen(keyHandler, goog.events.KeyHandler.EventType.KEY,
    -      function(e) { keyEvent = e; });
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.ENTER);
    -  fireKeyPress(keyHandler, goog.events.KeyCodes.ENTER);
    -  assertEquals('Enter should fire a key event with the keycode 13',
    -               goog.events.KeyCodes.ENTER,
    -               keyEvent.keyCode);
    -  assertEquals('Enter should fire a key event with the charcode 0',
    -               0,
    -               keyEvent.charCode);
    -  fireKeyUp(keyHandler, goog.events.KeyCodes.ENTER);
    -
    -  // Add a listener to ensure that an extra ENTER event is not dispatched
    -  // by a subsequent keypress.
    -  var enterCheck = goog.events.listen(keyHandler,
    -      goog.events.KeyHandler.EventType.KEY,
    -      function(e) {
    -        assertNotEquals('Unexpected ENTER keypress dispatched',
    -            e.keyCode, goog.events.KeyCodes.ENTER);
    -      });
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.ESC);
    -  assertEquals('Esc should fire a key event with the keycode 27',
    -               goog.events.KeyCodes.ESC,
    -               keyEvent.keyCode);
    -  assertEquals('Esc should fire a key event with the charcode 0',
    -               0,
    -               keyEvent.charCode);
    -  fireKeyPress(keyHandler, goog.events.KeyCodes.ESC);
    -  goog.events.unlistenByKey(enterCheck);
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.UP);
    -  assertEquals('Up should fire a key event with the keycode 38',
    -               goog.events.KeyCodes.UP,
    -               keyEvent.keyCode);
    -  assertEquals('Up should fire a key event with the charcode 0',
    -               0,
    -               keyEvent.charCode);
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.SEVEN, undefined, undefined,
    -      undefined, undefined, true);
    -  fireKeyPress(keyHandler, 38, 38, undefined, undefined, undefined, true);
    -  assertEquals('Shift+7 should fire a key event with the keycode 55',
    -               goog.events.KeyCodes.SEVEN,
    -               keyEvent.keyCode);
    -  assertEquals('Shift+7 should fire a key event with the charcode 38',
    -               38,
    -               keyEvent.charCode);
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.A);
    -  fireKeyPress(keyHandler, 97, 97);
    -  assertEquals('Lower case a should fire a key event with the keycode 65',
    -               goog.events.KeyCodes.A,
    -               keyEvent.keyCode);
    -  assertEquals('Lower case a should fire a key event with the charcode 97',
    -               97,
    -               keyEvent.charCode);
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.A);
    -  fireKeyPress(keyHandler, 65, 65);
    -  assertEquals('Upper case A should fire a key event with the keycode 65',
    -               goog.events.KeyCodes.A,
    -               keyEvent.keyCode);
    -  assertEquals('Upper case A should fire a key event with the charcode 65',
    -               65,
    -               keyEvent.charCode);
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.CTRL);
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.A, null, null, true /*ctrl*/);
    -  assertEquals('A with control down should fire a key event',
    -               goog.events.KeyCodes.A,
    -               keyEvent.keyCode);
    -
    -  // Test that Alt-Tab outside the window doesn't break things.
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.ALT);
    -  keyEvent.keyCode = -1;  // Reset the event.
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.A);
    -  assertEquals('Should not have dispatched an Alt-A', -1, keyEvent.keyCode);
    -  fireKeyPress(keyHandler, 65, 65);
    -  assertEquals('Alt should be ignored since it isn\'t currently depressed',
    -               goog.events.KeyCodes.A,
    -               keyEvent.keyCode);
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.DELETE);
    -  assertEquals('Delete should fire a key event with the keycode 46',
    -               goog.events.KeyCodes.DELETE,
    -               keyEvent.keyCode);
    -  assertEquals('Delete should fire a key event with the charcode 0',
    -               0,
    -               keyEvent.charCode);
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.PERIOD);
    -  fireKeyPress(keyHandler, 46, 46);
    -  assertEquals('Period should fire a key event with the keycode 190',
    -               goog.events.KeyCodes.PERIOD,
    -               keyEvent.keyCode);
    -  assertEquals('Period should fire a key event with the charcode 46',
    -               46,
    -               keyEvent.charCode);
    -
    -  // Safari sends zero key code for non-latin characters.
    -  fireKeyDown(keyHandler, 0, 0);
    -  fireKeyPress(keyHandler, 1092, 1092);
    -  assertEquals('Cyrillic small letter "Ef" should fire a key event with ' +
    -                   'the keycode 0',
    -               0,
    -               keyEvent.keyCode);
    -  assertEquals('Cyrillic small letter "Ef" should fire a key event with ' +
    -                   'the charcode 1092',
    -               1092,
    -               keyEvent.charCode);
    -}
    -
    -
    -/**
    - * Tests the key handler for the Opera behavior.
    - */
    -function testOperaStyleKeyHandling() {
    -  goog.userAgent.OPERA = true;
    -  goog.userAgent.IE = false;
    -  goog.userAgent.GECKO = false;
    -  goog.userAgent.WEBKIT = false;
    -  goog.userAgent.MAC = false;
    -  goog.userAgent.WINDOWS = true;
    -  goog.userAgent.LINUX = false;
    -  goog.events.KeyHandler.USES_KEYDOWN_ = false;
    -
    -  var keyEvent, keyHandler = new goog.events.KeyHandler();
    -  goog.events.listen(keyHandler, goog.events.KeyHandler.EventType.KEY,
    -      function(e) { keyEvent = e; });
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.ENTER);
    -  fireKeyPress(keyHandler, goog.events.KeyCodes.ENTER);
    -  assertEquals('Enter should fire a key event with the keycode 13',
    -               goog.events.KeyCodes.ENTER,
    -               keyEvent.keyCode);
    -  assertEquals('Enter should fire a key event with the charcode 0',
    -               0,
    -               keyEvent.charCode);
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.ESC);
    -  fireKeyPress(keyHandler, goog.events.KeyCodes.ESC);
    -  assertEquals('Esc should fire a key event with the keycode 27',
    -               goog.events.KeyCodes.ESC,
    -               keyEvent.keyCode);
    -  assertEquals('Esc should fire a key event with the charcode 0',
    -               0,
    -               keyEvent.charCode);
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.UP);
    -  fireKeyPress(keyHandler, goog.events.KeyCodes.UP);
    -  assertEquals('Up should fire a key event with the keycode 38',
    -               goog.events.KeyCodes.UP,
    -               keyEvent.keyCode);
    -  assertEquals('Up should fire a key event with the charcode 0',
    -               0,
    -               keyEvent.charCode);
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.SEVEN, undefined, undefined,
    -      undefined, undefined, true);
    -  fireKeyPress(keyHandler, 38, undefined, undefined, undefined, undefined,
    -      true);
    -  assertEquals('Shift+7 should fire a key event with the keycode 55',
    -               goog.events.KeyCodes.SEVEN,
    -               keyEvent.keyCode);
    -  assertEquals('Shift+7 should fire a key event with the charcode 38',
    -               38,
    -               keyEvent.charCode);
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.A);
    -  fireKeyPress(keyHandler, 97);
    -  assertEquals('Lower case a should fire a key event with the keycode 65',
    -               goog.events.KeyCodes.A,
    -               keyEvent.keyCode);
    -  assertEquals('Lower case a should fire a key event with the charcode 97',
    -               97,
    -               keyEvent.charCode);
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.A);
    -  fireKeyPress(keyHandler, 65);
    -  assertEquals('Upper case A should fire a key event with the keycode 65',
    -               goog.events.KeyCodes.A,
    -               keyEvent.keyCode);
    -  assertEquals('Upper case A should fire a key event with the charcode 65',
    -               65,
    -               keyEvent.charCode);
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.DELETE);
    -  fireKeyPress(keyHandler, goog.events.KeyCodes.DELETE);
    -  assertEquals('Delete should fire a key event with the keycode 46',
    -               goog.events.KeyCodes.DELETE,
    -               keyEvent.keyCode);
    -  assertEquals('Delete should fire a key event with the charcode 0',
    -               0,
    -               keyEvent.charCode);
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.PERIOD);
    -  fireKeyPress(keyHandler, 46);
    -  assertEquals('Period should fire a key event with the keycode 190',
    -               goog.events.KeyCodes.PERIOD,
    -               keyEvent.keyCode);
    -  assertEquals('Period should fire a key event with the charcode 46',
    -               46,
    -               keyEvent.charCode);
    -}
    -
    -function testGeckoOnMacAltHandling() {
    -  goog.userAgent.OPERA = false;
    -  goog.userAgent.IE = false;
    -  goog.userAgent.GECKO = true;
    -  goog.userAgent.WEBKIT = false;
    -  goog.userAgent.MAC = true;
    -  goog.userAgent.WINDOWS = false;
    -  goog.userAgent.LINUX = false;
    -  goog.events.KeyHandler.SAVE_ALT_FOR_KEYPRESS_ = true;
    -
    -  var keyEvent, keyHandler = new goog.events.KeyHandler();
    -  goog.events.listen(keyHandler, goog.events.KeyHandler.EventType.KEY,
    -      function(e) { keyEvent = e; });
    -
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.COMMA, 0, null, false,
    -      true, false);
    -  fireKeyPress(keyHandler, 0, 8804, null, false, false, false);
    -  assertEquals('should fire a key event with COMMA',
    -      goog.events.KeyCodes.COMMA,
    -      keyEvent.keyCode);
    -  assertEquals('should fire a key event with alt key set',
    -      true,
    -      keyEvent.altKey);
    -
    -  // Scenario: alt down, a down, a press, a up (should say alt is true),
    -  // alt up.
    -  keyEvent = undefined;
    -  fireKeyDown(keyHandler, 18, 0, null, false, true, false);
    -  fireKeyDown(keyHandler, goog.events.KeyCodes.A, 0, null, false, true,
    -      false);
    -  fireKeyPress(keyHandler, 0, 229, null, false, false, false);
    -  assertEquals('should fire a key event with alt key set',
    -      true,
    -      keyEvent.altKey);
    -  fireKeyUp(keyHandler, 0, 229, null, false, true, false);
    -  assertEquals('alt key should still be set',
    -      true,
    -      keyEvent.altKey);
    -  fireKeyUp(keyHandler, 18, 0, null, false, false, false);
    -}
    -
    -function testGeckoEqualSign() {
    -  goog.userAgent.OPERA = false;
    -  goog.userAgent.IE = false;
    -  goog.userAgent.GECKO = true;
    -  goog.userAgent.WEBKIT = false;
    -  goog.userAgent.MAC = false;
    -  goog.userAgent.WINDOWS = true;
    -  goog.userAgent.LINUX = false;
    -  goog.events.KeyHandler.USES_KEYDOWN_ = false;
    -
    -  var keyEvent, keyHandler = new goog.events.KeyHandler();
    -  goog.events.listen(keyHandler, goog.events.KeyHandler.EventType.KEY,
    -      function(e) { keyEvent = e; });
    -
    -  fireKeyDown(keyHandler, 61, 0);
    -  fireKeyPress(keyHandler, 0, 61);
    -  assertEquals('= should fire should fire a key event with the keyCode 187',
    -               goog.events.KeyCodes.EQUALS,
    -               keyEvent.keyCode);
    -  assertEquals('= should fire a key event with the charCode 61',
    -               goog.events.KeyCodes.FF_EQUALS,
    -               keyEvent.charCode);
    -}
    -
    -function testMacGeckoSlash() {
    -  goog.userAgent.OPERA = false;
    -  goog.userAgent.IE = false;
    -  goog.userAgent.GECKO = true;
    -  goog.userAgent.WEBKIT = false;
    -  goog.userAgent.MAC = true;
    -  goog.userAgent.WINDOWS = false;
    -  goog.userAgent.LINUX = false;
    -  goog.events.KeyHandler.USES_KEYDOWN_ = false;
    -
    -  var keyEvent, keyHandler = new goog.events.KeyHandler();
    -  goog.events.listen(keyHandler, goog.events.KeyHandler.EventType.KEY,
    -      function(e) { keyEvent = e; });
    -
    -  fireKeyDown(keyHandler, 0, 63, null, false, false, true);
    -  fireKeyPress(keyHandler, 0, 63, null, false, false, true);
    -  assertEquals('/ should fire a key event with the keyCode 191',
    -               goog.events.KeyCodes.SLASH,
    -               keyEvent.keyCode);
    -  assertEquals('? should fire a key event with the charCode 63',
    -               goog.events.KeyCodes.QUESTION_MARK,
    -               keyEvent.charCode);
    -}
    -
    -function testGetElement() {
    -  var target = goog.dom.createDom('div');
    -  var target2 = goog.dom.createDom('div');
    -  var keyHandler = new goog.events.KeyHandler();
    -  assertNull(keyHandler.getElement());
    -
    -  keyHandler.attach(target);
    -  assertEquals(target, keyHandler.getElement());
    -
    -  keyHandler.attach(target2);
    -  assertNotEquals(target, keyHandler.getElement());
    -  assertEquals(target2, keyHandler.getElement());
    -
    -  var doc = goog.dom.getDocument();
    -  keyHandler.attach(doc);
    -  assertEquals(doc, keyHandler.getElement());
    -
    -  keyHandler = new goog.events.KeyHandler(doc);
    -  assertEquals(doc, keyHandler.getElement());
    -
    -  keyHandler = new goog.events.KeyHandler(target);
    -  assertEquals(target, keyHandler.getElement());
    -}
    -
    -function testDetach() {
    -  var target = goog.dom.createDom('div');
    -  var keyHandler = new goog.events.KeyHandler(target);
    -  assertEquals(target, keyHandler.getElement());
    -
    -  fireKeyDown(keyHandler, 0, 63, null, false, false, true);
    -  fireKeyPress(keyHandler, 0, 63, null, false, false, true);
    -  keyHandler.detach();
    -
    -  assertNull(keyHandler.getElement());
    -  // All listeners should be cleared.
    -  assertNull(keyHandler.keyDownKey_);
    -  assertNull(keyHandler.keyPressKey_);
    -  assertNull(keyHandler.keyUpKey_);
    -  // All key related state should be cleared.
    -  assertEquals('Last key should be -1', -1, keyHandler.lastKey_);
    -  assertEquals('keycode should be -1', -1, keyHandler.keyCode_);
    -}
    -
    -function testCapturePhase() {
    -  var gotInCapturePhase;
    -  var gotInBubblePhase;
    -
    -  var target = goog.dom.createDom('div');
    -  goog.events.listen(
    -      new goog.events.KeyHandler(target, false /* bubble */),
    -      goog.events.KeyHandler.EventType.KEY,
    -      function() {
    -        gotInBubblePhase = true;
    -        assertTrue(gotInCapturePhase);
    -      });
    -  goog.events.listen(
    -      new goog.events.KeyHandler(target, true /* capture */),
    -      goog.events.KeyHandler.EventType.KEY,
    -      function() {
    -        gotInCapturePhase = true;
    -      });
    -
    -  goog.testing.events.fireKeySequence(target, goog.events.KeyCodes.ESC);
    -  assertTrue(gotInBubblePhase);
    -}
    -
    -function fireKeyDown(keyHandler, keyCode, opt_charCode, opt_keyIdentifier,
    -    opt_ctrlKey, opt_altKey, opt_shiftKey) {
    -  var fakeEvent = createFakeKeyEvent(
    -      goog.events.EventType.KEYDOWN, keyCode, opt_charCode, opt_keyIdentifier,
    -      opt_ctrlKey, opt_altKey, opt_shiftKey);
    -  keyHandler.handleKeyDown_(fakeEvent);
    -  return fakeEvent.returnValue_;
    -}
    -
    -function fireKeyPress(keyHandler, keyCode, opt_charCode, opt_keyIdentifier,
    -    opt_ctrlKey, opt_altKey, opt_shiftKey) {
    -  var fakeEvent = createFakeKeyEvent(
    -      goog.events.EventType.KEYPRESS, keyCode, opt_charCode,
    -      opt_keyIdentifier, opt_ctrlKey, opt_altKey, opt_shiftKey);
    -  keyHandler.handleEvent(fakeEvent);
    -  return fakeEvent.returnValue_;
    -}
    -
    -function fireKeyUp(keyHandler, keyCode, opt_charCode, opt_keyIdentifier,
    -    opt_ctrlKey, opt_altKey, opt_shiftKey) {
    -  var fakeEvent = createFakeKeyEvent(
    -      goog.events.EventType.KEYUP, keyCode, opt_charCode,
    -      opt_keyIdentifier, opt_ctrlKey, opt_altKey, opt_shiftKey);
    -  keyHandler.handleKeyup_(fakeEvent);
    -  return fakeEvent.returnValue_;
    -}
    -
    -function createFakeKeyEvent(type, keyCode, opt_charCode, opt_keyIdentifier,
    -    opt_ctrlKey, opt_altKey, opt_shiftKey) {
    -  var event = {
    -    type: type,
    -    keyCode: keyCode,
    -    charCode: opt_charCode || undefined,
    -    keyIdentifier: opt_keyIdentifier || undefined,
    -    ctrlKey: opt_ctrlKey || false,
    -    altKey: opt_altKey || false,
    -    shiftKey: opt_shiftKey || false,
    -    timeStamp: goog.now()
    -  };
    -  return new goog.events.BrowserEvent(event);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/events/keynames.js b/src/database/third_party/closure-library/closure/goog/events/keynames.js
    deleted file mode 100644
    index b8e36af0ba6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/keynames.js
    +++ /dev/null
    @@ -1,139 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Constant declarations for common key codes.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - */
    -
    -goog.provide('goog.events.KeyNames');
    -
    -
    -/**
    - * Key names for common characters. These should be used with keyup/keydown
    - * events, since the .keyCode property on those is meant to indicate the
    - * *physical key* the user held down on the keyboard. Hence the mapping uses
    - * only the unshifted version of each key (e.g. no '#', since that's shift+3).
    - * Keypress events on the other hand generate (mostly) ASCII codes since they
    - * correspond to *characters* the user typed.
    - *
    - * For further reference: http://unixpapa.com/js/key.html
    - *
    - * This list is not localized and therefore some of the key codes are not
    - * correct for non-US keyboard layouts.
    - *
    - * @see goog.events.KeyCodes
    - * @enum {string}
    - */
    -goog.events.KeyNames = {
    -  8: 'backspace',
    -  9: 'tab',
    -  13: 'enter',
    -  16: 'shift',
    -  17: 'ctrl',
    -  18: 'alt',
    -  19: 'pause',
    -  20: 'caps-lock',
    -  27: 'esc',
    -  32: 'space',
    -  33: 'pg-up',
    -  34: 'pg-down',
    -  35: 'end',
    -  36: 'home',
    -  37: 'left',
    -  38: 'up',
    -  39: 'right',
    -  40: 'down',
    -  45: 'insert',
    -  46: 'delete',
    -  48: '0',
    -  49: '1',
    -  50: '2',
    -  51: '3',
    -  52: '4',
    -  53: '5',
    -  54: '6',
    -  55: '7',
    -  56: '8',
    -  57: '9',
    -  59: 'semicolon',
    -  61: 'equals',
    -  65: 'a',
    -  66: 'b',
    -  67: 'c',
    -  68: 'd',
    -  69: 'e',
    -  70: 'f',
    -  71: 'g',
    -  72: 'h',
    -  73: 'i',
    -  74: 'j',
    -  75: 'k',
    -  76: 'l',
    -  77: 'm',
    -  78: 'n',
    -  79: 'o',
    -  80: 'p',
    -  81: 'q',
    -  82: 'r',
    -  83: 's',
    -  84: 't',
    -  85: 'u',
    -  86: 'v',
    -  87: 'w',
    -  88: 'x',
    -  89: 'y',
    -  90: 'z',
    -  93: 'context',
    -  96: 'num-0',
    -  97: 'num-1',
    -  98: 'num-2',
    -  99: 'num-3',
    -  100: 'num-4',
    -  101: 'num-5',
    -  102: 'num-6',
    -  103: 'num-7',
    -  104: 'num-8',
    -  105: 'num-9',
    -  106: 'num-multiply',
    -  107: 'num-plus',
    -  109: 'num-minus',
    -  110: 'num-period',
    -  111: 'num-division',
    -  112: 'f1',
    -  113: 'f2',
    -  114: 'f3',
    -  115: 'f4',
    -  116: 'f5',
    -  117: 'f6',
    -  118: 'f7',
    -  119: 'f8',
    -  120: 'f9',
    -  121: 'f10',
    -  122: 'f11',
    -  123: 'f12',
    -  186: 'semicolon',
    -  187: 'equals',
    -  189: 'dash',
    -  188: ',',
    -  190: '.',
    -  191: '/',
    -  192: '`',
    -  219: 'open-square-bracket',
    -  220: '\\',
    -  221: 'close-square-bracket',
    -  222: 'single-quote',
    -  224: 'win'
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/events/listenable.js b/src/database/third_party/closure-library/closure/goog/events/listenable.js
    deleted file mode 100644
    index a05b348275f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/listenable.js
    +++ /dev/null
    @@ -1,335 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview An interface for a listenable JavaScript object.
    - * @author chrishenry@google.com (Chris Henry)
    - */
    -
    -goog.provide('goog.events.Listenable');
    -goog.provide('goog.events.ListenableKey');
    -
    -/** @suppress {extraRequire} */
    -goog.require('goog.events.EventId');
    -
    -
    -
    -/**
    - * A listenable interface. A listenable is an object with the ability
    - * to dispatch/broadcast events to "event listeners" registered via
    - * listen/listenOnce.
    - *
    - * The interface allows for an event propagation mechanism similar
    - * to one offered by native browser event targets, such as
    - * capture/bubble mechanism, stopping propagation, and preventing
    - * default actions. Capture/bubble mechanism depends on the ancestor
    - * tree constructed via {@code #getParentEventTarget}; this tree
    - * must be directed acyclic graph. The meaning of default action(s)
    - * in preventDefault is specific to a particular use case.
    - *
    - * Implementations that do not support capture/bubble or can not have
    - * a parent listenable can simply not implement any ability to set the
    - * parent listenable (and have {@code #getParentEventTarget} return
    - * null).
    - *
    - * Implementation of this class can be used with or independently from
    - * goog.events.
    - *
    - * Implementation must call {@code #addImplementation(implClass)}.
    - *
    - * @interface
    - * @see goog.events
    - * @see http://www.w3.org/TR/DOM-Level-2-Events/events.html
    - */
    -goog.events.Listenable = function() {};
    -
    -
    -/**
    - * An expando property to indicate that an object implements
    - * goog.events.Listenable.
    - *
    - * See addImplementation/isImplementedBy.
    - *
    - * @type {string}
    - * @const
    - */
    -goog.events.Listenable.IMPLEMENTED_BY_PROP =
    -    'closure_listenable_' + ((Math.random() * 1e6) | 0);
    -
    -
    -/**
    - * Marks a given class (constructor) as an implementation of
    - * Listenable, do that we can query that fact at runtime. The class
    - * must have already implemented the interface.
    - * @param {!Function} cls The class constructor. The corresponding
    - *     class must have already implemented the interface.
    - */
    -goog.events.Listenable.addImplementation = function(cls) {
    -  cls.prototype[goog.events.Listenable.IMPLEMENTED_BY_PROP] = true;
    -};
    -
    -
    -/**
    - * @param {Object} obj The object to check.
    - * @return {boolean} Whether a given instance implements Listenable. The
    - *     class/superclass of the instance must call addImplementation.
    - */
    -goog.events.Listenable.isImplementedBy = function(obj) {
    -  return !!(obj && obj[goog.events.Listenable.IMPLEMENTED_BY_PROP]);
    -};
    -
    -
    -/**
    - * Adds an event listener. A listener can only be added once to an
    - * object and if it is added again the key for the listener is
    - * returned. Note that if the existing listener is a one-off listener
    - * (registered via listenOnce), it will no longer be a one-off
    - * listener after a call to listen().
    - *
    - * @param {string|!goog.events.EventId<EVENTOBJ>} type The event type id.
    - * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener Callback
    - *     method.
    - * @param {boolean=} opt_useCapture Whether to fire in capture phase
    - *     (defaults to false).
    - * @param {SCOPE=} opt_listenerScope Object in whose scope to call the
    - *     listener.
    - * @return {goog.events.ListenableKey} Unique key for the listener.
    - * @template SCOPE,EVENTOBJ
    - */
    -goog.events.Listenable.prototype.listen;
    -
    -
    -/**
    - * Adds an event listener that is removed automatically after the
    - * listener fired once.
    - *
    - * If an existing listener already exists, listenOnce will do
    - * nothing. In particular, if the listener was previously registered
    - * via listen(), listenOnce() will not turn the listener into a
    - * one-off listener. Similarly, if there is already an existing
    - * one-off listener, listenOnce does not modify the listeners (it is
    - * still a once listener).
    - *
    - * @param {string|!goog.events.EventId<EVENTOBJ>} type The event type id.
    - * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener Callback
    - *     method.
    - * @param {boolean=} opt_useCapture Whether to fire in capture phase
    - *     (defaults to false).
    - * @param {SCOPE=} opt_listenerScope Object in whose scope to call the
    - *     listener.
    - * @return {goog.events.ListenableKey} Unique key for the listener.
    - * @template SCOPE,EVENTOBJ
    - */
    -goog.events.Listenable.prototype.listenOnce;
    -
    -
    -/**
    - * Removes an event listener which was added with listen() or listenOnce().
    - *
    - * @param {string|!goog.events.EventId<EVENTOBJ>} type The event type id.
    - * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener Callback
    - *     method.
    - * @param {boolean=} opt_useCapture Whether to fire in capture phase
    - *     (defaults to false).
    - * @param {SCOPE=} opt_listenerScope Object in whose scope to call
    - *     the listener.
    - * @return {boolean} Whether any listener was removed.
    - * @template SCOPE,EVENTOBJ
    - */
    -goog.events.Listenable.prototype.unlisten;
    -
    -
    -/**
    - * Removes an event listener which was added with listen() by the key
    - * returned by listen().
    - *
    - * @param {goog.events.ListenableKey} key The key returned by
    - *     listen() or listenOnce().
    - * @return {boolean} Whether any listener was removed.
    - */
    -goog.events.Listenable.prototype.unlistenByKey;
    -
    -
    -/**
    - * Dispatches an event (or event like object) and calls all listeners
    - * listening for events of this type. The type of the event is decided by the
    - * type property on the event object.
    - *
    - * If any of the listeners returns false OR calls preventDefault then this
    - * function will return false.  If one of the capture listeners calls
    - * stopPropagation, then the bubble listeners won't fire.
    - *
    - * @param {goog.events.EventLike} e Event object.
    - * @return {boolean} If anyone called preventDefault on the event object (or
    - *     if any of the listeners returns false) this will also return false.
    - */
    -goog.events.Listenable.prototype.dispatchEvent;
    -
    -
    -/**
    - * Removes all listeners from this listenable. If type is specified,
    - * it will only remove listeners of the particular type. otherwise all
    - * registered listeners will be removed.
    - *
    - * @param {string=} opt_type Type of event to remove, default is to
    - *     remove all types.
    - * @return {number} Number of listeners removed.
    - */
    -goog.events.Listenable.prototype.removeAllListeners;
    -
    -
    -/**
    - * Returns the parent of this event target to use for capture/bubble
    - * mechanism.
    - *
    - * NOTE(chrishenry): The name reflects the original implementation of
    - * custom event target ({@code goog.events.EventTarget}). We decided
    - * that changing the name is not worth it.
    - *
    - * @return {goog.events.Listenable} The parent EventTarget or null if
    - *     there is no parent.
    - */
    -goog.events.Listenable.prototype.getParentEventTarget;
    -
    -
    -/**
    - * Fires all registered listeners in this listenable for the given
    - * type and capture mode, passing them the given eventObject. This
    - * does not perform actual capture/bubble. Only implementors of the
    - * interface should be using this.
    - *
    - * @param {string|!goog.events.EventId<EVENTOBJ>} type The type of the
    - *     listeners to fire.
    - * @param {boolean} capture The capture mode of the listeners to fire.
    - * @param {EVENTOBJ} eventObject The event object to fire.
    - * @return {boolean} Whether all listeners succeeded without
    - *     attempting to prevent default behavior. If any listener returns
    - *     false or called goog.events.Event#preventDefault, this returns
    - *     false.
    - * @template EVENTOBJ
    - */
    -goog.events.Listenable.prototype.fireListeners;
    -
    -
    -/**
    - * Gets all listeners in this listenable for the given type and
    - * capture mode.
    - *
    - * @param {string|!goog.events.EventId} type The type of the listeners to fire.
    - * @param {boolean} capture The capture mode of the listeners to fire.
    - * @return {!Array<goog.events.ListenableKey>} An array of registered
    - *     listeners.
    - * @template EVENTOBJ
    - */
    -goog.events.Listenable.prototype.getListeners;
    -
    -
    -/**
    - * Gets the goog.events.ListenableKey for the event or null if no such
    - * listener is in use.
    - *
    - * @param {string|!goog.events.EventId<EVENTOBJ>} type The name of the event
    - *     without the 'on' prefix.
    - * @param {function(this:SCOPE, EVENTOBJ):(boolean|undefined)} listener The
    - *     listener function to get.
    - * @param {boolean} capture Whether the listener is a capturing listener.
    - * @param {SCOPE=} opt_listenerScope Object in whose scope to call the
    - *     listener.
    - * @return {goog.events.ListenableKey} the found listener or null if not found.
    - * @template SCOPE,EVENTOBJ
    - */
    -goog.events.Listenable.prototype.getListener;
    -
    -
    -/**
    - * Whether there is any active listeners matching the specified
    - * signature. If either the type or capture parameters are
    - * unspecified, the function will match on the remaining criteria.
    - *
    - * @param {string|!goog.events.EventId<EVENTOBJ>=} opt_type Event type.
    - * @param {boolean=} opt_capture Whether to check for capture or bubble
    - *     listeners.
    - * @return {boolean} Whether there is any active listeners matching
    - *     the requested type and/or capture phase.
    - * @template EVENTOBJ
    - */
    -goog.events.Listenable.prototype.hasListener;
    -
    -
    -
    -/**
    - * An interface that describes a single registered listener.
    - * @interface
    - */
    -goog.events.ListenableKey = function() {};
    -
    -
    -/**
    - * Counter used to create a unique key
    - * @type {number}
    - * @private
    - */
    -goog.events.ListenableKey.counter_ = 0;
    -
    -
    -/**
    - * Reserves a key to be used for ListenableKey#key field.
    - * @return {number} A number to be used to fill ListenableKey#key
    - *     field.
    - */
    -goog.events.ListenableKey.reserveKey = function() {
    -  return ++goog.events.ListenableKey.counter_;
    -};
    -
    -
    -/**
    - * The source event target.
    - * @type {!(Object|goog.events.Listenable|goog.events.EventTarget)}
    - */
    -goog.events.ListenableKey.prototype.src;
    -
    -
    -/**
    - * The event type the listener is listening to.
    - * @type {string}
    - */
    -goog.events.ListenableKey.prototype.type;
    -
    -
    -/**
    - * The listener function.
    - * @type {function(?):?|{handleEvent:function(?):?}|null}
    - */
    -goog.events.ListenableKey.prototype.listener;
    -
    -
    -/**
    - * Whether the listener works on capture phase.
    - * @type {boolean}
    - */
    -goog.events.ListenableKey.prototype.capture;
    -
    -
    -/**
    - * The 'this' object for the listener function's scope.
    - * @type {Object}
    - */
    -goog.events.ListenableKey.prototype.handler;
    -
    -
    -/**
    - * A globally unique number to identify the key.
    - * @type {number}
    - */
    -goog.events.ListenableKey.prototype.key;
    diff --git a/src/database/third_party/closure-library/closure/goog/events/listenable_test.html b/src/database/third_party/closure-library/closure/goog/events/listenable_test.html
    deleted file mode 100644
    index 55307ab7158..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/listenable_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.events.Listenable
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.events.ListenableTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/events/listenable_test.js b/src/database/third_party/closure-library/closure/goog/events/listenable_test.js
    deleted file mode 100644
    index 538fb78d933..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/listenable_test.js
    +++ /dev/null
    @@ -1,29 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.events.ListenableTest');
    -goog.setTestOnly('goog.events.ListenableTest');
    -
    -goog.require('goog.events.Listenable');
    -goog.require('goog.testing.jsunit');
    -
    -function testIsImplementedBy() {
    -  var ListenableClass = function() {};
    -  goog.events.Listenable.addImplementation(ListenableClass);
    -
    -  var NonListenableClass = function() {};
    -
    -  assertTrue(goog.events.Listenable.isImplementedBy(new ListenableClass()));
    -  assertFalse(goog.events.Listenable.isImplementedBy(new NonListenableClass()));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/events/listener.js b/src/database/third_party/closure-library/closure/goog/events/listener.js
    deleted file mode 100644
    index 60c737021b6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/listener.js
    +++ /dev/null
    @@ -1,131 +0,0 @@
    -// Copyright 2005 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Listener object.
    - * @see ../demos/events.html
    - */
    -
    -goog.provide('goog.events.Listener');
    -
    -goog.require('goog.events.ListenableKey');
    -
    -
    -
    -/**
    - * Simple class that stores information about a listener
    - * @param {!Function} listener Callback function.
    - * @param {Function} proxy Wrapper for the listener that patches the event.
    - * @param {EventTarget|goog.events.Listenable} src Source object for
    - *     the event.
    - * @param {string} type Event type.
    - * @param {boolean} capture Whether in capture or bubble phase.
    - * @param {Object=} opt_handler Object in whose context to execute the callback.
    - * @implements {goog.events.ListenableKey}
    - * @constructor
    - */
    -goog.events.Listener = function(
    -    listener, proxy, src, type, capture, opt_handler) {
    -  if (goog.events.Listener.ENABLE_MONITORING) {
    -    this.creationStack = new Error().stack;
    -  }
    -
    -  /**
    -   * Callback function.
    -   * @type {Function}
    -   */
    -  this.listener = listener;
    -
    -  /**
    -   * A wrapper over the original listener. This is used solely to
    -   * handle native browser events (it is used to simulate the capture
    -   * phase and to patch the event object).
    -   * @type {Function}
    -   */
    -  this.proxy = proxy;
    -
    -  /**
    -   * Object or node that callback is listening to
    -   * @type {EventTarget|goog.events.Listenable}
    -   */
    -  this.src = src;
    -
    -  /**
    -   * The event type.
    -   * @const {string}
    -   */
    -  this.type = type;
    -
    -  /**
    -   * Whether the listener is being called in the capture or bubble phase
    -   * @const {boolean}
    -   */
    -  this.capture = !!capture;
    -
    -  /**
    -   * Optional object whose context to execute the listener in
    -   * @type {Object|undefined}
    -   */
    -  this.handler = opt_handler;
    -
    -  /**
    -   * The key of the listener.
    -   * @const {number}
    -   * @override
    -   */
    -  this.key = goog.events.ListenableKey.reserveKey();
    -
    -  /**
    -   * Whether to remove the listener after it has been called.
    -   * @type {boolean}
    -   */
    -  this.callOnce = false;
    -
    -  /**
    -   * Whether the listener has been removed.
    -   * @type {boolean}
    -   */
    -  this.removed = false;
    -};
    -
    -
    -/**
    - * @define {boolean} Whether to enable the monitoring of the
    - *     goog.events.Listener instances. Switching on the monitoring is only
    - *     recommended for debugging because it has a significant impact on
    - *     performance and memory usage. If switched off, the monitoring code
    - *     compiles down to 0 bytes.
    - */
    -goog.define('goog.events.Listener.ENABLE_MONITORING', false);
    -
    -
    -/**
    - * If monitoring the goog.events.Listener instances is enabled, stores the
    - * creation stack trace of the Disposable instance.
    - * @type {string}
    - */
    -goog.events.Listener.prototype.creationStack;
    -
    -
    -/**
    - * Marks this listener as removed. This also remove references held by
    - * this listener object (such as listener and event source).
    - */
    -goog.events.Listener.prototype.markAsRemoved = function() {
    -  this.removed = true;
    -  this.listener = null;
    -  this.proxy = null;
    -  this.src = null;
    -  this.handler = null;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/events/listenermap.js b/src/database/third_party/closure-library/closure/goog/events/listenermap.js
    deleted file mode 100644
    index c20cdb97380..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/listenermap.js
    +++ /dev/null
    @@ -1,308 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A map of listeners that provides utility functions to
    - * deal with listeners on an event target. Used by
    - * {@code goog.events.EventTarget}.
    - *
    - * WARNING: Do not use this class from outside goog.events package.
    - *
    - * @visibility {//closure/goog/bin/sizetests:__pkg__}
    - * @visibility {//closure/goog/events:__pkg__}
    - * @visibility {//closure/goog/labs/events:__pkg__}
    - */
    -
    -goog.provide('goog.events.ListenerMap');
    -
    -goog.require('goog.array');
    -goog.require('goog.events.Listener');
    -goog.require('goog.object');
    -
    -
    -
    -/**
    - * Creates a new listener map.
    - * @param {EventTarget|goog.events.Listenable} src The src object.
    - * @constructor
    - * @final
    - */
    -goog.events.ListenerMap = function(src) {
    -  /** @type {EventTarget|goog.events.Listenable} */
    -  this.src = src;
    -
    -  /**
    -   * Maps of event type to an array of listeners.
    -   * @type {Object<string, !Array<!goog.events.Listener>>}
    -   */
    -  this.listeners = {};
    -
    -  /**
    -   * The count of types in this map that have registered listeners.
    -   * @private {number}
    -   */
    -  this.typeCount_ = 0;
    -};
    -
    -
    -/**
    - * @return {number} The count of event types in this map that actually
    - *     have registered listeners.
    - */
    -goog.events.ListenerMap.prototype.getTypeCount = function() {
    -  return this.typeCount_;
    -};
    -
    -
    -/**
    - * @return {number} Total number of registered listeners.
    - */
    -goog.events.ListenerMap.prototype.getListenerCount = function() {
    -  var count = 0;
    -  for (var type in this.listeners) {
    -    count += this.listeners[type].length;
    -  }
    -  return count;
    -};
    -
    -
    -/**
    - * Adds an event listener. A listener can only be added once to an
    - * object and if it is added again the key for the listener is
    - * returned.
    - *
    - * Note that a one-off listener will not change an existing listener,
    - * if any. On the other hand a normal listener will change existing
    - * one-off listener to become a normal listener.
    - *
    - * @param {string|!goog.events.EventId} type The listener event type.
    - * @param {!Function} listener This listener callback method.
    - * @param {boolean} callOnce Whether the listener is a one-off
    - *     listener.
    - * @param {boolean=} opt_useCapture The capture mode of the listener.
    - * @param {Object=} opt_listenerScope Object in whose scope to call the
    - *     listener.
    - * @return {goog.events.ListenableKey} Unique key for the listener.
    - */
    -goog.events.ListenerMap.prototype.add = function(
    -    type, listener, callOnce, opt_useCapture, opt_listenerScope) {
    -  var typeStr = type.toString();
    -  var listenerArray = this.listeners[typeStr];
    -  if (!listenerArray) {
    -    listenerArray = this.listeners[typeStr] = [];
    -    this.typeCount_++;
    -  }
    -
    -  var listenerObj;
    -  var index = goog.events.ListenerMap.findListenerIndex_(
    -      listenerArray, listener, opt_useCapture, opt_listenerScope);
    -  if (index > -1) {
    -    listenerObj = listenerArray[index];
    -    if (!callOnce) {
    -      // Ensure that, if there is an existing callOnce listener, it is no
    -      // longer a callOnce listener.
    -      listenerObj.callOnce = false;
    -    }
    -  } else {
    -    listenerObj = new goog.events.Listener(
    -        listener, null, this.src, typeStr, !!opt_useCapture, opt_listenerScope);
    -    listenerObj.callOnce = callOnce;
    -    listenerArray.push(listenerObj);
    -  }
    -  return listenerObj;
    -};
    -
    -
    -/**
    - * Removes a matching listener.
    - * @param {string|!goog.events.EventId} type The listener event type.
    - * @param {!Function} listener This listener callback method.
    - * @param {boolean=} opt_useCapture The capture mode of the listener.
    - * @param {Object=} opt_listenerScope Object in whose scope to call the
    - *     listener.
    - * @return {boolean} Whether any listener was removed.
    - */
    -goog.events.ListenerMap.prototype.remove = function(
    -    type, listener, opt_useCapture, opt_listenerScope) {
    -  var typeStr = type.toString();
    -  if (!(typeStr in this.listeners)) {
    -    return false;
    -  }
    -
    -  var listenerArray = this.listeners[typeStr];
    -  var index = goog.events.ListenerMap.findListenerIndex_(
    -      listenerArray, listener, opt_useCapture, opt_listenerScope);
    -  if (index > -1) {
    -    var listenerObj = listenerArray[index];
    -    listenerObj.markAsRemoved();
    -    goog.array.removeAt(listenerArray, index);
    -    if (listenerArray.length == 0) {
    -      delete this.listeners[typeStr];
    -      this.typeCount_--;
    -    }
    -    return true;
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Removes the given listener object.
    - * @param {goog.events.ListenableKey} listener The listener to remove.
    - * @return {boolean} Whether the listener is removed.
    - */
    -goog.events.ListenerMap.prototype.removeByKey = function(listener) {
    -  var type = listener.type;
    -  if (!(type in this.listeners)) {
    -    return false;
    -  }
    -
    -  var removed = goog.array.remove(this.listeners[type], listener);
    -  if (removed) {
    -    listener.markAsRemoved();
    -    if (this.listeners[type].length == 0) {
    -      delete this.listeners[type];
    -      this.typeCount_--;
    -    }
    -  }
    -  return removed;
    -};
    -
    -
    -/**
    - * Removes all listeners from this map. If opt_type is provided, only
    - * listeners that match the given type are removed.
    - * @param {string|!goog.events.EventId=} opt_type Type of event to remove.
    - * @return {number} Number of listeners removed.
    - */
    -goog.events.ListenerMap.prototype.removeAll = function(opt_type) {
    -  var typeStr = opt_type && opt_type.toString();
    -  var count = 0;
    -  for (var type in this.listeners) {
    -    if (!typeStr || type == typeStr) {
    -      var listenerArray = this.listeners[type];
    -      for (var i = 0; i < listenerArray.length; i++) {
    -        ++count;
    -        listenerArray[i].markAsRemoved();
    -      }
    -      delete this.listeners[type];
    -      this.typeCount_--;
    -    }
    -  }
    -  return count;
    -};
    -
    -
    -/**
    - * Gets all listeners that match the given type and capture mode. The
    - * returned array is a copy (but the listener objects are not).
    - * @param {string|!goog.events.EventId} type The type of the listeners
    - *     to retrieve.
    - * @param {boolean} capture The capture mode of the listeners to retrieve.
    - * @return {!Array<goog.events.ListenableKey>} An array of matching
    - *     listeners.
    - */
    -goog.events.ListenerMap.prototype.getListeners = function(type, capture) {
    -  var listenerArray = this.listeners[type.toString()];
    -  var rv = [];
    -  if (listenerArray) {
    -    for (var i = 0; i < listenerArray.length; ++i) {
    -      var listenerObj = listenerArray[i];
    -      if (listenerObj.capture == capture) {
    -        rv.push(listenerObj);
    -      }
    -    }
    -  }
    -  return rv;
    -};
    -
    -
    -/**
    - * Gets the goog.events.ListenableKey for the event or null if no such
    - * listener is in use.
    - *
    - * @param {string|!goog.events.EventId} type The type of the listener
    - *     to retrieve.
    - * @param {!Function} listener The listener function to get.
    - * @param {boolean} capture Whether the listener is a capturing listener.
    - * @param {Object=} opt_listenerScope Object in whose scope to call the
    - *     listener.
    - * @return {goog.events.ListenableKey} the found listener or null if not found.
    - */
    -goog.events.ListenerMap.prototype.getListener = function(
    -    type, listener, capture, opt_listenerScope) {
    -  var listenerArray = this.listeners[type.toString()];
    -  var i = -1;
    -  if (listenerArray) {
    -    i = goog.events.ListenerMap.findListenerIndex_(
    -        listenerArray, listener, capture, opt_listenerScope);
    -  }
    -  return i > -1 ? listenerArray[i] : null;
    -};
    -
    -
    -/**
    - * Whether there is a matching listener. If either the type or capture
    - * parameters are unspecified, the function will match on the
    - * remaining criteria.
    - *
    - * @param {string|!goog.events.EventId=} opt_type The type of the listener.
    - * @param {boolean=} opt_capture The capture mode of the listener.
    - * @return {boolean} Whether there is an active listener matching
    - *     the requested type and/or capture phase.
    - */
    -goog.events.ListenerMap.prototype.hasListener = function(
    -    opt_type, opt_capture) {
    -  var hasType = goog.isDef(opt_type);
    -  var typeStr = hasType ? opt_type.toString() : '';
    -  var hasCapture = goog.isDef(opt_capture);
    -
    -  return goog.object.some(
    -      this.listeners, function(listenerArray, type) {
    -        for (var i = 0; i < listenerArray.length; ++i) {
    -          if ((!hasType || listenerArray[i].type == typeStr) &&
    -              (!hasCapture || listenerArray[i].capture == opt_capture)) {
    -            return true;
    -          }
    -        }
    -
    -        return false;
    -      });
    -};
    -
    -
    -/**
    - * Finds the index of a matching goog.events.Listener in the given
    - * listenerArray.
    - * @param {!Array<!goog.events.Listener>} listenerArray Array of listener.
    - * @param {!Function} listener The listener function.
    - * @param {boolean=} opt_useCapture The capture flag for the listener.
    - * @param {Object=} opt_listenerScope The listener scope.
    - * @return {number} The index of the matching listener within the
    - *     listenerArray.
    - * @private
    - */
    -goog.events.ListenerMap.findListenerIndex_ = function(
    -    listenerArray, listener, opt_useCapture, opt_listenerScope) {
    -  for (var i = 0; i < listenerArray.length; ++i) {
    -    var listenerObj = listenerArray[i];
    -    if (!listenerObj.removed &&
    -        listenerObj.listener == listener &&
    -        listenerObj.capture == !!opt_useCapture &&
    -        listenerObj.handler == opt_listenerScope) {
    -      return i;
    -    }
    -  }
    -  return -1;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/events/listenermap_test.html b/src/database/third_party/closure-library/closure/goog/events/listenermap_test.html
    deleted file mode 100644
    index 1f544697c03..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/listenermap_test.html
    +++ /dev/null
    @@ -1,19 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.events.ListenerMap</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.events.ListenerMapTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/events/listenermap_test.js b/src/database/third_party/closure-library/closure/goog/events/listenermap_test.js
    deleted file mode 100644
    index 73c6772fec7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/listenermap_test.js
    +++ /dev/null
    @@ -1,161 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Tests for listenermap.js.
    - *
    - * Most of this class functionality is already tested by
    - * goog.events.EventTarget tests. This test file only provides tests
    - * for features that are not direct duplicates of tests in
    - * goog.events.EventTarget.
    - */
    -
    -goog.provide('goog.events.ListenerMapTest');
    -goog.setTestOnly('goog.events.ListenerMapTest');
    -
    -goog.require('goog.dispose');
    -goog.require('goog.events');
    -goog.require('goog.events.EventId');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.ListenerMap');
    -goog.require('goog.testing.jsunit');
    -
    -
    -var et, map;
    -var handler1 = function() {};
    -var handler2 = function() {};
    -var handler3 = function() {};
    -var CLICK_EVENT_ID = new goog.events.EventId(goog.events.getUniqueId('click'));
    -
    -
    -function setUp() {
    -  et = new goog.events.EventTarget();
    -  map = new goog.events.ListenerMap(et);
    -}
    -
    -
    -function tearDown() {
    -  goog.dispose(et);
    -}
    -
    -
    -function testGetTypeCount() {
    -  assertEquals(0, map.getTypeCount());
    -
    -  map.add('click', handler1, false);
    -  assertEquals(1, map.getTypeCount());
    -  map.remove('click', handler1);
    -  assertEquals(0, map.getTypeCount());
    -
    -  map.add(CLICK_EVENT_ID, handler1, false);
    -  assertEquals(1, map.getTypeCount());
    -  map.remove(CLICK_EVENT_ID, handler1);
    -  assertEquals(0, map.getTypeCount());
    -
    -  map.add('click', handler1, false, true);
    -  assertEquals(1, map.getTypeCount());
    -  map.remove('click', handler1, true);
    -  assertEquals(0, map.getTypeCount());
    -
    -  map.add(CLICK_EVENT_ID, handler1, false, true);
    -  assertEquals(1, map.getTypeCount());
    -  map.remove(CLICK_EVENT_ID, handler1, true);
    -  assertEquals(0, map.getTypeCount());
    -
    -  map.add('click', handler1, false);
    -  map.add('click', handler1, false, true);
    -  assertEquals(1, map.getTypeCount());
    -  map.remove('click', handler1);
    -  assertEquals(1, map.getTypeCount());
    -  map.remove('click', handler1, true);
    -  assertEquals(0, map.getTypeCount());
    -
    -  map.add(CLICK_EVENT_ID, handler1, false);
    -  map.add(CLICK_EVENT_ID, handler1, false, true);
    -  assertEquals(1, map.getTypeCount());
    -  map.remove(CLICK_EVENT_ID, handler1);
    -  assertEquals(1, map.getTypeCount());
    -  map.remove(CLICK_EVENT_ID, handler1, true);
    -  assertEquals(0, map.getTypeCount());
    -
    -  map.add('click', handler1, false);
    -  map.add('touchstart', handler2, false);
    -  map.add(CLICK_EVENT_ID, handler3, false);
    -  assertEquals(3, map.getTypeCount());
    -  map.remove(CLICK_EVENT_ID, handler3);
    -  assertEquals(2, map.getTypeCount());
    -  map.remove('touchstart', handler2);
    -  assertEquals(1, map.getTypeCount());
    -  map.remove('click', handler1);
    -  assertEquals(0, map.getTypeCount());
    -}
    -
    -
    -function testGetListenerCount() {
    -  assertEquals(0, map.getListenerCount());
    -
    -  map.add('click', handler1, false);
    -  assertEquals(1, map.getListenerCount());
    -  map.remove('click', handler1);
    -  assertEquals(0, map.getListenerCount());
    -
    -  map.add(CLICK_EVENT_ID, handler1, false);
    -  assertEquals(1, map.getListenerCount());
    -  map.remove(CLICK_EVENT_ID, handler1);
    -  assertEquals(0, map.getListenerCount());
    -
    -  map.add('click', handler1, false, true);
    -  assertEquals(1, map.getListenerCount());
    -  map.remove('click', handler1, true);
    -  assertEquals(0, map.getListenerCount());
    -
    -  map.add(CLICK_EVENT_ID, handler1, false, true);
    -  assertEquals(1, map.getListenerCount());
    -  map.remove(CLICK_EVENT_ID, handler1, true);
    -  assertEquals(0, map.getListenerCount());
    -
    -  map.add('click', handler1, false);
    -  map.add('click', handler1, false, true);
    -  assertEquals(2, map.getListenerCount());
    -  map.remove('click', handler1);
    -  map.remove('click', handler1, true);
    -  assertEquals(0, map.getListenerCount());
    -
    -  map.add(CLICK_EVENT_ID, handler1, false);
    -  map.add(CLICK_EVENT_ID, handler1, false, true);
    -  assertEquals(2, map.getListenerCount());
    -  map.remove(CLICK_EVENT_ID, handler1);
    -  map.remove(CLICK_EVENT_ID, handler1, true);
    -  assertEquals(0, map.getListenerCount());
    -
    -  map.add('click', handler1, false);
    -  map.add('touchstart', handler2, false);
    -  map.add(CLICK_EVENT_ID, handler3, false);
    -  assertEquals(3, map.getListenerCount());
    -  map.remove(CLICK_EVENT_ID, handler3);
    -  map.remove('touchstart', handler2);
    -  map.remove('click', handler1);
    -  assertEquals(0, map.getListenerCount());
    -}
    -
    -
    -function testListenerSourceIsSetCorrectly() {
    -  map.add('click', handler1, false);
    -  var listener = map.getListener('click', handler1);
    -  assertEquals(et, listener.src);
    -
    -  map.add(CLICK_EVENT_ID, handler2, false);
    -  listener = map.getListener(CLICK_EVENT_ID, handler2);
    -  assertEquals(et, listener.src);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/events/mousewheelhandler.js b/src/database/third_party/closure-library/closure/goog/events/mousewheelhandler.js
    deleted file mode 100644
    index 6729064c833..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/mousewheelhandler.js
    +++ /dev/null
    @@ -1,296 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview This event wrapper will dispatch an event when the user uses
    - * the mouse wheel to scroll an element. You can get the direction by checking
    - * the deltaX and deltaY properties of the event.
    - *
    - * This class aims to smooth out inconsistencies between browser platforms with
    - * regards to mousewheel events, but we do not cover every possible
    - * software/hardware combination out there, some of which occasionally produce
    - * very large deltas in mousewheel events. If your application wants to guard
    - * against extremely large deltas, use the setMaxDeltaX and setMaxDeltaY APIs
    - * to set maximum values that make sense for your application.
    - *
    - * @author arv@google.com (Erik Arvidsson)
    - * @see ../demos/mousewheelhandler.html
    - */
    -
    -goog.provide('goog.events.MouseWheelEvent');
    -goog.provide('goog.events.MouseWheelHandler');
    -goog.provide('goog.events.MouseWheelHandler.EventType');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.BrowserEvent');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.math');
    -goog.require('goog.style');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * This event handler allows you to catch mouse wheel events in a consistent
    - * manner.
    - * @param {Element|Document} element The element to listen to the mouse wheel
    - *     event on.
    - * @param {boolean=} opt_capture Whether to handle the mouse wheel event in
    - *     capture phase.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - */
    -goog.events.MouseWheelHandler = function(element, opt_capture) {
    -  goog.events.EventTarget.call(this);
    -
    -  /**
    -   * This is the element that we will listen to the real mouse wheel events on.
    -   * @type {Element|Document}
    -   * @private
    -   */
    -  this.element_ = element;
    -
    -  var rtlElement = goog.dom.isElement(this.element_) ?
    -      /** @type {Element} */ (this.element_) :
    -      (this.element_ ? /** @type {Document} */ (this.element_).body : null);
    -
    -  /**
    -   * True if the element exists and is RTL, false otherwise.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.isRtl_ = !!rtlElement && goog.style.isRightToLeft(rtlElement);
    -
    -  var type = goog.userAgent.GECKO ? 'DOMMouseScroll' : 'mousewheel';
    -
    -  /**
    -   * The key returned from the goog.events.listen.
    -   * @type {goog.events.Key}
    -   * @private
    -   */
    -  this.listenKey_ = goog.events.listen(this.element_, type, this, opt_capture);
    -};
    -goog.inherits(goog.events.MouseWheelHandler, goog.events.EventTarget);
    -
    -
    -/**
    - * Enum type for the events fired by the mouse wheel handler.
    - * @enum {string}
    - */
    -goog.events.MouseWheelHandler.EventType = {
    -  MOUSEWHEEL: 'mousewheel'
    -};
    -
    -
    -/**
    - * Optional maximum magnitude for x delta on each mousewheel event.
    - * @type {number|undefined}
    - * @private
    - */
    -goog.events.MouseWheelHandler.prototype.maxDeltaX_;
    -
    -
    -/**
    - * Optional maximum magnitude for y delta on each mousewheel event.
    - * @type {number|undefined}
    - * @private
    - */
    -goog.events.MouseWheelHandler.prototype.maxDeltaY_;
    -
    -
    -/**
    - * @param {number} maxDeltaX Maximum magnitude for x delta on each mousewheel
    - *     event. Should be non-negative.
    - */
    -goog.events.MouseWheelHandler.prototype.setMaxDeltaX = function(maxDeltaX) {
    -  this.maxDeltaX_ = maxDeltaX;
    -};
    -
    -
    -/**
    - * @param {number} maxDeltaY Maximum magnitude for y delta on each mousewheel
    - *     event. Should be non-negative.
    - */
    -goog.events.MouseWheelHandler.prototype.setMaxDeltaY = function(maxDeltaY) {
    -  this.maxDeltaY_ = maxDeltaY;
    -};
    -
    -
    -/**
    - * Handles the events on the element.
    - * @param {goog.events.BrowserEvent} e The underlying browser event.
    - */
    -goog.events.MouseWheelHandler.prototype.handleEvent = function(e) {
    -  var deltaX = 0;
    -  var deltaY = 0;
    -  var detail = 0;
    -  var be = e.getBrowserEvent();
    -  if (be.type == 'mousewheel') {
    -    var wheelDeltaScaleFactor = 1;
    -    if (goog.userAgent.IE ||
    -        goog.userAgent.WEBKIT &&
    -        (goog.userAgent.WINDOWS || goog.userAgent.isVersionOrHigher('532.0'))) {
    -      // In IE we get a multiple of 120; we adjust to a multiple of 3 to
    -      // represent number of lines scrolled (like Gecko).
    -      // Newer versions of Webkit match IE behavior, and WebKit on
    -      // Windows also matches IE behavior.
    -      // See bug https://bugs.webkit.org/show_bug.cgi?id=24368
    -      wheelDeltaScaleFactor = 40;
    -    }
    -
    -    detail = goog.events.MouseWheelHandler.smartScale_(
    -        -be.wheelDelta, wheelDeltaScaleFactor);
    -    if (goog.isDef(be.wheelDeltaX)) {
    -      // Webkit has two properties to indicate directional scroll, and
    -      // can scroll both directions at once.
    -      deltaX = goog.events.MouseWheelHandler.smartScale_(
    -          -be.wheelDeltaX, wheelDeltaScaleFactor);
    -      deltaY = goog.events.MouseWheelHandler.smartScale_(
    -          -be.wheelDeltaY, wheelDeltaScaleFactor);
    -    } else {
    -      deltaY = detail;
    -    }
    -
    -    // Historical note: Opera (pre 9.5) used to negate the detail value.
    -  } else { // Gecko
    -    // Gecko returns multiple of 3 (representing the number of lines scrolled)
    -    detail = be.detail;
    -
    -    // Gecko sometimes returns really big values if the user changes settings to
    -    // scroll a whole page per scroll
    -    if (detail > 100) {
    -      detail = 3;
    -    } else if (detail < -100) {
    -      detail = -3;
    -    }
    -
    -    // Firefox 3.1 adds an axis field to the event to indicate direction of
    -    // scroll.  See https://developer.mozilla.org/en/Gecko-Specific_DOM_Events
    -    if (goog.isDef(be.axis) && be.axis === be.HORIZONTAL_AXIS) {
    -      deltaX = detail;
    -    } else {
    -      deltaY = detail;
    -    }
    -  }
    -
    -  if (goog.isNumber(this.maxDeltaX_)) {
    -    deltaX = goog.math.clamp(deltaX, -this.maxDeltaX_, this.maxDeltaX_);
    -  }
    -  if (goog.isNumber(this.maxDeltaY_)) {
    -    deltaY = goog.math.clamp(deltaY, -this.maxDeltaY_, this.maxDeltaY_);
    -  }
    -  // Don't clamp 'detail', since it could be ambiguous which axis it refers to
    -  // and because it's informally deprecated anyways.
    -
    -  // For horizontal scrolling we need to flip the value for RTL grids.
    -  if (this.isRtl_) {
    -    deltaX = -deltaX;
    -  }
    -  var newEvent = new goog.events.MouseWheelEvent(detail, be, deltaX, deltaY);
    -  this.dispatchEvent(newEvent);
    -};
    -
    -
    -/**
    - * Helper for scaling down a mousewheel delta by a scale factor, if appropriate.
    - * @param {number} mouseWheelDelta Delta from a mouse wheel event. Expected to
    - *     be an integer.
    - * @param {number} scaleFactor Factor to scale the delta down by. Expected to
    - *     be an integer.
    - * @return {number} Scaled-down delta value, or the original delta if the
    - *     scaleFactor does not appear to be applicable.
    - * @private
    - */
    -goog.events.MouseWheelHandler.smartScale_ = function(mouseWheelDelta,
    -    scaleFactor) {
    -  // The basic problem here is that in Webkit on Mac and Linux, we can get two
    -  // very different types of mousewheel events: from continuous devices
    -  // (touchpads, Mighty Mouse) or non-continuous devices (normal wheel mice).
    -  //
    -  // Non-continuous devices in Webkit get their wheel deltas scaled up to
    -  // behave like IE. Continuous devices return much smaller unscaled values
    -  // (which most of the time will not be cleanly divisible by the IE scale
    -  // factor), so we should not try to normalize them down.
    -  //
    -  // Detailed discussion:
    -  //   https://bugs.webkit.org/show_bug.cgi?id=29601
    -  //   http://trac.webkit.org/browser/trunk/WebKit/chromium/src/mac/WebInputEventFactory.mm#L1063
    -  if (goog.userAgent.WEBKIT &&
    -      (goog.userAgent.MAC || goog.userAgent.LINUX) &&
    -      (mouseWheelDelta % scaleFactor) != 0) {
    -    return mouseWheelDelta;
    -  } else {
    -    return mouseWheelDelta / scaleFactor;
    -  }
    -};
    -
    -
    -/** @override */
    -goog.events.MouseWheelHandler.prototype.disposeInternal = function() {
    -  goog.events.MouseWheelHandler.superClass_.disposeInternal.call(this);
    -  goog.events.unlistenByKey(this.listenKey_);
    -  this.listenKey_ = null;
    -};
    -
    -
    -
    -/**
    - * A base class for mouse wheel events. This is used with the
    - * MouseWheelHandler.
    - *
    - * @param {number} detail The number of rows the user scrolled.
    - * @param {Event} browserEvent Browser event object.
    - * @param {number} deltaX The number of rows the user scrolled in the X
    - *     direction.
    - * @param {number} deltaY The number of rows the user scrolled in the Y
    - *     direction.
    - * @constructor
    - * @extends {goog.events.BrowserEvent}
    - * @final
    - */
    -goog.events.MouseWheelEvent = function(detail, browserEvent, deltaX, deltaY) {
    -  goog.events.BrowserEvent.call(this, browserEvent);
    -
    -  this.type = goog.events.MouseWheelHandler.EventType.MOUSEWHEEL;
    -
    -  /**
    -   * The number of lines the user scrolled
    -   * @type {number}
    -   * NOTE: Informally deprecated. Use deltaX and deltaY instead, they provide
    -   * more information.
    -   */
    -  this.detail = detail;
    -
    -  /**
    -   * The number of "lines" scrolled in the X direction.
    -   *
    -   * Note that not all browsers provide enough information to distinguish
    -   * horizontal and vertical scroll events, so for these unsupported browsers,
    -   * we will always have a deltaX of 0, even if the user scrolled their mouse
    -   * wheel or trackpad sideways.
    -   *
    -   * Currently supported browsers are Webkit and Firefox 3.1 or later.
    -   *
    -   * @type {number}
    -   */
    -  this.deltaX = deltaX;
    -
    -  /**
    -   * The number of lines scrolled in the Y direction.
    -   * @type {number}
    -   */
    -  this.deltaY = deltaY;
    -};
    -goog.inherits(goog.events.MouseWheelEvent, goog.events.BrowserEvent);
    diff --git a/src/database/third_party/closure-library/closure/goog/events/mousewheelhandler_test.html b/src/database/third_party/closure-library/closure/goog/events/mousewheelhandler_test.html
    deleted file mode 100644
    index 237498e6b98..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/mousewheelhandler_test.html
    +++ /dev/null
    @@ -1,31 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.events.MouseWheelHandler
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.events.MouseWheelHandlerTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="foo">
    -  </div>
    -  <div id="fooRtl" dir="rtl">
    -  </div>
    -  <div id="log" style="position:absolute;right:0;top:0">
    -   Logged events:
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/events/mousewheelhandler_test.js b/src/database/third_party/closure-library/closure/goog/events/mousewheelhandler_test.js
    deleted file mode 100644
    index a14ef577b17..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/mousewheelhandler_test.js
    +++ /dev/null
    @@ -1,375 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.events.MouseWheelHandlerTest');
    -goog.setTestOnly('goog.events.MouseWheelHandlerTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.BrowserEvent');
    -goog.require('goog.events.MouseWheelEvent');
    -goog.require('goog.events.MouseWheelHandler');
    -goog.require('goog.functions');
    -goog.require('goog.string');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -var log;
    -var stubs = new goog.testing.PropertyReplacer();
    -
    -var DEFAULT_TYPE = 'mousewheel';
    -var GECKO_TYPE = 'DOMMouseScroll';
    -
    -var HORIZONTAL = 'h';
    -var VERTICAL = 'v';
    -
    -var mouseWheelEvent;
    -var mouseWheelEventRtl;
    -var mouseWheelHandler;
    -var mouseWheelHandlerRtl;
    -
    -function setUpPage() {
    -  log = goog.dom.getElement('log');
    -}
    -
    -function setUp() {
    -  stubs.remove(goog, 'userAgent');
    -}
    -
    -function tearDown() {
    -  stubs.reset();
    -  goog.dispose(mouseWheelHandler);
    -  goog.dispose(mouseWheelHandlerRtl);
    -  mouseWheelHandlerRtl = null;
    -  mouseWheelHandler = null;
    -  mouseWheelEvent = null;
    -  mouseWheelEventRtl = null;
    -}
    -
    -function tearDownPage() {
    -  // Create interactive demo.
    -  mouseWheelHandler = new goog.events.MouseWheelHandler(document.body);
    -
    -  goog.events.listen(mouseWheelHandler,
    -      goog.events.MouseWheelHandler.EventType.MOUSEWHEEL,
    -      function(e) {
    -        log.innerHTML += goog.string.subs('<br />(deltaX, deltaY): (%s, %s)',
    -            e.deltaX, e.deltaY);
    -      });
    -}
    -
    -function testIeStyleMouseWheel() {
    -  goog.userAgent = {
    -    OPERA: false,
    -    IE: true,
    -    GECKO: false,
    -    WEBKIT: false
    -  };
    -
    -  createHandlerAndListen();
    -
    -  // Non-gecko, non-webkit events get wheelDelta divided by -40 to get detail.
    -  handleEvent(createFakeMouseWheelEvent(DEFAULT_TYPE, 120));
    -  assertMouseWheelEvent(-3, 0, -3);
    -
    -  handleEvent(createFakeMouseWheelEvent(DEFAULT_TYPE, -120));
    -  assertMouseWheelEvent(3, 0, 3);
    -
    -  handleEvent(createFakeMouseWheelEvent(DEFAULT_TYPE, 1200));
    -  assertMouseWheelEvent(-30, 0, -30);
    -}
    -
    -function testNullBody() {
    -  goog.userAgent = {
    -    OPERA: false,
    -    IE: true,
    -    GECKO: false,
    -    WEBKIT: false
    -  };
    -  var documentObjectWithNoBody = { };
    -  goog.testing.events.mixinListenable(documentObjectWithNoBody);
    -  mouseWheelHandler =
    -      new goog.events.MouseWheelHandler(documentObjectWithNoBody);
    -}
    -
    -function testGeckoStyleMouseWheel() {
    -  goog.userAgent = {
    -    OPERA: false,
    -    IE: false,
    -    GECKO: true,
    -    WEBKIT: false
    -  };
    -
    -  createHandlerAndListen();
    -
    -  handleEvent(createFakeMouseWheelEvent(GECKO_TYPE, null, 3));
    -  assertMouseWheelEvent(3, 0, 3);
    -
    -  handleEvent(createFakeMouseWheelEvent(GECKO_TYPE, null, -12));
    -  assertMouseWheelEvent(-12, 0, -12);
    -
    -  // Really big values should get truncated to +-3.
    -  handleEvent(createFakeMouseWheelEvent(GECKO_TYPE, null, 1200));
    -  assertMouseWheelEvent(3, 0, 3);
    -
    -  handleEvent(createFakeMouseWheelEvent(GECKO_TYPE, null, -1200));
    -  assertMouseWheelEvent(-3, 0, -3);
    -
    -  // Test scrolling with the additional axis property.
    -  handleEvent(createFakeMouseWheelEvent(GECKO_TYPE, null, 3, VERTICAL));
    -  assertMouseWheelEvent(3, 0, 3);
    -
    -  handleEvent(createFakeMouseWheelEvent(GECKO_TYPE, null, 3, HORIZONTAL));
    -  assertMouseWheelEvent(3, 3, 0);
    -
    -  handleEvent(createFakeMouseWheelEvent(GECKO_TYPE, null, -3, HORIZONTAL));
    -  assertMouseWheelEvent(-3, -3, 0);
    -}
    -
    -function testWebkitStyleMouseWheel_ieStyle() {
    -  goog.userAgent = {
    -    OPERA: false,
    -    IE: false,
    -    GECKO: false,
    -    WEBKIT: true,
    -    WINDOWS: true
    -  };
    -
    -  createHandlerAndListen();
    -
    -  // IE-style Webkit events get wheelDelta divided by -40 to get detail.
    -  handleEvent(createFakeWebkitMouseWheelEvent(-40, 0));
    -  assertMouseWheelEvent(1, 1, 0);
    -
    -  handleEvent(createFakeWebkitMouseWheelEvent(120, 0));
    -  assertMouseWheelEvent(-3, -3, 0);
    -
    -  handleEvent(createFakeWebkitMouseWheelEvent(0, 120));
    -  assertMouseWheelEvent(-3, 0, -3);
    -
    -  handleEvent(createFakeWebkitMouseWheelEvent(0, -40));
    -  assertMouseWheelEvent(1, 0, 1);
    -
    -  handleEvent(createFakeWebkitMouseWheelEvent(80, -40));
    -  assertMouseWheelEvent(-2, -2, 1);
    -}
    -
    -function testWebkitStyleMouseWheel_ieStyleOnLinux() {
    -  goog.userAgent = {
    -    OPERA: false,
    -    IE: false,
    -    GECKO: false,
    -    WEBKIT: true,
    -    WINDOWS: false,
    -    LINUX: true
    -  };
    -  runWebKitContinousAndDiscreteEventsTest();
    -}
    -
    -function testWebkitStyleMouseWheel_ieStyleOnMac() {
    -  goog.userAgent = {
    -    OPERA: false,
    -    IE: false,
    -    GECKO: false,
    -    WEBKIT: true,
    -    WINDOWS: false,
    -    MAC: true
    -  };
    -  runWebKitContinousAndDiscreteEventsTest();
    -}
    -
    -function runWebKitContinousAndDiscreteEventsTest() {
    -  goog.userAgent.isVersionOrHigher = goog.functions.TRUE;
    -
    -  createHandlerAndListen();
    -
    -  // IE-style wheel events.
    -  handleEvent(createFakeWebkitMouseWheelEvent(0, -40));
    -  assertMouseWheelEvent(1, 0, 1);
    -
    -  handleEvent(createFakeWebkitMouseWheelEvent(80, -40));
    -  assertMouseWheelEvent(-2, -2, 1);
    -
    -  // Even in Webkit versions that usually behave in IE style, sometimes wheel
    -  // events don't behave; this has been observed for instance with Macbook
    -  // and Chrome OS touchpads in Webkit 534.10+.
    -  handleEvent(createFakeWebkitMouseWheelEvent(-3, 5));
    -  assertMouseWheelEvent(-5, 3, -5);
    -
    -  handleEvent(createFakeWebkitMouseWheelEvent(4, -7));
    -  assertMouseWheelEvent(7, -4, 7);
    -}
    -
    -function testWebkitStyleMouseWheel_nonIeStyle() {
    -  goog.userAgent = {
    -    OPERA: false,
    -    IE: false,
    -    GECKO: false,
    -    WEBKIT: true,
    -    WINDOWS: false
    -  };
    -
    -  goog.userAgent.isVersionOrHigher = goog.functions.FALSE;
    -
    -  createHandlerAndListen();
    -
    -  // non-IE-style Webkit events do not get wheelDelta scaled
    -  handleEvent(createFakeWebkitMouseWheelEvent(-1, 0));
    -  assertMouseWheelEvent(1, 1, 0);
    -
    -  handleEvent(createFakeWebkitMouseWheelEvent(3, 0));
    -  assertMouseWheelEvent(-3, -3, 0);
    -
    -  handleEvent(createFakeWebkitMouseWheelEvent(0, 3));
    -  assertMouseWheelEvent(-3, 0, -3);
    -
    -  handleEvent(createFakeWebkitMouseWheelEvent(0, -1));
    -  assertMouseWheelEvent(1, 0, 1);
    -
    -  handleEvent(createFakeWebkitMouseWheelEvent(2, -1));
    -  assertMouseWheelEvent(-2, -2, 1);
    -}
    -
    -function testMaxDeltaX() {
    -  goog.userAgent = {
    -    OPERA: false,
    -    IE: false,
    -    GECKO: false,
    -    WEBKIT: true,
    -    WINDOWS: true
    -  };
    -
    -  createHandlerAndListen();
    -
    -  // IE-style Webkit events get wheelDelta divided by -40 to get detail.
    -  handleEvent(createFakeWebkitMouseWheelEvent(-120, 0));
    -  assertMouseWheelEvent(3, 3, 0);
    -
    -  mouseWheelHandler.setMaxDeltaX(3);
    -  mouseWheelHandlerRtl.setMaxDeltaX(3);
    -  handleEvent(createFakeWebkitMouseWheelEvent(-120, 0));
    -  assertMouseWheelEvent(3, 3, 0);
    -
    -  mouseWheelHandler.setMaxDeltaX(2);
    -  mouseWheelHandlerRtl.setMaxDeltaX(2);
    -  handleEvent(createFakeWebkitMouseWheelEvent(-120, 0));
    -  assertMouseWheelEvent(3, 2, 0);
    -
    -  handleEvent(createFakeWebkitMouseWheelEvent(0, -120));
    -  assertMouseWheelEvent(3, 0, 3);
    -}
    -
    -function testMaxDeltaY() {
    -  goog.userAgent = {
    -    OPERA: false,
    -    IE: false,
    -    GECKO: false,
    -    WEBKIT: true,
    -    WINDOWS: true
    -  };
    -
    -  createHandlerAndListen();
    -
    -  // IE-style Webkit events get wheelDelta divided by -40 to get detail.
    -  handleEvent(createFakeWebkitMouseWheelEvent(0, -120));
    -  assertMouseWheelEvent(3, 0, 3);
    -
    -  mouseWheelHandler.setMaxDeltaY(3);
    -  mouseWheelHandlerRtl.setMaxDeltaY(3);
    -  handleEvent(createFakeWebkitMouseWheelEvent(0, -120));
    -  assertMouseWheelEvent(3, 0, 3);
    -
    -  mouseWheelHandler.setMaxDeltaY(2);
    -  mouseWheelHandlerRtl.setMaxDeltaY(2);
    -  handleEvent(createFakeWebkitMouseWheelEvent(0, -120));
    -  assertMouseWheelEvent(3, 0, 2);
    -
    -  handleEvent(createFakeWebkitMouseWheelEvent(-120, 0));
    -  assertMouseWheelEvent(3, 3, 0);
    -}
    -
    -// Be sure to call this after setting up goog.userAgent mock and not before.
    -function createHandlerAndListen() {
    -  mouseWheelHandler = new goog.events.MouseWheelHandler(
    -      goog.dom.getElement('foo'));
    -
    -  goog.events.listen(mouseWheelHandler,
    -      goog.events.MouseWheelHandler.EventType.MOUSEWHEEL,
    -      function(e) { mouseWheelEvent = e; });
    -
    -  mouseWheelHandlerRtl = new goog.events.MouseWheelHandler(
    -      goog.dom.getElement('fooRtl'));
    -
    -  goog.events.listen(mouseWheelHandlerRtl,
    -      goog.events.MouseWheelHandler.EventType.MOUSEWHEEL,
    -      function(e) { mouseWheelEventRtl = e; });
    -}
    -
    -function handleEvent(event) {
    -  mouseWheelHandler.handleEvent(event);
    -  mouseWheelHandlerRtl.handleEvent(event);
    -}
    -
    -function assertMouseWheelEvent(expectedDetail, expectedDeltaX,
    -    expectedDeltaY) {
    -  assertTrue('event should be non-null', !!mouseWheelEvent);
    -  assertTrue('event should have correct JS type',
    -      mouseWheelEvent instanceof goog.events.MouseWheelEvent);
    -  assertEquals('event should have correct detail property',
    -      expectedDetail, mouseWheelEvent.detail);
    -  assertEquals('event should have correct deltaX property',
    -      expectedDeltaX, mouseWheelEvent.deltaX);
    -  assertEquals('event should have correct deltaY property',
    -      expectedDeltaY, mouseWheelEvent.deltaY);
    -
    -  // RTL
    -  assertTrue('event should be non-null', !!mouseWheelEventRtl);
    -  assertTrue('event should have correct JS type',
    -      mouseWheelEventRtl instanceof goog.events.MouseWheelEvent);
    -  assertEquals('event should have correct detail property',
    -      expectedDetail, mouseWheelEventRtl.detail);
    -  assertEquals('event should have correct deltaX property',
    -      -expectedDeltaX, mouseWheelEventRtl.deltaX);
    -  assertEquals('event should have correct deltaY property',
    -      expectedDeltaY, mouseWheelEventRtl.deltaY);
    -
    -}
    -
    -function createFakeMouseWheelEvent(type, opt_wheelDelta, opt_detail,
    -    opt_axis, opt_wheelDeltaX, opt_wheelDeltaY) {
    -  var event = {
    -    type: type,
    -    wheelDelta: goog.isDef(opt_wheelDelta) ? opt_wheelDelta : undefined,
    -    detail: goog.isDef(opt_detail) ? opt_detail : undefined,
    -    axis: opt_axis || undefined,
    -    wheelDeltaX: goog.isDef(opt_wheelDeltaX) ? opt_wheelDeltaX : undefined,
    -    wheelDeltaY: goog.isDef(opt_wheelDeltaY) ? opt_wheelDeltaY : undefined,
    -
    -    // These two are constants defined on the event in FF3.1 and later.
    -    // It doesn't matter exactly what they are, and it doesn't affect
    -    // our simulations of other browsers.
    -    HORIZONTAL_AXIS: HORIZONTAL,
    -    VERTICAL_AXIS: VERTICAL
    -  };
    -  return new goog.events.BrowserEvent(event);
    -}
    -
    -function createFakeWebkitMouseWheelEvent(wheelDeltaX, wheelDeltaY) {
    -  return createFakeMouseWheelEvent(DEFAULT_TYPE,
    -      Math.abs(wheelDeltaX) > Math.abs(wheelDeltaY) ?
    -          wheelDeltaX : wheelDeltaY,
    -      undefined, undefined, wheelDeltaX, wheelDeltaY);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/events/onlinehandler.js b/src/database/third_party/closure-library/closure/goog/events/onlinehandler.js
    deleted file mode 100644
    index 5c9fb1620bf..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/onlinehandler.js
    +++ /dev/null
    @@ -1,159 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview This event handler will dispatch events when
    - * {@code navigator.onLine} changes.  HTML5 defines two events, online and
    - * offline that is fired on the window.  As of today 3 browsers support these
    - * events: Firefox 3 (Gecko 1.9), Opera 9.5, and IE8.  If we have any of these
    - * we listen to the 'online' and 'offline' events on the current window
    - * object.  Otherwise we poll the navigator.onLine property to detect changes.
    - *
    - * Note that this class only reflects what the browser tells us and this usually
    - * only reflects changes to the File -> Work Offline menu item.
    - *
    - * @author arv@google.com (Erik Arvidsson)
    - * @see ../demos/onlinehandler.html
    - */
    -
    -// TODO(arv): We should probably implement some kind of polling service and/or
    -// a poll for changes event handler that can be used to fire events when a state
    -// changes.
    -
    -goog.provide('goog.events.OnlineHandler');
    -goog.provide('goog.events.OnlineHandler.EventType');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.events.BrowserFeature');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -goog.require('goog.net.NetworkStatusMonitor');
    -
    -
    -
    -/**
    - * Basic object for detecting whether the online state changes.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - * @implements {goog.net.NetworkStatusMonitor}
    - */
    -goog.events.OnlineHandler = function() {
    -  goog.events.OnlineHandler.base(this, 'constructor');
    -
    -  /**
    -   * @private {goog.events.EventHandler<!goog.events.OnlineHandler>}
    -   */
    -  this.eventHandler_ = new goog.events.EventHandler(this);
    -
    -  // Some browsers do not support navigator.onLine and therefore we don't
    -  // bother setting up events or timers.
    -  if (!goog.events.BrowserFeature.HAS_NAVIGATOR_ONLINE_PROPERTY) {
    -    return;
    -  }
    -
    -  if (goog.events.BrowserFeature.HAS_HTML5_NETWORK_EVENT_SUPPORT) {
    -    var target =
    -        goog.events.BrowserFeature.HTML5_NETWORK_EVENTS_FIRE_ON_BODY ?
    -        document.body : window;
    -    this.eventHandler_.listen(target,
    -        [goog.events.EventType.ONLINE, goog.events.EventType.OFFLINE],
    -        this.handleChange_);
    -  } else {
    -    this.online_ = this.isOnline();
    -    this.timer_ = new goog.Timer(goog.events.OnlineHandler.POLL_INTERVAL_);
    -    this.eventHandler_.listen(this.timer_, goog.Timer.TICK, this.handleTick_);
    -    this.timer_.start();
    -  }
    -};
    -goog.inherits(goog.events.OnlineHandler, goog.events.EventTarget);
    -
    -
    -/**
    - * Enum for the events dispatched by the OnlineHandler.
    - * @enum {string}
    - * @deprecated Use goog.net.NetworkStatusMonitor.EventType instead.
    - */
    -goog.events.OnlineHandler.EventType = goog.net.NetworkStatusMonitor.EventType;
    -
    -
    -/**
    - * The time to wait before checking the {@code navigator.onLine} again.
    - * @type {number}
    - * @private
    - */
    -goog.events.OnlineHandler.POLL_INTERVAL_ = 250;
    -
    -
    -/**
    - * Stores the last value of the online state so we can detect if this has
    - * changed.
    - * @type {boolean}
    - * @private
    - */
    -goog.events.OnlineHandler.prototype.online_;
    -
    -
    -/**
    - * The timer object used to poll the online state.
    - * @type {goog.Timer}
    - * @private
    - */
    -goog.events.OnlineHandler.prototype.timer_;
    -
    -
    -/** @override */
    -goog.events.OnlineHandler.prototype.isOnline = function() {
    -  return goog.events.BrowserFeature.HAS_NAVIGATOR_ONLINE_PROPERTY ?
    -      navigator.onLine : true;
    -};
    -
    -
    -/**
    - * Called every time the timer ticks to see if the state has changed and when
    - * the online state changes the method handleChange_ is called.
    - * @private
    - */
    -goog.events.OnlineHandler.prototype.handleTick_ = function() {
    -  var online = this.isOnline();
    -  if (online != this.online_) {
    -    this.online_ = online;
    -    this.handleChange_();
    -  }
    -};
    -
    -
    -/**
    - * Called when the online state changes.  This dispatches the
    - * {@code ONLINE} and {@code OFFLINE} events respectively.
    - * @private
    - */
    -goog.events.OnlineHandler.prototype.handleChange_ = function() {
    -  var type = this.isOnline() ?
    -      goog.net.NetworkStatusMonitor.EventType.ONLINE :
    -      goog.net.NetworkStatusMonitor.EventType.OFFLINE;
    -  this.dispatchEvent(type);
    -};
    -
    -
    -/** @override */
    -goog.events.OnlineHandler.prototype.disposeInternal = function() {
    -  goog.events.OnlineHandler.base(this, 'disposeInternal');
    -  this.eventHandler_.dispose();
    -  this.eventHandler_ = null;
    -  if (this.timer_) {
    -    this.timer_.dispose();
    -    this.timer_ = null;
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/events/onlinelistener_test.html b/src/database/third_party/closure-library/closure/goog/events/onlinelistener_test.html
    deleted file mode 100644
    index 4d243cbef68..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/onlinelistener_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -  Author: arv@google.com (Erik Arvidsson)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.events.OnlineListener
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.events.OnlineHandlerTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/events/onlinelistener_test.js b/src/database/third_party/closure-library/closure/goog/events/onlinelistener_test.js
    deleted file mode 100644
    index fa427507e5d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/onlinelistener_test.js
    +++ /dev/null
    @@ -1,154 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.events.OnlineHandlerTest');
    -goog.setTestOnly('goog.events.OnlineHandlerTest');
    -
    -goog.require('goog.events');
    -goog.require('goog.events.BrowserFeature');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.OnlineHandler');
    -goog.require('goog.net.NetworkStatusMonitor');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -
    -var stubs = new goog.testing.PropertyReplacer();
    -var clock = new goog.testing.MockClock();
    -var online = true;
    -var onlineCount;
    -var offlineCount;
    -
    -function listenToEvents(oh) {
    -  onlineCount = 0;
    -  offlineCount = 0;
    -
    -  goog.events.listen(oh, goog.net.NetworkStatusMonitor.EventType.ONLINE,
    -                     function(e) {
    -                       assertTrue(oh.isOnline());
    -                       onlineCount++;
    -                     });
    -  goog.events.listen(oh, goog.net.NetworkStatusMonitor.EventType.OFFLINE,
    -                     function(e) {
    -                       assertFalse(oh.isOnline());
    -                       offlineCount++;
    -                     });
    -}
    -
    -function setUp() {
    -  stubs.set(goog.events.OnlineHandler.prototype, 'isOnline', function() {
    -    return online;
    -  });
    -}
    -
    -function tearDown() {
    -  stubs.reset();
    -  clock.uninstall();
    -}
    -
    -function testConstructAndDispose() {
    -  var oh = new goog.events.OnlineHandler();
    -  oh.dispose();
    -}
    -
    -function testNoOnlineProperty() {
    -  stubs.set(goog.events.BrowserFeature,
    -      'HAS_NAVIGATOR_ONLINE_PROPERTY', false);
    -  stubs.set(goog.events.EventHandler.prototype, 'listen',
    -      goog.testing.recordFunction());
    -
    -  var oh = new goog.events.OnlineHandler();
    -
    -  assertEquals(0, oh.eventHandler_.listen.getCallCount());
    -
    -  oh.dispose();
    -}
    -
    -function testNonHtml5() {
    -  clock.install();
    -  stubs.set(goog.events.BrowserFeature,
    -      'HAS_HTML5_NETWORK_EVENT_SUPPORT', false);
    -
    -  var oh = new goog.events.OnlineHandler();
    -  listenToEvents(oh);
    -
    -  clock.tick(500);
    -  online = false;
    -  clock.tick(500);
    -
    -  assertEquals(0, onlineCount);
    -  assertEquals(1, offlineCount);
    -
    -  online = true;
    -  clock.tick(500);
    -
    -  assertEquals(1, onlineCount);
    -  assertEquals(1, offlineCount);
    -
    -  oh.dispose();
    -  clock.dispose();
    -}
    -
    -function testHtml5() {
    -  stubs.set(goog.events.BrowserFeature,
    -      'HAS_HTML5_NETWORK_EVENT_SUPPORT', true);
    -
    -  // Test for browsers that fire network events on document.body.
    -  stubs.set(goog.events.BrowserFeature,
    -      'HTML5_NETWORK_EVENTS_FIRE_ON_BODY', true);
    -
    -  var oh = new goog.events.OnlineHandler();
    -  listenToEvents(oh);
    -
    -  online = false;
    -  var e = new goog.events.Event('offline');
    -  goog.events.fireListeners(document.body, e.type, false, e);
    -
    -  assertEquals(0, onlineCount);
    -  assertEquals(1, offlineCount);
    -
    -  online = true;
    -  e = new goog.events.Event('online');
    -  goog.events.fireListeners(document.body, e.type, false, e);
    -
    -  assertEquals(1, onlineCount);
    -  assertEquals(1, offlineCount);
    -
    -  oh.dispose();
    -
    -  // Test for browsers that fire network events on window.
    -  stubs.set(goog.events.BrowserFeature,
    -      'HTML5_NETWORK_EVENTS_FIRE_ON_BODY', false);
    -
    -  oh = new goog.events.OnlineHandler();
    -  listenToEvents(oh);
    -
    -  online = false;
    -  e = new goog.events.Event('offline');
    -  goog.events.fireListeners(window, e.type, false, e);
    -
    -  assertEquals(0, onlineCount);
    -  assertEquals(1, offlineCount);
    -
    -  online = true;
    -  e = new goog.events.Event('online');
    -  goog.events.fireListeners(window, e.type, false, e);
    -
    -  assertEquals(1, onlineCount);
    -  assertEquals(1, offlineCount);
    -
    -  oh.dispose();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/events/pastehandler.js b/src/database/third_party/closure-library/closure/goog/events/pastehandler.js
    deleted file mode 100644
    index 4992ff0fe08..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/pastehandler.js
    +++ /dev/null
    @@ -1,517 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides a 'paste' event detector that works consistently
    - * across different browsers.
    - *
    - * IE5, IE6, IE7, Safari3.0 and FF3.0 all fire 'paste' events on textareas.
    - * FF2 doesn't. This class uses 'paste' events when they are available
    - * and uses heuristics to detect the 'paste' event when they are not available.
    - *
    - * Known issue: will not detect paste events in FF2 if you pasted exactly the
    - * same existing text.
    - * Known issue: Opera + Mac doesn't work properly because of the meta key. We
    - * can probably fix that. TODO(user): {@link KeyboardShortcutHandler} does not
    - * work either very well with opera + mac. fix that.
    - *
    - * @supported IE5, IE6, IE7, Safari3.0, Chrome, FF2.0 (linux) and FF3.0 and
    - * Opera (mac and windows).
    - *
    - * @see ../demos/pastehandler.html
    - */
    -
    -goog.provide('goog.events.PasteHandler');
    -goog.provide('goog.events.PasteHandler.EventType');
    -goog.provide('goog.events.PasteHandler.State');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.async.ConditionalDelay');
    -goog.require('goog.events.BrowserEvent');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.log');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * A paste event detector. Gets an {@code element} as parameter and fires
    - * {@code goog.events.PasteHandler.EventType.PASTE} events when text is
    - * pasted in the {@code element}. Uses heuristics to detect paste events in FF2.
    - * See more details of the heuristic on {@link #handleEvent_}.
    - *
    - * @param {Element} element The textarea element we are listening on.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - */
    -goog.events.PasteHandler = function(element) {
    -  goog.events.EventTarget.call(this);
    -
    -  /**
    -   * The element that you want to listen for paste events on.
    -   * @type {Element}
    -   * @private
    -   */
    -  this.element_ = element;
    -
    -  /**
    -   * The last known value of the element. Kept to check if things changed. See
    -   * more details on {@link #handleEvent_}.
    -   * @type {string}
    -   * @private
    -   */
    -  this.oldValue_ = this.element_.value;
    -
    -  /**
    -   * Handler for events.
    -   * @type {goog.events.EventHandler<!goog.events.PasteHandler>}
    -   * @private
    -   */
    -  this.eventHandler_ = new goog.events.EventHandler(this);
    -
    -  /**
    -   * The last time an event occurred on the element. Kept to check whether the
    -   * last event was generated by two input events or by multiple fast key events
    -   * that got swallowed. See more details on {@link #handleEvent_}.
    -   * @type {number}
    -   * @private
    -   */
    -  this.lastTime_ = goog.now();
    -
    -  if (goog.userAgent.WEBKIT ||
    -      goog.userAgent.IE ||
    -      goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.9')) {
    -    // Most modern browsers support the paste event.
    -    this.eventHandler_.listen(element, goog.events.EventType.PASTE,
    -        this.dispatch_);
    -  } else {
    -    // But FF2 and Opera doesn't. we listen for a series of events to try to
    -    // find out if a paste occurred. We enumerate and cover all known ways to
    -    // paste text on textareas.  See more details on {@link #handleEvent_}.
    -    var events = [
    -      goog.events.EventType.KEYDOWN,
    -      goog.events.EventType.BLUR,
    -      goog.events.EventType.FOCUS,
    -      goog.events.EventType.MOUSEOVER,
    -      'input'
    -    ];
    -    this.eventHandler_.listen(element, events, this.handleEvent_);
    -  }
    -
    -  /**
    -   * ConditionalDelay used to poll for changes in the text element once users
    -   * paste text. Browsers fire paste events BEFORE the text is actually present
    -   * in the element.value property.
    -   * @type {goog.async.ConditionalDelay}
    -   * @private
    -   */
    -  this.delay_ = new goog.async.ConditionalDelay(
    -      goog.bind(this.checkUpdatedText_, this));
    -
    -};
    -goog.inherits(goog.events.PasteHandler, goog.events.EventTarget);
    -
    -
    -/**
    - * The types of events fired by this class.
    - * @enum {string}
    - */
    -goog.events.PasteHandler.EventType = {
    -  /**
    -   * Dispatched as soon as the paste event is detected, but before the pasted
    -   * text has been added to the text element we're listening to.
    -   */
    -  PASTE: 'paste',
    -
    -  /**
    -   * Dispatched after detecting a change to the value of text element
    -   * (within 200msec of receiving the PASTE event).
    -   */
    -  AFTER_PASTE: 'after_paste'
    -};
    -
    -
    -/**
    - * The mandatory delay we expect between two {@code input} events, used to
    - * differentiated between non key paste events and key events.
    - * @type {number}
    - */
    -goog.events.PasteHandler.MANDATORY_MS_BETWEEN_INPUT_EVENTS_TIE_BREAKER =
    -    400;
    -
    -
    -/**
    - * The period between each time we check whether the pasted text appears in the
    - * text element or not.
    - * @type {number}
    - * @private
    - */
    -goog.events.PasteHandler.PASTE_POLLING_PERIOD_MS_ = 50;
    -
    -
    -/**
    - * The maximum amount of time we want to poll for changes.
    - * @type {number}
    - * @private
    - */
    -goog.events.PasteHandler.PASTE_POLLING_TIMEOUT_MS_ = 200;
    -
    -
    -/**
    - * The states that this class can be found, on the paste detection algorithm.
    - * @enum {string}
    - */
    -goog.events.PasteHandler.State = {
    -  INIT: 'init',
    -  FOCUSED: 'focused',
    -  TYPING: 'typing'
    -};
    -
    -
    -/**
    - * The initial state of the paste detection algorithm.
    - * @type {goog.events.PasteHandler.State}
    - * @private
    - */
    -goog.events.PasteHandler.prototype.state_ =
    -    goog.events.PasteHandler.State.INIT;
    -
    -
    -/**
    - * The previous event that caused us to be on the current state.
    - * @type {?string}
    - * @private
    - */
    -goog.events.PasteHandler.prototype.previousEvent_;
    -
    -
    -/**
    - * A logger, used to help us debug the algorithm.
    - * @type {goog.log.Logger}
    - * @private
    - */
    -goog.events.PasteHandler.prototype.logger_ =
    -    goog.log.getLogger('goog.events.PasteHandler');
    -
    -
    -/** @override */
    -goog.events.PasteHandler.prototype.disposeInternal = function() {
    -  goog.events.PasteHandler.superClass_.disposeInternal.call(this);
    -  this.eventHandler_.dispose();
    -  this.eventHandler_ = null;
    -  this.delay_.dispose();
    -  this.delay_ = null;
    -};
    -
    -
    -/**
    - * Returns the current state of the paste detection algorithm. Used mostly for
    - * testing.
    - * @return {goog.events.PasteHandler.State} The current state of the class.
    - */
    -goog.events.PasteHandler.prototype.getState = function() {
    -  return this.state_;
    -};
    -
    -
    -/**
    - * Returns the event handler.
    - * @return {goog.events.EventHandler<T>} The event handler.
    - * @protected
    - * @this T
    - * @template T
    - */
    -goog.events.PasteHandler.prototype.getEventHandler = function() {
    -  return this.eventHandler_;
    -};
    -
    -
    -/**
    - * Checks whether the element.value property was updated, and if so, dispatches
    - * the event that let clients know that the text is available.
    - * @return {boolean} Whether the polling should stop or not, based on whether
    - *     we found a text change or not.
    - * @private
    - */
    -goog.events.PasteHandler.prototype.checkUpdatedText_ = function() {
    -  if (this.oldValue_ == this.element_.value) {
    -    return false;
    -  }
    -  goog.log.info(this.logger_, 'detected textchange after paste');
    -  this.dispatchEvent(goog.events.PasteHandler.EventType.AFTER_PASTE);
    -  return true;
    -};
    -
    -
    -/**
    - * Dispatches the paste event.
    - * @param {goog.events.BrowserEvent} e The underlying browser event.
    - * @private
    - */
    -goog.events.PasteHandler.prototype.dispatch_ = function(e) {
    -  var event = new goog.events.BrowserEvent(e.getBrowserEvent());
    -  event.type = goog.events.PasteHandler.EventType.PASTE;
    -  this.dispatchEvent(event);
    -
    -  // Starts polling for updates in the element.value property so we can tell
    -  // when do dispatch the AFTER_PASTE event. (We do an initial check after an
    -  // async delay of 0 msec since some browsers update the text right away and
    -  // our poller will always wait one period before checking).
    -  goog.Timer.callOnce(function() {
    -    if (!this.checkUpdatedText_()) {
    -      this.delay_.start(
    -          goog.events.PasteHandler.PASTE_POLLING_PERIOD_MS_,
    -          goog.events.PasteHandler.PASTE_POLLING_TIMEOUT_MS_);
    -    }
    -  }, 0, this);
    -};
    -
    -
    -/**
    - * The main event handler which implements a state machine.
    - *
    - * To handle FF2, we enumerate and cover all the known ways a user can paste:
    - *
    - * 1) ctrl+v, shift+insert, cmd+v
    - * 2) right click -> paste
    - * 3) edit menu -> paste
    - * 4) drag and drop
    - * 5) middle click
    - *
    - * (1) is easy and can be detected by listening for key events and finding out
    - * which keys are pressed. (2), (3), (4) and (5) do not generate a key event,
    - * so we need to listen for more than that. (2-5) all generate 'input' events,
    - * but so does key events. So we need to have some sort of 'how did the input
    - * event was generated' history algorithm.
    - *
    - * (2) is an interesting case in Opera on a Mac: since Macs does not have two
    - * buttons, right clicking involves pressing the CTRL key. Even more interesting
    - * is the fact that opera does NOT set the e.ctrlKey bit. Instead, it sets
    - * e.keyCode = 0.
    - * {@link http://www.quirksmode.org/js/keys.html}
    - *
    - * (1) is also an interesting case in Opera on a Mac: Opera is the only browser
    - * covered by this class that can detect the cmd key (FF2 can't apparently). And
    - * it fires e.keyCode = 17, which is the CTRL key code.
    - * {@link http://www.quirksmode.org/js/keys.html}
    - *
    - * NOTE(user, pbarry): There is an interesting thing about (5): on Linux, (5)
    - * pastes the last thing that you highlighted, not the last thing that you
    - * ctrl+c'ed. This code will still generate a {@code PASTE} event though.
    - *
    - * We enumerate all the possible steps a user can take to paste text and we
    - * implemented the transition between the steps in a state machine. The
    - * following is the design of the state machine:
    - *
    - * matching paths:
    - *
    - * (1) happens on INIT -> FOCUSED -> TYPING -> [e.ctrlKey & e.keyCode = 'v']
    - * (2-3) happens on INIT -> FOCUSED -> [input event happened]
    - * (4) happens on INIT -> [mouseover && text changed]
    - *
    - * non matching paths:
    - *
    - * user is typing normally
    - * INIT -> FOCUS -> TYPING -> INPUT -> INIT
    - *
    - * @param {goog.events.BrowserEvent} e The underlying browser event.
    - * @private
    - */
    -goog.events.PasteHandler.prototype.handleEvent_ = function(e) {
    -  // transition between states happen at each browser event, and depend on the
    -  // current state, the event that led to this state, and the event input.
    -  switch (this.state_) {
    -    case goog.events.PasteHandler.State.INIT: {
    -      this.handleUnderInit_(e);
    -      break;
    -    }
    -    case goog.events.PasteHandler.State.FOCUSED: {
    -      this.handleUnderFocused_(e);
    -      break;
    -    }
    -    case goog.events.PasteHandler.State.TYPING: {
    -      this.handleUnderTyping_(e);
    -      break;
    -    }
    -    default: {
    -      goog.log.error(this.logger_, 'invalid ' + this.state_ + ' state');
    -    }
    -  }
    -  this.lastTime_ = goog.now();
    -  this.oldValue_ = this.element_.value;
    -  goog.log.info(this.logger_, e.type + ' -> ' + this.state_);
    -  this.previousEvent_ = e.type;
    -};
    -
    -
    -/**
    - * {@code goog.events.PasteHandler.EventType.INIT} is the first initial state
    - * the textarea is found. You can only leave this state by setting focus on the
    - * textarea, which is how users will input text. You can also paste things using
    - * drag and drop, which will not generate a {@code goog.events.EventType.FOCUS}
    - * event, but will generate a {@code goog.events.EventType.MOUSEOVER}.
    - *
    - * For browsers that support the 'paste' event, we match it and stay on the same
    - * state.
    - *
    - * @param {goog.events.BrowserEvent} e The underlying browser event.
    - * @private
    - */
    -goog.events.PasteHandler.prototype.handleUnderInit_ = function(e) {
    -  switch (e.type) {
    -    case goog.events.EventType.BLUR: {
    -      this.state_ = goog.events.PasteHandler.State.INIT;
    -      break;
    -    }
    -    case goog.events.EventType.FOCUS: {
    -      this.state_ = goog.events.PasteHandler.State.FOCUSED;
    -      break;
    -    }
    -    case goog.events.EventType.MOUSEOVER: {
    -      this.state_ = goog.events.PasteHandler.State.INIT;
    -      if (this.element_.value != this.oldValue_) {
    -        goog.log.info(this.logger_, 'paste by dragdrop while on init!');
    -        this.dispatch_(e);
    -      }
    -      break;
    -    }
    -    default: {
    -      goog.log.error(this.logger_,
    -          'unexpected event ' + e.type + 'during init');
    -    }
    -  }
    -};
    -
    -
    -/**
    - * {@code goog.events.PasteHandler.EventType.FOCUSED} is typically the second
    - * state the textarea will be, which is followed by the {@code INIT} state. On
    - * this state, users can paste in three different ways: edit -> paste,
    - * right click -> paste and drag and drop.
    - *
    - * The latter will generate a {@code goog.events.EventType.MOUSEOVER} event,
    - * which we match by making sure the textarea text changed. The first two will
    - * generate an 'input', which we match by making sure it was NOT generated by a
    - * key event (which also generates an 'input' event).
    - *
    - * Unfortunately, in Firefox, if you type fast, some KEYDOWN events are
    - * swallowed but an INPUT event may still happen. That means we need to
    - * differentiate between two consecutive INPUT events being generated either by
    - * swallowed key events OR by a valid edit -> paste -> edit -> paste action. We
    - * do this by checking a minimum time between the two events. This heuristic
    - * seems to work well, but it is obviously a heuristic :).
    - *
    - * @param {goog.events.BrowserEvent} e The underlying browser event.
    - * @private
    - */
    -goog.events.PasteHandler.prototype.handleUnderFocused_ = function(e) {
    -  switch (e.type) {
    -    case 'input' : {
    -      // there are two different events that happen in practice that involves
    -      // consecutive 'input' events. we use a heuristic to differentiate
    -      // between the one that generates a valid paste action and the one that
    -      // doesn't.
    -      // @see testTypingReallyFastDispatchesTwoInputEventsBeforeTheKEYDOWNEvent
    -      // and
    -      // @see testRightClickRightClickAlsoDispatchesTwoConsecutiveInputEvents
    -      // Notice that an 'input' event may be also triggered by a 'middle click'
    -      // paste event, which is described in
    -      // @see testMiddleClickWithoutFocusTriggersPasteEvent
    -      var minimumMilisecondsBetweenInputEvents = this.lastTime_ +
    -          goog.events.PasteHandler.
    -              MANDATORY_MS_BETWEEN_INPUT_EVENTS_TIE_BREAKER;
    -      if (goog.now() > minimumMilisecondsBetweenInputEvents ||
    -          this.previousEvent_ == goog.events.EventType.FOCUS) {
    -        goog.log.info(this.logger_, 'paste by textchange while focused!');
    -        this.dispatch_(e);
    -      }
    -      break;
    -    }
    -    case goog.events.EventType.BLUR: {
    -      this.state_ = goog.events.PasteHandler.State.INIT;
    -      break;
    -    }
    -    case goog.events.EventType.KEYDOWN: {
    -      goog.log.info(this.logger_, 'key down ... looking for ctrl+v');
    -      // Opera + MAC does not set e.ctrlKey. Instead, it gives me e.keyCode = 0.
    -      // http://www.quirksmode.org/js/keys.html
    -      if (goog.userAgent.MAC && goog.userAgent.OPERA && e.keyCode == 0 ||
    -          goog.userAgent.MAC && goog.userAgent.OPERA && e.keyCode == 17) {
    -        break;
    -      }
    -      this.state_ = goog.events.PasteHandler.State.TYPING;
    -      break;
    -    }
    -    case goog.events.EventType.MOUSEOVER: {
    -      if (this.element_.value != this.oldValue_) {
    -        goog.log.info(this.logger_, 'paste by dragdrop while focused!');
    -        this.dispatch_(e);
    -      }
    -      break;
    -    }
    -    default: {
    -      goog.log.error(this.logger_,
    -          'unexpected event ' + e.type + ' during focused');
    -    }
    -  }
    -};
    -
    -
    -/**
    - * {@code goog.events.PasteHandler.EventType.TYPING} is the third state
    - * this class can be. It exists because each KEYPRESS event will ALSO generate
    - * an INPUT event (because the textarea value changes), and we need to
    - * differentiate between an INPUT event generated by a key event and an INPUT
    - * event generated by edit -> paste actions.
    - *
    - * This is the state that we match the ctrl+v pattern.
    - *
    - * @param {goog.events.BrowserEvent} e The underlying browser event.
    - * @private
    - */
    -goog.events.PasteHandler.prototype.handleUnderTyping_ = function(e) {
    -  switch (e.type) {
    -    case 'input' : {
    -      this.state_ = goog.events.PasteHandler.State.FOCUSED;
    -      break;
    -    }
    -    case goog.events.EventType.BLUR: {
    -      this.state_ = goog.events.PasteHandler.State.INIT;
    -      break;
    -    }
    -    case goog.events.EventType.KEYDOWN: {
    -      if (e.ctrlKey && e.keyCode == goog.events.KeyCodes.V ||
    -          e.shiftKey && e.keyCode == goog.events.KeyCodes.INSERT ||
    -          e.metaKey && e.keyCode == goog.events.KeyCodes.V) {
    -        goog.log.info(this.logger_, 'paste by ctrl+v while keypressed!');
    -        this.dispatch_(e);
    -      }
    -      break;
    -    }
    -    case goog.events.EventType.MOUSEOVER: {
    -      if (this.element_.value != this.oldValue_) {
    -        goog.log.info(this.logger_, 'paste by dragdrop while keypressed!');
    -        this.dispatch_(e);
    -      }
    -      break;
    -    }
    -    default: {
    -      goog.log.error(this.logger_,
    -          'unexpected event ' + e.type + ' during keypressed');
    -    }
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/events/pastehandler_test.html b/src/database/third_party/closure-library/closure/goog/events/pastehandler_test.html
    deleted file mode 100644
    index d1ce327cd74..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/pastehandler_test.html
    +++ /dev/null
    @@ -1,26 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.events.PasteHandler
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.events.PasteHandlerTest');
    -  </script>
    - </head>
    - <body>
    -  <textarea id="foo">
    -  </textarea>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/events/pastehandler_test.js b/src/database/third_party/closure-library/closure/goog/events/pastehandler_test.js
    deleted file mode 100644
    index 7072f1fac33..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/pastehandler_test.js
    +++ /dev/null
    @@ -1,409 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.events.PasteHandlerTest');
    -goog.setTestOnly('goog.events.PasteHandlerTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.BrowserEvent');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.events.PasteHandler');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.MockUserAgent');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -function setUp() {
    -  // TODO(user): fix {@code goog.testing.MockUserAgent} to do the right thing.
    -  // the code doesn't seem to be updating the variables with
    -  // goog.userAgent.init_(), which means it is not allowing me to mock the
    -  // user agent variables.
    -  goog.userAgent.GECKO = true;
    -  goog.userAgent.IE = false;
    -  goog.userAgent.WEBKIT = false;
    -  goog.userAgent.VERSION = '1.8';
    -
    -  textarea = new goog.events.EventTarget();
    -  textarea.value = '';
    -  clock = new goog.testing.MockClock(true);
    -  mockUserAgent = new goog.testing.MockUserAgent();
    -  handler = new goog.events.PasteHandler(textarea);
    -  pasted = false;
    -  goog.events.listen(handler, goog.events.PasteHandler.EventType.PASTE,
    -      function() {
    -        pasted = true;
    -      });
    -}
    -
    -function tearDown() {
    -  textarea.dispose();
    -  handler.dispose();
    -  clock.dispose();
    -  mockUserAgent.dispose();
    -}
    -
    -function newBrowserEvent(type) {
    -  if (goog.isString(type)) {
    -    return new goog.events.BrowserEvent({type: type});
    -  } else {
    -    return new goog.events.BrowserEvent(type);
    -  }
    -}
    -
    -function testDispatchingPasteEventSupportedByAFewBrowsersWork() {
    -  goog.userAgent.IE = true;
    -  var handlerThatSupportsPasteEvents =
    -      new goog.events.PasteHandler(textarea);
    -  // user clicks on the textarea and give it focus
    -  goog.events.listen(handlerThatSupportsPasteEvents,
    -      goog.events.PasteHandler.EventType.PASTE,
    -      function() {
    -        pasted = true;
    -      });
    -  textarea.dispatchEvent(newBrowserEvent('paste'));
    -  assertTrue(pasted);
    -}
    -
    -function testJustTypingDoesntFirePasteEvent() {
    -  // user clicks on the textarea and give it focus
    -  textarea.dispatchEvent(newBrowserEvent(goog.events.EventType.FOCUS));
    -  assertFalse(pasted);
    -  // user starts typing
    -  textarea.dispatchEvent(newBrowserEvent({
    -    type: goog.events.EventType.KEYDOWN,
    -    keyCode: goog.events.KeyCodes.A
    -  }));
    -  textarea.value = 'a';
    -  assertFalse(pasted);
    -
    -  // still typing
    -  textarea.dispatchEvent({
    -    type: goog.events.EventType.KEYDOWN,
    -    keyCode: goog.events.KeyCodes.B
    -  });
    -  textarea.value = 'ab';
    -  assertFalse(pasted);
    -
    -  // ends typing
    -  textarea.dispatchEvent({
    -    type: goog.events.EventType.KEYDOWN,
    -    keyCode: goog.events.KeyCodes.C
    -  });
    -  textarea.value = 'abc';
    -  assertFalse(pasted);
    -}
    -
    -function testStartsOnInitialState() {
    -  assertTrue(handler.getState() == goog.events.PasteHandler.State.INIT);
    -  assertFalse(pasted);
    -}
    -
    -function testBlurOnInit() {
    -  textarea.dispatchEvent(goog.events.EventType.BLUR);
    -  assertTrue(handler.getState() == goog.events.PasteHandler.State.INIT);
    -  assertFalse(pasted);
    -}
    -
    -function testFocusOnInit() {
    -  textarea.dispatchEvent(goog.events.EventType.FOCUS);
    -  assertTrue(handler.getState() == goog.events.PasteHandler.State.FOCUSED);
    -  assertFalse(pasted);
    -}
    -
    -function testInputOnFocus() {
    -  // user clicks on the textarea
    -  textarea.dispatchEvent(newBrowserEvent(goog.events.EventType.FOCUS));
    -  clock.tick(
    -      goog.events.PasteHandler.MANDATORY_MS_BETWEEN_INPUT_EVENTS_TIE_BREAKER +
    -      1);
    -  // and right click -> paste a text!
    -  textarea.dispatchEvent(newBrowserEvent('input'));
    -  assertTrue(handler.getState() == goog.events.PasteHandler.State.FOCUSED);
    -  // make sure we detected it
    -  assertTrue(pasted);
    -}
    -
    -function testKeyPressOnFocus() {
    -  // user clicks on the textarea
    -  textarea.dispatchEvent(newBrowserEvent(goog.events.EventType.FOCUS));
    -
    -  // starts typing something
    -  textarea.dispatchEvent(newBrowserEvent({
    -    type: goog.events.EventType.KEYDOWN,
    -    keyCode: goog.events.KeyCodes.A
    -  }));
    -  assertTrue(handler.getState() == goog.events.PasteHandler.State.TYPING);
    -  assertFalse(pasted);
    -
    -  // and then presses ctrl+v
    -  textarea.dispatchEvent(newBrowserEvent({
    -    type: goog.events.EventType.KEYDOWN,
    -    keyCode: goog.events.KeyCodes.V,
    -    ctrlKey: true
    -  }));
    -  assertTrue(handler.getState() == goog.events.PasteHandler.State.TYPING);
    -
    -  // makes sure we detected it
    -  assertTrue(pasted);
    -}
    -
    -function testMouseOverOnInit() {
    -  // user has something on the events
    -  textarea.value = 'pasted string';
    -  // and right click -> paste it on the textarea, WITHOUT giving focus
    -  textarea.dispatchEvent(newBrowserEvent(goog.events.EventType.MOUSEOVER));
    -  assertTrue(handler.getState() == goog.events.PasteHandler.State.INIT);
    -  // makes sure we detect it
    -  assertTrue(pasted);
    -
    -  pasted = false;
    -
    -  // user normaly mouseovers the textarea, with no text change
    -  textarea.dispatchEvent(goog.events.EventType.MOUSEOVER);
    -  assertTrue(handler.getState() == goog.events.PasteHandler.State.INIT);
    -  // text area value doesnt change
    -  assertFalse(pasted);
    -}
    -
    -function testMouseOverAfterTyping() {
    -  textarea.dispatchEvent(goog.events.EventType.FOCUS);
    -  assertFalse(pasted);
    -  textarea.dispatchEvent(
    -      {type: goog.events.EventType.KEYDOWN, keyCode: goog.events.KeyCodes.A});
    -  assertFalse(pasted);
    -  textarea.value = 'a';
    -  textarea.dispatchEvent('input');
    -  assertFalse(pasted);
    -  assertEquals('a', handler.oldValue_);
    -  textarea.dispatchEvent(goog.events.EventType.MOUSEOVER);
    -  assertFalse(pasted);
    -}
    -
    -function testTypingAndThenRightClickPaste() {
    -  textarea.dispatchEvent(goog.events.EventType.FOCUS);
    -
    -  textarea.dispatchEvent(
    -      {type: goog.events.EventType.KEYDOWN, keyCode: goog.events.KeyCodes.A});
    -  assertFalse(pasted);
    -  textarea.value = 'a';
    -  clock.tick(
    -      goog.events.PasteHandler.MANDATORY_MS_BETWEEN_INPUT_EVENTS_TIE_BREAKER +
    -      1);
    -  textarea.dispatchEvent('input');
    -  assertFalse(pasted);
    -
    -  assertEquals('a', handler.oldValue_);
    -
    -  textarea.value = 'ab';
    -  clock.tick(
    -      goog.events.PasteHandler.MANDATORY_MS_BETWEEN_INPUT_EVENTS_TIE_BREAKER +
    -      1);
    -  textarea.dispatchEvent(newBrowserEvent('input'));
    -  assertTrue(pasted);
    -}
    -
    -function testTypingReallyFastDispatchesTwoInputEventsBeforeTheKeyDownEvent() {
    -  textarea.dispatchEvent(goog.events.EventType.FOCUS);
    -
    -  // keydown and input events seems to be fired indepently: even though input
    -  // should happen after the key event, it doens't if the user types fast
    -  // enough. FF2 + linux doesn't fire keydown events for every key pressed when
    -  // you type fast enough. if one of the keydown events gets swallowed, two
    -  // input events are fired consecutively. notice that there is a similar
    -  // scenario, that actually does produce a valid paste action.
    -  // {@see testRightClickRightClickAlsoDispatchesTwoConsecutiveInputEvents}
    -
    -  textarea.dispatchEvent(
    -      {type: goog.events.EventType.KEYDOWN, keyCode: goog.events.KeyCodes.A});
    -  assertFalse(pasted);
    -  textarea.value = 'a';
    -  clock.tick(
    -      goog.events.PasteHandler.MANDATORY_MS_BETWEEN_INPUT_EVENTS_TIE_BREAKER -
    -      1);
    -  textarea.dispatchEvent('input');
    -  assertFalse(pasted);
    -
    -  // second key down events gets fired on a different order
    -  textarea.value = 'ab';
    -  clock.tick(
    -      goog.events.PasteHandler.MANDATORY_MS_BETWEEN_INPUT_EVENTS_TIE_BREAKER -
    -      1);
    -  textarea.dispatchEvent('input');
    -  assertFalse(pasted);
    -}
    -
    -function testRightClickRightClickAlsoDispatchesTwoConsecutiveInputEvents() {
    -  textarea.dispatchEvent(goog.events.EventType.FOCUS);
    -
    -  // there is also another case that two consecutive INPUT events are fired,
    -  // but in a valid paste action: if the user edit -> paste -> edit -> paste,
    -  // it is a valid paste action.
    -
    -  textarea.value = 'a';
    -  clock.tick(
    -      goog.events.PasteHandler.MANDATORY_MS_BETWEEN_INPUT_EVENTS_TIE_BREAKER +
    -      1);
    -  textarea.dispatchEvent(newBrowserEvent('input'));
    -  assertTrue(pasted);
    -
    -  // second key down events gets fired on a different order
    -  textarea.value = 'ab';
    -  clock.tick(
    -      goog.events.PasteHandler.MANDATORY_MS_BETWEEN_INPUT_EVENTS_TIE_BREAKER +
    -      1);
    -  textarea.dispatchEvent(newBrowserEvent('input'));
    -  assertTrue(pasted);
    -}
    -
    -function testMiddleClickWithoutFocusTriggersPasteEvent() {
    -  // if the textarea is NOT selected, and then we use the middle button,
    -  // FF2+linux pastes what was last highlighted, causing a paste action.
    -  textarea.dispatchEvent(goog.events.EventType.FOCUS);
    -  textarea.dispatchEvent(newBrowserEvent('input'));
    -  assertTrue(pasted);
    -}
    -
    -
    -function testMacRightClickPasteRequiresCtrlBecauseItHasOneButton() {
    -  // Macs don't have two buttons mouse: this means that you need to press
    -  // ctrl + click to get to the menu, and then you can click paste.
    -  // The sequences of events fired on Opera are:
    -  // focus -> keydown (keyCode == 0, not e.ctrlKey) -> input
    -  goog.userAgent.OPERA = true;
    -  goog.userAgent.MAC = true;
    -  var handler = new goog.events.PasteHandler(textarea);
    -  // user clicks on the textarea and give it focus
    -  goog.events.listen(handler,
    -      goog.events.PasteHandler.EventType.PASTE,
    -      function() {
    -        pasted = true;
    -      });
    -  textarea.dispatchEvent(goog.events.EventType.FOCUS);
    -  assertFalse(pasted);
    -  textarea.dispatchEvent({type: goog.events.EventType.KEYDOWN, keyCode: 0});
    -  assertFalse(pasted);
    -  clock.tick(
    -      goog.events.PasteHandler.MANDATORY_MS_BETWEEN_INPUT_EVENTS_TIE_BREAKER +
    -      1);
    -  textarea.dispatchEvent(newBrowserEvent('input'));
    -  assertTrue(pasted);
    -}
    -
    -function testOperaMacFiresKeyCode17WhenAppleKeyPressedButDoesNotFireKeyDown() {
    -  // Opera on Macs fires keycode 17 when apple key is pressed, and then it does
    -  // not fire a keydown event when the V is pressed.
    -  goog.userAgent.OPERA = true;
    -  goog.userAgent.MAC = true;
    -  var handler = new goog.events.PasteHandler(textarea);
    -  // user clicks on the textarea and give it focus
    -  goog.events.listen(handler,
    -      goog.events.PasteHandler.EventType.PASTE,
    -      function() {
    -        pasted = true;
    -      });
    -  textarea.dispatchEvent(goog.events.EventType.FOCUS);
    -  assertFalse(pasted);
    -  // apple key is pressed, generating a keydown event
    -  textarea.dispatchEvent({type: goog.events.EventType.KEYDOWN, keyCode: 17});
    -  assertFalse(pasted);
    -  clock.tick(
    -      goog.events.PasteHandler.MANDATORY_MS_BETWEEN_INPUT_EVENTS_TIE_BREAKER +
    -      1);
    -  // and then text is added magically without any extra keydown events.
    -  textarea.dispatchEvent(newBrowserEvent('input'));
    -  assertTrue(pasted);
    -}
    -
    -function testScriptingDoesntTriggerPasteEvents() {
    -  var handlerUsedToListenForScriptingChanges =
    -      new goog.events.PasteHandler(textarea);
    -  pasted = false;
    -  // user clicks on the textarea and give it focus
    -  goog.events.listen(handlerUsedToListenForScriptingChanges,
    -      goog.events.PasteHandler.EventType.PASTE,
    -      function() {
    -        pasted = true;
    -      });
    -  goog.dom.getElement('foo').value = 'dear paste handler,';
    -  assertFalse(pasted);
    -  goog.dom.getElement('foo').value = 'please dont misunderstand script changes';
    -  assertFalse(pasted);
    -  goog.dom.getElement('foo').value = 'with user generated paste events';
    -  assertFalse(pasted);
    -  goog.dom.getElement('foo').value = 'thanks!';
    -  assertFalse(pasted);
    -}
    -
    -function testAfterPaste() {
    -  goog.userAgent.IE = true;
    -  var handlerThatSupportsPasteEvents =
    -      new goog.events.PasteHandler(textarea);
    -  pasted = false;
    -  goog.events.listen(handlerThatSupportsPasteEvents,
    -      goog.events.PasteHandler.EventType.PASTE,
    -      function() {
    -        pasted = true;
    -      });
    -  var afterPasteFired = false;
    -  goog.events.listen(handlerThatSupportsPasteEvents,
    -      goog.events.PasteHandler.EventType.AFTER_PASTE,
    -      function() {
    -        afterPasteFired = true;
    -      });
    -
    -  // Initial paste event comes before AFTER_PASTE has fired.
    -  textarea.dispatchEvent(newBrowserEvent('paste'));
    -  assertTrue(pasted);
    -  assertFalse(afterPasteFired);
    -
    -  // Once text is pasted, it takes a bit to detect it, at which point
    -  // AFTER_PASTE is fired.
    -  clock.tick(goog.events.PasteHandler.PASTE_POLLING_PERIOD_MS_);
    -  textarea.value = 'text';
    -  clock.tick(goog.events.PasteHandler.PASTE_POLLING_PERIOD_MS_);
    -  assertTrue(afterPasteFired);
    -}
    -
    -
    -function testAfterPasteNotFiredIfDelayTooLong() {
    -  goog.userAgent.IE = true;
    -  var handlerThatSupportsPasteEvents =
    -      new goog.events.PasteHandler(textarea);
    -  pasted = false;
    -  goog.events.listen(handlerThatSupportsPasteEvents,
    -      goog.events.PasteHandler.EventType.PASTE,
    -      function() {
    -        pasted = true;
    -      });
    -  var afterPasteFired = false;
    -  goog.events.listen(handlerThatSupportsPasteEvents,
    -      goog.events.PasteHandler.EventType.AFTER_PASTE,
    -      function() {
    -        afterPasteFired = true;
    -      });
    -
    -  // Initial paste event comes before AFTER_PASTE has fired.
    -  textarea.dispatchEvent(newBrowserEvent('paste'));
    -  assertTrue(pasted);
    -  assertFalse(afterPasteFired);
    -
    -  // If the new text doesn't show up in time, we never fire AFTER_PASTE.
    -  clock.tick(goog.events.PasteHandler.PASTE_POLLING_TIMEOUT_MS_);
    -  textarea.value = 'text';
    -  clock.tick(goog.events.PasteHandler.PASTE_POLLING_PERIOD_MS_);
    -  assertFalse(afterPasteFired);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/events/wheelevent.js b/src/database/third_party/closure-library/closure/goog/events/wheelevent.js
    deleted file mode 100644
    index 1f172eb0672..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/wheelevent.js
    +++ /dev/null
    @@ -1,169 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview This class aims to smooth out inconsistencies between browser
    - * handling of wheel events by providing an event that is similar to that
    - * defined in the standard, but also easier to consume.
    - *
    - * It is based upon the WheelEvent, which allows for up to 3 dimensional
    - * scrolling events that come in units of either pixels, lines or pages.
    - * http://www.w3.org/TR/2014/WD-DOM-Level-3-Events-20140925/#interface-WheelEvent
    - *
    - * The significant difference here is that it also provides reasonable pixel
    - * deltas for clients that do not want to treat line and page scrolling events
    - * specially.
    - *
    - * Clients of this code should be aware that some input devices only fire a few
    - * discrete events (such as a mouse wheel without acceleration) whereas some can
    - * generate a large number of events for a single interaction (such as a
    - * touchpad with acceleration). There is no signal in the events to reliably
    - * distinguish between these.
    - *
    - * @see ../demos/wheelhandler.html
    - */
    -
    -goog.provide('goog.events.WheelEvent');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.events.BrowserEvent');
    -
    -
    -
    -/**
    - * A common class for wheel events. This is used with the WheelHandler.
    - *
    - * @param {Event} browserEvent Browser event object.
    - * @param {goog.events.WheelEvent.DeltaMode} deltaMode The delta mode units of
    - *     the wheel event.
    - * @param {number} deltaX The number of delta units the user in the X axis.
    - * @param {number} deltaY The number of delta units the user in the Y axis.
    - * @param {number} deltaZ The number of delta units the user in the Z axis.
    - * @constructor
    - * @extends {goog.events.BrowserEvent}
    - * @final
    - */
    -goog.events.WheelEvent = function(
    -    browserEvent, deltaMode, deltaX, deltaY, deltaZ) {
    -  goog.events.WheelEvent.base(this, 'constructor', browserEvent);
    -  goog.asserts.assert(browserEvent, 'Expecting a non-null browserEvent');
    -
    -  /** @type {goog.events.WheelEvent.EventType} */
    -  this.type = goog.events.WheelEvent.EventType.WHEEL;
    -
    -  /**
    -   * An enum corresponding to the units of this event.
    -   * @type {goog.events.WheelEvent.DeltaMode}
    -   */
    -  this.deltaMode = deltaMode;
    -
    -  /**
    -   * The number of delta units in the X axis.
    -   * @type {number}
    -   */
    -  this.deltaX = deltaX;
    -
    -  /**
    -   * The number of delta units in the Y axis.
    -   * @type {number}
    -   */
    -  this.deltaY = deltaY;
    -
    -  /**
    -   * The number of delta units in the Z axis.
    -   * @type {number}
    -   */
    -  this.deltaZ = deltaZ;
    -
    -  // Ratio between delta and pixel values.
    -  var pixelRatio = 1;  // Value for DeltaMode.PIXEL
    -  switch (deltaMode) {
    -    case goog.events.WheelEvent.DeltaMode.PAGE:
    -      pixelRatio *= goog.events.WheelEvent.PIXELS_PER_PAGE_;
    -      break;
    -    case goog.events.WheelEvent.DeltaMode.LINE:
    -      pixelRatio *= goog.events.WheelEvent.PIXELS_PER_LINE_;
    -      break;
    -  }
    -
    -  /**
    -   * The number of delta pixels in the X axis. Code that doesn't want to handle
    -   * different deltaMode units can just look here.
    -   * @type {number}
    -   */
    -  this.pixelDeltaX = this.deltaX * pixelRatio;
    -
    -  /**
    -   * The number of pixels in the Y axis. Code that doesn't want to
    -   * handle different deltaMode units can just look here.
    -   * @type {number}
    -   */
    -  this.pixelDeltaY = this.deltaY * pixelRatio;
    -
    -  /**
    -   * The number of pixels scrolled in the Z axis. Code that doesn't want to
    -   * handle different deltaMode units can just look here.
    -   * @type {number}
    -   */
    -  this.pixelDeltaZ = this.deltaZ * pixelRatio;
    -};
    -goog.inherits(goog.events.WheelEvent, goog.events.BrowserEvent);
    -
    -
    -/**
    - * Enum type for the events fired by the wheel handler.
    - * @enum {string}
    - */
    -goog.events.WheelEvent.EventType = {
    -  /** The user has provided wheel-based input. */
    -  WHEEL: 'wheel'
    -};
    -
    -
    -/**
    - * Units for the deltas in a WheelEvent.
    - * @enum {number}
    - */
    -goog.events.WheelEvent.DeltaMode = {
    -  /** The units are in pixels. From DOM_DELTA_PIXEL. */
    -  PIXEL: 0,
    -  /** The units are in lines. From DOM_DELTA_LINE. */
    -  LINE: 1,
    -  /** The units are in pages. From DOM_DELTA_PAGE. */
    -  PAGE: 2
    -};
    -
    -
    -/**
    - * A conversion number between line scroll units and pixel scroll units. The
    - * actual value per line can vary a lot between devices and font sizes. This
    - * number can not be perfect, but it should be reasonable for converting lines
    - * scroll events into pixels.
    - * @const {number}
    - * @private
    - */
    -goog.events.WheelEvent.PIXELS_PER_LINE_ = 15;
    -
    -
    -/**
    - * A conversion number between page scroll units and pixel scroll units. The
    - * actual value per page can vary a lot as many different devices have different
    - * screen sizes, and the window might not be taking up the full screen. This
    - * number can not be perfect, but it should be reasonable for converting page
    - * scroll events into pixels.
    - * @const {number}
    - * @private
    - */
    -goog.events.WheelEvent.PIXELS_PER_PAGE_ = 30 *
    -    goog.events.WheelEvent.PIXELS_PER_LINE_;
    diff --git a/src/database/third_party/closure-library/closure/goog/events/wheelhandler.js b/src/database/third_party/closure-library/closure/goog/events/wheelhandler.js
    deleted file mode 100644
    index 9d0f1e33fe7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/wheelhandler.js
    +++ /dev/null
    @@ -1,159 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview This event wrapper will dispatch an event when the user uses
    - * the wheel on an element. The event provides details of the unit type (pixel /
    - * line / page) and deltas in those units in up to 3 dimensions. Additionally,
    - * simplified pixel deltas are provided for code that doesn't need to handle the
    - * different units differently. This is not to be confused with the scroll
    - * event, where an element in the dom can report that it was scrolled.
    - *
    - * This class aims to smooth out inconsistencies between browser platforms with
    - * regards to wheel events, but we do not cover every possible software/hardware
    - * combination out there, some of which occasionally produce very large deltas
    - * in wheel events, especially when the device supports acceleration.
    - *
    - * Relevant standard:
    - * http://www.w3.org/TR/2014/WD-DOM-Level-3-Events-20140925/#interface-WheelEvent
    - *
    - * Clients of this code should be aware that some input devices only fire a few
    - * discrete events (such as a mouse wheel without acceleration) whereas some can
    - * generate a large number of events for a single interaction (such as a
    - * touchpad with acceleration). There is no signal in the events to reliably
    - * distinguish between these.
    - *
    - * @author arv@google.com (Erik Arvidsson)
    - * @see ../demos/wheelhandler.html
    - */
    -
    -goog.provide('goog.events.WheelHandler');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.WheelEvent');
    -goog.require('goog.style');
    -goog.require('goog.userAgent');
    -goog.require('goog.userAgent.product');
    -goog.require('goog.userAgent.product.isVersion');
    -
    -
    -
    -/**
    - * This event handler allows you to catch wheel events in a consistent manner.
    - * @param {!Element|!Document} element The element to listen to the wheel event
    - *     on.
    - * @param {boolean=} opt_capture Whether to handle the wheel event in capture
    - *     phase.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - */
    -goog.events.WheelHandler = function(element, opt_capture) {
    -  goog.events.WheelHandler.base(this, 'constructor');
    -
    -  /**
    -   * This is the element that we will listen to the real wheel events on.
    -   * @private {!Element|!Document}
    -   */
    -  this.element_ = element;
    -
    -  var rtlElement = goog.dom.isElement(this.element_) ?
    -      /** @type {!Element} */ (this.element_) :
    -      /** @type {!Document} */ (this.element_).body;
    -
    -  /**
    -   * True if the element exists and is RTL, false otherwise.
    -   * @private {boolean}
    -   */
    -  this.isRtl_ = !!rtlElement && goog.style.isRightToLeft(rtlElement);
    -
    -  /**
    -   * The key returned from the goog.events.listen.
    -   * @private {goog.events.Key}
    -   */
    -  this.listenKey_ = goog.events.listen(
    -      this.element_, goog.events.WheelHandler.getDomEventType(),
    -      this, opt_capture);
    -};
    -goog.inherits(goog.events.WheelHandler, goog.events.EventTarget);
    -
    -
    -/**
    - * Returns the dom event type.
    - * @return {string} The dom event type.
    - */
    -goog.events.WheelHandler.getDomEventType = function() {
    -  // Prefer to use wheel events whenever supported.
    -  if (goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher(17) ||
    -      goog.userAgent.IE && goog.userAgent.isVersionOrHigher(9) ||
    -      goog.userAgent.product.CHROME && goog.userAgent.product.isVersion(31)) {
    -    return 'wheel';
    -  }
    -
    -  // Legacy events. Still the best we have on Opera and Safari.
    -  return goog.userAgent.GECKO ? 'DOMMouseScroll' : 'mousewheel';
    -};
    -
    -
    -/**
    - * Handles the events on the element.
    - * @param {!goog.events.BrowserEvent} e The underlying browser event.
    - */
    -goog.events.WheelHandler.prototype.handleEvent = function(e) {
    -  var deltaMode = goog.events.WheelEvent.DeltaMode.PIXEL;
    -  var deltaX = 0;
    -  var deltaY = 0;
    -  var deltaZ = 0;
    -  var be = e.getBrowserEvent();
    -  if (be.type == 'wheel') {
    -    deltaMode = be.deltaMode;
    -    deltaX = be.deltaX;
    -    deltaY = be.deltaY;
    -    deltaZ = be.deltaZ;
    -  } else if (be.type == 'mousewheel') {
    -    // Assume that these are still comparable to pixels. This may not be true
    -    // for all old browsers.
    -    if (goog.isDef(be.wheelDeltaX)) {
    -      deltaX = -be.wheelDeltaX;
    -      deltaY = -be.wheelDeltaY;
    -    } else {
    -      deltaY = -be.wheelDelta;
    -    }
    -  } else { // Historical Gecko
    -    // Gecko returns multiple of 3 (representing the number of lines)
    -    deltaMode = goog.events.WheelEvent.DeltaMode.LINE;
    -    // Firefox 3.1 adds an axis field to the event to indicate axis.
    -    if (goog.isDef(be.axis) && be.axis === be.HORIZONTAL_AXIS) {
    -      deltaX = be.detail;
    -    } else {
    -      deltaY = be.detail;
    -    }
    -  }
    -  // For horizontal deltas we need to flip the value for RTL grids.
    -  if (this.isRtl_) {
    -    deltaX = -deltaX;
    -  }
    -  var newEvent = new goog.events.WheelEvent(
    -      be, deltaMode, deltaX, deltaY, deltaZ);
    -  this.dispatchEvent(newEvent);
    -};
    -
    -
    -/** @override */
    -goog.events.WheelHandler.prototype.disposeInternal = function() {
    -  goog.events.WheelHandler.superClass_.disposeInternal.call(this);
    -  goog.events.unlistenByKey(this.listenKey_);
    -  this.listenKey_ = null;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/events/wheelhandler_test.html b/src/database/third_party/closure-library/closure/goog/events/wheelhandler_test.html
    deleted file mode 100644
    index 97994b3ba0e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/wheelhandler_test.html
    +++ /dev/null
    @@ -1,31 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.events.WheelHandler
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.events.WheelHandlerTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="foo">
    -  </div>
    -  <div id="fooRtl" dir="rtl">
    -  </div>
    -  <div id="log" style="position:absolute;right:0;top:0">
    -   Logged events:
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/events/wheelhandler_test.js b/src/database/third_party/closure-library/closure/goog/events/wheelhandler_test.js
    deleted file mode 100644
    index 179667d6620..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/events/wheelhandler_test.js
    +++ /dev/null
    @@ -1,296 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.events.WheelHandlerTest');
    -goog.setTestOnly('goog.events.WheelHandlerTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.BrowserEvent');
    -goog.require('goog.events.WheelEvent');
    -goog.require('goog.events.WheelHandler');
    -goog.require('goog.string');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -goog.require('goog.userAgent.product');
    -
    -var log;
    -var stubs = new goog.testing.PropertyReplacer();
    -
    -var PREFERRED_TYPE = 'wheel';
    -var LEGACY_TYPE = 'mousewheel';
    -var GECKO_TYPE = 'DOMMouseScroll';
    -
    -var HORIZONTAL = 'h';
    -var VERTICAL = 'v';
    -
    -var DeltaMode = goog.events.WheelEvent.DeltaMode;
    -
    -var mouseWheelEvent;
    -var mouseWheelEventRtl;
    -var mouseWheelHandler;
    -var mouseWheelHandlerRtl;
    -
    -function setUpPage() {
    -  log = goog.dom.getElement('log');
    -}
    -
    -function setUp() {
    -  stubs.remove(goog, 'userAgent');
    -  goog.userAgent = {
    -    product: {
    -      CHROME: false,
    -      version: 0,
    -      isVersion: function(version) {
    -        return goog.string.compareVersions(this.version, version) >= 0;
    -      }
    -    },
    -    GECKO: false,
    -    IE: false,
    -    version: 0,
    -    isVersionOrHigher: function(version) {
    -      return goog.string.compareVersions(this.version, version) >= 0;
    -    }
    -  };
    -}
    -
    -function tearDown() {
    -  stubs.reset();
    -  goog.dispose(mouseWheelHandler);
    -  goog.dispose(mouseWheelHandlerRtl);
    -  mouseWheelHandlerRtl = null;
    -  mouseWheelHandler = null;
    -  mouseWheelEvent = null;
    -  mouseWheelEventRtl = null;
    -}
    -
    -function tearDownPage() {
    -  // Create interactive demo.
    -  mouseWheelHandler = new goog.events.WheelHandler(document.body);
    -
    -  goog.events.listen(mouseWheelHandler,
    -      goog.events.WheelEvent.EventType.WHEEL,
    -      function(e) {
    -        log.innerHTML += goog.string.subs('<br />(deltaX, deltaY): (%s, %s)',
    -            e.deltaX, e.deltaY);
    -      });
    -}
    -
    -function testGetDomEventType() {
    -  // Defaults to legacy non-gecko event.
    -  assertEquals(LEGACY_TYPE, goog.events.WheelHandler.getDomEventType());
    -
    -  // Gecko start to support wheel with version 17.
    -  goog.userAgent.GECKO = true;
    -  goog.userAgent.version = 16;
    -  assertEquals(GECKO_TYPE, goog.events.WheelHandler.getDomEventType());
    -  goog.userAgent.version = 17;
    -  assertEquals(PREFERRED_TYPE, goog.events.WheelHandler.getDomEventType());
    -  goog.userAgent.GECKO = false;
    -
    -  // IE started with version 9.
    -  goog.userAgent.IE = true;
    -  goog.userAgent.version = 8;
    -  assertEquals(LEGACY_TYPE, goog.events.WheelHandler.getDomEventType());
    -  goog.userAgent.version = 9;
    -  assertEquals(PREFERRED_TYPE, goog.events.WheelHandler.getDomEventType());
    -  goog.userAgent.IE = false;
    -
    -  // Chrome started with version 31.
    -  goog.userAgent.product.CHROME = true;
    -  goog.userAgent.product.version = 30;
    -  assertEquals(LEGACY_TYPE, goog.events.WheelHandler.getDomEventType());
    -  goog.userAgent.product.version = 31;
    -  assertEquals(PREFERRED_TYPE, goog.events.WheelHandler.getDomEventType());
    -  goog.userAgent.product.CHROME = false;
    -}
    -
    -function testPreferredStyleWheel() {
    -  // Enable 'wheel'
    -  goog.userAgent.IE = true;
    -  goog.userAgent.version = 9;
    -  createHandlerAndListen();
    -
    -  handleEvent(createFakePreferredEvent(DeltaMode.PIXEL, 10, 20, 30));
    -  assertWheelEvent(DeltaMode.PIXEL, 10, 20, 30);
    -  assertPixelDeltas(1);
    -
    -  handleEvent(createFakePreferredEvent(DeltaMode.LINE, 10, 20, 30));
    -  assertWheelEvent(DeltaMode.LINE, 10, 20, 30);
    -  assertPixelDeltas(15);
    -
    -  handleEvent(createFakePreferredEvent(DeltaMode.PAGE, 10, 20, 30));
    -  assertWheelEvent(DeltaMode.PAGE, 10, 20, 30);
    -  assertPixelDeltas(30 * 15);
    -}
    -
    -function testLegacyStyleWheel() {
    -  // 'mousewheel' enabled by default
    -  createHandlerAndListen();
    -
    -  // Test one dimensional.
    -  handleEvent(createFakeLegacyEvent(10));
    -  assertWheelEvent(DeltaMode.PIXEL, 0, -10, 0);
    -  assertPixelDeltas(1);
    -
    -  // Test two dimensional.
    -  handleEvent(createFakeLegacyEvent(/* ignored */ 10, 20, 30));
    -  assertWheelEvent(DeltaMode.PIXEL, -20, -30, 0);
    -  assertPixelDeltas(1);
    -}
    -
    -function testLegacyGeckoStyleWheel() {
    -  goog.userAgent.GECKO = true;
    -  createHandlerAndListen();
    -
    -  // Test no axis.
    -  handleEvent(createFakeGeckoEvent(10));
    -  assertWheelEvent(DeltaMode.LINE, 0, 10, 0);
    -  assertPixelDeltas(15);
    -
    -  // Vertical axis.
    -  handleEvent(createFakeGeckoEvent(10, VERTICAL));
    -  assertWheelEvent(DeltaMode.LINE, 0, 10, 0);
    -  assertPixelDeltas(15);
    -
    -  // Horizontal axis.
    -  handleEvent(createFakeGeckoEvent(10, HORIZONTAL));
    -  assertWheelEvent(DeltaMode.LINE, 10, 0, 0);
    -  assertPixelDeltas(15);
    -}
    -
    -function testLegacyIeStyleWheel() {
    -  goog.userAgent.IE = true;
    -
    -  createHandlerAndListen();
    -
    -  // Non-gecko, non-webkit events get wheelDelta divided by -40 to get detail.
    -  handleEvent(createFakeLegacyEvent(120));
    -  assertWheelEvent(DeltaMode.PIXEL, 0, -120, 0);
    -
    -  handleEvent(createFakeLegacyEvent(-120));
    -  assertWheelEvent(DeltaMode.PIXEL, 0, 120, 0);
    -
    -  handleEvent(createFakeLegacyEvent(1200));
    -  assertWheelEvent(DeltaMode.PIXEL, 0, -1200, 0);
    -}
    -
    -function testNullBody() {
    -  goog.userAgent.IE = true;
    -  var documentObjectWithNoBody = { };
    -  goog.testing.events.mixinListenable(documentObjectWithNoBody);
    -  mouseWheelHandler =
    -      new goog.events.WheelHandler(documentObjectWithNoBody);
    -}
    -
    -// Be sure to call this after setting up goog.userAgent mock and not before.
    -function createHandlerAndListen() {
    -  mouseWheelHandler = new goog.events.WheelHandler(
    -      goog.dom.getElement('foo'));
    -
    -  goog.events.listen(mouseWheelHandler,
    -      goog.events.WheelEvent.EventType.WHEEL,
    -      function(e) { mouseWheelEvent = e; });
    -
    -  mouseWheelHandlerRtl = new goog.events.WheelHandler(
    -      goog.dom.getElement('fooRtl'));
    -
    -  goog.events.listen(mouseWheelHandlerRtl,
    -      goog.events.WheelEvent.EventType.WHEEL,
    -      function(e) { mouseWheelEventRtl = e; });
    -}
    -
    -function handleEvent(event) {
    -  mouseWheelHandler.handleEvent(event);
    -  mouseWheelHandlerRtl.handleEvent(event);
    -}
    -
    -function assertWheelEvent(deltaMode, deltaX, deltaY, deltaZ) {
    -  assertTrue('event should be non-null', !!mouseWheelEvent);
    -  assertTrue('event should have correct JS type',
    -      mouseWheelEvent instanceof goog.events.WheelEvent);
    -  assertEquals('event should have correct deltaMode property',
    -      deltaMode, mouseWheelEvent.deltaMode);
    -  assertEquals('event should have correct deltaX property',
    -      deltaX, mouseWheelEvent.deltaX);
    -  assertEquals('event should have correct deltaY property',
    -      deltaY, mouseWheelEvent.deltaY);
    -  assertEquals('event should have correct deltaZ property',
    -      deltaZ, mouseWheelEvent.deltaZ);
    -
    -  // RTL
    -  assertTrue('event should be non-null', !!mouseWheelEventRtl);
    -  assertTrue('event should have correct JS type',
    -      mouseWheelEventRtl instanceof goog.events.WheelEvent);
    -  assertEquals('event should have correct deltaMode property',
    -      deltaMode, mouseWheelEventRtl.deltaMode);
    -  assertEquals('event should have correct deltaX property',
    -      -deltaX, mouseWheelEventRtl.deltaX);
    -  assertEquals('event should have correct deltaY property',
    -      deltaY, mouseWheelEventRtl.deltaY);
    -  assertEquals('event should have correct deltaZ property',
    -      deltaZ, mouseWheelEventRtl.deltaZ);
    -
    -}
    -
    -function assertPixelDeltas(scale) {
    -  assertEquals(mouseWheelEvent.deltaX * scale, mouseWheelEvent.pixelDeltaX);
    -  assertEquals(mouseWheelEvent.deltaY * scale, mouseWheelEvent.pixelDeltaY);
    -  assertEquals(mouseWheelEvent.deltaZ * scale, mouseWheelEvent.pixelDeltaZ);
    -
    -  // RTL
    -  assertEquals(mouseWheelEventRtl.deltaX * scale,
    -      mouseWheelEventRtl.pixelDeltaX);
    -  assertEquals(mouseWheelEventRtl.deltaY * scale,
    -      mouseWheelEventRtl.pixelDeltaY);
    -  assertEquals(mouseWheelEventRtl.deltaZ * scale,
    -      mouseWheelEventRtl.pixelDeltaZ);
    -}
    -
    -function createFakePreferredEvent(
    -    opt_deltaMode, opt_deltaX, opt_deltaY, opt_deltaZ) {
    -  var event = {
    -    type: PREFERRED_TYPE,
    -    deltaMode: opt_deltaMode,
    -    deltaX: opt_deltaX,
    -    deltaY: opt_deltaY,
    -    deltaZ: opt_deltaZ
    -  };
    -  return new goog.events.BrowserEvent(event);
    -}
    -
    -
    -function createFakeLegacyEvent(
    -    opt_wheelDelta, opt_wheelDeltaX, opt_wheelDeltaY) {
    -  var event = {
    -    type: LEGACY_TYPE,
    -    wheelDelta: opt_wheelDelta,
    -    wheelDeltaX: opt_wheelDeltaX,
    -    wheelDeltaY: opt_wheelDeltaY
    -  };
    -  return new goog.events.BrowserEvent(event);
    -}
    -
    -function createFakeGeckoEvent(opt_detail, opt_axis) {
    -  var event = {
    -    type: GECKO_TYPE,
    -    detail: opt_detail,
    -    axis: opt_axis,
    -    HORIZONTAL_AXIS: HORIZONTAL,
    -    VERTICAL_AXIS: VERTICAL
    -  };
    -  return new goog.events.BrowserEvent(event);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/format/emailaddress.js b/src/database/third_party/closure-library/closure/goog/format/emailaddress.js
    deleted file mode 100644
    index 670bc33c783..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/format/emailaddress.js
    +++ /dev/null
    @@ -1,499 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides functions to parse and manipulate email addresses.
    - *
    - */
    -
    -goog.provide('goog.format.EmailAddress');
    -
    -goog.require('goog.string');
    -
    -
    -
    -/**
    - * Formats an email address string for display, and allows for extraction of
    - * the individual components of the address.
    - * @param {string=} opt_address The email address.
    - * @param {string=} opt_name The name associated with the email address.
    - * @constructor
    - */
    -goog.format.EmailAddress = function(opt_address, opt_name) {
    -  /**
    -   * The name or personal string associated with the address.
    -   * @type {string}
    -   * @private
    -   */
    -  this.name_ = opt_name || '';
    -
    -  /**
    -   * The email address.
    -   * @type {string}
    -   * @protected
    -   */
    -  this.address = opt_address || '';
    -};
    -
    -
    -/**
    - * Match string for opening tokens.
    - * @type {string}
    - * @private
    - */
    -goog.format.EmailAddress.OPENERS_ = '"<([';
    -
    -
    -/**
    - * Match string for closing tokens.
    - * @type {string}
    - * @private
    - */
    -goog.format.EmailAddress.CLOSERS_ = '">)]';
    -
    -
    -/**
    - * Match string for characters that require display names to be quoted and are
    - * not address separators.
    - * @type {string}
    - * @const
    - * @package
    - */
    -goog.format.EmailAddress.SPECIAL_CHARS = '()<>@:\\\".[]';
    -
    -
    -/**
    - * Match string for address separators.
    - * @type {string}
    - * @const
    - * @private
    - */
    -goog.format.EmailAddress.ADDRESS_SEPARATORS_ = ',;';
    -
    -
    -/**
    - * Match string for characters that, when in a display name, require it to be
    - * quoted.
    - * @type {string}
    - * @const
    - * @private
    - */
    -goog.format.EmailAddress.CHARS_REQUIRE_QUOTES_ =
    -    goog.format.EmailAddress.SPECIAL_CHARS +
    -    goog.format.EmailAddress.ADDRESS_SEPARATORS_;
    -
    -
    -/**
    - * A RegExp to match all double quotes.  Used in cleanAddress().
    - * @type {RegExp}
    - * @private
    - */
    -goog.format.EmailAddress.ALL_DOUBLE_QUOTES_ = /\"/g;
    -
    -
    -/**
    - * A RegExp to match escaped double quotes.  Used in parse().
    - * @type {RegExp}
    - * @private
    - */
    -goog.format.EmailAddress.ESCAPED_DOUBLE_QUOTES_ = /\\\"/g;
    -
    -
    -/**
    - * A RegExp to match all backslashes.  Used in cleanAddress().
    - * @type {RegExp}
    - * @private
    - */
    -goog.format.EmailAddress.ALL_BACKSLASHES_ = /\\/g;
    -
    -
    -/**
    - * A RegExp to match escaped backslashes.  Used in parse().
    - * @type {RegExp}
    - * @private
    - */
    -goog.format.EmailAddress.ESCAPED_BACKSLASHES_ = /\\\\/g;
    -
    -
    -/**
    - * A string representing the RegExp for the local part of an email address.
    - * @private {string}
    - */
    -goog.format.EmailAddress.LOCAL_PART_REGEXP_STR_ =
    -    '[+a-zA-Z0-9_.!#$%&\'*\\/=?^`{|}~-]+';
    -
    -
    -/**
    - * A string representing the RegExp for the domain part of an email address.
    - * @private {string}
    - */
    -goog.format.EmailAddress.DOMAIN_PART_REGEXP_STR_ =
    -    '([a-zA-Z0-9-]+\\.)+[a-zA-Z0-9]{2,63}';
    -
    -
    -/**
    - * A RegExp to match the local part of an email address.
    - * @private {!RegExp}
    - */
    -goog.format.EmailAddress.LOCAL_PART_ =
    -    new RegExp('^' + goog.format.EmailAddress.LOCAL_PART_REGEXP_STR_ + '$');
    -
    -
    -/**
    - * A RegExp to match the domain part of an email address.
    - * @private {!RegExp}
    - */
    -goog.format.EmailAddress.DOMAIN_PART_ =
    -    new RegExp('^' + goog.format.EmailAddress.DOMAIN_PART_REGEXP_STR_ + '$');
    -
    -
    -/**
    - * A RegExp to match an email address.
    - * @private {!RegExp}
    - */
    -goog.format.EmailAddress.EMAIL_ADDRESS_ =
    -    new RegExp('^' + goog.format.EmailAddress.LOCAL_PART_REGEXP_STR_ + '@' +
    -        goog.format.EmailAddress.DOMAIN_PART_REGEXP_STR_ + '$');
    -
    -
    -/**
    - * Get the name associated with the email address.
    - * @return {string} The name or personal portion of the address.
    - * @final
    - */
    -goog.format.EmailAddress.prototype.getName = function() {
    -  return this.name_;
    -};
    -
    -
    -/**
    - * Get the email address.
    - * @return {string} The email address.
    - * @final
    - */
    -goog.format.EmailAddress.prototype.getAddress = function() {
    -  return this.address;
    -};
    -
    -
    -/**
    - * Set the name associated with the email address.
    - * @param {string} name The name to associate.
    - * @final
    - */
    -goog.format.EmailAddress.prototype.setName = function(name) {
    -  this.name_ = name;
    -};
    -
    -
    -/**
    - * Set the email address.
    - * @param {string} address The email address.
    - * @final
    - */
    -goog.format.EmailAddress.prototype.setAddress = function(address) {
    -  this.address = address;
    -};
    -
    -
    -/**
    - * Return the address in a standard format:
    - *  - remove extra spaces.
    - *  - Surround name with quotes if it contains special characters.
    - * @return {string} The cleaned address.
    - * @override
    - */
    -goog.format.EmailAddress.prototype.toString = function() {
    -  return this.toStringInternal(
    -      goog.format.EmailAddress.CHARS_REQUIRE_QUOTES_);
    -};
    -
    -
    -/**
    - * Check if a display name requires quoting.
    - * @param {string} name The display name
    - * @param {string} specialChars String that contains the characters that require
    - *  the display name to be quoted. This may change based in whereas we are
    - *  in EAI context or not.
    - * @return {boolean}
    - * @private
    - */
    -goog.format.EmailAddress.isQuoteNeeded_ = function(name, specialChars) {
    -  for (var i = 0; i < specialChars.length; i++) {
    -    var specialChar = specialChars[i];
    -    if (goog.string.contains(name, specialChar)) {
    -      return true;
    -    }
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Return the address in a standard format:
    - *  - remove extra spaces.
    - *  - Surround name with quotes if it contains special characters.
    - * @param {string} specialChars String that contains the characters that require
    - *  the display name to be quoted.
    - * @return {string} The cleaned address.
    - * @protected
    - */
    -goog.format.EmailAddress.prototype.toStringInternal = function(specialChars) {
    -  var name = this.getName();
    -
    -  // We intentionally remove double quotes in the name because escaping
    -  // them to \" looks ugly.
    -  name = name.replace(goog.format.EmailAddress.ALL_DOUBLE_QUOTES_, '');
    -
    -  // If the name has special characters, we need to quote it and escape \'s.
    -  if (goog.format.EmailAddress.isQuoteNeeded_(name, specialChars)) {
    -    name = '"' +
    -        name.replace(goog.format.EmailAddress.ALL_BACKSLASHES_, '\\\\') + '"';
    -  }
    -
    -  if (name == '') {
    -    return this.address;
    -  }
    -  if (this.address == '') {
    -    return name;
    -  }
    -  return name + ' <' + this.address + '>';
    -};
    -
    -
    -/**
    - * Determines is the current object is a valid email address.
    - * @return {boolean} Whether the email address is valid.
    - */
    -goog.format.EmailAddress.prototype.isValid = function() {
    -  return goog.format.EmailAddress.isValidAddrSpec(this.address);
    -};
    -
    -
    -/**
    - * Checks if the provided string is a valid email address. Supports both
    - * simple email addresses (address specs) and addresses that contain display
    - * names.
    - * @param {string} str The email address to check.
    - * @return {boolean} Whether the provided string is a valid address.
    - */
    -goog.format.EmailAddress.isValidAddress = function(str) {
    -  return goog.format.EmailAddress.parse(str).isValid();
    -};
    -
    -
    -/**
    - * Checks if the provided string is a valid address spec (local@domain.com).
    - * @param {string} str The email address to check.
    - * @return {boolean} Whether the provided string is a valid address spec.
    - */
    -goog.format.EmailAddress.isValidAddrSpec = function(str) {
    -  // This is a fairly naive implementation, but it covers 99% of use cases.
    -  // For more details, see http://en.wikipedia.org/wiki/Email_address#Syntax
    -  return goog.format.EmailAddress.EMAIL_ADDRESS_.test(str);
    -};
    -
    -
    -/**
    - * Checks if the provided string is a valid local part (part before the '@') of
    - * an email address.
    - * @param {string} str The local part to check.
    - * @return {boolean} Whether the provided string is a valid local part.
    - */
    -goog.format.EmailAddress.isValidLocalPartSpec = function(str) {
    -  return goog.format.EmailAddress.LOCAL_PART_.test(str);
    -};
    -
    -
    -/**
    - * Checks if the provided string is a valid domain part (part after the '@') of
    - * an email address.
    - * @param {string} str The domain part to check.
    - * @return {boolean} Whether the provided string is a valid domain part.
    - */
    -goog.format.EmailAddress.isValidDomainPartSpec = function(str) {
    -  return goog.format.EmailAddress.DOMAIN_PART_.test(str);
    -};
    -
    -
    -/**
    - * Parses an email address of the form "name" &lt;address&gt; ("name" is
    - * optional) into an email address.
    - * @param {string} addr The address string.
    - * @param {function(new: goog.format.EmailAddress, string=,string=)} ctor
    - *     EmailAddress constructor to instantiate the output address.
    - * @return {!goog.format.EmailAddress} The parsed address.
    - * @protected
    - */
    -goog.format.EmailAddress.parseInternal = function(addr, ctor) {
    -  // TODO(ecattell): Strip bidi markers.
    -  var name = '';
    -  var address = '';
    -  for (var i = 0; i < addr.length;) {
    -    var token = goog.format.EmailAddress.getToken_(addr, i);
    -    if (token.charAt(0) == '<' && token.indexOf('>') != -1) {
    -      var end = token.indexOf('>');
    -      address = token.substring(1, end);
    -    } else if (address == '') {
    -      name += token;
    -    }
    -    i += token.length;
    -  }
    -
    -  // Check if it's a simple email address of the form "jlim@google.com".
    -  if (address == '' && name.indexOf('@') != -1) {
    -    address = name;
    -    name = '';
    -  }
    -
    -  name = goog.string.collapseWhitespace(name);
    -  name = goog.string.stripQuotes(name, '\'');
    -  name = goog.string.stripQuotes(name, '"');
    -  // Replace escaped quotes and slashes.
    -  name = name.replace(goog.format.EmailAddress.ESCAPED_DOUBLE_QUOTES_, '"');
    -  name = name.replace(goog.format.EmailAddress.ESCAPED_BACKSLASHES_, '\\');
    -  address = goog.string.collapseWhitespace(address);
    -  return new ctor(address, name);
    -};
    -
    -
    -/**
    - * Parses an email address of the form "name" &lt;address&gt; into
    - * an email address.
    - * @param {string} addr The address string.
    - * @return {!goog.format.EmailAddress} The parsed address.
    - */
    -goog.format.EmailAddress.parse = function(addr) {
    -  return goog.format.EmailAddress.parseInternal(
    -      addr, goog.format.EmailAddress);
    -};
    -
    -
    -/**
    - * Parse a string containing email addresses of the form
    - * "name" &lt;address&gt; into an array of email addresses.
    - * @param {string} str The address list.
    - * @param {function(string)} parser The parser to employ.
    - * @param {function(string):boolean} separatorChecker Accepts a character and
    - *    returns whether it should be considered an address separator.
    - * @return {!Array<!goog.format.EmailAddress>} The parsed emails.
    - * @protected
    - */
    -goog.format.EmailAddress.parseListInternal = function(
    -    str, parser, separatorChecker) {
    -  var result = [];
    -  var email = '';
    -  var token;
    -
    -  // Remove non-UNIX-style newlines that would otherwise cause getToken_ to
    -  // choke. Remove multiple consecutive whitespace characters for the same
    -  // reason.
    -  str = goog.string.collapseWhitespace(str);
    -
    -  for (var i = 0; i < str.length; ) {
    -    token = goog.format.EmailAddress.getToken_(str, i);
    -    if (separatorChecker(token) ||
    -        (token == ' ' && parser(email).isValid())) {
    -      if (!goog.string.isEmptyOrWhitespace(email)) {
    -        result.push(parser(email));
    -      }
    -      email = '';
    -      i++;
    -      continue;
    -    }
    -    email += token;
    -    i += token.length;
    -  }
    -
    -  // Add the final token.
    -  if (!goog.string.isEmptyOrWhitespace(email)) {
    -    result.push(parser(email));
    -  }
    -  return result;
    -};
    -
    -
    -/**
    - * Parses a string containing email addresses of the form
    - * "name" &lt;address&gt; into an array of email addresses.
    - * @param {string} str The address list.
    - * @return {!Array<!goog.format.EmailAddress>} The parsed emails.
    - */
    -goog.format.EmailAddress.parseList = function(str) {
    -  return goog.format.EmailAddress.parseListInternal(
    -      str, goog.format.EmailAddress.parse,
    -      goog.format.EmailAddress.isAddressSeparator);
    -};
    -
    -
    -/**
    - * Get the next token from a position in an address string.
    - * @param {string} str the string.
    - * @param {number} pos the position.
    - * @return {string} the token.
    - * @private
    - */
    -goog.format.EmailAddress.getToken_ = function(str, pos) {
    -  var ch = str.charAt(pos);
    -  var p = goog.format.EmailAddress.OPENERS_.indexOf(ch);
    -  if (p == -1) {
    -    return ch;
    -  }
    -  if (goog.format.EmailAddress.isEscapedDlQuote_(str, pos)) {
    -
    -    // If an opener is an escaped quote we do not treat it as a real opener
    -    // and keep accumulating the token.
    -    return ch;
    -  }
    -  var closerChar = goog.format.EmailAddress.CLOSERS_.charAt(p);
    -  var endPos = str.indexOf(closerChar, pos + 1);
    -
    -  // If the closer is a quote we go forward skipping escaped quotes until we
    -  // hit the real closing one.
    -  while (endPos >= 0 &&
    -         goog.format.EmailAddress.isEscapedDlQuote_(str, endPos)) {
    -    endPos = str.indexOf(closerChar, endPos + 1);
    -  }
    -  var token = (endPos >= 0) ? str.substring(pos, endPos + 1) : ch;
    -  return token;
    -};
    -
    -
    -/**
    - * Checks if the character in the current position is an escaped double quote
    - * ( \" ).
    - * @param {string} str the string.
    - * @param {number} pos the position.
    - * @return {boolean} true if the char is escaped double quote.
    - * @private
    - */
    -goog.format.EmailAddress.isEscapedDlQuote_ = function(str, pos) {
    -  if (str.charAt(pos) != '"') {
    -    return false;
    -  }
    -  var slashCount = 0;
    -  for (var idx = pos - 1; idx >= 0 && str.charAt(idx) == '\\'; idx--) {
    -    slashCount++;
    -  }
    -  return ((slashCount % 2) != 0);
    -};
    -
    -
    -/**
    - * @param {string} ch The character to test.
    - * @return {boolean} Whether the provided character is an address separator.
    - */
    -goog.format.EmailAddress.isAddressSeparator = function(ch) {
    -  return goog.string.contains(goog.format.EmailAddress.ADDRESS_SEPARATORS_, ch);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/format/emailaddress_test.html b/src/database/third_party/closure-library/closure/goog/format/emailaddress_test.html
    deleted file mode 100644
    index 1e60ff06898..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/format/emailaddress_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.format.EmailAddress
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.format.EmailAddressTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/format/emailaddress_test.js b/src/database/third_party/closure-library/closure/goog/format/emailaddress_test.js
    deleted file mode 100644
    index 004938e2ab0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/format/emailaddress_test.js
    +++ /dev/null
    @@ -1,229 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.format.EmailAddressTest');
    -goog.setTestOnly('goog.format.EmailAddressTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.format.EmailAddress');
    -goog.require('goog.testing.jsunit');
    -
    -function testparseList() {
    -  assertParsedList('', [], 'Failed to parse empty stringy');
    -  assertParsedList(',,', [], 'Failed to parse string with commas only');
    -
    -  assertParsedList('<foo@gmail.com>', ['foo@gmail.com']);
    -
    -  assertParsedList('<foo@gmail.com>,', ['foo@gmail.com'],
    -      'Failed to parse 1 address with trailing comma');
    -
    -  assertParsedList('<foo@gmail.com>, ', ['foo@gmail.com'],
    -      'Failed to parse 1 address with trailing whitespace and comma');
    -
    -  assertParsedList(',<foo@gmail.com>', ['foo@gmail.com'],
    -      'Failed to parse 1 address with leading comma');
    -
    -  assertParsedList(' ,<foo@gmail.com>', ['foo@gmail.com'],
    -      'Failed to parse 1 address with leading whitespace and comma');
    -
    -  assertParsedList('<foo@gmail.com>, <bar@gmail.com>',
    -      ['foo@gmail.com', 'bar@gmail.com'],
    -      'Failed to parse 2 email addresses');
    -
    -  assertParsedList('<foo@gmail.com>, <bar@gmail.com>,',
    -      ['foo@gmail.com', 'bar@gmail.com'],
    -      'Failed to parse 2 email addresses and trailing comma');
    -
    -  assertParsedList('<foo@gmail.com>, <bar@gmail.com>, ',
    -      ['foo@gmail.com', 'bar@gmail.com'],
    -      'Failed to parse 2 email addresses, trailing comma and whitespace');
    -
    -  assertParsedList(
    -      'John Doe <john@gmail.com>; Jane Doe <jane@gmail.com>, ' +
    -          '<jerry@gmail.com>',
    -      ['john@gmail.com', 'jane@gmail.com', 'jerry@gmail.com'],
    -      'Failed to parse addresses with semicolon separator');
    -}
    -
    -function testparseListOpenersAndClosers() {
    -  assertParsedList(
    -      'aaa@gmail.com, "bbb@gmail.com", <ccc@gmail.com>, ' +
    -          '(ddd@gmail.com), [eee@gmail.com]',
    -      ['aaa@gmail.com', '"bbb@gmail.com"', 'ccc@gmail.com',
    -        '(ddd@gmail.com)', '[eee@gmail.com]'],
    -      'Failed to handle all 5 opener/closer characters');
    -}
    -
    -function testparseListIdn() {
    -  var idnaddr = 'mailtest@\u4F8B\u3048.\u30C6\u30B9\u30C8';
    -  assertParsedList(idnaddr, [idnaddr]);
    -}
    -
    -function testparseListWithQuotedSpecialChars() {
    -  var res = assertParsedList(
    -      'a\\"b\\"c <d@e.f>,"g\\"h\\"i\\\\" <j@k.l>',
    -      ['d@e.f', 'j@k.l']);
    -  assertEquals('Wrong name 0', 'a"b"c', res[0].getName());
    -  assertEquals('Wrong name 1', 'g"h"i\\', res[1].getName());
    -}
    -
    -function testparseListWithCommaInLocalPart() {
    -  var res = assertParsedList(
    -      '"Doe, John" <doe.john@gmail.com>, <someone@gmail.com>',
    -      ['doe.john@gmail.com', 'someone@gmail.com']);
    -
    -  assertEquals('Doe, John', res[0].getName());
    -  assertEquals('', res[1].getName());
    -}
    -
    -function testparseListWithWhitespaceSeparatedEmails() {
    -  var res = assertParsedList(
    -      'a@b.com <c@d.com> e@f.com "G H" <g@h.com> i@j.com',
    -      ['a@b.com', 'c@d.com', 'e@f.com', 'g@h.com', 'i@j.com']);
    -  assertEquals('G H', res[3].getName());
    -}
    -
    -function testparseListSystemNewlines() {
    -  // These Windows newlines can be inserted in IE8, or copied-and-pasted from
    -  // bad data on a Mac, as seen in bug 11081852.
    -  assertParsedList('a@b.com\r\nc@d.com', ['a@b.com', 'c@d.com'],
    -      'Failed to parse Windows newlines');
    -  assertParsedList('a@b.com\nc@d.com', ['a@b.com', 'c@d.com'],
    -      'Failed to parse *nix newlines');
    -  assertParsedList('a@b.com\n\rc@d.com', ['a@b.com', 'c@d.com'],
    -      'Failed to parse obsolete newlines');
    -  assertParsedList('a@b.com\rc@d.com', ['a@b.com', 'c@d.com'],
    -      'Failed to parse pre-OS X Mac newlines');
    -}
    -
    -function testToString() {
    -  var f = function(str) {
    -    return goog.format.EmailAddress.parse(str).toString();
    -  };
    -
    -  // No modification.
    -  assertEquals('JOHN Doe <john@gmail.com>',
    -               f('JOHN Doe <john@gmail.com>'));
    -
    -  // Extra spaces.
    -  assertEquals('JOHN Doe <john@gmail.com>',
    -               f(' JOHN  Doe  <john@gmail.com> '));
    -
    -  // No name.
    -  assertEquals('john@gmail.com', f('<john@gmail.com>'));
    -  assertEquals('john@gmail.com', f('john@gmail.com'));
    -
    -  // No address.
    -  assertEquals('JOHN Doe', f('JOHN Doe <>'));
    -
    -  // Special chars in the name.
    -  assertEquals('"JOHN, Doe" <john@gmail.com>',
    -               f('JOHN, Doe <john@gmail.com>'));
    -  assertEquals('"JOHN(Johnny) Doe" <john@gmail.com>',
    -               f('JOHN(Johnny) Doe <john@gmail.com>'));
    -  assertEquals('"JOHN[Johnny] Doe" <john@gmail.com>',
    -               f('JOHN[Johnny] Doe <john@gmail.com>'));
    -  assertEquals('"JOHN@work Doe" <john@gmail.com>',
    -               f('JOHN@work Doe <john@gmail.com>'));
    -  assertEquals('"JOHN:theking Doe" <john@gmail.com>',
    -               f('JOHN:theking Doe <john@gmail.com>'));
    -  assertEquals('"JOHN\\\\ Doe" <john@gmail.com>',
    -               f('JOHN\\ Doe <john@gmail.com>'));
    -  assertEquals('"JOHN.com Doe" <john@gmail.com>',
    -               f('JOHN.com Doe <john@gmail.com>'));
    -
    -  // Already quoted.
    -  assertEquals('"JOHN, Doe" <john@gmail.com>',
    -               f('"JOHN, Doe" <john@gmail.com>'));
    -
    -  // Needless quotes.
    -  assertEquals('JOHN Doe <john@gmail.com>',
    -               f('"JOHN Doe" <john@gmail.com>'));
    -  // Not quoted-string, but has double quotes.
    -  assertEquals('"JOHN, Doe" <john@gmail.com>',
    -               f('JOHN, "Doe" <john@gmail.com>'));
    -
    -  // No special characters other than quotes.
    -  assertEquals('JOHN Doe <john@gmail.com>',
    -               f('JOHN "Doe" <john@gmail.com>'));
    -
    -  // Escaped quotes are also removed.
    -  assertEquals('"JOHN, Doe" <john@gmail.com>',
    -               f('JOHN, \\"Doe\\" <john@gmail.com>'));
    -}
    -
    -function doIsValidTest(testFunc, valid, invalid) {
    -  goog.array.forEach(valid, function(str) {
    -    assertTrue('"' + str + '" should be valid.', testFunc(str));
    -  });
    -  goog.array.forEach(invalid, function(str) {
    -    assertFalse('"' + str + '" should be invalid.', testFunc(str));
    -  });
    -}
    -
    -function testIsValid() {
    -  var valid = [
    -    'e@b.eu', '<a.b+foo@c.com>', 'eric <e@b.com>', '"e" <e@b.com>',
    -    'a@FOO.MUSEUM', 'bla@b.co.ac.uk', 'bla@a.b.com', 'o\'hara@gm.com',
    -    'plus+is+allowed@gmail.com', '!/#$%&\'*+-=~|`{}?^_@expample.com',
    -    'confirm-bhk=modulo.org@yahoogroups.com'];
    -  var invalid = [
    -    'e', '', 'e @c.com', 'a@b', 'foo.com', 'foo@c..com', 'test@gma=il.com',
    -    'aaa@gmail', 'has some spaces@gmail.com', 'has@three@at@signs.com',
    -    '@no-local-part.com', 'み.ん-あ@みんあ.みんあ',
    -    'みんあ@test.com', 'test@test.みんあ', 'test@みんあ.com',
    -    'fullwidthfullstop@sld' + '\uff0e' + 'tld',
    -    'ideographicfullstop@sld' + '\u3002' + 'tld',
    -    'halfwidthideographicfullstop@sld' + '\uff61' + 'tld'];
    -  doIsValidTest(goog.format.EmailAddress.isValidAddress, valid, invalid);
    -}
    -
    -function testIsValidLocalPart() {
    -  var valid = [
    -    'e', 'a.b+foo', 'o\'hara', 'user+someone', '!/#$%&\'*+-=~|`{}?^_',
    -    'confirm-bhk=modulo.org'];
    -  var invalid = [
    -    'A@b@c', 'a"b(c)d,e:f;g<h>i[j\\k]l', 'just"not"right',
    -    'this is"not\\allowed', 'this\\ still\"not\\\\allowed', 'has some spaces'];
    -  doIsValidTest(goog.format.EmailAddress.isValidLocalPartSpec, valid, invalid);
    -}
    -
    -function testIsValidDomainPart() {
    -  var valid = [
    -    'example.com', 'dept.example.org', 'long.domain.with.lots.of.dots'];
    -  var invalid = ['', '@has.an.at.sign', '..has.leading.dots', 'gma=il.com',
    -    'DoesNotHaveADot', 'sld' + '\uff0e' + 'tld', 'sld' + '\u3002' + 'tld',
    -    'sld' + '\uff61' + 'tld'];
    -  doIsValidTest(goog.format.EmailAddress.isValidDomainPartSpec, valid, invalid);
    -}
    -
    -
    -/**
    - * Asserts that parsing the inputString produces a list of email addresses
    - * containing the specified address strings, irrespective of their order.
    - * @param {string} inputString A raw address list.
    - * @param {Array<string>} expectedList The expected results.
    - * @param {string=} opt_message An assertion message.
    - * @return {string} the resulting email address objects.
    - */
    -function assertParsedList(inputString, expectedList, opt_message) {
    -  var message = opt_message || 'Should parse address correctly';
    -  var result = goog.format.EmailAddress.parseList(inputString);
    -  assertEquals(
    -      'Should have correct # of addresses', expectedList.length, result.length);
    -  for (var i = 0; i < expectedList.length; ++i) {
    -    assertEquals(message, expectedList[i], result[i].getAddress());
    -  }
    -  return result;
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/format/format.js b/src/database/third_party/closure-library/closure/goog/format/format.js
    deleted file mode 100644
    index f78067d665c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/format/format.js
    +++ /dev/null
    @@ -1,502 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides utility functions for formatting strings, numbers etc.
    - *
    - */
    -
    -goog.provide('goog.format');
    -
    -goog.require('goog.i18n.GraphemeBreak');
    -goog.require('goog.string');
    -goog.require('goog.userAgent');
    -
    -
    -/**
    - * Formats a number of bytes in human readable form.
    - * 54, 450K, 1.3M, 5G etc.
    - * @param {number} bytes The number of bytes to show.
    - * @param {number=} opt_decimals The number of decimals to use.  Defaults to 2.
    - * @return {string} The human readable form of the byte size.
    - */
    -goog.format.fileSize = function(bytes, opt_decimals) {
    -  return goog.format.numBytesToString(bytes, opt_decimals, false);
    -};
    -
    -
    -/**
    - * Checks whether string value containing scaling units (K, M, G, T, P, m,
    - * u, n) can be converted to a number.
    - *
    - * Where there is a decimal, there must be a digit to the left of the
    - * decimal point.
    - *
    - * Negative numbers are valid.
    - *
    - * Examples:
    - *   0, 1, 1.0, 10.4K, 2.3M, -0.3P, 1.2m
    - *
    - * @param {string} val String value to check.
    - * @return {boolean} True if string could be converted to a numeric value.
    - */
    -goog.format.isConvertableScaledNumber = function(val) {
    -  return goog.format.SCALED_NUMERIC_RE_.test(val);
    -};
    -
    -
    -/**
    - * Converts a string to numeric value, taking into account the units.
    - * If string ends in 'B', use binary conversion.
    - * @param {string} stringValue String to be converted to numeric value.
    - * @return {number} Numeric value for string.
    - */
    -goog.format.stringToNumericValue = function(stringValue) {
    -  if (goog.string.endsWith(stringValue, 'B')) {
    -    return goog.format.stringToNumericValue_(
    -        stringValue, goog.format.NUMERIC_SCALES_BINARY_);
    -  }
    -  return goog.format.stringToNumericValue_(
    -      stringValue, goog.format.NUMERIC_SCALES_SI_);
    -};
    -
    -
    -/**
    - * Converts a string to number of bytes, taking into account the units.
    - * Binary conversion.
    - * @param {string} stringValue String to be converted to numeric value.
    - * @return {number} Numeric value for string.
    - */
    -goog.format.stringToNumBytes = function(stringValue) {
    -  return goog.format.stringToNumericValue_(
    -      stringValue, goog.format.NUMERIC_SCALES_BINARY_);
    -};
    -
    -
    -/**
    - * Converts a numeric value to string representation. SI conversion.
    - * @param {number} val Value to be converted.
    - * @param {number=} opt_decimals The number of decimals to use.  Defaults to 2.
    - * @return {string} String representation of number.
    - */
    -goog.format.numericValueToString = function(val, opt_decimals) {
    -  return goog.format.numericValueToString_(
    -      val, goog.format.NUMERIC_SCALES_SI_, opt_decimals);
    -};
    -
    -
    -/**
    - * Converts number of bytes to string representation. Binary conversion.
    - * Default is to return the additional 'B' suffix, e.g. '10.5KB' to minimize
    - * confusion with counts that are scaled by powers of 1000.
    - * @param {number} val Value to be converted.
    - * @param {number=} opt_decimals The number of decimals to use.  Defaults to 2.
    - * @param {boolean=} opt_suffix If true, include trailing 'B' in returned
    - *     string.  Default is true.
    - * @param {boolean=} opt_useSeparator If true, number and scale will be
    - *     separated by a no break space. Default is false.
    - * @return {string} String representation of number of bytes.
    - */
    -goog.format.numBytesToString = function(val, opt_decimals, opt_suffix,
    -    opt_useSeparator) {
    -  var suffix = '';
    -  if (!goog.isDef(opt_suffix) || opt_suffix) {
    -    suffix = 'B';
    -  }
    -  return goog.format.numericValueToString_(
    -      val, goog.format.NUMERIC_SCALES_BINARY_, opt_decimals, suffix,
    -      opt_useSeparator);
    -};
    -
    -
    -/**
    - * Converts a string to numeric value, taking into account the units.
    - * @param {string} stringValue String to be converted to numeric value.
    - * @param {Object} conversion Dictionary of conversion scales.
    - * @return {number} Numeric value for string.  If it cannot be converted,
    - *    returns NaN.
    - * @private
    - */
    -goog.format.stringToNumericValue_ = function(stringValue, conversion) {
    -  var match = stringValue.match(goog.format.SCALED_NUMERIC_RE_);
    -  if (!match) {
    -    return NaN;
    -  }
    -  var val = match[1] * conversion[match[2]];
    -  return val;
    -};
    -
    -
    -/**
    - * Converts a numeric value to string, using specified conversion
    - * scales.
    - * @param {number} val Value to be converted.
    - * @param {Object} conversion Dictionary of scaling factors.
    - * @param {number=} opt_decimals The number of decimals to use.  Default is 2.
    - * @param {string=} opt_suffix Optional suffix to append.
    - * @param {boolean=} opt_useSeparator If true, number and scale will be
    - *     separated by a space. Default is false.
    - * @return {string} The human readable form of the byte size.
    - * @private
    - */
    -goog.format.numericValueToString_ = function(val, conversion,
    -    opt_decimals, opt_suffix, opt_useSeparator) {
    -  var prefixes = goog.format.NUMERIC_SCALE_PREFIXES_;
    -  var orig_val = val;
    -  var symbol = '';
    -  var separator = '';
    -  var scale = 1;
    -  if (val < 0) {
    -    val = -val;
    -  }
    -  for (var i = 0; i < prefixes.length; i++) {
    -    var unit = prefixes[i];
    -    scale = conversion[unit];
    -    if (val >= scale || (scale <= 1 && val > 0.1 * scale)) {
    -      // Treat values less than 1 differently, allowing 0.5 to be "0.5" rather
    -      // than "500m"
    -      symbol = unit;
    -      break;
    -    }
    -  }
    -  if (!symbol) {
    -    scale = 1;
    -  } else {
    -    if (opt_suffix) {
    -      symbol += opt_suffix;
    -    }
    -    if (opt_useSeparator) {
    -      separator = ' ';
    -    }
    -  }
    -  var ex = Math.pow(10, goog.isDef(opt_decimals) ? opt_decimals : 2);
    -  return Math.round(orig_val / scale * ex) / ex + separator + symbol;
    -};
    -
    -
    -/**
    - * Regular expression for detecting scaling units, such as K, M, G, etc. for
    - * converting a string representation to a numeric value.
    - *
    - * Also allow 'k' to be aliased to 'K'.  These could be used for SI (powers
    - * of 1000) or Binary (powers of 1024) conversions.
    - *
    - * Also allow final 'B' to be interpreted as byte-count, implicitly triggering
    - * binary conversion (e.g., '10.2MB').
    - *
    - * @type {RegExp}
    - * @private
    - */
    -goog.format.SCALED_NUMERIC_RE_ = /^([-]?\d+\.?\d*)([K,M,G,T,P,k,m,u,n]?)[B]?$/;
    -
    -
    -/**
    - * Ordered list of scaling prefixes in decreasing order.
    - * @private {Array<string>}
    - */
    -goog.format.NUMERIC_SCALE_PREFIXES_ = [
    -  'P', 'T', 'G', 'M', 'K', '', 'm', 'u', 'n'
    -];
    -
    -
    -/**
    - * Scaling factors for conversion of numeric value to string.  SI conversion.
    - * @type {Object}
    - * @private
    - */
    -goog.format.NUMERIC_SCALES_SI_ = {
    -  '': 1,
    -  'n': 1e-9,
    -  'u': 1e-6,
    -  'm': 1e-3,
    -  'k': 1e3,
    -  'K': 1e3,
    -  'M': 1e6,
    -  'G': 1e9,
    -  'T': 1e12,
    -  'P': 1e15
    -};
    -
    -
    -/**
    - * Scaling factors for conversion of numeric value to string.  Binary
    - * conversion.
    - * @type {Object}
    - * @private
    - */
    -goog.format.NUMERIC_SCALES_BINARY_ = {
    -  '': 1,
    -  'n': Math.pow(1024, -3),
    -  'u': Math.pow(1024, -2),
    -  'm': 1.0 / 1024,
    -  'k': 1024,
    -  'K': 1024,
    -  'M': Math.pow(1024, 2),
    -  'G': Math.pow(1024, 3),
    -  'T': Math.pow(1024, 4),
    -  'P': Math.pow(1024, 5)
    -};
    -
    -
    -/**
    - * First Unicode code point that has the Mark property.
    - * @type {number}
    - * @private
    - */
    -goog.format.FIRST_GRAPHEME_EXTEND_ = 0x300;
    -
    -
    -/**
    - * Returns true if and only if given character should be treated as a breaking
    - * space. All ASCII control characters, the main Unicode range of spacing
    - * characters (U+2000 to U+200B inclusive except for U+2007), and several other
    - * Unicode space characters are treated as breaking spaces.
    - * @param {number} charCode The character code under consideration.
    - * @return {boolean} True if the character is a breaking space.
    - * @private
    - */
    -goog.format.isTreatedAsBreakingSpace_ = function(charCode) {
    -  return (charCode <= goog.format.WbrToken_.SPACE) ||
    -         (charCode >= 0x1000 &&
    -          ((charCode >= 0x2000 && charCode <= 0x2006) ||
    -           (charCode >= 0x2008 && charCode <= 0x200B) ||
    -           charCode == 0x1680 ||
    -           charCode == 0x180E ||
    -           charCode == 0x2028 ||
    -           charCode == 0x2029 ||
    -           charCode == 0x205f ||
    -           charCode == 0x3000));
    -};
    -
    -
    -/**
    - * Returns true if and only if given character is an invisible formatting
    - * character.
    - * @param {number} charCode The character code under consideration.
    - * @return {boolean} True if the character is an invisible formatting character.
    - * @private
    - */
    -goog.format.isInvisibleFormattingCharacter_ = function(charCode) {
    -  // See: http://unicode.org/charts/PDF/U2000.pdf
    -  return (charCode >= 0x200C && charCode <= 0x200F) ||
    -         (charCode >= 0x202A && charCode <= 0x202E);
    -};
    -
    -
    -/**
    - * Inserts word breaks into an HTML string at a given interval.  The counter is
    - * reset if a space or a character which behaves like a space is encountered,
    - * but it isn't incremented if an invisible formatting character is encountered.
    - * WBRs aren't inserted into HTML tags or entities.  Entities count towards the
    - * character count, HTML tags do not.
    - *
    - * With common strings aliased, objects allocations are constant based on the
    - * length of the string: N + 3. This guarantee does not hold if the string
    - * contains an element >= U+0300 and hasGraphemeBreak is non-trivial.
    - *
    - * @param {string} str HTML to insert word breaks into.
    - * @param {function(number, number, boolean): boolean} hasGraphemeBreak A
    - *     function determining if there is a grapheme break between two characters,
    - *     in the same signature as goog.i18n.GraphemeBreak.hasGraphemeBreak.
    - * @param {number=} opt_maxlen Maximum length after which to ensure
    - *     there is a break.  Default is 10 characters.
    - * @return {string} The string including word breaks.
    - * @private
    - */
    -goog.format.insertWordBreaksGeneric_ = function(str, hasGraphemeBreak,
    -    opt_maxlen) {
    -  var maxlen = opt_maxlen || 10;
    -  if (maxlen > str.length) return str;
    -
    -  var rv = [];
    -  var n = 0; // The length of the current token
    -
    -  // This will contain the ampersand or less-than character if one of the
    -  // two has been seen; otherwise, the value is zero.
    -  var nestingCharCode = 0;
    -
    -  // First character position from input string that has not been outputted.
    -  var lastDumpPosition = 0;
    -
    -  var charCode = 0;
    -  for (var i = 0; i < str.length; i++) {
    -    // Using charCodeAt versus charAt avoids allocating new string objects.
    -    var lastCharCode = charCode;
    -    charCode = str.charCodeAt(i);
    -
    -    // Don't add a WBR before characters that might be grapheme extending.
    -    var isPotentiallyGraphemeExtending =
    -        charCode >= goog.format.FIRST_GRAPHEME_EXTEND_ &&
    -        !hasGraphemeBreak(lastCharCode, charCode, true);
    -
    -    // Don't add a WBR at the end of a word. For the purposes of determining
    -    // work breaks, all ASCII control characters and some commonly encountered
    -    // Unicode spacing characters are treated as breaking spaces.
    -    if (n >= maxlen &&
    -        !goog.format.isTreatedAsBreakingSpace_(charCode) &&
    -        !isPotentiallyGraphemeExtending) {
    -      // Flush everything seen so far, and append a word break.
    -      rv.push(str.substring(lastDumpPosition, i), goog.format.WORD_BREAK_HTML);
    -      lastDumpPosition = i;
    -      n = 0;
    -    }
    -
    -    if (!nestingCharCode) {
    -      // Not currently within an HTML tag or entity
    -
    -      if (charCode == goog.format.WbrToken_.LT ||
    -          charCode == goog.format.WbrToken_.AMP) {
    -
    -        // Entering an HTML Entity '&' or open tag '<'
    -        nestingCharCode = charCode;
    -      } else if (goog.format.isTreatedAsBreakingSpace_(charCode)) {
    -
    -        // A space or control character -- reset the token length
    -        n = 0;
    -      } else if (!goog.format.isInvisibleFormattingCharacter_(charCode)) {
    -
    -        // A normal flow character - increment.  For grapheme extending
    -        // characters, this is not *technically* a new character.  However,
    -        // since the grapheme break detector might be overly conservative,
    -        // we have to continue incrementing, or else we won't even be able
    -        // to add breaks when we get to things like punctuation.  For the
    -        // case where we have a full grapheme break detector, it is okay if
    -        // we occasionally break slightly early.
    -        n++;
    -      }
    -    } else if (charCode == goog.format.WbrToken_.GT &&
    -        nestingCharCode == goog.format.WbrToken_.LT) {
    -
    -      // Leaving an HTML tag, treat the tag as zero-length
    -      nestingCharCode = 0;
    -    } else if (charCode == goog.format.WbrToken_.SEMI_COLON &&
    -        nestingCharCode == goog.format.WbrToken_.AMP) {
    -
    -      // Leaving an HTML entity, treat it as length one
    -      nestingCharCode = 0;
    -      n++;
    -    }
    -  }
    -
    -  // Take care of anything we haven't flushed so far.
    -  rv.push(str.substr(lastDumpPosition));
    -
    -  return rv.join('');
    -};
    -
    -
    -/**
    - * Inserts word breaks into an HTML string at a given interval.
    - *
    - * This method is as aggressive as possible, using a full table of Unicode
    - * characters where it is legal to insert word breaks; however, this table
    - * comes at a 2.5k pre-gzip (~1k post-gzip) size cost.  Consider using
    - * insertWordBreaksBasic to minimize the size impact.
    - *
    - * @param {string} str HTML to insert word breaks into.
    - * @param {number=} opt_maxlen Maximum length after which to ensure there is a
    - *     break.  Default is 10 characters.
    - * @return {string} The string including word breaks.
    - */
    -goog.format.insertWordBreaks = function(str, opt_maxlen) {
    -  return goog.format.insertWordBreaksGeneric_(str,
    -      goog.i18n.GraphemeBreak.hasGraphemeBreak, opt_maxlen);
    -};
    -
    -
    -/**
    - * Determines conservatively if a character has a Grapheme break.
    - *
    - * Conforms to a similar signature as goog.i18n.GraphemeBreak, but is overly
    - * conservative, returning true only for characters in common scripts that
    - * are simple to account for.
    - *
    - * @param {number} lastCharCode The previous character code.  Ignored.
    - * @param {number} charCode The character code under consideration.  It must be
    - *     at least \u0300 as a precondition -- this case is covered by
    - *     insertWordBreaksGeneric_.
    - * @param {boolean=} opt_extended Ignored, to conform with the interface.
    - * @return {boolean} Whether it is one of the recognized subsets of characters
    - *     with a grapheme break.
    - * @private
    - */
    -goog.format.conservativelyHasGraphemeBreak_ = function(
    -    lastCharCode, charCode, opt_extended) {
    -  // Return false for everything except the most common Cyrillic characters.
    -  // Don't worry about Latin characters, because insertWordBreaksGeneric_
    -  // itself already handles those.
    -  // TODO(gboyer): Also account for Greek, Armenian, and Georgian if it is
    -  // simple to do so.
    -  return charCode >= 0x400 && charCode < 0x523;
    -};
    -
    -
    -// TODO(gboyer): Consider using a compile-time flag to switch implementations
    -// rather than relying on the developers to toggle implementations.
    -/**
    - * Inserts word breaks into an HTML string at a given interval.
    - *
    - * This method is less aggressive than insertWordBreaks, only inserting
    - * breaks next to punctuation and between Latin or Cyrillic characters.
    - * However, this is good enough for the common case of URLs.  It also
    - * works for all Latin and Cyrillic languages, plus CJK has no need for word
    - * breaks.  When this method is used, goog.i18n.GraphemeBreak may be dead
    - * code eliminated.
    - *
    - * @param {string} str HTML to insert word breaks into.
    - * @param {number=} opt_maxlen Maximum length after which to ensure there is a
    - *     break.  Default is 10 characters.
    - * @return {string} The string including word breaks.
    - */
    -goog.format.insertWordBreaksBasic = function(str, opt_maxlen) {
    -  return goog.format.insertWordBreaksGeneric_(str,
    -      goog.format.conservativelyHasGraphemeBreak_, opt_maxlen);
    -};
    -
    -
    -/**
    - * True iff the current userAgent is IE8 or above.
    - * @type {boolean}
    - * @private
    - */
    -goog.format.IS_IE8_OR_ABOVE_ = goog.userAgent.IE &&
    -    goog.userAgent.isVersionOrHigher(8);
    -
    -
    -/**
    - * Constant for the WBR replacement used by insertWordBreaks.  Safari requires
    - * <wbr></wbr>, Opera needs the &shy; entity, though this will give a visible
    - * hyphen at breaks.  IE8 uses a zero width space.
    - * Other browsers just use <wbr>.
    - * @type {string}
    - */
    -goog.format.WORD_BREAK_HTML =
    -    goog.userAgent.WEBKIT ?
    -        '<wbr></wbr>' : goog.userAgent.OPERA ?
    -            '&shy;' : goog.format.IS_IE8_OR_ABOVE_ ?
    -                '&#8203;' : '<wbr>';
    -
    -
    -/**
    - * Tokens used within insertWordBreaks.
    - * @private
    - * @enum {number}
    - */
    -goog.format.WbrToken_ = {
    -  LT: 60, // '<'.charCodeAt(0)
    -  GT: 62, // '>'.charCodeAt(0)
    -  AMP: 38, // '&'.charCodeAt(0)
    -  SEMI_COLON: 59, // ';'.charCodeAt(0)
    -  SPACE: 32 // ' '.charCodeAt(0)
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/format/format_test.html b/src/database/third_party/closure-library/closure/goog/format/format_test.html
    deleted file mode 100644
    index 0e639dafc29..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/format/format_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.format
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.formatTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/format/format_test.js b/src/database/third_party/closure-library/closure/goog/format/format_test.js
    deleted file mode 100644
    index 161e680e1be..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/format/format_test.js
    +++ /dev/null
    @@ -1,303 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.formatTest');
    -goog.setTestOnly('goog.formatTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.format');
    -goog.require('goog.string');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -
    -var propertyReplacer = new goog.testing.PropertyReplacer();
    -
    -function tearDown() {
    -  // set wordBreakHtml back to the original value (some tests edit this member).
    -  propertyReplacer.reset();
    -}
    -
    -function testFormatFileSize() {
    -  var fileSize = goog.format.fileSize;
    -
    -  assertEquals('45', fileSize(45));
    -  assertEquals('45', fileSize(45, 0));
    -  assertEquals('45', fileSize(45, 1));
    -  assertEquals('45', fileSize(45, 3));
    -  assertEquals('454', fileSize(454));
    -  assertEquals('600', fileSize(600));
    -
    -  assertEquals('1K', fileSize(1024));
    -  assertEquals('2K', fileSize(2 * 1024));
    -  assertEquals('5K', fileSize(5 * 1024));
    -  assertEquals('5.123K', fileSize(5.12345 * 1024, 3));
    -  assertEquals('5.68K', fileSize(5.678 * 1024, 2));
    -
    -  assertEquals('1M', fileSize(1024 * 1024));
    -  assertEquals('1.5M', fileSize(1.5 * 1024 * 1024));
    -  assertEquals('2M', fileSize(1.5 * 1024 * 1024, 0));
    -  assertEquals('1.5M', fileSize(1.51 * 1024 * 1024, 1));
    -  assertEquals('1.56M', fileSize(1.56 * 1024 * 1024, 2));
    -
    -  assertEquals('1G', fileSize(1024 * 1024 * 1024));
    -  assertEquals('6G', fileSize(6 * 1024 * 1024 * 1024));
    -  assertEquals('12.06T', fileSize(12345.6789 * 1024 * 1024 * 1024));
    -}
    -
    -function testIsConvertableScaledNumber() {
    -  var isConvertableScaledNumber = goog.format.isConvertableScaledNumber;
    -
    -  assertTrue(isConvertableScaledNumber('0'));
    -  assertTrue(isConvertableScaledNumber('45'));
    -  assertTrue(isConvertableScaledNumber('45K'));
    -  assertTrue(isConvertableScaledNumber('45MB'));
    -  assertTrue(isConvertableScaledNumber('45GB'));
    -  assertTrue(isConvertableScaledNumber('45T'));
    -  assertTrue(isConvertableScaledNumber('2.33P'));
    -  assertTrue(isConvertableScaledNumber('45m'));
    -  assertTrue(isConvertableScaledNumber('45u'));
    -  assertTrue(isConvertableScaledNumber('-5.0n'));
    -
    -  assertFalse(isConvertableScaledNumber('45x'));
    -  assertFalse(isConvertableScaledNumber('ux'));
    -  assertFalse(isConvertableScaledNumber('K'));
    -}
    -
    -function testNumericValueToString() {
    -  var numericValueToString = goog.format.numericValueToString;
    -
    -  assertEquals('0', numericValueToString(0.0));
    -  assertEquals('45', numericValueToString(45));
    -  assertEquals('454', numericValueToString(454));
    -  assertEquals('600', numericValueToString(600));
    -
    -  assertEquals('1.02K', numericValueToString(1024));
    -  assertEquals('2.05K', numericValueToString(2 * 1024));
    -  assertEquals('5.12K', numericValueToString(5 * 1024));
    -  assertEquals('5.246K', numericValueToString(5.12345 * 1024, 3));
    -  assertEquals('5.81K', numericValueToString(5.678 * 1024, 2));
    -
    -  assertEquals('1.05M', numericValueToString(1024 * 1024));
    -  assertEquals('1.57M', numericValueToString(1.5 * 1024 * 1024));
    -  assertEquals('2M', numericValueToString(1.5 * 1024 * 1024, 0));
    -  assertEquals('1.6M', numericValueToString(1.51 * 1024 * 1024, 1));
    -  assertEquals('1.64M', numericValueToString(1.56 * 1024 * 1024, 2));
    -
    -  assertEquals('1.07G', numericValueToString(1024 * 1024 * 1024));
    -  assertEquals('6.44G', numericValueToString(6 * 1024 * 1024 * 1024));
    -  assertEquals('13.26T', numericValueToString(12345.6789 * 1024 * 1024 * 1024));
    -
    -  assertEquals('23.4m', numericValueToString(0.0234));
    -  assertEquals('1.23u', numericValueToString(0.00000123));
    -  assertEquals('15.78n', numericValueToString(0.000000015784));
    -  assertEquals('0.58u', numericValueToString(0.0000005784));
    -  assertEquals('0.5', numericValueToString(0.5));
    -
    -  assertEquals('-45', numericValueToString(-45.3, 0));
    -  assertEquals('-45', numericValueToString(-45.5, 0));
    -  assertEquals('-46', numericValueToString(-45.51, 0));
    -}
    -
    -function testFormatNumBytes() {
    -  var numBytesToString = goog.format.numBytesToString;
    -
    -  assertEquals('45', numBytesToString(45));
    -  assertEquals('454', numBytesToString(454));
    -
    -  assertEquals('5KB', numBytesToString(5 * 1024));
    -  assertEquals('1MB', numBytesToString(1024 * 1024));
    -  assertEquals('6GB', numBytesToString(6 * 1024 * 1024 * 1024));
    -  assertEquals('12.06TB', numBytesToString(12345.6789 * 1024 * 1024 * 1024));
    -
    -  assertEquals('454', numBytesToString(454, 2, true, true));
    -  assertEquals('5 KB', numBytesToString(5 * 1024, 2, true, true));
    -}
    -
    -function testStringToNumeric() {
    -  var stringToNumericValue = goog.format.stringToNumericValue;
    -  var epsilon = Math.pow(10, -10);
    -
    -  assertNaN(stringToNumericValue('foo'));
    -
    -  assertEquals(45, stringToNumericValue('45'));
    -  assertEquals(-45, stringToNumericValue('-45'));
    -  assertEquals(-45, stringToNumericValue('-45'));
    -  assertEquals(454, stringToNumericValue('454'));
    -
    -  assertEquals(5 * 1024, stringToNumericValue('5KB'));
    -  assertEquals(1024 * 1024, stringToNumericValue('1MB'));
    -  assertEquals(6 * 1024 * 1024 * 1024, stringToNumericValue('6GB'));
    -  assertEquals(13260110230978.56, stringToNumericValue('12.06TB'));
    -
    -  assertEquals(5010, stringToNumericValue('5.01K'));
    -  assertEquals(5100000, stringToNumericValue('5.1M'));
    -  assertTrue(Math.abs(0.051 - stringToNumericValue('51.0m')) < epsilon);
    -  assertTrue(Math.abs(0.000051 - stringToNumericValue('51.0u')) < epsilon);
    -}
    -
    -function testStringToNumBytes() {
    -  var stringToNumBytes = goog.format.stringToNumBytes;
    -
    -  assertEquals(45, stringToNumBytes('45'));
    -  assertEquals(454, stringToNumBytes('454'));
    -
    -  assertEquals(5 * 1024, stringToNumBytes('5K'));
    -  assertEquals(1024 * 1024, stringToNumBytes('1M'));
    -  assertEquals(6 * 1024 * 1024 * 1024, stringToNumBytes('6G'));
    -  assertEquals(13260110230978.56, stringToNumBytes('12.06T'));
    -}
    -
    -function testInsertWordBreaks() {
    -  // HTML that gets inserted is browser dependent, ensure for the test it is
    -  // a constant - browser dependent HTML is for display purposes only.
    -  propertyReplacer.set(goog.format, 'WORD_BREAK_HTML', '<wbr>');
    -
    -  var insertWordBreaks = goog.format.insertWordBreaks;
    -
    -  assertEquals('abcdef', insertWordBreaks('abcdef', 10));
    -  assertEquals('ab<wbr>cd<wbr>ef', insertWordBreaks('abcdef', 2));
    -  assertEquals(
    -      'a<wbr>b<wbr>c<wbr>d<wbr>e<wbr>f', insertWordBreaks('abcdef', 1));
    -
    -  assertEquals(
    -      'a&amp;b=<wbr>=fal<wbr>se', insertWordBreaks('a&amp;b==false', 4));
    -  assertEquals('&lt;&amp;&gt;&raquo;<wbr>&laquo;',
    -               insertWordBreaks('&lt;&amp;&gt;&raquo;&laquo;', 4));
    -
    -  assertEquals('a<wbr>b<wbr>c d<wbr>e<wbr>f', insertWordBreaks('abc def', 1));
    -  assertEquals('ab<wbr>c de<wbr>f', insertWordBreaks('abc def', 2));
    -  assertEquals('abc def', insertWordBreaks('abc def', 3));
    -  assertEquals('abc def', insertWordBreaks('abc def', 4));
    -
    -  assertEquals('a<b>cd</b>e<wbr>f', insertWordBreaks('a<b>cd</b>ef', 4));
    -  assertEquals('Thi<wbr>s is a <a href="">lin<wbr>k</a>.',
    -               insertWordBreaks('This is a <a href="">link</a>.', 3));
    -  assertEquals('<abc a="&amp;&amp;&amp;&amp;&amp;">a<wbr>b',
    -      insertWordBreaks('<abc a="&amp;&amp;&amp;&amp;&amp;">ab', 1));
    -
    -  assertEquals('ab\u0300<wbr>cd', insertWordBreaks('ab\u0300cd', 2));
    -  assertEquals('ab\u036F<wbr>cd', insertWordBreaks('ab\u036Fcd', 2));
    -  assertEquals('ab<wbr>\u0370c<wbr>d', insertWordBreaks('ab\u0370cd', 2));
    -  assertEquals('ab<wbr>\uFE1Fc<wbr>d', insertWordBreaks('ab\uFE1Fcd', 2));
    -  assertEquals('ab\u0300<wbr>c\u0301<wbr>de<wbr>f',
    -      insertWordBreaks('ab\u0300c\u0301def', 2));
    -}
    -
    -function testInsertWordBreaksWithFormattingCharacters() {
    -  // HTML that gets inserted is browser dependent, ensure for the test it is
    -  // a constant - browser dependent HTML is for display purposes only.
    -  propertyReplacer.set(goog.format, 'WORD_BREAK_HTML', '<wbr>');
    -  var insertWordBreaks = goog.format.insertWordBreaks;
    -
    -  // A date in Arabic-Indic digits with Right-to-Left Marks (U+200F).
    -  // The date is "11<RLM>/01<RLM>/2012".
    -  var textWithRLMs = 'This is a date - ' +
    -      '\u0661\u0661\u200f/\u0660\u0661\u200f/\u0662\u0660\u0661\u0662';
    -  // A string of 10 Xs with invisible formatting characters in between.
    -  // These characters are in the ranges U+200C to U+200F and U+202A to
    -  // U+202E, inclusive. See: http://unicode.org/charts/PDF/U2000.pdf
    -  var stringWithInvisibleFormatting = 'X\u200cX\u200dX\u200eX\u200fX\u202a' +
    -      'X\u202bX\u202cX\u202dX\u202eX';
    -  // A string formed by concatenating copies of the previous string alternating
    -  // with characters which behave like breaking spaces. Besides the space
    -  // character itself, the other characters are in the range U+2000 to U+200B
    -  // inclusive, except for the exclusion of U+2007 and inclusion of U+2029.
    -  // See: http://unicode.org/charts/PDF/U2000.pdf
    -  var stringWithInvisibleFormattingAndSpacelikeCharacters =
    -      stringWithInvisibleFormatting + ' ' +
    -      stringWithInvisibleFormatting + '\u2000' +
    -      stringWithInvisibleFormatting + '\u2001' +
    -      stringWithInvisibleFormatting + '\u2002' +
    -      stringWithInvisibleFormatting + '\u2003' +
    -      stringWithInvisibleFormatting + '\u2005' +
    -      stringWithInvisibleFormatting + '\u2006' +
    -      stringWithInvisibleFormatting + '\u2008' +
    -      stringWithInvisibleFormatting + '\u2009' +
    -      stringWithInvisibleFormatting + '\u200A' +
    -      stringWithInvisibleFormatting + '\u200B' +
    -      stringWithInvisibleFormatting + '\u2029' +
    -      stringWithInvisibleFormatting;
    -
    -  // Test that the word break algorithm does not count RLMs towards word
    -  // length, and therefore does not insert word breaks into a typical date
    -  // written in Arabic-Indic digits with RTMs (b/5853915).
    -  assertEquals(textWithRLMs, insertWordBreaks(textWithRLMs, 10));
    -
    -  // Test that invisible formatting characters are not counted towards word
    -  // length, and that characters which are treated as breaking spaces behave as
    -  // breaking spaces.
    -  assertEquals(stringWithInvisibleFormattingAndSpacelikeCharacters,
    -      insertWordBreaks(stringWithInvisibleFormattingAndSpacelikeCharacters,
    -      10));
    -}
    -
    -function testInsertWordBreaksBasic() {
    -  // HTML that gets inserted is browser dependent, ensure for the test it is
    -  // a constant - browser dependent HTML is for display purposes only.
    -  propertyReplacer.set(goog.format, 'WORD_BREAK_HTML', '<wbr>');
    -  var insertWordBreaksBasic = goog.format.insertWordBreaksBasic;
    -
    -  assertEquals('abcdef', insertWordBreaksBasic('abcdef', 10));
    -  assertEquals('ab<wbr>cd<wbr>ef', insertWordBreaksBasic('abcdef', 2));
    -  assertEquals(
    -      'a<wbr>b<wbr>c<wbr>d<wbr>e<wbr>f', insertWordBreaksBasic('abcdef', 1));
    -  assertEquals('ab\u0300<wbr>c\u0301<wbr>de<wbr>f',
    -      insertWordBreaksBasic('ab\u0300c\u0301def', 2));
    -
    -  assertEquals(
    -      'Inserting word breaks into the word "Russia" should work fine.',
    -      '\u0420\u043E<wbr>\u0441\u0441<wbr>\u0438\u044F',
    -      insertWordBreaksBasic('\u0420\u043E\u0441\u0441\u0438\u044F', 2));
    -
    -  // The word 'Internet' in Hindi.
    -  var hindiInternet = '\u0907\u0902\u091F\u0930\u0928\u0947\u091F';
    -  assertEquals('The basic algorithm is not good enough to insert word ' +
    -      'breaks into Hindi.',
    -      hindiInternet, insertWordBreaksBasic(hindiInternet, 2));
    -  // The word 'Internet' in Hindi broken into slashes.
    -  assertEquals('Hindi can have word breaks inserted between slashes',
    -      hindiInternet + '<wbr>/' + hindiInternet + '<wbr>.' + hindiInternet,
    -      insertWordBreaksBasic(hindiInternet + '/' + hindiInternet + '.' +
    -          hindiInternet, 2));
    -}
    -
    -function testWordBreaksWorking() {
    -  var text = goog.string.repeat('test', 20);
    -  var textWbr = goog.string.repeat('test' + goog.format.WORD_BREAK_HTML, 20);
    -
    -  var overflowEl = goog.dom.createDom('div',
    -      {'style': 'width: 100px; overflow: hidden; margin 5px'});
    -  var wbrEl = goog.dom.createDom('div',
    -      {'style': 'width: 100px; overflow: hidden; margin-top: 15px'});
    -  goog.dom.appendChild(goog.global.document.body, overflowEl);
    -  goog.dom.appendChild(goog.global.document.body, wbrEl);
    -
    -  overflowEl.innerHTML = text;
    -  wbrEl.innerHTML = textWbr;
    -
    -  assertTrue('Text should overflow', overflowEl.scrollWidth > 100);
    -  assertTrue('Text should not overflow', wbrEl.scrollWidth <= 100);
    -}
    -
    -function testWordBreaksRemovedFromTextContent() {
    -  var expectedText = goog.string.repeat('test', 20);
    -  var textWbr = goog.string.repeat('test' + goog.format.WORD_BREAK_HTML, 20);
    -
    -  var wbrEl = goog.dom.createDom('div', null);
    -  wbrEl.innerHTML = textWbr;
    -
    -  assertEquals('text content should have wbr character removed', expectedText,
    -      goog.dom.getTextContent(wbrEl));
    -
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/format/htmlprettyprinter.js b/src/database/third_party/closure-library/closure/goog/format/htmlprettyprinter.js
    deleted file mode 100644
    index 3fbb5bdf52d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/format/htmlprettyprinter.js
    +++ /dev/null
    @@ -1,409 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides functions to parse and pretty-print HTML strings.
    - *
    - */
    -
    -goog.provide('goog.format.HtmlPrettyPrinter');
    -goog.provide('goog.format.HtmlPrettyPrinter.Buffer');
    -
    -goog.require('goog.object');
    -goog.require('goog.string.StringBuffer');
    -
    -
    -
    -/**
    - * This class formats HTML to be more human-readable.
    - * TODO(user): Add hierarchical indentation.
    - * @param {number=} opt_timeOutMillis Max # milliseconds to spend on #format. If
    - *     this time is exceeded, return partially formatted. 0 or negative number
    - *     indicates no timeout.
    - * @constructor
    - * @final
    - */
    -goog.format.HtmlPrettyPrinter = function(opt_timeOutMillis) {
    -  /**
    -   * Max # milliseconds to spend on #format.
    -   * @type {number}
    -   * @private
    -   */
    -  this.timeOutMillis_ = opt_timeOutMillis && opt_timeOutMillis > 0 ?
    -      opt_timeOutMillis : 0;
    -};
    -
    -
    -/**
    - * Singleton.
    - * @type {goog.format.HtmlPrettyPrinter?}
    - * @private
    - */
    -goog.format.HtmlPrettyPrinter.instance_ = null;
    -
    -
    -/**
    - * Singleton lazy initializer.
    - * @return {!goog.format.HtmlPrettyPrinter} Singleton.
    - * @private
    - */
    -goog.format.HtmlPrettyPrinter.getInstance_ = function() {
    -  if (!goog.format.HtmlPrettyPrinter.instance_) {
    -    goog.format.HtmlPrettyPrinter.instance_ =
    -        new goog.format.HtmlPrettyPrinter();
    -  }
    -  return goog.format.HtmlPrettyPrinter.instance_;
    -};
    -
    -
    -/**
    - * Static utility function. See prototype #format.
    - * @param {string} html The HTML text to pretty print.
    - * @return {string} Formatted result.
    - */
    -goog.format.HtmlPrettyPrinter.format = function(html) {
    -  return goog.format.HtmlPrettyPrinter.getInstance_().format(html);
    -};
    -
    -
    -/**
    - * List of patterns used to tokenize HTML for pretty printing. Cache
    - * subexpression for tag name.
    - * comment|meta-tag|tag|text|other-less-than-characters
    - * @type {RegExp}
    - * @private
    - */
    -goog.format.HtmlPrettyPrinter.TOKEN_REGEX_ =
    -    /(?:<!--.*?-->|<!.*?>|<(\/?)(\w+)[^>]*>|[^<]+|<)/g;
    -
    -
    -/**
    - * Tags whose contents we don't want pretty printed.
    - * @type {Object}
    - * @private
    - */
    -goog.format.HtmlPrettyPrinter.NON_PRETTY_PRINTED_TAGS_ = goog.object.createSet(
    -    'script',
    -    'style',
    -    'pre',
    -    'xmp');
    -
    -
    -/**
    - * 'Block' tags. We should add newlines before and after these tags during
    - * pretty printing. Tags drawn mostly from HTML4 definitions for block and other
    - * non-online tags, excepting the ones in
    - * #goog.format.HtmlPrettyPrinter.NON_PRETTY_PRINTED_TAGS_.
    - *
    - * @type {Object}
    - * @private
    - */
    -goog.format.HtmlPrettyPrinter.BLOCK_TAGS_ = goog.object.createSet(
    -    'address',
    -    'applet',
    -    'area',
    -    'base',
    -    'basefont',
    -    'blockquote',
    -    'body',
    -    'caption',
    -    'center',
    -    'col',
    -    'colgroup',
    -    'dir',
    -    'div',
    -    'dl',
    -    'fieldset',
    -    'form',
    -    'frame',
    -    'frameset',
    -    'h1',
    -    'h2',
    -    'h3',
    -    'h4',
    -    'h5',
    -    'h6',
    -    'head',
    -    'hr',
    -    'html',
    -    'iframe',
    -    'isindex',
    -    'legend',
    -    'link',
    -    'menu',
    -    'meta',
    -    'noframes',
    -    'noscript',
    -    'ol',
    -    'optgroup',
    -    'option',
    -    'p',
    -    'param',
    -    'table',
    -    'tbody',
    -    'td',
    -    'tfoot',
    -    'th',
    -    'thead',
    -    'title',
    -    'tr',
    -    'ul');
    -
    -
    -/**
    - * Non-block tags that break flow. We insert a line break after, but not before
    - * these. Tags drawn from HTML4 definitions.
    - * @type {Object}
    - * @private
    - */
    -goog.format.HtmlPrettyPrinter.BREAKS_FLOW_TAGS_ = goog.object.createSet(
    -    'br',
    -    'dd',
    -    'dt',
    -    'br',
    -    'li',
    -    'noframes');
    -
    -
    -/**
    - * Empty tags. These are treated as both start and end tags.
    - * @type {Object}
    - * @private
    - */
    -goog.format.HtmlPrettyPrinter.EMPTY_TAGS_ = goog.object.createSet(
    -    'br',
    -    'hr',
    -    'isindex');
    -
    -
    -/**
    - * Breaks up HTML so it's easily readable by the user.
    - * @param {string} html The HTML text to pretty print.
    - * @return {string} Formatted result.
    - * @throws {Error} Regex error, data loss, or endless loop detected.
    - */
    -goog.format.HtmlPrettyPrinter.prototype.format = function(html) {
    -  // Trim leading whitespace, but preserve first indent; in other words, keep
    -  // any spaces immediately before the first non-whitespace character (that's
    -  // what $1 is), but remove all other leading whitespace. This adjustment
    -  // historically had been made in Docs. The motivation is that some
    -  // browsers prepend several line breaks in designMode.
    -  html = html.replace(/^\s*?( *\S)/, '$1');
    -
    -  // Trim trailing whitespace.
    -  html = html.replace(/\s+$/, '');
    -
    -  // Keep track of how much time we've used.
    -  var timeOutMillis = this.timeOutMillis_;
    -  var startMillis = timeOutMillis ? goog.now() : 0;
    -
    -  // Handles concatenation of the result and required line breaks.
    -  var buffer = new goog.format.HtmlPrettyPrinter.Buffer();
    -
    -  // Declare these for efficiency since we access them in a loop.
    -  var tokenRegex = goog.format.HtmlPrettyPrinter.TOKEN_REGEX_;
    -  var nonPpTags = goog.format.HtmlPrettyPrinter.NON_PRETTY_PRINTED_TAGS_;
    -  var blockTags = goog.format.HtmlPrettyPrinter.BLOCK_TAGS_;
    -  var breaksFlowTags = goog.format.HtmlPrettyPrinter.BREAKS_FLOW_TAGS_;
    -  var emptyTags = goog.format.HtmlPrettyPrinter.EMPTY_TAGS_;
    -
    -  // Used to verify we're making progress through our regex tokenization.
    -  var lastIndex = 0;
    -
    -  // Use this to track non-pretty-printed tags and childen.
    -  var nonPpTagStack = [];
    -
    -  // Loop through each matched token.
    -  var match;
    -  while (match = tokenRegex.exec(html)) {
    -    // Get token.
    -    var token = match[0];
    -
    -    // Is this token a tag? match.length == 3 for tags, 1 for all others.
    -    if (match.length == 3) {
    -      var tagName = match[2];
    -      if (tagName) {
    -        tagName = tagName.toLowerCase();
    -      }
    -
    -      // Non-pretty-printed tags?
    -      if (nonPpTags.hasOwnProperty(tagName)) {
    -        // End tag?
    -        if (match[1] == '/') {
    -          // Do we have a matching start tag?
    -          var stackSize = nonPpTagStack.length;
    -          var startTagName = stackSize ? nonPpTagStack[stackSize - 1] : null;
    -          if (startTagName == tagName) {
    -            // End of non-pretty-printed block. Line break after.
    -            nonPpTagStack.pop();
    -            buffer.pushToken(false, token, !nonPpTagStack.length);
    -          } else {
    -            // Malformed HTML. No line breaks.
    -            buffer.pushToken(false, token, false);
    -          }
    -        } else {
    -          // Start of non-pretty-printed block. Line break before.
    -          buffer.pushToken(!nonPpTagStack.length, token, false);
    -          nonPpTagStack.push(tagName);
    -        }
    -      } else if (nonPpTagStack.length) {
    -        // Inside non-pretty-printed block, no new line breaks.
    -        buffer.pushToken(false, token, false);
    -      } else if (blockTags.hasOwnProperty(tagName)) {
    -        // Put line break before start block and after end block tags.
    -        var isEmpty = emptyTags.hasOwnProperty(tagName);
    -        var isEndTag = match[1] == '/';
    -        buffer.pushToken(isEmpty || !isEndTag, token, isEmpty || isEndTag);
    -      } else if (breaksFlowTags.hasOwnProperty(tagName)) {
    -        var isEmpty = emptyTags.hasOwnProperty(tagName);
    -        var isEndTag = match[1] == '/';
    -        // Put line break after end flow-breaking tags.
    -        buffer.pushToken(false, token, isEndTag || isEmpty);
    -      } else {
    -        // All other tags, no line break.
    -        buffer.pushToken(false, token, false);
    -      }
    -    } else {
    -      // Non-tags, no line break.
    -      buffer.pushToken(false, token, false);
    -    }
    -
    -    // Double check that we're making progress.
    -    var newLastIndex = tokenRegex.lastIndex;
    -    if (!token || newLastIndex <= lastIndex) {
    -      throw Error('Regex failed to make progress through source html.');
    -    }
    -    lastIndex = newLastIndex;
    -
    -    // Out of time?
    -    if (timeOutMillis) {
    -      if (goog.now() - startMillis > timeOutMillis) {
    -        // Push unprocessed data as one big token and reset regex object.
    -        buffer.pushToken(false, html.substring(tokenRegex.lastIndex), false);
    -        tokenRegex.lastIndex = 0;
    -        break;
    -      }
    -    }
    -  }
    -
    -  // Ensure we end in a line break.
    -  buffer.lineBreak();
    -
    -  // Construct result string.
    -  var result = String(buffer);
    -
    -  // Length should be original length plus # line breaks added.
    -  var expectedLength = html.length + buffer.breakCount;
    -  if (result.length != expectedLength) {
    -    throw Error('Lost data pretty printing html.');
    -  }
    -
    -  return result;
    -};
    -
    -
    -
    -/**
    - * This class is a buffer to which we push our output. It tracks line breaks to
    - * make sure we don't add unnecessary ones.
    - * @constructor
    - * @final
    - */
    -goog.format.HtmlPrettyPrinter.Buffer = function() {
    -  /**
    -   * Tokens to be output in #toString.
    -   * @type {goog.string.StringBuffer}
    -   * @private
    -   */
    -  this.out_ = new goog.string.StringBuffer();
    -};
    -
    -
    -/**
    - * Tracks number of line breaks added.
    - * @type {number}
    - */
    -goog.format.HtmlPrettyPrinter.Buffer.prototype.breakCount = 0;
    -
    -
    -/**
    - * Tracks if we are at the start of a new line.
    - * @type {boolean}
    - * @private
    - */
    -goog.format.HtmlPrettyPrinter.Buffer.prototype.isBeginningOfNewLine_ = true;
    -
    -
    -/**
    - * Tracks if we need a new line before the next token.
    - * @type {boolean}
    - * @private
    - */
    -goog.format.HtmlPrettyPrinter.Buffer.prototype.needsNewLine_ = false;
    -
    -
    -/**
    - * Adds token and necessary line breaks to output buffer.
    - * @param {boolean} breakBefore If true, add line break before token if
    - *     necessary.
    - * @param {string} token Token to push.
    - * @param {boolean} breakAfter If true, add line break after token if
    - *     necessary.
    - */
    -goog.format.HtmlPrettyPrinter.Buffer.prototype.pushToken = function(
    -    breakBefore, token, breakAfter) {
    -  // If this token needs a preceeding line break, and
    -  // we haven't already added a line break, and
    -  // this token does not start with a line break,
    -  // then add line break.
    -  // Due to FF3.0 bug with lists, we don't insert a /n
    -  // right before </ul>. See bug 1520665.
    -  if ((this.needsNewLine_ || breakBefore) &&
    -      !/^\r?\n/.test(token) &&
    -      !/\/ul/i.test(token)) {
    -    this.lineBreak();
    -  }
    -
    -  // Token.
    -  this.out_.append(token);
    -
    -  // Remember if this string ended with a line break so we know we don't have to
    -  // insert another one before the next token.
    -  this.isBeginningOfNewLine_ = /\r?\n$/.test(token);
    -
    -  // Remember if this token requires a line break after it. We don't insert it
    -  // here because we might not have to if the next token starts with a line
    -  // break.
    -  this.needsNewLine_ = breakAfter && !this.isBeginningOfNewLine_;
    -};
    -
    -
    -/**
    - * Append line break if we need one.
    - */
    -goog.format.HtmlPrettyPrinter.Buffer.prototype.lineBreak = function() {
    -  if (!this.isBeginningOfNewLine_) {
    -    this.out_.append('\n');
    -    ++this.breakCount;
    -  }
    -};
    -
    -
    -/**
    - * @return {string} String representation of tokens.
    - * @override
    - */
    -goog.format.HtmlPrettyPrinter.Buffer.prototype.toString = function() {
    -  return this.out_.toString();
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/format/htmlprettyprinter_test.html b/src/database/third_party/closure-library/closure/goog/format/htmlprettyprinter_test.html
    deleted file mode 100644
    index 03cf1ff0025..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/format/htmlprettyprinter_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.format.HtmlPrettyPrinter
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.format.HtmlPrettyPrinterTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/format/htmlprettyprinter_test.js b/src/database/third_party/closure-library/closure/goog/format/htmlprettyprinter_test.js
    deleted file mode 100644
    index 3519e923179..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/format/htmlprettyprinter_test.js
    +++ /dev/null
    @@ -1,205 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.format.HtmlPrettyPrinterTest');
    -goog.setTestOnly('goog.format.HtmlPrettyPrinterTest');
    -
    -goog.require('goog.format.HtmlPrettyPrinter');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.jsunit');
    -
    -var COMPLEX_HTML = '<!DOCTYPE root-element [SYSTEM OR PUBLIC FPI] "uri" [' +
    -    '<!-- internal declarations -->]>' +
    -    '<html><head><title>My HTML</title><!-- my comment --></head>' +
    -    '<body><h1>My Header</h1>My text.<br><b>My bold text.</b><hr>' +
    -    '<pre>My\npreformatted <br> HTML.</pre>5 < 10</body>' +
    -    '</html>';
    -var mockClock;
    -var mockClockTicks;
    -
    -function setUp() {
    -  mockClockTicks = 0;
    -  mockClock = new goog.testing.MockClock();
    -  mockClock.getCurrentTime = function() {
    -    return mockClockTicks++;
    -  };
    -  mockClock.install();
    -}
    -
    -function tearDown() {
    -  if (mockClock) {
    -    mockClock.uninstall();
    -  }
    -}
    -
    -function testSimpleHtml() {
    -  var actual = goog.format.HtmlPrettyPrinter.format('<br><b>bold</b>');
    -  assertEquals('<br>\n<b>bold</b>\n', actual);
    -  assertEquals(actual, goog.format.HtmlPrettyPrinter.format(actual));
    -}
    -
    -function testSimpleHtmlMixedCase() {
    -  var actual = goog.format.HtmlPrettyPrinter.format('<BR><b>bold</b>');
    -  assertEquals('<BR>\n<b>bold</b>\n', actual);
    -  assertEquals(actual, goog.format.HtmlPrettyPrinter.format(actual));
    -}
    -
    -function testComplexHtml() {
    -  var actual = goog.format.HtmlPrettyPrinter.format(COMPLEX_HTML);
    -  var expected = '<!DOCTYPE root-element [SYSTEM OR PUBLIC FPI] "uri" [' +
    -      '<!-- internal declarations -->]>\n' +
    -      '<html>\n' +
    -      '<head>\n' +
    -      '<title>My HTML</title>\n' +
    -      '<!-- my comment -->' +
    -      '</head>\n' +
    -      '<body>\n' +
    -      '<h1>My Header</h1>\n' +
    -      'My text.<br>\n' +
    -      '<b>My bold text.</b>\n' +
    -      '<hr>\n' +
    -      '<pre>My\npreformatted <br> HTML.</pre>\n' +
    -      '5 < 10' +
    -      '</body>\n' +
    -      '</html>\n';
    -  assertEquals(expected, actual);
    -  assertEquals(actual, goog.format.HtmlPrettyPrinter.format(actual));
    -}
    -
    -function testTimeout() {
    -  var pp = new goog.format.HtmlPrettyPrinter(3);
    -  var actual = pp.format(COMPLEX_HTML);
    -  var expected = '<!DOCTYPE root-element [SYSTEM OR PUBLIC FPI] "uri" [' +
    -      '<!-- internal declarations -->]>\n' +
    -      '<html>\n' +
    -      '<head><title>My HTML</title><!-- my comment --></head>' +
    -      '<body><h1>My Header</h1>My text.<br><b>My bold text.</b><hr>' +
    -      '<pre>My\npreformatted <br> HTML.</pre>5 < 10</body>' +
    -      '</html>\n';
    -  assertEquals(expected, actual);
    -}
    -
    -function testKeepLeadingIndent() {
    -  var original = ' <b>Bold</b> <i>Ital</i> ';
    -  var expected = ' <b>Bold</b> <i>Ital</i>\n';
    -  assertEquals(expected, goog.format.HtmlPrettyPrinter.format(original));
    -}
    -
    -function testTrimLeadingLineBreaks() {
    -  var original = '\n \t\r\n  \n <b>Bold</b> <i>Ital</i> ';
    -  var expected = ' <b>Bold</b> <i>Ital</i>\n';
    -  assertEquals(expected, goog.format.HtmlPrettyPrinter.format(original));
    -}
    -
    -function testExtraLines() {
    -  var original = '<br>\ntombrat';
    -  assertEquals(original + '\n', goog.format.HtmlPrettyPrinter.format(original));
    -}
    -
    -function testCrlf() {
    -  var original = '<br>\r\none\r\ntwo<br>';
    -  assertEquals(original + '\n', goog.format.HtmlPrettyPrinter.format(original));
    -}
    -
    -function testEndInLineBreak() {
    -  assertEquals('foo\n', goog.format.HtmlPrettyPrinter.format('foo'));
    -  assertEquals('foo\n', goog.format.HtmlPrettyPrinter.format('foo\n'));
    -  assertEquals('foo\n', goog.format.HtmlPrettyPrinter.format('foo\n\n'));
    -  assertEquals('foo<br>\n', goog.format.HtmlPrettyPrinter.format('foo<br>'));
    -  assertEquals('foo<br>\n', goog.format.HtmlPrettyPrinter.format('foo<br>\n'));
    -}
    -
    -function testTable() {
    -  var original = '<table>' +
    -      '<tr><td>one.one</td><td>one.two</td></tr>' +
    -      '<tr><td>two.one</td><td>two.two</td></tr>' +
    -      '</table>';
    -  var expected = '<table>\n' +
    -      '<tr>\n<td>one.one</td>\n<td>one.two</td>\n</tr>\n' +
    -      '<tr>\n<td>two.one</td>\n<td>two.two</td>\n</tr>\n' +
    -      '</table>\n';
    -  assertEquals(expected, goog.format.HtmlPrettyPrinter.format(original));
    -}
    -
    -
    -/**
    - * We have a sanity check in HtmlPrettyPrinter to make sure the regex index
    - * advances after every match. We should never hit this, but we include it on
    - * the chance there is some corner case where the pattern would match but not
    - * process a new token. It's not generally a good idea to break the
    - * implementation to test behavior, but this is the easiest way to mimic a
    - * bad internal state.
    - */
    -function testRegexMakesProgress() {
    -  var original = goog.format.HtmlPrettyPrinter.TOKEN_REGEX_;
    -
    -  try {
    -    // This regex matches \B, an index between 2 word characters, so the regex
    -    // index does not advance when matching this.
    -    goog.format.HtmlPrettyPrinter.TOKEN_REGEX_ =
    -        /(?:\B|<!--.*?-->|<!.*?>|<(\/?)(\w+)[^>]*>|[^<]+|<)/g;
    -
    -    // It would work on this string.
    -    assertEquals('f o o\n', goog.format.HtmlPrettyPrinter.format('f o o'));
    -
    -    // But not this one.
    -    var ex = assertThrows('should have failed for invalid regex - endless loop',
    -        goog.partial(goog.format.HtmlPrettyPrinter.format, COMPLEX_HTML));
    -    assertEquals('Regex failed to make progress through source html.',
    -        ex.message);
    -  } finally {
    -    goog.format.HtmlPrettyPrinter.TOKEN_REGEX_ = original;
    -  }
    -}
    -
    -
    -/**
    - * FF3.0 doesn't like \n between </li> and </ul>. See bug 1520665.
    - */
    -function testLists() {
    -  var original = '<ul><li>one</li><ul><li>two</li></UL><li>three</li></ul>';
    -  var expected =
    -      '<ul><li>one</li>\n<ul><li>two</li></UL>\n<li>three</li></ul>\n';
    -  assertEquals(expected, goog.format.HtmlPrettyPrinter.format(original));
    -}
    -
    -
    -/**
    - * We have a sanity check in HtmlPrettyPrinter to make sure the regex fully
    - * tokenizes the string. We should never hit this, but we include it on the
    - * chance there is some corner case where the pattern would miss a section of
    - * original string. It's not generally a good idea to break the
    - * implementation to test behavior, but this is the easiest way to mimic a
    - * bad internal state.
    - */
    -function testAvoidDataLoss() {
    -  var original = goog.format.HtmlPrettyPrinter.TOKEN_REGEX_;
    -
    -  try {
    -    // This regex does not match stranded '<' characters, so does not fully
    -    // tokenize the string.
    -    goog.format.HtmlPrettyPrinter.TOKEN_REGEX_ =
    -        /(?:<!--.*?-->|<!.*?>|<(\/?)(\w+)[^>]*>|[^<]+)/g;
    -
    -    // It would work on this string.
    -    assertEquals('foo\n', goog.format.HtmlPrettyPrinter.format('foo'));
    -
    -    // But not this one.
    -    var ex = assertThrows('should have failed for invalid regex - data loss',
    -        goog.partial(goog.format.HtmlPrettyPrinter.format, COMPLEX_HTML));
    -    assertEquals('Lost data pretty printing html.', ex.message);
    -  } finally {
    -    goog.format.HtmlPrettyPrinter.TOKEN_REGEX_ = original;
    -  }
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/format/internationalizedemailaddress.js b/src/database/third_party/closure-library/closure/goog/format/internationalizedemailaddress.js
    deleted file mode 100644
    index fd1dfe6cf0a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/format/internationalizedemailaddress.js
    +++ /dev/null
    @@ -1,256 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides functions to parse and manipulate internationalized
    - * email addresses. This is useful in the context of Email Address
    - * Internationalization (EAI) as defined by RFC6530.
    - *
    - */
    -
    -goog.provide('goog.format.InternationalizedEmailAddress');
    -
    -goog.require('goog.format.EmailAddress');
    -
    -goog.require('goog.string');
    -
    -
    -
    -/**
    - * Formats an email address string for display, and allows for extraction of
    - * the individual components of the address.
    - * @param {string=} opt_address The email address.
    - * @param {string=} opt_name The name associated with the email address.
    - * @constructor
    - * @extends {goog.format.EmailAddress}
    - */
    -goog.format.InternationalizedEmailAddress = function(opt_address, opt_name) {
    -  goog.format.InternationalizedEmailAddress.base(
    -      this, 'constructor', opt_address, opt_name);
    -};
    -goog.inherits(
    -    goog.format.InternationalizedEmailAddress, goog.format.EmailAddress);
    -
    -
    -/**
    - * A string representing the RegExp for the local part of an EAI email address.
    - * @private
    - */
    -goog.format.InternationalizedEmailAddress.EAI_LOCAL_PART_REGEXP_STR_ =
    -    '((?!\\s)[+a-zA-Z0-9_.!#$%&\'*\\/=?^`{|}~\u0080-\uFFFFFF-])+';
    -
    -
    -/**
    - * A string representing the RegExp for a label in the domain part of an EAI
    - * email address.
    - * @private
    - */
    -goog.format.InternationalizedEmailAddress.EAI_LABEL_CHAR_REGEXP_STR_ =
    -    '(?!\\s)[a-zA-Z0-9\u0080-\u3001\u3003-\uFF0D\uFF0F-\uFF60\uFF62-\uFFFFFF-]';
    -
    -
    -/**
    - * A string representing the RegExp for the domain part of an EAI email address.
    - * @private
    - */
    -goog.format.InternationalizedEmailAddress.EAI_DOMAIN_PART_REGEXP_STR_ =
    -    // A unicode character (ASCII or Unicode excluding periods)
    -    '(' + goog.format.InternationalizedEmailAddress.EAI_LABEL_CHAR_REGEXP_STR_ +
    -    // Such character 1+ times, followed by a Unicode period. All 1+ times.
    -    '+[\\.\\uFF0E\\u3002\\uFF61])+' +
    -    // And same thing but without a period in the end
    -    goog.format.InternationalizedEmailAddress.EAI_LABEL_CHAR_REGEXP_STR_ +
    -    '{2,63}';
    -
    -
    -/**
    - * Match string for address separators. This list is the result of the
    - * discussion in b/16241003.
    - * @type {string}
    - * @private
    - */
    -goog.format.InternationalizedEmailAddress.ADDRESS_SEPARATORS_ =
    -    ',' + // U+002C ( , ) COMMA
    -    ';' + // U+003B ( ; ) SEMICOLON
    -    '\u055D' + // ( ՝ ) ARMENIAN COMMA
    -    '\u060C' + // ( ، ) ARABIC COMMA
    -    '\u1363' + // ( ፣ ) ETHIOPIC COMMA
    -    '\u1802' + // ( ᠂ ) MONGOLIAN COMMA
    -    '\u1808' + // ( ᠈ ) MONGOLIAN MANCHU COMMA
    -    '\u2E41' + // ( ⹁ ) REVERSED COMMA
    -    '\u3001' + // ( 、 ) IDEOGRAPHIC COMMA
    -    '\uFF0C' + // ( , ) FULLWIDTH COMMA
    -    '\u061B' + // ( ‎؛‎ ) ARABIC SEMICOLON
    -    '\u1364' + // ( ፤ ) ETHIOPIC SEMICOLON
    -    '\uFF1B' + // ( ; ) FULLWIDTH SEMICOLON
    -    '\uFF64' + // ( 、 ) HALFWIDTH IDEOGRAPHIC COMMA
    -    '\u104A'; // ( ၊ ) MYANMAR SIGN LITTLE SECTION
    -
    -
    -/**
    - * Match string for characters that, when in a display name, require it to be
    - * quoted.
    - * @type {string}
    - * @private
    - */
    -goog.format.InternationalizedEmailAddress.CHARS_REQUIRE_QUOTES_ =
    -    goog.format.EmailAddress.SPECIAL_CHARS +
    -    goog.format.InternationalizedEmailAddress.ADDRESS_SEPARATORS_;
    -
    -
    -/**
    - * A RegExp to match the local part of an EAI email address.
    - * @private {!RegExp}
    - */
    -goog.format.InternationalizedEmailAddress.EAI_LOCAL_PART_ =
    -    new RegExp('^' +
    -        goog.format.InternationalizedEmailAddress.EAI_LOCAL_PART_REGEXP_STR_ +
    -        '$');
    -
    -
    -/**
    - * A RegExp to match the domain part of an EAI email address.
    - * @private {!RegExp}
    - */
    -goog.format.InternationalizedEmailAddress.EAI_DOMAIN_PART_ =
    -    new RegExp('^' +
    -        goog.format.InternationalizedEmailAddress.EAI_DOMAIN_PART_REGEXP_STR_ +
    -        '$');
    -
    -
    -/**
    - * A RegExp to match an EAI email address.
    - * @private {!RegExp}
    - */
    -goog.format.InternationalizedEmailAddress.EAI_EMAIL_ADDRESS_ =
    -    new RegExp('^' +
    -        goog.format.InternationalizedEmailAddress.EAI_LOCAL_PART_REGEXP_STR_ +
    -        '@' +
    -        goog.format.InternationalizedEmailAddress.EAI_DOMAIN_PART_REGEXP_STR_ +
    -        '$');
    -
    -
    -/**
    - * Checks if the provided string is a valid local part (part before the '@') of
    - * an EAI email address.
    - * @param {string} str The local part to check.
    - * @return {boolean} Whether the provided string is a valid local part.
    - */
    -goog.format.InternationalizedEmailAddress.isValidLocalPartSpec = function(str) {
    -  if (!goog.isDefAndNotNull(str)) {
    -    return false;
    -  }
    -  return goog.format.InternationalizedEmailAddress.EAI_LOCAL_PART_.test(str);
    -};
    -
    -
    -/**
    - * Checks if the provided string is a valid domain part (part after the '@') of
    - * an EAI email address.
    - * @param {string} str The domain part to check.
    - * @return {boolean} Whether the provided string is a valid domain part.
    - */
    -goog.format.InternationalizedEmailAddress.isValidDomainPartSpec =
    -    function(str) {
    -  if (!goog.isDefAndNotNull(str)) {
    -    return false;
    -  }
    -  return goog.format.InternationalizedEmailAddress.EAI_DOMAIN_PART_.test(str);
    -};
    -
    -
    -/** @override */
    -goog.format.InternationalizedEmailAddress.prototype.isValid = function() {
    -  return goog.format.InternationalizedEmailAddress.isValidAddrSpec(
    -      this.address);
    -};
    -
    -
    -/**
    - * Checks if the provided string is a valid email address. Supports both
    - * simple email addresses (address specs) and addresses that contain display
    - * names.
    - * @param {string} str The email address to check.
    - * @return {boolean} Whether the provided string is a valid address.
    - */
    -goog.format.InternationalizedEmailAddress.isValidAddress = function(str) {
    -  if (!goog.isDefAndNotNull(str)) {
    -    return false;
    -  }
    -  return goog.format.InternationalizedEmailAddress.parse(str).isValid();
    -};
    -
    -
    -/**
    - * Checks if the provided string is a valid address spec (local@domain.com).
    - * @param {string} str The email address to check.
    - * @return {boolean} Whether the provided string is a valid address spec.
    - */
    -goog.format.InternationalizedEmailAddress.isValidAddrSpec = function(str) {
    -  if (!goog.isDefAndNotNull(str)) {
    -    return false;
    -  }
    -
    -  // This is a fairly naive implementation, but it covers 99% of use cases.
    -  // For more details, see http://en.wikipedia.org/wiki/Email_address#Syntax
    -  return goog.format.InternationalizedEmailAddress.EAI_EMAIL_ADDRESS_.test(str);
    -};
    -
    -
    -/**
    - * Parses a string containing email addresses of the form
    - * "name" &lt;address&gt; into an array of email addresses.
    - * @param {string} str The address list.
    - * @return {!Array<!goog.format.EmailAddress>} The parsed emails.
    - */
    -goog.format.InternationalizedEmailAddress.parseList = function(str) {
    -  return goog.format.EmailAddress.parseListInternal(
    -      str, goog.format.InternationalizedEmailAddress.parse,
    -      goog.format.InternationalizedEmailAddress.isAddressSeparator);
    -};
    -
    -
    -/**
    - * Parses an email address of the form "name" &lt;address&gt; into
    - * an email address.
    - * @param {string} addr The address string.
    - * @return {!goog.format.EmailAddress} The parsed address.
    - */
    -goog.format.InternationalizedEmailAddress.parse = function(addr) {
    -  return goog.format.EmailAddress.parseInternal(
    -      addr, goog.format.InternationalizedEmailAddress);
    -};
    -
    -
    -/**
    - * @param {string} ch The character to test.
    - * @return {boolean} Whether the provided character is an address separator.
    - */
    -goog.format.InternationalizedEmailAddress.isAddressSeparator = function(ch) {
    -  return goog.string.contains(
    -      goog.format.InternationalizedEmailAddress.ADDRESS_SEPARATORS_, ch);
    -};
    -
    -
    -/**
    - * Return the address in a standard format:
    - *  - remove extra spaces.
    - *  - Surround name with quotes if it contains special characters.
    - * @return {string} The cleaned address.
    - * @override
    - */
    -goog.format.InternationalizedEmailAddress.prototype.toString = function() {
    -  return this.toStringInternal(
    -      goog.format.InternationalizedEmailAddress.CHARS_REQUIRE_QUOTES_);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/format/internationalizedemailaddress_test.html b/src/database/third_party/closure-library/closure/goog/format/internationalizedemailaddress_test.html
    deleted file mode 100644
    index c07e2137a54..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/format/internationalizedemailaddress_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.format.InternationalizedEmailAddress
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.format.InternationalizedEmailAddressTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/format/internationalizedemailaddress_test.js b/src/database/third_party/closure-library/closure/goog/format/internationalizedemailaddress_test.js
    deleted file mode 100644
    index 51450ee57fb..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/format/internationalizedemailaddress_test.js
    +++ /dev/null
    @@ -1,335 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.format.InternationalizedEmailAddressTest');
    -goog.setTestOnly('goog.format.InternationalizedEmailAddressTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.format.InternationalizedEmailAddress');
    -goog.require('goog.testing.jsunit');
    -
    -
    -/**
    - * Asserts that the given validation function generates the expected outcome for
    - * a set of expected valid and a second set of expected invalid addresses.
    - * containing the specified address strings, irrespective of their order.
    - * @param {function(string):boolean} testFunc Validation function to be tested.
    - * @param {!Array<string>} valid List of addresses that should be valid.
    - * @param {!Array<string>} invalid List of addresses that should be invalid.
    - * @private
    - */
    -function doIsValidTest(testFunc, valid, invalid) {
    -  goog.array.forEach(valid, function(str) {
    -    assertTrue('"' + str + '" should be valid.', testFunc(str));
    -  });
    -  goog.array.forEach(invalid, function(str) {
    -    assertFalse('"' + str + '" should be invalid.', testFunc(str));
    -  });
    -}
    -
    -
    -/**
    - * Asserts that parsing the inputString produces a list of email addresses
    - * containing the specified address strings, irrespective of their order.
    - * @param {string} inputString A raw address list.
    - * @param {!Array<string>} expectedList The expected results.
    - * @param {string=} opt_message An assertion message.
    - * @return {string} the resulting email address objects.
    - */
    -function assertParsedList(inputString, expectedList, opt_message) {
    -  var message = opt_message || 'Should parse address correctly';
    -  var result = goog.format.InternationalizedEmailAddress.parseList(inputString);
    -  assertEquals(
    -      'Should have correct # of addresses', expectedList.length, result.length);
    -  for (var i = 0; i < expectedList.length; ++i) {
    -    assertEquals(message, expectedList[i], result[i].getAddress());
    -  }
    -  return result;
    -}
    -
    -function testParseList() {
    -  // Test only the new cases added by EAI (other cases covered in parent
    -  // class test)
    -  assertParsedList('<me.みんあ@me.xn--l8jtg9b>', ['me.みんあ@me.xn--l8jtg9b']);
    -}
    -
    -function testIsEaiValid() {
    -  var valid = [
    -    'e@b.eu',
    -    '<a.b+foo@c.com>',
    -    'eric <e@b.com>',
    -    '"e" <e@b.com>',
    -    'a@FOO.MUSEUM',
    -    'bla@b.co.ac.uk',
    -    'bla@a.b.com',
    -    'o\'hara@gm.com',
    -    'plus+is+allowed@gmail.com',
    -    '!/#$%&\'*+-=~|`{}?^_@expample.com',
    -    'confirm-bhk=modulo.org@yahoogroups.com',
    -    'み.ん-あ@みんあ.みんあ',
    -    'みんあ@test.com',
    -    'test@test.みんあ',
    -    'test@みんあ.com',
    -    'me.みんあ@me.xn--l8jtg9b',
    -    'みんあ@me.xn--l8jtg9b',
    -    'fullwidthfullstop@sld' + '\uff0e' + 'tld',
    -    'ideographicfullstop@sld' + '\u3002' + 'tld',
    -    'halfwidthideographicfullstop@sld' + '\uff61' + 'tld'
    -  ];
    -  var invalid = [
    -    null,
    -    undefined,
    -    'e',
    -    '',
    -    'e @c.com',
    -    'a@b',
    -    'foo.com',
    -    'foo@c..com',
    -    'test@gma=il.com',
    -    'aaa@gmail',
    -    'has some spaces@gmail.com',
    -    'has@three@at@signs.com',
    -    '@no-local-part.com'
    -  ];
    -  doIsValidTest(
    -      goog.format.InternationalizedEmailAddress.isValidAddress, valid, invalid);
    -}
    -
    -function testIsValidLocalPart() {
    -  var valid = [
    -    'e',
    -    'a.b+foo',
    -    'o\'hara',
    -    'user+someone',
    -    '!/#$%&\'*+-=~|`{}?^_',
    -    'confirm-bhk=modulo.org',
    -    'me.みんあ',
    -    'みんあ'
    -  ];
    -  var invalid = [
    -    null,
    -    undefined,
    -    'A@b@c',
    -    'a"b(c)d,e:f;g<h>i[j\\k]l',
    -    'just"not"right',
    -    'this is"not\\allowed',
    -    'this\\ still\"not\\\\allowed',
    -    'has some spaces'
    -  ];
    -  doIsValidTest(goog.format.InternationalizedEmailAddress.isValidLocalPartSpec,
    -      valid, invalid);
    -}
    -
    -function testIsValidDomainPart() {
    -  var valid = [
    -    'example.com',
    -    'dept.example.org',
    -    'long.domain.with.lots.of.dots',
    -    'me.xn--l8jtg9b',
    -    'me.みんあ',
    -    'sld.looooooongtld',
    -    'sld' + '\uff0e' + 'tld',
    -    'sld' + '\u3002' + 'tld',
    -    'sld' + '\uff61' + 'tld'
    -  ];
    -  var invalid = [
    -    null,
    -    undefined,
    -    '',
    -    '@has.an.at.sign',
    -    '..has.leading.dots',
    -    'gma=il.com',
    -    'DoesNotHaveADot',
    -    'aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffgggggggggg'
    -  ];
    -  doIsValidTest(goog.format.InternationalizedEmailAddress.isValidDomainPartSpec,
    -      valid, invalid);
    -}
    -
    -
    -function testparseListWithAdditionalSeparators() {
    -  assertParsedList('<foo@gmail.com>\u055D <bar@gmail.com>',
    -      ['foo@gmail.com', 'bar@gmail.com'],
    -      'Failed to parse 2 email addresses with U+055D');
    -  assertParsedList('<foo@gmail.com>\u055D <bar@gmail.com>\u055D',
    -      ['foo@gmail.com', 'bar@gmail.com'],
    -      'Failed to parse 2 email addresses with trailing U+055D');
    -
    -  assertParsedList('<foo@gmail.com>\u060C <bar@gmail.com>',
    -      ['foo@gmail.com', 'bar@gmail.com'],
    -      'Failed to parse 2 email addresses with U+060C');
    -  assertParsedList('<foo@gmail.com>\u060C <bar@gmail.com>\u060C',
    -      ['foo@gmail.com', 'bar@gmail.com'],
    -      'Failed to parse 2 email addresses with trailing U+060C');
    -
    -  assertParsedList('<foo@gmail.com>\u1363 <bar@gmail.com>',
    -      ['foo@gmail.com', 'bar@gmail.com'],
    -      'Failed to parse 2 email addresses with U+1363');
    -  assertParsedList('<foo@gmail.com>\u1363 <bar@gmail.com>\u1363',
    -      ['foo@gmail.com', 'bar@gmail.com'],
    -      'Failed to parse 2 email addresses with trailing U+1363');
    -
    -  assertParsedList('<foo@gmail.com>\u1802 <bar@gmail.com>',
    -      ['foo@gmail.com', 'bar@gmail.com'],
    -      'Failed to parse 2 email addresses with U+1802');
    -  assertParsedList('<foo@gmail.com>\u1802 <bar@gmail.com>\u1802',
    -      ['foo@gmail.com', 'bar@gmail.com'],
    -      'Failed to parse 2 email addresses with trailing U+1802');
    -
    -  assertParsedList('<foo@gmail.com>\u1808 <bar@gmail.com>',
    -      ['foo@gmail.com', 'bar@gmail.com'],
    -      'Failed to parse 2 email addresses with U+1808');
    -  assertParsedList('<foo@gmail.com>\u1808 <bar@gmail.com>\u1808',
    -      ['foo@gmail.com', 'bar@gmail.com'],
    -      'Failed to parse 2 email addresses with trailing U+1808');
    -
    -  assertParsedList('<foo@gmail.com>\u2E41 <bar@gmail.com>',
    -      ['foo@gmail.com', 'bar@gmail.com'],
    -      'Failed to parse 2 email addresses with U+2E41');
    -  assertParsedList('<foo@gmail.com>\u2E41 <bar@gmail.com>\u2E41',
    -      ['foo@gmail.com', 'bar@gmail.com'],
    -      'Failed to parse 2 email addresses with trailing U+2E41');
    -
    -  assertParsedList('<foo@gmail.com>\u3001 <bar@gmail.com>',
    -      ['foo@gmail.com', 'bar@gmail.com'],
    -      'Failed to parse 2 email addresses with U+3001');
    -  assertParsedList('<foo@gmail.com>\u3001 <bar@gmail.com>\u3001',
    -      ['foo@gmail.com', 'bar@gmail.com'],
    -      'Failed to parse 2 email addresses with trailing U+3001');
    -
    -  assertParsedList('<foo@gmail.com>\uFF0C <bar@gmail.com>',
    -      ['foo@gmail.com', 'bar@gmail.com'],
    -      'Failed to parse 2 email addresses with U+FF0C');
    -  assertParsedList('<foo@gmail.com>\uFF0C <bar@gmail.com>\uFF0C',
    -      ['foo@gmail.com', 'bar@gmail.com'],
    -      'Failed to parse 2 email addresses with trailing U+FF0C');
    -
    -  assertParsedList('<foo@gmail.com>\u0613 <bar@gmail.com>',
    -      ['foo@gmail.com', 'bar@gmail.com'],
    -      'Failed to parse 2 email addresses with U+0613');
    -  assertParsedList('<foo@gmail.com>\u0613 <bar@gmail.com>\u0613',
    -      ['foo@gmail.com', 'bar@gmail.com'],
    -      'Failed to parse 2 email addresses with trailing U+0613');
    -
    -  assertParsedList('<foo@gmail.com>\u1364 <bar@gmail.com>',
    -      ['foo@gmail.com', 'bar@gmail.com'],
    -      'Failed to parse 2 email addresses with U+1364');
    -  assertParsedList('<foo@gmail.com>\u1364 <bar@gmail.com>\u1364',
    -      ['foo@gmail.com', 'bar@gmail.com'],
    -      'Failed to parse 2 email addresses with trailing U+1364');
    -
    -  assertParsedList('<foo@gmail.com>\uFF1B <bar@gmail.com>',
    -      ['foo@gmail.com', 'bar@gmail.com'],
    -      'Failed to parse 2 email addresses with U+FF1B');
    -  assertParsedList('<foo@gmail.com>\uFF1B <bar@gmail.com>\uFF1B',
    -      ['foo@gmail.com', 'bar@gmail.com'],
    -      'Failed to parse 2 email addresses with trailing U+FF1B');
    -
    -  assertParsedList('<foo@gmail.com>\uFF64 <bar@gmail.com>',
    -      ['foo@gmail.com', 'bar@gmail.com'],
    -      'Failed to parse 2 email addresses with U+FF64');
    -  assertParsedList('<foo@gmail.com>\uFF64 <bar@gmail.com>\uFF64',
    -      ['foo@gmail.com', 'bar@gmail.com'],
    -      'Failed to parse 2 email addresses with trailing U+FF64');
    -
    -  assertParsedList('<foo@gmail.com>\u104A <bar@gmail.com>',
    -      ['foo@gmail.com', 'bar@gmail.com'],
    -      'Failed to parse 2 email addresses with U+104A');
    -  assertParsedList('<foo@gmail.com>\u104A <bar@gmail.com>\u104A',
    -      ['foo@gmail.com', 'bar@gmail.com'],
    -      'Failed to parse 2 email addresses with trailing U+104A');
    -}
    -
    -function testToString() {
    -  var f = function(str) {
    -    return goog.format.InternationalizedEmailAddress.parse(str).toString();
    -  };
    -
    -  // No modification.
    -  assertEquals('JOHN Doe <john@gmail.com>',
    -               f('JOHN Doe <john@gmail.com>'));
    -
    -  // Extra spaces.
    -  assertEquals('JOHN Doe <john@gmail.com>',
    -               f(' JOHN  Doe  <john@gmail.com> '));
    -
    -  // No name.
    -  assertEquals('john@gmail.com', f('<john@gmail.com>'));
    -  assertEquals('john@gmail.com', f('john@gmail.com'));
    -
    -  // No address.
    -  assertEquals('JOHN Doe', f('JOHN Doe <>'));
    -
    -  // Already quoted.
    -  assertEquals('"JOHN, Doe" <john@gmail.com>',
    -               f('"JOHN, Doe" <john@gmail.com>'));
    -
    -  // Needless quotes.
    -  assertEquals('JOHN Doe <john@gmail.com>',
    -               f('"JOHN Doe" <john@gmail.com>'));
    -  // Not quoted-string, but has double quotes.
    -  assertEquals('"JOHN, Doe" <john@gmail.com>',
    -               f('JOHN, "Doe" <john@gmail.com>'));
    -
    -  // No special characters other than quotes.
    -  assertEquals('JOHN Doe <john@gmail.com>',
    -               f('JOHN "Doe" <john@gmail.com>'));
    -
    -  // Escaped quotes are also removed.
    -  assertEquals('"JOHN, Doe" <john@gmail.com>',
    -               f('JOHN, \\"Doe\\" <john@gmail.com>'));
    -
    -  // Characters that require quoting for the display name.
    -  assertEquals('"JOHN, Doe" <john@gmail.com>',
    -               f('JOHN, Doe <john@gmail.com>'));
    -  assertEquals('"JOHN; Doe" <john@gmail.com>',
    -               f('JOHN; Doe <john@gmail.com>'));
    -  assertEquals('"JOHN\u055D Doe" <john@gmail.com>',
    -               f('JOHN\u055D Doe <john@gmail.com>'));
    -  assertEquals('"JOHN\u060C Doe" <john@gmail.com>',
    -               f('JOHN\u060C Doe <john@gmail.com>'));
    -  assertEquals('"JOHN\u1363 Doe" <john@gmail.com>',
    -               f('JOHN\u1363 Doe <john@gmail.com>'));
    -  assertEquals('"JOHN\u1802 Doe" <john@gmail.com>',
    -               f('JOHN\u1802 Doe <john@gmail.com>'));
    -  assertEquals('"JOHN\u1808 Doe" <john@gmail.com>',
    -               f('JOHN\u1808 Doe <john@gmail.com>'));
    -  assertEquals('"JOHN\u2E41 Doe" <john@gmail.com>',
    -               f('JOHN\u2E41 Doe <john@gmail.com>'));
    -  assertEquals('"JOHN\u3001 Doe" <john@gmail.com>',
    -               f('JOHN\u3001 Doe <john@gmail.com>'));
    -  assertEquals('"JOHN\uFF0C Doe" <john@gmail.com>',
    -               f('JOHN\uFF0C Doe <john@gmail.com>'));
    -  assertEquals('"JOHN\u061B Doe" <john@gmail.com>',
    -               f('JOHN\u061B Doe <john@gmail.com>'));
    -  assertEquals('"JOHN\u1364 Doe" <john@gmail.com>',
    -               f('JOHN\u1364 Doe <john@gmail.com>'));
    -  assertEquals('"JOHN\uFF1B Doe" <john@gmail.com>',
    -               f('JOHN\uFF1B Doe <john@gmail.com>'));
    -  assertEquals('"JOHN\uFF64 Doe" <john@gmail.com>',
    -               f('JOHN\uFF64 Doe <john@gmail.com>'));
    -  assertEquals('"JOHN(Johnny) Doe" <john@gmail.com>',
    -               f('JOHN(Johnny) Doe <john@gmail.com>'));
    -  assertEquals('"JOHN[Johnny] Doe" <john@gmail.com>',
    -               f('JOHN[Johnny] Doe <john@gmail.com>'));
    -  assertEquals('"JOHN@work Doe" <john@gmail.com>',
    -               f('JOHN@work Doe <john@gmail.com>'));
    -  assertEquals('"JOHN:theking Doe" <john@gmail.com>',
    -               f('JOHN:theking Doe <john@gmail.com>'));
    -  assertEquals('"JOHN\\\\ Doe" <john@gmail.com>',
    -               f('JOHN\\ Doe <john@gmail.com>'));
    -  assertEquals('"JOHN.com Doe" <john@gmail.com>',
    -               f('JOHN.com Doe <john@gmail.com>'));
    -}
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/format/jsonprettyprinter.js b/src/database/third_party/closure-library/closure/goog/format/jsonprettyprinter.js
    deleted file mode 100644
    index 15e2cd2aafd..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/format/jsonprettyprinter.js
    +++ /dev/null
    @@ -1,414 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Creates a string of a JSON object, properly indented for
    - * display.
    - *
    - */
    -
    -goog.provide('goog.format.JsonPrettyPrinter');
    -goog.provide('goog.format.JsonPrettyPrinter.HtmlDelimiters');
    -goog.provide('goog.format.JsonPrettyPrinter.TextDelimiters');
    -
    -goog.require('goog.json');
    -goog.require('goog.json.Serializer');
    -goog.require('goog.string');
    -goog.require('goog.string.StringBuffer');
    -goog.require('goog.string.format');
    -
    -
    -
    -/**
    - * Formats a JSON object as a string, properly indented for display.  Supports
    - * displaying the string as text or html.  Users can also specify their own
    - * set of delimiters for different environments.  For example, the JSON object:
    - *
    - * <code>{"a": 1, "b": {"c": null, "d": true, "e": [1, 2]}}</code>
    - *
    - * Will be displayed like this:
    - *
    - * <code>{
    - *   "a": 1,
    - *   "b": {
    - *     "c": null,
    - *     "d": true,
    - *     "e": [
    - *       1,
    - *       2
    - *     ]
    - *   }
    - * }</code>
    - * @param {goog.format.JsonPrettyPrinter.TextDelimiters} delimiters Container
    - *     for the various strings to use to delimit objects, arrays, newlines, and
    - *     other pieces of the output.
    - * @constructor
    - */
    -goog.format.JsonPrettyPrinter = function(delimiters) {
    -
    -  /**
    -   * The set of characters to use as delimiters.
    -   * @type {goog.format.JsonPrettyPrinter.TextDelimiters}
    -   * @private
    -   */
    -  this.delimiters_ = delimiters ||
    -      new goog.format.JsonPrettyPrinter.TextDelimiters();
    -
    -  /**
    -   * Used to serialize property names and values.
    -   * @type {goog.json.Serializer}
    -   * @private
    -   */
    -  this.jsonSerializer_ = new goog.json.Serializer();
    -};
    -
    -
    -/**
    - * Formats a JSON object as a string, properly indented for display.
    - * @param {*} json The object to pretty print. It could be a JSON object, a
    - *     string representing a JSON object, or any other type.
    - * @return {string} Returns a string of the JSON object, properly indented for
    - *     display.
    - */
    -goog.format.JsonPrettyPrinter.prototype.format = function(json) {
    -  // If input is undefined, null, or empty, return an empty string.
    -  if (!goog.isDefAndNotNull(json)) {
    -    return '';
    -  }
    -  if (goog.isString(json)) {
    -    if (goog.string.isEmptyOrWhitespace(json)) {
    -      return '';
    -    }
    -    // Try to coerce a string into a JSON object.
    -    json = goog.json.parse(json);
    -  }
    -  var outputBuffer = new goog.string.StringBuffer();
    -  this.printObject_(json, outputBuffer, 0);
    -  return outputBuffer.toString();
    -};
    -
    -
    -/**
    - * Formats a property value based on the type of the propery.
    - * @param {*} val The object to format.
    - * @param {goog.string.StringBuffer} outputBuffer The buffer to write the
    - *     response to.
    - * @param {number} indent The number of spaces to indent each line of the
    - *     output.
    - * @private
    - */
    -goog.format.JsonPrettyPrinter.prototype.printObject_ = function(val,
    -    outputBuffer, indent) {
    -  var typeOf = goog.typeOf(val);
    -  switch (typeOf) {
    -    case 'null':
    -    case 'boolean':
    -    case 'number':
    -    case 'string':
    -      // "null", "boolean", "number" and "string" properties are printed
    -      // directly to the output.
    -      this.printValue_(
    -          /** @type {null|string|boolean|number} */ (val),
    -          typeOf, outputBuffer);
    -      break;
    -    case 'array':
    -      // Example of how an array looks when formatted
    -      // (using the default delimiters):
    -      // [
    -      //   1,
    -      //   2,
    -      //   3
    -      // ]
    -      outputBuffer.append(this.delimiters_.arrayStart);
    -      var i = 0;
    -      // Iterate through the array and format each element.
    -      for (i = 0; i < val.length; i++) {
    -        if (i > 0) {
    -          // There are multiple elements, add a comma to separate them.
    -          outputBuffer.append(this.delimiters_.propertySeparator);
    -        }
    -        outputBuffer.append(this.delimiters_.lineBreak);
    -        this.printSpaces_(indent + this.delimiters_.indent, outputBuffer);
    -        this.printObject_(val[i], outputBuffer,
    -            indent + this.delimiters_.indent);
    -      }
    -      // If there are no properties in this object, don't put a line break
    -      // between the beginning "[" and ending "]", so the output of an empty
    -      // array looks like <code>[]</code>.
    -      if (i > 0) {
    -        outputBuffer.append(this.delimiters_.lineBreak);
    -        this.printSpaces_(indent, outputBuffer);
    -      }
    -      outputBuffer.append(this.delimiters_.arrayEnd);
    -      break;
    -    case 'object':
    -      // Example of how an object looks when formatted
    -      // (using the default delimiters):
    -      // {
    -      //   "a": 1,
    -      //   "b": 2,
    -      //   "c": "3"
    -      // }
    -      outputBuffer.append(this.delimiters_.objectStart);
    -      var propertyCount = 0;
    -      // Iterate through the object and display each property.
    -      for (var name in val) {
    -        if (!val.hasOwnProperty(name)) {
    -          continue;
    -        }
    -        if (propertyCount > 0) {
    -          // There are multiple properties, add a comma to separate them.
    -          outputBuffer.append(this.delimiters_.propertySeparator);
    -        }
    -        outputBuffer.append(this.delimiters_.lineBreak);
    -        this.printSpaces_(indent + this.delimiters_.indent, outputBuffer);
    -        this.printName_(name, outputBuffer);
    -        outputBuffer.append(this.delimiters_.nameValueSeparator,
    -            this.delimiters_.space);
    -        this.printObject_(val[name], outputBuffer,
    -            indent + this.delimiters_.indent);
    -        propertyCount++;
    -      }
    -      // If there are no properties in this object, don't put a line break
    -      // between the beginning "{" and ending "}", so the output of an empty
    -      // object looks like <code>{}</code>.
    -      if (propertyCount > 0) {
    -        outputBuffer.append(this.delimiters_.lineBreak);
    -        this.printSpaces_(indent, outputBuffer);
    -      }
    -      outputBuffer.append(this.delimiters_.objectEnd);
    -      break;
    -    // Other types, such as "function", aren't expected in JSON, and their
    -    // behavior is undefined.  In these cases, just print an empty string to the
    -    // output buffer.  This allows the pretty printer to continue while still
    -    // outputing well-formed JSON.
    -    default:
    -      this.printValue_('', 'unknown', outputBuffer);
    -  }
    -};
    -
    -
    -/**
    - * Prints a property name to the output.
    - * @param {string} name The property name.
    - * @param {goog.string.StringBuffer} outputBuffer The buffer to write the
    - *     response to.
    - * @private
    - */
    -goog.format.JsonPrettyPrinter.prototype.printName_ = function(name,
    -    outputBuffer) {
    -  outputBuffer.append(this.delimiters_.preName,
    -      this.jsonSerializer_.serialize(name), this.delimiters_.postName);
    -};
    -
    -
    -/**
    - * Prints a property name to the output.
    - * @param {string|boolean|number|null} val The property value.
    - * @param {string} typeOf The type of the value.  Used to customize
    - *     value-specific css in the display.  This allows clients to distinguish
    - *     between different types in css.  For example, the client may define two
    - *     classes: "goog-jsonprettyprinter-propertyvalue-string" and
    - *     "goog-jsonprettyprinter-propertyvalue-number" to assign a different color
    - *     to string and number values.
    - * @param {goog.string.StringBuffer} outputBuffer The buffer to write the
    - *     response to.
    - * @private
    - */
    -goog.format.JsonPrettyPrinter.prototype.printValue_ = function(val,
    -    typeOf, outputBuffer) {
    -  outputBuffer.append(goog.string.format(this.delimiters_.preValue, typeOf),
    -      this.jsonSerializer_.serialize(val),
    -      goog.string.format(this.delimiters_.postValue, typeOf));
    -};
    -
    -
    -/**
    - * Print a number of space characters to the output.
    - * @param {number} indent The number of spaces to indent the line.
    - * @param {goog.string.StringBuffer} outputBuffer The buffer to write the
    - *     response to.
    - * @private
    - */
    -goog.format.JsonPrettyPrinter.prototype.printSpaces_ = function(indent,
    -    outputBuffer) {
    -  outputBuffer.append(goog.string.repeat(this.delimiters_.space, indent));
    -};
    -
    -
    -
    -/**
    - * A container for the delimiting characters used to display the JSON string
    - * to a text display.  Each delimiter is a publicly accessible property of
    - * the object, which makes it easy to tweak delimiters to specific environments.
    - * @constructor
    - */
    -goog.format.JsonPrettyPrinter.TextDelimiters = function() {
    -};
    -
    -
    -/**
    - * Represents a space character in the output.  Used to indent properties a
    - * certain number of spaces, and to separate property names from property
    - * values.
    - * @type {string}
    - */
    -goog.format.JsonPrettyPrinter.TextDelimiters.prototype.space = ' ';
    -
    -
    -/**
    - * Represents a newline character in the output.  Used to begin a new line.
    - * @type {string}
    - */
    -goog.format.JsonPrettyPrinter.TextDelimiters.prototype.lineBreak = '\n';
    -
    -
    -/**
    - * Represents the start of an object in the output.
    - * @type {string}
    - */
    -goog.format.JsonPrettyPrinter.TextDelimiters.prototype.objectStart = '{';
    -
    -
    -/**
    - * Represents the end of an object in the output.
    - * @type {string}
    - */
    -goog.format.JsonPrettyPrinter.TextDelimiters.prototype.objectEnd = '}';
    -
    -
    -/**
    - * Represents the start of an array in the output.
    - * @type {string}
    - */
    -goog.format.JsonPrettyPrinter.TextDelimiters.prototype.arrayStart = '[';
    -
    -
    -/**
    - * Represents the end of an array in the output.
    - * @type {string}
    - */
    -goog.format.JsonPrettyPrinter.TextDelimiters.prototype.arrayEnd = ']';
    -
    -
    -/**
    - * Represents the string used to separate properties in the output.
    - * @type {string}
    - */
    -goog.format.JsonPrettyPrinter.TextDelimiters.prototype.propertySeparator = ',';
    -
    -
    -/**
    - * Represents the string used to separate property names from property values in
    - * the output.
    - * @type {string}
    - */
    -goog.format.JsonPrettyPrinter.TextDelimiters.prototype.nameValueSeparator = ':';
    -
    -
    -/**
    - * A string that's placed before a property name in the output.  Useful for
    - * wrapping a property name in an html tag.
    - * @type {string}
    - */
    -goog.format.JsonPrettyPrinter.TextDelimiters.prototype.preName = '';
    -
    -
    -/**
    - * A string that's placed after a property name in the output.  Useful for
    - * wrapping a property name in an html tag.
    - * @type {string}
    - */
    -goog.format.JsonPrettyPrinter.TextDelimiters.prototype.postName = '';
    -
    -
    -/**
    - * A string that's placed before a property value in the output.  Useful for
    - * wrapping a property value in an html tag.
    - * @type {string}
    - */
    -goog.format.JsonPrettyPrinter.TextDelimiters.prototype.preValue = '';
    -
    -
    -/**
    - * A string that's placed after a property value in the output.  Useful for
    - * wrapping a property value in an html tag.
    - * @type {string}
    - */
    -goog.format.JsonPrettyPrinter.TextDelimiters.prototype.postValue = '';
    -
    -
    -/**
    - * Represents the number of spaces to indent each sub-property of the JSON.
    - * @type {number}
    - */
    -goog.format.JsonPrettyPrinter.TextDelimiters.prototype.indent = 2;
    -
    -
    -
    -/**
    - * A container for the delimiting characters used to display the JSON string
    - * to an HTML <code>&lt;pre&gt;</code> or <code>&lt;code&gt;</code> element.
    - * @constructor
    - * @extends {goog.format.JsonPrettyPrinter.TextDelimiters}
    - * @final
    - */
    -goog.format.JsonPrettyPrinter.HtmlDelimiters = function() {
    -  goog.format.JsonPrettyPrinter.TextDelimiters.call(this);
    -};
    -goog.inherits(goog.format.JsonPrettyPrinter.HtmlDelimiters,
    -    goog.format.JsonPrettyPrinter.TextDelimiters);
    -
    -
    -/**
    - * A <code>span</code> tag thats placed before a property name.  Used to style
    - * property names with CSS.
    - * @type {string}
    - * @override
    - */
    -goog.format.JsonPrettyPrinter.HtmlDelimiters.prototype.preName =
    -    '<span class="' +
    -    goog.getCssName('goog-jsonprettyprinter-propertyname') +
    -    '">';
    -
    -
    -/**
    - * A closing <code>span</code> tag that's placed after a property name.
    - * @type {string}
    - * @override
    - */
    -goog.format.JsonPrettyPrinter.HtmlDelimiters.prototype.postName = '</span>';
    -
    -
    -/**
    - * A <code>span</code> tag thats placed before a property value.  Used to style
    - * property value with CSS.  The span tag's class is in the format
    - * goog-jsonprettyprinter-propertyvalue-{TYPE}, where {TYPE} is the JavaScript
    - * type of the object (the {TYPE} parameter is obtained from goog.typeOf).  This
    - * can be used to style different value types.
    - * @type {string}
    - * @override
    - */
    -goog.format.JsonPrettyPrinter.HtmlDelimiters.prototype.preValue =
    -    '<span class="' +
    -    goog.getCssName('goog-jsonprettyprinter-propertyvalue') +
    -    '-%s">';
    -
    -
    -/**
    - * A closing <code>span</code> tag that's placed after a property value.
    - * @type {string}
    - * @override
    - */
    -goog.format.JsonPrettyPrinter.HtmlDelimiters.prototype.postValue = '</span>';
    diff --git a/src/database/third_party/closure-library/closure/goog/format/jsonprettyprinter_test.html b/src/database/third_party/closure-library/closure/goog/format/jsonprettyprinter_test.html
    deleted file mode 100644
    index 4b2d6667e57..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/format/jsonprettyprinter_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.format.JsonPrettyPrinter
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.format.JsonPrettyPrinterTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/format/jsonprettyprinter_test.js b/src/database/third_party/closure-library/closure/goog/format/jsonprettyprinter_test.js
    deleted file mode 100644
    index ae308cc9bb0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/format/jsonprettyprinter_test.js
    +++ /dev/null
    @@ -1,109 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.format.JsonPrettyPrinterTest');
    -goog.setTestOnly('goog.format.JsonPrettyPrinterTest');
    -
    -goog.require('goog.format.JsonPrettyPrinter');
    -goog.require('goog.testing.jsunit');
    -
    -var formatter;
    -
    -
    -function setUp() {
    -  formatter = new goog.format.JsonPrettyPrinter();
    -}
    -
    -
    -function testUndefined() {
    -  assertEquals('', formatter.format());
    -}
    -
    -
    -function testNull() {
    -  assertEquals('', formatter.format(null));
    -}
    -
    -
    -function testBoolean() {
    -  assertEquals('true', formatter.format(true));
    -}
    -
    -
    -function testNumber() {
    -  assertEquals('1', formatter.format(1));
    -}
    -
    -
    -function testEmptyString() {
    -  assertEquals('', formatter.format(''));
    -}
    -
    -
    -function testWhitespaceString() {
    -  assertEquals('', formatter.format('   '));
    -}
    -
    -
    -function testString() {
    -  assertEquals('{}', formatter.format('{}'));
    -}
    -
    -
    -function testEmptyArray() {
    -  assertEquals('[]', formatter.format([]));
    -}
    -
    -
    -function testArrayOneElement() {
    -  assertEquals('[\n  1\n]', formatter.format([1]));
    -}
    -
    -
    -function testArrayMultipleElements() {
    -  assertEquals('[\n  1,\n  2,\n  3\n]', formatter.format([1, 2, 3]));
    -}
    -
    -
    -function testFunction() {
    -  assertEquals('{\n  "a": "1",\n  "b": ""\n}',
    -      formatter.format({'a': '1', 'b': function() { return null; }}));
    -}
    -
    -
    -function testObject() {
    -  assertEquals('{}', formatter.format({}));
    -}
    -
    -
    -function testObjectMultipleProperties() {
    -  assertEquals('{\n  "a": null,\n  "b": true,\n  "c": 1,\n  "d": "d",\n  "e":' +
    -      ' [\n    1,\n    2,\n    3\n  ],\n  "f": {\n    "g": 1,\n    "h": "h"\n' +
    -      '  }\n}',
    -      formatter.format({'a': null, 'b': true, 'c': 1, 'd': 'd', 'e': [1, 2, 3],
    -        'f': {'g': 1, 'h': 'h'}}));
    -}
    -
    -
    -function testHtmlDelimiters() {
    -  var htmlFormatter = new goog.format.JsonPrettyPrinter(
    -      new goog.format.JsonPrettyPrinter.HtmlDelimiters());
    -  assertEquals('{\n  <span class="goog-jsonprettyprinter-propertyname">"a"</s' +
    -      'pan>: <span class="goog-jsonprettyprinter-propertyvalue-number">1</spa' +
    -      'n>,\n  <span class="goog-jsonprettyprinter-propertyname">"b"</span>: <' +
    -      'span class="goog-jsonprettyprinter-propertyvalue-string">"2"</span>,\n' +
    -      '  <span class="goog-jsonprettyprinter-propertyname">"c"</span>: <span ' +
    -      'class="goog-jsonprettyprinter-propertyvalue-unknown">""</span>\n}',
    -      htmlFormatter.format({'a': 1, 'b': '2', 'c': function() {}}));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/fs/entry.js b/src/database/third_party/closure-library/closure/goog/fs/entry.js
    deleted file mode 100644
    index 8143daa28d3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fs/entry.js
    +++ /dev/null
    @@ -1,272 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Wrappers for HTML5 Entry objects. These are all in the same
    - * file to avoid circular dependency issues.
    - *
    - * When adding or modifying functionality in this namespace, be sure to update
    - * the mock counterparts in goog.testing.fs.
    - *
    - */
    -goog.provide('goog.fs.DirectoryEntry');
    -goog.provide('goog.fs.DirectoryEntry.Behavior');
    -goog.provide('goog.fs.Entry');
    -goog.provide('goog.fs.FileEntry');
    -
    -
    -
    -/**
    - * The interface for entries in the filesystem.
    - * @interface
    - */
    -goog.fs.Entry = function() {};
    -
    -
    -/**
    - * @return {boolean} Whether or not this entry is a file.
    - */
    -goog.fs.Entry.prototype.isFile = function() {};
    -
    -
    -/**
    - * @return {boolean} Whether or not this entry is a directory.
    - */
    -goog.fs.Entry.prototype.isDirectory = function() {};
    -
    -
    -/**
    - * @return {string} The name of this entry.
    - */
    -goog.fs.Entry.prototype.getName = function() {};
    -
    -
    -/**
    - * @return {string} The full path to this entry.
    - */
    -goog.fs.Entry.prototype.getFullPath = function() {};
    -
    -
    -/**
    - * @return {!goog.fs.FileSystem} The filesystem backing this entry.
    - */
    -goog.fs.Entry.prototype.getFileSystem = function() {};
    -
    -
    -/**
    - * Retrieves the last modified date for this entry.
    - *
    - * @return {!goog.async.Deferred} The deferred Date for this entry. If an error
    - *     occurs, the errback is called with a {@link goog.fs.Error}.
    - */
    -goog.fs.Entry.prototype.getLastModified = function() {};
    -
    -
    -/**
    - * Retrieves the metadata for this entry.
    - *
    - * @return {!goog.async.Deferred} The deferred Metadata for this entry. If an
    - *     error occurs, the errback is called with a {@link goog.fs.Error}.
    - */
    -goog.fs.Entry.prototype.getMetadata = function() {};
    -
    -
    -/**
    - * Move this entry to a new location.
    - *
    - * @param {!goog.fs.DirectoryEntry} parent The new parent directory.
    - * @param {string=} opt_newName The new name of the entry. If omitted, the entry
    - *     retains its original name.
    - * @return {!goog.async.Deferred} The deferred {@link goog.fs.FileEntry} or
    - *     {@link goog.fs.DirectoryEntry} for the new entry. If an error occurs, the
    - *     errback is called with a {@link goog.fs.Error}.
    - */
    -goog.fs.Entry.prototype.moveTo = function(parent, opt_newName) {};
    -
    -
    -/**
    - * Copy this entry to a new location.
    - *
    - * @param {!goog.fs.DirectoryEntry} parent The new parent directory.
    - * @param {string=} opt_newName The name of the new entry. If omitted, the new
    - *     entry has the same name as the original.
    - * @return {!goog.async.Deferred} The deferred {@link goog.fs.FileEntry} or
    - *     {@link goog.fs.DirectoryEntry} for the new entry. If an error occurs, the
    - *     errback is called with a {@link goog.fs.Error}.
    - */
    -goog.fs.Entry.prototype.copyTo = function(parent, opt_newName) {};
    -
    -
    -/**
    - * Wrap an HTML5 entry object in an appropriate subclass instance.
    - *
    - * @param {!Entry} entry The underlying Entry object.
    - * @return {!goog.fs.Entry} The appropriate subclass wrapper.
    - * @protected
    - */
    -goog.fs.Entry.prototype.wrapEntry = function(entry) {};
    -
    -
    -/**
    - * Get the URL for this file.
    - *
    - * @param {string=} opt_mimeType The MIME type that will be served for the URL.
    - * @return {string} The URL.
    - */
    -goog.fs.Entry.prototype.toUrl = function(opt_mimeType) {};
    -
    -
    -/**
    - * Get the URI for this file.
    - *
    - * @deprecated Use {@link #toUrl} instead.
    - * @param {string=} opt_mimeType The MIME type that will be served for the URI.
    - * @return {string} The URI.
    - */
    -goog.fs.Entry.prototype.toUri = function(opt_mimeType) {};
    -
    -
    -/**
    - * Remove this entry.
    - *
    - * @return {!goog.async.Deferred} A deferred object. If the removal succeeds,
    - *     the callback is called with true. If an error occurs, the errback is
    - *     called a {@link goog.fs.Error}.
    - */
    -goog.fs.Entry.prototype.remove = function() {};
    -
    -
    -/**
    - * Gets the parent directory.
    - *
    - * @return {!goog.async.Deferred} The deferred {@link goog.fs.DirectoryEntry}.
    - *     If an error occurs, the errback is called with a {@link goog.fs.Error}.
    - */
    -goog.fs.Entry.prototype.getParent = function() {};
    -
    -
    -
    -/**
    - * A directory in a local FileSystem.
    - *
    - * @interface
    - * @extends {goog.fs.Entry}
    - */
    -goog.fs.DirectoryEntry = function() {};
    -
    -
    -/**
    - * Behaviors for getting files and directories.
    - * @enum {number}
    - */
    -goog.fs.DirectoryEntry.Behavior = {
    -  /**
    -   * Get the file if it exists, error out if it doesn't.
    -   */
    -  DEFAULT: 1,
    -  /**
    -   * Get the file if it exists, create it if it doesn't.
    -   */
    -  CREATE: 2,
    -  /**
    -   * Error out if the file exists, create it if it doesn't.
    -   */
    -  CREATE_EXCLUSIVE: 3
    -};
    -
    -
    -/**
    - * Get a file in the directory.
    - *
    - * @param {string} path The path to the file, relative to this directory.
    - * @param {goog.fs.DirectoryEntry.Behavior=} opt_behavior The behavior for
    - *     handling an existing file, or the lack thereof.
    - * @return {!goog.async.Deferred} The deferred {@link goog.fs.FileEntry}. If an
    - *     error occurs, the errback is called with a {@link goog.fs.Error}.
    - */
    -goog.fs.DirectoryEntry.prototype.getFile = function(path, opt_behavior) {};
    -
    -
    -/**
    - * Get a directory within this directory.
    - *
    - * @param {string} path The path to the directory, relative to this directory.
    - * @param {goog.fs.DirectoryEntry.Behavior=} opt_behavior The behavior for
    - *     handling an existing directory, or the lack thereof.
    - * @return {!goog.async.Deferred} The deferred {@link goog.fs.DirectoryEntry}.
    - *     If an error occurs, the errback is called a {@link goog.fs.Error}.
    - */
    -goog.fs.DirectoryEntry.prototype.getDirectory = function(path, opt_behavior) {};
    -
    -
    -/**
    - * Opens the directory for the specified path, creating the directory and any
    - * intermediate directories as necessary.
    - *
    - * @param {string} path The directory path to create. May be absolute or
    - *     relative to the current directory. The parent directory ".." and current
    - *     directory "." are supported.
    - * @return {!goog.async.Deferred} A deferred {@link goog.fs.DirectoryEntry} for
    - *     the requested path. If an error occurs, the errback is called with a
    - *     {@link goog.fs.Error}.
    - */
    -goog.fs.DirectoryEntry.prototype.createPath = function(path) {};
    -
    -
    -/**
    - * Gets a list of all entries in this directory.
    - *
    - * @return {!goog.async.Deferred} The deferred list of {@link goog.fs.Entry}
    - *     results. If an error occurs, the errback is called with a
    - *     {@link goog.fs.Error}.
    - */
    -goog.fs.DirectoryEntry.prototype.listDirectory = function() {};
    -
    -
    -/**
    - * Removes this directory and all its contents.
    - *
    - * @return {!goog.async.Deferred} A deferred object. If the removal succeeds,
    - *     the callback is called with true. If an error occurs, the errback is
    - *     called a {@link goog.fs.Error}.
    - */
    -goog.fs.DirectoryEntry.prototype.removeRecursively = function() {};
    -
    -
    -
    -/**
    - * A file in a local filesystem.
    - *
    - * @interface
    - * @extends {goog.fs.Entry}
    - */
    -goog.fs.FileEntry = function() {};
    -
    -
    -/**
    - * Create a writer for writing to the file.
    - *
    - * @return {!goog.async.Deferred<!goog.fs.FileWriter>} If an error occurs, the
    - *     errback is called with a {@link goog.fs.Error}.
    - */
    -goog.fs.FileEntry.prototype.createWriter = function() {};
    -
    -
    -/**
    - * Get the file contents as a File blob.
    - *
    - * @return {!goog.async.Deferred<!File>} If an error occurs, the errback is
    - *     called with a {@link goog.fs.Error}.
    - */
    -goog.fs.FileEntry.prototype.file = function() {};
    diff --git a/src/database/third_party/closure-library/closure/goog/fs/entryimpl.js b/src/database/third_party/closure-library/closure/goog/fs/entryimpl.js
    deleted file mode 100644
    index a4cbe7a41b2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fs/entryimpl.js
    +++ /dev/null
    @@ -1,404 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Concrete implementations of the
    - *     goog.fs.DirectoryEntry, and goog.fs.FileEntry interfaces.
    - */
    -goog.provide('goog.fs.DirectoryEntryImpl');
    -goog.provide('goog.fs.EntryImpl');
    -goog.provide('goog.fs.FileEntryImpl');
    -
    -goog.require('goog.array');
    -goog.require('goog.async.Deferred');
    -goog.require('goog.fs.DirectoryEntry');
    -goog.require('goog.fs.Entry');
    -goog.require('goog.fs.Error');
    -goog.require('goog.fs.FileEntry');
    -goog.require('goog.fs.FileWriter');
    -goog.require('goog.functions');
    -goog.require('goog.string');
    -
    -
    -
    -/**
    - * Base class for concrete implementations of goog.fs.Entry.
    - * @param {!goog.fs.FileSystem} fs The wrapped filesystem.
    - * @param {!Entry} entry The underlying Entry object.
    - * @constructor
    - * @implements {goog.fs.Entry}
    - */
    -goog.fs.EntryImpl = function(fs, entry) {
    -  /**
    -   * The wrapped filesystem.
    -   *
    -   * @type {!goog.fs.FileSystem}
    -   * @private
    -   */
    -  this.fs_ = fs;
    -
    -  /**
    -   * The underlying Entry object.
    -   *
    -   * @type {!Entry}
    -   * @private
    -   */
    -  this.entry_ = entry;
    -};
    -
    -
    -/** @override */
    -goog.fs.EntryImpl.prototype.isFile = function() {
    -  return this.entry_.isFile;
    -};
    -
    -
    -/** @override */
    -goog.fs.EntryImpl.prototype.isDirectory = function() {
    -  return this.entry_.isDirectory;
    -};
    -
    -
    -/** @override */
    -goog.fs.EntryImpl.prototype.getName = function() {
    -  return this.entry_.name;
    -};
    -
    -
    -/** @override */
    -goog.fs.EntryImpl.prototype.getFullPath = function() {
    -  return this.entry_.fullPath;
    -};
    -
    -
    -/** @override */
    -goog.fs.EntryImpl.prototype.getFileSystem = function() {
    -  return this.fs_;
    -};
    -
    -
    -/** @override */
    -goog.fs.EntryImpl.prototype.getLastModified = function() {
    -  return this.getMetadata().addCallback(function(metadata) {
    -    return metadata.modificationTime;
    -  });
    -};
    -
    -
    -/** @override */
    -goog.fs.EntryImpl.prototype.getMetadata = function() {
    -  var d = new goog.async.Deferred();
    -
    -  this.entry_.getMetadata(
    -      function(metadata) { d.callback(metadata); },
    -      goog.bind(function(err) {
    -        var msg = 'retrieving metadata for ' + this.getFullPath();
    -        d.errback(new goog.fs.Error(err, msg));
    -      }, this));
    -  return d;
    -};
    -
    -
    -/** @override */
    -goog.fs.EntryImpl.prototype.moveTo = function(parent, opt_newName) {
    -  var d = new goog.async.Deferred();
    -  this.entry_.moveTo(
    -      parent.dir_, opt_newName,
    -      goog.bind(function(entry) { d.callback(this.wrapEntry(entry)); }, this),
    -      goog.bind(function(err) {
    -        var msg = 'moving ' + this.getFullPath() + ' into ' +
    -            parent.getFullPath() +
    -            (opt_newName ? ', renaming to ' + opt_newName : '');
    -        d.errback(new goog.fs.Error(err, msg));
    -      }, this));
    -  return d;
    -};
    -
    -
    -/** @override */
    -goog.fs.EntryImpl.prototype.copyTo = function(parent, opt_newName) {
    -  var d = new goog.async.Deferred();
    -  this.entry_.copyTo(
    -      parent.dir_, opt_newName,
    -      goog.bind(function(entry) { d.callback(this.wrapEntry(entry)); }, this),
    -      goog.bind(function(err) {
    -        var msg = 'copying ' + this.getFullPath() + ' into ' +
    -            parent.getFullPath() +
    -            (opt_newName ? ', renaming to ' + opt_newName : '');
    -        d.errback(new goog.fs.Error(err, msg));
    -      }, this));
    -  return d;
    -};
    -
    -
    -/** @override */
    -goog.fs.EntryImpl.prototype.wrapEntry = function(entry) {
    -  return entry.isFile ?
    -      new goog.fs.FileEntryImpl(this.fs_, /** @type {!FileEntry} */ (entry)) :
    -      new goog.fs.DirectoryEntryImpl(
    -          this.fs_, /** @type {!DirectoryEntry} */ (entry));
    -};
    -
    -
    -/** @override */
    -goog.fs.EntryImpl.prototype.toUrl = function(opt_mimeType) {
    -  return this.entry_.toURL(opt_mimeType);
    -};
    -
    -
    -/** @override */
    -goog.fs.EntryImpl.prototype.toUri = goog.fs.EntryImpl.prototype.toUrl;
    -
    -
    -/** @override */
    -goog.fs.EntryImpl.prototype.remove = function() {
    -  var d = new goog.async.Deferred();
    -  this.entry_.remove(
    -      goog.bind(d.callback, d, true /* result */),
    -      goog.bind(function(err) {
    -        var msg = 'removing ' + this.getFullPath();
    -        d.errback(new goog.fs.Error(err, msg));
    -      }, this));
    -  return d;
    -};
    -
    -
    -/** @override */
    -goog.fs.EntryImpl.prototype.getParent = function() {
    -  var d = new goog.async.Deferred();
    -  this.entry_.getParent(
    -      goog.bind(function(parent) {
    -        d.callback(new goog.fs.DirectoryEntryImpl(this.fs_, parent));
    -      }, this),
    -      goog.bind(function(err) {
    -        var msg = 'getting parent of ' + this.getFullPath();
    -        d.errback(new goog.fs.Error(err, msg));
    -      }, this));
    -  return d;
    -};
    -
    -
    -
    -/**
    - * A directory in a local FileSystem.
    - *
    - * This should not be instantiated directly. Instead, it should be accessed via
    - * {@link goog.fs.FileSystem#getRoot} or
    - * {@link goog.fs.DirectoryEntry#getDirectoryEntry}.
    - *
    - * @param {!goog.fs.FileSystem} fs The wrapped filesystem.
    - * @param {!DirectoryEntry} dir The underlying DirectoryEntry object.
    - * @constructor
    - * @extends {goog.fs.EntryImpl}
    - * @implements {goog.fs.DirectoryEntry}
    - * @final
    - */
    -goog.fs.DirectoryEntryImpl = function(fs, dir) {
    -  goog.fs.DirectoryEntryImpl.base(this, 'constructor', fs, dir);
    -
    -  /**
    -   * The underlying DirectoryEntry object.
    -   *
    -   * @type {!DirectoryEntry}
    -   * @private
    -   */
    -  this.dir_ = dir;
    -};
    -goog.inherits(goog.fs.DirectoryEntryImpl, goog.fs.EntryImpl);
    -
    -
    -/** @override */
    -goog.fs.DirectoryEntryImpl.prototype.getFile = function(path, opt_behavior) {
    -  var d = new goog.async.Deferred();
    -  this.dir_.getFile(
    -      path, this.getOptions_(opt_behavior),
    -      goog.bind(function(entry) {
    -        d.callback(new goog.fs.FileEntryImpl(this.fs_, entry));
    -      }, this),
    -      goog.bind(function(err) {
    -        var msg = 'loading file ' + path + ' from ' + this.getFullPath();
    -        d.errback(new goog.fs.Error(err, msg));
    -      }, this));
    -  return d;
    -};
    -
    -
    -/** @override */
    -goog.fs.DirectoryEntryImpl.prototype.getDirectory =
    -    function(path, opt_behavior) {
    -  var d = new goog.async.Deferred();
    -  this.dir_.getDirectory(
    -      path, this.getOptions_(opt_behavior),
    -      goog.bind(function(entry) {
    -        d.callback(new goog.fs.DirectoryEntryImpl(this.fs_, entry));
    -      }, this),
    -      goog.bind(function(err) {
    -        var msg = 'loading directory ' + path + ' from ' + this.getFullPath();
    -        d.errback(new goog.fs.Error(err, msg));
    -      }, this));
    -  return d;
    -};
    -
    -
    -/** @override */
    -goog.fs.DirectoryEntryImpl.prototype.createPath = function(path) {
    -  // If the path begins at the root, reinvoke createPath on the root directory.
    -  if (goog.string.startsWith(path, '/')) {
    -    var root = this.getFileSystem().getRoot();
    -    if (this.getFullPath() != root.getFullPath()) {
    -      return root.createPath(path);
    -    }
    -  }
    -
    -  // Filter out any empty path components caused by '//' or a leading slash.
    -  var parts = goog.array.filter(path.split('/'), goog.functions.identity);
    -
    -  /**
    -   * @param {goog.fs.DirectoryEntryImpl} dir
    -   * @return {!goog.async.Deferred}
    -   */
    -  function getNextDirectory(dir) {
    -    if (!parts.length) {
    -      return goog.async.Deferred.succeed(dir);
    -    }
    -
    -    var def;
    -    var nextDir = parts.shift();
    -
    -    if (nextDir == '..') {
    -      def = dir.getParent();
    -    } else if (nextDir == '.') {
    -      def = goog.async.Deferred.succeed(dir);
    -    } else {
    -      def = dir.getDirectory(nextDir, goog.fs.DirectoryEntry.Behavior.CREATE);
    -    }
    -    return def.addCallback(getNextDirectory);
    -  }
    -
    -  return getNextDirectory(this);
    -};
    -
    -
    -/** @override */
    -goog.fs.DirectoryEntryImpl.prototype.listDirectory = function() {
    -  var d = new goog.async.Deferred();
    -  var reader = this.dir_.createReader();
    -  var results = [];
    -
    -  var errorCallback = goog.bind(function(err) {
    -    var msg = 'listing directory ' + this.getFullPath();
    -    d.errback(new goog.fs.Error(err, msg));
    -  }, this);
    -
    -  var successCallback = goog.bind(function(entries) {
    -    if (entries.length) {
    -      for (var i = 0, entry; entry = entries[i]; i++) {
    -        results.push(this.wrapEntry(entry));
    -      }
    -      reader.readEntries(successCallback, errorCallback);
    -    } else {
    -      d.callback(results);
    -    }
    -  }, this);
    -
    -  reader.readEntries(successCallback, errorCallback);
    -  return d;
    -};
    -
    -
    -/** @override */
    -goog.fs.DirectoryEntryImpl.prototype.removeRecursively = function() {
    -  var d = new goog.async.Deferred();
    -  this.dir_.removeRecursively(
    -      goog.bind(d.callback, d, true /* result */),
    -      goog.bind(function(err) {
    -        var msg = 'removing ' + this.getFullPath() + ' recursively';
    -        d.errback(new goog.fs.Error(err, msg));
    -      }, this));
    -  return d;
    -};
    -
    -
    -/**
    - * Converts a value in the Behavior enum into an options object expected by the
    - * File API.
    - *
    - * @param {goog.fs.DirectoryEntry.Behavior=} opt_behavior The behavior for
    - *     existing files.
    - * @return {!Object<boolean>} The options object expected by the File API.
    - * @private
    - */
    -goog.fs.DirectoryEntryImpl.prototype.getOptions_ = function(opt_behavior) {
    -  if (opt_behavior == goog.fs.DirectoryEntry.Behavior.CREATE) {
    -    return {'create': true};
    -  } else if (opt_behavior == goog.fs.DirectoryEntry.Behavior.CREATE_EXCLUSIVE) {
    -    return {'create': true, 'exclusive': true};
    -  } else {
    -    return {};
    -  }
    -};
    -
    -
    -
    -/**
    - * A file in a local filesystem.
    - *
    - * This should not be instantiated directly. Instead, it should be accessed via
    - * {@link goog.fs.DirectoryEntry#getFile}.
    - *
    - * @param {!goog.fs.FileSystem} fs The wrapped filesystem.
    - * @param {!FileEntry} file The underlying FileEntry object.
    - * @constructor
    - * @extends {goog.fs.EntryImpl}
    - * @implements {goog.fs.FileEntry}
    - * @final
    - */
    -goog.fs.FileEntryImpl = function(fs, file) {
    -  goog.fs.FileEntryImpl.base(this, 'constructor', fs, file);
    -
    -  /**
    -   * The underlying FileEntry object.
    -   *
    -   * @type {!FileEntry}
    -   * @private
    -   */
    -  this.file_ = file;
    -};
    -goog.inherits(goog.fs.FileEntryImpl, goog.fs.EntryImpl);
    -
    -
    -/** @override */
    -goog.fs.FileEntryImpl.prototype.createWriter = function() {
    -  var d = new goog.async.Deferred();
    -  this.file_.createWriter(
    -      function(w) { d.callback(new goog.fs.FileWriter(w)); },
    -      goog.bind(function(err) {
    -        var msg = 'creating writer for ' + this.getFullPath();
    -        d.errback(new goog.fs.Error(err, msg));
    -      }, this));
    -  return d;
    -};
    -
    -
    -/** @override */
    -goog.fs.FileEntryImpl.prototype.file = function() {
    -  var d = new goog.async.Deferred();
    -  this.file_.file(
    -      function(f) { d.callback(f); },
    -      goog.bind(function(err) {
    -        var msg = 'getting file for ' + this.getFullPath();
    -        d.errback(new goog.fs.Error(err, msg));
    -      }, this));
    -  return d;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/fs/error.js b/src/database/third_party/closure-library/closure/goog/fs/error.js
    deleted file mode 100644
    index 3a54f28084e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fs/error.js
    +++ /dev/null
    @@ -1,181 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A wrapper for the HTML5 FileError object.
    - *
    - */
    -
    -goog.provide('goog.fs.Error');
    -goog.provide('goog.fs.Error.ErrorCode');
    -
    -goog.require('goog.debug.Error');
    -goog.require('goog.object');
    -goog.require('goog.string');
    -
    -
    -
    -/**
    - * A filesystem error. Since the filesystem API is asynchronous, stack traces
    - * are less useful for identifying where errors come from, so this includes a
    - * large amount of metadata in the message.
    - *
    - * @param {!DOMError} error
    - * @param {string} action The action being undertaken when the error was raised.
    - * @constructor
    - * @extends {goog.debug.Error}
    - * @final
    - */
    -goog.fs.Error = function(error, action) {
    -  /** @type {string} */
    -  this.name;
    -
    -  /**
    -   * @type {goog.fs.Error.ErrorCode}
    -   * @deprecated Use the 'name' or 'message' field instead.
    -   */
    -  this.code;
    -
    -  if (goog.isDef(error.name)) {
    -    this.name = error.name;
    -    // TODO(user): Remove warning suppression after JSCompiler stops
    -    // firing a spurious warning here.
    -    /** @suppress {deprecated} */
    -    this.code = goog.fs.Error.getCodeFromName_(error.name);
    -  } else {
    -    this.code = error.code;
    -    this.name = goog.fs.Error.getNameFromCode_(error.code);
    -  }
    -  goog.fs.Error.base(this, 'constructor',
    -      goog.string.subs('%s %s', this.name, action));
    -};
    -goog.inherits(goog.fs.Error, goog.debug.Error);
    -
    -
    -/**
    - * Names of errors that may be thrown by the File API, the File System API, or
    - * the File Writer API.
    - *
    - * @see http://dev.w3.org/2006/webapi/FileAPI/#ErrorAndException
    - * @see http://www.w3.org/TR/file-system-api/#definitions
    - * @see http://dev.w3.org/2009/dap/file-system/file-writer.html#definitions
    - * @enum {string}
    - */
    -goog.fs.Error.ErrorName = {
    -  ABORT: 'AbortError',
    -  ENCODING: 'EncodingError',
    -  INVALID_MODIFICATION: 'InvalidModificationError',
    -  INVALID_STATE: 'InvalidStateError',
    -  NOT_FOUND: 'NotFoundError',
    -  NOT_READABLE: 'NotReadableError',
    -  NO_MODIFICATION_ALLOWED: 'NoModificationAllowedError',
    -  PATH_EXISTS: 'PathExistsError',
    -  QUOTA_EXCEEDED: 'QuotaExceededError',
    -  SECURITY: 'SecurityError',
    -  SYNTAX: 'SyntaxError',
    -  TYPE_MISMATCH: 'TypeMismatchError'
    -};
    -
    -
    -/**
    - * Error codes for file errors.
    - * @see http://www.w3.org/TR/file-system-api/#idl-def-FileException
    - *
    - * @enum {number}
    - * @deprecated Use the 'name' or 'message' attribute instead.
    - */
    -goog.fs.Error.ErrorCode = {
    -  NOT_FOUND: 1,
    -  SECURITY: 2,
    -  ABORT: 3,
    -  NOT_READABLE: 4,
    -  ENCODING: 5,
    -  NO_MODIFICATION_ALLOWED: 6,
    -  INVALID_STATE: 7,
    -  SYNTAX: 8,
    -  INVALID_MODIFICATION: 9,
    -  QUOTA_EXCEEDED: 10,
    -  TYPE_MISMATCH: 11,
    -  PATH_EXISTS: 12
    -};
    -
    -
    -/**
    - * @param {goog.fs.Error.ErrorCode} code
    - * @return {string} name
    - * @private
    - */
    -goog.fs.Error.getNameFromCode_ = function(code) {
    -  var name = goog.object.findKey(goog.fs.Error.NameToCodeMap_, function(c) {
    -    return code == c;
    -  });
    -  if (!goog.isDef(name)) {
    -    throw new Error('Invalid code: ' + code);
    -  }
    -  return name;
    -};
    -
    -
    -/**
    - * Returns the code that corresponds to the given name.
    - * @param {string} name
    - * @return {goog.fs.Error.ErrorCode} code
    - * @private
    - */
    -goog.fs.Error.getCodeFromName_ = function(name) {
    -  return goog.fs.Error.NameToCodeMap_[name];
    -};
    -
    -
    -/**
    - * Mapping from error names to values from the ErrorCode enum.
    - * @see http://www.w3.org/TR/file-system-api/#definitions.
    - * @private {!Object<string, goog.fs.Error.ErrorCode>}
    - */
    -goog.fs.Error.NameToCodeMap_ = goog.object.create(
    -    goog.fs.Error.ErrorName.ABORT,
    -    goog.fs.Error.ErrorCode.ABORT,
    -
    -    goog.fs.Error.ErrorName.ENCODING,
    -    goog.fs.Error.ErrorCode.ENCODING,
    -
    -    goog.fs.Error.ErrorName.INVALID_MODIFICATION,
    -    goog.fs.Error.ErrorCode.INVALID_MODIFICATION,
    -
    -    goog.fs.Error.ErrorName.INVALID_STATE,
    -    goog.fs.Error.ErrorCode.INVALID_STATE,
    -
    -    goog.fs.Error.ErrorName.NOT_FOUND,
    -    goog.fs.Error.ErrorCode.NOT_FOUND,
    -
    -    goog.fs.Error.ErrorName.NOT_READABLE,
    -    goog.fs.Error.ErrorCode.NOT_READABLE,
    -
    -    goog.fs.Error.ErrorName.NO_MODIFICATION_ALLOWED,
    -    goog.fs.Error.ErrorCode.NO_MODIFICATION_ALLOWED,
    -
    -    goog.fs.Error.ErrorName.PATH_EXISTS,
    -    goog.fs.Error.ErrorCode.PATH_EXISTS,
    -
    -    goog.fs.Error.ErrorName.QUOTA_EXCEEDED,
    -    goog.fs.Error.ErrorCode.QUOTA_EXCEEDED,
    -
    -    goog.fs.Error.ErrorName.SECURITY,
    -    goog.fs.Error.ErrorCode.SECURITY,
    -
    -    goog.fs.Error.ErrorName.SYNTAX,
    -    goog.fs.Error.ErrorCode.SYNTAX,
    -
    -    goog.fs.Error.ErrorName.TYPE_MISMATCH,
    -    goog.fs.Error.ErrorCode.TYPE_MISMATCH);
    diff --git a/src/database/third_party/closure-library/closure/goog/fs/filereader.js b/src/database/third_party/closure-library/closure/goog/fs/filereader.js
    deleted file mode 100644
    index 14d5245f355..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fs/filereader.js
    +++ /dev/null
    @@ -1,288 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A wrapper for the HTML5 FileReader object.
    - *
    - */
    -
    -goog.provide('goog.fs.FileReader');
    -goog.provide('goog.fs.FileReader.EventType');
    -goog.provide('goog.fs.FileReader.ReadyState');
    -
    -goog.require('goog.async.Deferred');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.fs.Error');
    -goog.require('goog.fs.ProgressEvent');
    -
    -
    -
    -/**
    - * An object for monitoring the reading of files. This emits ProgressEvents of
    - * the types listed in {@link goog.fs.FileReader.EventType}.
    - *
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - * @final
    - */
    -goog.fs.FileReader = function() {
    -  goog.fs.FileReader.base(this, 'constructor');
    -
    -  /**
    -   * The underlying FileReader object.
    -   *
    -   * @type {!FileReader}
    -   * @private
    -   */
    -  this.reader_ = new FileReader();
    -
    -  this.reader_.onloadstart = goog.bind(this.dispatchProgressEvent_, this);
    -  this.reader_.onprogress = goog.bind(this.dispatchProgressEvent_, this);
    -  this.reader_.onload = goog.bind(this.dispatchProgressEvent_, this);
    -  this.reader_.onabort = goog.bind(this.dispatchProgressEvent_, this);
    -  this.reader_.onerror = goog.bind(this.dispatchProgressEvent_, this);
    -  this.reader_.onloadend = goog.bind(this.dispatchProgressEvent_, this);
    -};
    -goog.inherits(goog.fs.FileReader, goog.events.EventTarget);
    -
    -
    -/**
    - * Possible states for a FileReader.
    - *
    - * @enum {number}
    - */
    -goog.fs.FileReader.ReadyState = {
    -  /**
    -   * The object has been constructed, but there is no pending read.
    -   */
    -  INIT: 0,
    -  /**
    -   * Data is being read.
    -   */
    -  LOADING: 1,
    -  /**
    -   * The data has been read from the file, the read was aborted, or an error
    -   * occurred.
    -   */
    -  DONE: 2
    -};
    -
    -
    -/**
    - * Events emitted by a FileReader.
    - *
    - * @enum {string}
    - */
    -goog.fs.FileReader.EventType = {
    -  /**
    -   * Emitted when the reading begins. readyState will be LOADING.
    -   */
    -  LOAD_START: 'loadstart',
    -  /**
    -   * Emitted when progress has been made in reading the file. readyState will be
    -   * LOADING.
    -   */
    -  PROGRESS: 'progress',
    -  /**
    -   * Emitted when the data has been successfully read. readyState will be
    -   * LOADING.
    -   */
    -  LOAD: 'load',
    -  /**
    -   * Emitted when the reading has been aborted. readyState will be LOADING.
    -   */
    -  ABORT: 'abort',
    -  /**
    -   * Emitted when an error is encountered or the reading has been aborted.
    -   * readyState will be LOADING.
    -   */
    -  ERROR: 'error',
    -  /**
    -   * Emitted when the reading is finished, whether successfully or not.
    -   * readyState will be DONE.
    -   */
    -  LOAD_END: 'loadend'
    -};
    -
    -
    -/**
    - * Abort the reading of the file.
    - */
    -goog.fs.FileReader.prototype.abort = function() {
    -  try {
    -    this.reader_.abort();
    -  } catch (e) {
    -    throw new goog.fs.Error(e, 'aborting read');
    -  }
    -};
    -
    -
    -/**
    - * @return {goog.fs.FileReader.ReadyState} The current state of the FileReader.
    - */
    -goog.fs.FileReader.prototype.getReadyState = function() {
    -  return /** @type {goog.fs.FileReader.ReadyState} */ (this.reader_.readyState);
    -};
    -
    -
    -/**
    - * @return {*} The result of the file read.
    - */
    -goog.fs.FileReader.prototype.getResult = function() {
    -  return this.reader_.result;
    -};
    -
    -
    -/**
    - * @return {goog.fs.Error} The error encountered while reading, if any.
    - */
    -goog.fs.FileReader.prototype.getError = function() {
    -  return this.reader_.error &&
    -      new goog.fs.Error(this.reader_.error, 'reading file');
    -};
    -
    -
    -/**
    - * Wrap a progress event emitted by the underlying file reader and re-emit it.
    - *
    - * @param {!ProgressEvent} event The underlying event.
    - * @private
    - */
    -goog.fs.FileReader.prototype.dispatchProgressEvent_ = function(event) {
    -  this.dispatchEvent(new goog.fs.ProgressEvent(event, this));
    -};
    -
    -
    -/** @override */
    -goog.fs.FileReader.prototype.disposeInternal = function() {
    -  goog.fs.FileReader.base(this, 'disposeInternal');
    -  delete this.reader_;
    -};
    -
    -
    -/**
    - * Starts reading a blob as a binary string.
    - * @param {!Blob} blob The blob to read.
    - */
    -goog.fs.FileReader.prototype.readAsBinaryString = function(blob) {
    -  this.reader_.readAsBinaryString(blob);
    -};
    -
    -
    -/**
    - * Reads a blob as a binary string.
    - * @param {!Blob} blob The blob to read.
    - * @return {!goog.async.Deferred} The deferred Blob contents as a binary string.
    - *     If an error occurs, the errback is called with a {@link goog.fs.Error}.
    - */
    -goog.fs.FileReader.readAsBinaryString = function(blob) {
    -  var reader = new goog.fs.FileReader();
    -  var d = goog.fs.FileReader.createDeferred_(reader);
    -  reader.readAsBinaryString(blob);
    -  return d;
    -};
    -
    -
    -/**
    - * Starts reading a blob as an array buffer.
    - * @param {!Blob} blob The blob to read.
    - */
    -goog.fs.FileReader.prototype.readAsArrayBuffer = function(blob) {
    -  this.reader_.readAsArrayBuffer(blob);
    -};
    -
    -
    -/**
    - * Reads a blob as an array buffer.
    - * @param {!Blob} blob The blob to read.
    - * @return {!goog.async.Deferred} The deferred Blob contents as an array buffer.
    - *     If an error occurs, the errback is called with a {@link goog.fs.Error}.
    - */
    -goog.fs.FileReader.readAsArrayBuffer = function(blob) {
    -  var reader = new goog.fs.FileReader();
    -  var d = goog.fs.FileReader.createDeferred_(reader);
    -  reader.readAsArrayBuffer(blob);
    -  return d;
    -};
    -
    -
    -/**
    - * Starts reading a blob as text.
    - * @param {!Blob} blob The blob to read.
    - * @param {string=} opt_encoding The name of the encoding to use.
    - */
    -goog.fs.FileReader.prototype.readAsText = function(blob, opt_encoding) {
    -  this.reader_.readAsText(blob, opt_encoding);
    -};
    -
    -
    -/**
    - * Reads a blob as text.
    - * @param {!Blob} blob The blob to read.
    - * @param {string=} opt_encoding The name of the encoding to use.
    - * @return {!goog.async.Deferred} The deferred Blob contents as text.
    - *     If an error occurs, the errback is called with a {@link goog.fs.Error}.
    - */
    -goog.fs.FileReader.readAsText = function(blob, opt_encoding) {
    -  var reader = new goog.fs.FileReader();
    -  var d = goog.fs.FileReader.createDeferred_(reader);
    -  reader.readAsText(blob, opt_encoding);
    -  return d;
    -};
    -
    -
    -/**
    - * Starts reading a blob as a data URL.
    - * @param {!Blob} blob The blob to read.
    - */
    -goog.fs.FileReader.prototype.readAsDataUrl = function(blob) {
    -  this.reader_.readAsDataURL(blob);
    -};
    -
    -
    -/**
    - * Reads a blob as a data URL.
    - * @param {!Blob} blob The blob to read.
    - * @return {!goog.async.Deferred} The deferred Blob contents as a data URL.
    - *     If an error occurs, the errback is called with a {@link goog.fs.Error}.
    - */
    -goog.fs.FileReader.readAsDataUrl = function(blob) {
    -  var reader = new goog.fs.FileReader();
    -  var d = goog.fs.FileReader.createDeferred_(reader);
    -  reader.readAsDataUrl(blob);
    -  return d;
    -};
    -
    -
    -/**
    - * Creates a new deferred object for the results of a read method.
    - * @param {goog.fs.FileReader} reader The reader to create a deferred for.
    - * @return {!goog.async.Deferred} The deferred results.
    - * @private
    - */
    -goog.fs.FileReader.createDeferred_ = function(reader) {
    -  var deferred = new goog.async.Deferred();
    -  reader.listen(goog.fs.FileReader.EventType.LOAD_END,
    -      goog.partial(function(d, r, e) {
    -        var result = r.getResult();
    -        var error = r.getError();
    -        if (result != null && !error) {
    -          d.callback(result);
    -        } else {
    -          d.errback(error);
    -        }
    -        r.dispose();
    -      }, deferred, reader));
    -  return deferred;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/fs/filesaver.js b/src/database/third_party/closure-library/closure/goog/fs/filesaver.js
    deleted file mode 100644
    index 8d441c4e23d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fs/filesaver.js
    +++ /dev/null
    @@ -1,166 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A wrapper for the HTML5 FileSaver object.
    - *
    - */
    -
    -goog.provide('goog.fs.FileSaver');
    -goog.provide('goog.fs.FileSaver.EventType');
    -goog.provide('goog.fs.FileSaver.ReadyState');
    -
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.fs.Error');
    -goog.require('goog.fs.ProgressEvent');
    -
    -
    -
    -/**
    - * An object for monitoring the saving of files. This emits ProgressEvents of
    - * the types listed in {@link goog.fs.FileSaver.EventType}.
    - *
    - * This should not be instantiated directly. Instead, its subclass
    - * {@link goog.fs.FileWriter} should be accessed via
    - * {@link goog.fs.FileEntry#createWriter}.
    - *
    - * @param {!FileSaver} fileSaver The underlying FileSaver object.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - */
    -goog.fs.FileSaver = function(fileSaver) {
    -  goog.fs.FileSaver.base(this, 'constructor');
    -
    -  /**
    -   * The underlying FileSaver object.
    -   *
    -   * @type {!FileSaver}
    -   * @private
    -   */
    -  this.saver_ = fileSaver;
    -
    -  this.saver_.onwritestart = goog.bind(this.dispatchProgressEvent_, this);
    -  this.saver_.onprogress = goog.bind(this.dispatchProgressEvent_, this);
    -  this.saver_.onwrite = goog.bind(this.dispatchProgressEvent_, this);
    -  this.saver_.onabort = goog.bind(this.dispatchProgressEvent_, this);
    -  this.saver_.onerror = goog.bind(this.dispatchProgressEvent_, this);
    -  this.saver_.onwriteend = goog.bind(this.dispatchProgressEvent_, this);
    -};
    -goog.inherits(goog.fs.FileSaver, goog.events.EventTarget);
    -
    -
    -/**
    - * Possible states for a FileSaver.
    - *
    - * @enum {number}
    - */
    -goog.fs.FileSaver.ReadyState = {
    -  /**
    -   * The object has been constructed, but there is no pending write.
    -   */
    -  INIT: 0,
    -  /**
    -   * Data is being written.
    -   */
    -  WRITING: 1,
    -  /**
    -   * The data has been written to the file, the write was aborted, or an error
    -   * occurred.
    -   */
    -  DONE: 2
    -};
    -
    -
    -/**
    - * Events emitted by a FileSaver.
    - *
    - * @enum {string}
    - */
    -goog.fs.FileSaver.EventType = {
    -  /**
    -   * Emitted when the writing begins. readyState will be WRITING.
    -   */
    -  WRITE_START: 'writestart',
    -  /**
    -   * Emitted when progress has been made in saving the file. readyState will be
    -   * WRITING.
    -   */
    -  PROGRESS: 'progress',
    -  /**
    -   * Emitted when the data has been successfully written. readyState will be
    -   * WRITING.
    -   */
    -  WRITE: 'write',
    -  /**
    -   * Emitted when the writing has been aborted. readyState will be WRITING.
    -   */
    -  ABORT: 'abort',
    -  /**
    -   * Emitted when an error is encountered or the writing has been aborted.
    -   * readyState will be WRITING.
    -   */
    -  ERROR: 'error',
    -  /**
    -   * Emitted when the writing is finished, whether successfully or not.
    -   * readyState will be DONE.
    -   */
    -  WRITE_END: 'writeend'
    -};
    -
    -
    -/**
    - * Abort the writing of the file.
    - */
    -goog.fs.FileSaver.prototype.abort = function() {
    -  try {
    -    this.saver_.abort();
    -  } catch (e) {
    -    throw new goog.fs.Error(e, 'aborting save');
    -  }
    -};
    -
    -
    -/**
    - * @return {goog.fs.FileSaver.ReadyState} The current state of the FileSaver.
    - */
    -goog.fs.FileSaver.prototype.getReadyState = function() {
    -  return /** @type {goog.fs.FileSaver.ReadyState} */ (this.saver_.readyState);
    -};
    -
    -
    -/**
    - * @return {goog.fs.Error} The error encountered while writing, if any.
    - */
    -goog.fs.FileSaver.prototype.getError = function() {
    -  return this.saver_.error &&
    -      new goog.fs.Error(this.saver_.error, 'saving file');
    -};
    -
    -
    -/**
    - * Wrap a progress event emitted by the underlying file saver and re-emit it.
    - *
    - * @param {!ProgressEvent} event The underlying event.
    - * @private
    - */
    -goog.fs.FileSaver.prototype.dispatchProgressEvent_ = function(event) {
    -  this.dispatchEvent(new goog.fs.ProgressEvent(event, this));
    -};
    -
    -
    -/** @override */
    -goog.fs.FileSaver.prototype.disposeInternal = function() {
    -  delete this.saver_;
    -  goog.fs.FileSaver.base(this, 'disposeInternal');
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/fs/filesystem.js b/src/database/third_party/closure-library/closure/goog/fs/filesystem.js
    deleted file mode 100644
    index b120b92dd59..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fs/filesystem.js
    +++ /dev/null
    @@ -1,41 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A wrapper for the HTML5 FileSystem object.
    - *
    - */
    -
    -goog.provide('goog.fs.FileSystem');
    -
    -
    -
    -/**
    - * A local filesystem.
    - *
    - * @interface
    - */
    -goog.fs.FileSystem = function() {};
    -
    -
    -/**
    - * @return {string} The name of the filesystem.
    - */
    -goog.fs.FileSystem.prototype.getName = function() {};
    -
    -
    -/**
    - * @return {!goog.fs.DirectoryEntry} The root directory of the filesystem.
    - */
    -goog.fs.FileSystem.prototype.getRoot = function() {};
    diff --git a/src/database/third_party/closure-library/closure/goog/fs/filesystemimpl.js b/src/database/third_party/closure-library/closure/goog/fs/filesystemimpl.js
    deleted file mode 100644
    index b5ebb33b00b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fs/filesystemimpl.js
    +++ /dev/null
    @@ -1,65 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Concrete implementation of the goog.fs.FileSystem interface
    - *     using an HTML FileSystem object.
    - */
    -goog.provide('goog.fs.FileSystemImpl');
    -
    -goog.require('goog.fs.DirectoryEntryImpl');
    -goog.require('goog.fs.FileSystem');
    -
    -
    -
    -/**
    - * A local filesystem.
    - *
    - * This shouldn't be instantiated directly. Instead, it should be accessed via
    - * {@link goog.fs.getTemporary} or {@link goog.fs.getPersistent}.
    - *
    - * @param {!FileSystem} fs The underlying FileSystem object.
    - * @constructor
    - * @implements {goog.fs.FileSystem}
    - * @final
    - */
    -goog.fs.FileSystemImpl = function(fs) {
    -  /**
    -   * The underlying FileSystem object.
    -   *
    -   * @type {!FileSystem}
    -   * @private
    -   */
    -  this.fs_ = fs;
    -};
    -
    -
    -/** @override */
    -goog.fs.FileSystemImpl.prototype.getName = function() {
    -  return this.fs_.name;
    -};
    -
    -
    -/** @override */
    -goog.fs.FileSystemImpl.prototype.getRoot = function() {
    -  return new goog.fs.DirectoryEntryImpl(this, this.fs_.root);
    -};
    -
    -
    -/**
    - * @return {!FileSystem} The underlying FileSystem object.
    - */
    -goog.fs.FileSystemImpl.prototype.getBrowserFileSystem = function() {
    -  return this.fs_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/fs/filewriter.js b/src/database/third_party/closure-library/closure/goog/fs/filewriter.js
    deleted file mode 100644
    index 170984651d7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fs/filewriter.js
    +++ /dev/null
    @@ -1,111 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A wrapper for the HTML5 FileWriter object.
    - *
    - * When adding or modifying functionality in this namespace, be sure to update
    - * the mock counterparts in goog.testing.fs.
    - *
    - */
    -
    -goog.provide('goog.fs.FileWriter');
    -
    -goog.require('goog.fs.Error');
    -goog.require('goog.fs.FileSaver');
    -
    -
    -
    -/**
    - * An object for monitoring the saving of files, as well as other fine-grained
    - * writing operations.
    - *
    - * This should not be instantiated directly. Instead, it should be accessed via
    - * {@link goog.fs.FileEntry#createWriter}.
    - *
    - * @param {!FileWriter} writer The underlying FileWriter object.
    - * @constructor
    - * @extends {goog.fs.FileSaver}
    - * @final
    - */
    -goog.fs.FileWriter = function(writer) {
    -  goog.fs.FileWriter.base(this, 'constructor', writer);
    -
    -  /**
    -   * The underlying FileWriter object.
    -   *
    -   * @type {!FileWriter}
    -   * @private
    -   */
    -  this.writer_ = writer;
    -};
    -goog.inherits(goog.fs.FileWriter, goog.fs.FileSaver);
    -
    -
    -/**
    - * @return {number} The byte offset at which the next write will occur.
    - */
    -goog.fs.FileWriter.prototype.getPosition = function() {
    -  return this.writer_.position;
    -};
    -
    -
    -/**
    - * @return {number} The length of the file.
    - */
    -goog.fs.FileWriter.prototype.getLength = function() {
    -  return this.writer_.length;
    -};
    -
    -
    -/**
    - * Write data to the file.
    - *
    - * @param {!Blob} blob The data to write.
    - */
    -goog.fs.FileWriter.prototype.write = function(blob) {
    -  try {
    -    this.writer_.write(blob);
    -  } catch (e) {
    -    throw new goog.fs.Error(e, 'writing file');
    -  }
    -};
    -
    -
    -/**
    - * Set the file position at which the next write will occur.
    - *
    - * @param {number} offset An absolute byte offset into the file.
    - */
    -goog.fs.FileWriter.prototype.seek = function(offset) {
    -  try {
    -    this.writer_.seek(offset);
    -  } catch (e) {
    -    throw new goog.fs.Error(e, 'seeking in file');
    -  }
    -};
    -
    -
    -/**
    - * Changes the length of the file to that specified.
    - *
    - * @param {number} size The new size of the file, in bytes.
    - */
    -goog.fs.FileWriter.prototype.truncate = function(size) {
    -  try {
    -    this.writer_.truncate(size);
    -  } catch (e) {
    -    throw new goog.fs.Error(e, 'truncating file');
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/fs/fs.js b/src/database/third_party/closure-library/closure/goog/fs/fs.js
    deleted file mode 100644
    index 25fb0cd5eec..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fs/fs.js
    +++ /dev/null
    @@ -1,319 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Wrappers for the HTML5 File API. These wrappers closely mirror
    - * the underlying APIs, but use Closure-style events and Deferred return values.
    - * Their existence also makes it possible to mock the FileSystem API for testing
    - * in browsers that don't support it natively.
    - *
    - * When adding public functions to anything under this namespace, be sure to add
    - * its mock counterpart to goog.testing.fs.
    - *
    - */
    -
    -goog.provide('goog.fs');
    -
    -goog.require('goog.array');
    -goog.require('goog.async.Deferred');
    -goog.require('goog.fs.Error');
    -goog.require('goog.fs.FileReader');
    -goog.require('goog.fs.FileSystemImpl');
    -goog.require('goog.userAgent');
    -
    -
    -/**
    - * Get a wrapped FileSystem object.
    - *
    - * @param {goog.fs.FileSystemType_} type The type of the filesystem to get.
    - * @param {number} size The size requested for the filesystem, in bytes.
    - * @return {!goog.async.Deferred} The deferred {@link goog.fs.FileSystem}. If an
    - *     error occurs, the errback is called with a {@link goog.fs.Error}.
    - * @private
    - */
    -goog.fs.get_ = function(type, size) {
    -  var requestFileSystem = goog.global.requestFileSystem ||
    -      goog.global.webkitRequestFileSystem;
    -
    -  if (!goog.isFunction(requestFileSystem)) {
    -    return goog.async.Deferred.fail(new Error('File API unsupported'));
    -  }
    -
    -  var d = new goog.async.Deferred();
    -  requestFileSystem(type, size, function(fs) {
    -    d.callback(new goog.fs.FileSystemImpl(fs));
    -  }, function(err) {
    -    d.errback(new goog.fs.Error(err, 'requesting filesystem'));
    -  });
    -  return d;
    -};
    -
    -
    -/**
    - * The two types of filesystem.
    - *
    - * @enum {number}
    - * @private
    - */
    -goog.fs.FileSystemType_ = {
    -  /**
    -   * A temporary filesystem may be deleted by the user agent at its discretion.
    -   */
    -  TEMPORARY: 0,
    -  /**
    -   * A persistent filesystem will never be deleted without the user's or
    -   * application's authorization.
    -   */
    -  PERSISTENT: 1
    -};
    -
    -
    -/**
    - * Returns a temporary FileSystem object. A temporary filesystem may be deleted
    - * by the user agent at its discretion.
    - *
    - * @param {number} size The size requested for the filesystem, in bytes.
    - * @return {!goog.async.Deferred} The deferred {@link goog.fs.FileSystem}. If an
    - *     error occurs, the errback is called with a {@link goog.fs.Error}.
    - */
    -goog.fs.getTemporary = function(size) {
    -  return goog.fs.get_(goog.fs.FileSystemType_.TEMPORARY, size);
    -};
    -
    -
    -/**
    - * Returns a persistent FileSystem object. A persistent filesystem will never be
    - * deleted without the user's or application's authorization.
    - *
    - * @param {number} size The size requested for the filesystem, in bytes.
    - * @return {!goog.async.Deferred} The deferred {@link goog.fs.FileSystem}. If an
    - *     error occurs, the errback is called with a {@link goog.fs.Error}.
    - */
    -goog.fs.getPersistent = function(size) {
    -  return goog.fs.get_(goog.fs.FileSystemType_.PERSISTENT, size);
    -};
    -
    -
    -/**
    - * Creates a blob URL for a blob object.
    - * Throws an error if the browser does not support Object Urls.
    - *
    - * @param {!Blob} blob The object for which to create the URL.
    - * @return {string} The URL for the object.
    - */
    -goog.fs.createObjectUrl = function(blob) {
    -  return goog.fs.getUrlObject_().createObjectURL(blob);
    -};
    -
    -
    -/**
    - * Revokes a URL created by {@link goog.fs.createObjectUrl}.
    - * Throws an error if the browser does not support Object Urls.
    - *
    - * @param {string} url The URL to revoke.
    - */
    -goog.fs.revokeObjectUrl = function(url) {
    -  goog.fs.getUrlObject_().revokeObjectURL(url);
    -};
    -
    -
    -/**
    - * @typedef {{createObjectURL: (function(!Blob): string),
    - *            revokeObjectURL: function(string): void}}
    - */
    -goog.fs.UrlObject_;
    -
    -
    -/**
    - * Get the object that has the createObjectURL and revokeObjectURL functions for
    - * this browser.
    - *
    - * @return {goog.fs.UrlObject_} The object for this browser.
    - * @private
    - */
    -goog.fs.getUrlObject_ = function() {
    -  var urlObject = goog.fs.findUrlObject_();
    -  if (urlObject != null) {
    -    return urlObject;
    -  } else {
    -    throw Error('This browser doesn\'t seem to support blob URLs');
    -  }
    -};
    -
    -
    -/**
    - * Finds the object that has the createObjectURL and revokeObjectURL functions
    - * for this browser.
    - *
    - * @return {?goog.fs.UrlObject_} The object for this browser or null if the
    - *     browser does not support Object Urls.
    - * @private
    - */
    -goog.fs.findUrlObject_ = function() {
    -  // This is what the spec says to do
    -  // http://dev.w3.org/2006/webapi/FileAPI/#dfn-createObjectURL
    -  if (goog.isDef(goog.global.URL) &&
    -      goog.isDef(goog.global.URL.createObjectURL)) {
    -    return /** @type {goog.fs.UrlObject_} */ (goog.global.URL);
    -  // This is what Chrome does (as of 10.0.648.6 dev)
    -  } else if (goog.isDef(goog.global.webkitURL) &&
    -             goog.isDef(goog.global.webkitURL.createObjectURL)) {
    -    return /** @type {goog.fs.UrlObject_} */ (goog.global.webkitURL);
    -  // This is what the spec used to say to do
    -  } else if (goog.isDef(goog.global.createObjectURL)) {
    -    return /** @type {goog.fs.UrlObject_} */ (goog.global);
    -  } else {
    -    return null;
    -  }
    -};
    -
    -
    -/**
    - * Checks whether this browser supports Object Urls. If not, calls to
    - * createObjectUrl and revokeObjectUrl will result in an error.
    - *
    - * @return {boolean} True if this browser supports Object Urls.
    - */
    -goog.fs.browserSupportsObjectUrls = function() {
    -  return goog.fs.findUrlObject_() != null;
    -};
    -
    -
    -/**
    - * Concatenates one or more values together and converts them to a Blob.
    - *
    - * @param {...(string|!Blob|!ArrayBuffer)} var_args The values that will make up
    - *     the resulting blob.
    - * @return {!Blob} The blob.
    - */
    -goog.fs.getBlob = function(var_args) {
    -  var BlobBuilder = goog.global.BlobBuilder || goog.global.WebKitBlobBuilder;
    -
    -  if (goog.isDef(BlobBuilder)) {
    -    var bb = new BlobBuilder();
    -    for (var i = 0; i < arguments.length; i++) {
    -      bb.append(arguments[i]);
    -    }
    -    return bb.getBlob();
    -  } else {
    -    return goog.fs.getBlobWithProperties(goog.array.toArray(arguments));
    -  }
    -};
    -
    -
    -/**
    - * Creates a blob with the given properties.
    - * See https://developer.mozilla.org/en-US/docs/Web/API/Blob for more details.
    - *
    - * @param {Array<string|!Blob>} parts The values that will make up the
    - *     resulting blob.
    - * @param {string=} opt_type The MIME type of the Blob.
    - * @param {string=} opt_endings Specifies how strings containing newlines are to
    - *     be written out.
    - * @return {!Blob} The blob.
    - */
    -goog.fs.getBlobWithProperties = function(parts, opt_type, opt_endings) {
    -  var BlobBuilder = goog.global.BlobBuilder || goog.global.WebKitBlobBuilder;
    -
    -  if (goog.isDef(BlobBuilder)) {
    -    var bb = new BlobBuilder();
    -    for (var i = 0; i < parts.length; i++) {
    -      bb.append(parts[i], opt_endings);
    -    }
    -    return bb.getBlob(opt_type);
    -  } else if (goog.isDef(goog.global.Blob)) {
    -    var properties = {};
    -    if (opt_type) {
    -      properties['type'] = opt_type;
    -    }
    -    if (opt_endings) {
    -      properties['endings'] = opt_endings;
    -    }
    -    return new Blob(parts, properties);
    -  } else {
    -    throw Error('This browser doesn\'t seem to support creating Blobs');
    -  }
    -};
    -
    -
    -/**
    - * Converts a Blob or a File into a string. This should only be used when the
    - * blob is known to be small.
    - *
    - * @param {!Blob} blob The blob to convert.
    - * @param {string=} opt_encoding The name of the encoding to use.
    - * @return {!goog.async.Deferred} The deferred string. If an error occurrs, the
    - *     errback is called with a {@link goog.fs.Error}.
    - * @deprecated Use {@link goog.fs.FileReader.readAsText} instead.
    - */
    -goog.fs.blobToString = function(blob, opt_encoding) {
    -  return goog.fs.FileReader.readAsText(blob, opt_encoding);
    -};
    -
    -
    -/**
    - * Slices the blob. The returned blob contains data from the start byte
    - * (inclusive) till the end byte (exclusive). Negative indices can be used
    - * to count bytes from the end of the blob (-1 == blob.size - 1). Indices
    - * are always clamped to blob range. If end is omitted, all the data till
    - * the end of the blob is taken.
    - *
    - * @param {!Blob} blob The blob to be sliced.
    - * @param {number} start Index of the starting byte.
    - * @param {number=} opt_end Index of the ending byte.
    - * @return {Blob} The blob slice or null if not supported.
    - */
    -goog.fs.sliceBlob = function(blob, start, opt_end) {
    -  if (!goog.isDef(opt_end)) {
    -    opt_end = blob.size;
    -  }
    -  if (blob.webkitSlice) {
    -    // Natively accepts negative indices, clamping to the blob range and
    -    // range end is optional. See http://trac.webkit.org/changeset/83873
    -    return blob.webkitSlice(start, opt_end);
    -  } else if (blob.mozSlice) {
    -    // Natively accepts negative indices, clamping to the blob range and
    -    // range end is optional. See https://developer.mozilla.org/en/DOM/Blob
    -    // and http://hg.mozilla.org/mozilla-central/rev/dae833f4d934
    -    return blob.mozSlice(start, opt_end);
    -  } else if (blob.slice) {
    -    // Old versions of Firefox and Chrome use the original specification.
    -    // Negative indices are not accepted, only range end is clamped and
    -    // range end specification is obligatory.
    -    // See http://www.w3.org/TR/2009/WD-FileAPI-20091117/
    -    if ((goog.userAgent.GECKO && !goog.userAgent.isVersionOrHigher('13.0')) ||
    -        (goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher('537.1'))) {
    -      if (start < 0) {
    -        start += blob.size;
    -      }
    -      if (start < 0) {
    -        start = 0;
    -      }
    -      if (opt_end < 0) {
    -        opt_end += blob.size;
    -      }
    -      if (opt_end < start) {
    -        opt_end = start;
    -      }
    -      return blob.slice(start, opt_end - start);
    -    }
    -    // IE and the latest versions of Firefox and Chrome use the new
    -    // specification. Natively accepts negative indices, clamping to the blob
    -    // range and range end is optional.
    -    // See http://dev.w3.org/2006/webapi/FileAPI/
    -    return blob.slice(start, opt_end);
    -  }
    -  return null;
    -};
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/fs/fs_test.html b/src/database/third_party/closure-library/closure/goog/fs/fs_test.html
    deleted file mode 100644
    index a76ee2a7030..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fs/fs_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <title>
    -   Closure Integration Tests - goog.fs
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.fsTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="closureTestRunnerLog">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/fs/fs_test.js b/src/database/third_party/closure-library/closure/goog/fs/fs_test.js
    deleted file mode 100644
    index 2558a7df619..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fs/fs_test.js
    +++ /dev/null
    @@ -1,776 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.fsTest');
    -goog.setTestOnly('goog.fsTest');
    -
    -goog.require('goog.Promise');
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.fs');
    -goog.require('goog.fs.DirectoryEntry');
    -goog.require('goog.fs.Error');
    -goog.require('goog.fs.FileReader');
    -goog.require('goog.fs.FileSaver');
    -goog.require('goog.string');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -
    -var TEST_DIR = 'goog-fs-test-dir';
    -
    -var fsExists = goog.isDef(goog.global.requestFileSystem) ||
    -    goog.isDef(goog.global.webkitRequestFileSystem);
    -var deferredFs = fsExists ? goog.fs.getTemporary() : null;
    -var stubs = new goog.testing.PropertyReplacer();
    -
    -function setUpPage() {
    -  if (!fsExists) {
    -    return;
    -  }
    -
    -  return loadTestDir().then(null, function(err) {
    -    var msg;
    -    if (err.code == goog.fs.Error.ErrorCode.QUOTA_EXCEEDED) {
    -      msg = err.message + '. If you\'re using Chrome, you probably need to ' +
    -          'pass --unlimited-quota-for-files on the command line.';
    -    } else if (err.code == goog.fs.Error.ErrorCode.SECURITY &&
    -               window.location.href.match(/^file:/)) {
    -      msg = err.message + '. file:// URLs can\'t access the filesystem API.';
    -    } else {
    -      msg = err.message;
    -    }
    -    var body = goog.dom.getDocument().body;
    -    goog.dom.insertSiblingBefore(
    -        goog.dom.createDom('h1', {}, msg), body.childNodes[0]);
    -  });
    -}
    -
    -function tearDown() {
    -  if (!fsExists) {
    -    return;
    -  }
    -
    -  return loadTestDir().then(function(dir) { return dir.removeRecursively(); });
    -}
    -
    -function testUnavailableTemporaryFilesystem() {
    -  stubs.set(goog.global, 'requestFileSystem', null);
    -  stubs.set(goog.global, 'webkitRequestFileSystem', null);
    -
    -  return goog.fs.getTemporary(1024).then(fail, function(e) {
    -    assertEquals('File API unsupported', e.message);
    -  });
    -}
    -
    -
    -function testUnavailablePersistentFilesystem() {
    -  stubs.set(goog.global, 'requestFileSystem', null);
    -  stubs.set(goog.global, 'webkitRequestFileSystem', null);
    -
    -  return goog.fs.getPersistent(2048).then(fail, function(e) {
    -    assertEquals('File API unsupported', e.message);
    -  });
    -}
    -
    -
    -function testIsFile() {
    -  if (!fsExists) {
    -    return;
    -  }
    -
    -  return loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE).then(
    -      function(fileEntry) {
    -        assertFalse(fileEntry.isDirectory());
    -        assertTrue(fileEntry.isFile());
    -      });
    -}
    -
    -function testIsDirectory() {
    -  if (!fsExists) {
    -    return;
    -  }
    -
    -  return loadDirectory('test', goog.fs.DirectoryEntry.Behavior.CREATE).then(
    -      function(fileEntry) {
    -        assertTrue(fileEntry.isDirectory());
    -        assertFalse(fileEntry.isFile());
    -      });
    -}
    -
    -function testReadFileUtf16() {
    -  if (!fsExists) {
    -    return;
    -  }
    -  var str = 'test content';
    -  var buf = new ArrayBuffer(str.length * 2);
    -  var arr = new Uint16Array(buf);
    -  for (var i = 0; i < str.length; i++) {
    -    arr[i] = str.charCodeAt(i);
    -  }
    -
    -  return loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE).
    -      then(goog.partial(writeToFile, arr.buffer)).
    -      then(goog.partial(checkFileContentWithEncoding, str, 'UTF-16'));
    -}
    -
    -function testReadFileUtf8() {
    -  if (!fsExists) {
    -    return;
    -  }
    -  var str = 'test content';
    -  var buf = new ArrayBuffer(str.length);
    -  var arr = new Uint8Array(buf);
    -  for (var i = 0; i < str.length; i++) {
    -    arr[i] = str.charCodeAt(i) & 0xff;
    -  }
    -
    -  return loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE).
    -      then(goog.partial(writeToFile, arr.buffer)).
    -      then(goog.partial(checkFileContentWithEncoding, str, 'UTF-8'));
    -}
    -
    -function testReadFileAsArrayBuffer() {
    -  if (!fsExists) {
    -    return;
    -  }
    -  var str = 'test content';
    -  var buf = new ArrayBuffer(str.length);
    -  var arr = new Uint8Array(buf);
    -  for (var i = 0; i < str.length; i++) {
    -    arr[i] = str.charCodeAt(i) & 0xff;
    -  }
    -
    -  return loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE).
    -      then(goog.partial(writeToFile, arr.buffer)).
    -      then(goog.partial(checkFileContentAs, arr.buffer, 'ArrayBuffer',
    -          undefined));
    -}
    -
    -function testReadFileAsBinaryString() {
    -  if (!fsExists) {
    -    return;
    -  }
    -  var str = 'test content';
    -  var buf = new ArrayBuffer(str.length);
    -  var arr = new Uint8Array(buf);
    -  for (var i = 0; i < str.length; i++) {
    -    arr[i] = str.charCodeAt(i);
    -  }
    -
    -  return loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE).
    -      then(goog.partial(writeToFile, arr.buffer)).
    -      then(goog.partial(checkFileContentAs, str, 'BinaryString', undefined));
    -}
    -
    -function testWriteFile() {
    -  if (!fsExists) {
    -    return;
    -  }
    -
    -  return loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE).
    -      then(goog.partial(writeToFile, 'test content')).
    -      then(goog.partial(checkFileContent, 'test content'));
    -}
    -
    -function testRemoveFile() {
    -  if (!fsExists) {
    -    return;
    -  }
    -
    -  return loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE).
    -      then(goog.partial(writeToFile, 'test content')).
    -      then(function(file) { return file.remove(); }).
    -      then(goog.partial(checkFileRemoved, 'test'));
    -}
    -
    -function testMoveFile() {
    -  if (!fsExists) {
    -    return;
    -  }
    -
    -  var deferredSubdir = loadDirectory(
    -      'subdir', goog.fs.DirectoryEntry.Behavior.CREATE);
    -  var deferredWrittenFile =
    -      loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE).
    -      then(goog.partial(writeToFile, 'test content'));
    -  return goog.Promise.all([deferredSubdir, deferredWrittenFile]).
    -      then(splitArgs(function(dir, file) { return file.moveTo(dir); })).
    -      then(goog.partial(checkFileContent, 'test content')).
    -      then(goog.partial(checkFileRemoved, 'test'));
    -}
    -
    -function testCopyFile() {
    -  if (!fsExists) {
    -    return;
    -  }
    -
    -  var deferredFile = loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE);
    -  var deferredSubdir = loadDirectory(
    -      'subdir', goog.fs.DirectoryEntry.Behavior.CREATE);
    -  var deferredWrittenFile = deferredFile.then(
    -      goog.partial(writeToFile, 'test content'));
    -  return goog.Promise.all([deferredSubdir, deferredWrittenFile]).
    -      then(splitArgs(function(dir, file) { return file.copyTo(dir); })).
    -      then(goog.partial(checkFileContent, 'test content')).
    -      then(function() { return deferredFile; }).
    -      then(goog.partial(checkFileContent, 'test content'));
    -}
    -
    -function testAbortWrite() {
    -  // TODO(nicksantos): This test is broken in newer versions of chrome.
    -  // We don't know why yet.
    -  if (true) return;
    -
    -  if (!fsExists) {
    -    return;
    -  }
    -
    -  var deferredFile = loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE);
    -  return deferredFile.
    -      then(goog.partial(startWrite, 'test content')).
    -      then(function(writer) {
    -        return new goog.Promise(function(resolve) {
    -          goog.events.listenOnce(
    -              writer, goog.fs.FileSaver.EventType.ABORT, resolve);
    -          writer.abort();
    -        });
    -      }).
    -      then(function() { return loadFile('test'); }).
    -      then(goog.partial(checkFileContent, ''));
    -}
    -
    -function testSeek() {
    -  if (!fsExists) {
    -    return;
    -  }
    -
    -  var deferredFile = loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE);
    -  return deferredFile.
    -      then(goog.partial(writeToFile, 'test content')).
    -      then(function(file) { return file.createWriter(); }).
    -      then(
    -          goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.INIT)).
    -      then(function(writer) {
    -        writer.seek(5);
    -        writer.write(goog.fs.getBlob('stuff and things'));
    -        return writer;
    -      }).
    -      then(
    -          goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.WRITING)).
    -      then(
    -          goog.partial(waitForEvent, goog.fs.FileSaver.EventType.WRITE)).
    -      then(function() { return deferredFile; }).
    -      then(goog.partial(checkFileContent, 'test stuff and things'));
    -}
    -
    -function testTruncate() {
    -  if (!fsExists) {
    -    return;
    -  }
    -
    -  var deferredFile = loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE);
    -  return deferredFile.
    -      then(goog.partial(writeToFile, 'test content')).
    -      then(function(file) { return file.createWriter(); }).
    -      then(goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.INIT)).
    -      then(function(writer) {
    -        writer.truncate(4);
    -        return writer;
    -      }).
    -      then(
    -          goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.WRITING)).
    -      then(
    -          goog.partial(waitForEvent, goog.fs.FileSaver.EventType.WRITE)).
    -      then(function() { return deferredFile; }).
    -      then(goog.partial(checkFileContent, 'test'));
    -}
    -
    -function testGetLastModified() {
    -  if (!fsExists) {
    -    return;
    -  }
    -  var now = goog.now();
    -  return loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE).
    -      then(function(entry) { return entry.getLastModified(); }).
    -      then(function(date) {
    -        assertRoughlyEquals('Expected the last modified date to be within ' +
    -           'a few milliseconds of the test start time.',
    -           now, date.getTime(), 2000);
    -      });
    -}
    -
    -function testCreatePath() {
    -  if (!fsExists) {
    -    return;
    -  }
    -
    -  return loadTestDir().
    -      then(function(testDir) {
    -        return testDir.createPath('foo');
    -      }).
    -      then(function(fooDir) {
    -        assertEquals('/goog-fs-test-dir/foo', fooDir.getFullPath());
    -        return fooDir.createPath('bar/baz/bat');
    -      }).
    -      then(function(batDir) {
    -        assertEquals('/goog-fs-test-dir/foo/bar/baz/bat', batDir.getFullPath());
    -      });
    -}
    -
    -function testCreateAbsolutePath() {
    -  if (!fsExists) {
    -    return;
    -  }
    -
    -  return loadTestDir().
    -      then(function(testDir) {
    -        return testDir.createPath('/' + TEST_DIR + '/fee/fi/fo/fum');
    -      }).
    -      then(function(absDir) {
    -        assertEquals('/goog-fs-test-dir/fee/fi/fo/fum', absDir.getFullPath());
    -      });
    -}
    -
    -function testCreateRelativePath() {
    -  if (!fsExists) {
    -    return;
    -  }
    -
    -  return loadTestDir().
    -      then(function(dir) {
    -        return dir.createPath('../' + TEST_DIR + '/dir');
    -      }).
    -      then(function(relDir) {
    -        assertEquals('/goog-fs-test-dir/dir', relDir.getFullPath());
    -        return relDir.createPath('.');
    -      }).
    -      then(function(sameDir) {
    -        assertEquals('/goog-fs-test-dir/dir', sameDir.getFullPath());
    -        return sameDir.createPath('./././.');
    -      }).
    -      then(function(reallySameDir) {
    -        assertEquals('/goog-fs-test-dir/dir', reallySameDir.getFullPath());
    -        return reallySameDir.createPath('./new/../..//dir/./new////.');
    -      }).
    -      then(function(newDir) {
    -        assertEquals('/goog-fs-test-dir/dir/new', newDir.getFullPath());
    -      });
    -}
    -
    -function testCreateBadPath() {
    -  if (!fsExists) {
    -    return;
    -  }
    -
    -  return loadTestDir().
    -      then(function() { return loadTestDir(); }).
    -      then(function(dir) {
    -        // There is only one layer of parent directory from the test dir.
    -        return dir.createPath('../../../../' + TEST_DIR + '/baz/bat');
    -      }).
    -      then(function(batDir) {
    -        assertEquals('The parent directory of the root directory should ' +
    -                     'point back to the root directory.',
    -                     '/goog-fs-test-dir/baz/bat', batDir.getFullPath());
    -      }).
    -
    -      then(function() { return loadTestDir(); }).
    -      then(function(dir) {
    -        // An empty path should return the same as the input directory.
    -        return dir.createPath('');
    -      }).
    -      then(function(testDir) {
    -        assertEquals('/goog-fs-test-dir', testDir.getFullPath());
    -      });
    -}
    -
    -function testGetAbsolutePaths() {
    -  if (!fsExists) {
    -    return;
    -  }
    -
    -  return loadFile('foo', goog.fs.DirectoryEntry.Behavior.CREATE).
    -      then(function() { return loadTestDir(); }).
    -      then(function(testDir) { return testDir.getDirectory('/'); }).
    -      then(function(root) {
    -        assertEquals('/', root.getFullPath());
    -        return root.getDirectory('/' + TEST_DIR);
    -      }).
    -      then(function(testDir) {
    -        assertEquals('/goog-fs-test-dir', testDir.getFullPath());
    -        return testDir.getDirectory('//' + TEST_DIR + '////');
    -      }).
    -      then(function(testDir) {
    -        assertEquals('/goog-fs-test-dir', testDir.getFullPath());
    -        return testDir.getDirectory('////');
    -      }).
    -      then(function(testDir) { assertEquals('/', testDir.getFullPath()); });
    -}
    -
    -
    -function testListEmptyDirectory() {
    -  if (!fsExists) {
    -    return;
    -  }
    -
    -  return loadTestDir().
    -      then(function(dir) { return dir.listDirectory(); }).
    -      then(function(entries) { assertArrayEquals([], entries); });
    -}
    -
    -
    -function testListDirectory() {
    -  if (!fsExists) {
    -    return;
    -  }
    -
    -  return loadDirectory('testDir', goog.fs.DirectoryEntry.Behavior.CREATE).
    -      then(function() {
    -        return loadFile('testFile', goog.fs.DirectoryEntry.Behavior.CREATE);
    -      }).
    -      then(function() { return loadTestDir(); }).
    -      then(function(testDir) { return testDir.listDirectory(); }).
    -      then(function(entries) {
    -        // Verify the contents of the directory listing.
    -        assertEquals(2, entries.length);
    -
    -        var dir = goog.array.find(entries, function(entry) {
    -          return entry.getName() == 'testDir';
    -        });
    -        assertNotNull(dir);
    -        assertTrue(dir.isDirectory());
    -
    -        var file = goog.array.find(entries, function(entry) {
    -          return entry.getName() == 'testFile';
    -        });
    -        assertNotNull(file);
    -        assertTrue(file.isFile());
    -      });
    -}
    -
    -
    -function testListBigDirectory() {
    -  // TODO(nicksantos): This test is broken in newer versions of chrome.
    -  // We don't know why yet.
    -  if (true) return;
    -
    -  if (!fsExists) {
    -    return;
    -  }
    -
    -  function getFileName(i) {
    -    return 'file' + goog.string.padNumber(i, String(count).length);
    -  }
    -
    -  // NOTE: This was intended to verify that the results from repeated
    -  // DirectoryReader.readEntries() callbacks are appropriately concatenated.
    -  // In current versions of Chrome (March 2011), all results are returned in the
    -  // first callback regardless of directory size. The count can be increased in
    -  // the future to test batched result lists once they are implemented.
    -  var count = 100;
    -
    -  var expectedNames = [];
    -
    -  var def = goog.Promise.resolve();
    -  for (var i = 0; i < count; i++) {
    -    var name = getFileName(i);
    -    expectedNames.push(name);
    -
    -    def.then(function() {
    -      return loadFile(name, goog.fs.DirectoryEntry.Behavior.CREATE);
    -    });
    -  }
    -
    -  return def.then(function() { return loadTestDir(); }).
    -      then(function(testDir) { return testDir.listDirectory(); }).
    -      then(function(entries) {
    -        assertEquals(count, entries.length);
    -
    -        assertSameElements(expectedNames,
    -                           goog.array.map(entries, function(entry) {
    -                             return entry.getName();
    -                           }));
    -        assertTrue(goog.array.every(entries, function(entry) {
    -          return entry.isFile();
    -        }));
    -      });
    -}
    -
    -
    -function testSliceBlob() {
    -  // A mock blob object whose slice returns the parameters it was called with.
    -  var blob = {
    -    'size': 10,
    -    'slice': function(start, end) {
    -      return [start, end];
    -    }
    -  };
    -
    -  // Simulate Firefox 13 that implements the new slice.
    -  var tmpStubs = new goog.testing.PropertyReplacer();
    -  tmpStubs.set(goog.userAgent, 'GECKO', true);
    -  tmpStubs.set(goog.userAgent, 'WEBKIT', false);
    -  tmpStubs.set(goog.userAgent, 'IE', false);
    -  tmpStubs.set(goog.userAgent, 'VERSION', '13.0');
    -  tmpStubs.set(goog.userAgent, 'isVersionOrHigherCache_', {});
    -
    -  // Expect slice to be called with no change to parameters
    -  assertArrayEquals([2, 10], goog.fs.sliceBlob(blob, 2));
    -  assertArrayEquals([-2, 10], goog.fs.sliceBlob(blob, -2));
    -  assertArrayEquals([3, 6], goog.fs.sliceBlob(blob, 3, 6));
    -  assertArrayEquals([3, -6], goog.fs.sliceBlob(blob, 3, -6));
    -
    -  // Simulate IE 10 that implements the new slice.
    -  var tmpStubs = new goog.testing.PropertyReplacer();
    -  tmpStubs.set(goog.userAgent, 'GECKO', false);
    -  tmpStubs.set(goog.userAgent, 'WEBKIT', false);
    -  tmpStubs.set(goog.userAgent, 'IE', true);
    -  tmpStubs.set(goog.userAgent, 'VERSION', '10.0');
    -  tmpStubs.set(goog.userAgent, 'isVersionOrHigherCache_', {});
    -
    -  // Expect slice to be called with no change to parameters
    -  assertArrayEquals([2, 10], goog.fs.sliceBlob(blob, 2));
    -  assertArrayEquals([-2, 10], goog.fs.sliceBlob(blob, -2));
    -  assertArrayEquals([3, 6], goog.fs.sliceBlob(blob, 3, 6));
    -  assertArrayEquals([3, -6], goog.fs.sliceBlob(blob, 3, -6));
    -
    -  // Simulate Firefox 4 that implements the old slice.
    -  tmpStubs.set(goog.userAgent, 'GECKO', true);
    -  tmpStubs.set(goog.userAgent, 'WEBKIT', false);
    -  tmpStubs.set(goog.userAgent, 'IE', false);
    -  tmpStubs.set(goog.userAgent, 'VERSION', '2.0');
    -  tmpStubs.set(goog.userAgent, 'isVersionOrHigherCache_', {});
    -
    -  // Expect slice to be called with transformed parameters.
    -  assertArrayEquals([2, 8], goog.fs.sliceBlob(blob, 2));
    -  assertArrayEquals([8, 2], goog.fs.sliceBlob(blob, -2));
    -  assertArrayEquals([3, 3], goog.fs.sliceBlob(blob, 3, 6));
    -  assertArrayEquals([3, 1], goog.fs.sliceBlob(blob, 3, -6));
    -
    -  // Simulate Firefox 5 that implements mozSlice (new spec).
    -  delete blob.slice;
    -  blob.mozSlice = function(start, end) {
    -    return ['moz', start, end];
    -  };
    -  tmpStubs.set(goog.userAgent, 'GECKO', true);
    -  tmpStubs.set(goog.userAgent, 'WEBKIT', false);
    -  tmpStubs.set(goog.userAgent, 'IE', false);
    -  tmpStubs.set(goog.userAgent, 'VERSION', '5.0');
    -  tmpStubs.set(goog.userAgent, 'isVersionOrHigherCache_', {});
    -
    -  // Expect mozSlice to be called with no change to parameters.
    -  assertArrayEquals(['moz', 2, 10], goog.fs.sliceBlob(blob, 2));
    -  assertArrayEquals(['moz', -2, 10], goog.fs.sliceBlob(blob, -2));
    -  assertArrayEquals(['moz', 3, 6], goog.fs.sliceBlob(blob, 3, 6));
    -  assertArrayEquals(['moz', 3, -6], goog.fs.sliceBlob(blob, 3, -6));
    -
    -  // Simulate Chrome 20 that implements webkitSlice (new spec).
    -  delete blob.mozSlice;
    -  blob.webkitSlice = function(start, end) {
    -    return ['webkit', start, end];
    -  };
    -  tmpStubs.set(goog.userAgent, 'GECKO', false);
    -  tmpStubs.set(goog.userAgent, 'WEBKIT', true);
    -  tmpStubs.set(goog.userAgent, 'IE', false);
    -  tmpStubs.set(goog.userAgent, 'VERSION', '536.10');
    -  tmpStubs.set(goog.userAgent, 'isVersionOrHigherCache_', {});
    -
    -  // Expect webkitSlice to be called with no change to parameters.
    -  assertArrayEquals(['webkit', 2, 10], goog.fs.sliceBlob(blob, 2));
    -  assertArrayEquals(['webkit', -2, 10], goog.fs.sliceBlob(blob, -2));
    -  assertArrayEquals(['webkit', 3, 6], goog.fs.sliceBlob(blob, 3, 6));
    -  assertArrayEquals(['webkit', 3, -6], goog.fs.sliceBlob(blob, 3, -6));
    -
    -  tmpStubs.reset();
    -}
    -
    -
    -function testBrowserSupportsObjectUrls() {
    -  stubs.remove(goog.global, 'URL');
    -  stubs.remove(goog.global, 'webkitURL');
    -  stubs.remove(goog.global, 'createObjectURL');
    -
    -  assertFalse(goog.fs.browserSupportsObjectUrls());
    -  try {
    -    goog.fs.createObjectUrl();
    -    fail();
    -  } catch (e) {
    -    assertEquals('This browser doesn\'t seem to support blob URLs', e.message);
    -  }
    -
    -  var objectUrl = {};
    -  function createObjectURL() { return objectUrl; }
    -  stubs.set(goog.global, 'createObjectURL', createObjectURL);
    -
    -  assertTrue(goog.fs.browserSupportsObjectUrls());
    -  assertEquals(objectUrl, goog.fs.createObjectUrl());
    -
    -  stubs.reset();
    -}
    -
    -
    -function testGetBlobThrowsError() {
    -  stubs.remove(goog.global, 'BlobBuilder');
    -  stubs.remove(goog.global, 'WebKitBlobBuilder');
    -  stubs.remove(goog.global, 'Blob');
    -
    -  try {
    -    goog.fs.getBlob();
    -    fail();
    -  } catch (e) {
    -    assertEquals('This browser doesn\'t seem to support creating Blobs',
    -        e.message);
    -  }
    -
    -  stubs.reset();
    -}
    -
    -
    -function testGetBlobWithProperties() {
    -  // Skip test if browser doesn't support Blob API.
    -  if (typeof(goog.global.Blob) != 'function') {
    -    return;
    -  }
    -
    -  var blob = goog.fs.getBlobWithProperties(['test'], 'text/test', 'native');
    -  assertEquals('text/test', blob.type);
    -}
    -
    -
    -function testGetBlobWithPropertiesThrowsError() {
    -  stubs.remove(goog.global, 'BlobBuilder');
    -  stubs.remove(goog.global, 'WebKitBlobBuilder');
    -  stubs.remove(goog.global, 'Blob');
    -
    -  try {
    -    goog.fs.getBlobWithProperties();
    -    fail();
    -  } catch (e) {
    -    assertEquals('This browser doesn\'t seem to support creating Blobs',
    -        e.message);
    -  }
    -
    -  stubs.reset();
    -}
    -
    -
    -function testGetBlobWithPropertiesUsingBlobBuilder() {
    -  function BlobBuilder() {
    -    this.parts = [];
    -    this.append = function(value, endings) {
    -      this.parts.push({value: value, endings: endings});
    -    };
    -    this.getBlob = function(type) {
    -      return {type: type, builder: this};
    -    };
    -  }
    -  stubs.set(goog.global, 'BlobBuilder', BlobBuilder);
    -
    -  var blob = goog.fs.getBlobWithProperties(['test'], 'text/test', 'native');
    -  assertEquals('text/test', blob.type);
    -  assertEquals('test', blob.builder.parts[0].value);
    -  assertEquals('native', blob.builder.parts[0].endings);
    -
    -  stubs.reset();
    -}
    -
    -
    -function loadTestDir() {
    -  return deferredFs.then(function(fs) {
    -    return fs.getRoot().getDirectory(
    -        TEST_DIR, goog.fs.DirectoryEntry.Behavior.CREATE);
    -  });
    -}
    -
    -function loadFile(filename, behavior) {
    -  return loadTestDir().then(function(dir) {
    -    return dir.getFile(filename, behavior);
    -  });
    -}
    -
    -function loadDirectory(filename, behavior) {
    -  return loadTestDir().then(function(dir) {
    -    return dir.getDirectory(filename, behavior);
    -  });
    -}
    -
    -function startWrite(content, file) {
    -  return file.createWriter().
    -      then(goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.INIT)).
    -      then(function(writer) {
    -        writer.write(goog.fs.getBlob(content));
    -        return writer;
    -      }).
    -      then(goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.WRITING));
    -}
    -
    -function waitForEvent(type, target) {
    -  var done;
    -  var promise = new goog.Promise(function(_done) { done = _done; });
    -  goog.events.listenOnce(target, type, done);
    -  return promise;
    -}
    -
    -function writeToFile(content, file) {
    -  return startWrite(content, file).
    -      then(goog.partial(waitForEvent, goog.fs.FileSaver.EventType.WRITE)).
    -      then(function() { return file; });
    -}
    -
    -function checkFileContent(content, file) {
    -  return checkFileContentAs(content, 'Text', undefined, file);
    -}
    -
    -function checkFileContentWithEncoding(content, encoding, file) {
    -  return checkFileContentAs(content, 'Text', encoding, file);
    -}
    -
    -function checkFileContentAs(content, filetype, encoding, file) {
    -  return file.file().
    -      then(function(blob) {
    -        return goog.fs.FileReader['readAs' + filetype](blob, encoding);
    -      }).
    -      then(goog.partial(checkEquals, content));
    -}
    -
    -function checkEquals(a, b) {
    -  if (a instanceof ArrayBuffer && b instanceof ArrayBuffer) {
    -    assertEquals(a.byteLength, b.byteLength);
    -    var viewA = new DataView(a);
    -    var viewB = new DataView(b);
    -    for (var i = 0; i < a.byteLength; i++) {
    -      assertEquals(viewA.getUint8(i), viewB.getUint8(i));
    -    }
    -  } else {
    -    assertEquals(a, b);
    -  }
    -}
    -
    -function checkFileRemoved(filename) {
    -  return loadFile(filename).then(
    -      goog.partial(fail, 'expected file to be removed'),
    -      function(err) {
    -        assertEquals(err.code, goog.fs.Error.ErrorCode.NOT_FOUND);
    -      });
    -}
    -
    -function checkReadyState(expectedState, writer) {
    -  assertEquals(expectedState, writer.getReadyState());
    -  return writer;
    -}
    -
    -function splitArgs(fn) {
    -  return function(args) { return fn(args[0], args[1]); };
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/fs/progressevent.js b/src/database/third_party/closure-library/closure/goog/fs/progressevent.js
    deleted file mode 100644
    index b0695bed9d3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fs/progressevent.js
    +++ /dev/null
    @@ -1,69 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A wrapper for the HTML5 File ProgressEvent objects.
    - *
    - */
    -goog.provide('goog.fs.ProgressEvent');
    -
    -goog.require('goog.events.Event');
    -
    -
    -
    -/**
    - * A wrapper for the progress events emitted by the File APIs.
    - *
    - * @param {!ProgressEvent} event The underlying event object.
    - * @param {!Object} target The file access object emitting the event.
    - * @extends {goog.events.Event}
    - * @constructor
    - * @final
    - */
    -goog.fs.ProgressEvent = function(event, target) {
    -  goog.fs.ProgressEvent.base(this, 'constructor', event.type, target);
    -
    -  /**
    -   * The underlying event object.
    -   * @type {!ProgressEvent}
    -   * @private
    -   */
    -  this.event_ = event;
    -};
    -goog.inherits(goog.fs.ProgressEvent, goog.events.Event);
    -
    -
    -/**
    - * @return {boolean} Whether or not the total size of the of the file being
    - *     saved is known.
    - */
    -goog.fs.ProgressEvent.prototype.isLengthComputable = function() {
    -  return this.event_.lengthComputable;
    -};
    -
    -
    -/**
    - * @return {number} The number of bytes saved so far.
    - */
    -goog.fs.ProgressEvent.prototype.getLoaded = function() {
    -  return this.event_.loaded;
    -};
    -
    -
    -/**
    - * @return {number} The total number of bytes in the file being saved.
    - */
    -goog.fs.ProgressEvent.prototype.getTotal = function() {
    -  return this.event_.total;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/functions/functions.js b/src/database/third_party/closure-library/closure/goog/functions/functions.js
    deleted file mode 100644
    index d7ccf403f50..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/functions/functions.js
    +++ /dev/null
    @@ -1,332 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Utilities for creating functions. Loosely inspired by the
    - * java classes: http://goo.gl/GM0Hmu and http://goo.gl/6k7nI8.
    - *
    - * @author nicksantos@google.com (Nick Santos)
    - */
    -
    -
    -goog.provide('goog.functions');
    -
    -
    -/**
    - * Creates a function that always returns the same value.
    - * @param {T} retValue The value to return.
    - * @return {function():T} The new function.
    - * @template T
    - */
    -goog.functions.constant = function(retValue) {
    -  return function() {
    -    return retValue;
    -  };
    -};
    -
    -
    -/**
    - * Always returns false.
    - * @type {function(...): boolean}
    - */
    -goog.functions.FALSE = goog.functions.constant(false);
    -
    -
    -/**
    - * Always returns true.
    - * @type {function(...): boolean}
    - */
    -goog.functions.TRUE = goog.functions.constant(true);
    -
    -
    -/**
    - * Always returns NULL.
    - * @type {function(...): null}
    - */
    -goog.functions.NULL = goog.functions.constant(null);
    -
    -
    -/**
    - * A simple function that returns the first argument of whatever is passed
    - * into it.
    - * @param {T=} opt_returnValue The single value that will be returned.
    - * @param {...*} var_args Optional trailing arguments. These are ignored.
    - * @return {T} The first argument passed in, or undefined if nothing was passed.
    - * @template T
    - */
    -goog.functions.identity = function(opt_returnValue, var_args) {
    -  return opt_returnValue;
    -};
    -
    -
    -/**
    - * Creates a function that always throws an error with the given message.
    - * @param {string} message The error message.
    - * @return {!Function} The error-throwing function.
    - */
    -goog.functions.error = function(message) {
    -  return function() {
    -    throw Error(message);
    -  };
    -};
    -
    -
    -/**
    - * Creates a function that throws the given object.
    - * @param {*} err An object to be thrown.
    - * @return {!Function} The error-throwing function.
    - */
    -goog.functions.fail = function(err) {
    -  return function() {
    -    throw err;
    -  }
    -};
    -
    -
    -/**
    - * Given a function, create a function that keeps opt_numArgs arguments and
    - * silently discards all additional arguments.
    - * @param {Function} f The original function.
    - * @param {number=} opt_numArgs The number of arguments to keep. Defaults to 0.
    - * @return {!Function} A version of f that only keeps the first opt_numArgs
    - *     arguments.
    - */
    -goog.functions.lock = function(f, opt_numArgs) {
    -  opt_numArgs = opt_numArgs || 0;
    -  return function() {
    -    return f.apply(this, Array.prototype.slice.call(arguments, 0, opt_numArgs));
    -  };
    -};
    -
    -
    -/**
    - * Creates a function that returns its nth argument.
    - * @param {number} n The position of the return argument.
    - * @return {!Function} A new function.
    - */
    -goog.functions.nth = function(n) {
    -  return function() {
    -    return arguments[n];
    -  };
    -};
    -
    -
    -/**
    - * Given a function, create a new function that swallows its return value
    - * and replaces it with a new one.
    - * @param {Function} f A function.
    - * @param {T} retValue A new return value.
    - * @return {function(...?):T} A new function.
    - * @template T
    - */
    -goog.functions.withReturnValue = function(f, retValue) {
    -  return goog.functions.sequence(f, goog.functions.constant(retValue));
    -};
    -
    -
    -/**
    - * Creates a function that returns whether its arguement equals the given value.
    - *
    - * Example:
    - * var key = goog.object.findKey(obj, goog.functions.equalTo('needle'));
    - *
    - * @param {*} value The value to compare to.
    - * @param {boolean=} opt_useLooseComparison Whether to use a loose (==)
    - *     comparison rather than a strict (===) one. Defaults to false.
    - * @return {function(*):boolean} The new function.
    - */
    -goog.functions.equalTo = function(value, opt_useLooseComparison) {
    -  return function(other) {
    -    return opt_useLooseComparison ? (value == other) : (value === other);
    -  };
    -};
    -
    -
    -/**
    - * Creates the composition of the functions passed in.
    - * For example, (goog.functions.compose(f, g))(a) is equivalent to f(g(a)).
    - * @param {function(...?):T} fn The final function.
    - * @param {...Function} var_args A list of functions.
    - * @return {function(...?):T} The composition of all inputs.
    - * @template T
    - */
    -goog.functions.compose = function(fn, var_args) {
    -  var functions = arguments;
    -  var length = functions.length;
    -  return function() {
    -    var result;
    -    if (length) {
    -      result = functions[length - 1].apply(this, arguments);
    -    }
    -
    -    for (var i = length - 2; i >= 0; i--) {
    -      result = functions[i].call(this, result);
    -    }
    -    return result;
    -  };
    -};
    -
    -
    -/**
    - * Creates a function that calls the functions passed in in sequence, and
    - * returns the value of the last function. For example,
    - * (goog.functions.sequence(f, g))(x) is equivalent to f(x),g(x).
    - * @param {...Function} var_args A list of functions.
    - * @return {!Function} A function that calls all inputs in sequence.
    - */
    -goog.functions.sequence = function(var_args) {
    -  var functions = arguments;
    -  var length = functions.length;
    -  return function() {
    -    var result;
    -    for (var i = 0; i < length; i++) {
    -      result = functions[i].apply(this, arguments);
    -    }
    -    return result;
    -  };
    -};
    -
    -
    -/**
    - * Creates a function that returns true if each of its components evaluates
    - * to true. The components are evaluated in order, and the evaluation will be
    - * short-circuited as soon as a function returns false.
    - * For example, (goog.functions.and(f, g))(x) is equivalent to f(x) && g(x).
    - * @param {...Function} var_args A list of functions.
    - * @return {function(...?):boolean} A function that ANDs its component
    - *      functions.
    - */
    -goog.functions.and = function(var_args) {
    -  var functions = arguments;
    -  var length = functions.length;
    -  return function() {
    -    for (var i = 0; i < length; i++) {
    -      if (!functions[i].apply(this, arguments)) {
    -        return false;
    -      }
    -    }
    -    return true;
    -  };
    -};
    -
    -
    -/**
    - * Creates a function that returns true if any of its components evaluates
    - * to true. The components are evaluated in order, and the evaluation will be
    - * short-circuited as soon as a function returns true.
    - * For example, (goog.functions.or(f, g))(x) is equivalent to f(x) || g(x).
    - * @param {...Function} var_args A list of functions.
    - * @return {function(...?):boolean} A function that ORs its component
    - *    functions.
    - */
    -goog.functions.or = function(var_args) {
    -  var functions = arguments;
    -  var length = functions.length;
    -  return function() {
    -    for (var i = 0; i < length; i++) {
    -      if (functions[i].apply(this, arguments)) {
    -        return true;
    -      }
    -    }
    -    return false;
    -  };
    -};
    -
    -
    -/**
    - * Creates a function that returns the Boolean opposite of a provided function.
    - * For example, (goog.functions.not(f))(x) is equivalent to !f(x).
    - * @param {!Function} f The original function.
    - * @return {function(...?):boolean} A function that delegates to f and returns
    - * opposite.
    - */
    -goog.functions.not = function(f) {
    -  return function() {
    -    return !f.apply(this, arguments);
    -  };
    -};
    -
    -
    -/**
    - * Generic factory function to construct an object given the constructor
    - * and the arguments. Intended to be bound to create object factories.
    - *
    - * Example:
    - *
    - * var factory = goog.partial(goog.functions.create, Class);
    - *
    - * @param {function(new:T, ...)} constructor The constructor for the Object.
    - * @param {...*} var_args The arguments to be passed to the constructor.
    - * @return {T} A new instance of the class given in {@code constructor}.
    - * @template T
    - */
    -goog.functions.create = function(constructor, var_args) {
    -  /**
    -   * @constructor
    -   * @final
    -   */
    -  var temp = function() {};
    -  temp.prototype = constructor.prototype;
    -
    -  // obj will have constructor's prototype in its chain and
    -  // 'obj instanceof constructor' will be true.
    -  var obj = new temp();
    -
    -  // obj is initialized by constructor.
    -  // arguments is only array-like so lacks shift(), but can be used with
    -  // the Array prototype function.
    -  constructor.apply(obj, Array.prototype.slice.call(arguments, 1));
    -  return obj;
    -};
    -
    -
    -/**
    - * @define {boolean} Whether the return value cache should be used.
    - *    This should only be used to disable caches when testing.
    - */
    -goog.define('goog.functions.CACHE_RETURN_VALUE', true);
    -
    -
    -/**
    - * Gives a wrapper function that caches the return value of a parameterless
    - * function when first called.
    - *
    - * When called for the first time, the given function is called and its
    - * return value is cached (thus this is only appropriate for idempotent
    - * functions).  Subsequent calls will return the cached return value. This
    - * allows the evaluation of expensive functions to be delayed until first used.
    - *
    - * To cache the return values of functions with parameters, see goog.memoize.
    - *
    - * @param {!function():T} fn A function to lazily evaluate.
    - * @return {!function():T} A wrapped version the function.
    - * @template T
    - */
    -goog.functions.cacheReturnValue = function(fn) {
    -  var called = false;
    -  var value;
    -
    -  return function() {
    -    if (!goog.functions.CACHE_RETURN_VALUE) {
    -      return fn();
    -    }
    -
    -    if (!called) {
    -      value = fn();
    -      called = true;
    -    }
    -
    -    return value;
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/functions/functions_test.html b/src/database/third_party/closure-library/closure/goog/functions/functions_test.html
    deleted file mode 100644
    index 0b45c154fba..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/functions/functions_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -
    -  @author nicksantos@google.com (Nick Santos)
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.functions</title>
    -<script src="../base.js"></script>
    -<script>
    -goog.require('goog.functionsTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/functions/functions_test.js b/src/database/third_party/closure-library/closure/goog/functions/functions_test.js
    deleted file mode 100644
    index 411f1b3c0a6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/functions/functions_test.js
    +++ /dev/null
    @@ -1,313 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.functions.
    - */
    -
    -goog.provide('goog.functionsTest');
    -goog.setTestOnly('goog.functionsTest');
    -
    -goog.require('goog.functions');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -
    -
    -var fTrue = makeCallOrderLogger('fTrue', true);
    -var gFalse = makeCallOrderLogger('gFalse', false);
    -var hTrue = makeCallOrderLogger('hTrue', true);
    -
    -var stubs = new goog.testing.PropertyReplacer();
    -
    -function setUp() {
    -  callOrder = [];
    -}
    -
    -function tearDown() {
    -  stubs.reset();
    -}
    -
    -function testTrue() {
    -  assertTrue(goog.functions.TRUE());
    -}
    -
    -function testFalse() {
    -  assertFalse(goog.functions.FALSE());
    -}
    -
    -function testLock() {
    -  function add(var_args) {
    -    var result = 0;
    -    for (var i = 0; i < arguments.length; i++) {
    -      result += arguments[i];
    -    }
    -    return result;
    -  }
    -
    -  assertEquals(6, add(1, 2, 3));
    -  assertEquals(0, goog.functions.lock(add)(1, 2, 3));
    -  assertEquals(3, goog.functions.lock(add, 2)(1, 2, 3));
    -  assertEquals(6, goog.partial(add, 1, 2)(3));
    -  assertEquals(3, goog.functions.lock(goog.partial(add, 1, 2))(3));
    -}
    -
    -function testNth() {
    -  assertEquals(1, goog.functions.nth(0)(1));
    -  assertEquals(2, goog.functions.nth(1)(1, 2));
    -  assertEquals('a', goog.functions.nth(0)('a', 'b'));
    -  assertEquals(undefined, goog.functions.nth(0)());
    -  assertEquals(undefined, goog.functions.nth(1)(true));
    -  assertEquals(undefined, goog.functions.nth(-1)());
    -}
    -
    -function testIdentity() {
    -  assertEquals(3, goog.functions.identity(3));
    -  assertEquals(3, goog.functions.identity(3, 4, 5, 6));
    -  assertEquals('Hi there', goog.functions.identity('Hi there'));
    -  assertEquals(null, goog.functions.identity(null));
    -  assertEquals(undefined, goog.functions.identity());
    -
    -  var arr = [1, 'b', null];
    -  assertEquals(arr, goog.functions.identity(arr));
    -  var obj = {a: 'ay', b: 'bee', c: 'see'};
    -  assertEquals(obj, goog.functions.identity(obj));
    -}
    -
    -function testConstant() {
    -  assertEquals(3, goog.functions.constant(3)());
    -  assertEquals(undefined, goog.functions.constant()());
    -}
    -
    -function testError() {
    -  var f = goog.functions.error('x');
    -  var e = assertThrows(
    -      'A function created by goog.functions.error must throw an error', f);
    -  assertEquals('x', e.message);
    -}
    -
    -function testFail() {
    -  var obj = {};
    -  var f = goog.functions.fail(obj);
    -  var e = assertThrows(
    -      'A function created by goog.functions.raise must throw its input', f);
    -  assertEquals(obj, e);
    -}
    -
    -function testCompose() {
    -  var add2 = function(x) {
    -    return x + 2;
    -  };
    -
    -  var doubleValue = function(x) {
    -    return x * 2;
    -  };
    -
    -  assertEquals(6, goog.functions.compose(doubleValue, add2)(1));
    -  assertEquals(4, goog.functions.compose(add2, doubleValue)(1));
    -  assertEquals(6, goog.functions.compose(add2, add2, doubleValue)(1));
    -  assertEquals(12,
    -      goog.functions.compose(doubleValue, add2, add2, doubleValue)(1));
    -  assertUndefined(goog.functions.compose()(1));
    -  assertEquals(3, goog.functions.compose(add2)(1));
    -
    -  var add2Numbers = function(x, y) {
    -    return x + y;
    -  };
    -  assertEquals(17, goog.functions.compose(add2Numbers)(10, 7));
    -  assertEquals(34, goog.functions.compose(doubleValue, add2Numbers)(10, 7));
    -}
    -
    -function testAdd() {
    -  assertUndefined(goog.functions.sequence()());
    -  assertCallOrderAndReset([]);
    -
    -  assert(goog.functions.sequence(fTrue)());
    -  assertCallOrderAndReset(['fTrue']);
    -
    -  assertFalse(goog.functions.sequence(fTrue, gFalse)());
    -  assertCallOrderAndReset(['fTrue', 'gFalse']);
    -
    -  assert(goog.functions.sequence(fTrue, gFalse, hTrue)());
    -  assertCallOrderAndReset(['fTrue', 'gFalse', 'hTrue']);
    -
    -  assert(goog.functions.sequence(goog.functions.identity)(true));
    -  assertFalse(goog.functions.sequence(goog.functions.identity)(false));
    -}
    -
    -function testAnd() {
    -  // the return value is unspecified for an empty and
    -  goog.functions.and()();
    -  assertCallOrderAndReset([]);
    -
    -  assert(goog.functions.and(fTrue)());
    -  assertCallOrderAndReset(['fTrue']);
    -
    -  assertFalse(goog.functions.and(fTrue, gFalse)());
    -  assertCallOrderAndReset(['fTrue', 'gFalse']);
    -
    -  assertFalse(goog.functions.and(fTrue, gFalse, hTrue)());
    -  assertCallOrderAndReset(['fTrue', 'gFalse']);
    -
    -  assert(goog.functions.and(goog.functions.identity)(true));
    -  assertFalse(goog.functions.and(goog.functions.identity)(false));
    -}
    -
    -function testOr() {
    -  // the return value is unspecified for an empty or
    -  goog.functions.or()();
    -  assertCallOrderAndReset([]);
    -
    -  assert(goog.functions.or(fTrue)());
    -  assertCallOrderAndReset(['fTrue']);
    -
    -  assert(goog.functions.or(fTrue, gFalse)());
    -  assertCallOrderAndReset(['fTrue']);
    -
    -  assert(goog.functions.or(fTrue, gFalse, hTrue)());
    -  assertCallOrderAndReset(['fTrue']);
    -
    -  assert(goog.functions.or(goog.functions.identity)(true));
    -  assertFalse(goog.functions.or(goog.functions.identity)(false));
    -}
    -
    -function testNot() {
    -  assertTrue(goog.functions.not(gFalse)());
    -  assertCallOrderAndReset(['gFalse']);
    -
    -  assertTrue(goog.functions.not(goog.functions.identity)(false));
    -  assertFalse(goog.functions.not(goog.functions.identity)(true));
    -
    -  var f = function(a, b) {
    -    assertEquals(1, a);
    -    assertEquals(2, b);
    -    return false;
    -  };
    -
    -  assertTrue(goog.functions.not(f)(1, 2));
    -}
    -
    -function testCreate(expectedArray) {
    -  var tempConstructor = function(a, b) {
    -    this.foo = a;
    -    this.bar = b;
    -  };
    -
    -  var factory = goog.partial(goog.functions.create, tempConstructor, 'baz');
    -  var instance = factory('qux');
    -
    -  assert(instance instanceof tempConstructor);
    -  assertEquals(instance.foo, 'baz');
    -  assertEquals(instance.bar, 'qux');
    -}
    -
    -function testWithReturnValue() {
    -  var obj = {};
    -  var f = function(a, b) {
    -    assertEquals(obj, this);
    -    assertEquals(1, a);
    -    assertEquals(2, b);
    -  };
    -  assertTrue(goog.functions.withReturnValue(f, true).call(obj, 1, 2));
    -  assertFalse(goog.functions.withReturnValue(f, false).call(obj, 1, 2));
    -}
    -
    -function testEqualTo() {
    -  assertTrue(goog.functions.equalTo(42)(42));
    -  assertFalse(goog.functions.equalTo(42)(13));
    -  assertFalse(goog.functions.equalTo(42)('a string'));
    -
    -  assertFalse(goog.functions.equalTo(42)('42'));
    -  assertTrue(goog.functions.equalTo(42, true)('42'));
    -
    -  assertTrue(goog.functions.equalTo(0)(0));
    -  assertFalse(goog.functions.equalTo(0)(''));
    -  assertFalse(goog.functions.equalTo(0)(1));
    -
    -  assertTrue(goog.functions.equalTo(0, true)(0));
    -  assertTrue(goog.functions.equalTo(0, true)(''));
    -  assertFalse(goog.functions.equalTo(0, true)(1));
    -}
    -
    -function makeCallOrderLogger(name, returnValue) {
    -  return function() {
    -    callOrder.push(name);
    -    return returnValue;
    -  };
    -}
    -
    -function assertCallOrderAndReset(expectedArray) {
    -  assertArrayEquals(expectedArray, callOrder);
    -  callOrder = [];
    -}
    -
    -function testCacheReturnValue() {
    -  var returnFive = function() {
    -    return 5;
    -  };
    -
    -  var recordedReturnFive = goog.testing.recordFunction(returnFive);
    -  var cachedRecordedReturnFive = goog.functions.cacheReturnValue(
    -      recordedReturnFive);
    -
    -  assertEquals(0, recordedReturnFive.getCallCount());
    -  assertEquals(5, cachedRecordedReturnFive());
    -  assertEquals(1, recordedReturnFive.getCallCount());
    -  assertEquals(5, cachedRecordedReturnFive());
    -  assertEquals(1, recordedReturnFive.getCallCount());
    -}
    -
    -
    -function testCacheReturnValueFlagEnabled() {
    -  var count = 0;
    -  var returnIncrementingInteger = function() {
    -    count++;
    -    return count;
    -  };
    -
    -  var recordedFunction = goog.testing.recordFunction(
    -      returnIncrementingInteger);
    -  var cachedRecordedFunction = goog.functions.cacheReturnValue(
    -      recordedFunction);
    -
    -  assertEquals(0, recordedFunction.getCallCount());
    -  assertEquals(1, cachedRecordedFunction());
    -  assertEquals(1, recordedFunction.getCallCount());
    -  assertEquals(1, cachedRecordedFunction());
    -  assertEquals(1, recordedFunction.getCallCount());
    -  assertEquals(1, cachedRecordedFunction());
    -}
    -
    -
    -function testCacheReturnValueFlagDisabled() {
    -  stubs.set(goog.functions, 'CACHE_RETURN_VALUE', false);
    -
    -  var count = 0;
    -  var returnIncrementingInteger = function() {
    -    count++;
    -    return count;
    -  };
    -
    -  var recordedFunction = goog.testing.recordFunction(
    -      returnIncrementingInteger);
    -  var cachedRecordedFunction = goog.functions.cacheReturnValue(
    -      recordedFunction);
    -
    -  assertEquals(0, recordedFunction.getCallCount());
    -  assertEquals(1, cachedRecordedFunction());
    -  assertEquals(1, recordedFunction.getCallCount());
    -  assertEquals(2, cachedRecordedFunction());
    -  assertEquals(2, recordedFunction.getCallCount());
    -  assertEquals(3, cachedRecordedFunction());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/abstractdragdrop.js b/src/database/third_party/closure-library/closure/goog/fx/abstractdragdrop.js
    deleted file mode 100644
    index afd4af8c9fd..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/abstractdragdrop.js
    +++ /dev/null
    @@ -1,1540 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Abstract Base Class for Drag and Drop.
    - *
    - * Provides functionality for implementing drag and drop classes. Also provides
    - * support classes and events.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - */
    -
    -goog.provide('goog.fx.AbstractDragDrop');
    -goog.provide('goog.fx.AbstractDragDrop.EventType');
    -goog.provide('goog.fx.DragDropEvent');
    -goog.provide('goog.fx.DragDropItem');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -goog.require('goog.fx.Dragger');
    -goog.require('goog.math.Box');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.style');
    -
    -
    -
    -/**
    - * Abstract class that provides reusable functionality for implementing drag
    - * and drop functionality.
    - *
    - * This class also allows clients to define their own subtargeting function
    - * so that drop areas can have finer granularity then a singe element. This is
    - * accomplished by using a client provided function to map from element and
    - * coordinates to a subregion id.
    - *
    - * This class can also be made aware of scrollable containers that contain
    - * drop targets by calling addScrollableContainer. This will cause dnd to
    - * take changing scroll positions into account while a drag is occuring.
    - *
    - * @extends {goog.events.EventTarget}
    - * @constructor
    - */
    -goog.fx.AbstractDragDrop = function() {
    -  goog.fx.AbstractDragDrop.base(this, 'constructor');
    -
    -  /**
    -   * List of items that makes up the drag source or drop target.
    -   * @type {Array<goog.fx.DragDropItem>}
    -   * @protected
    -   * @suppress {underscore|visibility}
    -   */
    -  this.items_ = [];
    -
    -  /**
    -   * List of associated drop targets.
    -   * @type {Array<goog.fx.AbstractDragDrop>}
    -   * @private
    -   */
    -  this.targets_ = [];
    -
    -  /**
    -   * Scrollable containers to account for during drag
    -   * @type {Array<goog.fx.ScrollableContainer_>}
    -   * @private
    -   */
    -  this.scrollableContainers_ = [];
    -
    -};
    -goog.inherits(goog.fx.AbstractDragDrop, goog.events.EventTarget);
    -
    -
    -/**
    - * Minimum size (in pixels) for a dummy target. If the box for the target is
    - * less than the specified size it's not created.
    - * @type {number}
    - * @private
    - */
    -goog.fx.AbstractDragDrop.DUMMY_TARGET_MIN_SIZE_ = 10;
    -
    -
    -/**
    - * Flag indicating if it's a drag source, set by addTarget.
    - * @type {boolean}
    - * @private
    - */
    -goog.fx.AbstractDragDrop.prototype.isSource_ = false;
    -
    -
    -/**
    - * Flag indicating if it's a drop target, set when added as target to another
    - * DragDrop object.
    - * @type {boolean}
    - * @private
    - */
    -goog.fx.AbstractDragDrop.prototype.isTarget_ = false;
    -
    -
    -/**
    - * Subtargeting function accepting args:
    - * (goog.fx.DragDropItem, goog.math.Box, number, number)
    - * @type {Function}
    - * @private
    - */
    -goog.fx.AbstractDragDrop.prototype.subtargetFunction_;
    -
    -
    -/**
    - * Last active subtarget.
    - * @type {Object}
    - * @private
    - */
    -goog.fx.AbstractDragDrop.prototype.activeSubtarget_;
    -
    -
    -/**
    - * Class name to add to source elements being dragged. Set by setDragClass.
    - * @type {?string}
    - * @private
    - */
    -goog.fx.AbstractDragDrop.prototype.dragClass_;
    -
    -
    -/**
    - * Class name to add to source elements. Set by setSourceClass.
    - * @type {?string}
    - * @private
    - */
    -goog.fx.AbstractDragDrop.prototype.sourceClass_;
    -
    -
    -/**
    - * Class name to add to target elements. Set by setTargetClass.
    - * @type {?string}
    - * @private
    - */
    -goog.fx.AbstractDragDrop.prototype.targetClass_;
    -
    -
    -/**
    - * The SCROLL event target used to make drag element follow scrolling.
    - * @type {EventTarget}
    - * @private
    - */
    -goog.fx.AbstractDragDrop.prototype.scrollTarget_;
    -
    -
    -/**
    - * Dummy target, {@see maybeCreateDummyTargetForPosition_}.
    - * @type {goog.fx.ActiveDropTarget_}
    - * @private
    - */
    -goog.fx.AbstractDragDrop.prototype.dummyTarget_;
    -
    -
    -/**
    - * Whether the object has been initialized.
    - * @type {boolean}
    - * @private
    - */
    -goog.fx.AbstractDragDrop.prototype.initialized_ = false;
    -
    -
    -/**
    - * Constants for event names
    - * @const
    - */
    -goog.fx.AbstractDragDrop.EventType = {
    -  DRAGOVER: 'dragover',
    -  DRAGOUT: 'dragout',
    -  DRAG: 'drag',
    -  DROP: 'drop',
    -  DRAGSTART: 'dragstart',
    -  DRAGEND: 'dragend'
    -};
    -
    -
    -/**
    - * Constant for distance threshold, in pixels, an element has to be moved to
    - * initiate a drag operation.
    - * @type {number}
    - */
    -goog.fx.AbstractDragDrop.initDragDistanceThreshold = 5;
    -
    -
    -/**
    - * Set class to add to source elements being dragged.
    - *
    - * @param {string} className Class to be added.  Must be a single, valid
    - *     classname.
    - */
    -goog.fx.AbstractDragDrop.prototype.setDragClass = function(className) {
    -  this.dragClass_ = className;
    -};
    -
    -
    -/**
    - * Set class to add to source elements.
    - *
    - * @param {string} className Class to be added.  Must be a single, valid
    - *     classname.
    - */
    -goog.fx.AbstractDragDrop.prototype.setSourceClass = function(className) {
    -  this.sourceClass_ = className;
    -};
    -
    -
    -/**
    - * Set class to add to target elements.
    - *
    - * @param {string} className Class to be added.  Must be a single, valid
    - *     classname.
    - */
    -goog.fx.AbstractDragDrop.prototype.setTargetClass = function(className) {
    -  this.targetClass_ = className;
    -};
    -
    -
    -/**
    - * Whether the control has been initialized.
    - *
    - * @return {boolean} True if it's been initialized.
    - */
    -goog.fx.AbstractDragDrop.prototype.isInitialized = function() {
    -  return this.initialized_;
    -};
    -
    -
    -/**
    - * Add item to drag object.
    - *
    - * @param {Element|string} element Dom Node, or string representation of node
    - *     id, to be used as drag source/drop target.
    - * @throws Error Thrown if called on instance of abstract class
    - */
    -goog.fx.AbstractDragDrop.prototype.addItem = goog.abstractMethod;
    -
    -
    -/**
    - * Associate drop target with drag element.
    - *
    - * @param {goog.fx.AbstractDragDrop} target Target to add.
    - */
    -goog.fx.AbstractDragDrop.prototype.addTarget = function(target) {
    -  this.targets_.push(target);
    -  target.isTarget_ = true;
    -  this.isSource_ = true;
    -};
    -
    -
    -/**
    - * Sets the SCROLL event target to make drag element follow scrolling.
    - *
    - * @param {EventTarget} scrollTarget The element that dispatches SCROLL events.
    - */
    -goog.fx.AbstractDragDrop.prototype.setScrollTarget = function(scrollTarget) {
    -  this.scrollTarget_ = scrollTarget;
    -};
    -
    -
    -/**
    - * Initialize drag and drop functionality for sources/targets already added.
    - * Sources/targets added after init has been called will initialize themselves
    - * one by one.
    - */
    -goog.fx.AbstractDragDrop.prototype.init = function() {
    -  if (this.initialized_) {
    -    return;
    -  }
    -  for (var item, i = 0; item = this.items_[i]; i++) {
    -    this.initItem(item);
    -  }
    -
    -  this.initialized_ = true;
    -};
    -
    -
    -/**
    - * Initializes a single item.
    - *
    - * @param {goog.fx.DragDropItem} item Item to initialize.
    - * @protected
    - */
    -goog.fx.AbstractDragDrop.prototype.initItem = function(item) {
    -  if (this.isSource_) {
    -    goog.events.listen(item.element, goog.events.EventType.MOUSEDOWN,
    -                       item.mouseDown_, false, item);
    -    if (this.sourceClass_) {
    -      goog.dom.classlist.add(
    -          goog.asserts.assert(item.element), this.sourceClass_);
    -    }
    -  }
    -
    -  if (this.isTarget_ && this.targetClass_) {
    -    goog.dom.classlist.add(
    -        goog.asserts.assert(item.element), this.targetClass_);
    -  }
    -};
    -
    -
    -/**
    - * Called when removing an item. Removes event listeners and classes.
    - *
    - * @param {goog.fx.DragDropItem} item Item to dispose.
    - * @protected
    - */
    -goog.fx.AbstractDragDrop.prototype.disposeItem = function(item) {
    -  if (this.isSource_) {
    -    goog.events.unlisten(item.element, goog.events.EventType.MOUSEDOWN,
    -                         item.mouseDown_, false, item);
    -    if (this.sourceClass_) {
    -      goog.dom.classlist.remove(
    -          goog.asserts.assert(item.element), this.sourceClass_);
    -    }
    -  }
    -  if (this.isTarget_ && this.targetClass_) {
    -    goog.dom.classlist.remove(
    -        goog.asserts.assert(item.element), this.targetClass_);
    -  }
    -  item.dispose();
    -};
    -
    -
    -/**
    - * Removes all items.
    - */
    -goog.fx.AbstractDragDrop.prototype.removeItems = function() {
    -  for (var item, i = 0; item = this.items_[i]; i++) {
    -    this.disposeItem(item);
    -  }
    -  this.items_.length = 0;
    -};
    -
    -
    -/**
    - * Starts a drag event for an item if the mouse button stays pressed and the
    - * cursor moves a few pixels. Allows dragging of items without first having to
    - * register them with addItem.
    - *
    - * @param {goog.events.BrowserEvent} event Mouse down event.
    - * @param {goog.fx.DragDropItem} item Item that's being dragged.
    - */
    -goog.fx.AbstractDragDrop.prototype.maybeStartDrag = function(event, item) {
    -  item.maybeStartDrag_(event, item.element);
    -};
    -
    -
    -/**
    - * Event handler that's used to start drag.
    - *
    - * @param {goog.events.BrowserEvent} event Mouse move event.
    - * @param {goog.fx.DragDropItem} item Item that's being dragged.
    - */
    -goog.fx.AbstractDragDrop.prototype.startDrag = function(event, item) {
    -
    -  // Prevent a new drag operation from being started if another one is already
    -  // in progress (could happen if the mouse was released outside of the
    -  // document).
    -  if (this.dragItem_) {
    -    return;
    -  }
    -
    -  this.dragItem_ = item;
    -
    -  // Dispatch DRAGSTART event
    -  var dragStartEvent = new goog.fx.DragDropEvent(
    -      goog.fx.AbstractDragDrop.EventType.DRAGSTART, this, this.dragItem_);
    -  if (this.dispatchEvent(dragStartEvent) == false) {
    -    this.dragItem_ = null;
    -    return;
    -  }
    -
    -  // Get the source element and create a drag element for it.
    -  var el = item.getCurrentDragElement();
    -  this.dragEl_ = this.createDragElement(el);
    -  var doc = goog.dom.getOwnerDocument(el);
    -  doc.body.appendChild(this.dragEl_);
    -
    -  this.dragger_ = this.createDraggerFor(el, this.dragEl_, event);
    -  this.dragger_.setScrollTarget(this.scrollTarget_);
    -
    -  goog.events.listen(this.dragger_, goog.fx.Dragger.EventType.DRAG,
    -                     this.moveDrag_, false, this);
    -
    -  goog.events.listen(this.dragger_, goog.fx.Dragger.EventType.END,
    -                     this.endDrag, false, this);
    -
    -  // IE may issue a 'selectstart' event when dragging over an iframe even when
    -  // default mousemove behavior is suppressed. If the default selectstart
    -  // behavior is not suppressed, elements dragged over will show as selected.
    -  goog.events.listen(doc.body, goog.events.EventType.SELECTSTART,
    -                     this.suppressSelect_);
    -
    -  this.recalculateDragTargets();
    -  this.recalculateScrollableContainers();
    -  this.activeTarget_ = null;
    -  this.initScrollableContainerListeners_();
    -  this.dragger_.startDrag(event);
    -
    -  event.preventDefault();
    -};
    -
    -
    -/**
    - * Recalculates the geometry of this source's drag targets.  Call this
    - * if the position or visibility of a drag target has changed during
    - * a drag, or if targets are added or removed.
    - *
    - * TODO(user): this is an expensive operation;  more efficient APIs
    - * may be necessary.
    - */
    -goog.fx.AbstractDragDrop.prototype.recalculateDragTargets = function() {
    -  this.targetList_ = [];
    -  for (var target, i = 0; target = this.targets_[i]; i++) {
    -    for (var itm, j = 0; itm = target.items_[j]; j++) {
    -      this.addDragTarget_(target, itm);
    -    }
    -  }
    -  if (!this.targetBox_) {
    -    this.targetBox_ = new goog.math.Box(0, 0, 0, 0);
    -  }
    -};
    -
    -
    -/**
    - * Recalculates the current scroll positions of scrollable containers and
    - * allocates targets. Call this if the position of a container changed or if
    - * targets are added or removed.
    - */
    -goog.fx.AbstractDragDrop.prototype.recalculateScrollableContainers =
    -    function() {
    -  var container, i, j, target;
    -  for (i = 0; container = this.scrollableContainers_[i]; i++) {
    -    container.containedTargets_ = [];
    -    container.savedScrollLeft_ = container.element_.scrollLeft;
    -    container.savedScrollTop_ = container.element_.scrollTop;
    -    var pos = goog.style.getPageOffset(container.element_);
    -    var size = goog.style.getSize(container.element_);
    -    container.box_ = new goog.math.Box(pos.y, pos.x + size.width,
    -                                       pos.y + size.height, pos.x);
    -  }
    -
    -  for (i = 0; target = this.targetList_[i]; i++) {
    -    for (j = 0; container = this.scrollableContainers_[j]; j++) {
    -      if (goog.dom.contains(container.element_, target.element_)) {
    -        container.containedTargets_.push(target);
    -        target.scrollableContainer_ = container;
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Creates the Dragger for the drag element.
    - * @param {Element} sourceEl Drag source element.
    - * @param {Element} el the element created by createDragElement().
    - * @param {goog.events.BrowserEvent} event Mouse down event for start of drag.
    - * @return {!goog.fx.Dragger} The new Dragger.
    - * @protected
    - */
    -goog.fx.AbstractDragDrop.prototype.createDraggerFor =
    -    function(sourceEl, el, event) {
    -  // Position the drag element.
    -  var pos = this.getDragElementPosition(sourceEl, el, event);
    -  el.style.position = 'absolute';
    -  el.style.left = pos.x + 'px';
    -  el.style.top = pos.y + 'px';
    -  return new goog.fx.Dragger(el);
    -};
    -
    -
    -/**
    - * Event handler that's used to stop drag. Fires a drop event if over a valid
    - * target.
    - *
    - * @param {goog.fx.DragEvent} event Drag event.
    - */
    -goog.fx.AbstractDragDrop.prototype.endDrag = function(event) {
    -  var activeTarget = event.dragCanceled ? null : this.activeTarget_;
    -  if (activeTarget && activeTarget.target_) {
    -    var clientX = event.clientX;
    -    var clientY = event.clientY;
    -    var scroll = this.getScrollPos();
    -    var x = clientX + scroll.x;
    -    var y = clientY + scroll.y;
    -
    -    var subtarget;
    -    // If a subtargeting function is enabled get the current subtarget
    -    if (this.subtargetFunction_) {
    -      subtarget = this.subtargetFunction_(activeTarget.item_,
    -          activeTarget.box_, x, y);
    -    }
    -
    -    var dragEvent = new goog.fx.DragDropEvent(
    -        goog.fx.AbstractDragDrop.EventType.DRAG, this, this.dragItem_,
    -        activeTarget.target_, activeTarget.item_, activeTarget.element_,
    -        clientX, clientY, x, y);
    -    this.dispatchEvent(dragEvent);
    -
    -    var dropEvent = new goog.fx.DragDropEvent(
    -        goog.fx.AbstractDragDrop.EventType.DROP, this, this.dragItem_,
    -        activeTarget.target_, activeTarget.item_, activeTarget.element_,
    -        clientX, clientY, x, y, subtarget);
    -    activeTarget.target_.dispatchEvent(dropEvent);
    -  }
    -
    -  var dragEndEvent = new goog.fx.DragDropEvent(
    -      goog.fx.AbstractDragDrop.EventType.DRAGEND, this, this.dragItem_);
    -  this.dispatchEvent(dragEndEvent);
    -
    -  goog.events.unlisten(this.dragger_, goog.fx.Dragger.EventType.DRAG,
    -                       this.moveDrag_, false, this);
    -  goog.events.unlisten(this.dragger_, goog.fx.Dragger.EventType.END,
    -                       this.endDrag, false, this);
    -  var doc = goog.dom.getOwnerDocument(this.dragItem_.getCurrentDragElement());
    -  goog.events.unlisten(doc.body, goog.events.EventType.SELECTSTART,
    -                       this.suppressSelect_);
    -
    -
    -  this.afterEndDrag(this.activeTarget_ ? this.activeTarget_.item_ : null);
    -};
    -
    -
    -/**
    - * Called after a drag operation has finished.
    - *
    - * @param {goog.fx.DragDropItem=} opt_dropTarget Target for successful drop.
    - * @protected
    - */
    -goog.fx.AbstractDragDrop.prototype.afterEndDrag = function(opt_dropTarget) {
    -  this.disposeDrag();
    -};
    -
    -
    -/**
    - * Called once a drag operation has finished. Removes event listeners and
    - * elements.
    - *
    - * @protected
    - */
    -goog.fx.AbstractDragDrop.prototype.disposeDrag = function() {
    -  this.disposeScrollableContainerListeners_();
    -  this.dragger_.dispose();
    -
    -  goog.dom.removeNode(this.dragEl_);
    -  delete this.dragItem_;
    -  delete this.dragEl_;
    -  delete this.dragger_;
    -  delete this.targetList_;
    -  delete this.activeTarget_;
    -};
    -
    -
    -/**
    - * Event handler for drag events. Determines the active drop target, if any, and
    - * fires dragover and dragout events appropriately.
    - *
    - * @param {goog.fx.DragEvent} event Drag event.
    - * @private
    - */
    -goog.fx.AbstractDragDrop.prototype.moveDrag_ = function(event) {
    -  var position = this.getEventPosition(event);
    -  var x = position.x;
    -  var y = position.y;
    -
    -  // Check if we're still inside the bounds of the active target, if not fire
    -  // a dragout event and proceed to find a new target.
    -  var activeTarget = this.activeTarget_;
    -
    -  var subtarget;
    -  if (activeTarget) {
    -    // If a subtargeting function is enabled get the current subtarget
    -    if (this.subtargetFunction_ && activeTarget.target_) {
    -      subtarget = this.subtargetFunction_(activeTarget.item_,
    -          activeTarget.box_, x, y);
    -    }
    -
    -    if (activeTarget.box_.contains(position) &&
    -        subtarget == this.activeSubtarget_) {
    -      return;
    -    }
    -
    -    if (activeTarget.target_) {
    -      var sourceDragOutEvent = new goog.fx.DragDropEvent(
    -          goog.fx.AbstractDragDrop.EventType.DRAGOUT, this, this.dragItem_,
    -          activeTarget.target_, activeTarget.item_, activeTarget.element_);
    -      this.dispatchEvent(sourceDragOutEvent);
    -
    -      // The event should be dispatched the by target DragDrop so that the
    -      // target DragDrop can manage these events without having to know what
    -      // sources this is a target for.
    -      var targetDragOutEvent = new goog.fx.DragDropEvent(
    -          goog.fx.AbstractDragDrop.EventType.DRAGOUT,
    -          this,
    -          this.dragItem_,
    -          activeTarget.target_,
    -          activeTarget.item_,
    -          activeTarget.element_,
    -          undefined,
    -          undefined,
    -          undefined,
    -          undefined,
    -          this.activeSubtarget_);
    -      activeTarget.target_.dispatchEvent(targetDragOutEvent);
    -    }
    -    this.activeSubtarget_ = subtarget;
    -    this.activeTarget_ = null;
    -  }
    -
    -  // Check if inside target box
    -  if (this.targetBox_.contains(position)) {
    -    // Search for target and fire a dragover event if found
    -    activeTarget = this.activeTarget_ = this.getTargetFromPosition_(position);
    -    if (activeTarget && activeTarget.target_) {
    -      // If a subtargeting function is enabled get the current subtarget
    -      if (this.subtargetFunction_) {
    -        subtarget = this.subtargetFunction_(activeTarget.item_,
    -            activeTarget.box_, x, y);
    -      }
    -      var sourceDragOverEvent = new goog.fx.DragDropEvent(
    -          goog.fx.AbstractDragDrop.EventType.DRAGOVER, this, this.dragItem_,
    -          activeTarget.target_, activeTarget.item_, activeTarget.element_);
    -      sourceDragOverEvent.subtarget = subtarget;
    -      this.dispatchEvent(sourceDragOverEvent);
    -
    -      // The event should be dispatched by the target DragDrop so that the
    -      // target DragDrop can manage these events without having to know what
    -      // sources this is a target for.
    -      var targetDragOverEvent = new goog.fx.DragDropEvent(
    -          goog.fx.AbstractDragDrop.EventType.DRAGOVER, this, this.dragItem_,
    -          activeTarget.target_, activeTarget.item_, activeTarget.element_,
    -          event.clientX, event.clientY, undefined, undefined, subtarget);
    -      activeTarget.target_.dispatchEvent(targetDragOverEvent);
    -
    -    } else if (!activeTarget) {
    -      // If no target was found create a dummy one so we won't have to iterate
    -      // over all possible targets for every move event.
    -      this.activeTarget_ = this.maybeCreateDummyTargetForPosition_(x, y);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Event handler for suppressing selectstart events. Selecting should be
    - * disabled while dragging.
    - *
    - * @param {goog.events.Event} event The selectstart event to suppress.
    - * @return {boolean} Whether to perform default behavior.
    - * @private
    - */
    -goog.fx.AbstractDragDrop.prototype.suppressSelect_ = function(event) {
    -  return false;
    -};
    -
    -
    -/**
    - * Sets up listeners for the scrollable containers that keep track of their
    - * scroll positions.
    - * @private
    - */
    -goog.fx.AbstractDragDrop.prototype.initScrollableContainerListeners_ =
    -    function() {
    -  var container, i;
    -  for (i = 0; container = this.scrollableContainers_[i]; i++) {
    -    goog.events.listen(container.element_, goog.events.EventType.SCROLL,
    -        this.containerScrollHandler_, false, this);
    -  }
    -};
    -
    -
    -/**
    - * Cleans up the scrollable container listeners.
    - * @private
    - */
    -goog.fx.AbstractDragDrop.prototype.disposeScrollableContainerListeners_ =
    -    function() {
    -  for (var i = 0, container; container = this.scrollableContainers_[i]; i++) {
    -    goog.events.unlisten(container.element_, 'scroll',
    -        this.containerScrollHandler_, false, this);
    -    container.containedTargets_ = [];
    -  }
    -};
    -
    -
    -/**
    - * Makes drag and drop aware of a target container that could scroll mid drag.
    - * @param {Element} element The scroll container.
    - */
    -goog.fx.AbstractDragDrop.prototype.addScrollableContainer = function(element) {
    -  this.scrollableContainers_.push(new goog.fx.ScrollableContainer_(element));
    -};
    -
    -
    -/**
    - * Removes all scrollable containers.
    - */
    -goog.fx.AbstractDragDrop.prototype.removeAllScrollableContainers = function() {
    -  this.disposeScrollableContainerListeners_();
    -  this.scrollableContainers_ = [];
    -};
    -
    -
    -/**
    - * Event handler for containers scrolling.
    - * @param {goog.events.Event} e The event.
    - * @private
    - */
    -goog.fx.AbstractDragDrop.prototype.containerScrollHandler_ = function(e) {
    -  for (var i = 0, container; container = this.scrollableContainers_[i]; i++) {
    -    if (e.target == container.element_) {
    -      var deltaTop = container.savedScrollTop_ - container.element_.scrollTop;
    -      var deltaLeft =
    -          container.savedScrollLeft_ - container.element_.scrollLeft;
    -      container.savedScrollTop_ = container.element_.scrollTop;
    -      container.savedScrollLeft_ = container.element_.scrollLeft;
    -
    -      // When the container scrolls, it's possible that one of the targets will
    -      // move to the region contained by the dummy target. Since we don't know
    -      // which sides (if any) of the dummy target are defined by targets
    -      // contained by this container, we are conservative and just shrink it.
    -      if (this.dummyTarget_ && this.activeTarget_ == this.dummyTarget_) {
    -        if (deltaTop > 0) {
    -          this.dummyTarget_.box_.top += deltaTop;
    -        } else {
    -          this.dummyTarget_.box_.bottom += deltaTop;
    -        }
    -        if (deltaLeft > 0) {
    -          this.dummyTarget_.box_.left += deltaLeft;
    -        } else {
    -          this.dummyTarget_.box_.right += deltaLeft;
    -        }
    -      }
    -      for (var j = 0, target; target = container.containedTargets_[j]; j++) {
    -        var box = target.box_;
    -        box.top += deltaTop;
    -        box.left += deltaLeft;
    -        box.bottom += deltaTop;
    -        box.right += deltaLeft;
    -
    -        this.calculateTargetBox_(box);
    -      }
    -    }
    -  }
    -  this.dragger_.onScroll_(e);
    -};
    -
    -
    -/**
    - * Set a function that provides subtargets. A subtargeting function
    - * returns an arbitrary identifier for each subtarget of an element.
    - * DnD code will generate additional drag over / out events when
    - * switching from subtarget to subtarget. This is useful for instance
    - * if you are interested if you are on the top half or the bottom half
    - * of the element.
    - * The provided function will be given the DragDropItem, box, x, y
    - * box is the current window coordinates occupied by element
    - * x, y is the mouse position in window coordinates
    - *
    - * @param {Function} f The new subtarget function.
    - */
    -goog.fx.AbstractDragDrop.prototype.setSubtargetFunction = function(f) {
    -  this.subtargetFunction_ = f;
    -};
    -
    -
    -/**
    - * Creates an element for the item being dragged.
    - *
    - * @param {Element} sourceEl Drag source element.
    - * @return {Element} The new drag element.
    - */
    -goog.fx.AbstractDragDrop.prototype.createDragElement = function(sourceEl) {
    -  var dragEl = this.createDragElementInternal(sourceEl);
    -  goog.asserts.assert(dragEl);
    -  if (this.dragClass_) {
    -    goog.dom.classlist.add(dragEl, this.dragClass_);
    -  }
    -
    -  return dragEl;
    -};
    -
    -
    -/**
    - * Returns the position for the drag element.
    - *
    - * @param {Element} el Drag source element.
    - * @param {Element} dragEl The dragged element created by createDragElement().
    - * @param {goog.events.BrowserEvent} event Mouse down event for start of drag.
    - * @return {!goog.math.Coordinate} The position for the drag element.
    - */
    -goog.fx.AbstractDragDrop.prototype.getDragElementPosition =
    -    function(el, dragEl, event) {
    -  var pos = goog.style.getPageOffset(el);
    -
    -  // Subtract margin from drag element position twice, once to adjust the
    -  // position given by the original node and once for the drag node.
    -  var marginBox = goog.style.getMarginBox(el);
    -  pos.x -= (marginBox.left || 0) * 2;
    -  pos.y -= (marginBox.top || 0) * 2;
    -
    -  return pos;
    -};
    -
    -
    -/**
    - * Returns the dragger object.
    - *
    - * @return {goog.fx.Dragger} The dragger object used by this drag and drop
    - *     instance.
    - */
    -goog.fx.AbstractDragDrop.prototype.getDragger = function() {
    -  return this.dragger_;
    -};
    -
    -
    -/**
    - * Creates copy of node being dragged.
    - *
    - * @param {Element} sourceEl Element to copy.
    - * @return {!Element} The clone of {@code sourceEl}.
    - * @deprecated Use goog.fx.Dragger.cloneNode().
    - * @private
    - */
    -goog.fx.AbstractDragDrop.prototype.cloneNode_ = function(sourceEl) {
    -  return goog.fx.Dragger.cloneNode(sourceEl);
    -};
    -
    -
    -/**
    - * Generates an element to follow the cursor during dragging, given a drag
    - * source element.  The default behavior is simply to clone the source element,
    - * but this may be overridden in subclasses.  This method is called by
    - * {@code createDragElement()} before the drag class is added.
    - *
    - * @param {Element} sourceEl Drag source element.
    - * @return {!Element} The new drag element.
    - * @protected
    - * @suppress {deprecated}
    - */
    -goog.fx.AbstractDragDrop.prototype.createDragElementInternal =
    -    function(sourceEl) {
    -  return this.cloneNode_(sourceEl);
    -};
    -
    -
    -/**
    - * Add possible drop target for current drag operation.
    - *
    - * @param {goog.fx.AbstractDragDrop} target Drag handler.
    - * @param {goog.fx.DragDropItem} item Item that's being dragged.
    - * @private
    - */
    -goog.fx.AbstractDragDrop.prototype.addDragTarget_ = function(target, item) {
    -
    -  // Get all the draggable elements and add each one.
    -  var draggableElements = item.getDraggableElements();
    -  var targetList = this.targetList_;
    -  for (var i = 0; i < draggableElements.length; i++) {
    -    var draggableElement = draggableElements[i];
    -
    -    // Determine target position and dimension
    -    var box = this.getElementBox(item, draggableElement);
    -
    -    targetList.push(
    -        new goog.fx.ActiveDropTarget_(box, target, item, draggableElement));
    -
    -    this.calculateTargetBox_(box);
    -  }
    -};
    -
    -
    -/**
    - * Calculates the position and dimension of a draggable element.
    - *
    - * @param {goog.fx.DragDropItem} item Item that's being dragged.
    - * @param {Element} element The element to calculate the box.
    - *
    - * @return {!goog.math.Box} Box describing the position and dimension
    - *     of element.
    - * @protected
    - */
    -goog.fx.AbstractDragDrop.prototype.getElementBox = function(item, element) {
    -  var pos = goog.style.getPageOffset(element);
    -  var size = goog.style.getSize(element);
    -  return new goog.math.Box(pos.y, pos.x + size.width, pos.y + size.height,
    -      pos.x);
    -};
    -
    -
    -/**
    - * Calculate the outer bounds (the region all targets are inside).
    - *
    - * @param {goog.math.Box} box Box describing the position and dimension
    - *     of a drag target.
    - * @private
    - */
    -goog.fx.AbstractDragDrop.prototype.calculateTargetBox_ = function(box) {
    -  if (this.targetList_.length == 1) {
    -    this.targetBox_ = new goog.math.Box(box.top, box.right,
    -                                        box.bottom, box.left);
    -  } else {
    -    var tb = this.targetBox_;
    -    tb.left = Math.min(box.left, tb.left);
    -    tb.right = Math.max(box.right, tb.right);
    -    tb.top = Math.min(box.top, tb.top);
    -    tb.bottom = Math.max(box.bottom, tb.bottom);
    -  }
    -};
    -
    -
    -/**
    - * Creates a dummy target for the given cursor position. The assumption is to
    - * create as big dummy target box as possible, the only constraints are:
    - * - The dummy target box cannot overlap any of real target boxes.
    - * - The dummy target has to contain a point with current mouse coordinates.
    - *
    - * NOTE: For performance reasons the box construction algorithm is kept simple
    - * and it is not optimal (see example below). Currently it is O(n) in regard to
    - * the number of real drop target boxes, but its result depends on the order
    - * of those boxes being processed (the order in which they're added to the
    - * targetList_ collection).
    - *
    - * The algorithm.
    - * a) Assumptions
    - * - Mouse pointer is in the bounding box of real target boxes.
    - * - None of the boxes have negative coordinate values.
    - * - Mouse pointer is not contained by any of "real target" boxes.
    - * - For targets inside a scrollable container, the box used is the
    - *   intersection of the scrollable container's box and the target's box.
    - *   This is because the part of the target that extends outside the scrollable
    - *   container should not be used in the clipping calculations.
    - *
    - * b) Outline
    - * - Initialize the fake target to the bounding box of real targets.
    - * - For each real target box - clip the fake target box so it does not contain
    - *   that target box, but does contain the mouse pointer.
    - *   -- Project the real target box, mouse pointer and fake target box onto
    - *      both axes and calculate the clipping coordinates.
    - *   -- Only one coordinate is used to clip the fake target box to keep the
    - *      fake target as big as possible.
    - *   -- If the projection of the real target box contains the mouse pointer,
    - *      clipping for a given axis is not possible.
    - *   -- If both clippings are possible, the clipping more distant from the
    - *      mouse pointer is selected to keep bigger fake target area.
    - * - Save the created fake target only if it has a big enough area.
    - *
    - *
    - * c) Example
    - * <pre>
    - *        Input:           Algorithm created box:        Maximum box:
    - * +---------------------+ +---------------------+ +---------------------+
    - * | B1      |        B2 | | B1               B2 | | B1               B2 |
    - * |         |           | |   +-------------+   | |+-------------------+|
    - * |---------x-----------| |   |             |   | ||                   ||
    - * |         |           | |   |             |   | ||                   ||
    - * |         |           | |   |             |   | ||                   ||
    - * |         |           | |   |             |   | ||                   ||
    - * |         |           | |   |             |   | ||                   ||
    - * |         |           | |   +-------------+   | |+-------------------+|
    - * | B4      |        B3 | | B4               B3 | | B4               B3 |
    - * +---------------------+ +---------------------+ +---------------------+
    - * </pre>
    - *
    - * @param {number} x Cursor position on the x-axis.
    - * @param {number} y Cursor position on the y-axis.
    - * @return {goog.fx.ActiveDropTarget_} Dummy drop target.
    - * @private
    - */
    -goog.fx.AbstractDragDrop.prototype.maybeCreateDummyTargetForPosition_ =
    -    function(x, y) {
    -  if (!this.dummyTarget_) {
    -    this.dummyTarget_ = new goog.fx.ActiveDropTarget_(this.targetBox_.clone());
    -  }
    -  var fakeTargetBox = this.dummyTarget_.box_;
    -
    -  // Initialize the fake target box to the bounding box of DnD targets.
    -  fakeTargetBox.top = this.targetBox_.top;
    -  fakeTargetBox.right = this.targetBox_.right;
    -  fakeTargetBox.bottom = this.targetBox_.bottom;
    -  fakeTargetBox.left = this.targetBox_.left;
    -
    -  // Clip the fake target based on mouse position and DnD target boxes.
    -  for (var i = 0, target; target = this.targetList_[i]; i++) {
    -    var box = target.box_;
    -
    -    if (target.scrollableContainer_) {
    -      // If the target has a scrollable container, use the intersection of that
    -      // container's box and the target's box.
    -      var scrollBox = target.scrollableContainer_.box_;
    -
    -      box = new goog.math.Box(
    -          Math.max(box.top, scrollBox.top),
    -          Math.min(box.right, scrollBox.right),
    -          Math.min(box.bottom, scrollBox.bottom),
    -          Math.max(box.left, scrollBox.left));
    -    }
    -
    -    // Calculate clipping coordinates for horizontal and vertical axis.
    -    // The clipping coordinate is calculated by projecting fake target box,
    -    // the mouse pointer and DnD target box onto an axis and checking how
    -    // box projections overlap and if the projected DnD target box contains
    -    // mouse pointer. The clipping coordinate cannot be computed and is set to
    -    // a negative value if the projected DnD target contains the mouse pointer.
    -
    -    var horizontalClip = null; // Assume mouse is above or below the DnD box.
    -    if (x >= box.right) { // Mouse is to the right of the DnD box.
    -      // Clip the fake box only if the DnD box overlaps it.
    -      horizontalClip = box.right > fakeTargetBox.left ?
    -          box.right : fakeTargetBox.left;
    -    } else if (x < box.left) { // Mouse is to the left of the DnD box.
    -      // Clip the fake box only if the DnD box overlaps it.
    -      horizontalClip = box.left < fakeTargetBox.right ?
    -          box.left : fakeTargetBox.right;
    -    }
    -    var verticalClip = null;
    -    if (y >= box.bottom) {
    -      verticalClip = box.bottom > fakeTargetBox.top ?
    -          box.bottom : fakeTargetBox.top;
    -    } else if (y < box.top) {
    -      verticalClip = box.top < fakeTargetBox.bottom ?
    -          box.top : fakeTargetBox.bottom;
    -    }
    -
    -    // If both clippings are possible, choose one that gives us larger distance
    -    // to mouse pointer (mark the shorter clipping as impossible, by setting it
    -    // to null).
    -    if (!goog.isNull(horizontalClip) && !goog.isNull(verticalClip)) {
    -      if (Math.abs(horizontalClip - x) > Math.abs(verticalClip - y)) {
    -        verticalClip = null;
    -      } else {
    -        horizontalClip = null;
    -      }
    -    }
    -
    -    // Clip none or one of fake target box sides (at most one clipping
    -    // coordinate can be active).
    -    if (!goog.isNull(horizontalClip)) {
    -      if (horizontalClip <= x) {
    -        fakeTargetBox.left = horizontalClip;
    -      } else {
    -        fakeTargetBox.right = horizontalClip;
    -      }
    -    } else if (!goog.isNull(verticalClip)) {
    -      if (verticalClip <= y) {
    -        fakeTargetBox.top = verticalClip;
    -      } else {
    -        fakeTargetBox.bottom = verticalClip;
    -      }
    -    }
    -  }
    -
    -  // Only return the new fake target if it is big enough.
    -  return (fakeTargetBox.right - fakeTargetBox.left) *
    -         (fakeTargetBox.bottom - fakeTargetBox.top) >=
    -         goog.fx.AbstractDragDrop.DUMMY_TARGET_MIN_SIZE_ ?
    -      this.dummyTarget_ : null;
    -};
    -
    -
    -/**
    - * Returns the target for a given cursor position.
    - *
    - * @param {goog.math.Coordinate} position Cursor position.
    - * @return {Object} Target for position or null if no target was defined
    - *     for the given position.
    - * @private
    - */
    -goog.fx.AbstractDragDrop.prototype.getTargetFromPosition_ = function(position) {
    -  for (var target, i = 0; target = this.targetList_[i]; i++) {
    -    if (target.box_.contains(position)) {
    -      if (target.scrollableContainer_) {
    -        // If we have a scrollable container we will need to make sure
    -        // we account for clipping of the scroll area
    -        var box = target.scrollableContainer_.box_;
    -        if (box.contains(position)) {
    -          return target;
    -        }
    -      } else {
    -        return target;
    -      }
    -    }
    -  }
    -
    -  return null;
    -};
    -
    -
    -/**
    - * Checks whatever a given point is inside a given box.
    - *
    - * @param {number} x Cursor position on the x-axis.
    - * @param {number} y Cursor position on the y-axis.
    - * @param {goog.math.Box} box Box to check position against.
    - * @return {boolean} Whether the given point is inside {@code box}.
    - * @protected
    - * @deprecated Use goog.math.Box.contains.
    - */
    -goog.fx.AbstractDragDrop.prototype.isInside = function(x, y, box) {
    -  return x >= box.left &&
    -         x < box.right &&
    -         y >= box.top &&
    -         y < box.bottom;
    -};
    -
    -
    -/**
    - * Gets the scroll distance as a coordinate object, using
    - * the window of the current drag element's dom.
    - * @return {!goog.math.Coordinate} Object with scroll offsets 'x' and 'y'.
    - * @protected
    - */
    -goog.fx.AbstractDragDrop.prototype.getScrollPos = function() {
    -  return goog.dom.getDomHelper(this.dragEl_).getDocumentScroll();
    -};
    -
    -
    -/**
    - * Get the position of a drag event.
    - * @param {goog.fx.DragEvent} event Drag event.
    - * @return {!goog.math.Coordinate} Position of the event.
    - * @protected
    - */
    -goog.fx.AbstractDragDrop.prototype.getEventPosition = function(event) {
    -  var scroll = this.getScrollPos();
    -  return new goog.math.Coordinate(event.clientX + scroll.x,
    -                                  event.clientY + scroll.y);
    -};
    -
    -
    -/** @override */
    -goog.fx.AbstractDragDrop.prototype.disposeInternal = function() {
    -  goog.fx.AbstractDragDrop.base(this, 'disposeInternal');
    -  this.removeItems();
    -};
    -
    -
    -
    -/**
    - * Object representing a drag and drop event.
    - *
    - * @param {string} type Event type.
    - * @param {goog.fx.AbstractDragDrop} source Source drag drop object.
    - * @param {goog.fx.DragDropItem} sourceItem Source item.
    - * @param {goog.fx.AbstractDragDrop=} opt_target Target drag drop object.
    - * @param {goog.fx.DragDropItem=} opt_targetItem Target item.
    - * @param {Element=} opt_targetElement Target element.
    - * @param {number=} opt_clientX X-Position relative to the screen.
    - * @param {number=} opt_clientY Y-Position relative to the screen.
    - * @param {number=} opt_x X-Position relative to the viewport.
    - * @param {number=} opt_y Y-Position relative to the viewport.
    - * @param {Object=} opt_subtarget The currently active subtarget.
    - * @extends {goog.events.Event}
    - * @constructor
    - */
    -goog.fx.DragDropEvent = function(type, source, sourceItem,
    -                                 opt_target, opt_targetItem, opt_targetElement,
    -                                 opt_clientX, opt_clientY, opt_x, opt_y,
    -                                 opt_subtarget) {
    -  // TODO(eae): Get rid of all the optional parameters and have the caller set
    -  // the fields directly instead.
    -  goog.fx.DragDropEvent.base(this, 'constructor', type);
    -
    -  /**
    -   * Reference to the source goog.fx.AbstractDragDrop object.
    -   * @type {goog.fx.AbstractDragDrop}
    -   */
    -  this.dragSource = source;
    -
    -  /**
    -   * Reference to the source goog.fx.DragDropItem object.
    -   * @type {goog.fx.DragDropItem}
    -   */
    -  this.dragSourceItem = sourceItem;
    -
    -  /**
    -   * Reference to the target goog.fx.AbstractDragDrop object.
    -   * @type {goog.fx.AbstractDragDrop|undefined}
    -   */
    -  this.dropTarget = opt_target;
    -
    -  /**
    -   * Reference to the target goog.fx.DragDropItem object.
    -   * @type {goog.fx.DragDropItem|undefined}
    -   */
    -  this.dropTargetItem = opt_targetItem;
    -
    -  /**
    -   * The actual element of the drop target that is the target for this event.
    -   * @type {Element|undefined}
    -   */
    -  this.dropTargetElement = opt_targetElement;
    -
    -  /**
    -   * X-Position relative to the screen.
    -   * @type {number|undefined}
    -   */
    -  this.clientX = opt_clientX;
    -
    -  /**
    -   * Y-Position relative to the screen.
    -   * @type {number|undefined}
    -   */
    -  this.clientY = opt_clientY;
    -
    -  /**
    -   * X-Position relative to the viewport.
    -   * @type {number|undefined}
    -   */
    -  this.viewportX = opt_x;
    -
    -  /**
    -   * Y-Position relative to the viewport.
    -   * @type {number|undefined}
    -   */
    -  this.viewportY = opt_y;
    -
    -  /**
    -   * The subtarget that is currently active if a subtargeting function
    -   * is supplied.
    -   * @type {Object|undefined}
    -   */
    -  this.subtarget = opt_subtarget;
    -};
    -goog.inherits(goog.fx.DragDropEvent, goog.events.Event);
    -
    -
    -
    -/**
    - * Class representing a source or target element for drag and drop operations.
    - *
    - * @param {Element|string} element Dom Node, or string representation of node
    - *     id, to be used as drag source/drop target.
    - * @param {Object=} opt_data Data associated with the source/target.
    - * @throws Error If no element argument is provided or if the type is invalid
    - * @extends {goog.events.EventTarget}
    - * @constructor
    - */
    -goog.fx.DragDropItem = function(element, opt_data) {
    -  goog.fx.DragDropItem.base(this, 'constructor');
    -
    -  /**
    -   * Reference to drag source/target element
    -   * @type {Element}
    -   */
    -  this.element = goog.dom.getElement(element);
    -
    -  /**
    -   * Data associated with element.
    -   * @type {Object|undefined}
    -   */
    -  this.data = opt_data;
    -
    -  /**
    -   * Drag object the item belongs to.
    -   * @type {goog.fx.AbstractDragDrop?}
    -   * @private
    -   */
    -  this.parent_ = null;
    -
    -  /**
    -   * Event handler for listeners on events that can initiate a drag.
    -   * @type {!goog.events.EventHandler<!goog.fx.DragDropItem>}
    -   * @private
    -   */
    -  this.eventHandler_ = new goog.events.EventHandler(this);
    -  this.registerDisposable(this.eventHandler_);
    -
    -  if (!this.element) {
    -    throw Error('Invalid argument');
    -  }
    -};
    -goog.inherits(goog.fx.DragDropItem, goog.events.EventTarget);
    -
    -
    -/**
    - * The current element being dragged. This is needed because a DragDropItem can
    - * have multiple elements that can be dragged.
    - * @type {Element}
    - * @private
    - */
    -goog.fx.DragDropItem.prototype.currentDragElement_ = null;
    -
    -
    -/**
    - * Get the data associated with the source/target.
    - * @return {Object|null|undefined} Data associated with the source/target.
    - */
    -goog.fx.DragDropItem.prototype.getData = function() {
    -  return this.data;
    -};
    -
    -
    -/**
    - * Gets the element that is actually draggable given that the given target was
    - * attempted to be dragged. This should be overriden when the element that was
    - * given actually contains many items that can be dragged. From the target, you
    - * can determine what element should actually be dragged.
    - *
    - * @param {Element} target The target that was attempted to be dragged.
    - * @return {Element} The element that is draggable given the target. If
    - *     none are draggable, this will return null.
    - */
    -goog.fx.DragDropItem.prototype.getDraggableElement = function(target) {
    -  return target;
    -};
    -
    -
    -/**
    - * Gets the element that is currently being dragged.
    - *
    - * @return {Element} The element that is currently being dragged.
    - */
    -goog.fx.DragDropItem.prototype.getCurrentDragElement = function() {
    -  return this.currentDragElement_;
    -};
    -
    -
    -/**
    - * Gets all the elements of this item that are potentially draggable/
    - *
    - * @return {!Array<Element>} The draggable elements.
    - */
    -goog.fx.DragDropItem.prototype.getDraggableElements = function() {
    -  return [this.element];
    -};
    -
    -
    -/**
    - * Event handler for mouse down.
    - *
    - * @param {goog.events.BrowserEvent} event Mouse down event.
    - * @private
    - */
    -goog.fx.DragDropItem.prototype.mouseDown_ = function(event) {
    -  if (!event.isMouseActionButton()) {
    -    return;
    -  }
    -
    -  // Get the draggable element for the target.
    -  var element = this.getDraggableElement(/** @type {Element} */ (event.target));
    -  if (element) {
    -    this.maybeStartDrag_(event, element);
    -  }
    -};
    -
    -
    -/**
    - * Sets the dragdrop to which this item belongs.
    - * @param {goog.fx.AbstractDragDrop} parent The parent dragdrop.
    - */
    -goog.fx.DragDropItem.prototype.setParent = function(parent) {
    -  this.parent_ = parent;
    -};
    -
    -
    -/**
    - * Adds mouse move, mouse out and mouse up handlers.
    - *
    - * @param {goog.events.BrowserEvent} event Mouse down event.
    - * @param {Element} element Element.
    - * @private
    - */
    -goog.fx.DragDropItem.prototype.maybeStartDrag_ = function(event, element) {
    -  var eventType = goog.events.EventType;
    -  this.eventHandler_.
    -      listen(element, eventType.MOUSEMOVE, this.mouseMove_, false).
    -      listen(element, eventType.MOUSEOUT, this.mouseMove_, false);
    -
    -  // Capture the MOUSEUP on the document to ensure that we cancel the start
    -  // drag handlers even if the mouse up occurs on some other element. This can
    -  // happen for instance when the mouse down changes the geometry of the element
    -  // clicked on (e.g. through changes in activation styling) such that the mouse
    -  // up occurs outside the original element.
    -  var doc = goog.dom.getOwnerDocument(element);
    -  this.eventHandler_.listen(doc, eventType.MOUSEUP, this.mouseUp_, true);
    -
    -  this.currentDragElement_ = element;
    -
    -  this.startPosition_ = new goog.math.Coordinate(
    -      event.clientX, event.clientY);
    -
    -  event.preventDefault();
    -};
    -
    -
    -/**
    - * Event handler for mouse move. Starts drag operation if moved more than the
    - * threshold value.
    - *
    - * @param {goog.events.BrowserEvent} event Mouse move or mouse out event.
    - * @private
    - */
    -goog.fx.DragDropItem.prototype.mouseMove_ = function(event) {
    -  var distance = Math.abs(event.clientX - this.startPosition_.x) +
    -      Math.abs(event.clientY - this.startPosition_.y);
    -  // Fire dragStart event if the drag distance exceeds the threshold or if the
    -  // mouse leave the dragged element.
    -  // TODO(user): Consider using the goog.fx.Dragger to track the distance
    -  // even after the mouse leaves the dragged element.
    -  var currentDragElement = this.currentDragElement_;
    -  var distanceAboveThreshold =
    -      distance > goog.fx.AbstractDragDrop.initDragDistanceThreshold;
    -  var mouseOutOnDragElement = event.type == goog.events.EventType.MOUSEOUT &&
    -      event.target == currentDragElement;
    -  if (distanceAboveThreshold || mouseOutOnDragElement) {
    -    this.eventHandler_.removeAll();
    -    this.parent_.startDrag(event, this);
    -  }
    -};
    -
    -
    -/**
    - * Event handler for mouse up. Removes mouse move, mouse out and mouse up event
    - * handlers.
    - *
    - * @param {goog.events.BrowserEvent} event Mouse up event.
    - * @private
    - */
    -goog.fx.DragDropItem.prototype.mouseUp_ = function(event) {
    -  this.eventHandler_.removeAll();
    -  delete this.startPosition_;
    -  this.currentDragElement_ = null;
    -};
    -
    -
    -
    -/**
    - * Class representing an active drop target
    - *
    - * @param {goog.math.Box} box Box describing the position and dimension of the
    - *     target item.
    - * @param {goog.fx.AbstractDragDrop=} opt_target Target that contains the item
    -       associated with position.
    - * @param {goog.fx.DragDropItem=} opt_item Item associated with position.
    - * @param {Element=} opt_element Element of item associated with position.
    - * @constructor
    - * @private
    - */
    -goog.fx.ActiveDropTarget_ = function(box, opt_target, opt_item, opt_element) {
    -
    -  /**
    -   * Box describing the position and dimension of the target item
    -   * @type {goog.math.Box}
    -   * @private
    -   */
    -  this.box_ = box;
    -
    -  /**
    -   * Target that contains the item associated with position
    -   * @type {goog.fx.AbstractDragDrop|undefined}
    -   * @private
    -   */
    -  this.target_ = opt_target;
    -
    -  /**
    -   * Item associated with position
    -   * @type {goog.fx.DragDropItem|undefined}
    -   * @private
    -   */
    -  this.item_ = opt_item;
    -
    -  /**
    -   * The draggable element of the item associated with position.
    -   * @type {Element|undefined}
    -   * @private
    -   */
    -  this.element_ = opt_element;
    -};
    -
    -
    -/**
    - * If this target is in a scrollable container this is it.
    - * @type {goog.fx.ScrollableContainer_}
    - * @private
    - */
    -goog.fx.ActiveDropTarget_.prototype.scrollableContainer_ = null;
    -
    -
    -
    -/**
    - * Class for representing a scrollable container
    - * @param {Element} element the scrollable element.
    - * @constructor
    - * @private
    - */
    -goog.fx.ScrollableContainer_ = function(element) {
    -
    -  /**
    -   * The targets that lie within this container.
    -   * @type {Array<goog.fx.ActiveDropTarget_>}
    -   * @private
    -   */
    -  this.containedTargets_ = [];
    -
    -  /**
    -   * The element that is this container
    -   * @type {Element}
    -   * @private
    -   */
    -  this.element_ = element;
    -
    -  /**
    -   * The saved scroll left location for calculating deltas.
    -   * @type {number}
    -   * @private
    -   */
    -  this.savedScrollLeft_ = 0;
    -
    -  /**
    -   * The saved scroll top location for calculating deltas.
    -   * @type {number}
    -   * @private
    -   */
    -  this.savedScrollTop_ = 0;
    -
    -  /**
    -   * The space occupied by the container.
    -   * @type {goog.math.Box}
    -   * @private
    -   */
    -  this.box_ = null;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/abstractdragdrop_test.html b/src/database/third_party/closure-library/closure/goog/fx/abstractdragdrop_test.html
    deleted file mode 100644
    index 72e023e4d5b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/abstractdragdrop_test.html
    +++ /dev/null
    @@ -1,57 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -  Author: eae@google.com (Emil A Eklund)
    -  Author: dgajda@google.com (Damian Gajda)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.fx.AbstractDragDrop
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.fx.AbstractDragDropTest');
    -  </script>
    -  <style>
    -   #cont {
    -    position: relative;
    -    border: 1px solid black;
    -    height: 100px;
    -    width: 100px;
    -  }
    -  #cont div {
    -    position: absolute;
    -    overflow: hidden;
    -  }
    -  </style>
    - </head>
    - <body>
    -  <div id="cont" style="">
    -  </div>
    -  <button onclick="drawTargets(targets, 10)">
    -   draw targets 1
    -  </button>
    -  <br />
    -  <button onclick="drawTargets(targets2, 1)">
    -   draw targets 2
    -  </button>
    -  <br />
    -  <button onclick="drawTargets(targets3, 10)">
    -   draw targets 3
    -  </button>
    -  <div id="container1">
    -   <div id="child1">
    -   </div>
    -   <div id="child2">
    -   </div>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/abstractdragdrop_test.js b/src/database/third_party/closure-library/closure/goog/fx/abstractdragdrop_test.js
    deleted file mode 100644
    index bcd46a6d076..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/abstractdragdrop_test.js
    +++ /dev/null
    @@ -1,636 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.fx.AbstractDragDropTest');
    -goog.setTestOnly('goog.fx.AbstractDragDropTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.events.EventType');
    -goog.require('goog.functions');
    -goog.require('goog.fx.AbstractDragDrop');
    -goog.require('goog.fx.DragDropItem');
    -goog.require('goog.math.Box');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.style');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -
    -var targets = [
    -  { box_: new goog.math.Box(0, 3, 1, 1) },
    -  { box_: new goog.math.Box(0, 7, 2, 6) },
    -  { box_: new goog.math.Box(2, 2, 3, 1) },
    -  { box_: new goog.math.Box(4, 1, 6, 1) },
    -  { box_: new goog.math.Box(4, 9, 7, 6) },
    -  { box_: new goog.math.Box(9, 9, 10, 1) }
    -];
    -
    -var targets2 = [
    -  { box_: new goog.math.Box(10, 50, 20, 10) },
    -  { box_: new goog.math.Box(20, 50, 30, 10) },
    -  { box_: new goog.math.Box(60, 50, 70, 10) },
    -  { box_: new goog.math.Box(70, 50, 80, 10) }
    -];
    -
    -var targets3 = [
    -  { box_: new goog.math.Box(0, 4, 1, 1) },
    -  { box_: new goog.math.Box(1, 6, 4, 5) },
    -  { box_: new goog.math.Box(5, 5, 6, 2) },
    -  { box_: new goog.math.Box(2, 1, 5, 0) }
    -];
    -
    -
    -/**
    - * Test the utility function which tells how two one dimensional ranges
    - * overlap.
    - */
    -function testRangeOverlap() {
    -  assertEquals(RangeOverlap.LEFT, rangeOverlap(1, 2, 3, 4));
    -  assertEquals(RangeOverlap.LEFT, rangeOverlap(2, 3, 3, 4));
    -  assertEquals(RangeOverlap.LEFT_IN, rangeOverlap(1, 3, 2, 4));
    -  assertEquals(RangeOverlap.IN, rangeOverlap(1, 3, 1, 4));
    -  assertEquals(RangeOverlap.IN, rangeOverlap(2, 3, 1, 4));
    -  assertEquals(RangeOverlap.IN, rangeOverlap(3, 4, 1, 4));
    -  assertEquals(RangeOverlap.RIGHT_IN, rangeOverlap(2, 4, 1, 3));
    -  assertEquals(RangeOverlap.RIGHT, rangeOverlap(2, 3, 1, 2));
    -  assertEquals(RangeOverlap.RIGHT, rangeOverlap(3, 4, 1, 2));
    -  assertEquals(RangeOverlap.CONTAINS, rangeOverlap(1, 4, 2, 3));
    -}
    -
    -
    -/**
    - * An enum describing how two ranges overlap (non-symmetrical relation).
    - * @enum {number}
    - */
    -RangeOverlap = {
    -  LEFT: 1,      // First range is placed to the left of the second.
    -  LEFT_IN: 2,   // First range overlaps on the left side of the second.
    -  IN: 3,        // First range is completely contained in the second.
    -  RIGHT_IN: 4,  // First range overlaps on the right side of the second.
    -  RIGHT: 5,     // First range is placed to the right side of the second.
    -  CONTAINS: 6   // First range contains the second.
    -};
    -
    -
    -/**
    - * Computes how two one dimentional ranges overlap.
    - *
    - * @param {number} left1 Left inclusive bound of the first range.
    - * @param {number} right1 Right exclusive bound of the first range.
    - * @param {number} left2 Left inclusive bound of the second range.
    - * @param {number} right2 Right exclusive bound of the second range.
    - * @return {RangeOverlap} The enum value describing the type of the overlap.
    - */
    -function rangeOverlap(left1, right1, left2, right2) {
    -  if (right1 <= left2) return RangeOverlap.LEFT;
    -  if (left1 >= right2) return RangeOverlap.RIGHT;
    -  var leftIn = left1 >= left2;
    -  var rightIn = right1 <= right2;
    -  if (leftIn && rightIn) return RangeOverlap.IN;
    -  if (leftIn) return RangeOverlap.RIGHT_IN;
    -  if (rightIn) return RangeOverlap.LEFT_IN;
    -  return RangeOverlap.CONTAINS;
    -}
    -
    -
    -/**
    - * Tells whether two boxes overlap.
    - *
    - * @param {goog.math.Box} box1 First box in question.
    - * @param {goog.math.Box} box2 Second box in question.
    - * @return {boolean} Whether boxes overlap in any way.
    - */
    -function boxOverlaps(box1, box2) {
    -  var horizontalOverlap = rangeOverlap(
    -      box1.left, box1.right, box2.left, box2.right);
    -  var verticalOverlap = rangeOverlap(
    -      box1.top, box1.bottom, box2.top, box2.bottom);
    -  return horizontalOverlap != RangeOverlap.LEFT &&
    -      horizontalOverlap != RangeOverlap.RIGHT &&
    -      verticalOverlap != RangeOverlap.LEFT &&
    -      verticalOverlap != RangeOverlap.RIGHT;
    -}
    -
    -
    -/**
    - * Tests if the utility function to compute box overlapping functions properly.
    - */
    -function testBoxOverlaps() {
    -  // Overlapping tests.
    -  var box2 = new goog.math.Box(1, 4, 4, 1);
    -
    -  // Corner overlaps.
    -  assertTrue('NW overlap', boxOverlaps(new goog.math.Box(0, 2, 2, 0), box2));
    -  assertTrue('NE overlap', boxOverlaps(new goog.math.Box(0, 5, 2, 3), box2));
    -  assertTrue('SE overlap', boxOverlaps(new goog.math.Box(3, 5, 5, 3), box2));
    -  assertTrue('SW overlap', boxOverlaps(new goog.math.Box(3, 2, 5, 0), box2));
    -
    -  // Inside.
    -  assertTrue('Inside overlap',
    -      boxOverlaps(new goog.math.Box(2, 3, 3, 2), box2));
    -
    -  // Around.
    -  assertTrue('Outside overlap',
    -      boxOverlaps(new goog.math.Box(0, 5, 5, 0), box2));
    -
    -  // Edge overlaps.
    -  assertTrue('N overlap', boxOverlaps(new goog.math.Box(0, 3, 2, 2), box2));
    -  assertTrue('E overlap', boxOverlaps(new goog.math.Box(2, 5, 3, 3), box2));
    -  assertTrue('S overlap', boxOverlaps(new goog.math.Box(3, 3, 5, 2), box2));
    -  assertTrue('W overlap', boxOverlaps(new goog.math.Box(2, 2, 3, 0), box2));
    -
    -  assertTrue('N-in overlap', boxOverlaps(new goog.math.Box(0, 5, 2, 0), box2));
    -  assertTrue('E-in overlap', boxOverlaps(new goog.math.Box(0, 5, 5, 3), box2));
    -  assertTrue('S-in overlap', boxOverlaps(new goog.math.Box(3, 5, 5, 0), box2));
    -  assertTrue('W-in overlap', boxOverlaps(new goog.math.Box(0, 2, 5, 0), box2));
    -
    -  // Does not overlap.
    -  var box2 = new goog.math.Box(3, 6, 6, 3);
    -
    -  // Along the edge - shorter.
    -  assertFalse('N-in no overlap',
    -      boxOverlaps(new goog.math.Box(1, 5, 2, 4), box2));
    -  assertFalse('E-in no overlap',
    -      boxOverlaps(new goog.math.Box(4, 8, 5, 7), box2));
    -  assertFalse('S-in no overlap',
    -      boxOverlaps(new goog.math.Box(7, 5, 8, 4), box2));
    -  assertFalse('N-in no overlap',
    -      boxOverlaps(new goog.math.Box(4, 2, 5, 1), box2));
    -
    -  // By the corner.
    -  assertFalse('NE no overlap',
    -      boxOverlaps(new goog.math.Box(1, 8, 2, 7), box2));
    -  assertFalse('SE no overlap',
    -      boxOverlaps(new goog.math.Box(7, 8, 8, 7), box2));
    -  assertFalse('SW no overlap',
    -      boxOverlaps(new goog.math.Box(7, 2, 8, 1), box2));
    -  assertFalse('NW no overlap',
    -      boxOverlaps(new goog.math.Box(1, 2, 2, 1), box2));
    -
    -  // Perpendicular to an edge.
    -  assertFalse('NNE no overlap',
    -      boxOverlaps(new goog.math.Box(1, 7, 2, 5), box2));
    -  assertFalse('NEE no overlap',
    -      boxOverlaps(new goog.math.Box(2, 8, 4, 7), box2));
    -  assertFalse('SEE no overlap',
    -      boxOverlaps(new goog.math.Box(5, 8, 7, 7), box2));
    -  assertFalse('SSE no overlap',
    -      boxOverlaps(new goog.math.Box(7, 7, 8, 5), box2));
    -  assertFalse('SSW no overlap',
    -      boxOverlaps(new goog.math.Box(7, 4, 8, 2), box2));
    -  assertFalse('SWW no overlap',
    -      boxOverlaps(new goog.math.Box(5, 2, 7, 1), box2));
    -  assertFalse('NWW no overlap',
    -      boxOverlaps(new goog.math.Box(2, 2, 4, 1), box2));
    -  assertFalse('NNW no overlap',
    -      boxOverlaps(new goog.math.Box(1, 4, 2, 2), box2));
    -
    -  // Along the edge - longer.
    -  assertFalse('N no overlap',
    -      boxOverlaps(new goog.math.Box(0, 7, 1, 2), box2));
    -  assertFalse('E no overlap',
    -      boxOverlaps(new goog.math.Box(2, 9, 7, 8), box2));
    -  assertFalse('S no overlap',
    -      boxOverlaps(new goog.math.Box(8, 7, 9, 2), box2));
    -  assertFalse('W no overlap',
    -      boxOverlaps(new goog.math.Box(2, 1, 7, 0), box2));
    -}
    -
    -
    -/**
    - * Checks whether a given box overlaps any of given DnD target boxes.
    - *
    - * @param {goog.math.Box} box The box to check.
    - * @param {Array<Object>} targets The array of targets with boxes to check
    - *     if they overlap with the given box.
    - * @return {boolean} Whether the box overlaps any of the target boxes.
    - */
    -function boxOverlapsTargets(box, targets) {
    -  return goog.array.some(targets, function(target) {
    -    return boxOverlaps(box, target.box_);
    -  });
    -}
    -
    -
    -function testMaybeCreateDummyTargetForPosition() {
    -  var testGroup = new goog.fx.AbstractDragDrop();
    -  testGroup.targetList_ = targets;
    -  testGroup.targetBox_ = new goog.math.Box(0, 9, 10, 1);
    -
    -  var target = testGroup.maybeCreateDummyTargetForPosition_(3, 3);
    -  assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_));
    -  assertTrue(testGroup.isInside(3, 3, target.box_));
    -
    -  target = testGroup.maybeCreateDummyTargetForPosition_(2, 4);
    -  assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_));
    -  assertTrue(testGroup.isInside(2, 4, target.box_));
    -
    -  target = testGroup.maybeCreateDummyTargetForPosition_(2, 7);
    -  assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_));
    -  assertTrue(testGroup.isInside(2, 7, target.box_));
    -
    -  testGroup.targetList_.push({ box_: new goog.math.Box(5, 6, 6, 0) });
    -
    -  target = testGroup.maybeCreateDummyTargetForPosition_(3, 3);
    -  assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_));
    -  assertTrue(testGroup.isInside(3, 3, target.box_));
    -
    -  target = testGroup.maybeCreateDummyTargetForPosition_(2, 7);
    -  assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_));
    -  assertTrue(testGroup.isInside(2, 7, target.box_));
    -
    -  target = testGroup.maybeCreateDummyTargetForPosition_(6, 3);
    -  assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_));
    -  assertTrue(testGroup.isInside(6, 3, target.box_));
    -
    -  target = testGroup.maybeCreateDummyTargetForPosition_(0, 3);
    -  assertNull(target);
    -  target = testGroup.maybeCreateDummyTargetForPosition_(9, 0);
    -  assertNull(target);
    -}
    -
    -
    -function testMaybeCreateDummyTargetForPosition2() {
    -  var testGroup = new goog.fx.AbstractDragDrop();
    -  testGroup.targetList_ = targets2;
    -  testGroup.targetBox_ = new goog.math.Box(10, 50, 80, 10);
    -
    -  var target = testGroup.maybeCreateDummyTargetForPosition_(30, 40);
    -  assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_));
    -  assertTrue(testGroup.isInside(30, 40, target.box_));
    -
    -  target = testGroup.maybeCreateDummyTargetForPosition_(45, 40);
    -  assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_));
    -  assertTrue(testGroup.isInside(45, 40, target.box_));
    -
    -  testGroup.targetList_.push({ box_: new goog.math.Box(40, 50, 50, 40) });
    -
    -  target = testGroup.maybeCreateDummyTargetForPosition_(30, 40);
    -  assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_));
    -  target = testGroup.maybeCreateDummyTargetForPosition_(45, 35);
    -  assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_));
    -}
    -
    -
    -function testMaybeCreateDummyTargetForPosition3BoxHasDecentSize() {
    -  var testGroup = new goog.fx.AbstractDragDrop();
    -  testGroup.targetList_ = targets3;
    -  testGroup.targetBox_ = new goog.math.Box(0, 6, 6, 0);
    -
    -  var target = testGroup.maybeCreateDummyTargetForPosition_(3, 3);
    -  assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_));
    -  assertTrue(testGroup.isInside(3, 3, target.box_));
    -  assertEquals('(1t, 5r, 5b, 1l)', target.box_.toString());
    -}
    -
    -
    -function testMaybeCreateDummyTargetForPosition4() {
    -  var testGroup = new goog.fx.AbstractDragDrop();
    -  testGroup.targetList_ = targets;
    -  testGroup.targetBox_ = new goog.math.Box(0, 9, 10, 1);
    -
    -  for (var x = testGroup.targetBox_.left;
    -       x < testGroup.targetBox_.right;
    -       x++) {
    -    for (var y = testGroup.targetBox_.top;
    -        y < testGroup.targetBox_.bottom;
    -        y++) {
    -      var inRealTarget = false;
    -      for (var i = 0; i < testGroup.targetList_.length; i++) {
    -        if (testGroup.isInside(x, y, testGroup.targetList_[i].box_)) {
    -          inRealTarget = true;
    -          break;
    -        }
    -      }
    -      if (!inRealTarget) {
    -        var target = testGroup.maybeCreateDummyTargetForPosition_(x, y);
    -        if (target) {
    -          assertFalse('Fake target for point(' + x + ',' + y + ') should ' +
    -              'not overlap any real targets.',
    -              boxOverlapsTargets(target.box_, testGroup.targetList_));
    -          assertTrue(testGroup.isInside(x, y, target.box_));
    -        }
    -      }
    -    }
    -  }
    -}
    -
    -function testMaybeCreateDummyTargetForPosition_NegativePositions() {
    -  var negTargets = [
    -    { box_: new goog.math.Box(-20, 10, -5, 1) },
    -    { box_: new goog.math.Box(20, 10, 30, 1) }
    -  ];
    -
    -  var testGroup = new goog.fx.AbstractDragDrop();
    -  testGroup.targetList_ = negTargets;
    -  testGroup.targetBox_ = new goog.math.Box(-20, 10, 30, 1);
    -
    -  var target = testGroup.maybeCreateDummyTargetForPosition_(1, 5);
    -  assertFalse(boxOverlapsTargets(target.box_, testGroup.targetList_));
    -  assertTrue(testGroup.isInside(1, 5, target.box_));
    -}
    -
    -function testMaybeCreateDummyTargetOutsideScrollableContainer() {
    -  var targets = [
    -    { box_: new goog.math.Box(0, 3, 10, 1) },
    -    { box_: new goog.math.Box(20, 3, 30, 1) }
    -  ];
    -  var target = targets[0];
    -
    -  var testGroup = new goog.fx.AbstractDragDrop();
    -  testGroup.targetList_ = targets;
    -  testGroup.targetBox_ = new goog.math.Box(0, 3, 30, 1);
    -
    -  testGroup.addScrollableContainer(document.getElementById('container1'));
    -  var container = testGroup.scrollableContainers_[0];
    -  container.containedTargets_.push(target);
    -  container.box_ = new goog.math.Box(0, 3, 5, 1); // shorter than target
    -  target.scrollableContainer_ = container;
    -
    -  // mouse cursor is below scrollable target but not the actual target
    -  var dummyTarget = testGroup.maybeCreateDummyTargetForPosition_(2, 7);
    -  // dummy target should not overlap the scrollable container
    -  assertFalse(boxOverlaps(dummyTarget.box_, container.box_));
    -  // but should overlap the actual target, since not all of it is visible
    -  assertTrue(boxOverlaps(dummyTarget.box_, target.box_));
    -}
    -
    -function testMaybeCreateDummyTargetInsideScrollableContainer() {
    -  var targets = [
    -    { box_: new goog.math.Box(0, 3, 10, 1) },
    -    { box_: new goog.math.Box(20, 3, 30, 1) }
    -  ];
    -  var target = targets[0];
    -
    -  var testGroup = new goog.fx.AbstractDragDrop();
    -  testGroup.targetList_ = targets;
    -  testGroup.targetBox_ = new goog.math.Box(0, 3, 30, 1);
    -
    -  testGroup.addScrollableContainer(document.getElementById('container1'));
    -  var container = testGroup.scrollableContainers_[0];
    -  container.containedTargets_.push(target);
    -  container.box_ = new goog.math.Box(0, 3, 20, 1); // longer than target
    -  target.scrollableContainer_ = container;
    -
    -  // mouse cursor is below both the scrollable and the actual target
    -  var dummyTarget = testGroup.maybeCreateDummyTargetForPosition_(2, 15);
    -  // dummy target should overlap the scrollable container
    -  assertTrue(boxOverlaps(dummyTarget.box_, container.box_));
    -  // but not overlap the actual target
    -  assertFalse(boxOverlaps(dummyTarget.box_, target.box_));
    -}
    -
    -function testCalculateTargetBox() {
    -  var testGroup = new goog.fx.AbstractDragDrop();
    -  testGroup.targetList_ = [];
    -  goog.array.forEach(targets, function(target) {
    -    testGroup.targetList_.push(target);
    -    testGroup.calculateTargetBox_(target.box_);
    -  });
    -  assertTrue(goog.math.Box.equals(testGroup.targetBox_,
    -      new goog.math.Box(0, 9, 10, 1)));
    -
    -  testGroup = new goog.fx.AbstractDragDrop();
    -  testGroup.targetList_ = [];
    -  goog.array.forEach(targets2, function(target) {
    -    testGroup.targetList_.push(target);
    -    testGroup.calculateTargetBox_(target.box_);
    -  });
    -  assertTrue(goog.math.Box.equals(testGroup.targetBox_,
    -      new goog.math.Box(10, 50, 80, 10)));
    -
    -  testGroup = new goog.fx.AbstractDragDrop();
    -  testGroup.targetList_ = [];
    -  goog.array.forEach(targets3, function(target) {
    -    testGroup.targetList_.push(target);
    -    testGroup.calculateTargetBox_(target.box_);
    -  });
    -  assertTrue(goog.math.Box.equals(testGroup.targetBox_,
    -      new goog.math.Box(0, 6, 6, 0)));
    -}
    -
    -
    -function testIsInside() {
    -  var add = new goog.fx.AbstractDragDrop();
    -  // The box in question.
    -  // 10,20+++++20,20
    -  //   +         |
    -  // 10,30-----20,30
    -  var box = new goog.math.Box(20, 20, 30, 10);
    -
    -  assertTrue('A point somewhere in the middle of the box should be inside.',
    -      add.isInside(15, 25, box));
    -
    -  assertTrue('A point in top-left corner should be inside the box.',
    -      add.isInside(10, 20, box));
    -
    -  assertTrue('A point on top border should be inside the box.',
    -      add.isInside(15, 20, box));
    -
    -  assertFalse('A point in top-right corner should be outside the box.',
    -      add.isInside(20, 20, box));
    -
    -  assertFalse('A point on right border should be outside the box.',
    -      add.isInside(20, 25, box));
    -
    -  assertFalse('A point in bottom-right corner should be outside the box.',
    -      add.isInside(20, 30, box));
    -
    -  assertFalse('A point on bottom border should be outside the box.',
    -      add.isInside(15, 30, box));
    -
    -  assertFalse('A point in bottom-left corner should be outside the box.',
    -      add.isInside(10, 30, box));
    -
    -  assertTrue('A point on left border should be inside the box.',
    -      add.isInside(10, 25, box));
    -
    -  add.dispose();
    -}
    -
    -
    -function testAddingRemovingScrollableContainers() {
    -  var group = new goog.fx.AbstractDragDrop();
    -  var el1 = document.createElement('div');
    -  var el2 = document.createElement('div');
    -
    -  assertEquals(0, group.scrollableContainers_.length);
    -
    -  group.addScrollableContainer(el1);
    -  assertEquals(1, group.scrollableContainers_.length);
    -
    -  group.addScrollableContainer(el2);
    -  assertEquals(2, group.scrollableContainers_.length);
    -
    -  group.removeAllScrollableContainers();
    -  assertEquals(0, group.scrollableContainers_.length);
    -}
    -
    -
    -function testScrollableContainersCalculation() {
    -  var group = new goog.fx.AbstractDragDrop();
    -  var target = new goog.fx.AbstractDragDrop();
    -
    -  group.addTarget(target);
    -  group.addScrollableContainer(document.getElementById('container1'));
    -  var container = group.scrollableContainers_[0];
    -
    -  var item1 = new goog.fx.DragDropItem(document.getElementById('child1'));
    -  var item2 = new goog.fx.DragDropItem(document.getElementById('child2'));
    -
    -  target.items_.push(item1);
    -  group.recalculateDragTargets();
    -  group.recalculateScrollableContainers();
    -
    -  assertEquals(1, container.containedTargets_.length);
    -  assertEquals(container, group.targetList_[0].scrollableContainer_);
    -
    -  target.items_.push(item2);
    -  group.recalculateDragTargets();
    -  assertEquals(1, container.containedTargets_.length);
    -  assertNull(group.targetList_[0].scrollableContainer_);
    -
    -  group.recalculateScrollableContainers();
    -  assertEquals(2, container.containedTargets_.length);
    -  assertEquals(container, group.targetList_[1].scrollableContainer_);
    -}
    -
    -// See http://b/7494613.
    -function testMouseUpOutsideElement() {
    -  var group = new goog.fx.AbstractDragDrop();
    -  var target = new goog.fx.AbstractDragDrop();
    -  group.addTarget(target);
    -  var item1 = new goog.fx.DragDropItem(document.getElementById('child1'));
    -  group.items_.push(item1);
    -  item1.setParent(group);
    -  group.init();
    -
    -  group.startDrag = goog.functions.error('startDrag should not be called.');
    -
    -  goog.testing.events.fireMouseDownEvent(item1.element);
    -  goog.testing.events.fireMouseUpEvent(item1.element.parentNode);
    -  // This should have no effect (not start a drag) since the previous event
    -  // should have cleared the listeners.
    -  goog.testing.events.fireMouseOutEvent(item1.element);
    -
    -  group.dispose();
    -  target.dispose();
    -}
    -
    -function testScrollBeforeMoveDrag() {
    -  var group = new goog.fx.AbstractDragDrop();
    -  var target = new goog.fx.AbstractDragDrop();
    -
    -  group.addTarget(target);
    -  var container = document.getElementById('container1');
    -  group.addScrollableContainer(container);
    -
    -  var childEl = document.getElementById('child1');
    -  var item = new goog.fx.DragDropItem(childEl);
    -  item.currentDragElement_ = childEl;
    -
    -  target.items_.push(item);
    -  group.recalculateDragTargets();
    -  group.recalculateScrollableContainers();
    -
    -  // Simulare starting a drag.
    -  var moveEvent = {
    -    'clientX': 8,
    -    'clientY': 10,
    -    'type': goog.events.EventType.MOUSEMOVE,
    -    'relatedTarget': childEl,
    -    'preventDefault': function() {}
    -  };
    -  group.startDrag(moveEvent, item);
    -
    -  // Simulate scrolling before the first move drag event.
    -  var scrollEvent = {
    -    'target': container
    -  };
    -  assertNotThrows(goog.bind(group.containerScrollHandler_, group, scrollEvent));
    -}
    -
    -
    -function testMouseMove_mouseOutBeforeThreshold() {
    -  // Setup dragdrop and item
    -  var itemEl = document.createElement('div');
    -  var childEl = document.createElement('div');
    -  itemEl.appendChild(childEl);
    -  var add = new goog.fx.AbstractDragDrop();
    -  var item = new goog.fx.DragDropItem(itemEl);
    -  item.setParent(add);
    -  add.items_.push(item);
    -
    -  // Simulate maybeStartDrag
    -  item.startPosition_ = new goog.math.Coordinate(10, 10);
    -  item.currentDragElement_ = itemEl;
    -
    -  // Test
    -  var draggedItem = null;
    -  add.startDrag = function(event, item) {
    -    draggedItem = item;
    -  };
    -
    -  var event = {'clientX': 8, 'clientY': 10, // Drag distance is only 2
    -    'type': goog.events.EventType.MOUSEOUT, 'target': childEl};
    -  item.mouseMove_(event);
    -  assertEquals('DragStart should not be fired for mouseout on child element.',
    -      null, draggedItem);
    -
    -  var event = {'clientX': 8, 'clientY': 10, // Drag distance is only 2
    -    'type': goog.events.EventType.MOUSEOUT, 'target': itemEl};
    -  item.mouseMove_(event);
    -  assertEquals('DragStart should be fired for mouseout on main element.',
    -      item, draggedItem);
    -}
    -
    -
    -function testGetDragElementPosition() {
    -  var testGroup = new goog.fx.AbstractDragDrop();
    -  var sourceEl = document.createElement('div');
    -  document.body.appendChild(sourceEl);
    -
    -  var pageOffset = goog.style.getPageOffset(sourceEl);
    -  var pos = testGroup.getDragElementPosition(sourceEl);
    -  assertEquals('Drag element position should be source element page offset',
    -      pageOffset.x, pos.x);
    -  assertEquals('Drag element position should be source element page offset',
    -      pageOffset.y, pos.y);
    -
    -  sourceEl.style.marginLeft = '5px';
    -  sourceEl.style.marginTop = '7px';
    -  pageOffset = goog.style.getPageOffset(sourceEl);
    -  pos = testGroup.getDragElementPosition(sourceEl);
    -  assertEquals('Drag element position should be adjusted for source element ' +
    -      'margins', pageOffset.x - 10, pos.x);
    -  assertEquals('Drag element position should be adjusted for source element ' +
    -      'margins', pageOffset.y - 14, pos.y);
    -}
    -
    -
    -// Helper function for manual debugging.
    -function drawTargets(targets, multiplier) {
    -  var colors = ['green', 'blue', 'red', 'lime', 'pink', 'silver', 'orange'];
    -  var cont = document.getElementById('cont');
    -  cont.innerHTML = '';
    -  for (var i = 0; i < targets.length; i++) {
    -    var box = targets[i].box_;
    -    var el = document.createElement('div');
    -    el.style.top = (box.top * multiplier) + 'px';
    -    el.style.left = (box.left * multiplier) + 'px';
    -    el.style.width = ((box.right - box.left) * multiplier) + 'px';
    -    el.style.height = ((box.bottom - box.top) * multiplier) + 'px';
    -    el.style.backgroundColor = colors[i];
    -    cont.appendChild(el);
    -  }
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/anim/anim.js b/src/database/third_party/closure-library/closure/goog/fx/anim/anim.js
    deleted file mode 100644
    index fdce5136d07..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/anim/anim.js
    +++ /dev/null
    @@ -1,211 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Basic animation controls.
    - *
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -goog.provide('goog.fx.anim');
    -goog.provide('goog.fx.anim.Animated');
    -
    -goog.require('goog.async.AnimationDelay');
    -goog.require('goog.async.Delay');
    -goog.require('goog.object');
    -
    -
    -
    -/**
    - * An interface for programatically animated objects. I.e. rendered in
    - * javascript frame by frame.
    - *
    - * @interface
    - */
    -goog.fx.anim.Animated = function() {};
    -
    -
    -/**
    - * Function called when a frame is requested for the animation.
    - *
    - * @param {number} now Current time in milliseconds.
    - */
    -goog.fx.anim.Animated.prototype.onAnimationFrame;
    -
    -
    -/**
    - * Default wait timeout for animations (in milliseconds).  Only used for timed
    - * animation, which uses a timer (setTimeout) to schedule animation.
    - *
    - * @type {number}
    - * @const
    - */
    -goog.fx.anim.TIMEOUT = goog.async.AnimationDelay.TIMEOUT;
    -
    -
    -/**
    - * A map of animations which should be cycled on the global timer.
    - *
    - * @type {Object<number, goog.fx.anim.Animated>}
    - * @private
    - */
    -goog.fx.anim.activeAnimations_ = {};
    -
    -
    -/**
    - * An optional animation window.
    - * @type {Window}
    - * @private
    - */
    -goog.fx.anim.animationWindow_ = null;
    -
    -
    -/**
    - * An interval ID for the global timer or event handler uid.
    - * @type {goog.async.Delay|goog.async.AnimationDelay}
    - * @private
    - */
    -goog.fx.anim.animationDelay_ = null;
    -
    -
    -/**
    - * Registers an animation to be cycled on the global timer.
    - * @param {goog.fx.anim.Animated} animation The animation to register.
    - */
    -goog.fx.anim.registerAnimation = function(animation) {
    -  var uid = goog.getUid(animation);
    -  if (!(uid in goog.fx.anim.activeAnimations_)) {
    -    goog.fx.anim.activeAnimations_[uid] = animation;
    -  }
    -
    -  // If the timer is not already started, start it now.
    -  goog.fx.anim.requestAnimationFrame_();
    -};
    -
    -
    -/**
    - * Removes an animation from the list of animations which are cycled on the
    - * global timer.
    - * @param {goog.fx.anim.Animated} animation The animation to unregister.
    - */
    -goog.fx.anim.unregisterAnimation = function(animation) {
    -  var uid = goog.getUid(animation);
    -  delete goog.fx.anim.activeAnimations_[uid];
    -
    -  // If a timer is running and we no longer have any active timers we stop the
    -  // timers.
    -  if (goog.object.isEmpty(goog.fx.anim.activeAnimations_)) {
    -    goog.fx.anim.cancelAnimationFrame_();
    -  }
    -};
    -
    -
    -/**
    - * Tears down this module. Useful for testing.
    - */
    -// TODO(nicksantos): Wow, this api is pretty broken. This should be fixed.
    -goog.fx.anim.tearDown = function() {
    -  goog.fx.anim.animationWindow_ = null;
    -  goog.dispose(goog.fx.anim.animationDelay_);
    -  goog.fx.anim.animationDelay_ = null;
    -  goog.fx.anim.activeAnimations_ = {};
    -};
    -
    -
    -/**
    - * Registers an animation window. This allows usage of the timing control API
    - * for animations. Note that this window must be visible, as non-visible
    - * windows can potentially stop animating. This window does not necessarily
    - * need to be the window inside which animation occurs, but must remain visible.
    - * See: https://developer.mozilla.org/en/DOM/window.mozRequestAnimationFrame.
    - *
    - * @param {Window} animationWindow The window in which to animate elements.
    - */
    -goog.fx.anim.setAnimationWindow = function(animationWindow) {
    -  // If a timer is currently running, reset it and restart with new functions
    -  // after a timeout. This is to avoid mismatching timer UIDs if we change the
    -  // animation window during a running animation.
    -  //
    -  // In practice this cannot happen before some animation window and timer
    -  // control functions has already been set.
    -  var hasTimer =
    -      goog.fx.anim.animationDelay_ && goog.fx.anim.animationDelay_.isActive();
    -
    -  goog.dispose(goog.fx.anim.animationDelay_);
    -  goog.fx.anim.animationDelay_ = null;
    -  goog.fx.anim.animationWindow_ = animationWindow;
    -
    -  // If the timer was running, start it again.
    -  if (hasTimer) {
    -    goog.fx.anim.requestAnimationFrame_();
    -  }
    -};
    -
    -
    -/**
    - * Requests an animation frame based on the requestAnimationFrame and
    - * cancelRequestAnimationFrame function pair.
    - * @private
    - */
    -goog.fx.anim.requestAnimationFrame_ = function() {
    -  if (!goog.fx.anim.animationDelay_) {
    -    // We cannot guarantee that the global window will be one that fires
    -    // requestAnimationFrame events (consider off-screen chrome extension
    -    // windows). Default to use goog.async.Delay, unless
    -    // the client has explicitly set an animation window.
    -    if (goog.fx.anim.animationWindow_) {
    -      // requestAnimationFrame will call cycleAnimations_ with the current
    -      // time in ms, as returned from goog.now().
    -      goog.fx.anim.animationDelay_ = new goog.async.AnimationDelay(
    -          function(now) {
    -            goog.fx.anim.cycleAnimations_(now);
    -          }, goog.fx.anim.animationWindow_);
    -    } else {
    -      goog.fx.anim.animationDelay_ = new goog.async.Delay(function() {
    -        goog.fx.anim.cycleAnimations_(goog.now());
    -      }, goog.fx.anim.TIMEOUT);
    -    }
    -  }
    -
    -  var delay = goog.fx.anim.animationDelay_;
    -  if (!delay.isActive()) {
    -    delay.start();
    -  }
    -};
    -
    -
    -/**
    - * Cancels an animation frame created by requestAnimationFrame_().
    - * @private
    - */
    -goog.fx.anim.cancelAnimationFrame_ = function() {
    -  if (goog.fx.anim.animationDelay_) {
    -    goog.fx.anim.animationDelay_.stop();
    -  }
    -};
    -
    -
    -/**
    - * Cycles through all registered animations.
    - * @param {number} now Current time in milliseconds.
    - * @private
    - */
    -goog.fx.anim.cycleAnimations_ = function(now) {
    -  goog.object.forEach(goog.fx.anim.activeAnimations_, function(anim) {
    -    anim.onAnimationFrame(now);
    -  });
    -
    -  if (!goog.object.isEmpty(goog.fx.anim.activeAnimations_)) {
    -    goog.fx.anim.requestAnimationFrame_();
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/anim/anim_test.html b/src/database/third_party/closure-library/closure/goog/fx/anim/anim_test.html
    deleted file mode 100644
    index 6c2fa205e33..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/anim/anim_test.html
    +++ /dev/null
    @@ -1,27 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -  Author: arv@google.com (Erik Arvidsson)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.fx
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.fx.animTest');
    -  </script>
    -  <style>
    -  </style>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/anim/anim_test.js b/src/database/third_party/closure-library/closure/goog/fx/anim/anim_test.js
    deleted file mode 100644
    index b9fe8a2b7ee..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/anim/anim_test.js
    +++ /dev/null
    @@ -1,218 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.fx.animTest');
    -goog.setTestOnly('goog.fx.animTest');
    -
    -goog.require('goog.async.AnimationDelay');
    -goog.require('goog.async.Delay');
    -goog.require('goog.events');
    -goog.require('goog.functions');
    -goog.require('goog.fx.Animation');
    -goog.require('goog.fx.anim');
    -goog.require('goog.object');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -goog.require('goog.userAgent');
    -
    -var clock, replacer;
    -
    -function setUpPage() {
    -  clock = new goog.testing.MockClock(true);
    -}
    -
    -function tearDownPage() {
    -  clock.dispose();
    -}
    -
    -function setUp() {
    -  replacer = new goog.testing.PropertyReplacer();
    -}
    -
    -function tearDown() {
    -  replacer.reset();
    -  goog.fx.anim.tearDown();
    -}
    -
    -function testDelayWithMocks() {
    -  goog.fx.anim.setAnimationWindow(null);
    -  registerAndUnregisterAnimationWithMocks(goog.async.Delay);
    -}
    -
    -function testAnimationDelayWithMocks() {
    -  goog.fx.anim.setAnimationWindow(window);
    -  registerAndUnregisterAnimationWithMocks(goog.async.AnimationDelay);
    -}
    -
    -
    -/**
    - * @param {!Function} delayType The constructor for Delay or AnimationDelay.
    - *     The methods will be mocked out.
    - */
    -function registerAndUnregisterAnimationWithMocks(delayType) {
    -  var timerCount = 0;
    -
    -  replacer.set(delayType.prototype, 'start', function() {
    -    timerCount++;
    -  });
    -  replacer.set(delayType.prototype, 'stop', function() {
    -    timerCount--;
    -  });
    -  replacer.set(delayType.prototype, 'isActive', function() {
    -    return timerCount > 0;
    -  });
    -
    -  var forbiddenDelayType = delayType == goog.async.AnimationDelay ?
    -      goog.async.Delay : goog.async.AnimationDelay;
    -  replacer.set(forbiddenDelayType.prototype,
    -      'start', goog.functions.error());
    -  replacer.set(forbiddenDelayType.prototype,
    -      'stop', goog.functions.error());
    -  replacer.set(forbiddenDelayType.prototype,
    -      'isActive', goog.functions.error());
    -
    -  var anim = new goog.fx.Animation([0], [1], 1000);
    -  var anim2 = new goog.fx.Animation([0], [1], 1000);
    -
    -  goog.fx.anim.registerAnimation(anim);
    -
    -  assertTrue('Should contain the animation',
    -             goog.object.containsValue(goog.fx.anim.activeAnimations_,
    -                                       anim));
    -  assertEquals('Should have called start once', 1, timerCount);
    -
    -  goog.fx.anim.registerAnimation(anim2);
    -
    -  assertEquals('Should not have called start again', 1, timerCount);
    -
    -  // Add anim again.
    -  goog.fx.anim.registerAnimation(anim);
    -  assertTrue('Should contain the animation',
    -             goog.object.containsValue(goog.fx.anim.activeAnimations_,
    -                                       anim));
    -  assertEquals('Should not have called start again', 1, timerCount);
    -
    -  goog.fx.anim.unregisterAnimation(anim);
    -  assertFalse('Should not contain the animation',
    -              goog.object.containsValue(goog.fx.anim.activeAnimations_,
    -                                        anim));
    -  assertEquals('clearTimeout should not have been called', 1, timerCount);
    -
    -  goog.fx.anim.unregisterAnimation(anim2);
    -  assertEquals('There should be no remaining timers', 0, timerCount);
    -
    -  // Make sure we don't trigger setTimeout or setInterval.
    -  clock.tick(1000);
    -  goog.fx.anim.cycleAnimations_(goog.now());
    -
    -  assertEquals('There should be no remaining timers', 0, timerCount);
    -
    -  anim.dispose();
    -  anim2.dispose();
    -}
    -
    -function testRegisterAndUnregisterAnimationWithRequestAnimationFrameGecko() {
    -  // Only FF4 onwards support requestAnimationFrame.
    -  if (!goog.userAgent.GECKO || !goog.userAgent.isVersionOrHigher('2.0') ||
    -      goog.userAgent.isVersionOrHigher('17')) {
    -    return;
    -  }
    -
    -  goog.fx.anim.setAnimationWindow(window);
    -
    -  var anim = new goog.fx.Animation([0], [1], 1000);
    -  var anim2 = new goog.fx.Animation([0], [1], 1000);
    -
    -  goog.fx.anim.registerAnimation(anim);
    -
    -  assertTrue('Should contain the animation',
    -             goog.object.containsValue(goog.fx.anim.activeAnimations_,
    -                                       anim));
    -
    -  assertEquals('Should have listen to MozBeforePaint once', 1,
    -      goog.events.getListeners(window, 'MozBeforePaint', false).length);
    -
    -  goog.fx.anim.registerAnimation(anim2);
    -
    -  assertEquals('Should not add more listener for MozBeforePaint', 1,
    -      goog.events.getListeners(window, 'MozBeforePaint', false).length);
    -
    -  // Add anim again.
    -  goog.fx.anim.registerAnimation(anim);
    -  assertTrue('Should contain the animation',
    -             goog.object.containsValue(goog.fx.anim.activeAnimations_,
    -                                       anim));
    -  assertEquals('Should not add more listener for MozBeforePaint', 1,
    -      goog.events.getListeners(window, 'MozBeforePaint', false).length);
    -
    -  goog.fx.anim.unregisterAnimation(anim);
    -  assertFalse('Should not contain the animation',
    -              goog.object.containsValue(goog.fx.anim.activeAnimations_,
    -                                        anim));
    -  assertEquals('Should not clear listener for MozBeforePaint yet', 1,
    -      goog.events.getListeners(window, 'MozBeforePaint', false).length);
    -
    -  goog.fx.anim.unregisterAnimation(anim2);
    -  assertEquals('There should be no more listener for MozBeforePaint', 0,
    -      goog.events.getListeners(window, 'MozBeforePaint', false).length);
    -
    -  anim.dispose();
    -  anim2.dispose();
    -
    -  goog.fx.anim.setAnimationWindow(null);
    -}
    -
    -function testRegisterUnregisterAnimation() {
    -  var anim = new goog.fx.Animation([0], [1], 1000);
    -
    -  goog.fx.anim.registerAnimation(anim);
    -
    -  assertTrue('There should be an active timer',
    -      goog.fx.anim.animationDelay_ && goog.fx.anim.animationDelay_.isActive());
    -  assertEquals('There should be an active animations',
    -      1, goog.object.getCount(goog.fx.anim.activeAnimations_));
    -
    -  goog.fx.anim.unregisterAnimation(anim);
    -
    -  assertTrue('There should be no active animations',
    -      goog.object.isEmpty(goog.fx.anim.activeAnimations_));
    -  assertFalse('There should be no active timer',
    -      goog.fx.anim.animationDelay_ && goog.fx.anim.animationDelay_.isActive());
    -
    -  anim.dispose();
    -}
    -
    -function testCycleWithMockClock() {
    -  goog.fx.anim.setAnimationWindow(null);
    -  var anim = new goog.fx.Animation([0], [1], 1000);
    -  anim.onAnimationFrame = goog.testing.recordFunction();
    -
    -  goog.fx.anim.registerAnimation(anim);
    -  clock.tick(goog.fx.anim.TIMEOUT);
    -
    -  assertEquals(1, anim.onAnimationFrame.getCallCount());
    -}
    -
    -function testCycleWithMockClockAndAnimationWindow() {
    -  goog.fx.anim.setAnimationWindow(window);
    -  var anim = new goog.fx.Animation([0], [1], 1000);
    -  anim.onAnimationFrame = goog.testing.recordFunction();
    -
    -  goog.fx.anim.registerAnimation(anim);
    -  clock.tick(goog.fx.anim.TIMEOUT);
    -
    -  assertEquals(1, anim.onAnimationFrame.getCallCount());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/animation.js b/src/database/third_party/closure-library/closure/goog/fx/animation.js
    deleted file mode 100644
    index 0a4401b2192..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/animation.js
    +++ /dev/null
    @@ -1,524 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Classes for doing animations and visual effects.
    - *
    - * (Based loosly on my animation code for 13thparallel.org, with extra
    - * inspiration from the DojoToolkit's modifications to my code)
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -goog.provide('goog.fx.Animation');
    -goog.provide('goog.fx.Animation.EventType');
    -goog.provide('goog.fx.Animation.State');
    -goog.provide('goog.fx.AnimationEvent');
    -
    -goog.require('goog.array');
    -goog.require('goog.events.Event');
    -goog.require('goog.fx.Transition');  // Unreferenced: interface
    -goog.require('goog.fx.TransitionBase');
    -goog.require('goog.fx.anim');
    -goog.require('goog.fx.anim.Animated');  // Unreferenced: interface
    -
    -
    -
    -/**
    - * Constructor for an animation object.
    - * @param {Array<number>} start Array for start coordinates.
    - * @param {Array<number>} end Array for end coordinates.
    - * @param {number} duration Length of animation in milliseconds.
    - * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
    - * @constructor
    - * @implements {goog.fx.anim.Animated}
    - * @implements {goog.fx.Transition}
    - * @extends {goog.fx.TransitionBase}
    - */
    -goog.fx.Animation = function(start, end, duration, opt_acc) {
    -  goog.fx.Animation.base(this, 'constructor');
    -
    -  if (!goog.isArray(start) || !goog.isArray(end)) {
    -    throw Error('Start and end parameters must be arrays');
    -  }
    -
    -  if (start.length != end.length) {
    -    throw Error('Start and end points must be the same length');
    -  }
    -
    -  /**
    -   * Start point.
    -   * @type {Array<number>}
    -   * @protected
    -   */
    -  this.startPoint = start;
    -
    -  /**
    -   * End point.
    -   * @type {Array<number>}
    -   * @protected
    -   */
    -  this.endPoint = end;
    -
    -  /**
    -   * Duration of animation in milliseconds.
    -   * @type {number}
    -   * @protected
    -   */
    -  this.duration = duration;
    -
    -  /**
    -   * Acceleration function, which must return a number between 0 and 1 for
    -   * inputs between 0 and 1.
    -   * @type {Function|undefined}
    -   * @private
    -   */
    -  this.accel_ = opt_acc;
    -
    -  /**
    -   * Current coordinate for animation.
    -   * @type {Array<number>}
    -   * @protected
    -   */
    -  this.coords = [];
    -
    -  /**
    -   * Whether the animation should use "right" rather than "left" to position
    -   * elements in RTL.  This is a temporary flag to allow clients to transition
    -   * to the new behavior at their convenience.  At some point it will be the
    -   * default.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.useRightPositioningForRtl_ = false;
    -
    -  /**
    -   * Current frame rate.
    -   * @private {number}
    -   */
    -  this.fps_ = 0;
    -
    -  /**
    -   * Percent of the way through the animation.
    -   * @protected {number}
    -   */
    -  this.progress = 0;
    -
    -  /**
    -   * Timestamp for when last frame was run.
    -   * @protected {?number}
    -   */
    -  this.lastFrame = null;
    -};
    -goog.inherits(goog.fx.Animation, goog.fx.TransitionBase);
    -
    -
    -/**
    - * Sets whether the animation should use "right" rather than "left" to position
    - * elements.  This is a temporary flag to allow clients to transition
    - * to the new component at their convenience.  At some point "right" will be
    - * used for RTL elements by default.
    - * @param {boolean} useRightPositioningForRtl True if "right" should be used for
    - *     positioning, false if "left" should be used for positioning.
    - */
    -goog.fx.Animation.prototype.enableRightPositioningForRtl =
    -    function(useRightPositioningForRtl) {
    -  this.useRightPositioningForRtl_ = useRightPositioningForRtl;
    -};
    -
    -
    -/**
    - * Whether the animation should use "right" rather than "left" to position
    - * elements.  This is a temporary flag to allow clients to transition
    - * to the new component at their convenience.  At some point "right" will be
    - * used for RTL elements by default.
    - * @return {boolean} True if "right" should be used for positioning, false if
    - *     "left" should be used for positioning.
    - */
    -goog.fx.Animation.prototype.isRightPositioningForRtlEnabled = function() {
    -  return this.useRightPositioningForRtl_;
    -};
    -
    -
    -/**
    - * Events fired by the animation.
    - * @enum {string}
    - */
    -goog.fx.Animation.EventType = {
    -  /**
    -   * Dispatched when played for the first time OR when it is resumed.
    -   * @deprecated Use goog.fx.Transition.EventType.PLAY.
    -   */
    -  PLAY: goog.fx.Transition.EventType.PLAY,
    -
    -  /**
    -   * Dispatched only when the animation starts from the beginning.
    -   * @deprecated Use goog.fx.Transition.EventType.BEGIN.
    -   */
    -  BEGIN: goog.fx.Transition.EventType.BEGIN,
    -
    -  /**
    -   * Dispatched only when animation is restarted after a pause.
    -   * @deprecated Use goog.fx.Transition.EventType.RESUME.
    -   */
    -  RESUME: goog.fx.Transition.EventType.RESUME,
    -
    -  /**
    -   * Dispatched when animation comes to the end of its duration OR stop
    -   * is called.
    -   * @deprecated Use goog.fx.Transition.EventType.END.
    -   */
    -  END: goog.fx.Transition.EventType.END,
    -
    -  /**
    -   * Dispatched only when stop is called.
    -   * @deprecated Use goog.fx.Transition.EventType.STOP.
    -   */
    -  STOP: goog.fx.Transition.EventType.STOP,
    -
    -  /**
    -   * Dispatched only when animation comes to its end naturally.
    -   * @deprecated Use goog.fx.Transition.EventType.FINISH.
    -   */
    -  FINISH: goog.fx.Transition.EventType.FINISH,
    -
    -  /**
    -   * Dispatched when an animation is paused.
    -   * @deprecated Use goog.fx.Transition.EventType.PAUSE.
    -   */
    -  PAUSE: goog.fx.Transition.EventType.PAUSE,
    -
    -  /**
    -   * Dispatched each frame of the animation.  This is where the actual animator
    -   * will listen.
    -   */
    -  ANIMATE: 'animate',
    -
    -  /**
    -   * Dispatched when the animation is destroyed.
    -   */
    -  DESTROY: 'destroy'
    -};
    -
    -
    -/**
    - * @deprecated Use goog.fx.anim.TIMEOUT.
    - */
    -goog.fx.Animation.TIMEOUT = goog.fx.anim.TIMEOUT;
    -
    -
    -/**
    - * Enum for the possible states of an animation.
    - * @deprecated Use goog.fx.Transition.State instead.
    - * @enum {number}
    - */
    -goog.fx.Animation.State = goog.fx.TransitionBase.State;
    -
    -
    -/**
    - * @deprecated Use goog.fx.anim.setAnimationWindow.
    - * @param {Window} animationWindow The window in which to animate elements.
    - */
    -goog.fx.Animation.setAnimationWindow = function(animationWindow) {
    -  goog.fx.anim.setAnimationWindow(animationWindow);
    -};
    -
    -
    -/**
    - * Starts or resumes an animation.
    - * @param {boolean=} opt_restart Whether to restart the
    - *     animation from the beginning if it has been paused.
    - * @return {boolean} Whether animation was started.
    - * @override
    - */
    -goog.fx.Animation.prototype.play = function(opt_restart) {
    -  if (opt_restart || this.isStopped()) {
    -    this.progress = 0;
    -    this.coords = this.startPoint;
    -  } else if (this.isPlaying()) {
    -    return false;
    -  }
    -
    -  goog.fx.anim.unregisterAnimation(this);
    -
    -  var now = /** @type {number} */ (goog.now());
    -
    -  this.startTime = now;
    -  if (this.isPaused()) {
    -    this.startTime -= this.duration * this.progress;
    -  }
    -
    -  this.endTime = this.startTime + this.duration;
    -  this.lastFrame = this.startTime;
    -
    -  if (!this.progress) {
    -    this.onBegin();
    -  }
    -
    -  this.onPlay();
    -
    -  if (this.isPaused()) {
    -    this.onResume();
    -  }
    -
    -  this.setStatePlaying();
    -
    -  goog.fx.anim.registerAnimation(this);
    -  this.cycle(now);
    -
    -  return true;
    -};
    -
    -
    -/**
    - * Stops the animation.
    - * @param {boolean=} opt_gotoEnd If true the animation will move to the
    - *     end coords.
    - * @override
    - */
    -goog.fx.Animation.prototype.stop = function(opt_gotoEnd) {
    -  goog.fx.anim.unregisterAnimation(this);
    -  this.setStateStopped();
    -
    -  if (!!opt_gotoEnd) {
    -    this.progress = 1;
    -  }
    -
    -  this.updateCoords_(this.progress);
    -
    -  this.onStop();
    -  this.onEnd();
    -};
    -
    -
    -/**
    - * Pauses the animation (iff it's playing).
    - * @override
    - */
    -goog.fx.Animation.prototype.pause = function() {
    -  if (this.isPlaying()) {
    -    goog.fx.anim.unregisterAnimation(this);
    -    this.setStatePaused();
    -    this.onPause();
    -  }
    -};
    -
    -
    -/**
    - * @return {number} The current progress of the animation, the number
    - *     is between 0 and 1 inclusive.
    - */
    -goog.fx.Animation.prototype.getProgress = function() {
    -  return this.progress;
    -};
    -
    -
    -/**
    - * Sets the progress of the animation.
    - * @param {number} progress The new progress of the animation.
    - */
    -goog.fx.Animation.prototype.setProgress = function(progress) {
    -  this.progress = progress;
    -  if (this.isPlaying()) {
    -    var now = goog.now();
    -    // If the animation is already playing, we recompute startTime and endTime
    -    // such that the animation plays consistently, that is:
    -    // now = startTime + progress * duration.
    -    this.startTime = now - this.duration * this.progress;
    -    this.endTime = this.startTime + this.duration;
    -  }
    -};
    -
    -
    -/**
    - * Disposes of the animation.  Stops an animation, fires a 'destroy' event and
    - * then removes all the event handlers to clean up memory.
    - * @override
    - * @protected
    - */
    -goog.fx.Animation.prototype.disposeInternal = function() {
    -  if (!this.isStopped()) {
    -    this.stop(false);
    -  }
    -  this.onDestroy();
    -  goog.fx.Animation.base(this, 'disposeInternal');
    -};
    -
    -
    -/**
    - * Stops an animation, fires a 'destroy' event and then removes all the event
    - * handlers to clean up memory.
    - * @deprecated Use dispose() instead.
    - */
    -goog.fx.Animation.prototype.destroy = function() {
    -  this.dispose();
    -};
    -
    -
    -/** @override */
    -goog.fx.Animation.prototype.onAnimationFrame = function(now) {
    -  this.cycle(now);
    -};
    -
    -
    -/**
    - * Handles the actual iteration of the animation in a timeout
    - * @param {number} now The current time.
    - */
    -goog.fx.Animation.prototype.cycle = function(now) {
    -  this.progress = (now - this.startTime) / (this.endTime - this.startTime);
    -
    -  if (this.progress >= 1) {
    -    this.progress = 1;
    -  }
    -
    -  this.fps_ = 1000 / (now - this.lastFrame);
    -  this.lastFrame = now;
    -
    -  this.updateCoords_(this.progress);
    -
    -  // Animation has finished.
    -  if (this.progress == 1) {
    -    this.setStateStopped();
    -    goog.fx.anim.unregisterAnimation(this);
    -
    -    this.onFinish();
    -    this.onEnd();
    -
    -  // Animation is still under way.
    -  } else if (this.isPlaying()) {
    -    this.onAnimate();
    -  }
    -};
    -
    -
    -/**
    - * Calculates current coordinates, based on the current state.  Applies
    - * the accelleration function if it exists.
    - * @param {number} t Percentage of the way through the animation as a decimal.
    - * @private
    - */
    -goog.fx.Animation.prototype.updateCoords_ = function(t) {
    -  if (goog.isFunction(this.accel_)) {
    -    t = this.accel_(t);
    -  }
    -  this.coords = new Array(this.startPoint.length);
    -  for (var i = 0; i < this.startPoint.length; i++) {
    -    this.coords[i] = (this.endPoint[i] - this.startPoint[i]) * t +
    -        this.startPoint[i];
    -  }
    -};
    -
    -
    -/**
    - * Dispatches the ANIMATE event. Sub classes should override this instead
    - * of listening to the event.
    - * @protected
    - */
    -goog.fx.Animation.prototype.onAnimate = function() {
    -  this.dispatchAnimationEvent(goog.fx.Animation.EventType.ANIMATE);
    -};
    -
    -
    -/**
    - * Dispatches the DESTROY event. Sub classes should override this instead
    - * of listening to the event.
    - * @protected
    - */
    -goog.fx.Animation.prototype.onDestroy = function() {
    -  this.dispatchAnimationEvent(goog.fx.Animation.EventType.DESTROY);
    -};
    -
    -
    -/** @override */
    -goog.fx.Animation.prototype.dispatchAnimationEvent = function(type) {
    -  this.dispatchEvent(new goog.fx.AnimationEvent(type, this));
    -};
    -
    -
    -
    -/**
    - * Class for an animation event object.
    - * @param {string} type Event type.
    - * @param {goog.fx.Animation} anim An animation object.
    - * @constructor
    - * @extends {goog.events.Event}
    - */
    -goog.fx.AnimationEvent = function(type, anim) {
    -  goog.fx.AnimationEvent.base(this, 'constructor', type);
    -
    -  /**
    -   * The current coordinates.
    -   * @type {Array<number>}
    -   */
    -  this.coords = anim.coords;
    -
    -  /**
    -   * The x coordinate.
    -   * @type {number}
    -   */
    -  this.x = anim.coords[0];
    -
    -  /**
    -   * The y coordinate.
    -   * @type {number}
    -   */
    -  this.y = anim.coords[1];
    -
    -  /**
    -   * The z coordinate.
    -   * @type {number}
    -   */
    -  this.z = anim.coords[2];
    -
    -  /**
    -   * The current duration.
    -   * @type {number}
    -   */
    -  this.duration = anim.duration;
    -
    -  /**
    -   * The current progress.
    -   * @type {number}
    -   */
    -  this.progress = anim.getProgress();
    -
    -  /**
    -   * Frames per second so far.
    -   */
    -  this.fps = anim.fps_;
    -
    -  /**
    -   * The state of the animation.
    -   * @type {number}
    -   */
    -  this.state = anim.getStateInternal();
    -
    -  /**
    -   * The animation object.
    -   * @type {goog.fx.Animation}
    -   */
    -  // TODO(arv): This can be removed as this is the same as the target
    -  this.anim = anim;
    -};
    -goog.inherits(goog.fx.AnimationEvent, goog.events.Event);
    -
    -
    -/**
    - * Returns the coordinates as integers (rounded to nearest integer).
    - * @return {!Array<number>} An array of the coordinates rounded to
    - *     the nearest integer.
    - */
    -goog.fx.AnimationEvent.prototype.coordsAsInts = function() {
    -  return goog.array.map(this.coords, Math.round);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/animation_test.html b/src/database/third_party/closure-library/closure/goog/fx/animation_test.html
    deleted file mode 100644
    index e365b285e66..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/animation_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.fx.Animation
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.fx.AnimationTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/animation_test.js b/src/database/third_party/closure-library/closure/goog/fx/animation_test.js
    deleted file mode 100644
    index 185763ae79a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/animation_test.js
    +++ /dev/null
    @@ -1,116 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.fx.AnimationTest');
    -goog.setTestOnly('goog.fx.AnimationTest');
    -
    -goog.require('goog.events');
    -goog.require('goog.fx.Animation');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.jsunit');
    -
    -var clock;
    -
    -function setUpPage() {
    -  clock = new goog.testing.MockClock(true);
    -}
    -
    -function tearDownPage() {
    -  clock.dispose();
    -}
    -
    -function testPauseLogic() {
    -  var anim = new goog.fx.Animation([], [], 3000);
    -  var nFrames = 0;
    -  goog.events.listen(anim, goog.fx.Animation.EventType.ANIMATE, function(e) {
    -    assertRoughlyEquals(e.progress, progress, 1e-6);
    -    nFrames++;
    -  });
    -  goog.events.listen(anim, goog.fx.Animation.EventType.END, function(e) {
    -    nFrames++;
    -  });
    -  var nSteps = 10;
    -  for (var i = 0; i < nSteps; i++) {
    -    progress = i / (nSteps - 1);
    -    anim.setProgress(progress);
    -    anim.play();
    -    anim.pause();
    -  }
    -  assertEquals(nSteps, nFrames);
    -}
    -
    -function testPauseOffset() {
    -  var anim = new goog.fx.Animation([0], [1000], 1000);
    -  anim.play();
    -
    -  assertEquals(0, anim.coords[0]);
    -  assertRoughlyEquals(0, anim.progress, 1e-4);
    -
    -  clock.tick(300);
    -
    -  assertEquals(300, anim.coords[0]);
    -  assertRoughlyEquals(0.3, anim.progress, 1e-4);
    -
    -  anim.pause();
    -
    -  clock.tick(400);
    -
    -  assertEquals(300, anim.coords[0]);
    -  assertRoughlyEquals(0.3, anim.progress, 1e-4);
    -
    -  anim.play();
    -
    -  assertEquals(300, anim.coords[0]);
    -  assertRoughlyEquals(0.3, anim.progress, 1e-4);
    -
    -  clock.tick(400);
    -
    -  assertEquals(700, anim.coords[0]);
    -  assertRoughlyEquals(0.7, anim.progress, 1e-4);
    -
    -  anim.pause();
    -
    -  clock.tick(300);
    -
    -  assertEquals(700, anim.coords[0]);
    -  assertRoughlyEquals(0.7, anim.progress, 1e-4);
    -
    -  anim.play();
    -
    -  var lastPlay = goog.now();
    -
    -  assertEquals(700, anim.coords[0]);
    -  assertRoughlyEquals(0.7, anim.progress, 1e-4);
    -
    -  clock.tick(300);
    -
    -  assertEquals(1000, anim.coords[0]);
    -  assertRoughlyEquals(1, anim.progress, 1e-4);
    -  assertEquals(goog.fx.Animation.State.STOPPED, anim.getStateInternal());
    -}
    -
    -function testSetProgress() {
    -  var anim = new goog.fx.Animation([0], [1000], 3000);
    -  var nFrames = 0;
    -  anim.play();
    -  anim.setProgress(0.5);
    -  goog.events.listen(anim, goog.fx.Animation.EventType.ANIMATE, function(e) {
    -    assertEquals(500, e.coords[0]);
    -    assertRoughlyEquals(0.5, e.progress, 1e-4);
    -    nFrames++;
    -  });
    -  anim.cycle(goog.now());
    -  anim.stop();
    -  assertEquals(1, nFrames);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/animationqueue.js b/src/database/third_party/closure-library/closure/goog/fx/animationqueue.js
    deleted file mode 100644
    index 2ad74ab867c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/animationqueue.js
    +++ /dev/null
    @@ -1,310 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A class which automatically plays through a queue of
    - * animations.  AnimationParallelQueue and AnimationSerialQueue provide
    - * specific implementations of the abstract class AnimationQueue.
    - *
    - * @see ../demos/animationqueue.html
    - */
    -
    -goog.provide('goog.fx.AnimationParallelQueue');
    -goog.provide('goog.fx.AnimationQueue');
    -goog.provide('goog.fx.AnimationSerialQueue');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.events');
    -goog.require('goog.fx.Transition');
    -goog.require('goog.fx.TransitionBase');
    -
    -
    -
    -/**
    - * Constructor for AnimationQueue object.
    - *
    - * @constructor
    - * @extends {goog.fx.TransitionBase}
    - * @struct
    - * @suppress {checkStructDictInheritance}
    - */
    -goog.fx.AnimationQueue = function() {
    -  goog.fx.AnimationQueue.base(this, 'constructor');
    -
    -  /**
    -   * An array holding all animations in the queue.
    -   * @type {Array<goog.fx.TransitionBase>}
    -   * @protected
    -   */
    -  this.queue = [];
    -};
    -goog.inherits(goog.fx.AnimationQueue, goog.fx.TransitionBase);
    -
    -
    -/**
    - * Pushes an Animation to the end of the queue.
    - * @param {goog.fx.TransitionBase} animation The animation to add to the queue.
    - */
    -goog.fx.AnimationQueue.prototype.add = function(animation) {
    -  goog.asserts.assert(this.isStopped(),
    -      'Not allowed to add animations to a running animation queue.');
    -
    -  if (goog.array.contains(this.queue, animation)) {
    -    return;
    -  }
    -
    -  this.queue.push(animation);
    -  goog.events.listen(animation, goog.fx.Transition.EventType.FINISH,
    -                     this.onAnimationFinish, false, this);
    -};
    -
    -
    -/**
    - * Removes an Animation from the queue.
    - * @param {goog.fx.Animation} animation The animation to remove.
    - */
    -goog.fx.AnimationQueue.prototype.remove = function(animation) {
    -  goog.asserts.assert(this.isStopped(),
    -      'Not allowed to remove animations from a running animation queue.');
    -
    -  if (goog.array.remove(this.queue, animation)) {
    -    goog.events.unlisten(animation, goog.fx.Transition.EventType.FINISH,
    -                         this.onAnimationFinish, false, this);
    -  }
    -};
    -
    -
    -/**
    - * Handles the event that an animation has finished.
    - * @param {goog.events.Event} e The finishing event.
    - * @protected
    - */
    -goog.fx.AnimationQueue.prototype.onAnimationFinish = goog.abstractMethod;
    -
    -
    -/**
    - * Disposes of the animations.
    - * @override
    - */
    -goog.fx.AnimationQueue.prototype.disposeInternal = function() {
    -  goog.array.forEach(this.queue, function(animation) {
    -    animation.dispose();
    -  });
    -  this.queue.length = 0;
    -
    -  goog.fx.AnimationQueue.base(this, 'disposeInternal');
    -};
    -
    -
    -
    -/**
    - * Constructor for AnimationParallelQueue object.
    - * @constructor
    - * @extends {goog.fx.AnimationQueue}
    - * @struct
    - */
    -goog.fx.AnimationParallelQueue = function() {
    -  goog.fx.AnimationParallelQueue.base(this, 'constructor');
    -
    -  /**
    -   * Number of finished animations.
    -   * @type {number}
    -   * @private
    -   */
    -  this.finishedCounter_ = 0;
    -};
    -goog.inherits(goog.fx.AnimationParallelQueue, goog.fx.AnimationQueue);
    -
    -
    -/** @override */
    -goog.fx.AnimationParallelQueue.prototype.play = function(opt_restart) {
    -  if (this.queue.length == 0) {
    -    return false;
    -  }
    -
    -  if (opt_restart || this.isStopped()) {
    -    this.finishedCounter_ = 0;
    -    this.onBegin();
    -  } else if (this.isPlaying()) {
    -    return false;
    -  }
    -
    -  this.onPlay();
    -  if (this.isPaused()) {
    -    this.onResume();
    -  }
    -  var resuming = this.isPaused() && !opt_restart;
    -
    -  this.startTime = goog.now();
    -  this.endTime = null;
    -  this.setStatePlaying();
    -
    -  goog.array.forEach(this.queue, function(anim) {
    -    if (!resuming || anim.isPaused()) {
    -      anim.play(opt_restart);
    -    }
    -  });
    -
    -  return true;
    -};
    -
    -
    -/** @override */
    -goog.fx.AnimationParallelQueue.prototype.pause = function() {
    -  if (this.isPlaying()) {
    -    goog.array.forEach(this.queue, function(anim) {
    -      if (anim.isPlaying()) {
    -        anim.pause();
    -      }
    -    });
    -
    -    this.setStatePaused();
    -    this.onPause();
    -  }
    -};
    -
    -
    -/** @override */
    -goog.fx.AnimationParallelQueue.prototype.stop = function(opt_gotoEnd) {
    -  goog.array.forEach(this.queue, function(anim) {
    -    if (!anim.isStopped()) {
    -      anim.stop(opt_gotoEnd);
    -    }
    -  });
    -
    -  this.setStateStopped();
    -  this.endTime = goog.now();
    -
    -  this.onStop();
    -  this.onEnd();
    -};
    -
    -
    -/** @override */
    -goog.fx.AnimationParallelQueue.prototype.onAnimationFinish = function(e) {
    -  this.finishedCounter_++;
    -  if (this.finishedCounter_ == this.queue.length) {
    -    this.endTime = goog.now();
    -
    -    this.setStateStopped();
    -
    -    this.onFinish();
    -    this.onEnd();
    -  }
    -};
    -
    -
    -
    -/**
    - * Constructor for AnimationSerialQueue object.
    - * @constructor
    - * @extends {goog.fx.AnimationQueue}
    - * @struct
    - */
    -goog.fx.AnimationSerialQueue = function() {
    -  goog.fx.AnimationSerialQueue.base(this, 'constructor');
    -
    -  /**
    -   * Current animation in queue currently active.
    -   * @type {number}
    -   * @private
    -   */
    -  this.current_ = 0;
    -};
    -goog.inherits(goog.fx.AnimationSerialQueue, goog.fx.AnimationQueue);
    -
    -
    -/** @override */
    -goog.fx.AnimationSerialQueue.prototype.play = function(opt_restart) {
    -  if (this.queue.length == 0) {
    -    return false;
    -  }
    -
    -  if (opt_restart || this.isStopped()) {
    -    if (this.current_ < this.queue.length &&
    -        !this.queue[this.current_].isStopped()) {
    -      this.queue[this.current_].stop(false);
    -    }
    -
    -    this.current_ = 0;
    -    this.onBegin();
    -  } else if (this.isPlaying()) {
    -    return false;
    -  }
    -
    -  this.onPlay();
    -  if (this.isPaused()) {
    -    this.onResume();
    -  }
    -
    -  this.startTime = goog.now();
    -  this.endTime = null;
    -  this.setStatePlaying();
    -
    -  this.queue[this.current_].play(opt_restart);
    -
    -  return true;
    -};
    -
    -
    -/** @override */
    -goog.fx.AnimationSerialQueue.prototype.pause = function() {
    -  if (this.isPlaying()) {
    -    this.queue[this.current_].pause();
    -    this.setStatePaused();
    -    this.onPause();
    -  }
    -};
    -
    -
    -/** @override */
    -goog.fx.AnimationSerialQueue.prototype.stop = function(opt_gotoEnd) {
    -  this.setStateStopped();
    -  this.endTime = goog.now();
    -
    -  if (opt_gotoEnd) {
    -    for (var i = this.current_; i < this.queue.length; ++i) {
    -      var anim = this.queue[i];
    -      // If the animation is stopped, start it to initiate rendering.  This
    -      // might be needed to make the next line work.
    -      if (anim.isStopped()) anim.play();
    -      // If the animation is not done, stop it and go to the end state of the
    -      // animation.
    -      if (!anim.isStopped()) anim.stop(true);
    -    }
    -  } else if (this.current_ < this.queue.length) {
    -    this.queue[this.current_].stop(false);
    -  }
    -
    -  this.onStop();
    -  this.onEnd();
    -};
    -
    -
    -/** @override */
    -goog.fx.AnimationSerialQueue.prototype.onAnimationFinish = function(e) {
    -  if (this.isPlaying()) {
    -    this.current_++;
    -    if (this.current_ < this.queue.length) {
    -      this.queue[this.current_].play();
    -    } else {
    -      this.endTime = goog.now();
    -      this.setStateStopped();
    -
    -      this.onFinish();
    -      this.onEnd();
    -    }
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/animationqueue_test.html b/src/database/third_party/closure-library/closure/goog/fx/animationqueue_test.html
    deleted file mode 100644
    index 408fce428b9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/animationqueue_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.fx.Animation
    -  </title>
    -  <script type="text/javascript" src="../base.js">
    -  </script>
    -  <script type="text/javascript">
    -    goog.require('goog.fx.AnimationQueueTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/animationqueue_test.js b/src/database/third_party/closure-library/closure/goog/fx/animationqueue_test.js
    deleted file mode 100644
    index 5f788fef76f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/animationqueue_test.js
    +++ /dev/null
    @@ -1,315 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.fx.AnimationQueueTest');
    -goog.setTestOnly('goog.fx.AnimationQueueTest');
    -
    -goog.require('goog.events');
    -goog.require('goog.fx.Animation');
    -goog.require('goog.fx.AnimationParallelQueue');
    -goog.require('goog.fx.AnimationSerialQueue');
    -goog.require('goog.fx.Transition');
    -goog.require('goog.fx.anim');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.jsunit');
    -
    -var clock;
    -
    -function setUpPage() {
    -  clock = new goog.testing.MockClock(true);
    -  goog.fx.anim.setAnimationWindow(null);
    -}
    -
    -function tearDownPage() {
    -  clock.dispose();
    -}
    -
    -function testParallelEvents() {
    -  var anim = new goog.fx.AnimationParallelQueue();
    -  anim.add(new goog.fx.Animation([0], [100], 200));
    -  anim.add(new goog.fx.Animation([0], [100], 400));
    -  anim.add(new goog.fx.Animation([0], [100], 600));
    -
    -  assertTrue(anim.queue[0].isStopped());
    -  assertTrue(anim.queue[1].isStopped());
    -  assertTrue(anim.queue[2].isStopped());
    -  assertTrue(anim.isStopped());
    -
    -  var playEvents = 0, beginEvents = 0, resumeEvents = 0, pauseEvents = 0;
    -  var endEvents = 0, stopEvents = 0, finishEvents = 0;
    -
    -  goog.events.listen(anim, goog.fx.Transition.EventType.PLAY, function() {
    -    ++playEvents; });
    -  goog.events.listen(anim, goog.fx.Transition.EventType.BEGIN, function() {
    -    ++beginEvents; });
    -  goog.events.listen(anim, goog.fx.Transition.EventType.RESUME, function() {
    -    ++resumeEvents; });
    -  goog.events.listen(anim, goog.fx.Transition.EventType.PAUSE, function() {
    -    ++pauseEvents; });
    -  goog.events.listen(anim, goog.fx.Transition.EventType.END, function() {
    -    ++endEvents; });
    -  goog.events.listen(anim, goog.fx.Transition.EventType.STOP, function() {
    -    ++stopEvents; });
    -  goog.events.listen(anim, goog.fx.Transition.EventType.FINISH, function() {
    -    ++finishEvents; });
    -
    -  // PLAY, BEGIN
    -  anim.play();
    -  // No queue events.
    -  clock.tick(100);
    -  // PAUSE
    -  anim.pause();
    -  // No queue events
    -  clock.tick(200);
    -  // PLAY, RESUME
    -  anim.play();
    -  // No queue events.
    -  clock.tick(400);
    -  // END, STOP
    -  anim.stop();
    -  // PLAY, BEGIN
    -  anim.play();
    -  // No queue events.
    -  clock.tick(400);
    -  // END, FINISH
    -  clock.tick(200);
    -
    -  // Make sure the event counts are right.
    -  assertEquals(3, playEvents);
    -  assertEquals(2, beginEvents);
    -  assertEquals(1, resumeEvents);
    -  assertEquals(1, pauseEvents);
    -  assertEquals(2, endEvents);
    -  assertEquals(1, stopEvents);
    -  assertEquals(1, finishEvents);
    -}
    -
    -function testSerialEvents() {
    -  var anim = new goog.fx.AnimationSerialQueue();
    -  anim.add(new goog.fx.Animation([0], [100], 100));
    -  anim.add(new goog.fx.Animation([0], [100], 200));
    -  anim.add(new goog.fx.Animation([0], [100], 300));
    -
    -  assertTrue(anim.queue[0].isStopped());
    -  assertTrue(anim.queue[1].isStopped());
    -  assertTrue(anim.queue[2].isStopped());
    -  assertTrue(anim.isStopped());
    -
    -  var playEvents = 0, beginEvents = 0, resumeEvents = 0, pauseEvents = 0;
    -  var endEvents = 0, stopEvents = 0, finishEvents = 0;
    -
    -  goog.events.listen(anim, goog.fx.Transition.EventType.PLAY, function() {
    -    ++playEvents; });
    -  goog.events.listen(anim, goog.fx.Transition.EventType.BEGIN, function() {
    -    ++beginEvents; });
    -  goog.events.listen(anim, goog.fx.Transition.EventType.RESUME, function() {
    -    ++resumeEvents; });
    -  goog.events.listen(anim, goog.fx.Transition.EventType.PAUSE, function() {
    -    ++pauseEvents; });
    -  goog.events.listen(anim, goog.fx.Transition.EventType.END, function() {
    -    ++endEvents; });
    -  goog.events.listen(anim, goog.fx.Transition.EventType.STOP, function() {
    -    ++stopEvents; });
    -  goog.events.listen(anim, goog.fx.Transition.EventType.FINISH, function() {
    -    ++finishEvents; });
    -
    -  // PLAY, BEGIN
    -  anim.play();
    -  // No queue events.
    -  clock.tick(100);
    -  // PAUSE
    -  anim.pause();
    -  // No queue events
    -  clock.tick(200);
    -  // PLAY, RESUME
    -  anim.play();
    -  // No queue events.
    -  clock.tick(400);
    -  // END, STOP
    -  anim.stop();
    -  // PLAY, BEGIN
    -  anim.play(true);
    -  // No queue events.
    -  clock.tick(400);
    -  // END, FINISH
    -  clock.tick(200);
    -
    -  // Make sure the event counts are right.
    -  assertEquals(3, playEvents);
    -  assertEquals(2, beginEvents);
    -  assertEquals(1, resumeEvents);
    -  assertEquals(1, pauseEvents);
    -  assertEquals(2, endEvents);
    -  assertEquals(1, stopEvents);
    -  assertEquals(1, finishEvents);
    -}
    -
    -function testParallelPause() {
    -  var anim = new goog.fx.AnimationParallelQueue();
    -  anim.add(new goog.fx.Animation([0], [100], 100));
    -  anim.add(new goog.fx.Animation([0], [100], 200));
    -  anim.add(new goog.fx.Animation([0], [100], 300));
    -
    -  assertTrue(anim.queue[0].isStopped());
    -  assertTrue(anim.queue[1].isStopped());
    -  assertTrue(anim.queue[2].isStopped());
    -  assertTrue(anim.isStopped());
    -
    -  anim.play();
    -
    -  assertTrue(anim.queue[0].isPlaying());
    -  assertTrue(anim.queue[1].isPlaying());
    -  assertTrue(anim.queue[2].isPlaying());
    -  assertTrue(anim.isPlaying());
    -
    -  clock.tick(100);
    -
    -  assertTrue(anim.queue[0].isStopped());
    -  assertTrue(anim.queue[1].isPlaying());
    -  assertTrue(anim.queue[2].isPlaying());
    -  assertTrue(anim.isPlaying());
    -
    -  anim.pause();
    -
    -  assertTrue(anim.queue[0].isStopped());
    -  assertTrue(anim.queue[1].isPaused());
    -  assertTrue(anim.queue[2].isPaused());
    -  assertTrue(anim.isPaused());
    -
    -  clock.tick(200);
    -
    -  assertTrue(anim.queue[0].isStopped());
    -  assertTrue(anim.queue[1].isPaused());
    -  assertTrue(anim.queue[2].isPaused());
    -  assertTrue(anim.isPaused());
    -
    -  anim.play();
    -
    -  assertTrue(anim.queue[0].isStopped());
    -  assertTrue(anim.queue[1].isPlaying());
    -  assertTrue(anim.queue[2].isPlaying());
    -  assertTrue(anim.isPlaying());
    -
    -  clock.tick(100);
    -
    -  assertTrue(anim.queue[0].isStopped());
    -  assertTrue(anim.queue[1].isStopped());
    -  assertTrue(anim.queue[2].isPlaying());
    -  assertTrue(anim.isPlaying());
    -
    -  anim.pause();
    -
    -  assertTrue(anim.queue[0].isStopped());
    -  assertTrue(anim.queue[1].isStopped());
    -  assertTrue(anim.queue[2].isPaused());
    -  assertTrue(anim.isPaused());
    -
    -  clock.tick(200);
    -
    -  assertTrue(anim.queue[0].isStopped());
    -  assertTrue(anim.queue[1].isStopped());
    -  assertTrue(anim.queue[2].isPaused());
    -  assertTrue(anim.isPaused());
    -
    -  anim.play();
    -
    -  assertTrue(anim.queue[0].isStopped());
    -  assertTrue(anim.queue[1].isStopped());
    -  assertTrue(anim.queue[2].isPlaying());
    -  assertTrue(anim.isPlaying());
    -
    -  clock.tick(100);
    -
    -  assertTrue(anim.queue[0].isStopped());
    -  assertTrue(anim.queue[1].isStopped());
    -  assertTrue(anim.queue[2].isStopped());
    -  assertTrue(anim.isStopped());
    -}
    -
    -function testSerialPause() {
    -  var anim = new goog.fx.AnimationSerialQueue();
    -  anim.add(new goog.fx.Animation([0], [100], 100));
    -  anim.add(new goog.fx.Animation([0], [100], 200));
    -  anim.add(new goog.fx.Animation([0], [100], 300));
    -
    -  assertTrue(anim.queue[0].isStopped());
    -  assertTrue(anim.queue[1].isStopped());
    -  assertTrue(anim.queue[2].isStopped());
    -  assertTrue(anim.isStopped());
    -
    -  anim.play();
    -
    -  assertTrue(anim.queue[0].isPlaying());
    -  assertTrue(anim.queue[1].isStopped());
    -  assertTrue(anim.queue[2].isStopped());
    -  assertTrue(anim.isPlaying());
    -
    -  clock.tick(100);
    -
    -  assertTrue(anim.queue[0].isStopped());
    -  assertTrue(anim.queue[1].isPlaying());
    -  assertTrue(anim.queue[2].isStopped());
    -  assertTrue(anim.isPlaying());
    -
    -  anim.pause();
    -
    -  assertTrue(anim.queue[0].isStopped());
    -  assertTrue(anim.queue[1].isPaused());
    -  assertTrue(anim.queue[2].isStopped());
    -  assertTrue(anim.isPaused());
    -
    -  clock.tick(400);
    -
    -  assertTrue(anim.queue[0].isStopped());
    -  assertTrue(anim.queue[1].isPaused());
    -  assertTrue(anim.queue[2].isStopped());
    -  assertTrue(anim.isPaused());
    -
    -  anim.play();
    -
    -  assertTrue(anim.queue[0].isStopped());
    -  assertTrue(anim.queue[1].isPlaying());
    -  assertTrue(anim.queue[2].isStopped());
    -  assertTrue(anim.isPlaying());
    -
    -  clock.tick(200);
    -
    -  assertTrue(anim.queue[0].isStopped());
    -  assertTrue(anim.queue[1].isStopped());
    -  assertTrue(anim.queue[2].isPlaying());
    -  assertTrue(anim.isPlaying());
    -
    -  anim.pause();
    -
    -  assertTrue(anim.queue[0].isStopped());
    -  assertTrue(anim.queue[1].isStopped());
    -  assertTrue(anim.queue[2].isPaused());
    -  assertTrue(anim.isPaused());
    -
    -  clock.tick(300);
    -
    -  assertTrue(anim.queue[0].isStopped());
    -  assertTrue(anim.queue[1].isStopped());
    -  assertTrue(anim.queue[2].isPaused());
    -  assertTrue(anim.isPaused());
    -
    -  anim.play();
    -
    -  clock.tick(300);
    -
    -  assertTrue(anim.queue[0].isStopped());
    -  assertTrue(anim.queue[1].isStopped());
    -  assertTrue(anim.queue[2].isStopped());
    -  assertTrue(anim.isStopped());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/css3/fx.js b/src/database/third_party/closure-library/closure/goog/fx/css3/fx.js
    deleted file mode 100644
    index 267c78a4c07..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/css3/fx.js
    +++ /dev/null
    @@ -1,63 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A collection of CSS3 targeted animation, based on
    - * {@code goog.fx.css3.Transition}.
    - *
    - * @author chrishenry@google.com (Chris Henry)
    - */
    -
    -goog.provide('goog.fx.css3');
    -
    -goog.require('goog.fx.css3.Transition');
    -
    -
    -/**
    - * Creates a transition to fade the element.
    - * @param {Element} element The element to fade.
    - * @param {number} duration Duration in seconds.
    - * @param {string} timing The CSS3 timing function.
    - * @param {number} startOpacity Starting opacity.
    - * @param {number} endOpacity Ending opacity.
    - * @return {!goog.fx.css3.Transition} The transition object.
    - */
    -goog.fx.css3.fade = function(
    -    element, duration, timing,  startOpacity, endOpacity) {
    -  return new goog.fx.css3.Transition(
    -      element, duration, {'opacity': startOpacity}, {'opacity': endOpacity},
    -      {property: 'opacity', duration: duration, timing: timing, delay: 0});
    -};
    -
    -
    -/**
    - * Creates a transition to fade in the element.
    - * @param {Element} element The element to fade in.
    - * @param {number} duration Duration in seconds.
    - * @return {!goog.fx.css3.Transition} The transition object.
    - */
    -goog.fx.css3.fadeIn = function(element, duration) {
    -  return goog.fx.css3.fade(element, duration, 'ease-out', 0, 1);
    -};
    -
    -
    -/**
    - * Creates a transition to fade out the element.
    - * @param {Element} element The element to fade out.
    - * @param {number} duration Duration in seconds.
    - * @return {!goog.fx.css3.Transition} The transition object.
    - */
    -goog.fx.css3.fadeOut = function(element, duration) {
    -  return goog.fx.css3.fade(element, duration, 'ease-in', 1, 0);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/css3/transition.js b/src/database/third_party/closure-library/closure/goog/fx/css3/transition.js
    deleted file mode 100644
    index 59ec3f78608..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/css3/transition.js
    +++ /dev/null
    @@ -1,201 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview CSS3 transition base library.
    - *
    - * @author chrishenry@google.com (Chris Henry)
    - */
    -
    -goog.provide('goog.fx.css3.Transition');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.asserts');
    -goog.require('goog.fx.TransitionBase');
    -goog.require('goog.style');
    -goog.require('goog.style.transition');
    -
    -
    -
    -/**
    - * A class to handle targeted CSS3 transition. This class
    - * handles common features required for targeted CSS3 transition.
    - *
    - * Browser that does not support CSS3 transition will still receive all
    - * the events fired by the transition object, but will not have any transition
    - * played. If the browser supports the final state as set in setFinalState
    - * method, the element will ends in the final state.
    - *
    - * Transitioning multiple properties with the same setting is possible
    - * by setting Css3Property's property to 'all'. Performing multiple
    - * transitions can be done via setting multiple initialStyle,
    - * finalStyle and transitions. Css3Property's delay can be used to
    - * delay one of the transition. Here is an example for a transition
    - * that expands on the width and then followed by the height:
    - *
    - * <pre>
    - *   initialStyle: {width: 10px, height: 10px}
    - *   finalStyle: {width: 100px, height: 100px}
    - *   transitions: [
    - *     {property: width, duration: 1, timing: 'ease-in', delay: 0},
    - *     {property: height, duration: 1, timing: 'ease-in', delay: 1}
    - *   ]
    - * </pre>
    - *
    - * @param {Element} element The element to be transitioned.
    - * @param {number} duration The duration of the transition in seconds.
    - *     This should be the longest of all transitions.
    - * @param {Object} initialStyle Initial style properties of the element before
    - *     animating. Set using {@code goog.style.setStyle}.
    - * @param {Object} finalStyle Final style properties of the element after
    - *     animating. Set using {@code goog.style.setStyle}.
    - * @param {goog.style.transition.Css3Property|
    - *     Array<goog.style.transition.Css3Property>} transitions A single CSS3
    - *     transition property or an array of it.
    - * @extends {goog.fx.TransitionBase}
    - * @constructor
    - */
    -goog.fx.css3.Transition = function(
    -    element, duration, initialStyle, finalStyle, transitions) {
    -  goog.fx.css3.Transition.base(this, 'constructor');
    -
    -  /**
    -   * @type {Element}
    -   * @private
    -   */
    -  this.element_ = element;
    -
    -  /**
    -   * @type {number}
    -   * @private
    -   */
    -  this.duration_ = duration;
    -
    -  /**
    -   * @type {Object}
    -   * @private
    -   */
    -  this.initialStyle_ = initialStyle;
    -
    -  /**
    -   * @type {Object}
    -   * @private
    -   */
    -  this.finalStyle_ = finalStyle;
    -
    -  /**
    -   * @type {Array<goog.style.transition.Css3Property>}
    -   * @private
    -   */
    -  this.transitions_ = goog.isArray(transitions) ? transitions : [transitions];
    -};
    -goog.inherits(goog.fx.css3.Transition, goog.fx.TransitionBase);
    -
    -
    -/**
    - * Timer id to be used to cancel animation part-way.
    - * @type {number}
    - * @private
    - */
    -goog.fx.css3.Transition.prototype.timerId_;
    -
    -
    -/** @override */
    -goog.fx.css3.Transition.prototype.play = function() {
    -  if (this.isPlaying()) {
    -    return false;
    -  }
    -
    -  this.onBegin();
    -  this.onPlay();
    -
    -  this.startTime = goog.now();
    -  this.setStatePlaying();
    -
    -  if (goog.style.transition.isSupported()) {
    -    goog.style.setStyle(this.element_, this.initialStyle_);
    -    // Allow element to get updated to its initial state before installing
    -    // CSS3 transition.
    -    this.timerId_ = goog.Timer.callOnce(this.play_, undefined, this);
    -    return true;
    -  } else {
    -    this.stop_(false);
    -    return false;
    -  }
    -};
    -
    -
    -/**
    - * Helper method for play method. This needs to be executed on a timer.
    - * @private
    - */
    -goog.fx.css3.Transition.prototype.play_ = function() {
    -  // This measurement of the DOM element causes the browser to recalculate its
    -  // initial state before the transition starts.
    -  goog.style.getSize(this.element_);
    -  goog.style.transition.set(this.element_, this.transitions_);
    -  goog.style.setStyle(this.element_, this.finalStyle_);
    -  this.timerId_ = goog.Timer.callOnce(
    -      goog.bind(this.stop_, this, false), this.duration_ * 1000);
    -};
    -
    -
    -/** @override */
    -goog.fx.css3.Transition.prototype.stop = function() {
    -  if (!this.isPlaying()) return;
    -
    -  this.stop_(true);
    -};
    -
    -
    -/**
    - * Helper method for stop method.
    - * @param {boolean} stopped If the transition was stopped.
    - * @private
    - */
    -goog.fx.css3.Transition.prototype.stop_ = function(stopped) {
    -  goog.style.transition.removeAll(this.element_);
    -
    -  // Clear the timer.
    -  goog.Timer.clear(this.timerId_);
    -
    -  // Make sure that we have reached the final style.
    -  goog.style.setStyle(this.element_, this.finalStyle_);
    -
    -  this.endTime = goog.now();
    -  this.setStateStopped();
    -
    -  if (stopped) {
    -    this.onStop();
    -  } else {
    -    this.onFinish();
    -  }
    -  this.onEnd();
    -};
    -
    -
    -/** @override */
    -goog.fx.css3.Transition.prototype.disposeInternal = function() {
    -  this.stop();
    -  goog.fx.css3.Transition.base(this, 'disposeInternal');
    -};
    -
    -
    -/**
    - * Pausing CSS3 Transitions in not supported.
    - * @override
    - */
    -goog.fx.css3.Transition.prototype.pause = function() {
    -  goog.asserts.assert(false, 'Css3 transitions does not support pause action.');
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/css3/transition_test.html b/src/database/third_party/closure-library/closure/goog/fx/css3/transition_test.html
    deleted file mode 100644
    index 936426a4673..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/css3/transition_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -  Author: chrishenry@google.com (Chris Henry)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.fx.css3.Transition
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.fx.css3.TransitionTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/css3/transition_test.js b/src/database/third_party/closure-library/closure/goog/fx/css3/transition_test.js
    deleted file mode 100644
    index 03ccc16aeca..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/css3/transition_test.js
    +++ /dev/null
    @@ -1,219 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.fx.css3.TransitionTest');
    -goog.setTestOnly('goog.fx.css3.TransitionTest');
    -
    -goog.require('goog.dispose');
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.fx.Transition');
    -goog.require('goog.fx.css3.Transition');
    -goog.require('goog.style.transition');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -
    -var transition;
    -var element;
    -var mockClock;
    -
    -
    -function createTransition(element, duration) {
    -  return new goog.fx.css3.Transition(
    -      element, duration, {'opacity': 0}, {'opacity': 1},
    -      {property: 'opacity', duration: duration, timing: 'ease-in', delay: 0});
    -}
    -
    -
    -function setUp() {
    -  mockClock = new goog.testing.MockClock(true);
    -  element = goog.dom.createElement('div');
    -  document.body.appendChild(element);
    -}
    -
    -
    -function tearDown() {
    -  goog.dispose(transition);
    -  goog.dispose(mockClock);
    -  goog.dom.removeNode(element);
    -}
    -
    -
    -function testPlayEventFiredOnPlay() {
    -  if (!goog.style.transition.isSupported()) return;
    -
    -  transition = createTransition(element, 10);
    -  var handlerCalled = false;
    -  goog.events.listen(transition, goog.fx.Transition.EventType.PLAY,
    -      function() {
    -        handlerCalled = true;
    -      });
    -
    -  transition.play();
    -  assertTrue(handlerCalled);
    -}
    -
    -
    -function testBeginEventFiredOnPlay() {
    -  if (!goog.style.transition.isSupported()) return;
    -
    -  transition = createTransition(element, 10);
    -  var handlerCalled = false;
    -  goog.events.listen(transition, goog.fx.Transition.EventType.BEGIN,
    -      function() {
    -        handlerCalled = true;
    -      });
    -
    -  transition.play();
    -  assertTrue(handlerCalled);
    -}
    -
    -
    -function testFinishEventsFiredAfterFinish() {
    -  if (!goog.style.transition.isSupported()) return;
    -
    -  transition = createTransition(element, 10);
    -  var finishHandlerCalled = false;
    -  var endHandlerCalled = false;
    -  goog.events.listen(transition, goog.fx.Transition.EventType.FINISH,
    -      function() {
    -        finishHandlerCalled = true;
    -      });
    -  goog.events.listen(transition, goog.fx.Transition.EventType.END,
    -      function() {
    -        endHandlerCalled = true;
    -      });
    -
    -  transition.play();
    -
    -  mockClock.tick(10000);
    -
    -  assertTrue(finishHandlerCalled);
    -  assertTrue(endHandlerCalled);
    -}
    -
    -
    -function testEventsWhenTransitionIsUnsupported() {
    -  if (goog.style.transition.isSupported()) return;
    -
    -  transition = createTransition(element, 10);
    -
    -  var stopHandlerCalled = false;
    -  var finishHandlerCalled = false, endHandlerCalled = false;
    -  var beginHandlerCalled = false, playHandlerCalled = false;
    -  goog.events.listen(transition, goog.fx.Transition.EventType.BEGIN,
    -      function() {
    -        beginHandlerCalled = true;
    -      });
    -  goog.events.listen(transition, goog.fx.Transition.EventType.PLAY,
    -      function() {
    -        playHandlerCalled = true;
    -      });
    -  goog.events.listen(transition, goog.fx.Transition.EventType.FINISH,
    -      function() {
    -        finishHandlerCalled = true;
    -      });
    -  goog.events.listen(transition, goog.fx.Transition.EventType.END,
    -      function() {
    -        endHandlerCalled = true;
    -      });
    -  goog.events.listen(transition, goog.fx.Transition.EventType.STOP,
    -      function() {
    -        stopHandlerCalled = true;
    -      });
    -
    -  assertFalse(transition.play());
    -
    -  assertTrue(beginHandlerCalled);
    -  assertTrue(playHandlerCalled);
    -  assertTrue(endHandlerCalled);
    -  assertTrue(finishHandlerCalled);
    -
    -  transition.stop();
    -
    -  assertFalse(stopHandlerCalled);
    -}
    -
    -
    -function testCallingStopDuringAnimationWorks() {
    -  if (!goog.style.transition.isSupported()) return;
    -
    -  transition = createTransition(element, 10);
    -
    -  var stopHandler = goog.testing.recordFunction();
    -  var endHandler = goog.testing.recordFunction();
    -  var finishHandler = goog.testing.recordFunction();
    -  goog.events.listen(transition, goog.fx.Transition.EventType.STOP,
    -      stopHandler);
    -  goog.events.listen(transition, goog.fx.Transition.EventType.END,
    -      endHandler);
    -  goog.events.listen(transition, goog.fx.Transition.EventType.FINISH,
    -      finishHandler);
    -
    -  transition.play();
    -  mockClock.tick(1);
    -  transition.stop();
    -  assertEquals(1, stopHandler.getCallCount());
    -  assertEquals(1, endHandler.getCallCount());
    -  mockClock.tick(10000);
    -  assertEquals(0, finishHandler.getCallCount());
    -}
    -
    -
    -function testCallingStopImmediatelyWorks() {
    -  if (!goog.style.transition.isSupported()) return;
    -
    -  transition = createTransition(element, 10);
    -
    -  var stopHandler = goog.testing.recordFunction();
    -  var endHandler = goog.testing.recordFunction();
    -  var finishHandler = goog.testing.recordFunction();
    -  goog.events.listen(transition, goog.fx.Transition.EventType.STOP,
    -      stopHandler);
    -  goog.events.listen(transition, goog.fx.Transition.EventType.END,
    -      endHandler);
    -  goog.events.listen(transition, goog.fx.Transition.EventType.FINISH,
    -      finishHandler);
    -
    -  transition.play();
    -  transition.stop();
    -  assertEquals(1, stopHandler.getCallCount());
    -  assertEquals(1, endHandler.getCallCount());
    -  mockClock.tick(10000);
    -  assertEquals(0, finishHandler.getCallCount());
    -}
    -
    -function testCallingStopAfterAnimationDoesNothing() {
    -  if (!goog.style.transition.isSupported()) return;
    -
    -  transition = createTransition(element, 10);
    -
    -  var stopHandler = goog.testing.recordFunction();
    -  var endHandler = goog.testing.recordFunction();
    -  var finishHandler = goog.testing.recordFunction();
    -  goog.events.listen(transition, goog.fx.Transition.EventType.STOP,
    -      stopHandler);
    -  goog.events.listen(transition, goog.fx.Transition.EventType.END,
    -      endHandler);
    -  goog.events.listen(transition, goog.fx.Transition.EventType.FINISH,
    -      finishHandler);
    -
    -  transition.play();
    -  mockClock.tick(10000);
    -  transition.stop();
    -  assertEquals(0, stopHandler.getCallCount());
    -  assertEquals(1, endHandler.getCallCount());
    -  assertEquals(1, finishHandler.getCallCount());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/cssspriteanimation.js b/src/database/third_party/closure-library/closure/goog/fx/cssspriteanimation.js
    deleted file mode 100644
    index 9813f7de286..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/cssspriteanimation.js
    +++ /dev/null
    @@ -1,130 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview An animation class that animates CSS sprites by changing the
    - * CSS background-position.
    - *
    - * @author arv@google.com (Erik Arvidsson)
    - * @see ../demos/cssspriteanimation.html
    - */
    -
    -goog.provide('goog.fx.CssSpriteAnimation');
    -
    -goog.require('goog.fx.Animation');
    -
    -
    -
    -/**
    - * This animation class is used to animate a CSS sprite (moving a background
    - * image).  This moves through a series of images in a single image sprite. By
    - * default, the animation loops when done.  Looping can be disabled by setting
    - * {@code opt_disableLoop} and results in the animation stopping on the last
    - * image in the image sprite.  You should set up the {@code background-image}
    - * and size in a CSS rule for the relevant element.
    - *
    - * @param {Element} element The HTML element to animate the background for.
    - * @param {goog.math.Size} size The size of one image in the image sprite.
    - * @param {goog.math.Box} box The box describing the layout of the sprites to
    - *     use in the large image.  The sprites can be position horizontally or
    - *     vertically and using a box here allows the implementation to know which
    - *     way to go.
    - * @param {number} time The duration in milliseconds for one iteration of the
    - *     animation.  For example, if the sprite contains 4 images and the duration
    - *     is set to 400ms then each sprite will be displayed for 100ms.
    - * @param {function(number) : number=} opt_acc Acceleration function,
    - *    returns 0-1 for inputs 0-1.  This can be used to make certain frames be
    - *    shown for a longer period of time.
    - * @param {boolean=} opt_disableLoop Whether the animation should be halted
    - *    after a single loop of the images in the sprite.
    - *
    - * @constructor
    - * @extends {goog.fx.Animation}
    - * @final
    - */
    -goog.fx.CssSpriteAnimation = function(element, size, box, time, opt_acc,
    -    opt_disableLoop) {
    -  var start = [box.left, box.top];
    -  // We never draw for the end so we do not need to subtract for the size
    -  var end = [box.right, box.bottom];
    -  goog.fx.CssSpriteAnimation.base(
    -      this, 'constructor', start, end, time, opt_acc);
    -
    -  /**
    -   * HTML element that will be used in the animation.
    -   * @type {Element}
    -   * @private
    -   */
    -  this.element_ = element;
    -
    -  /**
    -   * The size of an individual sprite in the image sprite.
    -   * @type {goog.math.Size}
    -   * @private
    -   */
    -  this.size_ = size;
    -
    -  /**
    -   * Whether the animation should be halted after a single loop of the images
    -   * in the sprite.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.disableLoop_ = !!opt_disableLoop;
    -};
    -goog.inherits(goog.fx.CssSpriteAnimation, goog.fx.Animation);
    -
    -
    -/** @override */
    -goog.fx.CssSpriteAnimation.prototype.onAnimate = function() {
    -  // Round to nearest sprite.
    -  var x = -Math.floor(this.coords[0] / this.size_.width) * this.size_.width;
    -  var y = -Math.floor(this.coords[1] / this.size_.height) * this.size_.height;
    -  this.element_.style.backgroundPosition = x + 'px ' + y + 'px';
    -
    -  goog.fx.CssSpriteAnimation.base(this, 'onAnimate');
    -};
    -
    -
    -/** @override */
    -goog.fx.CssSpriteAnimation.prototype.onFinish = function() {
    -  if (!this.disableLoop_) {
    -    this.play(true);
    -  }
    -  goog.fx.CssSpriteAnimation.base(this, 'onFinish');
    -};
    -
    -
    -/**
    - * Clears the background position style set directly on the element
    - * by the animation. Allows to apply CSS styling for background position on the
    - * same element when the sprite animation is not runniing.
    - */
    -goog.fx.CssSpriteAnimation.prototype.clearSpritePosition = function() {
    -  var style = this.element_.style;
    -  style.backgroundPosition = '';
    -
    -  if (typeof style.backgroundPositionX != 'undefined') {
    -    // IE needs to clear x and y to actually clear the position
    -    style.backgroundPositionX = '';
    -    style.backgroundPositionY = '';
    -  }
    -};
    -
    -
    -/** @override */
    -goog.fx.CssSpriteAnimation.prototype.disposeInternal = function() {
    -  goog.fx.CssSpriteAnimation.superClass_.disposeInternal.call(this);
    -  this.element_ = null;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/cssspriteanimation_test.html b/src/database/third_party/closure-library/closure/goog/fx/cssspriteanimation_test.html
    deleted file mode 100644
    index 48306d9656f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/cssspriteanimation_test.html
    +++ /dev/null
    @@ -1,33 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -  Author: arv@google.com (Erik Arvidsson)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.fx.CssSpriteAnimation
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.fx.CssSpriteAnimationTest');
    -  </script>
    -  <style>
    -   #test {
    -  width: 10px;
    -  height: 10px;
    -}
    -  </style>
    - </head>
    - <body>
    -  <div id="test">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/cssspriteanimation_test.js b/src/database/third_party/closure-library/closure/goog/fx/cssspriteanimation_test.js
    deleted file mode 100644
    index b29959eb047..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/cssspriteanimation_test.js
    +++ /dev/null
    @@ -1,153 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.fx.CssSpriteAnimationTest');
    -goog.setTestOnly('goog.fx.CssSpriteAnimationTest');
    -
    -goog.require('goog.fx.CssSpriteAnimation');
    -goog.require('goog.math.Box');
    -goog.require('goog.math.Size');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.jsunit');
    -
    -var el;
    -var size;
    -var box;
    -var time = 1000;
    -var anim, clock;
    -
    -function setUpPage() {
    -  clock = new goog.testing.MockClock(true);
    -  el = document.getElementById('test');
    -  size = new goog.math.Size(10, 10);
    -  box = new goog.math.Box(0, 10, 100, 0);
    -}
    -
    -function tearDownPage() {
    -  clock.dispose();
    -}
    -
    -function tearDown() {
    -  anim.clearSpritePosition();
    -  anim.dispose();
    -}
    -
    -function assertBackgroundPosition(x, y) {
    -  if (typeof el.style.backgroundPositionX != 'undefined') {
    -    assertEquals(x + 'px', el.style.backgroundPositionX);
    -    assertEquals(y + 'px', el.style.backgroundPositionY);
    -  } else {
    -    var bgPos = el.style.backgroundPosition;
    -    var message = 'Expected <' + x + 'px ' + y + 'px>, found <' + bgPos + '>';
    -    if (x == y) {
    -      // when x and y are the same the browser sometimes collapse the prop
    -      assertTrue(message,
    -                 bgPos == x || // in case of 0 without a unit
    -                 bgPos == x + 'px' ||
    -                 bgPos == x + ' ' + y ||
    -                 bgPos == x + 'px ' + y + 'px');
    -    } else {
    -      assertTrue(message,
    -                 bgPos == x + ' ' + y ||
    -                 bgPos == x + 'px ' + y ||
    -                 bgPos == x + ' ' + y + 'px' ||
    -                 bgPos == x + 'px ' + y + 'px');
    -    }
    -  }
    -}
    -
    -function testAnimation() {
    -  anim = new goog.fx.CssSpriteAnimation(el, size, box, time);
    -  anim.play();
    -
    -  assertBackgroundPosition(0, 0);
    -
    -  clock.tick(5);
    -  assertBackgroundPosition(0, 0);
    -
    -  clock.tick(95);
    -  assertBackgroundPosition(0, -10);
    -
    -  clock.tick(100);
    -  assertBackgroundPosition(0, -20);
    -
    -  clock.tick(300);
    -  assertBackgroundPosition(0, -50);
    -
    -  clock.tick(400);
    -  assertBackgroundPosition(0, -90);
    -
    -  // loop around to starting position
    -  clock.tick(100);
    -  assertBackgroundPosition(0, 0);
    -
    -  assertTrue(anim.isPlaying());
    -  assertFalse(anim.isStopped());
    -
    -  clock.tick(100);
    -  assertBackgroundPosition(0, -10);
    -}
    -
    -
    -function testAnimation_disableLoop() {
    -  anim = new goog.fx.CssSpriteAnimation(el, size, box, time, undefined,
    -      true /* opt_disableLoop */);
    -  anim.play();
    -
    -  assertBackgroundPosition(0, 0);
    -
    -  clock.tick(5);
    -  assertBackgroundPosition(0, 0);
    -
    -  clock.tick(95);
    -  assertBackgroundPosition(0, -10);
    -
    -  clock.tick(100);
    -  assertBackgroundPosition(0, -20);
    -
    -  clock.tick(300);
    -  assertBackgroundPosition(0, -50);
    -
    -  clock.tick(400);
    -  assertBackgroundPosition(0, -90);
    -
    -  // loop around to starting position
    -  clock.tick(100);
    -  assertBackgroundPosition(0, -90);
    -
    -  assertTrue(anim.isStopped());
    -  assertFalse(anim.isPlaying());
    -
    -  clock.tick(100);
    -  assertBackgroundPosition(0, -90);
    -}
    -
    -
    -function testClearSpritePosition() {
    -  anim = new goog.fx.CssSpriteAnimation(el, size, box, time);
    -  anim.play();
    -
    -  assertBackgroundPosition(0, 0);
    -
    -  clock.tick(100);
    -  assertBackgroundPosition(0, -10);
    -  anim.clearSpritePosition();
    -
    -  if (typeof el.style.backgroundPositionX != 'undefined') {
    -    assertEquals('', el.style.backgroundPositionX);
    -    assertEquals('', el.style.backgroundPositionY);
    -  }
    -
    -  assertEquals('', el.style.backgroundPosition);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/dom.js b/src/database/third_party/closure-library/closure/goog/fx/dom.js
    deleted file mode 100644
    index 8430fba8e2a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/dom.js
    +++ /dev/null
    @@ -1,686 +0,0 @@
    -// Copyright 2005 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Predefined DHTML animations such as slide, resize and fade.
    - *
    - * @see ../demos/effects.html
    - */
    -
    -goog.provide('goog.fx.dom');
    -goog.provide('goog.fx.dom.BgColorTransform');
    -goog.provide('goog.fx.dom.ColorTransform');
    -goog.provide('goog.fx.dom.Fade');
    -goog.provide('goog.fx.dom.FadeIn');
    -goog.provide('goog.fx.dom.FadeInAndShow');
    -goog.provide('goog.fx.dom.FadeOut');
    -goog.provide('goog.fx.dom.FadeOutAndHide');
    -goog.provide('goog.fx.dom.PredefinedEffect');
    -goog.provide('goog.fx.dom.Resize');
    -goog.provide('goog.fx.dom.ResizeHeight');
    -goog.provide('goog.fx.dom.ResizeWidth');
    -goog.provide('goog.fx.dom.Scroll');
    -goog.provide('goog.fx.dom.Slide');
    -goog.provide('goog.fx.dom.SlideFrom');
    -goog.provide('goog.fx.dom.Swipe');
    -
    -goog.require('goog.color');
    -goog.require('goog.events');
    -goog.require('goog.fx.Animation');
    -goog.require('goog.fx.Transition');
    -goog.require('goog.style');
    -goog.require('goog.style.bidi');
    -
    -
    -
    -/**
    - * Abstract class that provides reusable functionality for predefined animations
    - * that manipulate a single DOM element
    - *
    - * @param {Element} element Dom Node to be used in the animation.
    - * @param {Array<number>} start Array for start coordinates.
    - * @param {Array<number>} end Array for end coordinates.
    - * @param {number} time Length of animation in milliseconds.
    - * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
    - * @extends {goog.fx.Animation}
    - * @constructor
    - */
    -goog.fx.dom.PredefinedEffect = function(element, start, end, time, opt_acc) {
    -  goog.fx.Animation.call(this, start, end, time, opt_acc);
    -
    -  /**
    -   * DOM Node that will be used in the animation
    -   * @type {Element}
    -   */
    -  this.element = element;
    -
    -  /**
    -   * Whether the element is rendered right-to-left. We cache this here for
    -   * efficiency.
    -   * @private {boolean|undefined}
    -   */
    -  this.rightToLeft_;
    -};
    -goog.inherits(goog.fx.dom.PredefinedEffect, goog.fx.Animation);
    -
    -
    -/**
    - * Called to update the style of the element.
    - * @protected
    - */
    -goog.fx.dom.PredefinedEffect.prototype.updateStyle = goog.nullFunction;
    -
    -
    -/**
    - * Whether the DOM element being manipulated is rendered right-to-left.
    - * @return {boolean} True if the DOM element is rendered right-to-left, false
    - *     otherwise.
    - */
    -goog.fx.dom.PredefinedEffect.prototype.isRightToLeft = function() {
    -  if (!goog.isDef(this.rightToLeft_)) {
    -    this.rightToLeft_ = goog.style.isRightToLeft(this.element);
    -  }
    -  return this.rightToLeft_;
    -};
    -
    -
    -/** @override */
    -goog.fx.dom.PredefinedEffect.prototype.onAnimate = function() {
    -  this.updateStyle();
    -  goog.fx.dom.PredefinedEffect.superClass_.onAnimate.call(this);
    -};
    -
    -
    -/** @override */
    -goog.fx.dom.PredefinedEffect.prototype.onEnd = function() {
    -  this.updateStyle();
    -  goog.fx.dom.PredefinedEffect.superClass_.onEnd.call(this);
    -};
    -
    -
    -/** @override */
    -goog.fx.dom.PredefinedEffect.prototype.onBegin = function() {
    -  this.updateStyle();
    -  goog.fx.dom.PredefinedEffect.superClass_.onBegin.call(this);
    -};
    -
    -
    -
    -/**
    - * Creates an animation object that will slide an element from A to B.  (This
    - * in effect automatically sets up the onanimate event for an Animation object)
    - *
    - * Start and End should be 2 dimensional arrays
    - *
    - * @param {Element} element Dom Node to be used in the animation.
    - * @param {Array<number>} start 2D array for start coordinates (X, Y).
    - * @param {Array<number>} end 2D array for end coordinates (X, Y).
    - * @param {number} time Length of animation in milliseconds.
    - * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
    - * @extends {goog.fx.dom.PredefinedEffect}
    - * @constructor
    - */
    -goog.fx.dom.Slide = function(element, start, end, time, opt_acc) {
    -  if (start.length != 2 || end.length != 2) {
    -    throw Error('Start and end points must be 2D');
    -  }
    -  goog.fx.dom.PredefinedEffect.apply(this, arguments);
    -};
    -goog.inherits(goog.fx.dom.Slide, goog.fx.dom.PredefinedEffect);
    -
    -
    -/** @override */
    -goog.fx.dom.Slide.prototype.updateStyle = function() {
    -  var pos = (this.isRightPositioningForRtlEnabled() && this.isRightToLeft()) ?
    -      'right' : 'left';
    -  this.element.style[pos] = Math.round(this.coords[0]) + 'px';
    -  this.element.style.top = Math.round(this.coords[1]) + 'px';
    -};
    -
    -
    -
    -/**
    - * Slides an element from its current position.
    - *
    - * @param {Element} element DOM node to be used in the animation.
    - * @param {Array<number>} end 2D array for end coordinates (X, Y).
    - * @param {number} time Length of animation in milliseconds.
    - * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
    - * @extends {goog.fx.dom.Slide}
    - * @constructor
    - */
    -goog.fx.dom.SlideFrom = function(element, end, time, opt_acc) {
    -  var offsetLeft = this.isRightPositioningForRtlEnabled() ?
    -      goog.style.bidi.getOffsetStart(element) : element.offsetLeft;
    -  var start = [offsetLeft, element.offsetTop];
    -  goog.fx.dom.Slide.call(this, element, start, end, time, opt_acc);
    -};
    -goog.inherits(goog.fx.dom.SlideFrom, goog.fx.dom.Slide);
    -
    -
    -/** @override */
    -goog.fx.dom.SlideFrom.prototype.onBegin = function() {
    -  var offsetLeft = this.isRightPositioningForRtlEnabled() ?
    -      goog.style.bidi.getOffsetStart(this.element) : this.element.offsetLeft;
    -  this.startPoint = [offsetLeft, this.element.offsetTop];
    -  goog.fx.dom.SlideFrom.superClass_.onBegin.call(this);
    -};
    -
    -
    -
    -/**
    - * Creates an animation object that will slide an element into its final size.
    - * Requires that the element is absolutely positioned.
    - *
    - * @param {Element} element Dom Node to be used in the animation.
    - * @param {Array<number>} start 2D array for start size (W, H).
    - * @param {Array<number>} end 2D array for end size (W, H).
    - * @param {number} time Length of animation in milliseconds.
    - * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
    - * @extends {goog.fx.dom.PredefinedEffect}
    - * @constructor
    - */
    -goog.fx.dom.Swipe = function(element, start, end, time, opt_acc) {
    -  if (start.length != 2 || end.length != 2) {
    -    throw Error('Start and end points must be 2D');
    -  }
    -  goog.fx.dom.PredefinedEffect.apply(this, arguments);
    -
    -  /**
    -   * Maximum width for element.
    -   * @type {number}
    -   * @private
    -   */
    -  this.maxWidth_ = Math.max(this.endPoint[0], this.startPoint[0]);
    -
    -  /**
    -   * Maximum height for element.
    -   * @type {number}
    -   * @private
    -   */
    -  this.maxHeight_ = Math.max(this.endPoint[1], this.startPoint[1]);
    -};
    -goog.inherits(goog.fx.dom.Swipe, goog.fx.dom.PredefinedEffect);
    -
    -
    -/**
    - * Animation event handler that will resize an element by setting its width,
    - * height and clipping.
    - * @protected
    - * @override
    - */
    -goog.fx.dom.Swipe.prototype.updateStyle = function() {
    -  var x = this.coords[0];
    -  var y = this.coords[1];
    -  this.clip_(Math.round(x), Math.round(y), this.maxWidth_, this.maxHeight_);
    -  this.element.style.width = Math.round(x) + 'px';
    -  var marginX = (this.isRightPositioningForRtlEnabled() &&
    -      this.isRightToLeft()) ? 'marginRight' : 'marginLeft';
    -
    -  this.element.style[marginX] = Math.round(x) - this.maxWidth_ + 'px';
    -  this.element.style.marginTop = Math.round(y) - this.maxHeight_ + 'px';
    -};
    -
    -
    -/**
    - * Helper function for setting element clipping.
    - * @param {number} x Current element width.
    - * @param {number} y Current element height.
    - * @param {number} w Maximum element width.
    - * @param {number} h Maximum element height.
    - * @private
    - */
    -goog.fx.dom.Swipe.prototype.clip_ = function(x, y, w, h) {
    -  this.element.style.clip =
    -      'rect(' + (h - y) + 'px ' + w + 'px ' + h + 'px ' + (w - x) + 'px)';
    -};
    -
    -
    -
    -/**
    - * Creates an animation object that will scroll an element from A to B.
    - *
    - * Start and End should be 2 dimensional arrays
    - *
    - * @param {Element} element Dom Node to be used in the animation.
    - * @param {Array<number>} start 2D array for start scroll left and top.
    - * @param {Array<number>} end 2D array for end scroll left and top.
    - * @param {number} time Length of animation in milliseconds.
    - * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
    - * @extends {goog.fx.dom.PredefinedEffect}
    - * @constructor
    - */
    -goog.fx.dom.Scroll = function(element, start, end, time, opt_acc) {
    -  if (start.length != 2 || end.length != 2) {
    -    throw Error('Start and end points must be 2D');
    -  }
    -  goog.fx.dom.PredefinedEffect.apply(this, arguments);
    -};
    -goog.inherits(goog.fx.dom.Scroll, goog.fx.dom.PredefinedEffect);
    -
    -
    -/**
    - * Animation event handler that will set the scroll position of an element.
    - * @protected
    - * @override
    - */
    -goog.fx.dom.Scroll.prototype.updateStyle = function() {
    -  if (this.isRightPositioningForRtlEnabled()) {
    -    goog.style.bidi.setScrollOffset(this.element, Math.round(this.coords[0]));
    -  } else {
    -    this.element.scrollLeft = Math.round(this.coords[0]);
    -  }
    -  this.element.scrollTop = Math.round(this.coords[1]);
    -};
    -
    -
    -
    -/**
    - * Creates an animation object that will resize an element between two widths
    - * and heights.
    - *
    - * Start and End should be 2 dimensional arrays
    - *
    - * @param {Element} element Dom Node to be used in the animation.
    - * @param {Array<number>} start 2D array for start width and height.
    - * @param {Array<number>} end 2D array for end width and height.
    - * @param {number} time Length of animation in milliseconds.
    - * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
    - * @extends {goog.fx.dom.PredefinedEffect}
    - * @constructor
    - */
    -goog.fx.dom.Resize = function(element, start, end, time, opt_acc) {
    -  if (start.length != 2 || end.length != 2) {
    -    throw Error('Start and end points must be 2D');
    -  }
    -  goog.fx.dom.PredefinedEffect.apply(this, arguments);
    -};
    -goog.inherits(goog.fx.dom.Resize, goog.fx.dom.PredefinedEffect);
    -
    -
    -/**
    - * Animation event handler that will resize an element by setting its width and
    - * height.
    - * @protected
    - * @override
    - */
    -goog.fx.dom.Resize.prototype.updateStyle = function() {
    -  this.element.style.width = Math.round(this.coords[0]) + 'px';
    -  this.element.style.height = Math.round(this.coords[1]) + 'px';
    -};
    -
    -
    -
    -/**
    - * Creates an animation object that will resize an element between two widths
    - *
    - * Start and End should be numbers
    - *
    - * @param {Element} element Dom Node to be used in the animation.
    - * @param {number} start Start width.
    - * @param {number} end End width.
    - * @param {number} time Length of animation in milliseconds.
    - * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
    - * @extends {goog.fx.dom.PredefinedEffect}
    - * @constructor
    - */
    -goog.fx.dom.ResizeWidth = function(element, start, end, time, opt_acc) {
    -  goog.fx.dom.PredefinedEffect.call(this, element, [start],
    -                                    [end], time, opt_acc);
    -};
    -goog.inherits(goog.fx.dom.ResizeWidth, goog.fx.dom.PredefinedEffect);
    -
    -
    -/**
    - * Animation event handler that will resize an element by setting its width.
    - * @protected
    - * @override
    - */
    -goog.fx.dom.ResizeWidth.prototype.updateStyle = function() {
    -  this.element.style.width = Math.round(this.coords[0]) + 'px';
    -};
    -
    -
    -
    -/**
    - * Creates an animation object that will resize an element between two heights
    - *
    - * Start and End should be numbers
    - *
    - * @param {Element} element Dom Node to be used in the animation.
    - * @param {number} start Start height.
    - * @param {number} end End height.
    - * @param {number} time Length of animation in milliseconds.
    - * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
    - * @extends {goog.fx.dom.PredefinedEffect}
    - * @constructor
    - */
    -goog.fx.dom.ResizeHeight = function(element, start, end, time, opt_acc) {
    -  goog.fx.dom.PredefinedEffect.call(this, element, [start],
    -                                    [end], time, opt_acc);
    -};
    -goog.inherits(goog.fx.dom.ResizeHeight, goog.fx.dom.PredefinedEffect);
    -
    -
    -/**
    - * Animation event handler that will resize an element by setting its height.
    - * @protected
    - * @override
    - */
    -goog.fx.dom.ResizeHeight.prototype.updateStyle = function() {
    -  this.element.style.height = Math.round(this.coords[0]) + 'px';
    -};
    -
    -
    -
    -/**
    - * Creates an animation object that fades the opacity of an element between two
    - * limits.
    - *
    - * Start and End should be floats between 0 and 1
    - *
    - * @param {Element} element Dom Node to be used in the animation.
    - * @param {Array<number>|number} start 1D Array or Number with start opacity.
    - * @param {Array<number>|number} end 1D Array or Number for end opacity.
    - * @param {number} time Length of animation in milliseconds.
    - * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
    - * @extends {goog.fx.dom.PredefinedEffect}
    - * @constructor
    - */
    -goog.fx.dom.Fade = function(element, start, end, time, opt_acc) {
    -  if (goog.isNumber(start)) start = [start];
    -  if (goog.isNumber(end)) end = [end];
    -
    -  goog.fx.dom.Fade.base(this, 'constructor',
    -      element, start, end, time, opt_acc);
    -
    -  if (start.length != 1 || end.length != 1) {
    -    throw Error('Start and end points must be 1D');
    -  }
    -
    -  /**
    -   * The last opacity we set, or -1 for not set.
    -   * @private {number}
    -   */
    -  this.lastOpacityUpdate_ = goog.fx.dom.Fade.OPACITY_UNSET_;
    -};
    -goog.inherits(goog.fx.dom.Fade, goog.fx.dom.PredefinedEffect);
    -
    -
    -/**
    - * The quantization of opacity values to use.
    - * @private {number}
    - */
    -goog.fx.dom.Fade.TOLERANCE_ = 1.0 / 0x400;  // 10-bit color
    -
    -
    -/**
    - * Value indicating that the opacity must be set on next update.
    - * @private {number}
    - */
    -goog.fx.dom.Fade.OPACITY_UNSET_ = -1;
    -
    -
    -/**
    - * Animation event handler that will set the opacity of an element.
    - * @protected
    - * @override
    - */
    -goog.fx.dom.Fade.prototype.updateStyle = function() {
    -  var opacity = this.coords[0];
    -  var delta = Math.abs(opacity - this.lastOpacityUpdate_);
    -  // In order to keep eager browsers from over-rendering, only update
    -  // on a potentially visible change in opacity.
    -  if (delta >= goog.fx.dom.Fade.TOLERANCE_) {
    -    goog.style.setOpacity(this.element, opacity);
    -    this.lastOpacityUpdate_ = opacity;
    -  }
    -};
    -
    -
    -/** @override */
    -goog.fx.dom.Fade.prototype.onBegin = function() {
    -  this.lastOpacityUpdate_ = goog.fx.dom.Fade.OPACITY_UNSET_;
    -  goog.fx.dom.Fade.base(this, 'onBegin');
    -};
    -
    -
    -/** @override */
    -goog.fx.dom.Fade.prototype.onEnd = function() {
    -  this.lastOpacityUpdate_ = goog.fx.dom.Fade.OPACITY_UNSET_;
    -  goog.fx.dom.Fade.base(this, 'onEnd');
    -};
    -
    -
    -/**
    - * Animation event handler that will show the element.
    - */
    -goog.fx.dom.Fade.prototype.show = function() {
    -  this.element.style.display = '';
    -};
    -
    -
    -/**
    - * Animation event handler that will hide the element
    - */
    -goog.fx.dom.Fade.prototype.hide = function() {
    -  this.element.style.display = 'none';
    -};
    -
    -
    -
    -/**
    - * Fades an element out from full opacity to completely transparent.
    - *
    - * @param {Element} element Dom Node to be used in the animation.
    - * @param {number} time Length of animation in milliseconds.
    - * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
    - * @extends {goog.fx.dom.Fade}
    - * @constructor
    - */
    -goog.fx.dom.FadeOut = function(element, time, opt_acc) {
    -  goog.fx.dom.Fade.call(this, element, 1, 0, time, opt_acc);
    -};
    -goog.inherits(goog.fx.dom.FadeOut, goog.fx.dom.Fade);
    -
    -
    -
    -/**
    - * Fades an element in from completely transparent to fully opacity.
    - *
    - * @param {Element} element Dom Node to be used in the animation.
    - * @param {number} time Length of animation in milliseconds.
    - * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
    - * @extends {goog.fx.dom.Fade}
    - * @constructor
    - */
    -goog.fx.dom.FadeIn = function(element, time, opt_acc) {
    -  goog.fx.dom.Fade.call(this, element, 0, 1, time, opt_acc);
    -};
    -goog.inherits(goog.fx.dom.FadeIn, goog.fx.dom.Fade);
    -
    -
    -
    -/**
    - * Fades an element out from full opacity to completely transparent and then
    - * sets the display to 'none'
    - *
    - * @param {Element} element Dom Node to be used in the animation.
    - * @param {number} time Length of animation in milliseconds.
    - * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
    - * @extends {goog.fx.dom.Fade}
    - * @constructor
    - */
    -goog.fx.dom.FadeOutAndHide = function(element, time, opt_acc) {
    -  goog.fx.dom.Fade.call(this, element, 1, 0, time, opt_acc);
    -};
    -goog.inherits(goog.fx.dom.FadeOutAndHide, goog.fx.dom.Fade);
    -
    -
    -/** @override */
    -goog.fx.dom.FadeOutAndHide.prototype.onBegin = function() {
    -  this.show();
    -  goog.fx.dom.FadeOutAndHide.superClass_.onBegin.call(this);
    -};
    -
    -
    -/** @override */
    -goog.fx.dom.FadeOutAndHide.prototype.onEnd = function() {
    -  this.hide();
    -  goog.fx.dom.FadeOutAndHide.superClass_.onEnd.call(this);
    -};
    -
    -
    -
    -/**
    - * Sets an element's display to be visible and then fades an element in from
    - * completely transparent to fully opaque.
    - *
    - * @param {Element} element Dom Node to be used in the animation.
    - * @param {number} time Length of animation in milliseconds.
    - * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
    - * @extends {goog.fx.dom.Fade}
    - * @constructor
    - */
    -goog.fx.dom.FadeInAndShow = function(element, time, opt_acc) {
    -  goog.fx.dom.Fade.call(this, element, 0, 1, time, opt_acc);
    -};
    -goog.inherits(goog.fx.dom.FadeInAndShow, goog.fx.dom.Fade);
    -
    -
    -/** @override */
    -goog.fx.dom.FadeInAndShow.prototype.onBegin = function() {
    -  this.show();
    -  goog.fx.dom.FadeInAndShow.superClass_.onBegin.call(this);
    -};
    -
    -
    -
    -/**
    - * Provides a transformation of an elements background-color.
    - *
    - * Start and End should be 3D arrays representing R,G,B
    - *
    - * @param {Element} element Dom Node to be used in the animation.
    - * @param {Array<number>} start 3D Array for RGB of start color.
    - * @param {Array<number>} end 3D Array for RGB of end color.
    - * @param {number} time Length of animation in milliseconds.
    - * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
    - * @extends {goog.fx.dom.PredefinedEffect}
    - * @constructor
    - */
    -goog.fx.dom.BgColorTransform = function(element, start, end, time, opt_acc) {
    -  if (start.length != 3 || end.length != 3) {
    -    throw Error('Start and end points must be 3D');
    -  }
    -  goog.fx.dom.PredefinedEffect.apply(this, arguments);
    -};
    -goog.inherits(goog.fx.dom.BgColorTransform, goog.fx.dom.PredefinedEffect);
    -
    -
    -/**
    - * Animation event handler that will set the background-color of an element
    - */
    -goog.fx.dom.BgColorTransform.prototype.setColor = function() {
    -  var coordsAsInts = [];
    -  for (var i = 0; i < this.coords.length; i++) {
    -    coordsAsInts[i] = Math.round(this.coords[i]);
    -  }
    -  var color = 'rgb(' + coordsAsInts.join(',') + ')';
    -  this.element.style.backgroundColor = color;
    -};
    -
    -
    -/** @override */
    -goog.fx.dom.BgColorTransform.prototype.updateStyle = function() {
    -  this.setColor();
    -};
    -
    -
    -/**
    - * Fade elements background color from start color to the element's current
    - * background color.
    - *
    - * Start should be a 3D array representing R,G,B
    - *
    - * @param {Element} element Dom Node to be used in the animation.
    - * @param {Array<number>} start 3D Array for RGB of start color.
    - * @param {number} time Length of animation in milliseconds.
    - * @param {goog.events.EventHandler=} opt_eventHandler Optional event handler
    - *     to use when listening for events.
    - */
    -goog.fx.dom.bgColorFadeIn = function(element, start, time, opt_eventHandler) {
    -  var initialBgColor = element.style.backgroundColor || '';
    -  var computedBgColor = goog.style.getBackgroundColor(element);
    -  var end;
    -
    -  if (computedBgColor && computedBgColor != 'transparent' &&
    -      computedBgColor != 'rgba(0, 0, 0, 0)') {
    -    end = goog.color.hexToRgb(goog.color.parse(computedBgColor).hex);
    -  } else {
    -    end = [255, 255, 255];
    -  }
    -
    -  var anim = new goog.fx.dom.BgColorTransform(element, start, end, time);
    -
    -  function setBgColor() {
    -    element.style.backgroundColor = initialBgColor;
    -  }
    -
    -  if (opt_eventHandler) {
    -    opt_eventHandler.listen(
    -        anim, goog.fx.Transition.EventType.END, setBgColor);
    -  } else {
    -    goog.events.listen(
    -        anim, goog.fx.Transition.EventType.END, setBgColor);
    -  }
    -
    -  anim.play();
    -};
    -
    -
    -
    -/**
    - * Provides a transformation of an elements color.
    - *
    - * @param {Element} element Dom Node to be used in the animation.
    - * @param {Array<number>} start 3D Array representing R,G,B.
    - * @param {Array<number>} end 3D Array representing R,G,B.
    - * @param {number} time Length of animation in milliseconds.
    - * @param {Function=} opt_acc Acceleration function, returns 0-1 for inputs 0-1.
    - * @constructor
    - * @extends {goog.fx.dom.PredefinedEffect}
    - */
    -goog.fx.dom.ColorTransform = function(element, start, end, time, opt_acc) {
    -  if (start.length != 3 || end.length != 3) {
    -    throw Error('Start and end points must be 3D');
    -  }
    -  goog.fx.dom.PredefinedEffect.apply(this, arguments);
    -};
    -goog.inherits(goog.fx.dom.ColorTransform, goog.fx.dom.PredefinedEffect);
    -
    -
    -/**
    - * Animation event handler that will set the color of an element.
    - * @protected
    - * @override
    - */
    -goog.fx.dom.ColorTransform.prototype.updateStyle = function() {
    -  var coordsAsInts = [];
    -  for (var i = 0; i < this.coords.length; i++) {
    -    coordsAsInts[i] = Math.round(this.coords[i]);
    -  }
    -  var color = 'rgb(' + coordsAsInts.join(',') + ')';
    -  this.element.style.color = color;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/dragdrop.js b/src/database/third_party/closure-library/closure/goog/fx/dragdrop.js
    deleted file mode 100644
    index 7fe95455f69..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/dragdrop.js
    +++ /dev/null
    @@ -1,50 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Single Element Drag and Drop.
    - *
    - * Drag and drop implementation for sources/targets consisting of a single
    - * element.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - * @see ../demos/dragdrop.html
    - */
    -
    -goog.provide('goog.fx.DragDrop');
    -
    -goog.require('goog.fx.AbstractDragDrop');
    -goog.require('goog.fx.DragDropItem');
    -
    -
    -
    -/**
    - * Drag/drop implementation for creating drag sources/drop targets consisting of
    - * a single HTML Element.
    - *
    - * @param {Element|string} element Dom Node, or string representation of node
    - *     id, to be used as drag source/drop target.
    - * @param {Object=} opt_data Data associated with the source/target.
    - * @throws Error If no element argument is provided or if the type is invalid
    - * @extends {goog.fx.AbstractDragDrop}
    - * @constructor
    - */
    -goog.fx.DragDrop = function(element, opt_data) {
    -  goog.fx.AbstractDragDrop.call(this);
    -
    -  var item = new goog.fx.DragDropItem(element, opt_data);
    -  item.setParent(this);
    -  this.items_.push(item);
    -};
    -goog.inherits(goog.fx.DragDrop, goog.fx.AbstractDragDrop);
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/dragdropgroup.js b/src/database/third_party/closure-library/closure/goog/fx/dragdropgroup.js
    deleted file mode 100644
    index 01aab56a610..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/dragdropgroup.js
    +++ /dev/null
    @@ -1,109 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Multiple Element Drag and Drop.
    - *
    - * Drag and drop implementation for sources/targets consisting of multiple
    - * elements.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - * @see ../demos/dragdrop.html
    - */
    -
    -goog.provide('goog.fx.DragDropGroup');
    -
    -goog.require('goog.dom');
    -goog.require('goog.fx.AbstractDragDrop');
    -goog.require('goog.fx.DragDropItem');
    -
    -
    -
    -/**
    - * Drag/drop implementation for creating drag sources/drop targets consisting of
    - * multiple HTML Elements (items). All items share the same drop target(s) but
    - * can be dragged individually.
    - *
    - * @extends {goog.fx.AbstractDragDrop}
    - * @constructor
    - */
    -goog.fx.DragDropGroup = function() {
    -  goog.fx.AbstractDragDrop.call(this);
    -};
    -goog.inherits(goog.fx.DragDropGroup, goog.fx.AbstractDragDrop);
    -
    -
    -/**
    - * Add item to drag object.
    - *
    - * @param {Element|string} element Dom Node, or string representation of node
    - *     id, to be used as drag source/drop target.
    - * @param {Object=} opt_data Data associated with the source/target.
    - * @throws Error If no element argument is provided or if the type is
    - *     invalid
    - * @override
    - */
    -goog.fx.DragDropGroup.prototype.addItem = function(element, opt_data) {
    -  var item = new goog.fx.DragDropItem(element, opt_data);
    -  this.addDragDropItem(item);
    -};
    -
    -
    -/**
    - * Add DragDropItem to drag object.
    - *
    - * @param {goog.fx.DragDropItem} item DragDropItem being added to the
    - *     drag object.
    - * @throws Error If no element argument is provided or if the type is
    - *     invalid
    - */
    -goog.fx.DragDropGroup.prototype.addDragDropItem = function(item) {
    -  item.setParent(this);
    -  this.items_.push(item);
    -  if (this.isInitialized()) {
    -    this.initItem(item);
    -  }
    -};
    -
    -
    -/**
    - * Remove item from drag object.
    - *
    - * @param {Element|string} element Dom Node, or string representation of node
    - *     id, that was previously added with addItem().
    - */
    -goog.fx.DragDropGroup.prototype.removeItem = function(element) {
    -  element = goog.dom.getElement(element);
    -  for (var item, i = 0; item = this.items_[i]; i++) {
    -    if (item.element == element) {
    -      this.items_.splice(i, 1);
    -      this.disposeItem(item);
    -      break;
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Marks the supplied list of items as selected. A drag operation for any of the
    - * selected items will affect all of them.
    - *
    - * @param {Array<goog.fx.DragDropItem>} list List of items to select or null to
    - *     clear selection.
    - *
    - * TODO(eae): Not yet implemented.
    - */
    -goog.fx.DragDropGroup.prototype.setSelection = function(list) {
    -
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/dragdropgroup_test.html b/src/database/third_party/closure-library/closure/goog/fx/dragdropgroup_test.html
    deleted file mode 100644
    index 38a8fa5520c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/dragdropgroup_test.html
    +++ /dev/null
    @@ -1,32 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.fx.DragDropGroup
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.fx.DragDropGroupTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="s1" class="s">
    -  </div>
    -  <div id="s2" class="s">
    -  </div>
    -  <div id="t1" class="t">
    -  </div>
    -  <div id="t2" class="t">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/dragdropgroup_test.js b/src/database/third_party/closure-library/closure/goog/fx/dragdropgroup_test.js
    deleted file mode 100644
    index f53fc177f73..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/dragdropgroup_test.js
    +++ /dev/null
    @@ -1,229 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.fx.DragDropGroupTest');
    -goog.setTestOnly('goog.fx.DragDropGroupTest');
    -
    -goog.require('goog.events');
    -goog.require('goog.fx.DragDropGroup');
    -goog.require('goog.testing.jsunit');
    -
    -var s1;
    -var s2;
    -var t1;
    -var t2;
    -
    -var source = null;
    -var target = null;
    -
    -function setUpPage() {
    -  s1 = document.getElementById('s1');
    -  s2 = document.getElementById('s2');
    -  t1 = document.getElementById('t1');
    -  t2 = document.getElementById('t2');
    -}
    -
    -
    -function setUp() {
    -  source = new goog.fx.DragDropGroup();
    -  source.setSourceClass('ss');
    -  source.setTargetClass('st');
    -
    -  target = new goog.fx.DragDropGroup();
    -  target.setSourceClass('ts');
    -  target.setTargetClass('tt');
    -
    -  source.addTarget(target);
    -}
    -
    -
    -function tearDown() {
    -  source.removeItems();
    -  target.removeItems();
    -}
    -
    -
    -function addElementsToGroups() {
    -  source.addItem(s1);
    -  source.addItem(s2);
    -  target.addItem(t1);
    -  target.addItem(t2);
    -}
    -
    -
    -function testAddItemsBeforeInit() {
    -  addElementsToGroups();
    -  source.init();
    -  target.init();
    -
    -  assertEquals(2, source.items_.length);
    -  assertEquals(2, target.items_.length);
    -
    -  assertEquals('s ss', s1.className);
    -  assertEquals('s ss', s2.className);
    -  assertEquals('t tt', t1.className);
    -  assertEquals('t tt', t2.className);
    -
    -  assertTrue(goog.events.hasListener(s1));
    -  assertTrue(goog.events.hasListener(s2));
    -  assertFalse(goog.events.hasListener(t1));
    -  assertFalse(goog.events.hasListener(t2));
    -}
    -
    -function testAddItemsAfterInit() {
    -  source.init();
    -  target.init();
    -  addElementsToGroups();
    -
    -  assertEquals(2, source.items_.length);
    -  assertEquals(2, target.items_.length);
    -
    -  assertEquals('s ss', s1.className);
    -  assertEquals('s ss', s2.className);
    -  assertEquals('t tt', t1.className);
    -  assertEquals('t tt', t2.className);
    -
    -  assertTrue(goog.events.hasListener(s1));
    -  assertTrue(goog.events.hasListener(s2));
    -  assertFalse(goog.events.hasListener(t1));
    -  assertFalse(goog.events.hasListener(t2));
    -}
    -
    -
    -function testRemoveItems() {
    -  source.init();
    -  target.init();
    -  addElementsToGroups();
    -
    -  assertEquals(2, source.items_.length);
    -  assertEquals(s1, source.items_[0].element);
    -  assertEquals(s2, source.items_[1].element);
    -
    -  assertEquals('s ss', s1.className);
    -  assertEquals('s ss', s2.className);
    -  assertTrue(goog.events.hasListener(s1));
    -  assertTrue(goog.events.hasListener(s2));
    -
    -  source.removeItems();
    -
    -  assertEquals(0, source.items_.length);
    -
    -  assertEquals('s', s1.className);
    -  assertEquals('s', s2.className);
    -  assertFalse(goog.events.hasListener(s1));
    -  assertFalse(goog.events.hasListener(s2));
    -}
    -
    -function testRemoveSourceItem1() {
    -  source.init();
    -  target.init();
    -  addElementsToGroups();
    -
    -  assertEquals(2, source.items_.length);
    -  assertEquals(s1, source.items_[0].element);
    -  assertEquals(s2, source.items_[1].element);
    -
    -  assertEquals('s ss', s1.className);
    -  assertEquals('s ss', s2.className);
    -  assertTrue(goog.events.hasListener(s1));
    -  assertTrue(goog.events.hasListener(s2));
    -
    -  source.removeItem(s1);
    -
    -  assertEquals(1, source.items_.length);
    -  assertEquals(s2, source.items_[0].element);
    -
    -  assertEquals('s', s1.className);
    -  assertEquals('s ss', s2.className);
    -  assertFalse(goog.events.hasListener(s1));
    -  assertTrue(goog.events.hasListener(s2));
    -}
    -
    -
    -function testRemoveSourceItem2() {
    -  source.init();
    -  target.init();
    -  addElementsToGroups();
    -
    -  assertEquals(2, source.items_.length);
    -  assertEquals(s1, source.items_[0].element);
    -  assertEquals(s2, source.items_[1].element);
    -
    -  assertEquals('s ss', s1.className);
    -  assertEquals('s ss', s2.className);
    -  assertTrue(goog.events.hasListener(s1));
    -  assertTrue(goog.events.hasListener(s2));
    -
    -  source.removeItem(s2);
    -
    -  assertEquals(1, source.items_.length);
    -  assertEquals(s1, source.items_[0].element);
    -
    -  assertEquals('s ss', s1.className);
    -  assertEquals('s', s2.className);
    -  assertTrue(goog.events.hasListener(s1));
    -  assertFalse(goog.events.hasListener(s2));
    -}
    -
    -
    -function testRemoveTargetItem1() {
    -  source.init();
    -  target.init();
    -  addElementsToGroups();
    -
    -  assertEquals(2, target.items_.length);
    -  assertEquals(t1, target.items_[0].element);
    -  assertEquals(t2, target.items_[1].element);
    -
    -  assertEquals('t tt', t1.className);
    -  assertEquals('t tt', t2.className);
    -  assertFalse(goog.events.hasListener(t1));
    -  assertFalse(goog.events.hasListener(t2));
    -
    -  target.removeItem(t1);
    -
    -  assertEquals(1, target.items_.length);
    -  assertEquals(t2, target.items_[0].element);
    -
    -  assertEquals('t', t1.className);
    -  assertEquals('t tt', t2.className);
    -  assertFalse(goog.events.hasListener(t1));
    -  assertFalse(goog.events.hasListener(t2));
    -}
    -
    -
    -function testRemoveTargetItem2() {
    -  source.init();
    -  target.init();
    -  addElementsToGroups();
    -
    -  assertEquals(2, target.items_.length);
    -  assertEquals(t1, target.items_[0].element);
    -  assertEquals(t2, target.items_[1].element);
    -
    -  assertEquals('t tt', t1.className);
    -  assertEquals('t tt', t2.className);
    -  assertFalse(goog.events.hasListener(t1));
    -  assertFalse(goog.events.hasListener(t2));
    -
    -  target.removeItem(t2);
    -
    -  assertEquals(1, target.items_.length);
    -  assertEquals(t1, target.items_[0].element);
    -
    -  assertEquals('t tt', t1.className);
    -  assertEquals('t', t2.className);
    -  assertFalse(goog.events.hasListener(t1));
    -  assertFalse(goog.events.hasListener(t2));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/dragger.js b/src/database/third_party/closure-library/closure/goog/fx/dragger.js
    deleted file mode 100644
    index 5e2cb1060ad..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/dragger.js
    +++ /dev/null
    @@ -1,847 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Drag Utilities.
    - *
    - * Provides extensible functionality for drag & drop behaviour.
    - *
    - * @see ../demos/drag.html
    - * @see ../demos/dragger.html
    - */
    -
    -
    -goog.provide('goog.fx.DragEvent');
    -goog.provide('goog.fx.Dragger');
    -goog.provide('goog.fx.Dragger.EventType');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.math.Rect');
    -goog.require('goog.style');
    -goog.require('goog.style.bidi');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * A class that allows mouse or touch-based dragging (moving) of an element
    - *
    - * @param {Element} target The element that will be dragged.
    - * @param {Element=} opt_handle An optional handle to control the drag, if null
    - *     the target is used.
    - * @param {goog.math.Rect=} opt_limits Object containing left, top, width,
    - *     and height.
    - *
    - * @extends {goog.events.EventTarget}
    - * @constructor
    - */
    -goog.fx.Dragger = function(target, opt_handle, opt_limits) {
    -  goog.events.EventTarget.call(this);
    -  this.target = target;
    -  this.handle = opt_handle || target;
    -  this.limits = opt_limits || new goog.math.Rect(NaN, NaN, NaN, NaN);
    -
    -  this.document_ = goog.dom.getOwnerDocument(target);
    -  this.eventHandler_ = new goog.events.EventHandler(this);
    -  this.registerDisposable(this.eventHandler_);
    -
    -  // Add listener. Do not use the event handler here since the event handler is
    -  // used for listeners added and removed during the drag operation.
    -  goog.events.listen(this.handle,
    -      [goog.events.EventType.TOUCHSTART, goog.events.EventType.MOUSEDOWN],
    -      this.startDrag, false, this);
    -};
    -goog.inherits(goog.fx.Dragger, goog.events.EventTarget);
    -// Dragger is meant to be extended, but defines most properties on its
    -// prototype, thus making it unsuitable for sealing.
    -goog.tagUnsealableClass(goog.fx.Dragger);
    -
    -
    -/**
    - * Whether setCapture is supported by the browser.
    - * @type {boolean}
    - * @private
    - */
    -goog.fx.Dragger.HAS_SET_CAPTURE_ =
    -    // IE and Gecko after 1.9.3 has setCapture
    -    // WebKit does not yet: https://bugs.webkit.org/show_bug.cgi?id=27330
    -    goog.userAgent.IE ||
    -    goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.9.3');
    -
    -
    -/**
    - * Creates copy of node being dragged.  This is a utility function to be used
    - * wherever it is inappropriate for the original source to follow the mouse
    - * cursor itself.
    - *
    - * @param {Element} sourceEl Element to copy.
    - * @return {!Element} The clone of {@code sourceEl}.
    - */
    -goog.fx.Dragger.cloneNode = function(sourceEl) {
    -  var clonedEl = /** @type {Element} */ (sourceEl.cloneNode(true)),
    -      origTexts = sourceEl.getElementsByTagName('textarea'),
    -      dragTexts = clonedEl.getElementsByTagName('textarea');
    -  // Cloning does not copy the current value of textarea elements, so correct
    -  // this manually.
    -  for (var i = 0; i < origTexts.length; i++) {
    -    dragTexts[i].value = origTexts[i].value;
    -  }
    -  switch (sourceEl.tagName.toLowerCase()) {
    -    case 'tr':
    -      return goog.dom.createDom(
    -          'table', null, goog.dom.createDom('tbody', null, clonedEl));
    -    case 'td':
    -    case 'th':
    -      return goog.dom.createDom(
    -          'table', null, goog.dom.createDom('tbody', null, goog.dom.createDom(
    -          'tr', null, clonedEl)));
    -    case 'textarea':
    -      clonedEl.value = sourceEl.value;
    -    default:
    -      return clonedEl;
    -  }
    -};
    -
    -
    -/**
    - * Constants for event names.
    - * @enum {string}
    - */
    -goog.fx.Dragger.EventType = {
    -  // The drag action was canceled before the START event. Possible reasons:
    -  // disabled dragger, dragging with the right mouse button or releasing the
    -  // button before reaching the hysteresis distance.
    -  EARLY_CANCEL: 'earlycancel',
    -  START: 'start',
    -  BEFOREDRAG: 'beforedrag',
    -  DRAG: 'drag',
    -  END: 'end'
    -};
    -
    -
    -/**
    - * Reference to drag target element.
    - * @type {Element}
    - */
    -goog.fx.Dragger.prototype.target;
    -
    -
    -/**
    - * Reference to the handler that initiates the drag.
    - * @type {Element}
    - */
    -goog.fx.Dragger.prototype.handle;
    -
    -
    -/**
    - * Object representing the limits of the drag region.
    - * @type {goog.math.Rect}
    - */
    -goog.fx.Dragger.prototype.limits;
    -
    -
    -/**
    - * Whether the element is rendered right-to-left. We initialize this lazily.
    - * @type {boolean|undefined}}
    - * @private
    - */
    -goog.fx.Dragger.prototype.rightToLeft_;
    -
    -
    -/**
    - * Current x position of mouse or touch relative to viewport.
    - * @type {number}
    - */
    -goog.fx.Dragger.prototype.clientX = 0;
    -
    -
    -/**
    - * Current y position of mouse or touch relative to viewport.
    - * @type {number}
    - */
    -goog.fx.Dragger.prototype.clientY = 0;
    -
    -
    -/**
    - * Current x position of mouse or touch relative to screen. Deprecated because
    - * it doesn't take into affect zoom level or pixel density.
    - * @type {number}
    - * @deprecated Consider switching to clientX instead.
    - */
    -goog.fx.Dragger.prototype.screenX = 0;
    -
    -
    -/**
    - * Current y position of mouse or touch relative to screen. Deprecated because
    - * it doesn't take into affect zoom level or pixel density.
    - * @type {number}
    - * @deprecated Consider switching to clientY instead.
    - */
    -goog.fx.Dragger.prototype.screenY = 0;
    -
    -
    -/**
    - * The x position where the first mousedown or touchstart occurred.
    - * @type {number}
    - */
    -goog.fx.Dragger.prototype.startX = 0;
    -
    -
    -/**
    - * The y position where the first mousedown or touchstart occurred.
    - * @type {number}
    - */
    -goog.fx.Dragger.prototype.startY = 0;
    -
    -
    -/**
    - * Current x position of drag relative to target's parent.
    - * @type {number}
    - */
    -goog.fx.Dragger.prototype.deltaX = 0;
    -
    -
    -/**
    - * Current y position of drag relative to target's parent.
    - * @type {number}
    - */
    -goog.fx.Dragger.prototype.deltaY = 0;
    -
    -
    -/**
    - * The current page scroll value.
    - * @type {goog.math.Coordinate}
    - */
    -goog.fx.Dragger.prototype.pageScroll;
    -
    -
    -/**
    - * Whether dragging is currently enabled.
    - * @type {boolean}
    - * @private
    - */
    -goog.fx.Dragger.prototype.enabled_ = true;
    -
    -
    -/**
    - * Whether object is currently being dragged.
    - * @type {boolean}
    - * @private
    - */
    -goog.fx.Dragger.prototype.dragging_ = false;
    -
    -
    -/**
    - * The amount of distance, in pixels, after which a mousedown or touchstart is
    - * considered a drag.
    - * @type {number}
    - * @private
    - */
    -goog.fx.Dragger.prototype.hysteresisDistanceSquared_ = 0;
    -
    -
    -/**
    - * Timestamp of when the mousedown or touchstart occurred.
    - * @type {number}
    - * @private
    - */
    -goog.fx.Dragger.prototype.mouseDownTime_ = 0;
    -
    -
    -/**
    - * Reference to a document object to use for the events.
    - * @type {Document}
    - * @private
    - */
    -goog.fx.Dragger.prototype.document_;
    -
    -
    -/**
    - * The SCROLL event target used to make drag element follow scrolling.
    - * @type {EventTarget}
    - * @private
    - */
    -goog.fx.Dragger.prototype.scrollTarget_;
    -
    -
    -/**
    - * Whether IE drag events cancelling is on.
    - * @type {boolean}
    - * @private
    - */
    -goog.fx.Dragger.prototype.ieDragStartCancellingOn_ = false;
    -
    -
    -/**
    - * Whether the dragger implements the changes described in http://b/6324964,
    - * making it truly RTL.  This is a temporary flag to allow clients to transition
    - * to the new behavior at their convenience.  At some point it will be the
    - * default.
    - * @type {boolean}
    - * @private
    - */
    -goog.fx.Dragger.prototype.useRightPositioningForRtl_ = false;
    -
    -
    -/**
    - * Turns on/off true RTL behavior.  This should be called immediately after
    - * construction.  This is a temporary flag to allow clients to transition
    - * to the new component at their convenience.  At some point true will be the
    - * default.
    - * @param {boolean} useRightPositioningForRtl True if "right" should be used for
    - *     positioning, false if "left" should be used for positioning.
    - */
    -goog.fx.Dragger.prototype.enableRightPositioningForRtl =
    -    function(useRightPositioningForRtl) {
    -  this.useRightPositioningForRtl_ = useRightPositioningForRtl;
    -};
    -
    -
    -/**
    - * Returns the event handler, intended for subclass use.
    - * @return {!goog.events.EventHandler<T>} The event handler.
    - * @this T
    - * @template T
    - */
    -goog.fx.Dragger.prototype.getHandler = function() {
    -  // TODO(user): templated "this" values currently result in "this" being
    -  // "unknown" in the body of the function.
    -  var self = /** @type {goog.fx.Dragger} */ (this);
    -  return self.eventHandler_;
    -};
    -
    -
    -/**
    - * Sets (or reset) the Drag limits after a Dragger is created.
    - * @param {goog.math.Rect?} limits Object containing left, top, width,
    - *     height for new Dragger limits. If target is right-to-left and
    - *     enableRightPositioningForRtl(true) is called, then rect is interpreted as
    - *     right, top, width, and height.
    - */
    -goog.fx.Dragger.prototype.setLimits = function(limits) {
    -  this.limits = limits || new goog.math.Rect(NaN, NaN, NaN, NaN);
    -};
    -
    -
    -/**
    - * Sets the distance the user has to drag the element before a drag operation is
    - * started.
    - * @param {number} distance The number of pixels after which a mousedown and
    - *     move is considered a drag.
    - */
    -goog.fx.Dragger.prototype.setHysteresis = function(distance) {
    -  this.hysteresisDistanceSquared_ = Math.pow(distance, 2);
    -};
    -
    -
    -/**
    - * Gets the distance the user has to drag the element before a drag operation is
    - * started.
    - * @return {number} distance The number of pixels after which a mousedown and
    - *     move is considered a drag.
    - */
    -goog.fx.Dragger.prototype.getHysteresis = function() {
    -  return Math.sqrt(this.hysteresisDistanceSquared_);
    -};
    -
    -
    -/**
    - * Sets the SCROLL event target to make drag element follow scrolling.
    - *
    - * @param {EventTarget} scrollTarget The event target that dispatches SCROLL
    - *     events.
    - */
    -goog.fx.Dragger.prototype.setScrollTarget = function(scrollTarget) {
    -  this.scrollTarget_ = scrollTarget;
    -};
    -
    -
    -/**
    - * Enables cancelling of built-in IE drag events.
    - * @param {boolean} cancelIeDragStart Whether to enable cancelling of IE
    - *     dragstart event.
    - */
    -goog.fx.Dragger.prototype.setCancelIeDragStart = function(cancelIeDragStart) {
    -  this.ieDragStartCancellingOn_ = cancelIeDragStart;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the dragger is enabled.
    - */
    -goog.fx.Dragger.prototype.getEnabled = function() {
    -  return this.enabled_;
    -};
    -
    -
    -/**
    - * Set whether dragger is enabled
    - * @param {boolean} enabled Whether dragger is enabled.
    - */
    -goog.fx.Dragger.prototype.setEnabled = function(enabled) {
    -  this.enabled_ = enabled;
    -};
    -
    -
    -/** @override */
    -goog.fx.Dragger.prototype.disposeInternal = function() {
    -  goog.fx.Dragger.superClass_.disposeInternal.call(this);
    -  goog.events.unlisten(this.handle,
    -      [goog.events.EventType.TOUCHSTART, goog.events.EventType.MOUSEDOWN],
    -      this.startDrag, false, this);
    -  this.cleanUpAfterDragging_();
    -
    -  this.target = null;
    -  this.handle = null;
    -};
    -
    -
    -/**
    - * Whether the DOM element being manipulated is rendered right-to-left.
    - * @return {boolean} True if the DOM element is rendered right-to-left, false
    - *     otherwise.
    - * @private
    - */
    -goog.fx.Dragger.prototype.isRightToLeft_ = function() {
    -  if (!goog.isDef(this.rightToLeft_)) {
    -    this.rightToLeft_ = goog.style.isRightToLeft(this.target);
    -  }
    -  return this.rightToLeft_;
    -};
    -
    -
    -/**
    - * Event handler that is used to start the drag
    - * @param {goog.events.BrowserEvent} e Event object.
    - */
    -goog.fx.Dragger.prototype.startDrag = function(e) {
    -  var isMouseDown = e.type == goog.events.EventType.MOUSEDOWN;
    -
    -  // Dragger.startDrag() can be called by AbstractDragDrop with a mousemove
    -  // event and IE does not report pressed mouse buttons on mousemove. Also,
    -  // it does not make sense to check for the button if the user is already
    -  // dragging.
    -
    -  if (this.enabled_ && !this.dragging_ &&
    -      (!isMouseDown || e.isMouseActionButton())) {
    -    this.maybeReinitTouchEvent_(e);
    -    if (this.hysteresisDistanceSquared_ == 0) {
    -      if (this.fireDragStart_(e)) {
    -        this.dragging_ = true;
    -        e.preventDefault();
    -      } else {
    -        // If the start drag is cancelled, don't setup for a drag.
    -        return;
    -      }
    -    } else {
    -      // Need to preventDefault for hysteresis to prevent page getting selected.
    -      e.preventDefault();
    -    }
    -    this.setupDragHandlers();
    -
    -    this.clientX = this.startX = e.clientX;
    -    this.clientY = this.startY = e.clientY;
    -    this.screenX = e.screenX;
    -    this.screenY = e.screenY;
    -    this.computeInitialPosition();
    -    this.pageScroll = goog.dom.getDomHelper(this.document_).getDocumentScroll();
    -
    -    this.mouseDownTime_ = goog.now();
    -  } else {
    -    this.dispatchEvent(goog.fx.Dragger.EventType.EARLY_CANCEL);
    -  }
    -};
    -
    -
    -/**
    - * Sets up event handlers when dragging starts.
    - * @protected
    - */
    -goog.fx.Dragger.prototype.setupDragHandlers = function() {
    -  var doc = this.document_;
    -  var docEl = doc.documentElement;
    -  // Use bubbling when we have setCapture since we got reports that IE has
    -  // problems with the capturing events in combination with setCapture.
    -  var useCapture = !goog.fx.Dragger.HAS_SET_CAPTURE_;
    -
    -  this.eventHandler_.listen(doc,
    -      [goog.events.EventType.TOUCHMOVE, goog.events.EventType.MOUSEMOVE],
    -      this.handleMove_, useCapture);
    -  this.eventHandler_.listen(doc,
    -      [goog.events.EventType.TOUCHEND, goog.events.EventType.MOUSEUP],
    -      this.endDrag, useCapture);
    -
    -  if (goog.fx.Dragger.HAS_SET_CAPTURE_) {
    -    docEl.setCapture(false);
    -    this.eventHandler_.listen(docEl,
    -                              goog.events.EventType.LOSECAPTURE,
    -                              this.endDrag);
    -  } else {
    -    // Make sure we stop the dragging if the window loses focus.
    -    // Don't use capture in this listener because we only want to end the drag
    -    // if the actual window loses focus. Since blur events do not bubble we use
    -    // a bubbling listener on the window.
    -    this.eventHandler_.listen(goog.dom.getWindow(doc),
    -                              goog.events.EventType.BLUR,
    -                              this.endDrag);
    -  }
    -
    -  if (goog.userAgent.IE && this.ieDragStartCancellingOn_) {
    -    // Cancel IE's 'ondragstart' event.
    -    this.eventHandler_.listen(doc, goog.events.EventType.DRAGSTART,
    -                              goog.events.Event.preventDefault);
    -  }
    -
    -  if (this.scrollTarget_) {
    -    this.eventHandler_.listen(this.scrollTarget_, goog.events.EventType.SCROLL,
    -                              this.onScroll_, useCapture);
    -  }
    -};
    -
    -
    -/**
    - * Fires a goog.fx.Dragger.EventType.START event.
    - * @param {goog.events.BrowserEvent} e Browser event that triggered the drag.
    - * @return {boolean} False iff preventDefault was called on the DragEvent.
    - * @private
    - */
    -goog.fx.Dragger.prototype.fireDragStart_ = function(e) {
    -  return this.dispatchEvent(new goog.fx.DragEvent(
    -      goog.fx.Dragger.EventType.START, this, e.clientX, e.clientY, e));
    -};
    -
    -
    -/**
    - * Unregisters the event handlers that are only active during dragging, and
    - * releases mouse capture.
    - * @private
    - */
    -goog.fx.Dragger.prototype.cleanUpAfterDragging_ = function() {
    -  this.eventHandler_.removeAll();
    -  if (goog.fx.Dragger.HAS_SET_CAPTURE_) {
    -    this.document_.releaseCapture();
    -  }
    -};
    -
    -
    -/**
    - * Event handler that is used to end the drag.
    - * @param {goog.events.BrowserEvent} e Event object.
    - * @param {boolean=} opt_dragCanceled Whether the drag has been canceled.
    - */
    -goog.fx.Dragger.prototype.endDrag = function(e, opt_dragCanceled) {
    -  this.cleanUpAfterDragging_();
    -
    -  if (this.dragging_) {
    -    this.maybeReinitTouchEvent_(e);
    -    this.dragging_ = false;
    -
    -    var x = this.limitX(this.deltaX);
    -    var y = this.limitY(this.deltaY);
    -    var dragCanceled = opt_dragCanceled ||
    -        e.type == goog.events.EventType.TOUCHCANCEL;
    -    this.dispatchEvent(new goog.fx.DragEvent(
    -        goog.fx.Dragger.EventType.END, this, e.clientX, e.clientY, e, x, y,
    -        dragCanceled));
    -  } else {
    -    this.dispatchEvent(goog.fx.Dragger.EventType.EARLY_CANCEL);
    -  }
    -};
    -
    -
    -/**
    - * Event handler that is used to end the drag by cancelling it.
    - * @param {goog.events.BrowserEvent} e Event object.
    - */
    -goog.fx.Dragger.prototype.endDragCancel = function(e) {
    -  this.endDrag(e, true);
    -};
    -
    -
    -/**
    - * Re-initializes the event with the first target touch event or, in the case
    - * of a stop event, the last changed touch.
    - * @param {goog.events.BrowserEvent} e A TOUCH... event.
    - * @private
    - */
    -goog.fx.Dragger.prototype.maybeReinitTouchEvent_ = function(e) {
    -  var type = e.type;
    -
    -  if (type == goog.events.EventType.TOUCHSTART ||
    -      type == goog.events.EventType.TOUCHMOVE) {
    -    e.init(e.getBrowserEvent().targetTouches[0], e.currentTarget);
    -  } else if (type == goog.events.EventType.TOUCHEND ||
    -             type == goog.events.EventType.TOUCHCANCEL) {
    -    e.init(e.getBrowserEvent().changedTouches[0], e.currentTarget);
    -  }
    -};
    -
    -
    -/**
    - * Event handler that is used on mouse / touch move to update the drag
    - * @param {goog.events.BrowserEvent} e Event object.
    - * @private
    - */
    -goog.fx.Dragger.prototype.handleMove_ = function(e) {
    -  if (this.enabled_) {
    -    this.maybeReinitTouchEvent_(e);
    -    // dx in right-to-left cases is relative to the right.
    -    var sign = this.useRightPositioningForRtl_ &&
    -        this.isRightToLeft_() ? -1 : 1;
    -    var dx = sign * (e.clientX - this.clientX);
    -    var dy = e.clientY - this.clientY;
    -    this.clientX = e.clientX;
    -    this.clientY = e.clientY;
    -    this.screenX = e.screenX;
    -    this.screenY = e.screenY;
    -
    -    if (!this.dragging_) {
    -      var diffX = this.startX - this.clientX;
    -      var diffY = this.startY - this.clientY;
    -      var distance = diffX * diffX + diffY * diffY;
    -      if (distance > this.hysteresisDistanceSquared_) {
    -        if (this.fireDragStart_(e)) {
    -          this.dragging_ = true;
    -        } else {
    -          // DragListGroup disposes of the dragger if BEFOREDRAGSTART is
    -          // canceled.
    -          if (!this.isDisposed()) {
    -            this.endDrag(e);
    -          }
    -          return;
    -        }
    -      }
    -    }
    -
    -    var pos = this.calculatePosition_(dx, dy);
    -    var x = pos.x;
    -    var y = pos.y;
    -
    -    if (this.dragging_) {
    -
    -      var rv = this.dispatchEvent(new goog.fx.DragEvent(
    -          goog.fx.Dragger.EventType.BEFOREDRAG, this, e.clientX, e.clientY,
    -          e, x, y));
    -
    -      // Only do the defaultAction and dispatch drag event if predrag didn't
    -      // prevent default
    -      if (rv) {
    -        this.doDrag(e, x, y, false);
    -        e.preventDefault();
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Calculates the drag position.
    - *
    - * @param {number} dx The horizontal movement delta.
    - * @param {number} dy The vertical movement delta.
    - * @return {!goog.math.Coordinate} The newly calculated drag element position.
    - * @private
    - */
    -goog.fx.Dragger.prototype.calculatePosition_ = function(dx, dy) {
    -  // Update the position for any change in body scrolling
    -  var pageScroll = goog.dom.getDomHelper(this.document_).getDocumentScroll();
    -  dx += pageScroll.x - this.pageScroll.x;
    -  dy += pageScroll.y - this.pageScroll.y;
    -  this.pageScroll = pageScroll;
    -
    -  this.deltaX += dx;
    -  this.deltaY += dy;
    -
    -  var x = this.limitX(this.deltaX);
    -  var y = this.limitY(this.deltaY);
    -  return new goog.math.Coordinate(x, y);
    -};
    -
    -
    -/**
    - * Event handler for scroll target scrolling.
    - * @param {goog.events.BrowserEvent} e The event.
    - * @private
    - */
    -goog.fx.Dragger.prototype.onScroll_ = function(e) {
    -  var pos = this.calculatePosition_(0, 0);
    -  e.clientX = this.clientX;
    -  e.clientY = this.clientY;
    -  this.doDrag(e, pos.x, pos.y, true);
    -};
    -
    -
    -/**
    - * @param {goog.events.BrowserEvent} e The closure object
    - *     representing the browser event that caused a drag event.
    - * @param {number} x The new horizontal position for the drag element.
    - * @param {number} y The new vertical position for the drag element.
    - * @param {boolean} dragFromScroll Whether dragging was caused by scrolling
    - *     the associated scroll target.
    - * @protected
    - */
    -goog.fx.Dragger.prototype.doDrag = function(e, x, y, dragFromScroll) {
    -  this.defaultAction(x, y);
    -  this.dispatchEvent(new goog.fx.DragEvent(
    -      goog.fx.Dragger.EventType.DRAG, this, e.clientX, e.clientY, e, x, y));
    -};
    -
    -
    -/**
    - * Returns the 'real' x after limits are applied (allows for some
    - * limits to be undefined).
    - * @param {number} x X-coordinate to limit.
    - * @return {number} The 'real' X-coordinate after limits are applied.
    - */
    -goog.fx.Dragger.prototype.limitX = function(x) {
    -  var rect = this.limits;
    -  var left = !isNaN(rect.left) ? rect.left : null;
    -  var width = !isNaN(rect.width) ? rect.width : 0;
    -  var maxX = left != null ? left + width : Infinity;
    -  var minX = left != null ? left : -Infinity;
    -  return Math.min(maxX, Math.max(minX, x));
    -};
    -
    -
    -/**
    - * Returns the 'real' y after limits are applied (allows for some
    - * limits to be undefined).
    - * @param {number} y Y-coordinate to limit.
    - * @return {number} The 'real' Y-coordinate after limits are applied.
    - */
    -goog.fx.Dragger.prototype.limitY = function(y) {
    -  var rect = this.limits;
    -  var top = !isNaN(rect.top) ? rect.top : null;
    -  var height = !isNaN(rect.height) ? rect.height : 0;
    -  var maxY = top != null ? top + height : Infinity;
    -  var minY = top != null ? top : -Infinity;
    -  return Math.min(maxY, Math.max(minY, y));
    -};
    -
    -
    -/**
    - * Overridable function for computing the initial position of the target
    - * before dragging begins.
    - * @protected
    - */
    -goog.fx.Dragger.prototype.computeInitialPosition = function() {
    -  this.deltaX = this.useRightPositioningForRtl_ ?
    -      goog.style.bidi.getOffsetStart(this.target) : this.target.offsetLeft;
    -  this.deltaY = this.target.offsetTop;
    -};
    -
    -
    -/**
    - * Overridable function for handling the default action of the drag behaviour.
    - * Normally this is simply moving the element to x,y though in some cases it
    - * might be used to resize the layer.  This is basically a shortcut to
    - * implementing a default ondrag event handler.
    - * @param {number} x X-coordinate for target element. In right-to-left, x this
    - *     is the number of pixels the target should be moved to from the right.
    - * @param {number} y Y-coordinate for target element.
    - */
    -goog.fx.Dragger.prototype.defaultAction = function(x, y) {
    -  if (this.useRightPositioningForRtl_ && this.isRightToLeft_()) {
    -    this.target.style.right = x + 'px';
    -  } else {
    -    this.target.style.left = x + 'px';
    -  }
    -  this.target.style.top = y + 'px';
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the dragger is currently in the midst of a drag.
    - */
    -goog.fx.Dragger.prototype.isDragging = function() {
    -  return this.dragging_;
    -};
    -
    -
    -
    -/**
    - * Object representing a drag event
    - * @param {string} type Event type.
    - * @param {goog.fx.Dragger} dragobj Drag object initiating event.
    - * @param {number} clientX X-coordinate relative to the viewport.
    - * @param {number} clientY Y-coordinate relative to the viewport.
    - * @param {goog.events.BrowserEvent} browserEvent The closure object
    - *   representing the browser event that caused this drag event.
    - * @param {number=} opt_actX Optional actual x for drag if it has been limited.
    - * @param {number=} opt_actY Optional actual y for drag if it has been limited.
    - * @param {boolean=} opt_dragCanceled Whether the drag has been canceled.
    - * @constructor
    - * @extends {goog.events.Event}
    - */
    -goog.fx.DragEvent = function(type, dragobj, clientX, clientY, browserEvent,
    -                             opt_actX, opt_actY, opt_dragCanceled) {
    -  goog.events.Event.call(this, type);
    -
    -  /**
    -   * X-coordinate relative to the viewport
    -   * @type {number}
    -   */
    -  this.clientX = clientX;
    -
    -  /**
    -   * Y-coordinate relative to the viewport
    -   * @type {number}
    -   */
    -  this.clientY = clientY;
    -
    -  /**
    -   * The closure object representing the browser event that caused this drag
    -   * event.
    -   * @type {goog.events.BrowserEvent}
    -   */
    -  this.browserEvent = browserEvent;
    -
    -  /**
    -   * The real x-position of the drag if it has been limited
    -   * @type {number}
    -   */
    -  this.left = goog.isDef(opt_actX) ? opt_actX : dragobj.deltaX;
    -
    -  /**
    -   * The real y-position of the drag if it has been limited
    -   * @type {number}
    -   */
    -  this.top = goog.isDef(opt_actY) ? opt_actY : dragobj.deltaY;
    -
    -  /**
    -   * Reference to the drag object for this event
    -   * @type {goog.fx.Dragger}
    -   */
    -  this.dragger = dragobj;
    -
    -  /**
    -   * Whether drag was canceled with this event. Used to differentiate between
    -   * a legitimate drag END that can result in an action and a drag END which is
    -   * a result of a drag cancelation. For now it can happen 1) with drag END
    -   * event on FireFox when user drags the mouse out of the window, 2) with
    -   * drag END event on IE7 which is generated on MOUSEMOVE event when user
    -   * moves the mouse into the document after the mouse button has been
    -   * released, 3) when TOUCHCANCEL is raised instead of TOUCHEND (on touch
    -   * events).
    -   * @type {boolean}
    -   */
    -  this.dragCanceled = !!opt_dragCanceled;
    -};
    -goog.inherits(goog.fx.DragEvent, goog.events.Event);
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/dragger_test.html b/src/database/third_party/closure-library/closure/goog/fx/dragger_test.html
    deleted file mode 100644
    index bcf5e423824..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/dragger_test.html
    +++ /dev/null
    @@ -1,37 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.fx.Dragger
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.fx.DraggerTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="sandbox">
    -  </div>
    -  <div id="sandbox_rtl" dir="rtl" style="overflow: auto; position:absolute; top:20px; left: 20px;
    -         width: 100px; height: 100px; background: red;">
    -  </div>
    -  <br />
    -  <br />
    -  <br />
    -  <br />
    -  <br />
    -  <br />
    -  <br />
    -  <br />
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/dragger_test.js b/src/database/third_party/closure-library/closure/goog/fx/dragger_test.js
    deleted file mode 100644
    index a9ac058ed2b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/dragger_test.js
    +++ /dev/null
    @@ -1,459 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.fx.DraggerTest');
    -goog.setTestOnly('goog.fx.DraggerTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.BrowserEvent');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventType');
    -goog.require('goog.fx.Dragger');
    -goog.require('goog.math.Rect');
    -goog.require('goog.style.bidi');
    -goog.require('goog.testing.StrictMock');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -var HAS_SET_CAPTURE = goog.fx.Dragger.HAS_SET_CAPTURE_;
    -
    -var target;
    -var targetRtl;
    -
    -function setUp() {
    -  var sandbox = goog.dom.getElement('sandbox');
    -  target = goog.dom.createDom('div', {
    -    'id': 'target',
    -    'style': 'display:none;position:absolute;top:15px;left:10px'
    -  });
    -  sandbox.appendChild(target);
    -  sandbox.appendChild(goog.dom.createDom('div', {'id': 'handle'}));
    -
    -  var sandboxRtl = goog.dom.getElement('sandbox_rtl');
    -  targetRtl = goog.dom.createDom('div', {
    -    'id': 'target_rtl',
    -    'style': 'position:absolute; top:15px; right:10px; width:10px; ' +
    -        'height: 10px; background: green;'
    -  });
    -  sandboxRtl.appendChild(targetRtl);
    -  sandboxRtl.appendChild(goog.dom.createDom('div', {
    -    'id': 'background_rtl',
    -    'style': 'width: 10000px;height:50px;position:absolute;color:blue;'
    -  }));
    -  sandboxRtl.appendChild(goog.dom.createDom('div', {'id': 'handle_rtl'}));
    -}
    -
    -function tearDown() {
    -  goog.dom.getElement('sandbox').innerHTML = '';
    -  goog.dom.getElement('sandbox_rtl').innerHTML = '';
    -  goog.events.removeAll(document);
    -}
    -
    -function testStartDrag() {
    -  runStartDragTest('handle', target);
    -}
    -
    -function testStartDrag_rtl() {
    -  runStartDragTest('handle_rtl', targetRtl);
    -}
    -
    -function runStartDragTest(handleId, targetElement) {
    -  var dragger =
    -      new goog.fx.Dragger(targetElement, goog.dom.getElement(handleId));
    -  if (handleId == 'handle_rtl') {
    -    dragger.enableRightPositioningForRtl(true);
    -  }
    -  var e = new goog.testing.StrictMock(goog.events.BrowserEvent);
    -  e.type = goog.events.EventType.MOUSEDOWN;
    -  e.clientX = 1;
    -  e.clientY = 2;
    -  e.isMouseActionButton().$returns(true);
    -  e.preventDefault();
    -  e.isMouseActionButton().$returns(true);
    -  e.preventDefault();
    -  e.$replay();
    -
    -  goog.events.listen(dragger, goog.fx.Dragger.EventType.START, function() {
    -    targetElement.style.display = 'block';
    -  });
    -
    -  dragger.startDrag(e);
    -
    -  assertTrue('Start drag with no hysteresis must actually start the drag.',
    -      dragger.isDragging());
    -  if (handleId == 'handle_rtl') {
    -    assertEquals(10, goog.style.bidi.getOffsetStart(targetElement));
    -  }
    -  assertEquals('Dragger startX must match event\'s clientX.',
    -      1, dragger.startX);
    -  assertEquals('Dragger clientX must match event\'s clientX',
    -      1, dragger.clientX);
    -  assertEquals('Dragger startY must match event\'s clientY.',
    -      2, dragger.startY);
    -  assertEquals('Dragger clientY must match event\'s clientY',
    -      2, dragger.clientY);
    -  assertEquals('Dragger deltaX must match target\'s offsetLeft',
    -      10, dragger.deltaX);
    -  assertEquals('Dragger deltaY must match target\'s offsetTop',
    -      15, dragger.deltaY);
    -
    -  dragger = new goog.fx.Dragger(targetElement, goog.dom.getElement(handleId));
    -  dragger.setHysteresis(1);
    -  dragger.startDrag(e);
    -  assertFalse('Start drag with a valid non-zero hysteresis should not start ' +
    -      'the drag.', dragger.isDragging());
    -  e.$verify();
    -}
    -
    -
    -/**
    - * @bug 1381317 Cancelling start drag didn't end the attempt to drag.
    - */
    -function testStartDrag_Cancel() {
    -  var dragger = new goog.fx.Dragger(target);
    -
    -  var e = new goog.testing.StrictMock(goog.events.BrowserEvent);
    -  e.type = goog.events.EventType.MOUSEDOWN;
    -  e.clientX = 1;
    -  e.clientY = 2;
    -  e.isMouseActionButton().$returns(true);
    -  e.$replay();
    -
    -  goog.events.listen(dragger, goog.fx.Dragger.EventType.START, function(e) {
    -    // Cancel drag.
    -    e.preventDefault();
    -  });
    -
    -  dragger.startDrag(e);
    -
    -  assertFalse('Start drag must have been cancelled.',
    -      dragger.isDragging());
    -  assertFalse('Dragger must not have registered mousemove handlers.',
    -      goog.events.hasListener(dragger.document_,
    -          goog.events.EventType.MOUSEMOVE, !HAS_SET_CAPTURE));
    -  assertFalse('Dragger must not have registered mouseup handlers.',
    -      goog.events.hasListener(dragger.document_, goog.events.EventType.MOUSEUP,
    -          !HAS_SET_CAPTURE));
    -  e.$verify();
    -}
    -
    -
    -/**
    - * Tests that start drag happens on left mousedown.
    - */
    -function testStartDrag_LeftMouseDownOnly() {
    -  var dragger = new goog.fx.Dragger(target);
    -
    -  var e = new goog.testing.StrictMock(goog.events.BrowserEvent);
    -  e.type = goog.events.EventType.MOUSEDOWN;
    -  e.clientX = 1;
    -  e.clientY = 2;
    -  e.isMouseActionButton().$returns(false);
    -  e.$replay();
    -
    -  goog.events.listen(dragger, goog.fx.Dragger.EventType.START, function(e) {
    -    fail('No drag START event should have been dispatched');
    -  });
    -
    -  dragger.startDrag(e);
    -
    -  assertFalse('Start drag must have been cancelled.',
    -      dragger.isDragging());
    -  assertFalse('Dragger must not have registered mousemove handlers.',
    -      goog.events.hasListener(dragger.document_,
    -          goog.events.EventType.MOUSEMOVE, true));
    -  assertFalse('Dragger must not have registered mouseup handlers.',
    -      goog.events.hasListener(dragger.document_, goog.events.EventType.MOUSEUP,
    -          true));
    -  e.$verify();
    -}
    -
    -
    -/**
    - * Tests that start drag happens on other event type than MOUSEDOWN.
    - */
    -function testStartDrag_MouseMove() {
    -  var dragger = new goog.fx.Dragger(target);
    -
    -  var e = new goog.testing.StrictMock(goog.events.BrowserEvent);
    -  e.type = goog.events.EventType.MOUSEMOVE;
    -  e.clientX = 1;
    -  e.clientY = 2;
    -  e.preventDefault();
    -  e.$replay();
    -
    -  var startDragFired = false;
    -  goog.events.listen(dragger, goog.fx.Dragger.EventType.START, function(e) {
    -    startDragFired = true;
    -  });
    -
    -  dragger.startDrag(e);
    -
    -  assertTrue('Dragging should be in progress.', dragger.isDragging());
    -  assertTrue('Start drag event should have fired.', startDragFired);
    -  assertTrue('Dragger must have registered mousemove handlers.',
    -      goog.events.hasListener(dragger.document_,
    -          goog.events.EventType.MOUSEMOVE, !HAS_SET_CAPTURE));
    -  assertTrue('Dragger must have registered mouseup handlers.',
    -      goog.events.hasListener(dragger.document_, goog.events.EventType.MOUSEUP,
    -          !HAS_SET_CAPTURE));
    -  e.$verify();
    -}
    -
    -
    -/**
    - * @bug 1381317 Cancelling start drag didn't end the attempt to drag.
    - */
    -function testHandleMove_Cancel() {
    -  var dragger = new goog.fx.Dragger(target);
    -  dragger.setHysteresis(5);
    -
    -  goog.events.listen(dragger, goog.fx.Dragger.EventType.START, function(e) {
    -    // Cancel drag.
    -    e.preventDefault();
    -  });
    -
    -  var e = new goog.testing.StrictMock(goog.events.BrowserEvent);
    -  e.clientX = 1;
    -  e.clientY = 2;
    -  e.isMouseActionButton().$returns(true).
    -      $anyTimes();
    -  e.preventDefault();
    -  e.$replay();
    -  dragger.startDrag(e);
    -  assertFalse('Start drag must not start drag because of hysterisis.',
    -      dragger.isDragging());
    -  assertTrue('Dragger must have registered mousemove handlers.',
    -      goog.events.hasListener(dragger.document_,
    -          goog.events.EventType.MOUSEMOVE, !HAS_SET_CAPTURE));
    -  assertTrue('Dragger must have registered mouseup handlers.',
    -      goog.events.hasListener(dragger.document_, goog.events.EventType.MOUSEUP,
    -          !HAS_SET_CAPTURE));
    -
    -  e.clientX = 10;
    -  e.clientY = 10;
    -  dragger.handleMove_(e);
    -  assertFalse('Drag must be cancelled.', dragger.isDragging());
    -  assertFalse('Dragger must unregistered mousemove handlers.',
    -      goog.events.hasListener(dragger.document_,
    -          goog.events.EventType.MOUSEMOVE, true));
    -  assertFalse('Dragger must unregistered mouseup handlers.',
    -      goog.events.hasListener(dragger.document_, goog.events.EventType.MOUSEUP,
    -          true));
    -  e.$verify();
    -}
    -
    -
    -/**
    - * @bug 1714667 IE<9 built in drag and drop handling stops dragging.
    - */
    -function testIeDragStartCancelling() {
    -  // Testing only IE<9.
    -  if (!goog.userAgent.IE || goog.userAgent.isVersionOrHigher(9)) {
    -    return;
    -  }
    -
    -  // Built in 'dragstart' cancelling not enabled.
    -  var dragger = new goog.fx.Dragger(target);
    -
    -  var e = new goog.events.Event(goog.events.EventType.MOUSEDOWN);
    -  e.clientX = 1;
    -  e.clientY = 2;
    -  e.button = 1; // IE only constant for left button.
    -  var be = new goog.events.BrowserEvent(e);
    -  dragger.startDrag(be);
    -  assertTrue('The drag should have started.', dragger.isDragging());
    -
    -  e = new goog.events.Event(goog.events.EventType.DRAGSTART);
    -  e.target = dragger.document_.documentElement;
    -  assertTrue('The event should not be canceled.',
    -      goog.testing.events.fireBrowserEvent(e));
    -
    -  dragger.dispose();
    -
    -  // Built in 'dragstart' cancelling enabled.
    -  dragger = new goog.fx.Dragger(target);
    -  dragger.setCancelIeDragStart(true);
    -
    -  e = new goog.events.Event(goog.events.EventType.MOUSEDOWN);
    -  e.clientX = 1;
    -  e.clientY = 2;
    -  e.button = 1; // IE only constant for left button.
    -  be = new goog.events.BrowserEvent(e);
    -  dragger.startDrag(be);
    -  assertTrue('The drag should have started.', dragger.isDragging());
    -
    -  e = new goog.events.Event(goog.events.EventType.DRAGSTART);
    -  e.target = dragger.document_.documentElement;
    -  assertFalse('The event should be canceled.',
    -      goog.testing.events.fireBrowserEvent(e));
    -
    -  dragger.dispose();
    -}
    -
    -
    -/** @bug 1680770 */
    -function testOnWindowMouseOut() {
    -  // Test older Gecko browsers - FireFox 2.
    -  if (goog.userAgent.GECKO && !goog.userAgent.isVersionOrHigher('1.9a')) {
    -    var dragger = new goog.fx.Dragger(target);
    -
    -    var dragCanceled = false;
    -    goog.events.listen(dragger, goog.fx.Dragger.EventType.END, function(e) {
    -      dragCanceled = e.dragCanceled;
    -    });
    -
    -    var e = new goog.testing.StrictMock(goog.events.BrowserEvent);
    -    e.type = goog.events.EventType.MOUSEDOWN;
    -    e.clientX = 1;
    -    e.clientY = 2;
    -    e.isMouseActionButton().$returns(true);
    -    e.preventDefault();
    -    e.$replay();
    -    dragger.startDrag(e);
    -    e.$verify();
    -
    -    assertTrue(dragger.isDragging());
    -
    -    e = new goog.events.BrowserEvent();
    -    e.type = goog.events.EventType.MOUSEOUT;
    -    e.target = goog.dom.getElement('sandbox');
    -    e.currentTarget = window.top;
    -    e.relatedTarget = target;
    -    dragger.onWindowMouseOut_(e);
    -
    -    assertFalse('Drag is not canceled for normal in-window mouseout.',
    -        dragCanceled);
    -    assertTrue('Must not stop dragging for normal in-window mouseout.',
    -        dragger.isDragging());
    -
    -    dragCanceled = false;
    -    delete e.relatedTarget;
    -    e.target = goog.dom.createDom('iframe');
    -    dragger.onWindowMouseOut_(e);
    -    assertFalse('Drag is not canceled for mousing into iframe.',
    -        dragCanceled);
    -    assertTrue('Must not stop dragging for mousing into iframe.',
    -        dragger.isDragging());
    -
    -    dragCanceled = false;
    -    e.target = target;
    -    dragger.onWindowMouseOut_(e);
    -    assertTrue('Drag is canceled for real mouse out of top window.',
    -        dragCanceled);
    -    assertFalse('Must stop dragging for real mouse out of top window.',
    -        dragger.isDragging());
    -  }
    -}
    -
    -function testLimits() {
    -  var dragger = new goog.fx.Dragger(target);
    -
    -  assertEquals(100, dragger.limitX(100));
    -  assertEquals(100, dragger.limitY(100));
    -
    -  dragger.setLimits(new goog.math.Rect(10, 20, 30, 40));
    -
    -  assertEquals(10, dragger.limitX(0));
    -  assertEquals(40, dragger.limitX(100));
    -  assertEquals(20, dragger.limitY(0));
    -  assertEquals(60, dragger.limitY(100));
    -}
    -
    -function testWindowBlur() {
    -  if (!goog.fx.Dragger.HAS_SET_CAPTURE_) {
    -    var dragger = new goog.fx.Dragger(target);
    -
    -    var dragEnded = false;
    -    goog.events.listen(dragger, goog.fx.Dragger.EventType.END, function(e) {
    -      dragEnded = true;
    -    });
    -
    -    var e = new goog.testing.StrictMock(goog.events.BrowserEvent);
    -    e.type = goog.events.EventType.MOUSEDOWN;
    -    e.clientX = 1;
    -    e.clientY = 2;
    -    e.isMouseActionButton().$returns(true);
    -    e.preventDefault();
    -    e.$replay();
    -    dragger.startDrag(e);
    -    e.$verify();
    -
    -    assertTrue(dragger.isDragging());
    -
    -    e = new goog.events.BrowserEvent();
    -    e.type = goog.events.EventType.BLUR;
    -    e.target = window;
    -    e.currentTarget = window;
    -    goog.testing.events.fireBrowserEvent(e);
    -
    -    assertTrue(dragEnded);
    -  }
    -}
    -
    -function testBlur() {
    -  if (!goog.fx.Dragger.HAS_SET_CAPTURE_) {
    -    var dragger = new goog.fx.Dragger(target);
    -
    -    var dragEnded = false;
    -    goog.events.listen(dragger, goog.fx.Dragger.EventType.END, function(e) {
    -      dragEnded = true;
    -    });
    -
    -    var e = new goog.testing.StrictMock(goog.events.BrowserEvent);
    -    e.type = goog.events.EventType.MOUSEDOWN;
    -    e.clientX = 1;
    -    e.clientY = 2;
    -    e.isMouseActionButton().$returns(true);
    -    e.preventDefault();
    -    e.$replay();
    -    dragger.startDrag(e);
    -    e.$verify();
    -
    -    assertTrue(dragger.isDragging());
    -
    -    e = new goog.events.BrowserEvent();
    -    e.type = goog.events.EventType.BLUR;
    -    e.target = document.body;
    -    e.currentTarget = document.body;
    -    // Blur events do not bubble but the test event system does not emulate that
    -    // part so we add a capturing listener on the target and stops the
    -    // propagation at the target, preventing any event from bubbling.
    -    goog.events.listen(document.body, goog.events.EventType.BLUR, function(e) {
    -      e.propagationStopped_ = true;
    -    }, true);
    -    goog.testing.events.fireBrowserEvent(e);
    -
    -    assertFalse(dragEnded);
    -  }
    -}
    -
    -function testCloneNode() {
    -  var element = goog.dom.createDom('div');
    -  element.innerHTML =
    -      '<input type="hidden" value="v0">' +
    -      '<textarea>v1</textarea>' +
    -      '<textarea>v2</textarea>';
    -  element.childNodes[0].value = '\'new\'\n"value"';
    -  element.childNodes[1].value = '<' + '/textarea>&lt;3';
    -  element.childNodes[2].value = '<script>\n\talert("oops!");<' + '/script>';
    -  var clone = goog.fx.Dragger.cloneNode(element);
    -  assertEquals(element.childNodes[0].value, clone.childNodes[0].value);
    -  assertEquals(element.childNodes[1].value, clone.childNodes[1].value);
    -  assertEquals(element.childNodes[2].value, clone.childNodes[2].value);
    -  clone = goog.fx.Dragger.cloneNode(element.childNodes[2]);
    -  assertEquals(element.childNodes[2].value, clone.value);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/draglistgroup.js b/src/database/third_party/closure-library/closure/goog/fx/draglistgroup.js
    deleted file mode 100644
    index dc20ec02a8b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/draglistgroup.js
    +++ /dev/null
    @@ -1,1312 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A DragListGroup is a class representing a group of one or more
    - * "drag lists" with items that can be dragged within them and between them.
    - *
    - * @see ../demos/draglistgroup.html
    - */
    -
    -
    -goog.provide('goog.fx.DragListDirection');
    -goog.provide('goog.fx.DragListGroup');
    -goog.provide('goog.fx.DragListGroup.EventType');
    -goog.provide('goog.fx.DragListGroupEvent');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -goog.require('goog.fx.Dragger');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.string');
    -goog.require('goog.style');
    -
    -
    -
    -/**
    - * A class representing a group of one or more "drag lists" with items that can
    - * be dragged within them and between them.
    - *
    - * Example usage:
    - *   var dragListGroup = new goog.fx.DragListGroup();
    - *   dragListGroup.setDragItemHandleHoverClass(className1, className2);
    - *   dragListGroup.setDraggerElClass(className3);
    - *   dragListGroup.addDragList(vertList, goog.fx.DragListDirection.DOWN);
    - *   dragListGroup.addDragList(horizList, goog.fx.DragListDirection.RIGHT);
    - *   dragListGroup.init();
    - *
    - * @extends {goog.events.EventTarget}
    - * @constructor
    - */
    -goog.fx.DragListGroup = function() {
    -  goog.events.EventTarget.call(this);
    -
    -  /**
    -   * The drag lists.
    -   * @type {Array<Element>}
    -   * @private
    -   */
    -  this.dragLists_ = [];
    -
    -  /**
    -   * All the drag items. Set by init().
    -   * @type {Array<Element>}
    -   * @private
    -   */
    -  this.dragItems_ = [];
    -
    -  /**
    -   * Which drag item corresponds to a given handle.  Set by init().
    -   * Specifically, this maps from the unique ID (as given by goog.getUid)
    -   * of the handle to the drag item.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.dragItemForHandle_ = {};
    -
    -  /**
    -   * The event handler for this instance.
    -   * @type {goog.events.EventHandler<!goog.fx.DragListGroup>}
    -   * @private
    -   */
    -  this.eventHandler_ = new goog.events.EventHandler(this);
    -
    -  /**
    -   * Whether the setup has been done to make all items in all lists draggable.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.isInitialized_ = false;
    -
    -  /**
    -   * Whether the currDragItem is always displayed. By default the list
    -   * collapses, the currDragItem's display is set to none, when we do not
    -   * hover over a draglist.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.isCurrDragItemAlwaysDisplayed_ = false;
    -
    -  /**
    -   * Whether to update the position of the currDragItem as we drag, i.e.,
    -   * insert the currDragItem each time to the position where it would land if
    -   * we were to end the drag at that point. Defaults to true.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.updateWhileDragging_ = true;
    -};
    -goog.inherits(goog.fx.DragListGroup, goog.events.EventTarget);
    -
    -
    -/**
    - * Enum to indicate the direction that a drag list grows.
    - * @enum {number}
    - */
    -goog.fx.DragListDirection = {
    -  DOWN: 0,  // common
    -  RIGHT: 2,  // common
    -  LEFT: 3,  // uncommon (except perhaps for right-to-left interfaces)
    -  RIGHT_2D: 4, // common + handles multiple lines if items are wrapped
    -  LEFT_2D: 5 // for rtl languages
    -};
    -
    -
    -/**
    - * Events dispatched by this class.
    - * @const
    - */
    -goog.fx.DragListGroup.EventType = {
    -  BEFOREDRAGSTART: 'beforedragstart',
    -  DRAGSTART: 'dragstart',
    -  BEFOREDRAGMOVE: 'beforedragmove',
    -  DRAGMOVE: 'dragmove',
    -  BEFOREDRAGEND: 'beforedragend',
    -  DRAGEND: 'dragend'
    -};
    -
    -
    -// The next 4 are user-supplied CSS classes.
    -
    -
    -/**
    - * The user-supplied CSS classes to add to a drag item on hover (not during a
    - * drag action).
    - * @type {Array|undefined}
    - * @private
    - */
    -goog.fx.DragListGroup.prototype.dragItemHoverClasses_;
    -
    -
    -/**
    - * The user-supplied CSS classes to add to a drag item handle on hover (not
    - * during a drag action).
    - * @type {Array|undefined}
    - * @private
    - */
    -goog.fx.DragListGroup.prototype.dragItemHandleHoverClasses_;
    -
    -
    -/**
    - * The user-supplied CSS classes to add to the current drag item (during a drag
    - * action).
    - * @type {Array|undefined}
    - * @private
    - */
    -goog.fx.DragListGroup.prototype.currDragItemClasses_;
    -
    -
    -/**
    - * The user-supplied CSS classes to add to the clone of the current drag item
    - * that's actually being dragged around (during a drag action).
    - * @type {Array<string>|undefined}
    - * @private
    - */
    -goog.fx.DragListGroup.prototype.draggerElClasses_;
    -
    -
    -// The next 5 are info applicable during a drag action.
    -
    -
    -/**
    - * The current drag item being moved.
    - * Note: This is only defined while a drag action is happening.
    - * @type {Element}
    - * @private
    - */
    -goog.fx.DragListGroup.prototype.currDragItem_;
    -
    -
    -/**
    - * The drag list that {@code this.currDragItem_} is currently hovering over, or
    - * null if it is not hovering over a list.
    - * @type {Element}
    - * @private
    - */
    -goog.fx.DragListGroup.prototype.currHoverList_;
    -
    -
    -/**
    - * The original drag list that the current drag item came from. We need to
    - * remember this in case the user drops the item outside of any lists, in which
    - * case we return the item to its original location.
    - * Note: This is only defined while a drag action is happening.
    - * @type {Element}
    - * @private
    - */
    -goog.fx.DragListGroup.prototype.origList_;
    -
    -
    -/**
    - * The original next item in the original list that the current drag item came
    - * from. We need to remember this in case the user drops the item outside of
    - * any lists, in which case we return the item to its original location.
    - * Note: This is only defined while a drag action is happening.
    - * @type {Element}
    - * @private
    - */
    -goog.fx.DragListGroup.prototype.origNextItem_;
    -
    -
    -/**
    - * The current item in the list we are hovering over. We need to remember
    - * this in case we do not update the position of the current drag item while
    - * dragging (see {@code updateWhileDragging_}). In this case the current drag
    - * item will be inserted into the list before this element when the drag ends.
    - * @type {Element}
    - * @private
    - */
    -goog.fx.DragListGroup.prototype.currHoverItem_;
    -
    -
    -/**
    - * The clone of the current drag item that's actually being dragged around.
    - * Note: This is only defined while a drag action is happening.
    - * @type {Element}
    - * @private
    - */
    -goog.fx.DragListGroup.prototype.draggerEl_;
    -
    -
    -/**
    - * The dragger object.
    - * Note: This is only defined while a drag action is happening.
    - * @type {goog.fx.Dragger}
    - * @private
    - */
    -goog.fx.DragListGroup.prototype.dragger_;
    -
    -
    -/**
    - * The amount of distance, in pixels, after which a mousedown or touchstart is
    - * considered a drag.
    - * @type {number}
    - * @private
    - */
    -goog.fx.DragListGroup.prototype.hysteresisDistance_ = 0;
    -
    -
    -/**
    - * Sets the property of the currDragItem that it is always displayed in the
    - * list.
    - */
    -goog.fx.DragListGroup.prototype.setIsCurrDragItemAlwaysDisplayed = function() {
    -  this.isCurrDragItemAlwaysDisplayed_ = true;
    -};
    -
    -
    -/**
    - * Sets the private property updateWhileDragging_ to false. This disables the
    - * update of the position of the currDragItem while dragging. It will only be
    - * placed to its new location once the drag ends.
    - */
    -goog.fx.DragListGroup.prototype.setNoUpdateWhileDragging = function() {
    -  this.updateWhileDragging_ = false;
    -};
    -
    -
    -/**
    - * Sets the distance the user has to drag the element before a drag operation
    - * is started.
    - * @param {number} distance The number of pixels after which a mousedown and
    - *     move is considered a drag.
    - */
    -goog.fx.DragListGroup.prototype.setHysteresis = function(distance) {
    -  this.hysteresisDistance_ = distance;
    -};
    -
    -
    -/**
    - * @return {number} distance The number of pixels after which a mousedown and
    - *     move is considered a drag.
    - */
    -goog.fx.DragListGroup.prototype.getHysteresis = function() {
    -  return this.hysteresisDistance_;
    -};
    -
    -
    -/**
    - * Adds a drag list to this DragListGroup.
    - * All calls to this method must happen before the call to init().
    - * Remember that all child nodes (except text nodes) will be made draggable to
    - * any other drag list in this group.
    - *
    - * @param {Element} dragListElement Must be a container for a list of items
    - *     that should all be made draggable.
    - * @param {goog.fx.DragListDirection} growthDirection The direction that this
    - *     drag list grows in (i.e. if an item is appended to the DOM, the list's
    - *     bounding box expands in this direction).
    - * @param {boolean=} opt_unused Unused argument.
    - * @param {string=} opt_dragHoverClass CSS class to apply to this drag list when
    - *     the draggerEl hovers over it during a drag action.  If present, must be a
    - *     single, valid classname (not a string of space-separated classnames).
    - */
    -goog.fx.DragListGroup.prototype.addDragList = function(
    -    dragListElement, growthDirection, opt_unused, opt_dragHoverClass) {
    -  goog.asserts.assert(!this.isInitialized_);
    -
    -  dragListElement.dlgGrowthDirection_ = growthDirection;
    -  dragListElement.dlgDragHoverClass_ = opt_dragHoverClass;
    -  this.dragLists_.push(dragListElement);
    -};
    -
    -
    -/**
    - * Sets a user-supplied function used to get the "handle" element for a drag
    - * item. The function must accept exactly one argument. The argument may be
    - * any drag item element.
    - *
    - * If not set, the default implementation uses the whole drag item as the
    - * handle.
    - *
    - * @param {function(Element): Element} getHandleForDragItemFn A function that,
    - *     given any drag item, returns a reference to its "handle" element
    - *     (which may be the drag item element itself).
    - */
    -goog.fx.DragListGroup.prototype.setFunctionToGetHandleForDragItem = function(
    -    getHandleForDragItemFn) {
    -  goog.asserts.assert(!this.isInitialized_);
    -  this.getHandleForDragItem_ = getHandleForDragItemFn;
    -};
    -
    -
    -/**
    - * Sets a user-supplied CSS class to add to a drag item on hover (not during a
    - * drag action).
    - * @param {...!string} var_args The CSS class or classes.
    - */
    -goog.fx.DragListGroup.prototype.setDragItemHoverClass = function(var_args) {
    -  goog.asserts.assert(!this.isInitialized_);
    -  this.dragItemHoverClasses_ = goog.array.slice(arguments, 0);
    -};
    -
    -
    -/**
    - * Sets a user-supplied CSS class to add to a drag item handle on hover (not
    - * during a drag action).
    - * @param {...!string} var_args The CSS class or classes.
    - */
    -goog.fx.DragListGroup.prototype.setDragItemHandleHoverClass = function(
    -    var_args) {
    -  goog.asserts.assert(!this.isInitialized_);
    -  this.dragItemHandleHoverClasses_ = goog.array.slice(arguments, 0);
    -};
    -
    -
    -/**
    - * Sets a user-supplied CSS class to add to the current drag item (during a
    - * drag action).
    - *
    - * If not set, the default behavior adds visibility:hidden to the current drag
    - * item so that it is a block of empty space in the hover drag list (if any).
    - * If this class is set by the user, then the default behavior does not happen
    - * (unless, of course, the class also contains visibility:hidden).
    - *
    - * @param {...!string} var_args The CSS class or classes.
    - */
    -goog.fx.DragListGroup.prototype.setCurrDragItemClass = function(var_args) {
    -  goog.asserts.assert(!this.isInitialized_);
    -  this.currDragItemClasses_ = goog.array.slice(arguments, 0);
    -};
    -
    -
    -/**
    - * Sets a user-supplied CSS class to add to the clone of the current drag item
    - * that's actually being dragged around (during a drag action).
    - * @param {string} draggerElClass The CSS class.
    - */
    -goog.fx.DragListGroup.prototype.setDraggerElClass = function(draggerElClass) {
    -  goog.asserts.assert(!this.isInitialized_);
    -  // Split space-separated classes up into an array.
    -  this.draggerElClasses_ = goog.string.trim(draggerElClass).split(' ');
    -};
    -
    -
    -/**
    - * Performs the initial setup to make all items in all lists draggable.
    - */
    -goog.fx.DragListGroup.prototype.init = function() {
    -  if (this.isInitialized_) {
    -    return;
    -  }
    -
    -  for (var i = 0, numLists = this.dragLists_.length; i < numLists; i++) {
    -    var dragList = this.dragLists_[i];
    -
    -    var dragItems = goog.dom.getChildren(dragList);
    -    for (var j = 0, numItems = dragItems.length; j < numItems; ++j) {
    -      this.listenForDragEvents(dragItems[j]);
    -    }
    -  }
    -
    -  this.isInitialized_ = true;
    -};
    -
    -
    -/**
    - * Adds a single item to the given drag list and sets up the drag listeners for
    - * it.
    - * If opt_index is specified the item is inserted at this index, otherwise the
    - * item is added as the last child of the list.
    - *
    - * @param {!Element} list The drag list where to add item to.
    - * @param {!Element} item The new element to add.
    - * @param {number=} opt_index Index where to insert the item in the list. If not
    - * specified item is inserted as the last child of list.
    - */
    -goog.fx.DragListGroup.prototype.addItemToDragList = function(list, item,
    -    opt_index) {
    -  if (goog.isDef(opt_index)) {
    -    goog.dom.insertChildAt(list, item, opt_index);
    -  } else {
    -    goog.dom.appendChild(list, item);
    -  }
    -  this.listenForDragEvents(item);
    -};
    -
    -
    -/** @override */
    -goog.fx.DragListGroup.prototype.disposeInternal = function() {
    -  this.eventHandler_.dispose();
    -
    -  for (var i = 0, n = this.dragLists_.length; i < n; i++) {
    -    var dragList = this.dragLists_[i];
    -    // Note: IE doesn't allow 'delete' for fields on HTML elements (because
    -    // they're not real JS objects in IE), so we just set them to undefined.
    -    dragList.dlgGrowthDirection_ = undefined;
    -    dragList.dlgDragHoverClass_ = undefined;
    -  }
    -
    -  this.dragLists_.length = 0;
    -  this.dragItems_.length = 0;
    -  this.dragItemForHandle_ = null;
    -
    -  // In the case where a drag event is currently in-progress and dispose is
    -  // called, this cleans up the extra state.
    -  this.cleanupDragDom_();
    -
    -  goog.fx.DragListGroup.superClass_.disposeInternal.call(this);
    -};
    -
    -
    -/**
    - * Caches the heights of each drag list and drag item, except for the current
    - * drag item.
    - *
    - * @param {Element} currDragItem The item currently being dragged.
    - * @private
    - */
    -goog.fx.DragListGroup.prototype.recacheListAndItemBounds_ = function(
    -    currDragItem) {
    -  for (var i = 0, n = this.dragLists_.length; i < n; i++) {
    -    var dragList = this.dragLists_[i];
    -    dragList.dlgBounds_ = goog.style.getBounds(dragList);
    -  }
    -
    -  for (var i = 0, n = this.dragItems_.length; i < n; i++) {
    -    var dragItem = this.dragItems_[i];
    -    if (dragItem != currDragItem) {
    -      dragItem.dlgBounds_ = goog.style.getBounds(dragItem);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Listens for drag events on the given drag item. This method is currently used
    - * to initialize drag items.
    - *
    - * @param {Element} dragItem the element to initialize. This element has to be
    - * in one of the drag lists.
    - * @protected
    - */
    -goog.fx.DragListGroup.prototype.listenForDragEvents = function(dragItem) {
    -  var dragItemHandle = this.getHandleForDragItem_(dragItem);
    -  var uid = goog.getUid(dragItemHandle);
    -  this.dragItemForHandle_[uid] = dragItem;
    -
    -  if (this.dragItemHoverClasses_) {
    -    this.eventHandler_.listen(
    -        dragItem, goog.events.EventType.MOUSEOVER,
    -        this.handleDragItemMouseover_);
    -    this.eventHandler_.listen(
    -        dragItem, goog.events.EventType.MOUSEOUT,
    -        this.handleDragItemMouseout_);
    -  }
    -  if (this.dragItemHandleHoverClasses_) {
    -    this.eventHandler_.listen(
    -        dragItemHandle, goog.events.EventType.MOUSEOVER,
    -        this.handleDragItemHandleMouseover_);
    -    this.eventHandler_.listen(
    -        dragItemHandle, goog.events.EventType.MOUSEOUT,
    -        this.handleDragItemHandleMouseout_);
    -  }
    -
    -  this.dragItems_.push(dragItem);
    -  this.eventHandler_.listen(dragItemHandle,
    -      [goog.events.EventType.MOUSEDOWN, goog.events.EventType.TOUCHSTART],
    -      this.handlePotentialDragStart_);
    -};
    -
    -
    -/**
    - * Handles mouse and touch events which may start a drag action.
    - * @param {!goog.events.BrowserEvent} e MOUSEDOWN or TOUCHSTART event.
    - * @private
    - */
    -goog.fx.DragListGroup.prototype.handlePotentialDragStart_ = function(e) {
    -  var uid = goog.getUid(/** @type {Node} */ (e.currentTarget));
    -  this.currDragItem_ = /** @type {Element} */ (this.dragItemForHandle_[uid]);
    -
    -  this.draggerEl_ = this.createDragElementInternal(this.currDragItem_);
    -  if (this.draggerElClasses_) {
    -    // Add CSS class for the clone, if any.
    -    goog.dom.classlist.addAll(
    -        goog.asserts.assert(this.draggerEl_), this.draggerElClasses_ || []);
    -  }
    -
    -  // Place the clone (i.e. draggerEl) at the same position as the actual
    -  // current drag item. This is a bit tricky since
    -  //   goog.style.getPageOffset() gets the left-top pos of the border, but
    -  //   goog.style.setPageOffset() sets the left-top pos of the margin.
    -  // It's difficult to adjust for the margins of the clone because it's
    -  // difficult to read it: goog.style.getComputedStyle() doesn't work for IE.
    -  // Instead, our workaround is simply to set the clone's margins to 0px.
    -  this.draggerEl_.style.margin = '0';
    -  this.draggerEl_.style.position = 'absolute';
    -  this.draggerEl_.style.visibility = 'hidden';
    -  var doc = goog.dom.getOwnerDocument(this.currDragItem_);
    -  doc.body.appendChild(this.draggerEl_);
    -
    -  // Important: goog.style.setPageOffset() only works correctly for IE when the
    -  // element is already in the document.
    -  var currDragItemPos = goog.style.getPageOffset(this.currDragItem_);
    -  goog.style.setPageOffset(this.draggerEl_, currDragItemPos);
    -
    -  this.dragger_ = new goog.fx.Dragger(this.draggerEl_);
    -  this.dragger_.setHysteresis(this.hysteresisDistance_);
    -
    -  // Listen to events on the dragger. These handlers will be unregistered at
    -  // DRAGEND, when the dragger is disposed of. We can't use eventHandler_,
    -  // because it creates new references to the handler functions at each
    -  // dragging action, and keeps them until DragListGroup is disposed of.
    -  goog.events.listen(this.dragger_, goog.fx.Dragger.EventType.START,
    -      this.handleDragStart_, false, this);
    -  goog.events.listen(this.dragger_, goog.fx.Dragger.EventType.END,
    -      this.handleDragEnd_, false, this);
    -  goog.events.listen(this.dragger_, goog.fx.Dragger.EventType.EARLY_CANCEL,
    -      this.cleanup_, false, this);
    -  this.dragger_.startDrag(e);
    -};
    -
    -
    -/**
    - * Creates copy of node being dragged.
    - *
    - * @param {Element} sourceEl Element to copy.
    - * @return {!Element} The clone of {@code sourceEl}.
    - * @deprecated Use goog.fx.Dragger.cloneNode().
    - * @private
    - */
    -goog.fx.DragListGroup.prototype.cloneNode_ = function(sourceEl) {
    -  return goog.fx.Dragger.cloneNode(sourceEl);
    -};
    -
    -
    -/**
    - * Generates an element to follow the cursor during dragging, given a drag
    - * source element.  The default behavior is simply to clone the source element,
    - * but this may be overridden in subclasses.  This method is called by
    - * {@code createDragElement()} before the drag class is added.
    - *
    - * @param {Element} sourceEl Drag source element.
    - * @return {!Element} The new drag element.
    - * @protected
    - * @suppress {deprecated}
    - */
    -goog.fx.DragListGroup.prototype.createDragElementInternal =
    -    function(sourceEl) {
    -  return this.cloneNode_(sourceEl);
    -};
    -
    -
    -/**
    - * Handles the start of a drag action.
    - * @param {!goog.fx.DragEvent} e goog.fx.Dragger.EventType.START event.
    - * @private
    - */
    -goog.fx.DragListGroup.prototype.handleDragStart_ = function(e) {
    -  if (!this.dispatchEvent(new goog.fx.DragListGroupEvent(
    -      goog.fx.DragListGroup.EventType.BEFOREDRAGSTART, this, e.browserEvent,
    -      this.currDragItem_, null, null))) {
    -    e.preventDefault();
    -    this.cleanup_();
    -    return;
    -  }
    -
    -  // Record the original location of the current drag item.
    -  // Note: this.origNextItem_ may be null.
    -  this.origList_ = /** @type {Element} */ (this.currDragItem_.parentNode);
    -  this.origNextItem_ = goog.dom.getNextElementSibling(this.currDragItem_);
    -  this.currHoverItem_ = this.origNextItem_;
    -  this.currHoverList_ = this.origList_;
    -
    -  // If there's a CSS class specified for the current drag item, add it.
    -  // Otherwise, make the actual current drag item hidden (takes up space).
    -  if (this.currDragItemClasses_) {
    -    goog.dom.classlist.addAll(
    -        goog.asserts.assert(this.currDragItem_),
    -        this.currDragItemClasses_ || []);
    -  } else {
    -    this.currDragItem_.style.visibility = 'hidden';
    -  }
    -
    -  // Precompute distances from top-left corner to center for efficiency.
    -  var draggerElSize = goog.style.getSize(this.draggerEl_);
    -  this.draggerEl_.halfWidth = draggerElSize.width / 2;
    -  this.draggerEl_.halfHeight = draggerElSize.height / 2;
    -
    -  this.draggerEl_.style.visibility = '';
    -
    -  // Record the bounds of all the drag lists and all the other drag items. This
    -  // caching is for efficiency, so that we don't have to recompute the bounds on
    -  // each drag move. Do this in the state where the current drag item is not in
    -  // any of the lists, except when update while dragging is disabled, as in this
    -  // case the current drag item does not get removed until drag ends.
    -  if (this.updateWhileDragging_) {
    -    this.currDragItem_.style.display = 'none';
    -  }
    -  this.recacheListAndItemBounds_(this.currDragItem_);
    -  this.currDragItem_.style.display = '';
    -
    -  // Listen to events on the dragger.
    -  goog.events.listen(this.dragger_, goog.fx.Dragger.EventType.DRAG,
    -      this.handleDragMove_, false, this);
    -
    -  this.dispatchEvent(
    -      new goog.fx.DragListGroupEvent(
    -          goog.fx.DragListGroup.EventType.DRAGSTART, this, e.browserEvent,
    -          this.currDragItem_, this.draggerEl_, this.dragger_));
    -};
    -
    -
    -/**
    - * Handles a drag movement (i.e. DRAG event fired by the dragger).
    - *
    - * @param {goog.fx.DragEvent} dragEvent Event object fired by the dragger.
    - * @return {boolean} The return value for the event.
    - * @private
    - */
    -goog.fx.DragListGroup.prototype.handleDragMove_ = function(dragEvent) {
    -
    -  // Compute the center of the dragger element (i.e. the cloned drag item).
    -  var draggerElPos = goog.style.getPageOffset(this.draggerEl_);
    -  var draggerElCenter = new goog.math.Coordinate(
    -      draggerElPos.x + this.draggerEl_.halfWidth,
    -      draggerElPos.y + this.draggerEl_.halfHeight);
    -
    -  // Check whether the center is hovering over one of the drag lists.
    -  var hoverList = this.getHoverDragList_(draggerElCenter);
    -
    -  // If hovering over a list, find the next item (if drag were to end now).
    -  var hoverNextItem =
    -      hoverList ? this.getHoverNextItem_(hoverList, draggerElCenter) : null;
    -
    -  var rv = this.dispatchEvent(
    -      new goog.fx.DragListGroupEvent(
    -          goog.fx.DragListGroup.EventType.BEFOREDRAGMOVE, this, dragEvent,
    -          this.currDragItem_, this.draggerEl_, this.dragger_,
    -          draggerElCenter, hoverList, hoverNextItem));
    -  if (!rv) {
    -    return false;
    -  }
    -
    -  if (hoverList) {
    -    if (this.updateWhileDragging_) {
    -      this.insertCurrDragItem_(hoverList, hoverNextItem);
    -    } else {
    -      // If update while dragging is disabled do not insert
    -      // the dragged item, but update the hovered item instead.
    -      this.updateCurrHoverItem(hoverNextItem, draggerElCenter);
    -    }
    -    this.currDragItem_.style.display = '';
    -    // Add drag list's hover class (if any).
    -    if (hoverList.dlgDragHoverClass_) {
    -      goog.dom.classlist.add(
    -          goog.asserts.assert(hoverList), hoverList.dlgDragHoverClass_);
    -    }
    -
    -  } else {
    -    // Not hovering over a drag list, so remove the item altogether unless
    -    // specified otherwise by the user.
    -    if (!this.isCurrDragItemAlwaysDisplayed_) {
    -      this.currDragItem_.style.display = 'none';
    -    }
    -
    -    // Remove hover classes (if any) from all drag lists.
    -    for (var i = 0, n = this.dragLists_.length; i < n; i++) {
    -      var dragList = this.dragLists_[i];
    -      if (dragList.dlgDragHoverClass_) {
    -        goog.dom.classlist.remove(
    -            goog.asserts.assert(dragList), dragList.dlgDragHoverClass_);
    -      }
    -    }
    -  }
    -
    -  // If the current hover list is different than the last, the lists may have
    -  // shrunk, so we should recache the bounds.
    -  if (hoverList != this.currHoverList_) {
    -    this.currHoverList_ = hoverList;
    -    this.recacheListAndItemBounds_(this.currDragItem_);
    -  }
    -
    -  this.dispatchEvent(
    -      new goog.fx.DragListGroupEvent(
    -          goog.fx.DragListGroup.EventType.DRAGMOVE, this, dragEvent,
    -          /** @type {Element} */ (this.currDragItem_),
    -          this.draggerEl_, this.dragger_,
    -          draggerElCenter, hoverList, hoverNextItem));
    -
    -  // Return false to prevent selection due to mouse drag.
    -  return false;
    -};
    -
    -
    -/**
    - * Clear all our temporary fields that are only defined while dragging, and
    - * all the bounds info stored on the drag lists and drag elements.
    - * @param {!goog.events.Event=} opt_e EARLY_CANCEL event from the dragger if
    - *     cleanup_ was called as an event handler.
    - * @private
    - */
    -goog.fx.DragListGroup.prototype.cleanup_ = function(opt_e) {
    -  this.cleanupDragDom_();
    -
    -  this.currDragItem_ = null;
    -  this.currHoverList_ = null;
    -  this.origList_ = null;
    -  this.origNextItem_ = null;
    -  this.draggerEl_ = null;
    -  this.dragger_ = null;
    -
    -  // Note: IE doesn't allow 'delete' for fields on HTML elements (because
    -  // they're not real JS objects in IE), so we just set them to null.
    -  for (var i = 0, n = this.dragLists_.length; i < n; i++) {
    -    this.dragLists_[i].dlgBounds_ = null;
    -  }
    -  for (var i = 0, n = this.dragItems_.length; i < n; i++) {
    -    this.dragItems_[i].dlgBounds_ = null;
    -  }
    -};
    -
    -
    -/**
    - * Handles the end or the cancellation of a drag action, i.e. END or CLEANUP
    - * event fired by the dragger.
    - *
    - * @param {!goog.fx.DragEvent} dragEvent Event object fired by the dragger.
    - * @return {boolean} Whether the event was handled.
    - * @private
    - */
    -goog.fx.DragListGroup.prototype.handleDragEnd_ = function(dragEvent) {
    -  var rv = this.dispatchEvent(
    -      new goog.fx.DragListGroupEvent(
    -          goog.fx.DragListGroup.EventType.BEFOREDRAGEND, this, dragEvent,
    -          /** @type {Element} */ (this.currDragItem_),
    -          this.draggerEl_, this.dragger_));
    -  if (!rv) {
    -    return false;
    -  }
    -
    -  // If update while dragging is disabled insert the current drag item into
    -  // its intended location.
    -  if (!this.updateWhileDragging_) {
    -    this.insertCurrHoverItem();
    -  }
    -
    -  // The DRAGEND handler may need the new order of the list items. Clean up the
    -  // garbage.
    -  // TODO(user): Regression test.
    -  this.cleanupDragDom_();
    -
    -  this.dispatchEvent(
    -      new goog.fx.DragListGroupEvent(
    -          goog.fx.DragListGroup.EventType.DRAGEND, this, dragEvent,
    -          this.currDragItem_, this.draggerEl_, this.dragger_));
    -
    -  this.cleanup_();
    -
    -  return true;
    -};
    -
    -
    -/**
    - * Cleans up DOM changes that are made by the {@code handleDrag*} methods.
    - * @private
    - */
    -goog.fx.DragListGroup.prototype.cleanupDragDom_ = function() {
    -  // Disposes of the dragger and remove the cloned drag item.
    -  goog.dispose(this.dragger_);
    -  if (this.draggerEl_) {
    -    goog.dom.removeNode(this.draggerEl_);
    -  }
    -
    -  // If the current drag item is not in any list, put it back in its original
    -  // location.
    -  if (this.currDragItem_ && this.currDragItem_.style.display == 'none') {
    -    // Note: this.origNextItem_ may be null, but insertBefore() still works.
    -    this.origList_.insertBefore(this.currDragItem_, this.origNextItem_);
    -    this.currDragItem_.style.display = '';
    -  }
    -
    -  // If there's a CSS class specified for the current drag item, remove it.
    -  // Otherwise, make the current drag item visible (instead of empty space).
    -  if (this.currDragItemClasses_ && this.currDragItem_) {
    -    goog.dom.classlist.removeAll(
    -        goog.asserts.assert(this.currDragItem_),
    -        this.currDragItemClasses_ || []);
    -  } else if (this.currDragItem_) {
    -    this.currDragItem_.style.visibility = 'visible';
    -  }
    -
    -  // Remove hover classes (if any) from all drag lists.
    -  for (var i = 0, n = this.dragLists_.length; i < n; i++) {
    -    var dragList = this.dragLists_[i];
    -    if (dragList.dlgDragHoverClass_) {
    -      goog.dom.classlist.remove(
    -          goog.asserts.assert(dragList), dragList.dlgDragHoverClass_);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Default implementation of the function to get the "handle" element for a
    - * drag item. By default, we use the whole drag item as the handle. Users can
    - * change this by calling setFunctionToGetHandleForDragItem().
    - *
    - * @param {Element} dragItem The drag item to get the handle for.
    - * @return {Element} The dragItem element itself.
    - * @private
    - */
    -goog.fx.DragListGroup.prototype.getHandleForDragItem_ = function(dragItem) {
    -  return dragItem;
    -};
    -
    -
    -/**
    - * Handles a MOUSEOVER event fired on a drag item.
    - * @param {goog.events.BrowserEvent} e The event.
    - * @private
    - */
    -goog.fx.DragListGroup.prototype.handleDragItemMouseover_ = function(e) {
    -  var targetEl = goog.asserts.assertElement(e.currentTarget);
    -  goog.dom.classlist.addAll(targetEl, this.dragItemHoverClasses_ || []);
    -};
    -
    -
    -/**
    - * Handles a MOUSEOUT event fired on a drag item.
    - * @param {goog.events.BrowserEvent} e The event.
    - * @private
    - */
    -goog.fx.DragListGroup.prototype.handleDragItemMouseout_ = function(e) {
    -  var targetEl = goog.asserts.assertElement(e.currentTarget);
    -  goog.dom.classlist.removeAll(targetEl, this.dragItemHoverClasses_ || []);
    -};
    -
    -
    -/**
    - * Handles a MOUSEOVER event fired on the handle element of a drag item.
    - * @param {goog.events.BrowserEvent} e The event.
    - * @private
    - */
    -goog.fx.DragListGroup.prototype.handleDragItemHandleMouseover_ = function(e) {
    -  var targetEl = goog.asserts.assertElement(e.currentTarget);
    -  goog.dom.classlist.addAll(targetEl, this.dragItemHandleHoverClasses_ || []);
    -};
    -
    -
    -/**
    - * Handles a MOUSEOUT event fired on the handle element of a drag item.
    - * @param {goog.events.BrowserEvent} e The event.
    - * @private
    - */
    -goog.fx.DragListGroup.prototype.handleDragItemHandleMouseout_ = function(e) {
    -  var targetEl = goog.asserts.assertElement(e.currentTarget);
    -  goog.dom.classlist.removeAll(targetEl,
    -      this.dragItemHandleHoverClasses_ || []);
    -};
    -
    -
    -/**
    - * Helper for handleDragMove_().
    - * Given the position of the center of the dragger element, figures out whether
    - * it's currently hovering over any of the drag lists.
    - *
    - * @param {goog.math.Coordinate} draggerElCenter The center position of the
    - *     dragger element.
    - * @return {Element} If currently hovering over a drag list, returns the drag
    - *     list element. Else returns null.
    - * @private
    - */
    -goog.fx.DragListGroup.prototype.getHoverDragList_ = function(draggerElCenter) {
    -
    -  // If the current drag item was in a list last time we did this, then check
    -  // that same list first.
    -  var prevHoverList = null;
    -  if (this.currDragItem_.style.display != 'none') {
    -    prevHoverList = /** @type {Element} */ (this.currDragItem_.parentNode);
    -    // Important: We can't use the cached bounds for this list because the
    -    // cached bounds are based on the case where the current drag item is not
    -    // in the list. Since the current drag item is known to be in this list, we
    -    // must recompute the list's bounds.
    -    var prevHoverListBounds = goog.style.getBounds(prevHoverList);
    -    if (this.isInRect_(draggerElCenter, prevHoverListBounds)) {
    -      return prevHoverList;
    -    }
    -  }
    -
    -  for (var i = 0, n = this.dragLists_.length; i < n; i++) {
    -    var dragList = this.dragLists_[i];
    -    if (dragList == prevHoverList) {
    -      continue;
    -    }
    -    if (this.isInRect_(draggerElCenter, dragList.dlgBounds_)) {
    -      return dragList;
    -    }
    -  }
    -
    -  return null;
    -};
    -
    -
    -/**
    - * Checks whether a coordinate position resides inside a rectangle.
    - * @param {goog.math.Coordinate} pos The coordinate position.
    - * @param {goog.math.Rect} rect The rectangle.
    - * @return {boolean} True if 'pos' is within the bounds of 'rect'.
    - * @private
    - */
    -goog.fx.DragListGroup.prototype.isInRect_ = function(pos, rect) {
    -  return pos.x > rect.left && pos.x < rect.left + rect.width &&
    -         pos.y > rect.top && pos.y < rect.top + rect.height;
    -};
    -
    -
    -/**
    - * Updates the value of currHoverItem_.
    - *
    - * This method is used for insertion only when updateWhileDragging_ is false.
    - * The below implementation is the basic one. This method can be extended by
    - * a subclass to support changes to hovered item (eg: highlighting). Parametr
    - * opt_draggerElCenter can be used for more sophisticated effects.
    - *
    - * @param {Element} hoverNextItem element of the list that is hovered over.
    - * @param {goog.math.Coordinate=} opt_draggerElCenter current position of
    - *     the dragged element.
    - * @protected
    - */
    -goog.fx.DragListGroup.prototype.updateCurrHoverItem = function(
    -    hoverNextItem, opt_draggerElCenter) {
    -  if (hoverNextItem) {
    -    this.currHoverItem_ = hoverNextItem;
    -  }
    -};
    -
    -
    -/**
    - * Inserts the currently dragged item in its new place.
    - *
    - * This method is used for insertion only when updateWhileDragging_ is false
    - * (otherwise there is no need for that). In the basic implementation
    - * the element is inserted before the currently hovered over item (this can
    - * be changed by overriding the method in subclasses).
    - *
    - * @protected
    - */
    -goog.fx.DragListGroup.prototype.insertCurrHoverItem = function() {
    -  this.origList_.insertBefore(this.currDragItem_, this.currHoverItem_);
    -};
    -
    -
    -/**
    - * Helper for handleDragMove_().
    - * Given the position of the center of the dragger element, plus the drag list
    - * that it's currently hovering over, figures out the next drag item in the
    - * list that follows the current position of the dragger element. (I.e. if
    - * the drag action ends right now, it would become the item after the current
    - * drag item.)
    - *
    - * @param {Element} hoverList The drag list that we're hovering over.
    - * @param {goog.math.Coordinate} draggerElCenter The center position of the
    - *     dragger element.
    - * @return {Element} Returns the earliest item in the hover list that belongs
    - *     after the current position of the dragger element. If all items in the
    - *     list should come before the current drag item, then returns null.
    - * @private
    - */
    -goog.fx.DragListGroup.prototype.getHoverNextItem_ = function(
    -    hoverList, draggerElCenter) {
    -  if (hoverList == null) {
    -    throw Error('getHoverNextItem_ called with null hoverList.');
    -  }
    -
    -  // The definition of what it means for the draggerEl to be "before" a given
    -  // item in the hover drag list is not always the same. It changes based on
    -  // the growth direction of the hover drag list in question.
    -  /** @type {number} */
    -  var relevantCoord;
    -  var getRelevantBoundFn;
    -  var isBeforeFn;
    -  var pickClosestRow = false;
    -  var distanceToClosestRow = undefined;
    -  switch (hoverList.dlgGrowthDirection_) {
    -    case goog.fx.DragListDirection.DOWN:
    -      // "Before" means draggerElCenter.y is less than item's bottom y-value.
    -      relevantCoord = draggerElCenter.y;
    -      getRelevantBoundFn = goog.fx.DragListGroup.getBottomBound_;
    -      isBeforeFn = goog.fx.DragListGroup.isLessThan_;
    -      break;
    -    case goog.fx.DragListDirection.RIGHT_2D:
    -      pickClosestRow = true;
    -    case goog.fx.DragListDirection.RIGHT:
    -      // "Before" means draggerElCenter.x is less than item's right x-value.
    -      relevantCoord = draggerElCenter.x;
    -      getRelevantBoundFn = goog.fx.DragListGroup.getRightBound_;
    -      isBeforeFn = goog.fx.DragListGroup.isLessThan_;
    -      break;
    -    case goog.fx.DragListDirection.LEFT_2D:
    -      pickClosestRow = true;
    -    case goog.fx.DragListDirection.LEFT:
    -      // "Before" means draggerElCenter.x is greater than item's left x-value.
    -      relevantCoord = draggerElCenter.x;
    -      getRelevantBoundFn = goog.fx.DragListGroup.getLeftBound_;
    -      isBeforeFn = goog.fx.DragListGroup.isGreaterThan_;
    -      break;
    -  }
    -
    -  // This holds the earliest drag item found so far that should come after
    -  // this.currDragItem_ in the hover drag list (based on draggerElCenter).
    -  var earliestAfterItem = null;
    -  // This is the position of the relevant bound for the earliestAfterItem,
    -  // where "relevant" is determined by the growth direction of hoverList.
    -  var earliestAfterItemRelevantBound;
    -
    -  var hoverListItems = goog.dom.getChildren(hoverList);
    -  for (var i = 0, n = hoverListItems.length; i < n; i++) {
    -    var item = hoverListItems[i];
    -    if (item == this.currDragItem_) {
    -      continue;
    -    }
    -
    -    var relevantBound = getRelevantBoundFn(item.dlgBounds_);
    -    // When the hoverlist is broken into multiple rows (i.e., in the case of
    -    // LEFT_2D and RIGHT_2D) it is no longer enough to only look at the
    -    // x-coordinate alone in order to find the {@earliestAfterItem} in the
    -    // hoverlist. Make sure it is chosen from the row closest to the
    -    // {@code draggerElCenter}.
    -    if (pickClosestRow) {
    -      var distanceToRow = goog.fx.DragListGroup.verticalDistanceFromItem_(item,
    -          draggerElCenter);
    -      // Initialize the distance to the closest row to the current value if
    -      // undefined.
    -      if (!goog.isDef(distanceToClosestRow)) {
    -        distanceToClosestRow = distanceToRow;
    -      }
    -      if (isBeforeFn(relevantCoord, relevantBound) &&
    -          (earliestAfterItemRelevantBound == undefined ||
    -           (distanceToRow < distanceToClosestRow) ||
    -           ((distanceToRow == distanceToClosestRow) &&
    -            (isBeforeFn(relevantBound, earliestAfterItemRelevantBound) ||
    -            relevantBound == earliestAfterItemRelevantBound)))) {
    -        earliestAfterItem = item;
    -        earliestAfterItemRelevantBound = relevantBound;
    -      }
    -      // Update distance to closest row.
    -      if (distanceToRow < distanceToClosestRow) {
    -        distanceToClosestRow = distanceToRow;
    -      }
    -    } else if (isBeforeFn(relevantCoord, relevantBound) &&
    -        (earliestAfterItemRelevantBound == undefined ||
    -         isBeforeFn(relevantBound, earliestAfterItemRelevantBound))) {
    -      earliestAfterItem = item;
    -      earliestAfterItemRelevantBound = relevantBound;
    -    }
    -  }
    -  // If we ended up picking an element that is not in the closest row it can
    -  // only happen if we should have picked the last one in which case there is
    -  // no consecutive element.
    -  if (!goog.isNull(earliestAfterItem) &&
    -      goog.fx.DragListGroup.verticalDistanceFromItem_(
    -          earliestAfterItem, draggerElCenter) > distanceToClosestRow) {
    -    return null;
    -  } else {
    -    return earliestAfterItem;
    -  }
    -};
    -
    -
    -/**
    - * Private helper for getHoverNextItem().
    - * Given an item and a target determine the vertical distance from the item's
    - * center to the target.
    - * @param {Element} item The item to measure the distance from.
    - * @param {goog.math.Coordinate} target The (x,y) coordinate of the target
    - *     to measure the distance to.
    - * @return {number} The vertical distance between the center of the item and
    - *     the target.
    - * @private
    - */
    -goog.fx.DragListGroup.verticalDistanceFromItem_ = function(item, target) {
    -  var itemBounds = item.dlgBounds_;
    -  var itemCenterY = itemBounds.top + (itemBounds.height - 1) / 2;
    -  return Math.abs(target.y - itemCenterY);
    -};
    -
    -
    -/**
    - * Private helper for getHoverNextItem_().
    - * Given the bounds of an item, computes the item's bottom y-value.
    - * @param {goog.math.Rect} itemBounds The bounds of the item.
    - * @return {number} The item's bottom y-value.
    - * @private
    - */
    -goog.fx.DragListGroup.getBottomBound_ = function(itemBounds) {
    -  return itemBounds.top + itemBounds.height - 1;
    -};
    -
    -
    -/**
    - * Private helper for getHoverNextItem_().
    - * Given the bounds of an item, computes the item's right x-value.
    - * @param {goog.math.Rect} itemBounds The bounds of the item.
    - * @return {number} The item's right x-value.
    - * @private
    - */
    -goog.fx.DragListGroup.getRightBound_ = function(itemBounds) {
    -  return itemBounds.left + itemBounds.width - 1;
    -};
    -
    -
    -/**
    - * Private helper for getHoverNextItem_().
    - * Given the bounds of an item, computes the item's left x-value.
    - * @param {goog.math.Rect} itemBounds The bounds of the item.
    - * @return {number} The item's left x-value.
    - * @private
    - */
    -goog.fx.DragListGroup.getLeftBound_ = function(itemBounds) {
    -  return itemBounds.left || 0;
    -};
    -
    -
    -/**
    - * Private helper for getHoverNextItem_().
    - * @param {number} a Number to compare.
    - * @param {number} b Number to compare.
    - * @return {boolean} Whether a is less than b.
    - * @private
    - */
    -goog.fx.DragListGroup.isLessThan_ = function(a, b) {
    -  return a < b;
    -};
    -
    -
    -/**
    - * Private helper for getHoverNextItem_().
    - * @param {number} a Number to compare.
    - * @param {number} b Number to compare.
    - * @return {boolean} Whether a is greater than b.
    - * @private
    - */
    -goog.fx.DragListGroup.isGreaterThan_ = function(a, b) {
    -  return a > b;
    -};
    -
    -
    -/**
    - * Inserts the current drag item to the appropriate location in the drag list
    - * that we're hovering over (if the current drag item is not already there).
    - *
    - * @param {Element} hoverList The drag list we're hovering over.
    - * @param {Element} hoverNextItem The next item in the hover drag list.
    - * @private
    - */
    -goog.fx.DragListGroup.prototype.insertCurrDragItem_ = function(
    -    hoverList, hoverNextItem) {
    -  if (this.currDragItem_.parentNode != hoverList ||
    -      goog.dom.getNextElementSibling(this.currDragItem_) != hoverNextItem) {
    -    // The current drag item is not in the correct location, so we move it.
    -    // Note: hoverNextItem may be null, but insertBefore() still works.
    -    hoverList.insertBefore(this.currDragItem_, hoverNextItem);
    -  }
    -};
    -
    -
    -
    -/**
    - * The event object dispatched by DragListGroup.
    - * The fields draggerElCenter, hoverList, and hoverNextItem are only available
    - * for the BEFOREDRAGMOVE and DRAGMOVE events.
    - *
    - * @param {string} type The event type string.
    - * @param {goog.fx.DragListGroup} dragListGroup A reference to the associated
    - *     DragListGroup object.
    - * @param {goog.events.BrowserEvent|goog.fx.DragEvent} event The event fired
    - *     by the browser or fired by the dragger.
    - * @param {Element} currDragItem The current drag item being moved.
    - * @param {Element} draggerEl The clone of the current drag item that's actually
    - *     being dragged around.
    - * @param {goog.fx.Dragger} dragger The dragger object.
    - * @param {goog.math.Coordinate=} opt_draggerElCenter The current center
    - *     position of the draggerEl.
    - * @param {Element=} opt_hoverList The current drag list that's being hovered
    - *     over, or null if the center of draggerEl is outside of any drag lists.
    - *     If not null and the drag action ends right now, then currDragItem will
    - *     end up in this list.
    - * @param {Element=} opt_hoverNextItem The current next item in the hoverList
    - *     that the draggerEl is hovering over. (I.e. If the drag action ends
    - *     right now, then this item would become the next item after the new
    - *     location of currDragItem.) May be null if not applicable or if
    - *     currDragItem would be added to the end of hoverList.
    - * @constructor
    - * @extends {goog.events.Event}
    - */
    -goog.fx.DragListGroupEvent = function(
    -    type, dragListGroup, event, currDragItem, draggerEl, dragger,
    -    opt_draggerElCenter, opt_hoverList, opt_hoverNextItem) {
    -  goog.events.Event.call(this, type);
    -
    -  /**
    -   * A reference to the associated DragListGroup object.
    -   * @type {goog.fx.DragListGroup}
    -   */
    -  this.dragListGroup = dragListGroup;
    -
    -  /**
    -   * The event fired by the browser or fired by the dragger.
    -   * @type {goog.events.BrowserEvent|goog.fx.DragEvent}
    -   */
    -  this.event = event;
    -
    -  /**
    -   * The current drag item being move.
    -   * @type {Element}
    -   */
    -  this.currDragItem = currDragItem;
    -
    -  /**
    -   * The clone of the current drag item that's actually being dragged around.
    -   * @type {Element}
    -   */
    -  this.draggerEl = draggerEl;
    -
    -  /**
    -   * The dragger object.
    -   * @type {goog.fx.Dragger}
    -   */
    -  this.dragger = dragger;
    -
    -  /**
    -   * The current center position of the draggerEl.
    -   * @type {goog.math.Coordinate|undefined}
    -   */
    -  this.draggerElCenter = opt_draggerElCenter;
    -
    -  /**
    -   * The current drag list that's being hovered over, or null if the center of
    -   * draggerEl is outside of any drag lists. (I.e. If not null and the drag
    -   * action ends right now, then currDragItem will end up in this list.)
    -   * @type {Element|undefined}
    -   */
    -  this.hoverList = opt_hoverList;
    -
    -  /**
    -   * The current next item in the hoverList that the draggerEl is hovering over.
    -   * (I.e. If the drag action ends right now, then this item would become the
    -   * next item after the new location of currDragItem.) May be null if not
    -   * applicable or if currDragItem would be added to the end of hoverList.
    -   * @type {Element|undefined}
    -   */
    -  this.hoverNextItem = opt_hoverNextItem;
    -};
    -goog.inherits(goog.fx.DragListGroupEvent, goog.events.Event);
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/draglistgroup_test.html b/src/database/third_party/closure-library/closure/goog/fx/draglistgroup_test.html
    deleted file mode 100644
    index 868ee62e9b8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/draglistgroup_test.html
    +++ /dev/null
    @@ -1,42 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.fx.DragListGroup
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.fx.DragListGroupTest');
    -  </script>
    -  <style>
    -   .opacity-40 {
    -    opacity: 0.4;
    -    -moz-opacity: 0.4;
    -    filter: alpha(opacity=40);
    -  }
    -  .cursor_move {
    -    cursor: move;
    -    -moz-user-select: none;
    -    -webkit-user-select: none;
    -  }
    -  .cursor_pointer {
    -    cursor: pointer;
    -  }
    -  .blue_bg {
    -    background-color: #0000CC;
    -  }
    -  </style>
    - </head>
    - <body>
    -  <div id="sandbox">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/draglistgroup_test.js b/src/database/third_party/closure-library/closure/goog/fx/draglistgroup_test.js
    deleted file mode 100644
    index 8fc0664e350..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/draglistgroup_test.js
    +++ /dev/null
    @@ -1,397 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.fx.DragListGroupTest');
    -goog.setTestOnly('goog.fx.DragListGroupTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events');
    -goog.require('goog.events.BrowserEvent');
    -goog.require('goog.events.BrowserFeature');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventType');
    -goog.require('goog.fx.DragEvent');
    -goog.require('goog.fx.DragListDirection');
    -goog.require('goog.fx.DragListGroup');
    -goog.require('goog.fx.Dragger');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.object');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -
    -
    -/** @type {goog.fx.DragListGroup} */
    -var dlg;
    -
    -
    -/** @type {goog.dom.Element} */
    -var list;
    -
    -
    -/** @type {goog.events.BrowserEvent} */
    -var event;
    -
    -
    -/**
    - * The number of event listeners registered by the DragListGroup after the
    - * init() call.
    - * @type {number}
    - */
    -var initialListenerCount;
    -
    -
    -/**
    - * Type of events fired by the DragListGroup.
    - * @type {!Array<string>}
    - */
    -var firedEventTypes;
    -
    -function setUp() {
    -  var sandbox = goog.dom.getElement('sandbox');
    -  list = goog.dom.createDom('div', {'id': 'horiz_div'});
    -  list.appendChild(
    -      goog.dom.createDom('div', null, goog.dom.createTextNode('1')));
    -  list.appendChild(
    -      goog.dom.createDom('div', null, goog.dom.createTextNode('2')));
    -  list.appendChild(
    -      goog.dom.createDom('div', null, goog.dom.createTextNode('3')));
    -  sandbox.appendChild(list);
    -
    -  dlg = new goog.fx.DragListGroup();
    -  dlg.setDragItemHoverClass('opacity_40', 'cursor_move');
    -  dlg.setDragItemHandleHoverClass('opacity_40', 'cursor_pointer');
    -  dlg.setCurrDragItemClass('blue_bg', 'opacity_40');
    -  dlg.setDraggerElClass('cursor_move', 'blue_bg');
    -  dlg.addDragList(list, goog.fx.DragListDirection.RIGHT);
    -  dlg.init();
    -
    -  initialListenerCount = goog.object.getCount(dlg.eventHandler_.keys_);
    -
    -  event = new goog.events.BrowserEvent();
    -  event.currentTarget = list.getElementsByTagName('div')[0];
    -
    -  firedEventTypes = [];
    -  goog.events.listen(dlg,
    -      goog.object.getValues(goog.fx.DragListGroup.EventType),
    -      function(e) {
    -        firedEventTypes.push(e.type);
    -      });
    -}
    -
    -function tearDown() {
    -  dlg.dispose();
    -  goog.dom.getElement('sandbox').innerHTML = '';
    -}
    -
    -
    -/**
    - * Test the initial assumptions.
    - *
    - * Verify that the setter methods work properly, i.e., the CSS classes are
    - * stored in the private arrays after init() but are not added yet to target.
    - * (Since initially, we are not yet hovering over any list, in particular,
    - * over this target.)
    - */
    -function testSettersAfterInit() {
    -  assertTrue(goog.array.equals(dlg.dragItemHoverClasses_,
    -      ['opacity_40', 'cursor_move']));
    -  assertTrue(goog.array.equals(dlg.dragItemHandleHoverClasses_,
    -      ['opacity_40', 'cursor_pointer']));
    -  assertTrue(goog.array.equals(dlg.currDragItemClasses_,
    -      ['blue_bg', 'opacity_40']));
    -
    -  assertFalse('Should have no cursor_move class after init',
    -      goog.dom.classlist.contains(event.currentTarget, 'cursor_move'));
    -  assertFalse('Should have no cursor_pointer class after init',
    -      goog.dom.classlist.contains(event.currentTarget, 'cursor_pointer'));
    -  assertFalse('Should have no opacity_40 class after init',
    -      goog.dom.classlist.contains(event.currentTarget, 'opacity_40'));
    -  assertFalse('Should not have blue_bg class after init',
    -      goog.dom.classlist.contains(event.currentTarget, 'blue_bg'));
    -}
    -
    -
    -/**
    - * Test the effect of hovering over a list.
    - *
    - * Check that after the MOUSEOVER browser event these classes are added to
    - * the current target of the event.
    - */
    -function testAddDragItemHoverClasses() {
    -  dlg.handleDragItemMouseover_(event);
    -
    -  assertTrue('Should have cursor_move class after MOUSEOVER',
    -      goog.dom.classlist.contains(event.currentTarget, 'cursor_move'));
    -  assertTrue('Should have opacity_40 class after MOUSEOVER',
    -      goog.dom.classlist.contains(event.currentTarget, 'opacity_40'));
    -  assertFalse('Should not have cursor_pointer class after MOUSEOVER',
    -      goog.dom.classlist.contains(event.currentTarget, 'cursor_pointer'));
    -  assertFalse('Should not have blue_bg class after MOUSEOVER',
    -      goog.dom.classlist.contains(event.currentTarget, 'blue_bg'));
    -}
    -
    -function testAddDragItemHandleHoverClasses() {
    -  dlg.handleDragItemHandleMouseover_(event);
    -
    -  assertFalse('Should not have cursor_move class after MOUSEOVER',
    -      goog.dom.classlist.contains(event.currentTarget, 'cursor_move'));
    -  assertTrue('Should have opacity_40 class after MOUSEOVER',
    -      goog.dom.classlist.contains(event.currentTarget, 'opacity_40'));
    -  assertTrue('Should have cursor_pointer class after MOUSEOVER',
    -      goog.dom.classlist.contains(event.currentTarget, 'cursor_pointer'));
    -  assertFalse('Should not have blue_bg class after MOUSEOVER',
    -      goog.dom.classlist.contains(event.currentTarget, 'blue_bg'));
    -}
    -
    -
    -/**
    - * Test the effect of stopping hovering over a list.
    - *
    - * Check that after the MOUSEOUT browser event all CSS classes are removed
    - * from the target (as we are no longer hovering over the it).
    - */
    -function testRemoveDragItemHoverClasses() {
    -  dlg.handleDragItemMouseover_(event);
    -  dlg.handleDragItemMouseout_(event);
    -
    -  assertFalse('Should have no cursor_move class after MOUSEOUT',
    -      goog.dom.classlist.contains(event.currentTarget, 'cursor_move'));
    -  assertFalse('Should have no cursor_pointer class after MOUSEOUT',
    -      goog.dom.classlist.contains(event.currentTarget, 'cursor_pointer'));
    -  assertFalse('Should have no opacity_40 class after MOUSEOUT',
    -      goog.dom.classlist.contains(event.currentTarget, 'opacity_40'));
    -  assertFalse('Should have no blue_bg class after MOUSEOUT',
    -      goog.dom.classlist.contains(event.currentTarget, 'blue_bg'));
    -}
    -
    -function testRemoveDragItemHandleHoverClasses() {
    -  dlg.handleDragItemHandleMouseover_(event);
    -  dlg.handleDragItemHandleMouseout_(event);
    -
    -  assertFalse('Should have no cursor_move class after MOUSEOUT',
    -      goog.dom.classlist.contains(event.currentTarget, 'cursor_move'));
    -  assertFalse('Should have no cursor_pointer class after MOUSEOUT',
    -      goog.dom.classlist.contains(event.currentTarget, 'cursor_pointer'));
    -  assertFalse('Should have no opacity_40 class after MOUSEOUT',
    -      goog.dom.classlist.contains(event.currentTarget, 'opacity_40'));
    -  assertFalse('Should have no blue_bg class after MOUSEOUT',
    -      goog.dom.classlist.contains(event.currentTarget, 'blue_bg'));
    -}
    -
    -
    -/**
    - * Test the effect of dragging an item. (DRAGSTART event.)
    - *
    - * Check that after the MOUSEDOWN browser event is handled by the
    - * handlePotentialDragStart_() method the currDragItem has the CSS classes
    - * set by the setter method.
    - */
    -function testAddCurrentDragItemClasses() {
    -  var be = new goog.events.BrowserEvent({
    -    type: goog.events.EventType.MOUSEDOWN,
    -    button: goog.events.BrowserFeature.HAS_W3C_BUTTON ? 0 : 1
    -  });
    -  event.event_ = be;
    -
    -  dlg.handlePotentialDragStart_(event);
    -
    -  assertFalse('Should have no cursor_move class after MOUSEDOWN',
    -      goog.dom.classlist.contains(dlg.currDragItem_, 'cursor_move'));
    -  assertFalse('Should have no cursor_pointer class after MOUSEDOWN',
    -      goog.dom.classlist.contains(dlg.currDragItem_, 'cursor_pointer'));
    -  assertTrue('Should have opacity_40 class after MOUSEDOWN',
    -      goog.dom.classlist.contains(dlg.currDragItem_, 'opacity_40'));
    -  assertTrue('Should have blue_bg class after MOUSEDOWN',
    -      goog.dom.classlist.contains(dlg.currDragItem_, 'blue_bg'));
    -}
    -
    -
    -/**
    - * Test the effect of dragging an item. (DRAGEND event.)
    - *
    - * Check that after the MOUSEUP browser event handled by the handleDragEnd_()
    - * method the currDragItem has no CSS classes set in the dispatched event.
    - */
    -function testRemoveCurrentDragItemClasses() {
    -  var be = new goog.events.BrowserEvent({
    -    type: goog.events.EventType.MOUSEDOWN,
    -    button: goog.events.BrowserFeature.HAS_W3C_BUTTON ? 0 : 1
    -  });
    -  event.event_ = be;
    -  dlg.handlePotentialDragStart_(event);
    -
    -  // Need to catch the dispatched event because the temporary fields
    -  // including dlg.currentDragItem_ are cleared after the dragging has ended.
    -  var currDragItem = goog.dom.createDom(
    -      'div', ['cursor_move', 'blue_bg'], goog.dom.createTextNode('4'));
    -  goog.events.listen(dlg, goog.fx.DragListGroup.EventType.DRAGEND,
    -      function(e) {currDragItem = dlg.currDragItem_;});
    -
    -  var dragger = new goog.fx.Dragger(event.currentTarget);
    -  be.type = goog.events.EventType.MOUSEUP;
    -  be.clientX = 1;
    -  be.clientY = 2;
    -  var dragEvent = new goog.fx.DragEvent(
    -      goog.fx.Dragger.EventType.END, dragger, be.clientX, be.clientY, be);
    -  dlg.handleDragEnd_(dragEvent); // this method dispatches the DRAGEND event
    -  dragger.dispose();
    -
    -  assertFalse('Should have no cursor_move class after MOUSEUP',
    -      goog.dom.classlist.contains(currDragItem, 'cursor_move'));
    -  assertFalse('Should have no cursor_pointer class after MOUSEUP',
    -      goog.dom.classlist.contains(currDragItem, 'cursor_pointer'));
    -  assertFalse('Should have no opacity_40 class after MOUSEUP',
    -      goog.dom.classlist.contains(currDragItem, 'opacity_40'));
    -  assertFalse('Should have no blue_bg class after MOUSEUP',
    -      goog.dom.classlist.contains(currDragItem, 'blue_bg'));
    -}
    -
    -
    -/**
    - * Asserts that the DragListGroup is in idle state.
    - * @param {!goog.fx.DragListGroup} dlg The DragListGroup to examine.
    - */
    -function assertIdle(dlg) {
    -  assertNull('dragger element has been cleaned up', dlg.draggerEl_);
    -  assertNull('dragger has been cleaned up', dlg.dragger_);
    -  assertEquals('the additional event listeners have been removed',
    -      initialListenerCount, goog.object.getCount(dlg.eventHandler_.keys_));
    -}
    -
    -function testFiredEvents() {
    -  goog.testing.events.fireClickSequence(list.firstChild);
    -  assertArrayEquals('event types in case of zero distance dragging', [
    -    goog.fx.DragListGroup.EventType.BEFOREDRAGSTART,
    -    goog.fx.DragListGroup.EventType.DRAGSTART,
    -    goog.fx.DragListGroup.EventType.BEFOREDRAGEND,
    -    goog.fx.DragListGroup.EventType.DRAGEND
    -  ], firedEventTypes);
    -  assertIdle(dlg);
    -}
    -
    -function testFiredEventsWithHysteresis() {
    -  dlg.setHysteresis(2);
    -
    -  goog.testing.events.fireClickSequence(list.firstChild);
    -  assertArrayEquals('no events fired on click if hysteresis is enabled', [],
    -      firedEventTypes);
    -  assertIdle(dlg);
    -
    -  goog.testing.events.fireMouseDownEvent(list.firstChild, null,
    -      new goog.math.Coordinate(0, 0));
    -  goog.testing.events.fireMouseMoveEvent(list.firstChild,
    -      new goog.math.Coordinate(1, 0));
    -  assertArrayEquals('no events fired below hysteresis distance', [],
    -      firedEventTypes);
    -
    -  goog.testing.events.fireMouseMoveEvent(list.firstChild,
    -      new goog.math.Coordinate(3, 0));
    -  assertArrayEquals('start+move events are fired over hysteresis distance', [
    -    goog.fx.DragListGroup.EventType.BEFOREDRAGSTART,
    -    goog.fx.DragListGroup.EventType.DRAGSTART,
    -    goog.fx.DragListGroup.EventType.BEFOREDRAGMOVE,
    -    goog.fx.DragListGroup.EventType.DRAGMOVE
    -  ], firedEventTypes);
    -
    -  firedEventTypes.length = 0;
    -  goog.testing.events.fireMouseUpEvent(list.firstChild, null,
    -      new goog.math.Coordinate(3, 0));
    -  assertArrayEquals('end events are fired on mouseup', [
    -    goog.fx.DragListGroup.EventType.BEFOREDRAGEND,
    -    goog.fx.DragListGroup.EventType.DRAGEND
    -  ], firedEventTypes);
    -  assertIdle(dlg);
    -}
    -
    -function testPreventDefaultBeforeDragStart() {
    -  goog.events.listen(dlg, goog.fx.DragListGroup.EventType.BEFOREDRAGSTART,
    -      goog.events.Event.preventDefault);
    -
    -  goog.testing.events.fireMouseDownEvent(list.firstChild);
    -  assertArrayEquals('event types if dragging is prevented',
    -      [goog.fx.DragListGroup.EventType.BEFOREDRAGSTART], firedEventTypes);
    -  assertIdle(dlg);
    -}
    -
    -function testPreventDefaultBeforeDragStartWithHysteresis() {
    -  dlg.setHysteresis(5);
    -  goog.events.listen(dlg, goog.fx.DragListGroup.EventType.BEFOREDRAGSTART,
    -      goog.events.Event.preventDefault);
    -
    -  goog.testing.events.fireMouseDownEvent(list.firstChild, null,
    -      new goog.math.Coordinate(0, 0));
    -  goog.testing.events.fireMouseMoveEvent(list.firstChild,
    -      new goog.math.Coordinate(10, 0));
    -  assertArrayEquals('event types if dragging is prevented',
    -      [goog.fx.DragListGroup.EventType.BEFOREDRAGSTART], firedEventTypes);
    -  assertIdle(dlg);
    -}
    -
    -function testRightClick() {
    -  goog.testing.events.fireMouseDownEvent(list.firstChild,
    -      goog.events.BrowserEvent.MouseButton.RIGHT);
    -  goog.testing.events.fireMouseUpEvent(list.firstChild,
    -      goog.events.BrowserEvent.MouseButton.RIGHT);
    -
    -  assertArrayEquals('no events fired', [], firedEventTypes);
    -  assertIdle(dlg);
    -}
    -
    -
    -/**
    - * Tests that a new item can be added to a drag list after the control has
    - * been initialized.
    - */
    -function testAddItemToDragList() {
    -  var item =
    -      goog.dom.createDom('div', null, goog.dom.createTextNode('newItem'));
    -
    -  dlg.addItemToDragList(list, item);
    -
    -  assertEquals(item, list.lastChild);
    -  assertEquals(4, goog.dom.getChildren(list).length);
    -
    -  goog.events.listen(dlg, goog.fx.DragListGroup.EventType.BEFOREDRAGSTART,
    -      goog.events.Event.preventDefault);
    -
    -  goog.testing.events.fireMouseDownEvent(item);
    -  assertTrue('Should fire beforedragstart event when clicked',
    -      goog.array.equals([goog.fx.DragListGroup.EventType.BEFOREDRAGSTART],
    -      firedEventTypes));
    -}
    -
    -
    -/**
    - * Tests that a new item added to a drag list after the control has been
    - * initialized is inserted at the correct position.
    - */
    -function testInsertItemInDragList() {
    -  var item =
    -      goog.dom.createDom('div', null, goog.dom.createTextNode('newItem'));
    -
    -  dlg.addItemToDragList(list, item, 0);
    -
    -  assertEquals(item, list.firstChild);
    -  assertEquals(4, goog.dom.getChildren(list).length);
    -
    -  goog.events.listen(dlg, goog.fx.DragListGroup.EventType.BEFOREDRAGSTART,
    -      goog.events.Event.preventDefault);
    -
    -  goog.testing.events.fireMouseDownEvent(item);
    -  assertTrue('Should fire beforedragstart event when clicked',
    -      goog.array.equals([goog.fx.DragListGroup.EventType.BEFOREDRAGSTART],
    -      firedEventTypes));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/dragscrollsupport.js b/src/database/third_party/closure-library/closure/goog/fx/dragscrollsupport.js
    deleted file mode 100644
    index 66072e8d236..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/dragscrollsupport.js
    +++ /dev/null
    @@ -1,300 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Class to support scrollable containers for drag and drop.
    - *
    - * @author dgajda@google.com (Damian Gajda)
    - */
    -
    -goog.provide('goog.fx.DragScrollSupport');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.Timer');
    -goog.require('goog.dom');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventType');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.style');
    -
    -
    -
    -/**
    - * A scroll support class. Currently this class will automatically scroll
    - * a scrollable container node and scroll it by a fixed amount at a timed
    - * interval when the mouse is moved above or below the container or in vertical
    - * margin areas. Intended for use in drag and drop. This could potentially be
    - * made more general and could support horizontal scrolling.
    - *
    - * @param {Element} containerNode A container that can be scrolled.
    - * @param {number=} opt_margin Optional margin to use while scrolling.
    - * @param {boolean=} opt_externalMouseMoveTracking Whether mouse move events
    - *     are tracked externally by the client object which calls the mouse move
    - *     event handler, useful when events are generated for more than one source
    - *     element and/or are not real mousemove events.
    - * @constructor
    - * @extends {goog.Disposable}
    - * @see ../demos/dragscrollsupport.html
    - */
    -goog.fx.DragScrollSupport = function(containerNode, opt_margin,
    -                                     opt_externalMouseMoveTracking) {
    -  goog.Disposable.call(this);
    -
    -  /**
    -   * The container to be scrolled.
    -   * @type {Element}
    -   * @private
    -   */
    -  this.containerNode_ = containerNode;
    -
    -  /**
    -   * Scroll timer that will scroll the container until it is stopped.
    -   * It will scroll when the mouse is outside the scrolling area of the
    -   * container.
    -   *
    -   * @type {goog.Timer}
    -   * @private
    -   */
    -  this.scrollTimer_ = new goog.Timer(goog.fx.DragScrollSupport.TIMER_STEP_);
    -
    -  /**
    -   * EventHandler used to set up and tear down listeners.
    -   * @type {goog.events.EventHandler<!goog.fx.DragScrollSupport>}
    -   * @private
    -   */
    -  this.eventHandler_ = new goog.events.EventHandler(this);
    -
    -  /**
    -   * The current scroll delta.
    -   * @type {goog.math.Coordinate}
    -   * @private
    -   */
    -  this.scrollDelta_ = new goog.math.Coordinate();
    -
    -  /**
    -   * The container bounds.
    -   * @type {goog.math.Rect}
    -   * @private
    -   */
    -  this.containerBounds_ = goog.style.getBounds(containerNode);
    -
    -  /**
    -   * The margin for triggering a scroll.
    -   * @type {number}
    -   * @private
    -   */
    -  this.margin_ = opt_margin || 0;
    -
    -  /**
    -   * The bounding rectangle which if left triggers scrolling.
    -   * @type {goog.math.Rect}
    -   * @private
    -   */
    -  this.scrollBounds_ = opt_margin ?
    -      this.constrainBounds_(this.containerBounds_.clone()) :
    -      this.containerBounds_;
    -
    -  this.setupListeners_(!!opt_externalMouseMoveTracking);
    -};
    -goog.inherits(goog.fx.DragScrollSupport, goog.Disposable);
    -
    -
    -/**
    - * The scroll timer step in ms.
    - * @type {number}
    - * @private
    - */
    -goog.fx.DragScrollSupport.TIMER_STEP_ = 50;
    -
    -
    -/**
    - * The scroll step in pixels.
    - * @type {number}
    - * @private
    - */
    -goog.fx.DragScrollSupport.SCROLL_STEP_ = 8;
    -
    -
    -/**
    - * The suggested scrolling margin.
    - * @type {number}
    - */
    -goog.fx.DragScrollSupport.MARGIN = 32;
    -
    -
    -/**
    - * Whether scrolling should be constrained to happen only when the cursor is
    - * inside the container node.
    - * @type {boolean}
    - * @private
    - */
    -goog.fx.DragScrollSupport.prototype.constrainScroll_ = false;
    -
    -
    -/**
    - * Whether horizontal scrolling is allowed.
    - * @type {boolean}
    - * @private
    - */
    -goog.fx.DragScrollSupport.prototype.horizontalScrolling_ = true;
    -
    -
    -/**
    - * Sets whether scrolling should be constrained to happen only when the cursor
    - * is inside the container node.
    - * NOTE: If a margin is not set, then it does not make sense to
    - * contain the scroll, because in that case scroll will never be triggered.
    - * @param {boolean} constrain Whether scrolling should be constrained to happen
    - *     only when the cursor is inside the container node.
    - */
    -goog.fx.DragScrollSupport.prototype.setConstrainScroll = function(constrain) {
    -  this.constrainScroll_ = !!this.margin_ && constrain;
    -};
    -
    -
    -/**
    - * Sets whether horizontal scrolling is allowed.
    - * @param {boolean} scrolling Whether horizontal scrolling is allowed.
    - */
    -goog.fx.DragScrollSupport.prototype.setHorizontalScrolling =
    -    function(scrolling) {
    -  this.horizontalScrolling_ = scrolling;
    -};
    -
    -
    -/**
    - * Constrains the container bounds with respect to the margin.
    - *
    - * @param {goog.math.Rect} bounds The container element.
    - * @return {goog.math.Rect} The bounding rectangle used to calculate scrolling
    - *     direction.
    - * @private
    - */
    -goog.fx.DragScrollSupport.prototype.constrainBounds_ = function(bounds) {
    -  var margin = this.margin_;
    -  if (margin) {
    -    var quarterHeight = bounds.height * 0.25;
    -    var yMargin = Math.min(margin, quarterHeight);
    -    bounds.top += yMargin;
    -    bounds.height -= 2 * yMargin;
    -
    -    var quarterWidth = bounds.width * 0.25;
    -    var xMargin = Math.min(margin, quarterWidth);
    -    bounds.top += xMargin;
    -    bounds.height -= 2 * xMargin;
    -  }
    -  return bounds;
    -};
    -
    -
    -/**
    - * Attaches listeners and activates automatic scrolling.
    - * @param {boolean} externalMouseMoveTracking Whether to enable internal
    - *     mouse move event handling.
    - * @private
    - */
    -goog.fx.DragScrollSupport.prototype.setupListeners_ = function(
    -    externalMouseMoveTracking) {
    -  if (!externalMouseMoveTracking) {
    -    // Track mouse pointer position to determine scroll direction.
    -    this.eventHandler_.listen(goog.dom.getOwnerDocument(this.containerNode_),
    -        goog.events.EventType.MOUSEMOVE, this.onMouseMove);
    -  }
    -
    -  // Scroll with a constant speed.
    -  this.eventHandler_.listen(this.scrollTimer_, goog.Timer.TICK, this.onTick_);
    -};
    -
    -
    -/**
    - * Handler for timer tick event, scrolls the container by one scroll step if
    - * needed.
    - * @param {goog.events.Event} event Timer tick event.
    - * @private
    - */
    -goog.fx.DragScrollSupport.prototype.onTick_ = function(event) {
    -  this.containerNode_.scrollTop += this.scrollDelta_.y;
    -  this.containerNode_.scrollLeft += this.scrollDelta_.x;
    -};
    -
    -
    -/**
    - * Handler for mouse moves events.
    - * @param {goog.events.Event} event Mouse move event.
    - */
    -goog.fx.DragScrollSupport.prototype.onMouseMove = function(event) {
    -  var deltaX = this.horizontalScrolling_ ? this.calculateScrollDelta(
    -      event.clientX, this.scrollBounds_.left, this.scrollBounds_.width) : 0;
    -  var deltaY = this.calculateScrollDelta(event.clientY,
    -      this.scrollBounds_.top, this.scrollBounds_.height);
    -  this.scrollDelta_.x = deltaX;
    -  this.scrollDelta_.y = deltaY;
    -
    -  // If the scroll data is 0 or the event fired outside of the
    -  // bounds of the container node.
    -  if ((!deltaX && !deltaY) ||
    -      (this.constrainScroll_ &&
    -       !this.isInContainerBounds_(event.clientX, event.clientY))) {
    -    this.scrollTimer_.stop();
    -  } else if (!this.scrollTimer_.enabled) {
    -    this.scrollTimer_.start();
    -  }
    -};
    -
    -
    -/**
    - * Gets whether the input coordinate is in the container bounds.
    - * @param {number} x The x coordinate.
    - * @param {number} y The y coordinate.
    - * @return {boolean} Whether the input coordinate is in the container bounds.
    - * @private
    - */
    -goog.fx.DragScrollSupport.prototype.isInContainerBounds_ = function(x, y) {
    -  var containerBounds = this.containerBounds_;
    -  return containerBounds.left <= x &&
    -         containerBounds.left + containerBounds.width >= x &&
    -         containerBounds.top <= y &&
    -         containerBounds.top + containerBounds.height >= y;
    -};
    -
    -
    -/**
    - * Calculates scroll delta.
    - *
    - * @param {number} coordinate Current mouse pointer coordinate.
    - * @param {number} min The coordinate value below which scrolling up should be
    - *     started.
    - * @param {number} rangeLength The length of the range in which scrolling should
    - *     be disabled and above which scrolling down should be started.
    - * @return {number} The calculated scroll delta.
    - * @protected
    - */
    -goog.fx.DragScrollSupport.prototype.calculateScrollDelta = function(
    -    coordinate, min, rangeLength) {
    -  var delta = 0;
    -  if (coordinate < min) {
    -    delta = -goog.fx.DragScrollSupport.SCROLL_STEP_;
    -  } else if (coordinate > min + rangeLength) {
    -    delta = goog.fx.DragScrollSupport.SCROLL_STEP_;
    -  }
    -  return delta;
    -};
    -
    -
    -/** @override */
    -goog.fx.DragScrollSupport.prototype.disposeInternal = function() {
    -  goog.fx.DragScrollSupport.superClass_.disposeInternal.call(this);
    -  this.eventHandler_.dispose();
    -  this.scrollTimer_.dispose();
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/dragscrollsupport_test.html b/src/database/third_party/closure-library/closure/goog/fx/dragscrollsupport_test.html
    deleted file mode 100644
    index 5ef4c37d4b9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/dragscrollsupport_test.html
    +++ /dev/null
    @@ -1,63 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -  Author: dgajda@google.com (Damian Gajda)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.fx.DragScrollSupport
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.fx.DragScrollSupportTest');
    -  </script>
    -  <style>
    -   #vContainerDiv {
    -  position: absolute;
    -  top: 20px;
    -  overflow-y: scroll;
    -  width: 100px;
    -  height: 100px;
    -  visibility: hidden;
    -}
    -
    -#vContentDiv {
    -  height: 200px;
    -}
    -
    -#hContainerDiv {
    -  position: absolute;
    -  top: 20px;
    -  left: 200px;
    -  overflow-x: scroll;
    -  width: 100px;
    -  height: 100px;
    -  visibility: hidden;
    -}
    -
    -#hContentDiv {
    -  width: 200px;
    -}
    -  </style>
    - </head>
    - <body>
    -  <div id="vContainerDiv">
    -   <div id="vContentDiv">
    -    Sample text
    -   </div>
    -  </div>
    -  <div id="hContainerDiv">
    -   <div id="hContentDiv">
    -    Sample text
    -   </div>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/dragscrollsupport_test.js b/src/database/third_party/closure-library/closure/goog/fx/dragscrollsupport_test.js
    deleted file mode 100644
    index 94338fa55af..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/dragscrollsupport_test.js
    +++ /dev/null
    @@ -1,315 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.fx.DragScrollSupportTest');
    -goog.setTestOnly('goog.fx.DragScrollSupportTest');
    -
    -goog.require('goog.fx.DragScrollSupport');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -
    -var vContainerDiv;
    -var vContentDiv;
    -var hContainerDiv;
    -var hContentDiv;
    -var clock;
    -
    -function setUpPage() {
    -  vContainerDiv = document.getElementById('vContainerDiv');
    -  vContentDiv = document.getElementById('vContentDiv');
    -  hContainerDiv = document.getElementById('hContainerDiv');
    -  hContentDiv = document.getElementById('hContentDiv');
    -}
    -
    -function setUp() {
    -  clock = new goog.testing.MockClock(true);
    -}
    -
    -
    -function tearDown() {
    -  clock.dispose();
    -}
    -
    -
    -function testDragZeroMarginDivVContainer() {
    -  var dsc = new goog.fx.DragScrollSupport(vContainerDiv);
    -
    -  // Set initial scroll state.
    -  var scrollTop = 50;
    -  vContainerDiv.scrollTop = scrollTop;
    -
    -  goog.testing.events.fireMouseMoveEvent(vContainerDiv,
    -      new goog.math.Coordinate(50, 20 + 50));
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertEquals('Mousing inside the vContainer should not trigger scrolling.',
    -      scrollTop, vContainerDiv.scrollTop);
    -  assertEquals('Scroll timer should not tick yet', 0, clock.getTimeoutsMade());
    -
    -  scrollTop = vContainerDiv.scrollTop;
    -  goog.testing.events.fireMouseMoveEvent(vContainerDiv,
    -      new goog.math.Coordinate(50, 10));
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertTrue('Mousing above the vContainer should trigger scrolling up.',
    -      scrollTop > vContainerDiv.scrollTop);
    -  scrollTop = vContainerDiv.scrollTop;
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertTrue('Mousing above the vContainer should trigger scrolling up.',
    -      scrollTop > vContainerDiv.scrollTop);
    -
    -  scrollTop = vContainerDiv.scrollTop;
    -  goog.testing.events.fireMouseMoveEvent(vContainerDiv,
    -      new goog.math.Coordinate(50, 20 + 110));
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertTrue('Mousing below the vContainer should trigger scrolling down.',
    -      scrollTop < vContainerDiv.scrollTop);
    -  scrollTop = vContainerDiv.scrollTop;
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertTrue('Mousing below the vContainer should trigger scrolling down.',
    -      scrollTop < vContainerDiv.scrollTop);
    -
    -  scrollTop = vContainerDiv.scrollTop;
    -  goog.testing.events.fireMouseMoveEvent(vContainerDiv,
    -      new goog.math.Coordinate(50, 20 + 50));
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertEquals('Mousing inside the vContainer should stop scrolling.',
    -      scrollTop, vContainerDiv.scrollTop);
    -
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -
    -  dsc.dispose();
    -}
    -
    -function testDragZeroMarginDivHContainer() {
    -  var dsc = new goog.fx.DragScrollSupport(hContainerDiv);
    -
    -  // Set initial scroll state.
    -  var scrollLeft = 50;
    -  hContainerDiv.scrollLeft = scrollLeft;
    -
    -  goog.testing.events.fireMouseMoveEvent(hContainerDiv,
    -      new goog.math.Coordinate(200 + 50, 20 + 50));
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertEquals('Mousing inside the hContainer should not trigger scrolling.',
    -      scrollLeft, hContainerDiv.scrollLeft);
    -  assertEquals('Scroll timer should not tick yet', 0, clock.getTimeoutsMade());
    -
    -  scrollLeft = hContainerDiv.scrollLeft;
    -  goog.testing.events.fireMouseMoveEvent(hContainerDiv,
    -      new goog.math.Coordinate(200 - 10, 20 + 50));
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertTrue('Mousing left of the hContainer should trigger scrolling left.',
    -      scrollLeft > hContainerDiv.scrollLeft);
    -  scrollLeft = hContainerDiv.scrollLeft;
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertTrue('Mousing left of the hContainer should trigger scrolling left.',
    -      scrollLeft > hContainerDiv.scrollLeft);
    -
    -  scrollLeft = hContainerDiv.scrollLeft;
    -  goog.testing.events.fireMouseMoveEvent(hContainerDiv,
    -      new goog.math.Coordinate(200 + 110, 20 + 50));
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertTrue('Mousing right of the hContainer should trigger scrolling right.',
    -      scrollLeft < hContainerDiv.scrollLeft);
    -  scrollLeft = hContainerDiv.scrollLeft;
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertTrue('Mousing right of the hContainer should trigger scrolling right.',
    -      scrollLeft < hContainerDiv.scrollLeft);
    -
    -  scrollLeft = hContainerDiv.scrollLeft;
    -  goog.testing.events.fireMouseMoveEvent(hContainerDiv,
    -      new goog.math.Coordinate(200 + 50, 20 + 50));
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertEquals('Mousing inside the hContainer should stop scrolling.',
    -      scrollLeft, hContainerDiv.scrollLeft);
    -
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -
    -  dsc.dispose();
    -}
    -
    -
    -function testDragMarginDivVContainer() {
    -  var dsc = new goog.fx.DragScrollSupport(vContainerDiv, 20);
    -
    -  // Set initial scroll state.
    -  var scrollTop = 50;
    -  vContainerDiv.scrollTop = scrollTop;
    -
    -  goog.testing.events.fireMouseMoveEvent(vContainerDiv,
    -      new goog.math.Coordinate(50, 20 + 50));
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertEquals('Mousing inside the vContainer should not trigger scrolling.',
    -      scrollTop, vContainerDiv.scrollTop);
    -  assertEquals('Scroll timer should not tick yet', 0, clock.getTimeoutsMade());
    -
    -  scrollTop = vContainerDiv.scrollTop;
    -  goog.testing.events.fireMouseMoveEvent(vContainerDiv,
    -      new goog.math.Coordinate(50, 30));
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertTrue('Mousing above the margin should trigger scrolling up.',
    -      scrollTop > vContainerDiv.scrollTop);
    -  scrollTop = vContainerDiv.scrollTop;
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertTrue('Mousing above the margin should trigger scrolling up.',
    -      scrollTop > vContainerDiv.scrollTop);
    -
    -  scrollTop = vContainerDiv.scrollTop;
    -  goog.testing.events.fireMouseMoveEvent(vContainerDiv,
    -      new goog.math.Coordinate(50, 20 + 90));
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertTrue('Mousing below the margin should trigger scrolling down.',
    -      scrollTop < vContainerDiv.scrollTop);
    -  scrollTop = vContainerDiv.scrollTop;
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertTrue('Mousing above the margin should trigger scrolling down.',
    -      scrollTop < vContainerDiv.scrollTop);
    -
    -  scrollTop = vContainerDiv.scrollTop;
    -  goog.testing.events.fireMouseMoveEvent(vContainerDiv,
    -      new goog.math.Coordinate(50, 20 + 50));
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertEquals('Mousing inside the margin should stop scrolling.',
    -      scrollTop, vContainerDiv.scrollTop);
    -
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -
    -  assertEquals('Scroll timer should have ticked 5 times',
    -      5, clock.getTimeoutsMade());
    -
    -  dsc.dispose();
    -}
    -
    -
    -function testDragMarginScrollConstrainedDivVContainer() {
    -  var dsc = new goog.fx.DragScrollSupport(vContainerDiv, 20);
    -  dsc.setConstrainScroll(true);
    -
    -  // Set initial scroll state.
    -  var scrollTop = 50;
    -  vContainerDiv.scrollTop = scrollTop;
    -
    -  goog.testing.events.fireMouseMoveEvent(vContainerDiv,
    -      new goog.math.Coordinate(50, 20 + 50));
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertEquals('Mousing inside the vContainer should not trigger scrolling.',
    -      scrollTop, vContainerDiv.scrollTop);
    -  assertEquals('Scroll timer should not tick yet', 0, clock.getTimeoutsMade());
    -
    -  scrollTop = vContainerDiv.scrollTop;
    -  goog.testing.events.fireMouseMoveEvent(vContainerDiv,
    -      new goog.math.Coordinate(50, 30));
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertTrue('Mousing above the margin should trigger scrolling up.',
    -      scrollTop > vContainerDiv.scrollTop);
    -  scrollTop = vContainerDiv.scrollTop;
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertTrue('Mousing above the margin should trigger scrolling up.',
    -      scrollTop > vContainerDiv.scrollTop);
    -
    -  scrollTop = vContainerDiv.scrollTop;
    -  goog.testing.events.fireMouseMoveEvent(vContainerDiv,
    -      new goog.math.Coordinate(50, 20 + 90));
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertTrue('Mousing below the margin should trigger scrolling down.',
    -      scrollTop < vContainerDiv.scrollTop);
    -  scrollTop = vContainerDiv.scrollTop;
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertTrue('Mousing above the margin should trigger scrolling down.',
    -      scrollTop < vContainerDiv.scrollTop);
    -
    -  scrollTop = vContainerDiv.scrollTop;
    -  goog.testing.events.fireMouseMoveEvent(vContainerDiv,
    -      new goog.math.Coordinate(50, 20 + 50));
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertEquals('Mousing inside the margin should stop scrolling.',
    -      scrollTop, vContainerDiv.scrollTop);
    -
    -  scrollTop = vContainerDiv.scrollTop;
    -  goog.testing.events.fireMouseMoveEvent(vContainerDiv,
    -      new goog.math.Coordinate(50, 10));
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertEquals('Mousing above the vContainer should not trigger scrolling up.',
    -      scrollTop, vContainerDiv.scrollTop);
    -  scrollTop = vContainerDiv.scrollTop;
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertEquals('Mousing above the vContainer should not trigger scrolling up.',
    -      scrollTop, vContainerDiv.scrollTop);
    -
    -  scrollTop = vContainerDiv.scrollTop;
    -  goog.testing.events.fireMouseMoveEvent(vContainerDiv,
    -      new goog.math.Coordinate(50, 20 + 110));
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertEquals(
    -      'Mousing below the vContainer should not trigger scrolling down.',
    -      scrollTop, vContainerDiv.scrollTop);
    -  scrollTop = vContainerDiv.scrollTop;
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertEquals(
    -      'Mousing below the vContainer should not trigger scrolling down.',
    -      scrollTop, vContainerDiv.scrollTop);
    -
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -
    -  scrollTop = vContainerDiv.scrollTop;
    -  goog.testing.events.fireMouseMoveEvent(vContainerDiv,
    -      new goog.math.Coordinate(150, 20 + 90));
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertEquals('Mousing to the right of the vContainer should not trigger ' +
    -      'scrolling up.', scrollTop, vContainerDiv.scrollTop);
    -  scrollTop = vContainerDiv.scrollTop;
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertEquals('Mousing to the right of the vContainer should not trigger ' +
    -      'scrolling up.', scrollTop, vContainerDiv.scrollTop);
    -
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -
    -  assertEquals('Scroll timer should have ticked 5 times',
    -      5, clock.getTimeoutsMade());
    -
    -  dsc.dispose();
    -}
    -
    -
    -function testSetHorizontalScrolling() {
    -  var dsc = new goog.fx.DragScrollSupport(hContainerDiv);
    -  dsc.setHorizontalScrolling(false);
    -
    -  // Set initial scroll state.
    -  var scrollLeft = 50;
    -  hContainerDiv.scrollLeft = scrollLeft;
    -
    -  goog.testing.events.fireMouseMoveEvent(hContainerDiv,
    -      new goog.math.Coordinate(200 - 10, 20 + 50));
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertEquals('Horizontal scrolling should be turned off',
    -      0, clock.getTimeoutsMade());
    -
    -  goog.testing.events.fireMouseMoveEvent(hContainerDiv,
    -      new goog.math.Coordinate(200 + 110, 20 + 50));
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertEquals('Horizontal scrolling should be turned off',
    -      0, clock.getTimeoutsMade());
    -
    -  dsc.setHorizontalScrolling(true);
    -  scrollLeft = hContainerDiv.scrollLeft;
    -  goog.testing.events.fireMouseMoveEvent(hContainerDiv,
    -      new goog.math.Coordinate(200 - 10, 20 + 50));
    -  clock.tick(goog.fx.DragScrollSupport.TIMER_STEP_ + 1);
    -  assertTrue('Mousing left of the hContainer should trigger scrolling left.',
    -      scrollLeft > hContainerDiv.scrollLeft);
    -
    -  dsc.dispose();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/easing.js b/src/database/third_party/closure-library/closure/goog/fx/easing.js
    deleted file mode 100644
    index fda5122c8b8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/easing.js
    +++ /dev/null
    @@ -1,85 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Easing functions for animations.
    - *
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -goog.provide('goog.fx.easing');
    -
    -
    -/**
    - * Ease in - Start slow and speed up.
    - * @param {number} t Input between 0 and 1.
    - * @return {number} Output between 0 and 1.
    - */
    -goog.fx.easing.easeIn = function(t) {
    -  return goog.fx.easing.easeInInternal_(t, 3);
    -};
    -
    -
    -/**
    - * Ease in with specifiable exponent.
    - * @param {number} t Input between 0 and 1.
    - * @param {number} exp Ease exponent.
    - * @return {number} Output between 0 and 1.
    - * @private
    - */
    -goog.fx.easing.easeInInternal_ = function(t, exp) {
    -  return Math.pow(t, exp);
    -};
    -
    -
    -/**
    - * Ease out - Start fastest and slows to a stop.
    - * @param {number} t Input between 0 and 1.
    - * @return {number} Output between 0 and 1.
    - */
    -goog.fx.easing.easeOut = function(t) {
    -  return goog.fx.easing.easeOutInternal_(t, 3);
    -};
    -
    -
    -/**
    - * Ease out with specifiable exponent.
    - * @param {number} t Input between 0 and 1.
    - * @param {number} exp Ease exponent.
    - * @return {number} Output between 0 and 1.
    - * @private
    - */
    -goog.fx.easing.easeOutInternal_ = function(t, exp) {
    -  return 1 - goog.fx.easing.easeInInternal_(1 - t, exp);
    -};
    -
    -
    -/**
    - * Ease out long - Start fastest and slows to a stop with a long ease.
    - * @param {number} t Input between 0 and 1.
    - * @return {number} Output between 0 and 1.
    - */
    -goog.fx.easing.easeOutLong = function(t) {
    -  return goog.fx.easing.easeOutInternal_(t, 4);
    -};
    -
    -
    -/**
    - * Ease in and out - Start slow, speed up, then slow down.
    - * @param {number} t Input between 0 and 1.
    - * @return {number} Output between 0 and 1.
    - */
    -goog.fx.easing.inAndOut = function(t) {
    -  return 3 * t * t - 2 * t * t * t;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/easing_test.js b/src/database/third_party/closure-library/closure/goog/fx/easing_test.js
    deleted file mode 100644
    index db0ae35dbb3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/easing_test.js
    +++ /dev/null
    @@ -1,33 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -goog.provide('goog.fx.easingTest');
    -goog.setTestOnly('goog.fx.easingTest');
    -
    -goog.require('goog.fx.easing');
    -goog.require('goog.testing.jsunit');
    -
    -
    -function testEaseIn() {
    -  assertEquals(0, goog.fx.easing.easeIn(0));
    -  assertEquals(1, goog.fx.easing.easeIn(1));
    -  assertRoughlyEquals(Math.pow(0.5, 3), goog.fx.easing.easeIn(0.5), 0.01);
    -}
    -
    -function testEaseOut() {
    -  assertEquals(0, goog.fx.easing.easeOut(0));
    -  assertEquals(1, goog.fx.easing.easeOut(1));
    -  assertRoughlyEquals(1 - Math.pow(0.5, 3), goog.fx.easing.easeOut(0.5), 0.01);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/fx.js b/src/database/third_party/closure-library/closure/goog/fx/fx.js
    deleted file mode 100644
    index f654354377c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/fx.js
    +++ /dev/null
    @@ -1,32 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Legacy stub for the goog.fx namespace.  Requires the moved
    - * namespaces. Animation and easing have been moved to animation.js and
    - * easing.js.  Users of this stub should move off so we may remove it in the
    - * future.
    - *
    - * @author nnaze@google.com (Nathan Naze)
    - */
    -
    -goog.provide('goog.fx');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.fx.Animation');
    -goog.require('goog.fx.Animation.EventType');
    -goog.require('goog.fx.Animation.State');
    -goog.require('goog.fx.AnimationEvent');
    -goog.require('goog.fx.Transition.EventType');
    -goog.require('goog.fx.easing');
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/fx_test.html b/src/database/third_party/closure-library/closure/goog/fx/fx_test.html
    deleted file mode 100644
    index 6974cd3e6a3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/fx_test.html
    +++ /dev/null
    @@ -1,27 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -  Author: arv@google.com (Erik Arvidsson)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.fx
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.fxTest');
    -  </script>
    -  <style>
    -  </style>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/fx_test.js b/src/database/third_party/closure-library/closure/goog/fx/fx_test.js
    deleted file mode 100644
    index 70e1ea1ee7b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/fx_test.js
    +++ /dev/null
    @@ -1,86 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.fxTest');
    -goog.setTestOnly('goog.fxTest');
    -
    -goog.require('goog.fx.Animation');
    -goog.require('goog.object');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -// TODO(arv): Add tests for the event dispatches.
    -// TODO(arv): Add tests for the calculation of the coordinates.
    -
    -var clock, replacer, anim, anim2;
    -var Animation = goog.fx.Animation;
    -
    -function setUpPage() {
    -  clock = new goog.testing.MockClock(true);
    -}
    -
    -function tearDownPage() {
    -  clock.dispose();
    -}
    -
    -function setUp() {
    -  replacer = new goog.testing.PropertyReplacer();
    -}
    -
    -function tearDown() {
    -  replacer.reset();
    -
    -  if (anim && anim.dispose) {
    -    anim.dispose();
    -  }
    -
    -  if (anim2 && anim2.dispose) {
    -    anim2.dispose();
    -  }
    -}
    -
    -function testAnimationConstructor() {
    -  assertThrows('Should throw since first arg is not an array', function() {
    -    new Animation(1, [2], 3);
    -  });
    -  assertThrows('Should throw since second arg is not an array', function() {
    -    new Animation([1], 2, 3);
    -  });
    -  assertThrows('Should throw since the length are different', function() {
    -    new Animation([0, 1], [2], 3);
    -  });
    -}
    -
    -function testPlayAndStopDoesNotLeaveAnyActiveAnimations() {
    -  anim = new Animation([0], [1], 1000);
    -
    -  assertTrue('There should be no active animations',
    -             goog.object.isEmpty(goog.fx.anim.activeAnimations_));
    -
    -  anim.play();
    -  assertEquals('There should be one active animations',
    -               1, goog.object.getCount(goog.fx.anim.activeAnimations_));
    -
    -  anim.stop();
    -  assertTrue('There should be no active animations',
    -             goog.object.isEmpty(goog.fx.anim.activeAnimations_));
    -
    -  anim.play();
    -  assertEquals('There should be one active animations',
    -               1, goog.object.getCount(goog.fx.anim.activeAnimations_));
    -
    -  anim.pause();
    -  assertTrue('There should be no active animations',
    -             goog.object.isEmpty(goog.fx.anim.activeAnimations_));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/transition.js b/src/database/third_party/closure-library/closure/goog/fx/transition.js
    deleted file mode 100644
    index 57c4304d09b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/transition.js
    +++ /dev/null
    @@ -1,76 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview An interface for transition animation. This is a simple
    - * interface that allows for playing and stopping a transition. It adds
    - * a simple event model with BEGIN and END event.
    - *
    - * @author chrishenry@google.com (Chris Henry)
    - */
    -
    -goog.provide('goog.fx.Transition');
    -goog.provide('goog.fx.Transition.EventType');
    -
    -
    -
    -/**
    - * An interface for programmatic transition. Must extend
    - * {@code goog.events.EventTarget}.
    - * @interface
    - */
    -goog.fx.Transition = function() {};
    -
    -
    -/**
    - * Transition event types.
    - * @enum {string}
    - */
    -goog.fx.Transition.EventType = {
    -  /** Dispatched when played for the first time OR when it is resumed. */
    -  PLAY: 'play',
    -
    -  /** Dispatched only when the animation starts from the beginning. */
    -  BEGIN: 'begin',
    -
    -  /** Dispatched only when animation is restarted after a pause. */
    -  RESUME: 'resume',
    -
    -  /**
    -   * Dispatched when animation comes to the end of its duration OR stop
    -   * is called.
    -   */
    -  END: 'end',
    -
    -  /** Dispatched only when stop is called. */
    -  STOP: 'stop',
    -
    -  /** Dispatched only when animation comes to its end naturally. */
    -  FINISH: 'finish',
    -
    -  /** Dispatched when an animation is paused. */
    -  PAUSE: 'pause'
    -};
    -
    -
    -/**
    - * Plays the transition.
    - */
    -goog.fx.Transition.prototype.play;
    -
    -
    -/**
    - * Stops the transition.
    - */
    -goog.fx.Transition.prototype.stop;
    diff --git a/src/database/third_party/closure-library/closure/goog/fx/transitionbase.js b/src/database/third_party/closure-library/closure/goog/fx/transitionbase.js
    deleted file mode 100644
    index 0a2c184e6e4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/fx/transitionbase.js
    +++ /dev/null
    @@ -1,236 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview An abstract base class for transitions. This is a simple
    - * interface that allows for playing, pausing and stopping an animation. It adds
    - * a simple event model, and animation status.
    - */
    -goog.provide('goog.fx.TransitionBase');
    -goog.provide('goog.fx.TransitionBase.State');
    -
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.fx.Transition');  // Unreferenced: interface
    -
    -
    -
    -/**
    - * Constructor for a transition object.
    - *
    - * @constructor
    - * @implements {goog.fx.Transition}
    - * @extends {goog.events.EventTarget}
    - */
    -goog.fx.TransitionBase = function() {
    -  goog.fx.TransitionBase.base(this, 'constructor');
    -
    -  /**
    -   * The internal state of the animation.
    -   * @type {goog.fx.TransitionBase.State}
    -   * @private
    -   */
    -  this.state_ = goog.fx.TransitionBase.State.STOPPED;
    -
    -  /**
    -   * Timestamp for when the animation was started.
    -   * @type {?number}
    -   * @protected
    -   */
    -  this.startTime = null;
    -
    -  /**
    -   * Timestamp for when the animation finished or was stopped.
    -   * @type {?number}
    -   * @protected
    -   */
    -  this.endTime = null;
    -};
    -goog.inherits(goog.fx.TransitionBase, goog.events.EventTarget);
    -
    -
    -/**
    - * Enum for the possible states of an animation.
    - * @enum {number}
    - */
    -goog.fx.TransitionBase.State = {
    -  STOPPED: 0,
    -  PAUSED: -1,
    -  PLAYING: 1
    -};
    -
    -
    -/**
    - * Plays the animation.
    - *
    - * @param {boolean=} opt_restart Optional parameter to restart the animation.
    - * @return {boolean} True iff the animation was started.
    - * @override
    - */
    -goog.fx.TransitionBase.prototype.play = goog.abstractMethod;
    -
    -
    -/**
    - * Stops the animation.
    - *
    - * @param {boolean=} opt_gotoEnd Optional boolean parameter to go the the end of
    - *     the animation.
    - * @override
    - */
    -goog.fx.TransitionBase.prototype.stop = goog.abstractMethod;
    -
    -
    -/**
    - * Pauses the animation.
    - */
    -goog.fx.TransitionBase.prototype.pause = goog.abstractMethod;
    -
    -
    -/**
    - * Returns the current state of the animation.
    - * @return {goog.fx.TransitionBase.State} State of the animation.
    - */
    -goog.fx.TransitionBase.prototype.getStateInternal = function() {
    -  return this.state_;
    -};
    -
    -
    -/**
    - * Sets the current state of the animation to playing.
    - * @protected
    - */
    -goog.fx.TransitionBase.prototype.setStatePlaying = function() {
    -  this.state_ = goog.fx.TransitionBase.State.PLAYING;
    -};
    -
    -
    -/**
    - * Sets the current state of the animation to paused.
    - * @protected
    - */
    -goog.fx.TransitionBase.prototype.setStatePaused = function() {
    -  this.state_ = goog.fx.TransitionBase.State.PAUSED;
    -};
    -
    -
    -/**
    - * Sets the current state of the animation to stopped.
    - * @protected
    - */
    -goog.fx.TransitionBase.prototype.setStateStopped = function() {
    -  this.state_ = goog.fx.TransitionBase.State.STOPPED;
    -};
    -
    -
    -/**
    - * @return {boolean} True iff the current state of the animation is playing.
    - */
    -goog.fx.TransitionBase.prototype.isPlaying = function() {
    -  return this.state_ == goog.fx.TransitionBase.State.PLAYING;
    -};
    -
    -
    -/**
    - * @return {boolean} True iff the current state of the animation is paused.
    - */
    -goog.fx.TransitionBase.prototype.isPaused = function() {
    -  return this.state_ == goog.fx.TransitionBase.State.PAUSED;
    -};
    -
    -
    -/**
    - * @return {boolean} True iff the current state of the animation is stopped.
    - */
    -goog.fx.TransitionBase.prototype.isStopped = function() {
    -  return this.state_ == goog.fx.TransitionBase.State.STOPPED;
    -};
    -
    -
    -/**
    - * Dispatches the BEGIN event. Sub classes should override this instead
    - * of listening to the event, and call this instead of dispatching the event.
    - * @protected
    - */
    -goog.fx.TransitionBase.prototype.onBegin = function() {
    -  this.dispatchAnimationEvent(goog.fx.Transition.EventType.BEGIN);
    -};
    -
    -
    -/**
    - * Dispatches the END event. Sub classes should override this instead
    - * of listening to the event, and call this instead of dispatching the event.
    - * @protected
    - */
    -goog.fx.TransitionBase.prototype.onEnd = function() {
    -  this.dispatchAnimationEvent(goog.fx.Transition.EventType.END);
    -};
    -
    -
    -/**
    - * Dispatches the FINISH event. Sub classes should override this instead
    - * of listening to the event, and call this instead of dispatching the event.
    - * @protected
    - */
    -goog.fx.TransitionBase.prototype.onFinish = function() {
    -  this.dispatchAnimationEvent(goog.fx.Transition.EventType.FINISH);
    -};
    -
    -
    -/**
    - * Dispatches the PAUSE event. Sub classes should override this instead
    - * of listening to the event, and call this instead of dispatching the event.
    - * @protected
    - */
    -goog.fx.TransitionBase.prototype.onPause = function() {
    -  this.dispatchAnimationEvent(goog.fx.Transition.EventType.PAUSE);
    -};
    -
    -
    -/**
    - * Dispatches the PLAY event. Sub classes should override this instead
    - * of listening to the event, and call this instead of dispatching the event.
    - * @protected
    - */
    -goog.fx.TransitionBase.prototype.onPlay = function() {
    -  this.dispatchAnimationEvent(goog.fx.Transition.EventType.PLAY);
    -};
    -
    -
    -/**
    - * Dispatches the RESUME event. Sub classes should override this instead
    - * of listening to the event, and call this instead of dispatching the event.
    - * @protected
    - */
    -goog.fx.TransitionBase.prototype.onResume = function() {
    -  this.dispatchAnimationEvent(goog.fx.Transition.EventType.RESUME);
    -};
    -
    -
    -/**
    - * Dispatches the STOP event. Sub classes should override this instead
    - * of listening to the event, and call this instead of dispatching the event.
    - * @protected
    - */
    -goog.fx.TransitionBase.prototype.onStop = function() {
    -  this.dispatchAnimationEvent(goog.fx.Transition.EventType.STOP);
    -};
    -
    -
    -/**
    - * Dispatches an event object for the current animation.
    - * @param {string} type Event type that will be dispatched.
    - * @protected
    - */
    -goog.fx.TransitionBase.prototype.dispatchAnimationEvent = function(type) {
    -  this.dispatchEvent(type);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/abstractgraphics.js b/src/database/third_party/closure-library/closure/goog/graphics/abstractgraphics.js
    deleted file mode 100644
    index 0ae1776839f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/abstractgraphics.js
    +++ /dev/null
    @@ -1,454 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Graphics utility functions and factory methods.
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -
    -goog.provide('goog.graphics.AbstractGraphics');
    -
    -goog.require('goog.dom');
    -goog.require('goog.graphics.Path');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.math.Size');
    -goog.require('goog.style');
    -goog.require('goog.ui.Component');
    -
    -
    -
    -/**
    - * Base class for the different graphics. You should never construct objects
    - * of this class. Instead us goog.graphics.createGraphics
    - * @param {number|string} width The width in pixels or percent.
    - * @param {number|string} height The height in pixels or percent.
    - * @param {?number=} opt_coordWidth Optional coordinate system width - if
    - *     omitted or null, defaults to same as width.
    - * @param {?number=} opt_coordHeight Optional coordinate system height - if
    - *     omitted or null, defaults to same as height.
    - * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper object for the
    - *     document we want to render in.
    - * @constructor
    - * @extends {goog.ui.Component}
    - */
    -goog.graphics.AbstractGraphics = function(width, height,
    -                                          opt_coordWidth, opt_coordHeight,
    -                                          opt_domHelper) {
    -  goog.ui.Component.call(this, opt_domHelper);
    -
    -  /**
    -   * Width of graphics in pixels or percentage points.
    -   * @type {number|string}
    -   * @protected
    -   */
    -  this.width = width;
    -
    -  /**
    -   * Height of graphics in pixels or precentage points.
    -   * @type {number|string}
    -   * @protected
    -   */
    -  this.height = height;
    -
    -  /**
    -   * Width of coordinate system in units.
    -   * @type {?number}
    -   * @protected
    -   */
    -  this.coordWidth = opt_coordWidth || null;
    -
    -  /**
    -   * Height of coordinate system in units.
    -   * @type {?number}
    -   * @protected
    -   */
    -  this.coordHeight = opt_coordHeight || null;
    -};
    -goog.inherits(goog.graphics.AbstractGraphics, goog.ui.Component);
    -
    -
    -/**
    - * The root level group element.
    - * @type {goog.graphics.GroupElement?}
    - * @protected
    - */
    -goog.graphics.AbstractGraphics.prototype.canvasElement = null;
    -
    -
    -/**
    - * Left coordinate of the view box
    - * @type {number}
    - * @protected
    - */
    -goog.graphics.AbstractGraphics.prototype.coordLeft = 0;
    -
    -
    -/**
    - * Top coordinate of the view box
    - * @type {number}
    - * @protected
    - */
    -goog.graphics.AbstractGraphics.prototype.coordTop = 0;
    -
    -
    -/**
    - * @return {goog.graphics.GroupElement} The root level canvas element.
    - */
    -goog.graphics.AbstractGraphics.prototype.getCanvasElement = function() {
    -  return this.canvasElement;
    -};
    -
    -
    -/**
    - * Changes the coordinate size.
    - * @param {number} coordWidth  The coordinate width.
    - * @param {number} coordHeight  The coordinate height.
    - */
    -goog.graphics.AbstractGraphics.prototype.setCoordSize = function(coordWidth,
    -                                                                 coordHeight) {
    -  this.coordWidth = coordWidth;
    -  this.coordHeight = coordHeight;
    -};
    -
    -
    -/**
    - * @return {goog.math.Size} The coordinate size.
    - */
    -goog.graphics.AbstractGraphics.prototype.getCoordSize = function() {
    -  if (this.coordWidth) {
    -    return new goog.math.Size(this.coordWidth,
    -        /** @type {number} */ (this.coordHeight));
    -  } else {
    -    return this.getPixelSize();
    -  }
    -};
    -
    -
    -/**
    - * Changes the coordinate system position.
    - * @param {number} left  The coordinate system left bound.
    - * @param {number} top  The coordinate system top bound.
    - */
    -goog.graphics.AbstractGraphics.prototype.setCoordOrigin = goog.abstractMethod;
    -
    -
    -/**
    - * @return {!goog.math.Coordinate} The coordinate system position.
    - */
    -goog.graphics.AbstractGraphics.prototype.getCoordOrigin = function() {
    -  return new goog.math.Coordinate(this.coordLeft, this.coordTop);
    -};
    -
    -
    -/**
    - * Change the size of the canvas.
    - * @param {number} pixelWidth  The width in pixels.
    - * @param {number} pixelHeight  The height in pixels.
    - */
    -goog.graphics.AbstractGraphics.prototype.setSize = goog.abstractMethod;
    -
    -
    -/**
    - * @return {goog.math.Size} The size of canvas.
    - * @deprecated Use getPixelSize.
    - */
    -goog.graphics.AbstractGraphics.prototype.getSize = function() {
    -  return this.getPixelSize();
    -};
    -
    -
    -/**
    - * @return {goog.math.Size?} Returns the number of pixels spanned by the
    - *     surface, or null if the size could not be computed due to the size being
    - *     specified in percentage points and the component not being in the
    - *     document.
    - */
    -goog.graphics.AbstractGraphics.prototype.getPixelSize = function() {
    -  if (this.isInDocument()) {
    -    return goog.style.getSize(this.getElement());
    -  }
    -  if (goog.isNumber(this.width) && goog.isNumber(this.height)) {
    -    return new goog.math.Size(this.width, this.height);
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * @return {number} Returns the number of pixels per unit in the x direction.
    - */
    -goog.graphics.AbstractGraphics.prototype.getPixelScaleX = function() {
    -  var pixelSize = this.getPixelSize();
    -  return pixelSize ? pixelSize.width / this.getCoordSize().width : 0;
    -};
    -
    -
    -/**
    - * @return {number} Returns the number of pixels per unit in the y direction.
    - */
    -goog.graphics.AbstractGraphics.prototype.getPixelScaleY = function() {
    -  var pixelSize = this.getPixelSize();
    -  return pixelSize ? pixelSize.height / this.getCoordSize().height : 0;
    -};
    -
    -
    -/**
    - * Remove all drawing elements from the graphics.
    - */
    -goog.graphics.AbstractGraphics.prototype.clear = goog.abstractMethod;
    -
    -
    -/**
    - * Remove a single drawing element from the surface.  The default implementation
    - * assumes a DOM based drawing surface.
    - * @param {goog.graphics.Element} element The element to remove.
    - */
    -goog.graphics.AbstractGraphics.prototype.removeElement = function(element) {
    -  goog.dom.removeNode(element.getElement());
    -};
    -
    -
    -/**
    - * Sets the fill for the given element.
    - * @param {goog.graphics.StrokeAndFillElement} element The element wrapper.
    - * @param {goog.graphics.Fill?} fill The fill object.
    - */
    -goog.graphics.AbstractGraphics.prototype.setElementFill = goog.abstractMethod;
    -
    -
    -/**
    - * Sets the stroke for the given element.
    - * @param {goog.graphics.StrokeAndFillElement} element The element wrapper.
    - * @param {goog.graphics.Stroke?} stroke The stroke object.
    - */
    -goog.graphics.AbstractGraphics.prototype.setElementStroke = goog.abstractMethod;
    -
    -
    -/**
    - * Set the transformation of an element.
    - *
    - * If a more general affine transform is needed than this provides
    - * (e.g. skew and scale) then use setElementAffineTransform.
    - * @param {goog.graphics.Element} element The element wrapper.
    - * @param {number} x The x coordinate of the translation transform.
    - * @param {number} y The y coordinate of the translation transform.
    - * @param {number} angle The angle of the rotation transform.
    - * @param {number} centerX The horizontal center of the rotation transform.
    - * @param {number} centerY The vertical center of the rotation transform.
    - */
    -goog.graphics.AbstractGraphics.prototype.setElementTransform =
    -    goog.abstractMethod;
    -
    -
    -/**
    - * Set the affine transform of an element.
    - * @param {!goog.graphics.Element} element The element wrapper.
    - * @param {!goog.graphics.AffineTransform} affineTransform The
    - *     transformation applied to this element.
    - */
    -goog.graphics.AbstractGraphics.prototype.setElementAffineTransform =
    -    goog.abstractMethod;
    -
    -
    -/**
    - * Draw a circle
    - *
    - * @param {number} cx Center X coordinate.
    - * @param {number} cy Center Y coordinate.
    - * @param {number} r Radius length.
    - * @param {goog.graphics.Stroke?} stroke Stroke object describing the
    - *    stroke.
    - * @param {goog.graphics.Fill?} fill Fill object describing the fill.
    - * @param {goog.graphics.GroupElement=} opt_group The group wrapper element to
    - *     append to. If not specified, appends to the main canvas.
    - *
    - * @return {goog.graphics.EllipseElement} The newly created element.
    - */
    -goog.graphics.AbstractGraphics.prototype.drawCircle = function(
    -    cx, cy, r, stroke, fill, opt_group) {
    -  return this.drawEllipse(cx, cy, r, r, stroke, fill, opt_group);
    -};
    -
    -
    -/**
    - * Draw an ellipse
    - *
    - * @param {number} cx Center X coordinate.
    - * @param {number} cy Center Y coordinate.
    - * @param {number} rx Radius length for the x-axis.
    - * @param {number} ry Radius length for the y-axis.
    - * @param {goog.graphics.Stroke?} stroke Stroke object describing the
    - *    stroke.
    - * @param {goog.graphics.Fill?} fill Fill object describing the fill.
    - * @param {goog.graphics.GroupElement=} opt_group The group wrapper element to
    - *     append to. If not specified, appends to the main canvas.
    - *
    - * @return {goog.graphics.EllipseElement} The newly created element.
    - */
    -goog.graphics.AbstractGraphics.prototype.drawEllipse = goog.abstractMethod;
    -
    -
    -/**
    - * Draw a rectangle
    - *
    - * @param {number} x X coordinate (left).
    - * @param {number} y Y coordinate (top).
    - * @param {number} width Width of rectangle.
    - * @param {number} height Height of rectangle.
    - * @param {goog.graphics.Stroke?} stroke Stroke object describing the
    - *    stroke.
    - * @param {goog.graphics.Fill?} fill Fill object describing the fill.
    - * @param {goog.graphics.GroupElement=} opt_group The group wrapper element to
    - *     append to. If not specified, appends to the main canvas.
    - *
    - * @return {goog.graphics.RectElement} The newly created element.
    - */
    -goog.graphics.AbstractGraphics.prototype.drawRect = goog.abstractMethod;
    -
    -
    -/**
    - * Draw a text string within a rectangle (drawing is horizontal)
    - *
    - * @param {string} text The text to draw.
    - * @param {number} x X coordinate (left).
    - * @param {number} y Y coordinate (top).
    - * @param {number} width Width of rectangle.
    - * @param {number} height Height of rectangle.
    - * @param {string} align Horizontal alignment: left (default), center, right.
    - * @param {string} vAlign Vertical alignment: top (default), center, bottom.
    - * @param {goog.graphics.Font} font Font describing the font properties.
    - * @param {goog.graphics.Stroke?} stroke Stroke object describing the
    - *    stroke.
    - * @param {goog.graphics.Fill?} fill  Fill object describing the fill.
    - * @param {goog.graphics.GroupElement=} opt_group The group wrapper element to
    - *     append to. If not specified, appends to the main canvas.
    - *
    - * @return {goog.graphics.TextElement} The newly created element.
    - */
    -goog.graphics.AbstractGraphics.prototype.drawText = function(
    -    text, x, y, width, height, align, vAlign, font, stroke, fill, opt_group) {
    -  var baseline = font.size / 2; // Baseline is middle of line
    -  var textY;
    -  if (vAlign == 'bottom') {
    -    textY = y + height - baseline;
    -  } else if (vAlign == 'center') {
    -    textY = y + height / 2;
    -  } else {
    -    textY = y + baseline;
    -  }
    -
    -  return this.drawTextOnLine(text, x, textY, x + width, textY, align,
    -      font, stroke, fill, opt_group);
    -};
    -
    -
    -/**
    - * Draw a text string vertically centered on a given line.
    - *
    - * @param {string} text  The text to draw.
    - * @param {number} x1 X coordinate of start of line.
    - * @param {number} y1 Y coordinate of start of line.
    - * @param {number} x2 X coordinate of end of line.
    - * @param {number} y2 Y coordinate of end of line.
    - * @param {string} align Horizontal alingnment: left (default), center, right.
    - * @param {goog.graphics.Font} font Font describing the font properties.
    - * @param {goog.graphics.Stroke?} stroke Stroke object describing the
    - *    stroke.
    - * @param {goog.graphics.Fill?} fill Fill object describing the fill.
    - * @param {goog.graphics.GroupElement=} opt_group The group wrapper element to
    - *     append to. If not specified, appends to the main canvas.
    - *
    - * @return {goog.graphics.TextElement} The newly created element.
    - */
    -goog.graphics.AbstractGraphics.prototype.drawTextOnLine = goog.abstractMethod;
    -
    -
    -/**
    - * Draw a path.
    - *
    - * @param {!goog.graphics.Path} path The path object to draw.
    - * @param {goog.graphics.Stroke?} stroke Stroke object describing the
    - *    stroke.
    - * @param {goog.graphics.Fill?} fill Fill object describing the fill.
    - * @param {goog.graphics.GroupElement=} opt_group The group wrapper element to
    - *     append to. If not specified, appends to the main canvas.
    - *
    - * @return {goog.graphics.PathElement} The newly created element.
    - */
    -goog.graphics.AbstractGraphics.prototype.drawPath = goog.abstractMethod;
    -
    -
    -/**
    - * Create an empty group of drawing elements.
    - *
    - * @param {goog.graphics.GroupElement=} opt_group The group wrapper element to
    - *     append to. If not specified, appends to the main canvas.
    - *
    - * @return {goog.graphics.GroupElement} The newly created group.
    - */
    -goog.graphics.AbstractGraphics.prototype.createGroup = goog.abstractMethod;
    -
    -
    -/**
    - * Create an empty path.
    - *
    - * @return {!goog.graphics.Path} The path.
    - * @deprecated Use {@code new goog.graphics.Path()}.
    - */
    -goog.graphics.AbstractGraphics.prototype.createPath = function() {
    -  return new goog.graphics.Path();
    -};
    -
    -
    -/**
    - * Measure and return the width (in pixels) of a given text string.
    - * Text measurement is needed to make sure a text can fit in the allocated
    - * area. The way text length is measured is by writing it into a div that is
    - * after the visible area, measure the div width, and immediatly erase the
    - * written value.
    - *
    - * @param {string} text The text string to measure.
    - * @param {goog.graphics.Font} font The font object describing the font style.
    - *
    - * @return {number} The width in pixels of the text strings.
    - */
    -goog.graphics.AbstractGraphics.prototype.getTextWidth = goog.abstractMethod;
    -
    -
    -/**
    - * @return {boolean} Whether the underlying element can be cloned resulting in
    - *     an accurate reproduction of the graphics contents.
    - */
    -goog.graphics.AbstractGraphics.prototype.isDomClonable = function() {
    -  return false;
    -};
    -
    -
    -/**
    - * Start preventing redraws - useful for chaining large numbers of changes
    - * together.  Not guaranteed to do anything - i.e. only use this for
    - * optimization of a single code path.
    - */
    -goog.graphics.AbstractGraphics.prototype.suspend = function() {
    -};
    -
    -
    -/**
    - * Stop preventing redraws.  If any redraws had been prevented, a redraw will
    - * be done now.
    - */
    -goog.graphics.AbstractGraphics.prototype.resume = function() {
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/affinetransform.js b/src/database/third_party/closure-library/closure/goog/graphics/affinetransform.js
    deleted file mode 100644
    index ec328f28923..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/affinetransform.js
    +++ /dev/null
    @@ -1,588 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Provides an object representation of an AffineTransform and
    - * methods for working with it.
    - */
    -
    -
    -goog.provide('goog.graphics.AffineTransform');
    -
    -goog.require('goog.math');
    -
    -
    -
    -/**
    - * Creates a 2D affine transform. An affine transform performs a linear
    - * mapping from 2D coordinates to other 2D coordinates that preserves the
    - * "straightness" and "parallelness" of lines.
    - *
    - * Such a coordinate transformation can be represented by a 3 row by 3 column
    - * matrix with an implied last row of [ 0 0 1 ]. This matrix transforms source
    - * coordinates (x,y) into destination coordinates (x',y') by considering them
    - * to be a column vector and multiplying the coordinate vector by the matrix
    - * according to the following process:
    - * <pre>
    - *      [ x']   [  m00  m01  m02  ] [ x ]   [ m00x + m01y + m02 ]
    - *      [ y'] = [  m10  m11  m12  ] [ y ] = [ m10x + m11y + m12 ]
    - *      [ 1 ]   [   0    0    1   ] [ 1 ]   [         1         ]
    - * </pre>
    - *
    - * This class is optimized for speed and minimizes calculations based on its
    - * knowledge of the underlying matrix (as opposed to say simply performing
    - * matrix multiplication).
    - *
    - * @param {number=} opt_m00 The m00 coordinate of the transform.
    - * @param {number=} opt_m10 The m10 coordinate of the transform.
    - * @param {number=} opt_m01 The m01 coordinate of the transform.
    - * @param {number=} opt_m11 The m11 coordinate of the transform.
    - * @param {number=} opt_m02 The m02 coordinate of the transform.
    - * @param {number=} opt_m12 The m12 coordinate of the transform.
    - * @constructor
    - * @final
    - */
    -goog.graphics.AffineTransform = function(opt_m00, opt_m10, opt_m01,
    -    opt_m11, opt_m02, opt_m12) {
    -  if (arguments.length == 6) {
    -    this.setTransform(/** @type {number} */ (opt_m00),
    -                      /** @type {number} */ (opt_m10),
    -                      /** @type {number} */ (opt_m01),
    -                      /** @type {number} */ (opt_m11),
    -                      /** @type {number} */ (opt_m02),
    -                      /** @type {number} */ (opt_m12));
    -  } else if (arguments.length != 0) {
    -    throw Error('Insufficient matrix parameters');
    -  } else {
    -    this.m00_ = this.m11_ = 1;
    -    this.m10_ = this.m01_ = this.m02_ = this.m12_ = 0;
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} Whether this transform is the identity transform.
    - */
    -goog.graphics.AffineTransform.prototype.isIdentity = function() {
    -  return this.m00_ == 1 && this.m10_ == 0 && this.m01_ == 0 &&
    -      this.m11_ == 1 && this.m02_ == 0 && this.m12_ == 0;
    -};
    -
    -
    -/**
    - * @return {!goog.graphics.AffineTransform} A copy of this transform.
    - */
    -goog.graphics.AffineTransform.prototype.clone = function() {
    -  return new goog.graphics.AffineTransform(this.m00_, this.m10_, this.m01_,
    -      this.m11_, this.m02_, this.m12_);
    -};
    -
    -
    -/**
    - * Sets this transform to the matrix specified by the 6 values.
    - *
    - * @param {number} m00 The m00 coordinate of the transform.
    - * @param {number} m10 The m10 coordinate of the transform.
    - * @param {number} m01 The m01 coordinate of the transform.
    - * @param {number} m11 The m11 coordinate of the transform.
    - * @param {number} m02 The m02 coordinate of the transform.
    - * @param {number} m12 The m12 coordinate of the transform.
    - * @return {!goog.graphics.AffineTransform} This affine transform.
    - */
    -goog.graphics.AffineTransform.prototype.setTransform = function(m00, m10, m01,
    -    m11, m02, m12) {
    -  if (!goog.isNumber(m00) || !goog.isNumber(m10) || !goog.isNumber(m01) ||
    -      !goog.isNumber(m11) || !goog.isNumber(m02) || !goog.isNumber(m12)) {
    -    throw Error('Invalid transform parameters');
    -  }
    -  this.m00_ = m00;
    -  this.m10_ = m10;
    -  this.m01_ = m01;
    -  this.m11_ = m11;
    -  this.m02_ = m02;
    -  this.m12_ = m12;
    -  return this;
    -};
    -
    -
    -/**
    - * Sets this transform to be identical to the given transform.
    - *
    - * @param {!goog.graphics.AffineTransform} tx The transform to copy.
    - * @return {!goog.graphics.AffineTransform} This affine transform.
    - */
    -goog.graphics.AffineTransform.prototype.copyFrom = function(tx) {
    -  this.m00_ = tx.m00_;
    -  this.m10_ = tx.m10_;
    -  this.m01_ = tx.m01_;
    -  this.m11_ = tx.m11_;
    -  this.m02_ = tx.m02_;
    -  this.m12_ = tx.m12_;
    -  return this;
    -};
    -
    -
    -/**
    - * Concatenates this transform with a scaling transformation.
    - *
    - * @param {number} sx The x-axis scaling factor.
    - * @param {number} sy The y-axis scaling factor.
    - * @return {!goog.graphics.AffineTransform} This affine transform.
    - */
    -goog.graphics.AffineTransform.prototype.scale = function(sx, sy) {
    -  this.m00_ *= sx;
    -  this.m10_ *= sx;
    -  this.m01_ *= sy;
    -  this.m11_ *= sy;
    -  return this;
    -};
    -
    -
    -/**
    - * Pre-concatenates this transform with a scaling transformation,
    - * i.e. calculates the following matrix product:
    - *
    - * <pre>
    - * [sx  0 0] [m00 m01 m02]
    - * [ 0 sy 0] [m10 m11 m12]
    - * [ 0  0 1] [  0   0   1]
    - * </pre>
    - *
    - * @param {number} sx The x-axis scaling factor.
    - * @param {number} sy The y-axis scaling factor.
    - * @return {!goog.graphics.AffineTransform} This affine transform.
    - */
    -goog.graphics.AffineTransform.prototype.preScale = function(sx, sy) {
    -  this.m00_ *= sx;
    -  this.m01_ *= sx;
    -  this.m02_ *= sx;
    -  this.m10_ *= sy;
    -  this.m11_ *= sy;
    -  this.m12_ *= sy;
    -  return this;
    -};
    -
    -
    -/**
    - * Concatenates this transform with a translate transformation.
    - *
    - * @param {number} dx The distance to translate in the x direction.
    - * @param {number} dy The distance to translate in the y direction.
    - * @return {!goog.graphics.AffineTransform} This affine transform.
    - */
    -goog.graphics.AffineTransform.prototype.translate = function(dx, dy) {
    -  this.m02_ += dx * this.m00_ + dy * this.m01_;
    -  this.m12_ += dx * this.m10_ + dy * this.m11_;
    -  return this;
    -};
    -
    -
    -/**
    - * Pre-concatenates this transform with a translate transformation,
    - * i.e. calculates the following matrix product:
    - *
    - * <pre>
    - * [1 0 dx] [m00 m01 m02]
    - * [0 1 dy] [m10 m11 m12]
    - * [0 0  1] [  0   0   1]
    - * </pre>
    - *
    - * @param {number} dx The distance to translate in the x direction.
    - * @param {number} dy The distance to translate in the y direction.
    - * @return {!goog.graphics.AffineTransform} This affine transform.
    - */
    -goog.graphics.AffineTransform.prototype.preTranslate = function(dx, dy) {
    -  this.m02_ += dx;
    -  this.m12_ += dy;
    -  return this;
    -};
    -
    -
    -/**
    - * Concatenates this transform with a rotation transformation around an anchor
    - * point.
    - *
    - * @param {number} theta The angle of rotation measured in radians.
    - * @param {number} x The x coordinate of the anchor point.
    - * @param {number} y The y coordinate of the anchor point.
    - * @return {!goog.graphics.AffineTransform} This affine transform.
    - */
    -goog.graphics.AffineTransform.prototype.rotate = function(theta, x, y) {
    -  return this.concatenate(
    -      goog.graphics.AffineTransform.getRotateInstance(theta, x, y));
    -};
    -
    -
    -/**
    - * Pre-concatenates this transform with a rotation transformation around an
    - * anchor point.
    - *
    - * @param {number} theta The angle of rotation measured in radians.
    - * @param {number} x The x coordinate of the anchor point.
    - * @param {number} y The y coordinate of the anchor point.
    - * @return {!goog.graphics.AffineTransform} This affine transform.
    - */
    -goog.graphics.AffineTransform.prototype.preRotate = function(theta, x, y) {
    -  return this.preConcatenate(
    -      goog.graphics.AffineTransform.getRotateInstance(theta, x, y));
    -};
    -
    -
    -/**
    - * Concatenates this transform with a shear transformation.
    - *
    - * @param {number} shx The x shear factor.
    - * @param {number} shy The y shear factor.
    - * @return {!goog.graphics.AffineTransform} This affine transform.
    - */
    -goog.graphics.AffineTransform.prototype.shear = function(shx, shy) {
    -  var m00 = this.m00_;
    -  var m10 = this.m10_;
    -  this.m00_ += shy * this.m01_;
    -  this.m10_ += shy * this.m11_;
    -  this.m01_ += shx * m00;
    -  this.m11_ += shx * m10;
    -  return this;
    -};
    -
    -
    -/**
    - * Pre-concatenates this transform with a shear transformation.
    - * i.e. calculates the following matrix product:
    - *
    - * <pre>
    - * [  1 shx 0] [m00 m01 m02]
    - * [shy   1 0] [m10 m11 m12]
    - * [  0   0 1] [  0   0   1]
    - * </pre>
    - *
    - * @param {number} shx The x shear factor.
    - * @param {number} shy The y shear factor.
    - * @return {!goog.graphics.AffineTransform} This affine transform.
    - */
    -goog.graphics.AffineTransform.prototype.preShear = function(shx, shy) {
    -  var m00 = this.m00_;
    -  var m01 = this.m01_;
    -  var m02 = this.m02_;
    -  this.m00_ += shx * this.m10_;
    -  this.m01_ += shx * this.m11_;
    -  this.m02_ += shx * this.m12_;
    -  this.m10_ += shy * m00;
    -  this.m11_ += shy * m01;
    -  this.m12_ += shy * m02;
    -  return this;
    -};
    -
    -
    -/**
    - * @return {string} A string representation of this transform. The format of
    - *     of the string is compatible with SVG matrix notation, i.e.
    - *     "matrix(a,b,c,d,e,f)".
    - * @override
    - */
    -goog.graphics.AffineTransform.prototype.toString = function() {
    -  return 'matrix(' +
    -      [this.m00_, this.m10_, this.m01_, this.m11_, this.m02_, this.m12_].join(
    -          ',') +
    -      ')';
    -};
    -
    -
    -/**
    - * @return {number} The scaling factor in the x-direction (m00).
    - */
    -goog.graphics.AffineTransform.prototype.getScaleX = function() {
    -  return this.m00_;
    -};
    -
    -
    -/**
    - * @return {number} The scaling factor in the y-direction (m11).
    - */
    -goog.graphics.AffineTransform.prototype.getScaleY = function() {
    -  return this.m11_;
    -};
    -
    -
    -/**
    - * @return {number} The translation in the x-direction (m02).
    - */
    -goog.graphics.AffineTransform.prototype.getTranslateX = function() {
    -  return this.m02_;
    -};
    -
    -
    -/**
    - * @return {number} The translation in the y-direction (m12).
    - */
    -goog.graphics.AffineTransform.prototype.getTranslateY = function() {
    -  return this.m12_;
    -};
    -
    -
    -/**
    - * @return {number} The shear factor in the x-direction (m01).
    - */
    -goog.graphics.AffineTransform.prototype.getShearX = function() {
    -  return this.m01_;
    -};
    -
    -
    -/**
    - * @return {number} The shear factor in the y-direction (m10).
    - */
    -goog.graphics.AffineTransform.prototype.getShearY = function() {
    -  return this.m10_;
    -};
    -
    -
    -/**
    - * Concatenates an affine transform to this transform.
    - *
    - * @param {!goog.graphics.AffineTransform} tx The transform to concatenate.
    - * @return {!goog.graphics.AffineTransform} This affine transform.
    - */
    -goog.graphics.AffineTransform.prototype.concatenate = function(tx) {
    -  var m0 = this.m00_;
    -  var m1 = this.m01_;
    -  this.m00_ = tx.m00_ * m0 + tx.m10_ * m1;
    -  this.m01_ = tx.m01_ * m0 + tx.m11_ * m1;
    -  this.m02_ += tx.m02_ * m0 + tx.m12_ * m1;
    -
    -  m0 = this.m10_;
    -  m1 = this.m11_;
    -  this.m10_ = tx.m00_ * m0 + tx.m10_ * m1;
    -  this.m11_ = tx.m01_ * m0 + tx.m11_ * m1;
    -  this.m12_ += tx.m02_ * m0 + tx.m12_ * m1;
    -  return this;
    -};
    -
    -
    -/**
    - * Pre-concatenates an affine transform to this transform.
    - *
    - * @param {!goog.graphics.AffineTransform} tx The transform to preconcatenate.
    - * @return {!goog.graphics.AffineTransform} This affine transform.
    - */
    -goog.graphics.AffineTransform.prototype.preConcatenate = function(tx) {
    -  var m0 = this.m00_;
    -  var m1 = this.m10_;
    -  this.m00_ = tx.m00_ * m0 + tx.m01_ * m1;
    -  this.m10_ = tx.m10_ * m0 + tx.m11_ * m1;
    -
    -  m0 = this.m01_;
    -  m1 = this.m11_;
    -  this.m01_ = tx.m00_ * m0 + tx.m01_ * m1;
    -  this.m11_ = tx.m10_ * m0 + tx.m11_ * m1;
    -
    -  m0 = this.m02_;
    -  m1 = this.m12_;
    -  this.m02_ = tx.m00_ * m0 + tx.m01_ * m1 + tx.m02_;
    -  this.m12_ = tx.m10_ * m0 + tx.m11_ * m1 + tx.m12_;
    -  return this;
    -};
    -
    -
    -/**
    - * Transforms an array of coordinates by this transform and stores the result
    - * into a destination array.
    - *
    - * @param {!Array<number>} src The array containing the source points
    - *     as x, y value pairs.
    - * @param {number} srcOff The offset to the first point to be transformed.
    - * @param {!Array<number>} dst The array into which to store the transformed
    - *     point pairs.
    - * @param {number} dstOff The offset of the location of the first transformed
    - *     point in the destination array.
    - * @param {number} numPts The number of points to tranform.
    - */
    -goog.graphics.AffineTransform.prototype.transform = function(src, srcOff, dst,
    -    dstOff, numPts) {
    -  var i = srcOff;
    -  var j = dstOff;
    -  var srcEnd = srcOff + 2 * numPts;
    -  while (i < srcEnd) {
    -    var x = src[i++];
    -    var y = src[i++];
    -    dst[j++] = x * this.m00_ + y * this.m01_ + this.m02_;
    -    dst[j++] = x * this.m10_ + y * this.m11_ + this.m12_;
    -  }
    -};
    -
    -
    -/**
    - * @return {number} The determinant of this transform.
    - */
    -goog.graphics.AffineTransform.prototype.getDeterminant = function() {
    -  return this.m00_ * this.m11_ - this.m01_ * this.m10_;
    -};
    -
    -
    -/**
    - * Returns whether the transform is invertible. A transform is not invertible
    - * if the determinant is 0 or any value is non-finite or NaN.
    - *
    - * @return {boolean} Whether the transform is invertible.
    - */
    -goog.graphics.AffineTransform.prototype.isInvertible = function() {
    -  var det = this.getDeterminant();
    -  return goog.math.isFiniteNumber(det) &&
    -      goog.math.isFiniteNumber(this.m02_) &&
    -      goog.math.isFiniteNumber(this.m12_) &&
    -      det != 0;
    -};
    -
    -
    -/**
    - * @return {!goog.graphics.AffineTransform} An AffineTransform object
    - *     representing the inverse transformation.
    - */
    -goog.graphics.AffineTransform.prototype.createInverse = function() {
    -  var det = this.getDeterminant();
    -  return new goog.graphics.AffineTransform(
    -      this.m11_ / det,
    -      -this.m10_ / det,
    -      -this.m01_ / det,
    -      this.m00_ / det,
    -      (this.m01_ * this.m12_ - this.m11_ * this.m02_) / det,
    -      (this.m10_ * this.m02_ - this.m00_ * this.m12_) / det);
    -};
    -
    -
    -/**
    - * Creates a transform representing a scaling transformation.
    - *
    - * @param {number} sx The x-axis scaling factor.
    - * @param {number} sy The y-axis scaling factor.
    - * @return {!goog.graphics.AffineTransform} A transform representing a scaling
    - *     transformation.
    - */
    -goog.graphics.AffineTransform.getScaleInstance = function(sx, sy) {
    -  return new goog.graphics.AffineTransform().setToScale(sx, sy);
    -};
    -
    -
    -/**
    - * Creates a transform representing a translation transformation.
    - *
    - * @param {number} dx The distance to translate in the x direction.
    - * @param {number} dy The distance to translate in the y direction.
    - * @return {!goog.graphics.AffineTransform} A transform representing a
    - *     translation transformation.
    - */
    -goog.graphics.AffineTransform.getTranslateInstance = function(dx, dy) {
    -  return new goog.graphics.AffineTransform().setToTranslation(dx, dy);
    -};
    -
    -
    -/**
    - * Creates a transform representing a shearing transformation.
    - *
    - * @param {number} shx The x-axis shear factor.
    - * @param {number} shy The y-axis shear factor.
    - * @return {!goog.graphics.AffineTransform} A transform representing a shearing
    - *     transformation.
    - */
    -goog.graphics.AffineTransform.getShearInstance = function(shx, shy) {
    -  return new goog.graphics.AffineTransform().setToShear(shx, shy);
    -};
    -
    -
    -/**
    - * Creates a transform representing a rotation transformation.
    - *
    - * @param {number} theta The angle of rotation measured in radians.
    - * @param {number} x The x coordinate of the anchor point.
    - * @param {number} y The y coordinate of the anchor point.
    - * @return {!goog.graphics.AffineTransform} A transform representing a rotation
    - *     transformation.
    - */
    -goog.graphics.AffineTransform.getRotateInstance = function(theta, x, y) {
    -  return new goog.graphics.AffineTransform().setToRotation(theta, x, y);
    -};
    -
    -
    -/**
    - * Sets this transform to a scaling transformation.
    - *
    - * @param {number} sx The x-axis scaling factor.
    - * @param {number} sy The y-axis scaling factor.
    - * @return {!goog.graphics.AffineTransform} This affine transform.
    - */
    -goog.graphics.AffineTransform.prototype.setToScale = function(sx, sy) {
    -  return this.setTransform(sx, 0, 0, sy, 0, 0);
    -};
    -
    -
    -/**
    - * Sets this transform to a translation transformation.
    - *
    - * @param {number} dx The distance to translate in the x direction.
    - * @param {number} dy The distance to translate in the y direction.
    - * @return {!goog.graphics.AffineTransform} This affine transform.
    - */
    -goog.graphics.AffineTransform.prototype.setToTranslation = function(dx, dy) {
    -  return this.setTransform(1, 0, 0, 1, dx, dy);
    -};
    -
    -
    -/**
    - * Sets this transform to a shearing transformation.
    - *
    - * @param {number} shx The x-axis shear factor.
    - * @param {number} shy The y-axis shear factor.
    - * @return {!goog.graphics.AffineTransform} This affine transform.
    - */
    -goog.graphics.AffineTransform.prototype.setToShear = function(shx, shy) {
    -  return this.setTransform(1, shy, shx, 1, 0, 0);
    -};
    -
    -
    -/**
    - * Sets this transform to a rotation transformation.
    - *
    - * @param {number} theta The angle of rotation measured in radians.
    - * @param {number} x The x coordinate of the anchor point.
    - * @param {number} y The y coordinate of the anchor point.
    - * @return {!goog.graphics.AffineTransform} This affine transform.
    - */
    -goog.graphics.AffineTransform.prototype.setToRotation = function(theta, x, y) {
    -  var cos = Math.cos(theta);
    -  var sin = Math.sin(theta);
    -  return this.setTransform(cos, sin, -sin, cos,
    -      x - x * cos + y * sin, y - x * sin - y * cos);
    -};
    -
    -
    -/**
    - * Compares two affine transforms for equality.
    - *
    - * @param {goog.graphics.AffineTransform} tx The other affine transform.
    - * @return {boolean} whether the two transforms are equal.
    - */
    -goog.graphics.AffineTransform.prototype.equals = function(tx) {
    -  if (this == tx) {
    -    return true;
    -  }
    -  if (!tx) {
    -    return false;
    -  }
    -  return this.m00_ == tx.m00_ &&
    -      this.m01_ == tx.m01_ &&
    -      this.m02_ == tx.m02_ &&
    -      this.m10_ == tx.m10_ &&
    -      this.m11_ == tx.m11_ &&
    -      this.m12_ == tx.m12_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/affinetransform_test.html b/src/database/third_party/closure-library/closure/goog/graphics/affinetransform_test.html
    deleted file mode 100644
    index 79e7b124065..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/affinetransform_test.html
    +++ /dev/null
    @@ -1,360 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.graphics.AffineTransform</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.graphics');
    -  goog.require('goog.graphics.AffineTransform');
    -  goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -
    -<script>
    -  function testGetTranslateInstance() {
    -    var tx = goog.graphics.AffineTransform.getTranslateInstance(2, 4);
    -    assertEquals(1, tx.getScaleX());
    -    assertEquals(0, tx.getShearY());
    -    assertEquals(0, tx.getShearX());
    -    assertEquals(1, tx.getScaleY());
    -    assertEquals(2, tx.getTranslateX());
    -    assertEquals(4, tx.getTranslateY());
    -  }
    -
    -  function testGetScaleInstance() {
    -    var tx = goog.graphics.AffineTransform.getScaleInstance(2, 4);
    -    assertEquals(2, tx.getScaleX());
    -    assertEquals(0, tx.getShearY());
    -    assertEquals(0, tx.getShearX());
    -    assertEquals(4, tx.getScaleY());
    -    assertEquals(0, tx.getTranslateX());
    -    assertEquals(0, tx.getTranslateY());
    -  }
    -
    -  function testGetRotateInstance() {
    -    var tx = goog.graphics.AffineTransform.getRotateInstance(Math.PI / 2, 1, 2);
    -    assertRoughlyEquals(0, tx.getScaleX(), 1e-9);
    -    assertRoughlyEquals(1, tx.getShearY(), 1e-9);
    -    assertRoughlyEquals(-1, tx.getShearX(), 1e-9);
    -    assertRoughlyEquals(0, tx.getScaleY(), 1e-9);
    -    assertRoughlyEquals(3, tx.getTranslateX(), 1e-9);
    -    assertRoughlyEquals(1, tx.getTranslateY(), 1e-9);
    -  }
    -
    -  function testGetShearInstance() {
    -    var tx = goog.graphics.AffineTransform.getShearInstance(2, 4);
    -    assertEquals(1, tx.getScaleX());
    -    assertEquals(4, tx.getShearY());
    -    assertEquals(2, tx.getShearX());
    -    assertEquals(1, tx.getScaleY());
    -    assertEquals(0, tx.getTranslateX());
    -    assertEquals(0, tx.getTranslateY());
    -  }
    -
    -  function testConstructor() {
    -    assertThrows(function() {
    -      new goog.graphics.AffineTransform([0, 0]);
    -    });
    -    assertThrows(function() {
    -      new goog.graphics.AffineTransform({});
    -    });
    -    assertThrows(function() {
    -      new goog.graphics.AffineTransform(0, 0, 0, 'a', 0, 0);
    -    });
    -
    -    var tx = new goog.graphics.AffineTransform(1, 2, 3, 4, 5, 6);
    -    assertEquals(1, tx.getScaleX());
    -    assertEquals(2, tx.getShearY());
    -    assertEquals(3, tx.getShearX());
    -    assertEquals(4, tx.getScaleY());
    -    assertEquals(5, tx.getTranslateX());
    -    assertEquals(6, tx.getTranslateY());
    -
    -    tx = new goog.graphics.AffineTransform();
    -    assert(tx.isIdentity());
    -  }
    -
    -  function testIsIdentity() {
    -    var tx = new goog.graphics.AffineTransform(1, 2, 3, 4, 5, 6);
    -    assertFalse(tx.isIdentity());
    -    tx.setTransform(1, 0, 0, 1, 0, 0);
    -    assert(tx.isIdentity());
    -  }
    -
    -  function testClone() {
    -    var tx = new goog.graphics.AffineTransform(1, 2, 3, 4, 5, 6);
    -    var copy = tx.clone();
    -    assertEquals(copy.getScaleX(), tx.getScaleX());
    -    assertEquals(copy.getShearY(), tx.getShearY());
    -    assertEquals(copy.getShearX(), tx.getShearX());
    -    assertEquals(copy.getScaleY(), tx.getScaleY());
    -    assertEquals(copy.getTranslateX(), tx.getTranslateX());
    -    assertEquals(copy.getTranslateY(), tx.getTranslateY());
    -  }
    -
    -  function testSetTransform() {
    -    var tx = new goog.graphics.AffineTransform();
    -    assertThrows(function() {
    -      tx.setTransform(1, 2, 3, 4, 6);
    -    });
    -    assertThrows(function() {
    -      tx.setTransform('a', 2, 3, 4, 5, 6);
    -    });
    -
    -    tx.setTransform(1, 2, 3, 4, 5, 6);
    -    assertEquals(1, tx.getScaleX());
    -    assertEquals(2, tx.getShearY());
    -    assertEquals(3, tx.getShearX());
    -    assertEquals(4, tx.getScaleY());
    -    assertEquals(5, tx.getTranslateX());
    -    assertEquals(6, tx.getTranslateY());
    -  }
    -
    -  function testScale() {
    -    var tx = new goog.graphics.AffineTransform(1, 2, 3, 4, 5, 6);
    -    tx.scale(2, 3);
    -    assertEquals(2, tx.getScaleX());
    -    assertEquals(4, tx.getShearY());
    -    assertEquals(9, tx.getShearX());
    -    assertEquals(12, tx.getScaleY());
    -    assertEquals(5, tx.getTranslateX());
    -    assertEquals(6, tx.getTranslateY());
    -  }
    -
    -  function testPreScale() {
    -    var tx = new goog.graphics.AffineTransform(1, 2, 3, 4, 5, 6);
    -    tx.preScale(2, 3);
    -    assertEquals(2, tx.getScaleX());
    -    assertEquals(6, tx.getShearY());
    -    assertEquals(6, tx.getShearX());
    -    assertEquals(12, tx.getScaleY());
    -    assertEquals(10, tx.getTranslateX());
    -    assertEquals(18, tx.getTranslateY());
    -  }
    -
    -  function testTranslate() {
    -    var tx = new goog.graphics.AffineTransform(1, 2, 3, 4, 5, 6);
    -    tx.translate(2, 3);
    -    assertEquals(1, tx.getScaleX());
    -    assertEquals(2, tx.getShearY());
    -    assertEquals(3, tx.getShearX());
    -    assertEquals(4, tx.getScaleY());
    -    assertEquals(16, tx.getTranslateX());
    -    assertEquals(22, tx.getTranslateY());
    -  }
    -
    -  function testPreTranslate() {
    -    var tx = new goog.graphics.AffineTransform(1, 2, 3, 4, 5, 6);
    -    tx.preTranslate(2, 3);
    -    assertEquals(1, tx.getScaleX());
    -    assertEquals(2, tx.getShearY());
    -    assertEquals(3, tx.getShearX());
    -    assertEquals(4, tx.getScaleY());
    -    assertEquals(7, tx.getTranslateX());
    -    assertEquals(9, tx.getTranslateY());
    -  }
    -
    -  function testRotate() {
    -    var tx = new goog.graphics.AffineTransform(1, 2, 3, 4, 5, 6);
    -    tx.rotate(Math.PI / 2, 1, 1);
    -    assertRoughlyEquals(3, tx.getScaleX(), 1e-9);
    -    assertRoughlyEquals(4, tx.getShearY(), 1e-9);
    -    assertRoughlyEquals(-1, tx.getShearX(), 1e-9);
    -    assertRoughlyEquals(-2, tx.getScaleY(), 1e-9);
    -    assertRoughlyEquals(7, tx.getTranslateX(), 1e-9);
    -    assertRoughlyEquals(10, tx.getTranslateY(), 1e-9);
    -  }
    -
    -  function testPreRotate() {
    -    var tx = new goog.graphics.AffineTransform(1, 2, 3, 4, 5, 6);
    -    tx.preRotate(Math.PI / 2, 1, 1);
    -    assertRoughlyEquals(-2, tx.getScaleX(), 1e-9);
    -    assertRoughlyEquals(1, tx.getShearY(), 1e-9);
    -    assertRoughlyEquals(-4, tx.getShearX(), 1e-9);
    -    assertRoughlyEquals(3, tx.getScaleY(), 1e-9);
    -    assertRoughlyEquals(-4, tx.getTranslateX(), 1e-9);
    -    assertRoughlyEquals(5, tx.getTranslateY(), 1e-9);
    -  }
    -
    -  function testShear() {
    -    var tx = new goog.graphics.AffineTransform(1, 2, 3, 4, 5, 6);
    -    tx.shear(2, 3);
    -    assertEquals(10, tx.getScaleX());
    -    assertEquals(14, tx.getShearY());
    -    assertEquals(5, tx.getShearX());
    -    assertEquals(8, tx.getScaleY());
    -    assertEquals(5, tx.getTranslateX());
    -    assertEquals(6, tx.getTranslateY());
    -  }
    -
    -  function testPreShear() {
    -    var tx = new goog.graphics.AffineTransform(1, 2, 3, 4, 5, 6);
    -    tx.preShear(2, 3);
    -    assertEquals(5, tx.getScaleX());
    -    assertEquals(5, tx.getShearY());
    -    assertEquals(11, tx.getShearX());
    -    assertEquals(13, tx.getScaleY());
    -    assertEquals(17, tx.getTranslateX());
    -    assertEquals(21, tx.getTranslateY());
    -  }
    -
    -  function testConcatentate() {
    -    var tx = new goog.graphics.AffineTransform(1, 2, 3, 4, 5, 6);
    -    tx.concatenate(new goog.graphics.AffineTransform(2, 1, 6, 5, 4, 3));
    -    assertEquals(5, tx.getScaleX());
    -    assertEquals(8, tx.getShearY());
    -    assertEquals(21, tx.getShearX());
    -    assertEquals(32, tx.getScaleY());
    -    assertEquals(18, tx.getTranslateX());
    -    assertEquals(26, tx.getTranslateY());
    -  }
    -
    -  function testPreConcatentate() {
    -    var tx = new goog.graphics.AffineTransform(1, 2, 3, 4, 5, 6);
    -    tx.preConcatenate(new goog.graphics.AffineTransform(2, 1, 6, 5, 4, 3));
    -    assertEquals(14, tx.getScaleX());
    -    assertEquals(11, tx.getShearY());
    -    assertEquals(30, tx.getShearX());
    -    assertEquals(23, tx.getScaleY());
    -    assertEquals(50, tx.getTranslateX());
    -    assertEquals(38, tx.getTranslateY());
    -  }
    -
    -  function testAssociativeConcatenate() {
    -    var x = new goog.graphics.AffineTransform(2, 3, 5, 7, 11, 13).concatenate(
    -        new goog.graphics.AffineTransform(17, 19, 23, 29, 31, 37));
    -    var y = new goog.graphics.AffineTransform(17, 19, 23, 29, 31, 37)
    -        .preConcatenate(new goog.graphics.AffineTransform(2, 3, 5, 7, 11, 13));
    -    assertEquals(x.getScaleX(), y.getScaleX());
    -    assertEquals(x.getShearY(), y.getShearY());
    -    assertEquals(x.getShearX(), y.getShearX());
    -    assertEquals(x.getScaleY(), y.getScaleY());
    -    assertEquals(x.getTranslateX(), y.getTranslateX());
    -    assertEquals(x.getTranslateY(), y.getTranslateY());
    -  };
    -
    -  function testTransform() {
    -    var srcPts = [0, 0, 1, 0, 1, 1, 0, 1];
    -    var dstPts = [];
    -    var tx = goog.graphics.AffineTransform.getScaleInstance(2, 3);
    -    tx.translate(5, 10);
    -    tx.rotate(Math.PI / 4, 5, 10);
    -    tx.transform(srcPts, 0, dstPts, 0, 4);
    -    assert(goog.array.equals(
    -        [27.071068, 28.180195, 28.485281, 30.301516,
    -        27.071068, 32.422836, 25.656855, 30.301516],
    -        dstPts,
    -        goog.math.nearlyEquals));
    -  }
    -
    -  function testGetDeterminant() {
    -    var tx = goog.graphics.AffineTransform.getScaleInstance(2, 3);
    -    tx.translate(5, 10);
    -    tx.rotate(Math.PI / 4, 5, 10);
    -    assertRoughlyEquals(6, tx.getDeterminant(), 0.001);
    -  }
    -
    -  function testIsInvertible() {
    -    assertTrue(new goog.graphics.AffineTransform(2, 3, 4, 5, 6, 7).
    -        isInvertible());
    -    assertTrue(new goog.graphics.AffineTransform(1, 0, 0, 1, 0, 0).
    -        isInvertible());
    -    assertFalse(new goog.graphics.AffineTransform(NaN, 0, 0, 1, 0, 0).
    -        isInvertible());
    -    assertFalse(new goog.graphics.AffineTransform(1, NaN, 0, 1, 0, 0).
    -        isInvertible());
    -    assertFalse(new goog.graphics.AffineTransform(1, 0, NaN, 1, 0, 0).
    -        isInvertible());
    -    assertFalse(new goog.graphics.AffineTransform(1, 0, 0, NaN, 0, 0).
    -        isInvertible());
    -    assertFalse(new goog.graphics.AffineTransform(1, 0, 0, 1, NaN, 0).
    -        isInvertible());
    -    assertFalse(new goog.graphics.AffineTransform(1, 0, 0, 1, 0, NaN).
    -        isInvertible());
    -    assertFalse(new goog.graphics.AffineTransform(Infinity, 0, 0, 1, 0, 0).
    -        isInvertible());
    -    assertFalse(new goog.graphics.AffineTransform(1, Infinity, 0, 1, 0, 0).
    -        isInvertible());
    -    assertFalse(new goog.graphics.AffineTransform(1, 0, Infinity, 1, 0, 0).
    -        isInvertible());
    -    assertFalse(new goog.graphics.AffineTransform(1, 0, 0, Infinity, 0, 0).
    -        isInvertible());
    -    assertFalse(new goog.graphics.AffineTransform(1, 0, 0, 1, Infinity, 0).
    -        isInvertible());
    -    assertFalse(new goog.graphics.AffineTransform(1, 0, 0, 1, 0, Infinity).
    -        isInvertible());
    -    assertFalse(new goog.graphics.AffineTransform(0, 0, 0, 0, 1, 0).
    -        isInvertible());
    -  }
    -
    -  function testCreateInverse() {
    -    var tx = goog.graphics.AffineTransform.getScaleInstance(2, 3);
    -    tx.translate(5, 10);
    -    tx.rotate(Math.PI / 4, 5, 10);
    -    var inverse = tx.createInverse();
    -    assert(goog.math.nearlyEquals(0.353553, inverse.getScaleX()));
    -    assert(goog.math.nearlyEquals(-0.353553, inverse.getShearY()));
    -    assert(goog.math.nearlyEquals(0.235702, inverse.getShearX()));
    -    assert(goog.math.nearlyEquals(0.235702, inverse.getScaleY()));
    -    assert(goog.math.nearlyEquals(-16.213203, inverse.getTranslateX()));
    -    assert(goog.math.nearlyEquals(2.928932, inverse.getTranslateY()));
    -  }
    -
    -  function testCopyFrom() {
    -    var from = new goog.graphics.AffineTransform(1, 2, 3, 4, 5, 6);
    -    var to = new goog.graphics.AffineTransform();
    -    to.copyFrom(from);
    -    assertEquals(from.getScaleX(), to.getScaleX());
    -    assertEquals(from.getShearY(), to.getShearY());
    -    assertEquals(from.getShearX(), to.getShearX());
    -    assertEquals(from.getScaleY(), to.getScaleY());
    -    assertEquals(from.getTranslateX(), to.getTranslateX());
    -    assertEquals(from.getTranslateY(), to.getTranslateY());
    -  }
    -
    -  function testToString() {
    -    var tx = new goog.graphics.AffineTransform(1, 2, 3, 4, 5, 6);
    -    assertEquals("matrix(1,2,3,4,5,6)", tx.toString());
    -  }
    -
    -  function testEquals() {
    -    var tx1 = new goog.graphics.AffineTransform(1, 2, 3, 4, 5, 6);
    -    var tx2 = new goog.graphics.AffineTransform(1, 2, 3, 4, 5, 6);
    -    assertEqualsMethod(tx1, tx2, true);
    -
    -    tx2 = new goog.graphics.AffineTransform(-1, 2, 3, 4, 5, 6);
    -    assertEqualsMethod(tx1, tx2, false);
    -
    -    tx2 = new goog.graphics.AffineTransform(1, -1, 3, 4, 5, 6);
    -    assertEqualsMethod(tx1, tx2, false);
    -
    -    tx2 = new goog.graphics.AffineTransform(1, 2, -3, 4, 5, 6);
    -    assertEqualsMethod(tx1, tx2, false);
    -
    -    tx2 = new goog.graphics.AffineTransform(1, 2, 3, -4, 5, 6);
    -    assertEqualsMethod(tx1, tx2, false);
    -
    -    tx2 = new goog.graphics.AffineTransform(1, 2, 3, 4, -5, 6);
    -    assertEqualsMethod(tx1, tx2, false);
    -
    -    tx2 = new goog.graphics.AffineTransform(1, 2, 3, 4, 5, -6);
    -    assertEqualsMethod(tx1, tx2, false);
    -  }
    -
    -  function assertEqualsMethod(tx1, tx2, expected) {
    -    assertEquals(expected, tx1.equals(tx2));
    -    assertEquals(expected, tx2.equals(tx1));
    -    assertEquals(true, tx1.equals(tx1));
    -    assertEquals(true, tx2.equals(tx2));
    -  }
    -</script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/canvaselement.js b/src/database/third_party/closure-library/closure/goog/graphics/canvaselement.js
    deleted file mode 100644
    index 8e4e7c5d20e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/canvaselement.js
    +++ /dev/null
    @@ -1,812 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Objects representing shapes drawn on a canvas.
    - * @author robbyw@google.com (Robby Walker)
    - */
    -
    -goog.provide('goog.graphics.CanvasEllipseElement');
    -goog.provide('goog.graphics.CanvasGroupElement');
    -goog.provide('goog.graphics.CanvasImageElement');
    -goog.provide('goog.graphics.CanvasPathElement');
    -goog.provide('goog.graphics.CanvasRectElement');
    -goog.provide('goog.graphics.CanvasTextElement');
    -
    -
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.dom.safe');
    -goog.require('goog.graphics.EllipseElement');
    -goog.require('goog.graphics.GroupElement');
    -goog.require('goog.graphics.ImageElement');
    -goog.require('goog.graphics.Path');
    -goog.require('goog.graphics.PathElement');
    -goog.require('goog.graphics.RectElement');
    -goog.require('goog.graphics.TextElement');
    -goog.require('goog.html.SafeHtml');
    -goog.require('goog.html.uncheckedconversions');
    -goog.require('goog.math');
    -goog.require('goog.string');
    -goog.require('goog.string.Const');
    -
    -
    -
    -/**
    - * Object representing a group of objects in a canvas.
    - * This is an implementation of the goog.graphics.GroupElement interface.
    - * You should not construct objects from this constructor. The graphics
    - * will return the object for you.
    - * @param {goog.graphics.CanvasGraphics} graphics The graphics creating
    - *     this element.
    - * @constructor
    - * @extends {goog.graphics.GroupElement}
    - * @deprecated goog.graphics is deprecated. It existed to abstract over browser
    - *     differences before the canvas tag was widely supported.  See
    - *     http://en.wikipedia.org/wiki/Canvas_element for details.
    - * @final
    - */
    -goog.graphics.CanvasGroupElement = function(graphics) {
    -  goog.graphics.GroupElement.call(this, null, graphics);
    -
    -
    -  /**
    -   * Children contained by this group.
    -   * @type {Array<goog.graphics.Element>}
    -   * @private
    -   */
    -  this.children_ = [];
    -};
    -goog.inherits(goog.graphics.CanvasGroupElement, goog.graphics.GroupElement);
    -
    -
    -/**
    - * Remove all drawing elements from the group.
    - * @override
    - */
    -goog.graphics.CanvasGroupElement.prototype.clear = function() {
    -  if (this.children_.length) {
    -    this.children_.length = 0;
    -    this.getGraphics().redraw();
    -  }
    -};
    -
    -
    -/**
    - * Set the size of the group element.
    - * @param {number|string} width The width of the group element.
    - * @param {number|string} height The height of the group element.
    - * @override
    - */
    -goog.graphics.CanvasGroupElement.prototype.setSize = function(width, height) {
    -  // Do nothing.
    -};
    -
    -
    -/**
    - * Append a child to the group.  Does not draw it
    - * @param {goog.graphics.Element} element The child to append.
    - */
    -goog.graphics.CanvasGroupElement.prototype.appendChild = function(element) {
    -  this.children_.push(element);
    -};
    -
    -
    -/**
    - * Draw the group.
    - * @param {CanvasRenderingContext2D} ctx The context to draw the element in.
    - */
    -goog.graphics.CanvasGroupElement.prototype.draw = function(ctx) {
    -  for (var i = 0, len = this.children_.length; i < len; i++) {
    -    this.getGraphics().drawElement(this.children_[i]);
    -  }
    -};
    -
    -
    -
    -/**
    - * Thin wrapper for canvas ellipse elements.
    - * This is an implementation of the goog.graphics.EllipseElement interface.
    - * You should not construct objects from this constructor. The graphics
    - * will return the object for you.
    - * @param {Element} element The DOM element to wrap.
    - * @param {goog.graphics.CanvasGraphics} graphics  The graphics creating
    - *     this element.
    - * @param {number} cx Center X coordinate.
    - * @param {number} cy Center Y coordinate.
    - * @param {number} rx Radius length for the x-axis.
    - * @param {number} ry Radius length for the y-axis.
    - * @param {goog.graphics.Stroke} stroke The stroke to use for this element.
    - * @param {goog.graphics.Fill} fill The fill to use for this element.
    - * @constructor
    - * @extends {goog.graphics.EllipseElement}
    - * @final
    - */
    -goog.graphics.CanvasEllipseElement = function(element, graphics,
    -    cx, cy, rx, ry, stroke, fill) {
    -  goog.graphics.EllipseElement.call(this, element, graphics, stroke, fill);
    -
    -  /**
    -   * X coordinate of the ellipse center.
    -   * @type {number}
    -   * @private
    -   */
    -  this.cx_ = cx;
    -
    -
    -  /**
    -   * Y coordinate of the ellipse center.
    -   * @type {number}
    -   * @private
    -   */
    -  this.cy_ = cy;
    -
    -
    -  /**
    -   * Radius length for the x-axis.
    -   * @type {number}
    -   * @private
    -   */
    -  this.rx_ = rx;
    -
    -
    -  /**
    -   * Radius length for the y-axis.
    -   * @type {number}
    -   * @private
    -   */
    -  this.ry_ = ry;
    -
    -
    -  /**
    -   * Internal path approximating an ellipse.
    -   * @type {goog.graphics.Path}
    -   * @private
    -   */
    -  this.path_ = new goog.graphics.Path();
    -  this.setUpPath_();
    -
    -  /**
    -   * Internal path element that actually does the drawing.
    -   * @type {goog.graphics.CanvasPathElement}
    -   * @private
    -   */
    -  this.pathElement_ = new goog.graphics.CanvasPathElement(null, graphics,
    -      this.path_, stroke, fill);
    -};
    -goog.inherits(goog.graphics.CanvasEllipseElement, goog.graphics.EllipseElement);
    -
    -
    -/**
    - * Sets up the path.
    - * @private
    - */
    -goog.graphics.CanvasEllipseElement.prototype.setUpPath_ = function() {
    -  this.path_.clear();
    -  this.path_.moveTo(this.cx_ + goog.math.angleDx(0, this.rx_),
    -                    this.cy_ + goog.math.angleDy(0, this.ry_));
    -  this.path_.arcTo(this.rx_, this.ry_, 0, 360);
    -  this.path_.close();
    -};
    -
    -
    -/**
    - * Update the center point of the ellipse.
    - * @param {number} cx Center X coordinate.
    - * @param {number} cy Center Y coordinate.
    - * @override
    - */
    -goog.graphics.CanvasEllipseElement.prototype.setCenter = function(cx, cy) {
    -  this.cx_ = cx;
    -  this.cy_ = cy;
    -  this.setUpPath_();
    -  this.pathElement_.setPath(/** @type {!goog.graphics.Path} */ (this.path_));
    -};
    -
    -
    -/**
    - * Update the radius of the ellipse.
    - * @param {number} rx Center X coordinate.
    - * @param {number} ry Center Y coordinate.
    - * @override
    - */
    -goog.graphics.CanvasEllipseElement.prototype.setRadius = function(rx, ry) {
    -  this.rx_ = rx;
    -  this.ry_ = ry;
    -  this.setUpPath_();
    -  this.pathElement_.setPath(/** @type {!goog.graphics.Path} */ (this.path_));
    -};
    -
    -
    -/**
    - * Draw the ellipse.  Should be treated as package scope.
    - * @param {CanvasRenderingContext2D} ctx The context to draw the element in.
    - */
    -goog.graphics.CanvasEllipseElement.prototype.draw = function(ctx) {
    -  this.pathElement_.draw(ctx);
    -};
    -
    -
    -
    -/**
    - * Thin wrapper for canvas rectangle elements.
    - * This is an implementation of the goog.graphics.RectElement interface.
    - * You should not construct objects from this constructor. The graphics
    - * will return the object for you.
    - * @param {Element} element The DOM element to wrap.
    - * @param {goog.graphics.CanvasGraphics} graphics The graphics creating
    - *     this element.
    - * @param {number} x X coordinate (left).
    - * @param {number} y Y coordinate (top).
    - * @param {number} w Width of rectangle.
    - * @param {number} h Height of rectangle.
    - * @param {goog.graphics.Stroke} stroke The stroke to use for this element.
    - * @param {goog.graphics.Fill} fill The fill to use for this element.
    - * @constructor
    - * @extends {goog.graphics.RectElement}
    - * @final
    - */
    -goog.graphics.CanvasRectElement = function(element, graphics, x, y, w, h,
    -    stroke, fill) {
    -  goog.graphics.RectElement.call(this, element, graphics, stroke, fill);
    -
    -  /**
    -   * X coordinate of the top left corner.
    -   * @type {number}
    -   * @private
    -   */
    -  this.x_ = x;
    -
    -
    -  /**
    -   * Y coordinate of the top left corner.
    -   * @type {number}
    -   * @private
    -   */
    -  this.y_ = y;
    -
    -
    -  /**
    -   * Width of the rectangle.
    -   * @type {number}
    -   * @private
    -   */
    -  this.w_ = w;
    -
    -
    -  /**
    -   * Height of the rectangle.
    -   * @type {number}
    -   * @private
    -   */
    -  this.h_ = h;
    -};
    -goog.inherits(goog.graphics.CanvasRectElement, goog.graphics.RectElement);
    -
    -
    -/**
    - * Update the position of the rectangle.
    - * @param {number} x X coordinate (left).
    - * @param {number} y Y coordinate (top).
    - * @override
    - */
    -goog.graphics.CanvasRectElement.prototype.setPosition = function(x, y) {
    -  this.x_ = x;
    -  this.y_ = y;
    -  if (this.drawn_) {
    -    this.getGraphics().redraw();
    -  }
    -};
    -
    -
    -/**
    - * Whether the rectangle has been drawn yet.
    - * @type {boolean}
    - * @private
    - */
    -goog.graphics.CanvasRectElement.prototype.drawn_ = false;
    -
    -
    -/**
    - * Update the size of the rectangle.
    - * @param {number} width Width of rectangle.
    - * @param {number} height Height of rectangle.
    - * @override
    - */
    -goog.graphics.CanvasRectElement.prototype.setSize = function(width, height) {
    -  this.w_ = width;
    -  this.h_ = height;
    -  if (this.drawn_) {
    -    this.getGraphics().redraw();
    -  }
    -};
    -
    -
    -/**
    - * Draw the rectangle.  Should be treated as package scope.
    - * @param {CanvasRenderingContext2D} ctx The context to draw the element in.
    - */
    -goog.graphics.CanvasRectElement.prototype.draw = function(ctx) {
    -  this.drawn_ = true;
    -  ctx.beginPath();
    -  ctx.moveTo(this.x_, this.y_);
    -  ctx.lineTo(this.x_, this.y_ + this.h_);
    -  ctx.lineTo(this.x_ + this.w_, this.y_ + this.h_);
    -  ctx.lineTo(this.x_ + this.w_, this.y_);
    -  ctx.closePath();
    -};
    -
    -
    -
    -/**
    - * Thin wrapper for canvas path elements.
    - * This is an implementation of the goog.graphics.PathElement interface.
    - * You should not construct objects from this constructor. The graphics
    - * will return the object for you.
    - * @param {Element} element The DOM element to wrap.
    - * @param {goog.graphics.CanvasGraphics} graphics The graphics creating
    - *     this element.
    - * @param {!goog.graphics.Path} path The path object to draw.
    - * @param {goog.graphics.Stroke} stroke The stroke to use for this element.
    - * @param {goog.graphics.Fill} fill The fill to use for this element.
    - * @constructor
    - * @extends {goog.graphics.PathElement}
    - * @final
    - */
    -goog.graphics.CanvasPathElement = function(element, graphics, path, stroke,
    -    fill) {
    -  goog.graphics.PathElement.call(this, element, graphics, stroke, fill);
    -
    -  this.setPath(path);
    -};
    -goog.inherits(goog.graphics.CanvasPathElement, goog.graphics.PathElement);
    -
    -
    -/**
    - * Whether the shape has been drawn yet.
    - * @type {boolean}
    - * @private
    - */
    -goog.graphics.CanvasPathElement.prototype.drawn_ = false;
    -
    -
    -/**
    - * The path to draw.
    - * @type {goog.graphics.Path}
    - * @private
    - */
    -goog.graphics.CanvasPathElement.prototype.path_;
    -
    -
    -/**
    - * Update the underlying path.
    - * @param {!goog.graphics.Path} path The path object to draw.
    - * @override
    - */
    -goog.graphics.CanvasPathElement.prototype.setPath = function(path) {
    -  this.path_ = path.isSimple() ? path :
    -      goog.graphics.Path.createSimplifiedPath(path);
    -  if (this.drawn_) {
    -    this.getGraphics().redraw();
    -  }
    -};
    -
    -
    -/**
    - * Draw the path.  Should be treated as package scope.
    - * @param {CanvasRenderingContext2D} ctx The context to draw the element in.
    - * @suppress {deprecated} goog.graphics is deprecated.
    - */
    -goog.graphics.CanvasPathElement.prototype.draw = function(ctx) {
    -  this.drawn_ = true;
    -
    -  ctx.beginPath();
    -  this.path_.forEachSegment(function(segment, args) {
    -    switch (segment) {
    -      case goog.graphics.Path.Segment.MOVETO:
    -        ctx.moveTo(args[0], args[1]);
    -        break;
    -      case goog.graphics.Path.Segment.LINETO:
    -        for (var i = 0; i < args.length; i += 2) {
    -          ctx.lineTo(args[i], args[i + 1]);
    -        }
    -        break;
    -      case goog.graphics.Path.Segment.CURVETO:
    -        for (var i = 0; i < args.length; i += 6) {
    -          ctx.bezierCurveTo(args[i], args[i + 1], args[i + 2],
    -              args[i + 3], args[i + 4], args[i + 5]);
    -        }
    -        break;
    -      case goog.graphics.Path.Segment.ARCTO:
    -        throw Error('Canvas paths cannot contain arcs');
    -      case goog.graphics.Path.Segment.CLOSE:
    -        ctx.closePath();
    -        break;
    -    }
    -  });
    -};
    -
    -
    -
    -/**
    - * Thin wrapper for canvas text elements.
    - * This is an implementation of the goog.graphics.TextElement interface.
    - * You should not construct objects from this constructor. The graphics
    - * will return the object for you.
    - * @param {!goog.graphics.CanvasGraphics} graphics The graphics creating
    - *     this element.
    - * @param {string} text The text to draw.
    - * @param {number} x1 X coordinate of start of line.
    - * @param {number} y1 Y coordinate of start of line.
    - * @param {number} x2 X coordinate of end of line.
    - * @param {number} y2 Y coordinate of end of line.
    - * @param {?string} align Horizontal alignment: left (default), center, right.
    - * @param {!goog.graphics.Font} font Font describing the font properties.
    - * @param {goog.graphics.Stroke} stroke The stroke to use for this element.
    - * @param {goog.graphics.Fill} fill The fill to use for this element.
    - * @constructor
    - * @extends {goog.graphics.TextElement}
    - * @final
    - */
    -goog.graphics.CanvasTextElement = function(graphics, text, x1, y1, x2, y2,
    -    align, font, stroke, fill) {
    -  var element = goog.dom.createDom(goog.dom.TagName.DIV, {
    -    'style': 'display:table;position:absolute;padding:0;margin:0;border:0'
    -  });
    -  goog.graphics.TextElement.call(this, element, graphics, stroke, fill);
    -
    -  /**
    -   * The text to draw.
    -   * @type {string}
    -   * @private
    -   */
    -  this.text_ = text;
    -
    -  /**
    -   * X coordinate of the start of the line the text is drawn on.
    -   * @type {number}
    -   * @private
    -   */
    -  this.x1_ = x1;
    -
    -  /**
    -   * Y coordinate of the start of the line the text is drawn on.
    -   * @type {number}
    -   * @private
    -   */
    -  this.y1_ = y1;
    -
    -  /**
    -   * X coordinate of the end of the line the text is drawn on.
    -   * @type {number}
    -   * @private
    -   */
    -  this.x2_ = x2;
    -
    -  /**
    -   * Y coordinate of the end of the line the text is drawn on.
    -   * @type {number}
    -   * @private
    -   */
    -  this.y2_ = y2;
    -
    -  /**
    -   * Horizontal alignment: left (default), center, right.
    -   * @type {string}
    -   * @private
    -   */
    -  this.align_ = align || 'left';
    -
    -  /**
    -   * Font object describing the font properties.
    -   * @type {goog.graphics.Font}
    -   * @private
    -   */
    -  this.font_ = font;
    -
    -  /**
    -   * The inner element that contains the text.
    -   * @type {Element}
    -   * @private
    -   */
    -  this.innerElement_ = goog.dom.createDom('DIV', {
    -    'style': 'display:table-cell;padding: 0;margin: 0;border: 0'
    -  });
    -
    -  this.updateStyle_();
    -  this.updateText_();
    -
    -  // Append to the DOM.
    -  graphics.getElement().appendChild(element);
    -  element.appendChild(this.innerElement_);
    -};
    -goog.inherits(goog.graphics.CanvasTextElement, goog.graphics.TextElement);
    -
    -
    -/**
    - * Update the displayed text of the element.
    - * @param {string} text The text to draw.
    - * @override
    - */
    -goog.graphics.CanvasTextElement.prototype.setText = function(text) {
    -  this.text_ = text;
    -  this.updateText_();
    -};
    -
    -
    -/**
    - * Sets the fill for this element.
    - * @param {goog.graphics.Fill} fill The fill object.
    - * @override
    - */
    -goog.graphics.CanvasTextElement.prototype.setFill = function(fill) {
    -  this.fill = fill;
    -  var element = this.getElement();
    -  if (element) {
    -    element.style.color = fill.getColor() || fill.getColor1();
    -  }
    -};
    -
    -
    -/**
    - * Sets the stroke for this element.
    - * @param {goog.graphics.Stroke} stroke The stroke object.
    - * @override
    - */
    -goog.graphics.CanvasTextElement.prototype.setStroke = function(stroke) {
    -  // Ignore stroke
    -};
    -
    -
    -/**
    - * Draw the text.  Should be treated as package scope.
    - * @param {CanvasRenderingContext2D} ctx The context to draw the element in.
    - */
    -goog.graphics.CanvasTextElement.prototype.draw = function(ctx) {
    -  // Do nothing - the text is already drawn.
    -};
    -
    -
    -/**
    - * Update the styles of the DIVs.
    - * @private
    - */
    -goog.graphics.CanvasTextElement.prototype.updateStyle_ = function() {
    -  var x1 = this.x1_;
    -  var x2 = this.x2_;
    -  var y1 = this.y1_;
    -  var y2 = this.y2_;
    -  var align = this.align_;
    -  var font = this.font_;
    -  var style = this.getElement().style;
    -  var scaleX = this.getGraphics().getPixelScaleX();
    -  var scaleY = this.getGraphics().getPixelScaleY();
    -
    -  if (x1 == x2) {
    -    // Special case vertical text
    -    style.lineHeight = '90%';
    -
    -    this.innerElement_.style.verticalAlign = align == 'center' ? 'middle' :
    -        align == 'left' ? (y1 < y2 ? 'top' : 'bottom') :
    -        y1 < y2 ? 'bottom' : 'top';
    -    style.textAlign = 'center';
    -
    -    var w = font.size * scaleX;
    -    style.top = Math.round(Math.min(y1, y2) * scaleY) + 'px';
    -    style.left = Math.round((x1 - w / 2) * scaleX) + 'px';
    -    style.width = Math.round(w) + 'px';
    -    style.height = Math.abs(y1 - y2) * scaleY + 'px';
    -
    -    style.fontSize = font.size * 0.6 * scaleY + 'pt';
    -  } else {
    -    style.lineHeight = '100%';
    -    this.innerElement_.style.verticalAlign = 'top';
    -    style.textAlign = align;
    -
    -    style.top = Math.round(((y1 + y2) / 2 - font.size * 2 / 3) * scaleY) + 'px';
    -    style.left = Math.round(x1 * scaleX) + 'px';
    -    style.width = Math.round(Math.abs(x2 - x1) * scaleX) + 'px';
    -    style.height = 'auto';
    -
    -    style.fontSize = font.size * scaleY + 'pt';
    -  }
    -
    -  style.fontWeight = font.bold ? 'bold' : 'normal';
    -  style.fontStyle = font.italic ? 'italic' : 'normal';
    -  style.fontFamily = font.family;
    -
    -  var fill = this.getFill();
    -  style.color = fill.getColor() || fill.getColor1();
    -};
    -
    -
    -/**
    - * Update the text content.
    - * @private
    - */
    -goog.graphics.CanvasTextElement.prototype.updateText_ = function() {
    -  if (this.x1_ == this.x2_) {
    -    // Special case vertical text
    -    var html =
    -        goog.array.map(
    -            this.text_.split(''),
    -            function(entry) { return goog.string.htmlEscape(entry); })
    -        .join('<br>');
    -    // Creating a SafeHtml for each character would be quite expensive, and it's
    -    // obvious that this is safe, so an unchecked conversion is appropriate.
    -    var safeHtml = goog.html.uncheckedconversions
    -        .safeHtmlFromStringKnownToSatisfyTypeContract(
    -            goog.string.Const.from('Concatenate escaped chars and <br>'),
    -            html);
    -    goog.dom.safe.setInnerHtml(
    -        /** @type {!Element} */ (this.innerElement_), safeHtml);
    -  } else {
    -    goog.dom.safe.setInnerHtml(
    -        /** @type {!Element} */ (this.innerElement_),
    -        goog.html.SafeHtml.htmlEscape(this.text_));
    -  }
    -};
    -
    -
    -
    -/**
    - * Thin wrapper for canvas image elements.
    - * This is an implementation of the goog.graphics.ImageElement interface.
    - * You should not construct objects from this constructor. The graphics
    - * will return the object for you.
    - * @param {Element} element The DOM element to wrap.
    - * @param {goog.graphics.CanvasGraphics} graphics The graphics creating
    - *     this element.
    - * @param {number} x X coordinate (left).
    - * @param {number} y Y coordinate (top).
    - * @param {number} w Width of rectangle.
    - * @param {number} h Height of rectangle.
    - * @param {string} src Source of the image.
    - * @constructor
    - * @extends {goog.graphics.ImageElement}
    - * @final
    - */
    -goog.graphics.CanvasImageElement = function(element, graphics, x, y, w, h,
    -    src) {
    -  goog.graphics.ImageElement.call(this, element, graphics);
    -
    -  /**
    -   * X coordinate of the top left corner.
    -   * @type {number}
    -   * @private
    -   */
    -  this.x_ = x;
    -
    -
    -  /**
    -   * Y coordinate of the top left corner.
    -   * @type {number}
    -   * @private
    -   */
    -  this.y_ = y;
    -
    -
    -  /**
    -   * Width of the rectangle.
    -   * @type {number}
    -   * @private
    -   */
    -  this.w_ = w;
    -
    -
    -  /**
    -   * Height of the rectangle.
    -   * @type {number}
    -   * @private
    -   */
    -  this.h_ = h;
    -
    -
    -  /**
    -   * URL of the image source.
    -   * @type {string}
    -   * @private
    -   */
    -  this.src_ = src;
    -};
    -goog.inherits(goog.graphics.CanvasImageElement, goog.graphics.ImageElement);
    -
    -
    -/**
    - * Whether the image has been drawn yet.
    - * @type {boolean}
    - * @private
    - */
    -goog.graphics.CanvasImageElement.prototype.drawn_ = false;
    -
    -
    -/**
    - * Update the position of the image.
    - * @param {number} x X coordinate (left).
    - * @param {number} y Y coordinate (top).
    - * @override
    - */
    -goog.graphics.CanvasImageElement.prototype.setPosition = function(x, y) {
    -  this.x_ = x;
    -  this.y_ = y;
    -  if (this.drawn_) {
    -    this.getGraphics().redraw();
    -  }
    -};
    -
    -
    -/**
    - * Update the size of the image.
    - * @param {number} width Width of rectangle.
    - * @param {number} height Height of rectangle.
    - * @override
    - */
    -goog.graphics.CanvasImageElement.prototype.setSize = function(width, height) {
    -  this.w_ = width;
    -  this.h_ = height;
    -  if (this.drawn_) {
    -    this.getGraphics().redraw();
    -  }
    -};
    -
    -
    -/**
    - * Update the source of the image.
    - * @param {string} src Source of the image.
    - * @override
    - */
    -goog.graphics.CanvasImageElement.prototype.setSource = function(src) {
    -  this.src_ = src;
    -  if (this.drawn_) {
    -    // TODO(robbyw): Probably need to reload the image here.
    -    this.getGraphics().redraw();
    -  }
    -};
    -
    -
    -/**
    - * Draw the image.  Should be treated as package scope.
    - * @param {CanvasRenderingContext2D} ctx The context to draw the element in.
    - */
    -goog.graphics.CanvasImageElement.prototype.draw = function(ctx) {
    -  if (this.img_) {
    -    if (this.w_ && this.h_) {
    -      // If the image is already loaded, draw it.
    -      ctx.drawImage(this.img_, this.x_, this.y_, this.w_, this.h_);
    -    }
    -    this.drawn_ = true;
    -
    -  } else {
    -    // Otherwise, load it.
    -    var img = new Image();
    -    img.onload = goog.bind(this.handleImageLoad_, this, img);
    -    // TODO(robbyw): Handle image load errors.
    -    img.src = this.src_;
    -  }
    -};
    -
    -
    -/**
    - * Handle an image load.
    - * @param {Element} img The image element that finished loading.
    - * @private
    - */
    -goog.graphics.CanvasImageElement.prototype.handleImageLoad_ = function(img) {
    -  this.img_ = img;
    -
    -  // TODO(robbyw): Add a small delay to catch batched images
    -  this.getGraphics().redraw();
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/canvasgraphics.js b/src/database/third_party/closure-library/closure/goog/graphics/canvasgraphics.js
    deleted file mode 100644
    index 40af8c6b2c2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/canvasgraphics.js
    +++ /dev/null
    @@ -1,670 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview CanvasGraphics sub class that uses the canvas tag for drawing.
    - * @author robbyw@google.com (Robby Walker)
    - */
    -
    -
    -goog.provide('goog.graphics.CanvasGraphics');
    -
    -
    -goog.require('goog.events.EventType');
    -goog.require('goog.graphics.AbstractGraphics');
    -goog.require('goog.graphics.CanvasEllipseElement');
    -goog.require('goog.graphics.CanvasGroupElement');
    -goog.require('goog.graphics.CanvasImageElement');
    -goog.require('goog.graphics.CanvasPathElement');
    -goog.require('goog.graphics.CanvasRectElement');
    -goog.require('goog.graphics.CanvasTextElement');
    -goog.require('goog.graphics.SolidFill');
    -goog.require('goog.math.Size');
    -goog.require('goog.style');
    -
    -
    -
    -/**
    - * A Graphics implementation for drawing using canvas.
    - * @param {string|number} width The (non-zero) width in pixels.  Strings
    - *     expressing percentages of parent with (e.g. '80%') are also accepted.
    - * @param {string|number} height The (non-zero) height in pixels.  Strings
    - *     expressing percentages of parent with (e.g. '80%') are also accepted.
    - * @param {?number=} opt_coordWidth The coordinate width - if
    - *     omitted or null, defaults to same as width.
    - * @param {?number=} opt_coordHeight The coordinate height - if
    - *     omitted or null, defaults to same as height.
    - * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper object for the
    - *     document we want to render in.
    - * @constructor
    - * @extends {goog.graphics.AbstractGraphics}
    - * @deprecated goog.graphics is deprecated. It existed to abstract over browser
    - *     differences before the canvas tag was widely supported.  See
    - *     http://en.wikipedia.org/wiki/Canvas_element for details.
    - */
    -goog.graphics.CanvasGraphics = function(width, height,
    -                                        opt_coordWidth, opt_coordHeight,
    -                                        opt_domHelper) {
    -  goog.graphics.AbstractGraphics.call(this, width, height,
    -                                      opt_coordWidth, opt_coordHeight,
    -                                      opt_domHelper);
    -};
    -goog.inherits(goog.graphics.CanvasGraphics, goog.graphics.AbstractGraphics);
    -
    -
    -/**
    - * Sets the fill for the given element.
    - * @param {goog.graphics.StrokeAndFillElement} element The element
    - *     wrapper.
    - * @param {goog.graphics.Fill} fill The fill object.
    - * @override
    - */
    -goog.graphics.CanvasGraphics.prototype.setElementFill = function(element,
    -    fill) {
    -  this.redraw();
    -};
    -
    -
    -/**
    - * Sets the stroke for the given element.
    - * @param {goog.graphics.StrokeAndFillElement} element The element
    - *     wrapper.
    - * @param {goog.graphics.Stroke} stroke The stroke object.
    - * @override
    - */
    -goog.graphics.CanvasGraphics.prototype.setElementStroke = function(
    -    element, stroke) {
    -  this.redraw();
    -};
    -
    -
    -/**
    - * Set the translation and rotation of an element.
    - *
    - * If a more general affine transform is needed than this provides
    - * (e.g. skew and scale) then use setElementAffineTransform.
    - * @param {goog.graphics.Element} element The element wrapper.
    - * @param {number} x The x coordinate of the translation transform.
    - * @param {number} y The y coordinate of the translation transform.
    - * @param {number} angle The angle of the rotation transform.
    - * @param {number} centerX The horizontal center of the rotation transform.
    - * @param {number} centerY The vertical center of the rotation transform.
    - * @override
    - */
    -goog.graphics.CanvasGraphics.prototype.setElementTransform = function(element,
    -    x, y, angle, centerX, centerY) {
    -  this.redraw();
    -};
    -
    -
    -/**
    - * Set the transformation of an element.
    - *
    - * Note that in this implementation this method just calls this.redraw()
    - * and the affineTransform param is unused.
    - * @param {!goog.graphics.Element} element The element wrapper.
    - * @param {!goog.graphics.AffineTransform} affineTransform The
    - *     transformation applied to this element.
    - * @override
    - */
    -goog.graphics.CanvasGraphics.prototype.setElementAffineTransform =
    -    function(element, affineTransform) {
    -  this.redraw();
    -};
    -
    -
    -/**
    - * Push an element transform on to the transform stack.
    - * @param {goog.graphics.Element} element The transformed element.
    - */
    -goog.graphics.CanvasGraphics.prototype.pushElementTransform = function(
    -    element) {
    -  var ctx = this.getContext();
    -  ctx.save();
    -
    -  var transform = element.getTransform();
    -
    -  // TODO(robbyw): Test for unsupported transforms i.e. skews.
    -  var tx = transform.getTranslateX();
    -  var ty = transform.getTranslateY();
    -  if (tx || ty) {
    -    ctx.translate(tx, ty);
    -  }
    -
    -  var sinTheta = transform.getShearY();
    -  if (sinTheta) {
    -    ctx.rotate(Math.asin(sinTheta));
    -  }
    -};
    -
    -
    -/**
    - * Pop an element transform off of the transform stack.
    - */
    -goog.graphics.CanvasGraphics.prototype.popElementTransform = function() {
    -  this.getContext().restore();
    -};
    -
    -
    -/**
    - * Creates the DOM representation of the graphics area.
    - * @override
    - */
    -goog.graphics.CanvasGraphics.prototype.createDom = function() {
    -  var element = this.dom_.createDom('div',
    -      {'style': 'position:relative;overflow:hidden'});
    -  this.setElementInternal(element);
    -
    -  this.canvas_ = this.dom_.createDom('canvas');
    -  element.appendChild(this.canvas_);
    -
    -  /**
    -   * The main canvas element.
    -   * @type {goog.graphics.CanvasGroupElement}
    -   */
    -  this.canvasElement = new goog.graphics.CanvasGroupElement(this);
    -
    -  this.lastGroup_ = this.canvasElement;
    -  this.redrawTimeout_ = 0;
    -
    -  this.updateSize();
    -};
    -
    -
    -/**
    - * Clears the drawing context object in response to actions that make the old
    - * context invalid - namely resize of the canvas element.
    - * @private
    - */
    -goog.graphics.CanvasGraphics.prototype.clearContext_ = function() {
    -  this.context_ = null;
    -};
    -
    -
    -/**
    - * Returns the drawing context.
    - * @return {Object} The canvas element rendering context.
    - */
    -goog.graphics.CanvasGraphics.prototype.getContext = function() {
    -  if (!this.getElement()) {
    -    this.createDom();
    -  }
    -  if (!this.context_) {
    -    this.context_ = this.canvas_.getContext('2d');
    -    this.context_.save();
    -  }
    -  return this.context_;
    -};
    -
    -
    -/**
    - * Changes the coordinate system position.
    - * @param {number} left The coordinate system left bound.
    - * @param {number} top The coordinate system top bound.
    - * @override
    - */
    -goog.graphics.CanvasGraphics.prototype.setCoordOrigin = function(left, top) {
    -  this.coordLeft = left;
    -  this.coordTop = top;
    -  this.redraw();
    -};
    -
    -
    -/**
    - * Changes the coordinate size.
    - * @param {number} coordWidth The coordinate width.
    - * @param {number} coordHeight The coordinate height.
    - * @override
    - */
    -goog.graphics.CanvasGraphics.prototype.setCoordSize = function(coordWidth,
    -                                                               coordHeight) {
    -  goog.graphics.CanvasGraphics.superClass_.setCoordSize.apply(this, arguments);
    -  this.redraw();
    -};
    -
    -
    -/**
    - * Change the size of the canvas.
    - * @param {number} pixelWidth The width in pixels.
    - * @param {number} pixelHeight The height in pixels.
    - * @override
    - */
    -goog.graphics.CanvasGraphics.prototype.setSize = function(pixelWidth,
    -    pixelHeight) {
    -  this.width = pixelWidth;
    -  this.height = pixelHeight;
    -
    -  this.updateSize();
    -  this.redraw();
    -};
    -
    -
    -/** @override */
    -goog.graphics.CanvasGraphics.prototype.getPixelSize = function() {
    -  // goog.style.getSize does not work for Canvas elements.  We
    -  // have to compute the size manually if it is percentage based.
    -  var width = this.width;
    -  var height = this.height;
    -  var computeWidth = goog.isString(width) && width.indexOf('%') != -1;
    -  var computeHeight = goog.isString(height) && height.indexOf('%') != -1;
    -
    -  if (!this.isInDocument() && (computeWidth || computeHeight)) {
    -    return null;
    -  }
    -
    -  var parent;
    -  var parentSize;
    -
    -  if (computeWidth) {
    -    parent = /** @type {Element} */ (this.getElement().parentNode);
    -    parentSize = goog.style.getSize(parent);
    -    width = parseFloat(/** @type {string} */ (width)) * parentSize.width / 100;
    -  }
    -
    -  if (computeHeight) {
    -    parent = parent || /** @type {Element} */ (this.getElement().parentNode);
    -    parentSize = parentSize || goog.style.getSize(parent);
    -    height = parseFloat(/** @type {string} */ (height)) * parentSize.height /
    -        100;
    -  }
    -
    -  return new goog.math.Size(/** @type {number} */ (width),
    -      /** @type {number} */ (height));
    -};
    -
    -
    -/**
    - * Update the size of the canvas.
    - */
    -goog.graphics.CanvasGraphics.prototype.updateSize = function() {
    -  goog.style.setSize(this.getElement(), this.width, this.height);
    -
    -  var pixels = this.getPixelSize();
    -  if (pixels) {
    -    goog.style.setSize(this.canvas_,
    -        /** @type {number} */ (pixels.width),
    -        /** @type {number} */ (pixels.height));
    -    this.canvas_.width = pixels.width;
    -    this.canvas_.height = pixels.height;
    -    this.clearContext_();
    -  }
    -};
    -
    -
    -/**
    - * Reset the canvas.
    - */
    -goog.graphics.CanvasGraphics.prototype.reset = function() {
    -  var ctx = this.getContext();
    -  ctx.restore();
    -  var size = this.getPixelSize();
    -  if (size.width && size.height) {
    -    ctx.clearRect(0, 0, size.width, size.height);
    -  }
    -  ctx.save();
    -};
    -
    -
    -/**
    - * Remove all drawing elements from the graphics.
    - * @override
    - */
    -goog.graphics.CanvasGraphics.prototype.clear = function() {
    -  this.reset();
    -  this.canvasElement.clear();
    -  var el = this.getElement();
    -
    -  // Remove all children (text nodes) except the canvas (which is at index 0)
    -  while (el.childNodes.length > 1) {
    -    el.removeChild(el.lastChild);
    -  }
    -};
    -
    -
    -/**
    - * Redraw the entire canvas.
    - */
    -goog.graphics.CanvasGraphics.prototype.redraw = function() {
    -  if (this.preventRedraw_) {
    -    this.needsRedraw_ = true;
    -    return;
    -  }
    -
    -  if (this.isInDocument()) {
    -    this.reset();
    -
    -    if (this.coordWidth) {
    -      var pixels = this.getPixelSize();
    -      this.getContext().scale(pixels.width / this.coordWidth,
    -          pixels.height / this.coordHeight);
    -    }
    -    if (this.coordLeft || this.coordTop) {
    -      this.getContext().translate(-this.coordLeft, -this.coordTop);
    -    }
    -    this.pushElementTransform(this.canvasElement);
    -    this.canvasElement.draw(this.context_);
    -    this.popElementTransform();
    -  }
    -};
    -
    -
    -/**
    - * Draw an element, including any stroke or fill.
    - * @param {goog.graphics.Element} element The element to draw.
    - */
    -goog.graphics.CanvasGraphics.prototype.drawElement = function(element) {
    -  if (element instanceof goog.graphics.CanvasTextElement) {
    -    // Don't draw text since that is not implemented using canvas.
    -    return;
    -  }
    -
    -  var ctx = this.getContext();
    -  this.pushElementTransform(element);
    -
    -  if (!element.getFill || !element.getStroke) {
    -    // Draw without stroke or fill (e.g. the element is an image or group).
    -    element.draw(ctx);
    -    this.popElementTransform();
    -    return;
    -  }
    -
    -  var fill = element.getFill();
    -  if (fill) {
    -    if (fill instanceof goog.graphics.SolidFill) {
    -      if (fill.getOpacity() != 0) {
    -        ctx.globalAlpha = fill.getOpacity();
    -        ctx.fillStyle = fill.getColor();
    -        element.draw(ctx);
    -        ctx.fill();
    -        ctx.globalAlpha = 1;
    -      }
    -    } else { // (fill instanceof goog.graphics.LinearGradient)
    -      var linearGradient = ctx.createLinearGradient(fill.getX1(), fill.getY1(),
    -          fill.getX2(), fill.getY2());
    -      linearGradient.addColorStop(0.0, fill.getColor1());
    -      linearGradient.addColorStop(1.0, fill.getColor2());
    -
    -      ctx.fillStyle = linearGradient;
    -      element.draw(ctx);
    -      ctx.fill();
    -    }
    -  }
    -
    -  var stroke = element.getStroke();
    -  if (stroke) {
    -    element.draw(ctx);
    -    ctx.strokeStyle = stroke.getColor();
    -
    -    var width = stroke.getWidth();
    -    if (goog.isString(width) && width.indexOf('px') != -1) {
    -      width = parseFloat(width) / this.getPixelScaleX();
    -    }
    -    ctx.lineWidth = width;
    -
    -    ctx.stroke();
    -  }
    -
    -  this.popElementTransform();
    -};
    -
    -
    -
    -/**
    - * Append an element.
    - *
    - * @param {goog.graphics.Element} element The element to draw.
    - * @param {goog.graphics.GroupElement|undefined} group The group to draw
    - *     it in. If null or undefined, defaults to the root group.
    - * @protected
    - */
    -goog.graphics.CanvasGraphics.prototype.append = function(element, group) {
    -  group = group || this.canvasElement;
    -  group.appendChild(element);
    -
    -  if (this.isDrawable(group)) {
    -    this.drawElement(element);
    -  }
    -};
    -
    -
    -/**
    - * Draw an ellipse.
    - *
    - * @param {number} cx Center X coordinate.
    - * @param {number} cy Center Y coordinate.
    - * @param {number} rx Radius length for the x-axis.
    - * @param {number} ry Radius length for the y-axis.
    - * @param {goog.graphics.Stroke} stroke Stroke object describing the
    - *    stroke.
    - * @param {goog.graphics.Fill} fill Fill object describing the fill.
    - * @param {goog.graphics.GroupElement=} opt_group The group wrapper
    - *     element to append to.  If not specified, appends to the main canvas.
    - *
    - * @return {!goog.graphics.EllipseElement} The newly created element.
    - * @override
    - */
    -goog.graphics.CanvasGraphics.prototype.drawEllipse = function(cx, cy, rx, ry,
    -    stroke, fill, opt_group) {
    -  var element = new goog.graphics.CanvasEllipseElement(null, this,
    -      cx, cy, rx, ry, stroke, fill);
    -  this.append(element, opt_group);
    -  return element;
    -};
    -
    -
    -/**
    - * Draw a rectangle.
    - *
    - * @param {number} x X coordinate (left).
    - * @param {number} y Y coordinate (top).
    - * @param {number} width Width of rectangle.
    - * @param {number} height Height of rectangle.
    - * @param {goog.graphics.Stroke} stroke Stroke object describing the
    - *    stroke.
    - * @param {goog.graphics.Fill} fill Fill object describing the fill.
    - * @param {goog.graphics.GroupElement=} opt_group The group wrapper
    - *     element to append to. If not specified, appends to the main canvas.
    - *
    - * @return {!goog.graphics.RectElement} The newly created element.
    - * @override
    - */
    -goog.graphics.CanvasGraphics.prototype.drawRect = function(x, y, width, height,
    -    stroke, fill, opt_group) {
    -  var element = new goog.graphics.CanvasRectElement(null, this,
    -      x, y, width, height, stroke, fill);
    -  this.append(element, opt_group);
    -  return element;
    -};
    -
    -
    -/**
    - * Draw an image.
    - *
    - * @param {number} x X coordinate (left).
    - * @param {number} y Y coordinate (top).
    - * @param {number} width Width of image.
    - * @param {number} height Height of image.
    - * @param {string} src Source of the image.
    - * @param {goog.graphics.GroupElement=} opt_group The group wrapper
    - *     element to append to. If not specified, appends to the main canvas.
    - *
    - * @return {!goog.graphics.ImageElement} The newly created element.
    - */
    -goog.graphics.CanvasGraphics.prototype.drawImage = function(x, y, width, height,
    -    src, opt_group) {
    -  var element = new goog.graphics.CanvasImageElement(null, this, x, y, width,
    -      height, src);
    -  this.append(element, opt_group);
    -  return element;
    -};
    -
    -
    -/**
    - * Draw a text string vertically centered on a given line.
    - *
    - * @param {string} text The text to draw.
    - * @param {number} x1 X coordinate of start of line.
    - * @param {number} y1 Y coordinate of start of line.
    - * @param {number} x2 X coordinate of end of line.
    - * @param {number} y2 Y coordinate of end of line.
    - * @param {?string} align Horizontal alignment: left (default), center, right.
    - * @param {goog.graphics.Font} font Font describing the font properties.
    - * @param {goog.graphics.Stroke} stroke Stroke object describing the stroke.
    - * @param {goog.graphics.Fill} fill Fill object describing the fill.
    - * @param {goog.graphics.GroupElement=} opt_group The group wrapper
    - *     element to append to. If not specified, appends to the main canvas.
    - *
    - * @return {!goog.graphics.TextElement} The newly created element.
    - * @override
    - */
    -goog.graphics.CanvasGraphics.prototype.drawTextOnLine = function(
    -    text, x1, y1, x2, y2, align, font, stroke, fill, opt_group) {
    -  var element = new goog.graphics.CanvasTextElement(this,
    -      text, x1, y1, x2, y2, align, /** @type {!goog.graphics.Font} */ (font),
    -      stroke, fill);
    -  this.append(element, opt_group);
    -  return element;
    -};
    -
    -
    -/**
    - * Draw a path.
    - * @param {!goog.graphics.Path} path The path object to draw.
    - * @param {goog.graphics.Stroke} stroke Stroke object describing the stroke.
    - * @param {goog.graphics.Fill} fill Fill object describing the fill.
    - * @param {goog.graphics.GroupElement=} opt_group The group wrapper
    - *     element to append to. If not specified, appends to the main canvas.
    - *
    - * @return {!goog.graphics.PathElement} The newly created element.
    - * @override
    - */
    -goog.graphics.CanvasGraphics.prototype.drawPath = function(path, stroke, fill,
    -    opt_group) {
    -  var element = new goog.graphics.CanvasPathElement(null, this,
    -      path, stroke, fill);
    -  this.append(element, opt_group);
    -  return element;
    -};
    -
    -
    -/**
    - * @param {goog.graphics.GroupElement} group The group to possibly
    - *     draw to.
    - * @return {boolean} Whether drawing can occur now.
    - */
    -goog.graphics.CanvasGraphics.prototype.isDrawable = function(group) {
    -  return this.isInDocument() && !this.redrawTimeout_ &&
    -      !this.isRedrawRequired(group);
    -};
    -
    -
    -/**
    - * Returns true if drawing to the given group means a redraw is required.
    - * @param {goog.graphics.GroupElement} group The group to draw to.
    - * @return {boolean} Whether drawing to this group should force a redraw.
    - */
    -goog.graphics.CanvasGraphics.prototype.isRedrawRequired = function(group) {
    -  // TODO(robbyw): Moving up to any parent of lastGroup should not force redraw.
    -  return group != this.canvasElement && group != this.lastGroup_;
    -};
    -
    -
    -/**
    - * Create an empty group of drawing elements.
    - *
    - * @param {goog.graphics.GroupElement=} opt_group The group wrapper
    - *     element to append to. If not specified, appends to the main canvas.
    - *
    - * @return {!goog.graphics.CanvasGroupElement} The newly created group.
    - * @override
    - */
    -goog.graphics.CanvasGraphics.prototype.createGroup = function(opt_group) {
    -  var group = new goog.graphics.CanvasGroupElement(this);
    -
    -  opt_group = opt_group || this.canvasElement;
    -
    -  // TODO(robbyw): Moving up to any parent group should not force redraw.
    -  if (opt_group == this.canvasElement || opt_group == this.lastGroup_) {
    -    this.lastGroup_ = group;
    -  }
    -
    -  this.append(group, opt_group);
    -
    -  return group;
    -};
    -
    -
    -/**
    - * Measure and return the width (in pixels) of a given text string.
    - * Text measurement is needed to make sure a text can fit in the allocated
    - * area. The way text length is measured is by writing it into a div that is
    - * after the visible area, measure the div width, and immediatly erase the
    - * written value.
    - *
    - * @param {string} text The text string to measure.
    - * @param {goog.graphics.Font} font The font object describing the font style.
    - * @override
    - */
    -goog.graphics.CanvasGraphics.prototype.getTextWidth = goog.abstractMethod;
    -
    -
    -/**
    - * Disposes of the component by removing event handlers, detacing DOM nodes from
    - * the document body, and removing references to them.
    - * @override
    - * @protected
    - */
    -goog.graphics.CanvasGraphics.prototype.disposeInternal = function() {
    -  this.context_ = null;
    -  goog.graphics.CanvasGraphics.superClass_.disposeInternal.call(this);
    -};
    -
    -
    -/** @override */
    -goog.graphics.CanvasGraphics.prototype.enterDocument = function() {
    -  var oldPixelSize = this.getPixelSize();
    -  goog.graphics.CanvasGraphics.superClass_.enterDocument.call(this);
    -  if (!oldPixelSize) {
    -    this.updateSize();
    -    this.dispatchEvent(goog.events.EventType.RESIZE);
    -  }
    -  this.redraw();
    -};
    -
    -
    -/**
    - * Start preventing redraws - useful for chaining large numbers of changes
    - * together.  Not guaranteed to do anything - i.e. only use this for
    - * optimization of a single code path.
    - * @override
    - */
    -goog.graphics.CanvasGraphics.prototype.suspend = function() {
    -  this.preventRedraw_ = true;
    -};
    -
    -
    -/**
    - * Stop preventing redraws.  If any redraws had been prevented, a redraw will
    - * be done now.
    - * @override
    - */
    -goog.graphics.CanvasGraphics.prototype.resume = function() {
    -  this.preventRedraw_ = false;
    -
    -  if (this.needsRedraw_) {
    -    this.redraw();
    -    this.needsRedraw_ = false;
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/element.js b/src/database/third_party/closure-library/closure/goog/graphics/element.js
    deleted file mode 100644
    index 5a7bc8fd206..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/element.js
    +++ /dev/null
    @@ -1,164 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview A thin wrapper around the DOM element returned from
    - * the different draw methods of the graphics implementation, and
    - * all interfaces that the various element types support.
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -
    -goog.provide('goog.graphics.Element');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.events');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.Listenable');
    -goog.require('goog.graphics.AffineTransform');
    -goog.require('goog.math');
    -
    -
    -
    -/**
    - * Base class for a thin wrapper around the DOM element returned from
    - * the different draw methods of the graphics.
    - * You should not construct objects from this constructor. The graphics
    - * will return the object for you.
    - * @param {Element} element  The DOM element to wrap.
    - * @param {goog.graphics.AbstractGraphics} graphics  The graphics creating
    - *     this element.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - * @deprecated goog.graphics is deprecated. It existed to abstract over browser
    - *     differences before the canvas tag was widely supported.  See
    - *     http://en.wikipedia.org/wiki/Canvas_element for details.
    - */
    -goog.graphics.Element = function(element, graphics) {
    -  goog.events.EventTarget.call(this);
    -  this.element_ = element;
    -  this.graphics_ = graphics;
    -  // Overloading EventTarget field to state that this is not a custom event.
    -  // TODO(user) Should be handled in EventTarget.js (see bug 846824).
    -  this[goog.events.Listenable.IMPLEMENTED_BY_PROP] = false;
    -};
    -goog.inherits(goog.graphics.Element, goog.events.EventTarget);
    -
    -
    -/**
    - * The graphics object that contains this element.
    - * @type {goog.graphics.AbstractGraphics?}
    - * @private
    - */
    -goog.graphics.Element.prototype.graphics_ = null;
    -
    -
    -/**
    - * The native browser element this class wraps.
    - * @type {Element}
    - * @private
    - */
    -goog.graphics.Element.prototype.element_ = null;
    -
    -
    -/**
    - * The transformation applied to this element.
    - * @type {goog.graphics.AffineTransform?}
    - * @private
    - */
    -goog.graphics.Element.prototype.transform_ = null;
    -
    -
    -/**
    - * Returns the underlying object.
    - * @return {Element} The underlying element.
    - */
    -goog.graphics.Element.prototype.getElement = function() {
    -  return this.element_;
    -};
    -
    -
    -/**
    - * Returns the graphics.
    - * @return {goog.graphics.AbstractGraphics} The graphics that created the
    - *     element.
    - */
    -goog.graphics.Element.prototype.getGraphics = function() {
    -  return this.graphics_;
    -};
    -
    -
    -/**
    - * Set the translation and rotation of the element.
    - *
    - * If a more general affine transform is needed than this provides
    - * (e.g. skew and scale) then use setTransform.
    - * @param {number} x The x coordinate of the translation transform.
    - * @param {number} y The y coordinate of the translation transform.
    - * @param {number} rotate The angle of the rotation transform.
    - * @param {number} centerX The horizontal center of the rotation transform.
    - * @param {number} centerY The vertical center of the rotation transform.
    - */
    -goog.graphics.Element.prototype.setTransformation = function(x, y, rotate,
    -    centerX, centerY) {
    -  this.transform_ = goog.graphics.AffineTransform.getRotateInstance(
    -      goog.math.toRadians(rotate), centerX, centerY).translate(x, y);
    -  this.getGraphics().setElementTransform(this, x, y, rotate, centerX, centerY);
    -};
    -
    -
    -/**
    - * @return {!goog.graphics.AffineTransform} The transformation applied to
    - *     this element.
    - */
    -goog.graphics.Element.prototype.getTransform = function() {
    -  return this.transform_ ? this.transform_.clone() :
    -      new goog.graphics.AffineTransform();
    -};
    -
    -
    -/**
    - * Set the affine transform of the element.
    - * @param {!goog.graphics.AffineTransform} affineTransform The
    - *     transformation applied to this element.
    - */
    -goog.graphics.Element.prototype.setTransform = function(affineTransform) {
    -  this.transform_ = affineTransform.clone();
    -  this.getGraphics().setElementAffineTransform(this, affineTransform);
    -};
    -
    -
    -/** @override */
    -goog.graphics.Element.prototype.addEventListener = function(
    -    type, handler, opt_capture, opt_handlerScope) {
    -  goog.events.listen(this.element_, type, handler, opt_capture,
    -      opt_handlerScope);
    -};
    -
    -
    -/** @override */
    -goog.graphics.Element.prototype.removeEventListener = function(
    -    type, handler, opt_capture, opt_handlerScope) {
    -  goog.events.unlisten(this.element_, type, handler, opt_capture,
    -      opt_handlerScope);
    -};
    -
    -
    -/** @override */
    -goog.graphics.Element.prototype.disposeInternal = function() {
    -  goog.graphics.Element.superClass_.disposeInternal.call(this);
    -  goog.asserts.assert(this.element_);
    -  goog.events.removeAll(this.element_);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/ellipseelement.js b/src/database/third_party/closure-library/closure/goog/graphics/ellipseelement.js
    deleted file mode 100644
    index 975b462e37a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/ellipseelement.js
    +++ /dev/null
    @@ -1,63 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview A thin wrapper around the DOM element for ellipses.
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -
    -goog.provide('goog.graphics.EllipseElement');
    -
    -goog.require('goog.graphics.StrokeAndFillElement');
    -
    -
    -
    -/**
    - * Interface for a graphics ellipse element.
    - * You should not construct objects from this constructor. The graphics
    - * will return an implementation of this interface for you.
    - * @param {Element} element The DOM element to wrap.
    - * @param {goog.graphics.AbstractGraphics} graphics The graphics creating
    - *     this element.
    - * @param {goog.graphics.Stroke?} stroke The stroke to use for this element.
    - * @param {goog.graphics.Fill?} fill The fill to use for this element.
    - * @constructor
    - * @extends {goog.graphics.StrokeAndFillElement}
    - * @deprecated goog.graphics is deprecated. It existed to abstract over browser
    - *     differences before the canvas tag was widely supported.  See
    - *     http://en.wikipedia.org/wiki/Canvas_element for details.
    - */
    -goog.graphics.EllipseElement = function(element, graphics, stroke, fill) {
    -  goog.graphics.StrokeAndFillElement.call(this, element, graphics, stroke,
    -      fill);
    -};
    -goog.inherits(goog.graphics.EllipseElement, goog.graphics.StrokeAndFillElement);
    -
    -
    -/**
    - * Update the center point of the ellipse.
    - * @param {number} cx  Center X coordinate.
    - * @param {number} cy  Center Y coordinate.
    - */
    -goog.graphics.EllipseElement.prototype.setCenter = goog.abstractMethod;
    -
    -
    -/**
    - * Update the radius of the ellipse.
    - * @param {number} rx  Radius length for the x-axis.
    - * @param {number} ry  Radius length for the y-axis.
    - */
    -goog.graphics.EllipseElement.prototype.setRadius = goog.abstractMethod;
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/ext/coordinates.js b/src/database/third_party/closure-library/closure/goog/graphics/ext/coordinates.js
    deleted file mode 100644
    index 42385fea603..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/ext/coordinates.js
    +++ /dev/null
    @@ -1,159 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Graphics utility functions for advanced coordinates.
    - *
    - * This file assists the use of advanced coordinates in goog.graphics.  Coords
    - * can be specified as simple numbers which will correspond to units in the
    - * graphics element's coordinate space.  Alternately, coords can be expressed
    - * in pixels, meaning no matter what tranformations or coordinate system changes
    - * are present, the number of pixel changes will remain constant.  Coords can
    - * also be expressed as percentages of their parent's size.
    - *
    - * This file also allows for elements to have margins, expressable in any of
    - * the ways described above.
    - *
    - * Additional pieces of advanced coordinate functionality can (soon) be found in
    - * element.js and groupelement.js.
    - *
    - * @author robbyw@google.com (Robby Walker)
    - */
    -
    -goog.provide('goog.graphics.ext.coordinates');
    -
    -goog.require('goog.string');
    -
    -
    -/**
    - * Cache of boolean values.  For a given string (key), is it special? (value)
    - * @type {Object}
    - * @private
    - */
    -goog.graphics.ext.coordinates.specialCoordinateCache_ = {};
    -
    -
    -/**
    - * Determines if the given coordinate is a percent based coordinate or an
    - * expression with a percent based component.
    - * @param {string} coord The coordinate to test.
    - * @return {boolean} Whether the coordinate contains the string '%'.
    - * @private
    - */
    -goog.graphics.ext.coordinates.isPercent_ = function(coord) {
    -  return goog.string.contains(coord, '%');
    -};
    -
    -
    -/**
    - * Determines if the given coordinate is a pixel based coordinate or an
    - * expression with a pixel based component.
    - * @param {string} coord The coordinate to test.
    - * @return {boolean} Whether the coordinate contains the string 'px'.
    - * @private
    - */
    -goog.graphics.ext.coordinates.isPixels_ = function(coord) {
    -  return goog.string.contains(coord, 'px');
    -};
    -
    -
    -/**
    - * Determines if the given coordinate is special - i.e. not just a number.
    - * @param {string|number|null} coord The coordinate to test.
    - * @return {boolean} Whether the coordinate is special.
    - */
    -goog.graphics.ext.coordinates.isSpecial = function(coord) {
    -  var cache = goog.graphics.ext.coordinates.specialCoordinateCache_;
    -
    -  if (!(coord in cache)) {
    -    cache[coord] = goog.isString(coord) && (
    -        goog.graphics.ext.coordinates.isPercent_(coord) ||
    -        goog.graphics.ext.coordinates.isPixels_(coord));
    -  }
    -
    -  return cache[coord];
    -};
    -
    -
    -/**
    - * Returns the value of the given expression in the given context.
    - *
    - * Should be treated as package scope.
    - *
    - * @param {string|number} coord The coordinate to convert.
    - * @param {number} size The size of the parent element.
    - * @param {number} scale The ratio of pixels to units.
    - * @return {number} The number of coordinate space units that corresponds to
    - *     this coordinate.
    - */
    -goog.graphics.ext.coordinates.computeValue = function(coord, size, scale) {
    -  var number = parseFloat(String(coord));
    -  if (goog.isString(coord)) {
    -    if (goog.graphics.ext.coordinates.isPercent_(coord)) {
    -      return number * size / 100;
    -    } else if (goog.graphics.ext.coordinates.isPixels_(coord)) {
    -      return number / scale;
    -    }
    -  }
    -
    -  return number;
    -};
    -
    -
    -/**
    - * Converts the given coordinate to a number value in units.
    - *
    - * Should be treated as package scope.
    - *
    - * @param {string|number} coord The coordinate to retrieve the value for.
    - * @param {boolean|undefined} forMaximum Whether we are computing the largest
    - *     value this coordinate would be in a parent of no size.  The container
    - *     size in this case should be set to the size of the current element.
    - * @param {number} containerSize The unit value of the size of the container of
    - *     this element.  Should be set to the minimum width of this element if
    - *     forMaximum is true.
    - * @param {number} scale The ratio of pixels to units.
    - * @param {Object=} opt_cache Optional (but highly recommend) object to store
    - *     cached computations in.  The calling class should manage clearing out
    - *     the cache when the scale or containerSize changes.
    - * @return {number} The correct number of coordinate space units.
    - */
    -goog.graphics.ext.coordinates.getValue = function(coord, forMaximum,
    -    containerSize, scale, opt_cache) {
    -  if (!goog.isNumber(coord)) {
    -    var cacheString = opt_cache && ((forMaximum ? 'X' : '') + coord);
    -
    -    if (opt_cache && cacheString in opt_cache) {
    -      coord = opt_cache[cacheString];
    -    } else {
    -      if (goog.graphics.ext.coordinates.isSpecial(
    -          /** @type {string} */ (coord))) {
    -        coord = goog.graphics.ext.coordinates.computeValue(coord,
    -            containerSize, scale);
    -      } else {
    -        // Simple coordinates just need to be converted from a string to a
    -        // number.
    -        coord = parseFloat(/** @type {string} */ (coord));
    -      }
    -
    -      // Cache the result.
    -      if (opt_cache) {
    -        opt_cache[cacheString] = coord;
    -      }
    -    }
    -  }
    -
    -  return coord;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/ext/coordinates_test.html b/src/database/third_party/closure-library/closure/goog/graphics/ext/coordinates_test.html
    deleted file mode 100644
    index 14b5447677c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/ext/coordinates_test.html
    +++ /dev/null
    @@ -1,74 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.graphics.ext.coordinates</title>
    -<script src="../../base.js"></script>
    -<script>
    -  goog.require('goog.graphics');
    -  goog.require('goog.graphics.ext.coordinates');
    -  goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -
    -<script>
    -  function testIsPercent() {
    -    assert('50% is a percent',
    -        goog.graphics.ext.coordinates.isPercent_('50%'));
    -    assert('50 is not a percent',
    -        !goog.graphics.ext.coordinates.isPercent_('50'));
    -  }
    -
    -  function testIsPixels() {
    -    assert('50px is pixels', goog.graphics.ext.coordinates.isPixels_('50px'));
    -    assert('50 is not pixels', !goog.graphics.ext.coordinates.isPixels_('50'));
    -  }
    -
    -  function testIsSpecial() {
    -    assert('50px is special', goog.graphics.ext.coordinates.isSpecial('50px'));
    -    assert('50% is special', goog.graphics.ext.coordinates.isSpecial('50%'));
    -    assert('50 is not special', !goog.graphics.ext.coordinates.isSpecial('50'));
    -  }
    -
    -  function testComputeValue() {
    -    assertEquals('50% of 100 is 50', 50,
    -        goog.graphics.ext.coordinates.computeValue('50%', 100, null));
    -    assertEquals('50.5% of 200 is 101', 101,
    -        goog.graphics.ext.coordinates.computeValue('50.5%', 200, null));
    -    assertEquals('50px = 25 units when in 2x view', 25,
    -        goog.graphics.ext.coordinates.computeValue('50px', null, 2));
    -  }
    -
    -  function testGenericGetValue() {
    -    var getValue = goog.graphics.ext.coordinates.getValue;
    -
    -    var cache = {};
    -
    -    assertEquals('Testing 50%', 50,
    -        getValue('50%', false, 100, 2, cache));
    -
    -    var count = 0;
    -    for (var x in cache) {
    -      count++;
    -      cache[x] = 'OVERWRITE';
    -    }
    -
    -    assertEquals('Testing cache size', 1, count);
    -    assertEquals('Testing cache usage', 'OVERWRITE',
    -        getValue('50%', false, 100, 2, cache));
    -
    -    cache = {};
    -
    -    assertEquals('Testing 0%', 0,
    -        getValue('0%', false, 100, 2, cache));
    -  }
    -</script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/ext/element.js b/src/database/third_party/closure-library/closure/goog/graphics/ext/element.js
    deleted file mode 100644
    index 546c8c34a39..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/ext/element.js
    +++ /dev/null
    @@ -1,963 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A thicker wrapper around the DOM element returned from
    - * the different draw methods of the graphics implementation, and
    - * all interfaces that the various element types support.
    - * @author robbyw@google.com (Robby Walker)
    - */
    -
    -goog.provide('goog.graphics.ext.Element');
    -
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.functions');
    -goog.require('goog.graphics.ext.coordinates');
    -
    -
    -
    -/**
    - * Base class for a wrapper around the goog.graphics wrapper that enables
    - * more advanced functionality.
    - * @param {goog.graphics.ext.Group?} group Parent for this element.
    - * @param {goog.graphics.Element} wrapper The thin wrapper to wrap.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - */
    -goog.graphics.ext.Element = function(group, wrapper) {
    -  goog.events.EventTarget.call(this);
    -  this.wrapper_ = wrapper;
    -  this.graphics_ = group ? group.getGraphics() : this;
    -
    -  this.xPosition_ = new goog.graphics.ext.Element.Position_(this, true);
    -  this.yPosition_ = new goog.graphics.ext.Element.Position_(this, false);
    -
    -  // Handle parent / child relationships.
    -  if (group) {
    -    this.parent_ = group;
    -    this.parent_.addChild(this);
    -  }
    -};
    -goog.inherits(goog.graphics.ext.Element, goog.events.EventTarget);
    -
    -
    -/**
    - * The graphics object that contains this element.
    - * @type {goog.graphics.ext.Graphics|goog.graphics.ext.Element}
    - * @private
    - */
    -goog.graphics.ext.Element.prototype.graphics_;
    -
    -
    -/**
    - * The goog.graphics wrapper this class wraps.
    - * @type {goog.graphics.Element}
    - * @private
    - */
    -goog.graphics.ext.Element.prototype.wrapper_;
    -
    -
    -/**
    - * The group or surface containing this element.
    - * @type {goog.graphics.ext.Group|undefined}
    - * @private
    - */
    -goog.graphics.ext.Element.prototype.parent_;
    -
    -
    -/**
    - * Whether or not computation of this element's position or size depends on its
    - * parent's size.
    - * @type {boolean}
    - * @private
    - */
    -goog.graphics.ext.Element.prototype.parentDependent_ = false;
    -
    -
    -/**
    - * Whether the element has pending transformations.
    - * @type {boolean}
    - * @private
    - */
    -goog.graphics.ext.Element.prototype.needsTransform_ = false;
    -
    -
    -/**
    - * The current angle of rotation, expressed in degrees.
    - * @type {number}
    - * @private
    - */
    -goog.graphics.ext.Element.prototype.rotation_ = 0;
    -
    -
    -/**
    - * Object representing the x position and size of the element.
    - * @type {goog.graphics.ext.Element.Position_}
    - * @private
    - */
    -goog.graphics.ext.Element.prototype.xPosition_;
    -
    -
    -/**
    - * Object representing the y position and size of the element.
    - * @type {goog.graphics.ext.Element.Position_}
    - * @private
    - */
    -goog.graphics.ext.Element.prototype.yPosition_;
    -
    -
    -/** @return {goog.graphics.Element} The underlying thin wrapper. */
    -goog.graphics.ext.Element.prototype.getWrapper = function() {
    -  return this.wrapper_;
    -};
    -
    -
    -/**
    - * @return {goog.graphics.ext.Element|goog.graphics.ext.Graphics} The graphics
    - *     surface the element is a part of.
    - */
    -goog.graphics.ext.Element.prototype.getGraphics = function() {
    -  return this.graphics_;
    -};
    -
    -
    -/**
    - * Returns the graphics implementation.
    - * @return {goog.graphics.AbstractGraphics} The underlying graphics
    - *     implementation drawing this element's wrapper.
    - * @protected
    - */
    -goog.graphics.ext.Element.prototype.getGraphicsImplementation = function() {
    -  return this.graphics_.getImplementation();
    -};
    -
    -
    -/**
    - * @return {goog.graphics.ext.Group|undefined} The parent of this element.
    - */
    -goog.graphics.ext.Element.prototype.getParent = function() {
    -  return this.parent_;
    -};
    -
    -
    -// GENERAL POSITIONING
    -
    -
    -/**
    - * Internal convenience method for setting position - either as a left/top,
    - * center/middle, or right/bottom value.  Only one should be specified.
    - * @param {goog.graphics.ext.Element.Position_} position The position object to
    - *     set the value on.
    - * @param {number|string} value The value of the coordinate.
    - * @param {goog.graphics.ext.Element.PositionType_} type The type of the
    - *     coordinate.
    - * @param {boolean=} opt_chain Optional flag to specify this function is part
    - *     of a chain of calls and therefore transformations should be set as
    - *     pending but not yet performed.
    - * @private
    - */
    -goog.graphics.ext.Element.prototype.setPosition_ = function(position, value,
    -    type, opt_chain) {
    -  position.setPosition(value, type);
    -  this.computeIsParentDependent_(position);
    -
    -  this.needsTransform_ = true;
    -  if (!opt_chain) {
    -    this.transform();
    -  }
    -};
    -
    -
    -/**
    - * Sets the width/height of the element.
    - * @param {goog.graphics.ext.Element.Position_} position The position object to
    - *     set the value on.
    - * @param {string|number} size The new width/height value.
    - * @param {boolean=} opt_chain Optional flag to specify this function is part
    - *     of a chain of calls and therefore transformations should be set as
    - *     pending but not yet performed.
    - * @private
    - */
    -goog.graphics.ext.Element.prototype.setSize_ = function(position, size,
    -    opt_chain) {
    -  if (position.setSize(size)) {
    -    this.needsTransform_ = true;
    -
    -    this.computeIsParentDependent_(position);
    -
    -    if (!opt_chain) {
    -      this.reset();
    -    }
    -  } else if (!opt_chain && this.isPendingTransform()) {
    -    this.reset();
    -  }
    -};
    -
    -
    -/**
    - * Sets the minimum width/height of the element.
    - * @param {goog.graphics.ext.Element.Position_} position The position object to
    - *     set the value on.
    - * @param {string|number} minSize The minimum width/height of the element.
    - * @private
    - */
    -goog.graphics.ext.Element.prototype.setMinSize_ = function(position, minSize) {
    -  position.setMinSize(minSize);
    -  this.needsTransform_ = true;
    -  this.computeIsParentDependent_(position);
    -};
    -
    -
    -// HORIZONTAL POSITIONING
    -
    -
    -/**
    - * @return {number} The distance from the left edge of this element to the left
    - *     edge of its parent, specified in units of the parent's coordinate system.
    - */
    -goog.graphics.ext.Element.prototype.getLeft = function() {
    -  return this.xPosition_.getStart();
    -};
    -
    -
    -/**
    - * Sets the left coordinate of the element.  Overwrites any previous value of
    - * left, center, or right for this element.
    - * @param {string|number} left The left coordinate.
    - * @param {boolean=} opt_chain Optional flag to specify this function is part
    - *     of a chain of calls and therefore transformations should be set as
    - *     pending but not yet performed.
    - */
    -goog.graphics.ext.Element.prototype.setLeft = function(left, opt_chain) {
    -  this.setPosition_(this.xPosition_,
    -      left,
    -      goog.graphics.ext.Element.PositionType_.START,
    -      opt_chain);
    -};
    -
    -
    -/**
    - * @return {number} The right coordinate of the element, in units of the
    - *     parent's coordinate system.
    - */
    -goog.graphics.ext.Element.prototype.getRight = function() {
    -  return this.xPosition_.getEnd();
    -};
    -
    -
    -/**
    - * Sets the right coordinate of the element.  Overwrites any previous value of
    - * left, center, or right for this element.
    - * @param {string|number} right The right coordinate.
    - * @param {boolean=} opt_chain Optional flag to specify this function is part
    - *     of a chain of calls and therefore transformations should be set as
    - *     pending but not yet performed.
    - */
    -goog.graphics.ext.Element.prototype.setRight = function(right, opt_chain) {
    -  this.setPosition_(this.xPosition_,
    -      right,
    -      goog.graphics.ext.Element.PositionType_.END,
    -      opt_chain);
    -};
    -
    -
    -/**
    - * @return {number} The center coordinate of the element, in units of the
    - * parent's coordinate system.
    - */
    -goog.graphics.ext.Element.prototype.getCenter = function() {
    -  return this.xPosition_.getMiddle();
    -};
    -
    -
    -/**
    - * Sets the center coordinate of the element.  Overwrites any previous value of
    - * left, center, or right for this element.
    - * @param {string|number} center The center coordinate.
    - * @param {boolean=} opt_chain Optional flag to specify this function is part
    - *     of a chain of calls and therefore transformations should be set as
    - *     pending but not yet performed.
    - */
    -goog.graphics.ext.Element.prototype.setCenter = function(center, opt_chain) {
    -  this.setPosition_(this.xPosition_,
    -      center,
    -      goog.graphics.ext.Element.PositionType_.MIDDLE,
    -      opt_chain);
    -};
    -
    -
    -// VERTICAL POSITIONING
    -
    -
    -/**
    - * @return {number} The distance from the top edge of this element to the top
    - *     edge of its parent, specified in units of the parent's coordinate system.
    - */
    -goog.graphics.ext.Element.prototype.getTop = function() {
    -  return this.yPosition_.getStart();
    -};
    -
    -
    -/**
    - * Sets the top coordinate of the element.  Overwrites any previous value of
    - * top, middle, or bottom for this element.
    - * @param {string|number} top The top coordinate.
    - * @param {boolean=} opt_chain Optional flag to specify this function is part
    - *     of a chain of calls and therefore transformations should be set as
    - *     pending but not yet performed.
    - */
    -goog.graphics.ext.Element.prototype.setTop = function(top, opt_chain) {
    -  this.setPosition_(this.yPosition_,
    -      top,
    -      goog.graphics.ext.Element.PositionType_.START,
    -      opt_chain);
    -};
    -
    -
    -/**
    - * @return {number} The bottom coordinate of the element, in units of the
    - *     parent's coordinate system.
    - */
    -goog.graphics.ext.Element.prototype.getBottom = function() {
    -  return this.yPosition_.getEnd();
    -};
    -
    -
    -/**
    - * Sets the bottom coordinate of the element.  Overwrites any previous value of
    - * top, middle, or bottom for this element.
    - * @param {string|number} bottom The bottom coordinate.
    - * @param {boolean=} opt_chain Optional flag to specify this function is part
    - *     of a chain of calls and therefore transformations should be set as
    - *     pending but not yet performed.
    - */
    -goog.graphics.ext.Element.prototype.setBottom = function(bottom, opt_chain) {
    -  this.setPosition_(this.yPosition_,
    -      bottom,
    -      goog.graphics.ext.Element.PositionType_.END,
    -      opt_chain);
    -};
    -
    -
    -/**
    - * @return {number} The middle coordinate of the element, in units of the
    - *     parent's coordinate system.
    - */
    -goog.graphics.ext.Element.prototype.getMiddle = function() {
    -  return this.yPosition_.getMiddle();
    -};
    -
    -
    -/**
    - * Sets the middle coordinate of the element.  Overwrites any previous value of
    - * top, middle, or bottom for this element
    - * @param {string|number} middle The middle coordinate.
    - * @param {boolean=} opt_chain Optional flag to specify this function is part
    - *     of a chain of calls and therefore transformations should be set as
    - *     pending but not yet performed.
    - */
    -goog.graphics.ext.Element.prototype.setMiddle = function(middle, opt_chain) {
    -  this.setPosition_(this.yPosition_,
    -      middle,
    -      goog.graphics.ext.Element.PositionType_.MIDDLE,
    -      opt_chain);
    -};
    -
    -
    -// DIMENSIONS
    -
    -
    -/**
    - * @return {number} The width of the element, in units of the parent's
    - *     coordinate system.
    - */
    -goog.graphics.ext.Element.prototype.getWidth = function() {
    -  return this.xPosition_.getSize();
    -};
    -
    -
    -/**
    - * Sets the width of the element.
    - * @param {string|number} width The new width value.
    - * @param {boolean=} opt_chain Optional flag to specify this function is part
    - *     of a chain of calls and therefore transformations should be set as
    - *     pending but not yet performed.
    - */
    -goog.graphics.ext.Element.prototype.setWidth = function(width, opt_chain) {
    -  this.setSize_(this.xPosition_, width, opt_chain);
    -};
    -
    -
    -/**
    - * @return {number} The minimum width of the element, in units of the parent's
    - *     coordinate system.
    - */
    -goog.graphics.ext.Element.prototype.getMinWidth = function() {
    -  return this.xPosition_.getMinSize();
    -};
    -
    -
    -/**
    - * Sets the minimum width of the element.
    - * @param {string|number} minWidth The minimum width of the element.
    - */
    -goog.graphics.ext.Element.prototype.setMinWidth = function(minWidth) {
    -  this.setMinSize_(this.xPosition_, minWidth);
    -};
    -
    -
    -/**
    - * @return {number} The height of the element, in units of the parent's
    - *     coordinate system.
    - */
    -goog.graphics.ext.Element.prototype.getHeight = function() {
    -  return this.yPosition_.getSize();
    -};
    -
    -
    -/**
    - * Sets the height of the element.
    - * @param {string|number} height The new height value.
    - * @param {boolean=} opt_chain Optional flag to specify this function is part
    - *     of a chain of calls and therefore transformations should be set as
    - *     pending but not yet performed.
    - */
    -goog.graphics.ext.Element.prototype.setHeight = function(height, opt_chain) {
    -  this.setSize_(this.yPosition_, height, opt_chain);
    -};
    -
    -
    -/**
    - * @return {number} The minimum height of the element, in units of the parent's
    - *     coordinate system.
    - */
    -goog.graphics.ext.Element.prototype.getMinHeight = function() {
    -  return this.yPosition_.getMinSize();
    -};
    -
    -
    -/**
    - * Sets the minimum height of the element.
    - * @param {string|number} minHeight The minimum height of the element.
    - */
    -goog.graphics.ext.Element.prototype.setMinHeight = function(minHeight) {
    -  this.setMinSize_(this.yPosition_, minHeight);
    -};
    -
    -
    -// BOUNDS SHORTCUTS
    -
    -
    -/**
    - * Shortcut for setting the left and top position.
    - * @param {string|number} left The left coordinate.
    - * @param {string|number} top The top coordinate.
    - * @param {boolean=} opt_chain Optional flag to specify this function is part
    - *     of a chain of calls and therefore transformations should be set as
    - *     pending but not yet performed.
    - */
    -goog.graphics.ext.Element.prototype.setPosition = function(left, top,
    -                                                           opt_chain) {
    -  this.setLeft(left, true);
    -  this.setTop(top, opt_chain);
    -};
    -
    -
    -/**
    - * Shortcut for setting the width and height.
    - * @param {string|number} width The new width value.
    - * @param {string|number} height The new height value.
    - * @param {boolean=} opt_chain Optional flag to specify this function is part
    - *     of a chain of calls and therefore transformations should be set as
    - *     pending but not yet performed.
    - */
    -goog.graphics.ext.Element.prototype.setSize = function(width, height,
    -                                                       opt_chain) {
    -  this.setWidth(width, true);
    -  this.setHeight(height, opt_chain);
    -};
    -
    -
    -/**
    - * Shortcut for setting the left, top, width, and height.
    - * @param {string|number} left The left coordinate.
    - * @param {string|number} top The top coordinate.
    - * @param {string|number} width The new width value.
    - * @param {string|number} height The new height value.
    - * @param {boolean=} opt_chain Optional flag to specify this function is part
    - *     of a chain of calls and therefore transformations should be set as
    - *     pending but not yet performed.
    - */
    -goog.graphics.ext.Element.prototype.setBounds = function(left, top, width,
    -                                                         height, opt_chain) {
    -  this.setLeft(left, true);
    -  this.setTop(top, true);
    -  this.setWidth(width, true);
    -  this.setHeight(height, opt_chain);
    -};
    -
    -
    -// MAXIMUM BOUNDS
    -
    -
    -/**
    - * @return {number} An estimate of the maximum x extent this element would have
    - *     in a parent of no width.
    - */
    -goog.graphics.ext.Element.prototype.getMaxX = function() {
    -  return this.xPosition_.getMaxPosition();
    -};
    -
    -
    -/**
    - * @return {number} An estimate of the maximum y extent this element would have
    - *     in a parent of no height.
    - */
    -goog.graphics.ext.Element.prototype.getMaxY = function() {
    -  return this.yPosition_.getMaxPosition();
    -};
    -
    -
    -// RESET
    -
    -
    -/**
    - * Reset the element.  This is called when the element changes size, or when
    - * the coordinate system changes in a way that would affect pixel based
    - * rendering
    - */
    -goog.graphics.ext.Element.prototype.reset = function() {
    -  this.xPosition_.resetCache();
    -  this.yPosition_.resetCache();
    -
    -  this.redraw();
    -
    -  this.needsTransform_ = true;
    -  this.transform();
    -};
    -
    -
    -/**
    - * Overridable function for subclass specific reset.
    - * @protected
    - */
    -goog.graphics.ext.Element.prototype.redraw = goog.nullFunction;
    -
    -
    -// PARENT DEPENDENCY
    -
    -
    -/**
    - * Computes whether the element is still parent dependent.
    - * @param {goog.graphics.ext.Element.Position_} position The recently changed
    - *     position object.
    - * @private
    - */
    -goog.graphics.ext.Element.prototype.computeIsParentDependent_ = function(
    -    position) {
    -  this.parentDependent_ = position.isParentDependent() ||
    -      this.xPosition_.isParentDependent() ||
    -      this.yPosition_.isParentDependent() ||
    -      this.checkParentDependent();
    -};
    -
    -
    -/**
    - * Returns whether this element's bounds depend on its parents.
    - *
    - * This function should be treated as if it has package scope.
    - * @return {boolean} Whether this element's bounds depend on its parents.
    - */
    -goog.graphics.ext.Element.prototype.isParentDependent = function() {
    -  return this.parentDependent_;
    -};
    -
    -
    -/**
    - * Overridable function for subclass specific parent dependency.
    - * @return {boolean} Whether this shape's bounds depends on its parent's.
    - * @protected
    - */
    -goog.graphics.ext.Element.prototype.checkParentDependent =
    -    goog.functions.FALSE;
    -
    -
    -// ROTATION
    -
    -
    -/**
    - * Set the rotation of this element.
    - * @param {number} angle The angle of rotation, in degrees.
    - */
    -goog.graphics.ext.Element.prototype.setRotation = function(angle) {
    -  if (this.rotation_ != angle) {
    -    this.rotation_ = angle;
    -
    -    this.needsTransform_ = true;
    -    this.transform();
    -  }
    -};
    -
    -
    -/**
    - * @return {number} The angle of rotation of this element, in degrees.
    - */
    -goog.graphics.ext.Element.prototype.getRotation = function() {
    -  return this.rotation_;
    -};
    -
    -
    -// TRANSFORMS
    -
    -
    -/**
    - * Called by the parent when the parent has transformed.
    - *
    - * Should be treated as package scope.
    - */
    -goog.graphics.ext.Element.prototype.parentTransform = function() {
    -  this.needsTransform_ = this.needsTransform_ || this.parentDependent_;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether this element has pending transforms.
    - */
    -goog.graphics.ext.Element.prototype.isPendingTransform = function() {
    -  return this.needsTransform_;
    -};
    -
    -
    -/**
    - * Performs a pending transform.
    - * @protected
    - */
    -goog.graphics.ext.Element.prototype.transform = function() {
    -  if (this.isPendingTransform()) {
    -    this.needsTransform_ = false;
    -
    -    this.wrapper_.setTransformation(
    -        this.getLeft(),
    -        this.getTop(),
    -        this.rotation_,
    -        (this.getWidth() || 1) / 2,
    -        (this.getHeight() || 1) / 2);
    -
    -    // TODO(robbyw): this._fireEvent('transform', [ this ]);
    -  }
    -};
    -
    -
    -// PIXEL SCALE
    -
    -
    -/**
    - * @return {number} Returns the number of pixels per unit in the x direction.
    - */
    -goog.graphics.ext.Element.prototype.getPixelScaleX = function() {
    -  return this.getGraphics().getPixelScaleX();
    -};
    -
    -
    -/**
    - * @return {number} Returns the number of pixels per unit in the y direction.
    - */
    -goog.graphics.ext.Element.prototype.getPixelScaleY = function() {
    -  return this.getGraphics().getPixelScaleY();
    -};
    -
    -
    -// EVENT HANDLING
    -
    -
    -/** @override */
    -goog.graphics.ext.Element.prototype.disposeInternal = function() {
    -  goog.graphics.ext.Element.superClass_.disposeInternal.call();
    -  this.wrapper_.dispose();
    -};
    -
    -
    -// INTERNAL POSITION OBJECT
    -
    -
    -/**
    - * Position specification types.  Start corresponds to left/top, middle to
    - * center/middle, and end to right/bottom.
    - * @enum {number}
    - * @private
    - */
    -goog.graphics.ext.Element.PositionType_ = {
    -  START: 0,
    -  MIDDLE: 1,
    -  END: 2
    -};
    -
    -
    -
    -/**
    - * Manages a position and size, either horizontal or vertical.
    - * @param {goog.graphics.ext.Element} element The element the position applies
    - *     to.
    - * @param {boolean} horizontal Whether the position is horizontal or vertical.
    - * @constructor
    - * @private
    - */
    -goog.graphics.ext.Element.Position_ = function(element, horizontal) {
    -  this.element_ = element;
    -  this.horizontal_ = horizontal;
    -};
    -
    -
    -/**
    - * @return {!Object} The coordinate value computation cache.
    - * @private
    - */
    -goog.graphics.ext.Element.Position_.prototype.getCoordinateCache_ = function() {
    -  return this.coordinateCache_ || (this.coordinateCache_ = {});
    -};
    -
    -
    -/**
    - * @return {number} The size of the parent's coordinate space.
    - * @private
    - */
    -goog.graphics.ext.Element.Position_.prototype.getParentSize_ = function() {
    -  var parent = this.element_.getParent();
    -  return this.horizontal_ ?
    -      parent.getCoordinateWidth() :
    -      parent.getCoordinateHeight();
    -};
    -
    -
    -/**
    - * @return {number} The minimum width/height of the element.
    - */
    -goog.graphics.ext.Element.Position_.prototype.getMinSize = function() {
    -  return this.getValue_(this.minSize_);
    -};
    -
    -
    -/**
    - * Sets the minimum width/height of the element.
    - * @param {string|number} minSize The minimum width/height of the element.
    - */
    -goog.graphics.ext.Element.Position_.prototype.setMinSize = function(minSize) {
    -  this.minSize_ = minSize;
    -  this.resetCache();
    -};
    -
    -
    -/**
    - * @return {number} The width/height of the element.
    - */
    -goog.graphics.ext.Element.Position_.prototype.getSize = function() {
    -  return Math.max(this.getValue_(this.size_), this.getMinSize());
    -};
    -
    -
    -/**
    - * Sets the width/height of the element.
    - * @param {string|number} size The width/height of the element.
    - * @return {boolean} Whether the value was changed.
    - */
    -goog.graphics.ext.Element.Position_.prototype.setSize = function(size) {
    -  if (size != this.size_) {
    -    this.size_ = size;
    -    this.resetCache();
    -    return true;
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Converts the given x coordinate to a number value in units.
    - * @param {string|number} v The coordinate to retrieve the value for.
    - * @param {boolean=} opt_forMaximum Whether we are computing the largest value
    - *     this coordinate would be in a parent of no size.
    - * @return {number} The correct number of coordinate space units.
    - * @private
    - */
    -goog.graphics.ext.Element.Position_.prototype.getValue_ = function(v,
    -    opt_forMaximum) {
    -  if (!goog.graphics.ext.coordinates.isSpecial(v)) {
    -    return parseFloat(String(v));
    -  }
    -
    -  var cache = this.getCoordinateCache_();
    -  var scale = this.horizontal_ ?
    -      this.element_.getPixelScaleX() :
    -      this.element_.getPixelScaleY();
    -
    -  var containerSize;
    -  if (opt_forMaximum) {
    -    containerSize = goog.graphics.ext.coordinates.computeValue(
    -        this.size_ || 0, 0, scale);
    -  } else {
    -    var parent = this.element_.getParent();
    -    containerSize = this.horizontal_ ? parent.getWidth() : parent.getHeight();
    -  }
    -
    -  return goog.graphics.ext.coordinates.getValue(v, opt_forMaximum,
    -      containerSize, scale, cache);
    -};
    -
    -
    -/**
    - * @return {number} The distance from the left/top edge of this element to the
    - *     left/top edge of its parent, specified in units of the parent's
    - *     coordinate system.
    - */
    -goog.graphics.ext.Element.Position_.prototype.getStart = function() {
    -  if (this.cachedValue_ == null) {
    -    var value = this.getValue_(this.distance_);
    -    if (this.distanceType_ == goog.graphics.ext.Element.PositionType_.START) {
    -      this.cachedValue_ = value;
    -    } else if (this.distanceType_ ==
    -               goog.graphics.ext.Element.PositionType_.MIDDLE) {
    -      this.cachedValue_ = value + (this.getParentSize_() - this.getSize()) / 2;
    -    } else {
    -      this.cachedValue_ = this.getParentSize_() - value - this.getSize();
    -    }
    -  }
    -
    -  return this.cachedValue_;
    -};
    -
    -
    -/**
    - * @return {number} The middle coordinate of the element, in units of the
    - *     parent's coordinate system.
    - */
    -goog.graphics.ext.Element.Position_.prototype.getMiddle = function() {
    -  return this.distanceType_ == goog.graphics.ext.Element.PositionType_.MIDDLE ?
    -      this.getValue_(this.distance_) :
    -      (this.getParentSize_() - this.getSize()) / 2 - this.getStart();
    -};
    -
    -
    -/**
    - * @return {number} The end coordinate of the element, in units of the
    - *     parent's coordinate system.
    - */
    -goog.graphics.ext.Element.Position_.prototype.getEnd = function() {
    -  return this.distanceType_ == goog.graphics.ext.Element.PositionType_.END ?
    -      this.getValue_(this.distance_) :
    -      this.getParentSize_() - this.getStart() - this.getSize();
    -};
    -
    -
    -/**
    - * Sets the position, either as a left/top, center/middle, or right/bottom
    - * value.
    - * @param {number|string} value The value of the coordinate.
    - * @param {goog.graphics.ext.Element.PositionType_} type The type of the
    - *     coordinate.
    - */
    -goog.graphics.ext.Element.Position_.prototype.setPosition = function(value,
    -    type) {
    -  this.distance_ = value;
    -  this.distanceType_ = type;
    -
    -  // Clear cached value.
    -  this.cachedValue_ = null;
    -};
    -
    -
    -/**
    - * @return {number} An estimate of the maximum x/y extent this element would
    - *     have in a parent of no width/height.
    - */
    -goog.graphics.ext.Element.Position_.prototype.getMaxPosition = function() {
    -  // TODO(robbyw): Handle transformed or rotated coordinates
    -  // TODO(robbyw): Handle pixel based sizes?
    -
    -  return this.getValue_(this.distance_ || 0) + (
    -      goog.graphics.ext.coordinates.isSpecial(this.size_) ? 0 : this.getSize());
    -};
    -
    -
    -/**
    - * Resets the caches of position values and coordinate values.
    - */
    -goog.graphics.ext.Element.Position_.prototype.resetCache = function() {
    -  this.coordinateCache_ = null;
    -  this.cachedValue_ = null;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the size or position of this element depends on
    - *     the size of the parent element.
    - */
    -goog.graphics.ext.Element.Position_.prototype.isParentDependent = function() {
    -  return this.distanceType_ != goog.graphics.ext.Element.PositionType_.START ||
    -      goog.graphics.ext.coordinates.isSpecial(this.size_) ||
    -      goog.graphics.ext.coordinates.isSpecial(this.minSize_) ||
    -      goog.graphics.ext.coordinates.isSpecial(this.distance_);
    -};
    -
    -
    -/**
    - * The lazy loaded distance from the parent's top/left edge to this element's
    - * top/left edge expressed in the parent's coordinate system.  We cache this
    - * because it is most freqeuently requested by the element and it is easy to
    - * compute middle and end values from it.
    - * @type {?number}
    - * @private
    - */
    -goog.graphics.ext.Element.Position_.prototype.cachedValue_ = null;
    -
    -
    -/**
    - * A cache of computed x coordinates.
    - * @type {Object}
    - * @private
    - */
    -goog.graphics.ext.Element.Position_.prototype.coordinateCache_ = null;
    -
    -
    -/**
    - * The minimum width/height of this element, as specified by the caller.
    - * @type {string|number}
    - * @private
    - */
    -goog.graphics.ext.Element.Position_.prototype.minSize_ = 0;
    -
    -
    -/**
    - * The width/height of this object, as specified by the caller.
    - * @type {string|number}
    - * @private
    - */
    -goog.graphics.ext.Element.Position_.prototype.size_ = 0;
    -
    -
    -/**
    - * The coordinate of this object, as specified by the caller.  The type of
    - * coordinate is specified by distanceType_.
    - * @type {string|number}
    - * @private
    - */
    -goog.graphics.ext.Element.Position_.prototype.distance_ = 0;
    -
    -
    -/**
    - * The coordinate type specified by distance_.
    - * @type {goog.graphics.ext.Element.PositionType_}
    - * @private
    - */
    -goog.graphics.ext.Element.Position_.prototype.distanceType_ =
    -    goog.graphics.ext.Element.PositionType_.START;
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/ext/element_test.html b/src/database/third_party/closure-library/closure/goog/graphics/ext/element_test.html
    deleted file mode 100644
    index 293cb34548e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/ext/element_test.html
    +++ /dev/null
    @@ -1,144 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.graphics.ext.Element</title>
    -<script src="../../base.js"></script>
    -<script>
    -  goog.require('goog.graphics');
    -  goog.require('goog.graphics.ext');
    -  goog.require('goog.testing.StrictMock');
    -  goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -<div id="root" style="display: none"></div>
    -<script>
    -  var el, graphics, mockWrapper;
    -
    -  function setUp() {
    -    var div = document.getElementById('root');
    -    graphics = new goog.graphics.ext.Graphics(100, 100, 200, 200);
    -    div.innerHTML = '';
    -    graphics.render(div);
    -
    -    mockWrapper = new goog.testing.StrictMock(goog.graphics.Element);
    -  }
    -
    -  function tearDown() {
    -    mockWrapper.$verify();
    -  }
    -
    -  function assertPosition(fn, left, top, opt_width, opt_height) {
    -    mockWrapper.setTransformation(0, 0, 0, 5, 5);
    -    mockWrapper.setTransformation(left, top, 0,
    -        (opt_width || 10) / 2, (opt_height || 10) / 2);
    -    mockWrapper.$replay();
    -
    -    el = new goog.graphics.ext.Element(graphics, mockWrapper);
    -    el.setSize(10, 10);
    -    fn();
    -  }
    -
    -  function testLeft() {
    -    assertPosition(function() {
    -      el.setLeft(10);
    -    }, 10, 0);
    -    assertFalse(el.isParentDependent());
    -  }
    -
    -  function testLeftPercent() {
    -    assertPosition(function() {
    -      el.setLeft('10%');
    -    }, 20, 0);
    -  }
    -
    -  function testCenter() {
    -    assertPosition(function() {
    -      el.setCenter(0);
    -    }, 95, 0);
    -    assertTrue(el.isParentDependent());
    -  }
    -
    -  function testCenterPercent() {
    -    assertPosition(function() {
    -      el.setCenter('10%');
    -    }, 115, 0);
    -  }
    -
    -  function testRight() {
    -    assertPosition(function() {
    -      el.setRight(10);
    -    }, 180, 0);
    -    assertTrue(el.isParentDependent());
    -  }
    -
    -  function testRightPercent() {
    -    assertPosition(function() {
    -      el.setRight('10%');
    -    }, 170, 0);
    -    assertTrue(el.isParentDependent());
    -  }
    -
    -  function testTop() {
    -    assertPosition(function() {
    -      el.setTop(10);
    -    }, 0, 10);
    -    assertFalse(el.isParentDependent());
    -  }
    -
    -  function testTopPercent() {
    -    assertPosition(function() {
    -      el.setTop('10%');
    -    }, 0, 20);
    -  }
    -
    -  function testMiddle() {
    -    assertPosition(function() {
    -      el.setMiddle(0);
    -    }, 0, 95);
    -    assertTrue(el.isParentDependent());
    -  }
    -
    -  function testMiddlePercent() {
    -    assertPosition(function() {
    -      el.setMiddle('10%');
    -    }, 0, 115);
    -  }
    -
    -  function testBottom() {
    -    assertPosition(function() {
    -      el.setBottom(10);
    -    }, 0, 180);
    -    assertTrue(el.isParentDependent());
    -  }
    -
    -  function testBottomPercent() {
    -    assertPosition(function() {
    -      el.setBottom('10%');
    -    }, 0, 170);
    -    assertTrue(el.isParentDependent());
    -  }
    -
    -  function testSize() {
    -    assertPosition(function() {
    -      el.setSize(100, 100);
    -    }, 0, 0, 100, 100);
    -    assertFalse(el.isParentDependent());
    -  }
    -
    -  function testSizePercent() {
    -    assertPosition(function() {
    -      el.setSize('10%', '20%');
    -    }, 0, 0, 20, 40);
    -    assertTrue(el.isParentDependent());
    -  }
    -</script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/ext/ellipse.js b/src/database/third_party/closure-library/closure/goog/graphics/ext/ellipse.js
    deleted file mode 100644
    index db77524a025..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/ext/ellipse.js
    +++ /dev/null
    @@ -1,60 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview A thick wrapper around ellipses.
    - * @author robbyw@google.com (Robby Walker)
    - */
    -
    -
    -goog.provide('goog.graphics.ext.Ellipse');
    -
    -goog.require('goog.graphics.ext.StrokeAndFillElement');
    -
    -
    -
    -/**
    - * Wrapper for a graphics ellipse element.
    - * @param {goog.graphics.ext.Group} group Parent for this element.
    - * @constructor
    - * @extends {goog.graphics.ext.StrokeAndFillElement}
    - * @final
    - */
    -goog.graphics.ext.Ellipse = function(group) {
    -  // Initialize with some stock values.
    -  var wrapper = group.getGraphicsImplementation().drawEllipse(1, 1, 2, 2, null,
    -      null, group.getWrapper());
    -  goog.graphics.ext.StrokeAndFillElement.call(this, group, wrapper);
    -};
    -goog.inherits(goog.graphics.ext.Ellipse,
    -              goog.graphics.ext.StrokeAndFillElement);
    -
    -
    -/**
    - * Redraw the ellipse.  Called when the coordinate system is changed.
    - * @protected
    - * @override
    - */
    -goog.graphics.ext.Ellipse.prototype.redraw = function() {
    -  goog.graphics.ext.Ellipse.superClass_.redraw.call(this);
    -
    -  // Our position is already transformed in transform_, but because this is an
    -  // ellipse we need to position the center.
    -  var xRadius = this.getWidth() / 2;
    -  var yRadius = this.getHeight() / 2;
    -  var wrapper = this.getWrapper();
    -  wrapper.setCenter(xRadius, yRadius);
    -  wrapper.setRadius(xRadius, yRadius);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/ext/ext.js b/src/database/third_party/closure-library/closure/goog/graphics/ext/ext.js
    deleted file mode 100644
    index c991b48731d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/ext/ext.js
    +++ /dev/null
    @@ -1,29 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Extended graphics namespace.
    - */
    -
    -
    -goog.provide('goog.graphics.ext');
    -
    -goog.require('goog.graphics.ext.Ellipse');
    -goog.require('goog.graphics.ext.Graphics');
    -goog.require('goog.graphics.ext.Group');
    -goog.require('goog.graphics.ext.Image');
    -goog.require('goog.graphics.ext.Rectangle');
    -goog.require('goog.graphics.ext.Shape');
    -goog.require('goog.graphics.ext.coordinates');
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/ext/graphics.js b/src/database/third_party/closure-library/closure/goog/graphics/ext/graphics.js
    deleted file mode 100644
    index a3c1a545175..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/ext/graphics.js
    +++ /dev/null
    @@ -1,218 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Graphics surface type.
    - * @author robbyw@google.com (Robby Walker)
    - */
    -
    -
    -goog.provide('goog.graphics.ext.Graphics');
    -
    -goog.require('goog.events');
    -goog.require('goog.events.EventType');
    -goog.require('goog.graphics');
    -goog.require('goog.graphics.ext.Group');
    -
    -
    -
    -/**
    - * Wrapper for a graphics surface.
    - * @param {string|number} width The width in pixels.  Strings
    - *     expressing percentages of parent with (e.g. '80%') are also accepted.
    - * @param {string|number} height The height in pixels.  Strings
    - *     expressing percentages of parent with (e.g. '80%') are also accepted.
    - * @param {?number=} opt_coordWidth The coordinate width - if
    - *     omitted or null, defaults to same as width.
    - * @param {?number=} opt_coordHeight The coordinate height. - if
    - *     omitted or null, defaults to same as height.
    - * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper object for the
    - *     document we want to render in.
    - * @param {boolean=} opt_isSimple Flag used to indicate the graphics object will
    - *     be drawn to in a single pass, and the fastest implementation for this
    - *     scenario should be favored.  NOTE: Setting to true may result in
    - *     degradation of text support.
    - * @constructor
    - * @extends {goog.graphics.ext.Group}
    - * @final
    - */
    -goog.graphics.ext.Graphics = function(width, height, opt_coordWidth,
    -    opt_coordHeight, opt_domHelper, opt_isSimple) {
    -  var surface = opt_isSimple ?
    -      goog.graphics.createSimpleGraphics(width, height,
    -          opt_coordWidth, opt_coordHeight, opt_domHelper) :
    -      goog.graphics.createGraphics(width, height,
    -          opt_coordWidth, opt_coordHeight, opt_domHelper);
    -  this.implementation_ = surface;
    -
    -  goog.graphics.ext.Group.call(this, null, surface.getCanvasElement());
    -
    -  goog.events.listen(surface, goog.events.EventType.RESIZE,
    -      this.updateChildren, false, this);
    -};
    -goog.inherits(goog.graphics.ext.Graphics, goog.graphics.ext.Group);
    -
    -
    -/**
    - * The root level graphics implementation.
    - * @type {goog.graphics.AbstractGraphics}
    - * @private
    - */
    -goog.graphics.ext.Graphics.prototype.implementation_;
    -
    -
    -/**
    - * @return {goog.graphics.AbstractGraphics} The graphics implementation layer.
    - */
    -goog.graphics.ext.Graphics.prototype.getImplementation = function() {
    -  return this.implementation_;
    -};
    -
    -
    -/**
    - * Changes the coordinate size.
    - * @param {number} coordWidth The coordinate width.
    - * @param {number} coordHeight The coordinate height.
    - */
    -goog.graphics.ext.Graphics.prototype.setCoordSize = function(coordWidth,
    -                                                             coordHeight) {
    -  this.implementation_.setCoordSize(coordWidth, coordHeight);
    -  goog.graphics.ext.Graphics.superClass_.setSize.call(this, coordWidth,
    -      coordHeight);
    -};
    -
    -
    -/**
    - * @return {goog.math.Size} The coordinate size.
    - */
    -goog.graphics.ext.Graphics.prototype.getCoordSize = function() {
    -  return this.implementation_.getCoordSize();
    -};
    -
    -
    -/**
    - * Changes the coordinate system position.
    - * @param {number} left The coordinate system left bound.
    - * @param {number} top The coordinate system top bound.
    - */
    -goog.graphics.ext.Graphics.prototype.setCoordOrigin = function(left, top) {
    -  this.implementation_.setCoordOrigin(left, top);
    -};
    -
    -
    -/**
    - * @return {!goog.math.Coordinate} The coordinate system position.
    - */
    -goog.graphics.ext.Graphics.prototype.getCoordOrigin = function() {
    -  return this.implementation_.getCoordOrigin();
    -};
    -
    -
    -/**
    - * Change the size of the canvas.
    - * @param {number} pixelWidth The width in pixels.
    - * @param {number} pixelHeight The height in pixels.
    - */
    -goog.graphics.ext.Graphics.prototype.setPixelSize = function(pixelWidth,
    -                                                        pixelHeight) {
    -  this.implementation_.setSize(pixelWidth, pixelHeight);
    -
    -  var coordSize = this.getCoordSize();
    -  goog.graphics.ext.Graphics.superClass_.setSize.call(this, coordSize.width,
    -      coordSize.height);
    -};
    -
    -
    -/**
    - * @return {goog.math.Size?} Returns the number of pixels spanned by the
    - *     surface, or null if the size could not be computed due to the size being
    - *     specified in percentage points and the component not being in the
    - *     document.
    - */
    -goog.graphics.ext.Graphics.prototype.getPixelSize = function() {
    -  return this.implementation_.getPixelSize();
    -};
    -
    -
    -/**
    - * @return {number} The coordinate width of the canvas.
    - * @override
    - */
    -goog.graphics.ext.Graphics.prototype.getWidth = function() {
    -  return this.implementation_.getCoordSize().width;
    -};
    -
    -
    -/**
    - * @return {number} The coordinate width of the canvas.
    - * @override
    - */
    -goog.graphics.ext.Graphics.prototype.getHeight = function() {
    -  return this.implementation_.getCoordSize().height;
    -};
    -
    -
    -/**
    - * @return {number} Returns the number of pixels per unit in the x direction.
    - * @override
    - */
    -goog.graphics.ext.Graphics.prototype.getPixelScaleX = function() {
    -  return this.implementation_.getPixelScaleX();
    -};
    -
    -
    -/**
    - * @return {number} Returns the number of pixels per unit in the y direction.
    - * @override
    - */
    -goog.graphics.ext.Graphics.prototype.getPixelScaleY = function() {
    -  return this.implementation_.getPixelScaleY();
    -};
    -
    -
    -/**
    - * @return {Element} The root element of the graphics surface.
    - */
    -goog.graphics.ext.Graphics.prototype.getElement = function() {
    -  return this.implementation_.getElement();
    -};
    -
    -
    -/**
    - * Renders the underlying graphics.
    - *
    - * @param {Element} parentElement Parent element to render the component into.
    - */
    -goog.graphics.ext.Graphics.prototype.render = function(parentElement) {
    -  this.implementation_.render(parentElement);
    -};
    -
    -
    -/**
    - * Never transform a surface.
    - * @override
    - */
    -goog.graphics.ext.Graphics.prototype.transform = goog.nullFunction;
    -
    -
    -/**
    - * Called from the parent class, this method resets any pre-computed positions
    - * and sizes.
    - * @protected
    - * @override
    - */
    -goog.graphics.ext.Graphics.prototype.redraw = function() {
    -  this.transformChildren();
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/ext/group.js b/src/database/third_party/closure-library/closure/goog/graphics/ext/group.js
    deleted file mode 100644
    index 03479ad4bcf..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/ext/group.js
    +++ /dev/null
    @@ -1,216 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview A thicker wrapper around graphics groups.
    - * @author robbyw@google.com (Robby Walker)
    - */
    -
    -
    -goog.provide('goog.graphics.ext.Group');
    -
    -goog.require('goog.array');
    -goog.require('goog.graphics.ext.Element');
    -
    -
    -
    -/**
    - * Wrapper for a graphics group.
    - * @param {goog.graphics.ext.Group} group Parent for this element. Can
    - *     be null if this is a Graphics instance.
    - * @param {goog.graphics.GroupElement=} opt_wrapper The thin wrapper
    - *     to wrap. If omitted, a new group will be created. Must be included
    - *     when group is null.
    - * @constructor
    - * @extends {goog.graphics.ext.Element}
    - */
    -goog.graphics.ext.Group = function(group, opt_wrapper) {
    -  opt_wrapper = opt_wrapper || group.getGraphicsImplementation().createGroup(
    -      group.getWrapper());
    -  goog.graphics.ext.Element.call(this, group, opt_wrapper);
    -
    -  /**
    -   * Array of child elements this group contains.
    -   * @type {Array<goog.graphics.ext.Element>}
    -   * @private
    -   */
    -  this.children_ = [];
    -};
    -goog.inherits(goog.graphics.ext.Group, goog.graphics.ext.Element);
    -
    -
    -/**
    - * Add an element to the group.  This should be treated as package local, as
    - * it is called by the draw* methods.
    - * @param {!goog.graphics.ext.Element} element The element to add.
    - * @param {boolean=} opt_chain Whether this addition is part of a longer set
    - *     of element additions.
    - */
    -goog.graphics.ext.Group.prototype.addChild = function(element, opt_chain) {
    -  if (!goog.array.contains(this.children_, element)) {
    -    this.children_.push(element);
    -  }
    -
    -  var transformed = this.growToFit_(element);
    -
    -  if (element.isParentDependent()) {
    -    element.parentTransform();
    -  }
    -
    -  if (!opt_chain && element.isPendingTransform()) {
    -    element.reset();
    -  }
    -
    -  if (transformed) {
    -    this.reset();
    -  }
    -};
    -
    -
    -/**
    - * Remove an element from the group.
    - * @param {goog.graphics.ext.Element} element The element to remove.
    - */
    -goog.graphics.ext.Group.prototype.removeChild = function(element) {
    -  goog.array.remove(this.children_, element);
    -
    -  // TODO(robbyw): shape.fireEvent('delete')
    -
    -  this.getGraphicsImplementation().removeElement(element.getWrapper());
    -};
    -
    -
    -/**
    - * Calls the given function on each of this component's children in order.  If
    - * {@code opt_obj} is provided, it will be used as the 'this' object in the
    - * function when called.  The function should take two arguments:  the child
    - * component and its 0-based index.  The return value is ignored.
    - * @param {Function} f The function to call for every child component; should
    - *    take 2 arguments (the child and its index).
    - * @param {Object=} opt_obj Used as the 'this' object in f when called.
    - */
    -goog.graphics.ext.Group.prototype.forEachChild = function(f, opt_obj) {
    -  if (this.children_) {
    -    goog.array.forEach(this.children_, f, opt_obj);
    -  }
    -};
    -
    -
    -/**
    - * @return {goog.graphics.GroupElement} The underlying thin wrapper.
    - * @override
    - */
    -goog.graphics.ext.Group.prototype.getWrapper;
    -
    -
    -/**
    - * Reset the element.
    - * @override
    - */
    -goog.graphics.ext.Group.prototype.reset = function() {
    -  goog.graphics.ext.Group.superClass_.reset.call(this);
    -
    -  this.updateChildren();
    -};
    -
    -
    -/**
    - * Called from the parent class, this method resets any pre-computed positions
    - * and sizes.
    - * @protected
    - * @override
    - */
    -goog.graphics.ext.Group.prototype.redraw = function() {
    -  this.getWrapper().setSize(this.getWidth(), this.getHeight());
    -  this.transformChildren();
    -};
    -
    -
    -/**
    - * Transform the children that need to be transformed.
    - * @protected
    - */
    -goog.graphics.ext.Group.prototype.transformChildren = function() {
    -  this.forEachChild(function(child) {
    -    if (child.isParentDependent()) {
    -      child.parentTransform();
    -    }
    -  });
    -};
    -
    -
    -/**
    - * As part of the reset process, update child elements.
    - */
    -goog.graphics.ext.Group.prototype.updateChildren = function() {
    -  this.forEachChild(function(child) {
    -    if (child.isParentDependent() || child.isPendingTransform()) {
    -      child.reset();
    -    } else if (child.updateChildren) {
    -      child.updateChildren();
    -    }
    -  });
    -};
    -
    -
    -/**
    - * When adding an element, grow this group's bounds to fit it.
    - * @param {!goog.graphics.ext.Element} element The added element.
    - * @return {boolean} Whether the size of this group changed.
    - * @private
    - */
    -goog.graphics.ext.Group.prototype.growToFit_ = function(element) {
    -  var transformed = false;
    -
    -  var x = element.getMaxX();
    -  if (x > this.getWidth()) {
    -    this.setMinWidth(x);
    -    transformed = true;
    -  }
    -
    -  var y = element.getMaxY();
    -  if (y > this.getHeight()) {
    -    this.setMinHeight(y);
    -    transformed = true;
    -  }
    -
    -  return transformed;
    -};
    -
    -
    -/**
    - * @return {number} The width of the element's coordinate space.
    - */
    -goog.graphics.ext.Group.prototype.getCoordinateWidth = function() {
    -  return this.getWidth();
    -};
    -
    -
    -/**
    - * @return {number} The height of the element's coordinate space.
    - */
    -goog.graphics.ext.Group.prototype.getCoordinateHeight = function() {
    -  return this.getHeight();
    -};
    -
    -
    -/**
    - * Remove all drawing elements from the group.
    - */
    -goog.graphics.ext.Group.prototype.clear = function() {
    -  while (this.children_.length) {
    -    this.removeChild(this.children_[0]);
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/ext/image.js b/src/database/third_party/closure-library/closure/goog/graphics/ext/image.js
    deleted file mode 100644
    index ec24e1d85ee..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/ext/image.js
    +++ /dev/null
    @@ -1,64 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview A thick wrapper around images.
    - * @author robbyw@google.com (Robby Walker)
    - */
    -
    -
    -goog.provide('goog.graphics.ext.Image');
    -
    -goog.require('goog.graphics.ext.Element');
    -
    -
    -
    -/**
    - * Wrapper for a graphics image element.
    - * @param {goog.graphics.ext.Group} group Parent for this element.
    - * @param {string} src The path to the image to display.
    - * @constructor
    - * @extends {goog.graphics.ext.Element}
    - * @final
    - */
    -goog.graphics.ext.Image = function(group, src) {
    -  // Initialize with some stock values.
    -  var wrapper = group.getGraphicsImplementation().drawImage(0, 0, 1, 1, src,
    -      group.getWrapper());
    -  goog.graphics.ext.Element.call(this, group, wrapper);
    -};
    -goog.inherits(goog.graphics.ext.Image, goog.graphics.ext.Element);
    -
    -
    -/**
    - * Redraw the image.  Called when the coordinate system is changed.
    - * @protected
    - * @override
    - */
    -goog.graphics.ext.Image.prototype.redraw = function() {
    -  goog.graphics.ext.Image.superClass_.redraw.call(this);
    -
    -  // Our position is already handled bu transform_.
    -  this.getWrapper().setSize(this.getWidth(), this.getHeight());
    -};
    -
    -
    -/**
    - * Update the source of the image.
    - * @param {string} src  Source of the image.
    - */
    -goog.graphics.ext.Image.prototype.setSource = function(src) {
    -  this.getWrapper().setSource(src);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/ext/path.js b/src/database/third_party/closure-library/closure/goog/graphics/ext/path.js
    deleted file mode 100644
    index de550aa497b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/ext/path.js
    +++ /dev/null
    @@ -1,142 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview A thick wrapper around paths.
    - * @author robbyw@google.com (Robby Walker)
    - */
    -
    -
    -goog.provide('goog.graphics.ext.Path');
    -
    -goog.require('goog.graphics.AffineTransform');
    -goog.require('goog.graphics.Path');
    -goog.require('goog.math.Rect');
    -
    -
    -
    -/**
    - * Creates a path object
    - * @constructor
    - * @extends {goog.graphics.Path}
    - * @final
    - */
    -goog.graphics.ext.Path = function() {
    -  goog.graphics.Path.call(this);
    -};
    -goog.inherits(goog.graphics.ext.Path, goog.graphics.Path);
    -
    -
    -/**
    - * Optional cached or user specified bounding box.  A user may wish to
    - * precompute a bounding box to save time and include more accurate
    - * computations.
    - * @type {goog.math.Rect?}
    - * @private
    - */
    -goog.graphics.ext.Path.prototype.bounds_ = null;
    -
    -
    -/**
    - * Clones the path.
    - * @return {!goog.graphics.ext.Path} A clone of this path.
    - * @override
    - */
    -goog.graphics.ext.Path.prototype.clone = function() {
    -  var output = /** @type {goog.graphics.ext.Path} */
    -      (goog.graphics.ext.Path.superClass_.clone.call(this));
    -  output.bounds_ = this.bounds_ && this.bounds_.clone();
    -  return output;
    -};
    -
    -
    -/**
    - * Transforms the path. Only simple paths are transformable. Attempting
    - * to transform a non-simple path will throw an error.
    - * @param {!goog.graphics.AffineTransform} tx The transformation to perform.
    - * @return {!goog.graphics.ext.Path} The path itself.
    - * @override
    - */
    -goog.graphics.ext.Path.prototype.transform = function(tx) {
    -  goog.graphics.ext.Path.superClass_.transform.call(this, tx);
    -
    -  // Make sure the precomputed bounds are cleared when the path is transformed.
    -  this.bounds_ = null;
    -
    -  return this;
    -};
    -
    -
    -/**
    - * Modify the bounding box of the path.  This may cause the path to be
    - * simplified (i.e. arcs converted to curves) as a side-effect.
    - * @param {number} deltaX How far to translate the x coordinates.
    - * @param {number} deltaY How far to translate the y coordinates.
    - * @param {number} xFactor After translation, all x coordinates are multiplied
    - *     by this number.
    - * @param {number} yFactor After translation, all y coordinates are multiplied
    - *     by this number.
    - * @return {!goog.graphics.ext.Path} The path itself.
    - */
    -goog.graphics.ext.Path.prototype.modifyBounds = function(deltaX, deltaY,
    -    xFactor, yFactor) {
    -  if (!this.isSimple()) {
    -    var simple = goog.graphics.Path.createSimplifiedPath(this);
    -    this.clear();
    -    this.appendPath(simple);
    -  }
    -
    -  return this.transform(goog.graphics.AffineTransform.getScaleInstance(
    -      xFactor, yFactor).translate(deltaX, deltaY));
    -};
    -
    -
    -/**
    - * Set the precomputed bounds.
    - * @param {goog.math.Rect?} bounds The bounds to use, or set to null to clear
    - *     and recompute on the next call to getBoundingBox.
    - */
    -goog.graphics.ext.Path.prototype.useBoundingBox = function(bounds) {
    -  this.bounds_ = bounds && bounds.clone();
    -};
    -
    -
    -/**
    - * @return {goog.math.Rect?} The bounding box of the path, or null if the
    - *     path is empty.
    - */
    -goog.graphics.ext.Path.prototype.getBoundingBox = function() {
    -  if (!this.bounds_ && !this.isEmpty()) {
    -    var minY;
    -    var minX = minY = Number.POSITIVE_INFINITY;
    -    var maxY;
    -    var maxX = maxY = Number.NEGATIVE_INFINITY;
    -
    -    var simplePath = this.isSimple() ? this :
    -        goog.graphics.Path.createSimplifiedPath(this);
    -    simplePath.forEachSegment(function(type, points) {
    -      for (var i = 0, len = points.length; i < len; i += 2) {
    -        minX = Math.min(minX, points[i]);
    -        maxX = Math.max(maxX, points[i]);
    -        minY = Math.min(minY, points[i + 1]);
    -        maxY = Math.max(maxY, points[i + 1]);
    -      }
    -    });
    -
    -    this.bounds_ = new goog.math.Rect(minX, minY, maxX - minX, maxY - minY);
    -  }
    -
    -  return this.bounds_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/ext/path_test.html b/src/database/third_party/closure-library/closure/goog/graphics/ext/path_test.html
    deleted file mode 100644
    index 61dc55ce891..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/ext/path_test.html
    +++ /dev/null
    @@ -1,46 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.graphics.ext.Path</title>
    -<script src="../../base.js"></script>
    -<script>
    -  goog.require('goog.graphics');
    -  goog.require('goog.graphics.ext.Path');
    -  goog.require('goog.testing.graphics');
    -  goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -
    -<script>
    -  function testClone() {
    -    var path = new goog.graphics.ext.Path().moveTo(0, 0).lineTo(1, 1).
    -        curveTo(2, 2, 3, 3, 4, 4).arc(5, 5, 6, 6, 0, 90, false).close();
    -    assertTrue('Cloned path is a goog.graphics.ext.Path',
    -        path instanceof goog.graphics.ext.Path);
    -  }
    -
    -  function testBoundingBox() {
    -    var path = new goog.graphics.ext.Path().moveTo(0, 0).lineTo(1, 1).
    -        curveTo(2, 2, 3, 3, 4, 4).close();
    -    assertTrue('Bounding box is correct', goog.math.Rect.equals(
    -        path.getBoundingBox(), new goog.math.Rect(0, 0, 4, 4)));
    -  }
    -
    -  function testModifyBounds() {
    -    var path1 = new goog.graphics.ext.Path().moveTo(0, 0).lineTo(1, 1).
    -        curveTo(2, 2, 3, 3, 4, 4).close();
    -    goog.testing.graphics.assertPathEquals(
    -        ['M', -2, -2, 'L', 0, 0, 'C', 2, 2, 4, 4, 6, 6, 'X'],
    -        path1.modifyBounds(-1, -1, 2, 2));
    -  }
    -</script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/ext/rectangle.js b/src/database/third_party/closure-library/closure/goog/graphics/ext/rectangle.js
    deleted file mode 100644
    index d05c8b1bda0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/ext/rectangle.js
    +++ /dev/null
    @@ -1,55 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview A thick wrapper around rectangles.
    - * @author robbyw@google.com (Robby Walker)
    - */
    -
    -
    -goog.provide('goog.graphics.ext.Rectangle');
    -
    -goog.require('goog.graphics.ext.StrokeAndFillElement');
    -
    -
    -
    -/**
    - * Wrapper for a graphics rectangle element.
    - * @param {goog.graphics.ext.Group} group Parent for this element.
    - * @constructor
    - * @extends {goog.graphics.ext.StrokeAndFillElement}
    - * @final
    - */
    -goog.graphics.ext.Rectangle = function(group) {
    -  // Initialize with some stock values.
    -  var wrapper = group.getGraphicsImplementation().drawRect(0, 0, 1, 1, null,
    -      null, group.getWrapper());
    -  goog.graphics.ext.StrokeAndFillElement.call(this, group, wrapper);
    -};
    -goog.inherits(goog.graphics.ext.Rectangle,
    -              goog.graphics.ext.StrokeAndFillElement);
    -
    -
    -/**
    - * Redraw the rectangle.  Called when the coordinate system is changed.
    - * @protected
    - * @override
    - */
    -goog.graphics.ext.Rectangle.prototype.redraw = function() {
    -  goog.graphics.ext.Rectangle.superClass_.redraw.call(this);
    -
    -  // Our position is already handled by transform_.
    -  this.getWrapper().setSize(this.getWidth(), this.getHeight());
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/ext/shape.js b/src/database/third_party/closure-library/closure/goog/graphics/ext/shape.js
    deleted file mode 100644
    index 3f80e822279..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/ext/shape.js
    +++ /dev/null
    @@ -1,145 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview A thick wrapper around shapes with custom paths.
    - * @author robbyw@google.com (Robby Walker)
    - */
    -
    -
    -goog.provide('goog.graphics.ext.Shape');
    -
    -goog.require('goog.graphics.ext.StrokeAndFillElement');
    -
    -
    -
    -/**
    - * Wrapper for a graphics shape element.
    - * @param {goog.graphics.ext.Group} group Parent for this element.
    - * @param {!goog.graphics.ext.Path} path  The path to draw.
    - * @param {boolean=} opt_autoSize Optional flag to specify the path should
    - *     automatically resize to fit the element.  Defaults to false.
    - * @constructor
    - * @extends {goog.graphics.ext.StrokeAndFillElement}
    - * @final
    - */
    -goog.graphics.ext.Shape = function(group, path, opt_autoSize) {
    -  this.autoSize_ = !!opt_autoSize;
    -
    -  var graphics = group.getGraphicsImplementation();
    -  var wrapper = graphics.drawPath(path, null, null,
    -      group.getWrapper());
    -  goog.graphics.ext.StrokeAndFillElement.call(this, group, wrapper);
    -  this.setPath(path);
    -};
    -goog.inherits(goog.graphics.ext.Shape, goog.graphics.ext.StrokeAndFillElement);
    -
    -
    -/**
    - * Whether or not to automatically resize the shape's path when the element
    - * itself is resized.
    - * @type {boolean}
    - * @private
    - */
    -goog.graphics.ext.Shape.prototype.autoSize_ = false;
    -
    -
    -/**
    - * The original path, specified by the caller.
    - * @type {goog.graphics.Path}
    - * @private
    - */
    -goog.graphics.ext.Shape.prototype.path_;
    -
    -
    -/**
    - * The bounding box of the original path.
    - * @type {goog.math.Rect?}
    - * @private
    - */
    -goog.graphics.ext.Shape.prototype.boundingBox_ = null;
    -
    -
    -/**
    - * The scaled path.
    - * @type {goog.graphics.Path}
    - * @private
    - */
    -goog.graphics.ext.Shape.prototype.scaledPath_;
    -
    -
    -/**
    - * Get the path drawn by this shape.
    - * @return {goog.graphics.Path?} The path drawn by this shape.
    - */
    -goog.graphics.ext.Shape.prototype.getPath = function() {
    -  return this.path_;
    -};
    -
    -
    -/**
    - * Set the path to draw.
    - * @param {goog.graphics.ext.Path} path The path to draw.
    - */
    -goog.graphics.ext.Shape.prototype.setPath = function(path) {
    -  this.path_ = path;
    -
    -  if (this.autoSize_) {
    -    this.boundingBox_ = path.getBoundingBox();
    -  }
    -
    -  this.scaleAndSetPath_();
    -};
    -
    -
    -/**
    - * Scale the internal path to fit.
    - * @private
    - */
    -goog.graphics.ext.Shape.prototype.scaleAndSetPath_ = function() {
    -  this.scaledPath_ = this.boundingBox_ ? this.path_.clone().modifyBounds(
    -      -this.boundingBox_.left, -this.boundingBox_.top,
    -      this.getWidth() / (this.boundingBox_.width || 1),
    -      this.getHeight() / (this.boundingBox_.height || 1)) : this.path_;
    -
    -  var wrapper = this.getWrapper();
    -  if (wrapper) {
    -    wrapper.setPath(this.scaledPath_);
    -  }
    -};
    -
    -
    -/**
    - * Redraw the ellipse.  Called when the coordinate system is changed.
    - * @protected
    - * @override
    - */
    -goog.graphics.ext.Shape.prototype.redraw = function() {
    -  goog.graphics.ext.Shape.superClass_.redraw.call(this);
    -  if (this.autoSize_) {
    -    this.scaleAndSetPath_();
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the shape is parent dependent.
    - * @protected
    - * @override
    - */
    -goog.graphics.ext.Shape.prototype.checkParentDependent = function() {
    -  return this.autoSize_ ||
    -      goog.graphics.ext.Shape.superClass_.checkParentDependent.call(this);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/ext/strokeandfillelement.js b/src/database/third_party/closure-library/closure/goog/graphics/ext/strokeandfillelement.js
    deleted file mode 100644
    index 4ad69f316ab..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/ext/strokeandfillelement.js
    +++ /dev/null
    @@ -1,70 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview A thick wrapper around elements with stroke and fill.
    - * @author robbyw@google.com (Robby Walker)
    - */
    -
    -
    -goog.provide('goog.graphics.ext.StrokeAndFillElement');
    -
    -goog.require('goog.graphics.ext.Element');
    -
    -
    -
    -/**
    - * Interface for a graphics element that has a stroke and fill.
    - * This is the base interface for ellipse, rectangle and other
    - * shape interfaces.
    - * You should not construct objects from this constructor. Use a subclass.
    - * @param {goog.graphics.ext.Group} group Parent for this element.
    - * @param {goog.graphics.StrokeAndFillElement} wrapper The thin wrapper to wrap.
    - * @constructor
    - * @extends {goog.graphics.ext.Element}
    - */
    -goog.graphics.ext.StrokeAndFillElement = function(group, wrapper) {
    -  goog.graphics.ext.Element.call(this, group, wrapper);
    -};
    -goog.inherits(goog.graphics.ext.StrokeAndFillElement,
    -    goog.graphics.ext.Element);
    -
    -
    -/**
    - * Sets the fill for this element.
    - * @param {goog.graphics.Fill?} fill The fill object.
    - */
    -goog.graphics.ext.StrokeAndFillElement.prototype.setFill = function(fill) {
    -  this.getWrapper().setFill(fill);
    -};
    -
    -
    -/**
    - * Sets the stroke for this element.
    - * @param {goog.graphics.Stroke?} stroke The stroke object.
    - */
    -goog.graphics.ext.StrokeAndFillElement.prototype.setStroke = function(stroke) {
    -  this.getWrapper().setStroke(stroke);
    -};
    -
    -
    -/**
    - * Redraw the rectangle.  Called when the coordinate system is changed.
    - * @protected
    - * @override
    - */
    -goog.graphics.ext.StrokeAndFillElement.prototype.redraw = function() {
    -  this.getWrapper().reapplyStroke();
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/fill.js b/src/database/third_party/closure-library/closure/goog/graphics/fill.js
    deleted file mode 100644
    index 92e460e253f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/fill.js
    +++ /dev/null
    @@ -1,46 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Represents a fill goog.graphics.
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -
    -goog.provide('goog.graphics.Fill');
    -
    -
    -
    -/**
    - * Creates a fill object
    - * @constructor
    - * @deprecated goog.graphics is deprecated. It existed to abstract over browser
    - *     differences before the canvas tag was widely supported.  See
    - *     http://en.wikipedia.org/wiki/Canvas_element for details.
    - */
    -goog.graphics.Fill = function() {};
    -
    -
    -/**
    - * @return {string} The start color of a gradient fill.
    - */
    -goog.graphics.Fill.prototype.getColor1 = goog.abstractMethod;
    -
    -
    -/**
    - * @return {string} The end color of a gradient fill.
    - */
    -goog.graphics.Fill.prototype.getColor2 = goog.abstractMethod;
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/font.js b/src/database/third_party/closure-library/closure/goog/graphics/font.js
    deleted file mode 100644
    index f58bf41ad0e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/font.js
    +++ /dev/null
    @@ -1,64 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Represents a font to be used with a Renderer.
    - * @author arv@google.com (Erik Arvidsson)
    - * @see ../demos/graphics/basicelements.html
    - */
    -
    -
    -goog.provide('goog.graphics.Font');
    -
    -
    -
    -/**
    - * This class represents a font to be used with a renderer.
    - * @param {number} size  The font size.
    - * @param {string} family  The font family.
    - * @constructor
    - * @deprecated goog.graphics is deprecated. It existed to abstract over browser
    - *     differences before the canvas tag was widely supported.  See
    - *     http://en.wikipedia.org/wiki/Canvas_element for details.
    - * @final
    - */
    -goog.graphics.Font = function(size, family) {
    -  /**
    -   * Font size.
    -   * @type {number}
    -   */
    -  this.size = size;
    -  // TODO(arv): Is this in pixels or drawing units based on the coord size?
    -
    -  /**
    -   * The name of the font family to use, can be a comma separated string.
    -   * @type {string}
    -   */
    -  this.family = family;
    -};
    -
    -
    -/**
    - * Indication if text should be bolded
    - * @type {boolean}
    - */
    -goog.graphics.Font.prototype.bold = false;
    -
    -
    -/**
    - * Indication if text should be in italics
    - * @type {boolean}
    - */
    -goog.graphics.Font.prototype.italic = false;
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/graphics.js b/src/database/third_party/closure-library/closure/goog/graphics/graphics.js
    deleted file mode 100644
    index 0bde5b5b3d5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/graphics.js
    +++ /dev/null
    @@ -1,142 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Graphics utility functions and factory methods.
    - * @author arv@google.com (Erik Arvidsson)
    - * @see ../demos/graphics/advancedcoordinates.html
    - * @see ../demos/graphics/advancedcoordinates2.html
    - * @see ../demos/graphics/basicelements.html
    - * @see ../demos/graphics/events.html
    - * @see ../demos/graphics/modifyelements.html
    - * @see ../demos/graphics/tiger.html
    - */
    -
    -
    -goog.provide('goog.graphics');
    -
    -goog.require('goog.dom');
    -goog.require('goog.graphics.CanvasGraphics');
    -goog.require('goog.graphics.SvgGraphics');
    -goog.require('goog.graphics.VmlGraphics');
    -goog.require('goog.userAgent');
    -
    -
    -/**
    - * Returns an instance of goog.graphics.AbstractGraphics that knows how to draw
    - * for the current platform (A factory for the proper Graphics implementation)
    - * @param {string|number} width The width in pixels.  Strings
    - *     expressing percentages of parent with (e.g. '80%') are also accepted.
    - * @param {string|number} height The height in pixels.  Strings
    - *     expressing percentages of parent with (e.g. '80%') are also accepted.
    - * @param {?number=} opt_coordWidth The optional coordinate width - if
    - *     omitted or null, defaults to same as width.
    - * @param {?number=} opt_coordHeight The optional coordinate height - if
    - *     omitted or null, defaults to same as height.
    - * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper object for the
    - *     document we want to render in.
    - * @return {!goog.graphics.AbstractGraphics} The created instance.
    - * @deprecated goog.graphics is deprecated. It existed to abstract over browser
    - *     differences before the canvas tag was widely supported.  See
    - *     http://en.wikipedia.org/wiki/Canvas_element for details.
    - */
    -goog.graphics.createGraphics = function(width, height, opt_coordWidth,
    -    opt_coordHeight, opt_domHelper) {
    -  var graphics;
    -  // On IE9 and above, SVG is available, except in compatibility mode.
    -  // We check createElementNS on document object that is not exist in
    -  // compatibility mode.
    -  if (goog.userAgent.IE &&
    -      (!goog.userAgent.isVersionOrHigher('9') ||
    -       !(opt_domHelper || goog.dom.getDomHelper()).
    -           getDocument().createElementNS)) {
    -    graphics = new goog.graphics.VmlGraphics(width, height,
    -        opt_coordWidth, opt_coordHeight, opt_domHelper);
    -  } else if (goog.userAgent.WEBKIT &&
    -             (!goog.userAgent.isVersionOrHigher('420') ||
    -              goog.userAgent.MOBILE)) {
    -    graphics = new goog.graphics.CanvasGraphics(width, height,
    -        opt_coordWidth, opt_coordHeight, opt_domHelper);
    -  } else {
    -    graphics = new goog.graphics.SvgGraphics(width, height,
    -        opt_coordWidth, opt_coordHeight, opt_domHelper);
    -  }
    -
    -  // Create the dom now, because all drawing methods require that the
    -  // main dom element (the canvas) has been already created.
    -  graphics.createDom();
    -
    -  return graphics;
    -};
    -
    -
    -/**
    - * Returns an instance of goog.graphics.AbstractGraphics that knows how to draw
    - * for the current platform (A factory for the proper Graphics implementation)
    - * @param {string|number} width The width in pixels.  Strings
    - *     expressing percentages of parent with (e.g. '80%') are also accepted.
    - * @param {string|number} height The height in pixels.   Strings
    - *     expressing percentages of parent with (e.g. '80%') are also accepted.
    - * @param {?number=} opt_coordWidth The optional coordinate width, defaults to
    - *     same as width.
    - * @param {?number=} opt_coordHeight The optional coordinate height, defaults to
    - *     same as height.
    - * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper object for the
    - *     document we want to render in.
    - * @return {!goog.graphics.AbstractGraphics} The created instance.
    - * @deprecated goog.graphics is deprecated. It existed to abstract over browser
    - *     differences before the canvas tag was widely supported.  See
    - *     http://en.wikipedia.org/wiki/Canvas_element for details.
    - */
    -goog.graphics.createSimpleGraphics = function(width, height,
    -    opt_coordWidth, opt_coordHeight, opt_domHelper) {
    -  if (goog.userAgent.MAC && goog.userAgent.GECKO &&
    -      !goog.userAgent.isVersionOrHigher('1.9a')) {
    -    // Canvas is 6x faster than SVG on Mac FF 2.0
    -    var graphics = new goog.graphics.CanvasGraphics(
    -        width, height, opt_coordWidth, opt_coordHeight,
    -        opt_domHelper);
    -    graphics.createDom();
    -    return graphics;
    -  }
    -
    -  // Otherwise, defer to normal graphics object creation.
    -  return goog.graphics.createGraphics(width, height, opt_coordWidth,
    -      opt_coordHeight, opt_domHelper);
    -};
    -
    -
    -/**
    - * Static function to check if the current browser has Graphics support.
    - * @return {boolean} True if the current browser has Graphics support.
    - * @deprecated goog.graphics is deprecated. It existed to abstract over browser
    - *     differences before the canvas tag was widely supported.  See
    - *     http://en.wikipedia.org/wiki/Canvas_element for details.
    - */
    -goog.graphics.isBrowserSupported = function() {
    -  if (goog.userAgent.IE) {
    -    return goog.userAgent.isVersionOrHigher('5.5');
    -  }
    -  if (goog.userAgent.GECKO) {
    -    return goog.userAgent.isVersionOrHigher('1.8');
    -  }
    -  if (goog.userAgent.OPERA) {
    -    return goog.userAgent.isVersionOrHigher('9.0');
    -  }
    -  if (goog.userAgent.WEBKIT) {
    -    return goog.userAgent.isVersionOrHigher('412');
    -  }
    -  return false;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/groupelement.js b/src/database/third_party/closure-library/closure/goog/graphics/groupelement.js
    deleted file mode 100644
    index 9e60cd7ef7c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/groupelement.js
    +++ /dev/null
    @@ -1,58 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview A thin wrapper around the DOM element for graphics groups.
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -
    -goog.provide('goog.graphics.GroupElement');
    -
    -goog.require('goog.graphics.Element');
    -
    -
    -
    -/**
    - * Interface for a graphics group element.
    - * You should not construct objects from this constructor. The graphics
    - * will return the object for you.
    - * @param {Element} element The DOM element to wrap.
    - * @param {goog.graphics.AbstractGraphics} graphics The graphics creating
    - *     this element.
    - * @constructor
    - * @extends {goog.graphics.Element}
    - * @deprecated goog.graphics is deprecated. It existed to abstract over browser
    - *     differences before the canvas tag was widely supported.  See
    - *     http://en.wikipedia.org/wiki/Canvas_element for details.
    - */
    -goog.graphics.GroupElement = function(element, graphics) {
    -  goog.graphics.Element.call(this, element, graphics);
    -};
    -goog.inherits(goog.graphics.GroupElement, goog.graphics.Element);
    -
    -
    -/**
    - * Remove all drawing elements from the group.
    - */
    -goog.graphics.GroupElement.prototype.clear = goog.abstractMethod;
    -
    -
    -/**
    - * Set the size of the group element.
    - * @param {number|string} width The width of the group element.
    - * @param {number|string} height The height of the group element.
    - */
    -goog.graphics.GroupElement.prototype.setSize = goog.abstractMethod;
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/imageelement.js b/src/database/third_party/closure-library/closure/goog/graphics/imageelement.js
    deleted file mode 100644
    index 2f2d9b792cb..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/imageelement.js
    +++ /dev/null
    @@ -1,70 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview A thin wrapper around the DOM element for images.
    - */
    -
    -
    -goog.provide('goog.graphics.ImageElement');
    -
    -goog.require('goog.graphics.Element');
    -
    -
    -
    -/**
    - * Interface for a graphics image element.
    - * You should not construct objects from this constructor. Instead,
    - * you should use {@code goog.graphics.Graphics.drawImage} and it
    - * will return an implementation of this interface for you.
    - *
    - * @param {Element} element The DOM element to wrap.
    - * @param {goog.graphics.AbstractGraphics} graphics The graphics creating
    - *     this element.
    - * @constructor
    - * @extends {goog.graphics.Element}
    - * @deprecated goog.graphics is deprecated. It existed to abstract over browser
    - *     differences before the canvas tag was widely supported.  See
    - *     http://en.wikipedia.org/wiki/Canvas_element for details.
    - */
    -goog.graphics.ImageElement = function(element, graphics) {
    -  goog.graphics.Element.call(this, element, graphics);
    -};
    -goog.inherits(goog.graphics.ImageElement, goog.graphics.Element);
    -
    -
    -/**
    - * Update the position of the image.
    - *
    - * @param {number} x X coordinate (left).
    - * @param {number} y Y coordinate (top).
    - */
    -goog.graphics.ImageElement.prototype.setPosition = goog.abstractMethod;
    -
    -
    -/**
    - * Update the size of the image.
    - *
    - * @param {number} width Width of image.
    - * @param {number} height Height of image.
    - */
    -goog.graphics.ImageElement.prototype.setSize = goog.abstractMethod;
    -
    -
    -/**
    - * Update the source of the image.
    - * @param {string} src Source of the image.
    - */
    -goog.graphics.ImageElement.prototype.setSource = goog.abstractMethod;
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/lineargradient.js b/src/database/third_party/closure-library/closure/goog/graphics/lineargradient.js
    deleted file mode 100644
    index df59cbfe89e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/lineargradient.js
    +++ /dev/null
    @@ -1,175 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Represents a gradient to be used with a Graphics implementor.
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -
    -goog.provide('goog.graphics.LinearGradient');
    -
    -
    -goog.require('goog.asserts');
    -goog.require('goog.graphics.Fill');
    -
    -
    -
    -/**
    - * Creates an immutable linear gradient fill object.
    - *
    - * @param {number} x1 Start X position of the gradient.
    - * @param {number} y1 Start Y position of the gradient.
    - * @param {number} x2 End X position of the gradient.
    - * @param {number} y2 End Y position of the gradient.
    - * @param {string} color1 Start color of the gradient.
    - * @param {string} color2 End color of the gradient.
    - * @param {?number=} opt_opacity1 Start opacity of the gradient, both or neither
    - *     of opt_opacity1 and opt_opacity2 have to be set.
    - * @param {?number=} opt_opacity2 End opacity of the gradient.
    - * @constructor
    - * @extends {goog.graphics.Fill}
    - * @deprecated goog.graphics is deprecated. It existed to abstract over browser
    - *     differences before the canvas tag was widely supported.  See
    - *     http://en.wikipedia.org/wiki/Canvas_element for details.
    - * @final
    - */
    -goog.graphics.LinearGradient =
    -    function(x1, y1, x2, y2, color1, color2, opt_opacity1, opt_opacity2) {
    -  /**
    -   * Start X position of the gradient.
    -   * @type {number}
    -   * @private
    -   */
    -  this.x1_ = x1;
    -
    -  /**
    -   * Start Y position of the gradient.
    -   * @type {number}
    -   * @private
    -   */
    -  this.y1_ = y1;
    -
    -  /**
    -   * End X position of the gradient.
    -   * @type {number}
    -   * @private
    -   */
    -  this.x2_ = x2;
    -
    -  /**
    -   * End Y position of the gradient.
    -   * @type {number}
    -   * @private
    -   */
    -  this.y2_ = y2;
    -
    -  /**
    -   * Start color of the gradient.
    -   * @type {string}
    -   * @private
    -   */
    -  this.color1_ = color1;
    -
    -  /**
    -   * End color of the gradient.
    -   * @type {string}
    -   * @private
    -   */
    -  this.color2_ = color2;
    -
    -  goog.asserts.assert(
    -      goog.isNumber(opt_opacity1) == goog.isNumber(opt_opacity2),
    -      'Both or neither of opt_opacity1 and opt_opacity2 have to be set.');
    -
    -  /**
    -   * Start opacity of the gradient.
    -   * @type {?number}
    -   * @private
    -   */
    -  this.opacity1_ = goog.isDef(opt_opacity1) ? opt_opacity1 : null;
    -
    -  /**
    -   * End opacity of the gradient.
    -   * @type {?number}
    -   * @private
    -   */
    -  this.opacity2_ = goog.isDef(opt_opacity2) ? opt_opacity2 : null;
    -};
    -goog.inherits(goog.graphics.LinearGradient, goog.graphics.Fill);
    -
    -
    -/**
    - * @return {number} The start X position of the gradient.
    - */
    -goog.graphics.LinearGradient.prototype.getX1 = function() {
    -  return this.x1_;
    -};
    -
    -
    -/**
    - * @return {number} The start Y position of the gradient.
    - */
    -goog.graphics.LinearGradient.prototype.getY1 = function() {
    -  return this.y1_;
    -};
    -
    -
    -/**
    - * @return {number} The end X position of the gradient.
    - */
    -goog.graphics.LinearGradient.prototype.getX2 = function() {
    -  return this.x2_;
    -};
    -
    -
    -/**
    - * @return {number} The end Y position of the gradient.
    - */
    -goog.graphics.LinearGradient.prototype.getY2 = function() {
    -  return this.y2_;
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.graphics.LinearGradient.prototype.getColor1 = function() {
    -  return this.color1_;
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.graphics.LinearGradient.prototype.getColor2 = function() {
    -  return this.color2_;
    -};
    -
    -
    -/**
    - * @return {?number} The start opacity of the gradient.
    - */
    -goog.graphics.LinearGradient.prototype.getOpacity1 = function() {
    -  return this.opacity1_;
    -};
    -
    -
    -/**
    - * @return {?number} The end opacity of the gradient.
    - */
    -goog.graphics.LinearGradient.prototype.getOpacity2 = function() {
    -  return this.opacity2_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/path.js b/src/database/third_party/closure-library/closure/goog/graphics/path.js
    deleted file mode 100644
    index c19f2d9db3a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/path.js
    +++ /dev/null
    @@ -1,511 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Represents a path used with a Graphics implementation.
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -goog.provide('goog.graphics.Path');
    -goog.provide('goog.graphics.Path.Segment');
    -
    -goog.require('goog.array');
    -goog.require('goog.math');
    -
    -
    -
    -/**
    - * Creates a path object. A path is a sequence of segments and may be open or
    - * closed. Path uses the EVEN-ODD fill rule for determining the interior of the
    - * path. A path must start with a moveTo command.
    - *
    - * A "simple" path does not contain any arcs and may be transformed using
    - * the {@code transform} method.
    - *
    - * @constructor
    - */
    -goog.graphics.Path = function() {
    -  /**
    -   * The segment types that constitute this path.
    -   * @type {!Array<number>}
    -   * @private
    -   */
    -  this.segments_ = [];
    -
    -  /**
    -   * The number of repeated segments of the current type.
    -   * @type {!Array<number>}
    -   * @private
    -   */
    -  this.count_ = [];
    -
    -  /**
    -   * The arguments corresponding to each of the segments.
    -   * @type {!Array<number>}
    -   * @private
    -   */
    -  this.arguments_ = [];
    -};
    -
    -
    -/**
    - * The coordinates of the point which closes the path (the point of the
    - * last moveTo command).
    - * @type {Array<number>?}
    - * @private
    - */
    -goog.graphics.Path.prototype.closePoint_ = null;
    -
    -
    -/**
    - * The coordinates most recently added to the end of the path.
    - * @type {Array<number>?}
    - * @private
    - */
    -goog.graphics.Path.prototype.currentPoint_ = null;
    -
    -
    -/**
    - * Flag for whether this is a simple path (contains no arc segments).
    - * @type {boolean}
    - * @private
    - */
    -goog.graphics.Path.prototype.simple_ = true;
    -
    -
    -/**
    - * Path segment types.
    - * @enum {number}
    - */
    -goog.graphics.Path.Segment = {
    -  MOVETO: 0,
    -  LINETO: 1,
    -  CURVETO: 2,
    -  ARCTO: 3,
    -  CLOSE: 4
    -};
    -
    -
    -/**
    - * The number of points for each segment type.
    - * @type {!Array<number>}
    - * @private
    - */
    -goog.graphics.Path.segmentArgCounts_ = (function() {
    -  var counts = [];
    -  counts[goog.graphics.Path.Segment.MOVETO] = 2;
    -  counts[goog.graphics.Path.Segment.LINETO] = 2;
    -  counts[goog.graphics.Path.Segment.CURVETO] = 6;
    -  counts[goog.graphics.Path.Segment.ARCTO] = 6;
    -  counts[goog.graphics.Path.Segment.CLOSE] = 0;
    -  return counts;
    -})();
    -
    -
    -/**
    - * Returns the number of points for a segment type.
    - *
    - * @param {number} segment The segment type.
    - * @return {number} The number of points.
    - */
    -goog.graphics.Path.getSegmentCount = function(segment) {
    -  return goog.graphics.Path.segmentArgCounts_[segment];
    -};
    -
    -
    -/**
    - * Appends another path to the end of this path.
    - *
    - * @param {!goog.graphics.Path} path The path to append.
    - * @return {!goog.graphics.Path} This path.
    - */
    -goog.graphics.Path.prototype.appendPath = function(path) {
    -  if (path.currentPoint_) {
    -    Array.prototype.push.apply(this.segments_, path.segments_);
    -    Array.prototype.push.apply(this.count_, path.count_);
    -    Array.prototype.push.apply(this.arguments_, path.arguments_);
    -    this.currentPoint_ = path.currentPoint_.concat();
    -    this.closePoint_ = path.closePoint_.concat();
    -    this.simple_ = this.simple_ && path.simple_;
    -  }
    -  return this;
    -};
    -
    -
    -/**
    - * Clears the path.
    - *
    - * @return {!goog.graphics.Path} The path itself.
    - */
    -goog.graphics.Path.prototype.clear = function() {
    -  this.segments_.length = 0;
    -  this.count_.length = 0;
    -  this.arguments_.length = 0;
    -  delete this.closePoint_;
    -  delete this.currentPoint_;
    -  delete this.simple_;
    -  return this;
    -};
    -
    -
    -/**
    - * Adds a point to the path by moving to the specified point. Repeated moveTo
    - * commands are collapsed into a single moveTo.
    - *
    - * @param {number} x X coordinate of destination point.
    - * @param {number} y Y coordinate of destination point.
    - * @return {!goog.graphics.Path} The path itself.
    - */
    -goog.graphics.Path.prototype.moveTo = function(x, y) {
    -  if (goog.array.peek(this.segments_) == goog.graphics.Path.Segment.MOVETO) {
    -    this.arguments_.length -= 2;
    -  } else {
    -    this.segments_.push(goog.graphics.Path.Segment.MOVETO);
    -    this.count_.push(1);
    -  }
    -  this.arguments_.push(x, y);
    -  this.currentPoint_ = this.closePoint_ = [x, y];
    -  return this;
    -};
    -
    -
    -/**
    - * Adds points to the path by drawing a straight line to each point.
    - *
    - * @param {...number} var_args The coordinates of each destination point as x, y
    - *     value pairs.
    - * @return {!goog.graphics.Path} The path itself.
    - */
    -goog.graphics.Path.prototype.lineTo = function(var_args) {
    -  var lastSegment = goog.array.peek(this.segments_);
    -  if (lastSegment == null) {
    -    throw Error('Path cannot start with lineTo');
    -  }
    -  if (lastSegment != goog.graphics.Path.Segment.LINETO) {
    -    this.segments_.push(goog.graphics.Path.Segment.LINETO);
    -    this.count_.push(0);
    -  }
    -  for (var i = 0; i < arguments.length; i += 2) {
    -    var x = arguments[i];
    -    var y = arguments[i + 1];
    -    this.arguments_.push(x, y);
    -  }
    -  this.count_[this.count_.length - 1] += i / 2;
    -  this.currentPoint_ = [x, y];
    -  return this;
    -};
    -
    -
    -/**
    - * Adds points to the path by drawing cubic Bezier curves. Each curve is
    - * specified using 3 points (6 coordinates) - two control points and the end
    - * point of the curve.
    - *
    - * @param {...number} var_args The coordinates specifiying each curve in sets of
    - *     6 points: {@code [x1, y1]} the first control point, {@code [x2, y2]} the
    - *     second control point and {@code [x, y]} the end point.
    - * @return {!goog.graphics.Path} The path itself.
    - */
    -goog.graphics.Path.prototype.curveTo = function(var_args) {
    -  var lastSegment = goog.array.peek(this.segments_);
    -  if (lastSegment == null) {
    -    throw Error('Path cannot start with curve');
    -  }
    -  if (lastSegment != goog.graphics.Path.Segment.CURVETO) {
    -    this.segments_.push(goog.graphics.Path.Segment.CURVETO);
    -    this.count_.push(0);
    -  }
    -  for (var i = 0; i < arguments.length; i += 6) {
    -    var x = arguments[i + 4];
    -    var y = arguments[i + 5];
    -    this.arguments_.push(arguments[i], arguments[i + 1],
    -        arguments[i + 2], arguments[i + 3], x, y);
    -  }
    -  this.count_[this.count_.length - 1] += i / 6;
    -  this.currentPoint_ = [x, y];
    -  return this;
    -};
    -
    -
    -/**
    - * Adds a path command to close the path by connecting the
    - * last point to the first point.
    - *
    - * @return {!goog.graphics.Path} The path itself.
    - */
    -goog.graphics.Path.prototype.close = function() {
    -  var lastSegment = goog.array.peek(this.segments_);
    -  if (lastSegment == null) {
    -    throw Error('Path cannot start with close');
    -  }
    -  if (lastSegment != goog.graphics.Path.Segment.CLOSE) {
    -    this.segments_.push(goog.graphics.Path.Segment.CLOSE);
    -    this.count_.push(1);
    -    this.currentPoint_ = this.closePoint_;
    -  }
    -  return this;
    -};
    -
    -
    -/**
    - * Adds a path command to draw an arc centered at the point {@code (cx, cy)}
    - * with radius {@code rx} along the x-axis and {@code ry} along the y-axis from
    - * {@code startAngle} through {@code extent} degrees. Positive rotation is in
    - * the direction from positive x-axis to positive y-axis.
    - *
    - * @param {number} cx X coordinate of center of ellipse.
    - * @param {number} cy Y coordinate of center of ellipse.
    - * @param {number} rx Radius of ellipse on x axis.
    - * @param {number} ry Radius of ellipse on y axis.
    - * @param {number} fromAngle Starting angle measured in degrees from the
    - *     positive x-axis.
    - * @param {number} extent The span of the arc in degrees.
    - * @param {boolean} connect If true, the starting point of the arc is connected
    - *     to the current point.
    - * @return {!goog.graphics.Path} The path itself.
    - * @deprecated Use {@code arcTo} or {@code arcToAsCurves} instead.
    - */
    -goog.graphics.Path.prototype.arc = function(cx, cy, rx, ry,
    -    fromAngle, extent, connect) {
    -  var startX = cx + goog.math.angleDx(fromAngle, rx);
    -  var startY = cy + goog.math.angleDy(fromAngle, ry);
    -  if (connect) {
    -    if (!this.currentPoint_ || startX != this.currentPoint_[0] ||
    -        startY != this.currentPoint_[1]) {
    -      this.lineTo(startX, startY);
    -    }
    -  } else {
    -    this.moveTo(startX, startY);
    -  }
    -  return this.arcTo(rx, ry, fromAngle, extent);
    -};
    -
    -
    -/**
    - * Adds a path command to draw an arc starting at the path's current point,
    - * with radius {@code rx} along the x-axis and {@code ry} along the y-axis from
    - * {@code startAngle} through {@code extent} degrees. Positive rotation is in
    - * the direction from positive x-axis to positive y-axis.
    - *
    - * This method makes the path non-simple.
    - *
    - * @param {number} rx Radius of ellipse on x axis.
    - * @param {number} ry Radius of ellipse on y axis.
    - * @param {number} fromAngle Starting angle measured in degrees from the
    - *     positive x-axis.
    - * @param {number} extent The span of the arc in degrees.
    - * @return {!goog.graphics.Path} The path itself.
    - */
    -goog.graphics.Path.prototype.arcTo = function(rx, ry, fromAngle, extent) {
    -  var cx = this.currentPoint_[0] - goog.math.angleDx(fromAngle, rx);
    -  var cy = this.currentPoint_[1] - goog.math.angleDy(fromAngle, ry);
    -  var ex = cx + goog.math.angleDx(fromAngle + extent, rx);
    -  var ey = cy + goog.math.angleDy(fromAngle + extent, ry);
    -  this.segments_.push(goog.graphics.Path.Segment.ARCTO);
    -  this.count_.push(1);
    -  this.arguments_.push(rx, ry, fromAngle, extent, ex, ey);
    -  this.simple_ = false;
    -  this.currentPoint_ = [ex, ey];
    -  return this;
    -};
    -
    -
    -/**
    - * Same as {@code arcTo}, but approximates the arc using bezier curves.
    -.* As a result, this method does not affect the simplified status of this path.
    - * The algorithm is adapted from {@code java.awt.geom.ArcIterator}.
    - *
    - * @param {number} rx Radius of ellipse on x axis.
    - * @param {number} ry Radius of ellipse on y axis.
    - * @param {number} fromAngle Starting angle measured in degrees from the
    - *     positive x-axis.
    - * @param {number} extent The span of the arc in degrees.
    - * @return {!goog.graphics.Path} The path itself.
    - */
    -goog.graphics.Path.prototype.arcToAsCurves = function(
    -    rx, ry, fromAngle, extent) {
    -  var cx = this.currentPoint_[0] - goog.math.angleDx(fromAngle, rx);
    -  var cy = this.currentPoint_[1] - goog.math.angleDy(fromAngle, ry);
    -  var extentRad = goog.math.toRadians(extent);
    -  var arcSegs = Math.ceil(Math.abs(extentRad) / Math.PI * 2);
    -  var inc = extentRad / arcSegs;
    -  var angle = goog.math.toRadians(fromAngle);
    -  for (var j = 0; j < arcSegs; j++) {
    -    var relX = Math.cos(angle);
    -    var relY = Math.sin(angle);
    -    var z = 4 / 3 * Math.sin(inc / 2) / (1 + Math.cos(inc / 2));
    -    var c0 = cx + (relX - z * relY) * rx;
    -    var c1 = cy + (relY + z * relX) * ry;
    -    angle += inc;
    -    relX = Math.cos(angle);
    -    relY = Math.sin(angle);
    -    this.curveTo(c0, c1,
    -        cx + (relX + z * relY) * rx,
    -        cy + (relY - z * relX) * ry,
    -        cx + relX * rx,
    -        cy + relY * ry);
    -  }
    -  return this;
    -};
    -
    -
    -/**
    - * Iterates over the path calling the supplied callback once for each path
    - * segment. The arguments to the callback function are the segment type and
    - * an array of its arguments.
    - *
    - * The {@code LINETO} and {@code CURVETO} arrays can contain multiple
    - * segments of the same type. The number of segments is the length of the
    - * array divided by the segment length (2 for lines, 6 for  curves).
    - *
    - * As a convenience the {@code ARCTO} segment also includes the end point as the
    - * last two arguments: {@code rx, ry, fromAngle, extent, x, y}.
    - *
    - * @param {function(number, Array)} callback The function to call with each
    - *     path segment.
    - */
    -goog.graphics.Path.prototype.forEachSegment = function(callback) {
    -  var points = this.arguments_;
    -  var index = 0;
    -  for (var i = 0, length = this.segments_.length; i < length; i++) {
    -    var seg = this.segments_[i];
    -    var n = goog.graphics.Path.segmentArgCounts_[seg] * this.count_[i];
    -    callback(seg, points.slice(index, index + n));
    -    index += n;
    -  }
    -};
    -
    -
    -/**
    - * Returns the coordinates most recently added to the end of the path.
    - *
    - * @return {Array<number>?} An array containing the ending coordinates of the
    - *     path of the form {@code [x, y]}.
    - */
    -goog.graphics.Path.prototype.getCurrentPoint = function() {
    -  return this.currentPoint_ && this.currentPoint_.concat();
    -};
    -
    -
    -/**
    - * @return {!goog.graphics.Path} A copy of this path.
    - */
    -goog.graphics.Path.prototype.clone = function() {
    -  var path = new this.constructor();
    -  path.segments_ = this.segments_.concat();
    -  path.count_ = this.count_.concat();
    -  path.arguments_ = this.arguments_.concat();
    -  path.closePoint_ = this.closePoint_ && this.closePoint_.concat();
    -  path.currentPoint_ = this.currentPoint_ && this.currentPoint_.concat();
    -  path.simple_ = this.simple_;
    -  return path;
    -};
    -
    -
    -/**
    - * Returns true if this path contains no arcs. Simplified paths can be
    - * created using {@code createSimplifiedPath}.
    - *
    - * @return {boolean} True if the path contains no arcs.
    - */
    -goog.graphics.Path.prototype.isSimple = function() {
    -  return this.simple_;
    -};
    -
    -
    -/**
    - * A map from segment type to the path function to call to simplify a path.
    - * @type {!Object}
    - * @private
    - * @suppress {deprecated} goog.graphics.Path is deprecated.
    - */
    -goog.graphics.Path.simplifySegmentMap_ = (function() {
    -  var map = {};
    -  map[goog.graphics.Path.Segment.MOVETO] = goog.graphics.Path.prototype.moveTo;
    -  map[goog.graphics.Path.Segment.LINETO] = goog.graphics.Path.prototype.lineTo;
    -  map[goog.graphics.Path.Segment.CLOSE] = goog.graphics.Path.prototype.close;
    -  map[goog.graphics.Path.Segment.CURVETO] =
    -      goog.graphics.Path.prototype.curveTo;
    -  map[goog.graphics.Path.Segment.ARCTO] =
    -      goog.graphics.Path.prototype.arcToAsCurves;
    -  return map;
    -})();
    -
    -
    -/**
    - * Creates a copy of the given path, replacing {@code arcTo} with
    - * {@code arcToAsCurves}. The resulting path is simplified and can
    - * be transformed.
    - *
    - * @param {!goog.graphics.Path} src The path to simplify.
    - * @return {!goog.graphics.Path} A new simplified path.
    - * @suppress {deprecated} goog.graphics is deprecated.
    - */
    -goog.graphics.Path.createSimplifiedPath = function(src) {
    -  if (src.isSimple()) {
    -    return src.clone();
    -  }
    -  var path = new goog.graphics.Path();
    -  src.forEachSegment(function(segment, args) {
    -    goog.graphics.Path.simplifySegmentMap_[segment].apply(path, args);
    -  });
    -  return path;
    -};
    -
    -
    -// TODO(chrisn): Delete this method
    -/**
    - * Creates a transformed copy of this path. The path is simplified
    - * {@see #createSimplifiedPath} prior to transformation.
    - *
    - * @param {!goog.graphics.AffineTransform} tx The transformation to perform.
    - * @return {!goog.graphics.Path} A new, transformed path.
    - */
    -goog.graphics.Path.prototype.createTransformedPath = function(tx) {
    -  var path = goog.graphics.Path.createSimplifiedPath(this);
    -  path.transform(tx);
    -  return path;
    -};
    -
    -
    -/**
    - * Transforms the path. Only simple paths are transformable. Attempting
    - * to transform a non-simple path will throw an error.
    - *
    - * @param {!goog.graphics.AffineTransform} tx The transformation to perform.
    - * @return {!goog.graphics.Path} The path itself.
    - */
    -goog.graphics.Path.prototype.transform = function(tx) {
    -  if (!this.isSimple()) {
    -    throw Error('Non-simple path');
    -  }
    -  tx.transform(this.arguments_, 0, this.arguments_, 0,
    -      this.arguments_.length / 2);
    -  if (this.closePoint_) {
    -    tx.transform(this.closePoint_, 0, this.closePoint_, 0, 1);
    -  }
    -  if (this.currentPoint_ && this.closePoint_ != this.currentPoint_) {
    -    tx.transform(this.currentPoint_, 0, this.currentPoint_, 0, 1);
    -  }
    -  return this;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the path is empty.
    - */
    -goog.graphics.Path.prototype.isEmpty = function() {
    -  return this.segments_.length == 0;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/path_test.html b/src/database/third_party/closure-library/closure/goog/graphics/path_test.html
    deleted file mode 100644
    index b353c6decbd..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/path_test.html
    +++ /dev/null
    @@ -1,359 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.graphics.Path</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.array');
    -  goog.require('goog.math');
    -  goog.require('goog.graphics.Path');
    -  goog.require('goog.graphics.AffineTransform');
    -  goog.require('goog.testing.graphics');
    -  goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -
    -<script>
    -  function testConstructor() {
    -    var path = new goog.graphics.Path();
    -    assertTrue(path.isSimple());
    -    assertNull(path.getCurrentPoint());
    -    goog.testing.graphics.assertPathEquals([], path);
    -  }
    -
    -
    -  function testGetSegmentCount() {
    -    assertArrayEquals([2, 2, 6, 6, 0], goog.array.map([
    -      goog.graphics.Path.Segment.MOVETO,
    -      goog.graphics.Path.Segment.LINETO,
    -      goog.graphics.Path.Segment.CURVETO,
    -      goog.graphics.Path.Segment.ARCTO,
    -      goog.graphics.Path.Segment.CLOSE
    -    ], goog.graphics.Path.getSegmentCount));
    -  }
    -
    -
    -  function testSimpleMoveTo() {
    -    var path = new goog.graphics.Path();
    -    path.moveTo(30, 50);
    -    assertTrue(path.isSimple());
    -    assertObjectEquals([30, 50], path.getCurrentPoint());
    -    goog.testing.graphics.assertPathEquals(['M', 30, 50], path);
    -  }
    -
    -
    -  function testRepeatedMoveTo() {
    -    var path = new goog.graphics.Path();
    -    path.moveTo(30, 50);
    -    path.moveTo(40, 60);
    -    assertTrue(path.isSimple());
    -    assertObjectEquals([40, 60], path.getCurrentPoint());
    -    goog.testing.graphics.assertPathEquals(['M', 40, 60], path);
    -  }
    -
    -
    -  function testSimpleLineTo() {
    -    var path = new goog.graphics.Path();
    -    var e = assertThrows(function() {
    -      path.lineTo(30, 50);
    -    });
    -    assertEquals('Path cannot start with lineTo', e.message);
    -    path.moveTo(0, 0);
    -    path.lineTo(30, 50);
    -    assertTrue(path.isSimple());
    -    assertObjectEquals([30, 50], path.getCurrentPoint());
    -    goog.testing.graphics.assertPathEquals(['M', 0, 0, 'L', 30, 50], path);
    -  }
    -
    -
    -  function testMultiArgLineTo() {
    -    var path = new goog.graphics.Path();
    -    path.moveTo(0, 0);
    -    path.lineTo(30, 50, 40 , 60);
    -    assertTrue(path.isSimple());
    -    assertObjectEquals([40, 60], path.getCurrentPoint());
    -    goog.testing.graphics.assertPathEquals(['M', 0, 0, 'L', 30, 50, 40, 60],
    -        path);
    -  }
    -
    -
    -  function testRepeatedLineTo() {
    -    var path = new goog.graphics.Path();
    -    path.moveTo(0, 0);
    -    path.lineTo(30, 50);
    -    path.lineTo(40, 60);
    -    assertTrue(path.isSimple());
    -    assertObjectEquals([40, 60], path.getCurrentPoint());
    -    goog.testing.graphics.assertPathEquals(['M', 0, 0, 'L', 30, 50, 40, 60],
    -        path);
    -  }
    -
    -
    -  function testSimpleCurveTo() {
    -    var path = new goog.graphics.Path();
    -    var e = assertThrows(function() {
    -      path.curveTo(10, 20, 30, 40, 50, 60);
    -    });
    -    assertEquals('Path cannot start with curve', e.message);
    -    path.moveTo(0, 0);
    -    path.curveTo(10, 20, 30, 40, 50, 60);
    -    assertTrue(path.isSimple());
    -    assertObjectEquals([50, 60], path.getCurrentPoint());
    -    goog.testing.graphics.assertPathEquals(
    -        ['M', 0, 0, 'C', 10, 20, 30, 40, 50, 60], path);
    -  }
    -
    -
    -  function testMultiCurveTo() {
    -    var path = new goog.graphics.Path();
    -    path.moveTo(0, 0);
    -    path.curveTo(10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120);
    -    assertTrue(path.isSimple());
    -    assertObjectEquals([110, 120], path.getCurrentPoint());
    -    goog.testing.graphics.assertPathEquals(
    -        ['M', 0, 0, 'C', 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120],
    -        path);
    -  }
    -
    -
    -  function testRepeatedCurveTo() {
    -    var path = new goog.graphics.Path();
    -    path.moveTo(0, 0);
    -    path.curveTo(10, 20, 30, 40, 50, 60);
    -    path.curveTo(70, 80, 90, 100, 110, 120);
    -    assertTrue(path.isSimple());
    -    assertObjectEquals([110, 120], path.getCurrentPoint());
    -    goog.testing.graphics.assertPathEquals(
    -        ['M', 0, 0, 'C', 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120],
    -        path);
    -  }
    -
    -
    -  function testSimpleArc() {
    -    var path = new goog.graphics.Path();
    -    path.arc(50, 60, 10, 20, 30, 30, false);
    -    assertFalse(path.isSimple());
    -    var p = path.getCurrentPoint();
    -    assertEquals(55, p[0]);
    -    assertRoughlyEquals(77.32, p[1], 0.01);
    -    goog.testing.graphics.assertPathEquals(
    -        ['M', 58.66, 70, 'A', 10, 20, 30, 30, 55, 77.32], path);
    -  }
    -
    -
    -  function testArcNonConnectClose() {
    -    var path = new goog.graphics.Path();
    -    path.moveTo(0, 0);
    -    path.arc(10, 10, 10, 10, -90, 180);
    -    assertObjectEquals([10, 20], path.getCurrentPoint());
    -    path.close();
    -    assertObjectEquals([10, 0], path.getCurrentPoint());
    -  }
    -
    -
    -  function testRepeatedArc() {
    -    var path = new goog.graphics.Path();
    -    path.arc(50, 60, 10, 20, 30, 30, false);
    -    path.arc(50, 60, 10, 20, 60, 30, false);
    -    assertFalse(path.isSimple());
    -    assertObjectEquals([50, 80], path.getCurrentPoint());
    -    goog.testing.graphics.assertPathEquals(['M', 58.66, 70,
    -        'A', 10, 20, 30, 30, 55, 77.32,
    -        'M', 55, 77.32,
    -        'A', 10, 20, 60, 30, 50, 80], path);
    -  }
    -
    -
    -  function testRepeatedArc2() {
    -    var path = new goog.graphics.Path();
    -    path.arc(50, 60, 10, 20, 30, 30, false);
    -    path.arc(50, 60, 10, 20, 60, 30, true);
    -    goog.testing.graphics.assertPathEquals(['M', 58.66, 70,
    -        'A', 10, 20, 30, 30, 55, 77.32,
    -        'A', 10, 20, 60, 30, 50, 80], path);
    -  }
    -
    -
    -  function testCompleteCircle() {
    -    var path = new goog.graphics.Path();
    -    path.arc(0, 0, 10, 10, 0, 360, false);
    -    assertFalse(path.isSimple());
    -    var p = path.getCurrentPoint();
    -    assertRoughlyEquals(10, p[0], 0.01);
    -    assertRoughlyEquals(0, p[1], 0.01);
    -    goog.testing.graphics.assertPathEquals(
    -        ['M', 10, 0, 'A', 10, 10, 0, 360, 10, 0], path);
    -  }
    -
    -
    -  function testClose() {
    -    var path = new goog.graphics.Path();
    -    try {
    -      path.close();
    -      fail();
    -    } catch (e) {
    -      // Expected
    -      assertEquals('Path cannot start with close', e.message);
    -    }
    -    path.moveTo(0, 0);
    -    path.lineTo(10, 20, 30, 40, 50, 60);
    -    path.close()
    -    assertTrue(path.isSimple());
    -    assertObjectEquals([0, 0], path.getCurrentPoint());
    -    goog.testing.graphics.assertPathEquals(
    -        ['M', 0, 0, 'L', 10, 20, 30, 40, 50, 60, 'X'], path);
    -  }
    -
    -
    -  function testClear() {
    -    var path = new goog.graphics.Path();
    -    path.moveTo(0, 0);
    -    path.arc(50, 60, 10, 20, 30, 30, false);
    -    path.clear();
    -    assertTrue(path.isSimple());
    -    assertNull(path.getCurrentPoint());
    -    goog.testing.graphics.assertPathEquals([], path);
    -  }
    -
    -
    -  function testCreateSimplifiedPath() {
    -    var path = new goog.graphics.Path();
    -    path.moveTo(0, 0);
    -    path.arc(50, 60, 10, 20, 30, 30, false);
    -    assertFalse(path.isSimple());
    -    path = goog.graphics.Path.createSimplifiedPath(path);
    -    assertTrue(path.isSimple());
    -    var p = path.getCurrentPoint();
    -    assertEquals(55, p[0]);
    -    assertRoughlyEquals(77.32, p[1], 0.01);
    -    goog.testing.graphics.assertPathEquals(['M', 58.66, 70,
    -        'C', 57.78, 73.04, 56.52, 75.57, 55, 77.32], path);
    -  }
    -
    -
    -  function testCreateSimplifiedPath2() {
    -    var path = new goog.graphics.Path();
    -    path.arc(50, 60, 10, 20, 30, 30, false);
    -    path.arc(50, 60, 10, 20, 60, 30, false);
    -    assertFalse(path.isSimple());
    -    path = goog.graphics.Path.createSimplifiedPath(path);
    -    assertTrue(path.isSimple());
    -    goog.testing.graphics.assertPathEquals(['M', 58.66, 70,
    -        'C', 57.78, 73.04, 56.52, 75.57, 55, 77.32,
    -        'M', 55, 77.32,
    -        'C', 53.48, 79.08, 51.76, 80, 50, 80], path);
    -  }
    -
    -
    -  function testCreateSimplifiedPath3() {
    -    var path = new goog.graphics.Path();
    -    path.arc(50, 60, 10, 20, 30, 30, false);
    -    path.arc(50, 60, 10, 20, 60, 30, true);
    -    path.close();
    -    path = goog.graphics.Path.createSimplifiedPath(path);
    -    goog.testing.graphics.assertPathEquals(['M', 58.66, 70,
    -        'C', 57.78, 73.04, 56.52, 75.57, 55, 77.32,
    -        53.48, 79.08, 51.76, 80, 50, 80, 'X'], path);
    -    var p = path.getCurrentPoint();
    -    assertRoughlyEquals(58.66, p[0], 0.01);
    -    assertRoughlyEquals(70, p[1], 0.01);
    -  }
    -
    -
    -  function testArcToAsCurves() {
    -    var path = new goog.graphics.Path();
    -    path.moveTo(58.66, 70);
    -    path.arcToAsCurves(10, 20, 30, 30, false);
    -    goog.testing.graphics.assertPathEquals(['M', 58.66, 70,
    -        'C', 57.78, 73.04, 56.52, 75.57, 55, 77.32], path);
    -  }
    -
    -
    -  function testCreateTransformedPath() {
    -    var path = new goog.graphics.Path();
    -    path.moveTo(0, 0);
    -    path.lineTo(0, 10, 10, 10, 10, 0);
    -    path.close();
    -    var tx = new goog.graphics.AffineTransform(2, 0, 0, 3, 10, 20);
    -    var path2 = path.createTransformedPath(tx);
    -    goog.testing.graphics.assertPathEquals(
    -        ['M', 0, 0, 'L', 0, 10, 10, 10, 10, 0, 'X'], path);
    -    goog.testing.graphics.assertPathEquals(
    -        ['M', 10, 20, 'L', 10, 50, 30, 50, 30, 20, 'X'], path2);
    -  }
    -
    -
    -  function testTransform() {
    -    var path = new goog.graphics.Path();
    -    path.moveTo(0, 0);
    -    path.lineTo(0, 10, 10, 10, 10, 0);
    -    path.close();
    -    var tx = new goog.graphics.AffineTransform(2, 0, 0, 3, 10, 20);
    -    var path2 = path.transform(tx);
    -    assertTrue(path === path2);
    -    goog.testing.graphics.assertPathEquals(
    -        ['M', 10, 20, 'L', 10, 50, 30, 50, 30, 20, 'X'], path2);
    -  }
    -
    -
    -  function testTransformCurrentAndClosePoints() {
    -    var path = new goog.graphics.Path();
    -    path.moveTo(0, 0);
    -    assertObjectEquals([0, 0], path.getCurrentPoint());
    -    path.transform(new goog.graphics.AffineTransform(1, 0, 0, 1, 10, 20));
    -    assertObjectEquals([10, 20], path.getCurrentPoint());
    -    path.lineTo(50, 50);
    -    path.close();
    -    assertObjectEquals([10, 20], path.getCurrentPoint());
    -  }
    -
    -
    -  function testTransformNonSimple() {
    -    var path = new goog.graphics.Path();
    -    path.arc(50, 60, 10, 20, 30, 30, false);
    -    assertThrows(function() {
    -      path.transform(new goog.graphics.AffineTransform(1, 0, 0, 1, 10, 20));
    -    });
    -  }
    -
    -
    -  function testAppendPath() {
    -    var path1 = new goog.graphics.Path();
    -    path1.moveTo(0, 0);
    -    path1.lineTo(0, 10, 10, 10, 10, 0);
    -    path1.close();
    -
    -    var path2 = new goog.graphics.Path();
    -    path2.arc(50, 60, 10, 20, 30, 30, false);
    -
    -    assertTrue(path1.isSimple());
    -    path1.appendPath(path2);
    -    assertFalse(path1.isSimple());
    -    goog.testing.graphics.assertPathEquals([
    -        'M', 0, 0, 'L', 0, 10, 10, 10, 10, 0, 'X',
    -        'M', 58.66, 70, 'A', 10, 20, 30, 30, 55, 77.32
    -    ], path1);
    -  }
    -
    -
    -  function testIsEmpty() {
    -    var path = new goog.graphics.Path();
    -    assertTrue('Initially path is empty', path.isEmpty());
    -
    -    path.moveTo(0, 0);
    -    assertFalse('After command addition, path is not empty', path.isEmpty());
    -
    -    path.clear();
    -    assertTrue('After clear, path is empty again', path.isEmpty());
    -  }
    -</script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/pathelement.js b/src/database/third_party/closure-library/closure/goog/graphics/pathelement.js
    deleted file mode 100644
    index b58b8c61f3a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/pathelement.js
    +++ /dev/null
    @@ -1,54 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview A thin wrapper around the DOM element for paths.
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -
    -goog.provide('goog.graphics.PathElement');
    -
    -goog.require('goog.graphics.StrokeAndFillElement');
    -
    -
    -
    -/**
    - * Interface for a graphics path element.
    - * You should not construct objects from this constructor. The graphics
    - * will return an implementation of this interface for you.
    - * @param {Element} element The DOM element to wrap.
    - * @param {goog.graphics.AbstractGraphics} graphics The graphics creating
    - *     this element.
    - * @param {goog.graphics.Stroke?} stroke The stroke to use for this element.
    - * @param {goog.graphics.Fill?} fill The fill to use for this element.
    - * @constructor
    - * @extends {goog.graphics.StrokeAndFillElement}
    - * @deprecated goog.graphics is deprecated. It existed to abstract over browser
    - *     differences before the canvas tag was widely supported.  See
    - *     http://en.wikipedia.org/wiki/Canvas_element for details.
    - */
    -goog.graphics.PathElement = function(element, graphics, stroke, fill) {
    -  goog.graphics.StrokeAndFillElement.call(this, element, graphics, stroke,
    -      fill);
    -};
    -goog.inherits(goog.graphics.PathElement, goog.graphics.StrokeAndFillElement);
    -
    -
    -/**
    - * Update the underlying path.
    - * @param {!goog.graphics.Path} path The path object to draw.
    - */
    -goog.graphics.PathElement.prototype.setPath = goog.abstractMethod;
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/paths.js b/src/database/third_party/closure-library/closure/goog/graphics/paths.js
    deleted file mode 100644
    index 37b53d92caf..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/paths.js
    +++ /dev/null
    @@ -1,86 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Factories for common path types.
    - * @author nicksantos@google.com (Nick Santos)
    - */
    -
    -
    -goog.provide('goog.graphics.paths');
    -
    -goog.require('goog.graphics.Path');
    -goog.require('goog.math.Coordinate');
    -
    -
    -/**
    - * Defines a regular n-gon by specifing the center, a vertex, and the total
    - * number of vertices.
    - * @param {goog.math.Coordinate} center The center point.
    - * @param {goog.math.Coordinate} vertex The vertex, which implicitly defines
    - *     a radius as well.
    - * @param {number} n The number of vertices.
    - * @return {!goog.graphics.Path} The path.
    - */
    -goog.graphics.paths.createRegularNGon = function(center, vertex, n) {
    -  var path = new goog.graphics.Path();
    -  path.moveTo(vertex.x, vertex.y);
    -
    -  var startAngle = Math.atan2(vertex.y - center.y, vertex.x - center.x);
    -  var radius = goog.math.Coordinate.distance(center, vertex);
    -  for (var i = 1; i < n; i++) {
    -    var angle = startAngle + 2 * Math.PI * (i / n);
    -    path.lineTo(center.x + radius * Math.cos(angle),
    -                center.y + radius * Math.sin(angle));
    -  }
    -  path.close();
    -  return path;
    -};
    -
    -
    -/**
    - * Defines an arrow.
    - * @param {goog.math.Coordinate} a Point A.
    - * @param {goog.math.Coordinate} b Point B.
    - * @param {?number} aHead The size of the arrow head at point A.
    - *     0 omits the head.
    - * @param {?number} bHead The size of the arrow head at point B.
    - *     0 omits the head.
    - * @return {!goog.graphics.Path} The path.
    - */
    -goog.graphics.paths.createArrow = function(a, b, aHead, bHead) {
    -  var path = new goog.graphics.Path();
    -  path.moveTo(a.x, a.y);
    -  path.lineTo(b.x, b.y);
    -
    -  var angle = Math.atan2(b.y - a.y, b.x - a.x);
    -  if (aHead) {
    -    path.appendPath(
    -        goog.graphics.paths.createRegularNGon(
    -            new goog.math.Coordinate(
    -                a.x + aHead * Math.cos(angle),
    -                a.y + aHead * Math.sin(angle)),
    -            a, 3));
    -  }
    -  if (bHead) {
    -    path.appendPath(
    -        goog.graphics.paths.createRegularNGon(
    -            new goog.math.Coordinate(
    -                b.x + bHead * Math.cos(angle + Math.PI),
    -                b.y + bHead * Math.sin(angle + Math.PI)),
    -            b, 3));
    -  }
    -  return path;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/paths_test.html b/src/database/third_party/closure-library/closure/goog/graphics/paths_test.html
    deleted file mode 100644
    index e6e062b5b2d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/paths_test.html
    +++ /dev/null
    @@ -1,98 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    -Author: nicksantos@google.com (Nick Santos)
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>JsUnit tests for goog.graphics.paths</title>
    -<script src="../base.js"></script>
    -<script>
    -
    -goog.require('goog.dom');
    -goog.require('goog.graphics');
    -goog.require('goog.graphics.paths');
    -goog.require('goog.testing.jsunit');
    -
    -
    -</script>
    -</head>
    -<body>
    -
    -<div id="root"></div>
    -
    -<script type='text/javascript'>
    -
    -// The purpose of this test is less about the actual unit test, and
    -// more for drawing demos of shapes.
    -var regularNGon = goog.graphics.paths.createRegularNGon;
    -var arrow = goog.graphics.paths.createArrow;
    -
    -function setUp() {
    -  goog.dom.removeChildren(goog.dom.getElement('root'));
    -}
    -
    -function testSquare() {
    -  var square = regularNGon(
    -      $coord(10, 10), $coord(0, 10), 4);
    -  assertArrayRoughlyEquals(
    -      [0, 10, 10, 0, 20, 10, 10, 20], square.arguments_, 0.05);
    -}
    -
    -function assertArrayRoughlyEquals(expected, actual, delta) {
    -  var message = 'Expected: ' + expected + ', Actual: ' + actual;
    -  assertEquals('Wrong length. ' + message, expected.length, actual.length);
    -  for (var i = 0; i < expected.length; i++) {
    -    assertRoughlyEquals(
    -        'Wrong item at ' + i + '. ' + message,
    -        expected[i], actual[i], delta);
    -  }
    -}
    -
    -function tearDownPage() {
    -  var root = goog.dom.getElement('root');
    -  var graphics = goog.graphics.createGraphics(800, 600);
    -
    -  var blueFill = new goog.graphics.SolidFill('blue');
    -  var blackStroke = new goog.graphics.Stroke(1, 'black');
    -  graphics.drawPath(
    -      regularNGon($coord(20, 50), $coord(0, 20), 3),
    -      blackStroke, blueFill);
    -  graphics.drawPath(
    -      regularNGon($coord(120, 50), $coord(100, 20), 4),
    -      blackStroke, blueFill);
    -  graphics.drawPath(
    -      regularNGon($coord(220, 50), $coord(200, 20), 5),
    -      blackStroke, blueFill);
    -  graphics.drawPath(
    -      regularNGon($coord(320, 50), $coord(300, 20), 6),
    -      blackStroke, blueFill);
    -
    -  graphics.drawPath(
    -      arrow($coord(0, 300), $coord(100, 400), 0, 0),
    -      blackStroke, blueFill);
    -  graphics.drawPath(
    -      arrow($coord(120, 400), $coord(200, 300), 0, 10),
    -      blackStroke, blueFill);
    -  graphics.drawPath(
    -      arrow($coord(220, 300), $coord(300, 400), 10, 0),
    -      blackStroke, blueFill);
    -  graphics.drawPath(
    -      arrow($coord(320, 400), $coord(400, 300), 10, 10),
    -      blackStroke, blueFill);
    -
    -  root.appendChild(graphics.getElement());
    -}
    -
    -function $coord(x, y) {
    -  return new goog.math.Coordinate(x, y);
    -}
    -
    -</script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/rectelement.js b/src/database/third_party/closure-library/closure/goog/graphics/rectelement.js
    deleted file mode 100644
    index 9a6e9a17186..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/rectelement.js
    +++ /dev/null
    @@ -1,63 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview A thin wrapper around the DOM element for rectangles.
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -
    -goog.provide('goog.graphics.RectElement');
    -
    -goog.require('goog.graphics.StrokeAndFillElement');
    -
    -
    -
    -/**
    - * Interface for a graphics rectangle element.
    - * You should not construct objects from this constructor. The graphics
    - * will return an implementation of this interface for you.
    - * @param {Element} element The DOM element to wrap.
    - * @param {goog.graphics.AbstractGraphics} graphics The graphics creating
    - *     this element.
    - * @param {goog.graphics.Stroke?} stroke The stroke to use for this element.
    - * @param {goog.graphics.Fill?} fill The fill to use for this element.
    - * @constructor
    - * @extends {goog.graphics.StrokeAndFillElement}
    - * @deprecated goog.graphics is deprecated. It existed to abstract over browser
    - *     differences before the canvas tag was widely supported.  See
    - *     http://en.wikipedia.org/wiki/Canvas_element for details.
    - */
    -goog.graphics.RectElement = function(element, graphics, stroke, fill) {
    -  goog.graphics.StrokeAndFillElement.call(this, element, graphics, stroke,
    -      fill);
    -};
    -goog.inherits(goog.graphics.RectElement, goog.graphics.StrokeAndFillElement);
    -
    -
    -/**
    - * Update the position of the rectangle.
    - * @param {number} x X coordinate (left).
    - * @param {number} y Y coordinate (top).
    - */
    -goog.graphics.RectElement.prototype.setPosition = goog.abstractMethod;
    -
    -
    -/**
    - * Update the size of the rectangle.
    - * @param {number} width Width of rectangle.
    - * @param {number} height Height of rectangle.
    - */
    -goog.graphics.RectElement.prototype.setSize = goog.abstractMethod;
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/solidfill.js b/src/database/third_party/closure-library/closure/goog/graphics/solidfill.js
    deleted file mode 100644
    index fae3fc42483..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/solidfill.js
    +++ /dev/null
    @@ -1,74 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Represents a solid color fill goog.graphics.
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -
    -goog.provide('goog.graphics.SolidFill');
    -
    -
    -goog.require('goog.graphics.Fill');
    -
    -
    -
    -/**
    - * Creates an immutable solid color fill object.
    - *
    - * @param {string} color The color of the background.
    - * @param {number=} opt_opacity The opacity of the background fill. The value
    - *    must be greater than or equal to zero (transparent) and less than or
    - *    equal to 1 (opaque).
    - * @constructor
    - * @extends {goog.graphics.Fill}
    - * @deprecated goog.graphics is deprecated. It existed to abstract over browser
    - *     differences before the canvas tag was widely supported.  See
    - *     http://en.wikipedia.org/wiki/Canvas_element for details.
    - */
    -goog.graphics.SolidFill = function(color, opt_opacity) {
    -  /**
    -   * The color with which to fill.
    -   * @type {string}
    -   * @private
    -   */
    -  this.color_ = color;
    -
    -
    -  /**
    -   * The opacity of the fill.
    -   * @type {number}
    -   * @private
    -   */
    -  this.opacity_ = opt_opacity == null ? 1.0 : opt_opacity;
    -};
    -goog.inherits(goog.graphics.SolidFill, goog.graphics.Fill);
    -
    -
    -/**
    - * @return {string} The color of this fill.
    - */
    -goog.graphics.SolidFill.prototype.getColor = function() {
    -  return this.color_;
    -};
    -
    -
    -/**
    - * @return {number} The opacity of this fill.
    - */
    -goog.graphics.SolidFill.prototype.getOpacity = function() {
    -  return this.opacity_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/solidfill_test.html b/src/database/third_party/closure-library/closure/goog/graphics/solidfill_test.html
    deleted file mode 100644
    index 0282698b898..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/solidfill_test.html
    +++ /dev/null
    @@ -1,53 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.graphics.SolidFill</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.graphics.SolidFill');
    -  goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -
    -<script>
    -  function testGetColor() {
    -    var fill = new goog.graphics.SolidFill('#123');
    -    assertEquals('#123', fill.getColor());
    -    fill = new goog.graphics.SolidFill('#abcdef');
    -    assertEquals('#abcdef', fill.getColor());
    -
    -    fill = new goog.graphics.SolidFill('#123', 0.5);
    -    assertEquals('#123', fill.getColor());
    -    fill = new goog.graphics.SolidFill('#abcdef', 0.5);
    -    assertEquals('#abcdef', fill.getColor());
    -  }
    -
    -  function testGetOpacity() {
    -    // Default opacity
    -    var fill = new goog.graphics.SolidFill('#123');
    -    assertEquals(1, fill.getOpacity());
    -
    -    // Opaque
    -    var fill = new goog.graphics.SolidFill('#123', 1);
    -    assertEquals(1, fill.getOpacity());
    -
    -    // Semi-transparent
    -    fill = new goog.graphics.SolidFill('#123', 0.5);
    -    assertEquals(0.5, fill.getOpacity());
    -
    -    // Fully transparent
    -    fill = new goog.graphics.SolidFill('#123', 0);
    -    assertEquals(0, fill.getOpacity());
    -  }
    -</script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/stroke.js b/src/database/third_party/closure-library/closure/goog/graphics/stroke.js
    deleted file mode 100644
    index ae1eb8e9193..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/stroke.js
    +++ /dev/null
    @@ -1,86 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Represents a stroke object for goog.graphics.
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -
    -goog.provide('goog.graphics.Stroke');
    -
    -
    -
    -/**
    - * Creates an immutable stroke object.
    - *
    - * @param {number|string} width The width of the stroke.
    - * @param {string} color The color of the stroke.
    - * @param {number=} opt_opacity The opacity of the background fill. The value
    - *    must be greater than or equal to zero (transparent) and less than or
    - *    equal to 1 (opaque).
    - * @constructor
    - * @deprecated goog.graphics is deprecated. It existed to abstract over browser
    - *     differences before the canvas tag was widely supported.  See
    - *     http://en.wikipedia.org/wiki/Canvas_element for details.
    - */
    -goog.graphics.Stroke = function(width, color, opt_opacity) {
    -  /**
    -   * The width of the stroke.
    -   * @type {number|string}
    -   * @private
    -   */
    -  this.width_ = width;
    -
    -
    -  /**
    -   * The color with which to fill.
    -   * @type {string}
    -   * @private
    -   */
    -  this.color_ = color;
    -
    -
    -  /**
    -   * The opacity of the fill.
    -   * @type {number}
    -   * @private
    -   */
    -  this.opacity_ = opt_opacity == null ? 1.0 : opt_opacity;
    -};
    -
    -
    -/**
    - * @return {number|string} The width of this stroke.
    - */
    -goog.graphics.Stroke.prototype.getWidth = function() {
    -  return this.width_;
    -};
    -
    -
    -/**
    - * @return {string} The color of this stroke.
    - */
    -goog.graphics.Stroke.prototype.getColor = function() {
    -  return this.color_;
    -};
    -
    -
    -/**
    - * @return {number} The opacity of this fill.
    - */
    -goog.graphics.Stroke.prototype.getOpacity = function() {
    -  return this.opacity_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/strokeandfillelement.js b/src/database/third_party/closure-library/closure/goog/graphics/strokeandfillelement.js
    deleted file mode 100644
    index e3b50f99e53..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/strokeandfillelement.js
    +++ /dev/null
    @@ -1,114 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview A thin wrapper around the DOM element for elements with a
    - * stroke and fill.
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -
    -goog.provide('goog.graphics.StrokeAndFillElement');
    -
    -goog.require('goog.graphics.Element');
    -
    -
    -
    -/**
    - * Interface for a graphics element with a stroke and fill.
    - * This is the base interface for ellipse, rectangle and other
    - * shape interfaces.
    - * You should not construct objects from this constructor. The graphics
    - * will return an implementation of this interface for you.
    - *
    - * @param {Element} element The DOM element to wrap.
    - * @param {goog.graphics.AbstractGraphics} graphics The graphics creating
    - *     this element.
    - * @param {goog.graphics.Stroke?} stroke The stroke to use for this element.
    - * @param {goog.graphics.Fill?} fill The fill to use for this element.
    - * @constructor
    - * @extends {goog.graphics.Element}
    - * @deprecated goog.graphics is deprecated. It existed to abstract over browser
    - *     differences before the canvas tag was widely supported.  See
    - *     http://en.wikipedia.org/wiki/Canvas_element for details.
    - */
    -goog.graphics.StrokeAndFillElement = function(element, graphics, stroke, fill) {
    -  goog.graphics.Element.call(this, element, graphics);
    -  this.setStroke(stroke);
    -  this.setFill(fill);
    -};
    -goog.inherits(goog.graphics.StrokeAndFillElement, goog.graphics.Element);
    -
    -
    -/**
    - * The latest fill applied to this element.
    - * @type {goog.graphics.Fill?}
    - * @protected
    - */
    -goog.graphics.StrokeAndFillElement.prototype.fill = null;
    -
    -
    -/**
    - * The latest stroke applied to this element.
    - * @type {goog.graphics.Stroke?}
    - * @private
    - */
    -goog.graphics.StrokeAndFillElement.prototype.stroke_ = null;
    -
    -
    -/**
    - * Sets the fill for this element.
    - * @param {goog.graphics.Fill?} fill The fill object.
    - */
    -goog.graphics.StrokeAndFillElement.prototype.setFill = function(fill) {
    -  this.fill = fill;
    -  this.getGraphics().setElementFill(this, fill);
    -};
    -
    -
    -/**
    - * @return {goog.graphics.Fill?} fill The fill object.
    - */
    -goog.graphics.StrokeAndFillElement.prototype.getFill = function() {
    -  return this.fill;
    -};
    -
    -
    -/**
    - * Sets the stroke for this element.
    - * @param {goog.graphics.Stroke?} stroke The stroke object.
    - */
    -goog.graphics.StrokeAndFillElement.prototype.setStroke = function(stroke) {
    -  this.stroke_ = stroke;
    -  this.getGraphics().setElementStroke(this, stroke);
    -};
    -
    -
    -/**
    - * @return {goog.graphics.Stroke?} stroke The stroke object.
    - */
    -goog.graphics.StrokeAndFillElement.prototype.getStroke = function() {
    -  return this.stroke_;
    -};
    -
    -
    -/**
    - * Re-strokes the element to react to coordinate size changes.
    - */
    -goog.graphics.StrokeAndFillElement.prototype.reapplyStroke = function() {
    -  if (this.stroke_) {
    -    this.setStroke(this.stroke_);
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/svgelement.js b/src/database/third_party/closure-library/closure/goog/graphics/svgelement.js
    deleted file mode 100644
    index eddcbb52301..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/svgelement.js
    +++ /dev/null
    @@ -1,284 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Thin wrappers around the DOM element returned from
    - * the different draw methods of the graphics. This is the SVG implementation.
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -goog.provide('goog.graphics.SvgEllipseElement');
    -goog.provide('goog.graphics.SvgGroupElement');
    -goog.provide('goog.graphics.SvgImageElement');
    -goog.provide('goog.graphics.SvgPathElement');
    -goog.provide('goog.graphics.SvgRectElement');
    -goog.provide('goog.graphics.SvgTextElement');
    -
    -
    -goog.require('goog.dom');
    -goog.require('goog.graphics.EllipseElement');
    -goog.require('goog.graphics.GroupElement');
    -goog.require('goog.graphics.ImageElement');
    -goog.require('goog.graphics.PathElement');
    -goog.require('goog.graphics.RectElement');
    -goog.require('goog.graphics.TextElement');
    -
    -
    -
    -/**
    - * Thin wrapper for SVG group elements.
    - * You should not construct objects from this constructor. The graphics
    - * will return the object for you.
    - * @param {Element} element The DOM element to wrap.
    - * @param {goog.graphics.SvgGraphics} graphics The graphics creating
    - *     this element.
    - * @constructor
    - * @extends {goog.graphics.GroupElement}
    - * @deprecated goog.graphics is deprecated. It existed to abstract over browser
    - *     differences before the canvas tag was widely supported.  See
    - *     http://en.wikipedia.org/wiki/Canvas_element for details.
    - * @final
    - */
    -goog.graphics.SvgGroupElement = function(element, graphics) {
    -  goog.graphics.GroupElement.call(this, element, graphics);
    -};
    -goog.inherits(goog.graphics.SvgGroupElement, goog.graphics.GroupElement);
    -
    -
    -/**
    - * Remove all drawing elements from the group.
    - * @override
    - */
    -goog.graphics.SvgGroupElement.prototype.clear = function() {
    -  goog.dom.removeChildren(this.getElement());
    -};
    -
    -
    -/**
    - * Set the size of the group element.
    - * @param {number|string} width The width of the group element.
    - * @param {number|string} height The height of the group element.
    - * @override
    - */
    -goog.graphics.SvgGroupElement.prototype.setSize = function(width, height) {
    -  this.getGraphics().setElementAttributes(this.getElement(),
    -      {'width': width, 'height': height});
    -};
    -
    -
    -
    -/**
    - * Thin wrapper for SVG ellipse elements.
    - * This is an implementation of the goog.graphics.EllipseElement interface.
    - * You should not construct objects from this constructor. The graphics
    - * will return the object for you.
    - * @param {Element} element The DOM element to wrap.
    - * @param {goog.graphics.SvgGraphics} graphics The graphics creating
    - *     this element.
    - * @param {goog.graphics.Stroke?} stroke The stroke to use for this element.
    - * @param {goog.graphics.Fill?} fill The fill to use for this element.
    - * @constructor
    - * @extends {goog.graphics.EllipseElement}
    - * @final
    - */
    -goog.graphics.SvgEllipseElement = function(element, graphics, stroke, fill) {
    -  goog.graphics.EllipseElement.call(this, element, graphics, stroke, fill);
    -};
    -goog.inherits(goog.graphics.SvgEllipseElement, goog.graphics.EllipseElement);
    -
    -
    -/**
    - * Update the center point of the ellipse.
    - * @param {number} cx Center X coordinate.
    - * @param {number} cy Center Y coordinate.
    - * @override
    - */
    -goog.graphics.SvgEllipseElement.prototype.setCenter = function(cx, cy) {
    -  this.getGraphics().setElementAttributes(this.getElement(),
    -      {'cx': cx, 'cy': cy});
    -};
    -
    -
    -/**
    - * Update the radius of the ellipse.
    - * @param {number} rx Radius length for the x-axis.
    - * @param {number} ry Radius length for the y-axis.
    - * @override
    - */
    -goog.graphics.SvgEllipseElement.prototype.setRadius = function(rx, ry) {
    -  this.getGraphics().setElementAttributes(this.getElement(),
    -      {'rx': rx, 'ry': ry});
    -};
    -
    -
    -
    -/**
    - * Thin wrapper for SVG rectangle elements.
    - * This is an implementation of the goog.graphics.RectElement interface.
    - * You should not construct objects from this constructor. The graphics
    - * will return the object for you.
    - * @param {Element} element The DOM element to wrap.
    - * @param {goog.graphics.SvgGraphics} graphics The graphics creating
    - *     this element.
    - * @param {goog.graphics.Stroke?} stroke The stroke to use for this element.
    - * @param {goog.graphics.Fill?} fill The fill to use for this element.
    - * @constructor
    - * @extends {goog.graphics.RectElement}
    - * @final
    - */
    -goog.graphics.SvgRectElement = function(element, graphics, stroke, fill) {
    -  goog.graphics.RectElement.call(this, element, graphics, stroke, fill);
    -};
    -goog.inherits(goog.graphics.SvgRectElement, goog.graphics.RectElement);
    -
    -
    -/**
    - * Update the position of the rectangle.
    - * @param {number} x X coordinate (left).
    - * @param {number} y Y coordinate (top).
    - * @override
    - */
    -goog.graphics.SvgRectElement.prototype.setPosition = function(x, y) {
    -  this.getGraphics().setElementAttributes(this.getElement(), {'x': x, 'y': y});
    -};
    -
    -
    -/**
    - * Update the size of the rectangle.
    - * @param {number} width Width of rectangle.
    - * @param {number} height Height of rectangle.
    - * @override
    - */
    -goog.graphics.SvgRectElement.prototype.setSize = function(width, height) {
    -  this.getGraphics().setElementAttributes(this.getElement(),
    -      {'width': width, 'height': height});
    -};
    -
    -
    -
    -/**
    - * Thin wrapper for SVG path elements.
    - * This is an implementation of the goog.graphics.PathElement interface.
    - * You should not construct objects from this constructor. The graphics
    - * will return the object for you.
    - * @param {Element} element The DOM element to wrap.
    - * @param {goog.graphics.SvgGraphics} graphics The graphics creating
    - *     this element.
    - * @param {goog.graphics.Stroke?} stroke The stroke to use for this element.
    - * @param {goog.graphics.Fill?} fill The fill to use for this element.
    - * @constructor
    - * @extends {goog.graphics.PathElement}
    - * @final
    - */
    -goog.graphics.SvgPathElement = function(element, graphics, stroke, fill) {
    -  goog.graphics.PathElement.call(this, element, graphics, stroke, fill);
    -};
    -goog.inherits(goog.graphics.SvgPathElement, goog.graphics.PathElement);
    -
    -
    -/**
    - * Update the underlying path.
    - * @param {!goog.graphics.Path} path The path object to draw.
    - * @override
    - */
    -goog.graphics.SvgPathElement.prototype.setPath = function(path) {
    -  this.getGraphics().setElementAttributes(this.getElement(),
    -      {'d': /** @suppress {missingRequire} */
    -            goog.graphics.SvgGraphics.getSvgPath(path)});
    -};
    -
    -
    -
    -/**
    - * Thin wrapper for SVG text elements.
    - * This is an implementation of the goog.graphics.TextElement interface.
    - * You should not construct objects from this constructor. The graphics
    - * will return the object for you.
    - * @param {Element} element The DOM element to wrap.
    - * @param {goog.graphics.SvgGraphics} graphics The graphics creating
    - *     this element.
    - * @param {goog.graphics.Stroke?} stroke The stroke to use for this element.
    - * @param {goog.graphics.Fill?} fill The fill to use for this element.
    - * @constructor
    - * @extends {goog.graphics.TextElement}
    - * @final
    - */
    -goog.graphics.SvgTextElement = function(element, graphics, stroke, fill) {
    -  goog.graphics.TextElement.call(this, element, graphics, stroke, fill);
    -};
    -goog.inherits(goog.graphics.SvgTextElement, goog.graphics.TextElement);
    -
    -
    -/**
    - * Update the displayed text of the element.
    - * @param {string} text The text to draw.
    - * @override
    - */
    -goog.graphics.SvgTextElement.prototype.setText = function(text) {
    -  this.getElement().firstChild.data = text;
    -};
    -
    -
    -
    -/**
    - * Thin wrapper for SVG image elements.
    - * This is an implementation of the goog.graphics.ImageElement interface.
    - * You should not construct objects from this constructor. The graphics
    - * will return the object for you.
    - * @param {Element} element The DOM element to wrap.
    - * @param {goog.graphics.SvgGraphics} graphics The graphics creating
    - *     this element.
    - * @constructor
    - * @extends {goog.graphics.ImageElement}
    - * @final
    - */
    -goog.graphics.SvgImageElement = function(element, graphics) {
    -  goog.graphics.ImageElement.call(this, element, graphics);
    -};
    -goog.inherits(goog.graphics.SvgImageElement, goog.graphics.ImageElement);
    -
    -
    -/**
    - * Update the position of the image.
    - * @param {number} x X coordinate (left).
    - * @param {number} y Y coordinate (top).
    - * @override
    - */
    -goog.graphics.SvgImageElement.prototype.setPosition = function(x, y) {
    -  this.getGraphics().setElementAttributes(this.getElement(), {'x': x, 'y': y});
    -};
    -
    -
    -/**
    - * Update the size of the image.
    - * @param {number} width Width of image.
    - * @param {number} height Height of image.
    - * @override
    - */
    -goog.graphics.SvgImageElement.prototype.setSize = function(width, height) {
    -  this.getGraphics().setElementAttributes(this.getElement(),
    -      {'width': width, 'height': height});
    -};
    -
    -
    -/**
    - * Update the source of the image.
    - * @param {string} src Source of the image.
    - * @override
    - */
    -goog.graphics.SvgImageElement.prototype.setSource = function(src) {
    -  this.getGraphics().setElementAttributes(this.getElement(),
    -      {'xlink:href': src});
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/svggraphics.js b/src/database/third_party/closure-library/closure/goog/graphics/svggraphics.js
    deleted file mode 100644
    index 59db4a2ad44..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/svggraphics.js
    +++ /dev/null
    @@ -1,878 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview SvgGraphics sub class that uses SVG to draw the graphics.
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -goog.provide('goog.graphics.SvgGraphics');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.dom');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventType');
    -goog.require('goog.graphics.AbstractGraphics');
    -goog.require('goog.graphics.LinearGradient');
    -goog.require('goog.graphics.Path');
    -goog.require('goog.graphics.SolidFill');
    -goog.require('goog.graphics.Stroke');
    -goog.require('goog.graphics.SvgEllipseElement');
    -goog.require('goog.graphics.SvgGroupElement');
    -goog.require('goog.graphics.SvgImageElement');
    -goog.require('goog.graphics.SvgPathElement');
    -goog.require('goog.graphics.SvgRectElement');
    -goog.require('goog.graphics.SvgTextElement');
    -goog.require('goog.math');
    -goog.require('goog.math.Size');
    -goog.require('goog.style');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * A Graphics implementation for drawing using SVG.
    - * @param {string|number} width The width in pixels.  Strings
    - *     expressing percentages of parent with (e.g. '80%') are also accepted.
    - * @param {string|number} height The height in pixels.  Strings
    - *     expressing percentages of parent with (e.g. '80%') are also accepted.
    - * @param {?number=} opt_coordWidth The coordinate width - if
    - *     omitted or null, defaults to same as width.
    - * @param {?number=} opt_coordHeight The coordinate height - if
    - *     omitted or null, defaults to same as height.
    - * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper object for the
    - *     document we want to render in.
    - * @constructor
    - * @extends {goog.graphics.AbstractGraphics}
    - * @deprecated goog.graphics is deprecated. It existed to abstract over browser
    - *     differences before the canvas tag was widely supported.  See
    - *     http://en.wikipedia.org/wiki/Canvas_element for details.
    - * @final
    - */
    -goog.graphics.SvgGraphics = function(width, height,
    -                                     opt_coordWidth, opt_coordHeight,
    -                                     opt_domHelper) {
    -  goog.graphics.AbstractGraphics.call(this, width, height,
    -                                      opt_coordWidth, opt_coordHeight,
    -                                      opt_domHelper);
    -
    -  /**
    -   * Map from def key to id of def root element.
    -   * Defs are global "defines" of svg that are used to share common attributes,
    -   * for example gradients.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.defs_ = {};
    -
    -  /**
    -   * Whether to manually implement viewBox by using a coordinate transform.
    -   * As of 1/11/08 this is necessary for Safari 3 but not for the nightly
    -   * WebKit build. Apply to webkit versions < 526. 525 is the
    -   * last version used by Safari 3.1.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.useManualViewbox_ = goog.userAgent.WEBKIT &&
    -                           !goog.userAgent.isVersionOrHigher(526);
    -
    -  /**
    -   * Event handler.
    -   * @type {goog.events.EventHandler<!goog.graphics.SvgGraphics>}
    -   * @private
    -   */
    -  this.handler_ = new goog.events.EventHandler(this);
    -};
    -goog.inherits(goog.graphics.SvgGraphics, goog.graphics.AbstractGraphics);
    -
    -
    -/**
    - * The SVG namespace URN
    - * @private
    - * @type {string}
    - */
    -goog.graphics.SvgGraphics.SVG_NS_ = 'http://www.w3.org/2000/svg';
    -
    -
    -/**
    - * The name prefix for def entries
    - * @private
    - * @type {string}
    - */
    -goog.graphics.SvgGraphics.DEF_ID_PREFIX_ = '_svgdef_';
    -
    -
    -/**
    - * The next available unique identifier for a def entry.
    - * This is a static variable, so that when multiple graphics are used in one
    - * document, the same def id can not be re-defined by another SvgGraphics.
    - * @type {number}
    - * @private
    - */
    -goog.graphics.SvgGraphics.nextDefId_ = 0;
    -
    -
    -/**
    - * Svg element for definitions for other elements, e.g. linear gradients.
    - * @type {Element}
    - * @private
    - */
    -goog.graphics.SvgGraphics.prototype.defsElement_;
    -
    -
    -/**
    - * Creates an SVG element. Used internally and by different SVG classes.
    - * @param {string} tagName The type of element to create.
    - * @param {Object=} opt_attributes Map of name-value pairs for attributes.
    - * @return {!Element} The created element.
    - * @private
    - */
    -goog.graphics.SvgGraphics.prototype.createSvgElement_ = function(tagName,
    -    opt_attributes) {
    -  var element = this.dom_.getDocument().createElementNS(
    -      goog.graphics.SvgGraphics.SVG_NS_, tagName);
    -
    -  if (opt_attributes) {
    -    this.setElementAttributes(element, opt_attributes);
    -  }
    -
    -  return element;
    -};
    -
    -
    -/**
    - * Sets properties to an SVG element. Used internally and by different
    - * SVG elements.
    - * @param {Element} element The svg element.
    - * @param {Object} attributes Map of name-value pairs for attributes.
    - */
    -goog.graphics.SvgGraphics.prototype.setElementAttributes = function(element,
    -    attributes) {
    -  for (var key in attributes) {
    -    element.setAttribute(key, attributes[key]);
    -  }
    -};
    -
    -
    -/**
    - * Appends an element.
    - *
    - * @param {goog.graphics.Element} element The element wrapper.
    - * @param {goog.graphics.GroupElement=} opt_group The group wrapper element
    - *     to append to. If not specified, appends to the main canvas.
    - * @private
    - */
    -goog.graphics.SvgGraphics.prototype.append_ = function(element, opt_group) {
    -  var parent = opt_group || this.canvasElement;
    -  parent.getElement().appendChild(element.getElement());
    -};
    -
    -
    -/**
    - * Sets the fill of the given element.
    - * @param {goog.graphics.StrokeAndFillElement} element The element wrapper.
    - * @param {goog.graphics.Fill?} fill The fill object.
    - * @override
    - */
    -goog.graphics.SvgGraphics.prototype.setElementFill = function(element, fill) {
    -  var svgElement = element.getElement();
    -  if (fill instanceof goog.graphics.SolidFill) {
    -    svgElement.setAttribute('fill', fill.getColor());
    -    svgElement.setAttribute('fill-opacity', fill.getOpacity());
    -  } else if (fill instanceof goog.graphics.LinearGradient) {
    -    // create a def key which is just a concat of all the relevant fields
    -    var defKey = 'lg-' +
    -                 fill.getX1() + '-' + fill.getY1() + '-' +
    -                 fill.getX2() + '-' + fill.getY2() + '-' +
    -                 fill.getColor1() + '-' + fill.getColor2();
    -    // It seems that the SVG version accepts opacity where the VML does not
    -
    -    var id = this.getDef(defKey);
    -
    -    if (!id) { // No def for this yet, create it
    -      // Create the gradient def entry (only linear gradient are supported)
    -      var gradient = this.createSvgElement_('linearGradient', {
    -        'x1': fill.getX1(),
    -        'y1': fill.getY1(),
    -        'x2': fill.getX2(),
    -        'y2': fill.getY2(),
    -        'gradientUnits': 'userSpaceOnUse'
    -      });
    -
    -      var gstyle = 'stop-color:' + fill.getColor1();
    -      if (goog.isNumber(fill.getOpacity1())) {
    -        gstyle += ';stop-opacity:' + fill.getOpacity1();
    -      }
    -      var stop1 = this.createSvgElement_(
    -          'stop', {'offset': '0%', 'style': gstyle});
    -      gradient.appendChild(stop1);
    -
    -      // LinearGradients don't have opacity in VML so implement that before
    -      // enabling the following code.
    -      // if (fill.getOpacity() != null) {
    -      //   gstyles += 'opacity:' + fill.getOpacity() + ';'
    -      // }
    -      gstyle = 'stop-color:' + fill.getColor2();
    -      if (goog.isNumber(fill.getOpacity2())) {
    -        gstyle += ';stop-opacity:' + fill.getOpacity2();
    -      }
    -      var stop2 = this.createSvgElement_(
    -          'stop', {'offset': '100%', 'style': gstyle});
    -      gradient.appendChild(stop2);
    -
    -      // LinearGradients don't have opacity in VML so implement that before
    -      // enabling the following code.
    -      // if (fill.getOpacity() != null) {
    -      //   gstyles += 'opacity:' + fill.getOpacity() + ';'
    -      // }
    -
    -      id = this.addDef(defKey, gradient);
    -    }
    -
    -    // Link element to linearGradient definition
    -    svgElement.setAttribute('fill', 'url(#' + id + ')');
    -  } else {
    -    svgElement.setAttribute('fill', 'none');
    -  }
    -};
    -
    -
    -/**
    - * Sets the stroke of the given element.
    - * @param {goog.graphics.StrokeAndFillElement} element The element wrapper.
    - * @param {goog.graphics.Stroke?} stroke The stroke object.
    - * @override
    - */
    -goog.graphics.SvgGraphics.prototype.setElementStroke = function(element,
    -    stroke) {
    -  var svgElement = element.getElement();
    -  if (stroke) {
    -    svgElement.setAttribute('stroke', stroke.getColor());
    -    svgElement.setAttribute('stroke-opacity', stroke.getOpacity());
    -
    -    var width = stroke.getWidth();
    -    if (goog.isString(width) && width.indexOf('px') != -1) {
    -      svgElement.setAttribute('stroke-width',
    -          parseFloat(width) / this.getPixelScaleX());
    -    } else {
    -      svgElement.setAttribute('stroke-width', width);
    -    }
    -  } else {
    -    svgElement.setAttribute('stroke', 'none');
    -  }
    -};
    -
    -
    -/**
    - * Set the translation and rotation of an element.
    - *
    - * If a more general affine transform is needed than this provides
    - * (e.g. skew and scale) then use setElementAffineTransform.
    - * @param {goog.graphics.Element} element The element wrapper.
    - * @param {number} x The x coordinate of the translation transform.
    - * @param {number} y The y coordinate of the translation transform.
    - * @param {number} angle The angle of the rotation transform.
    - * @param {number} centerX The horizontal center of the rotation transform.
    - * @param {number} centerY The vertical center of the rotation transform.
    - * @override
    - */
    -goog.graphics.SvgGraphics.prototype.setElementTransform = function(element, x,
    -    y, angle, centerX, centerY) {
    -  element.getElement().setAttribute('transform', 'translate(' + x + ',' + y +
    -      ') rotate(' + angle + ' ' + centerX + ' ' + centerY + ')');
    -};
    -
    -
    -/**
    - * Set the transformation of an element.
    - * @param {goog.graphics.Element} element The element wrapper.
    - * @param {!goog.graphics.AffineTransform} affineTransform The
    - *     transformation applied to this element.
    - * @override
    - */
    -goog.graphics.SvgGraphics.prototype.setElementAffineTransform = function(
    -    element, affineTransform) {
    -  var t = affineTransform;
    -  var substr = [t.getScaleX(), t.getShearY(), t.getShearX(), t.getScaleY(),
    -                t.getTranslateX(), t.getTranslateY()].join(',');
    -  element.getElement().setAttribute('transform', 'matrix(' + substr + ')');
    -};
    -
    -
    -/**
    - * Creates the DOM representation of the graphics area.
    - * @override
    - */
    -goog.graphics.SvgGraphics.prototype.createDom = function() {
    -  // Set up the standard attributes.
    -  var attributes = {
    -    'width': this.width,
    -    'height': this.height,
    -    'overflow': 'hidden'
    -  };
    -
    -  var svgElement = this.createSvgElement_('svg', attributes);
    -
    -  var groupElement = this.createSvgElement_('g');
    -
    -  this.defsElement_ = this.createSvgElement_('defs');
    -  this.canvasElement = new goog.graphics.SvgGroupElement(groupElement, this);
    -
    -  svgElement.appendChild(this.defsElement_);
    -  svgElement.appendChild(groupElement);
    -
    -  // Use the svgElement as the root element.
    -  this.setElementInternal(svgElement);
    -
    -  // Set up the coordinate system.
    -  this.setViewBox_();
    -};
    -
    -
    -/**
    - * Changes the coordinate system position.
    - * @param {number} left The coordinate system left bound.
    - * @param {number} top The coordinate system top bound.
    - * @override
    - */
    -goog.graphics.SvgGraphics.prototype.setCoordOrigin = function(left, top) {
    -  this.coordLeft = left;
    -  this.coordTop = top;
    -
    -  this.setViewBox_();
    -};
    -
    -
    -/**
    - * Changes the coordinate size.
    - * @param {number} coordWidth The coordinate width.
    - * @param {number} coordHeight The coordinate height.
    - * @override
    - */
    -goog.graphics.SvgGraphics.prototype.setCoordSize = function(coordWidth,
    -    coordHeight) {
    -  goog.graphics.SvgGraphics.superClass_.setCoordSize.apply(
    -      this, arguments);
    -  this.setViewBox_();
    -};
    -
    -
    -/**
    - * @return {string} The view box string.
    - * @private
    - */
    -goog.graphics.SvgGraphics.prototype.getViewBox_ = function() {
    -  return this.coordLeft + ' ' + this.coordTop + ' ' +
    -      (this.coordWidth ? this.coordWidth + ' ' + this.coordHeight : '');
    -};
    -
    -
    -/**
    - * Sets up the view box.
    - * @private
    - */
    -goog.graphics.SvgGraphics.prototype.setViewBox_ = function() {
    -  if (this.coordWidth || this.coordLeft || this.coordTop) {
    -    this.getElement().setAttribute('preserveAspectRatio', 'none');
    -    if (this.useManualViewbox_) {
    -      this.updateManualViewBox_();
    -    } else {
    -      this.getElement().setAttribute('viewBox', this.getViewBox_());
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Updates the transform of the root element to fake a viewBox.  Should only
    - * be called when useManualViewbox_ is set.
    - * @private
    - */
    -goog.graphics.SvgGraphics.prototype.updateManualViewBox_ = function() {
    -  if (!this.isInDocument() ||
    -      !(this.coordWidth || this.coordLeft || !this.coordTop)) {
    -    return;
    -  }
    -
    -  var size = this.getPixelSize();
    -  if (size.width == 0) {
    -    // In Safari, invisible SVG is sometimes shown.  Explicitly hide it.
    -    this.getElement().style.visibility = 'hidden';
    -    return;
    -  }
    -
    -  this.getElement().style.visibility = '';
    -
    -  var offsetX = - this.coordLeft;
    -  var offsetY = - this.coordTop;
    -  var scaleX = size.width / this.coordWidth;
    -  var scaleY = size.height / this.coordHeight;
    -
    -  this.canvasElement.getElement().setAttribute('transform',
    -      'scale(' + scaleX + ' ' + scaleY + ') ' +
    -      'translate(' + offsetX + ' ' + offsetY + ')');
    -};
    -
    -
    -/**
    - * Change the size of the canvas.
    - * @param {number} pixelWidth The width in pixels.
    - * @param {number} pixelHeight The height in pixels.
    - * @override
    - */
    -goog.graphics.SvgGraphics.prototype.setSize = function(pixelWidth,
    -    pixelHeight) {
    -  goog.style.setSize(this.getElement(), pixelWidth, pixelHeight);
    -};
    -
    -
    -/** @override */
    -goog.graphics.SvgGraphics.prototype.getPixelSize = function() {
    -  if (!goog.userAgent.GECKO) {
    -    return this.isInDocument() ?
    -        goog.style.getSize(this.getElement()) :
    -        goog.graphics.SvgGraphics.base(this, 'getPixelSize');
    -  }
    -
    -  // In Gecko, goog.style.getSize does not work for SVG elements.  We have to
    -  // compute the size manually if it is percentage based.
    -  var width = this.width;
    -  var height = this.height;
    -  var computeWidth = goog.isString(width) && width.indexOf('%') != -1;
    -  var computeHeight = goog.isString(height) && height.indexOf('%') != -1;
    -
    -  if (!this.isInDocument() && (computeWidth || computeHeight)) {
    -    return null;
    -  }
    -
    -  var parent;
    -  var parentSize;
    -
    -  if (computeWidth) {
    -    parent = /** @type {Element} */ (this.getElement().parentNode);
    -    parentSize = goog.style.getSize(parent);
    -    width = parseFloat(/** @type {string} */ (width)) * parentSize.width / 100;
    -  }
    -
    -  if (computeHeight) {
    -    parent = parent || /** @type {Element} */ (this.getElement().parentNode);
    -    parentSize = parentSize || goog.style.getSize(parent);
    -    height = parseFloat(/** @type {string} */ (height)) * parentSize.height /
    -        100;
    -  }
    -
    -  return new goog.math.Size(/** @type {number} */ (width),
    -      /** @type {number} */ (height));
    -};
    -
    -
    -/**
    - * Remove all drawing elements from the graphics.
    - * @override
    - */
    -goog.graphics.SvgGraphics.prototype.clear = function() {
    -  this.canvasElement.clear();
    -  goog.dom.removeChildren(this.defsElement_);
    -  this.defs_ = {};
    -};
    -
    -
    -/**
    - * Draw an ellipse.
    - *
    - * @param {number} cx Center X coordinate.
    - * @param {number} cy Center Y coordinate.
    - * @param {number} rx Radius length for the x-axis.
    - * @param {number} ry Radius length for the y-axis.
    - * @param {goog.graphics.Stroke?} stroke Stroke object describing the
    - *    stroke.
    - * @param {goog.graphics.Fill?} fill Fill object describing the fill.
    - * @param {goog.graphics.GroupElement=} opt_group The group wrapper element
    - *     to append to. If not specified, appends to the main canvas.
    - *
    - * @return {!goog.graphics.EllipseElement} The newly created element.
    - * @override
    - */
    -goog.graphics.SvgGraphics.prototype.drawEllipse = function(
    -    cx, cy, rx, ry, stroke, fill, opt_group) {
    -  var element = this.createSvgElement_('ellipse',
    -      {'cx': cx, 'cy': cy, 'rx': rx, 'ry': ry});
    -  var wrapper = new goog.graphics.SvgEllipseElement(element, this, stroke,
    -      fill);
    -  this.append_(wrapper, opt_group);
    -  return wrapper;
    -};
    -
    -
    -/**
    - * Draw a rectangle.
    - *
    - * @param {number} x X coordinate (left).
    - * @param {number} y Y coordinate (top).
    - * @param {number} width Width of rectangle.
    - * @param {number} height Height of rectangle.
    - * @param {goog.graphics.Stroke?} stroke Stroke object describing the
    - *    stroke.
    - * @param {goog.graphics.Fill?} fill Fill object describing the fill.
    - * @param {goog.graphics.GroupElement=} opt_group The group wrapper element
    - *     to append to. If not specified, appends to the main canvas.
    - *
    - * @return {!goog.graphics.RectElement} The newly created element.
    - * @override
    - */
    -goog.graphics.SvgGraphics.prototype.drawRect = function(x, y, width, height,
    -    stroke, fill, opt_group) {
    -  var element = this.createSvgElement_('rect',
    -      {'x': x, 'y': y, 'width': width, 'height': height});
    -  var wrapper = new goog.graphics.SvgRectElement(element, this, stroke, fill);
    -  this.append_(wrapper, opt_group);
    -  return wrapper;
    -};
    -
    -
    -/**
    - * Draw an image.
    - *
    - * @param {number} x X coordinate (left).
    - * @param {number} y Y coordinate (top).
    - * @param {number} width Width of the image.
    - * @param {number} height Height of the image.
    - * @param {string} src The source fo the image.
    - * @param {goog.graphics.GroupElement=} opt_group The group wrapper element
    - *     to append to. If not specified, appends to the main canvas.
    - *
    - * @return {!goog.graphics.ImageElement} The newly created image wrapped in a
    - *     rectangle element.
    - */
    -goog.graphics.SvgGraphics.prototype.drawImage = function(x, y, width, height,
    -    src, opt_group) {
    -  var element = this.createSvgElement_('image', {
    -    'x': x,
    -    'y': y,
    -    'width': width,
    -    'height': height,
    -    'image-rendering': 'optimizeQuality',
    -    'preserveAspectRatio': 'none'
    -  });
    -  element.setAttributeNS('http://www.w3.org/1999/xlink', 'href', src);
    -  var wrapper = new goog.graphics.SvgImageElement(element, this);
    -  this.append_(wrapper, opt_group);
    -  return wrapper;
    -};
    -
    -
    -/**
    - * Draw a text string vertically centered on a given line.
    - *
    - * @param {string} text The text to draw.
    - * @param {number} x1 X coordinate of start of line.
    - * @param {number} y1 Y coordinate of start of line.
    - * @param {number} x2 X coordinate of end of line.
    - * @param {number} y2 Y coordinate of end of line.
    - * @param {string} align Horizontal alignment: left (default), center, right.
    - * @param {goog.graphics.Font} font Font describing the font properties.
    - * @param {goog.graphics.Stroke?} stroke Stroke object describing the
    - *    stroke.
    - * @param {goog.graphics.Fill?} fill Fill object describing the fill.
    - * @param {goog.graphics.GroupElement=} opt_group The group wrapper element
    - *     to append to. If not specified, appends to the main canvas.
    - *
    - * @return {!goog.graphics.TextElement} The newly created element.
    - * @override
    - */
    -goog.graphics.SvgGraphics.prototype.drawTextOnLine = function(
    -    text, x1, y1, x2, y2, align, font, stroke, fill, opt_group) {
    -  var angle = Math.round(goog.math.angle(x1, y1, x2, y2));
    -  var dx = x2 - x1;
    -  var dy = y2 - y1;
    -  var lineLength = Math.round(Math.sqrt(dx * dx + dy * dy)); // Length of line
    -
    -  // SVG baseline is on the glyph's base line. We estimate it as 85% of the
    -  // font height. This is just a rough estimate, but do not have a better way.
    -  var fontSize = font.size;
    -  var attributes = {'font-family': font.family, 'font-size': fontSize};
    -  var baseline = Math.round(fontSize * 0.85);
    -  var textY = Math.round(y1 - (fontSize / 2) + baseline);
    -  var textX = x1;
    -  if (align == 'center') {
    -    textX += Math.round(lineLength / 2);
    -    attributes['text-anchor'] = 'middle';
    -  } else if (align == 'right') {
    -    textX += lineLength;
    -    attributes['text-anchor'] = 'end';
    -  }
    -  attributes['x'] = textX;
    -  attributes['y'] = textY;
    -  if (font.bold) {
    -    attributes['font-weight'] = 'bold';
    -  }
    -  if (font.italic) {
    -    attributes['font-style'] = 'italic';
    -  }
    -  if (angle != 0) {
    -    attributes['transform'] = 'rotate(' + angle + ' ' + x1 + ' ' + y1 + ')';
    -  }
    -
    -  var element = this.createSvgElement_('text', attributes);
    -  element.appendChild(this.dom_.getDocument().createTextNode(text));
    -
    -  // Bypass a Firefox-Mac bug where text fill is ignored. If text has no stroke,
    -  // set a stroke, otherwise the text will not be visible.
    -  if (stroke == null && goog.userAgent.GECKO && goog.userAgent.MAC) {
    -    var color = 'black';
    -    // For solid fills, use the fill color
    -    if (fill instanceof goog.graphics.SolidFill) {
    -      color = fill.getColor();
    -    }
    -    stroke = new goog.graphics.Stroke(1, color);
    -  }
    -
    -  var wrapper = new goog.graphics.SvgTextElement(element, this, stroke, fill);
    -  this.append_(wrapper, opt_group);
    -  return wrapper;
    -};
    -
    -
    -/**
    - * Draw a path.
    - *
    - * @param {!goog.graphics.Path} path The path object to draw.
    - * @param {goog.graphics.Stroke?} stroke Stroke object describing the
    - *    stroke.
    - * @param {goog.graphics.Fill?} fill Fill object describing the fill.
    - * @param {goog.graphics.GroupElement=} opt_group The group wrapper element
    - *     to append to. If not specified, appends to the main canvas.
    - *
    - * @return {!goog.graphics.PathElement} The newly created element.
    - * @override
    - */
    -goog.graphics.SvgGraphics.prototype.drawPath = function(
    -    path, stroke, fill, opt_group) {
    -
    -  var element = this.createSvgElement_('path',
    -      {'d': goog.graphics.SvgGraphics.getSvgPath(path)});
    -  var wrapper = new goog.graphics.SvgPathElement(element, this, stroke, fill);
    -  this.append_(wrapper, opt_group);
    -  return wrapper;
    -};
    -
    -
    -/**
    - * Returns a string representation of a logical path suitable for use in
    - * an SVG element.
    - *
    - * @param {goog.graphics.Path} path The logical path.
    - * @return {string} The SVG path representation.
    - * @suppress {deprecated} goog.graphics is deprecated.
    - */
    -goog.graphics.SvgGraphics.getSvgPath = function(path) {
    -  var list = [];
    -  path.forEachSegment(function(segment, args) {
    -    switch (segment) {
    -      case goog.graphics.Path.Segment.MOVETO:
    -        list.push('M');
    -        Array.prototype.push.apply(list, args);
    -        break;
    -      case goog.graphics.Path.Segment.LINETO:
    -        list.push('L');
    -        Array.prototype.push.apply(list, args);
    -        break;
    -      case goog.graphics.Path.Segment.CURVETO:
    -        list.push('C');
    -        Array.prototype.push.apply(list, args);
    -        break;
    -      case goog.graphics.Path.Segment.ARCTO:
    -        var extent = args[3];
    -        list.push('A', args[0], args[1],
    -            0, Math.abs(extent) > 180 ? 1 : 0, extent > 0 ? 1 : 0,
    -            args[4], args[5]);
    -        break;
    -      case goog.graphics.Path.Segment.CLOSE:
    -        list.push('Z');
    -        break;
    -    }
    -  });
    -  return list.join(' ');
    -};
    -
    -
    -/**
    - * Create an empty group of drawing elements.
    - *
    - * @param {goog.graphics.GroupElement=} opt_group The group wrapper element
    - *     to append to. If not specified, appends to the main canvas.
    - *
    - * @return {!goog.graphics.GroupElement} The newly created group.
    - * @override
    - */
    -goog.graphics.SvgGraphics.prototype.createGroup = function(opt_group) {
    -  var element = this.createSvgElement_('g');
    -  var parent = opt_group || this.canvasElement;
    -  parent.getElement().appendChild(element);
    -  return new goog.graphics.SvgGroupElement(element, this);
    -};
    -
    -
    -/**
    - * Measure and return the width (in pixels) of a given text string.
    - * Text measurement is needed to make sure a text can fit in the allocated area.
    - * The way text length is measured is by writing it into a div that is after
    - * the visible area, measure the div width, and immediatly erase the written
    - * value.
    - *
    - * @param {string} text The text string to measure.
    - * @param {goog.graphics.Font} font The font object describing the font style.
    - * @override
    - */
    -goog.graphics.SvgGraphics.prototype.getTextWidth = function(text, font) {
    -  // TODO(user) Implement
    -};
    -
    -
    -/**
    - * Adds a defintion of an element to the global definitions.
    - * @param {string} defKey This is a key that should be unique in a way that
    - *     if two definitions are equal the should have the same key.
    - * @param {Element} defElement DOM element to add as a definition. It must
    - *     have an id attribute set.
    - * @return {string} The assigned id of the defElement.
    - */
    -goog.graphics.SvgGraphics.prototype.addDef = function(defKey, defElement) {
    -  if (defKey in this.defs_) {
    -    return this.defs_[defKey];
    -  }
    -  var id = goog.graphics.SvgGraphics.DEF_ID_PREFIX_ +
    -      goog.graphics.SvgGraphics.nextDefId_++;
    -  defElement.setAttribute('id', id);
    -  this.defs_[defKey] = id;
    -
    -  // Add the def defElement of the defs list.
    -  var defs = this.defsElement_;
    -  defs.appendChild(defElement);
    -  return id;
    -};
    -
    -
    -/**
    - * Returns the id of a definition element.
    - * @param {string} defKey This is a key that should be unique in a way that
    - *     if two definitions are equal the should have the same key.
    - * @return {?string} The id of the found definition element or null if
    - *     not found.
    - */
    -goog.graphics.SvgGraphics.prototype.getDef = function(defKey) {
    -  return defKey in this.defs_ ? this.defs_[defKey] : null;
    -};
    -
    -
    -/**
    - * Removes a definition of an elemnt from the global definitions.
    - * @param {string} defKey This is a key that should be unique in a way that
    - *     if two definitions are equal they should have the same key.
    - */
    -goog.graphics.SvgGraphics.prototype.removeDef = function(defKey) {
    -  var id = this.getDef(defKey);
    -  if (id) {
    -    var element = this.dom_.getElement(id);
    -    this.defsElement_.removeChild(element);
    -    delete this.defs_[defKey];
    -  }
    -};
    -
    -
    -/** @override */
    -goog.graphics.SvgGraphics.prototype.enterDocument = function() {
    -  var oldPixelSize = this.getPixelSize();
    -  goog.graphics.SvgGraphics.superClass_.enterDocument.call(this);
    -
    -  // Dispatch a resize if this is the first time the size value is accurate.
    -  if (!oldPixelSize) {
    -    this.dispatchEvent(goog.events.EventType.RESIZE);
    -  }
    -
    -
    -  // For percentage based heights, listen for changes to size.
    -  if (this.useManualViewbox_) {
    -    var width = this.width;
    -    var height = this.height;
    -
    -    if (typeof width == 'string' && width.indexOf('%') != -1 &&
    -        typeof height == 'string' && height.indexOf('%') != -1) {
    -      // SVG elements don't behave well with respect to size events, so we
    -      // resort to polling.
    -      this.handler_.listen(goog.graphics.SvgGraphics.getResizeCheckTimer_(),
    -          goog.Timer.TICK, this.updateManualViewBox_);
    -    }
    -
    -    this.updateManualViewBox_();
    -  }
    -};
    -
    -
    -/** @override */
    -goog.graphics.SvgGraphics.prototype.exitDocument = function() {
    -  goog.graphics.SvgGraphics.superClass_.exitDocument.call(this);
    -
    -  // Stop polling.
    -  if (this.useManualViewbox_) {
    -    this.handler_.unlisten(goog.graphics.SvgGraphics.getResizeCheckTimer_(),
    -        goog.Timer.TICK, this.updateManualViewBox_);
    -  }
    -};
    -
    -
    -/**
    - * Disposes of the component by removing event handlers, detacing DOM nodes from
    - * the document body, and removing references to them.
    - * @override
    - * @protected
    - */
    -goog.graphics.SvgGraphics.prototype.disposeInternal = function() {
    -  delete this.defs_;
    -  delete this.defsElement_;
    -  delete this.canvasElement;
    -  this.handler_.dispose();
    -  delete this.handler_;
    -  goog.graphics.SvgGraphics.superClass_.disposeInternal.call(this);
    -};
    -
    -
    -/**
    - * The centralized resize checking timer.
    - * @type {goog.Timer|undefined}
    - * @private
    - */
    -goog.graphics.SvgGraphics.resizeCheckTimer_;
    -
    -
    -/**
    - * @return {goog.Timer} The centralized timer object used for interval timing.
    - * @private
    - */
    -goog.graphics.SvgGraphics.getResizeCheckTimer_ = function() {
    -  if (!goog.graphics.SvgGraphics.resizeCheckTimer_) {
    -    goog.graphics.SvgGraphics.resizeCheckTimer_ = new goog.Timer(400);
    -    goog.graphics.SvgGraphics.resizeCheckTimer_.start();
    -  }
    -
    -  return /** @type {goog.Timer} */ (
    -      goog.graphics.SvgGraphics.resizeCheckTimer_);
    -};
    -
    -
    -/** @override */
    -goog.graphics.SvgGraphics.prototype.isDomClonable = function() {
    -  return true;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/svggraphics_test.html b/src/database/third_party/closure-library/closure/goog/graphics/svggraphics_test.html
    deleted file mode 100644
    index bb23ffbeff8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/svggraphics_test.html
    +++ /dev/null
    @@ -1,109 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.graphics.SvgGraphics</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.dom');
    -  goog.require('goog.graphics.SvgGraphics');
    -  goog.require('goog.testing.graphics');
    -  goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -<div id="root"> </div>
    -
    -<script>
    -  var graphics;
    -
    -  function setUp() {
    -    if (!document.createElementNS) {
    -      // Some browsers don't support document.createElementNS and this test
    -      // should not be run on those browsers (IE7,8).
    -      return;
    -    }
    -    graphics = new goog.graphics.SvgGraphics('100px', '100px');
    -    graphics.createDom();
    -    goog.dom.getElement('root').appendChild(graphics.getElement());
    -  }
    -
    -  function testAddDef() {
    -    if (!graphics) {
    -      // setUp has failed (no browser support), we should not run this test.
    -      return;
    -    }
    -    var defElement1 = document.createElement('div');
    -    var defElement2 = document.createElement('div');
    -    var defKey1 = 'def1';
    -    var defKey2 = 'def2';
    -    var id = graphics.addDef(defKey1, defElement1);
    -    assertEquals('_svgdef_0', id);
    -    id = graphics.addDef(defKey1, defElement2);
    -    assertEquals('_svgdef_0', id);
    -    id = graphics.addDef(defKey2, defElement2);
    -    assertEquals('_svgdef_1', id);
    -  }
    -
    -  function testGetDef() {
    -    if (!graphics) {
    -      // setUp has failed (no browser support), we should not run this test.
    -      return;
    -    }
    -    var defElement = document.createElement('div');
    -    var defKey = 'def';
    -    var id = graphics.addDef(defKey, defElement);
    -    assertEquals(id, graphics.getDef(defKey));
    -    assertNull(graphics.getDef('randomKey'));
    -  }
    -
    -  function testRemoveDef() {
    -    if (!graphics) {
    -      // setUp has failed (no browser support), we should not run this test.
    -      return;
    -    }
    -    var defElement = document.createElement('div');
    -    var defKey = 'def';
    -    var addedId = graphics.addDef(defKey, defElement);
    -    graphics.removeDef('randomKey');
    -    assertEquals(addedId, graphics.getDef(defKey));
    -    graphics.removeDef(defKey);
    -    assertNull(graphics.getDef(defKey));
    -  }
    -
    -  function testSetElementAffineTransform() {
    -    if (!graphics) {
    -      // setUp has failed (no browser support), we should not run this test.
    -      return;
    -    }
    -    var fill = new goog.graphics.SolidFill('blue');
    -    var stroke = null;
    -    var rad = -3.1415926 / 6;
    -    var costheta = Math.cos(rad);
    -    var sintheta = Math.sin(rad);
    -    var dx = 10;
    -    var dy = -20;
    -    var affine = new goog.graphics.AffineTransform(
    -      costheta, -sintheta + 1, sintheta, costheta, dx, dy);
    -    var rect = graphics.drawRect(10, 20, 30, 40, stroke, fill);
    -    rect.setTransform(affine);
    -    graphics.render();
    -    var svgMatrix = rect.getElement().getTransformToElement(graphics.getElement());
    -    assertRoughlyEquals(svgMatrix.a, costheta, 0.001);
    -    assertRoughlyEquals(svgMatrix.b, -sintheta + 1, 0.001);
    -    assertRoughlyEquals(svgMatrix.c, sintheta, 0.001);
    -    assertRoughlyEquals(svgMatrix.d, costheta, 0.001);
    -    assertRoughlyEquals(svgMatrix.e, dx, 0.001);
    -    assertRoughlyEquals(svgMatrix.f, dy, 0.001);
    -  }
    -</script>
    -</body>
    -</html>
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/textelement.js b/src/database/third_party/closure-library/closure/goog/graphics/textelement.js
    deleted file mode 100644
    index c96ae6d1f22..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/textelement.js
    +++ /dev/null
    @@ -1,55 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview A thin wrapper around the DOM element for text elements.
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -
    -goog.provide('goog.graphics.TextElement');
    -
    -goog.require('goog.graphics.StrokeAndFillElement');
    -
    -
    -
    -/**
    - * Interface for a graphics text element.
    - * You should not construct objects from this constructor. The graphics
    - * will return an implementation of this interface for you.
    - *
    - * @param {Element} element The DOM element to wrap.
    - * @param {goog.graphics.AbstractGraphics} graphics The graphics creating
    - *     this element.
    - * @param {goog.graphics.Stroke?} stroke The stroke to use for this element.
    - * @param {goog.graphics.Fill?} fill The fill to use for this element.
    - * @constructor
    - * @extends {goog.graphics.StrokeAndFillElement}
    - * @deprecated goog.graphics is deprecated. It existed to abstract over browser
    - *     differences before the canvas tag was widely supported.  See
    - *     http://en.wikipedia.org/wiki/Canvas_element for details.
    - */
    -goog.graphics.TextElement = function(element, graphics, stroke, fill) {
    -  goog.graphics.StrokeAndFillElement.call(this, element, graphics, stroke,
    -      fill);
    -};
    -goog.inherits(goog.graphics.TextElement, goog.graphics.StrokeAndFillElement);
    -
    -
    -/**
    - * Update the displayed text of the element.
    - * @param {string} text The text to draw.
    - */
    -goog.graphics.TextElement.prototype.setText = goog.abstractMethod;
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/vmlelement.js b/src/database/third_party/closure-library/closure/goog/graphics/vmlelement.js
    deleted file mode 100644
    index 9e72b132730..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/vmlelement.js
    +++ /dev/null
    @@ -1,438 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Thin wrappers around the DOM element returned from
    - * the different draw methods of the graphics. This is the VML implementation.
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -goog.provide('goog.graphics.VmlEllipseElement');
    -goog.provide('goog.graphics.VmlGroupElement');
    -goog.provide('goog.graphics.VmlImageElement');
    -goog.provide('goog.graphics.VmlPathElement');
    -goog.provide('goog.graphics.VmlRectElement');
    -goog.provide('goog.graphics.VmlTextElement');
    -
    -
    -goog.require('goog.dom');
    -goog.require('goog.graphics.EllipseElement');
    -goog.require('goog.graphics.GroupElement');
    -goog.require('goog.graphics.ImageElement');
    -goog.require('goog.graphics.PathElement');
    -goog.require('goog.graphics.RectElement');
    -goog.require('goog.graphics.TextElement');
    -
    -
    -/**
    - * Returns the VML element corresponding to this object.  This method is added
    - * to several classes below.  Note that the return value of this method may
    - * change frequently in IE8, so it should not be cached externally.
    - * @return {Element} The VML element corresponding to this object.
    - * @this {goog.graphics.VmlGroupElement|goog.graphics.VmlEllipseElement|
    - *     goog.graphics.VmlRectElement|goog.graphics.VmlPathElement|
    - *     goog.graphics.VmlTextElement|goog.graphics.VmlImageElement}
    - * @private
    - */
    -goog.graphics.vmlGetElement_ = function() {
    -  this.element_ = this.getGraphics().getVmlElement(this.id_) || this.element_;
    -  return this.element_;
    -};
    -
    -
    -
    -/**
    - * Thin wrapper for VML group elements.
    - * This is an implementation of the goog.graphics.GroupElement interface.
    - * You should not construct objects from this constructor. The graphics
    - * will return the object for you.
    - * @param {Element} element The DOM element to wrap.
    - * @param {goog.graphics.VmlGraphics} graphics The graphics creating
    - *     this element.
    - * @constructor
    - * @extends {goog.graphics.GroupElement}
    - * @deprecated goog.graphics is deprecated. It existed to abstract over browser
    - *     differences before the canvas tag was widely supported.  See
    - *     http://en.wikipedia.org/wiki/Canvas_element for details.
    - * @final
    - */
    -goog.graphics.VmlGroupElement = function(element, graphics) {
    -  this.id_ = element.id;
    -  goog.graphics.GroupElement.call(this, element, graphics);
    -};
    -goog.inherits(goog.graphics.VmlGroupElement, goog.graphics.GroupElement);
    -
    -
    -/** @override */
    -goog.graphics.VmlGroupElement.prototype.getElement =
    -    goog.graphics.vmlGetElement_;
    -
    -
    -/**
    - * Remove all drawing elements from the group.
    - * @override
    - */
    -goog.graphics.VmlGroupElement.prototype.clear = function() {
    -  goog.dom.removeChildren(this.getElement());
    -};
    -
    -
    -/**
    - * @return {boolean} True if this group is the root canvas element.
    - * @private
    - */
    -goog.graphics.VmlGroupElement.prototype.isRootElement_ = function() {
    -  return this.getGraphics().getCanvasElement() == this;
    -};
    -
    -
    -/**
    - * Set the size of the group element.
    - * @param {number|string} width The width of the group element.
    - * @param {number|string} height The height of the group element.
    - * @override
    - */
    -goog.graphics.VmlGroupElement.prototype.setSize = function(width, height) {
    -  var element = this.getElement();
    -
    -  var style = element.style;
    -  style.width = /** @suppress {missingRequire} */ (
    -      goog.graphics.VmlGraphics.toSizePx(width));
    -  style.height = /** @suppress {missingRequire} */ (
    -      goog.graphics.VmlGraphics.toSizePx(height));
    -
    -  element.coordsize = /** @suppress {missingRequire} */
    -      goog.graphics.VmlGraphics.toSizeCoord(width) +
    -      ' ' +
    -      /** @suppress {missingRequire} */
    -      goog.graphics.VmlGraphics.toSizeCoord(height);
    -
    -  // Don't overwrite the root element's origin.
    -  if (!this.isRootElement_()) {
    -    element.coordorigin = '0 0';
    -  }
    -};
    -
    -
    -
    -/**
    - * Thin wrapper for VML ellipse elements.
    - * This is an implementation of the goog.graphics.EllipseElement interface.
    - * You should not construct objects from this constructor. The graphics
    - * will return the object for you.
    - * @param {Element} element The DOM element to wrap.
    - * @param {goog.graphics.VmlGraphics} graphics  The graphics creating
    - *     this element.
    - * @param {number} cx Center X coordinate.
    - * @param {number} cy Center Y coordinate.
    - * @param {number} rx Radius length for the x-axis.
    - * @param {number} ry Radius length for the y-axis.
    - * @param {goog.graphics.Stroke?} stroke The stroke to use for this element.
    - * @param {goog.graphics.Fill?} fill The fill to use for this element.
    - * @constructor
    - * @extends {goog.graphics.EllipseElement}
    - * @deprecated goog.graphics is deprecated. It existed to abstract over browser
    - *     differences before the canvas tag was widely supported.  See
    - *     http://en.wikipedia.org/wiki/Canvas_element for details.
    - * @final
    - */
    -goog.graphics.VmlEllipseElement = function(element, graphics,
    -    cx, cy, rx, ry, stroke, fill) {
    -  this.id_ = element.id;
    -
    -  goog.graphics.EllipseElement.call(this, element, graphics, stroke, fill);
    -
    -  // Store center and radius for future calls to setRadius or setCenter.
    -
    -  /**
    -   * X coordinate of the ellipse center.
    -   * @type {number}
    -   */
    -  this.cx = cx;
    -
    -
    -  /**
    -   * Y coordinate of the ellipse center.
    -   * @type {number}
    -   */
    -  this.cy = cy;
    -
    -
    -  /**
    -   * Radius length for the x-axis.
    -   * @type {number}
    -   */
    -  this.rx = rx;
    -
    -
    -  /**
    -   * Radius length for the y-axis.
    -   * @type {number}
    -   */
    -  this.ry = ry;
    -};
    -goog.inherits(goog.graphics.VmlEllipseElement, goog.graphics.EllipseElement);
    -
    -
    -/** @override */
    -goog.graphics.VmlEllipseElement.prototype.getElement =
    -    goog.graphics.vmlGetElement_;
    -
    -
    -/**
    - * Update the center point of the ellipse.
    - * @param {number} cx Center X coordinate.
    - * @param {number} cy Center Y coordinate.
    - * @override
    - */
    -goog.graphics.VmlEllipseElement.prototype.setCenter = function(cx, cy) {
    -  this.cx = cx;
    -  this.cy = cy;
    -  /** @suppress {missingRequire} */
    -  goog.graphics.VmlGraphics.setPositionAndSize(this.getElement(),
    -      cx - this.rx, cy - this.ry, this.rx * 2, this.ry * 2);
    -};
    -
    -
    -/**
    - * Update the radius of the ellipse.
    - * @param {number} rx Center X coordinate.
    - * @param {number} ry Center Y coordinate.
    - * @override
    - */
    -goog.graphics.VmlEllipseElement.prototype.setRadius = function(rx, ry) {
    -  this.rx = rx;
    -  this.ry = ry;
    -  /** @suppress {missingRequire} */
    -  goog.graphics.VmlGraphics.setPositionAndSize(this.getElement(),
    -      this.cx - rx, this.cy - ry, rx * 2, ry * 2);
    -};
    -
    -
    -
    -/**
    - * Thin wrapper for VML rectangle elements.
    - * This is an implementation of the goog.graphics.RectElement interface.
    - * You should not construct objects from this constructor. The graphics
    - * will return the object for you.
    - * @param {Element} element The DOM element to wrap.
    - * @param {goog.graphics.VmlGraphics} graphics The graphics creating
    - *     this element.
    - * @param {goog.graphics.Stroke?} stroke The stroke to use for this element.
    - * @param {goog.graphics.Fill?} fill The fill to use for this element.
    - * @constructor
    - * @extends {goog.graphics.RectElement}
    - * @deprecated goog.graphics is deprecated. It existed to abstract over browser
    - *     differences before the canvas tag was widely supported.  See
    - *     http://en.wikipedia.org/wiki/Canvas_element for details.
    - * @final
    - */
    -goog.graphics.VmlRectElement = function(element, graphics, stroke, fill) {
    -  this.id_ = element.id;
    -  goog.graphics.RectElement.call(this, element, graphics, stroke, fill);
    -};
    -goog.inherits(goog.graphics.VmlRectElement, goog.graphics.RectElement);
    -
    -
    -/** @override */
    -goog.graphics.VmlRectElement.prototype.getElement =
    -    goog.graphics.vmlGetElement_;
    -
    -
    -/**
    - * Update the position of the rectangle.
    - * @param {number} x X coordinate (left).
    - * @param {number} y Y coordinate (top).
    - * @override
    - */
    -goog.graphics.VmlRectElement.prototype.setPosition = function(x, y) {
    -  var style = this.getElement().style;
    -
    -  style.left = /** @suppress {missingRequire} */
    -      goog.graphics.VmlGraphics.toPosPx(x);
    -  style.top = /** @suppress {missingRequire} */
    -      goog.graphics.VmlGraphics.toPosPx(y);
    -};
    -
    -
    -/**
    - * Update the size of the rectangle.
    - * @param {number} width Width of rectangle.
    - * @param {number} height Height of rectangle.
    - * @override
    - */
    -goog.graphics.VmlRectElement.prototype.setSize = function(width, height) {
    -  var style = this.getElement().style;
    -  style.width = /** @suppress {missingRequire} */
    -      goog.graphics.VmlGraphics.toSizePx(width);
    -  style.height = /** @suppress {missingRequire} */
    -      goog.graphics.VmlGraphics.toSizePx(height);
    -};
    -
    -
    -
    -/**
    - * Thin wrapper for VML path elements.
    - * This is an implementation of the goog.graphics.PathElement interface.
    - * You should not construct objects from this constructor. The graphics
    - * will return the object for you.
    - * @param {Element} element The DOM element to wrap.
    - * @param {goog.graphics.VmlGraphics} graphics The graphics creating
    - *     this element.
    - * @param {goog.graphics.Stroke?} stroke The stroke to use for this element.
    - * @param {goog.graphics.Fill?} fill The fill to use for this element.
    - * @constructor
    - * @extends {goog.graphics.PathElement}
    - * @deprecated goog.graphics is deprecated. It existed to abstract over browser
    - *     differences before the canvas tag was widely supported.  See
    - *     http://en.wikipedia.org/wiki/Canvas_element for details.
    - * @final
    - */
    -goog.graphics.VmlPathElement = function(element, graphics, stroke, fill) {
    -  this.id_ = element.id;
    -  goog.graphics.PathElement.call(this, element, graphics, stroke, fill);
    -};
    -goog.inherits(goog.graphics.VmlPathElement, goog.graphics.PathElement);
    -
    -
    -/** @override */
    -goog.graphics.VmlPathElement.prototype.getElement =
    -    goog.graphics.vmlGetElement_;
    -
    -
    -/**
    - * Update the underlying path.
    - * @param {!goog.graphics.Path} path The path object to draw.
    - * @override
    - */
    -goog.graphics.VmlPathElement.prototype.setPath = function(path) {
    -  /** @suppress {missingRequire} */
    -  goog.graphics.VmlGraphics.setAttribute(
    -      this.getElement(), 'path',
    -      /** @suppress {missingRequire} */
    -      goog.graphics.VmlGraphics.getVmlPath(path));
    -};
    -
    -
    -
    -/**
    - * Thin wrapper for VML text elements.
    - * This is an implementation of the goog.graphics.TextElement interface.
    - * You should not construct objects from this constructor. The graphics
    - * will return the object for you.
    - * @param {Element} element The DOM element to wrap.
    - * @param {goog.graphics.VmlGraphics} graphics The graphics creating
    - *     this element.
    - * @param {goog.graphics.Stroke?} stroke The stroke to use for this element.
    - * @param {goog.graphics.Fill?} fill The fill to use for this element.
    - * @constructor
    - * @extends {goog.graphics.TextElement}
    - * @deprecated goog.graphics is deprecated. It existed to abstract over browser
    - *     differences before the canvas tag was widely supported.  See
    - *     http://en.wikipedia.org/wiki/Canvas_element for details.
    - * @final
    - */
    -goog.graphics.VmlTextElement = function(element, graphics, stroke, fill) {
    -  this.id_ = element.id;
    -  goog.graphics.TextElement.call(this, element, graphics, stroke, fill);
    -};
    -goog.inherits(goog.graphics.VmlTextElement, goog.graphics.TextElement);
    -
    -
    -/** @override */
    -goog.graphics.VmlTextElement.prototype.getElement =
    -    goog.graphics.vmlGetElement_;
    -
    -
    -/**
    - * Update the displayed text of the element.
    - * @param {string} text The text to draw.
    - * @override
    - */
    -goog.graphics.VmlTextElement.prototype.setText = function(text) {
    -  /** @suppress {missingRequire} */
    -  goog.graphics.VmlGraphics.setAttribute(this.getElement().childNodes[1],
    -      'string', text);
    -};
    -
    -
    -
    -/**
    - * Thin wrapper for VML image elements.
    - * This is an implementation of the goog.graphics.ImageElement interface.
    - * You should not construct objects from this constructor. The graphics
    - * will return the object for you.
    - * @param {Element} element The DOM element to wrap.
    - * @param {goog.graphics.VmlGraphics} graphics The graphics creating
    - *     this element.
    - * @constructor
    - * @extends {goog.graphics.ImageElement}
    - * @deprecated goog.graphics is deprecated. It existed to abstract over browser
    - *     differences before the canvas tag was widely supported.  See
    - *     http://en.wikipedia.org/wiki/Canvas_element for details.
    - * @final
    - */
    -goog.graphics.VmlImageElement = function(element, graphics) {
    -  this.id_ = element.id;
    -  goog.graphics.ImageElement.call(this, element, graphics);
    -};
    -goog.inherits(goog.graphics.VmlImageElement, goog.graphics.ImageElement);
    -
    -
    -/** @override */
    -goog.graphics.VmlImageElement.prototype.getElement =
    -    goog.graphics.vmlGetElement_;
    -
    -
    -/**
    - * Update the position of the image.
    - * @param {number} x X coordinate (left).
    - * @param {number} y Y coordinate (top).
    - * @override
    - */
    -goog.graphics.VmlImageElement.prototype.setPosition = function(x, y) {
    -  var style = this.getElement().style;
    -
    -  style.left = /** @suppress {missingRequire} */
    -      goog.graphics.VmlGraphics.toPosPx(x);
    -  style.top = /** @suppress {missingRequire} */
    -      goog.graphics.VmlGraphics.toPosPx(y);
    -};
    -
    -
    -/**
    - * Update the size of the image.
    - * @param {number} width Width of rectangle.
    - * @param {number} height Height of rectangle.
    - * @override
    - */
    -goog.graphics.VmlImageElement.prototype.setSize = function(width, height) {
    -  var style = this.getElement().style;
    -  style.width = /** @suppress {missingRequire} */
    -      goog.graphics.VmlGraphics.toPosPx(width);
    -  style.height = /** @suppress {missingRequire} */
    -      goog.graphics.VmlGraphics.toPosPx(height);
    -};
    -
    -
    -/**
    - * Update the source of the image.
    - * @param {string} src Source of the image.
    - * @override
    - */
    -goog.graphics.VmlImageElement.prototype.setSource = function(src) {
    -  /** @suppress {missingRequire} */
    -  goog.graphics.VmlGraphics.setAttribute(this.getElement(), 'src', src);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/graphics/vmlgraphics.js b/src/database/third_party/closure-library/closure/goog/graphics/vmlgraphics.js
    deleted file mode 100644
    index 09d6844d513..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/graphics/vmlgraphics.js
    +++ /dev/null
    @@ -1,946 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview VmlGraphics sub class that uses VML to draw the graphics.
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -
    -goog.provide('goog.graphics.VmlGraphics');
    -
    -
    -goog.require('goog.array');
    -goog.require('goog.dom.safe');
    -goog.require('goog.events');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventType');
    -goog.require('goog.graphics.AbstractGraphics');
    -goog.require('goog.graphics.LinearGradient');
    -goog.require('goog.graphics.Path');
    -goog.require('goog.graphics.SolidFill');
    -goog.require('goog.graphics.VmlEllipseElement');
    -goog.require('goog.graphics.VmlGroupElement');
    -goog.require('goog.graphics.VmlImageElement');
    -goog.require('goog.graphics.VmlPathElement');
    -goog.require('goog.graphics.VmlRectElement');
    -goog.require('goog.graphics.VmlTextElement');
    -goog.require('goog.html.uncheckedconversions');
    -goog.require('goog.math');
    -goog.require('goog.math.Size');
    -goog.require('goog.string');
    -goog.require('goog.string.Const');
    -goog.require('goog.style');
    -
    -
    -
    -/**
    - * A Graphics implementation for drawing using VML.
    - * @param {string|number} width The (non-zero) width in pixels.  Strings
    - *     expressing percentages of parent with (e.g. '80%') are also accepted.
    - * @param {string|number} height The (non-zero) height in pixels.  Strings
    - *     expressing percentages of parent with (e.g. '80%') are also accepted.
    - * @param {?number=} opt_coordWidth The coordinate width - if
    - *     omitted or null, defaults to same as width.
    - * @param {?number=} opt_coordHeight The coordinate height - if
    - *     omitted or null, defaults to same as height.
    - * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper object for the
    - *     document we want to render in.
    - * @constructor
    - * @extends {goog.graphics.AbstractGraphics}
    - * @deprecated goog.graphics is deprecated. It existed to abstract over browser
    - *     differences before the canvas tag was widely supported.  See
    - *     http://en.wikipedia.org/wiki/Canvas_element for details.
    - * @final
    - */
    -goog.graphics.VmlGraphics = function(width, height,
    -                                     opt_coordWidth, opt_coordHeight,
    -                                     opt_domHelper) {
    -  goog.graphics.AbstractGraphics.call(this, width, height,
    -                                      opt_coordWidth, opt_coordHeight,
    -                                      opt_domHelper);
    -  this.handler_ = new goog.events.EventHandler(this);
    -  this.registerDisposable(this.handler_);
    -};
    -goog.inherits(goog.graphics.VmlGraphics, goog.graphics.AbstractGraphics);
    -
    -
    -/**
    - * The prefix to use for VML elements
    - * @private
    - * @type {string}
    - */
    -goog.graphics.VmlGraphics.VML_PREFIX_ = 'g_vml_';
    -
    -
    -/**
    - * The VML namespace URN
    - * @private
    - * @type {string}
    - */
    -goog.graphics.VmlGraphics.VML_NS_ = 'urn:schemas-microsoft-com:vml';
    -
    -
    -/**
    - * The VML behavior URL.
    - * @private
    - * @type {string}
    - */
    -goog.graphics.VmlGraphics.VML_IMPORT_ = '#default#VML';
    -
    -
    -/**
    - * Whether the document is using IE8 standards mode, and therefore needs hacks.
    - * @private
    - * @type {boolean}
    - */
    -goog.graphics.VmlGraphics.IE8_MODE_ = document.documentMode &&
    -    document.documentMode >= 8;
    -
    -
    -/**
    - * The coordinate multiplier to allow sub-pixel rendering
    - * @type {number}
    - */
    -goog.graphics.VmlGraphics.COORD_MULTIPLIER = 100;
    -
    -
    -/**
    - * Converts the given size to a css size.  If it is a percentage, leaves it
    - * alone.  Otherwise assumes px.
    - *
    - * @param {number|string} size The size to use.
    - * @return {string} The position adjusted for COORD_MULTIPLIER.
    - */
    -goog.graphics.VmlGraphics.toCssSize = function(size) {
    -  return goog.isString(size) && goog.string.endsWith(size, '%') ?
    -         size : parseFloat(size.toString()) + 'px';
    -};
    -
    -
    -/**
    - * Multiplies positioning coordinates by COORD_MULTIPLIER to allow sub-pixel
    - * coordinates.  Also adds a half pixel offset to match SVG.
    - *
    - * This function is internal for the VML supporting classes, and
    - * should not be used externally.
    - *
    - * @param {number|string} number A position in pixels.
    - * @return {number} The position adjusted for COORD_MULTIPLIER.
    - */
    -goog.graphics.VmlGraphics.toPosCoord = function(number) {
    -  return Math.round((parseFloat(number.toString()) - 0.5) *
    -      goog.graphics.VmlGraphics.COORD_MULTIPLIER);
    -};
    -
    -
    -/**
    - * Add a "px" suffix to a number of pixels, and multiplies all coordinates by
    - * COORD_MULTIPLIER to allow sub-pixel coordinates.
    - *
    - * This function is internal for the VML supporting classes, and
    - * should not be used externally.
    - *
    - * @param {number|string} number A position in pixels.
    - * @return {string} The position with suffix 'px'.
    - */
    -goog.graphics.VmlGraphics.toPosPx = function(number) {
    -  return goog.graphics.VmlGraphics.toPosCoord(number) + 'px';
    -};
    -
    -
    -/**
    - * Multiplies the width or height coordinate by COORD_MULTIPLIER to allow
    - * sub-pixel coordinates.
    - *
    - * This function is internal for the VML supporting classes, and
    - * should not be used externally.
    - *
    - * @param {string|number} number A size in units.
    - * @return {number} The size multiplied by the correct factor.
    - */
    -goog.graphics.VmlGraphics.toSizeCoord = function(number) {
    -  return Math.round(parseFloat(number.toString()) *
    -      goog.graphics.VmlGraphics.COORD_MULTIPLIER);
    -};
    -
    -
    -/**
    - * Add a "px" suffix to a number of pixels, and multiplies all coordinates by
    - * COORD_MULTIPLIER to allow sub-pixel coordinates.
    - *
    - * This function is internal for the VML supporting classes, and
    - * should not be used externally.
    - *
    - * @param {number|string} number A size in pixels.
    - * @return {string} The size with suffix 'px'.
    - */
    -goog.graphics.VmlGraphics.toSizePx = function(number) {
    -  return goog.graphics.VmlGraphics.toSizeCoord(number) + 'px';
    -};
    -
    -
    -/**
    - * Sets an attribute on the given VML element, in the way best suited to the
    - * current version of IE.  Should only be used in the goog.graphics package.
    - * @param {Element} element The element to set an attribute
    - *     on.
    - * @param {string} name The name of the attribute to set.
    - * @param {string} value The value to set it to.
    - */
    -goog.graphics.VmlGraphics.setAttribute = function(element, name, value) {
    -  if (goog.graphics.VmlGraphics.IE8_MODE_) {
    -    element[name] = value;
    -  } else {
    -    element.setAttribute(name, value);
    -  }
    -};
    -
    -
    -/**
    - * Event handler.
    - * @type {goog.events.EventHandler}
    - * @private
    - */
    -goog.graphics.VmlGraphics.prototype.handler_;
    -
    -
    -/**
    - * Creates a VML element. Used internally and by different VML classes.
    - * @param {string} tagName The type of element to create.
    - * @return {!Element} The created element.
    - */
    -goog.graphics.VmlGraphics.prototype.createVmlElement = function(tagName) {
    -  var element =
    -      this.dom_.createElement(goog.graphics.VmlGraphics.VML_PREFIX_ + ':' +
    -                              tagName);
    -  element.id = goog.string.createUniqueString();
    -  return element;
    -};
    -
    -
    -/**
    - * Returns the VML element with the given id that is a child of this graphics
    - * object.
    - * Should be considered package private, and not used externally.
    - * @param {string} id The element id to find.
    - * @return {Element} The element with the given id, or null if none is found.
    - */
    -goog.graphics.VmlGraphics.prototype.getVmlElement = function(id) {
    -  return this.dom_.getElement(id);
    -};
    -
    -
    -/**
    - * Resets the graphics so they will display properly on IE8.  Noop in older
    - * versions.
    - * @private
    - */
    -goog.graphics.VmlGraphics.prototype.updateGraphics_ = function() {
    -  if (goog.graphics.VmlGraphics.IE8_MODE_ && this.isInDocument()) {
    -    // There's a risk of mXSS here, as the browser is not guaranteed to
    -    // return the HTML that was originally written, when innerHTML is read.
    -    // However, given that this a deprecated API and affects only IE, it seems
    -    // an acceptable risk.
    -    var html = goog.html.uncheckedconversions
    -        .safeHtmlFromStringKnownToSatisfyTypeContract(
    -            goog.string.Const.from('Assign innerHTML to itself'),
    -            this.getElement().innerHTML);
    -    goog.dom.safe.setInnerHtml(
    -        /** @type {!Element} */ (this.getElement()), html);
    -  }
    -};
    -
    -
    -/**
    - * Appends an element.
    - *
    - * @param {goog.graphics.Element} element The element wrapper.
    - * @param {goog.graphics.GroupElement=} opt_group The group wrapper element
    - *     to append to. If not specified, appends to the main canvas.
    - * @private
    - */
    -goog.graphics.VmlGraphics.prototype.append_ = function(element, opt_group) {
    -  var parent = opt_group || this.canvasElement;
    -  parent.getElement().appendChild(element.getElement());
    -  this.updateGraphics_();
    -};
    -
    -
    -/**
    - * Sets the fill for the given element.
    - * @param {goog.graphics.StrokeAndFillElement} element The element wrapper.
    - * @param {goog.graphics.Fill?} fill The fill object.
    - * @override
    - */
    -goog.graphics.VmlGraphics.prototype.setElementFill = function(element, fill) {
    -  var vmlElement = element.getElement();
    -  goog.graphics.VmlGraphics.removeFill_(vmlElement);
    -  if (fill instanceof goog.graphics.SolidFill) {
    -    // NOTE(arv): VML does not understand 'transparent' so hard code support
    -    // for it.
    -    if (fill.getColor() == 'transparent') {
    -      vmlElement.filled = false;
    -    } else if (fill.getOpacity() != 1) {
    -      vmlElement.filled = true;
    -      // Set opacity (number 0-1 is translated to percent)
    -      var fillNode = this.createVmlElement('fill');
    -      fillNode.opacity = Math.round(fill.getOpacity() * 100) + '%';
    -      fillNode.color = fill.getColor();
    -      vmlElement.appendChild(fillNode);
    -    } else {
    -      vmlElement.filled = true;
    -      vmlElement.fillcolor = fill.getColor();
    -    }
    -  } else if (fill instanceof goog.graphics.LinearGradient) {
    -    vmlElement.filled = true;
    -    // Add a 'fill' element
    -    var gradient = this.createVmlElement('fill');
    -    gradient.color = fill.getColor1();
    -    gradient.color2 = fill.getColor2();
    -    if (goog.isNumber(fill.getOpacity1())) {
    -      gradient.opacity = fill.getOpacity1();
    -    }
    -    if (goog.isNumber(fill.getOpacity2())) {
    -      gradient.opacity2 = fill.getOpacity2();
    -    }
    -    var angle = goog.math.angle(fill.getX1(), fill.getY1(),
    -        fill.getX2(), fill.getY2());
    -    // Our angles start from 0 to the right, and grow clockwise.
    -    // MSIE starts from 0 to top, and grows anti-clockwise.
    -    angle = Math.round(goog.math.standardAngle(270 - angle));
    -    gradient.angle = angle;
    -    gradient.type = 'gradient';
    -    vmlElement.appendChild(gradient);
    -  } else {
    -    vmlElement.filled = false;
    -  }
    -  this.updateGraphics_();
    -};
    -
    -
    -/**
    - * Sets the stroke for the given element.
    - * @param {goog.graphics.StrokeAndFillElement} element The element wrapper.
    - * @param {goog.graphics.Stroke?} stroke The stroke object.
    - * @override
    - */
    -goog.graphics.VmlGraphics.prototype.setElementStroke = function(element,
    -    stroke) {
    -  var vmlElement = element.getElement();
    -  if (stroke) {
    -    vmlElement.stroked = true;
    -
    -    var width = stroke.getWidth();
    -    if (goog.isString(width) && width.indexOf('px') == -1) {
    -      width = parseFloat(width);
    -    } else {
    -      width = width * this.getPixelScaleX();
    -    }
    -
    -    var strokeElement = vmlElement.getElementsByTagName('stroke')[0];
    -    if (!strokeElement) {
    -      strokeElement = strokeElement || this.createVmlElement('stroke');
    -      vmlElement.appendChild(strokeElement);
    -    }
    -    strokeElement.opacity = stroke.getOpacity();
    -    strokeElement.weight = width + 'px';
    -    strokeElement.color = stroke.getColor();
    -  } else {
    -    vmlElement.stroked = false;
    -  }
    -  this.updateGraphics_();
    -};
    -
    -
    -/**
    - * Set the translation and rotation of an element.
    - *
    - * If a more general affine transform is needed than this provides
    - * (e.g. skew and scale) then use setElementAffineTransform.
    - * @param {number} x The x coordinate of the translation transform.
    - * @param {number} y The y coordinate of the translation transform.
    - * @param {number} angle The angle of the rotation transform.
    - * @param {number} centerX The horizontal center of the rotation transform.
    - * @param {number} centerY The vertical center of the rotation transform.
    - * @override
    - */
    -goog.graphics.VmlGraphics.prototype.setElementTransform = function(element, x,
    -    y, angle, centerX, centerY) {
    -  var el = element.getElement();
    -
    -  el.style.left = goog.graphics.VmlGraphics.toPosPx(x);
    -  el.style.top = goog.graphics.VmlGraphics.toPosPx(y);
    -  if (angle || el.rotation) {
    -    el.rotation = angle;
    -    el.coordsize = goog.graphics.VmlGraphics.toSizeCoord(centerX * 2) + ' ' +
    -        goog.graphics.VmlGraphics.toSizeCoord(centerY * 2);
    -  }
    -};
    -
    -
    -/**
    - * Set the transformation of an element.
    - * @param {!goog.graphics.Element} element The element wrapper.
    - * @param {!goog.graphics.AffineTransform} affineTransform The
    - *     transformation applied to this element.
    - * @override
    - */
    -goog.graphics.VmlGraphics.prototype.setElementAffineTransform = function(
    -    element, affineTransform) {
    -  var t = affineTransform;
    -  var vmlElement = element.getElement();
    -  goog.graphics.VmlGraphics.removeSkew_(vmlElement);
    -  var skewNode = this.createVmlElement('skew');
    -  skewNode.on = 'true';
    -  // Move the transform origin to 0px,0px of the graphics.
    -  // In VML, 0,0 means the center of the element, -0.5,-0.5 left top conner of
    -  // it.
    -  skewNode.origin =
    -      (-vmlElement.style.pixelLeft / vmlElement.style.pixelWidth - 0.5) + ',' +
    -      (-vmlElement.style.pixelTop / vmlElement.style.pixelHeight - 0.5);
    -  skewNode.offset = t.getTranslateX().toFixed(1) + 'px,' +
    -                    t.getTranslateY().toFixed(1) + 'px';
    -  skewNode.matrix = [t.getScaleX().toFixed(6), t.getShearX().toFixed(6),
    -                     t.getShearY().toFixed(6), t.getScaleY().toFixed(6),
    -                     0, 0].join(',');
    -  vmlElement.appendChild(skewNode);
    -  this.updateGraphics_();
    -};
    -
    -
    -/**
    - * Removes the skew information from a dom element.
    - * @param {Element} element DOM element.
    - * @private
    - */
    -goog.graphics.VmlGraphics.removeSkew_ = function(element) {
    -  goog.array.forEach(element.childNodes, function(child) {
    -    if (child.tagName == 'skew') {
    -      element.removeChild(child);
    -    }
    -  });
    -};
    -
    -
    -/**
    - * Removes the fill information from a dom element.
    - * @param {Element} element DOM element.
    - * @private
    - */
    -goog.graphics.VmlGraphics.removeFill_ = function(element) {
    -  element.fillcolor = '';
    -  goog.array.forEach(element.childNodes, function(child) {
    -    if (child.tagName == 'fill') {
    -      element.removeChild(child);
    -    }
    -  });
    -};
    -
    -
    -/**
    - * Set top, left, width and height for an element.
    - * This function is internal for the VML supporting classes, and
    - * should not be used externally.
    - *
    - * @param {Element} element DOM element.
    - * @param {number} left Left ccordinate in pixels.
    - * @param {number} top Top ccordinate in pixels.
    - * @param {number} width Width in pixels.
    - * @param {number} height Height in pixels.
    - */
    -goog.graphics.VmlGraphics.setPositionAndSize = function(
    -    element, left, top, width, height) {
    -  var style = element.style;
    -  style.position = 'absolute';
    -  style.left = goog.graphics.VmlGraphics.toPosPx(left);
    -  style.top = goog.graphics.VmlGraphics.toPosPx(top);
    -  style.width = goog.graphics.VmlGraphics.toSizePx(width);
    -  style.height = goog.graphics.VmlGraphics.toSizePx(height);
    -
    -  if (element.tagName == 'shape') {
    -    element.coordsize = goog.graphics.VmlGraphics.toSizeCoord(width) + ' ' +
    -                        goog.graphics.VmlGraphics.toSizeCoord(height);
    -  }
    -};
    -
    -
    -/**
    - * Creates an element spanning the surface.
    - *
    - * @param {string} type The type of element to create.
    - * @return {!Element} The created, positioned, and sized element.
    - * @private
    - */
    -goog.graphics.VmlGraphics.prototype.createFullSizeElement_ = function(type) {
    -  var element = this.createVmlElement(type);
    -  var size = this.getCoordSize();
    -  goog.graphics.VmlGraphics.setPositionAndSize(element, 0, 0, size.width,
    -      size.height);
    -  return element;
    -};
    -
    -
    -/**
    - * IE magic - if this "no-op" line is not here, the if statement below will
    - * fail intermittently.  The eval is used to prevent the JsCompiler from
    - * stripping this piece of code, which it quite reasonably thinks is doing
    - * nothing. Put it in try-catch block to prevent "Unspecified Error" when
    - * this statement is executed in a defer JS in IE.
    - * More info here:
    - * http://www.mail-archive.com/users@openlayers.org/msg01838.html
    - */
    -try {
    -  eval('document.namespaces');
    -} catch (ex) {}
    -
    -
    -/**
    - * Creates the DOM representation of the graphics area.
    - * @override
    - */
    -goog.graphics.VmlGraphics.prototype.createDom = function() {
    -  var doc = this.dom_.getDocument();
    -
    -  // Add the namespace.
    -  if (!doc.namespaces[goog.graphics.VmlGraphics.VML_PREFIX_]) {
    -    if (goog.graphics.VmlGraphics.IE8_MODE_) {
    -      doc.namespaces.add(goog.graphics.VmlGraphics.VML_PREFIX_,
    -                         goog.graphics.VmlGraphics.VML_NS_,
    -                         goog.graphics.VmlGraphics.VML_IMPORT_);
    -    } else {
    -      doc.namespaces.add(goog.graphics.VmlGraphics.VML_PREFIX_,
    -                         goog.graphics.VmlGraphics.VML_NS_);
    -    }
    -
    -    // We assume that we only need to add the CSS if the namespace was not
    -    // present
    -    var ss = doc.createStyleSheet();
    -    ss.cssText = goog.graphics.VmlGraphics.VML_PREFIX_ + '\\:*' +
    -                 '{behavior:url(#default#VML)}';
    -  }
    -
    -  // Outer a DIV with overflow hidden for clipping.
    -  // All inner elements are absolutly positioned on-top of this div.
    -  var pixelWidth = this.width;
    -  var pixelHeight = this.height;
    -  var divElement = this.dom_.createDom('div', {
    -    'style': 'overflow:hidden;position:relative;width:' +
    -        goog.graphics.VmlGraphics.toCssSize(pixelWidth) + ';height:' +
    -        goog.graphics.VmlGraphics.toCssSize(pixelHeight)
    -  });
    -
    -  this.setElementInternal(divElement);
    -
    -  var group = this.createVmlElement('group');
    -  var style = group.style;
    -
    -  style.position = 'absolute';
    -  style.left = style.top = 0;
    -  style.width = this.width;
    -  style.height = this.height;
    -  if (this.coordWidth) {
    -    group.coordsize =
    -        goog.graphics.VmlGraphics.toSizeCoord(this.coordWidth) + ' ' +
    -        goog.graphics.VmlGraphics.toSizeCoord(
    -            /** @type {number} */ (this.coordHeight));
    -  } else {
    -    group.coordsize = goog.graphics.VmlGraphics.toSizeCoord(pixelWidth) + ' ' +
    -        goog.graphics.VmlGraphics.toSizeCoord(pixelHeight);
    -  }
    -
    -  if (goog.isDef(this.coordLeft)) {
    -    group.coordorigin = goog.graphics.VmlGraphics.toSizeCoord(this.coordLeft) +
    -        ' ' + goog.graphics.VmlGraphics.toSizeCoord(this.coordTop);
    -  } else {
    -    group.coordorigin = '0 0';
    -  }
    -  divElement.appendChild(group);
    -
    -  this.canvasElement = new goog.graphics.VmlGroupElement(group, this);
    -
    -  goog.events.listen(divElement, goog.events.EventType.RESIZE, goog.bind(
    -      this.handleContainerResize_, this));
    -};
    -
    -
    -/**
    - * Changes the canvas element size to match the container element size.
    - * @private
    - */
    -goog.graphics.VmlGraphics.prototype.handleContainerResize_ = function() {
    -  var size = goog.style.getSize(this.getElement());
    -  var style = this.canvasElement.getElement().style;
    -
    -  if (size.width) {
    -    style.width = size.width + 'px';
    -    style.height = size.height + 'px';
    -  } else {
    -    var current = this.getElement();
    -    while (current && current.currentStyle &&
    -        current.currentStyle.display != 'none') {
    -      current = current.parentNode;
    -    }
    -    if (current && current.currentStyle) {
    -      this.handler_.listen(current, 'propertychange',
    -          this.handleContainerResize_);
    -    }
    -  }
    -
    -  this.dispatchEvent(goog.events.EventType.RESIZE);
    -};
    -
    -
    -/**
    - * Handle property changes on hidden ancestors.
    - * @param {goog.events.BrowserEvent} e The browser event.
    - * @private
    - */
    -goog.graphics.VmlGraphics.prototype.handlePropertyChange_ = function(e) {
    -  var prop = e.getBrowserEvent().propertyName;
    -  if (prop == 'display' || prop == 'className') {
    -    this.handler_.unlisten(/** @type {Element} */(e.target),
    -        'propertychange', this.handlePropertyChange_);
    -    this.handleContainerResize_();
    -  }
    -};
    -
    -
    -/**
    - * Changes the coordinate system position.
    - * @param {number} left The coordinate system left bound.
    - * @param {number} top The coordinate system top bound.
    - * @override
    - */
    -goog.graphics.VmlGraphics.prototype.setCoordOrigin = function(left, top) {
    -  this.coordLeft = left;
    -  this.coordTop = top;
    -
    -  this.canvasElement.getElement().coordorigin =
    -      goog.graphics.VmlGraphics.toSizeCoord(this.coordLeft) + ' ' +
    -      goog.graphics.VmlGraphics.toSizeCoord(this.coordTop);
    -};
    -
    -
    -/**
    - * Changes the coordinate size.
    - * @param {number} coordWidth The coordinate width.
    - * @param {number} coordHeight The coordinate height.
    - * @override
    - */
    -goog.graphics.VmlGraphics.prototype.setCoordSize = function(coordWidth,
    -                                                            coordHeight) {
    -  goog.graphics.VmlGraphics.superClass_.setCoordSize.apply(this, arguments);
    -
    -  this.canvasElement.getElement().coordsize =
    -      goog.graphics.VmlGraphics.toSizeCoord(coordWidth) + ' ' +
    -      goog.graphics.VmlGraphics.toSizeCoord(coordHeight);
    -};
    -
    -
    -/**
    - * Change the size of the canvas.
    - * @param {number} pixelWidth The width in pixels.
    - * @param {number} pixelHeight The height in pixels.
    - * @override
    - */
    -goog.graphics.VmlGraphics.prototype.setSize = function(pixelWidth,
    -    pixelHeight) {
    -  goog.style.setSize(this.getElement(), pixelWidth, pixelHeight);
    -};
    -
    -
    -/**
    - * @return {!goog.math.Size} Returns the number of pixels spanned by the
    - *     surface.
    - * @override
    - */
    -goog.graphics.VmlGraphics.prototype.getPixelSize = function() {
    -  var el = this.getElement();
    -  // The following relies on the fact that the size can never be 0.
    -  return new goog.math.Size(el.style.pixelWidth || el.offsetWidth || 1,
    -      el.style.pixelHeight || el.offsetHeight || 1);
    -};
    -
    -
    -/**
    - * Remove all drawing elements from the graphics.
    - * @override
    - */
    -goog.graphics.VmlGraphics.prototype.clear = function() {
    -  this.canvasElement.clear();
    -};
    -
    -
    -/**
    - * Draw an ellipse.
    - *
    - * @param {number} cx Center X coordinate.
    - * @param {number} cy Center Y coordinate.
    - * @param {number} rx Radius length for the x-axis.
    - * @param {number} ry Radius length for the y-axis.
    - * @param {goog.graphics.Stroke?} stroke Stroke object describing the
    - *    stroke.
    - * @param {goog.graphics.Fill?} fill Fill object describing the fill.
    - * @param {goog.graphics.GroupElement=} opt_group The group wrapper element
    - *     to append to. If not specified, appends to the main canvas.
    - *
    - * @return {!goog.graphics.EllipseElement} The newly created element.
    - * @override
    - */
    -goog.graphics.VmlGraphics.prototype.drawEllipse = function(cx, cy, rx, ry,
    -    stroke, fill, opt_group) {
    -  var element = this.createVmlElement('oval');
    -  goog.graphics.VmlGraphics.setPositionAndSize(element, cx - rx, cy - ry,
    -      rx * 2, ry * 2);
    -  var wrapper = new goog.graphics.VmlEllipseElement(element, this,
    -      cx, cy, rx, ry, stroke, fill);
    -  this.append_(wrapper, opt_group);
    -  return wrapper;
    -};
    -
    -
    -/**
    - * Draw a rectangle.
    - *
    - * @param {number} x X coordinate (left).
    - * @param {number} y Y coordinate (top).
    - * @param {number} width Width of rectangle.
    - * @param {number} height Height of rectangle.
    - * @param {goog.graphics.Stroke?} stroke Stroke object describing the
    - *    stroke.
    - * @param {goog.graphics.Fill?} fill Fill object describing the fill.
    - * @param {goog.graphics.GroupElement=} opt_group The group wrapper element
    - *     to append to. If not specified, appends to the main canvas.
    - *
    - * @return {!goog.graphics.RectElement} The newly created element.
    - * @override
    - */
    -goog.graphics.VmlGraphics.prototype.drawRect = function(x, y, width, height,
    -    stroke, fill, opt_group) {
    -  var element = this.createVmlElement('rect');
    -  goog.graphics.VmlGraphics.setPositionAndSize(element, x, y, width, height);
    -  var wrapper = new goog.graphics.VmlRectElement(element, this, stroke, fill);
    -  this.append_(wrapper, opt_group);
    -  return wrapper;
    -};
    -
    -
    -/**
    - * Draw an image.
    - *
    - * @param {number} x X coordinate (left).
    - * @param {number} y Y coordinate (top).
    - * @param {number} width Width of image.
    - * @param {number} height Height of image.
    - * @param {string} src Source of the image.
    - * @param {goog.graphics.GroupElement=} opt_group The group wrapper element
    - *     to append to. If not specified, appends to the main canvas.
    - *
    - * @return {!goog.graphics.ImageElement} The newly created element.
    - */
    -goog.graphics.VmlGraphics.prototype.drawImage = function(x, y, width, height,
    -    src, opt_group) {
    -  var element = this.createVmlElement('image');
    -  goog.graphics.VmlGraphics.setPositionAndSize(element, x, y, width, height);
    -  goog.graphics.VmlGraphics.setAttribute(element, 'src', src);
    -  var wrapper = new goog.graphics.VmlImageElement(element, this);
    -  this.append_(wrapper, opt_group);
    -  return wrapper;
    -};
    -
    -
    -/**
    - * Draw a text string vertically centered on a given line.
    - *
    - * @param {string} text The text to draw.
    - * @param {number} x1 X coordinate of start of line.
    - * @param {number} y1 Y coordinate of start of line.
    - * @param {number} x2 X coordinate of end of line.
    - * @param {number} y2 Y coordinate of end of line.
    - * @param {?string} align Horizontal alignment: left (default), center, right.
    - * @param {goog.graphics.Font} font Font describing the font properties.
    - * @param {goog.graphics.Stroke?} stroke Stroke object describing the stroke.
    - * @param {goog.graphics.Fill?} fill Fill object describing the fill.
    - * @param {goog.graphics.GroupElement=} opt_group The group wrapper element
    - *     to append to. If not specified, appends to the main canvas.
    - *
    - * @return {!goog.graphics.TextElement} The newly created element.
    - * @override
    - */
    -goog.graphics.VmlGraphics.prototype.drawTextOnLine = function(
    -    text, x1, y1, x2, y2, align, font, stroke, fill, opt_group) {
    -  var shape = this.createFullSizeElement_('shape');
    -
    -  var pathElement = this.createVmlElement('path');
    -  var path = 'M' + goog.graphics.VmlGraphics.toPosCoord(x1) + ',' +
    -             goog.graphics.VmlGraphics.toPosCoord(y1) + 'L' +
    -             goog.graphics.VmlGraphics.toPosCoord(x2) + ',' +
    -             goog.graphics.VmlGraphics.toPosCoord(y2) + 'E';
    -  goog.graphics.VmlGraphics.setAttribute(pathElement, 'v', path);
    -  goog.graphics.VmlGraphics.setAttribute(pathElement, 'textpathok', 'true');
    -
    -  var textPathElement = this.createVmlElement('textpath');
    -  textPathElement.setAttribute('on', 'true');
    -  var style = textPathElement.style;
    -  style.fontSize = font.size * this.getPixelScaleX();
    -  style.fontFamily = font.family;
    -  if (align != null) {
    -    style['v-text-align'] = align;
    -  }
    -  if (font.bold) {
    -    style.fontWeight = 'bold';
    -  }
    -  if (font.italic) {
    -    style.fontStyle = 'italic';
    -  }
    -  goog.graphics.VmlGraphics.setAttribute(textPathElement, 'string', text);
    -
    -  shape.appendChild(pathElement);
    -  shape.appendChild(textPathElement);
    -  var wrapper = new goog.graphics.VmlTextElement(shape, this, stroke, fill);
    -  this.append_(wrapper, opt_group);
    -  return wrapper;
    -};
    -
    -
    -/**
    - * Draw a path.
    - *
    - * @param {!goog.graphics.Path} path The path object to draw.
    - * @param {goog.graphics.Stroke?} stroke Stroke object describing the stroke.
    - * @param {goog.graphics.Fill?} fill Fill object describing the fill.
    - * @param {goog.graphics.GroupElement=} opt_group The group wrapper element
    - *     to append to. If not specified, appends to the main canvas.
    - *
    - * @return {!goog.graphics.PathElement} The newly created element.
    - * @override
    - */
    -goog.graphics.VmlGraphics.prototype.drawPath = function(path, stroke, fill,
    -    opt_group) {
    -  var element = this.createFullSizeElement_('shape');
    -  goog.graphics.VmlGraphics.setAttribute(element, 'path',
    -      goog.graphics.VmlGraphics.getVmlPath(path));
    -
    -  var wrapper = new goog.graphics.VmlPathElement(element, this, stroke, fill);
    -  this.append_(wrapper, opt_group);
    -  return wrapper;
    -};
    -
    -
    -/**
    - * Returns a string representation of a logical path suitable for use in
    - * a VML element.
    - *
    - * @param {goog.graphics.Path} path The logical path.
    - * @return {string} The VML path representation.
    - * @suppress {deprecated} goog.graphics is deprecated.
    - */
    -goog.graphics.VmlGraphics.getVmlPath = function(path) {
    -  var list = [];
    -  path.forEachSegment(function(segment, args) {
    -    switch (segment) {
    -      case goog.graphics.Path.Segment.MOVETO:
    -        list.push('m');
    -        Array.prototype.push.apply(list, goog.array.map(args,
    -            goog.graphics.VmlGraphics.toSizeCoord));
    -        break;
    -      case goog.graphics.Path.Segment.LINETO:
    -        list.push('l');
    -        Array.prototype.push.apply(list, goog.array.map(args,
    -            goog.graphics.VmlGraphics.toSizeCoord));
    -        break;
    -      case goog.graphics.Path.Segment.CURVETO:
    -        list.push('c');
    -        Array.prototype.push.apply(list, goog.array.map(args,
    -            goog.graphics.VmlGraphics.toSizeCoord));
    -        break;
    -      case goog.graphics.Path.Segment.CLOSE:
    -        list.push('x');
    -        break;
    -      case goog.graphics.Path.Segment.ARCTO:
    -        var toAngle = args[2] + args[3];
    -        var cx = goog.graphics.VmlGraphics.toSizeCoord(
    -            args[4] - goog.math.angleDx(toAngle, args[0]));
    -        var cy = goog.graphics.VmlGraphics.toSizeCoord(
    -            args[5] - goog.math.angleDy(toAngle, args[1]));
    -        var rx = goog.graphics.VmlGraphics.toSizeCoord(args[0]);
    -        var ry = goog.graphics.VmlGraphics.toSizeCoord(args[1]);
    -        // VML angles are in fd units (see http://www.w3.org/TR/NOTE-VML) and
    -        // are positive counter-clockwise.
    -        var fromAngle = Math.round(args[2] * -65536);
    -        var extent = Math.round(args[3] * -65536);
    -        list.push('ae', cx, cy, rx, ry, fromAngle, extent);
    -        break;
    -    }
    -  });
    -  return list.join(' ');
    -};
    -
    -
    -/**
    - * Create an empty group of drawing elements.
    - *
    - * @param {goog.graphics.GroupElement=} opt_group The group wrapper element
    - *     to append to. If not specified, appends to the main canvas.
    - *
    - * @return {!goog.graphics.GroupElement} The newly created group.
    - * @override
    - */
    -goog.graphics.VmlGraphics.prototype.createGroup = function(opt_group) {
    -  var element = this.createFullSizeElement_('group');
    -  var parent = opt_group || this.canvasElement;
    -  parent.getElement().appendChild(element);
    -  return new goog.graphics.VmlGroupElement(element, this);
    -};
    -
    -
    -/**
    - * Measure and return the width (in pixels) of a given text string.
    - * Text measurement is needed to make sure a text can fit in the allocated
    - * area. The way text length is measured is by writing it into a div that is
    - * after the visible area, measure the div width, and immediatly erase the
    - * written value.
    - *
    - * @param {string} text The text string to measure.
    - * @param {goog.graphics.Font} font The font object describing the font style.
    - *
    - * @return {number} The width in pixels of the text strings.
    - * @override
    - */
    -goog.graphics.VmlGraphics.prototype.getTextWidth = function(text, font) {
    -  // TODO(arv): Implement
    -  return 0;
    -};
    -
    -
    -/** @override */
    -goog.graphics.VmlGraphics.prototype.enterDocument = function() {
    -  goog.graphics.VmlGraphics.superClass_.enterDocument.call(this);
    -  this.handleContainerResize_();
    -  this.updateGraphics_();
    -};
    -
    -
    -/**
    - * Disposes of the component by removing event handlers, detacing DOM nodes from
    - * the document body, and removing references to them.
    - * @override
    - * @protected
    - */
    -goog.graphics.VmlGraphics.prototype.disposeInternal = function() {
    -  this.canvasElement = null;
    -  goog.graphics.VmlGraphics.superClass_.disposeInternal.call(this);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/history/event.js b/src/database/third_party/closure-library/closure/goog/history/event.js
    deleted file mode 100644
    index 19250df4c3f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/history/event.js
    +++ /dev/null
    @@ -1,55 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview The event object dispatched when the history changes.
    - *
    - */
    -
    -
    -goog.provide('goog.history.Event');
    -
    -goog.require('goog.events.Event');
    -goog.require('goog.history.EventType');
    -
    -
    -
    -/**
    - * Event object dispatched after the history state has changed.
    - * @param {string} token The string identifying the new history state.
    - * @param {boolean} isNavigation True if the event was triggered by a browser
    - *     action, such as forward or back, clicking on a link, editing the URL, or
    - *     calling {@code window.history.(go|back|forward)}.
    - *     False if the token has been changed by a {@code setToken} or
    - *     {@code replaceToken} call.
    - * @constructor
    - * @extends {goog.events.Event}
    - * @final
    - */
    -goog.history.Event = function(token, isNavigation) {
    -  goog.events.Event.call(this, goog.history.EventType.NAVIGATE);
    -
    -  /**
    -   * The current history state.
    -   * @type {string}
    -   */
    -  this.token = token;
    -
    -  /**
    -   * Whether the event was triggered by browser navigation.
    -   * @type {boolean}
    -   */
    -  this.isNavigation = isNavigation;
    -};
    -goog.inherits(goog.history.Event, goog.events.Event);
    diff --git a/src/database/third_party/closure-library/closure/goog/history/eventtype.js b/src/database/third_party/closure-library/closure/goog/history/eventtype.js
    deleted file mode 100644
    index 4268df38cad..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/history/eventtype.js
    +++ /dev/null
    @@ -1,30 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Event types for goog.history.
    - *
    - */
    -
    -
    -goog.provide('goog.history.EventType');
    -
    -
    -/**
    - * Event types for goog.history.
    - * @enum {string}
    - */
    -goog.history.EventType = {
    -  NAVIGATE: 'navigate'
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/history/history.js b/src/database/third_party/closure-library/closure/goog/history/history.js
    deleted file mode 100644
    index 6704529e444..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/history/history.js
    +++ /dev/null
    @@ -1,1001 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Browser history stack management class.
    - *
    - * The goog.History object allows a page to create history state without leaving
    - * the current document. This allows users to, for example, hit the browser's
    - * back button without leaving the current page.
    - *
    - * The history object can be instantiated in one of two modes. In user visible
    - * mode, the current history state is shown in the browser address bar as a
    - * document location fragment (the portion of the URL after the '#'). These
    - * addresses can be bookmarked, copied and pasted into another browser, and
    - * modified directly by the user like any other URL.
    - *
    - * If the history object is created in invisible mode, the user can still
    - * affect the state using the browser forward and back buttons, but the current
    - * state is not displayed in the browser address bar. These states are not
    - * bookmarkable or editable.
    - *
    - * It is possible to use both types of history object on the same page, but not
    - * currently recommended due to browser deficiencies.
    - *
    - * Tested to work in:
    - * <ul>
    - *   <li>Firefox 1.0-4.0
    - *   <li>Internet Explorer 5.5-9.0
    - *   <li>Opera 9+
    - *   <li>Safari 4+
    - * </ul>
    - *
    - * @author brenneman@google.com (Shawn Brenneman)
    - * @see ../demos/history1.html
    - * @see ../demos/history2.html
    - */
    -
    -/* Some browser specific implementation notes:
    - *
    - * Firefox (through version 2.0.0.1):
    - *
    - * Ideally, navigating inside the hidden iframe could be done using
    - * about:blank#state instead of a real page on the server. Setting the hash on
    - * about:blank creates history entries, but the hash is not recorded and is lost
    - * when the user hits the back button. This is true in Opera as well. A blank
    - * HTML page must be provided for invisible states to be recorded in the iframe
    - * hash.
    - *
    - * After leaving the page with the History object and returning to it (by
    - * hitting the back button from another site), the last state of the iframe is
    - * overwritten. The most recent state is saved in a hidden input field so the
    - * previous state can be restored.
    - *
    - * Firefox does not store the previous value of dynamically generated input
    - * elements. To save the state, the hidden element must be in the HTML document,
    - * either in the original source or added with document.write. If a reference
    - * to the input element is not provided as a constructor argument, then the
    - * history object creates one using document.write, in which case the history
    - * object must be created from a script in the body element of the page.
    - *
    - * Manually editing the address field to a different hash link prevents further
    - * updates to the address bar. The page continues to work as normal, but the
    - * address shown will be incorrect until the page is reloaded.
    - *
    - * NOTE(user): It should be noted that Firefox will URL encode any non-regular
    - * ascii character, along with |space|, ", <, and >, when added to the fragment.
    - * If you expect these characters in your tokens you should consider that
    - * setToken('<b>') would result in the history fragment "%3Cb%3E", and
    - * "esp&eacute;re" would show "esp%E8re".  (IE allows unicode characters in the
    - * fragment)
    - *
    - * TODO(user): Should we encapsulate this escaping into the API for visible
    - * history and encode all characters that aren't supported by Firefox?  It also
    - * needs to be optional so apps can elect to handle the escaping themselves.
    - *
    - *
    - * Internet Explorer (through version 7.0):
    - *
    - * IE does not modify the history stack when the document fragment is changed.
    - * We create history entries instead by using document.open and document.write
    - * into a hidden iframe.
    - *
    - * IE destroys the history stack when navigating from /foo.html#someFragment to
    - * /foo.html. The workaround is to always append the # to the URL. This is
    - * somewhat unfortunate when loading the page without any # specified, because
    - * a second "click" sound will play on load as the fragment is automatically
    - * appended. If the hash is always present, this can be avoided.
    - *
    - * Manually editing the hash in the address bar in IE6 and then hitting the back
    - * button can replace the page with a blank page. This is a Bad User Experience,
    - * but probably not preventable.
    - *
    - * IE also has a bug when the page is loaded via a server redirect, setting
    - * a new hash value on the window location will force a page reload. This will
    - * happen the first time setToken is called with a new token. The only known
    - * workaround is to force a client reload early, for example by setting
    - * window.location.hash = window.location.hash, which will otherwise be a no-op.
    - *
    - * Internet Explorer 8.0, Webkit 532.1 and Gecko 1.9.2:
    - *
    - * IE8 has introduced the support to the HTML5 onhashchange event, which means
    - * we don't have to do any polling to detect fragment changes. Chrome and
    - * Firefox have added it on their newer builds, wekbit 532.1 and gecko 1.9.2.
    - * http://www.w3.org/TR/html5/history.html
    - * NOTE(goto): it is important to note that the document needs to have the
    - * <!DOCTYPE html> tag to enable the IE8 HTML5 mode. If the tag is not present,
    - * IE8 will enter IE7 compatibility mode (which can also be enabled manually).
    - *
    - * Opera (through version 9.02):
    - *
    - * Navigating through pages at a rate faster than some threshhold causes Opera
    - * to cancel all outstanding timeouts and intervals, including the location
    - * polling loop. Since this condition cannot be detected, common input events
    - * are captured to cause the loop to restart.
    - *
    - * location.replace is adding a history entry inside setHash_, despite
    - * documentation that suggests it should not.
    - *
    - *
    - * Safari (through version 2.0.4):
    - *
    - * After hitting the back button, the location.hash property is no longer
    - * readable from JavaScript. This is fixed in later WebKit builds, but not in
    - * currently shipping Safari. For now, the only recourse is to disable history
    - * states in Safari. Pages are still navigable via the History object, but the
    - * back button cannot restore previous states.
    - *
    - * Safari sets history states on navigation to a hashlink, but doesn't allow
    - * polling of the hash, so following actual anchor links in the page will create
    - * useless history entries. Using location.replace does not seem to prevent
    - * this. Not a terribly good user experience, but fixed in later Webkits.
    - *
    - *
    - * WebKit (nightly version 420+):
    - *
    - * This almost works. Returning to a page with an invisible history object does
    - * not restore the old state, however, and there is no pageshow event that fires
    - * in this browser. Holding off on finding a solution for now.
    - *
    - *
    - * HTML5 capable browsers (Firefox 4, Chrome, Safari 5)
    - *
    - * No known issues. The goog.history.Html5History class provides a simpler
    - * implementation more suitable for recent browsers. These implementations
    - * should be merged so the history class automatically invokes the correct
    - * implementation.
    - */
    -
    -
    -goog.provide('goog.History');
    -goog.provide('goog.History.Event');
    -goog.provide('goog.History.EventType');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.dom');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -goog.require('goog.history.Event');
    -goog.require('goog.history.EventType');
    -goog.require('goog.labs.userAgent.device');
    -goog.require('goog.memoize');
    -goog.require('goog.string');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * A history management object. Can be instantiated in user-visible mode (uses
    - * the address fragment to manage state) or in hidden mode. This object should
    - * be created from a script in the document body before the document has
    - * finished loading.
    - *
    - * To store the hidden states in browsers other than IE, a hidden iframe is
    - * used. It must point to a valid html page on the same domain (which can and
    - * probably should be blank.)
    - *
    - * Sample instantiation and usage:
    - *
    - * <pre>
    - * // Instantiate history to use the address bar for state.
    - * var h = new goog.History();
    - * goog.events.listen(h, goog.history.EventType.NAVIGATE, navCallback);
    - * h.setEnabled(true);
    - *
    - * // Any changes to the location hash will call the following function.
    - * function navCallback(e) {
    - *   alert('Navigated to state "' + e.token + '"');
    - * }
    - *
    - * // The history token can also be set from code directly.
    - * h.setToken('foo');
    - * </pre>
    - *
    - * @param {boolean=} opt_invisible True to use hidden history states instead of
    - *     the user-visible location hash.
    - * @param {string=} opt_blankPageUrl A URL to a blank page on the same server.
    - *     Required if opt_invisible is true.  This URL is also used as the src
    - *     for the iframe used to track history state in IE (if not specified the
    - *     iframe is not given a src attribute).  Access is Denied error may
    - *     occur in IE7 if the window's URL's scheme is https, and this URL is
    - *     not specified.
    - * @param {HTMLInputElement=} opt_input The hidden input element to be used to
    - *     store the history token.  If not provided, a hidden input element will
    - *     be created using document.write.
    - * @param {HTMLIFrameElement=} opt_iframe The hidden iframe that will be used by
    - *     IE for pushing history state changes, or by all browsers if opt_invisible
    - *     is true. If not provided, a hidden iframe element will be created using
    - *     document.write.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - */
    -goog.History = function(opt_invisible, opt_blankPageUrl, opt_input,
    -                        opt_iframe) {
    -  goog.events.EventTarget.call(this);
    -
    -  if (opt_invisible && !opt_blankPageUrl) {
    -    throw Error('Can\'t use invisible history without providing a blank page.');
    -  }
    -
    -  var input;
    -  if (opt_input) {
    -    input = opt_input;
    -  } else {
    -    var inputId = 'history_state' + goog.History.historyCount_;
    -    document.write(goog.string.subs(goog.History.INPUT_TEMPLATE_,
    -                                    inputId, inputId));
    -    input = goog.dom.getElement(inputId);
    -  }
    -
    -  /**
    -   * An input element that stores the current iframe state. Used to restore
    -   * the state when returning to the page on non-IE browsers.
    -   * @type {HTMLInputElement}
    -   * @private
    -   */
    -  this.hiddenInput_ = /** @type {HTMLInputElement} */ (input);
    -
    -  /**
    -   * The window whose location contains the history token fragment. This is
    -   * the window that contains the hidden input. It's typically the top window.
    -   * It is not necessarily the same window that the js code is loaded in.
    -   * @type {Window}
    -   * @private
    -   */
    -  this.window_ = opt_input ?
    -      goog.dom.getWindow(goog.dom.getOwnerDocument(opt_input)) : window;
    -
    -  /**
    -   * The base URL for the hidden iframe. Must refer to a document in the
    -   * same domain as the main page.
    -   * @type {string|undefined}
    -   * @private
    -   */
    -  this.iframeSrc_ = opt_blankPageUrl;
    -
    -  if (goog.userAgent.IE && !opt_blankPageUrl) {
    -    this.iframeSrc_ = window.location.protocol == 'https' ? 'https:///' :
    -                                                            'javascript:""';
    -  }
    -
    -  /**
    -   * A timer for polling the current history state for changes.
    -   * @type {goog.Timer}
    -   * @private
    -   */
    -  this.timer_ = new goog.Timer(goog.History.PollingType.NORMAL);
    -  this.registerDisposable(this.timer_);
    -
    -  /**
    -   * True if the state tokens are displayed in the address bar, false for hidden
    -   * history states.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.userVisible_ = !opt_invisible;
    -
    -  /**
    -   * An object to keep track of the history event listeners.
    -   * @type {goog.events.EventHandler<!goog.History>}
    -   * @private
    -   */
    -  this.eventHandler_ = new goog.events.EventHandler(this);
    -
    -  if (opt_invisible || goog.History.LEGACY_IE) {
    -    var iframe;
    -    if (opt_iframe) {
    -      iframe = opt_iframe;
    -    } else {
    -      var iframeId = 'history_iframe' + goog.History.historyCount_;
    -      var srcAttribute = this.iframeSrc_ ?
    -          'src="' + goog.string.htmlEscape(this.iframeSrc_) + '"' :
    -          '';
    -      document.write(goog.string.subs(goog.History.IFRAME_TEMPLATE_,
    -                                      iframeId,
    -                                      srcAttribute));
    -      iframe = goog.dom.getElement(iframeId);
    -    }
    -
    -    /**
    -     * Internet Explorer uses a hidden iframe for all history changes. Other
    -     * browsers use the iframe only for pushing invisible states.
    -     * @type {HTMLIFrameElement}
    -     * @private
    -     */
    -    this.iframe_ = /** @type {HTMLIFrameElement} */ (iframe);
    -
    -    /**
    -     * Whether the hidden iframe has had a document written to it yet in this
    -     * session.
    -     * @type {boolean}
    -     * @private
    -     */
    -    this.unsetIframe_ = true;
    -  }
    -
    -  if (goog.History.LEGACY_IE) {
    -    // IE relies on the hidden input to restore the history state from previous
    -    // sessions, but input values are only restored after window.onload. Set up
    -    // a callback to poll the value after the onload event.
    -    this.eventHandler_.listen(this.window_,
    -                              goog.events.EventType.LOAD,
    -                              this.onDocumentLoaded);
    -
    -    /**
    -     * IE-only variable for determining if the document has loaded.
    -     * @type {boolean}
    -     * @protected
    -     */
    -    this.documentLoaded = false;
    -
    -    /**
    -     * IE-only variable for storing whether the history object should be enabled
    -     * once the document finishes loading.
    -     * @type {boolean}
    -     * @private
    -     */
    -    this.shouldEnable_ = false;
    -  }
    -
    -  // Set the initial history state.
    -  if (this.userVisible_) {
    -    this.setHash_(this.getToken(), true);
    -  } else {
    -    this.setIframeToken_(this.hiddenInput_.value);
    -  }
    -
    -  goog.History.historyCount_++;
    -};
    -goog.inherits(goog.History, goog.events.EventTarget);
    -
    -
    -/**
    - * Status of when the object is active and dispatching events.
    - * @type {boolean}
    - * @private
    - */
    -goog.History.prototype.enabled_ = false;
    -
    -
    -/**
    - * Whether the object is performing polling with longer intervals. This can
    - * occur for instance when setting the location of the iframe when in invisible
    - * mode and the server that is hosting the blank html page is down. In FF, this
    - * will cause the location of the iframe to no longer be accessible, with
    - * permision denied exceptions being thrown on every access of the history
    - * token. When this occurs, the polling interval is elongated. This causes
    - * exceptions to be thrown at a lesser rate while allowing for the history
    - * object to resurrect itself when the html page becomes accessible.
    - * @type {boolean}
    - * @private
    - */
    -goog.History.prototype.longerPolling_ = false;
    -
    -
    -/**
    - * The last token set by the history object, used to poll for changes.
    - * @type {?string}
    - * @private
    - */
    -goog.History.prototype.lastToken_ = null;
    -
    -
    -/**
    - * Whether the browser supports HTML5 history management's onhashchange event.
    - * {@link http://www.w3.org/TR/html5/history.html}. IE 9 in compatibility mode
    - * indicates that onhashchange is in window, but testing reveals the event
    - * isn't actually fired.
    - * @return {boolean} Whether onhashchange is supported.
    - */
    -goog.History.isOnHashChangeSupported = goog.memoize(function() {
    -  return goog.userAgent.IE ?
    -      document.documentMode >= 8 :
    -      'onhashchange' in goog.global;
    -});
    -
    -
    -/**
    - * Whether the current browser is Internet Explorer prior to version 8. Many IE
    - * specific workarounds developed before version 8 are unnecessary in more
    - * current versions.
    - * @type {boolean}
    - */
    -goog.History.LEGACY_IE = goog.userAgent.IE &&
    -    !goog.userAgent.isDocumentModeOrHigher(8);
    -
    -
    -/**
    - * Whether the browser always requires the hash to be present. Internet Explorer
    - * before version 8 will reload the HTML page if the hash is omitted.
    - * @type {boolean}
    - */
    -goog.History.HASH_ALWAYS_REQUIRED = goog.History.LEGACY_IE;
    -
    -
    -/**
    - * If not null, polling in the user invisible mode will be disabled until this
    - * token is seen. This is used to prevent a race condition where the iframe
    - * hangs temporarily while the location is changed.
    - * @type {?string}
    - * @private
    - */
    -goog.History.prototype.lockedToken_ = null;
    -
    -
    -/** @override */
    -goog.History.prototype.disposeInternal = function() {
    -  goog.History.superClass_.disposeInternal.call(this);
    -  this.eventHandler_.dispose();
    -  this.setEnabled(false);
    -};
    -
    -
    -/**
    - * Starts or stops the History polling loop. When enabled, the History object
    - * will immediately fire an event for the current location. The caller can set
    - * up event listeners between the call to the constructor and the call to
    - * setEnabled.
    - *
    - * On IE, actual startup may be delayed until the iframe and hidden input
    - * element have been loaded and can be polled. This behavior is transparent to
    - * the caller.
    - *
    - * @param {boolean} enable Whether to enable the history polling loop.
    - */
    -goog.History.prototype.setEnabled = function(enable) {
    -
    -  if (enable == this.enabled_) {
    -    return;
    -  }
    -
    -  if (goog.History.LEGACY_IE && !this.documentLoaded) {
    -    // Wait until the document has actually loaded before enabling the
    -    // object or any saved state from a previous session will be lost.
    -    this.shouldEnable_ = enable;
    -    return;
    -  }
    -
    -  if (enable) {
    -    if (goog.userAgent.OPERA) {
    -      // Capture events for common user input so we can restart the timer in
    -      // Opera if it fails. Yes, this is distasteful. See operaDefibrillator_.
    -      this.eventHandler_.listen(this.window_.document,
    -                                goog.History.INPUT_EVENTS_,
    -                                this.operaDefibrillator_);
    -    } else if (goog.userAgent.GECKO) {
    -      // Firefox will not restore the correct state after navigating away from
    -      // and then back to the page with the history object. This can be fixed
    -      // by restarting the history object on the pageshow event.
    -      this.eventHandler_.listen(this.window_, 'pageshow', this.onShow_);
    -    }
    -
    -    // TODO(user): make HTML5 and invisible history work by listening to the
    -    // iframe # changes instead of the window.
    -    if (goog.History.isOnHashChangeSupported() &&
    -        this.userVisible_) {
    -      this.eventHandler_.listen(
    -          this.window_, goog.events.EventType.HASHCHANGE, this.onHashChange_);
    -      this.enabled_ = true;
    -      this.dispatchEvent(new goog.history.Event(this.getToken(), false));
    -    } else if (!(goog.userAgent.IE && !goog.labs.userAgent.device.isMobile()) ||
    -               this.documentLoaded) {
    -      // Start dispatching history events if all necessary loading has
    -      // completed (always true for browsers other than IE.)
    -      this.eventHandler_.listen(this.timer_, goog.Timer.TICK,
    -          goog.bind(this.check_, this, true));
    -
    -      this.enabled_ = true;
    -
    -      // Initialize last token at startup except on IE < 8, where the last token
    -      // must only be set in conjunction with IFRAME updates, or the IFRAME will
    -      // start out of sync and remove any pre-existing URI fragment.
    -      if (!goog.History.LEGACY_IE) {
    -        this.lastToken_ = this.getToken();
    -        this.dispatchEvent(new goog.history.Event(this.getToken(), false));
    -      }
    -
    -      this.timer_.start();
    -    }
    -
    -  } else {
    -    this.enabled_ = false;
    -    this.eventHandler_.removeAll();
    -    this.timer_.stop();
    -  }
    -};
    -
    -
    -/**
    - * Callback for the window onload event in IE. This is necessary to read the
    - * value of the hidden input after restoring a history session. The value of
    - * input elements is not viewable until after window onload for some reason (the
    - * iframe state is similarly unavailable during the loading phase.)  If
    - * setEnabled is called before the iframe has completed loading, the history
    - * object will actually be enabled at this point.
    - * @protected
    - */
    -goog.History.prototype.onDocumentLoaded = function() {
    -  this.documentLoaded = true;
    -
    -  if (this.hiddenInput_.value) {
    -    // Any saved value in the hidden input can only be read after the document
    -    // has been loaded due to an IE limitation. Restore the previous state if
    -    // it has been set.
    -    this.setIframeToken_(this.hiddenInput_.value, true);
    -  }
    -
    -  this.setEnabled(this.shouldEnable_);
    -};
    -
    -
    -/**
    - * Handler for the Gecko pageshow event. Restarts the history object so that the
    - * correct state can be restored in the hash or iframe.
    - * @param {goog.events.BrowserEvent} e The browser event.
    - * @private
    - */
    -goog.History.prototype.onShow_ = function(e) {
    -  // NOTE(user): persisted is a property passed in the pageshow event that
    -  // indicates whether the page is being persisted from the cache or is being
    -  // loaded for the first time.
    -  if (e.getBrowserEvent()['persisted']) {
    -    this.setEnabled(false);
    -    this.setEnabled(true);
    -  }
    -};
    -
    -
    -/**
    - * Handles HTML5 onhashchange events on browsers where it is supported.
    - * This is very similar to {@link #check_}, except that it is not executed
    - * continuously. It is only used when
    - * {@code goog.History.isOnHashChangeSupported()} is true.
    - * @param {goog.events.BrowserEvent} e The browser event.
    - * @private
    - */
    -goog.History.prototype.onHashChange_ = function(e) {
    -  var hash = this.getLocationFragment_(this.window_);
    -  if (hash != this.lastToken_) {
    -    this.update_(hash, true);
    -  }
    -};
    -
    -
    -/**
    - * @return {string} The current token.
    - */
    -goog.History.prototype.getToken = function() {
    -  if (this.lockedToken_ != null) {
    -    return this.lockedToken_;
    -  } else if (this.userVisible_) {
    -    return this.getLocationFragment_(this.window_);
    -  } else {
    -    return this.getIframeToken_() || '';
    -  }
    -};
    -
    -
    -/**
    - * Sets the history state. When user visible states are used, the URL fragment
    - * will be set to the provided token.  Sometimes it is necessary to set the
    - * history token before the document title has changed, in this case IE's
    - * history drop down can be out of sync with the token.  To get around this
    - * problem, the app can pass in a title to use with the hidden iframe.
    - * @param {string} token The history state identifier.
    - * @param {string=} opt_title Optional title used when setting the hidden iframe
    - *     title in IE.
    - */
    -goog.History.prototype.setToken = function(token, opt_title) {
    -  this.setHistoryState_(token, false, opt_title);
    -};
    -
    -
    -/**
    - * Replaces the current history state without affecting the rest of the history
    - * stack.
    - * @param {string} token The history state identifier.
    - * @param {string=} opt_title Optional title used when setting the hidden iframe
    - *     title in IE.
    - */
    -goog.History.prototype.replaceToken = function(token, opt_title) {
    -  this.setHistoryState_(token, true, opt_title);
    -};
    -
    -
    -/**
    - * Gets the location fragment for the current URL.  We don't use location.hash
    - * directly as the browser helpfully urlDecodes the string for us which can
    - * corrupt the tokens.  For example, if we want to store: label/%2Froot it would
    - * be returned as label//root.
    - * @param {Window} win The window object to use.
    - * @return {string} The fragment.
    - * @private
    - */
    -goog.History.prototype.getLocationFragment_ = function(win) {
    -  var href = win.location.href;
    -  var index = href.indexOf('#');
    -  return index < 0 ? '' : href.substring(index + 1);
    -};
    -
    -
    -/**
    - * Sets the history state. When user visible states are used, the URL fragment
    - * will be set to the provided token. Setting opt_replace to true will cause the
    - * navigation to occur, but will replace the current history entry without
    - * affecting the length of the stack.
    - *
    - * @param {string} token The history state identifier.
    - * @param {boolean} replace Set to replace the current history entry instead of
    - *    appending a new history state.
    - * @param {string=} opt_title Optional title used when setting the hidden iframe
    - *     title in IE.
    - * @private
    - */
    -goog.History.prototype.setHistoryState_ = function(token, replace, opt_title) {
    -  if (this.getToken() != token) {
    -    if (this.userVisible_) {
    -      this.setHash_(token, replace);
    -
    -      if (!goog.History.isOnHashChangeSupported()) {
    -        if (goog.userAgent.IE && !goog.labs.userAgent.device.isMobile()) {
    -          // IE must save state using the iframe.
    -          this.setIframeToken_(token, replace, opt_title);
    -        }
    -      }
    -
    -      // This condition needs to be called even if
    -      // goog.History.isOnHashChangeSupported() is true so the NAVIGATE event
    -      // fires sychronously.
    -      if (this.enabled_) {
    -        this.check_(false);
    -      }
    -    } else {
    -      // Fire the event immediately so that setting history is synchronous, but
    -      // set a suspendToken so that polling doesn't trigger a 'back'.
    -      this.setIframeToken_(token, replace);
    -      this.lockedToken_ = this.lastToken_ = this.hiddenInput_.value = token;
    -      this.dispatchEvent(new goog.history.Event(token, false));
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Sets or replaces the URL fragment. The token does not need to be URL encoded
    - * according to the URL specification, though certain characters (like newline)
    - * are automatically stripped.
    - *
    - * If opt_replace is not set, non-IE browsers will append a new entry to the
    - * history list. Setting the hash does not affect the history stack in IE
    - * (unless there is a pre-existing named anchor for that hash.)
    - *
    - * Older versions of Webkit cannot query the location hash, but it still can be
    - * set. If we detect one of these versions, always replace instead of creating
    - * new history entries.
    - *
    - * window.location.replace replaces the current state from the history stack.
    - * http://www.whatwg.org/specs/web-apps/current-work/#dom-location-replace
    - * http://www.whatwg.org/specs/web-apps/current-work/#replacement-enabled
    - *
    - * @param {string} token The new string to set.
    - * @param {boolean=} opt_replace Set to true to replace the current token
    - *    without appending a history entry.
    - * @private
    - */
    -goog.History.prototype.setHash_ = function(token, opt_replace) {
    -  // If the page uses a BASE element, setting location.hash directly will
    -  // navigate away from the current document. Also, the original URL path may
    -  // possibly change from HTML5 history pushState. To account for these, the
    -  // full path is always specified.
    -  var loc = this.window_.location;
    -  var url = loc.href.split('#')[0];
    -
    -  // If a hash has already been set, then removing it programmatically will
    -  // reload the page. Once there is a hash, we won't remove it.
    -  var hasHash = goog.string.contains(loc.href, '#');
    -
    -  if (goog.History.HASH_ALWAYS_REQUIRED || hasHash || token) {
    -    url += '#' + token;
    -  }
    -
    -  if (url != loc.href) {
    -    if (opt_replace) {
    -      loc.replace(url);
    -    } else {
    -      loc.href = url;
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Sets the hidden iframe state. On IE, this is accomplished by writing a new
    - * document into the iframe. In Firefox, the iframe's URL fragment stores the
    - * state instead.
    - *
    - * Older versions of webkit cannot set the iframe, so ignore those browsers.
    - *
    - * @param {string} token The new string to set.
    - * @param {boolean=} opt_replace Set to true to replace the current iframe state
    - *     without appending a new history entry.
    - * @param {string=} opt_title Optional title used when setting the hidden iframe
    - *     title in IE.
    - * @private
    - */
    -goog.History.prototype.setIframeToken_ = function(token,
    -                                                  opt_replace,
    -                                                  opt_title) {
    -  if (this.unsetIframe_ || token != this.getIframeToken_()) {
    -
    -    this.unsetIframe_ = false;
    -    token = goog.string.urlEncode(token);
    -
    -    if (goog.userAgent.IE) {
    -      // Caching the iframe document results in document permission errors after
    -      // leaving the page and returning. Access it anew each time instead.
    -      var doc = goog.dom.getFrameContentDocument(this.iframe_);
    -
    -      doc.open('text/html', opt_replace ? 'replace' : undefined);
    -      doc.write(goog.string.subs(
    -          goog.History.IFRAME_SOURCE_TEMPLATE_,
    -          goog.string.htmlEscape(
    -              /** @type {string} */ (opt_title || this.window_.document.title)),
    -          token));
    -      doc.close();
    -    } else {
    -      var url = this.iframeSrc_ + '#' + token;
    -
    -      // In Safari, it is possible for the contentWindow of the iframe to not
    -      // be present when the page is loading after a reload.
    -      var contentWindow = this.iframe_.contentWindow;
    -      if (contentWindow) {
    -        if (opt_replace) {
    -          contentWindow.location.replace(url);
    -        } else {
    -          contentWindow.location.href = url;
    -        }
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Return the current state string from the hidden iframe. On internet explorer,
    - * this is stored as a string in the document body. Other browsers use the
    - * location hash of the hidden iframe.
    - *
    - * Older versions of webkit cannot access the iframe location, so always return
    - * null in that case.
    - *
    - * @return {?string} The state token saved in the iframe (possibly null if the
    - *     iframe has never loaded.).
    - * @private
    - */
    -goog.History.prototype.getIframeToken_ = function() {
    -  if (goog.userAgent.IE) {
    -    var doc = goog.dom.getFrameContentDocument(this.iframe_);
    -    return doc.body ? goog.string.urlDecode(doc.body.innerHTML) : null;
    -  } else {
    -    // In Safari, it is possible for the contentWindow of the iframe to not
    -    // be present when the page is loading after a reload.
    -    var contentWindow = this.iframe_.contentWindow;
    -    if (contentWindow) {
    -      var hash;
    -      /** @preserveTry */
    -      try {
    -        // Iframe tokens are urlEncoded
    -        hash = goog.string.urlDecode(this.getLocationFragment_(contentWindow));
    -      } catch (e) {
    -        // An exception will be thrown if the location of the iframe can not be
    -        // accessed (permission denied). This can occur in FF if the the server
    -        // that is hosting the blank html page goes down and then a new history
    -        // token is set. The iframe will navigate to an error page, and the
    -        // location of the iframe can no longer be accessed. Due to the polling,
    -        // this will cause constant exceptions to be thrown. In this case,
    -        // we enable longer polling. We do not have to attempt to reset the
    -        // iframe token because (a) we already fired the NAVIGATE event when
    -        // setting the token, (b) we can rely on the locked token for current
    -        // state, and (c) the token is still in the history and
    -        // accesible on forward/back.
    -        if (!this.longerPolling_) {
    -          this.setLongerPolling_(true);
    -        }
    -
    -        return null;
    -      }
    -
    -      // There was no exception when getting the hash so turn off longer polling
    -      // if it is on.
    -      if (this.longerPolling_) {
    -        this.setLongerPolling_(false);
    -      }
    -
    -      return hash || null;
    -    } else {
    -      return null;
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Checks the state of the document fragment and the iframe title to detect
    - * navigation changes. If {@code goog.HistoryisOnHashChangeSupported()} is
    - * {@code false}, then this runs approximately twenty times per second.
    - * @param {boolean} isNavigation True if the event was initiated by a browser
    - *     action, false if it was caused by a setToken call. See
    - *     {@link goog.history.Event}.
    - * @private
    - */
    -goog.History.prototype.check_ = function(isNavigation) {
    -  if (this.userVisible_) {
    -    var hash = this.getLocationFragment_(this.window_);
    -    if (hash != this.lastToken_) {
    -      this.update_(hash, isNavigation);
    -    }
    -  }
    -
    -  // Old IE uses the iframe for both visible and non-visible versions.
    -  if (!this.userVisible_ || goog.History.LEGACY_IE) {
    -    var token = this.getIframeToken_() || '';
    -    if (this.lockedToken_ == null || token == this.lockedToken_) {
    -      this.lockedToken_ = null;
    -      if (token != this.lastToken_) {
    -        this.update_(token, isNavigation);
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Updates the current history state with a given token. Called after a change
    - * to the location or the iframe state is detected by poll_.
    - *
    - * @param {string} token The new history state.
    - * @param {boolean} isNavigation True if the event was initiated by a browser
    - *     action, false if it was caused by a setToken call. See
    - *     {@link goog.history.Event}.
    - * @private
    - */
    -goog.History.prototype.update_ = function(token, isNavigation) {
    -  this.lastToken_ = this.hiddenInput_.value = token;
    -
    -  if (this.userVisible_) {
    -    if (goog.History.LEGACY_IE) {
    -      this.setIframeToken_(token);
    -    }
    -
    -    this.setHash_(token);
    -  } else {
    -    this.setIframeToken_(token);
    -  }
    -
    -  this.dispatchEvent(new goog.history.Event(this.getToken(), isNavigation));
    -};
    -
    -
    -/**
    - * Sets if the history oject should use longer intervals when polling.
    - *
    - * @param {boolean} longerPolling Whether to enable longer polling.
    - * @private
    - */
    -goog.History.prototype.setLongerPolling_ = function(longerPolling) {
    -  if (this.longerPolling_ != longerPolling) {
    -    this.timer_.setInterval(longerPolling ?
    -        goog.History.PollingType.LONG : goog.History.PollingType.NORMAL);
    -  }
    -  this.longerPolling_ = longerPolling;
    -};
    -
    -
    -/**
    - * Opera cancels all outstanding timeouts and intervals after any rapid
    - * succession of navigation events, including the interval used to detect
    - * navigation events. This function restarts the interval so that navigation can
    - * continue. Ideally, only events which would be likely to cause a navigation
    - * change (mousedown and keydown) would be bound to this function. Since Opera
    - * seems to ignore keydown events while the alt key is pressed (such as
    - * alt-left or right arrow), this function is also bound to the much more
    - * frequent mousemove event. This way, when the update loop freezes, it will
    - * unstick itself as the user wiggles the mouse in frustration.
    - * @private
    - */
    -goog.History.prototype.operaDefibrillator_ = function() {
    -  this.timer_.stop();
    -  this.timer_.start();
    -};
    -
    -
    -/**
    - * List of user input event types registered in Opera to restart the history
    - * timer (@see goog.History#operaDefibrillator_).
    - * @type {Array<string>}
    - * @private
    - */
    -goog.History.INPUT_EVENTS_ = [
    -  goog.events.EventType.MOUSEDOWN,
    -  goog.events.EventType.KEYDOWN,
    -  goog.events.EventType.MOUSEMOVE
    -];
    -
    -
    -/**
    - * Minimal HTML page used to populate the iframe in Internet Explorer. The title
    - * is visible in the history dropdown menu, the iframe state is stored as the
    - * body innerHTML.
    - * @type {string}
    - * @private
    - */
    -goog.History.IFRAME_SOURCE_TEMPLATE_ = '<title>%s</title><body>%s</body>';
    -
    -
    -/**
    - * HTML template for an invisible iframe.
    - * @type {string}
    - * @private
    - */
    -goog.History.IFRAME_TEMPLATE_ =
    -    '<iframe id="%s" style="display:none" %s></iframe>';
    -
    -
    -/**
    - * HTML template for an invisible named input element.
    - * @type {string}
    - * @private
    - */
    -goog.History.INPUT_TEMPLATE_ =
    -    '<input type="text" name="%s" id="%s" style="display:none">';
    -
    -
    -/**
    - * Counter for the number of goog.History objects that have been instantiated.
    - * Used to create unique IDs.
    - * @type {number}
    - * @private
    - */
    -goog.History.historyCount_ = 0;
    -
    -
    -/**
    - * Types of polling. The values are in ms of the polling interval.
    - * @enum {number}
    - */
    -goog.History.PollingType = {
    -  NORMAL: 150,
    -  LONG: 10000
    -};
    -
    -
    -/**
    - * Constant for the history change event type.
    - * @enum {string}
    - * @deprecated Use goog.history.EventType.
    - */
    -goog.History.EventType = goog.history.EventType;
    -
    -
    -
    -/**
    - * Constant for the history change event type.
    - * @param {string} token The string identifying the new history state.
    - * @extends {goog.events.Event}
    - * @constructor
    - * @deprecated Use goog.history.Event.
    - * @final
    - */
    -goog.History.Event = goog.history.Event;
    diff --git a/src/database/third_party/closure-library/closure/goog/history/history_test.html b/src/database/third_party/closure-library/closure/goog/history/history_test.html
    deleted file mode 100644
    index d13286e4da9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/history/history_test.html
    +++ /dev/null
    @@ -1,21 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.history</title>
    -<script src="../base.js"></script>
    -<script>
    -goog.require('goog.HistoryTest');
    -</script>
    -</head>
    -<body>
    -<input id="hidden-input" type="hidden">
    -<iframe id="hidden-iframe" style="display:none">
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/history/history_test.js b/src/database/third_party/closure-library/closure/goog/history/history_test.js
    deleted file mode 100644
    index 614d0047a94..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/history/history_test.js
    +++ /dev/null
    @@ -1,55 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.history.History.
    - */
    -
    -/** @suppress {extraProvide} */
    -goog.provide('goog.HistoryTest');
    -
    -goog.require('goog.History');
    -goog.require('goog.dispose');
    -goog.require('goog.dom');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -goog.setTestOnly('goog.HistoryTest');
    -
    -
    -// Mimimal function to exercise construction.
    -function testCreation() {
    -  var input = goog.dom.getElement('hidden-input');
    -  var iframe = goog.dom.getElement('hidden-iframe');
    -
    -  try {
    -    var history = new goog.History(undefined, undefined, input, iframe);
    -  } finally {
    -    goog.dispose(history);
    -  }
    -}
    -
    -function testIsHashChangeSupported() {
    -
    -  // This is the policy currently implemented.
    -  var supportsOnHashChange = (goog.userAgent.IE ?
    -      document.documentMode >= 8 :
    -      'onhashchange' in window);
    -
    -  assertEquals(
    -      supportsOnHashChange,
    -      goog.History.isOnHashChangeSupported());
    -}
    -
    -// TODO(nnaze): Test additional behavior.
    diff --git a/src/database/third_party/closure-library/closure/goog/history/html5history.js b/src/database/third_party/closure-library/closure/goog/history/html5history.js
    deleted file mode 100644
    index 038d711e3c4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/history/html5history.js
    +++ /dev/null
    @@ -1,303 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview HTML5 based history implementation, compatible with
    - * goog.History.
    - *
    - * TODO(user): There should really be a history interface and multiple
    - * implementations.
    - *
    - */
    -
    -
    -goog.provide('goog.history.Html5History');
    -goog.provide('goog.history.Html5History.TokenTransformer');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.events');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -goog.require('goog.history.Event');
    -
    -
    -
    -/**
    - * An implementation compatible with goog.History that uses the HTML5
    - * history APIs.
    - *
    - * @param {Window=} opt_win The window to listen/dispatch history events on.
    - * @param {goog.history.Html5History.TokenTransformer=} opt_transformer
    - *     The token transformer that is used to create URL from the token
    - *     when storing token without using hash fragment.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - * @final
    - */
    -goog.history.Html5History = function(opt_win, opt_transformer) {
    -  goog.events.EventTarget.call(this);
    -  goog.asserts.assert(goog.history.Html5History.isSupported(opt_win),
    -      'HTML5 history is not supported.');
    -
    -  /**
    -   * The window object to use for history tokens.  Typically the top window.
    -   * @type {Window}
    -   * @private
    -   */
    -  this.window_ = opt_win || window;
    -
    -  /**
    -   * The token transformer that is used to create URL from the token
    -   * when storing token without using hash fragment.
    -   * @type {goog.history.Html5History.TokenTransformer}
    -   * @private
    -   */
    -  this.transformer_ = opt_transformer || null;
    -
    -  goog.events.listen(this.window_, goog.events.EventType.POPSTATE,
    -      this.onHistoryEvent_, false, this);
    -  goog.events.listen(this.window_, goog.events.EventType.HASHCHANGE,
    -      this.onHistoryEvent_, false, this);
    -};
    -goog.inherits(goog.history.Html5History, goog.events.EventTarget);
    -
    -
    -/**
    - * Returns whether Html5History is supported.
    - * @param {Window=} opt_win Optional window to check.
    - * @return {boolean} Whether html5 history is supported.
    - */
    -goog.history.Html5History.isSupported = function(opt_win) {
    -  var win = opt_win || window;
    -  return !!(win.history && win.history.pushState);
    -};
    -
    -
    -/**
    - * Status of when the object is active and dispatching events.
    - * @type {boolean}
    - * @private
    - */
    -goog.history.Html5History.prototype.enabled_ = false;
    -
    -
    -/**
    - * Whether to use the fragment to store the token, defaults to true.
    - * @type {boolean}
    - * @private
    - */
    -goog.history.Html5History.prototype.useFragment_ = true;
    -
    -
    -/**
    - * If useFragment is false the path will be used, the path prefix will be
    - * prepended to all tokens. Defaults to '/'.
    - * @type {string}
    - * @private
    - */
    -goog.history.Html5History.prototype.pathPrefix_ = '/';
    -
    -
    -/**
    - * Starts or stops the History.  When enabled, the History object
    - * will immediately fire an event for the current location. The caller can set
    - * up event listeners between the call to the constructor and the call to
    - * setEnabled.
    - *
    - * @param {boolean} enable Whether to enable history.
    - */
    -goog.history.Html5History.prototype.setEnabled = function(enable) {
    -  if (enable == this.enabled_) {
    -    return;
    -  }
    -
    -  this.enabled_ = enable;
    -
    -  if (enable) {
    -    this.dispatchEvent(new goog.history.Event(this.getToken(), false));
    -  }
    -};
    -
    -
    -/**
    - * Returns the current token.
    - * @return {string} The current token.
    - */
    -goog.history.Html5History.prototype.getToken = function() {
    -  if (this.useFragment_) {
    -    var loc = this.window_.location.href;
    -    var index = loc.indexOf('#');
    -    return index < 0 ? '' : loc.substring(index + 1);
    -  } else {
    -    return this.transformer_ ?
    -        this.transformer_.retrieveToken(
    -            this.pathPrefix_, this.window_.location) :
    -        this.window_.location.pathname.substr(this.pathPrefix_.length);
    -  }
    -};
    -
    -
    -/**
    - * Sets the history state.
    - * @param {string} token The history state identifier.
    - * @param {string=} opt_title Optional title to associate with history entry.
    - */
    -goog.history.Html5History.prototype.setToken = function(token, opt_title) {
    -  if (token == this.getToken()) {
    -    return;
    -  }
    -
    -  // Per externs/gecko_dom.js document.title can be null.
    -  this.window_.history.pushState(null,
    -      opt_title || this.window_.document.title || '', this.getUrl_(token));
    -  this.dispatchEvent(new goog.history.Event(token, false));
    -};
    -
    -
    -/**
    - * Replaces the current history state without affecting the rest of the history
    - * stack.
    - * @param {string} token The history state identifier.
    - * @param {string=} opt_title Optional title to associate with history entry.
    - */
    -goog.history.Html5History.prototype.replaceToken = function(token, opt_title) {
    -  // Per externs/gecko_dom.js document.title can be null.
    -  this.window_.history.replaceState(null,
    -      opt_title || this.window_.document.title || '', this.getUrl_(token));
    -  this.dispatchEvent(new goog.history.Event(token, false));
    -};
    -
    -
    -/** @override */
    -goog.history.Html5History.prototype.disposeInternal = function() {
    -  goog.events.unlisten(this.window_, goog.events.EventType.POPSTATE,
    -      this.onHistoryEvent_, false, this);
    -  if (this.useFragment_) {
    -    goog.events.unlisten(this.window_, goog.events.EventType.HASHCHANGE,
    -        this.onHistoryEvent_, false, this);
    -  }
    -};
    -
    -
    -/**
    - * Sets whether to use the fragment to store tokens.
    - * @param {boolean} useFragment Whether to use the fragment.
    - */
    -goog.history.Html5History.prototype.setUseFragment = function(useFragment) {
    -  if (this.useFragment_ != useFragment) {
    -    if (useFragment) {
    -      goog.events.listen(this.window_, goog.events.EventType.HASHCHANGE,
    -          this.onHistoryEvent_, false, this);
    -    } else {
    -      goog.events.unlisten(this.window_, goog.events.EventType.HASHCHANGE,
    -          this.onHistoryEvent_, false, this);
    -    }
    -    this.useFragment_ = useFragment;
    -  }
    -};
    -
    -
    -/**
    - * Sets the path prefix to use if storing tokens in the path. The path
    - * prefix should start and end with slash.
    - * @param {string} pathPrefix Sets the path prefix.
    - */
    -goog.history.Html5History.prototype.setPathPrefix = function(pathPrefix) {
    -  this.pathPrefix_ = pathPrefix;
    -};
    -
    -
    -/**
    - * Gets the path prefix.
    - * @return {string} The path prefix.
    - */
    -goog.history.Html5History.prototype.getPathPrefix = function() {
    -  return this.pathPrefix_;
    -};
    -
    -
    -/**
    - * Gets the URL to set when calling history.pushState
    - * @param {string} token The history token.
    - * @return {string} The URL.
    - * @private
    - */
    -goog.history.Html5History.prototype.getUrl_ = function(token) {
    -  if (this.useFragment_) {
    -    return '#' + token;
    -  } else {
    -    return this.transformer_ ?
    -        this.transformer_.createUrl(
    -            token, this.pathPrefix_, this.window_.location) :
    -        this.pathPrefix_ + token + this.window_.location.search;
    -  }
    -};
    -
    -
    -/**
    - * Handles history events dispatched by the browser.
    - * @param {goog.events.BrowserEvent} e The browser event object.
    - * @private
    - */
    -goog.history.Html5History.prototype.onHistoryEvent_ = function(e) {
    -  if (this.enabled_) {
    -    this.dispatchEvent(new goog.history.Event(this.getToken(), true));
    -  }
    -};
    -
    -
    -
    -/**
    - * A token transformer that can create a URL from a history
    - * token. This is used by {@code goog.history.Html5History} to create
    - * URL when storing token without the hash fragment.
    - *
    - * Given a {@code window.location} object containing the location
    - * created by {@code createUrl}, the token transformer allows
    - * retrieval of the token back via {@code retrieveToken}.
    - *
    - * @interface
    - */
    -goog.history.Html5History.TokenTransformer = function() {};
    -
    -
    -/**
    - * Retrieves a history token given the path prefix and
    - * {@code window.location} object.
    - *
    - * @param {string} pathPrefix The path prefix to use when storing token
    - *     in a path; always begin with a slash.
    - * @param {Location} location The {@code window.location} object.
    - *     Treat this object as read-only.
    - * @return {string} token The history token.
    - */
    -goog.history.Html5History.TokenTransformer.prototype.retrieveToken = function(
    -    pathPrefix, location) {};
    -
    -
    -/**
    - * Creates a URL to be pushed into HTML5 history stack when storing
    - * token without using hash fragment.
    - *
    - * @param {string} token The history token.
    - * @param {string} pathPrefix The path prefix to use when storing token
    - *     in a path; always begin with a slash.
    - * @param {Location} location The {@code window.location} object.
    - *     Treat this object as read-only.
    - * @return {string} url The complete URL string from path onwards
    - *     (without {@code protocol://host:port} part); must begin with a
    - *     slash.
    - */
    -goog.history.Html5History.TokenTransformer.prototype.createUrl = function(
    -    token, pathPrefix, location) {};
    diff --git a/src/database/third_party/closure-library/closure/goog/history/html5history_test.html b/src/database/third_party/closure-library/closure/goog/history/html5history_test.html
    deleted file mode 100644
    index 13ef94e214c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/history/html5history_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.history.Html5History
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.history.Html5HistoryTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/history/html5history_test.js b/src/database/third_party/closure-library/closure/goog/history/html5history_test.js
    deleted file mode 100644
    index 955f28a4a14..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/history/html5history_test.js
    +++ /dev/null
    @@ -1,159 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.history.Html5HistoryTest');
    -goog.setTestOnly('goog.history.Html5HistoryTest');
    -
    -goog.require('goog.history.Html5History');
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.mockmatchers');
    -
    -var mockControl;
    -var mockWindow;
    -
    -var html5History;
    -
    -function setUp() {
    -  mockControl = new goog.testing.MockControl();
    -
    -  mockWindow = {
    -    location: {}
    -  };
    -  mockWindow.attachEvent = mockControl.createFunctionMock();
    -  mockWindow.attachEvent(
    -      goog.testing.mockmatchers.ignoreArgument,
    -      goog.testing.mockmatchers.ignoreArgument).$anyTimes();
    -  var mockHistoryIsSupportedMethod = mockControl.createMethodMock(
    -      goog.history.Html5History, 'isSupported');
    -  mockHistoryIsSupportedMethod(mockWindow).$returns(true).$anyTimes();
    -}
    -
    -function tearDown() {
    -  if (html5History) {
    -    html5History.dispose();
    -    html5History = null;
    -  }
    -  mockControl.$tearDown();
    -}
    -
    -function testGetTokenWithoutUsingFragment() {
    -  mockWindow.location.pathname = '/test/something';
    -
    -  mockControl.$replayAll();
    -  html5History = new goog.history.Html5History(mockWindow);
    -  html5History.setUseFragment(false);
    -
    -  assertEquals('test/something', html5History.getToken());
    -  mockControl.$verifyAll();
    -}
    -
    -function testGetTokenWithoutUsingFragmentWithCustomPathPrefix() {
    -  mockWindow.location.pathname = '/test/something';
    -
    -  mockControl.$replayAll();
    -  html5History = new goog.history.Html5History(mockWindow);
    -  html5History.setUseFragment(false);
    -  html5History.setPathPrefix('/test/');
    -
    -  assertEquals('something', html5History.getToken());
    -  mockControl.$verifyAll();
    -}
    -
    -function testGetTokenWithoutUsingFragmentWithCustomTransformer() {
    -  mockWindow.location.pathname = '/test/something';
    -  var mockTransformer = mockControl.createLooseMock(
    -      goog.history.Html5History.TokenTransformer);
    -  mockTransformer.retrieveToken('/', mockWindow.location).$returns('abc/1');
    -
    -  mockControl.$replayAll();
    -  html5History = new goog.history.Html5History(mockWindow, mockTransformer);
    -  html5History.setUseFragment(false);
    -
    -  assertEquals('abc/1', html5History.getToken());
    -  mockControl.$verifyAll();
    -}
    -
    -function testGetTokenWithoutUsingFragmentWithCustomTransformerAndPrefix() {
    -  mockWindow.location.pathname = '/test/something';
    -  var mockTransformer = mockControl.createLooseMock(
    -      goog.history.Html5History.TokenTransformer);
    -  mockTransformer.retrieveToken('/test/', mockWindow.location).
    -      $returns('abc/1');
    -
    -  mockControl.$replayAll();
    -  html5History = new goog.history.Html5History(mockWindow, mockTransformer);
    -  html5History.setUseFragment(false);
    -  html5History.setPathPrefix('/test/');
    -
    -  assertEquals('abc/1', html5History.getToken());
    -  mockControl.$verifyAll();
    -}
    -
    -function testGetUrlWithoutUsingFragment() {
    -  mockWindow.location.search = '?q=something';
    -
    -  mockControl.$replayAll();
    -  html5History = new goog.history.Html5History(mockWindow);
    -  html5History.setUseFragment(false);
    -
    -  assertEquals('/some/token?q=something', html5History.getUrl_('some/token'));
    -  mockControl.$verifyAll();
    -}
    -
    -function testGetUrlWithoutUsingFragmentWithCustomPathPrefix() {
    -  mockWindow.location.search = '?q=something';
    -
    -  mockControl.$replayAll();
    -  html5History = new goog.history.Html5History(mockWindow);
    -  html5History.setUseFragment(false);
    -  html5History.setPathPrefix('/test/');
    -
    -  assertEquals('/test/some/token?q=something',
    -               html5History.getUrl_('some/token'));
    -  mockControl.$verifyAll();
    -}
    -
    -function testGetUrlWithoutUsingFragmentWithCustomTransformer() {
    -  mockWindow.location.search = '?q=something';
    -  var mockTransformer = mockControl.createLooseMock(
    -      goog.history.Html5History.TokenTransformer);
    -  mockTransformer.createUrl('some/token', '/', mockWindow.location).
    -      $returns('/something/else/?different');
    -
    -  mockControl.$replayAll();
    -  html5History = new goog.history.Html5History(mockWindow, mockTransformer);
    -  html5History.setUseFragment(false);
    -
    -  assertEquals('/something/else/?different',
    -               html5History.getUrl_('some/token'));
    -  mockControl.$verifyAll();
    -}
    -
    -function testGetUrlWithoutUsingFragmentWithCustomTransformerAndPrefix() {
    -  mockWindow.location.search = '?q=something';
    -  var mockTransformer = mockControl.createLooseMock(
    -      goog.history.Html5History.TokenTransformer);
    -  mockTransformer.createUrl('some/token', '/test/', mockWindow.location).
    -      $returns('/something/else/?different');
    -
    -  mockControl.$replayAll();
    -  html5History = new goog.history.Html5History(mockWindow, mockTransformer);
    -  html5History.setUseFragment(false);
    -  html5History.setPathPrefix('/test/');
    -
    -  assertEquals('/something/else/?different',
    -               html5History.getUrl_('some/token'));
    -  mockControl.$verifyAll();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/html/flash.js b/src/database/third_party/closure-library/closure/goog/html/flash.js
    deleted file mode 100644
    index 9f72665db6f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/flash.js
    +++ /dev/null
    @@ -1,177 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview SafeHtml factory methods for creating object and embed tags
    - * for loading Flash files.
    - */
    -
    -goog.provide('goog.html.flash');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.html.SafeHtml');
    -
    -
    -/**
    - * Attributes and param tag name attributes not allowed to be overriden
    - * when calling createObject() and createObjectForOldIe().
    - *
    - * While values that should be specified as params are probably not
    - * recognized as attributes, we block them anyway just to be sure.
    - * @const {!Array<string>}
    - * @private
    - */
    -goog.html.flash.FORBIDDEN_ATTRS_AND_PARAMS_ON_FLASH_ = [
    -  'classid',  // Used on old IE.
    -  'data',  // Used in <object> to specify a URL.
    -  'movie',  // Used on old IE.
    -  'type',  // Used in <object> on for non-IE/modern IE.
    -  'typemustmatch'  // Always set to a fixed value.
    -];
    -
    -
    -goog.html.flash.createEmbed = function(src, opt_attributes) {
    -  var fixedAttributes = {
    -    'src': src,
    -    'type': 'application/x-shockwave-flash',
    -    'pluginspage': 'https://www.macromedia.com/go/getflashplayer'
    -  };
    -  var defaultAttributes = {
    -    'allownetworking': 'none',
    -    'allowscriptaccess': 'never'
    -  };
    -  var attributes = goog.html.SafeHtml.combineAttributes(
    -      fixedAttributes, defaultAttributes, opt_attributes);
    -  return goog.html.SafeHtml.
    -      createSafeHtmlTagSecurityPrivateDoNotAccessOrElse('embed', attributes);
    -};
    -
    -
    -goog.html.flash.createObject = function(
    -    data, opt_params, opt_attributes) {
    -  goog.html.flash.verifyKeysNotInMaps(
    -      goog.html.flash.FORBIDDEN_ATTRS_AND_PARAMS_ON_FLASH_,
    -      opt_attributes,
    -      opt_params);
    -
    -  var paramTags = goog.html.flash.combineParams(
    -      {
    -        'allownetworking': 'none',
    -        'allowscriptaccess': 'never'
    -      },
    -      opt_params);
    -  var fixedAttributes = {
    -    'data': data,
    -    'type': 'application/x-shockwave-flash',
    -    'typemustmatch': ''
    -  };
    -  var attributes = goog.html.SafeHtml.combineAttributes(
    -      fixedAttributes, {}, opt_attributes);
    -
    -  return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse(
    -      'object', attributes, paramTags);
    -};
    -
    -
    -goog.html.flash.createObjectForOldIe = function(
    -    movie, opt_params, opt_attributes) {
    -  goog.html.flash.verifyKeysNotInMaps(
    -      goog.html.flash.FORBIDDEN_ATTRS_AND_PARAMS_ON_FLASH_,
    -      opt_attributes,
    -      opt_params);
    -
    -  var paramTags = goog.html.flash.combineParams(
    -      {
    -        'allownetworking': 'none',
    -        'allowscriptaccess': 'never',
    -        'movie': movie
    -      },
    -      opt_params);
    -  var fixedAttributes =
    -      {'classid': 'clsid:d27cdb6e-ae6d-11cf-96b8-444553540000'};
    -  var attributes = goog.html.SafeHtml.combineAttributes(
    -      fixedAttributes, {}, opt_attributes);
    -
    -  return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse(
    -      'object', attributes, paramTags);
    -};
    -
    -
    -/**
    - * @param {!Object<string, string|!goog.string.TypedString>} defaultParams
    - * @param {!Object<string, string>=}
    - *     opt_params Optional params passed to create*().
    - * @return {!Array<!goog.html.SafeHtml>} Combined params.
    - * @throws {Error} If opt_attributes contains an attribute with the same name
    - *     as an attribute in fixedAttributes.
    - * @package
    - */
    -goog.html.flash.combineParams = function(defaultParams, opt_params) {
    -  var combinedParams = {};
    -  var name;
    -
    -  for (name in defaultParams) {
    -    goog.asserts.assert(name.toLowerCase() == name, 'Must be lower case');
    -    combinedParams[name] = defaultParams[name];
    -  }
    -  for (name in opt_params) {
    -    var nameLower = name.toLowerCase();
    -    if (nameLower in defaultParams) {
    -      delete combinedParams[nameLower];
    -    }
    -    combinedParams[name] = opt_params[name];
    -  }
    -
    -  var paramTags = [];
    -  for (name in combinedParams) {
    -    paramTags.push(
    -        goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse(
    -            'param', {'name': name, 'value': combinedParams[name]}));
    -
    -  }
    -  return paramTags;
    -};
    -
    -
    -/**
    - * Checks that keys are not present as keys in maps.
    - * @param {!Array<string>} keys Keys that must not be present, lower-case.
    - * @param {!Object<string, goog.html.SafeHtml.AttributeValue_>=}
    - *     opt_attributes Optional attributes passed to create*().
    - * @param {!Object<string, string>=}  opt_params Optional params passed to
    - *     createObject*().
    - * @throws {Error} If any of keys exist as a key, ignoring case, in
    - *     opt_attributes or opt_params.
    - * @package
    - */
    -goog.html.flash.verifyKeysNotInMaps = function(
    -    keys, opt_attributes, opt_params) {
    -  var verifyNotInMap = function(keys, map, type) {
    -    for (var keyMap in map) {
    -      var keyMapLower = keyMap.toLowerCase();
    -      for (var i = 0; i < keys.length; i++) {
    -        var keyToCheck = keys[i];
    -        goog.asserts.assert(keyToCheck.toLowerCase() == keyToCheck);
    -        if (keyMapLower == keyToCheck) {
    -          throw Error('Cannot override "' + keyToCheck + '" ' + type +
    -              ', got "' + keyMap + '" with value "' + map[keyMap] + '"');
    -        }
    -      }
    -    }
    -  };
    -
    -  verifyNotInMap(keys, opt_attributes, 'attribute');
    -  verifyNotInMap(keys, opt_params, 'param');
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/html/flash_test.html b/src/database/third_party/closure-library/closure/goog/html/flash_test.html
    deleted file mode 100644
    index 0477c48361d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/flash_test.html
    +++ /dev/null
    @@ -1,19 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.html.flash</title>
    -<script src="../base.js"></script>
    -<script>
    -goog.require('goog.html.flashTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/html/flash_test.js b/src/database/third_party/closure-library/closure/goog/html/flash_test.js
    deleted file mode 100644
    index 3ba31fe87c6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/flash_test.js
    +++ /dev/null
    @@ -1,111 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.html.flash.
    - */
    -
    -goog.provide('goog.html.flashTest');
    -
    -goog.require('goog.html.SafeHtml');
    -goog.require('goog.html.TrustedResourceUrl');
    -goog.require('goog.html.flash');
    -goog.require('goog.string.Const');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.html.flashTest');
    -
    -
    -function testCreateEmbed() {
    -  var trustedResourceUrl = goog.html.TrustedResourceUrl.fromConstant(
    -      goog.string.Const.from('https://google.com/trusted&'));
    -  assertSameHtml(
    -      '<embed ' +
    -          'src="https://google.com/trusted&amp;" ' +
    -          'type="application/x-shockwave-flash" ' +
    -          'pluginspage="https://www.macromedia.com/go/getflashplayer" ' +
    -          'allownetworking="none" ' +
    -          'allowScriptAccess="always&lt;" ' +
    -          'class="test&lt;">',
    -      goog.html.flash.createEmbed(
    -          trustedResourceUrl,
    -          {'allowScriptAccess': 'always<', 'class': 'test<'}));
    -
    -  // Cannot override attributes, case insensitive.
    -  assertThrows(function() {
    -    goog.html.flash.createEmbed(
    -        trustedResourceUrl, {'Type': 'cannotdothis'});
    -  });
    -}
    -
    -
    -function testCreateObject() {
    -  var trustedResourceUrl = goog.html.TrustedResourceUrl.fromConstant(
    -      goog.string.Const.from('https://google.com/trusted&'));
    -  assertSameHtml(
    -      '<object data="https://google.com/trusted&amp;" ' +
    -          'type="application/x-shockwave-flash" typemustmatch="" ' +
    -          'class="test&lt;">' +
    -          '<param name="allownetworking" value="none">' +
    -          '<param name="allowScriptAccess" value="always&lt;">' +
    -          '</object>',
    -      goog.html.flash.createObject(
    -          trustedResourceUrl,
    -          {'allowScriptAccess': 'always<'}, {'class': 'test<'}));
    -
    -  // Cannot override params, case insensitive.
    -  assertThrows(function() {
    -    goog.html.flash.createObject(
    -        trustedResourceUrl, {'datA': 'cantdothis'});
    -  });
    -
    -  // Cannot override attributes, case insensitive.
    -  assertThrows(function() {
    -    goog.html.flash.createObject(
    -        trustedResourceUrl, {}, {'datA': 'cantdothis'});
    -  });
    -}
    -
    -
    -function testCreateObjectForOldIe() {
    -  var trustedResourceUrl = goog.html.TrustedResourceUrl.fromConstant(
    -      goog.string.Const.from('https://google.com/trusted&'));
    -  assertSameHtml(
    -      '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" ' +
    -          'class="test&lt;">' +
    -          '<param name="allownetworking" value="none">' +
    -          '<param name="movie" value="https://google.com/trusted&amp;">' +
    -          '<param name="allowScriptAccess" value="always&lt;">' +
    -          '</object>',
    -      goog.html.flash.createObjectForOldIe(
    -          trustedResourceUrl,
    -          {'allowScriptAccess': 'always<'}, {'class': 'test<'}));
    -
    -  // Cannot override params, case insensitive.
    -  assertThrows(function() {
    -    goog.html.flash.createObjectForOldIe(
    -        trustedResourceUrl, {'datA': 'cantdothis'});
    -  });
    -
    -  // Cannot override attributes, case insensitive.
    -  assertThrows(function() {
    -    goog.html.flash.createObjectForOldIe(
    -        trustedResourceUrl, {}, {'datA': 'cantdothis'});
    -  });
    -}
    -
    -
    -function assertSameHtml(expected, html) {
    -  assertEquals(expected, goog.html.SafeHtml.unwrap(html));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/html/legacyconversions.js b/src/database/third_party/closure-library/closure/goog/html/legacyconversions.js
    deleted file mode 100644
    index 89a4c6d4453..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/legacyconversions.js
    +++ /dev/null
    @@ -1,200 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Conversions from plain string to goog.html types for use in
    - * legacy APIs that do not use goog.html types.
    - *
    - * This file provides conversions to create values of goog.html types from plain
    - * strings.  These conversions are intended for use in legacy APIs that consume
    - * HTML in the form of plain string types, but whose implementations use
    - * goog.html types internally (and expose such types in an augmented, HTML-type-
    - * safe API).
    - *
    - * IMPORTANT: No new code should use the conversion functions in this file.
    - *
    - * The conversion functions in this file are guarded with global flag
    - * (goog.html.legacyconversions.ALLOW_LEGACY_CONVERSIONS). If set to false, it
    - * effectively "locks in" an entire application to only use HTML-type-safe APIs.
    - *
    - * Intended use of the functions in this file are as follows:
    - *
    - * Many Closure and application-specific classes expose methods that consume
    - * values that in the class' implementation are forwarded to DOM APIs that can
    - * result in security vulnerabilities.  For example, goog.ui.Dialog's setContent
    - * method consumes a string that is assigned to an element's innerHTML property;
    - * if this string contains untrusted (attacker-controlled) data, this can result
    - * in a cross-site-scripting vulnerability.
    - *
    - * Widgets such as goog.ui.Dialog are being augmented to expose safe APIs
    - * expressed in terms of goog.html types.  For instance, goog.ui.Dialog has a
    - * method setSafeHtmlContent that consumes an object of type goog.html.SafeHtml,
    - * a type whose contract guarantees that its value is safe to use in HTML
    - * context, i.e. can be safely assigned to .innerHTML. An application that only
    - * uses this API is forced to only supply values of this type, i.e. values that
    - * are safe.
    - *
    - * However, the legacy method setContent cannot (for the time being) be removed
    - * from goog.ui.Dialog, due to a large number of existing callers.  The
    - * implementation of goog.ui.Dialog has been refactored to use
    - * goog.html.SafeHtml throughout.  This in turn requires that the value consumed
    - * by its setContent method is converted to goog.html.SafeHtml in an unchecked
    - * conversion. The conversion function is provided by this file:
    - * goog.html.legacyconversions.safeHtmlFromString.
    - *
    - * Note that the semantics of the conversions in goog.html.legacyconversions are
    - * very different from the ones provided by goog.html.uncheckedconversions:  The
    - * latter are for use in code where it has been established through manual
    - * security review that the value produced by a piece of code must always
    - * satisfy the SafeHtml contract (e.g., the output of a secure HTML sanitizer).
    - * In uses of goog.html.legacyconversions, this guarantee is not given -- the
    - * value in question originates in unreviewed legacy code and there is no
    - * guarantee that it satisfies the SafeHtml contract.
    - *
    - * To establish correctness with confidence, application code should be
    - * refactored to use SafeHtml instead of plain string to represent HTML markup,
    - * and to use goog.html-typed APIs (e.g., goog.ui.Dialog#setSafeHtmlContent
    - * instead of goog.ui.Dialog#setContent).
    - *
    - * To prevent introduction of new vulnerabilities, application owners can
    - * effectively disable unsafe legacy APIs by compiling with the define
    - * goog.html.legacyconversions.ALLOW_LEGACY_CONVERSIONS set to false.  When
    - * set, this define causes the conversion methods in this file to
    - * unconditionally throw an exception.
    - *
    - * Note that new code should always be compiled with
    - * ALLOW_LEGACY_CONVERSIONS=false.  At some future point, the default for this
    - * define may change to false.
    - */
    -
    -
    -goog.provide('goog.html.legacyconversions');
    -
    -goog.require('goog.html.SafeHtml');
    -goog.require('goog.html.SafeStyle');
    -goog.require('goog.html.SafeUrl');
    -goog.require('goog.html.TrustedResourceUrl');
    -
    -
    -/**
    - * @define {boolean} Whether conversion from string to goog.html types for
    - * legacy API purposes is permitted.
    - *
    - * If false, the conversion functions in this file unconditionally throw an
    - * exception.
    - */
    -goog.define('goog.html.legacyconversions.ALLOW_LEGACY_CONVERSIONS', true);
    -
    -
    -/**
    - * Performs an "unchecked conversion" from string to SafeHtml for legacy API
    - * purposes.
    - *
    - * Unchecked conversion will not proceed if ALLOW_LEGACY_CONVERSIONS is false,
    - * and instead this function unconditionally throws an exception.
    - *
    - * @param {string} html A string to be converted to SafeHtml.
    - * @return {!goog.html.SafeHtml} The value of html, wrapped in a SafeHtml
    - *     object.
    - */
    -goog.html.legacyconversions.safeHtmlFromString = function(html) {
    -  goog.html.legacyconversions.throwIfConversionsDisallowed();
    -  return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(
    -      html, null /* dir */);
    -};
    -
    -
    -/**
    - * Performs an "unchecked conversion" from string to SafeStyle for legacy API
    - * purposes.
    - *
    - * Unchecked conversion will not proceed if ALLOW_LEGACY_CONVERSIONS is false,
    - * and instead this function unconditionally throws an exception.
    - *
    - * @param {string} style A string to be converted to SafeStyle.
    - * @return {!goog.html.SafeStyle} The value of style, wrapped in a SafeStyle
    - *     object.
    - */
    -goog.html.legacyconversions.safeStyleFromString = function(style) {
    -  goog.html.legacyconversions.throwIfConversionsDisallowed();
    -  return goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(
    -      style);
    -};
    -
    -
    -/**
    - * Performs an "unchecked conversion" from string to TrustedResourceUrl for
    - * legacy API purposes.
    - *
    - * Unchecked conversion will not proceed if ALLOW_LEGACY_CONVERSIONS is false,
    - * and instead this function unconditionally throws an exception.
    - *
    - * @param {string} url A string to be converted to TrustedResourceUrl.
    - * @return {!goog.html.TrustedResourceUrl} The value of url, wrapped in a
    - *     TrustedResourceUrl object.
    - */
    -goog.html.legacyconversions.trustedResourceUrlFromString = function(url) {
    -  goog.html.legacyconversions.throwIfConversionsDisallowed();
    -  return goog.html.TrustedResourceUrl.
    -      createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(url);
    -};
    -
    -
    -/**
    - * Performs an "unchecked conversion" from string to SafeUrl for legacy API
    - * purposes.
    - *
    - * Unchecked conversion will not proceed if ALLOW_LEGACY_CONVERSIONS is false,
    - * and instead this function unconditionally throws an exception.
    - *
    - * @param {string} url A string to be converted to SafeUrl.
    - * @return {!goog.html.SafeUrl} The value of url, wrapped in a SafeUrl
    - *     object.
    - */
    -goog.html.legacyconversions.safeUrlFromString = function(url) {
    -  goog.html.legacyconversions.throwIfConversionsDisallowed();
    -  return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(url);
    -};
    -
    -
    -/**
    - * @private {function(): undefined}
    - */
    -goog.html.legacyconversions.reportCallback_ = goog.nullFunction;
    -
    -
    -/**
    - * Sets a function that will be called every time a legacy conversion is
    - * performed. The function is called with no parameters but it can use
    - * goog.debug.getStacktrace to get a stacktrace.
    - *
    - * @param {function(): undefined} callback Error callback as defined above.
    - */
    -goog.html.legacyconversions.setReportCallback = function(callback) {
    -  goog.html.legacyconversions.reportCallback_ = callback;
    -};
    -
    -
    -/**
    - * Throws an exception if ALLOW_LEGACY_CONVERSIONS is false. This is useful
    - * for legacy APIs which consume HTML in the form of plain string types, but
    - * do not provide an alternative HTML-type-safe API.
    - */
    -goog.html.legacyconversions.throwIfConversionsDisallowed = function() {
    -  if (!goog.html.legacyconversions.ALLOW_LEGACY_CONVERSIONS) {
    -    throw Error(
    -        'Error: Legacy conversion from string to goog.html types is disabled');
    -  }
    -  goog.html.legacyconversions.reportCallback_();
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/html/legacyconversions_test.html b/src/database/third_party/closure-library/closure/goog/html/legacyconversions_test.html
    deleted file mode 100644
    index 7af17d734c6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/legacyconversions_test.html
    +++ /dev/null
    @@ -1,19 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.html</title>
    -<script src="../base.js"></script>
    -<script>
    -goog.require('goog.html.legacyconversionsTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/html/legacyconversions_test.js b/src/database/third_party/closure-library/closure/goog/html/legacyconversions_test.js
    deleted file mode 100644
    index 9e8841b38aa..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/legacyconversions_test.js
    +++ /dev/null
    @@ -1,95 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.html.legacyconversions.
    - */
    -
    -goog.provide('goog.html.legacyconversionsTest');
    -
    -goog.require('goog.html.SafeHtml');
    -goog.require('goog.html.SafeUrl');
    -goog.require('goog.html.TrustedResourceUrl');
    -goog.require('goog.html.legacyconversions');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.html.legacyconversionsTest');
    -
    -
    -/** @type {!goog.testing.PropertyReplacer} */
    -var stubs = new goog.testing.PropertyReplacer();
    -
    -
    -function setUp() {
    -  // Reset goog.html.legacyconveresions global defines for each test case.
    -  stubs.set(goog.html.legacyconversions, 'ALLOW_LEGACY_CONVERSIONS', true);
    -}
    -
    -
    -function testSafeHtmlFromString_allowedIfNotGloballyDisabled() {
    -  var helloWorld = 'Hello <em>World</em>';
    -  var safeHtml = goog.html.legacyconversions.safeHtmlFromString(helloWorld);
    -  assertEquals(helloWorld, goog.html.SafeHtml.unwrap(safeHtml));
    -  assertNull(safeHtml.getDirection());
    -}
    -
    -
    -function testSafeHtmlFromString_guardedByGlobalFlag() {
    -  stubs.set(goog.html.legacyconversions, 'ALLOW_LEGACY_CONVERSIONS', false);
    -  assertEquals(
    -      'Error: Legacy conversion from string to goog.html types is disabled',
    -      assertThrows(function() {
    -        goog.html.legacyconversions.safeHtmlFromString(
    -            'Possibly untrusted <html>');
    -      }).message);
    -}
    -
    -
    -function testSafeHtmlFromString_reports() {
    -  var reported = false;
    -  goog.html.legacyconversions.setReportCallback(function() {
    -    reported = true;
    -  });
    -  goog.html.legacyconversions.safeHtmlFromString('<html>');
    -  assertTrue('Expected legacy conversion to be reported.', reported);
    -
    -  reported = false;
    -  stubs.set(goog.html.legacyconversions, 'ALLOW_LEGACY_CONVERSIONS', false);
    -  try {
    -    goog.html.legacyconversions.safeHtmlFromString('<html>');
    -  } catch (expected) {
    -  }
    -  assertFalse('Expected legacy conversion to not be reported.', reported);
    -
    -  stubs.set(goog.html.legacyconversions, 'ALLOW_LEGACY_CONVERSIONS', true);
    -  goog.html.legacyconversions.setReportCallback(goog.nullFunction);
    -  goog.html.legacyconversions.safeHtmlFromString('<html>');
    -  assertFalse('Expected legacy conversion to not be reported.', reported);
    -}
    -
    -
    -function testSafeUrlFromString() {
    -  var url = 'https://www.google.com';
    -  var safeUrl = goog.html.legacyconversions.safeUrlFromString(url);
    -  assertEquals(url, goog.html.SafeUrl.unwrap(safeUrl));
    -}
    -
    -
    -function testTrustedResourceUrlFromString() {
    -  var url = 'https://www.google.com/script.js';
    -  var trustedResourceUrl =
    -      goog.html.legacyconversions.trustedResourceUrlFromString(url);
    -  assertEquals(url, goog.html.TrustedResourceUrl.unwrap(trustedResourceUrl));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/html/safehtml.js b/src/database/third_party/closure-library/closure/goog/html/safehtml.js
    deleted file mode 100644
    index 4a99af521e6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/safehtml.js
    +++ /dev/null
    @@ -1,744 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview The SafeHtml type and its builders.
    - *
    - * TODO(user): Link to document stating type contract.
    - */
    -
    -goog.provide('goog.html.SafeHtml');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.dom.tags');
    -goog.require('goog.html.SafeStyle');
    -goog.require('goog.html.SafeStyleSheet');
    -goog.require('goog.html.SafeUrl');
    -goog.require('goog.html.TrustedResourceUrl');
    -goog.require('goog.i18n.bidi.Dir');
    -goog.require('goog.i18n.bidi.DirectionalString');
    -goog.require('goog.object');
    -goog.require('goog.string');
    -goog.require('goog.string.Const');
    -goog.require('goog.string.TypedString');
    -
    -
    -
    -/**
    - * A string that is safe to use in HTML context in DOM APIs and HTML documents.
    - *
    - * A SafeHtml is a string-like object that carries the security type contract
    - * that its value as a string will not cause untrusted script execution when
    - * evaluated as HTML in a browser.
    - *
    - * Values of this type are guaranteed to be safe to use in HTML contexts,
    - * such as, assignment to the innerHTML DOM property, or interpolation into
    - * a HTML template in HTML PC_DATA context, in the sense that the use will not
    - * result in a Cross-Site-Scripting vulnerability.
    - *
    - * Instances of this type must be created via the factory methods
    - * ({@code goog.html.SafeHtml.create}, {@code goog.html.SafeHtml.htmlEscape}),
    - * etc and not by invoking its constructor.  The constructor intentionally
    - * takes no parameters and the type is immutable; hence only a default instance
    - * corresponding to the empty string can be obtained via constructor invocation.
    - *
    - * @see goog.html.SafeHtml#create
    - * @see goog.html.SafeHtml#htmlEscape
    - * @constructor
    - * @final
    - * @struct
    - * @implements {goog.i18n.bidi.DirectionalString}
    - * @implements {goog.string.TypedString}
    - */
    -goog.html.SafeHtml = function() {
    -  /**
    -   * The contained value of this SafeHtml.  The field has a purposely ugly
    -   * name to make (non-compiled) code that attempts to directly access this
    -   * field stand out.
    -   * @private {string}
    -   */
    -  this.privateDoNotAccessOrElseSafeHtmlWrappedValue_ = '';
    -
    -  /**
    -   * A type marker used to implement additional run-time type checking.
    -   * @see goog.html.SafeHtml#unwrap
    -   * @const
    -   * @private
    -   */
    -  this.SAFE_HTML_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ =
    -      goog.html.SafeHtml.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_;
    -
    -  /**
    -   * This SafeHtml's directionality, or null if unknown.
    -   * @private {?goog.i18n.bidi.Dir}
    -   */
    -  this.dir_ = null;
    -};
    -
    -
    -/**
    - * @override
    - * @const
    - */
    -goog.html.SafeHtml.prototype.implementsGoogI18nBidiDirectionalString = true;
    -
    -
    -/** @override */
    -goog.html.SafeHtml.prototype.getDirection = function() {
    -  return this.dir_;
    -};
    -
    -
    -/**
    - * @override
    - * @const
    - */
    -goog.html.SafeHtml.prototype.implementsGoogStringTypedString = true;
    -
    -
    -/**
    - * Returns this SafeHtml's value a string.
    - *
    - * IMPORTANT: In code where it is security relevant that an object's type is
    - * indeed {@code SafeHtml}, use {@code goog.html.SafeHtml.unwrap} instead of
    - * this method. If in doubt, assume that it's security relevant. In particular,
    - * note that goog.html functions which return a goog.html type do not guarantee
    - * that the returned instance is of the right type. For example:
    - *
    - * <pre>
    - * var fakeSafeHtml = new String('fake');
    - * fakeSafeHtml.__proto__ = goog.html.SafeHtml.prototype;
    - * var newSafeHtml = goog.html.SafeHtml.htmlEscape(fakeSafeHtml);
    - * // newSafeHtml is just an alias for fakeSafeHtml, it's passed through by
    - * // goog.html.SafeHtml.htmlEscape() as fakeSafeHtml
    - * // instanceof goog.html.SafeHtml.
    - * </pre>
    - *
    - * @see goog.html.SafeHtml#unwrap
    - * @override
    - */
    -goog.html.SafeHtml.prototype.getTypedStringValue = function() {
    -  return this.privateDoNotAccessOrElseSafeHtmlWrappedValue_;
    -};
    -
    -
    -if (goog.DEBUG) {
    -  /**
    -   * Returns a debug string-representation of this value.
    -   *
    -   * To obtain the actual string value wrapped in a SafeHtml, use
    -   * {@code goog.html.SafeHtml.unwrap}.
    -   *
    -   * @see goog.html.SafeHtml#unwrap
    -   * @override
    -   */
    -  goog.html.SafeHtml.prototype.toString = function() {
    -    return 'SafeHtml{' + this.privateDoNotAccessOrElseSafeHtmlWrappedValue_ +
    -        '}';
    -  };
    -}
    -
    -
    -/**
    - * Performs a runtime check that the provided object is indeed a SafeHtml
    - * object, and returns its value.
    - * @param {!goog.html.SafeHtml} safeHtml The object to extract from.
    - * @return {string} The SafeHtml object's contained string, unless the run-time
    - *     type check fails. In that case, {@code unwrap} returns an innocuous
    - *     string, or, if assertions are enabled, throws
    - *     {@code goog.asserts.AssertionError}.
    - */
    -goog.html.SafeHtml.unwrap = function(safeHtml) {
    -  // Perform additional run-time type-checking to ensure that safeHtml is indeed
    -  // an instance of the expected type.  This provides some additional protection
    -  // against security bugs due to application code that disables type checks.
    -  // Specifically, the following checks are performed:
    -  // 1. The object is an instance of the expected type.
    -  // 2. The object is not an instance of a subclass.
    -  // 3. The object carries a type marker for the expected type. "Faking" an
    -  // object requires a reference to the type marker, which has names intended
    -  // to stand out in code reviews.
    -  if (safeHtml instanceof goog.html.SafeHtml &&
    -      safeHtml.constructor === goog.html.SafeHtml &&
    -      safeHtml.SAFE_HTML_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ ===
    -          goog.html.SafeHtml.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_) {
    -    return safeHtml.privateDoNotAccessOrElseSafeHtmlWrappedValue_;
    -  } else {
    -    goog.asserts.fail('expected object of type SafeHtml, got \'' +
    -                      safeHtml + '\'');
    -    return 'type_error:SafeHtml';
    -  }
    -};
    -
    -
    -/**
    - * Shorthand for union of types that can sensibly be converted to strings
    - * or might already be SafeHtml (as SafeHtml is a goog.string.TypedString).
    - * @private
    - * @typedef {string|number|boolean|!goog.string.TypedString|
    - *           !goog.i18n.bidi.DirectionalString}
    - */
    -goog.html.SafeHtml.TextOrHtml_;
    -
    -
    -/**
    - * Returns HTML-escaped text as a SafeHtml object.
    - *
    - * If text is of a type that implements
    - * {@code goog.i18n.bidi.DirectionalString}, the directionality of the new
    - * {@code SafeHtml} object is set to {@code text}'s directionality, if known.
    - * Otherwise, the directionality of the resulting SafeHtml is unknown (i.e.,
    - * {@code null}).
    - *
    - * @param {!goog.html.SafeHtml.TextOrHtml_} textOrHtml The text to escape. If
    - *     the parameter is of type SafeHtml it is returned directly (no escaping
    - *     is done).
    - * @return {!goog.html.SafeHtml} The escaped text, wrapped as a SafeHtml.
    - */
    -goog.html.SafeHtml.htmlEscape = function(textOrHtml) {
    -  if (textOrHtml instanceof goog.html.SafeHtml) {
    -    return textOrHtml;
    -  }
    -  var dir = null;
    -  if (textOrHtml.implementsGoogI18nBidiDirectionalString) {
    -    dir = textOrHtml.getDirection();
    -  }
    -  var textAsString;
    -  if (textOrHtml.implementsGoogStringTypedString) {
    -    textAsString = textOrHtml.getTypedStringValue();
    -  } else {
    -    textAsString = String(textOrHtml);
    -  }
    -  return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(
    -      goog.string.htmlEscape(textAsString), dir);
    -};
    -
    -
    -/**
    - * Returns HTML-escaped text as a SafeHtml object, with newlines changed to
    - * &lt;br&gt;.
    - * @param {!goog.html.SafeHtml.TextOrHtml_} textOrHtml The text to escape. If
    - *     the parameter is of type SafeHtml it is returned directly (no escaping
    - *     is done).
    - * @return {!goog.html.SafeHtml} The escaped text, wrapped as a SafeHtml.
    - */
    -goog.html.SafeHtml.htmlEscapePreservingNewlines = function(textOrHtml) {
    -  if (textOrHtml instanceof goog.html.SafeHtml) {
    -    return textOrHtml;
    -  }
    -  var html = goog.html.SafeHtml.htmlEscape(textOrHtml);
    -  return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(
    -      goog.string.newLineToBr(goog.html.SafeHtml.unwrap(html)),
    -      html.getDirection());
    -};
    -
    -
    -/**
    - * Returns HTML-escaped text as a SafeHtml object, with newlines changed to
    - * &lt;br&gt; and escaping whitespace to preserve spatial formatting. Character
    - * entity #160 is used to make it safer for XML.
    - * @param {!goog.html.SafeHtml.TextOrHtml_} textOrHtml The text to escape. If
    - *     the parameter is of type SafeHtml it is returned directly (no escaping
    - *     is done).
    - * @return {!goog.html.SafeHtml} The escaped text, wrapped as a SafeHtml.
    - */
    -goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces = function(
    -    textOrHtml) {
    -  if (textOrHtml instanceof goog.html.SafeHtml) {
    -    return textOrHtml;
    -  }
    -  var html = goog.html.SafeHtml.htmlEscape(textOrHtml);
    -  return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(
    -      goog.string.whitespaceEscape(goog.html.SafeHtml.unwrap(html)),
    -      html.getDirection());
    -};
    -
    -
    -/**
    - * Coerces an arbitrary object into a SafeHtml object.
    - *
    - * If {@code textOrHtml} is already of type {@code goog.html.SafeHtml}, the same
    - * object is returned. Otherwise, {@code textOrHtml} is coerced to string, and
    - * HTML-escaped. If {@code textOrHtml} is of a type that implements
    - * {@code goog.i18n.bidi.DirectionalString}, its directionality, if known, is
    - * preserved.
    - *
    - * @param {!goog.html.SafeHtml.TextOrHtml_} textOrHtml The text or SafeHtml to
    - *     coerce.
    - * @return {!goog.html.SafeHtml} The resulting SafeHtml object.
    - * @deprecated Use goog.html.SafeHtml.htmlEscape.
    - */
    -goog.html.SafeHtml.from = goog.html.SafeHtml.htmlEscape;
    -
    -
    -/**
    - * @const
    - * @private
    - */
    -goog.html.SafeHtml.VALID_NAMES_IN_TAG_ = /^[a-zA-Z0-9-]+$/;
    -
    -
    -/**
    - * Set of attributes containing URL as defined at
    - * http://www.w3.org/TR/html5/index.html#attributes-1.
    - * @private @const {!Object<string,boolean>}
    - */
    -goog.html.SafeHtml.URL_ATTRIBUTES_ = goog.object.createSet('action', 'cite',
    -    'data', 'formaction', 'href', 'manifest', 'poster', 'src');
    -
    -
    -/**
    - * Tags which are unsupported via create(). They might be supported via a
    - * tag-specific create method. These are tags which might require a
    - * TrustedResourceUrl in one of their attributes or a restricted type for
    - * their content.
    - * @private @const {!Object<string,boolean>}
    - */
    -goog.html.SafeHtml.NOT_ALLOWED_TAG_NAMES_ = goog.object.createSet(
    -    'embed', 'iframe', 'link', 'object', 'script', 'style', 'template');
    -
    -
    -/**
    - * @typedef {string|number|goog.string.TypedString|
    - *     goog.html.SafeStyle.PropertyMap}
    - * @private
    - */
    -goog.html.SafeHtml.AttributeValue_;
    -
    -
    -/**
    - * Creates a SafeHtml content consisting of a tag with optional attributes and
    - * optional content.
    - *
    - * For convenience tag names and attribute names are accepted as regular
    - * strings, instead of goog.string.Const. Nevertheless, you should not pass
    - * user-controlled values to these parameters. Note that these parameters are
    - * syntactically validated at runtime, and invalid values will result in
    - * an exception.
    - *
    - * Example usage:
    - *
    - * goog.html.SafeHtml.create('br');
    - * goog.html.SafeHtml.create('div', {'class': 'a'});
    - * goog.html.SafeHtml.create('p', {}, 'a');
    - * goog.html.SafeHtml.create('p', {}, goog.html.SafeHtml.create('br'));
    - *
    - * goog.html.SafeHtml.create('span', {
    - *   'style': {'margin': '0'}
    - * });
    - *
    - * To guarantee SafeHtml's type contract is upheld there are restrictions on
    - * attribute values and tag names.
    - *
    - * - For attributes which contain script code (on*), a goog.string.Const is
    - *   required.
    - * - For attributes which contain style (style), a goog.html.SafeStyle or a
    - *   goog.html.SafeStyle.PropertyMap is required.
    - * - For attributes which are interpreted as URLs (e.g. src, href) a
    - *   goog.html.SafeUrl or goog.string.Const is required.
    - * - For tags which can load code, more specific goog.html.SafeHtml.create*()
    - *   functions must be used. Tags which can load code and are not supported by
    - *   this function are embed, iframe, link, object, script, style, and template.
    - *
    - * @param {string} tagName The name of the tag. Only tag names consisting of
    - *     [a-zA-Z0-9-] are allowed. Tag names documented above are disallowed.
    - * @param {!Object<string, goog.html.SafeHtml.AttributeValue_>=}
    - *     opt_attributes Mapping from attribute names to their values. Only
    - *     attribute names consisting of [a-zA-Z0-9-] are allowed. Value of null or
    - *     undefined causes the attribute to be omitted.
    - * @param {!goog.html.SafeHtml.TextOrHtml_|
    - *     !Array<!goog.html.SafeHtml.TextOrHtml_>=} opt_content Content to
    - *     HTML-escape and put inside the tag. This must be empty for void tags
    - *     like <br>. Array elements are concatenated.
    - * @return {!goog.html.SafeHtml} The SafeHtml content with the tag.
    - * @throws {Error} If invalid tag name, attribute name, or attribute value is
    - *     provided.
    - * @throws {goog.asserts.AssertionError} If content for void tag is provided.
    - */
    -goog.html.SafeHtml.create = function(tagName, opt_attributes, opt_content) {
    -  if (!goog.html.SafeHtml.VALID_NAMES_IN_TAG_.test(tagName)) {
    -    throw Error('Invalid tag name <' + tagName + '>.');
    -  }
    -  if (tagName.toLowerCase() in goog.html.SafeHtml.NOT_ALLOWED_TAG_NAMES_) {
    -    throw Error('Tag name <' + tagName + '> is not allowed for SafeHtml.');
    -  }
    -  return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse(
    -      tagName, opt_attributes, opt_content);
    -};
    -
    -
    -/**
    - * Creates a SafeHtml representing an iframe tag.
    - *
    - * By default the sandbox attribute is set to an empty value, which is the most
    - * secure option, as it confers the iframe the least privileges. If this
    - * is too restrictive then granting individual privileges is the preferable
    - * option. Unsetting the attribute entirely is the least secure option and
    - * should never be done unless it's stricly necessary.
    - *
    - * @param {goog.html.TrustedResourceUrl=} opt_src The value of the src
    - *     attribute. If null or undefined src will not be set.
    - * @param {goog.html.SafeHtml=} opt_srcdoc The value of the srcdoc attribute.
    - *     If null or undefined srcdoc will not be set.
    - * @param {!Object<string, goog.html.SafeHtml.AttributeValue_>=}
    - *     opt_attributes Mapping from attribute names to their values. Only
    - *     attribute names consisting of [a-zA-Z0-9-] are allowed. Value of null or
    - *     undefined causes the attribute to be omitted.
    - * @param {!goog.html.SafeHtml.TextOrHtml_|
    - *     !Array<!goog.html.SafeHtml.TextOrHtml_>=} opt_content Content to
    - *     HTML-escape and put inside the tag. Array elements are concatenated.
    - * @return {!goog.html.SafeHtml} The SafeHtml content with the tag.
    - * @throws {Error} If invalid tag name, attribute name, or attribute value is
    - *     provided. If opt_attributes contains the src or srcdoc attributes.
    - */
    -goog.html.SafeHtml.createIframe = function(
    -    opt_src, opt_srcdoc, opt_attributes, opt_content) {
    -  var fixedAttributes = {};
    -  fixedAttributes['src'] = opt_src || null;
    -  fixedAttributes['srcdoc'] = opt_srcdoc || null;
    -  var defaultAttributes = {'sandbox': ''};
    -  var attributes = goog.html.SafeHtml.combineAttributes(
    -      fixedAttributes, defaultAttributes, opt_attributes);
    -  return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse(
    -      'iframe', attributes, opt_content);
    -};
    -
    -
    -/**
    - * Creates a SafeHtml representing a style tag. The type attribute is set
    - * to "text/css".
    - * @param {!goog.html.SafeStyleSheet|!Array<!goog.html.SafeStyleSheet>}
    - *     styleSheet Content to put inside the tag. Array elements are
    - *     concatenated.
    - * @param {!Object<string, goog.html.SafeHtml.AttributeValue_>=}
    - *     opt_attributes Mapping from attribute names to their values. Only
    - *     attribute names consisting of [a-zA-Z0-9-] are allowed. Value of null or
    - *     undefined causes the attribute to be omitted.
    - * @return {!goog.html.SafeHtml} The SafeHtml content with the tag.
    - * @throws {Error} If invalid attribute name or attribute value is provided. If
    - *     opt_attributes contains the type attribute.
    - */
    -goog.html.SafeHtml.createStyle = function(styleSheet, opt_attributes) {
    -  var fixedAttributes = {'type': 'text/css'};
    -  var defaultAttributes = {};
    -  var attributes = goog.html.SafeHtml.combineAttributes(
    -      fixedAttributes, defaultAttributes, opt_attributes);
    -
    -  var content = '';
    -  styleSheet = goog.array.concat(styleSheet);
    -  for (var i = 0; i < styleSheet.length; i++) {
    -    content += goog.html.SafeStyleSheet.unwrap(styleSheet[i]);
    -  }
    -  // Convert to SafeHtml so that it's not HTML-escaped.
    -  var htmlContent = goog.html.SafeHtml
    -      .createSafeHtmlSecurityPrivateDoNotAccessOrElse(
    -          content, goog.i18n.bidi.Dir.NEUTRAL);
    -  return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse(
    -      'style', attributes, htmlContent);
    -};
    -
    -
    -/**
    - * @param {string} tagName The tag name.
    - * @param {string} name The attribute name.
    - * @param {!goog.html.SafeHtml.AttributeValue_} value The attribute value.
    - * @return {string} A "name=value" string.
    - * @throws {Error} If attribute value is unsafe for the given tag and attribute.
    - * @private
    - */
    -goog.html.SafeHtml.getAttrNameAndValue_ = function(tagName, name, value) {
    -  // If it's goog.string.Const, allow any valid attribute name.
    -  if (value instanceof goog.string.Const) {
    -    value = goog.string.Const.unwrap(value);
    -  } else if (name.toLowerCase() == 'style') {
    -    value = goog.html.SafeHtml.getStyleValue_(value);
    -  } else if (/^on/i.test(name)) {
    -    // TODO(jakubvrana): Disallow more attributes with a special meaning.
    -    throw Error('Attribute "' + name +
    -        '" requires goog.string.Const value, "' + value + '" given.');
    -  // URL attributes handled differently accroding to tag.
    -  } else if (name.toLowerCase() in goog.html.SafeHtml.URL_ATTRIBUTES_) {
    -    if (value instanceof goog.html.TrustedResourceUrl) {
    -      value = goog.html.TrustedResourceUrl.unwrap(value);
    -    } else if (value instanceof goog.html.SafeUrl) {
    -      value = goog.html.SafeUrl.unwrap(value);
    -    } else {
    -      // TODO(user): Allow strings and sanitize them automatically,
    -      // so that it's consistent with accepting a map directly for "style".
    -      throw Error('Attribute "' + name + '" on tag "' + tagName +
    -          '" requires goog.html.SafeUrl or goog.string.Const value, "' +
    -          value + '" given.');
    -    }
    -  }
    -
    -  // Accept SafeUrl, TrustedResourceUrl, etc. for attributes which only require
    -  // HTML-escaping.
    -  if (value.implementsGoogStringTypedString) {
    -    // Ok to call getTypedStringValue() since there's no reliance on the type
    -    // contract for security here.
    -    value = value.getTypedStringValue();
    -  }
    -
    -  goog.asserts.assert(goog.isString(value) || goog.isNumber(value),
    -      'String or number value expected, got ' +
    -      (typeof value) + ' with value: ' + value);
    -  return name + '="' + goog.string.htmlEscape(String(value)) + '"';
    -};
    -
    -
    -/**
    - * Gets value allowed in "style" attribute.
    - * @param {goog.html.SafeHtml.AttributeValue_} value It could be SafeStyle or a
    - *     map which will be passed to goog.html.SafeStyle.create.
    - * @return {string} Unwrapped value.
    - * @throws {Error} If string value is given.
    - * @private
    - */
    -goog.html.SafeHtml.getStyleValue_ = function(value) {
    -  if (!goog.isObject(value)) {
    -    throw Error('The "style" attribute requires goog.html.SafeStyle or map ' +
    -        'of style properties, ' + (typeof value) + ' given: ' + value);
    -  }
    -  if (!(value instanceof goog.html.SafeStyle)) {
    -    // Process the property bag into a style object.
    -    value = goog.html.SafeStyle.create(value);
    -  }
    -  return goog.html.SafeStyle.unwrap(value);
    -};
    -
    -
    -/**
    - * Creates a SafeHtml content with known directionality consisting of a tag with
    - * optional attributes and optional content.
    - * @param {!goog.i18n.bidi.Dir} dir Directionality.
    - * @param {string} tagName
    - * @param {!Object<string, goog.html.SafeHtml.AttributeValue_>=} opt_attributes
    - * @param {!goog.html.SafeHtml.TextOrHtml_|
    - *     !Array<!goog.html.SafeHtml.TextOrHtml_>=} opt_content
    - * @return {!goog.html.SafeHtml} The SafeHtml content with the tag.
    - */
    -goog.html.SafeHtml.createWithDir = function(dir, tagName, opt_attributes,
    -    opt_content) {
    -  var html = goog.html.SafeHtml.create(tagName, opt_attributes, opt_content);
    -  html.dir_ = dir;
    -  return html;
    -};
    -
    -
    -/**
    - * Creates a new SafeHtml object by concatenating values.
    - * @param {...(!goog.html.SafeHtml.TextOrHtml_|
    - *     !Array<!goog.html.SafeHtml.TextOrHtml_>)} var_args Values to concatenate.
    - * @return {!goog.html.SafeHtml}
    - */
    -goog.html.SafeHtml.concat = function(var_args) {
    -  var dir = goog.i18n.bidi.Dir.NEUTRAL;
    -  var content = '';
    -
    -  /**
    -   * @param {!goog.html.SafeHtml.TextOrHtml_|
    -   *     !Array<!goog.html.SafeHtml.TextOrHtml_>} argument
    -   */
    -  var addArgument = function(argument) {
    -    if (goog.isArray(argument)) {
    -      goog.array.forEach(argument, addArgument);
    -    } else {
    -      var html = goog.html.SafeHtml.htmlEscape(argument);
    -      content += goog.html.SafeHtml.unwrap(html);
    -      var htmlDir = html.getDirection();
    -      if (dir == goog.i18n.bidi.Dir.NEUTRAL) {
    -        dir = htmlDir;
    -      } else if (htmlDir != goog.i18n.bidi.Dir.NEUTRAL && dir != htmlDir) {
    -        dir = null;
    -      }
    -    }
    -  };
    -
    -  goog.array.forEach(arguments, addArgument);
    -  return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(
    -      content, dir);
    -};
    -
    -
    -/**
    - * Creates a new SafeHtml object with known directionality by concatenating the
    - * values.
    - * @param {!goog.i18n.bidi.Dir} dir Directionality.
    - * @param {...(!goog.html.SafeHtml.TextOrHtml_|
    - *     !Array<!goog.html.SafeHtml.TextOrHtml_>)} var_args Elements of array
    - *     arguments would be processed recursively.
    - * @return {!goog.html.SafeHtml}
    - */
    -goog.html.SafeHtml.concatWithDir = function(dir, var_args) {
    -  var html = goog.html.SafeHtml.concat(goog.array.slice(arguments, 1));
    -  html.dir_ = dir;
    -  return html;
    -};
    -
    -
    -/**
    - * Type marker for the SafeHtml type, used to implement additional run-time
    - * type checking.
    - * @const
    - * @private
    - */
    -goog.html.SafeHtml.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {};
    -
    -
    -/**
    - * Package-internal utility method to create SafeHtml instances.
    - *
    - * @param {string} html The string to initialize the SafeHtml object with.
    - * @param {?goog.i18n.bidi.Dir} dir The directionality of the SafeHtml to be
    - *     constructed, or null if unknown.
    - * @return {!goog.html.SafeHtml} The initialized SafeHtml object.
    - * @package
    - */
    -goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse = function(
    -    html, dir) {
    -  return new goog.html.SafeHtml().initSecurityPrivateDoNotAccessOrElse_(
    -      html, dir);
    -};
    -
    -
    -/**
    - * Called from createSafeHtmlSecurityPrivateDoNotAccessOrElse(). This
    - * method exists only so that the compiler can dead code eliminate static
    - * fields (like EMPTY) when they're not accessed.
    - * @param {string} html
    - * @param {?goog.i18n.bidi.Dir} dir
    - * @return {!goog.html.SafeHtml}
    - * @private
    - */
    -goog.html.SafeHtml.prototype.initSecurityPrivateDoNotAccessOrElse_ = function(
    -    html, dir) {
    -  this.privateDoNotAccessOrElseSafeHtmlWrappedValue_ = html;
    -  this.dir_ = dir;
    -  return this;
    -};
    -
    -
    -/**
    - * Like create() but does not restrict which tags can be constructed.
    - *
    - * @param {string} tagName Tag name. Set or validated by caller.
    - * @param {!Object<string, goog.html.SafeHtml.AttributeValue_>=} opt_attributes
    - * @param {(!goog.html.SafeHtml.TextOrHtml_|
    - *     !Array<!goog.html.SafeHtml.TextOrHtml_>)=} opt_content
    - * @return {!goog.html.SafeHtml}
    - * @throws {Error} If invalid or unsafe attribute name or value is provided.
    - * @throws {goog.asserts.AssertionError} If content for void tag is provided.
    - * @package
    - */
    -goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse =
    -    function(tagName, opt_attributes, opt_content) {
    -  var dir = null;
    -  var result = '<' + tagName;
    -
    -  if (opt_attributes) {
    -    for (var name in opt_attributes) {
    -      if (!goog.html.SafeHtml.VALID_NAMES_IN_TAG_.test(name)) {
    -        throw Error('Invalid attribute name "' + name + '".');
    -      }
    -      var value = opt_attributes[name];
    -      if (!goog.isDefAndNotNull(value)) {
    -        continue;
    -      }
    -      result += ' ' +
    -          goog.html.SafeHtml.getAttrNameAndValue_(tagName, name, value);
    -    }
    -  }
    -
    -  var content = opt_content;
    -  if (!goog.isDef(content)) {
    -    content = [];
    -  } else if (!goog.isArray(content)) {
    -    content = [content];
    -  }
    -
    -  if (goog.dom.tags.isVoidTag(tagName.toLowerCase())) {
    -    goog.asserts.assert(!content.length,
    -        'Void tag <' + tagName + '> does not allow content.');
    -    result += '>';
    -  } else {
    -    var html = goog.html.SafeHtml.concat(content);
    -    result += '>' + goog.html.SafeHtml.unwrap(html) + '</' + tagName + '>';
    -    dir = html.getDirection();
    -  }
    -
    -  var dirAttribute = opt_attributes && opt_attributes['dir'];
    -  if (dirAttribute) {
    -    if (/^(ltr|rtl|auto)$/i.test(dirAttribute)) {
    -      // If the tag has the "dir" attribute specified then its direction is
    -      // neutral because it can be safely used in any context.
    -      dir = goog.i18n.bidi.Dir.NEUTRAL;
    -    } else {
    -      dir = null;
    -    }
    -  }
    -
    -  return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(
    -      result, dir);
    -};
    -
    -
    -/**
    - * @param {!Object<string, string>} fixedAttributes
    - * @param {!Object<string, string>} defaultAttributes
    - * @param {!Object<string, goog.html.SafeHtml.AttributeValue_>=}
    - *     opt_attributes Optional attributes passed to create*().
    - * @return {!Object<string, goog.html.SafeHtml.AttributeValue_>}
    - * @throws {Error} If opt_attributes contains an attribute with the same name
    - *     as an attribute in fixedAttributes.
    - * @package
    - */
    -goog.html.SafeHtml.combineAttributes = function(
    -    fixedAttributes, defaultAttributes, opt_attributes) {
    -  var combinedAttributes = {};
    -  var name;
    -
    -  for (name in fixedAttributes) {
    -    goog.asserts.assert(name.toLowerCase() == name, 'Must be lower case');
    -    combinedAttributes[name] = fixedAttributes[name];
    -  }
    -  for (name in defaultAttributes) {
    -    goog.asserts.assert(name.toLowerCase() == name, 'Must be lower case');
    -    combinedAttributes[name] = defaultAttributes[name];
    -  }
    -
    -  for (name in opt_attributes) {
    -    var nameLower = name.toLowerCase();
    -    if (nameLower in fixedAttributes) {
    -      throw Error('Cannot override "' + nameLower + '" attribute, got "' +
    -          name + '" with value "' + opt_attributes[name] + '"');
    -    }
    -    if (nameLower in defaultAttributes) {
    -      delete combinedAttributes[nameLower];
    -    }
    -    combinedAttributes[name] = opt_attributes[name];
    -  }
    -
    -  return combinedAttributes;
    -};
    -
    -
    -/**
    - * A SafeHtml instance corresponding to the empty string.
    - * @const {!goog.html.SafeHtml}
    - */
    -goog.html.SafeHtml.EMPTY =
    -    goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(
    -        '', goog.i18n.bidi.Dir.NEUTRAL);
    diff --git a/src/database/third_party/closure-library/closure/goog/html/safehtml_test.html b/src/database/third_party/closure-library/closure/goog/html/safehtml_test.html
    deleted file mode 100644
    index 9eeec19fc11..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/safehtml_test.html
    +++ /dev/null
    @@ -1,19 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.html</title>
    -<script src="../base.js"></script>
    -<script>
    -goog.require('goog.html.safeHtmlTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/html/safehtml_test.js b/src/database/third_party/closure-library/closure/goog/html/safehtml_test.js
    deleted file mode 100644
    index c3cadeb9366..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/safehtml_test.js
    +++ /dev/null
    @@ -1,387 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.html.SafeHtml and its builders.
    - */
    -
    -goog.provide('goog.html.safeHtmlTest');
    -
    -goog.require('goog.html.SafeHtml');
    -goog.require('goog.html.SafeStyle');
    -goog.require('goog.html.SafeStyleSheet');
    -goog.require('goog.html.SafeUrl');
    -goog.require('goog.html.TrustedResourceUrl');
    -goog.require('goog.html.testing');
    -goog.require('goog.i18n.bidi.Dir');
    -goog.require('goog.string.Const');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.html.safeHtmlTest');
    -
    -
    -
    -function testSafeHtml() {
    -  // TODO(user): Consider using SafeHtmlBuilder instead of newSafeHtmlForTest,
    -  // when available.
    -  var safeHtml = goog.html.testing.newSafeHtmlForTest('Hello <em>World</em>');
    -  assertSameHtml('Hello <em>World</em>', safeHtml);
    -  assertEquals('Hello <em>World</em>', goog.html.SafeHtml.unwrap(safeHtml));
    -  assertEquals('SafeHtml{Hello <em>World</em>}', String(safeHtml));
    -  assertNull(safeHtml.getDirection());
    -
    -  safeHtml = goog.html.testing.newSafeHtmlForTest(
    -      'World <em>Hello</em>', goog.i18n.bidi.Dir.RTL);
    -  assertSameHtml('World <em>Hello</em>', safeHtml);
    -  assertEquals('World <em>Hello</em>', goog.html.SafeHtml.unwrap(safeHtml));
    -  assertEquals('SafeHtml{World <em>Hello</em>}', String(safeHtml));
    -  assertEquals(goog.i18n.bidi.Dir.RTL, safeHtml.getDirection());
    -
    -  // Interface markers are present.
    -  assertTrue(safeHtml.implementsGoogStringTypedString);
    -  assertTrue(safeHtml.implementsGoogI18nBidiDirectionalString);
    -
    -  // Pre-defined constant.
    -  assertSameHtml('', goog.html.SafeHtml.EMPTY);
    -}
    -
    -
    -/** @suppress {checkTypes} */
    -function testUnwrap() {
    -  var evil = {};
    -  evil.safeHtmlValueWithSecurityContract__googHtmlSecurityPrivate_ =
    -      '<script>evil()</script';
    -  evil.SAFE_HTML_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {};
    -
    -  var exception = assertThrows(function() {
    -    goog.html.SafeHtml.unwrap(evil);
    -  });
    -  assertTrue(exception.message.indexOf('expected object of type SafeHtml') > 0);
    -}
    -
    -
    -function testHtmlEscape() {
    -  // goog.html.SafeHtml passes through unchanged.
    -  var safeHtmlIn = goog.html.SafeHtml.htmlEscape('<b>in</b>');
    -  assertTrue(safeHtmlIn === goog.html.SafeHtml.htmlEscape(safeHtmlIn));
    -
    -  // Plain strings are escaped.
    -  var safeHtml = goog.html.SafeHtml.htmlEscape('Hello <em>"\'&World</em>');
    -  assertSameHtml('Hello &lt;em&gt;&quot;&#39;&amp;World&lt;/em&gt;', safeHtml);
    -  assertEquals('SafeHtml{Hello &lt;em&gt;&quot;&#39;&amp;World&lt;/em&gt;}',
    -      String(safeHtml));
    -
    -  // Creating from a SafeUrl escapes and retains the known direction (which is
    -  // fixed to RTL for URLs).
    -  var safeUrl = goog.html.SafeUrl.fromConstant(
    -      goog.string.Const.from('http://example.com/?foo&bar'));
    -  var escapedUrl = goog.html.SafeHtml.htmlEscape(safeUrl);
    -  assertSameHtml('http://example.com/?foo&amp;bar', escapedUrl);
    -  assertEquals(goog.i18n.bidi.Dir.LTR, escapedUrl.getDirection());
    -
    -  // Creating SafeHtml from a goog.string.Const escapes as well (i.e., the
    -  // value is treated like any other string). To create HTML markup from
    -  // program literals, SafeHtmlBuilder should be used.
    -  assertSameHtml('this &amp; that',
    -      goog.html.SafeHtml.htmlEscape(goog.string.Const.from('this & that')));
    -}
    -
    -
    -function testSafeHtmlCreate() {
    -  var br = goog.html.SafeHtml.create('br');
    -
    -  assertSameHtml('<br>', br);
    -
    -  assertSameHtml('<span title="&quot;"></span>',
    -      goog.html.SafeHtml.create('span', {'title': '"'}));
    -
    -  assertSameHtml('<span>&lt;</span>',
    -      goog.html.SafeHtml.create('span', {}, '<'));
    -
    -  assertSameHtml('<span><br></span>',
    -      goog.html.SafeHtml.create('span', {}, br));
    -
    -  assertSameHtml('<span></span>', goog.html.SafeHtml.create('span', {}, []));
    -
    -  assertSameHtml('<span></span>',
    -      goog.html.SafeHtml.create('span', {'title': null, 'class': undefined}));
    -
    -  assertSameHtml('<span>x<br>y</span>',
    -      goog.html.SafeHtml.create('span', {}, ['x', br, 'y']));
    -
    -  assertSameHtml('<table border="0"></table>',
    -      goog.html.SafeHtml.create('table', {'border': 0}));
    -
    -  var onclick = goog.string.Const.from('alert(/"/)');
    -  assertSameHtml('<span onclick="alert(/&quot;/)"></span>',
    -      goog.html.SafeHtml.create('span', {'onclick': onclick}));
    -
    -  var href = goog.html.testing.newSafeUrlForTest('?a&b');
    -  assertSameHtml('<a href="?a&amp;b"></a>',
    -      goog.html.SafeHtml.create('a', {'href': href}));
    -
    -  var style = goog.html.testing.newSafeStyleForTest('border: /* " */ 0;');
    -  assertSameHtml('<hr style="border: /* &quot; */ 0;">',
    -      goog.html.SafeHtml.create('hr', {'style': style}));
    -
    -  assertEquals(goog.i18n.bidi.Dir.NEUTRAL,
    -      goog.html.SafeHtml.create('span').getDirection());
    -  assertNull(goog.html.SafeHtml.create('span', {'dir': 'x'}).getDirection());
    -  assertEquals(goog.i18n.bidi.Dir.NEUTRAL,
    -      goog.html.SafeHtml.create('span', {'dir': 'ltr'}, 'a').getDirection());
    -
    -  assertThrows(function() {
    -    goog.html.SafeHtml.create('script');
    -  });
    -
    -  assertThrows(function() {
    -    goog.html.SafeHtml.create('br', {}, 'x');
    -  });
    -
    -  assertThrows(function() {
    -    goog.html.SafeHtml.create('img', {'onerror': ''});
    -  });
    -
    -  assertThrows(function() {
    -    goog.html.SafeHtml.create('img', {'OnError': ''});
    -  });
    -
    -  assertThrows(function() {
    -    goog.html.SafeHtml.create('a', {'href': 'javascript:alert(1)'});
    -  });
    -
    -  assertThrows(function() {
    -    goog.html.SafeHtml.create('a href=""');
    -  });
    -
    -  assertThrows(function() {
    -    goog.html.SafeHtml.create('a', {'title="" href': ''});
    -  });
    -}
    -
    -
    -function testSafeHtmlCreate_styleAttribute() {
    -  var style = 'color:red;';
    -  var expected = '<hr style="' + style + '">';
    -  assertThrows(function() {
    -    goog.html.SafeHtml.create('hr', {'style': style});
    -  });
    -  assertSameHtml(expected, goog.html.SafeHtml.create('hr', {
    -    'style': goog.html.SafeStyle.fromConstant(goog.string.Const.from(style))
    -  }));
    -  assertSameHtml(expected, goog.html.SafeHtml.create('hr', {
    -    'style': {'color': 'red'}
    -  }));
    -}
    -
    -
    -function testSafeHtmlCreate_urlAttributes() {
    -  // TrustedResourceUrl is allowed.
    -  var trustedResourceUrl = goog.html.TrustedResourceUrl.fromConstant(
    -      goog.string.Const.from('https://google.com/trusted'));
    -  assertSameHtml(
    -      '<img src="https://google.com/trusted">',
    -      goog.html.SafeHtml.create('img', {'src': trustedResourceUrl}));
    -  // SafeUrl is allowed.
    -  var safeUrl = goog.html.SafeUrl.sanitize('https://google.com/safe');
    -  assertSameHtml(
    -      '<imG src="https://google.com/safe">',
    -      goog.html.SafeHtml.create('imG', {'src': safeUrl}));
    -  // Const is allowed.
    -  var constUrl = goog.string.Const.from('https://google.com/const');
    -  assertSameHtml(
    -      '<a href="https://google.com/const"></a>',
    -      goog.html.SafeHtml.create('a', {'href': constUrl}));
    -
    -  // string is not allowed.
    -  assertThrows(function() {
    -    goog.html.SafeHtml.create('imG', {'src': 'https://google.com'});
    -  });
    -}
    -
    -
    -function testSafeHtmlCreateIframe() {
    -  // Setting src and srcdoc.
    -  var url = goog.html.TrustedResourceUrl.fromConstant(
    -      goog.string.Const.from('https://google.com/trusted<'));
    -  assertSameHtml(
    -      '<iframe src="https://google.com/trusted&lt;"></iframe>',
    -      goog.html.SafeHtml.createIframe(url, null, {'sandbox': null}));
    -  var srcdoc = goog.html.SafeHtml.create('br');
    -  assertSameHtml(
    -      '<iframe srcdoc="&lt;br&gt;"></iframe>',
    -      goog.html.SafeHtml.createIframe(null, srcdoc, {'sandbox': null}));
    -
    -  // sandbox default and overriding it.
    -  assertSameHtml(
    -      '<iframe sandbox=""></iframe>',
    -      goog.html.SafeHtml.createIframe());
    -  assertSameHtml(
    -      '<iframe Sandbox="allow-same-origin allow-top-navigation"></iframe>',
    -      goog.html.SafeHtml.createIframe(
    -          null, null, {'Sandbox': 'allow-same-origin allow-top-navigation'}));
    -
    -  // Cannot override src and srddoc.
    -  assertThrows(function() {
    -    goog.html.SafeHtml.createIframe(null, null, {'Src': url});
    -  });
    -  assertThrows(function() {
    -    goog.html.SafeHtml.createIframe(null, null, {'Srcdoc': url});
    -  });
    -
    -  // Can set content.
    -  assertSameHtml(
    -      '<iframe>&lt;</iframe>',
    -      goog.html.SafeHtml.createIframe(null, null, {'sandbox': null}, '<'));
    -}
    -
    -
    -function testSafeHtmlCreateStyle() {
    -  var styleSheet = goog.html.SafeStyleSheet.fromConstant(
    -      goog.string.Const.from('P.special { color:"red" ; }'));
    -  var styleHtml = goog.html.SafeHtml.createStyle(styleSheet);
    -  assertSameHtml(
    -      '<style type="text/css">P.special { color:"red" ; }</style>', styleHtml);
    -
    -  // Two stylesheets.
    -  var otherStyleSheet = goog.html.SafeStyleSheet.fromConstant(
    -      goog.string.Const.from('P.regular { color:blue ; }'));
    -  styleHtml = goog.html.SafeHtml.createStyle([styleSheet, otherStyleSheet]);
    -  assertSameHtml(
    -      '<style type="text/css">P.special { color:"red" ; }' +
    -          'P.regular { color:blue ; }</style>',
    -      styleHtml);
    -
    -  // Set attribute.
    -  styleHtml = goog.html.SafeHtml.createStyle(styleSheet, {'id': 'test'});
    -  var styleHtmlString = goog.html.SafeHtml.unwrap(styleHtml);
    -  assertTrue(styleHtmlString, styleHtmlString.indexOf('id="test"') != -1);
    -  assertTrue(styleHtmlString, styleHtmlString.indexOf('type="text/css"') != -1);
    -
    -  // Set attribute to null.
    -  styleHtml = goog.html.SafeHtml.createStyle(
    -      goog.html.SafeStyleSheet.EMPTY, {'id': null});
    -  assertSameHtml('<style type="text/css"></style>', styleHtml);
    -
    -  // Set attribute to invalid value.
    -  assertThrows(function() {
    -    styleHtml = goog.html.SafeHtml.createStyle(
    -        goog.html.SafeStyleSheet.EMPTY, {'invalid.': 'cantdothis'});
    -  });
    -
    -  // Cannot override type attribute.
    -  assertThrows(function() {
    -    styleHtml = goog.html.SafeHtml.createStyle(
    -        goog.html.SafeStyleSheet.EMPTY, {'Type': 'cantdothis'});
    -  });
    -
    -  // Directionality.
    -  assertEquals(goog.i18n.bidi.Dir.NEUTRAL, styleHtml.getDirection());
    -}
    -
    -
    -function testSafeHtmlCreateWithDir() {
    -  var ltr = goog.i18n.bidi.Dir.LTR;
    -
    -  assertEquals(ltr, goog.html.SafeHtml.createWithDir(ltr, 'br').getDirection());
    -}
    -
    -
    -function testSafeHtmlConcat() {
    -  var br = goog.html.testing.newSafeHtmlForTest('<br>');
    -
    -  var html = goog.html.SafeHtml.htmlEscape('Hello');
    -  assertSameHtml('Hello<br>', goog.html.SafeHtml.concat(html, br));
    -
    -  assertSameHtml('', goog.html.SafeHtml.concat());
    -  assertSameHtml('', goog.html.SafeHtml.concat([]));
    -
    -  assertSameHtml('a<br>c', goog.html.SafeHtml.concat('a', br, 'c'));
    -  assertSameHtml('a<br>c', goog.html.SafeHtml.concat(['a', br, 'c']));
    -  assertSameHtml('a<br>c', goog.html.SafeHtml.concat('a', [br, 'c']));
    -  assertSameHtml('a<br>c', goog.html.SafeHtml.concat(['a'], br, ['c']));
    -
    -  var ltr = goog.html.testing.newSafeHtmlForTest('', goog.i18n.bidi.Dir.LTR);
    -  var rtl = goog.html.testing.newSafeHtmlForTest('', goog.i18n.bidi.Dir.RTL);
    -  var neutral = goog.html.testing.newSafeHtmlForTest('',
    -      goog.i18n.bidi.Dir.NEUTRAL);
    -  var unknown = goog.html.testing.newSafeHtmlForTest('');
    -  assertEquals(goog.i18n.bidi.Dir.NEUTRAL,
    -      goog.html.SafeHtml.concat().getDirection());
    -  assertEquals(goog.i18n.bidi.Dir.LTR,
    -      goog.html.SafeHtml.concat(ltr, ltr).getDirection());
    -  assertEquals(goog.i18n.bidi.Dir.LTR,
    -      goog.html.SafeHtml.concat(ltr, neutral, ltr).getDirection());
    -  assertNull(goog.html.SafeHtml.concat(ltr, unknown).getDirection());
    -  assertNull(goog.html.SafeHtml.concat(ltr, rtl).getDirection());
    -  assertNull(goog.html.SafeHtml.concat(ltr, [rtl]).getDirection());
    -}
    -
    -
    -function testHtmlEscapePreservingNewlines() {
    -  // goog.html.SafeHtml passes through unchanged.
    -  var safeHtmlIn = goog.html.SafeHtml.htmlEscapePreservingNewlines('<b>in</b>');
    -  assertTrue(safeHtmlIn ===
    -      goog.html.SafeHtml.htmlEscapePreservingNewlines(safeHtmlIn));
    -
    -  assertSameHtml('a<br>c',
    -      goog.html.SafeHtml.htmlEscapePreservingNewlines('a\nc'));
    -  assertSameHtml('&lt;<br>',
    -      goog.html.SafeHtml.htmlEscapePreservingNewlines('<\n'));
    -  assertSameHtml('<br>',
    -      goog.html.SafeHtml.htmlEscapePreservingNewlines('\r\n'));
    -  assertSameHtml('<br>', goog.html.SafeHtml.htmlEscapePreservingNewlines('\r'));
    -  assertSameHtml('', goog.html.SafeHtml.htmlEscapePreservingNewlines(''));
    -}
    -
    -
    -function testHtmlEscapePreservingNewlinesAndSpaces() {
    -  // goog.html.SafeHtml passes through unchanged.
    -  var safeHtmlIn = goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(
    -      '<b>in</b>');
    -  assertTrue(safeHtmlIn ===
    -      goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(safeHtmlIn));
    -
    -  assertSameHtml('a<br>c',
    -      goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces('a\nc'));
    -  assertSameHtml('&lt;<br>',
    -      goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces('<\n'));
    -  assertSameHtml(
    -      '<br>', goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces('\r\n'));
    -  assertSameHtml(
    -      '<br>', goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces('\r'));
    -  assertSameHtml(
    -      '', goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(''));
    -
    -  assertSameHtml('a &#160;b',
    -      goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces('a  b'));
    -}
    -
    -
    -function testSafeHtmlConcatWithDir() {
    -  var ltr = goog.i18n.bidi.Dir.LTR;
    -  var rtl = goog.i18n.bidi.Dir.RTL;
    -  var br = goog.html.testing.newSafeHtmlForTest('<br>');
    -
    -  assertEquals(ltr, goog.html.SafeHtml.concatWithDir(ltr).getDirection());
    -  assertEquals(ltr, goog.html.SafeHtml.concatWithDir(ltr,
    -      goog.html.testing.newSafeHtmlForTest('', rtl)).getDirection());
    -
    -  assertSameHtml('a<br>c', goog.html.SafeHtml.concatWithDir(ltr, 'a', br, 'c'));
    -}
    -
    -
    -function assertSameHtml(expected, html) {
    -  assertEquals(expected, goog.html.SafeHtml.unwrap(html));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/html/safescript.js b/src/database/third_party/closure-library/closure/goog/html/safescript.js
    deleted file mode 100644
    index 83995aa02f9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/safescript.js
    +++ /dev/null
    @@ -1,234 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview The SafeScript type and its builders.
    - *
    - * TODO(user): Link to document stating type contract.
    - */
    -
    -goog.provide('goog.html.SafeScript');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.string.Const');
    -goog.require('goog.string.TypedString');
    -
    -
    -
    -/**
    - * A string-like object which represents JavaScript code and that carries the
    - * security type contract that its value, as a string, will not cause execution
    - * of unconstrained attacker controlled code (XSS) when evaluated as JavaScript
    - * in a browser.
    - *
    - * Instances of this type must be created via the factory method
    - * {@code goog.html.SafeScript.fromConstant} and not by invoking its
    - * constructor. The constructor intentionally takes no parameters and the type
    - * is immutable; hence only a default instance corresponding to the empty string
    - * can be obtained via constructor invocation.
    - *
    - * A SafeScript's string representation can safely be interpolated as the
    - * content of a script element within HTML. The SafeScript string should not be
    - * escaped before interpolation.
    - *
    - * Note that the SafeScript might contain text that is attacker-controlled but
    - * that text should have been interpolated with appropriate escaping,
    - * sanitization and/or validation into the right location in the script, such
    - * that it is highly constrained in its effect (for example, it had to match a
    - * set of whitelisted words).
    - *
    - * A SafeScript can be constructed via security-reviewed unchecked
    - * conversions. In this case producers of SafeScript must ensure themselves that
    - * the SafeScript does not contain unsafe script. Note in particular that
    - * {@code &lt;} is dangerous, even when inside JavaScript strings, and so should
    - * always be forbidden or JavaScript escaped in user controlled input. For
    - * example, if {@code &lt;/script&gt;&lt;script&gt;evil&lt;/script&gt;"} were
    - * interpolated inside a JavaScript string, it would break out of the context
    - * of the original script element and {@code evil} would execute. Also note
    - * that within an HTML script (raw text) element, HTML character references,
    - * such as "&lt;" are not allowed. See
    - * http://www.w3.org/TR/html5/scripting-1.html#restrictions-for-contents-of-script-elements.
    - *
    - * @see goog.html.SafeScript#fromConstant
    - * @constructor
    - * @final
    - * @struct
    - * @implements {goog.string.TypedString}
    - */
    -goog.html.SafeScript = function() {
    -  /**
    -   * The contained value of this SafeScript.  The field has a purposely
    -   * ugly name to make (non-compiled) code that attempts to directly access this
    -   * field stand out.
    -   * @private {string}
    -   */
    -  this.privateDoNotAccessOrElseSafeScriptWrappedValue_ = '';
    -
    -  /**
    -   * A type marker used to implement additional run-time type checking.
    -   * @see goog.html.SafeScript#unwrap
    -   * @const
    -   * @private
    -   */
    -  this.SAFE_SCRIPT_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ =
    -      goog.html.SafeScript.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_;
    -};
    -
    -
    -/**
    - * @override
    - * @const
    - */
    -goog.html.SafeScript.prototype.implementsGoogStringTypedString = true;
    -
    -
    -/**
    - * Type marker for the SafeScript type, used to implement additional
    - * run-time type checking.
    - * @const
    - * @private
    - */
    -goog.html.SafeScript.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {};
    -
    -
    -/**
    - * Creates a SafeScript object from a compile-time constant string.
    - *
    - * @param {!goog.string.Const} script A compile-time-constant string from which
    - *     to create a SafeScript.
    - * @return {!goog.html.SafeScript} A SafeScript object initialized to
    - *     {@code script}.
    - */
    -goog.html.SafeScript.fromConstant = function(script) {
    -  var scriptString = goog.string.Const.unwrap(script);
    -  if (scriptString.length === 0) {
    -    return goog.html.SafeScript.EMPTY;
    -  }
    -  return goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse(
    -      scriptString);
    -};
    -
    -
    -/**
    - * Returns this SafeScript's value as a string.
    - *
    - * IMPORTANT: In code where it is security relevant that an object's type is
    - * indeed {@code SafeScript}, use {@code goog.html.SafeScript.unwrap} instead of
    - * this method. If in doubt, assume that it's security relevant. In particular,
    - * note that goog.html functions which return a goog.html type do not guarantee
    - * the returned instance is of the right type. For example:
    - *
    - * <pre>
    - * var fakeSafeHtml = new String('fake');
    - * fakeSafeHtml.__proto__ = goog.html.SafeHtml.prototype;
    - * var newSafeHtml = goog.html.SafeHtml.htmlEscape(fakeSafeHtml);
    - * // newSafeHtml is just an alias for fakeSafeHtml, it's passed through by
    - * // goog.html.SafeHtml.htmlEscape() as fakeSafeHtml
    - * // instanceof goog.html.SafeHtml.
    - * </pre>
    - *
    - * @see goog.html.SafeScript#unwrap
    - * @override
    - */
    -goog.html.SafeScript.prototype.getTypedStringValue = function() {
    -  return this.privateDoNotAccessOrElseSafeScriptWrappedValue_;
    -};
    -
    -
    -if (goog.DEBUG) {
    -  /**
    -   * Returns a debug string-representation of this value.
    -   *
    -   * To obtain the actual string value wrapped in a SafeScript, use
    -   * {@code goog.html.SafeScript.unwrap}.
    -   *
    -   * @see goog.html.SafeScript#unwrap
    -   * @override
    -   */
    -  goog.html.SafeScript.prototype.toString = function() {
    -    return 'SafeScript{' +
    -        this.privateDoNotAccessOrElseSafeScriptWrappedValue_ + '}';
    -  };
    -}
    -
    -
    -/**
    - * Performs a runtime check that the provided object is indeed a
    - * SafeScript object, and returns its value.
    - *
    - * @param {!goog.html.SafeScript} safeScript The object to extract from.
    - * @return {string} The safeScript object's contained string, unless
    - *     the run-time type check fails. In that case, {@code unwrap} returns an
    - *     innocuous string, or, if assertions are enabled, throws
    - *     {@code goog.asserts.AssertionError}.
    - */
    -goog.html.SafeScript.unwrap = function(safeScript) {
    -  // Perform additional Run-time type-checking to ensure that
    -  // safeScript is indeed an instance of the expected type.  This
    -  // provides some additional protection against security bugs due to
    -  // application code that disables type checks.
    -  // Specifically, the following checks are performed:
    -  // 1. The object is an instance of the expected type.
    -  // 2. The object is not an instance of a subclass.
    -  // 3. The object carries a type marker for the expected type. "Faking" an
    -  // object requires a reference to the type marker, which has names intended
    -  // to stand out in code reviews.
    -  if (safeScript instanceof goog.html.SafeScript &&
    -      safeScript.constructor === goog.html.SafeScript &&
    -      safeScript.SAFE_SCRIPT_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ ===
    -          goog.html.SafeScript.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_) {
    -    return safeScript.privateDoNotAccessOrElseSafeScriptWrappedValue_;
    -  } else {
    -    goog.asserts.fail(
    -        'expected object of type SafeScript, got \'' + safeScript + '\'');
    -    return 'type_error:SafeScript';
    -  }
    -};
    -
    -
    -/**
    - * Package-internal utility method to create SafeScript instances.
    - *
    - * @param {string} script The string to initialize the SafeScript object with.
    - * @return {!goog.html.SafeScript} The initialized SafeScript object.
    - * @package
    - */
    -goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse =
    -    function(script) {
    -  return new goog.html.SafeScript().initSecurityPrivateDoNotAccessOrElse_(
    -      script);
    -};
    -
    -
    -/**
    - * Called from createSafeScriptSecurityPrivateDoNotAccessOrElse(). This
    - * method exists only so that the compiler can dead code eliminate static
    - * fields (like EMPTY) when they're not accessed.
    - * @param {string} script
    - * @return {!goog.html.SafeScript}
    - * @private
    - */
    -goog.html.SafeScript.prototype.initSecurityPrivateDoNotAccessOrElse_ = function(
    -    script) {
    -  this.privateDoNotAccessOrElseSafeScriptWrappedValue_ = script;
    -  return this;
    -};
    -
    -
    -/**
    - * A SafeScript instance corresponding to the empty string.
    - * @const {!goog.html.SafeScript}
    - */
    -goog.html.SafeScript.EMPTY =
    -    goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse('');
    diff --git a/src/database/third_party/closure-library/closure/goog/html/safescript_test.html b/src/database/third_party/closure-library/closure/goog/html/safescript_test.html
    deleted file mode 100644
    index f8a7df60b22..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/safescript_test.html
    +++ /dev/null
    @@ -1,19 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.html</title>
    -<script src="../base.js"></script>
    -<script>
    -goog.require('goog.html.safeScriptTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/html/safescript_test.js b/src/database/third_party/closure-library/closure/goog/html/safescript_test.js
    deleted file mode 100644
    index 0441aa62f76..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/safescript_test.js
    +++ /dev/null
    @@ -1,66 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.html.SafeScript and its builders.
    - */
    -
    -goog.provide('goog.html.safeScriptTest');
    -
    -goog.require('goog.html.SafeScript');
    -goog.require('goog.string.Const');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.html.safeScriptTest');
    -
    -
    -function testSafeScript() {
    -  var script = 'var string = \'hello\';';
    -  var safeScript =
    -      goog.html.SafeScript.fromConstant(goog.string.Const.from(script));
    -  var extracted = goog.html.SafeScript.unwrap(safeScript);
    -  assertEquals(script, extracted);
    -  assertEquals(script, safeScript.getTypedStringValue());
    -  assertEquals('SafeScript{' + script + '}', String(safeScript));
    -
    -  // Interface marker is present.
    -  assertTrue(safeScript.implementsGoogStringTypedString);
    -}
    -
    -
    -/** @suppress {checkTypes} */
    -function testUnwrap() {
    -  var evil = {};
    -  evil.safeScriptValueWithSecurityContract__googHtmlSecurityPrivate_ =
    -      'var string = \'evil\';';
    -  evil.SAFE_STYLE_TYPE_MARKER__GOOG_HTML_SECURITY_PRIVATE_ = {};
    -
    -  var exception = assertThrows(function() {
    -    goog.html.SafeScript.unwrap(evil);
    -  });
    -  assertTrue(
    -      exception.message.indexOf('expected object of type SafeScript') > 0);
    -}
    -
    -
    -function testFromConstant_allowsEmptyString() {
    -  assertEquals(
    -      goog.html.SafeScript.EMPTY,
    -      goog.html.SafeScript.fromConstant(goog.string.Const.from('')));
    -}
    -
    -
    -function testEmpty() {
    -  assertEquals('', goog.html.SafeScript.unwrap(goog.html.SafeScript.EMPTY));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/html/safestyle.js b/src/database/third_party/closure-library/closure/goog/html/safestyle.js
    deleted file mode 100644
    index 2f9f2881c4e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/safestyle.js
    +++ /dev/null
    @@ -1,442 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview The SafeStyle type and its builders.
    - *
    - * TODO(user): Link to document stating type contract.
    - */
    -
    -goog.provide('goog.html.SafeStyle');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.string');
    -goog.require('goog.string.Const');
    -goog.require('goog.string.TypedString');
    -
    -
    -
    -/**
    - * A string-like object which represents a sequence of CSS declarations
    - * ({@code propertyName1: propertyvalue1; propertyName2: propertyValue2; ...})
    - * and that carries the security type contract that its value, as a string,
    - * will not cause untrusted script execution (XSS) when evaluated as CSS in a
    - * browser.
    - *
    - * Instances of this type must be created via the factory methods
    - * ({@code goog.html.SafeStyle.create} or
    - * {@code goog.html.SafeStyle.fromConstant}) and not by invoking its
    - * constructor. The constructor intentionally takes no parameters and the type
    - * is immutable; hence only a default instance corresponding to the empty string
    - * can be obtained via constructor invocation.
    - *
    - * A SafeStyle's string representation ({@link #getSafeStyleString()}) can
    - * safely:
    - * <ul>
    - *   <li>Be interpolated as the entire content of a *quoted* HTML style
    - *       attribute, or before already existing properties. The SafeStyle string
    - *       *must be HTML-attribute-escaped* (where " and ' are escaped) before
    - *       interpolation.
    - *   <li>Be interpolated as the entire content of a {}-wrapped block within a
    - *       stylesheet, or before already existing properties. The SafeStyle string
    - *       should not be escaped before interpolation. SafeStyle's contract also
    - *       guarantees that the string will not be able to introduce new properties
    - *       or elide existing ones.
    - *   <li>Be assigned to the style property of a DOM node. The SafeStyle string
    - *       should not be escaped before being assigned to the property.
    - * </ul>
    - *
    - * A SafeStyle may never contain literal angle brackets. Otherwise, it could
    - * be unsafe to place a SafeStyle into a &lt;style&gt; tag (where it can't
    - * be HTML escaped). For example, if the SafeStyle containing
    - * "{@code font: 'foo &lt;style/&gt;&lt;script&gt;evil&lt;/script&gt;'}" were
    - * interpolated within a &lt;style&gt; tag, this would then break out of the
    - * style context into HTML.
    - *
    - * A SafeStyle may contain literal single or double quotes, and as such the
    - * entire style string must be escaped when used in a style attribute (if
    - * this were not the case, the string could contain a matching quote that
    - * would escape from the style attribute).
    - *
    - * Values of this type must be composable, i.e. for any two values
    - * {@code style1} and {@code style2} of this type,
    - * {@code goog.html.SafeStyle.unwrap(style1) +
    - * goog.html.SafeStyle.unwrap(style2)} must itself be a value that satisfies
    - * the SafeStyle type constraint. This requirement implies that for any value
    - * {@code style} of this type, {@code goog.html.SafeStyle.unwrap(style)} must
    - * not end in a "property value" or "property name" context. For example,
    - * a value of {@code background:url("} or {@code font-} would not satisfy the
    - * SafeStyle contract. This is because concatenating such strings with a
    - * second value that itself does not contain unsafe CSS can result in an
    - * overall string that does. For example, if {@code javascript:evil())"} is
    - * appended to {@code background:url("}, the resulting string may result in
    - * the execution of a malicious script.
    - *
    - * TODO(user): Consider whether we should implement UTF-8 interchange
    - * validity checks and blacklisting of newlines (including Unicode ones) and
    - * other whitespace characters (\t, \f). Document here if so and also update
    - * SafeStyle.fromConstant().
    - *
    - * The following example values comply with this type's contract:
    - * <ul>
    - *   <li><pre>width: 1em;</pre>
    - *   <li><pre>height:1em;</pre>
    - *   <li><pre>width: 1em;height: 1em;</pre>
    - *   <li><pre>background:url('http://url');</pre>
    - * </ul>
    - * In addition, the empty string is safe for use in a CSS attribute.
    - *
    - * The following example values do NOT comply with this type's contract:
    - * <ul>
    - *   <li><pre>background: red</pre> (missing a trailing semi-colon)
    - *   <li><pre>background:</pre> (missing a value and a trailing semi-colon)
    - *   <li><pre>1em</pre> (missing an attribute name, which provides context for
    - *       the value)
    - * </ul>
    - *
    - * @see goog.html.SafeStyle#create
    - * @see goog.html.SafeStyle#fromConstant
    - * @see http://www.w3.org/TR/css3-syntax/
    - * @constructor
    - * @final
    - * @struct
    - * @implements {goog.string.TypedString}
    - */
    -goog.html.SafeStyle = function() {
    -  /**
    -   * The contained value of this SafeStyle.  The field has a purposely
    -   * ugly name to make (non-compiled) code that attempts to directly access this
    -   * field stand out.
    -   * @private {string}
    -   */
    -  this.privateDoNotAccessOrElseSafeStyleWrappedValue_ = '';
    -
    -  /**
    -   * A type marker used to implement additional run-time type checking.
    -   * @see goog.html.SafeStyle#unwrap
    -   * @const
    -   * @private
    -   */
    -  this.SAFE_STYLE_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ =
    -      goog.html.SafeStyle.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_;
    -};
    -
    -
    -/**
    - * @override
    - * @const
    - */
    -goog.html.SafeStyle.prototype.implementsGoogStringTypedString = true;
    -
    -
    -/**
    - * Type marker for the SafeStyle type, used to implement additional
    - * run-time type checking.
    - * @const
    - * @private
    - */
    -goog.html.SafeStyle.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {};
    -
    -
    -/**
    - * Creates a SafeStyle object from a compile-time constant string.
    - *
    - * {@code style} should be in the format
    - * {@code name: value; [name: value; ...]} and must not have any < or >
    - * characters in it. This is so that SafeStyle's contract is preserved,
    - * allowing the SafeStyle to correctly be interpreted as a sequence of CSS
    - * declarations and without affecting the syntactic structure of any
    - * surrounding CSS and HTML.
    - *
    - * This method performs basic sanity checks on the format of {@code style}
    - * but does not constrain the format of {@code name} and {@code value}, except
    - * for disallowing tag characters.
    - *
    - * @param {!goog.string.Const} style A compile-time-constant string from which
    - *     to create a SafeStyle.
    - * @return {!goog.html.SafeStyle} A SafeStyle object initialized to
    - *     {@code style}.
    - */
    -goog.html.SafeStyle.fromConstant = function(style) {
    -  var styleString = goog.string.Const.unwrap(style);
    -  if (styleString.length === 0) {
    -    return goog.html.SafeStyle.EMPTY;
    -  }
    -  goog.html.SafeStyle.checkStyle_(styleString);
    -  goog.asserts.assert(goog.string.endsWith(styleString, ';'),
    -      'Last character of style string is not \';\': ' + styleString);
    -  goog.asserts.assert(goog.string.contains(styleString, ':'),
    -      'Style string must contain at least one \':\', to ' +
    -      'specify a "name: value" pair: ' + styleString);
    -  return goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(
    -      styleString);
    -};
    -
    -
    -/**
    - * Checks if the style definition is valid.
    - * @param {string} style
    - * @private
    - */
    -goog.html.SafeStyle.checkStyle_ = function(style) {
    -  goog.asserts.assert(!/[<>]/.test(style),
    -      'Forbidden characters in style string: ' + style);
    -};
    -
    -
    -/**
    - * Returns this SafeStyle's value as a string.
    - *
    - * IMPORTANT: In code where it is security relevant that an object's type is
    - * indeed {@code SafeStyle}, use {@code goog.html.SafeStyle.unwrap} instead of
    - * this method. If in doubt, assume that it's security relevant. In particular,
    - * note that goog.html functions which return a goog.html type do not guarantee
    - * the returned instance is of the right type. For example:
    - *
    - * <pre>
    - * var fakeSafeHtml = new String('fake');
    - * fakeSafeHtml.__proto__ = goog.html.SafeHtml.prototype;
    - * var newSafeHtml = goog.html.SafeHtml.htmlEscape(fakeSafeHtml);
    - * // newSafeHtml is just an alias for fakeSafeHtml, it's passed through by
    - * // goog.html.SafeHtml.htmlEscape() as fakeSafeHtml
    - * // instanceof goog.html.SafeHtml.
    - * </pre>
    - *
    - * @see goog.html.SafeStyle#unwrap
    - * @override
    - */
    -goog.html.SafeStyle.prototype.getTypedStringValue = function() {
    -  return this.privateDoNotAccessOrElseSafeStyleWrappedValue_;
    -};
    -
    -
    -if (goog.DEBUG) {
    -  /**
    -   * Returns a debug string-representation of this value.
    -   *
    -   * To obtain the actual string value wrapped in a SafeStyle, use
    -   * {@code goog.html.SafeStyle.unwrap}.
    -   *
    -   * @see goog.html.SafeStyle#unwrap
    -   * @override
    -   */
    -  goog.html.SafeStyle.prototype.toString = function() {
    -    return 'SafeStyle{' +
    -        this.privateDoNotAccessOrElseSafeStyleWrappedValue_ + '}';
    -  };
    -}
    -
    -
    -/**
    - * Performs a runtime check that the provided object is indeed a
    - * SafeStyle object, and returns its value.
    - *
    - * @param {!goog.html.SafeStyle} safeStyle The object to extract from.
    - * @return {string} The safeStyle object's contained string, unless
    - *     the run-time type check fails. In that case, {@code unwrap} returns an
    - *     innocuous string, or, if assertions are enabled, throws
    - *     {@code goog.asserts.AssertionError}.
    - */
    -goog.html.SafeStyle.unwrap = function(safeStyle) {
    -  // Perform additional Run-time type-checking to ensure that
    -  // safeStyle is indeed an instance of the expected type.  This
    -  // provides some additional protection against security bugs due to
    -  // application code that disables type checks.
    -  // Specifically, the following checks are performed:
    -  // 1. The object is an instance of the expected type.
    -  // 2. The object is not an instance of a subclass.
    -  // 3. The object carries a type marker for the expected type. "Faking" an
    -  // object requires a reference to the type marker, which has names intended
    -  // to stand out in code reviews.
    -  if (safeStyle instanceof goog.html.SafeStyle &&
    -      safeStyle.constructor === goog.html.SafeStyle &&
    -      safeStyle.SAFE_STYLE_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ ===
    -          goog.html.SafeStyle.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_) {
    -    return safeStyle.privateDoNotAccessOrElseSafeStyleWrappedValue_;
    -  } else {
    -    goog.asserts.fail(
    -        'expected object of type SafeStyle, got \'' + safeStyle + '\'');
    -    return 'type_error:SafeStyle';
    -  }
    -};
    -
    -
    -/**
    - * Package-internal utility method to create SafeStyle instances.
    - *
    - * @param {string} style The string to initialize the SafeStyle object with.
    - * @return {!goog.html.SafeStyle} The initialized SafeStyle object.
    - * @package
    - */
    -goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse =
    -    function(style) {
    -  return new goog.html.SafeStyle().initSecurityPrivateDoNotAccessOrElse_(style);
    -};
    -
    -
    -/**
    - * Called from createSafeStyleSecurityPrivateDoNotAccessOrElse(). This
    - * method exists only so that the compiler can dead code eliminate static
    - * fields (like EMPTY) when they're not accessed.
    - * @param {string} style
    - * @return {!goog.html.SafeStyle}
    - * @private
    - */
    -goog.html.SafeStyle.prototype.initSecurityPrivateDoNotAccessOrElse_ = function(
    -    style) {
    -  this.privateDoNotAccessOrElseSafeStyleWrappedValue_ = style;
    -  return this;
    -};
    -
    -
    -/**
    - * A SafeStyle instance corresponding to the empty string.
    - * @const {!goog.html.SafeStyle}
    - */
    -goog.html.SafeStyle.EMPTY =
    -    goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse('');
    -
    -
    -/**
    - * The innocuous string generated by goog.html.SafeUrl.create when passed
    - * an unsafe value.
    - * @const {string}
    - */
    -goog.html.SafeStyle.INNOCUOUS_STRING = 'zClosurez';
    -
    -
    -/**
    - * Mapping of property names to their values.
    - * @typedef {!Object<string, goog.string.Const|string>}
    - */
    -goog.html.SafeStyle.PropertyMap;
    -
    -
    -/**
    - * Creates a new SafeStyle object from the properties specified in the map.
    - * @param {goog.html.SafeStyle.PropertyMap} map Mapping of property names to
    - *     their values, for example {'margin': '1px'}. Names must consist of
    - *     [-_a-zA-Z0-9]. Values might be strings consisting of
    - *     [-,.'"%_!# a-zA-Z0-9], where " and ' must be properly balanced.
    - *     Other values must be wrapped in goog.string.Const. Null value causes
    - *     skipping the property.
    - * @return {!goog.html.SafeStyle}
    - * @throws {Error} If invalid name is provided.
    - * @throws {goog.asserts.AssertionError} If invalid value is provided. With
    - *     disabled assertions, invalid value is replaced by
    - *     goog.html.SafeStyle.INNOCUOUS_STRING.
    - */
    -goog.html.SafeStyle.create = function(map) {
    -  var style = '';
    -  for (var name in map) {
    -    if (!/^[-_a-zA-Z0-9]+$/.test(name)) {
    -      throw Error('Name allows only [-_a-zA-Z0-9], got: ' + name);
    -    }
    -    var value = map[name];
    -    if (value == null) {
    -      continue;
    -    }
    -    if (value instanceof goog.string.Const) {
    -      value = goog.string.Const.unwrap(value);
    -      // These characters can be used to change context and we don't want that
    -      // even with const values.
    -      goog.asserts.assert(!/[{;}]/.test(value), 'Value does not allow [{;}].');
    -    } else if (!goog.html.SafeStyle.VALUE_RE_.test(value)) {
    -      goog.asserts.fail(
    -          'String value allows only [-,."\'%_!# a-zA-Z0-9], got: ' + value);
    -      value = goog.html.SafeStyle.INNOCUOUS_STRING;
    -    } else if (!goog.html.SafeStyle.hasBalancedQuotes_(value)) {
    -      goog.asserts.fail('String value requires balanced quotes, got: ' + value);
    -      value = goog.html.SafeStyle.INNOCUOUS_STRING;
    -    }
    -    style += name + ':' + value + ';';
    -  }
    -  if (!style) {
    -    return goog.html.SafeStyle.EMPTY;
    -  }
    -  goog.html.SafeStyle.checkStyle_(style);
    -  return goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(
    -      style);
    -};
    -
    -
    -/**
    - * Checks that quotes (" and ') are properly balanced inside a string. Assumes
    - * that neither escape (\) nor any other character that could result in
    - * breaking out of a string parsing context are allowed;
    - * see http://www.w3.org/TR/css3-syntax/#string-token-diagram.
    - * @param {string} value Untrusted CSS property value.
    - * @return {boolean} True if property value is safe with respect to quote
    - *     balancedness.
    - * @private
    - */
    -goog.html.SafeStyle.hasBalancedQuotes_ = function(value) {
    -  var outsideSingle = true;
    -  var outsideDouble = true;
    -  for (var i = 0; i < value.length; i++) {
    -    var c = value.charAt(i);
    -    if (c == "'" && outsideDouble) {
    -      outsideSingle = !outsideSingle;
    -    } else if (c == '"' && outsideSingle) {
    -      outsideDouble = !outsideDouble;
    -    }
    -  }
    -  return outsideSingle && outsideDouble;
    -};
    -
    -
    -// Keep in sync with the error string in create().
    -/**
    - * Regular expression for safe values.
    - *
    - * Quotes (" and ') are allowed, but a check must be done elsewhere to ensure
    - * they're balanced.
    - *
    - * ',' allows multiple values to be assigned to the same property
    - * (e.g. background-attachment or font-family) and hence could allow
    - * multiple values to get injected, but that should pose no risk of XSS.
    - * @const {!RegExp}
    - * @private
    - */
    -goog.html.SafeStyle.VALUE_RE_ = /^[-,."'%_!# a-zA-Z0-9]+$/;
    -
    -
    -/**
    - * Creates a new SafeStyle object by concatenating the values.
    - * @param {...(!goog.html.SafeStyle|!Array<!goog.html.SafeStyle>)} var_args
    - *     SafeStyles to concatenate.
    - * @return {!goog.html.SafeStyle}
    - */
    -goog.html.SafeStyle.concat = function(var_args) {
    -  var style = '';
    -
    -  /**
    -   * @param {!goog.html.SafeStyle|!Array<!goog.html.SafeStyle>} argument
    -   */
    -  var addArgument = function(argument) {
    -    if (goog.isArray(argument)) {
    -      goog.array.forEach(argument, addArgument);
    -    } else {
    -      style += goog.html.SafeStyle.unwrap(argument);
    -    }
    -  };
    -
    -  goog.array.forEach(arguments, addArgument);
    -  if (!style) {
    -    return goog.html.SafeStyle.EMPTY;
    -  }
    -  return goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(
    -      style);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/html/safestyle_test.html b/src/database/third_party/closure-library/closure/goog/html/safestyle_test.html
    deleted file mode 100644
    index 5c594499dcb..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/safestyle_test.html
    +++ /dev/null
    @@ -1,19 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.html</title>
    -<script src="../base.js"></script>
    -<script>
    -goog.require('goog.html.safeStyleTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/html/safestyle_test.js b/src/database/third_party/closure-library/closure/goog/html/safestyle_test.js
    deleted file mode 100644
    index c992351b8ab..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/safestyle_test.js
    +++ /dev/null
    @@ -1,191 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.html.SafeStyle and its builders.
    - */
    -
    -goog.provide('goog.html.safeStyleTest');
    -
    -goog.require('goog.html.SafeStyle');
    -goog.require('goog.string.Const');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.html.safeStyleTest');
    -
    -
    -function testSafeStyle() {
    -  var style = 'width: 1em;height: 1em;';
    -  var safeStyle =
    -      goog.html.SafeStyle.fromConstant(goog.string.Const.from(style));
    -  var extracted = goog.html.SafeStyle.unwrap(safeStyle);
    -  assertEquals(style, extracted);
    -  assertEquals(style, safeStyle.getTypedStringValue());
    -  assertEquals('SafeStyle{' + style + '}', String(safeStyle));
    -
    -  // Interface marker is present.
    -  assertTrue(safeStyle.implementsGoogStringTypedString);
    -}
    -
    -
    -/** @suppress {checkTypes} */
    -function testUnwrap() {
    -  var evil = {};
    -  evil.safeStyleValueWithSecurityContract__googHtmlSecurityPrivate_ =
    -      'width: expression(evil);';
    -  evil.SAFE_STYLE_TYPE_MARKER__GOOG_HTML_SECURITY_PRIVATE_ = {};
    -
    -  var exception = assertThrows(function() {
    -    goog.html.SafeStyle.unwrap(evil);
    -  });
    -  assertTrue(
    -      exception.message.indexOf('expected object of type SafeStyle') > 0);
    -}
    -
    -
    -function testFromConstant_allowsEmptyString() {
    -  assertEquals(
    -      goog.html.SafeStyle.EMPTY,
    -      goog.html.SafeStyle.fromConstant(goog.string.Const.from('')));
    -}
    -
    -function testFromConstant_throwsOnForbiddenCharacters() {
    -  assertThrows(function() {
    -    goog.html.SafeStyle.fromConstant(goog.string.Const.from('width: x<;'));
    -  });
    -  assertThrows(function() {
    -    goog.html.SafeStyle.fromConstant(goog.string.Const.from('width: x>;'));
    -  });
    -}
    -
    -
    -function testFromConstant_throwsIfNoFinalSemicolon() {
    -  assertThrows(function() {
    -    goog.html.SafeStyle.fromConstant(goog.string.Const.from('width: 1em'));
    -  });
    -}
    -
    -
    -function testFromConstant_throwsIfNoColon() {
    -  assertThrows(function() {
    -    goog.html.SafeStyle.fromConstant(goog.string.Const.from('width= 1em;'));
    -  });
    -}
    -
    -
    -function testEmpty() {
    -  assertEquals('', goog.html.SafeStyle.unwrap(goog.html.SafeStyle.EMPTY));
    -}
    -
    -
    -function testCreate() {
    -  var style = goog.html.SafeStyle.create({
    -    'background': goog.string.Const.from('url(i.png)'),
    -    'margin': '0'
    -  });
    -  assertEquals('background:url(i.png);margin:0;',
    -      goog.html.SafeStyle.unwrap(style));
    -}
    -
    -
    -function testCreate_allowsEmpty() {
    -  assertEquals(goog.html.SafeStyle.EMPTY, goog.html.SafeStyle.create({}));
    -}
    -
    -
    -function testCreate_skipsNull() {
    -  var style = goog.html.SafeStyle.create({'background': null});
    -  assertEquals(goog.html.SafeStyle.EMPTY, style);
    -}
    -
    -
    -function testCreate_allowsLengths() {
    -  var style = goog.html.SafeStyle.create({'padding': '0 1px .2% 3.4em'});
    -  assertEquals('padding:0 1px .2% 3.4em;', goog.html.SafeStyle.unwrap(style));
    -}
    -
    -
    -function testCreate_throwsOnForbiddenCharacters() {
    -  assertThrows(function() {
    -    goog.html.SafeStyle.create({'<': '0'});
    -  });
    -  assertThrows(function() {
    -    goog.html.SafeStyle.create({'color': goog.string.Const.from('<')});
    -  });
    -}
    -
    -
    -function testCreate_values() {
    -  var valids = [
    -    '0',
    -    '0 0',
    -    '1px',
    -    '100%',
    -    '2.3px',
    -    '.1em',
    -    'red',
    -    '#f00',
    -    'red !important',
    -    '"Times New Roman"',
    -    "'Times New Roman'",
    -    '"Bold \'nuff"',
    -    '"O\'Connor\'s Revenge"'
    -  ];
    -  for (var i = 0; i < valids.length; i++) {
    -    var value = valids[i];
    -    assertEquals('background:' + value + ';', goog.html.SafeStyle.unwrap(
    -        goog.html.SafeStyle.create({'background': value})));
    -  }
    -
    -  var invalids = [
    -    '',
    -    'expression(alert(1))',
    -    'url(i.png)',
    -    '"',
    -    '"\'"\'',
    -    goog.string.Const.from('red;')
    -  ];
    -  for (var i = 0; i < invalids.length; i++) {
    -    var value = invalids[i];
    -    assertThrows(function() {
    -      goog.html.SafeStyle.create({'background': value});
    -    });
    -  }
    -}
    -
    -
    -function testConcat() {
    -  var width = goog.html.SafeStyle.fromConstant(
    -      goog.string.Const.from('width: 1em;'));
    -  var margin = goog.html.SafeStyle.create({'margin': '0'});
    -  var padding = goog.html.SafeStyle.create({'padding': '0'});
    -
    -  var style = goog.html.SafeStyle.concat(width, margin);
    -  assertEquals('width: 1em;margin:0;', goog.html.SafeStyle.unwrap(style));
    -
    -  style = goog.html.SafeStyle.concat([width, margin]);
    -  assertEquals('width: 1em;margin:0;', goog.html.SafeStyle.unwrap(style));
    -
    -  style = goog.html.SafeStyle.concat([width], [padding, margin]);
    -  assertEquals('width: 1em;padding:0;margin:0;',
    -      goog.html.SafeStyle.unwrap(style));
    -}
    -
    -
    -function testConcat_allowsEmpty() {
    -  var empty = goog.html.SafeStyle.EMPTY;
    -  assertEquals(empty, goog.html.SafeStyle.concat());
    -  assertEquals(empty, goog.html.SafeStyle.concat([]));
    -  assertEquals(empty, goog.html.SafeStyle.concat(empty));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/html/safestylesheet.js b/src/database/third_party/closure-library/closure/goog/html/safestylesheet.js
    deleted file mode 100644
    index 79e8b51cd4b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/safestylesheet.js
    +++ /dev/null
    @@ -1,276 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview The SafeStyleSheet type and its builders.
    - *
    - * TODO(user): Link to document stating type contract.
    - */
    -
    -goog.provide('goog.html.SafeStyleSheet');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.string');
    -goog.require('goog.string.Const');
    -goog.require('goog.string.TypedString');
    -
    -
    -
    -/**
    - * A string-like object which represents a CSS style sheet and that carries the
    - * security type contract that its value, as a string, will not cause untrusted
    - * script execution (XSS) when evaluated as CSS in a browser.
    - *
    - * Instances of this type must be created via the factory method
    - * {@code goog.html.SafeStyleSheet.fromConstant} and not by invoking its
    - * constructor. The constructor intentionally takes no parameters and the type
    - * is immutable; hence only a default instance corresponding to the empty string
    - * can be obtained via constructor invocation.
    - *
    - * A SafeStyleSheet's string representation can safely be interpolated as the
    - * content of a style element within HTML. The SafeStyleSheet string should
    - * not be escaped before interpolation.
    - *
    - * Values of this type must be composable, i.e. for any two values
    - * {@code styleSheet1} and {@code styleSheet2} of this type,
    - * {@code goog.html.SafeStyleSheet.unwrap(styleSheet1) +
    - * goog.html.SafeStyleSheet.unwrap(styleSheet2)} must itself be a value that
    - * satisfies the SafeStyleSheet type constraint. This requirement implies that
    - * for any value {@code styleSheet} of this type,
    - * {@code goog.html.SafeStyleSheet.unwrap(styleSheet1)} must end in
    - * "beginning of rule" context.
    -
    - * A SafeStyleSheet can be constructed via security-reviewed unchecked
    - * conversions. In this case producers of SafeStyleSheet must ensure themselves
    - * that the SafeStyleSheet does not contain unsafe script. Note in particular
    - * that {@code &lt;} is dangerous, even when inside CSS strings, and so should
    - * always be forbidden or CSS-escaped in user controlled input. For example, if
    - * {@code &lt;/style&gt;&lt;script&gt;evil&lt;/script&gt;"} were interpolated
    - * inside a CSS string, it would break out of the context of the original
    - * style element and {@code evil} would execute. Also note that within an HTML
    - * style (raw text) element, HTML character references, such as
    - * {@code &amp;lt;}, are not allowed. See
    - * http://www.w3.org/TR/html5/scripting-1.html#restrictions-for-contents-of-script-elements
    - * (similar considerations apply to the style element).
    - *
    - * @see goog.html.SafeStyleSheet#fromConstant
    - * @constructor
    - * @final
    - * @struct
    - * @implements {goog.string.TypedString}
    - */
    -goog.html.SafeStyleSheet = function() {
    -  /**
    -   * The contained value of this SafeStyleSheet.  The field has a purposely
    -   * ugly name to make (non-compiled) code that attempts to directly access this
    -   * field stand out.
    -   * @private {string}
    -   */
    -  this.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_ = '';
    -
    -  /**
    -   * A type marker used to implement additional run-time type checking.
    -   * @see goog.html.SafeStyleSheet#unwrap
    -   * @const
    -   * @private
    -   */
    -  this.SAFE_SCRIPT_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ =
    -      goog.html.SafeStyleSheet.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_;
    -};
    -
    -
    -/**
    - * @override
    - * @const
    - */
    -goog.html.SafeStyleSheet.prototype.implementsGoogStringTypedString = true;
    -
    -
    -/**
    - * Type marker for the SafeStyleSheet type, used to implement additional
    - * run-time type checking.
    - * @const
    - * @private
    - */
    -goog.html.SafeStyleSheet.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {};
    -
    -
    -/**
    - * Creates a new SafeStyleSheet object by concatenating values.
    - * @param {...(!goog.html.SafeStyleSheet|!Array<!goog.html.SafeStyleSheet>)}
    - *     var_args Values to concatenate.
    - * @return {!goog.html.SafeStyleSheet}
    - */
    -goog.html.SafeStyleSheet.concat = function(var_args) {
    -  var result = '';
    -
    -  /**
    -   * @param {!goog.html.SafeStyleSheet|!Array<!goog.html.SafeStyleSheet>}
    -   *     argument
    -   */
    -  var addArgument = function(argument) {
    -    if (goog.isArray(argument)) {
    -      goog.array.forEach(argument, addArgument);
    -    } else {
    -      result += goog.html.SafeStyleSheet.unwrap(argument);
    -    }
    -  };
    -
    -  goog.array.forEach(arguments, addArgument);
    -  return goog.html.SafeStyleSheet
    -      .createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(result);
    -};
    -
    -
    -/**
    - * Creates a SafeStyleSheet object from a compile-time constant string.
    - *
    - * {@code styleSheet} must not have any &lt; characters in it, so that
    - * the syntactic structure of the surrounding HTML is not affected.
    - *
    - * @param {!goog.string.Const} styleSheet A compile-time-constant string from
    - *     which to create a SafeStyleSheet.
    - * @return {!goog.html.SafeStyleSheet} A SafeStyleSheet object initialized to
    - *     {@code styleSheet}.
    - */
    -goog.html.SafeStyleSheet.fromConstant = function(styleSheet) {
    -  var styleSheetString = goog.string.Const.unwrap(styleSheet);
    -  if (styleSheetString.length === 0) {
    -    return goog.html.SafeStyleSheet.EMPTY;
    -  }
    -  // > is a valid character in CSS selectors and there's no strict need to
    -  // block it if we already block <.
    -  goog.asserts.assert(!goog.string.contains(styleSheetString, '<'),
    -      "Forbidden '<' character in style sheet string: " + styleSheetString);
    -  return goog.html.SafeStyleSheet.
    -      createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(styleSheetString);
    -};
    -
    -
    -/**
    - * Returns this SafeStyleSheet's value as a string.
    - *
    - * IMPORTANT: In code where it is security relevant that an object's type is
    - * indeed {@code SafeStyleSheet}, use {@code goog.html.SafeStyleSheet.unwrap}
    - * instead of this method. If in doubt, assume that it's security relevant. In
    - * particular, note that goog.html functions which return a goog.html type do
    - * not guarantee the returned instance is of the right type. For example:
    - *
    - * <pre>
    - * var fakeSafeHtml = new String('fake');
    - * fakeSafeHtml.__proto__ = goog.html.SafeHtml.prototype;
    - * var newSafeHtml = goog.html.SafeHtml.htmlEscape(fakeSafeHtml);
    - * // newSafeHtml is just an alias for fakeSafeHtml, it's passed through by
    - * // goog.html.SafeHtml.htmlEscape() as fakeSafeHtml
    - * // instanceof goog.html.SafeHtml.
    - * </pre>
    - *
    - * @see goog.html.SafeStyleSheet#unwrap
    - * @override
    - */
    -goog.html.SafeStyleSheet.prototype.getTypedStringValue = function() {
    -  return this.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_;
    -};
    -
    -
    -if (goog.DEBUG) {
    -  /**
    -   * Returns a debug string-representation of this value.
    -   *
    -   * To obtain the actual string value wrapped in a SafeStyleSheet, use
    -   * {@code goog.html.SafeStyleSheet.unwrap}.
    -   *
    -   * @see goog.html.SafeStyleSheet#unwrap
    -   * @override
    -   */
    -  goog.html.SafeStyleSheet.prototype.toString = function() {
    -    return 'SafeStyleSheet{' +
    -        this.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_ + '}';
    -  };
    -}
    -
    -
    -/**
    - * Performs a runtime check that the provided object is indeed a
    - * SafeStyleSheet object, and returns its value.
    - *
    - * @param {!goog.html.SafeStyleSheet} safeStyleSheet The object to extract from.
    - * @return {string} The safeStyleSheet object's contained string, unless
    - *     the run-time type check fails. In that case, {@code unwrap} returns an
    - *     innocuous string, or, if assertions are enabled, throws
    - *     {@code goog.asserts.AssertionError}.
    - */
    -goog.html.SafeStyleSheet.unwrap = function(safeStyleSheet) {
    -  // Perform additional Run-time type-checking to ensure that
    -  // safeStyleSheet is indeed an instance of the expected type.  This
    -  // provides some additional protection against security bugs due to
    -  // application code that disables type checks.
    -  // Specifically, the following checks are performed:
    -  // 1. The object is an instance of the expected type.
    -  // 2. The object is not an instance of a subclass.
    -  // 3. The object carries a type marker for the expected type. "Faking" an
    -  // object requires a reference to the type marker, which has names intended
    -  // to stand out in code reviews.
    -  if (safeStyleSheet instanceof goog.html.SafeStyleSheet &&
    -      safeStyleSheet.constructor === goog.html.SafeStyleSheet &&
    -      safeStyleSheet.SAFE_SCRIPT_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ ===
    -          goog.html.SafeStyleSheet.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_) {
    -    return safeStyleSheet.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_;
    -  } else {
    -    goog.asserts.fail(
    -        "expected object of type SafeStyleSheet, got '" + safeStyleSheet +
    -        "'");
    -    return 'type_error:SafeStyleSheet';
    -  }
    -};
    -
    -
    -/**
    - * Package-internal utility method to create SafeStyleSheet instances.
    - *
    - * @param {string} styleSheet The string to initialize the SafeStyleSheet
    - *     object with.
    - * @return {!goog.html.SafeStyleSheet} The initialized SafeStyleSheet object.
    - * @package
    - */
    -goog.html.SafeStyleSheet.createSafeStyleSheetSecurityPrivateDoNotAccessOrElse =
    -    function(styleSheet) {
    -  return new goog.html.SafeStyleSheet().initSecurityPrivateDoNotAccessOrElse_(
    -      styleSheet);
    -};
    -
    -
    -/**
    - * Called from createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(). This
    - * method exists only so that the compiler can dead code eliminate static
    - * fields (like EMPTY) when they're not accessed.
    - * @param {string} styleSheet
    - * @return {!goog.html.SafeStyleSheet}
    - * @private
    - */
    -goog.html.SafeStyleSheet.prototype.initSecurityPrivateDoNotAccessOrElse_ =
    -    function(styleSheet) {
    -  this.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_ = styleSheet;
    -  return this;
    -};
    -
    -
    -/**
    - * A SafeStyleSheet instance corresponding to the empty string.
    - * @const {!goog.html.SafeStyleSheet}
    - */
    -goog.html.SafeStyleSheet.EMPTY =
    -    goog.html.SafeStyleSheet.
    -        createSafeStyleSheetSecurityPrivateDoNotAccessOrElse('');
    diff --git a/src/database/third_party/closure-library/closure/goog/html/safestylesheet_test.html b/src/database/third_party/closure-library/closure/goog/html/safestylesheet_test.html
    deleted file mode 100644
    index 1eee7f33cb0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/safestylesheet_test.html
    +++ /dev/null
    @@ -1,19 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.html</title>
    -<script src="../base.js"></script>
    -<script>
    -goog.require('goog.html.safeStyleSheetTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/html/safestylesheet_test.js b/src/database/third_party/closure-library/closure/goog/html/safestylesheet_test.js
    deleted file mode 100644
    index 084f91d8f57..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/safestylesheet_test.js
    +++ /dev/null
    @@ -1,97 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.html.SafeStyleSheet and its builders.
    - */
    -
    -goog.provide('goog.html.safeStyleSheetTest');
    -
    -goog.require('goog.html.SafeStyleSheet');
    -goog.require('goog.string');
    -goog.require('goog.string.Const');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.html.safeStyleSheetTest');
    -
    -
    -function testSafeStyleSheet() {
    -  var styleSheet = 'P.special { color:red ; }';
    -  var safeStyleSheet =
    -      goog.html.SafeStyleSheet.fromConstant(goog.string.Const.from(styleSheet));
    -  var extracted = goog.html.SafeStyleSheet.unwrap(safeStyleSheet);
    -  assertEquals(styleSheet, extracted);
    -  assertEquals(styleSheet, safeStyleSheet.getTypedStringValue());
    -  assertEquals('SafeStyleSheet{' + styleSheet + '}', String(safeStyleSheet));
    -
    -  // Interface marker is present.
    -  assertTrue(safeStyleSheet.implementsGoogStringTypedString);
    -}
    -
    -
    -/** @suppress {checkTypes} */
    -function testUnwrap() {
    -  var evil = {};
    -  evil.safeStyleSheetValueWithSecurityContract__googHtmlSecurityPrivate_ =
    -      'P.special { color:expression(evil) ; }';
    -  evil.SAFE_STYLE_TYPE_MARKER__GOOG_HTML_SECURITY_PRIVATE_ = {};
    -
    -  var exception = assertThrows(function() {
    -    goog.html.SafeStyleSheet.unwrap(evil);
    -  });
    -  assertTrue(goog.string.contains(
    -      exception.message,
    -      'expected object of type SafeStyleSheet'));
    -}
    -
    -
    -function testFromConstant_allowsEmptyString() {
    -  assertEquals(
    -      goog.html.SafeStyleSheet.EMPTY,
    -      goog.html.SafeStyleSheet.fromConstant(goog.string.Const.from('')));
    -}
    -
    -
    -function testFromConstant_throwsOnLessThanCharacter() {
    -  assertThrows(function() {
    -    goog.html.SafeStyleSheet.fromConstant(goog.string.Const.from('x<x'));
    -  });
    -}
    -
    -
    -function testConcat() {
    -  var styleSheet1 = goog.html.SafeStyleSheet.fromConstant(
    -      goog.string.Const.from('P.special { color:red ; }'));
    -  var styleSheet2 = goog.html.SafeStyleSheet.fromConstant(
    -      goog.string.Const.from('P.regular { color:blue ; }'));
    -  var expected = 'P.special { color:red ; }P.special { color:red ; }' +
    -      'P.regular { color:blue ; }P.regular { color:blue ; }';
    -
    -  var concatStyleSheet = goog.html.SafeStyleSheet.concat(
    -      styleSheet1, [styleSheet1, styleSheet2], styleSheet2);
    -  assertEquals(
    -      expected, goog.html.SafeStyleSheet.unwrap(concatStyleSheet));
    -
    -  // Empty.
    -  concatStyleSheet = goog.html.SafeStyleSheet.concat();
    -  assertEquals('', goog.html.SafeStyleSheet.unwrap(concatStyleSheet));
    -  concatStyleSheet = goog.html.SafeStyleSheet.concat([]);
    -  assertEquals('', goog.html.SafeStyleSheet.unwrap(concatStyleSheet));
    -}
    -
    -
    -function testEmpty() {
    -  assertEquals(
    -      '', goog.html.SafeStyleSheet.unwrap(goog.html.SafeStyleSheet.EMPTY));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/html/safeurl.js b/src/database/third_party/closure-library/closure/goog/html/safeurl.js
    deleted file mode 100644
    index 9153203a158..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/safeurl.js
    +++ /dev/null
    @@ -1,403 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview The SafeUrl type and its builders.
    - *
    - * TODO(user): Link to document stating type contract.
    - */
    -
    -goog.provide('goog.html.SafeUrl');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.i18n.bidi.Dir');
    -goog.require('goog.i18n.bidi.DirectionalString');
    -goog.require('goog.string.Const');
    -goog.require('goog.string.TypedString');
    -
    -
    -
    -/**
    - * A string that is safe to use in URL context in DOM APIs and HTML documents.
    - *
    - * A SafeUrl is a string-like object that carries the security type contract
    - * that its value as a string will not cause untrusted script execution
    - * when evaluated as a hyperlink URL in a browser.
    - *
    - * Values of this type are guaranteed to be safe to use in URL/hyperlink
    - * contexts, such as, assignment to URL-valued DOM properties, or
    - * interpolation into a HTML template in URL context (e.g., inside a href
    - * attribute), in the sense that the use will not result in a
    - * Cross-Site-Scripting vulnerability.
    - *
    - * Note that, as documented in {@code goog.html.SafeUrl.unwrap}, this type's
    - * contract does not guarantee that instances are safe to interpolate into HTML
    - * without appropriate escaping.
    - *
    - * Note also that this type's contract does not imply any guarantees regarding
    - * the resource the URL refers to.  In particular, SafeUrls are <b>not</b>
    - * safe to use in a context where the referred-to resource is interpreted as
    - * trusted code, e.g., as the src of a script tag.
    - *
    - * Instances of this type must be created via the factory methods
    - * ({@code goog.html.SafeUrl.fromConstant}, {@code goog.html.SafeUrl.sanitize}),
    - * etc and not by invoking its constructor.  The constructor intentionally
    - * takes no parameters and the type is immutable; hence only a default instance
    - * corresponding to the empty string can be obtained via constructor invocation.
    - *
    - * @see goog.html.SafeUrl#fromConstant
    - * @see goog.html.SafeUrl#from
    - * @see goog.html.SafeUrl#sanitize
    - * @constructor
    - * @final
    - * @struct
    - * @implements {goog.i18n.bidi.DirectionalString}
    - * @implements {goog.string.TypedString}
    - */
    -goog.html.SafeUrl = function() {
    -  /**
    -   * The contained value of this SafeUrl.  The field has a purposely ugly
    -   * name to make (non-compiled) code that attempts to directly access this
    -   * field stand out.
    -   * @private {string}
    -   */
    -  this.privateDoNotAccessOrElseSafeHtmlWrappedValue_ = '';
    -
    -  /**
    -   * A type marker used to implement additional run-time type checking.
    -   * @see goog.html.SafeUrl#unwrap
    -   * @const
    -   * @private
    -   */
    -  this.SAFE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ =
    -      goog.html.SafeUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_;
    -};
    -
    -
    -/**
    - * The innocuous string generated by goog.html.SafeUrl.sanitize when passed
    - * an unsafe URL.
    - *
    - * about:invalid is registered in
    - * http://www.w3.org/TR/css3-values/#about-invalid.
    - * http://tools.ietf.org/html/rfc6694#section-2.2.1 permits about URLs to
    - * contain a fragment, which is not to be considered when determining if an
    - * about URL is well-known.
    - *
    - * Using about:invalid seems preferable to using a fixed data URL, since
    - * browsers might choose to not report CSP violations on it, as legitimate
    - * CSS function calls to attr() can result in this URL being produced. It is
    - * also a standard URL which matches exactly the semantics we need:
    - * "The about:invalid URI references a non-existent document with a generic
    - * error condition. It can be used when a URI is necessary, but the default
    - * value shouldn't be resolveable as any type of document".
    - *
    - * @const {string}
    - */
    -goog.html.SafeUrl.INNOCUOUS_STRING = 'about:invalid#zClosurez';
    -
    -
    -/**
    - * @override
    - * @const
    - */
    -goog.html.SafeUrl.prototype.implementsGoogStringTypedString = true;
    -
    -
    -/**
    - * Returns this SafeUrl's value a string.
    - *
    - * IMPORTANT: In code where it is security relevant that an object's type is
    - * indeed {@code SafeUrl}, use {@code goog.html.SafeUrl.unwrap} instead of this
    - * method. If in doubt, assume that it's security relevant. In particular, note
    - * that goog.html functions which return a goog.html type do not guarantee that
    - * the returned instance is of the right type. For example:
    - *
    - * <pre>
    - * var fakeSafeHtml = new String('fake');
    - * fakeSafeHtml.__proto__ = goog.html.SafeHtml.prototype;
    - * var newSafeHtml = goog.html.SafeHtml.htmlEscape(fakeSafeHtml);
    - * // newSafeHtml is just an alias for fakeSafeHtml, it's passed through by
    - * // goog.html.SafeHtml.htmlEscape() as fakeSafeHtml instanceof
    - * // goog.html.SafeHtml.
    - * </pre>
    - *
    - * IMPORTANT: The guarantees of the SafeUrl type contract only extend to the
    - * behavior of browsers when interpreting URLs. Values of SafeUrl objects MUST
    - * be appropriately escaped before embedding in a HTML document. Note that the
    - * required escaping is context-sensitive (e.g. a different escaping is
    - * required for embedding a URL in a style property within a style
    - * attribute, as opposed to embedding in a href attribute).
    - *
    - * @see goog.html.SafeUrl#unwrap
    - * @override
    - */
    -goog.html.SafeUrl.prototype.getTypedStringValue = function() {
    -  return this.privateDoNotAccessOrElseSafeHtmlWrappedValue_;
    -};
    -
    -
    -/**
    - * @override
    - * @const
    - */
    -goog.html.SafeUrl.prototype.implementsGoogI18nBidiDirectionalString = true;
    -
    -
    -/**
    - * Returns this URLs directionality, which is always {@code LTR}.
    - * @override
    - */
    -goog.html.SafeUrl.prototype.getDirection = function() {
    -  return goog.i18n.bidi.Dir.LTR;
    -};
    -
    -
    -if (goog.DEBUG) {
    -  /**
    -   * Returns a debug string-representation of this value.
    -   *
    -   * To obtain the actual string value wrapped in a SafeUrl, use
    -   * {@code goog.html.SafeUrl.unwrap}.
    -   *
    -   * @see goog.html.SafeUrl#unwrap
    -   * @override
    -   */
    -  goog.html.SafeUrl.prototype.toString = function() {
    -    return 'SafeUrl{' + this.privateDoNotAccessOrElseSafeHtmlWrappedValue_ +
    -        '}';
    -  };
    -}
    -
    -
    -/**
    - * Performs a runtime check that the provided object is indeed a SafeUrl
    - * object, and returns its value.
    - *
    - * IMPORTANT: The guarantees of the SafeUrl type contract only extend to the
    - * behavior of  browsers when interpreting URLs. Values of SafeUrl objects MUST
    - * be appropriately escaped before embedding in a HTML document. Note that the
    - * required escaping is context-sensitive (e.g. a different escaping is
    - * required for embedding a URL in a style property within a style
    - * attribute, as opposed to embedding in a href attribute).
    - *
    - * Note that the returned value does not necessarily correspond to the string
    - * with which the SafeUrl was constructed, since goog.html.SafeUrl.sanitize
    - * will percent-encode many characters.
    - *
    - * @param {!goog.html.SafeUrl} safeUrl The object to extract from.
    - * @return {string} The SafeUrl object's contained string, unless the run-time
    - *     type check fails. In that case, {@code unwrap} returns an innocuous
    - *     string, or, if assertions are enabled, throws
    - *     {@code goog.asserts.AssertionError}.
    - */
    -goog.html.SafeUrl.unwrap = function(safeUrl) {
    -  // Perform additional Run-time type-checking to ensure that safeUrl is indeed
    -  // an instance of the expected type.  This provides some additional protection
    -  // against security bugs due to application code that disables type checks.
    -  // Specifically, the following checks are performed:
    -  // 1. The object is an instance of the expected type.
    -  // 2. The object is not an instance of a subclass.
    -  // 3. The object carries a type marker for the expected type. "Faking" an
    -  // object requires a reference to the type marker, which has names intended
    -  // to stand out in code reviews.
    -  if (safeUrl instanceof goog.html.SafeUrl &&
    -      safeUrl.constructor === goog.html.SafeUrl &&
    -      safeUrl.SAFE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ ===
    -          goog.html.SafeUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_) {
    -    return safeUrl.privateDoNotAccessOrElseSafeHtmlWrappedValue_;
    -  } else {
    -    goog.asserts.fail('expected object of type SafeUrl, got \'' +
    -                      safeUrl + '\'');
    -    return 'type_error:SafeUrl';
    -
    -  }
    -};
    -
    -
    -/**
    - * Creates a SafeUrl object from a compile-time constant string.
    - *
    - * Compile-time constant strings are inherently program-controlled and hence
    - * trusted.
    - *
    - * @param {!goog.string.Const} url A compile-time-constant string from which to
    - *         create a SafeUrl.
    - * @return {!goog.html.SafeUrl} A SafeUrl object initialized to {@code url}.
    - */
    -goog.html.SafeUrl.fromConstant = function(url) {
    -  return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(
    -      goog.string.Const.unwrap(url));
    -};
    -
    -
    -/**
    - * A pattern that recognizes a commonly useful subset of URLs that satisfy
    - * the SafeUrl contract.
    - *
    - * This regular expression matches a subset of URLs that will not cause script
    - * execution if used in URL context within a HTML document. Specifically, this
    - * regular expression matches if (comment from here on and regex copied from
    - * Soy's EscapingConventions):
    - * (1) Either a protocol in a whitelist (http, https, mailto or ftp).
    - * (2) or no protocol.  A protocol must be followed by a colon. The below
    - *     allows that by allowing colons only after one of the characters [/?#].
    - *     A colon after a hash (#) must be in the fragment.
    - *     Otherwise, a colon after a (?) must be in a query.
    - *     Otherwise, a colon after a single solidus (/) must be in a path.
    - *     Otherwise, a colon after a double solidus (//) must be in the authority
    - *     (before port).
    - *
    - * The pattern disallows &, used in HTML entity declarations before
    - * one of the characters in [/?#]. This disallows HTML entities used in the
    - * protocol name, which should never happen, e.g. "h&#116;tp" for "http".
    - * It also disallows HTML entities in the first path part of a relative path,
    - * e.g. "foo&lt;bar/baz".  Our existing escaping functions should not produce
    - * that. More importantly, it disallows masking of a colon,
    - * e.g. "javascript&#58;...".
    - *
    - * @private
    - * @const {!RegExp}
    - */
    -goog.html.SAFE_URL_PATTERN_ =
    -    /^(?:(?:https?|mailto|ftp):|[^&:/?#]*(?:[/?#]|$))/i;
    -
    -
    -/**
    - * Creates a SafeUrl object from {@code url}. If {@code url} is a
    - * goog.html.SafeUrl then it is simply returned. Otherwise the input string is
    - * validated to match a pattern of commonly used safe URLs. The string is
    - * converted to UTF-8 and non-whitelisted characters are percent-encoded. The
    - * string wrapped by the created SafeUrl will thus contain only ASCII printable
    - * characters.
    - *
    - * {@code url} may be a URL with the http, https, mailto or ftp scheme,
    - * or a relative URL (i.e., a URL without a scheme; specifically, a
    - * scheme-relative, absolute-path-relative, or path-relative URL).
    - *
    - * {@code url} is converted to UTF-8 and non-whitelisted characters are
    - * percent-encoded. Whitelisted characters are '%' and, from RFC 3986,
    - * unreserved characters and reserved characters, with the exception of '\'',
    - * '(' and ')'. This ensures the the SafeUrl contains only ASCII-printable
    - * characters and reduces the chance of security bugs were it to be
    - * interpolated into a specific context without the necessary escaping.
    - *
    - * If {@code url} fails validation or does not UTF-16 decode correctly
    - * (JavaScript strings are UTF-16 encoded), this function returns a SafeUrl
    - * object containing an innocuous string, goog.html.SafeUrl.INNOCUOUS_STRING.
    - *
    - * @see http://url.spec.whatwg.org/#concept-relative-url
    - * @param {string|!goog.string.TypedString} url The URL to validate.
    - * @return {!goog.html.SafeUrl} The validated URL, wrapped as a SafeUrl.
    - */
    -goog.html.SafeUrl.sanitize = function(url) {
    -  if (url instanceof goog.html.SafeUrl) {
    -    return url;
    -  }
    -  else if (url.implementsGoogStringTypedString) {
    -    url = url.getTypedStringValue();
    -  } else {
    -    url = String(url);
    -  }
    -  if (!goog.html.SAFE_URL_PATTERN_.test(url)) {
    -    url = goog.html.SafeUrl.INNOCUOUS_STRING;
    -  } else {
    -    url = goog.html.SafeUrl.normalize_(url);
    -  }
    -  return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(url);
    -};
    -
    -
    -/**
    - * Normalizes {@code url} the UTF-8 encoding of url, using a whitelist of
    - * characters. Whitelisted characters are not percent-encoded.
    - * @param {string} url The URL to normalize.
    - * @return {string} The normalized URL.
    - * @private
    - */
    -goog.html.SafeUrl.normalize_ = function(url) {
    -  try {
    -    var normalized = encodeURI(url);
    -  } catch (e) {  // Happens if url contains invalid surrogate sequences.
    -    return goog.html.SafeUrl.INNOCUOUS_STRING;
    -  }
    -
    -  return normalized.replace(
    -      goog.html.SafeUrl.NORMALIZE_MATCHER_,
    -      function(match) {
    -        return goog.html.SafeUrl.NORMALIZE_REPLACER_MAP_[match];
    -      });
    -};
    -
    -
    -/**
    - * Matches characters and strings which need to be replaced in the string
    - * generated by encodeURI. Specifically:
    - *
    - * - '\'', '(' and ')' are not encoded. They are part of the reserved
    - *   characters group in RFC 3986 but only appear in the obsolete mark
    - *   production in Appendix D.2 of RFC 3986, so they can be encoded without
    - *   changing semantics.
    - * - '[' and ']' are encoded by encodeURI, despite being reserved characters
    - *   which can be used to represent IPv6 addresses. So they need to be decoded.
    - * - '%' is encoded by encodeURI. However, encoding '%' characters that are
    - *   already part of a valid percent-encoded sequence changes the semantics of a
    - *   URL, and hence we need to preserve them. Note that this may allow
    - *   non-encoded '%' characters to remain in the URL (i.e., occurrences of '%'
    - *   that are not part of a valid percent-encoded sequence, for example,
    - *   'ab%xy').
    - *
    - * @const {!RegExp}
    - * @private
    - */
    -goog.html.SafeUrl.NORMALIZE_MATCHER_ = /[()']|%5B|%5D|%25/g;
    -
    -
    -/**
    - * Map of replacements to be done in string generated by encodeURI.
    - * @const {!Object<string, string>}
    - * @private
    - */
    -goog.html.SafeUrl.NORMALIZE_REPLACER_MAP_ = {
    -  '\'': '%27',
    -  '(': '%28',
    -  ')': '%29',
    -  '%5B': '[',
    -  '%5D': ']',
    -  '%25': '%'
    -};
    -
    -
    -/**
    - * Type marker for the SafeUrl type, used to implement additional run-time
    - * type checking.
    - * @const
    - * @private
    - */
    -goog.html.SafeUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {};
    -
    -
    -/**
    - * Package-internal utility method to create SafeUrl instances.
    - *
    - * @param {string} url The string to initialize the SafeUrl object with.
    - * @return {!goog.html.SafeUrl} The initialized SafeUrl object.
    - * @package
    - */
    -goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse = function(
    -    url) {
    -  var safeUrl = new goog.html.SafeUrl();
    -  safeUrl.privateDoNotAccessOrElseSafeHtmlWrappedValue_ = url;
    -  return safeUrl;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/html/safeurl_test.html b/src/database/third_party/closure-library/closure/goog/html/safeurl_test.html
    deleted file mode 100644
    index bc341ab5a93..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/safeurl_test.html
    +++ /dev/null
    @@ -1,19 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.html</title>
    -<script src="../base.js"></script>
    -<script>
    -goog.require('goog.html.safeUrlTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/html/safeurl_test.js b/src/database/third_party/closure-library/closure/goog/html/safeurl_test.js
    deleted file mode 100644
    index a0955ac5f8c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/safeurl_test.js
    +++ /dev/null
    @@ -1,204 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.html.SafeUrl and its builders.
    - */
    -
    -goog.provide('goog.html.safeUrlTest');
    -
    -goog.require('goog.html.SafeUrl');
    -goog.require('goog.i18n.bidi.Dir');
    -goog.require('goog.string.Const');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.html.safeUrlTest');
    -
    -
    -
    -function testSafeUrl() {
    -  var safeUrl = goog.html.SafeUrl.fromConstant(
    -      goog.string.Const.from('javascript:trusted();'));
    -  var extracted = goog.html.SafeUrl.unwrap(safeUrl);
    -  assertEquals('javascript:trusted();', extracted);
    -  assertEquals('javascript:trusted();', goog.html.SafeUrl.unwrap(safeUrl));
    -  assertEquals('SafeUrl{javascript:trusted();}', String(safeUrl));
    -
    -  // URLs are always LTR.
    -  assertEquals(goog.i18n.bidi.Dir.LTR, safeUrl.getDirection());
    -
    -  // Interface markers are present.
    -  assertTrue(safeUrl.implementsGoogStringTypedString);
    -  assertTrue(safeUrl.implementsGoogI18nBidiDirectionalString);
    -}
    -
    -
    -/** @suppress {checkTypes} */
    -function testUnwrap() {
    -  var evil = {};
    -  evil.safeUrlValueWithSecurityContract_googHtmlSecurityPrivate_ =
    -      '<script>evil()</script';
    -  evil.SAFE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {};
    -
    -  var exception = assertThrows(function() {
    -    goog.html.SafeUrl.unwrap(evil);
    -  });
    -  assertTrue(exception.message.indexOf('expected object of type SafeUrl') > 0);
    -}
    -
    -
    -/**
    - * Assert that url passes through sanitization unchanged.
    - * @param {string|!goog.string.TypedString} url The URL to sanitize.
    - */
    -function assertGoodUrl(url) {
    -  var expected = url;
    -  if (url.implementsGoogStringTypedString) {
    -    expected = url.getTypedStringValue();
    -  }
    -  var safeUrl = goog.html.SafeUrl.sanitize(url);
    -  var extracted = goog.html.SafeUrl.unwrap(safeUrl);
    -  assertEquals(expected, extracted);
    -}
    -
    -
    -/**
    - * Assert that url fails sanitization.
    - * @param {string|!goog.string.TypedString} url The URL to sanitize.
    - */
    -function assertBadUrl(url) {
    -  assertEquals(
    -      goog.html.SafeUrl.INNOCUOUS_STRING,
    -      goog.html.SafeUrl.unwrap(
    -          goog.html.SafeUrl.sanitize(url)));
    -}
    -
    -
    -function testSafeUrlSanitize_validatesUrl() {
    -  // Whitelisted schemes.
    -  assertGoodUrl('http://example.com/');
    -  assertGoodUrl('https://example.com');
    -  assertGoodUrl('mailto:foo@example.com');
    -  assertGoodUrl('ftp://example.com');
    -  assertGoodUrl('ftp://username@example.com');
    -  assertGoodUrl('ftp://username:password@example.com');
    -  // Scheme is case-insensitive
    -  assertGoodUrl('HTtp://example.com/');
    -  // Different URL components go through.
    -  assertGoodUrl('https://example.com/path?foo=bar#baz');
    -  // Scheme-less URL with authority.
    -  assertGoodUrl('//example.com/path');
    -  // Absolute path with no authority.
    -  assertGoodUrl('/path');
    -  assertGoodUrl('/path?foo=bar#baz');
    -  // Relative path.
    -  assertGoodUrl('path');
    -  assertGoodUrl('path?foo=bar#baz');
    -  assertGoodUrl('p//ath');
    -  assertGoodUrl('p//ath?foo=bar#baz');
    -  // Restricted characters ('&', ':', \') after [/?#].
    -  assertGoodUrl('/&');
    -  assertGoodUrl('?:');
    -
    -  // .sanitize() works on program constants.
    -  assertGoodUrl(goog.string.Const.from('http://example.com/'));
    -
    -  // Non-whitelisted schemes.
    -  assertBadUrl('javascript:evil();');
    -  assertBadUrl('javascript:evil();//\nhttp://good.com/');
    -  assertBadUrl('data:blah');
    -  // Restricted characters before [/?#].
    -  assertBadUrl('&');
    -  assertBadUrl(':');
    -  // '\' is not treated like '/': no restricted characters allowed after it.
    -  assertBadUrl('\\:');
    -  // Regex anchored to the left: doesn't match on '/:'.
    -  assertBadUrl(':/:');
    -  // Regex multiline not enabled: first line would match but second one
    -  // wouldn't.
    -  assertBadUrl('path\n:');
    -
    -  // .sanitize() does not exempt values known to be program constants.
    -  assertBadUrl(goog.string.Const.from('data:blah'));
    -}
    -
    -
    -/**
    - * Asserts that goog.html.SafeUrl.unwrap returns the expected string when the
    - * SafeUrl has been constructed by passing the given url to
    - * goog.html.SafeUrl.sanitize.
    - * @param {string} url The string to pass to goog.html.SafeUrl.sanitize.
    - * @param {string} expected The string representation that
    - *         goog.html.SafeUrl.unwrap should return.
    - */
    -function assertSanitizeEncodesTo(url, expected) {
    -  var safeUrl = goog.html.SafeUrl.sanitize(url);
    -  var actual = goog.html.SafeUrl.unwrap(safeUrl);
    -  assertEquals(
    -      'SafeUrl.sanitize().unwrap() doesn\'t return expected ' +
    -          'percent-encoded string',
    -      expected,
    -      actual);
    -}
    -
    -
    -function testSafeUrlSanitize_percentEncodesUrl() {
    -  // '%' is preserved.
    -  assertSanitizeEncodesTo('%', '%');
    -  assertSanitizeEncodesTo('%2F', '%2F');
    -
    -  // Unreserved characters, RFC 3986.
    -  assertSanitizeEncodesTo('aA1-._~', 'aA1-._~');
    -
    -  // Reserved characters, RFC 3986. Only '\'', '(' and ')' are encoded.
    -  assertSanitizeEncodesTo('/:?#[]@!$&\'()*+,;=', '/:?#[]@!$&%27%28%29*+,;=');
    -
    -
    -  // Other ASCII characters, printable and non-printable.
    -  assertSanitizeEncodesTo('^"\\`\x00\n\r\x7f', '%5E%22%5C%60%00%0A%0D%7F');
    -
    -  // Codepoints which UTF-8 encode to 2 bytes.
    -  assertSanitizeEncodesTo('\u0080\u07ff', '%C2%80%DF%BF');
    -
    -  // Highest codepoint which can be UTF-16 encoded using two bytes
    -  // (one code unit). Highest codepoint in basic multilingual plane and highest
    -  // that JavaScript can represent using \u.
    -  assertSanitizeEncodesTo('\uffff', '%EF%BF%BF');
    -
    -  // Supplementary plane codepoint which UTF-16 and UTF-8 encode to 4 bytes.
    -  // Valid surrogate sequence.
    -  assertSanitizeEncodesTo('\ud800\udc00', '%F0%90%80%80');
    -
    -  // Invalid lead/high surrogate.
    -  assertSanitizeEncodesTo('\udc00', goog.html.SafeUrl.INNOCUOUS_STRING);
    -
    -  // Invalid trail/low surrogate.
    -  assertSanitizeEncodesTo('\ud800\ud800', goog.html.SafeUrl.INNOCUOUS_STRING);
    -}
    -
    -
    -function testSafeUrlSanitize_idempotentForSafeUrlArgument() {
    -  // This goes through percent-encoding.
    -  var safeUrl = goog.html.SafeUrl.sanitize('%11"');
    -  var safeUrl2 = goog.html.SafeUrl.sanitize(safeUrl);
    -  assertEquals(
    -      goog.html.SafeUrl.unwrap(safeUrl), goog.html.SafeUrl.unwrap(safeUrl2));
    -
    -  // This doesn't match the safe prefix, getting converted into an innocuous
    -  // string.
    -  safeUrl = goog.html.SafeUrl.sanitize('disallowed:foo');
    -  safeUrl2 = goog.html.SafeUrl.sanitize(safeUrl);
    -  assertEquals(
    -      goog.html.SafeUrl.unwrap(safeUrl), goog.html.SafeUrl.unwrap(safeUrl2));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/html/silverlight.js b/src/database/third_party/closure-library/closure/goog/html/silverlight.js
    deleted file mode 100644
    index 6aed4e2aa30..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/silverlight.js
    +++ /dev/null
    @@ -1,92 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview SafeHtml factory methods for creating object tags for
    - * loading Silverlight files.
    - */
    -
    -goog.provide('goog.html.silverlight');
    -
    -goog.require('goog.html.SafeHtml');
    -goog.require('goog.html.TrustedResourceUrl');
    -goog.require('goog.html.flash');
    -goog.require('goog.string.Const');
    -
    -
    -/**
    - * Attributes and param tag name attributes not allowed to be overriden
    - * when calling createObjectForSilverlight().
    - *
    - * While values that should be specified as params are probably not
    - * recognized as attributes, we block them anyway just to be sure.
    - * @const {!Array<string>}
    - * @private
    - */
    -goog.html.silverlight.FORBIDDEN_ATTRS_AND_PARAMS_ON_SILVERLIGHT_ = [
    -  'data',  // Always set to a fixed value.
    -  'source',  // Specifies the URL for the Silverlight file.
    -  'type',  // Always set to a fixed value.
    -  'typemustmatch'  // Always set to a fixed value.
    -];
    -
    -
    -/**
    - * Creates a SafeHtml representing an object tag, for loading Silverlight files.
    - *
    - * The following attributes are set to these fixed values:
    - * - data: data:application/x-silverlight-2,
    - * - type: application/x-silverlight-2
    - * - typemustmatch: "" (the empty string, meaning true for a boolean attribute)
    - *
    - * @param {!goog.html.TrustedResourceUrl} source The value of the source param.
    - * @param {!Object<string, string>=} opt_params Mapping used to generate child
    - *     param tags. Each tag has a name and value attribute, as defined in
    - *     mapping. Only names consisting of [a-zA-Z0-9-] are allowed. Value of
    - *     null or undefined causes the param tag to be omitted.
    - * @param {!Object<string, goog.html.SafeHtml.AttributeValue_>=}
    - *     opt_attributes Mapping from other attribute names to their values. Only
    - *     attribute names consisting of [a-zA-Z0-9-] are allowed. Value of null or
    - *     undefined causes the attribute to be omitted.
    - * @return {!goog.html.SafeHtml} The SafeHtml content with the object tag.
    - * @throws {Error} If invalid attribute or param name, or attribute or param
    - *     value is provided. Also if opt_attributes or opt_params contains any of
    - *     the attributes set to fixed values, documented above, or contains source.
    - *
    - */
    -goog.html.silverlight.createObject = function(
    -    source, opt_params, opt_attributes) {
    -  goog.html.flash.verifyKeysNotInMaps(
    -      goog.html.silverlight.FORBIDDEN_ATTRS_AND_PARAMS_ON_SILVERLIGHT_,
    -      opt_attributes,
    -      opt_params);
    -
    -  // We don't set default for Silverlight's EnableHtmlAccess and
    -  // AllowHtmlPopupwindow because their default changes depending on whether
    -  // a file loaded from the same domain.
    -  var paramTags = goog.html.flash.combineParams(
    -      {'source': source}, opt_params);
    -  var fixedAttributes = {
    -    'data': goog.html.TrustedResourceUrl.fromConstant(
    -        goog.string.Const.from('data:application/x-silverlight-2,')),
    -    'type': 'application/x-silverlight-2',
    -    'typemustmatch': ''
    -  };
    -  var attributes = goog.html.SafeHtml.combineAttributes(
    -      fixedAttributes, {}, opt_attributes);
    -
    -  return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse(
    -      'object', attributes, paramTags);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/html/silverlight_test.html b/src/database/third_party/closure-library/closure/goog/html/silverlight_test.html
    deleted file mode 100644
    index 695fd327467..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/silverlight_test.html
    +++ /dev/null
    @@ -1,19 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.html.silverlight</title>
    -<script src="../base.js"></script>
    -<script>
    -goog.require('goog.html.silverlightTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/html/silverlight_test.js b/src/database/third_party/closure-library/closure/goog/html/silverlight_test.js
    deleted file mode 100644
    index b038b212e4e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/silverlight_test.js
    +++ /dev/null
    @@ -1,60 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.html.silverlight.
    - */
    -
    -goog.provide('goog.html.silverlightTest');
    -
    -goog.require('goog.html.SafeHtml');
    -goog.require('goog.html.TrustedResourceUrl');
    -goog.require('goog.html.silverlight');
    -goog.require('goog.string.Const');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.html.silverlightTest');
    -
    -
    -function testCreateObjectForSilverlight() {
    -  var trustedResourceUrl = goog.html.TrustedResourceUrl.fromConstant(
    -      goog.string.Const.from('https://google.com/trusted&'));
    -  assertSameHtml(
    -      '<object data="data:application/x-silverlight-2," ' +
    -          'type="application/x-silverlight-2" typemustmatch="" ' +
    -          'class="test&lt;">' +
    -          '<param name="source" value="https://google.com/trusted&amp;">' +
    -          '<param name="onload" value="onload&lt;">' +
    -          '</object>',
    -      goog.html.silverlight.createObject(
    -          trustedResourceUrl,
    -          {'onload': 'onload<'}, {'class': 'test<'}));
    -
    -  // Cannot override params, case insensitive.
    -  assertThrows(function() {
    -    goog.html.silverlight.createObject(
    -        trustedResourceUrl, {'datA': 'cantdothis'});
    -  });
    -
    -  // Cannot override attributes, case insensitive.
    -  assertThrows(function() {
    -    goog.html.silverlight.createObject(
    -        trustedResourceUrl, {}, {'datA': 'cantdothis'});
    -  });
    -}
    -
    -
    -function assertSameHtml(expected, html) {
    -  assertEquals(expected, goog.html.SafeHtml.unwrap(html));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/html/testing.js b/src/database/third_party/closure-library/closure/goog/html/testing.js
    deleted file mode 100644
    index 882f9832ac7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/testing.js
    +++ /dev/null
    @@ -1,129 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Utilities to create arbitrary values of goog.html types for
    - * testing purposes. These utility methods perform no validation, and the
    - * resulting instances may violate type contracts.
    - *
    - * These methods are useful when types are constructed in a manner where using
    - * the production API is too inconvenient. Please do use the production API
    - * whenever possible; there is value in having tests reflect common usage and it
    - * avoids, by design, non-contract complying instances from being created.
    - */
    -
    -
    -goog.provide('goog.html.testing');
    -goog.setTestOnly();
    -
    -goog.require('goog.html.SafeHtml');
    -goog.require('goog.html.SafeScript');
    -goog.require('goog.html.SafeStyle');
    -goog.require('goog.html.SafeStyleSheet');
    -goog.require('goog.html.SafeUrl');
    -goog.require('goog.html.TrustedResourceUrl');
    -
    -
    -/**
    - * Creates a SafeHtml wrapping the given value. No validation is performed.
    - *
    - * This function is for use in tests only and must never be used in production
    - * code.
    - *
    - * @param {string} html The string to wrap into a SafeHtml.
    - * @param {?goog.i18n.bidi.Dir=} opt_dir The optional directionality of the
    - *     SafeHtml to be constructed. A null or undefined value signifies an
    - *     unknown directionality.
    - * @return {!goog.html.SafeHtml}
    - */
    -goog.html.testing.newSafeHtmlForTest = function(html, opt_dir) {
    -  return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(
    -      html, (opt_dir == undefined ? null : opt_dir));
    -};
    -
    -
    -/**
    - * Creates a SafeScript wrapping the given value. No validation is performed.
    - *
    - * This function is for use in tests only and must never be used in production
    - * code.
    - *
    - * @param {string} script The string to wrap into a SafeScript.
    - * @return {!goog.html.SafeScript}
    - */
    -goog.html.testing.newSafeScriptForTest = function(script) {
    -  return goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse(
    -      script);
    -};
    -
    -
    -/**
    - * Creates a SafeStyle wrapping the given value. No validation is performed.
    - *
    - * This function is for use in tests only and must never be used in production
    - * code.
    - *
    - * @param {string} style String to wrap into a SafeStyle.
    - * @return {!goog.html.SafeStyle}
    - */
    -goog.html.testing.newSafeStyleForTest = function(style) {
    -  return goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(
    -      style);
    -};
    -
    -
    -/**
    - * Creates a SafeStyleSheet wrapping the given value. No validation is
    - * performed.
    - *
    - * This function is for use in tests only and must never be used in production
    - * code.
    - *
    - * @param {string} styleSheet String to wrap into a SafeStyleSheet.
    - * @return {!goog.html.SafeStyleSheet}
    - */
    -goog.html.testing.newSafeStyleSheetForTest = function(styleSheet) {
    -  return goog.html.SafeStyleSheet.
    -      createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(styleSheet);
    -};
    -
    -
    -/**
    - * Creates a SafeUrl wrapping the given value. No validation is performed.
    - *
    - * This function is for use in tests only and must never be used in production
    - * code.
    - *
    - * @param {string} url String to wrap into a SafeUrl.
    - * @return {!goog.html.SafeUrl}
    - */
    -goog.html.testing.newSafeUrlForTest = function(url) {
    -  return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(url);
    -};
    -
    -
    -/**
    - * Creates a TrustedResourceUrl wrapping the given value. No validation is
    - * performed.
    - *
    - * This function is for use in tests only and must never be used in production
    - * code.
    - *
    - * @param {string} url String to wrap into a TrustedResourceUrl.
    - * @return {!goog.html.TrustedResourceUrl}
    - */
    -goog.html.testing.newTrustedResourceUrlForTest = function(url) {
    -  return goog.html.TrustedResourceUrl.
    -      createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(url);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/html/trustedresourceurl.js b/src/database/third_party/closure-library/closure/goog/html/trustedresourceurl.js
    deleted file mode 100644
    index e7c7bf5f646..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/trustedresourceurl.js
    +++ /dev/null
    @@ -1,224 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview The TrustedResourceUrl type and its builders.
    - *
    - * TODO(user): Link to document stating type contract.
    - */
    -
    -goog.provide('goog.html.TrustedResourceUrl');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.i18n.bidi.Dir');
    -goog.require('goog.i18n.bidi.DirectionalString');
    -goog.require('goog.string.Const');
    -goog.require('goog.string.TypedString');
    -
    -
    -
    -/**
    - * A URL which is under application control and from which script, CSS, and
    - * other resources that represent executable code, can be fetched.
    - *
    - * Given that the URL can only be constructed from strings under application
    - * control and is used to load resources, bugs resulting in a malformed URL
    - * should not have a security impact and are likely to be easily detectable
    - * during testing. Given the wide number of non-RFC compliant URLs in use,
    - * stricter validation could prevent some applications from being able to use
    - * this type.
    - *
    - * Instances of this type must be created via the factory method,
    - * ({@code goog.html.TrustedResourceUrl.fromConstant}), and not by invoking its
    - * constructor. The constructor intentionally takes no parameters and the type
    - * is immutable; hence only a default instance corresponding to the empty
    - * string can be obtained via constructor invocation.
    - *
    - * @see goog.html.TrustedResourceUrl#fromConstant
    - * @constructor
    - * @final
    - * @struct
    - * @implements {goog.i18n.bidi.DirectionalString}
    - * @implements {goog.string.TypedString}
    - */
    -goog.html.TrustedResourceUrl = function() {
    -  /**
    -   * The contained value of this TrustedResourceUrl.  The field has a purposely
    -   * ugly name to make (non-compiled) code that attempts to directly access this
    -   * field stand out.
    -   * @private {string}
    -   */
    -  this.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_ = '';
    -
    -  /**
    -   * A type marker used to implement additional run-time type checking.
    -   * @see goog.html.TrustedResourceUrl#unwrap
    -   * @const
    -   * @private
    -   */
    -  this.TRUSTED_RESOURCE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ =
    -      goog.html.TrustedResourceUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_;
    -};
    -
    -
    -/**
    - * @override
    - * @const
    - */
    -goog.html.TrustedResourceUrl.prototype.implementsGoogStringTypedString = true;
    -
    -
    -/**
    - * Returns this TrustedResourceUrl's value as a string.
    - *
    - * IMPORTANT: In code where it is security relevant that an object's type is
    - * indeed {@code TrustedResourceUrl}, use
    - * {@code goog.html.TrustedResourceUrl.unwrap} instead of this method. If in
    - * doubt, assume that it's security relevant. In particular, note that
    - * goog.html functions which return a goog.html type do not guarantee that
    - * the returned instance is of the right type. For example:
    - *
    - * <pre>
    - * var fakeSafeHtml = new String('fake');
    - * fakeSafeHtml.__proto__ = goog.html.SafeHtml.prototype;
    - * var newSafeHtml = goog.html.SafeHtml.htmlEscape(fakeSafeHtml);
    - * // newSafeHtml is just an alias for fakeSafeHtml, it's passed through by
    - * // goog.html.SafeHtml.htmlEscape() as fakeSafeHtml instanceof
    - * // goog.html.SafeHtml.
    - * </pre>
    - *
    - * @see goog.html.TrustedResourceUrl#unwrap
    - * @override
    - */
    -goog.html.TrustedResourceUrl.prototype.getTypedStringValue = function() {
    -  return this.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_;
    -};
    -
    -
    -/**
    - * @override
    - * @const
    - */
    -goog.html.TrustedResourceUrl.prototype.implementsGoogI18nBidiDirectionalString =
    -    true;
    -
    -
    -/**
    - * Returns this URLs directionality, which is always {@code LTR}.
    - * @override
    - */
    -goog.html.TrustedResourceUrl.prototype.getDirection = function() {
    -  return goog.i18n.bidi.Dir.LTR;
    -};
    -
    -
    -if (goog.DEBUG) {
    -  /**
    -   * Returns a debug string-representation of this value.
    -   *
    -   * To obtain the actual string value wrapped in a TrustedResourceUrl, use
    -   * {@code goog.html.TrustedResourceUrl.unwrap}.
    -   *
    -   * @see goog.html.TrustedResourceUrl#unwrap
    -   * @override
    -   */
    -  goog.html.TrustedResourceUrl.prototype.toString = function() {
    -    return 'TrustedResourceUrl{' +
    -        this.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_ + '}';
    -  };
    -}
    -
    -
    -/**
    - * Performs a runtime check that the provided object is indeed a
    - * TrustedResourceUrl object, and returns its value.
    - *
    - * @param {!goog.html.TrustedResourceUrl} trustedResourceUrl The object to
    - *     extract from.
    - * @return {string} The trustedResourceUrl object's contained string, unless
    - *     the run-time type check fails. In that case, {@code unwrap} returns an
    - *     innocuous string, or, if assertions are enabled, throws
    - *     {@code goog.asserts.AssertionError}.
    - */
    -goog.html.TrustedResourceUrl.unwrap = function(trustedResourceUrl) {
    -  // Perform additional Run-time type-checking to ensure that
    -  // trustedResourceUrl is indeed an instance of the expected type.  This
    -  // provides some additional protection against security bugs due to
    -  // application code that disables type checks.
    -  // Specifically, the following checks are performed:
    -  // 1. The object is an instance of the expected type.
    -  // 2. The object is not an instance of a subclass.
    -  // 3. The object carries a type marker for the expected type. "Faking" an
    -  // object requires a reference to the type marker, which has names intended
    -  // to stand out in code reviews.
    -  if (trustedResourceUrl instanceof goog.html.TrustedResourceUrl &&
    -      trustedResourceUrl.constructor === goog.html.TrustedResourceUrl &&
    -      trustedResourceUrl
    -          .TRUSTED_RESOURCE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ ===
    -              goog.html.TrustedResourceUrl
    -                  .TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_) {
    -    return trustedResourceUrl
    -        .privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_;
    -  } else {
    -    goog.asserts.fail('expected object of type TrustedResourceUrl, got \'' +
    -                      trustedResourceUrl + '\'');
    -    return 'type_error:TrustedResourceUrl';
    -
    -  }
    -};
    -
    -
    -/**
    - * Creates a TrustedResourceUrl object from a compile-time constant string.
    - *
    - * Compile-time constant strings are inherently program-controlled and hence
    - * trusted.
    - *
    - * @param {!goog.string.Const} url A compile-time-constant string from which to
    - *     create a TrustedResourceUrl.
    - * @return {!goog.html.TrustedResourceUrl} A TrustedResourceUrl object
    - *     initialized to {@code url}.
    - */
    -goog.html.TrustedResourceUrl.fromConstant = function(url) {
    -  return goog.html.TrustedResourceUrl
    -      .createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(
    -          goog.string.Const.unwrap(url));
    -};
    -
    -
    -/**
    - * Type marker for the TrustedResourceUrl type, used to implement additional
    - * run-time type checking.
    - * @const
    - * @private
    - */
    -goog.html.TrustedResourceUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {};
    -
    -
    -/**
    - * Package-internal utility method to create TrustedResourceUrl instances.
    - *
    - * @param {string} url The string to initialize the TrustedResourceUrl object
    - *     with.
    - * @return {!goog.html.TrustedResourceUrl} The initialized TrustedResourceUrl
    - *     object.
    - * @package
    - */
    -goog.html.TrustedResourceUrl.
    -    createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse = function(url) {
    -  var trustedResourceUrl = new goog.html.TrustedResourceUrl();
    -  trustedResourceUrl.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_ =
    -      url;
    -  return trustedResourceUrl;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/html/trustedresourceurl_test.html b/src/database/third_party/closure-library/closure/goog/html/trustedresourceurl_test.html
    deleted file mode 100644
    index 9c0c6b2f04c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/trustedresourceurl_test.html
    +++ /dev/null
    @@ -1,19 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.html</title>
    -<script src="../base.js"></script>
    -<script>
    -goog.require('goog.html.trustedResourceUrlTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/html/trustedresourceurl_test.js b/src/database/third_party/closure-library/closure/goog/html/trustedresourceurl_test.js
    deleted file mode 100644
    index 151578fd178..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/trustedresourceurl_test.js
    +++ /dev/null
    @@ -1,60 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.html.TrustedResourceUrl and its builders.
    - */
    -
    -goog.provide('goog.html.trustedResourceUrlTest');
    -
    -goog.require('goog.html.TrustedResourceUrl');
    -goog.require('goog.i18n.bidi.Dir');
    -goog.require('goog.string.Const');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.html.trustedResourceUrlTest');
    -
    -
    -function testTrustedResourceUrl() {
    -  var url = 'javascript:trusted();';
    -  var trustedResourceUrl = goog.html.TrustedResourceUrl.fromConstant(
    -      goog.string.Const.from(url));
    -  var extracted = goog.html.TrustedResourceUrl.unwrap(trustedResourceUrl);
    -  assertEquals(url, extracted);
    -  assertEquals(url, trustedResourceUrl.getTypedStringValue());
    -  assertEquals(
    -      'TrustedResourceUrl{javascript:trusted();}', String(trustedResourceUrl));
    -
    -  // URLs are always LTR.
    -  assertEquals(goog.i18n.bidi.Dir.LTR, trustedResourceUrl.getDirection());
    -
    -  // Interface markers are present.
    -  assertTrue(trustedResourceUrl.implementsGoogStringTypedString);
    -  assertTrue(trustedResourceUrl.implementsGoogI18nBidiDirectionalString);
    -}
    -
    -
    -/** @suppress {checkTypes} */
    -function testUnwrap() {
    -  var evil = {};
    -  evil.trustedResourceUrlValueWithSecurityContract_googHtmlSecurityPrivate_ =
    -      '<script>evil()</script';
    -  evil.TRUSTED_RESOURCE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {};
    -
    -  var exception = assertThrows(function() {
    -    goog.html.TrustedResourceUrl.unwrap(evil);
    -  });
    -  assertTrue(exception.message.indexOf(
    -      'expected object of type TrustedResourceUrl') > 0);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/html/uncheckedconversions.js b/src/database/third_party/closure-library/closure/goog/html/uncheckedconversions.js
    deleted file mode 100644
    index a1a5a9a7e48..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/uncheckedconversions.js
    +++ /dev/null
    @@ -1,231 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unchecked conversions to create values of goog.html types from
    - * plain strings.  Use of these functions could potentially result in instances
    - * of goog.html types that violate their type contracts, and hence result in
    - * security vulnerabilties.
    - *
    - * Therefore, all uses of the methods herein must be carefully security
    - * reviewed.  Avoid use of the methods in this file whenever possible; instead
    - * prefer to create instances of goog.html types using inherently safe builders
    - * or template systems.
    - *
    - *
    - * @visibility {//closure/goog/html:approved_for_unchecked_conversion}
    - * @visibility {//closure/goog/bin/sizetests:__pkg__}
    - */
    -
    -
    -goog.provide('goog.html.uncheckedconversions');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.html.SafeHtml');
    -goog.require('goog.html.SafeScript');
    -goog.require('goog.html.SafeStyle');
    -goog.require('goog.html.SafeStyleSheet');
    -goog.require('goog.html.SafeUrl');
    -goog.require('goog.html.TrustedResourceUrl');
    -goog.require('goog.string');
    -goog.require('goog.string.Const');
    -
    -
    -/**
    - * Performs an "unchecked conversion" to SafeHtml from a plain string that is
    - * known to satisfy the SafeHtml type contract.
    - *
    - * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure
    - * that the value of {@code html} satisfies the SafeHtml type contract in all
    - * possible program states.
    - *
    - *
    - * @param {!goog.string.Const} justification A constant string explaining why
    - *     this use of this method is safe. May include a security review ticket
    - *     number.
    - * @param {string} html A string that is claimed to adhere to the SafeHtml
    - *     contract.
    - * @param {?goog.i18n.bidi.Dir=} opt_dir The optional directionality of the
    - *     SafeHtml to be constructed. A null or undefined value signifies an
    - *     unknown directionality.
    - * @return {!goog.html.SafeHtml} The value of html, wrapped in a SafeHtml
    - *     object.
    - * @suppress {visibility} For access to SafeHtml.create...  Note that this
    - *     use is appropriate since this method is intended to be "package private"
    - *     withing goog.html.  DO NOT call SafeHtml.create... from outside this
    - *     package; use appropriate wrappers instead.
    - */
    -goog.html.uncheckedconversions.safeHtmlFromStringKnownToSatisfyTypeContract =
    -    function(justification, html, opt_dir) {
    -  // unwrap() called inside an assert so that justification can be optimized
    -  // away in production code.
    -  goog.asserts.assertString(goog.string.Const.unwrap(justification),
    -                            'must provide justification');
    -  goog.asserts.assert(
    -      !goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(justification)),
    -      'must provide non-empty justification');
    -  return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(
    -      html, opt_dir || null);
    -};
    -
    -
    -/**
    - * Performs an "unchecked conversion" to SafeScript from a plain string that is
    - * known to satisfy the SafeScript type contract.
    - *
    - * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure
    - * that the value of {@code script} satisfies the SafeScript type contract in
    - * all possible program states.
    - *
    - *
    - * @param {!goog.string.Const} justification A constant string explaining why
    - *     this use of this method is safe. May include a security review ticket
    - *     number.
    - * @param {string} script The string to wrap as a SafeScript.
    - * @return {!goog.html.SafeScript} The value of {@code script}, wrapped in a
    - *     SafeScript object.
    - */
    -goog.html.uncheckedconversions.safeScriptFromStringKnownToSatisfyTypeContract =
    -    function(justification, script) {
    -  // unwrap() called inside an assert so that justification can be optimized
    -  // away in production code.
    -  goog.asserts.assertString(goog.string.Const.unwrap(justification),
    -                            'must provide justification');
    -  goog.asserts.assert(
    -      !goog.string.isEmpty(goog.string.Const.unwrap(justification)),
    -      'must provide non-empty justification');
    -  return goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse(
    -      script);
    -};
    -
    -
    -/**
    - * Performs an "unchecked conversion" to SafeStyle from a plain string that is
    - * known to satisfy the SafeStyle type contract.
    - *
    - * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure
    - * that the value of {@code style} satisfies the SafeUrl type contract in all
    - * possible program states.
    - *
    - *
    - * @param {!goog.string.Const} justification A constant string explaining why
    - *     this use of this method is safe. May include a security review ticket
    - *     number.
    - * @param {string} style The string to wrap as a SafeStyle.
    - * @return {!goog.html.SafeStyle} The value of {@code style}, wrapped in a
    - *     SafeStyle object.
    - */
    -goog.html.uncheckedconversions.safeStyleFromStringKnownToSatisfyTypeContract =
    -    function(justification, style) {
    -  // unwrap() called inside an assert so that justification can be optimized
    -  // away in production code.
    -  goog.asserts.assertString(goog.string.Const.unwrap(justification),
    -                            'must provide justification');
    -  goog.asserts.assert(
    -      !goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(justification)),
    -      'must provide non-empty justification');
    -  return goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(
    -      style);
    -};
    -
    -
    -/**
    - * Performs an "unchecked conversion" to SafeStyleSheet from a plain string
    - * that is known to satisfy the SafeStyleSheet type contract.
    - *
    - * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure
    - * that the value of {@code styleSheet} satisfies the SafeUrl type contract in
    - * all possible program states.
    - *
    - *
    - * @param {!goog.string.Const} justification A constant string explaining why
    - *     this use of this method is safe. May include a security review ticket
    - *     number.
    - * @param {string} styleSheet The string to wrap as a SafeStyleSheet.
    - * @return {!goog.html.SafeStyleSheet} The value of {@code styleSheet}, wrapped
    - *     in a SafeStyleSheet object.
    - */
    -goog.html.uncheckedconversions.
    -    safeStyleSheetFromStringKnownToSatisfyTypeContract =
    -    function(justification, styleSheet) {
    -  // unwrap() called inside an assert so that justification can be optimized
    -  // away in production code.
    -  goog.asserts.assertString(goog.string.Const.unwrap(justification),
    -                            'must provide justification');
    -  goog.asserts.assert(
    -      !goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(justification)),
    -      'must provide non-empty justification');
    -  return goog.html.SafeStyleSheet.
    -      createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(styleSheet);
    -};
    -
    -
    -/**
    - * Performs an "unchecked conversion" to SafeUrl from a plain string that is
    - * known to satisfy the SafeUrl type contract.
    - *
    - * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure
    - * that the value of {@code url} satisfies the SafeUrl type contract in all
    - * possible program states.
    - *
    - *
    - * @param {!goog.string.Const} justification A constant string explaining why
    - *     this use of this method is safe. May include a security review ticket
    - *     number.
    - * @param {string} url The string to wrap as a SafeUrl.
    - * @return {!goog.html.SafeUrl} The value of {@code url}, wrapped in a SafeUrl
    - *     object.
    - */
    -goog.html.uncheckedconversions.safeUrlFromStringKnownToSatisfyTypeContract =
    -    function(justification, url) {
    -  // unwrap() called inside an assert so that justification can be optimized
    -  // away in production code.
    -  goog.asserts.assertString(goog.string.Const.unwrap(justification),
    -                            'must provide justification');
    -  goog.asserts.assert(
    -      !goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(justification)),
    -      'must provide non-empty justification');
    -  return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(url);
    -};
    -
    -
    -/**
    - * Performs an "unchecked conversion" to TrustedResourceUrl from a plain string
    - * that is known to satisfy the TrustedResourceUrl type contract.
    - *
    - * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure
    - * that the value of {@code url} satisfies the TrustedResourceUrl type contract
    - * in all possible program states.
    - *
    - *
    - * @param {!goog.string.Const} justification A constant string explaining why
    - *     this use of this method is safe. May include a security review ticket
    - *     number.
    - * @param {string} url The string to wrap as a TrustedResourceUrl.
    - * @return {!goog.html.TrustedResourceUrl} The value of {@code url}, wrapped in
    - *     a TrustedResourceUrl object.
    - */
    -goog.html.uncheckedconversions.
    -    trustedResourceUrlFromStringKnownToSatisfyTypeContract =
    -    function(justification, url) {
    -  // unwrap() called inside an assert so that justification can be optimized
    -  // away in production code.
    -  goog.asserts.assertString(goog.string.Const.unwrap(justification),
    -                            'must provide justification');
    -  goog.asserts.assert(
    -      !goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(justification)),
    -      'must provide non-empty justification');
    -  return goog.html.TrustedResourceUrl.
    -      createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(url);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/html/uncheckedconversions_test.html b/src/database/third_party/closure-library/closure/goog/html/uncheckedconversions_test.html
    deleted file mode 100644
    index b42f1da4992..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/uncheckedconversions_test.html
    +++ /dev/null
    @@ -1,19 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.html</title>
    -<script src="../base.js"></script>
    -<script>
    -goog.require('goog.html.uncheckedconversionsTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/html/uncheckedconversions_test.js b/src/database/third_party/closure-library/closure/goog/html/uncheckedconversions_test.js
    deleted file mode 100644
    index b06e98372d2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/uncheckedconversions_test.js
    +++ /dev/null
    @@ -1,159 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.html.uncheckedconversions.
    - */
    -
    -goog.provide('goog.html.uncheckedconversionsTest');
    -
    -goog.require('goog.html.SafeHtml');
    -goog.require('goog.html.SafeScript');
    -goog.require('goog.html.SafeStyle');
    -goog.require('goog.html.SafeStyleSheet');
    -goog.require('goog.html.SafeUrl');
    -goog.require('goog.html.TrustedResourceUrl');
    -goog.require('goog.html.uncheckedconversions');
    -goog.require('goog.i18n.bidi.Dir');
    -goog.require('goog.string.Const');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.html.uncheckedconversionsTest');
    -
    -
    -function testSafeHtmlFromStringKnownToSatisfyTypeContract_ok() {
    -  var html = '<div>irrelevant</div>';
    -  var safeHtml = goog.html.uncheckedconversions.
    -      safeHtmlFromStringKnownToSatisfyTypeContract(
    -          goog.string.Const.from('Test'),
    -          html,
    -          goog.i18n.bidi.Dir.LTR);
    -  assertEquals(html, goog.html.SafeHtml.unwrap(safeHtml));
    -  assertEquals(goog.i18n.bidi.Dir.LTR, safeHtml.getDirection());
    -}
    -
    -
    -function testSafeHtmlFromStringKnownToSatisfyTypeContract_error() {
    -  assertThrows(function() {
    -    goog.html.uncheckedconversions.
    -        safeHtmlFromStringKnownToSatisfyTypeContract(
    -            goog.string.Const.from(''),
    -            'irrelevant');
    -  });
    -}
    -
    -
    -function testSafeScriptFromStringKnownToSatisfyTypeContract_ok() {
    -  var script = 'functionCall(\'irrelevant\');';
    -  var safeScript = goog.html.uncheckedconversions.
    -      safeScriptFromStringKnownToSatisfyTypeContract(
    -          goog.string.Const.from(
    -              'Safe because value is constant. Security review: b/7685625.'),
    -          script);
    -  assertEquals(script, goog.html.SafeScript.unwrap(safeScript));
    -}
    -
    -
    -function testSafeScriptFromStringKnownToSatisfyTypeContract_error() {
    -  assertThrows(function() {
    -    goog.html.uncheckedconversions.
    -        safeScriptFromStringKnownToSatisfyTypeContract(
    -            goog.string.Const.from(''),
    -            'irrelevant');
    -  });
    -}
    -
    -
    -function testSafeStyleFromStringKnownToSatisfyTypeContract_ok() {
    -  var style = 'P.special { color:red ; }';
    -  var safeStyle = goog.html.uncheckedconversions.
    -      safeStyleFromStringKnownToSatisfyTypeContract(
    -          goog.string.Const.from(
    -              'Safe because value is constant. Security review: b/7685625.'),
    -          style);
    -  assertEquals(style, goog.html.SafeStyle.unwrap(safeStyle));
    -}
    -
    -
    -function testSafeStyleFromStringKnownToSatisfyTypeContract_error() {
    -  assertThrows(function() {
    -    goog.html.uncheckedconversions.
    -        safeStyleFromStringKnownToSatisfyTypeContract(
    -            goog.string.Const.from(''),
    -            'irrelevant');
    -  });
    -}
    -
    -
    -function testSafeStyleSheetFromStringKnownToSatisfyTypeContract_ok() {
    -  var styleSheet = 'P.special { color:red ; }';
    -  var safeStyleSheet = goog.html.uncheckedconversions.
    -      safeStyleSheetFromStringKnownToSatisfyTypeContract(
    -          goog.string.Const.from(
    -              'Safe because value is constant. Security review: b/7685625.'),
    -          styleSheet);
    -  assertEquals(styleSheet, goog.html.SafeStyleSheet.unwrap(safeStyleSheet));
    -}
    -
    -
    -function testSafeStyleSheetFromStringKnownToSatisfyTypeContract_error() {
    -  assertThrows(function() {
    -    goog.html.uncheckedconversions.
    -        safeStyleSheetFromStringKnownToSatisfyTypeContract(
    -            goog.string.Const.from(''),
    -            'irrelevant');
    -  });
    -}
    -
    -
    -function testSafeUrlFromStringKnownToSatisfyTypeContract_ok() {
    -  var url = 'http://www.irrelevant.com';
    -  var safeUrl = goog.html.uncheckedconversions.
    -      safeUrlFromStringKnownToSatisfyTypeContract(
    -          goog.string.Const.from(
    -              'Safe because value is constant. Security review: b/7685625.'),
    -              url);
    -  assertEquals(url, goog.html.SafeUrl.unwrap(safeUrl));
    -}
    -
    -
    -function testSafeUrlFromStringKnownToSatisfyTypeContract_error() {
    -  assertThrows(function() {
    -    goog.html.uncheckedconversions.
    -        safeUrlFromStringKnownToSatisfyTypeContract(
    -            goog.string.Const.from(''),
    -            'http://irrelevant.com');
    -  });
    -}
    -
    -
    -function testTrustedResourceUrlFromStringKnownToSatisfyTypeContract_ok() {
    -  var url = 'http://www.irrelevant.com';
    -  var trustedResourceUrl = goog.html.uncheckedconversions.
    -      trustedResourceUrlFromStringKnownToSatisfyTypeContract(
    -          goog.string.Const.from(
    -              'Safe because value is constant. Security review: b/7685625.'),
    -              url);
    -  assertEquals(url, goog.html.TrustedResourceUrl.unwrap(trustedResourceUrl));
    -}
    -
    -
    -function testTrustedResourceFromStringKnownToSatisfyTypeContract_error() {
    -  assertThrows(function() {
    -    goog.html.uncheckedconversions.
    -        trustedResourceUrlFromStringKnownToSatisfyTypeContract(
    -            goog.string.Const.from(''),
    -            'http://irrelevant.com');
    -  });
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/html/utils.js b/src/database/third_party/closure-library/closure/goog/html/utils.js
    deleted file mode 100644
    index c54381bf28a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/utils.js
    +++ /dev/null
    @@ -1,67 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview HTML processing utilities for HTML in string form.
    - */
    -
    -goog.provide('goog.html.utils');
    -
    -goog.require('goog.string');
    -
    -
    -/**
    - * Extracts plain text from HTML.
    - *
    - * This behaves similarly to extracting textContent from a hypothetical DOM
    - * element containing the specified HTML.  Block-level elements such as div are
    - * surrounded with whitespace, but inline elements are not.  Span is treated as
    - * a block level element because it is often used as a container.  Breaking
    - * spaces are compressed and trimmed.
    - *
    - * @param {string} value The input HTML to have tags removed.
    - * @return {string} The plain text of value without tags, HTML comments, or
    - *     other non-text content.  Does NOT return safe HTML!
    - */
    -goog.html.utils.stripHtmlTags = function(value) {
    -  // TODO(user): Make a version that extracts text attributes such as alt.
    -  return goog.string.unescapeEntities(goog.string.trim(value.replace(
    -      goog.html.utils.HTML_TAG_REGEX_, function(fullMatch, tagName) {
    -        return goog.html.utils.INLINE_HTML_TAG_REGEX_.test(tagName) ? '' : ' ';
    -      }).
    -      replace(/[\t\n ]+/g, ' ')));
    -};
    -
    -
    -/**
    - * Matches all tags that do not require extra space.
    - *
    - * @const
    - * @private {RegExp}
    - */
    -goog.html.utils.INLINE_HTML_TAG_REGEX_ =
    -    /^(?:abbr|acronym|address|b|em|i|small|strong|su[bp]|u)$/i;
    -
    -
    -/**
    - * Matches all tags, HTML comments, and DOCTYPEs in tag soup HTML.
    - * By removing these, and replacing any '<' or '>' characters with
    - * entities we guarantee that the result can be embedded into
    - * an attribute without introducing a tag boundary.
    - *
    - * @private {RegExp}
    - * @const
    - */
    -goog.html.utils.HTML_TAG_REGEX_ = /<[!\/]?([a-z0-9]+)([\/ ][^>]*)?>/gi;
    diff --git a/src/database/third_party/closure-library/closure/goog/html/utils_test.html b/src/database/third_party/closure-library/closure/goog/html/utils_test.html
    deleted file mode 100644
    index 7aa69815efb..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/utils_test.html
    +++ /dev/null
    @@ -1,19 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.html.utils</title>
    -<script src="../base.js"></script>
    -<script>
    -goog.require('goog.html.UtilsTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/html/utils_test.js b/src/database/third_party/closure-library/closure/goog/html/utils_test.js
    deleted file mode 100644
    index c9173f702a7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/html/utils_test.js
    +++ /dev/null
    @@ -1,122 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.html.util.
    - */
    -
    -goog.provide('goog.html.UtilsTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.html.utils');
    -goog.require('goog.object');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.html.UtilsTest');
    -
    -
    -var FAILURE_MESSAGE = 'Failed to strip all HTML.';
    -var STRIP = 'Hello world!';
    -var result;
    -
    -
    -function tearDown() {
    -  result = null;
    -}
    -
    -
    -function testStripAllHtmlTagsSingle() {
    -  goog.object.forEach(goog.dom.TagName, function(tag) {
    -    result = goog.html.utils.stripHtmlTags(makeHtml_(tag, STRIP));
    -    assertEquals(FAILURE_MESSAGE, STRIP, result);
    -  });
    -}
    -
    -
    -function testStripAllHtmlTagsAttribute() {
    -  goog.object.forEach(goog.dom.TagName, function(tag) {
    -    result = goog.html.utils.stripHtmlTags(makeHtml_(tag, STRIP, 1, 0, 'a'));
    -    assertEquals(FAILURE_MESSAGE, STRIP, result);
    -  });
    -}
    -
    -
    -function testStripAllHtmlTagsDouble() {
    -  var tag1 = goog.dom.TagName.B;
    -  var tag2 = goog.dom.TagName.DIV;
    -  result = goog.html.utils.stripHtmlTags(makeHtml_(tag1, STRIP, 2));
    -  assertEquals(FAILURE_MESSAGE, STRIP + STRIP, result);
    -  result = goog.html.utils.stripHtmlTags(makeHtml_(tag2, STRIP, 2));
    -  assertEquals(FAILURE_MESSAGE, STRIP + ' ' + STRIP, result);
    -}
    -
    -
    -function testComplex() {
    -  var html = '<h1 id=\"life\">Life at Google</h1>' +
    -      '<p>Read and interact with the information below to learn about ' +
    -      'life at <u>Google</u>.</p>' +
    -      '<h2 id=\"food\">Food at Google</h2>' +
    -      '<p>Google has <em>the best food in the world</em>.</p>' +
    -      '<h2 id=\"transportation\">Transportation at Google</h2>' +
    -      '<p>Google provides <i>free transportation</i>.</p>' +
    -      // Some text with symbols to make sure that it does not get stripped
    -      '<3i><x>\n-10<x<10 3cat < 3dog &amp;&lt;&gt;&quot;';
    -  result = goog.html.utils.stripHtmlTags(html);
    -  var expected = 'Life at Google ' +
    -      'Read and interact with the information below to learn about ' +
    -      'life at Google. ' +
    -      'Food at Google ' +
    -      'Google has the best food in the world. ' +
    -      'Transportation at Google ' +
    -      'Google provides free transportation. ' +
    -      '-10<x<10 3cat < 3dog &<>\"';
    -  assertEquals(FAILURE_MESSAGE, expected, result);
    -}
    -
    -
    -function testInteresting() {
    -  result = goog.html.utils.stripHtmlTags(
    -      '<img/src="bogus"onerror=alert(13) style="display:none">');
    -  assertEquals(FAILURE_MESSAGE, '', result);
    -  result = goog.html.utils.stripHtmlTags(
    -      '<img o\'reilly blob src=bogus onerror=alert(1337)>');
    -  assertEquals(FAILURE_MESSAGE, '', result);
    -}
    -
    -
    -/**
    - * Constructs the HTML of an element from the given tag and content.
    - * @param {goog.dom.TagName} tag The HTML tagName for the element.
    - * @param {string} content The content.
    - * @param {number=} opt_copies Optional number of copies to make.
    - * @param {number=} opt_tabIndex Optional tabIndex to give the element.
    - * @param {string=} opt_id Optional id to give the element.
    - * @return {string} The HTML of an element from the given tag and content.
    - */
    -function makeHtml_(tag, content, opt_copies, opt_tabIndex, opt_id) {
    -  var html = ['<' + tag, '>' + content + '</' + tag + '>'];
    -  if (goog.isNumber(opt_tabIndex)) {
    -    goog.array.insertAt(html, ' tabIndex=\"' + opt_tabIndex + '\"', 1);
    -  }
    -  if (goog.isString(opt_id)) {
    -    goog.array.insertAt(html, ' id=\"' + opt_id + '\"', 1);
    -  }
    -  html = html.join('');
    -  var array = [];
    -  for (var i = 0, length = opt_copies || 1; i < length; i++) {
    -    array[i] = html;
    -  }
    -  return array.join('');
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/bidi.js b/src/database/third_party/closure-library/closure/goog/i18n/bidi.js
    deleted file mode 100644
    index 771ea3be27e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/bidi.js
    +++ /dev/null
    @@ -1,877 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Utility functions for supporting Bidi issues.
    - */
    -
    -
    -/**
    - * Namespace for bidi supporting functions.
    - */
    -goog.provide('goog.i18n.bidi');
    -goog.provide('goog.i18n.bidi.Dir');
    -goog.provide('goog.i18n.bidi.DirectionalString');
    -goog.provide('goog.i18n.bidi.Format');
    -
    -
    -/**
    - * @define {boolean} FORCE_RTL forces the {@link goog.i18n.bidi.IS_RTL} constant
    - * to say that the current locale is a RTL locale.  This should only be used
    - * if you want to override the default behavior for deciding whether the
    - * current locale is RTL or not.
    - *
    - * {@see goog.i18n.bidi.IS_RTL}
    - */
    -goog.define('goog.i18n.bidi.FORCE_RTL', false);
    -
    -
    -/**
    - * Constant that defines whether or not the current locale is a RTL locale.
    - * If {@link goog.i18n.bidi.FORCE_RTL} is not true, this constant will default
    - * to check that {@link goog.LOCALE} is one of a few major RTL locales.
    - *
    - * <p>This is designed to be a maximally efficient compile-time constant. For
    - * example, for the default goog.LOCALE, compiling
    - * "if (goog.i18n.bidi.IS_RTL) alert('rtl') else {}" should produce no code. It
    - * is this design consideration that limits the implementation to only
    - * supporting a few major RTL locales, as opposed to the broader repertoire of
    - * something like goog.i18n.bidi.isRtlLanguage.
    - *
    - * <p>Since this constant refers to the directionality of the locale, it is up
    - * to the caller to determine if this constant should also be used for the
    - * direction of the UI.
    - *
    - * {@see goog.LOCALE}
    - *
    - * @type {boolean}
    - *
    - * TODO(user): write a test that checks that this is a compile-time constant.
    - */
    -goog.i18n.bidi.IS_RTL = goog.i18n.bidi.FORCE_RTL ||
    -    (
    -        (goog.LOCALE.substring(0, 2).toLowerCase() == 'ar' ||
    -         goog.LOCALE.substring(0, 2).toLowerCase() == 'fa' ||
    -         goog.LOCALE.substring(0, 2).toLowerCase() == 'he' ||
    -         goog.LOCALE.substring(0, 2).toLowerCase() == 'iw' ||
    -         goog.LOCALE.substring(0, 2).toLowerCase() == 'ps' ||
    -         goog.LOCALE.substring(0, 2).toLowerCase() == 'sd' ||
    -         goog.LOCALE.substring(0, 2).toLowerCase() == 'ug' ||
    -         goog.LOCALE.substring(0, 2).toLowerCase() == 'ur' ||
    -         goog.LOCALE.substring(0, 2).toLowerCase() == 'yi') &&
    -        (goog.LOCALE.length == 2 ||
    -         goog.LOCALE.substring(2, 3) == '-' ||
    -         goog.LOCALE.substring(2, 3) == '_')
    -    ) || (
    -        goog.LOCALE.length >= 3 &&
    -        goog.LOCALE.substring(0, 3).toLowerCase() == 'ckb' &&
    -        (goog.LOCALE.length == 3 ||
    -         goog.LOCALE.substring(3, 4) == '-' ||
    -         goog.LOCALE.substring(3, 4) == '_')
    -    );
    -
    -
    -/**
    - * Unicode formatting characters and directionality string constants.
    - * @enum {string}
    - */
    -goog.i18n.bidi.Format = {
    -  /** Unicode "Left-To-Right Embedding" (LRE) character. */
    -  LRE: '\u202A',
    -  /** Unicode "Right-To-Left Embedding" (RLE) character. */
    -  RLE: '\u202B',
    -  /** Unicode "Pop Directional Formatting" (PDF) character. */
    -  PDF: '\u202C',
    -  /** Unicode "Left-To-Right Mark" (LRM) character. */
    -  LRM: '\u200E',
    -  /** Unicode "Right-To-Left Mark" (RLM) character. */
    -  RLM: '\u200F'
    -};
    -
    -
    -/**
    - * Directionality enum.
    - * @enum {number}
    - */
    -goog.i18n.bidi.Dir = {
    -  /**
    -   * Left-to-right.
    -   */
    -  LTR: 1,
    -
    -  /**
    -   * Right-to-left.
    -   */
    -  RTL: -1,
    -
    -  /**
    -   * Neither left-to-right nor right-to-left.
    -   */
    -  NEUTRAL: 0
    -};
    -
    -
    -/**
    - * 'right' string constant.
    - * @type {string}
    - */
    -goog.i18n.bidi.RIGHT = 'right';
    -
    -
    -/**
    - * 'left' string constant.
    - * @type {string}
    - */
    -goog.i18n.bidi.LEFT = 'left';
    -
    -
    -/**
    - * 'left' if locale is RTL, 'right' if not.
    - * @type {string}
    - */
    -goog.i18n.bidi.I18N_RIGHT = goog.i18n.bidi.IS_RTL ? goog.i18n.bidi.LEFT :
    -    goog.i18n.bidi.RIGHT;
    -
    -
    -/**
    - * 'right' if locale is RTL, 'left' if not.
    - * @type {string}
    - */
    -goog.i18n.bidi.I18N_LEFT = goog.i18n.bidi.IS_RTL ? goog.i18n.bidi.RIGHT :
    -    goog.i18n.bidi.LEFT;
    -
    -
    -/**
    - * Convert a directionality given in various formats to a goog.i18n.bidi.Dir
    - * constant. Useful for interaction with different standards of directionality
    - * representation.
    - *
    - * @param {goog.i18n.bidi.Dir|number|boolean|null} givenDir Directionality given
    - *     in one of the following formats:
    - *     1. A goog.i18n.bidi.Dir constant.
    - *     2. A number (positive = LTR, negative = RTL, 0 = neutral).
    - *     3. A boolean (true = RTL, false = LTR).
    - *     4. A null for unknown directionality.
    - * @param {boolean=} opt_noNeutral Whether a givenDir of zero or
    - *     goog.i18n.bidi.Dir.NEUTRAL should be treated as null, i.e. unknown, in
    - *     order to preserve legacy behavior.
    - * @return {?goog.i18n.bidi.Dir} A goog.i18n.bidi.Dir constant matching the
    - *     given directionality. If given null, returns null (i.e. unknown).
    - */
    -goog.i18n.bidi.toDir = function(givenDir, opt_noNeutral) {
    -  if (typeof givenDir == 'number') {
    -    // This includes the non-null goog.i18n.bidi.Dir case.
    -    return givenDir > 0 ? goog.i18n.bidi.Dir.LTR :
    -        givenDir < 0 ? goog.i18n.bidi.Dir.RTL :
    -        opt_noNeutral ? null : goog.i18n.bidi.Dir.NEUTRAL;
    -  } else if (givenDir == null) {
    -    return null;
    -  } else {
    -    // Must be typeof givenDir == 'boolean'.
    -    return givenDir ? goog.i18n.bidi.Dir.RTL : goog.i18n.bidi.Dir.LTR;
    -  }
    -};
    -
    -
    -/**
    - * A practical pattern to identify strong LTR characters. This pattern is not
    - * theoretically correct according to the Unicode standard. It is simplified for
    - * performance and small code size.
    - * @type {string}
    - * @private
    - */
    -goog.i18n.bidi.ltrChars_ =
    -    'A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02B8\u0300-\u0590\u0800-\u1FFF' +
    -    '\u200E\u2C00-\uFB1C\uFE00-\uFE6F\uFEFD-\uFFFF';
    -
    -
    -/**
    - * A practical pattern to identify strong RTL character. This pattern is not
    - * theoretically correct according to the Unicode standard. It is simplified
    - * for performance and small code size.
    - * @type {string}
    - * @private
    - */
    -goog.i18n.bidi.rtlChars_ = '\u0591-\u07FF\u200F\uFB1D-\uFDFF\uFE70-\uFEFC';
    -
    -
    -/**
    - * Simplified regular expression for an HTML tag (opening or closing) or an HTML
    - * escape. We might want to skip over such expressions when estimating the text
    - * directionality.
    - * @type {RegExp}
    - * @private
    - */
    -goog.i18n.bidi.htmlSkipReg_ = /<[^>]*>|&[^;]+;/g;
    -
    -
    -/**
    - * Returns the input text with spaces instead of HTML tags or HTML escapes, if
    - * opt_isStripNeeded is true. Else returns the input as is.
    - * Useful for text directionality estimation.
    - * Note: the function should not be used in other contexts; it is not 100%
    - * correct, but rather a good-enough implementation for directionality
    - * estimation purposes.
    - * @param {string} str The given string.
    - * @param {boolean=} opt_isStripNeeded Whether to perform the stripping.
    - *     Default: false (to retain consistency with calling functions).
    - * @return {string} The given string cleaned of HTML tags / escapes.
    - * @private
    - */
    -goog.i18n.bidi.stripHtmlIfNeeded_ = function(str, opt_isStripNeeded) {
    -  return opt_isStripNeeded ? str.replace(goog.i18n.bidi.htmlSkipReg_, '') :
    -      str;
    -};
    -
    -
    -/**
    - * Regular expression to check for RTL characters.
    - * @type {RegExp}
    - * @private
    - */
    -goog.i18n.bidi.rtlCharReg_ = new RegExp('[' + goog.i18n.bidi.rtlChars_ + ']');
    -
    -
    -/**
    - * Regular expression to check for LTR characters.
    - * @type {RegExp}
    - * @private
    - */
    -goog.i18n.bidi.ltrCharReg_ = new RegExp('[' + goog.i18n.bidi.ltrChars_ + ']');
    -
    -
    -/**
    - * Test whether the given string has any RTL characters in it.
    - * @param {string} str The given string that need to be tested.
    - * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped.
    - *     Default: false.
    - * @return {boolean} Whether the string contains RTL characters.
    - */
    -goog.i18n.bidi.hasAnyRtl = function(str, opt_isHtml) {
    -  return goog.i18n.bidi.rtlCharReg_.test(goog.i18n.bidi.stripHtmlIfNeeded_(
    -      str, opt_isHtml));
    -};
    -
    -
    -/**
    - * Test whether the given string has any RTL characters in it.
    - * @param {string} str The given string that need to be tested.
    - * @return {boolean} Whether the string contains RTL characters.
    - * @deprecated Use hasAnyRtl.
    - */
    -goog.i18n.bidi.hasRtlChar = goog.i18n.bidi.hasAnyRtl;
    -
    -
    -/**
    - * Test whether the given string has any LTR characters in it.
    - * @param {string} str The given string that need to be tested.
    - * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped.
    - *     Default: false.
    - * @return {boolean} Whether the string contains LTR characters.
    - */
    -goog.i18n.bidi.hasAnyLtr = function(str, opt_isHtml) {
    -  return goog.i18n.bidi.ltrCharReg_.test(goog.i18n.bidi.stripHtmlIfNeeded_(
    -      str, opt_isHtml));
    -};
    -
    -
    -/**
    - * Regular expression pattern to check if the first character in the string
    - * is LTR.
    - * @type {RegExp}
    - * @private
    - */
    -goog.i18n.bidi.ltrRe_ = new RegExp('^[' + goog.i18n.bidi.ltrChars_ + ']');
    -
    -
    -/**
    - * Regular expression pattern to check if the first character in the string
    - * is RTL.
    - * @type {RegExp}
    - * @private
    - */
    -goog.i18n.bidi.rtlRe_ = new RegExp('^[' + goog.i18n.bidi.rtlChars_ + ']');
    -
    -
    -/**
    - * Check if the first character in the string is RTL or not.
    - * @param {string} str The given string that need to be tested.
    - * @return {boolean} Whether the first character in str is an RTL char.
    - */
    -goog.i18n.bidi.isRtlChar = function(str) {
    -  return goog.i18n.bidi.rtlRe_.test(str);
    -};
    -
    -
    -/**
    - * Check if the first character in the string is LTR or not.
    - * @param {string} str The given string that need to be tested.
    - * @return {boolean} Whether the first character in str is an LTR char.
    - */
    -goog.i18n.bidi.isLtrChar = function(str) {
    -  return goog.i18n.bidi.ltrRe_.test(str);
    -};
    -
    -
    -/**
    - * Check if the first character in the string is neutral or not.
    - * @param {string} str The given string that need to be tested.
    - * @return {boolean} Whether the first character in str is a neutral char.
    - */
    -goog.i18n.bidi.isNeutralChar = function(str) {
    -  return !goog.i18n.bidi.isLtrChar(str) && !goog.i18n.bidi.isRtlChar(str);
    -};
    -
    -
    -/**
    - * Regular expressions to check if a piece of text is of LTR directionality
    - * on first character with strong directionality.
    - * @type {RegExp}
    - * @private
    - */
    -goog.i18n.bidi.ltrDirCheckRe_ = new RegExp(
    -    '^[^' + goog.i18n.bidi.rtlChars_ + ']*[' + goog.i18n.bidi.ltrChars_ + ']');
    -
    -
    -/**
    - * Regular expressions to check if a piece of text is of RTL directionality
    - * on first character with strong directionality.
    - * @type {RegExp}
    - * @private
    - */
    -goog.i18n.bidi.rtlDirCheckRe_ = new RegExp(
    -    '^[^' + goog.i18n.bidi.ltrChars_ + ']*[' + goog.i18n.bidi.rtlChars_ + ']');
    -
    -
    -/**
    - * Check whether the first strongly directional character (if any) is RTL.
    - * @param {string} str String being checked.
    - * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped.
    - *     Default: false.
    - * @return {boolean} Whether RTL directionality is detected using the first
    - *     strongly-directional character method.
    - */
    -goog.i18n.bidi.startsWithRtl = function(str, opt_isHtml) {
    -  return goog.i18n.bidi.rtlDirCheckRe_.test(goog.i18n.bidi.stripHtmlIfNeeded_(
    -      str, opt_isHtml));
    -};
    -
    -
    -/**
    - * Check whether the first strongly directional character (if any) is RTL.
    - * @param {string} str String being checked.
    - * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped.
    - *     Default: false.
    - * @return {boolean} Whether RTL directionality is detected using the first
    - *     strongly-directional character method.
    - * @deprecated Use startsWithRtl.
    - */
    -goog.i18n.bidi.isRtlText = goog.i18n.bidi.startsWithRtl;
    -
    -
    -/**
    - * Check whether the first strongly directional character (if any) is LTR.
    - * @param {string} str String being checked.
    - * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped.
    - *     Default: false.
    - * @return {boolean} Whether LTR directionality is detected using the first
    - *     strongly-directional character method.
    - */
    -goog.i18n.bidi.startsWithLtr = function(str, opt_isHtml) {
    -  return goog.i18n.bidi.ltrDirCheckRe_.test(goog.i18n.bidi.stripHtmlIfNeeded_(
    -      str, opt_isHtml));
    -};
    -
    -
    -/**
    - * Check whether the first strongly directional character (if any) is LTR.
    - * @param {string} str String being checked.
    - * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped.
    - *     Default: false.
    - * @return {boolean} Whether LTR directionality is detected using the first
    - *     strongly-directional character method.
    - * @deprecated Use startsWithLtr.
    - */
    -goog.i18n.bidi.isLtrText = goog.i18n.bidi.startsWithLtr;
    -
    -
    -/**
    - * Regular expression to check if a string looks like something that must
    - * always be LTR even in RTL text, e.g. a URL. When estimating the
    - * directionality of text containing these, we treat these as weakly LTR,
    - * like numbers.
    - * @type {RegExp}
    - * @private
    - */
    -goog.i18n.bidi.isRequiredLtrRe_ = /^http:\/\/.*/;
    -
    -
    -/**
    - * Check whether the input string either contains no strongly directional
    - * characters or looks like a url.
    - * @param {string} str String being checked.
    - * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped.
    - *     Default: false.
    - * @return {boolean} Whether neutral directionality is detected.
    - */
    -goog.i18n.bidi.isNeutralText = function(str, opt_isHtml) {
    -  str = goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml);
    -  return goog.i18n.bidi.isRequiredLtrRe_.test(str) ||
    -      !goog.i18n.bidi.hasAnyLtr(str) && !goog.i18n.bidi.hasAnyRtl(str);
    -};
    -
    -
    -/**
    - * Regular expressions to check if the last strongly-directional character in a
    - * piece of text is LTR.
    - * @type {RegExp}
    - * @private
    - */
    -goog.i18n.bidi.ltrExitDirCheckRe_ = new RegExp(
    -    '[' + goog.i18n.bidi.ltrChars_ + '][^' + goog.i18n.bidi.rtlChars_ + ']*$');
    -
    -
    -/**
    - * Regular expressions to check if the last strongly-directional character in a
    - * piece of text is RTL.
    - * @type {RegExp}
    - * @private
    - */
    -goog.i18n.bidi.rtlExitDirCheckRe_ = new RegExp(
    -    '[' + goog.i18n.bidi.rtlChars_ + '][^' + goog.i18n.bidi.ltrChars_ + ']*$');
    -
    -
    -/**
    - * Check if the exit directionality a piece of text is LTR, i.e. if the last
    - * strongly-directional character in the string is LTR.
    - * @param {string} str String being checked.
    - * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped.
    - *     Default: false.
    - * @return {boolean} Whether LTR exit directionality was detected.
    - */
    -goog.i18n.bidi.endsWithLtr = function(str, opt_isHtml) {
    -  return goog.i18n.bidi.ltrExitDirCheckRe_.test(
    -      goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml));
    -};
    -
    -
    -/**
    - * Check if the exit directionality a piece of text is LTR, i.e. if the last
    - * strongly-directional character in the string is LTR.
    - * @param {string} str String being checked.
    - * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped.
    - *     Default: false.
    - * @return {boolean} Whether LTR exit directionality was detected.
    - * @deprecated Use endsWithLtr.
    - */
    -goog.i18n.bidi.isLtrExitText = goog.i18n.bidi.endsWithLtr;
    -
    -
    -/**
    - * Check if the exit directionality a piece of text is RTL, i.e. if the last
    - * strongly-directional character in the string is RTL.
    - * @param {string} str String being checked.
    - * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped.
    - *     Default: false.
    - * @return {boolean} Whether RTL exit directionality was detected.
    - */
    -goog.i18n.bidi.endsWithRtl = function(str, opt_isHtml) {
    -  return goog.i18n.bidi.rtlExitDirCheckRe_.test(
    -      goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml));
    -};
    -
    -
    -/**
    - * Check if the exit directionality a piece of text is RTL, i.e. if the last
    - * strongly-directional character in the string is RTL.
    - * @param {string} str String being checked.
    - * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped.
    - *     Default: false.
    - * @return {boolean} Whether RTL exit directionality was detected.
    - * @deprecated Use endsWithRtl.
    - */
    -goog.i18n.bidi.isRtlExitText = goog.i18n.bidi.endsWithRtl;
    -
    -
    -/**
    - * A regular expression for matching right-to-left language codes.
    - * See {@link #isRtlLanguage} for the design.
    - * @type {RegExp}
    - * @private
    - */
    -goog.i18n.bidi.rtlLocalesRe_ = new RegExp(
    -    '^(ar|ckb|dv|he|iw|fa|nqo|ps|sd|ug|ur|yi|' +
    -    '.*[-_](Arab|Hebr|Thaa|Nkoo|Tfng))' +
    -    '(?!.*[-_](Latn|Cyrl)($|-|_))($|-|_)',
    -    'i');
    -
    -
    -/**
    - * Check if a BCP 47 / III language code indicates an RTL language, i.e. either:
    - * - a language code explicitly specifying one of the right-to-left scripts,
    - *   e.g. "az-Arab", or<p>
    - * - a language code specifying one of the languages normally written in a
    - *   right-to-left script, e.g. "fa" (Farsi), except ones explicitly specifying
    - *   Latin or Cyrillic script (which are the usual LTR alternatives).<p>
    - * The list of right-to-left scripts appears in the 100-199 range in
    - * http://www.unicode.org/iso15924/iso15924-num.html, of which Arabic and
    - * Hebrew are by far the most widely used. We also recognize Thaana, N'Ko, and
    - * Tifinagh, which also have significant modern usage. The rest (Syriac,
    - * Samaritan, Mandaic, etc.) seem to have extremely limited or no modern usage
    - * and are not recognized to save on code size.
    - * The languages usually written in a right-to-left script are taken as those
    - * with Suppress-Script: Hebr|Arab|Thaa|Nkoo|Tfng  in
    - * http://www.iana.org/assignments/language-subtag-registry,
    - * as well as Central (or Sorani) Kurdish (ckb), Sindhi (sd) and Uyghur (ug).
    - * Other subtags of the language code, e.g. regions like EG (Egypt), are
    - * ignored.
    - * @param {string} lang BCP 47 (a.k.a III) language code.
    - * @return {boolean} Whether the language code is an RTL language.
    - */
    -goog.i18n.bidi.isRtlLanguage = function(lang) {
    -  return goog.i18n.bidi.rtlLocalesRe_.test(lang);
    -};
    -
    -
    -/**
    - * Regular expression for bracket guard replacement in html.
    - * @type {RegExp}
    - * @private
    - */
    -goog.i18n.bidi.bracketGuardHtmlRe_ =
    -    /(\(.*?\)+)|(\[.*?\]+)|(\{.*?\}+)|(&lt;.*?(&gt;)+)/g;
    -
    -
    -/**
    - * Regular expression for bracket guard replacement in text.
    - * @type {RegExp}
    - * @private
    - */
    -goog.i18n.bidi.bracketGuardTextRe_ =
    -    /(\(.*?\)+)|(\[.*?\]+)|(\{.*?\}+)|(<.*?>+)/g;
    -
    -
    -/**
    - * Apply bracket guard using html span tag. This is to address the problem of
    - * messy bracket display frequently happens in RTL layout.
    - * @param {string} s The string that need to be processed.
    - * @param {boolean=} opt_isRtlContext specifies default direction (usually
    - *     direction of the UI).
    - * @return {string} The processed string, with all bracket guarded.
    - */
    -goog.i18n.bidi.guardBracketInHtml = function(s, opt_isRtlContext) {
    -  var useRtl = opt_isRtlContext === undefined ?
    -      goog.i18n.bidi.hasAnyRtl(s) : opt_isRtlContext;
    -  if (useRtl) {
    -    return s.replace(goog.i18n.bidi.bracketGuardHtmlRe_,
    -        '<span dir=rtl>$&</span>');
    -  }
    -  return s.replace(goog.i18n.bidi.bracketGuardHtmlRe_,
    -      '<span dir=ltr>$&</span>');
    -};
    -
    -
    -/**
    - * Apply bracket guard using LRM and RLM. This is to address the problem of
    - * messy bracket display frequently happens in RTL layout.
    - * This version works for both plain text and html. But it does not work as
    - * good as guardBracketInHtml in some cases.
    - * @param {string} s The string that need to be processed.
    - * @param {boolean=} opt_isRtlContext specifies default direction (usually
    - *     direction of the UI).
    - * @return {string} The processed string, with all bracket guarded.
    - */
    -goog.i18n.bidi.guardBracketInText = function(s, opt_isRtlContext) {
    -  var useRtl = opt_isRtlContext === undefined ?
    -      goog.i18n.bidi.hasAnyRtl(s) : opt_isRtlContext;
    -  var mark = useRtl ? goog.i18n.bidi.Format.RLM : goog.i18n.bidi.Format.LRM;
    -  return s.replace(goog.i18n.bidi.bracketGuardTextRe_, mark + '$&' + mark);
    -};
    -
    -
    -/**
    - * Enforce the html snippet in RTL directionality regardless overall context.
    - * If the html piece was enclosed by tag, dir will be applied to existing
    - * tag, otherwise a span tag will be added as wrapper. For this reason, if
    - * html snippet start with with tag, this tag must enclose the whole piece. If
    - * the tag already has a dir specified, this new one will override existing
    - * one in behavior (tested on FF and IE).
    - * @param {string} html The string that need to be processed.
    - * @return {string} The processed string, with directionality enforced to RTL.
    - */
    -goog.i18n.bidi.enforceRtlInHtml = function(html) {
    -  if (html.charAt(0) == '<') {
    -    return html.replace(/<\w+/, '$& dir=rtl');
    -  }
    -  // '\n' is important for FF so that it won't incorrectly merge span groups
    -  return '\n<span dir=rtl>' + html + '</span>';
    -};
    -
    -
    -/**
    - * Enforce RTL on both end of the given text piece using unicode BiDi formatting
    - * characters RLE and PDF.
    - * @param {string} text The piece of text that need to be wrapped.
    - * @return {string} The wrapped string after process.
    - */
    -goog.i18n.bidi.enforceRtlInText = function(text) {
    -  return goog.i18n.bidi.Format.RLE + text + goog.i18n.bidi.Format.PDF;
    -};
    -
    -
    -/**
    - * Enforce the html snippet in RTL directionality regardless overall context.
    - * If the html piece was enclosed by tag, dir will be applied to existing
    - * tag, otherwise a span tag will be added as wrapper. For this reason, if
    - * html snippet start with with tag, this tag must enclose the whole piece. If
    - * the tag already has a dir specified, this new one will override existing
    - * one in behavior (tested on FF and IE).
    - * @param {string} html The string that need to be processed.
    - * @return {string} The processed string, with directionality enforced to RTL.
    - */
    -goog.i18n.bidi.enforceLtrInHtml = function(html) {
    -  if (html.charAt(0) == '<') {
    -    return html.replace(/<\w+/, '$& dir=ltr');
    -  }
    -  // '\n' is important for FF so that it won't incorrectly merge span groups
    -  return '\n<span dir=ltr>' + html + '</span>';
    -};
    -
    -
    -/**
    - * Enforce LTR on both end of the given text piece using unicode BiDi formatting
    - * characters LRE and PDF.
    - * @param {string} text The piece of text that need to be wrapped.
    - * @return {string} The wrapped string after process.
    - */
    -goog.i18n.bidi.enforceLtrInText = function(text) {
    -  return goog.i18n.bidi.Format.LRE + text + goog.i18n.bidi.Format.PDF;
    -};
    -
    -
    -/**
    - * Regular expression to find dimensions such as "padding: .3 0.4ex 5px 6;"
    - * @type {RegExp}
    - * @private
    - */
    -goog.i18n.bidi.dimensionsRe_ =
    -    /:\s*([.\d][.\w]*)\s+([.\d][.\w]*)\s+([.\d][.\w]*)\s+([.\d][.\w]*)/g;
    -
    -
    -/**
    - * Regular expression for left.
    - * @type {RegExp}
    - * @private
    - */
    -goog.i18n.bidi.leftRe_ = /left/gi;
    -
    -
    -/**
    - * Regular expression for right.
    - * @type {RegExp}
    - * @private
    - */
    -goog.i18n.bidi.rightRe_ = /right/gi;
    -
    -
    -/**
    - * Placeholder regular expression for swapping.
    - * @type {RegExp}
    - * @private
    - */
    -goog.i18n.bidi.tempRe_ = /%%%%/g;
    -
    -
    -/**
    - * Swap location parameters and 'left'/'right' in CSS specification. The
    - * processed string will be suited for RTL layout. Though this function can
    - * cover most cases, there are always exceptions. It is suggested to put
    - * those exceptions in separate group of CSS string.
    - * @param {string} cssStr CSS spefication string.
    - * @return {string} Processed CSS specification string.
    - */
    -goog.i18n.bidi.mirrorCSS = function(cssStr) {
    -  return cssStr.
    -      // reverse dimensions
    -      replace(goog.i18n.bidi.dimensionsRe_, ':$1 $4 $3 $2').
    -      replace(goog.i18n.bidi.leftRe_, '%%%%').          // swap left and right
    -      replace(goog.i18n.bidi.rightRe_, goog.i18n.bidi.LEFT).
    -      replace(goog.i18n.bidi.tempRe_, goog.i18n.bidi.RIGHT);
    -};
    -
    -
    -/**
    - * Regular expression for hebrew double quote substitution, finding quote
    - * directly after hebrew characters.
    - * @type {RegExp}
    - * @private
    - */
    -goog.i18n.bidi.doubleQuoteSubstituteRe_ = /([\u0591-\u05f2])"/g;
    -
    -
    -/**
    - * Regular expression for hebrew single quote substitution, finding quote
    - * directly after hebrew characters.
    - * @type {RegExp}
    - * @private
    - */
    -goog.i18n.bidi.singleQuoteSubstituteRe_ = /([\u0591-\u05f2])'/g;
    -
    -
    -/**
    - * Replace the double and single quote directly after a Hebrew character with
    - * GERESH and GERSHAYIM. In such case, most likely that's user intention.
    - * @param {string} str String that need to be processed.
    - * @return {string} Processed string with double/single quote replaced.
    - */
    -goog.i18n.bidi.normalizeHebrewQuote = function(str) {
    -  return str.
    -      replace(goog.i18n.bidi.doubleQuoteSubstituteRe_, '$1\u05f4').
    -      replace(goog.i18n.bidi.singleQuoteSubstituteRe_, '$1\u05f3');
    -};
    -
    -
    -/**
    - * Regular expression to split a string into "words" for directionality
    - * estimation based on relative word counts.
    - * @type {RegExp}
    - * @private
    - */
    -goog.i18n.bidi.wordSeparatorRe_ = /\s+/;
    -
    -
    -/**
    - * Regular expression to check if a string contains any numerals. Used to
    - * differentiate between completely neutral strings and those containing
    - * numbers, which are weakly LTR.
    - * @type {RegExp}
    - * @private
    - */
    -goog.i18n.bidi.hasNumeralsRe_ = /\d/;
    -
    -
    -/**
    - * This constant controls threshold of RTL directionality.
    - * @type {number}
    - * @private
    - */
    -goog.i18n.bidi.rtlDetectionThreshold_ = 0.40;
    -
    -
    -/**
    - * Estimates the directionality of a string based on relative word counts.
    - * If the number of RTL words is above a certain percentage of the total number
    - * of strongly directional words, returns RTL.
    - * Otherwise, if any words are strongly or weakly LTR, returns LTR.
    - * Otherwise, returns UNKNOWN, which is used to mean "neutral".
    - * Numbers are counted as weakly LTR.
    - * @param {string} str The string to be checked.
    - * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped.
    - *     Default: false.
    - * @return {goog.i18n.bidi.Dir} Estimated overall directionality of {@code str}.
    - */
    -goog.i18n.bidi.estimateDirection = function(str, opt_isHtml) {
    -  var rtlCount = 0;
    -  var totalCount = 0;
    -  var hasWeaklyLtr = false;
    -  var tokens = goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml).
    -      split(goog.i18n.bidi.wordSeparatorRe_);
    -  for (var i = 0; i < tokens.length; i++) {
    -    var token = tokens[i];
    -    if (goog.i18n.bidi.startsWithRtl(token)) {
    -      rtlCount++;
    -      totalCount++;
    -    } else if (goog.i18n.bidi.isRequiredLtrRe_.test(token)) {
    -      hasWeaklyLtr = true;
    -    } else if (goog.i18n.bidi.hasAnyLtr(token)) {
    -      totalCount++;
    -    } else if (goog.i18n.bidi.hasNumeralsRe_.test(token)) {
    -      hasWeaklyLtr = true;
    -    }
    -  }
    -
    -  return totalCount == 0 ?
    -      (hasWeaklyLtr ? goog.i18n.bidi.Dir.LTR : goog.i18n.bidi.Dir.NEUTRAL) :
    -      (rtlCount / totalCount > goog.i18n.bidi.rtlDetectionThreshold_ ?
    -          goog.i18n.bidi.Dir.RTL : goog.i18n.bidi.Dir.LTR);
    -};
    -
    -
    -/**
    - * Check the directionality of a piece of text, return true if the piece of
    - * text should be laid out in RTL direction.
    - * @param {string} str The piece of text that need to be detected.
    - * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped.
    - *     Default: false.
    - * @return {boolean} Whether this piece of text should be laid out in RTL.
    - */
    -goog.i18n.bidi.detectRtlDirectionality = function(str, opt_isHtml) {
    -  return goog.i18n.bidi.estimateDirection(str, opt_isHtml) ==
    -      goog.i18n.bidi.Dir.RTL;
    -};
    -
    -
    -/**
    - * Sets text input element's directionality and text alignment based on a
    - * given directionality. Does nothing if the given directionality is unknown or
    - * neutral.
    - * @param {Element} element Input field element to set directionality to.
    - * @param {goog.i18n.bidi.Dir|number|boolean|null} dir Desired directionality,
    - *     given in one of the following formats:
    - *     1. A goog.i18n.bidi.Dir constant.
    - *     2. A number (positive = LRT, negative = RTL, 0 = neutral).
    - *     3. A boolean (true = RTL, false = LTR).
    - *     4. A null for unknown directionality.
    - */
    -goog.i18n.bidi.setElementDirAndAlign = function(element, dir) {
    -  if (element) {
    -    dir = goog.i18n.bidi.toDir(dir);
    -    if (dir) {
    -      element.style.textAlign =
    -          dir == goog.i18n.bidi.Dir.RTL ?
    -          goog.i18n.bidi.RIGHT : goog.i18n.bidi.LEFT;
    -      element.dir = dir == goog.i18n.bidi.Dir.RTL ? 'rtl' : 'ltr';
    -    }
    -  }
    -};
    -
    -
    -
    -/**
    - * Strings that have an (optional) known direction.
    - *
    - * Implementations of this interface are string-like objects that carry an
    - * attached direction, if known.
    - * @interface
    - */
    -goog.i18n.bidi.DirectionalString = function() {};
    -
    -
    -/**
    - * Interface marker of the DirectionalString interface.
    - *
    - * This property can be used to determine at runtime whether or not an object
    - * implements this interface.  All implementations of this interface set this
    - * property to {@code true}.
    - * @type {boolean}
    - */
    -goog.i18n.bidi.DirectionalString.prototype.
    -    implementsGoogI18nBidiDirectionalString;
    -
    -
    -/**
    - * Retrieves this object's known direction (if any).
    - * @return {?goog.i18n.bidi.Dir} The known direction. Null if unknown.
    - */
    -goog.i18n.bidi.DirectionalString.prototype.getDirection;
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/bidi_test.html b/src/database/third_party/closure-library/closure/goog/i18n/bidi_test.html
    deleted file mode 100644
    index 26f79823492..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/bidi_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.i18n.bidi
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.i18n.bidiTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/bidi_test.js b/src/database/third_party/closure-library/closure/goog/i18n/bidi_test.js
    deleted file mode 100644
    index b095459d090..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/bidi_test.js
    +++ /dev/null
    @@ -1,481 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.i18n.bidiTest');
    -goog.setTestOnly('goog.i18n.bidiTest');
    -
    -goog.require('goog.i18n.bidi');
    -goog.require('goog.i18n.bidi.Dir');
    -goog.require('goog.testing.jsunit');
    -
    -var LRE = '\u202A';
    -var RLE = '\u202B';
    -var PDF = '\u202C';
    -var LRM = '\u200E';
    -var RLM = '\u200F';
    -
    -function testToDir() {
    -  assertEquals(null, goog.i18n.bidi.toDir(null));
    -  assertEquals(null, goog.i18n.bidi.toDir(null, true));
    -
    -  assertEquals(goog.i18n.bidi.Dir.NEUTRAL,
    -      goog.i18n.bidi.toDir(goog.i18n.bidi.Dir.NEUTRAL));
    -  assertEquals(null, goog.i18n.bidi.toDir(0, true));
    -
    -  assertEquals(goog.i18n.bidi.Dir.LTR,
    -      goog.i18n.bidi.toDir(goog.i18n.bidi.Dir.LTR));
    -  assertEquals(goog.i18n.bidi.Dir.LTR,
    -      goog.i18n.bidi.toDir(goog.i18n.bidi.Dir.LTR, true));
    -  assertEquals(goog.i18n.bidi.Dir.LTR, goog.i18n.bidi.toDir(100));
    -  assertEquals(goog.i18n.bidi.Dir.LTR, goog.i18n.bidi.toDir(100, true));
    -  assertEquals(goog.i18n.bidi.Dir.LTR, goog.i18n.bidi.toDir(false));
    -  assertEquals(goog.i18n.bidi.Dir.LTR, goog.i18n.bidi.toDir(false, true));
    -
    -  assertEquals(goog.i18n.bidi.Dir.RTL,
    -      goog.i18n.bidi.toDir(goog.i18n.bidi.Dir.RTL));
    -  assertEquals(goog.i18n.bidi.Dir.RTL,
    -      goog.i18n.bidi.toDir(goog.i18n.bidi.Dir.RTL, true));
    -  assertEquals(goog.i18n.bidi.Dir.RTL, goog.i18n.bidi.toDir(-100));
    -  assertEquals(goog.i18n.bidi.Dir.RTL, goog.i18n.bidi.toDir(-100, true));
    -  assertEquals(goog.i18n.bidi.Dir.RTL, goog.i18n.bidi.toDir(true));
    -  assertEquals(goog.i18n.bidi.Dir.RTL, goog.i18n.bidi.toDir(true, true));
    -}
    -
    -function testIsRtlLang() {
    -  assert(!goog.i18n.bidi.isRtlLanguage('en'));
    -  assert(!goog.i18n.bidi.isRtlLanguage('fr'));
    -  assert(!goog.i18n.bidi.isRtlLanguage('zh-CN'));
    -  assert(!goog.i18n.bidi.isRtlLanguage('fil'));
    -  assert(!goog.i18n.bidi.isRtlLanguage('az'));
    -  assert(!goog.i18n.bidi.isRtlLanguage('iw-Latn'));
    -  assert(!goog.i18n.bidi.isRtlLanguage('iw-LATN'));
    -  assert(!goog.i18n.bidi.isRtlLanguage('iw_latn'));
    -  assert(goog.i18n.bidi.isRtlLanguage('ar'));
    -  assert(goog.i18n.bidi.isRtlLanguage('AR'));
    -  assert(goog.i18n.bidi.isRtlLanguage('iw'));
    -  assert(goog.i18n.bidi.isRtlLanguage('he'));
    -  assert(goog.i18n.bidi.isRtlLanguage('fa'));
    -  assert(goog.i18n.bidi.isRtlLanguage('ckb'));
    -  assert(goog.i18n.bidi.isRtlLanguage('ar-EG'));
    -  assert(goog.i18n.bidi.isRtlLanguage('az-Arab'));
    -  assert(goog.i18n.bidi.isRtlLanguage('az-ARAB-IR'));
    -  assert(goog.i18n.bidi.isRtlLanguage('az_arab_IR'));
    -}
    -
    -function testIsLtrChar() {
    -  assert(goog.i18n.bidi.isLtrChar('a'));
    -  assert(!goog.i18n.bidi.isLtrChar('\u05e0'));
    -  var str = 'a\u05e0z';
    -  assert(goog.i18n.bidi.isLtrChar(str.charAt(0)));
    -  assert(!goog.i18n.bidi.isLtrChar(str.charAt(1)));
    -  assert(goog.i18n.bidi.isLtrChar(str.charAt(2)));
    -}
    -
    -function testIsRtlChar() {
    -  assert(!goog.i18n.bidi.isRtlChar('a'));
    -  assert(goog.i18n.bidi.isRtlChar('\u05e0'));
    -  var str = 'a\u05e0z';
    -  assert(!goog.i18n.bidi.isRtlChar(str.charAt(0)));
    -  assert(goog.i18n.bidi.isRtlChar(str.charAt(1)));
    -  assert(!goog.i18n.bidi.isRtlChar(str.charAt(2)));
    -}
    -
    -function testIsNeutralChar() {
    -  assert(goog.i18n.bidi.isNeutralChar('\u0000'));
    -  assert(goog.i18n.bidi.isNeutralChar('\u0020'));
    -  assert(!goog.i18n.bidi.isNeutralChar('a'));
    -  assert(goog.i18n.bidi.isNeutralChar('!'));
    -  assert(goog.i18n.bidi.isNeutralChar('@'));
    -  assert(goog.i18n.bidi.isNeutralChar('['));
    -  assert(goog.i18n.bidi.isNeutralChar('`'));
    -  assert(goog.i18n.bidi.isNeutralChar('0'));
    -  assert(!goog.i18n.bidi.isNeutralChar('\u05e0'));
    -}
    -
    -function testIsNeutralText() {
    -  assert(goog.i18n.bidi.isNeutralText('123'));
    -  assert(!goog.i18n.bidi.isNeutralText('abc'));
    -  assert(goog.i18n.bidi.isNeutralText('http://abc'));
    -  assert(goog.i18n.bidi.isNeutralText(' 123-()'));
    -  assert(!goog.i18n.bidi.isNeutralText('123a456'));
    -  assert(!goog.i18n.bidi.isNeutralText('123\u05e0456'));
    -  assert(!goog.i18n.bidi.isNeutralText('<input value=\u05e0>123&lt;', false));
    -  assert(goog.i18n.bidi.isNeutralText('<input value=\u05e0>123&lt;', true));
    -}
    -
    -function testHasAnyLtr() {
    -  assert(!goog.i18n.bidi.hasAnyLtr(''));
    -  assert(!goog.i18n.bidi.hasAnyLtr('\u05e0\u05e1\u05e2'));
    -  assert(goog.i18n.bidi.hasAnyLtr('\u05e0\u05e1z\u05e2'));
    -  assert(!goog.i18n.bidi.hasAnyLtr('123\t...  \n'));
    -  assert(goog.i18n.bidi.hasAnyLtr('<br>123&lt;', false));
    -  assert(!goog.i18n.bidi.hasAnyLtr('<br>123&lt;', true));
    -}
    -
    -function testHasAnyRtl() {
    -  assert(!goog.i18n.bidi.hasAnyRtl(''));
    -  assert(!goog.i18n.bidi.hasAnyRtl('abc'));
    -  assert(goog.i18n.bidi.hasAnyRtl('ab\u05e0c'));
    -  assert(!goog.i18n.bidi.hasAnyRtl('123\t...  \n'));
    -  assert(goog.i18n.bidi.hasAnyRtl('<input value=\u05e0>123', false));
    -  assert(!goog.i18n.bidi.hasAnyRtl('<input value=\u05e0>123', true));
    -}
    -
    -function testEndsWithLtr() {
    -  assert(goog.i18n.bidi.endsWithLtr('a'));
    -  assert(goog.i18n.bidi.endsWithLtr('abc'));
    -  assert(goog.i18n.bidi.endsWithLtr('a (!)'));
    -  assert(goog.i18n.bidi.endsWithLtr('a.1'));
    -  assert(goog.i18n.bidi.endsWithLtr('http://www.google.com '));
    -  assert(goog.i18n.bidi.endsWithLtr('\u05e0a'));
    -  assert(goog.i18n.bidi.endsWithLtr(' \u05e0\u05e1a\u05e2\u05e3 a (!)'));
    -  assert(goog.i18n.bidi.endsWithLtr('\u202b\u05d0!\u202c\u200e'));
    -  assert(!goog.i18n.bidi.endsWithLtr(''));
    -  assert(!goog.i18n.bidi.endsWithLtr(' '));
    -  assert(!goog.i18n.bidi.endsWithLtr('1'));
    -  assert(!goog.i18n.bidi.endsWithLtr('\u05e0'));
    -  assert(!goog.i18n.bidi.endsWithLtr('\u05e0 1(!)'));
    -  assert(!goog.i18n.bidi.endsWithLtr('a\u05e0'));
    -  assert(!goog.i18n.bidi.endsWithLtr('a abc\u05e0\u05e1def\u05e2. 1'));
    -  assert(!goog.i18n.bidi.endsWithLtr('\u200f\u202eArtielish\u202c\u200f'));
    -  assert(!goog.i18n.bidi.endsWithLtr(' \u05e0\u05e1a\u05e2 &lt;', true));
    -  assert(goog.i18n.bidi.endsWithLtr(' \u05e0\u05e1a\u05e2 &lt;', false));
    -}
    -
    -function testEndsWithRtl() {
    -  assert(goog.i18n.bidi.endsWithRtl('\u05e0'));
    -  assert(goog.i18n.bidi.endsWithRtl('\u05e0\u05e1\u05e2'));
    -  assert(goog.i18n.bidi.endsWithRtl('\u05e0 (!)'));
    -  assert(goog.i18n.bidi.endsWithRtl('\u05e0.1'));
    -  assert(goog.i18n.bidi.endsWithRtl('http://www.google.com/\u05e0 '));
    -  assert(goog.i18n.bidi.endsWithRtl('a\u05e0'));
    -  assert(goog.i18n.bidi.endsWithRtl(' a abc\u05e0def\u05e3. 1'));
    -  assert(goog.i18n.bidi.endsWithRtl('\u200f\u202eArtielish\u202c\u200f'));
    -  assert(!goog.i18n.bidi.endsWithRtl(''));
    -  assert(!goog.i18n.bidi.endsWithRtl(' '));
    -  assert(!goog.i18n.bidi.endsWithRtl('1'));
    -  assert(!goog.i18n.bidi.endsWithRtl('a'));
    -  assert(!goog.i18n.bidi.endsWithRtl('a 1(!)'));
    -  assert(!goog.i18n.bidi.endsWithRtl('\u05e0a'));
    -  assert(!goog.i18n.bidi.endsWithRtl('\u202b\u05d0!\u202c\u200e'));
    -  assert(!goog.i18n.bidi.endsWithRtl('\u05e0 \u05e0\u05e1ab\u05e2 a (!)'));
    -  assert(goog.i18n.bidi.endsWithRtl(' \u05e0\u05e1a\u05e2 &lt;', true));
    -  assert(!goog.i18n.bidi.endsWithRtl(' \u05e0\u05e1a\u05e2 &lt;', false));
    -}
    -
    -function testGuardBracketInHtml() {
    -  var strWithRtl = 'asc \u05d0 (\u05d0\u05d0\u05d0)';
    -  assertEquals('asc \u05d0 <span dir=rtl>(\u05d0\u05d0\u05d0)</span>',
    -      goog.i18n.bidi.guardBracketInHtml(strWithRtl));
    -  assertEquals('asc \u05d0 <span dir=rtl>(\u05d0\u05d0\u05d0)</span>',
    -      goog.i18n.bidi.guardBracketInHtml(strWithRtl, true));
    -  assertEquals('asc \u05d0 <span dir=ltr>(\u05d0\u05d0\u05d0)</span>',
    -      goog.i18n.bidi.guardBracketInHtml(strWithRtl, false));
    -
    -  var strWithRtl2 = '\u05d0 a (asc:))';
    -  assertEquals('\u05d0 a <span dir=rtl>(asc:))</span>',
    -      goog.i18n.bidi.guardBracketInHtml(strWithRtl2));
    -  assertEquals('\u05d0 a <span dir=rtl>(asc:))</span>',
    -      goog.i18n.bidi.guardBracketInHtml(strWithRtl2, true));
    -  assertEquals('\u05d0 a <span dir=ltr>(asc:))</span>',
    -      goog.i18n.bidi.guardBracketInHtml(strWithRtl2, false));
    -
    -  var strWithoutRtl = 'a (asc) {{123}}';
    -  assertEquals('a <span dir=ltr>(asc)</span> <span dir=ltr>{{123}}</span>',
    -      goog.i18n.bidi.guardBracketInHtml(strWithoutRtl));
    -  assertEquals('a <span dir=rtl>(asc)</span> <span dir=rtl>{{123}}</span>',
    -      goog.i18n.bidi.guardBracketInHtml(strWithoutRtl, true));
    -  assertEquals('a <span dir=ltr>(asc)</span> <span dir=ltr>{{123}}</span>',
    -      goog.i18n.bidi.guardBracketInHtml(strWithoutRtl, false));
    -
    -}
    -
    -function testGuardBracketInText() {
    -  var strWithRtl = 'asc \u05d0 (\u05d0\u05d0\u05d0)';
    -  assertEquals('asc \u05d0 \u200f(\u05d0\u05d0\u05d0)\u200f',
    -      goog.i18n.bidi.guardBracketInText(strWithRtl));
    -  assertEquals('asc \u05d0 \u200f(\u05d0\u05d0\u05d0)\u200f',
    -      goog.i18n.bidi.guardBracketInText(strWithRtl, true));
    -  assertEquals('asc \u05d0 \u200e(\u05d0\u05d0\u05d0)\u200e',
    -      goog.i18n.bidi.guardBracketInText(strWithRtl, false));
    -
    -  var strWithRtl2 = '\u05d0 a (asc:))';
    -  assertEquals('\u05d0 a \u200f(asc:))\u200f',
    -      goog.i18n.bidi.guardBracketInText(strWithRtl2));
    -  assertEquals('\u05d0 a \u200f(asc:))\u200f',
    -      goog.i18n.bidi.guardBracketInText(strWithRtl2, true));
    -  assertEquals('\u05d0 a \u200e(asc:))\u200e',
    -      goog.i18n.bidi.guardBracketInText(strWithRtl2, false));
    -
    -  var strWithoutRtl = 'a (asc) {{123}}';
    -  assertEquals('a \u200e(asc)\u200e \u200e{{123}}\u200e',
    -      goog.i18n.bidi.guardBracketInText(strWithoutRtl));
    -  assertEquals('a \u200f(asc)\u200f \u200f{{123}}\u200f',
    -      goog.i18n.bidi.guardBracketInText(strWithoutRtl, true));
    -  assertEquals('a \u200e(asc)\u200e \u200e{{123}}\u200e',
    -      goog.i18n.bidi.guardBracketInText(strWithoutRtl, false));
    -
    -}
    -
    -function testEnforceRtlInHtml() {
    -  var str = '<div> first <br> second </div>';
    -  assertEquals('<div dir=rtl> first <br> second </div>',
    -               goog.i18n.bidi.enforceRtlInHtml(str));
    -  str = 'first second';
    -  assertEquals('\n<span dir=rtl>first second</span>',
    -               goog.i18n.bidi.enforceRtlInHtml(str));
    -}
    -
    -function testEnforceRtlInText() {
    -  var str = 'first second';
    -  assertEquals(RLE + 'first second' + PDF,
    -               goog.i18n.bidi.enforceRtlInText(str));
    -}
    -
    -function testEnforceLtrInHtml() {
    -  var str = '<div> first <br> second </div>';
    -  assertEquals('<div dir=ltr> first <br> second </div>',
    -               goog.i18n.bidi.enforceLtrInHtml(str));
    -  str = 'first second';
    -  assertEquals('\n<span dir=ltr>first second</span>',
    -               goog.i18n.bidi.enforceLtrInHtml(str));
    -}
    -
    -function testEnforceLtrInText() {
    -  var str = 'first second';
    -  assertEquals(LRE + 'first second' + PDF,
    -               goog.i18n.bidi.enforceLtrInText(str));
    -}
    -
    -function testNormalizeHebrewQuote() {
    -  assertEquals('\u05d0\u05f4', goog.i18n.bidi.normalizeHebrewQuote('\u05d0"'));
    -  assertEquals('\u05d0\u05f3', goog.i18n.bidi.normalizeHebrewQuote('\u05d0\''));
    -  assertEquals('\u05d0\u05f4\u05d0\u05f3',
    -               goog.i18n.bidi.normalizeHebrewQuote('\u05d0"\u05d0\''));
    -}
    -
    -function testMirrorCSS() {
    -  var str = 'left:10px;right:20px';
    -  assertEquals('right:10px;left:20px',
    -               goog.i18n.bidi.mirrorCSS(str));
    -  str = 'border:10px 20px 30px 40px';
    -  assertEquals('border:10px 40px 30px 20px',
    -               goog.i18n.bidi.mirrorCSS(str));
    -}
    -
    -function testEstimateDirection() {
    -  assertEquals(goog.i18n.bidi.Dir.NEUTRAL,
    -               goog.i18n.bidi.estimateDirection('', false));
    -  assertEquals(goog.i18n.bidi.Dir.NEUTRAL,
    -               goog.i18n.bidi.estimateDirection(' ', false));
    -  assertEquals(goog.i18n.bidi.Dir.NEUTRAL,
    -               goog.i18n.bidi.estimateDirection('! (...)', false));
    -  assertEquals(goog.i18n.bidi.Dir.LTR,
    -               goog.i18n.bidi.estimateDirection('All-Ascii content', false));
    -  assertEquals(goog.i18n.bidi.Dir.LTR,
    -               goog.i18n.bidi.estimateDirection('-17.0%', false));
    -  assertEquals(goog.i18n.bidi.Dir.LTR,
    -               goog.i18n.bidi.estimateDirection('http://foo/bar/', false));
    -  assertEquals(goog.i18n.bidi.Dir.LTR,
    -               goog.i18n.bidi.estimateDirection(
    -                   'http://foo/bar/?s=\u05d0\u05d0\u05d0\u05d0\u05d0\u05d0' +
    -                   '\u05d0\u05d0\u05d0\u05d0\u05d0\u05d0\u05d0\u05d0\u05d0' +
    -                   '\u05d0\u05d0\u05d0\u05d0\u05d0\u05d0\u05d0\u05d0\u05d0',
    -                   false));
    -  assertEquals(goog.i18n.bidi.Dir.RTL,
    -               goog.i18n.bidi.estimateDirection('\u05d0', false));
    -  assertEquals(goog.i18n.bidi.Dir.RTL,
    -               goog.i18n.bidi.estimateDirection(
    -                   '9 \u05d0 -> 17.5, 23, 45, 19', false));
    -  assertEquals(goog.i18n.bidi.Dir.RTL,
    -               goog.i18n.bidi.estimateDirection(
    -                   'http://foo/bar/ \u05d0 http://foo2/bar2/ ' +
    -                   'http://foo3/bar3/', false));
    -  assertEquals(goog.i18n.bidi.Dir.RTL,
    -               goog.i18n.bidi.estimateDirection(
    -                   '\u05d0\u05d9\u05df \u05de\u05de\u05e9 ' +
    -                   '\u05de\u05d4 \u05dc\u05e8\u05d0\u05d5\u05ea: ' +
    -                   '\u05dc\u05d0 \u05e6\u05d9\u05dc\u05de\u05ea\u05d9 ' +
    -                   '\u05d4\u05e8\u05d1\u05d4 \u05d5\u05d2\u05dd \u05d0' +
    -                   '\u05dd \u05d4\u05d9\u05d9\u05ea\u05d9 \u05de\u05e6' +
    -                   '\u05dc\u05dd, \u05d4\u05d9\u05d4 \u05e9\u05dd', false));
    -  assertEquals(goog.i18n.bidi.Dir.RTL,
    -               goog.i18n.bidi.estimateDirection(
    -                   '\u05db\u05d0 - http://geek.co.il/gallery/v/2007-06' +
    -                   ' - \u05d0\u05d9\u05df \u05de\u05de\u05e9 \u05de\u05d4 ' +
    -                   '\u05dc\u05e8\u05d0\u05d5\u05ea: \u05dc\u05d0 \u05e6' +
    -                   '\u05d9\u05dc\u05de\u05ea\u05d9 \u05d4\u05e8\u05d1 ' +
    -                   '\u05d5\u05d2\u05dd \u05d0\u05dd \u05d4\u05d9\u05d9' +
    -                   '\u05d9 \u05de\u05e6\u05dc\u05dd, \u05d4\u05d9\u05d4 ' +
    -                   '\u05e9\u05dd \u05d1\u05e2\u05d9\u05e7 \u05d4\u05e8' +
    -                   '\u05d1\u05d4 \u05d0\u05e0\u05e9\u05d9\u05dd. \u05de' +
    -                   '\u05d4 \u05e9\u05db\u05df - \u05d0\u05e4\u05e9\u05e8 ' +
    -                   '\u05dc\u05e0\u05e6\u05dc \u05d0\u05ea \u05d4\u05d4 ' +
    -                   '\u05d3\u05d6\u05de\u05e0\u05d5 \u05dc\u05d4\u05e1' +
    -                   '\u05ea\u05db\u05dc \u05e2\u05dc \u05db\u05de\u05d4 ' +
    -                   '\u05ea\u05de\u05d5\u05e0\u05d5\u05ea \u05de\u05e9' +
    -                   '\u05e9\u05e2\u05d5\u05ea \u05d9\u05e9\u05e0\u05d5 ' +
    -                   '\u05d9\u05d5\u05ea\u05e8 \u05e9\u05d9\u05e9 \u05dc' +
    -                   '\u05d9 \u05d1\u05d0\u05ea\u05e8', false));
    -  assertEquals(goog.i18n.bidi.Dir.RTL,
    -               goog.i18n.bidi.estimateDirection(
    -                   'CAPTCHA \u05de\u05e9\u05d5\u05db\u05dc\u05dc ' +
    -                   '\u05de\u05d3\u05d9?', false));
    -  assertEquals(goog.i18n.bidi.Dir.RTL,
    -               goog.i18n.bidi.estimateDirection(
    -                   'Yes Prime Minister \u05e2\u05d3\u05db\u05d5\u05df. ' +
    -                   '\u05e9\u05d0\u05dc\u05d5 \u05d0\u05d5\u05ea\u05d9 ' +
    -                   '\u05de\u05d4 \u05d0\u05e0\u05d9 \u05e8\u05d5\u05e6' +
    -                   '\u05d4 \u05de\u05ea\u05e0\u05d4 \u05dc\u05d7\u05d2',
    -                   false));
    -  assertEquals(goog.i18n.bidi.Dir.RTL,
    -               goog.i18n.bidi.estimateDirection(
    -                   '17.4.02 \u05e9\u05e2\u05d4:13-20 .15-00 .\u05dc\u05d0 ' +
    -                   '\u05d4\u05d9\u05d9\u05ea\u05d9 \u05db\u05d0\u05df.',
    -                   false));
    -  assertEquals(goog.i18n.bidi.Dir.RTL,
    -               goog.i18n.bidi.estimateDirection(
    -                   '5710 5720 5730. \u05d4\u05d3\u05dc\u05ea. ' +
    -                   '\u05d4\u05e0\u05e9\u05d9\u05e7\u05d4', false));
    -  assertEquals(goog.i18n.bidi.Dir.RTL,
    -               goog.i18n.bidi.estimateDirection(
    -                   '\u05d4\u05d3\u05dc\u05ea http://www.google.com ' +
    -                   'http://www.gmail.com', false));
    -  assertEquals(goog.i18n.bidi.Dir.RTL,
    -               goog.i18n.bidi.estimateDirection(
    -                   '\u200f\u202eArtielish\u202c\u200f'));
    -  assertEquals(goog.i18n.bidi.Dir.LTR,
    -               goog.i18n.bidi.estimateDirection(
    -                   '\u05d4\u05d3\u05dc <some quite nasty html mark up>',
    -                   false));
    -  assertEquals(goog.i18n.bidi.Dir.RTL,
    -               goog.i18n.bidi.estimateDirection(
    -                   '\u05d4\u05d3\u05dc <some quite nasty html mark up>',
    -                   true));
    -  assertEquals(goog.i18n.bidi.Dir.LTR,
    -               goog.i18n.bidi.estimateDirection(
    -                   '\u05d4\u05d3\u05dc\u05ea &amp; &lt; &gt;', false));
    -  assertEquals(goog.i18n.bidi.Dir.RTL,
    -               goog.i18n.bidi.estimateDirection(
    -                   '\u05d4\u05d3\u05dc\u05ea &amp; &lt; &gt;', true));
    -  assertEquals(goog.i18n.bidi.Dir.LTR,
    -               goog.i18n.bidi.estimateDirection(
    -                   'foo/<b>\u05d0</b>', true));
    -}
    -
    -var bidi_text = [];
    -
    -function testDetectRtlDirectionality() {
    -  InitializeSamples();
    -  for (var i = 0; i < bidi_text.length; i++) {
    -    //alert(bidi_text[i].text);
    -    var is_rtl = goog.i18n.bidi.detectRtlDirectionality(bidi_text[i].text,
    -                                                        bidi_text[i].isHtml);
    -    if (is_rtl != bidi_text[i].isRtl) {
    -      var str = '"' + bidi_text[i].text + '" should be ' +
    -                (bidi_text[i].isRtl ? 'rtl' : 'ltr') + ' but detected as ' +
    -                (is_rtl ? 'rtl' : 'ltr');
    -      alert(str);
    -    }
    -    assertEquals(bidi_text[i].isRtl, is_rtl);
    -  }
    -}
    -
    -
    -function SampleItem() {
    -  this.text = '';
    -  this.isRtl = false;
    -}
    -
    -function InitializeSamples() {
    -  var item = new SampleItem;
    -  item.text = 'Pure Ascii content';
    -  item.isRtl = false;
    -  bidi_text.push(item);
    -
    -  item = new SampleItem;
    -  item.text = '\u05d0\u05d9\u05df \u05de\u05de\u05e9 \u05de\u05d4 ' +
    -      '\u05dc\u05e8\u05d0\u05d5\u05ea: \u05dc\u05d0 ' +
    -      '\u05e6\u05d9\u05dc\u05de\u05ea\u05d9 \u05d4\u05e8\u05d1\u05d4 ' +
    -      '\u05d5\u05d2\u05dd \u05d0\u05dd \u05d4\u05d9\u05d9\u05ea\u05d9 ' +
    -      '\u05de\u05e6\u05dc\u05dd, \u05d4\u05d9\u05d4 \u05e9\u05dd';
    -  item.isRtl = true;
    -  bidi_text.push(item);
    -
    -  item = new SampleItem;
    -  item.text = '\u05db\u05d0\u05df - http://geek.co.il/gallery/v/2007-06 - ' +
    -      '\u05d0\u05d9\u05df \u05de\u05de\u05e9 \u05de\u05d4 ' +
    -      '\u05dc\u05e8\u05d0\u05d5\u05ea: ' +
    -      '\u05dc\u05d0 \u05e6\u05d9\u05dc\u05de\u05ea\u05d9 ' +
    -      '\u05d4\u05e8\u05d1\u05d4 \u05d5\u05d2\u05dd \u05d0\u05dd ' +
    -      '\u05d4\u05d9\u05d9\u05ea\u05d9 \u05de\u05e6\u05dc\u05dd, ' +
    -      '\u05d4\u05d9\u05d4 \u05e9\u05dd \u05d1\u05e2\u05d9\u05e7\u05e8 ' +
    -      '\u05d4\u05e8\u05d1\u05d4 \u05d0\u05e0\u05e9\u05d9\u05dd. ' +
    -      '\u05de\u05d4 \u05e9\u05db\u05df - \u05d0\u05e4\u05e9\u05e8 ' +
    -      '\u05dc\u05e0\u05e6\u05dc \u05d0\u05ea ' +
    -      '\u05d4\u05d4\u05d3\u05d6\u05de\u05e0\u05d5\u05ea ' +
    -      '\u05dc\u05d4\u05e1\u05ea\u05db\u05dc \u05e2\u05dc \u05db\u05de\u05d4 ' +
    -      '\u05ea\u05de\u05d5\u05e0\u05d5\u05ea ' +
    -      '\u05de\u05e9\u05e2\u05e9\u05e2\u05d5\u05ea ' +
    -      '\u05d9\u05e9\u05e0\u05d5\u05ea \u05d9\u05d5\u05ea\u05e8 ' +
    -      '\u05e9\u05d9\u05e9 \u05dc\u05d9 \u05d1\u05d0\u05ea\u05e8';
    -  item.isRtl = true;
    -  bidi_text.push(item);
    -
    -  item = new SampleItem;
    -  item.text =
    -      'CAPTCHA \u05de\u05e9\u05d5\u05db\u05dc\u05dc \u05de\u05d3\u05d9?';
    -  item.isRtl = true;
    -  bidi_text.push(item);
    -
    -
    -  item = new SampleItem;
    -  item.text = 'Yes Prime Minister \u05e2\u05d3\u05db\u05d5\u05df. ' +
    -      '\u05e9\u05d0\u05dc\u05d5 \u05d0\u05d5\u05ea\u05d9 \u05de\u05d4 ' +
    -      '\u05d0\u05e0\u05d9 \u05e8\u05d5\u05e6\u05d4 \u05de\u05ea\u05e0\u05d4 ' +
    -      '\u05dc\u05d7\u05d2';
    -  item.isRtl = true;
    -  bidi_text.push(item);
    -
    -  item = new SampleItem;
    -  item.text = '17.4.02 \u05e9\u05e2\u05d4:13-20 .15-00 .\u05dc\u05d0 ' +
    -      '\u05d4\u05d9\u05d9\u05ea\u05d9 \u05db\u05d0\u05df.';
    -  item.isRtl = true;
    -  bidi_text.push(item);
    -
    -  item = new SampleItem;
    -  item.text = '5710 5720 5730. \u05d4\u05d3\u05dc\u05ea. ' +
    -      '\u05d4\u05e0\u05e9\u05d9\u05e7\u05d4';
    -  item.isRtl = true;
    -  bidi_text.push(item);
    -
    -  item = new SampleItem;
    -  item.text =
    -      '\u05d4\u05d3\u05dc\u05ea http://www.google.com http://www.gmail.com';
    -  item.isRtl = true;
    -  bidi_text.push(item);
    -
    -  item = new SampleItem;
    -  item.text = '&gt;\u05d4&lt;';
    -  item.isHtml = true;
    -  item.isRtl = true;
    -  bidi_text.push(item);
    -
    -  item = new SampleItem;
    -  item.text = '&gt;\u05d4&lt;';
    -  item.isHtml = false;
    -  item.isRtl = false;
    -  bidi_text.push(item);
    -
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/bidiformatter.js b/src/database/third_party/closure-library/closure/goog/i18n/bidiformatter.js
    deleted file mode 100644
    index 0583f5b2ee8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/bidiformatter.js
    +++ /dev/null
    @@ -1,596 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Utility for formatting text for display in a potentially
    - * opposite-directionality context without garbling.
    - * Mostly a port of http://go/formatter.cc.
    - */
    -
    -
    -goog.provide('goog.i18n.BidiFormatter');
    -
    -goog.require('goog.html.SafeHtml');
    -goog.require('goog.html.legacyconversions');
    -goog.require('goog.i18n.bidi');
    -goog.require('goog.i18n.bidi.Dir');
    -goog.require('goog.i18n.bidi.Format');
    -
    -
    -
    -/**
    - * Utility class for formatting text for display in a potentially
    - * opposite-directionality context without garbling. Provides the following
    - * functionality:
    - *
    - * 1. BiDi Wrapping
    - * When text in one language is mixed into a document in another, opposite-
    - * directionality language, e.g. when an English business name is embedded in a
    - * Hebrew web page, both the inserted string and the text following it may be
    - * displayed incorrectly unless the inserted string is explicitly separated
    - * from the surrounding text in a "wrapper" that declares its directionality at
    - * the start and then resets it back at the end. This wrapping can be done in
    - * HTML mark-up (e.g. a 'span dir="rtl"' tag) or - only in contexts where
    - * mark-up can not be used - in Unicode BiDi formatting codes (LRE|RLE and PDF).
    - * Providing such wrapping services is the basic purpose of the BiDi formatter.
    - *
    - * 2. Directionality estimation
    - * How does one know whether a string about to be inserted into surrounding
    - * text has the same directionality? Well, in many cases, one knows that this
    - * must be the case when writing the code doing the insertion, e.g. when a
    - * localized message is inserted into a localized page. In such cases there is
    - * no need to involve the BiDi formatter at all. In the remaining cases, e.g.
    - * when the string is user-entered or comes from a database, the language of
    - * the string (and thus its directionality) is not known a priori, and must be
    - * estimated at run-time. The BiDi formatter does this automatically.
    - *
    - * 3. Escaping
    - * When wrapping plain text - i.e. text that is not already HTML or HTML-
    - * escaped - in HTML mark-up, the text must first be HTML-escaped to prevent XSS
    - * attacks and other nasty business. This of course is always true, but the
    - * escaping can not be done after the string has already been wrapped in
    - * mark-up, so the BiDi formatter also serves as a last chance and includes
    - * escaping services.
    - *
    - * Thus, in a single call, the formatter will escape the input string as
    - * specified, determine its directionality, and wrap it as necessary. It is
    - * then up to the caller to insert the return value in the output.
    - *
    - * See http://wiki/Main/TemplatesAndBiDi for more information.
    - *
    - * @param {goog.i18n.bidi.Dir|number|boolean|null} contextDir The context
    - *     directionality, in one of the following formats:
    - *     1. A goog.i18n.bidi.Dir constant. NEUTRAL is treated the same as null,
    - *        i.e. unknown, for backward compatibility with legacy calls.
    - *     2. A number (positive = LTR, negative = RTL, 0 = unknown).
    - *     3. A boolean (true = RTL, false = LTR).
    - *     4. A null for unknown directionality.
    - * @param {boolean=} opt_alwaysSpan Whether {@link #spanWrap} should always
    - *     use a 'span' tag, even when the input directionality is neutral or
    - *     matches the context, so that the DOM structure of the output does not
    - *     depend on the combination of directionalities. Default: false.
    - * @constructor
    - * @final
    - */
    -goog.i18n.BidiFormatter = function(contextDir, opt_alwaysSpan) {
    -  /**
    -   * The overall directionality of the context in which the formatter is being
    -   * used.
    -   * @type {?goog.i18n.bidi.Dir}
    -   * @private
    -   */
    -  this.contextDir_ = goog.i18n.bidi.toDir(contextDir, true /* opt_noNeutral */);
    -
    -  /**
    -   * Whether {@link #spanWrap} and similar methods should always use the same
    -   * span structure, regardless of the combination of directionalities, for a
    -   * stable DOM structure.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.alwaysSpan_ = !!opt_alwaysSpan;
    -};
    -
    -
    -/**
    - * @return {?goog.i18n.bidi.Dir} The context directionality.
    - */
    -goog.i18n.BidiFormatter.prototype.getContextDir = function() {
    -  return this.contextDir_;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether alwaysSpan is set.
    - */
    -goog.i18n.BidiFormatter.prototype.getAlwaysSpan = function() {
    -  return this.alwaysSpan_;
    -};
    -
    -
    -/**
    - * @param {goog.i18n.bidi.Dir|number|boolean|null} contextDir The context
    - *     directionality, in one of the following formats:
    - *     1. A goog.i18n.bidi.Dir constant. NEUTRAL is treated the same as null,
    - *        i.e. unknown.
    - *     2. A number (positive = LTR, negative = RTL, 0 = unknown).
    - *     3. A boolean (true = RTL, false = LTR).
    - *     4. A null for unknown directionality.
    - */
    -goog.i18n.BidiFormatter.prototype.setContextDir = function(contextDir) {
    -  this.contextDir_ = goog.i18n.bidi.toDir(contextDir, true /* opt_noNeutral */);
    -};
    -
    -
    -/**
    - * @param {boolean} alwaysSpan Whether {@link #spanWrap} should always use a
    - *     'span' tag, even when the input directionality is neutral or matches the
    - *     context, so that the DOM structure of the output does not depend on the
    - *     combination of directionalities.
    - */
    -goog.i18n.BidiFormatter.prototype.setAlwaysSpan = function(alwaysSpan) {
    -  this.alwaysSpan_ = alwaysSpan;
    -};
    -
    -
    -/**
    - * Returns the directionality of input argument {@code str}.
    - * Identical to {@link goog.i18n.bidi.estimateDirection}.
    - *
    - * @param {string} str The input text.
    - * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped.
    - *     Default: false.
    - * @return {goog.i18n.bidi.Dir} Estimated overall directionality of {@code str}.
    - */
    -goog.i18n.BidiFormatter.prototype.estimateDirection =
    -    goog.i18n.bidi.estimateDirection;
    -
    -
    -/**
    - * Returns true if two given directionalities are opposite.
    - * Note: the implementation is based on the numeric values of the Dir enum.
    - *
    - * @param {?goog.i18n.bidi.Dir} dir1 1st directionality.
    - * @param {?goog.i18n.bidi.Dir} dir2 2nd directionality.
    - * @return {boolean} Whether the directionalities are opposite.
    - * @private
    - */
    -goog.i18n.BidiFormatter.prototype.areDirectionalitiesOpposite_ = function(dir1,
    -    dir2) {
    -  return dir1 * dir2 < 0;
    -};
    -
    -
    -/**
    - * Returns a unicode BiDi mark matching the context directionality (LRM or
    - * RLM) if {@code opt_dirReset}, and if either the directionality or the exit
    - * directionality of {@code str} is opposite to the context directionality.
    - * Otherwise returns the empty string.
    - *
    - * @param {string} str The input text.
    - * @param {goog.i18n.bidi.Dir} dir {@code str}'s overall directionality.
    - * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped.
    - *     Default: false.
    - * @param {boolean=} opt_dirReset Whether to perform the reset. Default: false.
    - * @return {string} A unicode BiDi mark or the empty string.
    - * @private
    - */
    -goog.i18n.BidiFormatter.prototype.dirResetIfNeeded_ = function(str, dir,
    -    opt_isHtml, opt_dirReset) {
    -  // endsWithRtl and endsWithLtr are called only if needed (short-circuit).
    -  if (opt_dirReset &&
    -      (this.areDirectionalitiesOpposite_(dir, this.contextDir_) ||
    -       (this.contextDir_ == goog.i18n.bidi.Dir.LTR &&
    -        goog.i18n.bidi.endsWithRtl(str, opt_isHtml)) ||
    -       (this.contextDir_ == goog.i18n.bidi.Dir.RTL &&
    -        goog.i18n.bidi.endsWithLtr(str, opt_isHtml)))) {
    -    return this.contextDir_ == goog.i18n.bidi.Dir.LTR ?
    -        goog.i18n.bidi.Format.LRM : goog.i18n.bidi.Format.RLM;
    -  } else {
    -    return '';
    -  }
    -};
    -
    -
    -/**
    - * Returns "rtl" if {@code str}'s estimated directionality is RTL, and "ltr" if
    - * it is LTR. In case it's NEUTRAL, returns "rtl" if the context directionality
    - * is RTL, and "ltr" otherwise.
    - * Needed for GXP, which can't handle dirAttr.
    - * Example use case:
    - * &lt;td expr:dir='bidiFormatter.dirAttrValue(foo)'&gt;
    - *   &lt;gxp:eval expr='foo'&gt;
    - * &lt;/td&gt;
    - *
    - * @param {string} str Text whose directionality is to be estimated.
    - * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped.
    - *     Default: false.
    - * @return {string} "rtl" or "ltr", according to the logic described above.
    - */
    -goog.i18n.BidiFormatter.prototype.dirAttrValue = function(str, opt_isHtml) {
    -  return this.knownDirAttrValue(this.estimateDirection(str, opt_isHtml));
    -};
    -
    -
    -/**
    - * Returns "rtl" if the given directionality is RTL, and "ltr" if it is LTR. In
    - * case it's NEUTRAL, returns "rtl" if the context directionality is RTL, and
    - * "ltr" otherwise.
    - *
    - * @param {goog.i18n.bidi.Dir} dir A directionality.
    - * @return {string} "rtl" or "ltr", according to the logic described above.
    - */
    -goog.i18n.BidiFormatter.prototype.knownDirAttrValue = function(dir) {
    -  var resolvedDir = dir == goog.i18n.bidi.Dir.NEUTRAL ? this.contextDir_ : dir;
    -  return resolvedDir == goog.i18n.bidi.Dir.RTL ? 'rtl' : 'ltr';
    -};
    -
    -
    -/**
    - * Returns 'dir="ltr"' or 'dir="rtl"', depending on {@code str}'s estimated
    - * directionality, if it is not the same as the context directionality.
    - * Otherwise, returns the empty string.
    - *
    - * @param {string} str Text whose directionality is to be estimated.
    - * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped.
    - *     Default: false.
    - * @return {string} 'dir="rtl"' for RTL text in non-RTL context; 'dir="ltr"' for
    - *     LTR text in non-LTR context; else, the empty string.
    - */
    -goog.i18n.BidiFormatter.prototype.dirAttr = function(str, opt_isHtml) {
    -  return this.knownDirAttr(this.estimateDirection(str, opt_isHtml));
    -};
    -
    -
    -/**
    - * Returns 'dir="ltr"' or 'dir="rtl"', depending on the given directionality, if
    - * it is not the same as the context directionality. Otherwise, returns the
    - * empty string.
    - *
    - * @param {goog.i18n.bidi.Dir} dir A directionality.
    - * @return {string} 'dir="rtl"' for RTL text in non-RTL context; 'dir="ltr"' for
    - *     LTR text in non-LTR context; else, the empty string.
    - */
    -goog.i18n.BidiFormatter.prototype.knownDirAttr = function(dir) {
    -  if (dir != this.contextDir_) {
    -    return dir == goog.i18n.bidi.Dir.RTL ? 'dir="rtl"' :
    -        dir == goog.i18n.bidi.Dir.LTR ? 'dir="ltr"' : '';
    -  }
    -  return '';
    -};
    -
    -
    -/**
    - * Formats a string of unknown directionality for use in HTML output of the
    - * context directionality, so an opposite-directionality string is neither
    - * garbled nor garbles what follows it.
    - * The algorithm: estimates the directionality of input argument {@code html}.
    - * In case its directionality doesn't match the context directionality, wraps it
    - * with a 'span' tag and adds a "dir" attribute (either 'dir="rtl"' or
    - * 'dir="ltr"'). If setAlwaysSpan(true) was used, the input is always wrapped
    - * with 'span', skipping just the dir attribute when it's not needed.
    - *
    - * If {@code opt_dirReset}, and if the overall directionality or the exit
    - * directionality of {@code str} are opposite to the context directionality, a
    - * trailing unicode BiDi mark matching the context directionality is appened
    - * (LRM or RLM).
    - *
    - * @param {!goog.html.SafeHtml} html The input HTML.
    - * @param {boolean=} opt_dirReset Whether to append a trailing unicode bidi mark
    - *     matching the context directionality, when needed, to prevent the possible
    - *     garbling of whatever may follow {@code html}. Default: true.
    - * @return {!goog.html.SafeHtml} Input text after applying the processing.
    - */
    -goog.i18n.BidiFormatter.prototype.spanWrapSafeHtml = function(html,
    -    opt_dirReset) {
    -  return this.spanWrapSafeHtmlWithKnownDir(null, html, opt_dirReset);
    -};
    -
    -
    -/**
    - * String version of {@link #spanWrapSafeHtml}.
    - *
    - * If !{@code opt_isHtml}, HTML-escapes {@code str} regardless of wrapping.
    - *
    - * @param {string} str The input text.
    - * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped.
    - *     Default: false.
    - * @param {boolean=} opt_dirReset Whether to append a trailing unicode bidi mark
    - *     matching the context directionality, when needed, to prevent the possible
    - *     garbling of whatever may follow {@code str}. Default: true.
    - * @return {string} Input text after applying the above processing.
    - */
    -goog.i18n.BidiFormatter.prototype.spanWrap = function(str, opt_isHtml,
    -    opt_dirReset) {
    -  return this.spanWrapWithKnownDir(null, str, opt_isHtml, opt_dirReset);
    -};
    -
    -
    -/**
    - * Formats a string of given directionality for use in HTML output of the
    - * context directionality, so an opposite-directionality string is neither
    - * garbled nor garbles what follows it.
    - * The algorithm: If {@code dir} doesn't match the context directionality, wraps
    - * {@code html} with a 'span' tag and adds a "dir" attribute (either 'dir="rtl"'
    - * or 'dir="ltr"'). If setAlwaysSpan(true) was used, the input is always wrapped
    - * with 'span', skipping just the dir attribute when it's not needed.
    - *
    - * If {@code opt_dirReset}, and if {@code dir} or the exit directionality of
    - * {@code html} are opposite to the context directionality, a trailing unicode
    - * BiDi mark matching the context directionality is appened (LRM or RLM).
    - *
    - * @param {?goog.i18n.bidi.Dir} dir {@code html}'s overall directionality, or
    - *     null if unknown and needs to be estimated.
    - * @param {!goog.html.SafeHtml} html The input HTML.
    - * @param {boolean=} opt_dirReset Whether to append a trailing unicode bidi mark
    - *     matching the context directionality, when needed, to prevent the possible
    - *     garbling of whatever may follow {@code html}. Default: true.
    - * @return {!goog.html.SafeHtml} Input text after applying the processing.
    - */
    -goog.i18n.BidiFormatter.prototype.spanWrapSafeHtmlWithKnownDir = function(dir,
    -    html, opt_dirReset) {
    -  if (dir == null) {
    -    dir = this.estimateDirection(goog.html.SafeHtml.unwrap(html), true);
    -  }
    -  return this.spanWrapWithKnownDir_(dir, html, opt_dirReset);
    -};
    -
    -
    -/**
    - * String version of {@link #spanWrapSafeHtmlWithKnownDir}.
    - *
    - * If !{@code opt_isHtml}, HTML-escapes {@code str} regardless of wrapping.
    - *
    - * @param {?goog.i18n.bidi.Dir} dir {@code str}'s overall directionality, or
    - *     null if unknown and needs to be estimated.
    - * @param {string} str The input text.
    - * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped.
    - *     Default: false.
    - * @param {boolean=} opt_dirReset Whether to append a trailing unicode bidi mark
    - *     matching the context directionality, when needed, to prevent the possible
    - *     garbling of whatever may follow {@code str}. Default: true.
    - * @return {string} Input text after applying the above processing.
    - */
    -goog.i18n.BidiFormatter.prototype.spanWrapWithKnownDir = function(dir, str,
    -    opt_isHtml, opt_dirReset) {
    -  // We're calling legacy conversions, but quickly unwrapping it.
    -  var html = opt_isHtml ? goog.html.legacyconversions.safeHtmlFromString(str) :
    -      goog.html.SafeHtml.htmlEscape(str);
    -  return goog.html.SafeHtml.unwrap(
    -      this.spanWrapSafeHtmlWithKnownDir(dir, html, opt_dirReset));
    -};
    -
    -
    -/**
    - * The internal implementation of spanWrapSafeHtmlWithKnownDir for non-null dir,
    - * to help the compiler optimize.
    - *
    - * @param {goog.i18n.bidi.Dir} dir {@code str}'s overall directionality.
    - * @param {!goog.html.SafeHtml} html The input HTML.
    - * @param {boolean=} opt_dirReset Whether to append a trailing unicode bidi mark
    - *     matching the context directionality, when needed, to prevent the possible
    - *     garbling of whatever may follow {@code str}. Default: true.
    - * @return {!goog.html.SafeHtml} Input text after applying the above processing.
    - * @private
    - */
    -goog.i18n.BidiFormatter.prototype.spanWrapWithKnownDir_ = function(dir, html,
    -    opt_dirReset) {
    -  opt_dirReset = opt_dirReset || (opt_dirReset == undefined);
    -
    -  var result;
    -  // Whether to add the "dir" attribute.
    -  var dirCondition =
    -      dir != goog.i18n.bidi.Dir.NEUTRAL && dir != this.contextDir_;
    -  if (this.alwaysSpan_ || dirCondition) {  // Wrap is needed
    -    var dirAttribute;
    -    if (dirCondition) {
    -      dirAttribute = dir == goog.i18n.bidi.Dir.RTL ? 'rtl' : 'ltr';
    -    }
    -    result = goog.html.SafeHtml.create('span', {'dir': dirAttribute}, html);
    -  } else {
    -    result = html;
    -  }
    -  var str = goog.html.SafeHtml.unwrap(html);
    -  result = goog.html.SafeHtml.concatWithDir(goog.i18n.bidi.Dir.NEUTRAL, result,
    -      this.dirResetIfNeeded_(str, dir, true, opt_dirReset));
    -  return result;
    -};
    -
    -
    -/**
    - * Formats a string of unknown directionality for use in plain-text output of
    - * the context directionality, so an opposite-directionality string is neither
    - * garbled nor garbles what follows it.
    - * As opposed to {@link #spanWrap}, this makes use of unicode BiDi formatting
    - * characters. In HTML, its *only* valid use is inside of elements that do not
    - * allow mark-up, e.g. an 'option' tag.
    - * The algorithm: estimates the directionality of input argument {@code str}.
    - * In case it doesn't match  the context directionality, wraps it with Unicode
    - * BiDi formatting characters: RLE{@code str}PDF for RTL text, and
    - * LRE{@code str}PDF for LTR text.
    - *
    - * If {@code opt_dirReset}, and if the overall directionality or the exit
    - * directionality of {@code str} are opposite to the context directionality, a
    - * trailing unicode BiDi mark matching the context directionality is appended
    - * (LRM or RLM).
    - *
    - * Does *not* do HTML-escaping regardless of the value of {@code opt_isHtml}.
    - * The return value can be HTML-escaped as necessary.
    - *
    - * @param {string} str The input text.
    - * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped.
    - *     Default: false.
    - * @param {boolean=} opt_dirReset Whether to append a trailing unicode bidi mark
    - *     matching the context directionality, when needed, to prevent the possible
    - *     garbling of whatever may follow {@code str}. Default: true.
    - * @return {string} Input text after applying the above processing.
    - */
    -goog.i18n.BidiFormatter.prototype.unicodeWrap = function(str, opt_isHtml,
    -    opt_dirReset) {
    -  return this.unicodeWrapWithKnownDir(null, str, opt_isHtml, opt_dirReset);
    -};
    -
    -
    -/**
    - * Formats a string of given directionality for use in plain-text output of the
    - * context directionality, so an opposite-directionality string is neither
    - * garbled nor garbles what follows it.
    - * As opposed to {@link #spanWrapWithKnownDir}, makes use of unicode BiDi
    - * formatting characters. In HTML, its *only* valid use is inside of elements
    - * that do not allow mark-up, e.g. an 'option' tag.
    - * The algorithm: If {@code dir} doesn't match the context directionality, wraps
    - * {@code str} with Unicode BiDi formatting characters: RLE{@code str}PDF for
    - * RTL text, and LRE{@code str}PDF for LTR text.
    - *
    - * If {@code opt_dirReset}, and if the overall directionality or the exit
    - * directionality of {@code str} are opposite to the context directionality, a
    - * trailing unicode BiDi mark matching the context directionality is appended
    - * (LRM or RLM).
    - *
    - * Does *not* do HTML-escaping regardless of the value of {@code opt_isHtml}.
    - * The return value can be HTML-escaped as necessary.
    - *
    - * @param {?goog.i18n.bidi.Dir} dir {@code str}'s overall directionality, or
    - *     null if unknown and needs to be estimated.
    - * @param {string} str The input text.
    - * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped.
    - *     Default: false.
    - * @param {boolean=} opt_dirReset Whether to append a trailing unicode bidi mark
    - *     matching the context directionality, when needed, to prevent the possible
    - *     garbling of whatever may follow {@code str}. Default: true.
    - * @return {string} Input text after applying the above processing.
    - */
    -goog.i18n.BidiFormatter.prototype.unicodeWrapWithKnownDir = function(dir, str,
    -    opt_isHtml, opt_dirReset) {
    -  if (dir == null) {
    -    dir = this.estimateDirection(str, opt_isHtml);
    -  }
    -  return this.unicodeWrapWithKnownDir_(dir, str, opt_isHtml, opt_dirReset);
    -};
    -
    -
    -/**
    - * The internal implementation of unicodeWrapWithKnownDir for non-null dir, to
    - * help the compiler optimize.
    - *
    - * @param {goog.i18n.bidi.Dir} dir {@code str}'s overall directionality.
    - * @param {string} str The input text.
    - * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped.
    - *     Default: false.
    - * @param {boolean=} opt_dirReset Whether to append a trailing unicode bidi mark
    - *     matching the context directionality, when needed, to prevent the possible
    - *     garbling of whatever may follow {@code str}. Default: true.
    - * @return {string} Input text after applying the above processing.
    - * @private
    - */
    -goog.i18n.BidiFormatter.prototype.unicodeWrapWithKnownDir_ = function(dir, str,
    -    opt_isHtml, opt_dirReset) {
    -  opt_dirReset = opt_dirReset || (opt_dirReset == undefined);
    -  var result = [];
    -  if (dir != goog.i18n.bidi.Dir.NEUTRAL && dir != this.contextDir_) {
    -    result.push(dir == goog.i18n.bidi.Dir.RTL ? goog.i18n.bidi.Format.RLE :
    -                                                goog.i18n.bidi.Format.LRE);
    -    result.push(str);
    -    result.push(goog.i18n.bidi.Format.PDF);
    -  } else {
    -    result.push(str);
    -  }
    -
    -  result.push(this.dirResetIfNeeded_(str, dir, opt_isHtml, opt_dirReset));
    -  return result.join('');
    -};
    -
    -
    -/**
    - * Returns a Unicode BiDi mark matching the context directionality (LRM or RLM)
    - * if the directionality or the exit directionality of {@code str} are opposite
    - * to the context directionality. Otherwise returns the empty string.
    - *
    - * @param {string} str The input text.
    - * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped.
    - *     Default: false.
    - * @return {string} A Unicode bidi mark matching the global directionality or
    - *     the empty string.
    - */
    -goog.i18n.BidiFormatter.prototype.markAfter = function(str, opt_isHtml) {
    -  return this.markAfterKnownDir(null, str, opt_isHtml);
    -};
    -
    -
    -/**
    - * Returns a Unicode BiDi mark matching the context directionality (LRM or RLM)
    - * if the given directionality or the exit directionality of {@code str} are
    - * opposite to the context directionality. Otherwise returns the empty string.
    - *
    - * @param {?goog.i18n.bidi.Dir} dir {@code str}'s overall directionality, or
    - *     null if unknown and needs to be estimated.
    - * @param {string} str The input text.
    - * @param {boolean=} opt_isHtml Whether {@code str} is HTML / HTML-escaped.
    - *     Default: false.
    - * @return {string} A Unicode bidi mark matching the global directionality or
    - *     the empty string.
    - */
    -goog.i18n.BidiFormatter.prototype.markAfterKnownDir = function(
    -    dir, str, opt_isHtml) {
    -  if (dir == null) {
    -    dir = this.estimateDirection(str, opt_isHtml);
    -  }
    -  return this.dirResetIfNeeded_(str, dir, opt_isHtml, true);
    -};
    -
    -
    -/**
    - * Returns the Unicode BiDi mark matching the context directionality (LRM for
    - * LTR context directionality, RLM for RTL context directionality), or the
    - * empty string for neutral / unknown context directionality.
    - *
    - * @return {string} LRM for LTR context directionality and RLM for RTL context
    - *     directionality.
    - */
    -goog.i18n.BidiFormatter.prototype.mark = function() {
    -  switch (this.contextDir_) {
    -    case (goog.i18n.bidi.Dir.LTR):
    -      return goog.i18n.bidi.Format.LRM;
    -    case (goog.i18n.bidi.Dir.RTL):
    -      return goog.i18n.bidi.Format.RLM;
    -    default:
    -      return '';
    -  }
    -};
    -
    -
    -/**
    - * Returns 'right' for RTL context directionality. Otherwise (LTR or neutral /
    - * unknown context directionality) returns 'left'.
    - *
    - * @return {string} 'right' for RTL context directionality and 'left' for other
    - *     context directionality.
    - */
    -goog.i18n.BidiFormatter.prototype.startEdge = function() {
    -  return this.contextDir_ == goog.i18n.bidi.Dir.RTL ?
    -      goog.i18n.bidi.RIGHT : goog.i18n.bidi.LEFT;
    -};
    -
    -
    -/**
    - * Returns 'left' for RTL context directionality. Otherwise (LTR or neutral /
    - * unknown context directionality) returns 'right'.
    - *
    - * @return {string} 'left' for RTL context directionality and 'right' for other
    - *     context directionality.
    - */
    -goog.i18n.BidiFormatter.prototype.endEdge = function() {
    -  return this.contextDir_ == goog.i18n.bidi.Dir.RTL ?
    -      goog.i18n.bidi.LEFT : goog.i18n.bidi.RIGHT;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/bidiformatter_test.html b/src/database/third_party/closure-library/closure/goog/i18n/bidiformatter_test.html
    deleted file mode 100644
    index 752ac30ee3f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/bidiformatter_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.i18n.BidiFormatter
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.i18n.BidiFormatterTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/bidiformatter_test.js b/src/database/third_party/closure-library/closure/goog/i18n/bidiformatter_test.js
    deleted file mode 100644
    index 9129e31ccd1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/bidiformatter_test.js
    +++ /dev/null
    @@ -1,535 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.i18n.BidiFormatterTest');
    -goog.setTestOnly('goog.i18n.BidiFormatterTest');
    -
    -goog.require('goog.html.SafeHtml');
    -goog.require('goog.i18n.BidiFormatter');
    -goog.require('goog.i18n.bidi.Dir');
    -goog.require('goog.i18n.bidi.Format');
    -goog.require('goog.testing.jsunit');
    -
    -var LRM = goog.i18n.bidi.Format.LRM;
    -var RLM = goog.i18n.bidi.Format.RLM;
    -var LRE = goog.i18n.bidi.Format.LRE;
    -var RLE = goog.i18n.bidi.Format.RLE;
    -var PDF = goog.i18n.bidi.Format.PDF;
    -var LTR = goog.i18n.bidi.Dir.LTR;
    -var RTL = goog.i18n.bidi.Dir.RTL;
    -var NEUTRAL = goog.i18n.bidi.Dir.NEUTRAL;
    -var he = '\u05e0\u05e1';
    -var en = 'abba';
    -var html = '&lt;';
    -var longEn = 'abba sabba gabba ';
    -var longHe = '\u05e0 \u05e1 \u05e0 ';
    -var ltrFmt = new goog.i18n.BidiFormatter(LTR, false);  // LTR context
    -var rtlFmt = new goog.i18n.BidiFormatter(RTL, false);  // RTL context
    -var unkFmt = new goog.i18n.BidiFormatter(null, false);  // unknown context
    -
    -function testGetContextDir() {
    -  assertEquals(null, unkFmt.getContextDir());
    -  assertEquals(null, new goog.i18n.BidiFormatter(NEUTRAL).getContextDir());
    -  assertEquals(LTR, ltrFmt.getContextDir());
    -  assertEquals(RTL, rtlFmt.getContextDir());
    -}
    -
    -function testEstimateDirection() {
    -  assertEquals(NEUTRAL, ltrFmt.estimateDirection(''));
    -  assertEquals(NEUTRAL, rtlFmt.estimateDirection(''));
    -  assertEquals(NEUTRAL, unkFmt.estimateDirection(''));
    -  assertEquals(LTR, ltrFmt.estimateDirection(en));
    -  assertEquals(LTR, rtlFmt.estimateDirection(en));
    -  assertEquals(LTR, unkFmt.estimateDirection(en));
    -  assertEquals(RTL, ltrFmt.estimateDirection(he));
    -  assertEquals(RTL, rtlFmt.estimateDirection(he));
    -  assertEquals(RTL, unkFmt.estimateDirection(he));
    -
    -  // Text contains HTML or HTML-escaping.
    -  assertEquals(LTR, ltrFmt.estimateDirection(
    -      '<some sort of tag/>' + he + ' &amp;', false));
    -  assertEquals(RTL, ltrFmt.estimateDirection(
    -      '<some sort of tag/>' + he + ' &amp;', true));
    -}
    -
    -function testDirAttrValue() {
    -  assertEquals('overall dir is RTL, context dir is LTR',
    -      'rtl', ltrFmt.dirAttrValue(he, true));
    -  assertEquals('overall dir and context dir are RTL',
    -      'rtl', rtlFmt.dirAttrValue(he, true));
    -  assertEquals('overall dir is LTR, context dir is RTL',
    -      'ltr', rtlFmt.dirAttrValue(en, true));
    -  assertEquals('overall dir and context dir are LTR',
    -      'ltr', ltrFmt.dirAttrValue(en, true));
    -
    -  // Input's directionality is neutral.
    -  assertEquals('ltr', ltrFmt.dirAttrValue('', true));
    -  assertEquals('rtl', rtlFmt.dirAttrValue('', true));
    -  assertEquals('ltr', unkFmt.dirAttrValue('', true));
    -
    -  // Text contains HTML or HTML-escaping:
    -  assertEquals('rtl',
    -      ltrFmt.dirAttrValue(he + '<some sort of an HTML tag>', true));
    -  assertEquals('ltr',
    -      ltrFmt.dirAttrValue(he + '<some sort of an HTML tag>', false));
    -}
    -
    -function testKnownDirAttrValue() {
    -  assertEquals('rtl', ltrFmt.knownDirAttrValue(RTL));
    -  assertEquals('rtl', rtlFmt.knownDirAttrValue(RTL));
    -  assertEquals('rtl', unkFmt.knownDirAttrValue(RTL));
    -  assertEquals('ltr', rtlFmt.knownDirAttrValue(LTR));
    -  assertEquals('ltr', ltrFmt.knownDirAttrValue(LTR));
    -  assertEquals('ltr', unkFmt.knownDirAttrValue(LTR));
    -
    -  // Input directionality is neutral.
    -  assertEquals('ltr', ltrFmt.knownDirAttrValue(NEUTRAL));
    -  assertEquals('rtl', rtlFmt.knownDirAttrValue(NEUTRAL));
    -  assertEquals('ltr', unkFmt.knownDirAttrValue(NEUTRAL));
    -}
    -
    -function testDirAttr() {
    -  assertEquals('overall dir (RTL) doesnt match context dir (LTR)',
    -      'dir="rtl"', ltrFmt.dirAttr(he, true));
    -  assertEquals('overall dir (RTL) doesnt match context dir (unknown)',
    -      'dir="rtl"', unkFmt.dirAttr(he, true));
    -  assertEquals('overall dir matches context dir (RTL)',
    -      '', rtlFmt.dirAttr(he, true));
    -
    -  assertEquals('overall dir (LTR) doesnt match context dir (RTL)',
    -      'dir="ltr"', rtlFmt.dirAttr(en, true));
    -  assertEquals('overall dir (LTR) doesnt match context dir (unknown)',
    -      'dir="ltr"', unkFmt.dirAttr(en, true));
    -  assertEquals('overall dir matches context dir (LTR)',
    -      '', ltrFmt.dirAttr(en, true));
    -
    -  assertEquals('neutral in RTL context',
    -      '', rtlFmt.dirAttr('.', true));
    -  assertEquals('neutral in LTR context',
    -      '', ltrFmt.dirAttr('.', true));
    -  assertEquals('neutral in unknown context',
    -      '', unkFmt.dirAttr('.', true));
    -
    -  // Text contains HTML or HTML-escaping:
    -  assertEquals('dir="rtl"',
    -      ltrFmt.dirAttr(he + '<some sort of an HTML tag>', true));
    -  assertEquals('',
    -      ltrFmt.dirAttr(he + '<some sort of an HTML tag>', false));
    -}
    -
    -function testKnownDirAttr() {
    -  assertEquals('overall dir (RTL) doesnt match context dir (LTR)',
    -      'dir="rtl"', ltrFmt.knownDirAttr(RTL));
    -  assertEquals('overall dir matches context dir (RTL)',
    -      '', rtlFmt.knownDirAttr(RTL));
    -  assertEquals('overall dir (LTR) doesnt match context dir (RTL)',
    -      'dir="ltr"', rtlFmt.knownDirAttr(LTR));
    -  assertEquals('overall dir matches context dir (LTR)',
    -      '', ltrFmt.knownDirAttr(LTR));
    -}
    -
    -function testSpanWrap() {
    -  // alwaysSpan is false and opt_isHtml is true, unless specified otherwise.
    -  assertEquals('overall dir matches context dir (LTR), no dirReset',
    -      en, ltrFmt.spanWrap(en, true, false));
    -  assertEquals('overall dir matches context dir (LTR), dirReset',
    -      en, ltrFmt.spanWrap(en, true, true));
    -  assertEquals('overall dir matches context dir (RTL), no dirReset',
    -      he, rtlFmt.spanWrap(he, true, false));
    -  assertEquals('overall dir matches context dir (RTL), dirReset',
    -      he, rtlFmt.spanWrap(he, true, true));
    -
    -  assertEquals('overall dir (RTL) doesnt match context dir (LTR), ' +
    -      'no dirReset',
    -      '<span dir="rtl">' + he + '<\/span>', ltrFmt.spanWrap(he, true, false));
    -  assertEquals('overall dir (RTL) doesnt match context dir (LTR), dirReset',
    -      '<span dir="rtl">' + he + '<\/span>' + LRM,
    -      ltrFmt.spanWrap(he, true, true));
    -  assertEquals('overall dir (LTR) doesnt match context dir (RTL), ' +
    -      'no dirReset',
    -      '<span dir="ltr">' + en + '<\/span>', rtlFmt.spanWrap(en, true, false));
    -  assertEquals('overall dir (LTR) doesnt match context dir (RTL), dirReset',
    -      '<span dir="ltr">' + en + '<\/span>' + RLM,
    -      rtlFmt.spanWrap(en, true, true));
    -  assertEquals('overall dir (LTR) doesnt match context dir (unknown), ' +
    -      'no dirReset',
    -      '<span dir="ltr">' + en + '<\/span>', unkFmt.spanWrap(en, true, false));
    -  assertEquals('overall dir (RTL) doesnt match context dir (unknown), ' +
    -      'dirReset',
    -      '<span dir="rtl">' + he + '<\/span>', unkFmt.spanWrap(he, true, true));
    -  assertEquals('overall dir (neutral) doesnt match context dir (LTR), ' +
    -      'dirReset',
    -      '',
    -      ltrFmt.spanWrap('', true, true));
    -
    -  assertEquals('exit dir (but not overall dir) is opposite to context dir, ' +
    -      'dirReset',
    -      longEn + he + html + LRM,
    -      ltrFmt.spanWrap(longEn + he + html, true, true));
    -  assertEquals('overall dir (but not exit dir) is opposite to context dir, ' +
    -      'dirReset',
    -      '<span dir="ltr">' + longEn + he + '<\/span>' + RLM,
    -      rtlFmt.spanWrap(longEn + he, true, true));
    -
    -  assertEquals('input is plain text (not escaped)',
    -      '&lt;br&gt;' + en,
    -      ltrFmt.spanWrap('<br>' + en, false, false));
    -
    -  var ltrAlwaysSpanFmt = new goog.i18n.BidiFormatter(LTR, true);
    -  var rtlAlwaysSpanFmt = new goog.i18n.BidiFormatter(RTL, true);
    -  var unkAlwaysSpanFmt = new goog.i18n.BidiFormatter(null, true);
    -
    -  assertEquals('alwaysSpan, overall dir matches context dir (LTR), ' +
    -      'no dirReset',
    -      '<span>' + en + '<\/span>', ltrAlwaysSpanFmt.spanWrap(en, true, false));
    -  assertEquals('alwaysSpan, overall dir matches context dir (LTR), dirReset',
    -      '<span>' + en + '<\/span>', ltrAlwaysSpanFmt.spanWrap(en, true, true));
    -  assertEquals('alwaysSpan, overall dir matches context dir (RTL), ' +
    -      'no dirReset',
    -      '<span>' + he + '<\/span>', rtlAlwaysSpanFmt.spanWrap(he, true, false));
    -  assertEquals('alwaysSpan, overall dir matches context dir (RTL), dirReset',
    -      '<span>' + he + '<\/span>', rtlAlwaysSpanFmt.spanWrap(he, true, true));
    -
    -  assertEquals('alwaysSpan, overall dir (RTL) doesnt match ' +
    -      'context dir (LTR), no dirReset',
    -      '<span dir="rtl">' + he + '<\/span>',
    -      ltrAlwaysSpanFmt.spanWrap(he, true, false));
    -  assertEquals('alwaysSpan, overall dir (RTL) doesnt match ' +
    -      'context dir (LTR), dirReset',
    -      '<span dir="rtl">' + he + '<\/span>' + LRM,
    -      ltrAlwaysSpanFmt.spanWrap(he, true, true));
    -  assertEquals('alwaysSpan, overall dir (neutral) doesnt match ' +
    -      'context dir (LTR), dirReset',
    -      '<span></span>',
    -      ltrAlwaysSpanFmt.spanWrap('', true, true));
    -}
    -
    -function testSpanWrapSafeHtml() {
    -  var html = goog.html.SafeHtml.htmlEscape('a');
    -  var wrapped = rtlFmt.spanWrapSafeHtml(html, false);
    -  assertHtmlEquals('<span dir="ltr">a</span>', wrapped);
    -  assertEquals(NEUTRAL, wrapped.getDirection());
    -}
    -
    -function testSpanWrapWithKnownDir() {
    -  assertEquals('known LTR in LTR context',
    -      en, ltrFmt.spanWrapWithKnownDir(LTR, en));
    -  assertEquals('unknown LTR in LTR context',
    -      en, ltrFmt.spanWrapWithKnownDir(null, en));
    -  assertEquals('overall LTR but exit RTL in LTR context',
    -      he + LRM, ltrFmt.spanWrapWithKnownDir(LTR, he));
    -  assertEquals('known RTL in LTR context',
    -      '<span dir="rtl">' + he + '<\/span>' + LRM,
    -      ltrFmt.spanWrapWithKnownDir(RTL, he));
    -  assertEquals('unknown RTL in LTR context',
    -      '<span dir="rtl">' + he + '<\/span>' + LRM,
    -      ltrFmt.spanWrapWithKnownDir(null, he));
    -  assertEquals('overall RTL but exit LTR in LTR context',
    -      '<span dir="rtl">' + en + '<\/span>' + LRM,
    -      ltrFmt.spanWrapWithKnownDir(RTL, en));
    -  assertEquals('known neutral in LTR context',
    -      '.', ltrFmt.spanWrapWithKnownDir(NEUTRAL, '.'));
    -  assertEquals('unknown neutral in LTR context',
    -      '.', ltrFmt.spanWrapWithKnownDir(null, '.'));
    -  assertEquals('overall neutral but exit LTR in LTR context',
    -      en, ltrFmt.spanWrapWithKnownDir(NEUTRAL, en));
    -  assertEquals('overall neutral but exit RTL in LTR context',
    -      he + LRM, ltrFmt.spanWrapWithKnownDir(NEUTRAL, he));
    -
    -  assertEquals('known RTL in RTL context',
    -      he, rtlFmt.spanWrapWithKnownDir(RTL, he));
    -  assertEquals('unknown RTL in RTL context',
    -      he, rtlFmt.spanWrapWithKnownDir(null, he));
    -  assertEquals('overall RTL but exit LTR in RTL context',
    -      en + RLM, rtlFmt.spanWrapWithKnownDir(RTL, en));
    -  assertEquals('known LTR in RTL context',
    -      '<span dir="ltr">' + en + '<\/span>' + RLM,
    -      rtlFmt.spanWrapWithKnownDir(LTR, en));
    -  assertEquals('unknown LTR in RTL context',
    -      '<span dir="ltr">' + en + '<\/span>' + RLM,
    -      rtlFmt.spanWrapWithKnownDir(null, en));
    -  assertEquals('LTR but exit RTL in RTL context',
    -      '<span dir="ltr">' + he + '<\/span>' + RLM,
    -      rtlFmt.spanWrapWithKnownDir(LTR, he));
    -  assertEquals('known neutral in RTL context',
    -      '.', rtlFmt.spanWrapWithKnownDir(NEUTRAL, '.'));
    -  assertEquals('unknown neutral in RTL context',
    -      '.', rtlFmt.spanWrapWithKnownDir(null, '.'));
    -  assertEquals('overall neutral but exit LTR in LTR context',
    -      he, rtlFmt.spanWrapWithKnownDir(NEUTRAL, he));
    -  assertEquals('overall neutral but exit RTL in LTR context',
    -      en + RLM, rtlFmt.spanWrapWithKnownDir(NEUTRAL, en));
    -
    -  assertEquals('known RTL in unknown context',
    -      '<span dir="rtl">' + he + '<\/span>',
    -      unkFmt.spanWrapWithKnownDir(RTL, he));
    -  assertEquals('unknown RTL in unknown context',
    -      '<span dir="rtl">' + he + '<\/span>',
    -      unkFmt.spanWrapWithKnownDir(null, he));
    -  assertEquals('overall RTL but exit LTR in unknown context',
    -      '<span dir="rtl">' + en + '<\/span>',
    -      unkFmt.spanWrapWithKnownDir(RTL, en));
    -  assertEquals('known LTR in unknown context',
    -      '<span dir="ltr">' + en + '<\/span>',
    -      unkFmt.spanWrapWithKnownDir(LTR, en));
    -  assertEquals('unknown LTR in unknown context',
    -      '<span dir="ltr">' + en + '<\/span>',
    -      unkFmt.spanWrapWithKnownDir(null, en));
    -  assertEquals('LTR but exit RTL in unknown context',
    -      '<span dir="ltr">' + he + '<\/span>',
    -      unkFmt.spanWrapWithKnownDir(LTR, he));
    -  assertEquals('known neutral in unknown context',
    -      '.', unkFmt.spanWrapWithKnownDir(NEUTRAL, '.'));
    -  assertEquals('unknown neutral in unknown context',
    -      '.', unkFmt.spanWrapWithKnownDir(null, '.'));
    -  assertEquals('overall neutral but exit LTR in unknown context',
    -      he, unkFmt.spanWrapWithKnownDir(NEUTRAL, he));
    -  assertEquals('overall neutral but exit RTL in unknown context',
    -      en, unkFmt.spanWrapWithKnownDir(NEUTRAL, en));
    -}
    -
    -function testSpanWrapSafeHtmlWithKnownDir() {
    -  var html = goog.html.SafeHtml.htmlEscape('a');
    -  assertHtmlEquals('<span dir="ltr">a</span>',
    -      rtlFmt.spanWrapSafeHtmlWithKnownDir(LTR, html, false));
    -}
    -
    -function testUnicodeWrap() {
    -  // opt_isHtml is true, unless specified otherwise.
    -  assertEquals('overall dir matches context dir (LTR), no dirReset',
    -      en, ltrFmt.unicodeWrap(en, true, false));
    -  assertEquals('overall dir matches context dir (LTR), dirReset',
    -      en, ltrFmt.unicodeWrap(en, true, true));
    -  assertEquals('overall dir matches context dir (RTL), no dirReset',
    -      he, rtlFmt.unicodeWrap(he, true, false));
    -  assertEquals('overall dir matches context dir (RTL), dirReset',
    -      he, rtlFmt.unicodeWrap(he, true, true));
    -
    -  assertEquals('overall dir (RTL) doesnt match context dir (LTR), ' +
    -      'no dirReset',
    -      RLE + he + PDF, ltrFmt.unicodeWrap(he, true, false));
    -  assertEquals('overall dir (RTL) doesnt match context dir (LTR), dirReset',
    -      RLE + he + PDF + LRM, ltrFmt.unicodeWrap(he, true, true));
    -  assertEquals('overall dir (LTR) doesnt match context dir (RTL), ' +
    -      'no dirReset',
    -      LRE + en + PDF, rtlFmt.unicodeWrap(en, true, false));
    -  assertEquals('overall dir (LTR) doesnt match context dir (RTL), dirReset',
    -      LRE + en + PDF + RLM, rtlFmt.unicodeWrap(en, true, true));
    -  assertEquals('overall dir (LTR) doesnt match context dir (unknown), ' +
    -      'no dirReset',
    -      LRE + en + PDF, unkFmt.unicodeWrap(en, true, false));
    -  assertEquals('overall dir (RTL) doesnt match context dir (unknown), ' +
    -      'dirReset',
    -      RLE + he + PDF, unkFmt.unicodeWrap(he, true, true));
    -  assertEquals('overall dir (neutral) doesnt match context dir (LTR), ' +
    -      'dirReset',
    -      '',
    -      ltrFmt.unicodeWrap('', true, true));
    -
    -  assertEquals('exit dir (but not overall dir) is opposite to context dir, ' +
    -      'dirReset',
    -      longEn + he + html + LRM,
    -      ltrFmt.unicodeWrap(longEn + he + html, true, true));
    -  assertEquals('overall dir (but not exit dir) is opposite to context dir, ' +
    -      'dirReset',
    -      LRE + longEn + he + PDF + RLM,
    -      rtlFmt.unicodeWrap(longEn + he, true, true));
    -}
    -
    -function testUnicodeWrapWithKnownDir() {
    -  assertEquals('known LTR in LTR context',
    -      en, ltrFmt.unicodeWrapWithKnownDir(LTR, en));
    -  assertEquals('unknown LTR in LTR context',
    -      en, ltrFmt.unicodeWrapWithKnownDir(null, en));
    -  assertEquals('overall LTR but exit RTL in LTR context',
    -      he + LRM, ltrFmt.unicodeWrapWithKnownDir(LTR, he));
    -  assertEquals('known RTL in LTR context',
    -      RLE + he + PDF + LRM,
    -      ltrFmt.unicodeWrapWithKnownDir(RTL, he));
    -  assertEquals('unknown RTL in LTR context',
    -      RLE + he + PDF + LRM,
    -      ltrFmt.unicodeWrapWithKnownDir(null, he));
    -  assertEquals('overall RTL but exit LTR in LTR context',
    -      RLE + en + PDF + LRM,
    -      ltrFmt.unicodeWrapWithKnownDir(RTL, en));
    -  assertEquals('known neutral in LTR context',
    -      '.', ltrFmt.unicodeWrapWithKnownDir(NEUTRAL, '.'));
    -  assertEquals('unknown neutral in LTR context',
    -      '.', ltrFmt.unicodeWrapWithKnownDir(null, '.'));
    -  assertEquals('overall neutral but exit LTR in LTR context',
    -      en, ltrFmt.unicodeWrapWithKnownDir(NEUTRAL, en));
    -  assertEquals('overall neutral but exit RTL in LTR context',
    -      he + LRM,
    -      ltrFmt.unicodeWrapWithKnownDir(NEUTRAL, he));
    -
    -  assertEquals('known RTL in RTL context',
    -      he, rtlFmt.unicodeWrapWithKnownDir(RTL, he));
    -  assertEquals('unknown RTL in RTL context',
    -      he, rtlFmt.unicodeWrapWithKnownDir(null, he));
    -  assertEquals('overall RTL but exit LTR in RTL context',
    -      en + RLM, rtlFmt.unicodeWrapWithKnownDir(RTL, en));
    -  assertEquals('known LTR in RTL context',
    -      LRE + en + PDF + RLM,
    -      rtlFmt.unicodeWrapWithKnownDir(LTR, en));
    -  assertEquals('unknown LTR in RTL context',
    -      LRE + en + PDF + RLM,
    -      rtlFmt.unicodeWrapWithKnownDir(null, en));
    -  assertEquals('LTR but exit RTL in RTL context',
    -      LRE + he + PDF + RLM,
    -      rtlFmt.unicodeWrapWithKnownDir(LTR, he));
    -  assertEquals('known neutral in RTL context',
    -      '.', rtlFmt.unicodeWrapWithKnownDir(NEUTRAL, '.'));
    -  assertEquals('unknown neutral in RTL context',
    -      '.', rtlFmt.unicodeWrapWithKnownDir(null, '.'));
    -  assertEquals('overall neutral but exit LTR in LTR context',
    -      he, rtlFmt.unicodeWrapWithKnownDir(NEUTRAL, he));
    -  assertEquals('overall neutral but exit RTL in LTR context',
    -      en + RLM,
    -      rtlFmt.unicodeWrapWithKnownDir(NEUTRAL, en));
    -
    -  assertEquals('known RTL in unknown context',
    -      RLE + he + PDF,
    -      unkFmt.unicodeWrapWithKnownDir(RTL, he));
    -  assertEquals('unknown RTL in unknown context',
    -      RLE + he + PDF,
    -      unkFmt.unicodeWrapWithKnownDir(null, he));
    -  assertEquals('overall RTL but exit LTR in unknown context',
    -      RLE + en + PDF,
    -      unkFmt.unicodeWrapWithKnownDir(RTL, en));
    -  assertEquals('known LTR in unknown context',
    -      LRE + en + PDF,
    -      unkFmt.unicodeWrapWithKnownDir(LTR, en));
    -  assertEquals('unknown LTR in unknown context',
    -      LRE + en + PDF,
    -      unkFmt.unicodeWrapWithKnownDir(null, en));
    -  assertEquals('LTR but exit RTL in unknown context',
    -      LRE + he + PDF,
    -      unkFmt.unicodeWrapWithKnownDir(LTR, he));
    -  assertEquals('known neutral in unknown context',
    -      '.', unkFmt.unicodeWrapWithKnownDir(NEUTRAL, '.'));
    -  assertEquals('unknown neutral in unknown context',
    -      '.', unkFmt.unicodeWrapWithKnownDir(null, '.'));
    -  assertEquals('overall neutral but exit LTR in unknown context',
    -      he, unkFmt.unicodeWrapWithKnownDir(NEUTRAL, he));
    -  assertEquals('overall neutral but exit RTL in unknown context',
    -      en, unkFmt.unicodeWrapWithKnownDir(NEUTRAL, en));
    -}
    -
    -function testMarkAfter() {
    -  assertEquals('exit dir (RTL) is opposite to context dir (LTR)',
    -      LRM, ltrFmt.markAfter(longEn + he + html, true));
    -  assertEquals('exit dir (LTR) is opposite to context dir (RTL)',
    -      RLM, rtlFmt.markAfter(longHe + en, true));
    -  assertEquals('exit dir (LTR) doesnt match context dir (unknown)',
    -      '', unkFmt.markAfter(longEn + en, true));
    -  assertEquals('overall dir (RTL) is opposite to context dir (LTR)',
    -      LRM, ltrFmt.markAfter(longHe + en, true));
    -  assertEquals('overall dir (LTR) is opposite to context dir (RTL)',
    -      RLM, rtlFmt.markAfter(longEn + he, true));
    -  assertEquals('exit dir and overall dir match context dir (LTR)',
    -      '', ltrFmt.markAfter(longEn + he + html, false));
    -  assertEquals('exit dir and overall dir matches context dir (RTL)',
    -      '', rtlFmt.markAfter(longHe + he, true));
    -}
    -
    -function testMarkAfterKnownDir() {
    -  assertEquals('known LTR in LTR context',
    -      '', ltrFmt.markAfterKnownDir(LTR, en));
    -  assertEquals('unknown LTR in LTR context',
    -      '', ltrFmt.markAfterKnownDir(null, en));
    -  assertEquals('overall LTR but exit RTL in LTR context',
    -      LRM, ltrFmt.markAfterKnownDir(LTR, he));
    -  assertEquals('known RTL in LTR context',
    -      LRM, ltrFmt.markAfterKnownDir(RTL, he));
    -  assertEquals('unknown RTL in LTR context',
    -      LRM, ltrFmt.markAfterKnownDir(null, he));
    -  assertEquals('overall RTL but exit LTR in LTR context',
    -      LRM, ltrFmt.markAfterKnownDir(RTL, en));
    -  assertEquals('known neutral in LTR context',
    -      '', ltrFmt.markAfterKnownDir(NEUTRAL, '.'));
    -  assertEquals('unknown neutral in LTR context',
    -      '', ltrFmt.markAfterKnownDir(null, '.'));
    -  assertEquals('overall neutral but exit LTR in LTR context',
    -      '', ltrFmt.markAfterKnownDir(NEUTRAL, en));
    -  assertEquals('overall neutral but exit RTL in LTR context',
    -      LRM, ltrFmt.markAfterKnownDir(NEUTRAL, he));
    -
    -  assertEquals('known RTL in RTL context',
    -      '', rtlFmt.markAfterKnownDir(RTL, he));
    -  assertEquals('unknown RTL in RTL context',
    -      '', rtlFmt.markAfterKnownDir(null, he));
    -  assertEquals('overall RTL but exit LTR in RTL context',
    -      RLM, rtlFmt.markAfterKnownDir(RTL, en));
    -  assertEquals('known LTR in RTL context',
    -      RLM, rtlFmt.markAfterKnownDir(LTR, en));
    -  assertEquals('unknown LTR in RTL context',
    -      RLM, rtlFmt.markAfterKnownDir(null, en));
    -  assertEquals('LTR but exit RTL in RTL context',
    -      RLM, rtlFmt.markAfterKnownDir(LTR, he));
    -  assertEquals('known neutral in RTL context',
    -      '', rtlFmt.markAfterKnownDir(NEUTRAL, '.'));
    -  assertEquals('unknown neutral in RTL context',
    -      '', rtlFmt.markAfterKnownDir(null, '.'));
    -  assertEquals('overall neutral but exit LTR in LTR context',
    -      '', rtlFmt.markAfterKnownDir(NEUTRAL, he));
    -  assertEquals('overall neutral but exit RTL in LTR context',
    -      RLM, rtlFmt.markAfterKnownDir(NEUTRAL, en));
    -
    -  assertEquals('known RTL in unknown context',
    -      '', unkFmt.markAfterKnownDir(RTL, he));
    -  assertEquals('unknown RTL in unknown context',
    -      '', unkFmt.markAfterKnownDir(null, he));
    -  assertEquals('overall RTL but exit LTR in unknown context',
    -      '', unkFmt.markAfterKnownDir(RTL, en));
    -  assertEquals('known LTR in unknown context',
    -      '', unkFmt.markAfterKnownDir(LTR, en));
    -  assertEquals('unknown LTR in unknown context',
    -      '', unkFmt.markAfterKnownDir(null, en));
    -  assertEquals('LTR but exit RTL in unknown context',
    -      '', unkFmt.markAfterKnownDir(LTR, he));
    -  assertEquals('known neutral in unknown context',
    -      '', unkFmt.markAfterKnownDir(NEUTRAL, '.'));
    -  assertEquals('unknown neutral in unknown context',
    -      '', unkFmt.markAfterKnownDir(null, '.'));
    -  assertEquals('overall neutral but exit LTR in unknown context',
    -      '', unkFmt.markAfterKnownDir(NEUTRAL, he));
    -  assertEquals('overall neutral but exit RTL in unknown context',
    -      '', unkFmt.markAfterKnownDir(NEUTRAL, en));
    -}
    -
    -function testMark() {
    -  // Implicitly, also tests the constructor.
    -  assertEquals(LRM, (new goog.i18n.BidiFormatter(LTR)).mark());
    -  assertEquals('', (new goog.i18n.BidiFormatter(null)).mark());
    -  assertEquals('', (new goog.i18n.BidiFormatter(NEUTRAL)).mark());
    -  assertEquals(RLM, (new goog.i18n.BidiFormatter(RTL)).mark());
    -  assertEquals(RLM, (new goog.i18n.BidiFormatter(true)).mark());
    -  assertEquals(LRM, (new goog.i18n.BidiFormatter(false)).mark());
    -}
    -
    -function testStartEdge() {
    -  assertEquals('left', ltrFmt.startEdge());
    -  assertEquals('left', unkFmt.startEdge());
    -  assertEquals('right', rtlFmt.startEdge());
    -}
    -
    -function testEndEdge() {
    -  assertEquals('right', ltrFmt.endEdge());
    -  assertEquals('right', unkFmt.endEdge());
    -  assertEquals('left', rtlFmt.endEdge());
    -}
    -
    -function assertHtmlEquals(expected, html) {
    -  assertEquals(expected, goog.html.SafeHtml.unwrap(html));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/charlistdecompressor.js b/src/database/third_party/closure-library/closure/goog/i18n/charlistdecompressor.js
    deleted file mode 100644
    index 48fae13d13a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/charlistdecompressor.js
    +++ /dev/null
    @@ -1,158 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview The decompressor for Base88 compressed character lists.
    - *
    - * The compression is by base 88 encoding the delta between two adjacent
    - * characters in ths list. The deltas can be positive or negative. Also, there
    - * would be character ranges. These three types of values
    - * are given enum values 0, 1 and 2 respectively. Initial 3 bits are used for
    - * encoding the type and total length of the encoded value. Length enums 0, 1
    - * and 2 represents lengths 1, 2 and 4. So (value * 8 + type * 3 + length enum)
    - * is encoded in base 88 by following characters for numbers from 0 to 87:
    - * 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ (continued in next line)
    - * abcdefghijklmnopqrstuvwxyz!#$%()*+,-.:;<=>?@[]^_`{|}~
    - *
    - * Value uses 0 based counting. That is value for the range [a, b] is 0 and
    - * that of [a, c] is 1. Simillarly, the delta of "ab" is 0.
    - *
    - * Following python script can be used to compress character lists taken
    - * standard input: http://go/charlistcompressor.py
    - *
    - */
    -
    -goog.provide('goog.i18n.CharListDecompressor');
    -
    -goog.require('goog.array');
    -goog.require('goog.i18n.uChar');
    -
    -
    -
    -/**
    - * Class to decompress base88 compressed character list.
    - * @constructor
    - * @final
    - */
    -goog.i18n.CharListDecompressor = function() {
    -  this.buildCharMap_('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr' +
    -      'stuvwxyz!#$%()*+,-.:;<=>?@[]^_`{|}~');
    -};
    -
    -
    -/**
    - * 1-1 mapping from ascii characters used in encoding to an integer in the
    - * range 0 to 87.
    - * @type {Object}
    - * @private
    - */
    -goog.i18n.CharListDecompressor.prototype.charMap_ = null;
    -
    -
    -/**
    - * Builds the map from ascii characters used for the base88 scheme to number
    - * each character represents.
    - * @param {string} str The string of characters used in base88 scheme.
    - * @private
    - */
    -goog.i18n.CharListDecompressor.prototype.buildCharMap_ = function(str) {
    -  if (!this.charMap_) {
    -    this.charMap_ = {};
    -    for (var i = 0; i < str.length; i++) {
    -      this.charMap_[str.charAt(i)] = i;
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Gets the number encoded in base88 scheme by a substring of given length
    - * and placed at the a given position of the string.
    - * @param {string} str String containing sequence of characters encoding a
    - *     number in base 88 scheme.
    - * @param {number} start Starting position of substring encoding the number.
    - * @param {number} leng Length of the substring encoding the number.
    - * @return {number} The encoded number.
    - * @private
    - */
    -goog.i18n.CharListDecompressor.prototype.getCodeAt_ = function(str, start,
    -    leng) {
    -  var result = 0;
    -  for (var i = 0; i < leng; i++) {
    -    var c = this.charMap_[str.charAt(start + i)];
    -    result += c * Math.pow(88, i);
    -  }
    -  return result;
    -};
    -
    -
    -/**
    - * Add character(s) specified by the value and type to given list and return
    - * the next character in the sequence.
    - * @param {Array<string>} list The list of characters to which the specified
    - *     characters are appended.
    - * @param {number} lastcode The last codepoint that was added to the list.
    - * @param {number} value The value component that representing the delta or
    - *      range.
    - * @param {number} type The type component that representing whether the value
    - *      is a positive or negative delta or range.
    - * @return {number} Last codepoint that is added to the list.
    - * @private
    - */
    -goog.i18n.CharListDecompressor.prototype.addChars_ = function(list, lastcode,
    -    value, type) {
    -   if (type == 0) {
    -     lastcode += value + 1;
    -     goog.array.extend(list, goog.i18n.uChar.fromCharCode(lastcode));
    -   } else if (type == 1) {
    -     lastcode -= value + 1;
    -     goog.array.extend(list, goog.i18n.uChar.fromCharCode(lastcode));
    -   } else if (type == 2) {
    -     for (var i = 0; i <= value; i++) {
    -       lastcode++;
    -       goog.array.extend(list, goog.i18n.uChar.fromCharCode(lastcode));
    -     }
    -   }
    -  return lastcode;
    -};
    -
    -
    -/**
    - * Gets the list of characters specified in the given string by base 88 scheme.
    - * @param {string} str The string encoding character list.
    - * @return {!Array<string>} The list of characters specified by the given
    - *     string in base 88 scheme.
    - */
    -goog.i18n.CharListDecompressor.prototype.toCharList = function(str) {
    -  var metasize = 8;
    -  var result = [];
    -  var lastcode = 0;
    -  var i = 0;
    -  while (i < str.length) {
    -    var c = this.charMap_[str.charAt(i)];
    -    var meta = c % metasize;
    -    var type = Math.floor(meta / 3);
    -    var leng = (meta % 3) + 1;
    -    if (leng == 3) {
    -      leng++;
    -    }
    -    var code = this.getCodeAt_(str, i, leng);
    -    var value = Math.floor(code / metasize);
    -    lastcode = this.addChars_(result, lastcode, value, type);
    -
    -    i += leng;
    -  }
    -  return result;
    -};
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/charlistdecompressor_test.html b/src/database/third_party/closure-library/closure/goog/i18n/charlistdecompressor_test.html
    deleted file mode 100644
    index 4541a9735c2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/charlistdecompressor_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.i18n.CharListDecompressor
    -  </title>
    -  <meta charset="utf-8" />
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.i18n.CharListDecompressorTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/charlistdecompressor_test.js b/src/database/third_party/closure-library/closure/goog/i18n/charlistdecompressor_test.js
    deleted file mode 100644
    index e9913e2da3f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/charlistdecompressor_test.js
    +++ /dev/null
    @@ -1,58 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.i18n.CharListDecompressorTest');
    -goog.setTestOnly('goog.i18n.CharListDecompressorTest');
    -
    -goog.require('goog.i18n.CharListDecompressor');
    -goog.require('goog.testing.jsunit');
    -
    -var decompressor = new goog.i18n.CharListDecompressor();
    -
    -function testBuildCharMap() {
    -  assertEquals(0, decompressor.charMap_['0']);
    -  assertEquals(10, decompressor.charMap_['A']);
    -  assertEquals(87, decompressor.charMap_['}']);
    -}
    -
    -function testGetCodeAt() {
    -  var code = decompressor.getCodeAt_('321', 1, 2);
    -  assertEquals(90, code);
    -}
    -
    -function testAddCharsForType0() {
    -  var list = ['a'];
    -  var lastcode = decompressor.addChars_(list, 97, 0, 0);
    -  assertArrayEquals(['a', 'b'], list);
    -  assertEquals(98, lastcode);
    -}
    -
    -function testAddCharsForType1() {
    -  var list = ['a'];
    -  var lastcode = decompressor.addChars_(list, 98, 0, 1);
    -  assertArrayEquals(['a', 'a'], list);
    -  assertEquals(97, lastcode);
    -}
    -
    -function testAddCharsForType2() {
    -  var list = ['a'];
    -  var lastcode = decompressor.addChars_(list, 97, 1, 2);
    -  assertArrayEquals(['a', 'b', 'c'], list);
    -  assertEquals(99, lastcode);
    -}
    -
    -function testToCharList() {
    -  var list = decompressor.toCharList('%812E<E'); // a, x-z, p-r
    -  assertArrayEquals(['a', 'x', 'y', 'z', 'p', 'q', 'r'], list);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/charpickerdata.js b/src/database/third_party/closure-library/closure/goog/i18n/charpickerdata.js
    deleted file mode 100644
    index 4e34f0627fb..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/charpickerdata.js
    +++ /dev/null
    @@ -1,3667 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Character lists and their classifications used by character
    - * picker widget. Autogenerated from Unicode data:
    - * https://sites/cibu/character-picker.
    - *
    - */
    -
    -goog.provide('goog.i18n.CharPickerData');
    -
    -
    -
    -/**
    - * Object holding two level character organization and character listing.
    - * @constructor
    - */
    -goog.i18n.CharPickerData = function() {};
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_SYMBOL = goog.getMsg('Symbol');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_ARROWS = goog.getMsg('Arrows');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_BRAILLE = goog.getMsg('Braille');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_CONTROL_PICTURES =
    -    goog.getMsg('Control Pictures');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_CURRENCY = goog.getMsg('Currency');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_EMOTICONS = goog.getMsg('Emoticons');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_GAME_PIECES = goog.getMsg('Game Pieces');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_GENDER_AND_GENEALOGICAL =
    -    goog.getMsg('Gender and Genealogical');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_GEOMETRIC_SHAPES =
    -    goog.getMsg('Geometric Shapes');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_KEYBOARD_AND_UI =
    -    goog.getMsg('Keyboard and UI');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_LATIN_1_SUPPLEMENT =
    -    goog.getMsg('Latin 1 Supplement');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_MATH = goog.getMsg('Math');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_MATH_ALPHANUMERIC =
    -    goog.getMsg('Math Alphanumeric');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_MISCELLANEOUS = goog.getMsg('Miscellaneous');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_MUSICAL = goog.getMsg('Musical');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_STARS_ASTERISKS =
    -    goog.getMsg('Stars/Asterisks');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_SUBSCRIPT = goog.getMsg('Subscript');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_SUPERSCRIPT = goog.getMsg('Superscript');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_TECHNICAL = goog.getMsg('Technical');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_TRANSPORT_AND_MAP =
    -    goog.getMsg('Transport And Map');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_WEATHER_AND_ASTROLOGICAL =
    -    goog.getMsg('Weather and Astrological');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_YIJING_TAI_XUAN_JING =
    -    goog.getMsg('Yijing / Tai Xuan Jing');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_HISTORIC = goog.getMsg('Historic');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY = goog.getMsg('Compatibility');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_EMOJI = goog.getMsg('Emoji');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_PEOPLE_AND_EMOTIONS =
    -    goog.getMsg('People and Emotions');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_ANIMALS_PLANTS_AND_FOOD =
    -    goog.getMsg('Animals, Plants and Food');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_OBJECTS = goog.getMsg('Objects');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_SPORTS_CELEBRATIONS_AND_ACTIVITIES =
    -    goog.getMsg('Sports, Celebrations and Activities');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_TRANSPORT_MAPS_AND_SIGNAGE =
    -    goog.getMsg('Transport, Maps and Signage');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_WEATHER_SCENES_AND_ZODIAC_SIGNS =
    -    goog.getMsg('Weather, Scenes and Zodiac signs');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_ENCLOSED = goog.getMsg('Enclosed');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_MARKS = goog.getMsg('Marks');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_SYMBOLS = goog.getMsg('Symbols');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_PUNCTUATION = goog.getMsg('Punctuation');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_ASCII_BASED = goog.getMsg('ASCII Based');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_DASH_CONNECTOR = goog.getMsg('Dash/Connector');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_OTHER = goog.getMsg('Other');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_PAIRED = goog.getMsg('Paired');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_NUMBER = goog.getMsg('Number');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_DECIMAL = goog.getMsg('Decimal');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_ENCLOSED_DOTTED =
    -    goog.getMsg('Enclosed/Dotted');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_FRACTIONS_RELATED =
    -    goog.getMsg('Fractions/Related');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_FORMAT_WHITESPACE =
    -    goog.getMsg('Format & Whitespace');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_FORMAT = goog.getMsg('Format');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_VARIATION_SELECTOR =
    -    goog.getMsg('Variation Selector');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_WHITESPACE = goog.getMsg('Whitespace');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_MODIFIER = goog.getMsg('Modifier');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_ENCLOSING = goog.getMsg('Enclosing');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_NONSPACING = goog.getMsg('Nonspacing');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_SPACING = goog.getMsg('Spacing');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_LATIN = goog.getMsg('Latin');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_COMMON = goog.getMsg('Common');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_FLIPPED_MIRRORED =
    -    goog.getMsg('Flipped/Mirrored');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_PHONETICS_IPA = goog.getMsg('Phonetics (IPA)');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_PHONETICS_X_IPA =
    -    goog.getMsg('Phonetics (X-IPA)');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_OTHER_EUROPEAN_SCRIPTS =
    -    goog.getMsg('Other European Scripts');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_ARMENIAN = goog.getMsg('Armenian');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_CYRILLIC = goog.getMsg('Cyrillic');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_GEORGIAN = goog.getMsg('Georgian');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_GREEK = goog.getMsg('Greek');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_CYPRIOT = goog.getMsg('Cypriot');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_GLAGOLITIC = goog.getMsg('Glagolitic');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_GOTHIC = goog.getMsg('Gothic');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_LINEAR_B = goog.getMsg('Linear B');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_OGHAM = goog.getMsg('Ogham');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_OLD_ITALIC = goog.getMsg('Old Italic');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_RUNIC = goog.getMsg('Runic');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_SHAVIAN = goog.getMsg('Shavian');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_AMERICAN_SCRIPTS =
    -    goog.getMsg('American Scripts');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_CANADIAN_ABORIGINAL =
    -    goog.getMsg('Canadian Aboriginal');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_CHEROKEE = goog.getMsg('Cherokee');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_DESERET = goog.getMsg('Deseret');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_AFRICAN_SCRIPTS =
    -    goog.getMsg('African Scripts');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_EGYPTIAN_HIEROGLYPHS =
    -    goog.getMsg('Egyptian Hieroglyphs');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_ETHIOPIC = goog.getMsg('Ethiopic');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_MEROITIC_CURSIVE =
    -    goog.getMsg('Meroitic Cursive');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_MEROITIC_HIEROGLYPHS =
    -    goog.getMsg('Meroitic Hieroglyphs');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_NKO = goog.getMsg('Nko');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_TIFINAGH = goog.getMsg('Tifinagh');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_VAI = goog.getMsg('Vai');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_BAMUM = goog.getMsg('Bamum');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_COPTIC = goog.getMsg('Coptic');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_OSMANYA = goog.getMsg('Osmanya');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_MIDDLE_EASTERN_SCRIPTS =
    -    goog.getMsg('Middle Eastern Scripts');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_ARABIC = goog.getMsg('Arabic');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_HEBREW = goog.getMsg('Hebrew');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_IMPERIAL_ARAMAIC =
    -    goog.getMsg('Imperial Aramaic');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_INSCRIPTIONAL_PAHLAVI =
    -    goog.getMsg('Inscriptional Pahlavi');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_INSCRIPTIONAL_PARTHIAN =
    -    goog.getMsg('Inscriptional Parthian');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_MANDAIC = goog.getMsg('Mandaic');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_OLD_SOUTH_ARABIAN =
    -    goog.getMsg('Old South Arabian');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_SAMARITAN = goog.getMsg('Samaritan');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_SYRIAC = goog.getMsg('Syriac');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_AVESTAN = goog.getMsg('Avestan');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_CARIAN = goog.getMsg('Carian');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_CUNEIFORM = goog.getMsg('Cuneiform');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_LYCIAN = goog.getMsg('Lycian');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_LYDIAN = goog.getMsg('Lydian');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_OLD_PERSIAN = goog.getMsg('Old Persian');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_PHOENICIAN = goog.getMsg('Phoenician');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_UGARITIC = goog.getMsg('Ugaritic');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_SOUTH_ASIAN_SCRIPTS =
    -    goog.getMsg('South Asian Scripts');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_BENGALI = goog.getMsg('Bengali');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_CHAKMA = goog.getMsg('Chakma');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_DEVANAGARI = goog.getMsg('Devanagari');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_GUJARATI = goog.getMsg('Gujarati');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_GURMUKHI = goog.getMsg('Gurmukhi');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_KANNADA = goog.getMsg('Kannada');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_LEPCHA = goog.getMsg('Lepcha');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_LIMBU = goog.getMsg('Limbu');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_MALAYALAM = goog.getMsg('Malayalam');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_MEETEI_MAYEK = goog.getMsg('Meetei Mayek');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_OL_CHIKI = goog.getMsg('Ol Chiki');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_ORIYA = goog.getMsg('Oriya');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_SAURASHTRA = goog.getMsg('Saurashtra');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_SINHALA = goog.getMsg('Sinhala');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_SORA_SOMPENG = goog.getMsg('Sora Sompeng');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_TAMIL = goog.getMsg('Tamil');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_TELUGU = goog.getMsg('Telugu');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_THAANA = goog.getMsg('Thaana');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_TIBETAN = goog.getMsg('Tibetan');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_BRAHMI = goog.getMsg('Brahmi');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_KAITHI = goog.getMsg('Kaithi');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_KHAROSHTHI = goog.getMsg('Kharoshthi');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_SHARADA = goog.getMsg('Sharada');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_SYLOTI_NAGRI = goog.getMsg('Syloti Nagri');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_TAKRI = goog.getMsg('Takri');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_SOUTHEAST_ASIAN_SCRIPTS =
    -    goog.getMsg('Southeast Asian Scripts');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_BALINESE = goog.getMsg('Balinese');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_BATAK = goog.getMsg('Batak');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_CHAM = goog.getMsg('Cham');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_JAVANESE = goog.getMsg('Javanese');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_KAYAH_LI = goog.getMsg('Kayah Li');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_KHMER = goog.getMsg('Khmer');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_LAO = goog.getMsg('Lao');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_MYANMAR = goog.getMsg('Myanmar');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_NEW_TAI_LUE = goog.getMsg('New Tai Lue');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_TAI_LE = goog.getMsg('Tai Le');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_TAI_THAM = goog.getMsg('Tai Tham');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_TAI_VIET = goog.getMsg('Tai Viet');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_THAI = goog.getMsg('Thai');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_BUGINESE = goog.getMsg('Buginese');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_BUHID = goog.getMsg('Buhid');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_HANUNOO = goog.getMsg('Hanunoo');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_REJANG = goog.getMsg('Rejang');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_SUNDANESE = goog.getMsg('Sundanese');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_TAGALOG = goog.getMsg('Tagalog');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_TAGBANWA = goog.getMsg('Tagbanwa');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_HANGUL = goog.getMsg('Hangul');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_OTHER_EAST_ASIAN_SCRIPTS =
    -    goog.getMsg('Other East Asian Scripts');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_BOPOMOFO = goog.getMsg('Bopomofo');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_HIRAGANA = goog.getMsg('Hiragana');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_KATAKANA = goog.getMsg('Katakana');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_LISU = goog.getMsg('Lisu');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_MIAO = goog.getMsg('Miao');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_MONGOLIAN = goog.getMsg('Mongolian');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_OLD_TURKIC = goog.getMsg('Old Turkic');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_PHAGS_PA = goog.getMsg('Phags Pa');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_YI = goog.getMsg('Yi');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_HAN_1_STROKE_RADICALS =
    -    goog.getMsg('Han 1-Stroke Radicals');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_LESS_COMMON = goog.getMsg('Less Common');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_HAN_2_STROKE_RADICALS =
    -    goog.getMsg('Han 2-Stroke Radicals');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_HAN_3_STROKE_RADICALS =
    -    goog.getMsg('Han 3-Stroke Radicals');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_HAN_4_STROKE_RADICALS =
    -    goog.getMsg('Han 4-Stroke Radicals');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_HAN_5_STROKE_RADICALS =
    -    goog.getMsg('Han 5-Stroke Radicals');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_HAN_6_STROKE_RADICALS =
    -    goog.getMsg('Han 6-Stroke Radicals');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_HAN_7_STROKE_RADICALS =
    -    goog.getMsg('Han 7-Stroke Radicals');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_HAN_8_STROKE_RADICALS =
    -    goog.getMsg('Han 8-Stroke Radicals');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_HAN_9_STROKE_RADICALS =
    -    goog.getMsg('Han 9-Stroke Radicals');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_HAN_10_STROKE_RADICALS =
    -    goog.getMsg('Han 10-Stroke Radicals');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_HAN_11_17_STROKE_RADICALS =
    -    goog.getMsg('Han 11..17-Stroke Radicals');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_HAN_OTHER = goog.getMsg('Han - Other');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_CJK_STROKES = goog.getMsg('CJK Strokes');
    -
    -
    -/**
    - * @desc Name for a symbol or character category. Used in a pull-down list
    - *   shown to a  document editing user trying to insert a special character.
    - *   Newlines are not allowed; translation should be a noun and as consise as
    - *   possible. More details:
    - *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    - * @type {string}
    - */
    -goog.i18n.CharPickerData.MSG_CP_IDEOGRAPHIC_DESCRIPTION =
    -    goog.getMsg('Ideographic Description');
    -
    -
    -/**
    - * Top catagory names of character organization.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.prototype.categories = [
    -  goog.i18n.CharPickerData.MSG_CP_SYMBOL,
    -  goog.i18n.CharPickerData.MSG_CP_EMOJI,
    -  goog.i18n.CharPickerData.MSG_CP_PUNCTUATION,
    -  goog.i18n.CharPickerData.MSG_CP_NUMBER,
    -  goog.i18n.CharPickerData.MSG_CP_FORMAT_WHITESPACE,
    -  goog.i18n.CharPickerData.MSG_CP_MODIFIER,
    -  goog.i18n.CharPickerData.MSG_CP_LATIN,
    -  goog.i18n.CharPickerData.MSG_CP_OTHER_EUROPEAN_SCRIPTS,
    -  goog.i18n.CharPickerData.MSG_CP_AMERICAN_SCRIPTS,
    -  goog.i18n.CharPickerData.MSG_CP_AFRICAN_SCRIPTS,
    -  goog.i18n.CharPickerData.MSG_CP_MIDDLE_EASTERN_SCRIPTS,
    -  goog.i18n.CharPickerData.MSG_CP_SOUTH_ASIAN_SCRIPTS,
    -  goog.i18n.CharPickerData.MSG_CP_SOUTHEAST_ASIAN_SCRIPTS,
    -  goog.i18n.CharPickerData.MSG_CP_HANGUL,
    -  goog.i18n.CharPickerData.MSG_CP_OTHER_EAST_ASIAN_SCRIPTS,
    -  goog.i18n.CharPickerData.MSG_CP_HAN_1_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.MSG_CP_HAN_2_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.MSG_CP_HAN_3_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.MSG_CP_HAN_4_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.MSG_CP_HAN_5_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.MSG_CP_HAN_6_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.MSG_CP_HAN_7_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.MSG_CP_HAN_8_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.MSG_CP_HAN_9_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.MSG_CP_HAN_10_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.MSG_CP_HAN_11_17_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.MSG_CP_HAN_OTHER
    -];
    -
    -
    -/**
    - * Names of subcategories. Each message this array is the
    - * name for the corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_SYMBOL = [
    -  goog.i18n.CharPickerData.MSG_CP_ARROWS,
    -  goog.i18n.CharPickerData.MSG_CP_BRAILLE,
    -  goog.i18n.CharPickerData.MSG_CP_CONTROL_PICTURES,
    -  goog.i18n.CharPickerData.MSG_CP_CURRENCY,
    -  goog.i18n.CharPickerData.MSG_CP_EMOTICONS,
    -  goog.i18n.CharPickerData.MSG_CP_GAME_PIECES,
    -  goog.i18n.CharPickerData.MSG_CP_GENDER_AND_GENEALOGICAL,
    -  goog.i18n.CharPickerData.MSG_CP_GEOMETRIC_SHAPES,
    -  goog.i18n.CharPickerData.MSG_CP_KEYBOARD_AND_UI,
    -  goog.i18n.CharPickerData.MSG_CP_LATIN_1_SUPPLEMENT,
    -  goog.i18n.CharPickerData.MSG_CP_MATH,
    -  goog.i18n.CharPickerData.MSG_CP_MATH_ALPHANUMERIC,
    -  goog.i18n.CharPickerData.MSG_CP_MISCELLANEOUS,
    -  goog.i18n.CharPickerData.MSG_CP_MUSICAL,
    -  goog.i18n.CharPickerData.MSG_CP_STARS_ASTERISKS,
    -  goog.i18n.CharPickerData.MSG_CP_SUBSCRIPT,
    -  goog.i18n.CharPickerData.MSG_CP_SUPERSCRIPT,
    -  goog.i18n.CharPickerData.MSG_CP_TECHNICAL,
    -  goog.i18n.CharPickerData.MSG_CP_TRANSPORT_AND_MAP,
    -  goog.i18n.CharPickerData.MSG_CP_WEATHER_AND_ASTROLOGICAL,
    -  goog.i18n.CharPickerData.MSG_CP_YIJING_TAI_XUAN_JING,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC,
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY
    -];
    -
    -
    -/**
    - * List of characters in base88 encoding scheme. Each base88 encoded
    - * charater string represents corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}. Encoding
    - * scheme is described in {@code goog.i18n.CharListDecompressor}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.CHARLIST_OF_SYMBOL = [
    -  '2>807AnTMm6e6HDk%`O728F1f4V1PNF2WF1G}58?]514M]Ol1%2l2^3X1U:1Un2Mb>$0MD-(068k11I3706:%MwiZ06',
    -  ';oA0FN',
    -  '(j90d3',
    -  'H3XBMQQ10HB(2106uPM]N:qol202S20V2I:Z0^xM0:91E]J6O6',
    -  ';(i1-5W?',
    -  'Q6A06f5#1H2,]4MeEY[W1@3W}891N1GF1GN18N1P%k',
    -  '2JA0sOc',
    -  'oG90nMcPTFNfFEQE10t2H3kQ7X1sj>$0OW6*F%E',
    -  '(P90UGv771.Uv46%7Y^Y1F2mc]1M+<Z1',
    -  '9FP1',
    -  ':3f1En5894WX3:2v+]lEQ?60f2E11OH1P1M]1U11UfCf111MuUmH6Ue6WGGu:26G8:2NO$M:16H8%2V28H211cvg.]4s9AnU#5PNdkX4-1Gc24P1P2:2P2:2P2:2P2:2P2g>50M8V2868G8,8M88mW888E868G8888868GM8k8M8M88,8d1eE8U8d1%46bf$0:;c8%Ef1Ev2:28]BmMbp)02p8071WO6WUw+w0',
    -  '9G6e:-EGX26G6(k70Ocm,]AWG,8OUmOO68E86uMeU^`Q1t78V686GG6GM8|88k8-58MGs8k8d28M8U8Ok8-UGF28F28#28F28#28F28#28F28#28F28sGd4rLS1H1',
    -  '1FGW8Y040Mg%50EHB686WU8l1$Uv4?8En1E8|:29168U8718k8kG8M868688686e686888,148MO8|8E]7wV10k2tN1cYf806813692W]3%68X2f2|O6G86%1P5m6%5$6%468e[E8c11126v1MH2|%F9DuM8E86m8UTN%06',
    -  ';DA0k2mO1NM[d3GV5eEms$6ut2WN493@5OA;80sD790UOc$sGk%2MfDE',
    -  ';OA0v5-3g510E^jW1WV1:l',
    -  'Qq80N1871QC30',
    -  'XFu6e6^X80O?vE82+Y16T+g1Ug2709+H12F30QjW0PC6',
    -  'gM90sW#1G6$l7H1!%2N2O?ml1]6?',
    -  'g?i1N6',
    -  'Q4A0F1mv3}1v8,uUe^zX171',
    -  'w8A0sf7c2WA0#5A>E1-7',
    -  'I{)0%4!P7|%4}3A,$0dA',
    -  '(PD0M(ZU16H1-3e!u6'
    -];
    -
    -
    -/**
    - * Names of subcategories. Each message this array is the
    - * name for the corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_EMOJI = [
    -  goog.i18n.CharPickerData.MSG_CP_PEOPLE_AND_EMOTIONS,
    -  goog.i18n.CharPickerData.MSG_CP_ANIMALS_PLANTS_AND_FOOD,
    -  goog.i18n.CharPickerData.MSG_CP_OBJECTS,
    -  goog.i18n.CharPickerData.MSG_CP_SPORTS_CELEBRATIONS_AND_ACTIVITIES,
    -  goog.i18n.CharPickerData.MSG_CP_TRANSPORT_MAPS_AND_SIGNAGE,
    -  goog.i18n.CharPickerData.MSG_CP_WEATHER_SCENES_AND_ZODIAC_SIGNS,
    -  goog.i18n.CharPickerData.MSG_CP_ENCLOSED,
    -  goog.i18n.CharPickerData.MSG_CP_MARKS,
    -  goog.i18n.CharPickerData.MSG_CP_SYMBOLS
    -];
    -
    -
    -/**
    - * List of characters in base88 encoding scheme. Each base88 encoded
    - * charater string represents corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}. Encoding
    - * scheme is described in {@code goog.i18n.CharListDecompressor}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.CHARLIST_OF_EMOJI = [
    -  '^6A0n2:IE]7Y>X18N1%1-28EOO8871G|%U-5W?',
    -  'I6A0A_X1c8N6eXBt5',
    -  ';O906PJG]m1C1Amew)X16:It1]2W68E8X168[8d68MP171P1!1372',
    -  '2DA0s%76o]W1@3nAN1GF1GN18N1Xzd191N38U9I',
    -  '(DA0v1O]2694t1m72$2>X1d1%DvXUvBN6',
    -  'Q4A0F1mv4|HAUe98(rX1@2]k',
    -  'Y#90;v308ICU1d2W-3H9EH1-3e!u6',
    -  ';5A09M9188:48WE8n5EH2',
    -  'Y%C0(wV1P7N3[EP1M'
    -];
    -
    -
    -/**
    - * Names of subcategories. Each message this array is the
    - * name for the corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_PUNCTUATION = [
    -  goog.i18n.CharPickerData.MSG_CP_ASCII_BASED,
    -  goog.i18n.CharPickerData.MSG_CP_DASH_CONNECTOR,
    -  goog.i18n.CharPickerData.MSG_CP_OTHER,
    -  goog.i18n.CharPickerData.MSG_CP_PAIRED,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC,
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY
    -];
    -
    -
    -/**
    - * List of characters in base88 encoding scheme. Each base88 encoded
    - * charater string represents corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}. Encoding
    - * scheme is described in {@code goog.i18n.CharListDecompressor}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.CHARLIST_OF_PUNCTUATION = [
    -  ':2M8EG886[6O6f2H6eP16u',
    -  '14f4gX80c%36%1gu30:26Q3t0XG',
    -  '(s70:<.MOEmEGGG8OEms88Iu3068G6n1!',
    -  'n36f48v2894X1;P80sP26[6]46P16nvMPF6f3c1^F1H76:2,va@1%5M]26;7106G,fh,Gs2Ms06nPcXF6f48v288686',
    -  'gm808kQT30MnN72v1U8U(%t0Eb(t0',
    -  'Ig80e91E91686W8$EH1X36P162pw0,12-1G|8F18W86nDE8c8M[6O6X2E8f2886'
    -];
    -
    -
    -/**
    - * Names of subcategories. Each message this array is the
    - * name for the corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_NUMBER = [
    -  goog.i18n.CharPickerData.MSG_CP_DECIMAL,
    -  goog.i18n.CharPickerData.MSG_CP_ENCLOSED_DOTTED,
    -  goog.i18n.CharPickerData.MSG_CP_FRACTIONS_RELATED,
    -  goog.i18n.CharPickerData.MSG_CP_OTHER,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC,
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY
    -];
    -
    -
    -/**
    - * List of characters in base88 encoding scheme. Each base88 encoded
    - * charater string represents corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}. Encoding
    - * scheme is described in {@code goog.i18n.CharListDecompressor}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.CHARLIST_OF_NUMBER = [
    -  'P4,]A6egh10,HC,1I,fb,%A,%A,%A,%A,%A,%A,%A,%A,XK,%A,X6,PP,X6,Q]10,f3,PR,vB,9F,m,nG,]K,m,A710Ocm,^SZ0,vz,f3,1I,%A,]a,AnQ0,vB,f5,9D,2Q10,5O60,',
    -  'gs90#7%4@1Pvt2g+20,%2s8N1]2,n3N1',
    -  '9G6eGEoX80Ocm,1IV1%3',
    -  'ot20cHYc]AE9Ck]Lcvd,^910#1oF10,vh2}1073GMQ:30P2!P1EHVMI2V0,9Ts8^aP0sHn6%JsH2s](#2fg#1wnp0l1;-70?',
    -  'o560EgM10,Yk10EGMo230w6u0}39175n1:aMv2$HCUXI,^E10cnQso,60@8',
    -  'w.80-2o?30EHVMoSU1?b}#0,'
    -];
    -
    -
    -/**
    - * Names of subcategories. Each message this array is the
    - * name for the corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_FORMAT_WHITESPACE = [
    -  goog.i18n.CharPickerData.MSG_CP_FORMAT,
    -  goog.i18n.CharPickerData.MSG_CP_VARIATION_SELECTOR,
    -  goog.i18n.CharPickerData.MSG_CP_WHITESPACE,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC,
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY
    -];
    -
    -
    -/**
    - * List of characters in base88 encoding scheme. Each base88 encoded
    - * charater string represents corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}. Encoding
    - * scheme is described in {@code goog.i18n.CharListDecompressor}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.CHARLIST_OF_FORMAT_WHITESPACE = [
    -  'vF;Z10U92fHf4gh40;920UX2Uf4U8M2n#0;`o0sbwt0vME',
    -  ']=oY506%7E^$zA#LDF1AV1',
    -  'fEIH602920,H3P4wB40;#s0',
    -  'w-10f4^#206IV10(970ols0',
    -  'fEAQ80?P3P4wB40^@s0'
    -];
    -
    -
    -/**
    - * Names of subcategories. Each message this array is the
    - * name for the corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_MODIFIER = [
    -  goog.i18n.CharPickerData.MSG_CP_ENCLOSING,
    -  goog.i18n.CharPickerData.MSG_CP_NONSPACING,
    -  goog.i18n.CharPickerData.MSG_CP_SPACING,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC,
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY
    -];
    -
    -
    -/**
    - * List of characters in base88 encoding scheme. Each base88 encoded
    - * charater string represents corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}. Encoding
    - * scheme is described in {@code goog.i18n.CharListDecompressor}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.CHARLIST_OF_MODIFIER = [
    -  '(y80M8E',
    -  '%+#5GG,8t1(#60E8718kWm:I,H46v%71WO|oWQ1En1sGk%2MT_t0k',
    -  'f!!.M%3M91gz30(C30f1695E8?8l18d2X4N32D40XH',
    -  '%?71HP62x60M[F2926^Py0',
    -  'n<686'
    -];
    -
    -
    -/**
    - * Names of subcategories. Each message this array is the
    - * name for the corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_LATIN = [
    -  goog.i18n.CharPickerData.MSG_CP_COMMON,
    -  goog.i18n.CharPickerData.MSG_CP_ENCLOSED,
    -  goog.i18n.CharPickerData.MSG_CP_FLIPPED_MIRRORED,
    -  goog.i18n.CharPickerData.MSG_CP_OTHER,
    -  goog.i18n.CharPickerData.MSG_CP_PHONETICS_IPA,
    -  goog.i18n.CharPickerData.MSG_CP_PHONETICS_X_IPA,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC,
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY
    -];
    -
    -
    -/**
    - * List of characters in base88 encoding scheme. Each base88 encoded
    - * charater string represents corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}. Encoding
    - * scheme is described in {@code goog.i18n.CharListDecompressor}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.CHARLIST_OF_LATIN = [
    -  ':5N2mN2P6}18#28V1Gl1GcG|W68cGs8|GMGMG6G}1GWG6OU8GEOG6H168E11M.s$$6f16%2Mv3P168688uW.128$IN706126H26W6:16m6$6P16Gc916[878QAa06zph0696U8EOP3o2706',
    -  '^x90}6^yX1#28F5m-3:6N2',
    -  'X4X1m6OEWku8WGc88M8H6%1nFmu11916X16H3H1%4P3[8EOmeWW.euWM918HMH6%512]I1Q^+20f+.%2X8]cfBg*10I710P1681H]E^BZ01BE',
    -  ']N6v16m6P16Gv26W6W6G6H286O6G6m86OE86GUGGEGOEv2s8sG!OEOt2mV38?A570@3%5718}2H9|G@1G72GMG#1GcGsGF1G6m|GcHuO11G6e6O88mOuX18Eo]20}1u62cW0F1v6N1e68M91?H7zSi081s868EG?8E8EGcu8E8UGEw^60t5H193N3v!H1f171QmZ072f9E]96',
    -  '%8N2%96$uH4H3u:9M%CF28718M868UO?86G68E8868GHOeP1I>70EO6LF80E8GW11OO6918Of26868886OV3WU%2W',
    -  '1uH1WGeE11G6GO8G868s',
    -  'HZ6uP268691s15P36Al7068H8cHw!Y?20UwdW0#58s:BUbvh0d1g{A06AZW0sH2697',
    -  'XFX1:A6116v5H6!P3E(o706vtM8E8?86GUGE8O8M8E86W8.U12-2Qd40HBMvE,et8:2Qtq0kg710N2mN2bV)0mWOXnc'
    -];
    -
    -
    -/**
    - * Names of subcategories. Each message this array is the
    - * name for the corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_OTHER_EUROPEAN_SCRIPTS = [
    -  goog.i18n.CharPickerData.MSG_CP_ARMENIAN,
    -  goog.i18n.CharPickerData.MSG_CP_CYRILLIC,
    -  goog.i18n.CharPickerData.MSG_CP_GEORGIAN,
    -  goog.i18n.CharPickerData.MSG_CP_GREEK,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_CYPRIOT,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_CYRILLIC,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_GEORGIAN,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_GLAGOLITIC,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_GOTHIC,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_GREEK,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_LINEAR_B,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_OGHAM,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_OLD_ITALIC,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_RUNIC,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_SHAVIAN,
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_ARMENIAN,
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_GREEK
    -];
    -
    -
    -/**
    - * List of characters in base88 encoding scheme. Each base88 encoded
    - * charater string represents corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}. Encoding
    - * scheme is described in {@code goog.i18n.CharListDecompressor}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.CHARLIST_OF_OTHER_EUROPEAN_SCRIPTS = [
    -  '(W10V3Oc8V3G6W=4',
    -  '2510-BuNEKuvfE',
    -  '(e10o{20eG@2mMGEJ',
    -  ']]8E88#18@3P3$wC70@1GcGV3GcGs8888l1888888O#48U8eE8E88OEOUeE8k8eE8E88{l706W',
    -  '^-+0cG8@386OG',
    -  '2{h0F4W[872{<g06g^A0-2;;V0M8,8:2',
    -  ';Y40V3]3cW2a70V38e',
    -  '^tB0F48F4',
    -  '^l*0V2',
    -  ']@MG6OEX7EO71f18GU8E;{(0#6YBt0@5OJE',
    -  '(z)0|8N28t1868N1GF1937B',
    -  'o_50l2',
    -  'oh*0#28M',
    -  'g|50N7',
    -  'A;*0N4',
    -  'oe10g^$0U',
    -  'XG%$$%6Ef26OoN70888888n5G[8uuuuH189Rr:706we708E11EH1EH1EH16'
    -];
    -
    -
    -/**
    - * Names of subcategories. Each message this array is the
    - * name for the corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_AMERICAN_SCRIPTS = [
    -  goog.i18n.CharPickerData.MSG_CP_CANADIAN_ABORIGINAL,
    -  goog.i18n.CharPickerData.MSG_CP_CHEROKEE,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_DESERET
    -];
    -
    -
    -/**
    - * List of characters in base88 encoding scheme. Each base88 encoded
    - * charater string represents corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}. Encoding
    - * scheme is described in {@code goog.i18n.CharListDecompressor}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.CHARLIST_OF_AMERICAN_SCRIPTS = [
    -  'YP507w]oN6',
    -  'wG50t7',
    -  ';(*0F7'
    -];
    -
    -
    -/**
    - * Names of subcategories. Each message this array is the
    - * name for the corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_AFRICAN_SCRIPTS = [
    -  goog.i18n.CharPickerData.MSG_CP_EGYPTIAN_HIEROGLYPHS,
    -  goog.i18n.CharPickerData.MSG_CP_ETHIOPIC,
    -  goog.i18n.CharPickerData.MSG_CP_MEROITIC_CURSIVE,
    -  goog.i18n.CharPickerData.MSG_CP_MEROITIC_HIEROGLYPHS,
    -  goog.i18n.CharPickerData.MSG_CP_NKO,
    -  goog.i18n.CharPickerData.MSG_CP_TIFINAGH,
    -  goog.i18n.CharPickerData.MSG_CP_VAI,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_BAMUM,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_COPTIC,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_NKO,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_OSMANYA
    -];
    -
    -
    -/**
    - * List of characters in base88 encoding scheme. Each base88 encoded
    - * charater string represents corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}. Encoding
    - * scheme is described in {@code goog.i18n.CharListDecompressor}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.CHARLIST_OF_AFRICAN_SCRIPTS = [
    -  ';Y[0}}N9',
    -  ';(40l68MGk88MGt38MG@28MGk88MGN18758MG}5el2ON2(;60}1.k8k8k8k8k8k8k8kI8X0cGcGc.k8kDDe0E',
    -  '(L,072m6',
    -  ';I,0-2',
    -  'Q420l3P1MK1?W',
    -  'o_B0}4$3X1',
    -  '^th0NO8#2*2',
    -  '(5i0F7GcY4p0tpzup06',
    -  'Q210F12$A0}9O6eka1E',
    -  '^720E',
    -  'g?*0t2G,'
    -];
    -
    -
    -/**
    - * Names of subcategories. Each message this array is the
    - * name for the corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_MIDDLE_EASTERN_SCRIPTS = [
    -  goog.i18n.CharPickerData.MSG_CP_ARABIC,
    -  goog.i18n.CharPickerData.MSG_CP_HEBREW,
    -  goog.i18n.CharPickerData.MSG_CP_IMPERIAL_ARAMAIC,
    -  goog.i18n.CharPickerData.MSG_CP_INSCRIPTIONAL_PAHLAVI,
    -  goog.i18n.CharPickerData.MSG_CP_INSCRIPTIONAL_PARTHIAN,
    -  goog.i18n.CharPickerData.MSG_CP_MANDAIC,
    -  goog.i18n.CharPickerData.MSG_CP_OLD_SOUTH_ARABIAN,
    -  goog.i18n.CharPickerData.MSG_CP_SAMARITAN,
    -  goog.i18n.CharPickerData.MSG_CP_SYRIAC,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_ARABIC,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_AVESTAN,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_CARIAN,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_CUNEIFORM,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_HEBREW,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_LYCIAN,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_LYDIAN,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_OLD_PERSIAN,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_PHOENICIAN,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_SYRIAC,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_UGARITIC,
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_ARABIC,
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_HEBREW
    -];
    -
    -
    -/**
    - * List of characters in base88 encoding scheme. Each base88 encoded
    - * charater string represents corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}. Encoding
    - * scheme is described in {@code goog.i18n.CharListDecompressor}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.CHARLIST_OF_MIDDLE_EASTERN_SCRIPTS = [
    -  'op10U8,11Gl2m,]1F1O68W-18V6H2l1P774XQ8?^F60g2#0#2YVx06r##0vAry%0U]3[-1f11vV2QG$0V1',
    -  'oj108G91V2eUC6F1886A?$0',
    -  '(>+0@18!',
    -  'g!,0t1es',
    -  'ox,0@1Gs',
    -  '^F20F2eZE',
    -  'Id,0-2',
    -  'AA20@1X2N1Qt60{w6072',
    -  'wq10P1O]2[?X2',
    -  '^u10UH46%2H7[fD6=Wc1HkG,8M',
    -  '(r,0-4Ok',
    -  ';Y*0V4',
    -  'gE=0-@HD@8H1M',
    -  'Qk10^>$0!f35}$0#2:168',
    -  '^V*0l2',
    -  'AA,0N2e',
    -  'Aw*0F3WF1',
    -  'I7,0d2O',
    -  ';;10F1868t2v2Eq5%2V2',
    -  'It*0t28',
    -  'I!10MA^e1M8V2868G8,8M88mW888E868G8888868GM8k8M8M88,8d1eE8U8d1{W$0-813@Wv1#5G-4v371fAE88FC',
    -  '2a(08.F18U886868!'
    -];
    -
    -
    -/**
    - * Names of subcategories. Each message this array is the
    - * name for the corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_SOUTH_ASIAN_SCRIPTS = [
    -  goog.i18n.CharPickerData.MSG_CP_BENGALI,
    -  goog.i18n.CharPickerData.MSG_CP_CHAKMA,
    -  goog.i18n.CharPickerData.MSG_CP_DEVANAGARI,
    -  goog.i18n.CharPickerData.MSG_CP_GUJARATI,
    -  goog.i18n.CharPickerData.MSG_CP_GURMUKHI,
    -  goog.i18n.CharPickerData.MSG_CP_KANNADA,
    -  goog.i18n.CharPickerData.MSG_CP_LEPCHA,
    -  goog.i18n.CharPickerData.MSG_CP_LIMBU,
    -  goog.i18n.CharPickerData.MSG_CP_MALAYALAM,
    -  goog.i18n.CharPickerData.MSG_CP_MEETEI_MAYEK,
    -  goog.i18n.CharPickerData.MSG_CP_OL_CHIKI,
    -  goog.i18n.CharPickerData.MSG_CP_ORIYA,
    -  goog.i18n.CharPickerData.MSG_CP_SAURASHTRA,
    -  goog.i18n.CharPickerData.MSG_CP_SINHALA,
    -  goog.i18n.CharPickerData.MSG_CP_SORA_SOMPENG,
    -  goog.i18n.CharPickerData.MSG_CP_TAMIL,
    -  goog.i18n.CharPickerData.MSG_CP_TELUGU,
    -  goog.i18n.CharPickerData.MSG_CP_THAANA,
    -  goog.i18n.CharPickerData.MSG_CP_TIBETAN,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_BRAHMI,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_KAITHI,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_KANNADA,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_KHAROSHTHI,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_SHARADA,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_SYLOTI_NAGRI,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_TAKRI,
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_BENGALI,
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_DEVANAGARI,
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_GURMUKHI,
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_ORIYA,
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_TIBETAN
    -];
    -
    -
    -/**
    - * List of characters in base88 encoding scheme. Each base88 encoded
    - * charater string represents corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}. Encoding
    - * scheme is described in {@code goog.i18n.CharListDecompressor}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.CHARLIST_OF_SOUTH_ASIAN_SCRIPTS = [
    -  'gg206:2sG6G@18k8OMOf1n16W@1:*64[E958kG6GE.[6',
    -  'wH.0F3X1F146EP3F1',
    -  '(X20-4Ov1X16G718c8k9[6gMf0,DRg0M]4E8l18k[6H1YEg0l1',
    -  '(*20!8E8@18k868UOv1X16W|fk6*uE958s8E8E:16',
    -  'gg206fEcW6G@18k8GG693.,GE:v6a*E958UW6GEO%26O',
    -  'QR30s8E8}18,8UO936W,86CA6958k8E8Mu6116',
    -  'oZ70F392N1OE=3#1',
    -  '(r60l2H3O|K4|W|',
    -  '^c30s8E8t3Gf1n16WV1Okw@4053506P5k8E8M.[6',
    -  'wGj0?eEvI73$W,iOUOMfLs86',
    -  ';g70l3m6pc',
    -  'gg206%bsG6G@18k868UO13EWl1PY6CjE958kG6GE$6[6',
    -  'oni0d4X2|486n4d1',
    -  'oo30l1O728!8Gk94A+40j@406X6Wc88sv16',
    -  '2D.0F2u,',
    -  ';3308cOE8MO6886O6OEO|12]1-1=AX5UOE8M.',
    -  'wF30s8E8}18,8UOX26m6W,$sPA6=LEP5k8E8Mu6116',
    -  'wq10P1O:5,PPV311_?',
    -  '2{30|8?GV2888MGE8M8M8M8M8M8|8EH2GUf4s8c8kW6Ii806e,GsL$806f288W6f468ek8E86ec8M8M8M8M8M8|8E.',
    -  'YG40M2e30M8MO6',
    -  'Y^-0#4X1kWt24AE:4N1',
    -  '26.0}311k=5E94?',
    -  'YZ30',
    -  'gU,0X1M8E8V291s$!=7E86eMv3EW',
    -  'QT.0N4P1su,48EX4F1',
    -  '(bi068E8M8}1eMy3OW92U',
    -  'Yv:0-3]1,y271',
    -  'Yr2068',
    -  'Yf20s',
    -  'Qz20G93EG',
    -  'Q0306',
    -  'A|30]4.WWW91we#0M5e#0868$n1.WWW91'
    -];
    -
    -
    -/**
    - * Names of subcategories. Each message this array is the
    - * name for the corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_SOUTHEAST_ASIAN_SCRIPTS = [
    -  goog.i18n.CharPickerData.MSG_CP_BALINESE,
    -  goog.i18n.CharPickerData.MSG_CP_BATAK,
    -  goog.i18n.CharPickerData.MSG_CP_CHAM,
    -  goog.i18n.CharPickerData.MSG_CP_JAVANESE,
    -  goog.i18n.CharPickerData.MSG_CP_KAYAH_LI,
    -  goog.i18n.CharPickerData.MSG_CP_KHMER,
    -  goog.i18n.CharPickerData.MSG_CP_LAO,
    -  goog.i18n.CharPickerData.MSG_CP_MYANMAR,
    -  goog.i18n.CharPickerData.MSG_CP_NEW_TAI_LUE,
    -  goog.i18n.CharPickerData.MSG_CP_TAI_LE,
    -  goog.i18n.CharPickerData.MSG_CP_TAI_THAM,
    -  goog.i18n.CharPickerData.MSG_CP_TAI_VIET,
    -  goog.i18n.CharPickerData.MSG_CP_THAI,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_BUGINESE,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_BUHID,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_HANUNOO,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_KHMER,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_REJANG,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_SUNDANESE,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_TAGALOG,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_TAGBANWA
    -];
    -
    -
    -/**
    - * List of characters in base88 encoding scheme. Each base88 encoded
    - * charater string represents corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}. Encoding
    - * scheme is described in {@code goog.i18n.CharListDecompressor}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.CHARLIST_OF_SOUTHEAST_ASIAN_SCRIPTS = [
    -  '(C70F4n1kWV2.!KBUP4d1f3!',
    -  '(T70V312MK2F1',
    -  'Q`i0t392E8sW,GM=4F191$6',
    -  '2:i0F4P171G,W6q8MP4F1P1',
    -  '2zi0V3$6)s',
    -  ';I6073GE8?]2E8UO,m,Hi-2Srl286O',
    -  'g:3068G68GmM8k8E88G68M86.GU11,GMC4Gc86.8c',
    -  'QK40-3:1}1WMOO6uEW71918,W6Iwe0V18,D-e0#192MWE8EGkOMH1|8[M;xe0[',
    -  'Y%60@3]1k$?O6K4d1u6',
    -  '2z60t2GU',
    -  '^@60#4]3,m,mk8c`7,8l2Gn3',
    -  '^7j0N48O6GUG8H2686K48EG6e68f2',
    -  ';z30N48691c.71*3Gk11!',
    -  '2>60}1u6xU',
    -  '2C606.#1',
    -  'AA60l1O6RE',
    -  'gM60v311',
    -  'Y%i0}1H2C271',
    -  'IO70t2H1l1PNsyTE%271',
    -  'I760718MH36K3E',
    -  '2C606%3718E86'
    -];
    -
    -
    -/**
    - * Names of subcategories. Each message this array is the
    - * name for the corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_HANGUL = [
    -  goog.i18n.CharPickerData.MSG_CP_OTHER,
    -  '\u1100',
    -  '\u1102',
    -  '\u1103',
    -  '\u1105',
    -  '\u1106',
    -  '\u1107',
    -  '\u1109',
    -  '\u110B',
    -  '\u110C',
    -  '\u110E',
    -  '\u110F',
    -  '\u1110',
    -  '\u1111',
    -  '\u1112',
    -  '\u1159',
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC,
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY
    -];
    -
    -
    -/**
    - * List of characters in base88 encoding scheme. Each base88 encoded
    - * charater string represents corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}. Encoding
    - * scheme is described in {@code goog.i18n.CharListDecompressor}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.CHARLIST_OF_HANGUL = [
    -  'AzC0M88,8F1X1mWMPqYyh0}1WV42BA06Tis06',
    -  ';gj0}}-I',
    -  '(zk0Vr',
    -  '(+i0MAj20}}-I',
    -  'A,i0?2#30Vr',
    -  'A-i0EIS40Vr',
    -  'Y-i0EY]40}}-I',
    -  'w-i0IC60}}-I',
    -  '(-i06^U70Vr',
    -  '^-i0Q`70}}-I',
    -  'I}r0Vr',
    -  'wqs0Vr',
    -  '2.i02YA0Vr',
    -  'A.i0Y}A0Vr',
    -  'I.i0(qB0Vr',
    -  'Q.i0',
    -  'oh40FN^L80d8',
    -  'oJD0#2]5#2IGs0MX5#2OcGcGcGE'
    -];
    -
    -
    -/**
    - * Names of subcategories. Each message this array is the
    - * name for the corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_OTHER_EAST_ASIAN_SCRIPTS = [
    -  goog.i18n.CharPickerData.MSG_CP_BOPOMOFO,
    -  goog.i18n.CharPickerData.MSG_CP_HIRAGANA,
    -  goog.i18n.CharPickerData.MSG_CP_KATAKANA,
    -  goog.i18n.CharPickerData.MSG_CP_LISU,
    -  goog.i18n.CharPickerData.MSG_CP_MIAO,
    -  goog.i18n.CharPickerData.MSG_CP_MONGOLIAN,
    -  goog.i18n.CharPickerData.MSG_CP_OLD_TURKIC,
    -  goog.i18n.CharPickerData.MSG_CP_PHAGS_PA,
    -  goog.i18n.CharPickerData.MSG_CP_YI,
    -  goog.i18n.CharPickerData.MSG_CP_HISTORIC + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_PHAGS_PA,
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_BOPOMOFO,
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_HIRAGANA,
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_KATAKANA,
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_PHAGS_PA,
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY + ' - ' +
    -      goog.i18n.CharPickerData.MSG_CP_YI
    -];
    -
    -
    -/**
    - * List of characters in base88 encoding scheme. Each base88 encoded
    - * charater string represents corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}. Encoding
    - * scheme is described in {@code goog.i18n.CharListDecompressor}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.CHARLIST_OF_OTHER_EAST_ASIAN_SCRIPTS = [
    -  'AzC0M88,8F1X1mWM]Ht3XAV2I8s06+f(06^`B0M',
    -  'AzC0M88F2X1mWM8#7.H8fD6QCD1T0l065is0U196G6f8wqs0946',
    -  'AzC0M88F2X1mWM%8N8fD6n8V1I2D1L0l065is0U196:8Egqs0946',
    -  'oph0l3m6pc',
    -  '2591F611F4f1d1',
    -  'gU60?O8,m738t4$t38aEE:4H9',
    -  '2>,0l6',
    -  'wU6068AU606e,Gs',
    -  'AzC06e,Gs2qT0-18}}-FO@4DL10',
    -  'ohi0}4',
    -  'Ql)0M',
    -  '^%C0f91MF1^oU1bE$0Ujys06',
    -  '^%C0HIPDF1vRF48@7g`r0N18}3r%s06',
    -  'Ql)0M',
    -  'Ql)0M'
    -];
    -
    -
    -/**
    - * Names of subcategories. Each message this array is the
    - * name for the corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_HAN_1_STROKE_RADICALS = [
    -  '\u4E00',
    -  '\u4E28',
    -  '\u4E36',
    -  '\u4E3F',
    -  '\u4E59',
    -  '\u4E85',
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY,
    -  goog.i18n.CharPickerData.MSG_CP_LESS_COMMON
    -];
    -
    -
    -/**
    - * List of characters in base88 encoding scheme. Each base88 encoded
    - * charater string represents corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}. Encoding
    - * scheme is described in {@code goog.i18n.CharListDecompressor}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.CHARLIST_OF_HAN_1_STROKE_RADICALS = [
    -  'ItK0l3]1f7YL10',
    -  ';wK0M8!',
    -  'AyK0k8[',
    -  '^yK0,8N1^w30',
    -  'Q#K0sG}2YfL0',
    -  'Q)K0k',
    -  '(bC0c]R]q8O8f2EgqB2E5Cl1]116$f7fG',
    -  'A(D0t3(rX1V288k8!8k8868|8l188U8718M8N48E88GE8#48MG@3oA20]G2P60;QB0]9^(20^7L0t2'
    -];
    -
    -
    -/**
    - * Names of subcategories. Each message this array is the
    - * name for the corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_HAN_2_STROKE_RADICALS = [
    -  '\u4E8C',
    -  '\u4EA0',
    -  '\u4EBA',
    -  '\u513F',
    -  '\u5165',
    -  '\u516B',
    -  '\u5182',
    -  '\u5196',
    -  '\u51AB',
    -  '\u51E0',
    -  '\u51F5',
    -  '\u5200',
    -  '\u529B',
    -  '\u52F9',
    -  '\u5315',
    -  '\u531A',
    -  '\u5338',
    -  '\u5341',
    -  '\u535C',
    -  '\u5369',
    -  '\u5382',
    -  '\u53B6',
    -  '\u53C8',
    -  '\u8BA0',
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY,
    -  goog.i18n.CharPickerData.MSG_CP_LESS_COMMON
    -];
    -
    -
    -/**
    - * List of characters in base88 encoding scheme. Each base88 encoded
    - * charater string represents corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}. Encoding
    - * scheme is described in {@code goog.i18n.CharListDecompressor}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.CHARLIST_OF_HAN_2_STROKE_RADICALS = [
    -  '^)K0M8N1',
    -  '(+K0N2',
    -  'A.K0lww)K0',
    -  '(gL0V3',
    -  'IkL0cI870',
    -  '(kL0}1QyK0',
    -  ';mL0#1Yw50',
    -  'woL0-1',
    -  'oqL0#4',
    -  'YvL0-1',
    -  'QxL0?',
    -  'QyL0}D',
    -  'Y;L0V58@2',
    -  '^^L0d2',
    -  'g{L0U',
    -  '^{L0t2^IK0',
    -  'w0M0!',
    -  'g1M0E8}1QHK0',
    -  '^3M071',
    -  'A5M0F2',
    -  'Y7M0t4;XD0',
    -  'ACM0l1',
    -  '(DM0V2IS10',
    -  'Y]a0tD',
    -  'QcC0}1%P8]qG688P1W6G6mO8^pB2F28d292%B6f6%A15P1ODrl1f1E9386H18e11Ee[n16[91e11.G$H1n18611$X2cX5k',
    -  ';+D0tN8l49H2i40kAsS1uH3v1H788]9@18}2872Gk8E8|8s88E8G-18778@28lF8-6G,8@48#486GF28d28t18t48N3874868-78F58V18}28F48l48lG868d18N18#18!8FN8@98FP8s8}F8N28,8VG8F18tF8}2(s30%U;@101bI-50QE60^{40;X60IhB0}Oo_20d3j%S1'
    -];
    -
    -
    -/**
    - * Names of subcategories. Each message this array is the
    - * name for the corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_HAN_3_STROKE_RADICALS = [
    -  '\u53E3',
    -  '\u56D7',
    -  '\u571F',
    -  '\u58EB',
    -  '\u5902',
    -  '\u590A',
    -  '\u5915',
    -  '\u5927',
    -  '\u5973',
    -  '\u5B50',
    -  '\u5B80',
    -  '\u5BF8',
    -  '\u5C0F',
    -  '\u5C22',
    -  '\u5C38',
    -  '\u5C6E',
    -  '\u5C71',
    -  '\u5DDB',
    -  '\u5DE5',
    -  '\u5DF1',
    -  '\u5DFE',
    -  '\u5E72',
    -  '\u5E7A',
    -  '\u5E7F',
    -  '\u5EF4',
    -  '\u5EFE',
    -  '\u5F0B',
    -  '\u5F13',
    -  '\u5F50',
    -  '\u5F61',
    -  '\u5F73',
    -  '\u7E9F',
    -  '\u95E8',
    -  '\u98DE',
    -  '\u9963',
    -  '\u9A6C',
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY,
    -  goog.i18n.CharPickerData.MSG_CP_LESS_COMMON
    -];
    -
    -
    -/**
    - * List of characters in base88 encoding scheme. Each base88 encoded
    - * charater string represents corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}. Encoding
    - * scheme is described in {@code goog.i18n.CharListDecompressor}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.CHARLIST_OF_HAN_3_STROKE_RADICALS = [
    -  'IGM0dY8FM8tB',
    -  '^`M0d6^GJ0',
    -  'g3N0tZ8}48!Q#I0Ge',
    -  'gCN0%W}1',
    -  'YlN0k',
    -  '2mN0|',
    -  'AnN0l1',
    -  '(oN0-6',
    -  'wvN07D8}T',
    -  '2DO0N4',
    -  'YHO0-Aw]50',
    -  'QSO0}1',
    -  'YUO0t1^=H0',
    -  'AWO0@1',
    -  'AYO08t4',
    -  '2dO0E',
    -  'A$K0A#30-W',
    -  'I.O0c8E',
    -  'A:O0|',
    -  'I;O071',
    -  'Y<O0V78@2',
    -  '^{O0s',
    -  '2$K0oM40U',
    -  'A}O0lAw7H0',
    -  '(9P0,',
    -  'wAP071',
    -  ';BP0s',
    -  'oCP0d5',
    -  'AIP0d1',
    -  'wJP0!8s',
    -  'QLP0F7^]G06',
    -  '(gX0tD',
    -  'wud0t4',
    -  'obe0',
    -  'wne0l4',
    -  '(:e0V5',
    -  'YeC0#2P=11Wm11686W(uB2}18l58E8EGMP8:5]6]9Lvl1G86:1mP26m6%1me%1E11X1OmEf1692Ge6H1%1Gm8GX3kX4[F1',
    -  'YAE0@G8V(I!20|I!10E:5fX18EwYR1%1u8Gn3v11B1693P2uO91$8OH2H713vMXG%1%K:6]SG13%2H@vX93tU8F587w8}V8-68tA8dO8db8V38758V28t58F18k8#C8t!8V78V98tU8lT8de8}}V98lB8}B8#387987H8#38NJ8@78U8N18U8kgE10(L10v_X4ngA6109Nn2v2Ac101O1}HSQ*1094^.50N2:BP6Ay10Q<40]5;s20AE20V1H9^j20l1%g-3YY20YU10}zAv10@2;310F1]E72X3}1DeT18'
    -];
    -
    -
    -/**
    - * Names of subcategories. Each message this array is the
    - * name for the corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_HAN_4_STROKE_RADICALS = [
    -  '\u5FC3',
    -  '\u6208',
    -  '\u6236',
    -  '\u624B',
    -  '\u652F',
    -  '\u6534',
    -  '\u6587',
    -  '\u6597',
    -  '\u65A4',
    -  '\u65B9',
    -  '\u65E0',
    -  '\u65E5',
    -  '\u66F0',
    -  '\u6708',
    -  '\u6728',
    -  '\u6B20',
    -  '\u6B62',
    -  '\u6B79',
    -  '\u6BB3',
    -  '\u6BCB',
    -  '\u6BD4',
    -  '\u6BDB',
    -  '\u6C0F',
    -  '\u6C14',
    -  '\u6C34',
    -  '\u706B',
    -  '\u722A',
    -  '\u7236',
    -  '\u723B',
    -  '\u723F',
    -  '\u7247',
    -  '\u7259',
    -  '\u725B',
    -  '\u72AC',
    -  '\u89C1',
    -  '\u8D1D',
    -  '\u8F66',
    -  '\u97E6',
    -  '\u98CE',
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY,
    -  goog.i18n.CharPickerData.MSG_CP_LESS_COMMON
    -];
    -
    -
    -/**
    - * List of characters in base88 encoding scheme. Each base88 encoded
    - * charater string represents corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}. Encoding
    - * scheme is described in {@code goog.i18n.CharListDecompressor}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.CHARLIST_OF_HAN_4_STROKE_RADICALS = [
    -  'oSP0#q',
    -  'Y]P074',
    -  'o{P0-1',
    -  'g}P0F)2gF0',
    -  '((Q0U',
    -  '(oM0YG40d7(cA0',
    -  '(;Q0V1YNF0',
    -  'I=Q071',
    -  'Y>Q0-1',
    -  'Q@Q0d3',
    -  ';^Q0U',
    -  ';@L0Y350FOH1os602W80',
    -  ';@L0wR5071868k',
    -  '(LR0-2Y070',
    -  'wOR0}}N4:+IBD0',
    -  '2TS0@5',
    -  '2ZS0}1I-D0',
    -  'AbS0F5',
    -  'YgS072',
    -  'oiS0!',
    -  'YjS0k',
    -  '2kS0t4',
    -  '(oS0U',
    -  'IpS0-2',
    -  'AsS0dH8V[',
    -  'I$T0le;@402[60nI12',
    -  'A:M0wV70|',
    -  '^HU0U',
    -  'YIU0M',
    -  'IxK0gl90s',
    -  'gJU0l1',
    -  'ALU06',
    -  'QLU0N7',
    -  'wSU0lJ',
    -  ';ba0U8?',
    -  '2Sb0V6',
    -  'I]b0#4',
    -  '2Fe0k',
    -  'Aae071',
    -  '^SC0HE}2::MGEG.OovB2:8e#4G6G-28}2871]7$65ml1G$mEm6OGOEWE%1eE916Ou6m868W$6m6GU11OE8W91WEWGMmOG6eM$8e6W6mG611Of371136P2}18EH4M',
    -  '^aE0]uFq8#@^U20U%LEwSS1f7HLfkX2vCH4vM(a10gv10IO10Yg30Hz}}VE8to8-w8@J8-28tK8td8N48FC8E8l68cGNM8V#8#98lK8-A8-A8|8728E8l287N8}}#E8@N8V%8tC88V88-88lC8N18@48t38l`;Y20(>101dYk201)XQ6nUv^Xao940kAi10cv3QF40UHdXG|fe8o^40}}l3YD10c]Ak]7@19YcX4UjUT16'
    -];
    -
    -
    -/**
    - * Names of subcategories. Each message this array is the
    - * name for the corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_HAN_5_STROKE_RADICALS = [
    -  '\u7384',
    -  '\u7389',
    -  '\u74DC',
    -  '\u74E6',
    -  '\u7518',
    -  '\u751F',
    -  '\u7528',
    -  '\u7530',
    -  '\u758B',
    -  '\u7592',
    -  '\u7676',
    -  '\u767D',
    -  '\u76AE',
    -  '\u76BF',
    -  '\u76EE',
    -  '\u77DB',
    -  '\u77E2',
    -  '\u77F3',
    -  '\u793A',
    -  '\u79B8',
    -  '\u79BE',
    -  '\u7A74',
    -  '\u7ACB',
    -  '\u9485',
    -  '\u957F',
    -  '\u9E1F',
    -  '\u9F99',
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY,
    -  goog.i18n.CharPickerData.MSG_CP_LESS_COMMON
    -];
    -
    -
    -/**
    - * List of characters in base88 encoding scheme. Each base88 encoded
    - * charater string represents corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}. Encoding
    - * scheme is described in {@code goog.i18n.CharListDecompressor}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.CHARLIST_OF_HAN_5_STROKE_RADICALS = [
    -  'QmU0U',
    -  '(mU0#U',
    -  'o@U0,',
    -  'g[U0d4',
    -  '2{U0k',
    -  'w{U0!',
    -  'g|U0s',
    -  'I}U0N48k8}2',
    -  'g7V0k',
    -  'A8V0tK',
    -  ';SV0k',
    -  'o3V0:PV4',
    -  '^XV0d1A;A0',
    -  'gZV0F4',
    -  '(dV0dL(mA0',
    -  'QzV0k',
    -  '^zV0d1',
    -  'w-S0(@20tT',
    -  'I5W0VBQH40P4;-506',
    -  'wGW0c((20',
    -  'IHW0dG',
    -  '(XW0-7',
    -  'wfW0#1G72Ai70',
    -  'YOd0@L',
    -  'Ald0',
    -  ';-f0#7',
    -  'IIg0E',
    -  'QkC0}1n.O86n1^?B2V18V3{gl1$f2u6[P1[68$$P1P16926u[[E91$6.u:2UH4|f6O|11X1[E',
    -  'AoG0@:;12071n^kXD6I4R1:4WnB9d[15:49lHkX.1pP5Hw]nf]^H20()109d;u101@]2%KY!10:9f.;(307k8dL8}38@88-98?8V?WdA8}S87Q8748l!8-T8#d8d28lI8FK8#12@30nQI,10w^402B20F22,50-1AQ30}b(F10V49f}3]3'
    -];
    -
    -
    -/**
    - * Names of subcategories. Each message this array is the
    - * name for the corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_HAN_6_STROKE_RADICALS = [
    -  '\u7AF9',
    -  '\u7C73',
    -  '\u7CF8',
    -  '\u7F36',
    -  '\u7F51',
    -  '\u7F8A',
    -  '\u7FBD',
    -  '\u8001',
    -  '\u800C',
    -  '\u8012',
    -  '\u8033',
    -  '\u807F',
    -  '\u8089',
    -  '\u81E3',
    -  '\u81EA',
    -  '\u81F3',
    -  '\u81FC',
    -  '\u820C',
    -  '\u821B',
    -  '\u821F',
    -  '\u826E',
    -  '\u8272',
    -  '\u8278',
    -  '\u864D',
    -  '\u866B',
    -  '\u8840',
    -  '\u884C',
    -  '\u8863',
    -  '\u897E',
    -  '\u9875',
    -  '\u9F50',
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY,
    -  goog.i18n.CharPickerData.MSG_CP_LESS_COMMON
    -];
    -
    -
    -/**
    - * List of characters in base88 encoding scheme. Each base88 encoded
    - * charater string represents corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}. Encoding
    - * scheme is described in {@code goog.i18n.CharListDecompressor}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.CHARLIST_OF_HAN_6_STROKE_RADICALS = [
    -  ';jW0NY',
    -  ';,N0YL70;<10}B',
    -  'Q4X0Vc',
    -  'guX0V2',
    -  '^wX075',
    -  'IlV0;G20l4',
    -  '(*X076',
    -  '^;X0?',
    -  '^<X0c',
    -  'g=X0@2',
    -  'g@X0-6',
    -  'Y|X0,',
    -  ';^O0Y490tP8l5',
    -  '(UY0k',
    -  'YVY0!',
    -  'IWY0!',
    -  '2XY0V1',
    -  'gYY0N1',
    -  ';ZY0M',
    -  'IaY077',
    -  'YhY0M',
    -  '(hY0c',
    -  'QiY0ld8lC8taI!60H1u6.',
    -  'gKP0^OA0U872',
    -  'ImZ0lg',
    -  ';2a0|',
    -  '^3a0}1',
    -  '^!L0(K10IAD0tP2@50',
    -  '(Va071',
    -  '2Se0l4',
    -  'oBg06',
    -  'YmC0l2onC2Wn56XC-28U86G68M8@4jql1MemO68691Em6e6.6GO6n1Oem6P268me$6n19112Eue86WWW:168:4?v6G?%2',
    -  'o5E0oq10;%10VE8VH91l;P^w0S1Q0101Io3102E20XZoi10n>2;10XUPN18e]1;n30v6m6(L40vHvCX1:8;g10A{30HM}}N@X2#B8F68@D8VI8@(8NQG#L8#68t18tO8#v8Na8##8VC8#^8tt(j10wB30YE30E(870NF13#hfxd1>RT18'
    -];
    -
    -
    -/**
    - * Names of subcategories. Each message this array is the
    - * name for the corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_HAN_7_STROKE_RADICALS = [
    -  '\u5364',
    -  '\u898B',
    -  '\u89D2',
    -  '\u8A00',
    -  '\u8C37',
    -  '\u8C46',
    -  '\u8C55',
    -  '\u8C78',
    -  '\u8C9D',
    -  '\u8D64',
    -  '\u8D70',
    -  '\u8DB3',
    -  '\u8EAB',
    -  '\u8ECA',
    -  '\u8F9B',
    -  '\u8FB0',
    -  '\u8FB5',
    -  '\u9091',
    -  '\u9149',
    -  '\u91C6',
    -  '\u91CC',
    -  '\u9F9F',
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY,
    -  goog.i18n.CharPickerData.MSG_CP_LESS_COMMON
    -];
    -
    -
    -/**
    - * List of characters in base88 encoding scheme. Each base88 encoded
    - * charater string represents corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}. Encoding
    - * scheme is described in {@code goog.i18n.CharListDecompressor}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.CHARLIST_OF_HAN_7_STROKE_RADICALS = [
    -  'w4M0(<J0',
    -  '^Wa0?8#3',
    -  'Yda074QB50',
    -  'oha0#b^R50e',
    -  'A7b0N1',
    -  'g8b0N1',
    -  ';9b073',
    -  '2Db0N3',
    -  'YGb0}88V2',
    -  'gYb0|',
    -  'oZb0}5A(40',
    -  'wfb0dM',
    -  'I$b0#2',
    -  '2)b07EwQ4012',
    -  '2|b0-1',
    -  '^}b0U',
    -  '(.O0oFD0@J',
    -  'YKc0tG',
    -  'Abc0NB',
    -  'gmc0c',
    -  '2nc0U',
    -  '(Ig0',
    -  'oaC0XE#1X*en1;}B2n5F18E8!jul186X1ev1[.mn1Gn18116P1[8m]111%1n1v1[G92G6un4kX7|v1',
    -  'QAE0gj40lFu-8etLO#D^DT1PL9,AY30v9]_A^60Yl10;N50Az10oi10(I80F`8M8V58Nh8lCu}}}hml3Glb8N@;820o{80|m-3n3V3u-712#9nwv3+zT16'
    -];
    -
    -
    -/**
    - * Names of subcategories. Each message this array is the
    - * name for the corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_HAN_8_STROKE_RADICALS = [
    -  '\u91D1',
    -  '\u9577',
    -  '\u9580',
    -  '\u961C',
    -  '\u96B6',
    -  '\u96B9',
    -  '\u96E8',
    -  '\u9751',
    -  '\u975E',
    -  '\u9C7C',
    -  '\u9F7F',
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY,
    -  goog.i18n.CharPickerData.MSG_CP_LESS_COMMON
    -];
    -
    -
    -/**
    - * List of characters in base88 encoding scheme. Each base88 encoded
    - * charater string represents corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}. Encoding
    - * scheme is described in {@code goog.i18n.CharListDecompressor}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.CHARLIST_OF_HAN_8_STROKE_RADICALS = [
    -  'wVS0(HA0-!o_20GG',
    -  'Ykd0s',
    -  'Ild0V9',
    -  'Yzd0@D',
    -  'Y<d0E',
    -  'w<d0F4',
    -  '^@d0d9',
    -  'g1e071',
    -  'w2e0M',
    -  '(Xf0d9',
    -  ';Fg0F1',
    -  ';qC0!:(IvB2vf71865vl194m.uu14:1]1EWH191$H1m92v1v195X8M',
    -  'QTJ0l8H1F4OV68-5:ssQMR1AQ50Q>U0#88@yP2dcf1798N#8FJQn30@1^;106;y30l8f4@1P1N61OV39B!DzT1E'
    -];
    -
    -
    -/**
    - * Names of subcategories. Each message this array is the
    - * name for the corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_HAN_9_STROKE_RADICALS = [
    -  '\u9762',
    -  '\u9769',
    -  '\u97CB',
    -  '\u97ED',
    -  '\u97F3',
    -  '\u9801',
    -  '\u98A8',
    -  '\u98DB',
    -  '\u98DF',
    -  '\u9996',
    -  '\u9999',
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY,
    -  goog.i18n.CharPickerData.MSG_CP_LESS_COMMON
    -];
    -
    -
    -/**
    - * List of characters in base88 encoding scheme. Each base88 encoded
    - * charater string represents corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}. Encoding
    - * scheme is described in {@code goog.i18n.CharListDecompressor}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.CHARLIST_OF_HAN_9_STROKE_RADICALS = [
    -  '23e0k',
    -  'w3e0-8',
    -  'oCe0V2',
    -  'wFe0c',
    -  'ghW06oy70F1',
    -  'gHe0dA',
    -  'wWe0V3',
    -  'Qbe0E',
    -  'wbe0@B',
    -  'Qse0E',
    -  'ose0t1',
    -  'wrC0?f)(AC2N1{gl1f298Ef56n8M',
    -  'ooH0g520-Q8!IHS1:_P32-30ARC0YA40](^b70gd807Y8lBelaW728NG91}Zv1t288-4Iz70d1mt1n1|el1H2N1'
    -];
    -
    -
    -/**
    - * Names of subcategories. Each message this array is the
    - * name for the corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_HAN_10_STROKE_RADICALS = [
    -  '\u99AC',
    -  '\u9AA8',
    -  '\u9AD8',
    -  '\u9ADF',
    -  '\u9B25',
    -  '\u9B2F',
    -  '\u9B32',
    -  '\u9B3C',
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY,
    -  goog.i18n.CharPickerData.MSG_CP_LESS_COMMON
    -];
    -
    -
    -/**
    - * List of characters in base88 encoding scheme. Each base88 encoded
    - * charater string represents corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}. Encoding
    - * scheme is described in {@code goog.i18n.CharListDecompressor}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.CHARLIST_OF_HAN_10_STROKE_RADICALS = [
    -  'Que0VHQY106',
    -  'I@e0N4',
    -  'o_e0k',
    -  'I`e0N6',
    -  'o2f0,',
    -  'g3f0E',
    -  '(3f0,',
    -  'w4f0t2',
    -  'wsC0s^?C2Ubvl1:9nT',
    -  '^_J077O#9wM(1gQ10#Y]3};gl60@192l2'
    -];
    -
    -
    -/**
    - * Names of subcategories. Each message this array is the
    - * name for the corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_HAN_11_17_STROKE_RADICALS = [
    -  '\u9B5A',
    -  '\u9CE5',
    -  '\u9E75',
    -  '\u9E7F',
    -  '\u9EA5',
    -  '\u9EA6',
    -  '\u9EBB',
    -  '\u9EC3',
    -  '\u9ECD',
    -  '\u9ED1',
    -  '\u9EF9',
    -  '\u9EFD',
    -  '\u9EFE',
    -  '\u9F0E',
    -  '\u9F13',
    -  '\u9F20',
    -  '\u9F3B',
    -  '\u9F4A',
    -  '\u9F52',
    -  '\u9F8D',
    -  '\u9F9C',
    -  '\u9FA0',
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY,
    -  goog.i18n.CharPickerData.MSG_CP_LESS_COMMON
    -];
    -
    -
    -/**
    - * List of characters in base88 encoding scheme. Each base88 encoded
    - * charater string represents corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}. Encoding
    - * scheme is described in {@code goog.i18n.CharListDecompressor}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.CHARLIST_OF_HAN_11_17_STROKE_RADICALS = [
    -  'Y7f0NQXWPh',
    -  'Qhf0dB87B8l59c',
    -  'w@f0!',
    -  'o[f0V3',
    -  '2`f08d1',
    -  'A`f0n1E',
    -  '2|f0s',
    -  '(|f0,',
    -  'w}f0M',
    -  'IdN0(mI0s8#2',
    -  'w3g0M',
    -  '24g08|',
    -  'A4g091E',
    -  'o5g0U',
    -  '26g071',
    -  'I7g0V2',
    -  'w9g0N1',
    -  '2Bg0c',
    -  '(Bg0}3',
    -  'AHg0E8s',
    -  'gIg0E',
    -  ';Ig0c',
    -  'YtC0#12hC2fYt1>yl1692H26ef66P5946H5nE.6',
    -  'IDK0t9$@9uNDGkoOR1fk^x102.20nDQf301=^N50;g202j30M^>90od80g320to12t!]1-H8F[GN6284075f3@394E8l2.G'
    -];
    -
    -
    -/**
    - * Names of subcategories. Each message this array is the
    - * name for the corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_HAN_OTHER = [
    -  goog.i18n.CharPickerData.MSG_CP_CJK_STROKES,
    -  goog.i18n.CharPickerData.MSG_CP_IDEOGRAPHIC_DESCRIPTION,
    -  goog.i18n.CharPickerData.MSG_CP_OTHER,
    -  goog.i18n.CharPickerData.MSG_CP_COMPATIBILITY,
    -  goog.i18n.CharPickerData.MSG_CP_LESS_COMMON
    -];
    -
    -
    -/**
    - * List of characters in base88 encoding scheme. Each base88 encoded
    - * charater string represents corresponding subcategory specified in
    - * {@code goog.i18n.CharPickerData.subcategories}. Encoding
    - * scheme is described in {@code goog.i18n.CharListDecompressor}.
    - * @type {Array<string>}
    - */
    -goog.i18n.CharPickerData.CHARLIST_OF_HAN_OTHER = [
    -  'AQC0N28M8d7H%F3',
    -  'oxC0|',
    -  'AzC0M8|8}1mmWM2iT0o|O065ms0P3MH1',
    -  'gMD0F3PB|%CF2[U%8#2Q+r0M',
    -  'Q=727K'
    -];
    -
    -
    -/**
    - * Subcategory names. Each subarray in this array is a list of subcategory
    - * names for the corresponding category specified in
    - * {@code goog.i18n.CharPickerData.categories}.
    - * @type {Array<Array<string>>}
    - */
    -goog.i18n.CharPickerData.prototype.subcategories = [
    -  goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_SYMBOL,
    -  goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_EMOJI,
    -  goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_PUNCTUATION,
    -  goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_NUMBER,
    -  goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_FORMAT_WHITESPACE,
    -  goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_MODIFIER,
    -  goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_LATIN,
    -  goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_OTHER_EUROPEAN_SCRIPTS,
    -  goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_AMERICAN_SCRIPTS,
    -  goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_AFRICAN_SCRIPTS,
    -  goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_MIDDLE_EASTERN_SCRIPTS,
    -  goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_SOUTH_ASIAN_SCRIPTS,
    -  goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_SOUTHEAST_ASIAN_SCRIPTS,
    -  goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_HANGUL,
    -  goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_OTHER_EAST_ASIAN_SCRIPTS,
    -  goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_HAN_1_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_HAN_2_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_HAN_3_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_HAN_4_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_HAN_5_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_HAN_6_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_HAN_7_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_HAN_8_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_HAN_9_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_HAN_10_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_HAN_11_17_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.SUBCATEGORY_NAMES_OF_HAN_OTHER
    -];
    -
    -
    -/**
    - * Character lists in base88 encoding scheme. Each subarray is a list of
    - * base88 encoded charater strings representing corresponding subcategory
    - * specified in {@code goog.i18n.CharPickerData.categories}. Encoding
    - * scheme is described in {@code goog.i18n.CharListDecompressor}.
    - * @type {Array<Array<string>>}
    - */
    -goog.i18n.CharPickerData.prototype.charList = [
    -  goog.i18n.CharPickerData.CHARLIST_OF_SYMBOL,
    -  goog.i18n.CharPickerData.CHARLIST_OF_EMOJI,
    -  goog.i18n.CharPickerData.CHARLIST_OF_PUNCTUATION,
    -  goog.i18n.CharPickerData.CHARLIST_OF_NUMBER,
    -  goog.i18n.CharPickerData.CHARLIST_OF_FORMAT_WHITESPACE,
    -  goog.i18n.CharPickerData.CHARLIST_OF_MODIFIER,
    -  goog.i18n.CharPickerData.CHARLIST_OF_LATIN,
    -  goog.i18n.CharPickerData.CHARLIST_OF_OTHER_EUROPEAN_SCRIPTS,
    -  goog.i18n.CharPickerData.CHARLIST_OF_AMERICAN_SCRIPTS,
    -  goog.i18n.CharPickerData.CHARLIST_OF_AFRICAN_SCRIPTS,
    -  goog.i18n.CharPickerData.CHARLIST_OF_MIDDLE_EASTERN_SCRIPTS,
    -  goog.i18n.CharPickerData.CHARLIST_OF_SOUTH_ASIAN_SCRIPTS,
    -  goog.i18n.CharPickerData.CHARLIST_OF_SOUTHEAST_ASIAN_SCRIPTS,
    -  goog.i18n.CharPickerData.CHARLIST_OF_HANGUL,
    -  goog.i18n.CharPickerData.CHARLIST_OF_OTHER_EAST_ASIAN_SCRIPTS,
    -  goog.i18n.CharPickerData.CHARLIST_OF_HAN_1_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.CHARLIST_OF_HAN_2_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.CHARLIST_OF_HAN_3_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.CHARLIST_OF_HAN_4_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.CHARLIST_OF_HAN_5_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.CHARLIST_OF_HAN_6_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.CHARLIST_OF_HAN_7_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.CHARLIST_OF_HAN_8_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.CHARLIST_OF_HAN_9_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.CHARLIST_OF_HAN_10_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.CHARLIST_OF_HAN_11_17_STROKE_RADICALS,
    -  goog.i18n.CharPickerData.CHARLIST_OF_HAN_OTHER
    -];
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/collation.js b/src/database/third_party/closure-library/closure/goog/i18n/collation.js
    deleted file mode 100644
    index 7314912b88d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/collation.js
    +++ /dev/null
    @@ -1,58 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Contains helper functions for performing locale-sensitive
    - *     collation.
    - */
    -
    -
    -goog.provide('goog.i18n.collation');
    -
    -
    -/**
    - * Returns the comparator for a locale. If a locale is not explicitly specified,
    - * a comparator for the user's locale will be returned. Note that if the browser
    - * does not support locale-sensitive string comparisons, the comparator returned
    - * will be a simple codepoint comparator.
    - *
    - * @param {string=} opt_locale the locale that the comparator is used for.
    - * @return {function(string, string): number} The locale-specific comparator.
    - */
    -goog.i18n.collation.createComparator = function(opt_locale) {
    -  // See http://code.google.com/p/v8-i18n.
    -  if (goog.i18n.collation.hasNativeComparator()) {
    -    var intl = goog.global.Intl;
    -    return new intl.Collator([opt_locale || goog.LOCALE]).compare;
    -  } else {
    -    return function(arg1, arg2) {
    -      return arg1.localeCompare(arg2);
    -    };
    -  }
    -};
    -
    -
    -/**
    - * Returns true if a locale-sensitive comparator is available for a locale. If
    - * a locale is not explicitly specified, the user's locale is used instead.
    - *
    - * @param {string=} opt_locale The locale to be checked.
    - * @return {boolean} Whether there is a locale-sensitive comparator available
    - *     for the locale.
    - */
    -goog.i18n.collation.hasNativeComparator = function(opt_locale) {
    -  var intl = goog.global.Intl;
    -  return !!(intl && intl.Collator);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/collation_test.html b/src/database/third_party/closure-library/closure/goog/i18n/collation_test.html
    deleted file mode 100644
    index 550b24610a6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/collation_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<html>
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.i18n.collation
    -  </title>
    -  <meta charset="utf-8" />
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.i18n.collationTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/collation_test.js b/src/database/third_party/closure-library/closure/goog/i18n/collation_test.js
    deleted file mode 100644
    index d2cbe4e026a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/collation_test.js
    +++ /dev/null
    @@ -1,64 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -goog.provide('goog.i18n.collationTest');
    -goog.setTestOnly('goog.i18n.collationTest');
    -
    -goog.require('goog.i18n.collation');
    -goog.require('goog.testing.ExpectedFailures');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -var expectedFailures;
    -
    -function setUpPage() {
    -  expectedFailures = new goog.testing.ExpectedFailures();
    -}
    -
    -function tearDown() {
    -  expectedFailures.handleTearDown();
    -}
    -
    -function testGetEnComparator() {
    -  goog.LOCALE = 'en';
    -  var compare = goog.i18n.collation.createComparator();
    -  // The côte/coté comparison fails in FF/Linux (v19.0) because
    -  // calling 'côte'.localeCompare('coté')  gives a negative number (wrong)
    -  // when the test is run but a positive number (correct) when calling
    -  // it later in the web console. FF/OSX doesn't have this problem.
    -  // Mozilla bug: https://bugzilla.mozilla.org/show_bug.cgi?id=856115
    -  expectedFailures.expectFailureFor(
    -      goog.userAgent.GECKO && goog.userAgent.LINUX);
    -  try {
    -    assertTrue(compare('côte', 'coté') > 0);
    -  } catch (e) {
    -    expectedFailures.handleException(e);
    -  }
    -}
    -
    -function testGetFrComparator() {
    -  goog.LOCALE = 'fr-CA';
    -  var compare = goog.i18n.collation.createComparator();
    -  if (!goog.i18n.collation.hasNativeComparator()) return;
    -  assertTrue(compare('côte', 'coté') < 0);
    -}
    -
    -function testGetComparatorForSpecificLocale() {
    -  goog.LOCALE = 'en';
    -  var compare = goog.i18n.collation.createComparator('fr-CA');
    -  if (!goog.i18n.collation.hasNativeComparator('fr-CA')) return;
    -  // 'côte' and 'coté' sort differently for en and fr-CA.
    -  assertTrue(compare('côte', 'coté') < 0);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/compactnumberformatsymbols.js b/src/database/third_party/closure-library/closure/goog/i18n/compactnumberformatsymbols.js
    deleted file mode 100644
    index 979ceb3e8e1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/compactnumberformatsymbols.js
    +++ /dev/null
    @@ -1,9631 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
    -// implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Compact number formatting symbols.
    - *
    - * This file is autogenerated by script:
    - * http://go/generate_number_constants.py
    - * using the --for_closure flag.
    - * File generated from CLDR ver. 26
    - *
    - * To reduce the file size (which may cause issues in some JS
    - * developing environments), this file will only contain locales
    - * that are frequently used by web applications. This is defined as
    - * closure_tier1_locales and will change (most likely addition)
    - * over time.  Rest of the data can be found in another file named
    - * "compactnumberformatsymbols_ext.js", which will be generated at
    - * the same time together with this file.
    - *
    - * Before checkin, this file could have been manually edited. This is
    - * to incorporate changes before we could fix CLDR. All manual
    - * modification must be documented in this section, and should be
    - * removed after those changes land to CLDR.
    - */
    -
    -goog.provide('goog.i18n.CompactNumberFormatSymbols');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_af');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_af_ZA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_am');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_am_ET');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ar');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_001');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_az');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_az_Latn_AZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_bg');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_bg_BG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_bn');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_bn_BD');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_br');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_br_FR');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ca');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ca_AD');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ca_ES');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ca_ES_VALENCIA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ca_FR');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ca_IT');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_chr');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_chr_US');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_cs');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_cs_CZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_cy');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_cy_GB');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_da');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_da_DK');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_da_GL');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_de');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_de_AT');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_de_BE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_de_CH');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_de_DE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_de_LU');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_el');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_el_GR');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_001');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_AS');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_AU');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_DG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_FM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_GB');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_GU');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_IE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_IN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_IO');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_MH');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_MP');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_PR');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_PW');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_SG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_TC');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_UM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_US');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_VG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_VI');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_ZA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_ZW');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_es');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_es_419');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_es_EA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_es_ES');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_es_IC');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_et');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_et_EE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_eu');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_eu_ES');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fa');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fa_IR');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fi');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fi_FI');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fil');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fil_PH');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_BL');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_CA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_FR');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_GF');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_GP');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_MC');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_MF');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_MQ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_PM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_RE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_YT');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ga');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ga_IE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_gl');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_gl_ES');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_gsw');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_gsw_CH');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_gsw_LI');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_gu');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_gu_IN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_haw');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_haw_US');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_he');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_he_IL');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_hi');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_hi_IN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_hr');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_hr_HR');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_hu');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_hu_HU');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_hy');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_hy_AM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_id');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_id_ID');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_in');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_is');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_is_IS');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_it');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_it_IT');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_it_SM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_iw');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ja');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ja_JP');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ka');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ka_GE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_kk');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_kk_Cyrl_KZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_km');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_km_KH');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_kn');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_kn_IN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ko');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ko_KR');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ky');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ky_Cyrl_KG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ln');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ln_CD');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_lo');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_lo_LA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_lt');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_lt_LT');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_lv');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_lv_LV');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_mk');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_mk_MK');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ml');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ml_IN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_mn');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_mn_Cyrl_MN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_mr');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_mr_IN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ms');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ms_Latn_MY');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_mt');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_mt_MT');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_my');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_my_MM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_nb');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_nb_NO');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_nb_SJ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ne');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ne_NP');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_nl');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_nl_NL');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_no');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_no_NO');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_or');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_or_IN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_pa');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_pa_Guru_IN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_pl');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_pl_PL');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_pt');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_pt_BR');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_pt_PT');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ro');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ro_RO');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ru');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ru_RU');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_si');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_si_LK');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sk');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sk_SK');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sl');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sl_SI');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sq');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sq_AL');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sr');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sr_Cyrl_RS');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sv');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sv_SE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sw');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sw_TZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ta');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ta_IN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_te');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_te_IN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_th');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_th_TH');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_tl');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_tr');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_tr_TR');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_uk');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_uk_UA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ur');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ur_PK');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_uz');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_uz_Latn_UZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_vi');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_vi_VN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_zh');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_zh_CN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_zh_HK');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_zh_Hans_CN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_zh_TW');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_zu');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_zu_ZA');
    -
    -
    -/**
    - * Compact number formatting symbols for locale af.
    - */
    -goog.i18n.CompactNumberFormatSymbols_af = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '0'
    -    },
    -    '100000': {
    -      'other': '0'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0m'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0m'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0m'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mjd'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mjd'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mjd'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 duisend'
    -    },
    -    '10000': {
    -      'other': '00 duisend'
    -    },
    -    '100000': {
    -      'other': '000 duisend'
    -    },
    -    '1000000': {
    -      'other': '0 miljoen'
    -    },
    -    '10000000': {
    -      'other': '00 miljoen'
    -    },
    -    '100000000': {
    -      'other': '000 miljoen'
    -    },
    -    '1000000000': {
    -      'other': '0 miljard'
    -    },
    -    '10000000000': {
    -      'other': '00 miljard'
    -    },
    -    '100000000000': {
    -      'other': '000 miljard'
    -    },
    -    '1000000000000': {
    -      'other': '0 biljoen'
    -    },
    -    '10000000000000': {
    -      'other': '00 biljoen'
    -    },
    -    '100000000000000': {
    -      'other': '000 biljoen'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale af_ZA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_af_ZA =
    -    goog.i18n.CompactNumberFormatSymbols_af;
    -
    -
    -/**
    - * Compact number formatting symbols for locale am.
    - */
    -goog.i18n.CompactNumberFormatSymbols_am = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u123A'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u123A'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u123A'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u121C\u1275\u122D'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u121C\u1275\u122D'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u121C\u1275\u122D'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u1262'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u1262'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u1262'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u1275'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u1275'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u1275'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u123A'
    -    },
    -    '10000': {
    -      'other': '00 \u123A'
    -    },
    -    '100000': {
    -      'other': '000 \u123A'
    -    },
    -    '1000000': {
    -      'other': '0 \u121A\u120A\u12EE\u1295'
    -    },
    -    '10000000': {
    -      'other': '00 \u121A\u120A\u12EE\u1295'
    -    },
    -    '100000000': {
    -      'other': '000 \u121A\u120A\u12EE\u1295'
    -    },
    -    '1000000000': {
    -      'other': '0 \u1262\u120A\u12EE\u1295'
    -    },
    -    '10000000000': {
    -      'other': '00 \u1262\u120A\u12EE\u1295'
    -    },
    -    '100000000000': {
    -      'other': '000 \u1262\u120A\u12EE\u1295'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u1275\u122A\u120A\u12EE\u1295'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u1275\u122A\u120A\u12EE\u1295'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u1275\u122A\u120A\u12EE\u1295'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale am_ET.
    - */
    -goog.i18n.CompactNumberFormatSymbols_am_ET =
    -    goog.i18n.CompactNumberFormatSymbols_am;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ar.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ar = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00 \u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000 \u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ar_001.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ar_001 =
    -    goog.i18n.CompactNumberFormatSymbols_ar;
    -
    -
    -/**
    - * Compact number formatting symbols for locale az.
    - */
    -goog.i18n.CompactNumberFormatSymbols_az = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale az_Latn_AZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_az_Latn_AZ =
    -    goog.i18n.CompactNumberFormatSymbols_az;
    -
    -
    -/**
    - * Compact number formatting symbols for locale bg.
    - */
    -goog.i18n.CompactNumberFormatSymbols_bg = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0445\u0438\u043B.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0445\u0438\u043B.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0445\u0438\u043B.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u043C\u043B\u043D.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u043C\u043B\u043D.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u043C\u043B\u043D.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u043C\u043B\u0440\u0434.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u043C\u043B\u0440\u0434.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u043C\u043B\u0440\u0434.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u0442\u0440\u043B\u043D.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u0442\u0440\u043B\u043D.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u0442\u0440\u043B\u043D.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0445\u0438\u043B\u044F\u0434\u0438'
    -    },
    -    '10000': {
    -      'other': '00 \u0445\u0438\u043B\u044F\u0434\u0438'
    -    },
    -    '100000': {
    -      'other': '000 \u0445\u0438\u043B\u044F\u0434\u0438'
    -    },
    -    '1000000': {
    -      'other': '0 \u043C\u0438\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '10000000': {
    -      'other': '00 \u043C\u0438\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '100000000': {
    -      'other': '000 \u043C\u0438\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '1000000000': {
    -      'other': '0 \u043C\u0438\u043B\u0438\u0430\u0440\u0434\u0430'
    -    },
    -    '10000000000': {
    -      'other': '00 \u043C\u0438\u043B\u0438\u0430\u0440\u0434\u0430'
    -    },
    -    '100000000000': {
    -      'other': '000 \u043C\u0438\u043B\u0438\u0430\u0440\u0434\u0430'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0442\u0440\u0438\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0442\u0440\u0438\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0442\u0440\u0438\u043B\u0438\u043E\u043D\u0430'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale bg_BG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_bg_BG =
    -    goog.i18n.CompactNumberFormatSymbols_bg;
    -
    -
    -/**
    - * Compact number formatting symbols for locale bn.
    - */
    -goog.i18n.CompactNumberFormatSymbols_bn = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u09B9\u09BE\u099C\u09BE\u09B0'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u09B9\u09BE\u099C\u09BE\u09B0'
    -    },
    -    '100000': {
    -      'other': '0\u00A0\u09B2\u09BE\u0996'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u09B9\u09BE\u099C\u09BE\u09B0'
    -    },
    -    '10000': {
    -      'other': '00 \u09B9\u09BE\u099C\u09BE\u09B0'
    -    },
    -    '100000': {
    -      'other': '0 \u09B2\u09BE\u0996'
    -    },
    -    '1000000': {
    -      'other': '0 \u09AE\u09BF\u09B2\u09BF\u09AF\u09BC\u09A8'
    -    },
    -    '10000000': {
    -      'other': '00 \u09AE\u09BF\u09B2\u09BF\u09AF\u09BC\u09A8'
    -    },
    -    '100000000': {
    -      'other': '000 \u09AE\u09BF\u09B2\u09BF\u09AF\u09BC\u09A8'
    -    },
    -    '1000000000': {
    -      'other': '0 \u09AC\u09BF\u09B2\u09BF\u09AF\u09BC\u09A8'
    -    },
    -    '10000000000': {
    -      'other': '00 \u09AC\u09BF\u09B2\u09BF\u09AF\u09BC\u09A8'
    -    },
    -    '100000000000': {
    -      'other': '000 \u09AC\u09BF\u09B2\u09BF\u09AF\u09BC\u09A8'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u099F\u09CD\u09B0\u09BF\u09B2\u09BF\u09AF\u09BC\u09A8'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u099F\u09CD\u09B0\u09BF\u09B2\u09BF\u09AF\u09BC\u09A8'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u099F\u09CD\u09B0\u09BF\u09B2\u09BF\u09AF\u09BC\u09A8'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale bn_BD.
    - */
    -goog.i18n.CompactNumberFormatSymbols_bn_BD =
    -    goog.i18n.CompactNumberFormatSymbols_bn;
    -
    -
    -/**
    - * Compact number formatting symbols for locale br.
    - */
    -goog.i18n.CompactNumberFormatSymbols_br = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale br_FR.
    - */
    -goog.i18n.CompactNumberFormatSymbols_br_FR =
    -    goog.i18n.CompactNumberFormatSymbols_br;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ca.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ca = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0m'
    -    },
    -    '10000': {
    -      'other': '00m'
    -    },
    -    '100000': {
    -      'other': '000m'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0000\u00A0M'
    -    },
    -    '10000000000': {
    -      'other': '00mM'
    -    },
    -    '100000000000': {
    -      'other': '000mM'
    -    },
    -    '1000000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0B'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 milers'
    -    },
    -    '10000': {
    -      'other': '00 milers'
    -    },
    -    '100000': {
    -      'other': '000 milers'
    -    },
    -    '1000000': {
    -      'other': '0 milions'
    -    },
    -    '10000000': {
    -      'other': '00 milions'
    -    },
    -    '100000000': {
    -      'other': '000 milions'
    -    },
    -    '1000000000': {
    -      'other': '0 milers de milions'
    -    },
    -    '10000000000': {
    -      'other': '00 milers de milions'
    -    },
    -    '100000000000': {
    -      'other': '000 milers de milions'
    -    },
    -    '1000000000000': {
    -      'other': '0 bilions'
    -    },
    -    '10000000000000': {
    -      'other': '00 bilions'
    -    },
    -    '100000000000000': {
    -      'other': '000 bilions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ca_AD.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ca_AD =
    -    goog.i18n.CompactNumberFormatSymbols_ca;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ca_ES.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ca_ES =
    -    goog.i18n.CompactNumberFormatSymbols_ca;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ca_ES_VALENCIA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ca_ES_VALENCIA =
    -    goog.i18n.CompactNumberFormatSymbols_ca;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ca_FR.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ca_FR =
    -    goog.i18n.CompactNumberFormatSymbols_ca;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ca_IT.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ca_IT =
    -    goog.i18n.CompactNumberFormatSymbols_ca;
    -
    -
    -/**
    - * Compact number formatting symbols for locale chr.
    - */
    -goog.i18n.CompactNumberFormatSymbols_chr = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale chr_US.
    - */
    -goog.i18n.CompactNumberFormatSymbols_chr_US =
    -    goog.i18n.CompactNumberFormatSymbols_chr;
    -
    -
    -/**
    - * Compact number formatting symbols for locale cs.
    - */
    -goog.i18n.CompactNumberFormatSymbols_cs = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0tis.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0tis.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0tis.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mil.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mil.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mil.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mld.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mld.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mld.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bil.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bil.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bil.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 tis\u00EDc'
    -    },
    -    '10000': {
    -      'other': '00 tis\u00EDc'
    -    },
    -    '100000': {
    -      'other': '000 tis\u00EDc'
    -    },
    -    '1000000': {
    -      'other': '0 milion\u016F'
    -    },
    -    '10000000': {
    -      'other': '00 milion\u016F'
    -    },
    -    '100000000': {
    -      'other': '000 milion\u016F'
    -    },
    -    '1000000000': {
    -      'other': '0 miliard'
    -    },
    -    '10000000000': {
    -      'other': '00 miliard'
    -    },
    -    '100000000000': {
    -      'other': '000 miliard'
    -    },
    -    '1000000000000': {
    -      'other': '0 bilion\u016F'
    -    },
    -    '10000000000000': {
    -      'other': '00 bilion\u016F'
    -    },
    -    '100000000000000': {
    -      'other': '000 bilion\u016F'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale cs_CZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_cs_CZ =
    -    goog.i18n.CompactNumberFormatSymbols_cs;
    -
    -
    -/**
    - * Compact number formatting symbols for locale cy.
    - */
    -goog.i18n.CompactNumberFormatSymbols_cy = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 miliwn'
    -    },
    -    '10000000': {
    -      'other': '00 miliwn'
    -    },
    -    '100000000': {
    -      'other': '000 miliwn'
    -    },
    -    '1000000000': {
    -      'other': '0 biliwn'
    -    },
    -    '10000000000': {
    -      'other': '00 biliwn'
    -    },
    -    '100000000000': {
    -      'other': '000 biliwn'
    -    },
    -    '1000000000000': {
    -      'other': '0 triliwn'
    -    },
    -    '10000000000000': {
    -      'other': '00 triliwn'
    -    },
    -    '100000000000000': {
    -      'other': '000 triliwn'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale cy_GB.
    - */
    -goog.i18n.CompactNumberFormatSymbols_cy_GB =
    -    goog.i18n.CompactNumberFormatSymbols_cy;
    -
    -
    -/**
    - * Compact number formatting symbols for locale da.
    - */
    -goog.i18n.CompactNumberFormatSymbols_da = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0td'
    -    },
    -    '10000': {
    -      'other': '00\u00A0td'
    -    },
    -    '100000': {
    -      'other': '000\u00A0td'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mio'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mio'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mio'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mia'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mia'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mia'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bill'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bill'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bill'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 tusind'
    -    },
    -    '10000': {
    -      'other': '00 tusind'
    -    },
    -    '100000': {
    -      'other': '000 tusind'
    -    },
    -    '1000000': {
    -      'other': '0 millioner'
    -    },
    -    '10000000': {
    -      'other': '00 millioner'
    -    },
    -    '100000000': {
    -      'other': '000 millioner'
    -    },
    -    '1000000000': {
    -      'other': '0 milliarder'
    -    },
    -    '10000000000': {
    -      'other': '00 milliarder'
    -    },
    -    '100000000000': {
    -      'other': '000 milliarder'
    -    },
    -    '1000000000000': {
    -      'other': '0 billioner'
    -    },
    -    '10000000000000': {
    -      'other': '00 billioner'
    -    },
    -    '100000000000000': {
    -      'other': '000 billioner'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale da_DK.
    - */
    -goog.i18n.CompactNumberFormatSymbols_da_DK =
    -    goog.i18n.CompactNumberFormatSymbols_da;
    -
    -
    -/**
    - * Compact number formatting symbols for locale da_GL.
    - */
    -goog.i18n.CompactNumberFormatSymbols_da_GL =
    -    goog.i18n.CompactNumberFormatSymbols_da;
    -
    -
    -/**
    - * Compact number formatting symbols for locale de.
    - */
    -goog.i18n.CompactNumberFormatSymbols_de = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0Tsd.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0Tsd.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0Tsd.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0Mio'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0Mio'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0Mio'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Mrd'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Mrd'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Mrd'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bio.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bio.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bio.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 Tausend'
    -    },
    -    '10000': {
    -      'other': '00 Tausend'
    -    },
    -    '100000': {
    -      'other': '000 Tausend'
    -    },
    -    '1000000': {
    -      'other': '0 Millionen'
    -    },
    -    '10000000': {
    -      'other': '00 Millionen'
    -    },
    -    '100000000': {
    -      'other': '000 Millionen'
    -    },
    -    '1000000000': {
    -      'other': '0 Milliarden'
    -    },
    -    '10000000000': {
    -      'other': '00 Milliarden'
    -    },
    -    '100000000000': {
    -      'other': '000 Milliarden'
    -    },
    -    '1000000000000': {
    -      'other': '0 Billionen'
    -    },
    -    '10000000000000': {
    -      'other': '00 Billionen'
    -    },
    -    '100000000000000': {
    -      'other': '000 Billionen'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale de_AT.
    - */
    -goog.i18n.CompactNumberFormatSymbols_de_AT = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0Tsd.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0Tsd.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0Tsd.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0Mio'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0Mio'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0Mio'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Mrd'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Mrd'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Mrd'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bio.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bio.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bio.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 Tausend'
    -    },
    -    '10000': {
    -      'other': '00 Tausend'
    -    },
    -    '100000': {
    -      'other': '000 Tausend'
    -    },
    -    '1000000': {
    -      'other': '0 Millionen'
    -    },
    -    '10000000': {
    -      'other': '00 Millionen'
    -    },
    -    '100000000': {
    -      'other': '000 Millionen'
    -    },
    -    '1000000000': {
    -      'other': '0 Milliarden'
    -    },
    -    '10000000000': {
    -      'other': '00 Milliarden'
    -    },
    -    '100000000000': {
    -      'other': '000 Milliarden'
    -    },
    -    '1000000000000': {
    -      'other': '0 Billionen'
    -    },
    -    '10000000000000': {
    -      'other': '00 Billionen'
    -    },
    -    '100000000000000': {
    -      'other': '000 Billionen'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale de_BE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_de_BE =
    -    goog.i18n.CompactNumberFormatSymbols_de;
    -
    -
    -/**
    - * Compact number formatting symbols for locale de_CH.
    - */
    -goog.i18n.CompactNumberFormatSymbols_de_CH = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0Tsd.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0Tsd.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0Tsd.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0Mio'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0Mio'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0Mio'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Mrd'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Mrd'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Mrd'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bio.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bio.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bio.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 Tausend'
    -    },
    -    '10000': {
    -      'other': '00 Tausend'
    -    },
    -    '100000': {
    -      'other': '000 Tausend'
    -    },
    -    '1000000': {
    -      'other': '0 Millionen'
    -    },
    -    '10000000': {
    -      'other': '00 Millionen'
    -    },
    -    '100000000': {
    -      'other': '000 Millionen'
    -    },
    -    '1000000000': {
    -      'other': '0 Milliarden'
    -    },
    -    '10000000000': {
    -      'other': '00 Milliarden'
    -    },
    -    '100000000000': {
    -      'other': '000 Milliarden'
    -    },
    -    '1000000000000': {
    -      'other': '0 Billionen'
    -    },
    -    '10000000000000': {
    -      'other': '00 Billionen'
    -    },
    -    '100000000000000': {
    -      'other': '000 Billionen'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale de_DE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_de_DE =
    -    goog.i18n.CompactNumberFormatSymbols_de;
    -
    -
    -/**
    - * Compact number formatting symbols for locale de_LU.
    - */
    -goog.i18n.CompactNumberFormatSymbols_de_LU =
    -    goog.i18n.CompactNumberFormatSymbols_de;
    -
    -
    -/**
    - * Compact number formatting symbols for locale el.
    - */
    -goog.i18n.CompactNumberFormatSymbols_el = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u03C7\u03B9\u03BB.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u03C7\u03B9\u03BB.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u03C7\u03B9\u03BB.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u03B5\u03BA.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u03B5\u03BA.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u03B5\u03BA.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u03B4\u03B9\u03C3.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u03B4\u03B9\u03C3.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u03B4\u03B9\u03C3.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u03C4\u03C1\u03B9\u03C3.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u03C4\u03C1\u03B9\u03C3.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u03C4\u03C1\u03B9\u03C3.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u03C7\u03B9\u03BB\u03B9\u03AC\u03B4\u03B5\u03C2'
    -    },
    -    '10000': {
    -      'other': '00 \u03C7\u03B9\u03BB\u03B9\u03AC\u03B4\u03B5\u03C2'
    -    },
    -    '100000': {
    -      'other': '000 \u03C7\u03B9\u03BB\u03B9\u03AC\u03B4\u03B5\u03C2'
    -    },
    -    '1000000': {
    -      'other': '0 \u03B5\u03BA\u03B1\u03C4\u03BF\u03BC\u03BC\u03CD\u03C1\u03B9\u03B1'
    -    },
    -    '10000000': {
    -      'other': '00 \u03B5\u03BA\u03B1\u03C4\u03BF\u03BC\u03BC\u03CD\u03C1\u03B9\u03B1'
    -    },
    -    '100000000': {
    -      'other': '000 \u03B5\u03BA\u03B1\u03C4\u03BF\u03BC\u03BC\u03CD\u03C1\u03B9\u03B1'
    -    },
    -    '1000000000': {
    -      'other': '0 \u03B4\u03B9\u03C3\u03B5\u03BA\u03B1\u03C4\u03BF\u03BC\u03BC\u03CD\u03C1\u03B9\u03B1'
    -    },
    -    '10000000000': {
    -      'other': '00 \u03B4\u03B9\u03C3\u03B5\u03BA\u03B1\u03C4\u03BF\u03BC\u03BC\u03CD\u03C1\u03B9\u03B1'
    -    },
    -    '100000000000': {
    -      'other': '000 \u03B4\u03B9\u03C3\u03B5\u03BA\u03B1\u03C4\u03BF\u03BC\u03BC\u03CD\u03C1\u03B9\u03B1'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u03C4\u03C1\u03B9\u03C3\u03B5\u03BA\u03B1\u03C4\u03BF\u03BC\u03BC\u03CD\u03C1\u03B9\u03B1'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u03C4\u03C1\u03B9\u03C3\u03B5\u03BA\u03B1\u03C4\u03BF\u03BC\u03BC\u03CD\u03C1\u03B9\u03B1'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u03C4\u03C1\u03B9\u03C3\u03B5\u03BA\u03B1\u03C4\u03BF\u03BC\u03BC\u03CD\u03C1\u03B9\u03B1'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale el_GR.
    - */
    -goog.i18n.CompactNumberFormatSymbols_el_GR =
    -    goog.i18n.CompactNumberFormatSymbols_el;
    -
    -
    -/**
    - * Compact number formatting symbols for locale en.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_001.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_001 =
    -    goog.i18n.CompactNumberFormatSymbols_en;
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_AS.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_AS =
    -    goog.i18n.CompactNumberFormatSymbols_en;
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_AU.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_AU = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_DG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_DG =
    -    goog.i18n.CompactNumberFormatSymbols_en;
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_FM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_FM =
    -    goog.i18n.CompactNumberFormatSymbols_en;
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_GB.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_GB = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_GU.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_GU =
    -    goog.i18n.CompactNumberFormatSymbols_en;
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_IE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_IE = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_IN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_IN = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_IO.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_IO =
    -    goog.i18n.CompactNumberFormatSymbols_en;
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_MH.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_MH =
    -    goog.i18n.CompactNumberFormatSymbols_en;
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_MP.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_MP =
    -    goog.i18n.CompactNumberFormatSymbols_en;
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_PR.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_PR =
    -    goog.i18n.CompactNumberFormatSymbols_en;
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_PW.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_PW =
    -    goog.i18n.CompactNumberFormatSymbols_en;
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_SG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_SG = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_TC.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_TC =
    -    goog.i18n.CompactNumberFormatSymbols_en;
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_UM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_UM =
    -    goog.i18n.CompactNumberFormatSymbols_en;
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_US.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_US =
    -    goog.i18n.CompactNumberFormatSymbols_en;
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_VG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_VG =
    -    goog.i18n.CompactNumberFormatSymbols_en;
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_VI.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_VI =
    -    goog.i18n.CompactNumberFormatSymbols_en;
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_ZA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_ZA = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_ZW.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_ZW =
    -    goog.i18n.CompactNumberFormatSymbols_en;
    -
    -
    -/**
    - * Compact number formatting symbols for locale es.
    - */
    -goog.i18n.CompactNumberFormatSymbols_es = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0000M'
    -    },
    -    '10000000000': {
    -      'other': '00MRD'
    -    },
    -    '100000000000': {
    -      'other': '000MRD'
    -    },
    -    '1000000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000000': {
    -      'other': '000B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 millones'
    -    },
    -    '10000000': {
    -      'other': '00 millones'
    -    },
    -    '100000000': {
    -      'other': '000 millones'
    -    },
    -    '1000000000': {
    -      'other': '0 mil millones'
    -    },
    -    '10000000000': {
    -      'other': '00 mil millones'
    -    },
    -    '100000000000': {
    -      'other': '000 mil millones'
    -    },
    -    '1000000000000': {
    -      'other': '0 billones'
    -    },
    -    '10000000000000': {
    -      'other': '00 billones'
    -    },
    -    '100000000000000': {
    -      'other': '000 billones'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale es_419.
    - */
    -goog.i18n.CompactNumberFormatSymbols_es_419 = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '00k'
    -    },
    -    '100000': {
    -      'other': '000k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0k\u00A0M'
    -    },
    -    '10000000000': {
    -      'other': '00k\u00A0M'
    -    },
    -    '100000000000': {
    -      'other': '000k\u00A0M'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0B'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0B'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 millones'
    -    },
    -    '10000000': {
    -      'other': '00 millones'
    -    },
    -    '100000000': {
    -      'other': '000 millones'
    -    },
    -    '1000000000': {
    -      'other': '0 mil millones'
    -    },
    -    '10000000000': {
    -      'other': '00 mil millones'
    -    },
    -    '100000000000': {
    -      'other': '000 mil millones'
    -    },
    -    '1000000000000': {
    -      'other': '0 billones'
    -    },
    -    '10000000000000': {
    -      'other': '00 billones'
    -    },
    -    '100000000000000': {
    -      'other': '000 billones'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale es_EA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_es_EA =
    -    goog.i18n.CompactNumberFormatSymbols_es;
    -
    -
    -/**
    - * Compact number formatting symbols for locale es_ES.
    - */
    -goog.i18n.CompactNumberFormatSymbols_es_ES =
    -    goog.i18n.CompactNumberFormatSymbols_es;
    -
    -
    -/**
    - * Compact number formatting symbols for locale es_IC.
    - */
    -goog.i18n.CompactNumberFormatSymbols_es_IC =
    -    goog.i18n.CompactNumberFormatSymbols_es;
    -
    -
    -/**
    - * Compact number formatting symbols for locale et.
    - */
    -goog.i18n.CompactNumberFormatSymbols_et = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0tuh'
    -    },
    -    '10000': {
    -      'other': '00\u00A0tuh'
    -    },
    -    '100000': {
    -      'other': '000\u00A0tuh'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mln'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mln'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mln'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mld'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mld'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mld'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0trl'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0trl'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0trl'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 tuhat'
    -    },
    -    '10000': {
    -      'other': '00 tuhat'
    -    },
    -    '100000': {
    -      'other': '000 tuhat'
    -    },
    -    '1000000': {
    -      'other': '0 miljonit'
    -    },
    -    '10000000': {
    -      'other': '00 miljonit'
    -    },
    -    '100000000': {
    -      'other': '000 miljonit'
    -    },
    -    '1000000000': {
    -      'other': '0 miljardit'
    -    },
    -    '10000000000': {
    -      'other': '00 miljardit'
    -    },
    -    '100000000000': {
    -      'other': '000 miljardit'
    -    },
    -    '1000000000000': {
    -      'other': '0 triljonit'
    -    },
    -    '10000000000000': {
    -      'other': '00 triljonit'
    -    },
    -    '100000000000000': {
    -      'other': '000 triljonit'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale et_EE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_et_EE =
    -    goog.i18n.CompactNumberFormatSymbols_et;
    -
    -
    -/**
    - * Compact number formatting symbols for locale eu.
    - */
    -goog.i18n.CompactNumberFormatSymbols_eu = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0000'
    -    },
    -    '10000': {
    -      'other': '00000'
    -    },
    -    '100000': {
    -      'other': '000000'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0000\u00A0M'
    -    },
    -    '10000000000': {
    -      'other': '00000\u00A0M'
    -    },
    -    '100000000000': {
    -      'other': '000000\u00A0M'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0B'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0B'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0000'
    -    },
    -    '10000': {
    -      'other': '00000'
    -    },
    -    '100000': {
    -      'other': '000000'
    -    },
    -    '1000000': {
    -      'other': '0 milioi'
    -    },
    -    '10000000': {
    -      'other': '00 milioi'
    -    },
    -    '100000000': {
    -      'other': '000 milioi'
    -    },
    -    '1000000000': {
    -      'other': '0000 milioi'
    -    },
    -    '10000000000': {
    -      'other': '00000 milioi'
    -    },
    -    '100000000000': {
    -      'other': '000000 milioi'
    -    },
    -    '1000000000000': {
    -      'other': '0 bilioi'
    -    },
    -    '10000000000000': {
    -      'other': '00 bilioi'
    -    },
    -    '100000000000000': {
    -      'other': '000 bilioi'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale eu_ES.
    - */
    -goog.i18n.CompactNumberFormatSymbols_eu_ES =
    -    goog.i18n.CompactNumberFormatSymbols_eu;
    -
    -
    -/**
    - * Compact number formatting symbols for locale fa.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fa = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0647\u0632\u0627\u0631'
    -    },
    -    '10000': {
    -      'other': '00 \u0647\u0632\u0627\u0631'
    -    },
    -    '100000': {
    -      'other': '000 \u0647\u0632\u0627\u0631'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u06CC\u0644\u06CC\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u06CC\u0644\u06CC\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u06CC\u0644\u06CC\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0645\u06CC\u0644\u06CC\u0627\u0631\u062F'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0645\u06CC\u0644\u06CC\u0627\u0631\u062F'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0645\u06CC\u0644\u06CC\u0627\u0631\u062F'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0647\u0632\u0627\u0631 \u0645\u06CC\u0644\u06CC\u0627\u0631\u062F'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0647\u0632\u0627\u0631 \u0645\u06CC\u0644\u06CC\u0627\u0631\u062F'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0647\u0632\u0627\u0631 \u0645\u06CC\u0644\u06CC\u0627\u0631\u062F'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fa_IR.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fa_IR =
    -    goog.i18n.CompactNumberFormatSymbols_fa;
    -
    -
    -/**
    - * Compact number formatting symbols for locale fi.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fi = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0t.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0t.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0t.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0milj.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0milj.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0milj.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mrd.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mrd.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mrd.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bilj.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bilj.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bilj.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 tuhatta'
    -    },
    -    '10000': {
    -      'other': '00 tuhatta'
    -    },
    -    '100000': {
    -      'other': '000 tuhatta'
    -    },
    -    '1000000': {
    -      'other': '0 miljoonaa'
    -    },
    -    '10000000': {
    -      'other': '00 miljoonaa'
    -    },
    -    '100000000': {
    -      'other': '000 miljoonaa'
    -    },
    -    '1000000000': {
    -      'other': '0 miljardia'
    -    },
    -    '10000000000': {
    -      'other': '00 miljardia'
    -    },
    -    '100000000000': {
    -      'other': '000 miljardia'
    -    },
    -    '1000000000000': {
    -      'other': '0 biljoonaa'
    -    },
    -    '10000000000000': {
    -      'other': '00 biljoonaa'
    -    },
    -    '100000000000000': {
    -      'other': '000 biljoonaa'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fi_FI.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fi_FI =
    -    goog.i18n.CompactNumberFormatSymbols_fi;
    -
    -
    -/**
    - * Compact number formatting symbols for locale fil.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fil = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 libo'
    -    },
    -    '10000': {
    -      'other': '00 libo'
    -    },
    -    '100000': {
    -      'other': '000 libo'
    -    },
    -    '1000000': {
    -      'other': '0 milyon'
    -    },
    -    '10000000': {
    -      'other': '00 milyon'
    -    },
    -    '100000000': {
    -      'other': '000 milyon'
    -    },
    -    '1000000000': {
    -      'other': '0 bilyon'
    -    },
    -    '10000000000': {
    -      'other': '00 bilyon'
    -    },
    -    '100000000000': {
    -      'other': '000 bilyon'
    -    },
    -    '1000000000000': {
    -      'other': '0 trilyon'
    -    },
    -    '10000000000000': {
    -      'other': '00 trilyon'
    -    },
    -    '100000000000000': {
    -      'other': '000 trilyon'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fil_PH.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fil_PH =
    -    goog.i18n.CompactNumberFormatSymbols_fil;
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_BL.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_BL =
    -    goog.i18n.CompactNumberFormatSymbols_fr;
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_CA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_CA = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0G'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0G'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0G'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0T'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0T'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_FR.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_FR =
    -    goog.i18n.CompactNumberFormatSymbols_fr;
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_GF.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_GF =
    -    goog.i18n.CompactNumberFormatSymbols_fr;
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_GP.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_GP =
    -    goog.i18n.CompactNumberFormatSymbols_fr;
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_MC.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_MC =
    -    goog.i18n.CompactNumberFormatSymbols_fr;
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_MF.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_MF =
    -    goog.i18n.CompactNumberFormatSymbols_fr;
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_MQ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_MQ =
    -    goog.i18n.CompactNumberFormatSymbols_fr;
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_PM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_PM =
    -    goog.i18n.CompactNumberFormatSymbols_fr;
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_RE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_RE =
    -    goog.i18n.CompactNumberFormatSymbols_fr;
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_YT.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_YT =
    -    goog.i18n.CompactNumberFormatSymbols_fr;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ga.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ga = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0k'
    -    },
    -    '10000': {
    -      'other': '00k'
    -    },
    -    '100000': {
    -      'other': '000k'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 m\u00EDle'
    -    },
    -    '10000': {
    -      'other': '00 m\u00EDle'
    -    },
    -    '100000': {
    -      'other': '000 m\u00EDle'
    -    },
    -    '1000000': {
    -      'other': '0 milli\u00FAn'
    -    },
    -    '10000000': {
    -      'other': '00 milli\u00FAn'
    -    },
    -    '100000000': {
    -      'other': '000 milli\u00FAn'
    -    },
    -    '1000000000': {
    -      'other': '0 billi\u00FAn'
    -    },
    -    '10000000000': {
    -      'other': '00 billi\u00FAn'
    -    },
    -    '100000000000': {
    -      'other': '000 billi\u00FAn'
    -    },
    -    '1000000000000': {
    -      'other': '0 trilli\u00FAn'
    -    },
    -    '10000000000000': {
    -      'other': '00 trilli\u00FAn'
    -    },
    -    '100000000000000': {
    -      'other': '000 trilli\u00FAn'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ga_IE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ga_IE =
    -    goog.i18n.CompactNumberFormatSymbols_ga;
    -
    -
    -/**
    - * Compact number formatting symbols for locale gl.
    - */
    -goog.i18n.CompactNumberFormatSymbols_gl = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0k\u00A0M'
    -    },
    -    '10000000000': {
    -      'other': '00k\u00A0M'
    -    },
    -    '100000000000': {
    -      'other': '000k\u00A0M'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0B'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0B'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 mill\u00F3ns'
    -    },
    -    '10000000': {
    -      'other': '00 mill\u00F3ns'
    -    },
    -    '100000000': {
    -      'other': '000 mill\u00F3ns'
    -    },
    -    '1000000000': {
    -      'other': '0 mil mill\u00F3ns'
    -    },
    -    '10000000000': {
    -      'other': '00 mil mill\u00F3ns'
    -    },
    -    '100000000000': {
    -      'other': '000 mil mill\u00F3ns'
    -    },
    -    '1000000000000': {
    -      'other': '0 bill\u00F3ns'
    -    },
    -    '10000000000000': {
    -      'other': '00 bill\u00F3ns'
    -    },
    -    '100000000000000': {
    -      'other': '000 bill\u00F3ns'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale gl_ES.
    - */
    -goog.i18n.CompactNumberFormatSymbols_gl_ES =
    -    goog.i18n.CompactNumberFormatSymbols_gl;
    -
    -
    -/**
    - * Compact number formatting symbols for locale gsw.
    - */
    -goog.i18n.CompactNumberFormatSymbols_gsw = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0tsd'
    -    },
    -    '10000': {
    -      'other': '00\u00A0tsd'
    -    },
    -    '100000': {
    -      'other': '000\u00A0tsd'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0Mio'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0Mio'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0Mio'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Mrd'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Mrd'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Mrd'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bio'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bio'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bio'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 tausend'
    -    },
    -    '10000': {
    -      'other': '00 tausend'
    -    },
    -    '100000': {
    -      'other': '000 tausend'
    -    },
    -    '1000000': {
    -      'other': '0 Millionen'
    -    },
    -    '10000000': {
    -      'other': '00 Millionen'
    -    },
    -    '100000000': {
    -      'other': '000 Millionen'
    -    },
    -    '1000000000': {
    -      'other': '0 Milliarden'
    -    },
    -    '10000000000': {
    -      'other': '00 Milliarden'
    -    },
    -    '100000000000': {
    -      'other': '000 Milliarden'
    -    },
    -    '1000000000000': {
    -      'other': '0 Billionen'
    -    },
    -    '10000000000000': {
    -      'other': '00 Billionen'
    -    },
    -    '100000000000000': {
    -      'other': '000 Billionen'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale gsw_CH.
    - */
    -goog.i18n.CompactNumberFormatSymbols_gsw_CH =
    -    goog.i18n.CompactNumberFormatSymbols_gsw;
    -
    -
    -/**
    - * Compact number formatting symbols for locale gsw_LI.
    - */
    -goog.i18n.CompactNumberFormatSymbols_gsw_LI =
    -    goog.i18n.CompactNumberFormatSymbols_gsw;
    -
    -
    -/**
    - * Compact number formatting symbols for locale gu.
    - */
    -goog.i18n.CompactNumberFormatSymbols_gu = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0AB9\u0A9C\u0ABE\u0AB0'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0AB9\u0A9C\u0ABE\u0AB0'
    -    },
    -    '100000': {
    -      'other': '0\u00A0\u0AB2\u0ABE\u0A96'
    -    },
    -    '1000000': {
    -      'other': '00\u00A0\u0AB2\u0ABE\u0A96'
    -    },
    -    '10000000': {
    -      'other': '0\u00A0\u0A95\u0AB0\u0ACB\u0AA1'
    -    },
    -    '100000000': {
    -      'other': '00\u00A0\u0A95\u0AB0\u0ACB\u0AA1'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0A85\u0AAC\u0A9C'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0A85\u0AAC\u0A9C'
    -    },
    -    '100000000000': {
    -      'other': '0\u00A0\u0AA8\u0ABF\u0A96\u0AB0\u0ACD\u0AB5'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u0AAE\u0AB9\u0ABE\u0AAA\u0AA6\u0ACD\u0AAE'
    -    },
    -    '10000000000000': {
    -      'other': '0\u00A0\u0AB6\u0A82\u0A95\u0AC1'
    -    },
    -    '100000000000000': {
    -      'other': '0\u00A0\u0A9C\u0AB2\u0AA7\u0ABF'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0AB9\u0A9C\u0ABE\u0AB0'
    -    },
    -    '10000': {
    -      'other': '00 \u0AB9\u0A9C\u0ABE\u0AB0'
    -    },
    -    '100000': {
    -      'other': '0 \u0AB2\u0ABE\u0A96'
    -    },
    -    '1000000': {
    -      'other': '00 \u0AB2\u0ABE\u0A96'
    -    },
    -    '10000000': {
    -      'other': '0 \u0A95\u0AB0\u0ACB\u0AA1'
    -    },
    -    '100000000': {
    -      'other': '00 \u0A95\u0AB0\u0ACB\u0AA1'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0A85\u0AAC\u0A9C'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0A85\u0AAC\u0A9C'
    -    },
    -    '100000000000': {
    -      'other': '0 \u0AA8\u0ABF\u0A96\u0AB0\u0ACD\u0AB5'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0AAE\u0AB9\u0ABE\u0AAA\u0AA6\u0ACD\u0AAE'
    -    },
    -    '10000000000000': {
    -      'other': '0 \u0AB6\u0A82\u0A95\u0AC1'
    -    },
    -    '100000000000000': {
    -      'other': '0 \u0A9C\u0AB2\u0AA7\u0ABF'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale gu_IN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_gu_IN =
    -    goog.i18n.CompactNumberFormatSymbols_gu;
    -
    -
    -/**
    - * Compact number formatting symbols for locale haw.
    - */
    -goog.i18n.CompactNumberFormatSymbols_haw = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale haw_US.
    - */
    -goog.i18n.CompactNumberFormatSymbols_haw_US =
    -    goog.i18n.CompactNumberFormatSymbols_haw;
    -
    -
    -/**
    - * Compact number formatting symbols for locale he.
    - */
    -goog.i18n.CompactNumberFormatSymbols_he = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '\u200F0\u00A0\u05D0\u05DC\u05E3'
    -    },
    -    '10000': {
    -      'other': '\u200F00\u00A0\u05D0\u05DC\u05E3'
    -    },
    -    '100000': {
    -      'other': '\u200F000\u00A0\u05D0\u05DC\u05E3'
    -    },
    -    '1000000': {
    -      'other': '\u200F0\u00A0\u05DE\u05D9\u05DC\u05F3'
    -    },
    -    '10000000': {
    -      'other': '\u200F00\u00A0\u05DE\u05D9\u05DC\u05F3'
    -    },
    -    '100000000': {
    -      'other': '\u200F000\u00A0\u05DE\u05D9\u05DC\u05F3'
    -    },
    -    '1000000000': {
    -      'other': '\u200F0\u00A0\u05DE\u05DC\u05E8\u05D3'
    -    },
    -    '10000000000': {
    -      'other': '\u200F00\u00A0\u05DE\u05DC\u05E8\u05D3'
    -    },
    -    '100000000000': {
    -      'other': '\u200F000\u00A0\u05DE\u05DC\u05E8\u05D3'
    -    },
    -    '1000000000000': {
    -      'other': '\u200F0\u00A0\u05D1\u05D9\u05DC\u05F3'
    -    },
    -    '10000000000000': {
    -      'other': '\u200F00\u00A0\u05D1\u05D9\u05DC\u05F3'
    -    },
    -    '100000000000000': {
    -      'other': '\u200F000\u00A0\u05D1\u05D9\u05DC\u05F3'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '\u200F0 \u05D0\u05DC\u05E3'
    -    },
    -    '10000': {
    -      'other': '\u200F00 \u05D0\u05DC\u05E3'
    -    },
    -    '100000': {
    -      'other': '\u200F000 \u05D0\u05DC\u05E3'
    -    },
    -    '1000000': {
    -      'other': '\u200F0 \u05DE\u05D9\u05DC\u05D9\u05D5\u05DF'
    -    },
    -    '10000000': {
    -      'other': '\u200F00 \u05DE\u05D9\u05DC\u05D9\u05D5\u05DF'
    -    },
    -    '100000000': {
    -      'other': '\u200F000 \u05DE\u05D9\u05DC\u05D9\u05D5\u05DF'
    -    },
    -    '1000000000': {
    -      'other': '\u200F0 \u05DE\u05D9\u05DC\u05D9\u05D0\u05E8\u05D3'
    -    },
    -    '10000000000': {
    -      'other': '\u200F00 \u05DE\u05D9\u05DC\u05D9\u05D0\u05E8\u05D3'
    -    },
    -    '100000000000': {
    -      'other': '\u200F000 \u05DE\u05D9\u05DC\u05D9\u05D0\u05E8\u05D3'
    -    },
    -    '1000000000000': {
    -      'other': '\u200F0 \u05D8\u05E8\u05D9\u05DC\u05D9\u05D5\u05DF'
    -    },
    -    '10000000000000': {
    -      'other': '\u200F00 \u05D8\u05E8\u05D9\u05DC\u05D9\u05D5\u05DF'
    -    },
    -    '100000000000000': {
    -      'other': '\u200F000 \u05D8\u05E8\u05D9\u05DC\u05D9\u05D5\u05DF'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale he_IL.
    - */
    -goog.i18n.CompactNumberFormatSymbols_he_IL =
    -    goog.i18n.CompactNumberFormatSymbols_he;
    -
    -
    -/**
    - * Compact number formatting symbols for locale hi.
    - */
    -goog.i18n.CompactNumberFormatSymbols_hi = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0939\u091C\u093C\u093E\u0930'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0939\u091C\u093C\u093E\u0930'
    -    },
    -    '100000': {
    -      'other': '0\u00A0\u0932\u093E\u0916'
    -    },
    -    '1000000': {
    -      'other': '00\u00A0\u0932\u093E\u0916'
    -    },
    -    '10000000': {
    -      'other': '0\u00A0\u0915.'
    -    },
    -    '100000000': {
    -      'other': '00\u00A0\u0915.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0905.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0905.'
    -    },
    -    '100000000000': {
    -      'other': '0\u00A0\u0916.'
    -    },
    -    '1000000000000': {
    -      'other': '00\u00A0\u0916.'
    -    },
    -    '10000000000000': {
    -      'other': '0\u00A0\u0928\u0940\u0932'
    -    },
    -    '100000000000000': {
    -      'other': '00\u00A0\u0928\u0940\u0932'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0939\u091C\u093C\u093E\u0930'
    -    },
    -    '10000': {
    -      'other': '00 \u0939\u091C\u093C\u093E\u0930'
    -    },
    -    '100000': {
    -      'other': '0 \u0932\u093E\u0916'
    -    },
    -    '1000000': {
    -      'other': '00 \u0932\u093E\u0916'
    -    },
    -    '10000000': {
    -      'other': '0 \u0915\u0930\u094B\u0921\u093C'
    -    },
    -    '100000000': {
    -      'other': '00 \u0915\u0930\u094B\u0921\u093C'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0905\u0930\u092C'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0905\u0930\u092C'
    -    },
    -    '100000000000': {
    -      'other': '0 \u0916\u0930\u092C'
    -    },
    -    '1000000000000': {
    -      'other': '00 \u0916\u0930\u092C'
    -    },
    -    '10000000000000': {
    -      'other': '000 \u0916\u0930\u092C'
    -    },
    -    '100000000000000': {
    -      'other': '0000 \u0916\u0930\u092C'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale hi_IN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_hi_IN =
    -    goog.i18n.CompactNumberFormatSymbols_hi;
    -
    -
    -/**
    - * Compact number formatting symbols for locale hr.
    - */
    -goog.i18n.CompactNumberFormatSymbols_hr = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0tis.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0tis.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0tis.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mil.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mil.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mil.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mlr.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mlr.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mlr.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bil.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bil.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bil.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 tisu\u0107a'
    -    },
    -    '10000': {
    -      'other': '00 tisu\u0107a'
    -    },
    -    '100000': {
    -      'other': '000 tisu\u0107a'
    -    },
    -    '1000000': {
    -      'other': '0 milijuna'
    -    },
    -    '10000000': {
    -      'other': '00 milijuna'
    -    },
    -    '100000000': {
    -      'other': '000 milijuna'
    -    },
    -    '1000000000': {
    -      'other': '0 milijardi'
    -    },
    -    '10000000000': {
    -      'other': '00 milijardi'
    -    },
    -    '100000000000': {
    -      'other': '000 milijardi'
    -    },
    -    '1000000000000': {
    -      'other': '0 bilijuna'
    -    },
    -    '10000000000000': {
    -      'other': '00 bilijuna'
    -    },
    -    '100000000000000': {
    -      'other': '000 bilijuna'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale hr_HR.
    - */
    -goog.i18n.CompactNumberFormatSymbols_hr_HR =
    -    goog.i18n.CompactNumberFormatSymbols_hr;
    -
    -
    -/**
    - * Compact number formatting symbols for locale hu.
    - */
    -goog.i18n.CompactNumberFormatSymbols_hu = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0E'
    -    },
    -    '10000': {
    -      'other': '00\u00A0E'
    -    },
    -    '100000': {
    -      'other': '000\u00A0E'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Mrd'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Mrd'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Mrd'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0B'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0B'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 ezer'
    -    },
    -    '10000': {
    -      'other': '00 ezer'
    -    },
    -    '100000': {
    -      'other': '000 ezer'
    -    },
    -    '1000000': {
    -      'other': '0 milli\u00F3'
    -    },
    -    '10000000': {
    -      'other': '00 milli\u00F3'
    -    },
    -    '100000000': {
    -      'other': '000 milli\u00F3'
    -    },
    -    '1000000000': {
    -      'other': '0 milli\u00E1rd'
    -    },
    -    '10000000000': {
    -      'other': '00 milli\u00E1rd'
    -    },
    -    '100000000000': {
    -      'other': '000 milli\u00E1rd'
    -    },
    -    '1000000000000': {
    -      'other': '0 billi\u00F3'
    -    },
    -    '10000000000000': {
    -      'other': '00 billi\u00F3'
    -    },
    -    '100000000000000': {
    -      'other': '000 billi\u00F3'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale hu_HU.
    - */
    -goog.i18n.CompactNumberFormatSymbols_hu_HU =
    -    goog.i18n.CompactNumberFormatSymbols_hu;
    -
    -
    -/**
    - * Compact number formatting symbols for locale hy.
    - */
    -goog.i18n.CompactNumberFormatSymbols_hy = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0570\u0566\u0580'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0570\u0566\u0580'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0570\u0566\u0580'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0574\u056C\u0576'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0574\u056C\u0576'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0574\u056C\u0576'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0574\u056C\u0580\u0564'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0574\u056C\u0580\u0564'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u0574\u056C\u0580\u0564'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u057F\u0580\u056C\u0576'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u057F\u0580\u056C\u0576'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u057F\u0580\u056C\u0576'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0570\u0561\u0566\u0561\u0580'
    -    },
    -    '10000': {
    -      'other': '00 \u0570\u0561\u0566\u0561\u0580'
    -    },
    -    '100000': {
    -      'other': '000 \u0570\u0561\u0566\u0561\u0580'
    -    },
    -    '1000000': {
    -      'other': '0 \u0574\u056B\u056C\u056B\u0578\u0576'
    -    },
    -    '10000000': {
    -      'other': '00 \u0574\u056B\u056C\u056B\u0578\u0576'
    -    },
    -    '100000000': {
    -      'other': '000 \u0574\u056B\u056C\u056B\u0578\u0576'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0574\u056B\u056C\u056B\u0561\u0580\u0564'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0574\u056B\u056C\u056B\u0561\u0580\u0564'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0574\u056B\u056C\u056B\u0561\u0580\u0564'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u057F\u0580\u056B\u056C\u056B\u0578\u0576'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u057F\u0580\u056B\u056C\u056B\u0578\u0576'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u057F\u0580\u056B\u056C\u056B\u0578\u0576'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale hy_AM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_hy_AM =
    -    goog.i18n.CompactNumberFormatSymbols_hy;
    -
    -
    -/**
    - * Compact number formatting symbols for locale id.
    - */
    -goog.i18n.CompactNumberFormatSymbols_id = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '00\u00A0rb'
    -    },
    -    '100000': {
    -      'other': '000\u00A0rb'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0jt'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0jt'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0jt'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0T'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0T'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 ribu'
    -    },
    -    '10000': {
    -      'other': '00 ribu'
    -    },
    -    '100000': {
    -      'other': '000 ribu'
    -    },
    -    '1000000': {
    -      'other': '0 juta'
    -    },
    -    '10000000': {
    -      'other': '00 juta'
    -    },
    -    '100000000': {
    -      'other': '000 juta'
    -    },
    -    '1000000000': {
    -      'other': '0 miliar'
    -    },
    -    '10000000000': {
    -      'other': '00 miliar'
    -    },
    -    '100000000000': {
    -      'other': '000 miliar'
    -    },
    -    '1000000000000': {
    -      'other': '0 triliun'
    -    },
    -    '10000000000000': {
    -      'other': '00 triliun'
    -    },
    -    '100000000000000': {
    -      'other': '000 triliun'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale id_ID.
    - */
    -goog.i18n.CompactNumberFormatSymbols_id_ID =
    -    goog.i18n.CompactNumberFormatSymbols_id;
    -
    -
    -/**
    - * Compact number formatting symbols for locale in.
    - */
    -goog.i18n.CompactNumberFormatSymbols_in = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '00\u00A0rb'
    -    },
    -    '100000': {
    -      'other': '000\u00A0rb'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0jt'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0jt'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0jt'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0T'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0T'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 ribu'
    -    },
    -    '10000': {
    -      'other': '00 ribu'
    -    },
    -    '100000': {
    -      'other': '000 ribu'
    -    },
    -    '1000000': {
    -      'other': '0 juta'
    -    },
    -    '10000000': {
    -      'other': '00 juta'
    -    },
    -    '100000000': {
    -      'other': '000 juta'
    -    },
    -    '1000000000': {
    -      'other': '0 miliar'
    -    },
    -    '10000000000': {
    -      'other': '00 miliar'
    -    },
    -    '100000000000': {
    -      'other': '000 miliar'
    -    },
    -    '1000000000000': {
    -      'other': '0 triliun'
    -    },
    -    '10000000000000': {
    -      'other': '00 triliun'
    -    },
    -    '100000000000000': {
    -      'other': '000 triliun'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale is.
    - */
    -goog.i18n.CompactNumberFormatSymbols_is = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u00FE.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u00FE.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u00FE.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0m.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0m.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0m.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0ma.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0ma.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0ma.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u00FE\u00FAsund'
    -    },
    -    '10000': {
    -      'other': '00 \u00FE\u00FAsund'
    -    },
    -    '100000': {
    -      'other': '000 \u00FE\u00FAsund'
    -    },
    -    '1000000': {
    -      'other': '0 millj\u00F3nir'
    -    },
    -    '10000000': {
    -      'other': '00 millj\u00F3nir'
    -    },
    -    '100000000': {
    -      'other': '000 millj\u00F3nir'
    -    },
    -    '1000000000': {
    -      'other': '0 milljar\u00F0ar'
    -    },
    -    '10000000000': {
    -      'other': '00 milljar\u00F0ar'
    -    },
    -    '100000000000': {
    -      'other': '000 milljar\u00F0ar'
    -    },
    -    '1000000000000': {
    -      'other': '0 billj\u00F3nir'
    -    },
    -    '10000000000000': {
    -      'other': '00 billj\u00F3nir'
    -    },
    -    '100000000000000': {
    -      'other': '000 billj\u00F3nir'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale is_IS.
    - */
    -goog.i18n.CompactNumberFormatSymbols_is_IS =
    -    goog.i18n.CompactNumberFormatSymbols_is;
    -
    -
    -/**
    - * Compact number formatting symbols for locale it.
    - */
    -goog.i18n.CompactNumberFormatSymbols_it = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '0'
    -    },
    -    '100000': {
    -      'other': '0'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0Mln'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0Mln'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0Mln'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Mld'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Mld'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Mld'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bln'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bln'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bln'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 migliaia'
    -    },
    -    '10000': {
    -      'other': '00 migliaia'
    -    },
    -    '100000': {
    -      'other': '000 migliaia'
    -    },
    -    '1000000': {
    -      'other': '0 milioni'
    -    },
    -    '10000000': {
    -      'other': '00 milioni'
    -    },
    -    '100000000': {
    -      'other': '000 milioni'
    -    },
    -    '1000000000': {
    -      'other': '0 miliardi'
    -    },
    -    '10000000000': {
    -      'other': '00 miliardi'
    -    },
    -    '100000000000': {
    -      'other': '000 miliardi'
    -    },
    -    '1000000000000': {
    -      'other': '0 migliaia di miliardi'
    -    },
    -    '10000000000000': {
    -      'other': '00 migliaia di miliardi'
    -    },
    -    '100000000000000': {
    -      'other': '000 migliaia di miliardi'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale it_IT.
    - */
    -goog.i18n.CompactNumberFormatSymbols_it_IT =
    -    goog.i18n.CompactNumberFormatSymbols_it;
    -
    -
    -/**
    - * Compact number formatting symbols for locale it_SM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_it_SM =
    -    goog.i18n.CompactNumberFormatSymbols_it;
    -
    -
    -/**
    - * Compact number formatting symbols for locale iw.
    - */
    -goog.i18n.CompactNumberFormatSymbols_iw = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '\u200F0\u00A0\u05D0\u05DC\u05E3'
    -    },
    -    '10000': {
    -      'other': '\u200F00\u00A0\u05D0\u05DC\u05E3'
    -    },
    -    '100000': {
    -      'other': '\u200F000\u00A0\u05D0\u05DC\u05E3'
    -    },
    -    '1000000': {
    -      'other': '\u200F0\u00A0\u05DE\u05D9\u05DC\u05F3'
    -    },
    -    '10000000': {
    -      'other': '\u200F00\u00A0\u05DE\u05D9\u05DC\u05F3'
    -    },
    -    '100000000': {
    -      'other': '\u200F000\u00A0\u05DE\u05D9\u05DC\u05F3'
    -    },
    -    '1000000000': {
    -      'other': '\u200F0\u00A0\u05DE\u05DC\u05E8\u05D3'
    -    },
    -    '10000000000': {
    -      'other': '\u200F00\u00A0\u05DE\u05DC\u05E8\u05D3'
    -    },
    -    '100000000000': {
    -      'other': '\u200F000\u00A0\u05DE\u05DC\u05E8\u05D3'
    -    },
    -    '1000000000000': {
    -      'other': '\u200F0\u00A0\u05D1\u05D9\u05DC\u05F3'
    -    },
    -    '10000000000000': {
    -      'other': '\u200F00\u00A0\u05D1\u05D9\u05DC\u05F3'
    -    },
    -    '100000000000000': {
    -      'other': '\u200F000\u00A0\u05D1\u05D9\u05DC\u05F3'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '\u200F0 \u05D0\u05DC\u05E3'
    -    },
    -    '10000': {
    -      'other': '\u200F00 \u05D0\u05DC\u05E3'
    -    },
    -    '100000': {
    -      'other': '\u200F000 \u05D0\u05DC\u05E3'
    -    },
    -    '1000000': {
    -      'other': '\u200F0 \u05DE\u05D9\u05DC\u05D9\u05D5\u05DF'
    -    },
    -    '10000000': {
    -      'other': '\u200F00 \u05DE\u05D9\u05DC\u05D9\u05D5\u05DF'
    -    },
    -    '100000000': {
    -      'other': '\u200F000 \u05DE\u05D9\u05DC\u05D9\u05D5\u05DF'
    -    },
    -    '1000000000': {
    -      'other': '\u200F0 \u05DE\u05D9\u05DC\u05D9\u05D0\u05E8\u05D3'
    -    },
    -    '10000000000': {
    -      'other': '\u200F00 \u05DE\u05D9\u05DC\u05D9\u05D0\u05E8\u05D3'
    -    },
    -    '100000000000': {
    -      'other': '\u200F000 \u05DE\u05D9\u05DC\u05D9\u05D0\u05E8\u05D3'
    -    },
    -    '1000000000000': {
    -      'other': '\u200F0 \u05D8\u05E8\u05D9\u05DC\u05D9\u05D5\u05DF'
    -    },
    -    '10000000000000': {
    -      'other': '\u200F00 \u05D8\u05E8\u05D9\u05DC\u05D9\u05D5\u05DF'
    -    },
    -    '100000000000000': {
    -      'other': '\u200F000 \u05D8\u05E8\u05D9\u05DC\u05D9\u05D5\u05DF'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ja.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ja = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u5343'
    -    },
    -    '10000': {
    -      'other': '0\u4E07'
    -    },
    -    '100000': {
    -      'other': '00\u4E07'
    -    },
    -    '1000000': {
    -      'other': '000\u4E07'
    -    },
    -    '10000000': {
    -      'other': '0000\u4E07'
    -    },
    -    '100000000': {
    -      'other': '0\u5104'
    -    },
    -    '1000000000': {
    -      'other': '00\u5104'
    -    },
    -    '10000000000': {
    -      'other': '000\u5104'
    -    },
    -    '100000000000': {
    -      'other': '0000\u5104'
    -    },
    -    '1000000000000': {
    -      'other': '0\u5146'
    -    },
    -    '10000000000000': {
    -      'other': '00\u5146'
    -    },
    -    '100000000000000': {
    -      'other': '000\u5146'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0\u5343'
    -    },
    -    '10000': {
    -      'other': '0\u4E07'
    -    },
    -    '100000': {
    -      'other': '00\u4E07'
    -    },
    -    '1000000': {
    -      'other': '000\u4E07'
    -    },
    -    '10000000': {
    -      'other': '0000\u4E07'
    -    },
    -    '100000000': {
    -      'other': '0\u5104'
    -    },
    -    '1000000000': {
    -      'other': '00\u5104'
    -    },
    -    '10000000000': {
    -      'other': '000\u5104'
    -    },
    -    '100000000000': {
    -      'other': '0000\u5104'
    -    },
    -    '1000000000000': {
    -      'other': '0\u5146'
    -    },
    -    '10000000000000': {
    -      'other': '00\u5146'
    -    },
    -    '100000000000000': {
    -      'other': '000\u5146'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ja_JP.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ja_JP =
    -    goog.i18n.CompactNumberFormatSymbols_ja;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ka.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ka = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u10D0\u10D7.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u10D0\u10D7.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u10D0\u10D7.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u10DB\u10DA\u10DC.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u10DB\u10DA\u10DC.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u10DB\u10DA\u10DC.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u10DB\u10DA\u10E0\u10D3.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u10DB\u10DA\u10E0\u10D3.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u10DB\u10DA\u10E0.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u10E2\u10E0\u10DA.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u10E2\u10E0\u10DA.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u10E2\u10E0\u10DA.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u10D0\u10D7\u10D0\u10E1\u10D8'
    -    },
    -    '10000': {
    -      'other': '00 \u10D0\u10D7\u10D0\u10E1\u10D8'
    -    },
    -    '100000': {
    -      'other': '000 \u10D0\u10D7\u10D0\u10E1\u10D8'
    -    },
    -    '1000000': {
    -      'other': '0 \u10DB\u10D8\u10DA\u10D8\u10DD\u10DC\u10D8'
    -    },
    -    '10000000': {
    -      'other': '00 \u10DB\u10D8\u10DA\u10D8\u10DD\u10DC\u10D8'
    -    },
    -    '100000000': {
    -      'other': '000 \u10DB\u10D8\u10DA\u10D8\u10DD\u10DC\u10D8'
    -    },
    -    '1000000000': {
    -      'other': '0 \u10DB\u10D8\u10DA\u10D8\u10D0\u10E0\u10D3\u10D8'
    -    },
    -    '10000000000': {
    -      'other': '00 \u10DB\u10D8\u10DA\u10D8\u10D0\u10E0\u10D3\u10D8'
    -    },
    -    '100000000000': {
    -      'other': '000 \u10DB\u10D8\u10DA\u10D8\u10D0\u10E0\u10D3\u10D8'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u10E2\u10E0\u10D8\u10DA\u10D8\u10DD\u10DC\u10D8'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u10E2\u10E0\u10D8\u10DA\u10D8\u10DD\u10DC\u10D8'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u10E2\u10E0\u10D8\u10DA\u10D8\u10DD\u10DC\u10D8'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ka_GE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ka_GE =
    -    goog.i18n.CompactNumberFormatSymbols_ka;
    -
    -
    -/**
    - * Compact number formatting symbols for locale kk.
    - */
    -goog.i18n.CompactNumberFormatSymbols_kk = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u043C\u044B\u04A3'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u043C\u044B\u04A3'
    -    },
    -    '100000': {
    -      'other': '000\u041C'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u043C\u043B\u043D'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u043C\u043B\u043D'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u043C\u043B\u043D'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '100000000000': {
    -      'other': '000\u0411'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u0442\u0440\u043B\u043D'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u0442\u0440\u043B\u043D'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale kk_Cyrl_KZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_kk_Cyrl_KZ =
    -    goog.i18n.CompactNumberFormatSymbols_kk;
    -
    -
    -/**
    - * Compact number formatting symbols for locale km.
    - */
    -goog.i18n.CompactNumberFormatSymbols_km = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u1796\u17B6\u1793\u17CB'
    -    },
    -    '10000': {
    -      'other': '0\u200B\u1798\u17BA\u17BB\u1793'
    -    },
    -    '100000': {
    -      'other': '0\u179F\u17C2\u1793'
    -    },
    -    '1000000': {
    -      'other': '0\u179B\u17B6\u1793'
    -    },
    -    '10000000': {
    -      'other': '0\u200B\u178A\u1794\u17CB\u200B\u179B\u17B6\u1793'
    -    },
    -    '100000000': {
    -      'other': '0\u200B\u179A\u1799\u179B\u17B6\u1793'
    -    },
    -    '1000000000': {
    -      'other': '0\u200B\u1780\u17C4\u178A\u17B7'
    -    },
    -    '10000000000': {
    -      'other': '0\u200B\u178A\u1794\u17CB\u200B\u1780\u17C4\u178A\u17B7'
    -    },
    -    '100000000000': {
    -      'other': '0\u200B\u179A\u1799\u200B\u1780\u17C4\u178A\u17B7'
    -    },
    -    '1000000000000': {
    -      'other': '0\u200B\u1796\u17B6\u1793\u17CB\u200B\u1780\u17C4\u178A\u17B7'
    -    },
    -    '10000000000000': {
    -      'other': '0\u200B\u1798\u17BA\u17BB\u1793\u200B\u1780\u17C4\u178A\u17B7'
    -    },
    -    '100000000000000': {
    -      'other': '0\u200B\u179F\u17C2\u1793\u200B\u1780\u17C4\u178A\u17B7'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0\u1796\u17B6\u1793\u17CB'
    -    },
    -    '10000': {
    -      'other': '0\u200B\u1798\u17BA\u17BB\u1793'
    -    },
    -    '100000': {
    -      'other': '0\u179F\u17C2\u1793'
    -    },
    -    '1000000': {
    -      'other': '0\u179B\u17B6\u1793'
    -    },
    -    '10000000': {
    -      'other': '0\u200B\u178A\u1794\u17CB\u200B\u179B\u17B6\u1793'
    -    },
    -    '100000000': {
    -      'other': '0\u200B\u179A\u1799\u179B\u17B6\u1793'
    -    },
    -    '1000000000': {
    -      'other': '0\u200B\u1780\u17C4\u178A\u17B7'
    -    },
    -    '10000000000': {
    -      'other': '0\u200B\u178A\u1794\u17CB\u200B\u1780\u17C4\u178A\u17B7'
    -    },
    -    '100000000000': {
    -      'other': '0\u200B\u179A\u1799\u200B\u1780\u17C4\u178A\u17B7'
    -    },
    -    '1000000000000': {
    -      'other': '0\u200B\u1796\u17B6\u1793\u17CB\u200B\u1780\u17C4\u178A\u17B7'
    -    },
    -    '10000000000000': {
    -      'other': '0\u200B\u1798\u17BA\u17BB\u1793\u200B\u1780\u17C4\u178A\u17B7'
    -    },
    -    '100000000000000': {
    -      'other': '0\u200B\u179F\u17C2\u1793\u200B\u1780\u17C4\u178A\u17B7'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale km_KH.
    - */
    -goog.i18n.CompactNumberFormatSymbols_km_KH =
    -    goog.i18n.CompactNumberFormatSymbols_km;
    -
    -
    -/**
    - * Compact number formatting symbols for locale kn.
    - */
    -goog.i18n.CompactNumberFormatSymbols_kn = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u0CB8\u0CBE'
    -    },
    -    '10000': {
    -      'other': '00\u0CB8\u0CBE'
    -    },
    -    '100000': {
    -      'other': '000\u0CB8\u0CBE'
    -    },
    -    '1000000': {
    -      'other': '0\u0CAE\u0CBF'
    -    },
    -    '10000000': {
    -      'other': '00\u0CAE\u0CBF'
    -    },
    -    '100000000': {
    -      'other': '000\u0CAE\u0CBF'
    -    },
    -    '1000000000': {
    -      'other': '0\u0CAC\u0CBF'
    -    },
    -    '10000000000': {
    -      'other': '00\u0CAC\u0CBF'
    -    },
    -    '100000000000': {
    -      'other': '000\u0CAC\u0CBF'
    -    },
    -    '1000000000000': {
    -      'other': '0\u0C9F\u0CCD\u0CB0\u0CBF'
    -    },
    -    '10000000000000': {
    -      'other': '00\u0C9F\u0CCD\u0CB0\u0CBF'
    -    },
    -    '100000000000000': {
    -      'other': '000\u0C9F\u0CCD\u0CB0\u0CBF'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0CB8\u0CBE\u0CB5\u0CBF\u0CB0'
    -    },
    -    '10000': {
    -      'other': '00 \u0CB8\u0CBE\u0CB5\u0CBF\u0CB0'
    -    },
    -    '100000': {
    -      'other': '000 \u0CB8\u0CBE\u0CB5\u0CBF\u0CB0'
    -    },
    -    '1000000': {
    -      'other': '0 \u0CAE\u0CBF\u0CB2\u0CBF\u0CAF\u0CA8\u0CCD'
    -    },
    -    '10000000': {
    -      'other': '00 \u0CAE\u0CBF\u0CB2\u0CBF\u0CAF\u0CA8\u0CCD'
    -    },
    -    '100000000': {
    -      'other': '000 \u0CAE\u0CBF\u0CB2\u0CBF\u0CAF\u0CA8\u0CCD'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0CAC\u0CBF\u0CB2\u0CBF\u0CAF\u0CA8\u0CCD'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0CAC\u0CBF\u0CB2\u0CBF\u0CAF\u0CA8\u0CCD'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0CAC\u0CBF\u0CB2\u0CBF\u0CAF\u0CA8\u0CCD'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0C9F\u0CCD\u0CB0\u0CBF\u0CB2\u0CBF\u0CAF\u0CA8\u0CCD\u200C'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0C9F\u0CCD\u0CB0\u0CBF\u0CB2\u0CBF\u0CAF\u0CA8\u0CCD\u200C'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0C9F\u0CCD\u0CB0\u0CBF\u0CB2\u0CBF\u0CAF\u0CA8\u0CCD\u200C'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale kn_IN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_kn_IN =
    -    goog.i18n.CompactNumberFormatSymbols_kn;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ko.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ko = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0000'
    -    },
    -    '10000': {
    -      'other': '0\uB9CC'
    -    },
    -    '100000': {
    -      'other': '00\uB9CC'
    -    },
    -    '1000000': {
    -      'other': '000\uB9CC'
    -    },
    -    '10000000': {
    -      'other': '0000\uB9CC'
    -    },
    -    '100000000': {
    -      'other': '0\uC5B5'
    -    },
    -    '1000000000': {
    -      'other': '00\uC5B5'
    -    },
    -    '10000000000': {
    -      'other': '000\uC5B5'
    -    },
    -    '100000000000': {
    -      'other': '0000\uC5B5'
    -    },
    -    '1000000000000': {
    -      'other': '0\uC870'
    -    },
    -    '10000000000000': {
    -      'other': '00\uC870'
    -    },
    -    '100000000000000': {
    -      'other': '000\uC870'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0000'
    -    },
    -    '10000': {
    -      'other': '0\uB9CC'
    -    },
    -    '100000': {
    -      'other': '00\uB9CC'
    -    },
    -    '1000000': {
    -      'other': '000\uB9CC'
    -    },
    -    '10000000': {
    -      'other': '0000\uB9CC'
    -    },
    -    '100000000': {
    -      'other': '0\uC5B5'
    -    },
    -    '1000000000': {
    -      'other': '00\uC5B5'
    -    },
    -    '10000000000': {
    -      'other': '000\uC5B5'
    -    },
    -    '100000000000': {
    -      'other': '0000\uC5B5'
    -    },
    -    '1000000000000': {
    -      'other': '0\uC870'
    -    },
    -    '10000000000000': {
    -      'other': '00\uC870'
    -    },
    -    '100000000000000': {
    -      'other': '000\uC870'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ko_KR.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ko_KR =
    -    goog.i18n.CompactNumberFormatSymbols_ko;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ky.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ky = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u043C\u0438\u04CA'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u043C\u0438\u04CA'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u043C\u0438\u04CA'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u043C\u043B\u043D'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u043C\u043B\u043D'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u043C\u043B\u043D'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u043C\u043B\u0434'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u043C\u043B\u0434'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u043C\u043B\u0434'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u0442\u0440\u043D'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u0442\u0440\u043D'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u0442\u0440\u043D'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u043C\u0438\u04CA'
    -    },
    -    '10000': {
    -      'other': '00 \u043C\u0438\u04CA'
    -    },
    -    '100000': {
    -      'other': '000 \u043C\u0438\u04CA'
    -    },
    -    '1000000': {
    -      'other': '0 \u043C\u0438\u043B\u043B\u0438\u043E\u043D'
    -    },
    -    '10000000': {
    -      'other': '00 \u043C\u0438\u043B\u043B\u0438\u043E\u043D'
    -    },
    -    '100000000': {
    -      'other': '000 \u043C\u0438\u043B\u043B\u0438\u043E\u043D'
    -    },
    -    '1000000000': {
    -      'other': '0 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434'
    -    },
    -    '10000000000': {
    -      'other': '00 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434'
    -    },
    -    '100000000000': {
    -      'other': '000 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0442\u0440\u0438\u043B\u043B\u0438\u043E\u043D'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0442\u0440\u0438\u043B\u043B\u0438\u043E\u043D'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0442\u0440\u0438\u043B\u043B\u0438\u043E\u043D'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ky_Cyrl_KG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ky_Cyrl_KG =
    -    goog.i18n.CompactNumberFormatSymbols_ky;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ln.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ln = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ln_CD.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ln_CD =
    -    goog.i18n.CompactNumberFormatSymbols_ln;
    -
    -
    -/**
    - * Compact number formatting symbols for locale lo.
    - */
    -goog.i18n.CompactNumberFormatSymbols_lo = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u0E9E\u0EB1\u0E99'
    -    },
    -    '10000': {
    -      'other': '00\u0E9E\u0EB1\u0E99'
    -    },
    -    '100000': {
    -      'other': '000\u0E9E\u0EB1\u0E99'
    -    },
    -    '1000000': {
    -      'other': '0\u0EA5\u0EC9\u0EB2\u0E99'
    -    },
    -    '10000000': {
    -      'other': '00\u0EA5\u0EC9\u0EB2\u0E99'
    -    },
    -    '100000000': {
    -      'other': '000\u0EA5\u0EC9\u0EB2\u0E99'
    -    },
    -    '1000000000': {
    -      'other': '0\u0E95\u0EB7\u0EC9'
    -    },
    -    '10000000000': {
    -      'other': '00\u0E95\u0EB7\u0EC9'
    -    },
    -    '100000000000': {
    -      'other': '000\u0E95\u0EB7\u0EC9'
    -    },
    -    '1000000000000': {
    -      'other': '0000\u0E95\u0EB7\u0EC9'
    -    },
    -    '10000000000000': {
    -      'other': '00\u0E9E\u0EB1\u0E99\u0E95\u0EB7\u0EC9'
    -    },
    -    '100000000000000': {
    -      'other': '000\u0E9E\u0EB1\u0E99\u0E95\u0EB7\u0EC9'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0\u0E9E\u0EB1\u0E99'
    -    },
    -    '10000': {
    -      'other': '00\u0E9E\u0EB1\u0E99'
    -    },
    -    '100000': {
    -      'other': '000\u0E9E\u0EB1\u0E99'
    -    },
    -    '1000000': {
    -      'other': '0\u0EA5\u0EC9\u0EB2\u0E99'
    -    },
    -    '10000000': {
    -      'other': '00\u0EA5\u0EC9\u0EB2\u0E99'
    -    },
    -    '100000000': {
    -      'other': '000\u0EA5\u0EC9\u0EB2\u0E99'
    -    },
    -    '1000000000': {
    -      'other': '0\u0E9E\u0EB1\u0E99\u0EA5\u0EC9\u0EB2\u0E99'
    -    },
    -    '10000000000': {
    -      'other': '00\u0E9E\u0EB1\u0E99\u0EA5\u0EC9\u0EB2\u0E99'
    -    },
    -    '100000000000': {
    -      'other': '000\u0E9E\u0EB1\u0E99\u0EA5\u0EC9\u0EB2\u0E99'
    -    },
    -    '1000000000000': {
    -      'other': '0000\u0E9E\u0EB1\u0E99\u0EA5\u0EC9\u0EB2\u0E99'
    -    },
    -    '10000000000000': {
    -      'other': '00\u0EA5\u0EC9\u0EB2\u0E99\u0EA5\u0EC9\u0EB2\u0E99'
    -    },
    -    '100000000000000': {
    -      'other': '000\u0EA5\u0EC9\u0EB2\u0E99\u0EA5\u0EC9\u0EB2\u0E99'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale lo_LA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_lo_LA =
    -    goog.i18n.CompactNumberFormatSymbols_lo;
    -
    -
    -/**
    - * Compact number formatting symbols for locale lt.
    - */
    -goog.i18n.CompactNumberFormatSymbols_lt = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0t\u016Bkst.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0t\u016Bkst.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0t\u016Bkst.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mln.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mln.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mln.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mlrd.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mlrd.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mlrd.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0trln.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0trln.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0trln.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 t\u016Bkstan\u010Di\u0173'
    -    },
    -    '10000': {
    -      'other': '00 t\u016Bkstan\u010Di\u0173'
    -    },
    -    '100000': {
    -      'other': '000 t\u016Bkstan\u010Di\u0173'
    -    },
    -    '1000000': {
    -      'other': '0 milijon\u0173'
    -    },
    -    '10000000': {
    -      'other': '00 milijon\u0173'
    -    },
    -    '100000000': {
    -      'other': '000 milijon\u0173'
    -    },
    -    '1000000000': {
    -      'other': '0 milijard\u0173'
    -    },
    -    '10000000000': {
    -      'other': '00 milijard\u0173'
    -    },
    -    '100000000000': {
    -      'other': '000 milijard\u0173'
    -    },
    -    '1000000000000': {
    -      'other': '0 trilijon\u0173'
    -    },
    -    '10000000000000': {
    -      'other': '00 trilijon\u0173'
    -    },
    -    '100000000000000': {
    -      'other': '000 trilijon\u0173'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale lt_LT.
    - */
    -goog.i18n.CompactNumberFormatSymbols_lt_LT =
    -    goog.i18n.CompactNumberFormatSymbols_lt;
    -
    -
    -/**
    - * Compact number formatting symbols for locale lv.
    - */
    -goog.i18n.CompactNumberFormatSymbols_lv = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0t\u016Bkst.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0t\u016Bkst.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0t\u016Bkst.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0milj.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0milj.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0milj.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mljrd.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mljrd.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mljrd.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0trilj.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0trilj.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0trilj.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 t\u016Bksto\u0161i'
    -    },
    -    '10000': {
    -      'other': '00 t\u016Bksto\u0161i'
    -    },
    -    '100000': {
    -      'other': '000 t\u016Bksto\u0161i'
    -    },
    -    '1000000': {
    -      'other': '0 miljoni'
    -    },
    -    '10000000': {
    -      'other': '00 miljoni'
    -    },
    -    '100000000': {
    -      'other': '000 miljoni'
    -    },
    -    '1000000000': {
    -      'other': '0 miljardi'
    -    },
    -    '10000000000': {
    -      'other': '00 miljardi'
    -    },
    -    '100000000000': {
    -      'other': '000 miljardi'
    -    },
    -    '1000000000000': {
    -      'other': '0 triljoni'
    -    },
    -    '10000000000000': {
    -      'other': '00 triljoni'
    -    },
    -    '100000000000000': {
    -      'other': '000 triljoni'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale lv_LV.
    - */
    -goog.i18n.CompactNumberFormatSymbols_lv_LV =
    -    goog.i18n.CompactNumberFormatSymbols_lv;
    -
    -
    -/**
    - * Compact number formatting symbols for locale mk.
    - */
    -goog.i18n.CompactNumberFormatSymbols_mk = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0438\u043B\u0458.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0438\u043B\u0458.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0438\u043B\u0458.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u043C\u0438\u043B.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u043C\u0438\u043B.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u041C'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u043C\u0438\u043B\u0458.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u043C\u0438\u043B\u0458.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u043C\u0438\u043B\u0458.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u0442\u0440\u0438\u043B.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u0442\u0440\u0438\u043B.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u0442\u0440\u0438\u043B.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0438\u043B\u0458\u0430\u0434\u0438'
    -    },
    -    '10000': {
    -      'other': '00 \u0438\u043B\u0458\u0430\u0434\u0438'
    -    },
    -    '100000': {
    -      'other': '000 \u0438\u043B\u0458\u0430\u0434\u0438'
    -    },
    -    '1000000': {
    -      'other': '0 \u043C\u0438\u043B\u0438\u043E\u043D\u0438'
    -    },
    -    '10000000': {
    -      'other': '00 \u043C\u0438\u043B\u0438\u043E\u043D\u0438'
    -    },
    -    '100000000': {
    -      'other': '000 \u043C\u0438\u043B\u0438\u043E\u043D\u0438'
    -    },
    -    '1000000000': {
    -      'other': '0 \u043C\u0438\u043B\u0438\u0458\u0430\u0440\u0434\u0438'
    -    },
    -    '10000000000': {
    -      'other': '00 \u043C\u0438\u043B\u0438\u0458\u0430\u0440\u0434\u0438'
    -    },
    -    '100000000000': {
    -      'other': '000 \u043C\u0438\u043B\u0438\u0458\u0430\u0440\u0434\u0438'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0442\u0440\u0438\u043B\u0438\u043E\u043D\u0438'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0442\u0440\u0438\u043B\u0438\u043E\u043D\u0438'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0442\u0440\u0438\u043B\u0438\u043E\u043D\u0438'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale mk_MK.
    - */
    -goog.i18n.CompactNumberFormatSymbols_mk_MK =
    -    goog.i18n.CompactNumberFormatSymbols_mk;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ml.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ml = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0D06\u0D2F\u0D3F\u0D30\u0D02'
    -    },
    -    '10000': {
    -      'other': '00 \u0D06\u0D2F\u0D3F\u0D30\u0D02'
    -    },
    -    '100000': {
    -      'other': '000 \u0D06\u0D2F\u0D3F\u0D30\u0D02'
    -    },
    -    '1000000': {
    -      'other': '0 \u0D26\u0D36\u0D32\u0D15\u0D4D\u0D37\u0D02'
    -    },
    -    '10000000': {
    -      'other': '00 \u0D26\u0D36\u0D32\u0D15\u0D4D\u0D37\u0D02'
    -    },
    -    '100000000': {
    -      'other': '000 \u0D26\u0D36\u0D32\u0D15\u0D4D\u0D37\u0D02'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0D32\u0D15\u0D4D\u0D37\u0D02 \u0D15\u0D4B\u0D1F\u0D3F'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0D32\u0D15\u0D4D\u0D37\u0D02 \u0D15\u0D4B\u0D1F\u0D3F'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0D32\u0D15\u0D4D\u0D37\u0D02 \u0D15\u0D4B\u0D1F\u0D3F'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0D1F\u0D4D\u0D30\u0D3F\u0D32\u0D4D\u0D2F\u0D7A'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0D1F\u0D4D\u0D30\u0D3F\u0D32\u0D4D\u0D2F\u0D7A'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0D1F\u0D4D\u0D30\u0D3F\u0D32\u0D4D\u0D2F\u0D7A'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ml_IN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ml_IN =
    -    goog.i18n.CompactNumberFormatSymbols_ml;
    -
    -
    -/**
    - * Compact number formatting symbols for locale mn.
    - */
    -goog.i18n.CompactNumberFormatSymbols_mn = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u041C'
    -    },
    -    '10000': {
    -      'other': '00\u041C'
    -    },
    -    '100000': {
    -      'other': '000\u041C'
    -    },
    -    '1000000': {
    -      'other': '0\u0421'
    -    },
    -    '10000000': {
    -      'other': '00\u0421'
    -    },
    -    '100000000': {
    -      'other': '000\u0421'
    -    },
    -    '1000000000': {
    -      'other': '0\u0422'
    -    },
    -    '10000000000': {
    -      'other': '00\u0422'
    -    },
    -    '100000000000': {
    -      'other': '000\u0422'
    -    },
    -    '1000000000000': {
    -      'other': '0\u0418\u041D'
    -    },
    -    '10000000000000': {
    -      'other': '00\u0418\u041D'
    -    },
    -    '100000000000000': {
    -      'other': '000\u0418\u041D'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u043C\u044F\u043D\u0433\u0430'
    -    },
    -    '10000': {
    -      'other': '00 \u043C\u044F\u043D\u0433\u0430'
    -    },
    -    '100000': {
    -      'other': '000 \u043C\u044F\u043D\u0433\u0430'
    -    },
    -    '1000000': {
    -      'other': '0 \u0441\u0430\u044F'
    -    },
    -    '10000000': {
    -      'other': '00 \u0441\u0430\u044F'
    -    },
    -    '100000000': {
    -      'other': '000 \u0441\u0430\u044F'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0442\u044D\u0440\u0431\u0443\u043C'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0442\u044D\u0440\u0431\u0443\u043C'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0442\u044D\u0440\u0431\u0443\u043C'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0438\u0445 \u043D\u0430\u044F\u0434'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0438\u0445 \u043D\u0430\u044F\u0434'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0438\u0445 \u043D\u0430\u044F\u0434'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale mn_Cyrl_MN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_mn_Cyrl_MN =
    -    goog.i18n.CompactNumberFormatSymbols_mn;
    -
    -
    -/**
    - * Compact number formatting symbols for locale mr.
    - */
    -goog.i18n.CompactNumberFormatSymbols_mr = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0939'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0939'
    -    },
    -    '100000': {
    -      'other': '0\u00A0\u0932\u093E\u0916'
    -    },
    -    '1000000': {
    -      'other': '00\u00A0\u0932\u093E\u0916'
    -    },
    -    '10000000': {
    -      'other': '0\u00A0\u0915\u094B\u091F\u0940'
    -    },
    -    '100000000': {
    -      'other': '00\u00A0\u0915\u094B\u091F\u0940'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0905\u092C\u094D\u091C'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0905\u092C\u094D\u091C'
    -    },
    -    '100000000000': {
    -      'other': '0\u00A0\u0916\u0930\u094D\u0935'
    -    },
    -    '1000000000000': {
    -      'other': '00\u00A0\u0916\u0930\u094D\u0935'
    -    },
    -    '10000000000000': {
    -      'other': '0\u00A0\u092A\u0926\u094D\u092E'
    -    },
    -    '100000000000000': {
    -      'other': '00\u00A0\u092A\u0926\u094D\u092E'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0939\u091C\u093E\u0930'
    -    },
    -    '10000': {
    -      'other': '00 \u0939\u091C\u093E\u0930'
    -    },
    -    '100000': {
    -      'other': '000 \u0939\u091C\u093E\u0930'
    -    },
    -    '1000000': {
    -      'other': '0 \u0926\u0936\u0932\u0915\u094D\u0937'
    -    },
    -    '10000000': {
    -      'other': '00 \u0926\u0936\u0932\u0915\u094D\u0937'
    -    },
    -    '100000000': {
    -      'other': '000 \u0926\u0936\u0932\u0915\u094D\u0937'
    -    },
    -    '1000000000': {
    -      'other': '0 \u092E\u0939\u093E\u092A\u0926\u094D\u092E'
    -    },
    -    '10000000000': {
    -      'other': '00 \u092E\u0939\u093E\u092A\u0926\u094D\u092E'
    -    },
    -    '100000000000': {
    -      'other': '000 \u092E\u0939\u093E\u092A\u0926\u094D\u092E'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0916\u0930\u092C'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0916\u0930\u092C'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0916\u0930\u092C'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale mr_IN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_mr_IN =
    -    goog.i18n.CompactNumberFormatSymbols_mr;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ms.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ms = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0J'
    -    },
    -    '10000000': {
    -      'other': '00J'
    -    },
    -    '100000000': {
    -      'other': '000J'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 ribu'
    -    },
    -    '10000': {
    -      'other': '00 ribu'
    -    },
    -    '100000': {
    -      'other': '000 ribu'
    -    },
    -    '1000000': {
    -      'other': '0 juta'
    -    },
    -    '10000000': {
    -      'other': '00 juta'
    -    },
    -    '100000000': {
    -      'other': '000 juta'
    -    },
    -    '1000000000': {
    -      'other': '0 bilion'
    -    },
    -    '10000000000': {
    -      'other': '00 bilion'
    -    },
    -    '100000000000': {
    -      'other': '000 bilion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trilion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trilion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trilion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ms_Latn_MY.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ms_Latn_MY =
    -    goog.i18n.CompactNumberFormatSymbols_ms;
    -
    -
    -/**
    - * Compact number formatting symbols for locale mt.
    - */
    -goog.i18n.CompactNumberFormatSymbols_mt = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale mt_MT.
    - */
    -goog.i18n.CompactNumberFormatSymbols_mt_MT =
    -    goog.i18n.CompactNumberFormatSymbols_mt;
    -
    -
    -/**
    - * Compact number formatting symbols for locale my.
    - */
    -goog.i18n.CompactNumberFormatSymbols_my = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u1011\u1031\u102C\u1004\u103A'
    -    },
    -    '10000': {
    -      'other': '0\u101E\u1031\u102C\u1004\u103A\u1038'
    -    },
    -    '100000': {
    -      'other': '0\u101E\u102D\u1014\u103A\u1038'
    -    },
    -    '1000000': {
    -      'other': '0\u101E\u1014\u103A\u1038'
    -    },
    -    '10000000': {
    -      'other': '0\u1000\u102F\u100B\u1031'
    -    },
    -    '100000000': {
    -      'other': '00\u1000\u102F\u100B\u1031'
    -    },
    -    '1000000000': {
    -      'other': '\u1000\u102F\u100B\u1031000'
    -    },
    -    '10000000000': {
    -      'other': '\u1000\u102F\u100B\u10310000'
    -    },
    -    '100000000000': {
    -      'other': '0000\u1000\u102F\u100B\u1031'
    -    },
    -    '1000000000000': {
    -      'other': '\u1000\u102F\u100B\u10310\u101E\u102D\u1014\u103A\u1038'
    -    },
    -    '10000000000000': {
    -      'other': '\u1000\u102F\u100B\u10310\u101E\u1014\u103A\u1038'
    -    },
    -    '100000000000000': {
    -      'other': '0\u1000\u1031\u102C\u100B\u102D'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0\u1011\u1031\u102C\u1004\u103A'
    -    },
    -    '10000': {
    -      'other': '0\u101E\u1031\u102C\u1004\u103A\u1038'
    -    },
    -    '100000': {
    -      'other': '0\u101E\u102D\u1014\u103A\u1038'
    -    },
    -    '1000000': {
    -      'other': '0\u101E\u1014\u103A\u1038'
    -    },
    -    '10000000': {
    -      'other': '0\u1000\u102F\u100B\u1031'
    -    },
    -    '100000000': {
    -      'other': '00\u1000\u102F\u100B\u1031'
    -    },
    -    '1000000000': {
    -      'other': '000\u1000\u102F\u100B\u1031'
    -    },
    -    '10000000000': {
    -      'other': '0000\u1000\u102F\u100B\u1031'
    -    },
    -    '100000000000': {
    -      'other': '00000\u1000\u102F\u100B\u1031'
    -    },
    -    '1000000000000': {
    -      'other': '000000\u1000\u102F\u100B\u1031'
    -    },
    -    '10000000000000': {
    -      'other': '0000000\u1000\u102F\u100B\u1031'
    -    },
    -    '100000000000000': {
    -      'other': '0\u1000\u1031\u102C\u100B\u102D'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale my_MM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_my_MM =
    -    goog.i18n.CompactNumberFormatSymbols_my;
    -
    -
    -/**
    - * Compact number formatting symbols for locale nb.
    - */
    -goog.i18n.CompactNumberFormatSymbols_nb = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0K'
    -    },
    -    '10000': {
    -      'other': '00\u00A0K'
    -    },
    -    '100000': {
    -      'other': '000\u00A0K'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mill'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mill'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mill'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mrd'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mrd'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mrd'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bill'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bill'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bill'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 tusen'
    -    },
    -    '10000': {
    -      'other': '00 tusen'
    -    },
    -    '100000': {
    -      'other': '000 tusen'
    -    },
    -    '1000000': {
    -      'other': '0 millioner'
    -    },
    -    '10000000': {
    -      'other': '00 millioner'
    -    },
    -    '100000000': {
    -      'other': '000 millioner'
    -    },
    -    '1000000000': {
    -      'other': '0 milliarder'
    -    },
    -    '10000000000': {
    -      'other': '00 milliarder'
    -    },
    -    '100000000000': {
    -      'other': '000 milliarder'
    -    },
    -    '1000000000000': {
    -      'other': '0 billioner'
    -    },
    -    '10000000000000': {
    -      'other': '00 billioner'
    -    },
    -    '100000000000000': {
    -      'other': '000 billioner'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale nb_NO.
    - */
    -goog.i18n.CompactNumberFormatSymbols_nb_NO =
    -    goog.i18n.CompactNumberFormatSymbols_nb;
    -
    -
    -/**
    - * Compact number formatting symbols for locale nb_SJ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_nb_SJ =
    -    goog.i18n.CompactNumberFormatSymbols_nb;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ne.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ne = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0939\u091C\u093E\u0930'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0939\u091C\u093E\u0930'
    -    },
    -    '100000': {
    -      'other': '0\u00A0\u0932\u093E\u0916'
    -    },
    -    '1000000': {
    -      'other': '00\u00A0\u0932\u093E\u0916'
    -    },
    -    '10000000': {
    -      'other': '0\u00A0\u0915\u0930\u094B\u0921'
    -    },
    -    '100000000': {
    -      'other': '00\u00A0\u0915\u0930\u094B\u0921'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0905\u0930\u092C'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0905\u0930\u092C'
    -    },
    -    '100000000000': {
    -      'other': '0\u00A0\u0916\u0930\u092C'
    -    },
    -    '1000000000000': {
    -      'other': '00\u00A0\u0916\u0930\u092C'
    -    },
    -    '10000000000000': {
    -      'other': '0\u00A0\u0936\u0902\u0916'
    -    },
    -    '100000000000000': {
    -      'other': '00\u00A0\u0936\u0902\u0916'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0939\u091C\u093E\u0930'
    -    },
    -    '10000': {
    -      'other': '00 \u0939\u091C\u093E\u0930'
    -    },
    -    '100000': {
    -      'other': '0 \u0932\u093E\u0916'
    -    },
    -    '1000000': {
    -      'other': '0 \u0915\u0930\u094B\u0921'
    -    },
    -    '10000000': {
    -      'other': '00 \u0915\u0930\u094B\u0921'
    -    },
    -    '100000000': {
    -      'other': '000 \u0915\u0930\u094B\u0921'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0905\u0930\u094D\u092C'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0905\u0930\u094D\u092C'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0905\u0930\u092C'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0916\u0930\u094D\u092C'
    -    },
    -    '10000000000000': {
    -      'other': '0 \u0936\u0902\u0916'
    -    },
    -    '100000000000000': {
    -      'other': '00 \u0936\u0902\u0916'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ne_NP.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ne_NP =
    -    goog.i18n.CompactNumberFormatSymbols_ne;
    -
    -
    -/**
    - * Compact number formatting symbols for locale nl.
    - */
    -goog.i18n.CompactNumberFormatSymbols_nl = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mln.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mln.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mln.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mld.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mld.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mld.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bln.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bln.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bln.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 duizend'
    -    },
    -    '10000': {
    -      'other': '00 duizend'
    -    },
    -    '100000': {
    -      'other': '000 duizend'
    -    },
    -    '1000000': {
    -      'other': '0 miljoen'
    -    },
    -    '10000000': {
    -      'other': '00 miljoen'
    -    },
    -    '100000000': {
    -      'other': '000 miljoen'
    -    },
    -    '1000000000': {
    -      'other': '0 miljard'
    -    },
    -    '10000000000': {
    -      'other': '00 miljard'
    -    },
    -    '100000000000': {
    -      'other': '000 miljard'
    -    },
    -    '1000000000000': {
    -      'other': '0 biljoen'
    -    },
    -    '10000000000000': {
    -      'other': '00 biljoen'
    -    },
    -    '100000000000000': {
    -      'other': '000 biljoen'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale nl_NL.
    - */
    -goog.i18n.CompactNumberFormatSymbols_nl_NL =
    -    goog.i18n.CompactNumberFormatSymbols_nl;
    -
    -
    -/**
    - * Compact number formatting symbols for locale no.
    - */
    -goog.i18n.CompactNumberFormatSymbols_no = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0K'
    -    },
    -    '10000': {
    -      'other': '00\u00A0K'
    -    },
    -    '100000': {
    -      'other': '000\u00A0K'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mill'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mill'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mill'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mrd'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mrd'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mrd'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bill'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bill'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bill'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 tusen'
    -    },
    -    '10000': {
    -      'other': '00 tusen'
    -    },
    -    '100000': {
    -      'other': '000 tusen'
    -    },
    -    '1000000': {
    -      'other': '0 millioner'
    -    },
    -    '10000000': {
    -      'other': '00 millioner'
    -    },
    -    '100000000': {
    -      'other': '000 millioner'
    -    },
    -    '1000000000': {
    -      'other': '0 milliarder'
    -    },
    -    '10000000000': {
    -      'other': '00 milliarder'
    -    },
    -    '100000000000': {
    -      'other': '000 milliarder'
    -    },
    -    '1000000000000': {
    -      'other': '0 billioner'
    -    },
    -    '10000000000000': {
    -      'other': '00 billioner'
    -    },
    -    '100000000000000': {
    -      'other': '000 billioner'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale no_NO.
    - */
    -goog.i18n.CompactNumberFormatSymbols_no_NO =
    -    goog.i18n.CompactNumberFormatSymbols_no;
    -
    -
    -/**
    - * Compact number formatting symbols for locale or.
    - */
    -goog.i18n.CompactNumberFormatSymbols_or = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale or_IN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_or_IN =
    -    goog.i18n.CompactNumberFormatSymbols_or;
    -
    -
    -/**
    - * Compact number formatting symbols for locale pa.
    - */
    -goog.i18n.CompactNumberFormatSymbols_pa = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0A39\u0A1C\u0A3C\u0A3E\u0A30'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0A39\u0A1C\u0A3C\u0A3E\u0A30'
    -    },
    -    '100000': {
    -      'other': '0\u00A0\u0A32\u0A71\u0A16'
    -    },
    -    '1000000': {
    -      'other': '00\u00A0\u0A32\u0A71\u0A16'
    -    },
    -    '10000000': {
    -      'other': '0\u00A0\u0A15\u0A30\u0A4B\u0A5C'
    -    },
    -    '100000000': {
    -      'other': '00\u00A0\u0A15\u0A30\u0A4B\u0A5C'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0A05\u0A30\u0A2C'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0A05\u0A30\u0A2C'
    -    },
    -    '100000000000': {
    -      'other': '0\u00A0\u0A16\u0A30\u0A2C'
    -    },
    -    '1000000000000': {
    -      'other': '00\u00A0\u0A16\u0A30\u0A2C'
    -    },
    -    '10000000000000': {
    -      'other': '0\u00A0\u0A28\u0A40\u0A32'
    -    },
    -    '100000000000000': {
    -      'other': '00\u00A0\u0A28\u0A40\u0A32'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0A39\u0A1C\u0A3C\u0A3E\u0A30'
    -    },
    -    '10000': {
    -      'other': '00 \u0A39\u0A1C\u0A3C\u0A3E\u0A30'
    -    },
    -    '100000': {
    -      'other': '0 \u0A32\u0A71\u0A16'
    -    },
    -    '1000000': {
    -      'other': '00 \u0A32\u0A71\u0A16'
    -    },
    -    '10000000': {
    -      'other': '0 \u0A15\u0A30\u0A4B\u0A5C'
    -    },
    -    '100000000': {
    -      'other': '00 \u0A15\u0A30\u0A4B\u0A5C'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0A05\u0A30\u0A2C'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0A05\u0A30\u0A2C'
    -    },
    -    '100000000000': {
    -      'other': '0 \u0A16\u0A30\u0A2C'
    -    },
    -    '1000000000000': {
    -      'other': '00 \u0A16\u0A30\u0A2C'
    -    },
    -    '10000000000000': {
    -      'other': '0 \u0A28\u0A40\u0A32'
    -    },
    -    '100000000000000': {
    -      'other': '00 \u0A28\u0A40\u0A32'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale pa_Guru_IN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_pa_Guru_IN =
    -    goog.i18n.CompactNumberFormatSymbols_pa;
    -
    -
    -/**
    - * Compact number formatting symbols for locale pl.
    - */
    -goog.i18n.CompactNumberFormatSymbols_pl = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0tys.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0tys.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0tys.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mln'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mln'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mln'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mld'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mld'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mld'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bln'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bln'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bln'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 tysi\u0105ca'
    -    },
    -    '10000': {
    -      'other': '00 tysi\u0105ca'
    -    },
    -    '100000': {
    -      'other': '000 tysi\u0105ca'
    -    },
    -    '1000000': {
    -      'other': '0 miliona'
    -    },
    -    '10000000': {
    -      'other': '00 miliona'
    -    },
    -    '100000000': {
    -      'other': '000 miliona'
    -    },
    -    '1000000000': {
    -      'other': '0 miliarda'
    -    },
    -    '10000000000': {
    -      'other': '00 miliarda'
    -    },
    -    '100000000000': {
    -      'other': '000 miliarda'
    -    },
    -    '1000000000000': {
    -      'other': '0 biliona'
    -    },
    -    '10000000000000': {
    -      'other': '00 biliona'
    -    },
    -    '100000000000000': {
    -      'other': '000 biliona'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale pl_PL.
    - */
    -goog.i18n.CompactNumberFormatSymbols_pl_PL =
    -    goog.i18n.CompactNumberFormatSymbols_pl;
    -
    -
    -/**
    - * Compact number formatting symbols for locale pt.
    - */
    -goog.i18n.CompactNumberFormatSymbols_pt = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0mil'
    -    },
    -    '10000': {
    -      'other': '00\u00A0mil'
    -    },
    -    '100000': {
    -      'other': '000\u00A0mil'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mi'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mi'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mi'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0bi'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0bi'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0bi'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0tri'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0tri'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0tri'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 milh\u00F5es'
    -    },
    -    '10000000': {
    -      'other': '00 milh\u00F5es'
    -    },
    -    '100000000': {
    -      'other': '000 milh\u00F5es'
    -    },
    -    '1000000000': {
    -      'other': '0 bilh\u00F5es'
    -    },
    -    '10000000000': {
    -      'other': '00 bilh\u00F5es'
    -    },
    -    '100000000000': {
    -      'other': '000 bilh\u00F5es'
    -    },
    -    '1000000000000': {
    -      'other': '0 trilh\u00F5es'
    -    },
    -    '10000000000000': {
    -      'other': '00 trilh\u00F5es'
    -    },
    -    '100000000000000': {
    -      'other': '000 trilh\u00F5es'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale pt_BR.
    - */
    -goog.i18n.CompactNumberFormatSymbols_pt_BR =
    -    goog.i18n.CompactNumberFormatSymbols_pt;
    -
    -
    -/**
    - * Compact number formatting symbols for locale pt_PT.
    - */
    -goog.i18n.CompactNumberFormatSymbols_pt_PT = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0mil'
    -    },
    -    '10000': {
    -      'other': '00\u00A0mil'
    -    },
    -    '100000': {
    -      'other': '000\u00A0mil'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0MM'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0MM'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0MM'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bi'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bi'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bi'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 milh\u00F5es'
    -    },
    -    '10000000': {
    -      'other': '00 milh\u00F5es'
    -    },
    -    '100000000': {
    -      'other': '000 milh\u00F5es'
    -    },
    -    '1000000000': {
    -      'other': '0 mil milh\u00F5es'
    -    },
    -    '10000000000': {
    -      'other': '00 mil milh\u00F5es'
    -    },
    -    '100000000000': {
    -      'other': '000 mil milh\u00F5es'
    -    },
    -    '1000000000000': {
    -      'other': '0 bili\u00F5es'
    -    },
    -    '10000000000000': {
    -      'other': '00 bili\u00F5es'
    -    },
    -    '100000000000000': {
    -      'other': '000 bili\u00F5es'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ro.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ro = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0K'
    -    },
    -    '10000': {
    -      'other': '00\u00A0K'
    -    },
    -    '100000': {
    -      'other': '000\u00A0K'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mil.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mil.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mil.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mld.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mld.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mld.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0tril.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0tril.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0tril.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 de mii'
    -    },
    -    '10000': {
    -      'other': '00 de mii'
    -    },
    -    '100000': {
    -      'other': '000 de mii'
    -    },
    -    '1000000': {
    -      'other': '0 de milioane'
    -    },
    -    '10000000': {
    -      'other': '00 de milioane'
    -    },
    -    '100000000': {
    -      'other': '000 de milioane'
    -    },
    -    '1000000000': {
    -      'other': '0 de miliarde'
    -    },
    -    '10000000000': {
    -      'other': '00 de miliarde'
    -    },
    -    '100000000000': {
    -      'other': '000 de miliarde'
    -    },
    -    '1000000000000': {
    -      'other': '0 de trilioane'
    -    },
    -    '10000000000000': {
    -      'other': '00 de trilioane'
    -    },
    -    '100000000000000': {
    -      'other': '000 de trilioane'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ro_RO.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ro_RO =
    -    goog.i18n.CompactNumberFormatSymbols_ro;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ru.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ru = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0442\u044B\u0441.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0442\u044B\u0441.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0442\u044B\u0441.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u043C\u043B\u043D'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u043C\u043B\u043D'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u043C\u043B\u043D'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u0442\u0440\u043B\u043D'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u0442\u0440\u043B\u043D'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u0442\u0440\u043B\u043D'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0442\u044B\u0441\u044F\u0447\u0438'
    -    },
    -    '10000': {
    -      'other': '00 \u0442\u044B\u0441\u044F\u0447\u0438'
    -    },
    -    '100000': {
    -      'other': '000 \u0442\u044B\u0441\u044F\u0447\u0438'
    -    },
    -    '1000000': {
    -      'other': '0 \u043C\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '10000000': {
    -      'other': '00 \u043C\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '100000000': {
    -      'other': '000 \u043C\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '1000000000': {
    -      'other': '0 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434\u0430'
    -    },
    -    '10000000000': {
    -      'other': '00 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434\u0430'
    -    },
    -    '100000000000': {
    -      'other': '000 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434\u0430'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0442\u0440\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0442\u0440\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0442\u0440\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ru_RU.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ru_RU =
    -    goog.i18n.CompactNumberFormatSymbols_ru;
    -
    -
    -/**
    - * Compact number formatting symbols for locale si.
    - */
    -goog.i18n.CompactNumberFormatSymbols_si = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '\u0DAF0'
    -    },
    -    '10000': {
    -      'other': '\u0DAF00'
    -    },
    -    '100000': {
    -      'other': '\u0DAF000'
    -    },
    -    '1000000': {
    -      'other': '\u0DB8\u0DD20'
    -    },
    -    '10000000': {
    -      'other': '\u0DB8\u0DD200'
    -    },
    -    '100000000': {
    -      'other': '\u0DB8\u0DD2000'
    -    },
    -    '1000000000': {
    -      'other': '\u0DB6\u0DD20'
    -    },
    -    '10000000000': {
    -      'other': '\u0DB6\u0DD200'
    -    },
    -    '100000000000': {
    -      'other': '\u0DB6\u0DD2000'
    -    },
    -    '1000000000000': {
    -      'other': '\u0DA7\u0DCA\u200D\u0DBB\u0DD20'
    -    },
    -    '10000000000000': {
    -      'other': '\u0DA7\u0DCA\u200D\u0DBB\u0DD200'
    -    },
    -    '100000000000000': {
    -      'other': '\u0DA7\u0DCA\u200D\u0DBB\u0DD2000'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '\u0DAF\u0DC4\u0DC3 0'
    -    },
    -    '10000': {
    -      'other': '\u0DAF\u0DC4\u0DC3 00'
    -    },
    -    '100000': {
    -      'other': '\u0DAF\u0DC4\u0DC3 000'
    -    },
    -    '1000000': {
    -      'other': '\u0DB8\u0DD2\u0DBD\u0DD2\u0DBA\u0DB1 0'
    -    },
    -    '10000000': {
    -      'other': '\u0DB8\u0DD2\u0DBD\u0DD2\u0DBA\u0DB1 00'
    -    },
    -    '100000000': {
    -      'other': '\u0DB8\u0DD2\u0DBD\u0DD2\u0DBA\u0DB1 000'
    -    },
    -    '1000000000': {
    -      'other': '\u0DB6\u0DD2\u0DBD\u0DD2\u0DBA\u0DB1 0'
    -    },
    -    '10000000000': {
    -      'other': '\u0DB6\u0DD2\u0DBD\u0DD2\u0DBA\u0DB1 00'
    -    },
    -    '100000000000': {
    -      'other': '\u0DB6\u0DD2\u0DBD\u0DD2\u0DBA\u0DB1 000'
    -    },
    -    '1000000000000': {
    -      'other': '\u0DA7\u0DCA\u200D\u0DBB\u0DD2\u0DBD\u0DD2\u0DBA\u0DB1 0'
    -    },
    -    '10000000000000': {
    -      'other': '\u0DA7\u0DCA\u200D\u0DBB\u0DD2\u0DBD\u0DD2\u0DBA\u0DB1 00'
    -    },
    -    '100000000000000': {
    -      'other': '\u0DA7\u0DCA\u200D\u0DBB\u0DD2\u0DBD\u0DD2\u0DBA\u0DB1 000'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale si_LK.
    - */
    -goog.i18n.CompactNumberFormatSymbols_si_LK =
    -    goog.i18n.CompactNumberFormatSymbols_si;
    -
    -
    -/**
    - * Compact number formatting symbols for locale sk.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sk = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0tis.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0tis.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0tis.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mil.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mil.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mil.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mld.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mld.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mld.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bil.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bil.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bil.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 tis\u00EDc'
    -    },
    -    '10000': {
    -      'other': '00 tis\u00EDc'
    -    },
    -    '100000': {
    -      'other': '000 tis\u00EDc'
    -    },
    -    '1000000': {
    -      'other': '0 mili\u00F3nov'
    -    },
    -    '10000000': {
    -      'other': '00 mili\u00F3nov'
    -    },
    -    '100000000': {
    -      'other': '000 mili\u00F3nov'
    -    },
    -    '1000000000': {
    -      'other': '0 miliard'
    -    },
    -    '10000000000': {
    -      'other': '00 mili\u00E1rd'
    -    },
    -    '100000000000': {
    -      'other': '000 mili\u00E1rd'
    -    },
    -    '1000000000000': {
    -      'other': '0 bili\u00F3nov'
    -    },
    -    '10000000000000': {
    -      'other': '00 bili\u00F3nov'
    -    },
    -    '100000000000000': {
    -      'other': '000 bili\u00F3nov'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale sk_SK.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sk_SK =
    -    goog.i18n.CompactNumberFormatSymbols_sk;
    -
    -
    -/**
    - * Compact number formatting symbols for locale sl.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sl = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0tis.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0tis.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0tis.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mio.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mio.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mio.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mrd.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mrd.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mrd.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bil.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bil.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bil.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 tiso\u010D'
    -    },
    -    '10000': {
    -      'other': '00 tiso\u010D'
    -    },
    -    '100000': {
    -      'other': '000 tiso\u010D'
    -    },
    -    '1000000': {
    -      'other': '0 milijonov'
    -    },
    -    '10000000': {
    -      'other': '00 milijonov'
    -    },
    -    '100000000': {
    -      'other': '000 milijonov'
    -    },
    -    '1000000000': {
    -      'other': '0 milijard'
    -    },
    -    '10000000000': {
    -      'other': '00 milijard'
    -    },
    -    '100000000000': {
    -      'other': '000 milijard'
    -    },
    -    '1000000000000': {
    -      'other': '0 bilijonov'
    -    },
    -    '10000000000000': {
    -      'other': '00 bilijonov'
    -    },
    -    '100000000000000': {
    -      'other': '000 bilijonov'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale sl_SI.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sl_SI =
    -    goog.i18n.CompactNumberFormatSymbols_sl;
    -
    -
    -/**
    - * Compact number formatting symbols for locale sq.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sq = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0mij\u00EB'
    -    },
    -    '10000': {
    -      'other': '00\u00A0mij\u00EB'
    -    },
    -    '100000': {
    -      'other': '000\u00A0mij\u00EB'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0Mln'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0Mln'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0Mln'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Mld'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Mld'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Mld'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bln'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bln'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bln'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mij\u00EB'
    -    },
    -    '10000': {
    -      'other': '00 mij\u00EB'
    -    },
    -    '100000': {
    -      'other': '000 mij\u00EB'
    -    },
    -    '1000000': {
    -      'other': '0 milion'
    -    },
    -    '10000000': {
    -      'other': '00 milion'
    -    },
    -    '100000000': {
    -      'other': '000 milion'
    -    },
    -    '1000000000': {
    -      'other': '0 miliard'
    -    },
    -    '10000000000': {
    -      'other': '00 miliard'
    -    },
    -    '100000000000': {
    -      'other': '000 miliard'
    -    },
    -    '1000000000000': {
    -      'other': '0 bilion'
    -    },
    -    '10000000000000': {
    -      'other': '00 bilion'
    -    },
    -    '100000000000000': {
    -      'other': '000 bilion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale sq_AL.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sq_AL =
    -    goog.i18n.CompactNumberFormatSymbols_sq;
    -
    -
    -/**
    - * Compact number formatting symbols for locale sr.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sr = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0445\u0438\u0459.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0445\u0438\u0459.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0445\u0438\u0459.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u043C\u0438\u043B.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u043C\u0438\u043B.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u043C\u0438\u043B.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u043C\u043B\u0440\u0434.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u043C\u043B\u0440\u0434.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u043C\u043B\u0440\u0434.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u0431\u0438\u043B.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u0431\u0438\u043B.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u0431\u0438\u043B.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0445\u0438\u0459\u0430\u0434\u0430'
    -    },
    -    '10000': {
    -      'other': '00 \u0445\u0438\u0459\u0430\u0434\u0430'
    -    },
    -    '100000': {
    -      'other': '000 \u0445\u0438\u0459\u0430\u0434\u0430'
    -    },
    -    '1000000': {
    -      'other': '0 \u043C\u0438\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '10000000': {
    -      'other': '00 \u043C\u0438\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '100000000': {
    -      'other': '000 \u043C\u0438\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '1000000000': {
    -      'other': '0 \u043C\u0438\u043B\u0438\u0458\u0430\u0440\u0434\u0438'
    -    },
    -    '10000000000': {
    -      'other': '00 \u043C\u0438\u043B\u0438\u0458\u0430\u0440\u0434\u0438'
    -    },
    -    '100000000000': {
    -      'other': '000 \u043C\u0438\u043B\u0438\u0458\u0430\u0440\u0434\u0438'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0442\u0440\u0438\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0442\u0440\u0438\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0442\u0440\u0438\u043B\u0438\u043E\u043D\u0430'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale sr_Cyrl_RS.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sr_Cyrl_RS =
    -    goog.i18n.CompactNumberFormatSymbols_sr;
    -
    -
    -/**
    - * Compact number formatting symbols for locale sv.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sv = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0tn'
    -    },
    -    '10000': {
    -      'other': '00\u00A0tn'
    -    },
    -    '100000': {
    -      'other': '000\u00A0tn'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mn'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mn'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mn'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 tusen'
    -    },
    -    '10000': {
    -      'other': '00 tusen'
    -    },
    -    '100000': {
    -      'other': '000 tusen'
    -    },
    -    '1000000': {
    -      'other': '0 miljoner'
    -    },
    -    '10000000': {
    -      'other': '00 miljoner'
    -    },
    -    '100000000': {
    -      'other': '000 miljoner'
    -    },
    -    '1000000000': {
    -      'other': '0 miljarder'
    -    },
    -    '10000000000': {
    -      'other': '00 miljarder'
    -    },
    -    '100000000000': {
    -      'other': '000 miljarder'
    -    },
    -    '1000000000000': {
    -      'other': '0 biljoner'
    -    },
    -    '10000000000000': {
    -      'other': '00 biljoner'
    -    },
    -    '100000000000000': {
    -      'other': '000 biljoner'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale sv_SE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sv_SE =
    -    goog.i18n.CompactNumberFormatSymbols_sv;
    -
    -
    -/**
    - * Compact number formatting symbols for locale sw.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sw = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': 'elfu\u00A00'
    -    },
    -    '10000': {
    -      'other': 'elfu\u00A000'
    -    },
    -    '100000': {
    -      'other': 'elfu\u00A0000'
    -    },
    -    '1000000': {
    -      'other': 'M0'
    -    },
    -    '10000000': {
    -      'other': 'M00'
    -    },
    -    '100000000': {
    -      'other': 'M000'
    -    },
    -    '1000000000': {
    -      'other': 'B0'
    -    },
    -    '10000000000': {
    -      'other': 'B00'
    -    },
    -    '100000000000': {
    -      'other': 'B000'
    -    },
    -    '1000000000000': {
    -      'other': 'T0'
    -    },
    -    '10000000000000': {
    -      'other': 'T00'
    -    },
    -    '100000000000000': {
    -      'other': 'T000'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': 'Elfu 0'
    -    },
    -    '10000': {
    -      'other': 'Elfu 00'
    -    },
    -    '100000': {
    -      'other': 'Elfu 000'
    -    },
    -    '1000000': {
    -      'other': 'Milioni 0'
    -    },
    -    '10000000': {
    -      'other': 'Milioni 00'
    -    },
    -    '100000000': {
    -      'other': 'Milioni 000'
    -    },
    -    '1000000000': {
    -      'other': 'Bilioni 0'
    -    },
    -    '10000000000': {
    -      'other': 'Bilioni 00'
    -    },
    -    '100000000000': {
    -      'other': 'Bilioni 000'
    -    },
    -    '1000000000000': {
    -      'other': 'Trilioni 0'
    -    },
    -    '10000000000000': {
    -      'other': 'Trilioni 00'
    -    },
    -    '100000000000000': {
    -      'other': 'Trilioni 000'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale sw_TZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sw_TZ =
    -    goog.i18n.CompactNumberFormatSymbols_sw;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ta.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ta = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u0B86'
    -    },
    -    '10000': {
    -      'other': '00\u0B86'
    -    },
    -    '100000': {
    -      'other': '000\u0B86'
    -    },
    -    '1000000': {
    -      'other': '0\u0BAE\u0BBF'
    -    },
    -    '10000000': {
    -      'other': '00\u0BAE\u0BBF'
    -    },
    -    '100000000': {
    -      'other': '000\u0BAE\u0BBF'
    -    },
    -    '1000000000': {
    -      'other': '0\u0BAA\u0BBF'
    -    },
    -    '10000000000': {
    -      'other': '00\u0BAA\u0BBF'
    -    },
    -    '100000000000': {
    -      'other': '000\u0BAA\u0BBF'
    -    },
    -    '1000000000000': {
    -      'other': '0\u0B9F\u0BBF'
    -    },
    -    '10000000000000': {
    -      'other': '00\u0B9F\u0BBF'
    -    },
    -    '100000000000000': {
    -      'other': '000\u0B9F\u0BBF'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0B86\u0BAF\u0BBF\u0BB0\u0BAE\u0BCD'
    -    },
    -    '10000': {
    -      'other': '00 \u0B86\u0BAF\u0BBF\u0BB0\u0BAE\u0BCD'
    -    },
    -    '100000': {
    -      'other': '000 \u0B86\u0BAF\u0BBF\u0BB0\u0BAE\u0BCD'
    -    },
    -    '1000000': {
    -      'other': '0 \u0BAE\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '10000000': {
    -      'other': '00 \u0BAE\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '100000000': {
    -      'other': '000 \u0BAE\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0BAA\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0BAA\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0BAA\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0B9F\u0BBF\u0BB0\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0B9F\u0BBF\u0BB0\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0B9F\u0BBF\u0BB0\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ta_IN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ta_IN =
    -    goog.i18n.CompactNumberFormatSymbols_ta;
    -
    -
    -/**
    - * Compact number formatting symbols for locale te.
    - */
    -goog.i18n.CompactNumberFormatSymbols_te = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u0C35\u0C47'
    -    },
    -    '10000': {
    -      'other': '00\u0C35\u0C47'
    -    },
    -    '100000': {
    -      'other': '000\u0C35\u0C47'
    -    },
    -    '1000000': {
    -      'other': '0\u0C2E\u0C3F'
    -    },
    -    '10000000': {
    -      'other': '00\u0C2E\u0C3F'
    -    },
    -    '100000000': {
    -      'other': '000\u0C2E\u0C3F'
    -    },
    -    '1000000000': {
    -      'other': '0\u0C2C\u0C3F'
    -    },
    -    '10000000000': {
    -      'other': '00\u0C2C\u0C3F'
    -    },
    -    '100000000000': {
    -      'other': '000\u0C2C\u0C3F'
    -    },
    -    '1000000000000': {
    -      'other': '0\u0C1F\u0C4D\u0C30\u0C3F'
    -    },
    -    '10000000000000': {
    -      'other': '00\u0C1F\u0C4D\u0C30\u0C3F'
    -    },
    -    '100000000000000': {
    -      'other': '000\u0C1F\u0C4D\u0C30\u0C3F'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0C35\u0C47\u0C32\u0C41'
    -    },
    -    '10000': {
    -      'other': '00 \u0C35\u0C47\u0C32\u0C41'
    -    },
    -    '100000': {
    -      'other': '000 \u0C35\u0C47\u0C32\u0C41'
    -    },
    -    '1000000': {
    -      'other': '0 \u0C2E\u0C3F\u0C32\u0C3F\u0C2F\u0C28\u0C4D\u0C32\u0C41'
    -    },
    -    '10000000': {
    -      'other': '00 \u0C2E\u0C3F\u0C32\u0C3F\u0C2F\u0C28\u0C4D\u0C32\u0C41'
    -    },
    -    '100000000': {
    -      'other': '000 \u0C2E\u0C3F\u0C32\u0C3F\u0C2F\u0C28\u0C4D\u0C32\u0C41'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0C2C\u0C3F\u0C32\u0C3F\u0C2F\u0C28\u0C4D\u0C32\u0C41'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0C2C\u0C3F\u0C32\u0C3F\u0C2F\u0C28\u0C4D\u0C32\u0C41'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0C2C\u0C3F\u0C32\u0C3F\u0C2F\u0C28\u0C4D\u0C32\u0C41'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0C1F\u0C4D\u0C30\u0C3F\u0C32\u0C3F\u0C2F\u0C28\u0C4D\u0C32\u0C41'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0C1F\u0C4D\u0C30\u0C3F\u0C32\u0C3F\u0C2F\u0C28\u0C4D\u0C32\u0C41'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0C1F\u0C4D\u0C30\u0C3F\u0C32\u0C3F\u0C2F\u0C28\u0C4D\u0C32\u0C41'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale te_IN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_te_IN =
    -    goog.i18n.CompactNumberFormatSymbols_te;
    -
    -
    -/**
    - * Compact number formatting symbols for locale th.
    - */
    -goog.i18n.CompactNumberFormatSymbols_th = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0E1E.'
    -    },
    -    '10000': {
    -      'other': '0\u00A0\u0E21.'
    -    },
    -    '100000': {
    -      'other': '0\u00A0\u0E2A.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0E25.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0E25.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0E25.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0E1E.\u0E25.'
    -    },
    -    '10000000000': {
    -      'other': '0\u00A0\u0E21.\u0E25.'
    -    },
    -    '100000000000': {
    -      'other': '0\u00A0\u0E2A.\u0E25.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u0E25.\u0E25.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u0E25.\u0E25.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u0E25.\u0E25.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0E1E\u0E31\u0E19'
    -    },
    -    '10000': {
    -      'other': '0 \u0E2B\u0E21\u0E37\u0E48\u0E19'
    -    },
    -    '100000': {
    -      'other': '0 \u0E41\u0E2A\u0E19'
    -    },
    -    '1000000': {
    -      'other': '0 \u0E25\u0E49\u0E32\u0E19'
    -    },
    -    '10000000': {
    -      'other': '00 \u0E25\u0E49\u0E32\u0E19'
    -    },
    -    '100000000': {
    -      'other': '000 \u0E25\u0E49\u0E32\u0E19'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0E1E\u0E31\u0E19\u0E25\u0E49\u0E32\u0E19'
    -    },
    -    '10000000000': {
    -      'other': '0 \u0E2B\u0E21\u0E37\u0E48\u0E19\u0E25\u0E49\u0E32\u0E19'
    -    },
    -    '100000000000': {
    -      'other': '0 \u0E41\u0E2A\u0E19\u0E25\u0E49\u0E32\u0E19'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0E25\u0E49\u0E32\u0E19\u0E25\u0E49\u0E32\u0E19'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0E25\u0E49\u0E32\u0E19\u0E25\u0E49\u0E32\u0E19'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0E25\u0E49\u0E32\u0E19\u0E25\u0E49\u0E32\u0E19'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale th_TH.
    - */
    -goog.i18n.CompactNumberFormatSymbols_th_TH =
    -    goog.i18n.CompactNumberFormatSymbols_th;
    -
    -
    -/**
    - * Compact number formatting symbols for locale tl.
    - */
    -goog.i18n.CompactNumberFormatSymbols_tl = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 libo'
    -    },
    -    '10000': {
    -      'other': '00 libo'
    -    },
    -    '100000': {
    -      'other': '000 libo'
    -    },
    -    '1000000': {
    -      'other': '0 milyon'
    -    },
    -    '10000000': {
    -      'other': '00 milyon'
    -    },
    -    '100000000': {
    -      'other': '000 milyon'
    -    },
    -    '1000000000': {
    -      'other': '0 bilyon'
    -    },
    -    '10000000000': {
    -      'other': '00 bilyon'
    -    },
    -    '100000000000': {
    -      'other': '000 bilyon'
    -    },
    -    '1000000000000': {
    -      'other': '0 trilyon'
    -    },
    -    '10000000000000': {
    -      'other': '00 trilyon'
    -    },
    -    '100000000000000': {
    -      'other': '000 trilyon'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale tr.
    - */
    -goog.i18n.CompactNumberFormatSymbols_tr = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '00\u00A0B'
    -    },
    -    '100000': {
    -      'other': '000\u00A0B'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0Mn'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0Mn'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0Mn'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Mr'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Mr'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Mr'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Tn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Tn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Tn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 bin'
    -    },
    -    '10000': {
    -      'other': '00 bin'
    -    },
    -    '100000': {
    -      'other': '000 bin'
    -    },
    -    '1000000': {
    -      'other': '0 milyon'
    -    },
    -    '10000000': {
    -      'other': '00 milyon'
    -    },
    -    '100000000': {
    -      'other': '000 milyon'
    -    },
    -    '1000000000': {
    -      'other': '0 milyar'
    -    },
    -    '10000000000': {
    -      'other': '00 milyar'
    -    },
    -    '100000000000': {
    -      'other': '000 milyar'
    -    },
    -    '1000000000000': {
    -      'other': '0 trilyon'
    -    },
    -    '10000000000000': {
    -      'other': '00 trilyon'
    -    },
    -    '100000000000000': {
    -      'other': '000 trilyon'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale tr_TR.
    - */
    -goog.i18n.CompactNumberFormatSymbols_tr_TR =
    -    goog.i18n.CompactNumberFormatSymbols_tr;
    -
    -
    -/**
    - * Compact number formatting symbols for locale uk.
    - */
    -goog.i18n.CompactNumberFormatSymbols_uk = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0442\u0438\u0441'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0442\u0438\u0441'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0442\u0438\u0441'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u043C\u043B\u043D'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u043C\u043B\u043D'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u043C\u043B\u043D'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u0442\u0440\u043B\u043D'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u0442\u0440\u043B\u043D'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u0442\u0440\u043B\u043D'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0442\u0438\u0441\u044F\u0447\u0456'
    -    },
    -    '10000': {
    -      'other': '00 \u0442\u0438\u0441\u044F\u0447\u0456'
    -    },
    -    '100000': {
    -      'other': '000 \u0442\u0438\u0441\u044F\u0447\u0456'
    -    },
    -    '1000000': {
    -      'other': '0 \u043C\u0456\u043B\u044C\u0439\u043E\u043D\u0430'
    -    },
    -    '10000000': {
    -      'other': '00 \u043C\u0456\u043B\u044C\u0439\u043E\u043D\u0430'
    -    },
    -    '100000000': {
    -      'other': '000 \u043C\u0456\u043B\u044C\u0439\u043E\u043D\u0430'
    -    },
    -    '1000000000': {
    -      'other': '0 \u043C\u0456\u043B\u044C\u044F\u0440\u0434\u0430'
    -    },
    -    '10000000000': {
    -      'other': '00 \u043C\u0456\u043B\u044C\u044F\u0440\u0434\u0430'
    -    },
    -    '100000000000': {
    -      'other': '000 \u043C\u0456\u043B\u044C\u044F\u0440\u0434\u0430'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0442\u0440\u0438\u043B\u044C\u0439\u043E\u043D\u0430'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0442\u0440\u0438\u043B\u044C\u0439\u043E\u043D\u0430'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0442\u0440\u0438\u043B\u044C\u0439\u043E\u043D\u0430'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale uk_UA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_uk_UA =
    -    goog.i18n.CompactNumberFormatSymbols_uk;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ur.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ur = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u06C1\u0632\u0627\u0631'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u06C1\u0632\u0627\u0631'
    -    },
    -    '100000': {
    -      'other': '0\u00A0\u0644\u0627\u06A9\u06BE'
    -    },
    -    '1000000': {
    -      'other': '00\u00A0\u0644\u0627\u06A9\u06BE'
    -    },
    -    '10000000': {
    -      'other': '0\u00A0\u06A9\u0631\u0648\u0691'
    -    },
    -    '100000000': {
    -      'other': '00\u00A0\u06A9\u0631\u0648\u0691'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0627\u0631\u0628'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0627\u0631\u0628'
    -    },
    -    '100000000000': {
    -      'other': '0\u00A0\u06A9\u06BE\u0631\u0628'
    -    },
    -    '1000000000000': {
    -      'other': '00\u00A0\u06A9\u06BE\u0631\u0628'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u0679\u0631\u06CC\u0644\u06CC\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u0679\u0631\u06CC\u0644\u06CC\u0646'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u06C1\u0632\u0627\u0631'
    -    },
    -    '10000': {
    -      'other': '00 \u06C1\u0632\u0627\u0631'
    -    },
    -    '100000': {
    -      'other': '0 \u0644\u0627\u06A9\u06BE'
    -    },
    -    '1000000': {
    -      'other': '00 \u0644\u0627\u06A9\u06BE'
    -    },
    -    '10000000': {
    -      'other': '0 \u06A9\u0631\u0648\u0691'
    -    },
    -    '100000000': {
    -      'other': '00 \u06A9\u0631\u0648\u0691'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0627\u0631\u0628'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0627\u0631\u0628'
    -    },
    -    '100000000000': {
    -      'other': '0 \u06A9\u06BE\u0631\u0628'
    -    },
    -    '1000000000000': {
    -      'other': '00 \u06A9\u06BE\u0631\u0628'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0679\u0631\u06CC\u0644\u06CC\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0679\u0631\u06CC\u0644\u06CC\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ur_PK.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ur_PK =
    -    goog.i18n.CompactNumberFormatSymbols_ur;
    -
    -
    -/**
    - * Compact number formatting symbols for locale uz.
    - */
    -goog.i18n.CompactNumberFormatSymbols_uz = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0ming'
    -    },
    -    '10000': {
    -      'other': '00ming'
    -    },
    -    '100000': {
    -      'other': '000ming'
    -    },
    -    '1000000': {
    -      'other': '0mln'
    -    },
    -    '10000000': {
    -      'other': '00mln'
    -    },
    -    '100000000': {
    -      'other': '000mln'
    -    },
    -    '1000000000': {
    -      'other': '0mlrd'
    -    },
    -    '10000000000': {
    -      'other': '00mlrd'
    -    },
    -    '100000000000': {
    -      'other': '000mlrd'
    -    },
    -    '1000000000000': {
    -      'other': '0trln'
    -    },
    -    '10000000000000': {
    -      'other': '00trln'
    -    },
    -    '100000000000000': {
    -      'other': '000trln'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 ming'
    -    },
    -    '10000': {
    -      'other': '00 ming'
    -    },
    -    '100000': {
    -      'other': '000 ming'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 milliard'
    -    },
    -    '10000000000': {
    -      'other': '00 milliard'
    -    },
    -    '100000000000': {
    -      'other': '000 milliard'
    -    },
    -    '1000000000000': {
    -      'other': '0 trilion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trilion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trilion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale uz_Latn_UZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_uz_Latn_UZ =
    -    goog.i18n.CompactNumberFormatSymbols_uz;
    -
    -
    -/**
    - * Compact number formatting symbols for locale vi.
    - */
    -goog.i18n.CompactNumberFormatSymbols_vi = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0N'
    -    },
    -    '10000': {
    -      'other': '00\u00A0N'
    -    },
    -    '100000': {
    -      'other': '000\u00A0N'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0Tr'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0Tr'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0Tr'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0T'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0T'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0T'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0NT'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0NT'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0NT'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 ngh\u00ECn'
    -    },
    -    '10000': {
    -      'other': '00 ngh\u00ECn'
    -    },
    -    '100000': {
    -      'other': '000 ngh\u00ECn'
    -    },
    -    '1000000': {
    -      'other': '0 tri\u1EC7u'
    -    },
    -    '10000000': {
    -      'other': '00 tri\u1EC7u'
    -    },
    -    '100000000': {
    -      'other': '000 tri\u1EC7u'
    -    },
    -    '1000000000': {
    -      'other': '0 t\u1EF7'
    -    },
    -    '10000000000': {
    -      'other': '00 t\u1EF7'
    -    },
    -    '100000000000': {
    -      'other': '000 t\u1EF7'
    -    },
    -    '1000000000000': {
    -      'other': '0 ngh\u00ECn t\u1EF7'
    -    },
    -    '10000000000000': {
    -      'other': '00 ngh\u00ECn t\u1EF7'
    -    },
    -    '100000000000000': {
    -      'other': '000 ngh\u00ECn t\u1EF7'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale vi_VN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_vi_VN =
    -    goog.i18n.CompactNumberFormatSymbols_vi;
    -
    -
    -/**
    - * Compact number formatting symbols for locale zh.
    - */
    -goog.i18n.CompactNumberFormatSymbols_zh = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u5343'
    -    },
    -    '10000': {
    -      'other': '0\u4E07'
    -    },
    -    '100000': {
    -      'other': '00\u4E07'
    -    },
    -    '1000000': {
    -      'other': '000\u4E07'
    -    },
    -    '10000000': {
    -      'other': '0000\u4E07'
    -    },
    -    '100000000': {
    -      'other': '0\u4EBF'
    -    },
    -    '1000000000': {
    -      'other': '00\u4EBF'
    -    },
    -    '10000000000': {
    -      'other': '000\u4EBF'
    -    },
    -    '100000000000': {
    -      'other': '0000\u4EBF'
    -    },
    -    '1000000000000': {
    -      'other': '0\u5146'
    -    },
    -    '10000000000000': {
    -      'other': '00\u5146'
    -    },
    -    '100000000000000': {
    -      'other': '000\u5146'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0\u5343'
    -    },
    -    '10000': {
    -      'other': '0\u4E07'
    -    },
    -    '100000': {
    -      'other': '00\u4E07'
    -    },
    -    '1000000': {
    -      'other': '000\u4E07'
    -    },
    -    '10000000': {
    -      'other': '0000\u4E07'
    -    },
    -    '100000000': {
    -      'other': '0\u4EBF'
    -    },
    -    '1000000000': {
    -      'other': '00\u4EBF'
    -    },
    -    '10000000000': {
    -      'other': '000\u4EBF'
    -    },
    -    '100000000000': {
    -      'other': '0000\u4EBF'
    -    },
    -    '1000000000000': {
    -      'other': '0\u5146'
    -    },
    -    '10000000000000': {
    -      'other': '00\u5146'
    -    },
    -    '100000000000000': {
    -      'other': '000\u5146'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale zh_CN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_zh_CN =
    -    goog.i18n.CompactNumberFormatSymbols_zh;
    -
    -
    -/**
    - * Compact number formatting symbols for locale zh_HK.
    - */
    -goog.i18n.CompactNumberFormatSymbols_zh_HK = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0\u5343'
    -    },
    -    '10000': {
    -      'other': '0\u842C'
    -    },
    -    '100000': {
    -      'other': '00\u842C'
    -    },
    -    '1000000': {
    -      'other': '000\u842C'
    -    },
    -    '10000000': {
    -      'other': '0000\u842C'
    -    },
    -    '100000000': {
    -      'other': '0\u5104'
    -    },
    -    '1000000000': {
    -      'other': '00\u5104'
    -    },
    -    '10000000000': {
    -      'other': '000\u5104'
    -    },
    -    '100000000000': {
    -      'other': '0000\u5104'
    -    },
    -    '1000000000000': {
    -      'other': '0\u5146'
    -    },
    -    '10000000000000': {
    -      'other': '00\u5146'
    -    },
    -    '100000000000000': {
    -      'other': '000\u5146'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale zh_Hans_CN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_zh_Hans_CN =
    -    goog.i18n.CompactNumberFormatSymbols_zh;
    -
    -
    -/**
    - * Compact number formatting symbols for locale zh_TW.
    - */
    -goog.i18n.CompactNumberFormatSymbols_zh_TW = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u5343'
    -    },
    -    '10000': {
    -      'other': '0\u842C'
    -    },
    -    '100000': {
    -      'other': '00\u842C'
    -    },
    -    '1000000': {
    -      'other': '000\u842C'
    -    },
    -    '10000000': {
    -      'other': '0000\u842C'
    -    },
    -    '100000000': {
    -      'other': '0\u5104'
    -    },
    -    '1000000000': {
    -      'other': '00\u5104'
    -    },
    -    '10000000000': {
    -      'other': '000\u5104'
    -    },
    -    '100000000000': {
    -      'other': '0000\u5104'
    -    },
    -    '1000000000000': {
    -      'other': '0\u5146'
    -    },
    -    '10000000000000': {
    -      'other': '00\u5146'
    -    },
    -    '100000000000000': {
    -      'other': '000\u5146'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale zu.
    - */
    -goog.i18n.CompactNumberFormatSymbols_zu = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 inkulungwane'
    -    },
    -    '10000': {
    -      'other': '00 inkulungwane'
    -    },
    -    '100000': {
    -      'other': '000 inkulungwane'
    -    },
    -    '1000000': {
    -      'other': '0 isigidi'
    -    },
    -    '10000000': {
    -      'other': '00 isigidi'
    -    },
    -    '100000000': {
    -      'other': '000 isigidi'
    -    },
    -    '1000000000': {
    -      'other': '0 isigidi sezigidi'
    -    },
    -    '10000000000': {
    -      'other': '00 isigidi sezigidi'
    -    },
    -    '100000000000': {
    -      'other': '000 isigidi sezigidi'
    -    },
    -    '1000000000000': {
    -      'other': '0 isigidintathu'
    -    },
    -    '10000000000000': {
    -      'other': '00 isigidintathu'
    -    },
    -    '100000000000000': {
    -      'other': '000 isigidintathu'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale zu_ZA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_zu_ZA =
    -    goog.i18n.CompactNumberFormatSymbols_zu;
    -
    -
    -/**
    - * Selected compact number formatting symbols by locale.
    - */
    -goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en;
    -
    -if (goog.LOCALE == 'af') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_af;
    -}
    -
    -if (goog.LOCALE == 'af_ZA' || goog.LOCALE == 'af-ZA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_af;
    -}
    -
    -if (goog.LOCALE == 'am') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_am;
    -}
    -
    -if (goog.LOCALE == 'am_ET' || goog.LOCALE == 'am-ET') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_am;
    -}
    -
    -if (goog.LOCALE == 'ar') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ar;
    -}
    -
    -if (goog.LOCALE == 'ar_001' || goog.LOCALE == 'ar-001') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ar;
    -}
    -
    -if (goog.LOCALE == 'az') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_az;
    -}
    -
    -if (goog.LOCALE == 'az_Latn_AZ' || goog.LOCALE == 'az-Latn-AZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_az;
    -}
    -
    -if (goog.LOCALE == 'bg') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_bg;
    -}
    -
    -if (goog.LOCALE == 'bg_BG' || goog.LOCALE == 'bg-BG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_bg;
    -}
    -
    -if (goog.LOCALE == 'bn') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_bn;
    -}
    -
    -if (goog.LOCALE == 'bn_BD' || goog.LOCALE == 'bn-BD') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_bn;
    -}
    -
    -if (goog.LOCALE == 'br') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_br;
    -}
    -
    -if (goog.LOCALE == 'br_FR' || goog.LOCALE == 'br-FR') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_br;
    -}
    -
    -if (goog.LOCALE == 'ca') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ca;
    -}
    -
    -if (goog.LOCALE == 'ca_AD' || goog.LOCALE == 'ca-AD') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ca;
    -}
    -
    -if (goog.LOCALE == 'ca_ES' || goog.LOCALE == 'ca-ES') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ca;
    -}
    -
    -if (goog.LOCALE == 'ca_ES_VALENCIA' || goog.LOCALE == 'ca-ES-VALENCIA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ca;
    -}
    -
    -if (goog.LOCALE == 'ca_FR' || goog.LOCALE == 'ca-FR') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ca;
    -}
    -
    -if (goog.LOCALE == 'ca_IT' || goog.LOCALE == 'ca-IT') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ca;
    -}
    -
    -if (goog.LOCALE == 'chr') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_chr;
    -}
    -
    -if (goog.LOCALE == 'chr_US' || goog.LOCALE == 'chr-US') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_chr;
    -}
    -
    -if (goog.LOCALE == 'cs') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_cs;
    -}
    -
    -if (goog.LOCALE == 'cs_CZ' || goog.LOCALE == 'cs-CZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_cs;
    -}
    -
    -if (goog.LOCALE == 'cy') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_cy;
    -}
    -
    -if (goog.LOCALE == 'cy_GB' || goog.LOCALE == 'cy-GB') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_cy;
    -}
    -
    -if (goog.LOCALE == 'da') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_da;
    -}
    -
    -if (goog.LOCALE == 'da_DK' || goog.LOCALE == 'da-DK') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_da;
    -}
    -
    -if (goog.LOCALE == 'da_GL' || goog.LOCALE == 'da-GL') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_da;
    -}
    -
    -if (goog.LOCALE == 'de') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_de;
    -}
    -
    -if (goog.LOCALE == 'de_AT' || goog.LOCALE == 'de-AT') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_de_AT;
    -}
    -
    -if (goog.LOCALE == 'de_BE' || goog.LOCALE == 'de-BE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_de;
    -}
    -
    -if (goog.LOCALE == 'de_CH' || goog.LOCALE == 'de-CH') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_de_CH;
    -}
    -
    -if (goog.LOCALE == 'de_DE' || goog.LOCALE == 'de-DE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_de;
    -}
    -
    -if (goog.LOCALE == 'de_LU' || goog.LOCALE == 'de-LU') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_de;
    -}
    -
    -if (goog.LOCALE == 'el') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_el;
    -}
    -
    -if (goog.LOCALE == 'el_GR' || goog.LOCALE == 'el-GR') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_el;
    -}
    -
    -if (goog.LOCALE == 'en') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_001' || goog.LOCALE == 'en-001') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_AS' || goog.LOCALE == 'en-AS') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_AU' || goog.LOCALE == 'en-AU') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_AU;
    -}
    -
    -if (goog.LOCALE == 'en_DG' || goog.LOCALE == 'en-DG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_FM' || goog.LOCALE == 'en-FM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_GB' || goog.LOCALE == 'en-GB') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_GB;
    -}
    -
    -if (goog.LOCALE == 'en_GU' || goog.LOCALE == 'en-GU') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_IE' || goog.LOCALE == 'en-IE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_IE;
    -}
    -
    -if (goog.LOCALE == 'en_IN' || goog.LOCALE == 'en-IN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_IN;
    -}
    -
    -if (goog.LOCALE == 'en_IO' || goog.LOCALE == 'en-IO') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_MH' || goog.LOCALE == 'en-MH') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_MP' || goog.LOCALE == 'en-MP') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_PR' || goog.LOCALE == 'en-PR') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_PW' || goog.LOCALE == 'en-PW') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_SG' || goog.LOCALE == 'en-SG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_SG;
    -}
    -
    -if (goog.LOCALE == 'en_TC' || goog.LOCALE == 'en-TC') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_UM' || goog.LOCALE == 'en-UM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_US' || goog.LOCALE == 'en-US') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_VG' || goog.LOCALE == 'en-VG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_VI' || goog.LOCALE == 'en-VI') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_ZA' || goog.LOCALE == 'en-ZA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_ZA;
    -}
    -
    -if (goog.LOCALE == 'en_ZW' || goog.LOCALE == 'en-ZW') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'es') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_es;
    -}
    -
    -if (goog.LOCALE == 'es_419' || goog.LOCALE == 'es-419') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_es_419;
    -}
    -
    -if (goog.LOCALE == 'es_EA' || goog.LOCALE == 'es-EA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_es;
    -}
    -
    -if (goog.LOCALE == 'es_ES' || goog.LOCALE == 'es-ES') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_es;
    -}
    -
    -if (goog.LOCALE == 'es_IC' || goog.LOCALE == 'es-IC') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_es;
    -}
    -
    -if (goog.LOCALE == 'et') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_et;
    -}
    -
    -if (goog.LOCALE == 'et_EE' || goog.LOCALE == 'et-EE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_et;
    -}
    -
    -if (goog.LOCALE == 'eu') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_eu;
    -}
    -
    -if (goog.LOCALE == 'eu_ES' || goog.LOCALE == 'eu-ES') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_eu;
    -}
    -
    -if (goog.LOCALE == 'fa') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fa;
    -}
    -
    -if (goog.LOCALE == 'fa_IR' || goog.LOCALE == 'fa-IR') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fa;
    -}
    -
    -if (goog.LOCALE == 'fi') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fi;
    -}
    -
    -if (goog.LOCALE == 'fi_FI' || goog.LOCALE == 'fi-FI') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fi;
    -}
    -
    -if (goog.LOCALE == 'fil') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fil;
    -}
    -
    -if (goog.LOCALE == 'fil_PH' || goog.LOCALE == 'fil-PH') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fil;
    -}
    -
    -if (goog.LOCALE == 'fr') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr;
    -}
    -
    -if (goog.LOCALE == 'fr_BL' || goog.LOCALE == 'fr-BL') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr;
    -}
    -
    -if (goog.LOCALE == 'fr_CA' || goog.LOCALE == 'fr-CA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_CA;
    -}
    -
    -if (goog.LOCALE == 'fr_FR' || goog.LOCALE == 'fr-FR') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr;
    -}
    -
    -if (goog.LOCALE == 'fr_GF' || goog.LOCALE == 'fr-GF') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr;
    -}
    -
    -if (goog.LOCALE == 'fr_GP' || goog.LOCALE == 'fr-GP') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr;
    -}
    -
    -if (goog.LOCALE == 'fr_MC' || goog.LOCALE == 'fr-MC') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr;
    -}
    -
    -if (goog.LOCALE == 'fr_MF' || goog.LOCALE == 'fr-MF') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr;
    -}
    -
    -if (goog.LOCALE == 'fr_MQ' || goog.LOCALE == 'fr-MQ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr;
    -}
    -
    -if (goog.LOCALE == 'fr_PM' || goog.LOCALE == 'fr-PM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr;
    -}
    -
    -if (goog.LOCALE == 'fr_RE' || goog.LOCALE == 'fr-RE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr;
    -}
    -
    -if (goog.LOCALE == 'fr_YT' || goog.LOCALE == 'fr-YT') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr;
    -}
    -
    -if (goog.LOCALE == 'ga') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ga;
    -}
    -
    -if (goog.LOCALE == 'ga_IE' || goog.LOCALE == 'ga-IE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ga;
    -}
    -
    -if (goog.LOCALE == 'gl') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_gl;
    -}
    -
    -if (goog.LOCALE == 'gl_ES' || goog.LOCALE == 'gl-ES') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_gl;
    -}
    -
    -if (goog.LOCALE == 'gsw') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_gsw;
    -}
    -
    -if (goog.LOCALE == 'gsw_CH' || goog.LOCALE == 'gsw-CH') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_gsw;
    -}
    -
    -if (goog.LOCALE == 'gsw_LI' || goog.LOCALE == 'gsw-LI') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_gsw;
    -}
    -
    -if (goog.LOCALE == 'gu') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_gu;
    -}
    -
    -if (goog.LOCALE == 'gu_IN' || goog.LOCALE == 'gu-IN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_gu;
    -}
    -
    -if (goog.LOCALE == 'haw') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_haw;
    -}
    -
    -if (goog.LOCALE == 'haw_US' || goog.LOCALE == 'haw-US') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_haw;
    -}
    -
    -if (goog.LOCALE == 'he') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_he;
    -}
    -
    -if (goog.LOCALE == 'he_IL' || goog.LOCALE == 'he-IL') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_he;
    -}
    -
    -if (goog.LOCALE == 'hi') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_hi;
    -}
    -
    -if (goog.LOCALE == 'hi_IN' || goog.LOCALE == 'hi-IN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_hi;
    -}
    -
    -if (goog.LOCALE == 'hr') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_hr;
    -}
    -
    -if (goog.LOCALE == 'hr_HR' || goog.LOCALE == 'hr-HR') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_hr;
    -}
    -
    -if (goog.LOCALE == 'hu') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_hu;
    -}
    -
    -if (goog.LOCALE == 'hu_HU' || goog.LOCALE == 'hu-HU') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_hu;
    -}
    -
    -if (goog.LOCALE == 'hy') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_hy;
    -}
    -
    -if (goog.LOCALE == 'hy_AM' || goog.LOCALE == 'hy-AM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_hy;
    -}
    -
    -if (goog.LOCALE == 'id') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_id;
    -}
    -
    -if (goog.LOCALE == 'id_ID' || goog.LOCALE == 'id-ID') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_id;
    -}
    -
    -if (goog.LOCALE == 'in') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_in;
    -}
    -
    -if (goog.LOCALE == 'is') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_is;
    -}
    -
    -if (goog.LOCALE == 'is_IS' || goog.LOCALE == 'is-IS') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_is;
    -}
    -
    -if (goog.LOCALE == 'it') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_it;
    -}
    -
    -if (goog.LOCALE == 'it_IT' || goog.LOCALE == 'it-IT') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_it;
    -}
    -
    -if (goog.LOCALE == 'it_SM' || goog.LOCALE == 'it-SM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_it;
    -}
    -
    -if (goog.LOCALE == 'iw') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_iw;
    -}
    -
    -if (goog.LOCALE == 'ja') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ja;
    -}
    -
    -if (goog.LOCALE == 'ja_JP' || goog.LOCALE == 'ja-JP') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ja;
    -}
    -
    -if (goog.LOCALE == 'ka') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ka;
    -}
    -
    -if (goog.LOCALE == 'ka_GE' || goog.LOCALE == 'ka-GE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ka;
    -}
    -
    -if (goog.LOCALE == 'kk') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_kk;
    -}
    -
    -if (goog.LOCALE == 'kk_Cyrl_KZ' || goog.LOCALE == 'kk-Cyrl-KZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_kk;
    -}
    -
    -if (goog.LOCALE == 'km') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_km;
    -}
    -
    -if (goog.LOCALE == 'km_KH' || goog.LOCALE == 'km-KH') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_km;
    -}
    -
    -if (goog.LOCALE == 'kn') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_kn;
    -}
    -
    -if (goog.LOCALE == 'kn_IN' || goog.LOCALE == 'kn-IN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_kn;
    -}
    -
    -if (goog.LOCALE == 'ko') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ko;
    -}
    -
    -if (goog.LOCALE == 'ko_KR' || goog.LOCALE == 'ko-KR') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ko;
    -}
    -
    -if (goog.LOCALE == 'ky') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ky;
    -}
    -
    -if (goog.LOCALE == 'ky_Cyrl_KG' || goog.LOCALE == 'ky-Cyrl-KG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ky;
    -}
    -
    -if (goog.LOCALE == 'ln') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ln;
    -}
    -
    -if (goog.LOCALE == 'ln_CD' || goog.LOCALE == 'ln-CD') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ln;
    -}
    -
    -if (goog.LOCALE == 'lo') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_lo;
    -}
    -
    -if (goog.LOCALE == 'lo_LA' || goog.LOCALE == 'lo-LA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_lo;
    -}
    -
    -if (goog.LOCALE == 'lt') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_lt;
    -}
    -
    -if (goog.LOCALE == 'lt_LT' || goog.LOCALE == 'lt-LT') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_lt;
    -}
    -
    -if (goog.LOCALE == 'lv') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_lv;
    -}
    -
    -if (goog.LOCALE == 'lv_LV' || goog.LOCALE == 'lv-LV') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_lv;
    -}
    -
    -if (goog.LOCALE == 'mk') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_mk;
    -}
    -
    -if (goog.LOCALE == 'mk_MK' || goog.LOCALE == 'mk-MK') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_mk;
    -}
    -
    -if (goog.LOCALE == 'ml') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ml;
    -}
    -
    -if (goog.LOCALE == 'ml_IN' || goog.LOCALE == 'ml-IN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ml;
    -}
    -
    -if (goog.LOCALE == 'mn') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_mn;
    -}
    -
    -if (goog.LOCALE == 'mn_Cyrl_MN' || goog.LOCALE == 'mn-Cyrl-MN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_mn;
    -}
    -
    -if (goog.LOCALE == 'mr') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_mr;
    -}
    -
    -if (goog.LOCALE == 'mr_IN' || goog.LOCALE == 'mr-IN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_mr;
    -}
    -
    -if (goog.LOCALE == 'ms') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ms;
    -}
    -
    -if (goog.LOCALE == 'ms_Latn_MY' || goog.LOCALE == 'ms-Latn-MY') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ms;
    -}
    -
    -if (goog.LOCALE == 'mt') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_mt;
    -}
    -
    -if (goog.LOCALE == 'mt_MT' || goog.LOCALE == 'mt-MT') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_mt;
    -}
    -
    -if (goog.LOCALE == 'my') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_my;
    -}
    -
    -if (goog.LOCALE == 'my_MM' || goog.LOCALE == 'my-MM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_my;
    -}
    -
    -if (goog.LOCALE == 'nb') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_nb;
    -}
    -
    -if (goog.LOCALE == 'nb_NO' || goog.LOCALE == 'nb-NO') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_nb;
    -}
    -
    -if (goog.LOCALE == 'nb_SJ' || goog.LOCALE == 'nb-SJ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_nb;
    -}
    -
    -if (goog.LOCALE == 'ne') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ne;
    -}
    -
    -if (goog.LOCALE == 'ne_NP' || goog.LOCALE == 'ne-NP') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ne;
    -}
    -
    -if (goog.LOCALE == 'nl') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_nl;
    -}
    -
    -if (goog.LOCALE == 'nl_NL' || goog.LOCALE == 'nl-NL') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_nl;
    -}
    -
    -if (goog.LOCALE == 'no') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_no;
    -}
    -
    -if (goog.LOCALE == 'no_NO' || goog.LOCALE == 'no-NO') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_no;
    -}
    -
    -if (goog.LOCALE == 'or') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_or;
    -}
    -
    -if (goog.LOCALE == 'or_IN' || goog.LOCALE == 'or-IN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_or;
    -}
    -
    -if (goog.LOCALE == 'pa') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_pa;
    -}
    -
    -if (goog.LOCALE == 'pa_Guru_IN' || goog.LOCALE == 'pa-Guru-IN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_pa;
    -}
    -
    -if (goog.LOCALE == 'pl') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_pl;
    -}
    -
    -if (goog.LOCALE == 'pl_PL' || goog.LOCALE == 'pl-PL') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_pl;
    -}
    -
    -if (goog.LOCALE == 'pt') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_pt;
    -}
    -
    -if (goog.LOCALE == 'pt_BR' || goog.LOCALE == 'pt-BR') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_pt;
    -}
    -
    -if (goog.LOCALE == 'pt_PT' || goog.LOCALE == 'pt-PT') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_pt_PT;
    -}
    -
    -if (goog.LOCALE == 'ro') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ro;
    -}
    -
    -if (goog.LOCALE == 'ro_RO' || goog.LOCALE == 'ro-RO') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ro;
    -}
    -
    -if (goog.LOCALE == 'ru') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ru;
    -}
    -
    -if (goog.LOCALE == 'ru_RU' || goog.LOCALE == 'ru-RU') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ru;
    -}
    -
    -if (goog.LOCALE == 'si') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_si;
    -}
    -
    -if (goog.LOCALE == 'si_LK' || goog.LOCALE == 'si-LK') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_si;
    -}
    -
    -if (goog.LOCALE == 'sk') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sk;
    -}
    -
    -if (goog.LOCALE == 'sk_SK' || goog.LOCALE == 'sk-SK') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sk;
    -}
    -
    -if (goog.LOCALE == 'sl') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sl;
    -}
    -
    -if (goog.LOCALE == 'sl_SI' || goog.LOCALE == 'sl-SI') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sl;
    -}
    -
    -if (goog.LOCALE == 'sq') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sq;
    -}
    -
    -if (goog.LOCALE == 'sq_AL' || goog.LOCALE == 'sq-AL') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sq;
    -}
    -
    -if (goog.LOCALE == 'sr') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sr;
    -}
    -
    -if (goog.LOCALE == 'sr_Cyrl_RS' || goog.LOCALE == 'sr-Cyrl-RS') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sr;
    -}
    -
    -if (goog.LOCALE == 'sv') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sv;
    -}
    -
    -if (goog.LOCALE == 'sv_SE' || goog.LOCALE == 'sv-SE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sv;
    -}
    -
    -if (goog.LOCALE == 'sw') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sw;
    -}
    -
    -if (goog.LOCALE == 'sw_TZ' || goog.LOCALE == 'sw-TZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sw;
    -}
    -
    -if (goog.LOCALE == 'ta') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ta;
    -}
    -
    -if (goog.LOCALE == 'ta_IN' || goog.LOCALE == 'ta-IN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ta;
    -}
    -
    -if (goog.LOCALE == 'te') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_te;
    -}
    -
    -if (goog.LOCALE == 'te_IN' || goog.LOCALE == 'te-IN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_te;
    -}
    -
    -if (goog.LOCALE == 'th') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_th;
    -}
    -
    -if (goog.LOCALE == 'th_TH' || goog.LOCALE == 'th-TH') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_th;
    -}
    -
    -if (goog.LOCALE == 'tl') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_tl;
    -}
    -
    -if (goog.LOCALE == 'tr') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_tr;
    -}
    -
    -if (goog.LOCALE == 'tr_TR' || goog.LOCALE == 'tr-TR') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_tr;
    -}
    -
    -if (goog.LOCALE == 'uk') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_uk;
    -}
    -
    -if (goog.LOCALE == 'uk_UA' || goog.LOCALE == 'uk-UA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_uk;
    -}
    -
    -if (goog.LOCALE == 'ur') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ur;
    -}
    -
    -if (goog.LOCALE == 'ur_PK' || goog.LOCALE == 'ur-PK') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ur;
    -}
    -
    -if (goog.LOCALE == 'uz') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_uz;
    -}
    -
    -if (goog.LOCALE == 'uz_Latn_UZ' || goog.LOCALE == 'uz-Latn-UZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_uz;
    -}
    -
    -if (goog.LOCALE == 'vi') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_vi;
    -}
    -
    -if (goog.LOCALE == 'vi_VN' || goog.LOCALE == 'vi-VN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_vi;
    -}
    -
    -if (goog.LOCALE == 'zh') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_zh;
    -}
    -
    -if (goog.LOCALE == 'zh_CN' || goog.LOCALE == 'zh-CN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_zh;
    -}
    -
    -if (goog.LOCALE == 'zh_HK' || goog.LOCALE == 'zh-HK') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_zh_HK;
    -}
    -
    -if (goog.LOCALE == 'zh_Hans_CN' || goog.LOCALE == 'zh-Hans-CN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_zh;
    -}
    -
    -if (goog.LOCALE == 'zh_TW' || goog.LOCALE == 'zh-TW') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_zh_TW;
    -}
    -
    -if (goog.LOCALE == 'zu') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_zu;
    -}
    -
    -if (goog.LOCALE == 'zu_ZA' || goog.LOCALE == 'zu-ZA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_zu;
    -}
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/compactnumberformatsymbols_ext.js b/src/database/third_party/closure-library/closure/goog/i18n/compactnumberformatsymbols_ext.js
    deleted file mode 100644
    index 422fbc141b9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/compactnumberformatsymbols_ext.js
    +++ /dev/null
    @@ -1,30072 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
    -// implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Compact number formatting symbols.
    - *
    - * This file is autogenerated by script:
    - * http://go/generate_number_constants.py
    - * using the --for_closure flag.
    - * File generated from CLDR ver. 26
    - *
    - * This file coveres those locales that are not covered in
    - * "compactnumberformatsymbols.js".
    - *
    - * Before checkin, this file could have been manually edited. This is
    - * to incorporate changes before we could fix CLDR. All manual
    - * modification must be documented in this section, and should be
    - * removed after those changes land to CLDR.
    - */
    -
    -goog.provide('goog.i18n.CompactNumberFormatSymbolsExt');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_aa');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_aa_DJ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_aa_ER');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_aa_ET');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_af_NA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_agq');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_agq_CM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ak');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ak_GH');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_AE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_BH');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_DJ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_DZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_EG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_EH');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_ER');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_IL');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_IQ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_JO');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_KM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_KW');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_LB');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_LY');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_MA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_MR');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_OM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_PS');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_QA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_SA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_SD');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_SO');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_SS');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_SY');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_TD');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_TN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ar_YE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_as');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_as_IN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_asa');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_asa_TZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ast');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ast_ES');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_az_Cyrl');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_az_Cyrl_AZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_az_Latn');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_bas');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_bas_CM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_be');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_be_BY');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_bem');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_bem_ZM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_bez');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_bez_TZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_bm');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_bm_Latn');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_bm_Latn_ML');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_bn_IN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_bo');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_bo_CN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_bo_IN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_brx');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_brx_IN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_bs');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_bs_Cyrl');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_bs_Cyrl_BA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_bs_Latn');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_bs_Latn_BA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_cgg');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_cgg_UG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ckb');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ckb_Arab');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ckb_Arab_IQ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ckb_Arab_IR');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ckb_IQ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ckb_IR');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ckb_Latn');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ckb_Latn_IQ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_dav');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_dav_KE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_de_LI');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_dje');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_dje_NE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_dsb');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_dsb_DE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_dua');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_dua_CM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_dyo');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_dyo_SN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_dz');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_dz_BT');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ebu');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ebu_KE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ee');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ee_GH');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ee_TG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_el_CY');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_150');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_AG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_AI');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_BB');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_BE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_BM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_BS');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_BW');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_BZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_CA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_CC');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_CK');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_CM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_CX');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_DM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_ER');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_FJ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_FK');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_GD');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_GG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_GH');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_GI');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_GM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_GY');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_HK');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_IM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_JE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_JM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_KE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_KI');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_KN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_KY');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_LC');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_LR');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_LS');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_MG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_MO');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_MS');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_MT');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_MU');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_MW');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_MY');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_NA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_NF');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_NG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_NR');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_NU');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_NZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_PG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_PH');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_PK');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_PN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_RW');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_SB');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_SC');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_SD');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_SH');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_SL');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_SS');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_SX');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_SZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_TK');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_TO');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_TT');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_TV');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_TZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_UG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_VC');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_VU');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_WS');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_en_ZM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_eo');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_eo_001');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_es_AR');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_es_BO');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_es_CL');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_es_CO');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_es_CR');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_es_CU');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_es_DO');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_es_EC');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_es_GQ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_es_GT');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_es_HN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_es_MX');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_es_NI');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_es_PA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_es_PE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_es_PH');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_es_PR');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_es_PY');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_es_SV');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_es_US');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_es_UY');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_es_VE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ewo');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ewo_CM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fa_AF');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ff');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ff_CM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ff_GN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ff_MR');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ff_SN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fo');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fo_FO');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_BE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_BF');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_BI');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_BJ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_CD');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_CF');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_CG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_CH');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_CI');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_CM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_DJ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_DZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_GA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_GN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_GQ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_HT');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_KM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_LU');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_MA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_MG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_ML');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_MR');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_MU');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_NC');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_NE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_PF');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_RW');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_SC');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_SN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_SY');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_TD');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_TG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_TN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_VU');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fr_WF');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fur');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fur_IT');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fy');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_fy_NL');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_gd');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_gd_GB');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_gsw_FR');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_guz');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_guz_KE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_gv');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_gv_IM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ha');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ha_Latn');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ha_Latn_GH');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ha_Latn_NE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ha_Latn_NG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_hr_BA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_hsb');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_hsb_DE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ia');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ia_FR');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ig');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ig_NG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ii');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ii_CN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_it_CH');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_jgo');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_jgo_CM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_jmc');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_jmc_TZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_kab');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_kab_DZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_kam');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_kam_KE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_kde');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_kde_TZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_kea');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_kea_CV');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_khq');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_khq_ML');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ki');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ki_KE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_kk_Cyrl');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_kkj');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_kkj_CM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_kl');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_kl_GL');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_kln');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_kln_KE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ko_KP');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_kok');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_kok_IN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ks');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ks_Arab');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ks_Arab_IN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ksb');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ksb_TZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ksf');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ksf_CM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ksh');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ksh_DE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_kw');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_kw_GB');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ky_Cyrl');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_lag');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_lag_TZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_lb');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_lb_LU');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_lg');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_lg_UG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_lkt');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_lkt_US');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ln_AO');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ln_CF');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ln_CG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_lu');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_lu_CD');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_luo');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_luo_KE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_luy');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_luy_KE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_mas');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_mas_KE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_mas_TZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_mer');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_mer_KE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_mfe');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_mfe_MU');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_mg');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_mg_MG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_mgh');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_mgh_MZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_mgo');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_mgo_CM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_mn_Cyrl');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ms_Latn');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ms_Latn_BN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ms_Latn_SG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_mua');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_mua_CM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_naq');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_naq_NA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_nd');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_nd_ZW');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ne_IN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_nl_AW');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_nl_BE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_nl_BQ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_nl_CW');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_nl_SR');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_nl_SX');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_nmg');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_nmg_CM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_nn');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_nn_NO');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_nnh');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_nnh_CM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_nr');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_nr_ZA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_nso');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_nso_ZA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_nus');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_nus_SD');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_nyn');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_nyn_UG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_om');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_om_ET');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_om_KE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_os');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_os_GE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_os_RU');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_pa_Arab');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_pa_Arab_PK');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_pa_Guru');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ps');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ps_AF');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_pt_AO');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_pt_CV');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_pt_GW');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_pt_MO');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_pt_MZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_pt_ST');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_pt_TL');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_qu');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_qu_BO');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_qu_EC');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_qu_PE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_rm');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_rm_CH');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_rn');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_rn_BI');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ro_MD');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_rof');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_rof_TZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ru_BY');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ru_KG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ru_KZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ru_MD');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ru_UA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_rw');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_rw_RW');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_rwk');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_rwk_TZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sah');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sah_RU');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_saq');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_saq_KE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sbp');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sbp_TZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_se');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_se_FI');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_se_NO');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_se_SE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_seh');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_seh_MZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ses');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ses_ML');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sg');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sg_CF');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_shi');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_shi_Latn');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_shi_Latn_MA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_shi_Tfng');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_shi_Tfng_MA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_smn');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_smn_FI');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sn');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sn_ZW');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_so');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_so_DJ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_so_ET');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_so_KE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_so_SO');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sq_MK');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sq_XK');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sr_Cyrl');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sr_Cyrl_BA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sr_Cyrl_ME');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sr_Cyrl_XK');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sr_Latn');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sr_Latn_BA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sr_Latn_ME');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sr_Latn_RS');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sr_Latn_XK');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ss');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ss_SZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ss_ZA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ssy');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ssy_ER');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sv_AX');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sv_FI');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sw_KE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_sw_UG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_swc');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_swc_CD');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ta_LK');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ta_MY');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ta_SG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_teo');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_teo_KE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_teo_UG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ti');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ti_ER');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ti_ET');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_tn');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_tn_BW');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_tn_ZA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_to');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_to_TO');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_tr_CY');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ts');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ts_ZA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_twq');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_twq_NE');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_tzm');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_tzm_Latn');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_tzm_Latn_MA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ug');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ug_Arab');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ug_Arab_CN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ur_IN');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_uz_Arab');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_uz_Arab_AF');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_uz_Cyrl');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_uz_Cyrl_UZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_uz_Latn');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_vai');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_vai_Latn');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_vai_Latn_LR');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_vai_Vaii');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_vai_Vaii_LR');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ve');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_ve_ZA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_vo');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_vo_001');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_vun');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_vun_TZ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_wae');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_wae_CH');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_xog');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_xog_UG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_yav');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_yav_CM');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_yi');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_yi_001');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_yo');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_yo_BJ');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_yo_NG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_zgh');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_zgh_MA');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_zh_Hans');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_zh_Hans_HK');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_zh_Hans_MO');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_zh_Hans_SG');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_zh_Hant');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_zh_Hant_HK');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_zh_Hant_MO');
    -goog.provide('goog.i18n.CompactNumberFormatSymbols_zh_Hant_TW');
    -
    -
    -/**
    - * Compact number formatting symbols for locale aa.
    - */
    -goog.i18n.CompactNumberFormatSymbols_aa = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale aa_DJ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_aa_DJ = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale aa_ER.
    - */
    -goog.i18n.CompactNumberFormatSymbols_aa_ER = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale aa_ET.
    - */
    -goog.i18n.CompactNumberFormatSymbols_aa_ET =
    -    goog.i18n.CompactNumberFormatSymbols_aa;
    -
    -
    -/**
    - * Compact number formatting symbols for locale af_NA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_af_NA = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '0'
    -    },
    -    '100000': {
    -      'other': '0'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0m'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0m'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0m'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mjd'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mjd'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mjd'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 duisend'
    -    },
    -    '10000': {
    -      'other': '00 duisend'
    -    },
    -    '100000': {
    -      'other': '000 duisend'
    -    },
    -    '1000000': {
    -      'other': '0 miljoen'
    -    },
    -    '10000000': {
    -      'other': '00 miljoen'
    -    },
    -    '100000000': {
    -      'other': '000 miljoen'
    -    },
    -    '1000000000': {
    -      'other': '0 miljard'
    -    },
    -    '10000000000': {
    -      'other': '00 miljard'
    -    },
    -    '100000000000': {
    -      'other': '000 miljard'
    -    },
    -    '1000000000000': {
    -      'other': '0 biljoen'
    -    },
    -    '10000000000000': {
    -      'other': '00 biljoen'
    -    },
    -    '100000000000000': {
    -      'other': '000 biljoen'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale agq.
    - */
    -goog.i18n.CompactNumberFormatSymbols_agq = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale agq_CM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_agq_CM =
    -    goog.i18n.CompactNumberFormatSymbols_agq;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ak.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ak = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ak_GH.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ak_GH =
    -    goog.i18n.CompactNumberFormatSymbols_ak;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ar_AE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ar_AE = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00 \u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000 \u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ar_BH.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ar_BH = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00 \u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000 \u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ar_DJ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ar_DJ = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00 \u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000 \u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ar_DZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ar_DZ = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00 \u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000 \u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ar_EG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ar_EG = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00 \u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000 \u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ar_EH.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ar_EH = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00 \u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000 \u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ar_ER.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ar_ER = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00 \u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000 \u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ar_IL.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ar_IL = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00 \u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000 \u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ar_IQ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ar_IQ = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00 \u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000 \u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ar_JO.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ar_JO = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00 \u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000 \u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ar_KM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ar_KM = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00 \u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000 \u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ar_KW.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ar_KW = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00 \u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000 \u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ar_LB.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ar_LB = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00 \u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000 \u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ar_LY.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ar_LY = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00 \u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000 \u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ar_MA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ar_MA = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00 \u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000 \u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ar_MR.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ar_MR = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00 \u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000 \u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ar_OM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ar_OM = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00 \u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000 \u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ar_PS.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ar_PS = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00 \u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000 \u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ar_QA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ar_QA = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00 \u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000 \u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ar_SA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ar_SA = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00 \u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000 \u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ar_SD.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ar_SD = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00 \u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000 \u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ar_SO.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ar_SO = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00 \u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000 \u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ar_SS.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ar_SS = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00 \u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000 \u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ar_SY.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ar_SY = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00 \u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000 \u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ar_TD.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ar_TD = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00 \u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000 \u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ar_TN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ar_TN = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00 \u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000 \u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ar_YE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ar_YE = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u0645\u0644\u064A\u0648'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u0628\u0644\u064A\u0648'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u062A\u0631\u0644\u064A\u0648'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0623\u0644\u0641'
    -    },
    -    '10000': {
    -      'other': '00 \u0623\u0644\u0641'
    -    },
    -    '100000': {
    -      'other': '000 \u0623\u0644\u0641'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0628\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0631\u064A\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale as.
    - */
    -goog.i18n.CompactNumberFormatSymbols_as = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale as_IN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_as_IN =
    -    goog.i18n.CompactNumberFormatSymbols_as;
    -
    -
    -/**
    - * Compact number formatting symbols for locale asa.
    - */
    -goog.i18n.CompactNumberFormatSymbols_asa = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale asa_TZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_asa_TZ =
    -    goog.i18n.CompactNumberFormatSymbols_asa;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ast.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ast = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ast_ES.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ast_ES =
    -    goog.i18n.CompactNumberFormatSymbols_ast;
    -
    -
    -/**
    - * Compact number formatting symbols for locale az_Cyrl.
    - */
    -goog.i18n.CompactNumberFormatSymbols_az_Cyrl = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale az_Cyrl_AZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_az_Cyrl_AZ = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale az_Latn.
    - */
    -goog.i18n.CompactNumberFormatSymbols_az_Latn = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale bas.
    - */
    -goog.i18n.CompactNumberFormatSymbols_bas = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale bas_CM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_bas_CM =
    -    goog.i18n.CompactNumberFormatSymbols_bas;
    -
    -
    -/**
    - * Compact number formatting symbols for locale be.
    - */
    -goog.i18n.CompactNumberFormatSymbols_be = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale be_BY.
    - */
    -goog.i18n.CompactNumberFormatSymbols_be_BY =
    -    goog.i18n.CompactNumberFormatSymbols_be;
    -
    -
    -/**
    - * Compact number formatting symbols for locale bem.
    - */
    -goog.i18n.CompactNumberFormatSymbols_bem = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale bem_ZM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_bem_ZM =
    -    goog.i18n.CompactNumberFormatSymbols_bem;
    -
    -
    -/**
    - * Compact number formatting symbols for locale bez.
    - */
    -goog.i18n.CompactNumberFormatSymbols_bez = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale bez_TZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_bez_TZ =
    -    goog.i18n.CompactNumberFormatSymbols_bez;
    -
    -
    -/**
    - * Compact number formatting symbols for locale bm.
    - */
    -goog.i18n.CompactNumberFormatSymbols_bm = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale bm_Latn.
    - */
    -goog.i18n.CompactNumberFormatSymbols_bm_Latn = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale bm_Latn_ML.
    - */
    -goog.i18n.CompactNumberFormatSymbols_bm_Latn_ML =
    -    goog.i18n.CompactNumberFormatSymbols_bm;
    -
    -
    -/**
    - * Compact number formatting symbols for locale bn_IN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_bn_IN = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u09B9\u09BE\u099C\u09BE\u09B0'
    -    },
    -    '10000': {
    -      'other': '00 \u09B9\u09BE\u099C\u09BE\u09B0'
    -    },
    -    '100000': {
    -      'other': '000 \u09B9\u09BE\u099C\u09BE\u09B0'
    -    },
    -    '1000000': {
    -      'other': '0 \u09AE\u09BF\u09B2\u09BF\u09AF\u09BC\u09A8'
    -    },
    -    '10000000': {
    -      'other': '00 \u09AE\u09BF\u09B2\u09BF\u09AF\u09BC\u09A8'
    -    },
    -    '100000000': {
    -      'other': '000 \u09AE\u09BF\u09B2\u09BF\u09AF\u09BC\u09A8'
    -    },
    -    '1000000000': {
    -      'other': '0 \u09AC\u09BF\u09B2\u09BF\u09AF\u09BC\u09A8'
    -    },
    -    '10000000000': {
    -      'other': '00 \u09AC\u09BF\u09B2\u09BF\u09AF\u09BC\u09A8'
    -    },
    -    '100000000000': {
    -      'other': '000 \u09AC\u09BF\u09B2\u09BF\u09AF\u09BC\u09A8'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u099F\u09CD\u09B0\u09BF\u09B2\u09BF\u09AF\u09BC\u09A8'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u099F\u09CD\u09B0\u09BF\u09B2\u09BF\u09AF\u09BC\u09A8'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u099F\u09CD\u09B0\u09BF\u09B2\u09BF\u09AF\u09BC\u09A8'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale bo.
    - */
    -goog.i18n.CompactNumberFormatSymbols_bo = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale bo_CN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_bo_CN =
    -    goog.i18n.CompactNumberFormatSymbols_bo;
    -
    -
    -/**
    - * Compact number formatting symbols for locale bo_IN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_bo_IN = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale brx.
    - */
    -goog.i18n.CompactNumberFormatSymbols_brx = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale brx_IN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_brx_IN =
    -    goog.i18n.CompactNumberFormatSymbols_brx;
    -
    -
    -/**
    - * Compact number formatting symbols for locale bs.
    - */
    -goog.i18n.CompactNumberFormatSymbols_bs = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0hilj.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0hilj.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0hilj.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mil.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mil.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mil.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mlr.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mlr.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mlr.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bil.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bil.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bil.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 hiljada'
    -    },
    -    '10000': {
    -      'other': '00 hiljada'
    -    },
    -    '100000': {
    -      'other': '000 hiljada'
    -    },
    -    '1000000': {
    -      'other': '0 miliona'
    -    },
    -    '10000000': {
    -      'other': '00 miliona'
    -    },
    -    '100000000': {
    -      'other': '000 miliona'
    -    },
    -    '1000000000': {
    -      'other': '0 milijardi'
    -    },
    -    '10000000000': {
    -      'other': '00 milijardi'
    -    },
    -    '100000000000': {
    -      'other': '000 milijardi'
    -    },
    -    '1000000000000': {
    -      'other': '0 biliona'
    -    },
    -    '10000000000000': {
    -      'other': '00 biliona'
    -    },
    -    '100000000000000': {
    -      'other': '000 biliona'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale bs_Cyrl.
    - */
    -goog.i18n.CompactNumberFormatSymbols_bs_Cyrl = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0445\u0438\u0459'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0445\u0438\u0459'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u043C\u0438\u043B'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u043C\u0438\u043B'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u043C\u0438\u043B'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u0431\u0438\u043B'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u0431\u0438\u043B'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u0431\u0438\u043B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '00 \u0445\u0438\u0459'
    -    },
    -    '100000': {
    -      'other': '000 \u0445\u0438\u0459'
    -    },
    -    '1000000': {
    -      'other': '0 \u043C\u0438\u043B'
    -    },
    -    '10000000': {
    -      'other': '00 \u043C\u0438\u043B'
    -    },
    -    '100000000': {
    -      'other': '000 \u043C\u0438\u043B'
    -    },
    -    '1000000000': {
    -      'other': '0 \u043C\u043B\u0440\u0434'
    -    },
    -    '10000000000': {
    -      'other': '00 \u043C\u043B\u0440\u0434'
    -    },
    -    '100000000000': {
    -      'other': '000 \u043C\u043B\u0440\u0434'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0431\u0438\u043B'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0431\u0438\u043B'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0431\u0438\u043B'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale bs_Cyrl_BA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_bs_Cyrl_BA = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0445\u0438\u0459'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0445\u0438\u0459'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u043C\u0438\u043B'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u043C\u0438\u043B'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u043C\u0438\u043B'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u0431\u0438\u043B'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u0431\u0438\u043B'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u0431\u0438\u043B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '00 \u0445\u0438\u0459'
    -    },
    -    '100000': {
    -      'other': '000 \u0445\u0438\u0459'
    -    },
    -    '1000000': {
    -      'other': '0 \u043C\u0438\u043B'
    -    },
    -    '10000000': {
    -      'other': '00 \u043C\u0438\u043B'
    -    },
    -    '100000000': {
    -      'other': '000 \u043C\u0438\u043B'
    -    },
    -    '1000000000': {
    -      'other': '0 \u043C\u043B\u0440\u0434'
    -    },
    -    '10000000000': {
    -      'other': '00 \u043C\u043B\u0440\u0434'
    -    },
    -    '100000000000': {
    -      'other': '000 \u043C\u043B\u0440\u0434'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0431\u0438\u043B'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0431\u0438\u043B'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0431\u0438\u043B'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale bs_Latn.
    - */
    -goog.i18n.CompactNumberFormatSymbols_bs_Latn = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0hilj.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0hilj.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0hilj.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mil.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mil.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mil.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mlr.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mlr.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mlr.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bil.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bil.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bil.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 hiljada'
    -    },
    -    '10000': {
    -      'other': '00 hiljada'
    -    },
    -    '100000': {
    -      'other': '000 hiljada'
    -    },
    -    '1000000': {
    -      'other': '0 miliona'
    -    },
    -    '10000000': {
    -      'other': '00 miliona'
    -    },
    -    '100000000': {
    -      'other': '000 miliona'
    -    },
    -    '1000000000': {
    -      'other': '0 milijardi'
    -    },
    -    '10000000000': {
    -      'other': '00 milijardi'
    -    },
    -    '100000000000': {
    -      'other': '000 milijardi'
    -    },
    -    '1000000000000': {
    -      'other': '0 biliona'
    -    },
    -    '10000000000000': {
    -      'other': '00 biliona'
    -    },
    -    '100000000000000': {
    -      'other': '000 biliona'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale bs_Latn_BA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_bs_Latn_BA =
    -    goog.i18n.CompactNumberFormatSymbols_bs;
    -
    -
    -/**
    - * Compact number formatting symbols for locale cgg.
    - */
    -goog.i18n.CompactNumberFormatSymbols_cgg = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale cgg_UG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_cgg_UG =
    -    goog.i18n.CompactNumberFormatSymbols_cgg;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ckb.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ckb = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ckb_Arab.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ckb_Arab = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ckb_Arab_IQ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ckb_Arab_IQ =
    -    goog.i18n.CompactNumberFormatSymbols_ckb;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ckb_Arab_IR.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ckb_Arab_IR = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ckb_IQ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ckb_IQ =
    -    goog.i18n.CompactNumberFormatSymbols_ckb;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ckb_IR.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ckb_IR = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ckb_Latn.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ckb_Latn = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ckb_Latn_IQ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ckb_Latn_IQ =
    -    goog.i18n.CompactNumberFormatSymbols_ckb;
    -
    -
    -/**
    - * Compact number formatting symbols for locale dav.
    - */
    -goog.i18n.CompactNumberFormatSymbols_dav = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale dav_KE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_dav_KE =
    -    goog.i18n.CompactNumberFormatSymbols_dav;
    -
    -
    -/**
    - * Compact number formatting symbols for locale de_LI.
    - */
    -goog.i18n.CompactNumberFormatSymbols_de_LI = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0Tsd.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0Tsd.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0Tsd.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0Mio'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0Mio'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0Mio'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Mrd'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Mrd'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Mrd'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bio.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bio.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bio.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 Tausend'
    -    },
    -    '10000': {
    -      'other': '00 Tausend'
    -    },
    -    '100000': {
    -      'other': '000 Tausend'
    -    },
    -    '1000000': {
    -      'other': '0 Millionen'
    -    },
    -    '10000000': {
    -      'other': '00 Millionen'
    -    },
    -    '100000000': {
    -      'other': '000 Millionen'
    -    },
    -    '1000000000': {
    -      'other': '0 Milliarden'
    -    },
    -    '10000000000': {
    -      'other': '00 Milliarden'
    -    },
    -    '100000000000': {
    -      'other': '000 Milliarden'
    -    },
    -    '1000000000000': {
    -      'other': '0 Billionen'
    -    },
    -    '10000000000000': {
    -      'other': '00 Billionen'
    -    },
    -    '100000000000000': {
    -      'other': '000 Billionen'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale dje.
    - */
    -goog.i18n.CompactNumberFormatSymbols_dje = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale dje_NE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_dje_NE =
    -    goog.i18n.CompactNumberFormatSymbols_dje;
    -
    -
    -/**
    - * Compact number formatting symbols for locale dsb.
    - */
    -goog.i18n.CompactNumberFormatSymbols_dsb = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0tys.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0tys.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0tys.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mio.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mio.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mio.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mrd.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mrd.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mrd.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bil.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bil.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bil.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 tysac'
    -    },
    -    '10000': {
    -      'other': '00 tysac'
    -    },
    -    '100000': {
    -      'other': '000 tysac'
    -    },
    -    '1000000': {
    -      'other': '0 milionow'
    -    },
    -    '10000000': {
    -      'other': '00 milionow'
    -    },
    -    '100000000': {
    -      'other': '000 milionow'
    -    },
    -    '1000000000': {
    -      'other': '0 miliardow'
    -    },
    -    '10000000000': {
    -      'other': '00 miliardow'
    -    },
    -    '100000000000': {
    -      'other': '000 miliardow'
    -    },
    -    '1000000000000': {
    -      'other': '0 bilionow'
    -    },
    -    '10000000000000': {
    -      'other': '00 bilionow'
    -    },
    -    '100000000000000': {
    -      'other': '000 bilionow'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale dsb_DE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_dsb_DE =
    -    goog.i18n.CompactNumberFormatSymbols_dsb;
    -
    -
    -/**
    - * Compact number formatting symbols for locale dua.
    - */
    -goog.i18n.CompactNumberFormatSymbols_dua = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale dua_CM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_dua_CM =
    -    goog.i18n.CompactNumberFormatSymbols_dua;
    -
    -
    -/**
    - * Compact number formatting symbols for locale dyo.
    - */
    -goog.i18n.CompactNumberFormatSymbols_dyo = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale dyo_SN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_dyo_SN =
    -    goog.i18n.CompactNumberFormatSymbols_dyo;
    -
    -
    -/**
    - * Compact number formatting symbols for locale dz.
    - */
    -goog.i18n.CompactNumberFormatSymbols_dz = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '\u0F66\u0F9F\u0F7C\u0F44\u0F0B\u0F55\u0FB2\u0F42 0'
    -    },
    -    '10000': {
    -      'other': '\u0F41\u0FB2\u0F72\u0F0B\u0F55\u0FB2\u0F42 0'
    -    },
    -    '100000': {
    -      'other': '\u0F60\u0F56\u0F74\u0F58\u0F0B\u0F55\u0FB2\u0F42 0'
    -    },
    -    '1000000': {
    -      'other': '\u0F66\u0F0B\u0F61\u0F0B 0'
    -    },
    -    '10000000': {
    -      'other': '\u0F56\u0FB1\u0F7A\u0F0B\u0F56\u0F0B 0'
    -    },
    -    '100000000': {
    -      'other': '\u0F51\u0F74\u0F44\u0F0B\u0F55\u0FB1\u0F74\u0F62\u0F0B 0'
    -    },
    -    '1000000000': {
    -      'other': '\u0F51\u0F74\u0F44\u0F0B\u0F55\u0FB1\u0F74\u0F62\u0F0B 00'
    -    },
    -    '10000000000': {
    -      'other': '\u0F51\u0F74\u0F44\u0F0B\u0F55\u0FB1\u0F74\u0F62\u0F0B\u0F56\u0F62\u0F92\u0FB1\u0F0B 0'
    -    },
    -    '100000000000': {
    -      'other': '\u0F51\u0F74\u0F44\u0F0B\u0F55\u0FB1\u0F74\u0F62\u0F0B\u0F66\u0F9F\u0F7C\u0F44 0'
    -    },
    -    '1000000000000': {
    -      'other': '\u0F51\u0F74\u0F44\u0F0B\u0F55\u0FB1\u0F74\u0F62\u0F0B\u0F41\u0FB2\u0F72\u0F0B 0'
    -    },
    -    '10000000000000': {
    -      'other': '\u0F51\u0F74\u0F44\u0F0B\u0F55\u0FB1\u0F74\u0F62\u0F0B\u0F60\u0F56\u0F74\u0F58\u0F0B 0'
    -    },
    -    '100000000000000': {
    -      'other': '\u0F51\u0F74\u0F44\u0F0B\u0F55\u0FB1\u0F74\u0F62\u0F0B\u0F66\u0F0B\u0F61\u0F0B 0'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale dz_BT.
    - */
    -goog.i18n.CompactNumberFormatSymbols_dz_BT =
    -    goog.i18n.CompactNumberFormatSymbols_dz;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ebu.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ebu = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ebu_KE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ebu_KE =
    -    goog.i18n.CompactNumberFormatSymbols_ebu;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ee.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ee = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0000M'
    -    },
    -    '10000000000': {
    -      'other': '00000M'
    -    },
    -    '100000000000': {
    -      'other': '000000M'
    -    },
    -    '1000000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000000': {
    -      'other': '000B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': 'akpe 0'
    -    },
    -    '10000': {
    -      'other': 'akpe 00'
    -    },
    -    '100000': {
    -      'other': 'akpe 000'
    -    },
    -    '1000000': {
    -      'other': 'mili\u0254n 0'
    -    },
    -    '10000000': {
    -      'other': 'mili\u0254n 00'
    -    },
    -    '100000000': {
    -      'other': 'mili\u0254n 000'
    -    },
    -    '1000000000': {
    -      'other': 'mili\u0254n 0000'
    -    },
    -    '10000000000': {
    -      'other': 'mili\u0254n 00000'
    -    },
    -    '100000000000': {
    -      'other': 'mili\u0254n 000000'
    -    },
    -    '1000000000000': {
    -      'other': 'bili\u0254n 0'
    -    },
    -    '10000000000000': {
    -      'other': 'bili\u0254n 00'
    -    },
    -    '100000000000000': {
    -      'other': 'bili\u0254n 000'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ee_GH.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ee_GH =
    -    goog.i18n.CompactNumberFormatSymbols_ee;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ee_TG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ee_TG = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0000M'
    -    },
    -    '10000000000': {
    -      'other': '00000M'
    -    },
    -    '100000000000': {
    -      'other': '000000M'
    -    },
    -    '1000000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000000': {
    -      'other': '000B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': 'akpe 0'
    -    },
    -    '10000': {
    -      'other': 'akpe 00'
    -    },
    -    '100000': {
    -      'other': 'akpe 000'
    -    },
    -    '1000000': {
    -      'other': 'mili\u0254n 0'
    -    },
    -    '10000000': {
    -      'other': 'mili\u0254n 00'
    -    },
    -    '100000000': {
    -      'other': 'mili\u0254n 000'
    -    },
    -    '1000000000': {
    -      'other': 'mili\u0254n 0000'
    -    },
    -    '10000000000': {
    -      'other': 'mili\u0254n 00000'
    -    },
    -    '100000000000': {
    -      'other': 'mili\u0254n 000000'
    -    },
    -    '1000000000000': {
    -      'other': 'bili\u0254n 0'
    -    },
    -    '10000000000000': {
    -      'other': 'bili\u0254n 00'
    -    },
    -    '100000000000000': {
    -      'other': 'bili\u0254n 000'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale el_CY.
    - */
    -goog.i18n.CompactNumberFormatSymbols_el_CY = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u03C7\u03B9\u03BB.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u03C7\u03B9\u03BB.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u03C7\u03B9\u03BB.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u03B5\u03BA.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u03B5\u03BA.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u03B5\u03BA.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u03B4\u03B9\u03C3.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u03B4\u03B9\u03C3.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u03B4\u03B9\u03C3.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u03C4\u03C1\u03B9\u03C3.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u03C4\u03C1\u03B9\u03C3.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u03C4\u03C1\u03B9\u03C3.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u03C7\u03B9\u03BB\u03B9\u03AC\u03B4\u03B5\u03C2'
    -    },
    -    '10000': {
    -      'other': '00 \u03C7\u03B9\u03BB\u03B9\u03AC\u03B4\u03B5\u03C2'
    -    },
    -    '100000': {
    -      'other': '000 \u03C7\u03B9\u03BB\u03B9\u03AC\u03B4\u03B5\u03C2'
    -    },
    -    '1000000': {
    -      'other': '0 \u03B5\u03BA\u03B1\u03C4\u03BF\u03BC\u03BC\u03CD\u03C1\u03B9\u03B1'
    -    },
    -    '10000000': {
    -      'other': '00 \u03B5\u03BA\u03B1\u03C4\u03BF\u03BC\u03BC\u03CD\u03C1\u03B9\u03B1'
    -    },
    -    '100000000': {
    -      'other': '000 \u03B5\u03BA\u03B1\u03C4\u03BF\u03BC\u03BC\u03CD\u03C1\u03B9\u03B1'
    -    },
    -    '1000000000': {
    -      'other': '0 \u03B4\u03B9\u03C3\u03B5\u03BA\u03B1\u03C4\u03BF\u03BC\u03BC\u03CD\u03C1\u03B9\u03B1'
    -    },
    -    '10000000000': {
    -      'other': '00 \u03B4\u03B9\u03C3\u03B5\u03BA\u03B1\u03C4\u03BF\u03BC\u03BC\u03CD\u03C1\u03B9\u03B1'
    -    },
    -    '100000000000': {
    -      'other': '000 \u03B4\u03B9\u03C3\u03B5\u03BA\u03B1\u03C4\u03BF\u03BC\u03BC\u03CD\u03C1\u03B9\u03B1'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u03C4\u03C1\u03B9\u03C3\u03B5\u03BA\u03B1\u03C4\u03BF\u03BC\u03BC\u03CD\u03C1\u03B9\u03B1'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u03C4\u03C1\u03B9\u03C3\u03B5\u03BA\u03B1\u03C4\u03BF\u03BC\u03BC\u03CD\u03C1\u03B9\u03B1'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u03C4\u03C1\u03B9\u03C3\u03B5\u03BA\u03B1\u03C4\u03BF\u03BC\u03BC\u03CD\u03C1\u03B9\u03B1'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_150.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_150 = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_AG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_AG = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_AI.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_AI = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_BB.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_BB = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_BE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_BE = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_BM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_BM = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_BS.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_BS = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_BW.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_BW = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_BZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_BZ = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_CA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_CA = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_CC.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_CC = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_CK.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_CK = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_CM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_CM = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_CX.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_CX = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_DM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_DM = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_ER.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_ER = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_FJ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_FJ = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_FK.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_FK = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_GD.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_GD = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_GG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_GG = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_GH.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_GH = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_GI.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_GI = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_GM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_GM = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_GY.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_GY = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_HK.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_HK = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_IM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_IM = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_JE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_JE = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_JM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_JM = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_KE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_KE = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_KI.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_KI = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_KN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_KN = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_KY.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_KY = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_LC.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_LC = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_LR.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_LR = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_LS.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_LS = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_MG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_MG = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_MO.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_MO = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_MS.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_MS = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_MT.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_MT = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_MU.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_MU = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_MW.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_MW = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_MY.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_MY = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_NA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_NA = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_NF.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_NF = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_NG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_NG = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_NR.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_NR = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_NU.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_NU = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_NZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_NZ = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_PG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_PG = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_PH.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_PH = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_PK.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_PK = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_PN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_PN = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_RW.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_RW = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_SB.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_SB = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_SC.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_SC = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_SD.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_SD = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_SH.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_SH = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_SL.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_SL = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_SS.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_SS = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_SX.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_SX = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_SZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_SZ = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_TK.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_TK = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_TO.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_TO = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_TT.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_TT = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_TV.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_TV = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_TZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_TZ = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_UG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_UG = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_VC.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_VC = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_VU.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_VU = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_WS.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_WS = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale en_ZM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_en_ZM = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 thousand'
    -    },
    -    '10000': {
    -      'other': '00 thousand'
    -    },
    -    '100000': {
    -      'other': '000 thousand'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 billion'
    -    },
    -    '10000000000': {
    -      'other': '00 billion'
    -    },
    -    '100000000000': {
    -      'other': '000 billion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale eo.
    - */
    -goog.i18n.CompactNumberFormatSymbols_eo = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale eo_001.
    - */
    -goog.i18n.CompactNumberFormatSymbols_eo_001 =
    -    goog.i18n.CompactNumberFormatSymbols_eo;
    -
    -
    -/**
    - * Compact number formatting symbols for locale es_AR.
    - */
    -goog.i18n.CompactNumberFormatSymbols_es_AR = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '00k'
    -    },
    -    '100000': {
    -      'other': '000k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0k\u00A0M'
    -    },
    -    '10000000000': {
    -      'other': '00k\u00A0M'
    -    },
    -    '100000000000': {
    -      'other': '000k\u00A0M'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0B'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0B'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 millones'
    -    },
    -    '10000000': {
    -      'other': '00 millones'
    -    },
    -    '100000000': {
    -      'other': '000 millones'
    -    },
    -    '1000000000': {
    -      'other': '0 mil millones'
    -    },
    -    '10000000000': {
    -      'other': '00 mil millones'
    -    },
    -    '100000000000': {
    -      'other': '000 mil millones'
    -    },
    -    '1000000000000': {
    -      'other': '0 billones'
    -    },
    -    '10000000000000': {
    -      'other': '00 billones'
    -    },
    -    '100000000000000': {
    -      'other': '000 billones'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale es_BO.
    - */
    -goog.i18n.CompactNumberFormatSymbols_es_BO = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '00k'
    -    },
    -    '100000': {
    -      'other': '000k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0k\u00A0M'
    -    },
    -    '10000000000': {
    -      'other': '00k\u00A0M'
    -    },
    -    '100000000000': {
    -      'other': '000k\u00A0M'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0B'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0B'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 millones'
    -    },
    -    '10000000': {
    -      'other': '00 millones'
    -    },
    -    '100000000': {
    -      'other': '000 millones'
    -    },
    -    '1000000000': {
    -      'other': '0 mil millones'
    -    },
    -    '10000000000': {
    -      'other': '00 mil millones'
    -    },
    -    '100000000000': {
    -      'other': '000 mil millones'
    -    },
    -    '1000000000000': {
    -      'other': '0 billones'
    -    },
    -    '10000000000000': {
    -      'other': '00 billones'
    -    },
    -    '100000000000000': {
    -      'other': '000 billones'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale es_CL.
    - */
    -goog.i18n.CompactNumberFormatSymbols_es_CL = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '00k'
    -    },
    -    '100000': {
    -      'other': '000k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0k\u00A0M'
    -    },
    -    '10000000000': {
    -      'other': '00k\u00A0M'
    -    },
    -    '100000000000': {
    -      'other': '000k\u00A0M'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0B'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0B'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 millones'
    -    },
    -    '10000000': {
    -      'other': '00 millones'
    -    },
    -    '100000000': {
    -      'other': '000 millones'
    -    },
    -    '1000000000': {
    -      'other': '0 mil millones'
    -    },
    -    '10000000000': {
    -      'other': '00 mil millones'
    -    },
    -    '100000000000': {
    -      'other': '000 mil millones'
    -    },
    -    '1000000000000': {
    -      'other': '0 billones'
    -    },
    -    '10000000000000': {
    -      'other': '00 billones'
    -    },
    -    '100000000000000': {
    -      'other': '000 billones'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale es_CO.
    - */
    -goog.i18n.CompactNumberFormatSymbols_es_CO = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '00k'
    -    },
    -    '100000': {
    -      'other': '000k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0k\u00A0M'
    -    },
    -    '10000000000': {
    -      'other': '00k\u00A0M'
    -    },
    -    '100000000000': {
    -      'other': '000k\u00A0M'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0B'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0B'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 millones'
    -    },
    -    '10000000': {
    -      'other': '00 millones'
    -    },
    -    '100000000': {
    -      'other': '000 millones'
    -    },
    -    '1000000000': {
    -      'other': '0 mil millones'
    -    },
    -    '10000000000': {
    -      'other': '00 mil millones'
    -    },
    -    '100000000000': {
    -      'other': '000 mil millones'
    -    },
    -    '1000000000000': {
    -      'other': '0 billones'
    -    },
    -    '10000000000000': {
    -      'other': '00 billones'
    -    },
    -    '100000000000000': {
    -      'other': '000 billones'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale es_CR.
    - */
    -goog.i18n.CompactNumberFormatSymbols_es_CR = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '00k'
    -    },
    -    '100000': {
    -      'other': '000k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0k\u00A0M'
    -    },
    -    '10000000000': {
    -      'other': '00k\u00A0M'
    -    },
    -    '100000000000': {
    -      'other': '000k\u00A0M'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0B'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0B'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 millones'
    -    },
    -    '10000000': {
    -      'other': '00 millones'
    -    },
    -    '100000000': {
    -      'other': '000 millones'
    -    },
    -    '1000000000': {
    -      'other': '0 mil millones'
    -    },
    -    '10000000000': {
    -      'other': '00 mil millones'
    -    },
    -    '100000000000': {
    -      'other': '000 mil millones'
    -    },
    -    '1000000000000': {
    -      'other': '0 billones'
    -    },
    -    '10000000000000': {
    -      'other': '00 billones'
    -    },
    -    '100000000000000': {
    -      'other': '000 billones'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale es_CU.
    - */
    -goog.i18n.CompactNumberFormatSymbols_es_CU = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '00k'
    -    },
    -    '100000': {
    -      'other': '000k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0k\u00A0M'
    -    },
    -    '10000000000': {
    -      'other': '00k\u00A0M'
    -    },
    -    '100000000000': {
    -      'other': '000k\u00A0M'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0B'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0B'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 millones'
    -    },
    -    '10000000': {
    -      'other': '00 millones'
    -    },
    -    '100000000': {
    -      'other': '000 millones'
    -    },
    -    '1000000000': {
    -      'other': '0 mil millones'
    -    },
    -    '10000000000': {
    -      'other': '00 mil millones'
    -    },
    -    '100000000000': {
    -      'other': '000 mil millones'
    -    },
    -    '1000000000000': {
    -      'other': '0 billones'
    -    },
    -    '10000000000000': {
    -      'other': '00 billones'
    -    },
    -    '100000000000000': {
    -      'other': '000 billones'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale es_DO.
    - */
    -goog.i18n.CompactNumberFormatSymbols_es_DO = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '00k'
    -    },
    -    '100000': {
    -      'other': '000k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0k\u00A0M'
    -    },
    -    '10000000000': {
    -      'other': '00k\u00A0M'
    -    },
    -    '100000000000': {
    -      'other': '000k\u00A0M'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0B'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0B'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 millones'
    -    },
    -    '10000000': {
    -      'other': '00 millones'
    -    },
    -    '100000000': {
    -      'other': '000 millones'
    -    },
    -    '1000000000': {
    -      'other': '0 mil millones'
    -    },
    -    '10000000000': {
    -      'other': '00 mil millones'
    -    },
    -    '100000000000': {
    -      'other': '000 mil millones'
    -    },
    -    '1000000000000': {
    -      'other': '0 billones'
    -    },
    -    '10000000000000': {
    -      'other': '00 billones'
    -    },
    -    '100000000000000': {
    -      'other': '000 billones'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale es_EC.
    - */
    -goog.i18n.CompactNumberFormatSymbols_es_EC = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '00k'
    -    },
    -    '100000': {
    -      'other': '000k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0k\u00A0M'
    -    },
    -    '10000000000': {
    -      'other': '00k\u00A0M'
    -    },
    -    '100000000000': {
    -      'other': '000k\u00A0M'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0B'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0B'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 millones'
    -    },
    -    '10000000': {
    -      'other': '00 millones'
    -    },
    -    '100000000': {
    -      'other': '000 millones'
    -    },
    -    '1000000000': {
    -      'other': '0 mil millones'
    -    },
    -    '10000000000': {
    -      'other': '00 mil millones'
    -    },
    -    '100000000000': {
    -      'other': '000 mil millones'
    -    },
    -    '1000000000000': {
    -      'other': '0 billones'
    -    },
    -    '10000000000000': {
    -      'other': '00 billones'
    -    },
    -    '100000000000000': {
    -      'other': '000 billones'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale es_GQ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_es_GQ = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0000M'
    -    },
    -    '10000000000': {
    -      'other': '00MRD'
    -    },
    -    '100000000000': {
    -      'other': '000MRD'
    -    },
    -    '1000000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000000': {
    -      'other': '000B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 millones'
    -    },
    -    '10000000': {
    -      'other': '00 millones'
    -    },
    -    '100000000': {
    -      'other': '000 millones'
    -    },
    -    '1000000000': {
    -      'other': '0 mil millones'
    -    },
    -    '10000000000': {
    -      'other': '00 mil millones'
    -    },
    -    '100000000000': {
    -      'other': '000 mil millones'
    -    },
    -    '1000000000000': {
    -      'other': '0 billones'
    -    },
    -    '10000000000000': {
    -      'other': '00 billones'
    -    },
    -    '100000000000000': {
    -      'other': '000 billones'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale es_GT.
    - */
    -goog.i18n.CompactNumberFormatSymbols_es_GT = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '00k'
    -    },
    -    '100000': {
    -      'other': '000k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0k\u00A0M'
    -    },
    -    '10000000000': {
    -      'other': '00k\u00A0M'
    -    },
    -    '100000000000': {
    -      'other': '000k\u00A0M'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0B'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0B'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 millones'
    -    },
    -    '10000000': {
    -      'other': '00 millones'
    -    },
    -    '100000000': {
    -      'other': '000 millones'
    -    },
    -    '1000000000': {
    -      'other': '0 mil millones'
    -    },
    -    '10000000000': {
    -      'other': '00 mil millones'
    -    },
    -    '100000000000': {
    -      'other': '000 mil millones'
    -    },
    -    '1000000000000': {
    -      'other': '0 billones'
    -    },
    -    '10000000000000': {
    -      'other': '00 billones'
    -    },
    -    '100000000000000': {
    -      'other': '000 billones'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale es_HN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_es_HN = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '00k'
    -    },
    -    '100000': {
    -      'other': '000k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0k\u00A0M'
    -    },
    -    '10000000000': {
    -      'other': '00k\u00A0M'
    -    },
    -    '100000000000': {
    -      'other': '000k\u00A0M'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0B'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0B'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 millones'
    -    },
    -    '10000000': {
    -      'other': '00 millones'
    -    },
    -    '100000000': {
    -      'other': '000 millones'
    -    },
    -    '1000000000': {
    -      'other': '0 mil millones'
    -    },
    -    '10000000000': {
    -      'other': '00 mil millones'
    -    },
    -    '100000000000': {
    -      'other': '000 mil millones'
    -    },
    -    '1000000000000': {
    -      'other': '0 billones'
    -    },
    -    '10000000000000': {
    -      'other': '00 billones'
    -    },
    -    '100000000000000': {
    -      'other': '000 billones'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale es_MX.
    - */
    -goog.i18n.CompactNumberFormatSymbols_es_MX = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0k'
    -    },
    -    '10000': {
    -      'other': '00k'
    -    },
    -    '100000': {
    -      'other': '000k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0k\u00A0M'
    -    },
    -    '10000000000': {
    -      'other': '00k\u00A0M'
    -    },
    -    '100000000000': {
    -      'other': '000k\u00A0M'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0B'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0B'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 millones'
    -    },
    -    '10000000': {
    -      'other': '00 millones'
    -    },
    -    '100000000': {
    -      'other': '000 millones'
    -    },
    -    '1000000000': {
    -      'other': '0 mil millones'
    -    },
    -    '10000000000': {
    -      'other': '00 mil millones'
    -    },
    -    '100000000000': {
    -      'other': '000 mil millones'
    -    },
    -    '1000000000000': {
    -      'other': '0 billones'
    -    },
    -    '10000000000000': {
    -      'other': '00 billones'
    -    },
    -    '100000000000000': {
    -      'other': '000 billones'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale es_NI.
    - */
    -goog.i18n.CompactNumberFormatSymbols_es_NI = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '00k'
    -    },
    -    '100000': {
    -      'other': '000k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0k\u00A0M'
    -    },
    -    '10000000000': {
    -      'other': '00k\u00A0M'
    -    },
    -    '100000000000': {
    -      'other': '000k\u00A0M'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0B'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0B'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 millones'
    -    },
    -    '10000000': {
    -      'other': '00 millones'
    -    },
    -    '100000000': {
    -      'other': '000 millones'
    -    },
    -    '1000000000': {
    -      'other': '0 mil millones'
    -    },
    -    '10000000000': {
    -      'other': '00 mil millones'
    -    },
    -    '100000000000': {
    -      'other': '000 mil millones'
    -    },
    -    '1000000000000': {
    -      'other': '0 billones'
    -    },
    -    '10000000000000': {
    -      'other': '00 billones'
    -    },
    -    '100000000000000': {
    -      'other': '000 billones'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale es_PA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_es_PA = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '00k'
    -    },
    -    '100000': {
    -      'other': '000k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0k\u00A0M'
    -    },
    -    '10000000000': {
    -      'other': '00k\u00A0M'
    -    },
    -    '100000000000': {
    -      'other': '000k\u00A0M'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0B'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0B'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 millones'
    -    },
    -    '10000000': {
    -      'other': '00 millones'
    -    },
    -    '100000000': {
    -      'other': '000 millones'
    -    },
    -    '1000000000': {
    -      'other': '0 mil millones'
    -    },
    -    '10000000000': {
    -      'other': '00 mil millones'
    -    },
    -    '100000000000': {
    -      'other': '000 mil millones'
    -    },
    -    '1000000000000': {
    -      'other': '0 billones'
    -    },
    -    '10000000000000': {
    -      'other': '00 billones'
    -    },
    -    '100000000000000': {
    -      'other': '000 billones'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale es_PE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_es_PE = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '00k'
    -    },
    -    '100000': {
    -      'other': '000k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0k\u00A0M'
    -    },
    -    '10000000000': {
    -      'other': '00k\u00A0M'
    -    },
    -    '100000000000': {
    -      'other': '000k\u00A0M'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0B'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0B'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 millones'
    -    },
    -    '10000000': {
    -      'other': '00 millones'
    -    },
    -    '100000000': {
    -      'other': '000 millones'
    -    },
    -    '1000000000': {
    -      'other': '0 mil millones'
    -    },
    -    '10000000000': {
    -      'other': '00 mil millones'
    -    },
    -    '100000000000': {
    -      'other': '000 mil millones'
    -    },
    -    '1000000000000': {
    -      'other': '0 billones'
    -    },
    -    '10000000000000': {
    -      'other': '00 billones'
    -    },
    -    '100000000000000': {
    -      'other': '000 billones'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale es_PH.
    - */
    -goog.i18n.CompactNumberFormatSymbols_es_PH = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0000M'
    -    },
    -    '10000000000': {
    -      'other': '00MRD'
    -    },
    -    '100000000000': {
    -      'other': '000MRD'
    -    },
    -    '1000000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000000': {
    -      'other': '000B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 millones'
    -    },
    -    '10000000': {
    -      'other': '00 millones'
    -    },
    -    '100000000': {
    -      'other': '000 millones'
    -    },
    -    '1000000000': {
    -      'other': '0 mil millones'
    -    },
    -    '10000000000': {
    -      'other': '00 mil millones'
    -    },
    -    '100000000000': {
    -      'other': '000 mil millones'
    -    },
    -    '1000000000000': {
    -      'other': '0 billones'
    -    },
    -    '10000000000000': {
    -      'other': '00 billones'
    -    },
    -    '100000000000000': {
    -      'other': '000 billones'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale es_PR.
    - */
    -goog.i18n.CompactNumberFormatSymbols_es_PR = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '00k'
    -    },
    -    '100000': {
    -      'other': '000k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0k\u00A0M'
    -    },
    -    '10000000000': {
    -      'other': '00k\u00A0M'
    -    },
    -    '100000000000': {
    -      'other': '000k\u00A0M'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0B'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0B'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 millones'
    -    },
    -    '10000000': {
    -      'other': '00 millones'
    -    },
    -    '100000000': {
    -      'other': '000 millones'
    -    },
    -    '1000000000': {
    -      'other': '0 mil millones'
    -    },
    -    '10000000000': {
    -      'other': '00 mil millones'
    -    },
    -    '100000000000': {
    -      'other': '000 mil millones'
    -    },
    -    '1000000000000': {
    -      'other': '0 billones'
    -    },
    -    '10000000000000': {
    -      'other': '00 billones'
    -    },
    -    '100000000000000': {
    -      'other': '000 billones'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale es_PY.
    - */
    -goog.i18n.CompactNumberFormatSymbols_es_PY = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '00k'
    -    },
    -    '100000': {
    -      'other': '000k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0k\u00A0M'
    -    },
    -    '10000000000': {
    -      'other': '00k\u00A0M'
    -    },
    -    '100000000000': {
    -      'other': '000k\u00A0M'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0B'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0B'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 millones'
    -    },
    -    '10000000': {
    -      'other': '00 millones'
    -    },
    -    '100000000': {
    -      'other': '000 millones'
    -    },
    -    '1000000000': {
    -      'other': '0 mil millones'
    -    },
    -    '10000000000': {
    -      'other': '00 mil millones'
    -    },
    -    '100000000000': {
    -      'other': '000 mil millones'
    -    },
    -    '1000000000000': {
    -      'other': '0 billones'
    -    },
    -    '10000000000000': {
    -      'other': '00 billones'
    -    },
    -    '100000000000000': {
    -      'other': '000 billones'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale es_SV.
    - */
    -goog.i18n.CompactNumberFormatSymbols_es_SV = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '00k'
    -    },
    -    '100000': {
    -      'other': '000k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0k\u00A0M'
    -    },
    -    '10000000000': {
    -      'other': '00k\u00A0M'
    -    },
    -    '100000000000': {
    -      'other': '000k\u00A0M'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0B'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0B'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 millones'
    -    },
    -    '10000000': {
    -      'other': '00 millones'
    -    },
    -    '100000000': {
    -      'other': '000 millones'
    -    },
    -    '1000000000': {
    -      'other': '0 mil millones'
    -    },
    -    '10000000000': {
    -      'other': '00 mil millones'
    -    },
    -    '100000000000': {
    -      'other': '000 mil millones'
    -    },
    -    '1000000000000': {
    -      'other': '0 billones'
    -    },
    -    '10000000000000': {
    -      'other': '00 billones'
    -    },
    -    '100000000000000': {
    -      'other': '000 billones'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale es_US.
    - */
    -goog.i18n.CompactNumberFormatSymbols_es_US = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '00k'
    -    },
    -    '100000': {
    -      'other': '000k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0k\u00A0M'
    -    },
    -    '10000000000': {
    -      'other': '00k\u00A0M'
    -    },
    -    '100000000000': {
    -      'other': '000k\u00A0M'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0B'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0B'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 millones'
    -    },
    -    '10000000': {
    -      'other': '00 millones'
    -    },
    -    '100000000': {
    -      'other': '000 millones'
    -    },
    -    '1000000000': {
    -      'other': '0 mil millones'
    -    },
    -    '10000000000': {
    -      'other': '00 mil millones'
    -    },
    -    '100000000000': {
    -      'other': '000 mil millones'
    -    },
    -    '1000000000000': {
    -      'other': '0 billones'
    -    },
    -    '10000000000000': {
    -      'other': '00 billones'
    -    },
    -    '100000000000000': {
    -      'other': '000 billones'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale es_UY.
    - */
    -goog.i18n.CompactNumberFormatSymbols_es_UY = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '00k'
    -    },
    -    '100000': {
    -      'other': '000k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0k\u00A0M'
    -    },
    -    '10000000000': {
    -      'other': '00k\u00A0M'
    -    },
    -    '100000000000': {
    -      'other': '000k\u00A0M'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0B'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0B'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 millones'
    -    },
    -    '10000000': {
    -      'other': '00 millones'
    -    },
    -    '100000000': {
    -      'other': '000 millones'
    -    },
    -    '1000000000': {
    -      'other': '0 mil millones'
    -    },
    -    '10000000000': {
    -      'other': '00 mil millones'
    -    },
    -    '100000000000': {
    -      'other': '000 mil millones'
    -    },
    -    '1000000000000': {
    -      'other': '0 billones'
    -    },
    -    '10000000000000': {
    -      'other': '00 billones'
    -    },
    -    '100000000000000': {
    -      'other': '000 billones'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale es_VE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_es_VE = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '00k'
    -    },
    -    '100000': {
    -      'other': '000k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0k\u00A0M'
    -    },
    -    '10000000000': {
    -      'other': '00k\u00A0M'
    -    },
    -    '100000000000': {
    -      'other': '000k\u00A0M'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0B'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0B'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0B'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 millones'
    -    },
    -    '10000000': {
    -      'other': '00 millones'
    -    },
    -    '100000000': {
    -      'other': '000 millones'
    -    },
    -    '1000000000': {
    -      'other': '0 mil millones'
    -    },
    -    '10000000000': {
    -      'other': '00 mil millones'
    -    },
    -    '100000000000': {
    -      'other': '000 mil millones'
    -    },
    -    '1000000000000': {
    -      'other': '0 billones'
    -    },
    -    '10000000000000': {
    -      'other': '00 billones'
    -    },
    -    '100000000000000': {
    -      'other': '000 billones'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ewo.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ewo = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ewo_CM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ewo_CM =
    -    goog.i18n.CompactNumberFormatSymbols_ewo;
    -
    -
    -/**
    - * Compact number formatting symbols for locale fa_AF.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fa_AF = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0647\u0632\u0627\u0631'
    -    },
    -    '10000': {
    -      'other': '00 \u0647\u0632\u0627\u0631'
    -    },
    -    '100000': {
    -      'other': '000 \u0647\u0632\u0627\u0631'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u06CC\u0644\u06CC\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u06CC\u0644\u06CC\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u06CC\u0644\u06CC\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0645\u06CC\u0644\u06CC\u0627\u0631\u062F'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0645\u06CC\u0644\u06CC\u0627\u0631\u062F'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0645\u06CC\u0644\u06CC\u0627\u0631\u062F'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0647\u0632\u0627\u0631 \u0645\u06CC\u0644\u06CC\u0627\u0631\u062F'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0647\u0632\u0627\u0631 \u0645\u06CC\u0644\u06CC\u0627\u0631\u062F'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0647\u0632\u0627\u0631 \u0645\u06CC\u0644\u06CC\u0627\u0631\u062F'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ff.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ff = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ff_CM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ff_CM = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ff_GN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ff_GN = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ff_MR.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ff_MR = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ff_SN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ff_SN =
    -    goog.i18n.CompactNumberFormatSymbols_ff;
    -
    -
    -/**
    - * Compact number formatting symbols for locale fo.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fo = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0td'
    -    },
    -    '10000': {
    -      'other': '00\u00A0td'
    -    },
    -    '100000': {
    -      'other': '000\u00A0td'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mn'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mn'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mn'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 tusind'
    -    },
    -    '10000': {
    -      'other': '00 tusind'
    -    },
    -    '100000': {
    -      'other': '000 tusind'
    -    },
    -    '1000000': {
    -      'other': '0 millioner'
    -    },
    -    '10000000': {
    -      'other': '00 millioner'
    -    },
    -    '100000000': {
    -      'other': '000 millioner'
    -    },
    -    '1000000000': {
    -      'other': '0 milliarder'
    -    },
    -    '10000000000': {
    -      'other': '00 milliarder'
    -    },
    -    '100000000000': {
    -      'other': '000 milliarder'
    -    },
    -    '1000000000000': {
    -      'other': '0 billioner'
    -    },
    -    '10000000000000': {
    -      'other': '00 billioner'
    -    },
    -    '100000000000000': {
    -      'other': '000 billioner'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fo_FO.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fo_FO =
    -    goog.i18n.CompactNumberFormatSymbols_fo;
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_BE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_BE = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_BF.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_BF = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_BI.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_BI = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_BJ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_BJ = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_CD.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_CD = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_CF.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_CF = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_CG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_CG = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_CH.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_CH = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_CI.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_CI = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_CM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_CM = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_DJ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_DJ = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_DZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_DZ = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_GA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_GA = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_GN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_GN = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_GQ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_GQ = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_HT.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_HT = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_KM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_KM = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_LU.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_LU = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_MA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_MA = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_MG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_MG = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_ML.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_ML = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_MR.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_MR = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_MU.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_MU = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_NC.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_NC = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_NE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_NE = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_PF.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_PF = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_RW.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_RW = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_SC.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_SC = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_SN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_SN = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_SY.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_SY = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_TD.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_TD = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_TG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_TG = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_TN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_TN = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_VU.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_VU = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fr_WF.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fr_WF = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0k'
    -    },
    -    '10000': {
    -      'other': '00\u00A0k'
    -    },
    -    '100000': {
    -      'other': '000\u00A0k'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mille'
    -    },
    -    '10000': {
    -      'other': '00 mille'
    -    },
    -    '100000': {
    -      'other': '000 mille'
    -    },
    -    '1000000': {
    -      'other': '0 millions'
    -    },
    -    '10000000': {
    -      'other': '00 millions'
    -    },
    -    '100000000': {
    -      'other': '000 millions'
    -    },
    -    '1000000000': {
    -      'other': '0 milliards'
    -    },
    -    '10000000000': {
    -      'other': '00 milliards'
    -    },
    -    '100000000000': {
    -      'other': '000 milliards'
    -    },
    -    '1000000000000': {
    -      'other': '0 billions'
    -    },
    -    '10000000000000': {
    -      'other': '00 billions'
    -    },
    -    '100000000000000': {
    -      'other': '000 billions'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fur.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fur = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fur_IT.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fur_IT =
    -    goog.i18n.CompactNumberFormatSymbols_fur;
    -
    -
    -/**
    - * Compact number formatting symbols for locale fy.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fy = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mln.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mln.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mln.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mld.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mld.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mld.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bln.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bln.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bln.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 t\u00FBzen'
    -    },
    -    '10000': {
    -      'other': '00 t\u00FBzen'
    -    },
    -    '100000': {
    -      'other': '000 t\u00FBzen'
    -    },
    -    '1000000': {
    -      'other': '0 miljoen'
    -    },
    -    '10000000': {
    -      'other': '00 miljoen'
    -    },
    -    '100000000': {
    -      'other': '000 miljoen'
    -    },
    -    '1000000000': {
    -      'other': '0 miljard'
    -    },
    -    '10000000000': {
    -      'other': '00 miljard'
    -    },
    -    '100000000000': {
    -      'other': '000 miljard'
    -    },
    -    '1000000000000': {
    -      'other': '0 biljoen'
    -    },
    -    '10000000000000': {
    -      'other': '00 biljoen'
    -    },
    -    '100000000000000': {
    -      'other': '000 biljoen'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale fy_NL.
    - */
    -goog.i18n.CompactNumberFormatSymbols_fy_NL =
    -    goog.i18n.CompactNumberFormatSymbols_fy;
    -
    -
    -/**
    - * Compact number formatting symbols for locale gd.
    - */
    -goog.i18n.CompactNumberFormatSymbols_gd = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 m\u00ECle'
    -    },
    -    '10000': {
    -      'other': '00 m\u00ECle'
    -    },
    -    '100000': {
    -      'other': '000 m\u00ECle'
    -    },
    -    '1000000': {
    -      'other': '0 millean'
    -    },
    -    '10000000': {
    -      'other': '00 millean'
    -    },
    -    '100000000': {
    -      'other': '000 millean'
    -    },
    -    '1000000000': {
    -      'other': '0 billean'
    -    },
    -    '10000000000': {
    -      'other': '00 billean'
    -    },
    -    '100000000000': {
    -      'other': '000 billean'
    -    },
    -    '1000000000000': {
    -      'other': '0 trillean'
    -    },
    -    '10000000000000': {
    -      'other': '00 trillean'
    -    },
    -    '100000000000000': {
    -      'other': '000 trillean'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale gd_GB.
    - */
    -goog.i18n.CompactNumberFormatSymbols_gd_GB =
    -    goog.i18n.CompactNumberFormatSymbols_gd;
    -
    -
    -/**
    - * Compact number formatting symbols for locale gsw_FR.
    - */
    -goog.i18n.CompactNumberFormatSymbols_gsw_FR = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0tsd'
    -    },
    -    '10000': {
    -      'other': '00\u00A0tsd'
    -    },
    -    '100000': {
    -      'other': '000\u00A0tsd'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0Mio'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0Mio'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0Mio'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Mrd'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Mrd'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Mrd'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bio'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bio'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bio'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 tausend'
    -    },
    -    '10000': {
    -      'other': '00 tausend'
    -    },
    -    '100000': {
    -      'other': '000 tausend'
    -    },
    -    '1000000': {
    -      'other': '0 Millionen'
    -    },
    -    '10000000': {
    -      'other': '00 Millionen'
    -    },
    -    '100000000': {
    -      'other': '000 Millionen'
    -    },
    -    '1000000000': {
    -      'other': '0 Milliarden'
    -    },
    -    '10000000000': {
    -      'other': '00 Milliarden'
    -    },
    -    '100000000000': {
    -      'other': '000 Milliarden'
    -    },
    -    '1000000000000': {
    -      'other': '0 Billionen'
    -    },
    -    '10000000000000': {
    -      'other': '00 Billionen'
    -    },
    -    '100000000000000': {
    -      'other': '000 Billionen'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale guz.
    - */
    -goog.i18n.CompactNumberFormatSymbols_guz = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale guz_KE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_guz_KE =
    -    goog.i18n.CompactNumberFormatSymbols_guz;
    -
    -
    -/**
    - * Compact number formatting symbols for locale gv.
    - */
    -goog.i18n.CompactNumberFormatSymbols_gv = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale gv_IM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_gv_IM =
    -    goog.i18n.CompactNumberFormatSymbols_gv;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ha.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ha = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ha_Latn.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ha_Latn = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ha_Latn_GH.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ha_Latn_GH = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ha_Latn_NE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ha_Latn_NE = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ha_Latn_NG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ha_Latn_NG =
    -    goog.i18n.CompactNumberFormatSymbols_ha;
    -
    -
    -/**
    - * Compact number formatting symbols for locale hr_BA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_hr_BA = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0tis.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0tis.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0tis.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mil.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mil.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mil.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mlr.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mlr.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mlr.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bil.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bil.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bil.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 tisu\u0107a'
    -    },
    -    '10000': {
    -      'other': '00 tisu\u0107a'
    -    },
    -    '100000': {
    -      'other': '000 tisu\u0107a'
    -    },
    -    '1000000': {
    -      'other': '0 milijuna'
    -    },
    -    '10000000': {
    -      'other': '00 milijuna'
    -    },
    -    '100000000': {
    -      'other': '000 milijuna'
    -    },
    -    '1000000000': {
    -      'other': '0 milijardi'
    -    },
    -    '10000000000': {
    -      'other': '00 milijardi'
    -    },
    -    '100000000000': {
    -      'other': '000 milijardi'
    -    },
    -    '1000000000000': {
    -      'other': '0 bilijuna'
    -    },
    -    '10000000000000': {
    -      'other': '00 bilijuna'
    -    },
    -    '100000000000000': {
    -      'other': '000 bilijuna'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale hsb.
    - */
    -goog.i18n.CompactNumberFormatSymbols_hsb = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0tys.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0tys.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0tys.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mio.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mio.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mio.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mrd.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mrd.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mrd.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bil.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bil.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bil.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 tysac'
    -    },
    -    '10000': {
    -      'other': '00 tysac'
    -    },
    -    '100000': {
    -      'other': '000 tysac'
    -    },
    -    '1000000': {
    -      'other': '0 milionow'
    -    },
    -    '10000000': {
    -      'other': '00 milionow'
    -    },
    -    '100000000': {
    -      'other': '000 milionow'
    -    },
    -    '1000000000': {
    -      'other': '0 miliardow'
    -    },
    -    '10000000000': {
    -      'other': '00 miliardow'
    -    },
    -    '100000000000': {
    -      'other': '000 miliardow'
    -    },
    -    '1000000000000': {
    -      'other': '0 bilionow'
    -    },
    -    '10000000000000': {
    -      'other': '00 bilionow'
    -    },
    -    '100000000000000': {
    -      'other': '000 bilionow'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale hsb_DE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_hsb_DE =
    -    goog.i18n.CompactNumberFormatSymbols_hsb;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ia.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ia = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ia_FR.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ia_FR =
    -    goog.i18n.CompactNumberFormatSymbols_ia;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ig.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ig = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ig_NG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ig_NG =
    -    goog.i18n.CompactNumberFormatSymbols_ig;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ii.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ii = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ii_CN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ii_CN =
    -    goog.i18n.CompactNumberFormatSymbols_ii;
    -
    -
    -/**
    - * Compact number formatting symbols for locale it_CH.
    - */
    -goog.i18n.CompactNumberFormatSymbols_it_CH = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '0'
    -    },
    -    '100000': {
    -      'other': '0'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0Mln'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0Mln'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0Mln'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Mld'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Mld'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Mld'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bln'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bln'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bln'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 migliaia'
    -    },
    -    '10000': {
    -      'other': '00 migliaia'
    -    },
    -    '100000': {
    -      'other': '000 migliaia'
    -    },
    -    '1000000': {
    -      'other': '0 milioni'
    -    },
    -    '10000000': {
    -      'other': '00 milioni'
    -    },
    -    '100000000': {
    -      'other': '000 milioni'
    -    },
    -    '1000000000': {
    -      'other': '0 miliardi'
    -    },
    -    '10000000000': {
    -      'other': '00 miliardi'
    -    },
    -    '100000000000': {
    -      'other': '000 miliardi'
    -    },
    -    '1000000000000': {
    -      'other': '0 migliaia di miliardi'
    -    },
    -    '10000000000000': {
    -      'other': '00 migliaia di miliardi'
    -    },
    -    '100000000000000': {
    -      'other': '000 migliaia di miliardi'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale jgo.
    - */
    -goog.i18n.CompactNumberFormatSymbols_jgo = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale jgo_CM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_jgo_CM =
    -    goog.i18n.CompactNumberFormatSymbols_jgo;
    -
    -
    -/**
    - * Compact number formatting symbols for locale jmc.
    - */
    -goog.i18n.CompactNumberFormatSymbols_jmc = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale jmc_TZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_jmc_TZ =
    -    goog.i18n.CompactNumberFormatSymbols_jmc;
    -
    -
    -/**
    - * Compact number formatting symbols for locale kab.
    - */
    -goog.i18n.CompactNumberFormatSymbols_kab = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale kab_DZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_kab_DZ =
    -    goog.i18n.CompactNumberFormatSymbols_kab;
    -
    -
    -/**
    - * Compact number formatting symbols for locale kam.
    - */
    -goog.i18n.CompactNumberFormatSymbols_kam = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale kam_KE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_kam_KE =
    -    goog.i18n.CompactNumberFormatSymbols_kam;
    -
    -
    -/**
    - * Compact number formatting symbols for locale kde.
    - */
    -goog.i18n.CompactNumberFormatSymbols_kde = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale kde_TZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_kde_TZ =
    -    goog.i18n.CompactNumberFormatSymbols_kde;
    -
    -
    -/**
    - * Compact number formatting symbols for locale kea.
    - */
    -goog.i18n.CompactNumberFormatSymbols_kea = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0mil'
    -    },
    -    '10000': {
    -      'other': '00\u00A0mil'
    -    },
    -    '100000': {
    -      'other': '000\u00A0mil'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0MM'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0MM'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0MM'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bi'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bi'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bi'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 milh\u00E3u'
    -    },
    -    '10000000': {
    -      'other': '00 milh\u00E3u'
    -    },
    -    '100000000': {
    -      'other': '000 milh\u00E3u'
    -    },
    -    '1000000000': {
    -      'other': '0 mil milh\u00E3u'
    -    },
    -    '10000000000': {
    -      'other': '00 mil milh\u00E3u'
    -    },
    -    '100000000000': {
    -      'other': '000 mil milh\u00E3u'
    -    },
    -    '1000000000000': {
    -      'other': '0 bilh\u00E3u'
    -    },
    -    '10000000000000': {
    -      'other': '00 bilh\u00E3u'
    -    },
    -    '100000000000000': {
    -      'other': '000 bilh\u00E3u'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale kea_CV.
    - */
    -goog.i18n.CompactNumberFormatSymbols_kea_CV =
    -    goog.i18n.CompactNumberFormatSymbols_kea;
    -
    -
    -/**
    - * Compact number formatting symbols for locale khq.
    - */
    -goog.i18n.CompactNumberFormatSymbols_khq = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale khq_ML.
    - */
    -goog.i18n.CompactNumberFormatSymbols_khq_ML =
    -    goog.i18n.CompactNumberFormatSymbols_khq;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ki.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ki = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ki_KE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ki_KE =
    -    goog.i18n.CompactNumberFormatSymbols_ki;
    -
    -
    -/**
    - * Compact number formatting symbols for locale kk_Cyrl.
    - */
    -goog.i18n.CompactNumberFormatSymbols_kk_Cyrl = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u043C\u044B\u04A3'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u043C\u044B\u04A3'
    -    },
    -    '100000': {
    -      'other': '000\u041C'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u043C\u043B\u043D'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u043C\u043B\u043D'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u043C\u043B\u043D'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '100000000000': {
    -      'other': '000\u0411'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u0442\u0440\u043B\u043D'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u0442\u0440\u043B\u043D'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale kkj.
    - */
    -goog.i18n.CompactNumberFormatSymbols_kkj = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale kkj_CM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_kkj_CM =
    -    goog.i18n.CompactNumberFormatSymbols_kkj;
    -
    -
    -/**
    - * Compact number formatting symbols for locale kl.
    - */
    -goog.i18n.CompactNumberFormatSymbols_kl = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0td'
    -    },
    -    '10000': {
    -      'other': '00\u00A0td'
    -    },
    -    '100000': {
    -      'other': '000\u00A0td'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mn'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mn'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mn'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 tusind'
    -    },
    -    '10000': {
    -      'other': '00 tusind'
    -    },
    -    '100000': {
    -      'other': '000 tusind'
    -    },
    -    '1000000': {
    -      'other': '0 millioner'
    -    },
    -    '10000000': {
    -      'other': '00 millioner'
    -    },
    -    '100000000': {
    -      'other': '000 millioner'
    -    },
    -    '1000000000': {
    -      'other': '0 milliarder'
    -    },
    -    '10000000000': {
    -      'other': '00 milliarder'
    -    },
    -    '100000000000': {
    -      'other': '000 milliarder'
    -    },
    -    '1000000000000': {
    -      'other': '0 billioner'
    -    },
    -    '10000000000000': {
    -      'other': '00 billioner'
    -    },
    -    '100000000000000': {
    -      'other': '000 billioner'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale kl_GL.
    - */
    -goog.i18n.CompactNumberFormatSymbols_kl_GL =
    -    goog.i18n.CompactNumberFormatSymbols_kl;
    -
    -
    -/**
    - * Compact number formatting symbols for locale kln.
    - */
    -goog.i18n.CompactNumberFormatSymbols_kln = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale kln_KE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_kln_KE =
    -    goog.i18n.CompactNumberFormatSymbols_kln;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ko_KP.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ko_KP = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0000'
    -    },
    -    '10000': {
    -      'other': '0\uB9CC'
    -    },
    -    '100000': {
    -      'other': '00\uB9CC'
    -    },
    -    '1000000': {
    -      'other': '000\uB9CC'
    -    },
    -    '10000000': {
    -      'other': '0000\uB9CC'
    -    },
    -    '100000000': {
    -      'other': '0\uC5B5'
    -    },
    -    '1000000000': {
    -      'other': '00\uC5B5'
    -    },
    -    '10000000000': {
    -      'other': '000\uC5B5'
    -    },
    -    '100000000000': {
    -      'other': '0000\uC5B5'
    -    },
    -    '1000000000000': {
    -      'other': '0\uC870'
    -    },
    -    '10000000000000': {
    -      'other': '00\uC870'
    -    },
    -    '100000000000000': {
    -      'other': '000\uC870'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0000'
    -    },
    -    '10000': {
    -      'other': '0\uB9CC'
    -    },
    -    '100000': {
    -      'other': '00\uB9CC'
    -    },
    -    '1000000': {
    -      'other': '000\uB9CC'
    -    },
    -    '10000000': {
    -      'other': '0000\uB9CC'
    -    },
    -    '100000000': {
    -      'other': '0\uC5B5'
    -    },
    -    '1000000000': {
    -      'other': '00\uC5B5'
    -    },
    -    '10000000000': {
    -      'other': '000\uC5B5'
    -    },
    -    '100000000000': {
    -      'other': '0000\uC5B5'
    -    },
    -    '1000000000000': {
    -      'other': '0\uC870'
    -    },
    -    '10000000000000': {
    -      'other': '00\uC870'
    -    },
    -    '100000000000000': {
    -      'other': '000\uC870'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale kok.
    - */
    -goog.i18n.CompactNumberFormatSymbols_kok = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale kok_IN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_kok_IN =
    -    goog.i18n.CompactNumberFormatSymbols_kok;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ks.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ks = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ks_Arab.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ks_Arab = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ks_Arab_IN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ks_Arab_IN =
    -    goog.i18n.CompactNumberFormatSymbols_ks;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ksb.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ksb = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ksb_TZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ksb_TZ =
    -    goog.i18n.CompactNumberFormatSymbols_ksb;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ksf.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ksf = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ksf_CM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ksf_CM =
    -    goog.i18n.CompactNumberFormatSymbols_ksf;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ksh.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ksh = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0tsd'
    -    },
    -    '10000': {
    -      'other': '00\u00A0tsd'
    -    },
    -    '100000': {
    -      'other': '000\u00A0tsd'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0Mio'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0Mio'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0Mio'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Mrd'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Mrd'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Mrd'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bio'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bio'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bio'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 Dousend'
    -    },
    -    '10000': {
    -      'other': '00 Dousend'
    -    },
    -    '100000': {
    -      'other': '000 Dousend'
    -    },
    -    '1000000': {
    -      'other': '0 Milljuhne'
    -    },
    -    '10000000': {
    -      'other': '00 Millionen'
    -    },
    -    '100000000': {
    -      'other': '000 Millionen'
    -    },
    -    '1000000000': {
    -      'other': '0 Milljarde'
    -    },
    -    '10000000000': {
    -      'other': '00 Milliarden'
    -    },
    -    '100000000000': {
    -      'other': '000 Milliarden'
    -    },
    -    '1000000000000': {
    -      'other': '0 Billjuhn'
    -    },
    -    '10000000000000': {
    -      'other': '00 Billionen'
    -    },
    -    '100000000000000': {
    -      'other': '000 Billionen'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ksh_DE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ksh_DE =
    -    goog.i18n.CompactNumberFormatSymbols_ksh;
    -
    -
    -/**
    - * Compact number formatting symbols for locale kw.
    - */
    -goog.i18n.CompactNumberFormatSymbols_kw = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale kw_GB.
    - */
    -goog.i18n.CompactNumberFormatSymbols_kw_GB =
    -    goog.i18n.CompactNumberFormatSymbols_kw;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ky_Cyrl.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ky_Cyrl = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u043C\u0438\u04CA'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u043C\u0438\u04CA'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u043C\u0438\u04CA'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u043C\u043B\u043D'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u043C\u043B\u043D'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u043C\u043B\u043D'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u043C\u043B\u0434'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u043C\u043B\u0434'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u043C\u043B\u0434'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u0442\u0440\u043D'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u0442\u0440\u043D'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u0442\u0440\u043D'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u043C\u0438\u04CA'
    -    },
    -    '10000': {
    -      'other': '00 \u043C\u0438\u04CA'
    -    },
    -    '100000': {
    -      'other': '000 \u043C\u0438\u04CA'
    -    },
    -    '1000000': {
    -      'other': '0 \u043C\u0438\u043B\u043B\u0438\u043E\u043D'
    -    },
    -    '10000000': {
    -      'other': '00 \u043C\u0438\u043B\u043B\u0438\u043E\u043D'
    -    },
    -    '100000000': {
    -      'other': '000 \u043C\u0438\u043B\u043B\u0438\u043E\u043D'
    -    },
    -    '1000000000': {
    -      'other': '0 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434'
    -    },
    -    '10000000000': {
    -      'other': '00 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434'
    -    },
    -    '100000000000': {
    -      'other': '000 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0442\u0440\u0438\u043B\u043B\u0438\u043E\u043D'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0442\u0440\u0438\u043B\u043B\u0438\u043E\u043D'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0442\u0440\u0438\u043B\u043B\u0438\u043E\u043D'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale lag.
    - */
    -goog.i18n.CompactNumberFormatSymbols_lag = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale lag_TZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_lag_TZ =
    -    goog.i18n.CompactNumberFormatSymbols_lag;
    -
    -
    -/**
    - * Compact number formatting symbols for locale lb.
    - */
    -goog.i18n.CompactNumberFormatSymbols_lb = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0Dsd.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0Dsd.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0Dsd.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0Mio.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0Mio.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0Mio.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Mrd.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Mrd.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Mrd.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bio.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bio.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bio.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 Dausend'
    -    },
    -    '10000': {
    -      'other': '00 Dausend'
    -    },
    -    '100000': {
    -      'other': '000 Dausend'
    -    },
    -    '1000000': {
    -      'other': '0 Milliounen'
    -    },
    -    '10000000': {
    -      'other': '00 Milliounen'
    -    },
    -    '100000000': {
    -      'other': '000 Milliounen'
    -    },
    -    '1000000000': {
    -      'other': '0 Milliarden'
    -    },
    -    '10000000000': {
    -      'other': '00 Milliarden'
    -    },
    -    '100000000000': {
    -      'other': '000 Milliarden'
    -    },
    -    '1000000000000': {
    -      'other': '0 Billiounen'
    -    },
    -    '10000000000000': {
    -      'other': '00 Billiounen'
    -    },
    -    '100000000000000': {
    -      'other': '000 Billiounen'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale lb_LU.
    - */
    -goog.i18n.CompactNumberFormatSymbols_lb_LU =
    -    goog.i18n.CompactNumberFormatSymbols_lb;
    -
    -
    -/**
    - * Compact number formatting symbols for locale lg.
    - */
    -goog.i18n.CompactNumberFormatSymbols_lg = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale lg_UG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_lg_UG =
    -    goog.i18n.CompactNumberFormatSymbols_lg;
    -
    -
    -/**
    - * Compact number formatting symbols for locale lkt.
    - */
    -goog.i18n.CompactNumberFormatSymbols_lkt = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale lkt_US.
    - */
    -goog.i18n.CompactNumberFormatSymbols_lkt_US =
    -    goog.i18n.CompactNumberFormatSymbols_lkt;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ln_AO.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ln_AO = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ln_CF.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ln_CF = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ln_CG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ln_CG = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale lu.
    - */
    -goog.i18n.CompactNumberFormatSymbols_lu = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale lu_CD.
    - */
    -goog.i18n.CompactNumberFormatSymbols_lu_CD =
    -    goog.i18n.CompactNumberFormatSymbols_lu;
    -
    -
    -/**
    - * Compact number formatting symbols for locale luo.
    - */
    -goog.i18n.CompactNumberFormatSymbols_luo = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale luo_KE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_luo_KE =
    -    goog.i18n.CompactNumberFormatSymbols_luo;
    -
    -
    -/**
    - * Compact number formatting symbols for locale luy.
    - */
    -goog.i18n.CompactNumberFormatSymbols_luy = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale luy_KE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_luy_KE =
    -    goog.i18n.CompactNumberFormatSymbols_luy;
    -
    -
    -/**
    - * Compact number formatting symbols for locale mas.
    - */
    -goog.i18n.CompactNumberFormatSymbols_mas = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale mas_KE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_mas_KE =
    -    goog.i18n.CompactNumberFormatSymbols_mas;
    -
    -
    -/**
    - * Compact number formatting symbols for locale mas_TZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_mas_TZ = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale mer.
    - */
    -goog.i18n.CompactNumberFormatSymbols_mer = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale mer_KE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_mer_KE =
    -    goog.i18n.CompactNumberFormatSymbols_mer;
    -
    -
    -/**
    - * Compact number formatting symbols for locale mfe.
    - */
    -goog.i18n.CompactNumberFormatSymbols_mfe = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale mfe_MU.
    - */
    -goog.i18n.CompactNumberFormatSymbols_mfe_MU =
    -    goog.i18n.CompactNumberFormatSymbols_mfe;
    -
    -
    -/**
    - * Compact number formatting symbols for locale mg.
    - */
    -goog.i18n.CompactNumberFormatSymbols_mg = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale mg_MG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_mg_MG =
    -    goog.i18n.CompactNumberFormatSymbols_mg;
    -
    -
    -/**
    - * Compact number formatting symbols for locale mgh.
    - */
    -goog.i18n.CompactNumberFormatSymbols_mgh = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale mgh_MZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_mgh_MZ =
    -    goog.i18n.CompactNumberFormatSymbols_mgh;
    -
    -
    -/**
    - * Compact number formatting symbols for locale mgo.
    - */
    -goog.i18n.CompactNumberFormatSymbols_mgo = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale mgo_CM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_mgo_CM =
    -    goog.i18n.CompactNumberFormatSymbols_mgo;
    -
    -
    -/**
    - * Compact number formatting symbols for locale mn_Cyrl.
    - */
    -goog.i18n.CompactNumberFormatSymbols_mn_Cyrl = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u041C'
    -    },
    -    '10000': {
    -      'other': '00\u041C'
    -    },
    -    '100000': {
    -      'other': '000\u041C'
    -    },
    -    '1000000': {
    -      'other': '0\u0421'
    -    },
    -    '10000000': {
    -      'other': '00\u0421'
    -    },
    -    '100000000': {
    -      'other': '000\u0421'
    -    },
    -    '1000000000': {
    -      'other': '0\u0422'
    -    },
    -    '10000000000': {
    -      'other': '00\u0422'
    -    },
    -    '100000000000': {
    -      'other': '000\u0422'
    -    },
    -    '1000000000000': {
    -      'other': '0\u0418\u041D'
    -    },
    -    '10000000000000': {
    -      'other': '00\u0418\u041D'
    -    },
    -    '100000000000000': {
    -      'other': '000\u0418\u041D'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u043C\u044F\u043D\u0433\u0430'
    -    },
    -    '10000': {
    -      'other': '00 \u043C\u044F\u043D\u0433\u0430'
    -    },
    -    '100000': {
    -      'other': '000 \u043C\u044F\u043D\u0433\u0430'
    -    },
    -    '1000000': {
    -      'other': '0 \u0441\u0430\u044F'
    -    },
    -    '10000000': {
    -      'other': '00 \u0441\u0430\u044F'
    -    },
    -    '100000000': {
    -      'other': '000 \u0441\u0430\u044F'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0442\u044D\u0440\u0431\u0443\u043C'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0442\u044D\u0440\u0431\u0443\u043C'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0442\u044D\u0440\u0431\u0443\u043C'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0438\u0445 \u043D\u0430\u044F\u0434'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0438\u0445 \u043D\u0430\u044F\u0434'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0438\u0445 \u043D\u0430\u044F\u0434'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ms_Latn.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ms_Latn = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0J'
    -    },
    -    '10000000': {
    -      'other': '00J'
    -    },
    -    '100000000': {
    -      'other': '000J'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 ribu'
    -    },
    -    '10000': {
    -      'other': '00 ribu'
    -    },
    -    '100000': {
    -      'other': '000 ribu'
    -    },
    -    '1000000': {
    -      'other': '0 juta'
    -    },
    -    '10000000': {
    -      'other': '00 juta'
    -    },
    -    '100000000': {
    -      'other': '000 juta'
    -    },
    -    '1000000000': {
    -      'other': '0 bilion'
    -    },
    -    '10000000000': {
    -      'other': '00 bilion'
    -    },
    -    '100000000000': {
    -      'other': '000 bilion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trilion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trilion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trilion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ms_Latn_BN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ms_Latn_BN = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0J'
    -    },
    -    '10000000': {
    -      'other': '00J'
    -    },
    -    '100000000': {
    -      'other': '000J'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 ribu'
    -    },
    -    '10000': {
    -      'other': '00 ribu'
    -    },
    -    '100000': {
    -      'other': '000 ribu'
    -    },
    -    '1000000': {
    -      'other': '0 juta'
    -    },
    -    '10000000': {
    -      'other': '00 juta'
    -    },
    -    '100000000': {
    -      'other': '000 juta'
    -    },
    -    '1000000000': {
    -      'other': '0 bilion'
    -    },
    -    '10000000000': {
    -      'other': '00 bilion'
    -    },
    -    '100000000000': {
    -      'other': '000 bilion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trilion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trilion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trilion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ms_Latn_SG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ms_Latn_SG = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0J'
    -    },
    -    '10000000': {
    -      'other': '00J'
    -    },
    -    '100000000': {
    -      'other': '000J'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 ribu'
    -    },
    -    '10000': {
    -      'other': '00 ribu'
    -    },
    -    '100000': {
    -      'other': '000 ribu'
    -    },
    -    '1000000': {
    -      'other': '0 juta'
    -    },
    -    '10000000': {
    -      'other': '00 juta'
    -    },
    -    '100000000': {
    -      'other': '000 juta'
    -    },
    -    '1000000000': {
    -      'other': '0 bilion'
    -    },
    -    '10000000000': {
    -      'other': '00 bilion'
    -    },
    -    '100000000000': {
    -      'other': '000 bilion'
    -    },
    -    '1000000000000': {
    -      'other': '0 trilion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trilion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trilion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale mua.
    - */
    -goog.i18n.CompactNumberFormatSymbols_mua = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale mua_CM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_mua_CM =
    -    goog.i18n.CompactNumberFormatSymbols_mua;
    -
    -
    -/**
    - * Compact number formatting symbols for locale naq.
    - */
    -goog.i18n.CompactNumberFormatSymbols_naq = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale naq_NA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_naq_NA =
    -    goog.i18n.CompactNumberFormatSymbols_naq;
    -
    -
    -/**
    - * Compact number formatting symbols for locale nd.
    - */
    -goog.i18n.CompactNumberFormatSymbols_nd = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale nd_ZW.
    - */
    -goog.i18n.CompactNumberFormatSymbols_nd_ZW =
    -    goog.i18n.CompactNumberFormatSymbols_nd;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ne_IN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ne_IN = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0939\u091C\u093E\u0930'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0939\u091C\u093E\u0930'
    -    },
    -    '100000': {
    -      'other': '0\u00A0\u0932\u093E\u0916'
    -    },
    -    '1000000': {
    -      'other': '00\u00A0\u0932\u093E\u0916'
    -    },
    -    '10000000': {
    -      'other': '0\u00A0\u0915\u0930\u094B\u0921'
    -    },
    -    '100000000': {
    -      'other': '00\u00A0\u0915\u0930\u094B\u0921'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0905\u0930\u092C'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0905\u0930\u092C'
    -    },
    -    '100000000000': {
    -      'other': '0\u00A0\u0916\u0930\u092C'
    -    },
    -    '1000000000000': {
    -      'other': '00\u00A0\u0916\u0930\u092C'
    -    },
    -    '10000000000000': {
    -      'other': '0\u00A0\u0936\u0902\u0916'
    -    },
    -    '100000000000000': {
    -      'other': '00\u00A0\u0936\u0902\u0916'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0939\u091C\u093E\u0930'
    -    },
    -    '10000': {
    -      'other': '00 \u0939\u091C\u093E\u0930'
    -    },
    -    '100000': {
    -      'other': '0 \u0932\u093E\u0916'
    -    },
    -    '1000000': {
    -      'other': '0 \u0915\u0930\u094B\u0921'
    -    },
    -    '10000000': {
    -      'other': '00 \u0915\u0930\u094B\u0921'
    -    },
    -    '100000000': {
    -      'other': '000 \u0915\u0930\u094B\u0921'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0905\u0930\u094D\u092C'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0905\u0930\u094D\u092C'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0905\u0930\u092C'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0916\u0930\u094D\u092C'
    -    },
    -    '10000000000000': {
    -      'other': '0 \u0936\u0902\u0916'
    -    },
    -    '100000000000000': {
    -      'other': '00 \u0936\u0902\u0916'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale nl_AW.
    - */
    -goog.i18n.CompactNumberFormatSymbols_nl_AW = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mln.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mln.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mln.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mld.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mld.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mld.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bln.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bln.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bln.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 duizend'
    -    },
    -    '10000': {
    -      'other': '00 duizend'
    -    },
    -    '100000': {
    -      'other': '000 duizend'
    -    },
    -    '1000000': {
    -      'other': '0 miljoen'
    -    },
    -    '10000000': {
    -      'other': '00 miljoen'
    -    },
    -    '100000000': {
    -      'other': '000 miljoen'
    -    },
    -    '1000000000': {
    -      'other': '0 miljard'
    -    },
    -    '10000000000': {
    -      'other': '00 miljard'
    -    },
    -    '100000000000': {
    -      'other': '000 miljard'
    -    },
    -    '1000000000000': {
    -      'other': '0 biljoen'
    -    },
    -    '10000000000000': {
    -      'other': '00 biljoen'
    -    },
    -    '100000000000000': {
    -      'other': '000 biljoen'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale nl_BE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_nl_BE = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mln.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mln.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mln.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mld.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mld.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mld.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bln.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bln.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bln.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 duizend'
    -    },
    -    '10000': {
    -      'other': '00 duizend'
    -    },
    -    '100000': {
    -      'other': '000 duizend'
    -    },
    -    '1000000': {
    -      'other': '0 miljoen'
    -    },
    -    '10000000': {
    -      'other': '00 miljoen'
    -    },
    -    '100000000': {
    -      'other': '000 miljoen'
    -    },
    -    '1000000000': {
    -      'other': '0 miljard'
    -    },
    -    '10000000000': {
    -      'other': '00 miljard'
    -    },
    -    '100000000000': {
    -      'other': '000 miljard'
    -    },
    -    '1000000000000': {
    -      'other': '0 biljoen'
    -    },
    -    '10000000000000': {
    -      'other': '00 biljoen'
    -    },
    -    '100000000000000': {
    -      'other': '000 biljoen'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale nl_BQ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_nl_BQ = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mln.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mln.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mln.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mld.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mld.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mld.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bln.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bln.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bln.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 duizend'
    -    },
    -    '10000': {
    -      'other': '00 duizend'
    -    },
    -    '100000': {
    -      'other': '000 duizend'
    -    },
    -    '1000000': {
    -      'other': '0 miljoen'
    -    },
    -    '10000000': {
    -      'other': '00 miljoen'
    -    },
    -    '100000000': {
    -      'other': '000 miljoen'
    -    },
    -    '1000000000': {
    -      'other': '0 miljard'
    -    },
    -    '10000000000': {
    -      'other': '00 miljard'
    -    },
    -    '100000000000': {
    -      'other': '000 miljard'
    -    },
    -    '1000000000000': {
    -      'other': '0 biljoen'
    -    },
    -    '10000000000000': {
    -      'other': '00 biljoen'
    -    },
    -    '100000000000000': {
    -      'other': '000 biljoen'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale nl_CW.
    - */
    -goog.i18n.CompactNumberFormatSymbols_nl_CW = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mln.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mln.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mln.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mld.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mld.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mld.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bln.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bln.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bln.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 duizend'
    -    },
    -    '10000': {
    -      'other': '00 duizend'
    -    },
    -    '100000': {
    -      'other': '000 duizend'
    -    },
    -    '1000000': {
    -      'other': '0 miljoen'
    -    },
    -    '10000000': {
    -      'other': '00 miljoen'
    -    },
    -    '100000000': {
    -      'other': '000 miljoen'
    -    },
    -    '1000000000': {
    -      'other': '0 miljard'
    -    },
    -    '10000000000': {
    -      'other': '00 miljard'
    -    },
    -    '100000000000': {
    -      'other': '000 miljard'
    -    },
    -    '1000000000000': {
    -      'other': '0 biljoen'
    -    },
    -    '10000000000000': {
    -      'other': '00 biljoen'
    -    },
    -    '100000000000000': {
    -      'other': '000 biljoen'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale nl_SR.
    - */
    -goog.i18n.CompactNumberFormatSymbols_nl_SR = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mln.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mln.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mln.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mld.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mld.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mld.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bln.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bln.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bln.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 duizend'
    -    },
    -    '10000': {
    -      'other': '00 duizend'
    -    },
    -    '100000': {
    -      'other': '000 duizend'
    -    },
    -    '1000000': {
    -      'other': '0 miljoen'
    -    },
    -    '10000000': {
    -      'other': '00 miljoen'
    -    },
    -    '100000000': {
    -      'other': '000 miljoen'
    -    },
    -    '1000000000': {
    -      'other': '0 miljard'
    -    },
    -    '10000000000': {
    -      'other': '00 miljard'
    -    },
    -    '100000000000': {
    -      'other': '000 miljard'
    -    },
    -    '1000000000000': {
    -      'other': '0 biljoen'
    -    },
    -    '10000000000000': {
    -      'other': '00 biljoen'
    -    },
    -    '100000000000000': {
    -      'other': '000 biljoen'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale nl_SX.
    - */
    -goog.i18n.CompactNumberFormatSymbols_nl_SX = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mln.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mln.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mln.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mld.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mld.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mld.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bln.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bln.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bln.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 duizend'
    -    },
    -    '10000': {
    -      'other': '00 duizend'
    -    },
    -    '100000': {
    -      'other': '000 duizend'
    -    },
    -    '1000000': {
    -      'other': '0 miljoen'
    -    },
    -    '10000000': {
    -      'other': '00 miljoen'
    -    },
    -    '100000000': {
    -      'other': '000 miljoen'
    -    },
    -    '1000000000': {
    -      'other': '0 miljard'
    -    },
    -    '10000000000': {
    -      'other': '00 miljard'
    -    },
    -    '100000000000': {
    -      'other': '000 miljard'
    -    },
    -    '1000000000000': {
    -      'other': '0 biljoen'
    -    },
    -    '10000000000000': {
    -      'other': '00 biljoen'
    -    },
    -    '100000000000000': {
    -      'other': '000 biljoen'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale nmg.
    - */
    -goog.i18n.CompactNumberFormatSymbols_nmg = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale nmg_CM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_nmg_CM =
    -    goog.i18n.CompactNumberFormatSymbols_nmg;
    -
    -
    -/**
    - * Compact number formatting symbols for locale nn.
    - */
    -goog.i18n.CompactNumberFormatSymbols_nn = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0tn'
    -    },
    -    '10000': {
    -      'other': '00\u00A0tn'
    -    },
    -    '100000': {
    -      'other': '000\u00A0tn'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mn'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mn'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mn'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 tusen'
    -    },
    -    '10000': {
    -      'other': '00 tusen'
    -    },
    -    '100000': {
    -      'other': '000 tusen'
    -    },
    -    '1000000': {
    -      'other': '0 millioner'
    -    },
    -    '10000000': {
    -      'other': '00 millioner'
    -    },
    -    '100000000': {
    -      'other': '000 millioner'
    -    },
    -    '1000000000': {
    -      'other': '0 milliarder'
    -    },
    -    '10000000000': {
    -      'other': '00 milliarder'
    -    },
    -    '100000000000': {
    -      'other': '000 milliarder'
    -    },
    -    '1000000000000': {
    -      'other': '0 billioner'
    -    },
    -    '10000000000000': {
    -      'other': '00 billioner'
    -    },
    -    '100000000000000': {
    -      'other': '000 billioner'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale nn_NO.
    - */
    -goog.i18n.CompactNumberFormatSymbols_nn_NO =
    -    goog.i18n.CompactNumberFormatSymbols_nn;
    -
    -
    -/**
    - * Compact number formatting symbols for locale nnh.
    - */
    -goog.i18n.CompactNumberFormatSymbols_nnh = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale nnh_CM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_nnh_CM =
    -    goog.i18n.CompactNumberFormatSymbols_nnh;
    -
    -
    -/**
    - * Compact number formatting symbols for locale nr.
    - */
    -goog.i18n.CompactNumberFormatSymbols_nr = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale nr_ZA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_nr_ZA =
    -    goog.i18n.CompactNumberFormatSymbols_nr;
    -
    -
    -/**
    - * Compact number formatting symbols for locale nso.
    - */
    -goog.i18n.CompactNumberFormatSymbols_nso = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale nso_ZA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_nso_ZA =
    -    goog.i18n.CompactNumberFormatSymbols_nso;
    -
    -
    -/**
    - * Compact number formatting symbols for locale nus.
    - */
    -goog.i18n.CompactNumberFormatSymbols_nus = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale nus_SD.
    - */
    -goog.i18n.CompactNumberFormatSymbols_nus_SD =
    -    goog.i18n.CompactNumberFormatSymbols_nus;
    -
    -
    -/**
    - * Compact number formatting symbols for locale nyn.
    - */
    -goog.i18n.CompactNumberFormatSymbols_nyn = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale nyn_UG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_nyn_UG =
    -    goog.i18n.CompactNumberFormatSymbols_nyn;
    -
    -
    -/**
    - * Compact number formatting symbols for locale om.
    - */
    -goog.i18n.CompactNumberFormatSymbols_om = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale om_ET.
    - */
    -goog.i18n.CompactNumberFormatSymbols_om_ET =
    -    goog.i18n.CompactNumberFormatSymbols_om;
    -
    -
    -/**
    - * Compact number formatting symbols for locale om_KE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_om_KE = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale os.
    - */
    -goog.i18n.CompactNumberFormatSymbols_os = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale os_GE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_os_GE =
    -    goog.i18n.CompactNumberFormatSymbols_os;
    -
    -
    -/**
    - * Compact number formatting symbols for locale os_RU.
    - */
    -goog.i18n.CompactNumberFormatSymbols_os_RU = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale pa_Arab.
    - */
    -goog.i18n.CompactNumberFormatSymbols_pa_Arab = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale pa_Arab_PK.
    - */
    -goog.i18n.CompactNumberFormatSymbols_pa_Arab_PK =
    -    goog.i18n.CompactNumberFormatSymbols_pa_Arab;
    -
    -
    -/**
    - * Compact number formatting symbols for locale pa_Guru.
    - */
    -goog.i18n.CompactNumberFormatSymbols_pa_Guru = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0A39\u0A1C\u0A3C\u0A3E\u0A30'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0A39\u0A1C\u0A3C\u0A3E\u0A30'
    -    },
    -    '100000': {
    -      'other': '0\u00A0\u0A32\u0A71\u0A16'
    -    },
    -    '1000000': {
    -      'other': '00\u00A0\u0A32\u0A71\u0A16'
    -    },
    -    '10000000': {
    -      'other': '0\u00A0\u0A15\u0A30\u0A4B\u0A5C'
    -    },
    -    '100000000': {
    -      'other': '00\u00A0\u0A15\u0A30\u0A4B\u0A5C'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0A05\u0A30\u0A2C'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0A05\u0A30\u0A2C'
    -    },
    -    '100000000000': {
    -      'other': '0\u00A0\u0A16\u0A30\u0A2C'
    -    },
    -    '1000000000000': {
    -      'other': '00\u00A0\u0A16\u0A30\u0A2C'
    -    },
    -    '10000000000000': {
    -      'other': '0\u00A0\u0A28\u0A40\u0A32'
    -    },
    -    '100000000000000': {
    -      'other': '00\u00A0\u0A28\u0A40\u0A32'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0A39\u0A1C\u0A3C\u0A3E\u0A30'
    -    },
    -    '10000': {
    -      'other': '00 \u0A39\u0A1C\u0A3C\u0A3E\u0A30'
    -    },
    -    '100000': {
    -      'other': '0 \u0A32\u0A71\u0A16'
    -    },
    -    '1000000': {
    -      'other': '00 \u0A32\u0A71\u0A16'
    -    },
    -    '10000000': {
    -      'other': '0 \u0A15\u0A30\u0A4B\u0A5C'
    -    },
    -    '100000000': {
    -      'other': '00 \u0A15\u0A30\u0A4B\u0A5C'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0A05\u0A30\u0A2C'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0A05\u0A30\u0A2C'
    -    },
    -    '100000000000': {
    -      'other': '0 \u0A16\u0A30\u0A2C'
    -    },
    -    '1000000000000': {
    -      'other': '00 \u0A16\u0A30\u0A2C'
    -    },
    -    '10000000000000': {
    -      'other': '0 \u0A28\u0A40\u0A32'
    -    },
    -    '100000000000000': {
    -      'other': '00 \u0A28\u0A40\u0A32'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ps.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ps = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ps_AF.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ps_AF =
    -    goog.i18n.CompactNumberFormatSymbols_ps;
    -
    -
    -/**
    - * Compact number formatting symbols for locale pt_AO.
    - */
    -goog.i18n.CompactNumberFormatSymbols_pt_AO = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0mil'
    -    },
    -    '10000': {
    -      'other': '00\u00A0mil'
    -    },
    -    '100000': {
    -      'other': '000\u00A0mil'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0MM'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0MM'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0MM'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bi'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bi'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bi'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 milh\u00F5es'
    -    },
    -    '10000000': {
    -      'other': '00 milh\u00F5es'
    -    },
    -    '100000000': {
    -      'other': '000 milh\u00F5es'
    -    },
    -    '1000000000': {
    -      'other': '0 mil milh\u00F5es'
    -    },
    -    '10000000000': {
    -      'other': '00 mil milh\u00F5es'
    -    },
    -    '100000000000': {
    -      'other': '000 mil milh\u00F5es'
    -    },
    -    '1000000000000': {
    -      'other': '0 bili\u00F5es'
    -    },
    -    '10000000000000': {
    -      'other': '00 bili\u00F5es'
    -    },
    -    '100000000000000': {
    -      'other': '000 bili\u00F5es'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale pt_CV.
    - */
    -goog.i18n.CompactNumberFormatSymbols_pt_CV = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0mil'
    -    },
    -    '10000': {
    -      'other': '00\u00A0mil'
    -    },
    -    '100000': {
    -      'other': '000\u00A0mil'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0MM'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0MM'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0MM'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bi'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bi'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bi'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 milh\u00F5es'
    -    },
    -    '10000000': {
    -      'other': '00 milh\u00F5es'
    -    },
    -    '100000000': {
    -      'other': '000 milh\u00F5es'
    -    },
    -    '1000000000': {
    -      'other': '0 mil milh\u00F5es'
    -    },
    -    '10000000000': {
    -      'other': '00 mil milh\u00F5es'
    -    },
    -    '100000000000': {
    -      'other': '000 mil milh\u00F5es'
    -    },
    -    '1000000000000': {
    -      'other': '0 bili\u00F5es'
    -    },
    -    '10000000000000': {
    -      'other': '00 bili\u00F5es'
    -    },
    -    '100000000000000': {
    -      'other': '000 bili\u00F5es'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale pt_GW.
    - */
    -goog.i18n.CompactNumberFormatSymbols_pt_GW = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0mil'
    -    },
    -    '10000': {
    -      'other': '00\u00A0mil'
    -    },
    -    '100000': {
    -      'other': '000\u00A0mil'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0MM'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0MM'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0MM'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bi'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bi'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bi'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 milh\u00F5es'
    -    },
    -    '10000000': {
    -      'other': '00 milh\u00F5es'
    -    },
    -    '100000000': {
    -      'other': '000 milh\u00F5es'
    -    },
    -    '1000000000': {
    -      'other': '0 mil milh\u00F5es'
    -    },
    -    '10000000000': {
    -      'other': '00 mil milh\u00F5es'
    -    },
    -    '100000000000': {
    -      'other': '000 mil milh\u00F5es'
    -    },
    -    '1000000000000': {
    -      'other': '0 bili\u00F5es'
    -    },
    -    '10000000000000': {
    -      'other': '00 bili\u00F5es'
    -    },
    -    '100000000000000': {
    -      'other': '000 bili\u00F5es'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale pt_MO.
    - */
    -goog.i18n.CompactNumberFormatSymbols_pt_MO = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0mil'
    -    },
    -    '10000': {
    -      'other': '00\u00A0mil'
    -    },
    -    '100000': {
    -      'other': '000\u00A0mil'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0MM'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0MM'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0MM'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bi'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bi'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bi'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 milh\u00F5es'
    -    },
    -    '10000000': {
    -      'other': '00 milh\u00F5es'
    -    },
    -    '100000000': {
    -      'other': '000 milh\u00F5es'
    -    },
    -    '1000000000': {
    -      'other': '0 mil milh\u00F5es'
    -    },
    -    '10000000000': {
    -      'other': '00 mil milh\u00F5es'
    -    },
    -    '100000000000': {
    -      'other': '000 mil milh\u00F5es'
    -    },
    -    '1000000000000': {
    -      'other': '0 bili\u00F5es'
    -    },
    -    '10000000000000': {
    -      'other': '00 bili\u00F5es'
    -    },
    -    '100000000000000': {
    -      'other': '000 bili\u00F5es'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale pt_MZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_pt_MZ = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0mil'
    -    },
    -    '10000': {
    -      'other': '00\u00A0mil'
    -    },
    -    '100000': {
    -      'other': '000\u00A0mil'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0MM'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0MM'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0MM'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bi'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bi'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bi'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 milh\u00F5es'
    -    },
    -    '10000000': {
    -      'other': '00 milh\u00F5es'
    -    },
    -    '100000000': {
    -      'other': '000 milh\u00F5es'
    -    },
    -    '1000000000': {
    -      'other': '0 mil milh\u00F5es'
    -    },
    -    '10000000000': {
    -      'other': '00 mil milh\u00F5es'
    -    },
    -    '100000000000': {
    -      'other': '000 mil milh\u00F5es'
    -    },
    -    '1000000000000': {
    -      'other': '0 bili\u00F5es'
    -    },
    -    '10000000000000': {
    -      'other': '00 bili\u00F5es'
    -    },
    -    '100000000000000': {
    -      'other': '000 bili\u00F5es'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale pt_ST.
    - */
    -goog.i18n.CompactNumberFormatSymbols_pt_ST = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0mil'
    -    },
    -    '10000': {
    -      'other': '00\u00A0mil'
    -    },
    -    '100000': {
    -      'other': '000\u00A0mil'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0MM'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0MM'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0MM'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bi'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bi'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bi'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 milh\u00F5es'
    -    },
    -    '10000000': {
    -      'other': '00 milh\u00F5es'
    -    },
    -    '100000000': {
    -      'other': '000 milh\u00F5es'
    -    },
    -    '1000000000': {
    -      'other': '0 mil milh\u00F5es'
    -    },
    -    '10000000000': {
    -      'other': '00 mil milh\u00F5es'
    -    },
    -    '100000000000': {
    -      'other': '000 mil milh\u00F5es'
    -    },
    -    '1000000000000': {
    -      'other': '0 bili\u00F5es'
    -    },
    -    '10000000000000': {
    -      'other': '00 bili\u00F5es'
    -    },
    -    '100000000000000': {
    -      'other': '000 bili\u00F5es'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale pt_TL.
    - */
    -goog.i18n.CompactNumberFormatSymbols_pt_TL = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0mil'
    -    },
    -    '10000': {
    -      'other': '00\u00A0mil'
    -    },
    -    '100000': {
    -      'other': '000\u00A0mil'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0M'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0M'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0M'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0MM'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0MM'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0MM'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bi'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bi'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bi'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mil'
    -    },
    -    '10000': {
    -      'other': '00 mil'
    -    },
    -    '100000': {
    -      'other': '000 mil'
    -    },
    -    '1000000': {
    -      'other': '0 milh\u00F5es'
    -    },
    -    '10000000': {
    -      'other': '00 milh\u00F5es'
    -    },
    -    '100000000': {
    -      'other': '000 milh\u00F5es'
    -    },
    -    '1000000000': {
    -      'other': '0 mil milh\u00F5es'
    -    },
    -    '10000000000': {
    -      'other': '00 mil milh\u00F5es'
    -    },
    -    '100000000000': {
    -      'other': '000 mil milh\u00F5es'
    -    },
    -    '1000000000000': {
    -      'other': '0 bili\u00F5es'
    -    },
    -    '10000000000000': {
    -      'other': '00 bili\u00F5es'
    -    },
    -    '100000000000000': {
    -      'other': '000 bili\u00F5es'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale qu.
    - */
    -goog.i18n.CompactNumberFormatSymbols_qu = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale qu_BO.
    - */
    -goog.i18n.CompactNumberFormatSymbols_qu_BO = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale qu_EC.
    - */
    -goog.i18n.CompactNumberFormatSymbols_qu_EC = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale qu_PE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_qu_PE =
    -    goog.i18n.CompactNumberFormatSymbols_qu;
    -
    -
    -/**
    - * Compact number formatting symbols for locale rm.
    - */
    -goog.i18n.CompactNumberFormatSymbols_rm = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale rm_CH.
    - */
    -goog.i18n.CompactNumberFormatSymbols_rm_CH =
    -    goog.i18n.CompactNumberFormatSymbols_rm;
    -
    -
    -/**
    - * Compact number formatting symbols for locale rn.
    - */
    -goog.i18n.CompactNumberFormatSymbols_rn = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale rn_BI.
    - */
    -goog.i18n.CompactNumberFormatSymbols_rn_BI =
    -    goog.i18n.CompactNumberFormatSymbols_rn;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ro_MD.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ro_MD = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0K'
    -    },
    -    '10000': {
    -      'other': '00\u00A0K'
    -    },
    -    '100000': {
    -      'other': '000\u00A0K'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mil.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mil.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mil.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mld.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mld.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mld.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0tril.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0tril.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0tril.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 de mii'
    -    },
    -    '10000': {
    -      'other': '00 de mii'
    -    },
    -    '100000': {
    -      'other': '000 de mii'
    -    },
    -    '1000000': {
    -      'other': '0 de milioane'
    -    },
    -    '10000000': {
    -      'other': '00 de milioane'
    -    },
    -    '100000000': {
    -      'other': '000 de milioane'
    -    },
    -    '1000000000': {
    -      'other': '0 de miliarde'
    -    },
    -    '10000000000': {
    -      'other': '00 de miliarde'
    -    },
    -    '100000000000': {
    -      'other': '000 de miliarde'
    -    },
    -    '1000000000000': {
    -      'other': '0 de trilioane'
    -    },
    -    '10000000000000': {
    -      'other': '00 de trilioane'
    -    },
    -    '100000000000000': {
    -      'other': '000 de trilioane'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale rof.
    - */
    -goog.i18n.CompactNumberFormatSymbols_rof = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale rof_TZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_rof_TZ =
    -    goog.i18n.CompactNumberFormatSymbols_rof;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ru_BY.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ru_BY = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0442\u044B\u0441.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0442\u044B\u0441.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0442\u044B\u0441.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u043C\u043B\u043D'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u043C\u043B\u043D'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u043C\u043B\u043D'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u0442\u0440\u043B\u043D'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u0442\u0440\u043B\u043D'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u0442\u0440\u043B\u043D'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0442\u044B\u0441\u044F\u0447\u0438'
    -    },
    -    '10000': {
    -      'other': '00 \u0442\u044B\u0441\u044F\u0447\u0438'
    -    },
    -    '100000': {
    -      'other': '000 \u0442\u044B\u0441\u044F\u0447\u0438'
    -    },
    -    '1000000': {
    -      'other': '0 \u043C\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '10000000': {
    -      'other': '00 \u043C\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '100000000': {
    -      'other': '000 \u043C\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '1000000000': {
    -      'other': '0 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434\u0430'
    -    },
    -    '10000000000': {
    -      'other': '00 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434\u0430'
    -    },
    -    '100000000000': {
    -      'other': '000 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434\u0430'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0442\u0440\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0442\u0440\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0442\u0440\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ru_KG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ru_KG = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0442\u044B\u0441.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0442\u044B\u0441.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0442\u044B\u0441.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u043C\u043B\u043D'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u043C\u043B\u043D'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u043C\u043B\u043D'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u0442\u0440\u043B\u043D'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u0442\u0440\u043B\u043D'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u0442\u0440\u043B\u043D'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0442\u044B\u0441\u044F\u0447\u0438'
    -    },
    -    '10000': {
    -      'other': '00 \u0442\u044B\u0441\u044F\u0447\u0438'
    -    },
    -    '100000': {
    -      'other': '000 \u0442\u044B\u0441\u044F\u0447\u0438'
    -    },
    -    '1000000': {
    -      'other': '0 \u043C\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '10000000': {
    -      'other': '00 \u043C\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '100000000': {
    -      'other': '000 \u043C\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '1000000000': {
    -      'other': '0 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434\u0430'
    -    },
    -    '10000000000': {
    -      'other': '00 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434\u0430'
    -    },
    -    '100000000000': {
    -      'other': '000 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434\u0430'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0442\u0440\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0442\u0440\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0442\u0440\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ru_KZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ru_KZ = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0442\u044B\u0441.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0442\u044B\u0441.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0442\u044B\u0441.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u043C\u043B\u043D'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u043C\u043B\u043D'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u043C\u043B\u043D'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u0442\u0440\u043B\u043D'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u0442\u0440\u043B\u043D'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u0442\u0440\u043B\u043D'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0442\u044B\u0441\u044F\u0447\u0438'
    -    },
    -    '10000': {
    -      'other': '00 \u0442\u044B\u0441\u044F\u0447\u0438'
    -    },
    -    '100000': {
    -      'other': '000 \u0442\u044B\u0441\u044F\u0447\u0438'
    -    },
    -    '1000000': {
    -      'other': '0 \u043C\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '10000000': {
    -      'other': '00 \u043C\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '100000000': {
    -      'other': '000 \u043C\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '1000000000': {
    -      'other': '0 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434\u0430'
    -    },
    -    '10000000000': {
    -      'other': '00 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434\u0430'
    -    },
    -    '100000000000': {
    -      'other': '000 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434\u0430'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0442\u0440\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0442\u0440\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0442\u0440\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ru_MD.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ru_MD = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0442\u044B\u0441.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0442\u044B\u0441.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0442\u044B\u0441.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u043C\u043B\u043D'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u043C\u043B\u043D'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u043C\u043B\u043D'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u0442\u0440\u043B\u043D'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u0442\u0440\u043B\u043D'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u0442\u0440\u043B\u043D'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0442\u044B\u0441\u044F\u0447\u0438'
    -    },
    -    '10000': {
    -      'other': '00 \u0442\u044B\u0441\u044F\u0447\u0438'
    -    },
    -    '100000': {
    -      'other': '000 \u0442\u044B\u0441\u044F\u0447\u0438'
    -    },
    -    '1000000': {
    -      'other': '0 \u043C\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '10000000': {
    -      'other': '00 \u043C\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '100000000': {
    -      'other': '000 \u043C\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '1000000000': {
    -      'other': '0 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434\u0430'
    -    },
    -    '10000000000': {
    -      'other': '00 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434\u0430'
    -    },
    -    '100000000000': {
    -      'other': '000 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434\u0430'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0442\u0440\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0442\u0440\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0442\u0440\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ru_UA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ru_UA = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0442\u044B\u0441.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0442\u044B\u0441.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0442\u044B\u0441.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u043C\u043B\u043D'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u043C\u043B\u043D'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u043C\u043B\u043D'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u043C\u043B\u0440\u0434'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u0442\u0440\u043B\u043D'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u0442\u0440\u043B\u043D'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u0442\u0440\u043B\u043D'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0442\u044B\u0441\u044F\u0447\u0438'
    -    },
    -    '10000': {
    -      'other': '00 \u0442\u044B\u0441\u044F\u0447\u0438'
    -    },
    -    '100000': {
    -      'other': '000 \u0442\u044B\u0441\u044F\u0447\u0438'
    -    },
    -    '1000000': {
    -      'other': '0 \u043C\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '10000000': {
    -      'other': '00 \u043C\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '100000000': {
    -      'other': '000 \u043C\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '1000000000': {
    -      'other': '0 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434\u0430'
    -    },
    -    '10000000000': {
    -      'other': '00 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434\u0430'
    -    },
    -    '100000000000': {
    -      'other': '000 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434\u0430'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0442\u0440\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0442\u0440\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0442\u0440\u0438\u043B\u043B\u0438\u043E\u043D\u0430'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale rw.
    - */
    -goog.i18n.CompactNumberFormatSymbols_rw = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale rw_RW.
    - */
    -goog.i18n.CompactNumberFormatSymbols_rw_RW =
    -    goog.i18n.CompactNumberFormatSymbols_rw;
    -
    -
    -/**
    - * Compact number formatting symbols for locale rwk.
    - */
    -goog.i18n.CompactNumberFormatSymbols_rwk = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale rwk_TZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_rwk_TZ =
    -    goog.i18n.CompactNumberFormatSymbols_rwk;
    -
    -
    -/**
    - * Compact number formatting symbols for locale sah.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sah = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale sah_RU.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sah_RU =
    -    goog.i18n.CompactNumberFormatSymbols_sah;
    -
    -
    -/**
    - * Compact number formatting symbols for locale saq.
    - */
    -goog.i18n.CompactNumberFormatSymbols_saq = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale saq_KE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_saq_KE =
    -    goog.i18n.CompactNumberFormatSymbols_saq;
    -
    -
    -/**
    - * Compact number formatting symbols for locale sbp.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sbp = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale sbp_TZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sbp_TZ =
    -    goog.i18n.CompactNumberFormatSymbols_sbp;
    -
    -
    -/**
    - * Compact number formatting symbols for locale se.
    - */
    -goog.i18n.CompactNumberFormatSymbols_se = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0dt'
    -    },
    -    '10000': {
    -      'other': '00\u00A0dt'
    -    },
    -    '100000': {
    -      'other': '000\u00A0dt'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mn'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mn'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mn'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 duh\u00E1hat'
    -    },
    -    '10000': {
    -      'other': '00 duh\u00E1hat'
    -    },
    -    '100000': {
    -      'other': '000 duh\u00E1hat'
    -    },
    -    '1000000': {
    -      'other': '0 miljonat'
    -    },
    -    '10000000': {
    -      'other': '00 miljonat'
    -    },
    -    '100000000': {
    -      'other': '000 miljonat'
    -    },
    -    '1000000000': {
    -      'other': '0 miljardit'
    -    },
    -    '10000000000': {
    -      'other': '00 miljardit'
    -    },
    -    '100000000000': {
    -      'other': '000 miljardit'
    -    },
    -    '1000000000000': {
    -      'other': '0 biljonat'
    -    },
    -    '10000000000000': {
    -      'other': '00 biljonat'
    -    },
    -    '100000000000000': {
    -      'other': '000 biljonat'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale se_FI.
    - */
    -goog.i18n.CompactNumberFormatSymbols_se_FI = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0dt'
    -    },
    -    '10000': {
    -      'other': '00\u00A0dt'
    -    },
    -    '100000': {
    -      'other': '000\u00A0dt'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mn'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mn'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mn'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 duh\u00E1hat'
    -    },
    -    '10000': {
    -      'other': '00 duh\u00E1hat'
    -    },
    -    '100000': {
    -      'other': '000 duh\u00E1hat'
    -    },
    -    '1000000': {
    -      'other': '0 miljonat'
    -    },
    -    '10000000': {
    -      'other': '00 miljonat'
    -    },
    -    '100000000': {
    -      'other': '000 miljonat'
    -    },
    -    '1000000000': {
    -      'other': '0 miljardit'
    -    },
    -    '10000000000': {
    -      'other': '00 miljardit'
    -    },
    -    '100000000000': {
    -      'other': '000 miljardit'
    -    },
    -    '1000000000000': {
    -      'other': '0 biljonat'
    -    },
    -    '10000000000000': {
    -      'other': '00 biljonat'
    -    },
    -    '100000000000000': {
    -      'other': '000 biljonat'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale se_NO.
    - */
    -goog.i18n.CompactNumberFormatSymbols_se_NO =
    -    goog.i18n.CompactNumberFormatSymbols_se;
    -
    -
    -/**
    - * Compact number formatting symbols for locale se_SE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_se_SE = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0dt'
    -    },
    -    '10000': {
    -      'other': '00\u00A0dt'
    -    },
    -    '100000': {
    -      'other': '000\u00A0dt'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mn'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mn'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mn'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 duh\u00E1hat'
    -    },
    -    '10000': {
    -      'other': '00 duh\u00E1hat'
    -    },
    -    '100000': {
    -      'other': '000 duh\u00E1hat'
    -    },
    -    '1000000': {
    -      'other': '0 miljonat'
    -    },
    -    '10000000': {
    -      'other': '00 miljonat'
    -    },
    -    '100000000': {
    -      'other': '000 miljonat'
    -    },
    -    '1000000000': {
    -      'other': '0 miljardit'
    -    },
    -    '10000000000': {
    -      'other': '00 miljardit'
    -    },
    -    '100000000000': {
    -      'other': '000 miljardit'
    -    },
    -    '1000000000000': {
    -      'other': '0 biljonat'
    -    },
    -    '10000000000000': {
    -      'other': '00 biljonat'
    -    },
    -    '100000000000000': {
    -      'other': '000 biljonat'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale seh.
    - */
    -goog.i18n.CompactNumberFormatSymbols_seh = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale seh_MZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_seh_MZ =
    -    goog.i18n.CompactNumberFormatSymbols_seh;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ses.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ses = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ses_ML.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ses_ML =
    -    goog.i18n.CompactNumberFormatSymbols_ses;
    -
    -
    -/**
    - * Compact number formatting symbols for locale sg.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sg = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale sg_CF.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sg_CF =
    -    goog.i18n.CompactNumberFormatSymbols_sg;
    -
    -
    -/**
    - * Compact number formatting symbols for locale shi.
    - */
    -goog.i18n.CompactNumberFormatSymbols_shi = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale shi_Latn.
    - */
    -goog.i18n.CompactNumberFormatSymbols_shi_Latn = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale shi_Latn_MA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_shi_Latn_MA =
    -    goog.i18n.CompactNumberFormatSymbols_shi;
    -
    -
    -/**
    - * Compact number formatting symbols for locale shi_Tfng.
    - */
    -goog.i18n.CompactNumberFormatSymbols_shi_Tfng = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale shi_Tfng_MA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_shi_Tfng_MA =
    -    goog.i18n.CompactNumberFormatSymbols_shi;
    -
    -
    -/**
    - * Compact number formatting symbols for locale smn.
    - */
    -goog.i18n.CompactNumberFormatSymbols_smn = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 tuhh\u00E1\u00E1t'
    -    },
    -    '10000': {
    -      'other': '00 tuhh\u00E1\u00E1t'
    -    },
    -    '100000': {
    -      'other': '000 tuhh\u00E1\u00E1t'
    -    },
    -    '1000000': {
    -      'other': '0 miljovn'
    -    },
    -    '10000000': {
    -      'other': '00 miljovn'
    -    },
    -    '100000000': {
    -      'other': '000 miljovn'
    -    },
    -    '1000000000': {
    -      'other': '0 miljard'
    -    },
    -    '10000000000': {
    -      'other': '00 miljard'
    -    },
    -    '100000000000': {
    -      'other': '000 miljard'
    -    },
    -    '1000000000000': {
    -      'other': '0 biljovn'
    -    },
    -    '10000000000000': {
    -      'other': '00 biljovn'
    -    },
    -    '100000000000000': {
    -      'other': '000 biljovn'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale smn_FI.
    - */
    -goog.i18n.CompactNumberFormatSymbols_smn_FI =
    -    goog.i18n.CompactNumberFormatSymbols_smn;
    -
    -
    -/**
    - * Compact number formatting symbols for locale sn.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sn = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale sn_ZW.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sn_ZW =
    -    goog.i18n.CompactNumberFormatSymbols_sn;
    -
    -
    -/**
    - * Compact number formatting symbols for locale so.
    - */
    -goog.i18n.CompactNumberFormatSymbols_so = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale so_DJ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_so_DJ = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale so_ET.
    - */
    -goog.i18n.CompactNumberFormatSymbols_so_ET = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale so_KE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_so_KE = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale so_SO.
    - */
    -goog.i18n.CompactNumberFormatSymbols_so_SO =
    -    goog.i18n.CompactNumberFormatSymbols_so;
    -
    -
    -/**
    - * Compact number formatting symbols for locale sq_MK.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sq_MK = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0mij\u00EB'
    -    },
    -    '10000': {
    -      'other': '00\u00A0mij\u00EB'
    -    },
    -    '100000': {
    -      'other': '000\u00A0mij\u00EB'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0Mln'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0Mln'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0Mln'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Mld'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Mld'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Mld'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bln'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bln'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bln'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mij\u00EB'
    -    },
    -    '10000': {
    -      'other': '00 mij\u00EB'
    -    },
    -    '100000': {
    -      'other': '000 mij\u00EB'
    -    },
    -    '1000000': {
    -      'other': '0 milion'
    -    },
    -    '10000000': {
    -      'other': '00 milion'
    -    },
    -    '100000000': {
    -      'other': '000 milion'
    -    },
    -    '1000000000': {
    -      'other': '0 miliard'
    -    },
    -    '10000000000': {
    -      'other': '00 miliard'
    -    },
    -    '100000000000': {
    -      'other': '000 miliard'
    -    },
    -    '1000000000000': {
    -      'other': '0 bilion'
    -    },
    -    '10000000000000': {
    -      'other': '00 bilion'
    -    },
    -    '100000000000000': {
    -      'other': '000 bilion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale sq_XK.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sq_XK = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0mij\u00EB'
    -    },
    -    '10000': {
    -      'other': '00\u00A0mij\u00EB'
    -    },
    -    '100000': {
    -      'other': '000\u00A0mij\u00EB'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0Mln'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0Mln'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0Mln'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Mld'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Mld'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Mld'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Bln'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Bln'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Bln'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 mij\u00EB'
    -    },
    -    '10000': {
    -      'other': '00 mij\u00EB'
    -    },
    -    '100000': {
    -      'other': '000 mij\u00EB'
    -    },
    -    '1000000': {
    -      'other': '0 milion'
    -    },
    -    '10000000': {
    -      'other': '00 milion'
    -    },
    -    '100000000': {
    -      'other': '000 milion'
    -    },
    -    '1000000000': {
    -      'other': '0 miliard'
    -    },
    -    '10000000000': {
    -      'other': '00 miliard'
    -    },
    -    '100000000000': {
    -      'other': '000 miliard'
    -    },
    -    '1000000000000': {
    -      'other': '0 bilion'
    -    },
    -    '10000000000000': {
    -      'other': '00 bilion'
    -    },
    -    '100000000000000': {
    -      'other': '000 bilion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale sr_Cyrl.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sr_Cyrl = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0445\u0438\u0459.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0445\u0438\u0459.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0445\u0438\u0459.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u043C\u0438\u043B.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u043C\u0438\u043B.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u043C\u0438\u043B.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u043C\u043B\u0440\u0434.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u043C\u043B\u0440\u0434.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u043C\u043B\u0440\u0434.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u0431\u0438\u043B.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u0431\u0438\u043B.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u0431\u0438\u043B.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0445\u0438\u0459\u0430\u0434\u0430'
    -    },
    -    '10000': {
    -      'other': '00 \u0445\u0438\u0459\u0430\u0434\u0430'
    -    },
    -    '100000': {
    -      'other': '000 \u0445\u0438\u0459\u0430\u0434\u0430'
    -    },
    -    '1000000': {
    -      'other': '0 \u043C\u0438\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '10000000': {
    -      'other': '00 \u043C\u0438\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '100000000': {
    -      'other': '000 \u043C\u0438\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '1000000000': {
    -      'other': '0 \u043C\u0438\u043B\u0438\u0458\u0430\u0440\u0434\u0438'
    -    },
    -    '10000000000': {
    -      'other': '00 \u043C\u0438\u043B\u0438\u0458\u0430\u0440\u0434\u0438'
    -    },
    -    '100000000000': {
    -      'other': '000 \u043C\u0438\u043B\u0438\u0458\u0430\u0440\u0434\u0438'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0442\u0440\u0438\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0442\u0440\u0438\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0442\u0440\u0438\u043B\u0438\u043E\u043D\u0430'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale sr_Cyrl_BA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sr_Cyrl_BA = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u0445\u0438\u0459.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u0445\u0438\u0459.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0\u0445\u0438\u0459.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0\u043C\u0438\u043B.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0\u043C\u0438\u043B.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0\u043C\u0438\u043B.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u043C\u043B\u0440\u0434.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u043C\u043B\u0440\u0434.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0\u043C\u043B\u0440\u0434.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0\u0431\u0438\u043B.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u0431\u0438\u043B.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u0431\u0438\u043B.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0445\u0438\u0459\u0430\u0434\u0430'
    -    },
    -    '10000': {
    -      'other': '00 \u0445\u0438\u0459\u0430\u0434\u0430'
    -    },
    -    '100000': {
    -      'other': '000 \u0445\u0438\u0459\u0430\u0434\u0430'
    -    },
    -    '1000000': {
    -      'other': '0 \u043C\u0438\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '10000000': {
    -      'other': '00 \u043C\u0438\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '100000000': {
    -      'other': '000 \u043C\u0438\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '1000000000': {
    -      'other': '0 \u043C\u0438\u043B\u0438\u0458\u0430\u0440\u0434\u0438'
    -    },
    -    '10000000000': {
    -      'other': '00 \u043C\u0438\u043B\u0438\u0458\u0430\u0440\u0434\u0438'
    -    },
    -    '100000000000': {
    -      'other': '000 \u043C\u0438\u043B\u0438\u0458\u0430\u0440\u0434\u0438'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0442\u0440\u0438\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0442\u0440\u0438\u043B\u0438\u043E\u043D\u0430'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0442\u0440\u0438\u043B\u0438\u043E\u043D\u0430'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale sr_Cyrl_ME.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sr_Cyrl_ME =
    -    goog.i18n.CompactNumberFormatSymbols_sr_Cyrl;
    -
    -
    -/**
    - * Compact number formatting symbols for locale sr_Cyrl_XK.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sr_Cyrl_XK =
    -    goog.i18n.CompactNumberFormatSymbols_sr_Cyrl;
    -
    -
    -/**
    - * Compact number formatting symbols for locale sr_Latn.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sr_Latn = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0hilj.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0hilj.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0hilj.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mil.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mil.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mil.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mlrd.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mlrd.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mlrd.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bil.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bil.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bil.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 hiljada'
    -    },
    -    '10000': {
    -      'other': '00 hiljada'
    -    },
    -    '100000': {
    -      'other': '000 hiljada'
    -    },
    -    '1000000': {
    -      'other': '0 miliona'
    -    },
    -    '10000000': {
    -      'other': '00 miliona'
    -    },
    -    '100000000': {
    -      'other': '000 miliona'
    -    },
    -    '1000000000': {
    -      'other': '0 milijardi'
    -    },
    -    '10000000000': {
    -      'other': '00 milijardi'
    -    },
    -    '100000000000': {
    -      'other': '000 milijardi'
    -    },
    -    '1000000000000': {
    -      'other': '0 triliona'
    -    },
    -    '10000000000000': {
    -      'other': '00 triliona'
    -    },
    -    '100000000000000': {
    -      'other': '000 triliona'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale sr_Latn_BA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sr_Latn_BA = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0hilj.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0hilj.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0hilj.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mil.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mil.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mil.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mlrd.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mlrd.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mlrd.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bil.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bil.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bil.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 hiljada'
    -    },
    -    '10000': {
    -      'other': '00 hiljada'
    -    },
    -    '100000': {
    -      'other': '000 hiljada'
    -    },
    -    '1000000': {
    -      'other': '0 miliona'
    -    },
    -    '10000000': {
    -      'other': '00 miliona'
    -    },
    -    '100000000': {
    -      'other': '000 miliona'
    -    },
    -    '1000000000': {
    -      'other': '0 milijardi'
    -    },
    -    '10000000000': {
    -      'other': '00 milijardi'
    -    },
    -    '100000000000': {
    -      'other': '000 milijardi'
    -    },
    -    '1000000000000': {
    -      'other': '0 triliona'
    -    },
    -    '10000000000000': {
    -      'other': '00 triliona'
    -    },
    -    '100000000000000': {
    -      'other': '000 triliona'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale sr_Latn_ME.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sr_Latn_ME = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0hilj.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0hilj.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0hilj.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mil.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mil.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mil.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mlrd.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mlrd.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mlrd.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bil.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bil.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bil.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 hiljada'
    -    },
    -    '10000': {
    -      'other': '00 hiljada'
    -    },
    -    '100000': {
    -      'other': '000 hiljada'
    -    },
    -    '1000000': {
    -      'other': '0 miliona'
    -    },
    -    '10000000': {
    -      'other': '00 miliona'
    -    },
    -    '100000000': {
    -      'other': '000 miliona'
    -    },
    -    '1000000000': {
    -      'other': '0 milijardi'
    -    },
    -    '10000000000': {
    -      'other': '00 milijardi'
    -    },
    -    '100000000000': {
    -      'other': '000 milijardi'
    -    },
    -    '1000000000000': {
    -      'other': '0 triliona'
    -    },
    -    '10000000000000': {
    -      'other': '00 triliona'
    -    },
    -    '100000000000000': {
    -      'other': '000 triliona'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale sr_Latn_RS.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sr_Latn_RS =
    -    goog.i18n.CompactNumberFormatSymbols_sr_Latn;
    -
    -
    -/**
    - * Compact number formatting symbols for locale sr_Latn_XK.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sr_Latn_XK = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0hilj.'
    -    },
    -    '10000': {
    -      'other': '00\u00A0hilj.'
    -    },
    -    '100000': {
    -      'other': '000\u00A0hilj.'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mil.'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mil.'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mil.'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0mlrd.'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0mlrd.'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0mlrd.'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bil.'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bil.'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bil.'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 hiljada'
    -    },
    -    '10000': {
    -      'other': '00 hiljada'
    -    },
    -    '100000': {
    -      'other': '000 hiljada'
    -    },
    -    '1000000': {
    -      'other': '0 miliona'
    -    },
    -    '10000000': {
    -      'other': '00 miliona'
    -    },
    -    '100000000': {
    -      'other': '000 miliona'
    -    },
    -    '1000000000': {
    -      'other': '0 milijardi'
    -    },
    -    '10000000000': {
    -      'other': '00 milijardi'
    -    },
    -    '100000000000': {
    -      'other': '000 milijardi'
    -    },
    -    '1000000000000': {
    -      'other': '0 triliona'
    -    },
    -    '10000000000000': {
    -      'other': '00 triliona'
    -    },
    -    '100000000000000': {
    -      'other': '000 triliona'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ss.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ss = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ss_SZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ss_SZ = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ss_ZA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ss_ZA =
    -    goog.i18n.CompactNumberFormatSymbols_ss;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ssy.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ssy = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ssy_ER.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ssy_ER =
    -    goog.i18n.CompactNumberFormatSymbols_ssy;
    -
    -
    -/**
    - * Compact number formatting symbols for locale sv_AX.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sv_AX = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0tn'
    -    },
    -    '10000': {
    -      'other': '00\u00A0tn'
    -    },
    -    '100000': {
    -      'other': '000\u00A0tn'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mn'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mn'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mn'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 tusen'
    -    },
    -    '10000': {
    -      'other': '00 tusen'
    -    },
    -    '100000': {
    -      'other': '000 tusen'
    -    },
    -    '1000000': {
    -      'other': '0 miljoner'
    -    },
    -    '10000000': {
    -      'other': '00 miljoner'
    -    },
    -    '100000000': {
    -      'other': '000 miljoner'
    -    },
    -    '1000000000': {
    -      'other': '0 miljarder'
    -    },
    -    '10000000000': {
    -      'other': '00 miljarder'
    -    },
    -    '100000000000': {
    -      'other': '000 miljarder'
    -    },
    -    '1000000000000': {
    -      'other': '0 biljoner'
    -    },
    -    '10000000000000': {
    -      'other': '00 biljoner'
    -    },
    -    '100000000000000': {
    -      'other': '000 biljoner'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale sv_FI.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sv_FI = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0tn'
    -    },
    -    '10000': {
    -      'other': '00\u00A0tn'
    -    },
    -    '100000': {
    -      'other': '000\u00A0tn'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0mn'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0mn'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0mn'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0md'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0md'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0md'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0bn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0bn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0bn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 tusen'
    -    },
    -    '10000': {
    -      'other': '00 tusen'
    -    },
    -    '100000': {
    -      'other': '000 tusen'
    -    },
    -    '1000000': {
    -      'other': '0 miljoner'
    -    },
    -    '10000000': {
    -      'other': '00 miljoner'
    -    },
    -    '100000000': {
    -      'other': '000 miljoner'
    -    },
    -    '1000000000': {
    -      'other': '0 miljarder'
    -    },
    -    '10000000000': {
    -      'other': '00 miljarder'
    -    },
    -    '100000000000': {
    -      'other': '000 miljarder'
    -    },
    -    '1000000000000': {
    -      'other': '0 biljoner'
    -    },
    -    '10000000000000': {
    -      'other': '00 biljoner'
    -    },
    -    '100000000000000': {
    -      'other': '000 biljoner'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale sw_KE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sw_KE = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': 'elfu\u00A00'
    -    },
    -    '10000': {
    -      'other': 'elfu\u00A000'
    -    },
    -    '100000': {
    -      'other': 'elfu\u00A0000'
    -    },
    -    '1000000': {
    -      'other': 'M0'
    -    },
    -    '10000000': {
    -      'other': 'M00'
    -    },
    -    '100000000': {
    -      'other': 'M000'
    -    },
    -    '1000000000': {
    -      'other': 'B0'
    -    },
    -    '10000000000': {
    -      'other': 'B00'
    -    },
    -    '100000000000': {
    -      'other': 'B000'
    -    },
    -    '1000000000000': {
    -      'other': 'T0'
    -    },
    -    '10000000000000': {
    -      'other': 'T00'
    -    },
    -    '100000000000000': {
    -      'other': 'T000'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': 'Elfu 0'
    -    },
    -    '10000': {
    -      'other': 'Elfu 00'
    -    },
    -    '100000': {
    -      'other': 'Elfu 000'
    -    },
    -    '1000000': {
    -      'other': 'Milioni 0'
    -    },
    -    '10000000': {
    -      'other': 'Milioni 00'
    -    },
    -    '100000000': {
    -      'other': 'Milioni 000'
    -    },
    -    '1000000000': {
    -      'other': 'Bilioni 0'
    -    },
    -    '10000000000': {
    -      'other': 'Bilioni 00'
    -    },
    -    '100000000000': {
    -      'other': 'Bilioni 000'
    -    },
    -    '1000000000000': {
    -      'other': 'Trilioni 0'
    -    },
    -    '10000000000000': {
    -      'other': 'Trilioni 00'
    -    },
    -    '100000000000000': {
    -      'other': 'Trilioni 000'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale sw_UG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_sw_UG = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': 'elfu\u00A00'
    -    },
    -    '10000': {
    -      'other': 'elfu\u00A000'
    -    },
    -    '100000': {
    -      'other': 'elfu\u00A0000'
    -    },
    -    '1000000': {
    -      'other': 'M0'
    -    },
    -    '10000000': {
    -      'other': 'M00'
    -    },
    -    '100000000': {
    -      'other': 'M000'
    -    },
    -    '1000000000': {
    -      'other': 'B0'
    -    },
    -    '10000000000': {
    -      'other': 'B00'
    -    },
    -    '100000000000': {
    -      'other': 'B000'
    -    },
    -    '1000000000000': {
    -      'other': 'T0'
    -    },
    -    '10000000000000': {
    -      'other': 'T00'
    -    },
    -    '100000000000000': {
    -      'other': 'T000'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': 'Elfu 0'
    -    },
    -    '10000': {
    -      'other': 'Elfu 00'
    -    },
    -    '100000': {
    -      'other': 'Elfu 000'
    -    },
    -    '1000000': {
    -      'other': 'Milioni 0'
    -    },
    -    '10000000': {
    -      'other': 'Milioni 00'
    -    },
    -    '100000000': {
    -      'other': 'Milioni 000'
    -    },
    -    '1000000000': {
    -      'other': 'Bilioni 0'
    -    },
    -    '10000000000': {
    -      'other': 'Bilioni 00'
    -    },
    -    '100000000000': {
    -      'other': 'Bilioni 000'
    -    },
    -    '1000000000000': {
    -      'other': 'Trilioni 0'
    -    },
    -    '10000000000000': {
    -      'other': 'Trilioni 00'
    -    },
    -    '100000000000000': {
    -      'other': 'Trilioni 000'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale swc.
    - */
    -goog.i18n.CompactNumberFormatSymbols_swc = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale swc_CD.
    - */
    -goog.i18n.CompactNumberFormatSymbols_swc_CD =
    -    goog.i18n.CompactNumberFormatSymbols_swc;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ta_LK.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ta_LK = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u0B86'
    -    },
    -    '10000': {
    -      'other': '00\u0B86'
    -    },
    -    '100000': {
    -      'other': '000\u0B86'
    -    },
    -    '1000000': {
    -      'other': '0\u0BAE\u0BBF'
    -    },
    -    '10000000': {
    -      'other': '00\u0BAE\u0BBF'
    -    },
    -    '100000000': {
    -      'other': '000\u0BAE\u0BBF'
    -    },
    -    '1000000000': {
    -      'other': '0\u0BAA\u0BBF'
    -    },
    -    '10000000000': {
    -      'other': '00\u0BAA\u0BBF'
    -    },
    -    '100000000000': {
    -      'other': '000\u0BAA\u0BBF'
    -    },
    -    '1000000000000': {
    -      'other': '0\u0B9F\u0BBF'
    -    },
    -    '10000000000000': {
    -      'other': '00\u0B9F\u0BBF'
    -    },
    -    '100000000000000': {
    -      'other': '000\u0B9F\u0BBF'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0B86\u0BAF\u0BBF\u0BB0\u0BAE\u0BCD'
    -    },
    -    '10000': {
    -      'other': '00 \u0B86\u0BAF\u0BBF\u0BB0\u0BAE\u0BCD'
    -    },
    -    '100000': {
    -      'other': '000 \u0B86\u0BAF\u0BBF\u0BB0\u0BAE\u0BCD'
    -    },
    -    '1000000': {
    -      'other': '0 \u0BAE\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '10000000': {
    -      'other': '00 \u0BAE\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '100000000': {
    -      'other': '000 \u0BAE\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0BAA\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0BAA\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0BAA\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0B9F\u0BBF\u0BB0\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0B9F\u0BBF\u0BB0\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0B9F\u0BBF\u0BB0\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ta_MY.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ta_MY = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u0B86'
    -    },
    -    '10000': {
    -      'other': '00\u0B86'
    -    },
    -    '100000': {
    -      'other': '000\u0B86'
    -    },
    -    '1000000': {
    -      'other': '0\u0BAE\u0BBF'
    -    },
    -    '10000000': {
    -      'other': '00\u0BAE\u0BBF'
    -    },
    -    '100000000': {
    -      'other': '000\u0BAE\u0BBF'
    -    },
    -    '1000000000': {
    -      'other': '0\u0BAA\u0BBF'
    -    },
    -    '10000000000': {
    -      'other': '00\u0BAA\u0BBF'
    -    },
    -    '100000000000': {
    -      'other': '000\u0BAA\u0BBF'
    -    },
    -    '1000000000000': {
    -      'other': '0\u0B9F\u0BBF'
    -    },
    -    '10000000000000': {
    -      'other': '00\u0B9F\u0BBF'
    -    },
    -    '100000000000000': {
    -      'other': '000\u0B9F\u0BBF'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0B86\u0BAF\u0BBF\u0BB0\u0BAE\u0BCD'
    -    },
    -    '10000': {
    -      'other': '00 \u0B86\u0BAF\u0BBF\u0BB0\u0BAE\u0BCD'
    -    },
    -    '100000': {
    -      'other': '000 \u0B86\u0BAF\u0BBF\u0BB0\u0BAE\u0BCD'
    -    },
    -    '1000000': {
    -      'other': '0 \u0BAE\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '10000000': {
    -      'other': '00 \u0BAE\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '100000000': {
    -      'other': '000 \u0BAE\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0BAA\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0BAA\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0BAA\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0B9F\u0BBF\u0BB0\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0B9F\u0BBF\u0BB0\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0B9F\u0BBF\u0BB0\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ta_SG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ta_SG = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u0B86'
    -    },
    -    '10000': {
    -      'other': '00\u0B86'
    -    },
    -    '100000': {
    -      'other': '000\u0B86'
    -    },
    -    '1000000': {
    -      'other': '0\u0BAE\u0BBF'
    -    },
    -    '10000000': {
    -      'other': '00\u0BAE\u0BBF'
    -    },
    -    '100000000': {
    -      'other': '000\u0BAE\u0BBF'
    -    },
    -    '1000000000': {
    -      'other': '0\u0BAA\u0BBF'
    -    },
    -    '10000000000': {
    -      'other': '00\u0BAA\u0BBF'
    -    },
    -    '100000000000': {
    -      'other': '000\u0BAA\u0BBF'
    -    },
    -    '1000000000000': {
    -      'other': '0\u0B9F\u0BBF'
    -    },
    -    '10000000000000': {
    -      'other': '00\u0B9F\u0BBF'
    -    },
    -    '100000000000000': {
    -      'other': '000\u0B9F\u0BBF'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0B86\u0BAF\u0BBF\u0BB0\u0BAE\u0BCD'
    -    },
    -    '10000': {
    -      'other': '00 \u0B86\u0BAF\u0BBF\u0BB0\u0BAE\u0BCD'
    -    },
    -    '100000': {
    -      'other': '000 \u0B86\u0BAF\u0BBF\u0BB0\u0BAE\u0BCD'
    -    },
    -    '1000000': {
    -      'other': '0 \u0BAE\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '10000000': {
    -      'other': '00 \u0BAE\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '100000000': {
    -      'other': '000 \u0BAE\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0BAA\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0BAA\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0BAA\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0B9F\u0BBF\u0BB0\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0B9F\u0BBF\u0BB0\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0B9F\u0BBF\u0BB0\u0BBF\u0BB2\u0BCD\u0BB2\u0BBF\u0BAF\u0BA9\u0BCD'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale teo.
    - */
    -goog.i18n.CompactNumberFormatSymbols_teo = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale teo_KE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_teo_KE = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale teo_UG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_teo_UG =
    -    goog.i18n.CompactNumberFormatSymbols_teo;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ti.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ti = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ti_ER.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ti_ER = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ti_ET.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ti_ET =
    -    goog.i18n.CompactNumberFormatSymbols_ti;
    -
    -
    -/**
    - * Compact number formatting symbols for locale tn.
    - */
    -goog.i18n.CompactNumberFormatSymbols_tn = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale tn_BW.
    - */
    -goog.i18n.CompactNumberFormatSymbols_tn_BW = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale tn_ZA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_tn_ZA =
    -    goog.i18n.CompactNumberFormatSymbols_tn;
    -
    -
    -/**
    - * Compact number formatting symbols for locale to.
    - */
    -goog.i18n.CompactNumberFormatSymbols_to = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0k'
    -    },
    -    '10000': {
    -      'other': '00k'
    -    },
    -    '100000': {
    -      'other': '000k'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0Ki'
    -    },
    -    '10000000000': {
    -      'other': '00Ki'
    -    },
    -    '100000000000': {
    -      'other': '000Ki'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 afe'
    -    },
    -    '10000': {
    -      'other': '0 mano'
    -    },
    -    '100000': {
    -      'other': '0 kilu'
    -    },
    -    '1000000': {
    -      'other': '0 miliona'
    -    },
    -    '10000000': {
    -      'other': '00 miliona'
    -    },
    -    '100000000': {
    -      'other': '000 miliona'
    -    },
    -    '1000000000': {
    -      'other': '0 piliona'
    -    },
    -    '10000000000': {
    -      'other': '00 piliona'
    -    },
    -    '100000000000': {
    -      'other': '000 piliona'
    -    },
    -    '1000000000000': {
    -      'other': '0 tiliona'
    -    },
    -    '10000000000000': {
    -      'other': '00 tiliona'
    -    },
    -    '100000000000000': {
    -      'other': '000 tiliona'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale to_TO.
    - */
    -goog.i18n.CompactNumberFormatSymbols_to_TO =
    -    goog.i18n.CompactNumberFormatSymbols_to;
    -
    -
    -/**
    - * Compact number formatting symbols for locale tr_CY.
    - */
    -goog.i18n.CompactNumberFormatSymbols_tr_CY = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0'
    -    },
    -    '10000': {
    -      'other': '00\u00A0B'
    -    },
    -    '100000': {
    -      'other': '000\u00A0B'
    -    },
    -    '1000000': {
    -      'other': '0\u00A0Mn'
    -    },
    -    '10000000': {
    -      'other': '00\u00A0Mn'
    -    },
    -    '100000000': {
    -      'other': '000\u00A0Mn'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0Mr'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0Mr'
    -    },
    -    '100000000000': {
    -      'other': '000\u00A0Mr'
    -    },
    -    '1000000000000': {
    -      'other': '0\u00A0Tn'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0Tn'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0Tn'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 bin'
    -    },
    -    '10000': {
    -      'other': '00 bin'
    -    },
    -    '100000': {
    -      'other': '000 bin'
    -    },
    -    '1000000': {
    -      'other': '0 milyon'
    -    },
    -    '10000000': {
    -      'other': '00 milyon'
    -    },
    -    '100000000': {
    -      'other': '000 milyon'
    -    },
    -    '1000000000': {
    -      'other': '0 milyar'
    -    },
    -    '10000000000': {
    -      'other': '00 milyar'
    -    },
    -    '100000000000': {
    -      'other': '000 milyar'
    -    },
    -    '1000000000000': {
    -      'other': '0 trilyon'
    -    },
    -    '10000000000000': {
    -      'other': '00 trilyon'
    -    },
    -    '100000000000000': {
    -      'other': '000 trilyon'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ts.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ts = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ts_ZA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ts_ZA =
    -    goog.i18n.CompactNumberFormatSymbols_ts;
    -
    -
    -/**
    - * Compact number formatting symbols for locale twq.
    - */
    -goog.i18n.CompactNumberFormatSymbols_twq = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale twq_NE.
    - */
    -goog.i18n.CompactNumberFormatSymbols_twq_NE =
    -    goog.i18n.CompactNumberFormatSymbols_twq;
    -
    -
    -/**
    - * Compact number formatting symbols for locale tzm.
    - */
    -goog.i18n.CompactNumberFormatSymbols_tzm = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale tzm_Latn.
    - */
    -goog.i18n.CompactNumberFormatSymbols_tzm_Latn = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale tzm_Latn_MA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_tzm_Latn_MA =
    -    goog.i18n.CompactNumberFormatSymbols_tzm;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ug.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ug = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u0645\u0649\u06AD'
    -    },
    -    '10000': {
    -      'other': '00\u0645\u0649\u06AD'
    -    },
    -    '100000': {
    -      'other': '000\u0645\u0649\u06AD'
    -    },
    -    '1000000': {
    -      'other': '0\u0645\u0649\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00\u0645\u0649\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000\u0645\u0649\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0\u0645\u0649\u0644\u064A\u0627\u0631\u062F'
    -    },
    -    '10000000000': {
    -      'other': '00\u0645\u0649\u0644\u064A\u0627\u0631\u062F'
    -    },
    -    '100000000000': {
    -      'other': '000\u0645\u0649\u0644\u064A\u0627\u0631\u062F'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0645\u0649\u06AD'
    -    },
    -    '10000': {
    -      'other': '00 \u0645\u0649\u06AD'
    -    },
    -    '100000': {
    -      'other': '000 \u0645\u0649\u06AD'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0649\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0649\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0649\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0645\u0649\u0644\u064A\u0627\u0631\u062F'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0645\u0649\u0644\u064A\u0627\u0631\u062F'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0645\u0649\u0644\u064A\u0627\u0631\u062F'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0649\u0631\u0649\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0649\u0631\u0649\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0649\u0631\u0649\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ug_Arab.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ug_Arab = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u0645\u0649\u06AD'
    -    },
    -    '10000': {
    -      'other': '00\u0645\u0649\u06AD'
    -    },
    -    '100000': {
    -      'other': '000\u0645\u0649\u06AD'
    -    },
    -    '1000000': {
    -      'other': '0\u0645\u0649\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00\u0645\u0649\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000\u0645\u0649\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0\u0645\u0649\u0644\u064A\u0627\u0631\u062F'
    -    },
    -    '10000000000': {
    -      'other': '00\u0645\u0649\u0644\u064A\u0627\u0631\u062F'
    -    },
    -    '100000000000': {
    -      'other': '000\u0645\u0649\u0644\u064A\u0627\u0631\u062F'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u0645\u0649\u06AD'
    -    },
    -    '10000': {
    -      'other': '00 \u0645\u0649\u06AD'
    -    },
    -    '100000': {
    -      'other': '000 \u0645\u0649\u06AD'
    -    },
    -    '1000000': {
    -      'other': '0 \u0645\u0649\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000': {
    -      'other': '00 \u0645\u0649\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000': {
    -      'other': '000 \u0645\u0649\u0644\u064A\u0648\u0646'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0645\u0649\u0644\u064A\u0627\u0631\u062F'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0645\u0649\u0644\u064A\u0627\u0631\u062F'
    -    },
    -    '100000000000': {
    -      'other': '000 \u0645\u0649\u0644\u064A\u0627\u0631\u062F'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u062A\u0649\u0631\u0649\u0644\u064A\u0648\u0646'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u062A\u0649\u0631\u0649\u0644\u064A\u0648\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u062A\u0649\u0631\u0649\u0644\u064A\u0648\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ug_Arab_CN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ug_Arab_CN =
    -    goog.i18n.CompactNumberFormatSymbols_ug;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ur_IN.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ur_IN = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u00A0\u06C1\u0632\u0627\u0631'
    -    },
    -    '10000': {
    -      'other': '00\u00A0\u06C1\u0632\u0627\u0631'
    -    },
    -    '100000': {
    -      'other': '0\u00A0\u0644\u0627\u06A9\u06BE'
    -    },
    -    '1000000': {
    -      'other': '00\u00A0\u0644\u0627\u06A9\u06BE'
    -    },
    -    '10000000': {
    -      'other': '0\u00A0\u06A9\u0631\u0648\u0691'
    -    },
    -    '100000000': {
    -      'other': '00\u00A0\u06A9\u0631\u0648\u0691'
    -    },
    -    '1000000000': {
    -      'other': '0\u00A0\u0627\u0631\u0628'
    -    },
    -    '10000000000': {
    -      'other': '00\u00A0\u0627\u0631\u0628'
    -    },
    -    '100000000000': {
    -      'other': '0\u00A0\u06A9\u06BE\u0631\u0628'
    -    },
    -    '1000000000000': {
    -      'other': '00\u00A0\u06A9\u06BE\u0631\u0628'
    -    },
    -    '10000000000000': {
    -      'other': '00\u00A0\u0679\u0631\u06CC\u0644\u06CC\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000\u00A0\u0679\u0631\u06CC\u0644\u06CC\u0646'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u06C1\u0632\u0627\u0631'
    -    },
    -    '10000': {
    -      'other': '00 \u06C1\u0632\u0627\u0631'
    -    },
    -    '100000': {
    -      'other': '0 \u0644\u0627\u06A9\u06BE'
    -    },
    -    '1000000': {
    -      'other': '00 \u0644\u0627\u06A9\u06BE'
    -    },
    -    '10000000': {
    -      'other': '0 \u06A9\u0631\u0648\u0691'
    -    },
    -    '100000000': {
    -      'other': '00 \u06A9\u0631\u0648\u0691'
    -    },
    -    '1000000000': {
    -      'other': '0 \u0627\u0631\u0628'
    -    },
    -    '10000000000': {
    -      'other': '00 \u0627\u0631\u0628'
    -    },
    -    '100000000000': {
    -      'other': '0 \u06A9\u06BE\u0631\u0628'
    -    },
    -    '1000000000000': {
    -      'other': '00 \u06A9\u06BE\u0631\u0628'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0679\u0631\u06CC\u0644\u06CC\u0646'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0679\u0631\u06CC\u0644\u06CC\u0646'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale uz_Arab.
    - */
    -goog.i18n.CompactNumberFormatSymbols_uz_Arab = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale uz_Arab_AF.
    - */
    -goog.i18n.CompactNumberFormatSymbols_uz_Arab_AF =
    -    goog.i18n.CompactNumberFormatSymbols_uz_Arab;
    -
    -
    -/**
    - * Compact number formatting symbols for locale uz_Cyrl.
    - */
    -goog.i18n.CompactNumberFormatSymbols_uz_Cyrl = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u043C\u0438\u043D\u0433'
    -    },
    -    '10000': {
    -      'other': '00\u043C\u0438\u043D\u0433'
    -    },
    -    '100000': {
    -      'other': '000\u043C\u0438\u043D\u0433'
    -    },
    -    '1000000': {
    -      'other': '0\u043C\u043B\u043D'
    -    },
    -    '10000000': {
    -      'other': '00\u043C\u043B\u043D'
    -    },
    -    '100000000': {
    -      'other': '000\u043C\u043B\u043D'
    -    },
    -    '1000000000': {
    -      'other': '0\u043C\u043B\u0440\u0434'
    -    },
    -    '10000000000': {
    -      'other': '00\u043C\u043B\u0440\u0434'
    -    },
    -    '100000000000': {
    -      'other': '000\u043C\u043B\u0440\u0434'
    -    },
    -    '1000000000000': {
    -      'other': '0\u0442\u0440\u043B\u043D'
    -    },
    -    '10000000000000': {
    -      'other': '00\u0442\u0440\u043B\u043D'
    -    },
    -    '100000000000000': {
    -      'other': '000\u0442\u0440\u043B\u043D'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u043C\u0438\u043D\u0433'
    -    },
    -    '10000': {
    -      'other': '00 \u043C\u0438\u043D\u0433'
    -    },
    -    '100000': {
    -      'other': '000 \u043C\u0438\u043D\u0433'
    -    },
    -    '1000000': {
    -      'other': '0 \u043C\u0438\u043B\u043B\u0438\u043E\u043D'
    -    },
    -    '10000000': {
    -      'other': '00 \u043C\u0438\u043B\u043B\u0438\u043E\u043D'
    -    },
    -    '100000000': {
    -      'other': '000 \u043C\u0438\u043B\u043B\u0438\u043E\u043D'
    -    },
    -    '1000000000': {
    -      'other': '0 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434'
    -    },
    -    '10000000000': {
    -      'other': '00 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434'
    -    },
    -    '100000000000': {
    -      'other': '000 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0442\u0440\u0438\u043B\u0438\u043E\u043D'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0442\u0440\u0438\u043B\u0438\u043E\u043D'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0442\u0440\u0438\u043B\u0438\u043E\u043D'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale uz_Cyrl_UZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_uz_Cyrl_UZ = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u043C\u0438\u043D\u0433'
    -    },
    -    '10000': {
    -      'other': '00\u043C\u0438\u043D\u0433'
    -    },
    -    '100000': {
    -      'other': '000\u043C\u0438\u043D\u0433'
    -    },
    -    '1000000': {
    -      'other': '0\u043C\u043B\u043D'
    -    },
    -    '10000000': {
    -      'other': '00\u043C\u043B\u043D'
    -    },
    -    '100000000': {
    -      'other': '000\u043C\u043B\u043D'
    -    },
    -    '1000000000': {
    -      'other': '0\u043C\u043B\u0440\u0434'
    -    },
    -    '10000000000': {
    -      'other': '00\u043C\u043B\u0440\u0434'
    -    },
    -    '100000000000': {
    -      'other': '000\u043C\u043B\u0440\u0434'
    -    },
    -    '1000000000000': {
    -      'other': '0\u0442\u0440\u043B\u043D'
    -    },
    -    '10000000000000': {
    -      'other': '00\u0442\u0440\u043B\u043D'
    -    },
    -    '100000000000000': {
    -      'other': '000\u0442\u0440\u043B\u043D'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u043C\u0438\u043D\u0433'
    -    },
    -    '10000': {
    -      'other': '00 \u043C\u0438\u043D\u0433'
    -    },
    -    '100000': {
    -      'other': '000 \u043C\u0438\u043D\u0433'
    -    },
    -    '1000000': {
    -      'other': '0 \u043C\u0438\u043B\u043B\u0438\u043E\u043D'
    -    },
    -    '10000000': {
    -      'other': '00 \u043C\u0438\u043B\u043B\u0438\u043E\u043D'
    -    },
    -    '100000000': {
    -      'other': '000 \u043C\u0438\u043B\u043B\u0438\u043E\u043D'
    -    },
    -    '1000000000': {
    -      'other': '0 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434'
    -    },
    -    '10000000000': {
    -      'other': '00 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434'
    -    },
    -    '100000000000': {
    -      'other': '000 \u043C\u0438\u043B\u043B\u0438\u0430\u0440\u0434'
    -    },
    -    '1000000000000': {
    -      'other': '0 \u0442\u0440\u0438\u043B\u0438\u043E\u043D'
    -    },
    -    '10000000000000': {
    -      'other': '00 \u0442\u0440\u0438\u043B\u0438\u043E\u043D'
    -    },
    -    '100000000000000': {
    -      'other': '000 \u0442\u0440\u0438\u043B\u0438\u043E\u043D'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale uz_Latn.
    - */
    -goog.i18n.CompactNumberFormatSymbols_uz_Latn = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0ming'
    -    },
    -    '10000': {
    -      'other': '00ming'
    -    },
    -    '100000': {
    -      'other': '000ming'
    -    },
    -    '1000000': {
    -      'other': '0mln'
    -    },
    -    '10000000': {
    -      'other': '00mln'
    -    },
    -    '100000000': {
    -      'other': '000mln'
    -    },
    -    '1000000000': {
    -      'other': '0mlrd'
    -    },
    -    '10000000000': {
    -      'other': '00mlrd'
    -    },
    -    '100000000000': {
    -      'other': '000mlrd'
    -    },
    -    '1000000000000': {
    -      'other': '0trln'
    -    },
    -    '10000000000000': {
    -      'other': '00trln'
    -    },
    -    '100000000000000': {
    -      'other': '000trln'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 ming'
    -    },
    -    '10000': {
    -      'other': '00 ming'
    -    },
    -    '100000': {
    -      'other': '000 ming'
    -    },
    -    '1000000': {
    -      'other': '0 million'
    -    },
    -    '10000000': {
    -      'other': '00 million'
    -    },
    -    '100000000': {
    -      'other': '000 million'
    -    },
    -    '1000000000': {
    -      'other': '0 milliard'
    -    },
    -    '10000000000': {
    -      'other': '00 milliard'
    -    },
    -    '100000000000': {
    -      'other': '000 milliard'
    -    },
    -    '1000000000000': {
    -      'other': '0 trilion'
    -    },
    -    '10000000000000': {
    -      'other': '00 trilion'
    -    },
    -    '100000000000000': {
    -      'other': '000 trilion'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale vai.
    - */
    -goog.i18n.CompactNumberFormatSymbols_vai = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale vai_Latn.
    - */
    -goog.i18n.CompactNumberFormatSymbols_vai_Latn = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale vai_Latn_LR.
    - */
    -goog.i18n.CompactNumberFormatSymbols_vai_Latn_LR =
    -    goog.i18n.CompactNumberFormatSymbols_vai;
    -
    -
    -/**
    - * Compact number formatting symbols for locale vai_Vaii.
    - */
    -goog.i18n.CompactNumberFormatSymbols_vai_Vaii = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale vai_Vaii_LR.
    - */
    -goog.i18n.CompactNumberFormatSymbols_vai_Vaii_LR =
    -    goog.i18n.CompactNumberFormatSymbols_vai;
    -
    -
    -/**
    - * Compact number formatting symbols for locale ve.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ve = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale ve_ZA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_ve_ZA =
    -    goog.i18n.CompactNumberFormatSymbols_ve;
    -
    -
    -/**
    - * Compact number formatting symbols for locale vo.
    - */
    -goog.i18n.CompactNumberFormatSymbols_vo = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale vo_001.
    - */
    -goog.i18n.CompactNumberFormatSymbols_vo_001 =
    -    goog.i18n.CompactNumberFormatSymbols_vo;
    -
    -
    -/**
    - * Compact number formatting symbols for locale vun.
    - */
    -goog.i18n.CompactNumberFormatSymbols_vun = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale vun_TZ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_vun_TZ =
    -    goog.i18n.CompactNumberFormatSymbols_vun;
    -
    -
    -/**
    - * Compact number formatting symbols for locale wae.
    - */
    -goog.i18n.CompactNumberFormatSymbols_wae = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale wae_CH.
    - */
    -goog.i18n.CompactNumberFormatSymbols_wae_CH =
    -    goog.i18n.CompactNumberFormatSymbols_wae;
    -
    -
    -/**
    - * Compact number formatting symbols for locale xog.
    - */
    -goog.i18n.CompactNumberFormatSymbols_xog = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale xog_UG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_xog_UG =
    -    goog.i18n.CompactNumberFormatSymbols_xog;
    -
    -
    -/**
    - * Compact number formatting symbols for locale yav.
    - */
    -goog.i18n.CompactNumberFormatSymbols_yav = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale yav_CM.
    - */
    -goog.i18n.CompactNumberFormatSymbols_yav_CM =
    -    goog.i18n.CompactNumberFormatSymbols_yav;
    -
    -
    -/**
    - * Compact number formatting symbols for locale yi.
    - */
    -goog.i18n.CompactNumberFormatSymbols_yi = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale yi_001.
    - */
    -goog.i18n.CompactNumberFormatSymbols_yi_001 =
    -    goog.i18n.CompactNumberFormatSymbols_yi;
    -
    -
    -/**
    - * Compact number formatting symbols for locale yo.
    - */
    -goog.i18n.CompactNumberFormatSymbols_yo = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale yo_BJ.
    - */
    -goog.i18n.CompactNumberFormatSymbols_yo_BJ = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale yo_NG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_yo_NG =
    -    goog.i18n.CompactNumberFormatSymbols_yo;
    -
    -
    -/**
    - * Compact number formatting symbols for locale zgh.
    - */
    -goog.i18n.CompactNumberFormatSymbols_zgh = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0G'
    -    },
    -    '10000000000': {
    -      'other': '00G'
    -    },
    -    '100000000000': {
    -      'other': '000G'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale zgh_MA.
    - */
    -goog.i18n.CompactNumberFormatSymbols_zgh_MA =
    -    goog.i18n.CompactNumberFormatSymbols_zgh;
    -
    -
    -/**
    - * Compact number formatting symbols for locale zh_Hans.
    - */
    -goog.i18n.CompactNumberFormatSymbols_zh_Hans = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u5343'
    -    },
    -    '10000': {
    -      'other': '0\u4E07'
    -    },
    -    '100000': {
    -      'other': '00\u4E07'
    -    },
    -    '1000000': {
    -      'other': '000\u4E07'
    -    },
    -    '10000000': {
    -      'other': '0000\u4E07'
    -    },
    -    '100000000': {
    -      'other': '0\u4EBF'
    -    },
    -    '1000000000': {
    -      'other': '00\u4EBF'
    -    },
    -    '10000000000': {
    -      'other': '000\u4EBF'
    -    },
    -    '100000000000': {
    -      'other': '0000\u4EBF'
    -    },
    -    '1000000000000': {
    -      'other': '0\u5146'
    -    },
    -    '10000000000000': {
    -      'other': '00\u5146'
    -    },
    -    '100000000000000': {
    -      'other': '000\u5146'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0\u5343'
    -    },
    -    '10000': {
    -      'other': '0\u4E07'
    -    },
    -    '100000': {
    -      'other': '00\u4E07'
    -    },
    -    '1000000': {
    -      'other': '000\u4E07'
    -    },
    -    '10000000': {
    -      'other': '0000\u4E07'
    -    },
    -    '100000000': {
    -      'other': '0\u4EBF'
    -    },
    -    '1000000000': {
    -      'other': '00\u4EBF'
    -    },
    -    '10000000000': {
    -      'other': '000\u4EBF'
    -    },
    -    '100000000000': {
    -      'other': '0000\u4EBF'
    -    },
    -    '1000000000000': {
    -      'other': '0\u5146'
    -    },
    -    '10000000000000': {
    -      'other': '00\u5146'
    -    },
    -    '100000000000000': {
    -      'other': '000\u5146'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale zh_Hans_HK.
    - */
    -goog.i18n.CompactNumberFormatSymbols_zh_Hans_HK = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u5343'
    -    },
    -    '10000': {
    -      'other': '0\u4E07'
    -    },
    -    '100000': {
    -      'other': '00\u4E07'
    -    },
    -    '1000000': {
    -      'other': '000\u4E07'
    -    },
    -    '10000000': {
    -      'other': '0000\u4E07'
    -    },
    -    '100000000': {
    -      'other': '0\u4EBF'
    -    },
    -    '1000000000': {
    -      'other': '00\u4EBF'
    -    },
    -    '10000000000': {
    -      'other': '000\u4EBF'
    -    },
    -    '100000000000': {
    -      'other': '0000\u4EBF'
    -    },
    -    '1000000000000': {
    -      'other': '0\u4E07\u4EBF'
    -    },
    -    '10000000000000': {
    -      'other': '00\u4E07\u4EBF'
    -    },
    -    '100000000000000': {
    -      'other': '000\u4E07\u4EBF'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0\u5343'
    -    },
    -    '10000': {
    -      'other': '0\u4E07'
    -    },
    -    '100000': {
    -      'other': '00\u4E07'
    -    },
    -    '1000000': {
    -      'other': '000\u4E07'
    -    },
    -    '10000000': {
    -      'other': '0000\u4E07'
    -    },
    -    '100000000': {
    -      'other': '0\u4EBF'
    -    },
    -    '1000000000': {
    -      'other': '00\u4EBF'
    -    },
    -    '10000000000': {
    -      'other': '000\u4EBF'
    -    },
    -    '100000000000': {
    -      'other': '0000\u4EBF'
    -    },
    -    '1000000000000': {
    -      'other': '0\u4E07\u4EBF'
    -    },
    -    '10000000000000': {
    -      'other': '00\u4E07\u4EBF'
    -    },
    -    '100000000000000': {
    -      'other': '000\u4E07\u4EBF'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale zh_Hans_MO.
    - */
    -goog.i18n.CompactNumberFormatSymbols_zh_Hans_MO = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u5343'
    -    },
    -    '10000': {
    -      'other': '0\u4E07'
    -    },
    -    '100000': {
    -      'other': '00\u4E07'
    -    },
    -    '1000000': {
    -      'other': '000\u4E07'
    -    },
    -    '10000000': {
    -      'other': '0000\u4E07'
    -    },
    -    '100000000': {
    -      'other': '0\u4EBF'
    -    },
    -    '1000000000': {
    -      'other': '00\u4EBF'
    -    },
    -    '10000000000': {
    -      'other': '000\u4EBF'
    -    },
    -    '100000000000': {
    -      'other': '0000\u4EBF'
    -    },
    -    '1000000000000': {
    -      'other': '0\u5146'
    -    },
    -    '10000000000000': {
    -      'other': '00\u5146'
    -    },
    -    '100000000000000': {
    -      'other': '000\u5146'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0\u5343'
    -    },
    -    '10000': {
    -      'other': '0\u4E07'
    -    },
    -    '100000': {
    -      'other': '00\u4E07'
    -    },
    -    '1000000': {
    -      'other': '000\u4E07'
    -    },
    -    '10000000': {
    -      'other': '0000\u4E07'
    -    },
    -    '100000000': {
    -      'other': '0\u4EBF'
    -    },
    -    '1000000000': {
    -      'other': '00\u4EBF'
    -    },
    -    '10000000000': {
    -      'other': '000\u4EBF'
    -    },
    -    '100000000000': {
    -      'other': '0000\u4EBF'
    -    },
    -    '1000000000000': {
    -      'other': '0\u5146'
    -    },
    -    '10000000000000': {
    -      'other': '00\u5146'
    -    },
    -    '100000000000000': {
    -      'other': '000\u5146'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale zh_Hans_SG.
    - */
    -goog.i18n.CompactNumberFormatSymbols_zh_Hans_SG = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0\u5343'
    -    },
    -    '10000': {
    -      'other': '0\u4E07'
    -    },
    -    '100000': {
    -      'other': '00\u4E07'
    -    },
    -    '1000000': {
    -      'other': '000\u4E07'
    -    },
    -    '10000000': {
    -      'other': '0000\u4E07'
    -    },
    -    '100000000': {
    -      'other': '0\u4EBF'
    -    },
    -    '1000000000': {
    -      'other': '00\u4EBF'
    -    },
    -    '10000000000': {
    -      'other': '000\u4EBF'
    -    },
    -    '100000000000': {
    -      'other': '0000\u4EBF'
    -    },
    -    '1000000000000': {
    -      'other': '0\u5146'
    -    },
    -    '10000000000000': {
    -      'other': '00\u5146'
    -    },
    -    '100000000000000': {
    -      'other': '000\u5146'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0\u5343'
    -    },
    -    '10000': {
    -      'other': '0\u4E07'
    -    },
    -    '100000': {
    -      'other': '00\u4E07'
    -    },
    -    '1000000': {
    -      'other': '000\u4E07'
    -    },
    -    '10000000': {
    -      'other': '0000\u4E07'
    -    },
    -    '100000000': {
    -      'other': '0\u4EBF'
    -    },
    -    '1000000000': {
    -      'other': '00\u4EBF'
    -    },
    -    '10000000000': {
    -      'other': '000\u4EBF'
    -    },
    -    '100000000000': {
    -      'other': '0000\u4EBF'
    -    },
    -    '1000000000000': {
    -      'other': '0\u5146'
    -    },
    -    '10000000000000': {
    -      'other': '00\u5146'
    -    },
    -    '100000000000000': {
    -      'other': '000\u5146'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale zh_Hant.
    - */
    -goog.i18n.CompactNumberFormatSymbols_zh_Hant = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0 \u5343'
    -    },
    -    '10000': {
    -      'other': '0\u842C'
    -    },
    -    '100000': {
    -      'other': '00\u842C'
    -    },
    -    '1000000': {
    -      'other': '000\u842C'
    -    },
    -    '10000000': {
    -      'other': '0000\u842C'
    -    },
    -    '100000000': {
    -      'other': '0\u5104'
    -    },
    -    '1000000000': {
    -      'other': '00\u5104'
    -    },
    -    '10000000000': {
    -      'other': '000\u5104'
    -    },
    -    '100000000000': {
    -      'other': '0000\u5104'
    -    },
    -    '1000000000000': {
    -      'other': '0\u5146'
    -    },
    -    '10000000000000': {
    -      'other': '00\u5146'
    -    },
    -    '100000000000000': {
    -      'other': '000\u5146'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale zh_Hant_HK.
    - */
    -goog.i18n.CompactNumberFormatSymbols_zh_Hant_HK = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0\u5343'
    -    },
    -    '10000': {
    -      'other': '0\u842C'
    -    },
    -    '100000': {
    -      'other': '00\u842C'
    -    },
    -    '1000000': {
    -      'other': '000\u842C'
    -    },
    -    '10000000': {
    -      'other': '0000\u842C'
    -    },
    -    '100000000': {
    -      'other': '0\u5104'
    -    },
    -    '1000000000': {
    -      'other': '00\u5104'
    -    },
    -    '10000000000': {
    -      'other': '000\u5104'
    -    },
    -    '100000000000': {
    -      'other': '0000\u5104'
    -    },
    -    '1000000000000': {
    -      'other': '0\u5146'
    -    },
    -    '10000000000000': {
    -      'other': '00\u5146'
    -    },
    -    '100000000000000': {
    -      'other': '000\u5146'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale zh_Hant_MO.
    - */
    -goog.i18n.CompactNumberFormatSymbols_zh_Hant_MO = {
    -  COMPACT_DECIMAL_SHORT_PATTERN: {
    -    '1000': {
    -      'other': '0K'
    -    },
    -    '10000': {
    -      'other': '00K'
    -    },
    -    '100000': {
    -      'other': '000K'
    -    },
    -    '1000000': {
    -      'other': '0M'
    -    },
    -    '10000000': {
    -      'other': '00M'
    -    },
    -    '100000000': {
    -      'other': '000M'
    -    },
    -    '1000000000': {
    -      'other': '0B'
    -    },
    -    '10000000000': {
    -      'other': '00B'
    -    },
    -    '100000000000': {
    -      'other': '000B'
    -    },
    -    '1000000000000': {
    -      'other': '0T'
    -    },
    -    '10000000000000': {
    -      'other': '00T'
    -    },
    -    '100000000000000': {
    -      'other': '000T'
    -    }
    -  },
    -  COMPACT_DECIMAL_LONG_PATTERN: {
    -    '1000': {
    -      'other': '0\u5343'
    -    },
    -    '10000': {
    -      'other': '0\u842C'
    -    },
    -    '100000': {
    -      'other': '00\u842C'
    -    },
    -    '1000000': {
    -      'other': '000\u842C'
    -    },
    -    '10000000': {
    -      'other': '0000\u842C'
    -    },
    -    '100000000': {
    -      'other': '0\u5104'
    -    },
    -    '1000000000': {
    -      'other': '00\u5104'
    -    },
    -    '10000000000': {
    -      'other': '000\u5104'
    -    },
    -    '100000000000': {
    -      'other': '0000\u5104'
    -    },
    -    '1000000000000': {
    -      'other': '0\u5146'
    -    },
    -    '10000000000000': {
    -      'other': '00\u5146'
    -    },
    -    '100000000000000': {
    -      'other': '000\u5146'
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compact number formatting symbols for locale zh_Hant_TW.
    - */
    -goog.i18n.CompactNumberFormatSymbols_zh_Hant_TW =
    -    goog.i18n.CompactNumberFormatSymbols_zh_Hant;
    -
    -
    -/**
    - * Selected compact number formatting symbols by locale.
    - */
    -goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en;
    -
    -if (goog.LOCALE == 'aa') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_aa;
    -}
    -
    -if (goog.LOCALE == 'aa_DJ' || goog.LOCALE == 'aa-DJ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_aa_DJ;
    -}
    -
    -if (goog.LOCALE == 'aa_ER' || goog.LOCALE == 'aa-ER') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_aa_ER;
    -}
    -
    -if (goog.LOCALE == 'aa_ET' || goog.LOCALE == 'aa-ET') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_aa;
    -}
    -
    -if (goog.LOCALE == 'af_NA' || goog.LOCALE == 'af-NA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_af_NA;
    -}
    -
    -if (goog.LOCALE == 'agq') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_agq;
    -}
    -
    -if (goog.LOCALE == 'agq_CM' || goog.LOCALE == 'agq-CM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_agq;
    -}
    -
    -if (goog.LOCALE == 'ak') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ak;
    -}
    -
    -if (goog.LOCALE == 'ak_GH' || goog.LOCALE == 'ak-GH') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ak;
    -}
    -
    -if (goog.LOCALE == 'ar_AE' || goog.LOCALE == 'ar-AE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ar_AE;
    -}
    -
    -if (goog.LOCALE == 'ar_BH' || goog.LOCALE == 'ar-BH') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ar_BH;
    -}
    -
    -if (goog.LOCALE == 'ar_DJ' || goog.LOCALE == 'ar-DJ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ar_DJ;
    -}
    -
    -if (goog.LOCALE == 'ar_DZ' || goog.LOCALE == 'ar-DZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ar_DZ;
    -}
    -
    -if (goog.LOCALE == 'ar_EG' || goog.LOCALE == 'ar-EG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ar_EG;
    -}
    -
    -if (goog.LOCALE == 'ar_EH' || goog.LOCALE == 'ar-EH') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ar_EH;
    -}
    -
    -if (goog.LOCALE == 'ar_ER' || goog.LOCALE == 'ar-ER') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ar_ER;
    -}
    -
    -if (goog.LOCALE == 'ar_IL' || goog.LOCALE == 'ar-IL') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ar_IL;
    -}
    -
    -if (goog.LOCALE == 'ar_IQ' || goog.LOCALE == 'ar-IQ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ar_IQ;
    -}
    -
    -if (goog.LOCALE == 'ar_JO' || goog.LOCALE == 'ar-JO') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ar_JO;
    -}
    -
    -if (goog.LOCALE == 'ar_KM' || goog.LOCALE == 'ar-KM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ar_KM;
    -}
    -
    -if (goog.LOCALE == 'ar_KW' || goog.LOCALE == 'ar-KW') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ar_KW;
    -}
    -
    -if (goog.LOCALE == 'ar_LB' || goog.LOCALE == 'ar-LB') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ar_LB;
    -}
    -
    -if (goog.LOCALE == 'ar_LY' || goog.LOCALE == 'ar-LY') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ar_LY;
    -}
    -
    -if (goog.LOCALE == 'ar_MA' || goog.LOCALE == 'ar-MA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ar_MA;
    -}
    -
    -if (goog.LOCALE == 'ar_MR' || goog.LOCALE == 'ar-MR') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ar_MR;
    -}
    -
    -if (goog.LOCALE == 'ar_OM' || goog.LOCALE == 'ar-OM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ar_OM;
    -}
    -
    -if (goog.LOCALE == 'ar_PS' || goog.LOCALE == 'ar-PS') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ar_PS;
    -}
    -
    -if (goog.LOCALE == 'ar_QA' || goog.LOCALE == 'ar-QA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ar_QA;
    -}
    -
    -if (goog.LOCALE == 'ar_SA' || goog.LOCALE == 'ar-SA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ar_SA;
    -}
    -
    -if (goog.LOCALE == 'ar_SD' || goog.LOCALE == 'ar-SD') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ar_SD;
    -}
    -
    -if (goog.LOCALE == 'ar_SO' || goog.LOCALE == 'ar-SO') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ar_SO;
    -}
    -
    -if (goog.LOCALE == 'ar_SS' || goog.LOCALE == 'ar-SS') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ar_SS;
    -}
    -
    -if (goog.LOCALE == 'ar_SY' || goog.LOCALE == 'ar-SY') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ar_SY;
    -}
    -
    -if (goog.LOCALE == 'ar_TD' || goog.LOCALE == 'ar-TD') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ar_TD;
    -}
    -
    -if (goog.LOCALE == 'ar_TN' || goog.LOCALE == 'ar-TN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ar_TN;
    -}
    -
    -if (goog.LOCALE == 'ar_YE' || goog.LOCALE == 'ar-YE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ar_YE;
    -}
    -
    -if (goog.LOCALE == 'as') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_as;
    -}
    -
    -if (goog.LOCALE == 'as_IN' || goog.LOCALE == 'as-IN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_as;
    -}
    -
    -if (goog.LOCALE == 'asa') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_asa;
    -}
    -
    -if (goog.LOCALE == 'asa_TZ' || goog.LOCALE == 'asa-TZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_asa;
    -}
    -
    -if (goog.LOCALE == 'ast') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ast;
    -}
    -
    -if (goog.LOCALE == 'ast_ES' || goog.LOCALE == 'ast-ES') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ast;
    -}
    -
    -if (goog.LOCALE == 'az_Cyrl' || goog.LOCALE == 'az-Cyrl') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_az_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'az_Cyrl_AZ' || goog.LOCALE == 'az-Cyrl-AZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_az_Cyrl_AZ;
    -}
    -
    -if (goog.LOCALE == 'az_Latn' || goog.LOCALE == 'az-Latn') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_az_Latn;
    -}
    -
    -if (goog.LOCALE == 'bas') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_bas;
    -}
    -
    -if (goog.LOCALE == 'bas_CM' || goog.LOCALE == 'bas-CM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_bas;
    -}
    -
    -if (goog.LOCALE == 'be') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_be;
    -}
    -
    -if (goog.LOCALE == 'be_BY' || goog.LOCALE == 'be-BY') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_be;
    -}
    -
    -if (goog.LOCALE == 'bem') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_bem;
    -}
    -
    -if (goog.LOCALE == 'bem_ZM' || goog.LOCALE == 'bem-ZM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_bem;
    -}
    -
    -if (goog.LOCALE == 'bez') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_bez;
    -}
    -
    -if (goog.LOCALE == 'bez_TZ' || goog.LOCALE == 'bez-TZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_bez;
    -}
    -
    -if (goog.LOCALE == 'bm') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_bm;
    -}
    -
    -if (goog.LOCALE == 'bm_Latn' || goog.LOCALE == 'bm-Latn') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_bm_Latn;
    -}
    -
    -if (goog.LOCALE == 'bm_Latn_ML' || goog.LOCALE == 'bm-Latn-ML') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_bm;
    -}
    -
    -if (goog.LOCALE == 'bn_IN' || goog.LOCALE == 'bn-IN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_bn_IN;
    -}
    -
    -if (goog.LOCALE == 'bo') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_bo;
    -}
    -
    -if (goog.LOCALE == 'bo_CN' || goog.LOCALE == 'bo-CN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_bo;
    -}
    -
    -if (goog.LOCALE == 'bo_IN' || goog.LOCALE == 'bo-IN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_bo_IN;
    -}
    -
    -if (goog.LOCALE == 'brx') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_brx;
    -}
    -
    -if (goog.LOCALE == 'brx_IN' || goog.LOCALE == 'brx-IN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_brx;
    -}
    -
    -if (goog.LOCALE == 'bs') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_bs;
    -}
    -
    -if (goog.LOCALE == 'bs_Cyrl' || goog.LOCALE == 'bs-Cyrl') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_bs_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'bs_Cyrl_BA' || goog.LOCALE == 'bs-Cyrl-BA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_bs_Cyrl_BA;
    -}
    -
    -if (goog.LOCALE == 'bs_Latn' || goog.LOCALE == 'bs-Latn') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_bs_Latn;
    -}
    -
    -if (goog.LOCALE == 'bs_Latn_BA' || goog.LOCALE == 'bs-Latn-BA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_bs;
    -}
    -
    -if (goog.LOCALE == 'cgg') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_cgg;
    -}
    -
    -if (goog.LOCALE == 'cgg_UG' || goog.LOCALE == 'cgg-UG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_cgg;
    -}
    -
    -if (goog.LOCALE == 'ckb') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ckb;
    -}
    -
    -if (goog.LOCALE == 'ckb_Arab' || goog.LOCALE == 'ckb-Arab') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ckb_Arab;
    -}
    -
    -if (goog.LOCALE == 'ckb_Arab_IQ' || goog.LOCALE == 'ckb-Arab-IQ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ckb;
    -}
    -
    -if (goog.LOCALE == 'ckb_Arab_IR' || goog.LOCALE == 'ckb-Arab-IR') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ckb_Arab_IR;
    -}
    -
    -if (goog.LOCALE == 'ckb_IQ' || goog.LOCALE == 'ckb-IQ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ckb;
    -}
    -
    -if (goog.LOCALE == 'ckb_IR' || goog.LOCALE == 'ckb-IR') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ckb_IR;
    -}
    -
    -if (goog.LOCALE == 'ckb_Latn' || goog.LOCALE == 'ckb-Latn') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ckb_Latn;
    -}
    -
    -if (goog.LOCALE == 'ckb_Latn_IQ' || goog.LOCALE == 'ckb-Latn-IQ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ckb;
    -}
    -
    -if (goog.LOCALE == 'dav') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_dav;
    -}
    -
    -if (goog.LOCALE == 'dav_KE' || goog.LOCALE == 'dav-KE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_dav;
    -}
    -
    -if (goog.LOCALE == 'de_LI' || goog.LOCALE == 'de-LI') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_de_LI;
    -}
    -
    -if (goog.LOCALE == 'dje') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_dje;
    -}
    -
    -if (goog.LOCALE == 'dje_NE' || goog.LOCALE == 'dje-NE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_dje;
    -}
    -
    -if (goog.LOCALE == 'dsb') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_dsb;
    -}
    -
    -if (goog.LOCALE == 'dsb_DE' || goog.LOCALE == 'dsb-DE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_dsb;
    -}
    -
    -if (goog.LOCALE == 'dua') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_dua;
    -}
    -
    -if (goog.LOCALE == 'dua_CM' || goog.LOCALE == 'dua-CM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_dua;
    -}
    -
    -if (goog.LOCALE == 'dyo') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_dyo;
    -}
    -
    -if (goog.LOCALE == 'dyo_SN' || goog.LOCALE == 'dyo-SN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_dyo;
    -}
    -
    -if (goog.LOCALE == 'dz') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_dz;
    -}
    -
    -if (goog.LOCALE == 'dz_BT' || goog.LOCALE == 'dz-BT') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_dz;
    -}
    -
    -if (goog.LOCALE == 'ebu') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ebu;
    -}
    -
    -if (goog.LOCALE == 'ebu_KE' || goog.LOCALE == 'ebu-KE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ebu;
    -}
    -
    -if (goog.LOCALE == 'ee') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ee;
    -}
    -
    -if (goog.LOCALE == 'ee_GH' || goog.LOCALE == 'ee-GH') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ee;
    -}
    -
    -if (goog.LOCALE == 'ee_TG' || goog.LOCALE == 'ee-TG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ee_TG;
    -}
    -
    -if (goog.LOCALE == 'el_CY' || goog.LOCALE == 'el-CY') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_el_CY;
    -}
    -
    -if (goog.LOCALE == 'en_150' || goog.LOCALE == 'en-150') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_150;
    -}
    -
    -if (goog.LOCALE == 'en_AG' || goog.LOCALE == 'en-AG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_AG;
    -}
    -
    -if (goog.LOCALE == 'en_AI' || goog.LOCALE == 'en-AI') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_AI;
    -}
    -
    -if (goog.LOCALE == 'en_BB' || goog.LOCALE == 'en-BB') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_BB;
    -}
    -
    -if (goog.LOCALE == 'en_BE' || goog.LOCALE == 'en-BE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_BE;
    -}
    -
    -if (goog.LOCALE == 'en_BM' || goog.LOCALE == 'en-BM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_BM;
    -}
    -
    -if (goog.LOCALE == 'en_BS' || goog.LOCALE == 'en-BS') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_BS;
    -}
    -
    -if (goog.LOCALE == 'en_BW' || goog.LOCALE == 'en-BW') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_BW;
    -}
    -
    -if (goog.LOCALE == 'en_BZ' || goog.LOCALE == 'en-BZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_BZ;
    -}
    -
    -if (goog.LOCALE == 'en_CA' || goog.LOCALE == 'en-CA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_CA;
    -}
    -
    -if (goog.LOCALE == 'en_CC' || goog.LOCALE == 'en-CC') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_CC;
    -}
    -
    -if (goog.LOCALE == 'en_CK' || goog.LOCALE == 'en-CK') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_CK;
    -}
    -
    -if (goog.LOCALE == 'en_CM' || goog.LOCALE == 'en-CM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_CM;
    -}
    -
    -if (goog.LOCALE == 'en_CX' || goog.LOCALE == 'en-CX') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_CX;
    -}
    -
    -if (goog.LOCALE == 'en_DM' || goog.LOCALE == 'en-DM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_DM;
    -}
    -
    -if (goog.LOCALE == 'en_ER' || goog.LOCALE == 'en-ER') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_ER;
    -}
    -
    -if (goog.LOCALE == 'en_FJ' || goog.LOCALE == 'en-FJ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_FJ;
    -}
    -
    -if (goog.LOCALE == 'en_FK' || goog.LOCALE == 'en-FK') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_FK;
    -}
    -
    -if (goog.LOCALE == 'en_GD' || goog.LOCALE == 'en-GD') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_GD;
    -}
    -
    -if (goog.LOCALE == 'en_GG' || goog.LOCALE == 'en-GG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_GG;
    -}
    -
    -if (goog.LOCALE == 'en_GH' || goog.LOCALE == 'en-GH') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_GH;
    -}
    -
    -if (goog.LOCALE == 'en_GI' || goog.LOCALE == 'en-GI') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_GI;
    -}
    -
    -if (goog.LOCALE == 'en_GM' || goog.LOCALE == 'en-GM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_GM;
    -}
    -
    -if (goog.LOCALE == 'en_GY' || goog.LOCALE == 'en-GY') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_GY;
    -}
    -
    -if (goog.LOCALE == 'en_HK' || goog.LOCALE == 'en-HK') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_HK;
    -}
    -
    -if (goog.LOCALE == 'en_IM' || goog.LOCALE == 'en-IM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_IM;
    -}
    -
    -if (goog.LOCALE == 'en_JE' || goog.LOCALE == 'en-JE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_JE;
    -}
    -
    -if (goog.LOCALE == 'en_JM' || goog.LOCALE == 'en-JM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_JM;
    -}
    -
    -if (goog.LOCALE == 'en_KE' || goog.LOCALE == 'en-KE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_KE;
    -}
    -
    -if (goog.LOCALE == 'en_KI' || goog.LOCALE == 'en-KI') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_KI;
    -}
    -
    -if (goog.LOCALE == 'en_KN' || goog.LOCALE == 'en-KN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_KN;
    -}
    -
    -if (goog.LOCALE == 'en_KY' || goog.LOCALE == 'en-KY') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_KY;
    -}
    -
    -if (goog.LOCALE == 'en_LC' || goog.LOCALE == 'en-LC') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_LC;
    -}
    -
    -if (goog.LOCALE == 'en_LR' || goog.LOCALE == 'en-LR') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_LR;
    -}
    -
    -if (goog.LOCALE == 'en_LS' || goog.LOCALE == 'en-LS') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_LS;
    -}
    -
    -if (goog.LOCALE == 'en_MG' || goog.LOCALE == 'en-MG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_MG;
    -}
    -
    -if (goog.LOCALE == 'en_MO' || goog.LOCALE == 'en-MO') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_MO;
    -}
    -
    -if (goog.LOCALE == 'en_MS' || goog.LOCALE == 'en-MS') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_MS;
    -}
    -
    -if (goog.LOCALE == 'en_MT' || goog.LOCALE == 'en-MT') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_MT;
    -}
    -
    -if (goog.LOCALE == 'en_MU' || goog.LOCALE == 'en-MU') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_MU;
    -}
    -
    -if (goog.LOCALE == 'en_MW' || goog.LOCALE == 'en-MW') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_MW;
    -}
    -
    -if (goog.LOCALE == 'en_MY' || goog.LOCALE == 'en-MY') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_MY;
    -}
    -
    -if (goog.LOCALE == 'en_NA' || goog.LOCALE == 'en-NA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_NA;
    -}
    -
    -if (goog.LOCALE == 'en_NF' || goog.LOCALE == 'en-NF') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_NF;
    -}
    -
    -if (goog.LOCALE == 'en_NG' || goog.LOCALE == 'en-NG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_NG;
    -}
    -
    -if (goog.LOCALE == 'en_NR' || goog.LOCALE == 'en-NR') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_NR;
    -}
    -
    -if (goog.LOCALE == 'en_NU' || goog.LOCALE == 'en-NU') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_NU;
    -}
    -
    -if (goog.LOCALE == 'en_NZ' || goog.LOCALE == 'en-NZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_NZ;
    -}
    -
    -if (goog.LOCALE == 'en_PG' || goog.LOCALE == 'en-PG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_PG;
    -}
    -
    -if (goog.LOCALE == 'en_PH' || goog.LOCALE == 'en-PH') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_PH;
    -}
    -
    -if (goog.LOCALE == 'en_PK' || goog.LOCALE == 'en-PK') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_PK;
    -}
    -
    -if (goog.LOCALE == 'en_PN' || goog.LOCALE == 'en-PN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_PN;
    -}
    -
    -if (goog.LOCALE == 'en_RW' || goog.LOCALE == 'en-RW') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_RW;
    -}
    -
    -if (goog.LOCALE == 'en_SB' || goog.LOCALE == 'en-SB') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_SB;
    -}
    -
    -if (goog.LOCALE == 'en_SC' || goog.LOCALE == 'en-SC') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_SC;
    -}
    -
    -if (goog.LOCALE == 'en_SD' || goog.LOCALE == 'en-SD') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_SD;
    -}
    -
    -if (goog.LOCALE == 'en_SH' || goog.LOCALE == 'en-SH') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_SH;
    -}
    -
    -if (goog.LOCALE == 'en_SL' || goog.LOCALE == 'en-SL') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_SL;
    -}
    -
    -if (goog.LOCALE == 'en_SS' || goog.LOCALE == 'en-SS') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_SS;
    -}
    -
    -if (goog.LOCALE == 'en_SX' || goog.LOCALE == 'en-SX') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_SX;
    -}
    -
    -if (goog.LOCALE == 'en_SZ' || goog.LOCALE == 'en-SZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_SZ;
    -}
    -
    -if (goog.LOCALE == 'en_TK' || goog.LOCALE == 'en-TK') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_TK;
    -}
    -
    -if (goog.LOCALE == 'en_TO' || goog.LOCALE == 'en-TO') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_TO;
    -}
    -
    -if (goog.LOCALE == 'en_TT' || goog.LOCALE == 'en-TT') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_TT;
    -}
    -
    -if (goog.LOCALE == 'en_TV' || goog.LOCALE == 'en-TV') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_TV;
    -}
    -
    -if (goog.LOCALE == 'en_TZ' || goog.LOCALE == 'en-TZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_TZ;
    -}
    -
    -if (goog.LOCALE == 'en_UG' || goog.LOCALE == 'en-UG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_UG;
    -}
    -
    -if (goog.LOCALE == 'en_VC' || goog.LOCALE == 'en-VC') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_VC;
    -}
    -
    -if (goog.LOCALE == 'en_VU' || goog.LOCALE == 'en-VU') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_VU;
    -}
    -
    -if (goog.LOCALE == 'en_WS' || goog.LOCALE == 'en-WS') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_WS;
    -}
    -
    -if (goog.LOCALE == 'en_ZM' || goog.LOCALE == 'en-ZM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_en_ZM;
    -}
    -
    -if (goog.LOCALE == 'eo') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_eo;
    -}
    -
    -if (goog.LOCALE == 'eo_001' || goog.LOCALE == 'eo-001') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_eo;
    -}
    -
    -if (goog.LOCALE == 'es_AR' || goog.LOCALE == 'es-AR') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_es_AR;
    -}
    -
    -if (goog.LOCALE == 'es_BO' || goog.LOCALE == 'es-BO') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_es_BO;
    -}
    -
    -if (goog.LOCALE == 'es_CL' || goog.LOCALE == 'es-CL') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_es_CL;
    -}
    -
    -if (goog.LOCALE == 'es_CO' || goog.LOCALE == 'es-CO') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_es_CO;
    -}
    -
    -if (goog.LOCALE == 'es_CR' || goog.LOCALE == 'es-CR') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_es_CR;
    -}
    -
    -if (goog.LOCALE == 'es_CU' || goog.LOCALE == 'es-CU') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_es_CU;
    -}
    -
    -if (goog.LOCALE == 'es_DO' || goog.LOCALE == 'es-DO') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_es_DO;
    -}
    -
    -if (goog.LOCALE == 'es_EC' || goog.LOCALE == 'es-EC') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_es_EC;
    -}
    -
    -if (goog.LOCALE == 'es_GQ' || goog.LOCALE == 'es-GQ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_es_GQ;
    -}
    -
    -if (goog.LOCALE == 'es_GT' || goog.LOCALE == 'es-GT') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_es_GT;
    -}
    -
    -if (goog.LOCALE == 'es_HN' || goog.LOCALE == 'es-HN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_es_HN;
    -}
    -
    -if (goog.LOCALE == 'es_MX' || goog.LOCALE == 'es-MX') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_es_MX;
    -}
    -
    -if (goog.LOCALE == 'es_NI' || goog.LOCALE == 'es-NI') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_es_NI;
    -}
    -
    -if (goog.LOCALE == 'es_PA' || goog.LOCALE == 'es-PA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_es_PA;
    -}
    -
    -if (goog.LOCALE == 'es_PE' || goog.LOCALE == 'es-PE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_es_PE;
    -}
    -
    -if (goog.LOCALE == 'es_PH' || goog.LOCALE == 'es-PH') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_es_PH;
    -}
    -
    -if (goog.LOCALE == 'es_PR' || goog.LOCALE == 'es-PR') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_es_PR;
    -}
    -
    -if (goog.LOCALE == 'es_PY' || goog.LOCALE == 'es-PY') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_es_PY;
    -}
    -
    -if (goog.LOCALE == 'es_SV' || goog.LOCALE == 'es-SV') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_es_SV;
    -}
    -
    -if (goog.LOCALE == 'es_US' || goog.LOCALE == 'es-US') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_es_US;
    -}
    -
    -if (goog.LOCALE == 'es_UY' || goog.LOCALE == 'es-UY') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_es_UY;
    -}
    -
    -if (goog.LOCALE == 'es_VE' || goog.LOCALE == 'es-VE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_es_VE;
    -}
    -
    -if (goog.LOCALE == 'ewo') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ewo;
    -}
    -
    -if (goog.LOCALE == 'ewo_CM' || goog.LOCALE == 'ewo-CM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ewo;
    -}
    -
    -if (goog.LOCALE == 'fa_AF' || goog.LOCALE == 'fa-AF') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fa_AF;
    -}
    -
    -if (goog.LOCALE == 'ff') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ff;
    -}
    -
    -if (goog.LOCALE == 'ff_CM' || goog.LOCALE == 'ff-CM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ff_CM;
    -}
    -
    -if (goog.LOCALE == 'ff_GN' || goog.LOCALE == 'ff-GN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ff_GN;
    -}
    -
    -if (goog.LOCALE == 'ff_MR' || goog.LOCALE == 'ff-MR') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ff_MR;
    -}
    -
    -if (goog.LOCALE == 'ff_SN' || goog.LOCALE == 'ff-SN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ff;
    -}
    -
    -if (goog.LOCALE == 'fo') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fo;
    -}
    -
    -if (goog.LOCALE == 'fo_FO' || goog.LOCALE == 'fo-FO') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fo;
    -}
    -
    -if (goog.LOCALE == 'fr_BE' || goog.LOCALE == 'fr-BE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_BE;
    -}
    -
    -if (goog.LOCALE == 'fr_BF' || goog.LOCALE == 'fr-BF') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_BF;
    -}
    -
    -if (goog.LOCALE == 'fr_BI' || goog.LOCALE == 'fr-BI') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_BI;
    -}
    -
    -if (goog.LOCALE == 'fr_BJ' || goog.LOCALE == 'fr-BJ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_BJ;
    -}
    -
    -if (goog.LOCALE == 'fr_CD' || goog.LOCALE == 'fr-CD') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_CD;
    -}
    -
    -if (goog.LOCALE == 'fr_CF' || goog.LOCALE == 'fr-CF') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_CF;
    -}
    -
    -if (goog.LOCALE == 'fr_CG' || goog.LOCALE == 'fr-CG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_CG;
    -}
    -
    -if (goog.LOCALE == 'fr_CH' || goog.LOCALE == 'fr-CH') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_CH;
    -}
    -
    -if (goog.LOCALE == 'fr_CI' || goog.LOCALE == 'fr-CI') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_CI;
    -}
    -
    -if (goog.LOCALE == 'fr_CM' || goog.LOCALE == 'fr-CM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_CM;
    -}
    -
    -if (goog.LOCALE == 'fr_DJ' || goog.LOCALE == 'fr-DJ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_DJ;
    -}
    -
    -if (goog.LOCALE == 'fr_DZ' || goog.LOCALE == 'fr-DZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_DZ;
    -}
    -
    -if (goog.LOCALE == 'fr_GA' || goog.LOCALE == 'fr-GA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_GA;
    -}
    -
    -if (goog.LOCALE == 'fr_GN' || goog.LOCALE == 'fr-GN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_GN;
    -}
    -
    -if (goog.LOCALE == 'fr_GQ' || goog.LOCALE == 'fr-GQ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_GQ;
    -}
    -
    -if (goog.LOCALE == 'fr_HT' || goog.LOCALE == 'fr-HT') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_HT;
    -}
    -
    -if (goog.LOCALE == 'fr_KM' || goog.LOCALE == 'fr-KM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_KM;
    -}
    -
    -if (goog.LOCALE == 'fr_LU' || goog.LOCALE == 'fr-LU') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_LU;
    -}
    -
    -if (goog.LOCALE == 'fr_MA' || goog.LOCALE == 'fr-MA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_MA;
    -}
    -
    -if (goog.LOCALE == 'fr_MG' || goog.LOCALE == 'fr-MG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_MG;
    -}
    -
    -if (goog.LOCALE == 'fr_ML' || goog.LOCALE == 'fr-ML') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_ML;
    -}
    -
    -if (goog.LOCALE == 'fr_MR' || goog.LOCALE == 'fr-MR') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_MR;
    -}
    -
    -if (goog.LOCALE == 'fr_MU' || goog.LOCALE == 'fr-MU') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_MU;
    -}
    -
    -if (goog.LOCALE == 'fr_NC' || goog.LOCALE == 'fr-NC') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_NC;
    -}
    -
    -if (goog.LOCALE == 'fr_NE' || goog.LOCALE == 'fr-NE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_NE;
    -}
    -
    -if (goog.LOCALE == 'fr_PF' || goog.LOCALE == 'fr-PF') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_PF;
    -}
    -
    -if (goog.LOCALE == 'fr_RW' || goog.LOCALE == 'fr-RW') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_RW;
    -}
    -
    -if (goog.LOCALE == 'fr_SC' || goog.LOCALE == 'fr-SC') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_SC;
    -}
    -
    -if (goog.LOCALE == 'fr_SN' || goog.LOCALE == 'fr-SN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_SN;
    -}
    -
    -if (goog.LOCALE == 'fr_SY' || goog.LOCALE == 'fr-SY') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_SY;
    -}
    -
    -if (goog.LOCALE == 'fr_TD' || goog.LOCALE == 'fr-TD') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_TD;
    -}
    -
    -if (goog.LOCALE == 'fr_TG' || goog.LOCALE == 'fr-TG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_TG;
    -}
    -
    -if (goog.LOCALE == 'fr_TN' || goog.LOCALE == 'fr-TN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_TN;
    -}
    -
    -if (goog.LOCALE == 'fr_VU' || goog.LOCALE == 'fr-VU') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_VU;
    -}
    -
    -if (goog.LOCALE == 'fr_WF' || goog.LOCALE == 'fr-WF') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fr_WF;
    -}
    -
    -if (goog.LOCALE == 'fur') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fur;
    -}
    -
    -if (goog.LOCALE == 'fur_IT' || goog.LOCALE == 'fur-IT') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fur;
    -}
    -
    -if (goog.LOCALE == 'fy') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fy;
    -}
    -
    -if (goog.LOCALE == 'fy_NL' || goog.LOCALE == 'fy-NL') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_fy;
    -}
    -
    -if (goog.LOCALE == 'gd') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_gd;
    -}
    -
    -if (goog.LOCALE == 'gd_GB' || goog.LOCALE == 'gd-GB') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_gd;
    -}
    -
    -if (goog.LOCALE == 'gsw_FR' || goog.LOCALE == 'gsw-FR') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_gsw_FR;
    -}
    -
    -if (goog.LOCALE == 'guz') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_guz;
    -}
    -
    -if (goog.LOCALE == 'guz_KE' || goog.LOCALE == 'guz-KE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_guz;
    -}
    -
    -if (goog.LOCALE == 'gv') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_gv;
    -}
    -
    -if (goog.LOCALE == 'gv_IM' || goog.LOCALE == 'gv-IM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_gv;
    -}
    -
    -if (goog.LOCALE == 'ha') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ha;
    -}
    -
    -if (goog.LOCALE == 'ha_Latn' || goog.LOCALE == 'ha-Latn') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ha_Latn;
    -}
    -
    -if (goog.LOCALE == 'ha_Latn_GH' || goog.LOCALE == 'ha-Latn-GH') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ha_Latn_GH;
    -}
    -
    -if (goog.LOCALE == 'ha_Latn_NE' || goog.LOCALE == 'ha-Latn-NE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ha_Latn_NE;
    -}
    -
    -if (goog.LOCALE == 'ha_Latn_NG' || goog.LOCALE == 'ha-Latn-NG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ha;
    -}
    -
    -if (goog.LOCALE == 'hr_BA' || goog.LOCALE == 'hr-BA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_hr_BA;
    -}
    -
    -if (goog.LOCALE == 'hsb') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_hsb;
    -}
    -
    -if (goog.LOCALE == 'hsb_DE' || goog.LOCALE == 'hsb-DE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_hsb;
    -}
    -
    -if (goog.LOCALE == 'ia') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ia;
    -}
    -
    -if (goog.LOCALE == 'ia_FR' || goog.LOCALE == 'ia-FR') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ia;
    -}
    -
    -if (goog.LOCALE == 'ig') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ig;
    -}
    -
    -if (goog.LOCALE == 'ig_NG' || goog.LOCALE == 'ig-NG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ig;
    -}
    -
    -if (goog.LOCALE == 'ii') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ii;
    -}
    -
    -if (goog.LOCALE == 'ii_CN' || goog.LOCALE == 'ii-CN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ii;
    -}
    -
    -if (goog.LOCALE == 'it_CH' || goog.LOCALE == 'it-CH') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_it_CH;
    -}
    -
    -if (goog.LOCALE == 'jgo') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_jgo;
    -}
    -
    -if (goog.LOCALE == 'jgo_CM' || goog.LOCALE == 'jgo-CM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_jgo;
    -}
    -
    -if (goog.LOCALE == 'jmc') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_jmc;
    -}
    -
    -if (goog.LOCALE == 'jmc_TZ' || goog.LOCALE == 'jmc-TZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_jmc;
    -}
    -
    -if (goog.LOCALE == 'kab') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_kab;
    -}
    -
    -if (goog.LOCALE == 'kab_DZ' || goog.LOCALE == 'kab-DZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_kab;
    -}
    -
    -if (goog.LOCALE == 'kam') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_kam;
    -}
    -
    -if (goog.LOCALE == 'kam_KE' || goog.LOCALE == 'kam-KE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_kam;
    -}
    -
    -if (goog.LOCALE == 'kde') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_kde;
    -}
    -
    -if (goog.LOCALE == 'kde_TZ' || goog.LOCALE == 'kde-TZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_kde;
    -}
    -
    -if (goog.LOCALE == 'kea') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_kea;
    -}
    -
    -if (goog.LOCALE == 'kea_CV' || goog.LOCALE == 'kea-CV') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_kea;
    -}
    -
    -if (goog.LOCALE == 'khq') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_khq;
    -}
    -
    -if (goog.LOCALE == 'khq_ML' || goog.LOCALE == 'khq-ML') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_khq;
    -}
    -
    -if (goog.LOCALE == 'ki') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ki;
    -}
    -
    -if (goog.LOCALE == 'ki_KE' || goog.LOCALE == 'ki-KE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ki;
    -}
    -
    -if (goog.LOCALE == 'kk_Cyrl' || goog.LOCALE == 'kk-Cyrl') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_kk_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'kkj') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_kkj;
    -}
    -
    -if (goog.LOCALE == 'kkj_CM' || goog.LOCALE == 'kkj-CM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_kkj;
    -}
    -
    -if (goog.LOCALE == 'kl') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_kl;
    -}
    -
    -if (goog.LOCALE == 'kl_GL' || goog.LOCALE == 'kl-GL') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_kl;
    -}
    -
    -if (goog.LOCALE == 'kln') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_kln;
    -}
    -
    -if (goog.LOCALE == 'kln_KE' || goog.LOCALE == 'kln-KE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_kln;
    -}
    -
    -if (goog.LOCALE == 'ko_KP' || goog.LOCALE == 'ko-KP') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ko_KP;
    -}
    -
    -if (goog.LOCALE == 'kok') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_kok;
    -}
    -
    -if (goog.LOCALE == 'kok_IN' || goog.LOCALE == 'kok-IN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_kok;
    -}
    -
    -if (goog.LOCALE == 'ks') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ks;
    -}
    -
    -if (goog.LOCALE == 'ks_Arab' || goog.LOCALE == 'ks-Arab') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ks_Arab;
    -}
    -
    -if (goog.LOCALE == 'ks_Arab_IN' || goog.LOCALE == 'ks-Arab-IN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ks;
    -}
    -
    -if (goog.LOCALE == 'ksb') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ksb;
    -}
    -
    -if (goog.LOCALE == 'ksb_TZ' || goog.LOCALE == 'ksb-TZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ksb;
    -}
    -
    -if (goog.LOCALE == 'ksf') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ksf;
    -}
    -
    -if (goog.LOCALE == 'ksf_CM' || goog.LOCALE == 'ksf-CM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ksf;
    -}
    -
    -if (goog.LOCALE == 'ksh') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ksh;
    -}
    -
    -if (goog.LOCALE == 'ksh_DE' || goog.LOCALE == 'ksh-DE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ksh;
    -}
    -
    -if (goog.LOCALE == 'kw') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_kw;
    -}
    -
    -if (goog.LOCALE == 'kw_GB' || goog.LOCALE == 'kw-GB') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_kw;
    -}
    -
    -if (goog.LOCALE == 'ky_Cyrl' || goog.LOCALE == 'ky-Cyrl') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ky_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'lag') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_lag;
    -}
    -
    -if (goog.LOCALE == 'lag_TZ' || goog.LOCALE == 'lag-TZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_lag;
    -}
    -
    -if (goog.LOCALE == 'lb') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_lb;
    -}
    -
    -if (goog.LOCALE == 'lb_LU' || goog.LOCALE == 'lb-LU') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_lb;
    -}
    -
    -if (goog.LOCALE == 'lg') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_lg;
    -}
    -
    -if (goog.LOCALE == 'lg_UG' || goog.LOCALE == 'lg-UG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_lg;
    -}
    -
    -if (goog.LOCALE == 'lkt') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_lkt;
    -}
    -
    -if (goog.LOCALE == 'lkt_US' || goog.LOCALE == 'lkt-US') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_lkt;
    -}
    -
    -if (goog.LOCALE == 'ln_AO' || goog.LOCALE == 'ln-AO') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ln_AO;
    -}
    -
    -if (goog.LOCALE == 'ln_CF' || goog.LOCALE == 'ln-CF') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ln_CF;
    -}
    -
    -if (goog.LOCALE == 'ln_CG' || goog.LOCALE == 'ln-CG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ln_CG;
    -}
    -
    -if (goog.LOCALE == 'lu') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_lu;
    -}
    -
    -if (goog.LOCALE == 'lu_CD' || goog.LOCALE == 'lu-CD') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_lu;
    -}
    -
    -if (goog.LOCALE == 'luo') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_luo;
    -}
    -
    -if (goog.LOCALE == 'luo_KE' || goog.LOCALE == 'luo-KE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_luo;
    -}
    -
    -if (goog.LOCALE == 'luy') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_luy;
    -}
    -
    -if (goog.LOCALE == 'luy_KE' || goog.LOCALE == 'luy-KE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_luy;
    -}
    -
    -if (goog.LOCALE == 'mas') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_mas;
    -}
    -
    -if (goog.LOCALE == 'mas_KE' || goog.LOCALE == 'mas-KE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_mas;
    -}
    -
    -if (goog.LOCALE == 'mas_TZ' || goog.LOCALE == 'mas-TZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_mas_TZ;
    -}
    -
    -if (goog.LOCALE == 'mer') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_mer;
    -}
    -
    -if (goog.LOCALE == 'mer_KE' || goog.LOCALE == 'mer-KE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_mer;
    -}
    -
    -if (goog.LOCALE == 'mfe') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_mfe;
    -}
    -
    -if (goog.LOCALE == 'mfe_MU' || goog.LOCALE == 'mfe-MU') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_mfe;
    -}
    -
    -if (goog.LOCALE == 'mg') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_mg;
    -}
    -
    -if (goog.LOCALE == 'mg_MG' || goog.LOCALE == 'mg-MG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_mg;
    -}
    -
    -if (goog.LOCALE == 'mgh') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_mgh;
    -}
    -
    -if (goog.LOCALE == 'mgh_MZ' || goog.LOCALE == 'mgh-MZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_mgh;
    -}
    -
    -if (goog.LOCALE == 'mgo') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_mgo;
    -}
    -
    -if (goog.LOCALE == 'mgo_CM' || goog.LOCALE == 'mgo-CM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_mgo;
    -}
    -
    -if (goog.LOCALE == 'mn_Cyrl' || goog.LOCALE == 'mn-Cyrl') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_mn_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'ms_Latn' || goog.LOCALE == 'ms-Latn') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ms_Latn;
    -}
    -
    -if (goog.LOCALE == 'ms_Latn_BN' || goog.LOCALE == 'ms-Latn-BN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ms_Latn_BN;
    -}
    -
    -if (goog.LOCALE == 'ms_Latn_SG' || goog.LOCALE == 'ms-Latn-SG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ms_Latn_SG;
    -}
    -
    -if (goog.LOCALE == 'mua') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_mua;
    -}
    -
    -if (goog.LOCALE == 'mua_CM' || goog.LOCALE == 'mua-CM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_mua;
    -}
    -
    -if (goog.LOCALE == 'naq') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_naq;
    -}
    -
    -if (goog.LOCALE == 'naq_NA' || goog.LOCALE == 'naq-NA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_naq;
    -}
    -
    -if (goog.LOCALE == 'nd') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_nd;
    -}
    -
    -if (goog.LOCALE == 'nd_ZW' || goog.LOCALE == 'nd-ZW') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_nd;
    -}
    -
    -if (goog.LOCALE == 'ne_IN' || goog.LOCALE == 'ne-IN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ne_IN;
    -}
    -
    -if (goog.LOCALE == 'nl_AW' || goog.LOCALE == 'nl-AW') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_nl_AW;
    -}
    -
    -if (goog.LOCALE == 'nl_BE' || goog.LOCALE == 'nl-BE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_nl_BE;
    -}
    -
    -if (goog.LOCALE == 'nl_BQ' || goog.LOCALE == 'nl-BQ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_nl_BQ;
    -}
    -
    -if (goog.LOCALE == 'nl_CW' || goog.LOCALE == 'nl-CW') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_nl_CW;
    -}
    -
    -if (goog.LOCALE == 'nl_SR' || goog.LOCALE == 'nl-SR') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_nl_SR;
    -}
    -
    -if (goog.LOCALE == 'nl_SX' || goog.LOCALE == 'nl-SX') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_nl_SX;
    -}
    -
    -if (goog.LOCALE == 'nmg') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_nmg;
    -}
    -
    -if (goog.LOCALE == 'nmg_CM' || goog.LOCALE == 'nmg-CM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_nmg;
    -}
    -
    -if (goog.LOCALE == 'nn') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_nn;
    -}
    -
    -if (goog.LOCALE == 'nn_NO' || goog.LOCALE == 'nn-NO') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_nn;
    -}
    -
    -if (goog.LOCALE == 'nnh') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_nnh;
    -}
    -
    -if (goog.LOCALE == 'nnh_CM' || goog.LOCALE == 'nnh-CM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_nnh;
    -}
    -
    -if (goog.LOCALE == 'nr') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_nr;
    -}
    -
    -if (goog.LOCALE == 'nr_ZA' || goog.LOCALE == 'nr-ZA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_nr;
    -}
    -
    -if (goog.LOCALE == 'nso') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_nso;
    -}
    -
    -if (goog.LOCALE == 'nso_ZA' || goog.LOCALE == 'nso-ZA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_nso;
    -}
    -
    -if (goog.LOCALE == 'nus') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_nus;
    -}
    -
    -if (goog.LOCALE == 'nus_SD' || goog.LOCALE == 'nus-SD') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_nus;
    -}
    -
    -if (goog.LOCALE == 'nyn') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_nyn;
    -}
    -
    -if (goog.LOCALE == 'nyn_UG' || goog.LOCALE == 'nyn-UG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_nyn;
    -}
    -
    -if (goog.LOCALE == 'om') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_om;
    -}
    -
    -if (goog.LOCALE == 'om_ET' || goog.LOCALE == 'om-ET') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_om;
    -}
    -
    -if (goog.LOCALE == 'om_KE' || goog.LOCALE == 'om-KE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_om_KE;
    -}
    -
    -if (goog.LOCALE == 'os') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_os;
    -}
    -
    -if (goog.LOCALE == 'os_GE' || goog.LOCALE == 'os-GE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_os;
    -}
    -
    -if (goog.LOCALE == 'os_RU' || goog.LOCALE == 'os-RU') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_os_RU;
    -}
    -
    -if (goog.LOCALE == 'pa_Arab' || goog.LOCALE == 'pa-Arab') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_pa_Arab;
    -}
    -
    -if (goog.LOCALE == 'pa_Arab_PK' || goog.LOCALE == 'pa-Arab-PK') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_pa_Arab;
    -}
    -
    -if (goog.LOCALE == 'pa_Guru' || goog.LOCALE == 'pa-Guru') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_pa_Guru;
    -}
    -
    -if (goog.LOCALE == 'ps') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ps;
    -}
    -
    -if (goog.LOCALE == 'ps_AF' || goog.LOCALE == 'ps-AF') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ps;
    -}
    -
    -if (goog.LOCALE == 'pt_AO' || goog.LOCALE == 'pt-AO') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_pt_AO;
    -}
    -
    -if (goog.LOCALE == 'pt_CV' || goog.LOCALE == 'pt-CV') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_pt_CV;
    -}
    -
    -if (goog.LOCALE == 'pt_GW' || goog.LOCALE == 'pt-GW') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_pt_GW;
    -}
    -
    -if (goog.LOCALE == 'pt_MO' || goog.LOCALE == 'pt-MO') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_pt_MO;
    -}
    -
    -if (goog.LOCALE == 'pt_MZ' || goog.LOCALE == 'pt-MZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_pt_MZ;
    -}
    -
    -if (goog.LOCALE == 'pt_ST' || goog.LOCALE == 'pt-ST') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_pt_ST;
    -}
    -
    -if (goog.LOCALE == 'pt_TL' || goog.LOCALE == 'pt-TL') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_pt_TL;
    -}
    -
    -if (goog.LOCALE == 'qu') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_qu;
    -}
    -
    -if (goog.LOCALE == 'qu_BO' || goog.LOCALE == 'qu-BO') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_qu_BO;
    -}
    -
    -if (goog.LOCALE == 'qu_EC' || goog.LOCALE == 'qu-EC') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_qu_EC;
    -}
    -
    -if (goog.LOCALE == 'qu_PE' || goog.LOCALE == 'qu-PE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_qu;
    -}
    -
    -if (goog.LOCALE == 'rm') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_rm;
    -}
    -
    -if (goog.LOCALE == 'rm_CH' || goog.LOCALE == 'rm-CH') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_rm;
    -}
    -
    -if (goog.LOCALE == 'rn') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_rn;
    -}
    -
    -if (goog.LOCALE == 'rn_BI' || goog.LOCALE == 'rn-BI') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_rn;
    -}
    -
    -if (goog.LOCALE == 'ro_MD' || goog.LOCALE == 'ro-MD') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ro_MD;
    -}
    -
    -if (goog.LOCALE == 'rof') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_rof;
    -}
    -
    -if (goog.LOCALE == 'rof_TZ' || goog.LOCALE == 'rof-TZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_rof;
    -}
    -
    -if (goog.LOCALE == 'ru_BY' || goog.LOCALE == 'ru-BY') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ru_BY;
    -}
    -
    -if (goog.LOCALE == 'ru_KG' || goog.LOCALE == 'ru-KG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ru_KG;
    -}
    -
    -if (goog.LOCALE == 'ru_KZ' || goog.LOCALE == 'ru-KZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ru_KZ;
    -}
    -
    -if (goog.LOCALE == 'ru_MD' || goog.LOCALE == 'ru-MD') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ru_MD;
    -}
    -
    -if (goog.LOCALE == 'ru_UA' || goog.LOCALE == 'ru-UA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ru_UA;
    -}
    -
    -if (goog.LOCALE == 'rw') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_rw;
    -}
    -
    -if (goog.LOCALE == 'rw_RW' || goog.LOCALE == 'rw-RW') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_rw;
    -}
    -
    -if (goog.LOCALE == 'rwk') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_rwk;
    -}
    -
    -if (goog.LOCALE == 'rwk_TZ' || goog.LOCALE == 'rwk-TZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_rwk;
    -}
    -
    -if (goog.LOCALE == 'sah') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sah;
    -}
    -
    -if (goog.LOCALE == 'sah_RU' || goog.LOCALE == 'sah-RU') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sah;
    -}
    -
    -if (goog.LOCALE == 'saq') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_saq;
    -}
    -
    -if (goog.LOCALE == 'saq_KE' || goog.LOCALE == 'saq-KE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_saq;
    -}
    -
    -if (goog.LOCALE == 'sbp') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sbp;
    -}
    -
    -if (goog.LOCALE == 'sbp_TZ' || goog.LOCALE == 'sbp-TZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sbp;
    -}
    -
    -if (goog.LOCALE == 'se') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_se;
    -}
    -
    -if (goog.LOCALE == 'se_FI' || goog.LOCALE == 'se-FI') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_se_FI;
    -}
    -
    -if (goog.LOCALE == 'se_NO' || goog.LOCALE == 'se-NO') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_se;
    -}
    -
    -if (goog.LOCALE == 'se_SE' || goog.LOCALE == 'se-SE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_se_SE;
    -}
    -
    -if (goog.LOCALE == 'seh') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_seh;
    -}
    -
    -if (goog.LOCALE == 'seh_MZ' || goog.LOCALE == 'seh-MZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_seh;
    -}
    -
    -if (goog.LOCALE == 'ses') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ses;
    -}
    -
    -if (goog.LOCALE == 'ses_ML' || goog.LOCALE == 'ses-ML') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ses;
    -}
    -
    -if (goog.LOCALE == 'sg') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sg;
    -}
    -
    -if (goog.LOCALE == 'sg_CF' || goog.LOCALE == 'sg-CF') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sg;
    -}
    -
    -if (goog.LOCALE == 'shi') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_shi;
    -}
    -
    -if (goog.LOCALE == 'shi_Latn' || goog.LOCALE == 'shi-Latn') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_shi_Latn;
    -}
    -
    -if (goog.LOCALE == 'shi_Latn_MA' || goog.LOCALE == 'shi-Latn-MA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_shi;
    -}
    -
    -if (goog.LOCALE == 'shi_Tfng' || goog.LOCALE == 'shi-Tfng') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_shi_Tfng;
    -}
    -
    -if (goog.LOCALE == 'shi_Tfng_MA' || goog.LOCALE == 'shi-Tfng-MA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_shi;
    -}
    -
    -if (goog.LOCALE == 'smn') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_smn;
    -}
    -
    -if (goog.LOCALE == 'smn_FI' || goog.LOCALE == 'smn-FI') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_smn;
    -}
    -
    -if (goog.LOCALE == 'sn') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sn;
    -}
    -
    -if (goog.LOCALE == 'sn_ZW' || goog.LOCALE == 'sn-ZW') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sn;
    -}
    -
    -if (goog.LOCALE == 'so') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_so;
    -}
    -
    -if (goog.LOCALE == 'so_DJ' || goog.LOCALE == 'so-DJ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_so_DJ;
    -}
    -
    -if (goog.LOCALE == 'so_ET' || goog.LOCALE == 'so-ET') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_so_ET;
    -}
    -
    -if (goog.LOCALE == 'so_KE' || goog.LOCALE == 'so-KE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_so_KE;
    -}
    -
    -if (goog.LOCALE == 'so_SO' || goog.LOCALE == 'so-SO') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_so;
    -}
    -
    -if (goog.LOCALE == 'sq_MK' || goog.LOCALE == 'sq-MK') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sq_MK;
    -}
    -
    -if (goog.LOCALE == 'sq_XK' || goog.LOCALE == 'sq-XK') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sq_XK;
    -}
    -
    -if (goog.LOCALE == 'sr_Cyrl' || goog.LOCALE == 'sr-Cyrl') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sr_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'sr_Cyrl_BA' || goog.LOCALE == 'sr-Cyrl-BA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sr_Cyrl_BA;
    -}
    -
    -if (goog.LOCALE == 'sr_Cyrl_ME' || goog.LOCALE == 'sr-Cyrl-ME') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sr_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'sr_Cyrl_XK' || goog.LOCALE == 'sr-Cyrl-XK') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sr_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'sr_Latn' || goog.LOCALE == 'sr-Latn') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sr_Latn;
    -}
    -
    -if (goog.LOCALE == 'sr_Latn_BA' || goog.LOCALE == 'sr-Latn-BA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sr_Latn_BA;
    -}
    -
    -if (goog.LOCALE == 'sr_Latn_ME' || goog.LOCALE == 'sr-Latn-ME') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sr_Latn_ME;
    -}
    -
    -if (goog.LOCALE == 'sr_Latn_RS' || goog.LOCALE == 'sr-Latn-RS') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sr_Latn;
    -}
    -
    -if (goog.LOCALE == 'sr_Latn_XK' || goog.LOCALE == 'sr-Latn-XK') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sr_Latn_XK;
    -}
    -
    -if (goog.LOCALE == 'ss') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ss;
    -}
    -
    -if (goog.LOCALE == 'ss_SZ' || goog.LOCALE == 'ss-SZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ss_SZ;
    -}
    -
    -if (goog.LOCALE == 'ss_ZA' || goog.LOCALE == 'ss-ZA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ss;
    -}
    -
    -if (goog.LOCALE == 'ssy') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ssy;
    -}
    -
    -if (goog.LOCALE == 'ssy_ER' || goog.LOCALE == 'ssy-ER') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ssy;
    -}
    -
    -if (goog.LOCALE == 'sv_AX' || goog.LOCALE == 'sv-AX') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sv_AX;
    -}
    -
    -if (goog.LOCALE == 'sv_FI' || goog.LOCALE == 'sv-FI') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sv_FI;
    -}
    -
    -if (goog.LOCALE == 'sw_KE' || goog.LOCALE == 'sw-KE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sw_KE;
    -}
    -
    -if (goog.LOCALE == 'sw_UG' || goog.LOCALE == 'sw-UG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_sw_UG;
    -}
    -
    -if (goog.LOCALE == 'swc') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_swc;
    -}
    -
    -if (goog.LOCALE == 'swc_CD' || goog.LOCALE == 'swc-CD') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_swc;
    -}
    -
    -if (goog.LOCALE == 'ta_LK' || goog.LOCALE == 'ta-LK') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ta_LK;
    -}
    -
    -if (goog.LOCALE == 'ta_MY' || goog.LOCALE == 'ta-MY') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ta_MY;
    -}
    -
    -if (goog.LOCALE == 'ta_SG' || goog.LOCALE == 'ta-SG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ta_SG;
    -}
    -
    -if (goog.LOCALE == 'teo') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_teo;
    -}
    -
    -if (goog.LOCALE == 'teo_KE' || goog.LOCALE == 'teo-KE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_teo_KE;
    -}
    -
    -if (goog.LOCALE == 'teo_UG' || goog.LOCALE == 'teo-UG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_teo;
    -}
    -
    -if (goog.LOCALE == 'ti') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ti;
    -}
    -
    -if (goog.LOCALE == 'ti_ER' || goog.LOCALE == 'ti-ER') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ti_ER;
    -}
    -
    -if (goog.LOCALE == 'ti_ET' || goog.LOCALE == 'ti-ET') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ti;
    -}
    -
    -if (goog.LOCALE == 'tn') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_tn;
    -}
    -
    -if (goog.LOCALE == 'tn_BW' || goog.LOCALE == 'tn-BW') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_tn_BW;
    -}
    -
    -if (goog.LOCALE == 'tn_ZA' || goog.LOCALE == 'tn-ZA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_tn;
    -}
    -
    -if (goog.LOCALE == 'to') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_to;
    -}
    -
    -if (goog.LOCALE == 'to_TO' || goog.LOCALE == 'to-TO') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_to;
    -}
    -
    -if (goog.LOCALE == 'tr_CY' || goog.LOCALE == 'tr-CY') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_tr_CY;
    -}
    -
    -if (goog.LOCALE == 'ts') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ts;
    -}
    -
    -if (goog.LOCALE == 'ts_ZA' || goog.LOCALE == 'ts-ZA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ts;
    -}
    -
    -if (goog.LOCALE == 'twq') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_twq;
    -}
    -
    -if (goog.LOCALE == 'twq_NE' || goog.LOCALE == 'twq-NE') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_twq;
    -}
    -
    -if (goog.LOCALE == 'tzm') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_tzm;
    -}
    -
    -if (goog.LOCALE == 'tzm_Latn' || goog.LOCALE == 'tzm-Latn') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_tzm_Latn;
    -}
    -
    -if (goog.LOCALE == 'tzm_Latn_MA' || goog.LOCALE == 'tzm-Latn-MA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_tzm;
    -}
    -
    -if (goog.LOCALE == 'ug') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ug;
    -}
    -
    -if (goog.LOCALE == 'ug_Arab' || goog.LOCALE == 'ug-Arab') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ug_Arab;
    -}
    -
    -if (goog.LOCALE == 'ug_Arab_CN' || goog.LOCALE == 'ug-Arab-CN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ug;
    -}
    -
    -if (goog.LOCALE == 'ur_IN' || goog.LOCALE == 'ur-IN') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ur_IN;
    -}
    -
    -if (goog.LOCALE == 'uz_Arab' || goog.LOCALE == 'uz-Arab') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_uz_Arab;
    -}
    -
    -if (goog.LOCALE == 'uz_Arab_AF' || goog.LOCALE == 'uz-Arab-AF') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_uz_Arab;
    -}
    -
    -if (goog.LOCALE == 'uz_Cyrl' || goog.LOCALE == 'uz-Cyrl') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_uz_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'uz_Cyrl_UZ' || goog.LOCALE == 'uz-Cyrl-UZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_uz_Cyrl_UZ;
    -}
    -
    -if (goog.LOCALE == 'uz_Latn' || goog.LOCALE == 'uz-Latn') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_uz_Latn;
    -}
    -
    -if (goog.LOCALE == 'vai') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_vai;
    -}
    -
    -if (goog.LOCALE == 'vai_Latn' || goog.LOCALE == 'vai-Latn') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_vai_Latn;
    -}
    -
    -if (goog.LOCALE == 'vai_Latn_LR' || goog.LOCALE == 'vai-Latn-LR') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_vai;
    -}
    -
    -if (goog.LOCALE == 'vai_Vaii' || goog.LOCALE == 'vai-Vaii') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_vai_Vaii;
    -}
    -
    -if (goog.LOCALE == 'vai_Vaii_LR' || goog.LOCALE == 'vai-Vaii-LR') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_vai;
    -}
    -
    -if (goog.LOCALE == 've') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ve;
    -}
    -
    -if (goog.LOCALE == 've_ZA' || goog.LOCALE == 've-ZA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_ve;
    -}
    -
    -if (goog.LOCALE == 'vo') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_vo;
    -}
    -
    -if (goog.LOCALE == 'vo_001' || goog.LOCALE == 'vo-001') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_vo;
    -}
    -
    -if (goog.LOCALE == 'vun') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_vun;
    -}
    -
    -if (goog.LOCALE == 'vun_TZ' || goog.LOCALE == 'vun-TZ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_vun;
    -}
    -
    -if (goog.LOCALE == 'wae') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_wae;
    -}
    -
    -if (goog.LOCALE == 'wae_CH' || goog.LOCALE == 'wae-CH') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_wae;
    -}
    -
    -if (goog.LOCALE == 'xog') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_xog;
    -}
    -
    -if (goog.LOCALE == 'xog_UG' || goog.LOCALE == 'xog-UG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_xog;
    -}
    -
    -if (goog.LOCALE == 'yav') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_yav;
    -}
    -
    -if (goog.LOCALE == 'yav_CM' || goog.LOCALE == 'yav-CM') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_yav;
    -}
    -
    -if (goog.LOCALE == 'yi') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_yi;
    -}
    -
    -if (goog.LOCALE == 'yi_001' || goog.LOCALE == 'yi-001') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_yi;
    -}
    -
    -if (goog.LOCALE == 'yo') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_yo;
    -}
    -
    -if (goog.LOCALE == 'yo_BJ' || goog.LOCALE == 'yo-BJ') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_yo_BJ;
    -}
    -
    -if (goog.LOCALE == 'yo_NG' || goog.LOCALE == 'yo-NG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_yo;
    -}
    -
    -if (goog.LOCALE == 'zgh') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_zgh;
    -}
    -
    -if (goog.LOCALE == 'zgh_MA' || goog.LOCALE == 'zgh-MA') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_zgh;
    -}
    -
    -if (goog.LOCALE == 'zh_Hans' || goog.LOCALE == 'zh-Hans') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_zh_Hans;
    -}
    -
    -if (goog.LOCALE == 'zh_Hans_HK' || goog.LOCALE == 'zh-Hans-HK') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_zh_Hans_HK;
    -}
    -
    -if (goog.LOCALE == 'zh_Hans_MO' || goog.LOCALE == 'zh-Hans-MO') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_zh_Hans_MO;
    -}
    -
    -if (goog.LOCALE == 'zh_Hans_SG' || goog.LOCALE == 'zh-Hans-SG') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_zh_Hans_SG;
    -}
    -
    -if (goog.LOCALE == 'zh_Hant' || goog.LOCALE == 'zh-Hant') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_zh_Hant;
    -}
    -
    -if (goog.LOCALE == 'zh_Hant_HK' || goog.LOCALE == 'zh-Hant-HK') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_zh_Hant_HK;
    -}
    -
    -if (goog.LOCALE == 'zh_Hant_MO' || goog.LOCALE == 'zh-Hant-MO') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_zh_Hant_MO;
    -}
    -
    -if (goog.LOCALE == 'zh_Hant_TW' || goog.LOCALE == 'zh-Hant-TW') {
    -  goog.i18n.CompactNumberFormatSymbols = goog.i18n.CompactNumberFormatSymbols_zh_Hant;
    -}
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/currency.js b/src/database/third_party/closure-library/closure/goog/i18n/currency.js
    deleted file mode 100644
    index 6396efd811c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/currency.js
    +++ /dev/null
    @@ -1,437 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview A utility to get better currency format pattern.
    - *
    - * This module implements a new currency format representation model. It
    - * provides 3 currency representation forms: global, portable and local. Local
    - * format is the most popular format people use to represent currency in its
    - * circulating country without worrying about how it should be distinguished
    - * from other currencies.  Global format is a formal representation in context
    - * of multiple currencies in same page, it is ISO 4217 currency code. Portable
    - * format is a compromise between global and local. It looks similar to how
    - * people would like to see how their currency is being represented in other
    - * media. While at the same time, it should be distinguishable to world's
    - * popular currencies (like USD, EUR) and currencies somewhat relevant in the
    - * area (like CNY in HK, though native currency is HKD). There is no guarantee
    - * of uniqueness.
    - *
    - */
    -
    -
    -goog.provide('goog.i18n.currency');
    -goog.provide('goog.i18n.currency.CurrencyInfo');
    -goog.provide('goog.i18n.currency.CurrencyInfoTier2');
    -
    -
    -/**
    - * The mask of precision field.
    - * @private
    - */
    -goog.i18n.currency.PRECISION_MASK_ = 0x07;
    -
    -
    -/**
    - * Whether the currency sign should be positioned after the number.
    - * @private
    - */
    -goog.i18n.currency.POSITION_FLAG_ = 0x10;
    -
    -
    -/**
    - * Whether a space should be inserted between the number and currency sign.
    - * @private
    - */
    -goog.i18n.currency.SPACE_FLAG_ = 0x20;
    -
    -
    -/**
    - * Whether tier2 was enabled already by calling addTier2Support().
    - * @private
    - */
    -goog.i18n.currency.tier2Enabled_ = false;
    -
    -
    -/**
    - * This function will add tier2 currency support. Be default, only tier1
    - * (most popular currencies) are supported. If an application really needs
    - * to support some of the rarely used currencies, it should call this function
    - * before any other functions in this namespace.
    - */
    -goog.i18n.currency.addTier2Support = function() {
    -  // Protection from executing this these again and again.
    -  if (!goog.i18n.currency.tier2Enabled_) {
    -    for (var key in goog.i18n.currency.CurrencyInfoTier2) {
    -      goog.i18n.currency.CurrencyInfo[key] =
    -          goog.i18n.currency.CurrencyInfoTier2[key];
    -    }
    -    goog.i18n.currency.tier2Enabled_ = true;
    -  }
    -};
    -
    -
    -/**
    - * Global currency pattern always uses ISO-4217 currency code as prefix. Local
    - * currency sign is added if it is different from currency code. Each currency
    - * is unique in this form. The negative side is that ISO code looks weird in
    - * some countries as people normally do not use it. Local currency sign
    - * alleviates the problem, but also makes it a little verbose.
    - *
    - * @param {string} currencyCode ISO-4217 3-letter currency code.
    - * @return {string} Global currency pattern string for given currency.
    - */
    -goog.i18n.currency.getGlobalCurrencyPattern = function(currencyCode) {
    -  var info = goog.i18n.currency.CurrencyInfo[currencyCode];
    -  var patternNum = info[0];
    -  if (currencyCode == info[1]) {
    -    return goog.i18n.currency.getCurrencyPattern_(patternNum, info[1]);
    -  }
    -  return currencyCode + ' ' +
    -      goog.i18n.currency.getCurrencyPattern_(patternNum, info[1]);
    -};
    -
    -
    -/**
    - * Return global currency sign string for those applications
    - * that want to handle currency sign themselves.
    - *
    - * @param {string} currencyCode ISO-4217 3-letter currency code.
    - * @return {string} Global currency sign for given currency.
    - */
    -goog.i18n.currency.getGlobalCurrencySign = function(currencyCode) {
    -  var info = goog.i18n.currency.CurrencyInfo[currencyCode];
    -  return (currencyCode == info[1]) ? currencyCode :
    -      currencyCode + ' ' + info[1];
    -};
    -
    -
    -/**
    - * Local currency pattern is the most frequently used pattern in currency's
    - * native region. It does not care about how it is distinguished from other
    - * currencies.
    - *
    - * @param {string} currencyCode ISO-4217 3-letter currency code.
    - * @return {string} Local currency pattern string for given currency.
    - */
    -goog.i18n.currency.getLocalCurrencyPattern = function(currencyCode) {
    -  var info = goog.i18n.currency.CurrencyInfo[currencyCode];
    -  return goog.i18n.currency.getCurrencyPattern_(info[0], info[1]);
    -};
    -
    -
    -/**
    - * Returns local currency sign string for those applications that need to
    - * handle currency sign separately.
    - *
    - * @param {string} currencyCode ISO-4217 3-letter currency code.
    - * @return {string} Local currency sign for given currency.
    - */
    -goog.i18n.currency.getLocalCurrencySign = function(currencyCode) {
    -  return goog.i18n.currency.CurrencyInfo[currencyCode][1];
    -};
    -
    -
    -/**
    - * Portable currency pattern is a compromise between local and global. It is
    - * not a mere blend or mid-way between the two. Currency sign is chosen so that
    - * it looks familiar to native users. It also has enough information to
    - * distinguish itself from other popular currencies in its native region.
    - * In this pattern, currency sign symbols that has availability problem in
    - * popular fonts are also avoided.
    - *
    - * @param {string} currencyCode ISO-4217 3-letter currency code.
    - * @return {string} Portable currency pattern string for given currency.
    - */
    -goog.i18n.currency.getPortableCurrencyPattern = function(currencyCode) {
    -  var info = goog.i18n.currency.CurrencyInfo[currencyCode];
    -  return goog.i18n.currency.getCurrencyPattern_(info[0], info[2]);
    -};
    -
    -
    -/**
    - * Return portable currency sign string for those applications that need to
    - * handle currency sign themselves.
    - *
    - * @param {string} currencyCode ISO-4217 3-letter currency code.
    - * @return {string} Portable currency sign for given currency.
    - */
    -goog.i18n.currency.getPortableCurrencySign = function(currencyCode) {
    -  return goog.i18n.currency.CurrencyInfo[currencyCode][2];
    -};
    -
    -
    -/**
    - * This function returns the default currency sign position. Some applications
    - * may want to handle currency sign and currency amount separately. This
    - * function can be used in such situations to correctly position the currency
    - * sign relative to the amount.
    - *
    - * To match the behavior of ICU, position is not determined by display locale.
    - *
    - * @param {string} currencyCode ISO-4217 3-letter currency code.
    - * @return {boolean} true if currency should be positioned before amount field.
    - */
    -goog.i18n.currency.isPrefixSignPosition = function(currencyCode) {
    -  return (goog.i18n.currency.CurrencyInfo[currencyCode][0] &
    -          goog.i18n.currency.POSITION_FLAG_) == 0;
    -};
    -
    -
    -/**
    - * This function constructs the currency pattern. Currency sign is provided. The
    - * pattern information is encoded in patternNum.
    - *
    - * @param {number} patternNum Encoded pattern number that has
    - *     currency pattern information.
    - * @param {string} sign The currency sign that will be used in pattern.
    - * @return {string} currency pattern string.
    - * @private
    - */
    -goog.i18n.currency.getCurrencyPattern_ = function(patternNum, sign) {
    -  var strParts = ['#,##0'];
    -  var precision = patternNum & goog.i18n.currency.PRECISION_MASK_;
    -  if (precision > 0) {
    -    strParts.push('.');
    -    for (var i = 0; i < precision; i++) {
    -      strParts.push('0');
    -    }
    -  }
    -  if ((patternNum & goog.i18n.currency.POSITION_FLAG_) == 0) {
    -    strParts.unshift((patternNum & goog.i18n.currency.SPACE_FLAG_) ?
    -                     "' " : "'");
    -    strParts.unshift(sign);
    -    strParts.unshift("'");
    -  } else {
    -    strParts.push((patternNum & goog.i18n.currency.SPACE_FLAG_) ? " '" : "'",
    -                  sign, "'");
    -  }
    -  return strParts.join('');
    -};
    -
    -
    -/**
    - * Modify currency pattern string by adjusting precision for given currency.
    - * Standard currency pattern will have 2 digit after decimal point.
    - * Examples:
    - *   $#,##0.00 ->  $#,##0    (precision == 0)
    - *   $#,##0.00 ->  $#,##0.0  (precision == 1)
    - *   $#,##0.00 ->  $#,##0.000  (precision == 3)
    - *
    - * @param {string} pattern currency pattern string.
    - * @param {string} currencyCode 3-letter currency code.
    - * @return {string} modified currency pattern string.
    - */
    -goog.i18n.currency.adjustPrecision = function(pattern, currencyCode) {
    -  var strParts = ['0'];
    -  var info = goog.i18n.currency.CurrencyInfo[currencyCode];
    -  var precision = info[0] & goog.i18n.currency.PRECISION_MASK_;
    -  if (precision > 0) {
    -    strParts.push('.');
    -    for (var i = 0; i < precision; i++) {
    -      strParts.push('0');
    -    }
    -  }
    -  return pattern.replace(/0.00/g, strParts.join(''));
    -};
    -
    -
    -/**
    - * Tier 1 currency information.
    - *
    - * The first number in the array is a combination of the precision mask and
    - * other flags. The precision mask indicates how many decimal places to show for
    - * the currency. Valid values are [0..7]. The position flag indicates whether
    - * the currency sign should be positioned after the number. Valid values are 0
    - * (before the number) or 16 (after the number). The space flag indicates
    - * whether a space should be inserted between the currency sign and number.
    - * Valid values are 0 (no space) and 32 (space).
    - *
    - * The number in the array is calculated by adding together the mask and flag
    - * values. For example:
    - *
    - * 0: no precision (0), currency sign first (0), no space (0)
    - * 2: two decimals precision (2), currency sign first (0), no space (0)
    - * 18: two decimals precision (2), currency sign last (16), no space (0)
    - * 50: two decimals precision (2), currency sign last (16), space (32)
    - *
    - * @const {!Object<!Array<?>>}
    - */
    -goog.i18n.currency.CurrencyInfo = {
    -  'AED': [2, 'dh', '\u062f.\u0625.', 'DH'],
    -  'ALL': [0, 'Lek', 'Lek'],
    -  'AUD': [2, '$', 'AU$'],
    -  'BDT': [2, '\u09F3', 'Tk'],
    -  'BGN': [2, 'lev', 'lev'],
    -  'BRL': [2, 'R$', 'R$'],
    -  'CAD': [2, '$', 'C$'],
    -  'CDF': [2, 'FrCD', 'CDF'],
    -  'CHF': [2, 'CHF', 'CHF'],
    -  'CLP': [0, '$', 'CL$'],
    -  'CNY': [2, '¥', 'RMB¥'],
    -  'COP': [0, '$', 'COL$'],
    -  'CRC': [0, '\u20a1', 'CR\u20a1'],
    -  'CZK': [50, 'K\u010d', 'K\u010d'],
    -  'DKK': [18, 'kr', 'kr'],
    -  'DOP': [2, '$', 'RD$'],
    -  'EGP': [2, '£', 'LE'],
    -  'ETB': [2, 'Birr', 'Birr'],
    -  'EUR': [2, '€', '€'],
    -  'GBP': [2, '£', 'GB£'],
    -  'HKD': [2, '$', 'HK$'],
    -  'HRK': [2, 'kn', 'kn'],
    -  'HUF': [0, 'Ft', 'Ft'],
    -  'IDR': [0, 'Rp', 'Rp'],
    -  'ILS': [2, '\u20AA', 'IL\u20AA'],
    -  'INR': [2, '\u20B9', 'Rs'],
    -  'IRR': [0, 'Rial', 'IRR'],
    -  'ISK': [0, 'kr', 'kr'],
    -  'JMD': [2, '$', 'JA$'],
    -  'JPY': [0, '¥', 'JP¥'],
    -  'KRW': [0, '\u20A9', 'KR₩'],
    -  'LKR': [2, 'Rs', 'SLRs'],
    -  'LTL': [2, 'Lt', 'Lt'],
    -  'MNT': [0, '\u20AE', 'MN₮'],
    -  'MVR': [2, 'Rf', 'MVR'],
    -  'MXN': [2, '$', 'Mex$'],
    -  'MYR': [2, 'RM', 'RM'],
    -  'NOK': [50, 'kr', 'NOkr'],
    -  'PAB': [2, 'B/.', 'B/.'],
    -  'PEN': [2, 'S/.', 'S/.'],
    -  'PHP': [2, '\u20B1', 'Php'],
    -  'PKR': [0, 'Rs', 'PKRs.'],
    -  'PLN': [50, 'z\u0142', 'z\u0142'],
    -  'RON': [2, 'RON', 'RON'],
    -  'RSD': [0, 'din', 'RSD'],
    -  'RUB': [50, 'руб.', 'руб.'],
    -  'SAR': [2, 'Rial', 'Rial'],
    -  'SEK': [2, 'kr', 'kr'],
    -  'SGD': [2, '$', 'S$'],
    -  'THB': [2, '\u0e3f', 'THB'],
    -  'TRY': [2, 'TL', 'YTL'],
    -  'TWD': [2, 'NT$', 'NT$'],
    -  'TZS': [0, 'TSh', 'TSh'],
    -  'UAH': [2, '\u20B4', 'UAH'],
    -  'USD': [2, '$', 'US$'],
    -  'UYU': [2, '$', '$U'],
    -  'VND': [0, '\u20AB', 'VN\u20AB'],
    -  'YER': [0, 'Rial', 'Rial'],
    -  'ZAR': [2, 'R', 'ZAR']
    -};
    -
    -
    -/**
    - * Tier 2 currency information.
    - * @const {!Object<!Array<?>>}
    - */
    -goog.i18n.currency.CurrencyInfoTier2 = {
    -  'AFN': [48, 'Af.', 'AFN'],
    -  'AMD': [0, 'Dram', 'dram'],
    -  'ANG': [2, 'NAf.', 'ANG'],
    -  'AOA': [2, 'Kz', 'Kz'],
    -  'ARS': [2, '$', 'AR$'],
    -  'AWG': [2, 'Afl.', 'Afl.'],
    -  'AZN': [2, 'man.', 'man.'],
    -  'BAM': [2, 'KM', 'KM'],
    -  'BBD': [2, '$', 'Bds$'],
    -  'BHD': [3, 'din', 'din'],
    -  'BIF': [0, 'FBu', 'FBu'],
    -  'BMD': [2, '$', 'BD$'],
    -  'BND': [2, '$', 'B$'],
    -  'BOB': [2, 'Bs', 'Bs'],
    -  'BSD': [2, '$', 'BS$'],
    -  'BTN': [2, 'Nu.', 'Nu.'],
    -  'BWP': [2, 'P', 'pula'],
    -  'BYR': [0, 'BYR', 'BYR'],
    -  'BZD': [2, '$', 'BZ$'],
    -  'CUC': [1, '$', 'CUC$'],
    -  'CUP': [2, '$', 'CU$'],
    -  'CVE': [2, 'CVE', 'Esc'],
    -  'DJF': [0, 'Fdj', 'Fdj'],
    -  'DZD': [2, 'din', 'din'],
    -  'ERN': [2, 'Nfk', 'Nfk'],
    -  'FJD': [2, '$', 'FJ$'],
    -  'FKP': [2, '£', 'FK£'],
    -  'GEL': [2, 'GEL', 'GEL'],
    -  'GHS': [2, 'GHS', 'GHS'],
    -  'GIP': [2, '£', 'GI£'],
    -  'GMD': [2, 'GMD', 'GMD'],
    -  'GNF': [0, 'FG', 'FG'],
    -  'GTQ': [2, 'Q', 'GTQ'],
    -  'GYD': [0, '$', 'GY$'],
    -  'HNL': [2, 'L', 'HNL'],
    -  'HTG': [2, 'HTG', 'HTG'],
    -  'IQD': [0, 'din', 'IQD'],
    -  'JOD': [3, 'din', 'JOD'],
    -  'KES': [2, 'Ksh', 'Ksh'],
    -  'KGS': [2, 'KGS', 'KGS'],
    -  'KHR': [2, 'Riel', 'KHR'],
    -  'KMF': [0, 'CF', 'KMF'],
    -  'KPW': [0, '\u20A9KP', 'KPW'],
    -  'KWD': [3, 'din', 'KWD'],
    -  'KYD': [2, '$', 'KY$'],
    -  'KZT': [2, '\u20B8', 'KZT'],
    -  'LAK': [0, '\u20AD', '\u20AD'],
    -  'LBP': [0, 'L£', 'LBP'],
    -  'LRD': [2, '$', 'L$'],
    -  'LSL': [2, 'LSL', 'LSL'],
    -  'LYD': [3, 'din', 'LD'],
    -  'MAD': [2, 'dh', 'MAD'],
    -  'MDL': [2, 'MDL', 'MDL'],
    -  'MGA': [0, 'Ar', 'MGA'],
    -  'MKD': [2, 'din', 'MKD'],
    -  'MMK': [0, 'K', 'MMK'],
    -  'MOP': [2, 'MOP', 'MOP$'],
    -  'MRO': [0, 'MRO', 'MRO'],
    -  'MUR': [0, 'MURs', 'MURs'],
    -  'MWK': [2, 'MWK', 'MWK'],
    -  'MZN': [2, 'MTn', 'MTn'],
    -  'NAD': [2, '$', 'N$'],
    -  'NGN': [2, '\u20A6', 'NG\u20A6'],
    -  'NIO': [2, 'C$', 'C$'],
    -  'NPR': [2, 'Rs', 'NPRs'],
    -  'NZD': [2, '$', 'NZ$'],
    -  'OMR': [3, 'Rial', 'OMR'],
    -  'PGK': [2, 'PGK', 'PGK'],
    -  'PYG': [0, 'Gs', 'PYG'],
    -  'QAR': [2, 'Rial', 'QR'],
    -  'RWF': [0, 'RF', 'RF'],
    -  'SBD': [2, '$', 'SI$'],
    -  'SCR': [2, 'SCR', 'SCR'],
    -  'SDG': [2, 'SDG', 'SDG'],
    -  'SHP': [2, '£', 'SH£'],
    -  'SLL': [0, 'SLL', 'SLL'],
    -  'SOS': [0, 'SOS', 'SOS'],
    -  'SRD': [2, '$', 'SR$'],
    -  'SSP': [2, '£', 'SSP'],
    -  'STD': [0, 'Db', 'Db'],
    -  'SYP': [0, '£', 'SY£'],
    -  'SZL': [2, 'SZL', 'SZL'],
    -  'TJS': [2, 'Som', 'TJS'],
    -  'TND': [3, 'din', 'DT'],
    -  'TOP': [2, 'T$', 'T$'],
    -  'TTD': [2, '$', 'TT$'],
    -  'UGX': [0, 'UGX', 'UGX'],
    -  'UZS': [0, 'so\u02bcm', 'UZS'],
    -  'VEF': [2, 'Bs', 'Bs'],
    -  'VUV': [0, 'VUV', 'VUV'],
    -  'WST': [2, 'WST', 'WST'],
    -  'XAF': [0, 'FCFA', 'FCFA'],
    -  'XCD': [2, '$', 'EC$'],
    -  'XOF': [0, 'CFA', 'CFA'],
    -  'XPF': [0, 'FCFP', 'FCFP'],
    -  'ZMW': [0, 'ZMW', 'ZMW'],
    -  'ZWD': [0, '$', 'Z$']
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/currency_test.html b/src/database/third_party/closure-library/closure/goog/i18n/currency_test.html
    deleted file mode 100644
    index d6f1b1d4a2e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/currency_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<html>
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.i18n.currency
    -  </title>
    -  <meta charset="utf-8" />
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.i18n.currencyTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/currency_test.js b/src/database/third_party/closure-library/closure/goog/i18n/currency_test.js
    deleted file mode 100644
    index 6d61642b3c0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/currency_test.js
    +++ /dev/null
    @@ -1,267 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -goog.provide('goog.i18n.currencyTest');
    -goog.setTestOnly('goog.i18n.currencyTest');
    -
    -goog.require('goog.i18n.NumberFormat');
    -goog.require('goog.i18n.currency');
    -goog.require('goog.i18n.currency.CurrencyInfo');
    -goog.require('goog.object');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -
    -var stubs = new goog.testing.PropertyReplacer();
    -
    -function setUp() {
    -  stubs.replace(goog.i18n.currency, 'CurrencyInfo',
    -      goog.object.clone(goog.i18n.currency.CurrencyInfo));
    -}
    -
    -function tearDown() {
    -  stubs.reset();
    -}
    -
    -function testAddTier2Support() {
    -  assertFalse('LRD' in goog.i18n.currency.CurrencyInfo);
    -  assertThrows(function() {
    -    goog.i18n.currency.getLocalCurrencyPattern('LRD');
    -  });
    -
    -  goog.i18n.currency.addTier2Support();
    -  assertTrue('LRD' in goog.i18n.currency.CurrencyInfo);
    -  assertEquals("'$'#,##0.00",
    -      goog.i18n.currency.getLocalCurrencyPattern('LRD'));
    -}
    -
    -function testCurrencyPattern() {
    -  assertEquals("'$'#,##0.00",
    -      goog.i18n.currency.getLocalCurrencyPattern('USD'));
    -  assertEquals("'US$'#,##0.00",
    -      goog.i18n.currency.getPortableCurrencyPattern('USD'));
    -  assertEquals("USD '$'#,##0.00",
    -      goog.i18n.currency.getGlobalCurrencyPattern('USD'));
    -
    -  assertEquals("'¥'#,##0",
    -      goog.i18n.currency.getLocalCurrencyPattern('JPY'));
    -  assertEquals("'JP¥'#,##0",
    -      goog.i18n.currency.getPortableCurrencyPattern('JPY'));
    -  assertEquals("JPY '¥'#,##0",
    -      goog.i18n.currency.getGlobalCurrencyPattern('JPY'));
    -
    -  assertEquals("'€'#,##0.00",
    -      goog.i18n.currency.getLocalCurrencyPattern('EUR'));
    -  assertEquals("'€'#,##0.00",
    -      goog.i18n.currency.getPortableCurrencyPattern('EUR'));
    -  assertEquals("EUR '€'#,##0.00",
    -      goog.i18n.currency.getGlobalCurrencyPattern('EUR'));
    -
    -  assertEquals("'¥'#,##0.00",
    -      goog.i18n.currency.getLocalCurrencyPattern('CNY'));
    -  assertEquals("'RMB¥'#,##0.00",
    -      goog.i18n.currency.getPortableCurrencyPattern('CNY'));
    -  assertEquals("CNY '¥'#,##0.00",
    -      goog.i18n.currency.getGlobalCurrencyPattern('CNY'));
    -
    -  assertEquals("'Rial'#,##0",
    -      goog.i18n.currency.getLocalCurrencyPattern('YER'));
    -  assertEquals("'Rial'#,##0",
    -      goog.i18n.currency.getPortableCurrencyPattern('YER'));
    -  assertEquals("YER 'Rial'#,##0",
    -      goog.i18n.currency.getGlobalCurrencyPattern('YER'));
    -
    -  assertEquals("'CHF'#,##0.00",
    -      goog.i18n.currency.getLocalCurrencyPattern('CHF'));
    -  assertEquals("'CHF'#,##0.00",
    -      goog.i18n.currency.getPortableCurrencyPattern('CHF'));
    -  assertEquals("'CHF'#,##0.00",
    -      goog.i18n.currency.getGlobalCurrencyPattern('CHF'));
    -}
    -
    -function testCurrencyFormatCHF() {
    -  var formatter;
    -  var str;
    -
    -  formatter = new goog.i18n.NumberFormat(
    -      goog.i18n.currency.getLocalCurrencyPattern('CHF'));
    -  str = formatter.format(123456.7899);
    -  assertEquals('CHF123,456.79', str);
    -
    -  formatter = new goog.i18n.NumberFormat(
    -      goog.i18n.currency.getPortableCurrencyPattern('CHF'));
    -  str = formatter.format(123456.7899);
    -  assertEquals('CHF123,456.79', str);
    -
    -  formatter = new goog.i18n.NumberFormat(
    -      goog.i18n.currency.getGlobalCurrencyPattern('CHF'));
    -  str = formatter.format(123456.7899);
    -  assertEquals('CHF123,456.79', str);
    -}
    -
    -function testCurrencyFormatYER() {
    -  var formatter;
    -  var str;
    -
    -  formatter = new goog.i18n.NumberFormat(
    -      goog.i18n.currency.getLocalCurrencyPattern('YER'));
    -  str = formatter.format(123456.7899);
    -  assertEquals('Rial123,457', str);
    -
    -  formatter = new goog.i18n.NumberFormat(
    -      goog.i18n.currency.getPortableCurrencyPattern('YER'));
    -  str = formatter.format(123456.7899);
    -  assertEquals('Rial123,457', str);
    -
    -  formatter = new goog.i18n.NumberFormat(
    -      goog.i18n.currency.getGlobalCurrencyPattern('YER'));
    -  str = formatter.format(123456.7899);
    -  assertEquals('YER Rial123,457', str);
    -}
    -
    -function testCurrencyFormatCNY() {
    -  var formatter;
    -  var str;
    -
    -  formatter = new goog.i18n.NumberFormat(
    -      goog.i18n.currency.getLocalCurrencyPattern('CNY'));
    -  str = formatter.format(123456.7899);
    -  assertEquals('¥123,456.79', str);
    -
    -  formatter = new goog.i18n.NumberFormat(
    -      goog.i18n.currency.getPortableCurrencyPattern('CNY'));
    -  str = formatter.format(123456.7899);
    -  assertEquals('RMB¥123,456.79', str);
    -
    -  formatter = new goog.i18n.NumberFormat(
    -      goog.i18n.currency.getGlobalCurrencyPattern('CNY'));
    -  str = formatter.format(123456.7899);
    -  assertEquals('CNY ¥123,456.79', str);
    -}
    -
    -function testCurrencyFormatCZK() {
    -  var formatter;
    -  var str;
    -
    -  formatter = new goog.i18n.NumberFormat(
    -      goog.i18n.currency.getLocalCurrencyPattern('CZK'));
    -  str = formatter.format(123456.7899);
    -  assertEquals('123,456.79 Kč', str);
    -
    -  formatter = new goog.i18n.NumberFormat(
    -      goog.i18n.currency.getPortableCurrencyPattern('CZK'));
    -  str = formatter.format(123456.7899);
    -  assertEquals('123,456.79 Kč', str);
    -
    -  formatter = new goog.i18n.NumberFormat(
    -      goog.i18n.currency.getGlobalCurrencyPattern('CZK'));
    -  str = formatter.format(123456.7899);
    -  assertEquals('CZK 123,456.79 Kč', str);
    -}
    -
    -function testCurrencyFormatEUR() {
    -  var formatter;
    -  var str;
    -
    -  formatter = new goog.i18n.NumberFormat(
    -      goog.i18n.currency.getLocalCurrencyPattern('EUR'));
    -  str = formatter.format(123456.7899);
    -  assertEquals('€123,456.79', str);
    -
    -  formatter = new goog.i18n.NumberFormat(
    -      goog.i18n.currency.getPortableCurrencyPattern('EUR'));
    -  str = formatter.format(123456.7899);
    -  assertEquals('€123,456.79', str);
    -
    -  formatter = new goog.i18n.NumberFormat(
    -      goog.i18n.currency.getGlobalCurrencyPattern('EUR'));
    -  str = formatter.format(123456.7899);
    -  assertEquals('EUR €123,456.79', str);
    -}
    -
    -function testCurrencyFormatJPY() {
    -  var formatter;
    -  var str;
    -
    -  formatter = new goog.i18n.NumberFormat(
    -      goog.i18n.currency.getLocalCurrencyPattern('JPY'));
    -  str = formatter.format(123456.7899);
    -  assertEquals('¥123,457', str);
    -
    -  formatter = new goog.i18n.NumberFormat(
    -      goog.i18n.currency.getPortableCurrencyPattern('JPY'));
    -  str = formatter.format(123456.7899);
    -  assertEquals('JP¥123,457', str);
    -
    -  formatter = new goog.i18n.NumberFormat(
    -      goog.i18n.currency.getGlobalCurrencyPattern('JPY'));
    -  str = formatter.format(123456.7899);
    -  assertEquals('JPY ¥123,457', str);
    -}
    -
    -function testCurrencyFormatPLN() {
    -  var formatter;
    -  var str;
    -
    -  formatter = new goog.i18n.NumberFormat(
    -      goog.i18n.currency.getLocalCurrencyPattern('PLN'));
    -  str = formatter.format(123456.7899);
    -  assertEquals('123,456.79 zł', str);
    -
    -  formatter = new goog.i18n.NumberFormat(
    -      goog.i18n.currency.getPortableCurrencyPattern('PLN'));
    -  str = formatter.format(123456.7899);
    -  assertEquals('123,456.79 zł', str);
    -
    -  formatter = new goog.i18n.NumberFormat(
    -      goog.i18n.currency.getGlobalCurrencyPattern('PLN'));
    -  str = formatter.format(123456.7899);
    -  assertEquals('PLN 123,456.79 zł', str);
    -}
    -
    -function testCurrencyFormatUSD() {
    -  var formatter;
    -  var str;
    -
    -  formatter = new goog.i18n.NumberFormat(
    -      goog.i18n.currency.getLocalCurrencyPattern('USD'));
    -  str = formatter.format(123456.7899);
    -  assertEquals('$123,456.79', str);
    -
    -  formatter = new goog.i18n.NumberFormat(
    -      goog.i18n.currency.getPortableCurrencyPattern('USD'));
    -  str = formatter.format(123456.7899);
    -  assertEquals('US$123,456.79', str);
    -
    -  formatter = new goog.i18n.NumberFormat(
    -      goog.i18n.currency.getGlobalCurrencyPattern('USD'));
    -  str = formatter.format(123456.7899);
    -  assertEquals('USD $123,456.79', str);
    -}
    -
    -
    -function testIsPrefixSignPosition() {
    -  assertTrue(goog.i18n.currency.isPrefixSignPosition('USD'));
    -  assertTrue(goog.i18n.currency.isPrefixSignPosition('EUR'));
    -}
    -
    -function testGetCurrencySign() {
    -  assertEquals('USD $', goog.i18n.currency.getGlobalCurrencySign('USD'));
    -  assertEquals('$', goog.i18n.currency.getLocalCurrencySign('USD'));
    -  assertEquals('US$', goog.i18n.currency.getPortableCurrencySign('USD'));
    -
    -  assertEquals('YER Rial', goog.i18n.currency.getGlobalCurrencySign('YER'));
    -  assertEquals('Rial', goog.i18n.currency.getLocalCurrencySign('YER'));
    -  assertEquals('Rial', goog.i18n.currency.getPortableCurrencySign('YER'));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/currencycodemap.js b/src/database/third_party/closure-library/closure/goog/i18n/currencycodemap.js
    deleted file mode 100644
    index 2996f753f90..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/currencycodemap.js
    +++ /dev/null
    @@ -1,207 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Currency code map.
    - */
    -
    -
    -/**
    - * Namespace for locale number format functions
    - */
    -goog.provide('goog.i18n.currencyCodeMap');
    -goog.provide('goog.i18n.currencyCodeMapTier2');
    -
    -
    -/**
    - * The mapping of currency symbol through intl currency code.
    - * The source of information is mostly from wikipedia and CLDR. Since there is
    - * no authoritive source, items are judged by personal perception.
    -
    - * If an application need currency support that available in tier2, it
    - * should extend currencyCodeMap to include tier2 data by doing this:
    - *     goog.object.extend(goog.i18n.currencyCodeMap,
    - *                        goog.i18n.currencyCodeMapTier2);
    - *
    - * @const {!Object<string, string>}
    - */
    -goog.i18n.currencyCodeMap = {
    -  'AED': '\u062F\u002e\u0625',
    -  'ARS': '$',
    -  'AUD': '$',
    -  'BDT': '\u09F3',
    -  'BRL': 'R$',
    -  'CAD': '$',
    -  'CHF': 'Fr.',
    -  'CLP': '$',
    -  'CNY': '\u00a5',
    -  'COP': '$',
    -  'CRC': '\u20a1',
    -  'CUP': '$',
    -  'CZK': 'K\u010d',
    -  'DKK': 'kr',
    -  'DOP': '$',
    -  'EGP': '\u00a3',
    -  'EUR': '\u20ac',
    -  'GBP': '\u00a3',
    -  'HKD': '$',
    -  'HRK': 'kn',
    -  'HUF': 'Ft',
    -  'IDR': 'Rp',
    -  'ILS': '\u20AA',
    -  'INR': 'Rs',
    -  'IQD': '\u0639\u062F',
    -  'ISK': 'kr',
    -  'JMD': '$',
    -  'JPY': '\u00a5',
    -  'KRW': '\u20A9',
    -  'KWD': '\u062F\u002e\u0643',
    -  'LKR': 'Rs',
    -  'LVL': 'Ls',
    -  'MNT': '\u20AE',
    -  'MXN': '$',
    -  'MYR': 'RM',
    -  'NOK': 'kr',
    -  'NZD': '$',
    -  'PAB': 'B/.',
    -  'PEN': 'S/.',
    -  'PHP': 'P',
    -  'PKR': 'Rs.',
    -  'PLN': 'z\u0142',
    -  'RON': 'L',
    -  'RUB': '\u0440\u0443\u0431',
    -  'SAR': '\u0633\u002E\u0631',
    -  'SEK': 'kr',
    -  'SGD': '$',
    -  'SYP': 'SYP',
    -  'THB': '\u0e3f',
    -  'TRY': 'TL',
    -  'TWD': 'NT$',
    -  'USD': '$',
    -  'UYU': '$',
    -  'VEF': 'Bs.F',
    -  'VND': '\u20AB',
    -  'XAF': 'FCFA',
    -  'XCD': '$',
    -  'YER': 'YER',
    -  'ZAR': 'R'
    -};
    -
    -
    -/**
    - * This group of currency data is unlikely to be used. In case they are,
    - * program need to merge it into goog.locale.CurrencyCodeMap.
    - *
    - * @const {!Object<string, string>}
    - */
    -goog.i18n.currencyCodeMapTier2 = {
    -  'AFN': '\u060b',
    -  'ALL': 'Lek',
    -  'AMD': '\u0564\u0580\u002e',
    -  'ANG': 'ANf.',
    -  'AOA': 'Kz',
    -  'AWG': '\u0192',
    -  'AZN': 'm',
    -  'BAM': '\u041a\u041c',
    -  'BBD': '$',
    -  'BGN': '\u043b\u0432',
    -  'BHD': '\u0628\u002e\u062f\u002e',
    -  'BIF': 'FBu',
    -  'BMD': '$',
    -  'BND': '$',
    -  'BOB': 'B$',
    -  'BSD': '$',
    -  'BTN': 'Nu.',
    -  'BWP': 'P',
    -  'BYR': 'Br',
    -  'BZD': '$',
    -  'CDF': 'F',
    -  'CUC': 'CUC$',
    -  'CVE': '$',
    -  'DJF': 'Fdj',
    -  'DZD': '\u062f\u062C',
    -  'ERN': 'Nfk',
    -  'ETB': 'Br',
    -  'FJD': '$',
    -  'FKP': '\u00a3',
    -  'GEL': 'GEL',
    -  'GHS': '\u20B5',
    -  'GIP': '\u00a3',
    -  'GMD': 'D',
    -  'GNF': 'FG',
    -  'GTQ': 'Q',
    -  'GYD': '$',
    -  'HNL': 'L',
    -  'HTG': 'G',
    -  'IRR': '\ufdfc',
    -  'JOD': 'JOD',
    -  'KES': 'KSh',
    -  'KGS': 'som',
    -  'KHR': '\u17DB',
    -  'KMF': 'KMF',
    -  'KPW': '\u20A9',
    -  'KYD': '$',
    -  'KZT': 'KZT',
    -  'LAK': '\u20AD',
    -  'LBP': '\u0644\u002e\u0644',
    -  'LRD': '$',
    -  'LSL': 'L',
    -  'LTL': 'Lt',
    -  'LYD': '\u0644\u002e\u062F',
    -  'MAD': '\u0645\u002E\u062F\u002E',
    -  'MDL': 'MDL',
    -  'MGA': 'MGA',
    -  'MKD': 'MKD',
    -  'MMK': 'K',
    -  'MOP': 'MOP$',
    -  'MRO': 'UM',
    -  'MUR': 'Rs',
    -  'MVR': 'Rf',
    -  'MWK': 'MK',
    -  'MZN': 'MTn',
    -  'NAD': '$',
    -  'NGN': '\u20A6',
    -  'NIO': 'C$',
    -  'NPR': 'Rs',
    -  'OMR': '\u0639\u002E\u062F\u002E',
    -  'PGK': 'K',
    -  'PYG': '\u20b2',
    -  'QAR': '\u0642\u002E\u0631',
    -  'RSD': '\u0420\u0421\u0414',
    -  'RWF': 'RF',
    -  'SBD': '$',
    -  'SCR': 'SR',
    -  'SDG': 'SDG',
    -  'SHP': '\u00a3',
    -  'SLL': 'Le',
    -  'SOS': 'So. Sh.',
    -  'SRD': '$',
    -  'SSP': '£',
    -  'STD': 'Db',
    -  'SZL': 'L',
    -  'TJS': 'TJS',
    -  'TND': '\u062F\u002e\u062A ',
    -  'TOP': 'T$',
    -  'TTD': '$',
    -  'TZS': 'TZS',
    -  'UAH': 'UAH',
    -  'UGX': 'USh',
    -  'UZS': 'UZS',
    -  'VUV': 'Vt',
    -  'WST': 'WS$',
    -  'XOF': 'CFA',
    -  'XPF': 'F',
    -  'ZMW': 'ZMW',
    -  'ZWD': '$'
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/datetimeformat.js b/src/database/third_party/closure-library/closure/goog/i18n/datetimeformat.js
    deleted file mode 100644
    index 078c804eb36..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/datetimeformat.js
    +++ /dev/null
    @@ -1,758 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Functions for dealing with date/time formatting.
    - */
    -
    -
    -/**
    - * Namespace for i18n date/time formatting functions
    - */
    -goog.provide('goog.i18n.DateTimeFormat');
    -goog.provide('goog.i18n.DateTimeFormat.Format');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.date');
    -goog.require('goog.i18n.DateTimeSymbols');
    -goog.require('goog.i18n.TimeZone');
    -goog.require('goog.string');
    -
    -
    -/**
    - * Datetime formatting functions following the pattern specification as defined
    - * in JDK, ICU and CLDR, with minor modification for typical usage in JS.
    - * Pattern specification: (Refer to JDK/ICU/CLDR)
    - * <pre>
    - * Symbol Meaning Presentation        Example
    - * ------   -------                 ------------        -------
    - * G        era designator          (Text)              AD
    - * y#       year                    (Number)            1996
    - * Y*       year (week of year)     (Number)            1997
    - * u*       extended year           (Number)            4601
    - * M        month in year           (Text & Number)     July & 07
    - * d        day in month            (Number)            10
    - * h        hour in am/pm (1~12)    (Number)            12
    - * H        hour in day (0~23)      (Number)            0
    - * m        minute in hour          (Number)            30
    - * s        second in minute        (Number)            55
    - * S        fractional second       (Number)            978
    - * E        day of week             (Text)              Tuesday
    - * e*       day of week (local 1~7) (Number)            2
    - * D*       day in year             (Number)            189
    - * F*       day of week in month    (Number)            2 (2nd Wed in July)
    - * w        week in year            (Number)            27
    - * W*       week in month           (Number)            2
    - * a        am/pm marker            (Text)              PM
    - * k        hour in day (1~24)      (Number)            24
    - * K        hour in am/pm (0~11)    (Number)            0
    - * z        time zone               (Text)              Pacific Standard Time
    - * Z        time zone (RFC 822)     (Number)            -0800
    - * v        time zone (generic)     (Text)              Pacific Time
    - * g*       Julian day              (Number)            2451334
    - * A*       milliseconds in day     (Number)            69540000
    - * '        escape for text         (Delimiter)         'Date='
    - * ''       single quote            (Literal)           'o''clock'
    - *
    - * Item marked with '*' are not supported yet.
    - * Item marked with '#' works different than java
    - *
    - * The count of pattern letters determine the format.
    - * (Text): 4 or more, use full form, <4, use short or abbreviated form if it
    - * exists. (e.g., "EEEE" produces "Monday", "EEE" produces "Mon")
    - *
    - * (Number): the minimum number of digits. Shorter numbers are zero-padded to
    - * this amount (e.g. if "m" produces "6", "mm" produces "06"). Year is handled
    - * specially; that is, if the count of 'y' is 2, the Year will be truncated to
    - * 2 digits. (e.g., if "yyyy" produces "1997", "yy" produces "97".) Unlike other
    - * fields, fractional seconds are padded on the right with zero.
    - *
    - * (Text & Number): 3 or over, use text, otherwise use number. (e.g., "M"
    - * produces "1", "MM" produces "01", "MMM" produces "Jan", and "MMMM" produces
    - * "January".)
    - *
    - * Any characters in the pattern that are not in the ranges of ['a'..'z'] and
    - * ['A'..'Z'] will be treated as quoted text. For instance, characters like ':',
    - * '.', ' ', '#' and '@' will appear in the resulting time text even they are
    - * not embraced within single quotes.
    - * </pre>
    - */
    -
    -
    -
    -/**
    - * Construct a DateTimeFormat object based on current locale.
    - * @constructor
    - * @param {string|number} pattern pattern specification or pattern type.
    - * @param {!Object=} opt_dateTimeSymbols Optional symbols to use use for this
    - *     instance rather than the global symbols.
    - * @final
    - */
    -goog.i18n.DateTimeFormat = function(pattern, opt_dateTimeSymbols) {
    -  goog.asserts.assert(goog.isDef(pattern), 'Pattern must be defined');
    -  goog.asserts.assert(
    -      goog.isDef(opt_dateTimeSymbols) || goog.isDef(goog.i18n.DateTimeSymbols),
    -      'goog.i18n.DateTimeSymbols or explicit symbols must be defined');
    -
    -  this.patternParts_ = [];
    -
    -  /**
    -   * Data structure that with all the locale info needed for date formatting.
    -   * (day/month names, most common patterns, rules for week-end, etc.)
    -   * @type {!Object}
    -   * @private
    -   */
    -  this.dateTimeSymbols_ = opt_dateTimeSymbols || goog.i18n.DateTimeSymbols;
    -  if (typeof pattern == 'number') {
    -    this.applyStandardPattern_(pattern);
    -  } else {
    -    this.applyPattern_(pattern);
    -  }
    -};
    -
    -
    -/**
    - * Enum to identify predefined Date/Time format pattern.
    - * @enum {number}
    - */
    -goog.i18n.DateTimeFormat.Format = {
    -  FULL_DATE: 0,
    -  LONG_DATE: 1,
    -  MEDIUM_DATE: 2,
    -  SHORT_DATE: 3,
    -  FULL_TIME: 4,
    -  LONG_TIME: 5,
    -  MEDIUM_TIME: 6,
    -  SHORT_TIME: 7,
    -  FULL_DATETIME: 8,
    -  LONG_DATETIME: 9,
    -  MEDIUM_DATETIME: 10,
    -  SHORT_DATETIME: 11
    -};
    -
    -
    -/**
    - * regular expression pattern for parsing pattern string
    - * @type {Array<RegExp>}
    - * @private
    - */
    -goog.i18n.DateTimeFormat.TOKENS_ = [
    -  //quote string
    -  /^\'(?:[^\']|\'\')*\'/,
    -  // pattern chars
    -  /^(?:G+|y+|M+|k+|S+|E+|a+|h+|K+|H+|c+|L+|Q+|d+|m+|s+|v+|w+|z+|Z+)/,
    -  // and all the other chars
    -  /^[^\'GyMkSEahKHcLQdmsvwzZ]+/  // and all the other chars
    -];
    -
    -
    -/**
    - * These are token types, corresponding to above token definitions.
    - * @enum {number}
    - * @private
    - */
    -goog.i18n.DateTimeFormat.PartTypes_ = {
    -  QUOTED_STRING: 0,
    -  FIELD: 1,
    -  LITERAL: 2
    -};
    -
    -
    -/**
    - * Apply specified pattern to this formatter object.
    - * @param {string} pattern String specifying how the date should be formatted.
    - * @private
    - */
    -goog.i18n.DateTimeFormat.prototype.applyPattern_ = function(pattern) {
    -  // lex the pattern, once for all uses
    -  while (pattern) {
    -    for (var i = 0; i < goog.i18n.DateTimeFormat.TOKENS_.length; ++i) {
    -      var m = pattern.match(goog.i18n.DateTimeFormat.TOKENS_[i]);
    -      if (m) {
    -        var part = m[0];
    -        pattern = pattern.substring(part.length);
    -        if (i == goog.i18n.DateTimeFormat.PartTypes_.QUOTED_STRING) {
    -          if (part == "''") {
    -            part = "'";  // '' -> '
    -          } else {
    -            part = part.substring(1, part.length - 1); // strip quotes
    -            part = part.replace(/\'\'/, "'");
    -          }
    -        }
    -        this.patternParts_.push({ text: part, type: i });
    -        break;
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Format the given date object according to preset pattern and current lcoale.
    - * @param {goog.date.DateLike} date The Date object that is being formatted.
    - * @param {goog.i18n.TimeZone=} opt_timeZone optional, if specified, time
    - *    related fields will be formatted based on its setting. When this field
    - *    is not specified, "undefined" will be pass around and those function
    - *    that really need time zone service will create a default one.
    - * @return {string} Formatted string for the given date.
    - *    Throws an error if the date is null or if one tries to format a date-only
    - *    object (for instance goog.date.Date) using a pattern with time fields.
    - */
    -goog.i18n.DateTimeFormat.prototype.format = function(date, opt_timeZone) {
    -  if (!date)
    -    throw Error('The date to format must be non-null.');
    -
    -  // We don't want to write code to calculate each date field because we
    -  // want to maximize performance and minimize code size.
    -  // JavaScript only provide API to render local time.
    -  // Suppose target date is: 16:00 GMT-0400
    -  // OS local time is:       12:00 GMT-0800
    -  // We want to create a Local Date Object : 16:00 GMT-0800, and fix the
    -  // time zone display ourselves.
    -  // Thing get a little bit tricky when daylight time transition happens. For
    -  // example, suppose OS timeZone is America/Los_Angeles, it is impossible to
    -  // represent "2006/4/2 02:30" even for those timeZone that has no transition
    -  // at this time. Because 2:00 to 3:00 on that day does not exising in
    -  // America/Los_Angeles time zone. To avoid calculating date field through
    -  // our own code, we uses 3 Date object instead, one for "Year, month, day",
    -  // one for time within that day, and one for timeZone object since it need
    -  // the real time to figure out actual time zone offset.
    -  var diff = opt_timeZone ?
    -      (date.getTimezoneOffset() - opt_timeZone.getOffset(date)) * 60000 : 0;
    -  var dateForDate = diff ? new Date(date.getTime() + diff) : date;
    -  var dateForTime = dateForDate;
    -  // in daylight time switch on/off hour, diff adjustment could alter time
    -  // because of timeZone offset change, move 1 day forward or backward.
    -  if (opt_timeZone &&
    -      dateForDate.getTimezoneOffset() != date.getTimezoneOffset()) {
    -    diff += diff > 0 ? -goog.date.MS_PER_DAY : goog.date.MS_PER_DAY;
    -    dateForTime = new Date(date.getTime() + diff);
    -  }
    -
    -  var out = [];
    -  for (var i = 0; i < this.patternParts_.length; ++i) {
    -    var text = this.patternParts_[i].text;
    -    if (goog.i18n.DateTimeFormat.PartTypes_.FIELD ==
    -        this.patternParts_[i].type) {
    -      out.push(this.formatField_(text, date, dateForDate, dateForTime,
    -                                 opt_timeZone));
    -    } else {
    -      out.push(text);
    -    }
    -  }
    -  return out.join('');
    -};
    -
    -
    -/**
    - * Apply a predefined pattern as identified by formatType, which is stored in
    - * locale specific repository.
    - * @param {number} formatType A number that identified the predefined pattern.
    - * @private
    - */
    -goog.i18n.DateTimeFormat.prototype.applyStandardPattern_ =
    -    function(formatType) {
    -  var pattern;
    -  if (formatType < 4) {
    -    pattern = this.dateTimeSymbols_.DATEFORMATS[formatType];
    -  } else if (formatType < 8) {
    -    pattern = this.dateTimeSymbols_.TIMEFORMATS[formatType - 4];
    -  } else if (formatType < 12) {
    -    pattern = this.dateTimeSymbols_.DATETIMEFORMATS[formatType - 8];
    -    pattern = pattern.replace('{1}',
    -        this.dateTimeSymbols_.DATEFORMATS[formatType - 8]);
    -    pattern = pattern.replace('{0}',
    -        this.dateTimeSymbols_.TIMEFORMATS[formatType - 8]);
    -  } else {
    -    this.applyStandardPattern_(goog.i18n.DateTimeFormat.Format.MEDIUM_DATETIME);
    -    return;
    -  }
    -  this.applyPattern_(pattern);
    -};
    -
    -
    -/**
    - * Localizes a string potentially containing numbers, replacing ASCII digits
    - * with native digits if specified so by the locale. Leaves other characters.
    - * @param {string} input the string to be localized, using ASCII digits.
    - * @return {string} localized string, potentially using native digits.
    - * @private
    - */
    -goog.i18n.DateTimeFormat.prototype.localizeNumbers_ = function(input) {
    -  return goog.i18n.DateTimeFormat.localizeNumbers(input, this.dateTimeSymbols_);
    -};
    -
    -
    -/**
    - * Localizes a string potentially containing numbers, replacing ASCII digits
    - * with native digits if specified so by the locale. Leaves other characters.
    - * @param {number|string} input the string to be localized, using ASCII digits.
    - * @param {!Object=} opt_dateTimeSymbols Optional symbols to use use rather than
    - *     the global symbols.
    - * @return {string} localized string, potentially using native digits.
    - */
    -goog.i18n.DateTimeFormat.localizeNumbers =
    -    function(input, opt_dateTimeSymbols) {
    -  input = String(input);
    -  var dateTimeSymbols = opt_dateTimeSymbols || goog.i18n.DateTimeSymbols;
    -  if (dateTimeSymbols.ZERODIGIT === undefined) {
    -    return input;
    -  }
    -
    -  var parts = [];
    -  for (var i = 0; i < input.length; i++) {
    -    var c = input.charCodeAt(i);
    -    parts.push((0x30 <= c && c <= 0x39) ? // '0' <= c <= '9'
    -        String.fromCharCode(dateTimeSymbols.ZERODIGIT + c - 0x30) :
    -        input.charAt(i));
    -  }
    -  return parts.join('');
    -};
    -
    -
    -/**
    - * Formats Era field according to pattern specified.
    - *
    - * @param {number} count Number of time pattern char repeats, it controls
    - *     how a field should be formatted.
    - * @param {!goog.date.DateLike} date It holds the date object to be formatted.
    - * @return {string} Formatted string that represent this field.
    - * @private
    - */
    -goog.i18n.DateTimeFormat.prototype.formatEra_ = function(count, date) {
    -  var value = date.getFullYear() > 0 ? 1 : 0;
    -  return count >= 4 ? this.dateTimeSymbols_.ERANAMES[value] :
    -                      this.dateTimeSymbols_.ERAS[value];
    -};
    -
    -
    -/**
    - * Formats Year field according to pattern specified
    - *   Javascript Date object seems incapable handling 1BC and
    - *   year before. It can show you year 0 which does not exists.
    - *   following we just keep consistent with javascript's
    - *   toString method. But keep in mind those things should be
    - *   unsupported.
    - * @param {number} count Number of time pattern char repeats, it controls
    - *     how a field should be formatted.
    - * @param {!goog.date.DateLike} date It holds the date object to be formatted.
    - * @return {string} Formatted string that represent this field.
    - * @private
    - */
    -goog.i18n.DateTimeFormat.prototype.formatYear_ = function(count, date) {
    -  var value = date.getFullYear();
    -  if (value < 0) {
    -    value = -value;
    -  }
    -  if (count == 2) {
    -    // See comment about special casing 'yy' at the start of the file, this
    -    // matches ICU and CLDR behaviour. See also:
    -    // http://icu-project.org/apiref/icu4j/com/ibm/icu/text/SimpleDateFormat.html
    -    // http://www.unicode.org/reports/tr35/tr35-dates.html
    -    value = value % 100;
    -  }
    -  return this.localizeNumbers_(goog.string.padNumber(value, count));
    -};
    -
    -
    -/**
    - * Formats Month field according to pattern specified
    - *
    - * @param {number} count Number of time pattern char repeats, it controls
    - *     how a field should be formatted.
    - * @param {!goog.date.DateLike} date It holds the date object to be formatted.
    - * @return {string} Formatted string that represent this field.
    - * @private
    - */
    -goog.i18n.DateTimeFormat.prototype.formatMonth_ = function(count, date) {
    -  var value = date.getMonth();
    -  switch (count) {
    -    case 5: return this.dateTimeSymbols_.NARROWMONTHS[value];
    -    case 4: return this.dateTimeSymbols_.MONTHS[value];
    -    case 3: return this.dateTimeSymbols_.SHORTMONTHS[value];
    -    default:
    -      return this.localizeNumbers_(goog.string.padNumber(value + 1, count));
    -  }
    -};
    -
    -
    -/**
    - * Validates is the goog.date.DateLike object to format has a time.
    - * DateLike means Date|goog.date.Date, and goog.date.DateTime inherits
    - * from goog.date.Date. But goog.date.Date does not have time related
    - * members (getHours, getMinutes, getSeconds).
    - * Formatting can be done, if there are no time placeholders in the pattern.
    - *
    - * @param {!goog.date.DateLike} date the object to validate.
    - * @private
    - */
    -goog.i18n.DateTimeFormat.validateDateHasTime_ = function(date) {
    -  if (date.getHours && date.getSeconds && date.getMinutes)
    -    return;
    -  // if (date instanceof Date || date instanceof goog.date.DateTime)
    -  throw Error('The date to format has no time (probably a goog.date.Date). ' +
    -      'Use Date or goog.date.DateTime, or use a pattern without time fields.');
    -};
    -
    -
    -/**
    - * Formats (1..24) Hours field according to pattern specified
    - *
    - * @param {number} count Number of time pattern char repeats. This controls
    - *     how a field should be formatted.
    - * @param {!goog.date.DateLike} date It holds the date object to be formatted.
    - * @return {string} Formatted string that represent this field.
    - * @private
    - */
    -goog.i18n.DateTimeFormat.prototype.format24Hours_ =
    -    function(count, date) {
    -  goog.i18n.DateTimeFormat.validateDateHasTime_(date);
    -  return this.localizeNumbers_(
    -      goog.string.padNumber(date.getHours() || 24, count));
    -};
    -
    -
    -/**
    - * Formats Fractional seconds field according to pattern
    - * specified
    - *
    - * @param {number} count Number of time pattern char repeats, it controls
    - *     how a field should be formatted.
    - * @param {!goog.date.DateLike} date It holds the date object to be formatted.
    - *
    - * @return {string} Formatted string that represent this field.
    - * @private
    - */
    -goog.i18n.DateTimeFormat.prototype.formatFractionalSeconds_ =
    -    function(count, date) {
    -  // Fractional seconds left-justify, append 0 for precision beyond 3
    -  var value = date.getTime() % 1000 / 1000;
    -  return this.localizeNumbers_(
    -      value.toFixed(Math.min(3, count)).substr(2) +
    -      (count > 3 ? goog.string.padNumber(0, count - 3) : ''));
    -};
    -
    -
    -/**
    - * Formats Day of week field according to pattern specified
    - *
    - * @param {number} count Number of time pattern char repeats, it controls
    - *     how a field should be formatted.
    - * @param {!goog.date.DateLike} date It holds the date object to be formatted.
    - * @return {string} Formatted string that represent this field.
    - * @private
    - */
    -goog.i18n.DateTimeFormat.prototype.formatDayOfWeek_ =
    -    function(count, date) {
    -  var value = date.getDay();
    -  return count >= 4 ? this.dateTimeSymbols_.WEEKDAYS[value] :
    -                      this.dateTimeSymbols_.SHORTWEEKDAYS[value];
    -};
    -
    -
    -/**
    - * Formats Am/Pm field according to pattern specified
    - *
    - * @param {number} count Number of time pattern char repeats, it controls
    - *     how a field should be formatted.
    - * @param {!goog.date.DateLike} date It holds the date object to be formatted.
    - * @return {string} Formatted string that represent this field.
    - * @private
    - */
    -goog.i18n.DateTimeFormat.prototype.formatAmPm_ = function(count, date) {
    -  goog.i18n.DateTimeFormat.validateDateHasTime_(date);
    -  var hours = date.getHours();
    -  return this.dateTimeSymbols_.AMPMS[hours >= 12 && hours < 24 ? 1 : 0];
    -};
    -
    -
    -/**
    - * Formats (1..12) Hours field according to pattern specified
    - *
    - * @param {number} count Number of time pattern char repeats, it controls
    - *     how a field should be formatted.
    - * @param {!goog.date.DateLike} date It holds the date object to be formatted.
    - * @return {string} formatted string that represent this field.
    - * @private
    - */
    -goog.i18n.DateTimeFormat.prototype.format1To12Hours_ =
    -    function(count, date) {
    -  goog.i18n.DateTimeFormat.validateDateHasTime_(date);
    -  return this.localizeNumbers_(
    -      goog.string.padNumber(date.getHours() % 12 || 12, count));
    -};
    -
    -
    -/**
    - * Formats (0..11) Hours field according to pattern specified
    - *
    - * @param {number} count Number of time pattern char repeats, it controls
    - *     how a field should be formatted.
    - * @param {!goog.date.DateLike} date It holds the date object to be formatted.
    - * @return {string} formatted string that represent this field.
    - * @private
    - */
    -goog.i18n.DateTimeFormat.prototype.format0To11Hours_ =
    -    function(count, date) {
    -  goog.i18n.DateTimeFormat.validateDateHasTime_(date);
    -  return this.localizeNumbers_(
    -      goog.string.padNumber(date.getHours() % 12, count));
    -};
    -
    -
    -/**
    - * Formats (0..23) Hours field according to pattern specified
    - *
    - * @param {number} count Number of time pattern char repeats, it controls
    - *     how a field should be formatted.
    - * @param {!goog.date.DateLike} date It holds the date object to be formatted.
    - * @return {string} formatted string that represent this field.
    - * @private
    - */
    -goog.i18n.DateTimeFormat.prototype.format0To23Hours_ =
    -    function(count, date) {
    -  goog.i18n.DateTimeFormat.validateDateHasTime_(date);
    -  return this.localizeNumbers_(goog.string.padNumber(date.getHours(), count));
    -};
    -
    -
    -/**
    - * Formats Standalone weekday field according to pattern specified
    - *
    - * @param {number} count Number of time pattern char repeats, it controls
    - *     how a field should be formatted.
    - * @param {!goog.date.DateLike} date It holds the date object to be formatted.
    - * @return {string} formatted string that represent this field.
    - * @private
    - */
    -goog.i18n.DateTimeFormat.prototype.formatStandaloneDay_ =
    -    function(count, date) {
    -  var value = date.getDay();
    -  switch (count) {
    -    case 5:
    -      return this.dateTimeSymbols_.STANDALONENARROWWEEKDAYS[value];
    -    case 4:
    -      return this.dateTimeSymbols_.STANDALONEWEEKDAYS[value];
    -    case 3:
    -      return this.dateTimeSymbols_.STANDALONESHORTWEEKDAYS[value];
    -    default:
    -      return this.localizeNumbers_(goog.string.padNumber(value, 1));
    -  }
    -};
    -
    -
    -/**
    - * Formats Standalone Month field according to pattern specified
    - *
    - * @param {number} count Number of time pattern char repeats, it controls
    - *     how a field should be formatted.
    - * @param {!goog.date.DateLike} date It holds the date object to be formatted.
    - * @return {string} formatted string that represent this field.
    - * @private
    - */
    -goog.i18n.DateTimeFormat.prototype.formatStandaloneMonth_ =
    -    function(count, date) {
    -  var value = date.getMonth();
    -  switch (count) {
    -    case 5:
    -      return this.dateTimeSymbols_.STANDALONENARROWMONTHS[value];
    -    case 4:
    -      return this.dateTimeSymbols_.STANDALONEMONTHS[value];
    -    case 3:
    -      return this.dateTimeSymbols_.STANDALONESHORTMONTHS[value];
    -    default:
    -      return this.localizeNumbers_(goog.string.padNumber(value + 1, count));
    -  }
    -};
    -
    -
    -/**
    - * Formats Quarter field according to pattern specified
    - *
    - * @param {number} count Number of time pattern char repeats, it controls
    - *     how a field should be formatted.
    - * @param {!goog.date.DateLike} date It holds the date object to be formatted.
    - * @return {string} Formatted string that represent this field.
    - * @private
    - */
    -goog.i18n.DateTimeFormat.prototype.formatQuarter_ =
    -    function(count, date) {
    -  var value = Math.floor(date.getMonth() / 3);
    -  return count < 4 ? this.dateTimeSymbols_.SHORTQUARTERS[value] :
    -                     this.dateTimeSymbols_.QUARTERS[value];
    -};
    -
    -
    -/**
    - * Formats Date field according to pattern specified
    - *
    - * @param {number} count Number of time pattern char repeats, it controls
    - *     how a field should be formatted.
    - * @param {!goog.date.DateLike} date It holds the date object to be formatted.
    - * @return {string} Formatted string that represent this field.
    - * @private
    - */
    -goog.i18n.DateTimeFormat.prototype.formatDate_ = function(count, date) {
    -  return this.localizeNumbers_(goog.string.padNumber(date.getDate(), count));
    -};
    -
    -
    -/**
    - * Formats Minutes field according to pattern specified
    - *
    - * @param {number} count Number of time pattern char repeats, it controls
    - *     how a field should be formatted.
    - * @param {!goog.date.DateLike} date It holds the date object to be formatted.
    - * @return {string} Formatted string that represent this field.
    - * @private
    - */
    -goog.i18n.DateTimeFormat.prototype.formatMinutes_ =
    -    function(count, date) {
    -  goog.i18n.DateTimeFormat.validateDateHasTime_(date);
    -  return this.localizeNumbers_(goog.string.padNumber(date.getMinutes(), count));
    -};
    -
    -
    -/**
    - * Formats Seconds field according to pattern specified
    - *
    - * @param {number} count Number of time pattern char repeats, it controls
    - *     how a field should be formatted.
    - * @param {!goog.date.DateLike} date It holds the date object to be formatted.
    - * @return {string} Formatted string that represent this field.
    - * @private
    - */
    -goog.i18n.DateTimeFormat.prototype.formatSeconds_ =
    -    function(count, date) {
    -  goog.i18n.DateTimeFormat.validateDateHasTime_(date);
    -  return this.localizeNumbers_(goog.string.padNumber(date.getSeconds(), count));
    -};
    -
    -
    -/**
    - * Formats the week of year field according to pattern specified
    - *
    - * @param {number} count Number of time pattern char repeats, it controls
    - *     how a field should be formatted.
    - * @param {!goog.date.DateLike} date It holds the date object to be formatted.
    - * @return {string} Formatted string that represent this field.
    - * @private
    - */
    -goog.i18n.DateTimeFormat.prototype.formatWeekOfYear_ = function(count, date) {
    -
    -
    -  var weekNum = goog.date.getWeekNumber(
    -      date.getFullYear(), date.getMonth(), date.getDate(),
    -      this.dateTimeSymbols_.FIRSTWEEKCUTOFFDAY,
    -      this.dateTimeSymbols_.FIRSTDAYOFWEEK);
    -
    -  return this.localizeNumbers_(goog.string.padNumber(weekNum, count));
    -};
    -
    -
    -/**
    - * Formats TimeZone field following RFC
    - *
    - * @param {number} count Number of time pattern char repeats, it controls
    - *     how a field should be formatted.
    - * @param {!goog.date.DateLike} date It holds the date object to be formatted.
    - * @param {goog.i18n.TimeZone=} opt_timeZone This holds current time zone info.
    - * @return {string} Formatted string that represent this field.
    - * @private
    - */
    -goog.i18n.DateTimeFormat.prototype.formatTimeZoneRFC_ =
    -    function(count, date, opt_timeZone) {
    -  opt_timeZone = opt_timeZone ||
    -      goog.i18n.TimeZone.createTimeZone(date.getTimezoneOffset());
    -
    -  // RFC 822 formats should be kept in ASCII, but localized GMT formats may need
    -  // to use native digits.
    -  return count < 4 ? opt_timeZone.getRFCTimeZoneString(date) :
    -                     this.localizeNumbers_(opt_timeZone.getGMTString(date));
    -};
    -
    -
    -/**
    - * Generate GMT timeZone string for given date
    - * @param {number} count Number of time pattern char repeats, it controls
    - *     how a field should be formatted.
    - * @param {!goog.date.DateLike} date Whose value being evaluated.
    - * @param {goog.i18n.TimeZone=} opt_timeZone This holds current time zone info.
    - * @return {string} GMT timeZone string.
    - * @private
    - */
    -goog.i18n.DateTimeFormat.prototype.formatTimeZone_ =
    -    function(count, date, opt_timeZone) {
    -  opt_timeZone = opt_timeZone ||
    -      goog.i18n.TimeZone.createTimeZone(date.getTimezoneOffset());
    -  return count < 4 ? opt_timeZone.getShortName(date) :
    -             opt_timeZone.getLongName(date);
    -};
    -
    -
    -/**
    - * Generate GMT timeZone string for given date
    - * @param {!goog.date.DateLike} date Whose value being evaluated.
    - * @param {goog.i18n.TimeZone=} opt_timeZone This holds current time zone info.
    - * @return {string} GMT timeZone string.
    - * @private
    - */
    -goog.i18n.DateTimeFormat.prototype.formatTimeZoneId_ =
    -    function(date, opt_timeZone) {
    -  opt_timeZone = opt_timeZone ||
    -      goog.i18n.TimeZone.createTimeZone(date.getTimezoneOffset());
    -  return opt_timeZone.getTimeZoneId();
    -};
    -
    -
    -/**
    - * Formatting one date field.
    - * @param {string} patternStr The pattern string for the field being formatted.
    - * @param {!goog.date.DateLike} date represents the real date to be formatted.
    - * @param {!goog.date.DateLike} dateForDate used to resolve date fields
    - *     for formatting.
    - * @param {!goog.date.DateLike} dateForTime used to resolve time fields
    - *     for formatting.
    - * @param {goog.i18n.TimeZone=} opt_timeZone This holds current time zone info.
    - * @return {string} string representation for the given field.
    - * @private
    - */
    -goog.i18n.DateTimeFormat.prototype.formatField_ =
    -    function(patternStr, date, dateForDate, dateForTime, opt_timeZone) {
    -  var count = patternStr.length;
    -  switch (patternStr.charAt(0)) {
    -    case 'G': return this.formatEra_(count, dateForDate);
    -    case 'y': return this.formatYear_(count, dateForDate);
    -    case 'M': return this.formatMonth_(count, dateForDate);
    -    case 'k': return this.format24Hours_(count, dateForTime);
    -    case 'S': return this.formatFractionalSeconds_(count, dateForTime);
    -    case 'E': return this.formatDayOfWeek_(count, dateForDate);
    -    case 'a': return this.formatAmPm_(count, dateForTime);
    -    case 'h': return this.format1To12Hours_(count, dateForTime);
    -    case 'K': return this.format0To11Hours_(count, dateForTime);
    -    case 'H': return this.format0To23Hours_(count, dateForTime);
    -    case 'c': return this.formatStandaloneDay_(count, dateForDate);
    -    case 'L': return this.formatStandaloneMonth_(count, dateForDate);
    -    case 'Q': return this.formatQuarter_(count, dateForDate);
    -    case 'd': return this.formatDate_(count, dateForDate);
    -    case 'm': return this.formatMinutes_(count, dateForTime);
    -    case 's': return this.formatSeconds_(count, dateForTime);
    -    case 'v': return this.formatTimeZoneId_(date, opt_timeZone);
    -    case 'w': return this.formatWeekOfYear_(count, dateForTime);
    -    case 'z': return this.formatTimeZone_(count, date, opt_timeZone);
    -    case 'Z': return this.formatTimeZoneRFC_(count, date, opt_timeZone);
    -    default: return '';
    -  }
    -};
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/datetimeformat_test.html b/src/database/third_party/closure-library/closure/goog/i18n/datetimeformat_test.html
    deleted file mode 100644
    index 1d25722e2a2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/datetimeformat_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.i18n.DateTimeFormat
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.i18n.DateTimeFormatTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/datetimeformat_test.js b/src/database/third_party/closure-library/closure/goog/i18n/datetimeformat_test.js
    deleted file mode 100644
    index 0cb70c642c6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/datetimeformat_test.js
    +++ /dev/null
    @@ -1,768 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.i18n.DateTimeFormatTest');
    -goog.setTestOnly('goog.i18n.DateTimeFormatTest');
    -
    -goog.require('goog.date.Date');
    -goog.require('goog.date.DateTime');
    -goog.require('goog.i18n.DateTimeFormat');
    -goog.require('goog.i18n.DateTimePatterns');
    -goog.require('goog.i18n.DateTimePatterns_de');
    -goog.require('goog.i18n.DateTimePatterns_en');
    -goog.require('goog.i18n.DateTimePatterns_fa');
    -goog.require('goog.i18n.DateTimePatterns_fr');
    -goog.require('goog.i18n.DateTimePatterns_ja');
    -goog.require('goog.i18n.DateTimePatterns_sv');
    -goog.require('goog.i18n.DateTimeSymbols');
    -goog.require('goog.i18n.DateTimeSymbols_ar_AE');
    -goog.require('goog.i18n.DateTimeSymbols_ar_SA');
    -goog.require('goog.i18n.DateTimeSymbols_bn_BD');
    -goog.require('goog.i18n.DateTimeSymbols_de');
    -goog.require('goog.i18n.DateTimeSymbols_en');
    -goog.require('goog.i18n.DateTimeSymbols_en_GB');
    -goog.require('goog.i18n.DateTimeSymbols_en_IE');
    -goog.require('goog.i18n.DateTimeSymbols_en_IN');
    -goog.require('goog.i18n.DateTimeSymbols_en_US');
    -goog.require('goog.i18n.DateTimeSymbols_fa');
    -goog.require('goog.i18n.DateTimeSymbols_fr');
    -goog.require('goog.i18n.DateTimeSymbols_fr_DJ');
    -goog.require('goog.i18n.DateTimeSymbols_he_IL');
    -goog.require('goog.i18n.DateTimeSymbols_ja');
    -goog.require('goog.i18n.DateTimeSymbols_ro_RO');
    -goog.require('goog.i18n.DateTimeSymbols_sv');
    -goog.require('goog.i18n.TimeZone');
    -goog.require('goog.testing.jsunit');
    -
    -// Initial values
    -goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en;
    -goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en;
    -
    -function tearDown() {
    -  // We always revert to a known state
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en;
    -}
    -
    -// Helpers to make tests work regardless of the timeZone we're in.
    -function timezoneString(date) {
    -  var timeZone = goog.i18n.TimeZone.createTimeZone(date.getTimezoneOffset());
    -  return timeZone.getShortName(date);
    -}
    -
    -function timezoneId(date) {
    -  var timeZone = goog.i18n.TimeZone.createTimeZone(
    -      date.getTimezoneOffset());
    -  return timeZone.getTimeZoneId(date);
    -}
    -
    -function timezoneStringRFC(date) {
    -  var timeZone = goog.i18n.TimeZone.createTimeZone(date.getTimezoneOffset());
    -  return timeZone.getRFCTimeZoneString(date);
    -}
    -
    -// Where could such data be found
    -// In js_i18n_data in http://go/i18n_dir, we have a bunch of files with names
    -// like TimeZoneConstant__<locale>.js
    -// We strongly discourage you to use them directly as those data can make
    -// your client code bloated. You should try to provide this data from server
    -// in a selective manner. In typical scenario, user's time zone is retrieved
    -// and only data for that time zone should be provided.
    -var americaLosAngelesData = {
    -  'transitions': [
    -    2770, 60, 7137, 0, 11506, 60, 16041, 0, 20410, 60, 24777, 0, 29146, 60,
    -    33513, 0, 35194, 60, 42249, 0, 45106, 60, 50985, 0, 55354, 60, 59889, 0,
    -    64090, 60, 68625, 0, 72994, 60, 77361, 0, 81730, 60, 86097, 0, 90466, 60,
    -    94833, 0, 99202, 60, 103569, 0, 107938, 60, 112473, 0, 116674, 60, 121209,
    -    0, 125578, 60, 129945, 0, 134314, 60, 138681, 0, 143050, 60, 147417, 0,
    -    151282, 60, 156153, 0, 160018, 60, 165057, 0, 168754, 60, 173793, 0,
    -    177490, 60, 182529, 0, 186394, 60, 191265, 0, 195130, 60, 200001, 0,
    -    203866, 60, 208905, 0, 212602, 60, 217641, 0, 221338, 60, 226377, 0,
    -    230242, 60, 235113, 0, 238978, 60, 243849, 0, 247714, 60, 252585, 0,
    -    256450, 60, 261489, 0, 265186, 60, 270225, 0, 273922, 60, 278961, 0,
    -    282826, 60, 287697, 0, 291562, 60, 296433, 0, 300298, 60, 305337, 0,
    -    309034, 60, 314073, 0, 317770, 60, 322809, 0, 326002, 60, 331713, 0,
    -    334738, 60, 340449, 0, 343474, 60, 349185, 0, 352378, 60, 358089, 0,
    -    361114, 60, 366825, 0, 369850, 60, 375561, 0, 378586, 60, 384297, 0,
    -    387322, 60, 393033, 0, 396058, 60, 401769, 0, 404962, 60, 410673, 0,
    -    413698, 60, 419409, 0, 422434, 60, 428145, 0, 431170, 60, 436881, 0,
    -    439906, 60, 445617, 0, 448810, 60, 454521, 0, 457546, 60, 463257, 0,
    -    466282, 60, 471993, 0, 475018, 60, 480729, 0, 483754, 60, 489465, 0,
    -    492490, 60, 498201, 0, 501394, 60, 507105, 0, 510130, 60, 515841, 0,
    -    518866, 60, 524577, 0, 527602, 60, 533313, 0, 536338, 60, 542049, 0,
    -    545242, 60, 550953, 0, 553978, 60, 559689, 0, 562714, 60, 568425, 0,
    -    571450, 60, 577161, 0, 580186, 60, 585897, 0, 588922, 60, 594633, 0
    -  ],
    -  'names': ['PST', 'Pacific Standard Time', 'PDT', 'Pacific Daylight Time'],
    -  'id': 'America/Los_Angeles',
    -  'std_offset': -480
    -};
    -
    -var europeBerlinData = {
    -  'transitions': [
    -    89953, 60, 94153, 0, 98521, 60, 102889, 0, 107257, 60, 111625, 0,
    -    115993, 60, 120361, 0, 124729, 60, 129265, 0, 133633, 60, 138001, 0,
    -    142369, 60, 146737, 0, 151105, 60, 155473, 0, 159841, 60, 164209, 0,
    -    168577, 60, 172945, 0, 177313, 60, 181849, 0, 186217, 60, 190585, 0,
    -    194953, 60, 199321, 0, 203689, 60, 208057, 0, 212425, 60, 216793, 0,
    -    221161, 60, 225529, 0, 230065, 60, 235105, 0, 238801, 60, 243841, 0,
    -    247537, 60, 252577, 0, 256273, 60, 261481, 0, 265009, 60, 270217, 0,
    -    273745, 60, 278953, 0, 282649, 60, 287689, 0, 291385, 60, 296425, 0,
    -    300121, 60, 305329, 0, 308857, 60, 314065, 0, 317593, 60, 322801, 0,
    -    326329, 60, 331537, 0, 335233, 60, 340273, 0, 343969, 60, 349009, 0,
    -    352705, 60, 357913, 0, 361441, 60, 366649, 0, 370177, 60, 375385, 0,
    -    379081, 60, 384121, 0, 387817, 60, 392857, 0, 396553, 60, 401593, 0,
    -    405289, 60, 410497, 0, 414025, 60, 419233, 0, 422761, 60, 427969, 0,
    -    431665, 60, 436705, 0, 440401, 60, 445441, 0, 449137, 60, 454345, 0,
    -    457873, 60, 463081, 0, 466609, 60, 471817, 0, 475513, 60, 480553, 0,
    -    484249, 60, 489289, 0, 492985, 60, 498025, 0, 501721, 60, 506929, 0,
    -    510457, 60, 515665, 0, 519193, 60, 524401, 0, 528097, 60, 533137, 0,
    -    536833, 60, 541873, 0, 545569, 60, 550777, 0, 554305, 60, 559513, 0,
    -    563041, 60, 568249, 0, 571777, 60, 576985, 0, 580681, 60, 585721, 0,
    -    589417, 60, 594457, 0],
    -  'names': ['MEZ', 'Mitteleurop\u00e4ische Zeit',
    -            'MESZ', 'Mitteleurop\u00e4ische Sommerzeit'],
    -  'id': 'Europe/Berlin',
    -  'std_offset': 60
    -};
    -
    -var date;
    -
    -function testHHmmss() {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de;
    -  date = new Date(2006, 6, 27, 13, 10, 10, 250);
    -  var fmt = new goog.i18n.DateTimeFormat('HH:mm:ss');
    -  assertEquals('13:10:10', fmt.format(date));
    -}
    -
    -function testhhmmssa() {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de;
    -  date = new Date(2006, 6, 27, 13, 10, 10, 250);
    -  var fmt = new goog.i18n.DateTimeFormat('h:mm:ss a');
    -  assertEquals('1:10:10 nachm.', fmt.format(date));
    -}
    -
    -function testEEEMMMddyy() {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de;
    -  date = new Date(2006, 6, 27, 13, 10, 10, 250);
    -  var fmt = new goog.i18n.DateTimeFormat('EEE, MMM d, yy');
    -  assertEquals('Do., Juli 27, 06', fmt.format(date));
    -}
    -
    -function testEEEEMMMddyy() {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de;
    -  date = new Date(2006, 6, 27, 13, 10, 10, 250);
    -  var fmt = new goog.i18n.DateTimeFormat('EEEE,MMMM dd, yyyy');
    -  assertEquals('Donnerstag,Juli 27, 2006', fmt.format(date));
    -}
    -
    -function testyyyyMMddG() {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de;
    -  date = new Date(Date.UTC(2006, 6, 27, 13, 10, 10, 250));
    -  var timeZone = goog.i18n.TimeZone.createTimeZone(420,
    -      goog.i18n.DateTimeSymbols_de);
    -  var fmt = new goog.i18n.DateTimeFormat('yyyy.MM.dd G \'at\' HH:mm:ss vvvv');
    -  assertEquals('2006.07.27 n. Chr. at 06:10:10 Etc/GMT+7',
    -               fmt.format(date, timeZone));
    -}
    -
    -function testyyyyyMMMMM() {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de;
    -  date = new Date(2006, 6, 27, 13, 10, 10, 250);
    -  var fmt = new goog.i18n.DateTimeFormat('yyyyy.MMMMM.dd GGG hh:mm aaa');
    -  assertEquals('02006.J.27 n. Chr. 01:10 nachm.', fmt.format(date));
    -
    -  date = new Date(972, 11, 25, 13, 10, 10, 250);
    -  var fmt = new goog.i18n.DateTimeFormat('yyyyy.MMMMM.dd');
    -  assertEquals('00972.D.25', fmt.format(date));
    -}
    -
    -function testQQQQyy() {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de;
    -  date = new Date(2006, 0, 27, 13, 10, 10, 250);
    -  var fmt = new goog.i18n.DateTimeFormat('QQQQ yy');
    -  assertEquals('1. Quartal 06', fmt.format(date));
    -  date = new Date(2006, 1, 27, 13, 10, 10, 250);
    -  assertEquals('1. Quartal 06', fmt.format(date));
    -  date = new Date(2006, 2, 27, 13, 10, 10, 250);
    -  assertEquals('1. Quartal 06', fmt.format(date));
    -  date = new Date(2006, 3, 27, 13, 10, 10, 250);
    -  assertEquals('2. Quartal 06', fmt.format(date));
    -  date = new Date(2006, 4, 27, 13, 10, 10, 250);
    -  assertEquals('2. Quartal 06', fmt.format(date));
    -  date = new Date(2006, 5, 27, 13, 10, 10, 250);
    -  assertEquals('2. Quartal 06', fmt.format(date));
    -  date = new Date(2006, 6, 27, 13, 10, 10, 250);
    -  assertEquals('3. Quartal 06', fmt.format(date));
    -  date = new Date(2006, 7, 27, 13, 10, 10, 250);
    -  assertEquals('3. Quartal 06', fmt.format(date));
    -  date = new Date(2006, 8, 27, 13, 10, 10, 250);
    -  assertEquals('3. Quartal 06', fmt.format(date));
    -  date = new Date(2006, 9, 27, 13, 10, 10, 250);
    -  assertEquals('4. Quartal 06', fmt.format(date));
    -  date = new Date(2006, 10, 27, 13, 10, 10, 250);
    -  assertEquals('4. Quartal 06', fmt.format(date));
    -  date = new Date(2006, 11, 27, 13, 10, 10, 250);
    -  assertEquals('4. Quartal 06', fmt.format(date));
    -}
    -
    -function testQQyyyy() {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de;
    -  date = new Date(2006, 0, 27, 13, 10, 10, 250);
    -  var fmt = new goog.i18n.DateTimeFormat('QQ yyyy');
    -  assertEquals('Q1 2006', fmt.format(date));
    -  date = new Date(2006, 1, 27, 13, 10, 10, 250);
    -  assertEquals('Q1 2006', fmt.format(date));
    -  date = new Date(2006, 2, 27, 13, 10, 10, 250);
    -  assertEquals('Q1 2006', fmt.format(date));
    -  date = new Date(2006, 3, 27, 13, 10, 10, 250);
    -  assertEquals('Q2 2006', fmt.format(date));
    -  date = new Date(2006, 4, 27, 13, 10, 10, 250);
    -  assertEquals('Q2 2006', fmt.format(date));
    -  date = new Date(2006, 5, 27, 13, 10, 10, 250);
    -  assertEquals('Q2 2006', fmt.format(date));
    -  date = new Date(2006, 6, 27, 13, 10, 10, 250);
    -  assertEquals('Q3 2006', fmt.format(date));
    -  date = new Date(2006, 7, 27, 13, 10, 10, 250);
    -  assertEquals('Q3 2006', fmt.format(date));
    -  date = new Date(2006, 8, 27, 13, 10, 10, 250);
    -  assertEquals('Q3 2006', fmt.format(date));
    -  date = new Date(2006, 9, 27, 13, 10, 10, 250);
    -  assertEquals('Q4 2006', fmt.format(date));
    -  date = new Date(2006, 10, 27, 13, 10, 10, 250);
    -  assertEquals('Q4 2006', fmt.format(date));
    -  date = new Date(2006, 11, 27, 13, 10, 10, 250);
    -  assertEquals('Q4 2006', fmt.format(date));
    -}
    -
    -function testMMddyyyyHHmmsszzz() {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de;
    -  date = new Date(2006, 6, 27, 13, 10, 10, 250);
    -  var fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss zzz');
    -  assertEquals('07/27/2006 13:10:10 ' + timezoneString(date),
    -      fmt.format(date));
    -}
    -
    -function testMMddyyyyHHmmssZ() {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de;
    -  date = new Date(2006, 6, 27, 13, 10, 10, 250);
    -  var fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss Z');
    -  assertEquals('07/27/2006 13:10:10 ' + timezoneStringRFC(date),
    -      fmt.format(date));
    -}
    -
    -function testPatternMonthDayMedium() {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de;
    -  date = new Date(2006, 6, 27, 13, 10, 10, 250);
    -  var fmt = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimePatterns.MONTH_DAY_MEDIUM);
    -  assertEquals('27. Juli', fmt.format(date));
    -}
    -
    -function testPatternDayOfWeekMonthDayMedium() {
    -  date = new Date(2006, 6, 27, 13, 10, 10, 250);
    -
    -  var fmt = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimePatterns.WEEKDAY_MONTH_DAY_MEDIUM);
    -  assertEquals('Thu, Jul 27', fmt.format(date));
    -
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de;
    -  var fmt = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimePatterns.WEEKDAY_MONTH_DAY_MEDIUM);
    -  assertEquals('Do., 27. Juli', fmt.format(date));
    -}
    -
    -function testPatternDayOfWeekMonthDayYearMedium() {
    -  date = new Date(2012, 5, 28, 13, 10, 10, 250);
    -
    -  var fmt = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimePatterns.WEEKDAY_MONTH_DAY_YEAR_MEDIUM);
    -  assertEquals('Thu, Jun 28, 2012', fmt.format(date));
    -  var fmt = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimePatterns.MONTH_DAY_YEAR_MEDIUM);
    -  assertEquals('Jun 28, 2012', fmt.format(date));
    -
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sv;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sv;
    -  var fmt = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimePatterns.WEEKDAY_MONTH_DAY_YEAR_MEDIUM);
    -  assertEquals('tors 28 juni 2012', fmt.format(date));
    -  var fmt = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimePatterns.MONTH_DAY_YEAR_MEDIUM);
    -  assertEquals('28 juni 2012', fmt.format(date));
    -}
    -
    -function testQuote() {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de;
    -  date = new Date(2006, 6, 27, 13, 10, 10, 250);
    -  var fmt = new goog.i18n.DateTimeFormat('HH \'o\'\'clock\'');
    -  assertEquals('13 o\'clock', fmt.format(date));
    -  fmt = new goog.i18n.DateTimeFormat('HH \'oclock\'');
    -  assertEquals('13 oclock', fmt.format(date));
    -  fmt = new goog.i18n.DateTimeFormat('HH \'\'');
    -  assertEquals('13 \'', fmt.format(date));
    -}
    -
    -function testFractionalSeconds() {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de;
    -  date = new Date(2006, 6, 27, 13, 10, 10, 256);
    -  var fmt = new goog.i18n.DateTimeFormat('s:S');
    -  assertEquals('10:3', fmt.format(date));
    -  var fmt = new goog.i18n.DateTimeFormat('s:SS');
    -  assertEquals('10:26', fmt.format(date));
    -  var fmt = new goog.i18n.DateTimeFormat('s:SSS');
    -  assertEquals('10:256', fmt.format(date));
    -  var fmt = new goog.i18n.DateTimeFormat('s:SSSS');
    -  assertEquals('10:2560', fmt.format(date));
    -  var fmt = new goog.i18n.DateTimeFormat('s:SSSSS');
    -  assertEquals('10:25600', fmt.format(date));
    -}
    -
    -function testPredefinedFormatter() {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de;
    -  date = new Date(2006, 7, 4, 13, 49, 24, 000);
    -  var fmt = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimeFormat.Format.FULL_DATE);
    -  assertEquals('Freitag, 4. August 2006', fmt.format(date));
    -  fmt = new goog.i18n.DateTimeFormat(goog.i18n.DateTimeFormat.Format.LONG_DATE);
    -  assertEquals('4. August 2006', fmt.format(date));
    -  fmt = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimeFormat.Format.MEDIUM_DATE);
    -  assertEquals('04.08.2006', fmt.format(date));
    -  fmt = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimeFormat.Format.SHORT_DATE);
    -  assertEquals('04.08.06', fmt.format(date));
    -  fmt = new goog.i18n.DateTimeFormat(goog.i18n.DateTimeFormat.Format.FULL_TIME);
    -  assertEquals('13:49:24 ' + timezoneString(date), fmt.format(date));
    -  fmt = new goog.i18n.DateTimeFormat(goog.i18n.DateTimeFormat.Format.LONG_TIME);
    -  assertEquals('13:49:24 ' + timezoneString(date), fmt.format(date));
    -  fmt = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimeFormat.Format.MEDIUM_TIME);
    -  assertEquals('13:49:24', fmt.format(date));
    -  fmt = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimeFormat.Format.SHORT_TIME);
    -  assertEquals('13:49', fmt.format(date));
    -  fmt = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimeFormat.Format.FULL_DATETIME);
    -  assertEquals('Freitag, 4. August 2006 um 13:49:24 ' + timezoneString(date),
    -      fmt.format(date));
    -  fmt = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimeFormat.Format.LONG_DATETIME);
    -  assertEquals('4. August 2006 um 13:49:24 ' + timezoneString(date),
    -      fmt.format(date));
    -  fmt = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimeFormat.Format.MEDIUM_DATETIME);
    -  assertEquals('04.08.2006, 13:49:24', fmt.format(date));
    -  fmt = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimeFormat.Format.SHORT_DATETIME);
    -  assertEquals('04.08.06, 13:49', fmt.format(date));
    -}
    -
    -function testMMddyyyyHHmmssZSimpleTimeZone() {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de;
    -  var date = new Date(Date.UTC(2006, 6, 27, 13, 10, 10));
    -  var timeZone = goog.i18n.TimeZone.createTimeZone(480);
    -  var fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss Z');
    -  assertEquals('07/27/2006 05:10:10 -0800', fmt.format(date, timeZone));
    -  fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss ZZ');
    -  assertEquals('07/27/2006 05:10:10 -0800', fmt.format(date, timeZone));
    -  fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss ZZZ');
    -  assertEquals('07/27/2006 05:10:10 -0800', fmt.format(date, timeZone));
    -  fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss ZZZZ');
    -  assertEquals('07/27/2006 05:10:10 GMT-08:00', fmt.format(date, timeZone));
    -}
    -
    -
    -function testMMddyyyyHHmmssZCommonTimeZone() {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de;
    -  var date = new Date(Date.UTC(2006, 6, 27, 13, 10, 10));
    -  var timeZone = goog.i18n.TimeZone.createTimeZone(americaLosAngelesData);
    -  var fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss Z');
    -  assertEquals('07/27/2006 06:10:10 -0700', fmt.format(date, timeZone));
    -  fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss ZZ');
    -  assertEquals('07/27/2006 06:10:10 -0700', fmt.format(date, timeZone));
    -  fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss ZZZ');
    -  assertEquals('07/27/2006 06:10:10 -0700', fmt.format(date, timeZone));
    -  fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss ZZZZ');
    -  assertEquals('07/27/2006 06:10:10 GMT-07:00', fmt.format(date, timeZone));
    -  date = new Date(Date.UTC(2006, 1, 27, 13, 10, 10));
    -  fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss Z');
    -  assertEquals('02/27/2006 05:10:10 -0800', fmt.format(date, timeZone));
    -  fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss ZZ');
    -  assertEquals('02/27/2006 05:10:10 -0800', fmt.format(date, timeZone));
    -  fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss ZZZ');
    -  assertEquals('02/27/2006 05:10:10 -0800', fmt.format(date, timeZone));
    -  fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss ZZZZ');
    -  assertEquals('02/27/2006 05:10:10 GMT-08:00', fmt.format(date, timeZone));
    -}
    -
    -function testMMddyyyyHHmmsszSimpleTimeZone() {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de;
    -  var date = new Date(Date.UTC(2006, 6, 27, 13, 10, 10));
    -  var timeZone = goog.i18n.TimeZone.createTimeZone(420);
    -  var fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss z');
    -  assertEquals('07/27/2006 06:10:10 UTC-7', fmt.format(date, timeZone));
    -  fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss zz');
    -  assertEquals('07/27/2006 06:10:10 UTC-7', fmt.format(date, timeZone));
    -  fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss zzz');
    -  assertEquals('07/27/2006 06:10:10 UTC-7', fmt.format(date, timeZone));
    -  fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss zzzz');
    -  assertEquals('07/27/2006 06:10:10 UTC-7', fmt.format(date, timeZone));
    -}
    -
    -
    -function testMMddyyyyHHmmsszCommonTimeZone() {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de;
    -  var date = new Date(Date.UTC(2006, 6, 27, 13, 10, 10));
    -  var timeZone = goog.i18n.TimeZone.createTimeZone(americaLosAngelesData);
    -  var fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss z');
    -  assertEquals('07/27/2006 06:10:10 PDT', fmt.format(date, timeZone));
    -  fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss zz');
    -  assertEquals('07/27/2006 06:10:10 PDT', fmt.format(date, timeZone));
    -  fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss zzz');
    -  assertEquals('07/27/2006 06:10:10 PDT', fmt.format(date, timeZone));
    -  fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss zzzz');
    -  assertEquals('07/27/2006 06:10:10 Pacific Daylight Time',
    -               fmt.format(date, timeZone));
    -  date = new Date(Date.UTC(2006, 1, 27, 13, 10, 10));
    -  fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss z');
    -  assertEquals('02/27/2006 05:10:10 PST', fmt.format(date, timeZone));
    -  fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss zz');
    -  assertEquals('02/27/2006 05:10:10 PST', fmt.format(date, timeZone));
    -  fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss zzz');
    -  assertEquals('02/27/2006 05:10:10 PST', fmt.format(date, timeZone));
    -  fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss zzzz');
    -  assertEquals('02/27/2006 05:10:10 Pacific Standard Time',
    -      fmt.format(date, timeZone));
    -
    -  timeZone = goog.i18n.TimeZone.createTimeZone(europeBerlinData);
    -  fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss z');
    -  assertEquals('02/27/2006 14:10:10 MEZ', fmt.format(date, timeZone));
    -  var fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss zzzz');
    -  assertEquals('02/27/2006 14:10:10 Mitteleurop\u00e4ische Zeit',
    -      fmt.format(date, timeZone));
    -}
    -
    -function testMMddyyyyHHmmssvCommonTimeZone() {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de;
    -  var date = new Date(Date.UTC(2006, 6, 27, 13, 10, 10));
    -  var timeZone = goog.i18n.TimeZone.createTimeZone(americaLosAngelesData);
    -  var fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss v');
    -  assertEquals('07/27/2006 06:10:10 America/Los_Angeles',
    -               fmt.format(date, timeZone));
    -  fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss vv');
    -  assertEquals('07/27/2006 06:10:10 America/Los_Angeles',
    -               fmt.format(date, timeZone));
    -  fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss vvv');
    -  assertEquals('07/27/2006 06:10:10 America/Los_Angeles',
    -               fmt.format(date, timeZone));
    -  fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss vvvv');
    -  assertEquals('07/27/2006 06:10:10 America/Los_Angeles',
    -      fmt.format(date, timeZone));
    -}
    -
    -function testMMddyyyyHHmmssvSimpleTimeZone() {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de;
    -  var date = new Date(Date.UTC(2006, 6, 27, 13, 10, 10));
    -  var timeZone = goog.i18n.TimeZone.createTimeZone(420);
    -  var fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss v');
    -  assertEquals('07/27/2006 06:10:10 Etc/GMT+7', fmt.format(date, timeZone));
    -  fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss vv');
    -  assertEquals('07/27/2006 06:10:10 Etc/GMT+7', fmt.format(date, timeZone));
    -  fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss vvv');
    -  assertEquals('07/27/2006 06:10:10 Etc/GMT+7', fmt.format(date, timeZone));
    -  var fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss vvvv');
    -  assertEquals('07/27/2006 06:10:10 Etc/GMT+7', fmt.format(date, timeZone));
    -}
    -
    -
    -function test_yyyyMMddG() {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de;
    -  var date = new Date(Date.UTC(2006, 6, 27, 20, 10, 10));
    -  var timeZone = goog.i18n.TimeZone.createTimeZone(420);
    -  var fmt = new goog.i18n.DateTimeFormat('yyyy.MM.dd G \'at\' HH:mm:ss vvvv');
    -  assertEquals('2006.07.27 n. Chr. at 13:10:10 Etc/GMT+7',
    -               fmt.format(date, timeZone));
    -
    -  timeZone = goog.i18n.TimeZone.createTimeZone(americaLosAngelesData);
    -  fmt = new goog.i18n.DateTimeFormat('yyyy.MM.dd G \'at\' HH:mm:ss vvvv');
    -  assertEquals('2006.07.27 n. Chr. at 13:10:10 America/Los_Angeles',
    -      fmt.format(date, timeZone));
    -}
    -
    -function test_daylightTimeTransition() {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de;
    -
    -  // US PST transition to PDT on 2006/4/2/ 2:00am, jump to 2006/4/2 3:00am,
    -  // That's UTC time 2006/4/2 10:00am
    -  var timeZone = goog.i18n.TimeZone.createTimeZone(americaLosAngelesData);
    -  var date = new Date(Date.UTC(2006, 4 - 1, 2, 9, 59, 0));
    -  var fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss z');
    -  assertEquals('04/02/2006 01:59:00 PST', fmt.format(date, timeZone));
    -  date = new Date(Date.UTC(2006, 4 - 1, 2, 10, 01, 0));
    -  fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss z');
    -  assertEquals('04/02/2006 03:01:00 PDT', fmt.format(date, timeZone));
    -  date = new Date(Date.UTC(2006, 4 - 1, 2, 10, 00, 0));
    -  fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss z');
    -  assertEquals('04/02/2006 03:00:00 PDT', fmt.format(date, timeZone));
    -}
    -
    -function test_timeDisplayOnDaylighTimeTransition() {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de;
    -
    -  // US PST transition to PDT on 2006/4/2/ 2:00am, jump to 2006/4/2 3:00am,
    -  var date = new Date(Date.UTC(2006, 4 - 1, 2, 2, 30, 0));
    -  var timeZone = goog.i18n.TimeZone.createTimeZone(0);
    -  var fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss Z');
    -  assertEquals('04/02/2006 02:30:00 +0000', fmt.format(date, timeZone));
    -
    -  // US PDT transition to PST on 2006/10/29/ 2:00am, jump back to PDT
    -  // 2006/4/2 1:00am,
    -  date = new Date(Date.UTC(2006, 10 - 1, 29, 1, 30, 0));
    -  fmt = new goog.i18n.DateTimeFormat('MM/dd/yyyy HH:mm:ss Z');
    -  assertEquals('10/29/2006 01:30:00 +0000', fmt.format(date, timeZone));
    -}
    -
    -function test_nativeDigits() {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fa;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fa;
    -
    -  date = new Date(2006, 6, 27, 13, 10, 10, 250);
    -  var timeZone = goog.i18n.TimeZone.createTimeZone(420);
    -  var fmt = new goog.i18n.DateTimeFormat('y/MM/dd H:mm:ss٫SS');
    -  assertEquals('۲۰۰۶/۰۷/۲۷ ۱۳:۱۰:۱۰٫۲۵', fmt.format(date));
    -
    -  // Make sure standardized timezone formats don't use native digits
    -  fmt = new goog.i18n.DateTimeFormat('Z');
    -  assertEquals('-0700', fmt.format(date, timeZone));
    -}
    -
    -// Making sure that the date-time combination is not a simple concatenation
    -function test_dateTimeConcatenation() {
    -  var date = new Date(Date.UTC(2006, 4 - 1, 2, 2, 30, 0));
    -  var timeZone = goog.i18n.TimeZone.createTimeZone(americaLosAngelesData);
    -  var fmt = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimeFormat.Format.FULL_DATETIME);
    -  // {1} 'at' {0}
    -  assertEquals('Saturday, April 1, 2006 at 6:30:00 PM Pacific Standard Time',
    -               fmt.format(date, timeZone));
    -  fmt = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimeFormat.Format.LONG_DATETIME);
    -  assertEquals('April 1, 2006 at 6:30:00 PM PST', fmt.format(date, timeZone));
    -  // {1}, {0}
    -  fmt = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimeFormat.Format.MEDIUM_DATETIME);
    -  assertEquals('Apr 1, 2006, 6:30:00 PM', fmt.format(date, timeZone));
    -  fmt = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimeFormat.Format.SHORT_DATETIME);
    -  assertEquals('4/1/06, 6:30 PM', fmt.format(date, timeZone));
    -}
    -
    -function testNotUsingGlobalSymbols() {
    -  date = new Date(2013, 10, 15);
    -
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr;
    -  var fmtFr = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimeFormat.Format.FULL_DATE);
    -
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de;
    -  var fmtDe = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimeFormat.Format.FULL_DATE);
    -
    -  // The two formatters should return different results (French & German)
    -  assertEquals('vendredi 15 novembre 2013', fmtFr.format(date));
    -  assertEquals('Freitag, 15. November 2013', fmtDe.format(date));
    -}
    -
    -function testConstructorSymbols() {
    -  date = new Date(2013, 10, 15);
    -
    -  var fmtFr = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimeFormat.Format.FULL_DATE,
    -      goog.i18n.DateTimeSymbols_fr);
    -
    -  var fmtDe = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimeFormat.Format.FULL_DATE,
    -      goog.i18n.DateTimeSymbols_de);
    -
    -  // The two formatters should return different results (French & German)
    -  assertEquals('vendredi 15 novembre 2013', fmtFr.format(date));
    -  assertEquals('Freitag, 15. November 2013', fmtDe.format(date));
    -}
    -
    -function testSupportForWeekInYear() {
    -  var date = new Date(2013, 1, 25);
    -
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr;
    -  var fmt = new goog.i18n.DateTimeFormat('\'week\' w');
    -  assertEquals('week 9', fmt.format(date));
    -  var fmt = new goog.i18n.DateTimeFormat('\'week\' ww');
    -  assertEquals('week 09', fmt.format(date));
    -
    -  // Make sure it uses native digits when needed
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fa;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fa;
    -  var fmt = new goog.i18n.DateTimeFormat('\'week\' w');
    -  assertEquals('week ۹', fmt.format(date));
    -  var fmt = new goog.i18n.DateTimeFormat('\'week\' ww');
    -  assertEquals('week ۰۹', fmt.format(date));
    -}
    -
    -function testSupportForYearAndEra() {
    -  var date = new Date(2013, 1, 25);
    -  var fmt = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimePatterns.YEAR_FULL_WITH_ERA);
    -
    -  assertEquals('2013 AD', fmt.format(date));
    -
    -  date.setFullYear(213);
    -  assertEquals('213 AD', fmt.format(date));
    -
    -  date.setFullYear(11);
    -  assertEquals('11 AD', fmt.format(date));
    -
    -  date.setFullYear(-213);
    -  assertEquals('213 BC', fmt.format(date));
    -
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de;
    -  fmt = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimePatterns.YEAR_FULL_WITH_ERA);
    -
    -  date.setFullYear(2013);
    -  assertEquals('2013 n. Chr.', fmt.format(date));
    -
    -  date.setFullYear(213);
    -  assertEquals('213 n. Chr.', fmt.format(date));
    -
    -  date.setFullYear(11);
    -  assertEquals('11 n. Chr.', fmt.format(date));
    -
    -  date.setFullYear(-213);
    -  assertEquals('213 v. Chr.', fmt.format(date));
    -
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ja;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ja;
    -  fmt = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimePatterns.YEAR_FULL_WITH_ERA);
    -
    -  date.setFullYear(2013);
    -  assertEquals('西暦2013年', fmt.format(date));
    -
    -  date.setFullYear(213);
    -  assertEquals('西暦213年', fmt.format(date));
    -
    -  date.setFullYear(11);
    -  assertEquals('西暦11年', fmt.format(date));
    -
    -  date.setFullYear(-213);
    -  assertEquals('紀元前213年', fmt.format(date));
    -}
    -
    -// Creates a string by concatenating the week number for 7 successive days
    -function weekInYearFor7Days() {
    -  var date = new Date(2013, 0, 1); // January
    -  var fmt = new goog.i18n.DateTimeFormat('w');
    -  var result = '';
    -  for (var i = 1; i <= 7; ++i) {
    -    date.setDate(i);
    -    result += fmt.format(date);
    -  }
    -  return result;
    -}
    -
    -// Expected results from ICU4J v51. One entry will change in v52.
    -// These cover all combinations of FIRSTDAYOFWEEK / FIRSTWEEKCUTOFFDAY in use.
    -function testWeekInYearI18n() {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_bn_BD;
    -  assertEquals('bn_BD', '১১১২২২২', weekInYearFor7Days());
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_IE;
    -  assertEquals('en_IE', '1111122', weekInYearFor7Days());
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_DJ;
    -  assertEquals('fr_DJ', '1111222', weekInYearFor7Days());
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_he_IL;
    -  assertEquals('he_IL', '1111122', weekInYearFor7Days());
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_SA;
    -  assertEquals('ar_SA', '١١١١١٢٢', weekInYearFor7Days());
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_AE;
    -  assertEquals('ar_AE', '١١١١٢٢٢', weekInYearFor7Days());
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_IN;
    -  assertEquals('en_IN', '1111122', weekInYearFor7Days());
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_GB;
    -  assertEquals('en_GB', '1111112', weekInYearFor7Days());
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_US;
    -  assertEquals('en_US', '1111122', weekInYearFor7Days());
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ro_RO;
    -  assertEquals('ro_RO', '1111112', weekInYearFor7Days());
    -}
    -
    -// Regression for b/11567443 (no method 'getHours' when formatting a
    -// goog.date.Date)
    -function test_variousDateTypes() {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr;
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr;
    -
    -  var fmt = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimeFormat.Format.MEDIUM_DATETIME);
    -
    -  var date = new Date(2006, 6, 27, 13, 10, 42, 250);
    -  assertEquals('27 juil. 2006 13:10:42', fmt.format(date));
    -
    -  var gdatetime = new goog.date.DateTime(2006, 6, 27, 13, 10, 42, 250);
    -  assertEquals('27 juil. 2006 13:10:42', fmt.format(gdatetime));
    -
    -  var gdate = new goog.date.Date(2006, 6, 27);
    -  var fmtDate =
    -      new goog.i18n.DateTimeFormat(goog.i18n.DateTimeFormat.Format.MEDIUM_DATE);
    -  assertEquals('27 juil. 2006', fmtDate.format(gdatetime));
    -  try {
    -    fmt.format(gdate);
    -    fail('Should have thrown exception.');
    -  } catch (e) {}
    -}
    -
    -function testExceptionWhenFormattingNull() {
    -  var fmt = new goog.i18n.DateTimeFormat('M/d/y');
    -  try {
    -    fmt.format(null);
    -    fail('Should have thrown exception.');
    -  } catch (e) {}
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/datetimeparse.js b/src/database/third_party/closure-library/closure/goog/i18n/datetimeparse.js
    deleted file mode 100644
    index 806bfa507f8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/datetimeparse.js
    +++ /dev/null
    @@ -1,1150 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Date/Time parsing library with locale support.
    - */
    -
    -
    -/**
    - * Namespace for locale date/time parsing functions
    - */
    -goog.provide('goog.i18n.DateTimeParse');
    -
    -goog.require('goog.date');
    -goog.require('goog.i18n.DateTimeFormat');
    -goog.require('goog.i18n.DateTimeSymbols');
    -
    -
    -/**
    - * DateTimeParse is for parsing date in a locale-sensitive manner. It allows
    - * user to use any customized patterns to parse date-time string under certain
    - * locale. Things varies across locales like month name, weekname, field
    - * order, etc.
    - *
    - * This module is the counter-part of DateTimeFormat. They use the same
    - * date/time pattern specification, which is borrowed from ICU/JDK.
    - *
    - * This implementation could parse partial date/time.
    - *
    - * Time Format Syntax: To specify the time format use a time pattern string.
    - * In this pattern, following letters are reserved as pattern letters, which
    - * are defined as the following:
    - *
    - * <pre>
    - * Symbol   Meaning                 Presentation        Example
    - * ------   -------                 ------------        -------
    - * G        era designator          (Text)              AD
    - * y#       year                    (Number)            1996
    - * M        month in year           (Text & Number)     July & 07
    - * d        day in month            (Number)            10
    - * h        hour in am/pm (1~12)    (Number)            12
    - * H        hour in day (0~23)      (Number)            0
    - * m        minute in hour          (Number)            30
    - * s        second in minute        (Number)            55
    - * S        fractional second       (Number)            978
    - * E        day of week             (Text)              Tuesday
    - * D        day in year             (Number)            189
    - * a        am/pm marker            (Text)              PM
    - * k        hour in day (1~24)      (Number)            24
    - * K        hour in am/pm (0~11)    (Number)            0
    - * z        time zone               (Text)              Pacific Standard Time
    - * Z        time zone (RFC 822)     (Number)            -0800
    - * v        time zone (generic)     (Text)              Pacific Time
    - * '        escape for text         (Delimiter)         'Date='
    - * ''       single quote            (Literal)           'o''clock'
    - * </pre>
    - *
    - * The count of pattern letters determine the format. <p>
    - * (Text): 4 or more pattern letters--use full form,
    - *         less than 4--use short or abbreviated form if one exists.
    - *         In parsing, we will always try long format, then short. <p>
    - * (Number): the minimum number of digits. <p>
    - * (Text & Number): 3 or over, use text, otherwise use number. <p>
    - * Any characters that not in the pattern will be treated as quoted text. For
    - * instance, characters like ':', '.', ' ', '#' and '@' will appear in the
    - * resulting time text even they are not embraced within single quotes. In our
    - * current pattern usage, we didn't use up all letters. But those unused
    - * letters are strongly discouraged to be used as quoted text without quote.
    - * That's because we may use other letter for pattern in future. <p>
    - *
    - * Examples Using the US Locale:
    - *
    - * Format Pattern                         Result
    - * --------------                         -------
    - * "yyyy.MM.dd G 'at' HH:mm:ss vvvv" ->>  1996.07.10 AD at 15:08:56 Pacific Time
    - * "EEE, MMM d, ''yy"                ->>  Wed, July 10, '96
    - * "h:mm a"                          ->>  12:08 PM
    - * "hh 'o''clock' a, zzzz"           ->>  12 o'clock PM, Pacific Daylight Time
    - * "K:mm a, vvv"                     ->>  0:00 PM, PT
    - * "yyyyy.MMMMM.dd GGG hh:mm aaa"    ->>  01996.July.10 AD 12:08 PM
    - *
    - * <p> When parsing a date string using the abbreviated year pattern ("yy"),
    - * DateTimeParse must interpret the abbreviated year relative to some
    - * century. It does this by adjusting dates to be within 80 years before and 20
    - * years after the time the parse function is called. For example, using a
    - * pattern of "MM/dd/yy" and a DateTimeParse instance created on Jan 1, 1997,
    - * the string "01/11/12" would be interpreted as Jan 11, 2012 while the string
    - * "05/04/64" would be interpreted as May 4, 1964. During parsing, only
    - * strings consisting of exactly two digits, as defined by {@link
    - * java.lang.Character#isDigit(char)}, will be parsed into the default
    - * century. Any other numeric string, such as a one digit string, a three or
    - * more digit string will be interpreted as its face value.
    - *
    - * <p> If the year pattern does not have exactly two 'y' characters, the year is
    - * interpreted literally, regardless of the number of digits. So using the
    - * pattern "MM/dd/yyyy", "01/11/12" parses to Jan 11, 12 A.D.
    - *
    - * <p> When numeric fields abut one another directly, with no intervening
    - * delimiter characters, they constitute a run of abutting numeric fields. Such
    - * runs are parsed specially. For example, the format "HHmmss" parses the input
    - * text "123456" to 12:34:56, parses the input text "12345" to 1:23:45, and
    - * fails to parse "1234". In other words, the leftmost field of the run is
    - * flexible, while the others keep a fixed width. If the parse fails anywhere in
    - * the run, then the leftmost field is shortened by one character, and the
    - * entire run is parsed again. This is repeated until either the parse succeeds
    - * or the leftmost field is one character in length. If the parse still fails at
    - * that point, the parse of the run fails.
    - *
    - * <p> Now timezone parsing only support GMT:hhmm, GMT:+hhmm, GMT:-hhmm
    - */
    -
    -
    -
    -/**
    - * Construct a DateTimeParse based on current locale.
    - * @param {string|number} pattern pattern specification or pattern type.
    - * @constructor
    - * @final
    - */
    -goog.i18n.DateTimeParse = function(pattern) {
    -  this.patternParts_ = [];
    -  if (typeof pattern == 'number') {
    -    this.applyStandardPattern_(pattern);
    -  } else {
    -    this.applyPattern_(pattern);
    -  }
    -};
    -
    -
    -/**
    - * Number of years prior to now that the century used to
    - * disambiguate two digit years will begin
    - *
    - * @type {number}
    - */
    -goog.i18n.DateTimeParse.ambiguousYearCenturyStart = 80;
    -
    -
    -/**
    - * Apply a pattern to this Parser. The pattern string will be parsed and saved
    - * in "compiled" form.
    - * Note: this method is somewhat similar to the pattern parsing method in
    - *       datetimeformat. If you see something wrong here, you might want
    - *       to check the other.
    - * @param {string} pattern It describes the format of date string that need to
    - *     be parsed.
    - * @private
    - */
    -goog.i18n.DateTimeParse.prototype.applyPattern_ = function(pattern) {
    -  var inQuote = false;
    -  var buf = '';
    -
    -  for (var i = 0; i < pattern.length; i++) {
    -    var ch = pattern.charAt(i);
    -
    -    // handle space, add literal part (if exist), and add space part
    -    if (ch == ' ') {
    -      if (buf.length > 0) {
    -        this.patternParts_.push({text: buf, count: 0, abutStart: false});
    -        buf = '';
    -      }
    -      this.patternParts_.push({text: ' ', count: 0, abutStart: false});
    -      while (i < pattern.length - 1 && pattern.charAt(i + 1) == ' ') {
    -        i++;
    -      }
    -    } else if (inQuote) {
    -      // inside quote, except '', just copy or exit
    -      if (ch == '\'') {
    -        if (i + 1 < pattern.length && pattern.charAt(i + 1) == '\'') {
    -          // quote appeared twice continuously, interpret as one quote.
    -          buf += '\'';
    -          i++;
    -        } else {
    -          // exit quote
    -          inQuote = false;
    -        }
    -      } else {
    -        // literal
    -        buf += ch;
    -      }
    -    } else if (goog.i18n.DateTimeParse.PATTERN_CHARS_.indexOf(ch) >= 0) {
    -      // outside quote, it is a pattern char
    -      if (buf.length > 0) {
    -        this.patternParts_.push({text: buf, count: 0, abutStart: false});
    -        buf = '';
    -      }
    -      var count = this.getNextCharCount_(pattern, i);
    -      this.patternParts_.push({text: ch, count: count, abutStart: false});
    -      i += count - 1;
    -    } else if (ch == '\'') {
    -      // Two consecutive quotes is a quote literal, inside or outside of quotes.
    -      if (i + 1 < pattern.length && pattern.charAt(i + 1) == '\'') {
    -        buf += '\'';
    -        i++;
    -      } else {
    -        inQuote = true;
    -      }
    -    } else {
    -      buf += ch;
    -    }
    -  }
    -
    -  if (buf.length > 0) {
    -    this.patternParts_.push({text: buf, count: 0, abutStart: false});
    -  }
    -
    -  this.markAbutStart_();
    -};
    -
    -
    -/**
    - * Apply a predefined pattern to this Parser.
    - * @param {number} formatType A constant used to identified the predefined
    - *     pattern string stored in locale repository.
    - * @private
    - */
    -goog.i18n.DateTimeParse.prototype.applyStandardPattern_ = function(formatType) {
    -  var pattern;
    -  // formatType constants are in consecutive numbers. So it can be used to
    -  // index array in following way.
    -
    -  // if type is out of range, default to medium date/time format.
    -  if (formatType > goog.i18n.DateTimeFormat.Format.SHORT_DATETIME) {
    -    formatType = goog.i18n.DateTimeFormat.Format.MEDIUM_DATETIME;
    -  }
    -
    -  if (formatType < 4) {
    -    pattern = goog.i18n.DateTimeSymbols.DATEFORMATS[formatType];
    -  } else if (formatType < 8) {
    -    pattern = goog.i18n.DateTimeSymbols.TIMEFORMATS[formatType - 4];
    -  } else {
    -    pattern = goog.i18n.DateTimeSymbols.DATETIMEFORMATS[formatType - 8];
    -    pattern = pattern.replace('{1}',
    -        goog.i18n.DateTimeSymbols.DATEFORMATS[formatType - 8]);
    -    pattern = pattern.replace('{0}',
    -        goog.i18n.DateTimeSymbols.TIMEFORMATS[formatType - 8]);
    -  }
    -  this.applyPattern_(pattern);
    -};
    -
    -
    -/**
    - * Parse the given string and fill info into date object. This version does
    - * not validate the input.
    - * @param {string} text The string being parsed.
    - * @param {goog.date.DateLike} date The Date object to hold the parsed date.
    - * @param {number=} opt_start The position from where parse should begin.
    - * @return {number} How many characters parser advanced.
    - */
    -goog.i18n.DateTimeParse.prototype.parse = function(text, date, opt_start) {
    -  var start = opt_start || 0;
    -  return this.internalParse_(text, date, start, false/*validation*/);
    -};
    -
    -
    -/**
    - * Parse the given string and fill info into date object. This version will
    - * validate the input and make sure it is a validate date/time.
    - * @param {string} text The string being parsed.
    - * @param {goog.date.DateLike} date The Date object to hold the parsed date.
    - * @param {number=} opt_start The position from where parse should begin.
    - * @return {number} How many characters parser advanced.
    - */
    -goog.i18n.DateTimeParse.prototype.strictParse =
    -    function(text, date, opt_start) {
    -  var start = opt_start || 0;
    -  return this.internalParse_(text, date, start, true/*validation*/);
    -};
    -
    -
    -/**
    - * Parse the given string and fill info into date object.
    - * @param {string} text The string being parsed.
    - * @param {goog.date.DateLike} date The Date object to hold the parsed date.
    - * @param {number} start The position from where parse should begin.
    - * @param {boolean} validation If true, input string need to be a valid
    - *     date/time string.
    - * @return {number} How many characters parser advanced.
    - * @private
    - */
    -goog.i18n.DateTimeParse.prototype.internalParse_ =
    -    function(text, date, start, validation) {
    -  var cal = new goog.i18n.DateTimeParse.MyDate_();
    -  var parsePos = [start];
    -
    -  // For parsing abutting numeric fields. 'abutPat' is the
    -  // offset into 'pattern' of the first of 2 or more abutting
    -  // numeric fields. 'abutStart' is the offset into 'text'
    -  // where parsing the fields begins. 'abutPass' starts off as 0
    -  // and increments each time we try to parse the fields.
    -  var abutPat = -1; // If >=0, we are in a run of abutting numeric fields
    -  var abutStart = 0;
    -  var abutPass = 0;
    -
    -  for (var i = 0; i < this.patternParts_.length; i++) {
    -    if (this.patternParts_[i].count > 0) {
    -      if (abutPat < 0 && this.patternParts_[i].abutStart) {
    -        abutPat = i;
    -        abutStart = start;
    -        abutPass = 0;
    -      }
    -
    -      // Handle fields within a run of abutting numeric fields. Take
    -      // the pattern "HHmmss" as an example. We will try to parse
    -      // 2/2/2 characters of the input text, then if that fails,
    -      // 1/2/2. We only adjust the width of the leftmost field; the
    -      // others remain fixed. This allows "123456" => 12:34:56, but
    -      // "12345" => 1:23:45. Likewise, for the pattern "yyyyMMdd" we
    -      // try 4/2/2, 3/2/2, 2/2/2, and finally 1/2/2.
    -      if (abutPat >= 0) {
    -        // If we are at the start of a run of abutting fields, then
    -        // shorten this field in each pass. If we can't shorten
    -        // this field any more, then the parse of this set of
    -        // abutting numeric fields has failed.
    -        var count = this.patternParts_[i].count;
    -        if (i == abutPat) {
    -          count -= abutPass;
    -          abutPass++;
    -          if (count == 0) {
    -            // tried all possible width, fail now
    -            return 0;
    -          }
    -        }
    -
    -        if (!this.subParse_(text, parsePos, this.patternParts_[i], count,
    -                            cal)) {
    -          // If the parse fails anywhere in the run, back up to the
    -          // start of the run and retry.
    -          i = abutPat - 1;
    -          parsePos[0] = abutStart;
    -          continue;
    -        }
    -      }
    -
    -      // Handle non-numeric fields and non-abutting numeric fields.
    -      else {
    -        abutPat = -1;
    -        if (!this.subParse_(text, parsePos, this.patternParts_[i], 0, cal)) {
    -          return 0;
    -        }
    -      }
    -    } else {
    -      // Handle literal pattern characters. These are any
    -      // quoted characters and non-alphabetic unquoted
    -      // characters.
    -      abutPat = -1;
    -      // A run of white space in the pattern matches a run
    -      // of white space in the input text.
    -      if (this.patternParts_[i].text.charAt(0) == ' ') {
    -        // Advance over run in input text
    -        var s = parsePos[0];
    -        this.skipSpace_(text, parsePos);
    -
    -        // Must see at least one white space char in input
    -        if (parsePos[0] > s) {
    -          continue;
    -        }
    -      } else if (text.indexOf(this.patternParts_[i].text, parsePos[0]) ==
    -                 parsePos[0]) {
    -        parsePos[0] += this.patternParts_[i].text.length;
    -        continue;
    -      }
    -      // We fall through to this point if the match fails
    -      return 0;
    -    }
    -  }
    -
    -  // return progress
    -  return cal.calcDate_(date, validation) ? parsePos[0] - start : 0;
    -};
    -
    -
    -/**
    - * Calculate character repeat count in pattern.
    - *
    - * @param {string} pattern It describes the format of date string that need to
    - *     be parsed.
    - * @param {number} start The position of pattern character.
    - *
    - * @return {number} Repeat count.
    - * @private
    - */
    -goog.i18n.DateTimeParse.prototype.getNextCharCount_ =
    -    function(pattern, start) {
    -  var ch = pattern.charAt(start);
    -  var next = start + 1;
    -  while (next < pattern.length && pattern.charAt(next) == ch) {
    -    next++;
    -  }
    -  return next - start;
    -};
    -
    -
    -/**
    - * All acceptable pattern characters.
    - * @private
    - */
    -goog.i18n.DateTimeParse.PATTERN_CHARS_ = 'GyMdkHmsSEDahKzZvQL';
    -
    -
    -/**
    - * Pattern characters that specify numerical field.
    - * @private
    - */
    -goog.i18n.DateTimeParse.NUMERIC_FORMAT_CHARS_ = 'MydhHmsSDkK';
    -
    -
    -/**
    - * Check if the pattern part is a numeric field.
    - *
    - * @param {Object} part pattern part to be examined.
    - *
    - * @return {boolean} true if the pattern part is numeric field.
    - * @private
    - */
    -goog.i18n.DateTimeParse.prototype.isNumericField_ = function(part) {
    -  if (part.count <= 0) {
    -    return false;
    -  }
    -  var i = goog.i18n.DateTimeParse.NUMERIC_FORMAT_CHARS_.indexOf(
    -      part.text.charAt(0));
    -  return i > 0 || i == 0 && part.count < 3;
    -};
    -
    -
    -/**
    - * Identify the start of an abutting numeric fields' run. Taking pattern
    - * "HHmmss" as an example. It will try to parse 2/2/2 characters of the input
    - * text, then if that fails, 1/2/2. We only adjust the width of the leftmost
    - * field; the others remain fixed. This allows "123456" => 12:34:56, but
    - * "12345" => 1:23:45. Likewise, for the pattern "yyyyMMdd" we try 4/2/2,
    - * 3/2/2, 2/2/2, and finally 1/2/2. The first field of connected numeric
    - * fields will be marked as abutStart, its width can be reduced to accommodate
    - * others.
    - *
    - * @private
    - */
    -goog.i18n.DateTimeParse.prototype.markAbutStart_ = function() {
    -  // abut parts are continuous numeric parts. abutStart is the switch
    -  // point from non-abut to abut
    -  var abut = false;
    -
    -  for (var i = 0; i < this.patternParts_.length; i++) {
    -    if (this.isNumericField_(this.patternParts_[i])) {
    -      // if next part is not following abut sequence, and isNumericField_
    -      if (!abut && i + 1 < this.patternParts_.length &&
    -          this.isNumericField_(this.patternParts_[i + 1])) {
    -        abut = true;
    -        this.patternParts_[i].abutStart = true;
    -      }
    -    } else {
    -      abut = false;
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Skip space in the string.
    - *
    - * @param {string} text input string.
    - * @param {Array<number>} pos where skip start, and return back where the skip
    - *     stops.
    - * @private
    - */
    -goog.i18n.DateTimeParse.prototype.skipSpace_ = function(text, pos) {
    -  var m = text.substring(pos[0]).match(/^\s+/);
    -  if (m) {
    -    pos[0] += m[0].length;
    -  }
    -};
    -
    -
    -/**
    - * Protected method that converts one field of the input string into a
    - * numeric field value.
    - *
    - * @param {string} text the time text to be parsed.
    - * @param {Array<number>} pos Parse position.
    - * @param {Object} part the pattern part for this field.
    - * @param {number} digitCount when > 0, numeric parsing must obey the count.
    - * @param {goog.i18n.DateTimeParse.MyDate_} cal object that holds parsed value.
    - *
    - * @return {boolean} True if it parses successfully.
    - * @private
    - */
    -goog.i18n.DateTimeParse.prototype.subParse_ =
    -    function(text, pos, part, digitCount, cal) {
    -  this.skipSpace_(text, pos);
    -
    -  var start = pos[0];
    -  var ch = part.text.charAt(0);
    -
    -  // parse integer value if it is a numeric field
    -  var value = -1;
    -  if (this.isNumericField_(part)) {
    -    if (digitCount > 0) {
    -      if ((start + digitCount) > text.length) {
    -        return false;
    -      }
    -      value = this.parseInt_(
    -          text.substring(0, start + digitCount), pos);
    -    } else {
    -      value = this.parseInt_(text, pos);
    -    }
    -  }
    -
    -  switch (ch) {
    -    case 'G': // ERA
    -      value = this.matchString_(text, pos, goog.i18n.DateTimeSymbols.ERAS);
    -      if (value >= 0) {
    -        cal.era = value;
    -      }
    -      return true;
    -    case 'M': // MONTH
    -    case 'L': // STANDALONEMONTH
    -      return this.subParseMonth_(text, pos, cal, value);
    -    case 'E':
    -      return this.subParseDayOfWeek_(text, pos, cal);
    -    case 'a': // AM_PM
    -      value = this.matchString_(text, pos, goog.i18n.DateTimeSymbols.AMPMS);
    -      if (value >= 0) {
    -        cal.ampm = value;
    -      }
    -      return true;
    -    case 'y': // YEAR
    -      return this.subParseYear_(text, pos, start, value, part, cal);
    -    case 'Q': // QUARTER
    -      return this.subParseQuarter_(text, pos, cal, value);
    -    case 'd': // DATE
    -      if (value >= 0) {
    -        cal.day = value;
    -      }
    -      return true;
    -    case 'S': // FRACTIONAL_SECOND
    -      return this.subParseFractionalSeconds_(value, pos, start, cal);
    -    case 'h': // HOUR (1..12)
    -      if (value == 12) {
    -        value = 0;
    -      }
    -    case 'K': // HOUR (0..11)
    -    case 'H': // HOUR_OF_DAY (0..23)
    -    case 'k': // HOUR_OF_DAY (1..24)
    -      if (value >= 0) {
    -        cal.hours = value;
    -      }
    -      return true;
    -    case 'm': // MINUTE
    -      if (value >= 0) {
    -        cal.minutes = value;
    -      }
    -      return true;
    -    case 's': // SECOND
    -      if (value >= 0) {
    -        cal.seconds = value;
    -      }
    -      return true;
    -
    -    case 'z': // ZONE_OFFSET
    -    case 'Z': // TIMEZONE_RFC
    -    case 'v': // TIMEZONE_GENERIC
    -      return this.subparseTimeZoneInGMT_(text, pos, cal);
    -    default:
    -      return false;
    -  }
    -};
    -
    -
    -/**
    - * Parse year field. Year field is special because
    - * 1) two digit year need to be resolved.
    - * 2) we allow year to take a sign.
    - * 3) year field participate in abut processing.
    - *
    - * @param {string} text the time text to be parsed.
    - * @param {Array<number>} pos Parse position.
    - * @param {number} start where this field start.
    - * @param {number} value integer value of year.
    - * @param {Object} part the pattern part for this field.
    - * @param {goog.i18n.DateTimeParse.MyDate_} cal object to hold parsed value.
    - *
    - * @return {boolean} True if successful.
    - * @private
    - */
    -goog.i18n.DateTimeParse.prototype.subParseYear_ =
    -    function(text, pos, start, value, part, cal) {
    -  var ch;
    -  if (value < 0) {
    -    //possible sign
    -    ch = text.charAt(pos[0]);
    -    if (ch != '+' && ch != '-') {
    -      return false;
    -    }
    -    pos[0]++;
    -    value = this.parseInt_(text, pos);
    -    if (value < 0) {
    -      return false;
    -    }
    -    if (ch == '-') {
    -      value = -value;
    -    }
    -  }
    -
    -  // only if 2 digit was actually parsed, and pattern say it has 2 digit.
    -  if (!ch && pos[0] - start == 2 && part.count == 2) {
    -    cal.setTwoDigitYear_(value);
    -  } else {
    -    cal.year = value;
    -  }
    -  return true;
    -};
    -
    -
    -/**
    - * Parse Month field.
    - *
    - * @param {string} text the time text to be parsed.
    - * @param {Array<number>} pos Parse position.
    - * @param {goog.i18n.DateTimeParse.MyDate_} cal object to hold parsed value.
    - * @param {number} value numeric value if this field is expressed using
    - *      numeric pattern, or -1 if not.
    - *
    - * @return {boolean} True if parsing successful.
    - * @private
    - */
    -goog.i18n.DateTimeParse.prototype.subParseMonth_ =
    -    function(text, pos, cal, value) {
    -  // when month is symbols, i.e., MMM, MMMM, LLL or LLLL, value will be -1
    -  if (value < 0) {
    -    // Want to be able to parse both short and long forms.
    -    // Try count == 4 first
    -    var months = goog.i18n.DateTimeSymbols.MONTHS.concat(
    -        goog.i18n.DateTimeSymbols.STANDALONEMONTHS).concat(
    -        goog.i18n.DateTimeSymbols.SHORTMONTHS).concat(
    -        goog.i18n.DateTimeSymbols.STANDALONESHORTMONTHS);
    -    value = this.matchString_(text, pos, months);
    -    if (value < 0) {
    -      return false;
    -    }
    -    // The months variable is multiple of 12, so we have to get the actual
    -    // month index by modulo 12.
    -    cal.month = (value % 12);
    -    return true;
    -  } else {
    -    cal.month = value - 1;
    -    return true;
    -  }
    -};
    -
    -
    -/**
    - * Parse Quarter field.
    - *
    - * @param {string} text the time text to be parsed.
    - * @param {Array<number>} pos Parse position.
    - * @param {goog.i18n.DateTimeParse.MyDate_} cal object to hold parsed value.
    - * @param {number} value numeric value if this field is expressed using
    - *      numeric pattern, or -1 if not.
    - *
    - * @return {boolean} True if parsing successful.
    - * @private
    - */
    -goog.i18n.DateTimeParse.prototype.subParseQuarter_ =
    -    function(text, pos, cal, value) {
    -  // value should be -1, since this is a non-numeric field.
    -  if (value < 0) {
    -    // Want to be able to parse both short and long forms.
    -    // Try count == 4 first:
    -    value = this.matchString_(text, pos, goog.i18n.DateTimeSymbols.QUARTERS);
    -    if (value < 0) { // count == 4 failed, now try count == 3
    -      value = this.matchString_(text, pos,
    -                                goog.i18n.DateTimeSymbols.SHORTQUARTERS);
    -    }
    -    if (value < 0) {
    -      return false;
    -    }
    -    cal.month = value * 3;  // First month of quarter.
    -    cal.day = 1;
    -    return true;
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Parse Day of week field.
    - * @param {string} text the time text to be parsed.
    - * @param {Array<number>} pos Parse position.
    - * @param {goog.i18n.DateTimeParse.MyDate_} cal object to hold parsed value.
    - *
    - * @return {boolean} True if successful.
    - * @private
    - */
    -goog.i18n.DateTimeParse.prototype.subParseDayOfWeek_ =
    -    function(text, pos, cal) {
    -  // Handle both short and long forms.
    -  // Try count == 4 (DDDD) first:
    -  var value = this.matchString_(text, pos, goog.i18n.DateTimeSymbols.WEEKDAYS);
    -  if (value < 0) {
    -    value = this.matchString_(text, pos,
    -                              goog.i18n.DateTimeSymbols.SHORTWEEKDAYS);
    -  }
    -  if (value < 0) {
    -    return false;
    -  }
    -  cal.dayOfWeek = value;
    -  return true;
    -};
    -
    -
    -/**
    - * Parse fractional seconds field.
    - *
    - * @param {number} value parsed numeric value.
    - * @param {Array<number>} pos current parse position.
    - * @param {number} start where this field start.
    - * @param {goog.i18n.DateTimeParse.MyDate_} cal object to hold parsed value.
    - *
    - * @return {boolean} True if successful.
    - * @private
    - */
    -goog.i18n.DateTimeParse.prototype.subParseFractionalSeconds_ =
    -    function(value, pos, start, cal) {
    -  // Fractional seconds left-justify
    -  var len = pos[0] - start;
    -  cal.milliseconds = len < 3 ? value * Math.pow(10, 3 - len) :
    -                               Math.round(value / Math.pow(10, len - 3));
    -  return true;
    -};
    -
    -
    -/**
    - * Parse GMT type timezone.
    - *
    - * @param {string} text the time text to be parsed.
    - * @param {Array<number>} pos Parse position.
    - * @param {goog.i18n.DateTimeParse.MyDate_} cal object to hold parsed value.
    - *
    - * @return {boolean} True if successful.
    - * @private
    - */
    -goog.i18n.DateTimeParse.prototype.subparseTimeZoneInGMT_ =
    -    function(text, pos, cal) {
    -  // First try to parse generic forms such as GMT-07:00. Do this first
    -  // in case localized DateFormatZoneData contains the string "GMT"
    -  // for a zone; in that case, we don't want to match the first three
    -  // characters of GMT+/-HH:MM etc.
    -
    -  // For time zones that have no known names, look for strings
    -  // of the form:
    -  //    GMT[+-]hours:minutes or
    -  //    GMT[+-]hhmm or
    -  //    GMT.
    -  if (text.indexOf('GMT', pos[0]) == pos[0]) {
    -    pos[0] += 3;  // 3 is the length of GMT
    -    return this.parseTimeZoneOffset_(text, pos, cal);
    -  }
    -
    -  // TODO(user): check for named time zones by looking through the locale
    -  // data from the DateFormatZoneData strings. Should parse both short and long
    -  // forms.
    -  // subParseZoneString(text, start, cal);
    -
    -  // As a last resort, look for numeric timezones of the form
    -  // [+-]hhmm as specified by RFC 822.  This code is actually
    -  // a little more permissive than RFC 822.  It will try to do
    -  // its best with numbers that aren't strictly 4 digits long.
    -  return this.parseTimeZoneOffset_(text, pos, cal);
    -};
    -
    -
    -/**
    - * Parse time zone offset.
    - *
    - * @param {string} text the time text to be parsed.
    - * @param {Array<number>} pos Parse position.
    - * @param {goog.i18n.DateTimeParse.MyDate_} cal object to hold parsed value.
    - *
    - * @return {boolean} True if successful.
    - * @private
    - */
    -goog.i18n.DateTimeParse.prototype.parseTimeZoneOffset_ =
    -    function(text, pos, cal) {
    -  if (pos[0] >= text.length) {
    -    cal.tzOffset = 0;
    -    return true;
    -  }
    -
    -  var sign = 1;
    -  switch (text.charAt(pos[0])) {
    -    case '-': sign = -1;  // fall through
    -    case '+': pos[0]++;
    -  }
    -
    -  // Look for hours:minutes or hhmm.
    -  var st = pos[0];
    -  var value = this.parseInt_(text, pos);
    -  if (value < 0) {
    -    return false;
    -  }
    -
    -  var offset;
    -  if (pos[0] < text.length && text.charAt(pos[0]) == ':') {
    -    // This is the hours:minutes case
    -    offset = value * 60;
    -    pos[0]++;
    -    value = this.parseInt_(text, pos);
    -    if (value < 0) {
    -      return false;
    -    }
    -    offset += value;
    -  } else {
    -    // This is the hhmm case.
    -    offset = value;
    -    // Assume "-23".."+23" refers to hours.
    -    if (offset < 24 && (pos[0] - st) <= 2) {
    -      offset *= 60;
    -    } else {
    -      // todo: this looks questionable, should have more error checking
    -      offset = offset % 100 + offset / 100 * 60;
    -    }
    -  }
    -
    -  offset *= sign;
    -  cal.tzOffset = -offset;
    -  return true;
    -};
    -
    -
    -/**
    - * Parse an integer string and return integer value.
    - *
    - * @param {string} text string being parsed.
    - * @param {Array<number>} pos parse position.
    - *
    - * @return {number} Converted integer value or -1 if the integer cannot be
    - *     parsed.
    - * @private
    - */
    -goog.i18n.DateTimeParse.prototype.parseInt_ = function(text, pos) {
    -  // Delocalizes the string containing native digits specified by the locale,
    -  // replaces the native digits with ASCII digits. Leaves other characters.
    -  // This is the reverse operation of localizeNumbers_ in datetimeformat.js.
    -  if (goog.i18n.DateTimeSymbols.ZERODIGIT) {
    -    var parts = [];
    -    for (var i = pos[0]; i < text.length; i++) {
    -      var c = text.charCodeAt(i) - goog.i18n.DateTimeSymbols.ZERODIGIT;
    -      parts.push((0 <= c && c <= 9) ?
    -          String.fromCharCode(c + 0x30) :
    -          text.charAt(i));
    -    }
    -    text = parts.join('');
    -  } else {
    -    text = text.substring(pos[0]);
    -  }
    -
    -  var m = text.match(/^\d+/);
    -  if (!m) {
    -    return -1;
    -  }
    -  pos[0] += m[0].length;
    -  return parseInt(m[0], 10);
    -};
    -
    -
    -/**
    - * Attempt to match the text at a given position against an array of strings.
    - * Since multiple strings in the array may match (for example, if the array
    - * contains "a", "ab", and "abc", all will match the input string "abcd") the
    - * longest match is returned.
    - *
    - * @param {string} text The string to match to.
    - * @param {Array<number>} pos parsing position.
    - * @param {Array<string>} data The string array of matching patterns.
    - *
    - * @return {number} the new start position if matching succeeded; a negative
    - *     number indicating matching failure.
    - * @private
    - */
    -goog.i18n.DateTimeParse.prototype.matchString_ = function(text, pos, data) {
    -  // There may be multiple strings in the data[] array which begin with
    -  // the same prefix (e.g., Cerven and Cervenec (June and July) in Czech).
    -  // We keep track of the longest match, and return that. Note that this
    -  // unfortunately requires us to test all array elements.
    -  var bestMatchLength = 0;
    -  var bestMatch = -1;
    -  var lower_text = text.substring(pos[0]).toLowerCase();
    -  for (var i = 0; i < data.length; i++) {
    -    var len = data[i].length;
    -    // Always compare if we have no match yet; otherwise only compare
    -    // against potentially better matches (longer strings).
    -    if (len > bestMatchLength &&
    -        lower_text.indexOf(data[i].toLowerCase()) == 0) {
    -      bestMatch = i;
    -      bestMatchLength = len;
    -    }
    -  }
    -  if (bestMatch >= 0) {
    -    pos[0] += bestMatchLength;
    -  }
    -  return bestMatch;
    -};
    -
    -
    -
    -/**
    - * This class hold the intermediate parsing result. After all fields are
    - * consumed, final result will be resolved from this class.
    - * @constructor
    - * @private
    - */
    -goog.i18n.DateTimeParse.MyDate_ = function() {};
    -
    -
    -/**
    - * The date's era.
    - * @type {?number}
    - */
    -goog.i18n.DateTimeParse.MyDate_.prototype.era;
    -
    -
    -/**
    - * The date's year.
    - * @type {?number}
    - */
    -goog.i18n.DateTimeParse.MyDate_.prototype.year;
    -
    -
    -/**
    - * The date's month.
    - * @type {?number}
    - */
    -goog.i18n.DateTimeParse.MyDate_.prototype.month;
    -
    -
    -/**
    - * The date's day of month.
    - * @type {?number}
    - */
    -goog.i18n.DateTimeParse.MyDate_.prototype.day;
    -
    -
    -/**
    - * The date's hour.
    - * @type {?number}
    - */
    -goog.i18n.DateTimeParse.MyDate_.prototype.hours;
    -
    -
    -/**
    - * The date's before/afternoon denominator.
    - * @type {?number}
    - */
    -goog.i18n.DateTimeParse.MyDate_.prototype.ampm;
    -
    -
    -/**
    - * The date's minutes.
    - * @type {?number}
    - */
    -goog.i18n.DateTimeParse.MyDate_.prototype.minutes;
    -
    -
    -/**
    - * The date's seconds.
    - * @type {?number}
    - */
    -goog.i18n.DateTimeParse.MyDate_.prototype.seconds;
    -
    -
    -/**
    - * The date's milliseconds.
    - * @type {?number}
    - */
    -goog.i18n.DateTimeParse.MyDate_.prototype.milliseconds;
    -
    -
    -/**
    - * The date's timezone offset.
    - * @type {?number}
    - */
    -goog.i18n.DateTimeParse.MyDate_.prototype.tzOffset;
    -
    -
    -/**
    - * The date's day of week. Sunday is 0, Saturday is 6.
    - * @type {?number}
    - */
    -goog.i18n.DateTimeParse.MyDate_.prototype.dayOfWeek;
    -
    -
    -/**
    - * 2 digit year special handling. Assuming for example that the
    - * defaultCenturyStart is 6/18/1903. This means that two-digit years will be
    - * forced into the range 6/18/1903 to 6/17/2003. As a result, years 00, 01, and
    - * 02 correspond to 2000, 2001, and 2002. Years 04, 05, etc. correspond
    - * to 1904, 1905, etc. If the year is 03, then it is 2003 if the
    - * other fields specify a date before 6/18, or 1903 if they specify a
    - * date afterwards. As a result, 03 is an ambiguous year. All other
    - * two-digit years are unambiguous.
    - *
    - * @param {number} year 2 digit year value before adjustment.
    - * @return {number} disambiguated year.
    - * @private
    - */
    -goog.i18n.DateTimeParse.MyDate_.prototype.setTwoDigitYear_ = function(year) {
    -  var now = new Date();
    -  var defaultCenturyStartYear =
    -      now.getFullYear() - goog.i18n.DateTimeParse.ambiguousYearCenturyStart;
    -  var ambiguousTwoDigitYear = defaultCenturyStartYear % 100;
    -  this.ambiguousYear = (year == ambiguousTwoDigitYear);
    -  year += Math.floor(defaultCenturyStartYear / 100) * 100 +
    -      (year < ambiguousTwoDigitYear ? 100 : 0);
    -  return this.year = year;
    -};
    -
    -
    -/**
    - * Based on the fields set, fill a Date object. For those fields that not
    - * set, use the passed in date object's value.
    - *
    - * @param {goog.date.DateLike} date Date object to be filled.
    - * @param {boolean} validation If true, input string will be checked to make
    - *     sure it is valid.
    - *
    - * @return {boolean} false if fields specify a invalid date.
    - * @private
    - */
    -goog.i18n.DateTimeParse.MyDate_.prototype.calcDate_ =
    -    function(date, validation) {
    -  // year 0 is 1 BC, and so on.
    -  if (this.era != undefined && this.year != undefined &&
    -      this.era == 0 && this.year > 0) {
    -    this.year = -(this.year - 1);
    -  }
    -
    -  if (this.year != undefined) {
    -    date.setFullYear(this.year);
    -  }
    -
    -  // The setMonth and setDate logic is a little tricky. We need to make sure
    -  // day of month is smaller enough so that it won't cause a month switch when
    -  // setting month. For example, if data in date is Nov 30, when month is set
    -  // to Feb, because there is no Feb 30, JS adjust it to Mar 2. So Feb 12 will
    -  // become  Mar 12.
    -  var orgDate = date.getDate();
    -
    -  // Every month has a 1st day, this can actually be anything less than 29.
    -  date.setDate(1);
    -
    -  if (this.month != undefined) {
    -    date.setMonth(this.month);
    -  }
    -
    -  if (this.day != undefined) {
    -    date.setDate(this.day);
    -  } else {
    -    var maxDate =
    -        goog.date.getNumberOfDaysInMonth(date.getFullYear(), date.getMonth());
    -    date.setDate(orgDate > maxDate ? maxDate : orgDate);
    -  }
    -
    -  if (goog.isFunction(date.setHours)) {
    -    if (this.hours == undefined) {
    -      this.hours = date.getHours();
    -    }
    -    // adjust ampm
    -    if (this.ampm != undefined && this.ampm > 0 && this.hours < 12) {
    -      this.hours += 12;
    -    }
    -    date.setHours(this.hours);
    -  }
    -
    -  if (goog.isFunction(date.setMinutes) && this.minutes != undefined) {
    -    date.setMinutes(this.minutes);
    -  }
    -
    -  if (goog.isFunction(date.setSeconds) && this.seconds != undefined) {
    -    date.setSeconds(this.seconds);
    -  }
    -
    -  if (goog.isFunction(date.setMilliseconds) &&
    -      this.milliseconds != undefined) {
    -    date.setMilliseconds(this.milliseconds);
    -  }
    -
    -  // If validation is needed, verify that the uncalculated date fields
    -  // match the calculated date fields.  We do this before we set the
    -  // timezone offset, which will skew all of the dates.
    -  //
    -  // Don't need to check the day of week as it is guaranteed to be
    -  // correct or return false below.
    -  if (validation &&
    -      (this.year != undefined && this.year != date.getFullYear() ||
    -       this.month != undefined && this.month != date.getMonth() ||
    -       this.day != undefined && this.day != date.getDate() ||
    -       this.hours >= 24 || this.minutes >= 60 || this.seconds >= 60 ||
    -       this.milliseconds >= 1000)) {
    -    return false;
    -  }
    -
    -  // adjust time zone
    -  if (this.tzOffset != undefined) {
    -    var offset = date.getTimezoneOffset();
    -    date.setTime(date.getTime() + (this.tzOffset - offset) * 60 * 1000);
    -  }
    -
    -  // resolve ambiguous year if needed
    -  if (this.ambiguousYear) { // the two-digit year == the default start year
    -    var defaultCenturyStart = new Date();
    -    defaultCenturyStart.setFullYear(
    -        defaultCenturyStart.getFullYear() -
    -        goog.i18n.DateTimeParse.ambiguousYearCenturyStart);
    -    if (date.getTime() < defaultCenturyStart.getTime()) {
    -      date.setFullYear(defaultCenturyStart.getFullYear() + 100);
    -    }
    -  }
    -
    -  // dayOfWeek, validation only
    -  if (this.dayOfWeek != undefined) {
    -    if (this.day == undefined) {
    -      // adjust to the nearest day of the week
    -      var adjustment = (7 + this.dayOfWeek - date.getDay()) % 7;
    -      if (adjustment > 3) {
    -        adjustment -= 7;
    -      }
    -      var orgMonth = date.getMonth();
    -      date.setDate(date.getDate() + adjustment);
    -
    -      // don't let it switch month
    -      if (date.getMonth() != orgMonth) {
    -        date.setDate(date.getDate() + (adjustment > 0 ? -7 : 7));
    -      }
    -    } else if (this.dayOfWeek != date.getDay()) {
    -      return false;
    -    }
    -  }
    -  return true;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/datetimeparse_test.html b/src/database/third_party/closure-library/closure/goog/i18n/datetimeparse_test.html
    deleted file mode 100644
    index 56032b0e68e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/datetimeparse_test.html
    +++ /dev/null
    @@ -1,26 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -  All Rights Reserved.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.i18n.DateTimeParse
    -  </title>
    -  <meta charset="utf-8" />
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.i18n.DateTimeParseTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/datetimeparse_test.js b/src/database/third_party/closure-library/closure/goog/i18n/datetimeparse_test.js
    deleted file mode 100644
    index 3f8d788b92f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/datetimeparse_test.js
    +++ /dev/null
    @@ -1,630 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.i18n.DateTimeParseTest');
    -goog.setTestOnly('goog.i18n.DateTimeParseTest');
    -
    -goog.require('goog.date.Date');
    -goog.require('goog.i18n.DateTimeFormat');
    -goog.require('goog.i18n.DateTimeParse');
    -goog.require('goog.i18n.DateTimeSymbols');
    -goog.require('goog.i18n.DateTimeSymbols_en');
    -goog.require('goog.i18n.DateTimeSymbols_fa');
    -goog.require('goog.i18n.DateTimeSymbols_fr');
    -goog.require('goog.i18n.DateTimeSymbols_pl');
    -goog.require('goog.i18n.DateTimeSymbols_zh');
    -goog.require('goog.testing.ExpectedFailures');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en;
    -
    -var expectedFailures;
    -
    -function setUpPage() {
    -  expectedFailures = new goog.testing.ExpectedFailures();
    -}
    -
    -function tearDown() {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en;
    -  expectedFailures.handleTearDown();
    -}
    -
    -// Helper equivalent of assertEquals for dates, with day of month optional
    -function assertDateEquals(expectYear, expectMonth, expectDate, date) {
    -  assertEquals(expectYear, date.getFullYear());
    -  assertEquals(expectMonth, date.getMonth());
    -  if (expectDate)
    -    assertEquals(expectDate, date.getDate());
    -}
    -
    -// Helper equivalent of assertEquals for times, with seconds and milliseconds
    -function assertTimeEquals(expectHour, expectMin, expectSec, expectMilli, date) {
    -  assertEquals(expectHour, date.getHours());
    -  assertEquals(expectMin, date.getMinutes());
    -  if (expectSec)
    -    assertEquals(expectSec, date.getSeconds());
    -  if (expectMilli)
    -    assertEquals(expectMilli, date.getTime() % 1000);
    -}
    -
    -// Helper function, doing parse and assert on dates
    -function assertParsedDateEquals(expectYear, expectMonth, expectDate,
    -    parser, stringToParse, date) {
    -  assertTrue(parser.parse(stringToParse, date) > 0);
    -  assertDateEquals(expectYear, expectMonth, expectDate, date);
    -}
    -
    -// Helper function, doing parse and assert on times
    -function assertParsedTimeEquals(expectHour, expectMin, expectSec, expectMilli,
    -    parser, stringToParse, date) {
    -  assertTrue(parser.parse(stringToParse, date) > 0);
    -  assertTimeEquals(expectHour, expectMin, expectSec, expectMilli, date);
    -}
    -
    -function testNegativeYear() {
    -  var date = new Date();
    -
    -  var parser = new goog.i18n.DateTimeParse('MM/dd, yyyy');
    -  assertParsedDateEquals(1999, 11 - 1, 22, parser, '11/22, 1999', date);
    -  assertParsedDateEquals(-1999, 11 - 1, 22, parser, '11/22, -1999', date);
    -}
    -
    -function testEra() {
    -  // Bug 2350397
    -  if (goog.userAgent.WEBKIT) {
    -    // Bug 2350397 Test seems to be very flaky on Chrome. Disabling it
    -    return;
    -  }
    -
    -  var date = new Date();
    -  var parser = new goog.i18n.DateTimeParse('MM/dd, yyyyG');
    -  assertParsedDateEquals(-1998, 11 - 1, 22, parser, '11/22, 1999BC', date);
    -  assertParsedDateEquals(0, 11 - 1, 22, parser, '11/22, 1BC', date);
    -  assertParsedDateEquals(1999, 11 - 1, 22, parser, '11/22, 1999AD', date);
    -}
    -
    -function testFractionalSeconds() {
    -  var date = new Date();
    -  var parser = new goog.i18n.DateTimeParse('hh:mm:ss.SSS');
    -
    -  assertParsedTimeEquals(11, 12, 13, 956, parser, '11:12:13.956', date);
    -  assertParsedTimeEquals(11, 12, 13, 950, parser, '11:12:13.95', date);
    -  assertParsedTimeEquals(11, 12, 13, 900, parser, '11:12:13.9', date);
    -}
    -
    -function testAmbiguousYear() {
    -  // assume this year is 2006, year 27 to 99 will be interpret as 1927 to 1999
    -  // year 00 to 25 will be 2000 to 2025. Year 26 can be either 1926 or 2026
    -  // depend on the time being parsed and the time when this program runs.
    -  // For example, if the program is run at 2006/03/03 12:12:12, the following
    -  // code should work.
    -  // assertTrue(parser.parse('01/01/26 00:00:00:001', date) > 0);
    -  // assertTrue(date.getFullYear() == 2026 - 1900);
    -  // assertTrue(parser.parse('12/30/26 23:59:59:999', date) > 0);
    -  // assertTrue(date.getFullYear() == 1926 - 1900);
    -
    -  // Since this test can run in any time, some logic needed here.
    -
    -  var futureDate = new Date();
    -  futureDate.setFullYear(futureDate.getFullYear() +
    -      100 - goog.i18n.DateTimeParse.ambiguousYearCenturyStart);
    -  var ambiguousYear = futureDate.getFullYear() % 100;
    -
    -  var parser = new goog.i18n.DateTimeParse('MM/dd/yy HH:mm:ss:SSS');
    -  var date = new Date();
    -
    -  var str = '01/01/' + ambiguousYear + ' 00:00:00:001';
    -  assertTrue(parser.parse(str, date) > 0);
    -  assertEquals(futureDate.getFullYear(), date.getFullYear());
    -
    -  str = '12/31/' + ambiguousYear + ' 23:59:59:999';
    -  assertTrue(parser.parse(str, date) > 0);
    -  assertEquals(futureDate.getFullYear(), date.getFullYear() + 100);
    -
    -  // Test the ability to move the disambiguation century
    -  goog.i18n.DateTimeParse.ambiguousYearCenturyStart = 60;
    -
    -  futureDate = new Date();
    -  futureDate.setFullYear(futureDate.getFullYear() +
    -      100 - goog.i18n.DateTimeParse.ambiguousYearCenturyStart);
    -  ambiguousYear = futureDate.getFullYear() % 100;
    -
    -  var str = '01/01/' + ambiguousYear + ' 00:00:00:001';
    -  assertTrue(parser.parse(str, date) > 0);
    -  assertEquals(futureDate.getFullYear(), date.getFullYear());
    -
    -
    -  str = '12/31/' + ambiguousYear + ' 23:59:59:999';
    -  assertTrue(parser.parse(str, date) > 0);
    -  assertEquals(futureDate.getFullYear(), date.getFullYear() + 100);
    -
    -  // Reset parameter for other test cases
    -  goog.i18n.DateTimeParse.ambiguousYearCenturyStart = 80;
    -}
    -
    -function testLeapYear() {
    -  var date = new Date();
    -
    -  var parser = new goog.i18n.DateTimeParse('MMdd, yyyy');
    -
    -  assertParsedDateEquals(2001, 3 - 1, 1, parser, '0229, 2001', date);
    -  assertParsedDateEquals(2000, 2 - 1, 29, parser, '0229, 2000', date);
    -}
    -
    -function testAbutField() {
    -  var date = new Date();
    -
    -  var parser = new goog.i18n.DateTimeParse('hhmm');
    -  assertParsedTimeEquals(11, 22, undefined, undefined, parser, '1122', date);
    -  assertParsedTimeEquals(1, 22, undefined, undefined, parser, '122', date);
    -
    -  var parser2 = new goog.i18n.DateTimeParse('hhmmss');
    -  assertParsedTimeEquals(11, 22, 33, undefined, parser2, '112233', date);
    -  assertParsedTimeEquals(1, 22, 33, undefined, parser2, '12233', date);
    -
    -  var parser3 = new goog.i18n.DateTimeParse('yyyyMMdd');
    -  assertParsedDateEquals(1999, 12 - 1, 2, parser3, '19991202', date);
    -  assertParsedDateEquals(999, 12 - 1, 2, parser3, '9991202', date);
    -  assertParsedDateEquals(99, 12 - 1, 2, parser3, '991202', date);
    -  assertParsedDateEquals(9, 12 - 1, 2, parser3, '91202', date);
    -}
    -
    -function testYearParsing() {
    -  var date = new Date();
    -
    -  var parser = new goog.i18n.DateTimeParse('yyMMdd');
    -  assertParsedDateEquals(1999, 12 - 1, 2, parser, '991202', date);
    -
    -  var parser2 = new goog.i18n.DateTimeParse('yyyyMMdd');
    -  assertParsedDateEquals(2005, 12 - 1, 2, parser2, '20051202', date);
    -}
    -
    -function testGoogDateParsing() {
    -  var date = new goog.date.Date();
    -
    -  var parser = new goog.i18n.DateTimeParse('yyMMdd');
    -  assertParsedDateEquals(1999, 12 - 1, 2, parser, '991202', date);
    -}
    -
    -function testHourParsing_hh() {
    -  var date = new Date();
    -
    -  var parser = new goog.i18n.DateTimeParse('hhmm');
    -  assertParsedTimeEquals(0, 22, undefined, undefined, parser, '0022', date);
    -  assertParsedTimeEquals(11, 22, undefined, undefined, parser, '1122', date);
    -  assertParsedTimeEquals(0, 22, undefined, undefined, parser, '1222', date);
    -  assertParsedTimeEquals(23, 22, undefined, undefined, parser, '2322', date);
    -  assertParsedTimeEquals(0, 22, undefined, undefined, parser, '2422', date);
    -
    -  var parser2 = new goog.i18n.DateTimeParse('hhmma');
    -  assertParsedTimeEquals(0, 22, undefined, undefined, parser2, '0022am', date);
    -  assertParsedTimeEquals(11, 22, undefined, undefined, parser2, '1122am', date);
    -  assertParsedTimeEquals(0, 22, undefined, undefined, parser2, '1222am', date);
    -  assertParsedTimeEquals(23, 22, undefined, undefined, parser2, '2322am', date);
    -  assertParsedTimeEquals(0, 22, undefined, undefined, parser2, '2422am', date);
    -  assertParsedTimeEquals(12, 22, undefined, undefined, parser2, '0022pm', date);
    -  assertParsedTimeEquals(23, 22, undefined, undefined, parser2, '1122pm', date);
    -  assertParsedTimeEquals(12, 22, undefined, undefined, parser2, '1222pm', date);
    -  assertParsedTimeEquals(23, 22, undefined, undefined, parser2, '2322pm', date);
    -  assertParsedTimeEquals(0, 22, undefined, undefined, parser2, '2422pm', date);
    -}
    -
    -function testHourParsing_KK() {
    -  var date = new Date();
    -
    -  var parser = new goog.i18n.DateTimeParse('KKmm');
    -  assertParsedTimeEquals(0, 22, undefined, undefined, parser, '0022', date);
    -  assertParsedTimeEquals(11, 22, undefined, undefined, parser, '1122', date);
    -  assertParsedTimeEquals(12, 22, undefined, undefined, parser, '1222', date);
    -  assertParsedTimeEquals(23, 22, undefined, undefined, parser, '2322', date);
    -  assertParsedTimeEquals(0, 22, undefined, undefined, parser, '2422', date);
    -
    -  var parser2 = new goog.i18n.DateTimeParse('KKmma');
    -  assertParsedTimeEquals(0, 22, undefined, undefined, parser2, '0022am', date);
    -  assertParsedTimeEquals(11, 22, undefined, undefined, parser2, '1122am', date);
    -  assertParsedTimeEquals(12, 22, undefined, undefined, parser2, '1222am', date);
    -  assertParsedTimeEquals(23, 22, undefined, undefined, parser2, '2322am', date);
    -  assertParsedTimeEquals(0, 22, undefined, undefined, parser2, '2422am', date);
    -  assertParsedTimeEquals(12, 22, undefined, undefined, parser2, '0022pm', date);
    -  assertParsedTimeEquals(23, 22, undefined, undefined, parser2, '1122pm', date);
    -  assertParsedTimeEquals(12, 22, undefined, undefined, parser2, '1222pm', date);
    -  assertParsedTimeEquals(23, 22, undefined, undefined, parser2, '2322pm', date);
    -  assertParsedTimeEquals(0, 22, undefined, undefined, parser2, '2422pm', date);
    -}
    -
    -function testHourParsing_kk() {
    -  var date = new Date();
    -
    -  var parser = new goog.i18n.DateTimeParse('kkmm');
    -  assertParsedTimeEquals(0, 22, undefined, undefined, parser, '0022', date);
    -  assertParsedTimeEquals(11, 22, undefined, undefined, parser, '1122', date);
    -  assertParsedTimeEquals(12, 22, undefined, undefined, parser, '1222', date);
    -  assertParsedTimeEquals(23, 22, undefined, undefined, parser, '2322', date);
    -  assertParsedTimeEquals(0, 22, undefined, undefined, parser, '2422', date);
    -
    -  var parser2 = new goog.i18n.DateTimeParse('kkmma');
    -  assertParsedTimeEquals(0, 22, undefined, undefined, parser2, '0022am', date);
    -  assertParsedTimeEquals(11, 22, undefined, undefined, parser2, '1122am', date);
    -  assertParsedTimeEquals(12, 22, undefined, undefined, parser2, '1222am', date);
    -  assertParsedTimeEquals(23, 22, undefined, undefined, parser2, '2322am', date);
    -  assertParsedTimeEquals(0, 22, undefined, undefined, parser2, '2422am', date);
    -  assertParsedTimeEquals(12, 22, undefined, undefined, parser2, '0022pm', date);
    -  assertParsedTimeEquals(23, 22, undefined, undefined, parser2, '1122pm', date);
    -  assertParsedTimeEquals(12, 22, undefined, undefined, parser2, '1222pm', date);
    -  assertParsedTimeEquals(23, 22, undefined, undefined, parser2, '2322pm', date);
    -  assertParsedTimeEquals(0, 22, undefined, undefined, parser2, '2422pm', date);
    -}
    -
    -function testHourParsing_HH() {
    -  var date = new Date();
    -
    -  var parser = new goog.i18n.DateTimeParse('HHmm');
    -  assertParsedTimeEquals(0, 22, undefined, undefined, parser, '0022', date);
    -  assertParsedTimeEquals(11, 22, undefined, undefined, parser, '1122', date);
    -  assertParsedTimeEquals(12, 22, undefined, undefined, parser, '1222', date);
    -  assertParsedTimeEquals(23, 22, undefined, undefined, parser, '2322', date);
    -  assertParsedTimeEquals(0, 22, undefined, undefined, parser, '2422', date);
    -
    -  var parser2 = new goog.i18n.DateTimeParse('HHmma');
    -  assertParsedTimeEquals(0, 22, undefined, undefined, parser2, '0022am', date);
    -  assertParsedTimeEquals(11, 22, undefined, undefined, parser2, '1122am', date);
    -  assertParsedTimeEquals(12, 22, undefined, undefined, parser2, '1222am', date);
    -  assertParsedTimeEquals(23, 22, undefined, undefined, parser2, '2322am', date);
    -  assertParsedTimeEquals(0, 22, undefined, undefined, parser2, '2422am', date);
    -  assertParsedTimeEquals(12, 22, undefined, undefined, parser2, '0022pm', date);
    -  assertParsedTimeEquals(23, 22, undefined, undefined, parser2, '1122pm', date);
    -  assertParsedTimeEquals(12, 22, undefined, undefined, parser2, '1222pm', date);
    -  assertParsedTimeEquals(23, 22, undefined, undefined, parser2, '2322pm', date);
    -  assertParsedTimeEquals(0, 22, undefined, undefined, parser2, '2422pm', date);
    -}
    -
    -function testEnglishDate() {
    -  var date = new Date();
    -
    -  var parser = new goog.i18n.DateTimeParse('yyyy MMM dd hh:mm');
    -
    -  // Fails in Safari4/Chrome Winxp because of infrastructure issues, temporarily
    -  // disabled. See b/4274778.
    -  expectedFailures.expectFailureFor(goog.userAgent.WEBKIT);
    -  try {
    -    assertParsedDateEquals(2006, 7 - 1, 10, parser, '2006 Jul 10 15:44', date);
    -    assertTimeEquals(15, 44, undefined, undefined, date);
    -  } catch (e) {
    -    expectedFailures.handleException(e);
    -  }
    -}
    -
    -function testChineseDate() {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_zh;
    -
    -  // Javascript month start from 0, July is 7 - 1
    -  var date = new Date(2006, 7 - 1, 24, 12, 12, 12, 0);
    -  var formatter = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimeFormat.Format.FULL_DATE);
    -  var dateStr = formatter.format(date);
    -  var parser = new goog.i18n.DateTimeParse(
    -      goog.i18n.DateTimeFormat.Format.FULL_DATE);
    -
    -  assertParsedDateEquals(2006, 7 - 1, 24, parser, dateStr, date);
    -
    -  parser = new goog.i18n.DateTimeParse(
    -      goog.i18n.DateTimeFormat.Format.LONG_DATE);
    -  assertParsedDateEquals(
    -      2006, 7 - 1, 24, parser, '2006\u5E747\u670824\u65E5', date);
    -
    -  parser = new goog.i18n.DateTimeParse(
    -      goog.i18n.DateTimeFormat.Format.FULL_TIME);
    -  assertTrue(parser.parse('GMT-07:00\u4E0B\u534803:26:28', date) > 0);
    -
    -  // Fails in Safari4/Chrome Winxp because of infrastructure issues, temporarily
    -  // disabled. See b/4274778.
    -  expectedFailures.expectFailureFor(goog.userAgent.WEBKIT);
    -  try {
    -    assertEquals(
    -        22, (24 + date.getHours() + date.getTimezoneOffset() / 60) % 24);
    -    assertEquals(26, date.getMinutes());
    -    assertEquals(28, date.getSeconds());
    -  } catch (e) {
    -    expectedFailures.handleException(e);
    -  }
    -
    -}
    -
    -// For languages with goog.i18n.DateTimeSymbols.ZERODIGIT defined, the int
    -// digits are localized by the locale in datetimeformat.js. This test case is
    -// for parsing dates with such native digits.
    -function testDatesWithNativeDigits() {
    -  // Language Arabic is one example with
    -  // goog.i18n.DateTimeSymbols.ZERODIGIT defined.
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fa;
    -
    -  // Javascript month starts from 0, July is 7 - 1
    -  var date = new Date(2006, 7 - 1, 24, 12, 12, 12, 0);
    -  var formatter = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimeFormat.Format.FULL_DATE);
    -  dateStr = formatter.format(date);
    -  var parser = new goog.i18n.DateTimeParse(
    -      goog.i18n.DateTimeFormat.Format.FULL_DATE);
    -
    -  assertParsedDateEquals(2006, 7 - 1, 24, parser, dateStr, date);
    -
    -  date = new Date(2006, 7 - 1, 24);
    -  formatter = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimeFormat.Format.SHORT_DATE);
    -  dateStr = formatter.format(date);
    -  parser = new goog.i18n.DateTimeParse(
    -      goog.i18n.DateTimeFormat.Format.SHORT_DATE);
    -
    -  assertParsedDateEquals(2006, 7 - 1, 24, parser, dateStr, date);
    -
    -  date = new Date();
    -
    -  parser = new goog.i18n.DateTimeParse('y/MM/dd H:mm:ss٫SS');
    -  assertParsedDateEquals(2006, 6, 27, parser, '۲۰۰۶/۰۷/۲۷ ۱۳:۱۰:۱۰٫۲۵', date);
    -}
    -
    -function testTimeZone() {
    -  var date = new Date();
    -
    -  var parser = new goog.i18n.DateTimeParse('MM/dd/yyyy, hh:mm:ss zzz');
    -  assertTrue(parser.parse('07/21/2003, 11:22:33 GMT-0700', date) > 0);
    -  var hourGmtMinus07 = date.getHours();
    -
    -  assertTrue(parser.parse('07/21/2003, 11:22:33 GMT-0600', date) > 0);
    -  var hourGmtMinus06 = date.getHours();
    -  assertEquals(1, (hourGmtMinus07 + 24 - hourGmtMinus06) % 24);
    -
    -  assertTrue(parser.parse('07/21/2003, 11:22:33 GMT-0800', date) > 0);
    -  var hourGmtMinus08 = date.getHours();
    -  assertEquals(1, (hourGmtMinus08 + 24 - hourGmtMinus07) % 24);
    -
    -  assertTrue(parser.parse('07/21/2003, 23:22:33 GMT-0800', date) > 0);
    -  assertEquals((date.getHours() + 24 - hourGmtMinus07) % 24, 13);
    -
    -  assertTrue(parser.parse('07/21/2003, 11:22:33 GMT+0800', date) > 0);
    -  var hourGmt08 = date.getHours();
    -  assertEquals(16, (hourGmtMinus08 + 24 - hourGmt08) % 24);
    -
    -  assertTrue(parser.parse('07/21/2003, 11:22:33 GMT0800', date) > 0);
    -  assertEquals(hourGmt08, date.getHours());
    -
    -  // 'foo' is not a timezone
    -  assertFalse(parser.parse('07/21/2003, 11:22:33 foo', date) > 0);
    -}
    -
    -function testWeekDay() {
    -  var date = new Date();
    -  var parser = new goog.i18n.DateTimeParse('EEEE, MM/dd/yyyy');
    -
    -  assertTrue(parser.parse('Wednesday, 08/16/2006', date) > 0);
    -  assertDateEquals(2006, 8 - 1, 16, date);
    -  assertTrue(parser.parse('Tuesday, 08/16/2006', date) == 0);
    -  assertTrue(parser.parse('Thursday, 08/16/2006', date) == 0);
    -  assertTrue(parser.parse('Wed, 08/16/2006', date) > 0);
    -  assertTrue(parser.parse('Wasdfed, 08/16/2006', date) == 0);
    -
    -  date.setDate(25);
    -  parser = new goog.i18n.DateTimeParse('EEEE, MM/yyyy');
    -  assertTrue(parser.parse('Wed, 09/2006', date) > 0);
    -  assertEquals(27, date.getDate());
    -
    -  date.setDate(30);
    -  assertTrue(parser.parse('Wed, 09/2006', date) > 0);
    -  assertEquals(27, date.getDate());
    -  date.setDate(30);
    -  assertTrue(parser.parse('Mon, 09/2006', date) > 0);
    -  assertEquals(25, date.getDate());
    -}
    -
    -function testStrictParse() {
    -  var date = new Date();
    -
    -  var parser = new goog.i18n.DateTimeParse('yyyy/MM/dd');
    -  assertTrue(parser.strictParse('2000/13/10', date) == 0);
    -  assertTrue(parser.strictParse('2000/13/40', date) == 0);
    -  assertTrue(parser.strictParse('2000/11/10', date) > 0);
    -  assertDateEquals(2000, 11 - 1, 10, date);
    -
    -  parser = new goog.i18n.DateTimeParse('yy/MM/dd');
    -  assertTrue(parser.strictParse('00/11/10', date) > 0);
    -  assertTrue(parser.strictParse('99/11/10', date) > 0);
    -  assertTrue(parser.strictParse('00/13/10', date) == 0);
    -  assertTrue(parser.strictParse('00/11/32', date) == 0);
    -  assertTrue(parser.strictParse('1900/11/2', date) > 0);
    -
    -  parser = new goog.i18n.DateTimeParse('hh:mm');
    -  assertTrue(parser.strictParse('15:44', date) > 0);
    -  assertTrue(parser.strictParse('25:44', date) == 0);
    -  assertTrue(parser.strictParse('15:64', date) == 0);
    -
    -  // leap year
    -  parser = new goog.i18n.DateTimeParse('yy/MM/dd');
    -  assertTrue(parser.strictParse('00/02/29', date) > 0);
    -  assertTrue(parser.strictParse('01/02/29', date) == 0);
    -}
    -
    -function testPartialParses() {
    -  var date = new Date(0);
    -  var parser = new goog.i18n.DateTimeParse('h:mma');
    -  assertTrue(parser.parse('5:', date) > 0);
    -  assertEquals(5, date.getHours());
    -  assertEquals(0, date.getMinutes());
    -
    -  date = new Date(0);
    -  assertTrue(parser.parse('5:44pm', date) > 0);
    -  assertEquals(17, date.getHours());
    -  assertEquals(44, date.getMinutes());
    -
    -  date = new Date(0);
    -  assertTrue(parser.parse('5:44ym', date) > 0);
    -  assertEquals(5, date.getHours());
    -  assertEquals(44, date.getMinutes());
    -
    -  parser = new goog.i18n.DateTimeParse('mm:ss');
    -  date = new Date(0);
    -  assertTrue(parser.parse('15:', date) > 0);
    -  assertEquals(15, date.getMinutes());
    -  assertEquals(0, date.getSeconds());
    -}
    -
    -function testEnglishQuarter() {
    -  var date = new Date();
    -  var parser = new goog.i18n.DateTimeParse('QQQQ yyyy');
    -
    -  // Fails in Safari4/Chrome Winxp because of infrastructure issues, temporarily
    -  // disabled. See b/4274778.
    -  expectedFailures.expectFailureFor(goog.userAgent.WEBKIT);
    -  try {
    -    assertParsedDateEquals(2009, 0, 1, parser, '1st quarter 2009', date);
    -  } catch (e) {
    -    expectedFailures.handleException(e);
    -  }
    -}
    -
    -function testEnglishShortQuarter() {
    -  var date = new Date();
    -  var parser = new goog.i18n.DateTimeParse('yyyyQQ');
    -
    -  // Fails in Safari4/Chrome Winxp because of infrastructure issues, temporarily
    -  // disabled. See b/4274778.
    -  expectedFailures.expectFailureFor(goog.userAgent.WEBKIT);
    -  try {
    -    assertParsedDateEquals(2006, 4 - 1, 1, parser, '2006Q2', date);
    -  } catch (e) {
    -    expectedFailures.handleException(e);
    -  }
    -}
    -
    -function testFrenchShortQuarter() {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr;
    -
    -  var date = new Date();
    -  var parser = new goog.i18n.DateTimeParse('yyyyQQ');
    -  assertParsedDateEquals(2009, 7 - 1, 1, parser, '2009T3', date);
    -}
    -
    -function testDateTime() {
    -  var dateOrg = new Date(2006, 7 - 1, 24, 17, 21, 42, 0);
    -
    -  var formatter = new goog.i18n.DateTimeFormat(
    -      goog.i18n.DateTimeFormat.Format.MEDIUM_DATETIME);
    -  dateStr = formatter.format(dateOrg);
    -
    -  var parser = new goog.i18n.DateTimeParse(
    -      goog.i18n.DateTimeFormat.Format.MEDIUM_DATETIME);
    -  var dateParsed = new Date();
    -
    -  assertParsedDateEquals(dateOrg.getFullYear(), dateOrg.getMonth(),
    -      dateOrg.getDate(), parser, dateStr, dateParsed);
    -  assertTimeEquals(dateOrg.getHours(), dateOrg.getMinutes(),
    -      dateOrg.getSeconds(), undefined, dateParsed);
    -}
    -
    -
    -/** @bug 10075434 */
    -function testParseDateWithOverflow() {
    -
    -  // We force the initial day of month to 30 so that it will always cause an
    -  // overflow in February, no matter if it is a leap year or not.
    -  var dateOrg = new Date(2006, 7 - 1, 30, 17, 21, 42, 0);
    -  var dateParsed;  // this will receive the result of the parsing
    -
    -  var parserMonthYear = new goog.i18n.DateTimeParse('MMMM yyyy');
    -
    -  // The API can be a bit confusing, as this date is both input and output.
    -  // Benefit: fields that don't come from parsing are preserved.
    -  // In the typical use case, dateParsed = new Date()
    -  // and when you parse "February 3" the year is implied as "this year"
    -  // This works as intended.
    -  // But because of this we will initialize dateParsed from dateOrg
    -  // before every test (because the previous test changes it).
    -
    -  dateParsed = new Date(dateOrg.getTime());
    -  // if preserved February 30 overflows, so we get the closest February day, 28
    -  assertParsedDateEquals(
    -      2013, 2 - 1, 28, parserMonthYear, 'February 2013', dateParsed);
    -
    -  // Same as above, but the last February date is 29 (leap year)
    -  dateParsed = new Date(dateOrg.getTime());
    -  assertParsedDateEquals(
    -      2012, 2 - 1, 29, parserMonthYear, 'February 2012', dateParsed);
    -
    -  // Same as above, but no overflow (Match has 31 days, the parsed 30 is OK)
    -  dateParsed = new Date(dateOrg.getTime());
    -  assertParsedDateEquals(
    -      2013, 3 - 1, 30, parserMonthYear, 'March 2013', dateParsed);
    -
    -  // The pattern does not expect the day of month, so 12 is interpreted
    -  // as year, 12. May be weird, but this is the original behavior.
    -  // The overflow for leap year applies, same as above.
    -  dateParsed = new Date(dateOrg.getTime());
    -  assertParsedDateEquals(
    -      12, 2 - 1, 29, parserMonthYear, 'February 12, 2013', dateParsed);
    -
    -  // We make sure that the fix did not break parsing with day of month present
    -  var parserMonthDayYear = new goog.i18n.DateTimeParse('MMMM d, yyyy');
    -
    -  dateParsed = new Date(dateOrg.getTime());
    -  assertParsedDateEquals(
    -      2012, 2 - 1, 12, parserMonthDayYear, 'February 12, 2012', dateParsed);
    -
    -  // The current behavior when parsing 'February 31, 2012' is to
    -  // return 'March 2, 2012'
    -  // Expected or not, we make sure the fix does not break this.
    -  assertParsedDateEquals(
    -      2012, 3 - 1, 2, parserMonthDayYear, 'February 31, 2012', dateParsed);
    -}
    -
    -
    -/** @bug 9901750 */
    -function testStandaloneMonthPattern() {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_pl;
    -  var date1 = new goog.date.Date(2006, 7 - 1);
    -  var date2 = new goog.date.Date();
    -  var formatter =
    -      new goog.i18n.DateTimeFormat('LLLL yyyy');
    -  var parser =
    -      new goog.i18n.DateTimeParse('LLLL yyyy');
    -  var dateStr = formatter.format(date1);
    -  assertParsedDateEquals(
    -      date1.getFullYear(), date1.getMonth(), undefined, parser, dateStr, date2);
    -
    -  // Sanity tests to make sure MMM... (and LLL...) formats still work for
    -  // different locales.
    -  var symbols = [
    -    goog.i18n.DateTimeSymbols_en,
    -    goog.i18n.DateTimeSymbols_pl
    -  ];
    -
    -  for (var i = 0; i < symbols.length; i++) {
    -    goog.i18n.DateTimeSymbols = symbols[i];
    -    var tests = {
    -      'MMMM yyyy': goog.i18n.DateTimeSymbols.MONTHS,
    -      'LLLL yyyy': goog.i18n.DateTimeSymbols.STANDALONEMONTHS,
    -      'MMM yyyy': goog.i18n.DateTimeSymbols.SHORTMONTHS,
    -      'LLL yyyy': goog.i18n.DateTimeSymbols.STANDALONESHORTMONTHS
    -    };
    -
    -    for (var format in tests) {
    -      var parser = new goog.i18n.DateTimeParse(format);
    -      var months = tests[format];
    -      for (var m = 0; m < months.length; m++) {
    -        var dateStr = months[m] + ' 2006';
    -        var date = new goog.date.Date();
    -        assertParsedDateEquals(2006, m, undefined, parser, dateStr, date);
    -      }
    -    }
    -  }
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/datetimepatterns.js b/src/database/third_party/closure-library/closure/goog/i18n/datetimepatterns.js
    deleted file mode 100644
    index 3d99a3aef95..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/datetimepatterns.js
    +++ /dev/null
    @@ -1,2520 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Extended date/time patterns.
    - *
    - * This file is autogenerated by script.  See
    - * http://go/generate_datetime_pattern.cc
    - *
    - * This file is generated using ICU's implementation of
    - * DateTimePatternGenerator. The whole set has two files:
    - * datetimepatterns.js and datetimepatternsext.js. The former covers
    - * frequently used locales, the latter covers the rest. There won't be any
    - * difference in compiled code, but some developing environments have
    - * difficulty in dealing large js files. So we do the separation.
    -
    - * Only locales that can be enumerated in ICU are supported. For the rest
    - * of the locales, it will fallback to 'en'.
    - * The code is designed to work with Closure compiler using
    - * ADVANCED_OPTIMIZATIONS. We will continue to add popular date/time
    - * patterns over time. There is no intention cover all possible
    - * usages. If simple pattern works fine, it won't be covered here either.
    - * For example, pattern 'MMM' will work well to get short month name for
    - * almost all locales thus won't be included here.
    - */
    -
    -/* File generated from CLDR ver. 26.0 */
    -
    -goog.provide('goog.i18n.DateTimePatterns');
    -
    -goog.provide('goog.i18n.DateTimePatterns_af');
    -goog.provide('goog.i18n.DateTimePatterns_am');
    -goog.provide('goog.i18n.DateTimePatterns_ar');
    -goog.provide('goog.i18n.DateTimePatterns_az');
    -goog.provide('goog.i18n.DateTimePatterns_bg');
    -goog.provide('goog.i18n.DateTimePatterns_bn');
    -goog.provide('goog.i18n.DateTimePatterns_br');
    -goog.provide('goog.i18n.DateTimePatterns_ca');
    -goog.provide('goog.i18n.DateTimePatterns_chr');
    -goog.provide('goog.i18n.DateTimePatterns_cs');
    -goog.provide('goog.i18n.DateTimePatterns_cy');
    -goog.provide('goog.i18n.DateTimePatterns_da');
    -goog.provide('goog.i18n.DateTimePatterns_de');
    -goog.provide('goog.i18n.DateTimePatterns_de_AT');
    -goog.provide('goog.i18n.DateTimePatterns_de_CH');
    -goog.provide('goog.i18n.DateTimePatterns_el');
    -goog.provide('goog.i18n.DateTimePatterns_en');
    -goog.provide('goog.i18n.DateTimePatterns_en_AU');
    -goog.provide('goog.i18n.DateTimePatterns_en_GB');
    -goog.provide('goog.i18n.DateTimePatterns_en_IE');
    -goog.provide('goog.i18n.DateTimePatterns_en_IN');
    -goog.provide('goog.i18n.DateTimePatterns_en_SG');
    -goog.provide('goog.i18n.DateTimePatterns_en_US');
    -goog.provide('goog.i18n.DateTimePatterns_en_ZA');
    -goog.provide('goog.i18n.DateTimePatterns_es');
    -goog.provide('goog.i18n.DateTimePatterns_es_419');
    -goog.provide('goog.i18n.DateTimePatterns_es_ES');
    -goog.provide('goog.i18n.DateTimePatterns_et');
    -goog.provide('goog.i18n.DateTimePatterns_eu');
    -goog.provide('goog.i18n.DateTimePatterns_fa');
    -goog.provide('goog.i18n.DateTimePatterns_fi');
    -goog.provide('goog.i18n.DateTimePatterns_fil');
    -goog.provide('goog.i18n.DateTimePatterns_fr');
    -goog.provide('goog.i18n.DateTimePatterns_fr_CA');
    -goog.provide('goog.i18n.DateTimePatterns_ga');
    -goog.provide('goog.i18n.DateTimePatterns_gl');
    -goog.provide('goog.i18n.DateTimePatterns_gsw');
    -goog.provide('goog.i18n.DateTimePatterns_gu');
    -goog.provide('goog.i18n.DateTimePatterns_haw');
    -goog.provide('goog.i18n.DateTimePatterns_he');
    -goog.provide('goog.i18n.DateTimePatterns_hi');
    -goog.provide('goog.i18n.DateTimePatterns_hr');
    -goog.provide('goog.i18n.DateTimePatterns_hu');
    -goog.provide('goog.i18n.DateTimePatterns_hy');
    -goog.provide('goog.i18n.DateTimePatterns_id');
    -goog.provide('goog.i18n.DateTimePatterns_in');
    -goog.provide('goog.i18n.DateTimePatterns_is');
    -goog.provide('goog.i18n.DateTimePatterns_it');
    -goog.provide('goog.i18n.DateTimePatterns_iw');
    -goog.provide('goog.i18n.DateTimePatterns_ja');
    -goog.provide('goog.i18n.DateTimePatterns_ka');
    -goog.provide('goog.i18n.DateTimePatterns_kk');
    -goog.provide('goog.i18n.DateTimePatterns_km');
    -goog.provide('goog.i18n.DateTimePatterns_kn');
    -goog.provide('goog.i18n.DateTimePatterns_ko');
    -goog.provide('goog.i18n.DateTimePatterns_ky');
    -goog.provide('goog.i18n.DateTimePatterns_ln');
    -goog.provide('goog.i18n.DateTimePatterns_lo');
    -goog.provide('goog.i18n.DateTimePatterns_lt');
    -goog.provide('goog.i18n.DateTimePatterns_lv');
    -goog.provide('goog.i18n.DateTimePatterns_mk');
    -goog.provide('goog.i18n.DateTimePatterns_ml');
    -goog.provide('goog.i18n.DateTimePatterns_mn');
    -goog.provide('goog.i18n.DateTimePatterns_mo');
    -goog.provide('goog.i18n.DateTimePatterns_mr');
    -goog.provide('goog.i18n.DateTimePatterns_ms');
    -goog.provide('goog.i18n.DateTimePatterns_mt');
    -goog.provide('goog.i18n.DateTimePatterns_my');
    -goog.provide('goog.i18n.DateTimePatterns_nb');
    -goog.provide('goog.i18n.DateTimePatterns_ne');
    -goog.provide('goog.i18n.DateTimePatterns_nl');
    -goog.provide('goog.i18n.DateTimePatterns_no');
    -goog.provide('goog.i18n.DateTimePatterns_no_NO');
    -goog.provide('goog.i18n.DateTimePatterns_or');
    -goog.provide('goog.i18n.DateTimePatterns_pa');
    -goog.provide('goog.i18n.DateTimePatterns_pl');
    -goog.provide('goog.i18n.DateTimePatterns_pt');
    -goog.provide('goog.i18n.DateTimePatterns_pt_BR');
    -goog.provide('goog.i18n.DateTimePatterns_pt_PT');
    -goog.provide('goog.i18n.DateTimePatterns_ro');
    -goog.provide('goog.i18n.DateTimePatterns_ru');
    -goog.provide('goog.i18n.DateTimePatterns_sh');
    -goog.provide('goog.i18n.DateTimePatterns_si');
    -goog.provide('goog.i18n.DateTimePatterns_sk');
    -goog.provide('goog.i18n.DateTimePatterns_sl');
    -goog.provide('goog.i18n.DateTimePatterns_sq');
    -goog.provide('goog.i18n.DateTimePatterns_sr');
    -goog.provide('goog.i18n.DateTimePatterns_sv');
    -goog.provide('goog.i18n.DateTimePatterns_sw');
    -goog.provide('goog.i18n.DateTimePatterns_ta');
    -goog.provide('goog.i18n.DateTimePatterns_te');
    -goog.provide('goog.i18n.DateTimePatterns_th');
    -goog.provide('goog.i18n.DateTimePatterns_tl');
    -goog.provide('goog.i18n.DateTimePatterns_tr');
    -goog.provide('goog.i18n.DateTimePatterns_uk');
    -goog.provide('goog.i18n.DateTimePatterns_ur');
    -goog.provide('goog.i18n.DateTimePatterns_uz');
    -goog.provide('goog.i18n.DateTimePatterns_vi');
    -goog.provide('goog.i18n.DateTimePatterns_zh');
    -goog.provide('goog.i18n.DateTimePatterns_zh_CN');
    -goog.provide('goog.i18n.DateTimePatterns_zh_HK');
    -goog.provide('goog.i18n.DateTimePatterns_zh_TW');
    -goog.provide('goog.i18n.DateTimePatterns_zu');
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale af.
    - */
    -goog.i18n.DateTimePatterns_af = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd-MM',
    -  MONTH_DAY_MEDIUM: 'd MMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale am.
    - */
    -goog.i18n.DateTimePatterns_am = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE፣ MMM d y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ar.
    - */
    -goog.i18n.DateTimePatterns_ar = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/‏M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale az.
    - */
    -goog.i18n.DateTimePatterns_az = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'd MMM, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'd MMM y, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale bg.
    - */
    -goog.i18n.DateTimePatterns_bg = {
    -  YEAR_FULL: 'y \'г\'.',
    -  YEAR_FULL_WITH_ERA: 'y \'г\'. G',
    -  YEAR_MONTH_ABBR: 'MM.y \'г\'.',
    -  YEAR_MONTH_FULL: 'MMMM y \'г\'.',
    -  MONTH_DAY_ABBR: 'd.MM',
    -  MONTH_DAY_FULL: 'd MMMM',
    -  MONTH_DAY_SHORT: 'd.MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd.MM.y \'г\'.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d.MM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d.MM.y \'г\'.',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale bn.
    - */
    -goog.i18n.DateTimePatterns_bn = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale br.
    - */
    -goog.i18n.DateTimePatterns_br = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ca.
    - */
    -goog.i18n.DateTimePatterns_ca = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'LLL \'de\' y',
    -  YEAR_MONTH_FULL: 'LLLL \'de\' y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale chr.
    - */
    -goog.i18n.DateTimePatterns_chr = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale cs.
    - */
    -goog.i18n.DateTimePatterns_cs = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'LLLL y',
    -  YEAR_MONTH_FULL: 'LLLL y',
    -  MONTH_DAY_ABBR: 'd. M.',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd. M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. M. y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. M.',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d. M. y',
    -  DAY_ABBR: 'd.'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale cy.
    - */
    -goog.i18n.DateTimePatterns_cy = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale da.
    - */
    -goog.i18n.DateTimePatterns_da = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d. MMM y',
    -  DAY_ABBR: 'd.'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale de.
    - */
    -goog.i18n.DateTimePatterns_de = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale de_AT.
    - */
    -goog.i18n.DateTimePatterns_de_AT = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale de_CH.
    - */
    -goog.i18n.DateTimePatterns_de_CH = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale el.
    - */
    -goog.i18n.DateTimePatterns_el = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en.
    - */
    -goog.i18n.DateTimePatterns_en = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_AU.
    - */
    -goog.i18n.DateTimePatterns_en_AU = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_GB.
    - */
    -goog.i18n.DateTimePatterns_en_GB = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_IE.
    - */
    -goog.i18n.DateTimePatterns_en_IE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_IN.
    - */
    -goog.i18n.DateTimePatterns_en_IN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_SG.
    - */
    -goog.i18n.DateTimePatterns_en_SG = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_US.
    - */
    -goog.i18n.DateTimePatterns_en_US = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_ZA.
    - */
    -goog.i18n.DateTimePatterns_en_ZA = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'dd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'MM/dd',
    -  MONTH_DAY_MEDIUM: 'dd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'dd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE dd MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, dd MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale es.
    - */
    -goog.i18n.DateTimePatterns_es = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd \'de\' MMM',
    -  MONTH_DAY_FULL: 'dd \'de\' MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d \'de\' MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale es_419.
    - */
    -goog.i18n.DateTimePatterns_es_419 = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd \'de\' MMM',
    -  MONTH_DAY_FULL: 'dd-MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d \'de\' MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale es_ES.
    - */
    -goog.i18n.DateTimePatterns_es_ES = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd \'de\' MMM',
    -  MONTH_DAY_FULL: 'dd \'de\' MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d \'de\' MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale et.
    - */
    -goog.i18n.DateTimePatterns_et = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale eu.
    - */
    -goog.i18n.DateTimePatterns_eu = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y(\'e\')\'ko\' MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fa.
    - */
    -goog.i18n.DateTimePatterns_fa = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd LLL',
    -  MONTH_DAY_FULL: 'dd LLLL',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'd LLLL',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d LLL',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fi.
    - */
    -goog.i18n.DateTimePatterns_fi = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'LLL y',
    -  YEAR_MONTH_FULL: 'LLLL y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'ccc d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d. MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fil.
    - */
    -goog.i18n.DateTimePatterns_fil = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr.
    - */
    -goog.i18n.DateTimePatterns_fr = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_CA.
    - */
    -goog.i18n.DateTimePatterns_fr_CA = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'M-d',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ga.
    - */
    -goog.i18n.DateTimePatterns_ga = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale gl.
    - */
    -goog.i18n.DateTimePatterns_gl = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd-M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale gsw.
    - */
    -goog.i18n.DateTimePatterns_gsw = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale gu.
    - */
    -goog.i18n.DateTimePatterns_gu = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale haw.
    - */
    -goog.i18n.DateTimePatterns_haw = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale he.
    - */
    -goog.i18n.DateTimePatterns_he = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd בMMM',
    -  MONTH_DAY_FULL: 'dd בMMMM',
    -  MONTH_DAY_SHORT: 'd.M',
    -  MONTH_DAY_MEDIUM: 'd בMMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd בMMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d בMMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d בMMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale hi.
    - */
    -goog.i18n.DateTimePatterns_hi = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale hr.
    - */
    -goog.i18n.DateTimePatterns_hr = {
    -  YEAR_FULL: 'y.',
    -  YEAR_FULL_WITH_ERA: 'y. G',
    -  YEAR_MONTH_ABBR: 'LLL y.',
    -  YEAR_MONTH_FULL: 'LLLL y.',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y.',
    -  DAY_ABBR: 'd.'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale hu.
    - */
    -goog.i18n.DateTimePatterns_hu = {
    -  YEAR_FULL: 'y.',
    -  YEAR_FULL_WITH_ERA: 'G y.',
    -  YEAR_MONTH_ABBR: 'y. MMM',
    -  YEAR_MONTH_FULL: 'y. MMMM',
    -  MONTH_DAY_ABBR: 'MMM d.',
    -  MONTH_DAY_FULL: 'MMMM dd.',
    -  MONTH_DAY_SHORT: 'M. d.',
    -  MONTH_DAY_MEDIUM: 'MMMM d.',
    -  MONTH_DAY_YEAR_MEDIUM: 'y. MMM d.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d., EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y. MMM d., EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale hy.
    - */
    -goog.i18n.DateTimePatterns_hy = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G yթ.',
    -  YEAR_MONTH_ABBR: 'yթ. LLL',
    -  YEAR_MONTH_FULL: 'yթ. LLLL',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, yթ.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'd MMM, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'yթ. MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale id.
    - */
    -goog.i18n.DateTimePatterns_id = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale in.
    - */
    -goog.i18n.DateTimePatterns_in = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale is.
    - */
    -goog.i18n.DateTimePatterns_is = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale it.
    - */
    -goog.i18n.DateTimePatterns_it = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale iw.
    - */
    -goog.i18n.DateTimePatterns_iw = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd בMMM',
    -  MONTH_DAY_FULL: 'dd בMMMM',
    -  MONTH_DAY_SHORT: 'd.M',
    -  MONTH_DAY_MEDIUM: 'd בMMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd בMMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d בMMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d בMMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ja.
    - */
    -goog.i18n.DateTimePatterns_ja = {
    -  YEAR_FULL: 'y年',
    -  YEAR_FULL_WITH_ERA: 'Gy年',
    -  YEAR_MONTH_ABBR: 'y年M月',
    -  YEAR_MONTH_FULL: 'y年M月',
    -  MONTH_DAY_ABBR: 'M月d日',
    -  MONTH_DAY_FULL: 'M月dd日',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'M月d日',
    -  MONTH_DAY_YEAR_MEDIUM: 'y年M月d日',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'M月d日(EEE)',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y年M月d日(EEE)',
    -  DAY_ABBR: 'd日'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ka.
    - */
    -goog.i18n.DateTimePatterns_ka = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM, y',
    -  YEAR_MONTH_FULL: 'MMMM, y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd.M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale kk.
    - */
    -goog.i18n.DateTimePatterns_kk = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd-MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale km.
    - */
    -goog.i18n.DateTimePatterns_km = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y នៃ G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd-M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale kn.
    - */
    -goog.i18n.DateTimePatterns_kn = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d,y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ko.
    - */
    -goog.i18n.DateTimePatterns_ko = {
    -  YEAR_FULL: 'y년',
    -  YEAR_FULL_WITH_ERA: 'G y년',
    -  YEAR_MONTH_ABBR: 'y년 MMM',
    -  YEAR_MONTH_FULL: 'y년 MMMM',
    -  MONTH_DAY_ABBR: 'MMM d일',
    -  MONTH_DAY_FULL: 'MMMM dd일',
    -  MONTH_DAY_SHORT: 'M. d.',
    -  MONTH_DAY_MEDIUM: 'MMMM d일',
    -  MONTH_DAY_YEAR_MEDIUM: 'y년 MMM d일',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d일 (EEE)',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y년 MMM d일 (EEE)',
    -  DAY_ABBR: 'd일'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ky.
    - */
    -goog.i18n.DateTimePatterns_ky = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y-\'ж\'.',
    -  YEAR_MONTH_ABBR: 'y-\'ж\'. MMM',
    -  YEAR_MONTH_FULL: 'y-\'ж\'. MMMM',
    -  MONTH_DAY_ABBR: 'd-MMM',
    -  MONTH_DAY_FULL: 'dd-MMMM',
    -  MONTH_DAY_SHORT: 'dd-MM',
    -  MONTH_DAY_MEDIUM: 'd-MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'y-\'ж\'. d-MMM',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'd-MMM, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y-\'ж\'. d-MMM, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ln.
    - */
    -goog.i18n.DateTimePatterns_ln = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale lo.
    - */
    -goog.i18n.DateTimePatterns_lo = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale lt.
    - */
    -goog.i18n.DateTimePatterns_lt = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'y-MM',
    -  YEAR_MONTH_FULL: 'y LLLL',
    -  MONTH_DAY_ABBR: 'MM-dd',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y-MM-dd',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MM-dd, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y-MM-dd, EEE',
    -  DAY_ABBR: 'dd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale lv.
    - */
    -goog.i18n.DateTimePatterns_lv = {
    -  YEAR_FULL: 'y. \'g\'.',
    -  YEAR_FULL_WITH_ERA: 'G y. \'g\'.',
    -  YEAR_MONTH_ABBR: 'y. \'g\'. MMM',
    -  YEAR_MONTH_FULL: 'y. \'g\'. MMMM',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'y. \'g\'. d. MMM',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, y. \'g\'. d. MMM',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale mk.
    - */
    -goog.i18n.DateTimePatterns_mk = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y \'г\'.',
    -  YEAR_MONTH_FULL: 'MMMM y \'г\'.',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd.M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y \'г\'.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y \'г\'.',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ml.
    - */
    -goog.i18n.DateTimePatterns_ml = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale mn.
    - */
    -goog.i18n.DateTimePatterns_mn = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M-d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, y MMM d',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale mo.
    - */
    -goog.i18n.DateTimePatterns_mo = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale mr.
    - */
    -goog.i18n.DateTimePatterns_mr = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d, MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ms.
    - */
    -goog.i18n.DateTimePatterns_ms = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd-M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale mt.
    - */
    -goog.i18n.DateTimePatterns_mt = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale my.
    - */
    -goog.i18n.DateTimePatterns_my = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale nb.
    - */
    -goog.i18n.DateTimePatterns_nb = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d. MMM y',
    -  DAY_ABBR: 'd.'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ne.
    - */
    -goog.i18n.DateTimePatterns_ne = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale nl.
    - */
    -goog.i18n.DateTimePatterns_nl = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd-M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale no.
    - */
    -goog.i18n.DateTimePatterns_no = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d. MMM y',
    -  DAY_ABBR: 'd.'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale no_NO.
    - */
    -goog.i18n.DateTimePatterns_no_NO = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d. MMM y',
    -  DAY_ABBR: 'd.'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale or.
    - */
    -goog.i18n.DateTimePatterns_or = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'd-M',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale pa.
    - */
    -goog.i18n.DateTimePatterns_pa = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale pl.
    - */
    -goog.i18n.DateTimePatterns_pl = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'LLL y',
    -  YEAR_MONTH_FULL: 'LLLL y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd.MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale pt.
    - */
    -goog.i18n.DateTimePatterns_pt = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd \'de\' MMM',
    -  MONTH_DAY_FULL: 'dd \'de\' MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d \'de\' MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale pt_BR.
    - */
    -goog.i18n.DateTimePatterns_pt_BR = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd \'de\' MMM',
    -  MONTH_DAY_FULL: 'dd \'de\' MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d \'de\' MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale pt_PT.
    - */
    -goog.i18n.DateTimePatterns_pt_PT = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MM/y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd/MM',
    -  MONTH_DAY_FULL: 'dd \'de\' MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd/MM/y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d/MM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d/MM/y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ro.
    - */
    -goog.i18n.DateTimePatterns_ro = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ru.
    - */
    -goog.i18n.DateTimePatterns_ru = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'LLL y',
    -  YEAR_MONTH_FULL: 'LLLL y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y \'г\'.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'ccc, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y \'г\'.',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sh.
    - */
    -goog.i18n.DateTimePatterns_sh = {
    -  YEAR_FULL: 'y.',
    -  YEAR_FULL_WITH_ERA: 'y. G',
    -  YEAR_MONTH_ABBR: 'MMM y.',
    -  YEAR_MONTH_FULL: 'MMMM y.',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y.',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale si.
    - */
    -goog.i18n.DateTimePatterns_si = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M-d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sk.
    - */
    -goog.i18n.DateTimePatterns_sk = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'LLLL y',
    -  YEAR_MONTH_FULL: 'LLLL y',
    -  MONTH_DAY_ABBR: 'd. M',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd. M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. M. y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d. M.',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d. M. y',
    -  DAY_ABBR: 'd.'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sl.
    - */
    -goog.i18n.DateTimePatterns_sl = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd. M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sq.
    - */
    -goog.i18n.DateTimePatterns_sq = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd.M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sr.
    - */
    -goog.i18n.DateTimePatterns_sr = {
    -  YEAR_FULL: 'y.',
    -  YEAR_FULL_WITH_ERA: 'y. G',
    -  YEAR_MONTH_ABBR: 'MMM y.',
    -  YEAR_MONTH_FULL: 'MMMM y.',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y.',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sv.
    - */
    -goog.i18n.DateTimePatterns_sv = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sw.
    - */
    -goog.i18n.DateTimePatterns_sw = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd-M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ta.
    - */
    -goog.i18n.DateTimePatterns_ta = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale te.
    - */
    -goog.i18n.DateTimePatterns_te = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd, MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d, MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale th.
    - */
    -goog.i18n.DateTimePatterns_th = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale tl.
    - */
    -goog.i18n.DateTimePatterns_tl = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale tr.
    - */
    -goog.i18n.DateTimePatterns_tr = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'dd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'dd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'd MMMM EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'd MMM y EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale uk.
    - */
    -goog.i18n.DateTimePatterns_uk = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'LLL y',
    -  YEAR_MONTH_FULL: 'LLLL y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ur.
    - */
    -goog.i18n.DateTimePatterns_ur = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale uz.
    - */
    -goog.i18n.DateTimePatterns_uz = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale vi.
    - */
    -goog.i18n.DateTimePatterns_vi = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM \'năm\' y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd-M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'dd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, dd MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, dd MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale zh.
    - */
    -goog.i18n.DateTimePatterns_zh = {
    -  YEAR_FULL: 'y年',
    -  YEAR_FULL_WITH_ERA: 'Gy年',
    -  YEAR_MONTH_ABBR: 'y年M月',
    -  YEAR_MONTH_FULL: 'y年M月',
    -  MONTH_DAY_ABBR: 'M月d日',
    -  MONTH_DAY_FULL: 'M月dd日',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'M月d日',
    -  MONTH_DAY_YEAR_MEDIUM: 'y年M月d日',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'M月d日EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y年M月d日EEE',
    -  DAY_ABBR: 'd日'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale zh_CN.
    - */
    -goog.i18n.DateTimePatterns_zh_CN = {
    -  YEAR_FULL: 'y年',
    -  YEAR_FULL_WITH_ERA: 'Gy年',
    -  YEAR_MONTH_ABBR: 'y年M月',
    -  YEAR_MONTH_FULL: 'y年M月',
    -  MONTH_DAY_ABBR: 'M月d日',
    -  MONTH_DAY_FULL: 'M月dd日',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'M月d日',
    -  MONTH_DAY_YEAR_MEDIUM: 'y年M月d日',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'M月d日EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y年M月d日EEE',
    -  DAY_ABBR: 'd日'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale zh_HK.
    - */
    -goog.i18n.DateTimePatterns_zh_HK = {
    -  YEAR_FULL: 'y年',
    -  YEAR_FULL_WITH_ERA: 'Gy年',
    -  YEAR_MONTH_ABBR: 'y年M月',
    -  YEAR_MONTH_FULL: 'y年M月',
    -  MONTH_DAY_ABBR: 'M月d日',
    -  MONTH_DAY_FULL: 'M月dd日',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'M月d日',
    -  MONTH_DAY_YEAR_MEDIUM: 'y年M月d日',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'M月d日EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y年M月d日EEE',
    -  DAY_ABBR: 'd日'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale zh_TW.
    - */
    -goog.i18n.DateTimePatterns_zh_TW = {
    -  YEAR_FULL: 'y年',
    -  YEAR_FULL_WITH_ERA: 'Gy年',
    -  YEAR_MONTH_ABBR: 'y年M月',
    -  YEAR_MONTH_FULL: 'y年M月',
    -  MONTH_DAY_ABBR: 'M月d日',
    -  MONTH_DAY_FULL: 'M月dd日',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'M月d日',
    -  MONTH_DAY_YEAR_MEDIUM: 'y年M月d日',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'M月d日 EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y年M月d日 EEE',
    -  DAY_ABBR: 'd日'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale zu.
    - */
    -goog.i18n.DateTimePatterns_zu = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Select date/time pattern by locale.
    - */
    -goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en;
    -
    -if (goog.LOCALE == 'af') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_af;
    -}
    -
    -if (goog.LOCALE == 'am') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_am;
    -}
    -
    -if (goog.LOCALE == 'ar') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ar;
    -}
    -
    -if (goog.LOCALE == 'az') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_az;
    -}
    -
    -if (goog.LOCALE == 'bg') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_bg;
    -}
    -
    -if (goog.LOCALE == 'bn') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_bn;
    -}
    -
    -if (goog.LOCALE == 'br') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_br;
    -}
    -
    -if (goog.LOCALE == 'ca') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ca;
    -}
    -
    -if (goog.LOCALE == 'chr') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_chr;
    -}
    -
    -if (goog.LOCALE == 'cs') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_cs;
    -}
    -
    -if (goog.LOCALE == 'cy') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_cy;
    -}
    -
    -if (goog.LOCALE == 'da') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_da;
    -}
    -
    -if (goog.LOCALE == 'de') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de;
    -}
    -
    -if (goog.LOCALE == 'de_AT' || goog.LOCALE == 'de-AT') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de_AT;
    -}
    -
    -if (goog.LOCALE == 'de_CH' || goog.LOCALE == 'de-CH') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de_CH;
    -}
    -
    -if (goog.LOCALE == 'el') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_el;
    -}
    -
    -if (goog.LOCALE == 'en') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en;
    -}
    -
    -if (goog.LOCALE == 'en_AU' || goog.LOCALE == 'en-AU') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_AU;
    -}
    -
    -if (goog.LOCALE == 'en_GB' || goog.LOCALE == 'en-GB') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_GB;
    -}
    -
    -if (goog.LOCALE == 'en_IE' || goog.LOCALE == 'en-IE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_IE;
    -}
    -
    -if (goog.LOCALE == 'en_IN' || goog.LOCALE == 'en-IN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_IN;
    -}
    -
    -if (goog.LOCALE == 'en_SG' || goog.LOCALE == 'en-SG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_SG;
    -}
    -
    -if (goog.LOCALE == 'en_US' || goog.LOCALE == 'en-US') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_US;
    -}
    -
    -if (goog.LOCALE == 'en_ZA' || goog.LOCALE == 'en-ZA') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_ZA;
    -}
    -
    -if (goog.LOCALE == 'es') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_es;
    -}
    -
    -if (goog.LOCALE == 'es_419' || goog.LOCALE == 'es-419') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_es_419;
    -}
    -
    -if (goog.LOCALE == 'es_ES' || goog.LOCALE == 'es-ES') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_es_ES;
    -}
    -
    -if (goog.LOCALE == 'et') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_et;
    -}
    -
    -if (goog.LOCALE == 'eu') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_eu;
    -}
    -
    -if (goog.LOCALE == 'fa') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fa;
    -}
    -
    -if (goog.LOCALE == 'fi') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fi;
    -}
    -
    -if (goog.LOCALE == 'fil') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fil;
    -}
    -
    -if (goog.LOCALE == 'fr') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr;
    -}
    -
    -if (goog.LOCALE == 'fr_CA' || goog.LOCALE == 'fr-CA') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_CA;
    -}
    -
    -if (goog.LOCALE == 'ga') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ga;
    -}
    -
    -if (goog.LOCALE == 'gl') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_gl;
    -}
    -
    -if (goog.LOCALE == 'gsw') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_gsw;
    -}
    -
    -if (goog.LOCALE == 'gu') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_gu;
    -}
    -
    -if (goog.LOCALE == 'haw') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_haw;
    -}
    -
    -if (goog.LOCALE == 'he') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_he;
    -}
    -
    -if (goog.LOCALE == 'hi') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_hi;
    -}
    -
    -if (goog.LOCALE == 'hr') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_hr;
    -}
    -
    -if (goog.LOCALE == 'hu') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_hu;
    -}
    -
    -if (goog.LOCALE == 'hy') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_hy;
    -}
    -
    -if (goog.LOCALE == 'id') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_id;
    -}
    -
    -if (goog.LOCALE == 'in') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_in;
    -}
    -
    -if (goog.LOCALE == 'is') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_is;
    -}
    -
    -if (goog.LOCALE == 'it') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_it;
    -}
    -
    -if (goog.LOCALE == 'iw') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_iw;
    -}
    -
    -if (goog.LOCALE == 'ja') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ja;
    -}
    -
    -if (goog.LOCALE == 'ka') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ka;
    -}
    -
    -if (goog.LOCALE == 'kk') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_kk;
    -}
    -
    -if (goog.LOCALE == 'km') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_km;
    -}
    -
    -if (goog.LOCALE == 'kn') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_kn;
    -}
    -
    -if (goog.LOCALE == 'ko') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ko;
    -}
    -
    -if (goog.LOCALE == 'ky') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ky;
    -}
    -
    -if (goog.LOCALE == 'ln') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ln;
    -}
    -
    -if (goog.LOCALE == 'lo') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_lo;
    -}
    -
    -if (goog.LOCALE == 'lt') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_lt;
    -}
    -
    -if (goog.LOCALE == 'lv') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_lv;
    -}
    -
    -if (goog.LOCALE == 'mk') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_mk;
    -}
    -
    -if (goog.LOCALE == 'ml') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ml;
    -}
    -
    -if (goog.LOCALE == 'mn') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_mn;
    -}
    -
    -if (goog.LOCALE == 'mo') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_mo;
    -}
    -
    -if (goog.LOCALE == 'mr') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_mr;
    -}
    -
    -if (goog.LOCALE == 'ms') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ms;
    -}
    -
    -if (goog.LOCALE == 'mt') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_mt;
    -}
    -
    -if (goog.LOCALE == 'my') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_my;
    -}
    -
    -if (goog.LOCALE == 'nb') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_nb;
    -}
    -
    -if (goog.LOCALE == 'ne') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ne;
    -}
    -
    -if (goog.LOCALE == 'nl') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_nl;
    -}
    -
    -if (goog.LOCALE == 'no') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_no;
    -}
    -
    -if (goog.LOCALE == 'no_NO' || goog.LOCALE == 'no-NO') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_no_NO;
    -}
    -
    -if (goog.LOCALE == 'or') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_or;
    -}
    -
    -if (goog.LOCALE == 'pa') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_pa;
    -}
    -
    -if (goog.LOCALE == 'pl') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_pl;
    -}
    -
    -if (goog.LOCALE == 'pt') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_pt;
    -}
    -
    -if (goog.LOCALE == 'pt_BR' || goog.LOCALE == 'pt-BR') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_pt_BR;
    -}
    -
    -if (goog.LOCALE == 'pt_PT' || goog.LOCALE == 'pt-PT') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_pt_PT;
    -}
    -
    -if (goog.LOCALE == 'ro') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ro;
    -}
    -
    -if (goog.LOCALE == 'ru') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ru;
    -}
    -
    -if (goog.LOCALE == 'sh') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sh;
    -}
    -
    -if (goog.LOCALE == 'si') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_si;
    -}
    -
    -if (goog.LOCALE == 'sk') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sk;
    -}
    -
    -if (goog.LOCALE == 'sl') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sl;
    -}
    -
    -if (goog.LOCALE == 'sq') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sq;
    -}
    -
    -if (goog.LOCALE == 'sr') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sr;
    -}
    -
    -if (goog.LOCALE == 'sv') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sv;
    -}
    -
    -if (goog.LOCALE == 'sw') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sw;
    -}
    -
    -if (goog.LOCALE == 'ta') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ta;
    -}
    -
    -if (goog.LOCALE == 'te') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_te;
    -}
    -
    -if (goog.LOCALE == 'th') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_th;
    -}
    -
    -if (goog.LOCALE == 'tl') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_tl;
    -}
    -
    -if (goog.LOCALE == 'tr') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_tr;
    -}
    -
    -if (goog.LOCALE == 'uk') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_uk;
    -}
    -
    -if (goog.LOCALE == 'ur') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ur;
    -}
    -
    -if (goog.LOCALE == 'uz') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_uz;
    -}
    -
    -if (goog.LOCALE == 'vi') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_vi;
    -}
    -
    -if (goog.LOCALE == 'zh') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_zh;
    -}
    -
    -if (goog.LOCALE == 'zh_CN' || goog.LOCALE == 'zh-CN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_zh_CN;
    -}
    -
    -if (goog.LOCALE == 'zh_HK' || goog.LOCALE == 'zh-HK') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_zh_HK;
    -}
    -
    -if (goog.LOCALE == 'zh_TW' || goog.LOCALE == 'zh-TW') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_zh_TW;
    -}
    -
    -if (goog.LOCALE == 'zu') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_zu;
    -}
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/datetimepatternsext.js b/src/database/third_party/closure-library/closure/goog/i18n/datetimepatternsext.js
    deleted file mode 100644
    index b9ccc962284..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/datetimepatternsext.js
    +++ /dev/null
    @@ -1,14232 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Extended date/time patterns.
    - *
    - * This file is autogenerated by script.  See
    - * http://go/generate_datetime_pattern.cc
    - *
    - * This file is generated using ICU's implementation of
    - * DateTimePatternGenerator. The whole set has two files:
    - * datetimepatterns.js and datetimepatternsext.js. The former covers
    - * frequently used locales, the latter covers the rest. There won't be any
    - * difference in compiled code, but some developing environments have
    - * difficulty in dealing large js files. So we do the separation.
    -
    - * Only locales that can be enumerated in ICU are supported. For the rest
    - * of the locales, it will fallback to 'en'.
    - * The code is designed to work with Closure compiler using
    - * ADVANCED_OPTIMIZATIONS. We will continue to add popular date/time
    - * patterns over time. There is no intention cover all possible
    - * usages. If simple pattern works fine, it won't be covered here either.
    - * For example, pattern 'MMM' will work well to get short month name for
    - * almost all locales thus won't be included here.
    - */
    -
    -/* File generated from CLDR ver. 26.0 */
    -
    -goog.provide('goog.i18n.DateTimePatternsExt');
    -
    -goog.provide('goog.i18n.DateTimePatterns_af_NA');
    -goog.provide('goog.i18n.DateTimePatterns_af_ZA');
    -goog.provide('goog.i18n.DateTimePatterns_agq');
    -goog.provide('goog.i18n.DateTimePatterns_agq_CM');
    -goog.provide('goog.i18n.DateTimePatterns_ak');
    -goog.provide('goog.i18n.DateTimePatterns_ak_GH');
    -goog.provide('goog.i18n.DateTimePatterns_am_ET');
    -goog.provide('goog.i18n.DateTimePatterns_ar_001');
    -goog.provide('goog.i18n.DateTimePatterns_ar_AE');
    -goog.provide('goog.i18n.DateTimePatterns_ar_BH');
    -goog.provide('goog.i18n.DateTimePatterns_ar_DJ');
    -goog.provide('goog.i18n.DateTimePatterns_ar_DZ');
    -goog.provide('goog.i18n.DateTimePatterns_ar_EG');
    -goog.provide('goog.i18n.DateTimePatterns_ar_EH');
    -goog.provide('goog.i18n.DateTimePatterns_ar_ER');
    -goog.provide('goog.i18n.DateTimePatterns_ar_IL');
    -goog.provide('goog.i18n.DateTimePatterns_ar_IQ');
    -goog.provide('goog.i18n.DateTimePatterns_ar_JO');
    -goog.provide('goog.i18n.DateTimePatterns_ar_KM');
    -goog.provide('goog.i18n.DateTimePatterns_ar_KW');
    -goog.provide('goog.i18n.DateTimePatterns_ar_LB');
    -goog.provide('goog.i18n.DateTimePatterns_ar_LY');
    -goog.provide('goog.i18n.DateTimePatterns_ar_MA');
    -goog.provide('goog.i18n.DateTimePatterns_ar_MR');
    -goog.provide('goog.i18n.DateTimePatterns_ar_OM');
    -goog.provide('goog.i18n.DateTimePatterns_ar_PS');
    -goog.provide('goog.i18n.DateTimePatterns_ar_QA');
    -goog.provide('goog.i18n.DateTimePatterns_ar_SA');
    -goog.provide('goog.i18n.DateTimePatterns_ar_SD');
    -goog.provide('goog.i18n.DateTimePatterns_ar_SO');
    -goog.provide('goog.i18n.DateTimePatterns_ar_SS');
    -goog.provide('goog.i18n.DateTimePatterns_ar_SY');
    -goog.provide('goog.i18n.DateTimePatterns_ar_TD');
    -goog.provide('goog.i18n.DateTimePatterns_ar_TN');
    -goog.provide('goog.i18n.DateTimePatterns_ar_YE');
    -goog.provide('goog.i18n.DateTimePatterns_as');
    -goog.provide('goog.i18n.DateTimePatterns_as_IN');
    -goog.provide('goog.i18n.DateTimePatterns_asa');
    -goog.provide('goog.i18n.DateTimePatterns_asa_TZ');
    -goog.provide('goog.i18n.DateTimePatterns_az_Cyrl');
    -goog.provide('goog.i18n.DateTimePatterns_az_Cyrl_AZ');
    -goog.provide('goog.i18n.DateTimePatterns_az_Latn');
    -goog.provide('goog.i18n.DateTimePatterns_az_Latn_AZ');
    -goog.provide('goog.i18n.DateTimePatterns_bas');
    -goog.provide('goog.i18n.DateTimePatterns_bas_CM');
    -goog.provide('goog.i18n.DateTimePatterns_be');
    -goog.provide('goog.i18n.DateTimePatterns_be_BY');
    -goog.provide('goog.i18n.DateTimePatterns_bem');
    -goog.provide('goog.i18n.DateTimePatterns_bem_ZM');
    -goog.provide('goog.i18n.DateTimePatterns_bez');
    -goog.provide('goog.i18n.DateTimePatterns_bez_TZ');
    -goog.provide('goog.i18n.DateTimePatterns_bg_BG');
    -goog.provide('goog.i18n.DateTimePatterns_bm');
    -goog.provide('goog.i18n.DateTimePatterns_bm_Latn');
    -goog.provide('goog.i18n.DateTimePatterns_bm_Latn_ML');
    -goog.provide('goog.i18n.DateTimePatterns_bn_BD');
    -goog.provide('goog.i18n.DateTimePatterns_bn_IN');
    -goog.provide('goog.i18n.DateTimePatterns_bo');
    -goog.provide('goog.i18n.DateTimePatterns_bo_CN');
    -goog.provide('goog.i18n.DateTimePatterns_bo_IN');
    -goog.provide('goog.i18n.DateTimePatterns_br_FR');
    -goog.provide('goog.i18n.DateTimePatterns_brx');
    -goog.provide('goog.i18n.DateTimePatterns_brx_IN');
    -goog.provide('goog.i18n.DateTimePatterns_bs');
    -goog.provide('goog.i18n.DateTimePatterns_bs_Cyrl');
    -goog.provide('goog.i18n.DateTimePatterns_bs_Cyrl_BA');
    -goog.provide('goog.i18n.DateTimePatterns_bs_Latn');
    -goog.provide('goog.i18n.DateTimePatterns_bs_Latn_BA');
    -goog.provide('goog.i18n.DateTimePatterns_ca_AD');
    -goog.provide('goog.i18n.DateTimePatterns_ca_ES');
    -goog.provide('goog.i18n.DateTimePatterns_ca_FR');
    -goog.provide('goog.i18n.DateTimePatterns_ca_IT');
    -goog.provide('goog.i18n.DateTimePatterns_cgg');
    -goog.provide('goog.i18n.DateTimePatterns_cgg_UG');
    -goog.provide('goog.i18n.DateTimePatterns_chr_US');
    -goog.provide('goog.i18n.DateTimePatterns_cs_CZ');
    -goog.provide('goog.i18n.DateTimePatterns_cy_GB');
    -goog.provide('goog.i18n.DateTimePatterns_da_DK');
    -goog.provide('goog.i18n.DateTimePatterns_da_GL');
    -goog.provide('goog.i18n.DateTimePatterns_dav');
    -goog.provide('goog.i18n.DateTimePatterns_dav_KE');
    -goog.provide('goog.i18n.DateTimePatterns_de_BE');
    -goog.provide('goog.i18n.DateTimePatterns_de_DE');
    -goog.provide('goog.i18n.DateTimePatterns_de_LI');
    -goog.provide('goog.i18n.DateTimePatterns_de_LU');
    -goog.provide('goog.i18n.DateTimePatterns_dje');
    -goog.provide('goog.i18n.DateTimePatterns_dje_NE');
    -goog.provide('goog.i18n.DateTimePatterns_dsb');
    -goog.provide('goog.i18n.DateTimePatterns_dsb_DE');
    -goog.provide('goog.i18n.DateTimePatterns_dua');
    -goog.provide('goog.i18n.DateTimePatterns_dua_CM');
    -goog.provide('goog.i18n.DateTimePatterns_dyo');
    -goog.provide('goog.i18n.DateTimePatterns_dyo_SN');
    -goog.provide('goog.i18n.DateTimePatterns_dz');
    -goog.provide('goog.i18n.DateTimePatterns_dz_BT');
    -goog.provide('goog.i18n.DateTimePatterns_ebu');
    -goog.provide('goog.i18n.DateTimePatterns_ebu_KE');
    -goog.provide('goog.i18n.DateTimePatterns_ee');
    -goog.provide('goog.i18n.DateTimePatterns_ee_GH');
    -goog.provide('goog.i18n.DateTimePatterns_ee_TG');
    -goog.provide('goog.i18n.DateTimePatterns_el_CY');
    -goog.provide('goog.i18n.DateTimePatterns_el_GR');
    -goog.provide('goog.i18n.DateTimePatterns_en_001');
    -goog.provide('goog.i18n.DateTimePatterns_en_150');
    -goog.provide('goog.i18n.DateTimePatterns_en_AG');
    -goog.provide('goog.i18n.DateTimePatterns_en_AI');
    -goog.provide('goog.i18n.DateTimePatterns_en_AS');
    -goog.provide('goog.i18n.DateTimePatterns_en_BB');
    -goog.provide('goog.i18n.DateTimePatterns_en_BE');
    -goog.provide('goog.i18n.DateTimePatterns_en_BM');
    -goog.provide('goog.i18n.DateTimePatterns_en_BS');
    -goog.provide('goog.i18n.DateTimePatterns_en_BW');
    -goog.provide('goog.i18n.DateTimePatterns_en_BZ');
    -goog.provide('goog.i18n.DateTimePatterns_en_CA');
    -goog.provide('goog.i18n.DateTimePatterns_en_CC');
    -goog.provide('goog.i18n.DateTimePatterns_en_CK');
    -goog.provide('goog.i18n.DateTimePatterns_en_CM');
    -goog.provide('goog.i18n.DateTimePatterns_en_CX');
    -goog.provide('goog.i18n.DateTimePatterns_en_DG');
    -goog.provide('goog.i18n.DateTimePatterns_en_DM');
    -goog.provide('goog.i18n.DateTimePatterns_en_ER');
    -goog.provide('goog.i18n.DateTimePatterns_en_FJ');
    -goog.provide('goog.i18n.DateTimePatterns_en_FK');
    -goog.provide('goog.i18n.DateTimePatterns_en_FM');
    -goog.provide('goog.i18n.DateTimePatterns_en_GD');
    -goog.provide('goog.i18n.DateTimePatterns_en_GG');
    -goog.provide('goog.i18n.DateTimePatterns_en_GH');
    -goog.provide('goog.i18n.DateTimePatterns_en_GI');
    -goog.provide('goog.i18n.DateTimePatterns_en_GM');
    -goog.provide('goog.i18n.DateTimePatterns_en_GU');
    -goog.provide('goog.i18n.DateTimePatterns_en_GY');
    -goog.provide('goog.i18n.DateTimePatterns_en_HK');
    -goog.provide('goog.i18n.DateTimePatterns_en_IM');
    -goog.provide('goog.i18n.DateTimePatterns_en_IO');
    -goog.provide('goog.i18n.DateTimePatterns_en_JE');
    -goog.provide('goog.i18n.DateTimePatterns_en_JM');
    -goog.provide('goog.i18n.DateTimePatterns_en_KE');
    -goog.provide('goog.i18n.DateTimePatterns_en_KI');
    -goog.provide('goog.i18n.DateTimePatterns_en_KN');
    -goog.provide('goog.i18n.DateTimePatterns_en_KY');
    -goog.provide('goog.i18n.DateTimePatterns_en_LC');
    -goog.provide('goog.i18n.DateTimePatterns_en_LR');
    -goog.provide('goog.i18n.DateTimePatterns_en_LS');
    -goog.provide('goog.i18n.DateTimePatterns_en_MG');
    -goog.provide('goog.i18n.DateTimePatterns_en_MH');
    -goog.provide('goog.i18n.DateTimePatterns_en_MO');
    -goog.provide('goog.i18n.DateTimePatterns_en_MP');
    -goog.provide('goog.i18n.DateTimePatterns_en_MS');
    -goog.provide('goog.i18n.DateTimePatterns_en_MT');
    -goog.provide('goog.i18n.DateTimePatterns_en_MU');
    -goog.provide('goog.i18n.DateTimePatterns_en_MW');
    -goog.provide('goog.i18n.DateTimePatterns_en_MY');
    -goog.provide('goog.i18n.DateTimePatterns_en_NA');
    -goog.provide('goog.i18n.DateTimePatterns_en_NF');
    -goog.provide('goog.i18n.DateTimePatterns_en_NG');
    -goog.provide('goog.i18n.DateTimePatterns_en_NR');
    -goog.provide('goog.i18n.DateTimePatterns_en_NU');
    -goog.provide('goog.i18n.DateTimePatterns_en_NZ');
    -goog.provide('goog.i18n.DateTimePatterns_en_PG');
    -goog.provide('goog.i18n.DateTimePatterns_en_PH');
    -goog.provide('goog.i18n.DateTimePatterns_en_PK');
    -goog.provide('goog.i18n.DateTimePatterns_en_PN');
    -goog.provide('goog.i18n.DateTimePatterns_en_PR');
    -goog.provide('goog.i18n.DateTimePatterns_en_PW');
    -goog.provide('goog.i18n.DateTimePatterns_en_RW');
    -goog.provide('goog.i18n.DateTimePatterns_en_SB');
    -goog.provide('goog.i18n.DateTimePatterns_en_SC');
    -goog.provide('goog.i18n.DateTimePatterns_en_SD');
    -goog.provide('goog.i18n.DateTimePatterns_en_SH');
    -goog.provide('goog.i18n.DateTimePatterns_en_SL');
    -goog.provide('goog.i18n.DateTimePatterns_en_SS');
    -goog.provide('goog.i18n.DateTimePatterns_en_SX');
    -goog.provide('goog.i18n.DateTimePatterns_en_SZ');
    -goog.provide('goog.i18n.DateTimePatterns_en_TC');
    -goog.provide('goog.i18n.DateTimePatterns_en_TK');
    -goog.provide('goog.i18n.DateTimePatterns_en_TO');
    -goog.provide('goog.i18n.DateTimePatterns_en_TT');
    -goog.provide('goog.i18n.DateTimePatterns_en_TV');
    -goog.provide('goog.i18n.DateTimePatterns_en_TZ');
    -goog.provide('goog.i18n.DateTimePatterns_en_UG');
    -goog.provide('goog.i18n.DateTimePatterns_en_UM');
    -goog.provide('goog.i18n.DateTimePatterns_en_US_POSIX');
    -goog.provide('goog.i18n.DateTimePatterns_en_VC');
    -goog.provide('goog.i18n.DateTimePatterns_en_VG');
    -goog.provide('goog.i18n.DateTimePatterns_en_VI');
    -goog.provide('goog.i18n.DateTimePatterns_en_VU');
    -goog.provide('goog.i18n.DateTimePatterns_en_WS');
    -goog.provide('goog.i18n.DateTimePatterns_en_ZM');
    -goog.provide('goog.i18n.DateTimePatterns_en_ZW');
    -goog.provide('goog.i18n.DateTimePatterns_eo');
    -goog.provide('goog.i18n.DateTimePatterns_es_AR');
    -goog.provide('goog.i18n.DateTimePatterns_es_BO');
    -goog.provide('goog.i18n.DateTimePatterns_es_CL');
    -goog.provide('goog.i18n.DateTimePatterns_es_CO');
    -goog.provide('goog.i18n.DateTimePatterns_es_CR');
    -goog.provide('goog.i18n.DateTimePatterns_es_CU');
    -goog.provide('goog.i18n.DateTimePatterns_es_DO');
    -goog.provide('goog.i18n.DateTimePatterns_es_EA');
    -goog.provide('goog.i18n.DateTimePatterns_es_EC');
    -goog.provide('goog.i18n.DateTimePatterns_es_GQ');
    -goog.provide('goog.i18n.DateTimePatterns_es_GT');
    -goog.provide('goog.i18n.DateTimePatterns_es_HN');
    -goog.provide('goog.i18n.DateTimePatterns_es_IC');
    -goog.provide('goog.i18n.DateTimePatterns_es_MX');
    -goog.provide('goog.i18n.DateTimePatterns_es_NI');
    -goog.provide('goog.i18n.DateTimePatterns_es_PA');
    -goog.provide('goog.i18n.DateTimePatterns_es_PE');
    -goog.provide('goog.i18n.DateTimePatterns_es_PH');
    -goog.provide('goog.i18n.DateTimePatterns_es_PR');
    -goog.provide('goog.i18n.DateTimePatterns_es_PY');
    -goog.provide('goog.i18n.DateTimePatterns_es_SV');
    -goog.provide('goog.i18n.DateTimePatterns_es_US');
    -goog.provide('goog.i18n.DateTimePatterns_es_UY');
    -goog.provide('goog.i18n.DateTimePatterns_es_VE');
    -goog.provide('goog.i18n.DateTimePatterns_et_EE');
    -goog.provide('goog.i18n.DateTimePatterns_eu_ES');
    -goog.provide('goog.i18n.DateTimePatterns_ewo');
    -goog.provide('goog.i18n.DateTimePatterns_ewo_CM');
    -goog.provide('goog.i18n.DateTimePatterns_fa_AF');
    -goog.provide('goog.i18n.DateTimePatterns_fa_IR');
    -goog.provide('goog.i18n.DateTimePatterns_ff');
    -goog.provide('goog.i18n.DateTimePatterns_ff_CM');
    -goog.provide('goog.i18n.DateTimePatterns_ff_GN');
    -goog.provide('goog.i18n.DateTimePatterns_ff_MR');
    -goog.provide('goog.i18n.DateTimePatterns_ff_SN');
    -goog.provide('goog.i18n.DateTimePatterns_fi_FI');
    -goog.provide('goog.i18n.DateTimePatterns_fil_PH');
    -goog.provide('goog.i18n.DateTimePatterns_fo');
    -goog.provide('goog.i18n.DateTimePatterns_fo_FO');
    -goog.provide('goog.i18n.DateTimePatterns_fr_BE');
    -goog.provide('goog.i18n.DateTimePatterns_fr_BF');
    -goog.provide('goog.i18n.DateTimePatterns_fr_BI');
    -goog.provide('goog.i18n.DateTimePatterns_fr_BJ');
    -goog.provide('goog.i18n.DateTimePatterns_fr_BL');
    -goog.provide('goog.i18n.DateTimePatterns_fr_CD');
    -goog.provide('goog.i18n.DateTimePatterns_fr_CF');
    -goog.provide('goog.i18n.DateTimePatterns_fr_CG');
    -goog.provide('goog.i18n.DateTimePatterns_fr_CH');
    -goog.provide('goog.i18n.DateTimePatterns_fr_CI');
    -goog.provide('goog.i18n.DateTimePatterns_fr_CM');
    -goog.provide('goog.i18n.DateTimePatterns_fr_DJ');
    -goog.provide('goog.i18n.DateTimePatterns_fr_DZ');
    -goog.provide('goog.i18n.DateTimePatterns_fr_FR');
    -goog.provide('goog.i18n.DateTimePatterns_fr_GA');
    -goog.provide('goog.i18n.DateTimePatterns_fr_GF');
    -goog.provide('goog.i18n.DateTimePatterns_fr_GN');
    -goog.provide('goog.i18n.DateTimePatterns_fr_GP');
    -goog.provide('goog.i18n.DateTimePatterns_fr_GQ');
    -goog.provide('goog.i18n.DateTimePatterns_fr_HT');
    -goog.provide('goog.i18n.DateTimePatterns_fr_KM');
    -goog.provide('goog.i18n.DateTimePatterns_fr_LU');
    -goog.provide('goog.i18n.DateTimePatterns_fr_MA');
    -goog.provide('goog.i18n.DateTimePatterns_fr_MC');
    -goog.provide('goog.i18n.DateTimePatterns_fr_MF');
    -goog.provide('goog.i18n.DateTimePatterns_fr_MG');
    -goog.provide('goog.i18n.DateTimePatterns_fr_ML');
    -goog.provide('goog.i18n.DateTimePatterns_fr_MQ');
    -goog.provide('goog.i18n.DateTimePatterns_fr_MR');
    -goog.provide('goog.i18n.DateTimePatterns_fr_MU');
    -goog.provide('goog.i18n.DateTimePatterns_fr_NC');
    -goog.provide('goog.i18n.DateTimePatterns_fr_NE');
    -goog.provide('goog.i18n.DateTimePatterns_fr_PF');
    -goog.provide('goog.i18n.DateTimePatterns_fr_PM');
    -goog.provide('goog.i18n.DateTimePatterns_fr_RE');
    -goog.provide('goog.i18n.DateTimePatterns_fr_RW');
    -goog.provide('goog.i18n.DateTimePatterns_fr_SC');
    -goog.provide('goog.i18n.DateTimePatterns_fr_SN');
    -goog.provide('goog.i18n.DateTimePatterns_fr_SY');
    -goog.provide('goog.i18n.DateTimePatterns_fr_TD');
    -goog.provide('goog.i18n.DateTimePatterns_fr_TG');
    -goog.provide('goog.i18n.DateTimePatterns_fr_TN');
    -goog.provide('goog.i18n.DateTimePatterns_fr_VU');
    -goog.provide('goog.i18n.DateTimePatterns_fr_WF');
    -goog.provide('goog.i18n.DateTimePatterns_fr_YT');
    -goog.provide('goog.i18n.DateTimePatterns_fur');
    -goog.provide('goog.i18n.DateTimePatterns_fur_IT');
    -goog.provide('goog.i18n.DateTimePatterns_fy');
    -goog.provide('goog.i18n.DateTimePatterns_fy_NL');
    -goog.provide('goog.i18n.DateTimePatterns_ga_IE');
    -goog.provide('goog.i18n.DateTimePatterns_gd');
    -goog.provide('goog.i18n.DateTimePatterns_gd_GB');
    -goog.provide('goog.i18n.DateTimePatterns_gl_ES');
    -goog.provide('goog.i18n.DateTimePatterns_gsw_CH');
    -goog.provide('goog.i18n.DateTimePatterns_gsw_FR');
    -goog.provide('goog.i18n.DateTimePatterns_gsw_LI');
    -goog.provide('goog.i18n.DateTimePatterns_gu_IN');
    -goog.provide('goog.i18n.DateTimePatterns_guz');
    -goog.provide('goog.i18n.DateTimePatterns_guz_KE');
    -goog.provide('goog.i18n.DateTimePatterns_gv');
    -goog.provide('goog.i18n.DateTimePatterns_gv_IM');
    -goog.provide('goog.i18n.DateTimePatterns_ha');
    -goog.provide('goog.i18n.DateTimePatterns_ha_Latn');
    -goog.provide('goog.i18n.DateTimePatterns_ha_Latn_GH');
    -goog.provide('goog.i18n.DateTimePatterns_ha_Latn_NE');
    -goog.provide('goog.i18n.DateTimePatterns_ha_Latn_NG');
    -goog.provide('goog.i18n.DateTimePatterns_haw_US');
    -goog.provide('goog.i18n.DateTimePatterns_he_IL');
    -goog.provide('goog.i18n.DateTimePatterns_hi_IN');
    -goog.provide('goog.i18n.DateTimePatterns_hr_BA');
    -goog.provide('goog.i18n.DateTimePatterns_hr_HR');
    -goog.provide('goog.i18n.DateTimePatterns_hsb');
    -goog.provide('goog.i18n.DateTimePatterns_hsb_DE');
    -goog.provide('goog.i18n.DateTimePatterns_hu_HU');
    -goog.provide('goog.i18n.DateTimePatterns_hy_AM');
    -goog.provide('goog.i18n.DateTimePatterns_id_ID');
    -goog.provide('goog.i18n.DateTimePatterns_ig');
    -goog.provide('goog.i18n.DateTimePatterns_ig_NG');
    -goog.provide('goog.i18n.DateTimePatterns_ii');
    -goog.provide('goog.i18n.DateTimePatterns_ii_CN');
    -goog.provide('goog.i18n.DateTimePatterns_is_IS');
    -goog.provide('goog.i18n.DateTimePatterns_it_CH');
    -goog.provide('goog.i18n.DateTimePatterns_it_IT');
    -goog.provide('goog.i18n.DateTimePatterns_it_SM');
    -goog.provide('goog.i18n.DateTimePatterns_ja_JP');
    -goog.provide('goog.i18n.DateTimePatterns_jgo');
    -goog.provide('goog.i18n.DateTimePatterns_jgo_CM');
    -goog.provide('goog.i18n.DateTimePatterns_jmc');
    -goog.provide('goog.i18n.DateTimePatterns_jmc_TZ');
    -goog.provide('goog.i18n.DateTimePatterns_ka_GE');
    -goog.provide('goog.i18n.DateTimePatterns_kab');
    -goog.provide('goog.i18n.DateTimePatterns_kab_DZ');
    -goog.provide('goog.i18n.DateTimePatterns_kam');
    -goog.provide('goog.i18n.DateTimePatterns_kam_KE');
    -goog.provide('goog.i18n.DateTimePatterns_kde');
    -goog.provide('goog.i18n.DateTimePatterns_kde_TZ');
    -goog.provide('goog.i18n.DateTimePatterns_kea');
    -goog.provide('goog.i18n.DateTimePatterns_kea_CV');
    -goog.provide('goog.i18n.DateTimePatterns_khq');
    -goog.provide('goog.i18n.DateTimePatterns_khq_ML');
    -goog.provide('goog.i18n.DateTimePatterns_ki');
    -goog.provide('goog.i18n.DateTimePatterns_ki_KE');
    -goog.provide('goog.i18n.DateTimePatterns_kk_Cyrl');
    -goog.provide('goog.i18n.DateTimePatterns_kk_Cyrl_KZ');
    -goog.provide('goog.i18n.DateTimePatterns_kkj');
    -goog.provide('goog.i18n.DateTimePatterns_kkj_CM');
    -goog.provide('goog.i18n.DateTimePatterns_kl');
    -goog.provide('goog.i18n.DateTimePatterns_kl_GL');
    -goog.provide('goog.i18n.DateTimePatterns_kln');
    -goog.provide('goog.i18n.DateTimePatterns_kln_KE');
    -goog.provide('goog.i18n.DateTimePatterns_km_KH');
    -goog.provide('goog.i18n.DateTimePatterns_kn_IN');
    -goog.provide('goog.i18n.DateTimePatterns_ko_KP');
    -goog.provide('goog.i18n.DateTimePatterns_ko_KR');
    -goog.provide('goog.i18n.DateTimePatterns_kok');
    -goog.provide('goog.i18n.DateTimePatterns_kok_IN');
    -goog.provide('goog.i18n.DateTimePatterns_ks');
    -goog.provide('goog.i18n.DateTimePatterns_ks_Arab');
    -goog.provide('goog.i18n.DateTimePatterns_ks_Arab_IN');
    -goog.provide('goog.i18n.DateTimePatterns_ksb');
    -goog.provide('goog.i18n.DateTimePatterns_ksb_TZ');
    -goog.provide('goog.i18n.DateTimePatterns_ksf');
    -goog.provide('goog.i18n.DateTimePatterns_ksf_CM');
    -goog.provide('goog.i18n.DateTimePatterns_ksh');
    -goog.provide('goog.i18n.DateTimePatterns_ksh_DE');
    -goog.provide('goog.i18n.DateTimePatterns_kw');
    -goog.provide('goog.i18n.DateTimePatterns_kw_GB');
    -goog.provide('goog.i18n.DateTimePatterns_ky_Cyrl');
    -goog.provide('goog.i18n.DateTimePatterns_ky_Cyrl_KG');
    -goog.provide('goog.i18n.DateTimePatterns_lag');
    -goog.provide('goog.i18n.DateTimePatterns_lag_TZ');
    -goog.provide('goog.i18n.DateTimePatterns_lb');
    -goog.provide('goog.i18n.DateTimePatterns_lb_LU');
    -goog.provide('goog.i18n.DateTimePatterns_lg');
    -goog.provide('goog.i18n.DateTimePatterns_lg_UG');
    -goog.provide('goog.i18n.DateTimePatterns_lkt');
    -goog.provide('goog.i18n.DateTimePatterns_lkt_US');
    -goog.provide('goog.i18n.DateTimePatterns_ln_AO');
    -goog.provide('goog.i18n.DateTimePatterns_ln_CD');
    -goog.provide('goog.i18n.DateTimePatterns_ln_CF');
    -goog.provide('goog.i18n.DateTimePatterns_ln_CG');
    -goog.provide('goog.i18n.DateTimePatterns_lo_LA');
    -goog.provide('goog.i18n.DateTimePatterns_lt_LT');
    -goog.provide('goog.i18n.DateTimePatterns_lu');
    -goog.provide('goog.i18n.DateTimePatterns_lu_CD');
    -goog.provide('goog.i18n.DateTimePatterns_luo');
    -goog.provide('goog.i18n.DateTimePatterns_luo_KE');
    -goog.provide('goog.i18n.DateTimePatterns_luy');
    -goog.provide('goog.i18n.DateTimePatterns_luy_KE');
    -goog.provide('goog.i18n.DateTimePatterns_lv_LV');
    -goog.provide('goog.i18n.DateTimePatterns_mas');
    -goog.provide('goog.i18n.DateTimePatterns_mas_KE');
    -goog.provide('goog.i18n.DateTimePatterns_mas_TZ');
    -goog.provide('goog.i18n.DateTimePatterns_mer');
    -goog.provide('goog.i18n.DateTimePatterns_mer_KE');
    -goog.provide('goog.i18n.DateTimePatterns_mfe');
    -goog.provide('goog.i18n.DateTimePatterns_mfe_MU');
    -goog.provide('goog.i18n.DateTimePatterns_mg');
    -goog.provide('goog.i18n.DateTimePatterns_mg_MG');
    -goog.provide('goog.i18n.DateTimePatterns_mgh');
    -goog.provide('goog.i18n.DateTimePatterns_mgh_MZ');
    -goog.provide('goog.i18n.DateTimePatterns_mgo');
    -goog.provide('goog.i18n.DateTimePatterns_mgo_CM');
    -goog.provide('goog.i18n.DateTimePatterns_mk_MK');
    -goog.provide('goog.i18n.DateTimePatterns_ml_IN');
    -goog.provide('goog.i18n.DateTimePatterns_mn_Cyrl');
    -goog.provide('goog.i18n.DateTimePatterns_mn_Cyrl_MN');
    -goog.provide('goog.i18n.DateTimePatterns_mr_IN');
    -goog.provide('goog.i18n.DateTimePatterns_ms_Latn');
    -goog.provide('goog.i18n.DateTimePatterns_ms_Latn_BN');
    -goog.provide('goog.i18n.DateTimePatterns_ms_Latn_MY');
    -goog.provide('goog.i18n.DateTimePatterns_ms_Latn_SG');
    -goog.provide('goog.i18n.DateTimePatterns_mt_MT');
    -goog.provide('goog.i18n.DateTimePatterns_mua');
    -goog.provide('goog.i18n.DateTimePatterns_mua_CM');
    -goog.provide('goog.i18n.DateTimePatterns_my_MM');
    -goog.provide('goog.i18n.DateTimePatterns_naq');
    -goog.provide('goog.i18n.DateTimePatterns_naq_NA');
    -goog.provide('goog.i18n.DateTimePatterns_nb_NO');
    -goog.provide('goog.i18n.DateTimePatterns_nb_SJ');
    -goog.provide('goog.i18n.DateTimePatterns_nd');
    -goog.provide('goog.i18n.DateTimePatterns_nd_ZW');
    -goog.provide('goog.i18n.DateTimePatterns_ne_IN');
    -goog.provide('goog.i18n.DateTimePatterns_ne_NP');
    -goog.provide('goog.i18n.DateTimePatterns_nl_AW');
    -goog.provide('goog.i18n.DateTimePatterns_nl_BE');
    -goog.provide('goog.i18n.DateTimePatterns_nl_BQ');
    -goog.provide('goog.i18n.DateTimePatterns_nl_CW');
    -goog.provide('goog.i18n.DateTimePatterns_nl_NL');
    -goog.provide('goog.i18n.DateTimePatterns_nl_SR');
    -goog.provide('goog.i18n.DateTimePatterns_nl_SX');
    -goog.provide('goog.i18n.DateTimePatterns_nmg');
    -goog.provide('goog.i18n.DateTimePatterns_nmg_CM');
    -goog.provide('goog.i18n.DateTimePatterns_nn');
    -goog.provide('goog.i18n.DateTimePatterns_nn_NO');
    -goog.provide('goog.i18n.DateTimePatterns_nnh');
    -goog.provide('goog.i18n.DateTimePatterns_nnh_CM');
    -goog.provide('goog.i18n.DateTimePatterns_nus');
    -goog.provide('goog.i18n.DateTimePatterns_nus_SD');
    -goog.provide('goog.i18n.DateTimePatterns_nyn');
    -goog.provide('goog.i18n.DateTimePatterns_nyn_UG');
    -goog.provide('goog.i18n.DateTimePatterns_om');
    -goog.provide('goog.i18n.DateTimePatterns_om_ET');
    -goog.provide('goog.i18n.DateTimePatterns_om_KE');
    -goog.provide('goog.i18n.DateTimePatterns_or_IN');
    -goog.provide('goog.i18n.DateTimePatterns_os');
    -goog.provide('goog.i18n.DateTimePatterns_os_GE');
    -goog.provide('goog.i18n.DateTimePatterns_os_RU');
    -goog.provide('goog.i18n.DateTimePatterns_pa_Arab');
    -goog.provide('goog.i18n.DateTimePatterns_pa_Arab_PK');
    -goog.provide('goog.i18n.DateTimePatterns_pa_Guru');
    -goog.provide('goog.i18n.DateTimePatterns_pa_Guru_IN');
    -goog.provide('goog.i18n.DateTimePatterns_pl_PL');
    -goog.provide('goog.i18n.DateTimePatterns_ps');
    -goog.provide('goog.i18n.DateTimePatterns_ps_AF');
    -goog.provide('goog.i18n.DateTimePatterns_pt_AO');
    -goog.provide('goog.i18n.DateTimePatterns_pt_CV');
    -goog.provide('goog.i18n.DateTimePatterns_pt_GW');
    -goog.provide('goog.i18n.DateTimePatterns_pt_MO');
    -goog.provide('goog.i18n.DateTimePatterns_pt_MZ');
    -goog.provide('goog.i18n.DateTimePatterns_pt_ST');
    -goog.provide('goog.i18n.DateTimePatterns_pt_TL');
    -goog.provide('goog.i18n.DateTimePatterns_qu');
    -goog.provide('goog.i18n.DateTimePatterns_qu_BO');
    -goog.provide('goog.i18n.DateTimePatterns_qu_EC');
    -goog.provide('goog.i18n.DateTimePatterns_qu_PE');
    -goog.provide('goog.i18n.DateTimePatterns_rm');
    -goog.provide('goog.i18n.DateTimePatterns_rm_CH');
    -goog.provide('goog.i18n.DateTimePatterns_rn');
    -goog.provide('goog.i18n.DateTimePatterns_rn_BI');
    -goog.provide('goog.i18n.DateTimePatterns_ro_MD');
    -goog.provide('goog.i18n.DateTimePatterns_ro_RO');
    -goog.provide('goog.i18n.DateTimePatterns_rof');
    -goog.provide('goog.i18n.DateTimePatterns_rof_TZ');
    -goog.provide('goog.i18n.DateTimePatterns_ru_BY');
    -goog.provide('goog.i18n.DateTimePatterns_ru_KG');
    -goog.provide('goog.i18n.DateTimePatterns_ru_KZ');
    -goog.provide('goog.i18n.DateTimePatterns_ru_MD');
    -goog.provide('goog.i18n.DateTimePatterns_ru_RU');
    -goog.provide('goog.i18n.DateTimePatterns_ru_UA');
    -goog.provide('goog.i18n.DateTimePatterns_rw');
    -goog.provide('goog.i18n.DateTimePatterns_rw_RW');
    -goog.provide('goog.i18n.DateTimePatterns_rwk');
    -goog.provide('goog.i18n.DateTimePatterns_rwk_TZ');
    -goog.provide('goog.i18n.DateTimePatterns_sah');
    -goog.provide('goog.i18n.DateTimePatterns_sah_RU');
    -goog.provide('goog.i18n.DateTimePatterns_saq');
    -goog.provide('goog.i18n.DateTimePatterns_saq_KE');
    -goog.provide('goog.i18n.DateTimePatterns_sbp');
    -goog.provide('goog.i18n.DateTimePatterns_sbp_TZ');
    -goog.provide('goog.i18n.DateTimePatterns_se');
    -goog.provide('goog.i18n.DateTimePatterns_se_FI');
    -goog.provide('goog.i18n.DateTimePatterns_se_NO');
    -goog.provide('goog.i18n.DateTimePatterns_se_SE');
    -goog.provide('goog.i18n.DateTimePatterns_seh');
    -goog.provide('goog.i18n.DateTimePatterns_seh_MZ');
    -goog.provide('goog.i18n.DateTimePatterns_ses');
    -goog.provide('goog.i18n.DateTimePatterns_ses_ML');
    -goog.provide('goog.i18n.DateTimePatterns_sg');
    -goog.provide('goog.i18n.DateTimePatterns_sg_CF');
    -goog.provide('goog.i18n.DateTimePatterns_shi');
    -goog.provide('goog.i18n.DateTimePatterns_shi_Latn');
    -goog.provide('goog.i18n.DateTimePatterns_shi_Latn_MA');
    -goog.provide('goog.i18n.DateTimePatterns_shi_Tfng');
    -goog.provide('goog.i18n.DateTimePatterns_shi_Tfng_MA');
    -goog.provide('goog.i18n.DateTimePatterns_si_LK');
    -goog.provide('goog.i18n.DateTimePatterns_sk_SK');
    -goog.provide('goog.i18n.DateTimePatterns_sl_SI');
    -goog.provide('goog.i18n.DateTimePatterns_smn');
    -goog.provide('goog.i18n.DateTimePatterns_smn_FI');
    -goog.provide('goog.i18n.DateTimePatterns_sn');
    -goog.provide('goog.i18n.DateTimePatterns_sn_ZW');
    -goog.provide('goog.i18n.DateTimePatterns_so');
    -goog.provide('goog.i18n.DateTimePatterns_so_DJ');
    -goog.provide('goog.i18n.DateTimePatterns_so_ET');
    -goog.provide('goog.i18n.DateTimePatterns_so_KE');
    -goog.provide('goog.i18n.DateTimePatterns_so_SO');
    -goog.provide('goog.i18n.DateTimePatterns_sq_AL');
    -goog.provide('goog.i18n.DateTimePatterns_sq_MK');
    -goog.provide('goog.i18n.DateTimePatterns_sq_XK');
    -goog.provide('goog.i18n.DateTimePatterns_sr_Cyrl');
    -goog.provide('goog.i18n.DateTimePatterns_sr_Cyrl_BA');
    -goog.provide('goog.i18n.DateTimePatterns_sr_Cyrl_ME');
    -goog.provide('goog.i18n.DateTimePatterns_sr_Cyrl_RS');
    -goog.provide('goog.i18n.DateTimePatterns_sr_Cyrl_XK');
    -goog.provide('goog.i18n.DateTimePatterns_sr_Latn');
    -goog.provide('goog.i18n.DateTimePatterns_sr_Latn_BA');
    -goog.provide('goog.i18n.DateTimePatterns_sr_Latn_ME');
    -goog.provide('goog.i18n.DateTimePatterns_sr_Latn_RS');
    -goog.provide('goog.i18n.DateTimePatterns_sr_Latn_XK');
    -goog.provide('goog.i18n.DateTimePatterns_sv_AX');
    -goog.provide('goog.i18n.DateTimePatterns_sv_FI');
    -goog.provide('goog.i18n.DateTimePatterns_sv_SE');
    -goog.provide('goog.i18n.DateTimePatterns_sw_KE');
    -goog.provide('goog.i18n.DateTimePatterns_sw_TZ');
    -goog.provide('goog.i18n.DateTimePatterns_sw_UG');
    -goog.provide('goog.i18n.DateTimePatterns_swc');
    -goog.provide('goog.i18n.DateTimePatterns_swc_CD');
    -goog.provide('goog.i18n.DateTimePatterns_ta_IN');
    -goog.provide('goog.i18n.DateTimePatterns_ta_LK');
    -goog.provide('goog.i18n.DateTimePatterns_ta_MY');
    -goog.provide('goog.i18n.DateTimePatterns_ta_SG');
    -goog.provide('goog.i18n.DateTimePatterns_te_IN');
    -goog.provide('goog.i18n.DateTimePatterns_teo');
    -goog.provide('goog.i18n.DateTimePatterns_teo_KE');
    -goog.provide('goog.i18n.DateTimePatterns_teo_UG');
    -goog.provide('goog.i18n.DateTimePatterns_th_TH');
    -goog.provide('goog.i18n.DateTimePatterns_ti');
    -goog.provide('goog.i18n.DateTimePatterns_ti_ER');
    -goog.provide('goog.i18n.DateTimePatterns_ti_ET');
    -goog.provide('goog.i18n.DateTimePatterns_to');
    -goog.provide('goog.i18n.DateTimePatterns_to_TO');
    -goog.provide('goog.i18n.DateTimePatterns_tr_CY');
    -goog.provide('goog.i18n.DateTimePatterns_tr_TR');
    -goog.provide('goog.i18n.DateTimePatterns_twq');
    -goog.provide('goog.i18n.DateTimePatterns_twq_NE');
    -goog.provide('goog.i18n.DateTimePatterns_tzm');
    -goog.provide('goog.i18n.DateTimePatterns_tzm_Latn');
    -goog.provide('goog.i18n.DateTimePatterns_tzm_Latn_MA');
    -goog.provide('goog.i18n.DateTimePatterns_ug');
    -goog.provide('goog.i18n.DateTimePatterns_ug_Arab');
    -goog.provide('goog.i18n.DateTimePatterns_ug_Arab_CN');
    -goog.provide('goog.i18n.DateTimePatterns_uk_UA');
    -goog.provide('goog.i18n.DateTimePatterns_ur_IN');
    -goog.provide('goog.i18n.DateTimePatterns_ur_PK');
    -goog.provide('goog.i18n.DateTimePatterns_uz_Arab');
    -goog.provide('goog.i18n.DateTimePatterns_uz_Arab_AF');
    -goog.provide('goog.i18n.DateTimePatterns_uz_Cyrl');
    -goog.provide('goog.i18n.DateTimePatterns_uz_Cyrl_UZ');
    -goog.provide('goog.i18n.DateTimePatterns_uz_Latn');
    -goog.provide('goog.i18n.DateTimePatterns_uz_Latn_UZ');
    -goog.provide('goog.i18n.DateTimePatterns_vai');
    -goog.provide('goog.i18n.DateTimePatterns_vai_Latn');
    -goog.provide('goog.i18n.DateTimePatterns_vai_Latn_LR');
    -goog.provide('goog.i18n.DateTimePatterns_vai_Vaii');
    -goog.provide('goog.i18n.DateTimePatterns_vai_Vaii_LR');
    -goog.provide('goog.i18n.DateTimePatterns_vi_VN');
    -goog.provide('goog.i18n.DateTimePatterns_vun');
    -goog.provide('goog.i18n.DateTimePatterns_vun_TZ');
    -goog.provide('goog.i18n.DateTimePatterns_wae');
    -goog.provide('goog.i18n.DateTimePatterns_wae_CH');
    -goog.provide('goog.i18n.DateTimePatterns_xog');
    -goog.provide('goog.i18n.DateTimePatterns_xog_UG');
    -goog.provide('goog.i18n.DateTimePatterns_yav');
    -goog.provide('goog.i18n.DateTimePatterns_yav_CM');
    -goog.provide('goog.i18n.DateTimePatterns_yi');
    -goog.provide('goog.i18n.DateTimePatterns_yi_001');
    -goog.provide('goog.i18n.DateTimePatterns_yo');
    -goog.provide('goog.i18n.DateTimePatterns_yo_BJ');
    -goog.provide('goog.i18n.DateTimePatterns_yo_NG');
    -goog.provide('goog.i18n.DateTimePatterns_zgh');
    -goog.provide('goog.i18n.DateTimePatterns_zgh_MA');
    -goog.provide('goog.i18n.DateTimePatterns_zh_Hans');
    -goog.provide('goog.i18n.DateTimePatterns_zh_Hans_CN');
    -goog.provide('goog.i18n.DateTimePatterns_zh_Hans_HK');
    -goog.provide('goog.i18n.DateTimePatterns_zh_Hans_MO');
    -goog.provide('goog.i18n.DateTimePatterns_zh_Hans_SG');
    -goog.provide('goog.i18n.DateTimePatterns_zh_Hant');
    -goog.provide('goog.i18n.DateTimePatterns_zh_Hant_HK');
    -goog.provide('goog.i18n.DateTimePatterns_zh_Hant_MO');
    -goog.provide('goog.i18n.DateTimePatterns_zh_Hant_TW');
    -goog.provide('goog.i18n.DateTimePatterns_zu_ZA');
    -
    -goog.require('goog.i18n.DateTimePatterns');
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale af_NA.
    - */
    -goog.i18n.DateTimePatterns_af_NA = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd-MM',
    -  MONTH_DAY_MEDIUM: 'd MMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale af_ZA.
    - */
    -goog.i18n.DateTimePatterns_af_ZA = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd-MM',
    -  MONTH_DAY_MEDIUM: 'd MMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale agq.
    - */
    -goog.i18n.DateTimePatterns_agq = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale agq_CM.
    - */
    -goog.i18n.DateTimePatterns_agq_CM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ak.
    - */
    -goog.i18n.DateTimePatterns_ak = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ak_GH.
    - */
    -goog.i18n.DateTimePatterns_ak_GH = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale am_ET.
    - */
    -goog.i18n.DateTimePatterns_am_ET = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE፣ MMM d y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ar_001.
    - */
    -goog.i18n.DateTimePatterns_ar_001 = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/‏M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ar_AE.
    - */
    -goog.i18n.DateTimePatterns_ar_AE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/‏M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ar_BH.
    - */
    -goog.i18n.DateTimePatterns_ar_BH = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/‏M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ar_DJ.
    - */
    -goog.i18n.DateTimePatterns_ar_DJ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/‏M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ar_DZ.
    - */
    -goog.i18n.DateTimePatterns_ar_DZ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ar_EG.
    - */
    -goog.i18n.DateTimePatterns_ar_EG = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/‏M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ar_EH.
    - */
    -goog.i18n.DateTimePatterns_ar_EH = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/‏M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ar_ER.
    - */
    -goog.i18n.DateTimePatterns_ar_ER = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/‏M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ar_IL.
    - */
    -goog.i18n.DateTimePatterns_ar_IL = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/‏M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ar_IQ.
    - */
    -goog.i18n.DateTimePatterns_ar_IQ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/‏M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ar_JO.
    - */
    -goog.i18n.DateTimePatterns_ar_JO = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/‏M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ar_KM.
    - */
    -goog.i18n.DateTimePatterns_ar_KM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/‏M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ar_KW.
    - */
    -goog.i18n.DateTimePatterns_ar_KW = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/‏M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ar_LB.
    - */
    -goog.i18n.DateTimePatterns_ar_LB = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/‏M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ar_LY.
    - */
    -goog.i18n.DateTimePatterns_ar_LY = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/‏M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ar_MA.
    - */
    -goog.i18n.DateTimePatterns_ar_MA = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ar_MR.
    - */
    -goog.i18n.DateTimePatterns_ar_MR = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/‏M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ar_OM.
    - */
    -goog.i18n.DateTimePatterns_ar_OM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/‏M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ar_PS.
    - */
    -goog.i18n.DateTimePatterns_ar_PS = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/‏M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ar_QA.
    - */
    -goog.i18n.DateTimePatterns_ar_QA = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/‏M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ar_SA.
    - */
    -goog.i18n.DateTimePatterns_ar_SA = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/‏M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ar_SD.
    - */
    -goog.i18n.DateTimePatterns_ar_SD = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/‏M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ar_SO.
    - */
    -goog.i18n.DateTimePatterns_ar_SO = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/‏M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ar_SS.
    - */
    -goog.i18n.DateTimePatterns_ar_SS = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/‏M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ar_SY.
    - */
    -goog.i18n.DateTimePatterns_ar_SY = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/‏M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ar_TD.
    - */
    -goog.i18n.DateTimePatterns_ar_TD = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/‏M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ar_TN.
    - */
    -goog.i18n.DateTimePatterns_ar_TN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ar_YE.
    - */
    -goog.i18n.DateTimePatterns_ar_YE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/‏M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale as.
    - */
    -goog.i18n.DateTimePatterns_as = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale as_IN.
    - */
    -goog.i18n.DateTimePatterns_as_IN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale asa.
    - */
    -goog.i18n.DateTimePatterns_asa = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale asa_TZ.
    - */
    -goog.i18n.DateTimePatterns_asa_TZ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale az_Cyrl.
    - */
    -goog.i18n.DateTimePatterns_az_Cyrl = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM, y',
    -  YEAR_MONTH_FULL: 'MMMM, y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d, MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d, MMM, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale az_Cyrl_AZ.
    - */
    -goog.i18n.DateTimePatterns_az_Cyrl_AZ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM, y',
    -  YEAR_MONTH_FULL: 'MMMM, y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d, MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d, MMM, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale az_Latn.
    - */
    -goog.i18n.DateTimePatterns_az_Latn = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'd MMM, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'd MMM y, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale az_Latn_AZ.
    - */
    -goog.i18n.DateTimePatterns_az_Latn_AZ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'd MMM, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'd MMM y, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale bas.
    - */
    -goog.i18n.DateTimePatterns_bas = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale bas_CM.
    - */
    -goog.i18n.DateTimePatterns_bas_CM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale be.
    - */
    -goog.i18n.DateTimePatterns_be = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'LLL y',
    -  YEAR_MONTH_FULL: 'LLLL y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd.M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale be_BY.
    - */
    -goog.i18n.DateTimePatterns_be_BY = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'LLL y',
    -  YEAR_MONTH_FULL: 'LLLL y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd.M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale bem.
    - */
    -goog.i18n.DateTimePatterns_bem = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale bem_ZM.
    - */
    -goog.i18n.DateTimePatterns_bem_ZM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale bez.
    - */
    -goog.i18n.DateTimePatterns_bez = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale bez_TZ.
    - */
    -goog.i18n.DateTimePatterns_bez_TZ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale bg_BG.
    - */
    -goog.i18n.DateTimePatterns_bg_BG = {
    -  YEAR_FULL: 'y \'г\'.',
    -  YEAR_FULL_WITH_ERA: 'y \'г\'. G',
    -  YEAR_MONTH_ABBR: 'MM.y \'г\'.',
    -  YEAR_MONTH_FULL: 'MMMM y \'г\'.',
    -  MONTH_DAY_ABBR: 'd.MM',
    -  MONTH_DAY_FULL: 'd MMMM',
    -  MONTH_DAY_SHORT: 'd.MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd.MM.y \'г\'.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d.MM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d.MM.y \'г\'.',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale bm.
    - */
    -goog.i18n.DateTimePatterns_bm = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale bm_Latn.
    - */
    -goog.i18n.DateTimePatterns_bm_Latn = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale bm_Latn_ML.
    - */
    -goog.i18n.DateTimePatterns_bm_Latn_ML = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale bn_BD.
    - */
    -goog.i18n.DateTimePatterns_bn_BD = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale bn_IN.
    - */
    -goog.i18n.DateTimePatterns_bn_IN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale bo.
    - */
    -goog.i18n.DateTimePatterns_bo = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y ལོ་འི་MMMཙེས་d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale bo_CN.
    - */
    -goog.i18n.DateTimePatterns_bo_CN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y ལོ་འི་MMMཙེས་d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale bo_IN.
    - */
    -goog.i18n.DateTimePatterns_bo_IN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y ལོ་འི་MMMཙེས་d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale br_FR.
    - */
    -goog.i18n.DateTimePatterns_br_FR = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale brx.
    - */
    -goog.i18n.DateTimePatterns_brx = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd-MMM',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale brx_IN.
    - */
    -goog.i18n.DateTimePatterns_brx_IN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd-MMM',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale bs.
    - */
    -goog.i18n.DateTimePatterns_bs = {
    -  YEAR_FULL: 'y.',
    -  YEAR_FULL_WITH_ERA: 'y. G',
    -  YEAR_MONTH_ABBR: 'MMM y.',
    -  YEAR_MONTH_FULL: 'LLLL y.',
    -  MONTH_DAY_ABBR: 'dd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'dd. MMM y.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, dd. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, dd. MMM y.',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale bs_Cyrl.
    - */
    -goog.i18n.DateTimePatterns_bs_Cyrl = {
    -  YEAR_FULL: 'y.',
    -  YEAR_FULL_WITH_ERA: 'y. G',
    -  YEAR_MONTH_ABBR: 'MMM y.',
    -  YEAR_MONTH_FULL: 'MMMM y.',
    -  MONTH_DAY_ABBR: 'dd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM.',
    -  MONTH_DAY_MEDIUM: 'dd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'dd. MMM y.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, dd. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, dd. MMM y.',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale bs_Cyrl_BA.
    - */
    -goog.i18n.DateTimePatterns_bs_Cyrl_BA = {
    -  YEAR_FULL: 'y.',
    -  YEAR_FULL_WITH_ERA: 'y. G',
    -  YEAR_MONTH_ABBR: 'MMM y.',
    -  YEAR_MONTH_FULL: 'MMMM y.',
    -  MONTH_DAY_ABBR: 'dd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM.',
    -  MONTH_DAY_MEDIUM: 'dd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'dd. MMM y.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, dd. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, dd. MMM y.',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale bs_Latn.
    - */
    -goog.i18n.DateTimePatterns_bs_Latn = {
    -  YEAR_FULL: 'y.',
    -  YEAR_FULL_WITH_ERA: 'y. G',
    -  YEAR_MONTH_ABBR: 'MMM y.',
    -  YEAR_MONTH_FULL: 'LLLL y.',
    -  MONTH_DAY_ABBR: 'dd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'dd. MMM y.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, dd. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, dd. MMM y.',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale bs_Latn_BA.
    - */
    -goog.i18n.DateTimePatterns_bs_Latn_BA = {
    -  YEAR_FULL: 'y.',
    -  YEAR_FULL_WITH_ERA: 'y. G',
    -  YEAR_MONTH_ABBR: 'MMM y.',
    -  YEAR_MONTH_FULL: 'LLLL y.',
    -  MONTH_DAY_ABBR: 'dd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'dd. MMM y.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, dd. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, dd. MMM y.',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ca_AD.
    - */
    -goog.i18n.DateTimePatterns_ca_AD = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'LLL \'de\' y',
    -  YEAR_MONTH_FULL: 'LLLL \'de\' y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ca_ES.
    - */
    -goog.i18n.DateTimePatterns_ca_ES = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'LLL \'de\' y',
    -  YEAR_MONTH_FULL: 'LLLL \'de\' y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ca_FR.
    - */
    -goog.i18n.DateTimePatterns_ca_FR = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'LLL \'de\' y',
    -  YEAR_MONTH_FULL: 'LLLL \'de\' y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ca_IT.
    - */
    -goog.i18n.DateTimePatterns_ca_IT = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'LLL \'de\' y',
    -  YEAR_MONTH_FULL: 'LLLL \'de\' y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale cgg.
    - */
    -goog.i18n.DateTimePatterns_cgg = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale cgg_UG.
    - */
    -goog.i18n.DateTimePatterns_cgg_UG = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale chr_US.
    - */
    -goog.i18n.DateTimePatterns_chr_US = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale cs_CZ.
    - */
    -goog.i18n.DateTimePatterns_cs_CZ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'LLLL y',
    -  YEAR_MONTH_FULL: 'LLLL y',
    -  MONTH_DAY_ABBR: 'd. M.',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd. M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. M. y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. M.',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d. M. y',
    -  DAY_ABBR: 'd.'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale cy_GB.
    - */
    -goog.i18n.DateTimePatterns_cy_GB = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale da_DK.
    - */
    -goog.i18n.DateTimePatterns_da_DK = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d. MMM y',
    -  DAY_ABBR: 'd.'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale da_GL.
    - */
    -goog.i18n.DateTimePatterns_da_GL = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d. MMM y',
    -  DAY_ABBR: 'd.'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale dav.
    - */
    -goog.i18n.DateTimePatterns_dav = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale dav_KE.
    - */
    -goog.i18n.DateTimePatterns_dav_KE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale de_BE.
    - */
    -goog.i18n.DateTimePatterns_de_BE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale de_DE.
    - */
    -goog.i18n.DateTimePatterns_de_DE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale de_LI.
    - */
    -goog.i18n.DateTimePatterns_de_LI = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale de_LU.
    - */
    -goog.i18n.DateTimePatterns_de_LU = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale dje.
    - */
    -goog.i18n.DateTimePatterns_dje = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale dje_NE.
    - */
    -goog.i18n.DateTimePatterns_dje_NE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale dsb.
    - */
    -goog.i18n.DateTimePatterns_dsb = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale dsb_DE.
    - */
    -goog.i18n.DateTimePatterns_dsb_DE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale dua.
    - */
    -goog.i18n.DateTimePatterns_dua = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale dua_CM.
    - */
    -goog.i18n.DateTimePatterns_dua_CM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale dyo.
    - */
    -goog.i18n.DateTimePatterns_dyo = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale dyo_SN.
    - */
    -goog.i18n.DateTimePatterns_dyo_SN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale dz.
    - */
    -goog.i18n.DateTimePatterns_dz = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y སྤྱི་ཟླ་MMM',
    -  YEAR_MONTH_FULL: 'y སྤྱི་ཟླ་MMMM',
    -  MONTH_DAY_ABBR: 'སྤྱི་LLL ཚེ་d',
    -  MONTH_DAY_FULL: 'སྤྱི་LLLL ཚེ་dd',
    -  MONTH_DAY_SHORT: 'M-d',
    -  MONTH_DAY_MEDIUM: 'སྤྱི་LLLL ཚེ་d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, སྤྱི་LLL ཚེ་d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'གཟའ་EEE, ལོy ཟླ་MMM ཚེ་d',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale dz_BT.
    - */
    -goog.i18n.DateTimePatterns_dz_BT = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y སྤྱི་ཟླ་MMM',
    -  YEAR_MONTH_FULL: 'y སྤྱི་ཟླ་MMMM',
    -  MONTH_DAY_ABBR: 'སྤྱི་LLL ཚེ་d',
    -  MONTH_DAY_FULL: 'སྤྱི་LLLL ཚེ་dd',
    -  MONTH_DAY_SHORT: 'M-d',
    -  MONTH_DAY_MEDIUM: 'སྤྱི་LLLL ཚེ་d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, སྤྱི་LLL ཚེ་d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'གཟའ་EEE, ལོy ཟླ་MMM ཚེ་d',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ebu.
    - */
    -goog.i18n.DateTimePatterns_ebu = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ebu_KE.
    - */
    -goog.i18n.DateTimePatterns_ebu_KE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ee.
    - */
    -goog.i18n.DateTimePatterns_ee = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d \'lia\'',
    -  MONTH_DAY_FULL: 'MMMM dd \'lia\'',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d \'lia\'',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d \'lia\', y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d \'lia\'',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ee_GH.
    - */
    -goog.i18n.DateTimePatterns_ee_GH = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d \'lia\'',
    -  MONTH_DAY_FULL: 'MMMM dd \'lia\'',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d \'lia\'',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d \'lia\', y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d \'lia\'',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ee_TG.
    - */
    -goog.i18n.DateTimePatterns_ee_TG = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d \'lia\'',
    -  MONTH_DAY_FULL: 'MMMM dd \'lia\'',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d \'lia\'',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d \'lia\', y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d \'lia\'',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale el_CY.
    - */
    -goog.i18n.DateTimePatterns_el_CY = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale el_GR.
    - */
    -goog.i18n.DateTimePatterns_el_GR = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_001.
    - */
    -goog.i18n.DateTimePatterns_en_001 = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_150.
    - */
    -goog.i18n.DateTimePatterns_en_150 = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_AG.
    - */
    -goog.i18n.DateTimePatterns_en_AG = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_AI.
    - */
    -goog.i18n.DateTimePatterns_en_AI = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_AS.
    - */
    -goog.i18n.DateTimePatterns_en_AS = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_BB.
    - */
    -goog.i18n.DateTimePatterns_en_BB = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_BE.
    - */
    -goog.i18n.DateTimePatterns_en_BE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_BM.
    - */
    -goog.i18n.DateTimePatterns_en_BM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_BS.
    - */
    -goog.i18n.DateTimePatterns_en_BS = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_BW.
    - */
    -goog.i18n.DateTimePatterns_en_BW = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'dd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'dd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'dd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE dd MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE dd MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_BZ.
    - */
    -goog.i18n.DateTimePatterns_en_BZ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'dd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'dd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'dd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE dd MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE dd MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_CA.
    - */
    -goog.i18n.DateTimePatterns_en_CA = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_CC.
    - */
    -goog.i18n.DateTimePatterns_en_CC = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_CK.
    - */
    -goog.i18n.DateTimePatterns_en_CK = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_CM.
    - */
    -goog.i18n.DateTimePatterns_en_CM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_CX.
    - */
    -goog.i18n.DateTimePatterns_en_CX = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_DG.
    - */
    -goog.i18n.DateTimePatterns_en_DG = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_DM.
    - */
    -goog.i18n.DateTimePatterns_en_DM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_ER.
    - */
    -goog.i18n.DateTimePatterns_en_ER = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_FJ.
    - */
    -goog.i18n.DateTimePatterns_en_FJ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_FK.
    - */
    -goog.i18n.DateTimePatterns_en_FK = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_FM.
    - */
    -goog.i18n.DateTimePatterns_en_FM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_GD.
    - */
    -goog.i18n.DateTimePatterns_en_GD = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_GG.
    - */
    -goog.i18n.DateTimePatterns_en_GG = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_GH.
    - */
    -goog.i18n.DateTimePatterns_en_GH = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_GI.
    - */
    -goog.i18n.DateTimePatterns_en_GI = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_GM.
    - */
    -goog.i18n.DateTimePatterns_en_GM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_GU.
    - */
    -goog.i18n.DateTimePatterns_en_GU = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_GY.
    - */
    -goog.i18n.DateTimePatterns_en_GY = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_HK.
    - */
    -goog.i18n.DateTimePatterns_en_HK = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_IM.
    - */
    -goog.i18n.DateTimePatterns_en_IM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_IO.
    - */
    -goog.i18n.DateTimePatterns_en_IO = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_JE.
    - */
    -goog.i18n.DateTimePatterns_en_JE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_JM.
    - */
    -goog.i18n.DateTimePatterns_en_JM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_KE.
    - */
    -goog.i18n.DateTimePatterns_en_KE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_KI.
    - */
    -goog.i18n.DateTimePatterns_en_KI = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_KN.
    - */
    -goog.i18n.DateTimePatterns_en_KN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_KY.
    - */
    -goog.i18n.DateTimePatterns_en_KY = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_LC.
    - */
    -goog.i18n.DateTimePatterns_en_LC = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_LR.
    - */
    -goog.i18n.DateTimePatterns_en_LR = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_LS.
    - */
    -goog.i18n.DateTimePatterns_en_LS = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_MG.
    - */
    -goog.i18n.DateTimePatterns_en_MG = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_MH.
    - */
    -goog.i18n.DateTimePatterns_en_MH = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_MO.
    - */
    -goog.i18n.DateTimePatterns_en_MO = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_MP.
    - */
    -goog.i18n.DateTimePatterns_en_MP = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_MS.
    - */
    -goog.i18n.DateTimePatterns_en_MS = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_MT.
    - */
    -goog.i18n.DateTimePatterns_en_MT = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'dd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'dd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, dd MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_MU.
    - */
    -goog.i18n.DateTimePatterns_en_MU = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_MW.
    - */
    -goog.i18n.DateTimePatterns_en_MW = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_MY.
    - */
    -goog.i18n.DateTimePatterns_en_MY = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_NA.
    - */
    -goog.i18n.DateTimePatterns_en_NA = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_NF.
    - */
    -goog.i18n.DateTimePatterns_en_NF = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_NG.
    - */
    -goog.i18n.DateTimePatterns_en_NG = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_NR.
    - */
    -goog.i18n.DateTimePatterns_en_NR = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_NU.
    - */
    -goog.i18n.DateTimePatterns_en_NU = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_NZ.
    - */
    -goog.i18n.DateTimePatterns_en_NZ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_PG.
    - */
    -goog.i18n.DateTimePatterns_en_PG = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_PH.
    - */
    -goog.i18n.DateTimePatterns_en_PH = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_PK.
    - */
    -goog.i18n.DateTimePatterns_en_PK = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_PN.
    - */
    -goog.i18n.DateTimePatterns_en_PN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_PR.
    - */
    -goog.i18n.DateTimePatterns_en_PR = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_PW.
    - */
    -goog.i18n.DateTimePatterns_en_PW = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_RW.
    - */
    -goog.i18n.DateTimePatterns_en_RW = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_SB.
    - */
    -goog.i18n.DateTimePatterns_en_SB = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_SC.
    - */
    -goog.i18n.DateTimePatterns_en_SC = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_SD.
    - */
    -goog.i18n.DateTimePatterns_en_SD = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_SH.
    - */
    -goog.i18n.DateTimePatterns_en_SH = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_SL.
    - */
    -goog.i18n.DateTimePatterns_en_SL = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_SS.
    - */
    -goog.i18n.DateTimePatterns_en_SS = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_SX.
    - */
    -goog.i18n.DateTimePatterns_en_SX = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_SZ.
    - */
    -goog.i18n.DateTimePatterns_en_SZ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_TC.
    - */
    -goog.i18n.DateTimePatterns_en_TC = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_TK.
    - */
    -goog.i18n.DateTimePatterns_en_TK = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_TO.
    - */
    -goog.i18n.DateTimePatterns_en_TO = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_TT.
    - */
    -goog.i18n.DateTimePatterns_en_TT = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_TV.
    - */
    -goog.i18n.DateTimePatterns_en_TV = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_TZ.
    - */
    -goog.i18n.DateTimePatterns_en_TZ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_UG.
    - */
    -goog.i18n.DateTimePatterns_en_UG = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_UM.
    - */
    -goog.i18n.DateTimePatterns_en_UM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_US_POSIX.
    - */
    -goog.i18n.DateTimePatterns_en_US_POSIX = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_VC.
    - */
    -goog.i18n.DateTimePatterns_en_VC = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_VG.
    - */
    -goog.i18n.DateTimePatterns_en_VG = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_VI.
    - */
    -goog.i18n.DateTimePatterns_en_VI = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_VU.
    - */
    -goog.i18n.DateTimePatterns_en_VU = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_WS.
    - */
    -goog.i18n.DateTimePatterns_en_WS = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_ZM.
    - */
    -goog.i18n.DateTimePatterns_en_ZM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale en_ZW.
    - */
    -goog.i18n.DateTimePatterns_en_ZW = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'dd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'dd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'dd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE dd MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, dd MMM, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale eo.
    - */
    -goog.i18n.DateTimePatterns_eo = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale es_AR.
    - */
    -goog.i18n.DateTimePatterns_es_AR = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd \'de\' MMM',
    -  MONTH_DAY_FULL: 'dd-MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d \'de\' MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale es_BO.
    - */
    -goog.i18n.DateTimePatterns_es_BO = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd \'de\' MMM',
    -  MONTH_DAY_FULL: 'dd-MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d \'de\' MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale es_CL.
    - */
    -goog.i18n.DateTimePatterns_es_CL = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd \'de\' MMM',
    -  MONTH_DAY_FULL: 'dd-MMMM',
    -  MONTH_DAY_SHORT: 'dd-MM',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d \'de\' MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale es_CO.
    - */
    -goog.i18n.DateTimePatterns_es_CO = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd \'de\' MMM',
    -  MONTH_DAY_FULL: 'dd-MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d \'de\' MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale es_CR.
    - */
    -goog.i18n.DateTimePatterns_es_CR = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd \'de\' MMM',
    -  MONTH_DAY_FULL: 'dd-MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d \'de\' MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale es_CU.
    - */
    -goog.i18n.DateTimePatterns_es_CU = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd \'de\' MMM',
    -  MONTH_DAY_FULL: 'dd-MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d \'de\' MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale es_DO.
    - */
    -goog.i18n.DateTimePatterns_es_DO = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd \'de\' MMM',
    -  MONTH_DAY_FULL: 'dd-MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d \'de\' MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale es_EA.
    - */
    -goog.i18n.DateTimePatterns_es_EA = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd \'de\' MMM',
    -  MONTH_DAY_FULL: 'dd \'de\' MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d \'de\' MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale es_EC.
    - */
    -goog.i18n.DateTimePatterns_es_EC = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd \'de\' MMM',
    -  MONTH_DAY_FULL: 'dd-MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d \'de\' MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale es_GQ.
    - */
    -goog.i18n.DateTimePatterns_es_GQ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd \'de\' MMM',
    -  MONTH_DAY_FULL: 'dd \'de\' MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d \'de\' MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale es_GT.
    - */
    -goog.i18n.DateTimePatterns_es_GT = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd \'de\' MMM',
    -  MONTH_DAY_FULL: 'dd-MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d \'de\' MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale es_HN.
    - */
    -goog.i18n.DateTimePatterns_es_HN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd \'de\' MMM',
    -  MONTH_DAY_FULL: 'dd-MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d \'de\' MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale es_IC.
    - */
    -goog.i18n.DateTimePatterns_es_IC = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd \'de\' MMM',
    -  MONTH_DAY_FULL: 'dd \'de\' MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d \'de\' MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale es_MX.
    - */
    -goog.i18n.DateTimePatterns_es_MX = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd \'de\' MMM',
    -  MONTH_DAY_FULL: 'dd-MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d \'de\' MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale es_NI.
    - */
    -goog.i18n.DateTimePatterns_es_NI = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd \'de\' MMM',
    -  MONTH_DAY_FULL: 'dd-MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d \'de\' MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale es_PA.
    - */
    -goog.i18n.DateTimePatterns_es_PA = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd \'de\' MMM',
    -  MONTH_DAY_FULL: 'dd-MMMM',
    -  MONTH_DAY_SHORT: 'MM/dd',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d \'de\' MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale es_PE.
    - */
    -goog.i18n.DateTimePatterns_es_PE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd \'de\' MMM',
    -  MONTH_DAY_FULL: 'dd-MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d \'de\' MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale es_PH.
    - */
    -goog.i18n.DateTimePatterns_es_PH = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd \'de\' MMM',
    -  MONTH_DAY_FULL: 'dd \'de\' MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d \'de\' MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale es_PR.
    - */
    -goog.i18n.DateTimePatterns_es_PR = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd \'de\' MMM',
    -  MONTH_DAY_FULL: 'dd-MMMM',
    -  MONTH_DAY_SHORT: 'MM/dd',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d \'de\' MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale es_PY.
    - */
    -goog.i18n.DateTimePatterns_es_PY = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd \'de\' MMM',
    -  MONTH_DAY_FULL: 'dd-MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d \'de\' MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale es_SV.
    - */
    -goog.i18n.DateTimePatterns_es_SV = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd \'de\' MMM',
    -  MONTH_DAY_FULL: 'dd-MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d \'de\' MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale es_US.
    - */
    -goog.i18n.DateTimePatterns_es_US = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd \'de\' MMM',
    -  MONTH_DAY_FULL: 'dd-MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d \'de\' MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale es_UY.
    - */
    -goog.i18n.DateTimePatterns_es_UY = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd \'de\' MMM',
    -  MONTH_DAY_FULL: 'dd-MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d \'de\' MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale es_VE.
    - */
    -goog.i18n.DateTimePatterns_es_VE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd \'de\' MMM',
    -  MONTH_DAY_FULL: 'dd-MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d \'de\' MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale et_EE.
    - */
    -goog.i18n.DateTimePatterns_et_EE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale eu_ES.
    - */
    -goog.i18n.DateTimePatterns_eu_ES = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y(\'e\')\'ko\' MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ewo.
    - */
    -goog.i18n.DateTimePatterns_ewo = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ewo_CM.
    - */
    -goog.i18n.DateTimePatterns_ewo_CM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fa_AF.
    - */
    -goog.i18n.DateTimePatterns_fa_AF = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd LLL',
    -  MONTH_DAY_FULL: 'dd LLLL',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'd LLLL',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d LLL',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fa_IR.
    - */
    -goog.i18n.DateTimePatterns_fa_IR = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd LLL',
    -  MONTH_DAY_FULL: 'dd LLLL',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'd LLLL',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d LLL',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ff.
    - */
    -goog.i18n.DateTimePatterns_ff = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ff_CM.
    - */
    -goog.i18n.DateTimePatterns_ff_CM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ff_GN.
    - */
    -goog.i18n.DateTimePatterns_ff_GN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ff_MR.
    - */
    -goog.i18n.DateTimePatterns_ff_MR = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ff_SN.
    - */
    -goog.i18n.DateTimePatterns_ff_SN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fi_FI.
    - */
    -goog.i18n.DateTimePatterns_fi_FI = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'LLL y',
    -  YEAR_MONTH_FULL: 'LLLL y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'ccc d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d. MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fil_PH.
    - */
    -goog.i18n.DateTimePatterns_fil_PH = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fo.
    - */
    -goog.i18n.DateTimePatterns_fo = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M-d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, y MMM d',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fo_FO.
    - */
    -goog.i18n.DateTimePatterns_fo_FO = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M-d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, y MMM d',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_BE.
    - */
    -goog.i18n.DateTimePatterns_fr_BE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_BF.
    - */
    -goog.i18n.DateTimePatterns_fr_BF = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_BI.
    - */
    -goog.i18n.DateTimePatterns_fr_BI = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_BJ.
    - */
    -goog.i18n.DateTimePatterns_fr_BJ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_BL.
    - */
    -goog.i18n.DateTimePatterns_fr_BL = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_CD.
    - */
    -goog.i18n.DateTimePatterns_fr_CD = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_CF.
    - */
    -goog.i18n.DateTimePatterns_fr_CF = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_CG.
    - */
    -goog.i18n.DateTimePatterns_fr_CG = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_CH.
    - */
    -goog.i18n.DateTimePatterns_fr_CH = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_CI.
    - */
    -goog.i18n.DateTimePatterns_fr_CI = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_CM.
    - */
    -goog.i18n.DateTimePatterns_fr_CM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_DJ.
    - */
    -goog.i18n.DateTimePatterns_fr_DJ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_DZ.
    - */
    -goog.i18n.DateTimePatterns_fr_DZ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_FR.
    - */
    -goog.i18n.DateTimePatterns_fr_FR = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_GA.
    - */
    -goog.i18n.DateTimePatterns_fr_GA = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_GF.
    - */
    -goog.i18n.DateTimePatterns_fr_GF = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_GN.
    - */
    -goog.i18n.DateTimePatterns_fr_GN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_GP.
    - */
    -goog.i18n.DateTimePatterns_fr_GP = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_GQ.
    - */
    -goog.i18n.DateTimePatterns_fr_GQ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_HT.
    - */
    -goog.i18n.DateTimePatterns_fr_HT = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_KM.
    - */
    -goog.i18n.DateTimePatterns_fr_KM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_LU.
    - */
    -goog.i18n.DateTimePatterns_fr_LU = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_MA.
    - */
    -goog.i18n.DateTimePatterns_fr_MA = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_MC.
    - */
    -goog.i18n.DateTimePatterns_fr_MC = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_MF.
    - */
    -goog.i18n.DateTimePatterns_fr_MF = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_MG.
    - */
    -goog.i18n.DateTimePatterns_fr_MG = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_ML.
    - */
    -goog.i18n.DateTimePatterns_fr_ML = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_MQ.
    - */
    -goog.i18n.DateTimePatterns_fr_MQ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_MR.
    - */
    -goog.i18n.DateTimePatterns_fr_MR = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_MU.
    - */
    -goog.i18n.DateTimePatterns_fr_MU = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_NC.
    - */
    -goog.i18n.DateTimePatterns_fr_NC = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_NE.
    - */
    -goog.i18n.DateTimePatterns_fr_NE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_PF.
    - */
    -goog.i18n.DateTimePatterns_fr_PF = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_PM.
    - */
    -goog.i18n.DateTimePatterns_fr_PM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_RE.
    - */
    -goog.i18n.DateTimePatterns_fr_RE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_RW.
    - */
    -goog.i18n.DateTimePatterns_fr_RW = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_SC.
    - */
    -goog.i18n.DateTimePatterns_fr_SC = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_SN.
    - */
    -goog.i18n.DateTimePatterns_fr_SN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_SY.
    - */
    -goog.i18n.DateTimePatterns_fr_SY = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_TD.
    - */
    -goog.i18n.DateTimePatterns_fr_TD = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_TG.
    - */
    -goog.i18n.DateTimePatterns_fr_TG = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_TN.
    - */
    -goog.i18n.DateTimePatterns_fr_TN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_VU.
    - */
    -goog.i18n.DateTimePatterns_fr_VU = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_WF.
    - */
    -goog.i18n.DateTimePatterns_fr_WF = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fr_YT.
    - */
    -goog.i18n.DateTimePatterns_fr_YT = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fur.
    - */
    -goog.i18n.DateTimePatterns_fur = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'LLLL \'dal\' y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd \'di\' MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'di\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fur_IT.
    - */
    -goog.i18n.DateTimePatterns_fur_IT = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'LLLL \'dal\' y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd \'di\' MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'di\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fy.
    - */
    -goog.i18n.DateTimePatterns_fy = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd-M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale fy_NL.
    - */
    -goog.i18n.DateTimePatterns_fy_NL = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd-M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ga_IE.
    - */
    -goog.i18n.DateTimePatterns_ga_IE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale gd.
    - */
    -goog.i18n.DateTimePatterns_gd = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'LLLL y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd\'mh\' MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd\'mh\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale gd_GB.
    - */
    -goog.i18n.DateTimePatterns_gd_GB = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'LLLL y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd\'mh\' MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd\'mh\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale gl_ES.
    - */
    -goog.i18n.DateTimePatterns_gl_ES = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd-M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale gsw_CH.
    - */
    -goog.i18n.DateTimePatterns_gsw_CH = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale gsw_FR.
    - */
    -goog.i18n.DateTimePatterns_gsw_FR = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale gsw_LI.
    - */
    -goog.i18n.DateTimePatterns_gsw_LI = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale gu_IN.
    - */
    -goog.i18n.DateTimePatterns_gu_IN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale guz.
    - */
    -goog.i18n.DateTimePatterns_guz = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale guz_KE.
    - */
    -goog.i18n.DateTimePatterns_guz_KE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale gv.
    - */
    -goog.i18n.DateTimePatterns_gv = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale gv_IM.
    - */
    -goog.i18n.DateTimePatterns_gv_IM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ha.
    - */
    -goog.i18n.DateTimePatterns_ha = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ha_Latn.
    - */
    -goog.i18n.DateTimePatterns_ha_Latn = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ha_Latn_GH.
    - */
    -goog.i18n.DateTimePatterns_ha_Latn_GH = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ha_Latn_NE.
    - */
    -goog.i18n.DateTimePatterns_ha_Latn_NE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ha_Latn_NG.
    - */
    -goog.i18n.DateTimePatterns_ha_Latn_NG = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale haw_US.
    - */
    -goog.i18n.DateTimePatterns_haw_US = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale he_IL.
    - */
    -goog.i18n.DateTimePatterns_he_IL = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd בMMM',
    -  MONTH_DAY_FULL: 'dd בMMMM',
    -  MONTH_DAY_SHORT: 'd.M',
    -  MONTH_DAY_MEDIUM: 'd בMMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd בMMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d בMMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d בMMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale hi_IN.
    - */
    -goog.i18n.DateTimePatterns_hi_IN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale hr_BA.
    - */
    -goog.i18n.DateTimePatterns_hr_BA = {
    -  YEAR_FULL: 'y.',
    -  YEAR_FULL_WITH_ERA: 'y. G',
    -  YEAR_MONTH_ABBR: 'LLL y.',
    -  YEAR_MONTH_FULL: 'LLLL y.',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y.',
    -  DAY_ABBR: 'd.'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale hr_HR.
    - */
    -goog.i18n.DateTimePatterns_hr_HR = {
    -  YEAR_FULL: 'y.',
    -  YEAR_FULL_WITH_ERA: 'y. G',
    -  YEAR_MONTH_ABBR: 'LLL y.',
    -  YEAR_MONTH_FULL: 'LLLL y.',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y.',
    -  DAY_ABBR: 'd.'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale hsb.
    - */
    -goog.i18n.DateTimePatterns_hsb = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale hsb_DE.
    - */
    -goog.i18n.DateTimePatterns_hsb_DE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale hu_HU.
    - */
    -goog.i18n.DateTimePatterns_hu_HU = {
    -  YEAR_FULL: 'y.',
    -  YEAR_FULL_WITH_ERA: 'G y.',
    -  YEAR_MONTH_ABBR: 'y. MMM',
    -  YEAR_MONTH_FULL: 'y. MMMM',
    -  MONTH_DAY_ABBR: 'MMM d.',
    -  MONTH_DAY_FULL: 'MMMM dd.',
    -  MONTH_DAY_SHORT: 'M. d.',
    -  MONTH_DAY_MEDIUM: 'MMMM d.',
    -  MONTH_DAY_YEAR_MEDIUM: 'y. MMM d.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d., EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y. MMM d., EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale hy_AM.
    - */
    -goog.i18n.DateTimePatterns_hy_AM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G yթ.',
    -  YEAR_MONTH_ABBR: 'yթ. LLL',
    -  YEAR_MONTH_FULL: 'yթ. LLLL',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, yթ.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'd MMM, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'yթ. MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale id_ID.
    - */
    -goog.i18n.DateTimePatterns_id_ID = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ig.
    - */
    -goog.i18n.DateTimePatterns_ig = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ig_NG.
    - */
    -goog.i18n.DateTimePatterns_ig_NG = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ii.
    - */
    -goog.i18n.DateTimePatterns_ii = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ii_CN.
    - */
    -goog.i18n.DateTimePatterns_ii_CN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale is_IS.
    - */
    -goog.i18n.DateTimePatterns_is_IS = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale it_CH.
    - */
    -goog.i18n.DateTimePatterns_it_CH = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale it_IT.
    - */
    -goog.i18n.DateTimePatterns_it_IT = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale it_SM.
    - */
    -goog.i18n.DateTimePatterns_it_SM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ja_JP.
    - */
    -goog.i18n.DateTimePatterns_ja_JP = {
    -  YEAR_FULL: 'y年',
    -  YEAR_FULL_WITH_ERA: 'Gy年',
    -  YEAR_MONTH_ABBR: 'y年M月',
    -  YEAR_MONTH_FULL: 'y年M月',
    -  MONTH_DAY_ABBR: 'M月d日',
    -  MONTH_DAY_FULL: 'M月dd日',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'M月d日',
    -  MONTH_DAY_YEAR_MEDIUM: 'y年M月d日',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'M月d日(EEE)',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y年M月d日(EEE)',
    -  DAY_ABBR: 'd日'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale jgo.
    - */
    -goog.i18n.DateTimePatterns_jgo = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'd.M',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale jgo_CM.
    - */
    -goog.i18n.DateTimePatterns_jgo_CM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'd.M',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale jmc.
    - */
    -goog.i18n.DateTimePatterns_jmc = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale jmc_TZ.
    - */
    -goog.i18n.DateTimePatterns_jmc_TZ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ka_GE.
    - */
    -goog.i18n.DateTimePatterns_ka_GE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM, y',
    -  YEAR_MONTH_FULL: 'MMMM, y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd.M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale kab.
    - */
    -goog.i18n.DateTimePatterns_kab = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale kab_DZ.
    - */
    -goog.i18n.DateTimePatterns_kab_DZ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale kam.
    - */
    -goog.i18n.DateTimePatterns_kam = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale kam_KE.
    - */
    -goog.i18n.DateTimePatterns_kam_KE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale kde.
    - */
    -goog.i18n.DateTimePatterns_kde = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale kde_TZ.
    - */
    -goog.i18n.DateTimePatterns_kde_TZ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale kea.
    - */
    -goog.i18n.DateTimePatterns_kea = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'di\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'di\' y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd \'di\' MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'd \'di\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale kea_CV.
    - */
    -goog.i18n.DateTimePatterns_kea_CV = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM \'di\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'di\' y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd \'di\' MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'd \'di\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale khq.
    - */
    -goog.i18n.DateTimePatterns_khq = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale khq_ML.
    - */
    -goog.i18n.DateTimePatterns_khq_ML = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ki.
    - */
    -goog.i18n.DateTimePatterns_ki = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ki_KE.
    - */
    -goog.i18n.DateTimePatterns_ki_KE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale kk_Cyrl.
    - */
    -goog.i18n.DateTimePatterns_kk_Cyrl = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd-MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale kk_Cyrl_KZ.
    - */
    -goog.i18n.DateTimePatterns_kk_Cyrl_KZ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd-MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale kkj.
    - */
    -goog.i18n.DateTimePatterns_kkj = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale kkj_CM.
    - */
    -goog.i18n.DateTimePatterns_kkj_CM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale kl.
    - */
    -goog.i18n.DateTimePatterns_kl = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale kl_GL.
    - */
    -goog.i18n.DateTimePatterns_kl_GL = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale kln.
    - */
    -goog.i18n.DateTimePatterns_kln = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale kln_KE.
    - */
    -goog.i18n.DateTimePatterns_kln_KE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale km_KH.
    - */
    -goog.i18n.DateTimePatterns_km_KH = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y នៃ G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd-M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale kn_IN.
    - */
    -goog.i18n.DateTimePatterns_kn_IN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d,y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ko_KP.
    - */
    -goog.i18n.DateTimePatterns_ko_KP = {
    -  YEAR_FULL: 'y년',
    -  YEAR_FULL_WITH_ERA: 'G y년',
    -  YEAR_MONTH_ABBR: 'y년 MMM',
    -  YEAR_MONTH_FULL: 'y년 MMMM',
    -  MONTH_DAY_ABBR: 'MMM d일',
    -  MONTH_DAY_FULL: 'MMMM dd일',
    -  MONTH_DAY_SHORT: 'M. d.',
    -  MONTH_DAY_MEDIUM: 'MMMM d일',
    -  MONTH_DAY_YEAR_MEDIUM: 'y년 MMM d일',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d일 (EEE)',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y년 MMM d일 (EEE)',
    -  DAY_ABBR: 'd일'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ko_KR.
    - */
    -goog.i18n.DateTimePatterns_ko_KR = {
    -  YEAR_FULL: 'y년',
    -  YEAR_FULL_WITH_ERA: 'G y년',
    -  YEAR_MONTH_ABBR: 'y년 MMM',
    -  YEAR_MONTH_FULL: 'y년 MMMM',
    -  MONTH_DAY_ABBR: 'MMM d일',
    -  MONTH_DAY_FULL: 'MMMM dd일',
    -  MONTH_DAY_SHORT: 'M. d.',
    -  MONTH_DAY_MEDIUM: 'MMMM d일',
    -  MONTH_DAY_YEAR_MEDIUM: 'y년 MMM d일',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d일 (EEE)',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y년 MMM d일 (EEE)',
    -  DAY_ABBR: 'd일'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale kok.
    - */
    -goog.i18n.DateTimePatterns_kok = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale kok_IN.
    - */
    -goog.i18n.DateTimePatterns_kok_IN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ks.
    - */
    -goog.i18n.DateTimePatterns_ks = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'Gy',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd-MMM',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ks_Arab.
    - */
    -goog.i18n.DateTimePatterns_ks_Arab = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'Gy',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd-MMM',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ks_Arab_IN.
    - */
    -goog.i18n.DateTimePatterns_ks_Arab_IN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'Gy',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd-MMM',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ksb.
    - */
    -goog.i18n.DateTimePatterns_ksb = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ksb_TZ.
    - */
    -goog.i18n.DateTimePatterns_ksb_TZ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ksf.
    - */
    -goog.i18n.DateTimePatterns_ksf = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ksf_CM.
    - */
    -goog.i18n.DateTimePatterns_ksf_CM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ksh.
    - */
    -goog.i18n.DateTimePatterns_ksh = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM. y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d. MMM. y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ksh_DE.
    - */
    -goog.i18n.DateTimePatterns_ksh_DE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM. y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d. MMM. y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale kw.
    - */
    -goog.i18n.DateTimePatterns_kw = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale kw_GB.
    - */
    -goog.i18n.DateTimePatterns_kw_GB = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ky_Cyrl.
    - */
    -goog.i18n.DateTimePatterns_ky_Cyrl = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y-\'ж\'.',
    -  YEAR_MONTH_ABBR: 'y-\'ж\'. MMM',
    -  YEAR_MONTH_FULL: 'y-\'ж\'. MMMM',
    -  MONTH_DAY_ABBR: 'd-MMM',
    -  MONTH_DAY_FULL: 'dd-MMMM',
    -  MONTH_DAY_SHORT: 'dd-MM',
    -  MONTH_DAY_MEDIUM: 'd-MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'y-\'ж\'. d-MMM',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'd-MMM, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y-\'ж\'. d-MMM, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ky_Cyrl_KG.
    - */
    -goog.i18n.DateTimePatterns_ky_Cyrl_KG = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y-\'ж\'.',
    -  YEAR_MONTH_ABBR: 'y-\'ж\'. MMM',
    -  YEAR_MONTH_FULL: 'y-\'ж\'. MMMM',
    -  MONTH_DAY_ABBR: 'd-MMM',
    -  MONTH_DAY_FULL: 'dd-MMMM',
    -  MONTH_DAY_SHORT: 'dd-MM',
    -  MONTH_DAY_MEDIUM: 'd-MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'y-\'ж\'. d-MMM',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'd-MMM, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y-\'ж\'. d-MMM, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale lag.
    - */
    -goog.i18n.DateTimePatterns_lag = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale lag_TZ.
    - */
    -goog.i18n.DateTimePatterns_lag_TZ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale lb.
    - */
    -goog.i18n.DateTimePatterns_lb = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale lb_LU.
    - */
    -goog.i18n.DateTimePatterns_lb_LU = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale lg.
    - */
    -goog.i18n.DateTimePatterns_lg = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale lg_UG.
    - */
    -goog.i18n.DateTimePatterns_lg_UG = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale lkt.
    - */
    -goog.i18n.DateTimePatterns_lkt = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale lkt_US.
    - */
    -goog.i18n.DateTimePatterns_lkt_US = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ln_AO.
    - */
    -goog.i18n.DateTimePatterns_ln_AO = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ln_CD.
    - */
    -goog.i18n.DateTimePatterns_ln_CD = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ln_CF.
    - */
    -goog.i18n.DateTimePatterns_ln_CF = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ln_CG.
    - */
    -goog.i18n.DateTimePatterns_ln_CG = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale lo_LA.
    - */
    -goog.i18n.DateTimePatterns_lo_LA = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale lt_LT.
    - */
    -goog.i18n.DateTimePatterns_lt_LT = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'y-MM',
    -  YEAR_MONTH_FULL: 'y LLLL',
    -  MONTH_DAY_ABBR: 'MM-dd',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y-MM-dd',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MM-dd, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y-MM-dd, EEE',
    -  DAY_ABBR: 'dd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale lu.
    - */
    -goog.i18n.DateTimePatterns_lu = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale lu_CD.
    - */
    -goog.i18n.DateTimePatterns_lu_CD = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale luo.
    - */
    -goog.i18n.DateTimePatterns_luo = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale luo_KE.
    - */
    -goog.i18n.DateTimePatterns_luo_KE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale luy.
    - */
    -goog.i18n.DateTimePatterns_luy = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale luy_KE.
    - */
    -goog.i18n.DateTimePatterns_luy_KE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale lv_LV.
    - */
    -goog.i18n.DateTimePatterns_lv_LV = {
    -  YEAR_FULL: 'y. \'g\'.',
    -  YEAR_FULL_WITH_ERA: 'G y. \'g\'.',
    -  YEAR_MONTH_ABBR: 'y. \'g\'. MMM',
    -  YEAR_MONTH_FULL: 'y. \'g\'. MMMM',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'y. \'g\'. d. MMM',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, y. \'g\'. d. MMM',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale mas.
    - */
    -goog.i18n.DateTimePatterns_mas = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale mas_KE.
    - */
    -goog.i18n.DateTimePatterns_mas_KE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale mas_TZ.
    - */
    -goog.i18n.DateTimePatterns_mas_TZ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale mer.
    - */
    -goog.i18n.DateTimePatterns_mer = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale mer_KE.
    - */
    -goog.i18n.DateTimePatterns_mer_KE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale mfe.
    - */
    -goog.i18n.DateTimePatterns_mfe = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale mfe_MU.
    - */
    -goog.i18n.DateTimePatterns_mfe_MU = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale mg.
    - */
    -goog.i18n.DateTimePatterns_mg = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale mg_MG.
    - */
    -goog.i18n.DateTimePatterns_mg_MG = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale mgh.
    - */
    -goog.i18n.DateTimePatterns_mgh = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale mgh_MZ.
    - */
    -goog.i18n.DateTimePatterns_mgh_MZ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale mgo.
    - */
    -goog.i18n.DateTimePatterns_mgo = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale mgo_CM.
    - */
    -goog.i18n.DateTimePatterns_mgo_CM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale mk_MK.
    - */
    -goog.i18n.DateTimePatterns_mk_MK = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y \'г\'.',
    -  YEAR_MONTH_FULL: 'MMMM y \'г\'.',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd.M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y \'г\'.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y \'г\'.',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ml_IN.
    - */
    -goog.i18n.DateTimePatterns_ml_IN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale mn_Cyrl.
    - */
    -goog.i18n.DateTimePatterns_mn_Cyrl = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M-d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, y MMM d',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale mn_Cyrl_MN.
    - */
    -goog.i18n.DateTimePatterns_mn_Cyrl_MN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M-d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, y MMM d',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale mr_IN.
    - */
    -goog.i18n.DateTimePatterns_mr_IN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d, MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ms_Latn.
    - */
    -goog.i18n.DateTimePatterns_ms_Latn = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd-M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ms_Latn_BN.
    - */
    -goog.i18n.DateTimePatterns_ms_Latn_BN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd-M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ms_Latn_MY.
    - */
    -goog.i18n.DateTimePatterns_ms_Latn_MY = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd-M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ms_Latn_SG.
    - */
    -goog.i18n.DateTimePatterns_ms_Latn_SG = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd-M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale mt_MT.
    - */
    -goog.i18n.DateTimePatterns_mt_MT = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale mua.
    - */
    -goog.i18n.DateTimePatterns_mua = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale mua_CM.
    - */
    -goog.i18n.DateTimePatterns_mua_CM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale my_MM.
    - */
    -goog.i18n.DateTimePatterns_my_MM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale naq.
    - */
    -goog.i18n.DateTimePatterns_naq = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale naq_NA.
    - */
    -goog.i18n.DateTimePatterns_naq_NA = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale nb_NO.
    - */
    -goog.i18n.DateTimePatterns_nb_NO = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d. MMM y',
    -  DAY_ABBR: 'd.'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale nb_SJ.
    - */
    -goog.i18n.DateTimePatterns_nb_SJ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d. MMM y',
    -  DAY_ABBR: 'd.'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale nd.
    - */
    -goog.i18n.DateTimePatterns_nd = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale nd_ZW.
    - */
    -goog.i18n.DateTimePatterns_nd_ZW = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ne_IN.
    - */
    -goog.i18n.DateTimePatterns_ne_IN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ne_NP.
    - */
    -goog.i18n.DateTimePatterns_ne_NP = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale nl_AW.
    - */
    -goog.i18n.DateTimePatterns_nl_AW = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd-M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale nl_BE.
    - */
    -goog.i18n.DateTimePatterns_nl_BE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd-M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale nl_BQ.
    - */
    -goog.i18n.DateTimePatterns_nl_BQ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd-M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale nl_CW.
    - */
    -goog.i18n.DateTimePatterns_nl_CW = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd-M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale nl_NL.
    - */
    -goog.i18n.DateTimePatterns_nl_NL = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd-M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale nl_SR.
    - */
    -goog.i18n.DateTimePatterns_nl_SR = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd-M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale nl_SX.
    - */
    -goog.i18n.DateTimePatterns_nl_SX = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd-M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale nmg.
    - */
    -goog.i18n.DateTimePatterns_nmg = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale nmg_CM.
    - */
    -goog.i18n.DateTimePatterns_nmg_CM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale nn.
    - */
    -goog.i18n.DateTimePatterns_nn = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d. MMM y',
    -  DAY_ABBR: 'd.'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale nn_NO.
    - */
    -goog.i18n.DateTimePatterns_nn_NO = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d. MMM y',
    -  DAY_ABBR: 'd.'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale nnh.
    - */
    -goog.i18n.DateTimePatterns_nnh = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: '\'lyɛ\'̌ʼ d \'na\' MMMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE , \'lyɛ\'̌ʼ d \'na\' MMM, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale nnh_CM.
    - */
    -goog.i18n.DateTimePatterns_nnh_CM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: '\'lyɛ\'̌ʼ d \'na\' MMMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE , \'lyɛ\'̌ʼ d \'na\' MMM, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale nus.
    - */
    -goog.i18n.DateTimePatterns_nus = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale nus_SD.
    - */
    -goog.i18n.DateTimePatterns_nus_SD = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale nyn.
    - */
    -goog.i18n.DateTimePatterns_nyn = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale nyn_UG.
    - */
    -goog.i18n.DateTimePatterns_nyn_UG = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale om.
    - */
    -goog.i18n.DateTimePatterns_om = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd-MMM-y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale om_ET.
    - */
    -goog.i18n.DateTimePatterns_om_ET = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd-MMM-y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale om_KE.
    - */
    -goog.i18n.DateTimePatterns_om_KE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd-MMM-y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale or_IN.
    - */
    -goog.i18n.DateTimePatterns_or_IN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'd-M',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale os.
    - */
    -goog.i18n.DateTimePatterns_os = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'LLL y',
    -  YEAR_MONTH_FULL: 'LLLL y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y \'аз\'',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'ccc, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale os_GE.
    - */
    -goog.i18n.DateTimePatterns_os_GE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'LLL y',
    -  YEAR_MONTH_FULL: 'LLLL y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y \'аз\'',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'ccc, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale os_RU.
    - */
    -goog.i18n.DateTimePatterns_os_RU = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'LLL y',
    -  YEAR_MONTH_FULL: 'LLLL y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y \'аз\'',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'ccc, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale pa_Arab.
    - */
    -goog.i18n.DateTimePatterns_pa_Arab = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale pa_Arab_PK.
    - */
    -goog.i18n.DateTimePatterns_pa_Arab_PK = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale pa_Guru.
    - */
    -goog.i18n.DateTimePatterns_pa_Guru = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale pa_Guru_IN.
    - */
    -goog.i18n.DateTimePatterns_pa_Guru_IN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale pl_PL.
    - */
    -goog.i18n.DateTimePatterns_pl_PL = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'LLL y',
    -  YEAR_MONTH_FULL: 'LLLL y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd.MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ps.
    - */
    -goog.i18n.DateTimePatterns_ps = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ps_AF.
    - */
    -goog.i18n.DateTimePatterns_ps_AF = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale pt_AO.
    - */
    -goog.i18n.DateTimePatterns_pt_AO = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MM/y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd/MM',
    -  MONTH_DAY_FULL: 'dd \'de\' MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd/MM/y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d/MM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d/MM/y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale pt_CV.
    - */
    -goog.i18n.DateTimePatterns_pt_CV = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MM/y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd/MM',
    -  MONTH_DAY_FULL: 'dd \'de\' MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd/MM/y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d/MM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d/MM/y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale pt_GW.
    - */
    -goog.i18n.DateTimePatterns_pt_GW = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MM/y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd/MM',
    -  MONTH_DAY_FULL: 'dd \'de\' MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd/MM/y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d/MM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d/MM/y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale pt_MO.
    - */
    -goog.i18n.DateTimePatterns_pt_MO = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MM/y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd/MM',
    -  MONTH_DAY_FULL: 'dd \'de\' MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd/MM/y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d/MM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d/MM/y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale pt_MZ.
    - */
    -goog.i18n.DateTimePatterns_pt_MZ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MM/y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd/MM',
    -  MONTH_DAY_FULL: 'dd \'de\' MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd/MM/y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d/MM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d/MM/y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale pt_ST.
    - */
    -goog.i18n.DateTimePatterns_pt_ST = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MM/y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd/MM',
    -  MONTH_DAY_FULL: 'dd \'de\' MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd/MM/y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d/MM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d/MM/y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale pt_TL.
    - */
    -goog.i18n.DateTimePatterns_pt_TL = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MM/y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd/MM',
    -  MONTH_DAY_FULL: 'dd \'de\' MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd \'de\' MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd/MM/y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d/MM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d/MM/y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale qu.
    - */
    -goog.i18n.DateTimePatterns_qu = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale qu_BO.
    - */
    -goog.i18n.DateTimePatterns_qu_BO = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale qu_EC.
    - */
    -goog.i18n.DateTimePatterns_qu_EC = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale qu_PE.
    - */
    -goog.i18n.DateTimePatterns_qu_PE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale rm.
    - */
    -goog.i18n.DateTimePatterns_rm = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale rm_CH.
    - */
    -goog.i18n.DateTimePatterns_rm_CH = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd.M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale rn.
    - */
    -goog.i18n.DateTimePatterns_rn = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale rn_BI.
    - */
    -goog.i18n.DateTimePatterns_rn_BI = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ro_MD.
    - */
    -goog.i18n.DateTimePatterns_ro_MD = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ro_RO.
    - */
    -goog.i18n.DateTimePatterns_ro_RO = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale rof.
    - */
    -goog.i18n.DateTimePatterns_rof = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale rof_TZ.
    - */
    -goog.i18n.DateTimePatterns_rof_TZ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ru_BY.
    - */
    -goog.i18n.DateTimePatterns_ru_BY = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'LLL y',
    -  YEAR_MONTH_FULL: 'LLLL y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y \'г\'.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'ccc, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y \'г\'.',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ru_KG.
    - */
    -goog.i18n.DateTimePatterns_ru_KG = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'LLL y',
    -  YEAR_MONTH_FULL: 'LLLL y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y \'г\'.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'ccc, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y \'г\'.',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ru_KZ.
    - */
    -goog.i18n.DateTimePatterns_ru_KZ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'LLL y',
    -  YEAR_MONTH_FULL: 'LLLL y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y \'г\'.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'ccc, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y \'г\'.',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ru_MD.
    - */
    -goog.i18n.DateTimePatterns_ru_MD = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'LLL y',
    -  YEAR_MONTH_FULL: 'LLLL y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y \'г\'.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'ccc, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y \'г\'.',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ru_RU.
    - */
    -goog.i18n.DateTimePatterns_ru_RU = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'LLL y',
    -  YEAR_MONTH_FULL: 'LLLL y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y \'г\'.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'ccc, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y \'г\'.',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ru_UA.
    - */
    -goog.i18n.DateTimePatterns_ru_UA = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'LLL y',
    -  YEAR_MONTH_FULL: 'LLLL y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'ccc, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y \'г\'.',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale rw.
    - */
    -goog.i18n.DateTimePatterns_rw = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale rw_RW.
    - */
    -goog.i18n.DateTimePatterns_rw_RW = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale rwk.
    - */
    -goog.i18n.DateTimePatterns_rwk = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale rwk_TZ.
    - */
    -goog.i18n.DateTimePatterns_rwk_TZ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sah.
    - */
    -goog.i18n.DateTimePatterns_sah = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y, MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sah_RU.
    - */
    -goog.i18n.DateTimePatterns_sah_RU = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y, MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale saq.
    - */
    -goog.i18n.DateTimePatterns_saq = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale saq_KE.
    - */
    -goog.i18n.DateTimePatterns_saq_KE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sbp.
    - */
    -goog.i18n.DateTimePatterns_sbp = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sbp_TZ.
    - */
    -goog.i18n.DateTimePatterns_sbp_TZ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale se.
    - */
    -goog.i18n.DateTimePatterns_se = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale se_FI.
    - */
    -goog.i18n.DateTimePatterns_se_FI = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale se_NO.
    - */
    -goog.i18n.DateTimePatterns_se_NO = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale se_SE.
    - */
    -goog.i18n.DateTimePatterns_se_SE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale seh.
    - */
    -goog.i18n.DateTimePatterns_seh = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale seh_MZ.
    - */
    -goog.i18n.DateTimePatterns_seh_MZ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM \'de\' y',
    -  YEAR_MONTH_FULL: 'MMMM \'de\' y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd \'de\' MMM \'de\' y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d \'de\' MMM \'de\' y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ses.
    - */
    -goog.i18n.DateTimePatterns_ses = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ses_ML.
    - */
    -goog.i18n.DateTimePatterns_ses_ML = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sg.
    - */
    -goog.i18n.DateTimePatterns_sg = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sg_CF.
    - */
    -goog.i18n.DateTimePatterns_sg_CF = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale shi.
    - */
    -goog.i18n.DateTimePatterns_shi = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale shi_Latn.
    - */
    -goog.i18n.DateTimePatterns_shi_Latn = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale shi_Latn_MA.
    - */
    -goog.i18n.DateTimePatterns_shi_Latn_MA = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale shi_Tfng.
    - */
    -goog.i18n.DateTimePatterns_shi_Tfng = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale shi_Tfng_MA.
    - */
    -goog.i18n.DateTimePatterns_shi_Tfng_MA = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale si_LK.
    - */
    -goog.i18n.DateTimePatterns_si_LK = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M-d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sk_SK.
    - */
    -goog.i18n.DateTimePatterns_sk_SK = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'LLLL y',
    -  YEAR_MONTH_FULL: 'LLLL y',
    -  MONTH_DAY_ABBR: 'd. M',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd. M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. M. y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d. M.',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d. M. y',
    -  DAY_ABBR: 'd.'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sl_SI.
    - */
    -goog.i18n.DateTimePatterns_sl_SI = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd. M.',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale smn.
    - */
    -goog.i18n.DateTimePatterns_smn = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale smn_FI.
    - */
    -goog.i18n.DateTimePatterns_smn_FI = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sn.
    - */
    -goog.i18n.DateTimePatterns_sn = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sn_ZW.
    - */
    -goog.i18n.DateTimePatterns_sn_ZW = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale so.
    - */
    -goog.i18n.DateTimePatterns_so = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd-MMM-y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale so_DJ.
    - */
    -goog.i18n.DateTimePatterns_so_DJ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd-MMM-y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale so_ET.
    - */
    -goog.i18n.DateTimePatterns_so_ET = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd-MMM-y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale so_KE.
    - */
    -goog.i18n.DateTimePatterns_so_KE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd-MMM-y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale so_SO.
    - */
    -goog.i18n.DateTimePatterns_so_SO = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd-MMM-y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sq_AL.
    - */
    -goog.i18n.DateTimePatterns_sq_AL = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd.M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sq_MK.
    - */
    -goog.i18n.DateTimePatterns_sq_MK = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd.M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sq_XK.
    - */
    -goog.i18n.DateTimePatterns_sq_XK = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd.M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sr_Cyrl.
    - */
    -goog.i18n.DateTimePatterns_sr_Cyrl = {
    -  YEAR_FULL: 'y.',
    -  YEAR_FULL_WITH_ERA: 'y. G',
    -  YEAR_MONTH_ABBR: 'MMM y.',
    -  YEAR_MONTH_FULL: 'MMMM y.',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y.',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sr_Cyrl_BA.
    - */
    -goog.i18n.DateTimePatterns_sr_Cyrl_BA = {
    -  YEAR_FULL: 'y.',
    -  YEAR_FULL_WITH_ERA: 'y. G',
    -  YEAR_MONTH_ABBR: 'MMM y.',
    -  YEAR_MONTH_FULL: 'MMMM y.',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y.',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sr_Cyrl_ME.
    - */
    -goog.i18n.DateTimePatterns_sr_Cyrl_ME = {
    -  YEAR_FULL: 'y.',
    -  YEAR_FULL_WITH_ERA: 'y. G',
    -  YEAR_MONTH_ABBR: 'MMM y.',
    -  YEAR_MONTH_FULL: 'MMMM y.',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y.',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sr_Cyrl_RS.
    - */
    -goog.i18n.DateTimePatterns_sr_Cyrl_RS = {
    -  YEAR_FULL: 'y.',
    -  YEAR_FULL_WITH_ERA: 'y. G',
    -  YEAR_MONTH_ABBR: 'MMM y.',
    -  YEAR_MONTH_FULL: 'MMMM y.',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y.',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sr_Cyrl_XK.
    - */
    -goog.i18n.DateTimePatterns_sr_Cyrl_XK = {
    -  YEAR_FULL: 'y.',
    -  YEAR_FULL_WITH_ERA: 'y. G',
    -  YEAR_MONTH_ABBR: 'MMM y.',
    -  YEAR_MONTH_FULL: 'MMMM y.',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y.',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sr_Latn.
    - */
    -goog.i18n.DateTimePatterns_sr_Latn = {
    -  YEAR_FULL: 'y.',
    -  YEAR_FULL_WITH_ERA: 'y. G',
    -  YEAR_MONTH_ABBR: 'MMM y.',
    -  YEAR_MONTH_FULL: 'MMMM y.',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y.',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sr_Latn_BA.
    - */
    -goog.i18n.DateTimePatterns_sr_Latn_BA = {
    -  YEAR_FULL: 'y.',
    -  YEAR_FULL_WITH_ERA: 'y. G',
    -  YEAR_MONTH_ABBR: 'MMM y.',
    -  YEAR_MONTH_FULL: 'MMMM y.',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y.',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sr_Latn_ME.
    - */
    -goog.i18n.DateTimePatterns_sr_Latn_ME = {
    -  YEAR_FULL: 'y.',
    -  YEAR_FULL_WITH_ERA: 'y. G',
    -  YEAR_MONTH_ABBR: 'MMM y.',
    -  YEAR_MONTH_FULL: 'MMMM y.',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y.',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sr_Latn_RS.
    - */
    -goog.i18n.DateTimePatterns_sr_Latn_RS = {
    -  YEAR_FULL: 'y.',
    -  YEAR_FULL_WITH_ERA: 'y. G',
    -  YEAR_MONTH_ABBR: 'MMM y.',
    -  YEAR_MONTH_FULL: 'MMMM y.',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y.',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sr_Latn_XK.
    - */
    -goog.i18n.DateTimePatterns_sr_Latn_XK = {
    -  YEAR_FULL: 'y.',
    -  YEAR_FULL_WITH_ERA: 'y. G',
    -  YEAR_MONTH_ABBR: 'MMM y.',
    -  YEAR_MONTH_FULL: 'MMMM y.',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y.',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y.',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sv_AX.
    - */
    -goog.i18n.DateTimePatterns_sv_AX = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sv_FI.
    - */
    -goog.i18n.DateTimePatterns_sv_FI = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sv_SE.
    - */
    -goog.i18n.DateTimePatterns_sv_SE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sw_KE.
    - */
    -goog.i18n.DateTimePatterns_sw_KE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd-M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sw_TZ.
    - */
    -goog.i18n.DateTimePatterns_sw_TZ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd-M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale sw_UG.
    - */
    -goog.i18n.DateTimePatterns_sw_UG = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd-M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale swc.
    - */
    -goog.i18n.DateTimePatterns_swc = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale swc_CD.
    - */
    -goog.i18n.DateTimePatterns_swc_CD = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ta_IN.
    - */
    -goog.i18n.DateTimePatterns_ta_IN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ta_LK.
    - */
    -goog.i18n.DateTimePatterns_ta_LK = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ta_MY.
    - */
    -goog.i18n.DateTimePatterns_ta_MY = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ta_SG.
    - */
    -goog.i18n.DateTimePatterns_ta_SG = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale te_IN.
    - */
    -goog.i18n.DateTimePatterns_te_IN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd, MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d, MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale teo.
    - */
    -goog.i18n.DateTimePatterns_teo = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale teo_KE.
    - */
    -goog.i18n.DateTimePatterns_teo_KE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale teo_UG.
    - */
    -goog.i18n.DateTimePatterns_teo_UG = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale th_TH.
    - */
    -goog.i18n.DateTimePatterns_th_TH = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ti.
    - */
    -goog.i18n.DateTimePatterns_ti = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd-MMM-y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ti_ER.
    - */
    -goog.i18n.DateTimePatterns_ti_ER = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd-MMM-y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ti_ET.
    - */
    -goog.i18n.DateTimePatterns_ti_ET = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd-MMM-y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale to.
    - */
    -goog.i18n.DateTimePatterns_to = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale to_TO.
    - */
    -goog.i18n.DateTimePatterns_to_TO = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale tr_CY.
    - */
    -goog.i18n.DateTimePatterns_tr_CY = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'dd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'dd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'd MMMM EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'd MMM y EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale tr_TR.
    - */
    -goog.i18n.DateTimePatterns_tr_TR = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd/MM',
    -  MONTH_DAY_MEDIUM: 'dd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'dd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'd MMMM EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'd MMM y EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale twq.
    - */
    -goog.i18n.DateTimePatterns_twq = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale twq_NE.
    - */
    -goog.i18n.DateTimePatterns_twq_NE = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale tzm.
    - */
    -goog.i18n.DateTimePatterns_tzm = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale tzm_Latn.
    - */
    -goog.i18n.DateTimePatterns_tzm_Latn = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale tzm_Latn_MA.
    - */
    -goog.i18n.DateTimePatterns_tzm_Latn_MA = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ug.
    - */
    -goog.i18n.DateTimePatterns_ug = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، MMM d، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ug_Arab.
    - */
    -goog.i18n.DateTimePatterns_ug_Arab = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، MMM d، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ug_Arab_CN.
    - */
    -goog.i18n.DateTimePatterns_ug_Arab_CN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، MMM d، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale uk_UA.
    - */
    -goog.i18n.DateTimePatterns_uk_UA = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'LLL y',
    -  YEAR_MONTH_FULL: 'LLLL y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd.MM',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ur_IN.
    - */
    -goog.i18n.DateTimePatterns_ur_IN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale ur_PK.
    - */
    -goog.i18n.DateTimePatterns_ur_PK = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM، y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE، d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE، d MMM، y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale uz_Arab.
    - */
    -goog.i18n.DateTimePatterns_uz_Arab = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale uz_Arab_AF.
    - */
    -goog.i18n.DateTimePatterns_uz_Arab_AF = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale uz_Cyrl.
    - */
    -goog.i18n.DateTimePatterns_uz_Cyrl = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale uz_Cyrl_UZ.
    - */
    -goog.i18n.DateTimePatterns_uz_Cyrl_UZ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale uz_Latn.
    - */
    -goog.i18n.DateTimePatterns_uz_Latn = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale uz_Latn_UZ.
    - */
    -goog.i18n.DateTimePatterns_uz_Latn_UZ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'y MMM',
    -  YEAR_MONTH_FULL: 'y MMMM',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'y MMM d',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y MMM d, EEE',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale vai.
    - */
    -goog.i18n.DateTimePatterns_vai = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale vai_Latn.
    - */
    -goog.i18n.DateTimePatterns_vai_Latn = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale vai_Latn_LR.
    - */
    -goog.i18n.DateTimePatterns_vai_Latn_LR = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale vai_Vaii.
    - */
    -goog.i18n.DateTimePatterns_vai_Vaii = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale vai_Vaii_LR.
    - */
    -goog.i18n.DateTimePatterns_vai_Vaii_LR = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale vi_VN.
    - */
    -goog.i18n.DateTimePatterns_vi_VN = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM \'năm\' y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'dd-M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'dd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, dd MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, dd MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale vun.
    - */
    -goog.i18n.DateTimePatterns_vun = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale vun_TZ.
    - */
    -goog.i18n.DateTimePatterns_vun_TZ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale wae.
    - */
    -goog.i18n.DateTimePatterns_wae = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd. MMM',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale wae_CH.
    - */
    -goog.i18n.DateTimePatterns_wae_CH = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd. MMM',
    -  MONTH_DAY_FULL: 'dd. MMMM',
    -  MONTH_DAY_SHORT: 'd. MMM',
    -  MONTH_DAY_MEDIUM: 'd. MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd. MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, d. MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, d. MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale xog.
    - */
    -goog.i18n.DateTimePatterns_xog = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale xog_UG.
    - */
    -goog.i18n.DateTimePatterns_xog_UG = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale yav.
    - */
    -goog.i18n.DateTimePatterns_yav = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale yav_CM.
    - */
    -goog.i18n.DateTimePatterns_yav_CM = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale yi.
    - */
    -goog.i18n.DateTimePatterns_yi = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'dטן MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, dטן MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale yi_001.
    - */
    -goog.i18n.DateTimePatterns_yi_001 = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'MM-dd',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'dטן MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'MMM d, EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, dטן MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale yo.
    - */
    -goog.i18n.DateTimePatterns_yo = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale yo_BJ.
    - */
    -goog.i18n.DateTimePatterns_yo_BJ = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale yo_NG.
    - */
    -goog.i18n.DateTimePatterns_yo_NG = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale zgh.
    - */
    -goog.i18n.DateTimePatterns_zgh = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale zgh_MA.
    - */
    -goog.i18n.DateTimePatterns_zgh_MA = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'G y',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'd MMM',
    -  MONTH_DAY_FULL: 'dd MMMM',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'd MMMM',
    -  MONTH_DAY_YEAR_MEDIUM: 'd MMM, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE d MMM',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE d MMM y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale zh_Hans.
    - */
    -goog.i18n.DateTimePatterns_zh_Hans = {
    -  YEAR_FULL: 'y年',
    -  YEAR_FULL_WITH_ERA: 'Gy年',
    -  YEAR_MONTH_ABBR: 'y年M月',
    -  YEAR_MONTH_FULL: 'y年M月',
    -  MONTH_DAY_ABBR: 'M月d日',
    -  MONTH_DAY_FULL: 'M月dd日',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'M月d日',
    -  MONTH_DAY_YEAR_MEDIUM: 'y年M月d日',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'M月d日EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y年M月d日EEE',
    -  DAY_ABBR: 'd日'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale zh_Hans_CN.
    - */
    -goog.i18n.DateTimePatterns_zh_Hans_CN = {
    -  YEAR_FULL: 'y年',
    -  YEAR_FULL_WITH_ERA: 'Gy年',
    -  YEAR_MONTH_ABBR: 'y年M月',
    -  YEAR_MONTH_FULL: 'y年M月',
    -  MONTH_DAY_ABBR: 'M月d日',
    -  MONTH_DAY_FULL: 'M月dd日',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'M月d日',
    -  MONTH_DAY_YEAR_MEDIUM: 'y年M月d日',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'M月d日EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y年M月d日EEE',
    -  DAY_ABBR: 'd日'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale zh_Hans_HK.
    - */
    -goog.i18n.DateTimePatterns_zh_Hans_HK = {
    -  YEAR_FULL: 'y年',
    -  YEAR_FULL_WITH_ERA: 'Gy年',
    -  YEAR_MONTH_ABBR: 'y年M月',
    -  YEAR_MONTH_FULL: 'y年M月',
    -  MONTH_DAY_ABBR: 'M月d日',
    -  MONTH_DAY_FULL: 'M月d日',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'M月d日',
    -  MONTH_DAY_YEAR_MEDIUM: 'y年M月d日',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'M月d日EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y年M月d日EEE',
    -  DAY_ABBR: 'd日'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale zh_Hans_MO.
    - */
    -goog.i18n.DateTimePatterns_zh_Hans_MO = {
    -  YEAR_FULL: 'y年',
    -  YEAR_FULL_WITH_ERA: 'Gy年',
    -  YEAR_MONTH_ABBR: 'y年M月',
    -  YEAR_MONTH_FULL: 'y年M月',
    -  MONTH_DAY_ABBR: 'M月d日',
    -  MONTH_DAY_FULL: 'M月d日',
    -  MONTH_DAY_SHORT: 'M-d',
    -  MONTH_DAY_MEDIUM: 'M月d日',
    -  MONTH_DAY_YEAR_MEDIUM: 'y年M月d日',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'M月d日EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y年M月d日EEE',
    -  DAY_ABBR: 'd日'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale zh_Hans_SG.
    - */
    -goog.i18n.DateTimePatterns_zh_Hans_SG = {
    -  YEAR_FULL: 'y年',
    -  YEAR_FULL_WITH_ERA: 'Gy年',
    -  YEAR_MONTH_ABBR: 'y年M月',
    -  YEAR_MONTH_FULL: 'y年M月',
    -  MONTH_DAY_ABBR: 'M月d日',
    -  MONTH_DAY_FULL: 'M月d日',
    -  MONTH_DAY_SHORT: 'M-d',
    -  MONTH_DAY_MEDIUM: 'M月d日',
    -  MONTH_DAY_YEAR_MEDIUM: 'y年M月d日',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'M月d日EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y年M月d日EEE',
    -  DAY_ABBR: 'd日'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale zh_Hant.
    - */
    -goog.i18n.DateTimePatterns_zh_Hant = {
    -  YEAR_FULL: 'y年',
    -  YEAR_FULL_WITH_ERA: 'Gy年',
    -  YEAR_MONTH_ABBR: 'y年M月',
    -  YEAR_MONTH_FULL: 'y年M月',
    -  MONTH_DAY_ABBR: 'M月d日',
    -  MONTH_DAY_FULL: 'M月dd日',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'M月d日',
    -  MONTH_DAY_YEAR_MEDIUM: 'y年M月d日',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'M月d日 EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y年M月d日 EEE',
    -  DAY_ABBR: 'd日'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale zh_Hant_HK.
    - */
    -goog.i18n.DateTimePatterns_zh_Hant_HK = {
    -  YEAR_FULL: 'y年',
    -  YEAR_FULL_WITH_ERA: 'Gy年',
    -  YEAR_MONTH_ABBR: 'y年M月',
    -  YEAR_MONTH_FULL: 'y年M月',
    -  MONTH_DAY_ABBR: 'M月d日',
    -  MONTH_DAY_FULL: 'M月dd日',
    -  MONTH_DAY_SHORT: 'd/M',
    -  MONTH_DAY_MEDIUM: 'M月d日',
    -  MONTH_DAY_YEAR_MEDIUM: 'y年M月d日',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'M月d日EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y年M月d日EEE',
    -  DAY_ABBR: 'd日'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale zh_Hant_MO.
    - */
    -goog.i18n.DateTimePatterns_zh_Hant_MO = {
    -  YEAR_FULL: 'y年',
    -  YEAR_FULL_WITH_ERA: 'Gy年',
    -  YEAR_MONTH_ABBR: 'y年M月',
    -  YEAR_MONTH_FULL: 'y年M月',
    -  MONTH_DAY_ABBR: 'M月d日',
    -  MONTH_DAY_FULL: 'M月dd日',
    -  MONTH_DAY_SHORT: 'M-d',
    -  MONTH_DAY_MEDIUM: 'M月d日',
    -  MONTH_DAY_YEAR_MEDIUM: 'y年M月d日',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'M月d日EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y年M月d日EEE',
    -  DAY_ABBR: 'd日'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale zh_Hant_TW.
    - */
    -goog.i18n.DateTimePatterns_zh_Hant_TW = {
    -  YEAR_FULL: 'y年',
    -  YEAR_FULL_WITH_ERA: 'Gy年',
    -  YEAR_MONTH_ABBR: 'y年M月',
    -  YEAR_MONTH_FULL: 'y年M月',
    -  MONTH_DAY_ABBR: 'M月d日',
    -  MONTH_DAY_FULL: 'M月dd日',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'M月d日',
    -  MONTH_DAY_YEAR_MEDIUM: 'y年M月d日',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'M月d日 EEE',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'y年M月d日 EEE',
    -  DAY_ABBR: 'd日'
    -};
    -
    -
    -/**
    - * Extended set of localized date/time patterns for locale zu_ZA.
    - */
    -goog.i18n.DateTimePatterns_zu_ZA = {
    -  YEAR_FULL: 'y',
    -  YEAR_FULL_WITH_ERA: 'y G',
    -  YEAR_MONTH_ABBR: 'MMM y',
    -  YEAR_MONTH_FULL: 'MMMM y',
    -  MONTH_DAY_ABBR: 'MMM d',
    -  MONTH_DAY_FULL: 'MMMM dd',
    -  MONTH_DAY_SHORT: 'M/d',
    -  MONTH_DAY_MEDIUM: 'MMMM d',
    -  MONTH_DAY_YEAR_MEDIUM: 'MMM d, y',
    -  WEEKDAY_MONTH_DAY_MEDIUM: 'EEE, MMM d',
    -  WEEKDAY_MONTH_DAY_YEAR_MEDIUM: 'EEE, MMM d, y',
    -  DAY_ABBR: 'd'
    -};
    -
    -
    -/**
    - * Select date/time pattern by locale.
    - */
    -if (goog.LOCALE == 'af_NA' || goog.LOCALE == 'af-NA') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_af_NA;
    -}
    -
    -if (goog.LOCALE == 'af_ZA' || goog.LOCALE == 'af-ZA') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_af_ZA;
    -}
    -
    -if (goog.LOCALE == 'agq') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_agq;
    -}
    -
    -if (goog.LOCALE == 'agq_CM' || goog.LOCALE == 'agq-CM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_agq_CM;
    -}
    -
    -if (goog.LOCALE == 'ak') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ak;
    -}
    -
    -if (goog.LOCALE == 'ak_GH' || goog.LOCALE == 'ak-GH') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ak_GH;
    -}
    -
    -if (goog.LOCALE == 'am_ET' || goog.LOCALE == 'am-ET') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_am_ET;
    -}
    -
    -if (goog.LOCALE == 'ar_001' || goog.LOCALE == 'ar-001') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ar_001;
    -}
    -
    -if (goog.LOCALE == 'ar_AE' || goog.LOCALE == 'ar-AE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ar_AE;
    -}
    -
    -if (goog.LOCALE == 'ar_BH' || goog.LOCALE == 'ar-BH') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ar_BH;
    -}
    -
    -if (goog.LOCALE == 'ar_DJ' || goog.LOCALE == 'ar-DJ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ar_DJ;
    -}
    -
    -if (goog.LOCALE == 'ar_DZ' || goog.LOCALE == 'ar-DZ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ar_DZ;
    -}
    -
    -if (goog.LOCALE == 'ar_EG' || goog.LOCALE == 'ar-EG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ar_EG;
    -}
    -
    -if (goog.LOCALE == 'ar_EH' || goog.LOCALE == 'ar-EH') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ar_EH;
    -}
    -
    -if (goog.LOCALE == 'ar_ER' || goog.LOCALE == 'ar-ER') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ar_ER;
    -}
    -
    -if (goog.LOCALE == 'ar_IL' || goog.LOCALE == 'ar-IL') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ar_IL;
    -}
    -
    -if (goog.LOCALE == 'ar_IQ' || goog.LOCALE == 'ar-IQ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ar_IQ;
    -}
    -
    -if (goog.LOCALE == 'ar_JO' || goog.LOCALE == 'ar-JO') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ar_JO;
    -}
    -
    -if (goog.LOCALE == 'ar_KM' || goog.LOCALE == 'ar-KM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ar_KM;
    -}
    -
    -if (goog.LOCALE == 'ar_KW' || goog.LOCALE == 'ar-KW') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ar_KW;
    -}
    -
    -if (goog.LOCALE == 'ar_LB' || goog.LOCALE == 'ar-LB') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ar_LB;
    -}
    -
    -if (goog.LOCALE == 'ar_LY' || goog.LOCALE == 'ar-LY') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ar_LY;
    -}
    -
    -if (goog.LOCALE == 'ar_MA' || goog.LOCALE == 'ar-MA') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ar_MA;
    -}
    -
    -if (goog.LOCALE == 'ar_MR' || goog.LOCALE == 'ar-MR') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ar_MR;
    -}
    -
    -if (goog.LOCALE == 'ar_OM' || goog.LOCALE == 'ar-OM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ar_OM;
    -}
    -
    -if (goog.LOCALE == 'ar_PS' || goog.LOCALE == 'ar-PS') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ar_PS;
    -}
    -
    -if (goog.LOCALE == 'ar_QA' || goog.LOCALE == 'ar-QA') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ar_QA;
    -}
    -
    -if (goog.LOCALE == 'ar_SA' || goog.LOCALE == 'ar-SA') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ar_SA;
    -}
    -
    -if (goog.LOCALE == 'ar_SD' || goog.LOCALE == 'ar-SD') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ar_SD;
    -}
    -
    -if (goog.LOCALE == 'ar_SO' || goog.LOCALE == 'ar-SO') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ar_SO;
    -}
    -
    -if (goog.LOCALE == 'ar_SS' || goog.LOCALE == 'ar-SS') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ar_SS;
    -}
    -
    -if (goog.LOCALE == 'ar_SY' || goog.LOCALE == 'ar-SY') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ar_SY;
    -}
    -
    -if (goog.LOCALE == 'ar_TD' || goog.LOCALE == 'ar-TD') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ar_TD;
    -}
    -
    -if (goog.LOCALE == 'ar_TN' || goog.LOCALE == 'ar-TN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ar_TN;
    -}
    -
    -if (goog.LOCALE == 'ar_YE' || goog.LOCALE == 'ar-YE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ar_YE;
    -}
    -
    -if (goog.LOCALE == 'as') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_as;
    -}
    -
    -if (goog.LOCALE == 'as_IN' || goog.LOCALE == 'as-IN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_as_IN;
    -}
    -
    -if (goog.LOCALE == 'asa') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_asa;
    -}
    -
    -if (goog.LOCALE == 'asa_TZ' || goog.LOCALE == 'asa-TZ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_asa_TZ;
    -}
    -
    -if (goog.LOCALE == 'az_Cyrl' || goog.LOCALE == 'az-Cyrl') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_az_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'az_Cyrl_AZ' || goog.LOCALE == 'az-Cyrl-AZ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_az_Cyrl_AZ;
    -}
    -
    -if (goog.LOCALE == 'az_Latn' || goog.LOCALE == 'az-Latn') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_az_Latn;
    -}
    -
    -if (goog.LOCALE == 'az_Latn_AZ' || goog.LOCALE == 'az-Latn-AZ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_az_Latn_AZ;
    -}
    -
    -if (goog.LOCALE == 'bas') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_bas;
    -}
    -
    -if (goog.LOCALE == 'bas_CM' || goog.LOCALE == 'bas-CM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_bas_CM;
    -}
    -
    -if (goog.LOCALE == 'be') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_be;
    -}
    -
    -if (goog.LOCALE == 'be_BY' || goog.LOCALE == 'be-BY') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_be_BY;
    -}
    -
    -if (goog.LOCALE == 'bem') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_bem;
    -}
    -
    -if (goog.LOCALE == 'bem_ZM' || goog.LOCALE == 'bem-ZM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_bem_ZM;
    -}
    -
    -if (goog.LOCALE == 'bez') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_bez;
    -}
    -
    -if (goog.LOCALE == 'bez_TZ' || goog.LOCALE == 'bez-TZ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_bez_TZ;
    -}
    -
    -if (goog.LOCALE == 'bg_BG' || goog.LOCALE == 'bg-BG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_bg_BG;
    -}
    -
    -if (goog.LOCALE == 'bm') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_bm;
    -}
    -
    -if (goog.LOCALE == 'bm_Latn' || goog.LOCALE == 'bm-Latn') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_bm_Latn;
    -}
    -
    -if (goog.LOCALE == 'bm_Latn_ML' || goog.LOCALE == 'bm-Latn-ML') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_bm_Latn_ML;
    -}
    -
    -if (goog.LOCALE == 'bn_BD' || goog.LOCALE == 'bn-BD') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_bn_BD;
    -}
    -
    -if (goog.LOCALE == 'bn_IN' || goog.LOCALE == 'bn-IN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_bn_IN;
    -}
    -
    -if (goog.LOCALE == 'bo') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_bo;
    -}
    -
    -if (goog.LOCALE == 'bo_CN' || goog.LOCALE == 'bo-CN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_bo_CN;
    -}
    -
    -if (goog.LOCALE == 'bo_IN' || goog.LOCALE == 'bo-IN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_bo_IN;
    -}
    -
    -if (goog.LOCALE == 'br_FR' || goog.LOCALE == 'br-FR') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_br_FR;
    -}
    -
    -if (goog.LOCALE == 'brx') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_brx;
    -}
    -
    -if (goog.LOCALE == 'brx_IN' || goog.LOCALE == 'brx-IN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_brx_IN;
    -}
    -
    -if (goog.LOCALE == 'bs') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_bs;
    -}
    -
    -if (goog.LOCALE == 'bs_Cyrl' || goog.LOCALE == 'bs-Cyrl') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_bs_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'bs_Cyrl_BA' || goog.LOCALE == 'bs-Cyrl-BA') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_bs_Cyrl_BA;
    -}
    -
    -if (goog.LOCALE == 'bs_Latn' || goog.LOCALE == 'bs-Latn') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_bs_Latn;
    -}
    -
    -if (goog.LOCALE == 'bs_Latn_BA' || goog.LOCALE == 'bs-Latn-BA') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_bs_Latn_BA;
    -}
    -
    -if (goog.LOCALE == 'ca_AD' || goog.LOCALE == 'ca-AD') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ca_AD;
    -}
    -
    -if (goog.LOCALE == 'ca_ES' || goog.LOCALE == 'ca-ES') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ca_ES;
    -}
    -
    -if (goog.LOCALE == 'ca_FR' || goog.LOCALE == 'ca-FR') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ca_FR;
    -}
    -
    -if (goog.LOCALE == 'ca_IT' || goog.LOCALE == 'ca-IT') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ca_IT;
    -}
    -
    -if (goog.LOCALE == 'cgg') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_cgg;
    -}
    -
    -if (goog.LOCALE == 'cgg_UG' || goog.LOCALE == 'cgg-UG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_cgg_UG;
    -}
    -
    -if (goog.LOCALE == 'chr_US' || goog.LOCALE == 'chr-US') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_chr_US;
    -}
    -
    -if (goog.LOCALE == 'cs_CZ' || goog.LOCALE == 'cs-CZ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_cs_CZ;
    -}
    -
    -if (goog.LOCALE == 'cy_GB' || goog.LOCALE == 'cy-GB') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_cy_GB;
    -}
    -
    -if (goog.LOCALE == 'da_DK' || goog.LOCALE == 'da-DK') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_da_DK;
    -}
    -
    -if (goog.LOCALE == 'da_GL' || goog.LOCALE == 'da-GL') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_da_GL;
    -}
    -
    -if (goog.LOCALE == 'dav') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_dav;
    -}
    -
    -if (goog.LOCALE == 'dav_KE' || goog.LOCALE == 'dav-KE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_dav_KE;
    -}
    -
    -if (goog.LOCALE == 'de_BE' || goog.LOCALE == 'de-BE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de_BE;
    -}
    -
    -if (goog.LOCALE == 'de_DE' || goog.LOCALE == 'de-DE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de_DE;
    -}
    -
    -if (goog.LOCALE == 'de_LI' || goog.LOCALE == 'de-LI') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de_LI;
    -}
    -
    -if (goog.LOCALE == 'de_LU' || goog.LOCALE == 'de-LU') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_de_LU;
    -}
    -
    -if (goog.LOCALE == 'dje') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_dje;
    -}
    -
    -if (goog.LOCALE == 'dje_NE' || goog.LOCALE == 'dje-NE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_dje_NE;
    -}
    -
    -if (goog.LOCALE == 'dsb') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_dsb;
    -}
    -
    -if (goog.LOCALE == 'dsb_DE' || goog.LOCALE == 'dsb-DE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_dsb_DE;
    -}
    -
    -if (goog.LOCALE == 'dua') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_dua;
    -}
    -
    -if (goog.LOCALE == 'dua_CM' || goog.LOCALE == 'dua-CM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_dua_CM;
    -}
    -
    -if (goog.LOCALE == 'dyo') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_dyo;
    -}
    -
    -if (goog.LOCALE == 'dyo_SN' || goog.LOCALE == 'dyo-SN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_dyo_SN;
    -}
    -
    -if (goog.LOCALE == 'dz') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_dz;
    -}
    -
    -if (goog.LOCALE == 'dz_BT' || goog.LOCALE == 'dz-BT') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_dz_BT;
    -}
    -
    -if (goog.LOCALE == 'ebu') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ebu;
    -}
    -
    -if (goog.LOCALE == 'ebu_KE' || goog.LOCALE == 'ebu-KE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ebu_KE;
    -}
    -
    -if (goog.LOCALE == 'ee') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ee;
    -}
    -
    -if (goog.LOCALE == 'ee_GH' || goog.LOCALE == 'ee-GH') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ee_GH;
    -}
    -
    -if (goog.LOCALE == 'ee_TG' || goog.LOCALE == 'ee-TG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ee_TG;
    -}
    -
    -if (goog.LOCALE == 'el_CY' || goog.LOCALE == 'el-CY') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_el_CY;
    -}
    -
    -if (goog.LOCALE == 'el_GR' || goog.LOCALE == 'el-GR') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_el_GR;
    -}
    -
    -if (goog.LOCALE == 'en_001' || goog.LOCALE == 'en-001') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_001;
    -}
    -
    -if (goog.LOCALE == 'en_150' || goog.LOCALE == 'en-150') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_150;
    -}
    -
    -if (goog.LOCALE == 'en_AG' || goog.LOCALE == 'en-AG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_AG;
    -}
    -
    -if (goog.LOCALE == 'en_AI' || goog.LOCALE == 'en-AI') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_AI;
    -}
    -
    -if (goog.LOCALE == 'en_AS' || goog.LOCALE == 'en-AS') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_AS;
    -}
    -
    -if (goog.LOCALE == 'en_BB' || goog.LOCALE == 'en-BB') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_BB;
    -}
    -
    -if (goog.LOCALE == 'en_BE' || goog.LOCALE == 'en-BE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_BE;
    -}
    -
    -if (goog.LOCALE == 'en_BM' || goog.LOCALE == 'en-BM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_BM;
    -}
    -
    -if (goog.LOCALE == 'en_BS' || goog.LOCALE == 'en-BS') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_BS;
    -}
    -
    -if (goog.LOCALE == 'en_BW' || goog.LOCALE == 'en-BW') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_BW;
    -}
    -
    -if (goog.LOCALE == 'en_BZ' || goog.LOCALE == 'en-BZ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_BZ;
    -}
    -
    -if (goog.LOCALE == 'en_CA' || goog.LOCALE == 'en-CA') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_CA;
    -}
    -
    -if (goog.LOCALE == 'en_CC' || goog.LOCALE == 'en-CC') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_CC;
    -}
    -
    -if (goog.LOCALE == 'en_CK' || goog.LOCALE == 'en-CK') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_CK;
    -}
    -
    -if (goog.LOCALE == 'en_CM' || goog.LOCALE == 'en-CM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_CM;
    -}
    -
    -if (goog.LOCALE == 'en_CX' || goog.LOCALE == 'en-CX') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_CX;
    -}
    -
    -if (goog.LOCALE == 'en_DG' || goog.LOCALE == 'en-DG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_DG;
    -}
    -
    -if (goog.LOCALE == 'en_DM' || goog.LOCALE == 'en-DM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_DM;
    -}
    -
    -if (goog.LOCALE == 'en_ER' || goog.LOCALE == 'en-ER') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_ER;
    -}
    -
    -if (goog.LOCALE == 'en_FJ' || goog.LOCALE == 'en-FJ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_FJ;
    -}
    -
    -if (goog.LOCALE == 'en_FK' || goog.LOCALE == 'en-FK') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_FK;
    -}
    -
    -if (goog.LOCALE == 'en_FM' || goog.LOCALE == 'en-FM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_FM;
    -}
    -
    -if (goog.LOCALE == 'en_GD' || goog.LOCALE == 'en-GD') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_GD;
    -}
    -
    -if (goog.LOCALE == 'en_GG' || goog.LOCALE == 'en-GG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_GG;
    -}
    -
    -if (goog.LOCALE == 'en_GH' || goog.LOCALE == 'en-GH') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_GH;
    -}
    -
    -if (goog.LOCALE == 'en_GI' || goog.LOCALE == 'en-GI') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_GI;
    -}
    -
    -if (goog.LOCALE == 'en_GM' || goog.LOCALE == 'en-GM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_GM;
    -}
    -
    -if (goog.LOCALE == 'en_GU' || goog.LOCALE == 'en-GU') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_GU;
    -}
    -
    -if (goog.LOCALE == 'en_GY' || goog.LOCALE == 'en-GY') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_GY;
    -}
    -
    -if (goog.LOCALE == 'en_HK' || goog.LOCALE == 'en-HK') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_HK;
    -}
    -
    -if (goog.LOCALE == 'en_IM' || goog.LOCALE == 'en-IM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_IM;
    -}
    -
    -if (goog.LOCALE == 'en_IO' || goog.LOCALE == 'en-IO') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_IO;
    -}
    -
    -if (goog.LOCALE == 'en_JE' || goog.LOCALE == 'en-JE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_JE;
    -}
    -
    -if (goog.LOCALE == 'en_JM' || goog.LOCALE == 'en-JM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_JM;
    -}
    -
    -if (goog.LOCALE == 'en_KE' || goog.LOCALE == 'en-KE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_KE;
    -}
    -
    -if (goog.LOCALE == 'en_KI' || goog.LOCALE == 'en-KI') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_KI;
    -}
    -
    -if (goog.LOCALE == 'en_KN' || goog.LOCALE == 'en-KN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_KN;
    -}
    -
    -if (goog.LOCALE == 'en_KY' || goog.LOCALE == 'en-KY') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_KY;
    -}
    -
    -if (goog.LOCALE == 'en_LC' || goog.LOCALE == 'en-LC') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_LC;
    -}
    -
    -if (goog.LOCALE == 'en_LR' || goog.LOCALE == 'en-LR') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_LR;
    -}
    -
    -if (goog.LOCALE == 'en_LS' || goog.LOCALE == 'en-LS') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_LS;
    -}
    -
    -if (goog.LOCALE == 'en_MG' || goog.LOCALE == 'en-MG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_MG;
    -}
    -
    -if (goog.LOCALE == 'en_MH' || goog.LOCALE == 'en-MH') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_MH;
    -}
    -
    -if (goog.LOCALE == 'en_MO' || goog.LOCALE == 'en-MO') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_MO;
    -}
    -
    -if (goog.LOCALE == 'en_MP' || goog.LOCALE == 'en-MP') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_MP;
    -}
    -
    -if (goog.LOCALE == 'en_MS' || goog.LOCALE == 'en-MS') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_MS;
    -}
    -
    -if (goog.LOCALE == 'en_MT' || goog.LOCALE == 'en-MT') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_MT;
    -}
    -
    -if (goog.LOCALE == 'en_MU' || goog.LOCALE == 'en-MU') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_MU;
    -}
    -
    -if (goog.LOCALE == 'en_MW' || goog.LOCALE == 'en-MW') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_MW;
    -}
    -
    -if (goog.LOCALE == 'en_MY' || goog.LOCALE == 'en-MY') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_MY;
    -}
    -
    -if (goog.LOCALE == 'en_NA' || goog.LOCALE == 'en-NA') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_NA;
    -}
    -
    -if (goog.LOCALE == 'en_NF' || goog.LOCALE == 'en-NF') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_NF;
    -}
    -
    -if (goog.LOCALE == 'en_NG' || goog.LOCALE == 'en-NG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_NG;
    -}
    -
    -if (goog.LOCALE == 'en_NR' || goog.LOCALE == 'en-NR') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_NR;
    -}
    -
    -if (goog.LOCALE == 'en_NU' || goog.LOCALE == 'en-NU') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_NU;
    -}
    -
    -if (goog.LOCALE == 'en_NZ' || goog.LOCALE == 'en-NZ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_NZ;
    -}
    -
    -if (goog.LOCALE == 'en_PG' || goog.LOCALE == 'en-PG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_PG;
    -}
    -
    -if (goog.LOCALE == 'en_PH' || goog.LOCALE == 'en-PH') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_PH;
    -}
    -
    -if (goog.LOCALE == 'en_PK' || goog.LOCALE == 'en-PK') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_PK;
    -}
    -
    -if (goog.LOCALE == 'en_PN' || goog.LOCALE == 'en-PN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_PN;
    -}
    -
    -if (goog.LOCALE == 'en_PR' || goog.LOCALE == 'en-PR') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_PR;
    -}
    -
    -if (goog.LOCALE == 'en_PW' || goog.LOCALE == 'en-PW') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_PW;
    -}
    -
    -if (goog.LOCALE == 'en_RW' || goog.LOCALE == 'en-RW') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_RW;
    -}
    -
    -if (goog.LOCALE == 'en_SB' || goog.LOCALE == 'en-SB') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_SB;
    -}
    -
    -if (goog.LOCALE == 'en_SC' || goog.LOCALE == 'en-SC') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_SC;
    -}
    -
    -if (goog.LOCALE == 'en_SD' || goog.LOCALE == 'en-SD') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_SD;
    -}
    -
    -if (goog.LOCALE == 'en_SH' || goog.LOCALE == 'en-SH') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_SH;
    -}
    -
    -if (goog.LOCALE == 'en_SL' || goog.LOCALE == 'en-SL') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_SL;
    -}
    -
    -if (goog.LOCALE == 'en_SS' || goog.LOCALE == 'en-SS') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_SS;
    -}
    -
    -if (goog.LOCALE == 'en_SX' || goog.LOCALE == 'en-SX') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_SX;
    -}
    -
    -if (goog.LOCALE == 'en_SZ' || goog.LOCALE == 'en-SZ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_SZ;
    -}
    -
    -if (goog.LOCALE == 'en_TC' || goog.LOCALE == 'en-TC') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_TC;
    -}
    -
    -if (goog.LOCALE == 'en_TK' || goog.LOCALE == 'en-TK') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_TK;
    -}
    -
    -if (goog.LOCALE == 'en_TO' || goog.LOCALE == 'en-TO') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_TO;
    -}
    -
    -if (goog.LOCALE == 'en_TT' || goog.LOCALE == 'en-TT') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_TT;
    -}
    -
    -if (goog.LOCALE == 'en_TV' || goog.LOCALE == 'en-TV') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_TV;
    -}
    -
    -if (goog.LOCALE == 'en_TZ' || goog.LOCALE == 'en-TZ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_TZ;
    -}
    -
    -if (goog.LOCALE == 'en_UG' || goog.LOCALE == 'en-UG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_UG;
    -}
    -
    -if (goog.LOCALE == 'en_UM' || goog.LOCALE == 'en-UM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_UM;
    -}
    -
    -if (goog.LOCALE == 'en_US_POSIX' || goog.LOCALE == 'en-US-POSIX') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_US_POSIX;
    -}
    -
    -if (goog.LOCALE == 'en_VC' || goog.LOCALE == 'en-VC') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_VC;
    -}
    -
    -if (goog.LOCALE == 'en_VG' || goog.LOCALE == 'en-VG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_VG;
    -}
    -
    -if (goog.LOCALE == 'en_VI' || goog.LOCALE == 'en-VI') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_VI;
    -}
    -
    -if (goog.LOCALE == 'en_VU' || goog.LOCALE == 'en-VU') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_VU;
    -}
    -
    -if (goog.LOCALE == 'en_WS' || goog.LOCALE == 'en-WS') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_WS;
    -}
    -
    -if (goog.LOCALE == 'en_ZM' || goog.LOCALE == 'en-ZM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_ZM;
    -}
    -
    -if (goog.LOCALE == 'en_ZW' || goog.LOCALE == 'en-ZW') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_en_ZW;
    -}
    -
    -if (goog.LOCALE == 'eo') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_eo;
    -}
    -
    -if (goog.LOCALE == 'es_AR' || goog.LOCALE == 'es-AR') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_es_AR;
    -}
    -
    -if (goog.LOCALE == 'es_BO' || goog.LOCALE == 'es-BO') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_es_BO;
    -}
    -
    -if (goog.LOCALE == 'es_CL' || goog.LOCALE == 'es-CL') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_es_CL;
    -}
    -
    -if (goog.LOCALE == 'es_CO' || goog.LOCALE == 'es-CO') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_es_CO;
    -}
    -
    -if (goog.LOCALE == 'es_CR' || goog.LOCALE == 'es-CR') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_es_CR;
    -}
    -
    -if (goog.LOCALE == 'es_CU' || goog.LOCALE == 'es-CU') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_es_CU;
    -}
    -
    -if (goog.LOCALE == 'es_DO' || goog.LOCALE == 'es-DO') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_es_DO;
    -}
    -
    -if (goog.LOCALE == 'es_EA' || goog.LOCALE == 'es-EA') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_es_EA;
    -}
    -
    -if (goog.LOCALE == 'es_EC' || goog.LOCALE == 'es-EC') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_es_EC;
    -}
    -
    -if (goog.LOCALE == 'es_GQ' || goog.LOCALE == 'es-GQ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_es_GQ;
    -}
    -
    -if (goog.LOCALE == 'es_GT' || goog.LOCALE == 'es-GT') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_es_GT;
    -}
    -
    -if (goog.LOCALE == 'es_HN' || goog.LOCALE == 'es-HN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_es_HN;
    -}
    -
    -if (goog.LOCALE == 'es_IC' || goog.LOCALE == 'es-IC') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_es_IC;
    -}
    -
    -if (goog.LOCALE == 'es_MX' || goog.LOCALE == 'es-MX') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_es_MX;
    -}
    -
    -if (goog.LOCALE == 'es_NI' || goog.LOCALE == 'es-NI') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_es_NI;
    -}
    -
    -if (goog.LOCALE == 'es_PA' || goog.LOCALE == 'es-PA') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_es_PA;
    -}
    -
    -if (goog.LOCALE == 'es_PE' || goog.LOCALE == 'es-PE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_es_PE;
    -}
    -
    -if (goog.LOCALE == 'es_PH' || goog.LOCALE == 'es-PH') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_es_PH;
    -}
    -
    -if (goog.LOCALE == 'es_PR' || goog.LOCALE == 'es-PR') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_es_PR;
    -}
    -
    -if (goog.LOCALE == 'es_PY' || goog.LOCALE == 'es-PY') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_es_PY;
    -}
    -
    -if (goog.LOCALE == 'es_SV' || goog.LOCALE == 'es-SV') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_es_SV;
    -}
    -
    -if (goog.LOCALE == 'es_US' || goog.LOCALE == 'es-US') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_es_US;
    -}
    -
    -if (goog.LOCALE == 'es_UY' || goog.LOCALE == 'es-UY') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_es_UY;
    -}
    -
    -if (goog.LOCALE == 'es_VE' || goog.LOCALE == 'es-VE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_es_VE;
    -}
    -
    -if (goog.LOCALE == 'et_EE' || goog.LOCALE == 'et-EE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_et_EE;
    -}
    -
    -if (goog.LOCALE == 'eu_ES' || goog.LOCALE == 'eu-ES') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_eu_ES;
    -}
    -
    -if (goog.LOCALE == 'ewo') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ewo;
    -}
    -
    -if (goog.LOCALE == 'ewo_CM' || goog.LOCALE == 'ewo-CM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ewo_CM;
    -}
    -
    -if (goog.LOCALE == 'fa_AF' || goog.LOCALE == 'fa-AF') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fa_AF;
    -}
    -
    -if (goog.LOCALE == 'fa_IR' || goog.LOCALE == 'fa-IR') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fa_IR;
    -}
    -
    -if (goog.LOCALE == 'ff') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ff;
    -}
    -
    -if (goog.LOCALE == 'ff_CM' || goog.LOCALE == 'ff-CM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ff_CM;
    -}
    -
    -if (goog.LOCALE == 'ff_GN' || goog.LOCALE == 'ff-GN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ff_GN;
    -}
    -
    -if (goog.LOCALE == 'ff_MR' || goog.LOCALE == 'ff-MR') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ff_MR;
    -}
    -
    -if (goog.LOCALE == 'ff_SN' || goog.LOCALE == 'ff-SN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ff_SN;
    -}
    -
    -if (goog.LOCALE == 'fi_FI' || goog.LOCALE == 'fi-FI') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fi_FI;
    -}
    -
    -if (goog.LOCALE == 'fil_PH' || goog.LOCALE == 'fil-PH') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fil_PH;
    -}
    -
    -if (goog.LOCALE == 'fo') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fo;
    -}
    -
    -if (goog.LOCALE == 'fo_FO' || goog.LOCALE == 'fo-FO') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fo_FO;
    -}
    -
    -if (goog.LOCALE == 'fr_BE' || goog.LOCALE == 'fr-BE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_BE;
    -}
    -
    -if (goog.LOCALE == 'fr_BF' || goog.LOCALE == 'fr-BF') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_BF;
    -}
    -
    -if (goog.LOCALE == 'fr_BI' || goog.LOCALE == 'fr-BI') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_BI;
    -}
    -
    -if (goog.LOCALE == 'fr_BJ' || goog.LOCALE == 'fr-BJ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_BJ;
    -}
    -
    -if (goog.LOCALE == 'fr_BL' || goog.LOCALE == 'fr-BL') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_BL;
    -}
    -
    -if (goog.LOCALE == 'fr_CD' || goog.LOCALE == 'fr-CD') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_CD;
    -}
    -
    -if (goog.LOCALE == 'fr_CF' || goog.LOCALE == 'fr-CF') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_CF;
    -}
    -
    -if (goog.LOCALE == 'fr_CG' || goog.LOCALE == 'fr-CG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_CG;
    -}
    -
    -if (goog.LOCALE == 'fr_CH' || goog.LOCALE == 'fr-CH') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_CH;
    -}
    -
    -if (goog.LOCALE == 'fr_CI' || goog.LOCALE == 'fr-CI') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_CI;
    -}
    -
    -if (goog.LOCALE == 'fr_CM' || goog.LOCALE == 'fr-CM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_CM;
    -}
    -
    -if (goog.LOCALE == 'fr_DJ' || goog.LOCALE == 'fr-DJ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_DJ;
    -}
    -
    -if (goog.LOCALE == 'fr_DZ' || goog.LOCALE == 'fr-DZ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_DZ;
    -}
    -
    -if (goog.LOCALE == 'fr_FR' || goog.LOCALE == 'fr-FR') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_FR;
    -}
    -
    -if (goog.LOCALE == 'fr_GA' || goog.LOCALE == 'fr-GA') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_GA;
    -}
    -
    -if (goog.LOCALE == 'fr_GF' || goog.LOCALE == 'fr-GF') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_GF;
    -}
    -
    -if (goog.LOCALE == 'fr_GN' || goog.LOCALE == 'fr-GN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_GN;
    -}
    -
    -if (goog.LOCALE == 'fr_GP' || goog.LOCALE == 'fr-GP') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_GP;
    -}
    -
    -if (goog.LOCALE == 'fr_GQ' || goog.LOCALE == 'fr-GQ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_GQ;
    -}
    -
    -if (goog.LOCALE == 'fr_HT' || goog.LOCALE == 'fr-HT') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_HT;
    -}
    -
    -if (goog.LOCALE == 'fr_KM' || goog.LOCALE == 'fr-KM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_KM;
    -}
    -
    -if (goog.LOCALE == 'fr_LU' || goog.LOCALE == 'fr-LU') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_LU;
    -}
    -
    -if (goog.LOCALE == 'fr_MA' || goog.LOCALE == 'fr-MA') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_MA;
    -}
    -
    -if (goog.LOCALE == 'fr_MC' || goog.LOCALE == 'fr-MC') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_MC;
    -}
    -
    -if (goog.LOCALE == 'fr_MF' || goog.LOCALE == 'fr-MF') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_MF;
    -}
    -
    -if (goog.LOCALE == 'fr_MG' || goog.LOCALE == 'fr-MG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_MG;
    -}
    -
    -if (goog.LOCALE == 'fr_ML' || goog.LOCALE == 'fr-ML') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_ML;
    -}
    -
    -if (goog.LOCALE == 'fr_MQ' || goog.LOCALE == 'fr-MQ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_MQ;
    -}
    -
    -if (goog.LOCALE == 'fr_MR' || goog.LOCALE == 'fr-MR') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_MR;
    -}
    -
    -if (goog.LOCALE == 'fr_MU' || goog.LOCALE == 'fr-MU') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_MU;
    -}
    -
    -if (goog.LOCALE == 'fr_NC' || goog.LOCALE == 'fr-NC') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_NC;
    -}
    -
    -if (goog.LOCALE == 'fr_NE' || goog.LOCALE == 'fr-NE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_NE;
    -}
    -
    -if (goog.LOCALE == 'fr_PF' || goog.LOCALE == 'fr-PF') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_PF;
    -}
    -
    -if (goog.LOCALE == 'fr_PM' || goog.LOCALE == 'fr-PM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_PM;
    -}
    -
    -if (goog.LOCALE == 'fr_RE' || goog.LOCALE == 'fr-RE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_RE;
    -}
    -
    -if (goog.LOCALE == 'fr_RW' || goog.LOCALE == 'fr-RW') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_RW;
    -}
    -
    -if (goog.LOCALE == 'fr_SC' || goog.LOCALE == 'fr-SC') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_SC;
    -}
    -
    -if (goog.LOCALE == 'fr_SN' || goog.LOCALE == 'fr-SN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_SN;
    -}
    -
    -if (goog.LOCALE == 'fr_SY' || goog.LOCALE == 'fr-SY') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_SY;
    -}
    -
    -if (goog.LOCALE == 'fr_TD' || goog.LOCALE == 'fr-TD') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_TD;
    -}
    -
    -if (goog.LOCALE == 'fr_TG' || goog.LOCALE == 'fr-TG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_TG;
    -}
    -
    -if (goog.LOCALE == 'fr_TN' || goog.LOCALE == 'fr-TN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_TN;
    -}
    -
    -if (goog.LOCALE == 'fr_VU' || goog.LOCALE == 'fr-VU') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_VU;
    -}
    -
    -if (goog.LOCALE == 'fr_WF' || goog.LOCALE == 'fr-WF') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_WF;
    -}
    -
    -if (goog.LOCALE == 'fr_YT' || goog.LOCALE == 'fr-YT') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fr_YT;
    -}
    -
    -if (goog.LOCALE == 'fur') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fur;
    -}
    -
    -if (goog.LOCALE == 'fur_IT' || goog.LOCALE == 'fur-IT') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fur_IT;
    -}
    -
    -if (goog.LOCALE == 'fy') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fy;
    -}
    -
    -if (goog.LOCALE == 'fy_NL' || goog.LOCALE == 'fy-NL') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_fy_NL;
    -}
    -
    -if (goog.LOCALE == 'ga_IE' || goog.LOCALE == 'ga-IE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ga_IE;
    -}
    -
    -if (goog.LOCALE == 'gd') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_gd;
    -}
    -
    -if (goog.LOCALE == 'gd_GB' || goog.LOCALE == 'gd-GB') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_gd_GB;
    -}
    -
    -if (goog.LOCALE == 'gl_ES' || goog.LOCALE == 'gl-ES') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_gl_ES;
    -}
    -
    -if (goog.LOCALE == 'gsw_CH' || goog.LOCALE == 'gsw-CH') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_gsw_CH;
    -}
    -
    -if (goog.LOCALE == 'gsw_FR' || goog.LOCALE == 'gsw-FR') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_gsw_FR;
    -}
    -
    -if (goog.LOCALE == 'gsw_LI' || goog.LOCALE == 'gsw-LI') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_gsw_LI;
    -}
    -
    -if (goog.LOCALE == 'gu_IN' || goog.LOCALE == 'gu-IN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_gu_IN;
    -}
    -
    -if (goog.LOCALE == 'guz') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_guz;
    -}
    -
    -if (goog.LOCALE == 'guz_KE' || goog.LOCALE == 'guz-KE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_guz_KE;
    -}
    -
    -if (goog.LOCALE == 'gv') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_gv;
    -}
    -
    -if (goog.LOCALE == 'gv_IM' || goog.LOCALE == 'gv-IM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_gv_IM;
    -}
    -
    -if (goog.LOCALE == 'ha') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ha;
    -}
    -
    -if (goog.LOCALE == 'ha_Latn' || goog.LOCALE == 'ha-Latn') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ha_Latn;
    -}
    -
    -if (goog.LOCALE == 'ha_Latn_GH' || goog.LOCALE == 'ha-Latn-GH') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ha_Latn_GH;
    -}
    -
    -if (goog.LOCALE == 'ha_Latn_NE' || goog.LOCALE == 'ha-Latn-NE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ha_Latn_NE;
    -}
    -
    -if (goog.LOCALE == 'ha_Latn_NG' || goog.LOCALE == 'ha-Latn-NG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ha_Latn_NG;
    -}
    -
    -if (goog.LOCALE == 'haw_US' || goog.LOCALE == 'haw-US') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_haw_US;
    -}
    -
    -if (goog.LOCALE == 'he_IL' || goog.LOCALE == 'he-IL') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_he_IL;
    -}
    -
    -if (goog.LOCALE == 'hi_IN' || goog.LOCALE == 'hi-IN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_hi_IN;
    -}
    -
    -if (goog.LOCALE == 'hr_BA' || goog.LOCALE == 'hr-BA') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_hr_BA;
    -}
    -
    -if (goog.LOCALE == 'hr_HR' || goog.LOCALE == 'hr-HR') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_hr_HR;
    -}
    -
    -if (goog.LOCALE == 'hsb') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_hsb;
    -}
    -
    -if (goog.LOCALE == 'hsb_DE' || goog.LOCALE == 'hsb-DE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_hsb_DE;
    -}
    -
    -if (goog.LOCALE == 'hu_HU' || goog.LOCALE == 'hu-HU') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_hu_HU;
    -}
    -
    -if (goog.LOCALE == 'hy_AM' || goog.LOCALE == 'hy-AM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_hy_AM;
    -}
    -
    -if (goog.LOCALE == 'id_ID' || goog.LOCALE == 'id-ID') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_id_ID;
    -}
    -
    -if (goog.LOCALE == 'ig') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ig;
    -}
    -
    -if (goog.LOCALE == 'ig_NG' || goog.LOCALE == 'ig-NG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ig_NG;
    -}
    -
    -if (goog.LOCALE == 'ii') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ii;
    -}
    -
    -if (goog.LOCALE == 'ii_CN' || goog.LOCALE == 'ii-CN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ii_CN;
    -}
    -
    -if (goog.LOCALE == 'is_IS' || goog.LOCALE == 'is-IS') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_is_IS;
    -}
    -
    -if (goog.LOCALE == 'it_CH' || goog.LOCALE == 'it-CH') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_it_CH;
    -}
    -
    -if (goog.LOCALE == 'it_IT' || goog.LOCALE == 'it-IT') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_it_IT;
    -}
    -
    -if (goog.LOCALE == 'it_SM' || goog.LOCALE == 'it-SM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_it_SM;
    -}
    -
    -if (goog.LOCALE == 'ja_JP' || goog.LOCALE == 'ja-JP') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ja_JP;
    -}
    -
    -if (goog.LOCALE == 'jgo') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_jgo;
    -}
    -
    -if (goog.LOCALE == 'jgo_CM' || goog.LOCALE == 'jgo-CM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_jgo_CM;
    -}
    -
    -if (goog.LOCALE == 'jmc') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_jmc;
    -}
    -
    -if (goog.LOCALE == 'jmc_TZ' || goog.LOCALE == 'jmc-TZ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_jmc_TZ;
    -}
    -
    -if (goog.LOCALE == 'ka_GE' || goog.LOCALE == 'ka-GE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ka_GE;
    -}
    -
    -if (goog.LOCALE == 'kab') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_kab;
    -}
    -
    -if (goog.LOCALE == 'kab_DZ' || goog.LOCALE == 'kab-DZ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_kab_DZ;
    -}
    -
    -if (goog.LOCALE == 'kam') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_kam;
    -}
    -
    -if (goog.LOCALE == 'kam_KE' || goog.LOCALE == 'kam-KE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_kam_KE;
    -}
    -
    -if (goog.LOCALE == 'kde') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_kde;
    -}
    -
    -if (goog.LOCALE == 'kde_TZ' || goog.LOCALE == 'kde-TZ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_kde_TZ;
    -}
    -
    -if (goog.LOCALE == 'kea') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_kea;
    -}
    -
    -if (goog.LOCALE == 'kea_CV' || goog.LOCALE == 'kea-CV') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_kea_CV;
    -}
    -
    -if (goog.LOCALE == 'khq') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_khq;
    -}
    -
    -if (goog.LOCALE == 'khq_ML' || goog.LOCALE == 'khq-ML') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_khq_ML;
    -}
    -
    -if (goog.LOCALE == 'ki') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ki;
    -}
    -
    -if (goog.LOCALE == 'ki_KE' || goog.LOCALE == 'ki-KE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ki_KE;
    -}
    -
    -if (goog.LOCALE == 'kk_Cyrl' || goog.LOCALE == 'kk-Cyrl') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_kk_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'kk_Cyrl_KZ' || goog.LOCALE == 'kk-Cyrl-KZ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_kk_Cyrl_KZ;
    -}
    -
    -if (goog.LOCALE == 'kkj') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_kkj;
    -}
    -
    -if (goog.LOCALE == 'kkj_CM' || goog.LOCALE == 'kkj-CM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_kkj_CM;
    -}
    -
    -if (goog.LOCALE == 'kl') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_kl;
    -}
    -
    -if (goog.LOCALE == 'kl_GL' || goog.LOCALE == 'kl-GL') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_kl_GL;
    -}
    -
    -if (goog.LOCALE == 'kln') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_kln;
    -}
    -
    -if (goog.LOCALE == 'kln_KE' || goog.LOCALE == 'kln-KE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_kln_KE;
    -}
    -
    -if (goog.LOCALE == 'km_KH' || goog.LOCALE == 'km-KH') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_km_KH;
    -}
    -
    -if (goog.LOCALE == 'kn_IN' || goog.LOCALE == 'kn-IN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_kn_IN;
    -}
    -
    -if (goog.LOCALE == 'ko_KP' || goog.LOCALE == 'ko-KP') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ko_KP;
    -}
    -
    -if (goog.LOCALE == 'ko_KR' || goog.LOCALE == 'ko-KR') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ko_KR;
    -}
    -
    -if (goog.LOCALE == 'kok') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_kok;
    -}
    -
    -if (goog.LOCALE == 'kok_IN' || goog.LOCALE == 'kok-IN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_kok_IN;
    -}
    -
    -if (goog.LOCALE == 'ks') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ks;
    -}
    -
    -if (goog.LOCALE == 'ks_Arab' || goog.LOCALE == 'ks-Arab') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ks_Arab;
    -}
    -
    -if (goog.LOCALE == 'ks_Arab_IN' || goog.LOCALE == 'ks-Arab-IN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ks_Arab_IN;
    -}
    -
    -if (goog.LOCALE == 'ksb') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ksb;
    -}
    -
    -if (goog.LOCALE == 'ksb_TZ' || goog.LOCALE == 'ksb-TZ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ksb_TZ;
    -}
    -
    -if (goog.LOCALE == 'ksf') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ksf;
    -}
    -
    -if (goog.LOCALE == 'ksf_CM' || goog.LOCALE == 'ksf-CM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ksf_CM;
    -}
    -
    -if (goog.LOCALE == 'ksh') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ksh;
    -}
    -
    -if (goog.LOCALE == 'ksh_DE' || goog.LOCALE == 'ksh-DE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ksh_DE;
    -}
    -
    -if (goog.LOCALE == 'kw') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_kw;
    -}
    -
    -if (goog.LOCALE == 'kw_GB' || goog.LOCALE == 'kw-GB') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_kw_GB;
    -}
    -
    -if (goog.LOCALE == 'ky_Cyrl' || goog.LOCALE == 'ky-Cyrl') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ky_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'ky_Cyrl_KG' || goog.LOCALE == 'ky-Cyrl-KG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ky_Cyrl_KG;
    -}
    -
    -if (goog.LOCALE == 'lag') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_lag;
    -}
    -
    -if (goog.LOCALE == 'lag_TZ' || goog.LOCALE == 'lag-TZ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_lag_TZ;
    -}
    -
    -if (goog.LOCALE == 'lb') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_lb;
    -}
    -
    -if (goog.LOCALE == 'lb_LU' || goog.LOCALE == 'lb-LU') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_lb_LU;
    -}
    -
    -if (goog.LOCALE == 'lg') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_lg;
    -}
    -
    -if (goog.LOCALE == 'lg_UG' || goog.LOCALE == 'lg-UG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_lg_UG;
    -}
    -
    -if (goog.LOCALE == 'lkt') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_lkt;
    -}
    -
    -if (goog.LOCALE == 'lkt_US' || goog.LOCALE == 'lkt-US') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_lkt_US;
    -}
    -
    -if (goog.LOCALE == 'ln_AO' || goog.LOCALE == 'ln-AO') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ln_AO;
    -}
    -
    -if (goog.LOCALE == 'ln_CD' || goog.LOCALE == 'ln-CD') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ln_CD;
    -}
    -
    -if (goog.LOCALE == 'ln_CF' || goog.LOCALE == 'ln-CF') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ln_CF;
    -}
    -
    -if (goog.LOCALE == 'ln_CG' || goog.LOCALE == 'ln-CG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ln_CG;
    -}
    -
    -if (goog.LOCALE == 'lo_LA' || goog.LOCALE == 'lo-LA') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_lo_LA;
    -}
    -
    -if (goog.LOCALE == 'lt_LT' || goog.LOCALE == 'lt-LT') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_lt_LT;
    -}
    -
    -if (goog.LOCALE == 'lu') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_lu;
    -}
    -
    -if (goog.LOCALE == 'lu_CD' || goog.LOCALE == 'lu-CD') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_lu_CD;
    -}
    -
    -if (goog.LOCALE == 'luo') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_luo;
    -}
    -
    -if (goog.LOCALE == 'luo_KE' || goog.LOCALE == 'luo-KE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_luo_KE;
    -}
    -
    -if (goog.LOCALE == 'luy') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_luy;
    -}
    -
    -if (goog.LOCALE == 'luy_KE' || goog.LOCALE == 'luy-KE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_luy_KE;
    -}
    -
    -if (goog.LOCALE == 'lv_LV' || goog.LOCALE == 'lv-LV') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_lv_LV;
    -}
    -
    -if (goog.LOCALE == 'mas') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_mas;
    -}
    -
    -if (goog.LOCALE == 'mas_KE' || goog.LOCALE == 'mas-KE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_mas_KE;
    -}
    -
    -if (goog.LOCALE == 'mas_TZ' || goog.LOCALE == 'mas-TZ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_mas_TZ;
    -}
    -
    -if (goog.LOCALE == 'mer') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_mer;
    -}
    -
    -if (goog.LOCALE == 'mer_KE' || goog.LOCALE == 'mer-KE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_mer_KE;
    -}
    -
    -if (goog.LOCALE == 'mfe') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_mfe;
    -}
    -
    -if (goog.LOCALE == 'mfe_MU' || goog.LOCALE == 'mfe-MU') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_mfe_MU;
    -}
    -
    -if (goog.LOCALE == 'mg') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_mg;
    -}
    -
    -if (goog.LOCALE == 'mg_MG' || goog.LOCALE == 'mg-MG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_mg_MG;
    -}
    -
    -if (goog.LOCALE == 'mgh') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_mgh;
    -}
    -
    -if (goog.LOCALE == 'mgh_MZ' || goog.LOCALE == 'mgh-MZ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_mgh_MZ;
    -}
    -
    -if (goog.LOCALE == 'mgo') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_mgo;
    -}
    -
    -if (goog.LOCALE == 'mgo_CM' || goog.LOCALE == 'mgo-CM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_mgo_CM;
    -}
    -
    -if (goog.LOCALE == 'mk_MK' || goog.LOCALE == 'mk-MK') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_mk_MK;
    -}
    -
    -if (goog.LOCALE == 'ml_IN' || goog.LOCALE == 'ml-IN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ml_IN;
    -}
    -
    -if (goog.LOCALE == 'mn_Cyrl' || goog.LOCALE == 'mn-Cyrl') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_mn_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'mn_Cyrl_MN' || goog.LOCALE == 'mn-Cyrl-MN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_mn_Cyrl_MN;
    -}
    -
    -if (goog.LOCALE == 'mr_IN' || goog.LOCALE == 'mr-IN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_mr_IN;
    -}
    -
    -if (goog.LOCALE == 'ms_Latn' || goog.LOCALE == 'ms-Latn') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ms_Latn;
    -}
    -
    -if (goog.LOCALE == 'ms_Latn_BN' || goog.LOCALE == 'ms-Latn-BN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ms_Latn_BN;
    -}
    -
    -if (goog.LOCALE == 'ms_Latn_MY' || goog.LOCALE == 'ms-Latn-MY') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ms_Latn_MY;
    -}
    -
    -if (goog.LOCALE == 'ms_Latn_SG' || goog.LOCALE == 'ms-Latn-SG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ms_Latn_SG;
    -}
    -
    -if (goog.LOCALE == 'mt_MT' || goog.LOCALE == 'mt-MT') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_mt_MT;
    -}
    -
    -if (goog.LOCALE == 'mua') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_mua;
    -}
    -
    -if (goog.LOCALE == 'mua_CM' || goog.LOCALE == 'mua-CM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_mua_CM;
    -}
    -
    -if (goog.LOCALE == 'my_MM' || goog.LOCALE == 'my-MM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_my_MM;
    -}
    -
    -if (goog.LOCALE == 'naq') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_naq;
    -}
    -
    -if (goog.LOCALE == 'naq_NA' || goog.LOCALE == 'naq-NA') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_naq_NA;
    -}
    -
    -if (goog.LOCALE == 'nb_NO' || goog.LOCALE == 'nb-NO') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_nb_NO;
    -}
    -
    -if (goog.LOCALE == 'nb_SJ' || goog.LOCALE == 'nb-SJ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_nb_SJ;
    -}
    -
    -if (goog.LOCALE == 'nd') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_nd;
    -}
    -
    -if (goog.LOCALE == 'nd_ZW' || goog.LOCALE == 'nd-ZW') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_nd_ZW;
    -}
    -
    -if (goog.LOCALE == 'ne_IN' || goog.LOCALE == 'ne-IN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ne_IN;
    -}
    -
    -if (goog.LOCALE == 'ne_NP' || goog.LOCALE == 'ne-NP') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ne_NP;
    -}
    -
    -if (goog.LOCALE == 'nl_AW' || goog.LOCALE == 'nl-AW') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_nl_AW;
    -}
    -
    -if (goog.LOCALE == 'nl_BE' || goog.LOCALE == 'nl-BE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_nl_BE;
    -}
    -
    -if (goog.LOCALE == 'nl_BQ' || goog.LOCALE == 'nl-BQ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_nl_BQ;
    -}
    -
    -if (goog.LOCALE == 'nl_CW' || goog.LOCALE == 'nl-CW') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_nl_CW;
    -}
    -
    -if (goog.LOCALE == 'nl_NL' || goog.LOCALE == 'nl-NL') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_nl_NL;
    -}
    -
    -if (goog.LOCALE == 'nl_SR' || goog.LOCALE == 'nl-SR') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_nl_SR;
    -}
    -
    -if (goog.LOCALE == 'nl_SX' || goog.LOCALE == 'nl-SX') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_nl_SX;
    -}
    -
    -if (goog.LOCALE == 'nmg') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_nmg;
    -}
    -
    -if (goog.LOCALE == 'nmg_CM' || goog.LOCALE == 'nmg-CM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_nmg_CM;
    -}
    -
    -if (goog.LOCALE == 'nn') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_nn;
    -}
    -
    -if (goog.LOCALE == 'nn_NO' || goog.LOCALE == 'nn-NO') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_nn_NO;
    -}
    -
    -if (goog.LOCALE == 'nnh') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_nnh;
    -}
    -
    -if (goog.LOCALE == 'nnh_CM' || goog.LOCALE == 'nnh-CM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_nnh_CM;
    -}
    -
    -if (goog.LOCALE == 'nus') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_nus;
    -}
    -
    -if (goog.LOCALE == 'nus_SD' || goog.LOCALE == 'nus-SD') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_nus_SD;
    -}
    -
    -if (goog.LOCALE == 'nyn') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_nyn;
    -}
    -
    -if (goog.LOCALE == 'nyn_UG' || goog.LOCALE == 'nyn-UG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_nyn_UG;
    -}
    -
    -if (goog.LOCALE == 'om') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_om;
    -}
    -
    -if (goog.LOCALE == 'om_ET' || goog.LOCALE == 'om-ET') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_om_ET;
    -}
    -
    -if (goog.LOCALE == 'om_KE' || goog.LOCALE == 'om-KE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_om_KE;
    -}
    -
    -if (goog.LOCALE == 'or_IN' || goog.LOCALE == 'or-IN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_or_IN;
    -}
    -
    -if (goog.LOCALE == 'os') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_os;
    -}
    -
    -if (goog.LOCALE == 'os_GE' || goog.LOCALE == 'os-GE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_os_GE;
    -}
    -
    -if (goog.LOCALE == 'os_RU' || goog.LOCALE == 'os-RU') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_os_RU;
    -}
    -
    -if (goog.LOCALE == 'pa_Arab' || goog.LOCALE == 'pa-Arab') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_pa_Arab;
    -}
    -
    -if (goog.LOCALE == 'pa_Arab_PK' || goog.LOCALE == 'pa-Arab-PK') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_pa_Arab_PK;
    -}
    -
    -if (goog.LOCALE == 'pa_Guru' || goog.LOCALE == 'pa-Guru') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_pa_Guru;
    -}
    -
    -if (goog.LOCALE == 'pa_Guru_IN' || goog.LOCALE == 'pa-Guru-IN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_pa_Guru_IN;
    -}
    -
    -if (goog.LOCALE == 'pl_PL' || goog.LOCALE == 'pl-PL') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_pl_PL;
    -}
    -
    -if (goog.LOCALE == 'ps') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ps;
    -}
    -
    -if (goog.LOCALE == 'ps_AF' || goog.LOCALE == 'ps-AF') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ps_AF;
    -}
    -
    -if (goog.LOCALE == 'pt_AO' || goog.LOCALE == 'pt-AO') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_pt_AO;
    -}
    -
    -if (goog.LOCALE == 'pt_CV' || goog.LOCALE == 'pt-CV') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_pt_CV;
    -}
    -
    -if (goog.LOCALE == 'pt_GW' || goog.LOCALE == 'pt-GW') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_pt_GW;
    -}
    -
    -if (goog.LOCALE == 'pt_MO' || goog.LOCALE == 'pt-MO') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_pt_MO;
    -}
    -
    -if (goog.LOCALE == 'pt_MZ' || goog.LOCALE == 'pt-MZ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_pt_MZ;
    -}
    -
    -if (goog.LOCALE == 'pt_ST' || goog.LOCALE == 'pt-ST') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_pt_ST;
    -}
    -
    -if (goog.LOCALE == 'pt_TL' || goog.LOCALE == 'pt-TL') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_pt_TL;
    -}
    -
    -if (goog.LOCALE == 'qu') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_qu;
    -}
    -
    -if (goog.LOCALE == 'qu_BO' || goog.LOCALE == 'qu-BO') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_qu_BO;
    -}
    -
    -if (goog.LOCALE == 'qu_EC' || goog.LOCALE == 'qu-EC') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_qu_EC;
    -}
    -
    -if (goog.LOCALE == 'qu_PE' || goog.LOCALE == 'qu-PE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_qu_PE;
    -}
    -
    -if (goog.LOCALE == 'rm') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_rm;
    -}
    -
    -if (goog.LOCALE == 'rm_CH' || goog.LOCALE == 'rm-CH') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_rm_CH;
    -}
    -
    -if (goog.LOCALE == 'rn') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_rn;
    -}
    -
    -if (goog.LOCALE == 'rn_BI' || goog.LOCALE == 'rn-BI') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_rn_BI;
    -}
    -
    -if (goog.LOCALE == 'ro_MD' || goog.LOCALE == 'ro-MD') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ro_MD;
    -}
    -
    -if (goog.LOCALE == 'ro_RO' || goog.LOCALE == 'ro-RO') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ro_RO;
    -}
    -
    -if (goog.LOCALE == 'rof') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_rof;
    -}
    -
    -if (goog.LOCALE == 'rof_TZ' || goog.LOCALE == 'rof-TZ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_rof_TZ;
    -}
    -
    -if (goog.LOCALE == 'ru_BY' || goog.LOCALE == 'ru-BY') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ru_BY;
    -}
    -
    -if (goog.LOCALE == 'ru_KG' || goog.LOCALE == 'ru-KG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ru_KG;
    -}
    -
    -if (goog.LOCALE == 'ru_KZ' || goog.LOCALE == 'ru-KZ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ru_KZ;
    -}
    -
    -if (goog.LOCALE == 'ru_MD' || goog.LOCALE == 'ru-MD') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ru_MD;
    -}
    -
    -if (goog.LOCALE == 'ru_RU' || goog.LOCALE == 'ru-RU') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ru_RU;
    -}
    -
    -if (goog.LOCALE == 'ru_UA' || goog.LOCALE == 'ru-UA') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ru_UA;
    -}
    -
    -if (goog.LOCALE == 'rw') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_rw;
    -}
    -
    -if (goog.LOCALE == 'rw_RW' || goog.LOCALE == 'rw-RW') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_rw_RW;
    -}
    -
    -if (goog.LOCALE == 'rwk') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_rwk;
    -}
    -
    -if (goog.LOCALE == 'rwk_TZ' || goog.LOCALE == 'rwk-TZ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_rwk_TZ;
    -}
    -
    -if (goog.LOCALE == 'sah') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sah;
    -}
    -
    -if (goog.LOCALE == 'sah_RU' || goog.LOCALE == 'sah-RU') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sah_RU;
    -}
    -
    -if (goog.LOCALE == 'saq') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_saq;
    -}
    -
    -if (goog.LOCALE == 'saq_KE' || goog.LOCALE == 'saq-KE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_saq_KE;
    -}
    -
    -if (goog.LOCALE == 'sbp') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sbp;
    -}
    -
    -if (goog.LOCALE == 'sbp_TZ' || goog.LOCALE == 'sbp-TZ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sbp_TZ;
    -}
    -
    -if (goog.LOCALE == 'se') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_se;
    -}
    -
    -if (goog.LOCALE == 'se_FI' || goog.LOCALE == 'se-FI') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_se_FI;
    -}
    -
    -if (goog.LOCALE == 'se_NO' || goog.LOCALE == 'se-NO') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_se_NO;
    -}
    -
    -if (goog.LOCALE == 'se_SE' || goog.LOCALE == 'se-SE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_se_SE;
    -}
    -
    -if (goog.LOCALE == 'seh') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_seh;
    -}
    -
    -if (goog.LOCALE == 'seh_MZ' || goog.LOCALE == 'seh-MZ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_seh_MZ;
    -}
    -
    -if (goog.LOCALE == 'ses') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ses;
    -}
    -
    -if (goog.LOCALE == 'ses_ML' || goog.LOCALE == 'ses-ML') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ses_ML;
    -}
    -
    -if (goog.LOCALE == 'sg') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sg;
    -}
    -
    -if (goog.LOCALE == 'sg_CF' || goog.LOCALE == 'sg-CF') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sg_CF;
    -}
    -
    -if (goog.LOCALE == 'shi') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_shi;
    -}
    -
    -if (goog.LOCALE == 'shi_Latn' || goog.LOCALE == 'shi-Latn') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_shi_Latn;
    -}
    -
    -if (goog.LOCALE == 'shi_Latn_MA' || goog.LOCALE == 'shi-Latn-MA') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_shi_Latn_MA;
    -}
    -
    -if (goog.LOCALE == 'shi_Tfng' || goog.LOCALE == 'shi-Tfng') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_shi_Tfng;
    -}
    -
    -if (goog.LOCALE == 'shi_Tfng_MA' || goog.LOCALE == 'shi-Tfng-MA') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_shi_Tfng_MA;
    -}
    -
    -if (goog.LOCALE == 'si_LK' || goog.LOCALE == 'si-LK') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_si_LK;
    -}
    -
    -if (goog.LOCALE == 'sk_SK' || goog.LOCALE == 'sk-SK') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sk_SK;
    -}
    -
    -if (goog.LOCALE == 'sl_SI' || goog.LOCALE == 'sl-SI') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sl_SI;
    -}
    -
    -if (goog.LOCALE == 'smn') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_smn;
    -}
    -
    -if (goog.LOCALE == 'smn_FI' || goog.LOCALE == 'smn-FI') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_smn_FI;
    -}
    -
    -if (goog.LOCALE == 'sn') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sn;
    -}
    -
    -if (goog.LOCALE == 'sn_ZW' || goog.LOCALE == 'sn-ZW') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sn_ZW;
    -}
    -
    -if (goog.LOCALE == 'so') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_so;
    -}
    -
    -if (goog.LOCALE == 'so_DJ' || goog.LOCALE == 'so-DJ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_so_DJ;
    -}
    -
    -if (goog.LOCALE == 'so_ET' || goog.LOCALE == 'so-ET') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_so_ET;
    -}
    -
    -if (goog.LOCALE == 'so_KE' || goog.LOCALE == 'so-KE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_so_KE;
    -}
    -
    -if (goog.LOCALE == 'so_SO' || goog.LOCALE == 'so-SO') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_so_SO;
    -}
    -
    -if (goog.LOCALE == 'sq_AL' || goog.LOCALE == 'sq-AL') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sq_AL;
    -}
    -
    -if (goog.LOCALE == 'sq_MK' || goog.LOCALE == 'sq-MK') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sq_MK;
    -}
    -
    -if (goog.LOCALE == 'sq_XK' || goog.LOCALE == 'sq-XK') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sq_XK;
    -}
    -
    -if (goog.LOCALE == 'sr_Cyrl' || goog.LOCALE == 'sr-Cyrl') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sr_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'sr_Cyrl_BA' || goog.LOCALE == 'sr-Cyrl-BA') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sr_Cyrl_BA;
    -}
    -
    -if (goog.LOCALE == 'sr_Cyrl_ME' || goog.LOCALE == 'sr-Cyrl-ME') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sr_Cyrl_ME;
    -}
    -
    -if (goog.LOCALE == 'sr_Cyrl_RS' || goog.LOCALE == 'sr-Cyrl-RS') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sr_Cyrl_RS;
    -}
    -
    -if (goog.LOCALE == 'sr_Cyrl_XK' || goog.LOCALE == 'sr-Cyrl-XK') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sr_Cyrl_XK;
    -}
    -
    -if (goog.LOCALE == 'sr_Latn' || goog.LOCALE == 'sr-Latn') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sr_Latn;
    -}
    -
    -if (goog.LOCALE == 'sr_Latn_BA' || goog.LOCALE == 'sr-Latn-BA') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sr_Latn_BA;
    -}
    -
    -if (goog.LOCALE == 'sr_Latn_ME' || goog.LOCALE == 'sr-Latn-ME') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sr_Latn_ME;
    -}
    -
    -if (goog.LOCALE == 'sr_Latn_RS' || goog.LOCALE == 'sr-Latn-RS') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sr_Latn_RS;
    -}
    -
    -if (goog.LOCALE == 'sr_Latn_XK' || goog.LOCALE == 'sr-Latn-XK') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sr_Latn_XK;
    -}
    -
    -if (goog.LOCALE == 'sv_AX' || goog.LOCALE == 'sv-AX') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sv_AX;
    -}
    -
    -if (goog.LOCALE == 'sv_FI' || goog.LOCALE == 'sv-FI') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sv_FI;
    -}
    -
    -if (goog.LOCALE == 'sv_SE' || goog.LOCALE == 'sv-SE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sv_SE;
    -}
    -
    -if (goog.LOCALE == 'sw_KE' || goog.LOCALE == 'sw-KE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sw_KE;
    -}
    -
    -if (goog.LOCALE == 'sw_TZ' || goog.LOCALE == 'sw-TZ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sw_TZ;
    -}
    -
    -if (goog.LOCALE == 'sw_UG' || goog.LOCALE == 'sw-UG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_sw_UG;
    -}
    -
    -if (goog.LOCALE == 'swc') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_swc;
    -}
    -
    -if (goog.LOCALE == 'swc_CD' || goog.LOCALE == 'swc-CD') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_swc_CD;
    -}
    -
    -if (goog.LOCALE == 'ta_IN' || goog.LOCALE == 'ta-IN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ta_IN;
    -}
    -
    -if (goog.LOCALE == 'ta_LK' || goog.LOCALE == 'ta-LK') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ta_LK;
    -}
    -
    -if (goog.LOCALE == 'ta_MY' || goog.LOCALE == 'ta-MY') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ta_MY;
    -}
    -
    -if (goog.LOCALE == 'ta_SG' || goog.LOCALE == 'ta-SG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ta_SG;
    -}
    -
    -if (goog.LOCALE == 'te_IN' || goog.LOCALE == 'te-IN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_te_IN;
    -}
    -
    -if (goog.LOCALE == 'teo') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_teo;
    -}
    -
    -if (goog.LOCALE == 'teo_KE' || goog.LOCALE == 'teo-KE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_teo_KE;
    -}
    -
    -if (goog.LOCALE == 'teo_UG' || goog.LOCALE == 'teo-UG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_teo_UG;
    -}
    -
    -if (goog.LOCALE == 'th_TH' || goog.LOCALE == 'th-TH') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_th_TH;
    -}
    -
    -if (goog.LOCALE == 'ti') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ti;
    -}
    -
    -if (goog.LOCALE == 'ti_ER' || goog.LOCALE == 'ti-ER') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ti_ER;
    -}
    -
    -if (goog.LOCALE == 'ti_ET' || goog.LOCALE == 'ti-ET') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ti_ET;
    -}
    -
    -if (goog.LOCALE == 'to') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_to;
    -}
    -
    -if (goog.LOCALE == 'to_TO' || goog.LOCALE == 'to-TO') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_to_TO;
    -}
    -
    -if (goog.LOCALE == 'tr_CY' || goog.LOCALE == 'tr-CY') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_tr_CY;
    -}
    -
    -if (goog.LOCALE == 'tr_TR' || goog.LOCALE == 'tr-TR') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_tr_TR;
    -}
    -
    -if (goog.LOCALE == 'twq') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_twq;
    -}
    -
    -if (goog.LOCALE == 'twq_NE' || goog.LOCALE == 'twq-NE') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_twq_NE;
    -}
    -
    -if (goog.LOCALE == 'tzm') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_tzm;
    -}
    -
    -if (goog.LOCALE == 'tzm_Latn' || goog.LOCALE == 'tzm-Latn') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_tzm_Latn;
    -}
    -
    -if (goog.LOCALE == 'tzm_Latn_MA' || goog.LOCALE == 'tzm-Latn-MA') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_tzm_Latn_MA;
    -}
    -
    -if (goog.LOCALE == 'ug') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ug;
    -}
    -
    -if (goog.LOCALE == 'ug_Arab' || goog.LOCALE == 'ug-Arab') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ug_Arab;
    -}
    -
    -if (goog.LOCALE == 'ug_Arab_CN' || goog.LOCALE == 'ug-Arab-CN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ug_Arab_CN;
    -}
    -
    -if (goog.LOCALE == 'uk_UA' || goog.LOCALE == 'uk-UA') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_uk_UA;
    -}
    -
    -if (goog.LOCALE == 'ur_IN' || goog.LOCALE == 'ur-IN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ur_IN;
    -}
    -
    -if (goog.LOCALE == 'ur_PK' || goog.LOCALE == 'ur-PK') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_ur_PK;
    -}
    -
    -if (goog.LOCALE == 'uz_Arab' || goog.LOCALE == 'uz-Arab') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_uz_Arab;
    -}
    -
    -if (goog.LOCALE == 'uz_Arab_AF' || goog.LOCALE == 'uz-Arab-AF') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_uz_Arab_AF;
    -}
    -
    -if (goog.LOCALE == 'uz_Cyrl' || goog.LOCALE == 'uz-Cyrl') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_uz_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'uz_Cyrl_UZ' || goog.LOCALE == 'uz-Cyrl-UZ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_uz_Cyrl_UZ;
    -}
    -
    -if (goog.LOCALE == 'uz_Latn' || goog.LOCALE == 'uz-Latn') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_uz_Latn;
    -}
    -
    -if (goog.LOCALE == 'uz_Latn_UZ' || goog.LOCALE == 'uz-Latn-UZ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_uz_Latn_UZ;
    -}
    -
    -if (goog.LOCALE == 'vai') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_vai;
    -}
    -
    -if (goog.LOCALE == 'vai_Latn' || goog.LOCALE == 'vai-Latn') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_vai_Latn;
    -}
    -
    -if (goog.LOCALE == 'vai_Latn_LR' || goog.LOCALE == 'vai-Latn-LR') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_vai_Latn_LR;
    -}
    -
    -if (goog.LOCALE == 'vai_Vaii' || goog.LOCALE == 'vai-Vaii') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_vai_Vaii;
    -}
    -
    -if (goog.LOCALE == 'vai_Vaii_LR' || goog.LOCALE == 'vai-Vaii-LR') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_vai_Vaii_LR;
    -}
    -
    -if (goog.LOCALE == 'vi_VN' || goog.LOCALE == 'vi-VN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_vi_VN;
    -}
    -
    -if (goog.LOCALE == 'vun') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_vun;
    -}
    -
    -if (goog.LOCALE == 'vun_TZ' || goog.LOCALE == 'vun-TZ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_vun_TZ;
    -}
    -
    -if (goog.LOCALE == 'wae') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_wae;
    -}
    -
    -if (goog.LOCALE == 'wae_CH' || goog.LOCALE == 'wae-CH') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_wae_CH;
    -}
    -
    -if (goog.LOCALE == 'xog') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_xog;
    -}
    -
    -if (goog.LOCALE == 'xog_UG' || goog.LOCALE == 'xog-UG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_xog_UG;
    -}
    -
    -if (goog.LOCALE == 'yav') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_yav;
    -}
    -
    -if (goog.LOCALE == 'yav_CM' || goog.LOCALE == 'yav-CM') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_yav_CM;
    -}
    -
    -if (goog.LOCALE == 'yi') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_yi;
    -}
    -
    -if (goog.LOCALE == 'yi_001' || goog.LOCALE == 'yi-001') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_yi_001;
    -}
    -
    -if (goog.LOCALE == 'yo') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_yo;
    -}
    -
    -if (goog.LOCALE == 'yo_BJ' || goog.LOCALE == 'yo-BJ') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_yo_BJ;
    -}
    -
    -if (goog.LOCALE == 'yo_NG' || goog.LOCALE == 'yo-NG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_yo_NG;
    -}
    -
    -if (goog.LOCALE == 'zgh') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_zgh;
    -}
    -
    -if (goog.LOCALE == 'zgh_MA' || goog.LOCALE == 'zgh-MA') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_zgh_MA;
    -}
    -
    -if (goog.LOCALE == 'zh_Hans' || goog.LOCALE == 'zh-Hans') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_zh_Hans;
    -}
    -
    -if (goog.LOCALE == 'zh_Hans_CN' || goog.LOCALE == 'zh-Hans-CN') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_zh_Hans_CN;
    -}
    -
    -if (goog.LOCALE == 'zh_Hans_HK' || goog.LOCALE == 'zh-Hans-HK') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_zh_Hans_HK;
    -}
    -
    -if (goog.LOCALE == 'zh_Hans_MO' || goog.LOCALE == 'zh-Hans-MO') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_zh_Hans_MO;
    -}
    -
    -if (goog.LOCALE == 'zh_Hans_SG' || goog.LOCALE == 'zh-Hans-SG') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_zh_Hans_SG;
    -}
    -
    -if (goog.LOCALE == 'zh_Hant' || goog.LOCALE == 'zh-Hant') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_zh_Hant;
    -}
    -
    -if (goog.LOCALE == 'zh_Hant_HK' || goog.LOCALE == 'zh-Hant-HK') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_zh_Hant_HK;
    -}
    -
    -if (goog.LOCALE == 'zh_Hant_MO' || goog.LOCALE == 'zh-Hant-MO') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_zh_Hant_MO;
    -}
    -
    -if (goog.LOCALE == 'zh_Hant_TW' || goog.LOCALE == 'zh-Hant-TW') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_zh_Hant_TW;
    -}
    -
    -if (goog.LOCALE == 'zu_ZA' || goog.LOCALE == 'zu-ZA') {
    -  goog.i18n.DateTimePatterns = goog.i18n.DateTimePatterns_zu_ZA;
    -}
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/datetimesymbols.js b/src/database/third_party/closure-library/closure/goog/i18n/datetimesymbols.js
    deleted file mode 100644
    index ad299351e81..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/datetimesymbols.js
    +++ /dev/null
    @@ -1,4530 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Date/time formatting symbols for all locales.
    - *
    - * This file is autogenerated by script.  See
    - * http://go/generate_datetime_constants.py using --for_closure
    - * File generated from CLDR ver. 26
    - *
    - * To reduce the file size (which may cause issues in some JS
    - * developing environments), this file will only contain locales
    - * that are usually supported by google products. It is a super
    - * set of 40 languages. Rest of the data can be found in another file
    - * named "datetimesymbolsext.js", which will be generated at the same
    - * time as this file.
    - * Before checkin, this file could have been manually edited. This is
    - * to incorporate changes before we could correct CLDR. All manual
    - * modification must be documented in this section, and should be
    - * removed after those changes land to CLDR.
    - */
    -
    -goog.provide('goog.i18n.DateTimeSymbols');
    -goog.provide('goog.i18n.DateTimeSymbols_af');
    -goog.provide('goog.i18n.DateTimeSymbols_am');
    -goog.provide('goog.i18n.DateTimeSymbols_ar');
    -goog.provide('goog.i18n.DateTimeSymbols_az');
    -goog.provide('goog.i18n.DateTimeSymbols_bg');
    -goog.provide('goog.i18n.DateTimeSymbols_bn');
    -goog.provide('goog.i18n.DateTimeSymbols_br');
    -goog.provide('goog.i18n.DateTimeSymbols_ca');
    -goog.provide('goog.i18n.DateTimeSymbols_chr');
    -goog.provide('goog.i18n.DateTimeSymbols_cs');
    -goog.provide('goog.i18n.DateTimeSymbols_cy');
    -goog.provide('goog.i18n.DateTimeSymbols_da');
    -goog.provide('goog.i18n.DateTimeSymbols_de');
    -goog.provide('goog.i18n.DateTimeSymbols_de_AT');
    -goog.provide('goog.i18n.DateTimeSymbols_de_CH');
    -goog.provide('goog.i18n.DateTimeSymbols_el');
    -goog.provide('goog.i18n.DateTimeSymbols_en');
    -goog.provide('goog.i18n.DateTimeSymbols_en_AU');
    -goog.provide('goog.i18n.DateTimeSymbols_en_GB');
    -goog.provide('goog.i18n.DateTimeSymbols_en_IE');
    -goog.provide('goog.i18n.DateTimeSymbols_en_IN');
    -goog.provide('goog.i18n.DateTimeSymbols_en_ISO');
    -goog.provide('goog.i18n.DateTimeSymbols_en_SG');
    -goog.provide('goog.i18n.DateTimeSymbols_en_US');
    -goog.provide('goog.i18n.DateTimeSymbols_en_ZA');
    -goog.provide('goog.i18n.DateTimeSymbols_es');
    -goog.provide('goog.i18n.DateTimeSymbols_es_419');
    -goog.provide('goog.i18n.DateTimeSymbols_es_ES');
    -goog.provide('goog.i18n.DateTimeSymbols_et');
    -goog.provide('goog.i18n.DateTimeSymbols_eu');
    -goog.provide('goog.i18n.DateTimeSymbols_fa');
    -goog.provide('goog.i18n.DateTimeSymbols_fi');
    -goog.provide('goog.i18n.DateTimeSymbols_fil');
    -goog.provide('goog.i18n.DateTimeSymbols_fr');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_CA');
    -goog.provide('goog.i18n.DateTimeSymbols_ga');
    -goog.provide('goog.i18n.DateTimeSymbols_gl');
    -goog.provide('goog.i18n.DateTimeSymbols_gsw');
    -goog.provide('goog.i18n.DateTimeSymbols_gu');
    -goog.provide('goog.i18n.DateTimeSymbols_haw');
    -goog.provide('goog.i18n.DateTimeSymbols_he');
    -goog.provide('goog.i18n.DateTimeSymbols_hi');
    -goog.provide('goog.i18n.DateTimeSymbols_hr');
    -goog.provide('goog.i18n.DateTimeSymbols_hu');
    -goog.provide('goog.i18n.DateTimeSymbols_hy');
    -goog.provide('goog.i18n.DateTimeSymbols_id');
    -goog.provide('goog.i18n.DateTimeSymbols_in');
    -goog.provide('goog.i18n.DateTimeSymbols_is');
    -goog.provide('goog.i18n.DateTimeSymbols_it');
    -goog.provide('goog.i18n.DateTimeSymbols_iw');
    -goog.provide('goog.i18n.DateTimeSymbols_ja');
    -goog.provide('goog.i18n.DateTimeSymbols_ka');
    -goog.provide('goog.i18n.DateTimeSymbols_kk');
    -goog.provide('goog.i18n.DateTimeSymbols_km');
    -goog.provide('goog.i18n.DateTimeSymbols_kn');
    -goog.provide('goog.i18n.DateTimeSymbols_ko');
    -goog.provide('goog.i18n.DateTimeSymbols_ky');
    -goog.provide('goog.i18n.DateTimeSymbols_ln');
    -goog.provide('goog.i18n.DateTimeSymbols_lo');
    -goog.provide('goog.i18n.DateTimeSymbols_lt');
    -goog.provide('goog.i18n.DateTimeSymbols_lv');
    -goog.provide('goog.i18n.DateTimeSymbols_mk');
    -goog.provide('goog.i18n.DateTimeSymbols_ml');
    -goog.provide('goog.i18n.DateTimeSymbols_mn');
    -goog.provide('goog.i18n.DateTimeSymbols_mr');
    -goog.provide('goog.i18n.DateTimeSymbols_ms');
    -goog.provide('goog.i18n.DateTimeSymbols_mt');
    -goog.provide('goog.i18n.DateTimeSymbols_my');
    -goog.provide('goog.i18n.DateTimeSymbols_nb');
    -goog.provide('goog.i18n.DateTimeSymbols_ne');
    -goog.provide('goog.i18n.DateTimeSymbols_nl');
    -goog.provide('goog.i18n.DateTimeSymbols_no');
    -goog.provide('goog.i18n.DateTimeSymbols_no_NO');
    -goog.provide('goog.i18n.DateTimeSymbols_or');
    -goog.provide('goog.i18n.DateTimeSymbols_pa');
    -goog.provide('goog.i18n.DateTimeSymbols_pl');
    -goog.provide('goog.i18n.DateTimeSymbols_pt');
    -goog.provide('goog.i18n.DateTimeSymbols_pt_BR');
    -goog.provide('goog.i18n.DateTimeSymbols_pt_PT');
    -goog.provide('goog.i18n.DateTimeSymbols_ro');
    -goog.provide('goog.i18n.DateTimeSymbols_ru');
    -goog.provide('goog.i18n.DateTimeSymbols_si');
    -goog.provide('goog.i18n.DateTimeSymbols_sk');
    -goog.provide('goog.i18n.DateTimeSymbols_sl');
    -goog.provide('goog.i18n.DateTimeSymbols_sq');
    -goog.provide('goog.i18n.DateTimeSymbols_sr');
    -goog.provide('goog.i18n.DateTimeSymbols_sv');
    -goog.provide('goog.i18n.DateTimeSymbols_sw');
    -goog.provide('goog.i18n.DateTimeSymbols_ta');
    -goog.provide('goog.i18n.DateTimeSymbols_te');
    -goog.provide('goog.i18n.DateTimeSymbols_th');
    -goog.provide('goog.i18n.DateTimeSymbols_tl');
    -goog.provide('goog.i18n.DateTimeSymbols_tr');
    -goog.provide('goog.i18n.DateTimeSymbols_uk');
    -goog.provide('goog.i18n.DateTimeSymbols_ur');
    -goog.provide('goog.i18n.DateTimeSymbols_uz');
    -goog.provide('goog.i18n.DateTimeSymbols_vi');
    -goog.provide('goog.i18n.DateTimeSymbols_zh');
    -goog.provide('goog.i18n.DateTimeSymbols_zh_CN');
    -goog.provide('goog.i18n.DateTimeSymbols_zh_HK');
    -goog.provide('goog.i18n.DateTimeSymbols_zh_TW');
    -goog.provide('goog.i18n.DateTimeSymbols_zu');
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_ISO.
    - */
    -goog.i18n.DateTimeSymbols_en_ISO = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, y MMMM dd', 'y MMMM d', 'y MMM d', 'yyyy-MM-dd'],
    -  TIMEFORMATS: ['HH:mm:ss v', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}',
    -    '{1}, {0}', '{1}, {0}'],
    -  AVAILABLEFORMATS: {'Md': 'M/d', 'MMMMd': 'MMMM d', 'MMMd': 'MMM d'},
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale af.
    - */
    -goog.i18n.DateTimeSymbols_af = {
    -  ERAS: ['v.C.', 'n.C.'],
    -  ERANAMES: ['voor Christus', 'na Christus'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januarie', 'Februarie', 'Maart', 'April', 'Mei', 'Junie', 'Julie',
    -    'Augustus', 'September', 'Oktober', 'November', 'Desember'],
    -  STANDALONEMONTHS: ['Januarie', 'Februarie', 'Maart', 'April', 'Mei', 'Junie',
    -    'Julie', 'Augustus', 'September', 'Oktober', 'November', 'Desember'],
    -  SHORTMONTHS: ['Jan.', 'Feb.', 'Mrt.', 'Apr', 'Mei', 'Jun', 'Jul', 'Aug',
    -    'Sep', 'Okt', 'Nov', 'Des'],
    -  STANDALONESHORTMONTHS: ['Jan.', 'Feb.', 'Mrt.', 'Apr', 'Mei', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Okt', 'Nov', 'Des'],
    -  WEEKDAYS: ['Sondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrydag',
    -    'Saterdag'],
    -  STANDALONEWEEKDAYS: ['Sondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag',
    -    'Vrydag', 'Saterdag'],
    -  SHORTWEEKDAYS: ['So', 'Ma', 'Di', 'Wo', 'Do', 'Vr', 'Sa'],
    -  STANDALONESHORTWEEKDAYS: ['So', 'Ma', 'Di', 'Wo', 'Do', 'Vr', 'Sa'],
    -  NARROWWEEKDAYS: ['S', 'M', 'D', 'W', 'D', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'D', 'W', 'D', 'V', 'S'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['1ste kwartaal', '2de kwartaal', '3de kwartaal', '4de kwartaal'],
    -  AMPMS: ['vm.', 'nm.'],
    -  DATEFORMATS: ['EEEE, dd MMMM y', 'dd MMMM y', 'dd MMM y', 'y-MM-dd'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale am.
    - */
    -goog.i18n.DateTimeSymbols_am = {
    -  ERAS: ['ዓ/ዓ', 'ዓ/ም'],
    -  ERANAMES: ['ዓመተ ዓለም', 'ዓመተ ምሕረት'],
    -  NARROWMONTHS: ['ጃ', 'ፌ', 'ማ', 'ኤ', 'ሜ', 'ጁ', 'ጁ', 'ኦ', 'ሴ',
    -    'ኦ', 'ኖ', 'ዲ'],
    -  STANDALONENARROWMONTHS: ['ጃ', 'ፌ', 'ማ', 'ኤ', 'ሜ', 'ጁ', 'ጁ',
    -    'ኦ', 'ሴ', 'ኦ', 'ኖ', 'ዲ'],
    -  MONTHS: ['ጃንዩወሪ', 'ፌብሩወሪ', 'ማርች', 'ኤፕሪል',
    -    'ሜይ', 'ጁን', 'ጁላይ', 'ኦገስት', 'ሴፕቴምበር',
    -    'ኦክቶበር', 'ኖቬምበር', 'ዲሴምበር'],
    -  STANDALONEMONTHS: ['ጃንዩወሪ', 'ፌብሩወሪ', 'ማርች',
    -    'ኤፕሪል', 'ሜይ', 'ጁን', 'ጁላይ', 'ኦገስት',
    -    'ሴፕቴምበር', 'ኦክቶበር', 'ኖቬምበር',
    -    'ዲሴምበር'],
    -  SHORTMONTHS: ['ጃንዩ', 'ፌብሩ', 'ማርች', 'ኤፕሪ', 'ሜይ',
    -    'ጁን', 'ጁላይ', 'ኦገስ', 'ሴፕቴ', 'ኦክቶ', 'ኖቬም',
    -    'ዲሴም'],
    -  STANDALONESHORTMONTHS: ['ጃንዩ', 'ፌብሩ', 'ማርች', 'ኤፕሪ',
    -    'ሜይ', 'ጁን', 'ጁላይ', 'ኦገስ', 'ሴፕቴ', 'ኦክቶ',
    -    'ኖቬም', 'ዲሴም'],
    -  WEEKDAYS: ['እሑድ', 'ሰኞ', 'ማክሰኞ', 'ረቡዕ', 'ሐሙስ',
    -    'ዓርብ', 'ቅዳሜ'],
    -  STANDALONEWEEKDAYS: ['እሑድ', 'ሰኞ', 'ማክሰኞ', 'ረቡዕ',
    -    'ሐሙስ', 'ዓርብ', 'ቅዳሜ'],
    -  SHORTWEEKDAYS: ['እሑድ', 'ሰኞ', 'ማክሰ', 'ረቡዕ', 'ሐሙስ',
    -    'ዓርብ', 'ቅዳሜ'],
    -  STANDALONESHORTWEEKDAYS: ['እሑድ', 'ሰኞ', 'ማክሰ', 'ረቡዕ',
    -    'ሐሙስ', 'ዓርብ', 'ቅዳሜ'],
    -  NARROWWEEKDAYS: ['እ', 'ሰ', 'ማ', 'ረ', 'ሐ', 'ዓ', 'ቅ'],
    -  STANDALONENARROWWEEKDAYS: ['እ', 'ሰ', 'ማ', 'ረ', 'ሐ', 'ዓ', 'ቅ'],
    -  SHORTQUARTERS: ['ሩብ1', 'ሩብ2', 'ሩብ3', 'ሩብ4'],
    -  QUARTERS: ['1ኛው ሩብ', 'ሁለተኛው ሩብ', '3ኛው ሩብ',
    -    '4ኛው ሩብ'],
    -  AMPMS: ['ጥዋት', 'ከሰዓት'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ar.
    - */
    -goog.i18n.DateTimeSymbols_ar = {
    -  ZERODIGIT: 0x0660,
    -  ERAS: ['ق.م', 'م'],
    -  ERANAMES: ['قبل الميلاد', 'ميلادي'],
    -  NARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س', 'ك',
    -    'ب', 'د'],
    -  STANDALONENARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س',
    -    'ك', 'ب', 'د'],
    -  MONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو',
    -    'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر',
    -    'نوفمبر', 'ديسمبر'],
    -  STANDALONEMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  SHORTMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  STANDALONESHORTMONTHS: ['يناير', 'فبراير', 'مارس',
    -    'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس',
    -    'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  WEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONEWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  SHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONESHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  NARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  STANDALONENARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  SHORTQUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  QUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  AMPMS: ['ص', 'م'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'dd‏/MM‏/y',
    -    'd‏/M‏/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 5,
    -  WEEKENDRANGE: [4, 5],
    -  FIRSTWEEKCUTOFFDAY: 4
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale az.
    - */
    -goog.i18n.DateTimeSymbols_az = {
    -  ERAS: ['e.ə.', 'b.e.'],
    -  ERANAMES: ['eramızdan əvvəl', 'bizim eramızın'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['yanvar', 'fevral', 'mart', 'aprel', 'may', 'iyun', 'iyul', 'avqust',
    -    'sentyabr', 'oktyabr', 'noyabr', 'dekabr'],
    -  STANDALONEMONTHS: ['Yanvar', 'Fevral', 'Mart', 'Aprel', 'May', 'İyun',
    -    'İyul', 'Avqust', 'Sentyabr', 'Oktyabr', 'Noyabr', 'Dekabr'],
    -  SHORTMONTHS: ['yan', 'fev', 'mar', 'apr', 'may', 'iyn', 'iyl', 'avq', 'sen',
    -    'okt', 'noy', 'dek'],
    -  STANDALONESHORTMONTHS: ['yan', 'fev', 'mar', 'apr', 'may', 'iyn', 'iyl',
    -    'avq', 'sen', 'okt', 'noy', 'dek'],
    -  WEEKDAYS: ['bazar', 'bazar ertəsi', 'çərşənbə axşamı',
    -    'çərşənbə', 'cümə axşamı', 'cümə', 'şənbə'],
    -  STANDALONEWEEKDAYS: ['bazar', 'bazar ertəsi', 'çərşənbə axşamı',
    -    'çərşənbə', 'cümə axşamı', 'cümə', 'şənbə'],
    -  SHORTWEEKDAYS: ['B.', 'B.E.', 'Ç.A.', 'Ç.', 'C.A.', 'C.', 'Ş.'],
    -  STANDALONESHORTWEEKDAYS: ['B.', 'B.E.', 'Ç.A.', 'Ç.', 'C.A.', 'C.', 'Ş.'],
    -  NARROWWEEKDAYS: ['7', '1', '2', '3', '4', '5', '6'],
    -  STANDALONENARROWWEEKDAYS: ['7', '1', '2', '3', '4', '5', '6'],
    -  SHORTQUARTERS: ['1-ci kv.', '2-ci kv.', '3-cü kv.', '4-cü kv.'],
    -  QUARTERS: ['1-ci kvartal', '2-ci kvartal', '3-cü kvartal', '4-cü kvartal'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['d MMMM y, EEEE', 'd MMMM y', 'd MMM y', 'dd.MM.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale bg.
    - */
    -goog.i18n.DateTimeSymbols_bg = {
    -  ERAS: ['пр.Хр.', 'сл.Хр.'],
    -  ERANAMES: ['преди Христа', 'след Христа'],
    -  NARROWMONTHS: ['я', 'ф', 'м', 'а', 'м', 'ю', 'ю', 'а', 'с', 'о',
    -    'н', 'д'],
    -  STANDALONENARROWMONTHS: ['я', 'ф', 'м', 'а', 'м', 'ю', 'ю', 'а', 'с',
    -    'о', 'н', 'д'],
    -  MONTHS: ['януари', 'февруари', 'март', 'април',
    -    'май', 'юни', 'юли', 'август', 'септември',
    -    'октомври', 'ноември', 'декември'],
    -  STANDALONEMONTHS: ['януари', 'февруари', 'март',
    -    'април', 'май', 'юни', 'юли', 'август',
    -    'септември', 'октомври', 'ноември',
    -    'декември'],
    -  SHORTMONTHS: ['ян.', 'февр.', 'март', 'апр.', 'май', 'юни',
    -    'юли', 'авг.', 'септ.', 'окт.', 'ноем.', 'дек.'],
    -  STANDALONESHORTMONTHS: ['ян.', 'февр.', 'март', 'апр.', 'май',
    -    'юни', 'юли', 'авг.', 'септ.', 'окт.', 'ноем.',
    -    'дек.'],
    -  WEEKDAYS: ['неделя', 'понеделник', 'вторник',
    -    'сряда', 'четвъртък', 'петък', 'събота'],
    -  STANDALONEWEEKDAYS: ['неделя', 'понеделник', 'вторник',
    -    'сряда', 'четвъртък', 'петък', 'събота'],
    -  SHORTWEEKDAYS: ['нд', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],
    -  STANDALONESHORTWEEKDAYS: ['нд', 'пн', 'вт', 'ср', 'чт', 'пт',
    -    'сб'],
    -  NARROWWEEKDAYS: ['н', 'п', 'в', 'с', 'ч', 'п', 'с'],
    -  STANDALONENARROWWEEKDAYS: ['н', 'п', 'в', 'с', 'ч', 'п', 'с'],
    -  SHORTQUARTERS: ['1. трим.', '2. трим.', '3. трим.',
    -    '4. трим.'],
    -  QUARTERS: ['1. тримесечие', '2. тримесечие',
    -    '3. тримесечие', '4. тримесечие'],
    -  AMPMS: ['пр.об.', 'сл.об.'],
    -  DATEFORMATS: ['EEEE, d MMMM y \'г\'.', 'd MMMM y \'г\'.', 'd.MM.y \'г\'.',
    -    'd.MM.yy \'г\'.'],
    -  TIMEFORMATS: ['H:mm:ss zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale bn.
    - */
    -goog.i18n.DateTimeSymbols_bn = {
    -  ZERODIGIT: 0x09E6,
    -  ERAS: ['খ্রিস্টপূর্ব', 'খৃষ্টাব্দ'],
    -  ERANAMES: ['খ্রিস্টপূর্ব',
    -    'খৃষ্টাব্দ'],
    -  NARROWMONTHS: ['জা', 'ফে', 'মা', 'এ', 'মে', 'জুন',
    -    'জু', 'আ', 'সে', 'অ', 'ন', 'ডি'],
    -  STANDALONENARROWMONTHS: ['জা', 'ফে', 'মা', 'এ', 'মে',
    -    'জুন', 'জু', 'আ', 'সে', 'অ', 'ন', 'ডি'],
    -  MONTHS: ['জানুয়ারী', 'ফেব্রুয়ারী',
    -    'মার্চ', 'এপ্রিল', 'মে', 'জুন',
    -    'জুলাই', 'আগস্ট', 'সেপ্টেম্বর',
    -    'অক্টোবর', 'নভেম্বর',
    -    'ডিসেম্বর'],
    -  STANDALONEMONTHS: ['জানুয়ারী',
    -    'ফেব্রুয়ারী', 'মার্চ',
    -    'এপ্রিল', 'মে', 'জুন', 'জুলাই',
    -    'আগস্ট', 'সেপ্টেম্বর',
    -    'অক্টোবর', 'নভেম্বর',
    -    'ডিসেম্বর'],
    -  SHORTMONTHS: ['জানুয়ারী',
    -    'ফেব্রুয়ারী', 'মার্চ',
    -    'এপ্রিল', 'মে', 'জুন', 'জুলাই',
    -    'আগস্ট', 'সেপ্টেম্বর',
    -    'অক্টোবর', 'নভেম্বর',
    -    'ডিসেম্বর'],
    -  STANDALONESHORTMONTHS: ['জানুয়ারী',
    -    'ফেব্রুয়ারী', 'মার্চ',
    -    'এপ্রিল', 'মে', 'জুন', 'জুলাই',
    -    'আগস্ট', 'সেপ্টেম্বর',
    -    'অক্টোবর', 'নভেম্বর',
    -    'ডিসেম্বর'],
    -  WEEKDAYS: ['রবিবার', 'সোমবার',
    -    'মঙ্গলবার', 'বুধবার',
    -    'বৃহস্পতিবার', 'শুক্রবার',
    -    'শনিবার'],
    -  STANDALONEWEEKDAYS: ['রবিবার', 'সোমবার',
    -    'মঙ্গলবার', 'বুধবার',
    -    'বৃহষ্পতিবার', 'শুক্রবার',
    -    'শনিবার'],
    -  SHORTWEEKDAYS: ['রবি', 'সোম', 'মঙ্গল', 'বুধ',
    -    'বৃহস্পতি', 'শুক্র', 'শনি'],
    -  STANDALONESHORTWEEKDAYS: ['রবি', 'সোম', 'মঙ্গল',
    -    'বুধ', 'বৃহস্পতি', 'শুক্র', 'শনি'],
    -  NARROWWEEKDAYS: ['র', 'সো', 'ম', 'বু', 'বৃ', 'শু', 'শ'],
    -  STANDALONENARROWWEEKDAYS: ['র', 'সো', 'ম', 'বু', 'বৃ',
    -    'শু', 'শ'],
    -  SHORTQUARTERS: [
    -    'প্র. ত্রৈ. এক. চতুর্থাংশ',
    -    'দ্বি.ত্রৈ.এক. চতুর্থাংশ',
    -    'তৃ.ত্রৈ.এক.চতুর্থাংশ',
    -    'চ.ত্রৈ.এক চতুর্থাংশ'],
    -  QUARTERS: [
    -    'প্রথম ত্রৈমাসিকের এক চতুর্থাংশ',
    -    'দ্বিতীয় ত্রৈমাসিকের এক চতুর্থাংশ',
    -    'তৃতীয় ত্রৈমাসিকের এক চতুর্থাংশ',
    -    'চতুর্থ ত্রৈমাসিকের এক চতুর্থাংশ'],
    -  AMPMS: ['am', 'pm'],
    -  DATEFORMATS: ['EEEE, d MMMM, y', 'd MMMM, y', 'd MMM, y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 4,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale br.
    - */
    -goog.i18n.DateTimeSymbols_br = {
    -  ERAS: ['BCE', 'CE'],
    -  ERANAMES: ['BCE', 'CE'],
    -  NARROWMONTHS: ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10',
    -    '11', '12'],
    -  STANDALONENARROWMONTHS: ['01', '02', '03', '04', '05', '06', '07', '08', '09',
    -    '10', '11', '12'],
    -  MONTHS: ['Genver', 'Cʼhwevrer', 'Meurzh', 'Ebrel', 'Mae', 'Mezheven',
    -    'Gouere', 'Eost', 'Gwengolo', 'Here', 'Du', 'Kerzu'],
    -  STANDALONEMONTHS: ['Genver', 'Cʼhwevrer', 'Meurzh', 'Ebrel', 'Mae',
    -    'Mezheven', 'Gouere', 'Eost', 'Gwengolo', 'Here', 'Du', 'Kerzu'],
    -  SHORTMONTHS: ['Gen', 'Cʼhwe', 'Meur', 'Ebr', 'Mae', 'Mezh', 'Goue', 'Eost',
    -    'Gwen', 'Here', 'Du', 'Ker'],
    -  STANDALONESHORTMONTHS: ['Gen', 'Cʼhwe', 'Meur', 'Ebr', 'Mae', 'Mezh', 'Goue',
    -    'Eost', 'Gwen', 'Here', 'Du', 'Ker'],
    -  WEEKDAYS: ['Sul', 'Lun', 'Meurzh', 'Mercʼher', 'Yaou', 'Gwener', 'Sadorn'],
    -  STANDALONEWEEKDAYS: ['Sul', 'Lun', 'Meurzh', 'Mercʼher', 'Yaou', 'Gwener',
    -    'Sadorn'],
    -  SHORTWEEKDAYS: ['Sul', 'Lun', 'Meu.', 'Mer.', 'Yaou', 'Gwe.', 'Sad.'],
    -  STANDALONESHORTWEEKDAYS: ['Sul', 'Lun', 'Meu.', 'Mer.', 'Yaou', 'Gwe.',
    -    'Sad.'],
    -  NARROWWEEKDAYS: ['Su', 'L', 'Mz', 'Mc', 'Y', 'G', 'Sa'],
    -  STANDALONENARROWWEEKDAYS: ['Su', 'L', 'Mz', 'Mc', 'Y', 'G', 'Sa'],
    -  SHORTQUARTERS: ['1añ trim.', '2l trim.', '3e trim.', '4e trim.'],
    -  QUARTERS: ['1añ trimiziad', '2l trimiziad', '3e trimiziad', '4e trimiziad'],
    -  AMPMS: ['A.M.', 'G.M.'],
    -  DATEFORMATS: ['y MMMM d, EEEE', 'y MMMM d', 'y MMM d', 'y-MM-dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ca.
    - */
    -goog.i18n.DateTimeSymbols_ca = {
    -  ERAS: ['aC', 'dC'],
    -  ERANAMES: ['abans de Crist', 'després de Crist'],
    -  NARROWMONTHS: ['GN', 'FB', 'MÇ', 'AB', 'MG', 'JN', 'JL', 'AG', 'ST', 'OC',
    -    'NV', 'DS'],
    -  STANDALONENARROWMONTHS: ['GN', 'FB', 'MÇ', 'AB', 'MG', 'JN', 'JL', 'AG',
    -    'ST', 'OC', 'NV', 'DS'],
    -  MONTHS: ['gener', 'febrer', 'març', 'abril', 'maig', 'juny', 'juliol',
    -    'agost', 'setembre', 'octubre', 'novembre', 'desembre'],
    -  STANDALONEMONTHS: ['gener', 'febrer', 'març', 'abril', 'maig', 'juny',
    -    'juliol', 'agost', 'setembre', 'octubre', 'novembre', 'desembre'],
    -  SHORTMONTHS: ['gen.', 'febr.', 'març', 'abr.', 'maig', 'juny', 'jul.', 'ag.',
    -    'set.', 'oct.', 'nov.', 'des.'],
    -  STANDALONESHORTMONTHS: ['gen.', 'febr.', 'març', 'abr.', 'maig', 'juny',
    -    'jul.', 'ag.', 'set.', 'oct.', 'nov.', 'des.'],
    -  WEEKDAYS: ['diumenge', 'dilluns', 'dimarts', 'dimecres', 'dijous',
    -    'divendres', 'dissabte'],
    -  STANDALONEWEEKDAYS: ['diumenge', 'dilluns', 'dimarts', 'dimecres', 'dijous',
    -    'divendres', 'dissabte'],
    -  SHORTWEEKDAYS: ['dg.', 'dl.', 'dt.', 'dc.', 'dj.', 'dv.', 'ds.'],
    -  STANDALONESHORTWEEKDAYS: ['dg.', 'dl.', 'dt.', 'dc.', 'dj.', 'dv.', 'ds.'],
    -  NARROWWEEKDAYS: ['dg', 'dl', 'dt', 'dc', 'dj', 'dv', 'ds'],
    -  STANDALONENARROWWEEKDAYS: ['dg', 'dl', 'dt', 'dc', 'dj', 'dv', 'ds'],
    -  SHORTQUARTERS: ['1T', '2T', '3T', '4T'],
    -  QUARTERS: ['1r trimestre', '2n trimestre', '3r trimestre', '4t trimestre'],
    -  AMPMS: ['a. m.', 'p. m.'],
    -  DATEFORMATS: ['EEEE, d MMMM \'de\' y', 'd MMMM \'de\' y', 'd MMM y',
    -    'd/M/yy'],
    -  TIMEFORMATS: ['H:mm:ss zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1} \'a les\' {0}', '{1}, {0}', '{1} , {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale chr.
    - */
    -goog.i18n.DateTimeSymbols_chr = {
    -  ERAS: ['ᎤᏓᎷᎸ', 'ᎤᎶᏐᏅ'],
    -  ERANAMES: ['Ꮟ ᏥᏌ ᎾᏕᎲᏍᎬᎾ',
    -    'ᎠᎩᏃᎮᎵᏓᏍᏗᏱ ᎠᏕᏘᏱᏍᎬ ᏱᎰᏩ ᏧᏓᏂᎸᎢᏍᏗ'],
    -  NARROWMONTHS: ['Ꭴ', 'Ꭷ', 'Ꭰ', 'Ꭷ', 'Ꭰ', 'Ꮥ', 'Ꭻ', 'Ꭶ', 'Ꮪ',
    -    'Ꮪ', 'Ꮕ', 'Ꭵ'],
    -  STANDALONENARROWMONTHS: ['Ꭴ', 'Ꭷ', 'Ꭰ', 'Ꭷ', 'Ꭰ', 'Ꮥ', 'Ꭻ',
    -    'Ꭶ', 'Ꮪ', 'Ꮪ', 'Ꮕ', 'Ꭵ'],
    -  MONTHS: ['ᎤᏃᎸᏔᏅ', 'ᎧᎦᎵ', 'ᎠᏅᏱ', 'ᎧᏬᏂ',
    -    'ᎠᏂᏍᎬᏘ', 'ᏕᎭᎷᏱ', 'ᎫᏰᏉᏂ', 'ᎦᎶᏂ',
    -    'ᏚᎵᏍᏗ', 'ᏚᏂᏅᏗ', 'ᏅᏓᏕᏆ', 'ᎥᏍᎩᏱ'],
    -  STANDALONEMONTHS: ['ᎤᏃᎸᏔᏅ', 'ᎧᎦᎵ', 'ᎠᏅᏱ', 'ᎧᏬᏂ',
    -    'ᎠᏂᏍᎬᏘ', 'ᏕᎭᎷᏱ', 'ᎫᏰᏉᏂ', 'ᎦᎶᏂ',
    -    'ᏚᎵᏍᏗ', 'ᏚᏂᏅᏗ', 'ᏅᏓᏕᏆ', 'ᎥᏍᎩᏱ'],
    -  SHORTMONTHS: ['ᎤᏃ', 'ᎧᎦ', 'ᎠᏅ', 'ᎧᏬ', 'ᎠᏂ', 'ᏕᎭ',
    -    'ᎫᏰ', 'ᎦᎶ', 'ᏚᎵ', 'ᏚᏂ', 'ᏅᏓ', 'ᎥᏍ'],
    -  STANDALONESHORTMONTHS: ['ᎤᏃ', 'ᎧᎦ', 'ᎠᏅ', 'ᎧᏬ', 'ᎠᏂ',
    -    'ᏕᎭ', 'ᎫᏰ', 'ᎦᎶ', 'ᏚᎵ', 'ᏚᏂ', 'ᏅᏓ', 'ᎥᏍ'],
    -  WEEKDAYS: ['ᎤᎾᏙᏓᏆᏍᎬ', 'ᎤᎾᏙᏓᏉᏅᎯ',
    -    'ᏔᎵᏁᎢᎦ', 'ᏦᎢᏁᎢᎦ', 'ᏅᎩᏁᎢᎦ',
    -    'ᏧᎾᎩᎶᏍᏗ', 'ᎤᎾᏙᏓᏈᏕᎾ'],
    -  STANDALONEWEEKDAYS: ['ᎤᎾᏙᏓᏆᏍᎬ', 'ᎤᎾᏙᏓᏉᏅᎯ',
    -    'ᏔᎵᏁᎢᎦ', 'ᏦᎢᏁᎢᎦ', 'ᏅᎩᏁᎢᎦ',
    -    'ᏧᎾᎩᎶᏍᏗ', 'ᎤᎾᏙᏓᏈᏕᎾ'],
    -  SHORTWEEKDAYS: ['ᏆᏍᎬ', 'ᏉᏅᎯ', 'ᏔᎵᏁ', 'ᏦᎢᏁ',
    -    'ᏅᎩᏁ', 'ᏧᎾᎩ', 'ᏈᏕᎾ'],
    -  STANDALONESHORTWEEKDAYS: ['ᏆᏍᎬ', 'ᏉᏅᎯ', 'ᏔᎵᏁ', 'ᏦᎢᏁ',
    -    'ᏅᎩᏁ', 'ᏧᎾᎩ', 'ᏈᏕᎾ'],
    -  NARROWWEEKDAYS: ['Ꮖ', 'Ꮙ', 'Ꮤ', 'Ꮶ', 'Ꮕ', 'Ꮷ', 'Ꭴ'],
    -  STANDALONENARROWWEEKDAYS: ['Ꮖ', 'Ꮙ', 'Ꮤ', 'Ꮶ', 'Ꮕ', 'Ꮷ', 'Ꭴ'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['ᏌᎾᎴ', 'ᏒᎯᏱᎢᏗᏢ'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale cs.
    - */
    -goog.i18n.DateTimeSymbols_cs = {
    -  ERAS: ['př. n. l.', 'n. l.'],
    -  ERANAMES: ['př. n. l.', 'n. l.'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['ledna', 'února', 'března', 'dubna', 'května', 'června',
    -    'července', 'srpna', 'září', 'října', 'listopadu', 'prosince'],
    -  STANDALONEMONTHS: ['leden', 'únor', 'březen', 'duben', 'květen', 'červen',
    -    'červenec', 'srpen', 'září', 'říjen', 'listopad', 'prosinec'],
    -  SHORTMONTHS: ['led', 'úno', 'bře', 'dub', 'kvě', 'čvn', 'čvc', 'srp',
    -    'zář', 'říj', 'lis', 'pro'],
    -  STANDALONESHORTMONTHS: ['led', 'úno', 'bře', 'dub', 'kvě', 'čvn', 'čvc',
    -    'srp', 'zář', 'říj', 'lis', 'pro'],
    -  WEEKDAYS: ['neděle', 'pondělí', 'úterý', 'středa', 'čtvrtek', 'pátek',
    -    'sobota'],
    -  STANDALONEWEEKDAYS: ['neděle', 'pondělí', 'úterý', 'středa', 'čtvrtek',
    -    'pátek', 'sobota'],
    -  SHORTWEEKDAYS: ['ne', 'po', 'út', 'st', 'čt', 'pá', 'so'],
    -  STANDALONESHORTWEEKDAYS: ['ne', 'po', 'út', 'st', 'čt', 'pá', 'so'],
    -  NARROWWEEKDAYS: ['N', 'P', 'Ú', 'S', 'Č', 'P', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['N', 'P', 'Ú', 'S', 'Č', 'P', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1. čtvrtletí', '2. čtvrtletí', '3. čtvrtletí',
    -    '4. čtvrtletí'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d. MMMM y', 'd. MMMM y', 'd. M. y', 'dd.MM.yy'],
    -  TIMEFORMATS: ['H:mm:ss zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale cy.
    - */
    -goog.i18n.DateTimeSymbols_cy = {
    -  ERAS: ['CC', 'OC'],
    -  ERANAMES: ['Cyn Crist', 'Oed Crist'],
    -  NARROWMONTHS: ['I', 'Ch', 'M', 'E', 'M', 'M', 'G', 'A', 'M', 'H', 'T', 'Rh'],
    -  STANDALONENARROWMONTHS: ['I', 'Ch', 'M', 'E', 'M', 'M', 'G', 'A', 'M', 'H',
    -    'T', 'Rh'],
    -  MONTHS: ['Ionawr', 'Chwefror', 'Mawrth', 'Ebrill', 'Mai', 'Mehefin',
    -    'Gorffennaf', 'Awst', 'Medi', 'Hydref', 'Tachwedd', 'Rhagfyr'],
    -  STANDALONEMONTHS: ['Ionawr', 'Chwefror', 'Mawrth', 'Ebrill', 'Mai', 'Mehefin',
    -    'Gorffennaf', 'Awst', 'Medi', 'Hydref', 'Tachwedd', 'Rhagfyr'],
    -  SHORTMONTHS: ['Ion', 'Chwef', 'Mawrth', 'Ebrill', 'Mai', 'Meh', 'Gorff',
    -    'Awst', 'Medi', 'Hyd', 'Tach', 'Rhag'],
    -  STANDALONESHORTMONTHS: ['Ion', 'Chw', 'Maw', 'Ebr', 'Mai', 'Meh', 'Gor',
    -    'Awst', 'Medi', 'Hyd', 'Tach', 'Rhag'],
    -  WEEKDAYS: ['Dydd Sul', 'Dydd Llun', 'Dydd Mawrth', 'Dydd Mercher', 'Dydd Iau',
    -    'Dydd Gwener', 'Dydd Sadwrn'],
    -  STANDALONEWEEKDAYS: ['Dydd Sul', 'Dydd Llun', 'Dydd Mawrth', 'Dydd Mercher',
    -    'Dydd Iau', 'Dydd Gwener', 'Dydd Sadwrn'],
    -  SHORTWEEKDAYS: ['Sul', 'Llun', 'Maw', 'Mer', 'Iau', 'Gwen', 'Sad'],
    -  STANDALONESHORTWEEKDAYS: ['Sul', 'Llun', 'Maw', 'Mer', 'Iau', 'Gwe', 'Sad'],
    -  NARROWWEEKDAYS: ['S', 'Ll', 'M', 'M', 'I', 'G', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'Ll', 'M', 'M', 'I', 'G', 'S'],
    -  SHORTQUARTERS: ['Ch1', 'Ch2', 'Ch3', 'Ch4'],
    -  QUARTERS: ['Chwarter 1af', '2il chwarter', '3ydd chwarter', '4ydd chwarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'am\' {0}', '{1} \'am\' {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale da.
    - */
    -goog.i18n.DateTimeSymbols_da = {
    -  ERAS: ['f.Kr.', 'e.Kr.'],
    -  ERANAMES: ['f.Kr.', 'e.Kr.'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['januar', 'februar', 'marts', 'april', 'maj', 'juni', 'juli',
    -    'august', 'september', 'oktober', 'november', 'december'],
    -  STANDALONEMONTHS: ['januar', 'februar', 'marts', 'april', 'maj', 'juni',
    -    'juli', 'august', 'september', 'oktober', 'november', 'december'],
    -  SHORTMONTHS: ['jan.', 'feb.', 'mar.', 'apr.', 'maj', 'jun.', 'jul.', 'aug.',
    -    'sep.', 'okt.', 'nov.', 'dec.'],
    -  STANDALONESHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul',
    -    'aug', 'sep', 'okt', 'nov', 'dec'],
    -  WEEKDAYS: ['søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag', 'fredag',
    -    'lørdag'],
    -  STANDALONEWEEKDAYS: ['søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag',
    -    'fredag', 'lørdag'],
    -  SHORTWEEKDAYS: ['søn.', 'man.', 'tir.', 'ons.', 'tor.', 'fre.', 'lør.'],
    -  STANDALONESHORTWEEKDAYS: ['søn', 'man', 'tir', 'ons', 'tor', 'fre', 'lør'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'O', 'T', 'F', 'L'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'O', 'T', 'F', 'L'],
    -  SHORTQUARTERS: ['1. kvt.', '2. kvt.', '3. kvt.', '4. kvt.'],
    -  QUARTERS: ['1. kvartal', '2. kvartal', '3. kvartal', '4. kvartal'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE \'den\' d. MMMM y', 'd. MMMM y', 'dd/MM/y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH.mm.ss zzzz', 'HH.mm.ss z', 'HH.mm.ss', 'HH.mm'],
    -  DATETIMEFORMATS: ['{1} \'kl.\' {0}', '{1} \'kl.\' {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale de.
    - */
    -goog.i18n.DateTimeSymbols_de = {
    -  ERAS: ['v. Chr.', 'n. Chr.'],
    -  ERANAMES: ['v. Chr.', 'n. Chr.'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli',
    -    'August', 'September', 'Oktober', 'November', 'Dezember'],
    -  STANDALONEMONTHS: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni',
    -    'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
    -  SHORTMONTHS: ['Jan.', 'Feb.', 'März', 'Apr.', 'Mai', 'Juni', 'Juli', 'Aug.',
    -    'Sep.', 'Okt.', 'Nov.', 'Dez.'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
    -  WEEKDAYS: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag',
    -    'Freitag', 'Samstag'],
    -  STANDALONEWEEKDAYS: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch',
    -    'Donnerstag', 'Freitag', 'Samstag'],
    -  SHORTWEEKDAYS: ['So.', 'Mo.', 'Di.', 'Mi.', 'Do.', 'Fr.', 'Sa.'],
    -  STANDALONESHORTWEEKDAYS: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
    -  NARROWWEEKDAYS: ['S', 'M', 'D', 'M', 'D', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'D', 'M', 'D', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1. Quartal', '2. Quartal', '3. Quartal', '4. Quartal'],
    -  AMPMS: ['vorm.', 'nachm.'],
    -  DATEFORMATS: ['EEEE, d. MMMM y', 'd. MMMM y', 'dd.MM.y', 'dd.MM.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'um\' {0}', '{1} \'um\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale de_AT.
    - */
    -goog.i18n.DateTimeSymbols_de_AT = {
    -  ERAS: ['v. Chr.', 'n. Chr.'],
    -  ERANAMES: ['v. Chr.', 'n. Chr.'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Jänner', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli',
    -    'August', 'September', 'Oktober', 'November', 'Dezember'],
    -  STANDALONEMONTHS: ['Jänner', 'Februar', 'März', 'April', 'Mai', 'Juni',
    -    'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
    -  SHORTMONTHS: ['Jän.', 'Feb.', 'März', 'Apr.', 'Mai', 'Juni', 'Juli', 'Aug.',
    -    'Sep.', 'Okt.', 'Nov.', 'Dez.'],
    -  STANDALONESHORTMONTHS: ['Jän', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
    -  WEEKDAYS: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag',
    -    'Freitag', 'Samstag'],
    -  STANDALONEWEEKDAYS: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch',
    -    'Donnerstag', 'Freitag', 'Samstag'],
    -  SHORTWEEKDAYS: ['So.', 'Mo.', 'Di.', 'Mi.', 'Do.', 'Fr.', 'Sa.'],
    -  STANDALONESHORTWEEKDAYS: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
    -  NARROWWEEKDAYS: ['S', 'M', 'D', 'M', 'D', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'D', 'M', 'D', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1. Quartal', '2. Quartal', '3. Quartal', '4. Quartal'],
    -  AMPMS: ['vorm.', 'nachm.'],
    -  DATEFORMATS: ['EEEE, dd. MMMM y', 'dd. MMMM y', 'dd. MMM y', 'dd.MM.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'um\' {0}', '{1} \'um\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale de_CH.
    - */
    -goog.i18n.DateTimeSymbols_de_CH = goog.i18n.DateTimeSymbols_de;
    -
    -
    -/**
    - * Date/time formatting symbols for locale el.
    - */
    -goog.i18n.DateTimeSymbols_el = {
    -  ERAS: ['π.Χ.', 'μ.Χ.'],
    -  ERANAMES: ['προ Χριστού', 'μετά Χριστόν'],
    -  NARROWMONTHS: ['Ι', 'Φ', 'Μ', 'Α', 'Μ', 'Ι', 'Ι', 'Α', 'Σ', 'Ο',
    -    'Ν', 'Δ'],
    -  STANDALONENARROWMONTHS: ['Ι', 'Φ', 'Μ', 'Α', 'Μ', 'Ι', 'Ι', 'Α', 'Σ',
    -    'Ο', 'Ν', 'Δ'],
    -  MONTHS: ['Ιανουαρίου', 'Φεβρουαρίου', 'Μαρτίου',
    -    'Απριλίου', 'Μαΐου', 'Ιουνίου', 'Ιουλίου',
    -    'Αυγούστου', 'Σεπτεμβρίου', 'Οκτωβρίου',
    -    'Νοεμβρίου', 'Δεκεμβρίου'],
    -  STANDALONEMONTHS: ['Ιανουάριος', 'Φεβρουάριος',
    -    'Μάρτιος', 'Απρίλιος', 'Μάιος', 'Ιούνιος',
    -    'Ιούλιος', 'Αύγουστος', 'Σεπτέμβριος',
    -    'Οκτώβριος', 'Νοέμβριος', 'Δεκέμβριος'],
    -  SHORTMONTHS: ['Ιαν', 'Φεβ', 'Μαρ', 'Απρ', 'Μαΐ', 'Ιουν',
    -    'Ιουλ', 'Αυγ', 'Σεπ', 'Οκτ', 'Νοε', 'Δεκ'],
    -  STANDALONESHORTMONTHS: ['Ιαν', 'Φεβ', 'Μάρ', 'Απρ', 'Μάι',
    -    'Ιούν', 'Ιούλ', 'Αύγ', 'Σεπ', 'Οκτ', 'Νοέ', 'Δεκ'],
    -  WEEKDAYS: ['Κυριακή', 'Δευτέρα', 'Τρίτη', 'Τετάρτη',
    -    'Πέμπτη', 'Παρασκευή', 'Σάββατο'],
    -  STANDALONEWEEKDAYS: ['Κυριακή', 'Δευτέρα', 'Τρίτη',
    -    'Τετάρτη', 'Πέμπτη', 'Παρασκευή', 'Σάββατο'],
    -  SHORTWEEKDAYS: ['Κυρ', 'Δευ', 'Τρί', 'Τετ', 'Πέμ', 'Παρ',
    -    'Σάβ'],
    -  STANDALONESHORTWEEKDAYS: ['Κυρ', 'Δευ', 'Τρί', 'Τετ', 'Πέμ',
    -    'Παρ', 'Σάβ'],
    -  NARROWWEEKDAYS: ['Κ', 'Δ', 'Τ', 'Τ', 'Π', 'Π', 'Σ'],
    -  STANDALONENARROWWEEKDAYS: ['Κ', 'Δ', 'Τ', 'Τ', 'Π', 'Π', 'Σ'],
    -  SHORTQUARTERS: ['Τ1', 'Τ2', 'Τ3', 'Τ4'],
    -  QUARTERS: ['1ο τρίμηνο', '2ο τρίμηνο', '3ο τρίμηνο',
    -    '4ο τρίμηνο'],
    -  AMPMS: ['π.μ.', 'μ.μ.'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} - {0}', '{1} - {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en.
    - */
    -goog.i18n.DateTimeSymbols_en = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_AU.
    - */
    -goog.i18n.DateTimeSymbols_en_AU = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['am', 'pm'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_GB.
    - */
    -goog.i18n.DateTimeSymbols_en_GB = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['am', 'pm'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_IE.
    - */
    -goog.i18n.DateTimeSymbols_en_IE = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['a.m.', 'p.m.'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 2
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_IN.
    - */
    -goog.i18n.DateTimeSymbols_en_IN = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['am', 'pm'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'dd-MMM-y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [6, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_SG.
    - */
    -goog.i18n.DateTimeSymbols_en_SG = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['am', 'pm'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_US.
    - */
    -goog.i18n.DateTimeSymbols_en_US = goog.i18n.DateTimeSymbols_en;
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_ZA.
    - */
    -goog.i18n.DateTimeSymbols_en_ZA = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE dd MMMM y', 'dd MMMM y', 'dd MMM y', 'y/MM/dd'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale es.
    - */
    -goog.i18n.DateTimeSymbols_es = {
    -  ERAS: ['a. C.', 'd. C.'],
    -  ERANAMES: ['antes de Cristo', 'anno Dómini'],
    -  NARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
    -    'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],
    -  STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
    -    'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
    -  SHORTMONTHS: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.',
    -    'sept.', 'oct.', 'nov.', 'dic.'],
    -  STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
    -    'Jul.', 'Ago.', 'Sept.', 'Oct.', 'Nov.', 'Dic.'],
    -  WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
    -    'sábado'],
    -  STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
    -    'Viernes', 'Sábado'],
    -  SHORTWEEKDAYS: ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
    -  STANDALONESHORTWEEKDAYS: ['Dom.', 'Lun.', 'Mar.', 'Mié.', 'Jue.', 'Vie.',
    -    'Sáb.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'X', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'X', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1.er trimestre', '2.º trimestre', '3.er trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['a. m.', 'p. m.'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'd \'de\' MMM \'de\' y', 'd/M/yy'],
    -  TIMEFORMATS: ['H:mm:ss (zzzz)', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale es_419.
    - */
    -goog.i18n.DateTimeSymbols_es_419 = {
    -  ERAS: ['a. C.', 'd. C.'],
    -  ERANAMES: ['antes de Cristo', 'después de Cristo'],
    -  NARROWMONTHS: ['e', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
    -    'agosto', 'setiembre', 'octubre', 'noviembre', 'diciembre'],
    -  STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
    -    'Julio', 'Agosto', 'Setiembre', 'Octubre', 'Noviembre', 'Diciembre'],
    -  SHORTMONTHS: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.',
    -    'set.', 'oct.', 'nov.', 'dic.'],
    -  STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
    -    'Jul.', 'Ago.', 'Set.', 'Oct.', 'Nov.', 'Dic.'],
    -  WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
    -    'sábado'],
    -  STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
    -    'Viernes', 'Sábado'],
    -  SHORTWEEKDAYS: ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
    -  STANDALONESHORTWEEKDAYS: ['Dom.', 'Lun.', 'Mar.', 'Mié.', 'Jue.', 'Vie.',
    -    'Sáb.'],
    -  NARROWWEEKDAYS: ['d', 'l', 'm', 'm', 'j', 'v', 's'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['1.er trim.', '2.º trim.', '3.er trim.', '4.º trim.'],
    -  QUARTERS: ['1.er trimestre', '2.º trimestre', '3.er trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['a. m.', 'p. m.'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'd \'de\' MMM \'de\' y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale es_ES.
    - */
    -goog.i18n.DateTimeSymbols_es_ES = goog.i18n.DateTimeSymbols_es;
    -
    -
    -/**
    - * Date/time formatting symbols for locale et.
    - */
    -goog.i18n.DateTimeSymbols_et = {
    -  ERAS: ['e.m.a.', 'm.a.j.'],
    -  ERANAMES: ['enne meie aega', 'meie aja järgi'],
    -  NARROWMONTHS: ['J', 'V', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'V', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['jaanuar', 'veebruar', 'märts', 'aprill', 'mai', 'juuni', 'juuli',
    -    'august', 'september', 'oktoober', 'november', 'detsember'],
    -  STANDALONEMONTHS: ['jaanuar', 'veebruar', 'märts', 'aprill', 'mai', 'juuni',
    -    'juuli', 'august', 'september', 'oktoober', 'november', 'detsember'],
    -  SHORTMONTHS: ['jaan', 'veebr', 'märts', 'apr', 'mai', 'juuni', 'juuli',
    -    'aug', 'sept', 'okt', 'nov', 'dets'],
    -  STANDALONESHORTMONTHS: ['jaan', 'veebr', 'märts', 'apr', 'mai', 'juuni',
    -    'juuli', 'aug', 'sept', 'okt', 'nov', 'dets'],
    -  WEEKDAYS: ['pühapäev', 'esmaspäev', 'teisipäev', 'kolmapäev',
    -    'neljapäev', 'reede', 'laupäev'],
    -  STANDALONEWEEKDAYS: ['pühapäev', 'esmaspäev', 'teisipäev', 'kolmapäev',
    -    'neljapäev', 'reede', 'laupäev'],
    -  SHORTWEEKDAYS: ['P', 'E', 'T', 'K', 'N', 'R', 'L'],
    -  STANDALONESHORTWEEKDAYS: ['P', 'E', 'T', 'K', 'N', 'R', 'L'],
    -  NARROWWEEKDAYS: ['P', 'E', 'T', 'K', 'N', 'R', 'L'],
    -  STANDALONENARROWWEEKDAYS: ['P', 'E', 'T', 'K', 'N', 'R', 'L'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['1. kvartal', '2. kvartal', '3. kvartal', '4. kvartal'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d. MMMM y', 'd. MMMM y', 'd. MMM y', 'dd.MM.yy'],
    -  TIMEFORMATS: ['H:mm.ss zzzz', 'H:mm.ss z', 'H:mm.ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale eu.
    - */
    -goog.i18n.DateTimeSymbols_eu = {
    -  ERAS: ['K.a.', 'K.o.'],
    -  ERANAMES: ['K.a.', 'K.o.'],
    -  NARROWMONTHS: ['U', 'O', 'M', 'A', 'M', 'E', 'U', 'A', 'I', 'U', 'A', 'A'],
    -  STANDALONENARROWMONTHS: ['U', 'O', 'M', 'A', 'M', 'E', 'U', 'A', 'I', 'U',
    -    'A', 'A'],
    -  MONTHS: ['urtarrilak', 'otsailak', 'martxoak', 'apirilak', 'maiatzak',
    -    'ekainak', 'uztailak', 'abuztuak', 'irailak', 'urriak', 'azaroak',
    -    'abenduak'],
    -  STANDALONEMONTHS: ['Urtarrila', 'Otsaila', 'Martxoa', 'Apirila', 'Maiatza',
    -    'Ekaina', 'Uztaila', 'Abuztua', 'Iraila', 'Urria', 'Azaroa', 'Abendua'],
    -  SHORTMONTHS: ['urt.', 'ots.', 'mar.', 'api.', 'mai.', 'eka.', 'uzt.', 'abu.',
    -    'ira.', 'urr.', 'aza.', 'abe.'],
    -  STANDALONESHORTMONTHS: ['Urt.', 'Ots.', 'Mar.', 'Api.', 'Mai.', 'Eka.',
    -    'Uzt.', 'Abu.', 'Ira.', 'Urr.', 'Aza.', 'Abe.'],
    -  WEEKDAYS: ['igandea', 'astelehena', 'asteartea', 'asteazkena', 'osteguna',
    -    'ostirala', 'larunbata'],
    -  STANDALONEWEEKDAYS: ['Igandea', 'Astelehena', 'Asteartea', 'Asteazkena',
    -    'Osteguna', 'Ostirala', 'Larunbata'],
    -  SHORTWEEKDAYS: ['ig.', 'al.', 'ar.', 'az.', 'og.', 'or.', 'lr.'],
    -  STANDALONESHORTWEEKDAYS: ['Ig.', 'Al.', 'Ar.', 'Az.', 'Og.', 'Or.', 'Lr.'],
    -  NARROWWEEKDAYS: ['I', 'A', 'A', 'A', 'O', 'O', 'L'],
    -  STANDALONENARROWWEEKDAYS: ['I', 'A', 'A', 'A', 'O', 'O', 'L'],
    -  SHORTQUARTERS: ['1Hh', '2Hh', '3Hh', '4Hh'],
    -  QUARTERS: ['1. hiruhilekoa', '2. hiruhilekoa', '3. hiruhilekoa',
    -    '4. hiruhilekoa'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['y(\'e\')\'ko\' MMMM d, EEEE', 'y(\'e\')\'ko\' MMMM d',
    -    'y MMM d', 'y/MM/dd'],
    -  TIMEFORMATS: ['HH:mm:ss (zzzz)', 'HH:mm:ss (z)', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fa.
    - */
    -goog.i18n.DateTimeSymbols_fa = {
    -  ZERODIGIT: 0x06F0,
    -  ERAS: ['ق.م.', 'م.'],
    -  ERANAMES: ['قبل از میلاد', 'میلادی'],
    -  NARROWMONTHS: ['ژ', 'ف', 'م', 'آ', 'م', 'ژ', 'ژ', 'ا', 'س', 'ا',
    -    'ن', 'د'],
    -  STANDALONENARROWMONTHS: ['ژ', 'ف', 'م', 'آ', 'م', 'ژ', 'ژ', 'ا', 'س',
    -    'ا', 'ن', 'د'],
    -  MONTHS: ['ژانویهٔ', 'فوریهٔ', 'مارس', 'آوریل', 'مهٔ',
    -    'ژوئن', 'ژوئیهٔ', 'اوت', 'سپتامبر', 'اکتبر',
    -    'نوامبر', 'دسامبر'],
    -  STANDALONEMONTHS: ['ژانویه', 'فوریه', 'مارس', 'آوریل',
    -    'مه', 'ژوئن', 'ژوئیه', 'اوت', 'سپتامبر', 'اکتبر',
    -    'نوامبر', 'دسامبر'],
    -  SHORTMONTHS: ['ژانویهٔ', 'فوریهٔ', 'مارس', 'آوریل',
    -    'مهٔ', 'ژوئن', 'ژوئیهٔ', 'اوت', 'سپتامبر',
    -    'اکتبر', 'نوامبر', 'دسامبر'],
    -  STANDALONESHORTMONTHS: ['ژانویه', 'فوریه', 'مارس',
    -    'آوریل', 'مه', 'ژوئن', 'ژوئیه', 'اوت', 'سپتامبر',
    -    'اکتبر', 'نوامبر', 'دسامبر'],
    -  WEEKDAYS: ['یکشنبه', 'دوشنبه', 'سه‌شنبه',
    -    'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'],
    -  STANDALONEWEEKDAYS: ['یکشنبه', 'دوشنبه', 'سه‌شنبه',
    -    'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'],
    -  SHORTWEEKDAYS: ['یکشنبه', 'دوشنبه', 'سه‌شنبه',
    -    'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'],
    -  STANDALONESHORTWEEKDAYS: ['یکشنبه', 'دوشنبه', 'سه‌شنبه',
    -    'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'],
    -  NARROWWEEKDAYS: ['ی', 'د', 'س', 'چ', 'پ', 'ج', 'ش'],
    -  STANDALONENARROWWEEKDAYS: ['ی', 'د', 'س', 'چ', 'پ', 'ج', 'ش'],
    -  SHORTQUARTERS: ['س‌م۱', 'س‌م۲', 'س‌م۳', 'س‌م۴'],
    -  QUARTERS: ['سه‌ماههٔ اول', 'سه‌ماههٔ دوم',
    -    'سه‌ماههٔ سوم', 'سه‌ماههٔ چهارم'],
    -  AMPMS: ['قبل‌ازظهر', 'بعدازظهر'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'y/M/d'],
    -  TIMEFORMATS: ['H:mm:ss (zzzz)', 'H:mm:ss (z)', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1}، ساعت {0}', '{1}، ساعت {0}', '{1}،‏ {0}',
    -    '{1}،‏ {0}'],
    -  FIRSTDAYOFWEEK: 5,
    -  WEEKENDRANGE: [4, 4],
    -  FIRSTWEEKCUTOFFDAY: 4
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fi.
    - */
    -goog.i18n.DateTimeSymbols_fi = {
    -  ERAS: ['eKr.', 'jKr.'],
    -  ERANAMES: ['ennen Kristuksen syntymää', 'jälkeen Kristuksen syntymän'],
    -  NARROWMONTHS: ['T', 'H', 'M', 'H', 'T', 'K', 'H', 'E', 'S', 'L', 'M', 'J'],
    -  STANDALONENARROWMONTHS: ['T', 'H', 'M', 'H', 'T', 'K', 'H', 'E', 'S', 'L',
    -    'M', 'J'],
    -  MONTHS: ['tammikuuta', 'helmikuuta', 'maaliskuuta', 'huhtikuuta',
    -    'toukokuuta', 'kesäkuuta', 'heinäkuuta', 'elokuuta', 'syyskuuta',
    -    'lokakuuta', 'marraskuuta', 'joulukuuta'],
    -  STANDALONEMONTHS: ['tammikuu', 'helmikuu', 'maaliskuu', 'huhtikuu',
    -    'toukokuu', 'kesäkuu', 'heinäkuu', 'elokuu', 'syyskuu', 'lokakuu',
    -    'marraskuu', 'joulukuu'],
    -  SHORTMONTHS: ['tammikuuta', 'helmikuuta', 'maaliskuuta', 'huhtikuuta',
    -    'toukokuuta', 'kesäkuuta', 'heinäkuuta', 'elokuuta', 'syyskuuta',
    -    'lokakuuta', 'marraskuuta', 'joulukuuta'],
    -  STANDALONESHORTMONTHS: ['tammi', 'helmi', 'maalis', 'huhti', 'touko', 'kesä',
    -    'heinä', 'elo', 'syys', 'loka', 'marras', 'joulu'],
    -  WEEKDAYS: ['sunnuntaina', 'maanantaina', 'tiistaina', 'keskiviikkona',
    -    'torstaina', 'perjantaina', 'lauantaina'],
    -  STANDALONEWEEKDAYS: ['sunnuntai', 'maanantai', 'tiistai', 'keskiviikko',
    -    'torstai', 'perjantai', 'lauantai'],
    -  SHORTWEEKDAYS: ['su', 'ma', 'ti', 'ke', 'to', 'pe', 'la'],
    -  STANDALONESHORTWEEKDAYS: ['su', 'ma', 'ti', 'ke', 'to', 'pe', 'la'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'K', 'T', 'P', 'L'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'K', 'T', 'P', 'L'],
    -  SHORTQUARTERS: ['1. nelj.', '2. nelj.', '3. nelj.', '4. nelj.'],
    -  QUARTERS: ['1. neljännes', '2. neljännes', '3. neljännes',
    -    '4. neljännes'],
    -  AMPMS: ['ap.', 'ip.'],
    -  DATEFORMATS: ['cccc d. MMMM y', 'd. MMMM y', 'd.M.y', 'd.M.y'],
    -  TIMEFORMATS: ['H.mm.ss zzzz', 'H.mm.ss z', 'H.mm.ss', 'H.mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fil.
    - */
    -goog.i18n.DateTimeSymbols_fil = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['BC', 'AD'],
    -  NARROWMONTHS: ['E', 'P', 'M', 'A', 'M', 'H', 'H', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['E', 'P', 'M', 'A', 'M', 'H', 'H', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Enero', 'Pebrero', 'Marso', 'Abril', 'Mayo', 'Hunyo', 'Hulyo',
    -    'Agosto', 'Setyembre', 'Oktubre', 'Nobyembre', 'Disyembre'],
    -  STANDALONEMONTHS: ['Enero', 'Pebrero', 'Marso', 'Abril', 'Mayo', 'Hunyo',
    -    'Hulyo', 'Agosto', 'Setyembre', 'Oktubre', 'Nobyembre', 'Disyembre'],
    -  SHORTMONTHS: ['Ene', 'Peb', 'Mar', 'Abr', 'May', 'Hun', 'Hul', 'Ago', 'Set',
    -    'Okt', 'Nob', 'Dis'],
    -  STANDALONESHORTMONTHS: ['Ene', 'Peb', 'Mar', 'Abr', 'May', 'Hun', 'Hul',
    -    'Ago', 'Set', 'Okt', 'Nob', 'Dis'],
    -  WEEKDAYS: ['Linggo', 'Lunes', 'Martes', 'Miyerkules', 'Huwebes', 'Biyernes',
    -    'Sabado'],
    -  STANDALONEWEEKDAYS: ['Linggo', 'Lunes', 'Martes', 'Miyerkules', 'Huwebes',
    -    'Biyernes', 'Sabado'],
    -  SHORTWEEKDAYS: ['Lin', 'Lun', 'Mar', 'Miy', 'Huw', 'Biy', 'Sab'],
    -  STANDALONESHORTWEEKDAYS: ['Lin', 'Lun', 'Mar', 'Miy', 'Huw', 'Biy', 'Sab'],
    -  NARROWWEEKDAYS: ['L', 'L', 'M', 'M', 'H', 'B', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['L', 'L', 'M', 'M', 'H', 'B', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['ika-1 quarter', 'ika-2 quarter', 'ika-3 quarter',
    -    'ika-4 na quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'nang\' {0}', '{1} \'nang\' {0}', '{1}, {0}',
    -    '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr.
    - */
    -goog.i18n.DateTimeSymbols_fr = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_CA.
    - */
    -goog.i18n.DateTimeSymbols_fr_CA = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin',
    -    'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin',
    -    'juil.', 'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi',
    -    'vendredi', 'samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.',
    -    'sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'y-MM-dd', 'yy-MM-dd'],
    -  TIMEFORMATS: ['HH \'h\' mm \'min\' ss \'s\' zzzz', 'HH:mm:ss z', 'HH:mm:ss',
    -    'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'à\' {0}', '{1} \'à\' {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ga.
    - */
    -goog.i18n.DateTimeSymbols_ga = {
    -  ERAS: ['RC', 'AD'],
    -  ERANAMES: ['Roimh Chríost', 'Anno Domini'],
    -  NARROWMONTHS: ['E', 'F', 'M', 'A', 'B', 'M', 'I', 'L', 'M', 'D', 'S', 'N'],
    -  STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'B', 'M', 'I', 'L', 'M', 'D',
    -    'S', 'N'],
    -  MONTHS: ['Eanáir', 'Feabhra', 'Márta', 'Aibreán', 'Bealtaine', 'Meitheamh',
    -    'Iúil', 'Lúnasa', 'Meán Fómhair', 'Deireadh Fómhair', 'Samhain',
    -    'Nollaig'],
    -  STANDALONEMONTHS: ['Eanáir', 'Feabhra', 'Márta', 'Aibreán', 'Bealtaine',
    -    'Meitheamh', 'Iúil', 'Lúnasa', 'Meán Fómhair', 'Deireadh Fómhair',
    -    'Samhain', 'Nollaig'],
    -  SHORTMONTHS: ['Ean', 'Feabh', 'Márta', 'Aib', 'Beal', 'Meith', 'Iúil',
    -    'Lún', 'MFómh', 'DFómh', 'Samh', 'Noll'],
    -  STANDALONESHORTMONTHS: ['Ean', 'Feabh', 'Márta', 'Aib', 'Beal', 'Meith',
    -    'Iúil', 'Lún', 'MFómh', 'DFómh', 'Samh', 'Noll'],
    -  WEEKDAYS: ['Dé Domhnaigh', 'Dé Luain', 'Dé Máirt', 'Dé Céadaoin',
    -    'Déardaoin', 'Dé hAoine', 'Dé Sathairn'],
    -  STANDALONEWEEKDAYS: ['Dé Domhnaigh', 'Dé Luain', 'Dé Máirt',
    -    'Dé Céadaoin', 'Déardaoin', 'Dé hAoine', 'Dé Sathairn'],
    -  SHORTWEEKDAYS: ['Domh', 'Luan', 'Máirt', 'Céad', 'Déar', 'Aoine', 'Sath'],
    -  STANDALONESHORTWEEKDAYS: ['Domh', 'Luan', 'Máirt', 'Céad', 'Déar', 'Aoine',
    -    'Sath'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'C', 'D', 'A', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'C', 'D', 'A', 'S'],
    -  SHORTQUARTERS: ['R1', 'R2', 'R3', 'R4'],
    -  QUARTERS: ['1ú ráithe', '2ú ráithe', '3ú ráithe', '4ú ráithe'],
    -  AMPMS: ['a.m.', 'p.m.'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 2
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale gl.
    - */
    -goog.i18n.DateTimeSymbols_gl = {
    -  ERAS: ['a.C.', 'd.C.'],
    -  ERANAMES: ['antes de Cristo', 'despois de Cristo'],
    -  NARROWMONTHS: ['X', 'F', 'M', 'A', 'M', 'X', 'X', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['X', 'F', 'M', 'A', 'M', 'X', 'X', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['xaneiro', 'febreiro', 'marzo', 'abril', 'maio', 'xuño', 'xullo',
    -    'agosto', 'setembro', 'outubro', 'novembro', 'decembro'],
    -  STANDALONEMONTHS: ['Xaneiro', 'Febreiro', 'Marzo', 'Abril', 'Maio', 'Xuño',
    -    'Xullo', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Decembro'],
    -  SHORTMONTHS: ['xan', 'feb', 'mar', 'abr', 'mai', 'xuñ', 'xul', 'ago', 'set',
    -    'out', 'nov', 'dec'],
    -  STANDALONESHORTMONTHS: ['Xan', 'Feb', 'Mar', 'Abr', 'Mai', 'Xuñ', 'Xul',
    -    'Ago', 'Set', 'Out', 'Nov', 'Dec'],
    -  WEEKDAYS: ['domingo', 'luns', 'martes', 'mércores', 'xoves', 'venres',
    -    'sábado'],
    -  STANDALONEWEEKDAYS: ['Domingo', 'Luns', 'Martes', 'Mércores', 'Xoves',
    -    'Venres', 'Sábado'],
    -  SHORTWEEKDAYS: ['dom', 'lun', 'mar', 'mér', 'xov', 'ven', 'sáb'],
    -  STANDALONESHORTWEEKDAYS: ['Dom', 'Lun', 'Mar', 'Mér', 'Xov', 'Ven', 'Sáb'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'X', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'X', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1o trimestre', '2o trimestre', '3o trimestre', '4o trimestre'],
    -  AMPMS: ['a.m.', 'p.m.'],
    -  DATEFORMATS: ['EEEE dd MMMM y', 'dd MMMM y', 'd MMM, y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale gsw.
    - */
    -goog.i18n.DateTimeSymbols_gsw = {
    -  ERAS: ['v. Chr.', 'n. Chr.'],
    -  ERANAMES: ['v. Chr.', 'n. Chr.'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli',
    -    'Auguscht', 'Septämber', 'Oktoober', 'Novämber', 'Dezämber'],
    -  STANDALONEMONTHS: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni',
    -    'Juli', 'Auguscht', 'Septämber', 'Oktoober', 'Novämber', 'Dezämber'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Okt', 'Nov', 'Dez'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
    -  WEEKDAYS: ['Sunntig', 'Määntig', 'Ziischtig', 'Mittwuch', 'Dunschtig',
    -    'Friitig', 'Samschtig'],
    -  STANDALONEWEEKDAYS: ['Sunntig', 'Määntig', 'Ziischtig', 'Mittwuch',
    -    'Dunschtig', 'Friitig', 'Samschtig'],
    -  SHORTWEEKDAYS: ['Su.', 'Mä.', 'Zi.', 'Mi.', 'Du.', 'Fr.', 'Sa.'],
    -  STANDALONESHORTWEEKDAYS: ['Su.', 'Mä.', 'Zi.', 'Mi.', 'Du.', 'Fr.', 'Sa.'],
    -  NARROWWEEKDAYS: ['S', 'M', 'D', 'M', 'D', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'D', 'M', 'D', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1. Quartal', '2. Quartal', '3. Quartal', '4. Quartal'],
    -  AMPMS: ['vorm.', 'nam.'],
    -  DATEFORMATS: ['EEEE, d. MMMM y', 'd. MMMM y', 'dd.MM.y', 'dd.MM.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale gu.
    - */
    -goog.i18n.DateTimeSymbols_gu = {
    -  ERAS: ['ઈસુના જન્મ પહેલા', 'ઇસવીસન'],
    -  ERANAMES: ['ઈસવીસન પૂર્વે', 'ઇસવીસન'],
    -  NARROWMONTHS: ['જા', 'ફે', 'મા', 'એ', 'મે', 'જૂ',
    -    'જુ', 'ઑ', 'સ', 'ઑ', 'ન', 'ડિ'],
    -  STANDALONENARROWMONTHS: ['જા', 'ફે', 'મા', 'એ', 'મે',
    -    'જૂ', 'જુ', 'ઑ', 'સ', 'ઑ', 'ન', 'ડિ'],
    -  MONTHS: ['જાન્યુઆરી', 'ફેબ્રુઆરી',
    -    'માર્ચ', 'એપ્રિલ', 'મે', 'જૂન',
    -    'જુલાઈ', 'ઑગસ્ટ', 'સપ્ટેમ્બર',
    -    'ઑક્ટોબર', 'નવેમ્બર',
    -    'ડિસેમ્બર'],
    -  STANDALONEMONTHS: ['જાન્યુઆરી',
    -    'ફેબ્રુઆરી', 'માર્ચ', 'એપ્રિલ',
    -    'મે', 'જૂન', 'જુલાઈ', 'ઑગસ્ટ',
    -    'સપ્ટેમ્બર', 'ઑક્ટોબર',
    -    'નવેમ્બર', 'ડિસેમ્બર'],
    -  SHORTMONTHS: ['જાન્યુ', 'ફેબ્રુ', 'માર્ચ',
    -    'એપ્રિલ', 'મે', 'જૂન', 'જુલાઈ', 'ઑગ',
    -    'સપ્ટે', 'ઑક્ટો', 'નવે', 'ડિસે'],
    -  STANDALONESHORTMONTHS: ['જાન્યુ', 'ફેબ્રુ',
    -    'માર્ચ', 'એપ્રિલ', 'મે', 'જૂન',
    -    'જુલાઈ', 'ઑગસ્ટ', 'સપ્ટે', 'ઑક્ટો',
    -    'નવે', 'ડિસે'],
    -  WEEKDAYS: ['રવિવાર', 'સોમવાર',
    -    'મંગળવાર', 'બુધવાર', 'ગુરુવાર',
    -    'શુક્રવાર', 'શનિવાર'],
    -  STANDALONEWEEKDAYS: ['રવિવાર', 'સોમવાર',
    -    'મંગળવાર', 'બુધવાર', 'ગુરુવાર',
    -    'શુક્રવાર', 'શનિવાર'],
    -  SHORTWEEKDAYS: ['રવિ', 'સોમ', 'મંગળ', 'બુધ',
    -    'ગુરુ', 'શુક્ર', 'શનિ'],
    -  STANDALONESHORTWEEKDAYS: ['રવિ', 'સોમ', 'મંગળ',
    -    'બુધ', 'ગુરુ', 'શુક્ર', 'શનિ'],
    -  NARROWWEEKDAYS: ['ર', 'સો', 'મં', 'બુ', 'ગુ', 'શુ',
    -    'શ'],
    -  STANDALONENARROWWEEKDAYS: ['ર', 'સો', 'મં', 'બુ', 'ગુ',
    -    'શુ', 'શ'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['પહેલો ત્રિમાસ',
    -    'બીજો ત્રિમાસ',
    -    'ત્રીજો ત્રિમાસ',
    -    'ચોથો ત્રિમાસ'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM, y', 'd MMMM, y', 'd MMM, y', 'd/M/yy'],
    -  TIMEFORMATS: ['hh:mm:ss a zzzz', 'hh:mm:ss a z', 'hh:mm:ss a', 'hh:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [6, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale haw.
    - */
    -goog.i18n.DateTimeSymbols_haw = {
    -  ERAS: ['BCE', 'CE'],
    -  ERANAMES: ['BCE', 'CE'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['Ianuali', 'Pepeluali', 'Malaki', 'ʻApelila', 'Mei', 'Iune',
    -    'Iulai', 'ʻAukake', 'Kepakemapa', 'ʻOkakopa', 'Nowemapa', 'Kekemapa'],
    -  STANDALONEMONTHS: ['Ianuali', 'Pepeluali', 'Malaki', 'ʻApelila', 'Mei',
    -    'Iune', 'Iulai', 'ʻAukake', 'Kepakemapa', 'ʻOkakopa', 'Nowemapa',
    -    'Kekemapa'],
    -  SHORTMONTHS: ['Ian.', 'Pep.', 'Mal.', 'ʻAp.', 'Mei', 'Iun.', 'Iul.', 'ʻAu.',
    -    'Kep.', 'ʻOk.', 'Now.', 'Kek.'],
    -  STANDALONESHORTMONTHS: ['Ian.', 'Pep.', 'Mal.', 'ʻAp.', 'Mei', 'Iun.',
    -    'Iul.', 'ʻAu.', 'Kep.', 'ʻOk.', 'Now.', 'Kek.'],
    -  WEEKDAYS: ['Lāpule', 'Poʻakahi', 'Poʻalua', 'Poʻakolu', 'Poʻahā',
    -    'Poʻalima', 'Poʻaono'],
    -  STANDALONEWEEKDAYS: ['Lāpule', 'Poʻakahi', 'Poʻalua', 'Poʻakolu',
    -    'Poʻahā', 'Poʻalima', 'Poʻaono'],
    -  SHORTWEEKDAYS: ['LP', 'P1', 'P2', 'P3', 'P4', 'P5', 'P6'],
    -  STANDALONESHORTWEEKDAYS: ['LP', 'P1', 'P2', 'P3', 'P4', 'P5', 'P6'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale he.
    - */
    -goog.i18n.DateTimeSymbols_he = {
    -  ERAS: ['לפנה״ס', 'לספירה'],
    -  ERANAMES: ['לפני הספירה', 'לספירה'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['ינואר', 'פברואר', 'מרץ', 'אפריל', 'מאי',
    -    'יוני', 'יולי', 'אוגוסט', 'ספטמבר', 'אוקטובר',
    -    'נובמבר', 'דצמבר'],
    -  STANDALONEMONTHS: ['ינואר', 'פברואר', 'מרץ', 'אפריל',
    -    'מאי', 'יוני', 'יולי', 'אוגוסט', 'ספטמבר',
    -    'אוקטובר', 'נובמבר', 'דצמבר'],
    -  SHORTMONTHS: ['ינו׳', 'פבר׳', 'מרץ', 'אפר׳', 'מאי',
    -    'יוני', 'יולי', 'אוג׳', 'ספט׳', 'אוק׳', 'נוב׳',
    -    'דצמ׳'],
    -  STANDALONESHORTMONTHS: ['ינו׳', 'פבר׳', 'מרץ', 'אפר׳',
    -    'מאי', 'יוני', 'יולי', 'אוג׳', 'ספט׳', 'אוק׳',
    -    'נוב׳', 'דצמ׳'],
    -  WEEKDAYS: ['יום ראשון', 'יום שני', 'יום שלישי',
    -    'יום רביעי', 'יום חמישי', 'יום שישי',
    -    'יום שבת'],
    -  STANDALONEWEEKDAYS: ['יום ראשון', 'יום שני',
    -    'יום שלישי', 'יום רביעי', 'יום חמישי',
    -    'יום שישי', 'יום שבת'],
    -  SHORTWEEKDAYS: ['יום א׳', 'יום ב׳', 'יום ג׳', 'יום ד׳',
    -    'יום ה׳', 'יום ו׳', 'שבת'],
    -  STANDALONESHORTWEEKDAYS: ['יום א׳', 'יום ב׳', 'יום ג׳',
    -    'יום ד׳', 'יום ה׳', 'יום ו׳', 'שבת'],
    -  NARROWWEEKDAYS: ['א׳', 'ב׳', 'ג׳', 'ד׳', 'ה׳', 'ו׳', 'ש׳'],
    -  STANDALONENARROWWEEKDAYS: ['א׳', 'ב׳', 'ג׳', 'ד׳', 'ה׳', 'ו׳',
    -    'ש׳'],
    -  SHORTQUARTERS: ['רבעון 1', 'רבעון 2', 'רבעון 3',
    -    'רבעון 4'],
    -  QUARTERS: ['רבעון 1', 'רבעון 2', 'רבעון 3', 'רבעון 4'],
    -  AMPMS: ['לפנה״צ', 'אחה״צ'],
    -  DATEFORMATS: ['EEEE, d בMMMM y', 'd בMMMM y', 'd בMMM y', 'd.M.y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} בשעה {0}', '{1} בשעה {0}', '{1}, {0}',
    -    '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [4, 5],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale hi.
    - */
    -goog.i18n.DateTimeSymbols_hi = {
    -  ERAS: ['ईसा-पूर्व', 'ईस्वी'],
    -  ERANAMES: ['ईसा-पूर्व', 'ईसवी सन'],
    -  NARROWMONTHS: ['ज', 'फ़', 'मा', 'अ', 'म', 'जू', 'जु',
    -    'अ', 'सि', 'अ', 'न', 'दि'],
    -  STANDALONENARROWMONTHS: ['ज', 'फ़', 'मा', 'अ', 'म', 'जू',
    -    'जु', 'अ', 'सि', 'अ', 'न', 'दि'],
    -  MONTHS: ['जनवरी', 'फ़रवरी', 'मार्च',
    -    'अप्रैल', 'मई', 'जून', 'जुलाई',
    -    'अगस्त', 'सितंबर', 'अक्तूबर',
    -    'नवंबर', 'दिसंबर'],
    -  STANDALONEMONTHS: ['जनवरी', 'फ़रवरी', 'मार्च',
    -    'अप्रैल', 'मई', 'जून', 'जुलाई',
    -    'अगस्त', 'सितंबर', 'अक्तूबर',
    -    'नवंबर', 'दिसंबर'],
    -  SHORTMONTHS: ['जन॰', 'फ़र॰', 'मार्च',
    -    'अप्रैल', 'मई', 'जून', 'जुल॰', 'अग॰',
    -    'सित॰', 'अक्तू॰', 'नव॰', 'दिस॰'],
    -  STANDALONESHORTMONTHS: ['जन॰', 'फ़र॰', 'मार्च',
    -    'अप्रैल', 'मई', 'जून', 'जुल॰', 'अग॰',
    -    'सित॰', 'अक्तू॰', 'नव॰', 'दिस॰'],
    -  WEEKDAYS: ['रविवार', 'सोमवार',
    -    'मंगलवार', 'बुधवार', 'गुरुवार',
    -    'शुक्रवार', 'शनिवार'],
    -  STANDALONEWEEKDAYS: ['रविवार', 'सोमवार',
    -    'मंगलवार', 'बुधवार', 'गुरुवार',
    -    'शुक्रवार', 'शनिवार'],
    -  SHORTWEEKDAYS: ['रवि', 'सोम', 'मंगल', 'बुध',
    -    'गुरु', 'शुक्र', 'शनि'],
    -  STANDALONESHORTWEEKDAYS: ['रवि', 'सोम', 'मंगल',
    -    'बुध', 'गुरु', 'शुक्र', 'शनि'],
    -  NARROWWEEKDAYS: ['र', 'सो', 'मं', 'बु', 'गु', 'शु',
    -    'श'],
    -  STANDALONENARROWWEEKDAYS: ['र', 'सो', 'मं', 'बु', 'गु',
    -    'शु', 'श'],
    -  SHORTQUARTERS: ['ति1', 'ति2', 'ति3', 'ति4'],
    -  QUARTERS: ['पहली तिमाही',
    -    'दूसरी तिमाही', 'तीसरी तिमाही',
    -    'चौथी तिमाही'],
    -  AMPMS: ['am', 'pm'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'dd/MM/y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} को {0}', '{1} को {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [6, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale hr.
    - */
    -goog.i18n.DateTimeSymbols_hr = {
    -  ERAS: ['pr. Kr.', 'p. Kr.'],
    -  ERANAMES: ['Prije Krista', 'Poslije Krista'],
    -  NARROWMONTHS: ['1.', '2.', '3.', '4.', '5.', '6.', '7.', '8.', '9.', '10.',
    -    '11.', '12.'],
    -  STANDALONENARROWMONTHS: ['1.', '2.', '3.', '4.', '5.', '6.', '7.', '8.', '9.',
    -    '10.', '11.', '12.'],
    -  MONTHS: ['siječnja', 'veljače', 'ožujka', 'travnja', 'svibnja', 'lipnja',
    -    'srpnja', 'kolovoza', 'rujna', 'listopada', 'studenoga', 'prosinca'],
    -  STANDALONEMONTHS: ['siječanj', 'veljača', 'ožujak', 'travanj', 'svibanj',
    -    'lipanj', 'srpanj', 'kolovoz', 'rujan', 'listopad', 'studeni', 'prosinac'],
    -  SHORTMONTHS: ['sij', 'velj', 'ožu', 'tra', 'svi', 'lip', 'srp', 'kol', 'ruj',
    -    'lis', 'stu', 'pro'],
    -  STANDALONESHORTMONTHS: ['sij', 'velj', 'ožu', 'tra', 'svi', 'lip', 'srp',
    -    'kol', 'ruj', 'lis', 'stu', 'pro'],
    -  WEEKDAYS: ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda', 'četvrtak',
    -    'petak', 'subota'],
    -  STANDALONEWEEKDAYS: ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda',
    -    'četvrtak', 'petak', 'subota'],
    -  SHORTWEEKDAYS: ['ned', 'pon', 'uto', 'sri', 'čet', 'pet', 'sub'],
    -  STANDALONESHORTWEEKDAYS: ['ned', 'pon', 'uto', 'sri', 'čet', 'pet', 'sub'],
    -  NARROWWEEKDAYS: ['N', 'P', 'U', 'S', 'Č', 'P', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['n', 'p', 'u', 's', 'č', 'p', 's'],
    -  SHORTQUARTERS: ['1kv', '2kv', '3kv', '4kv'],
    -  QUARTERS: ['1. kvartal', '2. kvartal', '3. kvartal', '4. kvartal'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d. MMMM y.', 'd. MMMM y.', 'd. MMM y.', 'dd.MM.y.'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'u\' {0}', '{1} \'u\' {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale hu.
    - */
    -goog.i18n.DateTimeSymbols_hu = {
    -  ERAS: ['i. e.', 'i. sz.'],
    -  ERANAMES: ['időszámításunk előtt', 'időszámításunk szerint'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'Á', 'M', 'J', 'J', 'A', 'Sz', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'Á', 'M', 'J', 'J', 'A', 'Sz', 'O',
    -    'N', 'D'],
    -  MONTHS: ['január', 'február', 'március', 'április', 'május', 'június',
    -    'július', 'augusztus', 'szeptember', 'október', 'november', 'december'],
    -  STANDALONEMONTHS: ['január', 'február', 'március', 'április', 'május',
    -    'június', 'július', 'augusztus', 'szeptember', 'október', 'november',
    -    'december'],
    -  SHORTMONTHS: ['jan.', 'febr.', 'márc.', 'ápr.', 'máj.', 'jún.', 'júl.',
    -    'aug.', 'szept.', 'okt.', 'nov.', 'dec.'],
    -  STANDALONESHORTMONTHS: ['jan.', 'febr.', 'márc.', 'ápr.', 'máj.', 'jún.',
    -    'júl.', 'aug.', 'szept.', 'okt.', 'nov.', 'dec.'],
    -  WEEKDAYS: ['vasárnap', 'hétfő', 'kedd', 'szerda', 'csütörtök',
    -    'péntek', 'szombat'],
    -  STANDALONEWEEKDAYS: ['vasárnap', 'hétfő', 'kedd', 'szerda', 'csütörtök',
    -    'péntek', 'szombat'],
    -  SHORTWEEKDAYS: ['V', 'H', 'K', 'Sze', 'Cs', 'P', 'Szo'],
    -  STANDALONESHORTWEEKDAYS: ['V', 'H', 'K', 'Sze', 'Cs', 'P', 'Szo'],
    -  NARROWWEEKDAYS: ['V', 'H', 'K', 'Sz', 'Cs', 'P', 'Sz'],
    -  STANDALONENARROWWEEKDAYS: ['V', 'H', 'K', 'Sz', 'Cs', 'P', 'Sz'],
    -  SHORTQUARTERS: ['N1', 'N2', 'N3', 'N4'],
    -  QUARTERS: ['I. negyedév', 'II. negyedév', 'III. negyedév',
    -    'IV. negyedév'],
    -  AMPMS: ['de.', 'du.'],
    -  DATEFORMATS: ['y. MMMM d., EEEE', 'y. MMMM d.', 'y. MMM d.', 'y. MM. dd.'],
    -  TIMEFORMATS: ['H:mm:ss zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale hy.
    - */
    -goog.i18n.DateTimeSymbols_hy = {
    -  ERAS: ['մ.թ.ա.', 'մ.թ.'],
    -  ERANAMES: ['մ.թ.ա.', 'մ.թ.'],
    -  NARROWMONTHS: ['Հ', 'Փ', 'Մ', 'Ա', 'Մ', 'Հ', 'Հ', 'Օ', 'Ս', 'Հ',
    -    'Ն', 'Դ'],
    -  STANDALONENARROWMONTHS: ['Հ', 'Փ', 'Մ', 'Ա', 'Մ', 'Հ', 'Հ', 'Օ', 'Ս',
    -    'Հ', 'Ն', 'Դ'],
    -  MONTHS: ['հունվարի', 'փետրվարի', 'մարտի', 'ապրիլի',
    -    'մայիսի', 'հունիսի', 'հուլիսի', 'օգոստոսի',
    -    'սեպտեմբերի', 'հոկտեմբերի', 'նոյեմբերի',
    -    'դեկտեմբերի'],
    -  STANDALONEMONTHS: ['հունվար', 'փետրվար', 'մարտ',
    -    'ապրիլ', 'մայիս', 'հունիս', 'հուլիս',
    -    'օգոստոս', 'սեպտեմբեր', 'հոկտեմբեր',
    -    'նոյեմբեր', 'դեկտեմբեր'],
    -  SHORTMONTHS: ['հնվ', 'փտվ', 'մրտ', 'ապր', 'մյս', 'հնս',
    -    'հլս', 'օգս', 'սեպ', 'հոկ', 'նոյ', 'դեկ'],
    -  STANDALONESHORTMONTHS: ['հնվ', 'փտվ', 'մրտ', 'ապր', 'մյս',
    -    'հնս', 'հլս', 'օգս', 'սեպ', 'հոկ', 'նոյ', 'դեկ'],
    -  WEEKDAYS: ['կիրակի', 'երկուշաբթի', 'երեքշաբթի',
    -    'չորեքշաբթի', 'հինգշաբթի', 'ուրբաթ', 'շաբաթ'],
    -  STANDALONEWEEKDAYS: ['կիրակի', 'երկուշաբթի',
    -    'երեքշաբթի', 'չորեքշաբթի', 'հինգշաբթի',
    -    'ուրբաթ', 'շաբաթ'],
    -  SHORTWEEKDAYS: ['կիր', 'երկ', 'երք', 'չրք', 'հնգ', 'ուր',
    -    'շբթ'],
    -  STANDALONESHORTWEEKDAYS: ['կիր', 'երկ', 'երք', 'չրք', 'հնգ',
    -    'ուր', 'շբթ'],
    -  NARROWWEEKDAYS: ['Կ', 'Ե', 'Ե', 'Չ', 'Հ', 'Ու', 'Շ'],
    -  STANDALONENARROWWEEKDAYS: ['Կ', 'Ե', 'Ե', 'Չ', 'Հ', 'Ու', 'Շ'],
    -  SHORTQUARTERS: ['1-ին եռմս.', '2-րդ եռմս.', '3-րդ եռմս.',
    -    '4-րդ եռմս.'],
    -  QUARTERS: ['1-ին եռամսյակ', '2-րդ եռամսյակ',
    -    '3-րդ եռամսյակ', '4-րդ եռամսյակ'],
    -  AMPMS: ['կեսօրից առաջ', 'կեսօրից հետո'],
    -  DATEFORMATS: ['yթ. MMMM d, EEEE', 'dd MMMM, yթ.', 'dd MMM, yթ.',
    -    'dd.MM.yy'],
    -  TIMEFORMATS: ['H:mm:ss, zzzz', 'H:mm:ss, z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale id.
    - */
    -goog.i18n.DateTimeSymbols_id = {
    -  ERAS: ['SM', 'M'],
    -  ERANAMES: ['Sebelum Masehi', 'M'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni', 'Juli',
    -    'Agustus', 'September', 'Oktober', 'November', 'Desember'],
    -  STANDALONEMONTHS: ['Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni',
    -    'Juli', 'Agustus', 'September', 'Oktober', 'November', 'Desember'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Agt', 'Sep',
    -    'Okt', 'Nov', 'Des'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul',
    -    'Agt', 'Sep', 'Okt', 'Nov', 'Des'],
    -  WEEKDAYS: ['Minggu', 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu'],
    -  STANDALONEWEEKDAYS: ['Minggu', 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat',
    -    'Sabtu'],
    -  SHORTWEEKDAYS: ['Min', 'Sen', 'Sel', 'Rab', 'Kam', 'Jum', 'Sab'],
    -  STANDALONESHORTWEEKDAYS: ['Min', 'Sen', 'Sel', 'Rab', 'Kam', 'Jum', 'Sab'],
    -  NARROWWEEKDAYS: ['M', 'S', 'S', 'R', 'K', 'J', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['M', 'S', 'S', 'R', 'K', 'J', 'S'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['Kuartal ke-1', 'Kuartal ke-2', 'Kuartal ke-3', 'Kuartal ke-4'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, dd MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH.mm.ss zzzz', 'HH.mm.ss z', 'HH.mm.ss', 'HH.mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale in.
    - */
    -goog.i18n.DateTimeSymbols_in = {
    -  ERAS: ['SM', 'M'],
    -  ERANAMES: ['Sebelum Masehi', 'M'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni', 'Juli',
    -    'Agustus', 'September', 'Oktober', 'November', 'Desember'],
    -  STANDALONEMONTHS: ['Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni',
    -    'Juli', 'Agustus', 'September', 'Oktober', 'November', 'Desember'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Agt', 'Sep',
    -    'Okt', 'Nov', 'Des'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul',
    -    'Agt', 'Sep', 'Okt', 'Nov', 'Des'],
    -  WEEKDAYS: ['Minggu', 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu'],
    -  STANDALONEWEEKDAYS: ['Minggu', 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat',
    -    'Sabtu'],
    -  SHORTWEEKDAYS: ['Min', 'Sen', 'Sel', 'Rab', 'Kam', 'Jum', 'Sab'],
    -  STANDALONESHORTWEEKDAYS: ['Min', 'Sen', 'Sel', 'Rab', 'Kam', 'Jum', 'Sab'],
    -  NARROWWEEKDAYS: ['M', 'S', 'S', 'R', 'K', 'J', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['M', 'S', 'S', 'R', 'K', 'J', 'S'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['Kuartal ke-1', 'Kuartal ke-2', 'Kuartal ke-3', 'Kuartal ke-4'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, dd MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH.mm.ss zzzz', 'HH.mm.ss z', 'HH.mm.ss', 'HH.mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale is.
    - */
    -goog.i18n.DateTimeSymbols_is = {
    -  ERAS: ['f.Kr.', 'e.Kr.'],
    -  ERANAMES: ['fyrir Krist', 'eftir Krist'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'Á', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'Á', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janúar', 'febrúar', 'mars', 'apríl', 'maí', 'júní', 'júlí',
    -    'ágúst', 'september', 'október', 'nóvember', 'desember'],
    -  STANDALONEMONTHS: ['janúar', 'febrúar', 'mars', 'apríl', 'maí', 'júní',
    -    'júlí', 'ágúst', 'september', 'október', 'nóvember', 'desember'],
    -  SHORTMONTHS: ['jan.', 'feb.', 'mar.', 'apr.', 'maí', 'jún.', 'júl.',
    -    'ágú.', 'sep.', 'okt.', 'nóv.', 'des.'],
    -  STANDALONESHORTMONTHS: ['jan.', 'feb.', 'mar.', 'apr.', 'maí', 'jún.',
    -    'júl.', 'ágú.', 'sep.', 'okt.', 'nóv.', 'des.'],
    -  WEEKDAYS: ['sunnudagur', 'mánudagur', 'þriðjudagur', 'miðvikudagur',
    -    'fimmtudagur', 'föstudagur', 'laugardagur'],
    -  STANDALONEWEEKDAYS: ['sunnudagur', 'mánudagur', 'þriðjudagur',
    -    'miðvikudagur', 'fimmtudagur', 'föstudagur', 'laugardagur'],
    -  SHORTWEEKDAYS: ['sun.', 'mán.', 'þri.', 'mið.', 'fim.', 'fös.', 'lau.'],
    -  STANDALONESHORTWEEKDAYS: ['sun.', 'mán.', 'þri.', 'mið.', 'fim.', 'fös.',
    -    'lau.'],
    -  NARROWWEEKDAYS: ['S', 'M', 'Þ', 'M', 'F', 'F', 'L'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'Þ', 'M', 'F', 'F', 'L'],
    -  SHORTQUARTERS: ['F1', 'F2', 'F3', 'F4'],
    -  QUARTERS: ['1. fjórðungur', '2. fjórðungur', '3. fjórðungur',
    -    '4. fjórðungur'],
    -  AMPMS: ['f.h.', 'e.h.'],
    -  DATEFORMATS: ['EEEE, d. MMMM y', 'd. MMMM y', 'd. MMM y', 'd.M.y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'kl.\' {0}', '{1} \'kl.\' {0}', '{1}, {0}',
    -    '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale it.
    - */
    -goog.i18n.DateTimeSymbols_it = {
    -  ERAS: ['aC', 'dC'],
    -  ERANAMES: ['a.C.', 'd.C.'],
    -  NARROWMONTHS: ['G', 'F', 'M', 'A', 'M', 'G', 'L', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['G', 'F', 'M', 'A', 'M', 'G', 'L', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['gennaio', 'febbraio', 'marzo', 'aprile', 'maggio', 'giugno',
    -    'luglio', 'agosto', 'settembre', 'ottobre', 'novembre', 'dicembre'],
    -  STANDALONEMONTHS: ['Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio',
    -    'Giugno', 'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre',
    -    'Dicembre'],
    -  SHORTMONTHS: ['gen', 'feb', 'mar', 'apr', 'mag', 'giu', 'lug', 'ago', 'set',
    -    'ott', 'nov', 'dic'],
    -  STANDALONESHORTMONTHS: ['gen', 'feb', 'mar', 'apr', 'mag', 'giu', 'lug',
    -    'ago', 'set', 'ott', 'nov', 'dic'],
    -  WEEKDAYS: ['domenica', 'lunedì', 'martedì', 'mercoledì', 'giovedì',
    -    'venerdì', 'sabato'],
    -  STANDALONEWEEKDAYS: ['Domenica', 'Lunedì', 'Martedì', 'Mercoledì',
    -    'Giovedì', 'Venerdì', 'Sabato'],
    -  SHORTWEEKDAYS: ['dom', 'lun', 'mar', 'mer', 'gio', 'ven', 'sab'],
    -  STANDALONESHORTWEEKDAYS: ['dom', 'lun', 'mar', 'mer', 'gio', 'ven', 'sab'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'G', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'G', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1º trimestre', '2º trimestre', '3º trimestre',
    -    '4º trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'dd MMM y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale iw.
    - */
    -goog.i18n.DateTimeSymbols_iw = {
    -  ERAS: ['לפנה״ס', 'לספירה'],
    -  ERANAMES: ['לפני הספירה', 'לספירה'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['ינואר', 'פברואר', 'מרץ', 'אפריל', 'מאי',
    -    'יוני', 'יולי', 'אוגוסט', 'ספטמבר', 'אוקטובר',
    -    'נובמבר', 'דצמבר'],
    -  STANDALONEMONTHS: ['ינואר', 'פברואר', 'מרץ', 'אפריל',
    -    'מאי', 'יוני', 'יולי', 'אוגוסט', 'ספטמבר',
    -    'אוקטובר', 'נובמבר', 'דצמבר'],
    -  SHORTMONTHS: ['ינו׳', 'פבר׳', 'מרץ', 'אפר׳', 'מאי',
    -    'יוני', 'יולי', 'אוג׳', 'ספט׳', 'אוק׳', 'נוב׳',
    -    'דצמ׳'],
    -  STANDALONESHORTMONTHS: ['ינו׳', 'פבר׳', 'מרץ', 'אפר׳',
    -    'מאי', 'יוני', 'יולי', 'אוג׳', 'ספט׳', 'אוק׳',
    -    'נוב׳', 'דצמ׳'],
    -  WEEKDAYS: ['יום ראשון', 'יום שני', 'יום שלישי',
    -    'יום רביעי', 'יום חמישי', 'יום שישי',
    -    'יום שבת'],
    -  STANDALONEWEEKDAYS: ['יום ראשון', 'יום שני',
    -    'יום שלישי', 'יום רביעי', 'יום חמישי',
    -    'יום שישי', 'יום שבת'],
    -  SHORTWEEKDAYS: ['יום א׳', 'יום ב׳', 'יום ג׳', 'יום ד׳',
    -    'יום ה׳', 'יום ו׳', 'שבת'],
    -  STANDALONESHORTWEEKDAYS: ['יום א׳', 'יום ב׳', 'יום ג׳',
    -    'יום ד׳', 'יום ה׳', 'יום ו׳', 'שבת'],
    -  NARROWWEEKDAYS: ['א׳', 'ב׳', 'ג׳', 'ד׳', 'ה׳', 'ו׳', 'ש׳'],
    -  STANDALONENARROWWEEKDAYS: ['א׳', 'ב׳', 'ג׳', 'ד׳', 'ה׳', 'ו׳',
    -    'ש׳'],
    -  SHORTQUARTERS: ['רבעון 1', 'רבעון 2', 'רבעון 3',
    -    'רבעון 4'],
    -  QUARTERS: ['רבעון 1', 'רבעון 2', 'רבעון 3', 'רבעון 4'],
    -  AMPMS: ['לפנה״צ', 'אחה״צ'],
    -  DATEFORMATS: ['EEEE, d בMMMM y', 'd בMMMM y', 'd בMMM y', 'd.M.y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} בשעה {0}', '{1} בשעה {0}', '{1}, {0}',
    -    '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [4, 5],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ja.
    - */
    -goog.i18n.DateTimeSymbols_ja = {
    -  ERAS: ['紀元前', '西暦'],
    -  ERANAMES: ['紀元前', '西暦'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月',
    -    '9月', '10月', '11月', '12月'],
    -  STANDALONEMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月', '7月',
    -    '8月', '9月', '10月', '11月', '12月'],
    -  SHORTMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月',
    -    '9月', '10月', '11月', '12月'],
    -  STANDALONESHORTMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月',
    -    '7月', '8月', '9月', '10月', '11月', '12月'],
    -  WEEKDAYS: ['日曜日', '月曜日', '火曜日', '水曜日', '木曜日',
    -    '金曜日', '土曜日'],
    -  STANDALONEWEEKDAYS: ['日曜日', '月曜日', '火曜日', '水曜日',
    -    '木曜日', '金曜日', '土曜日'],
    -  SHORTWEEKDAYS: ['日', '月', '火', '水', '木', '金', '土'],
    -  STANDALONESHORTWEEKDAYS: ['日', '月', '火', '水', '木', '金', '土'],
    -  NARROWWEEKDAYS: ['日', '月', '火', '水', '木', '金', '土'],
    -  STANDALONENARROWWEEKDAYS: ['日', '月', '火', '水', '木', '金', '土'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['第1四半期', '第2四半期', '第3四半期',
    -    '第4四半期'],
    -  AMPMS: ['午前', '午後'],
    -  DATEFORMATS: ['y年M月d日EEEE', 'y年M月d日', 'y/MM/dd', 'y/MM/dd'],
    -  TIMEFORMATS: ['H時mm分ss秒 zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ka.
    - */
    -goog.i18n.DateTimeSymbols_ka = {
    -  ERAS: ['ძვ. წ.', 'ახ. წ.'],
    -  ERANAMES: ['ძველი წელთაღრიცხვით',
    -    'ახალი წელთაღრიცხვით'],
    -  NARROWMONTHS: ['ი', 'თ', 'მ', 'ა', 'მ', 'ი', 'ი', 'ა', 'ს',
    -    'ო', 'ნ', 'დ'],
    -  STANDALONENARROWMONTHS: ['ი', 'თ', 'მ', 'ა', 'მ', 'ი', 'ი',
    -    'ა', 'ს', 'ო', 'ნ', 'დ'],
    -  MONTHS: ['იანვარი', 'თებერვალი',
    -    'მარტი', 'აპრილი', 'მაისი',
    -    'ივნისი', 'ივლისი', 'აგვისტო',
    -    'სექტემბერი', 'ოქტომბერი',
    -    'ნოემბერი', 'დეკემბერი'],
    -  STANDALONEMONTHS: ['იანვარი', 'თებერვალი',
    -    'მარტი', 'აპრილი', 'მაისი',
    -    'ივნისი', 'ივლისი', 'აგვისტო',
    -    'სექტემბერი', 'ოქტომბერი',
    -    'ნოემბერი', 'დეკემბერი'],
    -  SHORTMONTHS: ['იან', 'თებ', 'მარ', 'აპრ', 'მაი',
    -    'ივნ', 'ივლ', 'აგვ', 'სექ', 'ოქტ',
    -    'ნოე', 'დეკ'],
    -  STANDALONESHORTMONTHS: ['იან', 'თებ', 'მარ', 'აპრ',
    -    'მაი', 'ივნ', 'ივლ', 'აგვ', 'სექ',
    -    'ოქტ', 'ნოე', 'დეკ'],
    -  WEEKDAYS: ['კვირა', 'ორშაბათი',
    -    'სამშაბათი', 'ოთხშაბათი',
    -    'ხუთშაბათი', 'პარასკევი',
    -    'შაბათი'],
    -  STANDALONEWEEKDAYS: ['კვირა', 'ორშაბათი',
    -    'სამშაბათი', 'ოთხშაბათი',
    -    'ხუთშაბათი', 'პარასკევი',
    -    'შაბათი'],
    -  SHORTWEEKDAYS: ['კვი', 'ორშ', 'სამ', 'ოთხ',
    -    'ხუთ', 'პარ', 'შაბ'],
    -  STANDALONESHORTWEEKDAYS: ['კვი', 'ორშ', 'სამ', 'ოთხ',
    -    'ხუთ', 'პარ', 'შაბ'],
    -  NARROWWEEKDAYS: ['კ', 'ო', 'ს', 'ო', 'ხ', 'პ', 'შ'],
    -  STANDALONENARROWWEEKDAYS: ['კ', 'ო', 'ს', 'ო', 'ხ', 'პ', 'შ'],
    -  SHORTQUARTERS: ['I კვ.', 'II კვ.', 'III კვ.', 'IV კვ.'],
    -  QUARTERS: ['I კვარტალი', 'II კვარტალი',
    -    'III კვარტალი', 'IV კვარტალი'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, dd MMMM, y', 'd MMMM, y', 'd MMM, y', 'dd.MM.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1}, {0}', '{1} {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale kk.
    - */
    -goog.i18n.DateTimeSymbols_kk = {
    -  ERAS: ['б.з.д.', 'б.з.'],
    -  ERANAMES: ['Біздің заманымызға дейін',
    -    'Біздің заманымыз'],
    -  NARROWMONTHS: ['Қ', 'А', 'Н', 'С', 'М', 'М', 'Ш', 'Т', 'Қ', 'Қ',
    -    'Қ', 'Ж'],
    -  STANDALONENARROWMONTHS: ['Қ', 'А', 'Н', 'С', 'М', 'М', 'Ш', 'Т', 'Қ',
    -    'Қ', 'Қ', 'Ж'],
    -  MONTHS: ['қаңтар', 'ақпан', 'наурыз', 'сәуір',
    -    'мамыр', 'маусым', 'шілде', 'тамыз',
    -    'қыркүйек', 'қазан', 'қараша', 'желтоқсан'],
    -  STANDALONEMONTHS: ['қаңтар', 'ақпан', 'наурыз', 'сәуір',
    -    'мамыр', 'маусым', 'шілде', 'тамыз',
    -    'қыркүйек', 'қазан', 'қараша', 'желтоқсан'],
    -  SHORTMONTHS: ['қаң.', 'ақп.', 'нау.', 'сәу.', 'мам.',
    -    'мау.', 'шіл.', 'там.', 'қыр.', 'қаз.', 'қар.',
    -    'желт.'],
    -  STANDALONESHORTMONTHS: ['қаң.', 'ақп.', 'нау.', 'сәу.', 'мам.',
    -    'мау.', 'шіл.', 'там.', 'қыр.', 'қаз.', 'қар.',
    -    'желт.'],
    -  WEEKDAYS: ['жексенбі', 'дүйсенбі', 'сейсенбі',
    -    'сәрсенбі', 'бейсенбі', 'жұма', 'сенбі'],
    -  STANDALONEWEEKDAYS: ['жексенбі', 'дүйсенбі',
    -    'сейсенбі', 'сәрсенбі', 'бейсенбі', 'жұма',
    -    'сенбі'],
    -  SHORTWEEKDAYS: ['жек', 'дүй', 'сей', 'сәр', 'бей', 'жұма',
    -    'сен'],
    -  STANDALONESHORTWEEKDAYS: ['жек', 'дүй', 'сей', 'сәр', 'бей',
    -    'жұма', 'сб.'],
    -  NARROWWEEKDAYS: ['Ж', 'Д', 'С', 'С', 'Б', 'Ж', 'С'],
    -  STANDALONENARROWWEEKDAYS: ['Ж', 'Д', 'С', 'С', 'Б', 'Ж', 'С'],
    -  SHORTQUARTERS: ['Т1', 'Т2', 'Т3', 'Т4'],
    -  QUARTERS: ['1-інші тоқсан', '2-інші тоқсан',
    -    '3-інші тоқсан', '4-інші тоқсан'],
    -  AMPMS: ['таңертеңгі', 'түстен кейінгі'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'y, dd-MMM', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale km.
    - */
    -goog.i18n.DateTimeSymbols_km = {
    -  ERAS: ['មុន គ.ស.', 'គ.ស.'],
    -  ERANAMES: ['មុន​គ្រិស្តសករាជ',
    -    'គ្រិស្តសករាជ'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['មករា', 'កុម្ភៈ', 'មីនា', 'មេសា',
    -    'ឧសភា', 'មិថុនា', 'កក្កដា', 'សីហា',
    -    'កញ្ញា', 'តុលា', 'វិច្ឆិកា',
    -    'ធ្នូ'],
    -  STANDALONEMONTHS: ['មករា', 'កុម្ភៈ', 'មីនា',
    -    'មេសា', 'ឧសភា', 'មិថុនា', 'កក្កដា',
    -    'សីហា', 'កញ្ញា', 'តុលា',
    -    'វិច្ឆិកា', 'ធ្នូ'],
    -  SHORTMONTHS: ['មករា', 'កុម្ភៈ', 'មីនា',
    -    'មេសា', 'ឧសភា', 'មិថុនា', 'កក្កដា',
    -    'សីហា', 'កញ្ញា', 'តុលា',
    -    'វិច្ឆិកា', 'ធ្នូ'],
    -  STANDALONESHORTMONTHS: ['មករា', 'កុម្ភៈ', 'មីនា',
    -    'មេសា', 'ឧសភា', 'មិថុនា', 'កក្កដា',
    -    'សីហា', 'កញ្ញា', 'តុលា',
    -    'វិច្ឆិកា', 'ធ្នូ'],
    -  WEEKDAYS: ['អាទិត្យ', 'ចន្ទ', 'អង្គារ',
    -    'ពុធ', 'ព្រហស្បតិ៍', 'សុក្រ',
    -    'សៅរ៍'],
    -  STANDALONEWEEKDAYS: ['អាទិត្យ', 'ចន្ទ',
    -    'អង្គារ', 'ពុធ', 'ព្រហស្បតិ៍',
    -    'សុក្រ', 'សៅរ៍'],
    -  SHORTWEEKDAYS: ['អាទិត្យ', 'ចន្ទ', 'អង្គារ',
    -    'ពុធ', 'ព្រហស្បតិ៍', 'សុក្រ',
    -    'សៅរ៍'],
    -  STANDALONESHORTWEEKDAYS: ['អាទិត្យ', 'ចន្ទ',
    -    'អង្គារ', 'ពុធ', 'ព្រហស្បតិ៍',
    -    'សុក្រ', 'សៅរ៍'],
    -  NARROWWEEKDAYS: ['1', '2', '3', '4', '5', '6', '7'],
    -  STANDALONENARROWWEEKDAYS: ['1', '2', '3', '4', '5', '6', '7'],
    -  SHORTQUARTERS: ['ត្រីមាសទី ១',
    -    'ត្រីមាសទី ២', 'ត្រីមាសទី ៣',
    -    'ត្រីមាសទី ៤'],
    -  QUARTERS: ['ត្រីមាសទី ១',
    -    'ត្រីមាសទី ២', 'ត្រីមាសទី ៣',
    -    'ត្រីមាសទី ៤'],
    -  AMPMS: ['ព្រឹក', 'ល្ងាច'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} នៅ {0}', '{1} នៅ {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale kn.
    - */
    -goog.i18n.DateTimeSymbols_kn = {
    -  ERAS: ['ಕ್ರಿ.ಪೂ', 'ಕ್ರಿ.ಶ'],
    -  ERANAMES: ['ಕ್ರಿಸ್ತ ಪೂರ್ವ',
    -    'ಕ್ರಿಸ್ತ ಶಕ'],
    -  NARROWMONTHS: ['ಜ', 'ಫೆ', 'ಮಾ', 'ಏ', 'ಮೇ', 'ಜೂ', 'ಜು',
    -    'ಆ', 'ಸೆ', 'ಅ', 'ನ', 'ಡಿ'],
    -  STANDALONENARROWMONTHS: ['ಜ', 'ಫೆ', 'ಮಾ', 'ಏ', 'ಮೇ', 'ಜೂ',
    -    'ಜು', 'ಆ', 'ಸೆ', 'ಅ', 'ನ', 'ಡಿ'],
    -  MONTHS: ['ಜನವರಿ', 'ಫೆಬ್ರವರಿ', 'ಮಾರ್ಚ್',
    -    'ಏಪ್ರಿಲ್', 'ಮೇ', 'ಜೂನ್', 'ಜುಲೈ',
    -    'ಆಗಸ್ಟ್', 'ಸೆಪ್ಟೆಂಬರ್',
    -    'ಅಕ್ಟೋಬರ್', 'ನವೆಂಬರ್',
    -    'ಡಿಸೆಂಬರ್'],
    -  STANDALONEMONTHS: ['ಜನವರಿ', 'ಫೆಬ್ರವರಿ',
    -    'ಮಾರ್ಚ್', 'ಏಪ್ರಿಲ್', 'ಮೇ', 'ಜೂನ್',
    -    'ಜುಲೈ', 'ಆಗಸ್ಟ್', 'ಸೆಪ್ಟೆಂಬರ್',
    -    'ಅಕ್ಟೋಬರ್', 'ನವೆಂಬರ್',
    -    'ಡಿಸೆಂಬರ್'],
    -  SHORTMONTHS: ['ಜನ', 'ಫೆಬ್ರ', 'ಮಾರ್ಚ್',
    -    'ಏಪ್ರಿ', 'ಮೇ', 'ಜೂನ್', 'ಜುಲೈ', 'ಆಗ',
    -    'ಸೆಪ್ಟೆಂ', 'ಅಕ್ಟೋ', 'ನವೆಂ',
    -    'ಡಿಸೆಂ'],
    -  STANDALONESHORTMONTHS: ['ಜನ', 'ಫೆಬ್ರ', 'ಮಾರ್ಚ್',
    -    'ಏಪ್ರಿ', 'ಮೇ', 'ಜೂನ್', 'ಜುಲೈ', 'ಆಗ',
    -    'ಸೆಪ್ಟೆಂ', 'ಅಕ್ಟೋ', 'ನವೆಂ',
    -    'ಡಿಸೆಂ'],
    -  WEEKDAYS: ['ಭಾನುವಾರ', 'ಸೋಮವಾರ',
    -    'ಮಂಗಳವಾರ', 'ಬುಧವಾರ', 'ಗುರುವಾರ',
    -    'ಶುಕ್ರವಾರ', 'ಶನಿವಾರ'],
    -  STANDALONEWEEKDAYS: ['ಭಾನುವಾರ', 'ಸೋಮವಾರ',
    -    'ಮಂಗಳವಾರ', 'ಬುಧವಾರ', 'ಗುರುವಾರ',
    -    'ಶುಕ್ರವಾರ', 'ಶನಿವಾರ'],
    -  SHORTWEEKDAYS: ['ಭಾನು', 'ಸೋಮ', 'ಮಂಗಳ', 'ಬುಧ',
    -    'ಗುರು', 'ಶುಕ್ರ', 'ಶನಿ'],
    -  STANDALONESHORTWEEKDAYS: ['ಭಾನು', 'ಸೋಮ', 'ಮಂಗಳ',
    -    'ಬುಧ', 'ಗುರು', 'ಶುಕ್ರ', 'ಶನಿ'],
    -  NARROWWEEKDAYS: ['ಭಾ', 'ಸೋ', 'ಮಂ', 'ಬು', 'ಗು', 'ಶು',
    -    'ಶ'],
    -  STANDALONENARROWWEEKDAYS: ['ಭಾ', 'ಸೋ', 'ಮಂ', 'ಬು', 'ಗು',
    -    'ಶು', 'ಶ'],
    -  SHORTQUARTERS: ['ತ್ರೈ 1', 'ತ್ರೈ 2', 'ತ್ರೈ 3',
    -    'ತ್ರೈ 4'],
    -  QUARTERS: ['1ನೇ ತ್ರೈಮಾಸಿಕ',
    -    '2ನೇ ತ್ರೈಮಾಸಿಕ',
    -    '3ನೇ ತ್ರೈಮಾಸಿಕ',
    -    '4ನೇ ತ್ರೈಮಾಸಿಕ'],
    -  AMPMS: ['ಪೂರ್ವಾಹ್ನ', 'ಅಪರಾಹ್ನ'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['hh:mm:ss a zzzz', 'hh:mm:ss a z', 'hh:mm:ss a', 'hh:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [6, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ko.
    - */
    -goog.i18n.DateTimeSymbols_ko = {
    -  ERAS: ['기원전', '서기'],
    -  ERANAMES: ['기원전', '서기'],
    -  NARROWMONTHS: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월',
    -    '9월', '10월', '11월', '12월'],
    -  STANDALONENARROWMONTHS: ['1월', '2월', '3월', '4월', '5월', '6월',
    -    '7월', '8월', '9월', '10월', '11월', '12월'],
    -  MONTHS: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월',
    -    '9월', '10월', '11월', '12월'],
    -  STANDALONEMONTHS: ['1월', '2월', '3월', '4월', '5월', '6월', '7월',
    -    '8월', '9월', '10월', '11월', '12월'],
    -  SHORTMONTHS: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월',
    -    '9월', '10월', '11월', '12월'],
    -  STANDALONESHORTMONTHS: ['1월', '2월', '3월', '4월', '5월', '6월',
    -    '7월', '8월', '9월', '10월', '11월', '12월'],
    -  WEEKDAYS: ['일요일', '월요일', '화요일', '수요일', '목요일',
    -    '금요일', '토요일'],
    -  STANDALONEWEEKDAYS: ['일요일', '월요일', '화요일', '수요일',
    -    '목요일', '금요일', '토요일'],
    -  SHORTWEEKDAYS: ['일', '월', '화', '수', '목', '금', '토'],
    -  STANDALONESHORTWEEKDAYS: ['일', '월', '화', '수', '목', '금', '토'],
    -  NARROWWEEKDAYS: ['일', '월', '화', '수', '목', '금', '토'],
    -  STANDALONENARROWWEEKDAYS: ['일', '월', '화', '수', '목', '금', '토'],
    -  SHORTQUARTERS: ['1분기', '2분기', '3분기', '4분기'],
    -  QUARTERS: ['제 1/4분기', '제 2/4분기', '제 3/4분기',
    -    '제 4/4분기'],
    -  AMPMS: ['오전', '오후'],
    -  DATEFORMATS: ['y년 M월 d일 EEEE', 'y년 M월 d일', 'y. M. d.',
    -    'yy. M. d.'],
    -  TIMEFORMATS: ['a h시 m분 s초 zzzz', 'a h시 m분 s초 z', 'a h:mm:ss',
    -    'a h:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ky.
    - */
    -goog.i18n.DateTimeSymbols_ky = {
    -  ERAS: ['б.з.ч.', 'б.з.'],
    -  ERANAMES: ['биздин заманга чейин',
    -    'биздин заман'],
    -  NARROWMONTHS: ['Я', 'Ф', 'М', 'А', 'М', 'И', 'И', 'А', 'С', 'О',
    -    'Н', 'Д'],
    -  STANDALONENARROWMONTHS: ['Я', 'Ф', 'М', 'А', 'М', 'И', 'И', 'А', 'С',
    -    'О', 'Н', 'Д'],
    -  MONTHS: ['январь', 'февраль', 'март', 'апрель',
    -    'май', 'июнь', 'июль', 'август', 'сентябрь',
    -    'октябрь', 'ноябрь', 'декабрь'],
    -  STANDALONEMONTHS: ['Январь', 'Февраль', 'Март',
    -    'Апрель', 'Май', 'Июнь', 'Июль', 'Август',
    -    'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'],
    -  SHORTMONTHS: ['янв.', 'фев.', 'мар.', 'апр.', 'май', 'июн.',
    -    'июл.', 'авг.', 'сен.', 'окт.', 'ноя.', 'дек.'],
    -  STANDALONESHORTMONTHS: ['Янв', 'Фев', 'Мар', 'Апр', 'Май',
    -    'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'],
    -  WEEKDAYS: ['жекшемби', 'дүйшөмбү', 'шейшемби',
    -    'шаршемби', 'бейшемби', 'жума', 'ишемби'],
    -  STANDALONEWEEKDAYS: ['жекшемби', 'дүйшөмбү',
    -    'шейшемби', 'шаршемби', 'бейшемби', 'жума',
    -    'ишемби'],
    -  SHORTWEEKDAYS: ['жек.', 'дүй.', 'шейш.', 'шарш.', 'бейш.',
    -    'жума', 'ишм.'],
    -  STANDALONESHORTWEEKDAYS: ['жек.', 'дүй.', 'шейш.', 'шарш.',
    -    'бейш.', 'жума', 'ишм.'],
    -  NARROWWEEKDAYS: ['Ж', 'Д', 'Ш', 'Ш', 'Б', 'Ж', 'И'],
    -  STANDALONENARROWWEEKDAYS: ['Ж', 'Д', 'Ш', 'Ш', 'Б', 'Ж', 'И'],
    -  SHORTQUARTERS: ['1-чей.', '2-чей.', '3-чей.', '4-чей.'],
    -  QUARTERS: ['1-чейрек', '2-чейрек', '3-чейрек',
    -    '4-чейрек'],
    -  AMPMS: ['таңкы', 'түштөн кийин'],
    -  DATEFORMATS: ['EEEE, d-MMMM, y-\'ж\'.', 'y MMMM d', 'y MMM d', 'dd.MM.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ln.
    - */
    -goog.i18n.DateTimeSymbols_ln = {
    -  ERAS: ['libóso ya', 'nsima ya Y'],
    -  ERANAMES: ['Yambo ya Yézu Krís', 'Nsima ya Yézu Krís'],
    -  NARROWMONTHS: ['y', 'f', 'm', 'a', 'm', 'y', 'y', 'a', 's', 'ɔ', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['y', 'f', 'm', 'a', 'm', 'y', 'y', 'a', 's', 'ɔ',
    -    'n', 'd'],
    -  MONTHS: ['sánzá ya yambo', 'sánzá ya míbalé', 'sánzá ya mísáto',
    -    'sánzá ya mínei', 'sánzá ya mítáno', 'sánzá ya motóbá',
    -    'sánzá ya nsambo', 'sánzá ya mwambe', 'sánzá ya libwa',
    -    'sánzá ya zómi', 'sánzá ya zómi na mɔ̌kɔ́',
    -    'sánzá ya zómi na míbalé'],
    -  STANDALONEMONTHS: ['sánzá ya yambo', 'sánzá ya míbalé',
    -    'sánzá ya mísáto', 'sánzá ya mínei', 'sánzá ya mítáno',
    -    'sánzá ya motóbá', 'sánzá ya nsambo', 'sánzá ya mwambe',
    -    'sánzá ya libwa', 'sánzá ya zómi', 'sánzá ya zómi na mɔ̌kɔ́',
    -    'sánzá ya zómi na míbalé'],
    -  SHORTMONTHS: ['yan', 'fbl', 'msi', 'apl', 'mai', 'yun', 'yul', 'agt', 'stb',
    -    'ɔtb', 'nvb', 'dsb'],
    -  STANDALONESHORTMONTHS: ['yan', 'fbl', 'msi', 'apl', 'mai', 'yun', 'yul',
    -    'agt', 'stb', 'ɔtb', 'nvb', 'dsb'],
    -  WEEKDAYS: ['eyenga', 'mokɔlɔ mwa yambo', 'mokɔlɔ mwa míbalé',
    -    'mokɔlɔ mwa mísáto', 'mokɔlɔ ya mínéi', 'mokɔlɔ ya mítáno',
    -    'mpɔ́sɔ'],
    -  STANDALONEWEEKDAYS: ['eyenga', 'mokɔlɔ mwa yambo', 'mokɔlɔ mwa míbalé',
    -    'mokɔlɔ mwa mísáto', 'mokɔlɔ ya mínéi', 'mokɔlɔ ya mítáno',
    -    'mpɔ́sɔ'],
    -  SHORTWEEKDAYS: ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'],
    -  STANDALONESHORTWEEKDAYS: ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'],
    -  NARROWWEEKDAYS: ['e', 'y', 'm', 'm', 'm', 'm', 'p'],
    -  STANDALONENARROWWEEKDAYS: ['e', 'y', 'm', 'm', 'm', 'm', 'p'],
    -  SHORTQUARTERS: ['SM1', 'SM2', 'SM3', 'SM4'],
    -  QUARTERS: ['sánzá mísáto ya yambo', 'sánzá mísáto ya míbalé',
    -    'sánzá mísáto ya mísáto', 'sánzá mísáto ya mínei'],
    -  AMPMS: ['ntɔ́ngɔ́', 'mpókwa'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale lo.
    - */
    -goog.i18n.DateTimeSymbols_lo = {
    -  ERAS: ['ກ່ອນ ຄ.ສ.', 'ຄ.ສ.'],
    -  ERANAMES: ['ກ່ອນຄຣິດສັກກະລາດ',
    -    'ຄຣິດສັກກະລາດ'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['ມັງກອນ', 'ກຸມພາ', 'ມີນາ',
    -    'ເມສາ', 'ພຶດສະພາ', 'ມິຖຸນາ',
    -    'ກໍລະກົດ', 'ສິງຫາ', 'ກັນຍາ',
    -    'ຕຸລາ', 'ພະຈິກ', 'ທັນວາ'],
    -  STANDALONEMONTHS: ['ມັງກອນ', 'ກຸມພາ', 'ມີນາ',
    -    'ເມສາ', 'ພຶດສະພາ', 'ມິຖຸນາ',
    -    'ກໍລະກົດ', 'ສິງຫາ', 'ກັນຍາ',
    -    'ຕຸລາ', 'ພະຈິກ', 'ທັນວາ'],
    -  SHORTMONTHS: ['ມ.ກ.', 'ກ.ພ.', 'ມ.ນ.', 'ມ.ສ.', 'ພ.ພ.',
    -    'ມິ.ຖ.', 'ກ.ລ.', 'ສ.ຫ.', 'ກ.ຍ.', 'ຕ.ລ.', 'ພ.ຈ.',
    -    'ທ.ວ.'],
    -  STANDALONESHORTMONTHS: ['ມ.ກ.', 'ກ.ພ.', 'ມ.ນ.', 'ມ.ສ.',
    -    'ພ.ພ.', 'ມິ.ຖ.', 'ກ.ລ.', 'ສ.ຫ.', 'ກ.ຍ.', 'ຕ.ລ.',
    -    'ພ.ຈ.', 'ທ.ວ.'],
    -  WEEKDAYS: ['ວັນອາທິດ', 'ວັນຈັນ',
    -    'ວັນອັງຄານ', 'ວັນພຸດ',
    -    'ວັນພະຫັດ', 'ວັນສຸກ', 'ວັນເສົາ'],
    -  STANDALONEWEEKDAYS: ['ວັນອາທິດ', 'ວັນຈັນ',
    -    'ວັນອັງຄານ', 'ວັນພຸດ',
    -    'ວັນພະຫັດ', 'ວັນສຸກ', 'ວັນເສົາ'],
    -  SHORTWEEKDAYS: ['ວັນອາທິດ', 'ວັນຈັນ',
    -    'ວັນອັງຄານ', 'ວັນພຸດ',
    -    'ວັນພະຫັດ', 'ວັນສຸກ', 'ວັນເສົາ'],
    -  STANDALONESHORTWEEKDAYS: ['ອາທິດ', 'ຈັນ',
    -    'ອັງຄານ', 'ພຸດ', 'ພະຫັດ', 'ສຸກ',
    -    'ເສົາ'],
    -  NARROWWEEKDAYS: ['1', '2', '3', '4', '5', '6', '7'],
    -  STANDALONENARROWWEEKDAYS: ['ອ', 'ຈ', 'ອ', 'ພ', 'ພຫ', 'ສຸ',
    -    'ສ'],
    -  SHORTQUARTERS: ['ຕມ1', 'ຕມ2', 'ຕມ3', 'ຕມ4'],
    -  QUARTERS: ['ໄຕຣມາດ 1', 'ໄຕຣມາດ 2',
    -    'ໄຕຣມາດ 3', 'ໄຕຣມາດ 4'],
    -  AMPMS: ['ກ່ອນທ່ຽງ', 'ຫຼັງທ່ຽງ'],
    -  DATEFORMATS: ['EEEE ທີ d MMMM G y', 'd MMMM y', 'd MMM y', 'd/M/y'],
    -  TIMEFORMATS: ['H ໂມງ m ນາທີ ss ວິນາທີ zzzz',
    -    'H ໂມງ m ນາທີ ss ວິນາທີ z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale lt.
    - */
    -goog.i18n.DateTimeSymbols_lt = {
    -  ERAS: ['pr. Kr.', 'po Kr.'],
    -  ERANAMES: ['prieš Kristų', 'po Kristaus'],
    -  NARROWMONTHS: ['S', 'V', 'K', 'B', 'G', 'B', 'L', 'R', 'R', 'S', 'L', 'G'],
    -  STANDALONENARROWMONTHS: ['S', 'V', 'K', 'B', 'G', 'B', 'L', 'R', 'R', 'S',
    -    'L', 'G'],
    -  MONTHS: ['sausio', 'vasario', 'kovo', 'balandžio', 'gegužės', 'birželio',
    -    'liepos', 'rugpjūčio', 'rugsėjo', 'spalio', 'lapkričio', 'gruodžio'],
    -  STANDALONEMONTHS: ['sausis', 'vasaris', 'kovas', 'balandis', 'gegužė',
    -    'birželis', 'liepa', 'rugpjūtis', 'rugsėjis', 'spalis', 'lapkritis',
    -    'gruodis'],
    -  SHORTMONTHS: ['saus.', 'vas.', 'kov.', 'bal.', 'geg.', 'birž.', 'liep.',
    -    'rugp.', 'rugs.', 'spal.', 'lapkr.', 'gruod.'],
    -  STANDALONESHORTMONTHS: ['saus.', 'vas.', 'kov.', 'bal.', 'geg.', 'birž.',
    -    'liep.', 'rugp.', 'rugs.', 'spal.', 'lapkr.', 'gruod.'],
    -  WEEKDAYS: ['sekmadienis', 'pirmadienis', 'antradienis', 'trečiadienis',
    -    'ketvirtadienis', 'penktadienis', 'šeštadienis'],
    -  STANDALONEWEEKDAYS: ['sekmadienis', 'pirmadienis', 'antradienis',
    -    'trečiadienis', 'ketvirtadienis', 'penktadienis', 'šeštadienis'],
    -  SHORTWEEKDAYS: ['sk', 'pr', 'an', 'tr', 'kt', 'pn', 'št'],
    -  STANDALONESHORTWEEKDAYS: ['sk', 'pr', 'an', 'tr', 'kt', 'pn', 'št'],
    -  NARROWWEEKDAYS: ['S', 'P', 'A', 'T', 'K', 'P', 'Š'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'P', 'A', 'T', 'K', 'P', 'Š'],
    -  SHORTQUARTERS: ['I k.', 'II k.', 'III k.', 'IV k.'],
    -  QUARTERS: ['I ketvirtis', 'II ketvirtis', 'III ketvirtis', 'IV ketvirtis'],
    -  AMPMS: ['priešpiet', 'popiet'],
    -  DATEFORMATS: ['y \'m\'. MMMM d \'d\'., EEEE', 'y \'m\'. MMMM d \'d\'.',
    -    'y-MM-dd', 'y-MM-dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale lv.
    - */
    -goog.i18n.DateTimeSymbols_lv = {
    -  ERAS: ['p.m.ē.', 'm.ē.'],
    -  ERANAMES: ['pirms mūsu ēras', 'mūsu ērā'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvāris', 'februāris', 'marts', 'aprīlis', 'maijs', 'jūnijs',
    -    'jūlijs', 'augusts', 'septembris', 'oktobris', 'novembris', 'decembris'],
    -  STANDALONEMONTHS: ['Janvāris', 'Februāris', 'Marts', 'Aprīlis', 'Maijs',
    -    'Jūnijs', 'Jūlijs', 'Augusts', 'Septembris', 'Oktobris', 'Novembris',
    -    'Decembris'],
    -  SHORTMONTHS: ['janv.', 'febr.', 'marts', 'apr.', 'maijs', 'jūn.', 'jūl.',
    -    'aug.', 'sept.', 'okt.', 'nov.', 'dec.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Febr.', 'Marts', 'Apr.', 'Maijs', 'Jūn.',
    -    'Jūl.', 'Aug.', 'Sept.', 'Okt.', 'Nov.', 'Dec.'],
    -  WEEKDAYS: ['svētdiena', 'pirmdiena', 'otrdiena', 'trešdiena', 'ceturtdiena',
    -    'piektdiena', 'sestdiena'],
    -  STANDALONEWEEKDAYS: ['Svētdiena', 'Pirmdiena', 'Otrdiena', 'Trešdiena',
    -    'Ceturtdiena', 'Piektdiena', 'Sestdiena'],
    -  SHORTWEEKDAYS: ['Sv', 'Pr', 'Ot', 'Tr', 'Ce', 'Pk', 'Se'],
    -  STANDALONESHORTWEEKDAYS: ['Sv', 'Pr', 'Ot', 'Tr', 'Ce', 'Pk', 'Se'],
    -  NARROWWEEKDAYS: ['S', 'P', 'O', 'T', 'C', 'P', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'P', 'O', 'T', 'C', 'P', 'S'],
    -  SHORTQUARTERS: ['1. cet.', '2. cet.', '3. cet.', '4. cet.'],
    -  QUARTERS: ['1. ceturksnis', '2. ceturksnis', '3. ceturksnis',
    -    '4. ceturksnis'],
    -  AMPMS: ['priekšpusdienā', 'pēcpusdienā'],
    -  DATEFORMATS: ['EEEE, y. \'gada\' d. MMMM', 'y. \'gada\' d. MMMM',
    -    'y. \'gada\' d. MMM', 'dd.MM.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale mk.
    - */
    -goog.i18n.DateTimeSymbols_mk = {
    -  ERAS: ['пр.н.е.', 'н.е.'],
    -  ERANAMES: ['пред нашата ера', 'од нашата ера'],
    -  NARROWMONTHS: ['ј', 'ф', 'м', 'а', 'м', 'ј', 'ј', 'а', 'с', 'о',
    -    'н', 'д'],
    -  STANDALONENARROWMONTHS: ['ј', 'ф', 'м', 'а', 'м', 'ј', 'ј', 'а', 'с',
    -    'о', 'н', 'д'],
    -  MONTHS: ['јануари', 'февруари', 'март', 'април',
    -    'мај', 'јуни', 'јули', 'август', 'септември',
    -    'октомври', 'ноември', 'декември'],
    -  STANDALONEMONTHS: ['јануари', 'февруари', 'март',
    -    'април', 'мај', 'јуни', 'јули', 'август',
    -    'септември', 'октомври', 'ноември',
    -    'декември'],
    -  SHORTMONTHS: ['јан.', 'фев.', 'мар.', 'апр.', 'мај', 'јун.',
    -    'јул.', 'авг.', 'септ.', 'окт.', 'ноем.', 'дек.'],
    -  STANDALONESHORTMONTHS: ['јан.', 'фев.', 'мар.', 'апр.', 'мај',
    -    'јун.', 'јул.', 'авг.', 'септ.', 'окт.', 'ноем.',
    -    'дек.'],
    -  WEEKDAYS: ['недела', 'понеделник', 'вторник',
    -    'среда', 'четврток', 'петок', 'сабота'],
    -  STANDALONEWEEKDAYS: ['недела', 'понеделник', 'вторник',
    -    'среда', 'четврток', 'петок', 'сабота'],
    -  SHORTWEEKDAYS: ['нед.', 'пон.', 'вт.', 'сре.', 'чет.',
    -    'пет.', 'саб.'],
    -  STANDALONESHORTWEEKDAYS: ['нед.', 'пон.', 'вт.', 'сре.', 'чет.',
    -    'пет.', 'саб.'],
    -  NARROWWEEKDAYS: ['н', 'п', 'в', 'с', 'ч', 'п', 'с'],
    -  STANDALONENARROWWEEKDAYS: ['н', 'п', 'в', 'с', 'ч', 'п', 'с'],
    -  SHORTQUARTERS: ['јан-мар', 'апр-јун', 'јул-сеп',
    -    'окт-дек'],
    -  QUARTERS: ['прво тромесечје', 'второ тромесечје',
    -    'трето тромесечје', 'четврто тромесечје'],
    -  AMPMS: ['претпладне', 'попладне'],
    -  DATEFORMATS: ['EEEE, dd MMMM y', 'dd MMMM y', 'dd.M.y', 'dd.M.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ml.
    - */
    -goog.i18n.DateTimeSymbols_ml = {
    -  ERAS: ['ക്രി.മു.', 'എഡി'],
    -  ERANAMES: ['ക്രിസ്‌തുവിന് മുമ്പ്',
    -    'ആന്നോ ഡൊമിനി'],
    -  NARROWMONTHS: ['ജ', 'ഫ', 'മാ', 'ഏ', 'മെ', 'ജൂ', 'ജൂ',
    -    'ഓ', 'സ', 'ഒ', 'ന', 'ഡി'],
    -  STANDALONENARROWMONTHS: ['ജ', 'ഫ', 'മാ', 'ഏ', 'മേ', 'ജൂ',
    -    'ജൂ', 'ഓ', 'സ', 'ഒ', 'ന', 'ഡി'],
    -  MONTHS: ['ജനുവരി', 'ഫെബ്രുവരി',
    -    'മാർച്ച്', 'ഏപ്രിൽ', 'മേയ്', 'ജൂൺ',
    -    'ജൂലൈ', 'ആഗസ്റ്റ്',
    -    'സെപ്റ്റംബർ', 'ഒക്‌ടോബർ',
    -    'നവംബർ', 'ഡിസംബർ'],
    -  STANDALONEMONTHS: ['ജനുവരി', 'ഫെബ്രുവരി',
    -    'മാർച്ച്', 'ഏപ്രിൽ', 'മേയ്', 'ജൂൺ',
    -    'ജൂലൈ', 'ആഗസ്റ്റ്',
    -    'സെപ്റ്റംബർ', 'ഒക്‌ടോബർ',
    -    'നവംബർ', 'ഡിസംബർ'],
    -  SHORTMONTHS: ['ജനു', 'ഫെബ്രു', 'മാർ',
    -    'ഏപ്രി', 'മേയ്', 'ജൂൺ', 'ജൂലൈ', 'ഓഗ',
    -    'സെപ്റ്റം', 'ഒക്ടോ', 'നവം', 'ഡിസം'],
    -  STANDALONESHORTMONTHS: ['ജനു', 'ഫെബ്രു', 'മാർ',
    -    'ഏപ്രി', 'മേയ്', 'ജൂൺ', 'ജൂലൈ', 'ഓഗ',
    -    'സെപ്റ്റം', 'ഒക്ടോ', 'നവം', 'ഡിസം'],
    -  WEEKDAYS: ['ഞായറാഴ്‌ച', 'തിങ്കളാഴ്‌ച',
    -    'ചൊവ്വാഴ്ച', 'ബുധനാഴ്‌ച',
    -    'വ്യാഴാഴ്‌ച', 'വെള്ളിയാഴ്‌ച',
    -    'ശനിയാഴ്‌ച'],
    -  STANDALONEWEEKDAYS: ['ഞായറാഴ്‌ച',
    -    'തിങ്കളാഴ്‌ച', 'ചൊവ്വാഴ്‌ച',
    -    'ബുധനാഴ്‌ച', 'വ്യാഴാഴ്‌ച',
    -    'വെള്ളിയാഴ്‌ച', 'ശനിയാഴ്‌ച'],
    -  SHORTWEEKDAYS: ['ഞായർ', 'തിങ്കൾ', 'ചൊവ്വ',
    -    'ബുധൻ', 'വ്യാഴം', 'വെള്ളി', 'ശനി'],
    -  STANDALONESHORTWEEKDAYS: ['ഞായർ', 'തിങ്കൾ',
    -    'ചൊവ്വ', 'ബുധൻ', 'വ്യാഴം',
    -    'വെള്ളി', 'ശനി'],
    -  NARROWWEEKDAYS: ['ഞ', 'തി', 'ച', 'ബു', 'വ', 'വെ', 'ശ'],
    -  STANDALONENARROWWEEKDAYS: ['ഞ', 'തി', 'ച', 'ബു', 'വ', 'വെ',
    -    'ശ'],
    -  SHORTQUARTERS: ['ഒന്നാം പാദം',
    -    'രണ്ടാം പാദം', 'മൂന്നാം പാദം',
    -    'നാലാം പാദം'],
    -  QUARTERS: ['ഒന്നാം പാദം',
    -    'രണ്ടാം പാദം', 'മൂന്നാം പാദം',
    -    'നാലാം പാദം'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['y, MMMM d, EEEE', 'y, MMMM d', 'y, MMM d', 'dd/MM/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [6, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale mn.
    - */
    -goog.i18n.DateTimeSymbols_mn = {
    -  ERAS: ['МЭӨ', 'МЭ'],
    -  ERANAMES: ['манай эриний өмнөх', 'манай эриний'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['Нэгдүгээр сар', 'Хоёрдугаар сар',
    -    'Гуравдугаар сар', 'Дөрөвдүгээр сар',
    -    'Тавдугаар сар', 'Зургадугаар сар',
    -    'Долдугаар сар', 'Наймдугаар сар',
    -    'Есдүгээр сар', 'Аравдугаар сар',
    -    'Арван нэгдүгээр сар',
    -    'Арван хоёрдугаар сар'],
    -  STANDALONEMONTHS: ['Нэгдүгээр сар', 'Хоёрдугаар сар',
    -    'Гуравдугаар сар', 'Дөрөвдүгээр сар',
    -    'Тавдугаар сар', 'Зургадугаар сар',
    -    'Долдугаар сар', 'Наймдугаар сар',
    -    'Есдүгээр сар', 'Аравдугаар сар',
    -    'Арван нэгдүгээр сар',
    -    'Арван хоёрдугаар сар'],
    -  SHORTMONTHS: ['1-р сар', '2-р сар', '3-р сар', '4-р сар',
    -    '5-р сар', '6-р сар', '7-р сар', '8-р сар', '9-р сар',
    -    '10-р сар', '11-р сар', '12-р сар'],
    -  STANDALONESHORTMONTHS: ['1-р сар', '2-р сар', '3-р сар',
    -    '4-р сар', '5-р сар', '6-р сар', '7-р сар', '8-р сар',
    -    '9-р сар', '10-р сар', '11-р сар', '12-р сар'],
    -  WEEKDAYS: ['ням', 'даваа', 'мягмар', 'лхагва',
    -    'пүрэв', 'баасан', 'бямба'],
    -  STANDALONEWEEKDAYS: ['ням', 'даваа', 'мягмар', 'лхагва',
    -    'пүрэв', 'баасан', 'бямба'],
    -  SHORTWEEKDAYS: ['Ня', 'Да', 'Мя', 'Лх', 'Пү', 'Ба', 'Бя'],
    -  STANDALONESHORTWEEKDAYS: ['Ня', 'Да', 'Мя', 'Лх', 'Пү', 'Ба',
    -    'Бя'],
    -  NARROWWEEKDAYS: ['1', '2', '3', '4', '5', '6', '7'],
    -  STANDALONENARROWWEEKDAYS: ['1', '2', '3', '4', '5', '6', '7'],
    -  SHORTQUARTERS: ['У1', 'У2', 'У3', 'У4'],
    -  QUARTERS: ['1-р улирал', '2-р улирал', '3-р улирал',
    -    '4-р улирал'],
    -  AMPMS: ['ҮӨ', 'ҮХ'],
    -  DATEFORMATS: ['EEEE, y \'оны\' MM \'сарын\' d',
    -    'y \'оны\' MM \'сарын\' d', 'y MMM d', 'y-MM-dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale mr.
    - */
    -goog.i18n.DateTimeSymbols_mr = {
    -  ZERODIGIT: 0x0966,
    -  ERAS: ['इ. स. पू.', 'इ. स.'],
    -  ERANAMES: ['ईसवीसनपूर्व', 'ईसवीसन'],
    -  NARROWMONTHS: ['जा', 'फे', 'मा', 'ए', 'मे', 'जू',
    -    'जु', 'ऑ', 'स', 'ऑ', 'नो', 'डि'],
    -  STANDALONENARROWMONTHS: ['जा', 'फे', 'मा', 'ए', 'मे',
    -    'जू', 'जु', 'ऑ', 'स', 'ऑ', 'नो', 'डि'],
    -  MONTHS: ['जानेवारी', 'फेब्रुवारी',
    -    'मार्च', 'एप्रिल', 'मे', 'जून',
    -    'जुलै', 'ऑगस्ट', 'सप्टेंबर',
    -    'ऑक्टोबर', 'नोव्हेंबर',
    -    'डिसेंबर'],
    -  STANDALONEMONTHS: ['जानेवारी',
    -    'फेब्रुवारी', 'मार्च', 'एप्रिल',
    -    'मे', 'जून', 'जुलै', 'ऑगस्ट',
    -    'सप्टेंबर', 'ऑक्टोबर',
    -    'नोव्हेंबर', 'डिसेंबर'],
    -  SHORTMONTHS: ['जाने', 'फेब्रु', 'मार्च',
    -    'एप्रि', 'मे', 'जून', 'जुलै', 'ऑग',
    -    'सप्टें', 'ऑक्टो', 'नोव्हें',
    -    'डिसें'],
    -  STANDALONESHORTMONTHS: ['जाने', 'फेब्रु',
    -    'मार्च', 'एप्रि', 'मे', 'जून', 'जुलै',
    -    'ऑग', 'सप्टें', 'ऑक्टो', 'नोव्हें',
    -    'डिसें'],
    -  WEEKDAYS: ['रविवार', 'सोमवार',
    -    'मंगळवार', 'बुधवार', 'गुरुवार',
    -    'शुक्रवार', 'शनिवार'],
    -  STANDALONEWEEKDAYS: ['रविवार', 'सोमवार',
    -    'मंगळवार', 'बुधवार', 'गुरुवार',
    -    'शुक्रवार', 'शनिवार'],
    -  SHORTWEEKDAYS: ['रवि', 'सोम', 'मंगळ', 'बुध',
    -    'गुरु', 'शुक्र', 'शनि'],
    -  STANDALONESHORTWEEKDAYS: ['रवि', 'सोम', 'मंगळ',
    -    'बुध', 'गुरु', 'शुक्र', 'शनि'],
    -  NARROWWEEKDAYS: ['र', 'सो', 'मं', 'बु', 'गु', 'शु',
    -    'श'],
    -  STANDALONENARROWWEEKDAYS: ['र', 'सो', 'मं', 'बु', 'गु',
    -    'शु', 'श'],
    -  SHORTQUARTERS: ['ति१', 'ति२', 'ति३', 'ति४'],
    -  QUARTERS: ['प्रथम तिमाही',
    -    'द्वितीय तिमाही',
    -    'तृतीय तिमाही',
    -    'चतुर्थ तिमाही'],
    -  AMPMS: ['म.पू.', 'म.उ.'],
    -  DATEFORMATS: ['EEEE, d MMMM, y', 'd MMMM, y', 'd MMM, y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'रोजी\' {0}', '{1} \'रोजी\' {0}',
    -    '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [6, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ms.
    - */
    -goog.i18n.DateTimeSymbols_ms = {
    -  ERAS: ['S.M.', 'TM'],
    -  ERANAMES: ['S.M.', 'TM'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'O', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'O', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januari', 'Februari', 'Mac', 'April', 'Mei', 'Jun', 'Julai', 'Ogos',
    -    'September', 'Oktober', 'November', 'Disember'],
    -  STANDALONEMONTHS: ['Januari', 'Februari', 'Mac', 'April', 'Mei', 'Jun',
    -    'Julai', 'Ogos', 'September', 'Oktober', 'November', 'Disember'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ogo', 'Sep',
    -    'Okt', 'Nov', 'Dis'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul',
    -    'Ogo', 'Sep', 'Okt', 'Nov', 'Dis'],
    -  WEEKDAYS: ['Ahad', 'Isnin', 'Selasa', 'Rabu', 'Khamis', 'Jumaat', 'Sabtu'],
    -  STANDALONEWEEKDAYS: ['Ahad', 'Isnin', 'Selasa', 'Rabu', 'Khamis', 'Jumaat',
    -    'Sabtu'],
    -  SHORTWEEKDAYS: ['Ahd', 'Isn', 'Sel', 'Rab', 'Kha', 'Jum', 'Sab'],
    -  STANDALONESHORTWEEKDAYS: ['Ahd', 'Isn', 'Sel', 'Rab', 'Kha', 'Jum', 'Sab'],
    -  NARROWWEEKDAYS: ['A', 'I', 'S', 'R', 'K', 'J', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['A', 'I', 'S', 'R', 'K', 'J', 'S'],
    -  SHORTQUARTERS: ['S1', 'S2', 'S3', 'S4'],
    -  QUARTERS: ['Suku pertama', 'Suku Ke-2', 'Suku Ke-3', 'Suku Ke-4'],
    -  AMPMS: ['PG', 'PTG'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'd/MM/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale mt.
    - */
    -goog.i18n.DateTimeSymbols_mt = {
    -  ERAS: ['QK', 'WK'],
    -  ERANAMES: ['Qabel Kristu', 'Wara Kristu'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'Ġ', 'L', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['Jn', 'Fr', 'Mz', 'Ap', 'Mj', 'Ġn', 'Lj', 'Aw',
    -    'St', 'Ob', 'Nv', 'Dċ'],
    -  MONTHS: ['Jannar', 'Frar', 'Marzu', 'April', 'Mejju', 'Ġunju', 'Lulju',
    -    'Awwissu', 'Settembru', 'Ottubru', 'Novembru', 'Diċembru'],
    -  STANDALONEMONTHS: ['Jannar', 'Frar', 'Marzu', 'April', 'Mejju', 'Ġunju',
    -    'Lulju', 'Awwissu', 'Settembru', 'Ottubru', 'Novembru', 'Diċembru'],
    -  SHORTMONTHS: ['Jan', 'Fra', 'Mar', 'Apr', 'Mej', 'Ġun', 'Lul', 'Aww', 'Set',
    -    'Ott', 'Nov', 'Diċ'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Fra', 'Mar', 'Apr', 'Mej', 'Ġun', 'Lul',
    -    'Aww', 'Set', 'Ott', 'Nov', 'Diċ'],
    -  WEEKDAYS: ['Il-Ħadd', 'It-Tnejn', 'It-Tlieta', 'L-Erbgħa', 'Il-Ħamis',
    -    'Il-Ġimgħa', 'Is-Sibt'],
    -  STANDALONEWEEKDAYS: ['Il-Ħadd', 'It-Tnejn', 'It-Tlieta', 'L-Erbgħa',
    -    'Il-Ħamis', 'Il-Ġimgħa', 'Is-Sibt'],
    -  SHORTWEEKDAYS: ['Ħad', 'Tne', 'Tli', 'Erb', 'Ħam', 'Ġim', 'Sib'],
    -  STANDALONESHORTWEEKDAYS: ['Ħad', 'Tne', 'Tli', 'Erb', 'Ħam', 'Ġim', 'Sib'],
    -  NARROWWEEKDAYS: ['Ħ', 'T', 'T', 'E', 'Ħ', 'Ġ', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['Ħd', 'Tn', 'Tl', 'Er', 'Ħm', 'Ġm', 'Sb'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['1el kwart', '2ni kwart', '3et kwart', '4ba’ kwart'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d \'ta\'’ MMMM y', 'd \'ta\'’ MMMM y', 'dd MMM y',
    -    'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale my.
    - */
    -goog.i18n.DateTimeSymbols_my = {
    -  ZERODIGIT: 0x1040,
    -  ERAS: ['ဘီစီ', 'အေဒီ'],
    -  ERANAMES: ['ခရစ်တော် မပေါ်မီကာလ',
    -    'ခရစ်တော် ပေါ်ထွန်းပြီးကာလ'],
    -  NARROWMONTHS: ['ဇ', 'ဖ', 'မ', 'ဧ', 'မ', 'ဇ', 'ဇ', 'ဩ', 'စ',
    -    'အ', 'န', 'ဒ'],
    -  STANDALONENARROWMONTHS: ['ဇ', 'ဖ', 'မ', 'ဧ', 'မ', 'ဇ', 'ဇ',
    -    'ဩ', 'စ', 'အ', 'န', 'ဒ'],
    -  MONTHS: ['ဇန်နဝါရီ', 'ဖေဖော်ဝါရီ',
    -    'မတ်', 'ဧပြီ', 'မေ', 'ဇွန်',
    -    'ဇူလိုင်', 'ဩဂုတ်', 'စက်တင်ဘာ',
    -    'အောက်တိုဘာ', 'နိုဝင်ဘာ',
    -    'ဒီဇင်ဘာ'],
    -  STANDALONEMONTHS: ['ဇန်နဝါရီ',
    -    'ဖေဖော်ဝါရီ', 'မတ်', 'ဧပြီ', 'မေ',
    -    'ဇွန်', 'ဇူလိုင်', 'ဩဂုတ်',
    -    'စက်တင်ဘာ', 'အောက်တိုဘာ',
    -    'နိုဝင်ဘာ', 'ဒီဇင်ဘာ'],
    -  SHORTMONTHS: ['ဇန်', 'ဖေ', 'မတ်', 'ဧပြီ', 'မေ',
    -    'ဇွန်', 'ဇူ', 'ဩ', 'စက်', 'အောက်',
    -    'နို', 'ဒီ'],
    -  STANDALONESHORTMONTHS: ['ဇန်', 'ဖေ', 'မတ်', 'ဧပြီ',
    -    'မေ', 'ဇွန်', 'ဇူ', 'ဩ', 'စက်', 'အောက်',
    -    'နို', 'ဒီ'],
    -  WEEKDAYS: ['တနင်္ဂနွေ', 'တနင်္လာ',
    -    'အင်္ဂါ', 'ဗုဒ္ဓဟူး',
    -    'ကြာသပတေး', 'သောကြာ', 'စနေ'],
    -  STANDALONEWEEKDAYS: ['တနင်္ဂနွေ', 'တနင်္လာ',
    -    'အင်္ဂါ', 'ဗုဒ္ဓဟူး',
    -    'ကြာသပတေး', 'သောကြာ', 'စနေ'],
    -  SHORTWEEKDAYS: ['တနင်္ဂနွေ', 'တနင်္လာ',
    -    'အင်္ဂါ', 'ဗုဒ္ဓဟူး',
    -    'ကြာသပတေး', 'သောကြာ', 'စနေ'],
    -  STANDALONESHORTWEEKDAYS: ['တနင်္ဂနွေ',
    -    'တနင်္လာ', 'အင်္ဂါ', 'ဗုဒ္ဓဟူး',
    -    'ကြာသပတေး', 'သောကြာ', 'စနေ'],
    -  NARROWWEEKDAYS: ['တ', 'တ', 'အ', 'ဗ', 'က', 'သ', 'စ'],
    -  STANDALONENARROWWEEKDAYS: ['တ', 'တ', 'အ', 'ဗ', 'က', 'သ', 'စ'],
    -  SHORTQUARTERS: ['ပထမ သုံးလပတ်',
    -    'ဒုတိယ သုံးလပတ်',
    -    'တတိယ သုံးလပတ်',
    -    'စတုတ္ထ သုံးလပတ်'],
    -  QUARTERS: ['ပထမ သုံးလပတ်',
    -    'ဒုတိယ သုံးလပတ်',
    -    'တတိယ သုံးလပတ်',
    -    'စတုတ္ထ သုံးလပတ်'],
    -  AMPMS: ['နံနက်', 'ညနေ'],
    -  DATEFORMATS: ['EEEE, dd MMMM y', 'd MMMM y', 'd MMM y', 'dd-MM-yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1}မှာ {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale nb.
    - */
    -goog.i18n.DateTimeSymbols_nb = {
    -  ERAS: ['f.Kr.', 'e.Kr.'],
    -  ERANAMES: ['f.Kr.', 'e.Kr.'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['januar', 'februar', 'mars', 'april', 'mai', 'juni', 'juli',
    -    'august', 'september', 'oktober', 'november', 'desember'],
    -  STANDALONEMONTHS: ['januar', 'februar', 'mars', 'april', 'mai', 'juni',
    -    'juli', 'august', 'september', 'oktober', 'november', 'desember'],
    -  SHORTMONTHS: ['jan.', 'feb.', 'mar.', 'apr.', 'mai', 'jun.', 'jul.', 'aug.',
    -    'sep.', 'okt.', 'nov.', 'des.'],
    -  STANDALONESHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'mai', 'jun', 'jul',
    -    'aug', 'sep', 'okt', 'nov', 'des'],
    -  WEEKDAYS: ['søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag', 'fredag',
    -    'lørdag'],
    -  STANDALONEWEEKDAYS: ['søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag',
    -    'fredag', 'lørdag'],
    -  SHORTWEEKDAYS: ['søn.', 'man.', 'tir.', 'ons.', 'tor.', 'fre.', 'lør.'],
    -  STANDALONESHORTWEEKDAYS: ['sø.', 'ma.', 'ti.', 'on.', 'to.', 'fr.', 'lø.'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'O', 'T', 'F', 'L'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'O', 'T', 'F', 'L'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['1. kvartal', '2. kvartal', '3. kvartal', '4. kvartal'],
    -  AMPMS: ['a.m.', 'p.m.'],
    -  DATEFORMATS: ['EEEE d. MMMM y', 'd. MMMM y', 'd. MMM y', 'dd.MM.y'],
    -  TIMEFORMATS: ['HH.mm.ss zzzz', 'HH.mm.ss z', 'HH.mm.ss', 'HH.mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} \'kl.\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ne.
    - */
    -goog.i18n.DateTimeSymbols_ne = {
    -  ZERODIGIT: 0x0966,
    -  ERAS: ['ईसा पूर्व', 'सन्'],
    -  ERANAMES: ['ईसा पूर्व', 'सन्'],
    -  NARROWMONTHS: ['१', '२', '३', '४', '५', '६', '७', '८', '९',
    -    '१०', '११', '१२'],
    -  STANDALONENARROWMONTHS: ['१', '२', '३', '४', '५', '६', '७',
    -    '८', '९', '१०', '११', '१२'],
    -  MONTHS: ['जनवरी', 'फेब्रुअरी', 'मार्च',
    -    'अप्रिल', 'मे', 'जुन', 'जुलाई',
    -    'अगस्ट', 'सेप्टेम्बर',
    -    'अक्टोबर', 'नोभेम्बर',
    -    'डिसेम्बर'],
    -  STANDALONEMONTHS: ['जनवरी', 'फेब्रुअरी',
    -    'मार्च', 'अप्रिल', 'मे', 'जुन',
    -    'जुलाई', 'अगस्ट', 'सेप्टेम्बर',
    -    'अक्टोबर', 'नोभेम्बर',
    -    'डिसेम्बर'],
    -  SHORTMONTHS: ['जनवरी', 'फेब्रुअरी',
    -    'मार्च', 'अप्रिल', 'मे', 'जुन',
    -    'जुलाई', 'अगस्ट', 'सेप्टेम्बर',
    -    'अक्टोबर', 'नोभेम्बर',
    -    'डिसेम्बर'],
    -  STANDALONESHORTMONTHS: ['जनवरी', 'फेब्रुअरी',
    -    'मार्च', 'अप्रिल', 'मे', 'जुन',
    -    'जुलाई', 'अगस्ट', 'सेप्टेम्बर',
    -    'अक्टोबर', 'नोभेम्बर',
    -    'डिसेम्बर'],
    -  WEEKDAYS: ['आइतबार', 'सोमबार',
    -    'मङ्गलबार', 'बुधबार', 'बिहीबार',
    -    'शुक्रबार', 'शनिबार'],
    -  STANDALONEWEEKDAYS: ['आइतबार', 'सोमबार',
    -    'मङ्गलबार', 'बुधबार', 'बिहीबार',
    -    'शुक्रबार', 'शनिबार'],
    -  SHORTWEEKDAYS: ['आइत', 'सोम', 'मङ्गल', 'बुध',
    -    'बिही', 'शुक्र', 'शनि'],
    -  STANDALONESHORTWEEKDAYS: ['आइत', 'सोम', 'मङ्गल',
    -    'बुध', 'बिही', 'शुक्र', 'शनि'],
    -  NARROWWEEKDAYS: ['आ', 'सो', 'म', 'बु', 'बि', 'शु', 'श'],
    -  STANDALONENARROWWEEKDAYS: ['आ', 'सो', 'म', 'बु', 'बि',
    -    'शु', 'श'],
    -  SHORTQUARTERS: ['पहिलो सत्र',
    -    'दोस्रो सत्र', 'तेस्रो सत्र',
    -    'चौथो सत्र'],
    -  QUARTERS: ['पहिलो सत्र', 'दोस्रो सत्र',
    -    'तेस्रो सत्र', 'चौथो सत्र'],
    -  AMPMS: ['पूर्व मध्यान्ह',
    -    'उत्तर मध्यान्ह'],
    -  DATEFORMATS: ['y MMMM d, EEEE', 'y MMMM d', 'y MMM d', 'y-MM-dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale nl.
    - */
    -goog.i18n.DateTimeSymbols_nl = {
    -  ERAS: ['v.Chr.', 'n.Chr.'],
    -  ERANAMES: ['voor Christus', 'na Christus'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli',
    -    'augustus', 'september', 'oktober', 'november', 'december'],
    -  STANDALONEMONTHS: ['Januari', 'Februari', 'Maart', 'April', 'Mei', 'Juni',
    -    'Juli', 'Augustus', 'September', 'Oktober', 'November', 'December'],
    -  SHORTMONTHS: ['jan.', 'feb.', 'mrt.', 'apr.', 'mei', 'jun.', 'jul.', 'aug.',
    -    'sep.', 'okt.', 'nov.', 'dec.'],
    -  STANDALONESHORTMONTHS: ['Jan.', 'Feb.', 'Mrt.', 'Apr.', 'Mei', 'Jun.', 'Jul.',
    -    'Aug.', 'Sep.', 'Okt.', 'Nov.', 'Dec.'],
    -  WEEKDAYS: ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag',
    -    'zaterdag'],
    -  STANDALONEWEEKDAYS: ['Zondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag',
    -    'Vrijdag', 'Zaterdag'],
    -  SHORTWEEKDAYS: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
    -  STANDALONESHORTWEEKDAYS: ['Zo', 'Ma', 'Di', 'Wo', 'Do', 'Vr', 'Za'],
    -  NARROWWEEKDAYS: ['Z', 'M', 'D', 'W', 'D', 'V', 'Z'],
    -  STANDALONENARROWWEEKDAYS: ['Z', 'M', 'D', 'W', 'D', 'V', 'Z'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['1e kwartaal', '2e kwartaal', '3e kwartaal', '4e kwartaal'],
    -  AMPMS: ['a.m.', 'p.m.'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd-MM-yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale no.
    - */
    -goog.i18n.DateTimeSymbols_no = {
    -  ERAS: ['f.Kr.', 'e.Kr.'],
    -  ERANAMES: ['f.Kr.', 'e.Kr.'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['januar', 'februar', 'mars', 'april', 'mai', 'juni', 'juli',
    -    'august', 'september', 'oktober', 'november', 'desember'],
    -  STANDALONEMONTHS: ['januar', 'februar', 'mars', 'april', 'mai', 'juni',
    -    'juli', 'august', 'september', 'oktober', 'november', 'desember'],
    -  SHORTMONTHS: ['jan.', 'feb.', 'mar.', 'apr.', 'mai', 'jun.', 'jul.', 'aug.',
    -    'sep.', 'okt.', 'nov.', 'des.'],
    -  STANDALONESHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'mai', 'jun', 'jul',
    -    'aug', 'sep', 'okt', 'nov', 'des'],
    -  WEEKDAYS: ['søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag', 'fredag',
    -    'lørdag'],
    -  STANDALONEWEEKDAYS: ['søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag',
    -    'fredag', 'lørdag'],
    -  SHORTWEEKDAYS: ['søn.', 'man.', 'tir.', 'ons.', 'tor.', 'fre.', 'lør.'],
    -  STANDALONESHORTWEEKDAYS: ['sø.', 'ma.', 'ti.', 'on.', 'to.', 'fr.', 'lø.'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'O', 'T', 'F', 'L'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'O', 'T', 'F', 'L'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['1. kvartal', '2. kvartal', '3. kvartal', '4. kvartal'],
    -  AMPMS: ['a.m.', 'p.m.'],
    -  DATEFORMATS: ['EEEE d. MMMM y', 'd. MMMM y', 'd. MMM y', 'dd.MM.y'],
    -  TIMEFORMATS: ['HH.mm.ss zzzz', 'HH.mm.ss z', 'HH.mm.ss', 'HH.mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} \'kl.\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale no_NO.
    - */
    -goog.i18n.DateTimeSymbols_no_NO = goog.i18n.DateTimeSymbols_no;
    -
    -
    -/**
    - * Date/time formatting symbols for locale or.
    - */
    -goog.i18n.DateTimeSymbols_or = {
    -  ERAS: ['BCE', 'CE'],
    -  ERANAMES: ['BCE', 'CE'],
    -  NARROWMONTHS: ['ଜା', 'ଫେ', 'ମା', 'ଅ', 'ମଇ', 'ଜୁ',
    -    'ଜୁ', 'ଅ', 'ସେ', 'ଅ', 'ନ', 'ଡି'],
    -  STANDALONENARROWMONTHS: ['ଜା', 'ଫେ', 'ମା', 'ଅ', 'ମଇ',
    -    'ଜୁ', 'ଜୁ', 'ଅ', 'ସେ', 'ଅ', 'ନ', 'ଡି'],
    -  MONTHS: ['ଜାନୁଆରୀ', 'ଫେବୃଆରୀ',
    -    'ମାର୍ଚ୍ଚ', 'ଅପ୍ରେଲ', 'ମଇ', 'ଜୁନ',
    -    'ଜୁଲାଇ', 'ଅଗଷ୍ଟ', 'ସେପ୍ଟେମ୍ବର',
    -    'ଅକ୍ଟୋବର', 'ନଭେମ୍ବର',
    -    'ଡିସେମ୍ବର'],
    -  STANDALONEMONTHS: ['ଜାନୁଆରୀ', 'ଫେବୃଆରୀ',
    -    'ମାର୍ଚ୍ଚ', 'ଅପ୍ରେଲ', 'ମଇ', 'ଜୁନ',
    -    'ଜୁଲାଇ', 'ଅଗଷ୍ଟ', 'ସେପ୍ଟେମ୍ବର',
    -    'ଅକ୍ଟୋବର', 'ନଭେମ୍ବର',
    -    'ଡିସେମ୍ବର'],
    -  SHORTMONTHS: ['ଜାନୁଆରୀ', 'ଫେବୃଆରୀ',
    -    'ମାର୍ଚ୍ଚ', 'ଅପ୍ରେଲ', 'ମଇ', 'ଜୁନ',
    -    'ଜୁଲାଇ', 'ଅଗଷ୍ଟ', 'ସେପ୍ଟେମ୍ବର',
    -    'ଅକ୍ଟୋବର', 'ନଭେମ୍ବର',
    -    'ଡିସେମ୍ବର'],
    -  STANDALONESHORTMONTHS: ['ଜାନୁଆରୀ', 'ଫେବୃଆରୀ',
    -    'ମାର୍ଚ୍ଚ', 'ଅପ୍ରେଲ', 'ମଇ', 'ଜୁନ',
    -    'ଜୁଲାଇ', 'ଅଗଷ୍ଟ', 'ସେପ୍ଟେମ୍ବର',
    -    'ଅକ୍ଟୋବର', 'ନଭେମ୍ବର',
    -    'ଡିସେମ୍ବର'],
    -  WEEKDAYS: ['ରବିବାର', 'ସୋମବାର',
    -    'ମଙ୍ଗଳବାର', 'ବୁଧବାର', 'ଗୁରୁବାର',
    -    'ଶୁକ୍ରବାର', 'ଶନିବାର'],
    -  STANDALONEWEEKDAYS: ['ରବିବାର', 'ସୋମବାର',
    -    'ମଙ୍ଗଳବାର', 'ବୁଧବାର', 'ଗୁରୁବାର',
    -    'ଶୁକ୍ରବାର', 'ଶନିବାର'],
    -  SHORTWEEKDAYS: ['ରବି', 'ସୋମ', 'ମଙ୍ଗଳ', 'ବୁଧ',
    -    'ଗୁରୁ', 'ଶୁକ୍ର', 'ଶନି'],
    -  STANDALONESHORTWEEKDAYS: ['ରବି', 'ସୋମ', 'ମଙ୍ଗଳ',
    -    'ବୁଧ', 'ଗୁରୁ', 'ଶୁକ୍ର', 'ଶନି'],
    -  NARROWWEEKDAYS: ['ର', 'ସୋ', 'ମ', 'ବୁ', 'ଗୁ', 'ଶୁ', 'ଶ'],
    -  STANDALONENARROWWEEKDAYS: ['ର', 'ସୋ', 'ମ', 'ବୁ', 'ଗୁ',
    -    'ଶୁ', 'ଶ'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['am', 'pm'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'd-M-yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [6, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale pa.
    - */
    -goog.i18n.DateTimeSymbols_pa = {
    -  ERAS: ['ਈ. ਪੂ.', 'ਸੰਨ'],
    -  ERANAMES: ['ਈਸਵੀ ਪੂਰਵ', 'ਈਸਵੀ ਸੰਨ'],
    -  NARROWMONTHS: ['ਜ', 'ਫ਼', 'ਮਾ', 'ਅ', 'ਮ', 'ਜੂ', 'ਜੁ',
    -    'ਅ', 'ਸ', 'ਅ', 'ਨ', 'ਦ'],
    -  STANDALONENARROWMONTHS: ['ਜ', 'ਫ਼', 'ਮਾ', 'ਅ', 'ਮ', 'ਜੂ',
    -    'ਜੁ', 'ਅ', 'ਸ', 'ਅ', 'ਨ', 'ਦ'],
    -  MONTHS: ['ਜਨਵਰੀ', 'ਫ਼ਰਵਰੀ', 'ਮਾਰਚ',
    -    'ਅਪ੍ਰੈਲ', 'ਮਈ', 'ਜੂਨ', 'ਜੁਲਾਈ',
    -    'ਅਗਸਤ', 'ਸਤੰਬਰ', 'ਅਕਤੂਬਰ', 'ਨਵੰਬਰ',
    -    'ਦਸੰਬਰ'],
    -  STANDALONEMONTHS: ['ਜਨਵਰੀ', 'ਫ਼ਰਵਰੀ', 'ਮਾਰਚ',
    -    'ਅਪ੍ਰੈਲ', 'ਮਈ', 'ਜੂਨ', 'ਜੁਲਾਈ',
    -    'ਅਗਸਤ', 'ਸਤੰਬਰ', 'ਅਕਤੂਬਰ', 'ਨਵੰਬਰ',
    -    'ਦਸੰਬਰ'],
    -  SHORTMONTHS: ['ਜਨ', 'ਫ਼ਰ', 'ਮਾਰਚ', 'ਅਪ੍ਰੈ',
    -    'ਮਈ', 'ਜੂਨ', 'ਜੁਲਾ', 'ਅਗ', 'ਸਤੰ',
    -    'ਅਕਤੂ', 'ਨਵੰ', 'ਦਸੰ'],
    -  STANDALONESHORTMONTHS: ['ਜਨ', 'ਫ਼ਰ', 'ਮਾਰਚ',
    -    'ਅਪ੍ਰੈ', 'ਮਈ', 'ਜੂਨ', 'ਜੁਲਾ', 'ਅਗ',
    -    'ਸਤੰ', 'ਅਕਤੂ', 'ਨਵੰ', 'ਦਸੰ'],
    -  WEEKDAYS: ['ਐਤਵਾਰ', 'ਸੋਮਵਾਰ', 'ਮੰਗਲਵਾਰ',
    -    'ਬੁੱਧਵਾਰ', 'ਵੀਰਵਾਰ',
    -    'ਸ਼ੁੱਕਰਵਾਰ', 'ਸ਼ਨਿੱਚਰਵਾਰ'],
    -  STANDALONEWEEKDAYS: ['ਐਤਵਾਰ', 'ਸੋਮਵਾਰ',
    -    'ਮੰਗਲਵਾਰ', 'ਬੁੱਧਵਾਰ', 'ਵੀਰਵਾਰ',
    -    'ਸ਼ੁੱਕਰਵਾਰ', 'ਸ਼ਨਿੱਚਰਵਾਰ'],
    -  SHORTWEEKDAYS: ['ਐਤ', 'ਸੋਮ', 'ਮੰਗਲ', 'ਬੁੱਧ',
    -    'ਵੀਰ', 'ਸ਼ੁੱਕਰ', 'ਸ਼ਨਿੱਚਰ'],
    -  STANDALONESHORTWEEKDAYS: ['ਐਤ', 'ਸੋਮ', 'ਮੰਗਲ',
    -    'ਬੁੱਧ', 'ਵੀਰ', 'ਸ਼ੁੱਕਰ', 'ਸ਼ਨਿੱਚਰ'],
    -  NARROWWEEKDAYS: ['ਐ', 'ਸੋ', 'ਮੰ', 'ਬੁੱ', 'ਵੀ',
    -    'ਸ਼ੁੱ', 'ਸ਼'],
    -  STANDALONENARROWWEEKDAYS: ['ਐ', 'ਸੋ', 'ਮੰ', 'ਬੁੱ', 'ਵੀ',
    -    'ਸ਼ੁੱ', 'ਸ਼'],
    -  SHORTQUARTERS: ['ਤਿਮਾਹੀ1', 'ਤਿਮਾਹੀ2',
    -    'ਤਿਮਾਹੀ3', 'ਤਿਮਾਹੀ4'],
    -  QUARTERS: ['ਪਹਿਲੀ ਤਿਮਾਹੀ',
    -    'ਦੂਜੀ ਤਿਮਾਹੀ', 'ਤੀਜੀ ਤਿਮਾਹੀ',
    -    'ਚੌਥੀ ਤਿਮਾਹੀ'],
    -  AMPMS: ['ਪੂ.ਦੁ.', 'ਬਾ.ਦੁ.'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [6, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale pl.
    - */
    -goog.i18n.DateTimeSymbols_pl = {
    -  ERAS: ['p.n.e.', 'n.e.'],
    -  ERANAMES: ['p.n.e.', 'n.e.'],
    -  NARROWMONTHS: ['s', 'l', 'm', 'k', 'm', 'c', 'l', 's', 'w', 'p', 'l', 'g'],
    -  STANDALONENARROWMONTHS: ['s', 'l', 'm', 'k', 'm', 'c', 'l', 's', 'w', 'p',
    -    'l', 'g'],
    -  MONTHS: ['stycznia', 'lutego', 'marca', 'kwietnia', 'maja', 'czerwca',
    -    'lipca', 'sierpnia', 'września', 'października', 'listopada', 'grudnia'],
    -  STANDALONEMONTHS: ['styczeń', 'luty', 'marzec', 'kwiecień', 'maj',
    -    'czerwiec', 'lipiec', 'sierpień', 'wrzesień', 'październik', 'listopad',
    -    'grudzień'],
    -  SHORTMONTHS: ['sty', 'lut', 'mar', 'kwi', 'maj', 'cze', 'lip', 'sie', 'wrz',
    -    'paź', 'lis', 'gru'],
    -  STANDALONESHORTMONTHS: ['sty', 'lut', 'mar', 'kwi', 'maj', 'cze', 'lip',
    -    'sie', 'wrz', 'paź', 'lis', 'gru'],
    -  WEEKDAYS: ['niedziela', 'poniedziałek', 'wtorek', 'środa', 'czwartek',
    -    'piątek', 'sobota'],
    -  STANDALONEWEEKDAYS: ['niedziela', 'poniedziałek', 'wtorek', 'środa',
    -    'czwartek', 'piątek', 'sobota'],
    -  SHORTWEEKDAYS: ['niedz.', 'pon.', 'wt.', 'śr.', 'czw.', 'pt.', 'sob.'],
    -  STANDALONESHORTWEEKDAYS: ['niedz.', 'pon.', 'wt.', 'śr.', 'czw.', 'pt.',
    -    'sob.'],
    -  NARROWWEEKDAYS: ['N', 'P', 'W', 'Ś', 'C', 'P', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['N', 'P', 'W', 'Ś', 'C', 'P', 'S'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['I kwartał', 'II kwartał', 'III kwartał', 'IV kwartał'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd.MM.y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale pt.
    - */
    -goog.i18n.DateTimeSymbols_pt = {
    -  ERAS: ['a.C.', 'd.C.'],
    -  ERANAMES: ['Antes de Cristo', 'Ano do Senhor'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janeiro', 'fevereiro', 'março', 'abril', 'maio', 'junho', 'julho',
    -    'agosto', 'setembro', 'outubro', 'novembro', 'dezembro'],
    -  STANDALONEMONTHS: ['janeiro', 'fevereiro', 'março', 'abril', 'maio', 'junho',
    -    'julho', 'agosto', 'setembro', 'outubro', 'novembro', 'dezembro'],
    -  SHORTMONTHS: ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set',
    -    'out', 'nov', 'dez'],
    -  STANDALONESHORTMONTHS: ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul',
    -    'ago', 'set', 'out', 'nov', 'dez'],
    -  WEEKDAYS: ['domingo', 'segunda-feira', 'terça-feira', 'quarta-feira',
    -    'quinta-feira', 'sexta-feira', 'sábado'],
    -  STANDALONEWEEKDAYS: ['domingo', 'segunda-feira', 'terça-feira',
    -    'quarta-feira', 'quinta-feira', 'sexta-feira', 'sábado'],
    -  SHORTWEEKDAYS: ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'],
    -  STANDALONESHORTWEEKDAYS: ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'],
    -  NARROWWEEKDAYS: ['D', 'S', 'T', 'Q', 'Q', 'S', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'S', 'T', 'Q', 'Q', 'S', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1º trimestre', '2º trimestre', '3º trimestre',
    -    '4º trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'd \'de\' MMM \'de\' y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale pt_BR.
    - */
    -goog.i18n.DateTimeSymbols_pt_BR = goog.i18n.DateTimeSymbols_pt;
    -
    -
    -/**
    - * Date/time formatting symbols for locale pt_PT.
    - */
    -goog.i18n.DateTimeSymbols_pt_PT = {
    -  ERAS: ['a.C.', 'd.C.'],
    -  ERANAMES: ['antes de Cristo', 'depois de Cristo'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janeiro', 'fevereiro', 'março', 'abril', 'maio', 'junho', 'julho',
    -    'agosto', 'setembro', 'outubro', 'novembro', 'dezembro'],
    -  STANDALONEMONTHS: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho',
    -    'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'],
    -  SHORTMONTHS: ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set',
    -    'out', 'nov', 'dez'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul',
    -    'Ago', 'Set', 'Out', 'Nov', 'Dez'],
    -  WEEKDAYS: ['domingo', 'segunda-feira', 'terça-feira', 'quarta-feira',
    -    'quinta-feira', 'sexta-feira', 'sábado'],
    -  STANDALONEWEEKDAYS: ['domingo', 'segunda-feira', 'terça-feira',
    -    'quarta-feira', 'quinta-feira', 'sexta-feira', 'sábado'],
    -  SHORTWEEKDAYS: ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'],
    -  STANDALONESHORTWEEKDAYS: ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'],
    -  NARROWWEEKDAYS: ['D', 'S', 'T', 'Q', 'Q', 'S', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'S', 'T', 'Q', 'Q', 'S', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1.º trimestre', '2.º trimestre', '3.º trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['da manhã', 'da tarde'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'dd/MM/y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'às\' {0}', '{1} \'às\' {0}', '{1}, {0}',
    -    '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ro.
    - */
    -goog.i18n.DateTimeSymbols_ro = {
    -  ERAS: ['î.Hr.', 'd.Hr.'],
    -  ERANAMES: ['înainte de Hristos', 'după Hristos'],
    -  NARROWMONTHS: ['I', 'F', 'M', 'A', 'M', 'I', 'I', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['I', 'F', 'M', 'A', 'M', 'I', 'I', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['ianuarie', 'februarie', 'martie', 'aprilie', 'mai', 'iunie',
    -    'iulie', 'august', 'septembrie', 'octombrie', 'noiembrie', 'decembrie'],
    -  STANDALONEMONTHS: ['Ianuarie', 'Februarie', 'Martie', 'Aprilie', 'Mai',
    -    'Iunie', 'Iulie', 'August', 'Septembrie', 'Octombrie', 'Noiembrie',
    -    'Decembrie'],
    -  SHORTMONTHS: ['ian.', 'feb.', 'mar.', 'apr.', 'mai', 'iun.', 'iul.', 'aug.',
    -    'sept.', 'oct.', 'nov.', 'dec.'],
    -  STANDALONESHORTMONTHS: ['ian.', 'feb.', 'mar.', 'apr.', 'mai', 'iun.', 'iul.',
    -    'aug.', 'sept.', 'oct.', 'nov.', 'dec.'],
    -  WEEKDAYS: ['duminică', 'luni', 'marți', 'miercuri', 'joi', 'vineri',
    -    'sâmbătă'],
    -  STANDALONEWEEKDAYS: ['Duminică', 'Luni', 'Marți', 'Miercuri', 'Joi',
    -    'Vineri', 'Sâmbătă'],
    -  SHORTWEEKDAYS: ['Dum', 'Lun', 'Mar', 'Mie', 'Joi', 'Vin', 'Sâm'],
    -  STANDALONESHORTWEEKDAYS: ['Dum', 'Lun', 'Mar', 'Mie', 'Joi', 'Vin', 'Sâm'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['trim. I', 'trim. II', 'trim. III', 'trim. IV'],
    -  QUARTERS: ['trimestrul I', 'trimestrul al II-lea', 'trimestrul al III-lea',
    -    'trimestrul al IV-lea'],
    -  AMPMS: ['a.m.', 'p.m.'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd.MM.y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ru.
    - */
    -goog.i18n.DateTimeSymbols_ru = {
    -  ERAS: ['до н. э.', 'н. э.'],
    -  ERANAMES: ['до н. э.', 'н. э.'],
    -  NARROWMONTHS: ['Я', 'Ф', 'М', 'А', 'М', 'И', 'И', 'А', 'С', 'О',
    -    'Н', 'Д'],
    -  STANDALONENARROWMONTHS: ['Я', 'Ф', 'М', 'А', 'М', 'И', 'И', 'А', 'С',
    -    'О', 'Н', 'Д'],
    -  MONTHS: ['января', 'февраля', 'марта', 'апреля',
    -    'мая', 'июня', 'июля', 'августа', 'сентября',
    -    'октября', 'ноября', 'декабря'],
    -  STANDALONEMONTHS: ['январь', 'февраль', 'март',
    -    'апрель', 'май', 'июнь', 'июль', 'август',
    -    'сентябрь', 'октябрь', 'ноябрь', 'декабрь'],
    -  SHORTMONTHS: ['янв.', 'февр.', 'марта', 'апр.', 'мая',
    -    'июня', 'июля', 'авг.', 'сент.', 'окт.', 'нояб.',
    -    'дек.'],
    -  STANDALONESHORTMONTHS: ['янв.', 'февр.', 'март', 'апр.',
    -    'май', 'июнь', 'июль', 'авг.', 'сент.', 'окт.',
    -    'нояб.', 'дек.'],
    -  WEEKDAYS: ['воскресенье', 'понедельник',
    -    'вторник', 'среда', 'четверг', 'пятница',
    -    'суббота'],
    -  STANDALONEWEEKDAYS: ['Воскресенье', 'Понедельник',
    -    'Вторник', 'Среда', 'Четверг', 'Пятница',
    -    'Суббота'],
    -  SHORTWEEKDAYS: ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],
    -  STANDALONESHORTWEEKDAYS: ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт',
    -    'Сб'],
    -  NARROWWEEKDAYS: ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],
    -  STANDALONENARROWWEEKDAYS: ['В', 'П', 'В', 'С', 'Ч', 'П', 'С'],
    -  SHORTQUARTERS: ['1-й кв.', '2-й кв.', '3-й кв.', '4-й кв.'],
    -  QUARTERS: ['1-й квартал', '2-й квартал',
    -    '3-й квартал', '4-й квартал'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM y \'г\'.', 'd MMMM y \'г\'.', 'd MMM y \'г\'.',
    -    'dd.MM.yy'],
    -  TIMEFORMATS: ['H:mm:ss zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale si.
    - */
    -goog.i18n.DateTimeSymbols_si = {
    -  ERAS: ['ක්‍රි.පූ.', 'ක්‍රි.ව.'],
    -  ERANAMES: ['ක්‍රිස්තු පූර්‍ව',
    -    'ක්‍රිස්තු වර්‍ෂ'],
    -  NARROWMONTHS: ['ජ', 'පෙ', 'මා', 'අ', 'මැ', 'ජූ', 'ජූ',
    -    'අ', 'සැ', 'ඔ', 'නෙ', 'දෙ'],
    -  STANDALONENARROWMONTHS: ['ජ', 'පෙ', 'මා', 'අ', 'මැ', 'ජූ',
    -    'ජූ', 'අ', 'සැ', 'ඔ', 'නෙ', 'දෙ'],
    -  MONTHS: ['ජනවාරි', 'පෙබරවාරි',
    -    'මාර්තු', 'අප්‍රේල්', 'මැයි',
    -    'ජූනි', 'ජූලි', 'අගෝස්තු',
    -    'සැප්තැම්බර්', 'ඔක්තෝබර්',
    -    'නොවැම්බර්', 'දෙසැම්බර්'],
    -  STANDALONEMONTHS: ['ජනවාරි', 'පෙබරවාරි',
    -    'මාර්තු', 'අප්‍රේල්', 'මැයි',
    -    'ජූනි', 'ජූලි', 'අගෝස්තු',
    -    'සැප්තැම්බර්', 'ඔක්තෝබර්',
    -    'නොවැම්බර්', 'දෙසැම්බර්'],
    -  SHORTMONTHS: ['ජන', 'පෙබ', 'මාර්තු',
    -    'අප්‍රේල්', 'මැයි', 'ජූනි', 'ජූලි',
    -    'අගෝ', 'සැප්', 'ඔක්', 'නොවැ', 'දෙසැ'],
    -  STANDALONESHORTMONTHS: ['ජන', 'පෙබ', 'මාර්',
    -    'අප්‍රේල්', 'මැයි', 'ජූනි', 'ජූලි',
    -    'අගෝ', 'සැප්', 'ඔක්', 'නොවැ', 'දෙසැ'],
    -  WEEKDAYS: ['ඉරිදා', 'සඳුදා',
    -    'අඟහරුවාදා', 'බදාදා',
    -    'බ්‍රහස්පතින්දා', 'සිකුරාදා',
    -    'සෙනසුරාදා'],
    -  STANDALONEWEEKDAYS: ['ඉරිදා', 'සඳුදා',
    -    'අඟහරුවාදා', 'බදාදා',
    -    'බ්‍රහස්පතින්දා', 'සිකුරාදා',
    -    'සෙනසුරාදා'],
    -  SHORTWEEKDAYS: ['ඉරිදා', 'සඳුදා', 'අඟහ',
    -    'බදාදා', 'බ්‍රහස්', 'සිකු', 'සෙන'],
    -  STANDALONESHORTWEEKDAYS: ['ඉරිදා', 'සඳුදා', 'අඟහ',
    -    'බදාදා', 'බ්‍රහස්', 'සිකු', 'සෙන'],
    -  NARROWWEEKDAYS: ['ඉ', 'ස', 'අ', 'බ', 'බ්‍ර', 'සි',
    -    'සෙ'],
    -  STANDALONENARROWWEEKDAYS: ['ඉ', 'ස', 'අ', 'බ', 'බ්‍ර',
    -    'සි', 'සෙ'],
    -  SHORTQUARTERS: ['කාර්:1', 'කාර්:2', 'කාර්:3',
    -    'කාර්:4'],
    -  QUARTERS: ['1 වන කාර්තුව', '2 වන කාර්තුව',
    -    '3 වන කාර්තුව', '4 වන කාර්තුව'],
    -  AMPMS: ['පෙ.ව.', 'ප.ව.'],
    -  DATEFORMATS: ['y MMMM d, EEEE', 'y MMMM d', 'y MMM d', 'y-MM-dd'],
    -  TIMEFORMATS: ['a h.mm.ss zzzz', 'a h.mm.ss z', 'a h.mm.ss', 'a h.mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale sk.
    - */
    -goog.i18n.DateTimeSymbols_sk = {
    -  ERAS: ['pred Kr.', 'po Kr.'],
    -  ERANAMES: ['pred Kristom', 'po Kristovi'],
    -  NARROWMONTHS: ['j', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['j', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o',
    -    'n', 'd'],
    -  MONTHS: ['januára', 'februára', 'marca', 'apríla', 'mája', 'júna',
    -    'júla', 'augusta', 'septembra', 'októbra', 'novembra', 'decembra'],
    -  STANDALONEMONTHS: ['január', 'február', 'marec', 'apríl', 'máj', 'jún',
    -    'júl', 'august', 'september', 'október', 'november', 'december'],
    -  SHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'máj', 'jún', 'júl', 'aug',
    -    'sep', 'okt', 'nov', 'dec'],
    -  STANDALONESHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'máj', 'jún', 'júl',
    -    'aug', 'sep', 'okt', 'nov', 'dec'],
    -  WEEKDAYS: ['nedeľa', 'pondelok', 'utorok', 'streda', 'štvrtok', 'piatok',
    -    'sobota'],
    -  STANDALONEWEEKDAYS: ['nedeľa', 'pondelok', 'utorok', 'streda', 'štvrtok',
    -    'piatok', 'sobota'],
    -  SHORTWEEKDAYS: ['ne', 'po', 'ut', 'st', 'št', 'pi', 'so'],
    -  STANDALONESHORTWEEKDAYS: ['ne', 'po', 'ut', 'st', 'št', 'pi', 'so'],
    -  NARROWWEEKDAYS: ['N', 'P', 'U', 'S', 'Š', 'P', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['N', 'P', 'U', 'S', 'Š', 'P', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1. štvrťrok', '2. štvrťrok', '3. štvrťrok',
    -    '4. štvrťrok'],
    -  AMPMS: ['dopoludnia', 'odpoludnia'],
    -  DATEFORMATS: ['EEEE, d. MMMM y', 'd. MMMM y', 'd. M. y', 'dd.MM.yy'],
    -  TIMEFORMATS: ['H:mm:ss zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1}, {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale sl.
    - */
    -goog.i18n.DateTimeSymbols_sl = {
    -  ERAS: ['pr. n. št.', 'po Kr.'],
    -  ERANAMES: ['pred našim štetjem', 'naše štetje'],
    -  NARROWMONTHS: ['j', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['j', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o',
    -    'n', 'd'],
    -  MONTHS: ['januar', 'februar', 'marec', 'april', 'maj', 'junij', 'julij',
    -    'avgust', 'september', 'oktober', 'november', 'december'],
    -  STANDALONEMONTHS: ['januar', 'februar', 'marec', 'april', 'maj', 'junij',
    -    'julij', 'avgust', 'september', 'oktober', 'november', 'december'],
    -  SHORTMONTHS: ['jan.', 'feb.', 'mar.', 'apr.', 'maj', 'jun.', 'jul.', 'avg.',
    -    'sep.', 'okt.', 'nov.', 'dec.'],
    -  STANDALONESHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul',
    -    'avg', 'sep', 'okt', 'nov', 'dec'],
    -  WEEKDAYS: ['nedelja', 'ponedeljek', 'torek', 'sreda', 'četrtek', 'petek',
    -    'sobota'],
    -  STANDALONEWEEKDAYS: ['nedelja', 'ponedeljek', 'torek', 'sreda', 'četrtek',
    -    'petek', 'sobota'],
    -  SHORTWEEKDAYS: ['ned.', 'pon.', 'tor.', 'sre.', 'čet.', 'pet.', 'sob.'],
    -  STANDALONESHORTWEEKDAYS: ['ned', 'pon', 'tor', 'sre', 'čet', 'pet', 'sob'],
    -  NARROWWEEKDAYS: ['n', 'p', 't', 's', 'č', 'p', 's'],
    -  STANDALONENARROWWEEKDAYS: ['n', 'p', 't', 's', 'č', 'p', 's'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1. četrtletje', '2. četrtletje', '3. četrtletje',
    -    '4. četrtletje'],
    -  AMPMS: ['dop.', 'pop.'],
    -  DATEFORMATS: ['EEEE, dd. MMMM y', 'dd. MMMM y', 'd. MMM y', 'd. MM. yy'],
    -  TIMEFORMATS: ['HH.mm.ss zzzz', 'HH.mm.ss z', 'HH.mm.ss', 'HH.mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale sq.
    - */
    -goog.i18n.DateTimeSymbols_sq = {
    -  ERAS: ['p.e.r.', 'e.r.'],
    -  ERANAMES: ['para erës së re', 'erës së re'],
    -  NARROWMONTHS: ['J', 'S', 'M', 'P', 'M', 'Q', 'K', 'G', 'S', 'T', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'S', 'M', 'P', 'M', 'Q', 'K', 'G', 'S', 'T',
    -    'N', 'D'],
    -  MONTHS: ['janar', 'shkurt', 'mars', 'prill', 'maj', 'qershor', 'korrik',
    -    'gusht', 'shtator', 'tetor', 'nëntor', 'dhjetor'],
    -  STANDALONEMONTHS: ['Janar', 'Shkurt', 'Mars', 'Prill', 'Maj', 'Qershor',
    -    'Korrik', 'Gusht', 'Shtator', 'Tetor', 'Nëntor', 'Dhjetor'],
    -  SHORTMONTHS: ['Jan', 'Shk', 'Mar', 'Pri', 'Maj', 'Qer', 'Kor', 'Gsh', 'Sht',
    -    'Tet', 'Nën', 'Dhj'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Shk', 'Mar', 'Pri', 'Maj', 'Qer', 'Kor',
    -    'Gsh', 'Sht', 'Tet', 'Nën', 'Dhj'],
    -  WEEKDAYS: ['e diel', 'e hënë', 'e martë', 'e mërkurë', 'e enjte',
    -    'e premte', 'e shtunë'],
    -  STANDALONEWEEKDAYS: ['E diel', 'E hënë', 'E martë', 'E mërkurë',
    -    'E enjte', 'E premte', 'E shtunë'],
    -  SHORTWEEKDAYS: ['Die', 'Hën', 'Mar', 'Mër', 'Enj', 'Pre', 'Sht'],
    -  STANDALONESHORTWEEKDAYS: ['Die', 'Hën', 'Mar', 'Mër', 'Enj', 'Pre', 'Sht'],
    -  NARROWWEEKDAYS: ['D', 'H', 'M', 'M', 'E', 'P', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'H', 'M', 'M', 'E', 'P', 'S'],
    -  SHORTQUARTERS: ['tremujori I', 'tremujori II', 'tremujori III',
    -    'tremujori IV'],
    -  QUARTERS: ['tremujori i parë', 'tremujori i dytë', 'tremujori i tretë',
    -    'tremujori i katërt'],
    -  AMPMS: ['paradite', 'pasdite'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'd.M.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'në\' {0}', '{1} \'në\' {0}', '{1}, {0}',
    -    '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale sr.
    - */
    -goog.i18n.DateTimeSymbols_sr = {
    -  ERAS: ['п. н. е.', 'н. е.'],
    -  ERANAMES: ['Пре нове ере', 'Нове ере'],
    -  NARROWMONTHS: ['ј', 'ф', 'м', 'а', 'м', 'ј', 'ј', 'а', 'с', 'о',
    -    'н', 'д'],
    -  STANDALONENARROWMONTHS: ['ј', 'ф', 'м', 'а', 'м', 'ј', 'ј', 'а', 'с',
    -    'о', 'н', 'д'],
    -  MONTHS: ['јануар', 'фебруар', 'март', 'април', 'мај',
    -    'јун', 'јул', 'август', 'септембар', 'октобар',
    -    'новембар', 'децембар'],
    -  STANDALONEMONTHS: ['јануар', 'фебруар', 'март', 'април',
    -    'мај', 'јун', 'јул', 'август', 'септембар',
    -    'октобар', 'новембар', 'децембар'],
    -  SHORTMONTHS: ['јан', 'феб', 'мар', 'апр', 'мај', 'јун',
    -    'јул', 'авг', 'сеп', 'окт', 'нов', 'дец'],
    -  STANDALONESHORTMONTHS: ['јан', 'феб', 'мар', 'апр', 'мај',
    -    'јун', 'јул', 'авг', 'сеп', 'окт', 'нов', 'дец'],
    -  WEEKDAYS: ['недеља', 'понедељак', 'уторак', 'среда',
    -    'четвртак', 'петак', 'субота'],
    -  STANDALONEWEEKDAYS: ['недеља', 'понедељак', 'уторак',
    -    'среда', 'четвртак', 'петак', 'субота'],
    -  SHORTWEEKDAYS: ['нед', 'пон', 'уто', 'сре', 'чет', 'пет',
    -    'суб'],
    -  STANDALONESHORTWEEKDAYS: ['нед', 'пон', 'уто', 'сре', 'чет',
    -    'пет', 'суб'],
    -  NARROWWEEKDAYS: ['н', 'п', 'у', 'с', 'ч', 'п', 'с'],
    -  STANDALONENARROWWEEKDAYS: ['н', 'п', 'у', 'с', 'ч', 'п', 'с'],
    -  SHORTQUARTERS: ['К1', 'К2', 'К3', 'К4'],
    -  QUARTERS: ['Прво тромесечје', 'Друго тромесечје',
    -    'Треће тромесечје', 'Четврто тромесечје'],
    -  AMPMS: ['пре подне', 'по подне'],
    -  DATEFORMATS: ['EEEE, dd. MMMM y.', 'dd. MMMM y.', 'dd.MM.y.', 'd.M.yy.'],
    -  TIMEFORMATS: ['HH.mm.ss zzzz', 'HH.mm.ss z', 'HH.mm.ss', 'HH.mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale sv.
    - */
    -goog.i18n.DateTimeSymbols_sv = {
    -  ERAS: ['f.Kr.', 'e.Kr.'],
    -  ERANAMES: ['före Kristus', 'efter Kristus'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['januari', 'februari', 'mars', 'april', 'maj', 'juni', 'juli',
    -    'augusti', 'september', 'oktober', 'november', 'december'],
    -  STANDALONEMONTHS: ['Januari', 'Februari', 'Mars', 'April', 'Maj', 'Juni',
    -    'Juli', 'Augusti', 'September', 'Oktober', 'November', 'December'],
    -  SHORTMONTHS: ['jan.', 'feb.', 'mars', 'apr.', 'maj', 'juni', 'juli', 'aug.',
    -    'sep.', 'okt.', 'nov.', 'dec.'],
    -  STANDALONESHORTMONTHS: ['Jan.', 'Feb.', 'Mars', 'Apr.', 'Maj', 'Juni', 'Juli',
    -    'Aug.', 'Sep.', 'Okt.', 'Nov.', 'Dec.'],
    -  WEEKDAYS: ['söndag', 'måndag', 'tisdag', 'onsdag', 'torsdag', 'fredag',
    -    'lördag'],
    -  STANDALONEWEEKDAYS: ['Söndag', 'Måndag', 'Tisdag', 'Onsdag', 'Torsdag',
    -    'Fredag', 'Lördag'],
    -  SHORTWEEKDAYS: ['sön', 'mån', 'tis', 'ons', 'tors', 'fre', 'lör'],
    -  STANDALONESHORTWEEKDAYS: ['Sön', 'Mån', 'Tis', 'Ons', 'Tor', 'Fre', 'Lör'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'O', 'T', 'F', 'L'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'O', 'T', 'F', 'L'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['1:a kvartalet', '2:a kvartalet', '3:e kvartalet',
    -    '4:e kvartalet'],
    -  AMPMS: ['fm', 'em'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'y-MM-dd'],
    -  TIMEFORMATS: ['\'kl\'. HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale sw.
    - */
    -goog.i18n.DateTimeSymbols_sw = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Kabla ya Kristo', 'Baada ya Kristo'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni', 'Julai',
    -    'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    -  STANDALONEMONTHS: ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni',
    -    'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep',
    -    'Okt', 'Nov', 'Des'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul',
    -    'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
    -  WEEKDAYS: ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alhamisi',
    -    'Ijumaa', 'Jumamosi'],
    -  STANDALONEWEEKDAYS: ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano',
    -    'Alhamisi', 'Ijumaa', 'Jumamosi'],
    -  SHORTWEEKDAYS: ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alhamisi',
    -    'Ijumaa', 'Jumamosi'],
    -  STANDALONESHORTWEEKDAYS: ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano',
    -    'Alhamisi', 'Ijumaa', 'Jumamosi'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Robo ya 1', 'Robo ya 2', 'Robo ya 3', 'Robo ya 4'],
    -  QUARTERS: ['Robo ya 1', 'Robo ya 2', 'Robo ya 3', 'Robo ya 4'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ta.
    - */
    -goog.i18n.DateTimeSymbols_ta = {
    -  ERAS: ['கி.மு.', 'கி.பி.'],
    -  ERANAMES: ['கிறிஸ்துவுக்கு முன்',
    -    'அனோ டோமினி'],
    -  NARROWMONTHS: ['ஜ', 'பி', 'மா', 'ஏ', 'மே', 'ஜூ', 'ஜூ',
    -    'ஆ', 'செ', 'அ', 'ந', 'டி'],
    -  STANDALONENARROWMONTHS: ['ஜ', 'பி', 'மா', 'ஏ', 'மே', 'ஜூ',
    -    'ஜூ', 'ஆ', 'செ', 'அ', 'ந', 'டி'],
    -  MONTHS: ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்',
    -    'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை',
    -    'ஆகஸ்ட்', 'செப்டம்பர்',
    -    'அக்டோபர்', 'நவம்பர்',
    -    'டிசம்பர்'],
    -  STANDALONEMONTHS: ['ஜனவரி', 'பிப்ரவரி',
    -    'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்',
    -    'ஜூலை', 'ஆகஸ்டு', 'செப்டம்பர்',
    -    'அக்டோபர்', 'நவம்பர்',
    -    'டிசம்பர்'],
    -  SHORTMONTHS: ['ஜன.', 'பிப்.', 'மார்.', 'ஏப்.',
    -    'மே', 'ஜூன்', 'ஜூலை', 'ஆக.', 'செப்.',
    -    'அக்.', 'நவ.', 'டிச.'],
    -  STANDALONESHORTMONTHS: ['ஜன.', 'பிப்.', 'மார்.',
    -    'ஏப்.', 'மே', 'ஜூன்', 'ஜூலை', 'ஆக.',
    -    'செப்.', 'அக்.', 'நவ.', 'டிச.'],
    -  WEEKDAYS: ['ஞாயிறு', 'திங்கள்',
    -    'செவ்வாய்', 'புதன்', 'வியாழன்',
    -    'வெள்ளி', 'சனி'],
    -  STANDALONEWEEKDAYS: ['ஞாயிறு', 'திங்கள்',
    -    'செவ்வாய்', 'புதன்', 'வியாழன்',
    -    'வெள்ளி', 'சனி'],
    -  SHORTWEEKDAYS: ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ',
    -    'ச'],
    -  STANDALONESHORTWEEKDAYS: ['ஞா', 'தி', 'செ', 'பு', 'வி',
    -    'வெ', 'ச'],
    -  NARROWWEEKDAYS: ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ',
    -    'ச'],
    -  STANDALONENARROWWEEKDAYS: ['ஞா', 'தி', 'செ', 'பு', 'வி',
    -    'வெ', 'ச'],
    -  SHORTQUARTERS: ['காலாண்டு1', 'காலாண்டு2',
    -    'காலாண்டு3', 'காலாண்டு4'],
    -  QUARTERS: ['முதல் காலாண்டு',
    -    'இரண்டாம் காலாண்டு',
    -    'மூன்றாம் காலாண்டு',
    -    'நான்காம் காலாண்டு'],
    -  AMPMS: ['முற்பகல்', 'பிற்பகல்'],
    -  DATEFORMATS: ['EEEE, d MMMM, y', 'd MMMM, y', 'd MMM, y', 'd-M-yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} ’அன்று’ {0}',
    -    '{1} ’அன்று’ {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [6, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale te.
    - */
    -goog.i18n.DateTimeSymbols_te = {
    -  ERAS: ['క్రీపూ', 'క్రీశ'],
    -  ERANAMES: ['క్రీస్తు పూర్వం',
    -    'క్రీస్తు శకం'],
    -  NARROWMONTHS: ['జ', 'ఫి', 'మా', 'ఏ', 'మే', 'జూ', 'జు',
    -    'ఆ', 'సె', 'అ', 'న', 'డి'],
    -  STANDALONENARROWMONTHS: ['జ', 'ఫి', 'మా', 'ఏ', 'మే', 'జూ',
    -    'జు', 'ఆ', 'సె', 'అ', 'న', 'డి'],
    -  MONTHS: ['జనవరి', 'ఫిబ్రవరి', 'మార్చి',
    -    'ఏప్రిల్', 'మే', 'జూన్', 'జులై',
    -    'ఆగస్టు', 'సెప్టెంబర్',
    -    'అక్టోబర్', 'నవంబర్',
    -    'డిసెంబర్'],
    -  STANDALONEMONTHS: ['జనవరి', 'ఫిబ్రవరి',
    -    'మార్చి', 'ఏప్రిల్', 'మే', 'జూన్',
    -    'జులై', 'ఆగస్టు', 'సెప్టెంబర్',
    -    'అక్టోబర్', 'నవంబర్',
    -    'డిసెంబర్'],
    -  SHORTMONTHS: ['జన', 'ఫిబ్ర', 'మార్చి',
    -    'ఏప్రి', 'మే', 'జూన్', 'జులై', 'ఆగ',
    -    'సెప్టెం', 'అక్టో', 'నవం', 'డిసెం'],
    -  STANDALONESHORTMONTHS: ['జన', 'ఫిబ్ర', 'మార్చి',
    -    'ఏప్రి', 'మే', 'జూన్', 'జులై',
    -    'ఆగస్టు', 'సెప్టెం', 'అక్టో',
    -    'నవం', 'డిసెం'],
    -  WEEKDAYS: ['ఆదివారం', 'సోమవారం',
    -    'మంగళవారం', 'బుధవారం',
    -    'గురువారం', 'శుక్రవారం',
    -    'శనివారం'],
    -  STANDALONEWEEKDAYS: ['ఆదివారం', 'సోమవారం',
    -    'మంగళవారం', 'బుధవారం',
    -    'గురువారం', 'శుక్రవారం',
    -    'శనివారం'],
    -  SHORTWEEKDAYS: ['ఆది', 'సోమ', 'మంగళ', 'బుధ',
    -    'గురు', 'శుక్ర', 'శని'],
    -  STANDALONESHORTWEEKDAYS: ['ఆది', 'సోమ', 'మంగళ',
    -    'బుధ', 'గురు', 'శుక్ర', 'శని'],
    -  NARROWWEEKDAYS: ['ఆ', 'సో', 'మ', 'బు', 'గు', 'శు', 'శ'],
    -  STANDALONENARROWWEEKDAYS: ['ఆ', 'సో', 'మ', 'బు', 'గు',
    -    'శు', 'శ'],
    -  SHORTQUARTERS: ['త్రై1', 'త్రై2', 'త్రై3',
    -    'త్రై4'],
    -  QUARTERS: ['1వ త్రైమాసం', '2వ త్రైమాసం',
    -    '3వ త్రైమాసం', '4వ త్రైమాసం'],
    -  AMPMS: ['[AM]', '[PM]'],
    -  DATEFORMATS: ['d, MMMM y, EEEE', 'd MMMM, y', 'd MMM, y', 'dd-MM-yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [6, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale th.
    - */
    -goog.i18n.DateTimeSymbols_th = {
    -  ERAS: ['ปีก่อน ค.ศ.', 'ค.ศ.'],
    -  ERANAMES: ['ปีก่อนคริสต์ศักราช',
    -    'คริสต์ศักราช'],
    -  NARROWMONTHS: ['ม.ค.', 'ก.พ.', 'มี.ค.', 'เม.ย.',
    -    'พ.ค.', 'มิ.ย.', 'ก.ค.', 'ส.ค.', 'ก.ย.', 'ต.ค.',
    -    'พ.ย.', 'ธ.ค.'],
    -  STANDALONENARROWMONTHS: ['ม.ค.', 'ก.พ.', 'มี.ค.', 'เม.ย.',
    -    'พ.ค.', 'มิ.ย.', 'ก.ค.', 'ส.ค.', 'ก.ย.', 'ต.ค.',
    -    'พ.ย.', 'ธ.ค.'],
    -  MONTHS: ['มกราคม', 'กุมภาพันธ์',
    -    'มีนาคม', 'เมษายน', 'พฤษภาคม',
    -    'มิถุนายน', 'กรกฎาคม',
    -    'สิงหาคม', 'กันยายน', 'ตุลาคม',
    -    'พฤศจิกายน', 'ธันวาคม'],
    -  STANDALONEMONTHS: ['มกราคม', 'กุมภาพันธ์',
    -    'มีนาคม', 'เมษายน', 'พฤษภาคม',
    -    'มิถุนายน', 'กรกฎาคม',
    -    'สิงหาคม', 'กันยายน', 'ตุลาคม',
    -    'พฤศจิกายน', 'ธันวาคม'],
    -  SHORTMONTHS: ['ม.ค.', 'ก.พ.', 'มี.ค.', 'เม.ย.',
    -    'พ.ค.', 'มิ.ย.', 'ก.ค.', 'ส.ค.', 'ก.ย.', 'ต.ค.',
    -    'พ.ย.', 'ธ.ค.'],
    -  STANDALONESHORTMONTHS: ['ม.ค.', 'ก.พ.', 'มี.ค.', 'เม.ย.',
    -    'พ.ค.', 'มิ.ย.', 'ก.ค.', 'ส.ค.', 'ก.ย.', 'ต.ค.',
    -    'พ.ย.', 'ธ.ค.'],
    -  WEEKDAYS: ['วันอาทิตย์', 'วันจันทร์',
    -    'วันอังคาร', 'วันพุธ',
    -    'วันพฤหัสบดี', 'วันศุกร์',
    -    'วันเสาร์'],
    -  STANDALONEWEEKDAYS: ['วันอาทิตย์',
    -    'วันจันทร์', 'วันอังคาร',
    -    'วันพุธ', 'วันพฤหัสบดี',
    -    'วันศุกร์', 'วันเสาร์'],
    -  SHORTWEEKDAYS: ['อา.', 'จ.', 'อ.', 'พ.', 'พฤ.', 'ศ.', 'ส.'],
    -  STANDALONESHORTWEEKDAYS: ['อา.', 'จ.', 'อ.', 'พ.', 'พฤ.',
    -    'ศ.', 'ส.'],
    -  NARROWWEEKDAYS: ['อา', 'จ', 'อ', 'พ', 'พฤ', 'ศ', 'ส'],
    -  STANDALONENARROWWEEKDAYS: ['อา', 'จ', 'อ', 'พ', 'พฤ', 'ศ',
    -    'ส'],
    -  SHORTQUARTERS: ['ไตรมาส 1', 'ไตรมาส 2',
    -    'ไตรมาส 3', 'ไตรมาส 4'],
    -  QUARTERS: ['ไตรมาส 1', 'ไตรมาส 2',
    -    'ไตรมาส 3', 'ไตรมาส 4'],
    -  AMPMS: ['ก่อนเที่ยง', 'หลังเที่ยง'],
    -  DATEFORMATS: ['EEEEที่ d MMMM G y', 'd MMMM G y', 'd MMM y', 'd/M/yy'],
    -  TIMEFORMATS: [
    -    'H นาฬิกา mm นาที ss วินาที zzzz',
    -    'H นาฬิกา mm นาที ss วินาที z', 'HH:mm:ss',
    -    'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale tl.
    - */
    -goog.i18n.DateTimeSymbols_tl = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['BC', 'AD'],
    -  NARROWMONTHS: ['E', 'P', 'M', 'A', 'M', 'H', 'H', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['E', 'P', 'M', 'A', 'M', 'H', 'H', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Enero', 'Pebrero', 'Marso', 'Abril', 'Mayo', 'Hunyo', 'Hulyo',
    -    'Agosto', 'Setyembre', 'Oktubre', 'Nobyembre', 'Disyembre'],
    -  STANDALONEMONTHS: ['Enero', 'Pebrero', 'Marso', 'Abril', 'Mayo', 'Hunyo',
    -    'Hulyo', 'Agosto', 'Setyembre', 'Oktubre', 'Nobyembre', 'Disyembre'],
    -  SHORTMONTHS: ['Ene', 'Peb', 'Mar', 'Abr', 'May', 'Hun', 'Hul', 'Ago', 'Set',
    -    'Okt', 'Nob', 'Dis'],
    -  STANDALONESHORTMONTHS: ['Ene', 'Peb', 'Mar', 'Abr', 'May', 'Hun', 'Hul',
    -    'Ago', 'Set', 'Okt', 'Nob', 'Dis'],
    -  WEEKDAYS: ['Linggo', 'Lunes', 'Martes', 'Miyerkules', 'Huwebes', 'Biyernes',
    -    'Sabado'],
    -  STANDALONEWEEKDAYS: ['Linggo', 'Lunes', 'Martes', 'Miyerkules', 'Huwebes',
    -    'Biyernes', 'Sabado'],
    -  SHORTWEEKDAYS: ['Lin', 'Lun', 'Mar', 'Miy', 'Huw', 'Biy', 'Sab'],
    -  STANDALONESHORTWEEKDAYS: ['Lin', 'Lun', 'Mar', 'Miy', 'Huw', 'Biy', 'Sab'],
    -  NARROWWEEKDAYS: ['L', 'L', 'M', 'M', 'H', 'B', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['L', 'L', 'M', 'M', 'H', 'B', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['ika-1 quarter', 'ika-2 quarter', 'ika-3 quarter',
    -    'ika-4 na quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'nang\' {0}', '{1} \'nang\' {0}', '{1}, {0}',
    -    '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale tr.
    - */
    -goog.i18n.DateTimeSymbols_tr = {
    -  ERAS: ['MÖ', 'MS'],
    -  ERANAMES: ['Milattan Önce', 'Milattan Sonra'],
    -  NARROWMONTHS: ['O', 'Ş', 'M', 'N', 'M', 'H', 'T', 'A', 'E', 'E', 'K', 'A'],
    -  STANDALONENARROWMONTHS: ['O', 'Ş', 'M', 'N', 'M', 'H', 'T', 'A', 'E', 'E',
    -    'K', 'A'],
    -  MONTHS: ['Ocak', 'Şubat', 'Mart', 'Nisan', 'Mayıs', 'Haziran', 'Temmuz',
    -    'Ağustos', 'Eylül', 'Ekim', 'Kasım', 'Aralık'],
    -  STANDALONEMONTHS: ['Ocak', 'Şubat', 'Mart', 'Nisan', 'Mayıs', 'Haziran',
    -    'Temmuz', 'Ağustos', 'Eylül', 'Ekim', 'Kasım', 'Aralık'],
    -  SHORTMONTHS: ['Oca', 'Şub', 'Mar', 'Nis', 'May', 'Haz', 'Tem', 'Ağu', 'Eyl',
    -    'Eki', 'Kas', 'Ara'],
    -  STANDALONESHORTMONTHS: ['Oca', 'Şub', 'Mar', 'Nis', 'May', 'Haz', 'Tem',
    -    'Ağu', 'Eyl', 'Eki', 'Kas', 'Ara'],
    -  WEEKDAYS: ['Pazar', 'Pazartesi', 'Salı', 'Çarşamba', 'Perşembe', 'Cuma',
    -    'Cumartesi'],
    -  STANDALONEWEEKDAYS: ['Pazar', 'Pazartesi', 'Salı', 'Çarşamba', 'Perşembe',
    -    'Cuma', 'Cumartesi'],
    -  SHORTWEEKDAYS: ['Paz', 'Pzt', 'Sal', 'Çar', 'Per', 'Cum', 'Cmt'],
    -  STANDALONESHORTWEEKDAYS: ['Paz', 'Pzt', 'Sal', 'Çar', 'Per', 'Cum', 'Cmt'],
    -  NARROWWEEKDAYS: ['P', 'P', 'S', 'Ç', 'P', 'C', 'C'],
    -  STANDALONENARROWWEEKDAYS: ['P', 'P', 'S', 'Ç', 'P', 'C', 'C'],
    -  SHORTQUARTERS: ['Ç1', 'Ç2', 'Ç3', 'Ç4'],
    -  QUARTERS: ['1. çeyrek', '2. çeyrek', '3. çeyrek', '4. çeyrek'],
    -  AMPMS: ['ÖÖ', 'ÖS'],
    -  DATEFORMATS: ['d MMMM y EEEE', 'd MMMM y', 'd MMM y', 'd MM y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale uk.
    - */
    -goog.i18n.DateTimeSymbols_uk = {
    -  ERAS: ['до н.е.', 'н.е.'],
    -  ERANAMES: ['до нашої ери', 'нашої ери'],
    -  NARROWMONTHS: ['С', 'Л', 'Б', 'К', 'Т', 'Ч', 'Л', 'С', 'В', 'Ж',
    -    'Л', 'Г'],
    -  STANDALONENARROWMONTHS: ['С', 'Л', 'Б', 'К', 'Т', 'Ч', 'Л', 'С', 'В',
    -    'Ж', 'Л', 'Г'],
    -  MONTHS: ['січня', 'лютого', 'березня', 'квітня',
    -    'травня', 'червня', 'липня', 'серпня',
    -    'вересня', 'жовтня', 'листопада', 'грудня'],
    -  STANDALONEMONTHS: ['Січень', 'Лютий', 'Березень',
    -    'Квітень', 'Травень', 'Червень', 'Липень',
    -    'Серпень', 'Вересень', 'Жовтень', 'Листопад',
    -    'Грудень'],
    -  SHORTMONTHS: ['січ.', 'лют.', 'бер.', 'квіт.', 'трав.',
    -    'черв.', 'лип.', 'серп.', 'вер.', 'жовт.', 'лист.',
    -    'груд.'],
    -  STANDALONESHORTMONTHS: ['Січ', 'Лют', 'Бер', 'Кві', 'Тра',
    -    'Чер', 'Лип', 'Сер', 'Вер', 'Жов', 'Лис', 'Гру'],
    -  WEEKDAYS: ['неділя', 'понеділок', 'вівторок',
    -    'середа', 'четвер', 'пʼятниця', 'субота'],
    -  STANDALONEWEEKDAYS: ['Неділя', 'Понеділок', 'Вівторок',
    -    'Середа', 'Четвер', 'Пʼятниця', 'Субота'],
    -  SHORTWEEKDAYS: ['Нд', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'],
    -  STANDALONESHORTWEEKDAYS: ['Нд', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт',
    -    'Сб'],
    -  NARROWWEEKDAYS: ['Н', 'П', 'В', 'С', 'Ч', 'П', 'С'],
    -  STANDALONENARROWWEEKDAYS: ['Н', 'П', 'В', 'С', 'Ч', 'П', 'С'],
    -  SHORTQUARTERS: ['I кв.', 'II кв.', 'III кв.', 'IV кв.'],
    -  QUARTERS: ['I квартал', 'II квартал', 'III квартал',
    -    'IV квартал'],
    -  AMPMS: ['дп', 'пп'],
    -  DATEFORMATS: ['EEEE, d MMMM y \'р\'.', 'd MMMM y \'р\'.', 'd MMM y \'р\'.',
    -    'dd.MM.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ur.
    - */
    -goog.i18n.DateTimeSymbols_ur = {
    -  ERAS: ['ق م', 'عیسوی سن'],
    -  ERANAMES: ['قبل مسیح', 'عیسوی سن'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئی',
    -    'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر',
    -    'نومبر', 'دسمبر'],
    -  STANDALONEMONTHS: ['جنوری', 'فروری', 'مارچ', 'اپریل',
    -    'مئی', 'جون', 'جولائی', 'اگست', 'ستمبر',
    -    'اکتوبر', 'نومبر', 'دسمبر'],
    -  SHORTMONTHS: ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئی',
    -    'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر',
    -    'نومبر', 'دسمبر'],
    -  STANDALONESHORTMONTHS: ['جنوری', 'فروری', 'مارچ', 'اپریل',
    -    'مئی', 'جون', 'جولائی', 'اگست', 'ستمبر',
    -    'اکتوبر', 'نومبر', 'دسمبر'],
    -  WEEKDAYS: ['اتوار', 'سوموار', 'منگل', 'بدھ', 'جمعرات',
    -    'جمعہ', 'ہفتہ'],
    -  STANDALONEWEEKDAYS: ['اتوار', 'سوموار', 'منگل', 'بدھ',
    -    'جمعرات', 'جمعہ', 'ہفتہ'],
    -  SHORTWEEKDAYS: ['اتوار', 'سوموار', 'منگل', 'بدھ',
    -    'جمعرات', 'جمعہ', 'ہفتہ'],
    -  STANDALONESHORTWEEKDAYS: ['اتوار', 'سوموار', 'منگل', 'بدھ',
    -    'جمعرات', 'جمعہ', 'ہفتہ'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['پہلی سہ ماہی', 'دوسری سہ ماہی',
    -    'تیسری سہ ماہی', 'چوتهی سہ ماہی'],
    -  QUARTERS: ['پہلی سہ ماہی', 'دوسری سہ ماہی',
    -    'تیسری سہ ماہی', 'چوتهی سہ ماہی'],
    -  AMPMS: ['قبل دوپہر', 'بعد دوپہر'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'd MMM، y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale uz.
    - */
    -goog.i18n.DateTimeSymbols_uz = {
    -  ERAS: ['M.A.', 'E'],
    -  ERANAMES: ['M.A.', 'E'],
    -  NARROWMONTHS: ['Y', 'F', 'M', 'A', 'M', 'I', 'I', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['Y', 'F', 'M', 'A', 'M', 'I', 'I', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Yanvar', 'Fevral', 'Mart', 'Aprel', 'May', 'Iyun', 'Iyul', 'Avgust',
    -    'Sentabr', 'Oktabr', 'Noyabr', 'Dekabr'],
    -  STANDALONEMONTHS: ['Yanvar', 'Fevral', 'Mart', 'Aprel', 'May', 'Iyun', 'Iyul',
    -    'Avgust', 'Sentabr', 'Oktabr', 'Noyabr', 'Dekabr'],
    -  SHORTMONTHS: ['Yanv', 'Fev', 'Mar', 'Apr', 'May', 'Iyun', 'Iyul', 'Avg',
    -    'Sen', 'Okt', 'Noya', 'Dek'],
    -  STANDALONESHORTMONTHS: ['Yanv', 'Fev', 'Mar', 'Apr', 'May', 'Iyun', 'Iyul',
    -    'Avg', 'Sen', 'Okt', 'Noya', 'Dek'],
    -  WEEKDAYS: ['yakshanba', 'dushanba', 'seshanba', 'chorshanba', 'payshanba',
    -    'juma', 'shanba'],
    -  STANDALONEWEEKDAYS: ['yakshanba', 'dushanba', 'seshanba', 'chorshanba',
    -    'payshanba', 'juma', 'shanba'],
    -  SHORTWEEKDAYS: ['Yaksh', 'Dush', 'Sesh', 'Chor', 'Pay', 'Jum', 'Shan'],
    -  STANDALONESHORTWEEKDAYS: ['Yaksh', 'Dush', 'Sesh', 'Chor', 'Pay', 'Jum',
    -    'Shan'],
    -  NARROWWEEKDAYS: ['Y', 'D', 'S', 'C', 'P', 'J', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['Y', 'D', 'S', 'C', 'P', 'J', 'S'],
    -  SHORTQUARTERS: ['1-ch', '2-ch', '3-ch', '4-ch'],
    -  QUARTERS: ['1-chorak', '2-chorak', '3-chorak', '4-chorak'],
    -  AMPMS: ['TO', 'TK'],
    -  DATEFORMATS: ['EEEE, y MMMM dd', 'y MMMM d', 'y MMM d', 'yy/MM/dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale vi.
    - */
    -goog.i18n.DateTimeSymbols_vi = {
    -  ERAS: ['tr. CN', 'sau CN'],
    -  ERANAMES: ['tr. CN', 'sau CN'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['tháng 1', 'tháng 2', 'tháng 3', 'tháng 4', 'tháng 5',
    -    'tháng 6', 'tháng 7', 'tháng 8', 'tháng 9', 'tháng 10', 'tháng 11',
    -    'tháng 12'],
    -  STANDALONEMONTHS: ['Tháng 1', 'Tháng 2', 'Tháng 3', 'Tháng 4', 'Tháng 5',
    -    'Tháng 6', 'Tháng 7', 'Tháng 8', 'Tháng 9', 'Tháng 10', 'Tháng 11',
    -    'Tháng 12'],
    -  SHORTMONTHS: ['thg 1', 'thg 2', 'thg 3', 'thg 4', 'thg 5', 'thg 6', 'thg 7',
    -    'thg 8', 'thg 9', 'thg 10', 'thg 11', 'thg 12'],
    -  STANDALONESHORTMONTHS: ['Thg 1', 'Thg 2', 'Thg 3', 'Thg 4', 'Thg 5', 'Thg 6',
    -    'Thg 7', 'Thg 8', 'Thg 9', 'Thg 10', 'Thg 11', 'Thg 12'],
    -  WEEKDAYS: ['Chủ Nhật', 'Thứ Hai', 'Thứ Ba', 'Thứ Tư', 'Thứ Năm',
    -    'Thứ Sáu', 'Thứ Bảy'],
    -  STANDALONEWEEKDAYS: ['Chủ Nhật', 'Thứ Hai', 'Thứ Ba', 'Thứ Tư',
    -    'Thứ Năm', 'Thứ Sáu', 'Thứ Bảy'],
    -  SHORTWEEKDAYS: ['CN', 'Th 2', 'Th 3', 'Th 4', 'Th 5', 'Th 6', 'Th 7'],
    -  STANDALONESHORTWEEKDAYS: ['CN', 'Th 2', 'Th 3', 'Th 4', 'Th 5', 'Th 6',
    -    'Th 7'],
    -  NARROWWEEKDAYS: ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'],
    -  STANDALONENARROWWEEKDAYS: ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Quý 1', 'Quý 2', 'Quý 3', 'Quý 4'],
    -  AMPMS: ['SA', 'CH'],
    -  DATEFORMATS: ['EEEE, \'ngày\' dd MMMM \'năm\' y',
    -    '\'Ngày\' dd \'tháng\' MM \'năm\' y', 'dd-MM-y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{0} {1}', '{0} {1}', '{0} {1}', '{0} {1}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale zh.
    - */
    -goog.i18n.DateTimeSymbols_zh = {
    -  ERAS: ['公元前', '公元'],
    -  ERANAMES: ['公元前', '公元'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['一月', '二月', '三月', '四月', '五月', '六月', '七月',
    -    '八月', '九月', '十月', '十一月', '十二月'],
    -  STANDALONEMONTHS: ['一月', '二月', '三月', '四月', '五月', '六月',
    -    '七月', '八月', '九月', '十月', '十一月', '十二月'],
    -  SHORTMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月',
    -    '9月', '10月', '11月', '12月'],
    -  STANDALONESHORTMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月',
    -    '7月', '8月', '9月', '10月', '11月', '12月'],
    -  WEEKDAYS: ['星期日', '星期一', '星期二', '星期三', '星期四',
    -    '星期五', '星期六'],
    -  STANDALONEWEEKDAYS: ['星期日', '星期一', '星期二', '星期三',
    -    '星期四', '星期五', '星期六'],
    -  SHORTWEEKDAYS: ['周日', '周一', '周二', '周三', '周四', '周五',
    -    '周六'],
    -  STANDALONESHORTWEEKDAYS: ['周日', '周一', '周二', '周三', '周四',
    -    '周五', '周六'],
    -  NARROWWEEKDAYS: ['日', '一', '二', '三', '四', '五', '六'],
    -  STANDALONENARROWWEEKDAYS: ['日', '一', '二', '三', '四', '五', '六'],
    -  SHORTQUARTERS: ['1季度', '2季度', '3季度', '4季度'],
    -  QUARTERS: ['第一季度', '第二季度', '第三季度', '第四季度'],
    -  AMPMS: ['上午', '下午'],
    -  DATEFORMATS: ['y年M月d日EEEE', 'y年M月d日', 'y年M月d日', 'yy/M/d'],
    -  TIMEFORMATS: ['zzzzah:mm:ss', 'zah:mm:ss', 'ah:mm:ss', 'ah:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale zh_CN.
    - */
    -goog.i18n.DateTimeSymbols_zh_CN = goog.i18n.DateTimeSymbols_zh;
    -
    -
    -/**
    - * Date/time formatting symbols for locale zh_HK.
    - */
    -goog.i18n.DateTimeSymbols_zh_HK = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['公元前', '公元'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月',
    -    '9月', '10月', '11月', '12月'],
    -  STANDALONEMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月', '7月',
    -    '8月', '9月', '10月', '11月', '12月'],
    -  SHORTMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月',
    -    '9月', '10月', '11月', '12月'],
    -  STANDALONESHORTMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月',
    -    '7月', '8月', '9月', '10月', '11月', '12月'],
    -  WEEKDAYS: ['星期日', '星期一', '星期二', '星期三', '星期四',
    -    '星期五', '星期六'],
    -  STANDALONEWEEKDAYS: ['星期日', '星期一', '星期二', '星期三',
    -    '星期四', '星期五', '星期六'],
    -  SHORTWEEKDAYS: ['週日', '週一', '週二', '週三', '週四', '週五',
    -    '週六'],
    -  STANDALONESHORTWEEKDAYS: ['週日', '週一', '週二', '週三', '週四',
    -    '週五', '週六'],
    -  NARROWWEEKDAYS: ['日', '一', '二', '三', '四', '五', '六'],
    -  STANDALONENARROWWEEKDAYS: ['日', '一', '二', '三', '四', '五', '六'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['第1季', '第2季', '第3季', '第4季'],
    -  AMPMS: ['上午', '下午'],
    -  DATEFORMATS: ['y年M月d日EEEE', 'y年M月d日', 'y年M月d日', 'd/M/yy'],
    -  TIMEFORMATS: ['ah:mm:ss [zzzz]', 'ah:mm:ss [z]', 'ah:mm:ss', 'ah:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale zh_TW.
    - */
    -goog.i18n.DateTimeSymbols_zh_TW = {
    -  ERAS: ['西元前', '西元'],
    -  ERANAMES: ['西元前', '西元'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月',
    -    '9月', '10月', '11月', '12月'],
    -  STANDALONEMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月', '7月',
    -    '8月', '9月', '10月', '11月', '12月'],
    -  SHORTMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月',
    -    '9月', '10月', '11月', '12月'],
    -  STANDALONESHORTMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月',
    -    '7月', '8月', '9月', '10月', '11月', '12月'],
    -  WEEKDAYS: ['星期日', '星期一', '星期二', '星期三', '星期四',
    -    '星期五', '星期六'],
    -  STANDALONEWEEKDAYS: ['星期日', '星期一', '星期二', '星期三',
    -    '星期四', '星期五', '星期六'],
    -  SHORTWEEKDAYS: ['週日', '週一', '週二', '週三', '週四', '週五',
    -    '週六'],
    -  STANDALONESHORTWEEKDAYS: ['週日', '週一', '週二', '週三', '週四',
    -    '週五', '週六'],
    -  NARROWWEEKDAYS: ['日', '一', '二', '三', '四', '五', '六'],
    -  STANDALONENARROWWEEKDAYS: ['日', '一', '二', '三', '四', '五', '六'],
    -  SHORTQUARTERS: ['1季', '2季', '3季', '4季'],
    -  QUARTERS: ['第1季', '第2季', '第3季', '第4季'],
    -  AMPMS: ['上午', '下午'],
    -  DATEFORMATS: ['y年M月d日 EEEE', 'y年M月d日', 'y年M月d日', 'y/M/d'],
    -  TIMEFORMATS: ['ah:mm:ss [zzzz]', 'ah:mm:ss [z]', 'ah:mm:ss', 'ah:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale zu.
    - */
    -goog.i18n.DateTimeSymbols_zu = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['BC', 'AD'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januwari', 'Februwari', 'Mashi', 'Apreli', 'Meyi', 'Juni', 'Julayi',
    -    'Agasti', 'Septhemba', 'Okthoba', 'Novemba', 'Disemba'],
    -  STANDALONEMONTHS: ['Januwari', 'Februwari', 'Mashi', 'Apreli', 'Meyi', 'Juni',
    -    'Julayi', 'Agasti', 'Septhemba', 'Okthoba', 'Novemba', 'Disemba'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mas', 'Apr', 'Mey', 'Jun', 'Jul', 'Aga', 'Sep',
    -    'Okt', 'Nov', 'Dis'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mas', 'Apr', 'Mey', 'Jun', 'Jul',
    -    'Aga', 'Sep', 'Okt', 'Nov', 'Dis'],
    -  WEEKDAYS: ['Sonto', 'Msombuluko', 'Lwesibili', 'Lwesithathu', 'Lwesine',
    -    'Lwesihlanu', 'Mgqibelo'],
    -  STANDALONEWEEKDAYS: ['Sonto', 'Msombuluko', 'Lwesibili', 'Lwesithathu',
    -    'Lwesine', 'Lwesihlanu', 'Mgqibelo'],
    -  SHORTWEEKDAYS: ['Son', 'Mso', 'Bil', 'Tha', 'Sin', 'Hla', 'Mgq'],
    -  STANDALONESHORTWEEKDAYS: ['Son', 'Mso', 'Bil', 'Tha', 'Sin', 'Hla', 'Mgq'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'T', 'S', 'H', 'M'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'B', 'T', 'S', 'H', 'M'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['ikota engu-1', 'ikota engu-2', 'ikota engu-3', 'ikota engu-4'],
    -  AMPMS: ['Ekuseni', 'Ntambama'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Selected date/time formatting symbols by locale.
    - * "switch" statement won't work here. JsCompiler cannot handle it yet.
    - */
    -if (goog.LOCALE == 'af') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_af;
    -} else if (goog.LOCALE == 'am') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_am;
    -} else if (goog.LOCALE == 'ar') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar;
    -} else if (goog.LOCALE == 'az') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_az;
    -} else if (goog.LOCALE == 'bg') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_bg;
    -} else if (goog.LOCALE == 'bn') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_bn;
    -} else if (goog.LOCALE == 'br') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_br;
    -} else if (goog.LOCALE == 'ca') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ca;
    -} else if (goog.LOCALE == 'chr') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_chr;
    -} else if (goog.LOCALE == 'cs') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_cs;
    -} else if (goog.LOCALE == 'cy') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_cy;
    -} else if (goog.LOCALE == 'da') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_da;
    -} else if (goog.LOCALE == 'de') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de;
    -} else if (goog.LOCALE == 'de_AT' || goog.LOCALE == 'de-AT') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de_AT;
    -} else if (goog.LOCALE == 'de_CH' || goog.LOCALE == 'de-CH') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de;
    -} else if (goog.LOCALE == 'el') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_el;
    -} else if (goog.LOCALE == 'en') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en;
    -} else if (goog.LOCALE == 'en_AU' || goog.LOCALE == 'en-AU') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_AU;
    -} else if (goog.LOCALE == 'en_GB' || goog.LOCALE == 'en-GB') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_GB;
    -} else if (goog.LOCALE == 'en_IE' || goog.LOCALE == 'en-IE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_IE;
    -} else if (goog.LOCALE == 'en_IN' || goog.LOCALE == 'en-IN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_IN;
    -} else if (goog.LOCALE == 'en_SG' || goog.LOCALE == 'en-SG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_SG;
    -} else if (goog.LOCALE == 'en_US' || goog.LOCALE == 'en-US') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en;
    -} else if (goog.LOCALE == 'en_ZA' || goog.LOCALE == 'en-ZA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_ZA;
    -} else if (goog.LOCALE == 'es') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es;
    -} else if (goog.LOCALE == 'es_419' || goog.LOCALE == 'es-419') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_419;
    -} else if (goog.LOCALE == 'es_ES' || goog.LOCALE == 'es-ES') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es;
    -} else if (goog.LOCALE == 'et') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_et;
    -} else if (goog.LOCALE == 'eu') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_eu;
    -} else if (goog.LOCALE == 'fa') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fa;
    -} else if (goog.LOCALE == 'fi') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fi;
    -} else if (goog.LOCALE == 'fil') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fil;
    -} else if (goog.LOCALE == 'fr') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr;
    -} else if (goog.LOCALE == 'fr_CA' || goog.LOCALE == 'fr-CA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_CA;
    -} else if (goog.LOCALE == 'ga') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ga;
    -} else if (goog.LOCALE == 'gl') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_gl;
    -} else if (goog.LOCALE == 'gsw') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_gsw;
    -} else if (goog.LOCALE == 'gu') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_gu;
    -} else if (goog.LOCALE == 'haw') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_haw;
    -} else if (goog.LOCALE == 'he') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_he;
    -} else if (goog.LOCALE == 'hi') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_hi;
    -} else if (goog.LOCALE == 'hr') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_hr;
    -} else if (goog.LOCALE == 'hu') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_hu;
    -} else if (goog.LOCALE == 'hy') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_hy;
    -} else if (goog.LOCALE == 'id') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_id;
    -} else if (goog.LOCALE == 'in') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_in;
    -} else if (goog.LOCALE == 'is') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_is;
    -} else if (goog.LOCALE == 'it') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_it;
    -} else if (goog.LOCALE == 'iw') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_iw;
    -} else if (goog.LOCALE == 'ja') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ja;
    -} else if (goog.LOCALE == 'ka') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ka;
    -} else if (goog.LOCALE == 'kk') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_kk;
    -} else if (goog.LOCALE == 'km') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_km;
    -} else if (goog.LOCALE == 'kn') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_kn;
    -} else if (goog.LOCALE == 'ko') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ko;
    -} else if (goog.LOCALE == 'ky') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ky;
    -} else if (goog.LOCALE == 'ln') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ln;
    -} else if (goog.LOCALE == 'lo') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_lo;
    -} else if (goog.LOCALE == 'lt') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_lt;
    -} else if (goog.LOCALE == 'lv') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_lv;
    -} else if (goog.LOCALE == 'mk') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_mk;
    -} else if (goog.LOCALE == 'ml') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ml;
    -} else if (goog.LOCALE == 'mn') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_mn;
    -} else if (goog.LOCALE == 'mr') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_mr;
    -} else if (goog.LOCALE == 'ms') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ms;
    -} else if (goog.LOCALE == 'mt') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_mt;
    -} else if (goog.LOCALE == 'my') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_my;
    -} else if (goog.LOCALE == 'nb') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_nb;
    -} else if (goog.LOCALE == 'ne') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ne;
    -} else if (goog.LOCALE == 'nl') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_nl;
    -} else if (goog.LOCALE == 'no') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_no;
    -} else if (goog.LOCALE == 'no_NO' || goog.LOCALE == 'no-NO') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_no;
    -} else if (goog.LOCALE == 'or') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_or;
    -} else if (goog.LOCALE == 'pa') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_pa;
    -} else if (goog.LOCALE == 'pl') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_pl;
    -} else if (goog.LOCALE == 'pt') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_pt;
    -} else if (goog.LOCALE == 'pt_BR' || goog.LOCALE == 'pt-BR') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_pt;
    -} else if (goog.LOCALE == 'pt_PT' || goog.LOCALE == 'pt-PT') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_pt_PT;
    -} else if (goog.LOCALE == 'ro') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ro;
    -} else if (goog.LOCALE == 'ru') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ru;
    -} else if (goog.LOCALE == 'si') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_si;
    -} else if (goog.LOCALE == 'sk') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sk;
    -} else if (goog.LOCALE == 'sl') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sl;
    -} else if (goog.LOCALE == 'sq') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sq;
    -} else if (goog.LOCALE == 'sr') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sr;
    -} else if (goog.LOCALE == 'sv') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sv;
    -} else if (goog.LOCALE == 'sw') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sw;
    -} else if (goog.LOCALE == 'ta') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ta;
    -} else if (goog.LOCALE == 'te') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_te;
    -} else if (goog.LOCALE == 'th') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_th;
    -} else if (goog.LOCALE == 'tl') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_tl;
    -} else if (goog.LOCALE == 'tr') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_tr;
    -} else if (goog.LOCALE == 'uk') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_uk;
    -} else if (goog.LOCALE == 'ur') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ur;
    -} else if (goog.LOCALE == 'uz') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_uz;
    -} else if (goog.LOCALE == 'vi') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_vi;
    -} else if (goog.LOCALE == 'zh') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_zh;
    -} else if (goog.LOCALE == 'zh_CN' || goog.LOCALE == 'zh-CN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_zh;
    -} else if (goog.LOCALE == 'zh_HK' || goog.LOCALE == 'zh-HK') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_zh_HK;
    -} else if (goog.LOCALE == 'zh_TW' || goog.LOCALE == 'zh-TW') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_zh_TW;
    -} else if (goog.LOCALE == 'zu') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_zu;
    -} else {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en;
    -}
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/datetimesymbolsext.js b/src/database/third_party/closure-library/closure/goog/i18n/datetimesymbolsext.js
    deleted file mode 100644
    index e6dda8f0349..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/datetimesymbolsext.js
    +++ /dev/null
    @@ -1,22754 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Date/time formatting symbols for all locales.
    - *
    - * This file is autogenerated by scripts
    - *   i18n/tools/generate_datetime_constants.py --for_closure
    - * File generated from CLDR ver. 26
    - *
    - * This file contains symbols for locales that are not covered by
    - * datetimesymbols.js.
    - * Before checkin, this file could have been manually edited. This is
    - * to incorporate changes before we could correct CLDR. All manual
    - * modification must be documented in this section, and should be
    - * removed after those changes lands to CLDR.
    - */
    -
    -goog.provide('goog.i18n.DateTimeSymbolsExt');
    -goog.provide('goog.i18n.DateTimeSymbols_aa');
    -goog.provide('goog.i18n.DateTimeSymbols_aa_DJ');
    -goog.provide('goog.i18n.DateTimeSymbols_aa_ER');
    -goog.provide('goog.i18n.DateTimeSymbols_aa_ET');
    -goog.provide('goog.i18n.DateTimeSymbols_af_NA');
    -goog.provide('goog.i18n.DateTimeSymbols_af_ZA');
    -goog.provide('goog.i18n.DateTimeSymbols_agq');
    -goog.provide('goog.i18n.DateTimeSymbols_agq_CM');
    -goog.provide('goog.i18n.DateTimeSymbols_ak');
    -goog.provide('goog.i18n.DateTimeSymbols_ak_GH');
    -goog.provide('goog.i18n.DateTimeSymbols_am_ET');
    -goog.provide('goog.i18n.DateTimeSymbols_ar_001');
    -goog.provide('goog.i18n.DateTimeSymbols_ar_AE');
    -goog.provide('goog.i18n.DateTimeSymbols_ar_BH');
    -goog.provide('goog.i18n.DateTimeSymbols_ar_DJ');
    -goog.provide('goog.i18n.DateTimeSymbols_ar_DZ');
    -goog.provide('goog.i18n.DateTimeSymbols_ar_EG');
    -goog.provide('goog.i18n.DateTimeSymbols_ar_EH');
    -goog.provide('goog.i18n.DateTimeSymbols_ar_ER');
    -goog.provide('goog.i18n.DateTimeSymbols_ar_IL');
    -goog.provide('goog.i18n.DateTimeSymbols_ar_IQ');
    -goog.provide('goog.i18n.DateTimeSymbols_ar_JO');
    -goog.provide('goog.i18n.DateTimeSymbols_ar_KM');
    -goog.provide('goog.i18n.DateTimeSymbols_ar_KW');
    -goog.provide('goog.i18n.DateTimeSymbols_ar_LB');
    -goog.provide('goog.i18n.DateTimeSymbols_ar_LY');
    -goog.provide('goog.i18n.DateTimeSymbols_ar_MA');
    -goog.provide('goog.i18n.DateTimeSymbols_ar_MR');
    -goog.provide('goog.i18n.DateTimeSymbols_ar_OM');
    -goog.provide('goog.i18n.DateTimeSymbols_ar_PS');
    -goog.provide('goog.i18n.DateTimeSymbols_ar_QA');
    -goog.provide('goog.i18n.DateTimeSymbols_ar_SA');
    -goog.provide('goog.i18n.DateTimeSymbols_ar_SD');
    -goog.provide('goog.i18n.DateTimeSymbols_ar_SO');
    -goog.provide('goog.i18n.DateTimeSymbols_ar_SS');
    -goog.provide('goog.i18n.DateTimeSymbols_ar_SY');
    -goog.provide('goog.i18n.DateTimeSymbols_ar_TD');
    -goog.provide('goog.i18n.DateTimeSymbols_ar_TN');
    -goog.provide('goog.i18n.DateTimeSymbols_ar_YE');
    -goog.provide('goog.i18n.DateTimeSymbols_as');
    -goog.provide('goog.i18n.DateTimeSymbols_as_IN');
    -goog.provide('goog.i18n.DateTimeSymbols_asa');
    -goog.provide('goog.i18n.DateTimeSymbols_asa_TZ');
    -goog.provide('goog.i18n.DateTimeSymbols_ast');
    -goog.provide('goog.i18n.DateTimeSymbols_ast_ES');
    -goog.provide('goog.i18n.DateTimeSymbols_az_Cyrl');
    -goog.provide('goog.i18n.DateTimeSymbols_az_Cyrl_AZ');
    -goog.provide('goog.i18n.DateTimeSymbols_az_Latn');
    -goog.provide('goog.i18n.DateTimeSymbols_az_Latn_AZ');
    -goog.provide('goog.i18n.DateTimeSymbols_bas');
    -goog.provide('goog.i18n.DateTimeSymbols_bas_CM');
    -goog.provide('goog.i18n.DateTimeSymbols_be');
    -goog.provide('goog.i18n.DateTimeSymbols_be_BY');
    -goog.provide('goog.i18n.DateTimeSymbols_bem');
    -goog.provide('goog.i18n.DateTimeSymbols_bem_ZM');
    -goog.provide('goog.i18n.DateTimeSymbols_bez');
    -goog.provide('goog.i18n.DateTimeSymbols_bez_TZ');
    -goog.provide('goog.i18n.DateTimeSymbols_bg_BG');
    -goog.provide('goog.i18n.DateTimeSymbols_bm');
    -goog.provide('goog.i18n.DateTimeSymbols_bm_Latn');
    -goog.provide('goog.i18n.DateTimeSymbols_bm_Latn_ML');
    -goog.provide('goog.i18n.DateTimeSymbols_bn_BD');
    -goog.provide('goog.i18n.DateTimeSymbols_bn_IN');
    -goog.provide('goog.i18n.DateTimeSymbols_bo');
    -goog.provide('goog.i18n.DateTimeSymbols_bo_CN');
    -goog.provide('goog.i18n.DateTimeSymbols_bo_IN');
    -goog.provide('goog.i18n.DateTimeSymbols_br_FR');
    -goog.provide('goog.i18n.DateTimeSymbols_brx');
    -goog.provide('goog.i18n.DateTimeSymbols_brx_IN');
    -goog.provide('goog.i18n.DateTimeSymbols_bs');
    -goog.provide('goog.i18n.DateTimeSymbols_bs_Cyrl');
    -goog.provide('goog.i18n.DateTimeSymbols_bs_Cyrl_BA');
    -goog.provide('goog.i18n.DateTimeSymbols_bs_Latn');
    -goog.provide('goog.i18n.DateTimeSymbols_bs_Latn_BA');
    -goog.provide('goog.i18n.DateTimeSymbols_ca_AD');
    -goog.provide('goog.i18n.DateTimeSymbols_ca_ES');
    -goog.provide('goog.i18n.DateTimeSymbols_ca_ES_VALENCIA');
    -goog.provide('goog.i18n.DateTimeSymbols_ca_FR');
    -goog.provide('goog.i18n.DateTimeSymbols_ca_IT');
    -goog.provide('goog.i18n.DateTimeSymbols_cgg');
    -goog.provide('goog.i18n.DateTimeSymbols_cgg_UG');
    -goog.provide('goog.i18n.DateTimeSymbols_chr_US');
    -goog.provide('goog.i18n.DateTimeSymbols_ckb');
    -goog.provide('goog.i18n.DateTimeSymbols_ckb_Arab');
    -goog.provide('goog.i18n.DateTimeSymbols_ckb_Arab_IQ');
    -goog.provide('goog.i18n.DateTimeSymbols_ckb_Arab_IR');
    -goog.provide('goog.i18n.DateTimeSymbols_ckb_IQ');
    -goog.provide('goog.i18n.DateTimeSymbols_ckb_IR');
    -goog.provide('goog.i18n.DateTimeSymbols_ckb_Latn');
    -goog.provide('goog.i18n.DateTimeSymbols_ckb_Latn_IQ');
    -goog.provide('goog.i18n.DateTimeSymbols_cs_CZ');
    -goog.provide('goog.i18n.DateTimeSymbols_cy_GB');
    -goog.provide('goog.i18n.DateTimeSymbols_da_DK');
    -goog.provide('goog.i18n.DateTimeSymbols_da_GL');
    -goog.provide('goog.i18n.DateTimeSymbols_dav');
    -goog.provide('goog.i18n.DateTimeSymbols_dav_KE');
    -goog.provide('goog.i18n.DateTimeSymbols_de_BE');
    -goog.provide('goog.i18n.DateTimeSymbols_de_DE');
    -goog.provide('goog.i18n.DateTimeSymbols_de_LI');
    -goog.provide('goog.i18n.DateTimeSymbols_de_LU');
    -goog.provide('goog.i18n.DateTimeSymbols_dje');
    -goog.provide('goog.i18n.DateTimeSymbols_dje_NE');
    -goog.provide('goog.i18n.DateTimeSymbols_dsb');
    -goog.provide('goog.i18n.DateTimeSymbols_dsb_DE');
    -goog.provide('goog.i18n.DateTimeSymbols_dua');
    -goog.provide('goog.i18n.DateTimeSymbols_dua_CM');
    -goog.provide('goog.i18n.DateTimeSymbols_dyo');
    -goog.provide('goog.i18n.DateTimeSymbols_dyo_SN');
    -goog.provide('goog.i18n.DateTimeSymbols_dz');
    -goog.provide('goog.i18n.DateTimeSymbols_dz_BT');
    -goog.provide('goog.i18n.DateTimeSymbols_ebu');
    -goog.provide('goog.i18n.DateTimeSymbols_ebu_KE');
    -goog.provide('goog.i18n.DateTimeSymbols_ee');
    -goog.provide('goog.i18n.DateTimeSymbols_ee_GH');
    -goog.provide('goog.i18n.DateTimeSymbols_ee_TG');
    -goog.provide('goog.i18n.DateTimeSymbols_el_CY');
    -goog.provide('goog.i18n.DateTimeSymbols_el_GR');
    -goog.provide('goog.i18n.DateTimeSymbols_en_001');
    -goog.provide('goog.i18n.DateTimeSymbols_en_150');
    -goog.provide('goog.i18n.DateTimeSymbols_en_AG');
    -goog.provide('goog.i18n.DateTimeSymbols_en_AI');
    -goog.provide('goog.i18n.DateTimeSymbols_en_AS');
    -goog.provide('goog.i18n.DateTimeSymbols_en_BB');
    -goog.provide('goog.i18n.DateTimeSymbols_en_BE');
    -goog.provide('goog.i18n.DateTimeSymbols_en_BM');
    -goog.provide('goog.i18n.DateTimeSymbols_en_BS');
    -goog.provide('goog.i18n.DateTimeSymbols_en_BW');
    -goog.provide('goog.i18n.DateTimeSymbols_en_BZ');
    -goog.provide('goog.i18n.DateTimeSymbols_en_CA');
    -goog.provide('goog.i18n.DateTimeSymbols_en_CC');
    -goog.provide('goog.i18n.DateTimeSymbols_en_CK');
    -goog.provide('goog.i18n.DateTimeSymbols_en_CM');
    -goog.provide('goog.i18n.DateTimeSymbols_en_CX');
    -goog.provide('goog.i18n.DateTimeSymbols_en_DG');
    -goog.provide('goog.i18n.DateTimeSymbols_en_DM');
    -goog.provide('goog.i18n.DateTimeSymbols_en_ER');
    -goog.provide('goog.i18n.DateTimeSymbols_en_FJ');
    -goog.provide('goog.i18n.DateTimeSymbols_en_FK');
    -goog.provide('goog.i18n.DateTimeSymbols_en_FM');
    -goog.provide('goog.i18n.DateTimeSymbols_en_GD');
    -goog.provide('goog.i18n.DateTimeSymbols_en_GG');
    -goog.provide('goog.i18n.DateTimeSymbols_en_GH');
    -goog.provide('goog.i18n.DateTimeSymbols_en_GI');
    -goog.provide('goog.i18n.DateTimeSymbols_en_GM');
    -goog.provide('goog.i18n.DateTimeSymbols_en_GU');
    -goog.provide('goog.i18n.DateTimeSymbols_en_GY');
    -goog.provide('goog.i18n.DateTimeSymbols_en_HK');
    -goog.provide('goog.i18n.DateTimeSymbols_en_IM');
    -goog.provide('goog.i18n.DateTimeSymbols_en_IO');
    -goog.provide('goog.i18n.DateTimeSymbols_en_JE');
    -goog.provide('goog.i18n.DateTimeSymbols_en_JM');
    -goog.provide('goog.i18n.DateTimeSymbols_en_KE');
    -goog.provide('goog.i18n.DateTimeSymbols_en_KI');
    -goog.provide('goog.i18n.DateTimeSymbols_en_KN');
    -goog.provide('goog.i18n.DateTimeSymbols_en_KY');
    -goog.provide('goog.i18n.DateTimeSymbols_en_LC');
    -goog.provide('goog.i18n.DateTimeSymbols_en_LR');
    -goog.provide('goog.i18n.DateTimeSymbols_en_LS');
    -goog.provide('goog.i18n.DateTimeSymbols_en_MG');
    -goog.provide('goog.i18n.DateTimeSymbols_en_MH');
    -goog.provide('goog.i18n.DateTimeSymbols_en_MO');
    -goog.provide('goog.i18n.DateTimeSymbols_en_MP');
    -goog.provide('goog.i18n.DateTimeSymbols_en_MS');
    -goog.provide('goog.i18n.DateTimeSymbols_en_MT');
    -goog.provide('goog.i18n.DateTimeSymbols_en_MU');
    -goog.provide('goog.i18n.DateTimeSymbols_en_MW');
    -goog.provide('goog.i18n.DateTimeSymbols_en_MY');
    -goog.provide('goog.i18n.DateTimeSymbols_en_NA');
    -goog.provide('goog.i18n.DateTimeSymbols_en_NF');
    -goog.provide('goog.i18n.DateTimeSymbols_en_NG');
    -goog.provide('goog.i18n.DateTimeSymbols_en_NR');
    -goog.provide('goog.i18n.DateTimeSymbols_en_NU');
    -goog.provide('goog.i18n.DateTimeSymbols_en_NZ');
    -goog.provide('goog.i18n.DateTimeSymbols_en_PG');
    -goog.provide('goog.i18n.DateTimeSymbols_en_PH');
    -goog.provide('goog.i18n.DateTimeSymbols_en_PK');
    -goog.provide('goog.i18n.DateTimeSymbols_en_PN');
    -goog.provide('goog.i18n.DateTimeSymbols_en_PR');
    -goog.provide('goog.i18n.DateTimeSymbols_en_PW');
    -goog.provide('goog.i18n.DateTimeSymbols_en_RW');
    -goog.provide('goog.i18n.DateTimeSymbols_en_SB');
    -goog.provide('goog.i18n.DateTimeSymbols_en_SC');
    -goog.provide('goog.i18n.DateTimeSymbols_en_SD');
    -goog.provide('goog.i18n.DateTimeSymbols_en_SH');
    -goog.provide('goog.i18n.DateTimeSymbols_en_SL');
    -goog.provide('goog.i18n.DateTimeSymbols_en_SS');
    -goog.provide('goog.i18n.DateTimeSymbols_en_SX');
    -goog.provide('goog.i18n.DateTimeSymbols_en_SZ');
    -goog.provide('goog.i18n.DateTimeSymbols_en_TC');
    -goog.provide('goog.i18n.DateTimeSymbols_en_TK');
    -goog.provide('goog.i18n.DateTimeSymbols_en_TO');
    -goog.provide('goog.i18n.DateTimeSymbols_en_TT');
    -goog.provide('goog.i18n.DateTimeSymbols_en_TV');
    -goog.provide('goog.i18n.DateTimeSymbols_en_TZ');
    -goog.provide('goog.i18n.DateTimeSymbols_en_UG');
    -goog.provide('goog.i18n.DateTimeSymbols_en_UM');
    -goog.provide('goog.i18n.DateTimeSymbols_en_VC');
    -goog.provide('goog.i18n.DateTimeSymbols_en_VG');
    -goog.provide('goog.i18n.DateTimeSymbols_en_VI');
    -goog.provide('goog.i18n.DateTimeSymbols_en_VU');
    -goog.provide('goog.i18n.DateTimeSymbols_en_WS');
    -goog.provide('goog.i18n.DateTimeSymbols_en_ZM');
    -goog.provide('goog.i18n.DateTimeSymbols_en_ZW');
    -goog.provide('goog.i18n.DateTimeSymbols_eo');
    -goog.provide('goog.i18n.DateTimeSymbols_eo_001');
    -goog.provide('goog.i18n.DateTimeSymbols_es_AR');
    -goog.provide('goog.i18n.DateTimeSymbols_es_BO');
    -goog.provide('goog.i18n.DateTimeSymbols_es_CL');
    -goog.provide('goog.i18n.DateTimeSymbols_es_CO');
    -goog.provide('goog.i18n.DateTimeSymbols_es_CR');
    -goog.provide('goog.i18n.DateTimeSymbols_es_CU');
    -goog.provide('goog.i18n.DateTimeSymbols_es_DO');
    -goog.provide('goog.i18n.DateTimeSymbols_es_EA');
    -goog.provide('goog.i18n.DateTimeSymbols_es_EC');
    -goog.provide('goog.i18n.DateTimeSymbols_es_GQ');
    -goog.provide('goog.i18n.DateTimeSymbols_es_GT');
    -goog.provide('goog.i18n.DateTimeSymbols_es_HN');
    -goog.provide('goog.i18n.DateTimeSymbols_es_IC');
    -goog.provide('goog.i18n.DateTimeSymbols_es_MX');
    -goog.provide('goog.i18n.DateTimeSymbols_es_NI');
    -goog.provide('goog.i18n.DateTimeSymbols_es_PA');
    -goog.provide('goog.i18n.DateTimeSymbols_es_PE');
    -goog.provide('goog.i18n.DateTimeSymbols_es_PH');
    -goog.provide('goog.i18n.DateTimeSymbols_es_PR');
    -goog.provide('goog.i18n.DateTimeSymbols_es_PY');
    -goog.provide('goog.i18n.DateTimeSymbols_es_SV');
    -goog.provide('goog.i18n.DateTimeSymbols_es_US');
    -goog.provide('goog.i18n.DateTimeSymbols_es_UY');
    -goog.provide('goog.i18n.DateTimeSymbols_es_VE');
    -goog.provide('goog.i18n.DateTimeSymbols_et_EE');
    -goog.provide('goog.i18n.DateTimeSymbols_eu_ES');
    -goog.provide('goog.i18n.DateTimeSymbols_ewo');
    -goog.provide('goog.i18n.DateTimeSymbols_ewo_CM');
    -goog.provide('goog.i18n.DateTimeSymbols_fa_AF');
    -goog.provide('goog.i18n.DateTimeSymbols_fa_IR');
    -goog.provide('goog.i18n.DateTimeSymbols_ff');
    -goog.provide('goog.i18n.DateTimeSymbols_ff_CM');
    -goog.provide('goog.i18n.DateTimeSymbols_ff_GN');
    -goog.provide('goog.i18n.DateTimeSymbols_ff_MR');
    -goog.provide('goog.i18n.DateTimeSymbols_ff_SN');
    -goog.provide('goog.i18n.DateTimeSymbols_fi_FI');
    -goog.provide('goog.i18n.DateTimeSymbols_fil_PH');
    -goog.provide('goog.i18n.DateTimeSymbols_fo');
    -goog.provide('goog.i18n.DateTimeSymbols_fo_FO');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_BE');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_BF');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_BI');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_BJ');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_BL');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_CD');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_CF');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_CG');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_CH');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_CI');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_CM');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_DJ');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_DZ');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_FR');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_GA');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_GF');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_GN');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_GP');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_GQ');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_HT');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_KM');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_LU');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_MA');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_MC');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_MF');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_MG');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_ML');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_MQ');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_MR');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_MU');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_NC');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_NE');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_PF');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_PM');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_RE');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_RW');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_SC');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_SN');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_SY');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_TD');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_TG');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_TN');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_VU');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_WF');
    -goog.provide('goog.i18n.DateTimeSymbols_fr_YT');
    -goog.provide('goog.i18n.DateTimeSymbols_fur');
    -goog.provide('goog.i18n.DateTimeSymbols_fur_IT');
    -goog.provide('goog.i18n.DateTimeSymbols_fy');
    -goog.provide('goog.i18n.DateTimeSymbols_fy_NL');
    -goog.provide('goog.i18n.DateTimeSymbols_ga_IE');
    -goog.provide('goog.i18n.DateTimeSymbols_gd');
    -goog.provide('goog.i18n.DateTimeSymbols_gd_GB');
    -goog.provide('goog.i18n.DateTimeSymbols_gl_ES');
    -goog.provide('goog.i18n.DateTimeSymbols_gsw_CH');
    -goog.provide('goog.i18n.DateTimeSymbols_gsw_FR');
    -goog.provide('goog.i18n.DateTimeSymbols_gsw_LI');
    -goog.provide('goog.i18n.DateTimeSymbols_gu_IN');
    -goog.provide('goog.i18n.DateTimeSymbols_guz');
    -goog.provide('goog.i18n.DateTimeSymbols_guz_KE');
    -goog.provide('goog.i18n.DateTimeSymbols_gv');
    -goog.provide('goog.i18n.DateTimeSymbols_gv_IM');
    -goog.provide('goog.i18n.DateTimeSymbols_ha');
    -goog.provide('goog.i18n.DateTimeSymbols_ha_Latn');
    -goog.provide('goog.i18n.DateTimeSymbols_ha_Latn_GH');
    -goog.provide('goog.i18n.DateTimeSymbols_ha_Latn_NE');
    -goog.provide('goog.i18n.DateTimeSymbols_ha_Latn_NG');
    -goog.provide('goog.i18n.DateTimeSymbols_haw_US');
    -goog.provide('goog.i18n.DateTimeSymbols_he_IL');
    -goog.provide('goog.i18n.DateTimeSymbols_hi_IN');
    -goog.provide('goog.i18n.DateTimeSymbols_hr_BA');
    -goog.provide('goog.i18n.DateTimeSymbols_hr_HR');
    -goog.provide('goog.i18n.DateTimeSymbols_hsb');
    -goog.provide('goog.i18n.DateTimeSymbols_hsb_DE');
    -goog.provide('goog.i18n.DateTimeSymbols_hu_HU');
    -goog.provide('goog.i18n.DateTimeSymbols_hy_AM');
    -goog.provide('goog.i18n.DateTimeSymbols_ia');
    -goog.provide('goog.i18n.DateTimeSymbols_ia_FR');
    -goog.provide('goog.i18n.DateTimeSymbols_id_ID');
    -goog.provide('goog.i18n.DateTimeSymbols_ig');
    -goog.provide('goog.i18n.DateTimeSymbols_ig_NG');
    -goog.provide('goog.i18n.DateTimeSymbols_ii');
    -goog.provide('goog.i18n.DateTimeSymbols_ii_CN');
    -goog.provide('goog.i18n.DateTimeSymbols_is_IS');
    -goog.provide('goog.i18n.DateTimeSymbols_it_CH');
    -goog.provide('goog.i18n.DateTimeSymbols_it_IT');
    -goog.provide('goog.i18n.DateTimeSymbols_it_SM');
    -goog.provide('goog.i18n.DateTimeSymbols_ja_JP');
    -goog.provide('goog.i18n.DateTimeSymbols_jgo');
    -goog.provide('goog.i18n.DateTimeSymbols_jgo_CM');
    -goog.provide('goog.i18n.DateTimeSymbols_jmc');
    -goog.provide('goog.i18n.DateTimeSymbols_jmc_TZ');
    -goog.provide('goog.i18n.DateTimeSymbols_ka_GE');
    -goog.provide('goog.i18n.DateTimeSymbols_kab');
    -goog.provide('goog.i18n.DateTimeSymbols_kab_DZ');
    -goog.provide('goog.i18n.DateTimeSymbols_kam');
    -goog.provide('goog.i18n.DateTimeSymbols_kam_KE');
    -goog.provide('goog.i18n.DateTimeSymbols_kde');
    -goog.provide('goog.i18n.DateTimeSymbols_kde_TZ');
    -goog.provide('goog.i18n.DateTimeSymbols_kea');
    -goog.provide('goog.i18n.DateTimeSymbols_kea_CV');
    -goog.provide('goog.i18n.DateTimeSymbols_khq');
    -goog.provide('goog.i18n.DateTimeSymbols_khq_ML');
    -goog.provide('goog.i18n.DateTimeSymbols_ki');
    -goog.provide('goog.i18n.DateTimeSymbols_ki_KE');
    -goog.provide('goog.i18n.DateTimeSymbols_kk_Cyrl');
    -goog.provide('goog.i18n.DateTimeSymbols_kk_Cyrl_KZ');
    -goog.provide('goog.i18n.DateTimeSymbols_kkj');
    -goog.provide('goog.i18n.DateTimeSymbols_kkj_CM');
    -goog.provide('goog.i18n.DateTimeSymbols_kl');
    -goog.provide('goog.i18n.DateTimeSymbols_kl_GL');
    -goog.provide('goog.i18n.DateTimeSymbols_kln');
    -goog.provide('goog.i18n.DateTimeSymbols_kln_KE');
    -goog.provide('goog.i18n.DateTimeSymbols_km_KH');
    -goog.provide('goog.i18n.DateTimeSymbols_kn_IN');
    -goog.provide('goog.i18n.DateTimeSymbols_ko_KP');
    -goog.provide('goog.i18n.DateTimeSymbols_ko_KR');
    -goog.provide('goog.i18n.DateTimeSymbols_kok');
    -goog.provide('goog.i18n.DateTimeSymbols_kok_IN');
    -goog.provide('goog.i18n.DateTimeSymbols_ks');
    -goog.provide('goog.i18n.DateTimeSymbols_ks_Arab');
    -goog.provide('goog.i18n.DateTimeSymbols_ks_Arab_IN');
    -goog.provide('goog.i18n.DateTimeSymbols_ksb');
    -goog.provide('goog.i18n.DateTimeSymbols_ksb_TZ');
    -goog.provide('goog.i18n.DateTimeSymbols_ksf');
    -goog.provide('goog.i18n.DateTimeSymbols_ksf_CM');
    -goog.provide('goog.i18n.DateTimeSymbols_ksh');
    -goog.provide('goog.i18n.DateTimeSymbols_ksh_DE');
    -goog.provide('goog.i18n.DateTimeSymbols_kw');
    -goog.provide('goog.i18n.DateTimeSymbols_kw_GB');
    -goog.provide('goog.i18n.DateTimeSymbols_ky_Cyrl');
    -goog.provide('goog.i18n.DateTimeSymbols_ky_Cyrl_KG');
    -goog.provide('goog.i18n.DateTimeSymbols_lag');
    -goog.provide('goog.i18n.DateTimeSymbols_lag_TZ');
    -goog.provide('goog.i18n.DateTimeSymbols_lb');
    -goog.provide('goog.i18n.DateTimeSymbols_lb_LU');
    -goog.provide('goog.i18n.DateTimeSymbols_lg');
    -goog.provide('goog.i18n.DateTimeSymbols_lg_UG');
    -goog.provide('goog.i18n.DateTimeSymbols_lkt');
    -goog.provide('goog.i18n.DateTimeSymbols_lkt_US');
    -goog.provide('goog.i18n.DateTimeSymbols_ln_AO');
    -goog.provide('goog.i18n.DateTimeSymbols_ln_CD');
    -goog.provide('goog.i18n.DateTimeSymbols_ln_CF');
    -goog.provide('goog.i18n.DateTimeSymbols_ln_CG');
    -goog.provide('goog.i18n.DateTimeSymbols_lo_LA');
    -goog.provide('goog.i18n.DateTimeSymbols_lt_LT');
    -goog.provide('goog.i18n.DateTimeSymbols_lu');
    -goog.provide('goog.i18n.DateTimeSymbols_lu_CD');
    -goog.provide('goog.i18n.DateTimeSymbols_luo');
    -goog.provide('goog.i18n.DateTimeSymbols_luo_KE');
    -goog.provide('goog.i18n.DateTimeSymbols_luy');
    -goog.provide('goog.i18n.DateTimeSymbols_luy_KE');
    -goog.provide('goog.i18n.DateTimeSymbols_lv_LV');
    -goog.provide('goog.i18n.DateTimeSymbols_mas');
    -goog.provide('goog.i18n.DateTimeSymbols_mas_KE');
    -goog.provide('goog.i18n.DateTimeSymbols_mas_TZ');
    -goog.provide('goog.i18n.DateTimeSymbols_mer');
    -goog.provide('goog.i18n.DateTimeSymbols_mer_KE');
    -goog.provide('goog.i18n.DateTimeSymbols_mfe');
    -goog.provide('goog.i18n.DateTimeSymbols_mfe_MU');
    -goog.provide('goog.i18n.DateTimeSymbols_mg');
    -goog.provide('goog.i18n.DateTimeSymbols_mg_MG');
    -goog.provide('goog.i18n.DateTimeSymbols_mgh');
    -goog.provide('goog.i18n.DateTimeSymbols_mgh_MZ');
    -goog.provide('goog.i18n.DateTimeSymbols_mgo');
    -goog.provide('goog.i18n.DateTimeSymbols_mgo_CM');
    -goog.provide('goog.i18n.DateTimeSymbols_mk_MK');
    -goog.provide('goog.i18n.DateTimeSymbols_ml_IN');
    -goog.provide('goog.i18n.DateTimeSymbols_mn_Cyrl');
    -goog.provide('goog.i18n.DateTimeSymbols_mn_Cyrl_MN');
    -goog.provide('goog.i18n.DateTimeSymbols_mr_IN');
    -goog.provide('goog.i18n.DateTimeSymbols_ms_Latn');
    -goog.provide('goog.i18n.DateTimeSymbols_ms_Latn_BN');
    -goog.provide('goog.i18n.DateTimeSymbols_ms_Latn_MY');
    -goog.provide('goog.i18n.DateTimeSymbols_ms_Latn_SG');
    -goog.provide('goog.i18n.DateTimeSymbols_mt_MT');
    -goog.provide('goog.i18n.DateTimeSymbols_mua');
    -goog.provide('goog.i18n.DateTimeSymbols_mua_CM');
    -goog.provide('goog.i18n.DateTimeSymbols_my_MM');
    -goog.provide('goog.i18n.DateTimeSymbols_naq');
    -goog.provide('goog.i18n.DateTimeSymbols_naq_NA');
    -goog.provide('goog.i18n.DateTimeSymbols_nb_NO');
    -goog.provide('goog.i18n.DateTimeSymbols_nb_SJ');
    -goog.provide('goog.i18n.DateTimeSymbols_nd');
    -goog.provide('goog.i18n.DateTimeSymbols_nd_ZW');
    -goog.provide('goog.i18n.DateTimeSymbols_ne_IN');
    -goog.provide('goog.i18n.DateTimeSymbols_ne_NP');
    -goog.provide('goog.i18n.DateTimeSymbols_nl_AW');
    -goog.provide('goog.i18n.DateTimeSymbols_nl_BE');
    -goog.provide('goog.i18n.DateTimeSymbols_nl_BQ');
    -goog.provide('goog.i18n.DateTimeSymbols_nl_CW');
    -goog.provide('goog.i18n.DateTimeSymbols_nl_NL');
    -goog.provide('goog.i18n.DateTimeSymbols_nl_SR');
    -goog.provide('goog.i18n.DateTimeSymbols_nl_SX');
    -goog.provide('goog.i18n.DateTimeSymbols_nmg');
    -goog.provide('goog.i18n.DateTimeSymbols_nmg_CM');
    -goog.provide('goog.i18n.DateTimeSymbols_nn');
    -goog.provide('goog.i18n.DateTimeSymbols_nn_NO');
    -goog.provide('goog.i18n.DateTimeSymbols_nnh');
    -goog.provide('goog.i18n.DateTimeSymbols_nnh_CM');
    -goog.provide('goog.i18n.DateTimeSymbols_nr');
    -goog.provide('goog.i18n.DateTimeSymbols_nr_ZA');
    -goog.provide('goog.i18n.DateTimeSymbols_nso');
    -goog.provide('goog.i18n.DateTimeSymbols_nso_ZA');
    -goog.provide('goog.i18n.DateTimeSymbols_nus');
    -goog.provide('goog.i18n.DateTimeSymbols_nus_SD');
    -goog.provide('goog.i18n.DateTimeSymbols_nyn');
    -goog.provide('goog.i18n.DateTimeSymbols_nyn_UG');
    -goog.provide('goog.i18n.DateTimeSymbols_om');
    -goog.provide('goog.i18n.DateTimeSymbols_om_ET');
    -goog.provide('goog.i18n.DateTimeSymbols_om_KE');
    -goog.provide('goog.i18n.DateTimeSymbols_or_IN');
    -goog.provide('goog.i18n.DateTimeSymbols_os');
    -goog.provide('goog.i18n.DateTimeSymbols_os_GE');
    -goog.provide('goog.i18n.DateTimeSymbols_os_RU');
    -goog.provide('goog.i18n.DateTimeSymbols_pa_Arab');
    -goog.provide('goog.i18n.DateTimeSymbols_pa_Arab_PK');
    -goog.provide('goog.i18n.DateTimeSymbols_pa_Guru');
    -goog.provide('goog.i18n.DateTimeSymbols_pa_Guru_IN');
    -goog.provide('goog.i18n.DateTimeSymbols_pl_PL');
    -goog.provide('goog.i18n.DateTimeSymbols_ps');
    -goog.provide('goog.i18n.DateTimeSymbols_ps_AF');
    -goog.provide('goog.i18n.DateTimeSymbols_pt_AO');
    -goog.provide('goog.i18n.DateTimeSymbols_pt_CV');
    -goog.provide('goog.i18n.DateTimeSymbols_pt_GW');
    -goog.provide('goog.i18n.DateTimeSymbols_pt_MO');
    -goog.provide('goog.i18n.DateTimeSymbols_pt_MZ');
    -goog.provide('goog.i18n.DateTimeSymbols_pt_ST');
    -goog.provide('goog.i18n.DateTimeSymbols_pt_TL');
    -goog.provide('goog.i18n.DateTimeSymbols_qu');
    -goog.provide('goog.i18n.DateTimeSymbols_qu_BO');
    -goog.provide('goog.i18n.DateTimeSymbols_qu_EC');
    -goog.provide('goog.i18n.DateTimeSymbols_qu_PE');
    -goog.provide('goog.i18n.DateTimeSymbols_rm');
    -goog.provide('goog.i18n.DateTimeSymbols_rm_CH');
    -goog.provide('goog.i18n.DateTimeSymbols_rn');
    -goog.provide('goog.i18n.DateTimeSymbols_rn_BI');
    -goog.provide('goog.i18n.DateTimeSymbols_ro_MD');
    -goog.provide('goog.i18n.DateTimeSymbols_ro_RO');
    -goog.provide('goog.i18n.DateTimeSymbols_rof');
    -goog.provide('goog.i18n.DateTimeSymbols_rof_TZ');
    -goog.provide('goog.i18n.DateTimeSymbols_ru_BY');
    -goog.provide('goog.i18n.DateTimeSymbols_ru_KG');
    -goog.provide('goog.i18n.DateTimeSymbols_ru_KZ');
    -goog.provide('goog.i18n.DateTimeSymbols_ru_MD');
    -goog.provide('goog.i18n.DateTimeSymbols_ru_RU');
    -goog.provide('goog.i18n.DateTimeSymbols_ru_UA');
    -goog.provide('goog.i18n.DateTimeSymbols_rw');
    -goog.provide('goog.i18n.DateTimeSymbols_rw_RW');
    -goog.provide('goog.i18n.DateTimeSymbols_rwk');
    -goog.provide('goog.i18n.DateTimeSymbols_rwk_TZ');
    -goog.provide('goog.i18n.DateTimeSymbols_sah');
    -goog.provide('goog.i18n.DateTimeSymbols_sah_RU');
    -goog.provide('goog.i18n.DateTimeSymbols_saq');
    -goog.provide('goog.i18n.DateTimeSymbols_saq_KE');
    -goog.provide('goog.i18n.DateTimeSymbols_sbp');
    -goog.provide('goog.i18n.DateTimeSymbols_sbp_TZ');
    -goog.provide('goog.i18n.DateTimeSymbols_se');
    -goog.provide('goog.i18n.DateTimeSymbols_se_FI');
    -goog.provide('goog.i18n.DateTimeSymbols_se_NO');
    -goog.provide('goog.i18n.DateTimeSymbols_se_SE');
    -goog.provide('goog.i18n.DateTimeSymbols_seh');
    -goog.provide('goog.i18n.DateTimeSymbols_seh_MZ');
    -goog.provide('goog.i18n.DateTimeSymbols_ses');
    -goog.provide('goog.i18n.DateTimeSymbols_ses_ML');
    -goog.provide('goog.i18n.DateTimeSymbols_sg');
    -goog.provide('goog.i18n.DateTimeSymbols_sg_CF');
    -goog.provide('goog.i18n.DateTimeSymbols_shi');
    -goog.provide('goog.i18n.DateTimeSymbols_shi_Latn');
    -goog.provide('goog.i18n.DateTimeSymbols_shi_Latn_MA');
    -goog.provide('goog.i18n.DateTimeSymbols_shi_Tfng');
    -goog.provide('goog.i18n.DateTimeSymbols_shi_Tfng_MA');
    -goog.provide('goog.i18n.DateTimeSymbols_si_LK');
    -goog.provide('goog.i18n.DateTimeSymbols_sk_SK');
    -goog.provide('goog.i18n.DateTimeSymbols_sl_SI');
    -goog.provide('goog.i18n.DateTimeSymbols_smn');
    -goog.provide('goog.i18n.DateTimeSymbols_smn_FI');
    -goog.provide('goog.i18n.DateTimeSymbols_sn');
    -goog.provide('goog.i18n.DateTimeSymbols_sn_ZW');
    -goog.provide('goog.i18n.DateTimeSymbols_so');
    -goog.provide('goog.i18n.DateTimeSymbols_so_DJ');
    -goog.provide('goog.i18n.DateTimeSymbols_so_ET');
    -goog.provide('goog.i18n.DateTimeSymbols_so_KE');
    -goog.provide('goog.i18n.DateTimeSymbols_so_SO');
    -goog.provide('goog.i18n.DateTimeSymbols_sq_AL');
    -goog.provide('goog.i18n.DateTimeSymbols_sq_MK');
    -goog.provide('goog.i18n.DateTimeSymbols_sq_XK');
    -goog.provide('goog.i18n.DateTimeSymbols_sr_Cyrl');
    -goog.provide('goog.i18n.DateTimeSymbols_sr_Cyrl_BA');
    -goog.provide('goog.i18n.DateTimeSymbols_sr_Cyrl_ME');
    -goog.provide('goog.i18n.DateTimeSymbols_sr_Cyrl_RS');
    -goog.provide('goog.i18n.DateTimeSymbols_sr_Cyrl_XK');
    -goog.provide('goog.i18n.DateTimeSymbols_sr_Latn');
    -goog.provide('goog.i18n.DateTimeSymbols_sr_Latn_BA');
    -goog.provide('goog.i18n.DateTimeSymbols_sr_Latn_ME');
    -goog.provide('goog.i18n.DateTimeSymbols_sr_Latn_RS');
    -goog.provide('goog.i18n.DateTimeSymbols_sr_Latn_XK');
    -goog.provide('goog.i18n.DateTimeSymbols_ss');
    -goog.provide('goog.i18n.DateTimeSymbols_ss_SZ');
    -goog.provide('goog.i18n.DateTimeSymbols_ss_ZA');
    -goog.provide('goog.i18n.DateTimeSymbols_ssy');
    -goog.provide('goog.i18n.DateTimeSymbols_ssy_ER');
    -goog.provide('goog.i18n.DateTimeSymbols_sv_AX');
    -goog.provide('goog.i18n.DateTimeSymbols_sv_FI');
    -goog.provide('goog.i18n.DateTimeSymbols_sv_SE');
    -goog.provide('goog.i18n.DateTimeSymbols_sw_KE');
    -goog.provide('goog.i18n.DateTimeSymbols_sw_TZ');
    -goog.provide('goog.i18n.DateTimeSymbols_sw_UG');
    -goog.provide('goog.i18n.DateTimeSymbols_swc');
    -goog.provide('goog.i18n.DateTimeSymbols_swc_CD');
    -goog.provide('goog.i18n.DateTimeSymbols_ta_IN');
    -goog.provide('goog.i18n.DateTimeSymbols_ta_LK');
    -goog.provide('goog.i18n.DateTimeSymbols_ta_MY');
    -goog.provide('goog.i18n.DateTimeSymbols_ta_SG');
    -goog.provide('goog.i18n.DateTimeSymbols_te_IN');
    -goog.provide('goog.i18n.DateTimeSymbols_teo');
    -goog.provide('goog.i18n.DateTimeSymbols_teo_KE');
    -goog.provide('goog.i18n.DateTimeSymbols_teo_UG');
    -goog.provide('goog.i18n.DateTimeSymbols_th_TH');
    -goog.provide('goog.i18n.DateTimeSymbols_ti');
    -goog.provide('goog.i18n.DateTimeSymbols_ti_ER');
    -goog.provide('goog.i18n.DateTimeSymbols_ti_ET');
    -goog.provide('goog.i18n.DateTimeSymbols_tn');
    -goog.provide('goog.i18n.DateTimeSymbols_tn_BW');
    -goog.provide('goog.i18n.DateTimeSymbols_tn_ZA');
    -goog.provide('goog.i18n.DateTimeSymbols_to');
    -goog.provide('goog.i18n.DateTimeSymbols_to_TO');
    -goog.provide('goog.i18n.DateTimeSymbols_tr_CY');
    -goog.provide('goog.i18n.DateTimeSymbols_tr_TR');
    -goog.provide('goog.i18n.DateTimeSymbols_ts');
    -goog.provide('goog.i18n.DateTimeSymbols_ts_ZA');
    -goog.provide('goog.i18n.DateTimeSymbols_twq');
    -goog.provide('goog.i18n.DateTimeSymbols_twq_NE');
    -goog.provide('goog.i18n.DateTimeSymbols_tzm');
    -goog.provide('goog.i18n.DateTimeSymbols_tzm_Latn');
    -goog.provide('goog.i18n.DateTimeSymbols_tzm_Latn_MA');
    -goog.provide('goog.i18n.DateTimeSymbols_ug');
    -goog.provide('goog.i18n.DateTimeSymbols_ug_Arab');
    -goog.provide('goog.i18n.DateTimeSymbols_ug_Arab_CN');
    -goog.provide('goog.i18n.DateTimeSymbols_uk_UA');
    -goog.provide('goog.i18n.DateTimeSymbols_ur_IN');
    -goog.provide('goog.i18n.DateTimeSymbols_ur_PK');
    -goog.provide('goog.i18n.DateTimeSymbols_uz_Arab');
    -goog.provide('goog.i18n.DateTimeSymbols_uz_Arab_AF');
    -goog.provide('goog.i18n.DateTimeSymbols_uz_Cyrl');
    -goog.provide('goog.i18n.DateTimeSymbols_uz_Cyrl_UZ');
    -goog.provide('goog.i18n.DateTimeSymbols_uz_Latn');
    -goog.provide('goog.i18n.DateTimeSymbols_uz_Latn_UZ');
    -goog.provide('goog.i18n.DateTimeSymbols_vai');
    -goog.provide('goog.i18n.DateTimeSymbols_vai_Latn');
    -goog.provide('goog.i18n.DateTimeSymbols_vai_Latn_LR');
    -goog.provide('goog.i18n.DateTimeSymbols_vai_Vaii');
    -goog.provide('goog.i18n.DateTimeSymbols_vai_Vaii_LR');
    -goog.provide('goog.i18n.DateTimeSymbols_ve');
    -goog.provide('goog.i18n.DateTimeSymbols_ve_ZA');
    -goog.provide('goog.i18n.DateTimeSymbols_vi_VN');
    -goog.provide('goog.i18n.DateTimeSymbols_vo');
    -goog.provide('goog.i18n.DateTimeSymbols_vo_001');
    -goog.provide('goog.i18n.DateTimeSymbols_vun');
    -goog.provide('goog.i18n.DateTimeSymbols_vun_TZ');
    -goog.provide('goog.i18n.DateTimeSymbols_wae');
    -goog.provide('goog.i18n.DateTimeSymbols_wae_CH');
    -goog.provide('goog.i18n.DateTimeSymbols_xog');
    -goog.provide('goog.i18n.DateTimeSymbols_xog_UG');
    -goog.provide('goog.i18n.DateTimeSymbols_yav');
    -goog.provide('goog.i18n.DateTimeSymbols_yav_CM');
    -goog.provide('goog.i18n.DateTimeSymbols_yi');
    -goog.provide('goog.i18n.DateTimeSymbols_yi_001');
    -goog.provide('goog.i18n.DateTimeSymbols_yo');
    -goog.provide('goog.i18n.DateTimeSymbols_yo_BJ');
    -goog.provide('goog.i18n.DateTimeSymbols_yo_NG');
    -goog.provide('goog.i18n.DateTimeSymbols_zgh');
    -goog.provide('goog.i18n.DateTimeSymbols_zgh_MA');
    -goog.provide('goog.i18n.DateTimeSymbols_zh_Hans');
    -goog.provide('goog.i18n.DateTimeSymbols_zh_Hans_CN');
    -goog.provide('goog.i18n.DateTimeSymbols_zh_Hans_HK');
    -goog.provide('goog.i18n.DateTimeSymbols_zh_Hans_MO');
    -goog.provide('goog.i18n.DateTimeSymbols_zh_Hans_SG');
    -goog.provide('goog.i18n.DateTimeSymbols_zh_Hant');
    -goog.provide('goog.i18n.DateTimeSymbols_zh_Hant_HK');
    -goog.provide('goog.i18n.DateTimeSymbols_zh_Hant_MO');
    -goog.provide('goog.i18n.DateTimeSymbols_zh_Hant_TW');
    -goog.provide('goog.i18n.DateTimeSymbols_zu_ZA');
    -
    -goog.require('goog.i18n.DateTimeSymbols');
    -
    -/**
    - * Date/time formatting symbols for locale aa.
    - */
    -goog.i18n.DateTimeSymbols_aa = {
    -  ERAS: ['Yaasuusuk Duma', 'Yaasuusuk Wadir'],
    -  ERANAMES: ['Yaasuusuk Duma', 'Yaasuusuk Wadir'],
    -  NARROWMONTHS: ['Q', 'N', 'C', 'A', 'C', 'Q', 'Q', 'L', 'W', 'D', 'X', 'K'],
    -  STANDALONENARROWMONTHS: ['Q', 'N', 'C', 'A', 'C', 'Q', 'Q', 'L', 'W', 'D',
    -    'X', 'K'],
    -  MONTHS: ['Qunxa Garablu', 'Kudo', 'Ciggilta Kudo', 'Agda Baxis', 'Caxah Alsa',
    -    'Qasa Dirri', 'Qado Dirri', 'Liiqen', 'Waysu', 'Diteli', 'Ximoli',
    -    'Kaxxa Garablu'],
    -  STANDALONEMONTHS: ['Qunxa Garablu', 'Kudo', 'Ciggilta Kudo', 'Agda Baxis',
    -    'Caxah Alsa', 'Qasa Dirri', 'Qado Dirri', 'Liiqen', 'Waysu', 'Diteli',
    -    'Ximoli', 'Kaxxa Garablu'],
    -  SHORTMONTHS: ['Qun', 'Nah', 'Cig', 'Agd', 'Cax', 'Qas', 'Qad', 'Leq', 'Way',
    -    'Dit', 'Xim', 'Kax'],
    -  STANDALONESHORTMONTHS: ['Qun', 'Nah', 'Cig', 'Agd', 'Cax', 'Qas', 'Qad',
    -    'Leq', 'Way', 'Dit', 'Xim', 'Kax'],
    -  WEEKDAYS: ['Acaada', 'Etleeni', 'Talaata', 'Arbaqa', 'Kamiisi', 'Gumqata',
    -    'Sabti'],
    -  STANDALONEWEEKDAYS: ['Acaada', 'Etleeni', 'Talaata', 'Arbaqa', 'Kamiisi',
    -    'Gumqata', 'Sabti'],
    -  SHORTWEEKDAYS: ['Aca', 'Etl', 'Tal', 'Arb', 'Kam', 'Gum', 'Sab'],
    -  STANDALONESHORTWEEKDAYS: ['Aca', 'Etl', 'Tal', 'Arb', 'Kam', 'Gum', 'Sab'],
    -  NARROWWEEKDAYS: ['A', 'E', 'T', 'A', 'K', 'G', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['A', 'E', 'T', 'A', 'K', 'G', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['saaku', 'carra'],
    -  DATEFORMATS: ['EEEE, MMMM dd, y', 'dd MMMM y', 'dd-MMM-y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale aa_DJ.
    - */
    -goog.i18n.DateTimeSymbols_aa_DJ = {
    -  ERAS: ['Yaasuusuk Duma', 'Yaasuusuk Wadir'],
    -  ERANAMES: ['Yaasuusuk Duma', 'Yaasuusuk Wadir'],
    -  NARROWMONTHS: ['Q', 'N', 'C', 'A', 'C', 'Q', 'Q', 'L', 'W', 'D', 'X', 'K'],
    -  STANDALONENARROWMONTHS: ['Q', 'N', 'C', 'A', 'C', 'Q', 'Q', 'L', 'W', 'D',
    -    'X', 'K'],
    -  MONTHS: ['Qunxa Garablu', 'Kudo', 'Ciggilta Kudo', 'Agda Baxis', 'Caxah Alsa',
    -    'Qasa Dirri', 'Qado Dirri', 'Leqeeni', 'Waysu', 'Diteli', 'Ximoli',
    -    'Kaxxa Garablu'],
    -  STANDALONEMONTHS: ['Qunxa Garablu', 'Kudo', 'Ciggilta Kudo', 'Agda Baxis',
    -    'Caxah Alsa', 'Qasa Dirri', 'Qado Dirri', 'Leqeeni', 'Waysu', 'Diteli',
    -    'Ximoli', 'Kaxxa Garablu'],
    -  SHORTMONTHS: ['Qun', 'Nah', 'Cig', 'Agd', 'Cax', 'Qas', 'Qad', 'Leq', 'Way',
    -    'Dit', 'Xim', 'Kax'],
    -  STANDALONESHORTMONTHS: ['Qun', 'Nah', 'Cig', 'Agd', 'Cax', 'Qas', 'Qad',
    -    'Leq', 'Way', 'Dit', 'Xim', 'Kax'],
    -  WEEKDAYS: ['Acaada', 'Etleeni', 'Talaata', 'Arbaqa', 'Kamiisi', 'Gumqata',
    -    'Sabti'],
    -  STANDALONEWEEKDAYS: ['Acaada', 'Etleeni', 'Talaata', 'Arbaqa', 'Kamiisi',
    -    'Gumqata', 'Sabti'],
    -  SHORTWEEKDAYS: ['Aca', 'Etl', 'Tal', 'Arb', 'Kam', 'Gum', 'Sab'],
    -  STANDALONESHORTWEEKDAYS: ['Aca', 'Etl', 'Tal', 'Arb', 'Kam', 'Gum', 'Sab'],
    -  NARROWWEEKDAYS: ['A', 'E', 'T', 'A', 'K', 'G', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['A', 'E', 'T', 'A', 'K', 'G', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['saaku', 'carra'],
    -  DATEFORMATS: ['EEEE, MMMM dd, y', 'dd MMMM y', 'dd-MMM-y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 5,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 4
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale aa_ER.
    - */
    -goog.i18n.DateTimeSymbols_aa_ER = goog.i18n.DateTimeSymbols_aa;
    -
    -
    -/**
    - * Date/time formatting symbols for locale aa_ET.
    - */
    -goog.i18n.DateTimeSymbols_aa_ET = goog.i18n.DateTimeSymbols_aa;
    -
    -
    -/**
    - * Date/time formatting symbols for locale af_NA.
    - */
    -goog.i18n.DateTimeSymbols_af_NA = {
    -  ERAS: ['v.C.', 'n.C.'],
    -  ERANAMES: ['voor Christus', 'na Christus'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januarie', 'Februarie', 'Maart', 'April', 'Mei', 'Junie', 'Julie',
    -    'Augustus', 'September', 'Oktober', 'November', 'Desember'],
    -  STANDALONEMONTHS: ['Januarie', 'Februarie', 'Maart', 'April', 'Mei', 'Junie',
    -    'Julie', 'Augustus', 'September', 'Oktober', 'November', 'Desember'],
    -  SHORTMONTHS: ['Jan.', 'Feb.', 'Mrt.', 'Apr', 'Mei', 'Jun', 'Jul', 'Aug',
    -    'Sep', 'Okt', 'Nov', 'Des'],
    -  STANDALONESHORTMONTHS: ['Jan.', 'Feb.', 'Mrt.', 'Apr', 'Mei', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Okt', 'Nov', 'Des'],
    -  WEEKDAYS: ['Sondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrydag',
    -    'Saterdag'],
    -  STANDALONEWEEKDAYS: ['Sondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag',
    -    'Vrydag', 'Saterdag'],
    -  SHORTWEEKDAYS: ['So', 'Ma', 'Di', 'Wo', 'Do', 'Vr', 'Sa'],
    -  STANDALONESHORTWEEKDAYS: ['So', 'Ma', 'Di', 'Wo', 'Do', 'Vr', 'Sa'],
    -  NARROWWEEKDAYS: ['S', 'M', 'D', 'W', 'D', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'D', 'W', 'D', 'V', 'S'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['1ste kwartaal', '2de kwartaal', '3de kwartaal', '4de kwartaal'],
    -  AMPMS: ['vm.', 'nm.'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'y-MM-dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale af_ZA.
    - */
    -goog.i18n.DateTimeSymbols_af_ZA = {
    -  ERAS: ['v.C.', 'n.C.'],
    -  ERANAMES: ['voor Christus', 'na Christus'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januarie', 'Februarie', 'Maart', 'April', 'Mei', 'Junie', 'Julie',
    -    'Augustus', 'September', 'Oktober', 'November', 'Desember'],
    -  STANDALONEMONTHS: ['Januarie', 'Februarie', 'Maart', 'April', 'Mei', 'Junie',
    -    'Julie', 'Augustus', 'September', 'Oktober', 'November', 'Desember'],
    -  SHORTMONTHS: ['Jan.', 'Feb.', 'Mrt.', 'Apr', 'Mei', 'Jun', 'Jul', 'Aug',
    -    'Sep', 'Okt', 'Nov', 'Des'],
    -  STANDALONESHORTMONTHS: ['Jan.', 'Feb.', 'Mrt.', 'Apr', 'Mei', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Okt', 'Nov', 'Des'],
    -  WEEKDAYS: ['Sondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrydag',
    -    'Saterdag'],
    -  STANDALONEWEEKDAYS: ['Sondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag',
    -    'Vrydag', 'Saterdag'],
    -  SHORTWEEKDAYS: ['So', 'Ma', 'Di', 'Wo', 'Do', 'Vr', 'Sa'],
    -  STANDALONESHORTWEEKDAYS: ['So', 'Ma', 'Di', 'Wo', 'Do', 'Vr', 'Sa'],
    -  NARROWWEEKDAYS: ['S', 'M', 'D', 'W', 'D', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'D', 'W', 'D', 'V', 'S'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['1ste kwartaal', '2de kwartaal', '3de kwartaal', '4de kwartaal'],
    -  AMPMS: ['vm.', 'nm.'],
    -  DATEFORMATS: ['EEEE, dd MMMM y', 'dd MMMM y', 'dd MMM y', 'y-MM-dd'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale agq.
    - */
    -goog.i18n.DateTimeSymbols_agq = {
    -  ERAS: ['SK', 'BK'],
    -  ERANAMES: ['Sěe Kɨ̀lesto', 'Bǎa Kɨ̀lesto'],
    -  NARROWMONTHS: ['n', 'k', 't', 't', 's', 'z', 'k', 'f', 'd', 'l', 'c', 'f'],
    -  STANDALONENARROWMONTHS: ['n', 'k', 't', 't', 's', 'z', 'k', 'f', 'd', 'l',
    -    'c', 'f'],
    -  MONTHS: ['ndzɔ̀ŋɔ̀nùm', 'ndzɔ̀ŋɔ̀kƗ̀zùʔ',
    -    'ndzɔ̀ŋɔ̀tƗ̀dʉ̀ghà', 'ndzɔ̀ŋɔ̀tǎafʉ̄ghā',
    -    'ndzɔ̀ŋèsèe', 'ndzɔ̀ŋɔ̀nzùghò', 'ndzɔ̀ŋɔ̀dùmlo',
    -    'ndzɔ̀ŋɔ̀kwîfɔ̀e', 'ndzɔ̀ŋɔ̀tƗ̀fʉ̀ghàdzughù',
    -    'ndzɔ̀ŋɔ̀ghǔuwelɔ̀m', 'ndzɔ̀ŋɔ̀chwaʔàkaa wo',
    -    'ndzɔ̀ŋèfwòo'],
    -  STANDALONEMONTHS: ['ndzɔ̀ŋɔ̀nùm', 'ndzɔ̀ŋɔ̀kƗ̀zùʔ',
    -    'ndzɔ̀ŋɔ̀tƗ̀dʉ̀ghà', 'ndzɔ̀ŋɔ̀tǎafʉ̄ghā',
    -    'ndzɔ̀ŋèsèe', 'ndzɔ̀ŋɔ̀nzùghò', 'ndzɔ̀ŋɔ̀dùmlo',
    -    'ndzɔ̀ŋɔ̀kwîfɔ̀e', 'ndzɔ̀ŋɔ̀tƗ̀fʉ̀ghàdzughù',
    -    'ndzɔ̀ŋɔ̀ghǔuwelɔ̀m', 'ndzɔ̀ŋɔ̀chwaʔàkaa wo',
    -    'ndzɔ̀ŋèfwòo'],
    -  SHORTMONTHS: ['nùm', 'kɨz', 'tɨd', 'taa', 'see', 'nzu', 'dum', 'fɔe',
    -    'dzu', 'lɔm', 'kaa', 'fwo'],
    -  STANDALONESHORTMONTHS: ['nùm', 'kɨz', 'tɨd', 'taa', 'see', 'nzu', 'dum',
    -    'fɔe', 'dzu', 'lɔm', 'kaa', 'fwo'],
    -  WEEKDAYS: ['tsuʔntsɨ', 'tsuʔukpà', 'tsuʔughɔe', 'tsuʔutɔ̀mlò',
    -    'tsuʔumè', 'tsuʔughɨ̂m', 'tsuʔndzɨkɔʔɔ'],
    -  STANDALONEWEEKDAYS: ['tsuʔntsɨ', 'tsuʔukpà', 'tsuʔughɔe',
    -    'tsuʔutɔ̀mlò', 'tsuʔumè', 'tsuʔughɨ̂m', 'tsuʔndzɨkɔʔɔ'],
    -  SHORTWEEKDAYS: ['nts', 'kpa', 'ghɔ', 'tɔm', 'ume', 'ghɨ', 'dzk'],
    -  STANDALONESHORTWEEKDAYS: ['nts', 'kpa', 'ghɔ', 'tɔm', 'ume', 'ghɨ', 'dzk'],
    -  NARROWWEEKDAYS: ['n', 'k', 'g', 't', 'u', 'g', 'd'],
    -  STANDALONENARROWWEEKDAYS: ['n', 'k', 'g', 't', 'u', 'g', 'd'],
    -  SHORTQUARTERS: ['kɨbâ kɨ 1', 'ugbâ u 2', 'ugbâ u 3', 'ugbâ u 4'],
    -  QUARTERS: ['kɨbâ kɨ 1', 'ugbâ u 2', 'ugbâ u 3', 'ugbâ u 4'],
    -  AMPMS: ['a.g', 'a.k'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM, y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale agq_CM.
    - */
    -goog.i18n.DateTimeSymbols_agq_CM = goog.i18n.DateTimeSymbols_agq;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ak.
    - */
    -goog.i18n.DateTimeSymbols_ak = {
    -  ERAS: ['AK', 'KE'],
    -  ERANAMES: ['Ansa Kristo', 'Kristo Ekyiri'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['Sanda-Ɔpɛpɔn', 'Kwakwar-Ɔgyefuo', 'Ebɔw-Ɔbenem',
    -    'Ebɔbira-Oforisuo', 'Esusow Aketseaba-Kɔtɔnimba', 'Obirade-Ayɛwohomumu',
    -    'Ayɛwoho-Kitawonsa', 'Difuu-Ɔsandaa', 'Fankwa-Ɛbɔ', 'Ɔbɛsɛ-Ahinime',
    -    'Ɔberɛfɛw-Obubuo', 'Mumu-Ɔpɛnimba'],
    -  STANDALONEMONTHS: ['Sanda-Ɔpɛpɔn', 'Kwakwar-Ɔgyefuo', 'Ebɔw-Ɔbenem',
    -    'Ebɔbira-Oforisuo', 'Esusow Aketseaba-Kɔtɔnimba', 'Obirade-Ayɛwohomumu',
    -    'Ayɛwoho-Kitawonsa', 'Difuu-Ɔsandaa', 'Fankwa-Ɛbɔ', 'Ɔbɛsɛ-Ahinime',
    -    'Ɔberɛfɛw-Obubuo', 'Mumu-Ɔpɛnimba'],
    -  SHORTMONTHS: ['S-Ɔ', 'K-Ɔ', 'E-Ɔ', 'E-O', 'E-K', 'O-A', 'A-K', 'D-Ɔ',
    -    'F-Ɛ', 'Ɔ-A', 'Ɔ-O', 'M-Ɔ'],
    -  STANDALONESHORTMONTHS: ['S-Ɔ', 'K-Ɔ', 'E-Ɔ', 'E-O', 'E-K', 'O-A', 'A-K',
    -    'D-Ɔ', 'F-Ɛ', 'Ɔ-A', 'Ɔ-O', 'M-Ɔ'],
    -  WEEKDAYS: ['Kwesida', 'Dwowda', 'Benada', 'Wukuda', 'Yawda', 'Fida',
    -    'Memeneda'],
    -  STANDALONEWEEKDAYS: ['Kwesida', 'Dwowda', 'Benada', 'Wukuda', 'Yawda', 'Fida',
    -    'Memeneda'],
    -  SHORTWEEKDAYS: ['Kwe', 'Dwo', 'Ben', 'Wuk', 'Yaw', 'Fia', 'Mem'],
    -  STANDALONESHORTWEEKDAYS: ['Kwe', 'Dwo', 'Ben', 'Wuk', 'Yaw', 'Fia', 'Mem'],
    -  NARROWWEEKDAYS: ['K', 'D', 'B', 'W', 'Y', 'F', 'M'],
    -  STANDALONENARROWWEEKDAYS: ['K', 'D', 'B', 'W', 'Y', 'F', 'M'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['AN', 'EW'],
    -  DATEFORMATS: ['EEEE, y MMMM dd', 'y MMMM d', 'y MMM d', 'yy/MM/dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ak_GH.
    - */
    -goog.i18n.DateTimeSymbols_ak_GH = goog.i18n.DateTimeSymbols_ak;
    -
    -
    -/**
    - * Date/time formatting symbols for locale am_ET.
    - */
    -goog.i18n.DateTimeSymbols_am_ET = {
    -  ERAS: ['ዓ/ዓ', 'ዓ/ም'],
    -  ERANAMES: ['ዓመተ ዓለም', 'ዓመተ ምሕረት'],
    -  NARROWMONTHS: ['ጃ', 'ፌ', 'ማ', 'ኤ', 'ሜ', 'ጁ', 'ጁ', 'ኦ', 'ሴ',
    -    'ኦ', 'ኖ', 'ዲ'],
    -  STANDALONENARROWMONTHS: ['ጃ', 'ፌ', 'ማ', 'ኤ', 'ሜ', 'ጁ', 'ጁ',
    -    'ኦ', 'ሴ', 'ኦ', 'ኖ', 'ዲ'],
    -  MONTHS: ['ጃንዩወሪ', 'ፌብሩወሪ', 'ማርች', 'ኤፕሪል',
    -    'ሜይ', 'ጁን', 'ጁላይ', 'ኦገስት', 'ሴፕቴምበር',
    -    'ኦክቶበር', 'ኖቬምበር', 'ዲሴምበር'],
    -  STANDALONEMONTHS: ['ጃንዩወሪ', 'ፌብሩወሪ', 'ማርች',
    -    'ኤፕሪል', 'ሜይ', 'ጁን', 'ጁላይ', 'ኦገስት',
    -    'ሴፕቴምበር', 'ኦክቶበር', 'ኖቬምበር',
    -    'ዲሴምበር'],
    -  SHORTMONTHS: ['ጃንዩ', 'ፌብሩ', 'ማርች', 'ኤፕሪ', 'ሜይ',
    -    'ጁን', 'ጁላይ', 'ኦገስ', 'ሴፕቴ', 'ኦክቶ', 'ኖቬም',
    -    'ዲሴም'],
    -  STANDALONESHORTMONTHS: ['ጃንዩ', 'ፌብሩ', 'ማርች', 'ኤፕሪ',
    -    'ሜይ', 'ጁን', 'ጁላይ', 'ኦገስ', 'ሴፕቴ', 'ኦክቶ',
    -    'ኖቬም', 'ዲሴም'],
    -  WEEKDAYS: ['እሑድ', 'ሰኞ', 'ማክሰኞ', 'ረቡዕ', 'ሐሙስ',
    -    'ዓርብ', 'ቅዳሜ'],
    -  STANDALONEWEEKDAYS: ['እሑድ', 'ሰኞ', 'ማክሰኞ', 'ረቡዕ',
    -    'ሐሙስ', 'ዓርብ', 'ቅዳሜ'],
    -  SHORTWEEKDAYS: ['እሑድ', 'ሰኞ', 'ማክሰ', 'ረቡዕ', 'ሐሙስ',
    -    'ዓርብ', 'ቅዳሜ'],
    -  STANDALONESHORTWEEKDAYS: ['እሑድ', 'ሰኞ', 'ማክሰ', 'ረቡዕ',
    -    'ሐሙስ', 'ዓርብ', 'ቅዳሜ'],
    -  NARROWWEEKDAYS: ['እ', 'ሰ', 'ማ', 'ረ', 'ሐ', 'ዓ', 'ቅ'],
    -  STANDALONENARROWWEEKDAYS: ['እ', 'ሰ', 'ማ', 'ረ', 'ሐ', 'ዓ', 'ቅ'],
    -  SHORTQUARTERS: ['ሩብ1', 'ሩብ2', 'ሩብ3', 'ሩብ4'],
    -  QUARTERS: ['1ኛው ሩብ', 'ሁለተኛው ሩብ', '3ኛው ሩብ',
    -    '4ኛው ሩብ'],
    -  AMPMS: ['ጥዋት', 'ከሰዓት'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ar_001.
    - */
    -goog.i18n.DateTimeSymbols_ar_001 = {
    -  ZERODIGIT: 0x0660,
    -  ERAS: ['ق.م', 'م'],
    -  ERANAMES: ['قبل الميلاد', 'ميلادي'],
    -  NARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س', 'ك',
    -    'ب', 'د'],
    -  STANDALONENARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س',
    -    'ك', 'ب', 'د'],
    -  MONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو',
    -    'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر',
    -    'نوفمبر', 'ديسمبر'],
    -  STANDALONEMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  SHORTMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  STANDALONESHORTMONTHS: ['يناير', 'فبراير', 'مارس',
    -    'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس',
    -    'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  WEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONEWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  SHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONESHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  NARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  STANDALONENARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  SHORTQUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  QUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  AMPMS: ['ص', 'م'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'dd‏/MM‏/y',
    -    'd‏/M‏/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 5,
    -  WEEKENDRANGE: [4, 5],
    -  FIRSTWEEKCUTOFFDAY: 4
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ar_AE.
    - */
    -goog.i18n.DateTimeSymbols_ar_AE = {
    -  ZERODIGIT: 0x0660,
    -  ERAS: ['ق.م', 'م'],
    -  ERANAMES: ['قبل الميلاد', 'ميلادي'],
    -  NARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س', 'ك',
    -    'ب', 'د'],
    -  STANDALONENARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س',
    -    'ك', 'ب', 'د'],
    -  MONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو',
    -    'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر',
    -    'نوفمبر', 'ديسمبر'],
    -  STANDALONEMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  SHORTMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  STANDALONESHORTMONTHS: ['يناير', 'فبراير', 'مارس',
    -    'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس',
    -    'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  WEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONEWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  SHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONESHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  NARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  STANDALONENARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  SHORTQUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  QUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  AMPMS: ['ص', 'م'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'dd‏/MM‏/y',
    -    'd‏/M‏/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 5,
    -  WEEKENDRANGE: [4, 5],
    -  FIRSTWEEKCUTOFFDAY: 4
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ar_BH.
    - */
    -goog.i18n.DateTimeSymbols_ar_BH = {
    -  ZERODIGIT: 0x0660,
    -  ERAS: ['ق.م', 'م'],
    -  ERANAMES: ['قبل الميلاد', 'ميلادي'],
    -  NARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س', 'ك',
    -    'ب', 'د'],
    -  STANDALONENARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س',
    -    'ك', 'ب', 'د'],
    -  MONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو',
    -    'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر',
    -    'نوفمبر', 'ديسمبر'],
    -  STANDALONEMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  SHORTMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  STANDALONESHORTMONTHS: ['يناير', 'فبراير', 'مارس',
    -    'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس',
    -    'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  WEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONEWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  SHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONESHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  NARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  STANDALONENARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  SHORTQUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  QUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  AMPMS: ['ص', 'م'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'dd‏/MM‏/y',
    -    'd‏/M‏/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 5,
    -  WEEKENDRANGE: [4, 5],
    -  FIRSTWEEKCUTOFFDAY: 4
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ar_DJ.
    - */
    -goog.i18n.DateTimeSymbols_ar_DJ = {
    -  ZERODIGIT: 0x0660,
    -  ERAS: ['ق.م', 'م'],
    -  ERANAMES: ['قبل الميلاد', 'ميلادي'],
    -  NARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س', 'ك',
    -    'ب', 'د'],
    -  STANDALONENARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س',
    -    'ك', 'ب', 'د'],
    -  MONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو',
    -    'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر',
    -    'نوفمبر', 'ديسمبر'],
    -  STANDALONEMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  SHORTMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  STANDALONESHORTMONTHS: ['يناير', 'فبراير', 'مارس',
    -    'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس',
    -    'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  WEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONEWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  SHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONESHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  NARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  STANDALONENARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  SHORTQUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  QUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  AMPMS: ['ص', 'م'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'dd‏/MM‏/y',
    -    'd‏/M‏/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 5,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 4
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ar_DZ.
    - */
    -goog.i18n.DateTimeSymbols_ar_DZ = {
    -  ERAS: ['ق.م', 'م'],
    -  ERANAMES: ['قبل الميلاد', 'ميلادي'],
    -  NARROWMONTHS: ['ج', 'ف', 'م', 'أ', 'م', 'ج', 'ج', 'أ', 'س', 'أ',
    -    'ن', 'د'],
    -  STANDALONENARROWMONTHS: ['ج', 'ف', 'م', 'أ', 'م', 'ج', 'ج', 'أ', 'س',
    -    'أ', 'ن', 'د'],
    -  MONTHS: ['جانفي', 'فيفري', 'مارس', 'أفريل', 'ماي',
    -    'جوان', 'جويلية', 'أوت', 'سبتمبر', 'أكتوبر',
    -    'نوفمبر', 'ديسمبر'],
    -  STANDALONEMONTHS: ['جانفي', 'فيفري', 'مارس', 'أفريل',
    -    'ماي', 'جوان', 'جويلية', 'أوت', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  SHORTMONTHS: ['جانفي', 'فيفري', 'مارس', 'أفريل', 'ماي',
    -    'جوان', 'جويلية', 'أوت', 'سبتمبر', 'أكتوبر',
    -    'نوفمبر', 'ديسمبر'],
    -  STANDALONESHORTMONTHS: ['جانفي', 'فيفري', 'مارس', 'أفريل',
    -    'ماي', 'جوان', 'جويلية', 'أوت', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  WEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONEWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  SHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONESHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  NARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  STANDALONENARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  SHORTQUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  QUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  AMPMS: ['ص', 'م'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'y/MM/dd', 'y/M/d'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 5,
    -  WEEKENDRANGE: [4, 5],
    -  FIRSTWEEKCUTOFFDAY: 4
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ar_EG.
    - */
    -goog.i18n.DateTimeSymbols_ar_EG = {
    -  ZERODIGIT: 0x0660,
    -  ERAS: ['ق.م', 'م'],
    -  ERANAMES: ['قبل الميلاد', 'ميلادي'],
    -  NARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س', 'ك',
    -    'ب', 'د'],
    -  STANDALONENARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س',
    -    'ك', 'ب', 'د'],
    -  MONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو',
    -    'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر',
    -    'نوفمبر', 'ديسمبر'],
    -  STANDALONEMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  SHORTMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  STANDALONESHORTMONTHS: ['يناير', 'فبراير', 'مارس',
    -    'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس',
    -    'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  WEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONEWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  SHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONESHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  NARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  STANDALONENARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  SHORTQUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  QUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  AMPMS: ['ص', 'م'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'dd‏/MM‏/y',
    -    'd‏/M‏/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 5,
    -  WEEKENDRANGE: [4, 5],
    -  FIRSTWEEKCUTOFFDAY: 4
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ar_EH.
    - */
    -goog.i18n.DateTimeSymbols_ar_EH = {
    -  ERAS: ['ق.م', 'م'],
    -  ERANAMES: ['قبل الميلاد', 'ميلادي'],
    -  NARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س', 'ك',
    -    'ب', 'د'],
    -  STANDALONENARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س',
    -    'ك', 'ب', 'د'],
    -  MONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو',
    -    'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر',
    -    'نوفمبر', 'ديسمبر'],
    -  STANDALONEMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  SHORTMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  STANDALONESHORTMONTHS: ['يناير', 'فبراير', 'مارس',
    -    'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس',
    -    'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  WEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONEWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  SHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONESHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  NARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  STANDALONENARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  SHORTQUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  QUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  AMPMS: ['ص', 'م'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'dd‏/MM‏/y',
    -    'd‏/M‏/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ar_ER.
    - */
    -goog.i18n.DateTimeSymbols_ar_ER = {
    -  ZERODIGIT: 0x0660,
    -  ERAS: ['ق.م', 'م'],
    -  ERANAMES: ['قبل الميلاد', 'ميلادي'],
    -  NARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س', 'ك',
    -    'ب', 'د'],
    -  STANDALONENARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س',
    -    'ك', 'ب', 'د'],
    -  MONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو',
    -    'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر',
    -    'نوفمبر', 'ديسمبر'],
    -  STANDALONEMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  SHORTMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  STANDALONESHORTMONTHS: ['يناير', 'فبراير', 'مارس',
    -    'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس',
    -    'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  WEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONEWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  SHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONESHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  NARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  STANDALONENARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  SHORTQUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  QUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  AMPMS: ['ص', 'م'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'dd‏/MM‏/y',
    -    'd‏/M‏/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ar_IL.
    - */
    -goog.i18n.DateTimeSymbols_ar_IL = {
    -  ZERODIGIT: 0x0660,
    -  ERAS: ['ق.م', 'م'],
    -  ERANAMES: ['قبل الميلاد', 'ميلادي'],
    -  NARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س', 'ك',
    -    'ب', 'د'],
    -  STANDALONENARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س',
    -    'ك', 'ب', 'د'],
    -  MONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو',
    -    'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر',
    -    'نوفمبر', 'ديسمبر'],
    -  STANDALONEMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  SHORTMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  STANDALONESHORTMONTHS: ['يناير', 'فبراير', 'مارس',
    -    'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس',
    -    'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  WEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONEWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  SHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONESHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  NARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  STANDALONENARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  SHORTQUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  QUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  AMPMS: ['ص', 'م'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'dd‏/MM‏/y',
    -    'd‏/M‏/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [4, 5],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ar_IQ.
    - */
    -goog.i18n.DateTimeSymbols_ar_IQ = {
    -  ZERODIGIT: 0x0660,
    -  ERAS: ['ق.م', 'م'],
    -  ERANAMES: ['قبل الميلاد', 'ميلادي'],
    -  NARROWMONTHS: ['ك', 'ش', 'آ', 'ن', 'أ', 'ح', 'ت', 'آ', 'أ', 'ت',
    -    'ت', 'ك'],
    -  STANDALONENARROWMONTHS: ['ك', 'ش', 'آ', 'ن', 'أ', 'ح', 'ت', 'آ', 'أ',
    -    'ت', 'ت', 'ك'],
    -  MONTHS: ['كانون الثاني', 'شباط', 'آذار', 'نيسان',
    -    'أيار', 'حزيران', 'تموز', 'آب', 'أيلول',
    -    'تشرين الأول', 'تشرين الثاني',
    -    'كانون الأول'],
    -  STANDALONEMONTHS: ['كانون الثاني', 'شباط', 'آذار',
    -    'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول',
    -    'تشرين الأول', 'تشرين الثاني',
    -    'كانون الأول'],
    -  SHORTMONTHS: ['كانون الثاني', 'شباط', 'آذار', 'نيسان',
    -    'أيار', 'حزيران', 'تموز', 'آب', 'أيلول',
    -    'تشرین الأول', 'تشرين الثاني',
    -    'كانون الأول'],
    -  STANDALONESHORTMONTHS: ['كانون الثاني', 'شباط', 'آذار',
    -    'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول',
    -    'تشرين الأول', 'تشرين الثاني',
    -    'كانون الأول'],
    -  WEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONEWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  SHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONESHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  NARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  STANDALONENARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  SHORTQUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  QUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  AMPMS: ['ص', 'م'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'dd‏/MM‏/y',
    -    'd‏/M‏/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 5,
    -  WEEKENDRANGE: [4, 5],
    -  FIRSTWEEKCUTOFFDAY: 4
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ar_JO.
    - */
    -goog.i18n.DateTimeSymbols_ar_JO = {
    -  ZERODIGIT: 0x0660,
    -  ERAS: ['ق.م', 'م'],
    -  ERANAMES: ['قبل الميلاد', 'ميلادي'],
    -  NARROWMONTHS: ['ك', 'ش', 'آ', 'ن', 'أ', 'ح', 'ت', 'آ', 'أ', 'ت',
    -    'ت', 'ك'],
    -  STANDALONENARROWMONTHS: ['ك', 'ش', 'آ', 'ن', 'أ', 'ح', 'ت', 'آ', 'أ',
    -    'ت', 'ت', 'ك'],
    -  MONTHS: ['كانون الثاني', 'شباط', 'آذار', 'نيسان',
    -    'أيار', 'حزيران', 'تموز', 'آب', 'أيلول',
    -    'تشرين الأول', 'تشرين الثاني',
    -    'كانون الأول'],
    -  STANDALONEMONTHS: ['كانون الثاني', 'شباط', 'آذار',
    -    'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول',
    -    'تشرين الأول', 'تشرين الثاني',
    -    'كانون الأول'],
    -  SHORTMONTHS: ['كانون الثاني', 'شباط', 'آذار', 'نيسان',
    -    'أيار', 'حزيران', 'تموز', 'آب', 'أيلول',
    -    'تشرين الأول', 'تشرين الثاني',
    -    'كانون الأول'],
    -  STANDALONESHORTMONTHS: ['كانون الثاني', 'شباط', 'آذار',
    -    'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول',
    -    'تشرين الأول', 'تشرين الثاني',
    -    'كانون الأول'],
    -  WEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONEWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  SHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONESHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  NARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  STANDALONENARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  SHORTQUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  QUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  AMPMS: ['ص', 'م'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'dd‏/MM‏/y',
    -    'd‏/M‏/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 5,
    -  WEEKENDRANGE: [4, 5],
    -  FIRSTWEEKCUTOFFDAY: 4
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ar_KM.
    - */
    -goog.i18n.DateTimeSymbols_ar_KM = {
    -  ZERODIGIT: 0x0660,
    -  ERAS: ['ق.م', 'م'],
    -  ERANAMES: ['قبل الميلاد', 'ميلادي'],
    -  NARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س', 'ك',
    -    'ب', 'د'],
    -  STANDALONENARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س',
    -    'ك', 'ب', 'د'],
    -  MONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو',
    -    'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر',
    -    'نوفمبر', 'ديسمبر'],
    -  STANDALONEMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  SHORTMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  STANDALONESHORTMONTHS: ['يناير', 'فبراير', 'مارس',
    -    'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس',
    -    'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  WEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONEWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  SHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONESHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  NARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  STANDALONENARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  SHORTQUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  QUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  AMPMS: ['ص', 'م'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'dd‏/MM‏/y',
    -    'd‏/M‏/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ar_KW.
    - */
    -goog.i18n.DateTimeSymbols_ar_KW = {
    -  ZERODIGIT: 0x0660,
    -  ERAS: ['ق.م', 'م'],
    -  ERANAMES: ['قبل الميلاد', 'ميلادي'],
    -  NARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س', 'ك',
    -    'ب', 'د'],
    -  STANDALONENARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س',
    -    'ك', 'ب', 'د'],
    -  MONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو',
    -    'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر',
    -    'نوفمبر', 'ديسمبر'],
    -  STANDALONEMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  SHORTMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  STANDALONESHORTMONTHS: ['يناير', 'فبراير', 'مارس',
    -    'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس',
    -    'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  WEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONEWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  SHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONESHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  NARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  STANDALONENARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  SHORTQUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  QUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  AMPMS: ['ص', 'م'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'dd‏/MM‏/y',
    -    'd‏/M‏/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 5,
    -  WEEKENDRANGE: [4, 5],
    -  FIRSTWEEKCUTOFFDAY: 4
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ar_LB.
    - */
    -goog.i18n.DateTimeSymbols_ar_LB = {
    -  ZERODIGIT: 0x0660,
    -  ERAS: ['ق.م', 'م'],
    -  ERANAMES: ['قبل الميلاد', 'ميلادي'],
    -  NARROWMONTHS: ['ك', 'ش', 'آ', 'ن', 'أ', 'ح', 'ت', 'آ', 'أ', 'ت',
    -    'ت', 'ك'],
    -  STANDALONENARROWMONTHS: ['ك', 'ش', 'آ', 'ن', 'أ', 'ح', 'ت', 'آ', 'أ',
    -    'ت', 'ت', 'ك'],
    -  MONTHS: ['كانون الثاني', 'شباط', 'آذار', 'نيسان',
    -    'أيار', 'حزيران', 'تموز', 'آب', 'أيلول',
    -    'تشرين الأول', 'تشرين الثاني',
    -    'كانون الأول'],
    -  STANDALONEMONTHS: ['كانون الثاني', 'شباط', 'آذار',
    -    'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول',
    -    'تشرين الأول', 'تشرين الثاني',
    -    'كانون الأول'],
    -  SHORTMONTHS: ['كانون الثاني', 'شباط', 'آذار', 'نيسان',
    -    'أيار', 'حزيران', 'تموز', 'آب', 'أيلول',
    -    'تشرين الأول', 'تشرين الثاني',
    -    'كانون الأول'],
    -  STANDALONESHORTMONTHS: ['كانون الثاني', 'شباط', 'آذار',
    -    'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول',
    -    'تشرين الأول', 'تشرين الثاني',
    -    'كانون الأول'],
    -  WEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONEWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  SHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONESHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  NARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  STANDALONENARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  SHORTQUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  QUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  AMPMS: ['ص', 'م'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'MMM d, y', 'd‏/M‏/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ar_LY.
    - */
    -goog.i18n.DateTimeSymbols_ar_LY = {
    -  ERAS: ['ق.م', 'م'],
    -  ERANAMES: ['قبل الميلاد', 'ميلادي'],
    -  NARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س', 'ك',
    -    'ب', 'د'],
    -  STANDALONENARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س',
    -    'ك', 'ب', 'د'],
    -  MONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو',
    -    'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر',
    -    'نوفمبر', 'ديسمبر'],
    -  STANDALONEMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  SHORTMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  STANDALONESHORTMONTHS: ['يناير', 'فبراير', 'مارس',
    -    'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس',
    -    'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  WEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONEWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  SHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONESHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  NARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  STANDALONENARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  SHORTQUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  QUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  AMPMS: ['ص', 'م'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'dd‏/MM‏/y',
    -    'd‏/M‏/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 5,
    -  WEEKENDRANGE: [4, 5],
    -  FIRSTWEEKCUTOFFDAY: 4
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ar_MA.
    - */
    -goog.i18n.DateTimeSymbols_ar_MA = {
    -  ERAS: ['ق.م', 'م'],
    -  ERANAMES: ['قبل الميلاد', 'ميلادي'],
    -  NARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'م', 'ن', 'ل', 'غ', 'ش', 'ك',
    -    'ب', 'د'],
    -  STANDALONENARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'م', 'ن', 'ل', 'غ', 'ش',
    -    'ك', 'ب', 'د'],
    -  MONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل', 'ماي',
    -    'يونيو', 'يوليوز', 'غشت', 'شتنبر', 'أكتوبر',
    -    'نونبر', 'دجنبر'],
    -  STANDALONEMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'ماي', 'يونيو', 'يوليوز', 'غشت', 'شتنبر',
    -    'أكتوبر', 'نونبر', 'دجنبر'],
    -  SHORTMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'ماي', 'يونيو', 'يوليوز', 'غشت', 'شتنبر',
    -    'أكتوبر', 'نونبر', 'دجنبر'],
    -  STANDALONESHORTMONTHS: ['يناير', 'فبراير', 'مارس',
    -    'أبريل', 'ماي', 'يونيو', 'يوليوز', 'غشت',
    -    'شتنبر', 'أكتوبر', 'نونبر', 'دجنبر'],
    -  WEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONEWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  SHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONESHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  NARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  STANDALONENARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  SHORTQUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  QUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  AMPMS: ['ص', 'م'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'y/MM/dd', 'y/M/d'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 5,
    -  WEEKENDRANGE: [4, 5],
    -  FIRSTWEEKCUTOFFDAY: 4
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ar_MR.
    - */
    -goog.i18n.DateTimeSymbols_ar_MR = {
    -  ZERODIGIT: 0x0660,
    -  ERAS: ['ق.م', 'م'],
    -  ERANAMES: ['قبل الميلاد', 'ميلادي'],
    -  NARROWMONTHS: ['ي', 'ف', 'م', 'إ', 'و', 'ن', 'ل', 'غ', 'ش', 'ك',
    -    'ب', 'د'],
    -  STANDALONENARROWMONTHS: ['ي', 'ف', 'م', 'إ', 'و', 'ن', 'ل', 'غ', 'ش',
    -    'ك', 'ب', 'د'],
    -  MONTHS: ['يناير', 'فبراير', 'مارس', 'إبريل', 'مايو',
    -    'يونيو', 'يوليو', 'أغشت', 'شتمبر', 'أكتوبر',
    -    'نوفمبر', 'دجمبر'],
    -  STANDALONEMONTHS: ['يناير', 'فبراير', 'مارس', 'إبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغشت', 'شتمبر',
    -    'أكتوبر', 'نوفمبر', 'دجمبر'],
    -  SHORTMONTHS: ['يناير', 'فبراير', 'مارس', 'إبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغشت', 'شتمبر',
    -    'أكتوبر', 'نوفمبر', 'دجمبر'],
    -  STANDALONESHORTMONTHS: ['يناير', 'فبراير', 'مارس',
    -    'إبريل', 'مايو', 'يونيو', 'يوليو', 'أغشت',
    -    'شتمبر', 'أكتوبر', 'نوفمبر', 'دجمبر'],
    -  WEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONEWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  SHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONESHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  NARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  STANDALONENARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  SHORTQUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  QUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  AMPMS: ['ص', 'م'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'dd‏/MM‏/y',
    -    'd‏/M‏/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ar_OM.
    - */
    -goog.i18n.DateTimeSymbols_ar_OM = {
    -  ZERODIGIT: 0x0660,
    -  ERAS: ['ق.م', 'م'],
    -  ERANAMES: ['قبل الميلاد', 'ميلادي'],
    -  NARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س', 'ك',
    -    'ب', 'د'],
    -  STANDALONENARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س',
    -    'ك', 'ب', 'د'],
    -  MONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو',
    -    'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر',
    -    'نوفمبر', 'ديسمبر'],
    -  STANDALONEMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  SHORTMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  STANDALONESHORTMONTHS: ['يناير', 'فبراير', 'مارس',
    -    'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس',
    -    'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  WEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONEWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  SHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONESHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  NARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  STANDALONENARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  SHORTQUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  QUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  AMPMS: ['ص', 'م'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'dd‏/MM‏/y',
    -    'd‏/M‏/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 5,
    -  WEEKENDRANGE: [4, 5],
    -  FIRSTWEEKCUTOFFDAY: 4
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ar_PS.
    - */
    -goog.i18n.DateTimeSymbols_ar_PS = {
    -  ZERODIGIT: 0x0660,
    -  ERAS: ['ق.م', 'م'],
    -  ERANAMES: ['قبل الميلاد', 'ميلادي'],
    -  NARROWMONTHS: ['ك', 'ش', 'آ', 'ن', 'أ', 'ح', 'ت', 'آ', 'أ', 'ت',
    -    'ت', 'ك'],
    -  STANDALONENARROWMONTHS: ['ك', 'ش', 'آ', 'ن', 'أ', 'ح', 'ت', 'آ', 'أ',
    -    'ت', 'ت', 'ك'],
    -  MONTHS: ['كانون الثاني', 'شباط', 'آذار', 'نيسان',
    -    'أيار', 'حزيران', 'تموز', 'آب', 'أيلول',
    -    'تشرين الأول', 'تشرين الثاني',
    -    'كانون الأول'],
    -  STANDALONEMONTHS: ['كانون الثاني', 'شباط', 'آذار',
    -    'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول',
    -    'تشرين الأول', 'تشرين الثاني',
    -    'كانون الأول'],
    -  SHORTMONTHS: ['كانون الثاني', 'شباط', 'آذار', 'نيسان',
    -    'أيار', 'حزيران', 'تموز', 'آب', 'أيلول',
    -    'تشرين الأول', 'تشرين الثاني',
    -    'كانون الأول'],
    -  STANDALONESHORTMONTHS: ['كانون الثاني', 'شباط', 'آذار',
    -    'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول',
    -    'تشرين الأول', 'تشرين الثاني',
    -    'كانون الأول'],
    -  WEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONEWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  SHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONESHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  NARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  STANDALONENARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  SHORTQUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  QUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  AMPMS: ['ص', 'م'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'dd‏/MM‏/y',
    -    'd‏/M‏/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ar_QA.
    - */
    -goog.i18n.DateTimeSymbols_ar_QA = {
    -  ZERODIGIT: 0x0660,
    -  ERAS: ['ق.م', 'م'],
    -  ERANAMES: ['قبل الميلاد', 'ميلادي'],
    -  NARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س', 'ك',
    -    'ب', 'د'],
    -  STANDALONENARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س',
    -    'ك', 'ب', 'د'],
    -  MONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو',
    -    'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر',
    -    'نوفمبر', 'ديسمبر'],
    -  STANDALONEMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  SHORTMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  STANDALONESHORTMONTHS: ['يناير', 'فبراير', 'مارس',
    -    'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس',
    -    'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  WEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONEWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  SHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONESHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  NARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  STANDALONENARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  SHORTQUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  QUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  AMPMS: ['ص', 'م'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'dd‏/MM‏/y',
    -    'd‏/M‏/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 5,
    -  WEEKENDRANGE: [4, 5],
    -  FIRSTWEEKCUTOFFDAY: 4
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ar_SA.
    - */
    -goog.i18n.DateTimeSymbols_ar_SA = {
    -  ZERODIGIT: 0x0660,
    -  ERAS: ['ق.م', 'م'],
    -  ERANAMES: ['قبل الميلاد', 'ميلادي'],
    -  NARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س', 'ك',
    -    'ب', 'د'],
    -  STANDALONENARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س',
    -    'ك', 'ب', 'د'],
    -  MONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو',
    -    'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر',
    -    'نوفمبر', 'ديسمبر'],
    -  STANDALONEMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  SHORTMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  STANDALONESHORTMONTHS: ['يناير', 'فبراير', 'مارس',
    -    'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس',
    -    'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  WEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONEWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  SHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONESHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  NARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  STANDALONENARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  SHORTQUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  QUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  AMPMS: ['ص', 'م'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'dd‏/MM‏/y',
    -    'd‏/M‏/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [4, 5],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ar_SD.
    - */
    -goog.i18n.DateTimeSymbols_ar_SD = {
    -  ZERODIGIT: 0x0660,
    -  ERAS: ['ق.م', 'م'],
    -  ERANAMES: ['قبل الميلاد', 'ميلادي'],
    -  NARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س', 'ك',
    -    'ب', 'د'],
    -  STANDALONENARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س',
    -    'ك', 'ب', 'د'],
    -  MONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو',
    -    'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر',
    -    'نوفمبر', 'ديسمبر'],
    -  STANDALONEMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  SHORTMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  STANDALONESHORTMONTHS: ['يناير', 'فبراير', 'مارس',
    -    'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس',
    -    'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  WEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONEWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  SHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONESHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  NARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  STANDALONENARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  SHORTQUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  QUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  AMPMS: ['ص', 'م'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'dd‏/MM‏/y',
    -    'd‏/M‏/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 5,
    -  WEEKENDRANGE: [4, 5],
    -  FIRSTWEEKCUTOFFDAY: 4
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ar_SO.
    - */
    -goog.i18n.DateTimeSymbols_ar_SO = {
    -  ZERODIGIT: 0x0660,
    -  ERAS: ['ق.م', 'م'],
    -  ERANAMES: ['قبل الميلاد', 'ميلادي'],
    -  NARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س', 'ك',
    -    'ب', 'د'],
    -  STANDALONENARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س',
    -    'ك', 'ب', 'د'],
    -  MONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو',
    -    'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر',
    -    'نوفمبر', 'ديسمبر'],
    -  STANDALONEMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  SHORTMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  STANDALONESHORTMONTHS: ['يناير', 'فبراير', 'مارس',
    -    'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس',
    -    'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  WEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONEWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  SHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONESHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  NARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  STANDALONENARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  SHORTQUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  QUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  AMPMS: ['ص', 'م'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'dd‏/MM‏/y',
    -    'd‏/M‏/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ar_SS.
    - */
    -goog.i18n.DateTimeSymbols_ar_SS = {
    -  ZERODIGIT: 0x0660,
    -  ERAS: ['ق.م', 'م'],
    -  ERANAMES: ['قبل الميلاد', 'ميلادي'],
    -  NARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س', 'ك',
    -    'ب', 'د'],
    -  STANDALONENARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س',
    -    'ك', 'ب', 'د'],
    -  MONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو',
    -    'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر',
    -    'نوفمبر', 'ديسمبر'],
    -  STANDALONEMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  SHORTMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  STANDALONESHORTMONTHS: ['يناير', 'فبراير', 'مارس',
    -    'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس',
    -    'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  WEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONEWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  SHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONESHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  NARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  STANDALONENARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  SHORTQUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  QUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  AMPMS: ['ص', 'م'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'dd‏/MM‏/y',
    -    'd‏/M‏/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ar_SY.
    - */
    -goog.i18n.DateTimeSymbols_ar_SY = {
    -  ZERODIGIT: 0x0660,
    -  ERAS: ['ق.م', 'م'],
    -  ERANAMES: ['قبل الميلاد', 'ميلادي'],
    -  NARROWMONTHS: ['ك', 'ش', 'آ', 'ن', 'أ', 'ح', 'ت', 'آ', 'أ', 'ت',
    -    'ت', 'ك'],
    -  STANDALONENARROWMONTHS: ['ك', 'ش', 'آ', 'ن', 'أ', 'ح', 'ت', 'آ', 'أ',
    -    'ت', 'ت', 'ك'],
    -  MONTHS: ['كانون الثاني', 'شباط', 'آذار', 'نيسان',
    -    'أيار', 'حزيران', 'تموز', 'آب', 'أيلول',
    -    'تشرين الأول', 'تشرين الثاني',
    -    'كانون الأول'],
    -  STANDALONEMONTHS: ['كانون الثاني', 'شباط', 'آذار',
    -    'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول',
    -    'تشرين الأول', 'تشرين الثاني',
    -    'كانون الأول'],
    -  SHORTMONTHS: ['كانون الثاني', 'شباط', 'آذار', 'نيسان',
    -    'أيار', 'حزيران', 'تموز', 'آب', 'أيلول',
    -    'تشرين الأول', 'تشرين الثاني',
    -    'كانون الأول'],
    -  STANDALONESHORTMONTHS: ['كانون الثاني', 'شباط', 'آذار',
    -    'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول',
    -    'تشرين الأول', 'تشرين الثاني',
    -    'كانون الأول'],
    -  WEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONEWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  SHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONESHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  NARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  STANDALONENARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  SHORTQUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  QUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  AMPMS: ['ص', 'م'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'dd‏/MM‏/y',
    -    'd‏/M‏/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 5,
    -  WEEKENDRANGE: [4, 5],
    -  FIRSTWEEKCUTOFFDAY: 4
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ar_TD.
    - */
    -goog.i18n.DateTimeSymbols_ar_TD = {
    -  ZERODIGIT: 0x0660,
    -  ERAS: ['ق.م', 'م'],
    -  ERANAMES: ['قبل الميلاد', 'ميلادي'],
    -  NARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س', 'ك',
    -    'ب', 'د'],
    -  STANDALONENARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س',
    -    'ك', 'ب', 'د'],
    -  MONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو',
    -    'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر',
    -    'نوفمبر', 'ديسمبر'],
    -  STANDALONEMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  SHORTMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  STANDALONESHORTMONTHS: ['يناير', 'فبراير', 'مارس',
    -    'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس',
    -    'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  WEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONEWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  SHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONESHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  NARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  STANDALONENARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  SHORTQUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  QUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  AMPMS: ['ص', 'م'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'dd‏/MM‏/y',
    -    'd‏/M‏/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ar_TN.
    - */
    -goog.i18n.DateTimeSymbols_ar_TN = {
    -  ERAS: ['ق.م', 'م'],
    -  ERANAMES: ['قبل الميلاد', 'ميلادي'],
    -  NARROWMONTHS: ['ج', 'ف', 'م', 'أ', 'م', 'ج', 'ج', 'أ', 'س', 'أ',
    -    'ن', 'د'],
    -  STANDALONENARROWMONTHS: ['ج', 'ف', 'م', 'أ', 'م', 'ج', 'ج', 'أ', 'س',
    -    'أ', 'ن', 'د'],
    -  MONTHS: ['جانفي', 'فيفري', 'مارس', 'أفريل', 'ماي',
    -    'جوان', 'جويلية', 'أوت', 'سبتمبر', 'أكتوبر',
    -    'نوفمبر', 'ديسمبر'],
    -  STANDALONEMONTHS: ['جانفي', 'فيفري', 'مارس', 'أفريل',
    -    'ماي', 'جوان', 'جويلية', 'أوت', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  SHORTMONTHS: ['جانفي', 'فيفري', 'مارس', 'أفريل', 'ماي',
    -    'جوان', 'جويلية', 'أوت', 'سبتمبر', 'أكتوبر',
    -    'نوفمبر', 'ديسمبر'],
    -  STANDALONESHORTMONTHS: ['جانفي', 'فيفري', 'مارس', 'أفريل',
    -    'ماي', 'جوان', 'جويلية', 'أوت', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  WEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONEWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  SHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONESHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  NARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  STANDALONENARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  SHORTQUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  QUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  AMPMS: ['ص', 'م'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'y/MM/dd', 'y/M/d'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [4, 5],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ar_YE.
    - */
    -goog.i18n.DateTimeSymbols_ar_YE = {
    -  ZERODIGIT: 0x0660,
    -  ERAS: ['ق.م', 'م'],
    -  ERANAMES: ['قبل الميلاد', 'ميلادي'],
    -  NARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س', 'ك',
    -    'ب', 'د'],
    -  STANDALONENARROWMONTHS: ['ي', 'ف', 'م', 'أ', 'و', 'ن', 'ل', 'غ', 'س',
    -    'ك', 'ب', 'د'],
    -  MONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو',
    -    'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر',
    -    'نوفمبر', 'ديسمبر'],
    -  STANDALONEMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  SHORTMONTHS: ['يناير', 'فبراير', 'مارس', 'أبريل',
    -    'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر',
    -    'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  STANDALONESHORTMONTHS: ['يناير', 'فبراير', 'مارس',
    -    'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس',
    -    'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
    -  WEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONEWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  SHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  STANDALONESHORTWEEKDAYS: ['الأحد', 'الاثنين', 'الثلاثاء',
    -    'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    -  NARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  STANDALONENARROWWEEKDAYS: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    -  SHORTQUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  QUARTERS: ['الربع الأول', 'الربع الثاني',
    -    'الربع الثالث', 'الربع الرابع'],
    -  AMPMS: ['ص', 'م'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'dd‏/MM‏/y',
    -    'd‏/M‏/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [4, 5],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale as.
    - */
    -goog.i18n.DateTimeSymbols_as = {
    -  ZERODIGIT: 0x09E6,
    -  ERAS: ['BCE', 'CE'],
    -  ERANAMES: ['BCE', 'CE'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['জানুৱাৰী', 'ফেব্ৰুৱাৰী',
    -    'মাৰ্চ', 'এপ্ৰিল', 'মে', 'জুন',
    -    'জুলাই', 'আগষ্ট', 'ছেপ্তেম্বৰ',
    -    'অক্টোবৰ', 'নৱেম্বৰ',
    -    'ডিচেম্বৰ'],
    -  STANDALONEMONTHS: ['জানুৱাৰী',
    -    'ফেব্ৰুৱাৰী', 'মাৰ্চ', 'এপ্ৰিল',
    -    'মে', 'জুন', 'জুলাই', 'আগষ্ট',
    -    'ছেপ্তেম্বৰ', 'অক্টোবৰ',
    -    'নৱেম্বৰ', 'ডিচেম্বৰ'],
    -  SHORTMONTHS: ['জানু', 'ফেব্ৰু', 'মাৰ্চ',
    -    'এপ্ৰিল', 'মে', 'জুন', 'জুলাই', 'আগ',
    -    'সেপ্ট', 'অক্টো', 'নভে', 'ডিসে'],
    -  STANDALONESHORTMONTHS: ['জানু', 'ফেব্ৰু',
    -    'মাৰ্চ', 'এপ্ৰিল', 'মে', 'জুন',
    -    'জুলাই', 'আগ', 'সেপ্ট', 'অক্টো',
    -    'নভে', 'ডিসে'],
    -  WEEKDAYS: ['দেওবাৰ', 'সোমবাৰ',
    -    'মঙ্গলবাৰ', 'বুধবাৰ',
    -    'বৃহষ্পতিবাৰ', 'শুক্ৰবাৰ',
    -    'শনিবাৰ'],
    -  STANDALONEWEEKDAYS: ['দেওবাৰ', 'সোমবাৰ',
    -    'মঙ্গলবাৰ', 'বুধবাৰ',
    -    'বৃহষ্পতিবাৰ', 'শুক্ৰবাৰ',
    -    'শনিবাৰ'],
    -  SHORTWEEKDAYS: ['ৰবি', 'সোম', 'মঙ্গল', 'বুধ',
    -    'বৃহষ্পতি', 'শুক্ৰ', 'শনি'],
    -  STANDALONESHORTWEEKDAYS: ['ৰবি', 'সোম', 'মঙ্গল',
    -    'বুধ', 'বৃহষ্পতি', 'শুক্ৰ', 'শনি'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['প্ৰথম প্ৰহৰ',
    -    'দ্বিতীয় প্ৰহৰ',
    -    'তৃতীয় প্ৰহৰ', 'চতুৰ্থ প্ৰহৰ'],
    -  QUARTERS: ['প্ৰথম প্ৰহৰ',
    -    'দ্বিতীয় প্ৰহৰ',
    -    'তৃতীয় প্ৰহৰ', 'চতুৰ্থ প্ৰহৰ'],
    -  AMPMS: ['পূৰ্বাহ্ণ', 'অপৰাহ্ণ'],
    -  DATEFORMATS: ['EEEE, d MMMM, y', 'd MMMM, y', 'dd-MM-y', 'd-M-y'],
    -  TIMEFORMATS: ['h.mm.ss a zzzz', 'h.mm.ss a z', 'h.mm.ss a', 'h.mm. a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [6, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale as_IN.
    - */
    -goog.i18n.DateTimeSymbols_as_IN = goog.i18n.DateTimeSymbols_as;
    -
    -
    -/**
    - * Date/time formatting symbols for locale asa.
    - */
    -goog.i18n.DateTimeSymbols_asa = {
    -  ERAS: ['KM', 'BM'],
    -  ERANAMES: ['Kabla yakwe Yethu', 'Baada yakwe Yethu'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni', 'Julai',
    -    'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    -  STANDALONEMONTHS: ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni',
    -    'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep',
    -    'Okt', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul',
    -    'Ago', 'Sep', 'Okt', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alhamisi',
    -    'Ijumaa', 'Jumamosi'],
    -  STANDALONEWEEKDAYS: ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano',
    -    'Alhamisi', 'Ijumaa', 'Jumamosi'],
    -  SHORTWEEKDAYS: ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Ijm', 'Jmo'],
    -  STANDALONESHORTWEEKDAYS: ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Ijm', 'Jmo'],
    -  NARROWWEEKDAYS: ['J', 'J', 'J', 'J', 'A', 'I', 'J'],
    -  STANDALONENARROWWEEKDAYS: ['J', 'J', 'J', 'J', 'A', 'I', 'J'],
    -  SHORTQUARTERS: ['R1', 'R2', 'R3', 'R4'],
    -  QUARTERS: ['Robo 1', 'Robo 2', 'Robo 3', 'Robo 4'],
    -  AMPMS: ['icheheavo', 'ichamthi'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale asa_TZ.
    - */
    -goog.i18n.DateTimeSymbols_asa_TZ = goog.i18n.DateTimeSymbols_asa;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ast.
    - */
    -goog.i18n.DateTimeSymbols_ast = {
    -  ERAS: ['a.C.', 'd.C.'],
    -  ERANAMES: ['a.C.', 'd.C.'],
    -  NARROWMONTHS: ['X', 'F', 'M', 'A', 'M', 'X', 'X', 'A', 'S', 'O', 'P', 'A'],
    -  STANDALONENARROWMONTHS: ['X', 'F', 'M', 'A', 'M', 'X', 'X', 'A', 'S', 'O',
    -    'P', 'A'],
    -  MONTHS: ['de xineru', 'de febreru', 'de marzu', 'd’abril', 'de mayu',
    -    'de xunu', 'de xunetu', 'd’agostu', 'de setiembre', 'd’ochobre',
    -    'de payares', 'd’avientu'],
    -  STANDALONEMONTHS: ['xineru', 'febreru', 'marzu', 'abril', 'mayu', 'xunu',
    -    'xunetu', 'agostu', 'setiembre', 'ochobre', 'payares', 'avientu'],
    -  SHORTMONTHS: ['xin', 'feb', 'mar', 'abr', 'may', 'xun', 'xnt', 'ago', 'set',
    -    'och', 'pay', 'avi'],
    -  STANDALONESHORTMONTHS: ['Xin', 'Feb', 'Mar', 'Abr', 'May', 'Xun', 'Xnt',
    -    'Ago', 'Set', 'Och', 'Pay', 'Avi'],
    -  WEEKDAYS: ['domingu', 'llunes', 'martes', 'miércoles', 'xueves', 'vienres',
    -    'sábadu'],
    -  STANDALONEWEEKDAYS: ['domingu', 'llunes', 'martes', 'miércoles', 'xueves',
    -    'vienres', 'sábadu'],
    -  SHORTWEEKDAYS: ['dom', 'llu', 'mar', 'mie', 'xue', 'vie', 'sab'],
    -  STANDALONESHORTWEEKDAYS: ['dom', 'llu', 'mar', 'mie', 'xue', 'vie', 'sab'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'X', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'X', 'V', 'S'],
    -  SHORTQUARTERS: ['1T', '2T', '3T', '4T'],
    -  QUARTERS: ['1er trimestre', '2u trimestre', '3er trimestre', '4u trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM \'de\' y', 'd MMMM \'de\' y', 'd MMM y',
    -    'd/M/yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ast_ES.
    - */
    -goog.i18n.DateTimeSymbols_ast_ES = goog.i18n.DateTimeSymbols_ast;
    -
    -
    -/**
    - * Date/time formatting symbols for locale az_Cyrl.
    - */
    -goog.i18n.DateTimeSymbols_az_Cyrl = {
    -  ERAS: ['BCE', 'CE'],
    -  ERANAMES: ['BCE', 'CE'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['јанвар', 'феврал', 'март', 'апрел', 'май',
    -    'ијун', 'ијул', 'август', 'сентјабр',
    -    'октјабр', 'нојабр', 'декабр'],
    -  STANDALONEMONTHS: ['јанвар', 'феврал', 'март', 'апрел',
    -    'май', 'ијун', 'ијул', 'август', 'сентјабр',
    -    'октјабр', 'нојабр', 'декабр'],
    -  SHORTMONTHS: ['јанвар', 'феврал', 'март', 'апрел',
    -    'май', 'ијун', 'ијул', 'август', 'сентјабр',
    -    'октјабр', 'нојабр', 'декабр'],
    -  STANDALONESHORTMONTHS: ['јанвар', 'феврал', 'март',
    -    'апрел', 'май', 'ијун', 'ијул', 'август',
    -    'сентјабр', 'октјабр', 'нојабр', 'декабр'],
    -  WEEKDAYS: ['базар', 'базар ертәси',
    -    'чәршәнбә ахшамы', 'чәршәнбә',
    -    'ҹүмә ахшамы', 'ҹүмә', 'шәнбә'],
    -  STANDALONEWEEKDAYS: ['базар', 'базар ертәси',
    -    'чәршәнбә ахшамы', 'чәршәнбә',
    -    'ҹүмә ахшамы', 'ҹүмә', 'шәнбә'],
    -  SHORTWEEKDAYS: ['базар', 'базар ертәси',
    -    'чәршәнбә ахшамы', 'чәршәнбә',
    -    'ҹүмә ахшамы', 'ҹүмә', 'шәнбә'],
    -  STANDALONESHORTWEEKDAYS: ['базар', 'базар ертәси',
    -    'чәршәнбә ахшамы', 'чәршәнбә',
    -    'ҹүмә ахшамы', 'ҹүмә', 'шәнбә'],
    -  NARROWWEEKDAYS: ['7', '1', '2', '3', '4', '5', '6'],
    -  STANDALONENARROWWEEKDAYS: ['7', '1', '2', '3', '4', '5', '6'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d, MMMM, y', 'd MMMM, y', 'd MMM, y', 'dd.MM.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale az_Cyrl_AZ.
    - */
    -goog.i18n.DateTimeSymbols_az_Cyrl_AZ = goog.i18n.DateTimeSymbols_az_Cyrl;
    -
    -
    -/**
    - * Date/time formatting symbols for locale az_Latn.
    - */
    -goog.i18n.DateTimeSymbols_az_Latn = {
    -  ERAS: ['e.ə.', 'b.e.'],
    -  ERANAMES: ['eramızdan əvvəl', 'bizim eramızın'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['yanvar', 'fevral', 'mart', 'aprel', 'may', 'iyun', 'iyul', 'avqust',
    -    'sentyabr', 'oktyabr', 'noyabr', 'dekabr'],
    -  STANDALONEMONTHS: ['Yanvar', 'Fevral', 'Mart', 'Aprel', 'May', 'İyun',
    -    'İyul', 'Avqust', 'Sentyabr', 'Oktyabr', 'Noyabr', 'Dekabr'],
    -  SHORTMONTHS: ['yan', 'fev', 'mar', 'apr', 'may', 'iyn', 'iyl', 'avq', 'sen',
    -    'okt', 'noy', 'dek'],
    -  STANDALONESHORTMONTHS: ['yan', 'fev', 'mar', 'apr', 'may', 'iyn', 'iyl',
    -    'avq', 'sen', 'okt', 'noy', 'dek'],
    -  WEEKDAYS: ['bazar', 'bazar ertəsi', 'çərşənbə axşamı',
    -    'çərşənbə', 'cümə axşamı', 'cümə', 'şənbə'],
    -  STANDALONEWEEKDAYS: ['bazar', 'bazar ertəsi', 'çərşənbə axşamı',
    -    'çərşənbə', 'cümə axşamı', 'cümə', 'şənbə'],
    -  SHORTWEEKDAYS: ['B.', 'B.E.', 'Ç.A.', 'Ç.', 'C.A.', 'C.', 'Ş.'],
    -  STANDALONESHORTWEEKDAYS: ['B.', 'B.E.', 'Ç.A.', 'Ç.', 'C.A.', 'C.', 'Ş.'],
    -  NARROWWEEKDAYS: ['7', '1', '2', '3', '4', '5', '6'],
    -  STANDALONENARROWWEEKDAYS: ['7', '1', '2', '3', '4', '5', '6'],
    -  SHORTQUARTERS: ['1-ci kv.', '2-ci kv.', '3-cü kv.', '4-cü kv.'],
    -  QUARTERS: ['1-ci kvartal', '2-ci kvartal', '3-cü kvartal', '4-cü kvartal'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['d MMMM y, EEEE', 'd MMMM y', 'd MMM y', 'dd.MM.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale az_Latn_AZ.
    - */
    -goog.i18n.DateTimeSymbols_az_Latn_AZ = goog.i18n.DateTimeSymbols_az_Latn;
    -
    -
    -/**
    - * Date/time formatting symbols for locale bas.
    - */
    -goog.i18n.DateTimeSymbols_bas = {
    -  ERAS: ['b.Y.K', 'm.Y.K'],
    -  ERANAMES: ['bisū bi Yesù Krǐstò', 'i mbūs Yesù Krǐstò'],
    -  NARROWMONTHS: ['k', 'm', 'm', 'm', 'm', 'h', 'n', 'h', 'd', 'b', 'm', 'l'],
    -  STANDALONENARROWMONTHS: ['k', 'm', 'm', 'm', 'm', 'h', 'n', 'h', 'd', 'b',
    -    'm', 'l'],
    -  MONTHS: ['Kɔndɔŋ', 'Màcɛ̂l', 'Màtùmb', 'Màtop', 'M̀puyɛ',
    -    'Hìlòndɛ̀', 'Njèbà', 'Hìkaŋ', 'Dìpɔ̀s', 'Bìòôm', 'Màyɛsèp',
    -    'Lìbuy li ńyèe'],
    -  STANDALONEMONTHS: ['Kɔndɔŋ', 'Màcɛ̂l', 'Màtùmb', 'Màtop', 'M̀puyɛ',
    -    'Hìlòndɛ̀', 'Njèbà', 'Hìkaŋ', 'Dìpɔ̀s', 'Bìòôm', 'Màyɛsèp',
    -    'Lìbuy li ńyèe'],
    -  SHORTMONTHS: ['kɔn', 'mac', 'mat', 'mto', 'mpu', 'hil', 'nje', 'hik', 'dip',
    -    'bio', 'may', 'liɓ'],
    -  STANDALONESHORTMONTHS: ['kɔn', 'mac', 'mat', 'mto', 'mpu', 'hil', 'nje',
    -    'hik', 'dip', 'bio', 'may', 'liɓ'],
    -  WEEKDAYS: ['ŋgwà nɔ̂y', 'ŋgwà njaŋgumba', 'ŋgwà ûm', 'ŋgwà ŋgê',
    -    'ŋgwà mbɔk', 'ŋgwà kɔɔ', 'ŋgwà jôn'],
    -  STANDALONEWEEKDAYS: ['ŋgwà nɔ̂y', 'ŋgwà njaŋgumba', 'ŋgwà ûm',
    -    'ŋgwà ŋgê', 'ŋgwà mbɔk', 'ŋgwà kɔɔ', 'ŋgwà jôn'],
    -  SHORTWEEKDAYS: ['nɔy', 'nja', 'uum', 'ŋge', 'mbɔ', 'kɔɔ', 'jon'],
    -  STANDALONESHORTWEEKDAYS: ['nɔy', 'nja', 'uum', 'ŋge', 'mbɔ', 'kɔɔ',
    -    'jon'],
    -  NARROWWEEKDAYS: ['n', 'n', 'u', 'ŋ', 'm', 'k', 'j'],
    -  STANDALONENARROWWEEKDAYS: ['n', 'n', 'u', 'ŋ', 'm', 'k', 'j'],
    -  SHORTQUARTERS: ['K1s3', 'K2s3', 'K3s3', 'K4s3'],
    -  QUARTERS: ['Kèk bisu i soŋ iaâ', 'Kèk i ńyonos biɓaà i soŋ iaâ',
    -    'Kèk i ńyonos biaâ i soŋ iaâ', 'Kèk i ńyonos binâ i soŋ iaâ'],
    -  AMPMS: ['I bikɛ̂glà', 'I ɓugajɔp'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM, y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale bas_CM.
    - */
    -goog.i18n.DateTimeSymbols_bas_CM = goog.i18n.DateTimeSymbols_bas;
    -
    -
    -/**
    - * Date/time formatting symbols for locale be.
    - */
    -goog.i18n.DateTimeSymbols_be = {
    -  ERAS: ['да н.э.', 'н.э.'],
    -  ERANAMES: ['да н.э.', 'н.э.'],
    -  NARROWMONTHS: ['с', 'л', 'с', 'к', 'м', 'ч', 'л', 'ж', 'в', 'к',
    -    'л', 'с'],
    -  STANDALONENARROWMONTHS: ['с', 'л', 'с', 'к', 'м', 'ч', 'л', 'ж', 'в',
    -    'к', 'л', 'с'],
    -  MONTHS: ['студзеня', 'лютага', 'сакавіка',
    -    'красавіка', 'мая', 'чэрвеня', 'ліпеня',
    -    'жніўня', 'верасня', 'кастрычніка',
    -    'лістапада', 'снежня'],
    -  STANDALONEMONTHS: ['студзень', 'люты', 'сакавік',
    -    'красавік', 'май', 'чэрвень', 'ліпень',
    -    'жнівень', 'верасень', 'кастрычнік',
    -    'лістапад', 'снежань'],
    -  SHORTMONTHS: ['сту', 'лют', 'сак', 'кра', 'мая', 'чэр',
    -    'ліп', 'жні', 'вер', 'кас', 'ліс', 'сне'],
    -  STANDALONESHORTMONTHS: ['сту', 'лют', 'сак', 'кра', 'май',
    -    'чэр', 'ліп', 'жні', 'вер', 'кас', 'ліс', 'сне'],
    -  WEEKDAYS: ['нядзеля', 'панядзелак', 'аўторак',
    -    'серада', 'чацвер', 'пятніца', 'субота'],
    -  STANDALONEWEEKDAYS: ['нядзеля', 'панядзелак',
    -    'аўторак', 'серада', 'чацвер', 'пятніца',
    -    'субота'],
    -  SHORTWEEKDAYS: ['нд', 'пн', 'аў', 'ср', 'чц', 'пт', 'сб'],
    -  STANDALONESHORTWEEKDAYS: ['нд', 'пн', 'аў', 'ср', 'чц', 'пт',
    -    'сб'],
    -  NARROWWEEKDAYS: ['н', 'п', 'а', 'с', 'ч', 'п', 'с'],
    -  STANDALONENARROWWEEKDAYS: ['н', 'п', 'а', 'с', 'ч', 'п', 'с'],
    -  SHORTQUARTERS: ['1-шы кв.', '2-гі кв.', '3-ці кв.',
    -    '4-ты кв.'],
    -  QUARTERS: ['1-шы квартал', '2-гі квартал',
    -    '3-ці квартал', '4-ты квартал'],
    -  AMPMS: ['да палудня', 'пасля палудня'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd.M.y', 'd.M.yy'],
    -  TIMEFORMATS: ['HH.mm.ss zzzz', 'HH.mm.ss z', 'HH.mm.ss', 'HH.mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale be_BY.
    - */
    -goog.i18n.DateTimeSymbols_be_BY = goog.i18n.DateTimeSymbols_be;
    -
    -
    -/**
    - * Date/time formatting symbols for locale bem.
    - */
    -goog.i18n.DateTimeSymbols_bem = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Yesu', 'After Yesu'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'E', 'M', 'J', 'J', 'O', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'E', 'M', 'J', 'J', 'O', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januari', 'Februari', 'Machi', 'Epreo', 'Mei', 'Juni', 'Julai',
    -    'Ogasti', 'Septemba', 'Oktoba', 'Novemba', 'Disemba'],
    -  STANDALONEMONTHS: ['Januari', 'Februari', 'Machi', 'Epreo', 'Mei', 'Juni',
    -    'Julai', 'Ogasti', 'Septemba', 'Oktoba', 'Novemba', 'Disemba'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mac', 'Epr', 'Mei', 'Jun', 'Jul', 'Oga', 'Sep',
    -    'Okt', 'Nov', 'Dis'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mac', 'Epr', 'Mei', 'Jun', 'Jul',
    -    'Oga', 'Sep', 'Okt', 'Nov', 'Dis'],
    -  WEEKDAYS: ['Pa Mulungu', 'Palichimo', 'Palichibuli', 'Palichitatu',
    -    'Palichine', 'Palichisano', 'Pachibelushi'],
    -  STANDALONEWEEKDAYS: ['Pa Mulungu', 'Palichimo', 'Palichibuli', 'Palichitatu',
    -    'Palichine', 'Palichisano', 'Pachibelushi'],
    -  SHORTWEEKDAYS: ['Pa Mulungu', 'Palichimo', 'Palichibuli', 'Palichitatu',
    -    'Palichine', 'Palichisano', 'Pachibelushi'],
    -  STANDALONESHORTWEEKDAYS: ['Pa Mulungu', 'Palichimo', 'Palichibuli',
    -    'Palichitatu', 'Palichine', 'Palichisano', 'Pachibelushi'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['uluchelo', 'akasuba'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale bem_ZM.
    - */
    -goog.i18n.DateTimeSymbols_bem_ZM = goog.i18n.DateTimeSymbols_bem;
    -
    -
    -/**
    - * Date/time formatting symbols for locale bez.
    - */
    -goog.i18n.DateTimeSymbols_bez = {
    -  ERAS: ['KM', 'BM'],
    -  ERANAMES: ['Kabla ya Mtwaa', 'Baada ya Mtwaa'],
    -  NARROWMONTHS: ['H', 'V', 'D', 'T', 'H', 'S', 'S', 'N', 'T', 'K', 'K', 'K'],
    -  STANDALONENARROWMONTHS: ['H', 'V', 'D', 'T', 'H', 'S', 'S', 'N', 'T', 'K',
    -    'K', 'K'],
    -  MONTHS: ['pa mwedzi gwa hutala', 'pa mwedzi gwa wuvili',
    -    'pa mwedzi gwa wudatu', 'pa mwedzi gwa wutai', 'pa mwedzi gwa wuhanu',
    -    'pa mwedzi gwa sita', 'pa mwedzi gwa saba', 'pa mwedzi gwa nane',
    -    'pa mwedzi gwa tisa', 'pa mwedzi gwa kumi', 'pa mwedzi gwa kumi na moja',
    -    'pa mwedzi gwa kumi na mbili'],
    -  STANDALONEMONTHS: ['pa mwedzi gwa hutala', 'pa mwedzi gwa wuvili',
    -    'pa mwedzi gwa wudatu', 'pa mwedzi gwa wutai', 'pa mwedzi gwa wuhanu',
    -    'pa mwedzi gwa sita', 'pa mwedzi gwa saba', 'pa mwedzi gwa nane',
    -    'pa mwedzi gwa tisa', 'pa mwedzi gwa kumi', 'pa mwedzi gwa kumi na moja',
    -    'pa mwedzi gwa kumi na mbili'],
    -  SHORTMONTHS: ['Hut', 'Vil', 'Dat', 'Tai', 'Han', 'Sit', 'Sab', 'Nan', 'Tis',
    -    'Kum', 'Kmj', 'Kmb'],
    -  STANDALONESHORTMONTHS: ['Hut', 'Vil', 'Dat', 'Tai', 'Han', 'Sit', 'Sab',
    -    'Nan', 'Tis', 'Kum', 'Kmj', 'Kmb'],
    -  WEEKDAYS: ['pa mulungu', 'pa shahuviluha', 'pa hivili', 'pa hidatu',
    -    'pa hitayi', 'pa hihanu', 'pa shahulembela'],
    -  STANDALONEWEEKDAYS: ['pa mulungu', 'pa shahuviluha', 'pa hivili', 'pa hidatu',
    -    'pa hitayi', 'pa hihanu', 'pa shahulembela'],
    -  SHORTWEEKDAYS: ['Mul', 'Vil', 'Hiv', 'Hid', 'Hit', 'Hih', 'Lem'],
    -  STANDALONESHORTWEEKDAYS: ['Mul', 'Vil', 'Hiv', 'Hid', 'Hit', 'Hih', 'Lem'],
    -  NARROWWEEKDAYS: ['M', 'J', 'H', 'H', 'H', 'W', 'J'],
    -  STANDALONENARROWWEEKDAYS: ['M', 'J', 'H', 'H', 'H', 'W', 'J'],
    -  SHORTQUARTERS: ['L1', 'L2', 'L3', 'L4'],
    -  QUARTERS: ['Lobo 1', 'Lobo 2', 'Lobo 3', 'Lobo 4'],
    -  AMPMS: ['pamilau', 'pamunyi'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale bez_TZ.
    - */
    -goog.i18n.DateTimeSymbols_bez_TZ = goog.i18n.DateTimeSymbols_bez;
    -
    -
    -/**
    - * Date/time formatting symbols for locale bg_BG.
    - */
    -goog.i18n.DateTimeSymbols_bg_BG = {
    -  ERAS: ['пр.Хр.', 'сл.Хр.'],
    -  ERANAMES: ['преди Христа', 'след Христа'],
    -  NARROWMONTHS: ['я', 'ф', 'м', 'а', 'м', 'ю', 'ю', 'а', 'с', 'о',
    -    'н', 'д'],
    -  STANDALONENARROWMONTHS: ['я', 'ф', 'м', 'а', 'м', 'ю', 'ю', 'а', 'с',
    -    'о', 'н', 'д'],
    -  MONTHS: ['януари', 'февруари', 'март', 'април',
    -    'май', 'юни', 'юли', 'август', 'септември',
    -    'октомври', 'ноември', 'декември'],
    -  STANDALONEMONTHS: ['януари', 'февруари', 'март',
    -    'април', 'май', 'юни', 'юли', 'август',
    -    'септември', 'октомври', 'ноември',
    -    'декември'],
    -  SHORTMONTHS: ['ян.', 'февр.', 'март', 'апр.', 'май', 'юни',
    -    'юли', 'авг.', 'септ.', 'окт.', 'ноем.', 'дек.'],
    -  STANDALONESHORTMONTHS: ['ян.', 'февр.', 'март', 'апр.', 'май',
    -    'юни', 'юли', 'авг.', 'септ.', 'окт.', 'ноем.',
    -    'дек.'],
    -  WEEKDAYS: ['неделя', 'понеделник', 'вторник',
    -    'сряда', 'четвъртък', 'петък', 'събота'],
    -  STANDALONEWEEKDAYS: ['неделя', 'понеделник', 'вторник',
    -    'сряда', 'четвъртък', 'петък', 'събота'],
    -  SHORTWEEKDAYS: ['нд', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],
    -  STANDALONESHORTWEEKDAYS: ['нд', 'пн', 'вт', 'ср', 'чт', 'пт',
    -    'сб'],
    -  NARROWWEEKDAYS: ['н', 'п', 'в', 'с', 'ч', 'п', 'с'],
    -  STANDALONENARROWWEEKDAYS: ['н', 'п', 'в', 'с', 'ч', 'п', 'с'],
    -  SHORTQUARTERS: ['1. трим.', '2. трим.', '3. трим.',
    -    '4. трим.'],
    -  QUARTERS: ['1. тримесечие', '2. тримесечие',
    -    '3. тримесечие', '4. тримесечие'],
    -  AMPMS: ['пр.об.', 'сл.об.'],
    -  DATEFORMATS: ['EEEE, d MMMM y \'г\'.', 'd MMMM y \'г\'.', 'd.MM.y \'г\'.',
    -    'd.MM.yy \'г\'.'],
    -  TIMEFORMATS: ['H:mm:ss zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale bm.
    - */
    -goog.i18n.DateTimeSymbols_bm = {
    -  ERAS: ['J.-C. ɲɛ', 'ni J.-C.'],
    -  ERANAMES: ['jezu krisiti ɲɛ', 'jezu krisiti minkɛ'],
    -  NARROWMONTHS: ['Z', 'F', 'M', 'A', 'M', 'Z', 'Z', 'U', 'S', 'Ɔ', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['Z', 'F', 'M', 'A', 'M', 'Z', 'Z', 'U', 'S', 'Ɔ',
    -    'N', 'D'],
    -  MONTHS: ['zanwuye', 'feburuye', 'marisi', 'awirili', 'mɛ', 'zuwɛn',
    -    'zuluye', 'uti', 'sɛtanburu', 'ɔkutɔburu', 'nowanburu', 'desanburu'],
    -  STANDALONEMONTHS: ['zanwuye', 'feburuye', 'marisi', 'awirili', 'mɛ',
    -    'zuwɛn', 'zuluye', 'uti', 'sɛtanburu', 'ɔkutɔburu', 'nowanburu',
    -    'desanburu'],
    -  SHORTMONTHS: ['zan', 'feb', 'mar', 'awi', 'mɛ', 'zuw', 'zul', 'uti', 'sɛt',
    -    'ɔku', 'now', 'des'],
    -  STANDALONESHORTMONTHS: ['zan', 'feb', 'mar', 'awi', 'mɛ', 'zuw', 'zul',
    -    'uti', 'sɛt', 'ɔku', 'now', 'des'],
    -  WEEKDAYS: ['kari', 'ntɛnɛ', 'tarata', 'araba', 'alamisa', 'juma', 'sibiri'],
    -  STANDALONEWEEKDAYS: ['kari', 'ntɛnɛ', 'tarata', 'araba', 'alamisa', 'juma',
    -    'sibiri'],
    -  SHORTWEEKDAYS: ['kar', 'ntɛ', 'tar', 'ara', 'ala', 'jum', 'sib'],
    -  STANDALONESHORTWEEKDAYS: ['kar', 'ntɛ', 'tar', 'ara', 'ala', 'jum', 'sib'],
    -  NARROWWEEKDAYS: ['K', 'N', 'T', 'A', 'A', 'J', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['K', 'N', 'T', 'A', 'A', 'J', 'S'],
    -  SHORTQUARTERS: ['KS1', 'KS2', 'KS3', 'KS4'],
    -  QUARTERS: ['kalo saba fɔlɔ', 'kalo saba filanan', 'kalo saba sabanan',
    -    'kalo saba naaninan'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM, y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale bm_Latn.
    - */
    -goog.i18n.DateTimeSymbols_bm_Latn = goog.i18n.DateTimeSymbols_bm;
    -
    -
    -/**
    - * Date/time formatting symbols for locale bm_Latn_ML.
    - */
    -goog.i18n.DateTimeSymbols_bm_Latn_ML = goog.i18n.DateTimeSymbols_bm;
    -
    -
    -/**
    - * Date/time formatting symbols for locale bn_BD.
    - */
    -goog.i18n.DateTimeSymbols_bn_BD = {
    -  ZERODIGIT: 0x09E6,
    -  ERAS: ['খ্রিস্টপূর্ব', 'খৃষ্টাব্দ'],
    -  ERANAMES: ['খ্রিস্টপূর্ব',
    -    'খৃষ্টাব্দ'],
    -  NARROWMONTHS: ['জা', 'ফে', 'মা', 'এ', 'মে', 'জুন',
    -    'জু', 'আ', 'সে', 'অ', 'ন', 'ডি'],
    -  STANDALONENARROWMONTHS: ['জা', 'ফে', 'মা', 'এ', 'মে',
    -    'জুন', 'জু', 'আ', 'সে', 'অ', 'ন', 'ডি'],
    -  MONTHS: ['জানুয়ারী', 'ফেব্রুয়ারী',
    -    'মার্চ', 'এপ্রিল', 'মে', 'জুন',
    -    'জুলাই', 'আগস্ট', 'সেপ্টেম্বর',
    -    'অক্টোবর', 'নভেম্বর',
    -    'ডিসেম্বর'],
    -  STANDALONEMONTHS: ['জানুয়ারী',
    -    'ফেব্রুয়ারী', 'মার্চ',
    -    'এপ্রিল', 'মে', 'জুন', 'জুলাই',
    -    'আগস্ট', 'সেপ্টেম্বর',
    -    'অক্টোবর', 'নভেম্বর',
    -    'ডিসেম্বর'],
    -  SHORTMONTHS: ['জানুয়ারী',
    -    'ফেব্রুয়ারী', 'মার্চ',
    -    'এপ্রিল', 'মে', 'জুন', 'জুলাই',
    -    'আগস্ট', 'সেপ্টেম্বর',
    -    'অক্টোবর', 'নভেম্বর',
    -    'ডিসেম্বর'],
    -  STANDALONESHORTMONTHS: ['জানুয়ারী',
    -    'ফেব্রুয়ারী', 'মার্চ',
    -    'এপ্রিল', 'মে', 'জুন', 'জুলাই',
    -    'আগস্ট', 'সেপ্টেম্বর',
    -    'অক্টোবর', 'নভেম্বর',
    -    'ডিসেম্বর'],
    -  WEEKDAYS: ['রবিবার', 'সোমবার',
    -    'মঙ্গলবার', 'বুধবার',
    -    'বৃহস্পতিবার', 'শুক্রবার',
    -    'শনিবার'],
    -  STANDALONEWEEKDAYS: ['রবিবার', 'সোমবার',
    -    'মঙ্গলবার', 'বুধবার',
    -    'বৃহষ্পতিবার', 'শুক্রবার',
    -    'শনিবার'],
    -  SHORTWEEKDAYS: ['রবি', 'সোম', 'মঙ্গল', 'বুধ',
    -    'বৃহস্পতি', 'শুক্র', 'শনি'],
    -  STANDALONESHORTWEEKDAYS: ['রবি', 'সোম', 'মঙ্গল',
    -    'বুধ', 'বৃহস্পতি', 'শুক্র', 'শনি'],
    -  NARROWWEEKDAYS: ['র', 'সো', 'ম', 'বু', 'বৃ', 'শু', 'শ'],
    -  STANDALONENARROWWEEKDAYS: ['র', 'সো', 'ম', 'বু', 'বৃ',
    -    'শু', 'শ'],
    -  SHORTQUARTERS: [
    -    'প্র. ত্রৈ. এক. চতুর্থাংশ',
    -    'দ্বি.ত্রৈ.এক. চতুর্থাংশ',
    -    'তৃ.ত্রৈ.এক.চতুর্থাংশ',
    -    'চ.ত্রৈ.এক চতুর্থাংশ'],
    -  QUARTERS: [
    -    'প্রথম ত্রৈমাসিকের এক চতুর্থাংশ',
    -    'দ্বিতীয় ত্রৈমাসিকের এক চতুর্থাংশ',
    -    'তৃতীয় ত্রৈমাসিকের এক চতুর্থাংশ',
    -    'চতুর্থ ত্রৈমাসিকের এক চতুর্থাংশ'],
    -  AMPMS: ['am', 'pm'],
    -  DATEFORMATS: ['EEEE, d MMMM, y', 'd MMMM, y', 'd MMM, y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 4,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale bn_IN.
    - */
    -goog.i18n.DateTimeSymbols_bn_IN = {
    -  ZERODIGIT: 0x09E6,
    -  ERAS: ['খ্রিস্টপূর্ব', 'খৃষ্টাব্দ'],
    -  ERANAMES: ['খ্রিস্টপূর্ব',
    -    'খৃষ্টাব্দ'],
    -  NARROWMONTHS: ['জা', 'ফে', 'মা', 'এ', 'মে', 'জুন',
    -    'জু', 'আ', 'সে', 'অ', 'ন', 'ডি'],
    -  STANDALONENARROWMONTHS: ['জা', 'ফে', 'মা', 'এ', 'মে',
    -    'জুন', 'জু', 'আ', 'সে', 'অ', 'ন', 'ডি'],
    -  MONTHS: ['জানুয়ারী', 'ফেব্রুয়ারী',
    -    'মার্চ', 'এপ্রিল', 'মে', 'জুন',
    -    'জুলাই', 'আগস্ট', 'সেপ্টেম্বর',
    -    'অক্টোবর', 'নভেম্বর',
    -    'ডিসেম্বর'],
    -  STANDALONEMONTHS: ['জানুয়ারী',
    -    'ফেব্রুয়ারী', 'মার্চ',
    -    'এপ্রিল', 'মে', 'জুন', 'জুলাই',
    -    'আগস্ট', 'সেপ্টেম্বর',
    -    'অক্টোবর', 'নভেম্বর',
    -    'ডিসেম্বর'],
    -  SHORTMONTHS: ['জানুয়ারী',
    -    'ফেব্রুয়ারী', 'মার্চ',
    -    'এপ্রিল', 'মে', 'জুন', 'জুলাই',
    -    'আগস্ট', 'সেপ্টেম্বর',
    -    'অক্টোবর', 'নভেম্বর',
    -    'ডিসেম্বর'],
    -  STANDALONESHORTMONTHS: ['জানুয়ারী',
    -    'ফেব্রুয়ারী', 'মার্চ',
    -    'এপ্রিল', 'মে', 'জুন', 'জুলাই',
    -    'আগস্ট', 'সেপ্টেম্বর',
    -    'অক্টোবর', 'নভেম্বর',
    -    'ডিসেম্বর'],
    -  WEEKDAYS: ['রবিবার', 'সোমবার',
    -    'মঙ্গলবার', 'বুধবার',
    -    'বৃহস্পতিবার', 'শুক্রবার',
    -    'শনিবার'],
    -  STANDALONEWEEKDAYS: ['রবিবার', 'সোমবার',
    -    'মঙ্গলবার', 'বুধবার',
    -    'বৃহষ্পতিবার', 'শুক্রবার',
    -    'শনিবার'],
    -  SHORTWEEKDAYS: ['রবি', 'সোম', 'মঙ্গল', 'বুধ',
    -    'বৃহস্পতি', 'শুক্র', 'শনি'],
    -  STANDALONESHORTWEEKDAYS: ['রবি', 'সোম', 'মঙ্গল',
    -    'বুধ', 'বৃহস্পতি', 'শুক্র', 'শনি'],
    -  NARROWWEEKDAYS: ['র', 'সো', 'ম', 'বু', 'বৃ', 'শু', 'শ'],
    -  STANDALONENARROWWEEKDAYS: ['র', 'সো', 'ম', 'বু', 'বৃ',
    -    'শু', 'শ'],
    -  SHORTQUARTERS: ['ত্রৈমাসিক', 'ষাণ্মাসিক',
    -    'তৃ.ত্রৈ.এক.চতুর্থাংশ',
    -    'বার্ষিক'],
    -  QUARTERS: ['ত্রৈমাসিক', 'ষাণ্মাসিক',
    -    'তৃতীয় চতুর্থাংশ', 'বার্ষিক'],
    -  AMPMS: ['am', 'pm'],
    -  DATEFORMATS: ['EEEE, d MMMM, y', 'd MMMM, y', 'd MMM, y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [6, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale bo.
    - */
    -goog.i18n.DateTimeSymbols_bo = {
    -  ERAS: ['སྤྱི་ལོ་སྔོན།', 'སྤྱི་ལོ།'],
    -  ERANAMES: ['སྤྱི་ལོ་སྔོན།',
    -    'སྤྱི་ལོ།'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['ཟླ་བ་དང་པོ་',
    -    'ཟླ་བ་གཉིས་པ་', 'ཟླ་བ་སུམ་པ་',
    -    'ཟླ་བ་བཞི་པ་', 'ཟླ་བ་ལྔ་པ་',
    -    'ཟླ་བ་དྲུག་པ་',
    -    'ཟླ་བ་བདུན་པ་',
    -    'ཟླ་བ་བརྒྱད་པ་',
    -    'ཟླ་བ་དགུ་པ་', 'ཟླ་བ་བཅུ་པ་',
    -    'ཟླ་བ་བཅུ་གཅིག་པ་',
    -    'ཟླ་བ་བཅུ་གཉིས་པ་'],
    -  STANDALONEMONTHS: ['ཟླ་བ་དང་པོ་',
    -    'ཟླ་བ་གཉིས་པ་', 'ཟླ་བ་སུམ་པ་',
    -    'ཟླ་བ་བཞི་པ་', 'ཟླ་བ་ལྔ་པ་',
    -    'ཟླ་བ་དྲུག་པ་',
    -    'ཟླ་བ་བདུན་པ་',
    -    'ཟླ་བ་བརྒྱད་པ་',
    -    'ཟླ་བ་དགུ་པ་', 'ཟླ་བ་བཅུ་པ་',
    -    'ཟླ་བ་བཅུ་གཅིག་པ་',
    -    'ཟླ་བ་བཅུ་གཉིས་པ་'],
    -  SHORTMONTHS: ['ཟླ་༡', 'ཟླ་༢', 'ཟླ་༣', 'ཟླ་༤',
    -    'ཟླ་༥', 'ཟླ་༦', 'ཟླ་༧', 'ཟླ་༨',
    -    'ཟླ་༩', 'ཟླ་༡༠', 'ཟླ་༡༡', 'ཟླ་༡༢'],
    -  STANDALONESHORTMONTHS: ['ཟླ་༡', 'ཟླ་༢', 'ཟླ་༣',
    -    'ཟླ་༤', 'ཟླ་༥', 'ཟླ་༦', 'ཟླ་༧',
    -    'ཟླ་༨', 'ཟླ་༩', 'ཟླ་༡༠', 'ཟླ་༡༡',
    -    'ཟླ་༡༢'],
    -  WEEKDAYS: ['གཟའ་ཉི་མ་', 'གཟའ་ཟླ་བ་',
    -    'གཟའ་མིག་དམར་', 'གཟའ་ལྷག་པ་',
    -    'གཟའ་ཕུར་བུ་', 'གཟའ་པ་སངས་',
    -    'གཟའ་སྤེན་པ་'],
    -  STANDALONEWEEKDAYS: ['གཟའ་ཉི་མ་',
    -    'གཟའ་ཟླ་བ་', 'གཟའ་མིག་དམར་',
    -    'གཟའ་ལྷག་པ་', 'གཟའ་ཕུར་བུ་',
    -    'གཟའ་པ་སངས་', 'གཟའ་སྤེན་པ་'],
    -  SHORTWEEKDAYS: ['ཉི་མ་', 'ཟླ་བ་',
    -    'མིག་དམར་', 'ལྷག་པ་', 'ཕུར་བུ་',
    -    'པ་སངས་', 'སྤེན་པ་'],
    -  STANDALONESHORTWEEKDAYS: ['ཉི་མ་', 'ཟླ་བ་',
    -    'མིག་དམར་', 'ལྷག་པ་', 'ཕུར་བུ་',
    -    'པ་སངས་', 'སྤེན་པ་'],
    -  NARROWWEEKDAYS: ['ཉི', 'ཟླ', 'མི', 'ལྷ', 'ཕུ', 'པ',
    -    'སྤེ'],
    -  STANDALONENARROWWEEKDAYS: ['ཉི', 'ཟླ', 'མི', 'ལྷ', 'ཕུ',
    -    'པ', 'སྤེ'],
    -  SHORTQUARTERS: ['དུས་ཚིགས་དང་པོ།',
    -    'དུས་ཚིགས་གཉིས་པ།',
    -    '་དུས་ཚིགས་གསུམ་པ།',
    -    'དུས་ཚིགས་བཞི་པ།'],
    -  QUARTERS: ['དུས་ཚིགས་དང་པོ།',
    -    'དུས་ཚིགས་གཉིས་པ།',
    -    '་དུས་ཚིགས་གསུམ་པ།',
    -    'དུས་ཚིགས་བཞི་པ།'],
    -  AMPMS: ['སྔ་དྲོ་', 'ཕྱི་དྲོ་'],
    -  DATEFORMATS: ['y MMMM d, EEEE',
    -    'སྤྱི་ལོ་y MMMMའི་ཙེས་dད',
    -    'y ལོ་འི་MMMཙེས་d', 'y-MM-dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale bo_CN.
    - */
    -goog.i18n.DateTimeSymbols_bo_CN = goog.i18n.DateTimeSymbols_bo;
    -
    -
    -/**
    - * Date/time formatting symbols for locale bo_IN.
    - */
    -goog.i18n.DateTimeSymbols_bo_IN = goog.i18n.DateTimeSymbols_bo;
    -
    -
    -/**
    - * Date/time formatting symbols for locale br_FR.
    - */
    -goog.i18n.DateTimeSymbols_br_FR = {
    -  ERAS: ['BCE', 'CE'],
    -  ERANAMES: ['BCE', 'CE'],
    -  NARROWMONTHS: ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10',
    -    '11', '12'],
    -  STANDALONENARROWMONTHS: ['01', '02', '03', '04', '05', '06', '07', '08', '09',
    -    '10', '11', '12'],
    -  MONTHS: ['Genver', 'Cʼhwevrer', 'Meurzh', 'Ebrel', 'Mae', 'Mezheven',
    -    'Gouere', 'Eost', 'Gwengolo', 'Here', 'Du', 'Kerzu'],
    -  STANDALONEMONTHS: ['Genver', 'Cʼhwevrer', 'Meurzh', 'Ebrel', 'Mae',
    -    'Mezheven', 'Gouere', 'Eost', 'Gwengolo', 'Here', 'Du', 'Kerzu'],
    -  SHORTMONTHS: ['Gen', 'Cʼhwe', 'Meur', 'Ebr', 'Mae', 'Mezh', 'Goue', 'Eost',
    -    'Gwen', 'Here', 'Du', 'Ker'],
    -  STANDALONESHORTMONTHS: ['Gen', 'Cʼhwe', 'Meur', 'Ebr', 'Mae', 'Mezh', 'Goue',
    -    'Eost', 'Gwen', 'Here', 'Du', 'Ker'],
    -  WEEKDAYS: ['Sul', 'Lun', 'Meurzh', 'Mercʼher', 'Yaou', 'Gwener', 'Sadorn'],
    -  STANDALONEWEEKDAYS: ['Sul', 'Lun', 'Meurzh', 'Mercʼher', 'Yaou', 'Gwener',
    -    'Sadorn'],
    -  SHORTWEEKDAYS: ['Sul', 'Lun', 'Meu.', 'Mer.', 'Yaou', 'Gwe.', 'Sad.'],
    -  STANDALONESHORTWEEKDAYS: ['Sul', 'Lun', 'Meu.', 'Mer.', 'Yaou', 'Gwe.',
    -    'Sad.'],
    -  NARROWWEEKDAYS: ['Su', 'L', 'Mz', 'Mc', 'Y', 'G', 'Sa'],
    -  STANDALONENARROWWEEKDAYS: ['Su', 'L', 'Mz', 'Mc', 'Y', 'G', 'Sa'],
    -  SHORTQUARTERS: ['1añ trim.', '2l trim.', '3e trim.', '4e trim.'],
    -  QUARTERS: ['1añ trimiziad', '2l trimiziad', '3e trimiziad', '4e trimiziad'],
    -  AMPMS: ['A.M.', 'G.M.'],
    -  DATEFORMATS: ['y MMMM d, EEEE', 'y MMMM d', 'y MMM d', 'y-MM-dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale brx.
    - */
    -goog.i18n.DateTimeSymbols_brx = {
    -  ERAS: ['ईसा.पूर्व', 'सन'],
    -  ERANAMES: ['ईसा.पूर्व', 'सन'],
    -  NARROWMONTHS: ['ज', 'फे', 'मा', 'ए', 'मे', 'जु', 'जु',
    -    'आ', 'से', 'अ', 'न', 'दि'],
    -  STANDALONENARROWMONTHS: ['ज', 'फे', 'मा', 'ए', 'मे', 'जु',
    -    'जु', 'आ', 'से', 'अ', 'न', 'दि'],
    -  MONTHS: ['जानुवारी', 'फेब्रुवारी',
    -    'मार्स', 'एफ्रिल', 'मे', 'जुन',
    -    'जुलाइ', 'आगस्थ', 'सेबथेज्ब़र',
    -    'अखथबर', 'नबेज्ब़र',
    -    'दिसेज्ब़र'],
    -  STANDALONEMONTHS: ['जानुवारी',
    -    'फेब्रुवारी', 'मार्स', 'एफ्रिल',
    -    'मे', 'जुन', 'जुलाइ', 'आगस्थ',
    -    'सेबथेज्ब़र', 'अखथबर',
    -    'नबेज्ब़र', 'दिसेज्ब़र'],
    -  SHORTMONTHS: ['जानुवारी', 'फेब्रुवारी',
    -    'मार्स', 'एफ्रिल', 'मे', 'जुन',
    -    'जुलाइ', 'आगस्थ', 'सेबथेज्ब़र',
    -    'अखथबर', 'नबेज्ब़र',
    -    'दिसेज्ब़र'],
    -  STANDALONESHORTMONTHS: ['जानुवारी',
    -    'फेब्रुवारी', 'मार्स', 'एफ्रिल',
    -    'मे', 'जुन', 'जुलाइ', 'आगस्थ',
    -    'सेबथेज्ब़र', 'अखथबर',
    -    'नबेज्ब़र', 'दिसेज्ब़र'],
    -  WEEKDAYS: ['रबिबार', 'समबार', 'मंगलबार',
    -    'बुदबार', 'बिसथिबार',
    -    'सुखुरबार', 'सुनिबार'],
    -  STANDALONEWEEKDAYS: ['रबिबार', 'समबार',
    -    'मंगलबार', 'बुदबार', 'बिसथिबार',
    -    'सुखुरबार', 'सुनिबार'],
    -  SHORTWEEKDAYS: ['रबि', 'सम', 'मंगल', 'बुद',
    -    'बिसथि', 'सुखुर', 'सुनि'],
    -  STANDALONESHORTWEEKDAYS: ['रबि', 'सम', 'मंगल', 'बुद',
    -    'बिसथि', 'सुखुर', 'सुनि'],
    -  NARROWWEEKDAYS: ['र', 'स', 'मं', 'बु', 'बि', 'सु',
    -    'सु'],
    -  STANDALONENARROWWEEKDAYS: ['र', 'स', 'मं', 'बु', 'बि',
    -    'सु', 'सु'],
    -  SHORTQUARTERS: [
    -    'सिथासे/खोन्दोसे/बाहागोसे',
    -    'खावसे/खोन्दोनै/बाहागोनै',
    -    'खावथाम/खोन्दोथाम/बाहागोथाम',
    -    'खावब्रै/खोन्दोब्रै/फुरा/आबुं'],
    -  QUARTERS: [
    -    'सिथासे/खोन्दोसे/बाहागोसे',
    -    'खावसे/खोन्दोनै/बाहागोनै',
    -    'खावथाम/खोन्दोथाम/बाहागोथाम',
    -    'खावब्रै/खोन्दोब्रै/फुरा/आबुं'],
    -  AMPMS: ['फुं', 'बेलासे'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale brx_IN.
    - */
    -goog.i18n.DateTimeSymbols_brx_IN = goog.i18n.DateTimeSymbols_brx;
    -
    -
    -/**
    - * Date/time formatting symbols for locale bs.
    - */
    -goog.i18n.DateTimeSymbols_bs = {
    -  ERAS: ['p. n. e.', 'n. e.'],
    -  ERANAMES: ['Prije nove ere', 'Nove ere'],
    -  NARROWMONTHS: ['j', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['j', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o',
    -    'n', 'd'],
    -  MONTHS: ['januar', 'februar', 'mart', 'april', 'maj', 'juni', 'juli',
    -    'august', 'septembar', 'oktobar', 'novembar', 'decembar'],
    -  STANDALONEMONTHS: ['januar', 'februar', 'mart', 'april', 'maj', 'juni',
    -    'juli', 'august', 'septembar', 'oktobar', 'novembar', 'decembar'],
    -  SHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'aug', 'sep',
    -    'okt', 'nov', 'dec'],
    -  STANDALONESHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul',
    -    'aug', 'sep', 'okt', 'nov', 'dec'],
    -  WEEKDAYS: ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda', 'četvrtak',
    -    'petak', 'subota'],
    -  STANDALONEWEEKDAYS: ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda',
    -    'četvrtak', 'petak', 'subota'],
    -  SHORTWEEKDAYS: ['ned', 'pon', 'uto', 'sri', 'čet', 'pet', 'sub'],
    -  STANDALONESHORTWEEKDAYS: ['ned', 'pon', 'uto', 'sri', 'čet', 'pet', 'sub'],
    -  NARROWWEEKDAYS: ['N', 'P', 'U', 'S', 'Č', 'P', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['n', 'p', 'u', 's', 'č', 'p', 's'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['Prvi kvartal', 'Drugi kvartal', 'Treći kvartal',
    -    'Četvrti kvartal'],
    -  AMPMS: ['prije podne', 'popodne'],
    -  DATEFORMATS: ['EEEE, dd. MMMM y.', 'dd. MMMM y.', 'dd. MMM. y.', 'dd.MM.yy.'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'u\' {0}', '{1} \'u\' {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale bs_Cyrl.
    - */
    -goog.i18n.DateTimeSymbols_bs_Cyrl = {
    -  ERAS: ['п. н. е.', 'н. е.'],
    -  ERANAMES: ['Пре нове ере', 'Нове ере'],
    -  NARROWMONTHS: ['ј', 'ф', 'м', 'а', 'м', 'ј', 'ј', 'а', 'с', 'о',
    -    'н', 'д'],
    -  STANDALONENARROWMONTHS: ['ј', 'ф', 'м', 'а', 'м', 'ј', 'ј', 'а', 'с',
    -    'о', 'н', 'д'],
    -  MONTHS: ['јануар', 'фебруар', 'март', 'април', 'мај',
    -    'јуни', 'јули', 'август', 'септембар',
    -    'октобар', 'новембар', 'децембар'],
    -  STANDALONEMONTHS: ['јануар', 'фебруар', 'март', 'април',
    -    'мај', 'јуни', 'јули', 'август', 'септембар',
    -    'октобар', 'новембар', 'децембар'],
    -  SHORTMONTHS: ['јан', 'феб', 'мар', 'апр', 'мај', 'јун',
    -    'јул', 'авг', 'сеп', 'окт', 'нов', 'дец'],
    -  STANDALONESHORTMONTHS: ['јан', 'феб', 'мар', 'апр', 'мај',
    -    'јун', 'јул', 'авг', 'сеп', 'окт', 'нов', 'дец'],
    -  WEEKDAYS: ['недеља', 'понедељак', 'уторак',
    -    'сриједа', 'четвртак', 'петак', 'субота'],
    -  STANDALONEWEEKDAYS: ['недеља', 'понедељак', 'уторак',
    -    'сриједа', 'четвртак', 'петак', 'субота'],
    -  SHORTWEEKDAYS: ['нед', 'пон', 'уто', 'сри', 'чет', 'пет',
    -    'суб'],
    -  STANDALONESHORTWEEKDAYS: ['нед', 'пон', 'уто', 'сри', 'чет',
    -    'пет', 'суб'],
    -  NARROWWEEKDAYS: ['н', 'п', 'у', 'с', 'ч', 'п', 'с'],
    -  STANDALONENARROWWEEKDAYS: ['н', 'п', 'у', 'с', 'ч', 'п', 'с'],
    -  SHORTQUARTERS: ['К1', 'К2', 'К3', 'К4'],
    -  QUARTERS: ['Прво тромесечје', 'Друго тромесечје',
    -    'Треће тромесечје', 'Четврто тромесечје'],
    -  AMPMS: ['пре подне', 'поподне'],
    -  DATEFORMATS: ['EEEE, dd. MMMM y.', 'dd. MMMM y.', 'dd.MM.y.', 'd.M.yy.'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale bs_Cyrl_BA.
    - */
    -goog.i18n.DateTimeSymbols_bs_Cyrl_BA = goog.i18n.DateTimeSymbols_bs_Cyrl;
    -
    -
    -/**
    - * Date/time formatting symbols for locale bs_Latn.
    - */
    -goog.i18n.DateTimeSymbols_bs_Latn = goog.i18n.DateTimeSymbols_bs;
    -
    -
    -/**
    - * Date/time formatting symbols for locale bs_Latn_BA.
    - */
    -goog.i18n.DateTimeSymbols_bs_Latn_BA = goog.i18n.DateTimeSymbols_bs;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ca_AD.
    - */
    -goog.i18n.DateTimeSymbols_ca_AD = {
    -  ERAS: ['aC', 'dC'],
    -  ERANAMES: ['abans de Crist', 'després de Crist'],
    -  NARROWMONTHS: ['GN', 'FB', 'MÇ', 'AB', 'MG', 'JN', 'JL', 'AG', 'ST', 'OC',
    -    'NV', 'DS'],
    -  STANDALONENARROWMONTHS: ['GN', 'FB', 'MÇ', 'AB', 'MG', 'JN', 'JL', 'AG',
    -    'ST', 'OC', 'NV', 'DS'],
    -  MONTHS: ['gener', 'febrer', 'març', 'abril', 'maig', 'juny', 'juliol',
    -    'agost', 'setembre', 'octubre', 'novembre', 'desembre'],
    -  STANDALONEMONTHS: ['gener', 'febrer', 'març', 'abril', 'maig', 'juny',
    -    'juliol', 'agost', 'setembre', 'octubre', 'novembre', 'desembre'],
    -  SHORTMONTHS: ['gen.', 'febr.', 'març', 'abr.', 'maig', 'juny', 'jul.', 'ag.',
    -    'set.', 'oct.', 'nov.', 'des.'],
    -  STANDALONESHORTMONTHS: ['gen.', 'febr.', 'març', 'abr.', 'maig', 'juny',
    -    'jul.', 'ag.', 'set.', 'oct.', 'nov.', 'des.'],
    -  WEEKDAYS: ['diumenge', 'dilluns', 'dimarts', 'dimecres', 'dijous',
    -    'divendres', 'dissabte'],
    -  STANDALONEWEEKDAYS: ['diumenge', 'dilluns', 'dimarts', 'dimecres', 'dijous',
    -    'divendres', 'dissabte'],
    -  SHORTWEEKDAYS: ['dg.', 'dl.', 'dt.', 'dc.', 'dj.', 'dv.', 'ds.'],
    -  STANDALONESHORTWEEKDAYS: ['dg.', 'dl.', 'dt.', 'dc.', 'dj.', 'dv.', 'ds.'],
    -  NARROWWEEKDAYS: ['dg', 'dl', 'dt', 'dc', 'dj', 'dv', 'ds'],
    -  STANDALONENARROWWEEKDAYS: ['dg', 'dl', 'dt', 'dc', 'dj', 'dv', 'ds'],
    -  SHORTQUARTERS: ['1T', '2T', '3T', '4T'],
    -  QUARTERS: ['1r trimestre', '2n trimestre', '3r trimestre', '4t trimestre'],
    -  AMPMS: ['a. m.', 'p. m.'],
    -  DATEFORMATS: ['EEEE, d MMMM \'de\' y', 'd MMMM \'de\' y', 'd MMM y',
    -    'd/M/yy'],
    -  TIMEFORMATS: ['H:mm:ss zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1} \'a les\' {0}', '{1}, {0}', '{1} , {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ca_ES.
    - */
    -goog.i18n.DateTimeSymbols_ca_ES = {
    -  ERAS: ['aC', 'dC'],
    -  ERANAMES: ['abans de Crist', 'després de Crist'],
    -  NARROWMONTHS: ['GN', 'FB', 'MÇ', 'AB', 'MG', 'JN', 'JL', 'AG', 'ST', 'OC',
    -    'NV', 'DS'],
    -  STANDALONENARROWMONTHS: ['GN', 'FB', 'MÇ', 'AB', 'MG', 'JN', 'JL', 'AG',
    -    'ST', 'OC', 'NV', 'DS'],
    -  MONTHS: ['gener', 'febrer', 'març', 'abril', 'maig', 'juny', 'juliol',
    -    'agost', 'setembre', 'octubre', 'novembre', 'desembre'],
    -  STANDALONEMONTHS: ['gener', 'febrer', 'març', 'abril', 'maig', 'juny',
    -    'juliol', 'agost', 'setembre', 'octubre', 'novembre', 'desembre'],
    -  SHORTMONTHS: ['gen.', 'febr.', 'març', 'abr.', 'maig', 'juny', 'jul.', 'ag.',
    -    'set.', 'oct.', 'nov.', 'des.'],
    -  STANDALONESHORTMONTHS: ['gen.', 'febr.', 'març', 'abr.', 'maig', 'juny',
    -    'jul.', 'ag.', 'set.', 'oct.', 'nov.', 'des.'],
    -  WEEKDAYS: ['diumenge', 'dilluns', 'dimarts', 'dimecres', 'dijous',
    -    'divendres', 'dissabte'],
    -  STANDALONEWEEKDAYS: ['diumenge', 'dilluns', 'dimarts', 'dimecres', 'dijous',
    -    'divendres', 'dissabte'],
    -  SHORTWEEKDAYS: ['dg.', 'dl.', 'dt.', 'dc.', 'dj.', 'dv.', 'ds.'],
    -  STANDALONESHORTWEEKDAYS: ['dg.', 'dl.', 'dt.', 'dc.', 'dj.', 'dv.', 'ds.'],
    -  NARROWWEEKDAYS: ['dg', 'dl', 'dt', 'dc', 'dj', 'dv', 'ds'],
    -  STANDALONENARROWWEEKDAYS: ['dg', 'dl', 'dt', 'dc', 'dj', 'dv', 'ds'],
    -  SHORTQUARTERS: ['1T', '2T', '3T', '4T'],
    -  QUARTERS: ['1r trimestre', '2n trimestre', '3r trimestre', '4t trimestre'],
    -  AMPMS: ['a. m.', 'p. m.'],
    -  DATEFORMATS: ['EEEE, d MMMM \'de\' y', 'd MMMM \'de\' y', 'd MMM y',
    -    'd/M/yy'],
    -  TIMEFORMATS: ['H:mm:ss zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1} \'a les\' {0}', '{1}, {0}', '{1} , {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ca_ES_VALENCIA.
    - */
    -goog.i18n.DateTimeSymbols_ca_ES_VALENCIA = goog.i18n.DateTimeSymbols_ca_ES;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ca_FR.
    - */
    -goog.i18n.DateTimeSymbols_ca_FR = {
    -  ERAS: ['aC', 'dC'],
    -  ERANAMES: ['abans de Crist', 'després de Crist'],
    -  NARROWMONTHS: ['GN', 'FB', 'MÇ', 'AB', 'MG', 'JN', 'JL', 'AG', 'ST', 'OC',
    -    'NV', 'DS'],
    -  STANDALONENARROWMONTHS: ['GN', 'FB', 'MÇ', 'AB', 'MG', 'JN', 'JL', 'AG',
    -    'ST', 'OC', 'NV', 'DS'],
    -  MONTHS: ['gener', 'febrer', 'març', 'abril', 'maig', 'juny', 'juliol',
    -    'agost', 'setembre', 'octubre', 'novembre', 'desembre'],
    -  STANDALONEMONTHS: ['gener', 'febrer', 'març', 'abril', 'maig', 'juny',
    -    'juliol', 'agost', 'setembre', 'octubre', 'novembre', 'desembre'],
    -  SHORTMONTHS: ['gen.', 'febr.', 'març', 'abr.', 'maig', 'juny', 'jul.', 'ag.',
    -    'set.', 'oct.', 'nov.', 'des.'],
    -  STANDALONESHORTMONTHS: ['gen.', 'febr.', 'març', 'abr.', 'maig', 'juny',
    -    'jul.', 'ag.', 'set.', 'oct.', 'nov.', 'des.'],
    -  WEEKDAYS: ['diumenge', 'dilluns', 'dimarts', 'dimecres', 'dijous',
    -    'divendres', 'dissabte'],
    -  STANDALONEWEEKDAYS: ['diumenge', 'dilluns', 'dimarts', 'dimecres', 'dijous',
    -    'divendres', 'dissabte'],
    -  SHORTWEEKDAYS: ['dg.', 'dl.', 'dt.', 'dc.', 'dj.', 'dv.', 'ds.'],
    -  STANDALONESHORTWEEKDAYS: ['dg.', 'dl.', 'dt.', 'dc.', 'dj.', 'dv.', 'ds.'],
    -  NARROWWEEKDAYS: ['dg', 'dl', 'dt', 'dc', 'dj', 'dv', 'ds'],
    -  STANDALONENARROWWEEKDAYS: ['dg', 'dl', 'dt', 'dc', 'dj', 'dv', 'ds'],
    -  SHORTQUARTERS: ['1T', '2T', '3T', '4T'],
    -  QUARTERS: ['1r trimestre', '2n trimestre', '3r trimestre', '4t trimestre'],
    -  AMPMS: ['a. m.', 'p. m.'],
    -  DATEFORMATS: ['EEEE, d MMMM \'de\' y', 'd MMMM \'de\' y', 'd MMM y',
    -    'd/M/yy'],
    -  TIMEFORMATS: ['H:mm:ss zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1} \'a les\' {0}', '{1}, {0}', '{1} , {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ca_IT.
    - */
    -goog.i18n.DateTimeSymbols_ca_IT = {
    -  ERAS: ['aC', 'dC'],
    -  ERANAMES: ['abans de Crist', 'després de Crist'],
    -  NARROWMONTHS: ['GN', 'FB', 'MÇ', 'AB', 'MG', 'JN', 'JL', 'AG', 'ST', 'OC',
    -    'NV', 'DS'],
    -  STANDALONENARROWMONTHS: ['GN', 'FB', 'MÇ', 'AB', 'MG', 'JN', 'JL', 'AG',
    -    'ST', 'OC', 'NV', 'DS'],
    -  MONTHS: ['gener', 'febrer', 'març', 'abril', 'maig', 'juny', 'juliol',
    -    'agost', 'setembre', 'octubre', 'novembre', 'desembre'],
    -  STANDALONEMONTHS: ['gener', 'febrer', 'març', 'abril', 'maig', 'juny',
    -    'juliol', 'agost', 'setembre', 'octubre', 'novembre', 'desembre'],
    -  SHORTMONTHS: ['gen.', 'febr.', 'març', 'abr.', 'maig', 'juny', 'jul.', 'ag.',
    -    'set.', 'oct.', 'nov.', 'des.'],
    -  STANDALONESHORTMONTHS: ['gen.', 'febr.', 'març', 'abr.', 'maig', 'juny',
    -    'jul.', 'ag.', 'set.', 'oct.', 'nov.', 'des.'],
    -  WEEKDAYS: ['diumenge', 'dilluns', 'dimarts', 'dimecres', 'dijous',
    -    'divendres', 'dissabte'],
    -  STANDALONEWEEKDAYS: ['diumenge', 'dilluns', 'dimarts', 'dimecres', 'dijous',
    -    'divendres', 'dissabte'],
    -  SHORTWEEKDAYS: ['dg.', 'dl.', 'dt.', 'dc.', 'dj.', 'dv.', 'ds.'],
    -  STANDALONESHORTWEEKDAYS: ['dg.', 'dl.', 'dt.', 'dc.', 'dj.', 'dv.', 'ds.'],
    -  NARROWWEEKDAYS: ['dg', 'dl', 'dt', 'dc', 'dj', 'dv', 'ds'],
    -  STANDALONENARROWWEEKDAYS: ['dg', 'dl', 'dt', 'dc', 'dj', 'dv', 'ds'],
    -  SHORTQUARTERS: ['1T', '2T', '3T', '4T'],
    -  QUARTERS: ['1r trimestre', '2n trimestre', '3r trimestre', '4t trimestre'],
    -  AMPMS: ['a. m.', 'p. m.'],
    -  DATEFORMATS: ['EEEE, d MMMM \'de\' y', 'd MMMM \'de\' y', 'd MMM y',
    -    'd/M/yy'],
    -  TIMEFORMATS: ['H:mm:ss zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1} \'a les\' {0}', '{1}, {0}', '{1} , {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale cgg.
    - */
    -goog.i18n.DateTimeSymbols_cgg = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Kurisito Atakaijire', 'Kurisito Yaijire'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Okwokubanza', 'Okwakabiri', 'Okwakashatu', 'Okwakana',
    -    'Okwakataana', 'Okwamukaaga', 'Okwamushanju', 'Okwamunaana', 'Okwamwenda',
    -    'Okwaikumi', 'Okwaikumi na kumwe', 'Okwaikumi na ibiri'],
    -  STANDALONEMONTHS: ['Okwokubanza', 'Okwakabiri', 'Okwakashatu', 'Okwakana',
    -    'Okwakataana', 'Okwamukaaga', 'Okwamushanju', 'Okwamunaana', 'Okwamwenda',
    -    'Okwaikumi', 'Okwaikumi na kumwe', 'Okwaikumi na ibiri'],
    -  SHORTMONTHS: ['KBZ', 'KBR', 'KST', 'KKN', 'KTN', 'KMK', 'KMS', 'KMN', 'KMW',
    -    'KKM', 'KNK', 'KNB'],
    -  STANDALONESHORTMONTHS: ['KBZ', 'KBR', 'KST', 'KKN', 'KTN', 'KMK', 'KMS',
    -    'KMN', 'KMW', 'KKM', 'KNK', 'KNB'],
    -  WEEKDAYS: ['Sande', 'Orwokubanza', 'Orwakabiri', 'Orwakashatu', 'Orwakana',
    -    'Orwakataano', 'Orwamukaaga'],
    -  STANDALONEWEEKDAYS: ['Sande', 'Orwokubanza', 'Orwakabiri', 'Orwakashatu',
    -    'Orwakana', 'Orwakataano', 'Orwamukaaga'],
    -  SHORTWEEKDAYS: ['SAN', 'ORK', 'OKB', 'OKS', 'OKN', 'OKT', 'OMK'],
    -  STANDALONESHORTWEEKDAYS: ['SAN', 'ORK', 'OKB', 'OKS', 'OKN', 'OKT', 'OMK'],
    -  NARROWWEEKDAYS: ['S', 'K', 'R', 'S', 'N', 'T', 'M'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'K', 'R', 'S', 'N', 'T', 'M'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['KWOTA 1', 'KWOTA 2', 'KWOTA 3', 'KWOTA 4'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale cgg_UG.
    - */
    -goog.i18n.DateTimeSymbols_cgg_UG = goog.i18n.DateTimeSymbols_cgg;
    -
    -
    -/**
    - * Date/time formatting symbols for locale chr_US.
    - */
    -goog.i18n.DateTimeSymbols_chr_US = {
    -  ERAS: ['ᎤᏓᎷᎸ', 'ᎤᎶᏐᏅ'],
    -  ERANAMES: ['Ꮟ ᏥᏌ ᎾᏕᎲᏍᎬᎾ',
    -    'ᎠᎩᏃᎮᎵᏓᏍᏗᏱ ᎠᏕᏘᏱᏍᎬ ᏱᎰᏩ ᏧᏓᏂᎸᎢᏍᏗ'],
    -  NARROWMONTHS: ['Ꭴ', 'Ꭷ', 'Ꭰ', 'Ꭷ', 'Ꭰ', 'Ꮥ', 'Ꭻ', 'Ꭶ', 'Ꮪ',
    -    'Ꮪ', 'Ꮕ', 'Ꭵ'],
    -  STANDALONENARROWMONTHS: ['Ꭴ', 'Ꭷ', 'Ꭰ', 'Ꭷ', 'Ꭰ', 'Ꮥ', 'Ꭻ',
    -    'Ꭶ', 'Ꮪ', 'Ꮪ', 'Ꮕ', 'Ꭵ'],
    -  MONTHS: ['ᎤᏃᎸᏔᏅ', 'ᎧᎦᎵ', 'ᎠᏅᏱ', 'ᎧᏬᏂ',
    -    'ᎠᏂᏍᎬᏘ', 'ᏕᎭᎷᏱ', 'ᎫᏰᏉᏂ', 'ᎦᎶᏂ',
    -    'ᏚᎵᏍᏗ', 'ᏚᏂᏅᏗ', 'ᏅᏓᏕᏆ', 'ᎥᏍᎩᏱ'],
    -  STANDALONEMONTHS: ['ᎤᏃᎸᏔᏅ', 'ᎧᎦᎵ', 'ᎠᏅᏱ', 'ᎧᏬᏂ',
    -    'ᎠᏂᏍᎬᏘ', 'ᏕᎭᎷᏱ', 'ᎫᏰᏉᏂ', 'ᎦᎶᏂ',
    -    'ᏚᎵᏍᏗ', 'ᏚᏂᏅᏗ', 'ᏅᏓᏕᏆ', 'ᎥᏍᎩᏱ'],
    -  SHORTMONTHS: ['ᎤᏃ', 'ᎧᎦ', 'ᎠᏅ', 'ᎧᏬ', 'ᎠᏂ', 'ᏕᎭ',
    -    'ᎫᏰ', 'ᎦᎶ', 'ᏚᎵ', 'ᏚᏂ', 'ᏅᏓ', 'ᎥᏍ'],
    -  STANDALONESHORTMONTHS: ['ᎤᏃ', 'ᎧᎦ', 'ᎠᏅ', 'ᎧᏬ', 'ᎠᏂ',
    -    'ᏕᎭ', 'ᎫᏰ', 'ᎦᎶ', 'ᏚᎵ', 'ᏚᏂ', 'ᏅᏓ', 'ᎥᏍ'],
    -  WEEKDAYS: ['ᎤᎾᏙᏓᏆᏍᎬ', 'ᎤᎾᏙᏓᏉᏅᎯ',
    -    'ᏔᎵᏁᎢᎦ', 'ᏦᎢᏁᎢᎦ', 'ᏅᎩᏁᎢᎦ',
    -    'ᏧᎾᎩᎶᏍᏗ', 'ᎤᎾᏙᏓᏈᏕᎾ'],
    -  STANDALONEWEEKDAYS: ['ᎤᎾᏙᏓᏆᏍᎬ', 'ᎤᎾᏙᏓᏉᏅᎯ',
    -    'ᏔᎵᏁᎢᎦ', 'ᏦᎢᏁᎢᎦ', 'ᏅᎩᏁᎢᎦ',
    -    'ᏧᎾᎩᎶᏍᏗ', 'ᎤᎾᏙᏓᏈᏕᎾ'],
    -  SHORTWEEKDAYS: ['ᏆᏍᎬ', 'ᏉᏅᎯ', 'ᏔᎵᏁ', 'ᏦᎢᏁ',
    -    'ᏅᎩᏁ', 'ᏧᎾᎩ', 'ᏈᏕᎾ'],
    -  STANDALONESHORTWEEKDAYS: ['ᏆᏍᎬ', 'ᏉᏅᎯ', 'ᏔᎵᏁ', 'ᏦᎢᏁ',
    -    'ᏅᎩᏁ', 'ᏧᎾᎩ', 'ᏈᏕᎾ'],
    -  NARROWWEEKDAYS: ['Ꮖ', 'Ꮙ', 'Ꮤ', 'Ꮶ', 'Ꮕ', 'Ꮷ', 'Ꭴ'],
    -  STANDALONENARROWWEEKDAYS: ['Ꮖ', 'Ꮙ', 'Ꮤ', 'Ꮶ', 'Ꮕ', 'Ꮷ', 'Ꭴ'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['ᏌᎾᎴ', 'ᏒᎯᏱᎢᏗᏢ'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ckb.
    - */
    -goog.i18n.DateTimeSymbols_ckb = {
    -  ZERODIGIT: 0x0660,
    -  ERAS: ['پێش زاییین', 'ز'],
    -  ERANAMES: ['پێش زایین', 'زایینی'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', 'D'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', 'D'],
    -  MONTHS: ['کانوونی دووەم', 'شوبات', 'ئازار',
    -    'نیسان', 'ئایار', 'حوزەیران', 'تەمووز', 'ئاب',
    -    'ئەیلوول', 'تشرینی یەکەم', 'تشرینی دووەم',
    -    'کانونی یەکەم'],
    -  STANDALONEMONTHS: ['کانوونی دووەم', 'شوبات', 'ئازار',
    -    'نیسان', 'ئایار', 'حوزەیران', 'تەمووز', 'ئاب',
    -    'ئەیلوول', 'تشرینی یەکەم', 'تشرینی دووەم',
    -    'کانونی یەکەم'],
    -  SHORTMONTHS: ['کانوونی دووەم', 'شوبات', 'ئازار',
    -    'نیسان', 'ئایار', 'حوزەیران', 'تەمووز', 'ئاب',
    -    'ئەیلوول', 'تشرینی یەکەم', 'تشرینی دووەم',
    -    'کانونی یەکەم'],
    -  STANDALONESHORTMONTHS: ['کانوونی دووەم', 'شوبات',
    -    'ئازار', 'نیسان', 'ئایار', 'حوزەیران',
    -    'تەمووز', 'ئاب', 'ئەیلوول', 'تشرینی یەکەم',
    -    'تشرینی دووەم', 'کانونی یەکەم'],
    -  WEEKDAYS: ['یەکشەممە', 'دووشەممە', 'سێشەممە',
    -    'چوارشەممە', 'پێنجشەممە', 'ھەینی', 'شەممە'],
    -  STANDALONEWEEKDAYS: ['یەکشەممە', 'دووشەممە', 'سێشەممە',
    -    'چوارشەممە', 'پێنجشەممە', 'ھەینی', 'شەممە'],
    -  SHORTWEEKDAYS: ['یەکشەممە', 'دووشەممە', 'سێشەممە',
    -    'چوارشەممە', 'پێنجشەممە', 'ھەینی', 'شەممە'],
    -  STANDALONESHORTWEEKDAYS: ['یەکشەممە', 'دووشەممە',
    -    'سێشەممە', 'چوارشەممە', 'پێنجشەممە', 'ھەینی',
    -    'شەممە'],
    -  NARROWWEEKDAYS: ['ی', 'د', 'س', 'چ', 'پ', 'ھ', 'ش'],
    -  STANDALONENARROWWEEKDAYS: ['ی', 'د', 'س', 'چ', 'پ', 'ھ', 'ش'],
    -  SHORTQUARTERS: ['چارەکی یەکەم', 'چارەکی دووەم',
    -    'چارەکی سێەم', 'چارەکی چوارەم'],
    -  QUARTERS: ['چارەکی یەکەم', 'چارەکی دووەم',
    -    'چارەکی سێەم', 'چارەکی چوارەم'],
    -  AMPMS: ['ب.ن', 'د.ن'],
    -  DATEFORMATS: ['y MMMM d, EEEE', 'dی MMMMی y', 'y MMM d', 'y-MM-dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 5,
    -  WEEKENDRANGE: [4, 5],
    -  FIRSTWEEKCUTOFFDAY: 4
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ckb_Arab.
    - */
    -goog.i18n.DateTimeSymbols_ckb_Arab = goog.i18n.DateTimeSymbols_ckb;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ckb_Arab_IQ.
    - */
    -goog.i18n.DateTimeSymbols_ckb_Arab_IQ = goog.i18n.DateTimeSymbols_ckb;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ckb_Arab_IR.
    - */
    -goog.i18n.DateTimeSymbols_ckb_Arab_IR = goog.i18n.DateTimeSymbols_ckb;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ckb_IQ.
    - */
    -goog.i18n.DateTimeSymbols_ckb_IQ = goog.i18n.DateTimeSymbols_ckb;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ckb_IR.
    - */
    -goog.i18n.DateTimeSymbols_ckb_IR = goog.i18n.DateTimeSymbols_ckb;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ckb_Latn.
    - */
    -goog.i18n.DateTimeSymbols_ckb_Latn = goog.i18n.DateTimeSymbols_ckb;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ckb_Latn_IQ.
    - */
    -goog.i18n.DateTimeSymbols_ckb_Latn_IQ = goog.i18n.DateTimeSymbols_ckb;
    -
    -
    -/**
    - * Date/time formatting symbols for locale cs_CZ.
    - */
    -goog.i18n.DateTimeSymbols_cs_CZ = {
    -  ERAS: ['př. n. l.', 'n. l.'],
    -  ERANAMES: ['př. n. l.', 'n. l.'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['ledna', 'února', 'března', 'dubna', 'května', 'června',
    -    'července', 'srpna', 'září', 'října', 'listopadu', 'prosince'],
    -  STANDALONEMONTHS: ['leden', 'únor', 'březen', 'duben', 'květen', 'červen',
    -    'červenec', 'srpen', 'září', 'říjen', 'listopad', 'prosinec'],
    -  SHORTMONTHS: ['led', 'úno', 'bře', 'dub', 'kvě', 'čvn', 'čvc', 'srp',
    -    'zář', 'říj', 'lis', 'pro'],
    -  STANDALONESHORTMONTHS: ['led', 'úno', 'bře', 'dub', 'kvě', 'čvn', 'čvc',
    -    'srp', 'zář', 'říj', 'lis', 'pro'],
    -  WEEKDAYS: ['neděle', 'pondělí', 'úterý', 'středa', 'čtvrtek', 'pátek',
    -    'sobota'],
    -  STANDALONEWEEKDAYS: ['neděle', 'pondělí', 'úterý', 'středa', 'čtvrtek',
    -    'pátek', 'sobota'],
    -  SHORTWEEKDAYS: ['ne', 'po', 'út', 'st', 'čt', 'pá', 'so'],
    -  STANDALONESHORTWEEKDAYS: ['ne', 'po', 'út', 'st', 'čt', 'pá', 'so'],
    -  NARROWWEEKDAYS: ['N', 'P', 'Ú', 'S', 'Č', 'P', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['N', 'P', 'Ú', 'S', 'Č', 'P', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1. čtvrtletí', '2. čtvrtletí', '3. čtvrtletí',
    -    '4. čtvrtletí'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d. MMMM y', 'd. MMMM y', 'd. M. y', 'dd.MM.yy'],
    -  TIMEFORMATS: ['H:mm:ss zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale cy_GB.
    - */
    -goog.i18n.DateTimeSymbols_cy_GB = {
    -  ERAS: ['CC', 'OC'],
    -  ERANAMES: ['Cyn Crist', 'Oed Crist'],
    -  NARROWMONTHS: ['I', 'Ch', 'M', 'E', 'M', 'M', 'G', 'A', 'M', 'H', 'T', 'Rh'],
    -  STANDALONENARROWMONTHS: ['I', 'Ch', 'M', 'E', 'M', 'M', 'G', 'A', 'M', 'H',
    -    'T', 'Rh'],
    -  MONTHS: ['Ionawr', 'Chwefror', 'Mawrth', 'Ebrill', 'Mai', 'Mehefin',
    -    'Gorffennaf', 'Awst', 'Medi', 'Hydref', 'Tachwedd', 'Rhagfyr'],
    -  STANDALONEMONTHS: ['Ionawr', 'Chwefror', 'Mawrth', 'Ebrill', 'Mai', 'Mehefin',
    -    'Gorffennaf', 'Awst', 'Medi', 'Hydref', 'Tachwedd', 'Rhagfyr'],
    -  SHORTMONTHS: ['Ion', 'Chwef', 'Mawrth', 'Ebrill', 'Mai', 'Meh', 'Gorff',
    -    'Awst', 'Medi', 'Hyd', 'Tach', 'Rhag'],
    -  STANDALONESHORTMONTHS: ['Ion', 'Chw', 'Maw', 'Ebr', 'Mai', 'Meh', 'Gor',
    -    'Awst', 'Medi', 'Hyd', 'Tach', 'Rhag'],
    -  WEEKDAYS: ['Dydd Sul', 'Dydd Llun', 'Dydd Mawrth', 'Dydd Mercher', 'Dydd Iau',
    -    'Dydd Gwener', 'Dydd Sadwrn'],
    -  STANDALONEWEEKDAYS: ['Dydd Sul', 'Dydd Llun', 'Dydd Mawrth', 'Dydd Mercher',
    -    'Dydd Iau', 'Dydd Gwener', 'Dydd Sadwrn'],
    -  SHORTWEEKDAYS: ['Sul', 'Llun', 'Maw', 'Mer', 'Iau', 'Gwen', 'Sad'],
    -  STANDALONESHORTWEEKDAYS: ['Sul', 'Llun', 'Maw', 'Mer', 'Iau', 'Gwe', 'Sad'],
    -  NARROWWEEKDAYS: ['S', 'Ll', 'M', 'M', 'I', 'G', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'Ll', 'M', 'M', 'I', 'G', 'S'],
    -  SHORTQUARTERS: ['Ch1', 'Ch2', 'Ch3', 'Ch4'],
    -  QUARTERS: ['Chwarter 1af', '2il chwarter', '3ydd chwarter', '4ydd chwarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'am\' {0}', '{1} \'am\' {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale da_DK.
    - */
    -goog.i18n.DateTimeSymbols_da_DK = {
    -  ERAS: ['f.Kr.', 'e.Kr.'],
    -  ERANAMES: ['f.Kr.', 'e.Kr.'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['januar', 'februar', 'marts', 'april', 'maj', 'juni', 'juli',
    -    'august', 'september', 'oktober', 'november', 'december'],
    -  STANDALONEMONTHS: ['januar', 'februar', 'marts', 'april', 'maj', 'juni',
    -    'juli', 'august', 'september', 'oktober', 'november', 'december'],
    -  SHORTMONTHS: ['jan.', 'feb.', 'mar.', 'apr.', 'maj', 'jun.', 'jul.', 'aug.',
    -    'sep.', 'okt.', 'nov.', 'dec.'],
    -  STANDALONESHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul',
    -    'aug', 'sep', 'okt', 'nov', 'dec'],
    -  WEEKDAYS: ['søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag', 'fredag',
    -    'lørdag'],
    -  STANDALONEWEEKDAYS: ['søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag',
    -    'fredag', 'lørdag'],
    -  SHORTWEEKDAYS: ['søn.', 'man.', 'tir.', 'ons.', 'tor.', 'fre.', 'lør.'],
    -  STANDALONESHORTWEEKDAYS: ['søn', 'man', 'tir', 'ons', 'tor', 'fre', 'lør'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'O', 'T', 'F', 'L'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'O', 'T', 'F', 'L'],
    -  SHORTQUARTERS: ['1. kvt.', '2. kvt.', '3. kvt.', '4. kvt.'],
    -  QUARTERS: ['1. kvartal', '2. kvartal', '3. kvartal', '4. kvartal'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE \'den\' d. MMMM y', 'd. MMMM y', 'dd/MM/y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH.mm.ss zzzz', 'HH.mm.ss z', 'HH.mm.ss', 'HH.mm'],
    -  DATETIMEFORMATS: ['{1} \'kl.\' {0}', '{1} \'kl.\' {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale da_GL.
    - */
    -goog.i18n.DateTimeSymbols_da_GL = {
    -  ERAS: ['f.Kr.', 'e.Kr.'],
    -  ERANAMES: ['f.Kr.', 'e.Kr.'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['januar', 'februar', 'marts', 'april', 'maj', 'juni', 'juli',
    -    'august', 'september', 'oktober', 'november', 'december'],
    -  STANDALONEMONTHS: ['januar', 'februar', 'marts', 'april', 'maj', 'juni',
    -    'juli', 'august', 'september', 'oktober', 'november', 'december'],
    -  SHORTMONTHS: ['jan.', 'feb.', 'mar.', 'apr.', 'maj', 'jun.', 'jul.', 'aug.',
    -    'sep.', 'okt.', 'nov.', 'dec.'],
    -  STANDALONESHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul',
    -    'aug', 'sep', 'okt', 'nov', 'dec'],
    -  WEEKDAYS: ['søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag', 'fredag',
    -    'lørdag'],
    -  STANDALONEWEEKDAYS: ['søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag',
    -    'fredag', 'lørdag'],
    -  SHORTWEEKDAYS: ['søn.', 'man.', 'tir.', 'ons.', 'tor.', 'fre.', 'lør.'],
    -  STANDALONESHORTWEEKDAYS: ['søn', 'man', 'tir', 'ons', 'tor', 'fre', 'lør'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'O', 'T', 'F', 'L'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'O', 'T', 'F', 'L'],
    -  SHORTQUARTERS: ['1. kvt.', '2. kvt.', '3. kvt.', '4. kvt.'],
    -  QUARTERS: ['1. kvartal', '2. kvartal', '3. kvartal', '4. kvartal'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE \'den\' d. MMMM y', 'd. MMMM y', 'dd/MM/y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH.mm.ss zzzz', 'HH.mm.ss z', 'HH.mm.ss', 'HH.mm'],
    -  DATETIMEFORMATS: ['{1} \'kl.\' {0}', '{1} \'kl.\' {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale dav.
    - */
    -goog.i18n.DateTimeSymbols_dav = {
    -  ERAS: ['KK', 'BK'],
    -  ERANAMES: ['Kabla ya Kristo', 'Baada ya Kristo'],
    -  NARROWMONTHS: ['I', 'K', 'K', 'K', 'K', 'K', 'M', 'W', 'I', 'I', 'I', 'I'],
    -  STANDALONENARROWMONTHS: ['I', 'K', 'K', 'K', 'K', 'K', 'M', 'W', 'I', 'I',
    -    'I', 'I'],
    -  MONTHS: ['Mori ghwa imbiri', 'Mori ghwa kawi', 'Mori ghwa kadadu',
    -    'Mori ghwa kana', 'Mori ghwa kasanu', 'Mori ghwa karandadu',
    -    'Mori ghwa mfungade', 'Mori ghwa wunyanya', 'Mori ghwa ikenda',
    -    'Mori ghwa ikumi', 'Mori ghwa ikumi na imweri', 'Mori ghwa ikumi na iwi'],
    -  STANDALONEMONTHS: ['Mori ghwa imbiri', 'Mori ghwa kawi', 'Mori ghwa kadadu',
    -    'Mori ghwa kana', 'Mori ghwa kasanu', 'Mori ghwa karandadu',
    -    'Mori ghwa mfungade', 'Mori ghwa wunyanya', 'Mori ghwa ikenda',
    -    'Mori ghwa ikumi', 'Mori ghwa ikumi na imweri', 'Mori ghwa ikumi na iwi'],
    -  SHORTMONTHS: ['Imb', 'Kaw', 'Kad', 'Kan', 'Kas', 'Kar', 'Mfu', 'Wun', 'Ike',
    -    'Iku', 'Imw', 'Iwi'],
    -  STANDALONESHORTMONTHS: ['Imb', 'Kaw', 'Kad', 'Kan', 'Kas', 'Kar', 'Mfu',
    -    'Wun', 'Ike', 'Iku', 'Imw', 'Iwi'],
    -  WEEKDAYS: ['Ituku ja jumwa', 'Kuramuka jimweri', 'Kuramuka kawi',
    -    'Kuramuka kadadu', 'Kuramuka kana', 'Kuramuka kasanu', 'Kifula nguwo'],
    -  STANDALONEWEEKDAYS: ['Ituku ja jumwa', 'Kuramuka jimweri', 'Kuramuka kawi',
    -    'Kuramuka kadadu', 'Kuramuka kana', 'Kuramuka kasanu', 'Kifula nguwo'],
    -  SHORTWEEKDAYS: ['Jum', 'Jim', 'Kaw', 'Kad', 'Kan', 'Kas', 'Ngu'],
    -  STANDALONESHORTWEEKDAYS: ['Jum', 'Jim', 'Kaw', 'Kad', 'Kan', 'Kas', 'Ngu'],
    -  NARROWWEEKDAYS: ['J', 'J', 'K', 'K', 'K', 'K', 'N'],
    -  STANDALONENARROWWEEKDAYS: ['J', 'J', 'K', 'K', 'K', 'K', 'N'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['Kimu cha imbiri', 'Kimu cha kawi', 'Kimu cha kadadu',
    -    'Kimu cha kana'],
    -  AMPMS: ['Luma lwa K', 'luma lwa p'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale dav_KE.
    - */
    -goog.i18n.DateTimeSymbols_dav_KE = goog.i18n.DateTimeSymbols_dav;
    -
    -
    -/**
    - * Date/time formatting symbols for locale de_BE.
    - */
    -goog.i18n.DateTimeSymbols_de_BE = {
    -  ERAS: ['v. Chr.', 'n. Chr.'],
    -  ERANAMES: ['v. Chr.', 'n. Chr.'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli',
    -    'August', 'September', 'Oktober', 'November', 'Dezember'],
    -  STANDALONEMONTHS: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni',
    -    'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
    -  SHORTMONTHS: ['Jan.', 'Feb.', 'März', 'Apr.', 'Mai', 'Juni', 'Juli', 'Aug.',
    -    'Sep.', 'Okt.', 'Nov.', 'Dez.'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
    -  WEEKDAYS: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag',
    -    'Freitag', 'Samstag'],
    -  STANDALONEWEEKDAYS: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch',
    -    'Donnerstag', 'Freitag', 'Samstag'],
    -  SHORTWEEKDAYS: ['So.', 'Mo.', 'Di.', 'Mi.', 'Do.', 'Fr.', 'Sa.'],
    -  STANDALONESHORTWEEKDAYS: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
    -  NARROWWEEKDAYS: ['S', 'M', 'D', 'M', 'D', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'D', 'M', 'D', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1. Quartal', '2. Quartal', '3. Quartal', '4. Quartal'],
    -  AMPMS: ['vorm.', 'nachm.'],
    -  DATEFORMATS: ['EEEE, d. MMMM y', 'd. MMMM y', 'dd.MM.y', 'dd.MM.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'um\' {0}', '{1} \'um\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale de_DE.
    - */
    -goog.i18n.DateTimeSymbols_de_DE = {
    -  ERAS: ['v. Chr.', 'n. Chr.'],
    -  ERANAMES: ['v. Chr.', 'n. Chr.'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli',
    -    'August', 'September', 'Oktober', 'November', 'Dezember'],
    -  STANDALONEMONTHS: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni',
    -    'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
    -  SHORTMONTHS: ['Jan.', 'Feb.', 'März', 'Apr.', 'Mai', 'Juni', 'Juli', 'Aug.',
    -    'Sep.', 'Okt.', 'Nov.', 'Dez.'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
    -  WEEKDAYS: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag',
    -    'Freitag', 'Samstag'],
    -  STANDALONEWEEKDAYS: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch',
    -    'Donnerstag', 'Freitag', 'Samstag'],
    -  SHORTWEEKDAYS: ['So.', 'Mo.', 'Di.', 'Mi.', 'Do.', 'Fr.', 'Sa.'],
    -  STANDALONESHORTWEEKDAYS: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
    -  NARROWWEEKDAYS: ['S', 'M', 'D', 'M', 'D', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'D', 'M', 'D', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1. Quartal', '2. Quartal', '3. Quartal', '4. Quartal'],
    -  AMPMS: ['vorm.', 'nachm.'],
    -  DATEFORMATS: ['EEEE, d. MMMM y', 'd. MMMM y', 'dd.MM.y', 'dd.MM.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'um\' {0}', '{1} \'um\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale de_LI.
    - */
    -goog.i18n.DateTimeSymbols_de_LI = {
    -  ERAS: ['v. Chr.', 'n. Chr.'],
    -  ERANAMES: ['v. Chr.', 'n. Chr.'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli',
    -    'August', 'September', 'Oktober', 'November', 'Dezember'],
    -  STANDALONEMONTHS: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni',
    -    'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
    -  SHORTMONTHS: ['Jan.', 'Feb.', 'März', 'Apr.', 'Mai', 'Juni', 'Juli', 'Aug.',
    -    'Sep.', 'Okt.', 'Nov.', 'Dez.'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
    -  WEEKDAYS: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag',
    -    'Freitag', 'Samstag'],
    -  STANDALONEWEEKDAYS: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch',
    -    'Donnerstag', 'Freitag', 'Samstag'],
    -  SHORTWEEKDAYS: ['So.', 'Mo.', 'Di.', 'Mi.', 'Do.', 'Fr.', 'Sa.'],
    -  STANDALONESHORTWEEKDAYS: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
    -  NARROWWEEKDAYS: ['S', 'M', 'D', 'M', 'D', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'D', 'M', 'D', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1. Quartal', '2. Quartal', '3. Quartal', '4. Quartal'],
    -  AMPMS: ['vorm.', 'nachm.'],
    -  DATEFORMATS: ['EEEE, d. MMMM y', 'd. MMMM y', 'dd.MM.y', 'dd.MM.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'um\' {0}', '{1} \'um\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale de_LU.
    - */
    -goog.i18n.DateTimeSymbols_de_LU = {
    -  ERAS: ['v. Chr.', 'n. Chr.'],
    -  ERANAMES: ['v. Chr.', 'n. Chr.'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli',
    -    'August', 'September', 'Oktober', 'November', 'Dezember'],
    -  STANDALONEMONTHS: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni',
    -    'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
    -  SHORTMONTHS: ['Jan.', 'Feb.', 'März', 'Apr.', 'Mai', 'Juni', 'Juli', 'Aug.',
    -    'Sep.', 'Okt.', 'Nov.', 'Dez.'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
    -  WEEKDAYS: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag',
    -    'Freitag', 'Samstag'],
    -  STANDALONEWEEKDAYS: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch',
    -    'Donnerstag', 'Freitag', 'Samstag'],
    -  SHORTWEEKDAYS: ['So.', 'Mo.', 'Di.', 'Mi.', 'Do.', 'Fr.', 'Sa.'],
    -  STANDALONESHORTWEEKDAYS: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
    -  NARROWWEEKDAYS: ['S', 'M', 'D', 'M', 'D', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'D', 'M', 'D', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1. Quartal', '2. Quartal', '3. Quartal', '4. Quartal'],
    -  AMPMS: ['vorm.', 'nachm.'],
    -  DATEFORMATS: ['EEEE, d. MMMM y', 'd. MMMM y', 'dd.MM.y', 'dd.MM.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'um\' {0}', '{1} \'um\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale dje.
    - */
    -goog.i18n.DateTimeSymbols_dje = {
    -  ERAS: ['IJ', 'IZ'],
    -  ERANAMES: ['Isaa jine', 'Isaa zamanoo'],
    -  NARROWMONTHS: ['Ž', 'F', 'M', 'A', 'M', 'Ž', 'Ž', 'U', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['Ž', 'F', 'M', 'A', 'M', 'Ž', 'Ž', 'U', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Žanwiye', 'Feewiriye', 'Marsi', 'Awiril', 'Me', 'Žuweŋ',
    -    'Žuyye', 'Ut', 'Sektanbur', 'Oktoobur', 'Noowanbur', 'Deesanbur'],
    -  STANDALONEMONTHS: ['Žanwiye', 'Feewiriye', 'Marsi', 'Awiril', 'Me',
    -    'Žuweŋ', 'Žuyye', 'Ut', 'Sektanbur', 'Oktoobur', 'Noowanbur',
    -    'Deesanbur'],
    -  SHORTMONTHS: ['Žan', 'Fee', 'Mar', 'Awi', 'Me', 'Žuw', 'Žuy', 'Ut', 'Sek',
    -    'Okt', 'Noo', 'Dee'],
    -  STANDALONESHORTMONTHS: ['Žan', 'Fee', 'Mar', 'Awi', 'Me', 'Žuw', 'Žuy',
    -    'Ut', 'Sek', 'Okt', 'Noo', 'Dee'],
    -  WEEKDAYS: ['Alhadi', 'Atinni', 'Atalaata', 'Alarba', 'Alhamisi', 'Alzuma',
    -    'Asibti'],
    -  STANDALONEWEEKDAYS: ['Alhadi', 'Atinni', 'Atalaata', 'Alarba', 'Alhamisi',
    -    'Alzuma', 'Asibti'],
    -  SHORTWEEKDAYS: ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alz', 'Asi'],
    -  STANDALONESHORTWEEKDAYS: ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alz', 'Asi'],
    -  NARROWWEEKDAYS: ['H', 'T', 'T', 'L', 'M', 'Z', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['H', 'T', 'T', 'L', 'M', 'Z', 'S'],
    -  SHORTQUARTERS: ['A1', 'A2', 'A3', 'A4'],
    -  QUARTERS: ['Arrubu 1', 'Arrubu 2', 'Arrubu 3', 'Arrubu 4'],
    -  AMPMS: ['Subbaahi', 'Zaarikay b'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM, y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale dje_NE.
    - */
    -goog.i18n.DateTimeSymbols_dje_NE = goog.i18n.DateTimeSymbols_dje;
    -
    -
    -/**
    - * Date/time formatting symbols for locale dsb.
    - */
    -goog.i18n.DateTimeSymbols_dsb = {
    -  ERAS: ['pś.Chr.n.', 'pó Chr.n.'],
    -  ERANAMES: ['pśed Kristusowym naroźenim', 'pó Kristusowem naroźenju'],
    -  NARROWMONTHS: ['j', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['j', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o',
    -    'n', 'd'],
    -  MONTHS: ['januara', 'februara', 'měrca', 'apryla', 'maja', 'junija',
    -    'julija', 'awgusta', 'septembra', 'oktobra', 'nowembra', 'decembra'],
    -  STANDALONEMONTHS: ['januar', 'februar', 'měrc', 'apryl', 'maj', 'junij',
    -    'julij', 'awgust', 'september', 'oktober', 'nowember', 'december'],
    -  SHORTMONTHS: ['jan.', 'feb.', 'měr.', 'apr.', 'maj.', 'jun.', 'jul.', 'awg.',
    -    'sep.', 'okt.', 'now.', 'dec.'],
    -  STANDALONESHORTMONTHS: ['jan', 'feb', 'měr', 'apr', 'maj', 'jun', 'jul',
    -    'awg', 'sep', 'okt', 'now', 'dec'],
    -  WEEKDAYS: ['njeźela', 'pónjeźele', 'wałtora', 'srjoda', 'stwórtk',
    -    'pětk', 'sobota'],
    -  STANDALONEWEEKDAYS: ['njeźela', 'pónjeźele', 'wałtora', 'srjoda',
    -    'stwórtk', 'pětk', 'sobota'],
    -  SHORTWEEKDAYS: ['nje', 'pón', 'wał', 'srj', 'stw', 'pět', 'sob'],
    -  STANDALONESHORTWEEKDAYS: ['nje', 'pón', 'wał', 'srj', 'stw', 'pět', 'sob'],
    -  NARROWWEEKDAYS: ['n', 'p', 'w', 's', 's', 'p', 's'],
    -  STANDALONENARROWWEEKDAYS: ['n', 'p', 'w', 's', 's', 'p', 's'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1. kwartal', '2. kwartal', '3. kwartal', '4. kwartal'],
    -  AMPMS: ['dopołdnja', 'wótpołdnja'],
    -  DATEFORMATS: ['EEEE, d. MMMM y', 'd. MMMM y', 'd.M.y', 'd.M.yy'],
    -  TIMEFORMATS: ['H:mm:ss zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale dsb_DE.
    - */
    -goog.i18n.DateTimeSymbols_dsb_DE = goog.i18n.DateTimeSymbols_dsb;
    -
    -
    -/**
    - * Date/time formatting symbols for locale dua.
    - */
    -goog.i18n.DateTimeSymbols_dua = {
    -  ERAS: ['ɓ.Ys', 'mb.Ys'],
    -  ERANAMES: ['ɓoso ɓwá yáɓe lá', 'mbúsa kwédi a Yés'],
    -  NARROWMONTHS: ['d', 'ŋ', 's', 'd', 'e', 'e', 'm', 'd', 'n', 'm', 't', 'e'],
    -  STANDALONENARROWMONTHS: ['d', 'ŋ', 's', 'd', 'e', 'e', 'm', 'd', 'n', 'm',
    -    't', 'e'],
    -  MONTHS: ['dimɔ́di', 'ŋgɔndɛ', 'sɔŋɛ', 'diɓáɓá', 'emiasele',
    -    'esɔpɛsɔpɛ', 'madiɓɛ́díɓɛ́', 'diŋgindi', 'nyɛtɛki',
    -    'mayésɛ́', 'tiníní', 'eláŋgɛ́'],
    -  STANDALONEMONTHS: ['dimɔ́di', 'ŋgɔndɛ', 'sɔŋɛ', 'diɓáɓá',
    -    'emiasele', 'esɔpɛsɔpɛ', 'madiɓɛ́díɓɛ́', 'diŋgindi',
    -    'nyɛtɛki', 'mayésɛ́', 'tiníní', 'eláŋgɛ́'],
    -  SHORTMONTHS: ['di', 'ŋgɔn', 'sɔŋ', 'diɓ', 'emi', 'esɔ', 'mad', 'diŋ',
    -    'nyɛt', 'may', 'tin', 'elá'],
    -  STANDALONESHORTMONTHS: ['di', 'ŋgɔn', 'sɔŋ', 'diɓ', 'emi', 'esɔ', 'mad',
    -    'diŋ', 'nyɛt', 'may', 'tin', 'elá'],
    -  WEEKDAYS: ['éti', 'mɔ́sú', 'kwasú', 'mukɔ́sú', 'ŋgisú',
    -    'ɗónɛsú', 'esaɓasú'],
    -  STANDALONEWEEKDAYS: ['éti', 'mɔ́sú', 'kwasú', 'mukɔ́sú', 'ŋgisú',
    -    'ɗónɛsú', 'esaɓasú'],
    -  SHORTWEEKDAYS: ['ét', 'mɔ́s', 'kwa', 'muk', 'ŋgi', 'ɗón', 'esa'],
    -  STANDALONESHORTWEEKDAYS: ['ét', 'mɔ́s', 'kwa', 'muk', 'ŋgi', 'ɗón',
    -    'esa'],
    -  NARROWWEEKDAYS: ['e', 'm', 'k', 'm', 'ŋ', 'ɗ', 'e'],
    -  STANDALONENARROWWEEKDAYS: ['e', 'm', 'k', 'm', 'ŋ', 'ɗ', 'e'],
    -  SHORTQUARTERS: ['ndu1', 'ndu2', 'ndu3', 'ndu4'],
    -  QUARTERS: ['ndúmbū nyá ɓosó', 'ndúmbū ní lóndɛ́ íɓaá',
    -    'ndúmbū ní lóndɛ́ ílálo', 'ndúmbū ní lóndɛ́ ínɛ́y'],
    -  AMPMS: ['idiɓa', 'ebyámu'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale dua_CM.
    - */
    -goog.i18n.DateTimeSymbols_dua_CM = goog.i18n.DateTimeSymbols_dua;
    -
    -
    -/**
    - * Date/time formatting symbols for locale dyo.
    - */
    -goog.i18n.DateTimeSymbols_dyo = {
    -  ERAS: ['ArY', 'AtY'],
    -  ERANAMES: ['Ariŋuu Yeesu', 'Atooŋe Yeesu'],
    -  NARROWMONTHS: ['S', 'F', 'M', 'A', 'M', 'S', 'S', 'U', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['S', 'F', 'M', 'A', 'M', 'S', 'S', 'U', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Sanvie', 'Fébirie', 'Mars', 'Aburil', 'Mee', 'Sueŋ', 'Súuyee',
    -    'Ut', 'Settembar', 'Oktobar', 'Novembar', 'Disambar'],
    -  STANDALONEMONTHS: ['Sanvie', 'Fébirie', 'Mars', 'Aburil', 'Mee', 'Sueŋ',
    -    'Súuyee', 'Ut', 'Settembar', 'Oktobar', 'Novembar', 'Disambar'],
    -  SHORTMONTHS: ['Sa', 'Fe', 'Ma', 'Ab', 'Me', 'Su', 'Sú', 'Ut', 'Se', 'Ok',
    -    'No', 'De'],
    -  STANDALONESHORTMONTHS: ['Sa', 'Fe', 'Ma', 'Ab', 'Me', 'Su', 'Sú', 'Ut', 'Se',
    -    'Ok', 'No', 'De'],
    -  WEEKDAYS: ['Dimas', 'Teneŋ', 'Talata', 'Alarbay', 'Aramisay', 'Arjuma',
    -    'Sibiti'],
    -  STANDALONEWEEKDAYS: ['Dimas', 'Teneŋ', 'Talata', 'Alarbay', 'Aramisay',
    -    'Arjuma', 'Sibiti'],
    -  SHORTWEEKDAYS: ['Dim', 'Ten', 'Tal', 'Ala', 'Ara', 'Arj', 'Sib'],
    -  STANDALONESHORTWEEKDAYS: ['Dim', 'Ten', 'Tal', 'Ala', 'Ara', 'Arj', 'Sib'],
    -  NARROWWEEKDAYS: ['D', 'T', 'T', 'A', 'A', 'A', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'T', 'T', 'A', 'A', 'A', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale dyo_SN.
    - */
    -goog.i18n.DateTimeSymbols_dyo_SN = goog.i18n.DateTimeSymbols_dyo;
    -
    -
    -/**
    - * Date/time formatting symbols for locale dz.
    - */
    -goog.i18n.DateTimeSymbols_dz = {
    -  ZERODIGIT: 0x0F20,
    -  ERAS: ['BCE', 'CE'],
    -  ERANAMES: ['BCE', 'CE'],
    -  NARROWMONTHS: ['༡', '༢', '༣', '4', '༥', '༦', '༧', '༨', '9',
    -    '༡༠', '༡༡', '༡༢'],
    -  STANDALONENARROWMONTHS: ['༡', '༢', '༣', '༤', '༥', '༦', '༧',
    -    '༨', '༩', '༡༠', '༡༡', '༡༢'],
    -  MONTHS: ['ཟླ་དངཔ་', 'ཟླ་གཉིས་པ་',
    -    'ཟླ་གསུམ་པ་', 'ཟླ་བཞི་པ་',
    -    'ཟླ་ལྔ་པ་', 'ཟླ་དྲུག་པ',
    -    'ཟླ་བདུན་པ་', 'ཟླ་བརྒྱད་པ་',
    -    'ཟླ་དགུ་པ་', 'ཟླ་བཅུ་པ་',
    -    'ཟླ་བཅུ་གཅིག་པ་',
    -    'ཟླ་བཅུ་གཉིས་པ་'],
    -  STANDALONEMONTHS: ['སྤྱི་ཟླ་དངཔ་',
    -    'སྤྱི་ཟླ་གཉིས་པ་',
    -    'སྤྱི་ཟླ་གསུམ་པ་',
    -    'སྤྱི་ཟླ་བཞི་པ',
    -    'སྤྱི་ཟླ་ལྔ་པ་',
    -    'སྤྱི་ཟླ་དྲུག་པ',
    -    'སྤྱི་ཟླ་བདུན་པ་',
    -    'སྤྱི་ཟླ་བརྒྱད་པ་',
    -    'སྤྱི་ཟླ་དགུ་པ་',
    -    'སྤྱི་ཟླ་བཅུ་པ་',
    -    'སྤྱི་ཟླ་བཅུ་གཅིག་པ་',
    -    'སྤྱི་ཟླ་བཅུ་གཉིས་པ་'],
    -  SHORTMONTHS: ['༡', '༢', '༣', '༤', '༥', '༦', '༧', '༨', '༩',
    -    '༡༠', '༡༡', '12'],
    -  STANDALONESHORTMONTHS: ['ཟླ་༡', 'ཟླ་༢', 'ཟླ་༣',
    -    'ཟླ་༤', 'ཟླ་༥', 'ཟླ་༦', 'ཟླ་༧',
    -    'ཟླ་༨', 'ཟླ་༩', 'ཟླ་༡༠', 'ཟླ་༡༡',
    -    'ཟླ་༡༢'],
    -  WEEKDAYS: ['གཟའ་ཟླ་བ་',
    -    'གཟའ་མིག་དམར་', 'གཟའ་ལྷག་པ་',
    -    'གཟའ་ཕུར་བུ་', 'གཟའ་པ་སངས་',
    -    'གཟའ་སྤེན་པ་', 'གཟའ་ཉི་མ་'],
    -  STANDALONEWEEKDAYS: ['གཟའ་ཟླ་བ་',
    -    'གཟའ་མིག་དམར་', 'གཟའ་ལྷག་པ་',
    -    'གཟའ་ཕུར་བུ་', 'གཟའ་པ་སངས་',
    -    'གཟའ་སྤེན་པ་', 'གཟའ་ཉི་མ་'],
    -  SHORTWEEKDAYS: ['ཟླ་', 'མིར་', 'ལྷག་', 'ཕུར་',
    -    'སངས་', 'སྤེན་', 'ཉི་'],
    -  STANDALONESHORTWEEKDAYS: ['ཟླ་', 'མིར་', 'ལྷག་',
    -    'ཕུར་', 'སངས་', 'སྤེན་', 'ཉི་'],
    -  NARROWWEEKDAYS: ['ཟླ', 'མིར', 'ལྷག', 'ཕུར', 'སངྶ',
    -    'སྤེན', 'ཉི'],
    -  STANDALONENARROWWEEKDAYS: ['ཟླ', 'མིར', 'ལྷག', 'ཕུར',
    -    'སངྶ', 'སྤེན', 'ཉི'],
    -  SHORTQUARTERS: ['བཞི་དཔྱ་༡', 'བཞི་དཔྱ་༢',
    -    'བཞི་དཔྱ་༣', 'བཞི་དཔྱ་༤'],
    -  QUARTERS: ['བཞི་དཔྱ་དང་པ་',
    -    'བཞི་དཔྱ་གཉིས་པ་',
    -    'བཞི་དཔྱ་གསུམ་པ་',
    -    'བཞི་དཔྱ་བཞི་པ་'],
    -  AMPMS: ['སྔ་ཆ་', 'ཕྱི་ཆ་'],
    -  DATEFORMATS: ['EEEE, སྤྱི་ལོ་y MMMM ཚེས་dd',
    -    'སྤྱི་ལོ་y MMMM ཚེས་ dd',
    -    'སྤྱི་ལོ་y ཟླ་MMM ཚེས་dd', 'y-MM-dd'],
    -  TIMEFORMATS: ['ཆུ་ཚོད་ h སྐར་མ་ mm:ss a zzzz',
    -    'ཆུ་ཚོད་ h སྐར་མ་ mm:ss a z',
    -    'ཆུ་ཚོད་h:mm:ss a',
    -    'ཆུ་ཚོད་ h སྐར་མ་ mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale dz_BT.
    - */
    -goog.i18n.DateTimeSymbols_dz_BT = goog.i18n.DateTimeSymbols_dz;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ebu.
    - */
    -goog.i18n.DateTimeSymbols_ebu = {
    -  ERAS: ['MK', 'TK'],
    -  ERANAMES: ['Mbere ya Kristo', 'Thutha wa Kristo'],
    -  NARROWMONTHS: ['M', 'K', 'K', 'K', 'G', 'G', 'M', 'K', 'K', 'I', 'I', 'I'],
    -  STANDALONENARROWMONTHS: ['M', 'K', 'K', 'K', 'G', 'G', 'M', 'K', 'K', 'I',
    -    'I', 'I'],
    -  MONTHS: ['Mweri wa mbere', 'Mweri wa kaĩri', 'Mweri wa kathatũ',
    -    'Mweri wa kana', 'Mweri wa gatano', 'Mweri wa gatantatũ',
    -    'Mweri wa mũgwanja', 'Mweri wa kanana', 'Mweri wa kenda',
    -    'Mweri wa ikũmi', 'Mweri wa ikũmi na ũmwe',
    -    'Mweri wa ikũmi na Kaĩrĩ'],
    -  STANDALONEMONTHS: ['Mweri wa mbere', 'Mweri wa kaĩri', 'Mweri wa kathatũ',
    -    'Mweri wa kana', 'Mweri wa gatano', 'Mweri wa gatantatũ',
    -    'Mweri wa mũgwanja', 'Mweri wa kanana', 'Mweri wa kenda',
    -    'Mweri wa ikũmi', 'Mweri wa ikũmi na ũmwe',
    -    'Mweri wa ikũmi na Kaĩrĩ'],
    -  SHORTMONTHS: ['Mbe', 'Kai', 'Kat', 'Kan', 'Gat', 'Gan', 'Mug', 'Knn', 'Ken',
    -    'Iku', 'Imw', 'Igi'],
    -  STANDALONESHORTMONTHS: ['Mbe', 'Kai', 'Kat', 'Kan', 'Gat', 'Gan', 'Mug',
    -    'Knn', 'Ken', 'Iku', 'Imw', 'Igi'],
    -  WEEKDAYS: ['Kiumia', 'Njumatatu', 'Njumaine', 'Njumatano', 'Aramithi',
    -    'Njumaa', 'NJumamothii'],
    -  STANDALONEWEEKDAYS: ['Kiumia', 'Njumatatu', 'Njumaine', 'Njumatano',
    -    'Aramithi', 'Njumaa', 'NJumamothii'],
    -  SHORTWEEKDAYS: ['Kma', 'Tat', 'Ine', 'Tan', 'Arm', 'Maa', 'NMM'],
    -  STANDALONESHORTWEEKDAYS: ['Kma', 'Tat', 'Ine', 'Tan', 'Arm', 'Maa', 'NMM'],
    -  NARROWWEEKDAYS: ['K', 'N', 'N', 'N', 'A', 'M', 'N'],
    -  STANDALONENARROWWEEKDAYS: ['K', 'N', 'N', 'N', 'A', 'M', 'N'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['Kuota ya mbere', 'Kuota ya Kaĩrĩ', 'Kuota ya kathatu',
    -    'Kuota ya kana'],
    -  AMPMS: ['KI', 'UT'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ebu_KE.
    - */
    -goog.i18n.DateTimeSymbols_ebu_KE = goog.i18n.DateTimeSymbols_ebu;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ee.
    - */
    -goog.i18n.DateTimeSymbols_ee = {
    -  ERAS: ['hY', 'Yŋ'],
    -  ERANAMES: ['Hafi Yesu Va Do ŋgɔ', 'Yesu Ŋɔli'],
    -  NARROWMONTHS: ['d', 'd', 't', 'a', 'd', 'm', 's', 'd', 'a', 'k', 'a', 'd'],
    -  STANDALONENARROWMONTHS: ['d', 'd', 't', 'a', 'd', 'm', 's', 'd', 'a', 'k',
    -    'a', 'd'],
    -  MONTHS: ['dzove', 'dzodze', 'tedoxe', 'afɔfĩe', 'dama', 'masa', 'siamlɔm',
    -    'deasiamime', 'anyɔnyɔ', 'kele', 'adeɛmekpɔxe', 'dzome'],
    -  STANDALONEMONTHS: ['dzove', 'dzodze', 'tedoxe', 'afɔfĩe', 'dama', 'masa',
    -    'siamlɔm', 'deasiamime', 'anyɔnyɔ', 'kele', 'adeɛmekpɔxe', 'dzome'],
    -  SHORTMONTHS: ['dzv', 'dzd', 'ted', 'afɔ', 'dam', 'mas', 'sia', 'dea', 'any',
    -    'kel', 'ade', 'dzm'],
    -  STANDALONESHORTMONTHS: ['dzv', 'dzd', 'ted', 'afɔ', 'dam', 'mas', 'sia',
    -    'dea', 'any', 'kel', 'ade', 'dzm'],
    -  WEEKDAYS: ['kɔsiɖa', 'dzoɖa', 'blaɖa', 'kuɖa', 'yawoɖa', 'fiɖa',
    -    'memleɖa'],
    -  STANDALONEWEEKDAYS: ['kɔsiɖa', 'dzoɖa', 'blaɖa', 'kuɖa', 'yawoɖa',
    -    'fiɖa', 'memleɖa'],
    -  SHORTWEEKDAYS: ['kɔs', 'dzo', 'bla', 'kuɖ', 'yaw', 'fiɖ', 'mem'],
    -  STANDALONESHORTWEEKDAYS: ['kɔs', 'dzo', 'bla', 'kuɖ', 'yaw', 'fiɖ', 'mem'],
    -  NARROWWEEKDAYS: ['k', 'd', 'b', 'k', 'y', 'f', 'm'],
    -  STANDALONENARROWWEEKDAYS: ['k', 'd', 'b', 'k', 'y', 'f', 'm'],
    -  SHORTQUARTERS: ['k1', 'k2', 'k3', 'k4'],
    -  QUARTERS: ['kɔta gbãtɔ', 'kɔta evelia', 'kɔta etɔ̃lia',
    -    'kɔta enelia'],
    -  AMPMS: ['ŋdi', 'ɣetrɔ'],
    -  DATEFORMATS: ['EEEE, MMMM d \'lia\' y', 'MMMM d \'lia\' y',
    -    'MMM d \'lia\', y', 'M/d/yy'],
    -  TIMEFORMATS: ['a h:mm:ss zzzz', 'a \'ga\' h:mm:ss z', 'a \'ga\' h:mm:ss',
    -    'a \'ga\' h:mm'],
    -  DATETIMEFORMATS: ['{0} {1}', '{0} {1}', '{0} {1}', '{0} {1}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ee_GH.
    - */
    -goog.i18n.DateTimeSymbols_ee_GH = goog.i18n.DateTimeSymbols_ee;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ee_TG.
    - */
    -goog.i18n.DateTimeSymbols_ee_TG = goog.i18n.DateTimeSymbols_ee;
    -
    -
    -/**
    - * Date/time formatting symbols for locale el_CY.
    - */
    -goog.i18n.DateTimeSymbols_el_CY = {
    -  ERAS: ['π.Χ.', 'μ.Χ.'],
    -  ERANAMES: ['προ Χριστού', 'μετά Χριστόν'],
    -  NARROWMONTHS: ['Ι', 'Φ', 'Μ', 'Α', 'Μ', 'Ι', 'Ι', 'Α', 'Σ', 'Ο',
    -    'Ν', 'Δ'],
    -  STANDALONENARROWMONTHS: ['Ι', 'Φ', 'Μ', 'Α', 'Μ', 'Ι', 'Ι', 'Α', 'Σ',
    -    'Ο', 'Ν', 'Δ'],
    -  MONTHS: ['Ιανουαρίου', 'Φεβρουαρίου', 'Μαρτίου',
    -    'Απριλίου', 'Μαΐου', 'Ιουνίου', 'Ιουλίου',
    -    'Αυγούστου', 'Σεπτεμβρίου', 'Οκτωβρίου',
    -    'Νοεμβρίου', 'Δεκεμβρίου'],
    -  STANDALONEMONTHS: ['Ιανουάριος', 'Φεβρουάριος',
    -    'Μάρτιος', 'Απρίλιος', 'Μάιος', 'Ιούνιος',
    -    'Ιούλιος', 'Αύγουστος', 'Σεπτέμβριος',
    -    'Οκτώβριος', 'Νοέμβριος', 'Δεκέμβριος'],
    -  SHORTMONTHS: ['Ιαν', 'Φεβ', 'Μαρ', 'Απρ', 'Μαΐ', 'Ιουν',
    -    'Ιουλ', 'Αυγ', 'Σεπ', 'Οκτ', 'Νοε', 'Δεκ'],
    -  STANDALONESHORTMONTHS: ['Ιαν', 'Φεβ', 'Μάρ', 'Απρ', 'Μάι',
    -    'Ιούν', 'Ιούλ', 'Αύγ', 'Σεπ', 'Οκτ', 'Νοέ', 'Δεκ'],
    -  WEEKDAYS: ['Κυριακή', 'Δευτέρα', 'Τρίτη', 'Τετάρτη',
    -    'Πέμπτη', 'Παρασκευή', 'Σάββατο'],
    -  STANDALONEWEEKDAYS: ['Κυριακή', 'Δευτέρα', 'Τρίτη',
    -    'Τετάρτη', 'Πέμπτη', 'Παρασκευή', 'Σάββατο'],
    -  SHORTWEEKDAYS: ['Κυρ', 'Δευ', 'Τρί', 'Τετ', 'Πέμ', 'Παρ',
    -    'Σάβ'],
    -  STANDALONESHORTWEEKDAYS: ['Κυρ', 'Δευ', 'Τρί', 'Τετ', 'Πέμ',
    -    'Παρ', 'Σάβ'],
    -  NARROWWEEKDAYS: ['Κ', 'Δ', 'Τ', 'Τ', 'Π', 'Π', 'Σ'],
    -  STANDALONENARROWWEEKDAYS: ['Κ', 'Δ', 'Τ', 'Τ', 'Π', 'Π', 'Σ'],
    -  SHORTQUARTERS: ['Τ1', 'Τ2', 'Τ3', 'Τ4'],
    -  QUARTERS: ['1ο τρίμηνο', '2ο τρίμηνο', '3ο τρίμηνο',
    -    '4ο τρίμηνο'],
    -  AMPMS: ['π.μ.', 'μ.μ.'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} - {0}', '{1} - {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale el_GR.
    - */
    -goog.i18n.DateTimeSymbols_el_GR = {
    -  ERAS: ['π.Χ.', 'μ.Χ.'],
    -  ERANAMES: ['προ Χριστού', 'μετά Χριστόν'],
    -  NARROWMONTHS: ['Ι', 'Φ', 'Μ', 'Α', 'Μ', 'Ι', 'Ι', 'Α', 'Σ', 'Ο',
    -    'Ν', 'Δ'],
    -  STANDALONENARROWMONTHS: ['Ι', 'Φ', 'Μ', 'Α', 'Μ', 'Ι', 'Ι', 'Α', 'Σ',
    -    'Ο', 'Ν', 'Δ'],
    -  MONTHS: ['Ιανουαρίου', 'Φεβρουαρίου', 'Μαρτίου',
    -    'Απριλίου', 'Μαΐου', 'Ιουνίου', 'Ιουλίου',
    -    'Αυγούστου', 'Σεπτεμβρίου', 'Οκτωβρίου',
    -    'Νοεμβρίου', 'Δεκεμβρίου'],
    -  STANDALONEMONTHS: ['Ιανουάριος', 'Φεβρουάριος',
    -    'Μάρτιος', 'Απρίλιος', 'Μάιος', 'Ιούνιος',
    -    'Ιούλιος', 'Αύγουστος', 'Σεπτέμβριος',
    -    'Οκτώβριος', 'Νοέμβριος', 'Δεκέμβριος'],
    -  SHORTMONTHS: ['Ιαν', 'Φεβ', 'Μαρ', 'Απρ', 'Μαΐ', 'Ιουν',
    -    'Ιουλ', 'Αυγ', 'Σεπ', 'Οκτ', 'Νοε', 'Δεκ'],
    -  STANDALONESHORTMONTHS: ['Ιαν', 'Φεβ', 'Μάρ', 'Απρ', 'Μάι',
    -    'Ιούν', 'Ιούλ', 'Αύγ', 'Σεπ', 'Οκτ', 'Νοέ', 'Δεκ'],
    -  WEEKDAYS: ['Κυριακή', 'Δευτέρα', 'Τρίτη', 'Τετάρτη',
    -    'Πέμπτη', 'Παρασκευή', 'Σάββατο'],
    -  STANDALONEWEEKDAYS: ['Κυριακή', 'Δευτέρα', 'Τρίτη',
    -    'Τετάρτη', 'Πέμπτη', 'Παρασκευή', 'Σάββατο'],
    -  SHORTWEEKDAYS: ['Κυρ', 'Δευ', 'Τρί', 'Τετ', 'Πέμ', 'Παρ',
    -    'Σάβ'],
    -  STANDALONESHORTWEEKDAYS: ['Κυρ', 'Δευ', 'Τρί', 'Τετ', 'Πέμ',
    -    'Παρ', 'Σάβ'],
    -  NARROWWEEKDAYS: ['Κ', 'Δ', 'Τ', 'Τ', 'Π', 'Π', 'Σ'],
    -  STANDALONENARROWWEEKDAYS: ['Κ', 'Δ', 'Τ', 'Τ', 'Π', 'Π', 'Σ'],
    -  SHORTQUARTERS: ['Τ1', 'Τ2', 'Τ3', 'Τ4'],
    -  QUARTERS: ['1ο τρίμηνο', '2ο τρίμηνο', '3ο τρίμηνο',
    -    '4ο τρίμηνο'],
    -  AMPMS: ['π.μ.', 'μ.μ.'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} - {0}', '{1} - {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_001.
    - */
    -goog.i18n.DateTimeSymbols_en_001 = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_150.
    - */
    -goog.i18n.DateTimeSymbols_en_150 = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['am', 'pm'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMM y', 'dd MMM y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH \'h\' mm \'min\' ss \'s\' zzzz', 'HH:mm:ss z', 'HH:mm:ss',
    -    'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_AG.
    - */
    -goog.i18n.DateTimeSymbols_en_AG = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_AI.
    - */
    -goog.i18n.DateTimeSymbols_en_AI = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_AS.
    - */
    -goog.i18n.DateTimeSymbols_en_AS = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_BB.
    - */
    -goog.i18n.DateTimeSymbols_en_BB = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_BE.
    - */
    -goog.i18n.DateTimeSymbols_en_BE = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['am', 'pm'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMM y', 'dd MMM y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH \'h\' mm \'min\' ss \'s\' zzzz', 'HH:mm:ss z', 'HH:mm:ss',
    -    'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_BM.
    - */
    -goog.i18n.DateTimeSymbols_en_BM = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_BS.
    - */
    -goog.i18n.DateTimeSymbols_en_BS = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_BW.
    - */
    -goog.i18n.DateTimeSymbols_en_BW = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE dd MMMM y', 'dd MMMM y', 'dd MMM y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_BZ.
    - */
    -goog.i18n.DateTimeSymbols_en_BZ = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE dd MMMM y', 'dd MMMM y', 'dd-MMM-y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_CA.
    - */
    -goog.i18n.DateTimeSymbols_en_CA = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'y-MM-dd'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_CC.
    - */
    -goog.i18n.DateTimeSymbols_en_CC = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_CK.
    - */
    -goog.i18n.DateTimeSymbols_en_CK = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_CM.
    - */
    -goog.i18n.DateTimeSymbols_en_CM = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_CX.
    - */
    -goog.i18n.DateTimeSymbols_en_CX = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_DG.
    - */
    -goog.i18n.DateTimeSymbols_en_DG = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['am', 'pm'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_DM.
    - */
    -goog.i18n.DateTimeSymbols_en_DM = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_ER.
    - */
    -goog.i18n.DateTimeSymbols_en_ER = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_FJ.
    - */
    -goog.i18n.DateTimeSymbols_en_FJ = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_FK.
    - */
    -goog.i18n.DateTimeSymbols_en_FK = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['am', 'pm'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_FM.
    - */
    -goog.i18n.DateTimeSymbols_en_FM = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_GD.
    - */
    -goog.i18n.DateTimeSymbols_en_GD = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_GG.
    - */
    -goog.i18n.DateTimeSymbols_en_GG = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['am', 'pm'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_GH.
    - */
    -goog.i18n.DateTimeSymbols_en_GH = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_GI.
    - */
    -goog.i18n.DateTimeSymbols_en_GI = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['am', 'pm'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_GM.
    - */
    -goog.i18n.DateTimeSymbols_en_GM = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_GU.
    - */
    -goog.i18n.DateTimeSymbols_en_GU = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_GY.
    - */
    -goog.i18n.DateTimeSymbols_en_GY = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_HK.
    - */
    -goog.i18n.DateTimeSymbols_en_HK = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['am', 'pm'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_IM.
    - */
    -goog.i18n.DateTimeSymbols_en_IM = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['am', 'pm'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_IO.
    - */
    -goog.i18n.DateTimeSymbols_en_IO = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['am', 'pm'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_JE.
    - */
    -goog.i18n.DateTimeSymbols_en_JE = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['am', 'pm'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_JM.
    - */
    -goog.i18n.DateTimeSymbols_en_JM = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_KE.
    - */
    -goog.i18n.DateTimeSymbols_en_KE = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_KI.
    - */
    -goog.i18n.DateTimeSymbols_en_KI = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_KN.
    - */
    -goog.i18n.DateTimeSymbols_en_KN = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_KY.
    - */
    -goog.i18n.DateTimeSymbols_en_KY = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_LC.
    - */
    -goog.i18n.DateTimeSymbols_en_LC = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_LR.
    - */
    -goog.i18n.DateTimeSymbols_en_LR = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_LS.
    - */
    -goog.i18n.DateTimeSymbols_en_LS = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_MG.
    - */
    -goog.i18n.DateTimeSymbols_en_MG = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_MH.
    - */
    -goog.i18n.DateTimeSymbols_en_MH = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_MO.
    - */
    -goog.i18n.DateTimeSymbols_en_MO = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['am', 'pm'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_MP.
    - */
    -goog.i18n.DateTimeSymbols_en_MP = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_MS.
    - */
    -goog.i18n.DateTimeSymbols_en_MS = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_MT.
    - */
    -goog.i18n.DateTimeSymbols_en_MT = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['am', 'pm'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'dd MMMM y', 'dd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_MU.
    - */
    -goog.i18n.DateTimeSymbols_en_MU = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_MW.
    - */
    -goog.i18n.DateTimeSymbols_en_MW = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_MY.
    - */
    -goog.i18n.DateTimeSymbols_en_MY = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_NA.
    - */
    -goog.i18n.DateTimeSymbols_en_NA = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_NF.
    - */
    -goog.i18n.DateTimeSymbols_en_NF = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_NG.
    - */
    -goog.i18n.DateTimeSymbols_en_NG = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_NR.
    - */
    -goog.i18n.DateTimeSymbols_en_NR = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_NU.
    - */
    -goog.i18n.DateTimeSymbols_en_NU = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_NZ.
    - */
    -goog.i18n.DateTimeSymbols_en_NZ = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['am', 'pm'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd/MM/y', 'd/MM/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_PG.
    - */
    -goog.i18n.DateTimeSymbols_en_PG = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_PH.
    - */
    -goog.i18n.DateTimeSymbols_en_PH = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_PK.
    - */
    -goog.i18n.DateTimeSymbols_en_PK = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['am', 'pm'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'dd-MMM-y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_PN.
    - */
    -goog.i18n.DateTimeSymbols_en_PN = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_PR.
    - */
    -goog.i18n.DateTimeSymbols_en_PR = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_PW.
    - */
    -goog.i18n.DateTimeSymbols_en_PW = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_RW.
    - */
    -goog.i18n.DateTimeSymbols_en_RW = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_SB.
    - */
    -goog.i18n.DateTimeSymbols_en_SB = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_SC.
    - */
    -goog.i18n.DateTimeSymbols_en_SC = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_SD.
    - */
    -goog.i18n.DateTimeSymbols_en_SD = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 5,
    -  WEEKENDRANGE: [4, 5],
    -  FIRSTWEEKCUTOFFDAY: 4
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_SH.
    - */
    -goog.i18n.DateTimeSymbols_en_SH = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['am', 'pm'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_SL.
    - */
    -goog.i18n.DateTimeSymbols_en_SL = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_SS.
    - */
    -goog.i18n.DateTimeSymbols_en_SS = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_SX.
    - */
    -goog.i18n.DateTimeSymbols_en_SX = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_SZ.
    - */
    -goog.i18n.DateTimeSymbols_en_SZ = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_TC.
    - */
    -goog.i18n.DateTimeSymbols_en_TC = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_TK.
    - */
    -goog.i18n.DateTimeSymbols_en_TK = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_TO.
    - */
    -goog.i18n.DateTimeSymbols_en_TO = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_TT.
    - */
    -goog.i18n.DateTimeSymbols_en_TT = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_TV.
    - */
    -goog.i18n.DateTimeSymbols_en_TV = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_TZ.
    - */
    -goog.i18n.DateTimeSymbols_en_TZ = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_UG.
    - */
    -goog.i18n.DateTimeSymbols_en_UG = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_UM.
    - */
    -goog.i18n.DateTimeSymbols_en_UM = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_VC.
    - */
    -goog.i18n.DateTimeSymbols_en_VC = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_VG.
    - */
    -goog.i18n.DateTimeSymbols_en_VG = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['am', 'pm'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_VI.
    - */
    -goog.i18n.DateTimeSymbols_en_VI = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_VU.
    - */
    -goog.i18n.DateTimeSymbols_en_VU = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_WS.
    - */
    -goog.i18n.DateTimeSymbols_en_WS = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_ZM.
    - */
    -goog.i18n.DateTimeSymbols_en_ZM = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale en_ZW.
    - */
    -goog.i18n.DateTimeSymbols_en_ZW = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Before Christ', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['January', 'February', 'March', 'April', 'May', 'June', 'July',
    -    'August', 'September', 'October', 'November', 'December'],
    -  STANDALONEMONTHS: ['January', 'February', 'March', 'April', 'May', 'June',
    -    'July', 'August', 'September', 'October', 'November', 'December'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
    -    'Saturday'],
    -  STANDALONEWEEKDAYS: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
    -    'Friday', 'Saturday'],
    -  SHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE dd MMMM y', 'dd MMMM y', 'dd MMM,y', 'd/M/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'at\' {0}', '{1} \'at\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale eo.
    - */
    -goog.i18n.DateTimeSymbols_eo = {
    -  ERAS: ['aK', 'pK'],
    -  ERANAMES: ['aK', 'pK'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['januaro', 'februaro', 'marto', 'aprilo', 'majo', 'junio', 'julio',
    -    'aŭgusto', 'septembro', 'oktobro', 'novembro', 'decembro'],
    -  STANDALONEMONTHS: ['januaro', 'februaro', 'marto', 'aprilo', 'majo', 'junio',
    -    'julio', 'aŭgusto', 'septembro', 'oktobro', 'novembro', 'decembro'],
    -  SHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'aŭg', 'sep',
    -    'okt', 'nov', 'dec'],
    -  STANDALONESHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul',
    -    'aŭg', 'sep', 'okt', 'nov', 'dec'],
    -  WEEKDAYS: ['dimanĉo', 'lundo', 'mardo', 'merkredo', 'ĵaŭdo', 'vendredo',
    -    'sabato'],
    -  STANDALONEWEEKDAYS: ['dimanĉo', 'lundo', 'mardo', 'merkredo', 'ĵaŭdo',
    -    'vendredo', 'sabato'],
    -  SHORTWEEKDAYS: ['di', 'lu', 'ma', 'me', 'ĵa', 've', 'sa'],
    -  STANDALONESHORTWEEKDAYS: ['di', 'lu', 'ma', 'me', 'ĵa', 've', 'sa'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'Ĵ', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'Ĵ', 'V', 'S'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['1-a kvaronjaro', '2-a kvaronjaro', '3-a kvaronjaro',
    -    '4-a kvaronjaro'],
    -  AMPMS: ['atm', 'ptm'],
    -  DATEFORMATS: ['EEEE, d-\'a\' \'de\' MMMM y', 'y-MMMM-dd', 'y-MMM-dd',
    -    'yy-MM-dd'],
    -  TIMEFORMATS: ['H-\'a\' \'horo\' \'kaj\' m:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss',
    -    'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale eo_001.
    - */
    -goog.i18n.DateTimeSymbols_eo_001 = goog.i18n.DateTimeSymbols_eo;
    -
    -
    -/**
    - * Date/time formatting symbols for locale es_AR.
    - */
    -goog.i18n.DateTimeSymbols_es_AR = {
    -  ERAS: ['a. C.', 'd. C.'],
    -  ERANAMES: ['antes de Cristo', 'después de Cristo'],
    -  NARROWMONTHS: ['e', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
    -    'agosto', 'setiembre', 'octubre', 'noviembre', 'diciembre'],
    -  STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
    -    'Julio', 'Agosto', 'Setiembre', 'Octubre', 'Noviembre', 'Diciembre'],
    -  SHORTMONTHS: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.',
    -    'set.', 'oct.', 'nov.', 'dic.'],
    -  STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
    -    'Jul.', 'Ago.', 'Set.', 'Oct.', 'Nov.', 'Dic.'],
    -  WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
    -    'sábado'],
    -  STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
    -    'Viernes', 'Sábado'],
    -  SHORTWEEKDAYS: ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
    -  STANDALONESHORTWEEKDAYS: ['Dom.', 'Lun.', 'Mar.', 'Mié.', 'Jue.', 'Vie.',
    -    'Sáb.'],
    -  NARROWWEEKDAYS: ['d', 'l', 'm', 'm', 'j', 'v', 's'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['1.er trim.', '2.º trim.', '3.er trim.', '4.º trim.'],
    -  QUARTERS: ['1.er trimestre', '2.º trimestre', '3.er trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['a. m.', 'p. m.'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'd \'de\' MMM \'de\' y', 'd/M/yy'],
    -  TIMEFORMATS: ['HH\'h\'\'\'mm:ss zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale es_BO.
    - */
    -goog.i18n.DateTimeSymbols_es_BO = {
    -  ERAS: ['a. C.', 'd. C.'],
    -  ERANAMES: ['antes de Cristo', 'después de Cristo'],
    -  NARROWMONTHS: ['e', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
    -    'agosto', 'setiembre', 'octubre', 'noviembre', 'diciembre'],
    -  STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
    -    'Julio', 'Agosto', 'Setiembre', 'Octubre', 'Noviembre', 'Diciembre'],
    -  SHORTMONTHS: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.',
    -    'set.', 'oct.', 'nov.', 'dic.'],
    -  STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
    -    'Jul.', 'Ago.', 'Set.', 'Oct.', 'Nov.', 'Dic.'],
    -  WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
    -    'sábado'],
    -  STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
    -    'Viernes', 'Sábado'],
    -  SHORTWEEKDAYS: ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
    -  STANDALONESHORTWEEKDAYS: ['Dom.', 'Lun.', 'Mar.', 'Mié.', 'Jue.', 'Vie.',
    -    'Sáb.'],
    -  NARROWWEEKDAYS: ['d', 'l', 'm', 'm', 'j', 'v', 's'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['1.er trim.', '2.º trim.', '3.er trim.', '4.º trim.'],
    -  QUARTERS: ['1.er trimestre', '2.º trimestre', '3.er trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['a. m.', 'p. m.'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'd \'de\' MMM \'de\' y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale es_CL.
    - */
    -goog.i18n.DateTimeSymbols_es_CL = {
    -  ERAS: ['a. C.', 'd. C.'],
    -  ERANAMES: ['antes de Cristo', 'después de Cristo'],
    -  NARROWMONTHS: ['e', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
    -    'agosto', 'setiembre', 'octubre', 'noviembre', 'diciembre'],
    -  STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
    -    'Julio', 'Agosto', 'Setiembre', 'Octubre', 'Noviembre', 'Diciembre'],
    -  SHORTMONTHS: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.',
    -    'set.', 'oct.', 'nov.', 'dic.'],
    -  STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
    -    'Jul.', 'Ago.', 'Set.', 'Oct.', 'Nov.', 'Dic.'],
    -  WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
    -    'sábado'],
    -  STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
    -    'Viernes', 'Sábado'],
    -  SHORTWEEKDAYS: ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
    -  STANDALONESHORTWEEKDAYS: ['Dom.', 'Lun.', 'Mar.', 'Mié.', 'Jue.', 'Vie.',
    -    'Sáb.'],
    -  NARROWWEEKDAYS: ['d', 'l', 'm', 'm', 'j', 'v', 's'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['1.er trim.', '2.º trim.', '3.er trim.', '4.º trim.'],
    -  QUARTERS: ['1.er trimestre', '2.º trimestre', '3.er trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['a. m.', 'p. m.'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'dd-MM-y', 'dd-MM-yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale es_CO.
    - */
    -goog.i18n.DateTimeSymbols_es_CO = {
    -  ERAS: ['a. C.', 'd. C.'],
    -  ERANAMES: ['antes de Cristo', 'después de Cristo'],
    -  NARROWMONTHS: ['e', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
    -    'agosto', 'setiembre', 'octubre', 'noviembre', 'diciembre'],
    -  STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
    -    'Julio', 'Agosto', 'Setiembre', 'Octubre', 'Noviembre', 'Diciembre'],
    -  SHORTMONTHS: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.',
    -    'set.', 'oct.', 'nov.', 'dic.'],
    -  STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
    -    'Jul.', 'Ago.', 'Set.', 'Oct.', 'Nov.', 'Dic.'],
    -  WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
    -    'sábado'],
    -  STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
    -    'Viernes', 'Sábado'],
    -  SHORTWEEKDAYS: ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
    -  STANDALONESHORTWEEKDAYS: ['Dom.', 'Lun.', 'Mar.', 'Mié.', 'Jue.', 'Vie.',
    -    'Sáb.'],
    -  NARROWWEEKDAYS: ['d', 'l', 'm', 'm', 'j', 'v', 's'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['1.er trim.', '2.º trim.', '3.er trim.', '4.º trim.'],
    -  QUARTERS: ['1.er trimestre', '2.º trimestre', '3.er trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['a. m.', 'p. m.'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'd/MM/y', 'd/MM/yy'],
    -  TIMEFORMATS: ['h:mm:ss a (zzzz)', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale es_CR.
    - */
    -goog.i18n.DateTimeSymbols_es_CR = {
    -  ERAS: ['a. C.', 'd. C.'],
    -  ERANAMES: ['antes de Cristo', 'después de Cristo'],
    -  NARROWMONTHS: ['e', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
    -    'agosto', 'setiembre', 'octubre', 'noviembre', 'diciembre'],
    -  STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
    -    'Julio', 'Agosto', 'Setiembre', 'Octubre', 'Noviembre', 'Diciembre'],
    -  SHORTMONTHS: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.',
    -    'set.', 'oct.', 'nov.', 'dic.'],
    -  STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
    -    'Jul.', 'Ago.', 'Set.', 'Oct.', 'Nov.', 'Dic.'],
    -  WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
    -    'sábado'],
    -  STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
    -    'Viernes', 'Sábado'],
    -  SHORTWEEKDAYS: ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
    -  STANDALONESHORTWEEKDAYS: ['Dom.', 'Lun.', 'Mar.', 'Mié.', 'Jue.', 'Vie.',
    -    'Sáb.'],
    -  NARROWWEEKDAYS: ['d', 'l', 'm', 'm', 'j', 'v', 's'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['1.er trim.', '2.º trim.', '3.er trim.', '4.º trim.'],
    -  QUARTERS: ['1.er trimestre', '2.º trimestre', '3.er trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['a. m.', 'p. m.'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'd \'de\' MMM \'de\' y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale es_CU.
    - */
    -goog.i18n.DateTimeSymbols_es_CU = {
    -  ERAS: ['a. C.', 'd. C.'],
    -  ERANAMES: ['antes de Cristo', 'después de Cristo'],
    -  NARROWMONTHS: ['e', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
    -    'agosto', 'setiembre', 'octubre', 'noviembre', 'diciembre'],
    -  STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
    -    'Julio', 'Agosto', 'Setiembre', 'Octubre', 'Noviembre', 'Diciembre'],
    -  SHORTMONTHS: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.',
    -    'set.', 'oct.', 'nov.', 'dic.'],
    -  STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
    -    'Jul.', 'Ago.', 'Set.', 'Oct.', 'Nov.', 'Dic.'],
    -  WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
    -    'sábado'],
    -  STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
    -    'Viernes', 'Sábado'],
    -  SHORTWEEKDAYS: ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
    -  STANDALONESHORTWEEKDAYS: ['Dom.', 'Lun.', 'Mar.', 'Mié.', 'Jue.', 'Vie.',
    -    'Sáb.'],
    -  NARROWWEEKDAYS: ['d', 'l', 'm', 'm', 'j', 'v', 's'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['1.er trim.', '2.º trim.', '3.er trim.', '4.º trim.'],
    -  QUARTERS: ['1.er trimestre', '2.º trimestre', '3.er trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['a. m.', 'p. m.'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'd \'de\' MMM \'de\' y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale es_DO.
    - */
    -goog.i18n.DateTimeSymbols_es_DO = {
    -  ERAS: ['a. C.', 'd. C.'],
    -  ERANAMES: ['antes de Cristo', 'después de Cristo'],
    -  NARROWMONTHS: ['e', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
    -    'agosto', 'setiembre', 'octubre', 'noviembre', 'diciembre'],
    -  STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
    -    'Julio', 'Agosto', 'Setiembre', 'Octubre', 'Noviembre', 'Diciembre'],
    -  SHORTMONTHS: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.',
    -    'set.', 'oct.', 'nov.', 'dic.'],
    -  STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
    -    'Jul.', 'Ago.', 'Set.', 'Oct.', 'Nov.', 'Dic.'],
    -  WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
    -    'sábado'],
    -  STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
    -    'Viernes', 'Sábado'],
    -  SHORTWEEKDAYS: ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
    -  STANDALONESHORTWEEKDAYS: ['Dom.', 'Lun.', 'Mar.', 'Mié.', 'Jue.', 'Vie.',
    -    'Sáb.'],
    -  NARROWWEEKDAYS: ['d', 'l', 'm', 'm', 'j', 'v', 's'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['1.er trim.', '2.º trim.', '3.er trim.', '4.º trim.'],
    -  QUARTERS: ['1.er trimestre', '2.º trimestre', '3.er trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['a. m.', 'p. m.'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'd \'de\' MMM \'de\' y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale es_EA.
    - */
    -goog.i18n.DateTimeSymbols_es_EA = {
    -  ERAS: ['a. C.', 'd. C.'],
    -  ERANAMES: ['antes de Cristo', 'anno Dómini'],
    -  NARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
    -    'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],
    -  STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
    -    'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
    -  SHORTMONTHS: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.',
    -    'sept.', 'oct.', 'nov.', 'dic.'],
    -  STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
    -    'Jul.', 'Ago.', 'Sept.', 'Oct.', 'Nov.', 'Dic.'],
    -  WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
    -    'sábado'],
    -  STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
    -    'Viernes', 'Sábado'],
    -  SHORTWEEKDAYS: ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
    -  STANDALONESHORTWEEKDAYS: ['Dom.', 'Lun.', 'Mar.', 'Mié.', 'Jue.', 'Vie.',
    -    'Sáb.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'X', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'X', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1.er trimestre', '2.º trimestre', '3.er trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['a. m.', 'p. m.'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'd \'de\' MMM \'de\' y', 'd/M/yy'],
    -  TIMEFORMATS: ['H:mm:ss (zzzz)', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale es_EC.
    - */
    -goog.i18n.DateTimeSymbols_es_EC = {
    -  ERAS: ['a. C.', 'd. C.'],
    -  ERANAMES: ['antes de Cristo', 'después de Cristo'],
    -  NARROWMONTHS: ['e', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
    -    'agosto', 'setiembre', 'octubre', 'noviembre', 'diciembre'],
    -  STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
    -    'Julio', 'Agosto', 'Setiembre', 'Octubre', 'Noviembre', 'Diciembre'],
    -  SHORTMONTHS: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.',
    -    'set.', 'oct.', 'nov.', 'dic.'],
    -  STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
    -    'Jul.', 'Ago.', 'Set.', 'Oct.', 'Nov.', 'Dic.'],
    -  WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
    -    'sábado'],
    -  STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
    -    'Viernes', 'Sábado'],
    -  SHORTWEEKDAYS: ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
    -  STANDALONESHORTWEEKDAYS: ['Dom.', 'Lun.', 'Mar.', 'Mié.', 'Jue.', 'Vie.',
    -    'Sáb.'],
    -  NARROWWEEKDAYS: ['d', 'l', 'm', 'm', 'j', 'v', 's'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['1.er trim.', '2.º trim.', '3.er trim.', '4.º trim.'],
    -  QUARTERS: ['1.er trimestre', '2.º trimestre', '3.er trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['a. m.', 'p. m.'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'd \'de\' MMM \'de\' y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale es_GQ.
    - */
    -goog.i18n.DateTimeSymbols_es_GQ = {
    -  ERAS: ['a. C.', 'd. C.'],
    -  ERANAMES: ['antes de Cristo', 'anno Dómini'],
    -  NARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
    -    'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],
    -  STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
    -    'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
    -  SHORTMONTHS: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.',
    -    'sept.', 'oct.', 'nov.', 'dic.'],
    -  STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
    -    'Jul.', 'Ago.', 'Sept.', 'Oct.', 'Nov.', 'Dic.'],
    -  WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
    -    'sábado'],
    -  STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
    -    'Viernes', 'Sábado'],
    -  SHORTWEEKDAYS: ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
    -  STANDALONESHORTWEEKDAYS: ['Dom.', 'Lun.', 'Mar.', 'Mié.', 'Jue.', 'Vie.',
    -    'Sáb.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'X', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'X', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1.er trimestre', '2.º trimestre', '3.er trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['a. m.', 'p. m.'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'd \'de\' MMM \'de\' y', 'd/M/yy'],
    -  TIMEFORMATS: ['H:mm:ss (zzzz)', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale es_GT.
    - */
    -goog.i18n.DateTimeSymbols_es_GT = {
    -  ERAS: ['a. C.', 'd. C.'],
    -  ERANAMES: ['antes de Cristo', 'después de Cristo'],
    -  NARROWMONTHS: ['e', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
    -    'agosto', 'setiembre', 'octubre', 'noviembre', 'diciembre'],
    -  STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
    -    'Julio', 'Agosto', 'Setiembre', 'Octubre', 'Noviembre', 'Diciembre'],
    -  SHORTMONTHS: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.',
    -    'set.', 'oct.', 'nov.', 'dic.'],
    -  STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
    -    'Jul.', 'Ago.', 'Set.', 'Oct.', 'Nov.', 'Dic.'],
    -  WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
    -    'sábado'],
    -  STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
    -    'Viernes', 'Sábado'],
    -  SHORTWEEKDAYS: ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
    -  STANDALONESHORTWEEKDAYS: ['Dom.', 'Lun.', 'Mar.', 'Mié.', 'Jue.', 'Vie.',
    -    'Sáb.'],
    -  NARROWWEEKDAYS: ['d', 'l', 'm', 'm', 'j', 'v', 's'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['1.er trim.', '2.º trim.', '3.er trim.', '4.º trim.'],
    -  QUARTERS: ['1.er trimestre', '2.º trimestre', '3.er trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['a. m.', 'p. m.'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'd/MM/y', 'd/MM/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale es_HN.
    - */
    -goog.i18n.DateTimeSymbols_es_HN = {
    -  ERAS: ['a. C.', 'd. C.'],
    -  ERANAMES: ['antes de Cristo', 'después de Cristo'],
    -  NARROWMONTHS: ['e', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
    -    'agosto', 'setiembre', 'octubre', 'noviembre', 'diciembre'],
    -  STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
    -    'Julio', 'Agosto', 'Setiembre', 'Octubre', 'Noviembre', 'Diciembre'],
    -  SHORTMONTHS: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.',
    -    'set.', 'oct.', 'nov.', 'dic.'],
    -  STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
    -    'Jul.', 'Ago.', 'Set.', 'Oct.', 'Nov.', 'Dic.'],
    -  WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
    -    'sábado'],
    -  STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
    -    'Viernes', 'Sábado'],
    -  SHORTWEEKDAYS: ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
    -  STANDALONESHORTWEEKDAYS: ['Dom.', 'Lun.', 'Mar.', 'Mié.', 'Jue.', 'Vie.',
    -    'Sáb.'],
    -  NARROWWEEKDAYS: ['d', 'l', 'm', 'm', 'j', 'v', 's'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['1.er trim.', '2.º trim.', '3.er trim.', '4.º trim.'],
    -  QUARTERS: ['1.er trimestre', '2.º trimestre', '3.er trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['a. m.', 'p. m.'],
    -  DATEFORMATS: ['EEEE dd \'de\' MMMM \'de\' y', 'dd \'de\' MMMM \'de\' y',
    -    'd \'de\' MMM \'de\' y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale es_IC.
    - */
    -goog.i18n.DateTimeSymbols_es_IC = {
    -  ERAS: ['a. C.', 'd. C.'],
    -  ERANAMES: ['antes de Cristo', 'anno Dómini'],
    -  NARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
    -    'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],
    -  STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
    -    'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
    -  SHORTMONTHS: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.',
    -    'sept.', 'oct.', 'nov.', 'dic.'],
    -  STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
    -    'Jul.', 'Ago.', 'Sept.', 'Oct.', 'Nov.', 'Dic.'],
    -  WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
    -    'sábado'],
    -  STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
    -    'Viernes', 'Sábado'],
    -  SHORTWEEKDAYS: ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
    -  STANDALONESHORTWEEKDAYS: ['Dom.', 'Lun.', 'Mar.', 'Mié.', 'Jue.', 'Vie.',
    -    'Sáb.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'X', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'X', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1.er trimestre', '2.º trimestre', '3.er trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['a. m.', 'p. m.'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'd \'de\' MMM \'de\' y', 'd/M/yy'],
    -  TIMEFORMATS: ['H:mm:ss (zzzz)', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale es_MX.
    - */
    -goog.i18n.DateTimeSymbols_es_MX = {
    -  ERAS: ['a.C.', 'd.C.'],
    -  ERANAMES: ['antes de Cristo', 'Anno Domini'],
    -  NARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
    -    'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],
    -  STANDALONEMONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio',
    -    'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],
    -  SHORTMONTHS: ['ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul', 'ago', 'sep',
    -    'oct', 'nov', 'dic'],
    -  STANDALONESHORTMONTHS: ['ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul',
    -    'ago', 'sep', 'oct', 'nov', 'dic'],
    -  WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
    -    'sábado'],
    -  STANDALONEWEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves',
    -    'viernes', 'sábado'],
    -  SHORTWEEKDAYS: ['dom', 'lun', 'mar', 'mié', 'jue', 'vie', 'sáb'],
    -  STANDALONESHORTWEEKDAYS: ['dom', 'lun', 'mar', 'mié', 'jue', 'vie', 'sáb'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['d', 'l', 'm', 'm', 'j', 'v', 's'],
    -  SHORTQUARTERS: ['1er. trim.', '2º. trim.', '3er. trim.', '4º trim.'],
    -  QUARTERS: ['1er. trimestre', '2º. trimestre', '3er. trimestre',
    -    '4º trimestre'],
    -  AMPMS: ['a.m.', 'p.m.'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'dd/MM/y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['H:mm:ss zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale es_NI.
    - */
    -goog.i18n.DateTimeSymbols_es_NI = {
    -  ERAS: ['a. C.', 'd. C.'],
    -  ERANAMES: ['antes de Cristo', 'después de Cristo'],
    -  NARROWMONTHS: ['e', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
    -    'agosto', 'setiembre', 'octubre', 'noviembre', 'diciembre'],
    -  STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
    -    'Julio', 'Agosto', 'Setiembre', 'Octubre', 'Noviembre', 'Diciembre'],
    -  SHORTMONTHS: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.',
    -    'set.', 'oct.', 'nov.', 'dic.'],
    -  STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
    -    'Jul.', 'Ago.', 'Set.', 'Oct.', 'Nov.', 'Dic.'],
    -  WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
    -    'sábado'],
    -  STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
    -    'Viernes', 'Sábado'],
    -  SHORTWEEKDAYS: ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
    -  STANDALONESHORTWEEKDAYS: ['Dom.', 'Lun.', 'Mar.', 'Mié.', 'Jue.', 'Vie.',
    -    'Sáb.'],
    -  NARROWWEEKDAYS: ['d', 'l', 'm', 'm', 'j', 'v', 's'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['1.er trim.', '2.º trim.', '3.er trim.', '4.º trim.'],
    -  QUARTERS: ['1.er trimestre', '2.º trimestre', '3.er trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['a. m.', 'p. m.'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'd \'de\' MMM \'de\' y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale es_PA.
    - */
    -goog.i18n.DateTimeSymbols_es_PA = {
    -  ERAS: ['a. C.', 'd. C.'],
    -  ERANAMES: ['antes de Cristo', 'después de Cristo'],
    -  NARROWMONTHS: ['e', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
    -    'agosto', 'setiembre', 'octubre', 'noviembre', 'diciembre'],
    -  STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
    -    'Julio', 'Agosto', 'Setiembre', 'Octubre', 'Noviembre', 'Diciembre'],
    -  SHORTMONTHS: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.',
    -    'set.', 'oct.', 'nov.', 'dic.'],
    -  STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
    -    'Jul.', 'Ago.', 'Set.', 'Oct.', 'Nov.', 'Dic.'],
    -  WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
    -    'sábado'],
    -  STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
    -    'Viernes', 'Sábado'],
    -  SHORTWEEKDAYS: ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
    -  STANDALONESHORTWEEKDAYS: ['Dom.', 'Lun.', 'Mar.', 'Mié.', 'Jue.', 'Vie.',
    -    'Sáb.'],
    -  NARROWWEEKDAYS: ['d', 'l', 'm', 'm', 'j', 'v', 's'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['1.er trim.', '2.º trim.', '3.er trim.', '4.º trim.'],
    -  QUARTERS: ['1.er trimestre', '2.º trimestre', '3.er trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['a. m.', 'p. m.'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'MM/dd/y', 'MM/dd/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale es_PE.
    - */
    -goog.i18n.DateTimeSymbols_es_PE = {
    -  ERAS: ['a. C.', 'd. C.'],
    -  ERANAMES: ['antes de Cristo', 'después de Cristo'],
    -  NARROWMONTHS: ['e', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
    -    'agosto', 'setiembre', 'octubre', 'noviembre', 'diciembre'],
    -  STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
    -    'Julio', 'Agosto', 'Setiembre', 'Octubre', 'Noviembre', 'Diciembre'],
    -  SHORTMONTHS: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.',
    -    'set.', 'oct.', 'nov.', 'dic.'],
    -  STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
    -    'Jul.', 'Ago.', 'Set.', 'Oct.', 'Nov.', 'Dic.'],
    -  WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
    -    'sábado'],
    -  STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
    -    'Viernes', 'Sábado'],
    -  SHORTWEEKDAYS: ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
    -  STANDALONESHORTWEEKDAYS: ['Dom.', 'Lun.', 'Mar.', 'Mié.', 'Jue.', 'Vie.',
    -    'Sáb.'],
    -  NARROWWEEKDAYS: ['d', 'l', 'm', 'm', 'j', 'v', 's'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['1.er trim.', '2.º trim.', '3.er trim.', '4.º trim.'],
    -  QUARTERS: ['1.er trimestre', '2.º trimestre', '3.er trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['a. m.', 'p. m.'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'd \'de\' MMM \'de\' y', 'd/MM/yy'],
    -  TIMEFORMATS: ['HH\'H\'mm\'\'ss\'\' zzzz', 'h:mm:ss a z', 'h:mm:ss a',
    -    'h:mm a'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale es_PH.
    - */
    -goog.i18n.DateTimeSymbols_es_PH = {
    -  ERAS: ['a. C.', 'd. C.'],
    -  ERANAMES: ['antes de Cristo', 'anno Dómini'],
    -  NARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
    -    'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],
    -  STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
    -    'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
    -  SHORTMONTHS: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.',
    -    'sept.', 'oct.', 'nov.', 'dic.'],
    -  STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
    -    'Jul.', 'Ago.', 'Sept.', 'Oct.', 'Nov.', 'Dic.'],
    -  WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
    -    'sábado'],
    -  STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
    -    'Viernes', 'Sábado'],
    -  SHORTWEEKDAYS: ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
    -  STANDALONESHORTWEEKDAYS: ['Dom.', 'Lun.', 'Mar.', 'Mié.', 'Jue.', 'Vie.',
    -    'Sáb.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'X', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'X', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1.er trimestre', '2.º trimestre', '3.er trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['a. m.', 'p. m.'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'd \'de\' MMM \'de\' y', 'd/M/yy'],
    -  TIMEFORMATS: ['H:mm:ss (zzzz)', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale es_PR.
    - */
    -goog.i18n.DateTimeSymbols_es_PR = {
    -  ERAS: ['a. C.', 'd. C.'],
    -  ERANAMES: ['antes de Cristo', 'después de Cristo'],
    -  NARROWMONTHS: ['e', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
    -    'agosto', 'setiembre', 'octubre', 'noviembre', 'diciembre'],
    -  STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
    -    'Julio', 'Agosto', 'Setiembre', 'Octubre', 'Noviembre', 'Diciembre'],
    -  SHORTMONTHS: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.',
    -    'set.', 'oct.', 'nov.', 'dic.'],
    -  STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
    -    'Jul.', 'Ago.', 'Set.', 'Oct.', 'Nov.', 'Dic.'],
    -  WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
    -    'sábado'],
    -  STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
    -    'Viernes', 'Sábado'],
    -  SHORTWEEKDAYS: ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
    -  STANDALONESHORTWEEKDAYS: ['Dom.', 'Lun.', 'Mar.', 'Mié.', 'Jue.', 'Vie.',
    -    'Sáb.'],
    -  NARROWWEEKDAYS: ['d', 'l', 'm', 'm', 'j', 'v', 's'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['1.er trim.', '2.º trim.', '3.er trim.', '4.º trim.'],
    -  QUARTERS: ['1.er trimestre', '2.º trimestre', '3.er trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['a. m.', 'p. m.'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'MM/dd/y', 'MM/dd/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale es_PY.
    - */
    -goog.i18n.DateTimeSymbols_es_PY = {
    -  ERAS: ['a. C.', 'd. C.'],
    -  ERANAMES: ['antes de Cristo', 'después de Cristo'],
    -  NARROWMONTHS: ['e', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
    -    'agosto', 'setiembre', 'octubre', 'noviembre', 'diciembre'],
    -  STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
    -    'Julio', 'Agosto', 'Setiembre', 'Octubre', 'Noviembre', 'Diciembre'],
    -  SHORTMONTHS: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.',
    -    'set.', 'oct.', 'nov.', 'dic.'],
    -  STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
    -    'Jul.', 'Ago.', 'Set.', 'Oct.', 'Nov.', 'Dic.'],
    -  WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
    -    'sábado'],
    -  STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
    -    'Viernes', 'Sábado'],
    -  SHORTWEEKDAYS: ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
    -  STANDALONESHORTWEEKDAYS: ['Dom.', 'Lun.', 'Mar.', 'Mié.', 'Jue.', 'Vie.',
    -    'Sáb.'],
    -  NARROWWEEKDAYS: ['d', 'l', 'm', 'm', 'j', 'v', 's'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['1.er trim.', '2.º trim.', '3.er trim.', '4.º trim.'],
    -  QUARTERS: ['1.er trimestre', '2.º trimestre', '3.er trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['a. m.', 'p. m.'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'd \'de\' MMM \'de\' y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale es_SV.
    - */
    -goog.i18n.DateTimeSymbols_es_SV = {
    -  ERAS: ['a. C.', 'd. C.'],
    -  ERANAMES: ['antes de Cristo', 'después de Cristo'],
    -  NARROWMONTHS: ['e', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
    -    'agosto', 'setiembre', 'octubre', 'noviembre', 'diciembre'],
    -  STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
    -    'Julio', 'Agosto', 'Setiembre', 'Octubre', 'Noviembre', 'Diciembre'],
    -  SHORTMONTHS: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.',
    -    'set.', 'oct.', 'nov.', 'dic.'],
    -  STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
    -    'Jul.', 'Ago.', 'Set.', 'Oct.', 'Nov.', 'Dic.'],
    -  WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
    -    'sábado'],
    -  STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
    -    'Viernes', 'Sábado'],
    -  SHORTWEEKDAYS: ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
    -  STANDALONESHORTWEEKDAYS: ['Dom.', 'Lun.', 'Mar.', 'Mié.', 'Jue.', 'Vie.',
    -    'Sáb.'],
    -  NARROWWEEKDAYS: ['d', 'l', 'm', 'm', 'j', 'v', 's'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['1.er trim.', '2.º trim.', '3.er trim.', '4.º trim.'],
    -  QUARTERS: ['1.er trimestre', '2.º trimestre', '3.er trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['a. m.', 'p. m.'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'd \'de\' MMM \'de\' y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale es_US.
    - */
    -goog.i18n.DateTimeSymbols_es_US = {
    -  ERAS: ['a. C.', 'd. C.'],
    -  ERANAMES: ['antes de Cristo', 'después de Cristo'],
    -  NARROWMONTHS: ['e', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
    -    'agosto', 'setiembre', 'octubre', 'noviembre', 'diciembre'],
    -  STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
    -    'Julio', 'Agosto', 'Setiembre', 'Octubre', 'Noviembre', 'Diciembre'],
    -  SHORTMONTHS: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.',
    -    'set.', 'oct.', 'nov.', 'dic.'],
    -  STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
    -    'Jul.', 'Ago.', 'Set.', 'Oct.', 'Nov.', 'Dic.'],
    -  WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
    -    'sábado'],
    -  STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
    -    'Viernes', 'Sábado'],
    -  SHORTWEEKDAYS: ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
    -  STANDALONESHORTWEEKDAYS: ['Dom.', 'Lun.', 'Mar.', 'Mié.', 'Jue.', 'Vie.',
    -    'Sáb.'],
    -  NARROWWEEKDAYS: ['d', 'l', 'm', 'm', 'j', 'v', 's'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['1.er trim.', '2.º trim.', '3.er trim.', '4.º trim.'],
    -  QUARTERS: ['1.er trimestre', '2.º trimestre', '3.er trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'd \'de\' MMM \'de\' y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale es_UY.
    - */
    -goog.i18n.DateTimeSymbols_es_UY = {
    -  ERAS: ['a. C.', 'd. C.'],
    -  ERANAMES: ['antes de Cristo', 'después de Cristo'],
    -  NARROWMONTHS: ['e', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
    -    'agosto', 'setiembre', 'octubre', 'noviembre', 'diciembre'],
    -  STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
    -    'Julio', 'Agosto', 'Setiembre', 'Octubre', 'Noviembre', 'Diciembre'],
    -  SHORTMONTHS: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.',
    -    'set.', 'oct.', 'nov.', 'dic.'],
    -  STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
    -    'Jul.', 'Ago.', 'Set.', 'Oct.', 'Nov.', 'Dic.'],
    -  WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
    -    'sábado'],
    -  STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
    -    'Viernes', 'Sábado'],
    -  SHORTWEEKDAYS: ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
    -  STANDALONESHORTWEEKDAYS: ['Dom.', 'Lun.', 'Mar.', 'Mié.', 'Jue.', 'Vie.',
    -    'Sáb.'],
    -  NARROWWEEKDAYS: ['d', 'l', 'm', 'm', 'j', 'v', 's'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['1.er trim.', '2.º trim.', '3.er trim.', '4.º trim.'],
    -  QUARTERS: ['1.er trimestre', '2.º trimestre', '3.er trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['a. m.', 'p. m.'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'd \'de\' MMM \'de\' y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale es_VE.
    - */
    -goog.i18n.DateTimeSymbols_es_VE = {
    -  ERAS: ['a. C.', 'd. C.'],
    -  ERANAMES: ['antes de Cristo', 'después de Cristo'],
    -  NARROWMONTHS: ['e', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio',
    -    'agosto', 'setiembre', 'octubre', 'noviembre', 'diciembre'],
    -  STANDALONEMONTHS: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
    -    'Julio', 'Agosto', 'Setiembre', 'Octubre', 'Noviembre', 'Diciembre'],
    -  SHORTMONTHS: ['ene.', 'feb.', 'mar.', 'abr.', 'may.', 'jun.', 'jul.', 'ago.',
    -    'set.', 'oct.', 'nov.', 'dic.'],
    -  STANDALONESHORTMONTHS: ['Ene.', 'Feb.', 'Mar.', 'Abr.', 'May.', 'Jun.',
    -    'Jul.', 'Ago.', 'Set.', 'Oct.', 'Nov.', 'Dic.'],
    -  WEEKDAYS: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes',
    -    'sábado'],
    -  STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
    -    'Viernes', 'Sábado'],
    -  SHORTWEEKDAYS: ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
    -  STANDALONESHORTWEEKDAYS: ['Dom.', 'Lun.', 'Mar.', 'Mié.', 'Jue.', 'Vie.',
    -    'Sáb.'],
    -  NARROWWEEKDAYS: ['d', 'l', 'm', 'm', 'j', 'v', 's'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['1.er trim.', '2.º trim.', '3.er trim.', '4.º trim.'],
    -  QUARTERS: ['1.er trimestre', '2.º trimestre', '3.er trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['a. m.', 'p. m.'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'd \'de\' MMM \'de\' y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale et_EE.
    - */
    -goog.i18n.DateTimeSymbols_et_EE = {
    -  ERAS: ['e.m.a.', 'm.a.j.'],
    -  ERANAMES: ['enne meie aega', 'meie aja järgi'],
    -  NARROWMONTHS: ['J', 'V', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'V', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['jaanuar', 'veebruar', 'märts', 'aprill', 'mai', 'juuni', 'juuli',
    -    'august', 'september', 'oktoober', 'november', 'detsember'],
    -  STANDALONEMONTHS: ['jaanuar', 'veebruar', 'märts', 'aprill', 'mai', 'juuni',
    -    'juuli', 'august', 'september', 'oktoober', 'november', 'detsember'],
    -  SHORTMONTHS: ['jaan', 'veebr', 'märts', 'apr', 'mai', 'juuni', 'juuli',
    -    'aug', 'sept', 'okt', 'nov', 'dets'],
    -  STANDALONESHORTMONTHS: ['jaan', 'veebr', 'märts', 'apr', 'mai', 'juuni',
    -    'juuli', 'aug', 'sept', 'okt', 'nov', 'dets'],
    -  WEEKDAYS: ['pühapäev', 'esmaspäev', 'teisipäev', 'kolmapäev',
    -    'neljapäev', 'reede', 'laupäev'],
    -  STANDALONEWEEKDAYS: ['pühapäev', 'esmaspäev', 'teisipäev', 'kolmapäev',
    -    'neljapäev', 'reede', 'laupäev'],
    -  SHORTWEEKDAYS: ['P', 'E', 'T', 'K', 'N', 'R', 'L'],
    -  STANDALONESHORTWEEKDAYS: ['P', 'E', 'T', 'K', 'N', 'R', 'L'],
    -  NARROWWEEKDAYS: ['P', 'E', 'T', 'K', 'N', 'R', 'L'],
    -  STANDALONENARROWWEEKDAYS: ['P', 'E', 'T', 'K', 'N', 'R', 'L'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['1. kvartal', '2. kvartal', '3. kvartal', '4. kvartal'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d. MMMM y', 'd. MMMM y', 'd. MMM y', 'dd.MM.yy'],
    -  TIMEFORMATS: ['H:mm.ss zzzz', 'H:mm.ss z', 'H:mm.ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale eu_ES.
    - */
    -goog.i18n.DateTimeSymbols_eu_ES = {
    -  ERAS: ['K.a.', 'K.o.'],
    -  ERANAMES: ['K.a.', 'K.o.'],
    -  NARROWMONTHS: ['U', 'O', 'M', 'A', 'M', 'E', 'U', 'A', 'I', 'U', 'A', 'A'],
    -  STANDALONENARROWMONTHS: ['U', 'O', 'M', 'A', 'M', 'E', 'U', 'A', 'I', 'U',
    -    'A', 'A'],
    -  MONTHS: ['urtarrilak', 'otsailak', 'martxoak', 'apirilak', 'maiatzak',
    -    'ekainak', 'uztailak', 'abuztuak', 'irailak', 'urriak', 'azaroak',
    -    'abenduak'],
    -  STANDALONEMONTHS: ['Urtarrila', 'Otsaila', 'Martxoa', 'Apirila', 'Maiatza',
    -    'Ekaina', 'Uztaila', 'Abuztua', 'Iraila', 'Urria', 'Azaroa', 'Abendua'],
    -  SHORTMONTHS: ['urt.', 'ots.', 'mar.', 'api.', 'mai.', 'eka.', 'uzt.', 'abu.',
    -    'ira.', 'urr.', 'aza.', 'abe.'],
    -  STANDALONESHORTMONTHS: ['Urt.', 'Ots.', 'Mar.', 'Api.', 'Mai.', 'Eka.',
    -    'Uzt.', 'Abu.', 'Ira.', 'Urr.', 'Aza.', 'Abe.'],
    -  WEEKDAYS: ['igandea', 'astelehena', 'asteartea', 'asteazkena', 'osteguna',
    -    'ostirala', 'larunbata'],
    -  STANDALONEWEEKDAYS: ['Igandea', 'Astelehena', 'Asteartea', 'Asteazkena',
    -    'Osteguna', 'Ostirala', 'Larunbata'],
    -  SHORTWEEKDAYS: ['ig.', 'al.', 'ar.', 'az.', 'og.', 'or.', 'lr.'],
    -  STANDALONESHORTWEEKDAYS: ['Ig.', 'Al.', 'Ar.', 'Az.', 'Og.', 'Or.', 'Lr.'],
    -  NARROWWEEKDAYS: ['I', 'A', 'A', 'A', 'O', 'O', 'L'],
    -  STANDALONENARROWWEEKDAYS: ['I', 'A', 'A', 'A', 'O', 'O', 'L'],
    -  SHORTQUARTERS: ['1Hh', '2Hh', '3Hh', '4Hh'],
    -  QUARTERS: ['1. hiruhilekoa', '2. hiruhilekoa', '3. hiruhilekoa',
    -    '4. hiruhilekoa'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['y(\'e\')\'ko\' MMMM d, EEEE', 'y(\'e\')\'ko\' MMMM d',
    -    'y MMM d', 'y/MM/dd'],
    -  TIMEFORMATS: ['HH:mm:ss (zzzz)', 'HH:mm:ss (z)', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ewo.
    - */
    -goog.i18n.DateTimeSymbols_ewo = {
    -  ERAS: ['oyk', 'ayk'],
    -  ERANAMES: ['osúsúa Yésus kiri', 'ámvus Yésus Kirís'],
    -  NARROWMONTHS: ['o', 'b', 'l', 'n', 't', 's', 'z', 'm', 'e', 'a', 'd', 'b'],
    -  STANDALONENARROWMONTHS: ['o', 'b', 'l', 'n', 't', 's', 'z', 'm', 'e', 'a',
    -    'd', 'b'],
    -  MONTHS: ['ngɔn osú', 'ngɔn bɛ̌', 'ngɔn lála', 'ngɔn nyina',
    -    'ngɔn tána', 'ngɔn saməna', 'ngɔn zamgbála', 'ngɔn mwom',
    -    'ngɔn ebulú', 'ngɔn awóm', 'ngɔn awóm ai dziá',
    -    'ngɔn awóm ai bɛ̌'],
    -  STANDALONEMONTHS: ['ngɔn osú', 'ngɔn bɛ̌', 'ngɔn lála', 'ngɔn nyina',
    -    'ngɔn tána', 'ngɔn saməna', 'ngɔn zamgbála', 'ngɔn mwom',
    -    'ngɔn ebulú', 'ngɔn awóm', 'ngɔn awóm ai dziá',
    -    'ngɔn awóm ai bɛ̌'],
    -  SHORTMONTHS: ['ngo', 'ngb', 'ngl', 'ngn', 'ngt', 'ngs', 'ngz', 'ngm', 'nge',
    -    'nga', 'ngad', 'ngab'],
    -  STANDALONESHORTMONTHS: ['ngo', 'ngb', 'ngl', 'ngn', 'ngt', 'ngs', 'ngz',
    -    'ngm', 'nge', 'nga', 'ngad', 'ngab'],
    -  WEEKDAYS: ['sɔ́ndɔ', 'mɔ́ndi', 'sɔ́ndɔ məlú mə́bɛ̌',
    -    'sɔ́ndɔ məlú mə́lɛ́', 'sɔ́ndɔ məlú mə́nyi', 'fúladé',
    -    'séradé'],
    -  STANDALONEWEEKDAYS: ['sɔ́ndɔ', 'mɔ́ndi', 'sɔ́ndɔ məlú mə́bɛ̌',
    -    'sɔ́ndɔ məlú mə́lɛ́', 'sɔ́ndɔ məlú mə́nyi', 'fúladé',
    -    'séradé'],
    -  SHORTWEEKDAYS: ['sɔ́n', 'mɔ́n', 'smb', 'sml', 'smn', 'fúl', 'sér'],
    -  STANDALONESHORTWEEKDAYS: ['sɔ́n', 'mɔ́n', 'smb', 'sml', 'smn', 'fúl',
    -    'sér'],
    -  NARROWWEEKDAYS: ['s', 'm', 's', 's', 's', 'f', 's'],
    -  STANDALONENARROWWEEKDAYS: ['s', 'm', 's', 's', 's', 'f', 's'],
    -  SHORTQUARTERS: ['nno', 'nnb', 'nnl', 'nnny'],
    -  QUARTERS: ['nsámbá ngɔn asú', 'nsámbá ngɔn bɛ̌',
    -    'nsámbá ngɔn lála', 'nsámbá ngɔn nyina'],
    -  AMPMS: ['kíkíríg', 'ngəgógəle'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ewo_CM.
    - */
    -goog.i18n.DateTimeSymbols_ewo_CM = goog.i18n.DateTimeSymbols_ewo;
    -
    -
    -/**
    - * Date/time formatting symbols for locale fa_AF.
    - */
    -goog.i18n.DateTimeSymbols_fa_AF = {
    -  ZERODIGIT: 0x06F0,
    -  ERAS: ['ق.م.', 'م.'],
    -  ERANAMES: ['قبل از میلاد', 'میلادی'],
    -  NARROWMONTHS: ['ژ', 'ف', 'م', 'آ', 'م', 'ژ', 'ژ', 'ا', 'س', 'ا',
    -    'ن', 'د'],
    -  STANDALONENARROWMONTHS: ['ج', 'ف', 'م', 'ا', 'م', 'ج', 'ج', 'ا', 'س',
    -    'ا', 'ن', 'د'],
    -  MONTHS: ['جنوری', 'فبروری', 'مارچ', 'اپریل', 'می',
    -    'جون', 'جولای', 'اگست', 'سپتمبر', 'اکتوبر',
    -    'نومبر', 'دسمبر'],
    -  STANDALONEMONTHS: ['ژانویه', 'فوریه', 'مارس', 'آوریل',
    -    'مه', 'ژوئن', 'ژوئیه', 'اوت', 'سپتامبر', 'اکتبر',
    -    'نوامبر', 'دسامبر'],
    -  SHORTMONTHS: ['جنو', 'فوریهٔ', 'مارس', 'آوریل', 'مـی',
    -    'ژوئن', 'جول', 'اوت', 'سپتامبر', 'اکتبر',
    -    'نوامبر', 'دسم'],
    -  STANDALONESHORTMONTHS: ['ژانویه', 'فوریه', 'مارس',
    -    'آوریل', 'مه', 'ژوئن', 'ژوئیه', 'اوت', 'سپتامبر',
    -    'اکتبر', 'نوامبر', 'دسامبر'],
    -  WEEKDAYS: ['یکشنبه', 'دوشنبه', 'سه‌شنبه',
    -    'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'],
    -  STANDALONEWEEKDAYS: ['یکشنبه', 'دوشنبه', 'سه‌شنبه',
    -    'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'],
    -  SHORTWEEKDAYS: ['یکشنبه', 'دوشنبه', 'سه‌شنبه',
    -    'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'],
    -  STANDALONESHORTWEEKDAYS: ['یکشنبه', 'دوشنبه', 'سه‌شنبه',
    -    'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'],
    -  NARROWWEEKDAYS: ['ی', 'د', 'س', 'چ', 'پ', 'ج', 'ش'],
    -  STANDALONENARROWWEEKDAYS: ['ی', 'د', 'س', 'چ', 'پ', 'ج', 'ش'],
    -  SHORTQUARTERS: ['س‌م۱', 'س‌م۲', 'س‌م۳', 'س‌م۴'],
    -  QUARTERS: ['سه‌ماههٔ اول', 'سه‌ماههٔ دوم',
    -    'سه‌ماههٔ سوم', 'سه‌ماههٔ چهارم'],
    -  AMPMS: ['قبل‌ازظهر', 'بعدازظهر'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'y/M/d'],
    -  TIMEFORMATS: ['H:mm:ss (zzzz)', 'H:mm:ss (z)', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1}، ساعت {0}', '{1}، ساعت {0}', '{1}،‏ {0}',
    -    '{1}،‏ {0}'],
    -  FIRSTDAYOFWEEK: 5,
    -  WEEKENDRANGE: [3, 4],
    -  FIRSTWEEKCUTOFFDAY: 4
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fa_IR.
    - */
    -goog.i18n.DateTimeSymbols_fa_IR = {
    -  ZERODIGIT: 0x06F0,
    -  ERAS: ['ق.م.', 'م.'],
    -  ERANAMES: ['قبل از میلاد', 'میلادی'],
    -  NARROWMONTHS: ['ژ', 'ف', 'م', 'آ', 'م', 'ژ', 'ژ', 'ا', 'س', 'ا',
    -    'ن', 'د'],
    -  STANDALONENARROWMONTHS: ['ژ', 'ف', 'م', 'آ', 'م', 'ژ', 'ژ', 'ا', 'س',
    -    'ا', 'ن', 'د'],
    -  MONTHS: ['ژانویهٔ', 'فوریهٔ', 'مارس', 'آوریل', 'مهٔ',
    -    'ژوئن', 'ژوئیهٔ', 'اوت', 'سپتامبر', 'اکتبر',
    -    'نوامبر', 'دسامبر'],
    -  STANDALONEMONTHS: ['ژانویه', 'فوریه', 'مارس', 'آوریل',
    -    'مه', 'ژوئن', 'ژوئیه', 'اوت', 'سپتامبر', 'اکتبر',
    -    'نوامبر', 'دسامبر'],
    -  SHORTMONTHS: ['ژانویهٔ', 'فوریهٔ', 'مارس', 'آوریل',
    -    'مهٔ', 'ژوئن', 'ژوئیهٔ', 'اوت', 'سپتامبر',
    -    'اکتبر', 'نوامبر', 'دسامبر'],
    -  STANDALONESHORTMONTHS: ['ژانویه', 'فوریه', 'مارس',
    -    'آوریل', 'مه', 'ژوئن', 'ژوئیه', 'اوت', 'سپتامبر',
    -    'اکتبر', 'نوامبر', 'دسامبر'],
    -  WEEKDAYS: ['یکشنبه', 'دوشنبه', 'سه‌شنبه',
    -    'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'],
    -  STANDALONEWEEKDAYS: ['یکشنبه', 'دوشنبه', 'سه‌شنبه',
    -    'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'],
    -  SHORTWEEKDAYS: ['یکشنبه', 'دوشنبه', 'سه‌شنبه',
    -    'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'],
    -  STANDALONESHORTWEEKDAYS: ['یکشنبه', 'دوشنبه', 'سه‌شنبه',
    -    'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'],
    -  NARROWWEEKDAYS: ['ی', 'د', 'س', 'چ', 'پ', 'ج', 'ش'],
    -  STANDALONENARROWWEEKDAYS: ['ی', 'د', 'س', 'چ', 'پ', 'ج', 'ش'],
    -  SHORTQUARTERS: ['س‌م۱', 'س‌م۲', 'س‌م۳', 'س‌م۴'],
    -  QUARTERS: ['سه‌ماههٔ اول', 'سه‌ماههٔ دوم',
    -    'سه‌ماههٔ سوم', 'سه‌ماههٔ چهارم'],
    -  AMPMS: ['قبل‌ازظهر', 'بعدازظهر'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'y/M/d'],
    -  TIMEFORMATS: ['H:mm:ss (zzzz)', 'H:mm:ss (z)', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1}، ساعت {0}', '{1}، ساعت {0}', '{1}،‏ {0}',
    -    '{1}،‏ {0}'],
    -  FIRSTDAYOFWEEK: 5,
    -  WEEKENDRANGE: [4, 4],
    -  FIRSTWEEKCUTOFFDAY: 4
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ff.
    - */
    -goog.i18n.DateTimeSymbols_ff = {
    -  ERAS: ['H-I', 'C-I'],
    -  ERANAMES: ['Hade Iisa', 'Caggal Iisa'],
    -  NARROWMONTHS: ['s', 'c', 'm', 's', 'd', 'k', 'm', 'j', 's', 'y', 'j', 'b'],
    -  STANDALONENARROWMONTHS: ['s', 'c', 'm', 's', 'd', 'k', 'm', 'j', 's', 'y',
    -    'j', 'b'],
    -  MONTHS: ['siilo', 'colte', 'mbooy', 'seeɗto', 'duujal', 'korse', 'morso',
    -    'juko', 'siilto', 'yarkomaa', 'jolal', 'bowte'],
    -  STANDALONEMONTHS: ['siilo', 'colte', 'mbooy', 'seeɗto', 'duujal', 'korse',
    -    'morso', 'juko', 'siilto', 'yarkomaa', 'jolal', 'bowte'],
    -  SHORTMONTHS: ['sii', 'col', 'mbo', 'see', 'duu', 'kor', 'mor', 'juk', 'slt',
    -    'yar', 'jol', 'bow'],
    -  STANDALONESHORTMONTHS: ['sii', 'col', 'mbo', 'see', 'duu', 'kor', 'mor',
    -    'juk', 'slt', 'yar', 'jol', 'bow'],
    -  WEEKDAYS: ['dewo', 'aaɓnde', 'mawbaare', 'njeslaare', 'naasaande', 'mawnde',
    -    'hoore-biir'],
    -  STANDALONEWEEKDAYS: ['dewo', 'aaɓnde', 'mawbaare', 'njeslaare', 'naasaande',
    -    'mawnde', 'hoore-biir'],
    -  SHORTWEEKDAYS: ['dew', 'aaɓ', 'maw', 'nje', 'naa', 'mwd', 'hbi'],
    -  STANDALONESHORTWEEKDAYS: ['dew', 'aaɓ', 'maw', 'nje', 'naa', 'mwd', 'hbi'],
    -  NARROWWEEKDAYS: ['d', 'a', 'm', 'n', 'n', 'm', 'h'],
    -  STANDALONENARROWWEEKDAYS: ['d', 'a', 'm', 'n', 'n', 'm', 'h'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['Termes 1', 'Termes 2', 'Termes 3', 'Termes 4'],
    -  AMPMS: ['subaka', 'kikiiɗe'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM, y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ff_CM.
    - */
    -goog.i18n.DateTimeSymbols_ff_CM = goog.i18n.DateTimeSymbols_ff;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ff_GN.
    - */
    -goog.i18n.DateTimeSymbols_ff_GN = goog.i18n.DateTimeSymbols_ff;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ff_MR.
    - */
    -goog.i18n.DateTimeSymbols_ff_MR = goog.i18n.DateTimeSymbols_ff;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ff_SN.
    - */
    -goog.i18n.DateTimeSymbols_ff_SN = goog.i18n.DateTimeSymbols_ff;
    -
    -
    -/**
    - * Date/time formatting symbols for locale fi_FI.
    - */
    -goog.i18n.DateTimeSymbols_fi_FI = {
    -  ERAS: ['eKr.', 'jKr.'],
    -  ERANAMES: ['ennen Kristuksen syntymää', 'jälkeen Kristuksen syntymän'],
    -  NARROWMONTHS: ['T', 'H', 'M', 'H', 'T', 'K', 'H', 'E', 'S', 'L', 'M', 'J'],
    -  STANDALONENARROWMONTHS: ['T', 'H', 'M', 'H', 'T', 'K', 'H', 'E', 'S', 'L',
    -    'M', 'J'],
    -  MONTHS: ['tammikuuta', 'helmikuuta', 'maaliskuuta', 'huhtikuuta',
    -    'toukokuuta', 'kesäkuuta', 'heinäkuuta', 'elokuuta', 'syyskuuta',
    -    'lokakuuta', 'marraskuuta', 'joulukuuta'],
    -  STANDALONEMONTHS: ['tammikuu', 'helmikuu', 'maaliskuu', 'huhtikuu',
    -    'toukokuu', 'kesäkuu', 'heinäkuu', 'elokuu', 'syyskuu', 'lokakuu',
    -    'marraskuu', 'joulukuu'],
    -  SHORTMONTHS: ['tammikuuta', 'helmikuuta', 'maaliskuuta', 'huhtikuuta',
    -    'toukokuuta', 'kesäkuuta', 'heinäkuuta', 'elokuuta', 'syyskuuta',
    -    'lokakuuta', 'marraskuuta', 'joulukuuta'],
    -  STANDALONESHORTMONTHS: ['tammi', 'helmi', 'maalis', 'huhti', 'touko', 'kesä',
    -    'heinä', 'elo', 'syys', 'loka', 'marras', 'joulu'],
    -  WEEKDAYS: ['sunnuntaina', 'maanantaina', 'tiistaina', 'keskiviikkona',
    -    'torstaina', 'perjantaina', 'lauantaina'],
    -  STANDALONEWEEKDAYS: ['sunnuntai', 'maanantai', 'tiistai', 'keskiviikko',
    -    'torstai', 'perjantai', 'lauantai'],
    -  SHORTWEEKDAYS: ['su', 'ma', 'ti', 'ke', 'to', 'pe', 'la'],
    -  STANDALONESHORTWEEKDAYS: ['su', 'ma', 'ti', 'ke', 'to', 'pe', 'la'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'K', 'T', 'P', 'L'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'K', 'T', 'P', 'L'],
    -  SHORTQUARTERS: ['1. nelj.', '2. nelj.', '3. nelj.', '4. nelj.'],
    -  QUARTERS: ['1. neljännes', '2. neljännes', '3. neljännes',
    -    '4. neljännes'],
    -  AMPMS: ['ap.', 'ip.'],
    -  DATEFORMATS: ['cccc d. MMMM y', 'd. MMMM y', 'd.M.y', 'd.M.y'],
    -  TIMEFORMATS: ['H.mm.ss zzzz', 'H.mm.ss z', 'H.mm.ss', 'H.mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fil_PH.
    - */
    -goog.i18n.DateTimeSymbols_fil_PH = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['BC', 'AD'],
    -  NARROWMONTHS: ['E', 'P', 'M', 'A', 'M', 'H', 'H', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['E', 'P', 'M', 'A', 'M', 'H', 'H', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Enero', 'Pebrero', 'Marso', 'Abril', 'Mayo', 'Hunyo', 'Hulyo',
    -    'Agosto', 'Setyembre', 'Oktubre', 'Nobyembre', 'Disyembre'],
    -  STANDALONEMONTHS: ['Enero', 'Pebrero', 'Marso', 'Abril', 'Mayo', 'Hunyo',
    -    'Hulyo', 'Agosto', 'Setyembre', 'Oktubre', 'Nobyembre', 'Disyembre'],
    -  SHORTMONTHS: ['Ene', 'Peb', 'Mar', 'Abr', 'May', 'Hun', 'Hul', 'Ago', 'Set',
    -    'Okt', 'Nob', 'Dis'],
    -  STANDALONESHORTMONTHS: ['Ene', 'Peb', 'Mar', 'Abr', 'May', 'Hun', 'Hul',
    -    'Ago', 'Set', 'Okt', 'Nob', 'Dis'],
    -  WEEKDAYS: ['Linggo', 'Lunes', 'Martes', 'Miyerkules', 'Huwebes', 'Biyernes',
    -    'Sabado'],
    -  STANDALONEWEEKDAYS: ['Linggo', 'Lunes', 'Martes', 'Miyerkules', 'Huwebes',
    -    'Biyernes', 'Sabado'],
    -  SHORTWEEKDAYS: ['Lin', 'Lun', 'Mar', 'Miy', 'Huw', 'Biy', 'Sab'],
    -  STANDALONESHORTWEEKDAYS: ['Lin', 'Lun', 'Mar', 'Miy', 'Huw', 'Biy', 'Sab'],
    -  NARROWWEEKDAYS: ['L', 'L', 'M', 'M', 'H', 'B', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['L', 'L', 'M', 'M', 'H', 'B', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['ika-1 quarter', 'ika-2 quarter', 'ika-3 quarter',
    -    'ika-4 na quarter'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'nang\' {0}', '{1} \'nang\' {0}', '{1}, {0}',
    -    '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fo.
    - */
    -goog.i18n.DateTimeSymbols_fo = {
    -  ERAS: ['f.Kr.', 'e.Kr.'],
    -  ERANAMES: ['fyrir Krist', 'eftir Krist'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['januar', 'februar', 'mars', 'apríl', 'mai', 'juni', 'juli',
    -    'august', 'september', 'oktober', 'november', 'desember'],
    -  STANDALONEMONTHS: ['januar', 'februar', 'mars', 'apríl', 'mai', 'juni',
    -    'juli', 'august', 'september', 'oktober', 'november', 'desember'],
    -  SHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'mai', 'jun', 'jul', 'aug', 'sep',
    -    'okt', 'nov', 'des'],
    -  STANDALONESHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'mai', 'jun', 'jul',
    -    'aug', 'sep', 'okt', 'nov', 'des'],
    -  WEEKDAYS: ['sunnudagur', 'mánadagur', 'týsdagur', 'mikudagur', 'hósdagur',
    -    'fríggjadagur', 'leygardagur'],
    -  STANDALONEWEEKDAYS: ['sunnudagur', 'mánadagur', 'týsdagur', 'mikudagur',
    -    'hósdagur', 'fríggjadagur', 'leygardagur'],
    -  SHORTWEEKDAYS: ['sun', 'mán', 'týs', 'mik', 'hós', 'frí', 'ley'],
    -  STANDALONESHORTWEEKDAYS: ['sun', 'mán', 'týs', 'mik', 'hós', 'frí',
    -    'ley'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'M', 'H', 'F', 'L'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'M', 'H', 'F', 'L'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['1. kvartal', '2. kvartal', '3. kvartal', '4. kvartal'],
    -  AMPMS: ['um fyrrapartur', 'um seinnapartur'],
    -  DATEFORMATS: ['EEEE dd MMMM y', 'd. MMM y', 'dd-MM-y', 'dd-MM-yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fo_FO.
    - */
    -goog.i18n.DateTimeSymbols_fo_FO = goog.i18n.DateTimeSymbols_fo;
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_BE.
    - */
    -goog.i18n.DateTimeSymbols_fr_BE = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'd/MM/yy'],
    -  TIMEFORMATS: ['H \'h\' mm \'min\' ss \'s\' zzzz', 'HH:mm:ss z', 'HH:mm:ss',
    -    'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_BF.
    - */
    -goog.i18n.DateTimeSymbols_fr_BF = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_BI.
    - */
    -goog.i18n.DateTimeSymbols_fr_BI = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_BJ.
    - */
    -goog.i18n.DateTimeSymbols_fr_BJ = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_BL.
    - */
    -goog.i18n.DateTimeSymbols_fr_BL = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_CD.
    - */
    -goog.i18n.DateTimeSymbols_fr_CD = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_CF.
    - */
    -goog.i18n.DateTimeSymbols_fr_CF = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_CG.
    - */
    -goog.i18n.DateTimeSymbols_fr_CG = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_CH.
    - */
    -goog.i18n.DateTimeSymbols_fr_CH = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd.MM.yy'],
    -  TIMEFORMATS: ['HH.mm:ss \'h\' zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_CI.
    - */
    -goog.i18n.DateTimeSymbols_fr_CI = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_CM.
    - */
    -goog.i18n.DateTimeSymbols_fr_CM = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_DJ.
    - */
    -goog.i18n.DateTimeSymbols_fr_DJ = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 5,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 4
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_DZ.
    - */
    -goog.i18n.DateTimeSymbols_fr_DZ = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 5,
    -  WEEKENDRANGE: [4, 5],
    -  FIRSTWEEKCUTOFFDAY: 4
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_FR.
    - */
    -goog.i18n.DateTimeSymbols_fr_FR = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_GA.
    - */
    -goog.i18n.DateTimeSymbols_fr_GA = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_GF.
    - */
    -goog.i18n.DateTimeSymbols_fr_GF = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_GN.
    - */
    -goog.i18n.DateTimeSymbols_fr_GN = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_GP.
    - */
    -goog.i18n.DateTimeSymbols_fr_GP = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_GQ.
    - */
    -goog.i18n.DateTimeSymbols_fr_GQ = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_HT.
    - */
    -goog.i18n.DateTimeSymbols_fr_HT = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_KM.
    - */
    -goog.i18n.DateTimeSymbols_fr_KM = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_LU.
    - */
    -goog.i18n.DateTimeSymbols_fr_LU = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_MA.
    - */
    -goog.i18n.DateTimeSymbols_fr_MA = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 5,
    -  WEEKENDRANGE: [4, 5],
    -  FIRSTWEEKCUTOFFDAY: 4
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_MC.
    - */
    -goog.i18n.DateTimeSymbols_fr_MC = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_MF.
    - */
    -goog.i18n.DateTimeSymbols_fr_MF = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_MG.
    - */
    -goog.i18n.DateTimeSymbols_fr_MG = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_ML.
    - */
    -goog.i18n.DateTimeSymbols_fr_ML = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_MQ.
    - */
    -goog.i18n.DateTimeSymbols_fr_MQ = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_MR.
    - */
    -goog.i18n.DateTimeSymbols_fr_MR = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_MU.
    - */
    -goog.i18n.DateTimeSymbols_fr_MU = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_NC.
    - */
    -goog.i18n.DateTimeSymbols_fr_NC = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_NE.
    - */
    -goog.i18n.DateTimeSymbols_fr_NE = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_PF.
    - */
    -goog.i18n.DateTimeSymbols_fr_PF = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_PM.
    - */
    -goog.i18n.DateTimeSymbols_fr_PM = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_RE.
    - */
    -goog.i18n.DateTimeSymbols_fr_RE = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_RW.
    - */
    -goog.i18n.DateTimeSymbols_fr_RW = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_SC.
    - */
    -goog.i18n.DateTimeSymbols_fr_SC = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_SN.
    - */
    -goog.i18n.DateTimeSymbols_fr_SN = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_SY.
    - */
    -goog.i18n.DateTimeSymbols_fr_SY = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 5,
    -  WEEKENDRANGE: [4, 5],
    -  FIRSTWEEKCUTOFFDAY: 4
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_TD.
    - */
    -goog.i18n.DateTimeSymbols_fr_TD = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_TG.
    - */
    -goog.i18n.DateTimeSymbols_fr_TG = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_TN.
    - */
    -goog.i18n.DateTimeSymbols_fr_TN = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [4, 5],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_VU.
    - */
    -goog.i18n.DateTimeSymbols_fr_VU = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_WF.
    - */
    -goog.i18n.DateTimeSymbols_fr_WF = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fr_YT.
    - */
    -goog.i18n.DateTimeSymbols_fr_YT = {
    -  ERAS: ['av. J.-C.', 'ap. J.-C.'],
    -  ERANAMES: ['avant Jésus-Christ', 'après Jésus-Christ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
    -    'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    -  STANDALONEMONTHS: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
    -    'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
    -  SHORTMONTHS: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.',
    -    'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Févr.', 'Mars', 'Avr.', 'Mai', 'Juin',
    -    'Juil.', 'Août', 'Sept.', 'Oct.', 'Nov.', 'Déc.'],
    -  WEEKDAYS: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi',
    -    'samedi'],
    -  STANDALONEWEEKDAYS: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi',
    -    'Vendredi', 'Samedi'],
    -  SHORTWEEKDAYS: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Dim.', 'Lun.', 'Mar.', 'Mer.', 'Jeu.', 'Ven.',
    -    'Sam.'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1er trimestre', '2e trimestre', '3e trimestre', '4e trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fur.
    - */
    -goog.i18n.DateTimeSymbols_fur = {
    -  ERAS: ['pdC', 'ddC'],
    -  ERANAMES: ['pdC', 'ddC'],
    -  NARROWMONTHS: ['Z', 'F', 'M', 'A', 'M', 'J', 'L', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['Z', 'F', 'M', 'A', 'M', 'J', 'L', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Zenâr', 'Fevrâr', 'Març', 'Avrîl', 'Mai', 'Jugn', 'Lui',
    -    'Avost', 'Setembar', 'Otubar', 'Novembar', 'Dicembar'],
    -  STANDALONEMONTHS: ['Zenâr', 'Fevrâr', 'Març', 'Avrîl', 'Mai', 'Jugn',
    -    'Lui', 'Avost', 'Setembar', 'Otubar', 'Novembar', 'Dicembar'],
    -  SHORTMONTHS: ['Zen', 'Fev', 'Mar', 'Avr', 'Mai', 'Jug', 'Lui', 'Avo', 'Set',
    -    'Otu', 'Nov', 'Dic'],
    -  STANDALONESHORTMONTHS: ['Zen', 'Fev', 'Mar', 'Avr', 'Mai', 'Jug', 'Lui',
    -    'Avo', 'Set', 'Otu', 'Nov', 'Dic'],
    -  WEEKDAYS: ['domenie', 'lunis', 'martars', 'miercus', 'joibe', 'vinars',
    -    'sabide'],
    -  STANDALONEWEEKDAYS: ['domenie', 'lunis', 'martars', 'miercus', 'joibe',
    -    'vinars', 'sabide'],
    -  SHORTWEEKDAYS: ['dom', 'lun', 'mar', 'mie', 'joi', 'vin', 'sab'],
    -  STANDALONESHORTWEEKDAYS: ['dom', 'lun', 'mar', 'mie', 'joi', 'vin', 'sab'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['Prin trimestri', 'Secont trimestri', 'Tierç trimestri',
    -    'Cuart trimestri'],
    -  AMPMS: ['a.', 'p.'],
    -  DATEFORMATS: ['EEEE d \'di\' MMMM \'dal\' y', 'd \'di\' MMMM \'dal\' y',
    -    'dd/MM/y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fur_IT.
    - */
    -goog.i18n.DateTimeSymbols_fur_IT = goog.i18n.DateTimeSymbols_fur;
    -
    -
    -/**
    - * Date/time formatting symbols for locale fy.
    - */
    -goog.i18n.DateTimeSymbols_fy = {
    -  ERAS: ['f.Kr.', 'n.Kr.'],
    -  ERANAMES: ['Foar Kristus', 'nei Kristus'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['jannewaris', 'febrewaris', 'maart', 'april', 'maaie', 'juny',
    -    'july', 'augustus', 'septimber', 'oktober', 'novimber', 'desimber'],
    -  STANDALONEMONTHS: ['jannewaris', 'febrewaris', 'maart', 'april', 'maaie',
    -    'juny', 'july', 'augustus', 'septimber', 'oktober', 'novimber', 'desimber'],
    -  SHORTMONTHS: ['jan.', 'feb.', 'mrt.', 'apr.', 'mai', 'jun.', 'jul.', 'aug.',
    -    'sep.', 'okt.', 'nov.', 'des.'],
    -  STANDALONESHORTMONTHS: ['jan', 'feb', 'mrt', 'apr', 'mai', 'jun', 'jul',
    -    'aug', 'sep', 'okt', 'nov', 'des'],
    -  WEEKDAYS: ['snein', 'moandei', 'tiisdei', 'woansdei', 'tongersdei', 'freed',
    -    'sneon'],
    -  STANDALONEWEEKDAYS: ['snein', 'moandei', 'tiisdei', 'woansdei', 'tongersdei',
    -    'freed', 'sneon'],
    -  SHORTWEEKDAYS: ['si', 'mo', 'ti', 'wo', 'to', 'fr', 'so'],
    -  STANDALONESHORTWEEKDAYS: ['si', 'mo', 'ti', 'wo', 'to', 'fr', 'so'],
    -  NARROWWEEKDAYS: ['Z', 'M', 'D', 'W', 'D', 'V', 'Z'],
    -  STANDALONENARROWWEEKDAYS: ['Z', 'M', 'D', 'W', 'D', 'V', 'Z'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['1e kwartaal', '2e kwartaal', '3e kwartaal', '4e kwartaal'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd-MM-yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale fy_NL.
    - */
    -goog.i18n.DateTimeSymbols_fy_NL = goog.i18n.DateTimeSymbols_fy;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ga_IE.
    - */
    -goog.i18n.DateTimeSymbols_ga_IE = {
    -  ERAS: ['RC', 'AD'],
    -  ERANAMES: ['Roimh Chríost', 'Anno Domini'],
    -  NARROWMONTHS: ['E', 'F', 'M', 'A', 'B', 'M', 'I', 'L', 'M', 'D', 'S', 'N'],
    -  STANDALONENARROWMONTHS: ['E', 'F', 'M', 'A', 'B', 'M', 'I', 'L', 'M', 'D',
    -    'S', 'N'],
    -  MONTHS: ['Eanáir', 'Feabhra', 'Márta', 'Aibreán', 'Bealtaine', 'Meitheamh',
    -    'Iúil', 'Lúnasa', 'Meán Fómhair', 'Deireadh Fómhair', 'Samhain',
    -    'Nollaig'],
    -  STANDALONEMONTHS: ['Eanáir', 'Feabhra', 'Márta', 'Aibreán', 'Bealtaine',
    -    'Meitheamh', 'Iúil', 'Lúnasa', 'Meán Fómhair', 'Deireadh Fómhair',
    -    'Samhain', 'Nollaig'],
    -  SHORTMONTHS: ['Ean', 'Feabh', 'Márta', 'Aib', 'Beal', 'Meith', 'Iúil',
    -    'Lún', 'MFómh', 'DFómh', 'Samh', 'Noll'],
    -  STANDALONESHORTMONTHS: ['Ean', 'Feabh', 'Márta', 'Aib', 'Beal', 'Meith',
    -    'Iúil', 'Lún', 'MFómh', 'DFómh', 'Samh', 'Noll'],
    -  WEEKDAYS: ['Dé Domhnaigh', 'Dé Luain', 'Dé Máirt', 'Dé Céadaoin',
    -    'Déardaoin', 'Dé hAoine', 'Dé Sathairn'],
    -  STANDALONEWEEKDAYS: ['Dé Domhnaigh', 'Dé Luain', 'Dé Máirt',
    -    'Dé Céadaoin', 'Déardaoin', 'Dé hAoine', 'Dé Sathairn'],
    -  SHORTWEEKDAYS: ['Domh', 'Luan', 'Máirt', 'Céad', 'Déar', 'Aoine', 'Sath'],
    -  STANDALONESHORTWEEKDAYS: ['Domh', 'Luan', 'Máirt', 'Céad', 'Déar', 'Aoine',
    -    'Sath'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'C', 'D', 'A', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'C', 'D', 'A', 'S'],
    -  SHORTQUARTERS: ['R1', 'R2', 'R3', 'R4'],
    -  QUARTERS: ['1ú ráithe', '2ú ráithe', '3ú ráithe', '4ú ráithe'],
    -  AMPMS: ['a.m.', 'p.m.'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 2
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale gd.
    - */
    -goog.i18n.DateTimeSymbols_gd = {
    -  ERAS: ['RC', 'AD'],
    -  ERANAMES: ['Ro Chrìosta', 'An dèidh Chrìosta'],
    -  NARROWMONTHS: ['F', 'G', 'M', 'G', 'C', 'Ò', 'I', 'L', 'S', 'D', 'S', 'D'],
    -  STANDALONENARROWMONTHS: ['F', 'G', 'M', 'G', 'C', 'Ò', 'I', 'L', 'S', 'D',
    -    'S', 'D'],
    -  MONTHS: ['dhen Fhaoilleach', 'dhen Ghearran', 'dhen Mhàrt', 'dhen Ghiblean',
    -    'dhen Chèitean', 'dhen Ògmhios', 'dhen Iuchar', 'dhen Lùnastal',
    -    'dhen t-Sultain', 'dhen Dàmhair', 'dhen t-Samhain', 'dhen Dùbhlachd'],
    -  STANDALONEMONTHS: ['Am Faoilleach', 'An Gearran', 'Am Màrt', 'An Giblean',
    -    'An Cèitean', 'An t-Ògmhios', 'An t-Iuchar', 'An Lùnastal',
    -    'An t-Sultain', 'An Dàmhair', 'An t-Samhain', 'An Dùbhlachd'],
    -  SHORTMONTHS: ['Faoi', 'Gearr', 'Màrt', 'Gibl', 'Cèit', 'Ògmh', 'Iuch',
    -    'Lùna', 'Sult', 'Dàmh', 'Samh', 'Dùbh'],
    -  STANDALONESHORTMONTHS: ['Faoi', 'Gearr', 'Màrt', 'Gibl', 'Cèit', 'Ògmh',
    -    'Iuch', 'Lùna', 'Sult', 'Dàmh', 'Samh', 'Dùbh'],
    -  WEEKDAYS: ['DiDòmhnaich', 'DiLuain', 'DiMàirt', 'DiCiadain', 'DiarDaoin',
    -    'DihAoine', 'DiSathairne'],
    -  STANDALONEWEEKDAYS: ['DiDòmhnaich', 'DiLuain', 'DiMàirt', 'DiCiadain',
    -    'DiarDaoin', 'DihAoine', 'DiSathairne'],
    -  SHORTWEEKDAYS: ['DiD', 'DiL', 'DiM', 'DiC', 'Dia', 'Dih', 'DiS'],
    -  STANDALONESHORTWEEKDAYS: ['DiD', 'DiL', 'DiM', 'DiC', 'Dia', 'Dih', 'DiS'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'C', 'A', 'H', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'C', 'A', 'H', 'S'],
    -  SHORTQUARTERS: ['C1', 'C2', 'C3', 'C4'],
    -  QUARTERS: ['1d chairteal', '2na cairteal', '3s cairteal', '4mh cairteal'],
    -  AMPMS: ['m', 'f'],
    -  DATEFORMATS: ['EEEE, d\'mh\' MMMM y', 'd\'mh\' MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale gd_GB.
    - */
    -goog.i18n.DateTimeSymbols_gd_GB = goog.i18n.DateTimeSymbols_gd;
    -
    -
    -/**
    - * Date/time formatting symbols for locale gl_ES.
    - */
    -goog.i18n.DateTimeSymbols_gl_ES = {
    -  ERAS: ['a.C.', 'd.C.'],
    -  ERANAMES: ['antes de Cristo', 'despois de Cristo'],
    -  NARROWMONTHS: ['X', 'F', 'M', 'A', 'M', 'X', 'X', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['X', 'F', 'M', 'A', 'M', 'X', 'X', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['xaneiro', 'febreiro', 'marzo', 'abril', 'maio', 'xuño', 'xullo',
    -    'agosto', 'setembro', 'outubro', 'novembro', 'decembro'],
    -  STANDALONEMONTHS: ['Xaneiro', 'Febreiro', 'Marzo', 'Abril', 'Maio', 'Xuño',
    -    'Xullo', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Decembro'],
    -  SHORTMONTHS: ['xan', 'feb', 'mar', 'abr', 'mai', 'xuñ', 'xul', 'ago', 'set',
    -    'out', 'nov', 'dec'],
    -  STANDALONESHORTMONTHS: ['Xan', 'Feb', 'Mar', 'Abr', 'Mai', 'Xuñ', 'Xul',
    -    'Ago', 'Set', 'Out', 'Nov', 'Dec'],
    -  WEEKDAYS: ['domingo', 'luns', 'martes', 'mércores', 'xoves', 'venres',
    -    'sábado'],
    -  STANDALONEWEEKDAYS: ['Domingo', 'Luns', 'Martes', 'Mércores', 'Xoves',
    -    'Venres', 'Sábado'],
    -  SHORTWEEKDAYS: ['dom', 'lun', 'mar', 'mér', 'xov', 'ven', 'sáb'],
    -  STANDALONESHORTWEEKDAYS: ['Dom', 'Lun', 'Mar', 'Mér', 'Xov', 'Ven', 'Sáb'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'X', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'X', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1o trimestre', '2o trimestre', '3o trimestre', '4o trimestre'],
    -  AMPMS: ['a.m.', 'p.m.'],
    -  DATEFORMATS: ['EEEE dd MMMM y', 'dd MMMM y', 'd MMM, y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale gsw_CH.
    - */
    -goog.i18n.DateTimeSymbols_gsw_CH = {
    -  ERAS: ['v. Chr.', 'n. Chr.'],
    -  ERANAMES: ['v. Chr.', 'n. Chr.'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli',
    -    'Auguscht', 'Septämber', 'Oktoober', 'Novämber', 'Dezämber'],
    -  STANDALONEMONTHS: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni',
    -    'Juli', 'Auguscht', 'Septämber', 'Oktoober', 'Novämber', 'Dezämber'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Okt', 'Nov', 'Dez'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
    -  WEEKDAYS: ['Sunntig', 'Määntig', 'Ziischtig', 'Mittwuch', 'Dunschtig',
    -    'Friitig', 'Samschtig'],
    -  STANDALONEWEEKDAYS: ['Sunntig', 'Määntig', 'Ziischtig', 'Mittwuch',
    -    'Dunschtig', 'Friitig', 'Samschtig'],
    -  SHORTWEEKDAYS: ['Su.', 'Mä.', 'Zi.', 'Mi.', 'Du.', 'Fr.', 'Sa.'],
    -  STANDALONESHORTWEEKDAYS: ['Su.', 'Mä.', 'Zi.', 'Mi.', 'Du.', 'Fr.', 'Sa.'],
    -  NARROWWEEKDAYS: ['S', 'M', 'D', 'M', 'D', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'D', 'M', 'D', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1. Quartal', '2. Quartal', '3. Quartal', '4. Quartal'],
    -  AMPMS: ['vorm.', 'nam.'],
    -  DATEFORMATS: ['EEEE, d. MMMM y', 'd. MMMM y', 'dd.MM.y', 'dd.MM.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale gsw_FR.
    - */
    -goog.i18n.DateTimeSymbols_gsw_FR = {
    -  ERAS: ['v. Chr.', 'n. Chr.'],
    -  ERANAMES: ['v. Chr.', 'n. Chr.'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli',
    -    'Auguscht', 'Septämber', 'Oktoober', 'Novämber', 'Dezämber'],
    -  STANDALONEMONTHS: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni',
    -    'Juli', 'Auguscht', 'Septämber', 'Oktoober', 'Novämber', 'Dezämber'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Okt', 'Nov', 'Dez'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
    -  WEEKDAYS: ['Sunntig', 'Määntig', 'Ziischtig', 'Mittwuch', 'Dunschtig',
    -    'Friitig', 'Samschtig'],
    -  STANDALONEWEEKDAYS: ['Sunntig', 'Määntig', 'Ziischtig', 'Mittwuch',
    -    'Dunschtig', 'Friitig', 'Samschtig'],
    -  SHORTWEEKDAYS: ['Su.', 'Mä.', 'Zi.', 'Mi.', 'Du.', 'Fr.', 'Sa.'],
    -  STANDALONESHORTWEEKDAYS: ['Su.', 'Mä.', 'Zi.', 'Mi.', 'Du.', 'Fr.', 'Sa.'],
    -  NARROWWEEKDAYS: ['S', 'M', 'D', 'M', 'D', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'D', 'M', 'D', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1. Quartal', '2. Quartal', '3. Quartal', '4. Quartal'],
    -  AMPMS: ['vorm.', 'nam.'],
    -  DATEFORMATS: ['EEEE, d. MMMM y', 'd. MMMM y', 'dd.MM.y', 'dd.MM.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale gsw_LI.
    - */
    -goog.i18n.DateTimeSymbols_gsw_LI = {
    -  ERAS: ['v. Chr.', 'n. Chr.'],
    -  ERANAMES: ['v. Chr.', 'n. Chr.'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli',
    -    'Auguscht', 'Septämber', 'Oktoober', 'Novämber', 'Dezämber'],
    -  STANDALONEMONTHS: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni',
    -    'Juli', 'Auguscht', 'Septämber', 'Oktoober', 'Novämber', 'Dezämber'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Okt', 'Nov', 'Dez'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
    -  WEEKDAYS: ['Sunntig', 'Määntig', 'Ziischtig', 'Mittwuch', 'Dunschtig',
    -    'Friitig', 'Samschtig'],
    -  STANDALONEWEEKDAYS: ['Sunntig', 'Määntig', 'Ziischtig', 'Mittwuch',
    -    'Dunschtig', 'Friitig', 'Samschtig'],
    -  SHORTWEEKDAYS: ['Su.', 'Mä.', 'Zi.', 'Mi.', 'Du.', 'Fr.', 'Sa.'],
    -  STANDALONESHORTWEEKDAYS: ['Su.', 'Mä.', 'Zi.', 'Mi.', 'Du.', 'Fr.', 'Sa.'],
    -  NARROWWEEKDAYS: ['S', 'M', 'D', 'M', 'D', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'D', 'M', 'D', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1. Quartal', '2. Quartal', '3. Quartal', '4. Quartal'],
    -  AMPMS: ['vorm.', 'nam.'],
    -  DATEFORMATS: ['EEEE, d. MMMM y', 'd. MMMM y', 'dd.MM.y', 'dd.MM.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale gu_IN.
    - */
    -goog.i18n.DateTimeSymbols_gu_IN = {
    -  ERAS: ['ઈસુના જન્મ પહેલા', 'ઇસવીસન'],
    -  ERANAMES: ['ઈસવીસન પૂર્વે', 'ઇસવીસન'],
    -  NARROWMONTHS: ['જા', 'ફે', 'મા', 'એ', 'મે', 'જૂ',
    -    'જુ', 'ઑ', 'સ', 'ઑ', 'ન', 'ડિ'],
    -  STANDALONENARROWMONTHS: ['જા', 'ફે', 'મા', 'એ', 'મે',
    -    'જૂ', 'જુ', 'ઑ', 'સ', 'ઑ', 'ન', 'ડિ'],
    -  MONTHS: ['જાન્યુઆરી', 'ફેબ્રુઆરી',
    -    'માર્ચ', 'એપ્રિલ', 'મે', 'જૂન',
    -    'જુલાઈ', 'ઑગસ્ટ', 'સપ્ટેમ્બર',
    -    'ઑક્ટોબર', 'નવેમ્બર',
    -    'ડિસેમ્બર'],
    -  STANDALONEMONTHS: ['જાન્યુઆરી',
    -    'ફેબ્રુઆરી', 'માર્ચ', 'એપ્રિલ',
    -    'મે', 'જૂન', 'જુલાઈ', 'ઑગસ્ટ',
    -    'સપ્ટેમ્બર', 'ઑક્ટોબર',
    -    'નવેમ્બર', 'ડિસેમ્બર'],
    -  SHORTMONTHS: ['જાન્યુ', 'ફેબ્રુ', 'માર્ચ',
    -    'એપ્રિલ', 'મે', 'જૂન', 'જુલાઈ', 'ઑગ',
    -    'સપ્ટે', 'ઑક્ટો', 'નવે', 'ડિસે'],
    -  STANDALONESHORTMONTHS: ['જાન્યુ', 'ફેબ્રુ',
    -    'માર્ચ', 'એપ્રિલ', 'મે', 'જૂન',
    -    'જુલાઈ', 'ઑગસ્ટ', 'સપ્ટે', 'ઑક્ટો',
    -    'નવે', 'ડિસે'],
    -  WEEKDAYS: ['રવિવાર', 'સોમવાર',
    -    'મંગળવાર', 'બુધવાર', 'ગુરુવાર',
    -    'શુક્રવાર', 'શનિવાર'],
    -  STANDALONEWEEKDAYS: ['રવિવાર', 'સોમવાર',
    -    'મંગળવાર', 'બુધવાર', 'ગુરુવાર',
    -    'શુક્રવાર', 'શનિવાર'],
    -  SHORTWEEKDAYS: ['રવિ', 'સોમ', 'મંગળ', 'બુધ',
    -    'ગુરુ', 'શુક્ર', 'શનિ'],
    -  STANDALONESHORTWEEKDAYS: ['રવિ', 'સોમ', 'મંગળ',
    -    'બુધ', 'ગુરુ', 'શુક્ર', 'શનિ'],
    -  NARROWWEEKDAYS: ['ર', 'સો', 'મં', 'બુ', 'ગુ', 'શુ',
    -    'શ'],
    -  STANDALONENARROWWEEKDAYS: ['ર', 'સો', 'મં', 'બુ', 'ગુ',
    -    'શુ', 'શ'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['પહેલો ત્રિમાસ',
    -    'બીજો ત્રિમાસ',
    -    'ત્રીજો ત્રિમાસ',
    -    'ચોથો ત્રિમાસ'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM, y', 'd MMMM, y', 'd MMM, y', 'd/M/yy'],
    -  TIMEFORMATS: ['hh:mm:ss a zzzz', 'hh:mm:ss a z', 'hh:mm:ss a', 'hh:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [6, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale guz.
    - */
    -goog.i18n.DateTimeSymbols_guz = {
    -  ERAS: ['YA', 'YK'],
    -  ERANAMES: ['Yeso ataiborwa', 'Yeso kaiboirwe'],
    -  NARROWMONTHS: ['C', 'F', 'M', 'A', 'M', 'J', 'C', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['C', 'F', 'M', 'A', 'M', 'J', 'C', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Chanuari', 'Feburari', 'Machi', 'Apiriri', 'Mei', 'Juni', 'Chulai',
    -    'Agosti', 'Septemba', 'Okitoba', 'Nobemba', 'Disemba'],
    -  STANDALONEMONTHS: ['Chanuari', 'Feburari', 'Machi', 'Apiriri', 'Mei', 'Juni',
    -    'Chulai', 'Agosti', 'Septemba', 'Okitoba', 'Nobemba', 'Disemba'],
    -  SHORTMONTHS: ['Can', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Cul', 'Agt', 'Sep',
    -    'Okt', 'Nob', 'Dis'],
    -  STANDALONESHORTMONTHS: ['Can', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Cul',
    -    'Agt', 'Sep', 'Okt', 'Nob', 'Dis'],
    -  WEEKDAYS: ['Chumapiri', 'Chumatato', 'Chumaine', 'Chumatano', 'Aramisi',
    -    'Ichuma', 'Esabato'],
    -  STANDALONEWEEKDAYS: ['Chumapiri', 'Chumatato', 'Chumaine', 'Chumatano',
    -    'Aramisi', 'Ichuma', 'Esabato'],
    -  SHORTWEEKDAYS: ['Cpr', 'Ctt', 'Cmn', 'Cmt', 'Ars', 'Icm', 'Est'],
    -  STANDALONESHORTWEEKDAYS: ['Cpr', 'Ctt', 'Cmn', 'Cmt', 'Ars', 'Icm', 'Est'],
    -  NARROWWEEKDAYS: ['C', 'C', 'C', 'C', 'A', 'I', 'E'],
    -  STANDALONENARROWWEEKDAYS: ['C', 'C', 'C', 'C', 'A', 'I', 'E'],
    -  SHORTQUARTERS: ['E1', 'E2', 'E3', 'E4'],
    -  QUARTERS: ['Erobo entang’ani', 'Erobo yakabere', 'Erobo yagatato',
    -    'Erobo yakane'],
    -  AMPMS: ['Ma/Mo', 'Mambia/Mog'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale guz_KE.
    - */
    -goog.i18n.DateTimeSymbols_guz_KE = goog.i18n.DateTimeSymbols_guz;
    -
    -
    -/**
    - * Date/time formatting symbols for locale gv.
    - */
    -goog.i18n.DateTimeSymbols_gv = {
    -  ERAS: ['RC', 'AD'],
    -  ERANAMES: ['RC', 'AD'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['Jerrey-geuree', 'Toshiaght-arree', 'Mayrnt', 'Averil', 'Boaldyn',
    -    'Mean-souree', 'Jerrey-souree', 'Luanistyn', 'Mean-fouyir', 'Jerrey-fouyir',
    -    'Mee Houney', 'Mee ny Nollick'],
    -  STANDALONEMONTHS: ['Jerrey-geuree', 'Toshiaght-arree', 'Mayrnt', 'Averil',
    -    'Boaldyn', 'Mean-souree', 'Jerrey-souree', 'Luanistyn', 'Mean-fouyir',
    -    'Jerrey-fouyir', 'Mee Houney', 'Mee ny Nollick'],
    -  SHORTMONTHS: ['J-guer', 'T-arree', 'Mayrnt', 'Avrril', 'Boaldyn', 'M-souree',
    -    'J-souree', 'Luanistyn', 'M-fouyir', 'J-fouyir', 'M.Houney', 'M.Nollick'],
    -  STANDALONESHORTMONTHS: ['J-guer', 'T-arree', 'Mayrnt', 'Avrril', 'Boaldyn',
    -    'M-souree', 'J-souree', 'Luanistyn', 'M-fouyir', 'J-fouyir', 'M.Houney',
    -    'M.Nollick'],
    -  WEEKDAYS: ['Jedoonee', 'Jelhein', 'Jemayrt', 'Jercean', 'Jerdein', 'Jeheiney',
    -    'Jesarn'],
    -  STANDALONEWEEKDAYS: ['Jedoonee', 'Jelhein', 'Jemayrt', 'Jercean', 'Jerdein',
    -    'Jeheiney', 'Jesarn'],
    -  SHORTWEEKDAYS: ['Jed', 'Jel', 'Jem', 'Jerc', 'Jerd', 'Jeh', 'Jes'],
    -  STANDALONESHORTWEEKDAYS: ['Jed', 'Jel', 'Jem', 'Jerc', 'Jerd', 'Jeh', 'Jes'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['a.m.', 'p.m.'],
    -  DATEFORMATS: ['EEEE dd MMMM y', 'dd MMMM y', 'MMM dd, y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale gv_IM.
    - */
    -goog.i18n.DateTimeSymbols_gv_IM = goog.i18n.DateTimeSymbols_gv;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ha.
    - */
    -goog.i18n.DateTimeSymbols_ha = {
    -  ERAS: ['KHAI', 'BHAI'],
    -  ERANAMES: ['Kafin haihuwar annab', 'Bayan haihuwar annab'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'Y', 'Y', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'Y', 'Y', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Janairu', 'Faburairu', 'Maris', 'Afirilu', 'Mayu', 'Yuni', 'Yuli',
    -    'Agusta', 'Satumba', 'Oktoba', 'Nuwamba', 'Disamba'],
    -  STANDALONEMONTHS: ['Janairu', 'Faburairu', 'Maris', 'Afirilu', 'Mayu', 'Yuni',
    -    'Yuli', 'Agusta', 'Satumba', 'Oktoba', 'Nuwamba', 'Disamba'],
    -  SHORTMONTHS: ['Jan', 'Fab', 'Mar', 'Afi', 'May', 'Yun', 'Yul', 'Agu', 'Sat',
    -    'Okt', 'Nuw', 'Dis'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Fab', 'Mar', 'Afi', 'May', 'Yun', 'Yul',
    -    'Agu', 'Sat', 'Okt', 'Nuw', 'Dis'],
    -  WEEKDAYS: ['Lahadi', 'Litinin', 'Talata', 'Laraba', 'Alhamis', 'Jummaʼa',
    -    'Asabar'],
    -  STANDALONEWEEKDAYS: ['Lahadi', 'Litinin', 'Talata', 'Laraba', 'Alhamis',
    -    'Jummaʼa', 'Asabar'],
    -  SHORTWEEKDAYS: ['Lh', 'Li', 'Ta', 'Lr', 'Al', 'Ju', 'As'],
    -  STANDALONESHORTWEEKDAYS: ['Lh', 'Li', 'Ta', 'Lr', 'Al', 'Ju', 'As'],
    -  NARROWWEEKDAYS: ['L', 'L', 'T', 'L', 'A', 'J', 'A'],
    -  STANDALONENARROWWEEKDAYS: ['L', 'L', 'T', 'L', 'A', 'J', 'A'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['Kwata na ɗaya', 'Kwata na biyu', 'Kwata na uku',
    -    'Kwata na huɗu'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM, y', 'd MMMM, y', 'd MMM, y', 'd/M/yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ha_Latn.
    - */
    -goog.i18n.DateTimeSymbols_ha_Latn = goog.i18n.DateTimeSymbols_ha;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ha_Latn_GH.
    - */
    -goog.i18n.DateTimeSymbols_ha_Latn_GH = goog.i18n.DateTimeSymbols_ha;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ha_Latn_NE.
    - */
    -goog.i18n.DateTimeSymbols_ha_Latn_NE = goog.i18n.DateTimeSymbols_ha;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ha_Latn_NG.
    - */
    -goog.i18n.DateTimeSymbols_ha_Latn_NG = goog.i18n.DateTimeSymbols_ha;
    -
    -
    -/**
    - * Date/time formatting symbols for locale haw_US.
    - */
    -goog.i18n.DateTimeSymbols_haw_US = {
    -  ERAS: ['BCE', 'CE'],
    -  ERANAMES: ['BCE', 'CE'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['Ianuali', 'Pepeluali', 'Malaki', 'ʻApelila', 'Mei', 'Iune',
    -    'Iulai', 'ʻAukake', 'Kepakemapa', 'ʻOkakopa', 'Nowemapa', 'Kekemapa'],
    -  STANDALONEMONTHS: ['Ianuali', 'Pepeluali', 'Malaki', 'ʻApelila', 'Mei',
    -    'Iune', 'Iulai', 'ʻAukake', 'Kepakemapa', 'ʻOkakopa', 'Nowemapa',
    -    'Kekemapa'],
    -  SHORTMONTHS: ['Ian.', 'Pep.', 'Mal.', 'ʻAp.', 'Mei', 'Iun.', 'Iul.', 'ʻAu.',
    -    'Kep.', 'ʻOk.', 'Now.', 'Kek.'],
    -  STANDALONESHORTMONTHS: ['Ian.', 'Pep.', 'Mal.', 'ʻAp.', 'Mei', 'Iun.',
    -    'Iul.', 'ʻAu.', 'Kep.', 'ʻOk.', 'Now.', 'Kek.'],
    -  WEEKDAYS: ['Lāpule', 'Poʻakahi', 'Poʻalua', 'Poʻakolu', 'Poʻahā',
    -    'Poʻalima', 'Poʻaono'],
    -  STANDALONEWEEKDAYS: ['Lāpule', 'Poʻakahi', 'Poʻalua', 'Poʻakolu',
    -    'Poʻahā', 'Poʻalima', 'Poʻaono'],
    -  SHORTWEEKDAYS: ['LP', 'P1', 'P2', 'P3', 'P4', 'P5', 'P6'],
    -  STANDALONESHORTWEEKDAYS: ['LP', 'P1', 'P2', 'P3', 'P4', 'P5', 'P6'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale he_IL.
    - */
    -goog.i18n.DateTimeSymbols_he_IL = {
    -  ERAS: ['לפנה״ס', 'לספירה'],
    -  ERANAMES: ['לפני הספירה', 'לספירה'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['ינואר', 'פברואר', 'מרץ', 'אפריל', 'מאי',
    -    'יוני', 'יולי', 'אוגוסט', 'ספטמבר', 'אוקטובר',
    -    'נובמבר', 'דצמבר'],
    -  STANDALONEMONTHS: ['ינואר', 'פברואר', 'מרץ', 'אפריל',
    -    'מאי', 'יוני', 'יולי', 'אוגוסט', 'ספטמבר',
    -    'אוקטובר', 'נובמבר', 'דצמבר'],
    -  SHORTMONTHS: ['ינו׳', 'פבר׳', 'מרץ', 'אפר׳', 'מאי',
    -    'יוני', 'יולי', 'אוג׳', 'ספט׳', 'אוק׳', 'נוב׳',
    -    'דצמ׳'],
    -  STANDALONESHORTMONTHS: ['ינו׳', 'פבר׳', 'מרץ', 'אפר׳',
    -    'מאי', 'יוני', 'יולי', 'אוג׳', 'ספט׳', 'אוק׳',
    -    'נוב׳', 'דצמ׳'],
    -  WEEKDAYS: ['יום ראשון', 'יום שני', 'יום שלישי',
    -    'יום רביעי', 'יום חמישי', 'יום שישי',
    -    'יום שבת'],
    -  STANDALONEWEEKDAYS: ['יום ראשון', 'יום שני',
    -    'יום שלישי', 'יום רביעי', 'יום חמישי',
    -    'יום שישי', 'יום שבת'],
    -  SHORTWEEKDAYS: ['יום א׳', 'יום ב׳', 'יום ג׳', 'יום ד׳',
    -    'יום ה׳', 'יום ו׳', 'שבת'],
    -  STANDALONESHORTWEEKDAYS: ['יום א׳', 'יום ב׳', 'יום ג׳',
    -    'יום ד׳', 'יום ה׳', 'יום ו׳', 'שבת'],
    -  NARROWWEEKDAYS: ['א׳', 'ב׳', 'ג׳', 'ד׳', 'ה׳', 'ו׳', 'ש׳'],
    -  STANDALONENARROWWEEKDAYS: ['א׳', 'ב׳', 'ג׳', 'ד׳', 'ה׳', 'ו׳',
    -    'ש׳'],
    -  SHORTQUARTERS: ['רבעון 1', 'רבעון 2', 'רבעון 3',
    -    'רבעון 4'],
    -  QUARTERS: ['רבעון 1', 'רבעון 2', 'רבעון 3', 'רבעון 4'],
    -  AMPMS: ['לפנה״צ', 'אחה״צ'],
    -  DATEFORMATS: ['EEEE, d בMMMM y', 'd בMMMM y', 'd בMMM y', 'd.M.y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} בשעה {0}', '{1} בשעה {0}', '{1}, {0}',
    -    '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [4, 5],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale hi_IN.
    - */
    -goog.i18n.DateTimeSymbols_hi_IN = {
    -  ERAS: ['ईसा-पूर्व', 'ईस्वी'],
    -  ERANAMES: ['ईसा-पूर्व', 'ईसवी सन'],
    -  NARROWMONTHS: ['ज', 'फ़', 'मा', 'अ', 'म', 'जू', 'जु',
    -    'अ', 'सि', 'अ', 'न', 'दि'],
    -  STANDALONENARROWMONTHS: ['ज', 'फ़', 'मा', 'अ', 'म', 'जू',
    -    'जु', 'अ', 'सि', 'अ', 'न', 'दि'],
    -  MONTHS: ['जनवरी', 'फ़रवरी', 'मार्च',
    -    'अप्रैल', 'मई', 'जून', 'जुलाई',
    -    'अगस्त', 'सितंबर', 'अक्तूबर',
    -    'नवंबर', 'दिसंबर'],
    -  STANDALONEMONTHS: ['जनवरी', 'फ़रवरी', 'मार्च',
    -    'अप्रैल', 'मई', 'जून', 'जुलाई',
    -    'अगस्त', 'सितंबर', 'अक्तूबर',
    -    'नवंबर', 'दिसंबर'],
    -  SHORTMONTHS: ['जन॰', 'फ़र॰', 'मार्च',
    -    'अप्रैल', 'मई', 'जून', 'जुल॰', 'अग॰',
    -    'सित॰', 'अक्तू॰', 'नव॰', 'दिस॰'],
    -  STANDALONESHORTMONTHS: ['जन॰', 'फ़र॰', 'मार्च',
    -    'अप्रैल', 'मई', 'जून', 'जुल॰', 'अग॰',
    -    'सित॰', 'अक्तू॰', 'नव॰', 'दिस॰'],
    -  WEEKDAYS: ['रविवार', 'सोमवार',
    -    'मंगलवार', 'बुधवार', 'गुरुवार',
    -    'शुक्रवार', 'शनिवार'],
    -  STANDALONEWEEKDAYS: ['रविवार', 'सोमवार',
    -    'मंगलवार', 'बुधवार', 'गुरुवार',
    -    'शुक्रवार', 'शनिवार'],
    -  SHORTWEEKDAYS: ['रवि', 'सोम', 'मंगल', 'बुध',
    -    'गुरु', 'शुक्र', 'शनि'],
    -  STANDALONESHORTWEEKDAYS: ['रवि', 'सोम', 'मंगल',
    -    'बुध', 'गुरु', 'शुक्र', 'शनि'],
    -  NARROWWEEKDAYS: ['र', 'सो', 'मं', 'बु', 'गु', 'शु',
    -    'श'],
    -  STANDALONENARROWWEEKDAYS: ['र', 'सो', 'मं', 'बु', 'गु',
    -    'शु', 'श'],
    -  SHORTQUARTERS: ['ति1', 'ति2', 'ति3', 'ति4'],
    -  QUARTERS: ['पहली तिमाही',
    -    'दूसरी तिमाही', 'तीसरी तिमाही',
    -    'चौथी तिमाही'],
    -  AMPMS: ['am', 'pm'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'dd/MM/y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} को {0}', '{1} को {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [6, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale hr_BA.
    - */
    -goog.i18n.DateTimeSymbols_hr_BA = {
    -  ERAS: ['pr. Kr.', 'p. Kr.'],
    -  ERANAMES: ['Prije Krista', 'Poslije Krista'],
    -  NARROWMONTHS: ['1.', '2.', '3.', '4.', '5.', '6.', '7.', '8.', '9.', '10.',
    -    '11.', '12.'],
    -  STANDALONENARROWMONTHS: ['1.', '2.', '3.', '4.', '5.', '6.', '7.', '8.', '9.',
    -    '10.', '11.', '12.'],
    -  MONTHS: ['siječnja', 'veljače', 'ožujka', 'travnja', 'svibnja', 'lipnja',
    -    'srpnja', 'kolovoza', 'rujna', 'listopada', 'studenoga', 'prosinca'],
    -  STANDALONEMONTHS: ['siječanj', 'veljača', 'ožujak', 'travanj', 'svibanj',
    -    'lipanj', 'srpanj', 'kolovoz', 'rujan', 'listopad', 'studeni', 'prosinac'],
    -  SHORTMONTHS: ['sij', 'velj', 'ožu', 'tra', 'svi', 'lip', 'srp', 'kol', 'ruj',
    -    'lis', 'stu', 'pro'],
    -  STANDALONESHORTMONTHS: ['sij', 'velj', 'ožu', 'tra', 'svi', 'lip', 'srp',
    -    'kol', 'ruj', 'lis', 'stu', 'pro'],
    -  WEEKDAYS: ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda', 'četvrtak',
    -    'petak', 'subota'],
    -  STANDALONEWEEKDAYS: ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda',
    -    'četvrtak', 'petak', 'subota'],
    -  SHORTWEEKDAYS: ['ned', 'pon', 'uto', 'sri', 'čet', 'pet', 'sub'],
    -  STANDALONESHORTWEEKDAYS: ['ned', 'pon', 'uto', 'sri', 'čet', 'pet', 'sub'],
    -  NARROWWEEKDAYS: ['N', 'P', 'U', 'S', 'Č', 'P', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['n', 'p', 'u', 's', 'č', 'p', 's'],
    -  SHORTQUARTERS: ['1kv', '2kv', '3kv', '4kv'],
    -  QUARTERS: ['1. kvartal', '2. kvartal', '3. kvartal', '4. kvartal'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d. MMMM y.', 'd. MMMM y.', 'd. MMM y.', 'dd.MM.y.'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'u\' {0}', '{1} \'u\' {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale hr_HR.
    - */
    -goog.i18n.DateTimeSymbols_hr_HR = {
    -  ERAS: ['pr. Kr.', 'p. Kr.'],
    -  ERANAMES: ['Prije Krista', 'Poslije Krista'],
    -  NARROWMONTHS: ['1.', '2.', '3.', '4.', '5.', '6.', '7.', '8.', '9.', '10.',
    -    '11.', '12.'],
    -  STANDALONENARROWMONTHS: ['1.', '2.', '3.', '4.', '5.', '6.', '7.', '8.', '9.',
    -    '10.', '11.', '12.'],
    -  MONTHS: ['siječnja', 'veljače', 'ožujka', 'travnja', 'svibnja', 'lipnja',
    -    'srpnja', 'kolovoza', 'rujna', 'listopada', 'studenoga', 'prosinca'],
    -  STANDALONEMONTHS: ['siječanj', 'veljača', 'ožujak', 'travanj', 'svibanj',
    -    'lipanj', 'srpanj', 'kolovoz', 'rujan', 'listopad', 'studeni', 'prosinac'],
    -  SHORTMONTHS: ['sij', 'velj', 'ožu', 'tra', 'svi', 'lip', 'srp', 'kol', 'ruj',
    -    'lis', 'stu', 'pro'],
    -  STANDALONESHORTMONTHS: ['sij', 'velj', 'ožu', 'tra', 'svi', 'lip', 'srp',
    -    'kol', 'ruj', 'lis', 'stu', 'pro'],
    -  WEEKDAYS: ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda', 'četvrtak',
    -    'petak', 'subota'],
    -  STANDALONEWEEKDAYS: ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda',
    -    'četvrtak', 'petak', 'subota'],
    -  SHORTWEEKDAYS: ['ned', 'pon', 'uto', 'sri', 'čet', 'pet', 'sub'],
    -  STANDALONESHORTWEEKDAYS: ['ned', 'pon', 'uto', 'sri', 'čet', 'pet', 'sub'],
    -  NARROWWEEKDAYS: ['N', 'P', 'U', 'S', 'Č', 'P', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['n', 'p', 'u', 's', 'č', 'p', 's'],
    -  SHORTQUARTERS: ['1kv', '2kv', '3kv', '4kv'],
    -  QUARTERS: ['1. kvartal', '2. kvartal', '3. kvartal', '4. kvartal'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d. MMMM y.', 'd. MMMM y.', 'd. MMM y.', 'dd.MM.y.'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'u\' {0}', '{1} \'u\' {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale hsb.
    - */
    -goog.i18n.DateTimeSymbols_hsb = {
    -  ERAS: ['př.Chr.n.', 'po Chr.n.'],
    -  ERANAMES: ['před Chrystowym narodźenjom', 'po Chrystowym narodźenju'],
    -  NARROWMONTHS: ['j', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['j', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o',
    -    'n', 'd'],
    -  MONTHS: ['januara', 'februara', 'měrca', 'apryla', 'meje', 'junija',
    -    'julija', 'awgusta', 'septembra', 'oktobra', 'nowembra', 'decembra'],
    -  STANDALONEMONTHS: ['januar', 'februar', 'měrc', 'apryl', 'meja', 'junij',
    -    'julij', 'awgust', 'september', 'oktober', 'nowember', 'december'],
    -  SHORTMONTHS: ['jan.', 'feb.', 'měr.', 'apr.', 'mej.', 'jun.', 'jul.', 'awg.',
    -    'sep.', 'okt.', 'now.', 'dec.'],
    -  STANDALONESHORTMONTHS: ['jan', 'feb', 'měr', 'apr', 'mej', 'jun', 'jul',
    -    'awg', 'sep', 'okt', 'now', 'dec'],
    -  WEEKDAYS: ['njedźela', 'póndźela', 'wutora', 'srjeda', 'štwórtk',
    -    'pjatk', 'sobota'],
    -  STANDALONEWEEKDAYS: ['njedźela', 'póndźela', 'wutora', 'srjeda',
    -    'štwórtk', 'pjatk', 'sobota'],
    -  SHORTWEEKDAYS: ['nje', 'pón', 'wut', 'srj', 'štw', 'pja', 'sob'],
    -  STANDALONESHORTWEEKDAYS: ['nje', 'pón', 'wut', 'srj', 'štw', 'pja', 'sob'],
    -  NARROWWEEKDAYS: ['n', 'p', 'w', 's', 'š', 'p', 's'],
    -  STANDALONENARROWWEEKDAYS: ['n', 'p', 'w', 's', 'š', 'p', 's'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1. kwartal', '2. kwartal', '3. kwartal', '4. kwartal'],
    -  AMPMS: ['dopołdnja', 'popołdnju'],
    -  DATEFORMATS: ['EEEE, d. MMMM y', 'd. MMMM y', 'd.M.y', 'd.M.yy'],
    -  TIMEFORMATS: ['H:mm:ss zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm \'hodź\'.'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale hsb_DE.
    - */
    -goog.i18n.DateTimeSymbols_hsb_DE = goog.i18n.DateTimeSymbols_hsb;
    -
    -
    -/**
    - * Date/time formatting symbols for locale hu_HU.
    - */
    -goog.i18n.DateTimeSymbols_hu_HU = {
    -  ERAS: ['i. e.', 'i. sz.'],
    -  ERANAMES: ['időszámításunk előtt', 'időszámításunk szerint'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'Á', 'M', 'J', 'J', 'A', 'Sz', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'Á', 'M', 'J', 'J', 'A', 'Sz', 'O',
    -    'N', 'D'],
    -  MONTHS: ['január', 'február', 'március', 'április', 'május', 'június',
    -    'július', 'augusztus', 'szeptember', 'október', 'november', 'december'],
    -  STANDALONEMONTHS: ['január', 'február', 'március', 'április', 'május',
    -    'június', 'július', 'augusztus', 'szeptember', 'október', 'november',
    -    'december'],
    -  SHORTMONTHS: ['jan.', 'febr.', 'márc.', 'ápr.', 'máj.', 'jún.', 'júl.',
    -    'aug.', 'szept.', 'okt.', 'nov.', 'dec.'],
    -  STANDALONESHORTMONTHS: ['jan.', 'febr.', 'márc.', 'ápr.', 'máj.', 'jún.',
    -    'júl.', 'aug.', 'szept.', 'okt.', 'nov.', 'dec.'],
    -  WEEKDAYS: ['vasárnap', 'hétfő', 'kedd', 'szerda', 'csütörtök',
    -    'péntek', 'szombat'],
    -  STANDALONEWEEKDAYS: ['vasárnap', 'hétfő', 'kedd', 'szerda', 'csütörtök',
    -    'péntek', 'szombat'],
    -  SHORTWEEKDAYS: ['V', 'H', 'K', 'Sze', 'Cs', 'P', 'Szo'],
    -  STANDALONESHORTWEEKDAYS: ['V', 'H', 'K', 'Sze', 'Cs', 'P', 'Szo'],
    -  NARROWWEEKDAYS: ['V', 'H', 'K', 'Sz', 'Cs', 'P', 'Sz'],
    -  STANDALONENARROWWEEKDAYS: ['V', 'H', 'K', 'Sz', 'Cs', 'P', 'Sz'],
    -  SHORTQUARTERS: ['N1', 'N2', 'N3', 'N4'],
    -  QUARTERS: ['I. negyedév', 'II. negyedév', 'III. negyedév',
    -    'IV. negyedév'],
    -  AMPMS: ['de.', 'du.'],
    -  DATEFORMATS: ['y. MMMM d., EEEE', 'y. MMMM d.', 'y. MMM d.', 'y. MM. dd.'],
    -  TIMEFORMATS: ['H:mm:ss zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale hy_AM.
    - */
    -goog.i18n.DateTimeSymbols_hy_AM = {
    -  ERAS: ['մ.թ.ա.', 'մ.թ.'],
    -  ERANAMES: ['մ.թ.ա.', 'մ.թ.'],
    -  NARROWMONTHS: ['Հ', 'Փ', 'Մ', 'Ա', 'Մ', 'Հ', 'Հ', 'Օ', 'Ս', 'Հ',
    -    'Ն', 'Դ'],
    -  STANDALONENARROWMONTHS: ['Հ', 'Փ', 'Մ', 'Ա', 'Մ', 'Հ', 'Հ', 'Օ', 'Ս',
    -    'Հ', 'Ն', 'Դ'],
    -  MONTHS: ['հունվարի', 'փետրվարի', 'մարտի', 'ապրիլի',
    -    'մայիսի', 'հունիսի', 'հուլիսի', 'օգոստոսի',
    -    'սեպտեմբերի', 'հոկտեմբերի', 'նոյեմբերի',
    -    'դեկտեմբերի'],
    -  STANDALONEMONTHS: ['հունվար', 'փետրվար', 'մարտ',
    -    'ապրիլ', 'մայիս', 'հունիս', 'հուլիս',
    -    'օգոստոս', 'սեպտեմբեր', 'հոկտեմբեր',
    -    'նոյեմբեր', 'դեկտեմբեր'],
    -  SHORTMONTHS: ['հնվ', 'փտվ', 'մրտ', 'ապր', 'մյս', 'հնս',
    -    'հլս', 'օգս', 'սեպ', 'հոկ', 'նոյ', 'դեկ'],
    -  STANDALONESHORTMONTHS: ['հնվ', 'փտվ', 'մրտ', 'ապր', 'մյս',
    -    'հնս', 'հլս', 'օգս', 'սեպ', 'հոկ', 'նոյ', 'դեկ'],
    -  WEEKDAYS: ['կիրակի', 'երկուշաբթի', 'երեքշաբթի',
    -    'չորեքշաբթի', 'հինգշաբթի', 'ուրբաթ', 'շաբաթ'],
    -  STANDALONEWEEKDAYS: ['կիրակի', 'երկուշաբթի',
    -    'երեքշաբթի', 'չորեքշաբթի', 'հինգշաբթի',
    -    'ուրբաթ', 'շաբաթ'],
    -  SHORTWEEKDAYS: ['կիր', 'երկ', 'երք', 'չրք', 'հնգ', 'ուր',
    -    'շբթ'],
    -  STANDALONESHORTWEEKDAYS: ['կիր', 'երկ', 'երք', 'չրք', 'հնգ',
    -    'ուր', 'շբթ'],
    -  NARROWWEEKDAYS: ['Կ', 'Ե', 'Ե', 'Չ', 'Հ', 'Ու', 'Շ'],
    -  STANDALONENARROWWEEKDAYS: ['Կ', 'Ե', 'Ե', 'Չ', 'Հ', 'Ու', 'Շ'],
    -  SHORTQUARTERS: ['1-ին եռմս.', '2-րդ եռմս.', '3-րդ եռմս.',
    -    '4-րդ եռմս.'],
    -  QUARTERS: ['1-ին եռամսյակ', '2-րդ եռամսյակ',
    -    '3-րդ եռամսյակ', '4-րդ եռամսյակ'],
    -  AMPMS: ['կեսօրից առաջ', 'կեսօրից հետո'],
    -  DATEFORMATS: ['yթ. MMMM d, EEEE', 'dd MMMM, yթ.', 'dd MMM, yթ.',
    -    'dd.MM.yy'],
    -  TIMEFORMATS: ['H:mm:ss, zzzz', 'H:mm:ss, z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ia.
    - */
    -goog.i18n.DateTimeSymbols_ia = {
    -  ERAS: ['a.Chr.', 'p.Chr.'],
    -  ERANAMES: ['ante Christo', 'post Christo'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['januario', 'februario', 'martio', 'april', 'maio', 'junio', 'julio',
    -    'augusto', 'septembre', 'octobre', 'novembre', 'decembre'],
    -  STANDALONEMONTHS: ['januario', 'februario', 'martio', 'april', 'maio',
    -    'junio', 'julio', 'augusto', 'septembre', 'octobre', 'novembre',
    -    'decembre'],
    -  SHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'mai', 'jun', 'jul', 'aug', 'sep',
    -    'oct', 'nov', 'dec'],
    -  STANDALONESHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'mai', 'jun', 'jul',
    -    'aug', 'sep', 'oct', 'nov', 'dec'],
    -  WEEKDAYS: ['dominica', 'lunedi', 'martedi', 'mercuridi', 'jovedi', 'venerdi',
    -    'sabbato'],
    -  STANDALONEWEEKDAYS: ['dominica', 'lunedi', 'martedi', 'mercuridi', 'jovedi',
    -    'venerdi', 'sabbato'],
    -  SHORTWEEKDAYS: ['dom', 'lun', 'mar', 'mer', 'jov', 'ven', 'sab'],
    -  STANDALONESHORTWEEKDAYS: ['dom', 'lun', 'mar', 'mer', 'jov', 'ven', 'sab'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1-me trimestre', '2-nde trimestre', '3-tie trimestre',
    -    '4-te trimestre'],
    -  AMPMS: ['a.m.', 'p.m.'],
    -  DATEFORMATS: ['EEEE, y MMMM dd', 'y MMMM d', 'y MMM d', 'yy/MM/dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ia_FR.
    - */
    -goog.i18n.DateTimeSymbols_ia_FR = goog.i18n.DateTimeSymbols_ia;
    -
    -
    -/**
    - * Date/time formatting symbols for locale id_ID.
    - */
    -goog.i18n.DateTimeSymbols_id_ID = {
    -  ERAS: ['SM', 'M'],
    -  ERANAMES: ['Sebelum Masehi', 'M'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni', 'Juli',
    -    'Agustus', 'September', 'Oktober', 'November', 'Desember'],
    -  STANDALONEMONTHS: ['Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni',
    -    'Juli', 'Agustus', 'September', 'Oktober', 'November', 'Desember'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Agt', 'Sep',
    -    'Okt', 'Nov', 'Des'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul',
    -    'Agt', 'Sep', 'Okt', 'Nov', 'Des'],
    -  WEEKDAYS: ['Minggu', 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu'],
    -  STANDALONEWEEKDAYS: ['Minggu', 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat',
    -    'Sabtu'],
    -  SHORTWEEKDAYS: ['Min', 'Sen', 'Sel', 'Rab', 'Kam', 'Jum', 'Sab'],
    -  STANDALONESHORTWEEKDAYS: ['Min', 'Sen', 'Sel', 'Rab', 'Kam', 'Jum', 'Sab'],
    -  NARROWWEEKDAYS: ['M', 'S', 'S', 'R', 'K', 'J', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['M', 'S', 'S', 'R', 'K', 'J', 'S'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['Kuartal ke-1', 'Kuartal ke-2', 'Kuartal ke-3', 'Kuartal ke-4'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, dd MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH.mm.ss zzzz', 'HH.mm.ss z', 'HH.mm.ss', 'HH.mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ig.
    - */
    -goog.i18n.DateTimeSymbols_ig = {
    -  ERAS: ['T.K.', 'A.K.'],
    -  ERANAMES: ['Tupu Kristi', 'Afọ Kristi'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['Jenụwarị', 'Febrụwarị', 'Maachị', 'Eprel', 'Mee', 'Juun',
    -    'Julaị', 'Ọgọọst', 'Septemba', 'Ọktoba', 'Novemba', 'Disemba'],
    -  STANDALONEMONTHS: ['Jenụwarị', 'Febrụwarị', 'Maachị', 'Eprel',
    -    'Mee', 'Juun', 'Julaị', 'Ọgọọst', 'Septemba', 'Ọktoba', 'Novemba',
    -    'Disemba'],
    -  SHORTMONTHS: ['Jen', 'Feb', 'Maa', 'Epr', 'Mee', 'Juu', 'Jul', 'Ọgọ',
    -    'Sep', 'Ọkt', 'Nov', 'Dis'],
    -  STANDALONESHORTMONTHS: ['Jen', 'Feb', 'Maa', 'Epr', 'Mee', 'Juu', 'Jul',
    -    'Ọgọ', 'Sep', 'Ọkt', 'Nov', 'Dis'],
    -  WEEKDAYS: ['Mbọsị Ụka', 'Mọnde', 'Tiuzdee', 'Wenezdee', 'Tọọzdee',
    -    'Fraịdee', 'Satọdee'],
    -  STANDALONEWEEKDAYS: ['Mbọsị Ụka', 'Mọnde', 'Tiuzdee', 'Wenezdee',
    -    'Tọọzdee', 'Fraịdee', 'Satọdee'],
    -  SHORTWEEKDAYS: ['Ụka', 'Mọn', 'Tiu', 'Wen', 'Tọọ', 'Fraị', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Ụka', 'Mọn', 'Tiu', 'Wen', 'Tọọ', 'Fraị',
    -    'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Ọ1', 'Ọ2', 'Ọ3', 'Ọ4'],
    -  QUARTERS: ['Ọkara 1', 'Ọkara 2', 'Ọkara 3', 'Ọkara 4'],
    -  AMPMS: ['A.M.', 'P.M.'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ig_NG.
    - */
    -goog.i18n.DateTimeSymbols_ig_NG = goog.i18n.DateTimeSymbols_ig;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ii.
    - */
    -goog.i18n.DateTimeSymbols_ii = {
    -  ERAS: ['ꃅꋊꂿ', 'ꃅꋊꊂ'],
    -  ERANAMES: ['ꃅꋊꂿ', 'ꃅꋊꊂ'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['ꋍꆪ', 'ꑍꆪ', 'ꌕꆪ', 'ꇖꆪ', 'ꉬꆪ', 'ꃘꆪ', 'ꏃꆪ',
    -    'ꉆꆪ', 'ꈬꆪ', 'ꊰꆪ', 'ꊰꊪꆪ', 'ꊰꑋꆪ'],
    -  STANDALONEMONTHS: ['ꋍꆪ', 'ꑍꆪ', 'ꌕꆪ', 'ꇖꆪ', 'ꉬꆪ', 'ꃘꆪ',
    -    'ꏃꆪ', 'ꉆꆪ', 'ꈬꆪ', 'ꊰꆪ', 'ꊰꊪꆪ', 'ꊰꑋꆪ'],
    -  SHORTMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONESHORTMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  WEEKDAYS: ['ꑭꆏꑍ', 'ꆏꊂꋍ', 'ꆏꊂꑍ', 'ꆏꊂꌕ', 'ꆏꊂꇖ',
    -    'ꆏꊂꉬ', 'ꆏꊂꃘ'],
    -  STANDALONEWEEKDAYS: ['ꑭꆏꑍ', 'ꆏꊂꋍ', 'ꆏꊂꑍ', 'ꆏꊂꌕ',
    -    'ꆏꊂꇖ', 'ꆏꊂꉬ', 'ꆏꊂꃘ'],
    -  SHORTWEEKDAYS: ['ꑭꆏ', 'ꆏꋍ', 'ꆏꑍ', 'ꆏꌕ', 'ꆏꇖ', 'ꆏꉬ',
    -    'ꆏꃘ'],
    -  STANDALONESHORTWEEKDAYS: ['ꑭꆏ', 'ꆏꋍ', 'ꆏꑍ', 'ꆏꌕ', 'ꆏꇖ',
    -    'ꆏꉬ', 'ꆏꃘ'],
    -  NARROWWEEKDAYS: ['ꆏ', 'ꋍ', 'ꑍ', 'ꌕ', 'ꇖ', 'ꉬ', 'ꃘ'],
    -  STANDALONENARROWWEEKDAYS: ['ꆏ', 'ꋍ', 'ꑍ', 'ꌕ', 'ꇖ', 'ꉬ', 'ꃘ'],
    -  SHORTQUARTERS: ['ꃅꑌ', 'ꃅꎸ', 'ꃅꍵ', 'ꃅꋆ'],
    -  QUARTERS: ['ꃅꑌ', 'ꃅꎸ', 'ꃅꍵ', 'ꃅꋆ'],
    -  AMPMS: ['ꎸꄑ', 'ꁯꋒ'],
    -  DATEFORMATS: ['y MMMM d, EEEE', 'y MMMM d', 'y MMM d', 'y-MM-dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ii_CN.
    - */
    -goog.i18n.DateTimeSymbols_ii_CN = goog.i18n.DateTimeSymbols_ii;
    -
    -
    -/**
    - * Date/time formatting symbols for locale is_IS.
    - */
    -goog.i18n.DateTimeSymbols_is_IS = {
    -  ERAS: ['f.Kr.', 'e.Kr.'],
    -  ERANAMES: ['fyrir Krist', 'eftir Krist'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'Á', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'Á', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janúar', 'febrúar', 'mars', 'apríl', 'maí', 'júní', 'júlí',
    -    'ágúst', 'september', 'október', 'nóvember', 'desember'],
    -  STANDALONEMONTHS: ['janúar', 'febrúar', 'mars', 'apríl', 'maí', 'júní',
    -    'júlí', 'ágúst', 'september', 'október', 'nóvember', 'desember'],
    -  SHORTMONTHS: ['jan.', 'feb.', 'mar.', 'apr.', 'maí', 'jún.', 'júl.',
    -    'ágú.', 'sep.', 'okt.', 'nóv.', 'des.'],
    -  STANDALONESHORTMONTHS: ['jan.', 'feb.', 'mar.', 'apr.', 'maí', 'jún.',
    -    'júl.', 'ágú.', 'sep.', 'okt.', 'nóv.', 'des.'],
    -  WEEKDAYS: ['sunnudagur', 'mánudagur', 'þriðjudagur', 'miðvikudagur',
    -    'fimmtudagur', 'föstudagur', 'laugardagur'],
    -  STANDALONEWEEKDAYS: ['sunnudagur', 'mánudagur', 'þriðjudagur',
    -    'miðvikudagur', 'fimmtudagur', 'föstudagur', 'laugardagur'],
    -  SHORTWEEKDAYS: ['sun.', 'mán.', 'þri.', 'mið.', 'fim.', 'fös.', 'lau.'],
    -  STANDALONESHORTWEEKDAYS: ['sun.', 'mán.', 'þri.', 'mið.', 'fim.', 'fös.',
    -    'lau.'],
    -  NARROWWEEKDAYS: ['S', 'M', 'Þ', 'M', 'F', 'F', 'L'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'Þ', 'M', 'F', 'F', 'L'],
    -  SHORTQUARTERS: ['F1', 'F2', 'F3', 'F4'],
    -  QUARTERS: ['1. fjórðungur', '2. fjórðungur', '3. fjórðungur',
    -    '4. fjórðungur'],
    -  AMPMS: ['f.h.', 'e.h.'],
    -  DATEFORMATS: ['EEEE, d. MMMM y', 'd. MMMM y', 'd. MMM y', 'd.M.y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'kl.\' {0}', '{1} \'kl.\' {0}', '{1}, {0}',
    -    '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale it_CH.
    - */
    -goog.i18n.DateTimeSymbols_it_CH = {
    -  ERAS: ['aC', 'dC'],
    -  ERANAMES: ['a.C.', 'd.C.'],
    -  NARROWMONTHS: ['G', 'F', 'M', 'A', 'M', 'G', 'L', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['G', 'F', 'M', 'A', 'M', 'G', 'L', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['gennaio', 'febbraio', 'marzo', 'aprile', 'maggio', 'giugno',
    -    'luglio', 'agosto', 'settembre', 'ottobre', 'novembre', 'dicembre'],
    -  STANDALONEMONTHS: ['Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio',
    -    'Giugno', 'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre',
    -    'Dicembre'],
    -  SHORTMONTHS: ['gen', 'feb', 'mar', 'apr', 'mag', 'giu', 'lug', 'ago', 'set',
    -    'ott', 'nov', 'dic'],
    -  STANDALONESHORTMONTHS: ['gen', 'feb', 'mar', 'apr', 'mag', 'giu', 'lug',
    -    'ago', 'set', 'ott', 'nov', 'dic'],
    -  WEEKDAYS: ['domenica', 'lunedì', 'martedì', 'mercoledì', 'giovedì',
    -    'venerdì', 'sabato'],
    -  STANDALONEWEEKDAYS: ['Domenica', 'Lunedì', 'Martedì', 'Mercoledì',
    -    'Giovedì', 'Venerdì', 'Sabato'],
    -  SHORTWEEKDAYS: ['dom', 'lun', 'mar', 'mer', 'gio', 'ven', 'sab'],
    -  STANDALONESHORTWEEKDAYS: ['dom', 'lun', 'mar', 'mer', 'gio', 'ven', 'sab'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'G', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'G', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1º trimestre', '2º trimestre', '3º trimestre',
    -    '4º trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd-MMM-y', 'dd.MM.yy'],
    -  TIMEFORMATS: ['HH.mm:ss \'h\' zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale it_IT.
    - */
    -goog.i18n.DateTimeSymbols_it_IT = {
    -  ERAS: ['aC', 'dC'],
    -  ERANAMES: ['a.C.', 'd.C.'],
    -  NARROWMONTHS: ['G', 'F', 'M', 'A', 'M', 'G', 'L', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['G', 'F', 'M', 'A', 'M', 'G', 'L', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['gennaio', 'febbraio', 'marzo', 'aprile', 'maggio', 'giugno',
    -    'luglio', 'agosto', 'settembre', 'ottobre', 'novembre', 'dicembre'],
    -  STANDALONEMONTHS: ['Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio',
    -    'Giugno', 'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre',
    -    'Dicembre'],
    -  SHORTMONTHS: ['gen', 'feb', 'mar', 'apr', 'mag', 'giu', 'lug', 'ago', 'set',
    -    'ott', 'nov', 'dic'],
    -  STANDALONESHORTMONTHS: ['gen', 'feb', 'mar', 'apr', 'mag', 'giu', 'lug',
    -    'ago', 'set', 'ott', 'nov', 'dic'],
    -  WEEKDAYS: ['domenica', 'lunedì', 'martedì', 'mercoledì', 'giovedì',
    -    'venerdì', 'sabato'],
    -  STANDALONEWEEKDAYS: ['Domenica', 'Lunedì', 'Martedì', 'Mercoledì',
    -    'Giovedì', 'Venerdì', 'Sabato'],
    -  SHORTWEEKDAYS: ['dom', 'lun', 'mar', 'mer', 'gio', 'ven', 'sab'],
    -  STANDALONESHORTWEEKDAYS: ['dom', 'lun', 'mar', 'mer', 'gio', 'ven', 'sab'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'G', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'G', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1º trimestre', '2º trimestre', '3º trimestre',
    -    '4º trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'dd MMM y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale it_SM.
    - */
    -goog.i18n.DateTimeSymbols_it_SM = {
    -  ERAS: ['aC', 'dC'],
    -  ERANAMES: ['a.C.', 'd.C.'],
    -  NARROWMONTHS: ['G', 'F', 'M', 'A', 'M', 'G', 'L', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['G', 'F', 'M', 'A', 'M', 'G', 'L', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['gennaio', 'febbraio', 'marzo', 'aprile', 'maggio', 'giugno',
    -    'luglio', 'agosto', 'settembre', 'ottobre', 'novembre', 'dicembre'],
    -  STANDALONEMONTHS: ['Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio',
    -    'Giugno', 'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre',
    -    'Dicembre'],
    -  SHORTMONTHS: ['gen', 'feb', 'mar', 'apr', 'mag', 'giu', 'lug', 'ago', 'set',
    -    'ott', 'nov', 'dic'],
    -  STANDALONESHORTMONTHS: ['gen', 'feb', 'mar', 'apr', 'mag', 'giu', 'lug',
    -    'ago', 'set', 'ott', 'nov', 'dic'],
    -  WEEKDAYS: ['domenica', 'lunedì', 'martedì', 'mercoledì', 'giovedì',
    -    'venerdì', 'sabato'],
    -  STANDALONEWEEKDAYS: ['Domenica', 'Lunedì', 'Martedì', 'Mercoledì',
    -    'Giovedì', 'Venerdì', 'Sabato'],
    -  SHORTWEEKDAYS: ['dom', 'lun', 'mar', 'mer', 'gio', 'ven', 'sab'],
    -  STANDALONESHORTWEEKDAYS: ['dom', 'lun', 'mar', 'mer', 'gio', 'ven', 'sab'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'G', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'G', 'V', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1º trimestre', '2º trimestre', '3º trimestre',
    -    '4º trimestre'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'dd MMM y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ja_JP.
    - */
    -goog.i18n.DateTimeSymbols_ja_JP = {
    -  ERAS: ['紀元前', '西暦'],
    -  ERANAMES: ['紀元前', '西暦'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月',
    -    '9月', '10月', '11月', '12月'],
    -  STANDALONEMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月', '7月',
    -    '8月', '9月', '10月', '11月', '12月'],
    -  SHORTMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月',
    -    '9月', '10月', '11月', '12月'],
    -  STANDALONESHORTMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月',
    -    '7月', '8月', '9月', '10月', '11月', '12月'],
    -  WEEKDAYS: ['日曜日', '月曜日', '火曜日', '水曜日', '木曜日',
    -    '金曜日', '土曜日'],
    -  STANDALONEWEEKDAYS: ['日曜日', '月曜日', '火曜日', '水曜日',
    -    '木曜日', '金曜日', '土曜日'],
    -  SHORTWEEKDAYS: ['日', '月', '火', '水', '木', '金', '土'],
    -  STANDALONESHORTWEEKDAYS: ['日', '月', '火', '水', '木', '金', '土'],
    -  NARROWWEEKDAYS: ['日', '月', '火', '水', '木', '金', '土'],
    -  STANDALONENARROWWEEKDAYS: ['日', '月', '火', '水', '木', '金', '土'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['第1四半期', '第2四半期', '第3四半期',
    -    '第4四半期'],
    -  AMPMS: ['午前', '午後'],
    -  DATEFORMATS: ['y年M月d日EEEE', 'y年M月d日', 'y/MM/dd', 'y/MM/dd'],
    -  TIMEFORMATS: ['H時mm分ss秒 zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale jgo.
    - */
    -goog.i18n.DateTimeSymbols_jgo = {
    -  ERAS: ['tsɛttsɛt mɛŋguꞌ mi ɛ́ lɛɛnɛ Kɛlísɛtɔ gɔ ńɔ́',
    -    'tsɛttsɛt mɛŋguꞌ mi ɛ́ fúnɛ Kɛlísɛtɔ tɔ́ mɔ́'],
    -  ERANAMES: ['tsɛttsɛt mɛŋguꞌ mi ɛ́ lɛɛnɛ Kɛlísɛtɔ gɔ ńɔ́',
    -    'tsɛttsɛt mɛŋguꞌ mi ɛ́ fúnɛ Kɛlísɛtɔ tɔ́ mɔ́'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['Nduŋmbi Saŋ', 'Pɛsaŋ Pɛ́pá', 'Pɛsaŋ Pɛ́tát',
    -    'Pɛsaŋ Pɛ́nɛ́kwa', 'Pɛsaŋ Pataa', 'Pɛsaŋ Pɛ́nɛ́ntúkú',
    -    'Pɛsaŋ Saambá', 'Pɛsaŋ Pɛ́nɛ́fɔm', 'Pɛsaŋ Pɛ́nɛ́pfúꞋú',
    -    'Pɛsaŋ Nɛgɛ́m', 'Pɛsaŋ Ntsɔ̌pmɔ́', 'Pɛsaŋ Ntsɔ̌ppá'],
    -  STANDALONEMONTHS: ['Nduŋmbi Saŋ', 'Pɛsaŋ Pɛ́pá', 'Pɛsaŋ Pɛ́tát',
    -    'Pɛsaŋ Pɛ́nɛ́kwa', 'Pɛsaŋ Pataa', 'Pɛsaŋ Pɛ́nɛ́ntúkú',
    -    'Pɛsaŋ Saambá', 'Pɛsaŋ Pɛ́nɛ́fɔm', 'Pɛsaŋ Pɛ́nɛ́pfúꞋú',
    -    'Pɛsaŋ Nɛgɛ́m', 'Pɛsaŋ Ntsɔ̌pmɔ́', 'Pɛsaŋ Ntsɔ̌ppá'],
    -  SHORTMONTHS: ['Nduŋmbi Saŋ', 'Pɛsaŋ Pɛ́pá', 'Pɛsaŋ Pɛ́tát',
    -    'Pɛsaŋ Pɛ́nɛ́kwa', 'Pɛsaŋ Pataa', 'Pɛsaŋ Pɛ́nɛ́ntúkú',
    -    'Pɛsaŋ Saambá', 'Pɛsaŋ Pɛ́nɛ́fɔm', 'Pɛsaŋ Pɛ́nɛ́pfúꞋú',
    -    'Pɛsaŋ Nɛgɛ́m', 'Pɛsaŋ Ntsɔ̌pmɔ́', 'Pɛsaŋ Ntsɔ̌ppá'],
    -  STANDALONESHORTMONTHS: ['Nduŋmbi Saŋ', 'Pɛsaŋ Pɛ́pá',
    -    'Pɛsaŋ Pɛ́tát', 'Pɛsaŋ Pɛ́nɛ́kwa', 'Pɛsaŋ Pataa',
    -    'Pɛsaŋ Pɛ́nɛ́ntúkú', 'Pɛsaŋ Saambá', 'Pɛsaŋ Pɛ́nɛ́fɔm',
    -    'Pɛsaŋ Pɛ́nɛ́pfúꞋú', 'Pɛsaŋ Nɛgɛ́m', 'Pɛsaŋ Ntsɔ̌pmɔ́',
    -    'Pɛsaŋ Ntsɔ̌ppá'],
    -  WEEKDAYS: ['Sɔ́ndi', 'Mɔ́ndi', 'Ápta Mɔ́ndi', 'Wɛ́nɛsɛdɛ',
    -    'Tɔ́sɛdɛ', 'Fɛlâyɛdɛ', 'Sásidɛ'],
    -  STANDALONEWEEKDAYS: ['Sɔ́ndi', 'Mɔ́ndi', 'Ápta Mɔ́ndi',
    -    'Wɛ́nɛsɛdɛ', 'Tɔ́sɛdɛ', 'Fɛlâyɛdɛ', 'Sásidɛ'],
    -  SHORTWEEKDAYS: ['Sɔ́ndi', 'Mɔ́ndi', 'Ápta Mɔ́ndi', 'Wɛ́nɛsɛdɛ',
    -    'Tɔ́sɛdɛ', 'Fɛlâyɛdɛ', 'Sásidɛ'],
    -  STANDALONESHORTWEEKDAYS: ['Sɔ́ndi', 'Mɔ́ndi', 'Ápta Mɔ́ndi',
    -    'Wɛ́nɛsɛdɛ', 'Tɔ́sɛdɛ', 'Fɛlâyɛdɛ', 'Sásidɛ'],
    -  NARROWWEEKDAYS: ['Sɔ́', 'Mɔ́', 'ÁM', 'Wɛ́', 'Tɔ́', 'Fɛ', 'Sá'],
    -  STANDALONENARROWWEEKDAYS: ['Sɔ́', 'Mɔ́', 'ÁM', 'Wɛ́', 'Tɔ́', 'Fɛ',
    -    'Sá'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['mbaꞌmbaꞌ', 'ŋka mbɔ́t nji'],
    -  DATEFORMATS: ['EEEE, y MMMM dd', 'y MMMM d', 'y MMM d', 'y-MM-dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale jgo_CM.
    - */
    -goog.i18n.DateTimeSymbols_jgo_CM = goog.i18n.DateTimeSymbols_jgo;
    -
    -
    -/**
    - * Date/time formatting symbols for locale jmc.
    - */
    -goog.i18n.DateTimeSymbols_jmc = {
    -  ERAS: ['KK', 'BK'],
    -  ERANAMES: ['Kabla ya Kristu', 'Baada ya Kristu'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januari', 'Februari', 'Machi', 'Aprilyi', 'Mei', 'Junyi', 'Julyai',
    -    'Agusti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    -  STANDALONEMONTHS: ['Januari', 'Februari', 'Machi', 'Aprilyi', 'Mei', 'Junyi',
    -    'Julyai', 'Agusti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep',
    -    'Okt', 'Nov', 'Des'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul',
    -    'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
    -  WEEKDAYS: ['Jumapilyi', 'Jumatatuu', 'Jumanne', 'Jumatanu', 'Alhamisi',
    -    'Ijumaa', 'Jumamosi'],
    -  STANDALONEWEEKDAYS: ['Jumapilyi', 'Jumatatuu', 'Jumanne', 'Jumatanu',
    -    'Alhamisi', 'Ijumaa', 'Jumamosi'],
    -  SHORTWEEKDAYS: ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
    -  STANDALONESHORTWEEKDAYS: ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
    -  NARROWWEEKDAYS: ['J', 'J', 'J', 'J', 'A', 'I', 'J'],
    -  STANDALONENARROWWEEKDAYS: ['J', 'J', 'J', 'J', 'A', 'I', 'J'],
    -  SHORTQUARTERS: ['R1', 'R2', 'R3', 'R4'],
    -  QUARTERS: ['Robo 1', 'Robo 2', 'Robo 3', 'Robo 4'],
    -  AMPMS: ['utuko', 'kyiukonyi'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale jmc_TZ.
    - */
    -goog.i18n.DateTimeSymbols_jmc_TZ = goog.i18n.DateTimeSymbols_jmc;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ka_GE.
    - */
    -goog.i18n.DateTimeSymbols_ka_GE = {
    -  ERAS: ['ძვ. წ.', 'ახ. წ.'],
    -  ERANAMES: ['ძველი წელთაღრიცხვით',
    -    'ახალი წელთაღრიცხვით'],
    -  NARROWMONTHS: ['ი', 'თ', 'მ', 'ა', 'მ', 'ი', 'ი', 'ა', 'ს',
    -    'ო', 'ნ', 'დ'],
    -  STANDALONENARROWMONTHS: ['ი', 'თ', 'მ', 'ა', 'მ', 'ი', 'ი',
    -    'ა', 'ს', 'ო', 'ნ', 'დ'],
    -  MONTHS: ['იანვარი', 'თებერვალი',
    -    'მარტი', 'აპრილი', 'მაისი',
    -    'ივნისი', 'ივლისი', 'აგვისტო',
    -    'სექტემბერი', 'ოქტომბერი',
    -    'ნოემბერი', 'დეკემბერი'],
    -  STANDALONEMONTHS: ['იანვარი', 'თებერვალი',
    -    'მარტი', 'აპრილი', 'მაისი',
    -    'ივნისი', 'ივლისი', 'აგვისტო',
    -    'სექტემბერი', 'ოქტომბერი',
    -    'ნოემბერი', 'დეკემბერი'],
    -  SHORTMONTHS: ['იან', 'თებ', 'მარ', 'აპრ', 'მაი',
    -    'ივნ', 'ივლ', 'აგვ', 'სექ', 'ოქტ',
    -    'ნოე', 'დეკ'],
    -  STANDALONESHORTMONTHS: ['იან', 'თებ', 'მარ', 'აპრ',
    -    'მაი', 'ივნ', 'ივლ', 'აგვ', 'სექ',
    -    'ოქტ', 'ნოე', 'დეკ'],
    -  WEEKDAYS: ['კვირა', 'ორშაბათი',
    -    'სამშაბათი', 'ოთხშაბათი',
    -    'ხუთშაბათი', 'პარასკევი',
    -    'შაბათი'],
    -  STANDALONEWEEKDAYS: ['კვირა', 'ორშაბათი',
    -    'სამშაბათი', 'ოთხშაბათი',
    -    'ხუთშაბათი', 'პარასკევი',
    -    'შაბათი'],
    -  SHORTWEEKDAYS: ['კვი', 'ორშ', 'სამ', 'ოთხ',
    -    'ხუთ', 'პარ', 'შაბ'],
    -  STANDALONESHORTWEEKDAYS: ['კვი', 'ორშ', 'სამ', 'ოთხ',
    -    'ხუთ', 'პარ', 'შაბ'],
    -  NARROWWEEKDAYS: ['კ', 'ო', 'ს', 'ო', 'ხ', 'პ', 'შ'],
    -  STANDALONENARROWWEEKDAYS: ['კ', 'ო', 'ს', 'ო', 'ხ', 'პ', 'შ'],
    -  SHORTQUARTERS: ['I კვ.', 'II კვ.', 'III კვ.', 'IV კვ.'],
    -  QUARTERS: ['I კვარტალი', 'II კვარტალი',
    -    'III კვარტალი', 'IV კვარტალი'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, dd MMMM, y', 'd MMMM, y', 'd MMM, y', 'dd.MM.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1}, {0}', '{1} {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale kab.
    - */
    -goog.i18n.DateTimeSymbols_kab = {
    -  ERAS: ['snd. T.Ɛ', 'sld. T.Ɛ'],
    -  ERANAMES: ['send talalit n Ɛisa', 'seld talalit n Ɛisa'],
    -  NARROWMONTHS: ['Y', 'F', 'M', 'Y', 'M', 'Y', 'Y', 'Ɣ', 'C', 'T', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['Y', 'F', 'M', 'Y', 'M', 'Y', 'Y', 'Ɣ', 'C', 'T',
    -    'N', 'D'],
    -  MONTHS: ['Yennayer', 'Fuṛar', 'Meɣres', 'Yebrir', 'Mayyu', 'Yunyu',
    -    'Yulyu', 'Ɣuct', 'Ctembeṛ', 'Tubeṛ', 'Nunembeṛ', 'Duǧembeṛ'],
    -  STANDALONEMONTHS: ['Yennayer', 'Fuṛar', 'Meɣres', 'Yebrir', 'Mayyu',
    -    'Yunyu', 'Yulyu', 'Ɣuct', 'Ctembeṛ', 'Tubeṛ', 'Nunembeṛ',
    -    'Duǧembeṛ'],
    -  SHORTMONTHS: ['Yen', 'Fur', 'Meɣ', 'Yeb', 'May', 'Yun', 'Yul', 'Ɣuc', 'Cte',
    -    'Tub', 'Nun', 'Duǧ'],
    -  STANDALONESHORTMONTHS: ['Yen', 'Fur', 'Meɣ', 'Yeb', 'May', 'Yun', 'Yul',
    -    'Ɣuc', 'Cte', 'Tub', 'Nun', 'Duǧ'],
    -  WEEKDAYS: ['Yanass', 'Sanass', 'Kraḍass', 'Kuẓass', 'Samass', 'Sḍisass',
    -    'Sayass'],
    -  STANDALONEWEEKDAYS: ['Yanass', 'Sanass', 'Kraḍass', 'Kuẓass', 'Samass',
    -    'Sḍisass', 'Sayass'],
    -  SHORTWEEKDAYS: ['Yan', 'San', 'Kraḍ', 'Kuẓ', 'Sam', 'Sḍis', 'Say'],
    -  STANDALONESHORTWEEKDAYS: ['Yan', 'San', 'Kraḍ', 'Kuẓ', 'Sam', 'Sḍis',
    -    'Say'],
    -  NARROWWEEKDAYS: ['Y', 'S', 'K', 'K', 'S', 'S', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['Y', 'S', 'K', 'K', 'S', 'S', 'S'],
    -  SHORTQUARTERS: ['Kḍg1', 'Kḍg2', 'Kḍg3', 'Kḍg4'],
    -  QUARTERS: ['akraḍaggur amenzu', 'akraḍaggur wis-sin',
    -    'akraḍaggur wis-kraḍ', 'akraḍaggur wis-kuẓ'],
    -  AMPMS: ['n tufat', 'n tmeddit'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM, y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale kab_DZ.
    - */
    -goog.i18n.DateTimeSymbols_kab_DZ = goog.i18n.DateTimeSymbols_kab;
    -
    -
    -/**
    - * Date/time formatting symbols for locale kam.
    - */
    -goog.i18n.DateTimeSymbols_kam = {
    -  ERAS: ['MY', 'IY'],
    -  ERANAMES: ['Mbee wa Yesũ', 'Ĩtina wa Yesũ'],
    -  NARROWMONTHS: ['M', 'K', 'K', 'K', 'K', 'T', 'M', 'N', 'K', 'Ĩ', 'Ĩ', 'Ĩ'],
    -  STANDALONENARROWMONTHS: ['M', 'K', 'K', 'K', 'K', 'T', 'M', 'N', 'K', 'Ĩ',
    -    'Ĩ', 'Ĩ'],
    -  MONTHS: ['Mwai wa mbee', 'Mwai wa kelĩ', 'Mwai wa katatũ', 'Mwai wa kana',
    -    'Mwai wa katano', 'Mwai wa thanthatũ', 'Mwai wa muonza', 'Mwai wa nyaanya',
    -    'Mwai wa kenda', 'Mwai wa ĩkumi', 'Mwai wa ĩkumi na ĩmwe',
    -    'Mwai wa ĩkumi na ilĩ'],
    -  STANDALONEMONTHS: ['Mwai wa mbee', 'Mwai wa kelĩ', 'Mwai wa katatũ',
    -    'Mwai wa kana', 'Mwai wa katano', 'Mwai wa thanthatũ', 'Mwai wa muonza',
    -    'Mwai wa nyaanya', 'Mwai wa kenda', 'Mwai wa ĩkumi',
    -    'Mwai wa ĩkumi na ĩmwe', 'Mwai wa ĩkumi na ilĩ'],
    -  SHORTMONTHS: ['Mbe', 'Kel', 'Ktũ', 'Kan', 'Ktn', 'Tha', 'Moo', 'Nya', 'Knd',
    -    'Ĩku', 'Ĩkm', 'Ĩkl'],
    -  STANDALONESHORTMONTHS: ['Mbe', 'Kel', 'Ktũ', 'Kan', 'Ktn', 'Tha', 'Moo',
    -    'Nya', 'Knd', 'Ĩku', 'Ĩkm', 'Ĩkl'],
    -  WEEKDAYS: ['Wa kyumwa', 'Wa kwambĩlĩlya', 'Wa kelĩ', 'Wa katatũ',
    -    'Wa kana', 'Wa katano', 'Wa thanthatũ'],
    -  STANDALONEWEEKDAYS: ['Wa kyumwa', 'Wa kwambĩlĩlya', 'Wa kelĩ',
    -    'Wa katatũ', 'Wa kana', 'Wa katano', 'Wa thanthatũ'],
    -  SHORTWEEKDAYS: ['Wky', 'Wkw', 'Wkl', 'Wtũ', 'Wkn', 'Wtn', 'Wth'],
    -  STANDALONESHORTWEEKDAYS: ['Wky', 'Wkw', 'Wkl', 'Wtũ', 'Wkn', 'Wtn', 'Wth'],
    -  NARROWWEEKDAYS: ['Y', 'W', 'E', 'A', 'A', 'A', 'A'],
    -  STANDALONENARROWWEEKDAYS: ['Y', 'W', 'E', 'A', 'A', 'A', 'A'],
    -  SHORTQUARTERS: ['L1', 'L2', 'L3', 'L4'],
    -  QUARTERS: ['Lovo ya mbee', 'Lovo ya kelĩ', 'Lovo ya katatũ',
    -    'Lovo ya kana'],
    -  AMPMS: ['Ĩyakwakya', 'Ĩyawĩoo'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale kam_KE.
    - */
    -goog.i18n.DateTimeSymbols_kam_KE = goog.i18n.DateTimeSymbols_kam;
    -
    -
    -/**
    - * Date/time formatting symbols for locale kde.
    - */
    -goog.i18n.DateTimeSymbols_kde = {
    -  ERAS: ['AY', 'NY'],
    -  ERANAMES: ['Akanapawa Yesu', 'Nankuida Yesu'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Mwedi Ntandi', 'Mwedi wa Pili', 'Mwedi wa Tatu', 'Mwedi wa Nchechi',
    -    'Mwedi wa Nnyano', 'Mwedi wa Nnyano na Umo', 'Mwedi wa Nnyano na Mivili',
    -    'Mwedi wa Nnyano na Mitatu', 'Mwedi wa Nnyano na Nchechi',
    -    'Mwedi wa Nnyano na Nnyano', 'Mwedi wa Nnyano na Nnyano na U',
    -    'Mwedi wa Nnyano na Nnyano na M'],
    -  STANDALONEMONTHS: ['Mwedi Ntandi', 'Mwedi wa Pili', 'Mwedi wa Tatu',
    -    'Mwedi wa Nchechi', 'Mwedi wa Nnyano', 'Mwedi wa Nnyano na Umo',
    -    'Mwedi wa Nnyano na Mivili', 'Mwedi wa Nnyano na Mitatu',
    -    'Mwedi wa Nnyano na Nchechi', 'Mwedi wa Nnyano na Nnyano',
    -    'Mwedi wa Nnyano na Nnyano na U', 'Mwedi wa Nnyano na Nnyano na M'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep',
    -    'Okt', 'Nov', 'Des'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul',
    -    'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
    -  WEEKDAYS: ['Liduva lyapili', 'Liduva lyatatu', 'Liduva lyanchechi',
    -    'Liduva lyannyano', 'Liduva lyannyano na linji',
    -    'Liduva lyannyano na mavili', 'Liduva litandi'],
    -  STANDALONEWEEKDAYS: ['Liduva lyapili', 'Liduva lyatatu', 'Liduva lyanchechi',
    -    'Liduva lyannyano', 'Liduva lyannyano na linji',
    -    'Liduva lyannyano na mavili', 'Liduva litandi'],
    -  SHORTWEEKDAYS: ['Ll2', 'Ll3', 'Ll4', 'Ll5', 'Ll6', 'Ll7', 'Ll1'],
    -  STANDALONESHORTWEEKDAYS: ['Ll2', 'Ll3', 'Ll4', 'Ll5', 'Ll6', 'Ll7', 'Ll1'],
    -  NARROWWEEKDAYS: ['2', '3', '4', '5', '6', '7', '1'],
    -  STANDALONENARROWWEEKDAYS: ['2', '3', '4', '5', '6', '7', '1'],
    -  SHORTQUARTERS: ['L1', 'L2', 'L3', 'L4'],
    -  QUARTERS: ['Lobo 1', 'Lobo 2', 'Lobo 3', 'Lobo 4'],
    -  AMPMS: ['Muhi', 'Chilo'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale kde_TZ.
    - */
    -goog.i18n.DateTimeSymbols_kde_TZ = goog.i18n.DateTimeSymbols_kde;
    -
    -
    -/**
    - * Date/time formatting symbols for locale kea.
    - */
    -goog.i18n.DateTimeSymbols_kea = {
    -  ERAS: ['AK', 'DK'],
    -  ERANAMES: ['Antis di Kristu', 'Dispos di Kristu'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Janeru', 'Febreru', 'Marsu', 'Abril', 'Maiu', 'Junhu', 'Julhu',
    -    'Agostu', 'Setenbru', 'Otubru', 'Nuvenbru', 'Dizenbru'],
    -  STANDALONEMONTHS: ['Janeru', 'Febreru', 'Marsu', 'Abril', 'Maiu', 'Junhu',
    -    'Julhu', 'Agostu', 'Setenbru', 'Otubru', 'Nuvenbru', 'Dizenbru'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set',
    -    'Otu', 'Nuv', 'Diz'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul',
    -    'Ago', 'Set', 'Otu', 'Nuv', 'Diz'],
    -  WEEKDAYS: ['dumingu', 'sigunda-fera', 'tersa-fera', 'kuarta-fera',
    -    'kinta-fera', 'sesta-fera', 'sabadu'],
    -  STANDALONEWEEKDAYS: ['dumingu', 'sigunda-fera', 'tersa-fera', 'kuarta-fera',
    -    'kinta-fera', 'sesta-fera', 'sabadu'],
    -  SHORTWEEKDAYS: ['dum', 'sig', 'ter', 'kua', 'kin', 'ses', 'sab'],
    -  STANDALONESHORTWEEKDAYS: ['dum', 'sig', 'ter', 'kua', 'kin', 'ses', 'sab'],
    -  NARROWWEEKDAYS: ['D', 'S', 'T', 'K', 'K', 'S', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['d', 's', 't', 'k', 'k', 's', 's'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1º trimestri', '2º trimestri', '3º trimestri',
    -    '4º trimestri'],
    -  AMPMS: ['am', 'pm'],
    -  DATEFORMATS: ['EEEE, d \'di\' MMMM \'di\' y', 'd \'di\' MMMM \'di\' y',
    -    'd MMM y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale kea_CV.
    - */
    -goog.i18n.DateTimeSymbols_kea_CV = goog.i18n.DateTimeSymbols_kea;
    -
    -
    -/**
    - * Date/time formatting symbols for locale khq.
    - */
    -goog.i18n.DateTimeSymbols_khq = {
    -  ERAS: ['IJ', 'IZ'],
    -  ERANAMES: ['Isaa jine', 'Isaa jamanoo'],
    -  NARROWMONTHS: ['Ž', 'F', 'M', 'A', 'M', 'Ž', 'Ž', 'U', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['Ž', 'F', 'M', 'A', 'M', 'Ž', 'Ž', 'U', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Žanwiye', 'Feewiriye', 'Marsi', 'Awiril', 'Me', 'Žuweŋ',
    -    'Žuyye', 'Ut', 'Sektanbur', 'Oktoobur', 'Noowanbur', 'Deesanbur'],
    -  STANDALONEMONTHS: ['Žanwiye', 'Feewiriye', 'Marsi', 'Awiril', 'Me',
    -    'Žuweŋ', 'Žuyye', 'Ut', 'Sektanbur', 'Oktoobur', 'Noowanbur',
    -    'Deesanbur'],
    -  SHORTMONTHS: ['Žan', 'Fee', 'Mar', 'Awi', 'Me', 'Žuw', 'Žuy', 'Ut', 'Sek',
    -    'Okt', 'Noo', 'Dee'],
    -  STANDALONESHORTMONTHS: ['Žan', 'Fee', 'Mar', 'Awi', 'Me', 'Žuw', 'Žuy',
    -    'Ut', 'Sek', 'Okt', 'Noo', 'Dee'],
    -  WEEKDAYS: ['Alhadi', 'Atini', 'Atalata', 'Alarba', 'Alhamiisa', 'Aljuma',
    -    'Assabdu'],
    -  STANDALONEWEEKDAYS: ['Alhadi', 'Atini', 'Atalata', 'Alarba', 'Alhamiisa',
    -    'Aljuma', 'Assabdu'],
    -  SHORTWEEKDAYS: ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alj', 'Ass'],
    -  STANDALONESHORTWEEKDAYS: ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alj', 'Ass'],
    -  NARROWWEEKDAYS: ['H', 'T', 'T', 'L', 'L', 'L', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['H', 'T', 'T', 'L', 'L', 'L', 'S'],
    -  SHORTQUARTERS: ['A1', 'A2', 'A3', 'A4'],
    -  QUARTERS: ['Arrubu 1', 'Arrubu 2', 'Arrubu 3', 'Arrubu 4'],
    -  AMPMS: ['Adduha', 'Aluula'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM, y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale khq_ML.
    - */
    -goog.i18n.DateTimeSymbols_khq_ML = goog.i18n.DateTimeSymbols_khq;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ki.
    - */
    -goog.i18n.DateTimeSymbols_ki = {
    -  ERAS: ['MK', 'TK'],
    -  ERANAMES: ['Mbere ya Kristo', 'Thutha wa Kristo'],
    -  NARROWMONTHS: ['J', 'K', 'G', 'K', 'G', 'G', 'M', 'K', 'K', 'I', 'I', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'K', 'G', 'K', 'G', 'G', 'M', 'K', 'K', 'I',
    -    'I', 'D'],
    -  MONTHS: ['Njenuarĩ', 'Mwere wa kerĩ', 'Mwere wa gatatũ', 'Mwere wa kana',
    -    'Mwere wa gatano', 'Mwere wa gatandatũ', 'Mwere wa mũgwanja',
    -    'Mwere wa kanana', 'Mwere wa kenda', 'Mwere wa ikũmi',
    -    'Mwere wa ikũmi na ũmwe', 'Ndithemba'],
    -  STANDALONEMONTHS: ['Njenuarĩ', 'Mwere wa kerĩ', 'Mwere wa gatatũ',
    -    'Mwere wa kana', 'Mwere wa gatano', 'Mwere wa gatandatũ',
    -    'Mwere wa mũgwanja', 'Mwere wa kanana', 'Mwere wa kenda',
    -    'Mwere wa ikũmi', 'Mwere wa ikũmi na ũmwe', 'Ndithemba'],
    -  SHORTMONTHS: ['JEN', 'WKR', 'WGT', 'WKN', 'WTN', 'WTD', 'WMJ', 'WNN', 'WKD',
    -    'WIK', 'WMW', 'DIT'],
    -  STANDALONESHORTMONTHS: ['JEN', 'WKR', 'WGT', 'WKN', 'WTN', 'WTD', 'WMJ',
    -    'WNN', 'WKD', 'WIK', 'WMW', 'DIT'],
    -  WEEKDAYS: ['Kiumia', 'Njumatatũ', 'Njumaine', 'Njumatana', 'Aramithi',
    -    'Njumaa', 'Njumamothi'],
    -  STANDALONEWEEKDAYS: ['Kiumia', 'Njumatatũ', 'Njumaine', 'Njumatana',
    -    'Aramithi', 'Njumaa', 'Njumamothi'],
    -  SHORTWEEKDAYS: ['KMA', 'NTT', 'NMN', 'NMT', 'ART', 'NMA', 'NMM'],
    -  STANDALONESHORTWEEKDAYS: ['KMA', 'NTT', 'NMN', 'NMT', 'ART', 'NMA', 'NMM'],
    -  NARROWWEEKDAYS: ['K', 'N', 'N', 'N', 'A', 'N', 'N'],
    -  STANDALONENARROWWEEKDAYS: ['K', 'N', 'N', 'N', 'A', 'N', 'N'],
    -  SHORTQUARTERS: ['R1', 'R2', 'R3', 'R4'],
    -  QUARTERS: ['Robo ya mbere', 'Robo ya kerĩ', 'Robo ya gatatũ',
    -    'Robo ya kana'],
    -  AMPMS: ['Kiroko', 'Hwaĩ-inĩ'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ki_KE.
    - */
    -goog.i18n.DateTimeSymbols_ki_KE = goog.i18n.DateTimeSymbols_ki;
    -
    -
    -/**
    - * Date/time formatting symbols for locale kk_Cyrl.
    - */
    -goog.i18n.DateTimeSymbols_kk_Cyrl = {
    -  ERAS: ['б.з.д.', 'б.з.'],
    -  ERANAMES: ['Біздің заманымызға дейін',
    -    'Біздің заманымыз'],
    -  NARROWMONTHS: ['Қ', 'А', 'Н', 'С', 'М', 'М', 'Ш', 'Т', 'Қ', 'Қ',
    -    'Қ', 'Ж'],
    -  STANDALONENARROWMONTHS: ['Қ', 'А', 'Н', 'С', 'М', 'М', 'Ш', 'Т', 'Қ',
    -    'Қ', 'Қ', 'Ж'],
    -  MONTHS: ['қаңтар', 'ақпан', 'наурыз', 'сәуір',
    -    'мамыр', 'маусым', 'шілде', 'тамыз',
    -    'қыркүйек', 'қазан', 'қараша', 'желтоқсан'],
    -  STANDALONEMONTHS: ['қаңтар', 'ақпан', 'наурыз', 'сәуір',
    -    'мамыр', 'маусым', 'шілде', 'тамыз',
    -    'қыркүйек', 'қазан', 'қараша', 'желтоқсан'],
    -  SHORTMONTHS: ['қаң.', 'ақп.', 'нау.', 'сәу.', 'мам.',
    -    'мау.', 'шіл.', 'там.', 'қыр.', 'қаз.', 'қар.',
    -    'желт.'],
    -  STANDALONESHORTMONTHS: ['қаң.', 'ақп.', 'нау.', 'сәу.', 'мам.',
    -    'мау.', 'шіл.', 'там.', 'қыр.', 'қаз.', 'қар.',
    -    'желт.'],
    -  WEEKDAYS: ['жексенбі', 'дүйсенбі', 'сейсенбі',
    -    'сәрсенбі', 'бейсенбі', 'жұма', 'сенбі'],
    -  STANDALONEWEEKDAYS: ['жексенбі', 'дүйсенбі',
    -    'сейсенбі', 'сәрсенбі', 'бейсенбі', 'жұма',
    -    'сенбі'],
    -  SHORTWEEKDAYS: ['жек', 'дүй', 'сей', 'сәр', 'бей', 'жұма',
    -    'сен'],
    -  STANDALONESHORTWEEKDAYS: ['жек', 'дүй', 'сей', 'сәр', 'бей',
    -    'жұма', 'сб.'],
    -  NARROWWEEKDAYS: ['Ж', 'Д', 'С', 'С', 'Б', 'Ж', 'С'],
    -  STANDALONENARROWWEEKDAYS: ['Ж', 'Д', 'С', 'С', 'Б', 'Ж', 'С'],
    -  SHORTQUARTERS: ['Т1', 'Т2', 'Т3', 'Т4'],
    -  QUARTERS: ['1-інші тоқсан', '2-інші тоқсан',
    -    '3-інші тоқсан', '4-інші тоқсан'],
    -  AMPMS: ['таңертеңгі', 'түстен кейінгі'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'y, dd-MMM', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale kk_Cyrl_KZ.
    - */
    -goog.i18n.DateTimeSymbols_kk_Cyrl_KZ = goog.i18n.DateTimeSymbols_kk_Cyrl;
    -
    -
    -/**
    - * Date/time formatting symbols for locale kkj.
    - */
    -goog.i18n.DateTimeSymbols_kkj = {
    -  ERAS: ['BCE', 'CE'],
    -  ERANAMES: ['BCE', 'CE'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['pamba', 'wanja', 'mbiyɔ mɛndoŋgɔ', 'Nyɔlɔmbɔŋgɔ',
    -    'Mɔnɔ ŋgbanja', 'Nyaŋgwɛ ŋgbanja', 'kuŋgwɛ', 'fɛ', 'njapi',
    -    'nyukul', '11', 'ɓulɓusɛ'],
    -  STANDALONEMONTHS: ['pamba', 'wanja', 'mbiyɔ mɛndoŋgɔ', 'Nyɔlɔmbɔŋgɔ',
    -    'Mɔnɔ ŋgbanja', 'Nyaŋgwɛ ŋgbanja', 'kuŋgwɛ', 'fɛ', 'njapi',
    -    'nyukul', '11', 'ɓulɓusɛ'],
    -  SHORTMONTHS: ['pamba', 'wanja', 'mbiyɔ mɛndoŋgɔ', 'Nyɔlɔmbɔŋgɔ',
    -    'Mɔnɔ ŋgbanja', 'Nyaŋgwɛ ŋgbanja', 'kuŋgwɛ', 'fɛ', 'njapi',
    -    'nyukul', '11', 'ɓulɓusɛ'],
    -  STANDALONESHORTMONTHS: ['pamba', 'wanja', 'mbiyɔ mɛndoŋgɔ',
    -    'Nyɔlɔmbɔŋgɔ', 'Mɔnɔ ŋgbanja', 'Nyaŋgwɛ ŋgbanja', 'kuŋgwɛ',
    -    'fɛ', 'njapi', 'nyukul', '11', 'ɓulɓusɛ'],
    -  WEEKDAYS: ['sɔndi', 'lundi', 'mardi', 'mɛrkɛrɛdi', 'yedi', 'vaŋdɛrɛdi',
    -    'mɔnɔ sɔndi'],
    -  STANDALONEWEEKDAYS: ['sɔndi', 'lundi', 'mardi', 'mɛrkɛrɛdi', 'yedi',
    -    'vaŋdɛrɛdi', 'mɔnɔ sɔndi'],
    -  SHORTWEEKDAYS: ['sɔndi', 'lundi', 'mardi', 'mɛrkɛrɛdi', 'yedi',
    -    'vaŋdɛrɛdi', 'mɔnɔ sɔndi'],
    -  STANDALONESHORTWEEKDAYS: ['sɔndi', 'lundi', 'mardi', 'mɛrkɛrɛdi', 'yedi',
    -    'vaŋdɛrɛdi', 'mɔnɔ sɔndi'],
    -  NARROWWEEKDAYS: ['so', 'lu', 'ma', 'mɛ', 'ye', 'va', 'ms'],
    -  STANDALONENARROWWEEKDAYS: ['so', 'lu', 'ma', 'mɛ', 'ye', 'va', 'ms'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE dd MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale kkj_CM.
    - */
    -goog.i18n.DateTimeSymbols_kkj_CM = goog.i18n.DateTimeSymbols_kkj;
    -
    -
    -/**
    - * Date/time formatting symbols for locale kl.
    - */
    -goog.i18n.DateTimeSymbols_kl = {
    -  ERAS: ['Kr.in.si.', 'Kr.in.king.'],
    -  ERANAMES: ['Kristusip inunngornerata siornagut',
    -    'Kristusip inunngornerata kingornagut'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['januari', 'februari', 'martsi', 'aprili', 'maji', 'juni', 'juli',
    -    'augustusi', 'septemberi', 'oktoberi', 'novemberi', 'decemberi'],
    -  STANDALONEMONTHS: ['januari', 'februari', 'martsi', 'aprili', 'maji', 'juni',
    -    'juli', 'augustusi', 'septemberi', 'oktoberi', 'novemberi', 'decemberi'],
    -  SHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'aug', 'sep',
    -    'okt', 'nov', 'dec'],
    -  STANDALONESHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul',
    -    'aug', 'sep', 'okt', 'nov', 'dec'],
    -  WEEKDAYS: ['sabaat', 'ataasinngorneq', 'marlunngorneq', 'pingasunngorneq',
    -    'sisamanngorneq', 'tallimanngorneq', 'arfininngorneq'],
    -  STANDALONEWEEKDAYS: ['sabaat', 'ataasinngorneq', 'marlunngorneq',
    -    'pingasunngorneq', 'sisamanngorneq', 'tallimanngorneq', 'arfininngorneq'],
    -  SHORTWEEKDAYS: ['sab', 'ata', 'mar', 'pin', 'sis', 'tal', 'arf'],
    -  STANDALONESHORTWEEKDAYS: ['sab', 'ata', 'mar', 'pin', 'sis', 'tal', 'arf'],
    -  NARROWWEEKDAYS: ['S', 'A', 'M', 'P', 'S', 'T', 'A'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'A', 'M', 'P', 'S', 'T', 'A'],
    -  SHORTQUARTERS: ['S1', 'S2', 'S3', 'S4'],
    -  QUARTERS: ['ukiup sisamararterutaa 1', 'ukiup sisamararterutaa 2',
    -    'ukiup sisamararterutaa 3', 'ukiup sisamararterutaa 4'],
    -  AMPMS: ['ulloqeqqata-tungaa', 'ulloqeqqata-kingorna'],
    -  DATEFORMATS: ['EEEE dd MMMM y', 'dd MMMM y', 'MMM dd, y', 'y-MM-dd'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale kl_GL.
    - */
    -goog.i18n.DateTimeSymbols_kl_GL = goog.i18n.DateTimeSymbols_kl;
    -
    -
    -/**
    - * Date/time formatting symbols for locale kln.
    - */
    -goog.i18n.DateTimeSymbols_kln = {
    -  ERAS: ['AM', 'KO'],
    -  ERANAMES: ['Amait kesich Jesu', 'Kokakesich Jesu'],
    -  NARROWMONTHS: ['M', 'N', 'K', 'I', 'N', 'W', 'R', 'K', 'B', 'E', 'K', 'K'],
    -  STANDALONENARROWMONTHS: ['M', 'N', 'K', 'I', 'N', 'W', 'R', 'K', 'B', 'E',
    -    'K', 'K'],
    -  MONTHS: ['Mulgul', 'Ng’atyato', 'Kiptamo', 'Iwat kut', 'Ng’eiyet', 'Waki',
    -    'Roptui', 'Kipkogaga', 'Buret', 'Epeso', 'Kipsunde netai',
    -    'Kipsunde nebo aeng'],
    -  STANDALONEMONTHS: ['Mulgul', 'Ng’atyato', 'Kiptamo', 'Iwat kut',
    -    'Ng’eiyet', 'Waki', 'Roptui', 'Kipkogaga', 'Buret', 'Epeso',
    -    'Kipsunde netai', 'Kipsunde nebo aeng'],
    -  SHORTMONTHS: ['Mul', 'Nga', 'Kip', 'Iwa', 'Nge', 'Wak', 'Rop', 'Kog', 'Bur',
    -    'Epe', 'Tai', 'Aen'],
    -  STANDALONESHORTMONTHS: ['Mul', 'Nga', 'Kip', 'Iwa', 'Nge', 'Wak', 'Rop',
    -    'Kog', 'Bur', 'Epe', 'Tai', 'Aen'],
    -  WEEKDAYS: ['Betutab tisap', 'Betut netai', 'Betutab aeng’', 'Betutab somok',
    -    'Betutab ang’wan', 'Betutab mut', 'Betutab lo'],
    -  STANDALONEWEEKDAYS: ['Betutab tisap', 'Betut netai', 'Betutab aeng’',
    -    'Betutab somok', 'Betutab ang’wan', 'Betutab mut', 'Betutab lo'],
    -  SHORTWEEKDAYS: ['Tis', 'Tai', 'Aen', 'Som', 'Ang', 'Mut', 'Loh'],
    -  STANDALONESHORTWEEKDAYS: ['Tis', 'Tai', 'Aen', 'Som', 'Ang', 'Mut', 'Loh'],
    -  NARROWWEEKDAYS: ['T', 'T', 'A', 'S', 'A', 'M', 'L'],
    -  STANDALONENARROWWEEKDAYS: ['T', 'T', 'A', 'S', 'A', 'M', 'L'],
    -  SHORTQUARTERS: ['R1', 'R2', 'R3', 'R4'],
    -  QUARTERS: ['Robo netai', 'Robo nebo aeng’', 'Robo nebo somok',
    -    'Robo nebo ang’wan'],
    -  AMPMS: ['Beet', 'Kemo'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale kln_KE.
    - */
    -goog.i18n.DateTimeSymbols_kln_KE = goog.i18n.DateTimeSymbols_kln;
    -
    -
    -/**
    - * Date/time formatting symbols for locale km_KH.
    - */
    -goog.i18n.DateTimeSymbols_km_KH = {
    -  ERAS: ['មុន គ.ស.', 'គ.ស.'],
    -  ERANAMES: ['មុន​គ្រិស្តសករាជ',
    -    'គ្រិស្តសករាជ'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['មករា', 'កុម្ភៈ', 'មីនា', 'មេសា',
    -    'ឧសភា', 'មិថុនា', 'កក្កដា', 'សីហា',
    -    'កញ្ញា', 'តុលា', 'វិច្ឆិកា',
    -    'ធ្នូ'],
    -  STANDALONEMONTHS: ['មករា', 'កុម្ភៈ', 'មីនា',
    -    'មេសា', 'ឧសភា', 'មិថុនា', 'កក្កដា',
    -    'សីហា', 'កញ្ញា', 'តុលា',
    -    'វិច្ឆិកា', 'ធ្នូ'],
    -  SHORTMONTHS: ['មករា', 'កុម្ភៈ', 'មីនា',
    -    'មេសា', 'ឧសភា', 'មិថុនា', 'កក្កដា',
    -    'សីហា', 'កញ្ញា', 'តុលា',
    -    'វិច្ឆិកា', 'ធ្នូ'],
    -  STANDALONESHORTMONTHS: ['មករា', 'កុម្ភៈ', 'មីនា',
    -    'មេសា', 'ឧសភា', 'មិថុនា', 'កក្កដា',
    -    'សីហា', 'កញ្ញា', 'តុលា',
    -    'វិច្ឆិកា', 'ធ្នូ'],
    -  WEEKDAYS: ['អាទិត្យ', 'ចន្ទ', 'អង្គារ',
    -    'ពុធ', 'ព្រហស្បតិ៍', 'សុក្រ',
    -    'សៅរ៍'],
    -  STANDALONEWEEKDAYS: ['អាទិត្យ', 'ចន្ទ',
    -    'អង្គារ', 'ពុធ', 'ព្រហស្បតិ៍',
    -    'សុក្រ', 'សៅរ៍'],
    -  SHORTWEEKDAYS: ['អាទិត្យ', 'ចន្ទ', 'អង្គារ',
    -    'ពុធ', 'ព្រហស្បតិ៍', 'សុក្រ',
    -    'សៅរ៍'],
    -  STANDALONESHORTWEEKDAYS: ['អាទិត្យ', 'ចន្ទ',
    -    'អង្គារ', 'ពុធ', 'ព្រហស្បតិ៍',
    -    'សុក្រ', 'សៅរ៍'],
    -  NARROWWEEKDAYS: ['1', '2', '3', '4', '5', '6', '7'],
    -  STANDALONENARROWWEEKDAYS: ['1', '2', '3', '4', '5', '6', '7'],
    -  SHORTQUARTERS: ['ត្រីមាសទី ១',
    -    'ត្រីមាសទី ២', 'ត្រីមាសទី ៣',
    -    'ត្រីមាសទី ៤'],
    -  QUARTERS: ['ត្រីមាសទី ១',
    -    'ត្រីមាសទី ២', 'ត្រីមាសទី ៣',
    -    'ត្រីមាសទី ៤'],
    -  AMPMS: ['ព្រឹក', 'ល្ងាច'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} នៅ {0}', '{1} នៅ {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale kn_IN.
    - */
    -goog.i18n.DateTimeSymbols_kn_IN = {
    -  ERAS: ['ಕ್ರಿ.ಪೂ', 'ಕ್ರಿ.ಶ'],
    -  ERANAMES: ['ಕ್ರಿಸ್ತ ಪೂರ್ವ',
    -    'ಕ್ರಿಸ್ತ ಶಕ'],
    -  NARROWMONTHS: ['ಜ', 'ಫೆ', 'ಮಾ', 'ಏ', 'ಮೇ', 'ಜೂ', 'ಜು',
    -    'ಆ', 'ಸೆ', 'ಅ', 'ನ', 'ಡಿ'],
    -  STANDALONENARROWMONTHS: ['ಜ', 'ಫೆ', 'ಮಾ', 'ಏ', 'ಮೇ', 'ಜೂ',
    -    'ಜು', 'ಆ', 'ಸೆ', 'ಅ', 'ನ', 'ಡಿ'],
    -  MONTHS: ['ಜನವರಿ', 'ಫೆಬ್ರವರಿ', 'ಮಾರ್ಚ್',
    -    'ಏಪ್ರಿಲ್', 'ಮೇ', 'ಜೂನ್', 'ಜುಲೈ',
    -    'ಆಗಸ್ಟ್', 'ಸೆಪ್ಟೆಂಬರ್',
    -    'ಅಕ್ಟೋಬರ್', 'ನವೆಂಬರ್',
    -    'ಡಿಸೆಂಬರ್'],
    -  STANDALONEMONTHS: ['ಜನವರಿ', 'ಫೆಬ್ರವರಿ',
    -    'ಮಾರ್ಚ್', 'ಏಪ್ರಿಲ್', 'ಮೇ', 'ಜೂನ್',
    -    'ಜುಲೈ', 'ಆಗಸ್ಟ್', 'ಸೆಪ್ಟೆಂಬರ್',
    -    'ಅಕ್ಟೋಬರ್', 'ನವೆಂಬರ್',
    -    'ಡಿಸೆಂಬರ್'],
    -  SHORTMONTHS: ['ಜನ', 'ಫೆಬ್ರ', 'ಮಾರ್ಚ್',
    -    'ಏಪ್ರಿ', 'ಮೇ', 'ಜೂನ್', 'ಜುಲೈ', 'ಆಗ',
    -    'ಸೆಪ್ಟೆಂ', 'ಅಕ್ಟೋ', 'ನವೆಂ',
    -    'ಡಿಸೆಂ'],
    -  STANDALONESHORTMONTHS: ['ಜನ', 'ಫೆಬ್ರ', 'ಮಾರ್ಚ್',
    -    'ಏಪ್ರಿ', 'ಮೇ', 'ಜೂನ್', 'ಜುಲೈ', 'ಆಗ',
    -    'ಸೆಪ್ಟೆಂ', 'ಅಕ್ಟೋ', 'ನವೆಂ',
    -    'ಡಿಸೆಂ'],
    -  WEEKDAYS: ['ಭಾನುವಾರ', 'ಸೋಮವಾರ',
    -    'ಮಂಗಳವಾರ', 'ಬುಧವಾರ', 'ಗುರುವಾರ',
    -    'ಶುಕ್ರವಾರ', 'ಶನಿವಾರ'],
    -  STANDALONEWEEKDAYS: ['ಭಾನುವಾರ', 'ಸೋಮವಾರ',
    -    'ಮಂಗಳವಾರ', 'ಬುಧವಾರ', 'ಗುರುವಾರ',
    -    'ಶುಕ್ರವಾರ', 'ಶನಿವಾರ'],
    -  SHORTWEEKDAYS: ['ಭಾನು', 'ಸೋಮ', 'ಮಂಗಳ', 'ಬುಧ',
    -    'ಗುರು', 'ಶುಕ್ರ', 'ಶನಿ'],
    -  STANDALONESHORTWEEKDAYS: ['ಭಾನು', 'ಸೋಮ', 'ಮಂಗಳ',
    -    'ಬುಧ', 'ಗುರು', 'ಶುಕ್ರ', 'ಶನಿ'],
    -  NARROWWEEKDAYS: ['ಭಾ', 'ಸೋ', 'ಮಂ', 'ಬು', 'ಗು', 'ಶು',
    -    'ಶ'],
    -  STANDALONENARROWWEEKDAYS: ['ಭಾ', 'ಸೋ', 'ಮಂ', 'ಬು', 'ಗು',
    -    'ಶು', 'ಶ'],
    -  SHORTQUARTERS: ['ತ್ರೈ 1', 'ತ್ರೈ 2', 'ತ್ರೈ 3',
    -    'ತ್ರೈ 4'],
    -  QUARTERS: ['1ನೇ ತ್ರೈಮಾಸಿಕ',
    -    '2ನೇ ತ್ರೈಮಾಸಿಕ',
    -    '3ನೇ ತ್ರೈಮಾಸಿಕ',
    -    '4ನೇ ತ್ರೈಮಾಸಿಕ'],
    -  AMPMS: ['ಪೂರ್ವಾಹ್ನ', 'ಅಪರಾಹ್ನ'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['hh:mm:ss a zzzz', 'hh:mm:ss a z', 'hh:mm:ss a', 'hh:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [6, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ko_KP.
    - */
    -goog.i18n.DateTimeSymbols_ko_KP = {
    -  ERAS: ['기원전', '서기'],
    -  ERANAMES: ['기원전', '서기'],
    -  NARROWMONTHS: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월',
    -    '9월', '10월', '11월', '12월'],
    -  STANDALONENARROWMONTHS: ['1월', '2월', '3월', '4월', '5월', '6월',
    -    '7월', '8월', '9월', '10월', '11월', '12월'],
    -  MONTHS: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월',
    -    '9월', '10월', '11월', '12월'],
    -  STANDALONEMONTHS: ['1월', '2월', '3월', '4월', '5월', '6월', '7월',
    -    '8월', '9월', '10월', '11월', '12월'],
    -  SHORTMONTHS: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월',
    -    '9월', '10월', '11월', '12월'],
    -  STANDALONESHORTMONTHS: ['1월', '2월', '3월', '4월', '5월', '6월',
    -    '7월', '8월', '9월', '10월', '11월', '12월'],
    -  WEEKDAYS: ['일요일', '월요일', '화요일', '수요일', '목요일',
    -    '금요일', '토요일'],
    -  STANDALONEWEEKDAYS: ['일요일', '월요일', '화요일', '수요일',
    -    '목요일', '금요일', '토요일'],
    -  SHORTWEEKDAYS: ['일', '월', '화', '수', '목', '금', '토'],
    -  STANDALONESHORTWEEKDAYS: ['일', '월', '화', '수', '목', '금', '토'],
    -  NARROWWEEKDAYS: ['일', '월', '화', '수', '목', '금', '토'],
    -  STANDALONENARROWWEEKDAYS: ['일', '월', '화', '수', '목', '금', '토'],
    -  SHORTQUARTERS: ['1분기', '2분기', '3분기', '4분기'],
    -  QUARTERS: ['제 1/4분기', '제 2/4분기', '제 3/4분기',
    -    '제 4/4분기'],
    -  AMPMS: ['오전', '오후'],
    -  DATEFORMATS: ['y년 M월 d일 EEEE', 'y년 M월 d일', 'y. M. d.',
    -    'yy. M. d.'],
    -  TIMEFORMATS: ['a h시 m분 s초 zzzz', 'a h시 m분 s초 z', 'a h:mm:ss',
    -    'a h:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ko_KR.
    - */
    -goog.i18n.DateTimeSymbols_ko_KR = {
    -  ERAS: ['기원전', '서기'],
    -  ERANAMES: ['기원전', '서기'],
    -  NARROWMONTHS: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월',
    -    '9월', '10월', '11월', '12월'],
    -  STANDALONENARROWMONTHS: ['1월', '2월', '3월', '4월', '5월', '6월',
    -    '7월', '8월', '9월', '10월', '11월', '12월'],
    -  MONTHS: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월',
    -    '9월', '10월', '11월', '12월'],
    -  STANDALONEMONTHS: ['1월', '2월', '3월', '4월', '5월', '6월', '7월',
    -    '8월', '9월', '10월', '11월', '12월'],
    -  SHORTMONTHS: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월',
    -    '9월', '10월', '11월', '12월'],
    -  STANDALONESHORTMONTHS: ['1월', '2월', '3월', '4월', '5월', '6월',
    -    '7월', '8월', '9월', '10월', '11월', '12월'],
    -  WEEKDAYS: ['일요일', '월요일', '화요일', '수요일', '목요일',
    -    '금요일', '토요일'],
    -  STANDALONEWEEKDAYS: ['일요일', '월요일', '화요일', '수요일',
    -    '목요일', '금요일', '토요일'],
    -  SHORTWEEKDAYS: ['일', '월', '화', '수', '목', '금', '토'],
    -  STANDALONESHORTWEEKDAYS: ['일', '월', '화', '수', '목', '금', '토'],
    -  NARROWWEEKDAYS: ['일', '월', '화', '수', '목', '금', '토'],
    -  STANDALONENARROWWEEKDAYS: ['일', '월', '화', '수', '목', '금', '토'],
    -  SHORTQUARTERS: ['1분기', '2분기', '3분기', '4분기'],
    -  QUARTERS: ['제 1/4분기', '제 2/4분기', '제 3/4분기',
    -    '제 4/4분기'],
    -  AMPMS: ['오전', '오후'],
    -  DATEFORMATS: ['y년 M월 d일 EEEE', 'y년 M월 d일', 'y. M. d.',
    -    'yy. M. d.'],
    -  TIMEFORMATS: ['a h시 m분 s초 zzzz', 'a h시 m분 s초 z', 'a h:mm:ss',
    -    'a h:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale kok.
    - */
    -goog.i18n.DateTimeSymbols_kok = {
    -  ERAS: ['क्रिस्तपूर्व',
    -    'क्रिस्तशखा'],
    -  ERANAMES: ['क्रिस्तपूर्व',
    -    'क्रिस्तशखा'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['जानेवारी', 'फेब्रुवारी',
    -    'मार्च', 'एप्रिल', 'मे', 'जून',
    -    'जुलै', 'ओगस्ट', 'सेप्टेंबर',
    -    'ओक्टोबर', 'नोव्हेंबर',
    -    'डिसेंबर'],
    -  STANDALONEMONTHS: ['जानेवारी',
    -    'फेब्रुवारी', 'मार्च', 'एप्रिल',
    -    'मे', 'जून', 'जुलै', 'ओगस्ट',
    -    'सेप्टेंबर', 'ओक्टोबर',
    -    'नोव्हेंबर', 'डिसेंबर'],
    -  SHORTMONTHS: ['जानेवारी', 'फेब्रुवारी',
    -    'मार्च', 'एप्रिल', 'मे', 'जून',
    -    'जुलै', 'ओगस्ट', 'सेप्टेंबर',
    -    'ओक्टोबर', 'नोव्हेंबर',
    -    'डिसेंबर'],
    -  STANDALONESHORTMONTHS: ['जानेवारी',
    -    'फेब्रुवारी', 'मार्च', 'एप्रिल',
    -    'मे', 'जून', 'जुलै', 'ओगस्ट',
    -    'सेप्टेंबर', 'ओक्टोबर',
    -    'नोव्हेंबर', 'डिसेंबर'],
    -  WEEKDAYS: ['आदित्यवार', 'सोमवार',
    -    'मंगळार', 'बुधवार', 'गुरुवार',
    -    'शुक्रवार', 'शनिवार'],
    -  STANDALONEWEEKDAYS: ['आदित्यवार', 'सोमवार',
    -    'मंगळार', 'बुधवार', 'गुरुवार',
    -    'शुक्रवार', 'शनिवार'],
    -  SHORTWEEKDAYS: ['रवि', 'सोम', 'मंगळ', 'बुध',
    -    'गुरु', 'शुक्र', 'शनि'],
    -  STANDALONESHORTWEEKDAYS: ['रवि', 'सोम', 'मंगळ',
    -    'बुध', 'गुरु', 'शुक्र', 'शनि'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['म.पू.', 'म.नं.'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'dd-MM-y', 'd-M-yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [6, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale kok_IN.
    - */
    -goog.i18n.DateTimeSymbols_kok_IN = goog.i18n.DateTimeSymbols_kok;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ks.
    - */
    -goog.i18n.DateTimeSymbols_ks = {
    -  ZERODIGIT: 0x06F0,
    -  ERAS: ['بی سی', 'اے ڈی'],
    -  ERANAMES: ['قبٕل مسیٖح', 'عیٖسوی سنہٕ'],
    -  NARROWMONTHS: ['ج', 'ف', 'م', 'ا', 'م', 'ج', 'ج', 'ا', 'س', 'س',
    -    'ا', 'ن'],
    -  STANDALONENARROWMONTHS: ['ج', 'ف', 'م', 'ا', 'م', 'ج', 'ج', 'ا', 'س',
    -    'س', 'ا', 'ن'],
    -  MONTHS: ['جنؤری', 'فرؤری', 'مارٕچ', 'اپریل', 'میٔ',
    -    'جوٗن', 'جوٗلایی', 'اگست', 'ستمبر', 'اکتوٗبر',
    -    'نومبر', 'دسمبر'],
    -  STANDALONEMONTHS: ['جنؤری', 'فرؤری', 'مارٕچ', 'اپریل',
    -    'میٔ', 'جوٗن', 'جوٗلایی', 'اگست', 'ستمبر',
    -    'اکتوٗبر', 'نومبر', 'دسمبر'],
    -  SHORTMONTHS: ['جنؤری', 'فرؤری', 'مارٕچ', 'اپریل',
    -    'میٔ', 'جوٗن', 'جوٗلایی', 'اگست', 'ستمبر',
    -    'اکتوٗبر', 'نومبر', 'دسمبر'],
    -  STANDALONESHORTMONTHS: ['جنؤری', 'فرؤری', 'مارٕچ',
    -    'اپریل', 'میٔ', 'جوٗن', 'جوٗلایی', 'اگست',
    -    'ستمبر', 'اکتوٗبر', 'نومبر', 'دسمبر'],
    -  WEEKDAYS: ['اَتھوار', 'ژٔنٛدرٕروار', 'بوٚموار',
    -    'بودوار', 'برٛٮ۪سوار', 'جُمہ', 'بٹوار'],
    -  STANDALONEWEEKDAYS: ['اَتھوار', 'ژٔنٛدرٕروار',
    -    'بوٚموار', 'بودوار', 'برٛٮ۪سوار', 'جُمہ',
    -    'بٹوار'],
    -  SHORTWEEKDAYS: ['آتھوار', 'ژٔنٛدٕروار', 'بوٚموار',
    -    'بودوار', 'برٛٮ۪سوار', 'جُمہ', 'بٹوار'],
    -  STANDALONESHORTWEEKDAYS: ['آتھوار', 'ژٔنٛدٕروار',
    -    'بوٚموار', 'بودوار', 'برٛٮ۪سوار', 'جُمہ',
    -    'بٹوار'],
    -  NARROWWEEKDAYS: ['ا', 'ژ', 'ب', 'ب', 'ب', 'ج', 'ب'],
    -  STANDALONENARROWWEEKDAYS: ['ا', 'ژ', 'ب', 'ب', 'ب', 'ج', 'ب'],
    -  SHORTQUARTERS: ['ژۄباگ', 'دوٚیِم ژۄباگ',
    -    'ترٛیِم ژۄباگ', 'ژوٗرِم ژۄباگ'],
    -  QUARTERS: ['گۄڑنیُک ژۄباگ', 'دوٚیِم ژۄباگ',
    -    'ترٛیِم ژۄباگ', 'ژوٗرِم ژۄباگ'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [6, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ks_Arab.
    - */
    -goog.i18n.DateTimeSymbols_ks_Arab = goog.i18n.DateTimeSymbols_ks;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ks_Arab_IN.
    - */
    -goog.i18n.DateTimeSymbols_ks_Arab_IN = goog.i18n.DateTimeSymbols_ks;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ksb.
    - */
    -goog.i18n.DateTimeSymbols_ksb = {
    -  ERAS: ['KK', 'BK'],
    -  ERANAMES: ['Kabla ya Klisto', 'Baada ya Klisto'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januali', 'Febluali', 'Machi', 'Aplili', 'Mei', 'Juni', 'Julai',
    -    'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    -  STANDALONEMONTHS: ['Januali', 'Febluali', 'Machi', 'Aplili', 'Mei', 'Juni',
    -    'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep',
    -    'Okt', 'Nov', 'Des'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul',
    -    'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
    -  WEEKDAYS: ['Jumaapii', 'Jumaatatu', 'Jumaane', 'Jumaatano', 'Alhamisi',
    -    'Ijumaa', 'Jumaamosi'],
    -  STANDALONEWEEKDAYS: ['Jumaapii', 'Jumaatatu', 'Jumaane', 'Jumaatano',
    -    'Alhamisi', 'Ijumaa', 'Jumaamosi'],
    -  SHORTWEEKDAYS: ['Jpi', 'Jtt', 'Jmn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
    -  STANDALONESHORTWEEKDAYS: ['Jpi', 'Jtt', 'Jmn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
    -  NARROWWEEKDAYS: ['2', '3', '4', '5', 'A', 'I', '1'],
    -  STANDALONENARROWWEEKDAYS: ['2', '3', '4', '5', 'A', 'I', '1'],
    -  SHORTQUARTERS: ['L1', 'L2', 'L3', 'L4'],
    -  QUARTERS: ['Lobo ya bosi', 'Lobo ya mbii', 'Lobo ya nnd’atu',
    -    'Lobo ya nne'],
    -  AMPMS: ['makeo', 'nyiaghuo'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ksb_TZ.
    - */
    -goog.i18n.DateTimeSymbols_ksb_TZ = goog.i18n.DateTimeSymbols_ksb;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ksf.
    - */
    -goog.i18n.DateTimeSymbols_ksf = {
    -  ERAS: ['d.Y.', 'k.Y.'],
    -  ERANAMES: ['di Yɛ́sus aká yálɛ', 'cámɛɛn kǝ kǝbɔpka Y'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['ŋwíí a ntɔ́ntɔ', 'ŋwíí akǝ bɛ́ɛ', 'ŋwíí akǝ ráá',
    -    'ŋwíí akǝ nin', 'ŋwíí akǝ táan', 'ŋwíí akǝ táafɔk',
    -    'ŋwíí akǝ táabɛɛ', 'ŋwíí akǝ táaraa', 'ŋwíí akǝ táanin',
    -    'ŋwíí akǝ ntɛk', 'ŋwíí akǝ ntɛk di bɔ́k',
    -    'ŋwíí akǝ ntɛk di bɛ́ɛ'],
    -  STANDALONEMONTHS: ['ŋwíí a ntɔ́ntɔ', 'ŋwíí akǝ bɛ́ɛ',
    -    'ŋwíí akǝ ráá', 'ŋwíí akǝ nin', 'ŋwíí akǝ táan',
    -    'ŋwíí akǝ táafɔk', 'ŋwíí akǝ táabɛɛ', 'ŋwíí akǝ táaraa',
    -    'ŋwíí akǝ táanin', 'ŋwíí akǝ ntɛk',
    -    'ŋwíí akǝ ntɛk di bɔ́k', 'ŋwíí akǝ ntɛk di bɛ́ɛ'],
    -  SHORTMONTHS: ['ŋ1', 'ŋ2', 'ŋ3', 'ŋ4', 'ŋ5', 'ŋ6', 'ŋ7', 'ŋ8', 'ŋ9',
    -    'ŋ10', 'ŋ11', 'ŋ12'],
    -  STANDALONESHORTMONTHS: ['ŋ1', 'ŋ2', 'ŋ3', 'ŋ4', 'ŋ5', 'ŋ6', 'ŋ7',
    -    'ŋ8', 'ŋ9', 'ŋ10', 'ŋ11', 'ŋ12'],
    -  WEEKDAYS: ['sɔ́ndǝ', 'lǝndí', 'maadí', 'mɛkrɛdí', 'jǝǝdí',
    -    'júmbá', 'samdí'],
    -  STANDALONEWEEKDAYS: ['sɔ́ndǝ', 'lǝndí', 'maadí', 'mɛkrɛdí',
    -    'jǝǝdí', 'júmbá', 'samdí'],
    -  SHORTWEEKDAYS: ['sɔ́n', 'lǝn', 'maa', 'mɛk', 'jǝǝ', 'júm', 'sam'],
    -  STANDALONESHORTWEEKDAYS: ['sɔ́n', 'lǝn', 'maa', 'mɛk', 'jǝǝ', 'júm',
    -    'sam'],
    -  NARROWWEEKDAYS: ['s', 'l', 'm', 'm', 'j', 'j', 's'],
    -  STANDALONENARROWWEEKDAYS: ['s', 'l', 'm', 'm', 'j', 'j', 's'],
    -  SHORTQUARTERS: ['i1', 'i2', 'i3', 'i4'],
    -  QUARTERS: ['id́ɛ́n kǝbǝk kǝ ntɔ́ntɔ́',
    -    'idɛ́n kǝbǝk kǝ kǝbɛ́ɛ', 'idɛ́n kǝbǝk kǝ kǝráá',
    -    'idɛ́n kǝbǝk kǝ kǝnin'],
    -  AMPMS: ['sárúwá', 'cɛɛ́nko'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ksf_CM.
    - */
    -goog.i18n.DateTimeSymbols_ksf_CM = goog.i18n.DateTimeSymbols_ksf;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ksh.
    - */
    -goog.i18n.DateTimeSymbols_ksh = {
    -  ERAS: ['v. Chr.', 'n. Chr.'],
    -  ERANAMES: ['vür Chrestus', 'noh Chrestus'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Jannewa', 'Fäbrowa', 'Määz', 'Aprell', 'Mäi', 'Juuni', 'Juuli',
    -    'Oujoß', 'Septämber', 'Oktoober', 'Novämber', 'Dezämber'],
    -  STANDALONEMONTHS: ['Jannewa', 'Fäbrowa', 'Määz', 'Aprell', 'Mäi', 'Juuni',
    -    'Juuli', 'Oujoß', 'Septämber', 'Oktoober', 'Novämber', 'Dezämber'],
    -  SHORTMONTHS: ['Jan', 'Fäb', 'Mäz', 'Apr', 'Mäi', 'Jun', 'Jul', 'Ouj',
    -    'Säp', 'Okt', 'Nov', 'Dez'],
    -  STANDALONESHORTMONTHS: ['Jan.', 'Fäb.', 'Mäz.', 'Apr.', 'Mäi', 'Jun.',
    -    'Jul.', 'Ouj.', 'Säp.', 'Okt.', 'Nov.', 'Dez.'],
    -  WEEKDAYS: ['Sunndaach', 'Moondaach', 'Dinnsdaach', 'Metwoch', 'Dunnersdaach',
    -    'Friidaach', 'Samsdaach'],
    -  STANDALONEWEEKDAYS: ['Sunndaach', 'Moondaach', 'Dinnsdaach', 'Metwoch',
    -    'Dunnersdaach', 'Friidaach', 'Samsdaach'],
    -  SHORTWEEKDAYS: ['Su.', 'Mo.', 'Di.', 'Me.', 'Du.', 'Fr.', 'Sa.'],
    -  STANDALONESHORTWEEKDAYS: ['Su.', 'Mo.', 'Di.', 'Me.', 'Du.', 'Fr.', 'Sa.'],
    -  NARROWWEEKDAYS: ['S', 'M', 'D', 'M', 'D', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'D', 'M', 'D', 'F', 'S'],
    -  SHORTQUARTERS: ['1.Q.', '2.Q.', '3.Q.', '4.Q.'],
    -  QUARTERS: ['1. Quattaal', '2. Quattaal', '3. Quattaal', '4. Quattaal'],
    -  AMPMS: ['Uhr vörmiddaachs', 'Uhr nommendaachs'],
    -  DATEFORMATS: ['EEEE, \'dä\' d. MMMM y', 'd. MMMM y', 'd. MMM. y', 'd. M. y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ksh_DE.
    - */
    -goog.i18n.DateTimeSymbols_ksh_DE = goog.i18n.DateTimeSymbols_ksh;
    -
    -
    -/**
    - * Date/time formatting symbols for locale kw.
    - */
    -goog.i18n.DateTimeSymbols_kw = {
    -  ERAS: ['RC', 'AD'],
    -  ERANAMES: ['RC', 'AD'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['Mys Genver', 'Mys Whevrel', 'Mys Merth', 'Mys Ebrel', 'Mys Me',
    -    'Mys Efan', 'Mys Gortheren', 'Mye Est', 'Mys Gwyngala', 'Mys Hedra',
    -    'Mys Du', 'Mys Kevardhu'],
    -  STANDALONEMONTHS: ['Mys Genver', 'Mys Whevrel', 'Mys Merth', 'Mys Ebrel',
    -    'Mys Me', 'Mys Efan', 'Mys Gortheren', 'Mye Est', 'Mys Gwyngala',
    -    'Mys Hedra', 'Mys Du', 'Mys Kevardhu'],
    -  SHORTMONTHS: ['Gen', 'Whe', 'Mer', 'Ebr', 'Me', 'Efn', 'Gor', 'Est', 'Gwn',
    -    'Hed', 'Du', 'Kev'],
    -  STANDALONESHORTMONTHS: ['Gen', 'Whe', 'Mer', 'Ebr', 'Me', 'Efn', 'Gor', 'Est',
    -    'Gwn', 'Hed', 'Du', 'Kev'],
    -  WEEKDAYS: ['De Sul', 'De Lun', 'De Merth', 'De Merher', 'De Yow', 'De Gwener',
    -    'De Sadorn'],
    -  STANDALONEWEEKDAYS: ['De Sul', 'De Lun', 'De Merth', 'De Merher', 'De Yow',
    -    'De Gwener', 'De Sadorn'],
    -  SHORTWEEKDAYS: ['Sul', 'Lun', 'Mth', 'Mhr', 'Yow', 'Gwe', 'Sad'],
    -  STANDALONESHORTWEEKDAYS: ['Sul', 'Lun', 'Mth', 'Mhr', 'Yow', 'Gwe', 'Sad'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['a.m.', 'p.m.'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale kw_GB.
    - */
    -goog.i18n.DateTimeSymbols_kw_GB = goog.i18n.DateTimeSymbols_kw;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ky_Cyrl.
    - */
    -goog.i18n.DateTimeSymbols_ky_Cyrl = {
    -  ERAS: ['б.з.ч.', 'б.з.'],
    -  ERANAMES: ['биздин заманга чейин',
    -    'биздин заман'],
    -  NARROWMONTHS: ['Я', 'Ф', 'М', 'А', 'М', 'И', 'И', 'А', 'С', 'О',
    -    'Н', 'Д'],
    -  STANDALONENARROWMONTHS: ['Я', 'Ф', 'М', 'А', 'М', 'И', 'И', 'А', 'С',
    -    'О', 'Н', 'Д'],
    -  MONTHS: ['январь', 'февраль', 'март', 'апрель',
    -    'май', 'июнь', 'июль', 'август', 'сентябрь',
    -    'октябрь', 'ноябрь', 'декабрь'],
    -  STANDALONEMONTHS: ['Январь', 'Февраль', 'Март',
    -    'Апрель', 'Май', 'Июнь', 'Июль', 'Август',
    -    'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'],
    -  SHORTMONTHS: ['янв.', 'фев.', 'мар.', 'апр.', 'май', 'июн.',
    -    'июл.', 'авг.', 'сен.', 'окт.', 'ноя.', 'дек.'],
    -  STANDALONESHORTMONTHS: ['Янв', 'Фев', 'Мар', 'Апр', 'Май',
    -    'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'],
    -  WEEKDAYS: ['жекшемби', 'дүйшөмбү', 'шейшемби',
    -    'шаршемби', 'бейшемби', 'жума', 'ишемби'],
    -  STANDALONEWEEKDAYS: ['жекшемби', 'дүйшөмбү',
    -    'шейшемби', 'шаршемби', 'бейшемби', 'жума',
    -    'ишемби'],
    -  SHORTWEEKDAYS: ['жек.', 'дүй.', 'шейш.', 'шарш.', 'бейш.',
    -    'жума', 'ишм.'],
    -  STANDALONESHORTWEEKDAYS: ['жек.', 'дүй.', 'шейш.', 'шарш.',
    -    'бейш.', 'жума', 'ишм.'],
    -  NARROWWEEKDAYS: ['Ж', 'Д', 'Ш', 'Ш', 'Б', 'Ж', 'И'],
    -  STANDALONENARROWWEEKDAYS: ['Ж', 'Д', 'Ш', 'Ш', 'Б', 'Ж', 'И'],
    -  SHORTQUARTERS: ['1-чей.', '2-чей.', '3-чей.', '4-чей.'],
    -  QUARTERS: ['1-чейрек', '2-чейрек', '3-чейрек',
    -    '4-чейрек'],
    -  AMPMS: ['таңкы', 'түштөн кийин'],
    -  DATEFORMATS: ['EEEE, d-MMMM, y-\'ж\'.', 'y MMMM d', 'y MMM d', 'dd.MM.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ky_Cyrl_KG.
    - */
    -goog.i18n.DateTimeSymbols_ky_Cyrl_KG = goog.i18n.DateTimeSymbols_ky_Cyrl;
    -
    -
    -/**
    - * Date/time formatting symbols for locale lag.
    - */
    -goog.i18n.DateTimeSymbols_lag = {
    -  ERAS: ['KSA', 'KA'],
    -  ERANAMES: ['Kɨrɨsitʉ sɨ anavyaal', 'Kɨrɨsitʉ akavyaalwe'],
    -  NARROWMONTHS: ['F', 'N', 'K', 'I', 'I', 'I', 'M', 'V', 'S', 'I', 'S', 'S'],
    -  STANDALONENARROWMONTHS: ['F', 'N', 'K', 'I', 'I', 'I', 'M', 'V', 'S', 'I',
    -    'S', 'S'],
    -  MONTHS: ['Kʉfúngatɨ', 'Kʉnaanɨ', 'Kʉkeenda', 'Kwiikumi',
    -    'Kwiinyambála', 'Kwiidwaata', 'Kʉmʉʉnchɨ', 'Kʉvɨɨrɨ', 'Kʉsaatʉ',
    -    'Kwiinyi', 'Kʉsaano', 'Kʉsasatʉ'],
    -  STANDALONEMONTHS: ['Kʉfúngatɨ', 'Kʉnaanɨ', 'Kʉkeenda', 'Kwiikumi',
    -    'Kwiinyambála', 'Kwiidwaata', 'Kʉmʉʉnchɨ', 'Kʉvɨɨrɨ', 'Kʉsaatʉ',
    -    'Kwiinyi', 'Kʉsaano', 'Kʉsasatʉ'],
    -  SHORTMONTHS: ['Fúngatɨ', 'Naanɨ', 'Keenda', 'Ikúmi', 'Inyambala',
    -    'Idwaata', 'Mʉʉnchɨ', 'Vɨɨrɨ', 'Saatʉ', 'Inyi', 'Saano', 'Sasatʉ'],
    -  STANDALONESHORTMONTHS: ['Fúngatɨ', 'Naanɨ', 'Keenda', 'Ikúmi',
    -    'Inyambala', 'Idwaata', 'Mʉʉnchɨ', 'Vɨɨrɨ', 'Saatʉ', 'Inyi', 'Saano',
    -    'Sasatʉ'],
    -  WEEKDAYS: ['Jumapíiri', 'Jumatátu', 'Jumaíne', 'Jumatáano', 'Alamíisi',
    -    'Ijumáa', 'Jumamóosi'],
    -  STANDALONEWEEKDAYS: ['Jumapíiri', 'Jumatátu', 'Jumaíne', 'Jumatáano',
    -    'Alamíisi', 'Ijumáa', 'Jumamóosi'],
    -  SHORTWEEKDAYS: ['Píili', 'Táatu', 'Íne', 'Táano', 'Alh', 'Ijm', 'Móosi'],
    -  STANDALONESHORTWEEKDAYS: ['Píili', 'Táatu', 'Íne', 'Táano', 'Alh', 'Ijm',
    -    'Móosi'],
    -  NARROWWEEKDAYS: ['P', 'T', 'E', 'O', 'A', 'I', 'M'],
    -  STANDALONENARROWWEEKDAYS: ['P', 'T', 'E', 'O', 'A', 'I', 'M'],
    -  SHORTQUARTERS: ['Ncho 1', 'Ncho 2', 'Ncho 3', 'Ncho 4'],
    -  QUARTERS: ['Ncholo ya 1', 'Ncholo ya 2', 'Ncholo ya 3', 'Ncholo ya 4'],
    -  AMPMS: ['TOO', 'MUU'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale lag_TZ.
    - */
    -goog.i18n.DateTimeSymbols_lag_TZ = goog.i18n.DateTimeSymbols_lag;
    -
    -
    -/**
    - * Date/time formatting symbols for locale lb.
    - */
    -goog.i18n.DateTimeSymbols_lb = {
    -  ERAS: ['v. Chr.', 'n. Chr.'],
    -  ERANAMES: ['v. Chr.', 'n. Chr.'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januar', 'Februar', 'Mäerz', 'Abrëll', 'Mee', 'Juni', 'Juli',
    -    'August', 'September', 'Oktober', 'November', 'Dezember'],
    -  STANDALONEMONTHS: ['Januar', 'Februar', 'Mäerz', 'Abrëll', 'Mee', 'Juni',
    -    'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
    -  SHORTMONTHS: ['Jan.', 'Feb.', 'Mäe.', 'Abr.', 'Mee', 'Juni', 'Juli', 'Aug.',
    -    'Sep.', 'Okt.', 'Nov.', 'Dez.'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mäe', 'Abr', 'Mee', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
    -  WEEKDAYS: ['Sonndeg', 'Méindeg', 'Dënschdeg', 'Mëttwoch', 'Donneschdeg',
    -    'Freideg', 'Samschdeg'],
    -  STANDALONEWEEKDAYS: ['Sonndeg', 'Méindeg', 'Dënschdeg', 'Mëttwoch',
    -    'Donneschdeg', 'Freideg', 'Samschdeg'],
    -  SHORTWEEKDAYS: ['Son.', 'Méi.', 'Dën.', 'Mët.', 'Don.', 'Fre.', 'Sam.'],
    -  STANDALONESHORTWEEKDAYS: ['Son', 'Méi', 'Dën', 'Mët', 'Don', 'Fre', 'Sam'],
    -  NARROWWEEKDAYS: ['S', 'M', 'D', 'M', 'D', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'D', 'M', 'D', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1. Quartal', '2. Quartal', '3. Quartal', '4. Quartal'],
    -  AMPMS: ['moies', 'nomëttes'],
    -  DATEFORMATS: ['EEEE, d. MMMM y', 'd. MMMM y', 'd. MMM y', 'dd.MM.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale lb_LU.
    - */
    -goog.i18n.DateTimeSymbols_lb_LU = goog.i18n.DateTimeSymbols_lb;
    -
    -
    -/**
    - * Date/time formatting symbols for locale lg.
    - */
    -goog.i18n.DateTimeSymbols_lg = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Kulisito nga tannaza', 'Bukya Kulisito Azaal'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Janwaliyo', 'Febwaliyo', 'Marisi', 'Apuli', 'Maayi', 'Juuni',
    -    'Julaayi', 'Agusito', 'Sebuttemba', 'Okitobba', 'Novemba', 'Desemba'],
    -  STANDALONEMONTHS: ['Janwaliyo', 'Febwaliyo', 'Marisi', 'Apuli', 'Maayi',
    -    'Juuni', 'Julaayi', 'Agusito', 'Sebuttemba', 'Okitobba', 'Novemba',
    -    'Desemba'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apu', 'Maa', 'Juu', 'Jul', 'Agu', 'Seb',
    -    'Oki', 'Nov', 'Des'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apu', 'Maa', 'Juu', 'Jul',
    -    'Agu', 'Seb', 'Oki', 'Nov', 'Des'],
    -  WEEKDAYS: ['Sabbiiti', 'Balaza', 'Lwakubiri', 'Lwakusatu', 'Lwakuna',
    -    'Lwakutaano', 'Lwamukaaga'],
    -  STANDALONEWEEKDAYS: ['Sabbiiti', 'Balaza', 'Lwakubiri', 'Lwakusatu',
    -    'Lwakuna', 'Lwakutaano', 'Lwamukaaga'],
    -  SHORTWEEKDAYS: ['Sab', 'Bal', 'Lw2', 'Lw3', 'Lw4', 'Lw5', 'Lw6'],
    -  STANDALONESHORTWEEKDAYS: ['Sab', 'Bal', 'Lw2', 'Lw3', 'Lw4', 'Lw5', 'Lw6'],
    -  NARROWWEEKDAYS: ['S', 'B', 'L', 'L', 'L', 'L', 'L'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'B', 'L', 'L', 'L', 'L', 'L'],
    -  SHORTQUARTERS: ['Kya1', 'Kya2', 'Kya3', 'Kya4'],
    -  QUARTERS: ['Kyakuna 1', 'Kyakuna 2', 'Kyakuna 3', 'Kyakuna 4'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale lg_UG.
    - */
    -goog.i18n.DateTimeSymbols_lg_UG = goog.i18n.DateTimeSymbols_lg;
    -
    -
    -/**
    - * Date/time formatting symbols for locale lkt.
    - */
    -goog.i18n.DateTimeSymbols_lkt = {
    -  ERAS: ['BCE', 'CE'],
    -  ERANAMES: ['BCE', 'CE'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['Wiótheȟika Wí', 'Thiyóȟeyuŋka Wí', 'Ištáwičhayazaŋ Wí',
    -    'Pȟežítȟo Wí', 'Čhaŋwápetȟo Wí', 'Wípazukȟa-wašté Wí',
    -    'Čhaŋpȟásapa Wí', 'Wasútȟuŋ Wí', 'Čhaŋwápeǧi Wí',
    -    'Čhaŋwápe-kasná Wí', 'Waníyetu Wí', 'Tȟahékapšuŋ Wí'],
    -  STANDALONEMONTHS: ['Wiótheȟika Wí', 'Thiyóȟeyuŋka Wí',
    -    'Ištáwičhayazaŋ Wí', 'Pȟežítȟo Wí', 'Čhaŋwápetȟo Wí',
    -    'Wípazukȟa-wašté Wí', 'Čhaŋpȟásapa Wí', 'Wasútȟuŋ Wí',
    -    'Čhaŋwápeǧi Wí', 'Čhaŋwápe-kasná Wí', 'Waníyetu Wí',
    -    'Tȟahékapšuŋ Wí'],
    -  SHORTMONTHS: ['Wiótheȟika Wí', 'Thiyóȟeyuŋka Wí',
    -    'Ištáwičhayazaŋ Wí', 'Pȟežítȟo Wí', 'Čhaŋwápetȟo Wí',
    -    'Wípazukȟa-wašté Wí', 'Čhaŋpȟásapa Wí', 'Wasútȟuŋ Wí',
    -    'Čhaŋwápeǧi Wí', 'Čhaŋwápe-kasná Wí', 'Waníyetu Wí',
    -    'Tȟahékapšuŋ Wí'],
    -  STANDALONESHORTMONTHS: ['Wiótheȟika Wí', 'Thiyóȟeyuŋka Wí',
    -    'Ištáwičhayazaŋ Wí', 'Pȟežítȟo Wí', 'Čhaŋwápetȟo Wí',
    -    'Wípazukȟa-wašté Wí', 'Čhaŋpȟásapa Wí', 'Wasútȟuŋ Wí',
    -    'Čhaŋwápeǧi Wí', 'Čhaŋwápe-kasná Wí', 'Waníyetu Wí',
    -    'Tȟahékapšuŋ Wí'],
    -  WEEKDAYS: ['Aŋpétuwakȟaŋ', 'Aŋpétuwaŋži', 'Aŋpétunuŋpa',
    -    'Aŋpétuyamni', 'Aŋpétutopa', 'Aŋpétuzaptaŋ', 'Owáŋgyužažapi'],
    -  STANDALONEWEEKDAYS: ['Aŋpétuwakȟaŋ', 'Aŋpétuwaŋži', 'Aŋpétunuŋpa',
    -    'Aŋpétuyamni', 'Aŋpétutopa', 'Aŋpétuzaptaŋ', 'Owáŋgyužažapi'],
    -  SHORTWEEKDAYS: ['Aŋpétuwakȟaŋ', 'Aŋpétuwaŋži', 'Aŋpétunuŋpa',
    -    'Aŋpétuyamni', 'Aŋpétutopa', 'Aŋpétuzaptaŋ', 'Owáŋgyužažapi'],
    -  STANDALONESHORTWEEKDAYS: ['Aŋpétuwakȟaŋ', 'Aŋpétuwaŋži',
    -    'Aŋpétunuŋpa', 'Aŋpétuyamni', 'Aŋpétutopa', 'Aŋpétuzaptaŋ',
    -    'Owáŋgyužažapi'],
    -  NARROWWEEKDAYS: ['A', 'W', 'N', 'Y', 'T', 'Z', 'O'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale lkt_US.
    - */
    -goog.i18n.DateTimeSymbols_lkt_US = goog.i18n.DateTimeSymbols_lkt;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ln_AO.
    - */
    -goog.i18n.DateTimeSymbols_ln_AO = {
    -  ERAS: ['libóso ya', 'nsima ya Y'],
    -  ERANAMES: ['Yambo ya Yézu Krís', 'Nsima ya Yézu Krís'],
    -  NARROWMONTHS: ['y', 'f', 'm', 'a', 'm', 'y', 'y', 'a', 's', 'ɔ', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['y', 'f', 'm', 'a', 'm', 'y', 'y', 'a', 's', 'ɔ',
    -    'n', 'd'],
    -  MONTHS: ['sánzá ya yambo', 'sánzá ya míbalé', 'sánzá ya mísáto',
    -    'sánzá ya mínei', 'sánzá ya mítáno', 'sánzá ya motóbá',
    -    'sánzá ya nsambo', 'sánzá ya mwambe', 'sánzá ya libwa',
    -    'sánzá ya zómi', 'sánzá ya zómi na mɔ̌kɔ́',
    -    'sánzá ya zómi na míbalé'],
    -  STANDALONEMONTHS: ['sánzá ya yambo', 'sánzá ya míbalé',
    -    'sánzá ya mísáto', 'sánzá ya mínei', 'sánzá ya mítáno',
    -    'sánzá ya motóbá', 'sánzá ya nsambo', 'sánzá ya mwambe',
    -    'sánzá ya libwa', 'sánzá ya zómi', 'sánzá ya zómi na mɔ̌kɔ́',
    -    'sánzá ya zómi na míbalé'],
    -  SHORTMONTHS: ['yan', 'fbl', 'msi', 'apl', 'mai', 'yun', 'yul', 'agt', 'stb',
    -    'ɔtb', 'nvb', 'dsb'],
    -  STANDALONESHORTMONTHS: ['yan', 'fbl', 'msi', 'apl', 'mai', 'yun', 'yul',
    -    'agt', 'stb', 'ɔtb', 'nvb', 'dsb'],
    -  WEEKDAYS: ['eyenga', 'mokɔlɔ mwa yambo', 'mokɔlɔ mwa míbalé',
    -    'mokɔlɔ mwa mísáto', 'mokɔlɔ ya mínéi', 'mokɔlɔ ya mítáno',
    -    'mpɔ́sɔ'],
    -  STANDALONEWEEKDAYS: ['eyenga', 'mokɔlɔ mwa yambo', 'mokɔlɔ mwa míbalé',
    -    'mokɔlɔ mwa mísáto', 'mokɔlɔ ya mínéi', 'mokɔlɔ ya mítáno',
    -    'mpɔ́sɔ'],
    -  SHORTWEEKDAYS: ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'],
    -  STANDALONESHORTWEEKDAYS: ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'],
    -  NARROWWEEKDAYS: ['e', 'y', 'm', 'm', 'm', 'm', 'p'],
    -  STANDALONENARROWWEEKDAYS: ['e', 'y', 'm', 'm', 'm', 'm', 'p'],
    -  SHORTQUARTERS: ['SM1', 'SM2', 'SM3', 'SM4'],
    -  QUARTERS: ['sánzá mísáto ya yambo', 'sánzá mísáto ya míbalé',
    -    'sánzá mísáto ya mísáto', 'sánzá mísáto ya mínei'],
    -  AMPMS: ['ntɔ́ngɔ́', 'mpókwa'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ln_CD.
    - */
    -goog.i18n.DateTimeSymbols_ln_CD = {
    -  ERAS: ['libóso ya', 'nsima ya Y'],
    -  ERANAMES: ['Yambo ya Yézu Krís', 'Nsima ya Yézu Krís'],
    -  NARROWMONTHS: ['y', 'f', 'm', 'a', 'm', 'y', 'y', 'a', 's', 'ɔ', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['y', 'f', 'm', 'a', 'm', 'y', 'y', 'a', 's', 'ɔ',
    -    'n', 'd'],
    -  MONTHS: ['sánzá ya yambo', 'sánzá ya míbalé', 'sánzá ya mísáto',
    -    'sánzá ya mínei', 'sánzá ya mítáno', 'sánzá ya motóbá',
    -    'sánzá ya nsambo', 'sánzá ya mwambe', 'sánzá ya libwa',
    -    'sánzá ya zómi', 'sánzá ya zómi na mɔ̌kɔ́',
    -    'sánzá ya zómi na míbalé'],
    -  STANDALONEMONTHS: ['sánzá ya yambo', 'sánzá ya míbalé',
    -    'sánzá ya mísáto', 'sánzá ya mínei', 'sánzá ya mítáno',
    -    'sánzá ya motóbá', 'sánzá ya nsambo', 'sánzá ya mwambe',
    -    'sánzá ya libwa', 'sánzá ya zómi', 'sánzá ya zómi na mɔ̌kɔ́',
    -    'sánzá ya zómi na míbalé'],
    -  SHORTMONTHS: ['yan', 'fbl', 'msi', 'apl', 'mai', 'yun', 'yul', 'agt', 'stb',
    -    'ɔtb', 'nvb', 'dsb'],
    -  STANDALONESHORTMONTHS: ['yan', 'fbl', 'msi', 'apl', 'mai', 'yun', 'yul',
    -    'agt', 'stb', 'ɔtb', 'nvb', 'dsb'],
    -  WEEKDAYS: ['eyenga', 'mokɔlɔ mwa yambo', 'mokɔlɔ mwa míbalé',
    -    'mokɔlɔ mwa mísáto', 'mokɔlɔ ya mínéi', 'mokɔlɔ ya mítáno',
    -    'mpɔ́sɔ'],
    -  STANDALONEWEEKDAYS: ['eyenga', 'mokɔlɔ mwa yambo', 'mokɔlɔ mwa míbalé',
    -    'mokɔlɔ mwa mísáto', 'mokɔlɔ ya mínéi', 'mokɔlɔ ya mítáno',
    -    'mpɔ́sɔ'],
    -  SHORTWEEKDAYS: ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'],
    -  STANDALONESHORTWEEKDAYS: ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'],
    -  NARROWWEEKDAYS: ['e', 'y', 'm', 'm', 'm', 'm', 'p'],
    -  STANDALONENARROWWEEKDAYS: ['e', 'y', 'm', 'm', 'm', 'm', 'p'],
    -  SHORTQUARTERS: ['SM1', 'SM2', 'SM3', 'SM4'],
    -  QUARTERS: ['sánzá mísáto ya yambo', 'sánzá mísáto ya míbalé',
    -    'sánzá mísáto ya mísáto', 'sánzá mísáto ya mínei'],
    -  AMPMS: ['ntɔ́ngɔ́', 'mpókwa'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ln_CF.
    - */
    -goog.i18n.DateTimeSymbols_ln_CF = {
    -  ERAS: ['libóso ya', 'nsima ya Y'],
    -  ERANAMES: ['Yambo ya Yézu Krís', 'Nsima ya Yézu Krís'],
    -  NARROWMONTHS: ['y', 'f', 'm', 'a', 'm', 'y', 'y', 'a', 's', 'ɔ', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['y', 'f', 'm', 'a', 'm', 'y', 'y', 'a', 's', 'ɔ',
    -    'n', 'd'],
    -  MONTHS: ['sánzá ya yambo', 'sánzá ya míbalé', 'sánzá ya mísáto',
    -    'sánzá ya mínei', 'sánzá ya mítáno', 'sánzá ya motóbá',
    -    'sánzá ya nsambo', 'sánzá ya mwambe', 'sánzá ya libwa',
    -    'sánzá ya zómi', 'sánzá ya zómi na mɔ̌kɔ́',
    -    'sánzá ya zómi na míbalé'],
    -  STANDALONEMONTHS: ['sánzá ya yambo', 'sánzá ya míbalé',
    -    'sánzá ya mísáto', 'sánzá ya mínei', 'sánzá ya mítáno',
    -    'sánzá ya motóbá', 'sánzá ya nsambo', 'sánzá ya mwambe',
    -    'sánzá ya libwa', 'sánzá ya zómi', 'sánzá ya zómi na mɔ̌kɔ́',
    -    'sánzá ya zómi na míbalé'],
    -  SHORTMONTHS: ['yan', 'fbl', 'msi', 'apl', 'mai', 'yun', 'yul', 'agt', 'stb',
    -    'ɔtb', 'nvb', 'dsb'],
    -  STANDALONESHORTMONTHS: ['yan', 'fbl', 'msi', 'apl', 'mai', 'yun', 'yul',
    -    'agt', 'stb', 'ɔtb', 'nvb', 'dsb'],
    -  WEEKDAYS: ['eyenga', 'mokɔlɔ mwa yambo', 'mokɔlɔ mwa míbalé',
    -    'mokɔlɔ mwa mísáto', 'mokɔlɔ ya mínéi', 'mokɔlɔ ya mítáno',
    -    'mpɔ́sɔ'],
    -  STANDALONEWEEKDAYS: ['eyenga', 'mokɔlɔ mwa yambo', 'mokɔlɔ mwa míbalé',
    -    'mokɔlɔ mwa mísáto', 'mokɔlɔ ya mínéi', 'mokɔlɔ ya mítáno',
    -    'mpɔ́sɔ'],
    -  SHORTWEEKDAYS: ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'],
    -  STANDALONESHORTWEEKDAYS: ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'],
    -  NARROWWEEKDAYS: ['e', 'y', 'm', 'm', 'm', 'm', 'p'],
    -  STANDALONENARROWWEEKDAYS: ['e', 'y', 'm', 'm', 'm', 'm', 'p'],
    -  SHORTQUARTERS: ['SM1', 'SM2', 'SM3', 'SM4'],
    -  QUARTERS: ['sánzá mísáto ya yambo', 'sánzá mísáto ya míbalé',
    -    'sánzá mísáto ya mísáto', 'sánzá mísáto ya mínei'],
    -  AMPMS: ['ntɔ́ngɔ́', 'mpókwa'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ln_CG.
    - */
    -goog.i18n.DateTimeSymbols_ln_CG = {
    -  ERAS: ['libóso ya', 'nsima ya Y'],
    -  ERANAMES: ['Yambo ya Yézu Krís', 'Nsima ya Yézu Krís'],
    -  NARROWMONTHS: ['y', 'f', 'm', 'a', 'm', 'y', 'y', 'a', 's', 'ɔ', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['y', 'f', 'm', 'a', 'm', 'y', 'y', 'a', 's', 'ɔ',
    -    'n', 'd'],
    -  MONTHS: ['sánzá ya yambo', 'sánzá ya míbalé', 'sánzá ya mísáto',
    -    'sánzá ya mínei', 'sánzá ya mítáno', 'sánzá ya motóbá',
    -    'sánzá ya nsambo', 'sánzá ya mwambe', 'sánzá ya libwa',
    -    'sánzá ya zómi', 'sánzá ya zómi na mɔ̌kɔ́',
    -    'sánzá ya zómi na míbalé'],
    -  STANDALONEMONTHS: ['sánzá ya yambo', 'sánzá ya míbalé',
    -    'sánzá ya mísáto', 'sánzá ya mínei', 'sánzá ya mítáno',
    -    'sánzá ya motóbá', 'sánzá ya nsambo', 'sánzá ya mwambe',
    -    'sánzá ya libwa', 'sánzá ya zómi', 'sánzá ya zómi na mɔ̌kɔ́',
    -    'sánzá ya zómi na míbalé'],
    -  SHORTMONTHS: ['yan', 'fbl', 'msi', 'apl', 'mai', 'yun', 'yul', 'agt', 'stb',
    -    'ɔtb', 'nvb', 'dsb'],
    -  STANDALONESHORTMONTHS: ['yan', 'fbl', 'msi', 'apl', 'mai', 'yun', 'yul',
    -    'agt', 'stb', 'ɔtb', 'nvb', 'dsb'],
    -  WEEKDAYS: ['eyenga', 'mokɔlɔ mwa yambo', 'mokɔlɔ mwa míbalé',
    -    'mokɔlɔ mwa mísáto', 'mokɔlɔ ya mínéi', 'mokɔlɔ ya mítáno',
    -    'mpɔ́sɔ'],
    -  STANDALONEWEEKDAYS: ['eyenga', 'mokɔlɔ mwa yambo', 'mokɔlɔ mwa míbalé',
    -    'mokɔlɔ mwa mísáto', 'mokɔlɔ ya mínéi', 'mokɔlɔ ya mítáno',
    -    'mpɔ́sɔ'],
    -  SHORTWEEKDAYS: ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'],
    -  STANDALONESHORTWEEKDAYS: ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'],
    -  NARROWWEEKDAYS: ['e', 'y', 'm', 'm', 'm', 'm', 'p'],
    -  STANDALONENARROWWEEKDAYS: ['e', 'y', 'm', 'm', 'm', 'm', 'p'],
    -  SHORTQUARTERS: ['SM1', 'SM2', 'SM3', 'SM4'],
    -  QUARTERS: ['sánzá mísáto ya yambo', 'sánzá mísáto ya míbalé',
    -    'sánzá mísáto ya mísáto', 'sánzá mísáto ya mínei'],
    -  AMPMS: ['ntɔ́ngɔ́', 'mpókwa'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale lo_LA.
    - */
    -goog.i18n.DateTimeSymbols_lo_LA = {
    -  ERAS: ['ກ່ອນ ຄ.ສ.', 'ຄ.ສ.'],
    -  ERANAMES: ['ກ່ອນຄຣິດສັກກະລາດ',
    -    'ຄຣິດສັກກະລາດ'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['ມັງກອນ', 'ກຸມພາ', 'ມີນາ',
    -    'ເມສາ', 'ພຶດສະພາ', 'ມິຖຸນາ',
    -    'ກໍລະກົດ', 'ສິງຫາ', 'ກັນຍາ',
    -    'ຕຸລາ', 'ພະຈິກ', 'ທັນວາ'],
    -  STANDALONEMONTHS: ['ມັງກອນ', 'ກຸມພາ', 'ມີນາ',
    -    'ເມສາ', 'ພຶດສະພາ', 'ມິຖຸນາ',
    -    'ກໍລະກົດ', 'ສິງຫາ', 'ກັນຍາ',
    -    'ຕຸລາ', 'ພະຈິກ', 'ທັນວາ'],
    -  SHORTMONTHS: ['ມ.ກ.', 'ກ.ພ.', 'ມ.ນ.', 'ມ.ສ.', 'ພ.ພ.',
    -    'ມິ.ຖ.', 'ກ.ລ.', 'ສ.ຫ.', 'ກ.ຍ.', 'ຕ.ລ.', 'ພ.ຈ.',
    -    'ທ.ວ.'],
    -  STANDALONESHORTMONTHS: ['ມ.ກ.', 'ກ.ພ.', 'ມ.ນ.', 'ມ.ສ.',
    -    'ພ.ພ.', 'ມິ.ຖ.', 'ກ.ລ.', 'ສ.ຫ.', 'ກ.ຍ.', 'ຕ.ລ.',
    -    'ພ.ຈ.', 'ທ.ວ.'],
    -  WEEKDAYS: ['ວັນອາທິດ', 'ວັນຈັນ',
    -    'ວັນອັງຄານ', 'ວັນພຸດ',
    -    'ວັນພະຫັດ', 'ວັນສຸກ', 'ວັນເສົາ'],
    -  STANDALONEWEEKDAYS: ['ວັນອາທິດ', 'ວັນຈັນ',
    -    'ວັນອັງຄານ', 'ວັນພຸດ',
    -    'ວັນພະຫັດ', 'ວັນສຸກ', 'ວັນເສົາ'],
    -  SHORTWEEKDAYS: ['ວັນອາທິດ', 'ວັນຈັນ',
    -    'ວັນອັງຄານ', 'ວັນພຸດ',
    -    'ວັນພະຫັດ', 'ວັນສຸກ', 'ວັນເສົາ'],
    -  STANDALONESHORTWEEKDAYS: ['ອາທິດ', 'ຈັນ',
    -    'ອັງຄານ', 'ພຸດ', 'ພະຫັດ', 'ສຸກ',
    -    'ເສົາ'],
    -  NARROWWEEKDAYS: ['1', '2', '3', '4', '5', '6', '7'],
    -  STANDALONENARROWWEEKDAYS: ['ອ', 'ຈ', 'ອ', 'ພ', 'ພຫ', 'ສຸ',
    -    'ສ'],
    -  SHORTQUARTERS: ['ຕມ1', 'ຕມ2', 'ຕມ3', 'ຕມ4'],
    -  QUARTERS: ['ໄຕຣມາດ 1', 'ໄຕຣມາດ 2',
    -    'ໄຕຣມາດ 3', 'ໄຕຣມາດ 4'],
    -  AMPMS: ['ກ່ອນທ່ຽງ', 'ຫຼັງທ່ຽງ'],
    -  DATEFORMATS: ['EEEE ທີ d MMMM G y', 'd MMMM y', 'd MMM y', 'd/M/y'],
    -  TIMEFORMATS: ['H ໂມງ m ນາທີ ss ວິນາທີ zzzz',
    -    'H ໂມງ m ນາທີ ss ວິນາທີ z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale lt_LT.
    - */
    -goog.i18n.DateTimeSymbols_lt_LT = {
    -  ERAS: ['pr. Kr.', 'po Kr.'],
    -  ERANAMES: ['prieš Kristų', 'po Kristaus'],
    -  NARROWMONTHS: ['S', 'V', 'K', 'B', 'G', 'B', 'L', 'R', 'R', 'S', 'L', 'G'],
    -  STANDALONENARROWMONTHS: ['S', 'V', 'K', 'B', 'G', 'B', 'L', 'R', 'R', 'S',
    -    'L', 'G'],
    -  MONTHS: ['sausio', 'vasario', 'kovo', 'balandžio', 'gegužės', 'birželio',
    -    'liepos', 'rugpjūčio', 'rugsėjo', 'spalio', 'lapkričio', 'gruodžio'],
    -  STANDALONEMONTHS: ['sausis', 'vasaris', 'kovas', 'balandis', 'gegužė',
    -    'birželis', 'liepa', 'rugpjūtis', 'rugsėjis', 'spalis', 'lapkritis',
    -    'gruodis'],
    -  SHORTMONTHS: ['saus.', 'vas.', 'kov.', 'bal.', 'geg.', 'birž.', 'liep.',
    -    'rugp.', 'rugs.', 'spal.', 'lapkr.', 'gruod.'],
    -  STANDALONESHORTMONTHS: ['saus.', 'vas.', 'kov.', 'bal.', 'geg.', 'birž.',
    -    'liep.', 'rugp.', 'rugs.', 'spal.', 'lapkr.', 'gruod.'],
    -  WEEKDAYS: ['sekmadienis', 'pirmadienis', 'antradienis', 'trečiadienis',
    -    'ketvirtadienis', 'penktadienis', 'šeštadienis'],
    -  STANDALONEWEEKDAYS: ['sekmadienis', 'pirmadienis', 'antradienis',
    -    'trečiadienis', 'ketvirtadienis', 'penktadienis', 'šeštadienis'],
    -  SHORTWEEKDAYS: ['sk', 'pr', 'an', 'tr', 'kt', 'pn', 'št'],
    -  STANDALONESHORTWEEKDAYS: ['sk', 'pr', 'an', 'tr', 'kt', 'pn', 'št'],
    -  NARROWWEEKDAYS: ['S', 'P', 'A', 'T', 'K', 'P', 'Š'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'P', 'A', 'T', 'K', 'P', 'Š'],
    -  SHORTQUARTERS: ['I k.', 'II k.', 'III k.', 'IV k.'],
    -  QUARTERS: ['I ketvirtis', 'II ketvirtis', 'III ketvirtis', 'IV ketvirtis'],
    -  AMPMS: ['priešpiet', 'popiet'],
    -  DATEFORMATS: ['y \'m\'. MMMM d \'d\'., EEEE', 'y \'m\'. MMMM d \'d\'.',
    -    'y-MM-dd', 'y-MM-dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale lu.
    - */
    -goog.i18n.DateTimeSymbols_lu = {
    -  ERAS: ['kmp. Y.K.', 'kny. Y. K.'],
    -  ERANAMES: ['Kumpala kwa Yezu Kli', 'Kunyima kwa Yezu Kli'],
    -  NARROWMONTHS: ['C', 'L', 'L', 'M', 'L', 'L', 'K', 'L', 'L', 'L', 'K', 'C'],
    -  STANDALONENARROWMONTHS: ['C', 'L', 'L', 'M', 'L', 'L', 'K', 'L', 'L', 'L',
    -    'K', 'C'],
    -  MONTHS: ['Ciongo', 'Lùishi', 'Lusòlo', 'Mùuyà', 'Lumùngùlù', 'Lufuimi',
    -    'Kabàlàshìpù', 'Lùshìkà', 'Lutongolo', 'Lungùdi', 'Kaswèkèsè',
    -    'Ciswà'],
    -  STANDALONEMONTHS: ['Ciongo', 'Lùishi', 'Lusòlo', 'Mùuyà', 'Lumùngùlù',
    -    'Lufuimi', 'Kabàlàshìpù', 'Lùshìkà', 'Lutongolo', 'Lungùdi',
    -    'Kaswèkèsè', 'Ciswà'],
    -  SHORTMONTHS: ['Cio', 'Lui', 'Lus', 'Muu', 'Lum', 'Luf', 'Kab', 'Lush', 'Lut',
    -    'Lun', 'Kas', 'Cis'],
    -  STANDALONESHORTMONTHS: ['Cio', 'Lui', 'Lus', 'Muu', 'Lum', 'Luf', 'Kab',
    -    'Lush', 'Lut', 'Lun', 'Kas', 'Cis'],
    -  WEEKDAYS: ['Lumingu', 'Nkodya', 'Ndàayà', 'Ndangù', 'Njòwa', 'Ngòvya',
    -    'Lubingu'],
    -  STANDALONEWEEKDAYS: ['Lumingu', 'Nkodya', 'Ndàayà', 'Ndangù', 'Njòwa',
    -    'Ngòvya', 'Lubingu'],
    -  SHORTWEEKDAYS: ['Lum', 'Nko', 'Ndy', 'Ndg', 'Njw', 'Ngv', 'Lub'],
    -  STANDALONESHORTWEEKDAYS: ['Lum', 'Nko', 'Ndy', 'Ndg', 'Njw', 'Ngv', 'Lub'],
    -  NARROWWEEKDAYS: ['L', 'N', 'N', 'N', 'N', 'N', 'L'],
    -  STANDALONENARROWWEEKDAYS: ['L', 'N', 'N', 'N', 'N', 'N', 'L'],
    -  SHORTQUARTERS: ['M1', 'M2', 'M3', 'M4'],
    -  QUARTERS: ['Mueji 1', 'Mueji 2', 'Mueji 3', 'Mueji 4'],
    -  AMPMS: ['Dinda', 'Dilolo'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale lu_CD.
    - */
    -goog.i18n.DateTimeSymbols_lu_CD = goog.i18n.DateTimeSymbols_lu;
    -
    -
    -/**
    - * Date/time formatting symbols for locale luo.
    - */
    -goog.i18n.DateTimeSymbols_luo = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Kapok Kristo obiro', 'Ka Kristo osebiro'],
    -  NARROWMONTHS: ['C', 'R', 'D', 'N', 'B', 'U', 'B', 'B', 'C', 'P', 'C', 'P'],
    -  STANDALONENARROWMONTHS: ['C', 'R', 'D', 'N', 'B', 'U', 'B', 'B', 'C', 'P',
    -    'C', 'P'],
    -  MONTHS: ['Dwe mar Achiel', 'Dwe mar Ariyo', 'Dwe mar Adek',
    -    'Dwe mar Ang’wen', 'Dwe mar Abich', 'Dwe mar Auchiel', 'Dwe mar Abiriyo',
    -    'Dwe mar Aboro', 'Dwe mar Ochiko', 'Dwe mar Apar', 'Dwe mar gi achiel',
    -    'Dwe mar Apar gi ariyo'],
    -  STANDALONEMONTHS: ['Dwe mar Achiel', 'Dwe mar Ariyo', 'Dwe mar Adek',
    -    'Dwe mar Ang’wen', 'Dwe mar Abich', 'Dwe mar Auchiel', 'Dwe mar Abiriyo',
    -    'Dwe mar Aboro', 'Dwe mar Ochiko', 'Dwe mar Apar', 'Dwe mar gi achiel',
    -    'Dwe mar Apar gi ariyo'],
    -  SHORTMONTHS: ['DAC', 'DAR', 'DAD', 'DAN', 'DAH', 'DAU', 'DAO', 'DAB', 'DOC',
    -    'DAP', 'DGI', 'DAG'],
    -  STANDALONESHORTMONTHS: ['DAC', 'DAR', 'DAD', 'DAN', 'DAH', 'DAU', 'DAO',
    -    'DAB', 'DOC', 'DAP', 'DGI', 'DAG'],
    -  WEEKDAYS: ['Jumapil', 'Wuok Tich', 'Tich Ariyo', 'Tich Adek',
    -    'Tich Ang’wen', 'Tich Abich', 'Ngeso'],
    -  STANDALONEWEEKDAYS: ['Jumapil', 'Wuok Tich', 'Tich Ariyo', 'Tich Adek',
    -    'Tich Ang’wen', 'Tich Abich', 'Ngeso'],
    -  SHORTWEEKDAYS: ['JMP', 'WUT', 'TAR', 'TAD', 'TAN', 'TAB', 'NGS'],
    -  STANDALONESHORTWEEKDAYS: ['JMP', 'WUT', 'TAR', 'TAD', 'TAN', 'TAB', 'NGS'],
    -  NARROWWEEKDAYS: ['J', 'W', 'T', 'T', 'T', 'T', 'N'],
    -  STANDALONENARROWWEEKDAYS: ['J', 'W', 'T', 'T', 'T', 'T', 'N'],
    -  SHORTQUARTERS: ['NMN1', 'NMN2', 'NMN3', 'NMN4'],
    -  QUARTERS: ['nus mar nus 1', 'nus mar nus 2', 'nus mar nus 3',
    -    'nus mar nus 4'],
    -  AMPMS: ['OD', 'OT'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale luo_KE.
    - */
    -goog.i18n.DateTimeSymbols_luo_KE = goog.i18n.DateTimeSymbols_luo;
    -
    -
    -/**
    - * Date/time formatting symbols for locale luy.
    - */
    -goog.i18n.DateTimeSymbols_luy = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Imberi ya Kuuza Kwa', 'Muhiga Kuvita Kuuza'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni', 'Julai',
    -    'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    -  STANDALONEMONTHS: ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni',
    -    'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep',
    -    'Okt', 'Nov', 'Des'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul',
    -    'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
    -  WEEKDAYS: ['Jumapiri', 'Jumatatu', 'Jumanne', 'Jumatano', 'Murwa wa Kanne',
    -    'Murwa wa Katano', 'Jumamosi'],
    -  STANDALONEWEEKDAYS: ['Jumapiri', 'Jumatatu', 'Jumanne', 'Jumatano',
    -    'Murwa wa Kanne', 'Murwa wa Katano', 'Jumamosi'],
    -  SHORTWEEKDAYS: ['J2', 'J3', 'J4', 'J5', 'Al', 'Ij', 'J1'],
    -  STANDALONESHORTWEEKDAYS: ['J2', 'J3', 'J4', 'J5', 'Al', 'Ij', 'J1'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Robo ya Kala', 'Robo ya Kaviri', 'Robo ya Kavaga',
    -    'Robo ya Kanne'],
    -  AMPMS: ['a.m.', 'p.m.'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale luy_KE.
    - */
    -goog.i18n.DateTimeSymbols_luy_KE = goog.i18n.DateTimeSymbols_luy;
    -
    -
    -/**
    - * Date/time formatting symbols for locale lv_LV.
    - */
    -goog.i18n.DateTimeSymbols_lv_LV = {
    -  ERAS: ['p.m.ē.', 'm.ē.'],
    -  ERANAMES: ['pirms mūsu ēras', 'mūsu ērā'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janvāris', 'februāris', 'marts', 'aprīlis', 'maijs', 'jūnijs',
    -    'jūlijs', 'augusts', 'septembris', 'oktobris', 'novembris', 'decembris'],
    -  STANDALONEMONTHS: ['Janvāris', 'Februāris', 'Marts', 'Aprīlis', 'Maijs',
    -    'Jūnijs', 'Jūlijs', 'Augusts', 'Septembris', 'Oktobris', 'Novembris',
    -    'Decembris'],
    -  SHORTMONTHS: ['janv.', 'febr.', 'marts', 'apr.', 'maijs', 'jūn.', 'jūl.',
    -    'aug.', 'sept.', 'okt.', 'nov.', 'dec.'],
    -  STANDALONESHORTMONTHS: ['Janv.', 'Febr.', 'Marts', 'Apr.', 'Maijs', 'Jūn.',
    -    'Jūl.', 'Aug.', 'Sept.', 'Okt.', 'Nov.', 'Dec.'],
    -  WEEKDAYS: ['svētdiena', 'pirmdiena', 'otrdiena', 'trešdiena', 'ceturtdiena',
    -    'piektdiena', 'sestdiena'],
    -  STANDALONEWEEKDAYS: ['Svētdiena', 'Pirmdiena', 'Otrdiena', 'Trešdiena',
    -    'Ceturtdiena', 'Piektdiena', 'Sestdiena'],
    -  SHORTWEEKDAYS: ['Sv', 'Pr', 'Ot', 'Tr', 'Ce', 'Pk', 'Se'],
    -  STANDALONESHORTWEEKDAYS: ['Sv', 'Pr', 'Ot', 'Tr', 'Ce', 'Pk', 'Se'],
    -  NARROWWEEKDAYS: ['S', 'P', 'O', 'T', 'C', 'P', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'P', 'O', 'T', 'C', 'P', 'S'],
    -  SHORTQUARTERS: ['1. cet.', '2. cet.', '3. cet.', '4. cet.'],
    -  QUARTERS: ['1. ceturksnis', '2. ceturksnis', '3. ceturksnis',
    -    '4. ceturksnis'],
    -  AMPMS: ['priekšpusdienā', 'pēcpusdienā'],
    -  DATEFORMATS: ['EEEE, y. \'gada\' d. MMMM', 'y. \'gada\' d. MMMM',
    -    'y. \'gada\' d. MMM', 'dd.MM.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale mas.
    - */
    -goog.i18n.DateTimeSymbols_mas = {
    -  ERAS: ['MY', 'EY'],
    -  ERANAMES: ['Meínō Yɛ́sʉ', 'Eínō Yɛ́sʉ'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['Oladalʉ́', 'Arát', 'Ɔɛnɨ́ɔɨŋɔk',
    -    'Olodoyíóríê inkókúâ', 'Oloilépūnyīē inkókúâ', 'Kújúɔrɔk',
    -    'Mórusásin', 'Ɔlɔ́ɨ́bɔ́rárɛ', 'Kúshîn', 'Olgísan',
    -    'Pʉshʉ́ka', 'Ntʉ́ŋʉ́s'],
    -  STANDALONEMONTHS: ['Oladalʉ́', 'Arát', 'Ɔɛnɨ́ɔɨŋɔk',
    -    'Olodoyíóríê inkókúâ', 'Oloilépūnyīē inkókúâ', 'Kújúɔrɔk',
    -    'Mórusásin', 'Ɔlɔ́ɨ́bɔ́rárɛ', 'Kúshîn', 'Olgísan',
    -    'Pʉshʉ́ka', 'Ntʉ́ŋʉ́s'],
    -  SHORTMONTHS: ['Dal', 'Ará', 'Ɔɛn', 'Doy', 'Lép', 'Rok', 'Sás', 'Bɔ́r',
    -    'Kús', 'Gís', 'Shʉ́', 'Ntʉ́'],
    -  STANDALONESHORTMONTHS: ['Dal', 'Ará', 'Ɔɛn', 'Doy', 'Lép', 'Rok', 'Sás',
    -    'Bɔ́r', 'Kús', 'Gís', 'Shʉ́', 'Ntʉ́'],
    -  WEEKDAYS: ['Jumapílí', 'Jumatátu', 'Jumane', 'Jumatánɔ', 'Alaámisi',
    -    'Jumáa', 'Jumamósi'],
    -  STANDALONEWEEKDAYS: ['Jumapílí', 'Jumatátu', 'Jumane', 'Jumatánɔ',
    -    'Alaámisi', 'Jumáa', 'Jumamósi'],
    -  SHORTWEEKDAYS: ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
    -  STANDALONESHORTWEEKDAYS: ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
    -  NARROWWEEKDAYS: ['2', '3', '4', '5', '6', '7', '1'],
    -  STANDALONENARROWWEEKDAYS: ['2', '3', '4', '5', '6', '7', '1'],
    -  SHORTQUARTERS: ['E1', 'E2', 'E3', 'E4'],
    -  QUARTERS: ['Erobo 1', 'Erobo 2', 'Erobo 3', 'Erobo 4'],
    -  AMPMS: ['Ɛnkakɛnyá', 'Ɛndámâ'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale mas_KE.
    - */
    -goog.i18n.DateTimeSymbols_mas_KE = goog.i18n.DateTimeSymbols_mas;
    -
    -
    -/**
    - * Date/time formatting symbols for locale mas_TZ.
    - */
    -goog.i18n.DateTimeSymbols_mas_TZ = goog.i18n.DateTimeSymbols_mas;
    -
    -
    -/**
    - * Date/time formatting symbols for locale mer.
    - */
    -goog.i18n.DateTimeSymbols_mer = {
    -  ERAS: ['MK', 'NK'],
    -  ERANAMES: ['Mbere ya Kristũ', 'Nyuma ya Kristũ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'Ĩ', 'M', 'N', 'N', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'Ĩ', 'M', 'N', 'N', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januarĩ', 'Feburuarĩ', 'Machi', 'Ĩpurũ', 'Mĩĩ', 'Njuni',
    -    'Njuraĩ', 'Agasti', 'Septemba', 'Oktũba', 'Novemba', 'Dicemba'],
    -  STANDALONEMONTHS: ['Januarĩ', 'Feburuarĩ', 'Machi', 'Ĩpurũ', 'Mĩĩ',
    -    'Njuni', 'Njuraĩ', 'Agasti', 'Septemba', 'Oktũba', 'Novemba', 'Dicemba'],
    -  SHORTMONTHS: ['JAN', 'FEB', 'MAC', 'ĨPU', 'MĨĨ', 'NJU', 'NJR', 'AGA',
    -    'SPT', 'OKT', 'NOV', 'DEC'],
    -  STANDALONESHORTMONTHS: ['JAN', 'FEB', 'MAC', 'ĨPU', 'MĨĨ', 'NJU', 'NJR',
    -    'AGA', 'SPT', 'OKT', 'NOV', 'DEC'],
    -  WEEKDAYS: ['Kiumia', 'Muramuko', 'Wairi', 'Wethatu', 'Wena', 'Wetano',
    -    'Jumamosi'],
    -  STANDALONEWEEKDAYS: ['Kiumia', 'Muramuko', 'Wairi', 'Wethatu', 'Wena',
    -    'Wetano', 'Jumamosi'],
    -  SHORTWEEKDAYS: ['KIU', 'MRA', 'WAI', 'WET', 'WEN', 'WTN', 'JUM'],
    -  STANDALONESHORTWEEKDAYS: ['KIU', 'MRA', 'WAI', 'WET', 'WEN', 'WTN', 'JUM'],
    -  NARROWWEEKDAYS: ['K', 'M', 'W', 'W', 'W', 'W', 'J'],
    -  STANDALONENARROWWEEKDAYS: ['K', 'M', 'W', 'W', 'W', 'W', 'J'],
    -  SHORTQUARTERS: ['Ĩmwe kĩrĩ inya', 'Ijĩrĩ kĩrĩ inya',
    -    'Ithatũ kĩrĩ inya', 'Inya kĩrĩ inya'],
    -  QUARTERS: ['Ĩmwe kĩrĩ inya', 'Ijĩrĩ kĩrĩ inya', 'Ithatũ kĩrĩ inya',
    -    'Inya kĩrĩ inya'],
    -  AMPMS: ['RŨ', 'ŨG'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale mer_KE.
    - */
    -goog.i18n.DateTimeSymbols_mer_KE = goog.i18n.DateTimeSymbols_mer;
    -
    -
    -/**
    - * Date/time formatting symbols for locale mfe.
    - */
    -goog.i18n.DateTimeSymbols_mfe = {
    -  ERAS: ['av. Z-K', 'ap. Z-K'],
    -  ERANAMES: ['avan Zezi-Krist', 'apre Zezi-Krist'],
    -  NARROWMONTHS: ['z', 'f', 'm', 'a', 'm', 'z', 'z', 'o', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['z', 'f', 'm', 'a', 'm', 'z', 'z', 'o', 's', 'o',
    -    'n', 'd'],
    -  MONTHS: ['zanvie', 'fevriye', 'mars', 'avril', 'me', 'zin', 'zilye', 'out',
    -    'septam', 'oktob', 'novam', 'desam'],
    -  STANDALONEMONTHS: ['zanvie', 'fevriye', 'mars', 'avril', 'me', 'zin', 'zilye',
    -    'out', 'septam', 'oktob', 'novam', 'desam'],
    -  SHORTMONTHS: ['zan', 'fev', 'mar', 'avr', 'me', 'zin', 'zil', 'out', 'sep',
    -    'okt', 'nov', 'des'],
    -  STANDALONESHORTMONTHS: ['zan', 'fev', 'mar', 'avr', 'me', 'zin', 'zil', 'out',
    -    'sep', 'okt', 'nov', 'des'],
    -  WEEKDAYS: ['dimans', 'lindi', 'mardi', 'merkredi', 'zedi', 'vandredi',
    -    'samdi'],
    -  STANDALONEWEEKDAYS: ['dimans', 'lindi', 'mardi', 'merkredi', 'zedi',
    -    'vandredi', 'samdi'],
    -  SHORTWEEKDAYS: ['dim', 'lin', 'mar', 'mer', 'ze', 'van', 'sam'],
    -  STANDALONESHORTWEEKDAYS: ['dim', 'lin', 'mar', 'mer', 'ze', 'van', 'sam'],
    -  NARROWWEEKDAYS: ['d', 'l', 'm', 'm', 'z', 'v', 's'],
    -  STANDALONENARROWWEEKDAYS: ['d', 'l', 'm', 'm', 'z', 'v', 's'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1e trimes', '2em trimes', '3em trimes', '4em trimes'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM, y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale mfe_MU.
    - */
    -goog.i18n.DateTimeSymbols_mfe_MU = goog.i18n.DateTimeSymbols_mfe;
    -
    -
    -/**
    - * Date/time formatting symbols for locale mg.
    - */
    -goog.i18n.DateTimeSymbols_mg = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Alohan’i JK', 'Aorian’i JK'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Janoary', 'Febroary', 'Martsa', 'Aprily', 'Mey', 'Jona', 'Jolay',
    -    'Aogositra', 'Septambra', 'Oktobra', 'Novambra', 'Desambra'],
    -  STANDALONEMONTHS: ['Janoary', 'Febroary', 'Martsa', 'Aprily', 'Mey', 'Jona',
    -    'Jolay', 'Aogositra', 'Septambra', 'Oktobra', 'Novambra', 'Desambra'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'Mey', 'Jon', 'Jol', 'Aog', 'Sep',
    -    'Okt', 'Nov', 'Des'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'Mey', 'Jon', 'Jol',
    -    'Aog', 'Sep', 'Okt', 'Nov', 'Des'],
    -  WEEKDAYS: ['Alahady', 'Alatsinainy', 'Talata', 'Alarobia', 'Alakamisy',
    -    'Zoma', 'Asabotsy'],
    -  STANDALONEWEEKDAYS: ['Alahady', 'Alatsinainy', 'Talata', 'Alarobia',
    -    'Alakamisy', 'Zoma', 'Asabotsy'],
    -  SHORTWEEKDAYS: ['Alah', 'Alats', 'Tal', 'Alar', 'Alak', 'Zom', 'Asab'],
    -  STANDALONESHORTWEEKDAYS: ['Alah', 'Alats', 'Tal', 'Alar', 'Alak', 'Zom',
    -    'Asab'],
    -  NARROWWEEKDAYS: ['A', 'A', 'T', 'A', 'A', 'Z', 'A'],
    -  STANDALONENARROWWEEKDAYS: ['A', 'A', 'T', 'A', 'A', 'Z', 'A'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['Telovolana voalohany', 'Telovolana faharoa',
    -    'Telovolana fahatelo', 'Telovolana fahefatra'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM, y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale mg_MG.
    - */
    -goog.i18n.DateTimeSymbols_mg_MG = goog.i18n.DateTimeSymbols_mg;
    -
    -
    -/**
    - * Date/time formatting symbols for locale mgh.
    - */
    -goog.i18n.DateTimeSymbols_mgh = {
    -  ERAS: ['HY', 'YY'],
    -  ERANAMES: ['Hinapiya yesu', 'Yopia yesu'],
    -  NARROWMONTHS: ['K', 'U', 'R', 'C', 'T', 'M', 'S', 'N', 'T', 'K', 'M', 'Y'],
    -  STANDALONENARROWMONTHS: ['K', 'U', 'R', 'C', 'T', 'M', 'S', 'N', 'T', 'K',
    -    'M', 'Y'],
    -  MONTHS: ['Mweri wo kwanza', 'Mweri wo unayeli', 'Mweri wo uneraru',
    -    'Mweri wo unecheshe', 'Mweri wo unethanu', 'Mweri wo thanu na mocha',
    -    'Mweri wo saba', 'Mweri wo nane', 'Mweri wo tisa', 'Mweri wo kumi',
    -    'Mweri wo kumi na moja', 'Mweri wo kumi na yel’li'],
    -  STANDALONEMONTHS: ['Mweri wo kwanza', 'Mweri wo unayeli', 'Mweri wo uneraru',
    -    'Mweri wo unecheshe', 'Mweri wo unethanu', 'Mweri wo thanu na mocha',
    -    'Mweri wo saba', 'Mweri wo nane', 'Mweri wo tisa', 'Mweri wo kumi',
    -    'Mweri wo kumi na moja', 'Mweri wo kumi na yel’li'],
    -  SHORTMONTHS: ['Kwa', 'Una', 'Rar', 'Che', 'Tha', 'Moc', 'Sab', 'Nan', 'Tis',
    -    'Kum', 'Moj', 'Yel'],
    -  STANDALONESHORTMONTHS: ['Kwa', 'Una', 'Rar', 'Che', 'Tha', 'Moc', 'Sab',
    -    'Nan', 'Tis', 'Kum', 'Moj', 'Yel'],
    -  WEEKDAYS: ['Sabato', 'Jumatatu', 'Jumanne', 'Jumatano', 'Arahamisi', 'Ijumaa',
    -    'Jumamosi'],
    -  STANDALONEWEEKDAYS: ['Sabato', 'Jumatatu', 'Jumanne', 'Jumatano', 'Arahamisi',
    -    'Ijumaa', 'Jumamosi'],
    -  SHORTWEEKDAYS: ['Sab', 'Jtt', 'Jnn', 'Jtn', 'Ara', 'Iju', 'Jmo'],
    -  STANDALONESHORTWEEKDAYS: ['Sab', 'Jtt', 'Jnn', 'Jtn', 'Ara', 'Iju', 'Jmo'],
    -  NARROWWEEKDAYS: ['S', 'J', 'J', 'J', 'A', 'I', 'J'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'J', 'J', 'J', 'A', 'I', 'J'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['wichishu', 'mchochil’l'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale mgh_MZ.
    - */
    -goog.i18n.DateTimeSymbols_mgh_MZ = goog.i18n.DateTimeSymbols_mgh;
    -
    -
    -/**
    - * Date/time formatting symbols for locale mgo.
    - */
    -goog.i18n.DateTimeSymbols_mgo = {
    -  ERAS: ['BCE', 'CE'],
    -  ERANAMES: ['BCE', 'CE'],
    -  NARROWMONTHS: ['M1', 'A2', 'M3', 'N4', 'F5', 'I6', 'A7', 'I8', 'K9', '10',
    -    '11', '12'],
    -  STANDALONENARROWMONTHS: ['M1', 'A2', 'M3', 'N4', 'F5', 'I6', 'A7', 'I8', 'K9',
    -    '10', '11', '12'],
    -  MONTHS: ['iməg mbegtug', 'imeg àbùbì', 'imeg mbəŋchubi',
    -    'iməg ngwə̀t', 'iməg fog', 'iməg ichiibɔd', 'iməg àdùmbə̀ŋ',
    -    'iməg ichika', 'iməg kud', 'iməg tèsiʼe', 'iməg zò',
    -    'iməg krizmed'],
    -  STANDALONEMONTHS: ['iməg mbegtug', 'imeg àbùbì', 'imeg mbəŋchubi',
    -    'iməg ngwə̀t', 'iməg fog', 'iməg ichiibɔd', 'iməg àdùmbə̀ŋ',
    -    'iməg ichika', 'iməg kud', 'iməg tèsiʼe', 'iməg zò',
    -    'iməg krizmed'],
    -  SHORTMONTHS: ['mbegtug', 'imeg àbùbì', 'imeg mbəŋchubi',
    -    'iməg ngwə̀t', 'iməg fog', 'iməg ichiibɔd', 'iməg àdùmbə̀ŋ',
    -    'iməg ichika', 'iməg kud', 'iməg tèsiʼe', 'iməg zò',
    -    'iməg krizmed'],
    -  STANDALONESHORTMONTHS: ['mbegtug', 'imeg àbùbì', 'imeg mbəŋchubi',
    -    'iməg ngwə̀t', 'iməg fog', 'iməg ichiibɔd', 'iməg àdùmbə̀ŋ',
    -    'iməg ichika', 'iməg kud', 'iməg tèsiʼe', 'iməg zò',
    -    'iməg krizmed'],
    -  WEEKDAYS: ['Aneg 1', 'Aneg 2', 'Aneg 3', 'Aneg 4', 'Aneg 5', 'Aneg 6',
    -    'Aneg 7'],
    -  STANDALONEWEEKDAYS: ['Aneg 1', 'Aneg 2', 'Aneg 3', 'Aneg 4', 'Aneg 5',
    -    'Aneg 6', 'Aneg 7'],
    -  SHORTWEEKDAYS: ['Aneg 1', 'Aneg 2', 'Aneg 3', 'Aneg 4', 'Aneg 5', 'Aneg 6',
    -    'Aneg 7'],
    -  STANDALONESHORTWEEKDAYS: ['Aneg 1', 'Aneg 2', 'Aneg 3', 'Aneg 4', 'Aneg 5',
    -    'Aneg 6', 'Aneg 7'],
    -  NARROWWEEKDAYS: ['A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7'],
    -  STANDALONENARROWWEEKDAYS: ['A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, y MMMM dd', 'y MMMM d', 'y MMM d', 'y-MM-dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale mgo_CM.
    - */
    -goog.i18n.DateTimeSymbols_mgo_CM = goog.i18n.DateTimeSymbols_mgo;
    -
    -
    -/**
    - * Date/time formatting symbols for locale mk_MK.
    - */
    -goog.i18n.DateTimeSymbols_mk_MK = {
    -  ERAS: ['пр.н.е.', 'н.е.'],
    -  ERANAMES: ['пред нашата ера', 'од нашата ера'],
    -  NARROWMONTHS: ['ј', 'ф', 'м', 'а', 'м', 'ј', 'ј', 'а', 'с', 'о',
    -    'н', 'д'],
    -  STANDALONENARROWMONTHS: ['ј', 'ф', 'м', 'а', 'м', 'ј', 'ј', 'а', 'с',
    -    'о', 'н', 'д'],
    -  MONTHS: ['јануари', 'февруари', 'март', 'април',
    -    'мај', 'јуни', 'јули', 'август', 'септември',
    -    'октомври', 'ноември', 'декември'],
    -  STANDALONEMONTHS: ['јануари', 'февруари', 'март',
    -    'април', 'мај', 'јуни', 'јули', 'август',
    -    'септември', 'октомври', 'ноември',
    -    'декември'],
    -  SHORTMONTHS: ['јан.', 'фев.', 'мар.', 'апр.', 'мај', 'јун.',
    -    'јул.', 'авг.', 'септ.', 'окт.', 'ноем.', 'дек.'],
    -  STANDALONESHORTMONTHS: ['јан.', 'фев.', 'мар.', 'апр.', 'мај',
    -    'јун.', 'јул.', 'авг.', 'септ.', 'окт.', 'ноем.',
    -    'дек.'],
    -  WEEKDAYS: ['недела', 'понеделник', 'вторник',
    -    'среда', 'четврток', 'петок', 'сабота'],
    -  STANDALONEWEEKDAYS: ['недела', 'понеделник', 'вторник',
    -    'среда', 'четврток', 'петок', 'сабота'],
    -  SHORTWEEKDAYS: ['нед.', 'пон.', 'вт.', 'сре.', 'чет.',
    -    'пет.', 'саб.'],
    -  STANDALONESHORTWEEKDAYS: ['нед.', 'пон.', 'вт.', 'сре.', 'чет.',
    -    'пет.', 'саб.'],
    -  NARROWWEEKDAYS: ['н', 'п', 'в', 'с', 'ч', 'п', 'с'],
    -  STANDALONENARROWWEEKDAYS: ['н', 'п', 'в', 'с', 'ч', 'п', 'с'],
    -  SHORTQUARTERS: ['јан-мар', 'апр-јун', 'јул-сеп',
    -    'окт-дек'],
    -  QUARTERS: ['прво тромесечје', 'второ тромесечје',
    -    'трето тромесечје', 'четврто тромесечје'],
    -  AMPMS: ['претпладне', 'попладне'],
    -  DATEFORMATS: ['EEEE, dd MMMM y', 'dd MMMM y', 'dd.M.y', 'dd.M.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ml_IN.
    - */
    -goog.i18n.DateTimeSymbols_ml_IN = {
    -  ERAS: ['ക്രി.മു.', 'എഡി'],
    -  ERANAMES: ['ക്രിസ്‌തുവിന് മുമ്പ്',
    -    'ആന്നോ ഡൊമിനി'],
    -  NARROWMONTHS: ['ജ', 'ഫ', 'മാ', 'ഏ', 'മെ', 'ജൂ', 'ജൂ',
    -    'ഓ', 'സ', 'ഒ', 'ന', 'ഡി'],
    -  STANDALONENARROWMONTHS: ['ജ', 'ഫ', 'മാ', 'ഏ', 'മേ', 'ജൂ',
    -    'ജൂ', 'ഓ', 'സ', 'ഒ', 'ന', 'ഡി'],
    -  MONTHS: ['ജനുവരി', 'ഫെബ്രുവരി',
    -    'മാർച്ച്', 'ഏപ്രിൽ', 'മേയ്', 'ജൂൺ',
    -    'ജൂലൈ', 'ആഗസ്റ്റ്',
    -    'സെപ്റ്റംബർ', 'ഒക്‌ടോബർ',
    -    'നവംബർ', 'ഡിസംബർ'],
    -  STANDALONEMONTHS: ['ജനുവരി', 'ഫെബ്രുവരി',
    -    'മാർച്ച്', 'ഏപ്രിൽ', 'മേയ്', 'ജൂൺ',
    -    'ജൂലൈ', 'ആഗസ്റ്റ്',
    -    'സെപ്റ്റംബർ', 'ഒക്‌ടോബർ',
    -    'നവംബർ', 'ഡിസംബർ'],
    -  SHORTMONTHS: ['ജനു', 'ഫെബ്രു', 'മാർ',
    -    'ഏപ്രി', 'മേയ്', 'ജൂൺ', 'ജൂലൈ', 'ഓഗ',
    -    'സെപ്റ്റം', 'ഒക്ടോ', 'നവം', 'ഡിസം'],
    -  STANDALONESHORTMONTHS: ['ജനു', 'ഫെബ്രു', 'മാർ',
    -    'ഏപ്രി', 'മേയ്', 'ജൂൺ', 'ജൂലൈ', 'ഓഗ',
    -    'സെപ്റ്റം', 'ഒക്ടോ', 'നവം', 'ഡിസം'],
    -  WEEKDAYS: ['ഞായറാഴ്‌ച', 'തിങ്കളാഴ്‌ച',
    -    'ചൊവ്വാഴ്ച', 'ബുധനാഴ്‌ച',
    -    'വ്യാഴാഴ്‌ച', 'വെള്ളിയാഴ്‌ച',
    -    'ശനിയാഴ്‌ച'],
    -  STANDALONEWEEKDAYS: ['ഞായറാഴ്‌ച',
    -    'തിങ്കളാഴ്‌ച', 'ചൊവ്വാഴ്‌ച',
    -    'ബുധനാഴ്‌ച', 'വ്യാഴാഴ്‌ച',
    -    'വെള്ളിയാഴ്‌ച', 'ശനിയാഴ്‌ച'],
    -  SHORTWEEKDAYS: ['ഞായർ', 'തിങ്കൾ', 'ചൊവ്വ',
    -    'ബുധൻ', 'വ്യാഴം', 'വെള്ളി', 'ശനി'],
    -  STANDALONESHORTWEEKDAYS: ['ഞായർ', 'തിങ്കൾ',
    -    'ചൊവ്വ', 'ബുധൻ', 'വ്യാഴം',
    -    'വെള്ളി', 'ശനി'],
    -  NARROWWEEKDAYS: ['ഞ', 'തി', 'ച', 'ബു', 'വ', 'വെ', 'ശ'],
    -  STANDALONENARROWWEEKDAYS: ['ഞ', 'തി', 'ച', 'ബു', 'വ', 'വെ',
    -    'ശ'],
    -  SHORTQUARTERS: ['ഒന്നാം പാദം',
    -    'രണ്ടാം പാദം', 'മൂന്നാം പാദം',
    -    'നാലാം പാദം'],
    -  QUARTERS: ['ഒന്നാം പാദം',
    -    'രണ്ടാം പാദം', 'മൂന്നാം പാദം',
    -    'നാലാം പാദം'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['y, MMMM d, EEEE', 'y, MMMM d', 'y, MMM d', 'dd/MM/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [6, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale mn_Cyrl.
    - */
    -goog.i18n.DateTimeSymbols_mn_Cyrl = {
    -  ERAS: ['МЭӨ', 'МЭ'],
    -  ERANAMES: ['манай эриний өмнөх', 'манай эриний'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['Нэгдүгээр сар', 'Хоёрдугаар сар',
    -    'Гуравдугаар сар', 'Дөрөвдүгээр сар',
    -    'Тавдугаар сар', 'Зургадугаар сар',
    -    'Долдугаар сар', 'Наймдугаар сар',
    -    'Есдүгээр сар', 'Аравдугаар сар',
    -    'Арван нэгдүгээр сар',
    -    'Арван хоёрдугаар сар'],
    -  STANDALONEMONTHS: ['Нэгдүгээр сар', 'Хоёрдугаар сар',
    -    'Гуравдугаар сар', 'Дөрөвдүгээр сар',
    -    'Тавдугаар сар', 'Зургадугаар сар',
    -    'Долдугаар сар', 'Наймдугаар сар',
    -    'Есдүгээр сар', 'Аравдугаар сар',
    -    'Арван нэгдүгээр сар',
    -    'Арван хоёрдугаар сар'],
    -  SHORTMONTHS: ['1-р сар', '2-р сар', '3-р сар', '4-р сар',
    -    '5-р сар', '6-р сар', '7-р сар', '8-р сар', '9-р сар',
    -    '10-р сар', '11-р сар', '12-р сар'],
    -  STANDALONESHORTMONTHS: ['1-р сар', '2-р сар', '3-р сар',
    -    '4-р сар', '5-р сар', '6-р сар', '7-р сар', '8-р сар',
    -    '9-р сар', '10-р сар', '11-р сар', '12-р сар'],
    -  WEEKDAYS: ['ням', 'даваа', 'мягмар', 'лхагва',
    -    'пүрэв', 'баасан', 'бямба'],
    -  STANDALONEWEEKDAYS: ['ням', 'даваа', 'мягмар', 'лхагва',
    -    'пүрэв', 'баасан', 'бямба'],
    -  SHORTWEEKDAYS: ['Ня', 'Да', 'Мя', 'Лх', 'Пү', 'Ба', 'Бя'],
    -  STANDALONESHORTWEEKDAYS: ['Ня', 'Да', 'Мя', 'Лх', 'Пү', 'Ба',
    -    'Бя'],
    -  NARROWWEEKDAYS: ['1', '2', '3', '4', '5', '6', '7'],
    -  STANDALONENARROWWEEKDAYS: ['1', '2', '3', '4', '5', '6', '7'],
    -  SHORTQUARTERS: ['У1', 'У2', 'У3', 'У4'],
    -  QUARTERS: ['1-р улирал', '2-р улирал', '3-р улирал',
    -    '4-р улирал'],
    -  AMPMS: ['ҮӨ', 'ҮХ'],
    -  DATEFORMATS: ['EEEE, y \'оны\' MM \'сарын\' d',
    -    'y \'оны\' MM \'сарын\' d', 'y MMM d', 'y-MM-dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale mn_Cyrl_MN.
    - */
    -goog.i18n.DateTimeSymbols_mn_Cyrl_MN = goog.i18n.DateTimeSymbols_mn_Cyrl;
    -
    -
    -/**
    - * Date/time formatting symbols for locale mr_IN.
    - */
    -goog.i18n.DateTimeSymbols_mr_IN = {
    -  ZERODIGIT: 0x0966,
    -  ERAS: ['इ. स. पू.', 'इ. स.'],
    -  ERANAMES: ['ईसवीसनपूर्व', 'ईसवीसन'],
    -  NARROWMONTHS: ['जा', 'फे', 'मा', 'ए', 'मे', 'जू',
    -    'जु', 'ऑ', 'स', 'ऑ', 'नो', 'डि'],
    -  STANDALONENARROWMONTHS: ['जा', 'फे', 'मा', 'ए', 'मे',
    -    'जू', 'जु', 'ऑ', 'स', 'ऑ', 'नो', 'डि'],
    -  MONTHS: ['जानेवारी', 'फेब्रुवारी',
    -    'मार्च', 'एप्रिल', 'मे', 'जून',
    -    'जुलै', 'ऑगस्ट', 'सप्टेंबर',
    -    'ऑक्टोबर', 'नोव्हेंबर',
    -    'डिसेंबर'],
    -  STANDALONEMONTHS: ['जानेवारी',
    -    'फेब्रुवारी', 'मार्च', 'एप्रिल',
    -    'मे', 'जून', 'जुलै', 'ऑगस्ट',
    -    'सप्टेंबर', 'ऑक्टोबर',
    -    'नोव्हेंबर', 'डिसेंबर'],
    -  SHORTMONTHS: ['जाने', 'फेब्रु', 'मार्च',
    -    'एप्रि', 'मे', 'जून', 'जुलै', 'ऑग',
    -    'सप्टें', 'ऑक्टो', 'नोव्हें',
    -    'डिसें'],
    -  STANDALONESHORTMONTHS: ['जाने', 'फेब्रु',
    -    'मार्च', 'एप्रि', 'मे', 'जून', 'जुलै',
    -    'ऑग', 'सप्टें', 'ऑक्टो', 'नोव्हें',
    -    'डिसें'],
    -  WEEKDAYS: ['रविवार', 'सोमवार',
    -    'मंगळवार', 'बुधवार', 'गुरुवार',
    -    'शुक्रवार', 'शनिवार'],
    -  STANDALONEWEEKDAYS: ['रविवार', 'सोमवार',
    -    'मंगळवार', 'बुधवार', 'गुरुवार',
    -    'शुक्रवार', 'शनिवार'],
    -  SHORTWEEKDAYS: ['रवि', 'सोम', 'मंगळ', 'बुध',
    -    'गुरु', 'शुक्र', 'शनि'],
    -  STANDALONESHORTWEEKDAYS: ['रवि', 'सोम', 'मंगळ',
    -    'बुध', 'गुरु', 'शुक्र', 'शनि'],
    -  NARROWWEEKDAYS: ['र', 'सो', 'मं', 'बु', 'गु', 'शु',
    -    'श'],
    -  STANDALONENARROWWEEKDAYS: ['र', 'सो', 'मं', 'बु', 'गु',
    -    'शु', 'श'],
    -  SHORTQUARTERS: ['ति१', 'ति२', 'ति३', 'ति४'],
    -  QUARTERS: ['प्रथम तिमाही',
    -    'द्वितीय तिमाही',
    -    'तृतीय तिमाही',
    -    'चतुर्थ तिमाही'],
    -  AMPMS: ['म.पू.', 'म.उ.'],
    -  DATEFORMATS: ['EEEE, d MMMM, y', 'd MMMM, y', 'd MMM, y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} \'रोजी\' {0}', '{1} \'रोजी\' {0}',
    -    '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [6, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ms_Latn.
    - */
    -goog.i18n.DateTimeSymbols_ms_Latn = {
    -  ERAS: ['S.M.', 'TM'],
    -  ERANAMES: ['S.M.', 'TM'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'O', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'O', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januari', 'Februari', 'Mac', 'April', 'Mei', 'Jun', 'Julai', 'Ogos',
    -    'September', 'Oktober', 'November', 'Disember'],
    -  STANDALONEMONTHS: ['Januari', 'Februari', 'Mac', 'April', 'Mei', 'Jun',
    -    'Julai', 'Ogos', 'September', 'Oktober', 'November', 'Disember'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ogo', 'Sep',
    -    'Okt', 'Nov', 'Dis'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul',
    -    'Ogo', 'Sep', 'Okt', 'Nov', 'Dis'],
    -  WEEKDAYS: ['Ahad', 'Isnin', 'Selasa', 'Rabu', 'Khamis', 'Jumaat', 'Sabtu'],
    -  STANDALONEWEEKDAYS: ['Ahad', 'Isnin', 'Selasa', 'Rabu', 'Khamis', 'Jumaat',
    -    'Sabtu'],
    -  SHORTWEEKDAYS: ['Ahd', 'Isn', 'Sel', 'Rab', 'Kha', 'Jum', 'Sab'],
    -  STANDALONESHORTWEEKDAYS: ['Ahd', 'Isn', 'Sel', 'Rab', 'Kha', 'Jum', 'Sab'],
    -  NARROWWEEKDAYS: ['A', 'I', 'S', 'R', 'K', 'J', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['A', 'I', 'S', 'R', 'K', 'J', 'S'],
    -  SHORTQUARTERS: ['S1', 'S2', 'S3', 'S4'],
    -  QUARTERS: ['Suku pertama', 'Suku Ke-2', 'Suku Ke-3', 'Suku Ke-4'],
    -  AMPMS: ['PG', 'PTG'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'd/MM/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ms_Latn_BN.
    - */
    -goog.i18n.DateTimeSymbols_ms_Latn_BN = {
    -  ERAS: ['S.M.', 'TM'],
    -  ERANAMES: ['S.M.', 'TM'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'O', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'O', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januari', 'Februari', 'Mac', 'April', 'Mei', 'Jun', 'Julai', 'Ogos',
    -    'September', 'Oktober', 'November', 'Disember'],
    -  STANDALONEMONTHS: ['Januari', 'Februari', 'Mac', 'April', 'Mei', 'Jun',
    -    'Julai', 'Ogos', 'September', 'Oktober', 'November', 'Disember'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ogo', 'Sep',
    -    'Okt', 'Nov', 'Dis'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul',
    -    'Ogo', 'Sep', 'Okt', 'Nov', 'Dis'],
    -  WEEKDAYS: ['Ahad', 'Isnin', 'Selasa', 'Rabu', 'Khamis', 'Jumaat', 'Sabtu'],
    -  STANDALONEWEEKDAYS: ['Ahad', 'Isnin', 'Selasa', 'Rabu', 'Khamis', 'Jumaat',
    -    'Sabtu'],
    -  SHORTWEEKDAYS: ['Ahd', 'Isn', 'Sel', 'Rab', 'Kha', 'Jum', 'Sab'],
    -  STANDALONESHORTWEEKDAYS: ['Ahd', 'Isn', 'Sel', 'Rab', 'Kha', 'Jum', 'Sab'],
    -  NARROWWEEKDAYS: ['A', 'I', 'S', 'R', 'K', 'J', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['A', 'I', 'S', 'R', 'K', 'J', 'S'],
    -  SHORTQUARTERS: ['S1', 'S2', 'S3', 'S4'],
    -  QUARTERS: ['Suku pertama', 'Suku Ke-2', 'Suku Ke-3', 'Suku Ke-4'],
    -  AMPMS: ['PG', 'PTG'],
    -  DATEFORMATS: ['dd MMMM y', 'd MMMM y', 'd MMM y', 'd/MM/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ms_Latn_MY.
    - */
    -goog.i18n.DateTimeSymbols_ms_Latn_MY = goog.i18n.DateTimeSymbols_ms_Latn;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ms_Latn_SG.
    - */
    -goog.i18n.DateTimeSymbols_ms_Latn_SG = goog.i18n.DateTimeSymbols_ms_Latn;
    -
    -
    -/**
    - * Date/time formatting symbols for locale mt_MT.
    - */
    -goog.i18n.DateTimeSymbols_mt_MT = {
    -  ERAS: ['QK', 'WK'],
    -  ERANAMES: ['Qabel Kristu', 'Wara Kristu'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'Ġ', 'L', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['Jn', 'Fr', 'Mz', 'Ap', 'Mj', 'Ġn', 'Lj', 'Aw',
    -    'St', 'Ob', 'Nv', 'Dċ'],
    -  MONTHS: ['Jannar', 'Frar', 'Marzu', 'April', 'Mejju', 'Ġunju', 'Lulju',
    -    'Awwissu', 'Settembru', 'Ottubru', 'Novembru', 'Diċembru'],
    -  STANDALONEMONTHS: ['Jannar', 'Frar', 'Marzu', 'April', 'Mejju', 'Ġunju',
    -    'Lulju', 'Awwissu', 'Settembru', 'Ottubru', 'Novembru', 'Diċembru'],
    -  SHORTMONTHS: ['Jan', 'Fra', 'Mar', 'Apr', 'Mej', 'Ġun', 'Lul', 'Aww', 'Set',
    -    'Ott', 'Nov', 'Diċ'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Fra', 'Mar', 'Apr', 'Mej', 'Ġun', 'Lul',
    -    'Aww', 'Set', 'Ott', 'Nov', 'Diċ'],
    -  WEEKDAYS: ['Il-Ħadd', 'It-Tnejn', 'It-Tlieta', 'L-Erbgħa', 'Il-Ħamis',
    -    'Il-Ġimgħa', 'Is-Sibt'],
    -  STANDALONEWEEKDAYS: ['Il-Ħadd', 'It-Tnejn', 'It-Tlieta', 'L-Erbgħa',
    -    'Il-Ħamis', 'Il-Ġimgħa', 'Is-Sibt'],
    -  SHORTWEEKDAYS: ['Ħad', 'Tne', 'Tli', 'Erb', 'Ħam', 'Ġim', 'Sib'],
    -  STANDALONESHORTWEEKDAYS: ['Ħad', 'Tne', 'Tli', 'Erb', 'Ħam', 'Ġim', 'Sib'],
    -  NARROWWEEKDAYS: ['Ħ', 'T', 'T', 'E', 'Ħ', 'Ġ', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['Ħd', 'Tn', 'Tl', 'Er', 'Ħm', 'Ġm', 'Sb'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['1el kwart', '2ni kwart', '3et kwart', '4ba’ kwart'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d \'ta\'’ MMMM y', 'd \'ta\'’ MMMM y', 'dd MMM y',
    -    'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale mua.
    - */
    -goog.i18n.DateTimeSymbols_mua = {
    -  ERAS: ['KK', 'PK'],
    -  ERANAMES: ['KǝPel Kristu', 'Pel Kristu'],
    -  NARROWMONTHS: ['O', 'A', 'I', 'F', 'D', 'B', 'L', 'M', 'E', 'U', 'W', 'Y'],
    -  STANDALONENARROWMONTHS: ['O', 'A', 'I', 'F', 'D', 'B', 'L', 'M', 'E', 'U',
    -    'W', 'Y'],
    -  MONTHS: ['Fĩi Loo', 'Cokcwaklaŋne', 'Cokcwaklii', 'Fĩi Marfoo',
    -    'Madǝǝuutǝbijaŋ', 'Mamǝŋgwãafahbii', 'Mamǝŋgwãalii', 'Madǝmbii',
    -    'Fĩi Dǝɓlii', 'Fĩi Mundaŋ', 'Fĩi Gwahlle', 'Fĩi Yuru'],
    -  STANDALONEMONTHS: ['Fĩi Loo', 'Cokcwaklaŋne', 'Cokcwaklii', 'Fĩi Marfoo',
    -    'Madǝǝuutǝbijaŋ', 'Mamǝŋgwãafahbii', 'Mamǝŋgwãalii', 'Madǝmbii',
    -    'Fĩi Dǝɓlii', 'Fĩi Mundaŋ', 'Fĩi Gwahlle', 'Fĩi Yuru'],
    -  SHORTMONTHS: ['FLO', 'CLA', 'CKI', 'FMF', 'MAD', 'MBI', 'MLI', 'MAM', 'FDE',
    -    'FMU', 'FGW', 'FYU'],
    -  STANDALONESHORTMONTHS: ['FLO', 'CLA', 'CKI', 'FMF', 'MAD', 'MBI', 'MLI',
    -    'MAM', 'FDE', 'FMU', 'FGW', 'FYU'],
    -  WEEKDAYS: ['Com’yakke', 'Comlaaɗii', 'Comzyiiɗii', 'Comkolle',
    -    'Comkaldǝɓlii', 'Comgaisuu', 'Comzyeɓsuu'],
    -  STANDALONEWEEKDAYS: ['Com’yakke', 'Comlaaɗii', 'Comzyiiɗii', 'Comkolle',
    -    'Comkaldǝɓlii', 'Comgaisuu', 'Comzyeɓsuu'],
    -  SHORTWEEKDAYS: ['Cya', 'Cla', 'Czi', 'Cko', 'Cka', 'Cga', 'Cze'],
    -  STANDALONESHORTWEEKDAYS: ['Cya', 'Cla', 'Czi', 'Cko', 'Cka', 'Cga', 'Cze'],
    -  NARROWWEEKDAYS: ['Y', 'L', 'Z', 'O', 'A', 'G', 'E'],
    -  STANDALONENARROWWEEKDAYS: ['Y', 'L', 'Z', 'O', 'A', 'G', 'E'],
    -  SHORTQUARTERS: ['F1', 'F2', 'F3', 'F4'],
    -  QUARTERS: ['Tai fĩi sai ma tǝn kee zah', 'Tai fĩi sai zah lǝn gwa ma kee',
    -    'Tai fĩi sai zah lǝn sai ma kee', 'Tai fĩi sai ma coo kee zah ‘na'],
    -  AMPMS: ['comme', 'lilli'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale mua_CM.
    - */
    -goog.i18n.DateTimeSymbols_mua_CM = goog.i18n.DateTimeSymbols_mua;
    -
    -
    -/**
    - * Date/time formatting symbols for locale my_MM.
    - */
    -goog.i18n.DateTimeSymbols_my_MM = {
    -  ZERODIGIT: 0x1040,
    -  ERAS: ['ဘီစီ', 'အေဒီ'],
    -  ERANAMES: ['ခရစ်တော် မပေါ်မီကာလ',
    -    'ခရစ်တော် ပေါ်ထွန်းပြီးကာလ'],
    -  NARROWMONTHS: ['ဇ', 'ဖ', 'မ', 'ဧ', 'မ', 'ဇ', 'ဇ', 'ဩ', 'စ',
    -    'အ', 'န', 'ဒ'],
    -  STANDALONENARROWMONTHS: ['ဇ', 'ဖ', 'မ', 'ဧ', 'မ', 'ဇ', 'ဇ',
    -    'ဩ', 'စ', 'အ', 'န', 'ဒ'],
    -  MONTHS: ['ဇန်နဝါရီ', 'ဖေဖော်ဝါရီ',
    -    'မတ်', 'ဧပြီ', 'မေ', 'ဇွန်',
    -    'ဇူလိုင်', 'ဩဂုတ်', 'စက်တင်ဘာ',
    -    'အောက်တိုဘာ', 'နိုဝင်ဘာ',
    -    'ဒီဇင်ဘာ'],
    -  STANDALONEMONTHS: ['ဇန်နဝါရီ',
    -    'ဖေဖော်ဝါရီ', 'မတ်', 'ဧပြီ', 'မေ',
    -    'ဇွန်', 'ဇူလိုင်', 'ဩဂုတ်',
    -    'စက်တင်ဘာ', 'အောက်တိုဘာ',
    -    'နိုဝင်ဘာ', 'ဒီဇင်ဘာ'],
    -  SHORTMONTHS: ['ဇန်', 'ဖေ', 'မတ်', 'ဧပြီ', 'မေ',
    -    'ဇွန်', 'ဇူ', 'ဩ', 'စက်', 'အောက်',
    -    'နို', 'ဒီ'],
    -  STANDALONESHORTMONTHS: ['ဇန်', 'ဖေ', 'မတ်', 'ဧပြီ',
    -    'မေ', 'ဇွန်', 'ဇူ', 'ဩ', 'စက်', 'အောက်',
    -    'နို', 'ဒီ'],
    -  WEEKDAYS: ['တနင်္ဂနွေ', 'တနင်္လာ',
    -    'အင်္ဂါ', 'ဗုဒ္ဓဟူး',
    -    'ကြာသပတေး', 'သောကြာ', 'စနေ'],
    -  STANDALONEWEEKDAYS: ['တနင်္ဂနွေ', 'တနင်္လာ',
    -    'အင်္ဂါ', 'ဗုဒ္ဓဟူး',
    -    'ကြာသပတေး', 'သောကြာ', 'စနေ'],
    -  SHORTWEEKDAYS: ['တနင်္ဂနွေ', 'တနင်္လာ',
    -    'အင်္ဂါ', 'ဗုဒ္ဓဟူး',
    -    'ကြာသပတေး', 'သောကြာ', 'စနေ'],
    -  STANDALONESHORTWEEKDAYS: ['တနင်္ဂနွေ',
    -    'တနင်္လာ', 'အင်္ဂါ', 'ဗုဒ္ဓဟူး',
    -    'ကြာသပတေး', 'သောကြာ', 'စနေ'],
    -  NARROWWEEKDAYS: ['တ', 'တ', 'အ', 'ဗ', 'က', 'သ', 'စ'],
    -  STANDALONENARROWWEEKDAYS: ['တ', 'တ', 'အ', 'ဗ', 'က', 'သ', 'စ'],
    -  SHORTQUARTERS: ['ပထမ သုံးလပတ်',
    -    'ဒုတိယ သုံးလပတ်',
    -    'တတိယ သုံးလပတ်',
    -    'စတုတ္ထ သုံးလပတ်'],
    -  QUARTERS: ['ပထမ သုံးလပတ်',
    -    'ဒုတိယ သုံးလပတ်',
    -    'တတိယ သုံးလပတ်',
    -    'စတုတ္ထ သုံးလပတ်'],
    -  AMPMS: ['နံနက်', 'ညနေ'],
    -  DATEFORMATS: ['EEEE, dd MMMM y', 'd MMMM y', 'd MMM y', 'dd-MM-yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1}မှာ {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale naq.
    - */
    -goog.i18n.DateTimeSymbols_naq = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Xristub aiǃâ', 'Xristub khaoǃgâ'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['ǃKhanni', 'ǃKhanǀgôab', 'ǀKhuuǁkhâb', 'ǃHôaǂkhaib',
    -    'ǃKhaitsâb', 'Gamaǀaeb', 'ǂKhoesaob', 'Aoǁkhuumûǁkhâb',
    -    'Taraǀkhuumûǁkhâb', 'ǂNûǁnâiseb', 'ǀHooǂgaeb', 'Hôasoreǁkhâb'],
    -  STANDALONEMONTHS: ['ǃKhanni', 'ǃKhanǀgôab', 'ǀKhuuǁkhâb',
    -    'ǃHôaǂkhaib', 'ǃKhaitsâb', 'Gamaǀaeb', 'ǂKhoesaob',
    -    'Aoǁkhuumûǁkhâb', 'Taraǀkhuumûǁkhâb', 'ǂNûǁnâiseb',
    -    'ǀHooǂgaeb', 'Hôasoreǁkhâb'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
    -    'Oct', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
    -    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Sontaxtsees', 'Mantaxtsees', 'Denstaxtsees', 'Wunstaxtsees',
    -    'Dondertaxtsees', 'Fraitaxtsees', 'Satertaxtsees'],
    -  STANDALONEWEEKDAYS: ['Sontaxtsees', 'Mantaxtsees', 'Denstaxtsees',
    -    'Wunstaxtsees', 'Dondertaxtsees', 'Fraitaxtsees', 'Satertaxtsees'],
    -  SHORTWEEKDAYS: ['Son', 'Ma', 'De', 'Wu', 'Do', 'Fr', 'Sat'],
    -  STANDALONESHORTWEEKDAYS: ['Son', 'Ma', 'De', 'Wu', 'Do', 'Fr', 'Sat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'E', 'W', 'D', 'F', 'A'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'E', 'W', 'D', 'F', 'A'],
    -  SHORTQUARTERS: ['KW1', 'KW2', 'KW3', 'KW4'],
    -  QUARTERS: ['1ro kwartals', '2ǁî kwartals', '3ǁî kwartals',
    -    '4ǁî kwartals'],
    -  AMPMS: ['ǁgoagas', 'ǃuias'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale naq_NA.
    - */
    -goog.i18n.DateTimeSymbols_naq_NA = goog.i18n.DateTimeSymbols_naq;
    -
    -
    -/**
    - * Date/time formatting symbols for locale nb_NO.
    - */
    -goog.i18n.DateTimeSymbols_nb_NO = {
    -  ERAS: ['f.Kr.', 'e.Kr.'],
    -  ERANAMES: ['f.Kr.', 'e.Kr.'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['januar', 'februar', 'mars', 'april', 'mai', 'juni', 'juli',
    -    'august', 'september', 'oktober', 'november', 'desember'],
    -  STANDALONEMONTHS: ['januar', 'februar', 'mars', 'april', 'mai', 'juni',
    -    'juli', 'august', 'september', 'oktober', 'november', 'desember'],
    -  SHORTMONTHS: ['jan.', 'feb.', 'mar.', 'apr.', 'mai', 'jun.', 'jul.', 'aug.',
    -    'sep.', 'okt.', 'nov.', 'des.'],
    -  STANDALONESHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'mai', 'jun', 'jul',
    -    'aug', 'sep', 'okt', 'nov', 'des'],
    -  WEEKDAYS: ['søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag', 'fredag',
    -    'lørdag'],
    -  STANDALONEWEEKDAYS: ['søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag',
    -    'fredag', 'lørdag'],
    -  SHORTWEEKDAYS: ['søn.', 'man.', 'tir.', 'ons.', 'tor.', 'fre.', 'lør.'],
    -  STANDALONESHORTWEEKDAYS: ['sø.', 'ma.', 'ti.', 'on.', 'to.', 'fr.', 'lø.'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'O', 'T', 'F', 'L'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'O', 'T', 'F', 'L'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['1. kvartal', '2. kvartal', '3. kvartal', '4. kvartal'],
    -  AMPMS: ['a.m.', 'p.m.'],
    -  DATEFORMATS: ['EEEE d. MMMM y', 'd. MMMM y', 'd. MMM y', 'dd.MM.y'],
    -  TIMEFORMATS: ['HH.mm.ss zzzz', 'HH.mm.ss z', 'HH.mm.ss', 'HH.mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} \'kl.\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale nb_SJ.
    - */
    -goog.i18n.DateTimeSymbols_nb_SJ = {
    -  ERAS: ['f.Kr.', 'e.Kr.'],
    -  ERANAMES: ['f.Kr.', 'e.Kr.'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['januar', 'februar', 'mars', 'april', 'mai', 'juni', 'juli',
    -    'august', 'september', 'oktober', 'november', 'desember'],
    -  STANDALONEMONTHS: ['januar', 'februar', 'mars', 'april', 'mai', 'juni',
    -    'juli', 'august', 'september', 'oktober', 'november', 'desember'],
    -  SHORTMONTHS: ['jan.', 'feb.', 'mar.', 'apr.', 'mai', 'jun.', 'jul.', 'aug.',
    -    'sep.', 'okt.', 'nov.', 'des.'],
    -  STANDALONESHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'mai', 'jun', 'jul',
    -    'aug', 'sep', 'okt', 'nov', 'des'],
    -  WEEKDAYS: ['søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag', 'fredag',
    -    'lørdag'],
    -  STANDALONEWEEKDAYS: ['søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag',
    -    'fredag', 'lørdag'],
    -  SHORTWEEKDAYS: ['søn.', 'man.', 'tir.', 'ons.', 'tor.', 'fre.', 'lør.'],
    -  STANDALONESHORTWEEKDAYS: ['sø.', 'ma.', 'ti.', 'on.', 'to.', 'fr.', 'lø.'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'O', 'T', 'F', 'L'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'O', 'T', 'F', 'L'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['1. kvartal', '2. kvartal', '3. kvartal', '4. kvartal'],
    -  AMPMS: ['a.m.', 'p.m.'],
    -  DATEFORMATS: ['EEEE d. MMMM y', 'd. MMMM y', 'd. MMM y', 'dd.MM.y'],
    -  TIMEFORMATS: ['HH.mm.ss zzzz', 'HH.mm.ss z', 'HH.mm.ss', 'HH.mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} \'kl.\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale nd.
    - */
    -goog.i18n.DateTimeSymbols_nd = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['UKristo angakabuyi', 'Ukristo ebuyile'],
    -  NARROWMONTHS: ['Z', 'N', 'M', 'M', 'N', 'N', 'N', 'N', 'M', 'M', 'L', 'M'],
    -  STANDALONENARROWMONTHS: ['Z', 'N', 'M', 'M', 'N', 'N', 'N', 'N', 'M', 'M',
    -    'L', 'M'],
    -  MONTHS: ['Zibandlela', 'Nhlolanja', 'Mbimbitho', 'Mabasa', 'Nkwenkwezi',
    -    'Nhlangula', 'Ntulikazi', 'Ncwabakazi', 'Mpandula', 'Mfumfu', 'Lwezi',
    -    'Mpalakazi'],
    -  STANDALONEMONTHS: ['Zibandlela', 'Nhlolanja', 'Mbimbitho', 'Mabasa',
    -    'Nkwenkwezi', 'Nhlangula', 'Ntulikazi', 'Ncwabakazi', 'Mpandula', 'Mfumfu',
    -    'Lwezi', 'Mpalakazi'],
    -  SHORTMONTHS: ['Zib', 'Nhlo', 'Mbi', 'Mab', 'Nkw', 'Nhla', 'Ntu', 'Ncw',
    -    'Mpan', 'Mfu', 'Lwe', 'Mpal'],
    -  STANDALONESHORTMONTHS: ['Zib', 'Nhlo', 'Mbi', 'Mab', 'Nkw', 'Nhla', 'Ntu',
    -    'Ncw', 'Mpan', 'Mfu', 'Lwe', 'Mpal'],
    -  WEEKDAYS: ['Sonto', 'Mvulo', 'Sibili', 'Sithathu', 'Sine', 'Sihlanu',
    -    'Mgqibelo'],
    -  STANDALONEWEEKDAYS: ['Sonto', 'Mvulo', 'Sibili', 'Sithathu', 'Sine',
    -    'Sihlanu', 'Mgqibelo'],
    -  SHORTWEEKDAYS: ['Son', 'Mvu', 'Sib', 'Sit', 'Sin', 'Sih', 'Mgq'],
    -  STANDALONESHORTWEEKDAYS: ['Son', 'Mvu', 'Sib', 'Sit', 'Sin', 'Sih', 'Mgq'],
    -  NARROWWEEKDAYS: ['S', 'M', 'S', 'S', 'S', 'S', 'M'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'S', 'S', 'S', 'S', 'M'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['Kota 1', 'Kota 2', 'Kota 3', 'Kota 4'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale nd_ZW.
    - */
    -goog.i18n.DateTimeSymbols_nd_ZW = goog.i18n.DateTimeSymbols_nd;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ne_IN.
    - */
    -goog.i18n.DateTimeSymbols_ne_IN = {
    -  ZERODIGIT: 0x0966,
    -  ERAS: ['ईसा पूर्व', 'सन्'],
    -  ERANAMES: ['ईसा पूर्व', 'सन्'],
    -  NARROWMONTHS: ['१', '२', '३', '४', '५', '६', '७', '८', '९',
    -    '१०', '११', '१२'],
    -  STANDALONENARROWMONTHS: ['१', '२', '३', '४', '५', '६', '७',
    -    '८', '९', '१०', '११', '१२'],
    -  MONTHS: ['जनवरी', 'फरवरी', 'मार्च',
    -    'अप्रेल', 'मई', 'जुन', 'जुलाई',
    -    'अगस्त', 'सेप्टेम्बर',
    -    'अक्टोबर', 'नोभेम्बर',
    -    'दिसम्बर'],
    -  STANDALONEMONTHS: ['जनवरी', 'फेब्रुअरी',
    -    'मार्च', 'अप्रिल', 'मे', 'जुन',
    -    'जुलाई', 'अगस्ट', 'सेप्टेम्बर',
    -    'अक्टोबर', 'नोभेम्बर',
    -    'डिसेम्बर'],
    -  SHORTMONTHS: ['जनवरी', 'फेब्रुअरी',
    -    'मार्च', 'अप्रिल', 'मे', 'जुन',
    -    'जुलाई', 'अगस्ट', 'सेप्टेम्बर',
    -    'अक्टोबर', 'नोभेम्बर',
    -    'डिसेम्बर'],
    -  STANDALONESHORTMONTHS: ['जनवरी', 'फेब्रुअरी',
    -    'मार्च', 'अप्रिल', 'मे', 'जुन',
    -    'जुलाई', 'अगस्ट', 'सेप्टेम्बर',
    -    'अक्टोबर', 'नोभेम्बर',
    -    'डिसेम्बर'],
    -  WEEKDAYS: ['आइतवार', 'सोमवार',
    -    'मङ्गलवार', 'बुधवार', 'बिहीवार',
    -    'शुक्रवार', 'शनिवार'],
    -  STANDALONEWEEKDAYS: ['आइतबार', 'सोमबार',
    -    'मङ्गलबार', 'बुधबार', 'बिहीबार',
    -    'शुक्रबार', 'शनिबार'],
    -  SHORTWEEKDAYS: ['आइत', 'सोम', 'मङ्गल', 'बुध',
    -    'बिही', 'शुक्र', 'शनि'],
    -  STANDALONESHORTWEEKDAYS: ['आइत', 'सोम', 'मङ्गल',
    -    'बुध', 'बिही', 'शुक्र', 'शनि'],
    -  NARROWWEEKDAYS: ['आ', 'सो', 'म', 'बु', 'बि', 'शु', 'श'],
    -  STANDALONENARROWWEEKDAYS: ['आ', 'सो', 'म', 'बु', 'बि',
    -    'शु', 'श'],
    -  SHORTQUARTERS: ['पहिलो सत्र',
    -    'दोस्रो सत्र', 'तेस्रो सत्र',
    -    'चौथो सत्र'],
    -  QUARTERS: ['पहिलो सत्र', 'दोस्रो सत्र',
    -    'तेस्रो सत्र', 'चौथो सत्र'],
    -  AMPMS: ['पूर्वाह्न', 'अपराह्न'],
    -  DATEFORMATS: ['y MMMM d, EEEE', 'y MMMM d', 'y MMM d', 'y-MM-dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [6, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ne_NP.
    - */
    -goog.i18n.DateTimeSymbols_ne_NP = {
    -  ZERODIGIT: 0x0966,
    -  ERAS: ['ईसा पूर्व', 'सन्'],
    -  ERANAMES: ['ईसा पूर्व', 'सन्'],
    -  NARROWMONTHS: ['१', '२', '३', '४', '५', '६', '७', '८', '९',
    -    '१०', '११', '१२'],
    -  STANDALONENARROWMONTHS: ['१', '२', '३', '४', '५', '६', '७',
    -    '८', '९', '१०', '११', '१२'],
    -  MONTHS: ['जनवरी', 'फेब्रुअरी', 'मार्च',
    -    'अप्रिल', 'मे', 'जुन', 'जुलाई',
    -    'अगस्ट', 'सेप्टेम्बर',
    -    'अक्टोबर', 'नोभेम्बर',
    -    'डिसेम्बर'],
    -  STANDALONEMONTHS: ['जनवरी', 'फेब्रुअरी',
    -    'मार्च', 'अप्रिल', 'मे', 'जुन',
    -    'जुलाई', 'अगस्ट', 'सेप्टेम्बर',
    -    'अक्टोबर', 'नोभेम्बर',
    -    'डिसेम्बर'],
    -  SHORTMONTHS: ['जनवरी', 'फेब्रुअरी',
    -    'मार्च', 'अप्रिल', 'मे', 'जुन',
    -    'जुलाई', 'अगस्ट', 'सेप्टेम्बर',
    -    'अक्टोबर', 'नोभेम्बर',
    -    'डिसेम्बर'],
    -  STANDALONESHORTMONTHS: ['जनवरी', 'फेब्रुअरी',
    -    'मार्च', 'अप्रिल', 'मे', 'जुन',
    -    'जुलाई', 'अगस्ट', 'सेप्टेम्बर',
    -    'अक्टोबर', 'नोभेम्बर',
    -    'डिसेम्बर'],
    -  WEEKDAYS: ['आइतबार', 'सोमबार',
    -    'मङ्गलबार', 'बुधबार', 'बिहीबार',
    -    'शुक्रबार', 'शनिबार'],
    -  STANDALONEWEEKDAYS: ['आइतबार', 'सोमबार',
    -    'मङ्गलबार', 'बुधबार', 'बिहीबार',
    -    'शुक्रबार', 'शनिबार'],
    -  SHORTWEEKDAYS: ['आइत', 'सोम', 'मङ्गल', 'बुध',
    -    'बिही', 'शुक्र', 'शनि'],
    -  STANDALONESHORTWEEKDAYS: ['आइत', 'सोम', 'मङ्गल',
    -    'बुध', 'बिही', 'शुक्र', 'शनि'],
    -  NARROWWEEKDAYS: ['आ', 'सो', 'म', 'बु', 'बि', 'शु', 'श'],
    -  STANDALONENARROWWEEKDAYS: ['आ', 'सो', 'म', 'बु', 'बि',
    -    'शु', 'श'],
    -  SHORTQUARTERS: ['पहिलो सत्र',
    -    'दोस्रो सत्र', 'तेस्रो सत्र',
    -    'चौथो सत्र'],
    -  QUARTERS: ['पहिलो सत्र', 'दोस्रो सत्र',
    -    'तेस्रो सत्र', 'चौथो सत्र'],
    -  AMPMS: ['पूर्व मध्यान्ह',
    -    'उत्तर मध्यान्ह'],
    -  DATEFORMATS: ['y MMMM d, EEEE', 'y MMMM d', 'y MMM d', 'y-MM-dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale nl_AW.
    - */
    -goog.i18n.DateTimeSymbols_nl_AW = {
    -  ERAS: ['v.Chr.', 'n.Chr.'],
    -  ERANAMES: ['voor Christus', 'na Christus'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli',
    -    'augustus', 'september', 'oktober', 'november', 'december'],
    -  STANDALONEMONTHS: ['Januari', 'Februari', 'Maart', 'April', 'Mei', 'Juni',
    -    'Juli', 'Augustus', 'September', 'Oktober', 'November', 'December'],
    -  SHORTMONTHS: ['jan.', 'feb.', 'mrt.', 'apr.', 'mei', 'jun.', 'jul.', 'aug.',
    -    'sep.', 'okt.', 'nov.', 'dec.'],
    -  STANDALONESHORTMONTHS: ['Jan.', 'Feb.', 'Mrt.', 'Apr.', 'Mei', 'Jun.', 'Jul.',
    -    'Aug.', 'Sep.', 'Okt.', 'Nov.', 'Dec.'],
    -  WEEKDAYS: ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag',
    -    'zaterdag'],
    -  STANDALONEWEEKDAYS: ['Zondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag',
    -    'Vrijdag', 'Zaterdag'],
    -  SHORTWEEKDAYS: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
    -  STANDALONESHORTWEEKDAYS: ['Zo', 'Ma', 'Di', 'Wo', 'Do', 'Vr', 'Za'],
    -  NARROWWEEKDAYS: ['Z', 'M', 'D', 'W', 'D', 'V', 'Z'],
    -  STANDALONENARROWWEEKDAYS: ['Z', 'M', 'D', 'W', 'D', 'V', 'Z'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['1e kwartaal', '2e kwartaal', '3e kwartaal', '4e kwartaal'],
    -  AMPMS: ['a.m.', 'p.m.'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd-MM-yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale nl_BE.
    - */
    -goog.i18n.DateTimeSymbols_nl_BE = {
    -  ERAS: ['v.Chr.', 'n.Chr.'],
    -  ERANAMES: ['voor Christus', 'na Christus'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli',
    -    'augustus', 'september', 'oktober', 'november', 'december'],
    -  STANDALONEMONTHS: ['Januari', 'Februari', 'Maart', 'April', 'Mei', 'Juni',
    -    'Juli', 'Augustus', 'September', 'Oktober', 'November', 'December'],
    -  SHORTMONTHS: ['jan.', 'feb.', 'mrt.', 'apr.', 'mei', 'jun.', 'jul.', 'aug.',
    -    'sep.', 'okt.', 'nov.', 'dec.'],
    -  STANDALONESHORTMONTHS: ['Jan.', 'Feb.', 'Mrt.', 'Apr.', 'Mei', 'Jun.', 'Jul.',
    -    'Aug.', 'Sep.', 'Okt.', 'Nov.', 'Dec.'],
    -  WEEKDAYS: ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag',
    -    'zaterdag'],
    -  STANDALONEWEEKDAYS: ['Zondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag',
    -    'Vrijdag', 'Zaterdag'],
    -  SHORTWEEKDAYS: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
    -  STANDALONESHORTWEEKDAYS: ['Zo', 'Ma', 'Di', 'Wo', 'Do', 'Vr', 'Za'],
    -  NARROWWEEKDAYS: ['Z', 'M', 'D', 'W', 'D', 'V', 'Z'],
    -  STANDALONENARROWWEEKDAYS: ['Z', 'M', 'D', 'W', 'D', 'V', 'Z'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['1e kwartaal', '2e kwartaal', '3e kwartaal', '4e kwartaal'],
    -  AMPMS: ['a.m.', 'p.m.'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd-MMM-y', 'd/MM/yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale nl_BQ.
    - */
    -goog.i18n.DateTimeSymbols_nl_BQ = {
    -  ERAS: ['v.Chr.', 'n.Chr.'],
    -  ERANAMES: ['voor Christus', 'na Christus'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli',
    -    'augustus', 'september', 'oktober', 'november', 'december'],
    -  STANDALONEMONTHS: ['Januari', 'Februari', 'Maart', 'April', 'Mei', 'Juni',
    -    'Juli', 'Augustus', 'September', 'Oktober', 'November', 'December'],
    -  SHORTMONTHS: ['jan.', 'feb.', 'mrt.', 'apr.', 'mei', 'jun.', 'jul.', 'aug.',
    -    'sep.', 'okt.', 'nov.', 'dec.'],
    -  STANDALONESHORTMONTHS: ['Jan.', 'Feb.', 'Mrt.', 'Apr.', 'Mei', 'Jun.', 'Jul.',
    -    'Aug.', 'Sep.', 'Okt.', 'Nov.', 'Dec.'],
    -  WEEKDAYS: ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag',
    -    'zaterdag'],
    -  STANDALONEWEEKDAYS: ['Zondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag',
    -    'Vrijdag', 'Zaterdag'],
    -  SHORTWEEKDAYS: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
    -  STANDALONESHORTWEEKDAYS: ['Zo', 'Ma', 'Di', 'Wo', 'Do', 'Vr', 'Za'],
    -  NARROWWEEKDAYS: ['Z', 'M', 'D', 'W', 'D', 'V', 'Z'],
    -  STANDALONENARROWWEEKDAYS: ['Z', 'M', 'D', 'W', 'D', 'V', 'Z'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['1e kwartaal', '2e kwartaal', '3e kwartaal', '4e kwartaal'],
    -  AMPMS: ['a.m.', 'p.m.'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd-MM-yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale nl_CW.
    - */
    -goog.i18n.DateTimeSymbols_nl_CW = {
    -  ERAS: ['v.Chr.', 'n.Chr.'],
    -  ERANAMES: ['voor Christus', 'na Christus'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli',
    -    'augustus', 'september', 'oktober', 'november', 'december'],
    -  STANDALONEMONTHS: ['Januari', 'Februari', 'Maart', 'April', 'Mei', 'Juni',
    -    'Juli', 'Augustus', 'September', 'Oktober', 'November', 'December'],
    -  SHORTMONTHS: ['jan.', 'feb.', 'mrt.', 'apr.', 'mei', 'jun.', 'jul.', 'aug.',
    -    'sep.', 'okt.', 'nov.', 'dec.'],
    -  STANDALONESHORTMONTHS: ['Jan.', 'Feb.', 'Mrt.', 'Apr.', 'Mei', 'Jun.', 'Jul.',
    -    'Aug.', 'Sep.', 'Okt.', 'Nov.', 'Dec.'],
    -  WEEKDAYS: ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag',
    -    'zaterdag'],
    -  STANDALONEWEEKDAYS: ['Zondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag',
    -    'Vrijdag', 'Zaterdag'],
    -  SHORTWEEKDAYS: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
    -  STANDALONESHORTWEEKDAYS: ['Zo', 'Ma', 'Di', 'Wo', 'Do', 'Vr', 'Za'],
    -  NARROWWEEKDAYS: ['Z', 'M', 'D', 'W', 'D', 'V', 'Z'],
    -  STANDALONENARROWWEEKDAYS: ['Z', 'M', 'D', 'W', 'D', 'V', 'Z'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['1e kwartaal', '2e kwartaal', '3e kwartaal', '4e kwartaal'],
    -  AMPMS: ['a.m.', 'p.m.'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd-MM-yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale nl_NL.
    - */
    -goog.i18n.DateTimeSymbols_nl_NL = {
    -  ERAS: ['v.Chr.', 'n.Chr.'],
    -  ERANAMES: ['voor Christus', 'na Christus'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli',
    -    'augustus', 'september', 'oktober', 'november', 'december'],
    -  STANDALONEMONTHS: ['Januari', 'Februari', 'Maart', 'April', 'Mei', 'Juni',
    -    'Juli', 'Augustus', 'September', 'Oktober', 'November', 'December'],
    -  SHORTMONTHS: ['jan.', 'feb.', 'mrt.', 'apr.', 'mei', 'jun.', 'jul.', 'aug.',
    -    'sep.', 'okt.', 'nov.', 'dec.'],
    -  STANDALONESHORTMONTHS: ['Jan.', 'Feb.', 'Mrt.', 'Apr.', 'Mei', 'Jun.', 'Jul.',
    -    'Aug.', 'Sep.', 'Okt.', 'Nov.', 'Dec.'],
    -  WEEKDAYS: ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag',
    -    'zaterdag'],
    -  STANDALONEWEEKDAYS: ['Zondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag',
    -    'Vrijdag', 'Zaterdag'],
    -  SHORTWEEKDAYS: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
    -  STANDALONESHORTWEEKDAYS: ['Zo', 'Ma', 'Di', 'Wo', 'Do', 'Vr', 'Za'],
    -  NARROWWEEKDAYS: ['Z', 'M', 'D', 'W', 'D', 'V', 'Z'],
    -  STANDALONENARROWWEEKDAYS: ['Z', 'M', 'D', 'W', 'D', 'V', 'Z'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['1e kwartaal', '2e kwartaal', '3e kwartaal', '4e kwartaal'],
    -  AMPMS: ['a.m.', 'p.m.'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd-MM-yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale nl_SR.
    - */
    -goog.i18n.DateTimeSymbols_nl_SR = {
    -  ERAS: ['v.Chr.', 'n.Chr.'],
    -  ERANAMES: ['voor Christus', 'na Christus'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli',
    -    'augustus', 'september', 'oktober', 'november', 'december'],
    -  STANDALONEMONTHS: ['Januari', 'Februari', 'Maart', 'April', 'Mei', 'Juni',
    -    'Juli', 'Augustus', 'September', 'Oktober', 'November', 'December'],
    -  SHORTMONTHS: ['jan.', 'feb.', 'mrt.', 'apr.', 'mei', 'jun.', 'jul.', 'aug.',
    -    'sep.', 'okt.', 'nov.', 'dec.'],
    -  STANDALONESHORTMONTHS: ['Jan.', 'Feb.', 'Mrt.', 'Apr.', 'Mei', 'Jun.', 'Jul.',
    -    'Aug.', 'Sep.', 'Okt.', 'Nov.', 'Dec.'],
    -  WEEKDAYS: ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag',
    -    'zaterdag'],
    -  STANDALONEWEEKDAYS: ['Zondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag',
    -    'Vrijdag', 'Zaterdag'],
    -  SHORTWEEKDAYS: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
    -  STANDALONESHORTWEEKDAYS: ['Zo', 'Ma', 'Di', 'Wo', 'Do', 'Vr', 'Za'],
    -  NARROWWEEKDAYS: ['Z', 'M', 'D', 'W', 'D', 'V', 'Z'],
    -  STANDALONENARROWWEEKDAYS: ['Z', 'M', 'D', 'W', 'D', 'V', 'Z'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['1e kwartaal', '2e kwartaal', '3e kwartaal', '4e kwartaal'],
    -  AMPMS: ['a.m.', 'p.m.'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd-MM-yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale nl_SX.
    - */
    -goog.i18n.DateTimeSymbols_nl_SX = {
    -  ERAS: ['v.Chr.', 'n.Chr.'],
    -  ERANAMES: ['voor Christus', 'na Christus'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli',
    -    'augustus', 'september', 'oktober', 'november', 'december'],
    -  STANDALONEMONTHS: ['Januari', 'Februari', 'Maart', 'April', 'Mei', 'Juni',
    -    'Juli', 'Augustus', 'September', 'Oktober', 'November', 'December'],
    -  SHORTMONTHS: ['jan.', 'feb.', 'mrt.', 'apr.', 'mei', 'jun.', 'jul.', 'aug.',
    -    'sep.', 'okt.', 'nov.', 'dec.'],
    -  STANDALONESHORTMONTHS: ['Jan.', 'Feb.', 'Mrt.', 'Apr.', 'Mei', 'Jun.', 'Jul.',
    -    'Aug.', 'Sep.', 'Okt.', 'Nov.', 'Dec.'],
    -  WEEKDAYS: ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag',
    -    'zaterdag'],
    -  STANDALONEWEEKDAYS: ['Zondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag',
    -    'Vrijdag', 'Zaterdag'],
    -  SHORTWEEKDAYS: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
    -  STANDALONESHORTWEEKDAYS: ['Zo', 'Ma', 'Di', 'Wo', 'Do', 'Vr', 'Za'],
    -  NARROWWEEKDAYS: ['Z', 'M', 'D', 'W', 'D', 'V', 'Z'],
    -  STANDALONENARROWWEEKDAYS: ['Z', 'M', 'D', 'W', 'D', 'V', 'Z'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['1e kwartaal', '2e kwartaal', '3e kwartaal', '4e kwartaal'],
    -  AMPMS: ['a.m.', 'p.m.'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'dd-MM-yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale nmg.
    - */
    -goog.i18n.DateTimeSymbols_nmg = {
    -  ERAS: ['BL', 'PB'],
    -  ERANAMES: ['Bó Lahlɛ̄', 'Pfiɛ Burī'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['ngwɛn matáhra', 'ngwɛn ńmba', 'ngwɛn ńlal', 'ngwɛn ńna',
    -    'ngwɛn ńtan', 'ngwɛn ńtuó', 'ngwɛn hɛmbuɛrí', 'ngwɛn lɔmbi',
    -    'ngwɛn rɛbvuâ', 'ngwɛn wum', 'ngwɛn wum navǔr', 'krísimin'],
    -  STANDALONEMONTHS: ['ngwɛn matáhra', 'ngwɛn ńmba', 'ngwɛn ńlal',
    -    'ngwɛn ńna', 'ngwɛn ńtan', 'ngwɛn ńtuó', 'ngwɛn hɛmbuɛrí',
    -    'ngwɛn lɔmbi', 'ngwɛn rɛbvuâ', 'ngwɛn wum', 'ngwɛn wum navǔr',
    -    'krísimin'],
    -  SHORTMONTHS: ['ng1', 'ng2', 'ng3', 'ng4', 'ng5', 'ng6', 'ng7', 'ng8', 'ng9',
    -    'ng10', 'ng11', 'kris'],
    -  STANDALONESHORTMONTHS: ['ng1', 'ng2', 'ng3', 'ng4', 'ng5', 'ng6', 'ng7',
    -    'ng8', 'ng9', 'ng10', 'ng11', 'kris'],
    -  WEEKDAYS: ['sɔ́ndɔ', 'mɔ́ndɔ', 'sɔ́ndɔ mafú mába',
    -    'sɔ́ndɔ mafú málal', 'sɔ́ndɔ mafú mána', 'mabágá má sukul',
    -    'sásadi'],
    -  STANDALONEWEEKDAYS: ['sɔ́ndɔ', 'mɔ́ndɔ', 'sɔ́ndɔ mafú mába',
    -    'sɔ́ndɔ mafú málal', 'sɔ́ndɔ mafú mána', 'mabágá má sukul',
    -    'sásadi'],
    -  SHORTWEEKDAYS: ['sɔ́n', 'mɔ́n', 'smb', 'sml', 'smn', 'mbs', 'sas'],
    -  STANDALONESHORTWEEKDAYS: ['sɔ́n', 'mɔ́n', 'smb', 'sml', 'smn', 'mbs',
    -    'sas'],
    -  NARROWWEEKDAYS: ['s', 'm', 's', 's', 's', 'm', 's'],
    -  STANDALONENARROWWEEKDAYS: ['s', 'm', 's', 's', 's', 'm', 's'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['Tindɛ nvúr', 'Tindɛ ńmba', 'Tindɛ ńlal', 'Tindɛ ńna'],
    -  AMPMS: ['maná', 'kugú'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale nmg_CM.
    - */
    -goog.i18n.DateTimeSymbols_nmg_CM = goog.i18n.DateTimeSymbols_nmg;
    -
    -
    -/**
    - * Date/time formatting symbols for locale nn.
    - */
    -goog.i18n.DateTimeSymbols_nn = {
    -  ERAS: ['f.Kr.', 'e.Kr.'],
    -  ERANAMES: ['f.Kr.', 'e.Kr.'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['januar', 'februar', 'mars', 'april', 'mai', 'juni', 'juli',
    -    'august', 'september', 'oktober', 'november', 'desember'],
    -  STANDALONEMONTHS: ['januar', 'februar', 'mars', 'april', 'mai', 'juni',
    -    'juli', 'august', 'september', 'oktober', 'november', 'desember'],
    -  SHORTMONTHS: ['jan.', 'feb.', 'mars', 'apr.', 'mai', 'juni', 'juli', 'aug.',
    -    'sep.', 'okt.', 'nov.', 'des.'],
    -  STANDALONESHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'mai', 'jun', 'jul',
    -    'aug', 'sep', 'okt', 'nov', 'des'],
    -  WEEKDAYS: ['søndag', 'måndag', 'tysdag', 'onsdag', 'torsdag', 'fredag',
    -    'laurdag'],
    -  STANDALONEWEEKDAYS: ['søndag', 'måndag', 'tysdag', 'onsdag', 'torsdag',
    -    'fredag', 'laurdag'],
    -  SHORTWEEKDAYS: ['sø.', 'må.', 'ty.', 'on.', 'to.', 'fr.', 'la.'],
    -  STANDALONESHORTWEEKDAYS: ['søn', 'mån', 'tys', 'ons', 'tor', 'fre', 'lau'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'O', 'T', 'F', 'L'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'O', 'T', 'F', 'L'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['1. kvartal', '2. kvartal', '3. kvartal', '4. kvartal'],
    -  AMPMS: ['formiddag', 'ettermiddag'],
    -  DATEFORMATS: ['EEEE d. MMMM y', 'd. MMMM y', 'd. MMM y', 'dd.MM.y'],
    -  TIMEFORMATS: ['\'kl\'. HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} \'kl.\' {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale nn_NO.
    - */
    -goog.i18n.DateTimeSymbols_nn_NO = goog.i18n.DateTimeSymbols_nn;
    -
    -
    -/**
    - * Date/time formatting symbols for locale nnh.
    - */
    -goog.i18n.DateTimeSymbols_nnh = {
    -  ERAS: ['m.z.Y.', 'm.g.n.Y.'],
    -  ERANAMES: ['mé zyé Yěsô', 'mé gÿo ńzyé Yěsô'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['saŋ tsetsɛ̀ɛ lùm', 'saŋ kàg ngwóŋ', 'saŋ lepyè shúm',
    -    'saŋ cÿó', 'saŋ tsɛ̀ɛ cÿó', 'saŋ njÿoláʼ',
    -    'saŋ tyɛ̀b tyɛ̀b mbʉ̀', 'saŋ mbʉ̀ŋ', 'saŋ ngwɔ̀ʼ mbÿɛ',
    -    'saŋ tàŋa tsetsáʼ', 'saŋ mejwoŋó', 'saŋ lùm'],
    -  STANDALONEMONTHS: ['saŋ tsetsɛ̀ɛ lùm', 'saŋ kàg ngwóŋ',
    -    'saŋ lepyè shúm', 'saŋ cÿó', 'saŋ tsɛ̀ɛ cÿó', 'saŋ njÿoláʼ',
    -    'saŋ tyɛ̀b tyɛ̀b mbʉ̀', 'saŋ mbʉ̀ŋ', 'saŋ ngwɔ̀ʼ mbÿɛ',
    -    'saŋ tàŋa tsetsáʼ', 'saŋ mejwoŋó', 'saŋ lùm'],
    -  SHORTMONTHS: ['saŋ tsetsɛ̀ɛ lùm', 'saŋ kàg ngwóŋ',
    -    'saŋ lepyè shúm', 'saŋ cÿó', 'saŋ tsɛ̀ɛ cÿó', 'saŋ njÿoláʼ',
    -    'saŋ tyɛ̀b tyɛ̀b mbʉ̀', 'saŋ mbʉ̀ŋ', 'saŋ ngwɔ̀ʼ mbÿɛ',
    -    'saŋ tàŋa tsetsáʼ', 'saŋ mejwoŋó', 'saŋ lùm'],
    -  STANDALONESHORTMONTHS: ['saŋ tsetsɛ̀ɛ lùm', 'saŋ kàg ngwóŋ',
    -    'saŋ lepyè shúm', 'saŋ cÿó', 'saŋ tsɛ̀ɛ cÿó', 'saŋ njÿoláʼ',
    -    'saŋ tyɛ̀b tyɛ̀b mbʉ̀', 'saŋ mbʉ̀ŋ', 'saŋ ngwɔ̀ʼ mbÿɛ',
    -    'saŋ tàŋa tsetsáʼ', 'saŋ mejwoŋó', 'saŋ lùm'],
    -  WEEKDAYS: ['lyɛʼɛ́ sẅíŋtè', 'mvfò lyɛ̌ʼ',
    -    'mbɔ́ɔntè mvfò lyɛ̌ʼ', 'tsètsɛ̀ɛ lyɛ̌ʼ',
    -    'mbɔ́ɔntè tsetsɛ̀ɛ lyɛ̌ʼ', 'mvfò màga lyɛ̌ʼ',
    -    'màga lyɛ̌ʼ'],
    -  STANDALONEWEEKDAYS: ['lyɛʼɛ́ sẅíŋtè', 'mvfò lyɛ̌ʼ',
    -    'mbɔ́ɔntè mvfò lyɛ̌ʼ', 'tsètsɛ̀ɛ lyɛ̌ʼ',
    -    'mbɔ́ɔntè tsetsɛ̀ɛ lyɛ̌ʼ', 'mvfò màga lyɛ̌ʼ',
    -    'màga lyɛ̌ʼ'],
    -  SHORTWEEKDAYS: ['lyɛʼɛ́ sẅíŋtè', 'mvfò lyɛ̌ʼ',
    -    'mbɔ́ɔntè mvfò lyɛ̌ʼ', 'tsètsɛ̀ɛ lyɛ̌ʼ',
    -    'mbɔ́ɔntè tsetsɛ̀ɛ lyɛ̌ʼ', 'mvfò màga lyɛ̌ʼ',
    -    'màga lyɛ̌ʼ'],
    -  STANDALONESHORTWEEKDAYS: ['lyɛʼɛ́ sẅíŋtè', 'mvfò lyɛ̌ʼ',
    -    'mbɔ́ɔntè mvfò lyɛ̌ʼ', 'tsètsɛ̀ɛ lyɛ̌ʼ',
    -    'mbɔ́ɔntè tsetsɛ̀ɛ lyɛ̌ʼ', 'mvfò màga lyɛ̌ʼ',
    -    'màga lyɛ̌ʼ'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['mbaʼámbaʼ', 'ncwònzém'],
    -  DATEFORMATS: ['EEEE , \'lyɛ\'̌ʼ d \'na\' MMMM, y',
    -    '\'lyɛ\'̌ʼ d \'na\' MMMM, y', 'd MMM, y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1},{0}', '{1}, {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale nnh_CM.
    - */
    -goog.i18n.DateTimeSymbols_nnh_CM = goog.i18n.DateTimeSymbols_nnh;
    -
    -
    -/**
    - * Date/time formatting symbols for locale nr.
    - */
    -goog.i18n.DateTimeSymbols_nr = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['BC', 'AD'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['Janabari', 'uFeberbari', 'uMatjhi', 'u-Apreli', 'Meyi', 'Juni',
    -    'Julayi', 'Arhostosi', 'Septemba', 'Oktoba', 'Usinyikhaba', 'Disemba'],
    -  STANDALONEMONTHS: ['Janabari', 'uFeberbari', 'uMatjhi', 'u-Apreli', 'Meyi',
    -    'Juni', 'Julayi', 'Arhostosi', 'Septemba', 'Oktoba', 'Usinyikhaba',
    -    'Disemba'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mat', 'Apr', 'Mey', 'Jun', 'Jul', 'Arh', 'Sep',
    -    'Okt', 'Usi', 'Dis'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mat', 'Apr', 'Mey', 'Jun', 'Jul',
    -    'Arh', 'Sep', 'Okt', 'Usi', 'Dis'],
    -  WEEKDAYS: ['uSonto', 'uMvulo', 'uLesibili', 'Lesithathu', 'uLesine',
    -    'ngoLesihlanu', 'umGqibelo'],
    -  STANDALONEWEEKDAYS: ['uSonto', 'uMvulo', 'uLesibili', 'Lesithathu', 'uLesine',
    -    'ngoLesihlanu', 'umGqibelo'],
    -  SHORTWEEKDAYS: ['Son', 'Mvu', 'Bil', 'Tha', 'Ne', 'Hla', 'Gqi'],
    -  STANDALONESHORTWEEKDAYS: ['Son', 'Mvu', 'Bil', 'Tha', 'Ne', 'Hla', 'Gqi'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['y MMMM d, EEEE', 'y MMMM d', 'y MMM d', 'y-MM-dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale nr_ZA.
    - */
    -goog.i18n.DateTimeSymbols_nr_ZA = goog.i18n.DateTimeSymbols_nr;
    -
    -
    -/**
    - * Date/time formatting symbols for locale nso.
    - */
    -goog.i18n.DateTimeSymbols_nso = {
    -  ERAS: ['BCE', 'CE'],
    -  ERANAMES: ['BCE', 'CE'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['Janaware', 'Feberware', 'Matšhe', 'Aporele', 'Mei', 'June',
    -    'Julae', 'Agostose', 'Setemere', 'Oktobore', 'Nofemere', 'Disemere'],
    -  STANDALONEMONTHS: ['Janaware', 'Feberware', 'Matšhe', 'Aporele', 'Mei',
    -    'June', 'Julae', 'Agostose', 'Setemere', 'Oktobore', 'Nofemere',
    -    'Disemere'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mat', 'Apo', 'Mei', 'Jun', 'Jul', 'Ago', 'Set',
    -    'Okt', 'Nof', 'Dis'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mat', 'Apo', 'Mei', 'Jun', 'Jul',
    -    'Ago', 'Set', 'Okt', 'Nof', 'Dis'],
    -  WEEKDAYS: ['Sontaga', 'Mosupalogo', 'Labobedi', 'Laboraro', 'Labone',
    -    'Labohlano', 'Mokibelo'],
    -  STANDALONEWEEKDAYS: ['Sontaga', 'Mosupalogo', 'Labobedi', 'Laboraro',
    -    'Labone', 'Labohlano', 'Mokibelo'],
    -  SHORTWEEKDAYS: ['Son', 'Mos', 'Bed', 'Rar', 'Ne', 'Hla', 'Mok'],
    -  STANDALONESHORTWEEKDAYS: ['Son', 'Mos', 'Bed', 'Rar', 'Ne', 'Hla', 'Mok'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['y MMMM d, EEEE', 'y MMMM d', 'y MMM d', 'y-MM-dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale nso_ZA.
    - */
    -goog.i18n.DateTimeSymbols_nso_ZA = goog.i18n.DateTimeSymbols_nso;
    -
    -
    -/**
    - * Date/time formatting symbols for locale nus.
    - */
    -goog.i18n.DateTimeSymbols_nus = {
    -  ERAS: ['AY', 'ƐY'],
    -  ERANAMES: ['A ka̱n Yecu ni dap', 'Ɛ ca Yecu dap'],
    -  NARROWMONTHS: ['T', 'P', 'D', 'G', 'D', 'K', 'P', 'T', 'T', 'L', 'K', 'T'],
    -  STANDALONENARROWMONTHS: ['T', 'P', 'D', 'G', 'D', 'K', 'P', 'T', 'T', 'L',
    -    'K', 'T'],
    -  MONTHS: ['Tiop thar pɛt', 'Pɛt', 'Duɔ̱ɔ̱ŋ', 'Guak', 'Duät',
    -    'Kornyoot', 'Pay yie̱tni', 'Tho̱o̱r', 'Tɛɛr', 'Laath', 'Kur',
    -    'Tio̱p in di̱i̱t'],
    -  STANDALONEMONTHS: ['Tiop thar pɛt', 'Pɛt', 'Duɔ̱ɔ̱ŋ', 'Guak', 'Duät',
    -    'Kornyoot', 'Pay yie̱tni', 'Tho̱o̱r', 'Tɛɛr', 'Laath', 'Kur',
    -    'Tio̱p in di̱i̱t'],
    -  SHORTMONTHS: ['Tiop', 'Pɛt', 'Duɔ̱ɔ̱', 'Guak', 'Duä', 'Kor', 'Pay',
    -    'Thoo', 'Tɛɛ', 'Laa', 'Kur', 'Tid'],
    -  STANDALONESHORTMONTHS: ['Tiop', 'Pɛt', 'Duɔ̱ɔ̱', 'Guak', 'Duä', 'Kor',
    -    'Pay', 'Thoo', 'Tɛɛ', 'Laa', 'Kur', 'Tid'],
    -  WEEKDAYS: ['Cäŋ kuɔth', 'Jiec la̱t', 'Rɛw lätni', 'Diɔ̱k lätni',
    -    'Ŋuaan lätni', 'Dhieec lätni', 'Bäkɛl lätni'],
    -  STANDALONEWEEKDAYS: ['Cäŋ kuɔth', 'Jiec la̱t', 'Rɛw lätni',
    -    'Diɔ̱k lätni', 'Ŋuaan lätni', 'Dhieec lätni', 'Bäkɛl lätni'],
    -  SHORTWEEKDAYS: ['Cäŋ', 'Jiec', 'Rɛw', 'Diɔ̱k', 'Ŋuaan', 'Dhieec',
    -    'Bäkɛl'],
    -  STANDALONESHORTWEEKDAYS: ['Cäŋ', 'Jiec', 'Rɛw', 'Diɔ̱k', 'Ŋuaan',
    -    'Dhieec', 'Bäkɛl'],
    -  NARROWWEEKDAYS: ['C', 'J', 'R', 'D', 'Ŋ', 'D', 'B'],
    -  STANDALONENARROWWEEKDAYS: ['C', 'J', 'R', 'D', 'Ŋ', 'D', 'B'],
    -  SHORTQUARTERS: ['P1', 'P2', 'P3', 'P4'],
    -  QUARTERS: ['Päth diɔk tin nhiam', 'Päth diɔk tin guurɛ',
    -    'Päth diɔk tin wä kɔɔriɛn', 'Päth diɔk tin jiɔakdiɛn'],
    -  AMPMS: ['RW', 'TŊ'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'd/MM/y'],
    -  TIMEFORMATS: ['zzzz h:mm:ss a', 'z h:mm:ss a', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale nus_SD.
    - */
    -goog.i18n.DateTimeSymbols_nus_SD = goog.i18n.DateTimeSymbols_nus;
    -
    -
    -/**
    - * Date/time formatting symbols for locale nyn.
    - */
    -goog.i18n.DateTimeSymbols_nyn = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Kurisito Atakaijire', 'Kurisito Yaijire'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Okwokubanza', 'Okwakabiri', 'Okwakashatu', 'Okwakana',
    -    'Okwakataana', 'Okwamukaaga', 'Okwamushanju', 'Okwamunaana', 'Okwamwenda',
    -    'Okwaikumi', 'Okwaikumi na kumwe', 'Okwaikumi na ibiri'],
    -  STANDALONEMONTHS: ['Okwokubanza', 'Okwakabiri', 'Okwakashatu', 'Okwakana',
    -    'Okwakataana', 'Okwamukaaga', 'Okwamushanju', 'Okwamunaana', 'Okwamwenda',
    -    'Okwaikumi', 'Okwaikumi na kumwe', 'Okwaikumi na ibiri'],
    -  SHORTMONTHS: ['KBZ', 'KBR', 'KST', 'KKN', 'KTN', 'KMK', 'KMS', 'KMN', 'KMW',
    -    'KKM', 'KNK', 'KNB'],
    -  STANDALONESHORTMONTHS: ['KBZ', 'KBR', 'KST', 'KKN', 'KTN', 'KMK', 'KMS',
    -    'KMN', 'KMW', 'KKM', 'KNK', 'KNB'],
    -  WEEKDAYS: ['Sande', 'Orwokubanza', 'Orwakabiri', 'Orwakashatu', 'Orwakana',
    -    'Orwakataano', 'Orwamukaaga'],
    -  STANDALONEWEEKDAYS: ['Sande', 'Orwokubanza', 'Orwakabiri', 'Orwakashatu',
    -    'Orwakana', 'Orwakataano', 'Orwamukaaga'],
    -  SHORTWEEKDAYS: ['SAN', 'ORK', 'OKB', 'OKS', 'OKN', 'OKT', 'OMK'],
    -  STANDALONESHORTWEEKDAYS: ['SAN', 'ORK', 'OKB', 'OKS', 'OKN', 'OKT', 'OMK'],
    -  NARROWWEEKDAYS: ['S', 'K', 'R', 'S', 'N', 'T', 'M'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'K', 'R', 'S', 'N', 'T', 'M'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['KWOTA 1', 'KWOTA 2', 'KWOTA 3', 'KWOTA 4'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale nyn_UG.
    - */
    -goog.i18n.DateTimeSymbols_nyn_UG = goog.i18n.DateTimeSymbols_nyn;
    -
    -
    -/**
    - * Date/time formatting symbols for locale om.
    - */
    -goog.i18n.DateTimeSymbols_om = {
    -  ERAS: ['KD', 'KB'],
    -  ERANAMES: ['KD', 'KB'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Amajjii', 'Guraandhala', 'Bitooteessa', 'Elba', 'Caamsa',
    -    'Waxabajjii', 'Adooleessa', 'Hagayya', 'Fuulbana', 'Onkololeessa',
    -    'Sadaasa', 'Muddee'],
    -  STANDALONEMONTHS: ['Amajjii', 'Guraandhala', 'Bitooteessa', 'Elba', 'Caamsa',
    -    'Waxabajjii', 'Adooleessa', 'Hagayya', 'Fuulbana', 'Onkololeessa',
    -    'Sadaasa', 'Muddee'],
    -  SHORTMONTHS: ['Ama', 'Gur', 'Bit', 'Elb', 'Cam', 'Wax', 'Ado', 'Hag', 'Ful',
    -    'Onk', 'Sad', 'Mud'],
    -  STANDALONESHORTMONTHS: ['Ama', 'Gur', 'Bit', 'Elb', 'Cam', 'Wax', 'Ado',
    -    'Hag', 'Ful', 'Onk', 'Sad', 'Mud'],
    -  WEEKDAYS: ['Dilbata', 'Wiixata', 'Qibxata', 'Roobii', 'Kamiisa', 'Jimaata',
    -    'Sanbata'],
    -  STANDALONEWEEKDAYS: ['Dilbata', 'Wiixata', 'Qibxata', 'Roobii', 'Kamiisa',
    -    'Jimaata', 'Sanbata'],
    -  SHORTWEEKDAYS: ['Dil', 'Wix', 'Qib', 'Rob', 'Kam', 'Jim', 'San'],
    -  STANDALONESHORTWEEKDAYS: ['Dil', 'Wix', 'Qib', 'Rob', 'Kam', 'Jim', 'San'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['WD', 'WB'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'dd MMMM y', 'dd-MMM-y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale om_ET.
    - */
    -goog.i18n.DateTimeSymbols_om_ET = goog.i18n.DateTimeSymbols_om;
    -
    -
    -/**
    - * Date/time formatting symbols for locale om_KE.
    - */
    -goog.i18n.DateTimeSymbols_om_KE = goog.i18n.DateTimeSymbols_om;
    -
    -
    -/**
    - * Date/time formatting symbols for locale or_IN.
    - */
    -goog.i18n.DateTimeSymbols_or_IN = {
    -  ERAS: ['BCE', 'CE'],
    -  ERANAMES: ['BCE', 'CE'],
    -  NARROWMONTHS: ['ଜା', 'ଫେ', 'ମା', 'ଅ', 'ମଇ', 'ଜୁ',
    -    'ଜୁ', 'ଅ', 'ସେ', 'ଅ', 'ନ', 'ଡି'],
    -  STANDALONENARROWMONTHS: ['ଜା', 'ଫେ', 'ମା', 'ଅ', 'ମଇ',
    -    'ଜୁ', 'ଜୁ', 'ଅ', 'ସେ', 'ଅ', 'ନ', 'ଡି'],
    -  MONTHS: ['ଜାନୁଆରୀ', 'ଫେବୃଆରୀ',
    -    'ମାର୍ଚ୍ଚ', 'ଅପ୍ରେଲ', 'ମଇ', 'ଜୁନ',
    -    'ଜୁଲାଇ', 'ଅଗଷ୍ଟ', 'ସେପ୍ଟେମ୍ବର',
    -    'ଅକ୍ଟୋବର', 'ନଭେମ୍ବର',
    -    'ଡିସେମ୍ବର'],
    -  STANDALONEMONTHS: ['ଜାନୁଆରୀ', 'ଫେବୃଆରୀ',
    -    'ମାର୍ଚ୍ଚ', 'ଅପ୍ରେଲ', 'ମଇ', 'ଜୁନ',
    -    'ଜୁଲାଇ', 'ଅଗଷ୍ଟ', 'ସେପ୍ଟେମ୍ବର',
    -    'ଅକ୍ଟୋବର', 'ନଭେମ୍ବର',
    -    'ଡିସେମ୍ବର'],
    -  SHORTMONTHS: ['ଜାନୁଆରୀ', 'ଫେବୃଆରୀ',
    -    'ମାର୍ଚ୍ଚ', 'ଅପ୍ରେଲ', 'ମଇ', 'ଜୁନ',
    -    'ଜୁଲାଇ', 'ଅଗଷ୍ଟ', 'ସେପ୍ଟେମ୍ବର',
    -    'ଅକ୍ଟୋବର', 'ନଭେମ୍ବର',
    -    'ଡିସେମ୍ବର'],
    -  STANDALONESHORTMONTHS: ['ଜାନୁଆରୀ', 'ଫେବୃଆରୀ',
    -    'ମାର୍ଚ୍ଚ', 'ଅପ୍ରେଲ', 'ମଇ', 'ଜୁନ',
    -    'ଜୁଲାଇ', 'ଅଗଷ୍ଟ', 'ସେପ୍ଟେମ୍ବର',
    -    'ଅକ୍ଟୋବର', 'ନଭେମ୍ବର',
    -    'ଡିସେମ୍ବର'],
    -  WEEKDAYS: ['ରବିବାର', 'ସୋମବାର',
    -    'ମଙ୍ଗଳବାର', 'ବୁଧବାର', 'ଗୁରୁବାର',
    -    'ଶୁକ୍ରବାର', 'ଶନିବାର'],
    -  STANDALONEWEEKDAYS: ['ରବିବାର', 'ସୋମବାର',
    -    'ମଙ୍ଗଳବାର', 'ବୁଧବାର', 'ଗୁରୁବାର',
    -    'ଶୁକ୍ରବାର', 'ଶନିବାର'],
    -  SHORTWEEKDAYS: ['ରବି', 'ସୋମ', 'ମଙ୍ଗଳ', 'ବୁଧ',
    -    'ଗୁରୁ', 'ଶୁକ୍ର', 'ଶନି'],
    -  STANDALONESHORTWEEKDAYS: ['ରବି', 'ସୋମ', 'ମଙ୍ଗଳ',
    -    'ବୁଧ', 'ଗୁରୁ', 'ଶୁକ୍ର', 'ଶନି'],
    -  NARROWWEEKDAYS: ['ର', 'ସୋ', 'ମ', 'ବୁ', 'ଗୁ', 'ଶୁ', 'ଶ'],
    -  STANDALONENARROWWEEKDAYS: ['ର', 'ସୋ', 'ମ', 'ବୁ', 'ଗୁ',
    -    'ଶୁ', 'ଶ'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['am', 'pm'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'd-M-yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [6, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale os.
    - */
    -goog.i18n.DateTimeSymbols_os = {
    -  ERAS: ['н.д.а.', 'н.д.'],
    -  ERANAMES: ['н.д.а.', 'н.д.'],
    -  NARROWMONTHS: ['Я', 'Ф', 'М', 'А', 'М', 'И', 'И', 'А', 'С', 'О',
    -    'Н', 'Д'],
    -  STANDALONENARROWMONTHS: ['Я', 'Ф', 'М', 'А', 'М', 'И', 'И', 'А', 'С',
    -    'О', 'Н', 'Д'],
    -  MONTHS: ['январы', 'февралы', 'мартъийы', 'апрелы',
    -    'майы', 'июны', 'июлы', 'августы', 'сентябры',
    -    'октябры', 'ноябры', 'декабры'],
    -  STANDALONEMONTHS: ['Январь', 'Февраль', 'Мартъи',
    -    'Апрель', 'Май', 'Июнь', 'Июль', 'Август',
    -    'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'],
    -  SHORTMONTHS: ['янв.', 'фев.', 'мар.', 'апр.', 'мая',
    -    'июны', 'июлы', 'авг.', 'сен.', 'окт.', 'ноя.',
    -    'дек.'],
    -  STANDALONESHORTMONTHS: ['Янв.', 'Февр.', 'Март', 'Апр.',
    -    'Май', 'Июнь', 'Июль', 'Авг.', 'Сент.', 'Окт.',
    -    'Нояб.', 'Дек.'],
    -  WEEKDAYS: ['хуыцаубон', 'къуырисӕр', 'дыццӕг',
    -    'ӕртыццӕг', 'цыппӕрӕм', 'майрӕмбон', 'сабат'],
    -  STANDALONEWEEKDAYS: ['Хуыцаубон', 'Къуырисӕр',
    -    'Дыццӕг', 'Ӕртыццӕг', 'Цыппӕрӕм',
    -    'Майрӕмбон', 'Сабат'],
    -  SHORTWEEKDAYS: ['хцб', 'крс', 'дцг', 'ӕрт', 'цпр', 'мрб',
    -    'сбт'],
    -  STANDALONESHORTWEEKDAYS: ['Хцб', 'Крс', 'Дцг', 'Ӕрт', 'Цпр',
    -    'Мрб', 'Сбт'],
    -  NARROWWEEKDAYS: ['Х', 'К', 'Д', 'Ӕ', 'Ц', 'М', 'С'],
    -  STANDALONENARROWWEEKDAYS: ['Х', 'К', 'Д', 'Ӕ', 'Ц', 'М', 'С'],
    -  SHORTQUARTERS: ['1-аг кв.', '2-аг кв.', '3-аг кв.',
    -    '4-ӕм кв.'],
    -  QUARTERS: ['1-аг квартал', '2-аг квартал',
    -    '3-аг квартал', '4-ӕм квартал'],
    -  AMPMS: ['ӕмбисбоны размӕ', 'ӕмбисбоны фӕстӕ'],
    -  DATEFORMATS: ['EEEE, d MMMM, y \'аз\'', 'd MMMM, y \'аз\'',
    -    'dd MMM y \'аз\'', 'dd.MM.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale os_GE.
    - */
    -goog.i18n.DateTimeSymbols_os_GE = goog.i18n.DateTimeSymbols_os;
    -
    -
    -/**
    - * Date/time formatting symbols for locale os_RU.
    - */
    -goog.i18n.DateTimeSymbols_os_RU = goog.i18n.DateTimeSymbols_os;
    -
    -
    -/**
    - * Date/time formatting symbols for locale pa_Arab.
    - */
    -goog.i18n.DateTimeSymbols_pa_Arab = {
    -  ZERODIGIT: 0x06F0,
    -  ERAS: ['BCE', 'CE'],
    -  ERANAMES: ['ايساپورو', 'سں'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئ',
    -    'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر',
    -    'نومبر', 'دسمبر'],
    -  STANDALONEMONTHS: ['جنوری', 'فروری', 'مارچ', 'اپریل',
    -    'مئ', 'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر',
    -    'نومبر', 'دسمبر'],
    -  SHORTMONTHS: ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئ',
    -    'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر',
    -    'نومبر', 'دسمبر'],
    -  STANDALONESHORTMONTHS: ['جنوری', 'فروری', 'مارچ', 'اپریل',
    -    'مئ', 'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر',
    -    'نومبر', 'دسمبر'],
    -  WEEKDAYS: ['اتوار', 'پیر', 'منگل', 'بُدھ', 'جمعرات',
    -    'جمعہ', 'ہفتہ'],
    -  STANDALONEWEEKDAYS: ['اتوار', 'پیر', 'منگل', 'بُدھ',
    -    'جمعرات', 'جمعہ', 'ہفتہ'],
    -  SHORTWEEKDAYS: ['اتوار', 'پیر', 'منگل', 'بُدھ',
    -    'جمعرات', 'جمعہ', 'ہفتہ'],
    -  STANDALONESHORTWEEKDAYS: ['اتوار', 'پیر', 'منگل', 'بُدھ',
    -    'جمعرات', 'جمعہ', 'ہفتہ'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['چوتھاي پہلاں', 'چوتھاي دوجا',
    -    'چوتھاي تيجا', 'چوتھاي چوتھا'],
    -  QUARTERS: ['چوتھاي پہلاں', 'چوتھاي دوجا',
    -    'چوتھاي تيجا', 'چوتھاي چوتھا'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, dd MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale pa_Arab_PK.
    - */
    -goog.i18n.DateTimeSymbols_pa_Arab_PK = goog.i18n.DateTimeSymbols_pa_Arab;
    -
    -
    -/**
    - * Date/time formatting symbols for locale pa_Guru.
    - */
    -goog.i18n.DateTimeSymbols_pa_Guru = {
    -  ERAS: ['ਈ. ਪੂ.', 'ਸੰਨ'],
    -  ERANAMES: ['ਈਸਵੀ ਪੂਰਵ', 'ਈਸਵੀ ਸੰਨ'],
    -  NARROWMONTHS: ['ਜ', 'ਫ਼', 'ਮਾ', 'ਅ', 'ਮ', 'ਜੂ', 'ਜੁ',
    -    'ਅ', 'ਸ', 'ਅ', 'ਨ', 'ਦ'],
    -  STANDALONENARROWMONTHS: ['ਜ', 'ਫ਼', 'ਮਾ', 'ਅ', 'ਮ', 'ਜੂ',
    -    'ਜੁ', 'ਅ', 'ਸ', 'ਅ', 'ਨ', 'ਦ'],
    -  MONTHS: ['ਜਨਵਰੀ', 'ਫ਼ਰਵਰੀ', 'ਮਾਰਚ',
    -    'ਅਪ੍ਰੈਲ', 'ਮਈ', 'ਜੂਨ', 'ਜੁਲਾਈ',
    -    'ਅਗਸਤ', 'ਸਤੰਬਰ', 'ਅਕਤੂਬਰ', 'ਨਵੰਬਰ',
    -    'ਦਸੰਬਰ'],
    -  STANDALONEMONTHS: ['ਜਨਵਰੀ', 'ਫ਼ਰਵਰੀ', 'ਮਾਰਚ',
    -    'ਅਪ੍ਰੈਲ', 'ਮਈ', 'ਜੂਨ', 'ਜੁਲਾਈ',
    -    'ਅਗਸਤ', 'ਸਤੰਬਰ', 'ਅਕਤੂਬਰ', 'ਨਵੰਬਰ',
    -    'ਦਸੰਬਰ'],
    -  SHORTMONTHS: ['ਜਨ', 'ਫ਼ਰ', 'ਮਾਰਚ', 'ਅਪ੍ਰੈ',
    -    'ਮਈ', 'ਜੂਨ', 'ਜੁਲਾ', 'ਅਗ', 'ਸਤੰ',
    -    'ਅਕਤੂ', 'ਨਵੰ', 'ਦਸੰ'],
    -  STANDALONESHORTMONTHS: ['ਜਨ', 'ਫ਼ਰ', 'ਮਾਰਚ',
    -    'ਅਪ੍ਰੈ', 'ਮਈ', 'ਜੂਨ', 'ਜੁਲਾ', 'ਅਗ',
    -    'ਸਤੰ', 'ਅਕਤੂ', 'ਨਵੰ', 'ਦਸੰ'],
    -  WEEKDAYS: ['ਐਤਵਾਰ', 'ਸੋਮਵਾਰ', 'ਮੰਗਲਵਾਰ',
    -    'ਬੁੱਧਵਾਰ', 'ਵੀਰਵਾਰ',
    -    'ਸ਼ੁੱਕਰਵਾਰ', 'ਸ਼ਨਿੱਚਰਵਾਰ'],
    -  STANDALONEWEEKDAYS: ['ਐਤਵਾਰ', 'ਸੋਮਵਾਰ',
    -    'ਮੰਗਲਵਾਰ', 'ਬੁੱਧਵਾਰ', 'ਵੀਰਵਾਰ',
    -    'ਸ਼ੁੱਕਰਵਾਰ', 'ਸ਼ਨਿੱਚਰਵਾਰ'],
    -  SHORTWEEKDAYS: ['ਐਤ', 'ਸੋਮ', 'ਮੰਗਲ', 'ਬੁੱਧ',
    -    'ਵੀਰ', 'ਸ਼ੁੱਕਰ', 'ਸ਼ਨਿੱਚਰ'],
    -  STANDALONESHORTWEEKDAYS: ['ਐਤ', 'ਸੋਮ', 'ਮੰਗਲ',
    -    'ਬੁੱਧ', 'ਵੀਰ', 'ਸ਼ੁੱਕਰ', 'ਸ਼ਨਿੱਚਰ'],
    -  NARROWWEEKDAYS: ['ਐ', 'ਸੋ', 'ਮੰ', 'ਬੁੱ', 'ਵੀ',
    -    'ਸ਼ੁੱ', 'ਸ਼'],
    -  STANDALONENARROWWEEKDAYS: ['ਐ', 'ਸੋ', 'ਮੰ', 'ਬੁੱ', 'ਵੀ',
    -    'ਸ਼ੁੱ', 'ਸ਼'],
    -  SHORTQUARTERS: ['ਤਿਮਾਹੀ1', 'ਤਿਮਾਹੀ2',
    -    'ਤਿਮਾਹੀ3', 'ਤਿਮਾਹੀ4'],
    -  QUARTERS: ['ਪਹਿਲੀ ਤਿਮਾਹੀ',
    -    'ਦੂਜੀ ਤਿਮਾਹੀ', 'ਤੀਜੀ ਤਿਮਾਹੀ',
    -    'ਚੌਥੀ ਤਿਮਾਹੀ'],
    -  AMPMS: ['ਪੂ.ਦੁ.', 'ਬਾ.ਦੁ.'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [6, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale pa_Guru_IN.
    - */
    -goog.i18n.DateTimeSymbols_pa_Guru_IN = goog.i18n.DateTimeSymbols_pa_Guru;
    -
    -
    -/**
    - * Date/time formatting symbols for locale pl_PL.
    - */
    -goog.i18n.DateTimeSymbols_pl_PL = {
    -  ERAS: ['p.n.e.', 'n.e.'],
    -  ERANAMES: ['p.n.e.', 'n.e.'],
    -  NARROWMONTHS: ['s', 'l', 'm', 'k', 'm', 'c', 'l', 's', 'w', 'p', 'l', 'g'],
    -  STANDALONENARROWMONTHS: ['s', 'l', 'm', 'k', 'm', 'c', 'l', 's', 'w', 'p',
    -    'l', 'g'],
    -  MONTHS: ['stycznia', 'lutego', 'marca', 'kwietnia', 'maja', 'czerwca',
    -    'lipca', 'sierpnia', 'września', 'października', 'listopada', 'grudnia'],
    -  STANDALONEMONTHS: ['styczeń', 'luty', 'marzec', 'kwiecień', 'maj',
    -    'czerwiec', 'lipiec', 'sierpień', 'wrzesień', 'październik', 'listopad',
    -    'grudzień'],
    -  SHORTMONTHS: ['sty', 'lut', 'mar', 'kwi', 'maj', 'cze', 'lip', 'sie', 'wrz',
    -    'paź', 'lis', 'gru'],
    -  STANDALONESHORTMONTHS: ['sty', 'lut', 'mar', 'kwi', 'maj', 'cze', 'lip',
    -    'sie', 'wrz', 'paź', 'lis', 'gru'],
    -  WEEKDAYS: ['niedziela', 'poniedziałek', 'wtorek', 'środa', 'czwartek',
    -    'piątek', 'sobota'],
    -  STANDALONEWEEKDAYS: ['niedziela', 'poniedziałek', 'wtorek', 'środa',
    -    'czwartek', 'piątek', 'sobota'],
    -  SHORTWEEKDAYS: ['niedz.', 'pon.', 'wt.', 'śr.', 'czw.', 'pt.', 'sob.'],
    -  STANDALONESHORTWEEKDAYS: ['niedz.', 'pon.', 'wt.', 'śr.', 'czw.', 'pt.',
    -    'sob.'],
    -  NARROWWEEKDAYS: ['N', 'P', 'W', 'Ś', 'C', 'P', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['N', 'P', 'W', 'Ś', 'C', 'P', 'S'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['I kwartał', 'II kwartał', 'III kwartał', 'IV kwartał'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd.MM.y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ps.
    - */
    -goog.i18n.DateTimeSymbols_ps = {
    -  ZERODIGIT: 0x06F0,
    -  ERAS: ['ق.م.', 'م.'],
    -  ERANAMES: ['ق.م.', 'م.'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['جنوري', 'فبروري', 'مارچ', 'اپریل', 'می',
    -    'جون', 'جولای', 'اګست', 'سپتمبر', 'اکتوبر',
    -    'نومبر', 'دسمبر'],
    -  STANDALONEMONTHS: ['جنوري', 'فبروري', 'مارچ', 'اپریل',
    -    'می', 'جون', 'جولای', 'اګست', 'سپتمبر', 'اکتوبر',
    -    'نومبر', 'دسمبر'],
    -  SHORTMONTHS: ['جنوري', 'فبروري', 'مارچ', 'اپریل', 'می',
    -    'جون', 'جولای', 'اګست', 'سپتمبر', 'اکتوبر',
    -    'نومبر', 'دسمبر'],
    -  STANDALONESHORTMONTHS: ['جنوري', 'فبروري', 'مارچ',
    -    'اپریل', 'می', 'جون', 'جولای', 'اګست', 'سپتمبر',
    -    'اکتوبر', 'نومبر', 'دسمبر'],
    -  WEEKDAYS: ['یکشنبه', 'دوشنبه', 'سه‌شنبه',
    -    'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'],
    -  STANDALONEWEEKDAYS: ['یکشنبه', 'دوشنبه', 'سه‌شنبه',
    -    'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'],
    -  SHORTWEEKDAYS: ['یکشنبه', 'دوشنبه', 'سه‌شنبه',
    -    'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'],
    -  STANDALONESHORTWEEKDAYS: ['یکشنبه', 'دوشنبه', 'سه‌شنبه',
    -    'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['غ.م.', 'غ.و.'],
    -  DATEFORMATS: ['EEEE د y د MMMM d', 'د y د MMMM d', 'd MMM y', 'y/M/d'],
    -  TIMEFORMATS: ['H:mm:ss (zzzz)', 'H:mm:ss (z)', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 5,
    -  WEEKENDRANGE: [3, 4],
    -  FIRSTWEEKCUTOFFDAY: 4
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ps_AF.
    - */
    -goog.i18n.DateTimeSymbols_ps_AF = goog.i18n.DateTimeSymbols_ps;
    -
    -
    -/**
    - * Date/time formatting symbols for locale pt_AO.
    - */
    -goog.i18n.DateTimeSymbols_pt_AO = {
    -  ERAS: ['a.C.', 'd.C.'],
    -  ERANAMES: ['antes de Cristo', 'depois de Cristo'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janeiro', 'fevereiro', 'março', 'abril', 'maio', 'junho', 'julho',
    -    'agosto', 'setembro', 'outubro', 'novembro', 'dezembro'],
    -  STANDALONEMONTHS: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho',
    -    'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'],
    -  SHORTMONTHS: ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set',
    -    'out', 'nov', 'dez'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul',
    -    'Ago', 'Set', 'Out', 'Nov', 'Dez'],
    -  WEEKDAYS: ['domingo', 'segunda-feira', 'terça-feira', 'quarta-feira',
    -    'quinta-feira', 'sexta-feira', 'sábado'],
    -  STANDALONEWEEKDAYS: ['domingo', 'segunda-feira', 'terça-feira',
    -    'quarta-feira', 'quinta-feira', 'sexta-feira', 'sábado'],
    -  SHORTWEEKDAYS: ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'],
    -  STANDALONESHORTWEEKDAYS: ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'],
    -  NARROWWEEKDAYS: ['D', 'S', 'T', 'Q', 'Q', 'S', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'S', 'T', 'Q', 'Q', 'S', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1.º trimestre', '2.º trimestre', '3.º trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['da manhã', 'da tarde'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'dd/MM/y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'às\' {0}', '{1} \'às\' {0}', '{1}, {0}',
    -    '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale pt_CV.
    - */
    -goog.i18n.DateTimeSymbols_pt_CV = {
    -  ERAS: ['a.C.', 'd.C.'],
    -  ERANAMES: ['antes de Cristo', 'depois de Cristo'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janeiro', 'fevereiro', 'março', 'abril', 'maio', 'junho', 'julho',
    -    'agosto', 'setembro', 'outubro', 'novembro', 'dezembro'],
    -  STANDALONEMONTHS: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho',
    -    'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'],
    -  SHORTMONTHS: ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set',
    -    'out', 'nov', 'dez'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul',
    -    'Ago', 'Set', 'Out', 'Nov', 'Dez'],
    -  WEEKDAYS: ['domingo', 'segunda-feira', 'terça-feira', 'quarta-feira',
    -    'quinta-feira', 'sexta-feira', 'sábado'],
    -  STANDALONEWEEKDAYS: ['domingo', 'segunda-feira', 'terça-feira',
    -    'quarta-feira', 'quinta-feira', 'sexta-feira', 'sábado'],
    -  SHORTWEEKDAYS: ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'],
    -  STANDALONESHORTWEEKDAYS: ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'],
    -  NARROWWEEKDAYS: ['D', 'S', 'T', 'Q', 'Q', 'S', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'S', 'T', 'Q', 'Q', 'S', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1.º trimestre', '2.º trimestre', '3.º trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['da manhã', 'da tarde'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'dd/MM/y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'às\' {0}', '{1} \'às\' {0}', '{1}, {0}',
    -    '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale pt_GW.
    - */
    -goog.i18n.DateTimeSymbols_pt_GW = {
    -  ERAS: ['a.C.', 'd.C.'],
    -  ERANAMES: ['antes de Cristo', 'depois de Cristo'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janeiro', 'fevereiro', 'março', 'abril', 'maio', 'junho', 'julho',
    -    'agosto', 'setembro', 'outubro', 'novembro', 'dezembro'],
    -  STANDALONEMONTHS: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho',
    -    'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'],
    -  SHORTMONTHS: ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set',
    -    'out', 'nov', 'dez'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul',
    -    'Ago', 'Set', 'Out', 'Nov', 'Dez'],
    -  WEEKDAYS: ['domingo', 'segunda-feira', 'terça-feira', 'quarta-feira',
    -    'quinta-feira', 'sexta-feira', 'sábado'],
    -  STANDALONEWEEKDAYS: ['domingo', 'segunda-feira', 'terça-feira',
    -    'quarta-feira', 'quinta-feira', 'sexta-feira', 'sábado'],
    -  SHORTWEEKDAYS: ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'],
    -  STANDALONESHORTWEEKDAYS: ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'],
    -  NARROWWEEKDAYS: ['D', 'S', 'T', 'Q', 'Q', 'S', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'S', 'T', 'Q', 'Q', 'S', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1.º trimestre', '2.º trimestre', '3.º trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['da manhã', 'da tarde'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'dd/MM/y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'às\' {0}', '{1} \'às\' {0}', '{1}, {0}',
    -    '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale pt_MO.
    - */
    -goog.i18n.DateTimeSymbols_pt_MO = {
    -  ERAS: ['a.C.', 'd.C.'],
    -  ERANAMES: ['antes de Cristo', 'depois de Cristo'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janeiro', 'fevereiro', 'março', 'abril', 'maio', 'junho', 'julho',
    -    'agosto', 'setembro', 'outubro', 'novembro', 'dezembro'],
    -  STANDALONEMONTHS: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho',
    -    'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'],
    -  SHORTMONTHS: ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set',
    -    'out', 'nov', 'dez'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul',
    -    'Ago', 'Set', 'Out', 'Nov', 'Dez'],
    -  WEEKDAYS: ['domingo', 'segunda-feira', 'terça-feira', 'quarta-feira',
    -    'quinta-feira', 'sexta-feira', 'sábado'],
    -  STANDALONEWEEKDAYS: ['domingo', 'segunda-feira', 'terça-feira',
    -    'quarta-feira', 'quinta-feira', 'sexta-feira', 'sábado'],
    -  SHORTWEEKDAYS: ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'],
    -  STANDALONESHORTWEEKDAYS: ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'],
    -  NARROWWEEKDAYS: ['D', 'S', 'T', 'Q', 'Q', 'S', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'S', 'T', 'Q', 'Q', 'S', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1.º trimestre', '2.º trimestre', '3.º trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['da manhã', 'da tarde'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'dd/MM/y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'às\' {0}', '{1} \'às\' {0}', '{1}, {0}',
    -    '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale pt_MZ.
    - */
    -goog.i18n.DateTimeSymbols_pt_MZ = {
    -  ERAS: ['a.C.', 'd.C.'],
    -  ERANAMES: ['antes de Cristo', 'depois de Cristo'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janeiro', 'fevereiro', 'março', 'abril', 'maio', 'junho', 'julho',
    -    'agosto', 'setembro', 'outubro', 'novembro', 'dezembro'],
    -  STANDALONEMONTHS: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho',
    -    'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'],
    -  SHORTMONTHS: ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set',
    -    'out', 'nov', 'dez'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul',
    -    'Ago', 'Set', 'Out', 'Nov', 'Dez'],
    -  WEEKDAYS: ['domingo', 'segunda-feira', 'terça-feira', 'quarta-feira',
    -    'quinta-feira', 'sexta-feira', 'sábado'],
    -  STANDALONEWEEKDAYS: ['domingo', 'segunda-feira', 'terça-feira',
    -    'quarta-feira', 'quinta-feira', 'sexta-feira', 'sábado'],
    -  SHORTWEEKDAYS: ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'],
    -  STANDALONESHORTWEEKDAYS: ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'],
    -  NARROWWEEKDAYS: ['D', 'S', 'T', 'Q', 'Q', 'S', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'S', 'T', 'Q', 'Q', 'S', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1.º trimestre', '2.º trimestre', '3.º trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['da manhã', 'da tarde'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'dd/MM/y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'às\' {0}', '{1} \'às\' {0}', '{1}, {0}',
    -    '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale pt_ST.
    - */
    -goog.i18n.DateTimeSymbols_pt_ST = {
    -  ERAS: ['a.C.', 'd.C.'],
    -  ERANAMES: ['antes de Cristo', 'depois de Cristo'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janeiro', 'fevereiro', 'março', 'abril', 'maio', 'junho', 'julho',
    -    'agosto', 'setembro', 'outubro', 'novembro', 'dezembro'],
    -  STANDALONEMONTHS: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho',
    -    'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'],
    -  SHORTMONTHS: ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set',
    -    'out', 'nov', 'dez'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul',
    -    'Ago', 'Set', 'Out', 'Nov', 'Dez'],
    -  WEEKDAYS: ['domingo', 'segunda-feira', 'terça-feira', 'quarta-feira',
    -    'quinta-feira', 'sexta-feira', 'sábado'],
    -  STANDALONEWEEKDAYS: ['domingo', 'segunda-feira', 'terça-feira',
    -    'quarta-feira', 'quinta-feira', 'sexta-feira', 'sábado'],
    -  SHORTWEEKDAYS: ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'],
    -  STANDALONESHORTWEEKDAYS: ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'],
    -  NARROWWEEKDAYS: ['D', 'S', 'T', 'Q', 'Q', 'S', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'S', 'T', 'Q', 'Q', 'S', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1.º trimestre', '2.º trimestre', '3.º trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['da manhã', 'da tarde'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'dd/MM/y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'às\' {0}', '{1} \'às\' {0}', '{1}, {0}',
    -    '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale pt_TL.
    - */
    -goog.i18n.DateTimeSymbols_pt_TL = {
    -  ERAS: ['a.C.', 'd.C.'],
    -  ERANAMES: ['antes de Cristo', 'depois de Cristo'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['janeiro', 'fevereiro', 'março', 'abril', 'maio', 'junho', 'julho',
    -    'agosto', 'setembro', 'outubro', 'novembro', 'dezembro'],
    -  STANDALONEMONTHS: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho',
    -    'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'],
    -  SHORTMONTHS: ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set',
    -    'out', 'nov', 'dez'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul',
    -    'Ago', 'Set', 'Out', 'Nov', 'Dez'],
    -  WEEKDAYS: ['domingo', 'segunda-feira', 'terça-feira', 'quarta-feira',
    -    'quinta-feira', 'sexta-feira', 'sábado'],
    -  STANDALONEWEEKDAYS: ['domingo', 'segunda-feira', 'terça-feira',
    -    'quarta-feira', 'quinta-feira', 'sexta-feira', 'sábado'],
    -  SHORTWEEKDAYS: ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'],
    -  STANDALONESHORTWEEKDAYS: ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'],
    -  NARROWWEEKDAYS: ['D', 'S', 'T', 'Q', 'Q', 'S', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'S', 'T', 'Q', 'Q', 'S', 'S'],
    -  SHORTQUARTERS: ['T1', 'T2', 'T3', 'T4'],
    -  QUARTERS: ['1.º trimestre', '2.º trimestre', '3.º trimestre',
    -    '4.º trimestre'],
    -  AMPMS: ['da manhã', 'da tarde'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'dd/MM/y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'às\' {0}', '{1} \'às\' {0}', '{1}, {0}',
    -    '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale qu.
    - */
    -goog.i18n.DateTimeSymbols_qu = {
    -  ERAS: ['BCE', 'd.C.'],
    -  ERANAMES: ['BCE', 'd.C.'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['Qulla puquy', 'Hatun puquy', 'Pauqar waray', 'Ayriwa', 'Aymuray',
    -    'Inti raymi', 'Anta Sitwa', 'Qhapaq Sitwa', 'Uma raymi', 'Kantaray',
    -    'Ayamarqʼa', 'Kapaq Raymi'],
    -  STANDALONEMONTHS: ['Qulla puquy', 'Hatun puquy', 'Pauqar waray', 'Ayriwa',
    -    'Aymuray', 'Inti raymi', 'Anta Sitwa', 'Qhapaq Sitwa', 'Uma raymi',
    -    'Kantaray', 'Ayamarqʼa', 'Kapaq Raymi'],
    -  SHORTMONTHS: ['Qul', 'Hat', 'Pau', 'Ayr', 'Aym', 'Int', 'Ant', 'Qha', 'Uma',
    -    'Kan', 'Aya', 'Kap'],
    -  STANDALONESHORTMONTHS: ['Qul', 'Hat', 'Pau', 'Ayr', 'Aym', 'Int', 'Ant',
    -    'Qha', 'Uma', 'Kan', 'Aya', 'Kap'],
    -  WEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes',
    -    'Sábado'],
    -  STANDALONEWEEKDAYS: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
    -    'Viernes', 'Sábado'],
    -  SHORTWEEKDAYS: ['Dom', 'Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sab'],
    -  STANDALONESHORTWEEKDAYS: ['Dom', 'Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sab'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'X', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'X', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['a.m.', 'p.m.'],
    -  DATEFORMATS: ['EEEE, d MMMM, y', 'y MMMM d', 'y MMM d', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'hh:mm:ss a', 'hh:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale qu_BO.
    - */
    -goog.i18n.DateTimeSymbols_qu_BO = goog.i18n.DateTimeSymbols_qu;
    -
    -
    -/**
    - * Date/time formatting symbols for locale qu_EC.
    - */
    -goog.i18n.DateTimeSymbols_qu_EC = goog.i18n.DateTimeSymbols_qu;
    -
    -
    -/**
    - * Date/time formatting symbols for locale qu_PE.
    - */
    -goog.i18n.DateTimeSymbols_qu_PE = goog.i18n.DateTimeSymbols_qu;
    -
    -
    -/**
    - * Date/time formatting symbols for locale rm.
    - */
    -goog.i18n.DateTimeSymbols_rm = {
    -  ERAS: ['av. Cr.', 's. Cr.'],
    -  ERANAMES: ['avant Cristus', 'suenter Cristus'],
    -  NARROWMONTHS: ['S', 'F', 'M', 'A', 'M', 'Z', 'F', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['S', 'F', 'M', 'A', 'M', 'Z', 'F', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['schaner', 'favrer', 'mars', 'avrigl', 'matg', 'zercladur',
    -    'fanadur', 'avust', 'settember', 'october', 'november', 'december'],
    -  STANDALONEMONTHS: ['schaner', 'favrer', 'mars', 'avrigl', 'matg', 'zercladur',
    -    'fanadur', 'avust', 'settember', 'october', 'november', 'december'],
    -  SHORTMONTHS: ['schan.', 'favr.', 'mars', 'avr.', 'matg', 'zercl.', 'fan.',
    -    'avust', 'sett.', 'oct.', 'nov.', 'dec.'],
    -  STANDALONESHORTMONTHS: ['schan.', 'favr.', 'mars', 'avr.', 'matg', 'zercl.',
    -    'fan.', 'avust', 'sett.', 'oct.', 'nov.', 'dec.'],
    -  WEEKDAYS: ['dumengia', 'glindesdi', 'mardi', 'mesemna', 'gievgia', 'venderdi',
    -    'sonda'],
    -  STANDALONEWEEKDAYS: ['dumengia', 'glindesdi', 'mardi', 'mesemna', 'gievgia',
    -    'venderdi', 'sonda'],
    -  SHORTWEEKDAYS: ['du', 'gli', 'ma', 'me', 'gie', 've', 'so'],
    -  STANDALONESHORTWEEKDAYS: ['du', 'gli', 'ma', 'me', 'gie', 've', 'so'],
    -  NARROWWEEKDAYS: ['D', 'G', 'M', 'M', 'G', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'G', 'M', 'M', 'G', 'V', 'S'],
    -  SHORTQUARTERS: ['1. quartal', '2. quartal', '3. quartal', '4. quartal'],
    -  QUARTERS: ['1. quartal', '2. quartal', '3. quartal', '4. quartal'],
    -  AMPMS: ['am', 'sm'],
    -  DATEFORMATS: ['EEEE, \'ils\' d \'da\' MMMM y', 'd \'da\' MMMM y', 'dd-MM-y',
    -    'dd-MM-yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale rm_CH.
    - */
    -goog.i18n.DateTimeSymbols_rm_CH = goog.i18n.DateTimeSymbols_rm;
    -
    -
    -/**
    - * Date/time formatting symbols for locale rn.
    - */
    -goog.i18n.DateTimeSymbols_rn = {
    -  ERAS: ['Mb.Y.', 'Ny.Y'],
    -  ERANAMES: ['Mbere ya Yezu', 'Nyuma ya Yezu'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['Nzero', 'Ruhuhuma', 'Ntwarante', 'Ndamukiza', 'Rusama', 'Ruheshi',
    -    'Mukakaro', 'Nyandagaro', 'Nyakanga', 'Gitugutu', 'Munyonyo', 'Kigarama'],
    -  STANDALONEMONTHS: ['Nzero', 'Ruhuhuma', 'Ntwarante', 'Ndamukiza', 'Rusama',
    -    'Ruheshi', 'Mukakaro', 'Nyandagaro', 'Nyakanga', 'Gitugutu', 'Munyonyo',
    -    'Kigarama'],
    -  SHORTMONTHS: ['Mut.', 'Gas.', 'Wer.', 'Mat.', 'Gic.', 'Kam.', 'Nya.', 'Kan.',
    -    'Nze.', 'Ukw.', 'Ugu.', 'Uku.'],
    -  STANDALONESHORTMONTHS: ['Mut.', 'Gas.', 'Wer.', 'Mat.', 'Gic.', 'Kam.',
    -    'Nya.', 'Kan.', 'Nze.', 'Ukw.', 'Ugu.', 'Uku.'],
    -  WEEKDAYS: ['Ku w’indwi', 'Ku wa mbere', 'Ku wa kabiri', 'Ku wa gatatu',
    -    'Ku wa kane', 'Ku wa gatanu', 'Ku wa gatandatu'],
    -  STANDALONEWEEKDAYS: ['Ku w’indwi', 'Ku wa mbere', 'Ku wa kabiri',
    -    'Ku wa gatatu', 'Ku wa kane', 'Ku wa gatanu', 'Ku wa gatandatu'],
    -  SHORTWEEKDAYS: ['cu.', 'mbe.', 'kab.', 'gtu.', 'kan.', 'gnu.', 'gnd.'],
    -  STANDALONESHORTWEEKDAYS: ['cu.', 'mbe.', 'kab.', 'gtu.', 'kan.', 'gnu.',
    -    'gnd.'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['I1', 'I2', 'I3', 'I4'],
    -  QUARTERS: ['Igice ca mbere c’umwaka', 'Igice ca kabiri c’umwaka',
    -    'Igice ca gatatu c’umwaka', 'Igice ca kane c’umwaka'],
    -  AMPMS: ['Z.MU.', 'Z.MW.'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale rn_BI.
    - */
    -goog.i18n.DateTimeSymbols_rn_BI = goog.i18n.DateTimeSymbols_rn;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ro_MD.
    - */
    -goog.i18n.DateTimeSymbols_ro_MD = {
    -  ERAS: ['î.Hr.', 'd.Hr.'],
    -  ERANAMES: ['înainte de Hristos', 'după Hristos'],
    -  NARROWMONTHS: ['I', 'F', 'M', 'A', 'M', 'I', 'I', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['I', 'F', 'M', 'A', 'M', 'I', 'I', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['ianuarie', 'februarie', 'martie', 'aprilie', 'mai', 'iunie',
    -    'iulie', 'august', 'septembrie', 'octombrie', 'noiembrie', 'decembrie'],
    -  STANDALONEMONTHS: ['Ianuarie', 'Februarie', 'Martie', 'Aprilie', 'Mai',
    -    'Iunie', 'Iulie', 'August', 'Septembrie', 'Octombrie', 'Noiembrie',
    -    'Decembrie'],
    -  SHORTMONTHS: ['ian.', 'feb.', 'mar.', 'apr.', 'mai', 'iun.', 'iul.', 'aug.',
    -    'sept.', 'oct.', 'nov.', 'dec.'],
    -  STANDALONESHORTMONTHS: ['ian.', 'feb.', 'mar.', 'apr.', 'mai', 'iun.', 'iul.',
    -    'aug.', 'sept.', 'oct.', 'nov.', 'dec.'],
    -  WEEKDAYS: ['duminică', 'luni', 'marți', 'miercuri', 'joi', 'vineri',
    -    'sâmbătă'],
    -  STANDALONEWEEKDAYS: ['Duminică', 'Luni', 'Marți', 'Miercuri', 'Joi',
    -    'Vineri', 'Sâmbătă'],
    -  SHORTWEEKDAYS: ['Dum', 'Lun', 'Mar', 'Mie', 'Joi', 'Vin', 'Sâm'],
    -  STANDALONESHORTWEEKDAYS: ['Dum', 'Lun', 'Mar', 'Mie', 'Joi', 'Vin', 'Sâm'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['trim. I', 'trim. II', 'trim. III', 'trim. IV'],
    -  QUARTERS: ['trimestrul I', 'trimestrul al II-lea', 'trimestrul al III-lea',
    -    'trimestrul al IV-lea'],
    -  AMPMS: ['a.m.', 'p.m.'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd.MM.y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ro_RO.
    - */
    -goog.i18n.DateTimeSymbols_ro_RO = {
    -  ERAS: ['î.Hr.', 'd.Hr.'],
    -  ERANAMES: ['înainte de Hristos', 'după Hristos'],
    -  NARROWMONTHS: ['I', 'F', 'M', 'A', 'M', 'I', 'I', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['I', 'F', 'M', 'A', 'M', 'I', 'I', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['ianuarie', 'februarie', 'martie', 'aprilie', 'mai', 'iunie',
    -    'iulie', 'august', 'septembrie', 'octombrie', 'noiembrie', 'decembrie'],
    -  STANDALONEMONTHS: ['Ianuarie', 'Februarie', 'Martie', 'Aprilie', 'Mai',
    -    'Iunie', 'Iulie', 'August', 'Septembrie', 'Octombrie', 'Noiembrie',
    -    'Decembrie'],
    -  SHORTMONTHS: ['ian.', 'feb.', 'mar.', 'apr.', 'mai', 'iun.', 'iul.', 'aug.',
    -    'sept.', 'oct.', 'nov.', 'dec.'],
    -  STANDALONESHORTMONTHS: ['ian.', 'feb.', 'mar.', 'apr.', 'mai', 'iun.', 'iul.',
    -    'aug.', 'sept.', 'oct.', 'nov.', 'dec.'],
    -  WEEKDAYS: ['duminică', 'luni', 'marți', 'miercuri', 'joi', 'vineri',
    -    'sâmbătă'],
    -  STANDALONEWEEKDAYS: ['Duminică', 'Luni', 'Marți', 'Miercuri', 'Joi',
    -    'Vineri', 'Sâmbătă'],
    -  SHORTWEEKDAYS: ['Dum', 'Lun', 'Mar', 'Mie', 'Joi', 'Vin', 'Sâm'],
    -  STANDALONESHORTWEEKDAYS: ['Dum', 'Lun', 'Mar', 'Mie', 'Joi', 'Vin', 'Sâm'],
    -  NARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],
    -  SHORTQUARTERS: ['trim. I', 'trim. II', 'trim. III', 'trim. IV'],
    -  QUARTERS: ['trimestrul I', 'trimestrul al II-lea', 'trimestrul al III-lea',
    -    'trimestrul al IV-lea'],
    -  AMPMS: ['a.m.', 'p.m.'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd.MM.y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale rof.
    - */
    -goog.i18n.DateTimeSymbols_rof = {
    -  ERAS: ['KM', 'BM'],
    -  ERANAMES: ['Kabla ya Mayesu', 'Baada ya Mayesu'],
    -  NARROWMONTHS: ['K', 'K', 'K', 'K', 'T', 'S', 'S', 'N', 'T', 'I', 'I', 'I'],
    -  STANDALONENARROWMONTHS: ['K', 'K', 'K', 'K', 'T', 'S', 'S', 'N', 'T', 'I',
    -    'I', 'I'],
    -  MONTHS: ['Mweri wa kwanza', 'Mweri wa kaili', 'Mweri wa katatu',
    -    'Mweri wa kaana', 'Mweri wa tanu', 'Mweri wa sita', 'Mweri wa saba',
    -    'Mweri wa nane', 'Mweri wa tisa', 'Mweri wa ikumi',
    -    'Mweri wa ikumi na moja', 'Mweri wa ikumi na mbili'],
    -  STANDALONEMONTHS: ['Mweri wa kwanza', 'Mweri wa kaili', 'Mweri wa katatu',
    -    'Mweri wa kaana', 'Mweri wa tanu', 'Mweri wa sita', 'Mweri wa saba',
    -    'Mweri wa nane', 'Mweri wa tisa', 'Mweri wa ikumi',
    -    'Mweri wa ikumi na moja', 'Mweri wa ikumi na mbili'],
    -  SHORTMONTHS: ['M1', 'M2', 'M3', 'M4', 'M5', 'M6', 'M7', 'M8', 'M9', 'M10',
    -    'M11', 'M12'],
    -  STANDALONESHORTMONTHS: ['M1', 'M2', 'M3', 'M4', 'M5', 'M6', 'M7', 'M8', 'M9',
    -    'M10', 'M11', 'M12'],
    -  WEEKDAYS: ['Ijumapili', 'Ijumatatu', 'Ijumanne', 'Ijumatano', 'Alhamisi',
    -    'Ijumaa', 'Ijumamosi'],
    -  STANDALONEWEEKDAYS: ['Ijumapili', 'Ijumatatu', 'Ijumanne', 'Ijumatano',
    -    'Alhamisi', 'Ijumaa', 'Ijumamosi'],
    -  SHORTWEEKDAYS: ['Ijp', 'Ijt', 'Ijn', 'Ijtn', 'Alh', 'Iju', 'Ijm'],
    -  STANDALONESHORTWEEKDAYS: ['Ijp', 'Ijt', 'Ijn', 'Ijtn', 'Alh', 'Iju', 'Ijm'],
    -  NARROWWEEKDAYS: ['2', '3', '4', '5', '6', '7', '1'],
    -  STANDALONENARROWWEEKDAYS: ['2', '3', '4', '5', '6', '7', '1'],
    -  SHORTQUARTERS: ['R1', 'R2', 'R3', 'R4'],
    -  QUARTERS: ['Robo ya kwanza', 'Robo ya kaili', 'Robo ya katatu',
    -    'Robo ya kaana'],
    -  AMPMS: ['kang’ama', 'kingoto'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale rof_TZ.
    - */
    -goog.i18n.DateTimeSymbols_rof_TZ = goog.i18n.DateTimeSymbols_rof;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ru_BY.
    - */
    -goog.i18n.DateTimeSymbols_ru_BY = {
    -  ERAS: ['до н. э.', 'н. э.'],
    -  ERANAMES: ['до н. э.', 'н. э.'],
    -  NARROWMONTHS: ['Я', 'Ф', 'М', 'А', 'М', 'И', 'И', 'А', 'С', 'О',
    -    'Н', 'Д'],
    -  STANDALONENARROWMONTHS: ['Я', 'Ф', 'М', 'А', 'М', 'И', 'И', 'А', 'С',
    -    'О', 'Н', 'Д'],
    -  MONTHS: ['января', 'февраля', 'марта', 'апреля',
    -    'мая', 'июня', 'июля', 'августа', 'сентября',
    -    'октября', 'ноября', 'декабря'],
    -  STANDALONEMONTHS: ['январь', 'февраль', 'март',
    -    'апрель', 'май', 'июнь', 'июль', 'август',
    -    'сентябрь', 'октябрь', 'ноябрь', 'декабрь'],
    -  SHORTMONTHS: ['янв.', 'февр.', 'марта', 'апр.', 'мая',
    -    'июня', 'июля', 'авг.', 'сент.', 'окт.', 'нояб.',
    -    'дек.'],
    -  STANDALONESHORTMONTHS: ['янв.', 'февр.', 'март', 'апр.',
    -    'май', 'июнь', 'июль', 'авг.', 'сент.', 'окт.',
    -    'нояб.', 'дек.'],
    -  WEEKDAYS: ['воскресенье', 'понедельник',
    -    'вторник', 'среда', 'четверг', 'пятница',
    -    'суббота'],
    -  STANDALONEWEEKDAYS: ['Воскресенье', 'Понедельник',
    -    'Вторник', 'Среда', 'Четверг', 'Пятница',
    -    'Суббота'],
    -  SHORTWEEKDAYS: ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],
    -  STANDALONESHORTWEEKDAYS: ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт',
    -    'Сб'],
    -  NARROWWEEKDAYS: ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],
    -  STANDALONENARROWWEEKDAYS: ['В', 'П', 'В', 'С', 'Ч', 'П', 'С'],
    -  SHORTQUARTERS: ['1-й кв.', '2-й кв.', '3-й кв.', '4-й кв.'],
    -  QUARTERS: ['1-й квартал', '2-й квартал',
    -    '3-й квартал', '4-й квартал'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM y \'г\'.', 'd MMMM y \'г\'.', 'd MMM y \'г\'.',
    -    'dd.MM.yy'],
    -  TIMEFORMATS: ['H:mm:ss zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ru_KG.
    - */
    -goog.i18n.DateTimeSymbols_ru_KG = {
    -  ERAS: ['до н. э.', 'н. э.'],
    -  ERANAMES: ['до н. э.', 'н. э.'],
    -  NARROWMONTHS: ['Я', 'Ф', 'М', 'А', 'М', 'И', 'И', 'А', 'С', 'О',
    -    'Н', 'Д'],
    -  STANDALONENARROWMONTHS: ['Я', 'Ф', 'М', 'А', 'М', 'И', 'И', 'А', 'С',
    -    'О', 'Н', 'Д'],
    -  MONTHS: ['января', 'февраля', 'марта', 'апреля',
    -    'мая', 'июня', 'июля', 'августа', 'сентября',
    -    'октября', 'ноября', 'декабря'],
    -  STANDALONEMONTHS: ['январь', 'февраль', 'март',
    -    'апрель', 'май', 'июнь', 'июль', 'август',
    -    'сентябрь', 'октябрь', 'ноябрь', 'декабрь'],
    -  SHORTMONTHS: ['янв.', 'февр.', 'марта', 'апр.', 'мая',
    -    'июня', 'июля', 'авг.', 'сент.', 'окт.', 'нояб.',
    -    'дек.'],
    -  STANDALONESHORTMONTHS: ['янв.', 'февр.', 'март', 'апр.',
    -    'май', 'июнь', 'июль', 'авг.', 'сент.', 'окт.',
    -    'нояб.', 'дек.'],
    -  WEEKDAYS: ['воскресенье', 'понедельник',
    -    'вторник', 'среда', 'четверг', 'пятница',
    -    'суббота'],
    -  STANDALONEWEEKDAYS: ['Воскресенье', 'Понедельник',
    -    'Вторник', 'Среда', 'Четверг', 'Пятница',
    -    'Суббота'],
    -  SHORTWEEKDAYS: ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],
    -  STANDALONESHORTWEEKDAYS: ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт',
    -    'Сб'],
    -  NARROWWEEKDAYS: ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],
    -  STANDALONENARROWWEEKDAYS: ['В', 'П', 'В', 'С', 'Ч', 'П', 'С'],
    -  SHORTQUARTERS: ['1-й кв.', '2-й кв.', '3-й кв.', '4-й кв.'],
    -  QUARTERS: ['1-й квартал', '2-й квартал',
    -    '3-й квартал', '4-й квартал'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM y \'г\'.', 'd MMMM y \'г\'.', 'd MMM y \'г\'.',
    -    'dd.MM.yy'],
    -  TIMEFORMATS: ['H:mm:ss zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ru_KZ.
    - */
    -goog.i18n.DateTimeSymbols_ru_KZ = {
    -  ERAS: ['до н. э.', 'н. э.'],
    -  ERANAMES: ['до н. э.', 'н. э.'],
    -  NARROWMONTHS: ['Я', 'Ф', 'М', 'А', 'М', 'И', 'И', 'А', 'С', 'О',
    -    'Н', 'Д'],
    -  STANDALONENARROWMONTHS: ['Я', 'Ф', 'М', 'А', 'М', 'И', 'И', 'А', 'С',
    -    'О', 'Н', 'Д'],
    -  MONTHS: ['января', 'февраля', 'марта', 'апреля',
    -    'мая', 'июня', 'июля', 'августа', 'сентября',
    -    'октября', 'ноября', 'декабря'],
    -  STANDALONEMONTHS: ['январь', 'февраль', 'март',
    -    'апрель', 'май', 'июнь', 'июль', 'август',
    -    'сентябрь', 'октябрь', 'ноябрь', 'декабрь'],
    -  SHORTMONTHS: ['янв.', 'февр.', 'марта', 'апр.', 'мая',
    -    'июня', 'июля', 'авг.', 'сент.', 'окт.', 'нояб.',
    -    'дек.'],
    -  STANDALONESHORTMONTHS: ['янв.', 'февр.', 'март', 'апр.',
    -    'май', 'июнь', 'июль', 'авг.', 'сент.', 'окт.',
    -    'нояб.', 'дек.'],
    -  WEEKDAYS: ['воскресенье', 'понедельник',
    -    'вторник', 'среда', 'четверг', 'пятница',
    -    'суббота'],
    -  STANDALONEWEEKDAYS: ['Воскресенье', 'Понедельник',
    -    'Вторник', 'Среда', 'Четверг', 'Пятница',
    -    'Суббота'],
    -  SHORTWEEKDAYS: ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],
    -  STANDALONESHORTWEEKDAYS: ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт',
    -    'Сб'],
    -  NARROWWEEKDAYS: ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],
    -  STANDALONENARROWWEEKDAYS: ['В', 'П', 'В', 'С', 'Ч', 'П', 'С'],
    -  SHORTQUARTERS: ['1-й кв.', '2-й кв.', '3-й кв.', '4-й кв.'],
    -  QUARTERS: ['1-й квартал', '2-й квартал',
    -    '3-й квартал', '4-й квартал'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM y \'г\'.', 'd MMMM y \'г\'.', 'd MMM y \'г\'.',
    -    'dd.MM.yy'],
    -  TIMEFORMATS: ['H:mm:ss zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ru_MD.
    - */
    -goog.i18n.DateTimeSymbols_ru_MD = {
    -  ERAS: ['до н. э.', 'н. э.'],
    -  ERANAMES: ['до н. э.', 'н. э.'],
    -  NARROWMONTHS: ['Я', 'Ф', 'М', 'А', 'М', 'И', 'И', 'А', 'С', 'О',
    -    'Н', 'Д'],
    -  STANDALONENARROWMONTHS: ['Я', 'Ф', 'М', 'А', 'М', 'И', 'И', 'А', 'С',
    -    'О', 'Н', 'Д'],
    -  MONTHS: ['января', 'февраля', 'марта', 'апреля',
    -    'мая', 'июня', 'июля', 'августа', 'сентября',
    -    'октября', 'ноября', 'декабря'],
    -  STANDALONEMONTHS: ['январь', 'февраль', 'март',
    -    'апрель', 'май', 'июнь', 'июль', 'август',
    -    'сентябрь', 'октябрь', 'ноябрь', 'декабрь'],
    -  SHORTMONTHS: ['янв.', 'февр.', 'марта', 'апр.', 'мая',
    -    'июня', 'июля', 'авг.', 'сент.', 'окт.', 'нояб.',
    -    'дек.'],
    -  STANDALONESHORTMONTHS: ['янв.', 'февр.', 'март', 'апр.',
    -    'май', 'июнь', 'июль', 'авг.', 'сент.', 'окт.',
    -    'нояб.', 'дек.'],
    -  WEEKDAYS: ['воскресенье', 'понедельник',
    -    'вторник', 'среда', 'четверг', 'пятница',
    -    'суббота'],
    -  STANDALONEWEEKDAYS: ['Воскресенье', 'Понедельник',
    -    'Вторник', 'Среда', 'Четверг', 'Пятница',
    -    'Суббота'],
    -  SHORTWEEKDAYS: ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],
    -  STANDALONESHORTWEEKDAYS: ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт',
    -    'Сб'],
    -  NARROWWEEKDAYS: ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],
    -  STANDALONENARROWWEEKDAYS: ['В', 'П', 'В', 'С', 'Ч', 'П', 'С'],
    -  SHORTQUARTERS: ['1-й кв.', '2-й кв.', '3-й кв.', '4-й кв.'],
    -  QUARTERS: ['1-й квартал', '2-й квартал',
    -    '3-й квартал', '4-й квартал'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM y \'г\'.', 'd MMMM y \'г\'.', 'd MMM y \'г\'.',
    -    'dd.MM.yy'],
    -  TIMEFORMATS: ['H:mm:ss zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ru_RU.
    - */
    -goog.i18n.DateTimeSymbols_ru_RU = {
    -  ERAS: ['до н. э.', 'н. э.'],
    -  ERANAMES: ['до н. э.', 'н. э.'],
    -  NARROWMONTHS: ['Я', 'Ф', 'М', 'А', 'М', 'И', 'И', 'А', 'С', 'О',
    -    'Н', 'Д'],
    -  STANDALONENARROWMONTHS: ['Я', 'Ф', 'М', 'А', 'М', 'И', 'И', 'А', 'С',
    -    'О', 'Н', 'Д'],
    -  MONTHS: ['января', 'февраля', 'марта', 'апреля',
    -    'мая', 'июня', 'июля', 'августа', 'сентября',
    -    'октября', 'ноября', 'декабря'],
    -  STANDALONEMONTHS: ['январь', 'февраль', 'март',
    -    'апрель', 'май', 'июнь', 'июль', 'август',
    -    'сентябрь', 'октябрь', 'ноябрь', 'декабрь'],
    -  SHORTMONTHS: ['янв.', 'февр.', 'марта', 'апр.', 'мая',
    -    'июня', 'июля', 'авг.', 'сент.', 'окт.', 'нояб.',
    -    'дек.'],
    -  STANDALONESHORTMONTHS: ['янв.', 'февр.', 'март', 'апр.',
    -    'май', 'июнь', 'июль', 'авг.', 'сент.', 'окт.',
    -    'нояб.', 'дек.'],
    -  WEEKDAYS: ['воскресенье', 'понедельник',
    -    'вторник', 'среда', 'четверг', 'пятница',
    -    'суббота'],
    -  STANDALONEWEEKDAYS: ['Воскресенье', 'Понедельник',
    -    'Вторник', 'Среда', 'Четверг', 'Пятница',
    -    'Суббота'],
    -  SHORTWEEKDAYS: ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],
    -  STANDALONESHORTWEEKDAYS: ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт',
    -    'Сб'],
    -  NARROWWEEKDAYS: ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],
    -  STANDALONENARROWWEEKDAYS: ['В', 'П', 'В', 'С', 'Ч', 'П', 'С'],
    -  SHORTQUARTERS: ['1-й кв.', '2-й кв.', '3-й кв.', '4-й кв.'],
    -  QUARTERS: ['1-й квартал', '2-й квартал',
    -    '3-й квартал', '4-й квартал'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM y \'г\'.', 'd MMMM y \'г\'.', 'd MMM y \'г\'.',
    -    'dd.MM.yy'],
    -  TIMEFORMATS: ['H:mm:ss zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ru_UA.
    - */
    -goog.i18n.DateTimeSymbols_ru_UA = {
    -  ERAS: ['до н. э.', 'н. э.'],
    -  ERANAMES: ['до н. э.', 'н. э.'],
    -  NARROWMONTHS: ['Я', 'Ф', 'М', 'А', 'М', 'И', 'И', 'А', 'С', 'О',
    -    'Н', 'Д'],
    -  STANDALONENARROWMONTHS: ['Я', 'Ф', 'М', 'А', 'М', 'И', 'И', 'А', 'С',
    -    'О', 'Н', 'Д'],
    -  MONTHS: ['января', 'февраля', 'марта', 'апреля',
    -    'мая', 'июня', 'июля', 'августа', 'сентября',
    -    'октября', 'ноября', 'декабря'],
    -  STANDALONEMONTHS: ['январь', 'февраль', 'март',
    -    'апрель', 'май', 'июнь', 'июль', 'август',
    -    'сентябрь', 'октябрь', 'ноябрь', 'декабрь'],
    -  SHORTMONTHS: ['янв.', 'февр.', 'марта', 'апр.', 'мая',
    -    'июня', 'июля', 'авг.', 'сент.', 'окт.', 'нояб.',
    -    'дек.'],
    -  STANDALONESHORTMONTHS: ['янв.', 'февр.', 'март', 'апр.',
    -    'май', 'июнь', 'июль', 'авг.', 'сент.', 'окт.',
    -    'нояб.', 'дек.'],
    -  WEEKDAYS: ['воскресенье', 'понедельник',
    -    'вторник', 'среда', 'четверг', 'пятница',
    -    'суббота'],
    -  STANDALONEWEEKDAYS: ['Воскресенье', 'Понедельник',
    -    'Вторник', 'Среда', 'Четверг', 'Пятница',
    -    'Суббота'],
    -  SHORTWEEKDAYS: ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],
    -  STANDALONESHORTWEEKDAYS: ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт',
    -    'Сб'],
    -  NARROWWEEKDAYS: ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],
    -  STANDALONENARROWWEEKDAYS: ['В', 'П', 'В', 'С', 'Ч', 'П', 'С'],
    -  SHORTQUARTERS: ['1-й кв.', '2-й кв.', '3-й кв.', '4-й кв.'],
    -  QUARTERS: ['1-й квартал', '2-й квартал',
    -    '3-й квартал', '4-й квартал'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM y \'г\'.', 'd MMMM y', 'd MMM y', 'dd.MM.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale rw.
    - */
    -goog.i18n.DateTimeSymbols_rw = {
    -  ERAS: ['BCE', 'CE'],
    -  ERANAMES: ['BCE', 'CE'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['Mutarama', 'Gashyantare', 'Werurwe', 'Mata', 'Gicuransi', 'Kamena',
    -    'Nyakanga', 'Kanama', 'Nzeli', 'Ukwakira', 'Ugushyingo', 'Ukuboza'],
    -  STANDALONEMONTHS: ['Mutarama', 'Gashyantare', 'Werurwe', 'Mata', 'Gicuransi',
    -    'Kamena', 'Nyakanga', 'Kanama', 'Nzeli', 'Ukwakira', 'Ugushyingo',
    -    'Ukuboza'],
    -  SHORTMONTHS: ['mut.', 'gas.', 'wer.', 'mat.', 'gic.', 'kam.', 'nya.', 'kan.',
    -    'nze.', 'ukw.', 'ugu.', 'uku.'],
    -  STANDALONESHORTMONTHS: ['mut.', 'gas.', 'wer.', 'mat.', 'gic.', 'kam.',
    -    'nya.', 'kan.', 'nze.', 'ukw.', 'ugu.', 'uku.'],
    -  WEEKDAYS: ['Ku cyumweru', 'Kuwa mbere', 'Kuwa kabiri', 'Kuwa gatatu',
    -    'Kuwa kane', 'Kuwa gatanu', 'Kuwa gatandatu'],
    -  STANDALONEWEEKDAYS: ['Ku cyumweru', 'Kuwa mbere', 'Kuwa kabiri',
    -    'Kuwa gatatu', 'Kuwa kane', 'Kuwa gatanu', 'Kuwa gatandatu'],
    -  SHORTWEEKDAYS: ['cyu.', 'mbe.', 'kab.', 'gtu.', 'kan.', 'gnu.', 'gnd.'],
    -  STANDALONESHORTWEEKDAYS: ['cyu.', 'mbe.', 'kab.', 'gtu.', 'kan.', 'gnu.',
    -    'gnd.'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['I1', 'I2', 'I3', 'I4'],
    -  QUARTERS: ['igihembwe cya mbere', 'igihembwe cya kabiri',
    -    'igihembwe cya gatatu', 'igihembwe cya kane'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, y MMMM dd', 'y MMMM d', 'y MMM d', 'yy/MM/dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale rw_RW.
    - */
    -goog.i18n.DateTimeSymbols_rw_RW = goog.i18n.DateTimeSymbols_rw;
    -
    -
    -/**
    - * Date/time formatting symbols for locale rwk.
    - */
    -goog.i18n.DateTimeSymbols_rwk = {
    -  ERAS: ['KK', 'BK'],
    -  ERANAMES: ['Kabla ya Kristu', 'Baada ya Kristu'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januari', 'Februari', 'Machi', 'Aprilyi', 'Mei', 'Junyi', 'Julyai',
    -    'Agusti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    -  STANDALONEMONTHS: ['Januari', 'Februari', 'Machi', 'Aprilyi', 'Mei', 'Junyi',
    -    'Julyai', 'Agusti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep',
    -    'Okt', 'Nov', 'Des'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul',
    -    'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
    -  WEEKDAYS: ['Jumapilyi', 'Jumatatuu', 'Jumanne', 'Jumatanu', 'Alhamisi',
    -    'Ijumaa', 'Jumamosi'],
    -  STANDALONEWEEKDAYS: ['Jumapilyi', 'Jumatatuu', 'Jumanne', 'Jumatanu',
    -    'Alhamisi', 'Ijumaa', 'Jumamosi'],
    -  SHORTWEEKDAYS: ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
    -  STANDALONESHORTWEEKDAYS: ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
    -  NARROWWEEKDAYS: ['J', 'J', 'J', 'J', 'A', 'I', 'J'],
    -  STANDALONENARROWWEEKDAYS: ['J', 'J', 'J', 'J', 'A', 'I', 'J'],
    -  SHORTQUARTERS: ['R1', 'R2', 'R3', 'R4'],
    -  QUARTERS: ['Robo 1', 'Robo 2', 'Robo 3', 'Robo 4'],
    -  AMPMS: ['utuko', 'kyiukonyi'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale rwk_TZ.
    - */
    -goog.i18n.DateTimeSymbols_rwk_TZ = goog.i18n.DateTimeSymbols_rwk;
    -
    -
    -/**
    - * Date/time formatting symbols for locale sah.
    - */
    -goog.i18n.DateTimeSymbols_sah = {
    -  ERAS: ['б. э. и.', 'б. э'],
    -  ERANAMES: ['б. э. и.', 'б. э'],
    -  NARROWMONTHS: ['Т', 'О', 'К', 'М', 'Ы', 'Б', 'О', 'А', 'Б', 'А',
    -    'С', 'А'],
    -  STANDALONENARROWMONTHS: ['Т', 'О', 'К', 'М', 'Ы', 'Б', 'О', 'А', 'Б',
    -    'А', 'С', 'А'],
    -  MONTHS: ['Тохсунньу', 'Олунньу', 'Кулун тутар',
    -    'Муус устар', 'Ыам ыйын', 'Бэс ыйын',
    -    'От ыйын', 'Атырдьых ыйын', 'Балаҕан ыйын',
    -    'Алтынньы', 'Сэтинньи', 'Ахсынньы'],
    -  STANDALONEMONTHS: ['Тохсунньу', 'Олунньу',
    -    'Кулун тутар', 'Муус устар', 'Ыам ыйын',
    -    'Бэс ыйын', 'От ыйын', 'Атырдьых ыйын',
    -    'Балаҕан ыйын', 'Алтынньы', 'Сэтинньи',
    -    'Ахсынньы'],
    -  SHORTMONTHS: ['Тохс', 'Олун', 'Клн_ттр', 'Мус_уст',
    -    'Ыам_йн', 'Бэс_йн', 'От_йн', 'Атрдь_йн',
    -    'Блҕн_йн', 'Алт', 'Сэт', 'Ахс'],
    -  STANDALONESHORTMONTHS: ['Тохс', 'Олун', 'Клн_ттр',
    -    'Мус_уст', 'Ыам_йн', 'Бэс_йн', 'От_йн',
    -    'Атрдь_йн', 'Блҕн_йн', 'Алт', 'Сэт', 'Ахс'],
    -  WEEKDAYS: ['Баскыһыанньа', 'Бэнидиэлинньик',
    -    'Оптуорунньук', 'Сэрэдэ', 'Чэппиэр',
    -    'Бээтиҥсэ', 'Субуота'],
    -  STANDALONEWEEKDAYS: ['Баскыһыанньа',
    -    'Бэнидиэлинньик', 'Оптуорунньук', 'Сэрэдэ',
    -    'Чэппиэр', 'Бээтиҥсэ', 'Субуота'],
    -  SHORTWEEKDAYS: ['Бс', 'Бн', 'Оп', 'Сэ', 'Чп', 'Бэ', 'Сб'],
    -  STANDALONESHORTWEEKDAYS: ['Бс', 'Бн', 'Оп', 'Сэ', 'Чп', 'Бэ',
    -    'Сб'],
    -  NARROWWEEKDAYS: ['Б', 'Б', 'О', 'С', 'Ч', 'Б', 'С'],
    -  STANDALONENARROWWEEKDAYS: ['Б', 'Б', 'О', 'С', 'Ч', 'Б', 'С'],
    -  SHORTQUARTERS: ['1-кы кб', '2-с кб', '3-с кб', '4-с кб'],
    -  QUARTERS: ['1-кы кыбаартал', '2-с кыбаартал',
    -    '3-с кыбаартал', '4-с кыбаартал'],
    -  AMPMS: ['ЭИ', 'ЭК'],
    -  DATEFORMATS: ['y \'сыл\' MMMM d \'күнэ\', EEEE', 'y, MMMM d',
    -    'y, MMM d', 'yy/M/d'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale sah_RU.
    - */
    -goog.i18n.DateTimeSymbols_sah_RU = goog.i18n.DateTimeSymbols_sah;
    -
    -
    -/**
    - * Date/time formatting symbols for locale saq.
    - */
    -goog.i18n.DateTimeSymbols_saq = {
    -  ERAS: ['KK', 'BK'],
    -  ERANAMES: ['Kabla ya Christo', 'Baada ya Christo'],
    -  NARROWMONTHS: ['O', 'W', 'O', 'O', 'I', 'I', 'S', 'I', 'S', 'T', 'T', 'T'],
    -  STANDALONENARROWMONTHS: ['O', 'W', 'O', 'O', 'I', 'I', 'S', 'I', 'S', 'T',
    -    'T', 'T'],
    -  MONTHS: ['Lapa le obo', 'Lapa le waare', 'Lapa le okuni', 'Lapa le ong’wan',
    -    'Lapa le imet', 'Lapa le ile', 'Lapa le sapa', 'Lapa le isiet',
    -    'Lapa le saal', 'Lapa le tomon', 'Lapa le tomon obo',
    -    'Lapa le tomon waare'],
    -  STANDALONEMONTHS: ['Lapa le obo', 'Lapa le waare', 'Lapa le okuni',
    -    'Lapa le ong’wan', 'Lapa le imet', 'Lapa le ile', 'Lapa le sapa',
    -    'Lapa le isiet', 'Lapa le saal', 'Lapa le tomon', 'Lapa le tomon obo',
    -    'Lapa le tomon waare'],
    -  SHORTMONTHS: ['Obo', 'Waa', 'Oku', 'Ong', 'Ime', 'Ile', 'Sap', 'Isi', 'Saa',
    -    'Tom', 'Tob', 'Tow'],
    -  STANDALONESHORTMONTHS: ['Obo', 'Waa', 'Oku', 'Ong', 'Ime', 'Ile', 'Sap',
    -    'Isi', 'Saa', 'Tom', 'Tob', 'Tow'],
    -  WEEKDAYS: ['Mderot ee are', 'Mderot ee kuni', 'Mderot ee ong’wan',
    -    'Mderot ee inet', 'Mderot ee ile', 'Mderot ee sapa', 'Mderot ee kwe'],
    -  STANDALONEWEEKDAYS: ['Mderot ee are', 'Mderot ee kuni', 'Mderot ee ong’wan',
    -    'Mderot ee inet', 'Mderot ee ile', 'Mderot ee sapa', 'Mderot ee kwe'],
    -  SHORTWEEKDAYS: ['Are', 'Kun', 'Ong', 'Ine', 'Ile', 'Sap', 'Kwe'],
    -  STANDALONESHORTWEEKDAYS: ['Are', 'Kun', 'Ong', 'Ine', 'Ile', 'Sap', 'Kwe'],
    -  NARROWWEEKDAYS: ['A', 'K', 'O', 'I', 'I', 'S', 'K'],
    -  STANDALONENARROWWEEKDAYS: ['A', 'K', 'O', 'I', 'I', 'S', 'K'],
    -  SHORTQUARTERS: ['R1', 'R2', 'R3', 'R4'],
    -  QUARTERS: ['Robo 1', 'Robo 2', 'Robo 3', 'Robo 4'],
    -  AMPMS: ['Tesiran', 'Teipa'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale saq_KE.
    - */
    -goog.i18n.DateTimeSymbols_saq_KE = goog.i18n.DateTimeSymbols_saq;
    -
    -
    -/**
    - * Date/time formatting symbols for locale sbp.
    - */
    -goog.i18n.DateTimeSymbols_sbp = {
    -  ERAS: ['AK', 'PK'],
    -  ERANAMES: ['Ashanali uKilisito', 'Pamwandi ya Kilisto'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['Mupalangulwa', 'Mwitope', 'Mushende', 'Munyi', 'Mushende Magali',
    -    'Mujimbi', 'Mushipepo', 'Mupuguto', 'Munyense', 'Mokhu', 'Musongandembwe',
    -    'Muhaano'],
    -  STANDALONEMONTHS: ['Mupalangulwa', 'Mwitope', 'Mushende', 'Munyi',
    -    'Mushende Magali', 'Mujimbi', 'Mushipepo', 'Mupuguto', 'Munyense', 'Mokhu',
    -    'Musongandembwe', 'Muhaano'],
    -  SHORTMONTHS: ['Mup', 'Mwi', 'Msh', 'Mun', 'Mag', 'Muj', 'Msp', 'Mpg', 'Mye',
    -    'Mok', 'Mus', 'Muh'],
    -  STANDALONESHORTMONTHS: ['Mup', 'Mwi', 'Msh', 'Mun', 'Mag', 'Muj', 'Msp',
    -    'Mpg', 'Mye', 'Mok', 'Mus', 'Muh'],
    -  WEEKDAYS: ['Mulungu', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alahamisi',
    -    'Ijumaa', 'Jumamosi'],
    -  STANDALONEWEEKDAYS: ['Mulungu', 'Jumatatu', 'Jumanne', 'Jumatano',
    -    'Alahamisi', 'Ijumaa', 'Jumamosi'],
    -  SHORTWEEKDAYS: ['Mul', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
    -  STANDALONESHORTWEEKDAYS: ['Mul', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
    -  NARROWWEEKDAYS: ['M', 'J', 'J', 'J', 'A', 'I', 'J'],
    -  STANDALONENARROWWEEKDAYS: ['M', 'J', 'J', 'J', 'A', 'I', 'J'],
    -  SHORTQUARTERS: ['L1', 'L2', 'L3', 'L4'],
    -  QUARTERS: ['Lobo 1', 'Lobo 2', 'Lobo 3', 'Lobo 4'],
    -  AMPMS: ['Lwamilawu', 'Pashamihe'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale sbp_TZ.
    - */
    -goog.i18n.DateTimeSymbols_sbp_TZ = goog.i18n.DateTimeSymbols_sbp;
    -
    -
    -/**
    - * Date/time formatting symbols for locale se.
    - */
    -goog.i18n.DateTimeSymbols_se = {
    -  ERAS: ['o.Kr.', 'm.Kr.'],
    -  ERANAMES: ['ovdal Kristtusa', 'maŋŋel Kristtusa'],
    -  NARROWMONTHS: ['O', 'G', 'N', 'C', 'M', 'G', 'S', 'B', 'Č', 'G', 'S', 'J'],
    -  STANDALONENARROWMONTHS: ['O', 'G', 'N', 'C', 'M', 'G', 'S', 'B', 'Č', 'G',
    -    'S', 'J'],
    -  MONTHS: ['ođđajagemánnu', 'guovvamánnu', 'njukčamánnu', 'cuoŋománnu',
    -    'miessemánnu', 'geassemánnu', 'suoidnemánnu', 'borgemánnu',
    -    'čakčamánnu', 'golggotmánnu', 'skábmamánnu', 'juovlamánnu'],
    -  STANDALONEMONTHS: ['ođđajagemánnu', 'guovvamánnu', 'njukčamánnu',
    -    'cuoŋománnu', 'miessemánnu', 'geassemánnu', 'suoidnemánnu',
    -    'borgemánnu', 'čakčamánnu', 'golggotmánnu', 'skábmamánnu',
    -    'juovlamánnu'],
    -  SHORTMONTHS: ['ođđj', 'guov', 'njuk', 'cuo', 'mies', 'geas', 'suoi', 'borg',
    -    'čakč', 'golg', 'skáb', 'juov'],
    -  STANDALONESHORTMONTHS: ['ođđj', 'guov', 'njuk', 'cuo', 'mies', 'geas',
    -    'suoi', 'borg', 'čakč', 'golg', 'skáb', 'juov'],
    -  WEEKDAYS: ['sotnabeaivi', 'vuossárga', 'maŋŋebárga', 'gaskavahkku',
    -    'duorasdat', 'bearjadat', 'lávvardat'],
    -  STANDALONEWEEKDAYS: ['sotnabeaivi', 'vuossárga', 'maŋŋebárga',
    -    'gaskavahkku', 'duorasdat', 'bearjadat', 'lávvardat'],
    -  SHORTWEEKDAYS: ['sotn', 'vuos', 'maŋ', 'gask', 'duor', 'bear', 'láv'],
    -  STANDALONESHORTWEEKDAYS: ['sotn', 'vuos', 'maŋ', 'gask', 'duor', 'bear',
    -    'láv'],
    -  NARROWWEEKDAYS: ['S', 'V', 'M', 'G', 'D', 'B', 'L'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'V', 'M', 'G', 'D', 'B', 'L'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['iđitbeaivet', 'eahketbeaivet'],
    -  DATEFORMATS: ['y MMMM d, EEEE', 'y MMMM d', 'y MMM d', 'y-MM-dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale se_FI.
    - */
    -goog.i18n.DateTimeSymbols_se_FI = {
    -  ERAS: ['o.Kr.', 'm.Kr.'],
    -  ERANAMES: ['ovdal Kristtusa', 'maŋŋel Kristtusa'],
    -  NARROWMONTHS: ['O', 'G', 'N', 'C', 'M', 'G', 'S', 'B', 'Č', 'G', 'S', 'J'],
    -  STANDALONENARROWMONTHS: ['O', 'G', 'N', 'C', 'M', 'G', 'S', 'B', 'Č', 'G',
    -    'S', 'J'],
    -  MONTHS: ['ođđajagemánnu', 'guovvamánnu', 'njukčamánnu', 'cuoŋománnu',
    -    'miessemánnu', 'geassemánnu', 'suoidnemánnu', 'borgemánnu',
    -    'čakčamánnu', 'golggotmánnu', 'skábmamánnu', 'juovlamánnu'],
    -  STANDALONEMONTHS: ['ođđajagemánnu', 'guovvamánnu', 'njukčamánnu',
    -    'cuoŋománnu', 'miessemánnu', 'geassemánnu', 'suoidnemánnu',
    -    'borgemánnu', 'čakčamánnu', 'golggotmánnu', 'skábmamánnu',
    -    'juovlamánnu'],
    -  SHORTMONTHS: ['ođđajage', 'guovva', 'njukča', 'cuoŋo', 'miesse', 'geasse',
    -    'suoidne', 'borge', 'čakča', 'golggot', 'skábma', 'juovla'],
    -  STANDALONESHORTMONTHS: ['ođđajage', 'guovva', 'njukča', 'cuoŋo', 'miesse',
    -    'geasse', 'suoidne', 'borge', 'čakča', 'golggot', 'skábma', 'juovla'],
    -  WEEKDAYS: ['aejlege', 'måanta', 'däjsta', 'gaskevahkoe', 'dåarsta',
    -    'bearjadahke', 'laavadahke'],
    -  STANDALONEWEEKDAYS: ['aejlege', 'måanta', 'däjsta', 'gaskevahkoe',
    -    'dåarsta', 'bearjadahke', 'laavadahke'],
    -  SHORTWEEKDAYS: ['sotn', 'vuos', 'maŋ', 'gask', 'duor', 'bear', 'láv'],
    -  STANDALONESHORTWEEKDAYS: ['sotn', 'vuos', 'maŋ', 'gask', 'duor', 'bear',
    -    'láv'],
    -  NARROWWEEKDAYS: ['S', 'M', 'D', 'G', 'D', 'B', 'L'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'D', 'G', 'D', 'B', 'L'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['iđitbeaivet', 'eahketbeaivet'],
    -  DATEFORMATS: ['y MMMM d, EEEE', 'y MMMM d', 'y MMM d', 'y-MM-dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale se_NO.
    - */
    -goog.i18n.DateTimeSymbols_se_NO = goog.i18n.DateTimeSymbols_se;
    -
    -
    -/**
    - * Date/time formatting symbols for locale se_SE.
    - */
    -goog.i18n.DateTimeSymbols_se_SE = goog.i18n.DateTimeSymbols_se;
    -
    -
    -/**
    - * Date/time formatting symbols for locale seh.
    - */
    -goog.i18n.DateTimeSymbols_seh = {
    -  ERAS: ['AC', 'AD'],
    -  ERANAMES: ['Antes de Cristo', 'Anno Domini'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Janeiro', 'Fevreiro', 'Marco', 'Abril', 'Maio', 'Junho', 'Julho',
    -    'Augusto', 'Setembro', 'Otubro', 'Novembro', 'Decembro'],
    -  STANDALONEMONTHS: ['Janeiro', 'Fevreiro', 'Marco', 'Abril', 'Maio', 'Junho',
    -    'Julho', 'Augusto', 'Setembro', 'Otubro', 'Novembro', 'Decembro'],
    -  SHORTMONTHS: ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Aug', 'Set',
    -    'Otu', 'Nov', 'Dec'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul',
    -    'Aug', 'Set', 'Otu', 'Nov', 'Dec'],
    -  WEEKDAYS: ['Dimingu', 'Chiposi', 'Chipiri', 'Chitatu', 'Chinai', 'Chishanu',
    -    'Sabudu'],
    -  STANDALONEWEEKDAYS: ['Dimingu', 'Chiposi', 'Chipiri', 'Chitatu', 'Chinai',
    -    'Chishanu', 'Sabudu'],
    -  SHORTWEEKDAYS: ['Dim', 'Pos', 'Pir', 'Tat', 'Nai', 'Sha', 'Sab'],
    -  STANDALONESHORTWEEKDAYS: ['Dim', 'Pos', 'Pir', 'Tat', 'Nai', 'Sha', 'Sab'],
    -  NARROWWEEKDAYS: ['D', 'P', 'C', 'T', 'N', 'S', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'P', 'C', 'T', 'N', 'S', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d \'de\' MMMM \'de\' y', 'd \'de\' MMMM \'de\' y',
    -    'd \'de\' MMM \'de\' y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale seh_MZ.
    - */
    -goog.i18n.DateTimeSymbols_seh_MZ = goog.i18n.DateTimeSymbols_seh;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ses.
    - */
    -goog.i18n.DateTimeSymbols_ses = {
    -  ERAS: ['IJ', 'IZ'],
    -  ERANAMES: ['Isaa jine', 'Isaa zamanoo'],
    -  NARROWMONTHS: ['Ž', 'F', 'M', 'A', 'M', 'Ž', 'Ž', 'U', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['Ž', 'F', 'M', 'A', 'M', 'Ž', 'Ž', 'U', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Žanwiye', 'Feewiriye', 'Marsi', 'Awiril', 'Me', 'Žuweŋ',
    -    'Žuyye', 'Ut', 'Sektanbur', 'Oktoobur', 'Noowanbur', 'Deesanbur'],
    -  STANDALONEMONTHS: ['Žanwiye', 'Feewiriye', 'Marsi', 'Awiril', 'Me',
    -    'Žuweŋ', 'Žuyye', 'Ut', 'Sektanbur', 'Oktoobur', 'Noowanbur',
    -    'Deesanbur'],
    -  SHORTMONTHS: ['Žan', 'Fee', 'Mar', 'Awi', 'Me', 'Žuw', 'Žuy', 'Ut', 'Sek',
    -    'Okt', 'Noo', 'Dee'],
    -  STANDALONESHORTMONTHS: ['Žan', 'Fee', 'Mar', 'Awi', 'Me', 'Žuw', 'Žuy',
    -    'Ut', 'Sek', 'Okt', 'Noo', 'Dee'],
    -  WEEKDAYS: ['Alhadi', 'Atinni', 'Atalaata', 'Alarba', 'Alhamiisa', 'Alzuma',
    -    'Asibti'],
    -  STANDALONEWEEKDAYS: ['Alhadi', 'Atinni', 'Atalaata', 'Alarba', 'Alhamiisa',
    -    'Alzuma', 'Asibti'],
    -  SHORTWEEKDAYS: ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alz', 'Asi'],
    -  STANDALONESHORTWEEKDAYS: ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alz', 'Asi'],
    -  NARROWWEEKDAYS: ['H', 'T', 'T', 'L', 'L', 'L', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['H', 'T', 'T', 'L', 'L', 'L', 'S'],
    -  SHORTQUARTERS: ['A1', 'A2', 'A3', 'A4'],
    -  QUARTERS: ['Arrubu 1', 'Arrubu 2', 'Arrubu 3', 'Arrubu 4'],
    -  AMPMS: ['Adduha', 'Aluula'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM, y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ses_ML.
    - */
    -goog.i18n.DateTimeSymbols_ses_ML = goog.i18n.DateTimeSymbols_ses;
    -
    -
    -/**
    - * Date/time formatting symbols for locale sg.
    - */
    -goog.i18n.DateTimeSymbols_sg = {
    -  ERAS: ['KnK', 'NpK'],
    -  ERANAMES: ['Kôzo na Krîstu', 'Na pekô tî Krîstu'],
    -  NARROWMONTHS: ['N', 'F', 'M', 'N', 'B', 'F', 'L', 'K', 'M', 'N', 'N', 'K'],
    -  STANDALONENARROWMONTHS: ['N', 'F', 'M', 'N', 'B', 'F', 'L', 'K', 'M', 'N',
    -    'N', 'K'],
    -  MONTHS: ['Nyenye', 'Fulundïgi', 'Mbängü', 'Ngubùe', 'Bêläwü', 'Föndo',
    -    'Lengua', 'Kükürü', 'Mvuka', 'Ngberere', 'Nabändüru', 'Kakauka'],
    -  STANDALONEMONTHS: ['Nyenye', 'Fulundïgi', 'Mbängü', 'Ngubùe', 'Bêläwü',
    -    'Föndo', 'Lengua', 'Kükürü', 'Mvuka', 'Ngberere', 'Nabändüru',
    -    'Kakauka'],
    -  SHORTMONTHS: ['Nye', 'Ful', 'Mbä', 'Ngu', 'Bêl', 'Fön', 'Len', 'Kük',
    -    'Mvu', 'Ngb', 'Nab', 'Kak'],
    -  STANDALONESHORTMONTHS: ['Nye', 'Ful', 'Mbä', 'Ngu', 'Bêl', 'Fön', 'Len',
    -    'Kük', 'Mvu', 'Ngb', 'Nab', 'Kak'],
    -  WEEKDAYS: ['Bikua-ôko', 'Bïkua-ûse', 'Bïkua-ptâ', 'Bïkua-usïö',
    -    'Bïkua-okü', 'Lâpôsö', 'Lâyenga'],
    -  STANDALONEWEEKDAYS: ['Bikua-ôko', 'Bïkua-ûse', 'Bïkua-ptâ',
    -    'Bïkua-usïö', 'Bïkua-okü', 'Lâpôsö', 'Lâyenga'],
    -  SHORTWEEKDAYS: ['Bk1', 'Bk2', 'Bk3', 'Bk4', 'Bk5', 'Lâp', 'Lây'],
    -  STANDALONESHORTWEEKDAYS: ['Bk1', 'Bk2', 'Bk3', 'Bk4', 'Bk5', 'Lâp', 'Lây'],
    -  NARROWWEEKDAYS: ['K', 'S', 'T', 'S', 'K', 'P', 'Y'],
    -  STANDALONENARROWWEEKDAYS: ['K', 'S', 'T', 'S', 'K', 'P', 'Y'],
    -  SHORTQUARTERS: ['F4-1', 'F4-2', 'F4-3', 'F4-4'],
    -  QUARTERS: ['Fângbisïö ôko', 'Fângbisïö ûse', 'Fângbisïö otâ',
    -    'Fângbisïö usïö'],
    -  AMPMS: ['ND', 'LK'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM, y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale sg_CF.
    - */
    -goog.i18n.DateTimeSymbols_sg_CF = goog.i18n.DateTimeSymbols_sg;
    -
    -
    -/**
    - * Date/time formatting symbols for locale shi.
    - */
    -goog.i18n.DateTimeSymbols_shi = {
    -  ERAS: ['ⴷⴰⵄ', 'ⴷⴼⵄ'],
    -  ERANAMES: ['ⴷⴰⵜ ⵏ ⵄⵉⵙⴰ', 'ⴷⴼⴼⵉⵔ ⵏ ⵄⵉⵙⴰ'],
    -  NARROWMONTHS: ['ⵉ', 'ⴱ', 'ⵎ', 'ⵉ', 'ⵎ', 'ⵢ', 'ⵢ', 'ⵖ', 'ⵛ',
    -    'ⴽ', 'ⵏ', 'ⴷ'],
    -  STANDALONENARROWMONTHS: ['ⵉ', 'ⴱ', 'ⵎ', 'ⵉ', 'ⵎ', 'ⵢ', 'ⵢ',
    -    'ⵖ', 'ⵛ', 'ⴽ', 'ⵏ', 'ⴷ'],
    -  MONTHS: ['ⵉⵏⵏⴰⵢⵔ', 'ⴱⵕⴰⵢⵕ', 'ⵎⴰⵕⵚ',
    -    'ⵉⴱⵔⵉⵔ', 'ⵎⴰⵢⵢⵓ', 'ⵢⵓⵏⵢⵓ',
    -    'ⵢⵓⵍⵢⵓⵣ', 'ⵖⵓⵛⵜ', 'ⵛⵓⵜⴰⵏⴱⵉⵔ',
    -    'ⴽⵜⵓⴱⵔ', 'ⵏⵓⵡⴰⵏⴱⵉⵔ', 'ⴷⵓⵊⴰⵏⴱⵉⵔ'],
    -  STANDALONEMONTHS: ['ⵉⵏⵏⴰⵢⵔ', 'ⴱⵕⴰⵢⵕ', 'ⵎⴰⵕⵚ',
    -    'ⵉⴱⵔⵉⵔ', 'ⵎⴰⵢⵢⵓ', 'ⵢⵓⵏⵢⵓ',
    -    'ⵢⵓⵍⵢⵓⵣ', 'ⵖⵓⵛⵜ', 'ⵛⵓⵜⴰⵏⴱⵉⵔ',
    -    'ⴽⵜⵓⴱⵔ', 'ⵏⵓⵡⴰⵏⴱⵉⵔ', 'ⴷⵓⵊⴰⵏⴱⵉⵔ'],
    -  SHORTMONTHS: ['ⵉⵏⵏ', 'ⴱⵕⴰ', 'ⵎⴰⵕ', 'ⵉⴱⵔ', 'ⵎⴰⵢ',
    -    'ⵢⵓⵏ', 'ⵢⵓⵍ', 'ⵖⵓⵛ', 'ⵛⵓⵜ', 'ⴽⵜⵓ',
    -    'ⵏⵓⵡ', 'ⴷⵓⵊ'],
    -  STANDALONESHORTMONTHS: ['ⵉⵏⵏ', 'ⴱⵕⴰ', 'ⵎⴰⵕ', 'ⵉⴱⵔ',
    -    'ⵎⴰⵢ', 'ⵢⵓⵏ', 'ⵢⵓⵍ', 'ⵖⵓⵛ', 'ⵛⵓⵜ',
    -    'ⴽⵜⵓ', 'ⵏⵓⵡ', 'ⴷⵓⵊ'],
    -  WEEKDAYS: ['ⴰⵙⴰⵎⴰⵙ', 'ⴰⵢⵏⴰⵙ', 'ⴰⵙⵉⵏⴰⵙ',
    -    'ⴰⴽⵕⴰⵙ', 'ⴰⴽⵡⴰⵙ', 'ⵙⵉⵎⵡⴰⵙ',
    -    'ⴰⵙⵉⴹⵢⴰⵙ'],
    -  STANDALONEWEEKDAYS: ['ⴰⵙⴰⵎⴰⵙ', 'ⴰⵢⵏⴰⵙ',
    -    'ⴰⵙⵉⵏⴰⵙ', 'ⴰⴽⵕⴰⵙ', 'ⴰⴽⵡⴰⵙ',
    -    'ⵙⵉⵎⵡⴰⵙ', 'ⴰⵙⵉⴹⵢⴰⵙ'],
    -  SHORTWEEKDAYS: ['ⴰⵙⴰ', 'ⴰⵢⵏ', 'ⴰⵙⵉ', 'ⴰⴽⵕ',
    -    'ⴰⴽⵡ', 'ⴰⵙⵉⵎ', 'ⴰⵙⵉⴹ'],
    -  STANDALONESHORTWEEKDAYS: ['ⴰⵙⴰ', 'ⴰⵢⵏ', 'ⴰⵙⵉ', 'ⴰⴽⵕ',
    -    'ⴰⴽⵡ', 'ⴰⵙⵉⵎ', 'ⴰⵙⵉⴹ'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['ⴰⴽ 1', 'ⴰⴽ 2', 'ⴰⴽ 3', 'ⴰⴽ 4'],
    -  QUARTERS: ['ⴰⴽⵕⴰⴹⵢⵓⵔ 1', 'ⴰⴽⵕⴰⴹⵢⵓⵔ 2',
    -    'ⴰⴽⵕⴰⴹⵢⵓⵔ 3', 'ⴰⴽⵕⴰⴹⵢⵓⵔ 4'],
    -  AMPMS: ['ⵜⵉⴼⴰⵡⵜ', 'ⵜⴰⴷⴳⴳⵯⴰⵜ'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM, y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale shi_Latn.
    - */
    -goog.i18n.DateTimeSymbols_shi_Latn = {
    -  ERAS: ['daɛ', 'dfɛ'],
    -  ERANAMES: ['dat n ɛisa', 'dffir n ɛisa'],
    -  NARROWMONTHS: ['i', 'b', 'm', 'i', 'm', 'y', 'y', 'ɣ', 'c', 'k', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['i', 'b', 'm', 'i', 'm', 'y', 'y', 'ɣ', 'c', 'k',
    -    'n', 'd'],
    -  MONTHS: ['innayr', 'bṛayṛ', 'maṛṣ', 'ibrir', 'mayyu', 'yunyu',
    -    'yulyuz', 'ɣuct', 'cutanbir', 'ktubr', 'nuwanbir', 'dujanbir'],
    -  STANDALONEMONTHS: ['innayr', 'bṛayṛ', 'maṛṣ', 'ibrir', 'mayyu',
    -    'yunyu', 'yulyuz', 'ɣuct', 'cutanbir', 'ktubr', 'nuwanbir', 'dujanbir'],
    -  SHORTMONTHS: ['inn', 'bṛa', 'maṛ', 'ibr', 'may', 'yun', 'yul', 'ɣuc',
    -    'cut', 'ktu', 'nuw', 'duj'],
    -  STANDALONESHORTMONTHS: ['inn', 'bṛa', 'maṛ', 'ibr', 'may', 'yun', 'yul',
    -    'ɣuc', 'cut', 'ktu', 'nuw', 'duj'],
    -  WEEKDAYS: ['asamas', 'aynas', 'asinas', 'akṛas', 'akwas', 'asimwas',
    -    'asiḍyas'],
    -  STANDALONEWEEKDAYS: ['asamas', 'aynas', 'asinas', 'akṛas', 'akwas',
    -    'asimwas', 'asiḍyas'],
    -  SHORTWEEKDAYS: ['asa', 'ayn', 'asi', 'akṛ', 'akw', 'asim', 'asiḍ'],
    -  STANDALONESHORTWEEKDAYS: ['asa', 'ayn', 'asi', 'akṛ', 'akw', 'asim',
    -    'asiḍ'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['ak 1', 'ak 2', 'ak 3', 'ak 4'],
    -  QUARTERS: ['akṛaḍyur 1', 'akṛaḍyur 2', 'akṛaḍyur 3',
    -    'akṛaḍyur 4'],
    -  AMPMS: ['tifawt', 'tadggʷat'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM, y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale shi_Latn_MA.
    - */
    -goog.i18n.DateTimeSymbols_shi_Latn_MA = goog.i18n.DateTimeSymbols_shi_Latn;
    -
    -
    -/**
    - * Date/time formatting symbols for locale shi_Tfng.
    - */
    -goog.i18n.DateTimeSymbols_shi_Tfng = goog.i18n.DateTimeSymbols_shi;
    -
    -
    -/**
    - * Date/time formatting symbols for locale shi_Tfng_MA.
    - */
    -goog.i18n.DateTimeSymbols_shi_Tfng_MA = goog.i18n.DateTimeSymbols_shi;
    -
    -
    -/**
    - * Date/time formatting symbols for locale si_LK.
    - */
    -goog.i18n.DateTimeSymbols_si_LK = {
    -  ERAS: ['ක්‍රි.පූ.', 'ක්‍රි.ව.'],
    -  ERANAMES: ['ක්‍රිස්තු පූර්‍ව',
    -    'ක්‍රිස්තු වර්‍ෂ'],
    -  NARROWMONTHS: ['ජ', 'පෙ', 'මා', 'අ', 'මැ', 'ජූ', 'ජූ',
    -    'අ', 'සැ', 'ඔ', 'නෙ', 'දෙ'],
    -  STANDALONENARROWMONTHS: ['ජ', 'පෙ', 'මා', 'අ', 'මැ', 'ජූ',
    -    'ජූ', 'අ', 'සැ', 'ඔ', 'නෙ', 'දෙ'],
    -  MONTHS: ['ජනවාරි', 'පෙබරවාරි',
    -    'මාර්තු', 'අප්‍රේල්', 'මැයි',
    -    'ජූනි', 'ජූලි', 'අගෝස්තු',
    -    'සැප්තැම්බර්', 'ඔක්තෝබර්',
    -    'නොවැම්බර්', 'දෙසැම්බර්'],
    -  STANDALONEMONTHS: ['ජනවාරි', 'පෙබරවාරි',
    -    'මාර්තු', 'අප්‍රේල්', 'මැයි',
    -    'ජූනි', 'ජූලි', 'අගෝස්තු',
    -    'සැප්තැම්බර්', 'ඔක්තෝබර්',
    -    'නොවැම්බර්', 'දෙසැම්බර්'],
    -  SHORTMONTHS: ['ජන', 'පෙබ', 'මාර්තු',
    -    'අප්‍රේල්', 'මැයි', 'ජූනි', 'ජූලි',
    -    'අගෝ', 'සැප්', 'ඔක්', 'නොවැ', 'දෙසැ'],
    -  STANDALONESHORTMONTHS: ['ජන', 'පෙබ', 'මාර්',
    -    'අප්‍රේල්', 'මැයි', 'ජූනි', 'ජූලි',
    -    'අගෝ', 'සැප්', 'ඔක්', 'නොවැ', 'දෙසැ'],
    -  WEEKDAYS: ['ඉරිදා', 'සඳුදා',
    -    'අඟහරුවාදා', 'බදාදා',
    -    'බ්‍රහස්පතින්දා', 'සිකුරාදා',
    -    'සෙනසුරාදා'],
    -  STANDALONEWEEKDAYS: ['ඉරිදා', 'සඳුදා',
    -    'අඟහරුවාදා', 'බදාදා',
    -    'බ්‍රහස්පතින්දා', 'සිකුරාදා',
    -    'සෙනසුරාදා'],
    -  SHORTWEEKDAYS: ['ඉරිදා', 'සඳුදා', 'අඟහ',
    -    'බදාදා', 'බ්‍රහස්', 'සිකු', 'සෙන'],
    -  STANDALONESHORTWEEKDAYS: ['ඉරිදා', 'සඳුදා', 'අඟහ',
    -    'බදාදා', 'බ්‍රහස්', 'සිකු', 'සෙන'],
    -  NARROWWEEKDAYS: ['ඉ', 'ස', 'අ', 'බ', 'බ්‍ර', 'සි',
    -    'සෙ'],
    -  STANDALONENARROWWEEKDAYS: ['ඉ', 'ස', 'අ', 'බ', 'බ්‍ර',
    -    'සි', 'සෙ'],
    -  SHORTQUARTERS: ['කාර්:1', 'කාර්:2', 'කාර්:3',
    -    'කාර්:4'],
    -  QUARTERS: ['1 වන කාර්තුව', '2 වන කාර්තුව',
    -    '3 වන කාර්තුව', '4 වන කාර්තුව'],
    -  AMPMS: ['පෙ.ව.', 'ප.ව.'],
    -  DATEFORMATS: ['y MMMM d, EEEE', 'y MMMM d', 'y MMM d', 'y-MM-dd'],
    -  TIMEFORMATS: ['a h.mm.ss zzzz', 'a h.mm.ss z', 'a h.mm.ss', 'a h.mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale sk_SK.
    - */
    -goog.i18n.DateTimeSymbols_sk_SK = {
    -  ERAS: ['pred Kr.', 'po Kr.'],
    -  ERANAMES: ['pred Kristom', 'po Kristovi'],
    -  NARROWMONTHS: ['j', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['j', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o',
    -    'n', 'd'],
    -  MONTHS: ['januára', 'februára', 'marca', 'apríla', 'mája', 'júna',
    -    'júla', 'augusta', 'septembra', 'októbra', 'novembra', 'decembra'],
    -  STANDALONEMONTHS: ['január', 'február', 'marec', 'apríl', 'máj', 'jún',
    -    'júl', 'august', 'september', 'október', 'november', 'december'],
    -  SHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'máj', 'jún', 'júl', 'aug',
    -    'sep', 'okt', 'nov', 'dec'],
    -  STANDALONESHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'máj', 'jún', 'júl',
    -    'aug', 'sep', 'okt', 'nov', 'dec'],
    -  WEEKDAYS: ['nedeľa', 'pondelok', 'utorok', 'streda', 'štvrtok', 'piatok',
    -    'sobota'],
    -  STANDALONEWEEKDAYS: ['nedeľa', 'pondelok', 'utorok', 'streda', 'štvrtok',
    -    'piatok', 'sobota'],
    -  SHORTWEEKDAYS: ['ne', 'po', 'ut', 'st', 'št', 'pi', 'so'],
    -  STANDALONESHORTWEEKDAYS: ['ne', 'po', 'ut', 'st', 'št', 'pi', 'so'],
    -  NARROWWEEKDAYS: ['N', 'P', 'U', 'S', 'Š', 'P', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['N', 'P', 'U', 'S', 'Š', 'P', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1. štvrťrok', '2. štvrťrok', '3. štvrťrok',
    -    '4. štvrťrok'],
    -  AMPMS: ['dopoludnia', 'odpoludnia'],
    -  DATEFORMATS: ['EEEE, d. MMMM y', 'd. MMMM y', 'd. M. y', 'dd.MM.yy'],
    -  TIMEFORMATS: ['H:mm:ss zzzz', 'H:mm:ss z', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1}, {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale sl_SI.
    - */
    -goog.i18n.DateTimeSymbols_sl_SI = {
    -  ERAS: ['pr. n. št.', 'po Kr.'],
    -  ERANAMES: ['pred našim štetjem', 'naše štetje'],
    -  NARROWMONTHS: ['j', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['j', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o',
    -    'n', 'd'],
    -  MONTHS: ['januar', 'februar', 'marec', 'april', 'maj', 'junij', 'julij',
    -    'avgust', 'september', 'oktober', 'november', 'december'],
    -  STANDALONEMONTHS: ['januar', 'februar', 'marec', 'april', 'maj', 'junij',
    -    'julij', 'avgust', 'september', 'oktober', 'november', 'december'],
    -  SHORTMONTHS: ['jan.', 'feb.', 'mar.', 'apr.', 'maj', 'jun.', 'jul.', 'avg.',
    -    'sep.', 'okt.', 'nov.', 'dec.'],
    -  STANDALONESHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul',
    -    'avg', 'sep', 'okt', 'nov', 'dec'],
    -  WEEKDAYS: ['nedelja', 'ponedeljek', 'torek', 'sreda', 'četrtek', 'petek',
    -    'sobota'],
    -  STANDALONEWEEKDAYS: ['nedelja', 'ponedeljek', 'torek', 'sreda', 'četrtek',
    -    'petek', 'sobota'],
    -  SHORTWEEKDAYS: ['ned.', 'pon.', 'tor.', 'sre.', 'čet.', 'pet.', 'sob.'],
    -  STANDALONESHORTWEEKDAYS: ['ned', 'pon', 'tor', 'sre', 'čet', 'pet', 'sob'],
    -  NARROWWEEKDAYS: ['n', 'p', 't', 's', 'č', 'p', 's'],
    -  STANDALONENARROWWEEKDAYS: ['n', 'p', 't', 's', 'č', 'p', 's'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1. četrtletje', '2. četrtletje', '3. četrtletje',
    -    '4. četrtletje'],
    -  AMPMS: ['dop.', 'pop.'],
    -  DATEFORMATS: ['EEEE, dd. MMMM y', 'dd. MMMM y', 'd. MMM y', 'd. MM. yy'],
    -  TIMEFORMATS: ['HH.mm.ss zzzz', 'HH.mm.ss z', 'HH.mm.ss', 'HH.mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale smn.
    - */
    -goog.i18n.DateTimeSymbols_smn = {
    -  ERAS: ['BCE', 'CE'],
    -  ERANAMES: ['BCE', 'CE'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['M01', 'M02', 'M03', 'M04', 'M05', 'M06', 'M07', 'M08', 'M09', 'M10',
    -    'M11', 'M12'],
    -  STANDALONEMONTHS: ['uđđâivemáánu', 'kuovâmáánu', 'njuhčâmáánu',
    -    'cuáŋuimáánu', 'vyesimáánu', 'kesimáánu', 'syeinimáánu',
    -    'porgemáánu', 'čohčâmáánu', 'roovvâdmáánu', 'skammâmáánu',
    -    'juovlâmáánu'],
    -  SHORTMONTHS: ['M01', 'M02', 'M03', 'M04', 'M05', 'M06', 'M07', 'M08', 'M09',
    -    'M10', 'M11', 'M12'],
    -  STANDALONESHORTMONTHS: ['M01', 'M02', 'M03', 'M04', 'M05', 'M06', 'M07',
    -    'M08', 'M09', 'M10', 'M11', 'M12'],
    -  WEEKDAYS: ['pasepeeivi', 'vuossaargâ', 'majebaargâ', 'koskoho',
    -    'tuorâstuv', 'vástuppeeivi', 'lávurduv'],
    -  STANDALONEWEEKDAYS: ['pasepeivi', 'vuossargâ', 'majebargâ', 'koskokko',
    -    'tuorâstâh', 'vástuppeivi', 'lávurdâh'],
    -  SHORTWEEKDAYS: ['pa', 'vu', 'ma', 'ko', 'tu', 'vá', 'lá'],
    -  STANDALONESHORTWEEKDAYS: ['pa', 'vu', 'ma', 'ko', 'tu', 'vá', 'lá'],
    -  NARROWWEEKDAYS: ['P', 'V', 'M', 'K', 'T', 'V', 'L'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['1. niälj.', '2. niälj.', '3. niälj.', '4. niälj.'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['y MMMM d, EEEE', 'y MMMM d', 'y MMM d', 'y-MM-dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale smn_FI.
    - */
    -goog.i18n.DateTimeSymbols_smn_FI = goog.i18n.DateTimeSymbols_smn;
    -
    -
    -/**
    - * Date/time formatting symbols for locale sn.
    - */
    -goog.i18n.DateTimeSymbols_sn = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Kristo asati auya', 'Kristo ashaya'],
    -  NARROWMONTHS: ['N', 'K', 'K', 'K', 'C', 'C', 'C', 'N', 'G', 'G', 'M', 'Z'],
    -  STANDALONENARROWMONTHS: ['N', 'K', 'K', 'K', 'C', 'C', 'C', 'N', 'G', 'G',
    -    'M', 'Z'],
    -  MONTHS: ['Ndira', 'Kukadzi', 'Kurume', 'Kubvumbi', 'Chivabvu', 'Chikumi',
    -    'Chikunguru', 'Nyamavhuvhu', 'Gunyana', 'Gumiguru', 'Mbudzi', 'Zvita'],
    -  STANDALONEMONTHS: ['Ndira', 'Kukadzi', 'Kurume', 'Kubvumbi', 'Chivabvu',
    -    'Chikumi', 'Chikunguru', 'Nyamavhuvhu', 'Gunyana', 'Gumiguru', 'Mbudzi',
    -    'Zvita'],
    -  SHORTMONTHS: ['Ndi', 'Kuk', 'Kur', 'Kub', 'Chv', 'Chk', 'Chg', 'Nya', 'Gun',
    -    'Gum', 'Mb', 'Zvi'],
    -  STANDALONESHORTMONTHS: ['Ndi', 'Kuk', 'Kur', 'Kub', 'Chv', 'Chk', 'Chg',
    -    'Nya', 'Gun', 'Gum', 'Mb', 'Zvi'],
    -  WEEKDAYS: ['Svondo', 'Muvhuro', 'Chipiri', 'Chitatu', 'China', 'Chishanu',
    -    'Mugovera'],
    -  STANDALONEWEEKDAYS: ['Svondo', 'Muvhuro', 'Chipiri', 'Chitatu', 'China',
    -    'Chishanu', 'Mugovera'],
    -  SHORTWEEKDAYS: ['Svo', 'Muv', 'Chip', 'Chit', 'Chin', 'Chis', 'Mug'],
    -  STANDALONESHORTWEEKDAYS: ['Svo', 'Muv', 'Chip', 'Chit', 'Chin', 'Chis',
    -    'Mug'],
    -  NARROWWEEKDAYS: ['S', 'M', 'C', 'C', 'C', 'C', 'M'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'C', 'C', 'C', 'C', 'M'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['Kota 1', 'Kota 2', 'Kota 3', 'Kota 4'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale sn_ZW.
    - */
    -goog.i18n.DateTimeSymbols_sn_ZW = goog.i18n.DateTimeSymbols_sn;
    -
    -
    -/**
    - * Date/time formatting symbols for locale so.
    - */
    -goog.i18n.DateTimeSymbols_so = {
    -  ERAS: ['CK', 'CD'],
    -  ERANAMES: ['Ciise ka hor (CS)', 'Ciise ka dib (CS)'],
    -  NARROWMONTHS: ['K', 'L', 'S', 'A', 'S', 'L', 'T', 'S', 'S', 'T', 'K', 'L'],
    -  STANDALONENARROWMONTHS: ['K', 'L', 'S', 'A', 'S', 'L', 'T', 'S', 'S', 'T',
    -    'K', 'L'],
    -  MONTHS: ['Bisha Koobaad', 'Bisha Labaad', 'Bisha Saddexaad', 'Bisha Afraad',
    -    'Bisha Shanaad', 'Bisha Lixaad', 'Bisha Todobaad', 'Bisha Sideedaad',
    -    'Bisha Sagaalaad', 'Bisha Tobnaad', 'Bisha Kow iyo Tobnaad',
    -    'Bisha Laba iyo Tobnaad'],
    -  STANDALONEMONTHS: ['Bisha Koobaad', 'Bisha Labaad', 'Bisha Saddexaad',
    -    'Bisha Afraad', 'Bisha Shanaad', 'Bisha Lixaad', 'Bisha Todobaad',
    -    'Bisha Sideedaad', 'Bisha Sagaalaad', 'Bisha Tobnaad',
    -    'Bisha Kow iyo Tobnaad', 'Bisha Laba iyo Tobnaad'],
    -  SHORTMONTHS: ['Kob', 'Lab', 'Sad', 'Afr', 'Sha', 'Lix', 'Tod', 'Sid', 'Sag',
    -    'Tob', 'KIT', 'LIT'],
    -  STANDALONESHORTMONTHS: ['Kob', 'Lab', 'Sad', 'Afr', 'Sha', 'Lix', 'Tod',
    -    'Sid', 'Sag', 'Tob', 'KIT', 'LIT'],
    -  WEEKDAYS: ['Axad', 'Isniin', 'Talaado', 'Arbaco', 'Khamiis', 'Jimco',
    -    'Sabti'],
    -  STANDALONEWEEKDAYS: ['Axad', 'Isniin', 'Talaado', 'Arbaco', 'Khamiis',
    -    'Jimco', 'Sabti'],
    -  SHORTWEEKDAYS: ['Axd', 'Isn', 'Tal', 'Arb', 'Kha', 'Jim', 'Sab'],
    -  STANDALONESHORTWEEKDAYS: ['Axd', 'Isn', 'Tal', 'Arb', 'Kha', 'Jim', 'Sab'],
    -  NARROWWEEKDAYS: ['A', 'I', 'T', 'A', 'K', 'J', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['A', 'I', 'T', 'A', 'K', 'J', 'S'],
    -  SHORTQUARTERS: ['R1', 'R2', 'R3', 'R4'],
    -  QUARTERS: ['Rubaca 1aad', 'Rubaca 2aad', 'Rubaca 3aad', 'Rubaca 4aad'],
    -  AMPMS: ['sn.', 'gn.'],
    -  DATEFORMATS: ['EEEE, MMMM dd, y', 'dd MMMM y', 'dd-MMM-y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale so_DJ.
    - */
    -goog.i18n.DateTimeSymbols_so_DJ = goog.i18n.DateTimeSymbols_so;
    -
    -
    -/**
    - * Date/time formatting symbols for locale so_ET.
    - */
    -goog.i18n.DateTimeSymbols_so_ET = goog.i18n.DateTimeSymbols_so;
    -
    -
    -/**
    - * Date/time formatting symbols for locale so_KE.
    - */
    -goog.i18n.DateTimeSymbols_so_KE = goog.i18n.DateTimeSymbols_so;
    -
    -
    -/**
    - * Date/time formatting symbols for locale so_SO.
    - */
    -goog.i18n.DateTimeSymbols_so_SO = goog.i18n.DateTimeSymbols_so;
    -
    -
    -/**
    - * Date/time formatting symbols for locale sq_AL.
    - */
    -goog.i18n.DateTimeSymbols_sq_AL = {
    -  ERAS: ['p.e.r.', 'e.r.'],
    -  ERANAMES: ['para erës së re', 'erës së re'],
    -  NARROWMONTHS: ['J', 'S', 'M', 'P', 'M', 'Q', 'K', 'G', 'S', 'T', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'S', 'M', 'P', 'M', 'Q', 'K', 'G', 'S', 'T',
    -    'N', 'D'],
    -  MONTHS: ['janar', 'shkurt', 'mars', 'prill', 'maj', 'qershor', 'korrik',
    -    'gusht', 'shtator', 'tetor', 'nëntor', 'dhjetor'],
    -  STANDALONEMONTHS: ['Janar', 'Shkurt', 'Mars', 'Prill', 'Maj', 'Qershor',
    -    'Korrik', 'Gusht', 'Shtator', 'Tetor', 'Nëntor', 'Dhjetor'],
    -  SHORTMONTHS: ['Jan', 'Shk', 'Mar', 'Pri', 'Maj', 'Qer', 'Kor', 'Gsh', 'Sht',
    -    'Tet', 'Nën', 'Dhj'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Shk', 'Mar', 'Pri', 'Maj', 'Qer', 'Kor',
    -    'Gsh', 'Sht', 'Tet', 'Nën', 'Dhj'],
    -  WEEKDAYS: ['e diel', 'e hënë', 'e martë', 'e mërkurë', 'e enjte',
    -    'e premte', 'e shtunë'],
    -  STANDALONEWEEKDAYS: ['E diel', 'E hënë', 'E martë', 'E mërkurë',
    -    'E enjte', 'E premte', 'E shtunë'],
    -  SHORTWEEKDAYS: ['Die', 'Hën', 'Mar', 'Mër', 'Enj', 'Pre', 'Sht'],
    -  STANDALONESHORTWEEKDAYS: ['Die', 'Hën', 'Mar', 'Mër', 'Enj', 'Pre', 'Sht'],
    -  NARROWWEEKDAYS: ['D', 'H', 'M', 'M', 'E', 'P', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'H', 'M', 'M', 'E', 'P', 'S'],
    -  SHORTQUARTERS: ['tremujori I', 'tremujori II', 'tremujori III',
    -    'tremujori IV'],
    -  QUARTERS: ['tremujori i parë', 'tremujori i dytë', 'tremujori i tretë',
    -    'tremujori i katërt'],
    -  AMPMS: ['paradite', 'pasdite'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'd.M.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'në\' {0}', '{1} \'në\' {0}', '{1}, {0}',
    -    '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale sq_MK.
    - */
    -goog.i18n.DateTimeSymbols_sq_MK = {
    -  ERAS: ['p.e.r.', 'e.r.'],
    -  ERANAMES: ['para erës së re', 'erës së re'],
    -  NARROWMONTHS: ['J', 'S', 'M', 'P', 'M', 'Q', 'K', 'G', 'S', 'T', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'S', 'M', 'P', 'M', 'Q', 'K', 'G', 'S', 'T',
    -    'N', 'D'],
    -  MONTHS: ['janar', 'shkurt', 'mars', 'prill', 'maj', 'qershor', 'korrik',
    -    'gusht', 'shtator', 'tetor', 'nëntor', 'dhjetor'],
    -  STANDALONEMONTHS: ['Janar', 'Shkurt', 'Mars', 'Prill', 'Maj', 'Qershor',
    -    'Korrik', 'Gusht', 'Shtator', 'Tetor', 'Nëntor', 'Dhjetor'],
    -  SHORTMONTHS: ['Jan', 'Shk', 'Mar', 'Pri', 'Maj', 'Qer', 'Kor', 'Gsh', 'Sht',
    -    'Tet', 'Nën', 'Dhj'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Shk', 'Mar', 'Pri', 'Maj', 'Qer', 'Kor',
    -    'Gsh', 'Sht', 'Tet', 'Nën', 'Dhj'],
    -  WEEKDAYS: ['e diel', 'e hënë', 'e martë', 'e mërkurë', 'e enjte',
    -    'e premte', 'e shtunë'],
    -  STANDALONEWEEKDAYS: ['E diel', 'E hënë', 'E martë', 'E mërkurë',
    -    'E enjte', 'E premte', 'E shtunë'],
    -  SHORTWEEKDAYS: ['Die', 'Hën', 'Mar', 'Mër', 'Enj', 'Pre', 'Sht'],
    -  STANDALONESHORTWEEKDAYS: ['Die', 'Hën', 'Mar', 'Mër', 'Enj', 'Pre', 'Sht'],
    -  NARROWWEEKDAYS: ['D', 'H', 'M', 'M', 'E', 'P', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'H', 'M', 'M', 'E', 'P', 'S'],
    -  SHORTQUARTERS: ['tremujori I', 'tremujori II', 'tremujori III',
    -    'tremujori IV'],
    -  QUARTERS: ['tremujori i parë', 'tremujori i dytë', 'tremujori i tretë',
    -    'tremujori i katërt'],
    -  AMPMS: ['paradite', 'pasdite'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'd.M.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'në\' {0}', '{1} \'në\' {0}', '{1}, {0}',
    -    '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale sq_XK.
    - */
    -goog.i18n.DateTimeSymbols_sq_XK = {
    -  ERAS: ['p.e.r.', 'e.r.'],
    -  ERANAMES: ['para erës së re', 'erës së re'],
    -  NARROWMONTHS: ['J', 'S', 'M', 'P', 'M', 'Q', 'K', 'G', 'S', 'T', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'S', 'M', 'P', 'M', 'Q', 'K', 'G', 'S', 'T',
    -    'N', 'D'],
    -  MONTHS: ['janar', 'shkurt', 'mars', 'prill', 'maj', 'qershor', 'korrik',
    -    'gusht', 'shtator', 'tetor', 'nëntor', 'dhjetor'],
    -  STANDALONEMONTHS: ['Janar', 'Shkurt', 'Mars', 'Prill', 'Maj', 'Qershor',
    -    'Korrik', 'Gusht', 'Shtator', 'Tetor', 'Nëntor', 'Dhjetor'],
    -  SHORTMONTHS: ['Jan', 'Shk', 'Mar', 'Pri', 'Maj', 'Qer', 'Kor', 'Gsh', 'Sht',
    -    'Tet', 'Nën', 'Dhj'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Shk', 'Mar', 'Pri', 'Maj', 'Qer', 'Kor',
    -    'Gsh', 'Sht', 'Tet', 'Nën', 'Dhj'],
    -  WEEKDAYS: ['e diel', 'e hënë', 'e martë', 'e mërkurë', 'e enjte',
    -    'e premte', 'e shtunë'],
    -  STANDALONEWEEKDAYS: ['E diel', 'E hënë', 'E martë', 'E mërkurë',
    -    'E enjte', 'E premte', 'E shtunë'],
    -  SHORTWEEKDAYS: ['Die', 'Hën', 'Mar', 'Mër', 'Enj', 'Pre', 'Sht'],
    -  STANDALONESHORTWEEKDAYS: ['Die', 'Hën', 'Mar', 'Mër', 'Enj', 'Pre', 'Sht'],
    -  NARROWWEEKDAYS: ['D', 'H', 'M', 'M', 'E', 'P', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['D', 'H', 'M', 'M', 'E', 'P', 'S'],
    -  SHORTQUARTERS: ['tremujori I', 'tremujori II', 'tremujori III',
    -    'tremujori IV'],
    -  QUARTERS: ['tremujori i parë', 'tremujori i dytë', 'tremujori i tretë',
    -    'tremujori i katërt'],
    -  AMPMS: ['paradite', 'pasdite'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'd.M.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} \'në\' {0}', '{1} \'në\' {0}', '{1}, {0}',
    -    '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale sr_Cyrl.
    - */
    -goog.i18n.DateTimeSymbols_sr_Cyrl = {
    -  ERAS: ['п. н. е.', 'н. е.'],
    -  ERANAMES: ['Пре нове ере', 'Нове ере'],
    -  NARROWMONTHS: ['ј', 'ф', 'м', 'а', 'м', 'ј', 'ј', 'а', 'с', 'о',
    -    'н', 'д'],
    -  STANDALONENARROWMONTHS: ['ј', 'ф', 'м', 'а', 'м', 'ј', 'ј', 'а', 'с',
    -    'о', 'н', 'д'],
    -  MONTHS: ['јануар', 'фебруар', 'март', 'април', 'мај',
    -    'јун', 'јул', 'август', 'септембар', 'октобар',
    -    'новембар', 'децембар'],
    -  STANDALONEMONTHS: ['јануар', 'фебруар', 'март', 'април',
    -    'мај', 'јун', 'јул', 'август', 'септембар',
    -    'октобар', 'новембар', 'децембар'],
    -  SHORTMONTHS: ['јан', 'феб', 'мар', 'апр', 'мај', 'јун',
    -    'јул', 'авг', 'сеп', 'окт', 'нов', 'дец'],
    -  STANDALONESHORTMONTHS: ['јан', 'феб', 'мар', 'апр', 'мај',
    -    'јун', 'јул', 'авг', 'сеп', 'окт', 'нов', 'дец'],
    -  WEEKDAYS: ['недеља', 'понедељак', 'уторак', 'среда',
    -    'четвртак', 'петак', 'субота'],
    -  STANDALONEWEEKDAYS: ['недеља', 'понедељак', 'уторак',
    -    'среда', 'четвртак', 'петак', 'субота'],
    -  SHORTWEEKDAYS: ['нед', 'пон', 'уто', 'сре', 'чет', 'пет',
    -    'суб'],
    -  STANDALONESHORTWEEKDAYS: ['нед', 'пон', 'уто', 'сре', 'чет',
    -    'пет', 'суб'],
    -  NARROWWEEKDAYS: ['н', 'п', 'у', 'с', 'ч', 'п', 'с'],
    -  STANDALONENARROWWEEKDAYS: ['н', 'п', 'у', 'с', 'ч', 'п', 'с'],
    -  SHORTQUARTERS: ['К1', 'К2', 'К3', 'К4'],
    -  QUARTERS: ['Прво тромесечје', 'Друго тромесечје',
    -    'Треће тромесечје', 'Четврто тромесечје'],
    -  AMPMS: ['пре подне', 'по подне'],
    -  DATEFORMATS: ['EEEE, dd. MMMM y.', 'dd. MMMM y.', 'dd.MM.y.', 'd.M.yy.'],
    -  TIMEFORMATS: ['HH.mm.ss zzzz', 'HH.mm.ss z', 'HH.mm.ss', 'HH.mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale sr_Cyrl_BA.
    - */
    -goog.i18n.DateTimeSymbols_sr_Cyrl_BA = {
    -  ERAS: ['п. н. е.', 'н. е.'],
    -  ERANAMES: ['Пре нове ере', 'Нове ере'],
    -  NARROWMONTHS: ['ј', 'ф', 'м', 'а', 'м', 'ј', 'ј', 'а', 'с', 'о',
    -    'н', 'д'],
    -  STANDALONENARROWMONTHS: ['ј', 'ф', 'м', 'а', 'м', 'ј', 'ј', 'а', 'с',
    -    'о', 'н', 'д'],
    -  MONTHS: ['јануар', 'фебруар', 'март', 'април', 'мај',
    -    'јуни', 'јули', 'август', 'септембар',
    -    'октобар', 'новембар', 'децембар'],
    -  STANDALONEMONTHS: ['јануар', 'фебруар', 'март', 'април',
    -    'мај', 'јун', 'јул', 'август', 'септембар',
    -    'октобар', 'новембар', 'децембар'],
    -  SHORTMONTHS: ['јан', 'феб', 'мар', 'апр', 'мај', 'јун',
    -    'јул', 'авг', 'сеп', 'окт', 'нов', 'дец'],
    -  STANDALONESHORTMONTHS: ['јан', 'феб', 'мар', 'апр', 'мај',
    -    'јун', 'јул', 'авг', 'сеп', 'окт', 'нов', 'дец'],
    -  WEEKDAYS: ['недеља', 'понедељак', 'уторак',
    -    'сриједа', 'четвртак', 'петак', 'субота'],
    -  STANDALONEWEEKDAYS: ['недеља', 'понедељак', 'уторак',
    -    'среда', 'четвртак', 'петак', 'субота'],
    -  SHORTWEEKDAYS: ['нед', 'пон', 'уто', 'сри', 'чет', 'пет',
    -    'суб'],
    -  STANDALONESHORTWEEKDAYS: ['нед', 'пон', 'уто', 'сре', 'чет',
    -    'пет', 'суб'],
    -  NARROWWEEKDAYS: ['н', 'п', 'у', 'с', 'ч', 'п', 'с'],
    -  STANDALONENARROWWEEKDAYS: ['н', 'п', 'у', 'с', 'ч', 'п', 'с'],
    -  SHORTQUARTERS: ['К1', 'К2', 'К3', 'К4'],
    -  QUARTERS: ['Прво тромесечје', 'Друго тромесечје',
    -    'Треће тромесечје', 'Четврто тромесечје'],
    -  AMPMS: ['пре подне', 'по подне'],
    -  DATEFORMATS: ['EEEE, dd. MMMM y.', 'dd. MMMM y.', 'y-MM-dd', 'yy-MM-dd'],
    -  TIMEFORMATS: [
    -    'HH \'часова\', mm \'минута\', ss \'секунди\' zzzz',
    -    'HH.mm.ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale sr_Cyrl_ME.
    - */
    -goog.i18n.DateTimeSymbols_sr_Cyrl_ME = goog.i18n.DateTimeSymbols_sr_Cyrl;
    -
    -
    -/**
    - * Date/time formatting symbols for locale sr_Cyrl_RS.
    - */
    -goog.i18n.DateTimeSymbols_sr_Cyrl_RS = goog.i18n.DateTimeSymbols_sr_Cyrl;
    -
    -
    -/**
    - * Date/time formatting symbols for locale sr_Cyrl_XK.
    - */
    -goog.i18n.DateTimeSymbols_sr_Cyrl_XK = goog.i18n.DateTimeSymbols_sr_Cyrl;
    -
    -
    -/**
    - * Date/time formatting symbols for locale sr_Latn.
    - */
    -goog.i18n.DateTimeSymbols_sr_Latn = {
    -  ERAS: ['p. n. e.', 'n. e.'],
    -  ERANAMES: ['Pre nove ere', 'Nove ere'],
    -  NARROWMONTHS: ['j', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['j', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o',
    -    'n', 'd'],
    -  MONTHS: ['januar', 'februar', 'mart', 'april', 'maj', 'jun', 'jul', 'avgust',
    -    'septembar', 'oktobar', 'novembar', 'decembar'],
    -  STANDALONEMONTHS: ['januar', 'februar', 'mart', 'april', 'maj', 'jun', 'jul',
    -    'avgust', 'septembar', 'oktobar', 'novembar', 'decembar'],
    -  SHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'avg', 'sep',
    -    'okt', 'nov', 'dec'],
    -  STANDALONESHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul',
    -    'avg', 'sep', 'okt', 'nov', 'dec'],
    -  WEEKDAYS: ['nedelja', 'ponedeljak', 'utorak', 'sreda', 'četvrtak', 'petak',
    -    'subota'],
    -  STANDALONEWEEKDAYS: ['nedelja', 'ponedeljak', 'utorak', 'sreda', 'četvrtak',
    -    'petak', 'subota'],
    -  SHORTWEEKDAYS: ['ned', 'pon', 'uto', 'sre', 'čet', 'pet', 'sub'],
    -  STANDALONESHORTWEEKDAYS: ['ned', 'pon', 'uto', 'sre', 'čet', 'pet', 'sub'],
    -  NARROWWEEKDAYS: ['n', 'p', 'u', 's', 'č', 'p', 's'],
    -  STANDALONENARROWWEEKDAYS: ['n', 'p', 'u', 's', 'č', 'p', 's'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['Prvo tromesečje', 'Drugo tromesečje', 'Treće tromesečje',
    -    'Četvrto tromesečje'],
    -  AMPMS: ['pre podne', 'po podne'],
    -  DATEFORMATS: ['EEEE, dd. MMMM y.', 'dd. MMMM y.', 'dd.MM.y.', 'd.M.yy.'],
    -  TIMEFORMATS: ['HH.mm.ss zzzz', 'HH.mm.ss z', 'HH.mm.ss', 'HH.mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale sr_Latn_BA.
    - */
    -goog.i18n.DateTimeSymbols_sr_Latn_BA = {
    -  ERAS: ['p. n. e.', 'n. e.'],
    -  ERANAMES: ['Pre nove ere', 'Nove ere'],
    -  NARROWMONTHS: ['j', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],
    -  STANDALONENARROWMONTHS: ['j', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o',
    -    'n', 'd'],
    -  MONTHS: ['januar', 'februar', 'mart', 'april', 'maj', 'juni', 'juli',
    -    'avgust', 'septembar', 'oktobar', 'novembar', 'decembar'],
    -  STANDALONEMONTHS: ['januar', 'februar', 'mart', 'april', 'maj', 'jun', 'jul',
    -    'avgust', 'septembar', 'oktobar', 'novembar', 'decembar'],
    -  SHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'avg', 'sep',
    -    'okt', 'nov', 'dec'],
    -  STANDALONESHORTMONTHS: ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul',
    -    'avg', 'sep', 'okt', 'nov', 'dec'],
    -  WEEKDAYS: ['nedelja', 'ponedeljak', 'utorak', 'srijeda', 'četvrtak', 'petak',
    -    'subota'],
    -  STANDALONEWEEKDAYS: ['nedelja', 'ponedeljak', 'utorak', 'sreda', 'četvrtak',
    -    'petak', 'subota'],
    -  SHORTWEEKDAYS: ['ned', 'pon', 'uto', 'sri', 'čet', 'pet', 'sub'],
    -  STANDALONESHORTWEEKDAYS: ['ned', 'pon', 'uto', 'sre', 'čet', 'pet', 'sub'],
    -  NARROWWEEKDAYS: ['n', 'p', 'u', 's', 'č', 'p', 's'],
    -  STANDALONENARROWWEEKDAYS: ['n', 'p', 'u', 's', 'č', 'p', 's'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['Prvo tromesečje', 'Drugo tromesečje', 'Treće tromesečje',
    -    'Četvrto tromesečje'],
    -  AMPMS: ['pre podne', 'po podne'],
    -  DATEFORMATS: ['EEEE, dd. MMMM y.', 'dd. MMMM y.', 'y-MM-dd', 'yy-MM-dd'],
    -  TIMEFORMATS: ['HH \'časova\', mm \'minuta\', ss \'sekundi\' zzzz',
    -    'HH.mm.ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale sr_Latn_ME.
    - */
    -goog.i18n.DateTimeSymbols_sr_Latn_ME = goog.i18n.DateTimeSymbols_sr_Latn;
    -
    -
    -/**
    - * Date/time formatting symbols for locale sr_Latn_RS.
    - */
    -goog.i18n.DateTimeSymbols_sr_Latn_RS = goog.i18n.DateTimeSymbols_sr_Latn;
    -
    -
    -/**
    - * Date/time formatting symbols for locale sr_Latn_XK.
    - */
    -goog.i18n.DateTimeSymbols_sr_Latn_XK = goog.i18n.DateTimeSymbols_sr_Latn;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ss.
    - */
    -goog.i18n.DateTimeSymbols_ss = {
    -  ERAS: ['BCE', 'CE'],
    -  ERANAMES: ['BCE', 'CE'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['Bhimbidvwane', 'iNdlovana', 'iNdlovu-lenkhulu', 'Mabasa',
    -    'iNkhwekhweti', 'iNhlaba', 'Kholwane', 'iNgci', 'iNyoni', 'iMphala',
    -    'Lweti', 'iNgongoni'],
    -  STANDALONEMONTHS: ['Bhimbidvwane', 'iNdlovana', 'iNdlovu-lenkhulu', 'Mabasa',
    -    'iNkhwekhweti', 'iNhlaba', 'Kholwane', 'iNgci', 'iNyoni', 'iMphala',
    -    'Lweti', 'iNgongoni'],
    -  SHORTMONTHS: ['Bhi', 'Van', 'Vol', 'Mab', 'Nkh', 'Nhl', 'Kho', 'Ngc', 'Nyo',
    -    'Mph', 'Lwe', 'Ngo'],
    -  STANDALONESHORTMONTHS: ['Bhi', 'Van', 'Vol', 'Mab', 'Nkh', 'Nhl', 'Kho',
    -    'Ngc', 'Nyo', 'Mph', 'Lwe', 'Ngo'],
    -  WEEKDAYS: ['Lisontfo', 'uMsombuluko', 'Lesibili', 'Lesitsatfu', 'Lesine',
    -    'Lesihlanu', 'uMgcibelo'],
    -  STANDALONEWEEKDAYS: ['Lisontfo', 'uMsombuluko', 'Lesibili', 'Lesitsatfu',
    -    'Lesine', 'Lesihlanu', 'uMgcibelo'],
    -  SHORTWEEKDAYS: ['Son', 'Mso', 'Bil', 'Tsa', 'Ne', 'Hla', 'Mgc'],
    -  STANDALONESHORTWEEKDAYS: ['Son', 'Mso', 'Bil', 'Tsa', 'Ne', 'Hla', 'Mgc'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['y MMMM d, EEEE', 'y MMMM d', 'y MMM d', 'y-MM-dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ss_SZ.
    - */
    -goog.i18n.DateTimeSymbols_ss_SZ = goog.i18n.DateTimeSymbols_ss;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ss_ZA.
    - */
    -goog.i18n.DateTimeSymbols_ss_ZA = goog.i18n.DateTimeSymbols_ss;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ssy.
    - */
    -goog.i18n.DateTimeSymbols_ssy = {
    -  ERAS: ['Yaasuusuk Duma', 'Yaasuusuk Wadir'],
    -  ERANAMES: ['Yaasuusuk Duma', 'Yaasuusuk Wadir'],
    -  NARROWMONTHS: ['Q', 'N', 'C', 'A', 'C', 'Q', 'Q', 'L', 'W', 'D', 'X', 'K'],
    -  STANDALONENARROWMONTHS: ['Q', 'N', 'C', 'A', 'C', 'Q', 'Q', 'L', 'W', 'D',
    -    'X', 'K'],
    -  MONTHS: ['Qunxa Garablu', 'Kudo', 'Ciggilta Kudo', 'Agda Baxis', 'Caxah Alsa',
    -    'Qasa Dirri', 'Qado Dirri', 'Liiqen', 'Waysu', 'Diteli', 'Ximoli',
    -    'Kaxxa Garablu'],
    -  STANDALONEMONTHS: ['Qunxa Garablu', 'Kudo', 'Ciggilta Kudo', 'Agda Baxis',
    -    'Caxah Alsa', 'Qasa Dirri', 'Qado Dirri', 'Liiqen', 'Waysu', 'Diteli',
    -    'Ximoli', 'Kaxxa Garablu'],
    -  SHORTMONTHS: ['Qun', 'Nah', 'Cig', 'Agd', 'Cax', 'Qas', 'Qad', 'Leq', 'Way',
    -    'Dit', 'Xim', 'Kax'],
    -  STANDALONESHORTMONTHS: ['Qun', 'Nah', 'Cig', 'Agd', 'Cax', 'Qas', 'Qad',
    -    'Leq', 'Way', 'Dit', 'Xim', 'Kax'],
    -  WEEKDAYS: ['Naba Sambat', 'Sani', 'Salus', 'Rabuq', 'Camus', 'Jumqata',
    -    'Qunxa Sambat'],
    -  STANDALONEWEEKDAYS: ['Naba Sambat', 'Sani', 'Salus', 'Rabuq', 'Camus',
    -    'Jumqata', 'Qunxa Sambat'],
    -  SHORTWEEKDAYS: ['Nab', 'San', 'Sal', 'Rab', 'Cam', 'Jum', 'Qun'],
    -  STANDALONESHORTWEEKDAYS: ['Nab', 'San', 'Sal', 'Rab', 'Cam', 'Jum', 'Qun'],
    -  NARROWWEEKDAYS: ['N', 'S', 'S', 'R', 'C', 'J', 'Q'],
    -  STANDALONENARROWWEEKDAYS: ['N', 'S', 'S', 'R', 'C', 'J', 'Q'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['saaku', 'carra'],
    -  DATEFORMATS: ['EEEE, MMMM dd, y', 'dd MMMM y', 'dd-MMM-y', 'dd/MM/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ssy_ER.
    - */
    -goog.i18n.DateTimeSymbols_ssy_ER = goog.i18n.DateTimeSymbols_ssy;
    -
    -
    -/**
    - * Date/time formatting symbols for locale sv_AX.
    - */
    -goog.i18n.DateTimeSymbols_sv_AX = {
    -  ERAS: ['f.Kr.', 'e.Kr.'],
    -  ERANAMES: ['före Kristus', 'efter Kristus'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['januari', 'februari', 'mars', 'april', 'maj', 'juni', 'juli',
    -    'augusti', 'september', 'oktober', 'november', 'december'],
    -  STANDALONEMONTHS: ['Januari', 'Februari', 'Mars', 'April', 'Maj', 'Juni',
    -    'Juli', 'Augusti', 'September', 'Oktober', 'November', 'December'],
    -  SHORTMONTHS: ['jan.', 'feb.', 'mars', 'apr.', 'maj', 'juni', 'juli', 'aug.',
    -    'sep.', 'okt.', 'nov.', 'dec.'],
    -  STANDALONESHORTMONTHS: ['Jan.', 'Feb.', 'Mars', 'Apr.', 'Maj', 'Juni', 'Juli',
    -    'Aug.', 'Sep.', 'Okt.', 'Nov.', 'Dec.'],
    -  WEEKDAYS: ['söndag', 'måndag', 'tisdag', 'onsdag', 'torsdag', 'fredag',
    -    'lördag'],
    -  STANDALONEWEEKDAYS: ['Söndag', 'Måndag', 'Tisdag', 'Onsdag', 'Torsdag',
    -    'Fredag', 'Lördag'],
    -  SHORTWEEKDAYS: ['sön', 'mån', 'tis', 'ons', 'tors', 'fre', 'lör'],
    -  STANDALONESHORTWEEKDAYS: ['Sön', 'Mån', 'Tis', 'Ons', 'Tor', 'Fre', 'Lör'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'O', 'T', 'F', 'L'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'O', 'T', 'F', 'L'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['1:a kvartalet', '2:a kvartalet', '3:e kvartalet',
    -    '4:e kvartalet'],
    -  AMPMS: ['fm', 'em'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'y-MM-dd'],
    -  TIMEFORMATS: ['\'kl\'. HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale sv_FI.
    - */
    -goog.i18n.DateTimeSymbols_sv_FI = {
    -  ERAS: ['f.Kr.', 'e.Kr.'],
    -  ERANAMES: ['före Kristus', 'efter Kristus'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['januari', 'februari', 'mars', 'april', 'maj', 'juni', 'juli',
    -    'augusti', 'september', 'oktober', 'november', 'december'],
    -  STANDALONEMONTHS: ['Januari', 'Februari', 'Mars', 'April', 'Maj', 'Juni',
    -    'Juli', 'Augusti', 'September', 'Oktober', 'November', 'December'],
    -  SHORTMONTHS: ['jan.', 'feb.', 'mars', 'apr.', 'maj', 'juni', 'juli', 'aug.',
    -    'sep.', 'okt.', 'nov.', 'dec.'],
    -  STANDALONESHORTMONTHS: ['Jan.', 'Feb.', 'Mars', 'Apr.', 'Maj', 'Juni', 'Juli',
    -    'Aug.', 'Sep.', 'Okt.', 'Nov.', 'Dec.'],
    -  WEEKDAYS: ['söndag', 'måndag', 'tisdag', 'onsdag', 'torsdag', 'fredag',
    -    'lördag'],
    -  STANDALONEWEEKDAYS: ['Söndag', 'Måndag', 'Tisdag', 'Onsdag', 'Torsdag',
    -    'Fredag', 'Lördag'],
    -  SHORTWEEKDAYS: ['sön', 'mån', 'tis', 'ons', 'tors', 'fre', 'lör'],
    -  STANDALONESHORTWEEKDAYS: ['Sön', 'Mån', 'Tis', 'Ons', 'Tor', 'Fre', 'Lör'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'O', 'T', 'F', 'L'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'O', 'T', 'F', 'L'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['1:a kvartalet', '2:a kvartalet', '3:e kvartalet',
    -    '4:e kvartalet'],
    -  AMPMS: ['fm', 'em'],
    -  DATEFORMATS: ['EEEE\'en\' \'den\' d:\'e\' MMMM y', 'd MMMM y', 'd MMM y',
    -    'dd-MM-y'],
    -  TIMEFORMATS: ['\'kl\'. HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale sv_SE.
    - */
    -goog.i18n.DateTimeSymbols_sv_SE = {
    -  ERAS: ['f.Kr.', 'e.Kr.'],
    -  ERANAMES: ['före Kristus', 'efter Kristus'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['januari', 'februari', 'mars', 'april', 'maj', 'juni', 'juli',
    -    'augusti', 'september', 'oktober', 'november', 'december'],
    -  STANDALONEMONTHS: ['Januari', 'Februari', 'Mars', 'April', 'Maj', 'Juni',
    -    'Juli', 'Augusti', 'September', 'Oktober', 'November', 'December'],
    -  SHORTMONTHS: ['jan.', 'feb.', 'mars', 'apr.', 'maj', 'juni', 'juli', 'aug.',
    -    'sep.', 'okt.', 'nov.', 'dec.'],
    -  STANDALONESHORTMONTHS: ['Jan.', 'Feb.', 'Mars', 'Apr.', 'Maj', 'Juni', 'Juli',
    -    'Aug.', 'Sep.', 'Okt.', 'Nov.', 'Dec.'],
    -  WEEKDAYS: ['söndag', 'måndag', 'tisdag', 'onsdag', 'torsdag', 'fredag',
    -    'lördag'],
    -  STANDALONEWEEKDAYS: ['Söndag', 'Måndag', 'Tisdag', 'Onsdag', 'Torsdag',
    -    'Fredag', 'Lördag'],
    -  SHORTWEEKDAYS: ['sön', 'mån', 'tis', 'ons', 'tors', 'fre', 'lör'],
    -  STANDALONESHORTWEEKDAYS: ['Sön', 'Mån', 'Tis', 'Ons', 'Tor', 'Fre', 'Lör'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'O', 'T', 'F', 'L'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'O', 'T', 'F', 'L'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['1:a kvartalet', '2:a kvartalet', '3:e kvartalet',
    -    '4:e kvartalet'],
    -  AMPMS: ['fm', 'em'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'y-MM-dd'],
    -  TIMEFORMATS: ['\'kl\'. HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 3
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale sw_KE.
    - */
    -goog.i18n.DateTimeSymbols_sw_KE = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Kabla ya Kristo', 'Baada ya Kristo'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni', 'Julai',
    -    'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    -  STANDALONEMONTHS: ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni',
    -    'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep',
    -    'Okt', 'Nov', 'Des'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul',
    -    'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
    -  WEEKDAYS: ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alhamisi',
    -    'Ijumaa', 'Jumamosi'],
    -  STANDALONEWEEKDAYS: ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano',
    -    'Alhamisi', 'Ijumaa', 'Jumamosi'],
    -  SHORTWEEKDAYS: ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alhamisi',
    -    'Ijumaa', 'Jumamosi'],
    -  STANDALONESHORTWEEKDAYS: ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano',
    -    'Alhamisi', 'Ijumaa', 'Jumamosi'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Robo ya 1', 'Robo ya 2', 'Robo ya 3', 'Robo ya 4'],
    -  QUARTERS: ['Robo ya 1', 'Robo ya 2', 'Robo ya 3', 'Robo ya 4'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale sw_TZ.
    - */
    -goog.i18n.DateTimeSymbols_sw_TZ = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Kabla ya Kristo', 'Baada ya Kristo'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni', 'Julai',
    -    'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    -  STANDALONEMONTHS: ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni',
    -    'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep',
    -    'Okt', 'Nov', 'Des'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul',
    -    'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
    -  WEEKDAYS: ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alhamisi',
    -    'Ijumaa', 'Jumamosi'],
    -  STANDALONEWEEKDAYS: ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano',
    -    'Alhamisi', 'Ijumaa', 'Jumamosi'],
    -  SHORTWEEKDAYS: ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alhamisi',
    -    'Ijumaa', 'Jumamosi'],
    -  STANDALONESHORTWEEKDAYS: ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano',
    -    'Alhamisi', 'Ijumaa', 'Jumamosi'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Robo ya 1', 'Robo ya 2', 'Robo ya 3', 'Robo ya 4'],
    -  QUARTERS: ['Robo ya 1', 'Robo ya 2', 'Robo ya 3', 'Robo ya 4'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale sw_UG.
    - */
    -goog.i18n.DateTimeSymbols_sw_UG = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['Kabla ya Kristo', 'Baada ya Kristo'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni', 'Julai',
    -    'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    -  STANDALONEMONTHS: ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni',
    -    'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep',
    -    'Okt', 'Nov', 'Des'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul',
    -    'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
    -  WEEKDAYS: ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alhamisi',
    -    'Ijumaa', 'Jumamosi'],
    -  STANDALONEWEEKDAYS: ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano',
    -    'Alhamisi', 'Ijumaa', 'Jumamosi'],
    -  SHORTWEEKDAYS: ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alhamisi',
    -    'Ijumaa', 'Jumamosi'],
    -  STANDALONESHORTWEEKDAYS: ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano',
    -    'Alhamisi', 'Ijumaa', 'Jumamosi'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Robo ya 1', 'Robo ya 2', 'Robo ya 3', 'Robo ya 4'],
    -  QUARTERS: ['Robo ya 1', 'Robo ya 2', 'Robo ya 3', 'Robo ya 4'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale swc.
    - */
    -goog.i18n.DateTimeSymbols_swc = {
    -  ERAS: ['mbele ya Y', 'kisha ya Y'],
    -  ERANAMES: ['mbele ya Yezu Kristo', 'kisha ya Yezu Kristo'],
    -  NARROWMONTHS: ['k', 'p', 't', 'i', 't', 's', 's', 'm', 't', 'k', 'm', 'm'],
    -  STANDALONENARROWMONTHS: ['k', 'p', 't', 'i', 't', 's', 's', 'm', 't', 'k',
    -    'm', 'm'],
    -  MONTHS: ['mwezi ya kwanja', 'mwezi ya pili', 'mwezi ya tatu', 'mwezi ya ine',
    -    'mwezi ya tanu', 'mwezi ya sita', 'mwezi ya saba', 'mwezi ya munane',
    -    'mwezi ya tisa', 'mwezi ya kumi', 'mwezi ya kumi na moya',
    -    'mwezi ya kumi ya mbili'],
    -  STANDALONEMONTHS: ['mwezi ya kwanja', 'mwezi ya pili', 'mwezi ya tatu',
    -    'mwezi ya ine', 'mwezi ya tanu', 'mwezi ya sita', 'mwezi ya saba',
    -    'mwezi ya munane', 'mwezi ya tisa', 'mwezi ya kumi',
    -    'mwezi ya kumi na moya', 'mwezi ya kumi ya mbili'],
    -  SHORTMONTHS: ['mkw', 'mpi', 'mtu', 'min', 'mtn', 'mst', 'msb', 'mun', 'mts',
    -    'mku', 'mkm', 'mkb'],
    -  STANDALONESHORTMONTHS: ['mkw', 'mpi', 'mtu', 'min', 'mtn', 'mst', 'msb',
    -    'mun', 'mts', 'mku', 'mkm', 'mkb'],
    -  WEEKDAYS: ['siku ya yenga', 'siku ya kwanza', 'siku ya pili', 'siku ya tatu',
    -    'siku ya ine', 'siku ya tanu', 'siku ya sita'],
    -  STANDALONEWEEKDAYS: ['siku ya yenga', 'siku ya kwanza', 'siku ya pili',
    -    'siku ya tatu', 'siku ya ine', 'siku ya tanu', 'siku ya sita'],
    -  SHORTWEEKDAYS: ['yen', 'kwa', 'pil', 'tat', 'ine', 'tan', 'sit'],
    -  STANDALONESHORTWEEKDAYS: ['yen', 'kwa', 'pil', 'tat', 'ine', 'tan', 'sit'],
    -  NARROWWEEKDAYS: ['y', 'k', 'p', 't', 'i', 't', 's'],
    -  STANDALONENARROWWEEKDAYS: ['y', 'k', 'p', 't', 'i', 't', 's'],
    -  SHORTQUARTERS: ['R1', 'R2', 'R3', 'R4'],
    -  QUARTERS: ['Robo 1', 'Robo 2', 'Robo 3', 'Robo 4'],
    -  AMPMS: ['ya asubuyi', 'ya muchana'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale swc_CD.
    - */
    -goog.i18n.DateTimeSymbols_swc_CD = goog.i18n.DateTimeSymbols_swc;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ta_IN.
    - */
    -goog.i18n.DateTimeSymbols_ta_IN = {
    -  ERAS: ['கி.மு.', 'கி.பி.'],
    -  ERANAMES: ['கிறிஸ்துவுக்கு முன்',
    -    'அனோ டோமினி'],
    -  NARROWMONTHS: ['ஜ', 'பி', 'மா', 'ஏ', 'மே', 'ஜூ', 'ஜூ',
    -    'ஆ', 'செ', 'அ', 'ந', 'டி'],
    -  STANDALONENARROWMONTHS: ['ஜ', 'பி', 'மா', 'ஏ', 'மே', 'ஜூ',
    -    'ஜூ', 'ஆ', 'செ', 'அ', 'ந', 'டி'],
    -  MONTHS: ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்',
    -    'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை',
    -    'ஆகஸ்ட்', 'செப்டம்பர்',
    -    'அக்டோபர்', 'நவம்பர்',
    -    'டிசம்பர்'],
    -  STANDALONEMONTHS: ['ஜனவரி', 'பிப்ரவரி',
    -    'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்',
    -    'ஜூலை', 'ஆகஸ்டு', 'செப்டம்பர்',
    -    'அக்டோபர்', 'நவம்பர்',
    -    'டிசம்பர்'],
    -  SHORTMONTHS: ['ஜன.', 'பிப்.', 'மார்.', 'ஏப்.',
    -    'மே', 'ஜூன்', 'ஜூலை', 'ஆக.', 'செப்.',
    -    'அக்.', 'நவ.', 'டிச.'],
    -  STANDALONESHORTMONTHS: ['ஜன.', 'பிப்.', 'மார்.',
    -    'ஏப்.', 'மே', 'ஜூன்', 'ஜூலை', 'ஆக.',
    -    'செப்.', 'அக்.', 'நவ.', 'டிச.'],
    -  WEEKDAYS: ['ஞாயிறு', 'திங்கள்',
    -    'செவ்வாய்', 'புதன்', 'வியாழன்',
    -    'வெள்ளி', 'சனி'],
    -  STANDALONEWEEKDAYS: ['ஞாயிறு', 'திங்கள்',
    -    'செவ்வாய்', 'புதன்', 'வியாழன்',
    -    'வெள்ளி', 'சனி'],
    -  SHORTWEEKDAYS: ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ',
    -    'ச'],
    -  STANDALONESHORTWEEKDAYS: ['ஞா', 'தி', 'செ', 'பு', 'வி',
    -    'வெ', 'ச'],
    -  NARROWWEEKDAYS: ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ',
    -    'ச'],
    -  STANDALONENARROWWEEKDAYS: ['ஞா', 'தி', 'செ', 'பு', 'வி',
    -    'வெ', 'ச'],
    -  SHORTQUARTERS: ['காலாண்டு1', 'காலாண்டு2',
    -    'காலாண்டு3', 'காலாண்டு4'],
    -  QUARTERS: ['முதல் காலாண்டு',
    -    'இரண்டாம் காலாண்டு',
    -    'மூன்றாம் காலாண்டு',
    -    'நான்காம் காலாண்டு'],
    -  AMPMS: ['முற்பகல்', 'பிற்பகல்'],
    -  DATEFORMATS: ['EEEE, d MMMM, y', 'd MMMM, y', 'd MMM, y', 'd-M-yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} ’அன்று’ {0}',
    -    '{1} ’அன்று’ {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [6, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ta_LK.
    - */
    -goog.i18n.DateTimeSymbols_ta_LK = {
    -  ERAS: ['கி.மு.', 'கி.பி.'],
    -  ERANAMES: ['கிறிஸ்துவுக்கு முன்',
    -    'அனோ டோமினி'],
    -  NARROWMONTHS: ['ஜ', 'பி', 'மா', 'ஏ', 'மே', 'ஜூ', 'ஜூ',
    -    'ஆ', 'செ', 'அ', 'ந', 'டி'],
    -  STANDALONENARROWMONTHS: ['ஜ', 'பி', 'மா', 'ஏ', 'மே', 'ஜூ',
    -    'ஜூ', 'ஆ', 'செ', 'அ', 'ந', 'டி'],
    -  MONTHS: ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்',
    -    'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை',
    -    'ஆகஸ்ட்', 'செப்டம்பர்',
    -    'அக்டோபர்', 'நவம்பர்',
    -    'டிசம்பர்'],
    -  STANDALONEMONTHS: ['ஜனவரி', 'பிப்ரவரி',
    -    'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்',
    -    'ஜூலை', 'ஆகஸ்டு', 'செப்டம்பர்',
    -    'அக்டோபர்', 'நவம்பர்',
    -    'டிசம்பர்'],
    -  SHORTMONTHS: ['ஜன.', 'பிப்.', 'மார்.', 'ஏப்.',
    -    'மே', 'ஜூன்', 'ஜூலை', 'ஆக.', 'செப்.',
    -    'அக்.', 'நவ.', 'டிச.'],
    -  STANDALONESHORTMONTHS: ['ஜன.', 'பிப்.', 'மார்.',
    -    'ஏப்.', 'மே', 'ஜூன்', 'ஜூலை', 'ஆக.',
    -    'செப்.', 'அக்.', 'நவ.', 'டிச.'],
    -  WEEKDAYS: ['ஞாயிறு', 'திங்கள்',
    -    'செவ்வாய்', 'புதன்', 'வியாழன்',
    -    'வெள்ளி', 'சனி'],
    -  STANDALONEWEEKDAYS: ['ஞாயிறு', 'திங்கள்',
    -    'செவ்வாய்', 'புதன்', 'வியாழன்',
    -    'வெள்ளி', 'சனி'],
    -  SHORTWEEKDAYS: ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ',
    -    'ச'],
    -  STANDALONESHORTWEEKDAYS: ['ஞா', 'தி', 'செ', 'பு', 'வி',
    -    'வெ', 'ச'],
    -  NARROWWEEKDAYS: ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ',
    -    'ச'],
    -  STANDALONENARROWWEEKDAYS: ['ஞா', 'தி', 'செ', 'பு', 'வி',
    -    'வெ', 'ச'],
    -  SHORTQUARTERS: ['காலாண்டு1', 'காலாண்டு2',
    -    'காலாண்டு3', 'காலாண்டு4'],
    -  QUARTERS: ['முதல் காலாண்டு',
    -    'இரண்டாம் காலாண்டு',
    -    'மூன்றாம் காலாண்டு',
    -    'நான்காம் காலாண்டு'],
    -  AMPMS: ['முற்பகல்', 'பிற்பகல்'],
    -  DATEFORMATS: ['EEEE, d MMMM, y', 'd MMMM, y', 'd MMM, y', 'd-M-yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} ’அன்று’ {0}',
    -    '{1} ’அன்று’ {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ta_MY.
    - */
    -goog.i18n.DateTimeSymbols_ta_MY = {
    -  ERAS: ['கி.மு.', 'கி.பி.'],
    -  ERANAMES: ['கிறிஸ்துவுக்கு முன்',
    -    'அனோ டோமினி'],
    -  NARROWMONTHS: ['ஜ', 'பி', 'மா', 'ஏ', 'மே', 'ஜூ', 'ஜூ',
    -    'ஆ', 'செ', 'அ', 'ந', 'டி'],
    -  STANDALONENARROWMONTHS: ['ஜ', 'பி', 'மா', 'ஏ', 'மே', 'ஜூ',
    -    'ஜூ', 'ஆ', 'செ', 'அ', 'ந', 'டி'],
    -  MONTHS: ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்',
    -    'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை',
    -    'ஆகஸ்ட்', 'செப்டம்பர்',
    -    'அக்டோபர்', 'நவம்பர்',
    -    'டிசம்பர்'],
    -  STANDALONEMONTHS: ['ஜனவரி', 'பிப்ரவரி',
    -    'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்',
    -    'ஜூலை', 'ஆகஸ்டு', 'செப்டம்பர்',
    -    'அக்டோபர்', 'நவம்பர்',
    -    'டிசம்பர்'],
    -  SHORTMONTHS: ['ஜன.', 'பிப்.', 'மார்.', 'ஏப்.',
    -    'மே', 'ஜூன்', 'ஜூலை', 'ஆக.', 'செப்.',
    -    'அக்.', 'நவ.', 'டிச.'],
    -  STANDALONESHORTMONTHS: ['ஜன.', 'பிப்.', 'மார்.',
    -    'ஏப்.', 'மே', 'ஜூன்', 'ஜூலை', 'ஆக.',
    -    'செப்.', 'அக்.', 'நவ.', 'டிச.'],
    -  WEEKDAYS: ['ஞாயிறு', 'திங்கள்',
    -    'செவ்வாய்', 'புதன்', 'வியாழன்',
    -    'வெள்ளி', 'சனி'],
    -  STANDALONEWEEKDAYS: ['ஞாயிறு', 'திங்கள்',
    -    'செவ்வாய்', 'புதன்', 'வியாழன்',
    -    'வெள்ளி', 'சனி'],
    -  SHORTWEEKDAYS: ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ',
    -    'ச'],
    -  STANDALONESHORTWEEKDAYS: ['ஞா', 'தி', 'செ', 'பு', 'வி',
    -    'வெ', 'ச'],
    -  NARROWWEEKDAYS: ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ',
    -    'ச'],
    -  STANDALONENARROWWEEKDAYS: ['ஞா', 'தி', 'செ', 'பு', 'வி',
    -    'வெ', 'ச'],
    -  SHORTQUARTERS: ['காலாண்டு1', 'காலாண்டு2',
    -    'காலாண்டு3', 'காலாண்டு4'],
    -  QUARTERS: ['முதல் காலாண்டு',
    -    'இரண்டாம் காலாண்டு',
    -    'மூன்றாம் காலாண்டு',
    -    'நான்காம் காலாண்டு'],
    -  AMPMS: ['முற்பகல்', 'பிற்பகல்'],
    -  DATEFORMATS: ['EEEE, d MMMM, y', 'd MMMM, y', 'd MMM, y', 'd-M-yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} ’அன்று’ {0}',
    -    '{1} ’அன்று’ {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ta_SG.
    - */
    -goog.i18n.DateTimeSymbols_ta_SG = {
    -  ERAS: ['கி.மு.', 'கி.பி.'],
    -  ERANAMES: ['கிறிஸ்துவுக்கு முன்',
    -    'அனோ டோமினி'],
    -  NARROWMONTHS: ['ஜ', 'பி', 'மா', 'ஏ', 'மே', 'ஜூ', 'ஜூ',
    -    'ஆ', 'செ', 'அ', 'ந', 'டி'],
    -  STANDALONENARROWMONTHS: ['ஜ', 'பி', 'மா', 'ஏ', 'மே', 'ஜூ',
    -    'ஜூ', 'ஆ', 'செ', 'அ', 'ந', 'டி'],
    -  MONTHS: ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்',
    -    'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை',
    -    'ஆகஸ்ட்', 'செப்டம்பர்',
    -    'அக்டோபர்', 'நவம்பர்',
    -    'டிசம்பர்'],
    -  STANDALONEMONTHS: ['ஜனவரி', 'பிப்ரவரி',
    -    'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்',
    -    'ஜூலை', 'ஆகஸ்டு', 'செப்டம்பர்',
    -    'அக்டோபர்', 'நவம்பர்',
    -    'டிசம்பர்'],
    -  SHORTMONTHS: ['ஜன.', 'பிப்.', 'மார்.', 'ஏப்.',
    -    'மே', 'ஜூன்', 'ஜூலை', 'ஆக.', 'செப்.',
    -    'அக்.', 'நவ.', 'டிச.'],
    -  STANDALONESHORTMONTHS: ['ஜன.', 'பிப்.', 'மார்.',
    -    'ஏப்.', 'மே', 'ஜூன்', 'ஜூலை', 'ஆக.',
    -    'செப்.', 'அக்.', 'நவ.', 'டிச.'],
    -  WEEKDAYS: ['ஞாயிறு', 'திங்கள்',
    -    'செவ்வாய்', 'புதன்', 'வியாழன்',
    -    'வெள்ளி', 'சனி'],
    -  STANDALONEWEEKDAYS: ['ஞாயிறு', 'திங்கள்',
    -    'செவ்வாய்', 'புதன்', 'வியாழன்',
    -    'வெள்ளி', 'சனி'],
    -  SHORTWEEKDAYS: ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ',
    -    'ச'],
    -  STANDALONESHORTWEEKDAYS: ['ஞா', 'தி', 'செ', 'பு', 'வி',
    -    'வெ', 'ச'],
    -  NARROWWEEKDAYS: ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ',
    -    'ச'],
    -  STANDALONENARROWWEEKDAYS: ['ஞா', 'தி', 'செ', 'பு', 'வி',
    -    'வெ', 'ச'],
    -  SHORTQUARTERS: ['காலாண்டு1', 'காலாண்டு2',
    -    'காலாண்டு3', 'காலாண்டு4'],
    -  QUARTERS: ['முதல் காலாண்டு',
    -    'இரண்டாம் காலாண்டு',
    -    'மூன்றாம் காலாண்டு',
    -    'நான்காம் காலாண்டு'],
    -  AMPMS: ['முற்பகல்', 'பிற்பகல்'],
    -  DATEFORMATS: ['EEEE, d MMMM, y', 'd MMMM, y', 'd MMM, y', 'd-M-yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} ’அன்று’ {0}',
    -    '{1} ’அன்று’ {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale te_IN.
    - */
    -goog.i18n.DateTimeSymbols_te_IN = {
    -  ERAS: ['క్రీపూ', 'క్రీశ'],
    -  ERANAMES: ['క్రీస్తు పూర్వం',
    -    'క్రీస్తు శకం'],
    -  NARROWMONTHS: ['జ', 'ఫి', 'మా', 'ఏ', 'మే', 'జూ', 'జు',
    -    'ఆ', 'సె', 'అ', 'న', 'డి'],
    -  STANDALONENARROWMONTHS: ['జ', 'ఫి', 'మా', 'ఏ', 'మే', 'జూ',
    -    'జు', 'ఆ', 'సె', 'అ', 'న', 'డి'],
    -  MONTHS: ['జనవరి', 'ఫిబ్రవరి', 'మార్చి',
    -    'ఏప్రిల్', 'మే', 'జూన్', 'జులై',
    -    'ఆగస్టు', 'సెప్టెంబర్',
    -    'అక్టోబర్', 'నవంబర్',
    -    'డిసెంబర్'],
    -  STANDALONEMONTHS: ['జనవరి', 'ఫిబ్రవరి',
    -    'మార్చి', 'ఏప్రిల్', 'మే', 'జూన్',
    -    'జులై', 'ఆగస్టు', 'సెప్టెంబర్',
    -    'అక్టోబర్', 'నవంబర్',
    -    'డిసెంబర్'],
    -  SHORTMONTHS: ['జన', 'ఫిబ్ర', 'మార్చి',
    -    'ఏప్రి', 'మే', 'జూన్', 'జులై', 'ఆగ',
    -    'సెప్టెం', 'అక్టో', 'నవం', 'డిసెం'],
    -  STANDALONESHORTMONTHS: ['జన', 'ఫిబ్ర', 'మార్చి',
    -    'ఏప్రి', 'మే', 'జూన్', 'జులై',
    -    'ఆగస్టు', 'సెప్టెం', 'అక్టో',
    -    'నవం', 'డిసెం'],
    -  WEEKDAYS: ['ఆదివారం', 'సోమవారం',
    -    'మంగళవారం', 'బుధవారం',
    -    'గురువారం', 'శుక్రవారం',
    -    'శనివారం'],
    -  STANDALONEWEEKDAYS: ['ఆదివారం', 'సోమవారం',
    -    'మంగళవారం', 'బుధవారం',
    -    'గురువారం', 'శుక్రవారం',
    -    'శనివారం'],
    -  SHORTWEEKDAYS: ['ఆది', 'సోమ', 'మంగళ', 'బుధ',
    -    'గురు', 'శుక్ర', 'శని'],
    -  STANDALONESHORTWEEKDAYS: ['ఆది', 'సోమ', 'మంగళ',
    -    'బుధ', 'గురు', 'శుక్ర', 'శని'],
    -  NARROWWEEKDAYS: ['ఆ', 'సో', 'మ', 'బు', 'గు', 'శు', 'శ'],
    -  STANDALONENARROWWEEKDAYS: ['ఆ', 'సో', 'మ', 'బు', 'గు',
    -    'శు', 'శ'],
    -  SHORTQUARTERS: ['త్రై1', 'త్రై2', 'త్రై3',
    -    'త్రై4'],
    -  QUARTERS: ['1వ త్రైమాసం', '2వ త్రైమాసం',
    -    '3వ త్రైమాసం', '4వ త్రైమాసం'],
    -  AMPMS: ['[AM]', '[PM]'],
    -  DATEFORMATS: ['d, MMMM y, EEEE', 'd MMMM, y', 'd MMM, y', 'dd-MM-yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [6, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale teo.
    - */
    -goog.i18n.DateTimeSymbols_teo = {
    -  ERAS: ['KK', 'BK'],
    -  ERANAMES: ['Kabla ya Christo', 'Baada ya Christo'],
    -  NARROWMONTHS: ['R', 'M', 'K', 'D', 'M', 'M', 'J', 'P', 'S', 'T', 'L', 'P'],
    -  STANDALONENARROWMONTHS: ['R', 'M', 'K', 'D', 'M', 'M', 'J', 'P', 'S', 'T',
    -    'L', 'P'],
    -  MONTHS: ['Orara', 'Omuk', 'Okwamg’', 'Odung’el', 'Omaruk',
    -    'Omodok’king’ol', 'Ojola', 'Opedel', 'Osokosokoma', 'Otibar', 'Olabor',
    -    'Opoo'],
    -  STANDALONEMONTHS: ['Orara', 'Omuk', 'Okwamg’', 'Odung’el', 'Omaruk',
    -    'Omodok’king’ol', 'Ojola', 'Opedel', 'Osokosokoma', 'Otibar', 'Olabor',
    -    'Opoo'],
    -  SHORTMONTHS: ['Rar', 'Muk', 'Kwa', 'Dun', 'Mar', 'Mod', 'Jol', 'Ped', 'Sok',
    -    'Tib', 'Lab', 'Poo'],
    -  STANDALONESHORTMONTHS: ['Rar', 'Muk', 'Kwa', 'Dun', 'Mar', 'Mod', 'Jol',
    -    'Ped', 'Sok', 'Tib', 'Lab', 'Poo'],
    -  WEEKDAYS: ['Nakaejuma', 'Nakaebarasa', 'Nakaare', 'Nakauni', 'Nakaung’on',
    -    'Nakakany', 'Nakasabiti'],
    -  STANDALONEWEEKDAYS: ['Nakaejuma', 'Nakaebarasa', 'Nakaare', 'Nakauni',
    -    'Nakaung’on', 'Nakakany', 'Nakasabiti'],
    -  SHORTWEEKDAYS: ['Jum', 'Bar', 'Aar', 'Uni', 'Ung', 'Kan', 'Sab'],
    -  STANDALONESHORTWEEKDAYS: ['Jum', 'Bar', 'Aar', 'Uni', 'Ung', 'Kan', 'Sab'],
    -  NARROWWEEKDAYS: ['J', 'B', 'A', 'U', 'U', 'K', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['J', 'B', 'A', 'U', 'U', 'K', 'S'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['Akwota abe', 'Akwota Aane', 'Akwota auni', 'Akwota Aung’on'],
    -  AMPMS: ['Taparachu', 'Ebongi'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale teo_KE.
    - */
    -goog.i18n.DateTimeSymbols_teo_KE = goog.i18n.DateTimeSymbols_teo;
    -
    -
    -/**
    - * Date/time formatting symbols for locale teo_UG.
    - */
    -goog.i18n.DateTimeSymbols_teo_UG = goog.i18n.DateTimeSymbols_teo;
    -
    -
    -/**
    - * Date/time formatting symbols for locale th_TH.
    - */
    -goog.i18n.DateTimeSymbols_th_TH = {
    -  ERAS: ['ปีก่อน ค.ศ.', 'ค.ศ.'],
    -  ERANAMES: ['ปีก่อนคริสต์ศักราช',
    -    'คริสต์ศักราช'],
    -  NARROWMONTHS: ['ม.ค.', 'ก.พ.', 'มี.ค.', 'เม.ย.',
    -    'พ.ค.', 'มิ.ย.', 'ก.ค.', 'ส.ค.', 'ก.ย.', 'ต.ค.',
    -    'พ.ย.', 'ธ.ค.'],
    -  STANDALONENARROWMONTHS: ['ม.ค.', 'ก.พ.', 'มี.ค.', 'เม.ย.',
    -    'พ.ค.', 'มิ.ย.', 'ก.ค.', 'ส.ค.', 'ก.ย.', 'ต.ค.',
    -    'พ.ย.', 'ธ.ค.'],
    -  MONTHS: ['มกราคม', 'กุมภาพันธ์',
    -    'มีนาคม', 'เมษายน', 'พฤษภาคม',
    -    'มิถุนายน', 'กรกฎาคม',
    -    'สิงหาคม', 'กันยายน', 'ตุลาคม',
    -    'พฤศจิกายน', 'ธันวาคม'],
    -  STANDALONEMONTHS: ['มกราคม', 'กุมภาพันธ์',
    -    'มีนาคม', 'เมษายน', 'พฤษภาคม',
    -    'มิถุนายน', 'กรกฎาคม',
    -    'สิงหาคม', 'กันยายน', 'ตุลาคม',
    -    'พฤศจิกายน', 'ธันวาคม'],
    -  SHORTMONTHS: ['ม.ค.', 'ก.พ.', 'มี.ค.', 'เม.ย.',
    -    'พ.ค.', 'มิ.ย.', 'ก.ค.', 'ส.ค.', 'ก.ย.', 'ต.ค.',
    -    'พ.ย.', 'ธ.ค.'],
    -  STANDALONESHORTMONTHS: ['ม.ค.', 'ก.พ.', 'มี.ค.', 'เม.ย.',
    -    'พ.ค.', 'มิ.ย.', 'ก.ค.', 'ส.ค.', 'ก.ย.', 'ต.ค.',
    -    'พ.ย.', 'ธ.ค.'],
    -  WEEKDAYS: ['วันอาทิตย์', 'วันจันทร์',
    -    'วันอังคาร', 'วันพุธ',
    -    'วันพฤหัสบดี', 'วันศุกร์',
    -    'วันเสาร์'],
    -  STANDALONEWEEKDAYS: ['วันอาทิตย์',
    -    'วันจันทร์', 'วันอังคาร',
    -    'วันพุธ', 'วันพฤหัสบดี',
    -    'วันศุกร์', 'วันเสาร์'],
    -  SHORTWEEKDAYS: ['อา.', 'จ.', 'อ.', 'พ.', 'พฤ.', 'ศ.', 'ส.'],
    -  STANDALONESHORTWEEKDAYS: ['อา.', 'จ.', 'อ.', 'พ.', 'พฤ.',
    -    'ศ.', 'ส.'],
    -  NARROWWEEKDAYS: ['อา', 'จ', 'อ', 'พ', 'พฤ', 'ศ', 'ส'],
    -  STANDALONENARROWWEEKDAYS: ['อา', 'จ', 'อ', 'พ', 'พฤ', 'ศ',
    -    'ส'],
    -  SHORTQUARTERS: ['ไตรมาส 1', 'ไตรมาส 2',
    -    'ไตรมาส 3', 'ไตรมาส 4'],
    -  QUARTERS: ['ไตรมาส 1', 'ไตรมาส 2',
    -    'ไตรมาส 3', 'ไตรมาส 4'],
    -  AMPMS: ['ก่อนเที่ยง', 'หลังเที่ยง'],
    -  DATEFORMATS: ['EEEEที่ d MMMM G y', 'd MMMM G y', 'd MMM y', 'd/M/yy'],
    -  TIMEFORMATS: [
    -    'H นาฬิกา mm นาที ss วินาที zzzz',
    -    'H นาฬิกา mm นาที ss วินาที z', 'HH:mm:ss',
    -    'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ti.
    - */
    -goog.i18n.DateTimeSymbols_ti = {
    -  ERAS: ['ዓ/ዓ', 'ዓ/ም'],
    -  ERANAMES: ['ዓ/ዓ', 'ዓ/ም'],
    -  NARROWMONTHS: ['ጃ', 'ፌ', 'ማ', 'ኤ', 'ሜ', 'ጁ', 'ጁ', 'ኦ', 'ሴ',
    -    'ኦ', 'ኖ', 'ዲ'],
    -  STANDALONENARROWMONTHS: ['ጃ', 'ፌ', 'ማ', 'ኤ', 'ሜ', 'ጁ', 'ጁ',
    -    'ኦ', 'ሴ', 'ኦ', 'ኖ', 'ዲ'],
    -  MONTHS: ['ጃንዩወሪ', 'ፌብሩወሪ', 'ማርች', 'ኤፕረል',
    -    'ሜይ', 'ጁን', 'ጁላይ', 'ኦገስት', 'ሴፕቴምበር',
    -    'ኦክተውበር', 'ኖቬምበር', 'ዲሴምበር'],
    -  STANDALONEMONTHS: ['ጃንዩወሪ', 'ፌብሩወሪ', 'ማርች',
    -    'ኤፕረል', 'ሜይ', 'ጁን', 'ጁላይ', 'ኦገስት',
    -    'ሴፕቴምበር', 'ኦክተውበር', 'ኖቬምበር',
    -    'ዲሴምበር'],
    -  SHORTMONTHS: ['ጃንዩ', 'ፌብሩ', 'ማርች', 'ኤፕረ', 'ሜይ',
    -    'ጁን', 'ጁላይ', 'ኦገስ', 'ሴፕቴ', 'ኦክተ', 'ኖቬም',
    -    'ዲሴም'],
    -  STANDALONESHORTMONTHS: ['ጃንዩ', 'ፌብሩ', 'ማርች', 'ኤፕረ',
    -    'ሜይ', 'ጁን', 'ጁላይ', 'ኦገስ', 'ሴፕቴ', 'ኦክተ',
    -    'ኖቬም', 'ዲሴም'],
    -  WEEKDAYS: ['ሰንበት', 'ሰኑይ', 'ሠሉስ', 'ረቡዕ', 'ኃሙስ',
    -    'ዓርቢ', 'ቀዳም'],
    -  STANDALONEWEEKDAYS: ['ሰንበት', 'ሰኑይ', 'ሠሉስ', 'ረቡዕ',
    -    'ኃሙስ', 'ዓርቢ', 'ቀዳም'],
    -  SHORTWEEKDAYS: ['ሰንበት', 'ሰኑይ', 'ሠሉስ', 'ረቡዕ',
    -    'ኃሙስ', 'ዓርቢ', 'ቀዳም'],
    -  STANDALONESHORTWEEKDAYS: ['ሰንበት', 'ሰኑይ', 'ሠሉስ',
    -    'ረቡዕ', 'ኃሙስ', 'ዓርቢ', 'ቀዳም'],
    -  NARROWWEEKDAYS: ['ሰ', 'ሰ', 'ሠ', 'ረ', 'ኃ', 'ዓ', 'ቀ'],
    -  STANDALONENARROWWEEKDAYS: ['ሰ', 'ሰ', 'ሠ', 'ረ', 'ኃ', 'ዓ', 'ቀ'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['ንጉሆ ሰዓተ', 'ድሕር ሰዓት'],
    -  DATEFORMATS: ['EEEE፣ dd MMMM መዓልቲ y G', 'dd MMMM y', 'dd-MMM-y',
    -    'dd/MM/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ti_ER.
    - */
    -goog.i18n.DateTimeSymbols_ti_ER = {
    -  ERAS: ['ዓ/ዓ', 'ዓ/ም'],
    -  ERANAMES: ['ዓ/ዓ', 'ዓ/ም'],
    -  NARROWMONTHS: ['ጃ', 'ፌ', 'ማ', 'ኤ', 'ሜ', 'ጁ', 'ጁ', 'ኦ', 'ሴ',
    -    'ኦ', 'ኖ', 'ዲ'],
    -  STANDALONENARROWMONTHS: ['ጃ', 'ፌ', 'ማ', 'ኤ', 'ሜ', 'ጁ', 'ጁ',
    -    'ኦ', 'ሴ', 'ኦ', 'ኖ', 'ዲ'],
    -  MONTHS: ['ጥሪ', 'ለካቲት', 'መጋቢት', 'ሚያዝያ',
    -    'ግንቦት', 'ሰነ', 'ሓምለ', 'ነሓሰ', 'መስከረም',
    -    'ጥቅምቲ', 'ሕዳር', 'ታሕሳስ'],
    -  STANDALONEMONTHS: ['ጥሪ', 'ለካቲት', 'መጋቢት', 'ሚያዝያ',
    -    'ግንቦት', 'ሰነ', 'ሓምለ', 'ነሓሰ', 'መስከረም',
    -    'ጥቅምቲ', 'ሕዳር', 'ታሕሳስ'],
    -  SHORTMONTHS: ['ጥሪ', 'ለካቲ', 'መጋቢ', 'ሚያዝ', 'ግንቦ',
    -    'ሰነ', 'ሓምለ', 'ነሓሰ', 'መስከ', 'ጥቅም', 'ሕዳር',
    -    'ታሕሳ'],
    -  STANDALONESHORTMONTHS: ['ጥሪ', 'ለካቲ', 'መጋቢ', 'ሚያዝ',
    -    'ግንቦ', 'ሰነ', 'ሓምለ', 'ነሓሰ', 'መስከ', 'ጥቅም',
    -    'ሕዳር', 'ታሕሳ'],
    -  WEEKDAYS: ['ሰንበት', 'ሰኑይ', 'ሰሉስ', 'ረቡዕ', 'ሓሙስ',
    -    'ዓርቢ', 'ቀዳም'],
    -  STANDALONEWEEKDAYS: ['ሰንበት', 'ሰኑይ', 'ሰሉስ', 'ረቡዕ',
    -    'ሓሙስ', 'ዓርቢ', 'ቀዳም'],
    -  SHORTWEEKDAYS: ['ሰንበት', 'ሰኑይ', 'ሰሉስ', 'ረቡዕ',
    -    'ሓሙስ', 'ዓርቢ', 'ቀዳም'],
    -  STANDALONESHORTWEEKDAYS: ['ሰንበት', 'ሰኑይ', 'ሰሉስ',
    -    'ረቡዕ', 'ሓሙስ', 'ዓርቢ', 'ቀዳም'],
    -  NARROWWEEKDAYS: ['ሰ', 'ሰ', 'ሠ', 'ረ', 'ኃ', 'ዓ', 'ቀ'],
    -  STANDALONENARROWWEEKDAYS: ['ሰ', 'ሰ', 'ሠ', 'ረ', 'ኃ', 'ዓ', 'ቀ'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['ንጉሆ ሰዓተ', 'ድሕር ሰዓት'],
    -  DATEFORMATS: ['EEEE፡ dd MMMM መዓልቲ y G', 'dd MMMM y', 'dd-MMM-y',
    -    'dd/MM/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ti_ET.
    - */
    -goog.i18n.DateTimeSymbols_ti_ET = goog.i18n.DateTimeSymbols_ti;
    -
    -
    -/**
    - * Date/time formatting symbols for locale tn.
    - */
    -goog.i18n.DateTimeSymbols_tn = {
    -  ERAS: ['BCE', 'CE'],
    -  ERANAMES: ['BCE', 'CE'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['Ferikgong', 'Tlhakole', 'Mopitlo', 'Moranang', 'Motsheganang',
    -    'Seetebosigo', 'Phukwi', 'Phatwe', 'Lwetse', 'Diphalane', 'Ngwanatsele',
    -    'Sedimonthole'],
    -  STANDALONEMONTHS: ['Ferikgong', 'Tlhakole', 'Mopitlo', 'Moranang',
    -    'Motsheganang', 'Seetebosigo', 'Phukwi', 'Phatwe', 'Lwetse', 'Diphalane',
    -    'Ngwanatsele', 'Sedimonthole'],
    -  SHORTMONTHS: ['Fer', 'Tlh', 'Mop', 'Mor', 'Mot', 'See', 'Phu', 'Pha', 'Lwe',
    -    'Dip', 'Ngw', 'Sed'],
    -  STANDALONESHORTMONTHS: ['Fer', 'Tlh', 'Mop', 'Mor', 'Mot', 'See', 'Phu',
    -    'Pha', 'Lwe', 'Dip', 'Ngw', 'Sed'],
    -  WEEKDAYS: ['Tshipi', 'Mosopulogo', 'Labobedi', 'Laboraro', 'Labone',
    -    'Labotlhano', 'Matlhatso'],
    -  STANDALONEWEEKDAYS: ['Tshipi', 'Mosopulogo', 'Labobedi', 'Laboraro', 'Labone',
    -    'Labotlhano', 'Matlhatso'],
    -  SHORTWEEKDAYS: ['Tsh', 'Mos', 'Bed', 'Rar', 'Ne', 'Tla', 'Mat'],
    -  STANDALONESHORTWEEKDAYS: ['Tsh', 'Mos', 'Bed', 'Rar', 'Ne', 'Tla', 'Mat'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['y MMMM d, EEEE', 'y MMMM d', 'y MMM d', 'y-MM-dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale tn_BW.
    - */
    -goog.i18n.DateTimeSymbols_tn_BW = goog.i18n.DateTimeSymbols_tn;
    -
    -
    -/**
    - * Date/time formatting symbols for locale tn_ZA.
    - */
    -goog.i18n.DateTimeSymbols_tn_ZA = goog.i18n.DateTimeSymbols_tn;
    -
    -
    -/**
    - * Date/time formatting symbols for locale to.
    - */
    -goog.i18n.DateTimeSymbols_to = {
    -  ERAS: ['KM', 'TS'],
    -  ERANAMES: ['ki muʻa', 'taʻu ʻo Sīsū'],
    -  NARROWMONTHS: ['S', 'F', 'M', 'E', 'M', 'S', 'S', 'A', 'S', 'O', 'N', 'T'],
    -  STANDALONENARROWMONTHS: ['S', 'F', 'M', 'E', 'M', 'S', 'S', 'A', 'S', 'O',
    -    'N', 'T'],
    -  MONTHS: ['Sānuali', 'Fēpueli', 'Maʻasi', 'ʻEpeleli', 'Mē', 'Sune',
    -    'Siulai', 'ʻAokosi', 'Sepitema', 'ʻOkatopa', 'Nōvema', 'Tīsema'],
    -  STANDALONEMONTHS: ['Sānuali', 'Fēpueli', 'Maʻasi', 'ʻEpeleli', 'Mē',
    -    'Sune', 'Siulai', 'ʻAokosi', 'Sepitema', 'ʻOkatopa', 'Nōvema',
    -    'Tīsema'],
    -  SHORTMONTHS: ['Sān', 'Fēp', 'Maʻa', 'ʻEpe', 'Mē', 'Sun', 'Siu', 'ʻAok',
    -    'Sep', 'ʻOka', 'Nōv', 'Tīs'],
    -  STANDALONESHORTMONTHS: ['Sān', 'Fēp', 'Maʻa', 'ʻEpe', 'Mē', 'Sun', 'Siu',
    -    'ʻAok', 'Sep', 'ʻOka', 'Nōv', 'Tīs'],
    -  WEEKDAYS: ['Sāpate', 'Mōnite', 'Tūsite', 'Pulelulu', 'Tuʻapulelulu',
    -    'Falaite', 'Tokonaki'],
    -  STANDALONEWEEKDAYS: ['Sāpate', 'Mōnite', 'Tūsite', 'Pulelulu',
    -    'Tuʻapulelulu', 'Falaite', 'Tokonaki'],
    -  SHORTWEEKDAYS: ['Sāp', 'Mōn', 'Tūs', 'Pul', 'Tuʻa', 'Fal', 'Tok'],
    -  STANDALONESHORTWEEKDAYS: ['Sāp', 'Mōn', 'Tūs', 'Pul', 'Tuʻa', 'Fal',
    -    'Tok'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'P', 'T', 'F', 'T'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'P', 'T', 'F', 'T'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['kuata ʻuluaki', 'kuata ua', 'kuata tolu', 'kuata fā'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1}, {0}', '{1}, {0}', '{1}, {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale to_TO.
    - */
    -goog.i18n.DateTimeSymbols_to_TO = goog.i18n.DateTimeSymbols_to;
    -
    -
    -/**
    - * Date/time formatting symbols for locale tr_CY.
    - */
    -goog.i18n.DateTimeSymbols_tr_CY = {
    -  ERAS: ['MÖ', 'MS'],
    -  ERANAMES: ['Milattan Önce', 'Milattan Sonra'],
    -  NARROWMONTHS: ['O', 'Ş', 'M', 'N', 'M', 'H', 'T', 'A', 'E', 'E', 'K', 'A'],
    -  STANDALONENARROWMONTHS: ['O', 'Ş', 'M', 'N', 'M', 'H', 'T', 'A', 'E', 'E',
    -    'K', 'A'],
    -  MONTHS: ['Ocak', 'Şubat', 'Mart', 'Nisan', 'Mayıs', 'Haziran', 'Temmuz',
    -    'Ağustos', 'Eylül', 'Ekim', 'Kasım', 'Aralık'],
    -  STANDALONEMONTHS: ['Ocak', 'Şubat', 'Mart', 'Nisan', 'Mayıs', 'Haziran',
    -    'Temmuz', 'Ağustos', 'Eylül', 'Ekim', 'Kasım', 'Aralık'],
    -  SHORTMONTHS: ['Oca', 'Şub', 'Mar', 'Nis', 'May', 'Haz', 'Tem', 'Ağu', 'Eyl',
    -    'Eki', 'Kas', 'Ara'],
    -  STANDALONESHORTMONTHS: ['Oca', 'Şub', 'Mar', 'Nis', 'May', 'Haz', 'Tem',
    -    'Ağu', 'Eyl', 'Eki', 'Kas', 'Ara'],
    -  WEEKDAYS: ['Pazar', 'Pazartesi', 'Salı', 'Çarşamba', 'Perşembe', 'Cuma',
    -    'Cumartesi'],
    -  STANDALONEWEEKDAYS: ['Pazar', 'Pazartesi', 'Salı', 'Çarşamba', 'Perşembe',
    -    'Cuma', 'Cumartesi'],
    -  SHORTWEEKDAYS: ['Paz', 'Pzt', 'Sal', 'Çar', 'Per', 'Cum', 'Cmt'],
    -  STANDALONESHORTWEEKDAYS: ['Paz', 'Pzt', 'Sal', 'Çar', 'Per', 'Cum', 'Cmt'],
    -  NARROWWEEKDAYS: ['P', 'P', 'S', 'Ç', 'P', 'C', 'C'],
    -  STANDALONENARROWWEEKDAYS: ['P', 'P', 'S', 'Ç', 'P', 'C', 'C'],
    -  SHORTQUARTERS: ['Ç1', 'Ç2', 'Ç3', 'Ç4'],
    -  QUARTERS: ['1. çeyrek', '2. çeyrek', '3. çeyrek', '4. çeyrek'],
    -  AMPMS: ['ÖÖ', 'ÖS'],
    -  DATEFORMATS: ['d MMMM y EEEE', 'd MMMM y', 'd MMM y', 'd MM y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale tr_TR.
    - */
    -goog.i18n.DateTimeSymbols_tr_TR = {
    -  ERAS: ['MÖ', 'MS'],
    -  ERANAMES: ['Milattan Önce', 'Milattan Sonra'],
    -  NARROWMONTHS: ['O', 'Ş', 'M', 'N', 'M', 'H', 'T', 'A', 'E', 'E', 'K', 'A'],
    -  STANDALONENARROWMONTHS: ['O', 'Ş', 'M', 'N', 'M', 'H', 'T', 'A', 'E', 'E',
    -    'K', 'A'],
    -  MONTHS: ['Ocak', 'Şubat', 'Mart', 'Nisan', 'Mayıs', 'Haziran', 'Temmuz',
    -    'Ağustos', 'Eylül', 'Ekim', 'Kasım', 'Aralık'],
    -  STANDALONEMONTHS: ['Ocak', 'Şubat', 'Mart', 'Nisan', 'Mayıs', 'Haziran',
    -    'Temmuz', 'Ağustos', 'Eylül', 'Ekim', 'Kasım', 'Aralık'],
    -  SHORTMONTHS: ['Oca', 'Şub', 'Mar', 'Nis', 'May', 'Haz', 'Tem', 'Ağu', 'Eyl',
    -    'Eki', 'Kas', 'Ara'],
    -  STANDALONESHORTMONTHS: ['Oca', 'Şub', 'Mar', 'Nis', 'May', 'Haz', 'Tem',
    -    'Ağu', 'Eyl', 'Eki', 'Kas', 'Ara'],
    -  WEEKDAYS: ['Pazar', 'Pazartesi', 'Salı', 'Çarşamba', 'Perşembe', 'Cuma',
    -    'Cumartesi'],
    -  STANDALONEWEEKDAYS: ['Pazar', 'Pazartesi', 'Salı', 'Çarşamba', 'Perşembe',
    -    'Cuma', 'Cumartesi'],
    -  SHORTWEEKDAYS: ['Paz', 'Pzt', 'Sal', 'Çar', 'Per', 'Cum', 'Cmt'],
    -  STANDALONESHORTWEEKDAYS: ['Paz', 'Pzt', 'Sal', 'Çar', 'Per', 'Cum', 'Cmt'],
    -  NARROWWEEKDAYS: ['P', 'P', 'S', 'Ç', 'P', 'C', 'C'],
    -  STANDALONENARROWWEEKDAYS: ['P', 'P', 'S', 'Ç', 'P', 'C', 'C'],
    -  SHORTQUARTERS: ['Ç1', 'Ç2', 'Ç3', 'Ç4'],
    -  QUARTERS: ['1. çeyrek', '2. çeyrek', '3. çeyrek', '4. çeyrek'],
    -  AMPMS: ['ÖÖ', 'ÖS'],
    -  DATEFORMATS: ['d MMMM y EEEE', 'd MMMM y', 'd MMM y', 'd MM y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ts.
    - */
    -goog.i18n.DateTimeSymbols_ts = {
    -  ERAS: ['BCE', 'CE'],
    -  ERANAMES: ['BCE', 'CE'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['Sunguti', 'Nyenyenyani', 'Nyenyankulu', 'Dzivamisoko', 'Mudyaxihi',
    -    'Khotavuxika', 'Mawuwani', 'Mhawuri', 'Ndzhati', 'Nhlangula', 'Hukuri',
    -    'N’wendzamhala'],
    -  STANDALONEMONTHS: ['Sunguti', 'Nyenyenyani', 'Nyenyankulu', 'Dzivamisoko',
    -    'Mudyaxihi', 'Khotavuxika', 'Mawuwani', 'Mhawuri', 'Ndzhati', 'Nhlangula',
    -    'Hukuri', 'N’wendzamhala'],
    -  SHORTMONTHS: ['Sun', 'Yan', 'Kul', 'Dzi', 'Mud', 'Kho', 'Maw', 'Mha', 'Ndz',
    -    'Nhl', 'Huk', 'N’w'],
    -  STANDALONESHORTMONTHS: ['Sun', 'Yan', 'Kul', 'Dzi', 'Mud', 'Kho', 'Maw',
    -    'Mha', 'Ndz', 'Nhl', 'Huk', 'N’w'],
    -  WEEKDAYS: ['Sonto', 'Musumbhunuku', 'Ravumbirhi', 'Ravunharhu', 'Ravumune',
    -    'Ravuntlhanu', 'Mugqivela'],
    -  STANDALONEWEEKDAYS: ['Sonto', 'Musumbhunuku', 'Ravumbirhi', 'Ravunharhu',
    -    'Ravumune', 'Ravuntlhanu', 'Mugqivela'],
    -  SHORTWEEKDAYS: ['Son', 'Mus', 'Bir', 'Har', 'Ne', 'Tlh', 'Mug'],
    -  STANDALONESHORTWEEKDAYS: ['Son', 'Mus', 'Bir', 'Har', 'Ne', 'Tlh', 'Mug'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['Kotara yo sungula', 'Kotara ya vumbirhi', 'Kotara ya vunharhu',
    -    'Kotara ya vumune'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['y MMMM d, EEEE', 'y MMMM d', 'y MMM d', 'y-MM-dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ts_ZA.
    - */
    -goog.i18n.DateTimeSymbols_ts_ZA = goog.i18n.DateTimeSymbols_ts;
    -
    -
    -/**
    - * Date/time formatting symbols for locale twq.
    - */
    -goog.i18n.DateTimeSymbols_twq = {
    -  ERAS: ['IJ', 'IZ'],
    -  ERANAMES: ['Isaa jine', 'Isaa zamanoo'],
    -  NARROWMONTHS: ['Ž', 'F', 'M', 'A', 'M', 'Ž', 'Ž', 'U', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['Ž', 'F', 'M', 'A', 'M', 'Ž', 'Ž', 'U', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Žanwiye', 'Feewiriye', 'Marsi', 'Awiril', 'Me', 'Žuweŋ',
    -    'Žuyye', 'Ut', 'Sektanbur', 'Oktoobur', 'Noowanbur', 'Deesanbur'],
    -  STANDALONEMONTHS: ['Žanwiye', 'Feewiriye', 'Marsi', 'Awiril', 'Me',
    -    'Žuweŋ', 'Žuyye', 'Ut', 'Sektanbur', 'Oktoobur', 'Noowanbur',
    -    'Deesanbur'],
    -  SHORTMONTHS: ['Žan', 'Fee', 'Mar', 'Awi', 'Me', 'Žuw', 'Žuy', 'Ut', 'Sek',
    -    'Okt', 'Noo', 'Dee'],
    -  STANDALONESHORTMONTHS: ['Žan', 'Fee', 'Mar', 'Awi', 'Me', 'Žuw', 'Žuy',
    -    'Ut', 'Sek', 'Okt', 'Noo', 'Dee'],
    -  WEEKDAYS: ['Alhadi', 'Atinni', 'Atalaata', 'Alarba', 'Alhamiisa', 'Alzuma',
    -    'Asibti'],
    -  STANDALONEWEEKDAYS: ['Alhadi', 'Atinni', 'Atalaata', 'Alarba', 'Alhamiisa',
    -    'Alzuma', 'Asibti'],
    -  SHORTWEEKDAYS: ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alz', 'Asi'],
    -  STANDALONESHORTWEEKDAYS: ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alz', 'Asi'],
    -  NARROWWEEKDAYS: ['H', 'T', 'T', 'L', 'L', 'L', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['H', 'T', 'T', 'L', 'L', 'L', 'S'],
    -  SHORTQUARTERS: ['A1', 'A2', 'A3', 'A4'],
    -  QUARTERS: ['Arrubu 1', 'Arrubu 2', 'Arrubu 3', 'Arrubu 4'],
    -  AMPMS: ['Subbaahi', 'Zaarikay b'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale twq_NE.
    - */
    -goog.i18n.DateTimeSymbols_twq_NE = goog.i18n.DateTimeSymbols_twq;
    -
    -
    -/**
    - * Date/time formatting symbols for locale tzm.
    - */
    -goog.i18n.DateTimeSymbols_tzm = {
    -  ERAS: ['ZƐ', 'ḌƐ'],
    -  ERANAMES: ['Zdat Ɛisa (TAƔ)', 'Ḍeffir Ɛisa (TAƔ)'],
    -  NARROWMONTHS: ['Y', 'Y', 'M', 'I', 'M', 'Y', 'Y', 'Ɣ', 'C', 'K', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['Y', 'Y', 'M', 'I', 'M', 'Y', 'Y', 'Ɣ', 'C', 'K',
    -    'N', 'D'],
    -  MONTHS: ['Yennayer', 'Yebrayer', 'Mars', 'Ibrir', 'Mayyu', 'Yunyu', 'Yulyuz',
    -    'Ɣuct', 'Cutanbir', 'Kṭuber', 'Nwanbir', 'Dujanbir'],
    -  STANDALONEMONTHS: ['Yennayer', 'Yebrayer', 'Mars', 'Ibrir', 'Mayyu', 'Yunyu',
    -    'Yulyuz', 'Ɣuct', 'Cutanbir', 'Kṭuber', 'Nwanbir', 'Dujanbir'],
    -  SHORTMONTHS: ['Yen', 'Yeb', 'Mar', 'Ibr', 'May', 'Yun', 'Yul', 'Ɣuc', 'Cut',
    -    'Kṭu', 'Nwa', 'Duj'],
    -  STANDALONESHORTMONTHS: ['Yen', 'Yeb', 'Mar', 'Ibr', 'May', 'Yun', 'Yul',
    -    'Ɣuc', 'Cut', 'Kṭu', 'Nwa', 'Duj'],
    -  WEEKDAYS: ['Asamas', 'Aynas', 'Asinas', 'Akras', 'Akwas', 'Asimwas',
    -    'Asiḍyas'],
    -  STANDALONEWEEKDAYS: ['Asamas', 'Aynas', 'Asinas', 'Akras', 'Akwas', 'Asimwas',
    -    'Asiḍyas'],
    -  SHORTWEEKDAYS: ['Asa', 'Ayn', 'Asn', 'Akr', 'Akw', 'Asm', 'Asḍ'],
    -  STANDALONESHORTWEEKDAYS: ['Asa', 'Ayn', 'Asn', 'Akr', 'Akw', 'Asm', 'Asḍ'],
    -  NARROWWEEKDAYS: ['A', 'A', 'A', 'A', 'A', 'A', 'A'],
    -  STANDALONENARROWWEEKDAYS: ['A', 'A', 'A', 'A', 'A', 'A', 'A'],
    -  SHORTQUARTERS: ['IA1', 'IA2', 'IA3', 'IA4'],
    -  QUARTERS: ['Imir adamsan 1', 'Imir adamsan 2', 'Imir adamsan 3',
    -    'Imir adamsan 4'],
    -  AMPMS: ['Zdat azal', 'Ḍeffir aza'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 5,
    -  WEEKENDRANGE: [4, 5],
    -  FIRSTWEEKCUTOFFDAY: 4
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale tzm_Latn.
    - */
    -goog.i18n.DateTimeSymbols_tzm_Latn = goog.i18n.DateTimeSymbols_tzm;
    -
    -
    -/**
    - * Date/time formatting symbols for locale tzm_Latn_MA.
    - */
    -goog.i18n.DateTimeSymbols_tzm_Latn_MA = goog.i18n.DateTimeSymbols_tzm;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ug.
    - */
    -goog.i18n.DateTimeSymbols_ug = {
    -  ERAS: ['مىلادىيەدىن بۇرۇن', 'مىلادىيە'],
    -  ERANAMES: ['مىلادىيەدىن بۇرۇن', 'مىلادىيە'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['يانۋار', 'فېۋرال', 'مارت', 'ئاپرېل', 'ماي',
    -    'ئىيۇن', 'ئىيۇل', 'ئاۋغۇست', 'سېنتەبىر',
    -    'ئۆكتەبىر', 'بويابىر', 'دېكابىر'],
    -  STANDALONEMONTHS: ['يانۋار', 'فېۋرال', 'مارت', 'ئاپرېل',
    -    'ماي', 'ئىيۇن', 'ئىيۇل', 'ئاۋغۇست', 'سېنتەبىر',
    -    'ئۆكتەبىر', 'بويابىر', 'دېكابىر'],
    -  SHORTMONTHS: ['يانۋار', 'فېۋرال', 'مارت', 'ئاپرېل',
    -    'ماي', 'ئىيۇن', 'ئىيۇل', 'ئاۋغۇست', 'سېنتەبىر',
    -    'ئۆكتەبىر', 'نويابىر', 'دېكابىر'],
    -  STANDALONESHORTMONTHS: ['يانۋار', 'فېۋرال', 'مارت',
    -    'ئاپرېل', 'ماي', 'ئىيۇن', 'ئىيۇل', 'ئاۋغۇست',
    -    'سېنتەبىر', 'ئۆكتەبىر', 'نويابىر', 'دېكابىر'],
    -  WEEKDAYS: ['يەكشەنبە', 'دۈشەنبە', 'سەيشەنبە',
    -    'چارشەنبە', 'پەيشەنبە', 'جۈمە', 'شەنبە'],
    -  STANDALONEWEEKDAYS: ['يەكشەنبە', 'دۈشەنبە', 'سەيشەنبە',
    -    'چارشەنبە', 'پەيشەنبە', 'جۈمە', 'شەنبە'],
    -  SHORTWEEKDAYS: ['يە', 'دۈ', 'سە', 'چا', 'پە', 'چۈ', 'شە'],
    -  STANDALONESHORTWEEKDAYS: ['يە', 'دۈ', 'سە', 'چا', 'پە', 'چۈ',
    -    'شە'],
    -  NARROWWEEKDAYS: ['ي', 'د', 'س', 'چ', 'پ', 'ج', 'ش'],
    -  STANDALONENARROWWEEKDAYS: ['ي', 'د', 'س', 'چ', 'پ', 'ج', 'ش'],
    -  SHORTQUARTERS: ['بىرىنچى پەسىل', 'ئىككىنچى پەسىل',
    -    'ئۈچىنچى پەسىل', 'تۆتىنچى پەسىل'],
    -  QUARTERS: ['بىرىنچى پەسىل', 'ئىككىنچى پەسىل',
    -    'ئۈچىنچى پەسىل', 'تۆتىنچى پەسىل'],
    -  AMPMS: ['چۈشتىن بۇرۇن', 'چۈشتىن كېيىن'],
    -  DATEFORMATS: ['EEEE، MMMM d، y', 'MMMM d، y', 'MMM d، y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1}، {0}', '{1}، {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ug_Arab.
    - */
    -goog.i18n.DateTimeSymbols_ug_Arab = goog.i18n.DateTimeSymbols_ug;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ug_Arab_CN.
    - */
    -goog.i18n.DateTimeSymbols_ug_Arab_CN = goog.i18n.DateTimeSymbols_ug;
    -
    -
    -/**
    - * Date/time formatting symbols for locale uk_UA.
    - */
    -goog.i18n.DateTimeSymbols_uk_UA = {
    -  ERAS: ['до н.е.', 'н.е.'],
    -  ERANAMES: ['до нашої ери', 'нашої ери'],
    -  NARROWMONTHS: ['С', 'Л', 'Б', 'К', 'Т', 'Ч', 'Л', 'С', 'В', 'Ж',
    -    'Л', 'Г'],
    -  STANDALONENARROWMONTHS: ['С', 'Л', 'Б', 'К', 'Т', 'Ч', 'Л', 'С', 'В',
    -    'Ж', 'Л', 'Г'],
    -  MONTHS: ['січня', 'лютого', 'березня', 'квітня',
    -    'травня', 'червня', 'липня', 'серпня',
    -    'вересня', 'жовтня', 'листопада', 'грудня'],
    -  STANDALONEMONTHS: ['Січень', 'Лютий', 'Березень',
    -    'Квітень', 'Травень', 'Червень', 'Липень',
    -    'Серпень', 'Вересень', 'Жовтень', 'Листопад',
    -    'Грудень'],
    -  SHORTMONTHS: ['січ.', 'лют.', 'бер.', 'квіт.', 'трав.',
    -    'черв.', 'лип.', 'серп.', 'вер.', 'жовт.', 'лист.',
    -    'груд.'],
    -  STANDALONESHORTMONTHS: ['Січ', 'Лют', 'Бер', 'Кві', 'Тра',
    -    'Чер', 'Лип', 'Сер', 'Вер', 'Жов', 'Лис', 'Гру'],
    -  WEEKDAYS: ['неділя', 'понеділок', 'вівторок',
    -    'середа', 'четвер', 'пʼятниця', 'субота'],
    -  STANDALONEWEEKDAYS: ['Неділя', 'Понеділок', 'Вівторок',
    -    'Середа', 'Четвер', 'Пʼятниця', 'Субота'],
    -  SHORTWEEKDAYS: ['Нд', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'],
    -  STANDALONESHORTWEEKDAYS: ['Нд', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт',
    -    'Сб'],
    -  NARROWWEEKDAYS: ['Н', 'П', 'В', 'С', 'Ч', 'П', 'С'],
    -  STANDALONENARROWWEEKDAYS: ['Н', 'П', 'В', 'С', 'Ч', 'П', 'С'],
    -  SHORTQUARTERS: ['I кв.', 'II кв.', 'III кв.', 'IV кв.'],
    -  QUARTERS: ['I квартал', 'II квартал', 'III квартал',
    -    'IV квартал'],
    -  AMPMS: ['дп', 'пп'],
    -  DATEFORMATS: ['EEEE, d MMMM y \'р\'.', 'd MMMM y \'р\'.', 'd MMM y \'р\'.',
    -    'dd.MM.yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ur_IN.
    - */
    -goog.i18n.DateTimeSymbols_ur_IN = {
    -  ZERODIGIT: 0x06F0,
    -  ERAS: ['قبل مسیح', 'عیسوی'],
    -  ERANAMES: ['قبل مسیح', 'عیسوی'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئی',
    -    'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر',
    -    'نومبر', 'دسمبر'],
    -  STANDALONEMONTHS: ['جنوری', 'فروری', 'مارچ', 'اپریل',
    -    'مئی', 'جون', 'جولائی', 'اگست', 'ستمبر',
    -    'اکتوبر', 'نومبر', 'دسمبر'],
    -  SHORTMONTHS: ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئی',
    -    'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر',
    -    'نومبر', 'دسمبر'],
    -  STANDALONESHORTMONTHS: ['جنوری', 'فروری', 'مارچ', 'اپریل',
    -    'مئی', 'جون', 'جولائی', 'اگست', 'ستمبر',
    -    'اکتوبر', 'نومبر', 'دسمبر'],
    -  WEEKDAYS: ['اتوار', 'پیر', 'منگل', 'بدھ', 'جمعرات',
    -    'جمعہ', 'ہفتہ'],
    -  STANDALONEWEEKDAYS: ['اتوار', 'پیر', 'منگل', 'بدھ',
    -    'جمعرات', 'جمعہ', 'ہفتہ'],
    -  SHORTWEEKDAYS: ['اتوار', 'پیر', 'منگل', 'بدھ', 'جمعرات',
    -    'جمعہ', 'ہفتہ'],
    -  STANDALONESHORTWEEKDAYS: ['اتوار', 'پیر', 'منگل', 'بدھ',
    -    'جمعرات', 'جمعہ', 'ہفتہ'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['پہلی سہ ماہی', 'دوسری سہ ماہی',
    -    'تیسری سہ ماہی', 'چوتهی سہ ماہی'],
    -  AMPMS: ['قبل دوپہر', 'بعد دوپہر'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'd MMM، y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [6, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ur_PK.
    - */
    -goog.i18n.DateTimeSymbols_ur_PK = {
    -  ERAS: ['ق م', 'عیسوی سن'],
    -  ERANAMES: ['قبل مسیح', 'عیسوی سن'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئی',
    -    'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر',
    -    'نومبر', 'دسمبر'],
    -  STANDALONEMONTHS: ['جنوری', 'فروری', 'مارچ', 'اپریل',
    -    'مئی', 'جون', 'جولائی', 'اگست', 'ستمبر',
    -    'اکتوبر', 'نومبر', 'دسمبر'],
    -  SHORTMONTHS: ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئی',
    -    'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر',
    -    'نومبر', 'دسمبر'],
    -  STANDALONESHORTMONTHS: ['جنوری', 'فروری', 'مارچ', 'اپریل',
    -    'مئی', 'جون', 'جولائی', 'اگست', 'ستمبر',
    -    'اکتوبر', 'نومبر', 'دسمبر'],
    -  WEEKDAYS: ['اتوار', 'سوموار', 'منگل', 'بدھ', 'جمعرات',
    -    'جمعہ', 'ہفتہ'],
    -  STANDALONEWEEKDAYS: ['اتوار', 'سوموار', 'منگل', 'بدھ',
    -    'جمعرات', 'جمعہ', 'ہفتہ'],
    -  SHORTWEEKDAYS: ['اتوار', 'سوموار', 'منگل', 'بدھ',
    -    'جمعرات', 'جمعہ', 'ہفتہ'],
    -  STANDALONESHORTWEEKDAYS: ['اتوار', 'سوموار', 'منگل', 'بدھ',
    -    'جمعرات', 'جمعہ', 'ہفتہ'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['پہلی سہ ماہی', 'دوسری سہ ماہی',
    -    'تیسری سہ ماہی', 'چوتهی سہ ماہی'],
    -  QUARTERS: ['پہلی سہ ماہی', 'دوسری سہ ماہی',
    -    'تیسری سہ ماہی', 'چوتهی سہ ماہی'],
    -  AMPMS: ['قبل دوپہر', 'بعد دوپہر'],
    -  DATEFORMATS: ['EEEE، d MMMM، y', 'd MMMM، y', 'd MMM، y', 'd/M/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale uz_Arab.
    - */
    -goog.i18n.DateTimeSymbols_uz_Arab = {
    -  ZERODIGIT: 0x06F0,
    -  ERAS: ['ق.م.', 'م.'],
    -  ERANAMES: ['ق.م.', 'م.'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['جنوری', 'فبروری', 'مارچ', 'اپریل', 'می',
    -    'جون', 'جولای', 'اگست', 'سپتمبر', 'اکتوبر',
    -    'نومبر', 'دسمبر'],
    -  STANDALONEMONTHS: ['جنوری', 'فبروری', 'مارچ', 'اپریل',
    -    'می', 'جون', 'جولای', 'اگست', 'سپتمبر', 'اکتوبر',
    -    'نومبر', 'دسمبر'],
    -  SHORTMONTHS: ['جنو', 'فبر', 'مار', 'اپر', 'مـی', 'جون',
    -    'جول', 'اگس', 'سپت', 'اکت', 'نوم', 'دسم'],
    -  STANDALONESHORTMONTHS: ['جنو', 'فبر', 'مار', 'اپر', 'مـی',
    -    'جون', 'جول', 'اگس', 'سپت', 'اکت', 'نوم', 'دسم'],
    -  WEEKDAYS: ['یکشنبه', 'دوشنبه', 'سه‌شنبه',
    -    'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'],
    -  STANDALONEWEEKDAYS: ['یکشنبه', 'دوشنبه', 'سه‌شنبه',
    -    'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'],
    -  SHORTWEEKDAYS: ['ی.', 'د.', 'س.', 'چ.', 'پ.', 'ج.', 'ش.'],
    -  STANDALONESHORTWEEKDAYS: ['ی.', 'د.', 'س.', 'چ.', 'پ.', 'ج.', 'ش.'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['y نچی ییل d نچی MMMM EEEE کونی',
    -    'd نچی MMMM y', 'd MMM y', 'y/M/d'],
    -  TIMEFORMATS: ['H:mm:ss (zzzz)', 'H:mm:ss (z)', 'H:mm:ss', 'H:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 5,
    -  WEEKENDRANGE: [3, 4],
    -  FIRSTWEEKCUTOFFDAY: 4
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale uz_Arab_AF.
    - */
    -goog.i18n.DateTimeSymbols_uz_Arab_AF = goog.i18n.DateTimeSymbols_uz_Arab;
    -
    -
    -/**
    - * Date/time formatting symbols for locale uz_Cyrl.
    - */
    -goog.i18n.DateTimeSymbols_uz_Cyrl = {
    -  ERAS: ['М.А.', 'Э'],
    -  ERANAMES: ['М.А.', 'Э'],
    -  NARROWMONTHS: ['Я', 'Ф', 'М', 'А', 'М', 'И', 'И', 'А', 'С', 'О',
    -    'Н', 'Д'],
    -  STANDALONENARROWMONTHS: ['Я', 'Ф', 'М', 'А', 'М', 'И', 'И', 'А', 'С',
    -    'О', 'Н', 'Д'],
    -  MONTHS: ['Январ', 'Феврал', 'Март', 'Апрел', 'Май',
    -    'Июн', 'Июл', 'Август', 'Сентябр', 'Октябр',
    -    'Ноябр', 'Декабр'],
    -  STANDALONEMONTHS: ['Январ', 'Феврал', 'Март', 'Апрел',
    -    'Май', 'Июн', 'Июл', 'Август', 'Сентябр',
    -    'Октябр', 'Ноябр', 'Декабр'],
    -  SHORTMONTHS: ['Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн',
    -    'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'],
    -  STANDALONESHORTMONTHS: ['Янв', 'Фев', 'Мар', 'Апр', 'Май',
    -    'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'],
    -  WEEKDAYS: ['якшанба', 'душанба', 'сешанба',
    -    'чоршанба', 'пайшанба', 'жума', 'шанба'],
    -  STANDALONEWEEKDAYS: ['якшанба', 'душанба', 'сешанба',
    -    'чоршанба', 'пайшанба', 'жума', 'шанба'],
    -  SHORTWEEKDAYS: ['Якш', 'Душ', 'Сеш', 'Чор', 'Пай', 'Жум',
    -    'Шан'],
    -  STANDALONESHORTWEEKDAYS: ['Якш', 'Душ', 'Сеш', 'Чор', 'Пай',
    -    'Жум', 'Шан'],
    -  NARROWWEEKDAYS: ['Я', 'Д', 'С', 'Ч', 'П', 'Ж', 'Ш'],
    -  STANDALONENARROWWEEKDAYS: ['Я', 'Д', 'С', 'Ч', 'П', 'Ж', 'Ш'],
    -  SHORTQUARTERS: ['1-ч', '2-ч', '3-ч', '4-ч'],
    -  QUARTERS: ['1-чорак', '2-чорак', '3-чорак', '4-чорак'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, y MMMM dd', 'y MMMM d', 'y MMM d', 'yy/MM/dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale uz_Cyrl_UZ.
    - */
    -goog.i18n.DateTimeSymbols_uz_Cyrl_UZ = goog.i18n.DateTimeSymbols_uz_Cyrl;
    -
    -
    -/**
    - * Date/time formatting symbols for locale uz_Latn.
    - */
    -goog.i18n.DateTimeSymbols_uz_Latn = {
    -  ERAS: ['M.A.', 'E'],
    -  ERANAMES: ['M.A.', 'E'],
    -  NARROWMONTHS: ['Y', 'F', 'M', 'A', 'M', 'I', 'I', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['Y', 'F', 'M', 'A', 'M', 'I', 'I', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Yanvar', 'Fevral', 'Mart', 'Aprel', 'May', 'Iyun', 'Iyul', 'Avgust',
    -    'Sentabr', 'Oktabr', 'Noyabr', 'Dekabr'],
    -  STANDALONEMONTHS: ['Yanvar', 'Fevral', 'Mart', 'Aprel', 'May', 'Iyun', 'Iyul',
    -    'Avgust', 'Sentabr', 'Oktabr', 'Noyabr', 'Dekabr'],
    -  SHORTMONTHS: ['Yanv', 'Fev', 'Mar', 'Apr', 'May', 'Iyun', 'Iyul', 'Avg',
    -    'Sen', 'Okt', 'Noya', 'Dek'],
    -  STANDALONESHORTMONTHS: ['Yanv', 'Fev', 'Mar', 'Apr', 'May', 'Iyun', 'Iyul',
    -    'Avg', 'Sen', 'Okt', 'Noya', 'Dek'],
    -  WEEKDAYS: ['yakshanba', 'dushanba', 'seshanba', 'chorshanba', 'payshanba',
    -    'juma', 'shanba'],
    -  STANDALONEWEEKDAYS: ['yakshanba', 'dushanba', 'seshanba', 'chorshanba',
    -    'payshanba', 'juma', 'shanba'],
    -  SHORTWEEKDAYS: ['Yaksh', 'Dush', 'Sesh', 'Chor', 'Pay', 'Jum', 'Shan'],
    -  STANDALONESHORTWEEKDAYS: ['Yaksh', 'Dush', 'Sesh', 'Chor', 'Pay', 'Jum',
    -    'Shan'],
    -  NARROWWEEKDAYS: ['Y', 'D', 'S', 'C', 'P', 'J', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['Y', 'D', 'S', 'C', 'P', 'J', 'S'],
    -  SHORTQUARTERS: ['1-ch', '2-ch', '3-ch', '4-ch'],
    -  QUARTERS: ['1-chorak', '2-chorak', '3-chorak', '4-chorak'],
    -  AMPMS: ['TO', 'TK'],
    -  DATEFORMATS: ['EEEE, y MMMM dd', 'y MMMM d', 'y MMM d', 'yy/MM/dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale uz_Latn_UZ.
    - */
    -goog.i18n.DateTimeSymbols_uz_Latn_UZ = goog.i18n.DateTimeSymbols_uz_Latn;
    -
    -
    -/**
    - * Date/time formatting symbols for locale vai.
    - */
    -goog.i18n.DateTimeSymbols_vai = {
    -  ERAS: ['BCE', 'CE'],
    -  ERANAMES: ['BCE', 'CE'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['ꖨꕪꖃ ꔞꕮ', 'ꕒꕡꖝꖕ', 'ꕾꖺ', 'ꖢꖕ', 'ꖑꕱ',
    -    '6', '7', 'ꗛꔕ', 'ꕢꕌ', 'ꕭꖃ', 'ꔞꘋꕔꕿ ꕸꖃꗏ',
    -    'ꖨꕪꕱ ꗏꕮ'],
    -  STANDALONEMONTHS: ['ꖨꕪꖃ ꔞꕮ', 'ꕒꕡꖝꖕ', 'ꕾꖺ', 'ꖢꖕ',
    -    'ꖑꕱ', '6', '7', 'ꗛꔕ', 'ꕢꕌ', 'ꕭꖃ', 'ꔞꘋꕔꕿ ꕸꖃꗏ',
    -    'ꖨꕪꕱ ꗏꕮ'],
    -  SHORTMONTHS: ['ꖨꕪꖃ ꔞꕮ', 'ꕒꕡꖝꖕ', 'ꕾꖺ', 'ꖢꖕ',
    -    'ꖑꕱ', '6', '7', 'ꗛꔕ', 'ꕢꕌ', 'ꕭꖃ', 'ꔞꘋꕔꕿ ꕸꖃꗏ',
    -    'ꖨꕪꕱ ꗏꕮ'],
    -  STANDALONESHORTMONTHS: ['ꖨꕪꖃ ꔞꕮ', 'ꕒꕡꖝꖕ', 'ꕾꖺ',
    -    'ꖢꖕ', 'ꖑꕱ', '6', '7', 'ꗛꔕ', 'ꕢꕌ', 'ꕭꖃ',
    -    'ꔞꘋꕔꕿ ꕸꖃꗏ', 'ꖨꕪꕱ ꗏꕮ'],
    -  WEEKDAYS: ['ꕞꕌꔵ', 'ꗳꗡꘉ', 'ꕚꕞꕚ', 'ꕉꕞꕒ', 'ꕉꔤꕆꕢ',
    -    'ꕉꔤꕀꕮ', 'ꔻꔬꔳ'],
    -  STANDALONEWEEKDAYS: ['ꕞꕌꔵ', 'ꗳꗡꘉ', 'ꕚꕞꕚ', 'ꕉꕞꕒ',
    -    'ꕉꔤꕆꕢ', 'ꕉꔤꕀꕮ', 'ꔻꔬꔳ'],
    -  SHORTWEEKDAYS: ['ꕞꕌꔵ', 'ꗳꗡꘉ', 'ꕚꕞꕚ', 'ꕉꕞꕒ',
    -    'ꕉꔤꕆꕢ', 'ꕉꔤꕀꕮ', 'ꔻꔬꔳ'],
    -  STANDALONESHORTWEEKDAYS: ['ꕞꕌꔵ', 'ꗳꗡꘉ', 'ꕚꕞꕚ', 'ꕉꕞꕒ',
    -    'ꕉꔤꕆꕢ', 'ꕉꔤꕀꕮ', 'ꔻꔬꔳ'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale vai_Latn.
    - */
    -goog.i18n.DateTimeSymbols_vai_Latn = {
    -  ERAS: ['BCE', 'CE'],
    -  ERANAMES: ['BCE', 'CE'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['luukao kemã', 'ɓandaɓu', 'vɔɔ', 'fulu', 'goo', '6', '7',
    -    'kɔnde', 'saah', 'galo', 'kenpkato ɓololɔ', 'luukao lɔma'],
    -  STANDALONEMONTHS: ['luukao kemã', 'ɓandaɓu', 'vɔɔ', 'fulu', 'goo', '6',
    -    '7', 'kɔnde', 'saah', 'galo', 'kenpkato ɓololɔ', 'luukao lɔma'],
    -  SHORTMONTHS: ['luukao kemã', 'ɓandaɓu', 'vɔɔ', 'fulu', 'goo', '6', '7',
    -    'kɔnde', 'saah', 'galo', 'kenpkato ɓololɔ', 'luukao lɔma'],
    -  STANDALONESHORTMONTHS: ['luukao kemã', 'ɓandaɓu', 'vɔɔ', 'fulu', 'goo',
    -    '6', '7', 'kɔnde', 'saah', 'galo', 'kenpkato ɓololɔ', 'luukao lɔma'],
    -  WEEKDAYS: ['lahadi', 'tɛɛnɛɛ', 'talata', 'alaba', 'aimisa', 'aijima',
    -    'siɓiti'],
    -  STANDALONEWEEKDAYS: ['lahadi', 'tɛɛnɛɛ', 'talata', 'alaba', 'aimisa',
    -    'aijima', 'siɓiti'],
    -  SHORTWEEKDAYS: ['lahadi', 'tɛɛnɛɛ', 'talata', 'alaba', 'aimisa', 'aijima',
    -    'siɓiti'],
    -  STANDALONESHORTWEEKDAYS: ['lahadi', 'tɛɛnɛɛ', 'talata', 'alaba', 'aimisa',
    -    'aijima', 'siɓiti'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale vai_Latn_LR.
    - */
    -goog.i18n.DateTimeSymbols_vai_Latn_LR = goog.i18n.DateTimeSymbols_vai_Latn;
    -
    -
    -/**
    - * Date/time formatting symbols for locale vai_Vaii.
    - */
    -goog.i18n.DateTimeSymbols_vai_Vaii = goog.i18n.DateTimeSymbols_vai;
    -
    -
    -/**
    - * Date/time formatting symbols for locale vai_Vaii_LR.
    - */
    -goog.i18n.DateTimeSymbols_vai_Vaii_LR = goog.i18n.DateTimeSymbols_vai;
    -
    -
    -/**
    - * Date/time formatting symbols for locale ve.
    - */
    -goog.i18n.DateTimeSymbols_ve = {
    -  ERAS: ['BCE', 'CE'],
    -  ERANAMES: ['BCE', 'CE'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['Phando', 'Luhuhi', 'Ṱhafamuhwe', 'Lambamai', 'Shundunthule',
    -    'Fulwi', 'Fulwana', 'Ṱhangule', 'Khubvumedzi', 'Tshimedzi', 'Ḽara',
    -    'Nyendavhusiku'],
    -  STANDALONEMONTHS: ['Phando', 'Luhuhi', 'Ṱhafamuhwe', 'Lambamai',
    -    'Shundunthule', 'Fulwi', 'Fulwana', 'Ṱhangule', 'Khubvumedzi',
    -    'Tshimedzi', 'Ḽara', 'Nyendavhusiku'],
    -  SHORTMONTHS: ['Pha', 'Luh', 'Ṱhf', 'Lam', 'Shu', 'Lwi', 'Lwa', 'Ṱha',
    -    'Khu', 'Tsh', 'Ḽar', 'Nye'],
    -  STANDALONESHORTMONTHS: ['Pha', 'Luh', 'Ṱhf', 'Lam', 'Shu', 'Lwi', 'Lwa',
    -    'Ṱha', 'Khu', 'Tsh', 'Ḽar', 'Nye'],
    -  WEEKDAYS: ['Swondaha', 'Musumbuluwo', 'Ḽavhuvhili', 'Ḽavhuraru',
    -    'Ḽavhuṋa', 'Ḽavhuṱanu', 'Mugivhela'],
    -  STANDALONEWEEKDAYS: ['Swondaha', 'Musumbuluwo', 'Ḽavhuvhili', 'Ḽavhuraru',
    -    'Ḽavhuṋa', 'Ḽavhuṱanu', 'Mugivhela'],
    -  SHORTWEEKDAYS: ['Swo', 'Mus', 'Vhi', 'Rar', 'Ṋa', 'Ṱan', 'Mug'],
    -  STANDALONESHORTWEEKDAYS: ['Swo', 'Mus', 'Vhi', 'Rar', 'Ṋa', 'Ṱan', 'Mug'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['Kotara ya u thoma', 'Kotara ya vhuvhili', 'Kotara ya vhuraru',
    -    'Kotara ya vhuṋa'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['y MMMM d, EEEE', 'y MMMM d', 'y MMM d', 'y-MM-dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale ve_ZA.
    - */
    -goog.i18n.DateTimeSymbols_ve_ZA = goog.i18n.DateTimeSymbols_ve;
    -
    -
    -/**
    - * Date/time formatting symbols for locale vi_VN.
    - */
    -goog.i18n.DateTimeSymbols_vi_VN = {
    -  ERAS: ['tr. CN', 'sau CN'],
    -  ERANAMES: ['tr. CN', 'sau CN'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['tháng 1', 'tháng 2', 'tháng 3', 'tháng 4', 'tháng 5',
    -    'tháng 6', 'tháng 7', 'tháng 8', 'tháng 9', 'tháng 10', 'tháng 11',
    -    'tháng 12'],
    -  STANDALONEMONTHS: ['Tháng 1', 'Tháng 2', 'Tháng 3', 'Tháng 4', 'Tháng 5',
    -    'Tháng 6', 'Tháng 7', 'Tháng 8', 'Tháng 9', 'Tháng 10', 'Tháng 11',
    -    'Tháng 12'],
    -  SHORTMONTHS: ['thg 1', 'thg 2', 'thg 3', 'thg 4', 'thg 5', 'thg 6', 'thg 7',
    -    'thg 8', 'thg 9', 'thg 10', 'thg 11', 'thg 12'],
    -  STANDALONESHORTMONTHS: ['Thg 1', 'Thg 2', 'Thg 3', 'Thg 4', 'Thg 5', 'Thg 6',
    -    'Thg 7', 'Thg 8', 'Thg 9', 'Thg 10', 'Thg 11', 'Thg 12'],
    -  WEEKDAYS: ['Chủ Nhật', 'Thứ Hai', 'Thứ Ba', 'Thứ Tư', 'Thứ Năm',
    -    'Thứ Sáu', 'Thứ Bảy'],
    -  STANDALONEWEEKDAYS: ['Chủ Nhật', 'Thứ Hai', 'Thứ Ba', 'Thứ Tư',
    -    'Thứ Năm', 'Thứ Sáu', 'Thứ Bảy'],
    -  SHORTWEEKDAYS: ['CN', 'Th 2', 'Th 3', 'Th 4', 'Th 5', 'Th 6', 'Th 7'],
    -  STANDALONESHORTWEEKDAYS: ['CN', 'Th 2', 'Th 3', 'Th 4', 'Th 5', 'Th 6',
    -    'Th 7'],
    -  NARROWWEEKDAYS: ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'],
    -  STANDALONENARROWWEEKDAYS: ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Quý 1', 'Quý 2', 'Quý 3', 'Quý 4'],
    -  AMPMS: ['SA', 'CH'],
    -  DATEFORMATS: ['EEEE, \'ngày\' dd MMMM \'năm\' y',
    -    '\'Ngày\' dd \'tháng\' MM \'năm\' y', 'dd-MM-y', 'dd/MM/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{0} {1}', '{0} {1}', '{0} {1}', '{0} {1}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale vo.
    - */
    -goog.i18n.DateTimeSymbols_vo = {
    -  ERAS: ['b. t. kr.', 'p. t. kr.'],
    -  ERANAMES: ['b. t. kr.', 'p. t. kr.'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'P', 'M', 'Y', 'Y', 'G', 'S', 'T', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'P', 'M', 'Y', 'Y', 'G', 'S', 'T',
    -    'N', 'D'],
    -  MONTHS: ['janul', 'febul', 'mäzil', 'prilul', 'mayul', 'yunul', 'yulul',
    -    'gustul', 'setul', 'tobul', 'novul', 'dekul'],
    -  STANDALONEMONTHS: ['janul', 'febul', 'mäzil', 'prilul', 'mayul', 'yunul',
    -    'yulul', 'gustul', 'setul', 'tobul', 'novul', 'dekul'],
    -  SHORTMONTHS: ['jan', 'feb', 'mäz', 'prl', 'may', 'yun', 'yul', 'gst', 'set',
    -    'ton', 'nov', 'dek'],
    -  STANDALONESHORTMONTHS: ['jan', 'feb', 'mäz', 'prl', 'may', 'yun', 'yul',
    -    'gst', 'set', 'tob', 'nov', 'Dek'],
    -  WEEKDAYS: ['sudel', 'mudel', 'tudel', 'vedel', 'dödel', 'fridel', 'zädel'],
    -  STANDALONEWEEKDAYS: ['sudel', 'mudel', 'tudel', 'vedel', 'dödel', 'fridel',
    -    'zädel'],
    -  SHORTWEEKDAYS: ['su.', 'mu.', 'tu.', 've.', 'dö.', 'fr.', 'zä.'],
    -  STANDALONESHORTWEEKDAYS: ['Su', 'Mu', 'Tu', 'Ve', 'Dö', 'Fr', 'Zä'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'V', 'D', 'F', 'Z'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'V', 'D', 'F', 'Z'],
    -  SHORTQUARTERS: ['Yf1', 'Yf2', 'Yf3', 'Yf4'],
    -  QUARTERS: ['1id yelafoldil', '2id yelafoldil', '3id yelafoldil',
    -    '4id yelafoldil'],
    -  AMPMS: ['posz.', 'büz.'],
    -  DATEFORMATS: ['y MMMMa \'d\'. d\'id\'', 'y MMMM d', 'y MMM. d', 'y-MM-dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale vo_001.
    - */
    -goog.i18n.DateTimeSymbols_vo_001 = goog.i18n.DateTimeSymbols_vo;
    -
    -
    -/**
    - * Date/time formatting symbols for locale vun.
    - */
    -goog.i18n.DateTimeSymbols_vun = {
    -  ERAS: ['KK', 'BK'],
    -  ERANAMES: ['Kabla ya Kristu', 'Baada ya Kristu'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januari', 'Februari', 'Machi', 'Aprilyi', 'Mei', 'Junyi', 'Julyai',
    -    'Agusti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    -  STANDALONEMONTHS: ['Januari', 'Februari', 'Machi', 'Aprilyi', 'Mei', 'Junyi',
    -    'Julyai', 'Agusti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep',
    -    'Okt', 'Nov', 'Des'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul',
    -    'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
    -  WEEKDAYS: ['Jumapilyi', 'Jumatatuu', 'Jumanne', 'Jumatanu', 'Alhamisi',
    -    'Ijumaa', 'Jumamosi'],
    -  STANDALONEWEEKDAYS: ['Jumapilyi', 'Jumatatuu', 'Jumanne', 'Jumatanu',
    -    'Alhamisi', 'Ijumaa', 'Jumamosi'],
    -  SHORTWEEKDAYS: ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
    -  STANDALONESHORTWEEKDAYS: ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
    -  NARROWWEEKDAYS: ['J', 'J', 'J', 'J', 'A', 'I', 'J'],
    -  STANDALONENARROWWEEKDAYS: ['J', 'J', 'J', 'J', 'A', 'I', 'J'],
    -  SHORTQUARTERS: ['R1', 'R2', 'R3', 'R4'],
    -  QUARTERS: ['Robo 1', 'Robo 2', 'Robo 3', 'Robo 4'],
    -  AMPMS: ['utuko', 'kyiukonyi'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale vun_TZ.
    - */
    -goog.i18n.DateTimeSymbols_vun_TZ = goog.i18n.DateTimeSymbols_vun;
    -
    -
    -/**
    - * Date/time formatting symbols for locale wae.
    - */
    -goog.i18n.DateTimeSymbols_wae = {
    -  ERAS: ['v. Chr.', 'n. Chr'],
    -  ERANAMES: ['v. Chr.', 'n. Chr'],
    -  NARROWMONTHS: ['J', 'H', 'M', 'A', 'M', 'B', 'H', 'Ö', 'H', 'W', 'W', 'C'],
    -  STANDALONENARROWMONTHS: ['J', 'H', 'M', 'A', 'M', 'B', 'H', 'Ö', 'H', 'W',
    -    'W', 'C'],
    -  MONTHS: ['Jenner', 'Hornig', 'Märze', 'Abrille', 'Meije', 'Bráčet',
    -    'Heiwet', 'Öigšte', 'Herbštmánet', 'Wímánet', 'Wintermánet',
    -    'Chrištmánet'],
    -  STANDALONEMONTHS: ['Jenner', 'Hornig', 'Märze', 'Abrille', 'Meije',
    -    'Bráčet', 'Heiwet', 'Öigšte', 'Herbštmánet', 'Wímánet',
    -    'Wintermánet', 'Chrištmánet'],
    -  SHORTMONTHS: ['Jen', 'Hor', 'Mär', 'Abr', 'Mei', 'Brá', 'Hei', 'Öig',
    -    'Her', 'Wím', 'Win', 'Chr'],
    -  STANDALONESHORTMONTHS: ['Jen', 'Hor', 'Mär', 'Abr', 'Mei', 'Brá', 'Hei',
    -    'Öig', 'Her', 'Wím', 'Win', 'Chr'],
    -  WEEKDAYS: ['Sunntag', 'Mäntag', 'Zištag', 'Mittwuč', 'Fróntag', 'Fritag',
    -    'Samštag'],
    -  STANDALONEWEEKDAYS: ['Sunntag', 'Mäntag', 'Zištag', 'Mittwuč', 'Fróntag',
    -    'Fritag', 'Samštag'],
    -  SHORTWEEKDAYS: ['Sun', 'Män', 'Ziš', 'Mit', 'Fró', 'Fri', 'Sam'],
    -  STANDALONESHORTWEEKDAYS: ['Sun', 'Män', 'Ziš', 'Mit', 'Fró', 'Fri', 'Sam'],
    -  NARROWWEEKDAYS: ['S', 'M', 'Z', 'M', 'F', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'Z', 'M', 'F', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['1. quartal', '2. quartal', '3. quartal', '4. quartal'],
    -  AMPMS: ['AM', 'PM'],
    -  DATEFORMATS: ['EEEE, d. MMMM y', 'd. MMMM y', 'd. MMM y', 'y-MM-dd'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale wae_CH.
    - */
    -goog.i18n.DateTimeSymbols_wae_CH = goog.i18n.DateTimeSymbols_wae;
    -
    -
    -/**
    - * Date/time formatting symbols for locale xog.
    - */
    -goog.i18n.DateTimeSymbols_xog = {
    -  ERAS: ['AZ', 'AF'],
    -  ERANAMES: ['Kulisto nga azilawo', 'Kulisto nga affile'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Janwaliyo', 'Febwaliyo', 'Marisi', 'Apuli', 'Maayi', 'Juuni',
    -    'Julaayi', 'Agusito', 'Sebuttemba', 'Okitobba', 'Novemba', 'Desemba'],
    -  STANDALONEMONTHS: ['Janwaliyo', 'Febwaliyo', 'Marisi', 'Apuli', 'Maayi',
    -    'Juuni', 'Julaayi', 'Agusito', 'Sebuttemba', 'Okitobba', 'Novemba',
    -    'Desemba'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apu', 'Maa', 'Juu', 'Jul', 'Agu', 'Seb',
    -    'Oki', 'Nov', 'Des'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mar', 'Apu', 'Maa', 'Juu', 'Jul',
    -    'Agu', 'Seb', 'Oki', 'Nov', 'Des'],
    -  WEEKDAYS: ['Sabiiti', 'Balaza', 'Owokubili', 'Owokusatu', 'Olokuna',
    -    'Olokutaanu', 'Olomukaaga'],
    -  STANDALONEWEEKDAYS: ['Sabiiti', 'Balaza', 'Owokubili', 'Owokusatu', 'Olokuna',
    -    'Olokutaanu', 'Olomukaaga'],
    -  SHORTWEEKDAYS: ['Sabi', 'Bala', 'Kubi', 'Kusa', 'Kuna', 'Kuta', 'Muka'],
    -  STANDALONESHORTWEEKDAYS: ['Sabi', 'Bala', 'Kubi', 'Kusa', 'Kuna', 'Kuta',
    -    'Muka'],
    -  NARROWWEEKDAYS: ['S', 'B', 'B', 'S', 'K', 'K', 'M'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'B', 'B', 'S', 'K', 'K', 'M'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Ebisera ebyomwaka ebisoka', 'Ebisera ebyomwaka ebyokubiri',
    -    'Ebisera ebyomwaka ebyokusatu', 'Ebisera ebyomwaka ebyokuna'],
    -  AMPMS: ['Munkyo', 'Eigulo'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale xog_UG.
    - */
    -goog.i18n.DateTimeSymbols_xog_UG = goog.i18n.DateTimeSymbols_xog;
    -
    -
    -/**
    - * Date/time formatting symbols for locale yav.
    - */
    -goog.i18n.DateTimeSymbols_yav = {
    -  ERAS: ['k.Y.', '+J.C.'],
    -  ERANAMES: ['katikupíen Yésuse', 'ékélémkúnupíén n'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['pikítíkítie, oólí ú kutúan', 'siɛyɛ́, oóli ú kándíɛ',
    -    'ɔnsúmbɔl, oóli ú kátátúɛ', 'mesiŋ, oóli ú kénie',
    -    'ensil, oóli ú kátánuɛ', 'ɔsɔn', 'efute', 'pisuyú',
    -    'imɛŋ i puɔs', 'imɛŋ i putúk,oóli ú kátíɛ', 'makandikɛ',
    -    'pilɔndɔ́'],
    -  STANDALONEMONTHS: ['pikítíkítie, oólí ú kutúan',
    -    'siɛyɛ́, oóli ú kándíɛ', 'ɔnsúmbɔl, oóli ú kátátúɛ',
    -    'mesiŋ, oóli ú kénie', 'ensil, oóli ú kátánuɛ', 'ɔsɔn', 'efute',
    -    'pisuyú', 'imɛŋ i puɔs', 'imɛŋ i putúk,oóli ú kátíɛ',
    -    'makandikɛ', 'pilɔndɔ́'],
    -  SHORTMONTHS: ['o.1', 'o.2', 'o.3', 'o.4', 'o.5', 'o.6', 'o.7', 'o.8', 'o.9',
    -    'o.10', 'o.11', 'o.12'],
    -  STANDALONESHORTMONTHS: ['o.1', 'o.2', 'o.3', 'o.4', 'o.5', 'o.6', 'o.7',
    -    'o.8', 'o.9', 'o.10', 'o.11', 'o.12'],
    -  WEEKDAYS: ['sɔ́ndiɛ', 'móndie', 'muányáŋmóndie', 'metúkpíápɛ',
    -    'kúpélimetúkpiapɛ', 'feléte', 'séselé'],
    -  STANDALONEWEEKDAYS: ['sɔ́ndiɛ', 'móndie', 'muányáŋmóndie',
    -    'metúkpíápɛ', 'kúpélimetúkpiapɛ', 'feléte', 'séselé'],
    -  SHORTWEEKDAYS: ['sd', 'md', 'mw', 'et', 'kl', 'fl', 'ss'],
    -  STANDALONESHORTWEEKDAYS: ['sd', 'md', 'mw', 'et', 'kl', 'fl', 'ss'],
    -  NARROWWEEKDAYS: ['s', 'm', 'm', 'e', 'k', 'f', 's'],
    -  STANDALONENARROWWEEKDAYS: ['s', 'm', 'm', 'e', 'k', 'f', 's'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['ndátúɛ 1', 'ndátúɛ 2', 'ndátúɛ 3', 'ndátúɛ 4'],
    -  AMPMS: ['kiɛmɛ́ɛm', 'kisɛ́ndɛ'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale yav_CM.
    - */
    -goog.i18n.DateTimeSymbols_yav_CM = goog.i18n.DateTimeSymbols_yav;
    -
    -
    -/**
    - * Date/time formatting symbols for locale yi.
    - */
    -goog.i18n.DateTimeSymbols_yi = {
    -  ERAS: ['BCE', 'CE'],
    -  ERANAMES: ['BCE', 'CE'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['יאַנואַר', 'פֿעברואַר', 'מערץ',
    -    'אַפּריל', 'מיי', 'יוני', 'יולי', 'אויגוסט',
    -    'סעפּטעמבער', 'אקטאבער', 'נאוועמבער',
    -    'דעצעמבער'],
    -  STANDALONEMONTHS: ['יאַנואַר', 'פֿעברואַר', 'מערץ',
    -    'אַפּריל', 'מיי', 'יוני', 'יולי', 'אויגוסט',
    -    'סעפּטעמבער', 'אקטאבער', 'נאוועמבער',
    -    'דעצעמבער'],
    -  SHORTMONTHS: ['יאַנואַר', 'פֿעברואַר', 'מערץ',
    -    'אַפּריל', 'מיי', 'יוני', 'יולי', 'אויגוסט',
    -    'סעפּטעמבער', 'אקטאבער', 'נאוועמבער',
    -    'דעצעמבער'],
    -  STANDALONESHORTMONTHS: ['יאַנ', 'פֿעב', 'מערץ', 'אַפּר',
    -    'מיי', 'יוני', 'יולי', 'אויגוסט', 'סעפּ', 'אקט',
    -    'נאוו', 'דעצ'],
    -  WEEKDAYS: ['זונטיק', 'מאָנטיק', 'דינסטיק',
    -    'מיטוואך', 'דאנערשטיק', 'פֿרײַטיק', 'שבת'],
    -  STANDALONEWEEKDAYS: ['זונטיק', 'מאָנטיק', 'דינסטיק',
    -    'מיטוואך', 'דאנערשטיק', 'פֿרײַטיק', 'שבת'],
    -  SHORTWEEKDAYS: ['זונטיק', 'מאָנטיק', 'דינסטיק',
    -    'מיטוואך', 'דאנערשטיק', 'פֿרײַטיק', 'שבת'],
    -  STANDALONESHORTWEEKDAYS: ['זונטיק', 'מאָנטיק', 'דינסטיק',
    -    'מיטוואך', 'דאנערשטיק', 'פֿרײַטיק', 'שבת'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  AMPMS: ['פארמיטאג', 'נאכמיטאג'],
    -  DATEFORMATS: ['EEEE, dטן MMMM y', 'dטן MMMM y', 'dטן MMM y',
    -    'dd/MM/yy'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1}, {0}', '{1}, {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale yi_001.
    - */
    -goog.i18n.DateTimeSymbols_yi_001 = goog.i18n.DateTimeSymbols_yi;
    -
    -
    -/**
    - * Date/time formatting symbols for locale yo.
    - */
    -goog.i18n.DateTimeSymbols_yo = {
    -  ERAS: ['SK', 'LK'],
    -  ERANAMES: ['Saju Kristi', 'Lehin Kristi'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['Oṣù Ṣẹ́rẹ́', 'Oṣù Èrèlè', 'Oṣù Ẹrẹ̀nà',
    -    'Oṣù Ìgbé', 'Oṣù Ẹ̀bibi', 'Oṣù Òkúdu', 'Oṣù Agẹmọ',
    -    'Oṣù Ògún', 'Oṣù Owewe', 'Oṣù Ọ̀wàrà', 'Oṣù Bélú',
    -    'Oṣù Ọ̀pẹ̀'],
    -  STANDALONEMONTHS: ['Oṣù Ṣẹ́rẹ́', 'Oṣù Èrèlè',
    -    'Oṣù Ẹrẹ̀nà', 'Oṣù Ìgbé', 'Oṣù Ẹ̀bibi',
    -    'Oṣù Òkúdu', 'Oṣù Agẹmọ', 'Oṣù Ògún', 'Oṣù Owewe',
    -    'Oṣù Ọ̀wàrà', 'Oṣù Bélú', 'Oṣù Ọ̀pẹ̀'],
    -  SHORTMONTHS: ['Ṣẹ́rẹ́', 'Èrèlè', 'Ẹrẹ̀nà', 'Ìgbé',
    -    'Ẹ̀bibi', 'Òkúdu', 'Agẹmọ', 'Ògún', 'Owewe', 'Ọ̀wàrà',
    -    'Bélú', 'Ọ̀pẹ̀'],
    -  STANDALONESHORTMONTHS: ['Ṣẹ́rẹ́', 'Èrèlè', 'Ẹrẹ̀nà',
    -    'Ìgbé', 'Ẹ̀bibi', 'Òkúdu', 'Agẹmọ', 'Ògún', 'Owewe',
    -    'Ọ̀wàrà', 'Bélú', 'Ọ̀pẹ̀'],
    -  WEEKDAYS: ['Ọjọ́ Àìkú', 'Ọjọ́ Ajé', 'Ọjọ́ Ìsẹ́gun',
    -    'Ọjọ́rú', 'Ọjọ́bọ', 'Ọjọ́ Ẹtì',
    -    'Ọjọ́ Àbámẹ́ta'],
    -  STANDALONEWEEKDAYS: ['Ọjọ́ Àìkú', 'Ọjọ́ Ajé',
    -    'Ọjọ́ Ìsẹ́gun', 'Ọjọ́rú', 'Ọjọ́bọ',
    -    'Ọjọ́ Ẹtì', 'Ọjọ́ Àbámẹ́ta'],
    -  SHORTWEEKDAYS: ['Àìkú', 'Ajé', 'Ìsẹ́gun', 'Ọjọ́rú',
    -    'Ọjọ́bọ', 'Ẹtì', 'Àbámẹ́ta'],
    -  STANDALONESHORTWEEKDAYS: ['Àìkú', 'Ajé', 'Ìsẹ́gun', 'Ọjọ́rú',
    -    'Ọjọ́bọ', 'Ẹtì', 'Àbámẹ́ta'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['Kọ́tà Kínní', 'Kọ́tà Kejì', 'Kọ́à Keta',
    -    'Kọ́tà Kẹrin'],
    -  AMPMS: ['Àárọ̀', 'Ọ̀sán'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale yo_BJ.
    - */
    -goog.i18n.DateTimeSymbols_yo_BJ = {
    -  ERAS: ['SK', 'LK'],
    -  ERANAMES: ['Saju Kristi', 'Lehin Kristi'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['Oshù Shɛ́rɛ́', 'Oshù Èrèlè', 'Oshù Ɛrɛ̀nà',
    -    'Oshù Ìgbé', 'Oshù Ɛ̀bibi', 'Oshù Òkúdu', 'Oshù Agɛmɔ',
    -    'Oshù Ògún', 'Oshù Owewe', 'Oshù Ɔ̀wàrà', 'Oshù Bélú',
    -    'Oshù Ɔ̀pɛ̀'],
    -  STANDALONEMONTHS: ['Oshù Shɛ́rɛ́', 'Oshù Èrèlè', 'Oshù Ɛrɛ̀nà',
    -    'Oshù Ìgbé', 'Oshù Ɛ̀bibi', 'Oshù Òkúdu', 'Oshù Agɛmɔ',
    -    'Oshù Ògún', 'Oshù Owewe', 'Oshù Ɔ̀wàrà', 'Oshù Bélú',
    -    'Oshù Ɔ̀pɛ̀'],
    -  SHORTMONTHS: ['Shɛ́rɛ́', 'Èrèlè', 'Ɛrɛ̀nà', 'Ìgbé', 'Ɛ̀bibi',
    -    'Òkúdu', 'Agɛmɔ', 'Ògún', 'Owewe', 'Ɔ̀wàrà', 'Bélú',
    -    'Ɔ̀pɛ̀'],
    -  STANDALONESHORTMONTHS: ['Shɛ́rɛ́', 'Èrèlè', 'Ɛrɛ̀nà', 'Ìgbé',
    -    'Ɛ̀bibi', 'Òkúdu', 'Agɛmɔ', 'Ògún', 'Owewe', 'Ɔ̀wàrà', 'Bélú',
    -    'Ɔ̀pɛ̀'],
    -  WEEKDAYS: ['Ɔjɔ́ Àìkú', 'Ɔjɔ́ Ajé', 'Ɔjɔ́ Ìsɛ́gun',
    -    'Ɔjɔ́rú', 'Ɔjɔ́bɔ', 'Ɔjɔ́ Ɛtì', 'Ɔjɔ́ Àbámɛ́ta'],
    -  STANDALONEWEEKDAYS: ['Ɔjɔ́ Àìkú', 'Ɔjɔ́ Ajé', 'Ɔjɔ́ Ìsɛ́gun',
    -    'Ɔjɔ́rú', 'Ɔjɔ́bɔ', 'Ɔjɔ́ Ɛtì', 'Ɔjɔ́ Àbámɛ́ta'],
    -  SHORTWEEKDAYS: ['Àìkú', 'Ajé', 'Ìsɛ́gun', 'Ɔjɔ́rú', 'Ɔjɔ́bɔ',
    -    'Ɛtì', 'Àbámɛ́ta'],
    -  STANDALONESHORTWEEKDAYS: ['Àìkú', 'Ajé', 'Ìsɛ́gun', 'Ɔjɔ́rú',
    -    'Ɔjɔ́bɔ', 'Ɛtì', 'Àbámɛ́ta'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['K1', 'K2', 'K3', 'K4'],
    -  QUARTERS: ['Kɔ́tà Kínní', 'Kɔ́tà Kejì', 'Kɔ́à Keta',
    -    'Kɔ́tà Kɛrin'],
    -  AMPMS: ['Àárɔ̀', 'Ɔ̀sán'],
    -  DATEFORMATS: ['EEEE, d MMMM y', 'd MMMM y', 'd MMM y', 'dd/MM/y'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale yo_NG.
    - */
    -goog.i18n.DateTimeSymbols_yo_NG = goog.i18n.DateTimeSymbols_yo;
    -
    -
    -/**
    - * Date/time formatting symbols for locale zgh.
    - */
    -goog.i18n.DateTimeSymbols_zgh = {
    -  ERAS: ['ⴷⴰⵄ', 'ⴷⴼⵄ'],
    -  ERANAMES: ['ⴷⴰⵜ ⵏ ⵄⵉⵙⴰ', 'ⴷⴼⴼⵉⵔ ⵏ ⵄⵉⵙⴰ'],
    -  NARROWMONTHS: ['ⵉ', 'ⴱ', 'ⵎ', 'ⵉ', 'ⵎ', 'ⵢ', 'ⵢ', 'ⵖ', 'ⵛ',
    -    'ⴽ', 'ⵏ', 'ⴷ'],
    -  STANDALONENARROWMONTHS: ['ⵉ', 'ⴱ', 'ⵎ', 'ⵉ', 'ⵎ', 'ⵢ', 'ⵢ',
    -    'ⵖ', 'ⵛ', 'ⴽ', 'ⵏ', 'ⴷ'],
    -  MONTHS: ['ⵉⵏⵏⴰⵢⵔ', 'ⴱⵕⴰⵢⵕ', 'ⵎⴰⵕⵚ',
    -    'ⵉⴱⵔⵉⵔ', 'ⵎⴰⵢⵢⵓ', 'ⵢⵓⵏⵢⵓ',
    -    'ⵢⵓⵍⵢⵓⵣ', 'ⵖⵓⵛⵜ', 'ⵛⵓⵜⴰⵏⴱⵉⵔ',
    -    'ⴽⵜⵓⴱⵔ', 'ⵏⵓⵡⴰⵏⴱⵉⵔ', 'ⴷⵓⵊⴰⵏⴱⵉⵔ'],
    -  STANDALONEMONTHS: ['ⵉⵏⵏⴰⵢⵔ', 'ⴱⵕⴰⵢⵕ', 'ⵎⴰⵕⵚ',
    -    'ⵉⴱⵔⵉⵔ', 'ⵎⴰⵢⵢⵓ', 'ⵢⵓⵏⵢⵓ',
    -    'ⵢⵓⵍⵢⵓⵣ', 'ⵖⵓⵛⵜ', 'ⵛⵓⵜⴰⵏⴱⵉⵔ',
    -    'ⴽⵜⵓⴱⵔ', 'ⵏⵓⵡⴰⵏⴱⵉⵔ', 'ⴷⵓⵊⴰⵏⴱⵉⵔ'],
    -  SHORTMONTHS: ['ⵉⵏⵏ', 'ⴱⵕⴰ', 'ⵎⴰⵕ', 'ⵉⴱⵔ', 'ⵎⴰⵢ',
    -    'ⵢⵓⵏ', 'ⵢⵓⵍ', 'ⵖⵓⵛ', 'ⵛⵓⵜ', 'ⴽⵜⵓ',
    -    'ⵏⵓⵡ', 'ⴷⵓⵊ'],
    -  STANDALONESHORTMONTHS: ['ⵉⵏⵏ', 'ⴱⵕⴰ', 'ⵎⴰⵕ', 'ⵉⴱⵔ',
    -    'ⵎⴰⵢ', 'ⵢⵓⵏ', 'ⵢⵓⵍ', 'ⵖⵓⵛ', 'ⵛⵓⵜ',
    -    'ⴽⵜⵓ', 'ⵏⵓⵡ', 'ⴷⵓⵊ'],
    -  WEEKDAYS: ['ⴰⵙⴰⵎⴰⵙ', 'ⴰⵢⵏⴰⵙ', 'ⴰⵙⵉⵏⴰⵙ',
    -    'ⴰⴽⵕⴰⵙ', 'ⴰⴽⵡⴰⵙ', 'ⴰⵙⵉⵎⵡⴰⵙ',
    -    'ⴰⵙⵉⴹⵢⴰⵙ'],
    -  STANDALONEWEEKDAYS: ['ⴰⵙⴰⵎⴰⵙ', 'ⴰⵢⵏⴰⵙ',
    -    'ⴰⵙⵉⵏⴰⵙ', 'ⴰⴽⵕⴰⵙ', 'ⴰⴽⵡⴰⵙ',
    -    'ⴰⵙⵉⵎⵡⴰⵙ', 'ⴰⵙⵉⴹⵢⴰⵙ'],
    -  SHORTWEEKDAYS: ['ⴰⵙⴰ', 'ⴰⵢⵏ', 'ⴰⵙⵉ', 'ⴰⴽⵕ',
    -    'ⴰⴽⵡ', 'ⴰⵙⵉⵎ', 'ⴰⵙⵉⴹ'],
    -  STANDALONESHORTWEEKDAYS: ['ⴰⵙⴰ', 'ⴰⵢⵏ', 'ⴰⵙⵉ', 'ⴰⴽⵕ',
    -    'ⴰⴽⵡ', 'ⴰⵙⵉⵎ', 'ⴰⵙⵉⴹ'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    -  SHORTQUARTERS: ['ⴰⴽ 1', 'ⴰⴽ 2', 'ⴰⴽ 3', 'ⴰⴽ 4'],
    -  QUARTERS: ['ⴰⴽⵕⴰⴹⵢⵓⵔ 1', 'ⴰⴽⵕⴰⴹⵢⵓⵔ 2',
    -    'ⴰⴽⵕⴰⴹⵢⵓⵔ 3', 'ⴰⴽⵕⴰⴹⵢⵓⵔ 4'],
    -  AMPMS: ['ⵜⵉⴼⴰⵡⵜ', 'ⵜⴰⴷⴳⴳⵯⴰⵜ'],
    -  DATEFORMATS: ['EEEE d MMMM y', 'd MMMM y', 'd MMM, y', 'd/M/y'],
    -  TIMEFORMATS: ['HH:mm:ss zzzz', 'HH:mm:ss z', 'HH:mm:ss', 'HH:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 0,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 6
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale zgh_MA.
    - */
    -goog.i18n.DateTimeSymbols_zgh_MA = goog.i18n.DateTimeSymbols_zgh;
    -
    -
    -/**
    - * Date/time formatting symbols for locale zh_Hans.
    - */
    -goog.i18n.DateTimeSymbols_zh_Hans = {
    -  ERAS: ['公元前', '公元'],
    -  ERANAMES: ['公元前', '公元'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['一月', '二月', '三月', '四月', '五月', '六月', '七月',
    -    '八月', '九月', '十月', '十一月', '十二月'],
    -  STANDALONEMONTHS: ['一月', '二月', '三月', '四月', '五月', '六月',
    -    '七月', '八月', '九月', '十月', '十一月', '十二月'],
    -  SHORTMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月',
    -    '9月', '10月', '11月', '12月'],
    -  STANDALONESHORTMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月',
    -    '7月', '8月', '9月', '10月', '11月', '12月'],
    -  WEEKDAYS: ['星期日', '星期一', '星期二', '星期三', '星期四',
    -    '星期五', '星期六'],
    -  STANDALONEWEEKDAYS: ['星期日', '星期一', '星期二', '星期三',
    -    '星期四', '星期五', '星期六'],
    -  SHORTWEEKDAYS: ['周日', '周一', '周二', '周三', '周四', '周五',
    -    '周六'],
    -  STANDALONESHORTWEEKDAYS: ['周日', '周一', '周二', '周三', '周四',
    -    '周五', '周六'],
    -  NARROWWEEKDAYS: ['日', '一', '二', '三', '四', '五', '六'],
    -  STANDALONENARROWWEEKDAYS: ['日', '一', '二', '三', '四', '五', '六'],
    -  SHORTQUARTERS: ['1季度', '2季度', '3季度', '4季度'],
    -  QUARTERS: ['第一季度', '第二季度', '第三季度', '第四季度'],
    -  AMPMS: ['上午', '下午'],
    -  DATEFORMATS: ['y年M月d日EEEE', 'y年M月d日', 'y年M月d日', 'yy/M/d'],
    -  TIMEFORMATS: ['zzzzah:mm:ss', 'zah:mm:ss', 'ah:mm:ss', 'ah:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale zh_Hans_CN.
    - */
    -goog.i18n.DateTimeSymbols_zh_Hans_CN = goog.i18n.DateTimeSymbols_zh_Hans;
    -
    -
    -/**
    - * Date/time formatting symbols for locale zh_Hans_HK.
    - */
    -goog.i18n.DateTimeSymbols_zh_Hans_HK = {
    -  ERAS: ['公元前', '公元'],
    -  ERANAMES: ['公元前', '公元'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['一月', '二月', '三月', '四月', '五月', '六月', '七月',
    -    '八月', '九月', '十月', '十一月', '十二月'],
    -  STANDALONEMONTHS: ['一月', '二月', '三月', '四月', '五月', '六月',
    -    '七月', '八月', '九月', '十月', '十一月', '十二月'],
    -  SHORTMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月',
    -    '9月', '10月', '11月', '12月'],
    -  STANDALONESHORTMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月',
    -    '7月', '8月', '9月', '10月', '11月', '12月'],
    -  WEEKDAYS: ['星期日', '星期一', '星期二', '星期三', '星期四',
    -    '星期五', '星期六'],
    -  STANDALONEWEEKDAYS: ['星期日', '星期一', '星期二', '星期三',
    -    '星期四', '星期五', '星期六'],
    -  SHORTWEEKDAYS: ['周日', '周一', '周二', '周三', '周四', '周五',
    -    '周六'],
    -  STANDALONESHORTWEEKDAYS: ['周日', '周一', '周二', '周三', '周四',
    -    '周五', '周六'],
    -  NARROWWEEKDAYS: ['日', '一', '二', '三', '四', '五', '六'],
    -  STANDALONENARROWWEEKDAYS: ['日', '一', '二', '三', '四', '五', '六'],
    -  SHORTQUARTERS: ['1季度', '2季度', '3季度', '4季度'],
    -  QUARTERS: ['第一季度', '第二季度', '第三季度', '第四季度'],
    -  AMPMS: ['上午', '下午'],
    -  DATEFORMATS: ['y年M月d日EEEE', 'y年M月d日', 'y年M月d日', 'd/M/yy'],
    -  TIMEFORMATS: ['zzzzah:mm:ss', 'zah:mm:ss', 'ah:mm:ss', 'ah:mm'],
    -  DATETIMEFORMATS: ['{1}{0}', '{1}{0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale zh_Hans_MO.
    - */
    -goog.i18n.DateTimeSymbols_zh_Hans_MO = {
    -  ERAS: ['公元前', '公元'],
    -  ERANAMES: ['公元前', '公元'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['一月', '二月', '三月', '四月', '五月', '六月', '七月',
    -    '八月', '九月', '十月', '十一月', '十二月'],
    -  STANDALONEMONTHS: ['一月', '二月', '三月', '四月', '五月', '六月',
    -    '七月', '八月', '九月', '十月', '十一月', '十二月'],
    -  SHORTMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月',
    -    '9月', '10月', '11月', '12月'],
    -  STANDALONESHORTMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月',
    -    '7月', '8月', '9月', '10月', '11月', '12月'],
    -  WEEKDAYS: ['星期日', '星期一', '星期二', '星期三', '星期四',
    -    '星期五', '星期六'],
    -  STANDALONEWEEKDAYS: ['星期日', '星期一', '星期二', '星期三',
    -    '星期四', '星期五', '星期六'],
    -  SHORTWEEKDAYS: ['周日', '周一', '周二', '周三', '周四', '周五',
    -    '周六'],
    -  STANDALONESHORTWEEKDAYS: ['周日', '周一', '周二', '周三', '周四',
    -    '周五', '周六'],
    -  NARROWWEEKDAYS: ['日', '一', '二', '三', '四', '五', '六'],
    -  STANDALONENARROWWEEKDAYS: ['日', '一', '二', '三', '四', '五', '六'],
    -  SHORTQUARTERS: ['1季度', '2季度', '3季度', '4季度'],
    -  QUARTERS: ['第一季度', '第二季度', '第三季度', '第四季度'],
    -  AMPMS: ['上午', '下午'],
    -  DATEFORMATS: ['y年M月d日EEEE', 'y年M月d日', 'y年M月d日', 'd/M/yy'],
    -  TIMEFORMATS: ['zzzzah:mm:ss', 'zah:mm:ss', 'ah:mm:ss', 'ah:mm'],
    -  DATETIMEFORMATS: ['{1}{0}', '{1}{0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale zh_Hans_SG.
    - */
    -goog.i18n.DateTimeSymbols_zh_Hans_SG = {
    -  ERAS: ['公元前', '公元'],
    -  ERANAMES: ['公元前', '公元'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['一月', '二月', '三月', '四月', '五月', '六月', '七月',
    -    '八月', '九月', '十月', '十一月', '十二月'],
    -  STANDALONEMONTHS: ['一月', '二月', '三月', '四月', '五月', '六月',
    -    '七月', '八月', '九月', '十月', '十一月', '十二月'],
    -  SHORTMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月',
    -    '9月', '10月', '11月', '12月'],
    -  STANDALONESHORTMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月',
    -    '7月', '8月', '9月', '10月', '11月', '12月'],
    -  WEEKDAYS: ['星期日', '星期一', '星期二', '星期三', '星期四',
    -    '星期五', '星期六'],
    -  STANDALONEWEEKDAYS: ['星期日', '星期一', '星期二', '星期三',
    -    '星期四', '星期五', '星期六'],
    -  SHORTWEEKDAYS: ['周日', '周一', '周二', '周三', '周四', '周五',
    -    '周六'],
    -  STANDALONESHORTWEEKDAYS: ['周日', '周一', '周二', '周三', '周四',
    -    '周五', '周六'],
    -  NARROWWEEKDAYS: ['日', '一', '二', '三', '四', '五', '六'],
    -  STANDALONENARROWWEEKDAYS: ['日', '一', '二', '三', '四', '五', '六'],
    -  SHORTQUARTERS: ['1季度', '2季度', '3季度', '4季度'],
    -  QUARTERS: ['第一季度', '第二季度', '第三季度', '第四季度'],
    -  AMPMS: ['上午', '下午'],
    -  DATEFORMATS: ['y年M月d日EEEE', 'y年M月d日', 'y年M月d日', 'dd/MM/yy'],
    -  TIMEFORMATS: ['zzzzah:mm:ss', 'ahh:mm:ssz', 'ah:mm:ss', 'ahh:mm'],
    -  DATETIMEFORMATS: ['{1}{0}', '{1}{0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale zh_Hant.
    - */
    -goog.i18n.DateTimeSymbols_zh_Hant = {
    -  ERAS: ['西元前', '西元'],
    -  ERANAMES: ['西元前', '西元'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月',
    -    '9月', '10月', '11月', '12月'],
    -  STANDALONEMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月', '7月',
    -    '8月', '9月', '10月', '11月', '12月'],
    -  SHORTMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月',
    -    '9月', '10月', '11月', '12月'],
    -  STANDALONESHORTMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月',
    -    '7月', '8月', '9月', '10月', '11月', '12月'],
    -  WEEKDAYS: ['星期日', '星期一', '星期二', '星期三', '星期四',
    -    '星期五', '星期六'],
    -  STANDALONEWEEKDAYS: ['星期日', '星期一', '星期二', '星期三',
    -    '星期四', '星期五', '星期六'],
    -  SHORTWEEKDAYS: ['週日', '週一', '週二', '週三', '週四', '週五',
    -    '週六'],
    -  STANDALONESHORTWEEKDAYS: ['週日', '週一', '週二', '週三', '週四',
    -    '週五', '週六'],
    -  NARROWWEEKDAYS: ['日', '一', '二', '三', '四', '五', '六'],
    -  STANDALONENARROWWEEKDAYS: ['日', '一', '二', '三', '四', '五', '六'],
    -  SHORTQUARTERS: ['1季', '2季', '3季', '4季'],
    -  QUARTERS: ['第1季', '第2季', '第3季', '第4季'],
    -  AMPMS: ['上午', '下午'],
    -  DATEFORMATS: ['y年M月d日 EEEE', 'y年M月d日', 'y年M月d日', 'y/M/d'],
    -  TIMEFORMATS: ['ah:mm:ss [zzzz]', 'ah:mm:ss [z]', 'ah:mm:ss', 'ah:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale zh_Hant_HK.
    - */
    -goog.i18n.DateTimeSymbols_zh_Hant_HK = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['公元前', '公元'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月',
    -    '9月', '10月', '11月', '12月'],
    -  STANDALONEMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月', '7月',
    -    '8月', '9月', '10月', '11月', '12月'],
    -  SHORTMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月',
    -    '9月', '10月', '11月', '12月'],
    -  STANDALONESHORTMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月',
    -    '7月', '8月', '9月', '10月', '11月', '12月'],
    -  WEEKDAYS: ['星期日', '星期一', '星期二', '星期三', '星期四',
    -    '星期五', '星期六'],
    -  STANDALONEWEEKDAYS: ['星期日', '星期一', '星期二', '星期三',
    -    '星期四', '星期五', '星期六'],
    -  SHORTWEEKDAYS: ['週日', '週一', '週二', '週三', '週四', '週五',
    -    '週六'],
    -  STANDALONESHORTWEEKDAYS: ['週日', '週一', '週二', '週三', '週四',
    -    '週五', '週六'],
    -  NARROWWEEKDAYS: ['日', '一', '二', '三', '四', '五', '六'],
    -  STANDALONENARROWWEEKDAYS: ['日', '一', '二', '三', '四', '五', '六'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['第1季', '第2季', '第3季', '第4季'],
    -  AMPMS: ['上午', '下午'],
    -  DATEFORMATS: ['y年M月d日EEEE', 'y年M月d日', 'y年M月d日', 'd/M/yy'],
    -  TIMEFORMATS: ['ah:mm:ss [zzzz]', 'ah:mm:ss [z]', 'ah:mm:ss', 'ah:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale zh_Hant_MO.
    - */
    -goog.i18n.DateTimeSymbols_zh_Hant_MO = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['公元前', '公元'],
    -  NARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
    -  STANDALONENARROWMONTHS: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
    -    '11', '12'],
    -  MONTHS: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月',
    -    '9月', '10月', '11月', '12月'],
    -  STANDALONEMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月', '7月',
    -    '8月', '9月', '10月', '11月', '12月'],
    -  SHORTMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月',
    -    '9月', '10月', '11月', '12月'],
    -  STANDALONESHORTMONTHS: ['1月', '2月', '3月', '4月', '5月', '6月',
    -    '7月', '8月', '9月', '10月', '11月', '12月'],
    -  WEEKDAYS: ['星期日', '星期一', '星期二', '星期三', '星期四',
    -    '星期五', '星期六'],
    -  STANDALONEWEEKDAYS: ['星期日', '星期一', '星期二', '星期三',
    -    '星期四', '星期五', '星期六'],
    -  SHORTWEEKDAYS: ['週日', '週一', '週二', '週三', '週四', '週五',
    -    '週六'],
    -  STANDALONESHORTWEEKDAYS: ['週日', '週一', '週二', '週三', '週四',
    -    '週五', '週六'],
    -  NARROWWEEKDAYS: ['日', '一', '二', '三', '四', '五', '六'],
    -  STANDALONENARROWWEEKDAYS: ['日', '一', '二', '三', '四', '五', '六'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['第1季', '第2季', '第3季', '第4季'],
    -  AMPMS: ['上午', '下午'],
    -  DATEFORMATS: ['y年MM月dd日EEEE', 'y年MM月dd日', 'y年M月d日',
    -    'yy年M月d日'],
    -  TIMEFORMATS: ['ah:mm:ss [zzzz]', 'ah:mm:ss [z]', 'ah:mm:ss', 'ah:mm'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Date/time formatting symbols for locale zh_Hant_TW.
    - */
    -goog.i18n.DateTimeSymbols_zh_Hant_TW = goog.i18n.DateTimeSymbols_zh_Hant;
    -
    -
    -/**
    - * Date/time formatting symbols for locale zu_ZA.
    - */
    -goog.i18n.DateTimeSymbols_zu_ZA = {
    -  ERAS: ['BC', 'AD'],
    -  ERANAMES: ['BC', 'AD'],
    -  NARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],
    -  STANDALONENARROWMONTHS: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O',
    -    'N', 'D'],
    -  MONTHS: ['Januwari', 'Februwari', 'Mashi', 'Apreli', 'Meyi', 'Juni', 'Julayi',
    -    'Agasti', 'Septhemba', 'Okthoba', 'Novemba', 'Disemba'],
    -  STANDALONEMONTHS: ['Januwari', 'Februwari', 'Mashi', 'Apreli', 'Meyi', 'Juni',
    -    'Julayi', 'Agasti', 'Septhemba', 'Okthoba', 'Novemba', 'Disemba'],
    -  SHORTMONTHS: ['Jan', 'Feb', 'Mas', 'Apr', 'Mey', 'Jun', 'Jul', 'Aga', 'Sep',
    -    'Okt', 'Nov', 'Dis'],
    -  STANDALONESHORTMONTHS: ['Jan', 'Feb', 'Mas', 'Apr', 'Mey', 'Jun', 'Jul',
    -    'Aga', 'Sep', 'Okt', 'Nov', 'Dis'],
    -  WEEKDAYS: ['Sonto', 'Msombuluko', 'Lwesibili', 'Lwesithathu', 'Lwesine',
    -    'Lwesihlanu', 'Mgqibelo'],
    -  STANDALONEWEEKDAYS: ['Sonto', 'Msombuluko', 'Lwesibili', 'Lwesithathu',
    -    'Lwesine', 'Lwesihlanu', 'Mgqibelo'],
    -  SHORTWEEKDAYS: ['Son', 'Mso', 'Bil', 'Tha', 'Sin', 'Hla', 'Mgq'],
    -  STANDALONESHORTWEEKDAYS: ['Son', 'Mso', 'Bil', 'Tha', 'Sin', 'Hla', 'Mgq'],
    -  NARROWWEEKDAYS: ['S', 'M', 'T', 'T', 'S', 'H', 'M'],
    -  STANDALONENARROWWEEKDAYS: ['S', 'M', 'B', 'T', 'S', 'H', 'M'],
    -  SHORTQUARTERS: ['Q1', 'Q2', 'Q3', 'Q4'],
    -  QUARTERS: ['ikota engu-1', 'ikota engu-2', 'ikota engu-3', 'ikota engu-4'],
    -  AMPMS: ['Ekuseni', 'Ntambama'],
    -  DATEFORMATS: ['EEEE, MMMM d, y', 'MMMM d, y', 'MMM d, y', 'M/d/yy'],
    -  TIMEFORMATS: ['h:mm:ss a zzzz', 'h:mm:ss a z', 'h:mm:ss a', 'h:mm a'],
    -  DATETIMEFORMATS: ['{1} {0}', '{1} {0}', '{1} {0}', '{1} {0}'],
    -  FIRSTDAYOFWEEK: 6,
    -  WEEKENDRANGE: [5, 6],
    -  FIRSTWEEKCUTOFFDAY: 5
    -};
    -
    -
    -/**
    - * Selected date/time formatting symbols by locale.
    - */
    -if (goog.LOCALE == 'aa') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_aa;
    -}
    -
    -if (goog.LOCALE == 'aa_DJ' || goog.LOCALE == 'aa-DJ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_aa_DJ;
    -}
    -
    -if (goog.LOCALE == 'aa_ER' || goog.LOCALE == 'aa-ER') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_aa;
    -}
    -
    -if (goog.LOCALE == 'aa_ET' || goog.LOCALE == 'aa-ET') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_aa;
    -}
    -
    -if (goog.LOCALE == 'af_NA' || goog.LOCALE == 'af-NA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_af_NA;
    -}
    -
    -if (goog.LOCALE == 'af_ZA' || goog.LOCALE == 'af-ZA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_af_ZA;
    -}
    -
    -if (goog.LOCALE == 'agq') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_agq;
    -}
    -
    -if (goog.LOCALE == 'agq_CM' || goog.LOCALE == 'agq-CM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_agq;
    -}
    -
    -if (goog.LOCALE == 'ak') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ak;
    -}
    -
    -if (goog.LOCALE == 'ak_GH' || goog.LOCALE == 'ak-GH') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ak;
    -}
    -
    -if (goog.LOCALE == 'am_ET' || goog.LOCALE == 'am-ET') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_am_ET;
    -}
    -
    -if (goog.LOCALE == 'ar_001' || goog.LOCALE == 'ar-001') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_001;
    -}
    -
    -if (goog.LOCALE == 'ar_AE' || goog.LOCALE == 'ar-AE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_AE;
    -}
    -
    -if (goog.LOCALE == 'ar_BH' || goog.LOCALE == 'ar-BH') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_BH;
    -}
    -
    -if (goog.LOCALE == 'ar_DJ' || goog.LOCALE == 'ar-DJ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_DJ;
    -}
    -
    -if (goog.LOCALE == 'ar_DZ' || goog.LOCALE == 'ar-DZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_DZ;
    -}
    -
    -if (goog.LOCALE == 'ar_EG' || goog.LOCALE == 'ar-EG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_EG;
    -}
    -
    -if (goog.LOCALE == 'ar_EH' || goog.LOCALE == 'ar-EH') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_EH;
    -}
    -
    -if (goog.LOCALE == 'ar_ER' || goog.LOCALE == 'ar-ER') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_ER;
    -}
    -
    -if (goog.LOCALE == 'ar_IL' || goog.LOCALE == 'ar-IL') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_IL;
    -}
    -
    -if (goog.LOCALE == 'ar_IQ' || goog.LOCALE == 'ar-IQ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_IQ;
    -}
    -
    -if (goog.LOCALE == 'ar_JO' || goog.LOCALE == 'ar-JO') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_JO;
    -}
    -
    -if (goog.LOCALE == 'ar_KM' || goog.LOCALE == 'ar-KM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_KM;
    -}
    -
    -if (goog.LOCALE == 'ar_KW' || goog.LOCALE == 'ar-KW') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_KW;
    -}
    -
    -if (goog.LOCALE == 'ar_LB' || goog.LOCALE == 'ar-LB') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_LB;
    -}
    -
    -if (goog.LOCALE == 'ar_LY' || goog.LOCALE == 'ar-LY') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_LY;
    -}
    -
    -if (goog.LOCALE == 'ar_MA' || goog.LOCALE == 'ar-MA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_MA;
    -}
    -
    -if (goog.LOCALE == 'ar_MR' || goog.LOCALE == 'ar-MR') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_MR;
    -}
    -
    -if (goog.LOCALE == 'ar_OM' || goog.LOCALE == 'ar-OM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_OM;
    -}
    -
    -if (goog.LOCALE == 'ar_PS' || goog.LOCALE == 'ar-PS') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_PS;
    -}
    -
    -if (goog.LOCALE == 'ar_QA' || goog.LOCALE == 'ar-QA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_QA;
    -}
    -
    -if (goog.LOCALE == 'ar_SA' || goog.LOCALE == 'ar-SA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_SA;
    -}
    -
    -if (goog.LOCALE == 'ar_SD' || goog.LOCALE == 'ar-SD') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_SD;
    -}
    -
    -if (goog.LOCALE == 'ar_SO' || goog.LOCALE == 'ar-SO') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_SO;
    -}
    -
    -if (goog.LOCALE == 'ar_SS' || goog.LOCALE == 'ar-SS') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_SS;
    -}
    -
    -if (goog.LOCALE == 'ar_SY' || goog.LOCALE == 'ar-SY') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_SY;
    -}
    -
    -if (goog.LOCALE == 'ar_TD' || goog.LOCALE == 'ar-TD') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_TD;
    -}
    -
    -if (goog.LOCALE == 'ar_TN' || goog.LOCALE == 'ar-TN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_TN;
    -}
    -
    -if (goog.LOCALE == 'ar_YE' || goog.LOCALE == 'ar-YE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ar_YE;
    -}
    -
    -if (goog.LOCALE == 'as') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_as;
    -}
    -
    -if (goog.LOCALE == 'as_IN' || goog.LOCALE == 'as-IN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_as;
    -}
    -
    -if (goog.LOCALE == 'asa') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_asa;
    -}
    -
    -if (goog.LOCALE == 'asa_TZ' || goog.LOCALE == 'asa-TZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_asa;
    -}
    -
    -if (goog.LOCALE == 'ast') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ast;
    -}
    -
    -if (goog.LOCALE == 'ast_ES' || goog.LOCALE == 'ast-ES') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ast;
    -}
    -
    -if (goog.LOCALE == 'az_Cyrl' || goog.LOCALE == 'az-Cyrl') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_az_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'az_Cyrl_AZ' || goog.LOCALE == 'az-Cyrl-AZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_az_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'az_Latn' || goog.LOCALE == 'az-Latn') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_az_Latn;
    -}
    -
    -if (goog.LOCALE == 'az_Latn_AZ' || goog.LOCALE == 'az-Latn-AZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_az_Latn;
    -}
    -
    -if (goog.LOCALE == 'bas') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_bas;
    -}
    -
    -if (goog.LOCALE == 'bas_CM' || goog.LOCALE == 'bas-CM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_bas;
    -}
    -
    -if (goog.LOCALE == 'be') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_be;
    -}
    -
    -if (goog.LOCALE == 'be_BY' || goog.LOCALE == 'be-BY') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_be;
    -}
    -
    -if (goog.LOCALE == 'bem') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_bem;
    -}
    -
    -if (goog.LOCALE == 'bem_ZM' || goog.LOCALE == 'bem-ZM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_bem;
    -}
    -
    -if (goog.LOCALE == 'bez') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_bez;
    -}
    -
    -if (goog.LOCALE == 'bez_TZ' || goog.LOCALE == 'bez-TZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_bez;
    -}
    -
    -if (goog.LOCALE == 'bg_BG' || goog.LOCALE == 'bg-BG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_bg_BG;
    -}
    -
    -if (goog.LOCALE == 'bm') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_bm;
    -}
    -
    -if (goog.LOCALE == 'bm_Latn' || goog.LOCALE == 'bm-Latn') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_bm;
    -}
    -
    -if (goog.LOCALE == 'bm_Latn_ML' || goog.LOCALE == 'bm-Latn-ML') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_bm;
    -}
    -
    -if (goog.LOCALE == 'bn_BD' || goog.LOCALE == 'bn-BD') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_bn_BD;
    -}
    -
    -if (goog.LOCALE == 'bn_IN' || goog.LOCALE == 'bn-IN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_bn_IN;
    -}
    -
    -if (goog.LOCALE == 'bo') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_bo;
    -}
    -
    -if (goog.LOCALE == 'bo_CN' || goog.LOCALE == 'bo-CN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_bo;
    -}
    -
    -if (goog.LOCALE == 'bo_IN' || goog.LOCALE == 'bo-IN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_bo;
    -}
    -
    -if (goog.LOCALE == 'br_FR' || goog.LOCALE == 'br-FR') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_br_FR;
    -}
    -
    -if (goog.LOCALE == 'brx') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_brx;
    -}
    -
    -if (goog.LOCALE == 'brx_IN' || goog.LOCALE == 'brx-IN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_brx;
    -}
    -
    -if (goog.LOCALE == 'bs') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_bs;
    -}
    -
    -if (goog.LOCALE == 'bs_Cyrl' || goog.LOCALE == 'bs-Cyrl') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_bs_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'bs_Cyrl_BA' || goog.LOCALE == 'bs-Cyrl-BA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_bs_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'bs_Latn' || goog.LOCALE == 'bs-Latn') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_bs;
    -}
    -
    -if (goog.LOCALE == 'bs_Latn_BA' || goog.LOCALE == 'bs-Latn-BA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_bs;
    -}
    -
    -if (goog.LOCALE == 'ca_AD' || goog.LOCALE == 'ca-AD') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ca_AD;
    -}
    -
    -if (goog.LOCALE == 'ca_ES' || goog.LOCALE == 'ca-ES') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ca_ES;
    -}
    -
    -if (goog.LOCALE == 'ca_ES_VALENCIA' || goog.LOCALE == 'ca-ES-VALENCIA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ca_ES;
    -}
    -
    -if (goog.LOCALE == 'ca_FR' || goog.LOCALE == 'ca-FR') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ca_FR;
    -}
    -
    -if (goog.LOCALE == 'ca_IT' || goog.LOCALE == 'ca-IT') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ca_IT;
    -}
    -
    -if (goog.LOCALE == 'cgg') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_cgg;
    -}
    -
    -if (goog.LOCALE == 'cgg_UG' || goog.LOCALE == 'cgg-UG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_cgg;
    -}
    -
    -if (goog.LOCALE == 'chr_US' || goog.LOCALE == 'chr-US') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_chr_US;
    -}
    -
    -if (goog.LOCALE == 'ckb') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ckb;
    -}
    -
    -if (goog.LOCALE == 'ckb_Arab' || goog.LOCALE == 'ckb-Arab') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ckb;
    -}
    -
    -if (goog.LOCALE == 'ckb_Arab_IQ' || goog.LOCALE == 'ckb-Arab-IQ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ckb;
    -}
    -
    -if (goog.LOCALE == 'ckb_Arab_IR' || goog.LOCALE == 'ckb-Arab-IR') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ckb;
    -}
    -
    -if (goog.LOCALE == 'ckb_IQ' || goog.LOCALE == 'ckb-IQ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ckb;
    -}
    -
    -if (goog.LOCALE == 'ckb_IR' || goog.LOCALE == 'ckb-IR') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ckb;
    -}
    -
    -if (goog.LOCALE == 'ckb_Latn' || goog.LOCALE == 'ckb-Latn') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ckb;
    -}
    -
    -if (goog.LOCALE == 'ckb_Latn_IQ' || goog.LOCALE == 'ckb-Latn-IQ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ckb;
    -}
    -
    -if (goog.LOCALE == 'cs_CZ' || goog.LOCALE == 'cs-CZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_cs_CZ;
    -}
    -
    -if (goog.LOCALE == 'cy_GB' || goog.LOCALE == 'cy-GB') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_cy_GB;
    -}
    -
    -if (goog.LOCALE == 'da_DK' || goog.LOCALE == 'da-DK') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_da_DK;
    -}
    -
    -if (goog.LOCALE == 'da_GL' || goog.LOCALE == 'da-GL') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_da_GL;
    -}
    -
    -if (goog.LOCALE == 'dav') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_dav;
    -}
    -
    -if (goog.LOCALE == 'dav_KE' || goog.LOCALE == 'dav-KE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_dav;
    -}
    -
    -if (goog.LOCALE == 'de_BE' || goog.LOCALE == 'de-BE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de_BE;
    -}
    -
    -if (goog.LOCALE == 'de_DE' || goog.LOCALE == 'de-DE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de_DE;
    -}
    -
    -if (goog.LOCALE == 'de_LI' || goog.LOCALE == 'de-LI') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de_LI;
    -}
    -
    -if (goog.LOCALE == 'de_LU' || goog.LOCALE == 'de-LU') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_de_LU;
    -}
    -
    -if (goog.LOCALE == 'dje') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_dje;
    -}
    -
    -if (goog.LOCALE == 'dje_NE' || goog.LOCALE == 'dje-NE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_dje;
    -}
    -
    -if (goog.LOCALE == 'dsb') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_dsb;
    -}
    -
    -if (goog.LOCALE == 'dsb_DE' || goog.LOCALE == 'dsb-DE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_dsb;
    -}
    -
    -if (goog.LOCALE == 'dua') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_dua;
    -}
    -
    -if (goog.LOCALE == 'dua_CM' || goog.LOCALE == 'dua-CM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_dua;
    -}
    -
    -if (goog.LOCALE == 'dyo') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_dyo;
    -}
    -
    -if (goog.LOCALE == 'dyo_SN' || goog.LOCALE == 'dyo-SN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_dyo;
    -}
    -
    -if (goog.LOCALE == 'dz') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_dz;
    -}
    -
    -if (goog.LOCALE == 'dz_BT' || goog.LOCALE == 'dz-BT') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_dz;
    -}
    -
    -if (goog.LOCALE == 'ebu') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ebu;
    -}
    -
    -if (goog.LOCALE == 'ebu_KE' || goog.LOCALE == 'ebu-KE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ebu;
    -}
    -
    -if (goog.LOCALE == 'ee') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ee;
    -}
    -
    -if (goog.LOCALE == 'ee_GH' || goog.LOCALE == 'ee-GH') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ee;
    -}
    -
    -if (goog.LOCALE == 'ee_TG' || goog.LOCALE == 'ee-TG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ee;
    -}
    -
    -if (goog.LOCALE == 'el_CY' || goog.LOCALE == 'el-CY') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_el_CY;
    -}
    -
    -if (goog.LOCALE == 'el_GR' || goog.LOCALE == 'el-GR') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_el_GR;
    -}
    -
    -if (goog.LOCALE == 'en_001' || goog.LOCALE == 'en-001') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_001;
    -}
    -
    -if (goog.LOCALE == 'en_150' || goog.LOCALE == 'en-150') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_150;
    -}
    -
    -if (goog.LOCALE == 'en_AG' || goog.LOCALE == 'en-AG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_AG;
    -}
    -
    -if (goog.LOCALE == 'en_AI' || goog.LOCALE == 'en-AI') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_AI;
    -}
    -
    -if (goog.LOCALE == 'en_AS' || goog.LOCALE == 'en-AS') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_AS;
    -}
    -
    -if (goog.LOCALE == 'en_BB' || goog.LOCALE == 'en-BB') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_BB;
    -}
    -
    -if (goog.LOCALE == 'en_BE' || goog.LOCALE == 'en-BE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_BE;
    -}
    -
    -if (goog.LOCALE == 'en_BM' || goog.LOCALE == 'en-BM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_BM;
    -}
    -
    -if (goog.LOCALE == 'en_BS' || goog.LOCALE == 'en-BS') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_BS;
    -}
    -
    -if (goog.LOCALE == 'en_BW' || goog.LOCALE == 'en-BW') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_BW;
    -}
    -
    -if (goog.LOCALE == 'en_BZ' || goog.LOCALE == 'en-BZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_BZ;
    -}
    -
    -if (goog.LOCALE == 'en_CA' || goog.LOCALE == 'en-CA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_CA;
    -}
    -
    -if (goog.LOCALE == 'en_CC' || goog.LOCALE == 'en-CC') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_CC;
    -}
    -
    -if (goog.LOCALE == 'en_CK' || goog.LOCALE == 'en-CK') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_CK;
    -}
    -
    -if (goog.LOCALE == 'en_CM' || goog.LOCALE == 'en-CM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_CM;
    -}
    -
    -if (goog.LOCALE == 'en_CX' || goog.LOCALE == 'en-CX') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_CX;
    -}
    -
    -if (goog.LOCALE == 'en_DG' || goog.LOCALE == 'en-DG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_DG;
    -}
    -
    -if (goog.LOCALE == 'en_DM' || goog.LOCALE == 'en-DM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_DM;
    -}
    -
    -if (goog.LOCALE == 'en_ER' || goog.LOCALE == 'en-ER') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_ER;
    -}
    -
    -if (goog.LOCALE == 'en_FJ' || goog.LOCALE == 'en-FJ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_FJ;
    -}
    -
    -if (goog.LOCALE == 'en_FK' || goog.LOCALE == 'en-FK') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_FK;
    -}
    -
    -if (goog.LOCALE == 'en_FM' || goog.LOCALE == 'en-FM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_FM;
    -}
    -
    -if (goog.LOCALE == 'en_GD' || goog.LOCALE == 'en-GD') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_GD;
    -}
    -
    -if (goog.LOCALE == 'en_GG' || goog.LOCALE == 'en-GG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_GG;
    -}
    -
    -if (goog.LOCALE == 'en_GH' || goog.LOCALE == 'en-GH') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_GH;
    -}
    -
    -if (goog.LOCALE == 'en_GI' || goog.LOCALE == 'en-GI') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_GI;
    -}
    -
    -if (goog.LOCALE == 'en_GM' || goog.LOCALE == 'en-GM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_GM;
    -}
    -
    -if (goog.LOCALE == 'en_GU' || goog.LOCALE == 'en-GU') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_GU;
    -}
    -
    -if (goog.LOCALE == 'en_GY' || goog.LOCALE == 'en-GY') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_GY;
    -}
    -
    -if (goog.LOCALE == 'en_HK' || goog.LOCALE == 'en-HK') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_HK;
    -}
    -
    -if (goog.LOCALE == 'en_IM' || goog.LOCALE == 'en-IM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_IM;
    -}
    -
    -if (goog.LOCALE == 'en_IO' || goog.LOCALE == 'en-IO') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_IO;
    -}
    -
    -if (goog.LOCALE == 'en_JE' || goog.LOCALE == 'en-JE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_JE;
    -}
    -
    -if (goog.LOCALE == 'en_JM' || goog.LOCALE == 'en-JM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_JM;
    -}
    -
    -if (goog.LOCALE == 'en_KE' || goog.LOCALE == 'en-KE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_KE;
    -}
    -
    -if (goog.LOCALE == 'en_KI' || goog.LOCALE == 'en-KI') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_KI;
    -}
    -
    -if (goog.LOCALE == 'en_KN' || goog.LOCALE == 'en-KN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_KN;
    -}
    -
    -if (goog.LOCALE == 'en_KY' || goog.LOCALE == 'en-KY') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_KY;
    -}
    -
    -if (goog.LOCALE == 'en_LC' || goog.LOCALE == 'en-LC') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_LC;
    -}
    -
    -if (goog.LOCALE == 'en_LR' || goog.LOCALE == 'en-LR') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_LR;
    -}
    -
    -if (goog.LOCALE == 'en_LS' || goog.LOCALE == 'en-LS') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_LS;
    -}
    -
    -if (goog.LOCALE == 'en_MG' || goog.LOCALE == 'en-MG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_MG;
    -}
    -
    -if (goog.LOCALE == 'en_MH' || goog.LOCALE == 'en-MH') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_MH;
    -}
    -
    -if (goog.LOCALE == 'en_MO' || goog.LOCALE == 'en-MO') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_MO;
    -}
    -
    -if (goog.LOCALE == 'en_MP' || goog.LOCALE == 'en-MP') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_MP;
    -}
    -
    -if (goog.LOCALE == 'en_MS' || goog.LOCALE == 'en-MS') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_MS;
    -}
    -
    -if (goog.LOCALE == 'en_MT' || goog.LOCALE == 'en-MT') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_MT;
    -}
    -
    -if (goog.LOCALE == 'en_MU' || goog.LOCALE == 'en-MU') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_MU;
    -}
    -
    -if (goog.LOCALE == 'en_MW' || goog.LOCALE == 'en-MW') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_MW;
    -}
    -
    -if (goog.LOCALE == 'en_MY' || goog.LOCALE == 'en-MY') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_MY;
    -}
    -
    -if (goog.LOCALE == 'en_NA' || goog.LOCALE == 'en-NA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_NA;
    -}
    -
    -if (goog.LOCALE == 'en_NF' || goog.LOCALE == 'en-NF') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_NF;
    -}
    -
    -if (goog.LOCALE == 'en_NG' || goog.LOCALE == 'en-NG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_NG;
    -}
    -
    -if (goog.LOCALE == 'en_NR' || goog.LOCALE == 'en-NR') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_NR;
    -}
    -
    -if (goog.LOCALE == 'en_NU' || goog.LOCALE == 'en-NU') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_NU;
    -}
    -
    -if (goog.LOCALE == 'en_NZ' || goog.LOCALE == 'en-NZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_NZ;
    -}
    -
    -if (goog.LOCALE == 'en_PG' || goog.LOCALE == 'en-PG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_PG;
    -}
    -
    -if (goog.LOCALE == 'en_PH' || goog.LOCALE == 'en-PH') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_PH;
    -}
    -
    -if (goog.LOCALE == 'en_PK' || goog.LOCALE == 'en-PK') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_PK;
    -}
    -
    -if (goog.LOCALE == 'en_PN' || goog.LOCALE == 'en-PN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_PN;
    -}
    -
    -if (goog.LOCALE == 'en_PR' || goog.LOCALE == 'en-PR') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_PR;
    -}
    -
    -if (goog.LOCALE == 'en_PW' || goog.LOCALE == 'en-PW') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_PW;
    -}
    -
    -if (goog.LOCALE == 'en_RW' || goog.LOCALE == 'en-RW') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_RW;
    -}
    -
    -if (goog.LOCALE == 'en_SB' || goog.LOCALE == 'en-SB') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_SB;
    -}
    -
    -if (goog.LOCALE == 'en_SC' || goog.LOCALE == 'en-SC') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_SC;
    -}
    -
    -if (goog.LOCALE == 'en_SD' || goog.LOCALE == 'en-SD') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_SD;
    -}
    -
    -if (goog.LOCALE == 'en_SH' || goog.LOCALE == 'en-SH') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_SH;
    -}
    -
    -if (goog.LOCALE == 'en_SL' || goog.LOCALE == 'en-SL') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_SL;
    -}
    -
    -if (goog.LOCALE == 'en_SS' || goog.LOCALE == 'en-SS') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_SS;
    -}
    -
    -if (goog.LOCALE == 'en_SX' || goog.LOCALE == 'en-SX') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_SX;
    -}
    -
    -if (goog.LOCALE == 'en_SZ' || goog.LOCALE == 'en-SZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_SZ;
    -}
    -
    -if (goog.LOCALE == 'en_TC' || goog.LOCALE == 'en-TC') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_TC;
    -}
    -
    -if (goog.LOCALE == 'en_TK' || goog.LOCALE == 'en-TK') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_TK;
    -}
    -
    -if (goog.LOCALE == 'en_TO' || goog.LOCALE == 'en-TO') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_TO;
    -}
    -
    -if (goog.LOCALE == 'en_TT' || goog.LOCALE == 'en-TT') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_TT;
    -}
    -
    -if (goog.LOCALE == 'en_TV' || goog.LOCALE == 'en-TV') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_TV;
    -}
    -
    -if (goog.LOCALE == 'en_TZ' || goog.LOCALE == 'en-TZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_TZ;
    -}
    -
    -if (goog.LOCALE == 'en_UG' || goog.LOCALE == 'en-UG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_UG;
    -}
    -
    -if (goog.LOCALE == 'en_UM' || goog.LOCALE == 'en-UM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_UM;
    -}
    -
    -if (goog.LOCALE == 'en_VC' || goog.LOCALE == 'en-VC') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_VC;
    -}
    -
    -if (goog.LOCALE == 'en_VG' || goog.LOCALE == 'en-VG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_VG;
    -}
    -
    -if (goog.LOCALE == 'en_VI' || goog.LOCALE == 'en-VI') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_VI;
    -}
    -
    -if (goog.LOCALE == 'en_VU' || goog.LOCALE == 'en-VU') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_VU;
    -}
    -
    -if (goog.LOCALE == 'en_WS' || goog.LOCALE == 'en-WS') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_WS;
    -}
    -
    -if (goog.LOCALE == 'en_ZM' || goog.LOCALE == 'en-ZM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_ZM;
    -}
    -
    -if (goog.LOCALE == 'en_ZW' || goog.LOCALE == 'en-ZW') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_ZW;
    -}
    -
    -if (goog.LOCALE == 'eo') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_eo;
    -}
    -
    -if (goog.LOCALE == 'eo_001' || goog.LOCALE == 'eo-001') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_eo;
    -}
    -
    -if (goog.LOCALE == 'es_AR' || goog.LOCALE == 'es-AR') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_AR;
    -}
    -
    -if (goog.LOCALE == 'es_BO' || goog.LOCALE == 'es-BO') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_BO;
    -}
    -
    -if (goog.LOCALE == 'es_CL' || goog.LOCALE == 'es-CL') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_CL;
    -}
    -
    -if (goog.LOCALE == 'es_CO' || goog.LOCALE == 'es-CO') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_CO;
    -}
    -
    -if (goog.LOCALE == 'es_CR' || goog.LOCALE == 'es-CR') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_CR;
    -}
    -
    -if (goog.LOCALE == 'es_CU' || goog.LOCALE == 'es-CU') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_CU;
    -}
    -
    -if (goog.LOCALE == 'es_DO' || goog.LOCALE == 'es-DO') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_DO;
    -}
    -
    -if (goog.LOCALE == 'es_EA' || goog.LOCALE == 'es-EA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_EA;
    -}
    -
    -if (goog.LOCALE == 'es_EC' || goog.LOCALE == 'es-EC') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_EC;
    -}
    -
    -if (goog.LOCALE == 'es_GQ' || goog.LOCALE == 'es-GQ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_GQ;
    -}
    -
    -if (goog.LOCALE == 'es_GT' || goog.LOCALE == 'es-GT') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_GT;
    -}
    -
    -if (goog.LOCALE == 'es_HN' || goog.LOCALE == 'es-HN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_HN;
    -}
    -
    -if (goog.LOCALE == 'es_IC' || goog.LOCALE == 'es-IC') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_IC;
    -}
    -
    -if (goog.LOCALE == 'es_MX' || goog.LOCALE == 'es-MX') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_MX;
    -}
    -
    -if (goog.LOCALE == 'es_NI' || goog.LOCALE == 'es-NI') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_NI;
    -}
    -
    -if (goog.LOCALE == 'es_PA' || goog.LOCALE == 'es-PA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_PA;
    -}
    -
    -if (goog.LOCALE == 'es_PE' || goog.LOCALE == 'es-PE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_PE;
    -}
    -
    -if (goog.LOCALE == 'es_PH' || goog.LOCALE == 'es-PH') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_PH;
    -}
    -
    -if (goog.LOCALE == 'es_PR' || goog.LOCALE == 'es-PR') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_PR;
    -}
    -
    -if (goog.LOCALE == 'es_PY' || goog.LOCALE == 'es-PY') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_PY;
    -}
    -
    -if (goog.LOCALE == 'es_SV' || goog.LOCALE == 'es-SV') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_SV;
    -}
    -
    -if (goog.LOCALE == 'es_US' || goog.LOCALE == 'es-US') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_US;
    -}
    -
    -if (goog.LOCALE == 'es_UY' || goog.LOCALE == 'es-UY') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_UY;
    -}
    -
    -if (goog.LOCALE == 'es_VE' || goog.LOCALE == 'es-VE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_es_VE;
    -}
    -
    -if (goog.LOCALE == 'et_EE' || goog.LOCALE == 'et-EE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_et_EE;
    -}
    -
    -if (goog.LOCALE == 'eu_ES' || goog.LOCALE == 'eu-ES') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_eu_ES;
    -}
    -
    -if (goog.LOCALE == 'ewo') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ewo;
    -}
    -
    -if (goog.LOCALE == 'ewo_CM' || goog.LOCALE == 'ewo-CM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ewo;
    -}
    -
    -if (goog.LOCALE == 'fa_AF' || goog.LOCALE == 'fa-AF') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fa_AF;
    -}
    -
    -if (goog.LOCALE == 'fa_IR' || goog.LOCALE == 'fa-IR') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fa_IR;
    -}
    -
    -if (goog.LOCALE == 'ff') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ff;
    -}
    -
    -if (goog.LOCALE == 'ff_CM' || goog.LOCALE == 'ff-CM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ff;
    -}
    -
    -if (goog.LOCALE == 'ff_GN' || goog.LOCALE == 'ff-GN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ff;
    -}
    -
    -if (goog.LOCALE == 'ff_MR' || goog.LOCALE == 'ff-MR') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ff;
    -}
    -
    -if (goog.LOCALE == 'ff_SN' || goog.LOCALE == 'ff-SN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ff;
    -}
    -
    -if (goog.LOCALE == 'fi_FI' || goog.LOCALE == 'fi-FI') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fi_FI;
    -}
    -
    -if (goog.LOCALE == 'fil_PH' || goog.LOCALE == 'fil-PH') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fil_PH;
    -}
    -
    -if (goog.LOCALE == 'fo') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fo;
    -}
    -
    -if (goog.LOCALE == 'fo_FO' || goog.LOCALE == 'fo-FO') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fo;
    -}
    -
    -if (goog.LOCALE == 'fr_BE' || goog.LOCALE == 'fr-BE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_BE;
    -}
    -
    -if (goog.LOCALE == 'fr_BF' || goog.LOCALE == 'fr-BF') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_BF;
    -}
    -
    -if (goog.LOCALE == 'fr_BI' || goog.LOCALE == 'fr-BI') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_BI;
    -}
    -
    -if (goog.LOCALE == 'fr_BJ' || goog.LOCALE == 'fr-BJ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_BJ;
    -}
    -
    -if (goog.LOCALE == 'fr_BL' || goog.LOCALE == 'fr-BL') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_BL;
    -}
    -
    -if (goog.LOCALE == 'fr_CD' || goog.LOCALE == 'fr-CD') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_CD;
    -}
    -
    -if (goog.LOCALE == 'fr_CF' || goog.LOCALE == 'fr-CF') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_CF;
    -}
    -
    -if (goog.LOCALE == 'fr_CG' || goog.LOCALE == 'fr-CG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_CG;
    -}
    -
    -if (goog.LOCALE == 'fr_CH' || goog.LOCALE == 'fr-CH') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_CH;
    -}
    -
    -if (goog.LOCALE == 'fr_CI' || goog.LOCALE == 'fr-CI') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_CI;
    -}
    -
    -if (goog.LOCALE == 'fr_CM' || goog.LOCALE == 'fr-CM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_CM;
    -}
    -
    -if (goog.LOCALE == 'fr_DJ' || goog.LOCALE == 'fr-DJ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_DJ;
    -}
    -
    -if (goog.LOCALE == 'fr_DZ' || goog.LOCALE == 'fr-DZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_DZ;
    -}
    -
    -if (goog.LOCALE == 'fr_FR' || goog.LOCALE == 'fr-FR') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_FR;
    -}
    -
    -if (goog.LOCALE == 'fr_GA' || goog.LOCALE == 'fr-GA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_GA;
    -}
    -
    -if (goog.LOCALE == 'fr_GF' || goog.LOCALE == 'fr-GF') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_GF;
    -}
    -
    -if (goog.LOCALE == 'fr_GN' || goog.LOCALE == 'fr-GN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_GN;
    -}
    -
    -if (goog.LOCALE == 'fr_GP' || goog.LOCALE == 'fr-GP') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_GP;
    -}
    -
    -if (goog.LOCALE == 'fr_GQ' || goog.LOCALE == 'fr-GQ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_GQ;
    -}
    -
    -if (goog.LOCALE == 'fr_HT' || goog.LOCALE == 'fr-HT') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_HT;
    -}
    -
    -if (goog.LOCALE == 'fr_KM' || goog.LOCALE == 'fr-KM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_KM;
    -}
    -
    -if (goog.LOCALE == 'fr_LU' || goog.LOCALE == 'fr-LU') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_LU;
    -}
    -
    -if (goog.LOCALE == 'fr_MA' || goog.LOCALE == 'fr-MA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_MA;
    -}
    -
    -if (goog.LOCALE == 'fr_MC' || goog.LOCALE == 'fr-MC') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_MC;
    -}
    -
    -if (goog.LOCALE == 'fr_MF' || goog.LOCALE == 'fr-MF') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_MF;
    -}
    -
    -if (goog.LOCALE == 'fr_MG' || goog.LOCALE == 'fr-MG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_MG;
    -}
    -
    -if (goog.LOCALE == 'fr_ML' || goog.LOCALE == 'fr-ML') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_ML;
    -}
    -
    -if (goog.LOCALE == 'fr_MQ' || goog.LOCALE == 'fr-MQ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_MQ;
    -}
    -
    -if (goog.LOCALE == 'fr_MR' || goog.LOCALE == 'fr-MR') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_MR;
    -}
    -
    -if (goog.LOCALE == 'fr_MU' || goog.LOCALE == 'fr-MU') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_MU;
    -}
    -
    -if (goog.LOCALE == 'fr_NC' || goog.LOCALE == 'fr-NC') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_NC;
    -}
    -
    -if (goog.LOCALE == 'fr_NE' || goog.LOCALE == 'fr-NE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_NE;
    -}
    -
    -if (goog.LOCALE == 'fr_PF' || goog.LOCALE == 'fr-PF') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_PF;
    -}
    -
    -if (goog.LOCALE == 'fr_PM' || goog.LOCALE == 'fr-PM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_PM;
    -}
    -
    -if (goog.LOCALE == 'fr_RE' || goog.LOCALE == 'fr-RE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_RE;
    -}
    -
    -if (goog.LOCALE == 'fr_RW' || goog.LOCALE == 'fr-RW') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_RW;
    -}
    -
    -if (goog.LOCALE == 'fr_SC' || goog.LOCALE == 'fr-SC') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_SC;
    -}
    -
    -if (goog.LOCALE == 'fr_SN' || goog.LOCALE == 'fr-SN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_SN;
    -}
    -
    -if (goog.LOCALE == 'fr_SY' || goog.LOCALE == 'fr-SY') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_SY;
    -}
    -
    -if (goog.LOCALE == 'fr_TD' || goog.LOCALE == 'fr-TD') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_TD;
    -}
    -
    -if (goog.LOCALE == 'fr_TG' || goog.LOCALE == 'fr-TG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_TG;
    -}
    -
    -if (goog.LOCALE == 'fr_TN' || goog.LOCALE == 'fr-TN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_TN;
    -}
    -
    -if (goog.LOCALE == 'fr_VU' || goog.LOCALE == 'fr-VU') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_VU;
    -}
    -
    -if (goog.LOCALE == 'fr_WF' || goog.LOCALE == 'fr-WF') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_WF;
    -}
    -
    -if (goog.LOCALE == 'fr_YT' || goog.LOCALE == 'fr-YT') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fr_YT;
    -}
    -
    -if (goog.LOCALE == 'fur') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fur;
    -}
    -
    -if (goog.LOCALE == 'fur_IT' || goog.LOCALE == 'fur-IT') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fur;
    -}
    -
    -if (goog.LOCALE == 'fy') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fy;
    -}
    -
    -if (goog.LOCALE == 'fy_NL' || goog.LOCALE == 'fy-NL') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_fy;
    -}
    -
    -if (goog.LOCALE == 'ga_IE' || goog.LOCALE == 'ga-IE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ga_IE;
    -}
    -
    -if (goog.LOCALE == 'gd') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_gd;
    -}
    -
    -if (goog.LOCALE == 'gd_GB' || goog.LOCALE == 'gd-GB') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_gd;
    -}
    -
    -if (goog.LOCALE == 'gl_ES' || goog.LOCALE == 'gl-ES') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_gl_ES;
    -}
    -
    -if (goog.LOCALE == 'gsw_CH' || goog.LOCALE == 'gsw-CH') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_gsw_CH;
    -}
    -
    -if (goog.LOCALE == 'gsw_FR' || goog.LOCALE == 'gsw-FR') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_gsw_FR;
    -}
    -
    -if (goog.LOCALE == 'gsw_LI' || goog.LOCALE == 'gsw-LI') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_gsw_LI;
    -}
    -
    -if (goog.LOCALE == 'gu_IN' || goog.LOCALE == 'gu-IN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_gu_IN;
    -}
    -
    -if (goog.LOCALE == 'guz') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_guz;
    -}
    -
    -if (goog.LOCALE == 'guz_KE' || goog.LOCALE == 'guz-KE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_guz;
    -}
    -
    -if (goog.LOCALE == 'gv') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_gv;
    -}
    -
    -if (goog.LOCALE == 'gv_IM' || goog.LOCALE == 'gv-IM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_gv;
    -}
    -
    -if (goog.LOCALE == 'ha') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ha;
    -}
    -
    -if (goog.LOCALE == 'ha_Latn' || goog.LOCALE == 'ha-Latn') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ha;
    -}
    -
    -if (goog.LOCALE == 'ha_Latn_GH' || goog.LOCALE == 'ha-Latn-GH') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ha;
    -}
    -
    -if (goog.LOCALE == 'ha_Latn_NE' || goog.LOCALE == 'ha-Latn-NE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ha;
    -}
    -
    -if (goog.LOCALE == 'ha_Latn_NG' || goog.LOCALE == 'ha-Latn-NG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ha;
    -}
    -
    -if (goog.LOCALE == 'haw_US' || goog.LOCALE == 'haw-US') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_haw_US;
    -}
    -
    -if (goog.LOCALE == 'he_IL' || goog.LOCALE == 'he-IL') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_he_IL;
    -}
    -
    -if (goog.LOCALE == 'hi_IN' || goog.LOCALE == 'hi-IN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_hi_IN;
    -}
    -
    -if (goog.LOCALE == 'hr_BA' || goog.LOCALE == 'hr-BA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_hr_BA;
    -}
    -
    -if (goog.LOCALE == 'hr_HR' || goog.LOCALE == 'hr-HR') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_hr_HR;
    -}
    -
    -if (goog.LOCALE == 'hsb') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_hsb;
    -}
    -
    -if (goog.LOCALE == 'hsb_DE' || goog.LOCALE == 'hsb-DE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_hsb;
    -}
    -
    -if (goog.LOCALE == 'hu_HU' || goog.LOCALE == 'hu-HU') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_hu_HU;
    -}
    -
    -if (goog.LOCALE == 'hy_AM' || goog.LOCALE == 'hy-AM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_hy_AM;
    -}
    -
    -if (goog.LOCALE == 'ia') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ia;
    -}
    -
    -if (goog.LOCALE == 'ia_FR' || goog.LOCALE == 'ia-FR') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ia;
    -}
    -
    -if (goog.LOCALE == 'id_ID' || goog.LOCALE == 'id-ID') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_id_ID;
    -}
    -
    -if (goog.LOCALE == 'ig') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ig;
    -}
    -
    -if (goog.LOCALE == 'ig_NG' || goog.LOCALE == 'ig-NG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ig;
    -}
    -
    -if (goog.LOCALE == 'ii') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ii;
    -}
    -
    -if (goog.LOCALE == 'ii_CN' || goog.LOCALE == 'ii-CN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ii;
    -}
    -
    -if (goog.LOCALE == 'is_IS' || goog.LOCALE == 'is-IS') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_is_IS;
    -}
    -
    -if (goog.LOCALE == 'it_CH' || goog.LOCALE == 'it-CH') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_it_CH;
    -}
    -
    -if (goog.LOCALE == 'it_IT' || goog.LOCALE == 'it-IT') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_it_IT;
    -}
    -
    -if (goog.LOCALE == 'it_SM' || goog.LOCALE == 'it-SM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_it_SM;
    -}
    -
    -if (goog.LOCALE == 'ja_JP' || goog.LOCALE == 'ja-JP') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ja_JP;
    -}
    -
    -if (goog.LOCALE == 'jgo') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_jgo;
    -}
    -
    -if (goog.LOCALE == 'jgo_CM' || goog.LOCALE == 'jgo-CM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_jgo;
    -}
    -
    -if (goog.LOCALE == 'jmc') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_jmc;
    -}
    -
    -if (goog.LOCALE == 'jmc_TZ' || goog.LOCALE == 'jmc-TZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_jmc;
    -}
    -
    -if (goog.LOCALE == 'ka_GE' || goog.LOCALE == 'ka-GE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ka_GE;
    -}
    -
    -if (goog.LOCALE == 'kab') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_kab;
    -}
    -
    -if (goog.LOCALE == 'kab_DZ' || goog.LOCALE == 'kab-DZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_kab;
    -}
    -
    -if (goog.LOCALE == 'kam') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_kam;
    -}
    -
    -if (goog.LOCALE == 'kam_KE' || goog.LOCALE == 'kam-KE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_kam;
    -}
    -
    -if (goog.LOCALE == 'kde') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_kde;
    -}
    -
    -if (goog.LOCALE == 'kde_TZ' || goog.LOCALE == 'kde-TZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_kde;
    -}
    -
    -if (goog.LOCALE == 'kea') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_kea;
    -}
    -
    -if (goog.LOCALE == 'kea_CV' || goog.LOCALE == 'kea-CV') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_kea;
    -}
    -
    -if (goog.LOCALE == 'khq') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_khq;
    -}
    -
    -if (goog.LOCALE == 'khq_ML' || goog.LOCALE == 'khq-ML') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_khq;
    -}
    -
    -if (goog.LOCALE == 'ki') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ki;
    -}
    -
    -if (goog.LOCALE == 'ki_KE' || goog.LOCALE == 'ki-KE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ki;
    -}
    -
    -if (goog.LOCALE == 'kk_Cyrl' || goog.LOCALE == 'kk-Cyrl') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_kk_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'kk_Cyrl_KZ' || goog.LOCALE == 'kk-Cyrl-KZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_kk_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'kkj') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_kkj;
    -}
    -
    -if (goog.LOCALE == 'kkj_CM' || goog.LOCALE == 'kkj-CM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_kkj;
    -}
    -
    -if (goog.LOCALE == 'kl') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_kl;
    -}
    -
    -if (goog.LOCALE == 'kl_GL' || goog.LOCALE == 'kl-GL') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_kl;
    -}
    -
    -if (goog.LOCALE == 'kln') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_kln;
    -}
    -
    -if (goog.LOCALE == 'kln_KE' || goog.LOCALE == 'kln-KE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_kln;
    -}
    -
    -if (goog.LOCALE == 'km_KH' || goog.LOCALE == 'km-KH') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_km_KH;
    -}
    -
    -if (goog.LOCALE == 'kn_IN' || goog.LOCALE == 'kn-IN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_kn_IN;
    -}
    -
    -if (goog.LOCALE == 'ko_KP' || goog.LOCALE == 'ko-KP') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ko_KP;
    -}
    -
    -if (goog.LOCALE == 'ko_KR' || goog.LOCALE == 'ko-KR') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ko_KR;
    -}
    -
    -if (goog.LOCALE == 'kok') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_kok;
    -}
    -
    -if (goog.LOCALE == 'kok_IN' || goog.LOCALE == 'kok-IN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_kok;
    -}
    -
    -if (goog.LOCALE == 'ks') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ks;
    -}
    -
    -if (goog.LOCALE == 'ks_Arab' || goog.LOCALE == 'ks-Arab') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ks;
    -}
    -
    -if (goog.LOCALE == 'ks_Arab_IN' || goog.LOCALE == 'ks-Arab-IN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ks;
    -}
    -
    -if (goog.LOCALE == 'ksb') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ksb;
    -}
    -
    -if (goog.LOCALE == 'ksb_TZ' || goog.LOCALE == 'ksb-TZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ksb;
    -}
    -
    -if (goog.LOCALE == 'ksf') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ksf;
    -}
    -
    -if (goog.LOCALE == 'ksf_CM' || goog.LOCALE == 'ksf-CM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ksf;
    -}
    -
    -if (goog.LOCALE == 'ksh') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ksh;
    -}
    -
    -if (goog.LOCALE == 'ksh_DE' || goog.LOCALE == 'ksh-DE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ksh;
    -}
    -
    -if (goog.LOCALE == 'kw') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_kw;
    -}
    -
    -if (goog.LOCALE == 'kw_GB' || goog.LOCALE == 'kw-GB') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_kw;
    -}
    -
    -if (goog.LOCALE == 'ky_Cyrl' || goog.LOCALE == 'ky-Cyrl') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ky_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'ky_Cyrl_KG' || goog.LOCALE == 'ky-Cyrl-KG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ky_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'lag') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_lag;
    -}
    -
    -if (goog.LOCALE == 'lag_TZ' || goog.LOCALE == 'lag-TZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_lag;
    -}
    -
    -if (goog.LOCALE == 'lb') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_lb;
    -}
    -
    -if (goog.LOCALE == 'lb_LU' || goog.LOCALE == 'lb-LU') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_lb;
    -}
    -
    -if (goog.LOCALE == 'lg') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_lg;
    -}
    -
    -if (goog.LOCALE == 'lg_UG' || goog.LOCALE == 'lg-UG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_lg;
    -}
    -
    -if (goog.LOCALE == 'lkt') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_lkt;
    -}
    -
    -if (goog.LOCALE == 'lkt_US' || goog.LOCALE == 'lkt-US') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_lkt;
    -}
    -
    -if (goog.LOCALE == 'ln_AO' || goog.LOCALE == 'ln-AO') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ln_AO;
    -}
    -
    -if (goog.LOCALE == 'ln_CD' || goog.LOCALE == 'ln-CD') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ln_CD;
    -}
    -
    -if (goog.LOCALE == 'ln_CF' || goog.LOCALE == 'ln-CF') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ln_CF;
    -}
    -
    -if (goog.LOCALE == 'ln_CG' || goog.LOCALE == 'ln-CG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ln_CG;
    -}
    -
    -if (goog.LOCALE == 'lo_LA' || goog.LOCALE == 'lo-LA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_lo_LA;
    -}
    -
    -if (goog.LOCALE == 'lt_LT' || goog.LOCALE == 'lt-LT') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_lt_LT;
    -}
    -
    -if (goog.LOCALE == 'lu') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_lu;
    -}
    -
    -if (goog.LOCALE == 'lu_CD' || goog.LOCALE == 'lu-CD') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_lu;
    -}
    -
    -if (goog.LOCALE == 'luo') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_luo;
    -}
    -
    -if (goog.LOCALE == 'luo_KE' || goog.LOCALE == 'luo-KE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_luo;
    -}
    -
    -if (goog.LOCALE == 'luy') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_luy;
    -}
    -
    -if (goog.LOCALE == 'luy_KE' || goog.LOCALE == 'luy-KE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_luy;
    -}
    -
    -if (goog.LOCALE == 'lv_LV' || goog.LOCALE == 'lv-LV') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_lv_LV;
    -}
    -
    -if (goog.LOCALE == 'mas') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_mas;
    -}
    -
    -if (goog.LOCALE == 'mas_KE' || goog.LOCALE == 'mas-KE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_mas;
    -}
    -
    -if (goog.LOCALE == 'mas_TZ' || goog.LOCALE == 'mas-TZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_mas;
    -}
    -
    -if (goog.LOCALE == 'mer') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_mer;
    -}
    -
    -if (goog.LOCALE == 'mer_KE' || goog.LOCALE == 'mer-KE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_mer;
    -}
    -
    -if (goog.LOCALE == 'mfe') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_mfe;
    -}
    -
    -if (goog.LOCALE == 'mfe_MU' || goog.LOCALE == 'mfe-MU') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_mfe;
    -}
    -
    -if (goog.LOCALE == 'mg') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_mg;
    -}
    -
    -if (goog.LOCALE == 'mg_MG' || goog.LOCALE == 'mg-MG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_mg;
    -}
    -
    -if (goog.LOCALE == 'mgh') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_mgh;
    -}
    -
    -if (goog.LOCALE == 'mgh_MZ' || goog.LOCALE == 'mgh-MZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_mgh;
    -}
    -
    -if (goog.LOCALE == 'mgo') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_mgo;
    -}
    -
    -if (goog.LOCALE == 'mgo_CM' || goog.LOCALE == 'mgo-CM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_mgo;
    -}
    -
    -if (goog.LOCALE == 'mk_MK' || goog.LOCALE == 'mk-MK') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_mk_MK;
    -}
    -
    -if (goog.LOCALE == 'ml_IN' || goog.LOCALE == 'ml-IN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ml_IN;
    -}
    -
    -if (goog.LOCALE == 'mn_Cyrl' || goog.LOCALE == 'mn-Cyrl') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_mn_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'mn_Cyrl_MN' || goog.LOCALE == 'mn-Cyrl-MN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_mn_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'mr_IN' || goog.LOCALE == 'mr-IN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_mr_IN;
    -}
    -
    -if (goog.LOCALE == 'ms_Latn' || goog.LOCALE == 'ms-Latn') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ms_Latn;
    -}
    -
    -if (goog.LOCALE == 'ms_Latn_BN' || goog.LOCALE == 'ms-Latn-BN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ms_Latn_BN;
    -}
    -
    -if (goog.LOCALE == 'ms_Latn_MY' || goog.LOCALE == 'ms-Latn-MY') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ms_Latn;
    -}
    -
    -if (goog.LOCALE == 'ms_Latn_SG' || goog.LOCALE == 'ms-Latn-SG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ms_Latn;
    -}
    -
    -if (goog.LOCALE == 'mt_MT' || goog.LOCALE == 'mt-MT') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_mt_MT;
    -}
    -
    -if (goog.LOCALE == 'mua') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_mua;
    -}
    -
    -if (goog.LOCALE == 'mua_CM' || goog.LOCALE == 'mua-CM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_mua;
    -}
    -
    -if (goog.LOCALE == 'my_MM' || goog.LOCALE == 'my-MM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_my_MM;
    -}
    -
    -if (goog.LOCALE == 'naq') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_naq;
    -}
    -
    -if (goog.LOCALE == 'naq_NA' || goog.LOCALE == 'naq-NA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_naq;
    -}
    -
    -if (goog.LOCALE == 'nb_NO' || goog.LOCALE == 'nb-NO') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_nb_NO;
    -}
    -
    -if (goog.LOCALE == 'nb_SJ' || goog.LOCALE == 'nb-SJ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_nb_SJ;
    -}
    -
    -if (goog.LOCALE == 'nd') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_nd;
    -}
    -
    -if (goog.LOCALE == 'nd_ZW' || goog.LOCALE == 'nd-ZW') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_nd;
    -}
    -
    -if (goog.LOCALE == 'ne_IN' || goog.LOCALE == 'ne-IN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ne_IN;
    -}
    -
    -if (goog.LOCALE == 'ne_NP' || goog.LOCALE == 'ne-NP') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ne_NP;
    -}
    -
    -if (goog.LOCALE == 'nl_AW' || goog.LOCALE == 'nl-AW') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_nl_AW;
    -}
    -
    -if (goog.LOCALE == 'nl_BE' || goog.LOCALE == 'nl-BE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_nl_BE;
    -}
    -
    -if (goog.LOCALE == 'nl_BQ' || goog.LOCALE == 'nl-BQ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_nl_BQ;
    -}
    -
    -if (goog.LOCALE == 'nl_CW' || goog.LOCALE == 'nl-CW') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_nl_CW;
    -}
    -
    -if (goog.LOCALE == 'nl_NL' || goog.LOCALE == 'nl-NL') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_nl_NL;
    -}
    -
    -if (goog.LOCALE == 'nl_SR' || goog.LOCALE == 'nl-SR') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_nl_SR;
    -}
    -
    -if (goog.LOCALE == 'nl_SX' || goog.LOCALE == 'nl-SX') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_nl_SX;
    -}
    -
    -if (goog.LOCALE == 'nmg') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_nmg;
    -}
    -
    -if (goog.LOCALE == 'nmg_CM' || goog.LOCALE == 'nmg-CM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_nmg;
    -}
    -
    -if (goog.LOCALE == 'nn') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_nn;
    -}
    -
    -if (goog.LOCALE == 'nn_NO' || goog.LOCALE == 'nn-NO') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_nn;
    -}
    -
    -if (goog.LOCALE == 'nnh') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_nnh;
    -}
    -
    -if (goog.LOCALE == 'nnh_CM' || goog.LOCALE == 'nnh-CM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_nnh;
    -}
    -
    -if (goog.LOCALE == 'nr') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_nr;
    -}
    -
    -if (goog.LOCALE == 'nr_ZA' || goog.LOCALE == 'nr-ZA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_nr;
    -}
    -
    -if (goog.LOCALE == 'nso') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_nso;
    -}
    -
    -if (goog.LOCALE == 'nso_ZA' || goog.LOCALE == 'nso-ZA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_nso;
    -}
    -
    -if (goog.LOCALE == 'nus') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_nus;
    -}
    -
    -if (goog.LOCALE == 'nus_SD' || goog.LOCALE == 'nus-SD') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_nus;
    -}
    -
    -if (goog.LOCALE == 'nyn') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_nyn;
    -}
    -
    -if (goog.LOCALE == 'nyn_UG' || goog.LOCALE == 'nyn-UG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_nyn;
    -}
    -
    -if (goog.LOCALE == 'om') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_om;
    -}
    -
    -if (goog.LOCALE == 'om_ET' || goog.LOCALE == 'om-ET') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_om;
    -}
    -
    -if (goog.LOCALE == 'om_KE' || goog.LOCALE == 'om-KE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_om;
    -}
    -
    -if (goog.LOCALE == 'or_IN' || goog.LOCALE == 'or-IN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_or_IN;
    -}
    -
    -if (goog.LOCALE == 'os') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_os;
    -}
    -
    -if (goog.LOCALE == 'os_GE' || goog.LOCALE == 'os-GE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_os;
    -}
    -
    -if (goog.LOCALE == 'os_RU' || goog.LOCALE == 'os-RU') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_os;
    -}
    -
    -if (goog.LOCALE == 'pa_Arab' || goog.LOCALE == 'pa-Arab') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_pa_Arab;
    -}
    -
    -if (goog.LOCALE == 'pa_Arab_PK' || goog.LOCALE == 'pa-Arab-PK') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_pa_Arab;
    -}
    -
    -if (goog.LOCALE == 'pa_Guru' || goog.LOCALE == 'pa-Guru') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_pa_Guru;
    -}
    -
    -if (goog.LOCALE == 'pa_Guru_IN' || goog.LOCALE == 'pa-Guru-IN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_pa_Guru;
    -}
    -
    -if (goog.LOCALE == 'pl_PL' || goog.LOCALE == 'pl-PL') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_pl_PL;
    -}
    -
    -if (goog.LOCALE == 'ps') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ps;
    -}
    -
    -if (goog.LOCALE == 'ps_AF' || goog.LOCALE == 'ps-AF') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ps;
    -}
    -
    -if (goog.LOCALE == 'pt_AO' || goog.LOCALE == 'pt-AO') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_pt_AO;
    -}
    -
    -if (goog.LOCALE == 'pt_CV' || goog.LOCALE == 'pt-CV') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_pt_CV;
    -}
    -
    -if (goog.LOCALE == 'pt_GW' || goog.LOCALE == 'pt-GW') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_pt_GW;
    -}
    -
    -if (goog.LOCALE == 'pt_MO' || goog.LOCALE == 'pt-MO') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_pt_MO;
    -}
    -
    -if (goog.LOCALE == 'pt_MZ' || goog.LOCALE == 'pt-MZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_pt_MZ;
    -}
    -
    -if (goog.LOCALE == 'pt_ST' || goog.LOCALE == 'pt-ST') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_pt_ST;
    -}
    -
    -if (goog.LOCALE == 'pt_TL' || goog.LOCALE == 'pt-TL') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_pt_TL;
    -}
    -
    -if (goog.LOCALE == 'qu') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_qu;
    -}
    -
    -if (goog.LOCALE == 'qu_BO' || goog.LOCALE == 'qu-BO') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_qu;
    -}
    -
    -if (goog.LOCALE == 'qu_EC' || goog.LOCALE == 'qu-EC') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_qu;
    -}
    -
    -if (goog.LOCALE == 'qu_PE' || goog.LOCALE == 'qu-PE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_qu;
    -}
    -
    -if (goog.LOCALE == 'rm') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_rm;
    -}
    -
    -if (goog.LOCALE == 'rm_CH' || goog.LOCALE == 'rm-CH') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_rm;
    -}
    -
    -if (goog.LOCALE == 'rn') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_rn;
    -}
    -
    -if (goog.LOCALE == 'rn_BI' || goog.LOCALE == 'rn-BI') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_rn;
    -}
    -
    -if (goog.LOCALE == 'ro_MD' || goog.LOCALE == 'ro-MD') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ro_MD;
    -}
    -
    -if (goog.LOCALE == 'ro_RO' || goog.LOCALE == 'ro-RO') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ro_RO;
    -}
    -
    -if (goog.LOCALE == 'rof') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_rof;
    -}
    -
    -if (goog.LOCALE == 'rof_TZ' || goog.LOCALE == 'rof-TZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_rof;
    -}
    -
    -if (goog.LOCALE == 'ru_BY' || goog.LOCALE == 'ru-BY') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ru_BY;
    -}
    -
    -if (goog.LOCALE == 'ru_KG' || goog.LOCALE == 'ru-KG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ru_KG;
    -}
    -
    -if (goog.LOCALE == 'ru_KZ' || goog.LOCALE == 'ru-KZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ru_KZ;
    -}
    -
    -if (goog.LOCALE == 'ru_MD' || goog.LOCALE == 'ru-MD') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ru_MD;
    -}
    -
    -if (goog.LOCALE == 'ru_RU' || goog.LOCALE == 'ru-RU') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ru_RU;
    -}
    -
    -if (goog.LOCALE == 'ru_UA' || goog.LOCALE == 'ru-UA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ru_UA;
    -}
    -
    -if (goog.LOCALE == 'rw') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_rw;
    -}
    -
    -if (goog.LOCALE == 'rw_RW' || goog.LOCALE == 'rw-RW') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_rw;
    -}
    -
    -if (goog.LOCALE == 'rwk') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_rwk;
    -}
    -
    -if (goog.LOCALE == 'rwk_TZ' || goog.LOCALE == 'rwk-TZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_rwk;
    -}
    -
    -if (goog.LOCALE == 'sah') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sah;
    -}
    -
    -if (goog.LOCALE == 'sah_RU' || goog.LOCALE == 'sah-RU') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sah;
    -}
    -
    -if (goog.LOCALE == 'saq') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_saq;
    -}
    -
    -if (goog.LOCALE == 'saq_KE' || goog.LOCALE == 'saq-KE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_saq;
    -}
    -
    -if (goog.LOCALE == 'sbp') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sbp;
    -}
    -
    -if (goog.LOCALE == 'sbp_TZ' || goog.LOCALE == 'sbp-TZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sbp;
    -}
    -
    -if (goog.LOCALE == 'se') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_se;
    -}
    -
    -if (goog.LOCALE == 'se_FI' || goog.LOCALE == 'se-FI') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_se_FI;
    -}
    -
    -if (goog.LOCALE == 'se_NO' || goog.LOCALE == 'se-NO') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_se;
    -}
    -
    -if (goog.LOCALE == 'se_SE' || goog.LOCALE == 'se-SE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_se;
    -}
    -
    -if (goog.LOCALE == 'seh') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_seh;
    -}
    -
    -if (goog.LOCALE == 'seh_MZ' || goog.LOCALE == 'seh-MZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_seh;
    -}
    -
    -if (goog.LOCALE == 'ses') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ses;
    -}
    -
    -if (goog.LOCALE == 'ses_ML' || goog.LOCALE == 'ses-ML') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ses;
    -}
    -
    -if (goog.LOCALE == 'sg') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sg;
    -}
    -
    -if (goog.LOCALE == 'sg_CF' || goog.LOCALE == 'sg-CF') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sg;
    -}
    -
    -if (goog.LOCALE == 'shi') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_shi;
    -}
    -
    -if (goog.LOCALE == 'shi_Latn' || goog.LOCALE == 'shi-Latn') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_shi_Latn;
    -}
    -
    -if (goog.LOCALE == 'shi_Latn_MA' || goog.LOCALE == 'shi-Latn-MA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_shi_Latn;
    -}
    -
    -if (goog.LOCALE == 'shi_Tfng' || goog.LOCALE == 'shi-Tfng') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_shi;
    -}
    -
    -if (goog.LOCALE == 'shi_Tfng_MA' || goog.LOCALE == 'shi-Tfng-MA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_shi;
    -}
    -
    -if (goog.LOCALE == 'si_LK' || goog.LOCALE == 'si-LK') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_si_LK;
    -}
    -
    -if (goog.LOCALE == 'sk_SK' || goog.LOCALE == 'sk-SK') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sk_SK;
    -}
    -
    -if (goog.LOCALE == 'sl_SI' || goog.LOCALE == 'sl-SI') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sl_SI;
    -}
    -
    -if (goog.LOCALE == 'smn') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_smn;
    -}
    -
    -if (goog.LOCALE == 'smn_FI' || goog.LOCALE == 'smn-FI') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_smn;
    -}
    -
    -if (goog.LOCALE == 'sn') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sn;
    -}
    -
    -if (goog.LOCALE == 'sn_ZW' || goog.LOCALE == 'sn-ZW') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sn;
    -}
    -
    -if (goog.LOCALE == 'so') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_so;
    -}
    -
    -if (goog.LOCALE == 'so_DJ' || goog.LOCALE == 'so-DJ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_so;
    -}
    -
    -if (goog.LOCALE == 'so_ET' || goog.LOCALE == 'so-ET') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_so;
    -}
    -
    -if (goog.LOCALE == 'so_KE' || goog.LOCALE == 'so-KE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_so;
    -}
    -
    -if (goog.LOCALE == 'so_SO' || goog.LOCALE == 'so-SO') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_so;
    -}
    -
    -if (goog.LOCALE == 'sq_AL' || goog.LOCALE == 'sq-AL') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sq_AL;
    -}
    -
    -if (goog.LOCALE == 'sq_MK' || goog.LOCALE == 'sq-MK') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sq_MK;
    -}
    -
    -if (goog.LOCALE == 'sq_XK' || goog.LOCALE == 'sq-XK') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sq_XK;
    -}
    -
    -if (goog.LOCALE == 'sr_Cyrl' || goog.LOCALE == 'sr-Cyrl') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sr_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'sr_Cyrl_BA' || goog.LOCALE == 'sr-Cyrl-BA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sr_Cyrl_BA;
    -}
    -
    -if (goog.LOCALE == 'sr_Cyrl_ME' || goog.LOCALE == 'sr-Cyrl-ME') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sr_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'sr_Cyrl_RS' || goog.LOCALE == 'sr-Cyrl-RS') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sr_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'sr_Cyrl_XK' || goog.LOCALE == 'sr-Cyrl-XK') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sr_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'sr_Latn' || goog.LOCALE == 'sr-Latn') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sr_Latn;
    -}
    -
    -if (goog.LOCALE == 'sr_Latn_BA' || goog.LOCALE == 'sr-Latn-BA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sr_Latn_BA;
    -}
    -
    -if (goog.LOCALE == 'sr_Latn_ME' || goog.LOCALE == 'sr-Latn-ME') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sr_Latn;
    -}
    -
    -if (goog.LOCALE == 'sr_Latn_RS' || goog.LOCALE == 'sr-Latn-RS') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sr_Latn;
    -}
    -
    -if (goog.LOCALE == 'sr_Latn_XK' || goog.LOCALE == 'sr-Latn-XK') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sr_Latn;
    -}
    -
    -if (goog.LOCALE == 'ss') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ss;
    -}
    -
    -if (goog.LOCALE == 'ss_SZ' || goog.LOCALE == 'ss-SZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ss;
    -}
    -
    -if (goog.LOCALE == 'ss_ZA' || goog.LOCALE == 'ss-ZA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ss;
    -}
    -
    -if (goog.LOCALE == 'ssy') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ssy;
    -}
    -
    -if (goog.LOCALE == 'ssy_ER' || goog.LOCALE == 'ssy-ER') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ssy;
    -}
    -
    -if (goog.LOCALE == 'sv_AX' || goog.LOCALE == 'sv-AX') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sv_AX;
    -}
    -
    -if (goog.LOCALE == 'sv_FI' || goog.LOCALE == 'sv-FI') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sv_FI;
    -}
    -
    -if (goog.LOCALE == 'sv_SE' || goog.LOCALE == 'sv-SE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sv_SE;
    -}
    -
    -if (goog.LOCALE == 'sw_KE' || goog.LOCALE == 'sw-KE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sw_KE;
    -}
    -
    -if (goog.LOCALE == 'sw_TZ' || goog.LOCALE == 'sw-TZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sw_TZ;
    -}
    -
    -if (goog.LOCALE == 'sw_UG' || goog.LOCALE == 'sw-UG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_sw_UG;
    -}
    -
    -if (goog.LOCALE == 'swc') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_swc;
    -}
    -
    -if (goog.LOCALE == 'swc_CD' || goog.LOCALE == 'swc-CD') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_swc;
    -}
    -
    -if (goog.LOCALE == 'ta_IN' || goog.LOCALE == 'ta-IN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ta_IN;
    -}
    -
    -if (goog.LOCALE == 'ta_LK' || goog.LOCALE == 'ta-LK') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ta_LK;
    -}
    -
    -if (goog.LOCALE == 'ta_MY' || goog.LOCALE == 'ta-MY') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ta_MY;
    -}
    -
    -if (goog.LOCALE == 'ta_SG' || goog.LOCALE == 'ta-SG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ta_SG;
    -}
    -
    -if (goog.LOCALE == 'te_IN' || goog.LOCALE == 'te-IN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_te_IN;
    -}
    -
    -if (goog.LOCALE == 'teo') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_teo;
    -}
    -
    -if (goog.LOCALE == 'teo_KE' || goog.LOCALE == 'teo-KE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_teo;
    -}
    -
    -if (goog.LOCALE == 'teo_UG' || goog.LOCALE == 'teo-UG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_teo;
    -}
    -
    -if (goog.LOCALE == 'th_TH' || goog.LOCALE == 'th-TH') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_th_TH;
    -}
    -
    -if (goog.LOCALE == 'ti') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ti;
    -}
    -
    -if (goog.LOCALE == 'ti_ER' || goog.LOCALE == 'ti-ER') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ti_ER;
    -}
    -
    -if (goog.LOCALE == 'ti_ET' || goog.LOCALE == 'ti-ET') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ti;
    -}
    -
    -if (goog.LOCALE == 'tn') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_tn;
    -}
    -
    -if (goog.LOCALE == 'tn_BW' || goog.LOCALE == 'tn-BW') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_tn;
    -}
    -
    -if (goog.LOCALE == 'tn_ZA' || goog.LOCALE == 'tn-ZA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_tn;
    -}
    -
    -if (goog.LOCALE == 'to') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_to;
    -}
    -
    -if (goog.LOCALE == 'to_TO' || goog.LOCALE == 'to-TO') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_to;
    -}
    -
    -if (goog.LOCALE == 'tr_CY' || goog.LOCALE == 'tr-CY') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_tr_CY;
    -}
    -
    -if (goog.LOCALE == 'tr_TR' || goog.LOCALE == 'tr-TR') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_tr_TR;
    -}
    -
    -if (goog.LOCALE == 'ts') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ts;
    -}
    -
    -if (goog.LOCALE == 'ts_ZA' || goog.LOCALE == 'ts-ZA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ts;
    -}
    -
    -if (goog.LOCALE == 'twq') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_twq;
    -}
    -
    -if (goog.LOCALE == 'twq_NE' || goog.LOCALE == 'twq-NE') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_twq;
    -}
    -
    -if (goog.LOCALE == 'tzm') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_tzm;
    -}
    -
    -if (goog.LOCALE == 'tzm_Latn' || goog.LOCALE == 'tzm-Latn') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_tzm;
    -}
    -
    -if (goog.LOCALE == 'tzm_Latn_MA' || goog.LOCALE == 'tzm-Latn-MA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_tzm;
    -}
    -
    -if (goog.LOCALE == 'ug') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ug;
    -}
    -
    -if (goog.LOCALE == 'ug_Arab' || goog.LOCALE == 'ug-Arab') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ug;
    -}
    -
    -if (goog.LOCALE == 'ug_Arab_CN' || goog.LOCALE == 'ug-Arab-CN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ug;
    -}
    -
    -if (goog.LOCALE == 'uk_UA' || goog.LOCALE == 'uk-UA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_uk_UA;
    -}
    -
    -if (goog.LOCALE == 'ur_IN' || goog.LOCALE == 'ur-IN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ur_IN;
    -}
    -
    -if (goog.LOCALE == 'ur_PK' || goog.LOCALE == 'ur-PK') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ur_PK;
    -}
    -
    -if (goog.LOCALE == 'uz_Arab' || goog.LOCALE == 'uz-Arab') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_uz_Arab;
    -}
    -
    -if (goog.LOCALE == 'uz_Arab_AF' || goog.LOCALE == 'uz-Arab-AF') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_uz_Arab;
    -}
    -
    -if (goog.LOCALE == 'uz_Cyrl' || goog.LOCALE == 'uz-Cyrl') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_uz_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'uz_Cyrl_UZ' || goog.LOCALE == 'uz-Cyrl-UZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_uz_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'uz_Latn' || goog.LOCALE == 'uz-Latn') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_uz_Latn;
    -}
    -
    -if (goog.LOCALE == 'uz_Latn_UZ' || goog.LOCALE == 'uz-Latn-UZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_uz_Latn;
    -}
    -
    -if (goog.LOCALE == 'vai') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_vai;
    -}
    -
    -if (goog.LOCALE == 'vai_Latn' || goog.LOCALE == 'vai-Latn') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_vai_Latn;
    -}
    -
    -if (goog.LOCALE == 'vai_Latn_LR' || goog.LOCALE == 'vai-Latn-LR') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_vai_Latn;
    -}
    -
    -if (goog.LOCALE == 'vai_Vaii' || goog.LOCALE == 'vai-Vaii') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_vai;
    -}
    -
    -if (goog.LOCALE == 'vai_Vaii_LR' || goog.LOCALE == 'vai-Vaii-LR') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_vai;
    -}
    -
    -if (goog.LOCALE == 've') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ve;
    -}
    -
    -if (goog.LOCALE == 've_ZA' || goog.LOCALE == 've-ZA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_ve;
    -}
    -
    -if (goog.LOCALE == 'vi_VN' || goog.LOCALE == 'vi-VN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_vi_VN;
    -}
    -
    -if (goog.LOCALE == 'vo') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_vo;
    -}
    -
    -if (goog.LOCALE == 'vo_001' || goog.LOCALE == 'vo-001') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_vo;
    -}
    -
    -if (goog.LOCALE == 'vun') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_vun;
    -}
    -
    -if (goog.LOCALE == 'vun_TZ' || goog.LOCALE == 'vun-TZ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_vun;
    -}
    -
    -if (goog.LOCALE == 'wae') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_wae;
    -}
    -
    -if (goog.LOCALE == 'wae_CH' || goog.LOCALE == 'wae-CH') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_wae;
    -}
    -
    -if (goog.LOCALE == 'xog') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_xog;
    -}
    -
    -if (goog.LOCALE == 'xog_UG' || goog.LOCALE == 'xog-UG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_xog;
    -}
    -
    -if (goog.LOCALE == 'yav') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_yav;
    -}
    -
    -if (goog.LOCALE == 'yav_CM' || goog.LOCALE == 'yav-CM') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_yav;
    -}
    -
    -if (goog.LOCALE == 'yi') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_yi;
    -}
    -
    -if (goog.LOCALE == 'yi_001' || goog.LOCALE == 'yi-001') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_yi;
    -}
    -
    -if (goog.LOCALE == 'yo') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_yo;
    -}
    -
    -if (goog.LOCALE == 'yo_BJ' || goog.LOCALE == 'yo-BJ') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_yo_BJ;
    -}
    -
    -if (goog.LOCALE == 'yo_NG' || goog.LOCALE == 'yo-NG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_yo;
    -}
    -
    -if (goog.LOCALE == 'zgh') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_zgh;
    -}
    -
    -if (goog.LOCALE == 'zgh_MA' || goog.LOCALE == 'zgh-MA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_zgh;
    -}
    -
    -if (goog.LOCALE == 'zh_Hans' || goog.LOCALE == 'zh-Hans') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_zh_Hans;
    -}
    -
    -if (goog.LOCALE == 'zh_Hans_CN' || goog.LOCALE == 'zh-Hans-CN') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_zh_Hans;
    -}
    -
    -if (goog.LOCALE == 'zh_Hans_HK' || goog.LOCALE == 'zh-Hans-HK') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_zh_Hans_HK;
    -}
    -
    -if (goog.LOCALE == 'zh_Hans_MO' || goog.LOCALE == 'zh-Hans-MO') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_zh_Hans_MO;
    -}
    -
    -if (goog.LOCALE == 'zh_Hans_SG' || goog.LOCALE == 'zh-Hans-SG') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_zh_Hans_SG;
    -}
    -
    -if (goog.LOCALE == 'zh_Hant' || goog.LOCALE == 'zh-Hant') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_zh_Hant;
    -}
    -
    -if (goog.LOCALE == 'zh_Hant_HK' || goog.LOCALE == 'zh-Hant-HK') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_zh_Hant_HK;
    -}
    -
    -if (goog.LOCALE == 'zh_Hant_MO' || goog.LOCALE == 'zh-Hant-MO') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_zh_Hant_MO;
    -}
    -
    -if (goog.LOCALE == 'zh_Hant_TW' || goog.LOCALE == 'zh-Hant-TW') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_zh_Hant;
    -}
    -
    -if (goog.LOCALE == 'zu_ZA' || goog.LOCALE == 'zu-ZA') {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_zu_ZA;
    -}
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/graphemebreak.js b/src/database/third_party/closure-library/closure/goog/i18n/graphemebreak.js
    deleted file mode 100644
    index c5eb9ef4566..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/graphemebreak.js
    +++ /dev/null
    @@ -1,214 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Detect Grapheme Cluster Break in a pair of codepoints. Follows
    - * Unicode 5.1 UAX#29. Tailoring for Virama × Indic Consonants is used.
    - *
    - */
    -
    -goog.provide('goog.i18n.GraphemeBreak');
    -goog.require('goog.structs.InversionMap');
    -
    -
    -/**
    - * Enum for all Grapheme Cluster Break properties.
    - * These enums directly corresponds to Grapheme_Cluster_Break property values
    - * mentioned in http://unicode.org/reports/tr29 table 2. VIRAMA and
    - * INDIC_CONSONANT are for the Virama × Base tailoring mentioned in the notes.
    - *
    - * CR and LF are moved to the bottom of the list because they occur only once
    - * and so good candidates to take 2 decimal digit values.
    - * @enum {number}
    - * @protected
    - */
    -goog.i18n.GraphemeBreak.property = {
    -  ANY: 0,
    -  CONTROL: 1,
    -  EXTEND: 2,
    -  PREPEND: 3,
    -  SPACING_MARK: 4,
    -  INDIC_CONSONANT: 5,
    -  VIRAMA: 6,
    -  L: 7,
    -  V: 8,
    -  T: 9,
    -  LV: 10,
    -  LVT: 11,
    -  CR: 12,
    -  LF: 13,
    -  REGIONAL_INDICATOR: 14
    -};
    -
    -
    -/**
    - * Grapheme Cluster Break property values for all codepoints as inversion map.
    - * Constructed lazily.
    - *
    - * @type {goog.structs.InversionMap}
    - * @private
    - */
    -goog.i18n.GraphemeBreak.inversions_ = null;
    -
    -
    -/**
    - * There are two kinds of grapheme clusters: 1) Legacy 2)Extended. This method
    - * is to check for legacy rules.
    - *
    - * @param {number} prop_a The property enum value of the first character.
    - * @param {number} prop_b The property enum value of the second character.
    - * @return {boolean} True if a & b do not form a cluster; False otherwise.
    - * @private
    - */
    -goog.i18n.GraphemeBreak.applyLegacyBreakRules_ = function(prop_a, prop_b) {
    -
    -  var prop = goog.i18n.GraphemeBreak.property;
    -
    -  if (prop_a == prop.CR && prop_b == prop.LF) {
    -    return false;
    -  }
    -  if (prop_a == prop.CONTROL || prop_a == prop.CR || prop_a == prop.LF) {
    -    return true;
    -  }
    -  if (prop_b == prop.CONTROL || prop_b == prop.CR || prop_b == prop.LF) {
    -    return true;
    -  }
    -  if ((prop_a == prop.L) &&
    -      (prop_b == prop.L || prop_b == prop.V ||
    -      prop_b == prop.LV || prop_b == prop.LVT)) {
    -    return false;
    -  }
    -  if ((prop_a == prop.LV || prop_a == prop.V) &&
    -      (prop_b == prop.V || prop_b == prop.T)) {
    -    return false;
    -  }
    -  if ((prop_a == prop.LVT || prop_a == prop.T) && (prop_b == prop.T)) {
    -    return false;
    -  }
    -  if (prop_b == prop.EXTEND || prop_b == prop.VIRAMA) {
    -    return false;
    -  }
    -  if (prop_a == prop.VIRAMA && prop_b == prop.INDIC_CONSONANT) {
    -    return false;
    -  }
    -  return true;
    -};
    -
    -
    -/**
    - * Method to return property enum value of the codepoint. If it is Hangul LV or
    - * LVT, then it is computed; for the rest it is picked from the inversion map.
    - * @param {number} acode The code point value of the character.
    - * @return {number} Property enum value of codepoint.
    - * @private
    - */
    -goog.i18n.GraphemeBreak.getBreakProp_ = function(acode) {
    -  if (0xAC00 <= acode && acode <= 0xD7A3) {
    -    var prop = goog.i18n.GraphemeBreak.property;
    -    if (acode % 0x1C == 0x10) {
    -      return prop.LV;
    -    }
    -    return prop.LVT;
    -  } else {
    -    if (!goog.i18n.GraphemeBreak.inversions_) {
    -      goog.i18n.GraphemeBreak.inversions_ = new goog.structs.InversionMap(
    -          [0, 10, 1, 2, 1, 18, 95, 33, 13, 1, 594, 112, 275, 7, 263, 45, 1, 1,
    -           1, 2, 1, 2, 1, 1, 56, 5, 11, 11, 48, 21, 16, 1, 101, 7, 1, 1, 6, 2,
    -           2, 1, 4, 33, 1, 1, 1, 30, 27, 91, 11, 58, 9, 34, 4, 1, 9, 1, 3, 1,
    -           5, 43, 3, 136, 31, 1, 17, 37, 1, 1, 1, 1, 3, 8, 4, 1, 2, 1, 7, 8, 2,
    -           2, 21, 8, 1, 2, 17, 39, 1, 1, 1, 2, 6, 6, 1, 9, 5, 4, 2, 2, 12, 2,
    -           15, 2, 1, 17, 39, 2, 3, 12, 4, 8, 6, 17, 2, 3, 14, 1, 17, 39, 1, 1,
    -           3, 8, 4, 1, 20, 2, 29, 1, 2, 17, 39, 1, 1, 2, 1, 6, 6, 9, 6, 4, 2,
    -           2, 13, 1, 16, 1, 18, 41, 1, 1, 1, 12, 1, 9, 1, 41, 3, 17, 37, 4, 3,
    -           5, 7, 8, 3, 2, 8, 2, 30, 2, 17, 39, 1, 1, 1, 1, 2, 1, 3, 1, 5, 1, 8,
    -           9, 1, 3, 2, 30, 2, 17, 38, 3, 1, 2, 5, 7, 1, 9, 1, 10, 2, 30, 2, 22,
    -           48, 5, 1, 2, 6, 7, 19, 2, 13, 46, 2, 1, 1, 1, 6, 1, 12, 8, 50, 46,
    -           2, 1, 1, 1, 9, 11, 6, 14, 2, 58, 2, 27, 1, 1, 1, 1, 1, 4, 2, 49, 14,
    -           1, 4, 1, 1, 2, 5, 48, 9, 1, 57, 33, 12, 4, 1, 6, 1, 2, 2, 2, 1, 16,
    -           2, 4, 2, 2, 4, 3, 1, 3, 2, 7, 3, 4, 13, 1, 1, 1, 2, 6, 1, 1, 14, 1,
    -           98, 96, 72, 88, 349, 3, 931, 15, 2, 1, 14, 15, 2, 1, 14, 15, 2, 15,
    -           15, 14, 35, 17, 2, 1, 7, 8, 1, 2, 9, 1, 1, 9, 1, 45, 3, 155, 1, 87,
    -           31, 3, 4, 2, 9, 1, 6, 3, 20, 19, 29, 44, 9, 3, 2, 1, 69, 23, 2, 3,
    -           4, 45, 6, 2, 1, 1, 1, 8, 1, 1, 1, 2, 8, 6, 13, 128, 4, 1, 14, 33, 1,
    -           1, 5, 1, 1, 5, 1, 1, 1, 7, 31, 9, 12, 2, 1, 7, 23, 1, 4, 2, 2, 2, 2,
    -           2, 11, 3, 2, 36, 2, 1, 1, 2, 3, 1, 1, 3, 2, 12, 36, 8, 8, 2, 2, 21,
    -           3, 128, 3, 1, 13, 1, 7, 4, 1, 4, 2, 1, 203, 64, 523, 1, 2, 2, 24, 7,
    -           49, 16, 96, 33, 3070, 3, 141, 1, 96, 32, 554, 6, 105, 2, 30164, 4,
    -           1, 10, 33, 1, 80, 2, 272, 1, 3, 1, 4, 1, 23, 2, 2, 1, 24, 30, 4, 4,
    -           3, 8, 1, 1, 13, 2, 16, 34, 16, 1, 27, 18, 24, 24, 4, 8, 2, 23, 11,
    -           1, 1, 12, 32, 3, 1, 5, 3, 3, 36, 1, 2, 4, 2, 1, 3, 1, 69, 35, 6, 2,
    -           2, 2, 2, 12, 1, 8, 1, 1, 18, 16, 1, 3, 6, 1, 5, 48, 1, 1, 3, 2, 2,
    -           5, 2, 1, 1, 32, 9, 1, 2, 2, 5, 1, 1, 201, 14, 2, 1, 1, 9, 8, 2, 1,
    -           2, 1, 2, 1, 1, 1, 18, 11184, 27, 49, 1028, 1024, 6942, 1, 737, 16,
    -           16, 7, 216, 1, 158, 2, 89, 3, 513, 1, 2051, 15, 40, 7, 1, 1472, 1,
    -           1, 1, 53, 14, 1, 57, 2, 1, 45, 3, 4, 2, 1, 1, 2, 1, 66, 3, 36, 5, 1,
    -           6, 2, 75, 2, 1, 48, 3, 9, 1, 1, 1258, 1, 1, 1, 2, 6, 1, 1, 22681,
    -           62, 4, 25042, 1, 1, 3, 3, 1, 5, 8, 8, 2, 7, 30, 4, 148, 3, 8097, 26,
    -           790017, 255],
    -          [1, 13, 1, 12, 1, 0, 1, 0, 1, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0,
    -           2, 0, 1, 0, 2, 0, 2, 0, 2, 0, 2, 1, 0, 2, 0, 2, 0, 2, 0, 1, 0, 2, 0,
    -           2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 4, 0, 5, 2, 4, 2,
    -           0, 4, 2, 4, 6, 4, 0, 2, 5, 0, 2, 0, 5, 2, 4, 0, 5, 2, 0, 2, 4, 2, 4,
    -           6, 0, 2, 5, 0, 2, 0, 5, 0, 2, 4, 0, 5, 2, 4, 2, 6, 2, 5, 0, 2, 0, 2,
    -           4, 0, 5, 2, 0, 4, 2, 4, 6, 0, 2, 0, 2, 4, 0, 5, 2, 0, 2, 4, 2, 4, 6,
    -           2, 5, 0, 2, 0, 5, 0, 2, 0, 5, 2, 4, 2, 4, 6, 0, 2, 0, 4, 0, 5, 0, 2,
    -           4, 2, 6, 2, 5, 0, 2, 0, 4, 0, 5, 2, 0, 4, 2, 4, 2, 4, 2, 4, 2, 6, 2,
    -           5, 0, 2, 0, 4, 0, 5, 0, 2, 4, 2, 4, 6, 0, 2, 0, 2, 0, 4, 0, 5, 6, 2,
    -           4, 2, 4, 2, 4, 0, 5, 0, 2, 0, 4, 2, 6, 0, 2, 0, 5, 0, 2, 0, 4, 2, 0,
    -           2, 0, 5, 0, 2, 0, 2, 0, 2, 0, 2, 0, 4, 5, 2, 4, 2, 6, 0, 2, 0, 2, 0,
    -           2, 0, 5, 0, 2, 4, 2, 0, 6, 4, 2, 5, 0, 5, 0, 4, 2, 5, 2, 5, 0, 5, 0,
    -           5, 2, 5, 2, 0, 4, 2, 0, 2, 5, 0, 2, 0, 7, 8, 9, 0, 2, 0, 5, 2, 6, 0,
    -           5, 2, 6, 0, 5, 2, 0, 5, 2, 5, 0, 2, 4, 2, 4, 2, 4, 2, 6, 2, 0, 2, 0,
    -           2, 0, 2, 0, 5, 2, 4, 2, 4, 2, 4, 2, 0, 5, 0, 5, 0, 4, 0, 4, 0, 5, 2,
    -           4, 0, 5, 0, 5, 4, 2, 4, 2, 6, 0, 2, 0, 2, 4, 2, 0, 2, 4, 0, 5, 2, 4,
    -           2, 4, 2, 4, 2, 4, 6, 5, 0, 2, 0, 2, 4, 0, 5, 4, 2, 4, 2, 6, 4, 5, 0,
    -           5, 0, 5, 0, 2, 4, 2, 4, 2, 4, 2, 6, 0, 5, 4, 2, 4, 2, 0, 5, 0, 2, 0,
    -           2, 4, 2, 0, 2, 0, 4, 2, 0, 2, 0, 1, 2, 1, 0, 1, 0, 1, 0, 2, 0, 2, 0,
    -           6, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 6, 5, 2, 5, 4,
    -           2, 4, 0, 5, 0, 5, 0, 5, 0, 5, 0, 4, 0, 5, 4, 6, 0, 2, 0, 5, 0, 2, 0,
    -           5, 2, 4, 6, 0, 7, 2, 4, 0, 5, 0, 5, 2, 4, 2, 4, 2, 4, 6, 0, 5, 2, 4,
    -           2, 4, 2, 0, 2, 0, 2, 4, 0, 5, 0, 5, 0, 5, 0, 5, 2, 0, 2, 0, 2, 0, 2,
    -           0, 2, 0, 5, 4, 2, 4, 0, 4, 6, 0, 5, 0, 5, 0, 5, 0, 4, 2, 4, 2, 4, 0,
    -           4, 6, 0, 11, 8, 9, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1, 0, 2, 0, 1, 0, 2,
    -           0, 2, 0, 2, 6, 0, 4, 2, 4, 0, 2, 6, 0, 2, 4, 0, 4, 2, 4, 6, 2, 0, 1,
    -           0, 2, 0, 2, 4, 2, 6, 0, 2, 4, 0, 4, 2, 4, 6, 0, 2, 4, 2, 4, 2, 6, 2,
    -           0, 4, 2, 0, 2, 4, 2, 0, 4, 2, 1, 2, 0, 2, 0, 2, 0, 2, 0, 14, 0, 1,
    -           2],
    -          true);
    -    }
    -    return /** @type {number} */ (
    -        goog.i18n.GraphemeBreak.inversions_.at(acode));
    -  }
    -};
    -
    -
    -/**
    - * There are two kinds of grapheme clusters: 1) Legacy 2)Extended. This method
    - * is to check for both using a boolean flag to switch between them.
    - * @param {number} a The code point value of the first character.
    - * @param {number} b The code point value of the second character.
    - * @param {boolean=} opt_extended If true, indicates extended grapheme cluster;
    - *     If false, indicates legacy cluster.
    - * @return {boolean} True if a & b do not form a cluster; False otherwise.
    - */
    -goog.i18n.GraphemeBreak.hasGraphemeBreak = function(a, b, opt_extended) {
    -
    -  var prop_a = goog.i18n.GraphemeBreak.getBreakProp_(a);
    -  var prop_b = goog.i18n.GraphemeBreak.getBreakProp_(b);
    -  var prop = goog.i18n.GraphemeBreak.property;
    -
    -  return goog.i18n.GraphemeBreak.applyLegacyBreakRules_(prop_a, prop_b) &&
    -      !(opt_extended &&
    -          (prop_a == prop.PREPEND || prop_b == prop.SPACING_MARK));
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/graphemebreak_test.html b/src/database/third_party/closure-library/closure/goog/i18n/graphemebreak_test.html
    deleted file mode 100644
    index c40c1f53c60..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/graphemebreak_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.i18n.GraphemeBreak
    -  </title>
    -  <script type="text/javascript" src="../base.js">
    -  </script>
    -  <script type="text/javascript">
    -    goog.require('goog.i18n.GraphemeBreakTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/graphemebreak_test.js b/src/database/third_party/closure-library/closure/goog/i18n/graphemebreak_test.js
    deleted file mode 100644
    index 2cf92307c9f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/graphemebreak_test.js
    +++ /dev/null
    @@ -1,78 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.i18n.GraphemeBreakTest');
    -goog.setTestOnly('goog.i18n.GraphemeBreakTest');
    -
    -goog.require('goog.i18n.GraphemeBreak');
    -goog.require('goog.testing.jsunit');
    -
    -function testBreakNormalAscii() {
    -  assertTrue(goog.i18n.GraphemeBreak.hasGraphemeBreak('a'.charCodeAt(0),
    -      'b'.charCodeAt(0), true));
    -}
    -
    -function testBreakAsciiWithExtendedChar() {
    -  assertFalse(goog.i18n.GraphemeBreak.hasGraphemeBreak('a'.charCodeAt(0),
    -      0x0300, true));
    -}
    -
    -function testBreakSurrogates() {
    -  assertFalse(goog.i18n.GraphemeBreak.hasGraphemeBreak(0xDA00, 0xDC00, true));
    -  assertFalse(goog.i18n.GraphemeBreak.hasGraphemeBreak(0xDBFF, 0xDFFF, true));
    -}
    -
    -function testBreakHangLxL() {
    -  assertFalse(goog.i18n.GraphemeBreak.hasGraphemeBreak(0x1100, 0x1100, true));
    -}
    -
    -function testBreakHangL_T() {
    -  assertTrue(goog.i18n.GraphemeBreak.hasGraphemeBreak(0x1100, 0x11A8));
    -}
    -
    -function testBreakHangLVxV() {
    -  assertFalse(goog.i18n.GraphemeBreak.hasGraphemeBreak(0xAC00, 0x1160, true));
    -}
    -
    -function testBreakHangLV_L() {
    -  assertTrue(goog.i18n.GraphemeBreak.hasGraphemeBreak(0xAC00, 0x1100, true));
    -}
    -
    -function testBreakHangLVTxT() {
    -  assertFalse(goog.i18n.GraphemeBreak.hasGraphemeBreak(0xAC01, 0x11A8, true));
    -}
    -
    -function testBreakThaiPrependLegacy() {
    -  assertTrue(goog.i18n.GraphemeBreak.hasGraphemeBreak(0x0E40, 0x0E01));
    -}
    -
    -function testBreakThaiPrependExtended() {
    -  assertTrue(goog.i18n.GraphemeBreak.hasGraphemeBreak(0x0E40, 0x0E01, true));
    -}
    -
    -function testBreakDevaSpacingMarkLegacy() {
    -  assertTrue(goog.i18n.GraphemeBreak.hasGraphemeBreak(0x0915, 0x093E));
    -}
    -
    -function testBreakDevaSpacingMarkExtended() {
    -  assertFalse(goog.i18n.GraphemeBreak.hasGraphemeBreak(0x0915, 0x093E, true));
    -}
    -
    -function testBreakDevaViramaSpace() {
    -  assertTrue(goog.i18n.GraphemeBreak.hasGraphemeBreak(0x094D, 0x0020));
    -}
    -
    -function testBreakDevaViramaConsonant() {
    -  assertFalse(goog.i18n.GraphemeBreak.hasGraphemeBreak(0x094D, 0x0915));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/messageformat.js b/src/database/third_party/closure-library/closure/goog/i18n/messageformat.js
    deleted file mode 100644
    index 8f88370ba09..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/messageformat.js
    +++ /dev/null
    @@ -1,780 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Message/plural format library with locale support.
    - *
    - * Message format grammar:
    - *
    - * messageFormatPattern := string ( "{" messageFormatElement "}" string )*
    - * messageFormatElement := argumentIndex [ "," elementFormat ]
    - * elementFormat := "plural" "," pluralStyle
    - *                  | "selectordinal" "," ordinalStyle
    - *                  | "select" "," selectStyle
    - * pluralStyle :=  pluralFormatPattern
    - * ordinalStyle :=  selectFormatPattern
    - * selectStyle :=  selectFormatPattern
    - * pluralFormatPattern := [ "offset" ":" offsetIndex ] pluralForms*
    - * selectFormatPattern := pluralForms*
    - * pluralForms := stringKey "{" ( "{" messageFormatElement "}"|string )* "}"
    - *
    - * This is a subset of the ICU MessageFormatSyntax:
    - *   http://userguide.icu-project.org/formatparse/messages
    - * See also http://go/plurals and http://go/ordinals for internal details.
    - *
    - *
    - * Message example:
    - *
    - * I see {NUM_PEOPLE, plural, offset:1
    - *         =0 {no one at all}
    - *         =1 {{WHO}}
    - *         one {{WHO} and one other person}
    - *         other {{WHO} and # other people}}
    - * in {PLACE}.
    - *
    - * Calling format({'NUM_PEOPLE': 2, 'WHO': 'Mark', 'PLACE': 'Athens'}) would
    - * produce "I see Mark and one other person in Athens." as output.
    - *
    - * OR:
    - *
    - * {NUM_FLOOR, selectordinal,
    - *   one {Take the elevator to the #st floor.}
    - *   two {Take the elevator to the #nd floor.}
    - *   few {Take the elevator to the #rd floor.}
    - *   other {Take the elevator to the #th floor.}}
    - *
    - * Calling format({'NUM_FLOOR': 22}) would produce
    - * "Take the elevator to the 22nd floor".
    - *
    - * See messageformat_test.html for more examples.
    - */
    -
    -goog.provide('goog.i18n.MessageFormat');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.i18n.NumberFormat');
    -goog.require('goog.i18n.ordinalRules');
    -goog.require('goog.i18n.pluralRules');
    -
    -
    -
    -/**
    - * Constructor of MessageFormat.
    - * @param {string} pattern The pattern we parse and apply positional parameters
    - *     to.
    - * @constructor
    - * @final
    - */
    -goog.i18n.MessageFormat = function(pattern) {
    -  /**
    -   * All encountered literals during parse stage. Indices tell us the order of
    -   * replacement.
    -   * @type {!Array<string>}
    -   * @private
    -   */
    -  this.literals_ = [];
    -
    -  /**
    -   * Input pattern gets parsed into objects for faster formatting.
    -   * @type {!Array<!Object>}
    -   * @private
    -   */
    -  this.parsedPattern_ = [];
    -
    -  /**
    -   * Locale aware number formatter.
    -   * @type {goog.i18n.NumberFormat}
    -   * @private
    -   */
    -  this.numberFormatter_ = new goog.i18n.NumberFormat(
    -      goog.i18n.NumberFormat.Format.DECIMAL);
    -
    -  this.parsePattern_(pattern);
    -};
    -
    -
    -/**
    - * Literal strings, including '', are replaced with \uFDDF_x_ for
    - * parsing purposes, and recovered during format phase.
    - * \uFDDF is a Unicode nonprinting character, not expected to be found in the
    - * typical message.
    - * @type {string}
    - * @private
    - */
    -goog.i18n.MessageFormat.LITERAL_PLACEHOLDER_ = '\uFDDF_';
    -
    -
    -/**
    - * Marks a string and block during parsing.
    - * @enum {number}
    - * @private
    - */
    -goog.i18n.MessageFormat.Element_ = {
    -  STRING: 0,
    -  BLOCK: 1
    -};
    -
    -
    -/**
    - * Block type.
    - * @enum {number}
    - * @private
    - */
    -goog.i18n.MessageFormat.BlockType_ = {
    -  PLURAL: 0,
    -  ORDINAL: 1,
    -  SELECT: 2,
    -  SIMPLE: 3,
    -  STRING: 4,
    -  UNKNOWN: 5
    -};
    -
    -
    -/**
    - * Mandatory option in both select and plural form.
    - * @type {string}
    - * @private
    - */
    -goog.i18n.MessageFormat.OTHER_ = 'other';
    -
    -
    -/**
    - * Regular expression for looking for string literals.
    - * @type {RegExp}
    - * @private
    - */
    -goog.i18n.MessageFormat.REGEX_LITERAL_ = new RegExp("'([{}#].*?)'", 'g');
    -
    -
    -/**
    - * Regular expression for looking for '' in the message.
    - * @type {RegExp}
    - * @private
    - */
    -goog.i18n.MessageFormat.REGEX_DOUBLE_APOSTROPHE_ = new RegExp("''", 'g');
    -
    -
    -/**
    - * Formats a message, treating '#' with special meaning representing
    - * the number (plural_variable - offset).
    - * @param {!Object} namedParameters Parameters that either
    - *     influence the formatting or are used as actual data.
    - *     I.e. in call to fmt.format({'NUM_PEOPLE': 5, 'NAME': 'Angela'}),
    - *     object {'NUM_PEOPLE': 5, 'NAME': 'Angela'} holds positional parameters.
    - *     1st parameter could mean 5 people, which could influence plural format,
    - *     and 2nd parameter is just a data to be printed out in proper position.
    - * @return {string} Formatted message.
    - */
    -goog.i18n.MessageFormat.prototype.format = function(namedParameters) {
    -  return this.format_(namedParameters, false);
    -};
    -
    -
    -/**
    - * Formats a message, treating '#' as literary character.
    - * @param {!Object} namedParameters Parameters that either
    - *     influence the formatting or are used as actual data.
    - *     I.e. in call to fmt.format({'NUM_PEOPLE': 5, 'NAME': 'Angela'}),
    - *     object {'NUM_PEOPLE': 5, 'NAME': 'Angela'} holds positional parameters.
    - *     1st parameter could mean 5 people, which could influence plural format,
    - *     and 2nd parameter is just a data to be printed out in proper position.
    - * @return {string} Formatted message.
    - */
    -goog.i18n.MessageFormat.prototype.formatIgnoringPound =
    -    function(namedParameters) {
    -  return this.format_(namedParameters, true);
    -};
    -
    -
    -/**
    - * Formats a message.
    - * @param {!Object} namedParameters Parameters that either
    - *     influence the formatting or are used as actual data.
    - *     I.e. in call to fmt.format({'NUM_PEOPLE': 5, 'NAME': 'Angela'}),
    - *     object {'NUM_PEOPLE': 5, 'NAME': 'Angela'} holds positional parameters.
    - *     1st parameter could mean 5 people, which could influence plural format,
    - *     and 2nd parameter is just a data to be printed out in proper position.
    - * @param {boolean} ignorePound If true, treat '#' in plural messages as a
    - *     literary character, else treat it as an ICU syntax character, resolving
    - *     to the number (plural_variable - offset).
    - * @return {string} Formatted message.
    - * @private
    - */
    -goog.i18n.MessageFormat.prototype.format_ =
    -    function(namedParameters, ignorePound) {
    -  if (this.parsedPattern_.length == 0) {
    -    return '';
    -  }
    -
    -  var result = [];
    -  this.formatBlock_(this.parsedPattern_, namedParameters, ignorePound, result);
    -  var message = result.join('');
    -
    -  if (!ignorePound) {
    -    goog.asserts.assert(message.search('#') == -1, 'Not all # were replaced.');
    -  }
    -
    -  while (this.literals_.length > 0) {
    -    message = message.replace(this.buildPlaceholder_(this.literals_),
    -                              this.literals_.pop());
    -  }
    -
    -  return message;
    -};
    -
    -
    -/**
    - * Parses generic block and returns a formatted string.
    - * @param {!Array<!Object>} parsedPattern Holds parsed tree.
    - * @param {!Object} namedParameters Parameters that either influence
    - *     the formatting or are used as actual data.
    - * @param {boolean} ignorePound If true, treat '#' in plural messages as a
    - *     literary character, else treat it as an ICU syntax character, resolving
    - *     to the number (plural_variable - offset).
    - * @param {!Array<!string>} result Each formatting stage appends its product
    - *     to the result.
    - * @private
    - */
    -goog.i18n.MessageFormat.prototype.formatBlock_ = function(
    -    parsedPattern, namedParameters, ignorePound, result) {
    -  for (var i = 0; i < parsedPattern.length; i++) {
    -    switch (parsedPattern[i].type) {
    -      case goog.i18n.MessageFormat.BlockType_.STRING:
    -        result.push(parsedPattern[i].value);
    -        break;
    -      case goog.i18n.MessageFormat.BlockType_.SIMPLE:
    -        var pattern = parsedPattern[i].value;
    -        this.formatSimplePlaceholder_(pattern, namedParameters, result);
    -        break;
    -      case goog.i18n.MessageFormat.BlockType_.SELECT:
    -        var pattern = parsedPattern[i].value;
    -        this.formatSelectBlock_(pattern, namedParameters, ignorePound, result);
    -        break;
    -      case goog.i18n.MessageFormat.BlockType_.PLURAL:
    -        var pattern = parsedPattern[i].value;
    -        this.formatPluralOrdinalBlock_(pattern,
    -                                       namedParameters,
    -                                       goog.i18n.pluralRules.select,
    -                                       ignorePound,
    -                                       result);
    -        break;
    -      case goog.i18n.MessageFormat.BlockType_.ORDINAL:
    -        var pattern = parsedPattern[i].value;
    -        this.formatPluralOrdinalBlock_(pattern,
    -                                       namedParameters,
    -                                       goog.i18n.ordinalRules.select,
    -                                       ignorePound,
    -                                       result);
    -        break;
    -      default:
    -        goog.asserts.fail('Unrecognized block type: ' + parsedPattern[i].type);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Formats simple placeholder.
    - * @param {!Object} parsedPattern JSON object containing placeholder info.
    - * @param {!Object} namedParameters Parameters that are used as actual data.
    - * @param {!Array<!string>} result Each formatting stage appends its product
    - *     to the result.
    - * @private
    - */
    -goog.i18n.MessageFormat.prototype.formatSimplePlaceholder_ = function(
    -    parsedPattern, namedParameters, result) {
    -  var value = namedParameters[parsedPattern];
    -  if (!goog.isDef(value)) {
    -    result.push('Undefined parameter - ' + parsedPattern);
    -    return;
    -  }
    -
    -  // Don't push the value yet, it may contain any of # { } in it which
    -  // will break formatter. Insert a placeholder and replace at the end.
    -  this.literals_.push(value);
    -  result.push(this.buildPlaceholder_(this.literals_));
    -};
    -
    -
    -/**
    - * Formats select block. Only one option is selected.
    - * @param {!Object} parsedPattern JSON object containing select block info.
    - * @param {!Object} namedParameters Parameters that either influence
    - *     the formatting or are used as actual data.
    - * @param {boolean} ignorePound If true, treat '#' in plural messages as a
    - *     literary character, else treat it as an ICU syntax character, resolving
    - *     to the number (plural_variable - offset).
    - * @param {!Array<!string>} result Each formatting stage appends its product
    - *     to the result.
    - * @private
    - */
    -goog.i18n.MessageFormat.prototype.formatSelectBlock_ = function(
    -    parsedPattern, namedParameters, ignorePound, result) {
    -  var argumentIndex = parsedPattern.argumentIndex;
    -  if (!goog.isDef(namedParameters[argumentIndex])) {
    -    result.push('Undefined parameter - ' + argumentIndex);
    -    return;
    -  }
    -
    -  var option = parsedPattern[namedParameters[argumentIndex]];
    -  if (!goog.isDef(option)) {
    -    option = parsedPattern[goog.i18n.MessageFormat.OTHER_];
    -    goog.asserts.assertArray(
    -        option, 'Invalid option or missing other option for select block.');
    -  }
    -
    -  this.formatBlock_(option, namedParameters, ignorePound, result);
    -};
    -
    -
    -/**
    - * Formats plural or selectordinal block. Only one option is selected and all #
    - * are replaced.
    - * @param {!Object} parsedPattern JSON object containing plural block info.
    - * @param {!Object} namedParameters Parameters that either influence
    - *     the formatting or are used as actual data.
    - * @param {!function(number, number=):string} pluralSelector  A select function
    - *     from goog.i18n.pluralRules or goog.i18n.ordinalRules which determines
    - *     which plural/ordinal form to use based on the input number's cardinality.
    - * @param {boolean} ignorePound If true, treat '#' in plural messages as a
    - *     literary character, else treat it as an ICU syntax character, resolving
    - *     to the number (plural_variable - offset).
    - * @param {!Array<!string>} result Each formatting stage appends its product
    - *     to the result.
    - * @private
    - */
    -goog.i18n.MessageFormat.prototype.formatPluralOrdinalBlock_ = function(
    -    parsedPattern, namedParameters, pluralSelector, ignorePound, result) {
    -  var argumentIndex = parsedPattern.argumentIndex;
    -  var argumentOffset = parsedPattern.argumentOffset;
    -  var pluralValue = +namedParameters[argumentIndex];
    -  if (isNaN(pluralValue)) {
    -    // TODO(user): Distinguish between undefined and invalid parameters.
    -    result.push('Undefined or invalid parameter - ' + argumentIndex);
    -    return;
    -  }
    -  var diff = pluralValue - argumentOffset;
    -
    -  // Check if there is an exact match.
    -  var option = parsedPattern[namedParameters[argumentIndex]];
    -  if (!goog.isDef(option)) {
    -    goog.asserts.assert(diff >= 0, 'Argument index smaller than offset.');
    -    var item;
    -    if (this.numberFormatter_.getMinimumFractionDigits) { // number formatter?
    -      // If we know the number of fractional digits we can make better decisions
    -      // We can decide (for instance) between "1 dollar" and "1.00 dollars".
    -      item = pluralSelector(diff,
    -          this.numberFormatter_.getMinimumFractionDigits());
    -    } else {
    -      item = pluralSelector(diff);
    -    }
    -    goog.asserts.assertString(item, 'Invalid plural key.');
    -
    -    option = parsedPattern[item];
    -
    -    // If option is not provided fall back to "other".
    -    if (!goog.isDef(option)) {
    -      option = parsedPattern[goog.i18n.MessageFormat.OTHER_];
    -    }
    -
    -    goog.asserts.assertArray(
    -        option, 'Invalid option or missing other option for plural block.');
    -  }
    -
    -  var pluralResult = [];
    -  this.formatBlock_(option, namedParameters, ignorePound, pluralResult);
    -  var plural = pluralResult.join('');
    -  goog.asserts.assertString(plural, 'Empty block in plural.');
    -  if (ignorePound) {
    -    result.push(plural);
    -  } else {
    -    var localeAwareDiff = this.numberFormatter_.format(diff);
    -    result.push(plural.replace(/#/g, localeAwareDiff));
    -  }
    -};
    -
    -
    -/**
    - * Parses input pattern into an array, for faster reformatting with
    - * different input parameters.
    - * Parsing is locale independent.
    - * @param {string} pattern MessageFormat pattern to parse.
    - * @private
    - */
    -goog.i18n.MessageFormat.prototype.parsePattern_ = function(pattern) {
    -  if (pattern) {
    -    pattern = this.insertPlaceholders_(pattern);
    -
    -    this.parsedPattern_ = this.parseBlock_(pattern);
    -  }
    -};
    -
    -
    -/**
    - * Replaces string literals with literal placeholders.
    - * Literals are string of the form '}...', '{...' and '#...' where ... is
    - * set of characters not containing '
    - * Builds a dictionary so we can recover literals during format phase.
    - * @param {string} pattern Pattern to clean up.
    - * @return {string} Pattern with literals replaced with placeholders.
    - * @private
    - */
    -goog.i18n.MessageFormat.prototype.insertPlaceholders_ = function(pattern) {
    -  var literals = this.literals_;
    -  var buildPlaceholder = goog.bind(this.buildPlaceholder_, this);
    -
    -  // First replace '' with single quote placeholder since they can be found
    -  // inside other literals.
    -  pattern = pattern.replace(
    -      goog.i18n.MessageFormat.REGEX_DOUBLE_APOSTROPHE_,
    -      function() {
    -        literals.push("'");
    -        return buildPlaceholder(literals);
    -      });
    -
    -  pattern = pattern.replace(
    -      goog.i18n.MessageFormat.REGEX_LITERAL_,
    -      function(match, text) {
    -        literals.push(text);
    -        return buildPlaceholder(literals);
    -      });
    -
    -  return pattern;
    -};
    -
    -
    -/**
    - * Breaks pattern into strings and top level {...} blocks.
    - * @param {string} pattern (sub)Pattern to be broken.
    - * @return {!Array<Object>} Each item is {type, value}.
    - * @private
    - */
    -goog.i18n.MessageFormat.prototype.extractParts_ = function(pattern) {
    -  var prevPos = 0;
    -  var inBlock = false;
    -  var braceStack = [];
    -  var results = [];
    -
    -  var braces = /[{}]/g;
    -  braces.lastIndex = 0;  // lastIndex doesn't get set to 0 so we have to.
    -  var match;
    -
    -  while (match = braces.exec(pattern)) {
    -    var pos = match.index;
    -    if (match[0] == '}') {
    -      var brace = braceStack.pop();
    -      goog.asserts.assert(goog.isDef(brace) && brace == '{',
    -                          'No matching { for }.');
    -
    -      if (braceStack.length == 0) {
    -        // End of the block.
    -        var part = {};
    -        part.type = goog.i18n.MessageFormat.Element_.BLOCK;
    -        part.value = pattern.substring(prevPos, pos);
    -        results.push(part);
    -        prevPos = pos + 1;
    -        inBlock = false;
    -      }
    -    } else {
    -      if (braceStack.length == 0) {
    -        inBlock = true;
    -        var substring = pattern.substring(prevPos, pos);
    -        if (substring != '') {
    -          results.push({
    -            type: goog.i18n.MessageFormat.Element_.STRING,
    -            value: substring
    -          });
    -        }
    -        prevPos = pos + 1;
    -      }
    -      braceStack.push('{');
    -    }
    -  }
    -
    -  // Take care of the final string, and check if the braceStack is empty.
    -  goog.asserts.assert(braceStack.length == 0,
    -                      'There are mismatched { or } in the pattern.');
    -
    -  var substring = pattern.substring(prevPos);
    -  if (substring != '') {
    -    results.push({
    -      type: goog.i18n.MessageFormat.Element_.STRING,
    -      value: substring
    -    });
    -  }
    -
    -  return results;
    -};
    -
    -
    -/**
    - * A regular expression to parse the plural block, extracting the argument
    - * index and offset (if any).
    - * @type {RegExp}
    - * @private
    - */
    -goog.i18n.MessageFormat.PLURAL_BLOCK_RE_ =
    -    /^\s*(\w+)\s*,\s*plural\s*,(?:\s*offset:(\d+))?/;
    -
    -
    -/**
    - * A regular expression to parse the ordinal block, extracting the argument
    - * index.
    - * @type {RegExp}
    - * @private
    - */
    -goog.i18n.MessageFormat.ORDINAL_BLOCK_RE_ = /^\s*(\w+)\s*,\s*selectordinal\s*,/;
    -
    -
    -/**
    - * A regular expression to parse the select block, extracting the argument
    - * index.
    - * @type {RegExp}
    - * @private
    - */
    -goog.i18n.MessageFormat.SELECT_BLOCK_RE_ = /^\s*(\w+)\s*,\s*select\s*,/;
    -
    -
    -/**
    - * Detects which type of a block is the pattern.
    - * @param {string} pattern Content of the block.
    - * @return {goog.i18n.MessageFormat.BlockType_} One of the block types.
    - * @private
    - */
    -goog.i18n.MessageFormat.prototype.parseBlockType_ = function(pattern) {
    -  if (goog.i18n.MessageFormat.PLURAL_BLOCK_RE_.test(pattern)) {
    -    return goog.i18n.MessageFormat.BlockType_.PLURAL;
    -  }
    -
    -  if (goog.i18n.MessageFormat.ORDINAL_BLOCK_RE_.test(pattern)) {
    -    return goog.i18n.MessageFormat.BlockType_.ORDINAL;
    -  }
    -
    -  if (goog.i18n.MessageFormat.SELECT_BLOCK_RE_.test(pattern)) {
    -    return goog.i18n.MessageFormat.BlockType_.SELECT;
    -  }
    -
    -  if (/^\s*\w+\s*/.test(pattern)) {
    -    return goog.i18n.MessageFormat.BlockType_.SIMPLE;
    -  }
    -
    -  return goog.i18n.MessageFormat.BlockType_.UNKNOWN;
    -};
    -
    -
    -/**
    - * Parses generic block.
    - * @param {string} pattern Content of the block to parse.
    - * @return {!Array<!Object>} Subblocks marked as strings, select...
    - * @private
    - */
    -goog.i18n.MessageFormat.prototype.parseBlock_ = function(pattern) {
    -  var result = [];
    -  var parts = this.extractParts_(pattern);
    -  for (var i = 0; i < parts.length; i++) {
    -    var block = {};
    -    if (goog.i18n.MessageFormat.Element_.STRING == parts[i].type) {
    -      block.type = goog.i18n.MessageFormat.BlockType_.STRING;
    -      block.value = parts[i].value;
    -    } else if (goog.i18n.MessageFormat.Element_.BLOCK == parts[i].type) {
    -      var blockType = this.parseBlockType_(parts[i].value);
    -
    -      switch (blockType) {
    -        case goog.i18n.MessageFormat.BlockType_.SELECT:
    -          block.type = goog.i18n.MessageFormat.BlockType_.SELECT;
    -          block.value = this.parseSelectBlock_(parts[i].value);
    -          break;
    -        case goog.i18n.MessageFormat.BlockType_.PLURAL:
    -          block.type = goog.i18n.MessageFormat.BlockType_.PLURAL;
    -          block.value = this.parsePluralBlock_(parts[i].value);
    -          break;
    -        case goog.i18n.MessageFormat.BlockType_.ORDINAL:
    -          block.type = goog.i18n.MessageFormat.BlockType_.ORDINAL;
    -          block.value = this.parseOrdinalBlock_(parts[i].value);
    -          break;
    -        case goog.i18n.MessageFormat.BlockType_.SIMPLE:
    -          block.type = goog.i18n.MessageFormat.BlockType_.SIMPLE;
    -          block.value = parts[i].value;
    -          break;
    -        default:
    -          goog.asserts.fail(
    -              'Unknown block type for pattern: ' + parts[i].value);
    -      }
    -    } else {
    -      goog.asserts.fail('Unknown part of the pattern.');
    -    }
    -    result.push(block);
    -  }
    -
    -  return result;
    -};
    -
    -
    -/**
    - * Parses a select type of a block and produces JSON object for it.
    - * @param {string} pattern Subpattern that needs to be parsed as select pattern.
    - * @return {!Object} Object with select block info.
    - * @private
    - */
    -goog.i18n.MessageFormat.prototype.parseSelectBlock_ = function(pattern) {
    -  var argumentIndex = '';
    -  var replaceRegex = goog.i18n.MessageFormat.SELECT_BLOCK_RE_;
    -  pattern = pattern.replace(replaceRegex, function(string, name) {
    -    argumentIndex = name;
    -    return '';
    -  });
    -  var result = {};
    -  result.argumentIndex = argumentIndex;
    -
    -  var parts = this.extractParts_(pattern);
    -  // Looking for (key block)+ sequence. One of the keys has to be "other".
    -  var pos = 0;
    -  while (pos < parts.length) {
    -    var key = parts[pos].value;
    -    goog.asserts.assertString(key, 'Missing select key element.');
    -
    -    pos++;
    -    goog.asserts.assert(pos < parts.length,
    -                        'Missing or invalid select value element.');
    -
    -    if (goog.i18n.MessageFormat.Element_.BLOCK == parts[pos].type) {
    -      var value = this.parseBlock_(parts[pos].value);
    -    } else {
    -      goog.asserts.fail('Expected block type.');
    -    }
    -    result[key.replace(/\s/g, '')] = value;
    -    pos++;
    -  }
    -
    -  goog.asserts.assertArray(result[goog.i18n.MessageFormat.OTHER_],
    -                           'Missing other key in select statement.');
    -  return result;
    -};
    -
    -
    -/**
    - * Parses a plural type of a block and produces JSON object for it.
    - * @param {string} pattern Subpattern that needs to be parsed as plural pattern.
    - * @return {!Object} Object with select block info.
    - * @private
    - */
    -goog.i18n.MessageFormat.prototype.parsePluralBlock_ = function(pattern) {
    -  var argumentIndex = '';
    -  var argumentOffset = 0;
    -  var replaceRegex = goog.i18n.MessageFormat.PLURAL_BLOCK_RE_;
    -  pattern = pattern.replace(replaceRegex, function(string, name, offset) {
    -    argumentIndex = name;
    -    if (offset) {
    -      argumentOffset = parseInt(offset, 10);
    -    }
    -    return '';
    -  });
    -
    -  var result = {};
    -  result.argumentIndex = argumentIndex;
    -  result.argumentOffset = argumentOffset;
    -
    -  var parts = this.extractParts_(pattern);
    -  // Looking for (key block)+ sequence.
    -  var pos = 0;
    -  while (pos < parts.length) {
    -    var key = parts[pos].value;
    -    goog.asserts.assertString(key, 'Missing plural key element.');
    -
    -    pos++;
    -    goog.asserts.assert(pos < parts.length,
    -                        'Missing or invalid plural value element.');
    -
    -    if (goog.i18n.MessageFormat.Element_.BLOCK == parts[pos].type) {
    -      var value = this.parseBlock_(parts[pos].value);
    -    } else {
    -      goog.asserts.fail('Expected block type.');
    -    }
    -    result[key.replace(/\s*(?:=)?(\w+)\s*/, '$1')] = value;
    -    pos++;
    -  }
    -
    -  goog.asserts.assertArray(result[goog.i18n.MessageFormat.OTHER_],
    -                           'Missing other key in plural statement.');
    -
    -  return result;
    -};
    -
    -
    -/**
    - * Parses an ordinal type of a block and produces JSON object for it.
    - * For example the input string:
    - *  '{FOO, selectordinal, one {Message A}other {Message B}}'
    - * Should result in the output object:
    - * {
    - *   argumentIndex: 'FOO',
    - *   argumentOffest: 0,
    - *   one: [ { type: 4, value: 'Message A' } ],
    - *   other: [ { type: 4, value: 'Message B' } ]
    - * }
    - * @param {string} pattern Subpattern that needs to be parsed as plural pattern.
    - * @return {!Object} Object with select block info.
    - * @private
    - */
    -goog.i18n.MessageFormat.prototype.parseOrdinalBlock_ = function(pattern) {
    -  var argumentIndex = '';
    -  var replaceRegex = goog.i18n.MessageFormat.ORDINAL_BLOCK_RE_;
    -  pattern = pattern.replace(replaceRegex, function(string, name) {
    -    argumentIndex = name;
    -    return '';
    -  });
    -
    -  var result = {};
    -  result.argumentIndex = argumentIndex;
    -  result.argumentOffset = 0;
    -
    -  var parts = this.extractParts_(pattern);
    -  // Looking for (key block)+ sequence.
    -  var pos = 0;
    -  while (pos < parts.length) {
    -    var key = parts[pos].value;
    -    goog.asserts.assertString(key, 'Missing ordinal key element.');
    -
    -    pos++;
    -    goog.asserts.assert(pos < parts.length,
    -                        'Missing or invalid ordinal value element.');
    -
    -    if (goog.i18n.MessageFormat.Element_.BLOCK == parts[pos].type) {
    -      var value = this.parseBlock_(parts[pos].value);
    -    } else {
    -      goog.asserts.fail('Expected block type.');
    -    }
    -    result[key.replace(/\s*(?:=)?(\w+)\s*/, '$1')] = value;
    -    pos++;
    -  }
    -
    -  goog.asserts.assertArray(result[goog.i18n.MessageFormat.OTHER_],
    -                           'Missing other key in selectordinal statement.');
    -
    -  return result;
    -};
    -
    -
    -/**
    - * Builds a placeholder from the last index of the array.
    - * @param {!Array<string>} literals All literals encountered during parse.
    - * @return {string} \uFDDF_ + last index + _.
    - * @private
    - */
    -goog.i18n.MessageFormat.prototype.buildPlaceholder_ = function(literals) {
    -  goog.asserts.assert(literals.length > 0, 'Literal array is empty.');
    -
    -  var index = (literals.length - 1).toString(10);
    -  return goog.i18n.MessageFormat.LITERAL_PLACEHOLDER_ + index + '_';
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/messageformat_test.html b/src/database/third_party/closure-library/closure/goog/i18n/messageformat_test.html
    deleted file mode 100644
    index 3d85939080f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/messageformat_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.i18n.MessageFormat
    -  </title>
    -  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.i18n.MessageFormatTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/messageformat_test.js b/src/database/third_party/closure-library/closure/goog/i18n/messageformat_test.js
    deleted file mode 100644
    index 2dadb47a2e3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/messageformat_test.js
    +++ /dev/null
    @@ -1,464 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.i18n.MessageFormatTest');
    -goog.setTestOnly('goog.i18n.MessageFormatTest');
    -
    -goog.require('goog.i18n.MessageFormat');
    -goog.require('goog.i18n.NumberFormatSymbols_hr');
    -goog.require('goog.i18n.pluralRules');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -
    -// Testing stubs that autoreset after each test run.
    -var stubs = new goog.testing.PropertyReplacer();
    -
    -function tearDown() {
    -  stubs.reset();
    -}
    -
    -function testEmptyPattern() {
    -  var fmt = new goog.i18n.MessageFormat('');
    -  assertEquals('', fmt.format({}));
    -}
    -
    -function testMissingLeftCurlyBrace() {
    -  var err = assertThrows(function() {
    -    new goog.i18n.MessageFormat('\'\'{}}');
    -  });
    -  assertEquals('Assertion failed: No matching { for }.', err.message);
    -}
    -
    -function testTooManyLeftCurlyBraces() {
    -  var err = assertThrows(function() {
    -    new goog.i18n.MessageFormat('{} {');
    -  });
    -  assertEquals('Assertion failed: There are mismatched { or } in the pattern.',
    -      err.message);
    -}
    -
    -function testSimpleReplacement() {
    -  var fmt = new goog.i18n.MessageFormat('New York in {SEASON} is nice.');
    -  assertEquals('New York in the Summer is nice.',
    -               fmt.format({'SEASON': 'the Summer'}));
    -}
    -
    -function testSimpleSelect() {
    -  var fmt = new goog.i18n.MessageFormat('{GENDER, select,' +
    -      'male {His} ' +
    -      'female {Her} ' +
    -      'other {Its}}' +
    -      ' bicycle is {GENDER, select, male {blue} female {red} other {green}}.');
    -
    -  assertEquals('His bicycle is blue.', fmt.format({'GENDER': 'male'}));
    -  assertEquals('Her bicycle is red.', fmt.format({'GENDER': 'female'}));
    -  assertEquals('Its bicycle is green.', fmt.format({'GENDER': 'other'}));
    -  assertEquals('Its bicycle is green.', fmt.format({'GENDER': 'whatever'}));
    -}
    -
    -function testSimplePlural() {
    -  var fmt = new goog.i18n.MessageFormat('I see {NUM_PEOPLE, plural, offset:1 ' +
    -      '=0 {no one at all in {PLACE}.} ' +
    -      '=1 {{PERSON} in {PLACE}.} ' +
    -      'one {{PERSON} and one other person in {PLACE}.} ' +
    -      'other {{PERSON} and # other people in {PLACE}.}}');
    -
    -  assertEquals('I see no one at all in Belgrade.',
    -               fmt.format({'NUM_PEOPLE': 0,
    -        'PLACE': 'Belgrade'}));
    -  assertEquals('I see Markus in Berlin.',
    -               fmt.format({'NUM_PEOPLE': 1,
    -        'PERSON': 'Markus',
    -        'PLACE': 'Berlin'}));
    -  assertEquals('I see Mark and one other person in Athens.',
    -               fmt.format({'NUM_PEOPLE': 2,
    -        'PERSON': 'Mark',
    -        'PLACE': 'Athens'}));
    -  assertEquals('I see Cibu and 99 other people in the cubes.',
    -               fmt.format({'NUM_PEOPLE': 100,
    -        'PERSON': 'Cibu',
    -        'PLACE': 'the cubes'}));
    -}
    -
    -function testSimplePluralNoOffset() {
    -  var fmt = new goog.i18n.MessageFormat('I see {NUM_PEOPLE, plural, ' +
    -      '=0 {no one at all} ' +
    -      '=1 {{PERSON}} ' +
    -      'one {{PERSON} and one other person} ' +
    -      'other {{PERSON} and # other people}} in {PLACE}.');
    -
    -  assertEquals('I see no one at all in Belgrade.',
    -               fmt.format({'NUM_PEOPLE': 0,
    -        'PLACE': 'Belgrade'}));
    -  assertEquals('I see Markus in Berlin.',
    -               fmt.format({'NUM_PEOPLE': 1,
    -        'PERSON': 'Markus',
    -        'PLACE': 'Berlin'}));
    -  assertEquals('I see Mark and 2 other people in Athens.',
    -               fmt.format({'NUM_PEOPLE': 2,
    -        'PERSON': 'Mark',
    -        'PLACE': 'Athens'}));
    -  assertEquals('I see Cibu and 100 other people in the cubes.',
    -               fmt.format({'NUM_PEOPLE': 100,
    -        'PERSON': 'Cibu',
    -        'PLACE': 'the cubes'}));
    -}
    -
    -function testSelectNestedInPlural() {
    -  var fmt = new goog.i18n.MessageFormat('{CIRCLES, plural, ' +
    -      'one {{GENDER, select, ' +
    -      '  female {{WHO} added you to her circle} ' +
    -      '  other  {{WHO} added you to his circle}}} ' +
    -      'other {{GENDER, select, ' +
    -      '  female {{WHO} added you to her # circles} ' +
    -      '  other  {{WHO} added you to his # circles}}}}');
    -
    -  assertEquals('Jelena added you to her circle',
    -               fmt.format({'GENDER': 'female',
    -        'WHO': 'Jelena',
    -        'CIRCLES': 1}));
    -  assertEquals('Milan added you to his 1,234 circles',
    -               fmt.format({'GENDER': 'male',
    -        'WHO': 'Milan',
    -        'CIRCLES': 1234}));
    -}
    -
    -function testPluralNestedInSelect() {
    -  // Added offset just for testing purposes. It doesn't make sense
    -  // to have it otherwise.
    -  var fmt = new goog.i18n.MessageFormat('{GENDER, select, ' +
    -      'female {{NUM_GROUPS, plural, ' +
    -      '  one {{WHO} added you to her group} ' +
    -      '  other {{WHO} added you to her # groups}}} ' +
    -      'other {{NUM_GROUPS, plural, offset:1' +
    -      '  one {{WHO} added you to his group} ' +
    -      '  other {{WHO} added you to his # groups}}}}');
    -
    -  assertEquals('Jelena added you to her group',
    -               fmt.format({'GENDER': 'female',
    -        'WHO': 'Jelena',
    -        'NUM_GROUPS': 1}));
    -  assertEquals('Milan added you to his 1,233 groups',
    -               fmt.format({'GENDER': 'male',
    -        'WHO': 'Milan',
    -        'NUM_GROUPS': 1234}));
    -}
    -
    -function testLiteralOpenCurlyBrace() {
    -  var fmt = new goog.i18n.MessageFormat("Anna's house" +
    -      " has '{0} and # in the roof' and {NUM_COWS} cows.");
    -  assertEquals("Anna's house has {0} and # in the roof and 5 cows.",
    -               fmt.format({'NUM_COWS': '5'}));
    -}
    -
    -function testLiteralClosedCurlyBrace() {
    -  var fmt = new goog.i18n.MessageFormat("Anna's house" +
    -      " has '{'0'} and # in the roof' and {NUM_COWS} cows.");
    -  assertEquals("Anna's house has {0} and # in the roof and 5 cows.",
    -               fmt.format({'NUM_COWS': '5'}));
    -}
    -
    -function testLiteralPoundSign() {
    -  var fmt = new goog.i18n.MessageFormat("Anna's house" +
    -      " has '{0}' and '# in the roof' and {NUM_COWS} cows.");
    -  assertEquals("Anna's house has {0} and # in the roof and 5 cows.",
    -               fmt.format({'NUM_COWS': '5'}));
    -}
    -
    -function testNoLiteralsForSingleQuotes() {
    -  var fmt = new goog.i18n.MessageFormat("Anna's house" +
    -      " 'has {NUM_COWS} cows'.");
    -  assertEquals("Anna's house 'has 5 cows'.", fmt.format({'NUM_COWS': '5'}));
    -}
    -
    -function testConsecutiveSingleQuotesAreReplacedWithOneSingleQuote() {
    -  var fmt = new goog.i18n.MessageFormat("Anna''s house a'{''''b'");
    -  assertEquals("Anna's house a{''b", fmt.format({}));
    -}
    -
    -function testConsecutiveSingleQuotesBeforeSpecialCharDontCreateLiteral() {
    -  var fmt = new goog.i18n.MessageFormat("a''{NUM_COWS}'b");
    -  assertEquals("a'5'b", fmt.format({'NUM_COWS': '5'}));
    -}
    -
    -function testSerbianSimpleSelect() {
    -  stubs.set(goog.i18n.pluralRules, 'select', goog.i18n.pluralRules.beSelect_);
    -
    -  var fmt = new goog.i18n.MessageFormat('{GENDER, select, ' +
    -      'female {Njen} other {Njegov}} bicikl je ' +
    -      '{GENDER, select, female {crven} other {plav}}.');
    -
    -  assertEquals('Njegov bicikl je plav.', fmt.format({'GENDER': 'male'}));
    -  assertEquals('Njen bicikl je crven.', fmt.format({'GENDER': 'female'}));
    -}
    -
    -function testSerbianSimplePlural() {
    -  stubs.set(goog.i18n.pluralRules, 'select', goog.i18n.pluralRules.beSelect_);
    -
    -  var fmt = new goog.i18n.MessageFormat('Ja {NUM_PEOPLE, plural, offset:1 ' +
    -      '=0 {ne vidim nikoga} ' +
    -      '=1 {vidim {PERSON}} ' +
    -      'one {vidim {PERSON} i jos # osobu} ' +
    -      'few {vidim {PERSON} i jos # osobe} ' +
    -      'many {vidim {PERSON} i jos # osoba} ' +
    -      'other {{PERSON} i jos # osoba}} ' +
    -      'u {PLACE}.');
    -
    -  assertEquals('Ja ne vidim nikoga u Beogradu.',
    -               fmt.format({'NUM_PEOPLE': 0,
    -        'PLACE': 'Beogradu'}));
    -  assertEquals('Ja vidim Markusa u Berlinu.',
    -               fmt.format({'NUM_PEOPLE': 1,
    -        'PERSON': 'Markusa',
    -        'PLACE': 'Berlinu'}));
    -  assertEquals('Ja vidim Marka i jos 1 osobu u Atini.',
    -               fmt.format({'NUM_PEOPLE': 2,
    -        'PERSON': 'Marka',
    -        'PLACE': 'Atini'}));
    -  assertEquals('Ja vidim Petra i jos 3 osobe u muzeju.',
    -               fmt.format({'NUM_PEOPLE': 4,
    -        'PERSON': 'Petra',
    -        'PLACE': 'muzeju'}));
    -  assertEquals('Ja vidim Cibua i jos 99 osoba u bazenu.',
    -               fmt.format({'NUM_PEOPLE': 100,
    -        'PERSON': 'Cibua',
    -        'PLACE': 'bazenu'}));
    -}
    -
    -function testSerbianSimplePluralNoOffset() {
    -  stubs.set(goog.i18n.pluralRules, 'select', goog.i18n.pluralRules.beSelect_);
    -
    -  var fmt = new goog.i18n.MessageFormat('Ja {NUM_PEOPLE, plural, ' +
    -      '=0 {ne vidim nikoga} ' +
    -      '=1 {vidim {PERSON}} ' +
    -      'one {vidim {PERSON} i jos # osobu} ' +
    -      'few {vidim {PERSON} i jos # osobe} ' +
    -      'many {vidim {PERSON} i jos # osoba} ' +
    -      'other {{PERSON} i jos # osoba}} ' +
    -      'u {PLACE}.');
    -
    -  assertEquals('Ja ne vidim nikoga u Beogradu.',
    -               fmt.format({'NUM_PEOPLE': 0,
    -        'PLACE': 'Beogradu'}));
    -  assertEquals('Ja vidim Markusa u Berlinu.',
    -               fmt.format({'NUM_PEOPLE': 1,
    -        'PERSON': 'Markusa',
    -        'PLACE': 'Berlinu'}));
    -  assertEquals('Ja vidim Marka i jos 21 osobu u Atini.',
    -               fmt.format({'NUM_PEOPLE': 21,
    -        'PERSON': 'Marka',
    -        'PLACE': 'Atini'}));
    -  assertEquals('Ja vidim Petra i jos 3 osobe u muzeju.',
    -               fmt.format({'NUM_PEOPLE': 3,
    -        'PERSON': 'Petra',
    -        'PLACE': 'muzeju'}));
    -  assertEquals('Ja vidim Cibua i jos 100 osoba u bazenu.',
    -               fmt.format({'NUM_PEOPLE': 100,
    -        'PERSON': 'Cibua',
    -        'PLACE': 'bazenu'}));
    -}
    -
    -function testSerbianSelectNestedInPlural() {
    -  stubs.set(goog.i18n.pluralRules, 'select', goog.i18n.pluralRules.beSelect_);
    -  stubs.set(goog.i18n, 'NumberFormatSymbols', goog.i18n.NumberFormatSymbols_hr);
    -
    -  var fmt = new goog.i18n.MessageFormat('{CIRCLES, plural, ' +
    -      'one {{GENDER, select, ' +
    -      '  female {{WHO} vas je dodala u njen # kruzok} ' +
    -      '  other  {{WHO} vas je dodao u njegov # kruzok}}} ' +
    -      'few {{GENDER, select, ' +
    -      '  female {{WHO} vas je dodala u njena # kruzoka} ' +
    -      '  other  {{WHO} vas je dodao u njegova # kruzoka}}} ' +
    -      'many {{GENDER, select, ' +
    -      '  female {{WHO} vas je dodala u njenih # kruzoka} ' +
    -      '  other  {{WHO} vas je dodao u njegovih # kruzoka}}} ' +
    -      'other {{GENDER, select, ' +
    -      '  female {{WHO} vas je dodala u njenih # kruzoka} ' +
    -      '  other  {{WHO} vas je dodao u njegovih # kruzoka}}}}');
    -
    -  assertEquals('Jelena vas je dodala u njen 21 kruzok',
    -               fmt.format({'GENDER': 'female',
    -        'WHO': 'Jelena',
    -        'CIRCLES': 21}));
    -  assertEquals('Jelena vas je dodala u njena 3 kruzoka',
    -               fmt.format({'GENDER': 'female',
    -        'WHO': 'Jelena',
    -        'CIRCLES': 3}));
    -  assertEquals('Jelena vas je dodala u njenih 5 kruzoka',
    -               fmt.format({'GENDER': 'female',
    -        'WHO': 'Jelena',
    -        'CIRCLES': 5}));
    -  assertEquals('Milan vas je dodao u njegovih 1.235 kruzoka',
    -               fmt.format({'GENDER': 'male',
    -        'WHO': 'Milan',
    -        'CIRCLES': 1235}));
    -}
    -
    -function testFallbackToOtherOptionInPlurals() {
    -  // Use Arabic plural rules since they have all six cases.
    -  // Only locale and numbers matter, the actual language of the message
    -  // does not.
    -  stubs.set(goog.i18n.pluralRules, 'select', goog.i18n.pluralRules.arSelect_);
    -
    -  var fmt = new goog.i18n.MessageFormat('{NUM_MINUTES, plural, ' +
    -      'other {# minutes}}');
    -
    -  // These numbers exercise all cases for the arabic plural rules.
    -  assertEquals('0 minutes', fmt.format({'NUM_MINUTES': 0}));
    -  assertEquals('1 minutes', fmt.format({'NUM_MINUTES': 1}));
    -  assertEquals('2 minutes', fmt.format({'NUM_MINUTES': 2}));
    -  assertEquals('3 minutes', fmt.format({'NUM_MINUTES': 3}));
    -  assertEquals('11 minutes', fmt.format({'NUM_MINUTES': 11}));
    -  assertEquals('1.5 minutes', fmt.format({'NUM_MINUTES': 1.5}));
    -}
    -
    -function testPoundShowsNumberMinusOffsetInAllCases() {
    -  var fmt = new goog.i18n.MessageFormat('{SOME_NUM, plural, offset:1 ' +
    -      '=0 {#} =1 {#} =2 {#}one {#} other {#}}');
    -
    -  assertEquals('-1', fmt.format({'SOME_NUM': '0'}));
    -  assertEquals('0', fmt.format({'SOME_NUM': '1'}));
    -  assertEquals('1', fmt.format({'SOME_NUM': '2'}));
    -  assertEquals('20', fmt.format({'SOME_NUM': '21'}));
    -}
    -
    -function testSpecialCharactersInParamaterDontChangeFormat() {
    -  var fmt = new goog.i18n.MessageFormat('{SOME_NUM, plural,' +
    -      'other {# {GROUP}}}');
    -
    -  // Test pound sign.
    -  assertEquals('10 group#1',
    -               fmt.format({'SOME_NUM': '10', 'GROUP': 'group#1'}));
    -  // Test other special characters in parameters, like { and }.
    -  assertEquals('10 } {', fmt.format({'SOME_NUM': '10', 'GROUP': '} {'}));
    -}
    -
    -function testMissingOrInvalidPluralParameter() {
    -  var fmt = new goog.i18n.MessageFormat('{SOME_NUM, plural,' +
    -      'other {result}}');
    -
    -  // Key name doesn't match A != SOME_NUM.
    -  assertEquals('Undefined or invalid parameter - SOME_NUM',
    -               fmt.format({A: '10'}));
    -
    -  // Value is not a number.
    -  assertEquals('Undefined or invalid parameter - SOME_NUM',
    -               fmt.format({'SOME_NUM': 'Value'}));
    -}
    -
    -function testMissingSelectParameter() {
    -  var fmt = new goog.i18n.MessageFormat('{GENDER, select,' +
    -      'other {result}}');
    -
    -  // Key name doesn't match A != GENDER.
    -  assertEquals('Undefined parameter - GENDER',
    -               fmt.format({A: 'female'}));
    -}
    -
    -function testMissingSimplePlaceholder() {
    -  var fmt = new goog.i18n.MessageFormat('{result}');
    -
    -  // Key name doesn't match A != result.
    -  assertEquals('Undefined parameter - result',
    -               fmt.format({A: 'none'}));
    -}
    -
    -function testPluralWithIgnorePound() {
    -  var fmt = new goog.i18n.MessageFormat('{SOME_NUM, plural,' +
    -      'other {# {GROUP}}}');
    -
    -  // Test pound sign.
    -  assertEquals('# group#1',
    -               fmt.formatIgnoringPound({'SOME_NUM': '10', 'GROUP': 'group#1'}));
    -  // Test other special characters in parameters, like { and }.
    -  assertEquals('# } {',
    -      fmt.formatIgnoringPound({'SOME_NUM': '10', 'GROUP': '} {'}));
    -}
    -
    -function testSimplePluralWithIgnorePound() {
    -  var fmt = new goog.i18n.MessageFormat(
    -      'I see {NUM_PEOPLE, plural, offset:1 ' +
    -      '=0 {no one at all in {PLACE}.} ' +
    -      '=1 {{PERSON} in {PLACE}.} ' +
    -      'one {{PERSON} and one other person in {PLACE}.} ' +
    -      'other {{PERSON} and # other people in {PLACE}.}}');
    -
    -  assertEquals('I see Cibu and # other people in the cubes.',
    -               fmt.formatIgnoringPound({'NUM_PEOPLE': 100,
    -        'PERSON': 'Cibu',
    -        'PLACE': 'the cubes'}));
    -}
    -
    -function testSimpleOrdinal() {
    -  var fmt = new goog.i18n.MessageFormat('{NUM_FLOOR, selectordinal, ' +
    -      'one {Take the elevator to the #st floor.}' +
    -      'two {Take the elevator to the #nd floor.}' +
    -      'few {Take the elevator to the #rd floor.}' +
    -      'other {Take the elevator to the #th floor.}}');
    -
    -  assertEquals('Take the elevator to the 1st floor.',
    -               fmt.format({'NUM_FLOOR': 1}));
    -  assertEquals('Take the elevator to the 2nd floor.',
    -               fmt.format({'NUM_FLOOR': 2}));
    -  assertEquals('Take the elevator to the 3rd floor.',
    -               fmt.format({'NUM_FLOOR': 3}));
    -  assertEquals('Take the elevator to the 4th floor.',
    -               fmt.format({'NUM_FLOOR': 4}));
    -  assertEquals('Take the elevator to the 23rd floor.',
    -               fmt.format({'NUM_FLOOR': 23}));
    -  // Esoteric example.
    -  assertEquals('Take the elevator to the 0th floor.',
    -               fmt.format({'NUM_FLOOR': 0}));
    -}
    -
    -function testOrdinalWithNegativeValue() {
    -  var fmt = new goog.i18n.MessageFormat('{NUM_FLOOR, selectordinal, ' +
    -      'one {Take the elevator to the #st floor.}' +
    -      'two {Take the elevator to the #nd floor.}' +
    -      'few {Take the elevator to the #rd floor.}' +
    -      'other {Take the elevator to the #th floor.}}');
    -
    -  try {
    -    fmt.format({'NUM_FLOOR': -2});
    -  } catch (e) {
    -    assertEquals('Assertion failed: Argument index smaller than offset.',
    -                 e.message);
    -    return;
    -  }
    -  fail('Expected an error to be thrown');
    -}
    -
    -function testSimpleOrdinalWithIgnorePound() {
    -  var fmt = new goog.i18n.MessageFormat('{NUM_FLOOR, selectordinal, ' +
    -      'one {Take the elevator to the #st floor.}' +
    -      'two {Take the elevator to the #nd floor.}' +
    -      'few {Take the elevator to the #rd floor.}' +
    -      'other {Take the elevator to the #th floor.}}');
    -
    -  assertEquals('Take the elevator to the #th floor.',
    -               fmt.formatIgnoringPound({'NUM_FLOOR': 100}));
    -}
    -
    -function testMissingOrInvalidOrdinalParameter() {
    -  var fmt = new goog.i18n.MessageFormat('{SOME_NUM, selectordinal,' +
    -      'other {result}}');
    -
    -  // Key name doesn't match A != SOME_NUM.
    -  assertEquals('Undefined or invalid parameter - SOME_NUM',
    -               fmt.format({A: '10'}));
    -
    -  // Value is not a number.
    -  assertEquals('Undefined or invalid parameter - SOME_NUM',
    -               fmt.format({'SOME_NUM': 'Value'}));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/mime.js b/src/database/third_party/closure-library/closure/goog/i18n/mime.js
    deleted file mode 100644
    index 852d3b219ac..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/mime.js
    +++ /dev/null
    @@ -1,111 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Functions for encoding strings according to MIME
    - * standards, especially RFC 1522.
    - */
    -goog.provide('goog.i18n.mime');
    -goog.provide('goog.i18n.mime.encode');
    -
    -goog.require('goog.array');
    -
    -
    -/**
    - * Regular expression for matching those characters that are outside the
    - * range that can be used in the quoted-printable encoding of RFC 1522:
    - * anything outside the 7-bit ASCII encoding, plus ?, =, _ or space.
    - * @type {RegExp}
    - * @private
    - */
    -goog.i18n.mime.NONASCII_ = /[^!-<>@-^`-~]/g;
    -
    -
    -/**
    - * Like goog.i18n.NONASCII_ but also omits double-quotes.
    - * @type {RegExp}
    - * @private
    - */
    -goog.i18n.mime.NONASCII_NOQUOTE_ = /[^!#-<>@-^`-~]/g;
    -
    -
    -/**
    - * Encodes a string for inclusion in a MIME header. The string is encoded
    - * in UTF-8 according to RFC 1522, using quoted-printable form.
    - * @param {string} str The string to encode.
    - * @param {boolean=} opt_noquote Whether double-quote characters should also
    - *     be escaped (should be true if the result will be placed inside a
    - *     quoted string for a parameter value in a MIME header).
    - * @return {string} The encoded string.
    - */
    -goog.i18n.mime.encode = function(str, opt_noquote) {
    -  var nonascii = opt_noquote ?
    -      goog.i18n.mime.NONASCII_NOQUOTE_ : goog.i18n.mime.NONASCII_;
    -
    -  if (str.search(nonascii) >= 0) {
    -    str = '=?UTF-8?Q?' + str.replace(nonascii,
    -        /**
    -         * @param {string} c The matched char.
    -         * @return {string} The quoted-printable form of utf-8 encoding.
    -         */
    -        function(c) {
    -          var i = c.charCodeAt(0);
    -          if (i == 32) {
    -            // Special case for space, which can be encoded as _ not =20
    -            return '_';
    -          }
    -          var a = goog.array.concat('', goog.i18n.mime.getHexCharArray(c));
    -          return a.join('=');
    -        }) + '?=';
    -  }
    -  return str;
    -};
    -
    -
    -/**
    - * Get an array of UTF-8 hex codes for a given character.
    - * @param {string} c The matched character.
    - * @return {!Array<string>} A hex array representing the character.
    - */
    -goog.i18n.mime.getHexCharArray = function(c) {
    -  var i = c.charCodeAt(0);
    -  var a = [];
    -  // First convert the UCS-2 character into its UTF-8 bytes
    -  if (i < 128) {
    -    a.push(i);
    -  } else if (i <= 0x7ff) {
    -    a.push(
    -        0xc0 + ((i >> 6) & 0x3f),
    -        0x80 + (i & 0x3f));
    -  } else if (i <= 0xffff) {
    -    a.push(
    -        0xe0 + ((i >> 12) & 0x3f),
    -        0x80 + ((i >> 6) & 0x3f),
    -        0x80 + (i & 0x3f));
    -  } else {
    -    // (This is defensive programming, since ecmascript isn't supposed
    -    // to handle code points that take more than 16 bits.)
    -    a.push(
    -        0xf0 + ((i >> 18) & 0x3f),
    -        0x80 + ((i >> 12) & 0x3f),
    -        0x80 + ((i >> 6) & 0x3f),
    -        0x80 + (i & 0x3f));
    -  }
    -  // Now convert those bytes into hex strings (don't do anything with
    -  // a[0] as that's got the empty string that lets us use join())
    -  for (i = a.length - 1; i >= 0; --i) {
    -    a[i] = a[i].toString(16);
    -  }
    -  return a;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/mime_test.html b/src/database/third_party/closure-library/closure/goog/i18n/mime_test.html
    deleted file mode 100644
    index 6bbf95a1f34..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/mime_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.i18n.mime
    -  </title>
    -  <meta charset="utf-8" />
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.i18n.mime.encodeTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/mime_test.js b/src/database/third_party/closure-library/closure/goog/i18n/mime_test.js
    deleted file mode 100644
    index 94f569156a9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/mime_test.js
    +++ /dev/null
    @@ -1,43 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.i18n.mime.encodeTest');
    -goog.setTestOnly('goog.i18n.mime.encodeTest');
    -
    -goog.require('goog.i18n.mime.encode');
    -goog.require('goog.testing.jsunit');
    -
    -function testEncodeAllAscii() {
    -  // A string holding all the characters that should be encoded unchanged.
    -  // Double-quote is doubled to avoid annoying syntax highlighting in emacs,
    -  // which doesn't recognize the double-quote as being in a string constant.
    -  var identity = '!""#$%&\'()*+,-./0123456789:;<>@ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
    -      '[\\]^`abcdefghijklmnopqrstuvwxyz{|}~';
    -  assertEquals(identity, goog.i18n.mime.encode(identity));
    -}
    -
    -function testEncodeSpecials() {
    -  assertEquals('=?UTF-8?Q?=3f=5f=3d_?=', goog.i18n.mime.encode('?_= '));
    -  assertEquals('=?UTF-8?Q?=3f=5f=3d_=22=22?=',
    -      goog.i18n.mime.encode('?_= ""', true));
    -}
    -
    -function testEncodeUnicode() {
    -  // Two-byte UTF-8, plus a special
    -  assertEquals('=?UTF-8?Q?=c2=82=de=a0_dude?=',
    -      goog.i18n.mime.encode('\u0082\u07a0 dude'));
    -  // Three-byte UTF-8, plus a special
    -  assertEquals('=?UTF-8?Q?=e0=a0=80=ef=bf=bf=3d?=',
    -      goog.i18n.mime.encode('\u0800\uffff='));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/numberformat.js b/src/database/third_party/closure-library/closure/goog/i18n/numberformat.js
    deleted file mode 100644
    index f0b55c689a4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/numberformat.js
    +++ /dev/null
    @@ -1,1248 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Number format/parse library with locale support.
    - */
    -
    -
    -/**
    - * Namespace for locale number format functions
    - */
    -goog.provide('goog.i18n.NumberFormat');
    -goog.provide('goog.i18n.NumberFormat.CurrencyStyle');
    -goog.provide('goog.i18n.NumberFormat.Format');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.i18n.CompactNumberFormatSymbols');
    -goog.require('goog.i18n.NumberFormatSymbols');
    -goog.require('goog.i18n.currency');
    -goog.require('goog.math');
    -
    -
    -
    -/**
    - * Constructor of NumberFormat.
    - * @param {number|string} pattern The number that indicates a predefined
    - *     number format pattern.
    - * @param {string=} opt_currency Optional international currency
    - *     code. This determines the currency code/symbol used in format/parse. If
    - *     not given, the currency code for current locale will be used.
    - * @param {number=} opt_currencyStyle currency style, value defined in
    - *        goog.i18n.NumberFormat.CurrencyStyle.
    - * @constructor
    - */
    -goog.i18n.NumberFormat = function(pattern, opt_currency, opt_currencyStyle) {
    -  this.intlCurrencyCode_ = opt_currency ||
    -      goog.i18n.NumberFormatSymbols.DEF_CURRENCY_CODE;
    -
    -  this.currencyStyle_ = opt_currencyStyle ||
    -      goog.i18n.NumberFormat.CurrencyStyle.LOCAL;
    -
    -  this.maximumIntegerDigits_ = 40;
    -  this.minimumIntegerDigits_ = 1;
    -  this.significantDigits_ = 0; // invariant, <= maximumFractionDigits
    -  this.maximumFractionDigits_ = 3; // invariant, >= minFractionDigits
    -  this.minimumFractionDigits_ = 0;
    -  this.minExponentDigits_ = 0;
    -  this.useSignForPositiveExponent_ = false;
    -
    -  /**
    -   * Whether to show trailing zeros in the fraction when significantDigits_ is
    -   * positive.
    -   * @private {boolean}
    -   */
    -  this.showTrailingZeros_ = false;
    -
    -  this.positivePrefix_ = '';
    -  this.positiveSuffix_ = '';
    -  this.negativePrefix_ = '-';
    -  this.negativeSuffix_ = '';
    -
    -  // The multiplier for use in percent, per mille, etc.
    -  this.multiplier_ = 1;
    -  this.groupingSize_ = 3;
    -  this.decimalSeparatorAlwaysShown_ = false;
    -  this.useExponentialNotation_ = false;
    -  this.compactStyle_ = goog.i18n.NumberFormat.CompactStyle.NONE;
    -
    -  /**
    -   * The number to base the formatting on when using compact styles, or null
    -   * if formatting should not be based on another number.
    -   * @type {?number}
    -   * @private
    -   */
    -  this.baseFormattingNumber_ = null;
    -
    -  /** @private {string} */
    -  this.pattern_;
    -
    -  if (typeof pattern == 'number') {
    -    this.applyStandardPattern_(pattern);
    -  } else {
    -    this.applyPattern_(pattern);
    -  }
    -};
    -
    -
    -/**
    - * Standard number formatting patterns.
    - * @enum {number}
    - */
    -goog.i18n.NumberFormat.Format = {
    -  DECIMAL: 1,
    -  SCIENTIFIC: 2,
    -  PERCENT: 3,
    -  CURRENCY: 4,
    -  COMPACT_SHORT: 5,
    -  COMPACT_LONG: 6
    -};
    -
    -
    -/**
    - * Currency styles.
    - * @enum {number}
    - */
    -goog.i18n.NumberFormat.CurrencyStyle = {
    -  LOCAL: 0,     // currency style as it is used in its circulating country.
    -  PORTABLE: 1,  // currency style that differentiate it from other popular ones.
    -  GLOBAL: 2     // currency style that is unique among all currencies.
    -};
    -
    -
    -/**
    - * Compacting styles.
    - * @enum {number}
    - */
    -goog.i18n.NumberFormat.CompactStyle = {
    -  NONE: 0,  // Don't compact.
    -  SHORT: 1, // Short compact form, such as 1.2B.
    -  LONG: 2  // Long compact form, such as 1.2 billion.
    -};
    -
    -
    -/**
    - * If the usage of Ascii digits should be enforced.
    - * @type {boolean}
    - * @private
    - */
    -goog.i18n.NumberFormat.enforceAsciiDigits_ = false;
    -
    -
    -/**
    - * Set if the usage of Ascii digits in formatting should be enforced.
    - * @param {boolean} doEnforce Boolean value about if Ascii digits should be
    - *     enforced.
    - */
    -goog.i18n.NumberFormat.setEnforceAsciiDigits = function(doEnforce) {
    -  goog.i18n.NumberFormat.enforceAsciiDigits_ = doEnforce;
    -};
    -
    -
    -/**
    - * Return if Ascii digits is enforced.
    - * @return {boolean} If Ascii digits is enforced.
    - */
    -goog.i18n.NumberFormat.isEnforceAsciiDigits = function() {
    -  return goog.i18n.NumberFormat.enforceAsciiDigits_;
    -};
    -
    -
    -/**
    - * Sets minimum number of fraction digits.
    - * @param {number} min the minimum.
    - * @return {!goog.i18n.NumberFormat} Reference to this NumberFormat object.
    - */
    -goog.i18n.NumberFormat.prototype.setMinimumFractionDigits = function(min) {
    -  if (this.significantDigits_ > 0 && min > 0) {
    -    throw Error(
    -        'Can\'t combine significant digits and minimum fraction digits');
    -  }
    -  this.minimumFractionDigits_ = min;
    -  return this;
    -};
    -
    -
    -/**
    - * Sets maximum number of fraction digits.
    - * @param {number} max the maximum.
    - * @return {!goog.i18n.NumberFormat} Reference to this NumberFormat object.
    - */
    -goog.i18n.NumberFormat.prototype.setMaximumFractionDigits = function(max) {
    -  this.maximumFractionDigits_ = max;
    -  return this;
    -};
    -
    -
    -/**
    - * Sets number of significant digits to show. Only fractions will be rounded.
    - * @param {number} number The number of significant digits to include.
    - * @return {!goog.i18n.NumberFormat} Reference to this NumberFormat object.
    - */
    -goog.i18n.NumberFormat.prototype.setSignificantDigits = function(number) {
    -  if (this.minimumFractionDigits_ > 0 && number >= 0) {
    -    throw Error(
    -        'Can\'t combine significant digits and minimum fraction digits');
    -  }
    -  this.significantDigits_ = number;
    -  return this;
    -};
    -
    -
    -/**
    - * Gets number of significant digits to show. Only fractions will be rounded.
    - * @return {number} The number of significant digits to include.
    - */
    -goog.i18n.NumberFormat.prototype.getSignificantDigits = function() {
    -  return this.significantDigits_;
    -};
    -
    -
    -/**
    - * Sets whether trailing fraction zeros should be shown when significantDigits_
    - * is positive. If this is true and significantDigits_ is 2, 1 will be formatted
    - * as '1.0'.
    - * @param {boolean} showTrailingZeros Whether trailing zeros should be shown.
    - * @return {!goog.i18n.NumberFormat} Reference to this NumberFormat object.
    - */
    -goog.i18n.NumberFormat.prototype.setShowTrailingZeros =
    -    function(showTrailingZeros) {
    -  this.showTrailingZeros_ = showTrailingZeros;
    -  return this;
    -};
    -
    -
    -/**
    - * Sets a number to base the formatting on when compact style formatting is
    - * used. If this is null, the formatting should be based only on the number to
    - * be formatting.
    - *
    - * This base formatting number can be used to format the target number as
    - * another number would be formatted. For example, 100,000 is normally formatted
    - * as "100K" in the COMPACT_SHORT format. To instead format it as '0.1M', the
    - * base number could be set to 1,000,000 in order to force all numbers to be
    - * formatted in millions. Similarly, 1,000,000,000 would normally be formatted
    - * as '1B' and setting the base formatting number to 1,000,000, would cause it
    - * to be formatted instead as '1,000M'.
    - *
    - * @param {?number} baseFormattingNumber The number to base formatting on, or
    - * null if formatting should not be based on another number.
    - * @return {!goog.i18n.NumberFormat} Reference to this NumberFormat object.
    - */
    -goog.i18n.NumberFormat.prototype.setBaseFormatting =
    -    function(baseFormattingNumber) {
    -  goog.asserts.assert(goog.isNull(baseFormattingNumber) ||
    -      isFinite(baseFormattingNumber));
    -  this.baseFormattingNumber_ = baseFormattingNumber;
    -  return this;
    -};
    -
    -
    -/**
    - * Gets the number on which compact formatting is currently based, or null if
    - * no such number is set. See setBaseFormatting() for more information.
    - * @return {?number}
    - */
    -goog.i18n.NumberFormat.prototype.getBaseFormatting = function() {
    -  return this.baseFormattingNumber_;
    -};
    -
    -
    -/**
    - * Apply provided pattern, result are stored in member variables.
    - *
    - * @param {string} pattern String pattern being applied.
    - * @private
    - */
    -goog.i18n.NumberFormat.prototype.applyPattern_ = function(pattern) {
    -  this.pattern_ = pattern.replace(/ /g, '\u00a0');
    -  var pos = [0];
    -
    -  this.positivePrefix_ = this.parseAffix_(pattern, pos);
    -  var trunkStart = pos[0];
    -  this.parseTrunk_(pattern, pos);
    -  var trunkLen = pos[0] - trunkStart;
    -  this.positiveSuffix_ = this.parseAffix_(pattern, pos);
    -  if (pos[0] < pattern.length &&
    -      pattern.charAt(pos[0]) == goog.i18n.NumberFormat.PATTERN_SEPARATOR_) {
    -    pos[0]++;
    -    this.negativePrefix_ = this.parseAffix_(pattern, pos);
    -    // we assume this part is identical to positive part.
    -    // user must make sure the pattern is correctly constructed.
    -    pos[0] += trunkLen;
    -    this.negativeSuffix_ = this.parseAffix_(pattern, pos);
    -  } else {
    -    // if no negative affix specified, they share the same positive affix
    -    this.negativePrefix_ = this.positivePrefix_ + this.negativePrefix_;
    -    this.negativeSuffix_ += this.positiveSuffix_;
    -  }
    -};
    -
    -
    -/**
    - * Apply a predefined pattern to NumberFormat object.
    - * @param {number} patternType The number that indicates a predefined number
    - *     format pattern.
    - * @private
    - */
    -goog.i18n.NumberFormat.prototype.applyStandardPattern_ = function(patternType) {
    -  switch (patternType) {
    -    case goog.i18n.NumberFormat.Format.DECIMAL:
    -      this.applyPattern_(goog.i18n.NumberFormatSymbols.DECIMAL_PATTERN);
    -      break;
    -    case goog.i18n.NumberFormat.Format.SCIENTIFIC:
    -      this.applyPattern_(goog.i18n.NumberFormatSymbols.SCIENTIFIC_PATTERN);
    -      break;
    -    case goog.i18n.NumberFormat.Format.PERCENT:
    -      this.applyPattern_(goog.i18n.NumberFormatSymbols.PERCENT_PATTERN);
    -      break;
    -    case goog.i18n.NumberFormat.Format.CURRENCY:
    -      this.applyPattern_(goog.i18n.currency.adjustPrecision(
    -          goog.i18n.NumberFormatSymbols.CURRENCY_PATTERN,
    -          this.intlCurrencyCode_));
    -      break;
    -    case goog.i18n.NumberFormat.Format.COMPACT_SHORT:
    -      this.applyCompactStyle_(goog.i18n.NumberFormat.CompactStyle.SHORT);
    -      break;
    -    case goog.i18n.NumberFormat.Format.COMPACT_LONG:
    -      this.applyCompactStyle_(goog.i18n.NumberFormat.CompactStyle.LONG);
    -      break;
    -    default:
    -      throw Error('Unsupported pattern type.');
    -  }
    -};
    -
    -
    -/**
    - * Apply a predefined pattern for shorthand formats.
    - * @param {goog.i18n.NumberFormat.CompactStyle} style the compact style to
    - *     set defaults for.
    - * @private
    - */
    -goog.i18n.NumberFormat.prototype.applyCompactStyle_ = function(style) {
    -  this.compactStyle_ = style;
    -  this.applyPattern_(goog.i18n.NumberFormatSymbols.DECIMAL_PATTERN);
    -  this.setMinimumFractionDigits(0);
    -  this.setMaximumFractionDigits(2);
    -  this.setSignificantDigits(2);
    -};
    -
    -
    -/**
    - * Parses text string to produce a Number.
    - *
    - * This method attempts to parse text starting from position "opt_pos" if it
    - * is given. Otherwise the parse will start from the beginning of the text.
    - * When opt_pos presents, opt_pos will be updated to the character next to where
    - * parsing stops after the call. If an error occurs, opt_pos won't be updated.
    - *
    - * @param {string} text The string to be parsed.
    - * @param {Array<number>=} opt_pos Position to pass in and get back.
    - * @return {number} Parsed number. This throws an error if the text cannot be
    - *     parsed.
    - */
    -goog.i18n.NumberFormat.prototype.parse = function(text, opt_pos) {
    -  var pos = opt_pos || [0];
    -
    -  if (this.compactStyle_ != goog.i18n.NumberFormat.CompactStyle.NONE) {
    -    throw Error('Parsing of compact numbers is unimplemented');
    -  }
    -
    -  var ret = NaN;
    -
    -  // we don't want to handle 2 kind of space in parsing, normalize it to nbsp
    -  text = text.replace(/ /g, '\u00a0');
    -
    -  var gotPositive = text.indexOf(this.positivePrefix_, pos[0]) == pos[0];
    -  var gotNegative = text.indexOf(this.negativePrefix_, pos[0]) == pos[0];
    -
    -  // check for the longest match
    -  if (gotPositive && gotNegative) {
    -    if (this.positivePrefix_.length > this.negativePrefix_.length) {
    -      gotNegative = false;
    -    } else if (this.positivePrefix_.length < this.negativePrefix_.length) {
    -      gotPositive = false;
    -    }
    -  }
    -
    -  if (gotPositive) {
    -    pos[0] += this.positivePrefix_.length;
    -  } else if (gotNegative) {
    -    pos[0] += this.negativePrefix_.length;
    -  }
    -
    -  // process digits or Inf, find decimal position
    -  if (text.indexOf(goog.i18n.NumberFormatSymbols.INFINITY, pos[0]) == pos[0]) {
    -    pos[0] += goog.i18n.NumberFormatSymbols.INFINITY.length;
    -    ret = Infinity;
    -  } else {
    -    ret = this.parseNumber_(text, pos);
    -  }
    -
    -  // check for suffix
    -  if (gotPositive) {
    -    if (!(text.indexOf(this.positiveSuffix_, pos[0]) == pos[0])) {
    -      return NaN;
    -    }
    -    pos[0] += this.positiveSuffix_.length;
    -  } else if (gotNegative) {
    -    if (!(text.indexOf(this.negativeSuffix_, pos[0]) == pos[0])) {
    -      return NaN;
    -    }
    -    pos[0] += this.negativeSuffix_.length;
    -  }
    -
    -  return gotNegative ? -ret : ret;
    -};
    -
    -
    -/**
    - * This function will parse a "localized" text into a Number. It needs to
    - * handle locale specific decimal, grouping, exponent and digits.
    - *
    - * @param {string} text The text that need to be parsed.
    - * @param {Array<number>} pos  In/out parsing position. In case of failure,
    - *    pos value won't be changed.
    - * @return {number} Number value, or NaN if nothing can be parsed.
    - * @private
    - */
    -goog.i18n.NumberFormat.prototype.parseNumber_ = function(text, pos) {
    -  var sawDecimal = false;
    -  var sawExponent = false;
    -  var sawDigit = false;
    -  var scale = 1;
    -  var decimal = goog.i18n.NumberFormatSymbols.DECIMAL_SEP;
    -  var grouping = goog.i18n.NumberFormatSymbols.GROUP_SEP;
    -  var exponentChar = goog.i18n.NumberFormatSymbols.EXP_SYMBOL;
    -
    -  if (this.compactStyle_ != goog.i18n.NumberFormat.CompactStyle.NONE) {
    -    throw Error('Parsing of compact style numbers is not implemented');
    -  }
    -
    -  var normalizedText = '';
    -  for (; pos[0] < text.length; pos[0]++) {
    -    var ch = text.charAt(pos[0]);
    -    var digit = this.getDigit_(ch);
    -    if (digit >= 0 && digit <= 9) {
    -      normalizedText += digit;
    -      sawDigit = true;
    -    } else if (ch == decimal.charAt(0)) {
    -      if (sawDecimal || sawExponent) {
    -        break;
    -      }
    -      normalizedText += '.';
    -      sawDecimal = true;
    -    } else if (ch == grouping.charAt(0) &&
    -               ('\u00a0' != grouping.charAt(0) ||
    -                pos[0] + 1 < text.length &&
    -                this.getDigit_(text.charAt(pos[0] + 1)) >= 0)) {
    -      // Got a grouping character here. When grouping character is nbsp, need
    -      // to make sure the character following it is a digit.
    -      if (sawDecimal || sawExponent) {
    -        break;
    -      }
    -      continue;
    -    } else if (ch == exponentChar.charAt(0)) {
    -      if (sawExponent) {
    -        break;
    -      }
    -      normalizedText += 'E';
    -      sawExponent = true;
    -    } else if (ch == '+' || ch == '-') {
    -      normalizedText += ch;
    -    } else if (ch == goog.i18n.NumberFormatSymbols.PERCENT.charAt(0)) {
    -      if (scale != 1) {
    -        break;
    -      }
    -      scale = 100;
    -      if (sawDigit) {
    -        pos[0]++; // eat this character if parse end here
    -        break;
    -      }
    -    } else if (ch == goog.i18n.NumberFormatSymbols.PERMILL.charAt(0)) {
    -      if (scale != 1) {
    -        break;
    -      }
    -      scale = 1000;
    -      if (sawDigit) {
    -        pos[0]++; // eat this character if parse end here
    -        break;
    -      }
    -    } else {
    -      break;
    -    }
    -  }
    -  return parseFloat(normalizedText) / scale;
    -};
    -
    -
    -/**
    - * Formats a Number to produce a string.
    - *
    - * @param {number} number The Number to be formatted.
    - * @return {string} The formatted number string.
    - */
    -goog.i18n.NumberFormat.prototype.format = function(number) {
    -  if (isNaN(number)) {
    -    return goog.i18n.NumberFormatSymbols.NAN;
    -  }
    -
    -  var parts = [];
    -  var baseFormattingNumber = goog.isNull(this.baseFormattingNumber_) ?
    -      number :
    -      this.baseFormattingNumber_;
    -  var unit = this.getUnitAfterRounding_(baseFormattingNumber, number);
    -  number /= Math.pow(10, unit.divisorBase);
    -
    -  parts.push(unit.prefix);
    -
    -  // in icu code, it is commented that certain computation need to keep the
    -  // negative sign for 0.
    -  var isNegative = number < 0.0 || number == 0.0 && 1 / number < 0.0;
    -
    -  parts.push(isNegative ? this.negativePrefix_ : this.positivePrefix_);
    -
    -  if (!isFinite(number)) {
    -    parts.push(goog.i18n.NumberFormatSymbols.INFINITY);
    -  } else {
    -    // convert number to non-negative value
    -    number *= isNegative ? -1 : 1;
    -
    -    number *= this.multiplier_;
    -    this.useExponentialNotation_ ?
    -        this.subformatExponential_(number, parts) :
    -        this.subformatFixed_(number, this.minimumIntegerDigits_, parts);
    -  }
    -
    -  parts.push(isNegative ? this.negativeSuffix_ : this.positiveSuffix_);
    -  parts.push(unit.suffix);
    -
    -  return parts.join('');
    -};
    -
    -
    -/**
    - * Round a number into an integer and fractional part
    - * based on the rounding rules for this NumberFormat.
    - * @param {number} number The number to round.
    - * @return {{intValue: number, fracValue: number}} The integer and fractional
    - *     part after rounding.
    - * @private
    - */
    -goog.i18n.NumberFormat.prototype.roundNumber_ = function(number) {
    -  var power = Math.pow(10, this.maximumFractionDigits_);
    -  var shiftedNumber = this.significantDigits_ <= 0 ?
    -      Math.round(number * power) :
    -      Math.round(this.roundToSignificantDigits_(
    -          number * power,
    -          this.significantDigits_,
    -          this.maximumFractionDigits_));
    -
    -  var intValue, fracValue;
    -  if (isFinite(shiftedNumber)) {
    -    intValue = Math.floor(shiftedNumber / power);
    -    fracValue = Math.floor(shiftedNumber - intValue * power);
    -  } else {
    -    intValue = number;
    -    fracValue = 0;
    -  }
    -  return {intValue: intValue, fracValue: fracValue};
    -};
    -
    -
    -/**
    - * Formats a Number in fraction format.
    - *
    - * @param {number} number
    - * @param {number} minIntDigits Minimum integer digits.
    - * @param {Array<string>} parts
    - *     This array holds the pieces of formatted string.
    - *     This function will add its formatted pieces to the array.
    - * @private
    - */
    -goog.i18n.NumberFormat.prototype.subformatFixed_ =
    -    function(number, minIntDigits, parts) {
    -  if (this.minimumFractionDigits_ > this.maximumFractionDigits_) {
    -    throw Error('Min value must be less than max value');
    -  }
    -
    -  var rounded = this.roundNumber_(number);
    -  var power = Math.pow(10, this.maximumFractionDigits_);
    -  var intValue = rounded.intValue;
    -  var fracValue = rounded.fracValue;
    -
    -  var numIntDigits = (intValue == 0) ? 0 : this.intLog10_(intValue) + 1;
    -  var fractionPresent = this.minimumFractionDigits_ > 0 || fracValue > 0 ||
    -      (this.showTrailingZeros_ && numIntDigits < this.significantDigits_);
    -  var minimumFractionDigits = this.minimumFractionDigits_;
    -  if (fractionPresent) {
    -    if (this.showTrailingZeros_ && this.significantDigits_ > 0) {
    -      minimumFractionDigits = this.significantDigits_ - numIntDigits;
    -    } else {
    -      minimumFractionDigits = this.minimumFractionDigits_;
    -    }
    -  }
    -
    -  var intPart = '';
    -  var translatableInt = intValue;
    -  while (translatableInt > 1E20) {
    -    // here it goes beyond double precision, add '0' make it look better
    -    intPart = '0' + intPart;
    -    translatableInt = Math.round(translatableInt / 10);
    -  }
    -  intPart = translatableInt + intPart;
    -
    -  var decimal = goog.i18n.NumberFormatSymbols.DECIMAL_SEP;
    -  var grouping = goog.i18n.NumberFormatSymbols.GROUP_SEP;
    -  var zeroCode = goog.i18n.NumberFormat.enforceAsciiDigits_ ?
    -                 48  /* ascii '0' */ :
    -                 goog.i18n.NumberFormatSymbols.ZERO_DIGIT.charCodeAt(0);
    -  var digitLen = intPart.length;
    -
    -  if (intValue > 0 || minIntDigits > 0) {
    -    for (var i = digitLen; i < minIntDigits; i++) {
    -      parts.push(String.fromCharCode(zeroCode));
    -    }
    -
    -    for (var i = 0; i < digitLen; i++) {
    -      parts.push(String.fromCharCode(zeroCode + intPart.charAt(i) * 1));
    -
    -      if (digitLen - i > 1 && this.groupingSize_ > 0 &&
    -          ((digitLen - i) % this.groupingSize_ == 1)) {
    -        parts.push(grouping);
    -      }
    -    }
    -  } else if (!fractionPresent) {
    -    // If there is no fraction present, and we haven't printed any
    -    // integer digits, then print a zero.
    -    parts.push(String.fromCharCode(zeroCode));
    -  }
    -
    -  // Output the decimal separator if we always do so.
    -  if (this.decimalSeparatorAlwaysShown_ || fractionPresent) {
    -    parts.push(decimal);
    -  }
    -
    -  var fracPart = '' + (fracValue + power);
    -  var fracLen = fracPart.length;
    -  while (fracPart.charAt(fracLen - 1) == '0' &&
    -      fracLen > minimumFractionDigits + 1) {
    -    fracLen--;
    -  }
    -
    -  for (var i = 1; i < fracLen; i++) {
    -    parts.push(String.fromCharCode(zeroCode + fracPart.charAt(i) * 1));
    -  }
    -};
    -
    -
    -/**
    - * Formats exponent part of a Number.
    - *
    - * @param {number} exponent Exponential value.
    - * @param {Array<string>} parts The array that holds the pieces of formatted
    - *     string. This function will append more formatted pieces to the array.
    - * @private
    - */
    -goog.i18n.NumberFormat.prototype.addExponentPart_ = function(exponent, parts) {
    -  parts.push(goog.i18n.NumberFormatSymbols.EXP_SYMBOL);
    -
    -  if (exponent < 0) {
    -    exponent = -exponent;
    -    parts.push(goog.i18n.NumberFormatSymbols.MINUS_SIGN);
    -  } else if (this.useSignForPositiveExponent_) {
    -    parts.push(goog.i18n.NumberFormatSymbols.PLUS_SIGN);
    -  }
    -
    -  var exponentDigits = '' + exponent;
    -  var zeroChar = goog.i18n.NumberFormat.enforceAsciiDigits_ ? '0' :
    -                 goog.i18n.NumberFormatSymbols.ZERO_DIGIT;
    -  for (var i = exponentDigits.length; i < this.minExponentDigits_; i++) {
    -    parts.push(zeroChar);
    -  }
    -  parts.push(exponentDigits);
    -};
    -
    -
    -/**
    - * Formats Number in exponential format.
    - *
    - * @param {number} number Value need to be formated.
    - * @param {Array<string>} parts The array that holds the pieces of formatted
    - *     string. This function will append more formatted pieces to the array.
    - * @private
    - */
    -goog.i18n.NumberFormat.prototype.subformatExponential_ =
    -    function(number, parts) {
    -  if (number == 0.0) {
    -    this.subformatFixed_(number, this.minimumIntegerDigits_, parts);
    -    this.addExponentPart_(0, parts);
    -    return;
    -  }
    -
    -  var exponent = goog.math.safeFloor(Math.log(number) / Math.log(10));
    -  number /= Math.pow(10, exponent);
    -
    -  var minIntDigits = this.minimumIntegerDigits_;
    -  if (this.maximumIntegerDigits_ > 1 &&
    -      this.maximumIntegerDigits_ > this.minimumIntegerDigits_) {
    -    // A repeating range is defined; adjust to it as follows.
    -    // If repeat == 3, we have 6,5,4=>3; 3,2,1=>0; 0,-1,-2=>-3;
    -    // -3,-4,-5=>-6, etc. This takes into account that the
    -    // exponent we have here is off by one from what we expect;
    -    // it is for the format 0.MMMMMx10^n.
    -    while ((exponent % this.maximumIntegerDigits_) != 0) {
    -      number *= 10;
    -      exponent--;
    -    }
    -    minIntDigits = 1;
    -  } else {
    -    // No repeating range is defined; use minimum integer digits.
    -    if (this.minimumIntegerDigits_ < 1) {
    -      exponent++;
    -      number /= 10;
    -    } else {
    -      exponent -= this.minimumIntegerDigits_ - 1;
    -      number *= Math.pow(10, this.minimumIntegerDigits_ - 1);
    -    }
    -  }
    -  this.subformatFixed_(number, minIntDigits, parts);
    -  this.addExponentPart_(exponent, parts);
    -};
    -
    -
    -/**
    - * Returns the digit value of current character. The character could be either
    - * '0' to '9', or a locale specific digit.
    - *
    - * @param {string} ch Character that represents a digit.
    - * @return {number} The digit value, or -1 on error.
    - * @private
    - */
    -goog.i18n.NumberFormat.prototype.getDigit_ = function(ch) {
    -  var code = ch.charCodeAt(0);
    -  // between '0' to '9'
    -  if (48 <= code && code < 58) {
    -    return code - 48;
    -  } else {
    -    var zeroCode = goog.i18n.NumberFormatSymbols.ZERO_DIGIT.charCodeAt(0);
    -    return zeroCode <= code && code < zeroCode + 10 ? code - zeroCode : -1;
    -  }
    -};
    -
    -
    -// ----------------------------------------------------------------------
    -// CONSTANTS
    -// ----------------------------------------------------------------------
    -// Constants for characters used in programmatic (unlocalized) patterns.
    -/**
    - * A zero digit character.
    - * @type {string}
    - * @private
    - */
    -goog.i18n.NumberFormat.PATTERN_ZERO_DIGIT_ = '0';
    -
    -
    -/**
    - * A grouping separator character.
    - * @type {string}
    - * @private
    - */
    -goog.i18n.NumberFormat.PATTERN_GROUPING_SEPARATOR_ = ',';
    -
    -
    -/**
    - * A decimal separator character.
    - * @type {string}
    - * @private
    - */
    -goog.i18n.NumberFormat.PATTERN_DECIMAL_SEPARATOR_ = '.';
    -
    -
    -/**
    - * A per mille character.
    - * @type {string}
    - * @private
    - */
    -goog.i18n.NumberFormat.PATTERN_PER_MILLE_ = '\u2030';
    -
    -
    -/**
    - * A percent character.
    - * @type {string}
    - * @private
    - */
    -goog.i18n.NumberFormat.PATTERN_PERCENT_ = '%';
    -
    -
    -/**
    - * A digit character.
    - * @type {string}
    - * @private
    - */
    -goog.i18n.NumberFormat.PATTERN_DIGIT_ = '#';
    -
    -
    -/**
    - * A separator character.
    - * @type {string}
    - * @private
    - */
    -goog.i18n.NumberFormat.PATTERN_SEPARATOR_ = ';';
    -
    -
    -/**
    - * An exponent character.
    - * @type {string}
    - * @private
    - */
    -goog.i18n.NumberFormat.PATTERN_EXPONENT_ = 'E';
    -
    -
    -/**
    - * An plus character.
    - * @type {string}
    - * @private
    - */
    -goog.i18n.NumberFormat.PATTERN_PLUS_ = '+';
    -
    -
    -/**
    - * A minus character.
    - * @type {string}
    - * @private
    - */
    -goog.i18n.NumberFormat.PATTERN_MINUS_ = '-';
    -
    -
    -/**
    - * A quote character.
    - * @type {string}
    - * @private
    - */
    -goog.i18n.NumberFormat.PATTERN_CURRENCY_SIGN_ = '\u00A4';
    -
    -
    -/**
    - * A quote character.
    - * @type {string}
    - * @private
    - */
    -goog.i18n.NumberFormat.QUOTE_ = '\'';
    -
    -
    -/**
    - * Parses affix part of pattern.
    - *
    - * @param {string} pattern Pattern string that need to be parsed.
    - * @param {Array<number>} pos One element position array to set and receive
    - *     parsing position.
    - *
    - * @return {string} Affix received from parsing.
    - * @private
    - */
    -goog.i18n.NumberFormat.prototype.parseAffix_ = function(pattern, pos) {
    -  var affix = '';
    -  var inQuote = false;
    -  var len = pattern.length;
    -
    -  for (; pos[0] < len; pos[0]++) {
    -    var ch = pattern.charAt(pos[0]);
    -    if (ch == goog.i18n.NumberFormat.QUOTE_) {
    -      if (pos[0] + 1 < len &&
    -          pattern.charAt(pos[0] + 1) == goog.i18n.NumberFormat.QUOTE_) {
    -        pos[0]++;
    -        affix += '\''; // 'don''t'
    -      } else {
    -        inQuote = !inQuote;
    -      }
    -      continue;
    -    }
    -
    -    if (inQuote) {
    -      affix += ch;
    -    } else {
    -      switch (ch) {
    -        case goog.i18n.NumberFormat.PATTERN_DIGIT_:
    -        case goog.i18n.NumberFormat.PATTERN_ZERO_DIGIT_:
    -        case goog.i18n.NumberFormat.PATTERN_GROUPING_SEPARATOR_:
    -        case goog.i18n.NumberFormat.PATTERN_DECIMAL_SEPARATOR_:
    -        case goog.i18n.NumberFormat.PATTERN_SEPARATOR_:
    -          return affix;
    -        case goog.i18n.NumberFormat.PATTERN_CURRENCY_SIGN_:
    -          if ((pos[0] + 1) < len &&
    -              pattern.charAt(pos[0] + 1) ==
    -              goog.i18n.NumberFormat.PATTERN_CURRENCY_SIGN_) {
    -            pos[0]++;
    -            affix += this.intlCurrencyCode_;
    -          } else {
    -            switch (this.currencyStyle_) {
    -              case goog.i18n.NumberFormat.CurrencyStyle.LOCAL:
    -                affix += goog.i18n.currency.getLocalCurrencySign(
    -                    this.intlCurrencyCode_);
    -                break;
    -              case goog.i18n.NumberFormat.CurrencyStyle.GLOBAL:
    -                affix += goog.i18n.currency.getGlobalCurrencySign(
    -                    this.intlCurrencyCode_);
    -                break;
    -              case goog.i18n.NumberFormat.CurrencyStyle.PORTABLE:
    -                affix += goog.i18n.currency.getPortableCurrencySign(
    -                    this.intlCurrencyCode_);
    -                break;
    -              default:
    -                break;
    -            }
    -          }
    -          break;
    -        case goog.i18n.NumberFormat.PATTERN_PERCENT_:
    -          if (this.multiplier_ != 1) {
    -            throw Error('Too many percent/permill');
    -          }
    -          this.multiplier_ = 100;
    -          affix += goog.i18n.NumberFormatSymbols.PERCENT;
    -          break;
    -        case goog.i18n.NumberFormat.PATTERN_PER_MILLE_:
    -          if (this.multiplier_ != 1) {
    -            throw Error('Too many percent/permill');
    -          }
    -          this.multiplier_ = 1000;
    -          affix += goog.i18n.NumberFormatSymbols.PERMILL;
    -          break;
    -        default:
    -          affix += ch;
    -      }
    -    }
    -  }
    -
    -  return affix;
    -};
    -
    -
    -/**
    - * Parses the trunk part of a pattern.
    - *
    - * @param {string} pattern Pattern string that need to be parsed.
    - * @param {Array<number>} pos One element position array to set and receive
    - *     parsing position.
    - * @private
    - */
    -goog.i18n.NumberFormat.prototype.parseTrunk_ = function(pattern, pos) {
    -  var decimalPos = -1;
    -  var digitLeftCount = 0;
    -  var zeroDigitCount = 0;
    -  var digitRightCount = 0;
    -  var groupingCount = -1;
    -
    -  var len = pattern.length;
    -  for (var loop = true; pos[0] < len && loop; pos[0]++) {
    -    var ch = pattern.charAt(pos[0]);
    -    switch (ch) {
    -      case goog.i18n.NumberFormat.PATTERN_DIGIT_:
    -        if (zeroDigitCount > 0) {
    -          digitRightCount++;
    -        } else {
    -          digitLeftCount++;
    -        }
    -        if (groupingCount >= 0 && decimalPos < 0) {
    -          groupingCount++;
    -        }
    -        break;
    -      case goog.i18n.NumberFormat.PATTERN_ZERO_DIGIT_:
    -        if (digitRightCount > 0) {
    -          throw Error('Unexpected "0" in pattern "' + pattern + '"');
    -        }
    -        zeroDigitCount++;
    -        if (groupingCount >= 0 && decimalPos < 0) {
    -          groupingCount++;
    -        }
    -        break;
    -      case goog.i18n.NumberFormat.PATTERN_GROUPING_SEPARATOR_:
    -        groupingCount = 0;
    -        break;
    -      case goog.i18n.NumberFormat.PATTERN_DECIMAL_SEPARATOR_:
    -        if (decimalPos >= 0) {
    -          throw Error('Multiple decimal separators in pattern "' +
    -                      pattern + '"');
    -        }
    -        decimalPos = digitLeftCount + zeroDigitCount + digitRightCount;
    -        break;
    -      case goog.i18n.NumberFormat.PATTERN_EXPONENT_:
    -        if (this.useExponentialNotation_) {
    -          throw Error('Multiple exponential symbols in pattern "' +
    -                      pattern + '"');
    -        }
    -        this.useExponentialNotation_ = true;
    -        this.minExponentDigits_ = 0;
    -
    -        // exponent pattern can have a optional '+'.
    -        if ((pos[0] + 1) < len && pattern.charAt(pos[0] + 1) ==
    -            goog.i18n.NumberFormat.PATTERN_PLUS_) {
    -          pos[0]++;
    -          this.useSignForPositiveExponent_ = true;
    -        }
    -
    -        // Use lookahead to parse out the exponential part
    -        // of the pattern, then jump into phase 2.
    -        while ((pos[0] + 1) < len && pattern.charAt(pos[0] + 1) ==
    -               goog.i18n.NumberFormat.PATTERN_ZERO_DIGIT_) {
    -          pos[0]++;
    -          this.minExponentDigits_++;
    -        }
    -
    -        if ((digitLeftCount + zeroDigitCount) < 1 ||
    -            this.minExponentDigits_ < 1) {
    -          throw Error('Malformed exponential pattern "' + pattern + '"');
    -        }
    -        loop = false;
    -        break;
    -      default:
    -        pos[0]--;
    -        loop = false;
    -        break;
    -    }
    -  }
    -
    -  if (zeroDigitCount == 0 && digitLeftCount > 0 && decimalPos >= 0) {
    -    // Handle '###.###' and '###.' and '.###'
    -    var n = decimalPos;
    -    if (n == 0) { // Handle '.###'
    -      n++;
    -    }
    -    digitRightCount = digitLeftCount - n;
    -    digitLeftCount = n - 1;
    -    zeroDigitCount = 1;
    -  }
    -
    -  // Do syntax checking on the digits.
    -  if (decimalPos < 0 && digitRightCount > 0 ||
    -      decimalPos >= 0 && (decimalPos < digitLeftCount ||
    -                          decimalPos > digitLeftCount + zeroDigitCount) ||
    -      groupingCount == 0) {
    -    throw Error('Malformed pattern "' + pattern + '"');
    -  }
    -  var totalDigits = digitLeftCount + zeroDigitCount + digitRightCount;
    -
    -  this.maximumFractionDigits_ = decimalPos >= 0 ? totalDigits - decimalPos : 0;
    -  if (decimalPos >= 0) {
    -    this.minimumFractionDigits_ = digitLeftCount + zeroDigitCount - decimalPos;
    -    if (this.minimumFractionDigits_ < 0) {
    -      this.minimumFractionDigits_ = 0;
    -    }
    -  }
    -
    -  // The effectiveDecimalPos is the position the decimal is at or would be at
    -  // if there is no decimal. Note that if decimalPos<0, then digitTotalCount ==
    -  // digitLeftCount + zeroDigitCount.
    -  var effectiveDecimalPos = decimalPos >= 0 ? decimalPos : totalDigits;
    -  this.minimumIntegerDigits_ = effectiveDecimalPos - digitLeftCount;
    -  if (this.useExponentialNotation_) {
    -    this.maximumIntegerDigits_ = digitLeftCount + this.minimumIntegerDigits_;
    -
    -    // in exponential display, we need to at least show something.
    -    if (this.maximumFractionDigits_ == 0 && this.minimumIntegerDigits_ == 0) {
    -      this.minimumIntegerDigits_ = 1;
    -    }
    -  }
    -
    -  this.groupingSize_ = Math.max(0, groupingCount);
    -  this.decimalSeparatorAlwaysShown_ = decimalPos == 0 ||
    -                                      decimalPos == totalDigits;
    -};
    -
    -
    -/**
    - * Alias for the compact format 'unit' object.
    - * @typedef {{
    - *     prefix: string,
    - *     suffix: string,
    - *     divisorBase: number
    - * }}
    - */
    -goog.i18n.NumberFormat.CompactNumberUnit;
    -
    -
    -/**
    - * The empty unit, corresponding to a base of 0.
    - * @private {!goog.i18n.NumberFormat.CompactNumberUnit}
    - */
    -goog.i18n.NumberFormat.NULL_UNIT_ = { prefix: '', suffix: '', divisorBase: 0 };
    -
    -
    -/**
    - * Get compact unit for a certain number of digits
    - *
    - * @param {number} base The number of digits to get the unit for.
    - * @param {string} plurality The plurality of the number.
    - * @return {!goog.i18n.NumberFormat.CompactNumberUnit} The compact unit.
    - * @private
    - */
    -goog.i18n.NumberFormat.prototype.getUnitFor_ = function(base, plurality) {
    -  var table = this.compactStyle_ == goog.i18n.NumberFormat.CompactStyle.SHORT ?
    -      goog.i18n.CompactNumberFormatSymbols.COMPACT_DECIMAL_SHORT_PATTERN :
    -      goog.i18n.CompactNumberFormatSymbols.COMPACT_DECIMAL_LONG_PATTERN;
    -
    -  if (base < 3) {
    -    return goog.i18n.NumberFormat.NULL_UNIT_;
    -  } else {
    -    base = Math.min(14, base);
    -    var patterns = table[Math.pow(10, base)];
    -    if (!patterns) {
    -      return goog.i18n.NumberFormat.NULL_UNIT_;
    -    }
    -
    -    var pattern = patterns[plurality];
    -    if (!pattern || pattern == '0') {
    -      return goog.i18n.NumberFormat.NULL_UNIT_;
    -    }
    -
    -    var parts = /([^0]*)(0+)(.*)/.exec(pattern);
    -    if (!parts) {
    -      return goog.i18n.NumberFormat.NULL_UNIT_;
    -    }
    -
    -    return {
    -      prefix: parts[1],
    -      suffix: parts[3],
    -      divisorBase: base - (parts[2].length - 1)
    -    };
    -  }
    -};
    -
    -
    -/**
    - * Get the compact unit divisor, accounting for rounding of the quantity.
    - *
    - * @param {number} formattingNumber The number to base the formatting on. The
    - *     unit will be calculated from this number.
    - * @param {number} pluralityNumber The number to use for calculating the
    - *     plurality.
    - * @return {!goog.i18n.NumberFormat.CompactNumberUnit} The unit after rounding.
    - * @private
    - */
    -goog.i18n.NumberFormat.prototype.getUnitAfterRounding_ =
    -    function(formattingNumber, pluralityNumber) {
    -  if (this.compactStyle_ == goog.i18n.NumberFormat.CompactStyle.NONE) {
    -    return goog.i18n.NumberFormat.NULL_UNIT_;
    -  }
    -
    -  formattingNumber = Math.abs(formattingNumber);
    -  pluralityNumber = Math.abs(pluralityNumber);
    -
    -  var initialPlurality = this.pluralForm_(formattingNumber);
    -  // Compute the exponent from the formattingNumber, to compute the unit.
    -  var base = formattingNumber <= 1 ? 0 : this.intLog10_(formattingNumber);
    -  var initialDivisor = this.getUnitFor_(base, initialPlurality).divisorBase;
    -  // Round both numbers based on the unit used.
    -  var pluralityAttempt = pluralityNumber / Math.pow(10, initialDivisor);
    -  var pluralityRounded = this.roundNumber_(pluralityAttempt);
    -  var formattingAttempt = formattingNumber / Math.pow(10, initialDivisor);
    -  var formattingRounded = this.roundNumber_(formattingAttempt);
    -  // Compute the plurality of the pluralityNumber when formatted using the name
    -  // units as the formattingNumber.
    -  var finalPlurality =
    -      this.pluralForm_(pluralityRounded.intValue + pluralityRounded.fracValue);
    -  // Get the final unit, using the rounded formatting number to get the correct
    -  // unit, and the plurality computed from the pluralityNumber.
    -  return this.getUnitFor_(
    -      initialDivisor + this.intLog10_(formattingRounded.intValue),
    -      finalPlurality);
    -};
    -
    -
    -/**
    - * Get the integer base 10 logarithm of a number.
    - *
    - * @param {number} number The number to log.
    - * @return {number} The lowest integer n such that 10^n >= number.
    - * @private
    - */
    -goog.i18n.NumberFormat.prototype.intLog10_ = function(number) {
    -  // Turns out Math.log(1000000)/Math.LN10 is strictly less than 6.
    -  var i = 0;
    -  while ((number /= 10) >= 1) i++;
    -  return i;
    -};
    -
    -
    -/**
    - * Round to a certain number of significant digits.
    - *
    - * @param {number} number The number to round.
    - * @param {number} significantDigits The number of significant digits
    - *     to round to.
    - * @param {number} scale Treat number as fixed point times 10^scale.
    - * @return {number} The rounded number.
    - * @private
    - */
    -goog.i18n.NumberFormat.prototype.roundToSignificantDigits_ =
    -    function(number, significantDigits, scale) {
    -  if (!number)
    -    return number;
    -
    -  var digits = this.intLog10_(number);
    -  var magnitude = significantDigits - digits - 1;
    -
    -  // Only round fraction, not (potentially shifted) integers.
    -  if (magnitude < -scale) {
    -    var point = Math.pow(10, scale);
    -    return Math.round(number / point) * point;
    -  }
    -
    -  var power = Math.pow(10, magnitude);
    -  var shifted = Math.round(number * power);
    -  return shifted / power;
    -};
    -
    -
    -/**
    - * Get the plural form of a number.
    - * @param {number} quantity The quantity to find plurality of.
    - * @return {string} One of 'zero', 'one', 'two', 'few', 'many', 'other'.
    - * @private
    - */
    -goog.i18n.NumberFormat.prototype.pluralForm_ = function(quantity) {
    -  /* TODO: Implement */
    -  return 'other';
    -};
    -
    -
    -/**
    - * Checks if the currency symbol comes before the value ($12) or after (12$)
    - * Handy for applications that need to have separate UI fields for the currency
    - * value and symbol, especially for input: Price: [USD] [123.45]
    - * The currency symbol might be a combo box, or a label.
    - *
    - * @return {boolean} true if currency is before value.
    - */
    -goog.i18n.NumberFormat.prototype.isCurrencyCodeBeforeValue = function() {
    -  var posCurrSymbol = this.pattern_.indexOf('\u00A4'); // '¤' Currency sign
    -  var posPound = this.pattern_.indexOf('#');
    -  var posZero = this.pattern_.indexOf('0');
    -
    -  // posCurrValue is the first '#' or '0' found.
    -  // If none of them is found (not possible, but still),
    -  // the result is true (postCurrSymbol < MAX_VALUE)
    -  // That is OK, matches the en_US and ROOT locales.
    -  var posCurrValue = Number.MAX_VALUE;
    -  if (posPound >= 0 && posPound < posCurrValue) {
    -    posCurrValue = posPound;
    -  }
    -  if (posZero >= 0 && posZero < posCurrValue) {
    -    posCurrValue = posZero;
    -  }
    -
    -  // No need to test, it is guaranteed that both these symbols exist.
    -  // If not, we have bigger problems than this.
    -  return posCurrSymbol < posCurrValue;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/numberformat_test.html b/src/database/third_party/closure-library/closure/goog/i18n/numberformat_test.html
    deleted file mode 100644
    index 0bfbcedfb94..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/numberformat_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.i18n.NumberFormat
    -  </title>
    -  <meta charset="utf-8" />
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.i18n.NumberFormatTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/numberformat_test.js b/src/database/third_party/closure-library/closure/goog/i18n/numberformat_test.js
    deleted file mode 100644
    index 8e368747fa3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/numberformat_test.js
    +++ /dev/null
    @@ -1,1050 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.i18n.NumberFormatTest');
    -goog.setTestOnly('goog.i18n.NumberFormatTest');
    -
    -goog.require('goog.i18n.CompactNumberFormatSymbols');
    -goog.require('goog.i18n.CompactNumberFormatSymbols_de');
    -goog.require('goog.i18n.CompactNumberFormatSymbols_en');
    -goog.require('goog.i18n.CompactNumberFormatSymbols_fr');
    -goog.require('goog.i18n.NumberFormat');
    -goog.require('goog.i18n.NumberFormatSymbols');
    -goog.require('goog.i18n.NumberFormatSymbols_de');
    -goog.require('goog.i18n.NumberFormatSymbols_en');
    -goog.require('goog.i18n.NumberFormatSymbols_fr');
    -goog.require('goog.i18n.NumberFormatSymbols_pl');
    -goog.require('goog.i18n.NumberFormatSymbols_ro');
    -goog.require('goog.testing.ExpectedFailures');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -goog.require('goog.userAgent.product');
    -goog.require('goog.userAgent.product.isVersion');
    -
    -var expectedFailures;
    -
    -var stubs = new goog.testing.PropertyReplacer();
    -
    -function setUpPage() {
    -  expectedFailures = new goog.testing.ExpectedFailures();
    -}
    -
    -function setUp() {
    -  // Always switch back to English on startup.
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en;
    -  goog.i18n.CompactNumberFormatSymbols =
    -      goog.i18n.CompactNumberFormatSymbols_en;
    -}
    -
    -function tearDown() {
    -  expectedFailures.handleTearDown();
    -  stubs.reset();
    -}
    -
    -function veryBigNumberCompare(str1, str2) {
    -  return str1.length == str2.length &&
    -         str1.substring(0, 8) == str2.substring(0, 8);
    -}
    -
    -function testVeryBigNumber() {
    -  var str;
    -  var fmt = new goog.i18n.NumberFormat(goog.i18n.NumberFormat.Format.CURRENCY);
    -  str = fmt.format(1785599999999999888888888888888);
    -  // when comparing big number, various platform have small different in
    -  // precision. We have to tolerate that using veryBigNumberCompare.
    -  var expected = '$1,785,599,999,999,999,400,000,000,000,000.00';
    -  assertTrue(veryBigNumberCompare(
    -      '$1,785,599,999,999,999,400,000,000,000,000.00', str));
    -  str = fmt.format(1.7856E30);
    -  assertTrue(veryBigNumberCompare(
    -      '$1,785,599,999,999,999,400,000,000,000,000.00', str));
    -  str = fmt.format(1.3456E20);
    -  assertTrue(veryBigNumberCompare('$134,560,000,000,000,000,000.00', str));
    -
    -  fmt = new goog.i18n.NumberFormat(goog.i18n.NumberFormat.Format.DECIMAL);
    -  str = fmt.format(1.3456E20);
    -  assertTrue(veryBigNumberCompare('134,559,999,999,999,980,000', str));
    -
    -
    -  fmt = new goog.i18n.NumberFormat(goog.i18n.NumberFormat.Format.PERCENT);
    -  str = fmt.format(1.3456E20);
    -  assertTrue(veryBigNumberCompare('13,456,000,000,000,000,000,000%', str));
    -
    -  fmt = new goog.i18n.NumberFormat(
    -      goog.i18n.NumberFormat.Format.SCIENTIFIC);
    -  str = fmt.format(1.3456E20);
    -  assertEquals('1E20', str);
    -
    -  fmt = new goog.i18n.NumberFormat(
    -      goog.i18n.NumberFormat.Format.DECIMAL);
    -  str = fmt.format(-1.234567890123456e306);
    -  assertEquals(1 + 1 + 306 + 306 / 3, str.length);
    -  assertEquals('-1,234,567,890,123,45', str.substr(0, 21));
    -
    -  str = fmt.format(Infinity);
    -  assertEquals('\u221e', str);
    -  str = fmt.format(-Infinity);
    -  assertEquals('-\u221e', str);
    -}
    -
    -function testStandardFormat() {
    -  var str;
    -  var fmt = new goog.i18n.NumberFormat(
    -      goog.i18n.NumberFormat.Format.CURRENCY);
    -  str = fmt.format(1234.579);
    -  assertEquals('$1,234.58', str);
    -  fmt = new goog.i18n.NumberFormat(goog.i18n.NumberFormat.Format.DECIMAL);
    -  str = fmt.format(1234.579);
    -  assertEquals('1,234.579', str);
    -  fmt = new goog.i18n.NumberFormat(goog.i18n.NumberFormat.Format.PERCENT);
    -  str = fmt.format(1234.579);
    -  assertEquals('123,458%', str);
    -  fmt = new goog.i18n.NumberFormat(goog.i18n.NumberFormat.Format.SCIENTIFIC);
    -  str = fmt.format(1234.579);
    -  assertEquals('1E3', str);
    -  // Math.log(1000000)/Math.LN10 is strictly less than 6. Make sure it gets
    -  // formatted correctly.
    -  str = fmt.format(1000000);
    -  assertEquals('1E6', str);
    -}
    -
    -function testNegativePercentage() {
    -  var str;
    -  var fmt = new goog.i18n.NumberFormat('#,##0.00%');
    -  str = fmt.format(-1234.56);
    -  assertEquals('-123,456.00%', str);
    -
    -  fmt = new goog.i18n.NumberFormat(goog.i18n.NumberFormat.Format.PERCENT);
    -  str = fmt.format(-1234.579);
    -  assertEquals('-123,458%', str);
    -}
    -
    -function testCustomPercentage() {
    -  var fmt = new goog.i18n.NumberFormat(goog.i18n.NumberFormat.Format.PERCENT);
    -  fmt.setMaximumFractionDigits(1);
    -  fmt.setMinimumFractionDigits(1);
    -  var str = fmt.format(0.1291);
    -  assertEquals('12.9%', str);
    -  fmt.setMaximumFractionDigits(2);
    -  fmt.setMinimumFractionDigits(1);
    -  str = fmt.format(0.129);
    -  assertEquals('12.9%', str);
    -  fmt.setMaximumFractionDigits(2);
    -  fmt.setMinimumFractionDigits(1);
    -  str = fmt.format(0.12);
    -  assertEquals('12.0%', str);
    -  fmt.setMaximumFractionDigits(2);
    -  fmt.setMinimumFractionDigits(1);
    -  str = fmt.format(0.12911);
    -  assertEquals('12.91%', str);
    -}
    -
    -function testBasicParse() {
    -  var value;
    -
    -  var fmt = new goog.i18n.NumberFormat('0.0000');
    -  value = fmt.parse('123.4579');
    -  assertEquals(123.4579, value);
    -
    -  value = fmt.parse('+123.4579');
    -  assertEquals(123.4579, value);
    -
    -  value = fmt.parse('-123.4579');
    -  assertEquals(-123.4579, value);
    -}
    -
    -function testPrefixParse() {
    -  var value;
    -
    -  var fmt = new goog.i18n.NumberFormat('0.0;(0.0)');
    -  value = fmt.parse('123.4579');
    -  assertEquals(123.4579, value);
    -
    -  value = fmt.parse('(123.4579)');
    -  assertEquals(-123.4579, value);
    -}
    -
    -function testPrecentParse() {
    -  var value;
    -
    -  var fmt = new goog.i18n.NumberFormat('0.0;(0.0)');
    -  value = fmt.parse('123.4579%');
    -  assertEquals((123.4579 / 100), value);
    -
    -  value = fmt.parse('(%123.4579)');
    -  assertEquals((-123.4579 / 100), value);
    -
    -  value = fmt.parse('123.4579\u2030');
    -  assertEquals((123.4579 / 1000), value);
    -
    -  value = fmt.parse('(\u2030123.4579)');
    -  assertEquals((-123.4579 / 1000), value);
    -}
    -
    -function testPercentAndPerMillAdvance() {
    -  var value;
    -  var pos = [0];
    -  var fmt = new goog.i18n.NumberFormat('0');
    -  value = fmt.parse('120%', pos);
    -  assertEquals(1.2, value);
    -  assertEquals(4, pos[0]);
    -  pos[0] = 0;
    -  value = fmt.parse('120\u2030', pos);
    -  assertEquals(0.12, value);
    -  assertEquals(4, pos[0]);
    -}
    -
    -function testInfinityParse() {
    -  var value;
    -  var fmt = new goog.i18n.NumberFormat('0.0;(0.0)');
    -
    -  // gwt need to add those symbols first
    -  value = fmt.parse('\u221e');
    -  assertEquals(Number.POSITIVE_INFINITY, value);
    -
    -  value = fmt.parse('(\u221e)');
    -  assertEquals(Number.NEGATIVE_INFINITY, value);
    -}
    -function testExponentParse() {
    -  var value;
    -  var fmt;
    -
    -  fmt = new goog.i18n.NumberFormat('#E0');
    -  value = fmt.parse('1.234E3');
    -  assertEquals(1.234E+3, value);
    -
    -  fmt = new goog.i18n.NumberFormat('0.###E0');
    -  value = fmt.parse('1.234E3');
    -  assertEquals(1.234E+3, value);
    -
    -  fmt = new goog.i18n.NumberFormat('#E0');
    -  value = fmt.parse('1.2345E4');
    -  assertEquals(12345.0, value);
    -
    -  value = fmt.parse('1.2345E4');
    -  assertEquals(12345.0, value);
    -
    -  value = fmt.parse('1.2345E+4');
    -  assertEquals(12345.0, value);
    -}
    -
    -function testGroupingParse() {
    -  var value;
    -
    -  var fmt = new goog.i18n.NumberFormat('#,###');
    -  value = fmt.parse('1,234,567,890');
    -  assertEquals(1234567890, value);
    -  value = fmt.parse('12,3456,7890');
    -  assertEquals(1234567890, value);
    -
    -  fmt = new goog.i18n.NumberFormat('#');
    -  value = fmt.parse('1234567890');
    -  assertEquals(1234567890, value);
    -}
    -
    -function testBasicFormat() {
    -  var fmt = new goog.i18n.NumberFormat('0.0000');
    -  var str = fmt.format(123.45789179565757);
    -  assertEquals('123.4579', str);
    -}
    -
    -function testGrouping() {
    -  var str;
    -
    -  var fmt = new goog.i18n.NumberFormat('#,###');
    -  str = fmt.format(1234567890);
    -  assertEquals('1,234,567,890', str);
    -  fmt = new goog.i18n.NumberFormat('#,####');
    -  str = fmt.format(1234567890);
    -  assertEquals('12,3456,7890', str);
    -
    -  fmt = new goog.i18n.NumberFormat('#');
    -  str = fmt.format(1234567890);
    -  assertEquals('1234567890', str);
    -}
    -
    -function testPerMill() {
    -  var str;
    -
    -  var fmt = new goog.i18n.NumberFormat('###.###\u2030');
    -  str = fmt.format(0.4857);
    -  assertEquals('485.7\u2030', str);
    -}
    -
    -function testCurrency() {
    -  var str;
    -
    -  var fmt = new goog.i18n.NumberFormat('\u00a4#,##0.00;-\u00a4#,##0.00');
    -  str = fmt.format(1234.56);
    -  assertEquals('$1,234.56', str);
    -  str = fmt.format(-1234.56);
    -  assertEquals('-$1,234.56', str);
    -
    -  fmt = new goog.i18n.NumberFormat('\u00a4#,##0.00;-\u00a4#,##0.00', 'USD',
    -      goog.i18n.NumberFormat.CurrencyStyle.LOCAL);
    -  str = fmt.format(1234.56);
    -  assertEquals('$1,234.56', str);
    -  str = fmt.format(-1234.56);
    -  assertEquals('-$1,234.56', str);
    -  fmt = new goog.i18n.NumberFormat('\u00a4#,##0.00;-\u00a4#,##0.00', 'USD',
    -      goog.i18n.NumberFormat.CurrencyStyle.PORTABLE);
    -  str = fmt.format(1234.56);
    -  assertEquals('US$1,234.56', str);
    -  str = fmt.format(-1234.56);
    -  assertEquals('-US$1,234.56', str);
    -  fmt = new goog.i18n.NumberFormat('\u00a4#,##0.00;-\u00a4#,##0.00', 'USD',
    -      goog.i18n.NumberFormat.CurrencyStyle.GLOBAL);
    -  str = fmt.format(1234.56);
    -  assertEquals('USD $1,234.56', str);
    -  str = fmt.format(-1234.56);
    -  assertEquals('-USD $1,234.56', str);
    -
    -
    -  fmt = new goog.i18n.NumberFormat(
    -      '\u00a4\u00a4 #,##0.00;-\u00a4\u00a4 #,##0.00');
    -  str = fmt.format(1234.56);
    -  assertEquals('USD 1,234.56', str);
    -  fmt = new goog.i18n.NumberFormat(
    -      '\u00a4\u00a4 #,##0.00;\u00a4\u00a4 -#,##0.00');
    -  str = fmt.format(-1234.56);
    -  assertEquals('USD -1,234.56', str);
    -
    -  fmt = new goog.i18n.NumberFormat('\u00a4#,##0.00;-\u00a4#,##0.00', 'BRL');
    -  str = fmt.format(1234.56);
    -  assertEquals('R$1,234.56', str);
    -  str = fmt.format(-1234.56);
    -  assertEquals('-R$1,234.56', str);
    -
    -  fmt = new goog.i18n.NumberFormat(
    -      '\u00a4\u00a4 #,##0.00;(\u00a4\u00a4 #,##0.00)', 'BRL');
    -  str = fmt.format(1234.56);
    -  assertEquals('BRL 1,234.56', str);
    -  str = fmt.format(-1234.56);
    -  assertEquals('(BRL 1,234.56)', str);
    -}
    -
    -function testQuotes() {
    -  var str;
    -
    -  var fmt = new goog.i18n.NumberFormat('a\'fo\'\'o\'b#');
    -  str = fmt.format(123);
    -  assertEquals('afo\'ob123', str);
    -
    -  fmt = new goog.i18n.NumberFormat('a\'\'b#');
    -  str = fmt.format(123);
    -  assertEquals('a\'b123', str);
    -
    -  fmt = new goog.i18n.NumberFormat('a\'fo\'\'o\'b#');
    -  str = fmt.format(-123);
    -  assertEquals('afo\'ob-123', str);
    -
    -  fmt = new goog.i18n.NumberFormat('a\'\'b#');
    -  str = fmt.format(-123);
    -  assertEquals('a\'b-123', str);
    -}
    -
    -function testZeros() {
    -  var str;
    -  var fmt;
    -
    -  fmt = new goog.i18n.NumberFormat('#.#');
    -  str = fmt.format(0);
    -  assertEquals('0', str);
    -  fmt = new goog.i18n.NumberFormat('#.');
    -  str = fmt.format(0);
    -  assertEquals('0.', str);
    -  fmt = new goog.i18n.NumberFormat('.#');
    -  str = fmt.format(0);
    -  assertEquals('.0', str);
    -  fmt = new goog.i18n.NumberFormat('#');
    -  str = fmt.format(0);
    -  assertEquals('0', str);
    -
    -  fmt = new goog.i18n.NumberFormat('#0.#');
    -  str = fmt.format(0);
    -  assertEquals('0', str);
    -  fmt = new goog.i18n.NumberFormat('#0.');
    -  str = fmt.format(0);
    -  assertEquals('0.', str);
    -  fmt = new goog.i18n.NumberFormat('#.0');
    -  str = fmt.format(0);
    -  assertEquals('.0', str);
    -  fmt = new goog.i18n.NumberFormat('#');
    -  str = fmt.format(0);
    -  assertEquals('0', str);
    -  fmt = new goog.i18n.NumberFormat('000');
    -  str = fmt.format(0);
    -  assertEquals('000', str);
    -}
    -
    -function testExponential() {
    -  var str;
    -  var fmt;
    -
    -  fmt = new goog.i18n.NumberFormat('0.####E0');
    -  str = fmt.format(0.01234);
    -  assertEquals('1.234E-2', str);
    -  fmt = new goog.i18n.NumberFormat('00.000E00');
    -  str = fmt.format(0.01234);
    -  assertEquals('12.340E-03', str);
    -  fmt = new goog.i18n.NumberFormat('##0.######E000');
    -  str = fmt.format(0.01234);
    -  assertEquals('12.34E-003', str);
    -  fmt = new goog.i18n.NumberFormat('0.###E0;[0.###E0]');
    -  str = fmt.format(0.01234);
    -  assertEquals('1.234E-2', str);
    -
    -  fmt = new goog.i18n.NumberFormat('0.####E0');
    -  str = fmt.format(123456789);
    -  assertEquals('1.2346E8', str);
    -  fmt = new goog.i18n.NumberFormat('00.000E00');
    -  str = fmt.format(123456789);
    -  assertEquals('12.346E07', str);
    -  fmt = new goog.i18n.NumberFormat('##0.######E000');
    -  str = fmt.format(123456789);
    -  assertEquals('123.456789E006', str);
    -  fmt = new goog.i18n.NumberFormat('0.###E0;[0.###E0]');
    -  str = fmt.format(123456789);
    -  assertEquals('1.235E8', str);
    -
    -  fmt = new goog.i18n.NumberFormat('0.####E0');
    -  str = fmt.format(1.23e300);
    -  assertEquals('1.23E300', str);
    -  fmt = new goog.i18n.NumberFormat('00.000E00');
    -  str = fmt.format(1.23e300);
    -  assertEquals('12.300E299', str);
    -  fmt = new goog.i18n.NumberFormat('##0.######E000');
    -  str = fmt.format(1.23e300);
    -  assertEquals('1.23E300', str);
    -  fmt = new goog.i18n.NumberFormat('0.###E0;[0.###E0]');
    -  str = fmt.format(1.23e300);
    -  assertEquals('1.23E300', str);
    -
    -  fmt = new goog.i18n.NumberFormat('0.####E0');
    -  str = fmt.format(-3.141592653e-271);
    -  assertEquals('-3.1416E-271', str);
    -  fmt = new goog.i18n.NumberFormat('00.000E00');
    -  str = fmt.format(-3.141592653e-271);
    -  assertEquals('-31.416E-272', str);
    -  fmt = new goog.i18n.NumberFormat('##0.######E000');
    -  str = fmt.format(-3.141592653e-271);
    -  assertEquals('-314.159265E-273', str);
    -  fmt = new goog.i18n.NumberFormat('0.###E0;[0.###E0]');
    -  str = fmt.format(-3.141592653e-271);
    -  assertEquals('[3.142E-271]', str);
    -
    -  fmt = new goog.i18n.NumberFormat('0.####E0');
    -  str = fmt.format(0);
    -  assertEquals('0E0', str);
    -  fmt = new goog.i18n.NumberFormat('00.000E00');
    -  str = fmt.format(0);
    -  assertEquals('00.000E00', str);
    -  fmt = new goog.i18n.NumberFormat('##0.######E000');
    -  str = fmt.format(0);
    -  assertEquals('0E000', str);
    -  fmt = new goog.i18n.NumberFormat('0.###E0;[0.###E0]');
    -  str = fmt.format(0);
    -  assertEquals('0E0', str);
    -
    -  fmt = new goog.i18n.NumberFormat('0.####E0');
    -  str = fmt.format(-1);
    -  assertEquals('-1E0', str);
    -  fmt = new goog.i18n.NumberFormat('00.000E00');
    -  str = fmt.format(-1);
    -  assertEquals('-10.000E-01', str);
    -  fmt = new goog.i18n.NumberFormat('##0.######E000');
    -  str = fmt.format(-1);
    -  assertEquals('-1E000', str);
    -  fmt = new goog.i18n.NumberFormat('0.###E0;[0.###E0]');
    -  str = fmt.format(-1);
    -  assertEquals('[1E0]', str);
    -
    -  fmt = new goog.i18n.NumberFormat('0.####E0');
    -  str = fmt.format(1);
    -  assertEquals('1E0', str);
    -  fmt = new goog.i18n.NumberFormat('00.000E00');
    -  str = fmt.format(1);
    -  assertEquals('10.000E-01', str);
    -  fmt = new goog.i18n.NumberFormat('##0.######E000');
    -  str = fmt.format(1);
    -  assertEquals('1E000', str);
    -  fmt = new goog.i18n.NumberFormat('0.###E0;[0.###E0]');
    -  str = fmt.format(1);
    -  assertEquals('1E0', str);
    -
    -  fmt = new goog.i18n.NumberFormat('#E0');
    -  str = fmt.format(12345.0);
    -  assertEquals('1E4', str);
    -  fmt = new goog.i18n.NumberFormat('0E0');
    -  str = fmt.format(12345.0);
    -  assertEquals('1E4', str);
    -  fmt = new goog.i18n.NumberFormat('##0.###E0');
    -  str = fmt.format(12345.0);
    -  assertEquals('12.345E3', str);
    -  fmt = new goog.i18n.NumberFormat('##0.###E0');
    -  str = fmt.format(12345.00001);
    -  assertEquals('12.345E3', str);
    -  fmt = new goog.i18n.NumberFormat('##0.###E0');
    -  str = fmt.format(12345);
    -  assertEquals('12.345E3', str);
    -
    -  fmt = new goog.i18n.NumberFormat('##0.####E0');
    -  str = fmt.format(789.12345e-9);
    -  // Firefox 3.6.3 Linux is known to fail here with a rounding error.
    -  // fmt.format will return '789.1234E-9'.
    -  expectedFailures.expectFailureFor(isFirefox363Linux());
    -  try {
    -    assertEquals('789.1235E-9', str);
    -  } catch (e) {
    -    expectedFailures.handleException(e);
    -  }
    -  fmt = new goog.i18n.NumberFormat('##0.####E0');
    -  str = fmt.format(780.e-9);
    -  assertEquals('780E-9', str);
    -  fmt = new goog.i18n.NumberFormat('.###E0');
    -  str = fmt.format(45678.0);
    -  assertEquals('.457E5', str);
    -  fmt = new goog.i18n.NumberFormat('.###E0');
    -  str = fmt.format(0);
    -  assertEquals('.0E0', str);
    -
    -  fmt = new goog.i18n.NumberFormat('#E0');
    -  str = fmt.format(45678000);
    -  assertEquals('5E7', str);
    -  fmt = new goog.i18n.NumberFormat('##E0');
    -  str = fmt.format(45678000);
    -  assertEquals('46E6', str);
    -  fmt = new goog.i18n.NumberFormat('####E0');
    -  str = fmt.format(45678000);
    -  assertEquals('4568E4', str);
    -  fmt = new goog.i18n.NumberFormat('0E0');
    -  str = fmt.format(45678000);
    -  assertEquals('5E7', str);
    -  fmt = new goog.i18n.NumberFormat('00E0');
    -  str = fmt.format(45678000);
    -  assertEquals('46E6', str);
    -  fmt = new goog.i18n.NumberFormat('000E0');
    -  str = fmt.format(45678000);
    -  assertEquals('457E5', str);
    -  fmt = new goog.i18n.NumberFormat('###E0');
    -  str = fmt.format(0.0000123);
    -  assertEquals('12E-6', str);
    -  fmt = new goog.i18n.NumberFormat('###E0');
    -  str = fmt.format(0.000123);
    -  assertEquals('123E-6', str);
    -  fmt = new goog.i18n.NumberFormat('###E0');
    -  str = fmt.format(0.00123);
    -  assertEquals('1E-3', str);
    -  fmt = new goog.i18n.NumberFormat('###E0');
    -  str = fmt.format(0.0123);
    -  assertEquals('12E-3', str);
    -  fmt = new goog.i18n.NumberFormat('###E0');
    -  str = fmt.format(0.123);
    -  assertEquals('123E-3', str);
    -  fmt = new goog.i18n.NumberFormat('###E0');
    -  str = fmt.format(1.23);
    -  assertEquals('1E0', str);
    -  fmt = new goog.i18n.NumberFormat('###E0');
    -  str = fmt.format(12.3);
    -  assertEquals('12E0', str);
    -  fmt = new goog.i18n.NumberFormat('###E0');
    -  str = fmt.format(123.0);
    -  assertEquals('123E0', str);
    -  fmt = new goog.i18n.NumberFormat('###E0');
    -  str = fmt.format(1230.0);
    -  assertEquals('1E3', str);
    -}
    -
    -function testPlusSignInExponentPart() {
    -  var fmt;
    -  fmt = new goog.i18n.NumberFormat('0E+0');
    -  str = fmt.format(45678000);
    -  assertEquals('5E+7', str);
    -}
    -
    -function testGroupingParse2() {
    -  var value;
    -  var fmt;
    -
    -  fmt = new goog.i18n.NumberFormat('#,###');
    -  value = fmt.parse('1,234,567,890');
    -  assertEquals(1234567890, value);
    -  fmt = new goog.i18n.NumberFormat('#,###');
    -  value = fmt.parse('12,3456,7890');
    -  assertEquals(1234567890, value);
    -
    -  fmt = new goog.i18n.NumberFormat('#');
    -  value = fmt.parse('1234567890');
    -  assertEquals(1234567890, value);
    -}
    -
    -function testApis() {
    -  var fmt;
    -  var str;
    -
    -  fmt = new goog.i18n.NumberFormat('#,###');
    -  str = fmt.format(1234567890);
    -  assertEquals('1,234,567,890', str);
    -
    -  fmt = new goog.i18n.NumberFormat('\u00a4#,##0.00;-\u00a4#,##0.00');
    -  str = fmt.format(1234.56);
    -  assertEquals('$1,234.56', str);
    -  fmt = new goog.i18n.NumberFormat('\u00a4#,##0.00;(\u00a4#,##0.00)');
    -  str = fmt.format(-1234.56);
    -  assertEquals('($1,234.56)', str);
    -
    -  fmt = new goog.i18n.NumberFormat('\u00a4#,##0.00;-\u00a4#,##0.00', 'SEK');
    -  str = fmt.format(1234.56);
    -  assertEquals('kr1,234.56', str);
    -  fmt = new goog.i18n.NumberFormat('\u00a4#,##0.00;(\u00a4#,##0.00)', 'SEK');
    -  str = fmt.format(-1234.56);
    -  assertEquals('(kr1,234.56)', str);
    -}
    -
    -function testLocaleSwitch() {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr;
    -
    -  // When this test is performed in test cluster, 2 out of 60 machines have
    -  // problem getting the symbol. It is likely to be caused by size of uncompiled
    -  // symbol file. There will not be an issue after it is compiled.
    -  if (goog.i18n.NumberFormatSymbols.DECIMAL_SEP ==
    -      goog.i18n.NumberFormatSymbols_en.DECIMAL_SEP) {
    -    // fails to load French symbols, skip the test.
    -    return;
    -  }
    -
    -  var fmt = new goog.i18n.NumberFormat('#,###');
    -  var str = fmt.format(1234567890);
    -  assertEquals('1\u00a0234\u00a0567\u00a0890', str);
    -
    -  fmt = new goog.i18n.NumberFormat('\u00a4#,##0.00;-\u00a4#,##0.00');
    -  str = fmt.format(1234.56);
    -  assertEquals('\u20AC1\u00a0234,56', str);
    -  fmt = new goog.i18n.NumberFormat('\u00a4#,##0.00;(\u00a4#,##0.00)');
    -  str = fmt.format(-1234.56);
    -  assertEquals('(\u20AC1\u00a0234,56)', str);
    -
    -  fmt = new goog.i18n.NumberFormat('\u00a4#,##0.00;-\u00a4#,##0.00', 'SEK');
    -  str = fmt.format(1234.56);
    -  assertEquals('kr1\u00a0234,56', str);
    -  fmt = new goog.i18n.NumberFormat('\u00a4#,##0.00;(\u00a4#,##0.00)', 'SEK');
    -  str = fmt.format(-1234.56);
    -  assertEquals('(kr1\u00a0234,56)', str);
    -}
    -
    -function testFrenchParse() {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr;
    -
    -  // When this test is performed in test cluster, 2 out of 60 machines have
    -  // problem getting the symbol. It is likely to be caused by size of uncompiled
    -  // symbol file. There will not be an issue after it is compiled.
    -  if (goog.i18n.NumberFormatSymbols.DECIMAL_SEP ==
    -      goog.i18n.NumberFormatSymbols_en.DECIMAL_SEP) {
    -    // fails to load French symbols, skip the test.
    -    return;
    -  }
    -
    -  var fmt = new goog.i18n.NumberFormat('0.0000');
    -  var value = fmt.parse('0,30');
    -  assertEquals(0.30, value);
    -
    -  fmt = new goog.i18n.NumberFormat(goog.i18n.NumberFormat.Format.CURRENCY);
    -  value = fmt.parse('0,30\u00A0\u20AC');
    -  assertEquals(0.30, value);
    -  fmt = new goog.i18n.NumberFormat('#,##0.00');
    -  value = fmt.parse('123 456,99');
    -  assertEquals(123456.99, value);
    -
    -  fmt = new goog.i18n.NumberFormat('#,##0.00');
    -  value = fmt.parse('123\u00a0456,99');
    -  assertEquals(123456.99, value);
    -
    -  fmt = new goog.i18n.NumberFormat('#,##0.00');
    -  value = fmt.parse('8 123\u00a0456,99');
    -  assertEquals(8123456.99, value);
    -}
    -
    -
    -function testFailParseShouldThrow() {
    -  var fmt = new goog.i18n.NumberFormat('0.0000');
    -  var value = fmt.parse('x');
    -  assertNaN(value);
    -
    -  fmt = new goog.i18n.NumberFormat('0.000x');
    -  value = fmt.parse('3y');
    -  assertNaN(value);
    -
    -  fmt = new goog.i18n.NumberFormat('x0.000');
    -  value = fmt.parse('y3');
    -  assertNaN(value);
    -}
    -
    -
    -/**
    - * @return {boolean} Whether we're on Linux Firefox 3.6.3.
    - */
    -function isFirefox363Linux() {
    -  return goog.userAgent.product.FIREFOX && goog.userAgent.LINUX &&
    -      goog.userAgent.product.isVersion('3.6.3') &&
    -      !goog.userAgent.product.isVersion('3.6.4');
    -}
    -
    -
    -function testEnforceAscii() {
    -  try {
    -    goog.i18n.NumberFormatSymbols.ZERO_DIGIT = 'A';
    -    var fmt = new goog.i18n.NumberFormat('0.0000');
    -    var str = fmt.format(123.45789179565757);
    -    assertEquals('BCD.EFHJ', str);
    -    goog.i18n.NumberFormat.setEnforceAsciiDigits(true);
    -    str = fmt.format(123.45789179565757);
    -    assertEquals('123.4579', str);
    -    goog.i18n.NumberFormat.setEnforceAsciiDigits(false);
    -    str = fmt.format(123.45789179565757);
    -    assertEquals('BCD.EFHJ', str);
    -  } finally {
    -    goog.i18n.NumberFormatSymbols.ZERO_DIGIT = '0';
    -  }
    -}
    -
    -function testFractionDigits() {
    -  var fmt = new goog.i18n.NumberFormat(goog.i18n.NumberFormat.Format.DECIMAL);
    -  fmt.setMinimumFractionDigits(4);
    -  fmt.setMaximumFractionDigits(6);
    -  assertEquals('0.1230', fmt.format(0.123));
    -  assertEquals('0.123456', fmt.format(0.123456));
    -  assertEquals('0.123457', fmt.format(0.12345678));
    -}
    -
    -function testFractionDigitsSetOutOfOrder() {
    -  var fmt = new goog.i18n.NumberFormat(goog.i18n.NumberFormat.Format.DECIMAL);
    -  // First, setup basic min/max
    -  fmt.setMinimumFractionDigits(2);
    -  fmt.setMaximumFractionDigits(2);
    -  // Now change to a lower min & max, but change the max value first so that it
    -  // is temporarily less than the current "min" value.  This makes sure that we
    -  // don't throw an error.
    -  fmt.setMaximumFractionDigits(1);
    -  fmt.setMinimumFractionDigits(1);
    -  assertEquals('2.3', fmt.format(2.34));
    -}
    -
    -function testFractionDigitsInvalid() {
    -  var fmt = new goog.i18n.NumberFormat(goog.i18n.NumberFormat.Format.DECIMAL);
    -  fmt.setMinimumFractionDigits(2);
    -  fmt.setMaximumFractionDigits(1);
    -  try {
    -    fmt.format(0.123);
    -    fail('Should have thrown exception.');
    -  } catch (e) {}
    -}
    -
    -function testSignificantDigitsEqualToMax() {
    -  var fmt = new goog.i18n.NumberFormat(goog.i18n.NumberFormat.Format.DECIMAL);
    -  fmt.setMinimumFractionDigits(0);
    -  fmt.setMaximumFractionDigits(2);
    -
    -  fmt.setSignificantDigits(2);
    -  assertEquals('123', fmt.format(123.4));
    -  assertEquals('12', fmt.format(12.34));
    -  assertEquals('1.2', fmt.format(1.234));
    -  assertEquals('0.12', fmt.format(0.1234));
    -  assertEquals('0.13', fmt.format(0.1284));
    -}
    -
    -function testSignificantDigitsLessThanMax() {
    -  var fmt = new goog.i18n.NumberFormat(goog.i18n.NumberFormat.Format.DECIMAL);
    -  fmt.setMinimumFractionDigits(0);
    -  fmt.setMaximumFractionDigits(4);
    -  fmt.setSignificantDigits(1);
    -
    -  assertEquals('123', fmt.format(123.4));
    -  assertEquals('12', fmt.format(12.34));
    -  assertEquals('1', fmt.format(1.234));
    -  assertEquals('0.1', fmt.format(0.1234));
    -  assertEquals('0.2', fmt.format(0.1834));
    -}
    -
    -function testSignificantDigitsMoreThanMax() {
    -  // Max fractional digits should be absolute
    -  var fmt = new goog.i18n.NumberFormat(goog.i18n.NumberFormat.Format.DECIMAL);
    -  fmt.setMinimumFractionDigits(0);
    -  fmt.setMaximumFractionDigits(2);
    -  fmt.setSignificantDigits(3);
    -
    -  assertEquals('123', fmt.format(123.4));
    -  assertEquals('12.3', fmt.format(12.34));
    -  assertEquals('1.23', fmt.format(1.234));
    -  assertEquals('0.12', fmt.format(0.1234));
    -  assertEquals('0.13', fmt.format(0.1284));
    -}
    -
    -function testSimpleCompactFrench() {
    -  // Switch to French.
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr;
    -  goog.i18n.CompactNumberFormatSymbols =
    -      goog.i18n.CompactNumberFormatSymbols_fr;
    -
    -  var fmt = new goog.i18n.NumberFormat(
    -      goog.i18n.NumberFormat.Format.COMPACT_SHORT);
    -
    -  var str = fmt.format(123400000);
    -  assertEquals('123\u00A0M', str);
    -}
    -
    -function testSimpleCompactGerman() {
    -  // Switch to German.
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_de;
    -  goog.i18n.CompactNumberFormatSymbols =
    -      goog.i18n.CompactNumberFormatSymbols_de;
    -
    -  var fmt = new goog.i18n.NumberFormat(
    -      goog.i18n.NumberFormat.Format.COMPACT_SHORT);
    -
    -  // The german short compact decimal has a simple '0' for 1000's, which is
    -  // supposed to be interpreted as 'leave the number as-is'.
    -  // (The number itself will still be formatted with the '.', but no rounding)
    -  var str = fmt.format(1234);
    -  assertEquals('1,2\u00A0Tsd.', str);
    -}
    -
    -function testSimpleCompact1() {
    -  var fmt = new goog.i18n.NumberFormat(
    -      goog.i18n.NumberFormat.Format.COMPACT_SHORT);
    -
    -  var str = fmt.format(1234);
    -  assertEquals('1.2K', str);
    -}
    -
    -function testSimpleCompact2() {
    -  var fmt = new goog.i18n.NumberFormat(
    -      goog.i18n.NumberFormat.Format.COMPACT_SHORT);
    -
    -  var str = fmt.format(12345);
    -  assertEquals('12K', str);
    -}
    -
    -function testRoundingCompact() {
    -  var fmt = new goog.i18n.NumberFormat(
    -      goog.i18n.NumberFormat.Format.COMPACT_SHORT);
    -
    -  var str = fmt.format(999999);
    -  assertEquals('1M', str); //as opposed to 1000k
    -}
    -
    -function testRoundingCompactNegative() {
    -  var fmt = new goog.i18n.NumberFormat(
    -      goog.i18n.NumberFormat.Format.COMPACT_SHORT);
    -
    -  var str = fmt.format(-999999);
    -  assertEquals('-1M', str);
    -}
    -
    -function testCompactSmall() {
    -  var fmt = new goog.i18n.NumberFormat(
    -      goog.i18n.NumberFormat.Format.COMPACT_SHORT);
    -
    -  var str = fmt.format(0.1234);
    -  assertEquals('0.12', str);
    -}
    -
    -function testCompactLong() {
    -  var fmt = new goog.i18n.NumberFormat(
    -      goog.i18n.NumberFormat.Format.COMPACT_LONG);
    -
    -  var str = fmt.format(12345);
    -  assertEquals('12 thousand', str);
    -}
    -
    -function testCompactWithoutSignificant() {
    -  var fmt = new goog.i18n.NumberFormat(
    -      goog.i18n.NumberFormat.Format.COMPACT_SHORT);
    -  fmt.setSignificantDigits(0);
    -  fmt.setMinimumFractionDigits(2);
    -  fmt.setMaximumFractionDigits(2);
    -
    -  assertEquals('1.23K', fmt.format(1234));
    -  assertEquals('1.00K', fmt.format(1000));
    -  assertEquals('123.46K', fmt.format(123456.7));
    -  assertEquals('999.99K', fmt.format(999994));
    -  assertEquals('1.00M', fmt.format(999995));
    -}
    -
    -function testCompactWithoutSignificant2() {
    -  var fmt = new goog.i18n.NumberFormat(
    -      goog.i18n.NumberFormat.Format.COMPACT_SHORT);
    -  fmt.setSignificantDigits(0);
    -  fmt.setMinimumFractionDigits(0);
    -  fmt.setMaximumFractionDigits(2);
    -
    -  assertEquals('1.23K', fmt.format(1234));
    -  assertEquals('1K', fmt.format(1000));
    -  assertEquals('123.46K', fmt.format(123456.7));
    -  assertEquals('999.99K', fmt.format(999994));
    -  assertEquals('1M', fmt.format(999995));
    -}
    -
    -function testShowTrailingZerosWithSignificantDigits() {
    -  var fmt = new goog.i18n.NumberFormat(goog.i18n.NumberFormat.Format.DECIMAL);
    -  fmt.setSignificantDigits(2);
    -  fmt.setShowTrailingZeros(true);
    -
    -  assertEquals('2.0', fmt.format(2));
    -  assertEquals('2,000', fmt.format(2000));
    -  assertEquals('0.20', fmt.format(0.2));
    -  assertEquals('0.02', fmt.format(0.02));
    -  assertEquals('0.002', fmt.format(0.002));
    -  assertEquals('0.00', fmt.format(0));
    -
    -  fmt.setShowTrailingZeros(false);
    -  assertEquals('2', fmt.format(2));
    -  assertEquals('0.2', fmt.format(0.2));
    -}
    -
    -
    -function testShowTrailingZerosWithSignificantDigitsCompactShort() {
    -  var fmt = new goog.i18n.NumberFormat(
    -      goog.i18n.NumberFormat.Format.COMPACT_SHORT);
    -  fmt.setSignificantDigits(2);
    -  fmt.setShowTrailingZeros(true);
    -
    -  assertEquals('2.0', fmt.format(2));
    -  assertEquals('2.0K', fmt.format(2000));
    -  assertEquals('20', fmt.format(20));
    -}
    -
    -function testCurrencyCodeOrder() {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr;
    -  goog.i18n.CompactNumberFormatSymbols =
    -      goog.i18n.CompactNumberFormatSymbols_fr;
    -  var fmt = new goog.i18n.NumberFormat(goog.i18n.NumberFormat.Format.CURRENCY);
    -  assertFalse(fmt.isCurrencyCodeBeforeValue());
    -
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en;
    -  goog.i18n.CompactNumberFormatSymbols =
    -      goog.i18n.CompactNumberFormatSymbols_en;
    -  var fmt1 = new goog.i18n.NumberFormat(goog.i18n.NumberFormat.Format.CURRENCY);
    -  assertTrue(fmt1.isCurrencyCodeBeforeValue());
    -
    -  // Check that we really have different formatters with different patterns
    -  assertFalse(fmt.isCurrencyCodeBeforeValue());
    -
    -
    -  // Using custom patterns instead of standard locale ones
    -
    -  fmt = new goog.i18n.NumberFormat('\u00A4 #0');
    -  assertTrue(fmt.isCurrencyCodeBeforeValue());
    -
    -  fmt = new goog.i18n.NumberFormat('\u00A4 0 and #');
    -  assertTrue(fmt.isCurrencyCodeBeforeValue());
    -
    -  fmt = new goog.i18n.NumberFormat('#0 \u00A4');
    -  assertFalse(fmt.isCurrencyCodeBeforeValue());
    -
    -  fmt = new goog.i18n.NumberFormat('0 and # \u00A4');
    -  assertFalse(fmt.isCurrencyCodeBeforeValue());
    -
    -  fmt = new goog.i18n.NumberFormat('\u00A4 0');
    -  assertTrue(fmt.isCurrencyCodeBeforeValue());
    -
    -  fmt = new goog.i18n.NumberFormat('0 \u00A4');
    -  assertFalse(fmt.isCurrencyCodeBeforeValue());
    -
    -  fmt = new goog.i18n.NumberFormat('\u00A4 #');
    -  assertTrue(fmt.isCurrencyCodeBeforeValue());
    -
    -  fmt = new goog.i18n.NumberFormat('# \u00A4');
    -  assertFalse(fmt.isCurrencyCodeBeforeValue());
    -
    -
    -  // Edge cases, should never happen (like #0 separated by currency symbol,
    -  // or missing currency symbol, or missing both # and 0, or missing all)
    -  // We still make sure we get reasonable results (as much as possible)
    -
    -  fmt = new goog.i18n.NumberFormat('0 \u00A4 #');
    -  assertFalse(fmt.isCurrencyCodeBeforeValue());
    -
    -  fmt = new goog.i18n.NumberFormat('# \u00A4 0');
    -  assertFalse(fmt.isCurrencyCodeBeforeValue());
    -
    -  fmt = new goog.i18n.NumberFormat('\u00A4');
    -  assertTrue(fmt.isCurrencyCodeBeforeValue());  // currency first, en_US style
    -
    -  fmt = new goog.i18n.NumberFormat('0');
    -  assertTrue(fmt.isCurrencyCodeBeforeValue());  // currency first, en_US style
    -
    -  fmt = new goog.i18n.NumberFormat('#');
    -  assertTrue(fmt.isCurrencyCodeBeforeValue());  // currency first, en_US style
    -
    -  fmt = new goog.i18n.NumberFormat('#0');
    -  assertTrue(fmt.isCurrencyCodeBeforeValue());  // currency first, en_US style
    -
    -  fmt = new goog.i18n.NumberFormat('0 and #');
    -  assertTrue(fmt.isCurrencyCodeBeforeValue());  // currency first, en_US style
    -
    -  fmt = new goog.i18n.NumberFormat('nothing');
    -  assertTrue(fmt.isCurrencyCodeBeforeValue());  // currency first, en_US style
    -}
    -
    -function testCompactWithBaseFormattingNumber() {
    -  var fmt = new goog.i18n.NumberFormat(
    -      goog.i18n.NumberFormat.Format.COMPACT_SHORT);
    -
    -  fmt.setBaseFormatting(1000);
    -  assertEquals('0.8K', fmt.format(800, 1000));
    -
    -  fmt.setBaseFormatting(null);
    -  assertEquals('800', fmt.format(800, 1000));
    -  fmt.setBaseFormatting(1000);
    -  assertEquals('1,200K', fmt.format(1200000, 1000));
    -  assertEquals('0.01K', fmt.format(10, 1000));
    -  fmt.setSignificantDigits(0);
    -  fmt.setMinimumFractionDigits(2);
    -  assertEquals('0.00K', fmt.format(1, 1000));
    -}
    -
    -function testCompactWithBaseFormattingFrench() {
    -  // Switch to French.
    -  stubs.set(goog.i18n, 'NumberFormatSymbols', goog.i18n.NumberFormatSymbols_fr);
    -  stubs.set(goog.i18n, 'CompactNumberFormatSymbols',
    -            goog.i18n.CompactNumberFormatSymbols_fr);
    -
    -  var fmt = new goog.i18n.NumberFormat(
    -      goog.i18n.NumberFormat.Format.COMPACT_SHORT);
    -  assertEquals('123\u00A0M', fmt.format(123400000));
    -  fmt.setBaseFormatting(1000);
    -  assertEquals('123\u00A0400\u00A0k', fmt.format(123400000));
    -
    -}
    -
    -function testGetBaseFormattingNumber() {
    -  var fmt = new goog.i18n.NumberFormat(
    -      goog.i18n.NumberFormat.Format.COMPACT_SHORT);
    -  assertEquals(null, fmt.getBaseFormatting());
    -  fmt.setBaseFormatting(10000);
    -  assertEquals(10000, fmt.getBaseFormatting());
    -}
    -
    -// Moved Polish, Romanian, other currencies to tier 2, check that it works now
    -function testPolish() {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_pl;
    -  var fmPl = new goog.i18n.NumberFormat(goog.i18n.NumberFormat.Format.CURRENCY);
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ro;
    -  var fmRo = new goog.i18n.NumberFormat(goog.i18n.NumberFormat.Format.CURRENCY);
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en;
    -
    -  assertEquals('100.00\u00A0z\u0142', fmPl.format(100)); // 100.00 zł
    -  assertEquals('100.00\u00A0RON', fmRo.format(100));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/numberformatsymbols.js b/src/database/third_party/closure-library/closure/goog/i18n/numberformatsymbols.js
    deleted file mode 100644
    index 3f4296497e4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/numberformatsymbols.js
    +++ /dev/null
    @@ -1,4139 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Number formatting symbols.
    - *
    - * This file is autogenerated by script:
    - * http://go/generate_number_constants.py
    - * using the --for_closure flag.
    - * File generated from CLDR ver. 26
    - *
    - * To reduce the file size (which may cause issues in some JS
    - * developing environments), this file will only contain locales
    - * that are frequently used by web applications. This is defined as
    - * closure_tier1_locales and will change (most likely addition)
    - * over time.  Rest of the data can be found in another file named
    - * "numberformatsymbolsext.js", which will be generated at the
    - * same time together with this file.
    - *
    - * Before checkin, this file could have been manually edited. This is
    - * to incorporate changes before we could fix CLDR. All manual
    - * modification must be documented in this section, and should be
    - * removed after those changes land to CLDR.
    - */
    -
    -goog.provide('goog.i18n.NumberFormatSymbols');
    -goog.provide('goog.i18n.NumberFormatSymbols_af');
    -goog.provide('goog.i18n.NumberFormatSymbols_af_ZA');
    -goog.provide('goog.i18n.NumberFormatSymbols_am');
    -goog.provide('goog.i18n.NumberFormatSymbols_am_ET');
    -goog.provide('goog.i18n.NumberFormatSymbols_ar');
    -goog.provide('goog.i18n.NumberFormatSymbols_ar_001');
    -goog.provide('goog.i18n.NumberFormatSymbols_az');
    -goog.provide('goog.i18n.NumberFormatSymbols_az_Latn_AZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_bg');
    -goog.provide('goog.i18n.NumberFormatSymbols_bg_BG');
    -goog.provide('goog.i18n.NumberFormatSymbols_bn');
    -goog.provide('goog.i18n.NumberFormatSymbols_bn_BD');
    -goog.provide('goog.i18n.NumberFormatSymbols_br');
    -goog.provide('goog.i18n.NumberFormatSymbols_br_FR');
    -goog.provide('goog.i18n.NumberFormatSymbols_ca');
    -goog.provide('goog.i18n.NumberFormatSymbols_ca_AD');
    -goog.provide('goog.i18n.NumberFormatSymbols_ca_ES');
    -goog.provide('goog.i18n.NumberFormatSymbols_ca_ES_VALENCIA');
    -goog.provide('goog.i18n.NumberFormatSymbols_ca_FR');
    -goog.provide('goog.i18n.NumberFormatSymbols_ca_IT');
    -goog.provide('goog.i18n.NumberFormatSymbols_chr');
    -goog.provide('goog.i18n.NumberFormatSymbols_chr_US');
    -goog.provide('goog.i18n.NumberFormatSymbols_cs');
    -goog.provide('goog.i18n.NumberFormatSymbols_cs_CZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_cy');
    -goog.provide('goog.i18n.NumberFormatSymbols_cy_GB');
    -goog.provide('goog.i18n.NumberFormatSymbols_da');
    -goog.provide('goog.i18n.NumberFormatSymbols_da_DK');
    -goog.provide('goog.i18n.NumberFormatSymbols_da_GL');
    -goog.provide('goog.i18n.NumberFormatSymbols_de');
    -goog.provide('goog.i18n.NumberFormatSymbols_de_AT');
    -goog.provide('goog.i18n.NumberFormatSymbols_de_BE');
    -goog.provide('goog.i18n.NumberFormatSymbols_de_CH');
    -goog.provide('goog.i18n.NumberFormatSymbols_de_DE');
    -goog.provide('goog.i18n.NumberFormatSymbols_de_LU');
    -goog.provide('goog.i18n.NumberFormatSymbols_el');
    -goog.provide('goog.i18n.NumberFormatSymbols_el_GR');
    -goog.provide('goog.i18n.NumberFormatSymbols_en');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_001');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_AS');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_AU');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_DG');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_FM');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_GB');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_GU');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_IE');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_IN');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_IO');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_MH');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_MP');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_PR');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_PW');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_SG');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_TC');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_UM');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_US');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_VG');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_VI');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_ZA');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_ZW');
    -goog.provide('goog.i18n.NumberFormatSymbols_es');
    -goog.provide('goog.i18n.NumberFormatSymbols_es_419');
    -goog.provide('goog.i18n.NumberFormatSymbols_es_EA');
    -goog.provide('goog.i18n.NumberFormatSymbols_es_ES');
    -goog.provide('goog.i18n.NumberFormatSymbols_es_IC');
    -goog.provide('goog.i18n.NumberFormatSymbols_et');
    -goog.provide('goog.i18n.NumberFormatSymbols_et_EE');
    -goog.provide('goog.i18n.NumberFormatSymbols_eu');
    -goog.provide('goog.i18n.NumberFormatSymbols_eu_ES');
    -goog.provide('goog.i18n.NumberFormatSymbols_fa');
    -goog.provide('goog.i18n.NumberFormatSymbols_fa_IR');
    -goog.provide('goog.i18n.NumberFormatSymbols_fi');
    -goog.provide('goog.i18n.NumberFormatSymbols_fi_FI');
    -goog.provide('goog.i18n.NumberFormatSymbols_fil');
    -goog.provide('goog.i18n.NumberFormatSymbols_fil_PH');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_BL');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_CA');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_FR');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_GF');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_GP');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_MC');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_MF');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_MQ');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_PM');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_RE');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_YT');
    -goog.provide('goog.i18n.NumberFormatSymbols_ga');
    -goog.provide('goog.i18n.NumberFormatSymbols_ga_IE');
    -goog.provide('goog.i18n.NumberFormatSymbols_gl');
    -goog.provide('goog.i18n.NumberFormatSymbols_gl_ES');
    -goog.provide('goog.i18n.NumberFormatSymbols_gsw');
    -goog.provide('goog.i18n.NumberFormatSymbols_gsw_CH');
    -goog.provide('goog.i18n.NumberFormatSymbols_gsw_LI');
    -goog.provide('goog.i18n.NumberFormatSymbols_gu');
    -goog.provide('goog.i18n.NumberFormatSymbols_gu_IN');
    -goog.provide('goog.i18n.NumberFormatSymbols_haw');
    -goog.provide('goog.i18n.NumberFormatSymbols_haw_US');
    -goog.provide('goog.i18n.NumberFormatSymbols_he');
    -goog.provide('goog.i18n.NumberFormatSymbols_he_IL');
    -goog.provide('goog.i18n.NumberFormatSymbols_hi');
    -goog.provide('goog.i18n.NumberFormatSymbols_hi_IN');
    -goog.provide('goog.i18n.NumberFormatSymbols_hr');
    -goog.provide('goog.i18n.NumberFormatSymbols_hr_HR');
    -goog.provide('goog.i18n.NumberFormatSymbols_hu');
    -goog.provide('goog.i18n.NumberFormatSymbols_hu_HU');
    -goog.provide('goog.i18n.NumberFormatSymbols_hy');
    -goog.provide('goog.i18n.NumberFormatSymbols_hy_AM');
    -goog.provide('goog.i18n.NumberFormatSymbols_id');
    -goog.provide('goog.i18n.NumberFormatSymbols_id_ID');
    -goog.provide('goog.i18n.NumberFormatSymbols_in');
    -goog.provide('goog.i18n.NumberFormatSymbols_is');
    -goog.provide('goog.i18n.NumberFormatSymbols_is_IS');
    -goog.provide('goog.i18n.NumberFormatSymbols_it');
    -goog.provide('goog.i18n.NumberFormatSymbols_it_IT');
    -goog.provide('goog.i18n.NumberFormatSymbols_it_SM');
    -goog.provide('goog.i18n.NumberFormatSymbols_iw');
    -goog.provide('goog.i18n.NumberFormatSymbols_ja');
    -goog.provide('goog.i18n.NumberFormatSymbols_ja_JP');
    -goog.provide('goog.i18n.NumberFormatSymbols_ka');
    -goog.provide('goog.i18n.NumberFormatSymbols_ka_GE');
    -goog.provide('goog.i18n.NumberFormatSymbols_kk');
    -goog.provide('goog.i18n.NumberFormatSymbols_kk_Cyrl_KZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_km');
    -goog.provide('goog.i18n.NumberFormatSymbols_km_KH');
    -goog.provide('goog.i18n.NumberFormatSymbols_kn');
    -goog.provide('goog.i18n.NumberFormatSymbols_kn_IN');
    -goog.provide('goog.i18n.NumberFormatSymbols_ko');
    -goog.provide('goog.i18n.NumberFormatSymbols_ko_KR');
    -goog.provide('goog.i18n.NumberFormatSymbols_ky');
    -goog.provide('goog.i18n.NumberFormatSymbols_ky_Cyrl_KG');
    -goog.provide('goog.i18n.NumberFormatSymbols_ln');
    -goog.provide('goog.i18n.NumberFormatSymbols_ln_CD');
    -goog.provide('goog.i18n.NumberFormatSymbols_lo');
    -goog.provide('goog.i18n.NumberFormatSymbols_lo_LA');
    -goog.provide('goog.i18n.NumberFormatSymbols_lt');
    -goog.provide('goog.i18n.NumberFormatSymbols_lt_LT');
    -goog.provide('goog.i18n.NumberFormatSymbols_lv');
    -goog.provide('goog.i18n.NumberFormatSymbols_lv_LV');
    -goog.provide('goog.i18n.NumberFormatSymbols_mk');
    -goog.provide('goog.i18n.NumberFormatSymbols_mk_MK');
    -goog.provide('goog.i18n.NumberFormatSymbols_ml');
    -goog.provide('goog.i18n.NumberFormatSymbols_ml_IN');
    -goog.provide('goog.i18n.NumberFormatSymbols_mn');
    -goog.provide('goog.i18n.NumberFormatSymbols_mn_Cyrl_MN');
    -goog.provide('goog.i18n.NumberFormatSymbols_mr');
    -goog.provide('goog.i18n.NumberFormatSymbols_mr_IN');
    -goog.provide('goog.i18n.NumberFormatSymbols_ms');
    -goog.provide('goog.i18n.NumberFormatSymbols_ms_Latn_MY');
    -goog.provide('goog.i18n.NumberFormatSymbols_mt');
    -goog.provide('goog.i18n.NumberFormatSymbols_mt_MT');
    -goog.provide('goog.i18n.NumberFormatSymbols_my');
    -goog.provide('goog.i18n.NumberFormatSymbols_my_MM');
    -goog.provide('goog.i18n.NumberFormatSymbols_nb');
    -goog.provide('goog.i18n.NumberFormatSymbols_nb_NO');
    -goog.provide('goog.i18n.NumberFormatSymbols_nb_SJ');
    -goog.provide('goog.i18n.NumberFormatSymbols_ne');
    -goog.provide('goog.i18n.NumberFormatSymbols_ne_NP');
    -goog.provide('goog.i18n.NumberFormatSymbols_nl');
    -goog.provide('goog.i18n.NumberFormatSymbols_nl_NL');
    -goog.provide('goog.i18n.NumberFormatSymbols_no');
    -goog.provide('goog.i18n.NumberFormatSymbols_no_NO');
    -goog.provide('goog.i18n.NumberFormatSymbols_or');
    -goog.provide('goog.i18n.NumberFormatSymbols_or_IN');
    -goog.provide('goog.i18n.NumberFormatSymbols_pa');
    -goog.provide('goog.i18n.NumberFormatSymbols_pa_Guru_IN');
    -goog.provide('goog.i18n.NumberFormatSymbols_pl');
    -goog.provide('goog.i18n.NumberFormatSymbols_pl_PL');
    -goog.provide('goog.i18n.NumberFormatSymbols_pt');
    -goog.provide('goog.i18n.NumberFormatSymbols_pt_BR');
    -goog.provide('goog.i18n.NumberFormatSymbols_pt_PT');
    -goog.provide('goog.i18n.NumberFormatSymbols_ro');
    -goog.provide('goog.i18n.NumberFormatSymbols_ro_RO');
    -goog.provide('goog.i18n.NumberFormatSymbols_ru');
    -goog.provide('goog.i18n.NumberFormatSymbols_ru_RU');
    -goog.provide('goog.i18n.NumberFormatSymbols_si');
    -goog.provide('goog.i18n.NumberFormatSymbols_si_LK');
    -goog.provide('goog.i18n.NumberFormatSymbols_sk');
    -goog.provide('goog.i18n.NumberFormatSymbols_sk_SK');
    -goog.provide('goog.i18n.NumberFormatSymbols_sl');
    -goog.provide('goog.i18n.NumberFormatSymbols_sl_SI');
    -goog.provide('goog.i18n.NumberFormatSymbols_sq');
    -goog.provide('goog.i18n.NumberFormatSymbols_sq_AL');
    -goog.provide('goog.i18n.NumberFormatSymbols_sr');
    -goog.provide('goog.i18n.NumberFormatSymbols_sr_Cyrl_RS');
    -goog.provide('goog.i18n.NumberFormatSymbols_sv');
    -goog.provide('goog.i18n.NumberFormatSymbols_sv_SE');
    -goog.provide('goog.i18n.NumberFormatSymbols_sw');
    -goog.provide('goog.i18n.NumberFormatSymbols_sw_TZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_ta');
    -goog.provide('goog.i18n.NumberFormatSymbols_ta_IN');
    -goog.provide('goog.i18n.NumberFormatSymbols_te');
    -goog.provide('goog.i18n.NumberFormatSymbols_te_IN');
    -goog.provide('goog.i18n.NumberFormatSymbols_th');
    -goog.provide('goog.i18n.NumberFormatSymbols_th_TH');
    -goog.provide('goog.i18n.NumberFormatSymbols_tl');
    -goog.provide('goog.i18n.NumberFormatSymbols_tr');
    -goog.provide('goog.i18n.NumberFormatSymbols_tr_TR');
    -goog.provide('goog.i18n.NumberFormatSymbols_uk');
    -goog.provide('goog.i18n.NumberFormatSymbols_uk_UA');
    -goog.provide('goog.i18n.NumberFormatSymbols_ur');
    -goog.provide('goog.i18n.NumberFormatSymbols_ur_PK');
    -goog.provide('goog.i18n.NumberFormatSymbols_uz');
    -goog.provide('goog.i18n.NumberFormatSymbols_uz_Latn_UZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_vi');
    -goog.provide('goog.i18n.NumberFormatSymbols_vi_VN');
    -goog.provide('goog.i18n.NumberFormatSymbols_zh');
    -goog.provide('goog.i18n.NumberFormatSymbols_zh_CN');
    -goog.provide('goog.i18n.NumberFormatSymbols_zh_HK');
    -goog.provide('goog.i18n.NumberFormatSymbols_zh_Hans_CN');
    -goog.provide('goog.i18n.NumberFormatSymbols_zh_TW');
    -goog.provide('goog.i18n.NumberFormatSymbols_zu');
    -goog.provide('goog.i18n.NumberFormatSymbols_zu_ZA');
    -
    -
    -/**
    - * Number formatting symbols for locale af.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_af = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'ZAR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale af_ZA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_af_ZA = goog.i18n.NumberFormatSymbols_af;
    -
    -
    -/**
    - * Number formatting symbols for locale am.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_am = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'ETB'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale am_ET.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_am_ET = goog.i18n.NumberFormatSymbols_am;
    -
    -
    -/**
    - * Number formatting symbols for locale ar.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ar = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u0660',
    -  PLUS_SIGN: '\u200F+',
    -  MINUS_SIGN: '\u200F-',
    -  EXP_SYMBOL: '\u0627\u0633',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: '\u0644\u064A\u0633\u00A0\u0631\u0642\u0645',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'EGP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ar_001.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ar_001 = goog.i18n.NumberFormatSymbols_ar;
    -
    -
    -/**
    - * Number formatting symbols for locale az.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_az = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'AZN'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale az_Latn_AZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_az_Latn_AZ = goog.i18n.NumberFormatSymbols_az;
    -
    -
    -/**
    - * Number formatting symbols for locale bg.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_bg = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'BGN'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale bg_BG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_bg_BG = goog.i18n.NumberFormatSymbols_bg;
    -
    -
    -/**
    - * Number formatting symbols for locale bn.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_bn = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '\u09E6',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: '\u09B8\u0982\u0996\u09CD\u09AF\u09BE\u00A0\u09A8\u09BE',
    -  DECIMAL_PATTERN: '#,##,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##,##0%',
    -  CURRENCY_PATTERN: '#,##,##0.00\u00A4',
    -  DEF_CURRENCY_CODE: 'BDT'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale bn_BD.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_bn_BD = goog.i18n.NumberFormatSymbols_bn;
    -
    -
    -/**
    - * Number formatting symbols for locale br.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_br = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale br_FR.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_br_FR = goog.i18n.NumberFormatSymbols_br;
    -
    -
    -/**
    - * Number formatting symbols for locale ca.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ca = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ca_AD.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ca_AD = goog.i18n.NumberFormatSymbols_ca;
    -
    -
    -/**
    - * Number formatting symbols for locale ca_ES.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ca_ES = goog.i18n.NumberFormatSymbols_ca;
    -
    -
    -/**
    - * Number formatting symbols for locale ca_ES_VALENCIA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ca_ES_VALENCIA = goog.i18n.NumberFormatSymbols_ca;
    -
    -
    -/**
    - * Number formatting symbols for locale ca_FR.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ca_FR = goog.i18n.NumberFormatSymbols_ca;
    -
    -
    -/**
    - * Number formatting symbols for locale ca_IT.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ca_IT = goog.i18n.NumberFormatSymbols_ca;
    -
    -
    -/**
    - * Number formatting symbols for locale chr.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_chr = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'USD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale chr_US.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_chr_US = goog.i18n.NumberFormatSymbols_chr;
    -
    -
    -/**
    - * Number formatting symbols for locale cs.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_cs = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'CZK'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale cs_CZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_cs_CZ = goog.i18n.NumberFormatSymbols_cs;
    -
    -
    -/**
    - * Number formatting symbols for locale cy.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_cy = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'GBP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale cy_GB.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_cy_GB = goog.i18n.NumberFormatSymbols_cy;
    -
    -
    -/**
    - * Number formatting symbols for locale da.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_da = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'DKK'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale da_DK.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_da_DK = goog.i18n.NumberFormatSymbols_da;
    -
    -
    -/**
    - * Number formatting symbols for locale da_GL.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_da_GL = goog.i18n.NumberFormatSymbols_da;
    -
    -
    -/**
    - * Number formatting symbols for locale de.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_de = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale de_AT.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_de_AT = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale de_BE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_de_BE = goog.i18n.NumberFormatSymbols_de;
    -
    -
    -/**
    - * Number formatting symbols for locale de_CH.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_de_CH = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: '\'',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00;\u00A4-#,##0.00',
    -  DEF_CURRENCY_CODE: 'CHF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale de_DE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_de_DE = goog.i18n.NumberFormatSymbols_de;
    -
    -
    -/**
    - * Number formatting symbols for locale de_LU.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_de_LU = goog.i18n.NumberFormatSymbols_de;
    -
    -
    -/**
    - * Number formatting symbols for locale el.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_el = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'e',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale el_GR.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_el_GR = goog.i18n.NumberFormatSymbols_el;
    -
    -
    -/**
    - * Number formatting symbols for locale en.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'USD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_001.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_001 = goog.i18n.NumberFormatSymbols_en;
    -
    -
    -/**
    - * Number formatting symbols for locale en_AS.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_AS = goog.i18n.NumberFormatSymbols_en;
    -
    -
    -/**
    - * Number formatting symbols for locale en_AU.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_AU = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'AUD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_DG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_DG = goog.i18n.NumberFormatSymbols_en;
    -
    -
    -/**
    - * Number formatting symbols for locale en_FM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_FM = goog.i18n.NumberFormatSymbols_en;
    -
    -
    -/**
    - * Number formatting symbols for locale en_GB.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_GB = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'GBP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_GU.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_GU = goog.i18n.NumberFormatSymbols_en;
    -
    -
    -/**
    - * Number formatting symbols for locale en_IE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_IE = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_IN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_IN = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##,##0.00',
    -  DEF_CURRENCY_CODE: 'INR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_IO.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_IO = goog.i18n.NumberFormatSymbols_en;
    -
    -
    -/**
    - * Number formatting symbols for locale en_MH.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_MH = goog.i18n.NumberFormatSymbols_en;
    -
    -
    -/**
    - * Number formatting symbols for locale en_MP.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_MP = goog.i18n.NumberFormatSymbols_en;
    -
    -
    -/**
    - * Number formatting symbols for locale en_PR.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_PR = goog.i18n.NumberFormatSymbols_en;
    -
    -
    -/**
    - * Number formatting symbols for locale en_PW.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_PW = goog.i18n.NumberFormatSymbols_en;
    -
    -
    -/**
    - * Number formatting symbols for locale en_SG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_SG = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'SGD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_TC.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_TC = goog.i18n.NumberFormatSymbols_en;
    -
    -
    -/**
    - * Number formatting symbols for locale en_UM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_UM = goog.i18n.NumberFormatSymbols_en;
    -
    -
    -/**
    - * Number formatting symbols for locale en_US.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_US = goog.i18n.NumberFormatSymbols_en;
    -
    -
    -/**
    - * Number formatting symbols for locale en_VG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_VG = goog.i18n.NumberFormatSymbols_en;
    -
    -
    -/**
    - * Number formatting symbols for locale en_VI.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_VI = goog.i18n.NumberFormatSymbols_en;
    -
    -
    -/**
    - * Number formatting symbols for locale en_ZA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_ZA = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'ZAR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_ZW.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_ZW = goog.i18n.NumberFormatSymbols_en;
    -
    -
    -/**
    - * Number formatting symbols for locale es.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_es = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale es_419.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_es_419 = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'MXN'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale es_EA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_es_EA = goog.i18n.NumberFormatSymbols_es;
    -
    -
    -/**
    - * Number formatting symbols for locale es_ES.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_es_ES = goog.i18n.NumberFormatSymbols_es;
    -
    -
    -/**
    - * Number formatting symbols for locale es_IC.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_es_IC = goog.i18n.NumberFormatSymbols_es;
    -
    -
    -/**
    - * Number formatting symbols for locale et.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_et = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: '\u00D710^',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale et_EE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_et_EE = goog.i18n.NumberFormatSymbols_et;
    -
    -
    -/**
    - * Number formatting symbols for locale eu.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_eu = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '%\u00A0#,##0',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale eu_ES.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_eu_ES = goog.i18n.NumberFormatSymbols_eu;
    -
    -
    -/**
    - * Number formatting symbols for locale fa.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fa = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u06F0',
    -  PLUS_SIGN: '\u200E+\u200E',
    -  MINUS_SIGN: '\u200E\u2212',
    -  EXP_SYMBOL: '\u00D7\u06F1\u06F0^',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: '\u0646\u0627\u0639\u062F\u062F',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u200E\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'IRR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fa_IR.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fa_IR = goog.i18n.NumberFormatSymbols_fa;
    -
    -
    -/**
    - * Number formatting symbols for locale fi.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fi = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '\u2212',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'ep\u00E4luku',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fi_FI.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fi_FI = goog.i18n.NumberFormatSymbols_fi;
    -
    -
    -/**
    - * Number formatting symbols for locale fil.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fil = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'PHP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fil_PH.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fil_PH = goog.i18n.NumberFormatSymbols_fil;
    -
    -
    -/**
    - * Number formatting symbols for locale fr.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_BL.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_BL = goog.i18n.NumberFormatSymbols_fr;
    -
    -
    -/**
    - * Number formatting symbols for locale fr_CA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_CA = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'CAD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_FR.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_FR = goog.i18n.NumberFormatSymbols_fr;
    -
    -
    -/**
    - * Number formatting symbols for locale fr_GF.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_GF = goog.i18n.NumberFormatSymbols_fr;
    -
    -
    -/**
    - * Number formatting symbols for locale fr_GP.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_GP = goog.i18n.NumberFormatSymbols_fr;
    -
    -
    -/**
    - * Number formatting symbols for locale fr_MC.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_MC = goog.i18n.NumberFormatSymbols_fr;
    -
    -
    -/**
    - * Number formatting symbols for locale fr_MF.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_MF = goog.i18n.NumberFormatSymbols_fr;
    -
    -
    -/**
    - * Number formatting symbols for locale fr_MQ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_MQ = goog.i18n.NumberFormatSymbols_fr;
    -
    -
    -/**
    - * Number formatting symbols for locale fr_PM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_PM = goog.i18n.NumberFormatSymbols_fr;
    -
    -
    -/**
    - * Number formatting symbols for locale fr_RE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_RE = goog.i18n.NumberFormatSymbols_fr;
    -
    -
    -/**
    - * Number formatting symbols for locale fr_YT.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_YT = goog.i18n.NumberFormatSymbols_fr;
    -
    -
    -/**
    - * Number formatting symbols for locale ga.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ga = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ga_IE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ga_IE = goog.i18n.NumberFormatSymbols_ga;
    -
    -
    -/**
    - * Number formatting symbols for locale gl.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_gl = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale gl_ES.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_gl_ES = goog.i18n.NumberFormatSymbols_gl;
    -
    -
    -/**
    - * Number formatting symbols for locale gsw.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_gsw = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: '\u2019',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '\u2212',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'CHF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale gsw_CH.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_gsw_CH = goog.i18n.NumberFormatSymbols_gsw;
    -
    -
    -/**
    - * Number formatting symbols for locale gsw_LI.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_gsw_LI = goog.i18n.NumberFormatSymbols_gsw;
    -
    -
    -/**
    - * Number formatting symbols for locale gu.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_gu = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##,##0.###',
    -  SCIENTIFIC_PATTERN: '[#E0]',
    -  PERCENT_PATTERN: '#,##,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##,##0.00',
    -  DEF_CURRENCY_CODE: 'INR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale gu_IN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_gu_IN = goog.i18n.NumberFormatSymbols_gu;
    -
    -
    -/**
    - * Number formatting symbols for locale haw.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_haw = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'USD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale haw_US.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_haw_US = goog.i18n.NumberFormatSymbols_haw;
    -
    -
    -/**
    - * Number formatting symbols for locale he.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_he = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '\u200E+',
    -  MINUS_SIGN: '\u200E-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'ILS'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale he_IL.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_he_IL = goog.i18n.NumberFormatSymbols_he;
    -
    -
    -/**
    - * Number formatting symbols for locale hi.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_hi = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##,##0.###',
    -  SCIENTIFIC_PATTERN: '[#E0]',
    -  PERCENT_PATTERN: '#,##,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##,##0.00',
    -  DEF_CURRENCY_CODE: 'INR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale hi_IN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_hi_IN = goog.i18n.NumberFormatSymbols_hi;
    -
    -
    -/**
    - * Number formatting symbols for locale hr.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_hr = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'HRK'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale hr_HR.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_hr_HR = goog.i18n.NumberFormatSymbols_hr;
    -
    -
    -/**
    - * Number formatting symbols for locale hu.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_hu = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'HUF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale hu_HU.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_hu_HU = goog.i18n.NumberFormatSymbols_hu;
    -
    -
    -/**
    - * Number formatting symbols for locale hy.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_hy = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#0%',
    -  CURRENCY_PATTERN: '#0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'AMD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale hy_AM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_hy_AM = goog.i18n.NumberFormatSymbols_hy;
    -
    -
    -/**
    - * Number formatting symbols for locale id.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_id = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'IDR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale id_ID.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_id_ID = goog.i18n.NumberFormatSymbols_id;
    -
    -
    -/**
    - * Number formatting symbols for locale in.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_in = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'IDR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale is.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_is = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'ISK'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale is_IS.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_is_IS = goog.i18n.NumberFormatSymbols_is;
    -
    -
    -/**
    - * Number formatting symbols for locale it.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_it = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale it_IT.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_it_IT = goog.i18n.NumberFormatSymbols_it;
    -
    -
    -/**
    - * Number formatting symbols for locale it_SM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_it_SM = goog.i18n.NumberFormatSymbols_it;
    -
    -
    -/**
    - * Number formatting symbols for locale iw.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_iw = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '\u200E+',
    -  MINUS_SIGN: '\u200E-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'ILS'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ja.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ja = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'JPY'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ja_JP.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ja_JP = goog.i18n.NumberFormatSymbols_ja;
    -
    -
    -/**
    - * Number formatting symbols for locale ka.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ka = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN:
    -      '\u10D0\u10E0\u00A0\u10D0\u10E0\u10D8\u10E1\u00A0\u10E0\u10D8\u10EA\u10EE\u10D5\u10D8',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'GEL'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ka_GE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ka_GE = goog.i18n.NumberFormatSymbols_ka;
    -
    -
    -/**
    - * Number formatting symbols for locale kk.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_kk = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'KZT'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale kk_Cyrl_KZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_kk_Cyrl_KZ = goog.i18n.NumberFormatSymbols_kk;
    -
    -
    -/**
    - * Number formatting symbols for locale km.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_km = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'KHR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale km_KH.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_km_KH = goog.i18n.NumberFormatSymbols_km;
    -
    -
    -/**
    - * Number formatting symbols for locale kn.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_kn = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'INR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale kn_IN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_kn_IN = goog.i18n.NumberFormatSymbols_kn;
    -
    -
    -/**
    - * Number formatting symbols for locale ko.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ko = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'KRW'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ko_KR.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ko_KR = goog.i18n.NumberFormatSymbols_ko;
    -
    -
    -/**
    - * Number formatting symbols for locale ky.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ky = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: '\u0441\u0430\u043D\u00A0\u044D\u043C\u0435\u0441',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'KGS'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ky_Cyrl_KG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ky_Cyrl_KG = goog.i18n.NumberFormatSymbols_ky;
    -
    -
    -/**
    - * Number formatting symbols for locale ln.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ln = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'CDF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ln_CD.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ln_CD = goog.i18n.NumberFormatSymbols_ln;
    -
    -
    -/**
    - * Number formatting symbols for locale lo.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_lo = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN:
    -      '\u0E9A\u0ECD\u0EC8\u200B\u0EC1\u0EA1\u0EC8\u0E99\u200B\u0EC2\u0E95\u200B\u0EC0\u0EA5\u0E81',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00;\u00A4-#,##0.00',
    -  DEF_CURRENCY_CODE: 'LAK'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale lo_LA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_lo_LA = goog.i18n.NumberFormatSymbols_lo;
    -
    -
    -/**
    - * Number formatting symbols for locale lt.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_lt = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '\u2212',
    -  EXP_SYMBOL: '\u00D710^',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale lt_LT.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_lt_LT = goog.i18n.NumberFormatSymbols_lt;
    -
    -
    -/**
    - * Number formatting symbols for locale lv.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_lv = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'nav\u00A0skaitlis',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#0.00',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale lv_LV.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_lv_LV = goog.i18n.NumberFormatSymbols_lv;
    -
    -
    -/**
    - * Number formatting symbols for locale mk.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_mk = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'MKD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale mk_MK.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_mk_MK = goog.i18n.NumberFormatSymbols_mk;
    -
    -
    -/**
    - * Number formatting symbols for locale ml.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ml = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'INR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ml_IN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ml_IN = goog.i18n.NumberFormatSymbols_ml;
    -
    -
    -/**
    - * Number formatting symbols for locale mn.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_mn = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'MNT'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale mn_Cyrl_MN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_mn_Cyrl_MN = goog.i18n.NumberFormatSymbols_mn;
    -
    -
    -/**
    - * Number formatting symbols for locale mr.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_mr = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '\u0966',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##,##0.###',
    -  SCIENTIFIC_PATTERN: '[#E0]',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'INR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale mr_IN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_mr_IN = goog.i18n.NumberFormatSymbols_mr;
    -
    -
    -/**
    - * Number formatting symbols for locale ms.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ms = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'MYR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ms_Latn_MY.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ms_Latn_MY = goog.i18n.NumberFormatSymbols_ms;
    -
    -
    -/**
    - * Number formatting symbols for locale mt.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_mt = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale mt_MT.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_mt_MT = goog.i18n.NumberFormatSymbols_mt;
    -
    -
    -/**
    - * Number formatting symbols for locale my.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_my = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '\u1040',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN:
    -      '\u1002\u100F\u1014\u103A\u1038\u1019\u101F\u102F\u1010\u103A\u101E\u1031\u102C',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'MMK'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale my_MM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_my_MM = goog.i18n.NumberFormatSymbols_my;
    -
    -
    -/**
    - * Number formatting symbols for locale nb.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_nb = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '\u2212',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'NOK'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale nb_NO.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_nb_NO = goog.i18n.NumberFormatSymbols_nb;
    -
    -
    -/**
    - * Number formatting symbols for locale nb_SJ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_nb_SJ = goog.i18n.NumberFormatSymbols_nb;
    -
    -
    -/**
    - * Number formatting symbols for locale ne.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ne = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '\u0966',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'NPR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ne_NP.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ne_NP = goog.i18n.NumberFormatSymbols_ne;
    -
    -
    -/**
    - * Number formatting symbols for locale nl.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_nl = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00;\u00A4\u00A0#,##0.00-',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale nl_NL.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_nl_NL = goog.i18n.NumberFormatSymbols_nl;
    -
    -
    -/**
    - * Number formatting symbols for locale no.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_no = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '\u2212',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'NOK'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale no_NO.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_no_NO = goog.i18n.NumberFormatSymbols_no;
    -
    -
    -/**
    - * Number formatting symbols for locale or.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_or = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##,##0.00',
    -  DEF_CURRENCY_CODE: 'INR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale or_IN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_or_IN = goog.i18n.NumberFormatSymbols_or;
    -
    -
    -/**
    - * Number formatting symbols for locale pa.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_pa = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##,##0.###',
    -  SCIENTIFIC_PATTERN: '[#E0]',
    -  PERCENT_PATTERN: '#,##,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##,##0.00',
    -  DEF_CURRENCY_CODE: 'INR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale pa_Guru_IN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_pa_Guru_IN = goog.i18n.NumberFormatSymbols_pa;
    -
    -
    -/**
    - * Number formatting symbols for locale pl.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_pl = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'PLN'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale pl_PL.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_pl_PL = goog.i18n.NumberFormatSymbols_pl;
    -
    -
    -/**
    - * Number formatting symbols for locale pt.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_pt = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'BRL'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale pt_BR.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_pt_BR = goog.i18n.NumberFormatSymbols_pt;
    -
    -
    -/**
    - * Number formatting symbols for locale pt_PT.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_pt_PT = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ro.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ro = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'RON'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ro_RO.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ro_RO = goog.i18n.NumberFormatSymbols_ro;
    -
    -
    -/**
    - * Number formatting symbols for locale ru.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ru = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: '\u043D\u0435\u00A0\u0447\u0438\u0441\u043B\u043E',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'RUB'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ru_RU.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ru_RU = goog.i18n.NumberFormatSymbols_ru;
    -
    -
    -/**
    - * Number formatting symbols for locale si.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_si = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'LKR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale si_LK.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_si_LK = goog.i18n.NumberFormatSymbols_si;
    -
    -
    -/**
    - * Number formatting symbols for locale sk.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sk = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale sk_SK.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sk_SK = goog.i18n.NumberFormatSymbols_sk;
    -
    -
    -/**
    - * Number formatting symbols for locale sl.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sl = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'e',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale sl_SI.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sl_SI = goog.i18n.NumberFormatSymbols_sl;
    -
    -
    -/**
    - * Number formatting symbols for locale sq.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sq = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'ALL'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale sq_AL.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sq_AL = goog.i18n.NumberFormatSymbols_sq;
    -
    -
    -/**
    - * Number formatting symbols for locale sr.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sr = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'RSD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale sr_Cyrl_RS.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sr_Cyrl_RS = goog.i18n.NumberFormatSymbols_sr;
    -
    -
    -/**
    - * Number formatting symbols for locale sv.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sv = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '\u2212',
    -  EXP_SYMBOL: '\u00D710^',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: '\u00A4\u00A4\u00A4',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'SEK'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale sv_SE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sv_SE = goog.i18n.NumberFormatSymbols_sv;
    -
    -
    -/**
    - * Number formatting symbols for locale sw.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sw = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'TZS'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale sw_TZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sw_TZ = goog.i18n.NumberFormatSymbols_sw;
    -
    -
    -/**
    - * Number formatting symbols for locale ta.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ta = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##,##0.00',
    -  DEF_CURRENCY_CODE: 'INR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ta_IN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ta_IN = goog.i18n.NumberFormatSymbols_ta;
    -
    -
    -/**
    - * Number formatting symbols for locale te.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_te = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##,##0.00',
    -  DEF_CURRENCY_CODE: 'INR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale te_IN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_te_IN = goog.i18n.NumberFormatSymbols_te;
    -
    -
    -/**
    - * Number formatting symbols for locale th.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_th = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'THB'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale th_TH.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_th_TH = goog.i18n.NumberFormatSymbols_th;
    -
    -
    -/**
    - * Number formatting symbols for locale tl.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_tl = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'PHP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale tr.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_tr = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '%#,##0',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'TRY'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale tr_TR.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_tr_TR = goog.i18n.NumberFormatSymbols_tr;
    -
    -
    -/**
    - * Number formatting symbols for locale uk.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_uk = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: '\u0415',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: '\u041D\u0435\u00A0\u0447\u0438\u0441\u043B\u043E',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'UAH'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale uk_UA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_uk_UA = goog.i18n.NumberFormatSymbols_uk;
    -
    -
    -/**
    - * Number formatting symbols for locale ur.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ur = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '\u200E+',
    -  MINUS_SIGN: '\u200E-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##,##0.00',
    -  DEF_CURRENCY_CODE: 'PKR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ur_PK.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ur_PK = goog.i18n.NumberFormatSymbols_ur;
    -
    -
    -/**
    - * Number formatting symbols for locale uz.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_uz = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'UZS'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale uz_Latn_UZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_uz_Latn_UZ = goog.i18n.NumberFormatSymbols_uz;
    -
    -
    -/**
    - * Number formatting symbols for locale vi.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_vi = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'VND'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale vi_VN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_vi_VN = goog.i18n.NumberFormatSymbols_vi;
    -
    -
    -/**
    - * Number formatting symbols for locale zh.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_zh = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'CNY'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale zh_CN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_zh_CN = goog.i18n.NumberFormatSymbols_zh;
    -
    -
    -/**
    - * Number formatting symbols for locale zh_HK.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_zh_HK = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: '\u975E\u6578\u503C',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'HKD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale zh_Hans_CN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_zh_Hans_CN = goog.i18n.NumberFormatSymbols_zh;
    -
    -
    -/**
    - * Number formatting symbols for locale zh_TW.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_zh_TW = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: '\u975E\u6578\u503C',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'TWD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale zu.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_zu = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'I-NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'ZAR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale zu_ZA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_zu_ZA = goog.i18n.NumberFormatSymbols_zu;
    -
    -
    -/**
    - * Selected number formatting symbols by locale.
    - */
    -goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en;
    -
    -if (goog.LOCALE == 'af') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_af;
    -}
    -
    -if (goog.LOCALE == 'af_ZA' || goog.LOCALE == 'af-ZA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_af;
    -}
    -
    -if (goog.LOCALE == 'am') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_am;
    -}
    -
    -if (goog.LOCALE == 'am_ET' || goog.LOCALE == 'am-ET') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_am;
    -}
    -
    -if (goog.LOCALE == 'ar') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar;
    -}
    -
    -if (goog.LOCALE == 'ar_001' || goog.LOCALE == 'ar-001') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar;
    -}
    -
    -if (goog.LOCALE == 'az') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_az;
    -}
    -
    -if (goog.LOCALE == 'az_Latn_AZ' || goog.LOCALE == 'az-Latn-AZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_az;
    -}
    -
    -if (goog.LOCALE == 'bg') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bg;
    -}
    -
    -if (goog.LOCALE == 'bg_BG' || goog.LOCALE == 'bg-BG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bg;
    -}
    -
    -if (goog.LOCALE == 'bn') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bn;
    -}
    -
    -if (goog.LOCALE == 'bn_BD' || goog.LOCALE == 'bn-BD') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bn;
    -}
    -
    -if (goog.LOCALE == 'br') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_br;
    -}
    -
    -if (goog.LOCALE == 'br_FR' || goog.LOCALE == 'br-FR') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_br;
    -}
    -
    -if (goog.LOCALE == 'ca') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ca;
    -}
    -
    -if (goog.LOCALE == 'ca_AD' || goog.LOCALE == 'ca-AD') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ca;
    -}
    -
    -if (goog.LOCALE == 'ca_ES' || goog.LOCALE == 'ca-ES') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ca;
    -}
    -
    -if (goog.LOCALE == 'ca_ES_VALENCIA' || goog.LOCALE == 'ca-ES-VALENCIA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ca;
    -}
    -
    -if (goog.LOCALE == 'ca_FR' || goog.LOCALE == 'ca-FR') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ca;
    -}
    -
    -if (goog.LOCALE == 'ca_IT' || goog.LOCALE == 'ca-IT') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ca;
    -}
    -
    -if (goog.LOCALE == 'chr') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_chr;
    -}
    -
    -if (goog.LOCALE == 'chr_US' || goog.LOCALE == 'chr-US') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_chr;
    -}
    -
    -if (goog.LOCALE == 'cs') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_cs;
    -}
    -
    -if (goog.LOCALE == 'cs_CZ' || goog.LOCALE == 'cs-CZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_cs;
    -}
    -
    -if (goog.LOCALE == 'cy') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_cy;
    -}
    -
    -if (goog.LOCALE == 'cy_GB' || goog.LOCALE == 'cy-GB') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_cy;
    -}
    -
    -if (goog.LOCALE == 'da') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_da;
    -}
    -
    -if (goog.LOCALE == 'da_DK' || goog.LOCALE == 'da-DK') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_da;
    -}
    -
    -if (goog.LOCALE == 'da_GL' || goog.LOCALE == 'da-GL') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_da;
    -}
    -
    -if (goog.LOCALE == 'de') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_de;
    -}
    -
    -if (goog.LOCALE == 'de_AT' || goog.LOCALE == 'de-AT') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_de_AT;
    -}
    -
    -if (goog.LOCALE == 'de_BE' || goog.LOCALE == 'de-BE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_de;
    -}
    -
    -if (goog.LOCALE == 'de_CH' || goog.LOCALE == 'de-CH') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_de_CH;
    -}
    -
    -if (goog.LOCALE == 'de_DE' || goog.LOCALE == 'de-DE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_de;
    -}
    -
    -if (goog.LOCALE == 'de_LU' || goog.LOCALE == 'de-LU') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_de;
    -}
    -
    -if (goog.LOCALE == 'el') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_el;
    -}
    -
    -if (goog.LOCALE == 'el_GR' || goog.LOCALE == 'el-GR') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_el;
    -}
    -
    -if (goog.LOCALE == 'en') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_001' || goog.LOCALE == 'en-001') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_AS' || goog.LOCALE == 'en-AS') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_AU' || goog.LOCALE == 'en-AU') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_AU;
    -}
    -
    -if (goog.LOCALE == 'en_DG' || goog.LOCALE == 'en-DG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_FM' || goog.LOCALE == 'en-FM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_GB' || goog.LOCALE == 'en-GB') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_GB;
    -}
    -
    -if (goog.LOCALE == 'en_GU' || goog.LOCALE == 'en-GU') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_IE' || goog.LOCALE == 'en-IE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_IE;
    -}
    -
    -if (goog.LOCALE == 'en_IN' || goog.LOCALE == 'en-IN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_IN;
    -}
    -
    -if (goog.LOCALE == 'en_IO' || goog.LOCALE == 'en-IO') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_MH' || goog.LOCALE == 'en-MH') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_MP' || goog.LOCALE == 'en-MP') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_PR' || goog.LOCALE == 'en-PR') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_PW' || goog.LOCALE == 'en-PW') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_SG' || goog.LOCALE == 'en-SG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_SG;
    -}
    -
    -if (goog.LOCALE == 'en_TC' || goog.LOCALE == 'en-TC') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_UM' || goog.LOCALE == 'en-UM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_US' || goog.LOCALE == 'en-US') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_VG' || goog.LOCALE == 'en-VG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_VI' || goog.LOCALE == 'en-VI') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_ZA' || goog.LOCALE == 'en-ZA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_ZA;
    -}
    -
    -if (goog.LOCALE == 'en_ZW' || goog.LOCALE == 'en-ZW') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'es') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es;
    -}
    -
    -if (goog.LOCALE == 'es_419' || goog.LOCALE == 'es-419') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es_419;
    -}
    -
    -if (goog.LOCALE == 'es_EA' || goog.LOCALE == 'es-EA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es;
    -}
    -
    -if (goog.LOCALE == 'es_ES' || goog.LOCALE == 'es-ES') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es;
    -}
    -
    -if (goog.LOCALE == 'es_IC' || goog.LOCALE == 'es-IC') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es;
    -}
    -
    -if (goog.LOCALE == 'et') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_et;
    -}
    -
    -if (goog.LOCALE == 'et_EE' || goog.LOCALE == 'et-EE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_et;
    -}
    -
    -if (goog.LOCALE == 'eu') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_eu;
    -}
    -
    -if (goog.LOCALE == 'eu_ES' || goog.LOCALE == 'eu-ES') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_eu;
    -}
    -
    -if (goog.LOCALE == 'fa') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fa;
    -}
    -
    -if (goog.LOCALE == 'fa_IR' || goog.LOCALE == 'fa-IR') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fa;
    -}
    -
    -if (goog.LOCALE == 'fi') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fi;
    -}
    -
    -if (goog.LOCALE == 'fi_FI' || goog.LOCALE == 'fi-FI') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fi;
    -}
    -
    -if (goog.LOCALE == 'fil') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fil;
    -}
    -
    -if (goog.LOCALE == 'fil_PH' || goog.LOCALE == 'fil-PH') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fil;
    -}
    -
    -if (goog.LOCALE == 'fr') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr;
    -}
    -
    -if (goog.LOCALE == 'fr_BL' || goog.LOCALE == 'fr-BL') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr;
    -}
    -
    -if (goog.LOCALE == 'fr_CA' || goog.LOCALE == 'fr-CA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_CA;
    -}
    -
    -if (goog.LOCALE == 'fr_FR' || goog.LOCALE == 'fr-FR') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr;
    -}
    -
    -if (goog.LOCALE == 'fr_GF' || goog.LOCALE == 'fr-GF') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr;
    -}
    -
    -if (goog.LOCALE == 'fr_GP' || goog.LOCALE == 'fr-GP') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr;
    -}
    -
    -if (goog.LOCALE == 'fr_MC' || goog.LOCALE == 'fr-MC') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr;
    -}
    -
    -if (goog.LOCALE == 'fr_MF' || goog.LOCALE == 'fr-MF') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr;
    -}
    -
    -if (goog.LOCALE == 'fr_MQ' || goog.LOCALE == 'fr-MQ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr;
    -}
    -
    -if (goog.LOCALE == 'fr_PM' || goog.LOCALE == 'fr-PM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr;
    -}
    -
    -if (goog.LOCALE == 'fr_RE' || goog.LOCALE == 'fr-RE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr;
    -}
    -
    -if (goog.LOCALE == 'fr_YT' || goog.LOCALE == 'fr-YT') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr;
    -}
    -
    -if (goog.LOCALE == 'ga') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ga;
    -}
    -
    -if (goog.LOCALE == 'ga_IE' || goog.LOCALE == 'ga-IE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ga;
    -}
    -
    -if (goog.LOCALE == 'gl') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_gl;
    -}
    -
    -if (goog.LOCALE == 'gl_ES' || goog.LOCALE == 'gl-ES') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_gl;
    -}
    -
    -if (goog.LOCALE == 'gsw') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_gsw;
    -}
    -
    -if (goog.LOCALE == 'gsw_CH' || goog.LOCALE == 'gsw-CH') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_gsw;
    -}
    -
    -if (goog.LOCALE == 'gsw_LI' || goog.LOCALE == 'gsw-LI') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_gsw;
    -}
    -
    -if (goog.LOCALE == 'gu') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_gu;
    -}
    -
    -if (goog.LOCALE == 'gu_IN' || goog.LOCALE == 'gu-IN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_gu;
    -}
    -
    -if (goog.LOCALE == 'haw') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_haw;
    -}
    -
    -if (goog.LOCALE == 'haw_US' || goog.LOCALE == 'haw-US') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_haw;
    -}
    -
    -if (goog.LOCALE == 'he') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_he;
    -}
    -
    -if (goog.LOCALE == 'he_IL' || goog.LOCALE == 'he-IL') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_he;
    -}
    -
    -if (goog.LOCALE == 'hi') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_hi;
    -}
    -
    -if (goog.LOCALE == 'hi_IN' || goog.LOCALE == 'hi-IN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_hi;
    -}
    -
    -if (goog.LOCALE == 'hr') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_hr;
    -}
    -
    -if (goog.LOCALE == 'hr_HR' || goog.LOCALE == 'hr-HR') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_hr;
    -}
    -
    -if (goog.LOCALE == 'hu') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_hu;
    -}
    -
    -if (goog.LOCALE == 'hu_HU' || goog.LOCALE == 'hu-HU') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_hu;
    -}
    -
    -if (goog.LOCALE == 'hy') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_hy;
    -}
    -
    -if (goog.LOCALE == 'hy_AM' || goog.LOCALE == 'hy-AM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_hy;
    -}
    -
    -if (goog.LOCALE == 'id') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_id;
    -}
    -
    -if (goog.LOCALE == 'id_ID' || goog.LOCALE == 'id-ID') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_id;
    -}
    -
    -if (goog.LOCALE == 'in') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_in;
    -}
    -
    -if (goog.LOCALE == 'is') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_is;
    -}
    -
    -if (goog.LOCALE == 'is_IS' || goog.LOCALE == 'is-IS') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_is;
    -}
    -
    -if (goog.LOCALE == 'it') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_it;
    -}
    -
    -if (goog.LOCALE == 'it_IT' || goog.LOCALE == 'it-IT') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_it;
    -}
    -
    -if (goog.LOCALE == 'it_SM' || goog.LOCALE == 'it-SM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_it;
    -}
    -
    -if (goog.LOCALE == 'iw') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_iw;
    -}
    -
    -if (goog.LOCALE == 'ja') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ja;
    -}
    -
    -if (goog.LOCALE == 'ja_JP' || goog.LOCALE == 'ja-JP') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ja;
    -}
    -
    -if (goog.LOCALE == 'ka') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ka;
    -}
    -
    -if (goog.LOCALE == 'ka_GE' || goog.LOCALE == 'ka-GE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ka;
    -}
    -
    -if (goog.LOCALE == 'kk') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_kk;
    -}
    -
    -if (goog.LOCALE == 'kk_Cyrl_KZ' || goog.LOCALE == 'kk-Cyrl-KZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_kk;
    -}
    -
    -if (goog.LOCALE == 'km') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_km;
    -}
    -
    -if (goog.LOCALE == 'km_KH' || goog.LOCALE == 'km-KH') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_km;
    -}
    -
    -if (goog.LOCALE == 'kn') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_kn;
    -}
    -
    -if (goog.LOCALE == 'kn_IN' || goog.LOCALE == 'kn-IN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_kn;
    -}
    -
    -if (goog.LOCALE == 'ko') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ko;
    -}
    -
    -if (goog.LOCALE == 'ko_KR' || goog.LOCALE == 'ko-KR') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ko;
    -}
    -
    -if (goog.LOCALE == 'ky') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ky;
    -}
    -
    -if (goog.LOCALE == 'ky_Cyrl_KG' || goog.LOCALE == 'ky-Cyrl-KG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ky;
    -}
    -
    -if (goog.LOCALE == 'ln') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ln;
    -}
    -
    -if (goog.LOCALE == 'ln_CD' || goog.LOCALE == 'ln-CD') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ln;
    -}
    -
    -if (goog.LOCALE == 'lo') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_lo;
    -}
    -
    -if (goog.LOCALE == 'lo_LA' || goog.LOCALE == 'lo-LA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_lo;
    -}
    -
    -if (goog.LOCALE == 'lt') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_lt;
    -}
    -
    -if (goog.LOCALE == 'lt_LT' || goog.LOCALE == 'lt-LT') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_lt;
    -}
    -
    -if (goog.LOCALE == 'lv') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_lv;
    -}
    -
    -if (goog.LOCALE == 'lv_LV' || goog.LOCALE == 'lv-LV') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_lv;
    -}
    -
    -if (goog.LOCALE == 'mk') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mk;
    -}
    -
    -if (goog.LOCALE == 'mk_MK' || goog.LOCALE == 'mk-MK') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mk;
    -}
    -
    -if (goog.LOCALE == 'ml') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ml;
    -}
    -
    -if (goog.LOCALE == 'ml_IN' || goog.LOCALE == 'ml-IN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ml;
    -}
    -
    -if (goog.LOCALE == 'mn') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mn;
    -}
    -
    -if (goog.LOCALE == 'mn_Cyrl_MN' || goog.LOCALE == 'mn-Cyrl-MN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mn;
    -}
    -
    -if (goog.LOCALE == 'mr') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mr;
    -}
    -
    -if (goog.LOCALE == 'mr_IN' || goog.LOCALE == 'mr-IN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mr;
    -}
    -
    -if (goog.LOCALE == 'ms') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ms;
    -}
    -
    -if (goog.LOCALE == 'ms_Latn_MY' || goog.LOCALE == 'ms-Latn-MY') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ms;
    -}
    -
    -if (goog.LOCALE == 'mt') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mt;
    -}
    -
    -if (goog.LOCALE == 'mt_MT' || goog.LOCALE == 'mt-MT') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mt;
    -}
    -
    -if (goog.LOCALE == 'my') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_my;
    -}
    -
    -if (goog.LOCALE == 'my_MM' || goog.LOCALE == 'my-MM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_my;
    -}
    -
    -if (goog.LOCALE == 'nb') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_nb;
    -}
    -
    -if (goog.LOCALE == 'nb_NO' || goog.LOCALE == 'nb-NO') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_nb;
    -}
    -
    -if (goog.LOCALE == 'nb_SJ' || goog.LOCALE == 'nb-SJ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_nb;
    -}
    -
    -if (goog.LOCALE == 'ne') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ne;
    -}
    -
    -if (goog.LOCALE == 'ne_NP' || goog.LOCALE == 'ne-NP') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ne;
    -}
    -
    -if (goog.LOCALE == 'nl') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_nl;
    -}
    -
    -if (goog.LOCALE == 'nl_NL' || goog.LOCALE == 'nl-NL') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_nl;
    -}
    -
    -if (goog.LOCALE == 'no') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_no;
    -}
    -
    -if (goog.LOCALE == 'no_NO' || goog.LOCALE == 'no-NO') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_no;
    -}
    -
    -if (goog.LOCALE == 'or') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_or;
    -}
    -
    -if (goog.LOCALE == 'or_IN' || goog.LOCALE == 'or-IN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_or;
    -}
    -
    -if (goog.LOCALE == 'pa') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_pa;
    -}
    -
    -if (goog.LOCALE == 'pa_Guru_IN' || goog.LOCALE == 'pa-Guru-IN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_pa;
    -}
    -
    -if (goog.LOCALE == 'pl') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_pl;
    -}
    -
    -if (goog.LOCALE == 'pl_PL' || goog.LOCALE == 'pl-PL') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_pl;
    -}
    -
    -if (goog.LOCALE == 'pt') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_pt;
    -}
    -
    -if (goog.LOCALE == 'pt_BR' || goog.LOCALE == 'pt-BR') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_pt;
    -}
    -
    -if (goog.LOCALE == 'pt_PT' || goog.LOCALE == 'pt-PT') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_pt_PT;
    -}
    -
    -if (goog.LOCALE == 'ro') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ro;
    -}
    -
    -if (goog.LOCALE == 'ro_RO' || goog.LOCALE == 'ro-RO') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ro;
    -}
    -
    -if (goog.LOCALE == 'ru') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ru;
    -}
    -
    -if (goog.LOCALE == 'ru_RU' || goog.LOCALE == 'ru-RU') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ru;
    -}
    -
    -if (goog.LOCALE == 'si') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_si;
    -}
    -
    -if (goog.LOCALE == 'si_LK' || goog.LOCALE == 'si-LK') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_si;
    -}
    -
    -if (goog.LOCALE == 'sk') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sk;
    -}
    -
    -if (goog.LOCALE == 'sk_SK' || goog.LOCALE == 'sk-SK') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sk;
    -}
    -
    -if (goog.LOCALE == 'sl') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sl;
    -}
    -
    -if (goog.LOCALE == 'sl_SI' || goog.LOCALE == 'sl-SI') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sl;
    -}
    -
    -if (goog.LOCALE == 'sq') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sq;
    -}
    -
    -if (goog.LOCALE == 'sq_AL' || goog.LOCALE == 'sq-AL') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sq;
    -}
    -
    -if (goog.LOCALE == 'sr') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sr;
    -}
    -
    -if (goog.LOCALE == 'sr_Cyrl_RS' || goog.LOCALE == 'sr-Cyrl-RS') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sr;
    -}
    -
    -if (goog.LOCALE == 'sv') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sv;
    -}
    -
    -if (goog.LOCALE == 'sv_SE' || goog.LOCALE == 'sv-SE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sv;
    -}
    -
    -if (goog.LOCALE == 'sw') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sw;
    -}
    -
    -if (goog.LOCALE == 'sw_TZ' || goog.LOCALE == 'sw-TZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sw;
    -}
    -
    -if (goog.LOCALE == 'ta') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ta;
    -}
    -
    -if (goog.LOCALE == 'ta_IN' || goog.LOCALE == 'ta-IN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ta;
    -}
    -
    -if (goog.LOCALE == 'te') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_te;
    -}
    -
    -if (goog.LOCALE == 'te_IN' || goog.LOCALE == 'te-IN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_te;
    -}
    -
    -if (goog.LOCALE == 'th') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_th;
    -}
    -
    -if (goog.LOCALE == 'th_TH' || goog.LOCALE == 'th-TH') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_th;
    -}
    -
    -if (goog.LOCALE == 'tl') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_tl;
    -}
    -
    -if (goog.LOCALE == 'tr') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_tr;
    -}
    -
    -if (goog.LOCALE == 'tr_TR' || goog.LOCALE == 'tr-TR') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_tr;
    -}
    -
    -if (goog.LOCALE == 'uk') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_uk;
    -}
    -
    -if (goog.LOCALE == 'uk_UA' || goog.LOCALE == 'uk-UA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_uk;
    -}
    -
    -if (goog.LOCALE == 'ur') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ur;
    -}
    -
    -if (goog.LOCALE == 'ur_PK' || goog.LOCALE == 'ur-PK') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ur;
    -}
    -
    -if (goog.LOCALE == 'uz') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_uz;
    -}
    -
    -if (goog.LOCALE == 'uz_Latn_UZ' || goog.LOCALE == 'uz-Latn-UZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_uz;
    -}
    -
    -if (goog.LOCALE == 'vi') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_vi;
    -}
    -
    -if (goog.LOCALE == 'vi_VN' || goog.LOCALE == 'vi-VN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_vi;
    -}
    -
    -if (goog.LOCALE == 'zh') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_zh;
    -}
    -
    -if (goog.LOCALE == 'zh_CN' || goog.LOCALE == 'zh-CN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_zh;
    -}
    -
    -if (goog.LOCALE == 'zh_HK' || goog.LOCALE == 'zh-HK') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_zh_HK;
    -}
    -
    -if (goog.LOCALE == 'zh_Hans_CN' || goog.LOCALE == 'zh-Hans-CN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_zh;
    -}
    -
    -if (goog.LOCALE == 'zh_TW' || goog.LOCALE == 'zh-TW') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_zh_TW;
    -}
    -
    -if (goog.LOCALE == 'zu') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_zu;
    -}
    -
    -if (goog.LOCALE == 'zu_ZA' || goog.LOCALE == 'zu-ZA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_zu;
    -}
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/numberformatsymbolsext.js b/src/database/third_party/closure-library/closure/goog/i18n/numberformatsymbolsext.js
    deleted file mode 100644
    index e9c011196ca..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/numberformatsymbolsext.js
    +++ /dev/null
    @@ -1,12374 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Number formatting symbols.
    - *
    - * This file is autogenerated by script:
    - * http://go/generate_number_constants.py
    - * using the --for_closure flag.
    - * File generated from CLDR ver. 26
    - *
    - * This file coveres those locales that are not covered in
    - * "numberformatsymbols.js".
    - *
    - * Before checkin, this file could have been manually edited. This is
    - * to incorporate changes before we could fix CLDR. All manual
    - * modification must be documented in this section, and should be
    - * removed after those changes land to CLDR.
    - */
    -
    -goog.provide('goog.i18n.NumberFormatSymbolsExt');
    -goog.provide('goog.i18n.NumberFormatSymbols_aa');
    -goog.provide('goog.i18n.NumberFormatSymbols_aa_DJ');
    -goog.provide('goog.i18n.NumberFormatSymbols_aa_ER');
    -goog.provide('goog.i18n.NumberFormatSymbols_aa_ET');
    -goog.provide('goog.i18n.NumberFormatSymbols_af_NA');
    -goog.provide('goog.i18n.NumberFormatSymbols_agq');
    -goog.provide('goog.i18n.NumberFormatSymbols_agq_CM');
    -goog.provide('goog.i18n.NumberFormatSymbols_ak');
    -goog.provide('goog.i18n.NumberFormatSymbols_ak_GH');
    -goog.provide('goog.i18n.NumberFormatSymbols_ar_AE');
    -goog.provide('goog.i18n.NumberFormatSymbols_ar_BH');
    -goog.provide('goog.i18n.NumberFormatSymbols_ar_DJ');
    -goog.provide('goog.i18n.NumberFormatSymbols_ar_DZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_ar_EG');
    -goog.provide('goog.i18n.NumberFormatSymbols_ar_EH');
    -goog.provide('goog.i18n.NumberFormatSymbols_ar_ER');
    -goog.provide('goog.i18n.NumberFormatSymbols_ar_IL');
    -goog.provide('goog.i18n.NumberFormatSymbols_ar_IQ');
    -goog.provide('goog.i18n.NumberFormatSymbols_ar_JO');
    -goog.provide('goog.i18n.NumberFormatSymbols_ar_KM');
    -goog.provide('goog.i18n.NumberFormatSymbols_ar_KW');
    -goog.provide('goog.i18n.NumberFormatSymbols_ar_LB');
    -goog.provide('goog.i18n.NumberFormatSymbols_ar_LY');
    -goog.provide('goog.i18n.NumberFormatSymbols_ar_MA');
    -goog.provide('goog.i18n.NumberFormatSymbols_ar_MR');
    -goog.provide('goog.i18n.NumberFormatSymbols_ar_OM');
    -goog.provide('goog.i18n.NumberFormatSymbols_ar_PS');
    -goog.provide('goog.i18n.NumberFormatSymbols_ar_QA');
    -goog.provide('goog.i18n.NumberFormatSymbols_ar_SA');
    -goog.provide('goog.i18n.NumberFormatSymbols_ar_SD');
    -goog.provide('goog.i18n.NumberFormatSymbols_ar_SO');
    -goog.provide('goog.i18n.NumberFormatSymbols_ar_SS');
    -goog.provide('goog.i18n.NumberFormatSymbols_ar_SY');
    -goog.provide('goog.i18n.NumberFormatSymbols_ar_TD');
    -goog.provide('goog.i18n.NumberFormatSymbols_ar_TN');
    -goog.provide('goog.i18n.NumberFormatSymbols_ar_YE');
    -goog.provide('goog.i18n.NumberFormatSymbols_as');
    -goog.provide('goog.i18n.NumberFormatSymbols_as_IN');
    -goog.provide('goog.i18n.NumberFormatSymbols_asa');
    -goog.provide('goog.i18n.NumberFormatSymbols_asa_TZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_ast');
    -goog.provide('goog.i18n.NumberFormatSymbols_ast_ES');
    -goog.provide('goog.i18n.NumberFormatSymbols_az_Cyrl');
    -goog.provide('goog.i18n.NumberFormatSymbols_az_Cyrl_AZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_az_Latn');
    -goog.provide('goog.i18n.NumberFormatSymbols_bas');
    -goog.provide('goog.i18n.NumberFormatSymbols_bas_CM');
    -goog.provide('goog.i18n.NumberFormatSymbols_be');
    -goog.provide('goog.i18n.NumberFormatSymbols_be_BY');
    -goog.provide('goog.i18n.NumberFormatSymbols_bem');
    -goog.provide('goog.i18n.NumberFormatSymbols_bem_ZM');
    -goog.provide('goog.i18n.NumberFormatSymbols_bez');
    -goog.provide('goog.i18n.NumberFormatSymbols_bez_TZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_bm');
    -goog.provide('goog.i18n.NumberFormatSymbols_bm_Latn');
    -goog.provide('goog.i18n.NumberFormatSymbols_bm_Latn_ML');
    -goog.provide('goog.i18n.NumberFormatSymbols_bn_IN');
    -goog.provide('goog.i18n.NumberFormatSymbols_bo');
    -goog.provide('goog.i18n.NumberFormatSymbols_bo_CN');
    -goog.provide('goog.i18n.NumberFormatSymbols_bo_IN');
    -goog.provide('goog.i18n.NumberFormatSymbols_brx');
    -goog.provide('goog.i18n.NumberFormatSymbols_brx_IN');
    -goog.provide('goog.i18n.NumberFormatSymbols_bs');
    -goog.provide('goog.i18n.NumberFormatSymbols_bs_Cyrl');
    -goog.provide('goog.i18n.NumberFormatSymbols_bs_Cyrl_BA');
    -goog.provide('goog.i18n.NumberFormatSymbols_bs_Latn');
    -goog.provide('goog.i18n.NumberFormatSymbols_bs_Latn_BA');
    -goog.provide('goog.i18n.NumberFormatSymbols_cgg');
    -goog.provide('goog.i18n.NumberFormatSymbols_cgg_UG');
    -goog.provide('goog.i18n.NumberFormatSymbols_ckb');
    -goog.provide('goog.i18n.NumberFormatSymbols_ckb_Arab');
    -goog.provide('goog.i18n.NumberFormatSymbols_ckb_Arab_IQ');
    -goog.provide('goog.i18n.NumberFormatSymbols_ckb_Arab_IR');
    -goog.provide('goog.i18n.NumberFormatSymbols_ckb_IQ');
    -goog.provide('goog.i18n.NumberFormatSymbols_ckb_IR');
    -goog.provide('goog.i18n.NumberFormatSymbols_ckb_Latn');
    -goog.provide('goog.i18n.NumberFormatSymbols_ckb_Latn_IQ');
    -goog.provide('goog.i18n.NumberFormatSymbols_dav');
    -goog.provide('goog.i18n.NumberFormatSymbols_dav_KE');
    -goog.provide('goog.i18n.NumberFormatSymbols_de_LI');
    -goog.provide('goog.i18n.NumberFormatSymbols_dje');
    -goog.provide('goog.i18n.NumberFormatSymbols_dje_NE');
    -goog.provide('goog.i18n.NumberFormatSymbols_dsb');
    -goog.provide('goog.i18n.NumberFormatSymbols_dsb_DE');
    -goog.provide('goog.i18n.NumberFormatSymbols_dua');
    -goog.provide('goog.i18n.NumberFormatSymbols_dua_CM');
    -goog.provide('goog.i18n.NumberFormatSymbols_dyo');
    -goog.provide('goog.i18n.NumberFormatSymbols_dyo_SN');
    -goog.provide('goog.i18n.NumberFormatSymbols_dz');
    -goog.provide('goog.i18n.NumberFormatSymbols_dz_BT');
    -goog.provide('goog.i18n.NumberFormatSymbols_ebu');
    -goog.provide('goog.i18n.NumberFormatSymbols_ebu_KE');
    -goog.provide('goog.i18n.NumberFormatSymbols_ee');
    -goog.provide('goog.i18n.NumberFormatSymbols_ee_GH');
    -goog.provide('goog.i18n.NumberFormatSymbols_ee_TG');
    -goog.provide('goog.i18n.NumberFormatSymbols_el_CY');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_150');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_AG');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_AI');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_BB');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_BE');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_BM');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_BS');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_BW');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_BZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_CA');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_CC');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_CK');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_CM');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_CX');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_DM');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_ER');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_FJ');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_FK');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_GD');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_GG');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_GH');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_GI');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_GM');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_GY');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_HK');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_IM');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_JE');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_JM');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_KE');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_KI');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_KN');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_KY');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_LC');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_LR');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_LS');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_MG');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_MO');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_MS');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_MT');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_MU');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_MW');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_MY');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_NA');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_NF');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_NG');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_NR');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_NU');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_NZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_PG');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_PH');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_PK');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_PN');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_RW');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_SB');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_SC');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_SD');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_SH');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_SL');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_SS');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_SX');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_SZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_TK');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_TO');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_TT');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_TV');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_TZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_UG');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_VC');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_VU');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_WS');
    -goog.provide('goog.i18n.NumberFormatSymbols_en_ZM');
    -goog.provide('goog.i18n.NumberFormatSymbols_eo');
    -goog.provide('goog.i18n.NumberFormatSymbols_eo_001');
    -goog.provide('goog.i18n.NumberFormatSymbols_es_AR');
    -goog.provide('goog.i18n.NumberFormatSymbols_es_BO');
    -goog.provide('goog.i18n.NumberFormatSymbols_es_CL');
    -goog.provide('goog.i18n.NumberFormatSymbols_es_CO');
    -goog.provide('goog.i18n.NumberFormatSymbols_es_CR');
    -goog.provide('goog.i18n.NumberFormatSymbols_es_CU');
    -goog.provide('goog.i18n.NumberFormatSymbols_es_DO');
    -goog.provide('goog.i18n.NumberFormatSymbols_es_EC');
    -goog.provide('goog.i18n.NumberFormatSymbols_es_GQ');
    -goog.provide('goog.i18n.NumberFormatSymbols_es_GT');
    -goog.provide('goog.i18n.NumberFormatSymbols_es_HN');
    -goog.provide('goog.i18n.NumberFormatSymbols_es_MX');
    -goog.provide('goog.i18n.NumberFormatSymbols_es_NI');
    -goog.provide('goog.i18n.NumberFormatSymbols_es_PA');
    -goog.provide('goog.i18n.NumberFormatSymbols_es_PE');
    -goog.provide('goog.i18n.NumberFormatSymbols_es_PH');
    -goog.provide('goog.i18n.NumberFormatSymbols_es_PR');
    -goog.provide('goog.i18n.NumberFormatSymbols_es_PY');
    -goog.provide('goog.i18n.NumberFormatSymbols_es_SV');
    -goog.provide('goog.i18n.NumberFormatSymbols_es_US');
    -goog.provide('goog.i18n.NumberFormatSymbols_es_UY');
    -goog.provide('goog.i18n.NumberFormatSymbols_es_VE');
    -goog.provide('goog.i18n.NumberFormatSymbols_ewo');
    -goog.provide('goog.i18n.NumberFormatSymbols_ewo_CM');
    -goog.provide('goog.i18n.NumberFormatSymbols_fa_AF');
    -goog.provide('goog.i18n.NumberFormatSymbols_ff');
    -goog.provide('goog.i18n.NumberFormatSymbols_ff_CM');
    -goog.provide('goog.i18n.NumberFormatSymbols_ff_GN');
    -goog.provide('goog.i18n.NumberFormatSymbols_ff_MR');
    -goog.provide('goog.i18n.NumberFormatSymbols_ff_SN');
    -goog.provide('goog.i18n.NumberFormatSymbols_fo');
    -goog.provide('goog.i18n.NumberFormatSymbols_fo_FO');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_BE');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_BF');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_BI');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_BJ');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_CD');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_CF');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_CG');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_CH');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_CI');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_CM');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_DJ');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_DZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_GA');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_GN');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_GQ');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_HT');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_KM');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_LU');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_MA');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_MG');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_ML');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_MR');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_MU');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_NC');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_NE');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_PF');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_RW');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_SC');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_SN');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_SY');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_TD');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_TG');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_TN');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_VU');
    -goog.provide('goog.i18n.NumberFormatSymbols_fr_WF');
    -goog.provide('goog.i18n.NumberFormatSymbols_fur');
    -goog.provide('goog.i18n.NumberFormatSymbols_fur_IT');
    -goog.provide('goog.i18n.NumberFormatSymbols_fy');
    -goog.provide('goog.i18n.NumberFormatSymbols_fy_NL');
    -goog.provide('goog.i18n.NumberFormatSymbols_gd');
    -goog.provide('goog.i18n.NumberFormatSymbols_gd_GB');
    -goog.provide('goog.i18n.NumberFormatSymbols_gsw_FR');
    -goog.provide('goog.i18n.NumberFormatSymbols_guz');
    -goog.provide('goog.i18n.NumberFormatSymbols_guz_KE');
    -goog.provide('goog.i18n.NumberFormatSymbols_gv');
    -goog.provide('goog.i18n.NumberFormatSymbols_gv_IM');
    -goog.provide('goog.i18n.NumberFormatSymbols_ha');
    -goog.provide('goog.i18n.NumberFormatSymbols_ha_Latn');
    -goog.provide('goog.i18n.NumberFormatSymbols_ha_Latn_GH');
    -goog.provide('goog.i18n.NumberFormatSymbols_ha_Latn_NE');
    -goog.provide('goog.i18n.NumberFormatSymbols_ha_Latn_NG');
    -goog.provide('goog.i18n.NumberFormatSymbols_hr_BA');
    -goog.provide('goog.i18n.NumberFormatSymbols_hsb');
    -goog.provide('goog.i18n.NumberFormatSymbols_hsb_DE');
    -goog.provide('goog.i18n.NumberFormatSymbols_ia');
    -goog.provide('goog.i18n.NumberFormatSymbols_ia_FR');
    -goog.provide('goog.i18n.NumberFormatSymbols_ig');
    -goog.provide('goog.i18n.NumberFormatSymbols_ig_NG');
    -goog.provide('goog.i18n.NumberFormatSymbols_ii');
    -goog.provide('goog.i18n.NumberFormatSymbols_ii_CN');
    -goog.provide('goog.i18n.NumberFormatSymbols_it_CH');
    -goog.provide('goog.i18n.NumberFormatSymbols_jgo');
    -goog.provide('goog.i18n.NumberFormatSymbols_jgo_CM');
    -goog.provide('goog.i18n.NumberFormatSymbols_jmc');
    -goog.provide('goog.i18n.NumberFormatSymbols_jmc_TZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_kab');
    -goog.provide('goog.i18n.NumberFormatSymbols_kab_DZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_kam');
    -goog.provide('goog.i18n.NumberFormatSymbols_kam_KE');
    -goog.provide('goog.i18n.NumberFormatSymbols_kde');
    -goog.provide('goog.i18n.NumberFormatSymbols_kde_TZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_kea');
    -goog.provide('goog.i18n.NumberFormatSymbols_kea_CV');
    -goog.provide('goog.i18n.NumberFormatSymbols_khq');
    -goog.provide('goog.i18n.NumberFormatSymbols_khq_ML');
    -goog.provide('goog.i18n.NumberFormatSymbols_ki');
    -goog.provide('goog.i18n.NumberFormatSymbols_ki_KE');
    -goog.provide('goog.i18n.NumberFormatSymbols_kk_Cyrl');
    -goog.provide('goog.i18n.NumberFormatSymbols_kkj');
    -goog.provide('goog.i18n.NumberFormatSymbols_kkj_CM');
    -goog.provide('goog.i18n.NumberFormatSymbols_kl');
    -goog.provide('goog.i18n.NumberFormatSymbols_kl_GL');
    -goog.provide('goog.i18n.NumberFormatSymbols_kln');
    -goog.provide('goog.i18n.NumberFormatSymbols_kln_KE');
    -goog.provide('goog.i18n.NumberFormatSymbols_ko_KP');
    -goog.provide('goog.i18n.NumberFormatSymbols_kok');
    -goog.provide('goog.i18n.NumberFormatSymbols_kok_IN');
    -goog.provide('goog.i18n.NumberFormatSymbols_ks');
    -goog.provide('goog.i18n.NumberFormatSymbols_ks_Arab');
    -goog.provide('goog.i18n.NumberFormatSymbols_ks_Arab_IN');
    -goog.provide('goog.i18n.NumberFormatSymbols_ksb');
    -goog.provide('goog.i18n.NumberFormatSymbols_ksb_TZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_ksf');
    -goog.provide('goog.i18n.NumberFormatSymbols_ksf_CM');
    -goog.provide('goog.i18n.NumberFormatSymbols_ksh');
    -goog.provide('goog.i18n.NumberFormatSymbols_ksh_DE');
    -goog.provide('goog.i18n.NumberFormatSymbols_kw');
    -goog.provide('goog.i18n.NumberFormatSymbols_kw_GB');
    -goog.provide('goog.i18n.NumberFormatSymbols_ky_Cyrl');
    -goog.provide('goog.i18n.NumberFormatSymbols_lag');
    -goog.provide('goog.i18n.NumberFormatSymbols_lag_TZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_lb');
    -goog.provide('goog.i18n.NumberFormatSymbols_lb_LU');
    -goog.provide('goog.i18n.NumberFormatSymbols_lg');
    -goog.provide('goog.i18n.NumberFormatSymbols_lg_UG');
    -goog.provide('goog.i18n.NumberFormatSymbols_lkt');
    -goog.provide('goog.i18n.NumberFormatSymbols_lkt_US');
    -goog.provide('goog.i18n.NumberFormatSymbols_ln_AO');
    -goog.provide('goog.i18n.NumberFormatSymbols_ln_CF');
    -goog.provide('goog.i18n.NumberFormatSymbols_ln_CG');
    -goog.provide('goog.i18n.NumberFormatSymbols_lu');
    -goog.provide('goog.i18n.NumberFormatSymbols_lu_CD');
    -goog.provide('goog.i18n.NumberFormatSymbols_luo');
    -goog.provide('goog.i18n.NumberFormatSymbols_luo_KE');
    -goog.provide('goog.i18n.NumberFormatSymbols_luy');
    -goog.provide('goog.i18n.NumberFormatSymbols_luy_KE');
    -goog.provide('goog.i18n.NumberFormatSymbols_mas');
    -goog.provide('goog.i18n.NumberFormatSymbols_mas_KE');
    -goog.provide('goog.i18n.NumberFormatSymbols_mas_TZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_mer');
    -goog.provide('goog.i18n.NumberFormatSymbols_mer_KE');
    -goog.provide('goog.i18n.NumberFormatSymbols_mfe');
    -goog.provide('goog.i18n.NumberFormatSymbols_mfe_MU');
    -goog.provide('goog.i18n.NumberFormatSymbols_mg');
    -goog.provide('goog.i18n.NumberFormatSymbols_mg_MG');
    -goog.provide('goog.i18n.NumberFormatSymbols_mgh');
    -goog.provide('goog.i18n.NumberFormatSymbols_mgh_MZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_mgo');
    -goog.provide('goog.i18n.NumberFormatSymbols_mgo_CM');
    -goog.provide('goog.i18n.NumberFormatSymbols_mn_Cyrl');
    -goog.provide('goog.i18n.NumberFormatSymbols_ms_Latn');
    -goog.provide('goog.i18n.NumberFormatSymbols_ms_Latn_BN');
    -goog.provide('goog.i18n.NumberFormatSymbols_ms_Latn_SG');
    -goog.provide('goog.i18n.NumberFormatSymbols_mua');
    -goog.provide('goog.i18n.NumberFormatSymbols_mua_CM');
    -goog.provide('goog.i18n.NumberFormatSymbols_naq');
    -goog.provide('goog.i18n.NumberFormatSymbols_naq_NA');
    -goog.provide('goog.i18n.NumberFormatSymbols_nd');
    -goog.provide('goog.i18n.NumberFormatSymbols_nd_ZW');
    -goog.provide('goog.i18n.NumberFormatSymbols_ne_IN');
    -goog.provide('goog.i18n.NumberFormatSymbols_nl_AW');
    -goog.provide('goog.i18n.NumberFormatSymbols_nl_BE');
    -goog.provide('goog.i18n.NumberFormatSymbols_nl_BQ');
    -goog.provide('goog.i18n.NumberFormatSymbols_nl_CW');
    -goog.provide('goog.i18n.NumberFormatSymbols_nl_SR');
    -goog.provide('goog.i18n.NumberFormatSymbols_nl_SX');
    -goog.provide('goog.i18n.NumberFormatSymbols_nmg');
    -goog.provide('goog.i18n.NumberFormatSymbols_nmg_CM');
    -goog.provide('goog.i18n.NumberFormatSymbols_nn');
    -goog.provide('goog.i18n.NumberFormatSymbols_nn_NO');
    -goog.provide('goog.i18n.NumberFormatSymbols_nnh');
    -goog.provide('goog.i18n.NumberFormatSymbols_nnh_CM');
    -goog.provide('goog.i18n.NumberFormatSymbols_nr');
    -goog.provide('goog.i18n.NumberFormatSymbols_nr_ZA');
    -goog.provide('goog.i18n.NumberFormatSymbols_nso');
    -goog.provide('goog.i18n.NumberFormatSymbols_nso_ZA');
    -goog.provide('goog.i18n.NumberFormatSymbols_nus');
    -goog.provide('goog.i18n.NumberFormatSymbols_nus_SD');
    -goog.provide('goog.i18n.NumberFormatSymbols_nyn');
    -goog.provide('goog.i18n.NumberFormatSymbols_nyn_UG');
    -goog.provide('goog.i18n.NumberFormatSymbols_om');
    -goog.provide('goog.i18n.NumberFormatSymbols_om_ET');
    -goog.provide('goog.i18n.NumberFormatSymbols_om_KE');
    -goog.provide('goog.i18n.NumberFormatSymbols_os');
    -goog.provide('goog.i18n.NumberFormatSymbols_os_GE');
    -goog.provide('goog.i18n.NumberFormatSymbols_os_RU');
    -goog.provide('goog.i18n.NumberFormatSymbols_pa_Arab');
    -goog.provide('goog.i18n.NumberFormatSymbols_pa_Arab_PK');
    -goog.provide('goog.i18n.NumberFormatSymbols_pa_Guru');
    -goog.provide('goog.i18n.NumberFormatSymbols_ps');
    -goog.provide('goog.i18n.NumberFormatSymbols_ps_AF');
    -goog.provide('goog.i18n.NumberFormatSymbols_pt_AO');
    -goog.provide('goog.i18n.NumberFormatSymbols_pt_CV');
    -goog.provide('goog.i18n.NumberFormatSymbols_pt_GW');
    -goog.provide('goog.i18n.NumberFormatSymbols_pt_MO');
    -goog.provide('goog.i18n.NumberFormatSymbols_pt_MZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_pt_ST');
    -goog.provide('goog.i18n.NumberFormatSymbols_pt_TL');
    -goog.provide('goog.i18n.NumberFormatSymbols_qu');
    -goog.provide('goog.i18n.NumberFormatSymbols_qu_BO');
    -goog.provide('goog.i18n.NumberFormatSymbols_qu_EC');
    -goog.provide('goog.i18n.NumberFormatSymbols_qu_PE');
    -goog.provide('goog.i18n.NumberFormatSymbols_rm');
    -goog.provide('goog.i18n.NumberFormatSymbols_rm_CH');
    -goog.provide('goog.i18n.NumberFormatSymbols_rn');
    -goog.provide('goog.i18n.NumberFormatSymbols_rn_BI');
    -goog.provide('goog.i18n.NumberFormatSymbols_ro_MD');
    -goog.provide('goog.i18n.NumberFormatSymbols_rof');
    -goog.provide('goog.i18n.NumberFormatSymbols_rof_TZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_ru_BY');
    -goog.provide('goog.i18n.NumberFormatSymbols_ru_KG');
    -goog.provide('goog.i18n.NumberFormatSymbols_ru_KZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_ru_MD');
    -goog.provide('goog.i18n.NumberFormatSymbols_ru_UA');
    -goog.provide('goog.i18n.NumberFormatSymbols_rw');
    -goog.provide('goog.i18n.NumberFormatSymbols_rw_RW');
    -goog.provide('goog.i18n.NumberFormatSymbols_rwk');
    -goog.provide('goog.i18n.NumberFormatSymbols_rwk_TZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_sah');
    -goog.provide('goog.i18n.NumberFormatSymbols_sah_RU');
    -goog.provide('goog.i18n.NumberFormatSymbols_saq');
    -goog.provide('goog.i18n.NumberFormatSymbols_saq_KE');
    -goog.provide('goog.i18n.NumberFormatSymbols_sbp');
    -goog.provide('goog.i18n.NumberFormatSymbols_sbp_TZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_se');
    -goog.provide('goog.i18n.NumberFormatSymbols_se_FI');
    -goog.provide('goog.i18n.NumberFormatSymbols_se_NO');
    -goog.provide('goog.i18n.NumberFormatSymbols_se_SE');
    -goog.provide('goog.i18n.NumberFormatSymbols_seh');
    -goog.provide('goog.i18n.NumberFormatSymbols_seh_MZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_ses');
    -goog.provide('goog.i18n.NumberFormatSymbols_ses_ML');
    -goog.provide('goog.i18n.NumberFormatSymbols_sg');
    -goog.provide('goog.i18n.NumberFormatSymbols_sg_CF');
    -goog.provide('goog.i18n.NumberFormatSymbols_shi');
    -goog.provide('goog.i18n.NumberFormatSymbols_shi_Latn');
    -goog.provide('goog.i18n.NumberFormatSymbols_shi_Latn_MA');
    -goog.provide('goog.i18n.NumberFormatSymbols_shi_Tfng');
    -goog.provide('goog.i18n.NumberFormatSymbols_shi_Tfng_MA');
    -goog.provide('goog.i18n.NumberFormatSymbols_smn');
    -goog.provide('goog.i18n.NumberFormatSymbols_smn_FI');
    -goog.provide('goog.i18n.NumberFormatSymbols_sn');
    -goog.provide('goog.i18n.NumberFormatSymbols_sn_ZW');
    -goog.provide('goog.i18n.NumberFormatSymbols_so');
    -goog.provide('goog.i18n.NumberFormatSymbols_so_DJ');
    -goog.provide('goog.i18n.NumberFormatSymbols_so_ET');
    -goog.provide('goog.i18n.NumberFormatSymbols_so_KE');
    -goog.provide('goog.i18n.NumberFormatSymbols_so_SO');
    -goog.provide('goog.i18n.NumberFormatSymbols_sq_MK');
    -goog.provide('goog.i18n.NumberFormatSymbols_sq_XK');
    -goog.provide('goog.i18n.NumberFormatSymbols_sr_Cyrl');
    -goog.provide('goog.i18n.NumberFormatSymbols_sr_Cyrl_BA');
    -goog.provide('goog.i18n.NumberFormatSymbols_sr_Cyrl_ME');
    -goog.provide('goog.i18n.NumberFormatSymbols_sr_Cyrl_XK');
    -goog.provide('goog.i18n.NumberFormatSymbols_sr_Latn');
    -goog.provide('goog.i18n.NumberFormatSymbols_sr_Latn_BA');
    -goog.provide('goog.i18n.NumberFormatSymbols_sr_Latn_ME');
    -goog.provide('goog.i18n.NumberFormatSymbols_sr_Latn_RS');
    -goog.provide('goog.i18n.NumberFormatSymbols_sr_Latn_XK');
    -goog.provide('goog.i18n.NumberFormatSymbols_ss');
    -goog.provide('goog.i18n.NumberFormatSymbols_ss_SZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_ss_ZA');
    -goog.provide('goog.i18n.NumberFormatSymbols_ssy');
    -goog.provide('goog.i18n.NumberFormatSymbols_ssy_ER');
    -goog.provide('goog.i18n.NumberFormatSymbols_sv_AX');
    -goog.provide('goog.i18n.NumberFormatSymbols_sv_FI');
    -goog.provide('goog.i18n.NumberFormatSymbols_sw_KE');
    -goog.provide('goog.i18n.NumberFormatSymbols_sw_UG');
    -goog.provide('goog.i18n.NumberFormatSymbols_swc');
    -goog.provide('goog.i18n.NumberFormatSymbols_swc_CD');
    -goog.provide('goog.i18n.NumberFormatSymbols_ta_LK');
    -goog.provide('goog.i18n.NumberFormatSymbols_ta_MY');
    -goog.provide('goog.i18n.NumberFormatSymbols_ta_SG');
    -goog.provide('goog.i18n.NumberFormatSymbols_teo');
    -goog.provide('goog.i18n.NumberFormatSymbols_teo_KE');
    -goog.provide('goog.i18n.NumberFormatSymbols_teo_UG');
    -goog.provide('goog.i18n.NumberFormatSymbols_ti');
    -goog.provide('goog.i18n.NumberFormatSymbols_ti_ER');
    -goog.provide('goog.i18n.NumberFormatSymbols_ti_ET');
    -goog.provide('goog.i18n.NumberFormatSymbols_tn');
    -goog.provide('goog.i18n.NumberFormatSymbols_tn_BW');
    -goog.provide('goog.i18n.NumberFormatSymbols_tn_ZA');
    -goog.provide('goog.i18n.NumberFormatSymbols_to');
    -goog.provide('goog.i18n.NumberFormatSymbols_to_TO');
    -goog.provide('goog.i18n.NumberFormatSymbols_tr_CY');
    -goog.provide('goog.i18n.NumberFormatSymbols_ts');
    -goog.provide('goog.i18n.NumberFormatSymbols_ts_ZA');
    -goog.provide('goog.i18n.NumberFormatSymbols_twq');
    -goog.provide('goog.i18n.NumberFormatSymbols_twq_NE');
    -goog.provide('goog.i18n.NumberFormatSymbols_tzm');
    -goog.provide('goog.i18n.NumberFormatSymbols_tzm_Latn');
    -goog.provide('goog.i18n.NumberFormatSymbols_tzm_Latn_MA');
    -goog.provide('goog.i18n.NumberFormatSymbols_ug');
    -goog.provide('goog.i18n.NumberFormatSymbols_ug_Arab');
    -goog.provide('goog.i18n.NumberFormatSymbols_ug_Arab_CN');
    -goog.provide('goog.i18n.NumberFormatSymbols_ur_IN');
    -goog.provide('goog.i18n.NumberFormatSymbols_uz_Arab');
    -goog.provide('goog.i18n.NumberFormatSymbols_uz_Arab_AF');
    -goog.provide('goog.i18n.NumberFormatSymbols_uz_Cyrl');
    -goog.provide('goog.i18n.NumberFormatSymbols_uz_Cyrl_UZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_uz_Latn');
    -goog.provide('goog.i18n.NumberFormatSymbols_vai');
    -goog.provide('goog.i18n.NumberFormatSymbols_vai_Latn');
    -goog.provide('goog.i18n.NumberFormatSymbols_vai_Latn_LR');
    -goog.provide('goog.i18n.NumberFormatSymbols_vai_Vaii');
    -goog.provide('goog.i18n.NumberFormatSymbols_vai_Vaii_LR');
    -goog.provide('goog.i18n.NumberFormatSymbols_ve');
    -goog.provide('goog.i18n.NumberFormatSymbols_ve_ZA');
    -goog.provide('goog.i18n.NumberFormatSymbols_vo');
    -goog.provide('goog.i18n.NumberFormatSymbols_vo_001');
    -goog.provide('goog.i18n.NumberFormatSymbols_vun');
    -goog.provide('goog.i18n.NumberFormatSymbols_vun_TZ');
    -goog.provide('goog.i18n.NumberFormatSymbols_wae');
    -goog.provide('goog.i18n.NumberFormatSymbols_wae_CH');
    -goog.provide('goog.i18n.NumberFormatSymbols_xog');
    -goog.provide('goog.i18n.NumberFormatSymbols_xog_UG');
    -goog.provide('goog.i18n.NumberFormatSymbols_yav');
    -goog.provide('goog.i18n.NumberFormatSymbols_yav_CM');
    -goog.provide('goog.i18n.NumberFormatSymbols_yi');
    -goog.provide('goog.i18n.NumberFormatSymbols_yi_001');
    -goog.provide('goog.i18n.NumberFormatSymbols_yo');
    -goog.provide('goog.i18n.NumberFormatSymbols_yo_BJ');
    -goog.provide('goog.i18n.NumberFormatSymbols_yo_NG');
    -goog.provide('goog.i18n.NumberFormatSymbols_zgh');
    -goog.provide('goog.i18n.NumberFormatSymbols_zgh_MA');
    -goog.provide('goog.i18n.NumberFormatSymbols_zh_Hans');
    -goog.provide('goog.i18n.NumberFormatSymbols_zh_Hans_HK');
    -goog.provide('goog.i18n.NumberFormatSymbols_zh_Hans_MO');
    -goog.provide('goog.i18n.NumberFormatSymbols_zh_Hans_SG');
    -goog.provide('goog.i18n.NumberFormatSymbols_zh_Hant');
    -goog.provide('goog.i18n.NumberFormatSymbols_zh_Hant_HK');
    -goog.provide('goog.i18n.NumberFormatSymbols_zh_Hant_MO');
    -goog.provide('goog.i18n.NumberFormatSymbols_zh_Hant_TW');
    -
    -goog.require('goog.i18n.NumberFormatSymbols');
    -
    -
    -/**
    - * Number formatting symbols for locale aa.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_aa = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'ETB'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale aa_DJ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_aa_DJ = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'DJF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale aa_ER.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_aa_ER = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'ERN'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale aa_ET.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_aa_ET = goog.i18n.NumberFormatSymbols_aa;
    -
    -
    -/**
    - * Number formatting symbols for locale af_NA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_af_NA = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'NAD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale agq.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_agq = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A4',
    -  DEF_CURRENCY_CODE: 'XAF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale agq_CM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_agq_CM = goog.i18n.NumberFormatSymbols_agq;
    -
    -
    -/**
    - * Number formatting symbols for locale ak.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ak = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'GHS'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ak_GH.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ak_GH = goog.i18n.NumberFormatSymbols_ak;
    -
    -
    -/**
    - * Number formatting symbols for locale ar_AE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ar_AE = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u0660',
    -  PLUS_SIGN: '\u200F+',
    -  MINUS_SIGN: '\u200F-',
    -  EXP_SYMBOL: '\u0627\u0633',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: '\u0644\u064A\u0633\u00A0\u0631\u0642\u0645',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'AED'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ar_BH.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ar_BH = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u0660',
    -  PLUS_SIGN: '\u200F+',
    -  MINUS_SIGN: '\u200F-',
    -  EXP_SYMBOL: '\u0627\u0633',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: '\u0644\u064A\u0633\u00A0\u0631\u0642\u0645',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'BHD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ar_DJ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ar_DJ = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u0660',
    -  PLUS_SIGN: '\u200F+',
    -  MINUS_SIGN: '\u200F-',
    -  EXP_SYMBOL: '\u0627\u0633',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: '\u0644\u064A\u0633\u00A0\u0631\u0642\u0645',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'DJF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ar_DZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ar_DZ = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '\u200E+',
    -  MINUS_SIGN: '\u200E-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'DZD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ar_EG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ar_EG = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u0660',
    -  PLUS_SIGN: '\u200F+',
    -  MINUS_SIGN: '\u200F-',
    -  EXP_SYMBOL: '\u0627\u0633',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'EGP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ar_EH.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ar_EH = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '\u200E+',
    -  MINUS_SIGN: '\u200E-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'MAD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ar_ER.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ar_ER = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u0660',
    -  PLUS_SIGN: '\u200F+',
    -  MINUS_SIGN: '\u200F-',
    -  EXP_SYMBOL: '\u0627\u0633',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: '\u0644\u064A\u0633\u00A0\u0631\u0642\u0645',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'ERN'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ar_IL.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ar_IL = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u0660',
    -  PLUS_SIGN: '\u200F+',
    -  MINUS_SIGN: '\u200F-',
    -  EXP_SYMBOL: '\u0627\u0633',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: '\u0644\u064A\u0633\u00A0\u0631\u0642\u0645',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'ILS'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ar_IQ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ar_IQ = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u0660',
    -  PLUS_SIGN: '\u200F+',
    -  MINUS_SIGN: '\u200F-',
    -  EXP_SYMBOL: '\u0627\u0633',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: '\u0644\u064A\u0633\u00A0\u0631\u0642\u0645',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'IQD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ar_JO.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ar_JO = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u0660',
    -  PLUS_SIGN: '\u200F+',
    -  MINUS_SIGN: '\u200F-',
    -  EXP_SYMBOL: '\u0627\u0633',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: '\u0644\u064A\u0633\u00A0\u0631\u0642\u0645',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'JOD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ar_KM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ar_KM = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u0660',
    -  PLUS_SIGN: '\u200F+',
    -  MINUS_SIGN: '\u200F-',
    -  EXP_SYMBOL: '\u0627\u0633',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: '\u0644\u064A\u0633\u00A0\u0631\u0642\u0645',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'KMF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ar_KW.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ar_KW = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u0660',
    -  PLUS_SIGN: '\u200F+',
    -  MINUS_SIGN: '\u200F-',
    -  EXP_SYMBOL: '\u0627\u0633',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: '\u0644\u064A\u0633\u00A0\u0631\u0642\u0645',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'KWD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ar_LB.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ar_LB = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u0660',
    -  PLUS_SIGN: '\u200F+',
    -  MINUS_SIGN: '\u200F-',
    -  EXP_SYMBOL: '\u0627\u0633',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: '\u0644\u064A\u0633\u00A0\u0631\u0642\u0645',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'LBP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ar_LY.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ar_LY = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '\u200E+',
    -  MINUS_SIGN: '\u200E-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'LYD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ar_MA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ar_MA = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '\u200E+',
    -  MINUS_SIGN: '\u200E-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'MAD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ar_MR.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ar_MR = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u0660',
    -  PLUS_SIGN: '\u200F+',
    -  MINUS_SIGN: '\u200F-',
    -  EXP_SYMBOL: '\u0627\u0633',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: '\u0644\u064A\u0633\u00A0\u0631\u0642\u0645',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'MRO'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ar_OM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ar_OM = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u0660',
    -  PLUS_SIGN: '\u200F+',
    -  MINUS_SIGN: '\u200F-',
    -  EXP_SYMBOL: '\u0627\u0633',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: '\u0644\u064A\u0633\u00A0\u0631\u0642\u0645',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'OMR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ar_PS.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ar_PS = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u0660',
    -  PLUS_SIGN: '\u200F+',
    -  MINUS_SIGN: '\u200F-',
    -  EXP_SYMBOL: '\u0627\u0633',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: '\u0644\u064A\u0633\u00A0\u0631\u0642\u0645',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'ILS'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ar_QA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ar_QA = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u0660',
    -  PLUS_SIGN: '\u200F+',
    -  MINUS_SIGN: '\u200F-',
    -  EXP_SYMBOL: '\u0627\u0633',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: '\u0644\u064A\u0633\u00A0\u0631\u0642\u0645',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#0.00',
    -  DEF_CURRENCY_CODE: 'QAR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ar_SA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ar_SA = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u0660',
    -  PLUS_SIGN: '\u200F+',
    -  MINUS_SIGN: '\u200F-',
    -  EXP_SYMBOL: '\u0627\u0633',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: '\u0644\u064A\u0633\u00A0\u0631\u0642\u0645',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#0.00',
    -  DEF_CURRENCY_CODE: 'SAR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ar_SD.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ar_SD = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u0660',
    -  PLUS_SIGN: '\u200F+',
    -  MINUS_SIGN: '\u200F-',
    -  EXP_SYMBOL: '\u0627\u0633',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: '\u0644\u064A\u0633\u00A0\u0631\u0642\u0645',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'SDG'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ar_SO.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ar_SO = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u0660',
    -  PLUS_SIGN: '\u200F+',
    -  MINUS_SIGN: '\u200F-',
    -  EXP_SYMBOL: '\u0627\u0633',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: '\u0644\u064A\u0633\u00A0\u0631\u0642\u0645',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'SOS'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ar_SS.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ar_SS = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u0660',
    -  PLUS_SIGN: '\u200F+',
    -  MINUS_SIGN: '\u200F-',
    -  EXP_SYMBOL: '\u0627\u0633',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: '\u0644\u064A\u0633\u00A0\u0631\u0642\u0645',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'SSP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ar_SY.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ar_SY = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u0660',
    -  PLUS_SIGN: '\u200F+',
    -  MINUS_SIGN: '\u200F-',
    -  EXP_SYMBOL: '\u0627\u0633',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: '\u0644\u064A\u0633\u00A0\u0631\u0642\u0645',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#0.00',
    -  DEF_CURRENCY_CODE: 'SYP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ar_TD.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ar_TD = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u0660',
    -  PLUS_SIGN: '\u200F+',
    -  MINUS_SIGN: '\u200F-',
    -  EXP_SYMBOL: '\u0627\u0633',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: '\u0644\u064A\u0633\u00A0\u0631\u0642\u0645',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'XAF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ar_TN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ar_TN = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '\u200E+',
    -  MINUS_SIGN: '\u200E-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#0.00',
    -  DEF_CURRENCY_CODE: 'TND'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ar_YE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ar_YE = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u0660',
    -  PLUS_SIGN: '\u200F+',
    -  MINUS_SIGN: '\u200F-',
    -  EXP_SYMBOL: '\u0627\u0633',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: '\u0644\u064A\u0633\u00A0\u0631\u0642\u0645',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#0.00',
    -  DEF_CURRENCY_CODE: 'YER'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale as.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_as = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '\u09E6',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##,##0.00',
    -  DEF_CURRENCY_CODE: 'INR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale as_IN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_as_IN = goog.i18n.NumberFormatSymbols_as;
    -
    -
    -/**
    - * Number formatting symbols for locale asa.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_asa = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'TZS'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale asa_TZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_asa_TZ = goog.i18n.NumberFormatSymbols_asa;
    -
    -
    -/**
    - * Number formatting symbols for locale ast.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ast = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ast_ES.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ast_ES = goog.i18n.NumberFormatSymbols_ast;
    -
    -
    -/**
    - * Number formatting symbols for locale az_Cyrl.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_az_Cyrl = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale az_Cyrl_AZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_az_Cyrl_AZ = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'AZN'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale az_Latn.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_az_Latn = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale bas.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_bas = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'XAF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale bas_CM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_bas_CM = goog.i18n.NumberFormatSymbols_bas;
    -
    -
    -/**
    - * Number formatting symbols for locale be.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_be = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'BYR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale be_BY.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_be_BY = goog.i18n.NumberFormatSymbols_be;
    -
    -
    -/**
    - * Number formatting symbols for locale bem.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_bem = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'ZMW'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale bem_ZM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_bem_ZM = goog.i18n.NumberFormatSymbols_bem;
    -
    -
    -/**
    - * Number formatting symbols for locale bez.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_bez = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A4',
    -  DEF_CURRENCY_CODE: 'TZS'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale bez_TZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_bez_TZ = goog.i18n.NumberFormatSymbols_bez;
    -
    -
    -/**
    - * Number formatting symbols for locale bm.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_bm = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'XOF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale bm_Latn.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_bm_Latn = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale bm_Latn_ML.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_bm_Latn_ML = goog.i18n.NumberFormatSymbols_bm;
    -
    -
    -/**
    - * Number formatting symbols for locale bn_IN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_bn_IN = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '\u09E6',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: '\u09B8\u0982\u0996\u09CD\u09AF\u09BE\u00A0\u09A8\u09BE',
    -  DECIMAL_PATTERN: '#,##,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##,##0%',
    -  CURRENCY_PATTERN: '#,##,##0.00\u00A4',
    -  DEF_CURRENCY_CODE: 'INR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale bo.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_bo = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'CNY'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale bo_CN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_bo_CN = goog.i18n.NumberFormatSymbols_bo;
    -
    -
    -/**
    - * Number formatting symbols for locale bo_IN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_bo_IN = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'INR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale brx.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_brx = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##,##0.00',
    -  DEF_CURRENCY_CODE: 'INR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale brx_IN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_brx_IN = goog.i18n.NumberFormatSymbols_brx;
    -
    -
    -/**
    - * Number formatting symbols for locale bs.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_bs = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'BAM'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale bs_Cyrl.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_bs_Cyrl = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale bs_Cyrl_BA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_bs_Cyrl_BA = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'BAM'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale bs_Latn.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_bs_Latn = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale bs_Latn_BA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_bs_Latn_BA = goog.i18n.NumberFormatSymbols_bs;
    -
    -
    -/**
    - * Number formatting symbols for locale cgg.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_cgg = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'UGX'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale cgg_UG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_cgg_UG = goog.i18n.NumberFormatSymbols_cgg;
    -
    -
    -/**
    - * Number formatting symbols for locale ckb.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ckb = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u0660',
    -  PLUS_SIGN: '\u200F+',
    -  MINUS_SIGN: '\u200F-',
    -  EXP_SYMBOL: '\u0627\u0633',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'IQD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ckb_Arab.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ckb_Arab = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u0660',
    -  PLUS_SIGN: '\u200F+',
    -  MINUS_SIGN: '\u200F-',
    -  EXP_SYMBOL: '\u0627\u0633',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ckb_Arab_IQ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ckb_Arab_IQ = goog.i18n.NumberFormatSymbols_ckb;
    -
    -
    -/**
    - * Number formatting symbols for locale ckb_Arab_IR.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ckb_Arab_IR = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u0660',
    -  PLUS_SIGN: '\u200F+',
    -  MINUS_SIGN: '\u200F-',
    -  EXP_SYMBOL: '\u0627\u0633',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'IRR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ckb_IQ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ckb_IQ = goog.i18n.NumberFormatSymbols_ckb;
    -
    -
    -/**
    - * Number formatting symbols for locale ckb_IR.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ckb_IR = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u0660',
    -  PLUS_SIGN: '\u200F+',
    -  MINUS_SIGN: '\u200F-',
    -  EXP_SYMBOL: '\u0627\u0633',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'IRR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ckb_Latn.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ckb_Latn = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u0660',
    -  PLUS_SIGN: '\u200F+',
    -  MINUS_SIGN: '\u200F-',
    -  EXP_SYMBOL: '\u0627\u0633',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ckb_Latn_IQ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ckb_Latn_IQ = goog.i18n.NumberFormatSymbols_ckb;
    -
    -
    -/**
    - * Number formatting symbols for locale dav.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_dav = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'KES'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale dav_KE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_dav_KE = goog.i18n.NumberFormatSymbols_dav;
    -
    -
    -/**
    - * Number formatting symbols for locale de_LI.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_de_LI = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: '\'',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'CHF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale dje.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_dje = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A4',
    -  DEF_CURRENCY_CODE: 'XOF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale dje_NE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_dje_NE = goog.i18n.NumberFormatSymbols_dje;
    -
    -
    -/**
    - * Number formatting symbols for locale dsb.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_dsb = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale dsb_DE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_dsb_DE = goog.i18n.NumberFormatSymbols_dsb;
    -
    -
    -/**
    - * Number formatting symbols for locale dua.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_dua = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'XAF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale dua_CM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_dua_CM = goog.i18n.NumberFormatSymbols_dua;
    -
    -
    -/**
    - * Number formatting symbols for locale dyo.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_dyo = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'XOF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale dyo_SN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_dyo_SN = goog.i18n.NumberFormatSymbols_dyo;
    -
    -
    -/**
    - * Number formatting symbols for locale dz.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_dz = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '\u0F20',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u0F42\u0FB2\u0F44\u0F66\u0F0B\u0F58\u0F7A\u0F51',
    -  NAN: '\u0F68\u0F44\u0F0B\u0F58\u0F51',
    -  DECIMAL_PATTERN: '#,##,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4#,##,##0.00',
    -  DEF_CURRENCY_CODE: 'BTN'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale dz_BT.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_dz_BT = goog.i18n.NumberFormatSymbols_dz;
    -
    -
    -/**
    - * Number formatting symbols for locale ebu.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ebu = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'KES'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ebu_KE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ebu_KE = goog.i18n.NumberFormatSymbols_ebu;
    -
    -
    -/**
    - * Number formatting symbols for locale ee.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ee = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'mnn',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'GHS'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ee_GH.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ee_GH = goog.i18n.NumberFormatSymbols_ee;
    -
    -
    -/**
    - * Number formatting symbols for locale ee_TG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ee_TG = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'mnn',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'XOF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale el_CY.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_el_CY = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'e',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_150.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_150 = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'USD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_AG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_AG = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'XCD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_AI.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_AI = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'XCD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_BB.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_BB = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'BBD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_BE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_BE = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_BM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_BM = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'BMD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_BS.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_BS = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'BSD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_BW.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_BW = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'BWP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_BZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_BZ = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'BZD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_CA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_CA = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'CAD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_CC.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_CC = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'AUD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_CK.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_CK = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'NZD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_CM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_CM = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'XAF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_CX.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_CX = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'AUD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_DM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_DM = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'XCD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_ER.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_ER = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'ERN'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_FJ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_FJ = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'FJD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_FK.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_FK = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'FKP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_GD.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_GD = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'XCD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_GG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_GG = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'GBP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_GH.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_GH = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'GHS'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_GI.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_GI = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'GIP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_GM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_GM = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'GMD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_GY.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_GY = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'GYD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_HK.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_HK = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'HKD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_IM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_IM = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'GBP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_JE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_JE = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'GBP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_JM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_JM = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'JMD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_KE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_KE = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'KES'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_KI.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_KI = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'AUD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_KN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_KN = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'XCD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_KY.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_KY = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'KYD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_LC.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_LC = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'XCD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_LR.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_LR = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'LRD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_LS.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_LS = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'ZAR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_MG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_MG = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'MGA'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_MO.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_MO = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'MOP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_MS.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_MS = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'XCD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_MT.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_MT = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_MU.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_MU = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'MUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_MW.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_MW = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'MWK'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_MY.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_MY = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'MYR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_NA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_NA = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'NAD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_NF.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_NF = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'AUD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_NG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_NG = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'NGN'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_NR.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_NR = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'AUD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_NU.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_NU = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'NZD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_NZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_NZ = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'NZD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_PG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_PG = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'PGK'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_PH.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_PH = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'PHP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_PK.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_PK = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##,##0.00',
    -  DEF_CURRENCY_CODE: 'PKR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_PN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_PN = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'NZD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_RW.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_RW = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'RWF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_SB.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_SB = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'SBD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_SC.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_SC = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'SCR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_SD.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_SD = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'SDG'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_SH.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_SH = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'SHP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_SL.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_SL = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'SLL'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_SS.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_SS = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'SSP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_SX.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_SX = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'ANG'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_SZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_SZ = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'SZL'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_TK.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_TK = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'NZD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_TO.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_TO = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'TOP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_TT.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_TT = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'TTD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_TV.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_TV = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'AUD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_TZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_TZ = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'TZS'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_UG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_UG = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'UGX'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_VC.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_VC = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'XCD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_VU.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_VU = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'VUV'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_WS.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_WS = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'WST'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale en_ZM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_en_ZM = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'ZMW'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale eo.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_eo = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '\u2212',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'USD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale eo_001.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_eo_001 = goog.i18n.NumberFormatSymbols_eo;
    -
    -
    -/**
    - * Number formatting symbols for locale es_AR.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_es_AR = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'ARS'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale es_BO.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_es_BO = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'BOB'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale es_CL.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_es_CL = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00;\u00A4-#,##0.00',
    -  DEF_CURRENCY_CODE: 'CLP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale es_CO.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_es_CO = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'COP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale es_CR.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_es_CR = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'CRC'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale es_CU.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_es_CU = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'CUP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale es_DO.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_es_DO = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'DOP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale es_EC.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_es_EC = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00;\u00A4-#,##0.00',
    -  DEF_CURRENCY_CODE: 'USD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale es_GQ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_es_GQ = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'XAF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale es_GT.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_es_GT = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'GTQ'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale es_HN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_es_HN = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'HNL'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale es_MX.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_es_MX = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'MXN'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale es_NI.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_es_NI = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'NIO'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale es_PA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_es_PA = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'PAB'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale es_PE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_es_PE = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'PEN'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale es_PH.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_es_PH = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'PHP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale es_PR.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_es_PR = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'USD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale es_PY.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_es_PY = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00;\u00A4\u00A0-#,##0.00',
    -  DEF_CURRENCY_CODE: 'PYG'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale es_SV.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_es_SV = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'USD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale es_US.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_es_US = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'USD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale es_UY.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_es_UY = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'UYU'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale es_VE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_es_VE = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00;\u00A4-#,##0.00',
    -  DEF_CURRENCY_CODE: 'VEF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ewo.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ewo = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'XAF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ewo_CM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ewo_CM = goog.i18n.NumberFormatSymbols_ewo;
    -
    -
    -/**
    - * Number formatting symbols for locale fa_AF.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fa_AF = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u06F0',
    -  PLUS_SIGN: '\u200E+\u200E',
    -  MINUS_SIGN: '\u200E\u2212',
    -  EXP_SYMBOL: '\u00D7\u06F1\u06F0^',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: '\u0646\u0627\u0639\u062F\u062F',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '\'\u202A\'#,##0%\'\u202C\'',
    -  CURRENCY_PATTERN: '\u200E\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'AFN'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ff.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ff = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'XOF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ff_CM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ff_CM = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'XAF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ff_GN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ff_GN = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'GNF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ff_MR.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ff_MR = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'MRO'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ff_SN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ff_SN = goog.i18n.NumberFormatSymbols_ff;
    -
    -
    -/**
    - * Number formatting symbols for locale fo.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fo = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '\u2212',
    -  EXP_SYMBOL: '\u00D710^',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: '\u00A4\u00A4\u00A4',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00;\u00A4-#,##0.00',
    -  DEF_CURRENCY_CODE: 'DKK'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fo_FO.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fo_FO = goog.i18n.NumberFormatSymbols_fo;
    -
    -
    -/**
    - * Number formatting symbols for locale fr_BE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_BE = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_BF.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_BF = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'XOF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_BI.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_BI = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'BIF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_BJ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_BJ = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'XOF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_CD.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_CD = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'CDF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_CF.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_CF = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'XAF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_CG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_CG = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'XAF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_CH.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_CH = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00;\u00A4-#,##0.00',
    -  DEF_CURRENCY_CODE: 'CHF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_CI.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_CI = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'XOF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_CM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_CM = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'XAF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_DJ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_DJ = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'DJF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_DZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_DZ = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'DZD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_GA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_GA = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'XAF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_GN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_GN = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'GNF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_GQ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_GQ = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'XAF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_HT.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_HT = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'HTG'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_KM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_KM = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'KMF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_LU.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_LU = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_MA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_MA = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'MAD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_MG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_MG = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'MGA'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_ML.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_ML = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'XOF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_MR.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_MR = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'MRO'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_MU.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_MU = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'MUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_NC.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_NC = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'XPF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_NE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_NE = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'XOF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_PF.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_PF = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'XPF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_RW.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_RW = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'RWF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_SC.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_SC = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'SCR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_SN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_SN = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'XOF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_SY.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_SY = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'SYP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_TD.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_TD = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'XAF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_TG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_TG = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'XOF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_TN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_TN = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'TND'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_VU.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_VU = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'VUV'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fr_WF.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fr_WF = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'XPF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fur.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fur = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fur_IT.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fur_IT = goog.i18n.NumberFormatSymbols_fur;
    -
    -
    -/**
    - * Number formatting symbols for locale fy.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fy = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00;\u00A4\u00A0#,##0.00-',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale fy_NL.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_fy_NL = goog.i18n.NumberFormatSymbols_fy;
    -
    -
    -/**
    - * Number formatting symbols for locale gd.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_gd = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'GBP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale gd_GB.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_gd_GB = goog.i18n.NumberFormatSymbols_gd;
    -
    -
    -/**
    - * Number formatting symbols for locale gsw_FR.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_gsw_FR = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: '\u2019',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '\u2212',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale guz.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_guz = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'KES'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale guz_KE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_guz_KE = goog.i18n.NumberFormatSymbols_guz;
    -
    -
    -/**
    - * Number formatting symbols for locale gv.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_gv = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'GBP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale gv_IM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_gv_IM = goog.i18n.NumberFormatSymbols_gv;
    -
    -
    -/**
    - * Number formatting symbols for locale ha.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ha = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'NGN'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ha_Latn.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ha_Latn = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ha_Latn_GH.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ha_Latn_GH = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'GHS'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ha_Latn_NE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ha_Latn_NE = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'XOF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ha_Latn_NG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ha_Latn_NG = goog.i18n.NumberFormatSymbols_ha;
    -
    -
    -/**
    - * Number formatting symbols for locale hr_BA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_hr_BA = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'BAM'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale hsb.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_hsb = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale hsb_DE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_hsb_DE = goog.i18n.NumberFormatSymbols_hsb;
    -
    -
    -/**
    - * Number formatting symbols for locale ia.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ia = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ia_FR.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ia_FR = goog.i18n.NumberFormatSymbols_ia;
    -
    -
    -/**
    - * Number formatting symbols for locale ig.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ig = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'NGN'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ig_NG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ig_NG = goog.i18n.NumberFormatSymbols_ig;
    -
    -
    -/**
    - * Number formatting symbols for locale ii.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ii = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'CNY'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ii_CN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ii_CN = goog.i18n.NumberFormatSymbols_ii;
    -
    -
    -/**
    - * Number formatting symbols for locale it_CH.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_it_CH = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: '\'',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00;\u00A4-#,##0.00',
    -  DEF_CURRENCY_CODE: 'CHF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale jgo.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_jgo = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'XAF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale jgo_CM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_jgo_CM = goog.i18n.NumberFormatSymbols_jgo;
    -
    -
    -/**
    - * Number formatting symbols for locale jmc.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_jmc = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'TZS'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale jmc_TZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_jmc_TZ = goog.i18n.NumberFormatSymbols_jmc;
    -
    -
    -/**
    - * Number formatting symbols for locale kab.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_kab = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A4',
    -  DEF_CURRENCY_CODE: 'DZD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale kab_DZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_kab_DZ = goog.i18n.NumberFormatSymbols_kab;
    -
    -
    -/**
    - * Number formatting symbols for locale kam.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_kam = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'KES'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale kam_KE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_kam_KE = goog.i18n.NumberFormatSymbols_kam;
    -
    -
    -/**
    - * Number formatting symbols for locale kde.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_kde = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'TZS'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale kde_TZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_kde_TZ = goog.i18n.NumberFormatSymbols_kde;
    -
    -
    -/**
    - * Number formatting symbols for locale kea.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_kea = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'CVE'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale kea_CV.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_kea_CV = goog.i18n.NumberFormatSymbols_kea;
    -
    -
    -/**
    - * Number formatting symbols for locale khq.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_khq = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A4',
    -  DEF_CURRENCY_CODE: 'XOF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale khq_ML.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_khq_ML = goog.i18n.NumberFormatSymbols_khq;
    -
    -
    -/**
    - * Number formatting symbols for locale ki.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ki = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'KES'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ki_KE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ki_KE = goog.i18n.NumberFormatSymbols_ki;
    -
    -
    -/**
    - * Number formatting symbols for locale kk_Cyrl.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_kk_Cyrl = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale kkj.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_kkj = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'XAF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale kkj_CM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_kkj_CM = goog.i18n.NumberFormatSymbols_kkj;
    -
    -
    -/**
    - * Number formatting symbols for locale kl.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_kl = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '\u2212',
    -  EXP_SYMBOL: '\u00D710^',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: '\u00A4\u00A4\u00A4',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00;\u00A4-#,##0.00',
    -  DEF_CURRENCY_CODE: 'DKK'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale kl_GL.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_kl_GL = goog.i18n.NumberFormatSymbols_kl;
    -
    -
    -/**
    - * Number formatting symbols for locale kln.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_kln = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'KES'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale kln_KE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_kln_KE = goog.i18n.NumberFormatSymbols_kln;
    -
    -
    -/**
    - * Number formatting symbols for locale ko_KP.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ko_KP = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'KPW'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale kok.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_kok = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##,##0.00',
    -  DEF_CURRENCY_CODE: 'INR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale kok_IN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_kok_IN = goog.i18n.NumberFormatSymbols_kok;
    -
    -
    -/**
    - * Number formatting symbols for locale ks.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ks = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u06F0',
    -  PLUS_SIGN: '\u200E+\u200E',
    -  MINUS_SIGN: '\u200E-\u200E',
    -  EXP_SYMBOL: '\u00D7\u06F1\u06F0^',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##,##0.00',
    -  DEF_CURRENCY_CODE: 'INR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ks_Arab.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ks_Arab = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u06F0',
    -  PLUS_SIGN: '\u200E+\u200E',
    -  MINUS_SIGN: '\u200E-\u200E',
    -  EXP_SYMBOL: '\u00D7\u06F1\u06F0^',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##,##0.00',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ks_Arab_IN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ks_Arab_IN = goog.i18n.NumberFormatSymbols_ks;
    -
    -
    -/**
    - * Number formatting symbols for locale ksb.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ksb = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A4',
    -  DEF_CURRENCY_CODE: 'TZS'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ksb_TZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ksb_TZ = goog.i18n.NumberFormatSymbols_ksb;
    -
    -
    -/**
    - * Number formatting symbols for locale ksf.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ksf = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'XAF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ksf_CM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ksf_CM = goog.i18n.NumberFormatSymbols_ksf;
    -
    -
    -/**
    - * Number formatting symbols for locale ksh.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ksh = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '\u2212',
    -  EXP_SYMBOL: '\u00D710^',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: '\u00A4\u00A4\u00A4',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ksh_DE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ksh_DE = goog.i18n.NumberFormatSymbols_ksh;
    -
    -
    -/**
    - * Number formatting symbols for locale kw.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_kw = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'GBP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale kw_GB.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_kw_GB = goog.i18n.NumberFormatSymbols_kw;
    -
    -
    -/**
    - * Number formatting symbols for locale ky_Cyrl.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ky_Cyrl = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: '\u0441\u0430\u043D\u00A0\u044D\u043C\u0435\u0441',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale lag.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_lag = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'TZS'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale lag_TZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_lag_TZ = goog.i18n.NumberFormatSymbols_lag;
    -
    -
    -/**
    - * Number formatting symbols for locale lb.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_lb = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale lb_LU.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_lb_LU = goog.i18n.NumberFormatSymbols_lb;
    -
    -
    -/**
    - * Number formatting symbols for locale lg.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_lg = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A4',
    -  DEF_CURRENCY_CODE: 'UGX'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale lg_UG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_lg_UG = goog.i18n.NumberFormatSymbols_lg;
    -
    -
    -/**
    - * Number formatting symbols for locale lkt.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_lkt = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'USD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale lkt_US.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_lkt_US = goog.i18n.NumberFormatSymbols_lkt;
    -
    -
    -/**
    - * Number formatting symbols for locale ln_AO.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ln_AO = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'AOA'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ln_CF.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ln_CF = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'XAF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ln_CG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ln_CG = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'XAF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale lu.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_lu = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A4',
    -  DEF_CURRENCY_CODE: 'CDF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale lu_CD.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_lu_CD = goog.i18n.NumberFormatSymbols_lu;
    -
    -
    -/**
    - * Number formatting symbols for locale luo.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_luo = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A4',
    -  DEF_CURRENCY_CODE: 'KES'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale luo_KE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_luo_KE = goog.i18n.NumberFormatSymbols_luo;
    -
    -
    -/**
    - * Number formatting symbols for locale luy.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_luy = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00;\u00A4-\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'KES'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale luy_KE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_luy_KE = goog.i18n.NumberFormatSymbols_luy;
    -
    -
    -/**
    - * Number formatting symbols for locale mas.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_mas = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'KES'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale mas_KE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_mas_KE = goog.i18n.NumberFormatSymbols_mas;
    -
    -
    -/**
    - * Number formatting symbols for locale mas_TZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_mas_TZ = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'TZS'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale mer.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_mer = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'KES'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale mer_KE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_mer_KE = goog.i18n.NumberFormatSymbols_mer;
    -
    -
    -/**
    - * Number formatting symbols for locale mfe.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_mfe = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'MUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale mfe_MU.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_mfe_MU = goog.i18n.NumberFormatSymbols_mfe;
    -
    -
    -/**
    - * Number formatting symbols for locale mg.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_mg = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'MGA'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale mg_MG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_mg_MG = goog.i18n.NumberFormatSymbols_mg;
    -
    -
    -/**
    - * Number formatting symbols for locale mgh.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_mgh = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'MZN'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale mgh_MZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_mgh_MZ = goog.i18n.NumberFormatSymbols_mgh;
    -
    -
    -/**
    - * Number formatting symbols for locale mgo.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_mgo = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'XAF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale mgo_CM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_mgo_CM = goog.i18n.NumberFormatSymbols_mgo;
    -
    -
    -/**
    - * Number formatting symbols for locale mn_Cyrl.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_mn_Cyrl = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ms_Latn.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ms_Latn = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ms_Latn_BN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ms_Latn_BN = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'BND'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ms_Latn_SG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ms_Latn_SG = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'SGD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale mua.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_mua = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'XAF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale mua_CM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_mua_CM = goog.i18n.NumberFormatSymbols_mua;
    -
    -
    -/**
    - * Number formatting symbols for locale naq.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_naq = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'NAD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale naq_NA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_naq_NA = goog.i18n.NumberFormatSymbols_naq;
    -
    -
    -/**
    - * Number formatting symbols for locale nd.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_nd = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'USD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale nd_ZW.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_nd_ZW = goog.i18n.NumberFormatSymbols_nd;
    -
    -
    -/**
    - * Number formatting symbols for locale ne_IN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ne_IN = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '\u0966',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'INR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale nl_AW.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_nl_AW = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00;\u00A4\u00A0#,##0.00-',
    -  DEF_CURRENCY_CODE: 'AWG'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale nl_BE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_nl_BE = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale nl_BQ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_nl_BQ = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00;\u00A4\u00A0#,##0.00-',
    -  DEF_CURRENCY_CODE: 'USD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale nl_CW.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_nl_CW = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00;\u00A4\u00A0#,##0.00-',
    -  DEF_CURRENCY_CODE: 'ANG'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale nl_SR.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_nl_SR = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00;\u00A4\u00A0#,##0.00-',
    -  DEF_CURRENCY_CODE: 'SRD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale nl_SX.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_nl_SX = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00;\u00A4\u00A0#,##0.00-',
    -  DEF_CURRENCY_CODE: 'ANG'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale nmg.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_nmg = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'XAF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale nmg_CM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_nmg_CM = goog.i18n.NumberFormatSymbols_nmg;
    -
    -
    -/**
    - * Number formatting symbols for locale nn.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_nn = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '\u2212',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'NOK'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale nn_NO.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_nn_NO = goog.i18n.NumberFormatSymbols_nn;
    -
    -
    -/**
    - * Number formatting symbols for locale nnh.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_nnh = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'XAF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale nnh_CM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_nnh_CM = goog.i18n.NumberFormatSymbols_nnh;
    -
    -
    -/**
    - * Number formatting symbols for locale nr.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_nr = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'ZAR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale nr_ZA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_nr_ZA = goog.i18n.NumberFormatSymbols_nr;
    -
    -
    -/**
    - * Number formatting symbols for locale nso.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_nso = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'ZAR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale nso_ZA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_nso_ZA = goog.i18n.NumberFormatSymbols_nso;
    -
    -
    -/**
    - * Number formatting symbols for locale nus.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_nus = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'SDG'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale nus_SD.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_nus_SD = goog.i18n.NumberFormatSymbols_nus;
    -
    -
    -/**
    - * Number formatting symbols for locale nyn.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_nyn = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'UGX'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale nyn_UG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_nyn_UG = goog.i18n.NumberFormatSymbols_nyn;
    -
    -
    -/**
    - * Number formatting symbols for locale om.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_om = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'ETB'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale om_ET.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_om_ET = goog.i18n.NumberFormatSymbols_om;
    -
    -
    -/**
    - * Number formatting symbols for locale om_KE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_om_KE = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'KES'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale os.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_os = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: '\u041D\u041D',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'GEL'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale os_GE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_os_GE = goog.i18n.NumberFormatSymbols_os;
    -
    -
    -/**
    - * Number formatting symbols for locale os_RU.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_os_RU = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: '\u041D\u041D',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'RUB'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale pa_Arab.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_pa_Arab = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u06F0',
    -  PLUS_SIGN: '\u200E+\u200E',
    -  MINUS_SIGN: '\u200E-\u200E',
    -  EXP_SYMBOL: '\u00D7\u06F1\u06F0^',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'PKR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale pa_Arab_PK.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_pa_Arab_PK =
    -    goog.i18n.NumberFormatSymbols_pa_Arab;
    -
    -
    -/**
    - * Number formatting symbols for locale pa_Guru.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_pa_Guru = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##,##0.###',
    -  SCIENTIFIC_PATTERN: '[#E0]',
    -  PERCENT_PATTERN: '#,##,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##,##0.00',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ps.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ps = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u06F0',
    -  PLUS_SIGN: '\u200E+\u200E',
    -  MINUS_SIGN: '\u200E-\u200E',
    -  EXP_SYMBOL: '\u00D7\u06F1\u06F0^',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'AFN'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ps_AF.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ps_AF = goog.i18n.NumberFormatSymbols_ps;
    -
    -
    -/**
    - * Number formatting symbols for locale pt_AO.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_pt_AO = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'AOA'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale pt_CV.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_pt_CV = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'CVE'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale pt_GW.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_pt_GW = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'XOF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale pt_MO.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_pt_MO = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'MOP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale pt_MZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_pt_MZ = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'MZN'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale pt_ST.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_pt_ST = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'STD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale pt_TL.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_pt_TL = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'USD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale qu.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_qu = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'PEN'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale qu_BO.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_qu_BO = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'BOB'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale qu_EC.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_qu_EC = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'USD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale qu_PE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_qu_PE = goog.i18n.NumberFormatSymbols_qu;
    -
    -
    -/**
    - * Number formatting symbols for locale rm.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_rm = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: '\u2019',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '\u2212',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'CHF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale rm_CH.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_rm_CH = goog.i18n.NumberFormatSymbols_rm;
    -
    -
    -/**
    - * Number formatting symbols for locale rn.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_rn = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A4',
    -  DEF_CURRENCY_CODE: 'BIF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale rn_BI.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_rn_BI = goog.i18n.NumberFormatSymbols_rn;
    -
    -
    -/**
    - * Number formatting symbols for locale ro_MD.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ro_MD = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'MDL'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale rof.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_rof = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'TZS'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale rof_TZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_rof_TZ = goog.i18n.NumberFormatSymbols_rof;
    -
    -
    -/**
    - * Number formatting symbols for locale ru_BY.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ru_BY = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: '\u043D\u0435\u00A0\u0447\u0438\u0441\u043B\u043E',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'BYR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ru_KG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ru_KG = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: '\u043D\u0435\u00A0\u0447\u0438\u0441\u043B\u043E',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'KGS'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ru_KZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ru_KZ = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: '\u043D\u0435\u00A0\u0447\u0438\u0441\u043B\u043E',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'KZT'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ru_MD.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ru_MD = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: '\u043D\u0435\u00A0\u0447\u0438\u0441\u043B\u043E',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'MDL'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ru_UA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ru_UA = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: '\u043D\u0435\u00A0\u0447\u0438\u0441\u043B\u043E',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'UAH'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale rw.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_rw = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'RWF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale rw_RW.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_rw_RW = goog.i18n.NumberFormatSymbols_rw;
    -
    -
    -/**
    - * Number formatting symbols for locale rwk.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_rwk = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A4',
    -  DEF_CURRENCY_CODE: 'TZS'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale rwk_TZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_rwk_TZ = goog.i18n.NumberFormatSymbols_rwk;
    -
    -
    -/**
    - * Number formatting symbols for locale sah.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sah = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'RUB'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale sah_RU.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sah_RU = goog.i18n.NumberFormatSymbols_sah;
    -
    -
    -/**
    - * Number formatting symbols for locale saq.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_saq = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'KES'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale saq_KE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_saq_KE = goog.i18n.NumberFormatSymbols_saq;
    -
    -
    -/**
    - * Number formatting symbols for locale sbp.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sbp = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A4',
    -  DEF_CURRENCY_CODE: 'TZS'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale sbp_TZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sbp_TZ = goog.i18n.NumberFormatSymbols_sbp;
    -
    -
    -/**
    - * Number formatting symbols for locale se.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_se = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '\u2212',
    -  EXP_SYMBOL: '\u00D710^',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: '\u00A4\u00A4\u00A4',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'NOK'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale se_FI.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_se_FI = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '\u2212',
    -  EXP_SYMBOL: '\u00D710^',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: '\u00A4\u00A4\u00A4',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale se_NO.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_se_NO = goog.i18n.NumberFormatSymbols_se;
    -
    -
    -/**
    - * Number formatting symbols for locale se_SE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_se_SE = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '\u2212',
    -  EXP_SYMBOL: '\u00D710^',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: '\u00A4\u00A4\u00A4',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'SEK'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale seh.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_seh = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A4',
    -  DEF_CURRENCY_CODE: 'MZN'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale seh_MZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_seh_MZ = goog.i18n.NumberFormatSymbols_seh;
    -
    -
    -/**
    - * Number formatting symbols for locale ses.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ses = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A4',
    -  DEF_CURRENCY_CODE: 'XOF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ses_ML.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ses_ML = goog.i18n.NumberFormatSymbols_ses;
    -
    -
    -/**
    - * Number formatting symbols for locale sg.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sg = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00;\u00A4-#,##0.00',
    -  DEF_CURRENCY_CODE: 'XAF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale sg_CF.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sg_CF = goog.i18n.NumberFormatSymbols_sg;
    -
    -
    -/**
    - * Number formatting symbols for locale shi.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_shi = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A4',
    -  DEF_CURRENCY_CODE: 'MAD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale shi_Latn.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_shi_Latn = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale shi_Latn_MA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_shi_Latn_MA = goog.i18n.NumberFormatSymbols_shi;
    -
    -
    -/**
    - * Number formatting symbols for locale shi_Tfng.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_shi_Tfng = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale shi_Tfng_MA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_shi_Tfng_MA = goog.i18n.NumberFormatSymbols_shi;
    -
    -
    -/**
    - * Number formatting symbols for locale smn.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_smn = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'epiloho',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale smn_FI.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_smn_FI = goog.i18n.NumberFormatSymbols_smn;
    -
    -
    -/**
    - * Number formatting symbols for locale sn.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sn = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'USD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale sn_ZW.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sn_ZW = goog.i18n.NumberFormatSymbols_sn;
    -
    -
    -/**
    - * Number formatting symbols for locale so.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_so = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'SOS'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale so_DJ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_so_DJ = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'DJF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale so_ET.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_so_ET = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'ETB'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale so_KE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_so_KE = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'KES'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale so_SO.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_so_SO = goog.i18n.NumberFormatSymbols_so;
    -
    -
    -/**
    - * Number formatting symbols for locale sq_MK.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sq_MK = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'MKD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale sq_XK.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sq_XK = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale sr_Cyrl.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sr_Cyrl = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale sr_Cyrl_BA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sr_Cyrl_BA = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'BAM'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale sr_Cyrl_ME.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sr_Cyrl_ME =
    -    goog.i18n.NumberFormatSymbols_sr_Cyrl;
    -
    -
    -/**
    - * Number formatting symbols for locale sr_Cyrl_XK.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sr_Cyrl_XK =
    -    goog.i18n.NumberFormatSymbols_sr_Cyrl;
    -
    -
    -/**
    - * Number formatting symbols for locale sr_Latn.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sr_Latn = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'RSD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale sr_Latn_BA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sr_Latn_BA = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'BAM'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale sr_Latn_ME.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sr_Latn_ME = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale sr_Latn_RS.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sr_Latn_RS =
    -    goog.i18n.NumberFormatSymbols_sr_Latn;
    -
    -
    -/**
    - * Number formatting symbols for locale sr_Latn_XK.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sr_Latn_XK = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ss.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ss = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'ZAR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ss_SZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ss_SZ = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'SZL'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ss_ZA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ss_ZA = goog.i18n.NumberFormatSymbols_ss;
    -
    -
    -/**
    - * Number formatting symbols for locale ssy.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ssy = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'ERN'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ssy_ER.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ssy_ER = goog.i18n.NumberFormatSymbols_ssy;
    -
    -
    -/**
    - * Number formatting symbols for locale sv_AX.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sv_AX = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '\u2212',
    -  EXP_SYMBOL: '\u00D710^',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: '\u00A4\u00A4\u00A4',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale sv_FI.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sv_FI = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '\u2212',
    -  EXP_SYMBOL: '\u00D710^',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: '\u00A4\u00A4\u00A4',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale sw_KE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sw_KE = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'KES'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale sw_UG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_sw_UG = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'UGX'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale swc.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_swc = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'CDF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale swc_CD.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_swc_CD = goog.i18n.NumberFormatSymbols_swc;
    -
    -
    -/**
    - * Number formatting symbols for locale ta_LK.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ta_LK = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##,##0.00',
    -  DEF_CURRENCY_CODE: 'LKR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ta_MY.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ta_MY = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'MYR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ta_SG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ta_SG = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'SGD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale teo.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_teo = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'UGX'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale teo_KE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_teo_KE = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'KES'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale teo_UG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_teo_UG = goog.i18n.NumberFormatSymbols_teo;
    -
    -
    -/**
    - * Number formatting symbols for locale ti.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ti = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'ETB'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ti_ER.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ti_ER = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'ERN'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ti_ET.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ti_ET = goog.i18n.NumberFormatSymbols_ti;
    -
    -
    -/**
    - * Number formatting symbols for locale tn.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_tn = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'ZAR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale tn_BW.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_tn_BW = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'BWP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale tn_ZA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_tn_ZA = goog.i18n.NumberFormatSymbols_tn;
    -
    -
    -/**
    - * Number formatting symbols for locale to.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_to = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'TF',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'TOP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale to_TO.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_to_TO = goog.i18n.NumberFormatSymbols_to;
    -
    -
    -/**
    - * Number formatting symbols for locale tr_CY.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_tr_CY = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '.',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '%#,##0',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ts.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ts = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'ZAR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ts_ZA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ts_ZA = goog.i18n.NumberFormatSymbols_ts;
    -
    -
    -/**
    - * Number formatting symbols for locale twq.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_twq = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A4',
    -  DEF_CURRENCY_CODE: 'XOF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale twq_NE.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_twq_NE = goog.i18n.NumberFormatSymbols_twq;
    -
    -
    -/**
    - * Number formatting symbols for locale tzm.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_tzm = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'MAD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale tzm_Latn.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_tzm_Latn = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale tzm_Latn_MA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_tzm_Latn_MA = goog.i18n.NumberFormatSymbols_tzm;
    -
    -
    -/**
    - * Number formatting symbols for locale ug.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ug = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'CNY'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ug_Arab.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ug_Arab = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ug_Arab_CN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ug_Arab_CN = goog.i18n.NumberFormatSymbols_ug;
    -
    -
    -/**
    - * Number formatting symbols for locale ur_IN.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ur_IN = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '\u06F0',
    -  PLUS_SIGN: '\u200E+\u200E',
    -  MINUS_SIGN: '\u200E-\u200E',
    -  EXP_SYMBOL: '\u0642',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: '\u06CC\u06C1\u00A0\u0639\u062F\u062F\u00A0\u0646\u06C1\u06CC\u06BA',
    -  DECIMAL_PATTERN: '#,##,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##,##0.00',
    -  DEF_CURRENCY_CODE: 'INR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale uz_Arab.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_uz_Arab = {
    -  DECIMAL_SEP: '\u066B',
    -  GROUP_SEP: '\u066C',
    -  PERCENT: '\u066A',
    -  ZERO_DIGIT: '\u06F0',
    -  PLUS_SIGN: '\u200E+\u200E',
    -  MINUS_SIGN: '\u200E-\u200E',
    -  EXP_SYMBOL: '\u00D7\u06F1\u06F0^',
    -  PERMILL: '\u0609',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'AFN'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale uz_Arab_AF.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_uz_Arab_AF =
    -    goog.i18n.NumberFormatSymbols_uz_Arab;
    -
    -
    -/**
    - * Number formatting symbols for locale uz_Cyrl.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_uz_Cyrl = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale uz_Cyrl_UZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_uz_Cyrl_UZ = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'UZS'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale uz_Latn.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_uz_Latn = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale vai.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_vai = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'LRD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale vai_Latn.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_vai_Latn = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale vai_Latn_LR.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_vai_Latn_LR = goog.i18n.NumberFormatSymbols_vai;
    -
    -
    -/**
    - * Number formatting symbols for locale vai_Vaii.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_vai_Vaii = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale vai_Vaii_LR.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_vai_Vaii_LR = goog.i18n.NumberFormatSymbols_vai;
    -
    -
    -/**
    - * Number formatting symbols for locale ve.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ve = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'ZAR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale ve_ZA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_ve_ZA = goog.i18n.NumberFormatSymbols_ve;
    -
    -
    -/**
    - * Number formatting symbols for locale vo.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_vo = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'USD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale vo_001.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_vo_001 = goog.i18n.NumberFormatSymbols_vo;
    -
    -
    -/**
    - * Number formatting symbols for locale vun.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_vun = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'TZS'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale vun_TZ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_vun_TZ = goog.i18n.NumberFormatSymbols_vun;
    -
    -
    -/**
    - * Number formatting symbols for locale wae.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_wae = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u2019',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'CHF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale wae_CH.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_wae_CH = goog.i18n.NumberFormatSymbols_wae;
    -
    -
    -/**
    - * Number formatting symbols for locale xog.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_xog = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'UGX'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale xog_UG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_xog_UG = goog.i18n.NumberFormatSymbols_xog;
    -
    -
    -/**
    - * Number formatting symbols for locale yav.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_yav = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A0\u00A4',
    -  DEF_CURRENCY_CODE: 'XAF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale yav_CM.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_yav_CM = goog.i18n.NumberFormatSymbols_yav;
    -
    -
    -/**
    - * Number formatting symbols for locale yi.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_yi = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'USD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale yi_001.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_yi_001 = goog.i18n.NumberFormatSymbols_yi;
    -
    -
    -/**
    - * Number formatting symbols for locale yo.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_yo = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'NGN'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale yo_BJ.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_yo_BJ = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'XOF'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale yo_NG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_yo_NG = goog.i18n.NumberFormatSymbols_yo;
    -
    -
    -/**
    - * Number formatting symbols for locale zgh.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_zgh = {
    -  DECIMAL_SEP: ',',
    -  GROUP_SEP: '\u00A0',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0\u00A0%',
    -  CURRENCY_PATTERN: '#,##0.00\u00A4',
    -  DEF_CURRENCY_CODE: 'MAD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale zgh_MA.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_zgh_MA = goog.i18n.NumberFormatSymbols_zgh;
    -
    -
    -/**
    - * Number formatting symbols for locale zh_Hans.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_zh_Hans = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
    -  DEF_CURRENCY_CODE: 'EUR'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale zh_Hans_HK.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_zh_Hans_HK = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'HKD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale zh_Hans_MO.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_zh_Hans_MO = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'MOP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale zh_Hans_SG.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_zh_Hans_SG = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: 'NaN',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'SGD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale zh_Hant.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_zh_Hant = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: '\u975E\u6578\u503C',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'TWD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale zh_Hant_HK.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_zh_Hant_HK = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: '\u975E\u6578\u503C',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'HKD'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale zh_Hant_MO.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_zh_Hant_MO = {
    -  DECIMAL_SEP: '.',
    -  GROUP_SEP: ',',
    -  PERCENT: '%',
    -  ZERO_DIGIT: '0',
    -  PLUS_SIGN: '+',
    -  MINUS_SIGN: '-',
    -  EXP_SYMBOL: 'E',
    -  PERMILL: '\u2030',
    -  INFINITY: '\u221E',
    -  NAN: '\u975E\u6578\u503C',
    -  DECIMAL_PATTERN: '#,##0.###',
    -  SCIENTIFIC_PATTERN: '#E0',
    -  PERCENT_PATTERN: '#,##0%',
    -  CURRENCY_PATTERN: '\u00A4#,##0.00',
    -  DEF_CURRENCY_CODE: 'MOP'
    -};
    -
    -
    -/**
    - * Number formatting symbols for locale zh_Hant_TW.
    - * @enum {string}
    - */
    -goog.i18n.NumberFormatSymbols_zh_Hant_TW =
    -    goog.i18n.NumberFormatSymbols_zh_Hant;
    -
    -
    -/**
    - * Selected number formatting symbols by locale.
    - */
    -
    -if (goog.LOCALE == 'aa') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_aa;
    -}
    -
    -if (goog.LOCALE == 'aa_DJ' || goog.LOCALE == 'aa-DJ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_aa_DJ;
    -}
    -
    -if (goog.LOCALE == 'aa_ER' || goog.LOCALE == 'aa-ER') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_aa_ER;
    -}
    -
    -if (goog.LOCALE == 'aa_ET' || goog.LOCALE == 'aa-ET') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_aa;
    -}
    -
    -if (goog.LOCALE == 'af_NA' || goog.LOCALE == 'af-NA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_af_NA;
    -}
    -
    -if (goog.LOCALE == 'agq') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_agq;
    -}
    -
    -if (goog.LOCALE == 'agq_CM' || goog.LOCALE == 'agq-CM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_agq;
    -}
    -
    -if (goog.LOCALE == 'ak') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ak;
    -}
    -
    -if (goog.LOCALE == 'ak_GH' || goog.LOCALE == 'ak-GH') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ak;
    -}
    -
    -if (goog.LOCALE == 'ar_AE' || goog.LOCALE == 'ar-AE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar_AE;
    -}
    -
    -if (goog.LOCALE == 'ar_BH' || goog.LOCALE == 'ar-BH') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar_BH;
    -}
    -
    -if (goog.LOCALE == 'ar_DJ' || goog.LOCALE == 'ar-DJ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar_DJ;
    -}
    -
    -if (goog.LOCALE == 'ar_DZ' || goog.LOCALE == 'ar-DZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar_DZ;
    -}
    -
    -if (goog.LOCALE == 'ar_EG' || goog.LOCALE == 'ar-EG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar_EG;
    -}
    -
    -if (goog.LOCALE == 'ar_EH' || goog.LOCALE == 'ar-EH') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar_EH;
    -}
    -
    -if (goog.LOCALE == 'ar_ER' || goog.LOCALE == 'ar-ER') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar_ER;
    -}
    -
    -if (goog.LOCALE == 'ar_IL' || goog.LOCALE == 'ar-IL') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar_IL;
    -}
    -
    -if (goog.LOCALE == 'ar_IQ' || goog.LOCALE == 'ar-IQ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar_IQ;
    -}
    -
    -if (goog.LOCALE == 'ar_JO' || goog.LOCALE == 'ar-JO') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar_JO;
    -}
    -
    -if (goog.LOCALE == 'ar_KM' || goog.LOCALE == 'ar-KM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar_KM;
    -}
    -
    -if (goog.LOCALE == 'ar_KW' || goog.LOCALE == 'ar-KW') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar_KW;
    -}
    -
    -if (goog.LOCALE == 'ar_LB' || goog.LOCALE == 'ar-LB') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar_LB;
    -}
    -
    -if (goog.LOCALE == 'ar_LY' || goog.LOCALE == 'ar-LY') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar_LY;
    -}
    -
    -if (goog.LOCALE == 'ar_MA' || goog.LOCALE == 'ar-MA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar_MA;
    -}
    -
    -if (goog.LOCALE == 'ar_MR' || goog.LOCALE == 'ar-MR') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar_MR;
    -}
    -
    -if (goog.LOCALE == 'ar_OM' || goog.LOCALE == 'ar-OM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar_OM;
    -}
    -
    -if (goog.LOCALE == 'ar_PS' || goog.LOCALE == 'ar-PS') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar_PS;
    -}
    -
    -if (goog.LOCALE == 'ar_QA' || goog.LOCALE == 'ar-QA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar_QA;
    -}
    -
    -if (goog.LOCALE == 'ar_SA' || goog.LOCALE == 'ar-SA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar_SA;
    -}
    -
    -if (goog.LOCALE == 'ar_SD' || goog.LOCALE == 'ar-SD') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar_SD;
    -}
    -
    -if (goog.LOCALE == 'ar_SO' || goog.LOCALE == 'ar-SO') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar_SO;
    -}
    -
    -if (goog.LOCALE == 'ar_SS' || goog.LOCALE == 'ar-SS') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar_SS;
    -}
    -
    -if (goog.LOCALE == 'ar_SY' || goog.LOCALE == 'ar-SY') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar_SY;
    -}
    -
    -if (goog.LOCALE == 'ar_TD' || goog.LOCALE == 'ar-TD') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar_TD;
    -}
    -
    -if (goog.LOCALE == 'ar_TN' || goog.LOCALE == 'ar-TN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar_TN;
    -}
    -
    -if (goog.LOCALE == 'ar_YE' || goog.LOCALE == 'ar-YE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ar_YE;
    -}
    -
    -if (goog.LOCALE == 'as') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_as;
    -}
    -
    -if (goog.LOCALE == 'as_IN' || goog.LOCALE == 'as-IN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_as;
    -}
    -
    -if (goog.LOCALE == 'asa') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_asa;
    -}
    -
    -if (goog.LOCALE == 'asa_TZ' || goog.LOCALE == 'asa-TZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_asa;
    -}
    -
    -if (goog.LOCALE == 'ast') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ast;
    -}
    -
    -if (goog.LOCALE == 'ast_ES' || goog.LOCALE == 'ast-ES') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ast;
    -}
    -
    -if (goog.LOCALE == 'az_Cyrl' || goog.LOCALE == 'az-Cyrl') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_az_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'az_Cyrl_AZ' || goog.LOCALE == 'az-Cyrl-AZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_az_Cyrl_AZ;
    -}
    -
    -if (goog.LOCALE == 'az_Latn' || goog.LOCALE == 'az-Latn') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_az_Latn;
    -}
    -
    -if (goog.LOCALE == 'bas') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bas;
    -}
    -
    -if (goog.LOCALE == 'bas_CM' || goog.LOCALE == 'bas-CM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bas;
    -}
    -
    -if (goog.LOCALE == 'be') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_be;
    -}
    -
    -if (goog.LOCALE == 'be_BY' || goog.LOCALE == 'be-BY') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_be;
    -}
    -
    -if (goog.LOCALE == 'bem') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bem;
    -}
    -
    -if (goog.LOCALE == 'bem_ZM' || goog.LOCALE == 'bem-ZM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bem;
    -}
    -
    -if (goog.LOCALE == 'bez') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bez;
    -}
    -
    -if (goog.LOCALE == 'bez_TZ' || goog.LOCALE == 'bez-TZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bez;
    -}
    -
    -if (goog.LOCALE == 'bm') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bm;
    -}
    -
    -if (goog.LOCALE == 'bm_Latn' || goog.LOCALE == 'bm-Latn') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bm_Latn;
    -}
    -
    -if (goog.LOCALE == 'bm_Latn_ML' || goog.LOCALE == 'bm-Latn-ML') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bm;
    -}
    -
    -if (goog.LOCALE == 'bn_IN' || goog.LOCALE == 'bn-IN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bn_IN;
    -}
    -
    -if (goog.LOCALE == 'bo') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bo;
    -}
    -
    -if (goog.LOCALE == 'bo_CN' || goog.LOCALE == 'bo-CN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bo;
    -}
    -
    -if (goog.LOCALE == 'bo_IN' || goog.LOCALE == 'bo-IN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bo_IN;
    -}
    -
    -if (goog.LOCALE == 'brx') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_brx;
    -}
    -
    -if (goog.LOCALE == 'brx_IN' || goog.LOCALE == 'brx-IN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_brx;
    -}
    -
    -if (goog.LOCALE == 'bs') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bs;
    -}
    -
    -if (goog.LOCALE == 'bs_Cyrl' || goog.LOCALE == 'bs-Cyrl') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bs_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'bs_Cyrl_BA' || goog.LOCALE == 'bs-Cyrl-BA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bs_Cyrl_BA;
    -}
    -
    -if (goog.LOCALE == 'bs_Latn' || goog.LOCALE == 'bs-Latn') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bs_Latn;
    -}
    -
    -if (goog.LOCALE == 'bs_Latn_BA' || goog.LOCALE == 'bs-Latn-BA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_bs;
    -}
    -
    -if (goog.LOCALE == 'cgg') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_cgg;
    -}
    -
    -if (goog.LOCALE == 'cgg_UG' || goog.LOCALE == 'cgg-UG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_cgg;
    -}
    -
    -if (goog.LOCALE == 'ckb') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ckb;
    -}
    -
    -if (goog.LOCALE == 'ckb_Arab' || goog.LOCALE == 'ckb-Arab') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ckb_Arab;
    -}
    -
    -if (goog.LOCALE == 'ckb_Arab_IQ' || goog.LOCALE == 'ckb-Arab-IQ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ckb;
    -}
    -
    -if (goog.LOCALE == 'ckb_Arab_IR' || goog.LOCALE == 'ckb-Arab-IR') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ckb_Arab_IR;
    -}
    -
    -if (goog.LOCALE == 'ckb_IQ' || goog.LOCALE == 'ckb-IQ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ckb;
    -}
    -
    -if (goog.LOCALE == 'ckb_IR' || goog.LOCALE == 'ckb-IR') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ckb_IR;
    -}
    -
    -if (goog.LOCALE == 'ckb_Latn' || goog.LOCALE == 'ckb-Latn') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ckb_Latn;
    -}
    -
    -if (goog.LOCALE == 'ckb_Latn_IQ' || goog.LOCALE == 'ckb-Latn-IQ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ckb;
    -}
    -
    -if (goog.LOCALE == 'dav') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_dav;
    -}
    -
    -if (goog.LOCALE == 'dav_KE' || goog.LOCALE == 'dav-KE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_dav;
    -}
    -
    -if (goog.LOCALE == 'de_LI' || goog.LOCALE == 'de-LI') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_de_LI;
    -}
    -
    -if (goog.LOCALE == 'dje') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_dje;
    -}
    -
    -if (goog.LOCALE == 'dje_NE' || goog.LOCALE == 'dje-NE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_dje;
    -}
    -
    -if (goog.LOCALE == 'dsb') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_dsb;
    -}
    -
    -if (goog.LOCALE == 'dsb_DE' || goog.LOCALE == 'dsb-DE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_dsb;
    -}
    -
    -if (goog.LOCALE == 'dua') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_dua;
    -}
    -
    -if (goog.LOCALE == 'dua_CM' || goog.LOCALE == 'dua-CM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_dua;
    -}
    -
    -if (goog.LOCALE == 'dyo') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_dyo;
    -}
    -
    -if (goog.LOCALE == 'dyo_SN' || goog.LOCALE == 'dyo-SN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_dyo;
    -}
    -
    -if (goog.LOCALE == 'dz') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_dz;
    -}
    -
    -if (goog.LOCALE == 'dz_BT' || goog.LOCALE == 'dz-BT') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_dz;
    -}
    -
    -if (goog.LOCALE == 'ebu') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ebu;
    -}
    -
    -if (goog.LOCALE == 'ebu_KE' || goog.LOCALE == 'ebu-KE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ebu;
    -}
    -
    -if (goog.LOCALE == 'ee') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ee;
    -}
    -
    -if (goog.LOCALE == 'ee_GH' || goog.LOCALE == 'ee-GH') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ee;
    -}
    -
    -if (goog.LOCALE == 'ee_TG' || goog.LOCALE == 'ee-TG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ee_TG;
    -}
    -
    -if (goog.LOCALE == 'el_CY' || goog.LOCALE == 'el-CY') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_el_CY;
    -}
    -
    -if (goog.LOCALE == 'en_150' || goog.LOCALE == 'en-150') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_150;
    -}
    -
    -if (goog.LOCALE == 'en_AG' || goog.LOCALE == 'en-AG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_AG;
    -}
    -
    -if (goog.LOCALE == 'en_AI' || goog.LOCALE == 'en-AI') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_AI;
    -}
    -
    -if (goog.LOCALE == 'en_BB' || goog.LOCALE == 'en-BB') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_BB;
    -}
    -
    -if (goog.LOCALE == 'en_BE' || goog.LOCALE == 'en-BE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_BE;
    -}
    -
    -if (goog.LOCALE == 'en_BM' || goog.LOCALE == 'en-BM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_BM;
    -}
    -
    -if (goog.LOCALE == 'en_BS' || goog.LOCALE == 'en-BS') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_BS;
    -}
    -
    -if (goog.LOCALE == 'en_BW' || goog.LOCALE == 'en-BW') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_BW;
    -}
    -
    -if (goog.LOCALE == 'en_BZ' || goog.LOCALE == 'en-BZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_BZ;
    -}
    -
    -if (goog.LOCALE == 'en_CA' || goog.LOCALE == 'en-CA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_CA;
    -}
    -
    -if (goog.LOCALE == 'en_CC' || goog.LOCALE == 'en-CC') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_CC;
    -}
    -
    -if (goog.LOCALE == 'en_CK' || goog.LOCALE == 'en-CK') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_CK;
    -}
    -
    -if (goog.LOCALE == 'en_CM' || goog.LOCALE == 'en-CM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_CM;
    -}
    -
    -if (goog.LOCALE == 'en_CX' || goog.LOCALE == 'en-CX') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_CX;
    -}
    -
    -if (goog.LOCALE == 'en_DM' || goog.LOCALE == 'en-DM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_DM;
    -}
    -
    -if (goog.LOCALE == 'en_ER' || goog.LOCALE == 'en-ER') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_ER;
    -}
    -
    -if (goog.LOCALE == 'en_FJ' || goog.LOCALE == 'en-FJ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_FJ;
    -}
    -
    -if (goog.LOCALE == 'en_FK' || goog.LOCALE == 'en-FK') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_FK;
    -}
    -
    -if (goog.LOCALE == 'en_GD' || goog.LOCALE == 'en-GD') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_GD;
    -}
    -
    -if (goog.LOCALE == 'en_GG' || goog.LOCALE == 'en-GG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_GG;
    -}
    -
    -if (goog.LOCALE == 'en_GH' || goog.LOCALE == 'en-GH') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_GH;
    -}
    -
    -if (goog.LOCALE == 'en_GI' || goog.LOCALE == 'en-GI') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_GI;
    -}
    -
    -if (goog.LOCALE == 'en_GM' || goog.LOCALE == 'en-GM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_GM;
    -}
    -
    -if (goog.LOCALE == 'en_GY' || goog.LOCALE == 'en-GY') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_GY;
    -}
    -
    -if (goog.LOCALE == 'en_HK' || goog.LOCALE == 'en-HK') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_HK;
    -}
    -
    -if (goog.LOCALE == 'en_IM' || goog.LOCALE == 'en-IM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_IM;
    -}
    -
    -if (goog.LOCALE == 'en_JE' || goog.LOCALE == 'en-JE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_JE;
    -}
    -
    -if (goog.LOCALE == 'en_JM' || goog.LOCALE == 'en-JM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_JM;
    -}
    -
    -if (goog.LOCALE == 'en_KE' || goog.LOCALE == 'en-KE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_KE;
    -}
    -
    -if (goog.LOCALE == 'en_KI' || goog.LOCALE == 'en-KI') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_KI;
    -}
    -
    -if (goog.LOCALE == 'en_KN' || goog.LOCALE == 'en-KN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_KN;
    -}
    -
    -if (goog.LOCALE == 'en_KY' || goog.LOCALE == 'en-KY') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_KY;
    -}
    -
    -if (goog.LOCALE == 'en_LC' || goog.LOCALE == 'en-LC') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_LC;
    -}
    -
    -if (goog.LOCALE == 'en_LR' || goog.LOCALE == 'en-LR') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_LR;
    -}
    -
    -if (goog.LOCALE == 'en_LS' || goog.LOCALE == 'en-LS') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_LS;
    -}
    -
    -if (goog.LOCALE == 'en_MG' || goog.LOCALE == 'en-MG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_MG;
    -}
    -
    -if (goog.LOCALE == 'en_MO' || goog.LOCALE == 'en-MO') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_MO;
    -}
    -
    -if (goog.LOCALE == 'en_MS' || goog.LOCALE == 'en-MS') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_MS;
    -}
    -
    -if (goog.LOCALE == 'en_MT' || goog.LOCALE == 'en-MT') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_MT;
    -}
    -
    -if (goog.LOCALE == 'en_MU' || goog.LOCALE == 'en-MU') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_MU;
    -}
    -
    -if (goog.LOCALE == 'en_MW' || goog.LOCALE == 'en-MW') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_MW;
    -}
    -
    -if (goog.LOCALE == 'en_MY' || goog.LOCALE == 'en-MY') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_MY;
    -}
    -
    -if (goog.LOCALE == 'en_NA' || goog.LOCALE == 'en-NA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_NA;
    -}
    -
    -if (goog.LOCALE == 'en_NF' || goog.LOCALE == 'en-NF') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_NF;
    -}
    -
    -if (goog.LOCALE == 'en_NG' || goog.LOCALE == 'en-NG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_NG;
    -}
    -
    -if (goog.LOCALE == 'en_NR' || goog.LOCALE == 'en-NR') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_NR;
    -}
    -
    -if (goog.LOCALE == 'en_NU' || goog.LOCALE == 'en-NU') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_NU;
    -}
    -
    -if (goog.LOCALE == 'en_NZ' || goog.LOCALE == 'en-NZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_NZ;
    -}
    -
    -if (goog.LOCALE == 'en_PG' || goog.LOCALE == 'en-PG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_PG;
    -}
    -
    -if (goog.LOCALE == 'en_PH' || goog.LOCALE == 'en-PH') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_PH;
    -}
    -
    -if (goog.LOCALE == 'en_PK' || goog.LOCALE == 'en-PK') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_PK;
    -}
    -
    -if (goog.LOCALE == 'en_PN' || goog.LOCALE == 'en-PN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_PN;
    -}
    -
    -if (goog.LOCALE == 'en_RW' || goog.LOCALE == 'en-RW') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_RW;
    -}
    -
    -if (goog.LOCALE == 'en_SB' || goog.LOCALE == 'en-SB') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_SB;
    -}
    -
    -if (goog.LOCALE == 'en_SC' || goog.LOCALE == 'en-SC') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_SC;
    -}
    -
    -if (goog.LOCALE == 'en_SD' || goog.LOCALE == 'en-SD') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_SD;
    -}
    -
    -if (goog.LOCALE == 'en_SH' || goog.LOCALE == 'en-SH') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_SH;
    -}
    -
    -if (goog.LOCALE == 'en_SL' || goog.LOCALE == 'en-SL') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_SL;
    -}
    -
    -if (goog.LOCALE == 'en_SS' || goog.LOCALE == 'en-SS') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_SS;
    -}
    -
    -if (goog.LOCALE == 'en_SX' || goog.LOCALE == 'en-SX') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_SX;
    -}
    -
    -if (goog.LOCALE == 'en_SZ' || goog.LOCALE == 'en-SZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_SZ;
    -}
    -
    -if (goog.LOCALE == 'en_TK' || goog.LOCALE == 'en-TK') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_TK;
    -}
    -
    -if (goog.LOCALE == 'en_TO' || goog.LOCALE == 'en-TO') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_TO;
    -}
    -
    -if (goog.LOCALE == 'en_TT' || goog.LOCALE == 'en-TT') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_TT;
    -}
    -
    -if (goog.LOCALE == 'en_TV' || goog.LOCALE == 'en-TV') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_TV;
    -}
    -
    -if (goog.LOCALE == 'en_TZ' || goog.LOCALE == 'en-TZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_TZ;
    -}
    -
    -if (goog.LOCALE == 'en_UG' || goog.LOCALE == 'en-UG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_UG;
    -}
    -
    -if (goog.LOCALE == 'en_VC' || goog.LOCALE == 'en-VC') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_VC;
    -}
    -
    -if (goog.LOCALE == 'en_VU' || goog.LOCALE == 'en-VU') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_VU;
    -}
    -
    -if (goog.LOCALE == 'en_WS' || goog.LOCALE == 'en-WS') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_WS;
    -}
    -
    -if (goog.LOCALE == 'en_ZM' || goog.LOCALE == 'en-ZM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_en_ZM;
    -}
    -
    -if (goog.LOCALE == 'eo') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_eo;
    -}
    -
    -if (goog.LOCALE == 'eo_001' || goog.LOCALE == 'eo-001') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_eo;
    -}
    -
    -if (goog.LOCALE == 'es_AR' || goog.LOCALE == 'es-AR') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es_AR;
    -}
    -
    -if (goog.LOCALE == 'es_BO' || goog.LOCALE == 'es-BO') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es_BO;
    -}
    -
    -if (goog.LOCALE == 'es_CL' || goog.LOCALE == 'es-CL') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es_CL;
    -}
    -
    -if (goog.LOCALE == 'es_CO' || goog.LOCALE == 'es-CO') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es_CO;
    -}
    -
    -if (goog.LOCALE == 'es_CR' || goog.LOCALE == 'es-CR') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es_CR;
    -}
    -
    -if (goog.LOCALE == 'es_CU' || goog.LOCALE == 'es-CU') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es_CU;
    -}
    -
    -if (goog.LOCALE == 'es_DO' || goog.LOCALE == 'es-DO') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es_DO;
    -}
    -
    -if (goog.LOCALE == 'es_EC' || goog.LOCALE == 'es-EC') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es_EC;
    -}
    -
    -if (goog.LOCALE == 'es_GQ' || goog.LOCALE == 'es-GQ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es_GQ;
    -}
    -
    -if (goog.LOCALE == 'es_GT' || goog.LOCALE == 'es-GT') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es_GT;
    -}
    -
    -if (goog.LOCALE == 'es_HN' || goog.LOCALE == 'es-HN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es_HN;
    -}
    -
    -if (goog.LOCALE == 'es_MX' || goog.LOCALE == 'es-MX') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es_MX;
    -}
    -
    -if (goog.LOCALE == 'es_NI' || goog.LOCALE == 'es-NI') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es_NI;
    -}
    -
    -if (goog.LOCALE == 'es_PA' || goog.LOCALE == 'es-PA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es_PA;
    -}
    -
    -if (goog.LOCALE == 'es_PE' || goog.LOCALE == 'es-PE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es_PE;
    -}
    -
    -if (goog.LOCALE == 'es_PH' || goog.LOCALE == 'es-PH') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es_PH;
    -}
    -
    -if (goog.LOCALE == 'es_PR' || goog.LOCALE == 'es-PR') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es_PR;
    -}
    -
    -if (goog.LOCALE == 'es_PY' || goog.LOCALE == 'es-PY') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es_PY;
    -}
    -
    -if (goog.LOCALE == 'es_SV' || goog.LOCALE == 'es-SV') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es_SV;
    -}
    -
    -if (goog.LOCALE == 'es_US' || goog.LOCALE == 'es-US') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es_US;
    -}
    -
    -if (goog.LOCALE == 'es_UY' || goog.LOCALE == 'es-UY') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es_UY;
    -}
    -
    -if (goog.LOCALE == 'es_VE' || goog.LOCALE == 'es-VE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_es_VE;
    -}
    -
    -if (goog.LOCALE == 'ewo') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ewo;
    -}
    -
    -if (goog.LOCALE == 'ewo_CM' || goog.LOCALE == 'ewo-CM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ewo;
    -}
    -
    -if (goog.LOCALE == 'fa_AF' || goog.LOCALE == 'fa-AF') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fa_AF;
    -}
    -
    -if (goog.LOCALE == 'ff') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ff;
    -}
    -
    -if (goog.LOCALE == 'ff_CM' || goog.LOCALE == 'ff-CM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ff_CM;
    -}
    -
    -if (goog.LOCALE == 'ff_GN' || goog.LOCALE == 'ff-GN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ff_GN;
    -}
    -
    -if (goog.LOCALE == 'ff_MR' || goog.LOCALE == 'ff-MR') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ff_MR;
    -}
    -
    -if (goog.LOCALE == 'ff_SN' || goog.LOCALE == 'ff-SN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ff;
    -}
    -
    -if (goog.LOCALE == 'fo') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fo;
    -}
    -
    -if (goog.LOCALE == 'fo_FO' || goog.LOCALE == 'fo-FO') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fo;
    -}
    -
    -if (goog.LOCALE == 'fr_BE' || goog.LOCALE == 'fr-BE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_BE;
    -}
    -
    -if (goog.LOCALE == 'fr_BF' || goog.LOCALE == 'fr-BF') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_BF;
    -}
    -
    -if (goog.LOCALE == 'fr_BI' || goog.LOCALE == 'fr-BI') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_BI;
    -}
    -
    -if (goog.LOCALE == 'fr_BJ' || goog.LOCALE == 'fr-BJ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_BJ;
    -}
    -
    -if (goog.LOCALE == 'fr_CD' || goog.LOCALE == 'fr-CD') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_CD;
    -}
    -
    -if (goog.LOCALE == 'fr_CF' || goog.LOCALE == 'fr-CF') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_CF;
    -}
    -
    -if (goog.LOCALE == 'fr_CG' || goog.LOCALE == 'fr-CG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_CG;
    -}
    -
    -if (goog.LOCALE == 'fr_CH' || goog.LOCALE == 'fr-CH') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_CH;
    -}
    -
    -if (goog.LOCALE == 'fr_CI' || goog.LOCALE == 'fr-CI') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_CI;
    -}
    -
    -if (goog.LOCALE == 'fr_CM' || goog.LOCALE == 'fr-CM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_CM;
    -}
    -
    -if (goog.LOCALE == 'fr_DJ' || goog.LOCALE == 'fr-DJ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_DJ;
    -}
    -
    -if (goog.LOCALE == 'fr_DZ' || goog.LOCALE == 'fr-DZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_DZ;
    -}
    -
    -if (goog.LOCALE == 'fr_GA' || goog.LOCALE == 'fr-GA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_GA;
    -}
    -
    -if (goog.LOCALE == 'fr_GN' || goog.LOCALE == 'fr-GN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_GN;
    -}
    -
    -if (goog.LOCALE == 'fr_GQ' || goog.LOCALE == 'fr-GQ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_GQ;
    -}
    -
    -if (goog.LOCALE == 'fr_HT' || goog.LOCALE == 'fr-HT') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_HT;
    -}
    -
    -if (goog.LOCALE == 'fr_KM' || goog.LOCALE == 'fr-KM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_KM;
    -}
    -
    -if (goog.LOCALE == 'fr_LU' || goog.LOCALE == 'fr-LU') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_LU;
    -}
    -
    -if (goog.LOCALE == 'fr_MA' || goog.LOCALE == 'fr-MA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_MA;
    -}
    -
    -if (goog.LOCALE == 'fr_MG' || goog.LOCALE == 'fr-MG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_MG;
    -}
    -
    -if (goog.LOCALE == 'fr_ML' || goog.LOCALE == 'fr-ML') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_ML;
    -}
    -
    -if (goog.LOCALE == 'fr_MR' || goog.LOCALE == 'fr-MR') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_MR;
    -}
    -
    -if (goog.LOCALE == 'fr_MU' || goog.LOCALE == 'fr-MU') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_MU;
    -}
    -
    -if (goog.LOCALE == 'fr_NC' || goog.LOCALE == 'fr-NC') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_NC;
    -}
    -
    -if (goog.LOCALE == 'fr_NE' || goog.LOCALE == 'fr-NE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_NE;
    -}
    -
    -if (goog.LOCALE == 'fr_PF' || goog.LOCALE == 'fr-PF') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_PF;
    -}
    -
    -if (goog.LOCALE == 'fr_RW' || goog.LOCALE == 'fr-RW') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_RW;
    -}
    -
    -if (goog.LOCALE == 'fr_SC' || goog.LOCALE == 'fr-SC') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_SC;
    -}
    -
    -if (goog.LOCALE == 'fr_SN' || goog.LOCALE == 'fr-SN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_SN;
    -}
    -
    -if (goog.LOCALE == 'fr_SY' || goog.LOCALE == 'fr-SY') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_SY;
    -}
    -
    -if (goog.LOCALE == 'fr_TD' || goog.LOCALE == 'fr-TD') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_TD;
    -}
    -
    -if (goog.LOCALE == 'fr_TG' || goog.LOCALE == 'fr-TG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_TG;
    -}
    -
    -if (goog.LOCALE == 'fr_TN' || goog.LOCALE == 'fr-TN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_TN;
    -}
    -
    -if (goog.LOCALE == 'fr_VU' || goog.LOCALE == 'fr-VU') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_VU;
    -}
    -
    -if (goog.LOCALE == 'fr_WF' || goog.LOCALE == 'fr-WF') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fr_WF;
    -}
    -
    -if (goog.LOCALE == 'fur') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fur;
    -}
    -
    -if (goog.LOCALE == 'fur_IT' || goog.LOCALE == 'fur-IT') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fur;
    -}
    -
    -if (goog.LOCALE == 'fy') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fy;
    -}
    -
    -if (goog.LOCALE == 'fy_NL' || goog.LOCALE == 'fy-NL') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_fy;
    -}
    -
    -if (goog.LOCALE == 'gd') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_gd;
    -}
    -
    -if (goog.LOCALE == 'gd_GB' || goog.LOCALE == 'gd-GB') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_gd;
    -}
    -
    -if (goog.LOCALE == 'gsw_FR' || goog.LOCALE == 'gsw-FR') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_gsw_FR;
    -}
    -
    -if (goog.LOCALE == 'guz') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_guz;
    -}
    -
    -if (goog.LOCALE == 'guz_KE' || goog.LOCALE == 'guz-KE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_guz;
    -}
    -
    -if (goog.LOCALE == 'gv') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_gv;
    -}
    -
    -if (goog.LOCALE == 'gv_IM' || goog.LOCALE == 'gv-IM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_gv;
    -}
    -
    -if (goog.LOCALE == 'ha') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ha;
    -}
    -
    -if (goog.LOCALE == 'ha_Latn' || goog.LOCALE == 'ha-Latn') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ha_Latn;
    -}
    -
    -if (goog.LOCALE == 'ha_Latn_GH' || goog.LOCALE == 'ha-Latn-GH') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ha_Latn_GH;
    -}
    -
    -if (goog.LOCALE == 'ha_Latn_NE' || goog.LOCALE == 'ha-Latn-NE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ha_Latn_NE;
    -}
    -
    -if (goog.LOCALE == 'ha_Latn_NG' || goog.LOCALE == 'ha-Latn-NG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ha;
    -}
    -
    -if (goog.LOCALE == 'hr_BA' || goog.LOCALE == 'hr-BA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_hr_BA;
    -}
    -
    -if (goog.LOCALE == 'hsb') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_hsb;
    -}
    -
    -if (goog.LOCALE == 'hsb_DE' || goog.LOCALE == 'hsb-DE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_hsb;
    -}
    -
    -if (goog.LOCALE == 'ia') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ia;
    -}
    -
    -if (goog.LOCALE == 'ia_FR' || goog.LOCALE == 'ia-FR') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ia;
    -}
    -
    -if (goog.LOCALE == 'ig') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ig;
    -}
    -
    -if (goog.LOCALE == 'ig_NG' || goog.LOCALE == 'ig-NG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ig;
    -}
    -
    -if (goog.LOCALE == 'ii') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ii;
    -}
    -
    -if (goog.LOCALE == 'ii_CN' || goog.LOCALE == 'ii-CN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ii;
    -}
    -
    -if (goog.LOCALE == 'it_CH' || goog.LOCALE == 'it-CH') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_it_CH;
    -}
    -
    -if (goog.LOCALE == 'jgo') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_jgo;
    -}
    -
    -if (goog.LOCALE == 'jgo_CM' || goog.LOCALE == 'jgo-CM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_jgo;
    -}
    -
    -if (goog.LOCALE == 'jmc') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_jmc;
    -}
    -
    -if (goog.LOCALE == 'jmc_TZ' || goog.LOCALE == 'jmc-TZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_jmc;
    -}
    -
    -if (goog.LOCALE == 'kab') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_kab;
    -}
    -
    -if (goog.LOCALE == 'kab_DZ' || goog.LOCALE == 'kab-DZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_kab;
    -}
    -
    -if (goog.LOCALE == 'kam') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_kam;
    -}
    -
    -if (goog.LOCALE == 'kam_KE' || goog.LOCALE == 'kam-KE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_kam;
    -}
    -
    -if (goog.LOCALE == 'kde') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_kde;
    -}
    -
    -if (goog.LOCALE == 'kde_TZ' || goog.LOCALE == 'kde-TZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_kde;
    -}
    -
    -if (goog.LOCALE == 'kea') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_kea;
    -}
    -
    -if (goog.LOCALE == 'kea_CV' || goog.LOCALE == 'kea-CV') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_kea;
    -}
    -
    -if (goog.LOCALE == 'khq') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_khq;
    -}
    -
    -if (goog.LOCALE == 'khq_ML' || goog.LOCALE == 'khq-ML') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_khq;
    -}
    -
    -if (goog.LOCALE == 'ki') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ki;
    -}
    -
    -if (goog.LOCALE == 'ki_KE' || goog.LOCALE == 'ki-KE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ki;
    -}
    -
    -if (goog.LOCALE == 'kk_Cyrl' || goog.LOCALE == 'kk-Cyrl') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_kk_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'kkj') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_kkj;
    -}
    -
    -if (goog.LOCALE == 'kkj_CM' || goog.LOCALE == 'kkj-CM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_kkj;
    -}
    -
    -if (goog.LOCALE == 'kl') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_kl;
    -}
    -
    -if (goog.LOCALE == 'kl_GL' || goog.LOCALE == 'kl-GL') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_kl;
    -}
    -
    -if (goog.LOCALE == 'kln') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_kln;
    -}
    -
    -if (goog.LOCALE == 'kln_KE' || goog.LOCALE == 'kln-KE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_kln;
    -}
    -
    -if (goog.LOCALE == 'ko_KP' || goog.LOCALE == 'ko-KP') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ko_KP;
    -}
    -
    -if (goog.LOCALE == 'kok') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_kok;
    -}
    -
    -if (goog.LOCALE == 'kok_IN' || goog.LOCALE == 'kok-IN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_kok;
    -}
    -
    -if (goog.LOCALE == 'ks') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ks;
    -}
    -
    -if (goog.LOCALE == 'ks_Arab' || goog.LOCALE == 'ks-Arab') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ks_Arab;
    -}
    -
    -if (goog.LOCALE == 'ks_Arab_IN' || goog.LOCALE == 'ks-Arab-IN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ks;
    -}
    -
    -if (goog.LOCALE == 'ksb') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ksb;
    -}
    -
    -if (goog.LOCALE == 'ksb_TZ' || goog.LOCALE == 'ksb-TZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ksb;
    -}
    -
    -if (goog.LOCALE == 'ksf') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ksf;
    -}
    -
    -if (goog.LOCALE == 'ksf_CM' || goog.LOCALE == 'ksf-CM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ksf;
    -}
    -
    -if (goog.LOCALE == 'ksh') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ksh;
    -}
    -
    -if (goog.LOCALE == 'ksh_DE' || goog.LOCALE == 'ksh-DE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ksh;
    -}
    -
    -if (goog.LOCALE == 'kw') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_kw;
    -}
    -
    -if (goog.LOCALE == 'kw_GB' || goog.LOCALE == 'kw-GB') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_kw;
    -}
    -
    -if (goog.LOCALE == 'ky_Cyrl' || goog.LOCALE == 'ky-Cyrl') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ky_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'lag') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_lag;
    -}
    -
    -if (goog.LOCALE == 'lag_TZ' || goog.LOCALE == 'lag-TZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_lag;
    -}
    -
    -if (goog.LOCALE == 'lb') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_lb;
    -}
    -
    -if (goog.LOCALE == 'lb_LU' || goog.LOCALE == 'lb-LU') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_lb;
    -}
    -
    -if (goog.LOCALE == 'lg') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_lg;
    -}
    -
    -if (goog.LOCALE == 'lg_UG' || goog.LOCALE == 'lg-UG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_lg;
    -}
    -
    -if (goog.LOCALE == 'lkt') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_lkt;
    -}
    -
    -if (goog.LOCALE == 'lkt_US' || goog.LOCALE == 'lkt-US') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_lkt;
    -}
    -
    -if (goog.LOCALE == 'ln_AO' || goog.LOCALE == 'ln-AO') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ln_AO;
    -}
    -
    -if (goog.LOCALE == 'ln_CF' || goog.LOCALE == 'ln-CF') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ln_CF;
    -}
    -
    -if (goog.LOCALE == 'ln_CG' || goog.LOCALE == 'ln-CG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ln_CG;
    -}
    -
    -if (goog.LOCALE == 'lu') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_lu;
    -}
    -
    -if (goog.LOCALE == 'lu_CD' || goog.LOCALE == 'lu-CD') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_lu;
    -}
    -
    -if (goog.LOCALE == 'luo') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_luo;
    -}
    -
    -if (goog.LOCALE == 'luo_KE' || goog.LOCALE == 'luo-KE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_luo;
    -}
    -
    -if (goog.LOCALE == 'luy') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_luy;
    -}
    -
    -if (goog.LOCALE == 'luy_KE' || goog.LOCALE == 'luy-KE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_luy;
    -}
    -
    -if (goog.LOCALE == 'mas') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mas;
    -}
    -
    -if (goog.LOCALE == 'mas_KE' || goog.LOCALE == 'mas-KE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mas;
    -}
    -
    -if (goog.LOCALE == 'mas_TZ' || goog.LOCALE == 'mas-TZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mas_TZ;
    -}
    -
    -if (goog.LOCALE == 'mer') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mer;
    -}
    -
    -if (goog.LOCALE == 'mer_KE' || goog.LOCALE == 'mer-KE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mer;
    -}
    -
    -if (goog.LOCALE == 'mfe') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mfe;
    -}
    -
    -if (goog.LOCALE == 'mfe_MU' || goog.LOCALE == 'mfe-MU') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mfe;
    -}
    -
    -if (goog.LOCALE == 'mg') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mg;
    -}
    -
    -if (goog.LOCALE == 'mg_MG' || goog.LOCALE == 'mg-MG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mg;
    -}
    -
    -if (goog.LOCALE == 'mgh') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mgh;
    -}
    -
    -if (goog.LOCALE == 'mgh_MZ' || goog.LOCALE == 'mgh-MZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mgh;
    -}
    -
    -if (goog.LOCALE == 'mgo') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mgo;
    -}
    -
    -if (goog.LOCALE == 'mgo_CM' || goog.LOCALE == 'mgo-CM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mgo;
    -}
    -
    -if (goog.LOCALE == 'mn_Cyrl' || goog.LOCALE == 'mn-Cyrl') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mn_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'ms_Latn' || goog.LOCALE == 'ms-Latn') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ms_Latn;
    -}
    -
    -if (goog.LOCALE == 'ms_Latn_BN' || goog.LOCALE == 'ms-Latn-BN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ms_Latn_BN;
    -}
    -
    -if (goog.LOCALE == 'ms_Latn_SG' || goog.LOCALE == 'ms-Latn-SG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ms_Latn_SG;
    -}
    -
    -if (goog.LOCALE == 'mua') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mua;
    -}
    -
    -if (goog.LOCALE == 'mua_CM' || goog.LOCALE == 'mua-CM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_mua;
    -}
    -
    -if (goog.LOCALE == 'naq') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_naq;
    -}
    -
    -if (goog.LOCALE == 'naq_NA' || goog.LOCALE == 'naq-NA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_naq;
    -}
    -
    -if (goog.LOCALE == 'nd') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_nd;
    -}
    -
    -if (goog.LOCALE == 'nd_ZW' || goog.LOCALE == 'nd-ZW') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_nd;
    -}
    -
    -if (goog.LOCALE == 'ne_IN' || goog.LOCALE == 'ne-IN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ne_IN;
    -}
    -
    -if (goog.LOCALE == 'nl_AW' || goog.LOCALE == 'nl-AW') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_nl_AW;
    -}
    -
    -if (goog.LOCALE == 'nl_BE' || goog.LOCALE == 'nl-BE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_nl_BE;
    -}
    -
    -if (goog.LOCALE == 'nl_BQ' || goog.LOCALE == 'nl-BQ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_nl_BQ;
    -}
    -
    -if (goog.LOCALE == 'nl_CW' || goog.LOCALE == 'nl-CW') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_nl_CW;
    -}
    -
    -if (goog.LOCALE == 'nl_SR' || goog.LOCALE == 'nl-SR') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_nl_SR;
    -}
    -
    -if (goog.LOCALE == 'nl_SX' || goog.LOCALE == 'nl-SX') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_nl_SX;
    -}
    -
    -if (goog.LOCALE == 'nmg') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_nmg;
    -}
    -
    -if (goog.LOCALE == 'nmg_CM' || goog.LOCALE == 'nmg-CM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_nmg;
    -}
    -
    -if (goog.LOCALE == 'nn') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_nn;
    -}
    -
    -if (goog.LOCALE == 'nn_NO' || goog.LOCALE == 'nn-NO') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_nn;
    -}
    -
    -if (goog.LOCALE == 'nnh') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_nnh;
    -}
    -
    -if (goog.LOCALE == 'nnh_CM' || goog.LOCALE == 'nnh-CM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_nnh;
    -}
    -
    -if (goog.LOCALE == 'nr') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_nr;
    -}
    -
    -if (goog.LOCALE == 'nr_ZA' || goog.LOCALE == 'nr-ZA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_nr;
    -}
    -
    -if (goog.LOCALE == 'nso') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_nso;
    -}
    -
    -if (goog.LOCALE == 'nso_ZA' || goog.LOCALE == 'nso-ZA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_nso;
    -}
    -
    -if (goog.LOCALE == 'nus') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_nus;
    -}
    -
    -if (goog.LOCALE == 'nus_SD' || goog.LOCALE == 'nus-SD') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_nus;
    -}
    -
    -if (goog.LOCALE == 'nyn') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_nyn;
    -}
    -
    -if (goog.LOCALE == 'nyn_UG' || goog.LOCALE == 'nyn-UG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_nyn;
    -}
    -
    -if (goog.LOCALE == 'om') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_om;
    -}
    -
    -if (goog.LOCALE == 'om_ET' || goog.LOCALE == 'om-ET') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_om;
    -}
    -
    -if (goog.LOCALE == 'om_KE' || goog.LOCALE == 'om-KE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_om_KE;
    -}
    -
    -if (goog.LOCALE == 'os') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_os;
    -}
    -
    -if (goog.LOCALE == 'os_GE' || goog.LOCALE == 'os-GE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_os;
    -}
    -
    -if (goog.LOCALE == 'os_RU' || goog.LOCALE == 'os-RU') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_os_RU;
    -}
    -
    -if (goog.LOCALE == 'pa_Arab' || goog.LOCALE == 'pa-Arab') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_pa_Arab;
    -}
    -
    -if (goog.LOCALE == 'pa_Arab_PK' || goog.LOCALE == 'pa-Arab-PK') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_pa_Arab;
    -}
    -
    -if (goog.LOCALE == 'pa_Guru' || goog.LOCALE == 'pa-Guru') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_pa_Guru;
    -}
    -
    -if (goog.LOCALE == 'ps') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ps;
    -}
    -
    -if (goog.LOCALE == 'ps_AF' || goog.LOCALE == 'ps-AF') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ps;
    -}
    -
    -if (goog.LOCALE == 'pt_AO' || goog.LOCALE == 'pt-AO') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_pt_AO;
    -}
    -
    -if (goog.LOCALE == 'pt_CV' || goog.LOCALE == 'pt-CV') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_pt_CV;
    -}
    -
    -if (goog.LOCALE == 'pt_GW' || goog.LOCALE == 'pt-GW') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_pt_GW;
    -}
    -
    -if (goog.LOCALE == 'pt_MO' || goog.LOCALE == 'pt-MO') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_pt_MO;
    -}
    -
    -if (goog.LOCALE == 'pt_MZ' || goog.LOCALE == 'pt-MZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_pt_MZ;
    -}
    -
    -if (goog.LOCALE == 'pt_ST' || goog.LOCALE == 'pt-ST') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_pt_ST;
    -}
    -
    -if (goog.LOCALE == 'pt_TL' || goog.LOCALE == 'pt-TL') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_pt_TL;
    -}
    -
    -if (goog.LOCALE == 'qu') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_qu;
    -}
    -
    -if (goog.LOCALE == 'qu_BO' || goog.LOCALE == 'qu-BO') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_qu_BO;
    -}
    -
    -if (goog.LOCALE == 'qu_EC' || goog.LOCALE == 'qu-EC') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_qu_EC;
    -}
    -
    -if (goog.LOCALE == 'qu_PE' || goog.LOCALE == 'qu-PE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_qu;
    -}
    -
    -if (goog.LOCALE == 'rm') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_rm;
    -}
    -
    -if (goog.LOCALE == 'rm_CH' || goog.LOCALE == 'rm-CH') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_rm;
    -}
    -
    -if (goog.LOCALE == 'rn') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_rn;
    -}
    -
    -if (goog.LOCALE == 'rn_BI' || goog.LOCALE == 'rn-BI') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_rn;
    -}
    -
    -if (goog.LOCALE == 'ro_MD' || goog.LOCALE == 'ro-MD') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ro_MD;
    -}
    -
    -if (goog.LOCALE == 'rof') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_rof;
    -}
    -
    -if (goog.LOCALE == 'rof_TZ' || goog.LOCALE == 'rof-TZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_rof;
    -}
    -
    -if (goog.LOCALE == 'ru_BY' || goog.LOCALE == 'ru-BY') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ru_BY;
    -}
    -
    -if (goog.LOCALE == 'ru_KG' || goog.LOCALE == 'ru-KG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ru_KG;
    -}
    -
    -if (goog.LOCALE == 'ru_KZ' || goog.LOCALE == 'ru-KZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ru_KZ;
    -}
    -
    -if (goog.LOCALE == 'ru_MD' || goog.LOCALE == 'ru-MD') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ru_MD;
    -}
    -
    -if (goog.LOCALE == 'ru_UA' || goog.LOCALE == 'ru-UA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ru_UA;
    -}
    -
    -if (goog.LOCALE == 'rw') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_rw;
    -}
    -
    -if (goog.LOCALE == 'rw_RW' || goog.LOCALE == 'rw-RW') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_rw;
    -}
    -
    -if (goog.LOCALE == 'rwk') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_rwk;
    -}
    -
    -if (goog.LOCALE == 'rwk_TZ' || goog.LOCALE == 'rwk-TZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_rwk;
    -}
    -
    -if (goog.LOCALE == 'sah') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sah;
    -}
    -
    -if (goog.LOCALE == 'sah_RU' || goog.LOCALE == 'sah-RU') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sah;
    -}
    -
    -if (goog.LOCALE == 'saq') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_saq;
    -}
    -
    -if (goog.LOCALE == 'saq_KE' || goog.LOCALE == 'saq-KE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_saq;
    -}
    -
    -if (goog.LOCALE == 'sbp') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sbp;
    -}
    -
    -if (goog.LOCALE == 'sbp_TZ' || goog.LOCALE == 'sbp-TZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sbp;
    -}
    -
    -if (goog.LOCALE == 'se') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_se;
    -}
    -
    -if (goog.LOCALE == 'se_FI' || goog.LOCALE == 'se-FI') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_se_FI;
    -}
    -
    -if (goog.LOCALE == 'se_NO' || goog.LOCALE == 'se-NO') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_se;
    -}
    -
    -if (goog.LOCALE == 'se_SE' || goog.LOCALE == 'se-SE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_se_SE;
    -}
    -
    -if (goog.LOCALE == 'seh') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_seh;
    -}
    -
    -if (goog.LOCALE == 'seh_MZ' || goog.LOCALE == 'seh-MZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_seh;
    -}
    -
    -if (goog.LOCALE == 'ses') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ses;
    -}
    -
    -if (goog.LOCALE == 'ses_ML' || goog.LOCALE == 'ses-ML') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ses;
    -}
    -
    -if (goog.LOCALE == 'sg') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sg;
    -}
    -
    -if (goog.LOCALE == 'sg_CF' || goog.LOCALE == 'sg-CF') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sg;
    -}
    -
    -if (goog.LOCALE == 'shi') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_shi;
    -}
    -
    -if (goog.LOCALE == 'shi_Latn' || goog.LOCALE == 'shi-Latn') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_shi_Latn;
    -}
    -
    -if (goog.LOCALE == 'shi_Latn_MA' || goog.LOCALE == 'shi-Latn-MA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_shi;
    -}
    -
    -if (goog.LOCALE == 'shi_Tfng' || goog.LOCALE == 'shi-Tfng') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_shi_Tfng;
    -}
    -
    -if (goog.LOCALE == 'shi_Tfng_MA' || goog.LOCALE == 'shi-Tfng-MA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_shi;
    -}
    -
    -if (goog.LOCALE == 'smn') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_smn;
    -}
    -
    -if (goog.LOCALE == 'smn_FI' || goog.LOCALE == 'smn-FI') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_smn;
    -}
    -
    -if (goog.LOCALE == 'sn') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sn;
    -}
    -
    -if (goog.LOCALE == 'sn_ZW' || goog.LOCALE == 'sn-ZW') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sn;
    -}
    -
    -if (goog.LOCALE == 'so') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_so;
    -}
    -
    -if (goog.LOCALE == 'so_DJ' || goog.LOCALE == 'so-DJ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_so_DJ;
    -}
    -
    -if (goog.LOCALE == 'so_ET' || goog.LOCALE == 'so-ET') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_so_ET;
    -}
    -
    -if (goog.LOCALE == 'so_KE' || goog.LOCALE == 'so-KE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_so_KE;
    -}
    -
    -if (goog.LOCALE == 'so_SO' || goog.LOCALE == 'so-SO') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_so;
    -}
    -
    -if (goog.LOCALE == 'sq_MK' || goog.LOCALE == 'sq-MK') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sq_MK;
    -}
    -
    -if (goog.LOCALE == 'sq_XK' || goog.LOCALE == 'sq-XK') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sq_XK;
    -}
    -
    -if (goog.LOCALE == 'sr_Cyrl' || goog.LOCALE == 'sr-Cyrl') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sr_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'sr_Cyrl_BA' || goog.LOCALE == 'sr-Cyrl-BA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sr_Cyrl_BA;
    -}
    -
    -if (goog.LOCALE == 'sr_Cyrl_ME' || goog.LOCALE == 'sr-Cyrl-ME') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sr_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'sr_Cyrl_XK' || goog.LOCALE == 'sr-Cyrl-XK') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sr_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'sr_Latn' || goog.LOCALE == 'sr-Latn') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sr_Latn;
    -}
    -
    -if (goog.LOCALE == 'sr_Latn_BA' || goog.LOCALE == 'sr-Latn-BA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sr_Latn_BA;
    -}
    -
    -if (goog.LOCALE == 'sr_Latn_ME' || goog.LOCALE == 'sr-Latn-ME') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sr_Latn_ME;
    -}
    -
    -if (goog.LOCALE == 'sr_Latn_RS' || goog.LOCALE == 'sr-Latn-RS') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sr_Latn;
    -}
    -
    -if (goog.LOCALE == 'sr_Latn_XK' || goog.LOCALE == 'sr-Latn-XK') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sr_Latn_XK;
    -}
    -
    -if (goog.LOCALE == 'ss') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ss;
    -}
    -
    -if (goog.LOCALE == 'ss_SZ' || goog.LOCALE == 'ss-SZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ss_SZ;
    -}
    -
    -if (goog.LOCALE == 'ss_ZA' || goog.LOCALE == 'ss-ZA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ss;
    -}
    -
    -if (goog.LOCALE == 'ssy') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ssy;
    -}
    -
    -if (goog.LOCALE == 'ssy_ER' || goog.LOCALE == 'ssy-ER') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ssy;
    -}
    -
    -if (goog.LOCALE == 'sv_AX' || goog.LOCALE == 'sv-AX') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sv_AX;
    -}
    -
    -if (goog.LOCALE == 'sv_FI' || goog.LOCALE == 'sv-FI') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sv_FI;
    -}
    -
    -if (goog.LOCALE == 'sw_KE' || goog.LOCALE == 'sw-KE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sw_KE;
    -}
    -
    -if (goog.LOCALE == 'sw_UG' || goog.LOCALE == 'sw-UG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_sw_UG;
    -}
    -
    -if (goog.LOCALE == 'swc') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_swc;
    -}
    -
    -if (goog.LOCALE == 'swc_CD' || goog.LOCALE == 'swc-CD') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_swc;
    -}
    -
    -if (goog.LOCALE == 'ta_LK' || goog.LOCALE == 'ta-LK') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ta_LK;
    -}
    -
    -if (goog.LOCALE == 'ta_MY' || goog.LOCALE == 'ta-MY') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ta_MY;
    -}
    -
    -if (goog.LOCALE == 'ta_SG' || goog.LOCALE == 'ta-SG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ta_SG;
    -}
    -
    -if (goog.LOCALE == 'teo') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_teo;
    -}
    -
    -if (goog.LOCALE == 'teo_KE' || goog.LOCALE == 'teo-KE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_teo_KE;
    -}
    -
    -if (goog.LOCALE == 'teo_UG' || goog.LOCALE == 'teo-UG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_teo;
    -}
    -
    -if (goog.LOCALE == 'ti') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ti;
    -}
    -
    -if (goog.LOCALE == 'ti_ER' || goog.LOCALE == 'ti-ER') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ti_ER;
    -}
    -
    -if (goog.LOCALE == 'ti_ET' || goog.LOCALE == 'ti-ET') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ti;
    -}
    -
    -if (goog.LOCALE == 'tn') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_tn;
    -}
    -
    -if (goog.LOCALE == 'tn_BW' || goog.LOCALE == 'tn-BW') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_tn_BW;
    -}
    -
    -if (goog.LOCALE == 'tn_ZA' || goog.LOCALE == 'tn-ZA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_tn;
    -}
    -
    -if (goog.LOCALE == 'to') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_to;
    -}
    -
    -if (goog.LOCALE == 'to_TO' || goog.LOCALE == 'to-TO') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_to;
    -}
    -
    -if (goog.LOCALE == 'tr_CY' || goog.LOCALE == 'tr-CY') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_tr_CY;
    -}
    -
    -if (goog.LOCALE == 'ts') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ts;
    -}
    -
    -if (goog.LOCALE == 'ts_ZA' || goog.LOCALE == 'ts-ZA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ts;
    -}
    -
    -if (goog.LOCALE == 'twq') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_twq;
    -}
    -
    -if (goog.LOCALE == 'twq_NE' || goog.LOCALE == 'twq-NE') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_twq;
    -}
    -
    -if (goog.LOCALE == 'tzm') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_tzm;
    -}
    -
    -if (goog.LOCALE == 'tzm_Latn' || goog.LOCALE == 'tzm-Latn') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_tzm_Latn;
    -}
    -
    -if (goog.LOCALE == 'tzm_Latn_MA' || goog.LOCALE == 'tzm-Latn-MA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_tzm;
    -}
    -
    -if (goog.LOCALE == 'ug') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ug;
    -}
    -
    -if (goog.LOCALE == 'ug_Arab' || goog.LOCALE == 'ug-Arab') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ug_Arab;
    -}
    -
    -if (goog.LOCALE == 'ug_Arab_CN' || goog.LOCALE == 'ug-Arab-CN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ug;
    -}
    -
    -if (goog.LOCALE == 'ur_IN' || goog.LOCALE == 'ur-IN') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ur_IN;
    -}
    -
    -if (goog.LOCALE == 'uz_Arab' || goog.LOCALE == 'uz-Arab') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_uz_Arab;
    -}
    -
    -if (goog.LOCALE == 'uz_Arab_AF' || goog.LOCALE == 'uz-Arab-AF') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_uz_Arab;
    -}
    -
    -if (goog.LOCALE == 'uz_Cyrl' || goog.LOCALE == 'uz-Cyrl') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_uz_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'uz_Cyrl_UZ' || goog.LOCALE == 'uz-Cyrl-UZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_uz_Cyrl_UZ;
    -}
    -
    -if (goog.LOCALE == 'uz_Latn' || goog.LOCALE == 'uz-Latn') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_uz_Latn;
    -}
    -
    -if (goog.LOCALE == 'vai') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_vai;
    -}
    -
    -if (goog.LOCALE == 'vai_Latn' || goog.LOCALE == 'vai-Latn') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_vai_Latn;
    -}
    -
    -if (goog.LOCALE == 'vai_Latn_LR' || goog.LOCALE == 'vai-Latn-LR') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_vai;
    -}
    -
    -if (goog.LOCALE == 'vai_Vaii' || goog.LOCALE == 'vai-Vaii') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_vai_Vaii;
    -}
    -
    -if (goog.LOCALE == 'vai_Vaii_LR' || goog.LOCALE == 'vai-Vaii-LR') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_vai;
    -}
    -
    -if (goog.LOCALE == 've') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ve;
    -}
    -
    -if (goog.LOCALE == 've_ZA' || goog.LOCALE == 've-ZA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_ve;
    -}
    -
    -if (goog.LOCALE == 'vo') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_vo;
    -}
    -
    -if (goog.LOCALE == 'vo_001' || goog.LOCALE == 'vo-001') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_vo;
    -}
    -
    -if (goog.LOCALE == 'vun') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_vun;
    -}
    -
    -if (goog.LOCALE == 'vun_TZ' || goog.LOCALE == 'vun-TZ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_vun;
    -}
    -
    -if (goog.LOCALE == 'wae') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_wae;
    -}
    -
    -if (goog.LOCALE == 'wae_CH' || goog.LOCALE == 'wae-CH') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_wae;
    -}
    -
    -if (goog.LOCALE == 'xog') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_xog;
    -}
    -
    -if (goog.LOCALE == 'xog_UG' || goog.LOCALE == 'xog-UG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_xog;
    -}
    -
    -if (goog.LOCALE == 'yav') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_yav;
    -}
    -
    -if (goog.LOCALE == 'yav_CM' || goog.LOCALE == 'yav-CM') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_yav;
    -}
    -
    -if (goog.LOCALE == 'yi') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_yi;
    -}
    -
    -if (goog.LOCALE == 'yi_001' || goog.LOCALE == 'yi-001') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_yi;
    -}
    -
    -if (goog.LOCALE == 'yo') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_yo;
    -}
    -
    -if (goog.LOCALE == 'yo_BJ' || goog.LOCALE == 'yo-BJ') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_yo_BJ;
    -}
    -
    -if (goog.LOCALE == 'yo_NG' || goog.LOCALE == 'yo-NG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_yo;
    -}
    -
    -if (goog.LOCALE == 'zgh') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_zgh;
    -}
    -
    -if (goog.LOCALE == 'zgh_MA' || goog.LOCALE == 'zgh-MA') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_zgh;
    -}
    -
    -if (goog.LOCALE == 'zh_Hans' || goog.LOCALE == 'zh-Hans') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_zh_Hans;
    -}
    -
    -if (goog.LOCALE == 'zh_Hans_HK' || goog.LOCALE == 'zh-Hans-HK') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_zh_Hans_HK;
    -}
    -
    -if (goog.LOCALE == 'zh_Hans_MO' || goog.LOCALE == 'zh-Hans-MO') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_zh_Hans_MO;
    -}
    -
    -if (goog.LOCALE == 'zh_Hans_SG' || goog.LOCALE == 'zh-Hans-SG') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_zh_Hans_SG;
    -}
    -
    -if (goog.LOCALE == 'zh_Hant' || goog.LOCALE == 'zh-Hant') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_zh_Hant;
    -}
    -
    -if (goog.LOCALE == 'zh_Hant_HK' || goog.LOCALE == 'zh-Hant-HK') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_zh_Hant_HK;
    -}
    -
    -if (goog.LOCALE == 'zh_Hant_MO' || goog.LOCALE == 'zh-Hant-MO') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_zh_Hant_MO;
    -}
    -
    -if (goog.LOCALE == 'zh_Hant_TW' || goog.LOCALE == 'zh-Hant-TW') {
    -  goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_zh_Hant;
    -}
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/ordinalrules.js b/src/database/third_party/closure-library/closure/goog/i18n/ordinalrules.js
    deleted file mode 100644
    index c9dc82ed2b0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/ordinalrules.js
    +++ /dev/null
    @@ -1,748 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Ordinal rules.
    - *
    - * This file is autogenerated by script:
    - *   http://go/generate_pluralrules.py
    - * File generated from CLDR ver. 26
    - *
    - * Before check in, this file could have been manually edited. This is to
    - * incorporate changes before we could fix CLDR. All manual modification must be
    - * documented in this section, and should be removed after those changes land to
    - * CLDR.
    - */
    -
    -goog.provide('goog.i18n.ordinalRules');
    -/**
    - * Ordinal pattern keyword
    - * @enum {string}
    - */
    -goog.i18n.ordinalRules.Keyword = {
    -  ZERO: 'zero',
    -  ONE: 'one',
    -  TWO: 'two',
    -  FEW: 'few',
    -  MANY: 'many',
    -  OTHER: 'other'
    -};
    -
    -
    -/**
    - * Default Ordinal select rule.
    - * @param {number} n The count of items.
    - * @param {number=} opt_precision optional, precision.
    - * @return {goog.i18n.ordinalRules.Keyword} Default value.
    - * @private
    - */
    -goog.i18n.ordinalRules.defaultSelect_ = function(n, opt_precision) {
    -  return goog.i18n.ordinalRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Returns the fractional part of a number (3.1416 => 1416)
    - * @param {number} n The count of items.
    - * @return {number} The fractional part.
    - * @private
    - */
    -goog.i18n.ordinalRules.decimals_ = function(n) {
    -  var str = n + '';
    -  var result = str.indexOf('.');
    -  return (result == -1) ? 0 : str.length - result - 1;
    -};
    -
    -/**
    - * Calculates v and f as per CLDR plural rules.
    - * The short names for parameters / return match the CLDR syntax and UTS #35
    - *     (http://unicode.org/reports/tr35/tr35-numbers.html#Plural_rules_syntax)
    - * @param {number} n The count of items.
    - * @param {number=} opt_precision optional, precision.
    - * @return {!Object} The v and f.
    - * @private
    - */
    -goog.i18n.ordinalRules.get_vf_ = function(n, opt_precision) {
    -  var DEFAULT_DIGITS = 3;
    -
    -  if (undefined === opt_precision) {
    -    var v = Math.min(goog.i18n.ordinalRules.decimals_(n), DEFAULT_DIGITS);
    -  } else {
    -    var v = opt_precision;
    -  }
    -
    -  var base = Math.pow(10, v);
    -  var f = ((n * base) | 0) % base;
    -
    -  return {v: v, f: f};
    -};
    -
    -/**
    - * Calculates w and t as per CLDR plural rules.
    - * The short names for parameters / return match the CLDR syntax and UTS #35
    - *     (http://unicode.org/reports/tr35/tr35-numbers.html#Plural_rules_syntax)
    - * @param {number} v Calculated previously.
    - * @param {number} f Calculated previously.
    - * @return {!Object} The w and t.
    - * @private
    - */
    -goog.i18n.ordinalRules.get_wt_ = function(v, f) {
    -  if (f === 0) {
    -    return {w: 0, t: 0};
    -  }
    -
    -  while ((f % 10) === 0) {
    -    f /= 10;
    -    v--;
    -  }
    -
    -  return {w: v, t: f};
    -};
    -
    -/**
    - * Ordinal select rules for en locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
    - * @private
    - */
    -goog.i18n.ordinalRules.enSelect_ = function(n, opt_precision) {
    -  if (n % 10 == 1 && n % 100 != 11) {
    -    return goog.i18n.ordinalRules.Keyword.ONE;
    -  }
    -  if (n % 10 == 2 && n % 100 != 12) {
    -    return goog.i18n.ordinalRules.Keyword.TWO;
    -  }
    -  if (n % 10 == 3 && n % 100 != 13) {
    -    return goog.i18n.ordinalRules.Keyword.FEW;
    -  }
    -  return goog.i18n.ordinalRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Ordinal select rules for sv locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
    - * @private
    - */
    -goog.i18n.ordinalRules.svSelect_ = function(n, opt_precision) {
    -  if ((n % 10 == 1 || n % 10 == 2) && n % 100 != 11 && n % 100 != 12) {
    -    return goog.i18n.ordinalRules.Keyword.ONE;
    -  }
    -  return goog.i18n.ordinalRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Ordinal select rules for hu locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
    - * @private
    - */
    -goog.i18n.ordinalRules.huSelect_ = function(n, opt_precision) {
    -  if (n == 1 || n == 5) {
    -    return goog.i18n.ordinalRules.Keyword.ONE;
    -  }
    -  return goog.i18n.ordinalRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Ordinal select rules for kk locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
    - * @private
    - */
    -goog.i18n.ordinalRules.kkSelect_ = function(n, opt_precision) {
    -  if (n % 10 == 6 || n % 10 == 9 || n % 10 == 0 && n != 0) {
    -    return goog.i18n.ordinalRules.Keyword.MANY;
    -  }
    -  return goog.i18n.ordinalRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Ordinal select rules for mr locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
    - * @private
    - */
    -goog.i18n.ordinalRules.mrSelect_ = function(n, opt_precision) {
    -  if (n == 1) {
    -    return goog.i18n.ordinalRules.Keyword.ONE;
    -  }
    -  if (n == 2 || n == 3) {
    -    return goog.i18n.ordinalRules.Keyword.TWO;
    -  }
    -  if (n == 4) {
    -    return goog.i18n.ordinalRules.Keyword.FEW;
    -  }
    -  return goog.i18n.ordinalRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Ordinal select rules for sq locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
    - * @private
    - */
    -goog.i18n.ordinalRules.sqSelect_ = function(n, opt_precision) {
    -  if (n == 1) {
    -    return goog.i18n.ordinalRules.Keyword.ONE;
    -  }
    -  if (n % 10 == 4 && n % 100 != 14) {
    -    return goog.i18n.ordinalRules.Keyword.MANY;
    -  }
    -  return goog.i18n.ordinalRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Ordinal select rules for bn locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
    - * @private
    - */
    -goog.i18n.ordinalRules.bnSelect_ = function(n, opt_precision) {
    -  if (n == 1 || n == 5 || n == 7 || n == 8 || n == 9 || n == 10) {
    -    return goog.i18n.ordinalRules.Keyword.ONE;
    -  }
    -  if (n == 2 || n == 3) {
    -    return goog.i18n.ordinalRules.Keyword.TWO;
    -  }
    -  if (n == 4) {
    -    return goog.i18n.ordinalRules.Keyword.FEW;
    -  }
    -  if (n == 6) {
    -    return goog.i18n.ordinalRules.Keyword.MANY;
    -  }
    -  return goog.i18n.ordinalRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Ordinal select rules for gu locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
    - * @private
    - */
    -goog.i18n.ordinalRules.guSelect_ = function(n, opt_precision) {
    -  if (n == 1) {
    -    return goog.i18n.ordinalRules.Keyword.ONE;
    -  }
    -  if (n == 2 || n == 3) {
    -    return goog.i18n.ordinalRules.Keyword.TWO;
    -  }
    -  if (n == 4) {
    -    return goog.i18n.ordinalRules.Keyword.FEW;
    -  }
    -  if (n == 6) {
    -    return goog.i18n.ordinalRules.Keyword.MANY;
    -  }
    -  return goog.i18n.ordinalRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Ordinal select rules for ka locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
    - * @private
    - */
    -goog.i18n.ordinalRules.kaSelect_ = function(n, opt_precision) {
    -  var i = n | 0;
    -  if (i == 1) {
    -    return goog.i18n.ordinalRules.Keyword.ONE;
    -  }
    -  if (i == 0 || (i % 100 >= 2 && i % 100 <= 20 || i % 100 == 40 || i % 100 == 60 || i % 100 == 80)) {
    -    return goog.i18n.ordinalRules.Keyword.MANY;
    -  }
    -  return goog.i18n.ordinalRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Ordinal select rules for fr locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
    - * @private
    - */
    -goog.i18n.ordinalRules.frSelect_ = function(n, opt_precision) {
    -  if (n == 1) {
    -    return goog.i18n.ordinalRules.Keyword.ONE;
    -  }
    -  return goog.i18n.ordinalRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Ordinal select rules for ne locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
    - * @private
    - */
    -goog.i18n.ordinalRules.neSelect_ = function(n, opt_precision) {
    -  if (n >= 1 && n <= 4) {
    -    return goog.i18n.ordinalRules.Keyword.ONE;
    -  }
    -  return goog.i18n.ordinalRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Ordinal select rules for cy locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
    - * @private
    - */
    -goog.i18n.ordinalRules.cySelect_ = function(n, opt_precision) {
    -  if (n == 0 || n == 7 || n == 8 || n == 9) {
    -    return goog.i18n.ordinalRules.Keyword.ZERO;
    -  }
    -  if (n == 1) {
    -    return goog.i18n.ordinalRules.Keyword.ONE;
    -  }
    -  if (n == 2) {
    -    return goog.i18n.ordinalRules.Keyword.TWO;
    -  }
    -  if (n == 3 || n == 4) {
    -    return goog.i18n.ordinalRules.Keyword.FEW;
    -  }
    -  if (n == 5 || n == 6) {
    -    return goog.i18n.ordinalRules.Keyword.MANY;
    -  }
    -  return goog.i18n.ordinalRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Ordinal select rules for uk locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
    - * @private
    - */
    -goog.i18n.ordinalRules.ukSelect_ = function(n, opt_precision) {
    -  if (n % 10 == 3 && n % 100 != 13) {
    -    return goog.i18n.ordinalRules.Keyword.FEW;
    -  }
    -  return goog.i18n.ordinalRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Ordinal select rules for az locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
    - * @private
    - */
    -goog.i18n.ordinalRules.azSelect_ = function(n, opt_precision) {
    -  var i = n | 0;
    -  if ((i % 10 == 1 || i % 10 == 2 || i % 10 == 5 || i % 10 == 7 || i % 10 == 8) || (i % 100 == 20 || i % 100 == 50 || i % 100 == 70 || i % 100 == 80)) {
    -    return goog.i18n.ordinalRules.Keyword.ONE;
    -  }
    -  if ((i % 10 == 3 || i % 10 == 4) || (i % 1000 == 100 || i % 1000 == 200 || i % 1000 == 300 || i % 1000 == 400 || i % 1000 == 500 || i % 1000 == 600 || i % 1000 == 700 || i % 1000 == 800 || i % 1000 == 900)) {
    -    return goog.i18n.ordinalRules.Keyword.FEW;
    -  }
    -  if (i == 0 || i % 10 == 6 || (i % 100 == 40 || i % 100 == 60 || i % 100 == 90)) {
    -    return goog.i18n.ordinalRules.Keyword.MANY;
    -  }
    -  return goog.i18n.ordinalRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Ordinal select rules for ca locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
    - * @private
    - */
    -goog.i18n.ordinalRules.caSelect_ = function(n, opt_precision) {
    -  if (n == 1 || n == 3) {
    -    return goog.i18n.ordinalRules.Keyword.ONE;
    -  }
    -  if (n == 2) {
    -    return goog.i18n.ordinalRules.Keyword.TWO;
    -  }
    -  if (n == 4) {
    -    return goog.i18n.ordinalRules.Keyword.FEW;
    -  }
    -  return goog.i18n.ordinalRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Ordinal select rules for it locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
    - * @private
    - */
    -goog.i18n.ordinalRules.itSelect_ = function(n, opt_precision) {
    -  if (n == 11 || n == 8 || n == 80 || n == 800) {
    -    return goog.i18n.ordinalRules.Keyword.MANY;
    -  }
    -  return goog.i18n.ordinalRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Ordinal select rules for mk locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
    - * @private
    - */
    -goog.i18n.ordinalRules.mkSelect_ = function(n, opt_precision) {
    -  var i = n | 0;
    -  if (i % 10 == 1 && i % 100 != 11) {
    -    return goog.i18n.ordinalRules.Keyword.ONE;
    -  }
    -  if (i % 10 == 2 && i % 100 != 12) {
    -    return goog.i18n.ordinalRules.Keyword.TWO;
    -  }
    -  if ((i % 10 == 7 || i % 10 == 8) && i % 100 != 17 && i % 100 != 18) {
    -    return goog.i18n.ordinalRules.Keyword.MANY;
    -  }
    -  return goog.i18n.ordinalRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Selected Ordinal rules by locale.
    - */
    -goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.enSelect_;
    -if (goog.LOCALE == 'af') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'am') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'ar') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'az') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.azSelect_;
    -}
    -if (goog.LOCALE == 'bg') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'bn') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.bnSelect_;
    -}
    -if (goog.LOCALE == 'br') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'ca') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.caSelect_;
    -}
    -if (goog.LOCALE == 'chr') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'cs') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'cy') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.cySelect_;
    -}
    -if (goog.LOCALE == 'da') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'de') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'de_AT' || goog.LOCALE == 'de-AT') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'de_CH' || goog.LOCALE == 'de-CH') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'el') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'en') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.enSelect_;
    -}
    -if (goog.LOCALE == 'en_AU' || goog.LOCALE == 'en-AU') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.enSelect_;
    -}
    -if (goog.LOCALE == 'en_GB' || goog.LOCALE == 'en-GB') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.enSelect_;
    -}
    -if (goog.LOCALE == 'en_IE' || goog.LOCALE == 'en-IE') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.enSelect_;
    -}
    -if (goog.LOCALE == 'en_IN' || goog.LOCALE == 'en-IN') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.enSelect_;
    -}
    -if (goog.LOCALE == 'en_SG' || goog.LOCALE == 'en-SG') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.enSelect_;
    -}
    -if (goog.LOCALE == 'en_US' || goog.LOCALE == 'en-US') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.enSelect_;
    -}
    -if (goog.LOCALE == 'en_ZA' || goog.LOCALE == 'en-ZA') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.enSelect_;
    -}
    -if (goog.LOCALE == 'es') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'es_419' || goog.LOCALE == 'es-419') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'es_ES' || goog.LOCALE == 'es-ES') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'et') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'eu') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'fa') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'fi') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'fil') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.frSelect_;
    -}
    -if (goog.LOCALE == 'fr') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.frSelect_;
    -}
    -if (goog.LOCALE == 'fr_CA' || goog.LOCALE == 'fr-CA') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.frSelect_;
    -}
    -if (goog.LOCALE == 'ga') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'gl') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'gsw') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'gu') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.guSelect_;
    -}
    -if (goog.LOCALE == 'haw') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'he') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'hi') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.guSelect_;
    -}
    -if (goog.LOCALE == 'hr') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'hu') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.huSelect_;
    -}
    -if (goog.LOCALE == 'hy') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.frSelect_;
    -}
    -if (goog.LOCALE == 'id') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'in') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'is') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'it') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.itSelect_;
    -}
    -if (goog.LOCALE == 'iw') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'ja') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'ka') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.kaSelect_;
    -}
    -if (goog.LOCALE == 'kk') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.kkSelect_;
    -}
    -if (goog.LOCALE == 'km') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'kn') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'ko') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'ky') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'ln') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'lo') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.frSelect_;
    -}
    -if (goog.LOCALE == 'lt') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'lv') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'mk') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.mkSelect_;
    -}
    -if (goog.LOCALE == 'ml') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'mn') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'mo') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.frSelect_;
    -}
    -if (goog.LOCALE == 'mr') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.mrSelect_;
    -}
    -if (goog.LOCALE == 'ms') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.frSelect_;
    -}
    -if (goog.LOCALE == 'mt') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'my') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'nb') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'ne') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.neSelect_;
    -}
    -if (goog.LOCALE == 'nl') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'no') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'no_NO' || goog.LOCALE == 'no-NO') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'or') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'pa') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'pl') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'pt') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'pt_BR' || goog.LOCALE == 'pt-BR') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'pt_PT' || goog.LOCALE == 'pt-PT') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'ro') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.frSelect_;
    -}
    -if (goog.LOCALE == 'ru') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'sh') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'si') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'sk') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'sl') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'sq') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.sqSelect_;
    -}
    -if (goog.LOCALE == 'sr') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'sv') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.svSelect_;
    -}
    -if (goog.LOCALE == 'sw') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'ta') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'te') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'th') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'tl') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.frSelect_;
    -}
    -if (goog.LOCALE == 'tr') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'uk') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.ukSelect_;
    -}
    -if (goog.LOCALE == 'ur') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'uz') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'vi') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.frSelect_;
    -}
    -if (goog.LOCALE == 'zh') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'zh_CN' || goog.LOCALE == 'zh-CN') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'zh_HK' || goog.LOCALE == 'zh-HK') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'zh_TW' || goog.LOCALE == 'zh-TW') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'zu') {
    -  goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/pluralrules.js b/src/database/third_party/closure-library/closure/goog/i18n/pluralrules.js
    deleted file mode 100644
    index 78f3c7fb1a9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/pluralrules.js
    +++ /dev/null
    @@ -1,1120 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Plural rules.
    - *
    - * This file is autogenerated by script:
    - *   http://go/generate_pluralrules.py
    - * File generated from CLDR ver. 26
    - *
    - * Before check in, this file could have been manually edited. This is to
    - * incorporate changes before we could fix CLDR. All manual modification must be
    - * documented in this section, and should be removed after those changes land to
    - * CLDR.
    - */
    -
    -goog.provide('goog.i18n.pluralRules');
    -/**
    - * Plural pattern keyword
    - * @enum {string}
    - */
    -goog.i18n.pluralRules.Keyword = {
    -  ZERO: 'zero',
    -  ONE: 'one',
    -  TWO: 'two',
    -  FEW: 'few',
    -  MANY: 'many',
    -  OTHER: 'other'
    -};
    -
    -
    -/**
    - * Default Plural select rule.
    - * @param {number} n The count of items.
    - * @param {number=} opt_precision optional, precision.
    - * @return {goog.i18n.pluralRules.Keyword} Default value.
    - * @private
    - */
    -goog.i18n.pluralRules.defaultSelect_ = function(n, opt_precision) {
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Returns the fractional part of a number (3.1416 => 1416)
    - * @param {number} n The count of items.
    - * @return {number} The fractional part.
    - * @private
    - */
    -goog.i18n.pluralRules.decimals_ = function(n) {
    -  var str = n + '';
    -  var result = str.indexOf('.');
    -  return (result == -1) ? 0 : str.length - result - 1;
    -};
    -
    -/**
    - * Calculates v and f as per CLDR plural rules.
    - * The short names for parameters / return match the CLDR syntax and UTS #35
    - *     (http://unicode.org/reports/tr35/tr35-numbers.html#Plural_rules_syntax)
    - * @param {number} n The count of items.
    - * @param {number=} opt_precision optional, precision.
    - * @return {!Object} The v and f.
    - * @private
    - */
    -goog.i18n.pluralRules.get_vf_ = function(n, opt_precision) {
    -  var DEFAULT_DIGITS = 3;
    -
    -  if (undefined === opt_precision) {
    -    var v = Math.min(goog.i18n.pluralRules.decimals_(n), DEFAULT_DIGITS);
    -  } else {
    -    var v = opt_precision;
    -  }
    -
    -  var base = Math.pow(10, v);
    -  var f = ((n * base) | 0) % base;
    -
    -  return {v: v, f: f};
    -};
    -
    -/**
    - * Calculates w and t as per CLDR plural rules.
    - * The short names for parameters / return match the CLDR syntax and UTS #35
    - *     (http://unicode.org/reports/tr35/tr35-numbers.html#Plural_rules_syntax)
    - * @param {number} v Calculated previously.
    - * @param {number} f Calculated previously.
    - * @return {!Object} The w and t.
    - * @private
    - */
    -goog.i18n.pluralRules.get_wt_ = function(v, f) {
    -  if (f === 0) {
    -    return {w: 0, t: 0};
    -  }
    -
    -  while ((f % 10) === 0) {
    -    f /= 10;
    -    v--;
    -  }
    -
    -  return {w: v, t: f};
    -};
    -
    -/**
    - * Plural select rules for ga locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.gaSelect_ = function(n, opt_precision) {
    -  if (n == 1) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  if (n == 2) {
    -    return goog.i18n.pluralRules.Keyword.TWO;
    -  }
    -  if (n >= 3 && n <= 6) {
    -    return goog.i18n.pluralRules.Keyword.FEW;
    -  }
    -  if (n >= 7 && n <= 10) {
    -    return goog.i18n.pluralRules.Keyword.MANY;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for ro locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.roSelect_ = function(n, opt_precision) {
    -  var i = n | 0;
    -  var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
    -  if (i == 1 && vf.v == 0) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  if (vf.v != 0 || n == 0 || n != 1 && n % 100 >= 1 && n % 100 <= 19) {
    -    return goog.i18n.pluralRules.Keyword.FEW;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for fil locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.filSelect_ = function(n, opt_precision) {
    -  var i = n | 0;
    -  var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
    -  if (vf.v == 0 && (i == 1 || i == 2 || i == 3) || vf.v == 0 && i % 10 != 4 && i % 10 != 6 && i % 10 != 9 || vf.v != 0 && vf.f % 10 != 4 && vf.f % 10 != 6 && vf.f % 10 != 9) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for fr locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.frSelect_ = function(n, opt_precision) {
    -  var i = n | 0;
    -  if (i == 0 || i == 1) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for en locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.enSelect_ = function(n, opt_precision) {
    -  var i = n | 0;
    -  var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
    -  if (i == 1 && vf.v == 0) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for mt locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.mtSelect_ = function(n, opt_precision) {
    -  if (n == 1) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  if (n == 0 || n % 100 >= 2 && n % 100 <= 10) {
    -    return goog.i18n.pluralRules.Keyword.FEW;
    -  }
    -  if (n % 100 >= 11 && n % 100 <= 19) {
    -    return goog.i18n.pluralRules.Keyword.MANY;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for da locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.daSelect_ = function(n, opt_precision) {
    -  var i = n | 0;
    -  var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
    -  var wt = goog.i18n.pluralRules.get_wt_(vf.v, vf.f);
    -  if (n == 1 || wt.t != 0 && (i == 0 || i == 1)) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for gv locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.gvSelect_ = function(n, opt_precision) {
    -  var i = n | 0;
    -  var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
    -  if (vf.v == 0 && i % 10 == 1) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  if (vf.v == 0 && i % 10 == 2) {
    -    return goog.i18n.pluralRules.Keyword.TWO;
    -  }
    -  if (vf.v == 0 && (i % 100 == 0 || i % 100 == 20 || i % 100 == 40 || i % 100 == 60 || i % 100 == 80)) {
    -    return goog.i18n.pluralRules.Keyword.FEW;
    -  }
    -  if (vf.v != 0) {
    -    return goog.i18n.pluralRules.Keyword.MANY;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for cy locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.cySelect_ = function(n, opt_precision) {
    -  if (n == 0) {
    -    return goog.i18n.pluralRules.Keyword.ZERO;
    -  }
    -  if (n == 1) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  if (n == 2) {
    -    return goog.i18n.pluralRules.Keyword.TWO;
    -  }
    -  if (n == 3) {
    -    return goog.i18n.pluralRules.Keyword.FEW;
    -  }
    -  if (n == 6) {
    -    return goog.i18n.pluralRules.Keyword.MANY;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for br locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.brSelect_ = function(n, opt_precision) {
    -  if (n % 10 == 1 && n % 100 != 11 && n % 100 != 71 && n % 100 != 91) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  if (n % 10 == 2 && n % 100 != 12 && n % 100 != 72 && n % 100 != 92) {
    -    return goog.i18n.pluralRules.Keyword.TWO;
    -  }
    -  if ((n % 10 >= 3 && n % 10 <= 4 || n % 10 == 9) && (n % 100 < 10 || n % 100 > 19) && (n % 100 < 70 || n % 100 > 79) && (n % 100 < 90 || n % 100 > 99)) {
    -    return goog.i18n.pluralRules.Keyword.FEW;
    -  }
    -  if (n != 0 && n % 1000000 == 0) {
    -    return goog.i18n.pluralRules.Keyword.MANY;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for es locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.esSelect_ = function(n, opt_precision) {
    -  if (n == 1) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for si locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.siSelect_ = function(n, opt_precision) {
    -  var i = n | 0;
    -  var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
    -  if ((n == 0 || n == 1) || i == 0 && vf.f == 1) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for sl locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.slSelect_ = function(n, opt_precision) {
    -  var i = n | 0;
    -  var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
    -  if (vf.v == 0 && i % 100 == 1) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  if (vf.v == 0 && i % 100 == 2) {
    -    return goog.i18n.pluralRules.Keyword.TWO;
    -  }
    -  if (vf.v == 0 && i % 100 >= 3 && i % 100 <= 4 || vf.v != 0) {
    -    return goog.i18n.pluralRules.Keyword.FEW;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for tzm locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.tzmSelect_ = function(n, opt_precision) {
    -  if (n >= 0 && n <= 1 || n >= 11 && n <= 99) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for sr locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.srSelect_ = function(n, opt_precision) {
    -  var i = n | 0;
    -  var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
    -  if (vf.v == 0 && i % 10 == 1 && i % 100 != 11 || vf.f % 10 == 1 && vf.f % 100 != 11) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14) || vf.f % 10 >= 2 && vf.f % 10 <= 4 && (vf.f % 100 < 12 || vf.f % 100 > 14)) {
    -    return goog.i18n.pluralRules.Keyword.FEW;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for mk locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.mkSelect_ = function(n, opt_precision) {
    -  var i = n | 0;
    -  var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
    -  if (vf.v == 0 && i % 10 == 1 || vf.f % 10 == 1) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for hi locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.hiSelect_ = function(n, opt_precision) {
    -  var i = n | 0;
    -  if (i == 0 || n == 1) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for pt locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.ptSelect_ = function(n, opt_precision) {
    -  if (n >= 0 && n <= 2 && n != 2) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for ar locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.arSelect_ = function(n, opt_precision) {
    -  if (n == 0) {
    -    return goog.i18n.pluralRules.Keyword.ZERO;
    -  }
    -  if (n == 1) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  if (n == 2) {
    -    return goog.i18n.pluralRules.Keyword.TWO;
    -  }
    -  if (n % 100 >= 3 && n % 100 <= 10) {
    -    return goog.i18n.pluralRules.Keyword.FEW;
    -  }
    -  if (n % 100 >= 11 && n % 100 <= 99) {
    -    return goog.i18n.pluralRules.Keyword.MANY;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for iu locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.iuSelect_ = function(n, opt_precision) {
    -  if (n == 1) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  if (n == 2) {
    -    return goog.i18n.pluralRules.Keyword.TWO;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for cs locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.csSelect_ = function(n, opt_precision) {
    -  var i = n | 0;
    -  var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
    -  if (i == 1 && vf.v == 0) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  if (i >= 2 && i <= 4 && vf.v == 0) {
    -    return goog.i18n.pluralRules.Keyword.FEW;
    -  }
    -  if (vf.v != 0) {
    -    return goog.i18n.pluralRules.Keyword.MANY;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for pt_PT locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.pt_PTSelect_ = function(n, opt_precision) {
    -  var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
    -  if (n == 1 && vf.v == 0) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for be locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.beSelect_ = function(n, opt_precision) {
    -  if (n % 10 == 1 && n % 100 != 11) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  if (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14)) {
    -    return goog.i18n.pluralRules.Keyword.FEW;
    -  }
    -  if (n % 10 == 0 || n % 10 >= 5 && n % 10 <= 9 || n % 100 >= 11 && n % 100 <= 14) {
    -    return goog.i18n.pluralRules.Keyword.MANY;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for ak locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.akSelect_ = function(n, opt_precision) {
    -  if (n >= 0 && n <= 1) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for pl locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.plSelect_ = function(n, opt_precision) {
    -  var i = n | 0;
    -  var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
    -  if (i == 1 && vf.v == 0) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14)) {
    -    return goog.i18n.pluralRules.Keyword.FEW;
    -  }
    -  if (vf.v == 0 && i != 1 && i % 10 >= 0 && i % 10 <= 1 || vf.v == 0 && i % 10 >= 5 && i % 10 <= 9 || vf.v == 0 && i % 100 >= 12 && i % 100 <= 14) {
    -    return goog.i18n.pluralRules.Keyword.MANY;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for ru locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.ruSelect_ = function(n, opt_precision) {
    -  var i = n | 0;
    -  var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
    -  if (vf.v == 0 && i % 10 == 1 && i % 100 != 11) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14)) {
    -    return goog.i18n.pluralRules.Keyword.FEW;
    -  }
    -  if (vf.v == 0 && i % 10 == 0 || vf.v == 0 && i % 10 >= 5 && i % 10 <= 9 || vf.v == 0 && i % 100 >= 11 && i % 100 <= 14) {
    -    return goog.i18n.pluralRules.Keyword.MANY;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for lag locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.lagSelect_ = function(n, opt_precision) {
    -  var i = n | 0;
    -  if (n == 0) {
    -    return goog.i18n.pluralRules.Keyword.ZERO;
    -  }
    -  if ((i == 0 || i == 1) && n != 0) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for shi locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.shiSelect_ = function(n, opt_precision) {
    -  var i = n | 0;
    -  if (i == 0 || n == 1) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  if (n >= 2 && n <= 10) {
    -    return goog.i18n.pluralRules.Keyword.FEW;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for he locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.heSelect_ = function(n, opt_precision) {
    -  var i = n | 0;
    -  var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
    -  if (i == 1 && vf.v == 0) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  if (i == 2 && vf.v == 0) {
    -    return goog.i18n.pluralRules.Keyword.TWO;
    -  }
    -  if (vf.v == 0 && (n < 0 || n > 10) && n % 10 == 0) {
    -    return goog.i18n.pluralRules.Keyword.MANY;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for is locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.isSelect_ = function(n, opt_precision) {
    -  var i = n | 0;
    -  var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
    -  var wt = goog.i18n.pluralRules.get_wt_(vf.v, vf.f);
    -  if (wt.t == 0 && i % 10 == 1 && i % 100 != 11 || wt.t != 0) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for lt locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.ltSelect_ = function(n, opt_precision) {
    -  var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
    -  if (n % 10 == 1 && (n % 100 < 11 || n % 100 > 19)) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  if (n % 10 >= 2 && n % 10 <= 9 && (n % 100 < 11 || n % 100 > 19)) {
    -    return goog.i18n.pluralRules.Keyword.FEW;
    -  }
    -  if (vf.f != 0) {
    -    return goog.i18n.pluralRules.Keyword.MANY;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for gd locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.gdSelect_ = function(n, opt_precision) {
    -  if (n == 1 || n == 11) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  if (n == 2 || n == 12) {
    -    return goog.i18n.pluralRules.Keyword.TWO;
    -  }
    -  if (n >= 3 && n <= 10 || n >= 13 && n <= 19) {
    -    return goog.i18n.pluralRules.Keyword.FEW;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for dsb locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.dsbSelect_ = function(n, opt_precision) {
    -  var i = n | 0;
    -  var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
    -  if (vf.v == 0 && i % 100 == 1 || vf.f % 100 == 1) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  if (vf.v == 0 && i % 100 == 2 || vf.f % 100 == 2) {
    -    return goog.i18n.pluralRules.Keyword.TWO;
    -  }
    -  if (vf.v == 0 && i % 100 >= 3 && i % 100 <= 4 || vf.f % 100 >= 3 && vf.f % 100 <= 4) {
    -    return goog.i18n.pluralRules.Keyword.FEW;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for lv locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.lvSelect_ = function(n, opt_precision) {
    -  var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
    -  if (n % 10 == 0 || n % 100 >= 11 && n % 100 <= 19 || vf.v == 2 && vf.f % 100 >= 11 && vf.f % 100 <= 19) {
    -    return goog.i18n.pluralRules.Keyword.ZERO;
    -  }
    -  if (n % 10 == 1 && n % 100 != 11 || vf.v == 2 && vf.f % 10 == 1 && vf.f % 100 != 11 || vf.v != 2 && vf.f % 10 == 1) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Plural select rules for ksh locale
    - *
    - * @param {number} n  The count of items.
    - * @param {number=} opt_precision Precision for number formatting, if not default.
    - * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
    - * @private
    - */
    -goog.i18n.pluralRules.kshSelect_ = function(n, opt_precision) {
    -  if (n == 0) {
    -    return goog.i18n.pluralRules.Keyword.ZERO;
    -  }
    -  if (n == 1) {
    -    return goog.i18n.pluralRules.Keyword.ONE;
    -  }
    -  return goog.i18n.pluralRules.Keyword.OTHER;
    -};
    -
    -/**
    - * Selected Plural rules by locale.
    - */
    -goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
    -if (goog.LOCALE == 'af') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
    -}
    -if (goog.LOCALE == 'am') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.hiSelect_;
    -}
    -if (goog.LOCALE == 'ar') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.arSelect_;
    -}
    -if (goog.LOCALE == 'az') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
    -}
    -if (goog.LOCALE == 'bg') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
    -}
    -if (goog.LOCALE == 'bn') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.hiSelect_;
    -}
    -if (goog.LOCALE == 'br') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.brSelect_;
    -}
    -if (goog.LOCALE == 'ca') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
    -}
    -if (goog.LOCALE == 'chr') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
    -}
    -if (goog.LOCALE == 'cs') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.csSelect_;
    -}
    -if (goog.LOCALE == 'cy') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.cySelect_;
    -}
    -if (goog.LOCALE == 'da') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.daSelect_;
    -}
    -if (goog.LOCALE == 'de') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
    -}
    -if (goog.LOCALE == 'de_AT' || goog.LOCALE == 'de-AT') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
    -}
    -if (goog.LOCALE == 'de_CH' || goog.LOCALE == 'de-CH') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
    -}
    -if (goog.LOCALE == 'el') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
    -}
    -if (goog.LOCALE == 'en') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
    -}
    -if (goog.LOCALE == 'en_AU' || goog.LOCALE == 'en-AU') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
    -}
    -if (goog.LOCALE == 'en_GB' || goog.LOCALE == 'en-GB') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
    -}
    -if (goog.LOCALE == 'en_IE' || goog.LOCALE == 'en-IE') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
    -}
    -if (goog.LOCALE == 'en_IN' || goog.LOCALE == 'en-IN') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
    -}
    -if (goog.LOCALE == 'en_SG' || goog.LOCALE == 'en-SG') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
    -}
    -if (goog.LOCALE == 'en_US' || goog.LOCALE == 'en-US') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
    -}
    -if (goog.LOCALE == 'en_ZA' || goog.LOCALE == 'en-ZA') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
    -}
    -if (goog.LOCALE == 'es') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
    -}
    -if (goog.LOCALE == 'es_419' || goog.LOCALE == 'es-419') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
    -}
    -if (goog.LOCALE == 'es_ES' || goog.LOCALE == 'es-ES') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
    -}
    -if (goog.LOCALE == 'et') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
    -}
    -if (goog.LOCALE == 'eu') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
    -}
    -if (goog.LOCALE == 'fa') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.hiSelect_;
    -}
    -if (goog.LOCALE == 'fi') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
    -}
    -if (goog.LOCALE == 'fil') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.filSelect_;
    -}
    -if (goog.LOCALE == 'fr') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.frSelect_;
    -}
    -if (goog.LOCALE == 'fr_CA' || goog.LOCALE == 'fr-CA') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.frSelect_;
    -}
    -if (goog.LOCALE == 'ga') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.gaSelect_;
    -}
    -if (goog.LOCALE == 'gl') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
    -}
    -if (goog.LOCALE == 'gsw') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
    -}
    -if (goog.LOCALE == 'gu') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.hiSelect_;
    -}
    -if (goog.LOCALE == 'haw') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
    -}
    -if (goog.LOCALE == 'he') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.heSelect_;
    -}
    -if (goog.LOCALE == 'hi') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.hiSelect_;
    -}
    -if (goog.LOCALE == 'hr') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.srSelect_;
    -}
    -if (goog.LOCALE == 'hu') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
    -}
    -if (goog.LOCALE == 'hy') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.frSelect_;
    -}
    -if (goog.LOCALE == 'id') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'in') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'is') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.isSelect_;
    -}
    -if (goog.LOCALE == 'it') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
    -}
    -if (goog.LOCALE == 'iw') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.heSelect_;
    -}
    -if (goog.LOCALE == 'ja') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'ka') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
    -}
    -if (goog.LOCALE == 'kk') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
    -}
    -if (goog.LOCALE == 'km') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'kn') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.hiSelect_;
    -}
    -if (goog.LOCALE == 'ko') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'ky') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
    -}
    -if (goog.LOCALE == 'ln') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.akSelect_;
    -}
    -if (goog.LOCALE == 'lo') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'lt') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.ltSelect_;
    -}
    -if (goog.LOCALE == 'lv') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.lvSelect_;
    -}
    -if (goog.LOCALE == 'mk') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.mkSelect_;
    -}
    -if (goog.LOCALE == 'ml') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
    -}
    -if (goog.LOCALE == 'mn') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
    -}
    -if (goog.LOCALE == 'mo') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.roSelect_;
    -}
    -if (goog.LOCALE == 'mr') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.hiSelect_;
    -}
    -if (goog.LOCALE == 'ms') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'mt') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.mtSelect_;
    -}
    -if (goog.LOCALE == 'my') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'nb') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
    -}
    -if (goog.LOCALE == 'ne') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
    -}
    -if (goog.LOCALE == 'nl') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
    -}
    -if (goog.LOCALE == 'no') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
    -}
    -if (goog.LOCALE == 'no_NO' || goog.LOCALE == 'no-NO') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
    -}
    -if (goog.LOCALE == 'or') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
    -}
    -if (goog.LOCALE == 'pa') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.akSelect_;
    -}
    -if (goog.LOCALE == 'pl') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.plSelect_;
    -}
    -if (goog.LOCALE == 'pt') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.ptSelect_;
    -}
    -if (goog.LOCALE == 'pt_BR' || goog.LOCALE == 'pt-BR') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.ptSelect_;
    -}
    -if (goog.LOCALE == 'pt_PT' || goog.LOCALE == 'pt-PT') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.pt_PTSelect_;
    -}
    -if (goog.LOCALE == 'ro') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.roSelect_;
    -}
    -if (goog.LOCALE == 'ru') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.ruSelect_;
    -}
    -if (goog.LOCALE == 'sh') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.srSelect_;
    -}
    -if (goog.LOCALE == 'si') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.siSelect_;
    -}
    -if (goog.LOCALE == 'sk') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.csSelect_;
    -}
    -if (goog.LOCALE == 'sl') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.slSelect_;
    -}
    -if (goog.LOCALE == 'sq') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
    -}
    -if (goog.LOCALE == 'sr') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.srSelect_;
    -}
    -if (goog.LOCALE == 'sv') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
    -}
    -if (goog.LOCALE == 'sw') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
    -}
    -if (goog.LOCALE == 'ta') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
    -}
    -if (goog.LOCALE == 'te') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
    -}
    -if (goog.LOCALE == 'th') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'tl') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.filSelect_;
    -}
    -if (goog.LOCALE == 'tr') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
    -}
    -if (goog.LOCALE == 'uk') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.ruSelect_;
    -}
    -if (goog.LOCALE == 'ur') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
    -}
    -if (goog.LOCALE == 'uz') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
    -}
    -if (goog.LOCALE == 'vi') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'zh') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'zh_CN' || goog.LOCALE == 'zh-CN') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'zh_HK' || goog.LOCALE == 'zh-HK') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'zh_TW' || goog.LOCALE == 'zh-TW') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.defaultSelect_;
    -}
    -if (goog.LOCALE == 'zu') {
    -  goog.i18n.pluralRules.select = goog.i18n.pluralRules.hiSelect_;
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/pluralrules_test.html b/src/database/third_party/closure-library/closure/goog/i18n/pluralrules_test.html
    deleted file mode 100644
    index 0f546de80ad..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/pluralrules_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.i18n.pluralRules
    -  </title>
    -  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.i18n.pluralRulesTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/pluralrules_test.js b/src/database/third_party/closure-library/closure/goog/i18n/pluralrules_test.js
    deleted file mode 100644
    index 75d5eafe686..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/pluralrules_test.js
    +++ /dev/null
    @@ -1,102 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.i18n.pluralRulesTest');
    -goog.setTestOnly('goog.i18n.pluralRulesTest');
    -
    -goog.require('goog.i18n.pluralRules');
    -goog.require('goog.testing.jsunit');
    -
    -
    -/** @suppress {missingRequire} */
    -var Keyword = goog.i18n.pluralRules.Keyword;
    -
    -function testSimpleSelectEn() {
    -  var funcSelect = goog.i18n.pluralRules.enSelect_;
    -
    -  assertEquals(Keyword.OTHER, funcSelect(0)); // 0 dollars
    -  assertEquals(Keyword.ONE, funcSelect(1)); // 1 dollar
    -  assertEquals(Keyword.OTHER, funcSelect(2)); // 2 dollars
    -
    -  assertEquals(Keyword.OTHER, funcSelect(0, 2)); // 0.00 dollars
    -  assertEquals(Keyword.OTHER, funcSelect(1, 2)); // 1.00 dollars
    -  assertEquals(Keyword.OTHER, funcSelect(2, 2)); // 2.00 dollars
    -}
    -
    -function testSimpleSelectRo() {
    -  var funcSelect = goog.i18n.pluralRules.roSelect_;
    -
    -  assertEquals(Keyword.FEW, funcSelect(0)); // 0 dolari
    -  assertEquals(Keyword.ONE, funcSelect(1)); // 1 dolar
    -  assertEquals(Keyword.FEW, funcSelect(2)); // 2 dolari
    -  assertEquals(Keyword.FEW, funcSelect(12)); // 12 dolari
    -  assertEquals(Keyword.OTHER, funcSelect(23)); // 23 de dolari
    -  assertEquals(Keyword.FEW, funcSelect(1212)); // 1212 dolari
    -  assertEquals(Keyword.OTHER, funcSelect(1223)); // 1223 de dolari
    -
    -  assertEquals(Keyword.FEW, funcSelect(0, 2)); // 0.00 dolari
    -  assertEquals(Keyword.FEW, funcSelect(1, 2)); // 1.00 dolari
    -  assertEquals(Keyword.FEW, funcSelect(2, 2)); // 2.00 dolari
    -  assertEquals(Keyword.FEW, funcSelect(12, 2)); // 12.00 dolari
    -  assertEquals(Keyword.FEW, funcSelect(23, 2)); // 23.00  dolari
    -  assertEquals(Keyword.FEW, funcSelect(1212, 2)); // 1212.00  dolari
    -  assertEquals(Keyword.FEW, funcSelect(1223, 2)); // 1223.00 dolari
    -}
    -
    -function testSimpleSelectSr() {
    -  var funcSelect = goog.i18n.pluralRules.srSelect_; // Serbian
    -
    -  assertEquals(Keyword.ONE, funcSelect(1));
    -  assertEquals(Keyword.ONE, funcSelect(31));
    -  assertEquals(Keyword.ONE, funcSelect(0.1));
    -  assertEquals(Keyword.ONE, funcSelect(1.1));
    -  assertEquals(Keyword.ONE, funcSelect(2.1));
    -
    -  assertEquals(Keyword.FEW, funcSelect(3));
    -  assertEquals(Keyword.FEW, funcSelect(33));
    -  assertEquals(Keyword.FEW, funcSelect(0.2));
    -  assertEquals(Keyword.FEW, funcSelect(0.3));
    -  assertEquals(Keyword.FEW, funcSelect(0.4));
    -  assertEquals(Keyword.FEW, funcSelect(2.2));
    -
    -  assertEquals(Keyword.OTHER, funcSelect(2.11));
    -  assertEquals(Keyword.OTHER, funcSelect(2.12));
    -  assertEquals(Keyword.OTHER, funcSelect(2.13));
    -  assertEquals(Keyword.OTHER, funcSelect(2.14));
    -  assertEquals(Keyword.OTHER, funcSelect(2.15));
    -
    -  assertEquals(Keyword.OTHER, funcSelect(0));
    -  assertEquals(Keyword.OTHER, funcSelect(5));
    -  assertEquals(Keyword.OTHER, funcSelect(10));
    -  assertEquals(Keyword.OTHER, funcSelect(35));
    -  assertEquals(Keyword.OTHER, funcSelect(37));
    -  assertEquals(Keyword.OTHER, funcSelect(40));
    -  assertEquals(Keyword.OTHER, funcSelect(0.0, 1));
    -  assertEquals(Keyword.OTHER, funcSelect(0.5));
    -  assertEquals(Keyword.OTHER, funcSelect(0.6));
    -
    -  assertEquals(Keyword.FEW, funcSelect(2));
    -  assertEquals(Keyword.ONE, funcSelect(2.1));
    -  assertEquals(Keyword.FEW, funcSelect(2.2));
    -  assertEquals(Keyword.FEW, funcSelect(2.3));
    -  assertEquals(Keyword.FEW, funcSelect(2.4));
    -  assertEquals(Keyword.OTHER, funcSelect(2.5));
    -
    -  assertEquals(Keyword.OTHER, funcSelect(20));
    -  assertEquals(Keyword.ONE, funcSelect(21));
    -  assertEquals(Keyword.FEW, funcSelect(22));
    -  assertEquals(Keyword.FEW, funcSelect(23));
    -  assertEquals(Keyword.FEW, funcSelect(24));
    -  assertEquals(Keyword.OTHER, funcSelect(25));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/timezone.js b/src/database/third_party/closure-library/closure/goog/i18n/timezone.js
    deleted file mode 100644
    index 8123beda545..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/timezone.js
    +++ /dev/null
    @@ -1,341 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Functions to provide timezone information for use with
    - * date/time format.
    - */
    -
    -goog.provide('goog.i18n.TimeZone');
    -
    -goog.require('goog.array');
    -goog.require('goog.date.DateLike');
    -goog.require('goog.string');
    -
    -
    -
    -/**
    - * TimeZone class implemented a time zone resolution and name information
    - * source for client applications. The time zone object is initiated from
    - * a time zone information object. Application can initiate a time zone
    - * statically, or it may choose to initiate from a data obtained from server.
    - * Each time zone information array is small, but the whole set of data
    - * is too much for client application to download. If end user is allowed to
    - * change time zone setting, dynamic retrieval should be the method to use.
    - * In case only time zone offset is known, there is a decent fallback
    - * that only use the time zone offset to create a TimeZone object.
    - * A whole set of time zone information array was available under
    - * http://go/js_locale_data. It is generated based on CLDR and
    - * Olson time zone data base (through pytz), and will be updated timely.
    - *
    - * @constructor
    - * @final
    - */
    -goog.i18n.TimeZone = function() {
    -  /**
    -   * The standard time zone id.
    -   * @type {string}
    -   * @private
    -   */
    -  this.timeZoneId_;
    -
    -
    -  /**
    -   * The standard, non-daylight time zone offset, in minutes WEST of UTC.
    -   * @type {number}
    -   * @private
    -   */
    -  this.standardOffset_;
    -
    -
    -  /**
    -   * An array of strings that can have 2 or 4 elements.  The first two elements
    -   * are the long and short names for standard time in this time zone, and the
    -   * last two elements (if present) are the long and short names for daylight
    -   * time in this time zone.
    -   * @type {Array<string>}
    -   * @private
    -   */
    -  this.tzNames_;
    -
    -
    -  /**
    -   * This array specifies the Daylight Saving Time transitions for this time
    -   * zone.  This is a flat array of numbers which are interpreted in pairs:
    -   * [time1, adjustment1, time2, adjustment2, ...] where each time is a DST
    -   * transition point given as a number of hours since 00:00 UTC, January 1,
    -   * 1970, and each adjustment is the adjustment to apply for times after the
    -   * DST transition, given as minutes EAST of UTC.
    -   * @type {Array<number>}
    -   * @private
    -   */
    -  this.transitions_;
    -};
    -
    -
    -/**
    - * The number of milliseconds in an hour.
    - * @type {number}
    - * @private
    - */
    -goog.i18n.TimeZone.MILLISECONDS_PER_HOUR_ = 3600 * 1000;
    -
    -
    -/**
    - * Indices into the array of time zone names.
    - * @enum {number}
    - */
    -goog.i18n.TimeZone.NameType = {
    -  STD_SHORT_NAME: 0,
    -  STD_LONG_NAME: 1,
    -  DLT_SHORT_NAME: 2,
    -  DLT_LONG_NAME: 3
    -};
    -
    -
    -/**
    - * This factory method creates a time zone instance.  It takes either an object
    - * containing complete time zone information, or a single number representing a
    - * constant time zone offset.  If the latter form is used, DST functionality is
    - * not available.
    - *
    - * @param {number|Object} timeZoneData If this parameter is a number, it should
    - *     indicate minutes WEST of UTC to be used as a constant time zone offset.
    - *     Otherwise, it should be an object with these four fields:
    - *     <ul>
    - *     <li>id: A string ID for the time zone.
    - *     <li>std_offset: The standard time zone offset in minutes EAST of UTC.
    - *     <li>names: An array of four names (standard short name, standard long
    - *           name, daylight short name, daylight long, name)
    - *     <li>transitions: An array of numbers which are interpreted in pairs:
    - *           [time1, adjustment1, time2, adjustment2, ...] where each time is
    - *           a DST transition point given as a number of hours since 00:00 UTC,
    - *           January 1, 1970, and each adjustment is the adjustment to apply
    - *           for times after the DST transition, given as minutes EAST of UTC.
    - *     </ul>
    - * @return {!goog.i18n.TimeZone} A goog.i18n.TimeZone object for the given
    - *     time zone data.
    - */
    -goog.i18n.TimeZone.createTimeZone = function(timeZoneData) {
    -  if (typeof timeZoneData == 'number') {
    -    return goog.i18n.TimeZone.createSimpleTimeZone_(timeZoneData);
    -  }
    -  var tz = new goog.i18n.TimeZone();
    -  tz.timeZoneId_ = timeZoneData['id'];
    -  tz.standardOffset_ = -timeZoneData['std_offset'];
    -  tz.tzNames_ = timeZoneData['names'];
    -  tz.transitions_ = timeZoneData['transitions'];
    -  return tz;
    -};
    -
    -
    -/**
    - * This factory method creates a time zone object with a constant offset.
    - * @param {number} timeZoneOffsetInMinutes Offset in minutes WEST of UTC.
    - * @return {!goog.i18n.TimeZone} A time zone object with the given constant
    - *     offset.  Note that the time zone ID of this object will use the POSIX
    - *     convention, which has a reversed sign ("Etc/GMT+8" means UTC-8 or PST).
    - * @private
    - */
    -goog.i18n.TimeZone.createSimpleTimeZone_ = function(timeZoneOffsetInMinutes) {
    -  var tz = new goog.i18n.TimeZone();
    -  tz.standardOffset_ = timeZoneOffsetInMinutes;
    -  tz.timeZoneId_ =
    -      goog.i18n.TimeZone.composePosixTimeZoneID_(timeZoneOffsetInMinutes);
    -  var str = goog.i18n.TimeZone.composeUTCString_(timeZoneOffsetInMinutes);
    -  tz.tzNames_ = [str, str];
    -  tz.transitions_ = [];
    -  return tz;
    -};
    -
    -
    -/**
    - * Generate a GMT-relative string for a constant time zone offset.
    - * @param {number} offset The time zone offset in minutes WEST of UTC.
    - * @return {string} The GMT string for this offset, which will indicate
    - *     hours EAST of UTC.
    - * @private
    - */
    -goog.i18n.TimeZone.composeGMTString_ = function(offset) {
    -  var parts = ['GMT'];
    -  parts.push(offset <= 0 ? '+' : '-');
    -  offset = Math.abs(offset);
    -  parts.push(goog.string.padNumber(Math.floor(offset / 60) % 100, 2),
    -             ':', goog.string.padNumber(offset % 60, 2));
    -  return parts.join('');
    -};
    -
    -
    -/**
    - * Generate a POSIX time zone ID for a constant time zone offset.
    - * @param {number} offset The time zone offset in minutes WEST of UTC.
    - * @return {string} The POSIX time zone ID for this offset, which will indicate
    - *     hours WEST of UTC.
    - * @private
    - */
    -goog.i18n.TimeZone.composePosixTimeZoneID_ = function(offset) {
    -  if (offset == 0) {
    -    return 'Etc/GMT';
    -  }
    -  var parts = ['Etc/GMT', offset < 0 ? '-' : '+'];
    -  offset = Math.abs(offset);
    -  parts.push(Math.floor(offset / 60) % 100);
    -  offset = offset % 60;
    -  if (offset != 0) {
    -    parts.push(':', goog.string.padNumber(offset, 2));
    -  }
    -  return parts.join('');
    -};
    -
    -
    -/**
    - * Generate a UTC-relative string for a constant time zone offset.
    - * @param {number} offset The time zone offset in minutes WEST of UTC.
    - * @return {string} The UTC string for this offset, which will indicate
    - *     hours EAST of UTC.
    - * @private
    - */
    -goog.i18n.TimeZone.composeUTCString_ = function(offset) {
    -  if (offset == 0) {
    -    return 'UTC';
    -  }
    -  var parts = ['UTC', offset < 0 ? '+' : '-'];
    -  offset = Math.abs(offset);
    -  parts.push(Math.floor(offset / 60) % 100);
    -  offset = offset % 60;
    -  if (offset != 0) {
    -    parts.push(':', offset);
    -  }
    -  return parts.join('');
    -};
    -
    -
    -/**
    - * Convert the contents of time zone object to a timeZoneData object, suitable
    - * for passing to goog.i18n.TimeZone.createTimeZone.
    - * @return {!Object} A timeZoneData object (see the documentation for
    - *     goog.i18n.TimeZone.createTimeZone).
    - */
    -goog.i18n.TimeZone.prototype.getTimeZoneData = function() {
    -  return {
    -    'id': this.timeZoneId_,
    -    'std_offset': -this.standardOffset_,  // note createTimeZone flips the sign
    -    'names': goog.array.clone(this.tzNames_),  // avoid aliasing the array
    -    'transitions': goog.array.clone(this.transitions_)  // avoid aliasing
    -  };
    -};
    -
    -
    -/**
    - * Return the DST adjustment to the time zone offset for a given time.
    - * While Daylight Saving Time is in effect, this number is positive.
    - * Otherwise, it is zero.
    - * @param {goog.date.DateLike} date The time to check.
    - * @return {number} The DST adjustment in minutes EAST of UTC.
    - */
    -goog.i18n.TimeZone.prototype.getDaylightAdjustment = function(date) {
    -  var timeInMs = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(),
    -                          date.getUTCDate(), date.getUTCHours(),
    -                          date.getUTCMinutes());
    -  var timeInHours = timeInMs / goog.i18n.TimeZone.MILLISECONDS_PER_HOUR_;
    -  var index = 0;
    -  while (index < this.transitions_.length &&
    -         timeInHours >= this.transitions_[index]) {
    -    index += 2;
    -  }
    -  return (index == 0) ? 0 : this.transitions_[index - 1];
    -};
    -
    -
    -/**
    - * Return the GMT representation of this time zone object.
    - * @param {goog.date.DateLike} date The date for which time to retrieve
    - *     GMT string.
    - * @return {string} GMT representation string.
    - */
    -goog.i18n.TimeZone.prototype.getGMTString = function(date) {
    -  return goog.i18n.TimeZone.composeGMTString_(this.getOffset(date));
    -};
    -
    -
    -/**
    - * Get the long time zone name for a given date/time.
    - * @param {goog.date.DateLike} date The time for which to retrieve
    - *     the long time zone name.
    - * @return {string} The long time zone name.
    - */
    -goog.i18n.TimeZone.prototype.getLongName = function(date) {
    -  return this.tzNames_[this.isDaylightTime(date) ?
    -      goog.i18n.TimeZone.NameType.DLT_LONG_NAME :
    -      goog.i18n.TimeZone.NameType.STD_LONG_NAME];
    -};
    -
    -
    -/**
    - * Get the time zone offset in minutes WEST of UTC for a given date/time.
    - * @param {goog.date.DateLike} date The time for which to retrieve
    - *     the time zone offset.
    - * @return {number} The time zone offset in minutes WEST of UTC.
    - */
    -goog.i18n.TimeZone.prototype.getOffset = function(date) {
    -  return this.standardOffset_ - this.getDaylightAdjustment(date);
    -};
    -
    -
    -/**
    - * Get the RFC representation of the time zone for a given date/time.
    - * @param {goog.date.DateLike} date The time for which to retrieve the
    - *     RFC time zone string.
    - * @return {string} The RFC time zone string.
    - */
    -goog.i18n.TimeZone.prototype.getRFCTimeZoneString = function(date) {
    -  var offset = -this.getOffset(date);
    -  var parts = [offset < 0 ? '-' : '+'];
    -  offset = Math.abs(offset);
    -  parts.push(goog.string.padNumber(Math.floor(offset / 60) % 100, 2),
    -             goog.string.padNumber(offset % 60, 2));
    -  return parts.join('');
    -};
    -
    -
    -/**
    - * Get the short time zone name for given date/time.
    - * @param {goog.date.DateLike} date The time for which to retrieve
    - *     the short time zone name.
    - * @return {string} The short time zone name.
    - */
    -goog.i18n.TimeZone.prototype.getShortName = function(date) {
    -  return this.tzNames_[this.isDaylightTime(date) ?
    -      goog.i18n.TimeZone.NameType.DLT_SHORT_NAME :
    -      goog.i18n.TimeZone.NameType.STD_SHORT_NAME];
    -};
    -
    -
    -/**
    - * Return the time zone ID for this time zone.
    - * @return {string} The time zone ID.
    - */
    -goog.i18n.TimeZone.prototype.getTimeZoneId = function() {
    -  return this.timeZoneId_;
    -};
    -
    -
    -/**
    - * Check if Daylight Saving Time is in effect at a given time in this time zone.
    - * @param {goog.date.DateLike} date The time to check.
    - * @return {boolean} True if Daylight Saving Time is in effect.
    - */
    -goog.i18n.TimeZone.prototype.isDaylightTime = function(date) {
    -  return this.getDaylightAdjustment(date) > 0;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/timezone_test.html b/src/database/third_party/closure-library/closure/goog/i18n/timezone_test.html
    deleted file mode 100644
    index 94e6132c83f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/timezone_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.i18n.TimeZone
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.i18n.TimeZoneTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/timezone_test.js b/src/database/third_party/closure-library/closure/goog/i18n/timezone_test.js
    deleted file mode 100644
    index 3acef6cf34e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/timezone_test.js
    +++ /dev/null
    @@ -1,160 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.i18n.TimeZoneTest');
    -goog.setTestOnly('goog.i18n.TimeZoneTest');
    -
    -goog.require('goog.i18n.TimeZone');
    -goog.require('goog.testing.jsunit');
    -
    -// Where could such data be found
    -// In js_i18n_data in http://go/i18n_dir, we have a bunch of files with names
    -// like TimeZoneConstant__<locale>.js
    -// We strongly discourage you to use them directly as those data can make
    -// your client code bloated. You should try to provide this data from server
    -// in a selective manner. In typical scenario, user's time zone is retrieved
    -// and only data for that time zone should be provided.
    -// This piece of data is in JSON format. It requires double quote.
    -var americaLosAngelesData = {
    -  'transitions': [
    -    2770, 60, 7137, 0, 11506, 60, 16041, 0, 20410, 60, 24777, 0, 29146, 60,
    -    33513, 0, 35194, 60, 42249, 0, 45106, 60, 50985, 0, 55354, 60, 59889, 0,
    -    64090, 60, 68625, 0, 72994, 60, 77361, 0, 81730, 60, 86097, 0, 90466, 60,
    -    94833, 0, 99202, 60, 103569, 0, 107938, 60, 112473, 0, 116674, 60, 121209,
    -    0, 125578, 60, 129945, 0, 134314, 60, 138681, 0, 143050, 60, 147417, 0,
    -    151282, 60, 156153, 0, 160018, 60, 165057, 0, 168754, 60, 173793, 0,
    -    177490, 60, 182529, 0, 186394, 60, 191265, 0, 195130, 60, 200001, 0,
    -    203866, 60, 208905, 0, 212602, 60, 217641, 0, 221338, 60, 226377, 0,
    -    230242, 60, 235113, 0, 238978, 60, 243849, 0, 247714, 60, 252585, 0,
    -    256450, 60, 261489, 0, 265186, 60, 270225, 0, 273922, 60, 278961, 0,
    -    282826, 60, 287697, 0, 291562, 60, 296433, 0, 300298, 60, 305337, 0,
    -    309034, 60, 314073, 0, 317770, 60, 322809, 0, 326002, 60, 331713, 0,
    -    334738, 60, 340449, 0, 343474, 60, 349185, 0, 352378, 60, 358089, 0,
    -    361114, 60, 366825, 0, 369850, 60, 375561, 0, 378586, 60, 384297, 0,
    -    387322, 60, 393033, 0, 396058, 60, 401769, 0, 404962, 60, 410673, 0,
    -    413698, 60, 419409, 0, 422434, 60, 428145, 0, 431170, 60, 436881, 0,
    -    439906, 60, 445617, 0, 448810, 60, 454521, 0, 457546, 60, 463257, 0,
    -    466282, 60, 471993, 0, 475018, 60, 480729, 0, 483754, 60, 489465, 0,
    -    492490, 60, 498201, 0, 501394, 60, 507105, 0, 510130, 60, 515841, 0,
    -    518866, 60, 524577, 0, 527602, 60, 533313, 0, 536338, 60, 542049, 0,
    -    545242, 60, 550953, 0, 553978, 60, 559689, 0, 562714, 60, 568425, 0,
    -    571450, 60, 577161, 0, 580186, 60, 585897, 0, 588922, 60, 594633, 0
    -  ],
    -  'names': ['PST', 'Pacific Standard Time', 'PDT', 'Pacific Daylight Time'],
    -  'id': 'America/Los_Angeles',
    -  'std_offset': -480
    -};
    -
    -function testIsDaylightTime() {
    -  var usPacific = goog.i18n.TimeZone.createTimeZone(americaLosAngelesData);
    -  var dt = new Date(2007, 7 - 1, 1);
    -  assertTrue(usPacific.isDaylightTime(dt));
    -  // 2007/03/11 2:00am has daylight change. We set time through UTC so that
    -  // this test won't be affected by browser's local time handling.
    -  dt = new Date(2007, 3 - 1, 11);
    -  // The date above is created with a timezone of the computer it is run on.
    -  // Therefore the UTC day has to be set explicitly to be sure that the date
    -  // is correct for timezones east of Greenwich  where 2007/3/11 0:00 is still
    -  // 2007/03/10 in UTC.
    -  dt.setUTCDate(11);
    -  dt.setUTCHours(2 + 8);
    -  dt.setUTCMinutes(1);
    -  assertTrue(usPacific.isDaylightTime(dt));
    -  dt.setUTCHours(1 + 8);
    -  dt.setUTCMinutes(59);
    -  assertTrue(!usPacific.isDaylightTime(dt));
    -
    -  dt = new Date(2007, 11 - 1, 4);
    -  // Set the UTC day explicitly to make it work in timezones east of
    -  // Greenwich.
    -  dt.setUTCDate(4);
    -  dt.setUTCHours(2 + 7);
    -  dt.setUTCMinutes(1);
    -  assertTrue(!usPacific.isDaylightTime(dt));
    -
    -  // there seems to be a browser bug. local time 1:59am should still be PDT.
    -  dt.setUTCHours(0 + 7);
    -  dt.setUTCMinutes(59);
    -  assertTrue(usPacific.isDaylightTime(dt));
    -}
    -
    -function testGetters() {
    -  var date = new Date();
    -  var usPacific = goog.i18n.TimeZone.createTimeZone(americaLosAngelesData);
    -  if (usPacific.isDaylightTime(date)) {
    -    assertEquals(420, usPacific.getOffset(date));
    -  } else {
    -    assertEquals(480, usPacific.getOffset(date));
    -  }
    -  assertEquals('America/Los_Angeles', usPacific.getTimeZoneId());
    -  assertObjectEquals(americaLosAngelesData, usPacific.getTimeZoneData());
    -}
    -
    -function testNames() {
    -  var usPacific = goog.i18n.TimeZone.createTimeZone(americaLosAngelesData);
    -  var dt = new Date(2007, 7 - 1, 1);
    -  assertTrue(usPacific.isDaylightTime(dt));
    -  assertEquals('PDT', usPacific.getShortName(dt));
    -  assertEquals('Pacific Daylight Time', usPacific.getLongName(dt));
    -
    -  dt = new Date(2007, 12 - 1, 1);
    -  assertTrue(!usPacific.isDaylightTime(dt));
    -  assertEquals('PST', usPacific.getShortName(dt));
    -  assertEquals('Pacific Standard Time', usPacific.getLongName(dt));
    -}
    -
    -function testSimpleTimeZonePositive() {
    -  var date = new Date();
    -  var simpleTimeZone = goog.i18n.TimeZone.createTimeZone(480);
    -  assertEquals(480, simpleTimeZone.getOffset(date));
    -  assertEquals('GMT-08:00', simpleTimeZone.getGMTString(date));
    -  assertEquals('Etc/GMT+8', simpleTimeZone.getTimeZoneId());
    -  assertEquals('UTC-8', simpleTimeZone.getLongName(date));
    -  assertEquals('UTC-8', simpleTimeZone.getShortName(date));
    -  assertEquals('-0800', simpleTimeZone.getRFCTimeZoneString(date));
    -  assertEquals(false, simpleTimeZone.isDaylightTime(date));
    -
    -  simpleTimeZone = goog.i18n.TimeZone.createTimeZone(630);
    -  assertEquals(630, simpleTimeZone.getOffset(date));
    -  assertEquals('GMT-10:30', simpleTimeZone.getGMTString(date));
    -  assertEquals('Etc/GMT+10:30', simpleTimeZone.getTimeZoneId());
    -  assertEquals('UTC-10:30', simpleTimeZone.getLongName(date));
    -  assertEquals('UTC-10:30', simpleTimeZone.getShortName(date));
    -  assertEquals('-1030', simpleTimeZone.getRFCTimeZoneString(date));
    -  assertEquals(false, simpleTimeZone.isDaylightTime(date));
    -}
    -
    -function testSimpleTimeZoneNegative() {
    -  var date = new Date();
    -  var simpleTimeZone = goog.i18n.TimeZone.createTimeZone(-480);
    -  assertEquals(-480, simpleTimeZone.getOffset(date));
    -  assertEquals('GMT+08:00', simpleTimeZone.getGMTString(date));
    -  assertEquals('Etc/GMT-8', simpleTimeZone.getTimeZoneId());
    -  assertEquals('UTC+8', simpleTimeZone.getLongName(date));
    -  assertEquals('UTC+8', simpleTimeZone.getShortName(date));
    -  assertEquals('+0800', simpleTimeZone.getRFCTimeZoneString(date));
    -  assertEquals(false, simpleTimeZone.isDaylightTime(date));
    -}
    -
    -function testSimpleTimeZoneZero() {
    -  var date = new Date();
    -  var simpleTimeZone = goog.i18n.TimeZone.createTimeZone(0);
    -  assertEquals(0, simpleTimeZone.getOffset(date));
    -  assertEquals('GMT+00:00', simpleTimeZone.getGMTString(date));
    -  assertEquals('Etc/GMT', simpleTimeZone.getTimeZoneId());
    -  assertEquals('UTC', simpleTimeZone.getLongName(date));
    -  assertEquals('UTC', simpleTimeZone.getShortName(date));
    -  assertEquals('+0000', simpleTimeZone.getRFCTimeZoneString(date));
    -  assertEquals(false, simpleTimeZone.isDaylightTime(date));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/uchar.js b/src/database/third_party/closure-library/closure/goog/i18n/uchar.js
    deleted file mode 100644
    index b4568ab3128..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/uchar.js
    +++ /dev/null
    @@ -1,1368 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Collection of utility functions for Unicode character.
    - *
    - */
    -
    -goog.provide('goog.i18n.uChar');
    -
    -
    -/**
    - * Map used for looking up the char data.  Will be created lazily.
    - * @type {Object}
    - * @private
    - */
    -goog.i18n.uChar.charData_ = null;
    -
    -
    -// Constants for handling Unicode supplementary characters (surrogate pairs).
    -
    -
    -/**
    - * The minimum value for Supplementary code points.
    - * @type {number}
    - * @private
    - */
    -goog.i18n.uChar.SUPPLEMENTARY_CODE_POINT_MIN_VALUE_ = 0x10000;
    -
    -
    -/**
    - * The highest Unicode code point value (scalar value) according to the Unicode
    - * Standard.
    - * @type {number}
    - * @private
    - */
    -goog.i18n.uChar.CODE_POINT_MAX_VALUE_ = 0x10FFFF;
    -
    -
    -/**
    - * Lead surrogate minimum value.
    - * @type {number}
    - * @private
    - */
    -goog.i18n.uChar.LEAD_SURROGATE_MIN_VALUE_ = 0xD800;
    -
    -
    -/**
    - * Lead surrogate maximum value.
    - * @type {number}
    - * @private
    - */
    -goog.i18n.uChar.LEAD_SURROGATE_MAX_VALUE_ = 0xDBFF;
    -
    -
    -/**
    - * Trail surrogate minimum value.
    - * @type {number}
    - * @private
    - */
    -goog.i18n.uChar.TRAIL_SURROGATE_MIN_VALUE_ = 0xDC00;
    -
    -
    -/**
    - * Trail surrogate maximum value.
    - * @type {number}
    - * @private
    - */
    -goog.i18n.uChar.TRAIL_SURROGATE_MAX_VALUE_ = 0xDFFF;
    -
    -
    -/**
    - * The number of least significant bits of a supplementary code point that in
    - * UTF-16 become the least significant bits of the trail surrogate. The rest of
    - * the in-use bits of the supplementary code point become the least significant
    - * bits of the lead surrogate.
    - * @type {number}
    - * @private
    - */
    -goog.i18n.uChar.TRAIL_SURROGATE_BIT_COUNT_ = 10;
    -
    -
    -/**
    - * Gets the U+ notation string of a Unicode character. Ex: 'U+0041' for 'A'.
    - * @param {string} ch The given character.
    - * @return {string} The U+ notation of the given character.
    - */
    -goog.i18n.uChar.toHexString = function(ch) {
    -  var chCode = goog.i18n.uChar.toCharCode(ch);
    -  var chCodeStr = 'U+' + goog.i18n.uChar.padString_(
    -      chCode.toString(16).toUpperCase(), 4, '0');
    -
    -  return chCodeStr;
    -};
    -
    -
    -/**
    - * Gets a string padded with given character to get given size.
    - * @param {string} str The given string to be padded.
    - * @param {number} length The target size of the string.
    - * @param {string} ch The character to be padded with.
    - * @return {string} The padded string.
    - * @private
    - */
    -goog.i18n.uChar.padString_ = function(str, length, ch) {
    -  while (str.length < length) {
    -    str = ch + str;
    -  }
    -  return str;
    -};
    -
    -
    -/**
    - * Gets Unicode value of the given character.
    - * @param {string} ch The given character, which in the case of a supplementary
    - * character is actually a surrogate pair. The remainder of the string is
    - * ignored.
    - * @return {number} The Unicode value of the character.
    - */
    -goog.i18n.uChar.toCharCode = function(ch) {
    -  return goog.i18n.uChar.getCodePointAround(ch, 0);
    -};
    -
    -
    -/**
    - * Gets a character from the given Unicode value. If the given code point is not
    - * a valid Unicode code point, null is returned.
    - * @param {number} code The Unicode value of the character.
    - * @return {?string} The character corresponding to the given Unicode value.
    - */
    -goog.i18n.uChar.fromCharCode = function(code) {
    -  if (!goog.isDefAndNotNull(code) ||
    -      !(code >= 0 && code <= goog.i18n.uChar.CODE_POINT_MAX_VALUE_)) {
    -    return null;
    -  }
    -  if (goog.i18n.uChar.isSupplementaryCodePoint(code)) {
    -    // First, we split the code point into the trail surrogate part (the
    -    // TRAIL_SURROGATE_BIT_COUNT_ least significant bits) and the lead surrogate
    -    // part (the rest of the bits, shifted down; note that for now this includes
    -    // the supplementary offset, also shifted down, to be subtracted off below).
    -    var leadBits = code >> goog.i18n.uChar.TRAIL_SURROGATE_BIT_COUNT_;
    -    var trailBits = code &
    -        // A bit-mask to get the TRAIL_SURROGATE_BIT_COUNT_ (i.e. 10) least
    -        // significant bits. 1 << 10 = 0x0400. 0x0400 - 1 = 0x03FF.
    -        ((1 << goog.i18n.uChar.TRAIL_SURROGATE_BIT_COUNT_) - 1);
    -
    -    // Now we calculate the code point of each surrogate by adding each offset
    -    // to the corresponding base code point.
    -    var leadCodePoint = leadBits + (goog.i18n.uChar.LEAD_SURROGATE_MIN_VALUE_ -
    -        // Subtract off the supplementary offset, which had been shifted down
    -        // with the rest of leadBits. We do this here instead of before the
    -        // shift in order to save a separate subtraction step.
    -        (goog.i18n.uChar.SUPPLEMENTARY_CODE_POINT_MIN_VALUE_ >>
    -        goog.i18n.uChar.TRAIL_SURROGATE_BIT_COUNT_));
    -    var trailCodePoint = trailBits + goog.i18n.uChar.TRAIL_SURROGATE_MIN_VALUE_;
    -
    -    // Convert the code points into a 2-character long string.
    -    return String.fromCharCode(leadCodePoint) +
    -           String.fromCharCode(trailCodePoint);
    -  }
    -  return String.fromCharCode(code);
    -};
    -
    -
    -/**
    - * Returns the Unicode code point at the specified index.
    - *
    - * If the char value specified at the given index is in the leading-surrogate
    - * range, and the following index is less than the length of {@code string}, and
    - * the char value at the following index is in the trailing-surrogate range,
    - * then the supplementary code point corresponding to this surrogate pair is
    - * returned.
    - *
    - * If the char value specified at the given index is in the trailing-surrogate
    - * range, and the preceding index is not before the start of {@code string}, and
    - * the char value at the preceding index is in the leading-surrogate range, then
    - * the negated supplementary code point corresponding to this surrogate pair is
    - * returned.
    - *
    - * The negation allows the caller to differentiate between the case where the
    - * given index is at the leading surrogate and the one where it is at the
    - * trailing surrogate, and thus deduce where the next character starts and
    - * preceding character ends.
    - *
    - * Otherwise, the char value at the given index is returned. Thus, a leading
    - * surrogate is returned when it is not followed by a trailing surrogate, and a
    - * trailing surrogate is returned when it is not preceded by a leading
    - * surrogate.
    - *
    - * @param {!string} string The string.
    - * @param {number} index The index from which the code point is to be retrieved.
    - * @return {number} The code point at the given index. If the given index is
    - * that of the start (i.e. lead surrogate) of a surrogate pair, returns the code
    - * point encoded by the pair. If the given index is that of the end (i.e. trail
    - * surrogate) of a surrogate pair, returns the negated code pointed encoded by
    - * the pair.
    - */
    -goog.i18n.uChar.getCodePointAround = function(string, index) {
    -  var charCode = string.charCodeAt(index);
    -  if (goog.i18n.uChar.isLeadSurrogateCodePoint(charCode) &&
    -      index + 1 < string.length) {
    -    var trail = string.charCodeAt(index + 1);
    -    if (goog.i18n.uChar.isTrailSurrogateCodePoint(trail)) {
    -      // Part of a surrogate pair.
    -      return /** @type {number} */ (goog.i18n.uChar.
    -          buildSupplementaryCodePoint(charCode, trail));
    -    }
    -  } else if (goog.i18n.uChar.isTrailSurrogateCodePoint(charCode) &&
    -      index > 0) {
    -    var lead = string.charCodeAt(index - 1);
    -    if (goog.i18n.uChar.isLeadSurrogateCodePoint(lead)) {
    -      // Part of a surrogate pair.
    -      return /** @type {number} */ (-goog.i18n.uChar.
    -          buildSupplementaryCodePoint(lead, charCode));
    -    }
    -  }
    -  return charCode;
    -};
    -
    -
    -/**
    - * Determines the length of the string needed to represent the specified
    - * Unicode code point.
    - * @param {number} codePoint
    - * @return {number} 2 if codePoint is a supplementary character, 1 otherwise.
    - */
    -goog.i18n.uChar.charCount = function(codePoint) {
    -  return goog.i18n.uChar.isSupplementaryCodePoint(codePoint) ? 2 : 1;
    -};
    -
    -
    -/**
    - * Determines whether the specified Unicode code point is in the supplementary
    - * Unicode characters range.
    - * @param {number} codePoint
    - * @return {boolean} Whether then given code point is a supplementary character.
    - */
    -goog.i18n.uChar.isSupplementaryCodePoint = function(codePoint) {
    -  return codePoint >= goog.i18n.uChar.SUPPLEMENTARY_CODE_POINT_MIN_VALUE_ &&
    -         codePoint <= goog.i18n.uChar.CODE_POINT_MAX_VALUE_;
    -};
    -
    -
    -/**
    - * Gets whether the given code point is a leading surrogate character.
    - * @param {number} codePoint
    - * @return {boolean} Whether the given code point is a leading surrogate
    - * character.
    - */
    -goog.i18n.uChar.isLeadSurrogateCodePoint = function(codePoint) {
    -  return codePoint >= goog.i18n.uChar.LEAD_SURROGATE_MIN_VALUE_ &&
    -         codePoint <= goog.i18n.uChar.LEAD_SURROGATE_MAX_VALUE_;
    -};
    -
    -
    -/**
    - * Gets whether the given code point is a trailing surrogate character.
    - * @param {number} codePoint
    - * @return {boolean} Whether the given code point is a trailing surrogate
    - * character.
    - */
    -goog.i18n.uChar.isTrailSurrogateCodePoint = function(codePoint) {
    -  return codePoint >= goog.i18n.uChar.TRAIL_SURROGATE_MIN_VALUE_ &&
    -         codePoint <= goog.i18n.uChar.TRAIL_SURROGATE_MAX_VALUE_;
    -};
    -
    -
    -/**
    - * Composes a supplementary Unicode code point from the given UTF-16 surrogate
    - * pair. If leadSurrogate isn't a leading surrogate code point or trailSurrogate
    - * isn't a trailing surrogate code point, null is returned.
    - * @param {number} lead The leading surrogate code point.
    - * @param {number} trail The trailing surrogate code point.
    - * @return {?number} The supplementary Unicode code point obtained by decoding
    - * the given UTF-16 surrogate pair.
    - */
    -goog.i18n.uChar.buildSupplementaryCodePoint = function(lead, trail) {
    -  if (goog.i18n.uChar.isLeadSurrogateCodePoint(lead) &&
    -      goog.i18n.uChar.isTrailSurrogateCodePoint(trail)) {
    -    var shiftedLeadOffset = (lead <<
    -        goog.i18n.uChar.TRAIL_SURROGATE_BIT_COUNT_) -
    -        (goog.i18n.uChar.LEAD_SURROGATE_MIN_VALUE_ <<
    -        goog.i18n.uChar.TRAIL_SURROGATE_BIT_COUNT_);
    -    var trailOffset = trail - goog.i18n.uChar.TRAIL_SURROGATE_MIN_VALUE_ +
    -        goog.i18n.uChar.SUPPLEMENTARY_CODE_POINT_MIN_VALUE_;
    -    return shiftedLeadOffset + trailOffset;
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * Gets the name of a character, if available, returns null otherwise.
    - * @param {string} ch The character.
    - * @return {?string} The name of the character.
    - */
    -goog.i18n.uChar.toName = function(ch) {
    -  if (!goog.i18n.uChar.charData_) {
    -    goog.i18n.uChar.createCharData();
    -  }
    -
    -  var names = goog.i18n.uChar.charData_;
    -  var chCode = goog.i18n.uChar.toCharCode(ch);
    -  var chCodeStr = chCode + '';
    -
    -  if (ch in names) {
    -    return names[ch];
    -  } else if (chCodeStr in names) {
    -    return names[chCode];
    -  } else if (0xFE00 <= chCode && chCode <= 0xFE0F ||
    -      0xE0100 <= chCode && chCode <= 0xE01EF) {
    -    var seqnum;
    -    if (0xFE00 <= chCode && chCode <= 0xFE0F) {
    -      // Variation selectors from 1 to 16.
    -      seqnum = chCode - 0xFDFF;
    -    } else {
    -      // Variation selectors from 17 to 256.
    -      seqnum = chCode - 0xE00EF;
    -    }
    -
    -    /** @desc Variation selector with the sequence number. */
    -    var MSG_VARIATION_SELECTOR_SEQNUM =
    -        goog.getMsg('Variation Selector - {$seqnum}', {'seqnum': seqnum});
    -    return MSG_VARIATION_SELECTOR_SEQNUM;
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * Following lines are programatically created.
    - * Details: https://sites/cibu/character-picker.
    - **/
    -
    -
    -/**
    - * Sets up the character map, lazily.  Some characters are indexed by their
    - * decimal value.
    - * @protected
    - */
    -goog.i18n.uChar.createCharData = function() {
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_ARABIC_SIGN_SANAH = goog.getMsg('Arabic Sign Sanah');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_CANADIAN_SYLLABICS_HYPHEN =
    -      goog.getMsg('Canadian Syllabics Hyphen');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_ARABIC_SIGN_SAFHA = goog.getMsg('Arabic Sign Safha');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_ARABIC_FOOTNOTE_MARKER = goog.getMsg('Arabic Footnote Marker');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_FOUR_PER_EM_SPACE = goog.getMsg('Four-per-em Space');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_THREE_PER_EM_SPACE = goog.getMsg('Three-per-em Space');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_FIGURE_SPACE = goog.getMsg('Figure Space');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_MONGOLIAN_SOFT_HYPHEN = goog.getMsg('Mongolian Soft Hyphen');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_THIN_SPACE = goog.getMsg('Thin Space');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_SOFT_HYPHEN = goog.getMsg('Soft Hyphen');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_ZERO_WIDTH_SPACE = goog.getMsg('Zero Width Space');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_ARMENIAN_HYPHEN = goog.getMsg('Armenian Hyphen');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_ZERO_WIDTH_JOINER = goog.getMsg('Zero Width Joiner');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_EM_SPACE = goog.getMsg('Em Space');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_SYRIAC_ABBREVIATION_MARK = goog.getMsg('Syriac Abbreviation Mark');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_MONGOLIAN_VOWEL_SEPARATOR =
    -      goog.getMsg('Mongolian Vowel Separator');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_NON_BREAKING_HYPHEN = goog.getMsg('Non-breaking Hyphen');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_HYPHEN = goog.getMsg('Hyphen');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_EM_QUAD = goog.getMsg('Em Quad');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_EN_SPACE = goog.getMsg('En Space');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_HORIZONTAL_BAR = goog.getMsg('Horizontal Bar');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_EM_DASH = goog.getMsg('Em Dash');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_DOUBLE_OBLIQUE_HYPHEN = goog.getMsg('Double Oblique Hyphen');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_MUSICAL_SYMBOL_END_PHRASE =
    -      goog.getMsg('Musical Symbol End Phrase');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_MEDIUM_MATHEMATICAL_SPACE =
    -      goog.getMsg('Medium Mathematical Space');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_WAVE_DASH = goog.getMsg('Wave Dash');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_SPACE = goog.getMsg('Space');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_HYPHEN_WITH_DIAERESIS = goog.getMsg('Hyphen With Diaeresis');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_EN_QUAD = goog.getMsg('En Quad');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_RIGHT_TO_LEFT_EMBEDDING = goog.getMsg('Right-to-left Embedding');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_SIX_PER_EM_SPACE = goog.getMsg('Six-per-em Space');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_HYPHEN_MINUS = goog.getMsg('Hyphen-minus');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_POP_DIRECTIONAL_FORMATTING =
    -      goog.getMsg('Pop Directional Formatting');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_NARROW_NO_BREAK_SPACE = goog.getMsg('Narrow No-break Space');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_RIGHT_TO_LEFT_OVERRIDE = goog.getMsg('Right-to-left Override');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_PRESENTATION_FORM_FOR_VERTICAL_EM_DASH =
    -      goog.getMsg('Presentation Form For Vertical Em Dash');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_WAVY_DASH = goog.getMsg('Wavy Dash');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_PRESENTATION_FORM_FOR_VERTICAL_EN_DASH =
    -      goog.getMsg('Presentation Form For Vertical En Dash');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_KHMER_VOWEL_INHERENT_AA = goog.getMsg('Khmer Vowel Inherent Aa');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_KHMER_VOWEL_INHERENT_AQ = goog.getMsg('Khmer Vowel Inherent Aq');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_PUNCTUATION_SPACE = goog.getMsg('Punctuation Space');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_HALFWIDTH_HANGUL_FILLER = goog.getMsg('Halfwidth Hangul Filler');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_KAITHI_NUMBER_SIGN = goog.getMsg('Kaithi Number Sign');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_LEFT_TO_RIGHT_EMBEDDING = goog.getMsg('Left-to-right Embedding');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_HEBREW_PUNCTUATION_MAQAF = goog.getMsg('Hebrew Punctuation Maqaf');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_IDEOGRAPHIC_SPACE = goog.getMsg('Ideographic Space');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_HAIR_SPACE = goog.getMsg('Hair Space');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_NO_BREAK_SPACE = goog.getMsg('No-break Space');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_FULLWIDTH_HYPHEN_MINUS = goog.getMsg('Fullwidth Hyphen-minus');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_PARAGRAPH_SEPARATOR = goog.getMsg('Paragraph Separator');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_LEFT_TO_RIGHT_OVERRIDE = goog.getMsg('Left-to-right Override');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_SMALL_HYPHEN_MINUS = goog.getMsg('Small Hyphen-minus');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_COMBINING_GRAPHEME_JOINER =
    -      goog.getMsg('Combining Grapheme Joiner');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_ZERO_WIDTH_NON_JOINER = goog.getMsg('Zero Width Non-joiner');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_MUSICAL_SYMBOL_BEGIN_PHRASE =
    -      goog.getMsg('Musical Symbol Begin Phrase');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_ARABIC_NUMBER_SIGN = goog.getMsg('Arabic Number Sign');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_RIGHT_TO_LEFT_MARK = goog.getMsg('Right-to-left Mark');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_OGHAM_SPACE_MARK = goog.getMsg('Ogham Space Mark');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_SMALL_EM_DASH = goog.getMsg('Small Em Dash');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_LEFT_TO_RIGHT_MARK = goog.getMsg('Left-to-right Mark');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_ARABIC_END_OF_AYAH = goog.getMsg('Arabic End Of Ayah');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_HANGUL_CHOSEONG_FILLER = goog.getMsg('Hangul Choseong Filler');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_HANGUL_FILLER = goog.getMsg('Hangul Filler');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_FUNCTION_APPLICATION = goog.getMsg('Function Application');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_HANGUL_JUNGSEONG_FILLER = goog.getMsg('Hangul Jungseong Filler');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_INVISIBLE_SEPARATOR = goog.getMsg('Invisible Separator');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_INVISIBLE_TIMES = goog.getMsg('Invisible Times');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_INVISIBLE_PLUS = goog.getMsg('Invisible Plus');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_WORD_JOINER = goog.getMsg('Word Joiner');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_LINE_SEPARATOR = goog.getMsg('Line Separator');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_KATAKANA_HIRAGANA_DOUBLE_HYPHEN =
    -      goog.getMsg('Katakana-hiragana Double Hyphen');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_EN_DASH = goog.getMsg('En Dash');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_MUSICAL_SYMBOL_BEGIN_BEAM =
    -      goog.getMsg('Musical Symbol Begin Beam');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_FIGURE_DASH = goog.getMsg('Figure Dash');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_MUSICAL_SYMBOL_BEGIN_TIE = goog.getMsg('Musical Symbol Begin Tie');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_MUSICAL_SYMBOL_END_BEAM = goog.getMsg('Musical Symbol End Beam');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_MUSICAL_SYMBOL_BEGIN_SLUR =
    -      goog.getMsg('Musical Symbol Begin Slur');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_MUSICAL_SYMBOL_END_TIE = goog.getMsg('Musical Symbol End Tie');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_INTERLINEAR_ANNOTATION_ANCHOR =
    -      goog.getMsg('Interlinear Annotation Anchor');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_MUSICAL_SYMBOL_END_SLUR = goog.getMsg('Musical Symbol End Slur');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_INTERLINEAR_ANNOTATION_TERMINATOR =
    -      goog.getMsg('Interlinear Annotation Terminator');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_INTERLINEAR_ANNOTATION_SEPARATOR =
    -      goog.getMsg('Interlinear Annotation Separator');
    -
    -
    -  /**
    -   * @desc Name for a symbol, character or a letter. Used in a pop-up balloon,
    -   *   shown to a document editing user trying to insert a special character.
    -   *   The balloon help would appear while the user hovers over the character
    -   *   displayed. Newlines are not allowed; translation should be a noun and
    -   *   as consise as possible. More details:
    -   *   docs/fileview?id=0B8NbxddKsFtwYjExMGJjNzgtYjkzOS00NjdiLTlmOGQtOGVhZDkyZDU5YjM4.
    -   */
    -  var MSG_CP_ZERO_WIDTH_NO_BREAK_SPACE =
    -      goog.getMsg('Zero Width No-break Space');
    -
    -  goog.i18n.uChar.charData_ = {
    -    '\u0601': MSG_CP_ARABIC_SIGN_SANAH,
    -    '\u1400': MSG_CP_CANADIAN_SYLLABICS_HYPHEN,
    -    '\u0603': MSG_CP_ARABIC_SIGN_SAFHA,
    -    '\u0602': MSG_CP_ARABIC_FOOTNOTE_MARKER,
    -    '\u2005': MSG_CP_FOUR_PER_EM_SPACE,
    -    '\u2004': MSG_CP_THREE_PER_EM_SPACE,
    -    '\u2007': MSG_CP_FIGURE_SPACE,
    -    '\u1806': MSG_CP_MONGOLIAN_SOFT_HYPHEN,
    -    '\u2009': MSG_CP_THIN_SPACE,
    -    '\u00AD': MSG_CP_SOFT_HYPHEN,
    -    '\u200B': MSG_CP_ZERO_WIDTH_SPACE,
    -    '\u058A': MSG_CP_ARMENIAN_HYPHEN,
    -    '\u200D': MSG_CP_ZERO_WIDTH_JOINER,
    -    '\u2003': MSG_CP_EM_SPACE,
    -    '\u070F': MSG_CP_SYRIAC_ABBREVIATION_MARK,
    -    '\u180E': MSG_CP_MONGOLIAN_VOWEL_SEPARATOR,
    -    '\u2011': MSG_CP_NON_BREAKING_HYPHEN,
    -    '\u2010': MSG_CP_HYPHEN,
    -    '\u2001': MSG_CP_EM_QUAD,
    -    '\u2002': MSG_CP_EN_SPACE,
    -    '\u2015': MSG_CP_HORIZONTAL_BAR,
    -    '\u2014': MSG_CP_EM_DASH,
    -    '\u2E17': MSG_CP_DOUBLE_OBLIQUE_HYPHEN,
    -    '\u1D17A': MSG_CP_MUSICAL_SYMBOL_END_PHRASE,
    -    '\u205F': MSG_CP_MEDIUM_MATHEMATICAL_SPACE,
    -    '\u301C': MSG_CP_WAVE_DASH,
    -    ' ': MSG_CP_SPACE,
    -    '\u2E1A': MSG_CP_HYPHEN_WITH_DIAERESIS,
    -    '\u2000': MSG_CP_EN_QUAD,
    -    '\u202B': MSG_CP_RIGHT_TO_LEFT_EMBEDDING,
    -    '\u2006': MSG_CP_SIX_PER_EM_SPACE,
    -    '-': MSG_CP_HYPHEN_MINUS,
    -    '\u202C': MSG_CP_POP_DIRECTIONAL_FORMATTING,
    -    '\u202F': MSG_CP_NARROW_NO_BREAK_SPACE,
    -    '\u202E': MSG_CP_RIGHT_TO_LEFT_OVERRIDE,
    -    '\uFE31': MSG_CP_PRESENTATION_FORM_FOR_VERTICAL_EM_DASH,
    -    '\u3030': MSG_CP_WAVY_DASH,
    -    '\uFE32': MSG_CP_PRESENTATION_FORM_FOR_VERTICAL_EN_DASH,
    -    '\u17B5': MSG_CP_KHMER_VOWEL_INHERENT_AA,
    -    '\u17B4': MSG_CP_KHMER_VOWEL_INHERENT_AQ,
    -    '\u2008': MSG_CP_PUNCTUATION_SPACE,
    -    '\uFFA0': MSG_CP_HALFWIDTH_HANGUL_FILLER,
    -    '\u110BD': MSG_CP_KAITHI_NUMBER_SIGN,
    -    '\u202A': MSG_CP_LEFT_TO_RIGHT_EMBEDDING,
    -    '\u05BE': MSG_CP_HEBREW_PUNCTUATION_MAQAF,
    -    '\u3000': MSG_CP_IDEOGRAPHIC_SPACE,
    -    '\u200A': MSG_CP_HAIR_SPACE,
    -    '\u00A0': MSG_CP_NO_BREAK_SPACE,
    -    '\uFF0D': MSG_CP_FULLWIDTH_HYPHEN_MINUS,
    -    '8233': MSG_CP_PARAGRAPH_SEPARATOR,
    -    '\u202D': MSG_CP_LEFT_TO_RIGHT_OVERRIDE,
    -    '\uFE63': MSG_CP_SMALL_HYPHEN_MINUS,
    -    '\u034F': MSG_CP_COMBINING_GRAPHEME_JOINER,
    -    '\u200C': MSG_CP_ZERO_WIDTH_NON_JOINER,
    -    '\u1D179': MSG_CP_MUSICAL_SYMBOL_BEGIN_PHRASE,
    -    '\u0600': MSG_CP_ARABIC_NUMBER_SIGN,
    -    '\u200F': MSG_CP_RIGHT_TO_LEFT_MARK,
    -    '\u1680': MSG_CP_OGHAM_SPACE_MARK,
    -    '\uFE58': MSG_CP_SMALL_EM_DASH,
    -    '\u200E': MSG_CP_LEFT_TO_RIGHT_MARK,
    -    '\u06DD': MSG_CP_ARABIC_END_OF_AYAH,
    -    '\u115F': MSG_CP_HANGUL_CHOSEONG_FILLER,
    -    '\u3164': MSG_CP_HANGUL_FILLER,
    -    '\u2061': MSG_CP_FUNCTION_APPLICATION,
    -    '\u1160': MSG_CP_HANGUL_JUNGSEONG_FILLER,
    -    '\u2063': MSG_CP_INVISIBLE_SEPARATOR,
    -    '\u2062': MSG_CP_INVISIBLE_TIMES,
    -    '\u2064': MSG_CP_INVISIBLE_PLUS,
    -    '\u2060': MSG_CP_WORD_JOINER,
    -    '8232': MSG_CP_LINE_SEPARATOR,
    -    '\u30A0': MSG_CP_KATAKANA_HIRAGANA_DOUBLE_HYPHEN,
    -    '\u2013': MSG_CP_EN_DASH,
    -    '\u1D173': MSG_CP_MUSICAL_SYMBOL_BEGIN_BEAM,
    -    '\u2012': MSG_CP_FIGURE_DASH,
    -    '\u1D175': MSG_CP_MUSICAL_SYMBOL_BEGIN_TIE,
    -    '\u1D174': MSG_CP_MUSICAL_SYMBOL_END_BEAM,
    -    '\u1D177': MSG_CP_MUSICAL_SYMBOL_BEGIN_SLUR,
    -    '\u1D176': MSG_CP_MUSICAL_SYMBOL_END_TIE,
    -    '\uFFF9': MSG_CP_INTERLINEAR_ANNOTATION_ANCHOR,
    -    '\u1D178': MSG_CP_MUSICAL_SYMBOL_END_SLUR,
    -    '\uFFFB': MSG_CP_INTERLINEAR_ANNOTATION_TERMINATOR,
    -    '\uFFFA': MSG_CP_INTERLINEAR_ANNOTATION_SEPARATOR,
    -    '\uFEFF': MSG_CP_ZERO_WIDTH_NO_BREAK_SPACE
    -  };
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/uchar/localnamefetcher.js b/src/database/third_party/closure-library/closure/goog/i18n/uchar/localnamefetcher.js
    deleted file mode 100644
    index 5e1380f942b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/uchar/localnamefetcher.js
    +++ /dev/null
    @@ -1,74 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Object which fetches Unicode codepoint names that are locally
    - * stored in a bundled database. Currently, only invisible characters are
    - * covered by this database. See the goog.i18n.uChar.RemoteNameFetcher class for
    - * a remote database option.
    - */
    -
    -goog.provide('goog.i18n.uChar.LocalNameFetcher');
    -
    -goog.require('goog.i18n.uChar');
    -goog.require('goog.i18n.uChar.NameFetcher');
    -goog.require('goog.log');
    -
    -
    -
    -/**
    - * Builds the NameFetcherLocal object. This is a simple object which retrieves
    - * character names from a local bundled database. This database only covers
    - * invisible characters. See the goog.i18n.uChar class for more details.
    - *
    - * @constructor
    - * @implements {goog.i18n.uChar.NameFetcher}
    - * @final
    - */
    -goog.i18n.uChar.LocalNameFetcher = function() {
    -};
    -
    -
    -/**
    - * A reference to the LocalNameFetcher logger.
    - *
    - * @type {goog.log.Logger}
    - * @private
    - */
    -goog.i18n.uChar.LocalNameFetcher.logger_ =
    -    goog.log.getLogger('goog.i18n.uChar.LocalNameFetcher');
    -
    -
    -/** @override */
    -goog.i18n.uChar.LocalNameFetcher.prototype.prefetch = function(character) {
    -};
    -
    -
    -/** @override */
    -goog.i18n.uChar.LocalNameFetcher.prototype.getName = function(character,
    -    callback) {
    -  var localName = goog.i18n.uChar.toName(character);
    -  if (!localName) {
    -    goog.i18n.uChar.LocalNameFetcher.logger_.
    -        warning('No local name defined for character ' + character);
    -  }
    -  callback(localName);
    -};
    -
    -
    -/** @override */
    -goog.i18n.uChar.LocalNameFetcher.prototype.isNameAvailable = function(
    -    character) {
    -  return !!goog.i18n.uChar.toName(character);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/uchar/localnamefetcher_test.html b/src/database/third_party/closure-library/closure/goog/i18n/uchar/localnamefetcher_test.html
    deleted file mode 100644
    index e6c0237d3a2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/uchar/localnamefetcher_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<html>
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.i18n.uChar.LocalNameFetcher
    -  </title>
    -  <meta charset="utf-8" />
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.i18n.uChar.LocalNameFetcherTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/uchar/localnamefetcher_test.js b/src/database/third_party/closure-library/closure/goog/i18n/uchar/localnamefetcher_test.js
    deleted file mode 100644
    index 4f99c3f942f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/uchar/localnamefetcher_test.js
    +++ /dev/null
    @@ -1,59 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -goog.provide('goog.i18n.uChar.LocalNameFetcherTest');
    -goog.setTestOnly('goog.i18n.uChar.LocalNameFetcherTest');
    -
    -goog.require('goog.i18n.uChar.LocalNameFetcher');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -
    -var nameFetcher = null;
    -
    -function setUp() {
    -  nameFetcher = new goog.i18n.uChar.LocalNameFetcher();
    -}
    -
    -function testGetName_exists() {
    -  var callback = goog.testing.recordFunction(function(name) {
    -    assertEquals('Space', name);
    -  });
    -  nameFetcher.getName(' ', callback);
    -  assertEquals(1, callback.getCallCount());
    -}
    -
    -function testGetName_variationSelector() {
    -  var callback = goog.testing.recordFunction(function(name) {
    -    assertEquals('Variation Selector - 1', name);
    -  });
    -  nameFetcher.getName('\ufe00', callback);
    -  assertEquals(1, callback.getCallCount());
    -}
    -
    -function testGetName_missing() {
    -  var callback = goog.testing.recordFunction(function(name) {
    -    assertNull(name);
    -  });
    -  nameFetcher.getName('P', callback);
    -  assertEquals(1, callback.getCallCount());
    -}
    -
    -function testIsNameAvailable_withAvailableName() {
    -  assertTrue(nameFetcher.isNameAvailable(' '));
    -}
    -
    -function testIsNameAvailable_withoutAvailableName() {
    -  assertFalse(nameFetcher.isNameAvailable('a'));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/uchar/namefetcher.js b/src/database/third_party/closure-library/closure/goog/i18n/uchar/namefetcher.js
    deleted file mode 100644
    index 9cf9f2145f6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/uchar/namefetcher.js
    +++ /dev/null
    @@ -1,70 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Definition of the goog.i18n.CharNameFetcher interface. This
    - * interface is used to retrieve individual character names.
    - */
    -
    -goog.provide('goog.i18n.uChar.NameFetcher');
    -
    -
    -
    -/**
    - * NameFetcher interface. Implementations of this interface are used to retrieve
    - * Unicode character names.
    - *
    - * @interface
    - */
    -goog.i18n.uChar.NameFetcher = function() {
    -};
    -
    -
    -/**
    - * Retrieves the names of a given set of characters and stores them in a cache
    - * for fast retrieval. Offline implementations can simply provide an empty
    - * implementation.
    - *
    - * @param {string} characters The list of characters in base 88 to fetch. These
    - *     lists are stored by category and subcategory in the
    - *     goog.i18n.charpickerdata class.
    - */
    -goog.i18n.uChar.NameFetcher.prototype.prefetch = function(characters) {
    -};
    -
    -
    -/**
    - * Retrieves the name of a particular character.
    - *
    - * @param {string} character The character to retrieve.
    - * @param {function(?string)} callback The callback function called when the
    - *     name retrieval is complete, contains a single string parameter with the
    - *     codepoint name, this parameter will be null if the character name is not
    - *     defined.
    - */
    -goog.i18n.uChar.NameFetcher.prototype.getName = function(character, callback) {
    -};
    -
    -
    -/**
    - * Tests whether the name of a given character is available to be retrieved by
    - * the getName() function.
    - *
    - * @param {string} character The character to test.
    - * @return {boolean} True if the fetcher can retrieve or has a name available
    - *     for the given character.
    - */
    -goog.i18n.uChar.NameFetcher.prototype.isNameAvailable = function(character) {
    -};
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/uchar/remotenamefetcher.js b/src/database/third_party/closure-library/closure/goog/i18n/uchar/remotenamefetcher.js
    deleted file mode 100644
    index bde93932aec..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/uchar/remotenamefetcher.js
    +++ /dev/null
    @@ -1,282 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Object which fetches Unicode codepoint names from a remote data
    - * source. This data source should accept two parameters:
    - * <ol>
    - * <li>c - the list of codepoints in hexadecimal format
    - * <li>p - the name property
    - * </ol>
    - * and return a JSON object representation of the result.
    - * For example, calling this data source with the following URL:
    - * http://datasource?c=50,ff,102bd&p=name
    - * Should return a JSON object which looks like this:
    - * <pre>
    - * {"50":{"name":"LATIN CAPITAL LETTER P"},
    - * "ff":{"name":"LATIN SMALL LETTER Y WITH DIAERESIS"},
    - * "102bd":{"name":"CARIAN LETTER K2"}}
    - * </pre>.
    - */
    -
    -goog.provide('goog.i18n.uChar.RemoteNameFetcher');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.Uri');
    -goog.require('goog.i18n.uChar');
    -goog.require('goog.i18n.uChar.NameFetcher');
    -goog.require('goog.log');
    -goog.require('goog.net.XhrIo');
    -goog.require('goog.structs.Map');
    -
    -
    -
    -/**
    - * Builds the RemoteNameFetcher object. This object retrieves codepoint names
    - * from a remote data source.
    - *
    - * @param {string} dataSourceUri URI to the data source.
    - * @constructor
    - * @implements {goog.i18n.uChar.NameFetcher}
    - * @extends {goog.Disposable}
    - * @final
    - */
    -goog.i18n.uChar.RemoteNameFetcher = function(dataSourceUri) {
    -  goog.i18n.uChar.RemoteNameFetcher.base(this, 'constructor');
    -
    -  /**
    -   * XHRIo object for prefetch() asynchronous calls.
    -   *
    -   * @type {!goog.net.XhrIo}
    -   * @private
    -   */
    -  this.prefetchXhrIo_ = new goog.net.XhrIo();
    -
    -  /**
    -   * XHRIo object for getName() asynchronous calls.
    -   *
    -   * @type {!goog.net.XhrIo}
    -   * @private
    -   */
    -  this.getNameXhrIo_ = new goog.net.XhrIo();
    -
    -  /**
    -   * URI to the data.
    -   *
    -   * @type {string}
    -   * @private
    -   */
    -  this.dataSourceUri_ = dataSourceUri;
    -
    -  /**
    -   * A cache of all the collected names from the server.
    -   *
    -   * @type {!goog.structs.Map}
    -   * @private
    -   */
    -  this.charNames_ = new goog.structs.Map();
    -};
    -goog.inherits(goog.i18n.uChar.RemoteNameFetcher, goog.Disposable);
    -
    -
    -/**
    - * Key to the listener on XHR for prefetch(). Used to clear previous listeners.
    - *
    - * @type {goog.events.Key}
    - * @private
    - */
    -goog.i18n.uChar.RemoteNameFetcher.prototype.prefetchLastListenerKey_;
    -
    -
    -/**
    - * Key to the listener on XHR for getName(). Used to clear previous listeners.
    - *
    - * @type {goog.events.Key}
    - * @private
    - */
    -goog.i18n.uChar.RemoteNameFetcher.prototype.getNameLastListenerKey_;
    -
    -
    -/**
    - * A reference to the RemoteNameFetcher logger.
    - *
    - * @type {goog.log.Logger}
    - * @private
    - */
    -goog.i18n.uChar.RemoteNameFetcher.logger_ =
    -    goog.log.getLogger('goog.i18n.uChar.RemoteNameFetcher');
    -
    -
    -
    -
    -/** @override */
    -goog.i18n.uChar.RemoteNameFetcher.prototype.disposeInternal = function() {
    -  goog.i18n.uChar.RemoteNameFetcher.base(this, 'disposeInternal');
    -  this.prefetchXhrIo_.dispose();
    -  this.getNameXhrIo_.dispose();
    -};
    -
    -
    -/** @override */
    -goog.i18n.uChar.RemoteNameFetcher.prototype.prefetch = function(characters) {
    -  // Abort the current request if there is one
    -  if (this.prefetchXhrIo_.isActive()) {
    -    goog.i18n.uChar.RemoteNameFetcher.logger_.
    -        info('Aborted previous prefetch() call for new incoming request');
    -    this.prefetchXhrIo_.abort();
    -  }
    -  if (this.prefetchLastListenerKey_) {
    -    goog.events.unlistenByKey(this.prefetchLastListenerKey_);
    -  }
    -
    -  // Set up new listener
    -  var preFetchCallback = goog.bind(this.prefetchCallback_, this);
    -  this.prefetchLastListenerKey_ = goog.events.listenOnce(this.prefetchXhrIo_,
    -      goog.net.EventType.COMPLETE, preFetchCallback);
    -
    -  this.fetch_(goog.i18n.uChar.RemoteNameFetcher.RequestType_.BASE_88,
    -      characters, this.prefetchXhrIo_);
    -};
    -
    -
    -/**
    - * Callback on completion of the prefetch operation.
    - *
    - * @private
    - */
    -goog.i18n.uChar.RemoteNameFetcher.prototype.prefetchCallback_ = function() {
    -  this.processResponse_(this.prefetchXhrIo_);
    -};
    -
    -
    -/** @override */
    -goog.i18n.uChar.RemoteNameFetcher.prototype.getName = function(character,
    -    callback) {
    -  var codepoint = goog.i18n.uChar.toCharCode(character).toString(16);
    -
    -  if (this.charNames_.containsKey(codepoint)) {
    -    var name = /** @type {string} */ (this.charNames_.get(codepoint));
    -    callback(name);
    -    return;
    -  }
    -
    -  // Abort the current request if there is one
    -  if (this.getNameXhrIo_.isActive()) {
    -    goog.i18n.uChar.RemoteNameFetcher.logger_.
    -        info('Aborted previous getName() call for new incoming request');
    -    this.getNameXhrIo_.abort();
    -  }
    -  if (this.getNameLastListenerKey_) {
    -    goog.events.unlistenByKey(this.getNameLastListenerKey_);
    -  }
    -
    -  // Set up new listener
    -  var getNameCallback = goog.bind(this.getNameCallback_, this, codepoint,
    -      callback);
    -  this.getNameLastListenerKey_ = goog.events.listenOnce(this.getNameXhrIo_,
    -      goog.net.EventType.COMPLETE, getNameCallback);
    -
    -  this.fetch_(goog.i18n.uChar.RemoteNameFetcher.RequestType_.CODEPOINT,
    -      codepoint, this.getNameXhrIo_);
    -};
    -
    -
    -/**
    - * Callback on completion of the getName operation.
    - *
    - * @param {string} codepoint The codepoint in hexadecimal format.
    - * @param {function(?string)} callback The callback function called when the
    - *     name retrieval is complete, contains a single string parameter with the
    - *     codepoint name, this parameter will be null if the character name is not
    - *     defined.
    - * @private
    - */
    -goog.i18n.uChar.RemoteNameFetcher.prototype.getNameCallback_ = function(
    -    codepoint, callback) {
    -  this.processResponse_(this.getNameXhrIo_);
    -  var name = /** @type {?string} */ (this.charNames_.get(codepoint, null));
    -  callback(name);
    -};
    -
    -
    -/**
    - * Process the response received from the server and store results in the cache.
    - *
    - * @param {!goog.net.XhrIo} xhrIo The XhrIo object used to make the request.
    - * @private
    - */
    -goog.i18n.uChar.RemoteNameFetcher.prototype.processResponse_ = function(xhrIo) {
    -  if (!xhrIo.isSuccess()) {
    -    goog.log.error(goog.i18n.uChar.RemoteNameFetcher.logger_,
    -        'Problem with data source: ' + xhrIo.getLastError());
    -    return;
    -  }
    -  var result = xhrIo.getResponseJson();
    -  for (var codepoint in result) {
    -    if (result[codepoint].hasOwnProperty('name')) {
    -      this.charNames_.set(codepoint, result[codepoint]['name']);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Enum for the different request types.
    - *
    - * @enum {string}
    - * @private
    - */
    -goog.i18n.uChar.RemoteNameFetcher.RequestType_ = {
    -
    -  /**
    -   * Request type that uses a base 88 string containing a set of codepoints to
    -   * be fetched from the server (see goog.i18n.charpickerdata for more
    -   * information on b88).
    -   */
    -  BASE_88: 'b88',
    -
    -  /**
    -   * Request type that uses a a string of comma separated codepoint values.
    -   */
    -  CODEPOINT: 'c'
    -};
    -
    -
    -/**
    - * Fetches a set of codepoint names from the data source.
    - *
    - * @param {!goog.i18n.uChar.RemoteNameFetcher.RequestType_} requestType The
    - *     request type of the operation. This parameter specifies how the server is
    - *     called to fetch a particular set of codepoints.
    - * @param {string} requestInput The input to the request, this is the value that
    - *     is passed onto the server to complete the request.
    - * @param {!goog.net.XhrIo} xhrIo The XHRIo object to execute the server call.
    - * @private
    - */
    -goog.i18n.uChar.RemoteNameFetcher.prototype.fetch_ = function(requestType,
    -    requestInput, xhrIo) {
    -  var url = new goog.Uri(this.dataSourceUri_);
    -  url.setParameterValue(requestType, requestInput);
    -  url.setParameterValue('p', 'name');
    -  goog.log.info(goog.i18n.uChar.RemoteNameFetcher.logger_, 'Request: ' +
    -      url.toString());
    -  xhrIo.send(url);
    -};
    -
    -
    -/** @override */
    -goog.i18n.uChar.RemoteNameFetcher.prototype.isNameAvailable = function(
    -    character) {
    -  return true;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/uchar/remotenamefetcher_test.html b/src/database/third_party/closure-library/closure/goog/i18n/uchar/remotenamefetcher_test.html
    deleted file mode 100644
    index dd6aa9a2091..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/uchar/remotenamefetcher_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<html>
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.i18n.uChar.RemoteNameFetcher
    -  </title>
    -  <meta charset="utf-8" />
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.i18n.uChar.RemoteNameFetcherTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/uchar/remotenamefetcher_test.js b/src/database/third_party/closure-library/closure/goog/i18n/uchar/remotenamefetcher_test.js
    deleted file mode 100644
    index 45d11836a0d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/uchar/remotenamefetcher_test.js
    +++ /dev/null
    @@ -1,108 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -goog.provide('goog.i18n.uChar.RemoteNameFetcherTest');
    -goog.setTestOnly('goog.i18n.uChar.RemoteNameFetcherTest');
    -
    -goog.require('goog.i18n.uChar.RemoteNameFetcher');
    -goog.require('goog.net.XhrIo');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.net.XhrIo');
    -goog.require('goog.testing.recordFunction');
    -
    -var nameFetcher = null;
    -
    -function setUp() {
    -  goog.net.XhrIo = goog.testing.net.XhrIo;
    -  nameFetcher = new goog.i18n.uChar.RemoteNameFetcher('http://www.example.com');
    -}
    -
    -function tearDown() {
    -  nameFetcher.dispose();
    -}
    -
    -function testGetName_remote() {
    -  var callback = goog.testing.recordFunction(function(name) {
    -    assertEquals('Latin Capital Letter P', name);
    -    assertTrue(nameFetcher.charNames_.containsKey('50'));
    -  });
    -  nameFetcher.getName('P', callback);
    -  var responseJsonText = '{"50":{"name":"Latin Capital Letter P"}}';
    -  nameFetcher.getNameXhrIo_.simulateResponse(200, responseJsonText);
    -  assertEquals(1, callback.getCallCount());
    -}
    -
    -function testGetName_existing() {
    -  nameFetcher.charNames_.set('1049d', 'OSYMANYA LETTER OO');
    -  var callback = goog.testing.recordFunction(function(name) {
    -    assertEquals('OSYMANYA LETTER OO', name);
    -  });
    -  nameFetcher.getName('\uD801\uDC9D', callback);
    -  assertEquals(1, callback.getCallCount());
    -}
    -
    -function testGetName_fail() {
    -  var callback = goog.testing.recordFunction(function(name) {
    -    assertNull(name);
    -  });
    -  nameFetcher.getName('\uD801\uDC9D', callback);
    -  assertEquals('http://www.example.com?c=1049d&p=name',
    -      nameFetcher.getNameXhrIo_.getLastUri().toString());
    -  nameFetcher.getNameXhrIo_.simulateResponse(400);
    -  assertEquals(1, callback.getCallCount());
    -}
    -
    -function testGetName_abort() {
    -  var callback1 = goog.testing.recordFunction(function(name) {
    -    assertNull(name);
    -  });
    -  nameFetcher.getName('I', callback1);
    -  var callback2 = goog.testing.recordFunction(function(name) {
    -    assertEquals(name, 'LATIN SMALL LETTER Y');
    -  });
    -  nameFetcher.getName('ÿ', callback2);
    -  assertEquals('http://www.example.com?c=ff&p=name',
    -      nameFetcher.getNameXhrIo_.getLastUri().toString());
    -  var responseJsonText = '{"ff":{"name":"LATIN SMALL LETTER Y"}}';
    -  nameFetcher.getNameXhrIo_.simulateResponse(200, responseJsonText);
    -  assertEquals(1, callback1.getCallCount());
    -  assertEquals(1, callback2.getCallCount());
    -}
    -
    -function testPrefetch() {
    -  nameFetcher.prefetch('ÿI\uD801\uDC9D');
    -  assertEquals('http://www.example.com?b88=%C3%BFI%F0%90%92%9D&p=name',
    -      nameFetcher.prefetchXhrIo_.getLastUri().toString());
    -
    -  var responseJsonText = '{"ff":{"name":"LATIN SMALL LETTER Y"},"49":{' +
    -      '"name":"LATIN CAPITAL LETTER I"}, "1049d":{"name":"OSMYANA OO"}}';
    -  nameFetcher.prefetchXhrIo_.simulateResponse(200, responseJsonText);
    -
    -  assertEquals(3, nameFetcher.charNames_.getCount());
    -  assertEquals('LATIN SMALL LETTER Y', nameFetcher.charNames_.get('ff'));
    -  assertEquals('LATIN CAPITAL LETTER I', nameFetcher.charNames_.get('49'));
    -  assertEquals('OSMYANA OO', nameFetcher.charNames_.get('1049d'));
    -}
    -
    -function testPrefetch_abort() {
    -  nameFetcher.prefetch('I\uD801\uDC9D');
    -  nameFetcher.prefetch('ÿ');
    -  assertEquals('http://www.example.com?b88=%C3%BF&p=name',
    -      nameFetcher.prefetchXhrIo_.getLastUri().toString());
    -}
    -
    -function testIsNameAvailable() {
    -  assertTrue(nameFetcher.isNameAvailable('a'));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/uchar_test.html b/src/database/third_party/closure-library/closure/goog/i18n/uchar_test.html
    deleted file mode 100644
    index 8d490c796f2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/uchar_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.i18n.uChar
    -  </title>
    -  <meta charset="utf-8" />
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.i18n.uCharTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/i18n/uchar_test.js b/src/database/third_party/closure-library/closure/goog/i18n/uchar_test.js
    deleted file mode 100644
    index 3852be3a0f7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/i18n/uchar_test.js
    +++ /dev/null
    @@ -1,125 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.i18n.uCharTest');
    -goog.setTestOnly('goog.i18n.uCharTest');
    -
    -goog.require('goog.i18n.uChar');
    -goog.require('goog.testing.jsunit');
    -
    -function testToHexString() {
    -  var result = goog.i18n.uChar.toHexString('\uD869\uDED6');
    -  assertEquals('U+2A6D6', result);
    -}
    -
    -function testPadString() {
    -  var result = goog.i18n.uChar.padString_('abc', 4, '0');
    -  assertEquals('0abc', result);
    -}
    -
    -function testToCharCode() {
    -  var result = goog.i18n.uChar.toCharCode('\uD869\uDED6');
    -  assertEquals(0x2A6D6, result);
    -}
    -
    -function testcodePointAt() {
    -  // Basic cases.
    -  assertEquals(0x006C, goog.i18n.uChar.getCodePointAround('Hello!', 2));
    -  assertEquals(0x2708 /* Airplane symbol (non-ASCII) */,
    -      goog.i18n.uChar.getCodePointAround('Hello\u2708', 5));
    -
    -  // Supplementary characters.
    -  assertEquals(0x2A6D6, goog.i18n.uChar.getCodePointAround('\uD869\uDED6', 0));
    -  assertEquals(-0x2A6D6, goog.i18n.uChar.getCodePointAround('\uD869\uDED6', 1));
    -  assertEquals(0xD869, goog.i18n.uChar.getCodePointAround('\uD869' + 'w', 0));
    -  assertEquals(0xDED6, goog.i18n.uChar.getCodePointAround('\uD869' + 'w' +
    -      '\uDED6', 2));
    -}
    -
    -function testBuildSupplementaryCodePoint() {
    -  var result = goog.i18n.uChar.buildSupplementaryCodePoint(0xD869, 0xDED6);
    -  assertEquals(0x2A6D6, result);
    -  assertNull(goog.i18n.uChar.buildSupplementaryCodePoint(0xDED6, 0xD869));
    -  assertNull(goog.i18n.uChar.buildSupplementaryCodePoint(0xD869, 0xAC00));
    -}
    -
    -function testCharCount() {
    -  assertEquals(2, goog.i18n.uChar.charCount(0x2A6D6));
    -  assertEquals(1, goog.i18n.uChar.charCount(0xAC00));
    -}
    -
    -function testIsSupplementaryCodePoint() {
    -  assertTrue(goog.i18n.uChar.isSupplementaryCodePoint(0x2A6D6));
    -  assertFalse(goog.i18n.uChar.isSupplementaryCodePoint(0xAC00));
    -}
    -
    -function testIsLeadSurrogateCodepoint() {
    -  assertTrue(goog.i18n.uChar.isLeadSurrogateCodePoint(0xD869));
    -  assertFalse(goog.i18n.uChar.isLeadSurrogateCodePoint(0xDED6));
    -  assertFalse(goog.i18n.uChar.isLeadSurrogateCodePoint(0xAC00));
    -}
    -
    -function testIsTrailSurrogateCodePoint() {
    -  assertTrue(goog.i18n.uChar.isTrailSurrogateCodePoint(0xDED6));
    -  assertFalse(goog.i18n.uChar.isTrailSurrogateCodePoint(0xD869));
    -  assertFalse(goog.i18n.uChar.isTrailSurrogateCodePoint(0xAC00));
    -}
    -
    -function testFromCharCode() {
    -  var result = goog.i18n.uChar.fromCharCode(0x2A6D6);
    -  assertEquals('\uD869\uDED6', result);
    -}
    -
    -function testFromCharCode_invalidValues() {
    -  var result = goog.i18n.uChar.fromCharCode(-1);
    -  assertEquals(null, result);
    -
    -  result = goog.i18n.uChar.fromCharCode(
    -      goog.i18n.uChar.CODE_POINT_MAX_VALUE_ + 1);
    -  assertEquals(null, result);
    -
    -  result = goog.i18n.uChar.fromCharCode(null);
    -  assertEquals(null, result);
    -
    -  result = goog.i18n.uChar.fromCharCode(undefined);
    -  assertEquals(null, result);
    -
    -  result = goog.i18n.uChar.fromCharCode(NaN);
    -  assertEquals(null, result);
    -}
    -
    -function testToName() {
    -  var result = goog.i18n.uChar.toName(' ');
    -  assertEquals('Space', result);
    -}
    -
    -function testToNameForNumberKey() {
    -  var result = goog.i18n.uChar.toName('\u2028');
    -  assertEquals('Line Separator', result);
    -}
    -
    -function testToNameForVariationSelector() {
    -  var result = goog.i18n.uChar.toName('\ufe00');
    -  assertEquals('Variation Selector - 1', result);
    -}
    -
    -function testToNameForVariationSelectorSupp() {
    -  var result = goog.i18n.uChar.toName('\uDB40\uDD00');
    -  assertEquals('Variation Selector - 17', result);
    -}
    -
    -function testToNameForNull() {
    -  var result = goog.i18n.uChar.toName('a');
    -  assertNull(result);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/images/blank.gif b/src/database/third_party/closure-library/closure/goog/images/blank.gif
    deleted file mode 100644
    index 75b945d2553..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/blank.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/bubble_close.jpg b/src/database/third_party/closure-library/closure/goog/images/bubble_close.jpg
    deleted file mode 100644
    index 486ef47e5f8..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/bubble_close.jpg and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/bubble_left.gif b/src/database/third_party/closure-library/closure/goog/images/bubble_left.gif
    deleted file mode 100644
    index 0e890bfcaa8..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/bubble_left.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/bubble_right.gif b/src/database/third_party/closure-library/closure/goog/images/bubble_right.gif
    deleted file mode 100644
    index 5b42ea098e0..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/bubble_right.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/button-bg.gif b/src/database/third_party/closure-library/closure/goog/images/button-bg.gif
    deleted file mode 100644
    index cd2d728b232..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/button-bg.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/check-outline.gif b/src/database/third_party/closure-library/closure/goog/images/check-outline.gif
    deleted file mode 100644
    index 392ffcc4f4b..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/check-outline.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/check-sprite.gif b/src/database/third_party/closure-library/closure/goog/images/check-sprite.gif
    deleted file mode 100644
    index 44a927c49b3..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/check-sprite.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/check.gif b/src/database/third_party/closure-library/closure/goog/images/check.gif
    deleted file mode 100644
    index 1ccde2667dd..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/check.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/close_box.gif b/src/database/third_party/closure-library/closure/goog/images/close_box.gif
    deleted file mode 100644
    index d829321aaf1..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/close_box.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/color-swatch-tick.gif b/src/database/third_party/closure-library/closure/goog/images/color-swatch-tick.gif
    deleted file mode 100644
    index 392ffcc4f4b..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/color-swatch-tick.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/dialog_close_box.gif b/src/database/third_party/closure-library/closure/goog/images/dialog_close_box.gif
    deleted file mode 100644
    index d9b1a658cbb..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/dialog_close_box.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/dimension-highlighted.png b/src/database/third_party/closure-library/closure/goog/images/dimension-highlighted.png
    deleted file mode 100644
    index e03cc5a5ac9..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/dimension-highlighted.png and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/dimension-unhighlighted.png b/src/database/third_party/closure-library/closure/goog/images/dimension-unhighlighted.png
    deleted file mode 100644
    index 7fdc0c0bb8a..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/dimension-unhighlighted.png and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/dropdn.gif b/src/database/third_party/closure-library/closure/goog/images/dropdn.gif
    deleted file mode 100644
    index 9aeef817d0f..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/dropdn.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/dropdn_disabled.gif b/src/database/third_party/closure-library/closure/goog/images/dropdn_disabled.gif
    deleted file mode 100644
    index 8db1c2ff4ca..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/dropdn_disabled.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/dropdown.gif b/src/database/third_party/closure-library/closure/goog/images/dropdown.gif
    deleted file mode 100644
    index edcd0b9a621..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/dropdown.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/gears_bluedot.gif b/src/database/third_party/closure-library/closure/goog/images/gears_bluedot.gif
    deleted file mode 100644
    index 091af46b728..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/gears_bluedot.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/gears_online.gif b/src/database/third_party/closure-library/closure/goog/images/gears_online.gif
    deleted file mode 100644
    index 1a40b086d35..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/gears_online.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/gears_paused.gif b/src/database/third_party/closure-library/closure/goog/images/gears_paused.gif
    deleted file mode 100644
    index 135da131bbf..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/gears_paused.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/gears_syncing.gif b/src/database/third_party/closure-library/closure/goog/images/gears_syncing.gif
    deleted file mode 100644
    index 18c3e94d0ad..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/gears_syncing.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/hsv-sprite-sm.gif b/src/database/third_party/closure-library/closure/goog/images/hsv-sprite-sm.gif
    deleted file mode 100644
    index 8eb9aa4a236..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/hsv-sprite-sm.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/hsv-sprite-sm.png b/src/database/third_party/closure-library/closure/goog/images/hsv-sprite-sm.png
    deleted file mode 100644
    index 470f8e0c967..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/hsv-sprite-sm.png and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/hsv-sprite.gif b/src/database/third_party/closure-library/closure/goog/images/hsv-sprite.gif
    deleted file mode 100644
    index c6a62bae567..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/hsv-sprite.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/hsv-sprite.png b/src/database/third_party/closure-library/closure/goog/images/hsv-sprite.png
    deleted file mode 100644
    index 1dc6870e901..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/hsv-sprite.png and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/hsva-sprite-sm.gif b/src/database/third_party/closure-library/closure/goog/images/hsva-sprite-sm.gif
    deleted file mode 100644
    index fd0584ea014..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/hsva-sprite-sm.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/hsva-sprite-sm.png b/src/database/third_party/closure-library/closure/goog/images/hsva-sprite-sm.png
    deleted file mode 100644
    index 04d01f5a1a9..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/hsva-sprite-sm.png and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/hsva-sprite.gif b/src/database/third_party/closure-library/closure/goog/images/hsva-sprite.gif
    deleted file mode 100644
    index 5605741b2b9..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/hsva-sprite.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/hsva-sprite.png b/src/database/third_party/closure-library/closure/goog/images/hsva-sprite.png
    deleted file mode 100644
    index 9e5ccce6ad2..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/hsva-sprite.png and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/left_anchor_bubble_bot.gif b/src/database/third_party/closure-library/closure/goog/images/left_anchor_bubble_bot.gif
    deleted file mode 100644
    index e70f1966e1b..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/left_anchor_bubble_bot.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/left_anchor_bubble_top.gif b/src/database/third_party/closure-library/closure/goog/images/left_anchor_bubble_top.gif
    deleted file mode 100644
    index c9ea2b1fcd7..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/left_anchor_bubble_top.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/menu-arrows.gif b/src/database/third_party/closure-library/closure/goog/images/menu-arrows.gif
    deleted file mode 100644
    index 751d66f7a82..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/menu-arrows.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/minus.png b/src/database/third_party/closure-library/closure/goog/images/minus.png
    deleted file mode 100644
    index 6c10c0df1ad..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/minus.png and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/no_anchor_bubble_bot.gif b/src/database/third_party/closure-library/closure/goog/images/no_anchor_bubble_bot.gif
    deleted file mode 100644
    index c10b36b94db..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/no_anchor_bubble_bot.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/no_anchor_bubble_top.gif b/src/database/third_party/closure-library/closure/goog/images/no_anchor_bubble_top.gif
    deleted file mode 100644
    index 8fc55d12001..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/no_anchor_bubble_top.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/offlineicons.png b/src/database/third_party/closure-library/closure/goog/images/offlineicons.png
    deleted file mode 100644
    index 7cd51c1342b..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/offlineicons.png and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/plus.png b/src/database/third_party/closure-library/closure/goog/images/plus.png
    deleted file mode 100644
    index f5dcd2cbc48..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/plus.png and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/ratingstars.gif b/src/database/third_party/closure-library/closure/goog/images/ratingstars.gif
    deleted file mode 100644
    index 27ba1f6cdbf..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/ratingstars.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/right_anchor_bubble_bot.gif b/src/database/third_party/closure-library/closure/goog/images/right_anchor_bubble_bot.gif
    deleted file mode 100644
    index 4e81e25e394..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/right_anchor_bubble_bot.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/right_anchor_bubble_top.gif b/src/database/third_party/closure-library/closure/goog/images/right_anchor_bubble_top.gif
    deleted file mode 100644
    index 70bedfbade9..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/right_anchor_bubble_top.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/toolbar-bg.png b/src/database/third_party/closure-library/closure/goog/images/toolbar-bg.png
    deleted file mode 100644
    index cb6791ffdde..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/toolbar-bg.png and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/toolbar-separator.gif b/src/database/third_party/closure-library/closure/goog/images/toolbar-separator.gif
    deleted file mode 100644
    index a97cad9dd67..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/toolbar-separator.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/toolbar_icons.gif b/src/database/third_party/closure-library/closure/goog/images/toolbar_icons.gif
    deleted file mode 100644
    index 8b62ce87a97..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/toolbar_icons.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/tree/I.png b/src/database/third_party/closure-library/closure/goog/images/tree/I.png
    deleted file mode 100644
    index 62a05d5c60d..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/tree/I.png and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/tree/cleardot.gif b/src/database/third_party/closure-library/closure/goog/images/tree/cleardot.gif
    deleted file mode 100644
    index 35d42e808f0..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/tree/cleardot.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/tree/tree.gif b/src/database/third_party/closure-library/closure/goog/images/tree/tree.gif
    deleted file mode 100644
    index 0c2393207a7..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/tree/tree.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/tree/tree.png b/src/database/third_party/closure-library/closure/goog/images/tree/tree.png
    deleted file mode 100644
    index 0dd0ef15ae8..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/tree/tree.png and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/images/ui_controls.jpg b/src/database/third_party/closure-library/closure/goog/images/ui_controls.jpg
    deleted file mode 100644
    index 4e07611215f..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/images/ui_controls.jpg and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/iter/iter.js b/src/database/third_party/closure-library/closure/goog/iter/iter.js
    deleted file mode 100644
    index 751caff6756..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/iter/iter.js
    +++ /dev/null
    @@ -1,1305 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Python style iteration utilities.
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -
    -goog.provide('goog.iter');
    -goog.provide('goog.iter.Iterable');
    -goog.provide('goog.iter.Iterator');
    -goog.provide('goog.iter.StopIteration');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.functions');
    -goog.require('goog.math');
    -
    -
    -/**
    - * @typedef {goog.iter.Iterator|{length:number}|{__iterator__}}
    - */
    -goog.iter.Iterable;
    -
    -
    -/**
    - * Singleton Error object that is used to terminate iterations.
    - * @const {!Error}
    - */
    -goog.iter.StopIteration = ('StopIteration' in goog.global) ?
    -    // For script engines that support legacy iterators.
    -    goog.global['StopIteration'] :
    -    Error('StopIteration');
    -
    -
    -
    -/**
    - * Class/interface for iterators.  An iterator needs to implement a {@code next}
    - * method and it needs to throw a {@code goog.iter.StopIteration} when the
    - * iteration passes beyond the end.  Iterators have no {@code hasNext} method.
    - * It is recommended to always use the helper functions to iterate over the
    - * iterator or in case you are only targeting JavaScript 1.7 for in loops.
    - * @constructor
    - * @template VALUE
    - */
    -goog.iter.Iterator = function() {};
    -
    -
    -/**
    - * Returns the next value of the iteration.  This will throw the object
    - * {@see goog.iter#StopIteration} when the iteration passes the end.
    - * @return {VALUE} Any object or value.
    - */
    -goog.iter.Iterator.prototype.next = function() {
    -  throw goog.iter.StopIteration;
    -};
    -
    -
    -/**
    - * Returns the {@code Iterator} object itself.  This is used to implement
    - * the iterator protocol in JavaScript 1.7
    - * @param {boolean=} opt_keys  Whether to return the keys or values. Default is
    - *     to only return the values.  This is being used by the for-in loop (true)
    - *     and the for-each-in loop (false).  Even though the param gives a hint
    - *     about what the iterator will return there is no guarantee that it will
    - *     return the keys when true is passed.
    - * @return {!goog.iter.Iterator<VALUE>} The object itself.
    - */
    -goog.iter.Iterator.prototype.__iterator__ = function(opt_keys) {
    -  return this;
    -};
    -
    -
    -/**
    - * Returns an iterator that knows how to iterate over the values in the object.
    - * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable  If the
    - *     object is an iterator it will be returned as is.  If the object has an
    - *     {@code __iterator__} method that will be called to get the value
    - *     iterator.  If the object is an array-like object we create an iterator
    - *     for that.
    - * @return {!goog.iter.Iterator<VALUE>} An iterator that knows how to iterate
    - *     over the values in {@code iterable}.
    - * @template VALUE
    - */
    -goog.iter.toIterator = function(iterable) {
    -  if (iterable instanceof goog.iter.Iterator) {
    -    return iterable;
    -  }
    -  if (typeof iterable.__iterator__ == 'function') {
    -    return iterable.__iterator__(false);
    -  }
    -  if (goog.isArrayLike(iterable)) {
    -    var i = 0;
    -    var newIter = new goog.iter.Iterator;
    -    newIter.next = function() {
    -      while (true) {
    -        if (i >= iterable.length) {
    -          throw goog.iter.StopIteration;
    -        }
    -        // Don't include deleted elements.
    -        if (!(i in iterable)) {
    -          i++;
    -          continue;
    -        }
    -        return iterable[i++];
    -      }
    -    };
    -    return newIter;
    -  }
    -
    -
    -  // TODO(arv): Should we fall back on goog.structs.getValues()?
    -  throw Error('Not implemented');
    -};
    -
    -
    -/**
    - * Calls a function for each element in the iterator with the element of the
    - * iterator passed as argument.
    - *
    - * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable  The iterator
    - *     to iterate over. If the iterable is an object {@code toIterator} will be
    - *     called on it.
    - * @param {function(this:THIS,VALUE,?,!goog.iter.Iterator<VALUE>)} f
    - *     The function to call for every element.  This function takes 3 arguments
    - *     (the element, undefined, and the iterator) and the return value is
    - *     irrelevant.  The reason for passing undefined as the second argument is
    - *     so that the same function can be used in {@see goog.array#forEach} as
    - *     well as others.  The third parameter is of type "number" for
    - *     arraylike objects, undefined, otherwise.
    - * @param {THIS=} opt_obj  The object to be used as the value of 'this' within
    - *     {@code f}.
    - * @template THIS, VALUE
    - */
    -goog.iter.forEach = function(iterable, f, opt_obj) {
    -  if (goog.isArrayLike(iterable)) {
    -    /** @preserveTry */
    -    try {
    -      // NOTES: this passes the index number to the second parameter
    -      // of the callback contrary to the documentation above.
    -      goog.array.forEach(/** @type {goog.array.ArrayLike} */(iterable), f,
    -                         opt_obj);
    -    } catch (ex) {
    -      if (ex !== goog.iter.StopIteration) {
    -        throw ex;
    -      }
    -    }
    -  } else {
    -    iterable = goog.iter.toIterator(iterable);
    -    /** @preserveTry */
    -    try {
    -      while (true) {
    -        f.call(opt_obj, iterable.next(), undefined, iterable);
    -      }
    -    } catch (ex) {
    -      if (ex !== goog.iter.StopIteration) {
    -        throw ex;
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Calls a function for every element in the iterator, and if the function
    - * returns true adds the element to a new iterator.
    - *
    - * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
    - *     to iterate over.
    - * @param {
    - *     function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f
    - *     The function to call for every element. This function takes 3 arguments
    - *     (the element, undefined, and the iterator) and should return a boolean.
    - *     If the return value is true the element will be included in the returned
    - *     iterator.  If it is false the element is not included.
    - * @param {THIS=} opt_obj The object to be used as the value of 'this' within
    - *     {@code f}.
    - * @return {!goog.iter.Iterator<VALUE>} A new iterator in which only elements
    - *     that passed the test are present.
    - * @template THIS, VALUE
    - */
    -goog.iter.filter = function(iterable, f, opt_obj) {
    -  var iterator = goog.iter.toIterator(iterable);
    -  var newIter = new goog.iter.Iterator;
    -  newIter.next = function() {
    -    while (true) {
    -      var val = iterator.next();
    -      if (f.call(opt_obj, val, undefined, iterator)) {
    -        return val;
    -      }
    -    }
    -  };
    -  return newIter;
    -};
    -
    -
    -/**
    - * Calls a function for every element in the iterator, and if the function
    - * returns false adds the element to a new iterator.
    - *
    - * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
    - *     to iterate over.
    - * @param {
    - *     function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f
    - *     The function to call for every element. This function takes 3 arguments
    - *     (the element, undefined, and the iterator) and should return a boolean.
    - *     If the return value is false the element will be included in the returned
    - *     iterator.  If it is true the element is not included.
    - * @param {THIS=} opt_obj The object to be used as the value of 'this' within
    - *     {@code f}.
    - * @return {!goog.iter.Iterator<VALUE>} A new iterator in which only elements
    - *     that did not pass the test are present.
    - * @template THIS, VALUE
    - */
    -goog.iter.filterFalse = function(iterable, f, opt_obj) {
    -  return goog.iter.filter(iterable, goog.functions.not(f), opt_obj);
    -};
    -
    -
    -/**
    - * Creates a new iterator that returns the values in a range.  This function
    - * can take 1, 2 or 3 arguments:
    - * <pre>
    - * range(5) same as range(0, 5, 1)
    - * range(2, 5) same as range(2, 5, 1)
    - * </pre>
    - *
    - * @param {number} startOrStop  The stop value if only one argument is provided.
    - *     The start value if 2 or more arguments are provided.  If only one
    - *     argument is used the start value is 0.
    - * @param {number=} opt_stop  The stop value.  If left out then the first
    - *     argument is used as the stop value.
    - * @param {number=} opt_step  The number to increment with between each call to
    - *     next.  This can be negative.
    - * @return {!goog.iter.Iterator<number>} A new iterator that returns the values
    - *     in the range.
    - */
    -goog.iter.range = function(startOrStop, opt_stop, opt_step) {
    -  var start = 0;
    -  var stop = startOrStop;
    -  var step = opt_step || 1;
    -  if (arguments.length > 1) {
    -    start = startOrStop;
    -    stop = opt_stop;
    -  }
    -  if (step == 0) {
    -    throw Error('Range step argument must not be zero');
    -  }
    -
    -  var newIter = new goog.iter.Iterator;
    -  newIter.next = function() {
    -    if (step > 0 && start >= stop || step < 0 && start <= stop) {
    -      throw goog.iter.StopIteration;
    -    }
    -    var rv = start;
    -    start += step;
    -    return rv;
    -  };
    -  return newIter;
    -};
    -
    -
    -/**
    - * Joins the values in a iterator with a delimiter.
    - * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
    - *     to get the values from.
    - * @param {string} deliminator  The text to put between the values.
    - * @return {string} The joined value string.
    - * @template VALUE
    - */
    -goog.iter.join = function(iterable, deliminator) {
    -  return goog.iter.toArray(iterable).join(deliminator);
    -};
    -
    -
    -/**
    - * For every element in the iterator call a function and return a new iterator
    - * with that value.
    - *
    - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
    - *     iterator to iterate over.
    - * @param {
    - *     function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):RESULT} f
    - *     The function to call for every element.  This function takes 3 arguments
    - *     (the element, undefined, and the iterator) and should return a new value.
    - * @param {THIS=} opt_obj The object to be used as the value of 'this' within
    - *     {@code f}.
    - * @return {!goog.iter.Iterator<RESULT>} A new iterator that returns the
    - *     results of applying the function to each element in the original
    - *     iterator.
    - * @template THIS, VALUE, RESULT
    - */
    -goog.iter.map = function(iterable, f, opt_obj) {
    -  var iterator = goog.iter.toIterator(iterable);
    -  var newIter = new goog.iter.Iterator;
    -  newIter.next = function() {
    -    var val = iterator.next();
    -    return f.call(opt_obj, val, undefined, iterator);
    -  };
    -  return newIter;
    -};
    -
    -
    -/**
    - * Passes every element of an iterator into a function and accumulates the
    - * result.
    - *
    - * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
    - *     to iterate over.
    - * @param {function(this:THIS,VALUE,VALUE):VALUE} f The function to call for
    - *     every element. This function takes 2 arguments (the function's previous
    - *     result or the initial value, and the value of the current element).
    - *     function(previousValue, currentElement) : newValue.
    - * @param {VALUE} val The initial value to pass into the function on the first
    - *     call.
    - * @param {THIS=} opt_obj  The object to be used as the value of 'this' within
    - *     f.
    - * @return {VALUE} Result of evaluating f repeatedly across the values of
    - *     the iterator.
    - * @template THIS, VALUE
    - */
    -goog.iter.reduce = function(iterable, f, val, opt_obj) {
    -  var rval = val;
    -  goog.iter.forEach(iterable, function(val) {
    -    rval = f.call(opt_obj, rval, val);
    -  });
    -  return rval;
    -};
    -
    -
    -/**
    - * Goes through the values in the iterator. Calls f for each of these, and if
    - * any of them returns true, this returns true (without checking the rest). If
    - * all return false this will return false.
    - *
    - * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
    - *     object.
    - * @param {
    - *     function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f
    - *     The function to call for every value. This function takes 3 arguments
    - *     (the value, undefined, and the iterator) and should return a boolean.
    - * @param {THIS=} opt_obj The object to be used as the value of 'this' within
    - *     {@code f}.
    - * @return {boolean} true if any value passes the test.
    - * @template THIS, VALUE
    - */
    -goog.iter.some = function(iterable, f, opt_obj) {
    -  iterable = goog.iter.toIterator(iterable);
    -  /** @preserveTry */
    -  try {
    -    while (true) {
    -      if (f.call(opt_obj, iterable.next(), undefined, iterable)) {
    -        return true;
    -      }
    -    }
    -  } catch (ex) {
    -    if (ex !== goog.iter.StopIteration) {
    -      throw ex;
    -    }
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Goes through the values in the iterator. Calls f for each of these and if any
    - * of them returns false this returns false (without checking the rest). If all
    - * return true this will return true.
    - *
    - * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
    - *     object.
    - * @param {
    - *     function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f
    - *     The function to call for every value. This function takes 3 arguments
    - *     (the value, undefined, and the iterator) and should return a boolean.
    - * @param {THIS=} opt_obj The object to be used as the value of 'this' within
    - *     {@code f}.
    - * @return {boolean} true if every value passes the test.
    - * @template THIS, VALUE
    - */
    -goog.iter.every = function(iterable, f, opt_obj) {
    -  iterable = goog.iter.toIterator(iterable);
    -  /** @preserveTry */
    -  try {
    -    while (true) {
    -      if (!f.call(opt_obj, iterable.next(), undefined, iterable)) {
    -        return false;
    -      }
    -    }
    -  } catch (ex) {
    -    if (ex !== goog.iter.StopIteration) {
    -      throw ex;
    -    }
    -  }
    -  return true;
    -};
    -
    -
    -/**
    - * Takes zero or more iterables and returns one iterator that will iterate over
    - * them in the order chained.
    - * @param {...!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} var_args Any
    - *     number of iterable objects.
    - * @return {!goog.iter.Iterator<VALUE>} Returns a new iterator that will
    - *     iterate over all the given iterables' contents.
    - * @template VALUE
    - */
    -goog.iter.chain = function(var_args) {
    -  return goog.iter.chainFromIterable(arguments);
    -};
    -
    -
    -/**
    - * Takes a single iterable containing zero or more iterables and returns one
    - * iterator that will iterate over each one in the order given.
    - * @see http://docs.python.org/2/library/itertools.html#itertools.chain.from_iterable
    - * @param {goog.iter.Iterable} iterable The iterable of iterables to chain.
    - * @return {!goog.iter.Iterator<VALUE>} Returns a new iterator that will
    - *     iterate over all the contents of the iterables contained within
    - *     {@code iterable}.
    - * @template VALUE
    - */
    -goog.iter.chainFromIterable = function(iterable) {
    -  var iterator = goog.iter.toIterator(iterable);
    -  var iter = new goog.iter.Iterator();
    -  var current = null;
    -
    -  iter.next = function() {
    -    while (true) {
    -      if (current == null) {
    -        var it = iterator.next();
    -        current = goog.iter.toIterator(it);
    -      }
    -      try {
    -        return current.next();
    -      } catch (ex) {
    -        if (ex !== goog.iter.StopIteration) {
    -          throw ex;
    -        }
    -        current = null;
    -      }
    -    }
    -  };
    -
    -  return iter;
    -};
    -
    -
    -/**
    - * Builds a new iterator that iterates over the original, but skips elements as
    - * long as a supplied function returns true.
    - * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
    - *     object.
    - * @param {
    - *     function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f
    - *     The function to call for every value. This function takes 3 arguments
    - *     (the value, undefined, and the iterator) and should return a boolean.
    - * @param {THIS=} opt_obj The object to be used as the value of 'this' within
    - *     {@code f}.
    - * @return {!goog.iter.Iterator<VALUE>} A new iterator that drops elements from
    - *     the original iterator as long as {@code f} is true.
    - * @template THIS, VALUE
    - */
    -goog.iter.dropWhile = function(iterable, f, opt_obj) {
    -  var iterator = goog.iter.toIterator(iterable);
    -  var newIter = new goog.iter.Iterator;
    -  var dropping = true;
    -  newIter.next = function() {
    -    while (true) {
    -      var val = iterator.next();
    -      if (dropping && f.call(opt_obj, val, undefined, iterator)) {
    -        continue;
    -      } else {
    -        dropping = false;
    -      }
    -      return val;
    -    }
    -  };
    -  return newIter;
    -};
    -
    -
    -/**
    - * Builds a new iterator that iterates over the original, but only as long as a
    - * supplied function returns true.
    - * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
    - *     object.
    - * @param {
    - *     function(this:THIS,VALUE,undefined,!goog.iter.Iterator<VALUE>):boolean} f
    - *     The function to call for every value. This function takes 3 arguments
    - *     (the value, undefined, and the iterator) and should return a boolean.
    - * @param {THIS=} opt_obj This is used as the 'this' object in f when called.
    - * @return {!goog.iter.Iterator<VALUE>} A new iterator that keeps elements in
    - *     the original iterator as long as the function is true.
    - * @template THIS, VALUE
    - */
    -goog.iter.takeWhile = function(iterable, f, opt_obj) {
    -  var iterator = goog.iter.toIterator(iterable);
    -  var iter = new goog.iter.Iterator();
    -  iter.next = function() {
    -    var val = iterator.next();
    -    if (f.call(opt_obj, val, undefined, iterator)) {
    -      return val;
    -    }
    -    throw goog.iter.StopIteration;
    -  };
    -  return iter;
    -};
    -
    -
    -/**
    - * Converts the iterator to an array
    - * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterator
    - *     to convert to an array.
    - * @return {!Array<VALUE>} An array of the elements the iterator iterates over.
    - * @template VALUE
    - */
    -goog.iter.toArray = function(iterable) {
    -  // Fast path for array-like.
    -  if (goog.isArrayLike(iterable)) {
    -    return goog.array.toArray(/** @type {!goog.array.ArrayLike} */(iterable));
    -  }
    -  iterable = goog.iter.toIterator(iterable);
    -  var array = [];
    -  goog.iter.forEach(iterable, function(val) {
    -    array.push(val);
    -  });
    -  return array;
    -};
    -
    -
    -/**
    - * Iterates over two iterables and returns true if they contain the same
    - * sequence of elements and have the same length.
    - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable1 The first
    - *     iterable object.
    - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable2 The second
    - *     iterable object.
    - * @param {function(VALUE,VALUE):boolean=} opt_equalsFn Optional comparison
    - *     function.
    - *     Should take two arguments to compare, and return true if the arguments
    - *     are equal. Defaults to {@link goog.array.defaultCompareEquality} which
    - *     compares the elements using the built-in '===' operator.
    - * @return {boolean} true if the iterables contain the same sequence of elements
    - *     and have the same length.
    - * @template VALUE
    - */
    -goog.iter.equals = function(iterable1, iterable2, opt_equalsFn) {
    -  var fillValue = {};
    -  var pairs = goog.iter.zipLongest(fillValue, iterable1, iterable2);
    -  var equalsFn = opt_equalsFn || goog.array.defaultCompareEquality;
    -  return goog.iter.every(pairs, function(pair) {
    -    return equalsFn(pair[0], pair[1]);
    -  });
    -};
    -
    -
    -/**
    - * Advances the iterator to the next position, returning the given default value
    - * instead of throwing an exception if the iterator has no more entries.
    - * @param {goog.iter.Iterator<VALUE>|goog.iter.Iterable} iterable The iterable
    - *     object.
    - * @param {VALUE} defaultValue The value to return if the iterator is empty.
    - * @return {VALUE} The next item in the iteration, or defaultValue if the
    - *     iterator was empty.
    - * @template VALUE
    - */
    -goog.iter.nextOrValue = function(iterable, defaultValue) {
    -  try {
    -    return goog.iter.toIterator(iterable).next();
    -  } catch (e) {
    -    if (e != goog.iter.StopIteration) {
    -      throw e;
    -    }
    -    return defaultValue;
    -  }
    -};
    -
    -
    -/**
    - * Cartesian product of zero or more sets.  Gives an iterator that gives every
    - * combination of one element chosen from each set.  For example,
    - * ([1, 2], [3, 4]) gives ([1, 3], [1, 4], [2, 3], [2, 4]).
    - * @see http://docs.python.org/library/itertools.html#itertools.product
    - * @param {...!goog.array.ArrayLike<VALUE>} var_args Zero or more sets, as
    - *     arrays.
    - * @return {!goog.iter.Iterator<!Array<VALUE>>} An iterator that gives each
    - *     n-tuple (as an array).
    - * @template VALUE
    - */
    -goog.iter.product = function(var_args) {
    -  var someArrayEmpty = goog.array.some(arguments, function(arr) {
    -    return !arr.length;
    -  });
    -
    -  // An empty set in a cartesian product gives an empty set.
    -  if (someArrayEmpty || !arguments.length) {
    -    return new goog.iter.Iterator();
    -  }
    -
    -  var iter = new goog.iter.Iterator();
    -  var arrays = arguments;
    -
    -  // The first indices are [0, 0, ...]
    -  var indicies = goog.array.repeat(0, arrays.length);
    -
    -  iter.next = function() {
    -
    -    if (indicies) {
    -      var retVal = goog.array.map(indicies, function(valueIndex, arrayIndex) {
    -        return arrays[arrayIndex][valueIndex];
    -      });
    -
    -      // Generate the next-largest indices for the next call.
    -      // Increase the rightmost index. If it goes over, increase the next
    -      // rightmost (like carry-over addition).
    -      for (var i = indicies.length - 1; i >= 0; i--) {
    -        // Assertion prevents compiler warning below.
    -        goog.asserts.assert(indicies);
    -        if (indicies[i] < arrays[i].length - 1) {
    -          indicies[i]++;
    -          break;
    -        }
    -
    -        // We're at the last indices (the last element of every array), so
    -        // the iteration is over on the next call.
    -        if (i == 0) {
    -          indicies = null;
    -          break;
    -        }
    -        // Reset the index in this column and loop back to increment the
    -        // next one.
    -        indicies[i] = 0;
    -      }
    -      return retVal;
    -    }
    -
    -    throw goog.iter.StopIteration;
    -  };
    -
    -  return iter;
    -};
    -
    -
    -/**
    - * Create an iterator to cycle over the iterable's elements indefinitely.
    - * For example, ([1, 2, 3]) would return : 1, 2, 3, 1, 2, 3, ...
    - * @see: http://docs.python.org/library/itertools.html#itertools.cycle.
    - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
    - *     iterable object.
    - * @return {!goog.iter.Iterator<VALUE>} An iterator that iterates indefinitely
    - *     over the values in {@code iterable}.
    - * @template VALUE
    - */
    -goog.iter.cycle = function(iterable) {
    -  var baseIterator = goog.iter.toIterator(iterable);
    -
    -  // We maintain a cache to store the iterable elements as we iterate
    -  // over them. The cache is used to return elements once we have
    -  // iterated over the iterable once.
    -  var cache = [];
    -  var cacheIndex = 0;
    -
    -  var iter = new goog.iter.Iterator();
    -
    -  // This flag is set after the iterable is iterated over once
    -  var useCache = false;
    -
    -  iter.next = function() {
    -    var returnElement = null;
    -
    -    // Pull elements off the original iterator if not using cache
    -    if (!useCache) {
    -      try {
    -        // Return the element from the iterable
    -        returnElement = baseIterator.next();
    -        cache.push(returnElement);
    -        return returnElement;
    -      } catch (e) {
    -        // If an exception other than StopIteration is thrown
    -        // or if there are no elements to iterate over (the iterable was empty)
    -        // throw an exception
    -        if (e != goog.iter.StopIteration || goog.array.isEmpty(cache)) {
    -          throw e;
    -        }
    -        // set useCache to true after we know that a 'StopIteration' exception
    -        // was thrown and the cache is not empty (to handle the 'empty iterable'
    -        // use case)
    -        useCache = true;
    -      }
    -    }
    -
    -    returnElement = cache[cacheIndex];
    -    cacheIndex = (cacheIndex + 1) % cache.length;
    -
    -    return returnElement;
    -  };
    -
    -  return iter;
    -};
    -
    -
    -/**
    - * Creates an iterator that counts indefinitely from a starting value.
    - * @see http://docs.python.org/2/library/itertools.html#itertools.count
    - * @param {number=} opt_start The starting value. Default is 0.
    - * @param {number=} opt_step The number to increment with between each call to
    - *     next. Negative and floating point numbers are allowed. Default is 1.
    - * @return {!goog.iter.Iterator<number>} A new iterator that returns the values
    - *     in the series.
    - */
    -goog.iter.count = function(opt_start, opt_step) {
    -  var counter = opt_start || 0;
    -  var step = goog.isDef(opt_step) ? opt_step : 1;
    -  var iter = new goog.iter.Iterator();
    -
    -  iter.next = function() {
    -    var returnValue = counter;
    -    counter += step;
    -    return returnValue;
    -  };
    -
    -  return iter;
    -};
    -
    -
    -/**
    - * Creates an iterator that returns the same object or value repeatedly.
    - * @param {VALUE} value Any object or value to repeat.
    - * @return {!goog.iter.Iterator<VALUE>} A new iterator that returns the
    - *     repeated value.
    - * @template VALUE
    - */
    -goog.iter.repeat = function(value) {
    -  var iter = new goog.iter.Iterator();
    -
    -  iter.next = goog.functions.constant(value);
    -
    -  return iter;
    -};
    -
    -
    -/**
    - * Creates an iterator that returns running totals from the numbers in
    - * {@code iterable}. For example, the array {@code [1, 2, 3, 4, 5]} yields
    - * {@code 1 -> 3 -> 6 -> 10 -> 15}.
    - * @see http://docs.python.org/3.2/library/itertools.html#itertools.accumulate
    - * @param {!goog.iter.Iterable<number>} iterable The iterable of numbers to
    - *     accumulate.
    - * @return {!goog.iter.Iterator<number>} A new iterator that returns the
    - *     numbers in the series.
    - */
    -goog.iter.accumulate = function(iterable) {
    -  var iterator = goog.iter.toIterator(iterable);
    -  var total = 0;
    -  var iter = new goog.iter.Iterator();
    -
    -  iter.next = function() {
    -    total += iterator.next();
    -    return total;
    -  };
    -
    -  return iter;
    -};
    -
    -
    -/**
    - * Creates an iterator that returns arrays containing the ith elements from the
    - * provided iterables. The returned arrays will be the same size as the number
    - * of iterables given in {@code var_args}. Once the shortest iterable is
    - * exhausted, subsequent calls to {@code next()} will throw
    - * {@code goog.iter.StopIteration}.
    - * @see http://docs.python.org/2/library/itertools.html#itertools.izip
    - * @param {...!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} var_args Any
    - *     number of iterable objects.
    - * @return {!goog.iter.Iterator<!Array<VALUE>>} A new iterator that returns
    - *     arrays of elements from the provided iterables.
    - * @template VALUE
    - */
    -goog.iter.zip = function(var_args) {
    -  var args = arguments;
    -  var iter = new goog.iter.Iterator();
    -
    -  if (args.length > 0) {
    -    var iterators = goog.array.map(args, goog.iter.toIterator);
    -    iter.next = function() {
    -      var arr = goog.array.map(iterators, function(it) {
    -        return it.next();
    -      });
    -      return arr;
    -    };
    -  }
    -
    -  return iter;
    -};
    -
    -
    -/**
    - * Creates an iterator that returns arrays containing the ith elements from the
    - * provided iterables. The returned arrays will be the same size as the number
    - * of iterables given in {@code var_args}. Shorter iterables will be extended
    - * with {@code fillValue}. Once the longest iterable is exhausted, subsequent
    - * calls to {@code next()} will throw {@code goog.iter.StopIteration}.
    - * @see http://docs.python.org/2/library/itertools.html#itertools.izip_longest
    - * @param {VALUE} fillValue The object or value used to fill shorter iterables.
    - * @param {...!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} var_args Any
    - *     number of iterable objects.
    - * @return {!goog.iter.Iterator<!Array<VALUE>>} A new iterator that returns
    - *     arrays of elements from the provided iterables.
    - * @template VALUE
    - */
    -goog.iter.zipLongest = function(fillValue, var_args) {
    -  var args = goog.array.slice(arguments, 1);
    -  var iter = new goog.iter.Iterator();
    -
    -  if (args.length > 0) {
    -    var iterators = goog.array.map(args, goog.iter.toIterator);
    -
    -    iter.next = function() {
    -      var iteratorsHaveValues = false;  // false when all iterators are empty.
    -      var arr = goog.array.map(iterators, function(it) {
    -        var returnValue;
    -        try {
    -          returnValue = it.next();
    -          // Iterator had a value, so we've not exhausted the iterators.
    -          // Set flag accordingly.
    -          iteratorsHaveValues = true;
    -        } catch (ex) {
    -          if (ex !== goog.iter.StopIteration) {
    -            throw ex;
    -          }
    -          returnValue = fillValue;
    -        }
    -        return returnValue;
    -      });
    -
    -      if (!iteratorsHaveValues) {
    -        throw goog.iter.StopIteration;
    -      }
    -      return arr;
    -    };
    -  }
    -
    -  return iter;
    -};
    -
    -
    -/**
    - * Creates an iterator that filters {@code iterable} based on a series of
    - * {@code selectors}. On each call to {@code next()}, one item is taken from
    - * both the {@code iterable} and {@code selectors} iterators. If the item from
    - * {@code selectors} evaluates to true, the item from {@code iterable} is given.
    - * Otherwise, it is skipped. Once either {@code iterable} or {@code selectors}
    - * is exhausted, subsequent calls to {@code next()} will throw
    - * {@code goog.iter.StopIteration}.
    - * @see http://docs.python.org/2/library/itertools.html#itertools.compress
    - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
    - *     iterable to filter.
    - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} selectors An
    - *     iterable of items to be evaluated in a boolean context to determine if
    - *     the corresponding element in {@code iterable} should be included in the
    - *     result.
    - * @return {!goog.iter.Iterator<VALUE>} A new iterator that returns the
    - *     filtered values.
    - * @template VALUE
    - */
    -goog.iter.compress = function(iterable, selectors) {
    -  var selectorIterator = goog.iter.toIterator(selectors);
    -
    -  return goog.iter.filter(iterable, function() {
    -    return !!selectorIterator.next();
    -  });
    -};
    -
    -
    -
    -/**
    - * Implements the {@code goog.iter.groupBy} iterator.
    - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
    - *     iterable to group.
    - * @param {function(...VALUE): KEY=} opt_keyFunc  Optional function for
    - *     determining the key value for each group in the {@code iterable}. Default
    - *     is the identity function.
    - * @constructor
    - * @extends {goog.iter.Iterator<!Array<?>>}
    - * @template KEY, VALUE
    - * @private
    - */
    -goog.iter.GroupByIterator_ = function(iterable, opt_keyFunc) {
    -
    -  /**
    -   * The iterable to group, coerced to an iterator.
    -   * @type {!goog.iter.Iterator}
    -   */
    -  this.iterator = goog.iter.toIterator(iterable);
    -
    -  /**
    -   * A function for determining the key value for each element in the iterable.
    -   * If no function is provided, the identity function is used and returns the
    -   * element unchanged.
    -   * @type {function(...VALUE): KEY}
    -   */
    -  this.keyFunc = opt_keyFunc || goog.functions.identity;
    -
    -  /**
    -   * The target key for determining the start of a group.
    -   * @type {KEY}
    -   */
    -  this.targetKey;
    -
    -  /**
    -   * The current key visited during iteration.
    -   * @type {KEY}
    -   */
    -  this.currentKey;
    -
    -  /**
    -   * The current value being added to the group.
    -   * @type {VALUE}
    -   */
    -  this.currentValue;
    -};
    -goog.inherits(goog.iter.GroupByIterator_, goog.iter.Iterator);
    -
    -
    -/** @override */
    -goog.iter.GroupByIterator_.prototype.next = function() {
    -  while (this.currentKey == this.targetKey) {
    -    this.currentValue = this.iterator.next();  // Exits on StopIteration
    -    this.currentKey = this.keyFunc(this.currentValue);
    -  }
    -  this.targetKey = this.currentKey;
    -  return [this.currentKey, this.groupItems_(this.targetKey)];
    -};
    -
    -
    -/**
    - * Performs the grouping of objects using the given key.
    - * @param {KEY} targetKey  The target key object for the group.
    - * @return {!Array<VALUE>} An array of grouped objects.
    - * @private
    - */
    -goog.iter.GroupByIterator_.prototype.groupItems_ = function(targetKey) {
    -  var arr = [];
    -  while (this.currentKey == targetKey) {
    -    arr.push(this.currentValue);
    -    try {
    -      this.currentValue = this.iterator.next();
    -    } catch (ex) {
    -      if (ex !== goog.iter.StopIteration) {
    -        throw ex;
    -      }
    -      break;
    -    }
    -    this.currentKey = this.keyFunc(this.currentValue);
    -  }
    -  return arr;
    -};
    -
    -
    -/**
    - * Creates an iterator that returns arrays containing elements from the
    - * {@code iterable} grouped by a key value. For iterables with repeated
    - * elements (i.e. sorted according to a particular key function), this function
    - * has a {@code uniq}-like effect. For example, grouping the array:
    - * {@code [A, B, B, C, C, A]} produces
    - * {@code [A, [A]], [B, [B, B]], [C, [C, C]], [A, [A]]}.
    - * @see http://docs.python.org/2/library/itertools.html#itertools.groupby
    - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
    - *     iterable to group.
    - * @param {function(...VALUE): KEY=} opt_keyFunc  Optional function for
    - *     determining the key value for each group in the {@code iterable}. Default
    - *     is the identity function.
    - * @return {!goog.iter.Iterator<!Array<?>>} A new iterator that returns
    - *     arrays of consecutive key and groups.
    - * @template KEY, VALUE
    - */
    -goog.iter.groupBy = function(iterable, opt_keyFunc) {
    -  return new goog.iter.GroupByIterator_(iterable, opt_keyFunc);
    -};
    -
    -
    -/**
    - * Gives an iterator that gives the result of calling the given function
    - * <code>f</code> with the arguments taken from the next element from
    - * <code>iterable</code> (the elements are expected to also be iterables).
    - *
    - * Similar to {@see goog.iter#map} but allows the function to accept multiple
    - * arguments from the iterable.
    - *
    - * @param {!goog.iter.Iterable<!goog.iter.Iterable>} iterable The iterable of
    - *     iterables to iterate over.
    - * @param {function(this:THIS,...*):RESULT} f The function to call for every
    - *     element.  This function takes N+2 arguments, where N represents the
    - *     number of items from the next element of the iterable. The two
    - *     additional arguments passed to the function are undefined and the
    - *     iterator itself. The function should return a new value.
    - * @param {THIS=} opt_obj The object to be used as the value of 'this' within
    - *     {@code f}.
    - * @return {!goog.iter.Iterator<RESULT>} A new iterator that returns the
    - *     results of applying the function to each element in the original
    - *     iterator.
    - * @template THIS, RESULT
    - */
    -goog.iter.starMap = function(iterable, f, opt_obj) {
    -  var iterator = goog.iter.toIterator(iterable);
    -  var iter = new goog.iter.Iterator();
    -
    -  iter.next = function() {
    -    var args = goog.iter.toArray(iterator.next());
    -    return f.apply(opt_obj, goog.array.concat(args, undefined, iterator));
    -  };
    -
    -  return iter;
    -};
    -
    -
    -/**
    - * Returns an array of iterators each of which can iterate over the values in
    - * {@code iterable} without advancing the others.
    - * @see http://docs.python.org/2/library/itertools.html#itertools.tee
    - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
    - *     iterable to tee.
    - * @param {number=} opt_num  The number of iterators to create. Default is 2.
    - * @return {!Array<goog.iter.Iterator<VALUE>>} An array of iterators.
    - * @template VALUE
    - */
    -goog.iter.tee = function(iterable, opt_num) {
    -  var iterator = goog.iter.toIterator(iterable);
    -  var num = goog.isNumber(opt_num) ? opt_num : 2;
    -  var buffers = goog.array.map(goog.array.range(num), function() {
    -    return [];
    -  });
    -
    -  var addNextIteratorValueToBuffers = function() {
    -    var val = iterator.next();
    -    goog.array.forEach(buffers, function(buffer) {
    -      buffer.push(val);
    -    });
    -  };
    -
    -  var createIterator = function(buffer) {
    -    // Each tee'd iterator has an associated buffer (initially empty). When a
    -    // tee'd iterator's buffer is empty, it calls
    -    // addNextIteratorValueToBuffers(), adding the next value to all tee'd
    -    // iterators' buffers, and then returns that value. This allows each
    -    // iterator to be advanced independently.
    -    var iter = new goog.iter.Iterator();
    -
    -    iter.next = function() {
    -      if (goog.array.isEmpty(buffer)) {
    -        addNextIteratorValueToBuffers();
    -      }
    -      goog.asserts.assert(!goog.array.isEmpty(buffer));
    -      return buffer.shift();
    -    };
    -
    -    return iter;
    -  };
    -
    -  return goog.array.map(buffers, createIterator);
    -};
    -
    -
    -/**
    - * Creates an iterator that returns arrays containing a count and an element
    - * obtained from the given {@code iterable}.
    - * @see http://docs.python.org/2/library/functions.html#enumerate
    - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
    - *     iterable to enumerate.
    - * @param {number=} opt_start  Optional starting value. Default is 0.
    - * @return {!goog.iter.Iterator<!Array<?>>} A new iterator containing
    - *     count/item pairs.
    - * @template VALUE
    - */
    -goog.iter.enumerate = function(iterable, opt_start) {
    -  return goog.iter.zip(goog.iter.count(opt_start), iterable);
    -};
    -
    -
    -/**
    - * Creates an iterator that returns the first {@code limitSize} elements from an
    - * iterable. If this number is greater than the number of elements in the
    - * iterable, all the elements are returned.
    - * @see http://goo.gl/V0sihp Inspired by the limit iterator in Guava.
    - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
    - *     iterable to limit.
    - * @param {number} limitSize  The maximum number of elements to return.
    - * @return {!goog.iter.Iterator<VALUE>} A new iterator containing
    - *     {@code limitSize} elements.
    - * @template VALUE
    - */
    -goog.iter.limit = function(iterable, limitSize) {
    -  goog.asserts.assert(goog.math.isInt(limitSize) && limitSize >= 0);
    -
    -  var iterator = goog.iter.toIterator(iterable);
    -
    -  var iter = new goog.iter.Iterator();
    -  var remaining = limitSize;
    -
    -  iter.next = function() {
    -    if (remaining-- > 0) {
    -      return iterator.next();
    -    }
    -    throw goog.iter.StopIteration;
    -  };
    -
    -  return iter;
    -};
    -
    -
    -/**
    - * Creates an iterator that is advanced {@code count} steps ahead. Consumed
    - * values are silently discarded. If {@code count} is greater than the number
    - * of elements in {@code iterable}, an empty iterator is returned. Subsequent
    - * calls to {@code next()} will throw {@code goog.iter.StopIteration}.
    - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
    - *     iterable to consume.
    - * @param {number} count  The number of elements to consume from the iterator.
    - * @return {!goog.iter.Iterator<VALUE>} An iterator advanced zero or more steps
    - *     ahead.
    - * @template VALUE
    - */
    -goog.iter.consume = function(iterable, count) {
    -  goog.asserts.assert(goog.math.isInt(count) && count >= 0);
    -
    -  var iterator = goog.iter.toIterator(iterable);
    -
    -  while (count-- > 0) {
    -    goog.iter.nextOrValue(iterator, null);
    -  }
    -
    -  return iterator;
    -};
    -
    -
    -/**
    - * Creates an iterator that returns a range of elements from an iterable.
    - * Similar to {@see goog.array#slice} but does not support negative indexes.
    - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
    - *     iterable to slice.
    - * @param {number} start  The index of the first element to return.
    - * @param {number=} opt_end  The index after the last element to return. If
    - *     defined, must be greater than or equal to {@code start}.
    - * @return {!goog.iter.Iterator<VALUE>} A new iterator containing a slice of
    - *     the original.
    - * @template VALUE
    - */
    -goog.iter.slice = function(iterable, start, opt_end) {
    -  goog.asserts.assert(goog.math.isInt(start) && start >= 0);
    -
    -  var iterator = goog.iter.consume(iterable, start);
    -
    -  if (goog.isNumber(opt_end)) {
    -    goog.asserts.assert(
    -        goog.math.isInt(/** @type {number} */ (opt_end)) && opt_end >= start);
    -    iterator = goog.iter.limit(iterator, opt_end - start /* limitSize */);
    -  }
    -
    -  return iterator;
    -};
    -
    -
    -/**
    - * Checks an array for duplicate elements.
    - * @param {Array<VALUE>|goog.array.ArrayLike} arr The array to check for
    - *     duplicates.
    - * @return {boolean} True, if the array contains duplicates, false otherwise.
    - * @private
    - * @template VALUE
    - */
    -// TODO(user): Consider moving this into goog.array as a public function.
    -goog.iter.hasDuplicates_ = function(arr) {
    -  var deduped = [];
    -  goog.array.removeDuplicates(arr, deduped);
    -  return arr.length != deduped.length;
    -};
    -
    -
    -/**
    - * Creates an iterator that returns permutations of elements in
    - * {@code iterable}.
    - *
    - * Permutations are obtained by taking the Cartesian product of
    - * {@code opt_length} iterables and filtering out those with repeated
    - * elements. For example, the permutations of {@code [1,2,3]} are
    - * {@code [[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]]}.
    - * @see http://docs.python.org/2/library/itertools.html#itertools.permutations
    - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
    - *     iterable from which to generate permutations.
    - * @param {number=} opt_length Length of each permutation. If omitted, defaults
    - *     to the length of {@code iterable}.
    - * @return {!goog.iter.Iterator<!Array<VALUE>>} A new iterator containing the
    - *     permutations of {@code iterable}.
    - * @template VALUE
    - */
    -goog.iter.permutations = function(iterable, opt_length) {
    -  var elements = goog.iter.toArray(iterable);
    -  var length = goog.isNumber(opt_length) ? opt_length : elements.length;
    -
    -  var sets = goog.array.repeat(elements, length);
    -  var product = goog.iter.product.apply(undefined, sets);
    -
    -  return goog.iter.filter(product, function(arr) {
    -    return !goog.iter.hasDuplicates_(arr);
    -  });
    -};
    -
    -
    -/**
    - * Creates an iterator that returns combinations of elements from
    - * {@code iterable}.
    - *
    - * Combinations are obtained by taking the {@see goog.iter#permutations} of
    - * {@code iterable} and filtering those whose elements appear in the order they
    - * are encountered in {@code iterable}. For example, the 3-length combinations
    - * of {@code [0,1,2,3]} are {@code [[0,1,2], [0,1,3], [0,2,3], [1,2,3]]}.
    - * @see http://docs.python.org/2/library/itertools.html#itertools.combinations
    - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
    - *     iterable from which to generate combinations.
    - * @param {number} length The length of each combination.
    - * @return {!goog.iter.Iterator<!Array<VALUE>>} A new iterator containing
    - *     combinations from the {@code iterable}.
    - * @template VALUE
    - */
    -goog.iter.combinations = function(iterable, length) {
    -  var elements = goog.iter.toArray(iterable);
    -  var indexes = goog.iter.range(elements.length);
    -  var indexIterator = goog.iter.permutations(indexes, length);
    -  // sortedIndexIterator will now give arrays of with the given length that
    -  // indicate what indexes into "elements" should be returned on each iteration.
    -  var sortedIndexIterator = goog.iter.filter(indexIterator, function(arr) {
    -    return goog.array.isSorted(arr);
    -  });
    -
    -  var iter = new goog.iter.Iterator();
    -
    -  function getIndexFromElements(index) {
    -    return elements[index];
    -  }
    -
    -  iter.next = function() {
    -    return goog.array.map(
    -        /** @type {!Array<number>} */
    -        (sortedIndexIterator.next()), getIndexFromElements);
    -  };
    -
    -  return iter;
    -};
    -
    -
    -/**
    - * Creates an iterator that returns combinations of elements from
    - * {@code iterable}, with repeated elements possible.
    - *
    - * Combinations are obtained by taking the Cartesian product of {@code length}
    - * iterables and filtering those whose elements appear in the order they are
    - * encountered in {@code iterable}. For example, the 2-length combinations of
    - * {@code [1,2,3]} are {@code [[1,1], [1,2], [1,3], [2,2], [2,3], [3,3]]}.
    - * @see http://docs.python.org/2/library/itertools.html#itertools.combinations_with_replacement
    - * @see http://en.wikipedia.org/wiki/Combination#Number_of_combinations_with_repetition
    - * @param {!goog.iter.Iterator<VALUE>|!goog.iter.Iterable} iterable The
    - *     iterable to combine.
    - * @param {number} length The length of each combination.
    - * @return {!goog.iter.Iterator<!Array<VALUE>>} A new iterator containing
    - *     combinations from the {@code iterable}.
    - * @template VALUE
    - */
    -goog.iter.combinationsWithReplacement = function(iterable, length) {
    -  var elements = goog.iter.toArray(iterable);
    -  var indexes = goog.array.range(elements.length);
    -  var sets = goog.array.repeat(indexes, length);
    -  var indexIterator = goog.iter.product.apply(undefined, sets);
    -  // sortedIndexIterator will now give arrays of with the given length that
    -  // indicate what indexes into "elements" should be returned on each iteration.
    -  var sortedIndexIterator = goog.iter.filter(indexIterator, function(arr) {
    -    return goog.array.isSorted(arr);
    -  });
    -
    -  var iter = new goog.iter.Iterator();
    -
    -  function getIndexFromElements(index) {
    -    return elements[index];
    -  }
    -
    -  iter.next = function() {
    -    return goog.array.map(
    -        /** @type {!Array<number>} */
    -        (sortedIndexIterator.next()), getIndexFromElements);
    -  };
    -
    -  return iter;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/iter/iter_test.html b/src/database/third_party/closure-library/closure/goog/iter/iter_test.html
    deleted file mode 100644
    index e678f77e8e3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/iter/iter_test.html
    +++ /dev/null
    @@ -1,27 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.iter
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.iterTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="t1" style="display:none">
    -   <span>0</span>
    -   <span>1</span>
    -   <span>2</span>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/iter/iter_test.js b/src/database/third_party/closure-library/closure/goog/iter/iter_test.js
    deleted file mode 100644
    index ea29c655cfe..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/iter/iter_test.js
    +++ /dev/null
    @@ -1,867 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.iterTest');
    -goog.setTestOnly('goog.iterTest');
    -
    -goog.require('goog.iter');
    -goog.require('goog.iter.Iterator');
    -goog.require('goog.iter.StopIteration');
    -goog.require('goog.testing.jsunit');
    -
    -function ArrayIterator(array) {
    -  this.array_ = array;
    -  this.current_ = 0;
    -}
    -goog.inherits(ArrayIterator, goog.iter.Iterator);
    -
    -ArrayIterator.prototype.next = function() {
    -  if (this.current_ >= this.array_.length) {
    -    throw goog.iter.StopIteration;
    -  }
    -  return this.array_[this.current_++];
    -};
    -
    -function testForEach() {
    -  var s = '';
    -  var iter = new ArrayIterator(['a', 'b', 'c', 'd']);
    -  goog.iter.forEach(iter, function(val, index, iter2) {
    -    assertEquals(iter, iter2);
    -    assertEquals('index should be undefined', 'undefined', typeof index);
    -    s += val;
    -  });
    -  assertEquals('abcd', s);
    -}
    -
    -function testJoin() {
    -  var iter = new ArrayIterator(['a', 'b', 'c', 'd']);
    -  assertEquals('abcd', goog.iter.join(iter, ''));
    -
    -  iter = new ArrayIterator(['a', 'b', 'c', 'd']);
    -  assertEquals('a,b,c,d', goog.iter.join(iter, ','));
    -
    -  // make sure everything is treated as strings
    -  iter = new ArrayIterator([0, 1, 2, 3]);
    -  assertEquals('0123', goog.iter.join(iter, ''));
    -
    -  iter = new ArrayIterator([0, 1, 2, 3]);
    -  assertEquals('0919293', goog.iter.join(iter, 9));
    -
    -  // Joining an empty iterator should result in an empty string
    -  iter = new ArrayIterator([]);
    -  assertEquals('', goog.iter.join(iter, ','));
    -
    -}
    -
    -function testRange() {
    -  var iter = goog.iter.range(0, 5, 1);
    -  assertEquals('01234', goog.iter.join(iter, ''));
    -
    -  iter = goog.iter.range(0, 5, 2);
    -  assertEquals('024', goog.iter.join(iter, ''));
    -
    -  iter = goog.iter.range(0, 5, 5);
    -  assertEquals('0', goog.iter.join(iter, ''));
    -
    -  iter = goog.iter.range(0, 5, 10);
    -  assertEquals('0', goog.iter.join(iter, ''));
    -
    -  // negative step
    -  var iter = goog.iter.range(5, 0, -1);
    -  assertEquals('54321', goog.iter.join(iter, ''));
    -
    -
    -  iter = goog.iter.range(5, 0, -2);
    -  assertEquals('531', goog.iter.join(iter, ''));
    -
    -  iter = goog.iter.range(5, 0, -5);
    -  assertEquals('5', goog.iter.join(iter, ''));
    -
    -  iter = goog.iter.range(5, 0, -10);
    -  assertEquals('5', goog.iter.join(iter, ''));
    -
    -  // wrong direction should result in empty iterator
    -  iter = goog.iter.range(0, 5, -1);
    -  assertEquals('', goog.iter.join(iter, ''));
    -
    -  iter = goog.iter.range(5, 0, 1);
    -  assertEquals('', goog.iter.join(iter, ''));
    -
    -  // a step of 0 is not allowed
    -  goog.iter.range(0, 5, 0);
    -
    -  // test the opt args
    -  iter = goog.iter.range(0, 5);
    -  assertEquals('01234', goog.iter.join(iter, ''));
    -
    -  iter = goog.iter.range(5);
    -  assertEquals('01234', goog.iter.join(iter, ''));
    -
    -}
    -
    -function testFilter() {
    -  var iter = goog.iter.range(5);
    -  var iter2 = goog.iter.filter(iter, function(val, index, iter3) {
    -    assertEquals(iter, iter3);
    -    assertEquals('index should be undefined', 'undefined', typeof index);
    -    return val > 1;
    -  });
    -
    -  assertEquals('234', goog.iter.join(iter2, ''));
    -
    -  // Chaining filters
    -  iter = goog.iter.range(10);
    -  var sb = [];
    -  var evens = goog.iter.filter(iter, function(v) {
    -    sb.push('a' + v);
    -    return v % 2 == 0;
    -  });
    -  var evens2 = goog.iter.filter(evens, function(v) {
    -    sb.push('b' + v);
    -    return v >= 5;
    -  });
    -
    -  assertEquals('68', goog.iter.join(evens2, ''));
    -  // Note the order here. The next calls are done lazily.
    -  assertEquals('a0b0a1a2b2a3a4b4a5a6b6a7a8b8a9', sb.join(''));
    -
    -}
    -
    -function testFilterFalse() {
    -  var iter = goog.iter.range(5);
    -  var iter2 = goog.iter.filterFalse(iter, function(val, index, iter3) {
    -    assertEquals(iter, iter3);
    -    assertEquals('index should be undefined', 'undefined', typeof index);
    -    return val < 2;
    -  });
    -
    -  assertEquals('234', goog.iter.join(iter2, ''));
    -
    -  // Chaining filters
    -  iter = goog.iter.range(10);
    -  var sb = [];
    -  var odds = goog.iter.filterFalse(iter, function(v) {
    -    sb.push('a' + v);
    -    return v % 2 == 0;
    -  });
    -  var odds2 = goog.iter.filterFalse(odds, function(v) {
    -    sb.push('b' + v);
    -    return v <= 5;
    -  });
    -
    -  assertEquals('79', goog.iter.join(odds2, ''));
    -  // Note the order here. The next calls are done lazily.
    -  assertEquals('a0a1b1a2a3b3a4a5b5a6a7b7a8a9b9', sb.join(''));
    -
    -}
    -
    -function testMap() {
    -  var iter = goog.iter.range(4);
    -  var iter2 = goog.iter.map(iter, function(val, index, iter3) {
    -    assertEquals(iter, iter3);
    -    assertEquals('index should be undefined', 'undefined', typeof index);
    -    return val * val;
    -  });
    -  assertEquals('0149', goog.iter.join(iter2, ''));
    -}
    -
    -function testReduce() {
    -  var iter = goog.iter.range(1, 5);
    -  assertEquals(
    -      10, // 1 + 2 + 3 + 4
    -      goog.iter.reduce(iter, function(val, el) {
    -        return val + el;
    -      }, 0));
    -}
    -
    -function testReduce2() {
    -  var iter = goog.iter.range(1, 5);
    -  assertEquals(
    -      24, // 4!
    -      goog.iter.reduce(iter, function(val, el) {
    -        return val * el;
    -      }, 1));
    -}
    -
    -function testSome() {
    -  var iter = goog.iter.range(5);
    -  var b = goog.iter.some(iter, function(val, index, iter3) {
    -    assertEquals(iter, iter3);
    -    assertEquals('index should be undefined', 'undefined', typeof index);
    -    return val > 1;
    -  });
    -  assertTrue(b);
    -  iter = goog.iter.range(5);
    -  b = goog.iter.some(iter, function(val, index, iter3) {
    -    assertEquals(iter, iter3);
    -    assertEquals('index should be undefined', 'undefined', typeof index);
    -    return val > 100;
    -  });
    -  assertFalse(b);
    -}
    -
    -
    -function testEvery() {
    -  var iter = goog.iter.range(5);
    -  var b = goog.iter.every(iter, function(val, index, iter3) {
    -    assertEquals(iter, iter3);
    -    assertEquals('index should be undefined', 'undefined', typeof index);
    -    return val >= 0;
    -  });
    -  assertTrue(b);
    -  iter = goog.iter.range(5);
    -  b = goog.iter.every(iter, function(val, index, iter3) {
    -    assertEquals(iter, iter3);
    -    assertEquals('index should be undefined', 'undefined', typeof index);
    -    return val > 1;
    -  });
    -  assertFalse(b);
    -}
    -
    -function testChain() {
    -  var iter = goog.iter.range(0, 2);
    -  var iter2 = goog.iter.range(2, 4);
    -  var iter3 = goog.iter.range(4, 6);
    -  var iter4 = goog.iter.chain(iter, iter2, iter3);
    -
    -  assertEquals('012345', goog.iter.join(iter4, ''));
    -
    -  // empty iter
    -  iter = new goog.iter.Iterator;
    -  iter2 = goog.iter.chain(iter);
    -  assertEquals('', goog.iter.join(iter2, ''));
    -
    -  // no args
    -  iter2 = goog.iter.chain();
    -  assertEquals('', goog.iter.join(iter2, ''));
    -
    -  // arrays
    -  var arr = [0, 1];
    -  var arr2 = [2, 3];
    -  var arr3 = [4, 5];
    -  iter = goog.iter.chain(arr, arr2, arr3);
    -  assertEquals('012345', goog.iter.join(iter, ''));
    -}
    -
    -function testChainFromIterable() {
    -  var arg = [0, 1];
    -  var arg2 = [2, 3];
    -  var arg3 = goog.iter.range(4, 6);
    -  var iter = goog.iter.chainFromIterable([arg, arg2, arg3]);
    -  assertEquals('012345', goog.iter.join(iter, ''));
    -}
    -
    -function testChainFromIterable2() {
    -  var arg = goog.iter.zip([0, 3], [1, 4], [2, 5]);
    -  var iter = goog.iter.chainFromIterable(arg);
    -  assertEquals('012345', goog.iter.join(iter, ''));
    -}
    -
    -function testDropWhile() {
    -  var iter = goog.iter.range(10);
    -  var iter2 = goog.iter.dropWhile(iter, function(val, index, iter3) {
    -    assertEquals(iter, iter3);
    -    assertEquals('index should be undefined', 'undefined', typeof index);
    -    return val < 5;
    -  });
    -
    -  assertEquals('56789', goog.iter.join(iter2, ''));
    -}
    -
    -function testDropWhile2() {
    -  var iter = goog.iter.range(10);
    -  var iter2 = goog.iter.dropWhile(iter, function(val, index, iter3) {
    -    assertEquals(iter, iter3);
    -    assertEquals('index should be undefined', 'undefined', typeof index);
    -    return val != 5;
    -  });
    -
    -  assertEquals('56789', goog.iter.join(iter2, ''));
    -}
    -
    -
    -function testTakeWhile() {
    -  var iter = goog.iter.range(10);
    -  var iter2 = goog.iter.takeWhile(iter, function(val, index, iter3) {
    -    assertEquals(iter, iter3);
    -    assertEquals('index should be undefined', 'undefined', typeof index);
    -    return val < 5;
    -  });
    -
    -  assertEquals('01234', goog.iter.join(iter2, ''));
    -
    -  // next() should not have been called on iter after the first failure and
    -  // therefore it should contain some elements.  5 failed so we should have
    -  // the rest
    -  assertEquals('6789', goog.iter.join(iter, ''));
    -}
    -
    -function testTakeWhile2() {
    -  var iter = goog.iter.range(10);
    -  var iter2 = goog.iter.takeWhile(iter, function(val, index, iter3) {
    -    assertEquals(iter, iter3);
    -    assertEquals('index should be undefined', 'undefined', typeof index);
    -    return val != 5;
    -  });
    -
    -  assertEquals('01234', goog.iter.join(iter2, ''));
    -
    -  // next() should not have been called on iter after the first failure and
    -  // therefore it should contain some elements.  5 failed so we should have
    -  // the rest
    -  assertEquals('6789', goog.iter.join(iter, ''));
    -}
    -
    -function testToArray() {
    -  var iter = goog.iter.range(5);
    -  var array = goog.iter.toArray(iter);
    -  assertEquals('01234', array.join(''));
    -
    -  // Empty
    -  iter = new goog.iter.Iterator;
    -  array = goog.iter.toArray(iter);
    -  assertEquals('Empty iterator to array', '', array.join(''));
    -}
    -
    -function testToArray2() {
    -  var iterable = [0, 1, 2, 3, 4];
    -  var array = goog.iter.toArray(iterable);
    -  assertEquals('01234', array.join(''));
    -
    -  // Empty
    -  iterable = [];
    -  array = goog.iter.toArray(iterable);
    -  assertEquals('Empty iterator to array', '', array.join(''));
    -}
    -
    -function testEquals() {
    -  var iter = goog.iter.range(5);
    -  var iter2 = goog.iter.range(5);
    -  assertTrue('Equal iterators', goog.iter.equals(iter, iter2));
    -
    -  iter = goog.iter.range(4);
    -  iter2 = goog.iter.range(5);
    -  assertFalse('Second one is longer', goog.iter.equals(iter, iter2));
    -
    -  iter = goog.iter.range(5);
    -  iter2 = goog.iter.range(4);
    -  assertFalse('First one is longer', goog.iter.equals(iter, iter2));
    -
    -  // 2 empty iterators
    -  iter = new goog.iter.Iterator;
    -  iter2 = new goog.iter.Iterator;
    -  assertTrue('Two empty iterators are equal', goog.iter.equals(iter, iter2));
    -
    -  iter = goog.iter.range(4);
    -  assertFalse('Same iterator', goog.iter.equals(iter, iter));
    -
    -  // equality function
    -  iter = goog.iter.toIterator(['A', 'B', 'C']);
    -  iter2 = goog.iter.toIterator(['a', 'b', 'c']);
    -  var equalsFn = function(a, b) {
    -    return a.toLowerCase() == b.toLowerCase();
    -  };
    -  assertTrue('Case-insensitive equal', goog.iter.equals(iter, iter2, equalsFn));
    -}
    -
    -
    -function testToIterator() {
    -  var iter = new goog.iter.range(5);
    -  var iter2 = goog.iter.toIterator(iter);
    -  assertEquals('toIterator on an iterator should return the same obejct',
    -               iter, iter2);
    -
    -  var iterLikeObject = {
    -    next: function() {
    -      throw goog.iter.StopIteration;
    -    }
    -  };
    -  var obj = {
    -    __iterator__: function(opt_keys) {
    -      assertFalse(
    -          '__iterator__ should always be called with false in toIterator',
    -          opt_keys);
    -      return iterLikeObject;
    -    }
    -  };
    -
    -  assertEquals('Should return the return value of __iterator_(false)',
    -               iterLikeObject, goog.iter.toIterator(obj));
    -
    -  // Array
    -  var array = [0, 1, 2, 3, 4];
    -  iter = goog.iter.toIterator(array);
    -  assertEquals('01234', goog.iter.join(iter, ''));
    -
    -  // Array like
    -  var arrayLike = {'0': 0, '1': 1, '2': 2, length: 3};
    -  iter = goog.iter.toIterator(arrayLike);
    -  assertEquals('012', goog.iter.join(iter, ''));
    -
    -  // DOM
    -  var dom = document.getElementById('t1').childNodes;
    -  iter = goog.iter.toIterator(dom);
    -  iter2 = goog.iter.map(iter, function(el) {
    -    return el.innerHTML;
    -  });
    -  assertEquals('012', goog.iter.join(iter2, ''));
    -}
    -
    -
    -function testNextOrValue() {
    -  var iter = goog.iter.toIterator([1]);
    -
    -  assertEquals('Should return value when iterator is non-empty',
    -      1, goog.iter.nextOrValue(iter, null));
    -  assertNull('Should return given default when iterator is empty',
    -      goog.iter.nextOrValue(iter, null));
    -  assertEquals('Should return given default when iterator is (still) empty',
    -      -1, goog.iter.nextOrValue(iter, -1));
    -}
    -
    -// Return the product of several arrays as an array
    -function productAsArray(var_args) {
    -  var iter = goog.iter.product.apply(null, arguments);
    -  return goog.iter.toArray(iter);
    -}
    -
    -function testProduct() {
    -  assertArrayEquals([[1, 3], [1, 4], [2, 3], [2, 4]],
    -      productAsArray([1, 2], [3, 4]));
    -
    -  assertArrayEquals([
    -    [1, 3, 5], [1, 3, 6], [1, 4, 5], [1, 4, 6],
    -    [2, 3, 5], [2, 3, 6], [2, 4, 5], [2, 4, 6]
    -  ], productAsArray([1, 2], [3, 4], [5, 6]));
    -
    -  assertArrayEquals([[1]], productAsArray([1]));
    -  assertArrayEquals([], productAsArray([1], []));
    -  assertArrayEquals([], productAsArray());
    -
    -  var expectedResult = [];
    -  var a = [1, 2, 3];
    -  var b = [4, 5, 6];
    -  var c = [7, 8, 9];
    -  for (var i = 0; i < a.length; i++) {
    -    for (var j = 0; j < b.length; j++) {
    -      for (var k = 0; k < c.length; k++) {
    -        expectedResult.push([a[i], b[j], c[k]]);
    -      }
    -    }
    -  }
    -
    -  assertArrayEquals(expectedResult, productAsArray(a, b, c));
    -}
    -
    -function testProductIteration() {
    -  var iter = goog.iter.product([1, 2], [3, 4]);
    -
    -  assertArrayEquals([1, 3], iter.next());
    -  assertArrayEquals([1, 4], iter.next());
    -  assertArrayEquals([2, 3], iter.next());
    -  assertArrayEquals([2, 4], iter.next());
    -
    -  var ex = assertThrows(function() { iter.next() });
    -  assertEquals(goog.iter.StopIteration, ex);
    -
    -  // Ensure the iterator forever throws StopIteration.
    -  for (var i = 0; i < 5; i++) {
    -    var ex = assertThrows(function() { iter.next() });
    -    assertEquals(goog.iter.StopIteration, ex);
    -  }
    -
    -  iter = goog.iter.product();
    -  var ex = assertThrows(function() { iter.next() });
    -  assertEquals(goog.iter.StopIteration, ex);
    -
    -  iter = goog.iter.product([]);
    -  var ex = assertThrows(function() { iter.next() });
    -  assertEquals(goog.iter.StopIteration, ex);
    -}
    -
    -function testCycle() {
    -
    -  var regularArray = [1, 2, 3];
    -  var iter = goog.iter.cycle(regularArray);
    -
    -  // Test 3 cycles to ensure proper cache behavior
    -  var values = [];
    -  for (var i = 0; i < 9; i++) {
    -    values.push(iter.next());
    -  }
    -
    -  assertArrayEquals([1, 2, 3, 1, 2, 3, 1, 2, 3], values);
    -}
    -
    -function testCycleSingleItemIterable() {
    -  var singleItemArray = [1];
    -
    -  var iter = goog.iter.cycle(singleItemArray);
    -  var values = [];
    -
    -  for (var i = 0; i < 5; i++) {
    -    values.push(iter.next());
    -  }
    -
    -  assertArrayEquals([1, 1, 1, 1, 1], values);
    -}
    -
    -function testCycleEmptyIterable() {
    -
    -  var emptyArray = [];
    -
    -  var iter = goog.iter.cycle(emptyArray);
    -  var ex = assertThrows(function() { iter.next(); });
    -  assertEquals(goog.iter.StopIteration, ex);
    -}
    -
    -function testCountNoArgs() {
    -  var iter = goog.iter.count();
    -  var values = goog.iter.limit(iter, 5);
    -  assertArrayEquals([0, 1, 2, 3, 4], goog.iter.toArray(values));
    -}
    -
    -function testCountStart() {
    -  var iter = goog.iter.count(10);
    -  var values = goog.iter.limit(iter, 5);
    -  assertArrayEquals([10, 11, 12, 13, 14], goog.iter.toArray(values));
    -}
    -
    -function testCountStep() {
    -  var iter = goog.iter.count(10, 2);
    -  var values = goog.iter.limit(iter, 5);
    -  assertArrayEquals([10, 12, 14, 16, 18], goog.iter.toArray(values));
    -}
    -
    -function testCountNegativeStep() {
    -  var iter = goog.iter.count(10, -2);
    -  var values = goog.iter.limit(iter, 5);
    -  assertArrayEquals([10, 8, 6, 4, 2], goog.iter.toArray(values));
    -}
    -
    -function testCountZeroStep() {
    -  var iter = goog.iter.count(42, 0);
    -  assertEquals(42, iter.next());
    -  assertEquals(42, iter.next());
    -  assertEquals(42, iter.next());
    -}
    -
    -function testCountFloat() {
    -  var iter = goog.iter.count(1.5, 0.5);
    -  var values = goog.iter.limit(iter, 5);
    -  assertArrayEquals([1.5, 2.0, 2.5, 3.0, 3.5], goog.iter.toArray(values));
    -}
    -
    -function testRepeat() {
    -  var obj = {foo: 'bar'};
    -  var iter = goog.iter.repeat(obj);
    -  assertEquals(obj, iter.next());
    -  assertEquals(obj, iter.next());
    -  assertEquals(obj, iter.next());
    -}
    -
    -function testAccumulateArray() {
    -  var iter = goog.iter.accumulate([1, 2, 3, 4, 5]);
    -  assertArrayEquals([1, 3, 6, 10, 15], goog.iter.toArray(iter));
    -}
    -
    -function testAccumulateIterator() {
    -  var iter = goog.iter.accumulate(goog.iter.range(1, 6));
    -  assertArrayEquals([1, 3, 6, 10, 15], goog.iter.toArray(iter));
    -}
    -
    -function testAccumulateFloat() {
    -  var iter = goog.iter.accumulate([1.0, 2.5, 0.5, 1.5, 0.5]);
    -  assertArrayEquals([1.0, 3.5, 4.0, 5.5, 6.0], goog.iter.toArray(iter));
    -}
    -
    -function testZipArrays() {
    -  var iter = goog.iter.zip([1, 2, 3], [4, 5, 6], [7, 8, 9]);
    -  assertArrayEquals([1, 4, 7], iter.next());
    -  assertArrayEquals([2, 5, 8], iter.next());
    -  assertArrayEquals([3, 6, 9], iter.next());
    -  var ex = assertThrows(function() { iter.next() });
    -  assertEquals(goog.iter.StopIteration, ex);
    -}
    -
    -function testZipSingleArg() {
    -  var iter = goog.iter.zip([1, 2, 3]);
    -  assertArrayEquals([1], iter.next());
    -  assertArrayEquals([2], iter.next());
    -  assertArrayEquals([3], iter.next());
    -  var ex = assertThrows(function() { iter.next() });
    -  assertEquals(goog.iter.StopIteration, ex);
    -}
    -
    -function testZipUnevenArgs() {
    -  var iter = goog.iter.zip([1, 2, 3], [4, 5], [7]);
    -  assertArrayEquals([1, 4, 7], iter.next());
    -  var ex = assertThrows(function() { iter.next() });
    -  assertEquals(goog.iter.StopIteration, ex);
    -}
    -
    -function testZipNoArgs() {
    -  var iter = goog.iter.zip();
    -  var ex = assertThrows(function() { iter.next() });
    -  assertEquals(goog.iter.StopIteration, ex);
    -}
    -
    -function testZipIterators() {
    -  var iter = goog.iter.zip(goog.iter.count(), goog.iter.repeat('foo'));
    -  assertArrayEquals([0, 'foo'], iter.next());
    -  assertArrayEquals([1, 'foo'], iter.next());
    -  assertArrayEquals([2, 'foo'], iter.next());
    -  assertArrayEquals([3, 'foo'], iter.next());
    -}
    -
    -function testZipLongestArrays() {
    -  var iter = goog.iter.zipLongest('-', 'ABCD'.split(''), 'xy'.split(''));
    -  assertArrayEquals(['A', 'x'], iter.next());
    -  assertArrayEquals(['B', 'y'], iter.next());
    -  assertArrayEquals(['C', '-'], iter.next());
    -  assertArrayEquals(['D', '-'], iter.next());
    -  var ex = assertThrows(function() { iter.next() });
    -  assertEquals(goog.iter.StopIteration, ex);
    -}
    -
    -function testZipLongestSingleArg() {
    -  var iter = goog.iter.zipLongest('-', 'ABCD'.split(''));
    -  assertArrayEquals(['A'], iter.next());
    -  assertArrayEquals(['B'], iter.next());
    -  assertArrayEquals(['C'], iter.next());
    -  assertArrayEquals(['D'], iter.next());
    -  var ex = assertThrows(function() { iter.next() });
    -  assertEquals(goog.iter.StopIteration, ex);
    -}
    -
    -function testZipLongestNoArgs() {
    -  var iter = goog.iter.zipLongest();
    -  assertArrayEquals([], goog.iter.toArray(iter));
    -  var iter = goog.iter.zipLongest('fill');
    -  assertArrayEquals([], goog.iter.toArray(iter));
    -}
    -
    -function testZipLongestIterators() {
    -  var iter = goog.iter.zipLongest(null, goog.iter.range(3), goog.iter.range(5));
    -  assertArrayEquals([0, 0], iter.next());
    -  assertArrayEquals([1, 1], iter.next());
    -  assertArrayEquals([2, 2], iter.next());
    -  assertArrayEquals([null, 3], iter.next());
    -  assertArrayEquals([null, 4], iter.next());
    -  var ex = assertThrows(function() { iter.next() });
    -  assertEquals(goog.iter.StopIteration, ex);
    -}
    -
    -function testCompressArray() {
    -  var iter = goog.iter.compress('ABCDEF'.split(''), [1, 0, 1, 0, 1, 1]);
    -  assertEquals('ACEF', goog.iter.join(iter, ''));
    -}
    -
    -function testCompressUnevenArgs() {
    -  var iter = goog.iter.compress('ABCDEF'.split(''), [false, true, true]);
    -  assertEquals('BC', goog.iter.join(iter, ''));
    -}
    -
    -function testCompressIterators() {
    -  var iter = goog.iter.compress(goog.iter.range(10), goog.iter.cycle([0, 1]));
    -  assertArrayEquals([1, 3, 5, 7, 9], goog.iter.toArray(iter));
    -}
    -
    -function testGroupByNoKeyFunc() {
    -  var iter = goog.iter.groupBy('AAABBBBCDD'.split(''));
    -  assertArrayEquals(['A', ['A', 'A', 'A']], iter.next());
    -  assertArrayEquals(['B', ['B', 'B', 'B', 'B']], iter.next());
    -  assertArrayEquals(['C', ['C']], iter.next());
    -  assertArrayEquals(['D', ['D', 'D']], iter.next());
    -  var ex = assertThrows(function() { iter.next() });
    -  assertEquals(goog.iter.StopIteration, ex);
    -}
    -
    -function testGroupByKeyFunc() {
    -  var keyFunc = function(x) { return x.toLowerCase(); };
    -  var iter = goog.iter.groupBy('AaAABBbbBCccddDD'.split(''), keyFunc);
    -  assertArrayEquals(['a', ['A', 'a', 'A', 'A']], iter.next());
    -  assertArrayEquals(['b', ['B', 'B', 'b', 'b', 'B']], iter.next());
    -  assertArrayEquals(['c', ['C', 'c', 'c']], iter.next());
    -  assertArrayEquals(['d', ['d', 'd', 'D', 'D']], iter.next());
    -  var ex = assertThrows(function() { iter.next() });
    -  assertEquals(goog.iter.StopIteration, ex);
    -}
    -
    -function testStarMap() {
    -  var iter = goog.iter.starMap([[2, 5], [3, 2], [10, 3]], Math.pow);
    -  assertEquals(32, iter.next());
    -  assertEquals(9, iter.next());
    -  assertEquals(1000, iter.next());
    -  var ex = assertThrows(function() { iter.next() });
    -  assertEquals(goog.iter.StopIteration, ex);
    -}
    -
    -function testStarMapExtraArgs() {
    -  var func = function(string, radix, undef, iterator) {
    -    assertEquals('undef should be undefined', 'undefined', typeof undef);
    -    assertTrue(iterator instanceof goog.iter.Iterator);
    -    return parseInt(string, radix);
    -  };
    -  var iter = goog.iter.starMap([['42', 10], ['0xFF', 16], ['101', 2]], func);
    -  assertEquals(42, iter.next());
    -  assertEquals(255, iter.next());
    -  assertEquals(5, iter.next());
    -  var ex = assertThrows(function() { iter.next() });
    -  assertEquals(goog.iter.StopIteration, ex);
    -}
    -
    -function testTeeArray() {
    -  var iters = goog.iter.tee('ABC'.split(''));
    -  assertEquals(2, iters.length);
    -  var it0 = iters[0], it1 = iters[1];
    -  assertEquals('A', it0.next());
    -  assertEquals('A', it1.next());
    -  assertEquals('B', it0.next());
    -  assertEquals('B', it1.next());
    -  assertEquals('C', it0.next());
    -  assertEquals('C', it1.next());
    -  var ex = assertThrows(function() { it0.next() });
    -  assertEquals(goog.iter.StopIteration, ex);
    -  ex = assertThrows(function() { it1.next() });
    -  assertEquals(goog.iter.StopIteration, ex);
    -}
    -
    -function testTeeIterator() {
    -  var iters = goog.iter.tee(goog.iter.count(), 3);
    -  assertEquals(3, iters.length);
    -  var it0 = iters[0], it1 = iters[1], it2 = iters[2];
    -  assertEquals(0, it0.next());
    -  assertEquals(1, it0.next());
    -  assertEquals(0, it1.next());
    -  assertEquals(1, it1.next());
    -  assertEquals(2, it1.next());
    -  assertEquals(2, it0.next());
    -  assertEquals(0, it2.next());
    -  assertEquals(1, it2.next());
    -  assertEquals(2, it2.next());
    -  assertEquals(3, it0.next());
    -  assertEquals(3, it1.next());
    -  assertEquals(3, it2.next());
    -}
    -
    -function testEnumerateNoStart() {
    -  var iter = goog.iter.enumerate('ABC'.split(''));
    -  assertArrayEquals([0, 'A'], iter.next());
    -  assertArrayEquals([1, 'B'], iter.next());
    -  assertArrayEquals([2, 'C'], iter.next());
    -  var ex = assertThrows(function() { iter.next() });
    -  assertEquals(goog.iter.StopIteration, ex);
    -}
    -
    -function testEnumerateStart() {
    -  var iter = goog.iter.enumerate('DEF'.split(''), 3);
    -  assertArrayEquals([3, 'D'], iter.next());
    -  assertArrayEquals([4, 'E'], iter.next());
    -  assertArrayEquals([5, 'F'], iter.next());
    -  var ex = assertThrows(function() { iter.next() });
    -  assertEquals(goog.iter.StopIteration, ex);
    -}
    -
    -function testLimitLess() {
    -  var iter = goog.iter.limit('ABCDEFG'.split(''), 3);
    -  assertEquals('ABC', goog.iter.join(iter, ''));
    -}
    -
    -function testLimitGreater() {
    -  var iter = goog.iter.limit('ABCDEFG'.split(''), 10);
    -  assertEquals('ABCDEFG', goog.iter.join(iter, ''));
    -}
    -
    -function testConsumeLess() {
    -  var iter = goog.iter.consume('ABCDEFG'.split(''), 3);
    -  assertEquals('DEFG', goog.iter.join(iter, ''));
    -}
    -
    -function testConsumeGreater() {
    -  var iter = goog.iter.consume('ABCDEFG'.split(''), 10);
    -  var ex = assertThrows(function() { iter.next() });
    -  assertEquals(goog.iter.StopIteration, ex);
    -}
    -
    -function testSliceStart() {
    -  var iter = goog.iter.slice('ABCDEFG'.split(''), 2);
    -  assertEquals('CDEFG', goog.iter.join(iter, ''));
    -}
    -
    -function testSliceStop() {
    -  var iter = goog.iter.slice('ABCDEFG'.split(''), 2, 4);
    -  assertEquals('CD', goog.iter.join(iter, ''));
    -}
    -
    -function testSliceStartStopEqual() {
    -  var iter = goog.iter.slice('ABCDEFG'.split(''), 1, 1);
    -  var ex = assertThrows(function() { iter.next() });
    -  assertEquals(goog.iter.StopIteration, ex);
    -}
    -
    -function testSliceIterator() {
    -  var iter = goog.iter.slice(goog.iter.count(20), 0, 5);
    -  assertArrayEquals([20, 21, 22, 23, 24], goog.iter.toArray(iter));
    -}
    -
    -function testSliceStartGreater() {
    -  var iter = goog.iter.slice('ABCDEFG'.split(''), 10);
    -  var ex = assertThrows(function() { iter.next() });
    -  assertEquals(goog.iter.StopIteration, ex);
    -}
    -
    -function testPermutationsNoLength() {
    -  var iter = goog.iter.permutations(goog.iter.range(3));
    -  assertArrayEquals([0, 1, 2], iter.next());
    -  assertArrayEquals([0, 2, 1], iter.next());
    -  assertArrayEquals([1, 0, 2], iter.next());
    -  assertArrayEquals([1, 2, 0], iter.next());
    -  assertArrayEquals([2, 0, 1], iter.next());
    -  assertArrayEquals([2, 1, 0], iter.next());
    -  var ex = assertThrows(function() { iter.next() });
    -  assertEquals(goog.iter.StopIteration, ex);
    -}
    -
    -function testPermutationsLength() {
    -  var iter = goog.iter.permutations('ABC'.split(''), 2);
    -  assertArrayEquals(['A', 'B'], iter.next());
    -  assertArrayEquals(['A', 'C'], iter.next());
    -  assertArrayEquals(['B', 'A'], iter.next());
    -  assertArrayEquals(['B', 'C'], iter.next());
    -  assertArrayEquals(['C', 'A'], iter.next());
    -  assertArrayEquals(['C', 'B'], iter.next());
    -}
    -
    -function testCombinations() {
    -  var iter = goog.iter.combinations(goog.iter.range(4), 3);
    -  assertArrayEquals([0, 1, 2], iter.next());
    -  assertArrayEquals([0, 1, 3], iter.next());
    -  assertArrayEquals([0, 2, 3], iter.next());
    -  assertArrayEquals([1, 2, 3], iter.next());
    -  var ex = assertThrows(function() { iter.next() });
    -  assertEquals(goog.iter.StopIteration, ex);
    -}
    -
    -function testCombinationsWithReplacement() {
    -  var iter = goog.iter.combinationsWithReplacement('ABC'.split(''), 2);
    -  assertArrayEquals(['A', 'A'], iter.next());
    -  assertArrayEquals(['A', 'B'], iter.next());
    -  assertArrayEquals(['A', 'C'], iter.next());
    -  assertArrayEquals(['B', 'B'], iter.next());
    -  assertArrayEquals(['B', 'C'], iter.next());
    -  assertArrayEquals(['C', 'C'], iter.next());
    -  var ex = assertThrows(function() { iter.next() });
    -  assertEquals(goog.iter.StopIteration, ex);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/json/evaljsonprocessor.js b/src/database/third_party/closure-library/closure/goog/json/evaljsonprocessor.js
    deleted file mode 100644
    index 0144bf1ade6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/json/evaljsonprocessor.js
    +++ /dev/null
    @@ -1,67 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Defines a class for parsing JSON using eval.
    - */
    -
    -goog.provide('goog.json.EvalJsonProcessor');
    -
    -goog.require('goog.json');
    -goog.require('goog.json.Processor');
    -goog.require('goog.json.Serializer');
    -
    -
    -
    -/**
    - * A class that parses and stringifies JSON using eval (as implemented in
    - * goog.json).
    - * Adapts {@code goog.json} to the {@code goog.json.Processor} interface.
    - *
    - * @param {?goog.json.Replacer=} opt_replacer An optional replacer to use during
    - *     serialization.
    - * @param {?boolean=} opt_useUnsafeParsing Whether to use goog.json.unsafeParse
    - *     for parsing. Safe parsing is very slow on large strings. On the other
    - *     hand, unsafe parsing uses eval() without checking whether the string is
    - *     valid, so it should only be used if you trust the source of the string.
    - * @constructor
    - * @implements {goog.json.Processor}
    - * @final
    - */
    -goog.json.EvalJsonProcessor = function(opt_replacer, opt_useUnsafeParsing) {
    -  /**
    -   * @type {goog.json.Serializer}
    -   * @private
    -   */
    -  this.serializer_ = new goog.json.Serializer(opt_replacer);
    -
    -  /**
    -   * @type {function(string): *}
    -   * @private
    -   */
    -  this.parser_ = opt_useUnsafeParsing ? goog.json.unsafeParse : goog.json.parse;
    -};
    -
    -
    -/** @override */
    -goog.json.EvalJsonProcessor.prototype.stringify = function(object) {
    -  return this.serializer_.serialize(object);
    -};
    -
    -
    -/** @override */
    -goog.json.EvalJsonProcessor.prototype.parse = function(s) {
    -  return this.parser_(s);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/json/hybrid.js b/src/database/third_party/closure-library/closure/goog/json/hybrid.js
    deleted file mode 100644
    index ac58bf420a2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/json/hybrid.js
    +++ /dev/null
    @@ -1,103 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Utility to attempt native JSON processing, falling back to
    - *     goog.json if not available.
    - *
    - *     This is intended as a drop-in for current users of goog.json who want
    - *     to take advantage of native JSON if present.
    - *
    - * @author nnaze@google.com (Nathan Naze)
    - */
    -
    -goog.provide('goog.json.hybrid');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.json');
    -
    -
    -/**
    - * Attempts to serialize the JSON string natively, falling back to
    - * {@code goog.json.serialize} if unsuccessful.
    - * @param {!Object} obj JavaScript object to serialize to JSON.
    - * @return {string} Resulting JSON string.
    - */
    -goog.json.hybrid.stringify = goog.json.USE_NATIVE_JSON ?
    -    goog.global['JSON']['stringify'] :
    -    function(obj) {
    -      if (goog.global.JSON) {
    -        try {
    -          return goog.global.JSON.stringify(obj);
    -        } catch (e) {
    -          // Native serialization failed.  Fall through to retry with
    -          // goog.json.serialize.
    -        }
    -      }
    -
    -      return goog.json.serialize(obj);
    -    };
    -
    -
    -/**
    - * Attempts to parse the JSON string natively, falling back to
    - * the supplied {@code fallbackParser} if unsuccessful.
    - * @param {string} jsonString JSON string to parse.
    - * @param {function(string):Object} fallbackParser Fallback JSON parser used
    - *     if native
    - * @return {!Object} Resulting JSON object.
    - * @private
    - */
    -goog.json.hybrid.parse_ = function(jsonString, fallbackParser) {
    -  if (goog.global.JSON) {
    -    try {
    -      var obj = goog.global.JSON.parse(jsonString);
    -      goog.asserts.assertObject(obj);
    -      return obj;
    -    } catch (e) {
    -      // Native parse failed.  Fall through to retry with goog.json.unsafeParse.
    -    }
    -  }
    -
    -  var obj = fallbackParser(jsonString);
    -  goog.asserts.assert(obj);
    -  return obj;
    -};
    -
    -
    -/**
    - * Attempts to parse the JSON string natively, falling back to
    - * {@code goog.json.parse} if unsuccessful.
    - * @param {string} jsonString JSON string to parse.
    - * @return {!Object} Resulting JSON object.
    - */
    -goog.json.hybrid.parse = goog.json.USE_NATIVE_JSON ?
    -    goog.global['JSON']['parse'] :
    -    function(jsonString) {
    -      return goog.json.hybrid.parse_(jsonString, goog.json.parse);
    -    };
    -
    -
    -/**
    - * Attempts to parse the JSON string natively, falling back to
    - * {@code goog.json.unsafeParse} if unsuccessful.
    - * @param {string} jsonString JSON string to parse.
    - * @return {!Object} Resulting JSON object.
    - */
    -goog.json.hybrid.unsafeParse = goog.json.USE_NATIVE_JSON ?
    -    goog.global['JSON']['parse'] :
    -    function(jsonString) {
    -      return goog.json.hybrid.parse_(jsonString, goog.json.unsafeParse);
    -    };
    diff --git a/src/database/third_party/closure-library/closure/goog/json/hybrid_test.html b/src/database/third_party/closure-library/closure/goog/json/hybrid_test.html
    deleted file mode 100644
    index 02ec8b40ffe..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/json/hybrid_test.html
    +++ /dev/null
    @@ -1,19 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.json.hybridTest</title>
    -<script src="../base.js"></script>
    -<script>
    -goog.require('goog.json.hybridTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/json/hybrid_test.js b/src/database/third_party/closure-library/closure/goog/json/hybrid_test.js
    deleted file mode 100644
    index bd5ae03b34e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/json/hybrid_test.js
    +++ /dev/null
    @@ -1,157 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.json.hybrid.
    - * @author nnaze@google.com (Nathan Naze)
    - */
    -
    -goog.provide('goog.json.hybridTest');
    -
    -goog.require('goog.json');
    -goog.require('goog.json.hybrid');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -goog.require('goog.userAgent');
    -
    -goog.setTestOnly('goog.json.hybridTest');
    -
    -
    -var propertyReplacer = new goog.testing.PropertyReplacer();
    -
    -var jsonParse;
    -var jsonStringify;
    -var googJsonParse;
    -var googJsonUnsafeParse;
    -var googJsonSerialize;
    -
    -function isIe7() {
    -  return goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('8');
    -}
    -
    -function setUp() {
    -  googJsonParse = goog.testing.recordFunction(goog.json.parse);
    -  googJsonUnsafeParse = goog.testing.recordFunction(goog.json.unsafeParse);
    -  googJsonSerialize = goog.testing.recordFunction(goog.json.serialize);
    -
    -  propertyReplacer.set(goog.json, 'parse', googJsonParse);
    -  propertyReplacer.set(goog.json, 'unsafeParse', googJsonUnsafeParse);
    -  propertyReplacer.set(goog.json, 'serialize', googJsonSerialize);
    -
    -  jsonParse = goog.testing.recordFunction(
    -      goog.global.JSON && goog.global.JSON.parse);
    -  jsonStringify = goog.testing.recordFunction(
    -      goog.global.JSON && goog.global.JSON.stringify);
    -
    -  if (goog.global.JSON) {
    -    propertyReplacer.set(goog.global.JSON, 'parse', jsonParse);
    -    propertyReplacer.set(goog.global.JSON, 'stringify', jsonStringify);
    -  }
    -}
    -
    -function tearDown() {
    -  propertyReplacer.reset();
    -}
    -
    -function parseJson() {
    -  var obj = goog.json.hybrid.parse('{"a": 2}');
    -  assertObjectEquals({'a': 2}, obj);
    -}
    -
    -function unsafeParseJson() {
    -  var obj = goog.json.hybrid.unsafeParse('{"a": 2}');
    -  assertObjectEquals({'a': 2}, obj);
    -}
    -
    -function serializeJson() {
    -  var str = goog.json.hybrid.stringify({b: 2});
    -  assertEquals('{"b":2}', str);
    -}
    -
    -function testUnsafeParseNativeJsonPresent() {
    -  // No native JSON in IE7
    -  if (isIe7()) {
    -    return;
    -  }
    -
    -  unsafeParseJson();
    -  assertEquals(1, jsonParse.getCallCount());
    -  assertEquals(0, googJsonParse.getCallCount());
    -  assertEquals(0, googJsonUnsafeParse.getCallCount());
    -}
    -
    -function testParseNativeJsonPresent() {
    -  // No native JSON in IE7
    -  if (isIe7()) {
    -    return;
    -  }
    -
    -  unsafeParseJson();
    -  assertEquals(1, jsonParse.getCallCount());
    -  assertEquals(0, googJsonParse.getCallCount());
    -  assertEquals(0, googJsonUnsafeParse.getCallCount());
    -}
    -
    -function testStringifyNativeJsonPresent() {
    -  // No native JSON in IE7
    -  if (isIe7()) {
    -    return;
    -  }
    -
    -  serializeJson();
    -
    -  assertEquals(1, jsonStringify.getCallCount());
    -  assertEquals(0, googJsonSerialize.getCallCount());
    -}
    -
    -function testParseNativeJsonAbsent() {
    -  propertyReplacer.set(goog.global, 'JSON', null);
    -
    -  parseJson();
    -
    -  assertEquals(0, jsonParse.getCallCount());
    -  assertEquals(0, jsonStringify.getCallCount());
    -  assertEquals(1, googJsonParse.getCallCount());
    -  assertEquals(0, googJsonUnsafeParse.getCallCount());
    -}
    -
    -function testStringifyNativeJsonAbsent() {
    -  propertyReplacer.set(goog.global, 'JSON', null);
    -
    -  serializeJson();
    -
    -  assertEquals(0, jsonStringify.getCallCount());
    -  assertEquals(1, googJsonSerialize.getCallCount());
    -}
    -
    -function testParseCurrentBrowserParse() {
    -  parseJson();
    -  assertEquals(isIe7() ? 0 : 1, jsonParse.getCallCount());
    -  assertEquals(isIe7() ? 1 : 0, googJsonParse.getCallCount());
    -  assertEquals(0, googJsonUnsafeParse.getCallCount());
    -}
    -
    -function testParseCurrentBrowserUnsafeParse() {
    -  unsafeParseJson();
    -  assertEquals(isIe7() ? 0 : 1, jsonParse.getCallCount());
    -  assertEquals(0, googJsonParse.getCallCount());
    -  assertEquals(isIe7() ? 1 : 0, googJsonUnsafeParse.getCallCount());
    -}
    -
    -function testParseCurrentBrowserStringify() {
    -  serializeJson();
    -  assertEquals(isIe7() ? 0 : 1, jsonStringify.getCallCount());
    -  assertEquals(isIe7() ? 1 : 0, googJsonSerialize.getCallCount());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/json/hybridjsonprocessor.js b/src/database/third_party/closure-library/closure/goog/json/hybridjsonprocessor.js
    deleted file mode 100644
    index f00168dfe7e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/json/hybridjsonprocessor.js
    +++ /dev/null
    @@ -1,47 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is dihstributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview A class that attempts parse/serialize JSON using native JSON,
    - *     falling back to goog.json if necessary.
    - * @author nnaze@google.com (Nathan Naze)
    - */
    -
    -goog.provide('goog.json.HybridJsonProcessor');
    -
    -goog.require('goog.json.Processor');
    -goog.require('goog.json.hybrid');
    -
    -
    -
    -/**
    - * Processor form of goog.json.hybrid, which attempts to parse/serialize
    - * JSON using native JSON methods, falling back to goog.json if not
    - * available.
    - * @constructor
    - * @implements {goog.json.Processor}
    - * @final
    - */
    -goog.json.HybridJsonProcessor = function() {};
    -
    -
    -/** @override */
    -goog.json.HybridJsonProcessor.prototype.stringify =
    -    /** @type {function (*): string} */ (goog.json.hybrid.stringify);
    -
    -
    -/** @override */
    -goog.json.HybridJsonProcessor.prototype.parse =
    -    /** @type {function (*): !Object} */ (goog.json.hybrid.parse);
    diff --git a/src/database/third_party/closure-library/closure/goog/json/hybridjsonprocessor_test.html b/src/database/third_party/closure-library/closure/goog/json/hybridjsonprocessor_test.html
    deleted file mode 100644
    index fc99c5d6bbd..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/json/hybridjsonprocessor_test.html
    +++ /dev/null
    @@ -1,19 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.json.HybridJsonProcessor</title>
    -<script src="../base.js"></script>
    -<script>
    -goog.require('goog.json.HybridJsonProcessorTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/json/hybridjsonprocessor_test.js b/src/database/third_party/closure-library/closure/goog/json/hybridjsonprocessor_test.js
    deleted file mode 100644
    index 024f5b50f42..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/json/hybridjsonprocessor_test.js
    +++ /dev/null
    @@ -1,33 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.json.hybrid.
    - * @author nnaze@google.com (Nathan Naze)
    - */
    -
    -goog.provide('goog.json.HybridJsonProcessorTest');
    -
    -goog.require('goog.json.HybridJsonProcessor');
    -goog.require('goog.json.hybrid');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.json.HybridJsonProcessorTest');
    -
    -
    -function testCorrectFunctions() {
    -  var processor = new goog.json.HybridJsonProcessor();
    -  assertEquals(goog.json.hybrid.stringify, processor.stringify);
    -  assertEquals(goog.json.hybrid.parse, processor.parse);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/json/json.js b/src/database/third_party/closure-library/closure/goog/json/json.js
    deleted file mode 100644
    index 77dccc6f8c7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/json/json.js
    +++ /dev/null
    @@ -1,369 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview JSON utility functions.
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -
    -goog.provide('goog.json');
    -goog.provide('goog.json.Replacer');
    -goog.provide('goog.json.Reviver');
    -goog.provide('goog.json.Serializer');
    -
    -
    -/**
    - * @define {boolean} If true, use the native JSON parsing API.
    - * NOTE(ruilopes): EXPERIMENTAL, handle with care.  Setting this to true might
    - * break your code.  The default {@code goog.json.parse} implementation is able
    - * to handle invalid JSON, such as JSPB.
    - */
    -goog.define('goog.json.USE_NATIVE_JSON', false);
    -
    -
    -/**
    - * Tests if a string is an invalid JSON string. This only ensures that we are
    - * not using any invalid characters
    - * @param {string} s The string to test.
    - * @return {boolean} True if the input is a valid JSON string.
    - */
    -goog.json.isValid = function(s) {
    -  // All empty whitespace is not valid.
    -  if (/^\s*$/.test(s)) {
    -    return false;
    -  }
    -
    -  // This is taken from http://www.json.org/json2.js which is released to the
    -  // public domain.
    -  // Changes: We dissallow \u2028 Line separator and \u2029 Paragraph separator
    -  // inside strings.  We also treat \u2028 and \u2029 as whitespace which they
    -  // are in the RFC but IE and Safari does not match \s to these so we need to
    -  // include them in the reg exps in all places where whitespace is allowed.
    -  // We allowed \x7f inside strings because some tools don't escape it,
    -  // e.g. http://www.json.org/java/org/json/JSONObject.java
    -
    -  // Parsing happens in three stages. In the first stage, we run the text
    -  // against regular expressions that look for non-JSON patterns. We are
    -  // especially concerned with '()' and 'new' because they can cause invocation,
    -  // and '=' because it can cause mutation. But just to be safe, we want to
    -  // reject all unexpected forms.
    -
    -  // We split the first stage into 4 regexp operations in order to work around
    -  // crippling inefficiencies in IE's and Safari's regexp engines. First we
    -  // replace all backslash pairs with '@' (a non-JSON character). Second, we
    -  // replace all simple value tokens with ']' characters. Third, we delete all
    -  // open brackets that follow a colon or comma or that begin the text. Finally,
    -  // we look to see that the remaining characters are only whitespace or ']' or
    -  // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
    -
    -  // Don't make these static since they have the global flag.
    -  var backslashesRe = /\\["\\\/bfnrtu]/g;
    -  var simpleValuesRe =
    -      /"[^"\\\n\r\u2028\u2029\x00-\x08\x0a-\x1f]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
    -  var openBracketsRe = /(?:^|:|,)(?:[\s\u2028\u2029]*\[)+/g;
    -  var remainderRe = /^[\],:{}\s\u2028\u2029]*$/;
    -
    -  return remainderRe.test(s.replace(backslashesRe, '@').
    -      replace(simpleValuesRe, ']').
    -      replace(openBracketsRe, ''));
    -};
    -
    -
    -/**
    - * Parses a JSON string and returns the result. This throws an exception if
    - * the string is an invalid JSON string.
    - *
    - * Note that this is very slow on large strings. If you trust the source of
    - * the string then you should use unsafeParse instead.
    - *
    - * @param {*} s The JSON string to parse.
    - * @throws Error if s is invalid JSON.
    - * @return {Object} The object generated from the JSON string, or null.
    - */
    -goog.json.parse = goog.json.USE_NATIVE_JSON ?
    -    /** @type {function(*):Object} */ (goog.global['JSON']['parse']) :
    -    function(s) {
    -      var o = String(s);
    -      if (goog.json.isValid(o)) {
    -        /** @preserveTry */
    -        try {
    -          return /** @type {Object} */ (eval('(' + o + ')'));
    -        } catch (ex) {
    -        }
    -      }
    -      throw Error('Invalid JSON string: ' + o);
    -    };
    -
    -
    -/**
    - * Parses a JSON string and returns the result. This uses eval so it is open
    - * to security issues and it should only be used if you trust the source.
    - *
    - * @param {string} s The JSON string to parse.
    - * @return {Object} The object generated from the JSON string.
    - */
    -goog.json.unsafeParse = goog.json.USE_NATIVE_JSON ?
    -    /** @type {function(string):Object} */ (goog.global['JSON']['parse']) :
    -    function(s) {
    -      return /** @type {Object} */ (eval('(' + s + ')'));
    -    };
    -
    -
    -/**
    - * JSON replacer, as defined in Section 15.12.3 of the ES5 spec.
    - * @see http://ecma-international.org/ecma-262/5.1/#sec-15.12.3
    - *
    - * TODO(nicksantos): Array should also be a valid replacer.
    - *
    - * @typedef {function(this:Object, string, *): *}
    - */
    -goog.json.Replacer;
    -
    -
    -/**
    - * JSON reviver, as defined in Section 15.12.2 of the ES5 spec.
    - * @see http://ecma-international.org/ecma-262/5.1/#sec-15.12.3
    - *
    - * @typedef {function(this:Object, string, *): *}
    - */
    -goog.json.Reviver;
    -
    -
    -/**
    - * Serializes an object or a value to a JSON string.
    - *
    - * @param {*} object The object to serialize.
    - * @param {?goog.json.Replacer=} opt_replacer A replacer function
    - *     called for each (key, value) pair that determines how the value
    - *     should be serialized. By defult, this just returns the value
    - *     and allows default serialization to kick in.
    - * @throws Error if there are loops in the object graph.
    - * @return {string} A JSON string representation of the input.
    - */
    -goog.json.serialize = goog.json.USE_NATIVE_JSON ?
    -    /** @type {function(*, ?goog.json.Replacer=):string} */
    -    (goog.global['JSON']['stringify']) :
    -    function(object, opt_replacer) {
    -      // NOTE(nicksantos): Currently, we never use JSON.stringify.
    -      //
    -      // The last time I evaluated this, JSON.stringify had subtle bugs and
    -      // behavior differences on all browsers, and the performance win was not
    -      // large enough to justify all the issues. This may change in the future
    -      // as browser implementations get better.
    -      //
    -      // assertSerialize in json_test contains if branches for the cases
    -      // that fail.
    -      return new goog.json.Serializer(opt_replacer).serialize(object);
    -    };
    -
    -
    -
    -/**
    - * Class that is used to serialize JSON objects to a string.
    - * @param {?goog.json.Replacer=} opt_replacer Replacer.
    - * @constructor
    - */
    -goog.json.Serializer = function(opt_replacer) {
    -  /**
    -   * @type {goog.json.Replacer|null|undefined}
    -   * @private
    -   */
    -  this.replacer_ = opt_replacer;
    -};
    -
    -
    -/**
    - * Serializes an object or a value to a JSON string.
    - *
    - * @param {*} object The object to serialize.
    - * @throws Error if there are loops in the object graph.
    - * @return {string} A JSON string representation of the input.
    - */
    -goog.json.Serializer.prototype.serialize = function(object) {
    -  var sb = [];
    -  this.serializeInternal(object, sb);
    -  return sb.join('');
    -};
    -
    -
    -/**
    - * Serializes a generic value to a JSON string
    - * @protected
    - * @param {*} object The object to serialize.
    - * @param {Array<string>} sb Array used as a string builder.
    - * @throws Error if there are loops in the object graph.
    - */
    -goog.json.Serializer.prototype.serializeInternal = function(object, sb) {
    -  switch (typeof object) {
    -    case 'string':
    -      this.serializeString_(/** @type {string} */ (object), sb);
    -      break;
    -    case 'number':
    -      this.serializeNumber_(/** @type {number} */ (object), sb);
    -      break;
    -    case 'boolean':
    -      sb.push(object);
    -      break;
    -    case 'undefined':
    -      sb.push('null');
    -      break;
    -    case 'object':
    -      if (object == null) {
    -        sb.push('null');
    -        break;
    -      }
    -      if (goog.isArray(object)) {
    -        this.serializeArray(/** @type {!Array<?>} */ (object), sb);
    -        break;
    -      }
    -      // should we allow new String, new Number and new Boolean to be treated
    -      // as string, number and boolean? Most implementations do not and the
    -      // need is not very big
    -      this.serializeObject_(/** @type {Object} */ (object), sb);
    -      break;
    -    case 'function':
    -      // Skip functions.
    -      // TODO(user) Should we return something here?
    -      break;
    -    default:
    -      throw Error('Unknown type: ' + typeof object);
    -  }
    -};
    -
    -
    -/**
    - * Character mappings used internally for goog.string.quote
    - * @private
    - * @type {!Object}
    - */
    -goog.json.Serializer.charToJsonCharCache_ = {
    -  '\"': '\\"',
    -  '\\': '\\\\',
    -  '/': '\\/',
    -  '\b': '\\b',
    -  '\f': '\\f',
    -  '\n': '\\n',
    -  '\r': '\\r',
    -  '\t': '\\t',
    -
    -  '\x0B': '\\u000b' // '\v' is not supported in JScript
    -};
    -
    -
    -/**
    - * Regular expression used to match characters that need to be replaced.
    - * The S60 browser has a bug where unicode characters are not matched by
    - * regular expressions. The condition below detects such behaviour and
    - * adjusts the regular expression accordingly.
    - * @private
    - * @type {!RegExp}
    - */
    -goog.json.Serializer.charsToReplace_ = /\uffff/.test('\uffff') ?
    -    /[\\\"\x00-\x1f\x7f-\uffff]/g : /[\\\"\x00-\x1f\x7f-\xff]/g;
    -
    -
    -/**
    - * Serializes a string to a JSON string
    - * @private
    - * @param {string} s The string to serialize.
    - * @param {Array<string>} sb Array used as a string builder.
    - */
    -goog.json.Serializer.prototype.serializeString_ = function(s, sb) {
    -  // The official JSON implementation does not work with international
    -  // characters.
    -  sb.push('"', s.replace(goog.json.Serializer.charsToReplace_, function(c) {
    -    // caching the result improves performance by a factor 2-3
    -    if (c in goog.json.Serializer.charToJsonCharCache_) {
    -      return goog.json.Serializer.charToJsonCharCache_[c];
    -    }
    -
    -    var cc = c.charCodeAt(0);
    -    var rv = '\\u';
    -    if (cc < 16) {
    -      rv += '000';
    -    } else if (cc < 256) {
    -      rv += '00';
    -    } else if (cc < 4096) { // \u1000
    -      rv += '0';
    -    }
    -    return goog.json.Serializer.charToJsonCharCache_[c] = rv + cc.toString(16);
    -  }), '"');
    -};
    -
    -
    -/**
    - * Serializes a number to a JSON string
    - * @private
    - * @param {number} n The number to serialize.
    - * @param {Array<string>} sb Array used as a string builder.
    - */
    -goog.json.Serializer.prototype.serializeNumber_ = function(n, sb) {
    -  sb.push(isFinite(n) && !isNaN(n) ? n : 'null');
    -};
    -
    -
    -/**
    - * Serializes an array to a JSON string
    - * @param {Array<string>} arr The array to serialize.
    - * @param {Array<string>} sb Array used as a string builder.
    - * @protected
    - */
    -goog.json.Serializer.prototype.serializeArray = function(arr, sb) {
    -  var l = arr.length;
    -  sb.push('[');
    -  var sep = '';
    -  for (var i = 0; i < l; i++) {
    -    sb.push(sep);
    -
    -    var value = arr[i];
    -    this.serializeInternal(
    -        this.replacer_ ? this.replacer_.call(arr, String(i), value) : value,
    -        sb);
    -
    -    sep = ',';
    -  }
    -  sb.push(']');
    -};
    -
    -
    -/**
    - * Serializes an object to a JSON string
    - * @private
    - * @param {Object} obj The object to serialize.
    - * @param {Array<string>} sb Array used as a string builder.
    - */
    -goog.json.Serializer.prototype.serializeObject_ = function(obj, sb) {
    -  sb.push('{');
    -  var sep = '';
    -  for (var key in obj) {
    -    if (Object.prototype.hasOwnProperty.call(obj, key)) {
    -      var value = obj[key];
    -      // Skip functions.
    -      // TODO(ptucker) Should we return something for function properties?
    -      if (typeof value != 'function') {
    -        sb.push(sep);
    -        this.serializeString_(key, sb);
    -        sb.push(':');
    -
    -        this.serializeInternal(
    -            this.replacer_ ? this.replacer_.call(obj, key, value) : value,
    -            sb);
    -
    -        sep = ',';
    -      }
    -    }
    -  }
    -  sb.push('}');
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/json/json_perf.html b/src/database/third_party/closure-library/closure/goog/json/json_perf.html
    deleted file mode 100644
    index a7c2ee1c27c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/json/json_perf.html
    +++ /dev/null
    @@ -1,29 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -  <title>Closure Performance Tests - goog.json vs JSON</title>
    -  <link rel="stylesheet" type="text/css" href="../testing/performancetable.css"/>
    -  <script src="../base.js"></script>
    -</head>
    -<body>
    -<h1>goog.json and JSON Performance Tests</h1>
    -<p>
    -<strong>User-agent:</strong>
    -<script>document.write(navigator.userAgent);</script>
    -</p>
    -<div id="perfTable"></div>
    -<hr>
    -<script>
    -goog.require('goog.jsonPerf');
    -</script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/json/json_perf.js b/src/database/third_party/closure-library/closure/goog/json/json_perf.js
    deleted file mode 100644
    index ac732252986..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/json/json_perf.js
    +++ /dev/null
    @@ -1,112 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview JSON performance tests.
    - */
    -
    -goog.provide('goog.jsonPerf');
    -
    -goog.require('goog.dom');
    -goog.require('goog.json');
    -goog.require('goog.math');
    -goog.require('goog.string');
    -goog.require('goog.testing.PerformanceTable');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.jsonPerf');
    -
    -var table = new goog.testing.PerformanceTable(
    -    goog.dom.getElement('perfTable'));
    -
    -var stubs = new goog.testing.PropertyReplacer();
    -
    -function tearDown() {
    -  stubs.reset();
    -}
    -
    -function testSerialize() {
    -  var obj = populateObject({}, 50, 4);
    -
    -  table.run(function() {
    -    var s = JSON.stringify(obj);
    -  }, 'Stringify using JSON.stringify');
    -
    -  table.run(function() {
    -    var s = goog.json.serialize(obj);
    -  }, 'Stringify using goog.json.serialize');
    -}
    -
    -function testParse() {
    -  var obj = populateObject({}, 50, 4);
    -  var s = JSON.stringify(obj);
    -
    -  table.run(function() {
    -    var o = JSON.parse(s);
    -  }, 'Parse using JSON.parse');
    -
    -  table.run(function() {
    -    var o = goog.json.parse(s);
    -  }, 'Parse using goog.json.parse');
    -
    -  table.run(function() {
    -    var o = goog.json.unsafeParse(s);
    -  }, 'Parse using goog.json.unsafeParse');
    -}
    -
    -
    -/**
    - * @param {!Object} obj The object to add properties to.
    - * @param {number} numProperties The number of properties to add.
    - * @param {number} depth The depth at which to recursively add properties.
    - * @return {!Object} The object given in obj (for convenience).
    - */
    -function populateObject(obj, numProperties, depth) {
    -  if (depth == 0) {
    -    return randomLiteral();
    -  }
    -
    -  // Make an object with a mix of strings, numbers, arrays, objects, booleans
    -  // nulls as children.
    -  for (var i = 0; i < numProperties; i++) {
    -    var bucket = goog.math.randomInt(3);
    -    switch (bucket) {
    -      case 0:
    -        obj[i] = randomLiteral();
    -        break;
    -      case 1:
    -        obj[i] = populateObject({}, numProperties, depth - 1);
    -        break;
    -      case 2:
    -        obj[i] = populateObject([], numProperties, depth - 1);
    -        break;
    -    }
    -  }
    -  return obj;
    -}
    -
    -
    -function randomLiteral() {
    -  var bucket = goog.math.randomInt(3);
    -  switch (bucket) {
    -    case 0:
    -      return goog.string.getRandomString();
    -    case 1:
    -      return Math.random();
    -    case 2:
    -      return Math.random() >= .5;
    -  }
    -  return null;
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/json/json_test.html b/src/database/third_party/closure-library/closure/goog/json/json_test.html
    deleted file mode 100644
    index 3d49c9b56d2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/json/json_test.html
    +++ /dev/null
    @@ -1,19 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.json</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.jsonTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/json/json_test.js b/src/database/third_party/closure-library/closure/goog/json/json_test.js
    deleted file mode 100644
    index d762a9a74ee..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/json/json_test.js
    +++ /dev/null
    @@ -1,563 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.jsonTest');
    -goog.setTestOnly('goog.jsonTest');
    -
    -goog.require('goog.functions');
    -goog.require('goog.json');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -function allChars(start, end, opt_allowControlCharacters) {
    -  var sb = [];
    -  for (var i = start; i < end; i++) {
    -    // unicode without the control characters 0x00 - 0x1f
    -    if (opt_allowControlCharacters || i > 0x1f) {
    -      sb.push(String.fromCharCode(i));
    -    }
    -  }
    -  return sb.join('');
    -}
    -
    -// serialization
    -
    -function testStringSerialize() {
    -  assertSerialize('""', '');
    -
    -  // unicode
    -  var str = allChars(0, 10000);
    -  eval(goog.json.serialize(str));
    -
    -  assertSerialize('"true"', 'true');
    -  assertSerialize('"false"', 'false');
    -  assertSerialize('"null"', 'null');
    -  assertSerialize('"0"', '0');
    -}
    -
    -function testNullSerialize() {
    -  assertSerialize('null', null);
    -  assertSerialize('null', undefined);
    -  assertSerialize('null', NaN);
    -
    -  assertSerialize('0', 0);
    -  assertSerialize('""', '');
    -  assertSerialize('false', false);
    -}
    -
    -function testNullPropertySerialize() {
    -  assertSerialize('{"a":null}', {'a': null});
    -  assertSerialize('{"a":null}', {'a': undefined});
    -}
    -
    -function testNumberSerialize() {
    -  assertSerialize('0', 0);
    -  assertSerialize('12345', 12345);
    -  assertSerialize('-12345', -12345);
    -
    -  assertSerialize('0.1', 0.1);
    -  // the leading zero may not be omitted
    -  assertSerialize('0.1', .1);
    -
    -  // no leading +
    -  assertSerialize('1', +1);
    -
    -  // either format is OK
    -  var s = goog.json.serialize(1e50);
    -  assertTrue('1e50',
    -      s == '1e50' || s == '1E50' ||
    -      s == '1e+50' || s == '1E+50');
    -
    -  // either format is OK
    -  s = goog.json.serialize(1e-50);
    -  assertTrue('1e50', s == '1e-50' || s == '1E-50');
    -
    -  // These numbers cannot be represented in JSON
    -  assertSerialize('null', NaN);
    -  assertSerialize('null', Infinity);
    -  assertSerialize('null', -Infinity);
    -}
    -
    -function testBooleanSerialize() {
    -  assertSerialize('true', true);
    -  assertSerialize('"true"', 'true');
    -
    -  assertSerialize('false', false);
    -  assertSerialize('"false"', 'false');
    -}
    -
    -function testArraySerialize() {
    -  assertSerialize('[]', []);
    -  assertSerialize('[1]', [1]);
    -  assertSerialize('[1,2]', [1, 2]);
    -  assertSerialize('[1,2,3]', [1, 2, 3]);
    -  assertSerialize('[[]]', [[]]);
    -
    -  assertNotEquals('{length:0}', goog.json.serialize({length: 0}), '[]');
    -}
    -
    -function testObjectSerialize_emptyObject() {
    -  assertSerialize('{}', {});
    -}
    -
    -function testObjectSerialize_oneItem() {
    -  assertSerialize('{"a":"b"}', {a: 'b'});
    -}
    -
    -function testObjectSerialize_twoItems() {
    -  assertEquals('{"a":"b","c":"d"}',
    -               goog.json.serialize({a: 'b', c: 'd'}),
    -               '{"a":"b","c":"d"}');
    -}
    -
    -function testObjectSerialize_whitespace() {
    -  assertSerialize('{" ":" "}', {' ': ' '});
    -}
    -
    -function testSerializeSkipFunction() {
    -  var object = {
    -    s: 'string value',
    -    b: true,
    -    i: 100,
    -    f: function() { var x = 'x'; }
    -  };
    -  assertSerialize('', object.f);
    -  assertSerialize('{"s":"string value","b":true,"i":100}', object);
    -}
    -
    -function testObjectSerialize_array() {
    -  assertNotEquals('[0,1]', goog.json.serialize([0, 1]), '{"0":"0","1":"1"}');
    -}
    -
    -function testObjectSerialize_recursion() {
    -  if (goog.userAgent.WEBKIT) {
    -    return; // this makes safari 4 crash.
    -  }
    -
    -  var anObject = {};
    -  anObject.thisObject = anObject;
    -  assertThrows('expected recursion exception', function() {
    -    goog.json.serialize(anObject);
    -  });
    -}
    -
    -function testObjectSerializeWithHasOwnProperty() {
    -  var object = {'hasOwnProperty': null};
    -  if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9')) {
    -    assertEquals('{}', goog.json.serialize(object));
    -  } else {
    -    assertEquals('{"hasOwnProperty":null}', goog.json.serialize(object));
    -  }
    -}
    -
    -// parsing
    -
    -function testStringParse() {
    -
    -  assertEquals('Empty string', goog.json.parse('""'), '');
    -  assertEquals('whitespace string', goog.json.parse('" "'), ' ');
    -
    -  // unicode without the control characters 0x00 - 0x1f, 0x7f - 0x9f
    -  var str = allChars(0, 1000);
    -  var jsonString = goog.json.serialize(str);
    -  var a = eval(jsonString);
    -  assertEquals('unicode string', goog.json.parse(jsonString), a);
    -
    -  assertEquals('true as a string', goog.json.parse('"true"'), 'true');
    -  assertEquals('false as a string', goog.json.parse('"false"'), 'false');
    -  assertEquals('null as a string', goog.json.parse('"null"'), 'null');
    -  assertEquals('number as a string', goog.json.parse('"0"'), '0');
    -}
    -
    -function testStringUnsafeParse() {
    -
    -  assertEquals('Empty string', goog.json.unsafeParse('""'), '');
    -  assertEquals('whitespace string', goog.json.unsafeParse('" "'), ' ');
    -
    -  // unicode
    -  var str = allChars(0, 1000);
    -  var jsonString = goog.json.serialize(str);
    -  var a = eval(jsonString);
    -  assertEquals('unicode string', goog.json.unsafeParse(jsonString), a);
    -
    -  assertEquals('true as a string', goog.json.unsafeParse('"true"'), 'true');
    -  assertEquals('false as a string', goog.json.unsafeParse('"false"'), 'false');
    -  assertEquals('null as a string', goog.json.unsafeParse('"null"'), 'null');
    -  assertEquals('number as a string', goog.json.unsafeParse('"0"'), '0');
    -}
    -
    -function testNullParse() {
    -  assertEquals('null', goog.json.parse(null), null);
    -  assertEquals('null', goog.json.parse('null'), null);
    -
    -  assertNotEquals('0', goog.json.parse('0'), null);
    -  assertNotEquals('""', goog.json.parse('""'), null);
    -  assertNotEquals('false', goog.json.parse('false'), null);
    -}
    -
    -function testNullUnsafeParse() {
    -  assertEquals('null', goog.json.unsafeParse(null), null);
    -  assertEquals('null', goog.json.unsafeParse('null'), null);
    -
    -  assertNotEquals('0', goog.json.unsafeParse('0'), null);
    -  assertNotEquals('""', goog.json.unsafeParse('""'), null);
    -  assertNotEquals('false', goog.json.unsafeParse('false'), null);
    -}
    -
    -function testNumberParse() {
    -  assertEquals('0', goog.json.parse('0'), 0);
    -  assertEquals('12345', goog.json.parse('12345'), 12345);
    -  assertEquals('-12345', goog.json.parse('-12345'), -12345);
    -
    -  assertEquals('0.1', goog.json.parse('0.1'), 0.1);
    -
    -  // either format is OK
    -  assertEquals(1e50, goog.json.parse('1e50'));
    -  assertEquals(1e50, goog.json.parse('1E50'));
    -  assertEquals(1e50, goog.json.parse('1e+50'));
    -  assertEquals(1e50, goog.json.parse('1E+50'));
    -
    -  // either format is OK
    -  assertEquals(1e-50, goog.json.parse('1e-50'));
    -  assertEquals(1e-50, goog.json.parse('1E-50'));
    -}
    -
    -function testNumberUnsafeParse() {
    -  assertEquals('0', goog.json.unsafeParse('0'), 0);
    -  assertEquals('12345', goog.json.unsafeParse('12345'), 12345);
    -  assertEquals('-12345', goog.json.unsafeParse('-12345'), -12345);
    -
    -  assertEquals('0.1', goog.json.unsafeParse('0.1'), 0.1);
    -
    -  // either format is OK
    -  assertEquals(1e50, goog.json.unsafeParse('1e50'));
    -  assertEquals(1e50, goog.json.unsafeParse('1E50'));
    -  assertEquals(1e50, goog.json.unsafeParse('1e+50'));
    -  assertEquals(1e50, goog.json.unsafeParse('1E+50'));
    -
    -  // either format is OK
    -  assertEquals(1e-50, goog.json.unsafeParse('1e-50'));
    -  assertEquals(1e-50, goog.json.unsafeParse('1E-50'));
    -}
    -
    -function testBooleanParse() {
    -  assertEquals('true', goog.json.parse('true'), true);
    -  assertEquals('false', goog.json.parse('false'), false);
    -
    -  assertNotEquals('0', goog.json.parse('0'), false);
    -  assertNotEquals('"false"', goog.json.parse('"false"'), false);
    -  assertNotEquals('null', goog.json.parse('null'), false);
    -
    -  assertNotEquals('1', goog.json.parse('1'), true);
    -  assertNotEquals('"true"', goog.json.parse('"true"'), true);
    -  assertNotEquals('{}', goog.json.parse('{}'), true);
    -  assertNotEquals('[]', goog.json.parse('[]'), true);
    -}
    -
    -function testBooleanUnsafeParse() {
    -  assertEquals('true', goog.json.unsafeParse('true'), true);
    -  assertEquals('false', goog.json.unsafeParse('false'), false);
    -
    -  assertNotEquals('0', goog.json.unsafeParse('0'), false);
    -  assertNotEquals('"false"', goog.json.unsafeParse('"false"'), false);
    -  assertNotEquals('null', goog.json.unsafeParse('null'), false);
    -
    -  assertNotEquals('1', goog.json.unsafeParse('1'), true);
    -  assertNotEquals('"true"', goog.json.unsafeParse('"true"'), true);
    -  assertNotEquals('{}', goog.json.unsafeParse('{}'), true);
    -  assertNotEquals('[]', goog.json.unsafeParse('[]'), true);
    -}
    -
    -function testArrayParse() {
    -  assertArrayEquals([], goog.json.parse('[]'));
    -  assertArrayEquals([1], goog.json.parse('[1]'));
    -  assertArrayEquals([1, 2], goog.json.parse('[1,2]'));
    -  assertArrayEquals([1, 2, 3], goog.json.parse('[1,2,3]'));
    -  assertArrayEquals([[]], goog.json.parse('[[]]'));
    -
    -  // Note that array-holes are not valid json. However, goog.json.parse
    -  // supports them so that clients can reap the security benefits of
    -  // goog.json.parse even if they are using this non-standard format.
    -  assertArrayEquals([1, /* hole */, 3], goog.json.parse('[1,,3]'));
    -
    -  // make sure we do not get an array for something that looks like an array
    -  assertFalse('{length:0}', 'push' in goog.json.parse('{"length":0}'));
    -}
    -
    -function testArrayUnsafeParse() {
    -  function arrayEquals(a1, a2) {
    -    if (a1.length != a2.length) {
    -      return false;
    -    }
    -    for (var i = 0; i < a1.length; i++) {
    -      if (a1[i] != a2[i]) {
    -        return false;
    -      }
    -    }
    -    return true;
    -  }
    -
    -  assertTrue('[]', arrayEquals(goog.json.unsafeParse('[]'), []));
    -  assertTrue('[1]', arrayEquals(goog.json.unsafeParse('[1]'), [1]));
    -  assertTrue('[1,2]', arrayEquals(goog.json.unsafeParse('[1,2]'), [1, 2]));
    -  assertTrue('[1,2,3]',
    -      arrayEquals(goog.json.unsafeParse('[1,2,3]'), [1, 2, 3]));
    -  assertTrue('[[]]', arrayEquals(goog.json.unsafeParse('[[]]')[0], []));
    -
    -  // make sure we do not get an array for something that looks like an array
    -  assertFalse('{length:0}', 'push' in goog.json.unsafeParse('{"length":0}'));
    -}
    -
    -function testObjectParse() {
    -  function objectEquals(a1, a2) {
    -    for (var key in a1) {
    -      if (a1[key] != a2[key]) {
    -        return false;
    -      }
    -    }
    -    return true;
    -  }
    -
    -  assertTrue('{}', objectEquals(goog.json.parse('{}'), {}));
    -  assertTrue('{"a":"b"}',
    -      objectEquals(goog.json.parse('{"a":"b"}'), {a: 'b'}));
    -  assertTrue('{"a":"b","c":"d"}',
    -             objectEquals(goog.json.parse('{"a":"b","c":"d"}'),
    -             {a: 'b', c: 'd'}));
    -  assertTrue('{" ":" "}',
    -      objectEquals(goog.json.parse('{" ":" "}'), {' ': ' '}));
    -
    -  // make sure we do not get an Object when it is really an array
    -  assertTrue('[0,1]', 'length' in goog.json.parse('[0,1]'));
    -}
    -
    -function testObjectUnsafeParse() {
    -  function objectEquals(a1, a2) {
    -    for (var key in a1) {
    -      if (a1[key] != a2[key]) {
    -        return false;
    -      }
    -    }
    -    return true;
    -  }
    -
    -  assertTrue('{}', objectEquals(goog.json.unsafeParse('{}'), {}));
    -  assertTrue('{"a":"b"}',
    -      objectEquals(goog.json.unsafeParse('{"a":"b"}'), {a: 'b'}));
    -  assertTrue('{"a":"b","c":"d"}',
    -             objectEquals(goog.json.unsafeParse('{"a":"b","c":"d"}'),
    -             {a: 'b', c: 'd'}));
    -  assertTrue('{" ":" "}',
    -      objectEquals(goog.json.unsafeParse('{" ":" "}'), {' ': ' '}));
    -
    -  // make sure we do not get an Object when it is really an array
    -  assertTrue('[0,1]', 'length' in goog.json.unsafeParse('[0,1]'));
    -}
    -
    -
    -function testForValidJson() {
    -  function error_(msg, s) {
    -    assertThrows(msg + ', Should have raised an exception: ' + s,
    -        goog.partial(goog.json.parse, s));
    -  }
    -
    -  error_('Non closed string', '"dasdas');
    -  error_('undefined is not valid json', 'undefined');
    -
    -  // These numbers cannot be represented in JSON
    -  error_('NaN cannot be presented in JSON', 'NaN');
    -  error_('Infinity cannot be presented in JSON', 'Infinity');
    -  error_('-Infinity cannot be presented in JSON', '-Infinity');
    -}
    -
    -function testIsNotValid() {
    -  assertFalse(goog.json.isValid('t'));
    -  assertFalse(goog.json.isValid('r'));
    -  assertFalse(goog.json.isValid('u'));
    -  assertFalse(goog.json.isValid('e'));
    -  assertFalse(goog.json.isValid('f'));
    -  assertFalse(goog.json.isValid('a'));
    -  assertFalse(goog.json.isValid('l'));
    -  assertFalse(goog.json.isValid('s'));
    -  assertFalse(goog.json.isValid('n'));
    -  assertFalse(goog.json.isValid('E'));
    -
    -  assertFalse(goog.json.isValid('+'));
    -  assertFalse(goog.json.isValid('-'));
    -
    -  assertFalse(goog.json.isValid('t++'));
    -  assertFalse(goog.json.isValid('++t'));
    -  assertFalse(goog.json.isValid('t--'));
    -  assertFalse(goog.json.isValid('--t'));
    -  assertFalse(goog.json.isValid('-t'));
    -  assertFalse(goog.json.isValid('+t'));
    -
    -  assertFalse(goog.json.isValid('"\\"')); // "\"
    -  assertFalse(goog.json.isValid('"\\'));  // "\
    -
    -  // multiline string using \ at the end is not valid
    -  assertFalse(goog.json.isValid('"a\\\nb"'));
    -
    -
    -  assertFalse(goog.json.isValid('"\n"'));
    -  assertFalse(goog.json.isValid('"\r"'));
    -  assertFalse(goog.json.isValid('"\r\n"'));
    -  // Disallow the unicode newlines
    -  assertFalse(goog.json.isValid('"\u2028"'));
    -  assertFalse(goog.json.isValid('"\u2029"'));
    -
    -  assertFalse(goog.json.isValid(' '));
    -  assertFalse(goog.json.isValid('\n'));
    -  assertFalse(goog.json.isValid('\r'));
    -  assertFalse(goog.json.isValid('\r\n'));
    -
    -  assertFalse(goog.json.isValid('t.r'));
    -
    -  assertFalse(goog.json.isValid('1e'));
    -  assertFalse(goog.json.isValid('1e-'));
    -  assertFalse(goog.json.isValid('1e+'));
    -
    -  assertFalse(goog.json.isValid('1e-'));
    -
    -  assertFalse(goog.json.isValid('"\\\u200D\\"'));
    -  assertFalse(goog.json.isValid('"\\\0\\"'));
    -  assertFalse(goog.json.isValid('"\\\0"'));
    -  assertFalse(goog.json.isValid('"\\0"'));
    -  assertFalse(goog.json.isValid('"\x0c"'));
    -
    -  assertFalse(goog.json.isValid('"\\\u200D\\", alert(\'foo\') //"\n'));
    -}
    -
    -function testIsValid() {
    -  assertTrue(goog.json.isValid('\n""\n'));
    -  assertTrue(goog.json.isValid('[1\n,2\r,3\u2028\n,4\u2029]'));
    -  assertTrue(goog.json.isValid('"\x7f"'));
    -  assertTrue(goog.json.isValid('"\x09"'));
    -  // Test tab characters in json.
    -  assertTrue(goog.json.isValid('{"\t":"\t"}'));
    -}
    -
    -function testDoNotSerializeProto() {
    -  function F() {};
    -  F.prototype = {
    -    c: 3
    -  };
    -
    -  var obj = new F;
    -  obj.a = 1;
    -  obj.b = 2;
    -
    -  assertEquals('Should not follow the prototype chain',
    -               '{"a":1,"b":2}',
    -               goog.json.serialize(obj));
    -}
    -
    -function testEscape() {
    -  var unescaped = '1a*/]';
    -  assertEquals('Should not escape',
    -               '"' + unescaped + '"',
    -               goog.json.serialize(unescaped));
    -
    -  var escaped = '\n\x7f\u1049';
    -  assertEquals('Should escape',
    -               '',
    -               findCommonChar(escaped, goog.json.serialize(escaped)));
    -  assertEquals('Should eval to the same string after escaping',
    -               escaped,
    -               goog.json.parse(goog.json.serialize(escaped)));
    -}
    -
    -function testReplacer() {
    -  assertSerialize('[null,null,0]', [, , 0]);
    -
    -  assertSerialize('[0,0,{"x":0}]', [, , {x: 0}], function(k, v) {
    -    if (v === undefined && goog.isArray(this)) {
    -      return 0;
    -    }
    -    return v;
    -  });
    -
    -  assertSerialize('[0,1,2,3]', [0, 0, 0, 0], function(k, v) {
    -    var kNum = Number(k);
    -    if (k && !isNaN(kNum)) {
    -      return kNum;
    -    }
    -    return v;
    -  });
    -
    -  var f = function(k, v) {
    -    return typeof v == 'number' ? v + 1 : v;
    -  };
    -  assertSerialize('{"a":1,"b":{"c":2}}', {'a': 0, 'b': {'c': 1}}, f);
    -}
    -
    -function testDateSerialize() {
    -  assertSerialize('{}', new Date(0));
    -}
    -
    -function testToJSONSerialize() {
    -  assertSerialize('{}', {toJSON: goog.functions.constant('serialized')});
    -  assertSerialize('{"toJSON":"normal"}', {toJSON: 'normal'});
    -}
    -
    -
    -/**
    - * Asserts that the given object serializes to the given value.
    - * If the current browser has an implementation of JSON.serialize,
    - * we make sure our version matches that one.
    - */
    -function assertSerialize(expected, obj, opt_replacer) {
    -  assertEquals(expected, goog.json.serialize(obj, opt_replacer));
    -
    -  // I'm pretty sure that the goog.json.serialize behavior is correct by the ES5
    -  // spec, but JSON.stringify(undefined) is undefined on all browsers.
    -  if (obj === undefined) return;
    -
    -  // Browsers don't serialize undefined properties, but goog.json.serialize does
    -  if (goog.isObject(obj) && ('a' in obj) && obj['a'] === undefined) return;
    -
    -  // Replacers are broken on IE and older versions of firefox.
    -  if (opt_replacer && !goog.userAgent.WEBKIT) return;
    -
    -  // goog.json.serialize does not stringify dates the same way.
    -  if (obj instanceof Date) return;
    -
    -  // goog.json.serialize does not stringify functions the same way.
    -  if (obj instanceof Function) return;
    -
    -  // goog.json.serialize doesn't use the toJSON method.
    -  if (goog.isObject(obj) && goog.isFunction(obj.toJSON)) return;
    -
    -  if (typeof JSON != 'undefined') {
    -    assertEquals(
    -        'goog.json.serialize does not match JSON.stringify',
    -        expected,
    -        JSON.stringify(obj, opt_replacer));
    -  }
    -}
    -
    -
    -/**
    - * @param {string} a
    - * @param {string} b
    - * @return {string} any common character between two strings a and b.
    - */
    -function findCommonChar(a, b) {
    -  for (var i = 0; i < b.length; i++) {
    -    if (a.indexOf(b.charAt(i)) >= 0) {
    -      return b.charAt(i);
    -    }
    -  }
    -  return '';
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/json/nativejsonprocessor.js b/src/database/third_party/closure-library/closure/goog/json/nativejsonprocessor.js
    deleted file mode 100644
    index c6359aa325c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/json/nativejsonprocessor.js
    +++ /dev/null
    @@ -1,73 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Defines a class for parsing JSON using the browser's built in
    - * JSON library.
    - */
    -
    -goog.provide('goog.json.NativeJsonProcessor');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.json.Processor');
    -
    -
    -
    -/**
    - * A class that parses and stringifies JSON using the browser's built-in JSON
    - * library, if it is avaliable.
    - *
    - * Note that the native JSON api has subtle differences across browsers, so
    - * use this implementation with care.  See json_test#assertSerialize
    - * for details on the differences from goog.json.
    - *
    - * This implementation is signficantly faster than goog.json, at least on
    - * Chrome.  See json_perf.html for a perf test showing the difference.
    - *
    - * @param {?goog.json.Replacer=} opt_replacer An optional replacer to use during
    - *     serialization.
    - * @param {?goog.json.Reviver=} opt_reviver An optional reviver to use during
    - *     parsing.
    - * @constructor
    - * @implements {goog.json.Processor}
    - * @final
    - */
    -goog.json.NativeJsonProcessor = function(opt_replacer, opt_reviver) {
    -  goog.asserts.assert(goog.isDef(goog.global['JSON']), 'JSON not defined');
    -
    -  /**
    -   * @type {goog.json.Replacer|null|undefined}
    -   * @private
    -   */
    -  this.replacer_ = opt_replacer;
    -
    -  /**
    -   * @type {goog.json.Reviver|null|undefined}
    -   * @private
    -   */
    -  this.reviver_ = opt_reviver;
    -};
    -
    -
    -/** @override */
    -goog.json.NativeJsonProcessor.prototype.stringify = function(object) {
    -  return goog.global['JSON'].stringify(object, this.replacer_);
    -};
    -
    -
    -/** @override */
    -goog.json.NativeJsonProcessor.prototype.parse = function(s) {
    -  return goog.global['JSON'].parse(s, this.reviver_);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/json/processor.js b/src/database/third_party/closure-library/closure/goog/json/processor.js
    deleted file mode 100644
    index 5ac3df248d7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/json/processor.js
    +++ /dev/null
    @@ -1,33 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Defines an interface for JSON parsing and serialization.
    - */
    -
    -goog.provide('goog.json.Processor');
    -
    -goog.require('goog.string.Parser');
    -goog.require('goog.string.Stringifier');
    -
    -
    -
    -/**
    - * An interface for JSON parsing and serialization.
    - * @interface
    - * @extends {goog.string.Parser}
    - * @extends {goog.string.Stringifier}
    - */
    -goog.json.Processor = function() {};
    diff --git a/src/database/third_party/closure-library/closure/goog/json/processor_test.html b/src/database/third_party/closure-library/closure/goog/json/processor_test.html
    deleted file mode 100644
    index 2e270e39d86..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/json/processor_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.json.Processor
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.json.processorTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/json/processor_test.js b/src/database/third_party/closure-library/closure/goog/json/processor_test.js
    deleted file mode 100644
    index 2e508e09af6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/json/processor_test.js
    +++ /dev/null
    @@ -1,88 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.json.processorTest');
    -goog.setTestOnly('goog.json.processorTest');
    -
    -goog.require('goog.json.EvalJsonProcessor');
    -goog.require('goog.json.NativeJsonProcessor');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -var SUPPORTS_NATIVE_JSON = false;
    -
    -function setUpPage() {
    -  SUPPORTS_NATIVE_JSON = goog.global['JSON'] &&
    -      !(goog.userAgent.GECKO && !goog.userAgent.isVersionOrHigher('5.0'));
    -}
    -
    -var REPLACER = function(k, v) {
    -  return !!k ? v + 'd' : v;
    -};
    -
    -var REVIVER = function(k, v) {
    -  return !!k ? v.substring(0, v.length - 1) : v;
    -};
    -
    -// Just sanity check parsing and stringifying.
    -// Thorough tests are in json_test.html.
    -
    -function testJsParser() {
    -  var json = '{"a":1,"b":{"c":2}}';
    -  runParsingTest(new goog.json.EvalJsonProcessor(), json, json);
    -}
    -
    -function testNativeParser() {
    -  if (!SUPPORTS_NATIVE_JSON) {
    -    return;
    -  }
    -  var json = '{"a":1,"b":{"c":2}}';
    -  runParsingTest(new goog.json.NativeJsonProcessor(), json, json);
    -}
    -
    -function testJsParser_withReplacer() {
    -  runParsingTest(new goog.json.EvalJsonProcessor(REPLACER),
    -      '{"a":"foo","b":"goo"}', '{"a":"food","b":"good"}');
    -}
    -
    -function testNativeParser_withReplacer() {
    -  if (!SUPPORTS_NATIVE_JSON) {
    -    return;
    -  }
    -  runParsingTest(new goog.json.NativeJsonProcessor(REPLACER),
    -      '{"a":"foo","b":"goo"}', '{"a":"food","b":"good"}');
    -}
    -
    -function testNativeParser_withReviver() {
    -  if (!SUPPORTS_NATIVE_JSON) {
    -    return;
    -  }
    -  var json = '{"a":"fod","b":"god"}';
    -  runParsingTest(new goog.json.NativeJsonProcessor(REPLACER, REVIVER),
    -      json, json);
    -}
    -
    -function testUnsafeJsParser() {
    -  var json = '{"a":1,"b":{"c":2}}';
    -  runParsingTest(new goog.json.EvalJsonProcessor(null, true), json, json);
    -}
    -
    -function testUnsafeJsParser_withReplacer() {
    -  runParsingTest(new goog.json.EvalJsonProcessor(REPLACER, true),
    -      '{"a":"foo","b":"goo"}', '{"a":"food","b":"good"}');
    -}
    -
    -function runParsingTest(parser, input, expected) {
    -  assertEquals(expected, parser.stringify(parser.parse(input)));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/dom/pagevisibilitymonitor.js b/src/database/third_party/closure-library/closure/goog/labs/dom/pagevisibilitymonitor.js
    deleted file mode 100644
    index ef77c999a51..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/dom/pagevisibilitymonitor.js
    +++ /dev/null
    @@ -1,211 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview This event monitor wraps the Page Visibility API.
    - * @see http://www.w3.org/TR/page-visibility/
    - */
    -
    -goog.provide('goog.labs.dom.PageVisibilityEvent');
    -goog.provide('goog.labs.dom.PageVisibilityMonitor');
    -goog.provide('goog.labs.dom.PageVisibilityState');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.vendor');
    -goog.require('goog.events');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -goog.require('goog.memoize');
    -
    -goog.scope(function() {
    -var dom = goog.labs.dom;
    -
    -
    -/**
    - * The different visibility states.
    - * @enum {string}
    - */
    -dom.PageVisibilityState = {
    -  HIDDEN: 'hidden',
    -  VISIBLE: 'visible',
    -  PRERENDER: 'prerender',
    -  UNLOADED: 'unloaded'
    -};
    -
    -
    -
    -/**
    - * This event handler allows you to catch page visibility change events.
    - * @param {!goog.dom.DomHelper=} opt_domHelper
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - * @final
    - */
    -dom.PageVisibilityMonitor = function(opt_domHelper) {
    -  dom.PageVisibilityMonitor.base(this, 'constructor');
    -
    -  /**
    -   * @private {!goog.dom.DomHelper}
    -   */
    -  this.domHelper_ = opt_domHelper || goog.dom.getDomHelper();
    -
    -  /**
    -   * @private {?string}
    -   */
    -  this.eventType_ = this.getBrowserEventType_();
    -
    -  // Some browsers do not support visibilityChange and therefore we don't bother
    -  // setting up events.
    -  if (this.eventType_) {
    -    /**
    -     * @private {goog.events.Key}
    -     */
    -    this.eventKey_ = goog.events.listen(this.domHelper_.getDocument(),
    -        this.eventType_, goog.bind(this.handleChange_, this));
    -  }
    -};
    -goog.inherits(dom.PageVisibilityMonitor, goog.events.EventTarget);
    -
    -
    -/**
    - * @return {?string} The visibility change event type, or null if not supported.
    - *     Memoized for performance.
    - * @private
    - */
    -dom.PageVisibilityMonitor.prototype.getBrowserEventType_ =
    -    goog.memoize(function() {
    -  var isSupported = this.isSupported();
    -  var isPrefixed = this.isPrefixed_();
    -
    -  if (isSupported) {
    -    return isPrefixed ? goog.dom.vendor.getPrefixedEventType(
    -        goog.events.EventType.VISIBILITYCHANGE) :
    -        goog.events.EventType.VISIBILITYCHANGE;
    -  } else {
    -    return null;
    -  }
    -});
    -
    -
    -/**
    - * @return {?string} The browser-specific document.hidden property.  Memoized
    - *     for performance.
    - * @private
    - */
    -dom.PageVisibilityMonitor.prototype.getHiddenPropertyName_ = goog.memoize(
    -    function() {
    -      return goog.dom.vendor.getPrefixedPropertyName(
    -          'hidden', this.domHelper_.getDocument());
    -    });
    -
    -
    -/**
    - * @return {boolean} Whether the visibility API is prefixed.
    - * @private
    - */
    -dom.PageVisibilityMonitor.prototype.isPrefixed_ = function() {
    -  return this.getHiddenPropertyName_() != 'hidden';
    -};
    -
    -
    -/**
    - * @return {?string} The browser-specific document.visibilityState property.
    - *     Memoized for performance.
    - * @private
    - */
    -dom.PageVisibilityMonitor.prototype.getVisibilityStatePropertyName_ =
    -    goog.memoize(function() {
    -  return goog.dom.vendor.getPrefixedPropertyName(
    -      'visibilityState', this.domHelper_.getDocument());
    -});
    -
    -
    -/**
    - * @return {boolean} Whether the visibility API is supported.
    - */
    -dom.PageVisibilityMonitor.prototype.isSupported = function() {
    -  return !!this.getHiddenPropertyName_();
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the page is visible.
    - */
    -dom.PageVisibilityMonitor.prototype.isHidden = function() {
    -  return !!this.domHelper_.getDocument()[this.getHiddenPropertyName_()];
    -};
    -
    -
    -/**
    - * @return {?dom.PageVisibilityState} The page visibility state, or null if
    - *     not supported.
    - */
    -dom.PageVisibilityMonitor.prototype.getVisibilityState = function() {
    -  if (!this.isSupported()) {
    -    return null;
    -  }
    -  return this.domHelper_.getDocument()[this.getVisibilityStatePropertyName_()];
    -};
    -
    -
    -/**
    - * Handles the events on the element.
    - * @param {goog.events.BrowserEvent} e The underlying browser event.
    - * @private
    - */
    -dom.PageVisibilityMonitor.prototype.handleChange_ = function(e) {
    -  var state = this.getVisibilityState();
    -  var visibilityEvent = new dom.PageVisibilityEvent(
    -      this.isHidden(), /** @type {dom.PageVisibilityState} */ (state));
    -  this.dispatchEvent(visibilityEvent);
    -};
    -
    -
    -/** @override */
    -dom.PageVisibilityMonitor.prototype.disposeInternal = function() {
    -  goog.events.unlistenByKey(this.eventKey_);
    -  dom.PageVisibilityMonitor.base(this, 'disposeInternal');
    -};
    -
    -
    -
    -/**
    - * A page visibility change event.
    - * @param {boolean} hidden Whether the page is hidden.
    - * @param {goog.labs.dom.PageVisibilityState} visibilityState A more detailed
    - *     visibility state.
    - * @constructor
    - * @extends {goog.events.Event}
    - * @final
    - */
    -dom.PageVisibilityEvent = function(hidden, visibilityState) {
    -  dom.PageVisibilityEvent.base(
    -      this, 'constructor', goog.events.EventType.VISIBILITYCHANGE);
    -
    -  /**
    -   * Whether the page is hidden.
    -   * @type {boolean}
    -   */
    -  this.hidden = hidden;
    -
    -  /**
    -   * A more detailed visibility state.
    -   * @type {dom.PageVisibilityState}
    -   */
    -  this.visibilityState = visibilityState;
    -};
    -goog.inherits(dom.PageVisibilityEvent, goog.events.Event);
    -
    -});  // goog.scope
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/dom/pagevisibilitymonitor_test.js b/src/database/third_party/closure-library/closure/goog/labs/dom/pagevisibilitymonitor_test.js
    deleted file mode 100644
    index f1d21f79711..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/dom/pagevisibilitymonitor_test.js
    +++ /dev/null
    @@ -1,87 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.labs.dom.PageVisibilityMonitorTest');
    -goog.setTestOnly('goog.labs.dom.PageVisibilityMonitorTest');
    -
    -goog.require('goog.events');
    -goog.require('goog.functions');
    -goog.require('goog.labs.dom.PageVisibilityMonitor');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.events.Event');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -
    -var stubs = new goog.testing.PropertyReplacer();
    -var vh;
    -
    -
    -function tearDown() {
    -  goog.dispose(vh);
    -  vh = null;
    -  stubs.reset();
    -}
    -
    -function testConstructor() {
    -  vh = new goog.labs.dom.PageVisibilityMonitor();
    -}
    -
    -function testNoVisibilitySupport() {
    -  stubs.set(goog.labs.dom.PageVisibilityMonitor.prototype,
    -      'getBrowserEventType_', goog.functions.NULL);
    -
    -  var listener = goog.testing.recordFunction();
    -  vh = new goog.labs.dom.PageVisibilityMonitor();
    -
    -  goog.events.listen(vh, 'visibilitychange', listener);
    -
    -  var e = new goog.testing.events.Event('visibilitychange');
    -  e.target = window.document;
    -  goog.testing.events.fireBrowserEvent(e);
    -  assertEquals(0, listener.getCallCount());
    -}
    -
    -function testListener() {
    -  stubs.set(goog.labs.dom.PageVisibilityMonitor.prototype,
    -      'getBrowserEventType_', goog.functions.constant('visibilitychange'));
    -
    -  var listener = goog.testing.recordFunction();
    -  vh = new goog.labs.dom.PageVisibilityMonitor();
    -
    -  goog.events.listen(vh, 'visibilitychange', listener);
    -
    -  var e = new goog.testing.events.Event('visibilitychange');
    -  e.target = window.document;
    -  goog.testing.events.fireBrowserEvent(e);
    -
    -  assertEquals(1, listener.getCallCount());
    -}
    -
    -function testListenerForWebKit() {
    -  stubs.set(goog.labs.dom.PageVisibilityMonitor.prototype,
    -      'getBrowserEventType_',
    -      goog.functions.constant('webkitvisibilitychange'));
    -
    -  var listener = goog.testing.recordFunction();
    -  vh = new goog.labs.dom.PageVisibilityMonitor();
    -
    -  goog.events.listen(vh, 'visibilitychange', listener);
    -
    -  var e = new goog.testing.events.Event('webkitvisibilitychange');
    -  e.target = window.document;
    -  goog.testing.events.fireBrowserEvent(e);
    -
    -  assertEquals(1, listener.getCallCount());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/events/nondisposableeventtarget.js b/src/database/third_party/closure-library/closure/goog/labs/events/nondisposableeventtarget.js
    deleted file mode 100644
    index ea421094ee2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/events/nondisposableeventtarget.js
    +++ /dev/null
    @@ -1,305 +0,0 @@
    -// Copyright 2005 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview An implementation of {@link goog.events.Listenable} that does
    - * not need to be disposed.
    - */
    -
    -goog.provide('goog.labs.events.NonDisposableEventTarget');
    -
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.Listenable');
    -goog.require('goog.events.ListenerMap');
    -goog.require('goog.object');
    -
    -
    -
    -/**
    - * An implementation of {@code goog.events.Listenable} with full W3C
    - * EventTarget-like support (capture/bubble mechanism, stopping event
    - * propagation, preventing default actions).
    - *
    - * You may subclass this class to turn your class into a Listenable.
    - *
    - * Unlike {@link goog.events.EventTarget}, this class does not implement
    - * {@link goog.disposable.IDisposable}. Instances of this class that have had
    - * It is not necessary to call {@link goog.dispose}
    - * or {@link #removeAllListeners} in order for an instance of this class
    - * to be garbage collected.
    - *
    - * Unless propagation is stopped, an event dispatched by an
    - * EventTarget will bubble to the parent returned by
    - * {@code getParentEventTarget}. To set the parent, call
    - * {@code setParentEventTarget}. Subclasses that don't support
    - * changing the parent can override the setter to throw an error.
    - *
    - * Example usage:
    - * <pre>
    - *   var source = new goog.labs.events.NonDisposableEventTarget();
    - *   function handleEvent(e) {
    - *     alert('Type: ' + e.type + '; Target: ' + e.target);
    - *   }
    - *   source.listen('foo', handleEvent);
    - *   source.dispatchEvent('foo'); // will call handleEvent
    - * </pre>
    - *
    - * TODO(chrishenry|johnlenz): Consider a more modern, less viral
    - * (not based on inheritance) replacement of goog.Disposable, which will allow
    - * goog.events.EventTarget to not be disposable.
    - *
    - * @constructor
    - * @implements {goog.events.Listenable}
    - * @final
    - */
    -goog.labs.events.NonDisposableEventTarget = function() {
    -  /**
    -   * Maps of event type to an array of listeners.
    -   * @private {!goog.events.ListenerMap}
    -   */
    -  this.eventTargetListeners_ = new goog.events.ListenerMap(this);
    -};
    -goog.events.Listenable.addImplementation(
    -    goog.labs.events.NonDisposableEventTarget);
    -
    -
    -/**
    - * An artificial cap on the number of ancestors you can have. This is mainly
    - * for loop detection.
    - * @const {number}
    - * @private
    - */
    -goog.labs.events.NonDisposableEventTarget.MAX_ANCESTORS_ = 1000;
    -
    -
    -/**
    - * Parent event target, used during event bubbling.
    - * @private {goog.events.Listenable}
    - */
    -goog.labs.events.NonDisposableEventTarget.prototype.parentEventTarget_ = null;
    -
    -
    -/** @override */
    -goog.labs.events.NonDisposableEventTarget.prototype.getParentEventTarget =
    -    function() {
    -  return this.parentEventTarget_;
    -};
    -
    -
    -/**
    - * Sets the parent of this event target to use for capture/bubble
    - * mechanism.
    - * @param {goog.events.Listenable} parent Parent listenable (null if none).
    - */
    -goog.labs.events.NonDisposableEventTarget.prototype.setParentEventTarget =
    -    function(parent) {
    -  this.parentEventTarget_ = parent;
    -};
    -
    -
    -/** @override */
    -goog.labs.events.NonDisposableEventTarget.prototype.dispatchEvent = function(
    -    e) {
    -  this.assertInitialized_();
    -  var ancestorsTree, ancestor = this.getParentEventTarget();
    -  if (ancestor) {
    -    ancestorsTree = [];
    -    var ancestorCount = 1;
    -    for (; ancestor; ancestor = ancestor.getParentEventTarget()) {
    -      ancestorsTree.push(ancestor);
    -      goog.asserts.assert(
    -          (++ancestorCount <
    -                  goog.labs.events.NonDisposableEventTarget.MAX_ANCESTORS_),
    -          'infinite loop');
    -    }
    -  }
    -
    -  return goog.labs.events.NonDisposableEventTarget.dispatchEventInternal_(
    -      this, e, ancestorsTree);
    -};
    -
    -
    -/** @override */
    -goog.labs.events.NonDisposableEventTarget.prototype.listen = function(
    -    type, listener, opt_useCapture, opt_listenerScope) {
    -  this.assertInitialized_();
    -  return this.eventTargetListeners_.add(
    -      String(type), listener, false /* callOnce */, opt_useCapture,
    -      opt_listenerScope);
    -};
    -
    -
    -/** @override */
    -goog.labs.events.NonDisposableEventTarget.prototype.listenOnce = function(
    -    type, listener, opt_useCapture, opt_listenerScope) {
    -  return this.eventTargetListeners_.add(
    -      String(type), listener, true /* callOnce */, opt_useCapture,
    -      opt_listenerScope);
    -};
    -
    -
    -/** @override */
    -goog.labs.events.NonDisposableEventTarget.prototype.unlisten = function(
    -    type, listener, opt_useCapture, opt_listenerScope) {
    -  return this.eventTargetListeners_.remove(
    -      String(type), listener, opt_useCapture, opt_listenerScope);
    -};
    -
    -
    -/** @override */
    -goog.labs.events.NonDisposableEventTarget.prototype.unlistenByKey = function(
    -    key) {
    -  return this.eventTargetListeners_.removeByKey(key);
    -};
    -
    -
    -/** @override */
    -goog.labs.events.NonDisposableEventTarget.prototype.removeAllListeners =
    -    function(opt_type) {
    -  return this.eventTargetListeners_.removeAll(opt_type);
    -};
    -
    -
    -/** @override */
    -goog.labs.events.NonDisposableEventTarget.prototype.fireListeners = function(
    -    type, capture, eventObject) {
    -  // TODO(chrishenry): Original code avoids array creation when there
    -  // is no listener, so we do the same. If this optimization turns
    -  // out to be not required, we can replace this with
    -  // getListeners(type, capture) instead, which is simpler.
    -  var listenerArray = this.eventTargetListeners_.listeners[String(type)];
    -  if (!listenerArray) {
    -    return true;
    -  }
    -  listenerArray = goog.array.clone(listenerArray);
    -
    -  var rv = true;
    -  for (var i = 0; i < listenerArray.length; ++i) {
    -    var listener = listenerArray[i];
    -    // We might not have a listener if the listener was removed.
    -    if (listener && !listener.removed && listener.capture == capture) {
    -      var listenerFn = listener.listener;
    -      var listenerHandler = listener.handler || listener.src;
    -
    -      if (listener.callOnce) {
    -        this.unlistenByKey(listener);
    -      }
    -      rv = listenerFn.call(listenerHandler, eventObject) !== false && rv;
    -    }
    -  }
    -
    -  return rv && eventObject.returnValue_ != false;
    -};
    -
    -
    -/** @override */
    -goog.labs.events.NonDisposableEventTarget.prototype.getListeners = function(
    -    type, capture) {
    -  return this.eventTargetListeners_.getListeners(String(type), capture);
    -};
    -
    -
    -/** @override */
    -goog.labs.events.NonDisposableEventTarget.prototype.getListener = function(
    -    type, listener, capture, opt_listenerScope) {
    -  return this.eventTargetListeners_.getListener(
    -      String(type), listener, capture, opt_listenerScope);
    -};
    -
    -
    -/** @override */
    -goog.labs.events.NonDisposableEventTarget.prototype.hasListener = function(
    -    opt_type, opt_capture) {
    -  var id = goog.isDef(opt_type) ? String(opt_type) : undefined;
    -  return this.eventTargetListeners_.hasListener(id, opt_capture);
    -};
    -
    -
    -/**
    - * Asserts that the event target instance is initialized properly.
    - * @private
    - */
    -goog.labs.events.NonDisposableEventTarget.prototype.assertInitialized_ =
    -    function() {
    -  goog.asserts.assert(
    -      this.eventTargetListeners_,
    -      'Event target is not initialized. Did you call the superclass ' +
    -      '(goog.labs.events.NonDisposableEventTarget) constructor?');
    -};
    -
    -
    -/**
    - * Dispatches the given event on the ancestorsTree.
    - *
    - * TODO(chrishenry): Look for a way to reuse this logic in
    - * goog.events, if possible.
    - *
    - * @param {!Object} target The target to dispatch on.
    - * @param {goog.events.Event|Object|string} e The event object.
    - * @param {Array<goog.events.Listenable>=} opt_ancestorsTree The ancestors
    - *     tree of the target, in reverse order from the closest ancestor
    - *     to the root event target. May be null if the target has no ancestor.
    - * @return {boolean} If anyone called preventDefault on the event object (or
    - *     if any of the listeners returns false) this will also return false.
    - * @private
    - */
    -goog.labs.events.NonDisposableEventTarget.dispatchEventInternal_ = function(
    -    target, e, opt_ancestorsTree) {
    -  var type = e.type || /** @type {string} */ (e);
    -
    -  // If accepting a string or object, create a custom event object so that
    -  // preventDefault and stopPropagation work with the event.
    -  if (goog.isString(e)) {
    -    e = new goog.events.Event(e, target);
    -  } else if (!(e instanceof goog.events.Event)) {
    -    var oldEvent = e;
    -    e = new goog.events.Event(type, target);
    -    goog.object.extend(e, oldEvent);
    -  } else {
    -    e.target = e.target || target;
    -  }
    -
    -  var rv = true, currentTarget;
    -
    -  // Executes all capture listeners on the ancestors, if any.
    -  if (opt_ancestorsTree) {
    -    for (var i = opt_ancestorsTree.length - 1; !e.propagationStopped_ && i >= 0;
    -         i--) {
    -      currentTarget = e.currentTarget = opt_ancestorsTree[i];
    -      rv = currentTarget.fireListeners(type, true, e) && rv;
    -    }
    -  }
    -
    -  // Executes capture and bubble listeners on the target.
    -  if (!e.propagationStopped_) {
    -    currentTarget = e.currentTarget = target;
    -    rv = currentTarget.fireListeners(type, true, e) && rv;
    -    if (!e.propagationStopped_) {
    -      rv = currentTarget.fireListeners(type, false, e) && rv;
    -    }
    -  }
    -
    -  // Executes all bubble listeners on the ancestors, if any.
    -  if (opt_ancestorsTree) {
    -    for (i = 0; !e.propagationStopped_ && i < opt_ancestorsTree.length; i++) {
    -      currentTarget = e.currentTarget = opt_ancestorsTree[i];
    -      rv = currentTarget.fireListeners(type, false, e) && rv;
    -    }
    -  }
    -
    -  return rv;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/events/nondisposableeventtarget_test.html b/src/database/third_party/closure-library/closure/goog/labs/events/nondisposableeventtarget_test.html
    deleted file mode 100644
    index 63ee72aba9f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/events/nondisposableeventtarget_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.labs.events.EventTarget
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.labs.events.NonDisposableEventTargetTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/events/nondisposableeventtarget_test.js b/src/database/third_party/closure-library/closure/goog/labs/events/nondisposableeventtarget_test.js
    deleted file mode 100644
    index dee067b2b48..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/events/nondisposableeventtarget_test.js
    +++ /dev/null
    @@ -1,72 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.labs.events.NonDisposableEventTargetTest');
    -goog.setTestOnly('goog.labs.events.NonDisposableEventTargetTest');
    -
    -goog.require('goog.events.Listenable');
    -goog.require('goog.events.eventTargetTester');
    -goog.require('goog.events.eventTargetTester.KeyType');
    -goog.require('goog.events.eventTargetTester.UnlistenReturnType');
    -goog.require('goog.labs.events.NonDisposableEventTarget');
    -goog.require('goog.testing.jsunit');
    -
    -function setUp() {
    -  var newListenableFn = function() {
    -    return new goog.labs.events.NonDisposableEventTarget();
    -  };
    -  var listenFn = function(src, type, listener, opt_capt, opt_handler) {
    -    return src.listen(type, listener, opt_capt, opt_handler);
    -  };
    -  var unlistenFn = function(src, type, listener, opt_capt, opt_handler) {
    -    return src.unlisten(type, listener, opt_capt, opt_handler);
    -  };
    -  var unlistenByKeyFn = function(src, key) {
    -    return src.unlistenByKey(key);
    -  };
    -  var listenOnceFn = function(src, type, listener, opt_capt, opt_handler) {
    -    return src.listenOnce(type, listener, opt_capt, opt_handler);
    -  };
    -  var dispatchEventFn = function(src, e) {
    -    return src.dispatchEvent(e);
    -  };
    -  var removeAllFn = function(src, opt_type, opt_capture) {
    -    return src.removeAllListeners(opt_type, opt_capture);
    -  };
    -  var getListenersFn = function(src, type, capture) {
    -    return src.getListeners(type, capture);
    -  };
    -  var getListenerFn = function(src, type, listener, capture, opt_handler) {
    -    return src.getListener(type, listener, capture, opt_handler);
    -  };
    -  var hasListenerFn = function(src, opt_type, opt_capture) {
    -    return src.hasListener(opt_type, opt_capture);
    -  };
    -
    -  goog.events.eventTargetTester.setUp(
    -      newListenableFn, listenFn, unlistenFn, unlistenByKeyFn,
    -      listenOnceFn, dispatchEventFn,
    -      removeAllFn, getListenersFn, getListenerFn, hasListenerFn,
    -      goog.events.eventTargetTester.KeyType.NUMBER,
    -      goog.events.eventTargetTester.UnlistenReturnType.BOOLEAN, false);
    -}
    -
    -function tearDown() {
    -  goog.events.eventTargetTester.tearDown();
    -}
    -
    -function testRuntimeTypeIsCorrect() {
    -  var target = new goog.labs.events.NonDisposableEventTarget();
    -  assertTrue(goog.events.Listenable.isImplementedBy(target));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/events/nondisposableeventtarget_via_googevents_test.html b/src/database/third_party/closure-library/closure/goog/labs/events/nondisposableeventtarget_via_googevents_test.html
    deleted file mode 100644
    index 2483d41129e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/events/nondisposableeventtarget_via_googevents_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.labs.events.EventTarget
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -  goog.require('goog.labs.events.NonDisposableEventTargetGoogEventsTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/events/nondisposableeventtarget_via_googevents_test.js b/src/database/third_party/closure-library/closure/goog/labs/events/nondisposableeventtarget_via_googevents_test.js
    deleted file mode 100644
    index a0638197763..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/events/nondisposableeventtarget_via_googevents_test.js
    +++ /dev/null
    @@ -1,78 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.labs.events.NonDisposableEventTargetGoogEventsTest');
    -goog.setTestOnly('goog.labs.events.NonDisposableEventTargetGoogEventsTest');
    -
    -goog.require('goog.events');
    -goog.require('goog.events.eventTargetTester');
    -goog.require('goog.events.eventTargetTester.KeyType');
    -goog.require('goog.events.eventTargetTester.UnlistenReturnType');
    -goog.require('goog.labs.events.NonDisposableEventTarget');
    -goog.require('goog.testing');
    -goog.require('goog.testing.jsunit');
    -
    -function setUp() {
    -  var newListenableFn = function() {
    -    return new goog.labs.events.NonDisposableEventTarget();
    -  };
    -  var unlistenByKeyFn = function(src, key) {
    -    return goog.events.unlistenByKey(key);
    -  };
    -  goog.events.eventTargetTester.setUp(
    -      newListenableFn, goog.events.listen, goog.events.unlisten,
    -      unlistenByKeyFn,
    -      goog.events.listenOnce, goog.events.dispatchEvent,
    -      goog.events.removeAll, goog.events.getListeners,
    -      goog.events.getListener, goog.events.hasListener,
    -      goog.events.eventTargetTester.KeyType.NUMBER,
    -      goog.events.eventTargetTester.UnlistenReturnType.BOOLEAN, true);
    -}
    -
    -function tearDown() {
    -  goog.events.eventTargetTester.tearDown();
    -}
    -
    -function testUnlistenProperCleanup() {
    -  goog.events.listen(eventTargets[0], EventType.A, listeners[0]);
    -  goog.events.unlisten(eventTargets[0], EventType.A, listeners[0]);
    -
    -  goog.events.listen(eventTargets[0], EventType.A, listeners[0]);
    -  eventTargets[0].unlisten(EventType.A, listeners[0]);
    -}
    -
    -function testUnlistenByKeyProperCleanup() {
    -  var keyNum = goog.events.listen(eventTargets[0], EventType.A, listeners[0]);
    -  goog.events.unlistenByKey(keyNum);
    -}
    -
    -function testListenOnceProperCleanup() {
    -  goog.events.listenOnce(eventTargets[0], EventType.A, listeners[0]);
    -  eventTargets[0].dispatchEvent(EventType.A);
    -}
    -
    -function testListenWithObject() {
    -  var obj = {};
    -  obj.handleEvent = goog.testing.recordFunction();
    -  goog.events.listen(eventTargets[0], EventType.A, obj);
    -  eventTargets[0].dispatchEvent(EventType.A);
    -  assertEquals(1, obj.handleEvent.getCallCount());
    -}
    -
    -function testListenWithObjectHandleEventReturningFalse() {
    -  var obj = {};
    -  obj.handleEvent = function() { return false; };
    -  goog.events.listen(eventTargets[0], EventType.A, obj);
    -  assertFalse(eventTargets[0].dispatchEvent(EventType.A));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/events/touch.js b/src/database/third_party/closure-library/closure/goog/labs/events/touch.js
    deleted file mode 100644
    index f03a0ade430..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/events/touch.js
    +++ /dev/null
    @@ -1,82 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Utilities to abstract mouse and touch events.
    - */
    -
    -
    -goog.provide('goog.labs.events.touch');
    -goog.provide('goog.labs.events.touch.TouchData');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.events.EventType');
    -goog.require('goog.string');
    -
    -
    -/**
    - * Description the geometry and target of an event.
    - *
    - * @typedef {{
    - *   clientX: number,
    - *   clientY: number,
    - *   screenX: number,
    - *   screenY: number,
    - *   target: EventTarget
    - * }}
    - */
    -goog.labs.events.touch.TouchData;
    -
    -
    -/**
    - * Takes a mouse or touch event and returns the relevent geometry and target
    - * data.
    - * @param {!Event} e A mouse or touch event.
    - * @return {!goog.labs.events.touch.TouchData}
    - */
    -goog.labs.events.touch.getTouchData = function(e) {
    -
    -  var source = e;
    -  goog.asserts.assert(
    -      goog.string.startsWith(e.type, 'touch') ||
    -      goog.string.startsWith(e.type, 'mouse'),
    -      'Event must be mouse or touch event.');
    -
    -  if (goog.string.startsWith(e.type, 'touch')) {
    -    goog.asserts.assert(
    -        goog.array.contains([
    -          goog.events.EventType.TOUCHCANCEL,
    -          goog.events.EventType.TOUCHEND,
    -          goog.events.EventType.TOUCHMOVE,
    -          goog.events.EventType.TOUCHSTART
    -        ], e.type),
    -        'Touch event not of valid type.');
    -
    -    // If the event is end or cancel, take the first changed touch,
    -    // otherwise the first target touch.
    -    source = (e.type == goog.events.EventType.TOUCHEND ||
    -              e.type == goog.events.EventType.TOUCHCANCEL) ?
    -             e.changedTouches[0] : e.targetTouches[0];
    -  }
    -
    -  return {
    -    clientX: source['clientX'],
    -    clientY: source['clientY'],
    -    screenX: source['screenX'],
    -    screenY: source['screenY'],
    -    target: source['target']
    -  };
    -};
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/events/touch_test.html b/src/database/third_party/closure-library/closure/goog/labs/events/touch_test.html
    deleted file mode 100644
    index f1ad69dda8d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/events/touch_test.html
    +++ /dev/null
    @@ -1,19 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.labs.events.touch</title>
    -<script src="../../base.js"></script>
    -<script>
    -goog.require('goog.labs.events.touchTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/events/touch_test.js b/src/database/third_party/closure-library/closure/goog/labs/events/touch_test.js
    deleted file mode 100644
    index 77d1f52a682..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/events/touch_test.js
    +++ /dev/null
    @@ -1,96 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.labs.events.touch.
    - */
    -
    -
    -goog.provide('goog.labs.events.touchTest');
    -
    -goog.require('goog.labs.events.touch');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.labs.events.touchTest');
    -
    -function testMouseEvent() {
    -  var fakeTarget = {};
    -
    -  var fakeMouseMove = {
    -    'clientX': 1,
    -    'clientY': 2,
    -    'screenX': 3,
    -    'screenY': 4,
    -    'target': fakeTarget,
    -    'type': 'mousemove'
    -  };
    -
    -  var data = goog.labs.events.touch.getTouchData(fakeMouseMove);
    -  assertEquals(1, data.clientX);
    -  assertEquals(2, data.clientY);
    -  assertEquals(3, data.screenX);
    -  assertEquals(4, data.screenY);
    -  assertEquals(fakeTarget, data.target);
    -}
    -
    -function testTouchEvent() {
    -  var fakeTarget = {};
    -
    -  var fakeTouch = {
    -    'clientX': 1,
    -    'clientY': 2,
    -    'screenX': 3,
    -    'screenY': 4,
    -    'target': fakeTarget
    -  };
    -
    -  var fakeTouchStart = {
    -    'targetTouches': [fakeTouch],
    -    'target': fakeTarget,
    -    'type': 'touchstart'
    -  };
    -
    -  var data = goog.labs.events.touch.getTouchData(fakeTouchStart);
    -  assertEquals(1, data.clientX);
    -  assertEquals(2, data.clientY);
    -  assertEquals(3, data.screenX);
    -  assertEquals(4, data.screenY);
    -  assertEquals(fakeTarget, data.target);
    -}
    -
    -function testTouchChangeEvent() {
    -  var fakeTarget = {};
    -
    -  var fakeTouch = {
    -    'clientX': 1,
    -    'clientY': 2,
    -    'screenX': 3,
    -    'screenY': 4,
    -    'target': fakeTarget
    -  };
    -
    -  var fakeTouchStart = {
    -    'changedTouches': [fakeTouch],
    -    'target': fakeTarget,
    -    'type': 'touchend'
    -  };
    -
    -  var data = goog.labs.events.touch.getTouchData(fakeTouchStart);
    -  assertEquals(1, data.clientX);
    -  assertEquals(2, data.clientY);
    -  assertEquals(3, data.screenX);
    -  assertEquals(4, data.screenY);
    -  assertEquals(fakeTarget, data.target);
    -}
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/format/csv.js b/src/database/third_party/closure-library/closure/goog/labs/format/csv.js
    deleted file mode 100644
    index 36fe25e5863..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/format/csv.js
    +++ /dev/null
    @@ -1,415 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides a parser that turns a string of well-formed CSV data
    - * into an array of objects or an array of arrays. All values are returned as
    - * strings; the user has to convert data into numbers or Dates as required.
    - * Empty fields (adjacent commas) are returned as empty strings.
    - *
    - * This parser uses http://tools.ietf.org/html/rfc4180 as the definition of CSV.
    - *
    - * @author nnaze@google.com (Nathan Naze) Ported to Closure
    - */
    -goog.provide('goog.labs.format.csv');
    -goog.provide('goog.labs.format.csv.ParseError');
    -goog.provide('goog.labs.format.csv.Token');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.debug.Error');
    -goog.require('goog.object');
    -goog.require('goog.string');
    -goog.require('goog.string.newlines');
    -
    -
    -/**
    - * @define {boolean} Enable verbose debugging. This is a flag so it can be
    - * enabled in production if necessary post-compilation.  Otherwise, debug
    - * information will be stripped to minimize final code size.
    - */
    -goog.labs.format.csv.ENABLE_VERBOSE_DEBUGGING = goog.DEBUG;
    -
    -
    -
    -/**
    - * Error thrown when parsing fails.
    - *
    - * @param {string} text The CSV source text being parsed.
    - * @param {number} index The index, in the string, of the position of the
    - *      error.
    - * @param {string=} opt_message A description of the violated parse expectation.
    - * @constructor
    - * @extends {goog.debug.Error}
    - * @final
    - */
    -goog.labs.format.csv.ParseError = function(text, index, opt_message) {
    -
    -  var message;
    -
    -  /**
    -   * @type {?{line: number, column: number}} The line and column of the parse
    -   *     error.
    -   */
    -  this.position = null;
    -
    -  if (goog.labs.format.csv.ENABLE_VERBOSE_DEBUGGING) {
    -    message = opt_message || '';
    -
    -    var info = goog.labs.format.csv.ParseError.findLineInfo_(text, index);
    -    if (info) {
    -      var lineNumber = info.lineIndex + 1;
    -      var columnNumber = index - info.line.startLineIndex + 1;
    -
    -      this.position = {
    -        line: lineNumber,
    -        column: columnNumber
    -      };
    -
    -      message += goog.string.subs(' at line %s column %s',
    -                                  lineNumber, columnNumber);
    -      message += '\n' + goog.labs.format.csv.ParseError.getLineDebugString_(
    -          info.line.getContent(), columnNumber);
    -    }
    -  }
    -
    -  goog.labs.format.csv.ParseError.base(this, 'constructor', message);
    -};
    -goog.inherits(goog.labs.format.csv.ParseError, goog.debug.Error);
    -
    -
    -/** @inheritDoc */
    -goog.labs.format.csv.ParseError.prototype.name = 'ParseError';
    -
    -
    -/**
    - * Calculate the line and column for an index in a string.
    - * TODO(nnaze): Consider moving to goog.string.newlines.
    - * @param {string} str A string.
    - * @param {number} index An index into the string.
    - * @return {?{line: !goog.string.newlines.Line, lineIndex: number}} The line
    - *     and index of the line.
    - * @private
    - */
    -goog.labs.format.csv.ParseError.findLineInfo_ = function(str, index) {
    -  var lines = goog.string.newlines.getLines(str);
    -  var lineIndex = goog.array.findIndex(lines, function(line) {
    -    return line.startLineIndex <= index && line.endLineIndex > index;
    -  });
    -
    -  if (goog.isNumber(lineIndex)) {
    -    var line = lines[lineIndex];
    -    return {
    -      line: line,
    -      lineIndex: lineIndex
    -    };
    -  }
    -
    -  return null;
    -};
    -
    -
    -/**
    - * Get a debug string of a line and a pointing caret beneath it.
    - * @param {string} str The string.
    - * @param {number} column The column to point at (1-indexed).
    - * @return {string} The debug line.
    - * @private
    - */
    -goog.labs.format.csv.ParseError.getLineDebugString_ = function(str, column) {
    -  var returnString = str + '\n';
    -  returnString += goog.string.repeat(' ', column - 1) + '^';
    -  return returnString;
    -};
    -
    -
    -/**
    - * A token -- a single-character string or a sentinel.
    - * @typedef {string|!goog.labs.format.csv.Sentinels_}
    - */
    -goog.labs.format.csv.Token;
    -
    -
    -/**
    - * Parses a CSV string to create a two-dimensional array.
    - *
    - * This function does not process header lines, etc -- such transformations can
    - * be made on the resulting array.
    - *
    - * @param {string} text The entire CSV text to be parsed.
    - * @param {boolean=} opt_ignoreErrors Whether to ignore parsing errors and
    - *      instead try to recover and keep going.
    - * @return {!Array<!Array<string>>} The parsed CSV.
    - */
    -goog.labs.format.csv.parse = function(text, opt_ignoreErrors) {
    -
    -  var index = 0;  // current char offset being considered
    -
    -
    -  var EOF = goog.labs.format.csv.Sentinels_.EOF;
    -  var EOR = goog.labs.format.csv.Sentinels_.EOR;
    -  var NEWLINE = goog.labs.format.csv.Sentinels_.NEWLINE;   // \r?\n
    -  var EMPTY = goog.labs.format.csv.Sentinels_.EMPTY;
    -
    -  var pushBackToken = null;   // A single-token pushback.
    -  var sawComma = false; // Special case for terminal comma.
    -
    -  /**
    -   * Push a single token into the push-back variable.
    -   * @param {goog.labs.format.csv.Token} t Single token.
    -   */
    -  function pushBack(t) {
    -    goog.labs.format.csv.assertToken_(t);
    -    goog.asserts.assert(goog.isNull(pushBackToken));
    -    pushBackToken = t;
    -  }
    -
    -  /**
    -   * @return {goog.labs.format.csv.Token} The next token in the stream.
    -   */
    -  function nextToken() {
    -
    -    // Give the push back token if present.
    -    if (pushBackToken != null) {
    -      var c = pushBackToken;
    -      pushBackToken = null;
    -      return c;
    -    }
    -
    -    // We're done. EOF.
    -    if (index >= text.length) {
    -      return EOF;
    -    }
    -
    -    // Give the next charater.
    -    var chr = text.charAt(index++);
    -    goog.labs.format.csv.assertToken_(chr);
    -
    -    // Check if this is a newline.  If so, give the new line sentinel.
    -    var isNewline = false;
    -    if (chr == '\n') {
    -      isNewline = true;
    -    } else if (chr == '\r') {
    -
    -      // This is a '\r\n' newline. Treat as single token, go
    -      // forward two indicies.
    -      if (index < text.length && text.charAt(index) == '\n') {
    -        index++;
    -      }
    -
    -      isNewline = true;
    -    }
    -
    -    if (isNewline) {
    -      return NEWLINE;
    -    }
    -
    -    return chr;
    -  }
    -
    -  /**
    -   * Read a quoted field from input.
    -   * @return {string} The field, as a string.
    -   */
    -  function readQuotedField() {
    -    // We've already consumed the first quote by the time we get here.
    -    var start = index;
    -    var end = null;
    -
    -    for (var token = nextToken(); token != EOF; token = nextToken()) {
    -      if (token == '"') {
    -        end = index - 1;
    -        token = nextToken();
    -
    -        // Two double quotes in a row.  Keep scanning.
    -        if (token == '"') {
    -          end = null;
    -          continue;
    -        }
    -
    -        // End of field.  Break out.
    -        if (token == ',' || token == EOF || token == NEWLINE) {
    -          if (token == NEWLINE) {
    -            pushBack(token);
    -          }
    -          break;
    -        }
    -
    -        if (!opt_ignoreErrors) {
    -          // Ignoring errors here means keep going in current field after
    -          // closing quote. E.g. "ab"c,d splits into abc,d
    -          throw new goog.labs.format.csv.ParseError(
    -              text, index - 1,
    -              'Unexpected character "' + token + '" after quote mark');
    -        } else {
    -          // Fall back to reading the rest of this field as unquoted.
    -          // Note: the rest is guaranteed not start with ", as that case is
    -          // eliminated above.
    -          var prefix = '"' + text.substring(start, index);
    -          var suffix = readField();
    -          if (suffix == EOR) {
    -            pushBack(NEWLINE);
    -            return prefix;
    -          } else {
    -            return prefix + suffix;
    -          }
    -        }
    -      }
    -    }
    -
    -    if (goog.isNull(end)) {
    -      if (!opt_ignoreErrors) {
    -        throw new goog.labs.format.csv.ParseError(
    -            text, text.length - 1,
    -            'Unexpected end of text after open quote');
    -      } else {
    -        end = text.length;
    -      }
    -    }
    -
    -    // Take substring, combine double quotes.
    -    return text.substring(start, end).replace(/""/g, '"');
    -  }
    -
    -  /**
    -   * Read a field from input.
    -   * @return {string|!goog.labs.format.csv.Sentinels_} The field, as a string,
    -   *     or a sentinel (if applicable).
    -   */
    -  function readField() {
    -    var start = index;
    -    var didSeeComma = sawComma;
    -    sawComma = false;
    -    var token = nextToken();
    -    if (token == EMPTY) {
    -      return EOR;
    -    }
    -    if (token == EOF || token == NEWLINE) {
    -      if (didSeeComma) {
    -        pushBack(EMPTY);
    -        return '';
    -      }
    -      return EOR;
    -    }
    -
    -    // This is the beginning of a quoted field.
    -    if (token == '"') {
    -      return readQuotedField();
    -    }
    -
    -    while (true) {
    -
    -      // This is the end of line or file.
    -      if (token == EOF || token == NEWLINE) {
    -        pushBack(token);
    -        break;
    -      }
    -
    -      // This is the end of record.
    -      if (token == ',') {
    -        sawComma = true;
    -        break;
    -      }
    -
    -      if (token == '"' && !opt_ignoreErrors) {
    -        throw new goog.labs.format.csv.ParseError(text, index - 1,
    -                                                  'Unexpected quote mark');
    -      }
    -
    -      token = nextToken();
    -    }
    -
    -
    -    var returnString = (token == EOF) ?
    -        text.substring(start) :  // Return to end of file.
    -        text.substring(start, index - 1);
    -
    -    return returnString.replace(/[\r\n]+/g, ''); // Squash any CRLFs.
    -  }
    -
    -  /**
    -   * Read the next record.
    -   * @return {!Array<string>|!goog.labs.format.csv.Sentinels_} A single record
    -   *     with multiple fields.
    -   */
    -  function readRecord() {
    -    if (index >= text.length) {
    -      return EOF;
    -    }
    -    var record = [];
    -    for (var field = readField(); field != EOR; field = readField()) {
    -      record.push(field);
    -    }
    -    return record;
    -  }
    -
    -  // Read all records and return.
    -  var records = [];
    -  for (var record = readRecord(); record != EOF; record = readRecord()) {
    -    records.push(record);
    -  }
    -  return records;
    -};
    -
    -
    -/**
    - * Sentinel tracking objects.
    - * @enum {!Object}
    - * @private
    - */
    -goog.labs.format.csv.Sentinels_ = {
    -  /** Empty field */
    -  EMPTY: {},
    -
    -  /** End of file */
    -  EOF: {},
    -
    -  /** End of record */
    -  EOR: {},
    -
    -  /** Newline. \r?\n */
    -  NEWLINE: {}
    -};
    -
    -
    -/**
    - * @param {string} str A string.
    - * @return {boolean} Whether the string is a single character.
    - * @private
    - */
    -goog.labs.format.csv.isCharacterString_ = function(str) {
    -  return goog.isString(str) && str.length == 1;
    -};
    -
    -
    -/**
    - * Assert the parameter is a token.
    - * @param {*} o What should be a token.
    - * @throws {goog.asserts.AssertionError} If {@ code} is not a token.
    - * @private
    - */
    -goog.labs.format.csv.assertToken_ = function(o) {
    -  if (goog.isString(o)) {
    -    goog.asserts.assertString(o);
    -    goog.asserts.assert(goog.labs.format.csv.isCharacterString_(o),
    -        'Should be a string of length 1 or a sentinel.');
    -  } else {
    -    goog.asserts.assert(
    -        goog.object.containsValue(goog.labs.format.csv.Sentinels_, o),
    -        'Should be a string of length 1 or a sentinel.');
    -  }
    -};
    -
    -
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/format/csv_test.html b/src/database/third_party/closure-library/closure/goog/labs/format/csv_test.html
    deleted file mode 100644
    index 7e342b36973..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/format/csv_test.html
    +++ /dev/null
    @@ -1,20 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -  <head>
    -    <title>csv.js unit tests</title>
    -    <script type="text/javascript"
    -        src="../../base.js">
    -    </script>
    -    <script>
    -      goog.require('goog.labs.format.csvTest');
    -    </script>
    -  </head>
    -  <body>
    -  </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/format/csv_test.js b/src/database/third_party/closure-library/closure/goog/labs/format/csv_test.js
    deleted file mode 100644
    index 79eeaa1588e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/format/csv_test.js
    +++ /dev/null
    @@ -1,201 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.labs.format.csvTest');
    -
    -goog.require('goog.labs.format.csv');
    -goog.require('goog.labs.format.csv.ParseError');
    -goog.require('goog.object');
    -goog.require('goog.testing.asserts');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.labs.format.csvTest');
    -
    -
    -function testGoldenPath() {
    -  assertObjectEquals(
    -      [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']],
    -      goog.labs.format.csv.parse('a,b,c\nd,e,f\ng,h,i\n'));
    -  assertObjectEquals(
    -      [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']],
    -      goog.labs.format.csv.parse('a,b,c\r\nd,e,f\r\ng,h,i\r\n'));
    -}
    -
    -function testNoCrlfAtEnd() {
    -  assertObjectEquals(
    -      [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']],
    -      goog.labs.format.csv.parse('a,b,c\nd,e,f\ng,h,i'));
    -}
    -
    -function testQuotes() {
    -  assertObjectEquals(
    -      [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']],
    -      goog.labs.format.csv.parse('a,"b",c\n"d","e","f"\ng,h,"i"'));
    -  assertObjectEquals(
    -      [['a', 'b, as in boy', 'c'], ['d', 'e', 'f']],
    -      goog.labs.format.csv.parse('a,"b, as in boy",c\n"d","e","f"\n'));
    -}
    -
    -function testEmbeddedCrlfs() {
    -  assertObjectEquals(
    -      [['a', 'b\nball', 'c'], ['d\nd', 'e', 'f'], ['g', 'h', 'i']],
    -      goog.labs.format.csv.parse('a,"b\nball",c\n"d\nd","e","f"\ng,h,"i"\n'));
    -}
    -
    -function testEmbeddedQuotes() {
    -  assertObjectEquals(
    -      [['a', '"b"', 'Jonathan "Smokey" Feinberg'], ['d', 'e', 'f']],
    -      goog.labs.format.csv.parse(
    -          'a,"""b""","Jonathan ""Smokey"" Feinberg"\nd,e,f\r\n'));
    -}
    -
    -function testUnclosedQuote() {
    -  var e = assertThrows(function() {
    -    goog.labs.format.csv.parse('a,"b,c\nd,e,f');
    -  });
    -
    -  assertTrue(e instanceof goog.labs.format.csv.ParseError);
    -  assertEquals(2, e.position.line);
    -  assertEquals(5, e.position.column);
    -  assertEquals(
    -      'Unexpected end of text after open quote at line 2 column 5\n' +
    -      'd,e,f\n' +
    -      '    ^',
    -      e.message);
    -}
    -
    -function testQuotesInUnquotedField() {
    -  var e = assertThrows(function() {
    -    goog.labs.format.csv.parse('a,b "and" b,c\nd,e,f');
    -  });
    -
    -  assertTrue(e instanceof goog.labs.format.csv.ParseError);
    -
    -  assertEquals(1, e.position.line);
    -  assertEquals(5, e.position.column);
    -
    -  assertEquals(
    -      'Unexpected quote mark at line 1 column 5\n' +
    -      'a,b "and" b,c\n' +
    -      '    ^',
    -      e.message);
    -}
    -
    -function testGarbageOutsideQuotes() {
    -  var e = assertThrows(function() {
    -    goog.labs.format.csv.parse('a,"b",c\nd,"e"oops,f');
    -  });
    -
    -  assertTrue(e instanceof goog.labs.format.csv.ParseError);
    -  assertEquals(2, e.position.line);
    -  assertEquals(6, e.position.column);
    -  assertEquals(
    -      'Unexpected character "o" after quote mark at line 2 column 6\n' +
    -      'd,"e"oops,f\n' +
    -      '     ^',
    -      e.message);
    -}
    -
    -function testEmptyRecords() {
    -  assertObjectEquals(
    -      [['a', '', 'c'], ['d', 'e', ''], ['', '', '']],
    -      goog.labs.format.csv.parse('a,,c\r\nd,e,\n,,'));
    -}
    -
    -function testIgnoringErrors() {
    -  // The results of these tests are not defined by the RFC. They
    -  // generally strive to be "reasonable" while keeping the code simple.
    -
    -  // Quotes inside field
    -  assertObjectEquals(
    -      [['Hello "World"!', 'b'], ['c', 'd']], goog.labs.format.csv.parse(
    -          'Hello "World"!,b\nc,d', true));
    -
    -  // Missing closing quote
    -  assertObjectEquals(
    -      [['Hello', 'World!']], goog.labs.format.csv.parse(
    -          'Hello,"World!', true));
    -
    -  // Broken use of quotes in quoted field
    -  assertObjectEquals(
    -      [['a', '"Hello"World!"']], goog.labs.format.csv.parse(
    -          'a,"Hello"World!"', true));
    -
    -  // All of the above. A real mess.
    -  assertObjectEquals(
    -      [['This" is', '"very\n\tvery"broken"', ' indeed!']],
    -      goog.labs.format.csv.parse(
    -          'This" is,"very\n\tvery"broken"," indeed!', true));
    -}
    -
    -function testIgnoringErrorsTrailingTabs() {
    -  assertObjectEquals(
    -      [['"a\tb"\t'], ['c,d']], goog.labs.format.csv.parse(
    -          '"a\tb"\t\n"c,d"', true));
    -}
    -
    -function testFindLineInfo() {
    -  var testString = 'abc\ndef\rghi';
    -  var info = goog.labs.format.csv.ParseError.findLineInfo_(testString, 4);
    -
    -  assertEquals(4, info.line.startLineIndex);
    -  assertEquals(7, info.line.endContentIndex);
    -  assertEquals(8, info.line.endLineIndex);
    -
    -  assertEquals(1, info.lineIndex);
    -}
    -
    -function testGetLineDebugString() {
    -  var str = 'abcdefghijklmnop';
    -  var index = str.indexOf('j');
    -  var column = index + 1;
    -  assertEquals(
    -      goog.labs.format.csv.ParseError.getLineDebugString_(str, column),
    -      'abcdefghijklmnop\n' +
    -      '         ^');
    -
    -}
    -
    -function testIsCharacterString() {
    -  assertTrue(goog.labs.format.csv.isCharacterString_('a'));
    -  assertTrue(goog.labs.format.csv.isCharacterString_('\n'));
    -  assertTrue(goog.labs.format.csv.isCharacterString_(' '));
    -
    -  assertFalse(goog.labs.format.csv.isCharacterString_(null));
    -  assertFalse(goog.labs.format.csv.isCharacterString_('  '));
    -  assertFalse(goog.labs.format.csv.isCharacterString_(''));
    -  assertFalse(goog.labs.format.csv.isCharacterString_('aa'));
    -}
    -
    -
    -function testAssertToken() {
    -  goog.labs.format.csv.assertToken_('a');
    -
    -  goog.object.forEach(goog.labs.format.csv.SENTINELS_,
    -      function(value) {
    -        goog.labs.format.csv.assertToken_(value);
    -      });
    -
    -  assertThrows(function() {
    -    goog.labs.format.csv.assertToken_('aa');
    -  });
    -
    -  assertThrows(function() {
    -    goog.labs.format.csv.assertToken_('');
    -  });
    -
    -  assertThrows(function() {
    -    goog.labs.format.csv.assertToken_({});
    -  });
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/html/attribute_rewriter.js b/src/database/third_party/closure-library/closure/goog/labs/html/attribute_rewriter.js
    deleted file mode 100644
    index dec1cc2c42e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/html/attribute_rewriter.js
    +++ /dev/null
    @@ -1,74 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -goog.provide('goog.labs.html.AttributeRewriter');
    -goog.provide('goog.labs.html.AttributeValue');
    -goog.provide('goog.labs.html.attributeRewriterPresubmitWorkaround');
    -
    -
    -/**
    - * The type of an attribute value.
    - * <p>
    - * Many HTML attributes contain structured data like URLs, CSS, or even entire
    - * HTML documents, so the type is a union of several variants.
    - *
    - * @typedef {(string |
    - *            goog.html.SafeHtml | goog.html.SafeStyle | goog.html.SafeUrl)}
    - */
    -goog.labs.html.AttributeValue;
    -
    -
    -/**
    - * A function that takes an attribute value, and returns a safe value.
    - * <p>
    - * Since rewriters can be chained, a rewriter must be able to accept the output
    - * of another rewriter, instead of just a string though a rewriter that coerces
    - * its input to a string before checking its safety will fail safe.
    - * <p>
    - * The meaning of the result is:
    - * <table>
    - *   <tr><td>{@code null}</td>
    - *       <td>Unsafe.  The attribute should not be output.</tr>
    - *   <tr><td>a string</td>
    - *       <td>The plain text (not HTML-entity encoded) of a safe attribute
    - *           value.</td>
    - *   <tr><td>a {@link goog.html.SafeHtml}</td>
    - *       <td>A fragment that is safe to be included as embedded HTML as in
    - *           {@code <iframe srchtml="...">}</td></tr>
    - *   <tr><td>a {@link goog.html.SafeUrl}</td>
    - *       <td>A URL that does not need to be further checked against the URL
    - *           white-list.</td></tr>
    - *   <tr><td>a {@link goog.html.SafeStyle}</td>
    - *       <td>A safe value for a <code>style="..."</code> attribute.</td></tr>
    - * </table>
    - * <p>
    - * Implementations are responsible for making sure that "safe" complies with
    - * the contract established by the safe string types in {@link goog.html}.
    - * </p>
    - *
    - * @typedef {function(goog.labs.html.AttributeValue) :
    - *           goog.labs.html.AttributeValue}
    - */
    -goog.labs.html.AttributeRewriter;
    -
    -
    -/**
    - * g4 presubmit complains about requires of this file because its clients
    - * don't use any symbols from it outside JSCompiler comment annotations.
    - * genjsdeps.sh doesn't generate the right dependency graph unless this
    - * file is required.
    - * Clients can mention this noop.
    - */
    -goog.labs.html.attributeRewriterPresubmitWorkaround = function() {};
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/html/sanitizer.js b/src/database/third_party/closure-library/closure/goog/labs/html/sanitizer.js
    deleted file mode 100644
    index 10155c1fcc8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/html/sanitizer.js
    +++ /dev/null
    @@ -1,392 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview
    - * An HTML sanitizer that takes untrusted HTML snippets and produces
    - * safe HTML by filtering/rewriting tags and attributes that contain
    - * high-privilege instructions.
    - */
    -
    -
    -goog.provide('goog.labs.html.Sanitizer');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.html.SafeUrl');
    -goog.require('goog.labs.html.attributeRewriterPresubmitWorkaround');
    -goog.require('goog.labs.html.scrubber');
    -goog.require('goog.object');
    -goog.require('goog.string');
    -
    -
    -
    -/**
    - * A sanitizer that converts untrusted, messy HTML into more regular HTML
    - * that cannot abuse high-authority constructs like the ability to execute
    - * arbitrary JavaScript.
    - * @constructor
    - */
    -goog.labs.html.Sanitizer = function() {
    -  /**
    -   * Maps the lower-case names of allowed elements to attribute white-lists.
    -   * An attribute white-list maps lower-case attribute names to functions
    -   * from values to values or undefined to disallow.
    -   *
    -   * The special element name {@code "*"} contains a white-list of attributes
    -   * allowed on any tag, which is useful for attributes like {@code title} and
    -   * {@code id} which are widely available with element-agnostic meanings.
    -   * It should not be used for attributes like {@code type} whose meaning
    -   * differs based on the element on which it appears:
    -   * e.g. {@code <input type=text>} vs {@code <style type=text/css>}.
    -   *
    -   * @type {!Object<string, !Object<string, goog.labs.html.AttributeRewriter>>}
    -   * @private
    -   */
    -  this.whitelist_ = goog.labs.html.Sanitizer.createBlankObject_();
    -  this.whitelist_['*'] = goog.labs.html.Sanitizer.createBlankObject_();
    -
    -  // To use the sanitizer, we build inputs for the scrubber.
    -  // These inputs are invalidated by changes to the policy, so we (re)build them
    -  // lazily.
    -
    -  /**
    -   * Maps element names to {@code true} so the scrubber does not have to do
    -   * own property checks for every tag filtered.
    -   *
    -   * Built lazily and invalidated when the white-list is modified.
    -   *
    -   * @type {Object<string, boolean>}
    -   * @private
    -   */
    -  this.allowedElementSet_ = null;
    -};
    -
    -
    -// TODO(user): Should the return type be goog.html.SafeHtml?
    -// If we receive a safe HTML string as input, should we simply rebalance
    -// tags?
    -/**
    - * Yields a string of safe HTML that contains all and only the safe
    - * text-nodes and elements in the input.
    - *
    - * <p>
    - * For the purposes of this function, "safe" is defined thus:
    - * <ul>
    - *   <li>Contains only elements explicitly allowed via {@code this.allow*}.
    - *   <li>Contains only attributes explicitly allowed via {@code this.allow*}
    - *       and having had all relevant transformations applied.
    - *   <li>Contains an end tag for all and only non-void open tags.
    - *   <li>Tags nest per XHTML rules.
    - *   <li>Tags do not nest beyond a finite but fairly large level.
    - * </ul>
    - *
    - * @param {!string} unsafeHtml A string of HTML which need not originate with
    - *    a trusted source.
    - * @return {!string} A string of HTML that contains only tags and attributes
    - *    explicitly allowed by this sanitizer, and with end tags for all and only
    - *    non-void elements.
    - */
    -goog.labs.html.Sanitizer.prototype.sanitize = function(unsafeHtml) {
    -  var unsafeHtmlString = '' + unsafeHtml;
    -
    -  /**
    -   * @type {!Object<string, !Object<string, goog.labs.html.AttributeRewriter>>}
    -   */
    -  var whitelist = this.whitelist_;
    -  if (!this.allowedElementSet_) {
    -    this.allowedElementSet_ = goog.object.createSet(
    -        // This can lead to '*' in the allowed element set, but the scrubber
    -        // will not parse "<*" as a tag beginning.
    -        goog.object.getKeys(whitelist));
    -  }
    -
    -  return goog.labs.html.scrubber.scrub(
    -      this.allowedElementSet_, whitelist, unsafeHtmlString);
    -};
    -
    -
    -/**
    - * Adds the element names to the white-list of elements that are allowed
    - * in the safe HTML output.
    - * <p>
    - * Allowing elements does not, by itself, allow any attributes on
    - * those elements.
    - *
    - * @param {...!string} var_args element names that should be allowed in the
    - *     safe HTML output.
    - * @return {!goog.labs.html.Sanitizer} {@code this}.
    - */
    -goog.labs.html.Sanitizer.prototype.allowElements = function(var_args) {
    -  this.allowedElementSet_ = null;  // Invalidate.
    -  var whitelist = this.whitelist_;
    -  for (var i = 0; i < arguments.length; ++i) {
    -    var elementName = arguments[i].toLowerCase();
    -
    -    goog.asserts.assert(
    -        goog.labs.html.Sanitizer.isValidHtmlName_(elementName), elementName);
    -
    -    if (!Object.prototype.hasOwnProperty.call(whitelist, elementName)) {
    -      whitelist[elementName] = goog.labs.html.Sanitizer.createBlankObject_();
    -    }
    -  }
    -  return this;
    -};
    -
    -
    -/**
    - * Allows in the sanitized output
    - * <tt>&lt;<i>element</i> <i>attr</i>="..."&gt;</tt>
    - * when <i>element</i> is in {@code elementNames} and
    - * <i>attrNames</i> is in {@code attrNames}.
    - *
    - * If specified, {@code opt_valueXform} is a function that takes the
    - * HTML-entity-decoded attribute value, and can choose to disallow the
    - * attribute by returning {@code null} or substitute a new value
    - * by returning a string with the new value.
    - *
    - * @param {!Array<string>|string} elementNames names (or name) on which the
    - *     attributes are allowed.
    - *
    - *     Element names should be allowed via {@code allowElements(...)} prior
    - *     to white-listing attributes.
    - *
    - *     The special element name {@code "*"} has the same meaning as in CSS
    - *     selectors: it can be used to white-list attributes like {@code title}
    - *     and {@code id} which are widely available with element-agnostic
    - *     meanings.
    - *
    - *     It should not be used for attributes like {@code type} whose meaning
    - *     differs based on the element on which it appears:
    - *     e.g. {@code <input type=text>} vs {@code <style type=text/css>}.
    - *
    - * @param {!Array<string>|string} attrNames names (or name) of the attribute
    - *     that should be allowed.
    - *
    - * @param {goog.labs.html.AttributeRewriter=} opt_rewriteValue A function
    - *     that receives the HTML-entity-decoded attribute value and can return
    - *     {@code null} to disallow the attribute entirely or the value for the
    - *     attribute as a string.
    - *     <p>
    - *     The default is the identity function ({@code function(x){return x}}),
    - *     and the value rewriter is composed with an attribute specific handler:
    - *     <table>
    - *      <tr>
    - *        <th>href, src</th>
    - *        <td>Requires that the value be an absolute URL with a protocol in
    - *            (http, https, mailto) or a protocol relative URL.
    - *      </tr>
    - *     </table>
    - *
    - * @return {!goog.labs.html.Sanitizer} {@code this}.
    - */
    -goog.labs.html.Sanitizer.prototype.allowAttributes =
    -    function(elementNames, attrNames, opt_rewriteValue) {
    -  if (!goog.isArray(elementNames)) {
    -    elementNames = [elementNames];
    -  }
    -  if (!goog.isArray(attrNames)) {
    -    attrNames = [attrNames];
    -  }
    -  goog.asserts.assert(
    -      !opt_rewriteValue || 'function' === typeof opt_rewriteValue,
    -      'opt_rewriteValue should be a function');
    -
    -  var whitelist = this.whitelist_;
    -  for (var ei = 0; ei < elementNames.length; ++ei) {
    -    var elementName = elementNames[ei].toLowerCase();
    -    goog.asserts.assert(
    -        goog.labs.html.Sanitizer.isValidHtmlName_(elementName) ||
    -        '*' === elementName,
    -        elementName);
    -    // If the element has not been white-listed then panic.
    -    // TODO(user): allow allow{Elements,Attributes} to be called in any
    -    // order if someone needs it.
    -    if (!Object.prototype.hasOwnProperty.call(whitelist, elementName)) {
    -      throw new Error(elementName);
    -    }
    -    var attrWhitelist = whitelist[elementName];
    -    for (var ai = 0, an = attrNames.length; ai < an; ++ai) {
    -      var attrName = attrNames[ai].toLowerCase();
    -      goog.asserts.assert(
    -          goog.labs.html.Sanitizer.isValidHtmlName_(attrName), attrName);
    -
    -      // If the value has already been allowed, then chain the rewriters
    -      // so that both white-listers concerns are met.
    -      // We do not use the default rewriter here since it should have
    -      // been introduced by the call that created the initial white-list
    -      // entry.
    -      attrWhitelist[attrName] = goog.labs.html.Sanitizer.chain_(
    -          opt_rewriteValue || goog.labs.html.Sanitizer.valueIdentity_,
    -          Object.prototype.hasOwnProperty.call(attrWhitelist, attrName) ?
    -              attrWhitelist[attrName] :
    -              goog.labs.html.Sanitizer.defaultRewriterForAttr_(attrName));
    -    }
    -  }
    -  return this;
    -};
    -
    -
    -/**
    - * A new object that is as blank as possible.
    - *
    - * Using {@code Object.create} to create an object with
    - * no prototype speeds up whitelist access since there's fewer prototypes
    - * to fall-back to for a common case where an element is not in the
    - * white-list, and reduces the chance of confusing a member of
    - * {@code Object.prototype} with a whitelist entry.
    - *
    - * @return {!Object<string, ?>} a reference to a newly allocated object that
    - *    does not alias any reference that existed prior.
    - * @private
    - */
    -goog.labs.html.Sanitizer.createBlankObject_ = function() {
    -  return (Object.create || Object)(null);
    -};
    -
    -
    -/**
    - * HTML element and attribute names may be almost arbitrary strings, but the
    - * sanitizer is more restrictive as to what can be white-listed.
    - *
    - * Since HTML is case-insensitive, only lower-case identifiers composed of
    - * ASCII letters, digits, and select punctuation are allowed.
    - *
    - * @param {string} name
    - * @return {boolean} true iff name is a valid white-list key.
    - * @private
    - */
    -goog.labs.html.Sanitizer.isValidHtmlName_ = function(name) {
    -  return 'string' === typeof name &&  // Names must be strings.
    -      // Names must be lower-case and ASCII identifier chars only.
    -      /^[a-z][a-z0-9\-:]*$/.test(name);
    -};
    -
    -
    -/**
    - * @param  {goog.labs.html.AttributeValue} x
    - * @return {goog.labs.html.AttributeValue}
    - * @private
    - */
    -goog.labs.html.Sanitizer.valueIdentity_ = function(x) {
    -  return x;
    -};
    -
    -
    -/**
    - * @param  {goog.labs.html.AttributeValue} x
    - * @return {null}
    - * @private
    - */
    -goog.labs.html.Sanitizer.disallow_ = function(x) {
    -  return null;
    -};
    -
    -
    -/**
    - * Chains attribute rewriters.
    - *
    - * @param  {goog.labs.html.AttributeRewriter} f
    - * @param  {goog.labs.html.AttributeRewriter} g
    - * @return {goog.labs.html.AttributeRewriter}
    - *      a function that return g(f(x)) or null if f(x) is null.
    - * @private
    - */
    -goog.labs.html.Sanitizer.chain_ = function(f, g) {
    -  // Sometimes white-listing code ends up allowing things multiple times.
    -  if (f === goog.labs.html.Sanitizer.valueIdentity_) {
    -    return g;
    -  }
    -  if (g === goog.labs.html.Sanitizer.valueIdentity_) {
    -    return f;
    -  }
    -  // If someone tries to white-list a really problematic value, we reject
    -  // it by returning disallow_.  Disallow it quickly.
    -  if (f === goog.labs.html.Sanitizer.disallow_) {
    -    return f;
    -  }
    -  if (g === goog.labs.html.Sanitizer.disallow_) {
    -    return g;
    -  }
    -  return (
    -      /**
    -       * @param {goog.labs.html.AttributeValue} x
    -       * @return {goog.labs.html.AttributeValue}
    -       */
    -      function(x) {
    -        var y = f(x);
    -        return y != null ? g(y) : null;
    -      });
    -};
    -
    -
    -/**
    - * Given an attribute name, returns a value rewriter that enforces some
    - * minimal safety properties.
    - *
    - * <p>
    - * For url atributes, it checks that any protocol is on a safe set that
    - * doesn't allow script execution.
    - * <p>
    - * It also blanket disallows CSS and event handler attributes.
    - *
    - * @param  {string} attrName lower-cased attribute name.
    - * @return {goog.labs.html.AttributeRewriter}
    - * @private
    - */
    -goog.labs.html.Sanitizer.defaultRewriterForAttr_ = function(attrName) {
    -  if ('href' === attrName || 'src' === attrName) {
    -    return goog.labs.html.Sanitizer.checkUrl_;
    -  } else if ('style' === attrName || 'on' === attrName.substr(0, 2)) {
    -    // TODO(user): delegate to a CSS sanitizer if one is available.
    -    return goog.labs.html.Sanitizer.disallow_;
    -  }
    -  return goog.labs.html.Sanitizer.valueIdentity_;
    -};
    -
    -
    -/**
    - * Applied automatically to URL attributes to check that they are safe as per
    - * {@link SafeUrl}.
    - *
    - * @param {goog.labs.html.AttributeValue} attrValue a decoded attribute value.
    - * @return {goog.html.SafeUrl | null} a URL that is equivalent to the
    - *    input or {@code null} if the input is not a safe URL.
    - * @private
    - */
    -goog.labs.html.Sanitizer.checkUrl_ = function(attrValue) {
    -  if (attrValue == null) {
    -    return null;
    -  }
    -  /** @type {!goog.html.SafeUrl} */
    -  var safeUrl;
    -  if (attrValue instanceof goog.html.SafeUrl) {
    -    safeUrl = /** @type {!goog.html.SafeUrl} */ (attrValue);
    -  } else {
    -    if (typeof attrValue === 'string') {
    -      // Whitespace at the ends of URL-valued attributes in HTML is ignored.
    -      attrValue = goog.string.trim(/** @type {string} */ (attrValue));
    -    }
    -    safeUrl = goog.html.SafeUrl.sanitize(
    -        /** @type {!goog.string.TypedString | string} */ (attrValue));
    -  }
    -  if (goog.html.SafeUrl.unwrap(safeUrl) == goog.html.SafeUrl.INNOCUOUS_STRING) {
    -    return null;
    -  } else {
    -    return safeUrl;
    -  }
    -};
    -
    -
    -goog.labs.html.attributeRewriterPresubmitWorkaround();
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/html/sanitizer_test.js b/src/database/third_party/closure-library/closure/goog/labs/html/sanitizer_test.js
    deleted file mode 100644
    index d7846fac9d5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/html/sanitizer_test.js
    +++ /dev/null
    @@ -1,270 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -goog.provide('goog.labs.html.SanitizerTest');
    -
    -goog.require('goog.html.SafeUrl');
    -goog.require('goog.labs.html.Sanitizer');
    -goog.require('goog.string');
    -goog.require('goog.string.Const');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.labs.html.SanitizerTest');
    -
    -
    -var JENNYS_PHONE_NUMBER = goog.html.SafeUrl.fromConstant(
    -    goog.string.Const.from('tel:867-5309'));
    -
    -
    -var sanitizer = new goog.labs.html.Sanitizer()
    -    .allowElements(
    -        'a', 'b', 'i', 'p', 'font', 'hr', 'br', 'span',
    -        'ol', 'ul', 'li',
    -        'table', 'tr', 'td', 'th', 'tbody',
    -        'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
    -        'img',
    -        'html', 'head', 'body', 'title'
    -    )
    -    // allow unfiltered title attributes, and
    -    .allowAttributes('*', 'title')
    -    // specific dir values.
    -    .allowAttributes(
    -        '*', 'dir',
    -        function(dir) { return dir === 'ltr' || dir === 'rtl' ? dir : null; })
    -    .allowAttributes(
    -        // Specifically on <a> elements,
    -        'a',
    -        // allow an href but verify and rewrite, and
    -        'href',
    -        function(href) {
    -          if (href === 'tel:867-5309') {
    -            return JENNYS_PHONE_NUMBER;
    -          }
    -          // Missing anchor is an intentional error.
    -          return /https?:\/\/google\.[a-z]{2,3}\/search\?/.test(String(href)) ?
    -              href : null;
    -        })
    -    .allowAttributes(
    -        'a',
    -        // mask the generic title handler for no good reason.
    -        'title',
    -        function(title) { return '<' + title + '>'; });
    -
    -
    -function run(input, golden, desc) {
    -  var actual = sanitizer.sanitize(input);
    -  assertEquals(desc, golden, actual);
    -}
    -
    -
    -function testEmptyString() {
    -  run('', '', 'Empty string');
    -}
    -
    -function testHelloWorld() {
    -  run('Hello, <b>World</b>!', 'Hello, <b>World</b>!',
    -      'Hello World');
    -}
    -
    -function testNoEndTag() {
    -  run('<i>Hello, <b>World!',
    -      '<i>Hello, <b>World!</b></i>',
    -      'Hello World no end tag');
    -}
    -
    -function testUnclosedTags() {
    -  run('<html><head><title>Hello, <<World>>!</TITLE>' +
    -      '</head><body><p>Hello,<Br><<World>>!',
    -      '<html><head><title>Hello, <<World>>!</title>' +
    -      '</head><body><p>Hello,<br>&lt;&gt;!</p></body></html>',
    -      'RCDATA content, different case, unclosed tags');
    -}
    -
    -function testListInList() {
    -  run('<ul><li>foo</li><ul><li>bar</li></ul></ul>',
    -      '<ul><li>foo</li><li><ul><li>bar</li></ul></li></ul>',
    -      'list in list directly');
    -}
    -
    -function testHeaders() {
    -  run('<h1>header</h1>body' +
    -      '<H2>sub-header</h3>sub-body' +
    -      '<h3>sub-sub-</hr>header<hr></hr>sub-sub-body</H4></h2>',
    -      '<h1>header</h1>body' +
    -      '<h2>sub-header</h2>sub-body' +
    -      '<h3>sub-sub-header</h3><hr>sub-sub-body',
    -      'headers');
    -}
    -
    -function testListNesting() {
    -  run('<ul><li><ul><li>foo</li></li><ul><li>bar',
    -      '<ul><li><ul><li>foo</li><li><ul><li>bar</li></ul></li></ul></li></ul>',
    -      'list nesting');
    -}
    -
    -function testTableNesting() {
    -  run('<table><tbody><tr><td>foo</td><table><tbody><tr><th>bar</table></table>',
    -      '<table><tbody><tr><td>foo</td><td>' +
    -      '<table><tbody><tr><th>bar</th></tr></tbody></table>' +
    -      '</td></tr></tbody></table>',
    -      'table nesting');
    -}
    -
    -function testNestingLimit() {
    -  run(goog.string.repeat('<span>', 264) + goog.string.repeat('</span>', 264),
    -      goog.string.repeat('<span>', 256) + goog.string.repeat('</span>', 256),
    -      '264 open spans');
    -}
    -
    -function testTableScopes() {
    -  run('<html><head></head><body><p>Hi</p><p>How are you</p>\n' +
    -      '<p><table><tbody><tr>' +
    -      '<td><b><font><font><p>Cell</b></font></font></p>\n</td>' +
    -      '<td><b><font><font><p>Cell</b></font></font></p>\n</td>' +
    -      '</tr></tbody></table></p>\n' +
    -      '<p>x</p></body></html>',
    -
    -      '<html><head></head><body><p>Hi</p><p>How are you</p>\n' +
    -      '<p><table><tbody><tr>' +
    -      '<td><b><font><font></font></font></b><p>Cell</p>\n</td>' +
    -      // The close </p> tag does not close the whole table. +
    -      '<td><b><font><font></font></font></b><p>Cell</p>\n</td>' +
    -      '</tr></tbody></table></p>\n' +
    -      '<p>x</p></body></html>',
    -
    -      'Table Scopes');
    -}
    -
    -function testConcatSafe() {
    -  run('<<applet>script<applet>>alert(1337)<<!-- -->/script<?...?>>',
    -      '&lt;script&gt;alert(1337)&lt;/script&gt;',
    -      'Concat safe');
    -}
    -
    -function testPrototypeMembersDoNotInfectTables() {
    -  // Constructor is all lower-case so will survive tag name
    -  // normalization.
    -  run('<constructor>Foo</constructor>', 'Foo',
    -      'Object.prototype members');
    -}
    -
    -function testGenericAttributesAllowed() {
    -  run('<span title=howdy></span>', '<span title="howdy"></span>',
    -      'generic attrs allowed');
    -}
    -
    -function testValueWhitelisting() {
    -  run('<span dir=\'ltr\'>LTR</span><span dir=\'evil\'>Evil</span>',
    -      '<span dir="ltr">LTR</span><span>Evil</span>',
    -      'value whitelisted');
    -}
    -
    -function testAttributeNormalization() {
    -  run('<a href="http://google.com/search?q=tests suxor&hl=en">Click</a>',
    -      '<a href="http://google.com/search?q=tests%20suxor&amp;hl=en">Click</a>',
    -      'URL normalized');
    -}
    -
    -function testNaiveAttributeRewriterCaught() {
    -  run('<a href="javascript:http://google.com/&#10;alert(1337)">sneaky</a>',
    -      '<a>sneaky</a>',
    -      'Safety net saves naive attribute rewriters');
    -}
    -
    -function testSafeUrlFromAttributeRewriter() {
    -  run('<a href="tel:867-5309">Jenny</a>', '<a href="tel:867-5309">Jenny</a>',
    -      'Attribute rewriter escapes safety checks via SafeURL');
    -}
    -
    -function testTagSpecificityOfAttributeFiltering() {
    -  run('<img href="http://google.com/search?q=tests+suxor">',
    -      '<img>',
    -      'href blocked on img');
    -}
    -
    -function testTagSpecificAttributeFiltering() {
    -  run('<a href="http://google.evil.com/search?q=tests suxor">Unclicky</a>',
    -      '<a>Unclicky</a>',
    -      'bad href value blocked');
    -}
    -
    -function testNonWhitelistFunctionsNotCalled() {
    -  var called = false;
    -  Object.prototype.dontcallme = function() {
    -    called = true;
    -    return 'dontcallme was called despite being on the prototype';
    -  };
    -  try {
    -    run('<span dontcallme="I\'ll call you">Lorem Ipsum',
    -        '<span>Lorem Ipsum</span>',
    -        'non white-list fn not called');
    -  } finally {
    -    delete Object.prototype.dontcallme;
    -  }
    -  assertFalse('Object.prototype.dontcallme should not have been called',
    -              called);
    -}
    -
    -function testQuotesInAttributeValue() {
    -  run('<span tItlE =\n\'Quoth the raven, "Nevermore"\'>Lorem Ipsum',
    -      '<span title="Quoth the raven, &quot;Nevermore&quot;">Lorem Ipsum</span>',
    -      'quotes in attr value');
    -}
    -
    -function testAttributesNeverMentionedAreDropped() {
    -  run('<b onclick="evil=true">evil</b>', '<b>evil</b>', 'attrs white-listed');
    -}
    -
    -function testAttributesNotOverEscaped() {
    -  run('<I TITLE="Foo &AMP; Bar & Baz">/</I>',
    -      '<i title="Foo &amp; Bar &amp; Baz">/</i>',
    -      'attr value not over-escaped');
    -}
    -
    -function testTagSpecificRulesTakePrecedence() {
    -  run('<a title=zogberts>Link</a>',
    -      '<a title="&lt;zogberts&gt;">Link</a>',
    -      'tag specific rules take precedence');
    -}
    -
    -function testAttributeRejectionLocalized() {
    -  run('<a id=foo href =//evil.org/ title=>Link</a>',
    -      '<a title="&lt;&gt;">Link</a>',
    -      'failure of one attribute does not torpedo others');
    -}
    -
    -function testWeirdHtmlRulesFollowedForAttrValues() {
    -  run('<span title= id=>Lorem Ipsum</span>',
    -      '<span title=\"id=\">Lorem Ipsum</span>',
    -      'same as browser on weird values');
    -}
    -
    -function testAttributesDisallowedOnCloseTags() {
    -  run('<h1 title="open">Header</h1 title="closed">',
    -      '<h1 title="open">Header</h1>',
    -      'attributes on close tags');
    -}
    -
    -function testRoundTrippingOfHtmlSafeAgainstIEBacktickProblems() {
    -  // Introducing a space at the end of an attribute forces IE to quote it when
    -  // turning a DOM into innerHTML which protects against a bunch of problems
    -  // with backticks since IE treats them as attribute value delimiters, allowing
    -  //   foo.innerHTML += ...
    -  // to continue to "work" without introducing an XSS vector.
    -  // Adding a space at the end is innocuous since HTML attributes whose values
    -  // are structured content ignore spaces at the beginning or end.
    -  run('<span title="`backtick">*</span>', '<span title="`backtick ">*</span>',
    -      'not round-trippable on IE');
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/html/scrubber.js b/src/database/third_party/closure-library/closure/goog/labs/html/scrubber.js
    deleted file mode 100644
    index a5fbc822d9b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/html/scrubber.js
    +++ /dev/null
    @@ -1,1027 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview
    - * HTML tag filtering, and balancing.
    - * A more user-friendly API is exposed via {@code goog.labs.html.sanitizer}.
    - * @visibility {//visibility:private}
    - */
    -
    -
    -goog.provide('goog.labs.html.scrubber');
    -
    -goog.require('goog.array');
    -goog.require('goog.dom.tags');
    -goog.require('goog.labs.html.attributeRewriterPresubmitWorkaround');
    -goog.require('goog.string');
    -
    -
    -/**
    - * Replaces tags not on the white-list with empty text nodes, dropping all
    - * attributes, and drops other non-text nodes such as comments.
    - *
    - * @param {!Object<string, boolean>} tagWhitelist a set of lower-case tag names
    - *    following the convention established by {@link goog.object.createSet}.
    - * @param {!Object<string, Object<string, goog.labs.html.AttributeRewriter>>}
    - *        attrWhitelist
    - *    maps lower-case tag names and the special string {@code "*"} to functions
    - *    from decoded attribute values to sanitized values or {@code null} to
    - *    indicate that the attribute is not allowed with that value.
    - *
    - *    For example, if {@code attrWhitelist['a']['href']} is defined then it
    - *    is used to sanitize the value of the link's URL.
    - *
    - *    If {@code attrWhitelist['*']['id']} is defined, and
    - *    {@code attrWhitelist['div']['id']} is not, then the former is used to
    - *    sanitize any {@code id} attribute on a {@code <div>} element.
    - * @param {string} html a string of HTML
    - * @return {string} the input but with potentially dangerous tokens removed.
    - */
    -goog.labs.html.scrubber.scrub = function(tagWhitelist, attrWhitelist, html) {
    -  return goog.labs.html.scrubber.render_(
    -      goog.labs.html.scrubber.balance_(
    -          goog.labs.html.scrubber.filter_(
    -              tagWhitelist,
    -              attrWhitelist,
    -              goog.labs.html.scrubber.lex_(html))));
    -};
    -
    -
    -/**
    - * Balances tags in trusted HTML.
    - * @param {string} html a string of HTML
    - * @return {string} the input but with an end-tag for each non-void start tag
    - *     and only for non-void start tags, and with start and end tags nesting
    - *     properly.
    - */
    -goog.labs.html.scrubber.balance = function(html) {
    -  return goog.labs.html.scrubber.render_(
    -      goog.labs.html.scrubber.balance_(
    -          goog.labs.html.scrubber.lex_(html)));
    -};
    -
    -
    -/** Character code constant for {@code '<'}.  @private */
    -goog.labs.html.scrubber.CC_LT_ = '<'.charCodeAt(0);
    -
    -
    -/** Character code constant for {@code '!'}.  @private */
    -goog.labs.html.scrubber.CC_BANG_ = '!'.charCodeAt(0);
    -
    -
    -/** Character code constant for {@code '/'}.  @private */
    -goog.labs.html.scrubber.CC_SLASH_ = '/'.charCodeAt(0);
    -
    -
    -/** Character code constant for {@code '?'}.  @private */
    -goog.labs.html.scrubber.CC_QMARK_ = '?'.charCodeAt(0);
    -
    -
    -/**
    - * Matches content following a tag name or attribute value, and before the
    - * beginning of the next attribute value.
    - * @private
    - */
    -goog.labs.html.scrubber.ATTR_VALUE_PRECEDER_ = '[^=>]+';
    -
    -
    -/** @private */
    -goog.labs.html.scrubber.UNQUOTED_ATTR_VALUE_ = '(?:[^"\'\\s>][^\\s>]*)';
    -
    -
    -/** @private */
    -goog.labs.html.scrubber.DOUBLE_QUOTED_ATTR_VALUE_ = '(?:"[^"]*"?)';
    -
    -
    -/** @private */
    -goog.labs.html.scrubber.SINGLE_QUOTED_ATTR_VALUE_ = "(?:'[^']*'?)";
    -
    -
    -/**
    - * Matches the equals-sign and any attribute value following it, but does not
    - * capture any {@code >} that would close the tag.
    - * @private
    - */
    -goog.labs.html.scrubber.ATTR_VALUE_ = '=\\s*(?:' +
    -    goog.labs.html.scrubber.UNQUOTED_ATTR_VALUE_ +
    -    '|' + goog.labs.html.scrubber.DOUBLE_QUOTED_ATTR_VALUE_ +
    -    '|' + goog.labs.html.scrubber.SINGLE_QUOTED_ATTR_VALUE_ + ')?';
    -
    -
    -/**
    - * The body of a tag between the end of the name and the closing {@code >}
    - * if any.
    - * @private
    - */
    -goog.labs.html.scrubber.ATTRS_ =
    -    '(?:' + goog.labs.html.scrubber.ATTR_VALUE_PRECEDER_ +
    -    '|' + goog.labs.html.scrubber.ATTR_VALUE_ + ')*';
    -
    -
    -/**
    - * A character that continues a tag name as defined at
    - * http://www.w3.org/html/wg/drafts/html/master/syntax.html#tag-name-state
    - * @private
    - */
    -goog.labs.html.scrubber.TAG_NAME_CHAR_ = '[^\t\f\n />]';
    -
    -
    -/**
    - * Matches when the next character cannot continue a tag name.
    - * @private
    - */
    -goog.labs.html.scrubber.BREAK_ =
    -    '(?!' + goog.labs.html.scrubber.TAG_NAME_CHAR_ + ')';
    -
    -
    -/**
    - * Matches the open tag and body of a special element :
    - * one whose body cannot contain nested elements so uses special parsing rules.
    - * It does not include the end tag.
    - * @private
    - */
    -goog.labs.html.scrubber.SPECIAL_ELEMENT_ = '<(?:' +
    -    // Special tag name.
    -    '(iframe|script|style|textarea|title|xmp)' +
    -    // End of tag name
    -    goog.labs.html.scrubber.BREAK_ +
    -    // Attributes
    -    goog.labs.html.scrubber.ATTRS_ + '>' +
    -    // Element content includes non '<' characters, and
    -    // '<' that don't start a matching end tag.
    -    // This uses a back-reference to the tag name to determine whether
    -    // the tag names match.
    -    // Since matching is case-insensitive, this can only be used in
    -    // a case-insensitive regular expression.
    -    // JavaScript does not treat Turkish dotted I's as equivalent to their
    -    // ASCII equivalents.
    -    '(?:[^<]|<(?!/\\1' + goog.labs.html.scrubber.BREAK_ + '))*' +
    -    ')';
    -
    -
    -/**
    - * Regexp pattern for an HTML tag.
    - * @private
    - */
    -goog.labs.html.scrubber.TAG_ =
    -    '<[/]?[a-z]' + goog.labs.html.scrubber.TAG_NAME_CHAR_ + '*' +
    -    goog.labs.html.scrubber.ATTRS_ + '>?';
    -
    -
    -/**
    - * Regexp pattern for an HTML text node.
    - * @private
    - */
    -goog.labs.html.scrubber.TEXT_NODE_ = '(?:[^<]|<(?![a-z]|[?!/]))+';
    -
    -
    -/**
    - * Matches HTML comments including HTML 5 "bogus comments" of the form
    - * {@code <!...>} or {@code <?...>} or {@code </...>}.
    - * @private
    - */
    -goog.labs.html.scrubber.COMMENT_ =
    -    '<!--(?:[^\\-]|-+(?![\\->]))*(?:-(?:->?)?)?' +
    -    '|<[!?/][^>]*>?';
    -
    -
    -/**
    - * Regexp pattern for an HTML token after a doctype.
    - * Special elements introduces a capturing group for use with a
    - * back-reference.
    - * @private
    - */
    -goog.labs.html.scrubber.HTML_TOKENS_RE_ = new RegExp(
    -    '(?:' + goog.labs.html.scrubber.TEXT_NODE_ +
    -    '|' + goog.labs.html.scrubber.SPECIAL_ELEMENT_ +
    -    '|' + goog.labs.html.scrubber.TAG_ +
    -    '|' + goog.labs.html.scrubber.COMMENT_ + ')',
    -    'ig');
    -
    -
    -/**
    - * An HTML tag which captures the name in group 1,
    - * and any attributes in group 2.
    - * @private
    - */
    -goog.labs.html.scrubber.TAG_RE_ = new RegExp(
    -    '<[/]?([a-z]' + goog.labs.html.scrubber.TAG_NAME_CHAR_ + '*)' +
    -    '(' + goog.labs.html.scrubber.ATTRS_ + ')>?',
    -    'i');
    -
    -
    -/**
    - * A global matcher that separates attributes out of the tag body cruft.
    - * @private
    - */
    -goog.labs.html.scrubber.ATTRS_RE_ = new RegExp(
    -    '[^=\\s]+\\s*(?:' + goog.labs.html.scrubber.ATTR_VALUE_ + ')?', 'ig');
    -
    -
    -/**
    - * Returns an array of HTML tokens including tags, text nodes and comments.
    - * "Special" elements, like {@code <script>..</script>} whose bodies cannot
    - * include nested elements, are returned as single tokens.
    - *
    - * @param {string} html a string of HTML
    - * @return {!Array<string>}
    - * @private
    - */
    -goog.labs.html.scrubber.lex_ = function(html) {
    -  return ('' + html).match(goog.labs.html.scrubber.HTML_TOKENS_RE_) || [];
    -};
    -
    -
    -/**
    - * Replaces tags not on the white-list with empty text nodes, dropping all
    - * attributes, and drops other non-text nodes such as comments.
    - *
    - * @param {!Object<string, boolean>} tagWhitelist a set of lower-case tag names
    - *    following the convention established by {@link goog.object.createSet}.
    - * @param {!Object<string, Object<string, goog.labs.html.AttributeRewriter>>
    - *        } attrWhitelist
    - *    maps lower-case tag names and the special string {@code "*"} to functions
    - *    from decoded attribute values to sanitized values or {@code null} to
    - *    indicate that the attribute is not allowed with that value.
    - *
    - *    For example, if {@code attrWhitelist['a']['href']} is defined then it is
    - *    used to sanitize the value of the link's URL.
    - *
    - *    If {@code attrWhitelist['*']['id']} is defined, and
    - *    {@code attrWhitelist['div']['id']} is not, then the former is used to
    - *    sanitize any {@code id} attribute on a {@code <div>} element.
    - * @param {!Array<string>} htmlTokens an array of HTML tokens as returned by
    - *    {@link goog.labs.html.scrubber.lex_}.
    - * @return {!Array<string>} the input array modified in place to have some
    - *    tokens removed.
    - * @private
    - */
    -goog.labs.html.scrubber.filter_ = function(
    -    tagWhitelist, attrWhitelist, htmlTokens) {
    -  var genericAttrWhitelist = attrWhitelist['*'];
    -  for (var i = 0, n = htmlTokens.length; i < n; ++i) {
    -    var htmlToken = htmlTokens[i];
    -    if (htmlToken.charCodeAt(0) !== goog.labs.html.scrubber.CC_LT_) {
    -      // Definitely not a tag
    -      continue;
    -    }
    -
    -    var tag = htmlToken.match(goog.labs.html.scrubber.TAG_RE_);
    -    if (tag) {
    -      var lowerCaseTagName = tag[1].toLowerCase();
    -      var isCloseTag =
    -          htmlToken.charCodeAt(1) === goog.labs.html.scrubber.CC_SLASH_;
    -      var attrs = '';
    -      if (!isCloseTag && tag[2]) {
    -        var tagSpecificAttrWhitelist =
    -            /** @type {Object<string, goog.labs.html.AttributeRewriter>} */ (
    -            goog.labs.html.scrubber.readOwnProperty_(
    -                attrWhitelist, lowerCaseTagName));
    -        if (genericAttrWhitelist || tagSpecificAttrWhitelist) {
    -          attrs = goog.labs.html.scrubber.filterAttrs_(
    -              tag[2], genericAttrWhitelist, tagSpecificAttrWhitelist);
    -        }
    -      }
    -      var specialContent = htmlToken.substring(tag[0].length);
    -      htmlTokens[i] =
    -          (tagWhitelist[lowerCaseTagName] === true) ?
    -          (
    -              (isCloseTag ? '</' : '<') + lowerCaseTagName + attrs + '>' +
    -              specialContent
    -          ) :
    -          '';
    -    } else if (htmlToken.length > 1) {
    -      switch (htmlToken.charCodeAt(1)) {
    -        case goog.labs.html.scrubber.CC_BANG_:
    -        case goog.labs.html.scrubber.CC_SLASH_:
    -        case goog.labs.html.scrubber.CC_QMARK_:
    -          htmlTokens[i] = '';  // Elide comments.
    -          break;
    -        default:
    -          // Otherwise, token is just a text node that starts with '<'.
    -          // Speed up later passes by normalizing the text node.
    -          htmlTokens[i] = htmlTokens[i].replace(/</g, '&lt;');
    -      }
    -    }
    -  }
    -  return htmlTokens;
    -};
    -
    -
    -/**
    - * Parses attribute names and values out of a tag body and applies the attribute
    - * white-list to produce a tag body containing only safe attributes.
    - *
    - * @param {string} attrsText the text of a tag between the end of the tag name
    - *   and the beginning of the tag end marker, so {@code " foo bar='baz'"} for
    - *   the tag {@code <tag foo bar='baz'/>}.
    - * @param {Object<string, goog.labs.html.AttributeRewriter>}
    - *   genericAttrWhitelist
    - *   a whitelist of attribute transformations for attributes that are allowed
    - *   on any element.
    - * @param {Object<string, goog.labs.html.AttributeRewriter>}
    - *   tagSpecificAttrWhitelist
    - *   a whitelist of attribute transformations for attributes that are allowed
    - *   on the element started by the tag whose body is {@code tagBody}.
    - * @return {string} a tag-body that consists only of safe attributes.
    - * @private
    - */
    -goog.labs.html.scrubber.filterAttrs_ =
    -    function(attrsText, genericAttrWhitelist, tagSpecificAttrWhitelist) {
    -  var attrs = attrsText.match(goog.labs.html.scrubber.ATTRS_RE_);
    -  var nAttrs = attrs ? attrs.length : 0;
    -  var safeAttrs = '';
    -  for (var i = 0; i < nAttrs; ++i) {
    -    var attr = attrs[i];
    -    var eq = attr.indexOf('=');
    -    var name, value;
    -    if (eq >= 0) {
    -      name = goog.string.trim(attr.substr(0, eq));
    -      value = goog.string.stripQuotes(
    -          goog.string.trim(attr.substr(eq + 1)), '"\'');
    -    } else {
    -      name = value = attr;
    -    }
    -    name = name.toLowerCase();
    -    var rewriter = /** @type {?goog.labs.html.AttributeRewriter} */ (
    -        tagSpecificAttrWhitelist &&
    -        goog.labs.html.scrubber.readOwnProperty_(
    -            tagSpecificAttrWhitelist, name) ||
    -        genericAttrWhitelist &&
    -        goog.labs.html.scrubber.readOwnProperty_(genericAttrWhitelist, name));
    -    if (rewriter) {
    -      var safeValue = rewriter(goog.string.unescapeEntities(value));
    -      if (safeValue != null) {
    -        if (safeValue.implementsGoogStringTypedString) {
    -          safeValue = /** @type {goog.string.TypedString} */
    -              (safeValue).getTypedStringValue();
    -        }
    -        safeValue = String(safeValue);
    -        if (safeValue.indexOf('`') >= 0) {
    -          safeValue += ' ';
    -        }
    -        safeAttrs +=
    -            ' ' + name + '="' + goog.string.htmlEscape(safeValue, false) +
    -            '"';
    -      }
    -    }
    -  }
    -  return safeAttrs;
    -};
    -
    -
    -/**
    - * @param {!Object} o the object
    - * @param {!string} k a key into o
    - * @return {*}
    - * @private
    - */
    -goog.labs.html.scrubber.readOwnProperty_ = function(o, k) {
    -  return Object.prototype.hasOwnProperty.call(o, k) ? o[k] : undefined;
    -};
    -
    -
    -/**
    - * We limit the nesting limit of balanced HTML to a large but manageable number
    - * so that built-in browser limits aren't likely to kick in and undo all our
    - * matching of start and end tags.
    - * <br>
    - * This mitigates the HTML parsing equivalent of stack smashing attacks.
    - * <br>
    - * Otherwise, crafted inputs like
    - * {@code <p><p><p><p>...Ad nauseam..</p></p></p></p>} could exploit
    - * browser bugs, and/or undocumented nesting limit recovery code to misnest
    - * tags.
    - * @private
    - * @const
    - */
    -goog.labs.html.scrubber.BALANCE_NESTING_LIMIT_ = 256;
    -
    -
    -/**
    - * Ensures that there are end-tags for all and only for non-void start tags.
    - * @param {Array<string>} htmlTokens an array of HTML tokens as returned by
    - *    {@link goog.labs.html.scrubber.lex}.
    - * @return {!Array<string>} the input array modified in place to have some
    - *    tokens removed.
    - * @private
    - */
    -goog.labs.html.scrubber.balance_ = function(htmlTokens) {
    -  var openElementStack = [];
    -  for (var i = 0, n = htmlTokens.length; i < n; ++i) {
    -    var htmlToken = htmlTokens[i];
    -    if (htmlToken.charCodeAt(0) !== goog.labs.html.scrubber.CC_LT_) {
    -      // Definitely not a tag
    -      continue;
    -    }
    -    var tag = htmlToken.match(goog.labs.html.scrubber.TAG_RE_);
    -    if (tag) {
    -      var lowerCaseTagName = tag[1].toLowerCase();
    -      var isCloseTag =
    -          htmlToken.charCodeAt(1) === goog.labs.html.scrubber.CC_SLASH_;
    -      // Special case: HTML5 mandates that </br> be treated as <br>.
    -      if (isCloseTag && lowerCaseTagName == 'br') {
    -        isCloseTag = false;
    -        htmlToken = '<br>';
    -      }
    -      var isVoidTag = goog.dom.tags.isVoidTag(lowerCaseTagName);
    -      if (isVoidTag && isCloseTag) {
    -        htmlTokens[i] = '';
    -        continue;
    -      }
    -
    -      var prefix = '';
    -
    -      // Insert implied open tags.
    -      var nOpenElements = openElementStack.length;
    -      if (nOpenElements && !isCloseTag) {
    -        var top = openElementStack[nOpenElements - 1];
    -        var groups = goog.labs.html.scrubber.ELEMENT_GROUPS_[lowerCaseTagName];
    -        if (groups === undefined) {
    -          groups = goog.labs.html.scrubber.Group_.INLINE_;
    -        }
    -        var canContain = goog.labs.html.scrubber.ELEMENT_CONTENTS_[top];
    -        if (!(groups & canContain)) {
    -          var blockContainer = goog.labs.html.scrubber.BLOCK_CONTAINERS_[top];
    -          if ('string' === typeof blockContainer) {
    -            var containerCanContain =
    -                goog.labs.html.scrubber.ELEMENT_CONTENTS_[blockContainer];
    -            if (containerCanContain & groups) {
    -              if (nOpenElements <
    -                  goog.labs.html.scrubber.BALANCE_NESTING_LIMIT_) {
    -                prefix = '<' + blockContainer + '>';
    -              }
    -              openElementStack[nOpenElements] = blockContainer;
    -              ++nOpenElements;
    -            }
    -          }
    -        }
    -      }
    -
    -      // Insert any missing close tags we need.
    -      var newStackLen = goog.labs.html.scrubber.pickElementsToClose_(
    -          lowerCaseTagName, isCloseTag, openElementStack);
    -
    -      var nClosed = nOpenElements - newStackLen;
    -      if (nClosed) {  // ["p", "a", "b"] -> "</b></a></p>"
    -        // First, dump anything past the nesting limit.
    -        if (nOpenElements > goog.labs.html.scrubber.BALANCE_NESTING_LIMIT_) {
    -          nClosed -= nOpenElements -
    -              goog.labs.html.scrubber.BALANCE_NESTING_LIMIT_;
    -          nOpenElements = goog.labs.html.scrubber.BALANCE_NESTING_LIMIT_;
    -        }
    -        // Truncate to the new limit, and produce end tags.
    -        var closeTags = openElementStack.splice(newStackLen, nClosed);
    -        if (closeTags.length) {
    -          closeTags.reverse();
    -          prefix += '</' + closeTags.join('></') + '>';
    -        }
    -      }
    -
    -      // We could do resumption here to handle misnested tags like
    -      //    <b><i class="c">Foo</b>Bar</i>
    -      // which is equivalent to
    -      //    <b><i class="c">Foo</i></b><i class="c">Bar</i>
    -      // but that requires storing attributes on the open element stack
    -      // which complicates all the code using it for marginal added value.
    -
    -      if (isCloseTag) {
    -        // If the close tag matched an open tag, then the closed section
    -        // included that tag name.
    -        htmlTokens[i] = prefix;
    -      } else {
    -        if (!isVoidTag) {
    -          openElementStack[openElementStack.length] = lowerCaseTagName;
    -        }
    -        if (openElementStack.length >
    -            goog.labs.html.scrubber.BALANCE_NESTING_LIMIT_) {
    -          htmlToken = '';
    -        }
    -        htmlTokens[i] = prefix + htmlToken;
    -      }
    -    }
    -  }
    -  if (openElementStack.length) {
    -    if (openElementStack.length >
    -        goog.labs.html.scrubber.BALANCE_NESTING_LIMIT_) {
    -      openElementStack.length = goog.labs.html.scrubber.BALANCE_NESTING_LIMIT_;
    -    }
    -    if (openElementStack.length) {
    -      openElementStack.reverse();
    -      htmlTokens[htmlTokens.length] = '</' + openElementStack.join('></') + '>';
    -    }
    -  }
    -  return htmlTokens;
    -};
    -
    -
    -/**
    - * Normalizes HTML tokens and concatenates them into a string.
    - * @param {Array<string>} htmlTokens an array of HTML tokens as returned by
    - *    {@link goog.labs.html.scrubber.lex}.
    - * @return {string} a string of HTML.
    - * @private
    - */
    -goog.labs.html.scrubber.render_ = function(htmlTokens) {
    -  for (var i = 0, n = htmlTokens.length; i < n; ++i) {
    -    var htmlToken = htmlTokens[i];
    -    if (htmlToken.charCodeAt(0) === goog.labs.html.scrubber.CC_LT_ &&
    -        goog.labs.html.scrubber.TAG_RE_.test(htmlToken)) {
    -      // The well-formedness and quotedness of attributes must be ensured by
    -      // earlier passes.  filter does this.
    -    } else {
    -      if (htmlToken.indexOf('<') >= 0) {
    -        htmlToken = htmlToken.replace(/</g, '&lt;');
    -      }
    -      if (htmlToken.indexOf('>') >= 0) {
    -        htmlToken = htmlToken.replace(/>/g, '&gt;');
    -      }
    -      htmlTokens[i] = htmlToken;
    -    }
    -  }
    -  return htmlTokens.join('');
    -};
    -
    -
    -/**
    - * Groups of elements used to specify containment relationships.
    - * @enum {number}
    - * @private
    - */
    -goog.labs.html.scrubber.Group_ = {
    -  BLOCK_: (1 << 0),
    -  INLINE_: (1 << 1),
    -  INLINE_MINUS_A_: (1 << 2),
    -  MIXED_: (1 << 3),
    -  TABLE_CONTENT_: (1 << 4),
    -  HEAD_CONTENT_: (1 << 5),
    -  TOP_CONTENT_: (1 << 6),
    -  AREA_ELEMENT_: (1 << 7),
    -  FORM_ELEMENT_: (1 << 8),
    -  LEGEND_ELEMENT_: (1 << 9),
    -  LI_ELEMENT_: (1 << 10),
    -  DL_PART_: (1 << 11),
    -  P_ELEMENT_: (1 << 12),
    -  OPTIONS_ELEMENT_: (1 << 13),
    -  OPTION_ELEMENT_: (1 << 14),
    -  PARAM_ELEMENT_: (1 << 15),
    -  TABLE_ELEMENT_: (1 << 16),
    -  TR_ELEMENT_: (1 << 17),
    -  TD_ELEMENT_: (1 << 18),
    -  COL_ELEMENT_: (1 << 19),
    -  CHARACTER_DATA_: (1 << 20)
    -};
    -
    -
    -/**
    - * Element scopes limit where close tags can have effects.
    - * For example, a table cannot be implicitly closed by a {@code </p>} even if
    - * the table appears inside a {@code <p>} because the {@code <table>} element
    - * introduces a scope.
    - *
    - * @enum {number}
    - * @private
    - */
    -goog.labs.html.scrubber.Scope_ = {
    -  COMMON_: (1 << 0),
    -  BUTTON_: (1 << 1),
    -  LIST_ITEM_: (1 << 2),
    -  TABLE_: (1 << 3)
    -};
    -
    -
    -/** @const @private */
    -goog.labs.html.scrubber.ALL_SCOPES_ =
    -    goog.labs.html.scrubber.Scope_.COMMON_ |
    -    goog.labs.html.scrubber.Scope_.BUTTON_ |
    -    goog.labs.html.scrubber.Scope_.LIST_ITEM_ |
    -    goog.labs.html.scrubber.Scope_.TABLE_;
    -
    -
    -/**
    - * Picks which open HTML elements to close.
    - *
    - * @param {string}         lowerCaseTagName The name of the tag.
    - * @param {boolean}        isCloseTag       True for a {@code </tagname>} tag.
    - * @param {Array<string>} openElementStack The names of elements that have been
    - *                                          opened and not subsequently closed.
    - * @return {number} the length of openElementStack after closing any tags that
    - *               need to be closed.
    - * @private
    - */
    -goog.labs.html.scrubber.pickElementsToClose_ =
    -    function(lowerCaseTagName, isCloseTag, openElementStack) {
    -  var nOpenElements = openElementStack.length;
    -  if (isCloseTag) {
    -    // Look for a matching close tag inside blocking scopes.
    -    var topMost;
    -    if (/^h[1-6]$/.test(lowerCaseTagName)) {
    -      // </h1> will close any header.
    -      topMost = -1;
    -      for (var i = nOpenElements; --i >= 0;) {
    -        if (/^h[1-6]$/.test(openElementStack[i])) {
    -          topMost = i;
    -        }
    -      }
    -    } else {
    -      topMost = goog.array.lastIndexOf(openElementStack, lowerCaseTagName);
    -    }
    -    if (topMost >= 0) {
    -      var blockers = goog.labs.html.scrubber.ALL_SCOPES_ &
    -          ~(goog.labs.html.scrubber.ELEMENT_SCOPES_[lowerCaseTagName] | 0);
    -      for (var i = nOpenElements; --i > topMost;) {
    -        var blocks =
    -            goog.labs.html.scrubber.ELEMENT_SCOPES_[openElementStack[i]] | 0;
    -        if (blockers & blocks) {
    -          return nOpenElements;
    -        }
    -      }
    -      return topMost;
    -    }
    -    return nOpenElements;
    -  } else {
    -    // Close anything that cannot contain the tag name.
    -    var groups = goog.labs.html.scrubber.ELEMENT_GROUPS_[lowerCaseTagName];
    -    if (groups === undefined) {
    -      groups = goog.labs.html.scrubber.Group_.INLINE_;
    -    }
    -    for (var i = nOpenElements; --i >= 0;) {
    -      var canContain =
    -          goog.labs.html.scrubber.ELEMENT_CONTENTS_[openElementStack[i]];
    -      if (canContain === undefined) {
    -        canContain = goog.labs.html.scrubber.Group_.INLINE_;
    -      }
    -      if (groups & canContain) {
    -        return i + 1;
    -      }
    -    }
    -    return 0;
    -  }
    -};
    -
    -
    -/**
    - * The groups into which the element falls.
    - * The default is an inline element.
    - * @private
    - */
    -goog.labs.html.scrubber.ELEMENT_GROUPS_ = {
    -  'a': goog.labs.html.scrubber.Group_.INLINE_,
    -  'abbr': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'acronym': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'address': goog.labs.html.scrubber.Group_.BLOCK_,
    -  'applet': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'area': goog.labs.html.scrubber.Group_.AREA_ELEMENT_,
    -  'audio': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'b': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'base': goog.labs.html.scrubber.Group_.HEAD_CONTENT_,
    -  'basefont': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'bdi': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'bdo': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'big': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'blink': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'blockquote': goog.labs.html.scrubber.Group_.BLOCK_,
    -  'body': goog.labs.html.scrubber.Group_.TOP_CONTENT_,
    -  'br': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'button': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'canvas': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'caption': goog.labs.html.scrubber.Group_.TABLE_CONTENT_,
    -  'center': goog.labs.html.scrubber.Group_.BLOCK_,
    -  'cite': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'code': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'col': goog.labs.html.scrubber.Group_.TABLE_CONTENT_ |
    -      goog.labs.html.scrubber.Group_.COL_ELEMENT_,
    -  'colgroup': goog.labs.html.scrubber.Group_.TABLE_CONTENT_,
    -  'dd': goog.labs.html.scrubber.Group_.DL_PART_,
    -  'del': goog.labs.html.scrubber.Group_.BLOCK_ |
    -      goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.MIXED_,
    -  'dfn': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'dir': goog.labs.html.scrubber.Group_.BLOCK_,
    -  'div': goog.labs.html.scrubber.Group_.BLOCK_,
    -  'dl': goog.labs.html.scrubber.Group_.BLOCK_,
    -  'dt': goog.labs.html.scrubber.Group_.DL_PART_,
    -  'em': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'fieldset': goog.labs.html.scrubber.Group_.BLOCK_,
    -  'font': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'form': goog.labs.html.scrubber.Group_.BLOCK_ |
    -      goog.labs.html.scrubber.Group_.FORM_ELEMENT_,
    -  'h1': goog.labs.html.scrubber.Group_.BLOCK_,
    -  'h2': goog.labs.html.scrubber.Group_.BLOCK_,
    -  'h3': goog.labs.html.scrubber.Group_.BLOCK_,
    -  'h4': goog.labs.html.scrubber.Group_.BLOCK_,
    -  'h5': goog.labs.html.scrubber.Group_.BLOCK_,
    -  'h6': goog.labs.html.scrubber.Group_.BLOCK_,
    -  'head': goog.labs.html.scrubber.Group_.TOP_CONTENT_,
    -  'hr': goog.labs.html.scrubber.Group_.BLOCK_,
    -  'html': 0,
    -  'i': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'iframe': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'img': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'input': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'ins': goog.labs.html.scrubber.Group_.BLOCK_ |
    -      goog.labs.html.scrubber.Group_.INLINE_,
    -  'isindex': goog.labs.html.scrubber.Group_.INLINE_,
    -  'kbd': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'label': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'legend': goog.labs.html.scrubber.Group_.LEGEND_ELEMENT_,
    -  'li': goog.labs.html.scrubber.Group_.LI_ELEMENT_,
    -  'link': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.HEAD_CONTENT_,
    -  'listing': goog.labs.html.scrubber.Group_.BLOCK_,
    -  'map': goog.labs.html.scrubber.Group_.INLINE_,
    -  'meta': goog.labs.html.scrubber.Group_.HEAD_CONTENT_,
    -  'nobr': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'noframes': goog.labs.html.scrubber.Group_.BLOCK_ |
    -      goog.labs.html.scrubber.Group_.TOP_CONTENT_,
    -  'noscript': goog.labs.html.scrubber.Group_.BLOCK_,
    -  'object': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_ |
    -      goog.labs.html.scrubber.Group_.HEAD_CONTENT_,
    -  'ol': goog.labs.html.scrubber.Group_.BLOCK_,
    -  'optgroup': goog.labs.html.scrubber.Group_.OPTIONS_ELEMENT_,
    -  'option': goog.labs.html.scrubber.Group_.OPTIONS_ELEMENT_ |
    -      goog.labs.html.scrubber.Group_.OPTION_ELEMENT_,
    -  'p': goog.labs.html.scrubber.Group_.BLOCK_ |
    -      goog.labs.html.scrubber.Group_.P_ELEMENT_,
    -  'param': goog.labs.html.scrubber.Group_.PARAM_ELEMENT_,
    -  'pre': goog.labs.html.scrubber.Group_.BLOCK_,
    -  'q': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  's': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'samp': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'script': (goog.labs.html.scrubber.Group_.BLOCK_ |
    -      goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_ |
    -      goog.labs.html.scrubber.Group_.MIXED_ |
    -      goog.labs.html.scrubber.Group_.TABLE_CONTENT_ |
    -      goog.labs.html.scrubber.Group_.HEAD_CONTENT_ |
    -      goog.labs.html.scrubber.Group_.TOP_CONTENT_ |
    -      goog.labs.html.scrubber.Group_.AREA_ELEMENT_ |
    -      goog.labs.html.scrubber.Group_.FORM_ELEMENT_ |
    -      goog.labs.html.scrubber.Group_.LEGEND_ELEMENT_ |
    -      goog.labs.html.scrubber.Group_.LI_ELEMENT_ |
    -      goog.labs.html.scrubber.Group_.DL_PART_ |
    -      goog.labs.html.scrubber.Group_.P_ELEMENT_ |
    -      goog.labs.html.scrubber.Group_.OPTIONS_ELEMENT_ |
    -      goog.labs.html.scrubber.Group_.OPTION_ELEMENT_ |
    -      goog.labs.html.scrubber.Group_.PARAM_ELEMENT_ |
    -      goog.labs.html.scrubber.Group_.TABLE_ELEMENT_ |
    -      goog.labs.html.scrubber.Group_.TR_ELEMENT_ |
    -      goog.labs.html.scrubber.Group_.TD_ELEMENT_ |
    -      goog.labs.html.scrubber.Group_.COL_ELEMENT_),
    -  'select': goog.labs.html.scrubber.Group_.INLINE_,
    -  'small': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'span': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'strike': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'strong': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'style': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.HEAD_CONTENT_,
    -  'sub': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'sup': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'table': goog.labs.html.scrubber.Group_.BLOCK_ |
    -      goog.labs.html.scrubber.Group_.TABLE_ELEMENT_,
    -  'tbody': goog.labs.html.scrubber.Group_.TABLE_CONTENT_,
    -  'td': goog.labs.html.scrubber.Group_.TD_ELEMENT_,
    -  'textarea': goog.labs.html.scrubber.Group_.INLINE_,
    -  'tfoot': goog.labs.html.scrubber.Group_.TABLE_CONTENT_,
    -  'th': goog.labs.html.scrubber.Group_.TD_ELEMENT_,
    -  'thead': goog.labs.html.scrubber.Group_.TABLE_CONTENT_,
    -  'title': goog.labs.html.scrubber.Group_.HEAD_CONTENT_,
    -  'tr': goog.labs.html.scrubber.Group_.TABLE_CONTENT_ |
    -      goog.labs.html.scrubber.Group_.TR_ELEMENT_,
    -  'tt': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'u': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'ul': goog.labs.html.scrubber.Group_.BLOCK_,
    -  'var': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'video': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'wbr': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'xmp': goog.labs.html.scrubber.Group_.BLOCK_
    -};
    -
    -
    -/**
    - * The groups which the element can contain.
    - * Defaults to 0.
    - * @private
    - */
    -goog.labs.html.scrubber.ELEMENT_CONTENTS_ = {
    -  'a': goog.labs.html.scrubber.Group_.INLINE_MINUS_A_,
    -  'abbr': goog.labs.html.scrubber.Group_.INLINE_,
    -  'acronym': goog.labs.html.scrubber.Group_.INLINE_,
    -  'address': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.P_ELEMENT_,
    -  'applet': goog.labs.html.scrubber.Group_.BLOCK_ |
    -      goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.PARAM_ELEMENT_,
    -  'b': goog.labs.html.scrubber.Group_.INLINE_,
    -  'bdi': goog.labs.html.scrubber.Group_.INLINE_,
    -  'bdo': goog.labs.html.scrubber.Group_.INLINE_,
    -  'big': goog.labs.html.scrubber.Group_.INLINE_,
    -  'blink': goog.labs.html.scrubber.Group_.INLINE_,
    -  'blockquote': goog.labs.html.scrubber.Group_.BLOCK_ |
    -      goog.labs.html.scrubber.Group_.INLINE_,
    -  'body': goog.labs.html.scrubber.Group_.BLOCK_ |
    -      goog.labs.html.scrubber.Group_.INLINE_,
    -  'button': goog.labs.html.scrubber.Group_.BLOCK_ |
    -      goog.labs.html.scrubber.Group_.INLINE_,
    -  'canvas': goog.labs.html.scrubber.Group_.INLINE_,
    -  'caption': goog.labs.html.scrubber.Group_.INLINE_,
    -  'center': goog.labs.html.scrubber.Group_.BLOCK_ |
    -      goog.labs.html.scrubber.Group_.INLINE_,
    -  'cite': goog.labs.html.scrubber.Group_.INLINE_,
    -  'code': goog.labs.html.scrubber.Group_.INLINE_,
    -  'colgroup': goog.labs.html.scrubber.Group_.COL_ELEMENT_,
    -  'dd': goog.labs.html.scrubber.Group_.BLOCK_ |
    -      goog.labs.html.scrubber.Group_.INLINE_,
    -  'del': goog.labs.html.scrubber.Group_.BLOCK_ |
    -      goog.labs.html.scrubber.Group_.INLINE_,
    -  'dfn': goog.labs.html.scrubber.Group_.INLINE_,
    -  'dir': goog.labs.html.scrubber.Group_.LI_ELEMENT_,
    -  'div': goog.labs.html.scrubber.Group_.BLOCK_ |
    -      goog.labs.html.scrubber.Group_.INLINE_,
    -  'dl': goog.labs.html.scrubber.Group_.DL_PART_,
    -  'dt': goog.labs.html.scrubber.Group_.INLINE_,
    -  'em': goog.labs.html.scrubber.Group_.INLINE_,
    -  'fieldset': goog.labs.html.scrubber.Group_.BLOCK_ |
    -      goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.LEGEND_ELEMENT_,
    -  'font': goog.labs.html.scrubber.Group_.INLINE_,
    -  'form': (goog.labs.html.scrubber.Group_.BLOCK_ |
    -      goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.INLINE_MINUS_A_ |
    -      goog.labs.html.scrubber.Group_.TR_ELEMENT_ |
    -      goog.labs.html.scrubber.Group_.TD_ELEMENT_),
    -  'h1': goog.labs.html.scrubber.Group_.INLINE_,
    -  'h2': goog.labs.html.scrubber.Group_.INLINE_,
    -  'h3': goog.labs.html.scrubber.Group_.INLINE_,
    -  'h4': goog.labs.html.scrubber.Group_.INLINE_,
    -  'h5': goog.labs.html.scrubber.Group_.INLINE_,
    -  'h6': goog.labs.html.scrubber.Group_.INLINE_,
    -  'head': goog.labs.html.scrubber.Group_.HEAD_CONTENT_,
    -  'html': goog.labs.html.scrubber.Group_.TOP_CONTENT_,
    -  'i': goog.labs.html.scrubber.Group_.INLINE_,
    -  'iframe': goog.labs.html.scrubber.Group_.BLOCK_ |
    -      goog.labs.html.scrubber.Group_.INLINE_,
    -  'ins': goog.labs.html.scrubber.Group_.BLOCK_ |
    -      goog.labs.html.scrubber.Group_.INLINE_,
    -  'kbd': goog.labs.html.scrubber.Group_.INLINE_,
    -  'label': goog.labs.html.scrubber.Group_.INLINE_,
    -  'legend': goog.labs.html.scrubber.Group_.INLINE_,
    -  'li': goog.labs.html.scrubber.Group_.BLOCK_ |
    -      goog.labs.html.scrubber.Group_.INLINE_,
    -  'listing': goog.labs.html.scrubber.Group_.INLINE_,
    -  'map': goog.labs.html.scrubber.Group_.BLOCK_ |
    -      goog.labs.html.scrubber.Group_.AREA_ELEMENT_,
    -  'nobr': goog.labs.html.scrubber.Group_.INLINE_,
    -  'noframes': goog.labs.html.scrubber.Group_.BLOCK_ |
    -      goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.TOP_CONTENT_,
    -  'noscript': goog.labs.html.scrubber.Group_.BLOCK_ |
    -      goog.labs.html.scrubber.Group_.INLINE_,
    -  'object': goog.labs.html.scrubber.Group_.BLOCK_ |
    -      goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.PARAM_ELEMENT_,
    -  'ol': goog.labs.html.scrubber.Group_.LI_ELEMENT_,
    -  'optgroup': goog.labs.html.scrubber.Group_.OPTIONS_ELEMENT_,
    -  'option': goog.labs.html.scrubber.Group_.CHARACTER_DATA_,
    -  'p': goog.labs.html.scrubber.Group_.INLINE_ |
    -      goog.labs.html.scrubber.Group_.TABLE_ELEMENT_,
    -  'pre': goog.labs.html.scrubber.Group_.INLINE_,
    -  'q': goog.labs.html.scrubber.Group_.INLINE_,
    -  's': goog.labs.html.scrubber.Group_.INLINE_,
    -  'samp': goog.labs.html.scrubber.Group_.INLINE_,
    -  'script': goog.labs.html.scrubber.Group_.CHARACTER_DATA_,
    -  'select': goog.labs.html.scrubber.Group_.OPTIONS_ELEMENT_,
    -  'small': goog.labs.html.scrubber.Group_.INLINE_,
    -  'span': goog.labs.html.scrubber.Group_.INLINE_,
    -  'strike': goog.labs.html.scrubber.Group_.INLINE_,
    -  'strong': goog.labs.html.scrubber.Group_.INLINE_,
    -  'style': goog.labs.html.scrubber.Group_.CHARACTER_DATA_,
    -  'sub': goog.labs.html.scrubber.Group_.INLINE_,
    -  'sup': goog.labs.html.scrubber.Group_.INLINE_,
    -  'table': goog.labs.html.scrubber.Group_.TABLE_CONTENT_ |
    -      goog.labs.html.scrubber.Group_.FORM_ELEMENT_,
    -  'tbody': goog.labs.html.scrubber.Group_.TR_ELEMENT_,
    -  'td': goog.labs.html.scrubber.Group_.BLOCK_ |
    -      goog.labs.html.scrubber.Group_.INLINE_,
    -  'textarea': goog.labs.html.scrubber.Group_.CHARACTER_DATA_,
    -  'tfoot': goog.labs.html.scrubber.Group_.FORM_ELEMENT_ |
    -      goog.labs.html.scrubber.Group_.TR_ELEMENT_ |
    -      goog.labs.html.scrubber.Group_.TD_ELEMENT_,
    -  'th': goog.labs.html.scrubber.Group_.BLOCK_ |
    -      goog.labs.html.scrubber.Group_.INLINE_,
    -  'thead': goog.labs.html.scrubber.Group_.FORM_ELEMENT_ |
    -      goog.labs.html.scrubber.Group_.TR_ELEMENT_ |
    -      goog.labs.html.scrubber.Group_.TD_ELEMENT_,
    -  'title': goog.labs.html.scrubber.Group_.CHARACTER_DATA_,
    -  'tr': goog.labs.html.scrubber.Group_.FORM_ELEMENT_ |
    -      goog.labs.html.scrubber.Group_.TD_ELEMENT_,
    -  'tt': goog.labs.html.scrubber.Group_.INLINE_,
    -  'u': goog.labs.html.scrubber.Group_.INLINE_,
    -  'ul': goog.labs.html.scrubber.Group_.LI_ELEMENT_,
    -  'var': goog.labs.html.scrubber.Group_.INLINE_,
    -  'xmp': goog.labs.html.scrubber.Group_.INLINE_
    -};
    -
    -
    -/**
    - * The scopes in which an element falls.
    - * No property defaults to 0.
    - * @private
    - */
    -goog.labs.html.scrubber.ELEMENT_SCOPES_ = {
    -  'applet': goog.labs.html.scrubber.Scope_.COMMON_ |
    -      goog.labs.html.scrubber.Scope_.BUTTON_ |
    -      goog.labs.html.scrubber.Scope_.LIST_ITEM_,
    -  'button': goog.labs.html.scrubber.Scope_.BUTTON_,
    -  'caption': goog.labs.html.scrubber.Scope_.COMMON_ |
    -      goog.labs.html.scrubber.Scope_.BUTTON_ |
    -      goog.labs.html.scrubber.Scope_.LIST_ITEM_,
    -  'html': goog.labs.html.scrubber.Scope_.COMMON_ |
    -      goog.labs.html.scrubber.Scope_.BUTTON_ |
    -      goog.labs.html.scrubber.Scope_.LIST_ITEM_ |
    -      goog.labs.html.scrubber.Scope_.TABLE_,
    -  'object': goog.labs.html.scrubber.Scope_.COMMON_ |
    -      goog.labs.html.scrubber.Scope_.BUTTON_ |
    -      goog.labs.html.scrubber.Scope_.LIST_ITEM_,
    -  'ol': goog.labs.html.scrubber.Scope_.LIST_ITEM_,
    -  'table': goog.labs.html.scrubber.Scope_.COMMON_ |
    -      goog.labs.html.scrubber.Scope_.BUTTON_ |
    -      goog.labs.html.scrubber.Scope_.LIST_ITEM_ |
    -      goog.labs.html.scrubber.Scope_.TABLE_,
    -  'td': goog.labs.html.scrubber.Scope_.COMMON_ |
    -      goog.labs.html.scrubber.Scope_.BUTTON_ |
    -      goog.labs.html.scrubber.Scope_.LIST_ITEM_,
    -  'th': goog.labs.html.scrubber.Scope_.COMMON_ |
    -      goog.labs.html.scrubber.Scope_.BUTTON_ |
    -      goog.labs.html.scrubber.Scope_.LIST_ITEM_,
    -  'ul': goog.labs.html.scrubber.Scope_.LIST_ITEM_
    -};
    -
    -
    -/**
    - * Per-element, a child that can contain block content.
    - * @private
    - */
    -goog.labs.html.scrubber.BLOCK_CONTAINERS_ = {
    -  'dl': 'dd',
    -  'ol': 'li',
    -  'table': 'tr',
    -  'tr': 'td',
    -  'ul': 'li'
    -};
    -
    -
    -goog.labs.html.attributeRewriterPresubmitWorkaround();
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/html/scrubber_test.js b/src/database/third_party/closure-library/closure/goog/labs/html/scrubber_test.js
    deleted file mode 100644
    index c2689927718..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/html/scrubber_test.js
    +++ /dev/null
    @@ -1,254 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -goog.provide('goog.html.ScrubberTest');
    -
    -goog.require('goog.labs.html.scrubber');
    -goog.require('goog.object');
    -goog.require('goog.string');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.html.ScrubberTest');
    -
    -
    -
    -var tagWhitelist = goog.object.createSet(
    -    'a', 'b', 'i', 'p', 'font', 'hr', 'br', 'span',
    -    'ol', 'ul', 'li',
    -    'table', 'tr', 'td', 'th', 'tbody',
    -    'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
    -    'img',
    -    'html', 'head', 'body', 'title');
    -
    -var attrWhitelist = {
    -  // On any element,
    -  '*': {
    -    // allow unfiltered title attributes, and
    -    'title': function(title) { return title; },
    -    // specific dir values.
    -    'dir': function(dir) {
    -      return dir === 'ltr' || dir === 'rtl' ? dir : null;
    -    }
    -  },
    -  // Specifically on <a> elements,
    -  'a': {
    -    // allow an href but verify and rewrite, and
    -    'href': function(href) {
    -      return /^https?:\/\/google\.[a-z]{2,3}\/search\?/.test(href) ?
    -          href.replace(/[^A-Za-z0-9_\-.~:\/?#\[\]@!\$&()*+,;=%]+/,
    -                       encodeURIComponent) :
    -          null;
    -    },
    -    // mask the generic title handler for no good reason.
    -    'title': function(title) { return '<' + title + '>'; }
    -  }
    -};
    -
    -
    -function run(input, golden, desc) {
    -  var actual = goog.labs.html.scrubber.scrub(
    -      tagWhitelist, attrWhitelist, input);
    -  assertEquals(desc, golden, actual);
    -}
    -
    -
    -function testEmptyString() {
    -  run('', '', 'Empty string');
    -}
    -
    -function testHelloWorld() {
    -  run('Hello, <b>World</b>!', 'Hello, <b>World</b>!',
    -      'Hello World');
    -}
    -
    -function testNoEndTag() {
    -  run('<i>Hello, <b>World!',
    -      '<i>Hello, <b>World!</b></i>',
    -      'Hello World no end tag');
    -}
    -
    -function testUnclosedTags() {
    -  run('<html><head><title>Hello, <<World>>!</TITLE>' +
    -      '</head><body><p>Hello,<Br><<World>>!',
    -      '<html><head><title>Hello, <<World>>!</title>' +
    -      '</head><body><p>Hello,<br>&lt;&gt;!</p></body></html>',
    -      'RCDATA content, different case, unclosed tags');
    -}
    -
    -function testListInList() {
    -  run('<ul><li>foo</li><ul><li>bar</li></ul></ul>',
    -      '<ul><li>foo</li><li><ul><li>bar</li></ul></li></ul>',
    -      'list in list directly');
    -}
    -
    -function testHeaders() {
    -  run('<h1>header</h1>body' +
    -      '<H2>sub-header</h3>sub-body' +
    -      '<h3>sub-sub-</hr>header<hr></hr>sub-sub-body</H4></h2>',
    -      '<h1>header</h1>body' +
    -      '<h2>sub-header</h2>sub-body' +
    -      '<h3>sub-sub-header</h3><hr>sub-sub-body',
    -      'headers');
    -}
    -
    -function testListNesting() {
    -  run('<ul><li><ul><li>foo</li></li><ul><li>bar',
    -      '<ul><li><ul><li>foo</li><li><ul><li>bar</li></ul></li></ul></li></ul>',
    -      'list nesting');
    -}
    -
    -function testTableNesting() {
    -  run('<table><tbody><tr><td>foo</td><table><tbody><tr><th>bar</table></table>',
    -      '<table><tbody><tr><td>foo</td><td>' +
    -      '<table><tbody><tr><th>bar</th></tr></tbody></table>' +
    -      '</td></tr></tbody></table>',
    -      'table nesting');
    -}
    -
    -function testNestingLimit() {
    -  run(goog.string.repeat('<span>', 264) + goog.string.repeat('</span>', 264),
    -      goog.string.repeat('<span>', 256) + goog.string.repeat('</span>', 256),
    -      '264 open spans');
    -}
    -
    -function testTableScopes() {
    -  run('<html><head></head><body><p>Hi</p><p>How are you</p>\n' +
    -      '<p><table><tbody><tr>' +
    -      '<td><b><font><font><p>Cell</b></font></font></p>\n</td>' +
    -      '<td><b><font><font><p>Cell</b></font></font></p>\n</td>' +
    -      '</tr></tbody></table></p>\n' +
    -      '<p>x</p></body></html>',
    -
    -      '<html><head></head><body><p>Hi</p><p>How are you</p>\n' +
    -      '<p><table><tbody><tr>' +
    -      '<td><b><font><font></font></font></b><p>Cell</p>\n</td>' +
    -      // The close </p> tag does not close the whole table. +
    -      '<td><b><font><font></font></font></b><p>Cell</p>\n</td>' +
    -      '</tr></tbody></table></p>\n' +
    -      '<p>x</p></body></html>',
    -
    -      'Table Scopes');
    -}
    -
    -function testConcatSafe() {
    -  run('<<applet>script<applet>>alert(1337)<<!-- -->/script<?...?>>',
    -      '&lt;script&gt;alert(1337)&lt;/script&gt;',
    -      'Concat safe');
    -}
    -
    -function testPrototypeMembersDoNotInfectTables() {
    -  // Constructor is all lower-case so will survive tag name
    -  // normalization.
    -  run('<constructor>Foo</constructor>', 'Foo',
    -      'Object.prototype members');
    -}
    -
    -function testGenericAttributesAllowed() {
    -  run('<span title=howdy></span>', '<span title="howdy"></span>',
    -      'generic attrs allowed');
    -}
    -
    -function testValueWhitelisting() {
    -  run('<span dir=\'ltr\'>LTR</span><span dir=\'evil\'>Evil</span>',
    -      '<span dir="ltr">LTR</span><span>Evil</span>',
    -      'value whitelisted');
    -}
    -
    -function testAttributeNormalization() {
    -  run('<a href="http://google.com/search?q=tests suxor&hl=en">Click</a>',
    -      '<a href="http://google.com/search?q=tests%20suxor&amp;hl=en">Click</a>',
    -      'URL normalized');
    -}
    -
    -function testTagSpecificityOfAttributeFiltering() {
    -  run('<img href="http://google.com/search?q=tests+suxor">',
    -      '<img>',
    -      'href blocked on img');
    -}
    -
    -function testTagSpecificAttributeFiltering() {
    -  run('<a href="http://google.evil.com/search?q=tests suxor">Unclicky</a>',
    -      '<a>Unclicky</a>',
    -      'bad href value blocked');
    -}
    -
    -function testNonWhitelistFunctionsNotCalled() {
    -  var called = false;
    -  Object.prototype.dontcallme = function() {
    -    called = true;
    -    return 'dontcallme was called despite being on the prototype';
    -  };
    -  try {
    -    run('<span dontcallme="I\'ll call you">Lorem Ipsum',
    -        '<span>Lorem Ipsum</span>',
    -        'non white-list fn not called');
    -  } finally {
    -    delete Object.prototype.dontcallme;
    -  }
    -  assertFalse('Object.prototype.dontcallme should not have been called',
    -              called);
    -}
    -
    -function testQuotesInAttributeValue() {
    -  run('<span tItlE =\n\'Quoth the raven, "Nevermore"\'>Lorem Ipsum',
    -      '<span title="Quoth the raven, &quot;Nevermore&quot;">Lorem Ipsum</span>',
    -      'quotes in attr value');
    -}
    -
    -function testAttributesNeverMentionedAreDropped() {
    -  run('<b onclick="evil=true">evil</b>', '<b>evil</b>', 'attrs white-listed');
    -}
    -
    -function testAttributesNotOverEscaped() {
    -  run('<I TITLE="Foo &AMP; Bar & Baz">/</I>',
    -      '<i title="Foo &amp; Bar &amp; Baz">/</i>',
    -      'attr value not over-escaped');
    -}
    -
    -function testTagSpecificRulesTakePrecedence() {
    -  run('<a title=zogberts>Link</a>',
    -      '<a title="&lt;zogberts&gt;">Link</a>',
    -      'tag specific rules take precedence');
    -}
    -
    -function testAttributeRejectionLocalized() {
    -  run('<a id=foo href =//evil.org/ title=>Link</a>',
    -      '<a title="&lt;&gt;">Link</a>',
    -      'failure of one attribute does not torpedo others');
    -}
    -
    -function testWeirdHtmlRulesFollowedForAttrValues() {
    -  run('<span title= id=>Lorem Ipsum</span>',
    -      '<span title=\"id=\">Lorem Ipsum</span>',
    -      'same as browser on weird values');
    -}
    -
    -function testAttributesDisallowedOnCloseTags() {
    -  run('<h1 title="open">Header</h1 title="closed">',
    -      '<h1 title="open">Header</h1>',
    -      'attributes on close tags');
    -}
    -
    -function testRoundTrippingOfHtmlSafeAgainstIEBacktickProblems() {
    -  // Introducing a space at the end of an attribute forces IE to quote it when
    -  // turning a DOM into innerHTML which protects against a bunch of problems
    -  // with backticks since IE treats them as attribute value delimiters, allowing
    -  //   foo.innerHTML += ...
    -  // to continue to "work" without introducing an XSS vector.
    -  // Adding a space at the end is innocuous since HTML attributes whose values
    -  // are structured content ignore spaces at the beginning or end.
    -  run('<span title="`backtick">*</span>', '<span title="`backtick ">*</span>',
    -      'not round-trippable on IE');
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/i18n/listformat.js b/src/database/third_party/closure-library/closure/goog/labs/i18n/listformat.js
    deleted file mode 100644
    index aba373fff0f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/i18n/listformat.js
    +++ /dev/null
    @@ -1,261 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview List format and gender decision library with locale support.
    - *
    - * ListFormat takes an array or a var_arg of objects and generates a user
    - * friendly list in a locale-sensitive way (i.e. "red, green, and blue").
    - *
    - * GenderInfo can be used to determine the gender of a list of items,
    - * depending on the gender of all items in the list.
    - *
    - * In English, lists of items don't really have gender, and in fact few things
    - * have gender. But the idea is this:
    - *  - for a list of "male items" (think "John, Steve") you use "they"
    - *  - for "Marry, Ann" (all female) you might have a "feminine" form of "they"
    - *  - and yet another form for mixed lists ("John, Marry") or undetermined
    - *    (when you don't know the gender of the items, or when they are neuter)
    - *
    - * For example in Greek "they" will be translated as "αυτοί" for masculin,
    - * "αυτές" for feminin, and "αυτά" for neutral/undetermined.
    - * (it is in fact more complicated than that, as weak/strong forms and case
    - * also matter, see http://en.wiktionary.org/wiki/Appendix:Greek_pronouns)
    - *
    - */
    -
    -goog.provide('goog.labs.i18n.GenderInfo');
    -goog.provide('goog.labs.i18n.GenderInfo.Gender');
    -goog.provide('goog.labs.i18n.ListFormat');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.labs.i18n.ListFormatSymbols');
    -
    -
    -
    -/**
    - * ListFormat provides a method to format a list/array of objects to a string,
    - * in a user friendly way and in a locale sensitive manner.
    - * If the objects are not strings, toString is called to convert them.
    - * The constructor initializes the object based on the locale data from
    - * the current goog.labs.i18n.ListFormatSymbols.
    - *
    - * Similar to the ICU4J class com.ibm.icu.text.ListFormatter:
    - *   http://icu-project.org/apiref/icu4j/com/ibm/icu/text/ListFormatter.html
    - * @constructor
    - * @final
    - */
    -goog.labs.i18n.ListFormat = function() {
    -  /**
    -   * String for lists of exactly two items, containing {0} for the first,
    -   * and {1} for the second.
    -   * For instance '{0} and {1}' will give 'black and white'.
    -   * @private {string}
    -   *
    -   * Example: for "black and white" the pattern is "{0} and {1}"
    -   * While for a longer list we have "cyan, magenta, yellow, and black"
    -   * Think "{0} start {1} middle {2} middle {3} end {4}"
    -   * The last pattern is "{0}, and {1}." Note the comma before "and".
    -   * So the "Two" pattern can be different than Start/Middle/End ones.
    -   */
    -  this.listTwoPattern_ = goog.labs.i18n.ListFormatSymbols.LIST_TWO;
    -
    -  /**
    -   * String for the start of a list items, containing {0} for the first,
    -   * and {1} for the rest.
    -   * @private {string}
    -   */
    -  this.listStartPattern_ = goog.labs.i18n.ListFormatSymbols.LIST_START;
    -
    -  /**
    -   * String for the start of a list items, containing {0} for the first part
    -   * of the list, and {1} for the rest of the list.
    -   * @private {string}
    -   */
    -  this.listMiddlePattern_ = goog.labs.i18n.ListFormatSymbols.LIST_MIDDLE;
    -
    -  /**
    -   * String for the end of a list items, containing {0} for the first part
    -   * of the list, and {1} for the last item.
    -   *
    -   * This is how start/middle/end come together:
    -   *   start = '{0}, {1}'  middle = '{0}, {1}',  end = '{0}, and {1}'
    -   * will result in the typical English list: 'one, two, three, and four'
    -   * There are languages where the patterns are more complex than
    -   * '{1} someText {1}' and the start pattern is different than the middle one.
    -   *
    -   * @private {string}
    -   */
    -  this.listEndPattern_ = goog.labs.i18n.ListFormatSymbols.LIST_END;
    -};
    -
    -
    -/**
    - * Replaces the {0} and {1} placeholders in a pattern with the first and
    - * the second parameter respectively, and returns the result.
    - * It is a helper function for goog.labs.i18n.ListFormat.format.
    - *
    - * @param {string} pattern used for formatting.
    - * @param {string} first object to add to list.
    - * @param {string} second object to add to list.
    - * @return {string} The formatted list string.
    - * @private
    - */
    -goog.labs.i18n.ListFormat.prototype.patternBasedJoinTwoStrings_ =
    -    function(pattern, first, second) {
    -  return pattern.replace('{0}', first).replace('{1}', second);
    -};
    -
    -
    -/**
    - * Formats an array of strings into a string.
    - * It is a user facing, locale-aware list (i.e. 'red, green, and blue').
    - *
    - * @param {!Array<string|number>} items Items to format.
    - * @return {string} The items formatted into a string, as a list.
    - */
    -goog.labs.i18n.ListFormat.prototype.format = function(items) {
    -  var count = items.length;
    -  switch (count) {
    -    case 0:
    -      return '';
    -    case 1:
    -      return String(items[0]);
    -    case 2:
    -      return this.patternBasedJoinTwoStrings_(this.listTwoPattern_,
    -          String(items[0]), String(items[1]));
    -  }
    -
    -  var result = this.patternBasedJoinTwoStrings_(this.listStartPattern_,
    -      String(items[0]), String(items[1]));
    -
    -  for (var i = 2; i < count - 1; ++i) {
    -    result = this.patternBasedJoinTwoStrings_(this.listMiddlePattern_,
    -        result, String(items[i]));
    -  }
    -
    -  return this.patternBasedJoinTwoStrings_(this.listEndPattern_,
    -      result, String(items[count - 1]));
    -};
    -
    -
    -
    -/**
    - * GenderInfo provides a method to determine the gender of a list/array
    - * of objects when one knows the gender of each item of the list.
    - * It does this in a locale sensitive manner.
    - * The constructor initializes the object based on the locale data from
    - * the current goog.labs.i18n.ListFormatSymbols.
    - *
    - * Similar to the ICU4J class com.icu.util.GenderInfo:
    - *   http://icu-project.org/apiref/icu4j/com/ibm/icu/util/GenderInfo.html
    - * @constructor
    - * @final
    - */
    -goog.labs.i18n.GenderInfo = function() {
    -  /**
    -   * Stores the language-aware mode of determining the gender of a list.
    -   * @private {goog.labs.i18n.GenderInfo.ListGenderStyle_}
    -   */
    -  this.listGenderStyle_ = goog.labs.i18n.ListFormatSymbols.GENDER_STYLE;
    -};
    -
    -
    -/**
    - * Enumeration for the possible ways to generate list genders.
    - * Indicates the category for the locale.
    - * This only affects gender for lists more than one. For lists of 1 item,
    - * the gender of the list always equals the gender of that sole item.
    - * This is for internal use, matching ICU.
    - * @enum {number}
    - * @private
    - */
    -goog.labs.i18n.GenderInfo.ListGenderStyle_ = {
    -  NEUTRAL: 0,
    -  MIXED_NEUTRAL: 1,
    -  MALE_TAINTS: 2
    -};
    -
    -
    -/**
    - * Enumeration for the possible gender values.
    - * Gender: OTHER means either the information is unavailable,
    - * or the person has declined to state MALE or FEMALE.
    - * @enum {number}
    - */
    -goog.labs.i18n.GenderInfo.Gender = {
    -  MALE: 0,
    -  FEMALE: 1,
    -  OTHER: 2
    -};
    -
    -
    -/**
    - * Determines the overal gender of a list based on the gender of all the list
    - * items, in a locale-aware way.
    - * @param {!Array<!goog.labs.i18n.GenderInfo.Gender>} genders An array of
    - *        genders, will give the gender of the list.
    - * @return {goog.labs.i18n.GenderInfo.Gender} Get the gender of the list.
    -*/
    -goog.labs.i18n.GenderInfo.prototype.getListGender = function(genders) {
    -  var Gender = goog.labs.i18n.GenderInfo.Gender;
    -
    -  var count = genders.length;
    -  if (count == 0) {
    -    return Gender.OTHER; // degenerate case
    -  }
    -  if (count == 1) {
    -    return genders[0]; // degenerate case
    -  }
    -
    -  switch (this.listGenderStyle_) {
    -    case goog.labs.i18n.GenderInfo.ListGenderStyle_.NEUTRAL:
    -      return Gender.OTHER;
    -    case goog.labs.i18n.GenderInfo.ListGenderStyle_.MIXED_NEUTRAL:
    -      var hasFemale = false;
    -      var hasMale = false;
    -      for (var i = 0; i < count; ++i) {
    -        switch (genders[i]) {
    -          case Gender.FEMALE:
    -            if (hasMale) {
    -              return Gender.OTHER;
    -            }
    -            hasFemale = true;
    -            break;
    -          case Gender.MALE:
    -            if (hasFemale) {
    -              return Gender.OTHER;
    -            }
    -            hasMale = true;
    -            break;
    -          case Gender.OTHER:
    -            return Gender.OTHER;
    -          default: // Should never happen, but just in case
    -            goog.asserts.assert(false,
    -                'Invalid genders[' + i + '] = ' + genders[i]);
    -            return Gender.OTHER;
    -        }
    -      }
    -      return hasMale ? Gender.MALE : Gender.FEMALE;
    -    case goog.labs.i18n.GenderInfo.ListGenderStyle_.MALE_TAINTS:
    -      for (var i = 0; i < count; ++i) {
    -        if (genders[i] != Gender.FEMALE) {
    -          return Gender.MALE;
    -        }
    -      }
    -      return Gender.FEMALE;
    -    default:
    -      return Gender.OTHER;
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/i18n/listformat_test.html b/src/database/third_party/closure-library/closure/goog/labs/i18n/listformat_test.html
    deleted file mode 100644
    index c85ea9cf298..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/i18n/listformat_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.labs.i18n.ListFormat
    -  </title>
    -  <meta charset="utf-8" />
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.labs.i18n.ListFormatTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/i18n/listformat_test.js b/src/database/third_party/closure-library/closure/goog/labs/i18n/listformat_test.js
    deleted file mode 100644
    index be52881894f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/i18n/listformat_test.js
    +++ /dev/null
    @@ -1,324 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.labs.i18n.ListFormatTest');
    -goog.setTestOnly('goog.labs.i18n.ListFormatTest');
    -
    -goog.require('goog.labs.i18n.GenderInfo');
    -goog.require('goog.labs.i18n.ListFormat');
    -goog.require('goog.labs.i18n.ListFormatSymbols');
    -goog.require('goog.labs.i18n.ListFormatSymbols_el');
    -goog.require('goog.labs.i18n.ListFormatSymbols_en');
    -goog.require('goog.labs.i18n.ListFormatSymbols_fr');
    -goog.require('goog.labs.i18n.ListFormatSymbols_ml');
    -goog.require('goog.labs.i18n.ListFormatSymbols_zu');
    -goog.require('goog.testing.jsunit');
    -
    -function setUp() {
    -  // Always switch back to English on startup.
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en;
    -}
    -
    -function testListFormatterArrayDirect() {
    -  var fmt = new goog.labs.i18n.ListFormat();
    -  assertEquals(
    -      'One',
    -      fmt.format(['One'])
    -  );
    -  assertEquals(
    -      'One and Two',
    -      fmt.format(['One', 'Two'])
    -  );
    -  assertEquals(
    -      'One, Two, and Three',
    -      fmt.format(['One', 'Two', 'Three'])
    -  );
    -  assertEquals(
    -      'One, Two, Three, Four, Five, and Six',
    -      fmt.format(['One', 'Two', 'Three', 'Four', 'Five', 'Six'])
    -  );
    -}
    -
    -function testListFormatterArrayIndirect() {
    -  var fmt = new goog.labs.i18n.ListFormat();
    -
    -  var items = [];
    -
    -  items.push('One');
    -  assertEquals('One', fmt.format(items));
    -
    -  items.push('Two');
    -  assertEquals('One and Two', fmt.format(items));
    -  items.push('Three');
    -  assertEquals('One, Two, and Three', fmt.format(items));
    -
    -  items.push('Four');
    -  items.push('Five');
    -  items.push('Six');
    -  assertEquals('One, Two, Three, Four, Five, and Six', fmt.format(items));
    -}
    -
    -function testListFormatterFrench() {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr;
    -
    -  var fmt = new goog.labs.i18n.ListFormat();
    -  assertEquals(
    -      'One',
    -      fmt.format(['One'])
    -  );
    -  assertEquals(
    -      'One et Two',
    -      fmt.format(['One', 'Two'])
    -  );
    -  assertEquals(
    -      'One, Two et Three',
    -      fmt.format(['One', 'Two', 'Three'])
    -  );
    -  assertEquals(
    -      'One, Two, Three, Four, Five et Six',
    -      fmt.format(['One', 'Two', 'Three', 'Four', 'Five', 'Six'])
    -  );
    -
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en;
    -}
    -
    -// Malayalam and Zulu are the only two locales with pathers
    -// different than '{0} sometext {1}'
    -function testListFormatterSpecialLanguages() {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ml;
    -  var fmt_ml = new goog.labs.i18n.ListFormat();
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_zu;
    -  var fmt_zu = new goog.labs.i18n.ListFormat();
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en;
    -
    -  // Only the end pattern is special with Malayalam
    -  // Escaped for safety, the string is 'One, Two, Three എന്നിവ'
    -  assertEquals('One, Two, Three \u0D0E\u0D28\u0D4D\u0D28\u0D3F\u0D35',
    -      fmt_ml.format(['One', 'Two', 'Three']));
    -
    -  // Only the two items pattern is special with Zulu
    -  assertEquals('I-One ne-Two', fmt_zu.format(['One', 'Two']));
    -}
    -
    -function testVariousObjectTypes() {
    -  var fmt = new goog.labs.i18n.ListFormat();
    -  var booleanObject = new Boolean(1);
    -  var arrayObject = ['black', 'white'];
    -  // Not sure how "flaky" this is. Firefox and Chrome give the same results,
    -  // but I am not sure if the JavaScript standard specifies exactly what
    -  // Array toString does, for instance.
    -  assertEquals(
    -      'One, black,white, 42, true, and Five',
    -      fmt.format(['One', arrayObject, 42, booleanObject, 'Five'])
    -  );
    -}
    -
    -function testListGendersNeutral() {
    -  var Gender = goog.labs.i18n.GenderInfo.Gender;
    -
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en;
    -  var listGen = new goog.labs.i18n.GenderInfo();
    -
    -  assertEquals(Gender.MALE, listGen.getListGender([Gender.MALE]));
    -  assertEquals(Gender.FEMALE, listGen.getListGender([Gender.FEMALE]));
    -  assertEquals(Gender.OTHER, listGen.getListGender([Gender.OTHER]));
    -
    -  assertEquals(Gender.OTHER, listGen.getListGender([Gender.MALE, Gender.MALE]));
    -  assertEquals(
    -      Gender.OTHER, listGen.getListGender([Gender.FEMALE, Gender.FEMALE]));
    -  assertEquals(
    -      Gender.OTHER, listGen.getListGender([Gender.OTHER, Gender.OTHER]));
    -
    -  assertEquals(
    -      Gender.OTHER, listGen.getListGender([Gender.MALE, Gender.OTHER]));
    -  assertEquals(
    -      Gender.OTHER, listGen.getListGender([Gender.OTHER, Gender.MALE]));
    -  assertEquals(
    -      Gender.OTHER, listGen.getListGender([Gender.MALE, Gender.FEMALE]));
    -  assertEquals(
    -      Gender.OTHER, listGen.getListGender([Gender.FEMALE, Gender.MALE]));
    -  assertEquals(
    -      Gender.OTHER, listGen.getListGender([Gender.OTHER, Gender.FEMALE]));
    -  assertEquals(
    -      Gender.OTHER, listGen.getListGender([Gender.FEMALE, Gender.OTHER]));
    -
    -  assertEquals(
    -      Gender.OTHER,
    -      listGen.getListGender([Gender.MALE, Gender.FEMALE, Gender.OTHER]));
    -  assertEquals(
    -      Gender.OTHER,
    -      listGen.getListGender([Gender.MALE, Gender.OTHER, Gender.FEMALE]));
    -  assertEquals(
    -      Gender.OTHER,
    -      listGen.getListGender([Gender.FEMALE, Gender.MALE, Gender.OTHER]));
    -  assertEquals(
    -      Gender.OTHER,
    -      listGen.getListGender([Gender.FEMALE, Gender.OTHER, Gender.MALE]));
    -  assertEquals(
    -      Gender.OTHER,
    -      listGen.getListGender([Gender.OTHER, Gender.MALE, Gender.FEMALE]));
    -  assertEquals(
    -      Gender.OTHER,
    -      listGen.getListGender([Gender.OTHER, Gender.FEMALE, Gender.MALE]));
    -}
    -
    -function testListGendersMaleTaints() {
    -  var Gender = goog.labs.i18n.GenderInfo.Gender;
    -
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr;
    -  var listGen = new goog.labs.i18n.GenderInfo();
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en;
    -
    -  assertEquals(Gender.MALE, listGen.getListGender([Gender.MALE]));
    -  assertEquals(Gender.FEMALE, listGen.getListGender([Gender.FEMALE]));
    -  assertEquals(Gender.OTHER, listGen.getListGender([Gender.OTHER]));
    -
    -  assertEquals(Gender.MALE, listGen.getListGender([Gender.MALE, Gender.MALE]));
    -  assertEquals(
    -      Gender.FEMALE, listGen.getListGender([Gender.FEMALE, Gender.FEMALE]));
    -  assertEquals(
    -      Gender.MALE, listGen.getListGender([Gender.OTHER, Gender.OTHER]));
    -
    -  assertEquals(Gender.MALE, listGen.getListGender([Gender.MALE, Gender.OTHER]));
    -  assertEquals(Gender.MALE, listGen.getListGender([Gender.OTHER, Gender.MALE]));
    -  assertEquals(
    -      Gender.MALE, listGen.getListGender([Gender.MALE, Gender.FEMALE]));
    -  assertEquals(
    -      Gender.MALE, listGen.getListGender([Gender.FEMALE, Gender.MALE]));
    -  assertEquals(
    -      Gender.MALE, listGen.getListGender([Gender.OTHER, Gender.FEMALE]));
    -  assertEquals(
    -      Gender.MALE, listGen.getListGender([Gender.FEMALE, Gender.OTHER]));
    -
    -  assertEquals(
    -      Gender.MALE,
    -      listGen.getListGender([Gender.MALE, Gender.FEMALE, Gender.OTHER]));
    -  assertEquals(
    -      Gender.MALE,
    -      listGen.getListGender([Gender.MALE, Gender.OTHER, Gender.FEMALE]));
    -  assertEquals(
    -      Gender.MALE,
    -      listGen.getListGender([Gender.FEMALE, Gender.MALE, Gender.OTHER]));
    -  assertEquals(
    -      Gender.MALE,
    -      listGen.getListGender([Gender.FEMALE, Gender.OTHER, Gender.MALE]));
    -  assertEquals(
    -      Gender.MALE,
    -      listGen.getListGender([Gender.OTHER, Gender.MALE, Gender.FEMALE]));
    -  assertEquals(
    -      Gender.MALE,
    -      listGen.getListGender([Gender.OTHER, Gender.FEMALE, Gender.MALE]));
    -}
    -
    -function testListGendersMixedNeutral() {
    -  var Gender = goog.labs.i18n.GenderInfo.Gender;
    -
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_el;
    -  var listGen = new goog.labs.i18n.GenderInfo();
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en;
    -
    -  assertEquals(Gender.MALE, listGen.getListGender([Gender.MALE]));
    -  assertEquals(Gender.FEMALE, listGen.getListGender([Gender.FEMALE]));
    -  assertEquals(Gender.OTHER, listGen.getListGender([Gender.OTHER]));
    -
    -  assertEquals(Gender.MALE, listGen.getListGender([Gender.MALE, Gender.MALE]));
    -  assertEquals(
    -      Gender.FEMALE, listGen.getListGender([Gender.FEMALE, Gender.FEMALE]));
    -  assertEquals(
    -      Gender.OTHER, listGen.getListGender([Gender.OTHER, Gender.OTHER]));
    -
    -  assertEquals(
    -      Gender.OTHER, listGen.getListGender([Gender.MALE, Gender.OTHER]));
    -  assertEquals(
    -      Gender.OTHER, listGen.getListGender([Gender.OTHER, Gender.MALE]));
    -  assertEquals(
    -      Gender.OTHER, listGen.getListGender([Gender.MALE, Gender.FEMALE]));
    -  assertEquals(
    -      Gender.OTHER, listGen.getListGender([Gender.FEMALE, Gender.MALE]));
    -  assertEquals(
    -      Gender.OTHER, listGen.getListGender([Gender.OTHER, Gender.FEMALE]));
    -  assertEquals(
    -      Gender.OTHER, listGen.getListGender([Gender.FEMALE, Gender.OTHER]));
    -
    -  assertEquals(
    -      Gender.OTHER,
    -      listGen.getListGender([Gender.MALE, Gender.FEMALE, Gender.OTHER]));
    -  assertEquals(
    -      Gender.OTHER,
    -      listGen.getListGender([Gender.MALE, Gender.OTHER, Gender.FEMALE]));
    -  assertEquals(
    -      Gender.OTHER,
    -      listGen.getListGender([Gender.FEMALE, Gender.MALE, Gender.OTHER]));
    -  assertEquals(
    -      Gender.OTHER,
    -      listGen.getListGender([Gender.FEMALE, Gender.OTHER, Gender.MALE]));
    -  assertEquals(
    -      Gender.OTHER,
    -      listGen.getListGender([Gender.OTHER, Gender.MALE, Gender.FEMALE]));
    -  assertEquals(
    -      Gender.OTHER,
    -      listGen.getListGender([Gender.OTHER, Gender.FEMALE, Gender.MALE]));
    -}
    -
    -function testListGendersVariousCallTypes() {
    -  var Gender = goog.labs.i18n.GenderInfo.Gender;
    -
    -  // Using French because with English the results are mostly Gender.OTHER
    -  // so we can detect fewer problems
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr;
    -  var listGen = new goog.labs.i18n.GenderInfo();
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en;
    -
    -  // Anynymous Arrays
    -  assertEquals(Gender.MALE, listGen.getListGender([Gender.MALE]));
    -  assertEquals(Gender.FEMALE, listGen.getListGender([Gender.FEMALE]));
    -  assertEquals(Gender.OTHER, listGen.getListGender([Gender.OTHER]));
    -
    -  assertEquals(Gender.MALE, listGen.getListGender([Gender.MALE, Gender.MALE]));
    -  assertEquals(
    -      Gender.FEMALE, listGen.getListGender([Gender.FEMALE, Gender.FEMALE]));
    -  assertEquals(
    -      Gender.MALE, listGen.getListGender([Gender.OTHER, Gender.OTHER]));
    -
    -  assertEquals(
    -      Gender.MALE, listGen.getListGender([Gender.MALE, Gender.FEMALE]));
    -  assertEquals(Gender.MALE, listGen.getListGender([Gender.MALE, Gender.OTHER]));
    -  assertEquals(
    -      Gender.MALE, listGen.getListGender([Gender.FEMALE, Gender.OTHER]));
    -
    -  // Arrays
    -  var arrayM = [Gender.MALE];
    -  var arrayF = [Gender.FEMALE];
    -  var arrayO = [Gender.OTHER];
    -
    -  var arrayMM = [Gender.MALE, Gender.MALE];
    -  var arrayFF = [Gender.FEMALE, Gender.FEMALE];
    -  var arrayOO = [Gender.OTHER, Gender.OTHER];
    -
    -  var arrayMF = [Gender.MALE, Gender.FEMALE];
    -  var arrayMO = [Gender.MALE, Gender.OTHER];
    -  var arrayFO = [Gender.FEMALE, Gender.OTHER];
    -
    -  assertEquals(Gender.MALE, listGen.getListGender(arrayM));
    -  assertEquals(Gender.FEMALE, listGen.getListGender(arrayF));
    -  assertEquals(Gender.OTHER, listGen.getListGender(arrayO));
    -
    -  assertEquals(Gender.MALE, listGen.getListGender(arrayMM));
    -  assertEquals(Gender.FEMALE, listGen.getListGender(arrayFF));
    -  assertEquals(Gender.MALE, listGen.getListGender(arrayOO));
    -
    -  assertEquals(Gender.MALE, listGen.getListGender(arrayMF));
    -  assertEquals(Gender.MALE, listGen.getListGender(arrayMO));
    -  assertEquals(Gender.MALE, listGen.getListGender(arrayFO));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/i18n/listsymbols.js b/src/database/third_party/closure-library/closure/goog/labs/i18n/listsymbols.js
    deleted file mode 100644
    index c62b1d80d7c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/i18n/listsymbols.js
    +++ /dev/null
    @@ -1,1796 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview List formatting symbols for all locales.
    - *
    - * This file is autogenerated by script.  See
    - * http://go/generate_list_symbols.py using --for_closure
    - * File generated from CLDR ver. 26
    - *
    - * To reduce the file size (which may cause issues in some JS
    - * developing environments), this file will only contain locales
    - * that are usually supported by Google products. It is a super
    - * set of 40 languages. The rest of the data can be found in another file
    - * named "listsymbolsext.js", which will be generated at the same
    - * time as this file.
    - * Before checkin, this file could have been manually edited. This is
    - * to incorporate changes before we could correct CLDR. All manual
    - * modification must be documented in this section, and should be
    - * removed after those changes land to CLDR.
    - */
    -
    -goog.provide('goog.labs.i18n.ListFormatSymbols');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_af');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_am');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ar');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_az');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_bg');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_bn');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_br');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ca');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_chr');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_cs');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_cy');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_da');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_de');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_de_AT');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_de_CH');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_el');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_AU');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_GB');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_IE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_IN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_SG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_US');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_ZA');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_es');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_es_419');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_es_ES');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_et');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_eu');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fa');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fi');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fil');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_CA');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ga');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_gl');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_gsw');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_gu');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_haw');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_he');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_hi');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_hr');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_hu');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_hy');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_id');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_in');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_is');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_it');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_iw');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ja');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ka');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_kk');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_km');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_kn');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ko');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ky');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ln');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_lo');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_lt');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_lv');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_mk');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ml');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_mn');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_mo');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_mr');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ms');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_mt');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_my');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_nb');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ne');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_nl');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_no');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_no_NO');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_or');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_pa');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_pl');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_pt');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_pt_BR');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_pt_PT');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ro');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ru');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sh');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_si');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sk');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sl');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sq');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sr');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sv');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sw');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ta');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_te');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_th');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_tl');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_tr');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_uk');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ur');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_uz');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_vi');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_zh');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_zh_CN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_zh_HK');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_zh_TW');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_zu');
    -
    -
    -/**
    - * List formatting symbols for locale af.
    - */
    -goog.labs.i18n.ListFormatSymbols_af = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} en {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} en {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale am.
    - */
    -goog.labs.i18n.ListFormatSymbols_am = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} እና {1}',
    -  LIST_START: '{0}፣ {1}',
    -  LIST_MIDDLE: '{0}፣ {1}',
    -  LIST_END: '{0}, እና {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ar.
    - */
    -goog.labs.i18n.ListFormatSymbols_ar = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale az.
    - */
    -goog.labs.i18n.ListFormatSymbols_az = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} və {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} və {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale bg.
    - */
    -goog.labs.i18n.ListFormatSymbols_bg = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} и {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} и {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale bn.
    - */
    -goog.labs.i18n.ListFormatSymbols_bn = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} এবং {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, এবং {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale br.
    - */
    -goog.labs.i18n.ListFormatSymbols_br = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ca.
    - */
    -goog.labs.i18n.ListFormatSymbols_ca = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} i {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} i {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale chr.
    - */
    -goog.labs.i18n.ListFormatSymbols_chr = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale cs.
    - */
    -goog.labs.i18n.ListFormatSymbols_cs = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} a {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} a {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale cy.
    - */
    -goog.labs.i18n.ListFormatSymbols_cy = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale da.
    - */
    -goog.labs.i18n.ListFormatSymbols_da = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} og {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} og {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale de.
    - */
    -goog.labs.i18n.ListFormatSymbols_de = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} und {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} und {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale de_AT.
    - */
    -goog.labs.i18n.ListFormatSymbols_de_AT = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} und {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} und {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale de_CH.
    - */
    -goog.labs.i18n.ListFormatSymbols_de_CH = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} und {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} und {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale el.
    - */
    -goog.labs.i18n.ListFormatSymbols_el = {
    -  GENDER_STYLE: 1,
    -  LIST_TWO: '{0} και {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} και {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en.
    - */
    -goog.labs.i18n.ListFormatSymbols_en = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_AU.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_AU = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_GB.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_GB = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_IE.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_IE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_IN.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_IN = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_SG.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_SG = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_US.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_US = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_ZA.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_ZA = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale es.
    - */
    -goog.labs.i18n.ListFormatSymbols_es = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} y {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} y {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale es_419.
    - */
    -goog.labs.i18n.ListFormatSymbols_es_419 = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} y {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} y {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale es_ES.
    - */
    -goog.labs.i18n.ListFormatSymbols_es_ES = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} y {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} y {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale et.
    - */
    -goog.labs.i18n.ListFormatSymbols_et = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} ja {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} ja {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale eu.
    - */
    -goog.labs.i18n.ListFormatSymbols_eu = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} eta {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} eta {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fa.
    - */
    -goog.labs.i18n.ListFormatSymbols_fa = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}،‏ {1}',
    -  LIST_MIDDLE: '{0}،‏ {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fi.
    - */
    -goog.labs.i18n.ListFormatSymbols_fi = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} ja {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} ja {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fil.
    - */
    -goog.labs.i18n.ListFormatSymbols_fil = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} at {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, at {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_CA.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_CA = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ga.
    - */
    -goog.labs.i18n.ListFormatSymbols_ga = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} agus {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, agus {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale gl.
    - */
    -goog.labs.i18n.ListFormatSymbols_gl = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} e {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} e {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale gsw.
    - */
    -goog.labs.i18n.ListFormatSymbols_gsw = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} und {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} und {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale gu.
    - */
    -goog.labs.i18n.ListFormatSymbols_gu = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} અને {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} અને {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale haw.
    - */
    -goog.labs.i18n.ListFormatSymbols_haw = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale he.
    - */
    -goog.labs.i18n.ListFormatSymbols_he = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} ו{1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} ו{1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale hi.
    - */
    -goog.labs.i18n.ListFormatSymbols_hi = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} और {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, और {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale hr.
    - */
    -goog.labs.i18n.ListFormatSymbols_hr = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} i {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} i {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale hu.
    - */
    -goog.labs.i18n.ListFormatSymbols_hu = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} és {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} és {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale hy.
    - */
    -goog.labs.i18n.ListFormatSymbols_hy = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} և {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} և {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale id.
    - */
    -goog.labs.i18n.ListFormatSymbols_id = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} dan {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, dan {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale in.
    - */
    -goog.labs.i18n.ListFormatSymbols_in = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} dan {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, dan {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale is.
    - */
    -goog.labs.i18n.ListFormatSymbols_is = {
    -  GENDER_STYLE: 1,
    -  LIST_TWO: '{0} og {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} og {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale it.
    - */
    -goog.labs.i18n.ListFormatSymbols_it = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} e {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} e {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale iw.
    - */
    -goog.labs.i18n.ListFormatSymbols_iw = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} ו{1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} ו{1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ja.
    - */
    -goog.labs.i18n.ListFormatSymbols_ja = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}、{1}',
    -  LIST_START: '{0}、{1}',
    -  LIST_MIDDLE: '{0}、{1}',
    -  LIST_END: '{0}、{1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ka.
    - */
    -goog.labs.i18n.ListFormatSymbols_ka = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} და {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} და {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale kk.
    - */
    -goog.labs.i18n.ListFormatSymbols_kk = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} және {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale km.
    - */
    -goog.labs.i18n.ListFormatSymbols_km = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} និង​{1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale kn.
    - */
    -goog.labs.i18n.ListFormatSymbols_kn = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} ಮತ್ತು {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, ಮತ್ತು {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ko.
    - */
    -goog.labs.i18n.ListFormatSymbols_ko = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} 및 {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} 및 {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ky.
    - */
    -goog.labs.i18n.ListFormatSymbols_ky = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} жана {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} жана {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ln.
    - */
    -goog.labs.i18n.ListFormatSymbols_ln = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale lo.
    - */
    -goog.labs.i18n.ListFormatSymbols_lo = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} ແລະ {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale lt.
    - */
    -goog.labs.i18n.ListFormatSymbols_lt = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} ir {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} ir {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale lv.
    - */
    -goog.labs.i18n.ListFormatSymbols_lv = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} un {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} un {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale mk.
    - */
    -goog.labs.i18n.ListFormatSymbols_mk = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} и {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ml.
    - */
    -goog.labs.i18n.ListFormatSymbols_ml = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} കൂടാതെ {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1} എന്നിവ'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale mn.
    - */
    -goog.labs.i18n.ListFormatSymbols_mn = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale mo.
    - */
    -goog.labs.i18n.ListFormatSymbols_mo = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} și {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} și {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale mr.
    - */
    -goog.labs.i18n.ListFormatSymbols_mr = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} आणि {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} आणि {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ms.
    - */
    -goog.labs.i18n.ListFormatSymbols_ms = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} dan {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} dan {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale mt.
    - */
    -goog.labs.i18n.ListFormatSymbols_mt = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} u {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, u {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale my.
    - */
    -goog.labs.i18n.ListFormatSymbols_my = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}နှင့်{1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, နှင့်{1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale nb.
    - */
    -goog.labs.i18n.ListFormatSymbols_nb = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} og {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} og {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ne.
    - */
    -goog.labs.i18n.ListFormatSymbols_ne = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} र {1}',
    -  LIST_START: '{0} र {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} र {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale nl.
    - */
    -goog.labs.i18n.ListFormatSymbols_nl = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} en {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} en {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale no.
    - */
    -goog.labs.i18n.ListFormatSymbols_no = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} og {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} og {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale no_NO.
    - */
    -goog.labs.i18n.ListFormatSymbols_no_NO = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} og {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} og {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale or.
    - */
    -goog.labs.i18n.ListFormatSymbols_or = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale pa.
    - */
    -goog.labs.i18n.ListFormatSymbols_pa = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} ਅਤੇ {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} ਅਤੇ {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale pl.
    - */
    -goog.labs.i18n.ListFormatSymbols_pl = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} i {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} i {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale pt.
    - */
    -goog.labs.i18n.ListFormatSymbols_pt = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} e {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} e {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale pt_BR.
    - */
    -goog.labs.i18n.ListFormatSymbols_pt_BR = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} e {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} e {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale pt_PT.
    - */
    -goog.labs.i18n.ListFormatSymbols_pt_PT = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} e {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} e {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ro.
    - */
    -goog.labs.i18n.ListFormatSymbols_ro = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} și {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} și {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ru.
    - */
    -goog.labs.i18n.ListFormatSymbols_ru = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} и {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} и {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sh.
    - */
    -goog.labs.i18n.ListFormatSymbols_sh = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} i {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} i {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale si.
    - */
    -goog.labs.i18n.ListFormatSymbols_si = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} සහ {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, සහ {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sk.
    - */
    -goog.labs.i18n.ListFormatSymbols_sk = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} a {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} a {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sl.
    - */
    -goog.labs.i18n.ListFormatSymbols_sl = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} in {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} in {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sq.
    - */
    -goog.labs.i18n.ListFormatSymbols_sq = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} dhe {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} dhe {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sr.
    - */
    -goog.labs.i18n.ListFormatSymbols_sr = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} и {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} и {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sv.
    - */
    -goog.labs.i18n.ListFormatSymbols_sv = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} och {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} och {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sw.
    - */
    -goog.labs.i18n.ListFormatSymbols_sw = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} na {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, na {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ta.
    - */
    -goog.labs.i18n.ListFormatSymbols_ta = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} மற்றும் {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} மற்றும் {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale te.
    - */
    -goog.labs.i18n.ListFormatSymbols_te = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} మరియు {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} మరియు {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale th.
    - */
    -goog.labs.i18n.ListFormatSymbols_th = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}และ{1}',
    -  LIST_START: '{0} {1}',
    -  LIST_MIDDLE: '{0} {1}',
    -  LIST_END: '{0} และ{1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale tl.
    - */
    -goog.labs.i18n.ListFormatSymbols_tl = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} at {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, at {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale tr.
    - */
    -goog.labs.i18n.ListFormatSymbols_tr = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} ve {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} ve {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale uk.
    - */
    -goog.labs.i18n.ListFormatSymbols_uk = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} і {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} і {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ur.
    - */
    -goog.labs.i18n.ListFormatSymbols_ur = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} اور {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، اور {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale uz.
    - */
    -goog.labs.i18n.ListFormatSymbols_uz = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} va {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} va {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale vi.
    - */
    -goog.labs.i18n.ListFormatSymbols_vi = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} và {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} và {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale zh.
    - */
    -goog.labs.i18n.ListFormatSymbols_zh = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0}和{1}',
    -  LIST_START: '{0}、{1}',
    -  LIST_MIDDLE: '{0}、{1}',
    -  LIST_END: '{0}和{1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale zh_CN.
    - */
    -goog.labs.i18n.ListFormatSymbols_zh_CN = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0}和{1}',
    -  LIST_START: '{0}、{1}',
    -  LIST_MIDDLE: '{0}、{1}',
    -  LIST_END: '{0}和{1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale zh_HK.
    - */
    -goog.labs.i18n.ListFormatSymbols_zh_HK = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0}和{1}',
    -  LIST_START: '{0}、{1}',
    -  LIST_MIDDLE: '{0}、{1}',
    -  LIST_END: '{0}和{1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale zh_TW.
    - */
    -goog.labs.i18n.ListFormatSymbols_zh_TW = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0}和{1}',
    -  LIST_START: '{0}、{1}',
    -  LIST_MIDDLE: '{0}、{1}',
    -  LIST_END: '{0}和{1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale zu.
    - */
    -goog.labs.i18n.ListFormatSymbols_zu = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: 'I-{0} ne-{1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, ne-{1}'
    -};
    -
    -
    -/**
    - * Default value, in case nothing else matches
    - */
    -goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en;
    -
    -
    -/**
    - * Selecting symbols by locale.
    - */
    -if (goog.LOCALE == 'af') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_af;
    -}
    -
    -if (goog.LOCALE == 'am') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_am;
    -}
    -
    -if (goog.LOCALE == 'ar') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ar;
    -}
    -
    -if (goog.LOCALE == 'az') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_az;
    -}
    -
    -if (goog.LOCALE == 'bg') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_bg;
    -}
    -
    -if (goog.LOCALE == 'bn') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_bn;
    -}
    -
    -if (goog.LOCALE == 'br') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_br;
    -}
    -
    -if (goog.LOCALE == 'ca') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ca;
    -}
    -
    -if (goog.LOCALE == 'chr') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_chr;
    -}
    -
    -if (goog.LOCALE == 'cs') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_cs;
    -}
    -
    -if (goog.LOCALE == 'cy') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_cy;
    -}
    -
    -if (goog.LOCALE == 'da') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_da;
    -}
    -
    -if (goog.LOCALE == 'de') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_de;
    -}
    -
    -if (goog.LOCALE == 'de_AT' || goog.LOCALE == 'de-AT') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_de_AT;
    -}
    -
    -if (goog.LOCALE == 'de_CH' || goog.LOCALE == 'de-CH') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_de_CH;
    -}
    -
    -if (goog.LOCALE == 'el') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_el;
    -}
    -
    -if (goog.LOCALE == 'en') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en;
    -}
    -
    -if (goog.LOCALE == 'en_AU' || goog.LOCALE == 'en-AU') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_AU;
    -}
    -
    -if (goog.LOCALE == 'en_GB' || goog.LOCALE == 'en-GB') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_GB;
    -}
    -
    -if (goog.LOCALE == 'en_IE' || goog.LOCALE == 'en-IE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_IE;
    -}
    -
    -if (goog.LOCALE == 'en_IN' || goog.LOCALE == 'en-IN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_IN;
    -}
    -
    -if (goog.LOCALE == 'en_SG' || goog.LOCALE == 'en-SG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_SG;
    -}
    -
    -if (goog.LOCALE == 'en_US' || goog.LOCALE == 'en-US') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_US;
    -}
    -
    -if (goog.LOCALE == 'en_ZA' || goog.LOCALE == 'en-ZA') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_ZA;
    -}
    -
    -if (goog.LOCALE == 'es') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_es;
    -}
    -
    -if (goog.LOCALE == 'es_419' || goog.LOCALE == 'es-419') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_es_419;
    -}
    -
    -if (goog.LOCALE == 'es_ES' || goog.LOCALE == 'es-ES') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_es_ES;
    -}
    -
    -if (goog.LOCALE == 'et') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_et;
    -}
    -
    -if (goog.LOCALE == 'eu') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_eu;
    -}
    -
    -if (goog.LOCALE == 'fa') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fa;
    -}
    -
    -if (goog.LOCALE == 'fi') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fi;
    -}
    -
    -if (goog.LOCALE == 'fil') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fil;
    -}
    -
    -if (goog.LOCALE == 'fr') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr;
    -}
    -
    -if (goog.LOCALE == 'fr_CA' || goog.LOCALE == 'fr-CA') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_CA;
    -}
    -
    -if (goog.LOCALE == 'ga') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ga;
    -}
    -
    -if (goog.LOCALE == 'gl') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_gl;
    -}
    -
    -if (goog.LOCALE == 'gsw') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_gsw;
    -}
    -
    -if (goog.LOCALE == 'gu') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_gu;
    -}
    -
    -if (goog.LOCALE == 'haw') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_haw;
    -}
    -
    -if (goog.LOCALE == 'he') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_he;
    -}
    -
    -if (goog.LOCALE == 'hi') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_hi;
    -}
    -
    -if (goog.LOCALE == 'hr') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_hr;
    -}
    -
    -if (goog.LOCALE == 'hu') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_hu;
    -}
    -
    -if (goog.LOCALE == 'hy') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_hy;
    -}
    -
    -if (goog.LOCALE == 'id') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_id;
    -}
    -
    -if (goog.LOCALE == 'in') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_in;
    -}
    -
    -if (goog.LOCALE == 'is') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_is;
    -}
    -
    -if (goog.LOCALE == 'it') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_it;
    -}
    -
    -if (goog.LOCALE == 'iw') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_iw;
    -}
    -
    -if (goog.LOCALE == 'ja') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ja;
    -}
    -
    -if (goog.LOCALE == 'ka') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ka;
    -}
    -
    -if (goog.LOCALE == 'kk') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_kk;
    -}
    -
    -if (goog.LOCALE == 'km') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_km;
    -}
    -
    -if (goog.LOCALE == 'kn') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_kn;
    -}
    -
    -if (goog.LOCALE == 'ko') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ko;
    -}
    -
    -if (goog.LOCALE == 'ky') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ky;
    -}
    -
    -if (goog.LOCALE == 'ln') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ln;
    -}
    -
    -if (goog.LOCALE == 'lo') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_lo;
    -}
    -
    -if (goog.LOCALE == 'lt') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_lt;
    -}
    -
    -if (goog.LOCALE == 'lv') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_lv;
    -}
    -
    -if (goog.LOCALE == 'mk') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_mk;
    -}
    -
    -if (goog.LOCALE == 'ml') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ml;
    -}
    -
    -if (goog.LOCALE == 'mn') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_mn;
    -}
    -
    -if (goog.LOCALE == 'mo') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_mo;
    -}
    -
    -if (goog.LOCALE == 'mr') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_mr;
    -}
    -
    -if (goog.LOCALE == 'ms') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ms;
    -}
    -
    -if (goog.LOCALE == 'mt') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_mt;
    -}
    -
    -if (goog.LOCALE == 'my') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_my;
    -}
    -
    -if (goog.LOCALE == 'nb') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_nb;
    -}
    -
    -if (goog.LOCALE == 'ne') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ne;
    -}
    -
    -if (goog.LOCALE == 'nl') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_nl;
    -}
    -
    -if (goog.LOCALE == 'no') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_no;
    -}
    -
    -if (goog.LOCALE == 'no_NO' || goog.LOCALE == 'no-NO') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_no_NO;
    -}
    -
    -if (goog.LOCALE == 'or') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_or;
    -}
    -
    -if (goog.LOCALE == 'pa') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_pa;
    -}
    -
    -if (goog.LOCALE == 'pl') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_pl;
    -}
    -
    -if (goog.LOCALE == 'pt') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_pt;
    -}
    -
    -if (goog.LOCALE == 'pt_BR' || goog.LOCALE == 'pt-BR') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_pt_BR;
    -}
    -
    -if (goog.LOCALE == 'pt_PT' || goog.LOCALE == 'pt-PT') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_pt_PT;
    -}
    -
    -if (goog.LOCALE == 'ro') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ro;
    -}
    -
    -if (goog.LOCALE == 'ru') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ru;
    -}
    -
    -if (goog.LOCALE == 'sh') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sh;
    -}
    -
    -if (goog.LOCALE == 'si') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_si;
    -}
    -
    -if (goog.LOCALE == 'sk') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sk;
    -}
    -
    -if (goog.LOCALE == 'sl') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sl;
    -}
    -
    -if (goog.LOCALE == 'sq') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sq;
    -}
    -
    -if (goog.LOCALE == 'sr') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sr;
    -}
    -
    -if (goog.LOCALE == 'sv') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sv;
    -}
    -
    -if (goog.LOCALE == 'sw') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sw;
    -}
    -
    -if (goog.LOCALE == 'ta') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ta;
    -}
    -
    -if (goog.LOCALE == 'te') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_te;
    -}
    -
    -if (goog.LOCALE == 'th') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_th;
    -}
    -
    -if (goog.LOCALE == 'tl') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_tl;
    -}
    -
    -if (goog.LOCALE == 'tr') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_tr;
    -}
    -
    -if (goog.LOCALE == 'uk') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_uk;
    -}
    -
    -if (goog.LOCALE == 'ur') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ur;
    -}
    -
    -if (goog.LOCALE == 'uz') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_uz;
    -}
    -
    -if (goog.LOCALE == 'vi') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_vi;
    -}
    -
    -if (goog.LOCALE == 'zh') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_zh;
    -}
    -
    -if (goog.LOCALE == 'zh_CN' || goog.LOCALE == 'zh-CN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_zh_CN;
    -}
    -
    -if (goog.LOCALE == 'zh_HK' || goog.LOCALE == 'zh-HK') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_zh_HK;
    -}
    -
    -if (goog.LOCALE == 'zh_TW' || goog.LOCALE == 'zh-TW') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_zh_TW;
    -}
    -
    -if (goog.LOCALE == 'zu') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_zu;
    -}
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/i18n/listsymbolsext.js b/src/database/third_party/closure-library/closure/goog/labs/i18n/listsymbolsext.js
    deleted file mode 100644
    index 7f76fcd0cf1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/i18n/listsymbolsext.js
    +++ /dev/null
    @@ -1,10088 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview List formatting symbols for all locales.
    - *
    - * This file is autogenerated by script.  See
    - * http://go/generate_list_symbols.py using --for_closure
    - * File generated from CLDR ver. 26
    - *
    - * To reduce the file size (which may cause issues in some JS
    - * developing environments), this file will only contain locales
    - * that are usually supported by Google products. It is a super
    - * set of 40 languages. The rest of the data can be found in another file
    - * named "listsymbolsext.js", which will be generated at the same
    - * time as this file.
    - * Before checkin, this file could have been manually edited. This is
    - * to incorporate changes before we could correct CLDR. All manual
    - * modification must be documented in this section, and should be
    - * removed after those changes land to CLDR.
    - */
    -
    -goog.provide('goog.labs.i18n.ListFormatSymbolsExt');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_af_NA');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_af_ZA');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_agq');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_agq_CM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ak');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ak_GH');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_am_ET');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ar_001');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ar_AE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ar_BH');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ar_DJ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ar_DZ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ar_EG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ar_EH');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ar_ER');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ar_IL');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ar_IQ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ar_JO');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ar_KM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ar_KW');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ar_LB');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ar_LY');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ar_MA');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ar_MR');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ar_OM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ar_PS');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ar_QA');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ar_SA');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ar_SD');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ar_SO');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ar_SS');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ar_SY');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ar_TD');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ar_TN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ar_YE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_as');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_as_IN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_asa');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_asa_TZ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_az_Cyrl');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_az_Cyrl_AZ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_az_Latn');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_az_Latn_AZ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_bas');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_bas_CM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_be');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_be_BY');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_bem');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_bem_ZM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_bez');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_bez_TZ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_bg_BG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_bm');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_bm_Latn');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_bm_Latn_ML');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_bn_BD');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_bn_IN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_bo');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_bo_CN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_bo_IN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_br_FR');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_brx');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_brx_IN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_bs');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_bs_Cyrl');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_bs_Cyrl_BA');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_bs_Latn');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_bs_Latn_BA');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ca_AD');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ca_ES');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ca_FR');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ca_IT');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_cgg');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_cgg_UG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_chr_US');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_cs_CZ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_cy_GB');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_da_DK');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_da_GL');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_dav');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_dav_KE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_de_BE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_de_DE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_de_LI');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_de_LU');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_dje');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_dje_NE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_dsb');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_dsb_DE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_dua');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_dua_CM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_dyo');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_dyo_SN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_dz');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_dz_BT');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ebu');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ebu_KE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ee');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ee_GH');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ee_TG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_el_CY');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_el_GR');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_001');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_150');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_AG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_AI');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_AS');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_BB');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_BE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_BM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_BS');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_BW');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_BZ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_CA');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_CC');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_CK');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_CM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_CX');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_DG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_DM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_ER');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_FJ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_FK');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_FM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_GD');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_GG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_GH');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_GI');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_GM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_GU');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_GY');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_HK');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_IM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_IO');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_JE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_JM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_KE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_KI');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_KN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_KY');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_LC');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_LR');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_LS');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_MG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_MH');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_MO');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_MP');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_MS');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_MT');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_MU');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_MW');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_MY');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_NA');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_NF');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_NG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_NR');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_NU');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_NZ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_PG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_PH');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_PK');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_PN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_PR');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_PW');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_RW');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_SB');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_SC');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_SD');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_SH');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_SL');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_SS');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_SX');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_SZ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_TC');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_TK');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_TO');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_TT');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_TV');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_TZ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_UG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_UM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_US_POSIX');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_VC');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_VG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_VI');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_VU');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_WS');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_ZM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_en_ZW');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_eo');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_es_AR');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_es_BO');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_es_CL');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_es_CO');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_es_CR');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_es_CU');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_es_DO');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_es_EA');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_es_EC');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_es_GQ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_es_GT');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_es_HN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_es_IC');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_es_MX');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_es_NI');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_es_PA');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_es_PE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_es_PH');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_es_PR');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_es_PY');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_es_SV');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_es_US');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_es_UY');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_es_VE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_et_EE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_eu_ES');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ewo');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ewo_CM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fa_AF');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fa_IR');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ff');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ff_CM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ff_GN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ff_MR');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ff_SN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fi_FI');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fil_PH');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fo');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fo_FO');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_BE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_BF');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_BI');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_BJ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_BL');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_CD');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_CF');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_CG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_CH');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_CI');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_CM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_DJ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_DZ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_FR');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_GA');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_GF');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_GN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_GP');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_GQ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_HT');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_KM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_LU');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_MA');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_MC');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_MF');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_MG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_ML');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_MQ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_MR');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_MU');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_NC');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_NE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_PF');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_PM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_RE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_RW');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_SC');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_SN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_SY');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_TD');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_TG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_TN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_VU');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_WF');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fr_YT');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fur');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fur_IT');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fy');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_fy_NL');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ga_IE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_gd');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_gd_GB');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_gl_ES');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_gsw_CH');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_gsw_FR');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_gsw_LI');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_gu_IN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_guz');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_guz_KE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_gv');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_gv_IM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ha');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ha_Latn');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ha_Latn_GH');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ha_Latn_NE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ha_Latn_NG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_haw_US');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_he_IL');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_hi_IN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_hr_BA');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_hr_HR');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_hsb');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_hsb_DE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_hu_HU');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_hy_AM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_id_ID');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ig');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ig_NG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ii');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ii_CN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_is_IS');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_it_CH');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_it_IT');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_it_SM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ja_JP');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_jgo');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_jgo_CM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_jmc');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_jmc_TZ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ka_GE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_kab');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_kab_DZ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_kam');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_kam_KE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_kde');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_kde_TZ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_kea');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_kea_CV');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_khq');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_khq_ML');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ki');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ki_KE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_kk_Cyrl');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_kk_Cyrl_KZ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_kkj');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_kkj_CM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_kl');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_kl_GL');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_kln');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_kln_KE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_km_KH');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_kn_IN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ko_KP');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ko_KR');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_kok');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_kok_IN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ks');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ks_Arab');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ks_Arab_IN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ksb');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ksb_TZ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ksf');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ksf_CM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ksh');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ksh_DE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_kw');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_kw_GB');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ky_Cyrl');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ky_Cyrl_KG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_lag');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_lag_TZ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_lb');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_lb_LU');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_lg');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_lg_UG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_lkt');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_lkt_US');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ln_AO');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ln_CD');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ln_CF');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ln_CG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_lo_LA');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_lt_LT');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_lu');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_lu_CD');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_luo');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_luo_KE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_luy');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_luy_KE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_lv_LV');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_mas');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_mas_KE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_mas_TZ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_mer');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_mer_KE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_mfe');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_mfe_MU');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_mg');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_mg_MG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_mgh');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_mgh_MZ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_mgo');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_mgo_CM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_mk_MK');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ml_IN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_mn_Cyrl');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_mn_Cyrl_MN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_mr_IN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ms_Latn');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ms_Latn_BN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ms_Latn_MY');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ms_Latn_SG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_mt_MT');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_mua');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_mua_CM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_my_MM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_naq');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_naq_NA');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_nb_NO');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_nb_SJ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_nd');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_nd_ZW');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ne_IN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ne_NP');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_nl_AW');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_nl_BE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_nl_BQ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_nl_CW');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_nl_NL');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_nl_SR');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_nl_SX');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_nmg');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_nmg_CM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_nn');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_nn_NO');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_nnh');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_nnh_CM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_nus');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_nus_SD');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_nyn');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_nyn_UG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_om');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_om_ET');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_om_KE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_or_IN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_os');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_os_GE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_os_RU');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_pa_Arab');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_pa_Arab_PK');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_pa_Guru');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_pa_Guru_IN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_pl_PL');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ps');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ps_AF');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_pt_AO');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_pt_CV');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_pt_GW');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_pt_MO');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_pt_MZ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_pt_ST');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_pt_TL');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_qu');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_qu_BO');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_qu_EC');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_qu_PE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_rm');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_rm_CH');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_rn');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_rn_BI');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ro_MD');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ro_RO');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_rof');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_rof_TZ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ru_BY');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ru_KG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ru_KZ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ru_MD');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ru_RU');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ru_UA');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_rw');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_rw_RW');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_rwk');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_rwk_TZ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sah');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sah_RU');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_saq');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_saq_KE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sbp');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sbp_TZ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_se');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_se_FI');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_se_NO');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_se_SE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_seh');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_seh_MZ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ses');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ses_ML');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sg');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sg_CF');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_shi');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_shi_Latn');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_shi_Latn_MA');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_shi_Tfng');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_shi_Tfng_MA');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_si_LK');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sk_SK');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sl_SI');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_smn');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_smn_FI');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sn');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sn_ZW');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_so');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_so_DJ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_so_ET');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_so_KE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_so_SO');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sq_AL');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sq_MK');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sq_XK');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sr_Cyrl');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sr_Cyrl_BA');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sr_Cyrl_ME');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sr_Cyrl_RS');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sr_Cyrl_XK');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sr_Latn');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sr_Latn_BA');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sr_Latn_ME');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sr_Latn_RS');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sr_Latn_XK');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sv_AX');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sv_FI');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sv_SE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sw_KE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sw_TZ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_sw_UG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_swc');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_swc_CD');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ta_IN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ta_LK');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ta_MY');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ta_SG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_te_IN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_teo');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_teo_KE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_teo_UG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_th_TH');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ti');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ti_ER');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ti_ET');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_to');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_to_TO');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_tr_CY');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_tr_TR');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_twq');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_twq_NE');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_tzm');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_tzm_Latn');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_tzm_Latn_MA');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ug');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ug_Arab');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ug_Arab_CN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_uk_UA');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ur_IN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_ur_PK');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_uz_Arab');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_uz_Arab_AF');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_uz_Cyrl');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_uz_Cyrl_UZ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_uz_Latn');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_uz_Latn_UZ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_vai');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_vai_Latn');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_vai_Latn_LR');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_vai_Vaii');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_vai_Vaii_LR');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_vi_VN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_vun');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_vun_TZ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_wae');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_wae_CH');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_xog');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_xog_UG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_yav');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_yav_CM');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_yi');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_yi_001');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_yo');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_yo_BJ');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_yo_NG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_zgh');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_zgh_MA');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_zh_Hans');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_zh_Hans_CN');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_zh_Hans_HK');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_zh_Hans_MO');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_zh_Hans_SG');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_zh_Hant');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_zh_Hant_HK');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_zh_Hant_MO');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_zh_Hant_TW');
    -goog.provide('goog.labs.i18n.ListFormatSymbols_zu_ZA');
    -
    -goog.require('goog.labs.i18n.ListFormatSymbols');
    -
    -
    -/**
    - * List formatting symbols for locale af_NA.
    - */
    -goog.labs.i18n.ListFormatSymbols_af_NA = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} en {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} en {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale af_ZA.
    - */
    -goog.labs.i18n.ListFormatSymbols_af_ZA = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} en {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} en {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale agq.
    - */
    -goog.labs.i18n.ListFormatSymbols_agq = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale agq_CM.
    - */
    -goog.labs.i18n.ListFormatSymbols_agq_CM = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ak.
    - */
    -goog.labs.i18n.ListFormatSymbols_ak = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ak_GH.
    - */
    -goog.labs.i18n.ListFormatSymbols_ak_GH = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale am_ET.
    - */
    -goog.labs.i18n.ListFormatSymbols_am_ET = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} እና {1}',
    -  LIST_START: '{0}፣ {1}',
    -  LIST_MIDDLE: '{0}፣ {1}',
    -  LIST_END: '{0}, እና {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ar_001.
    - */
    -goog.labs.i18n.ListFormatSymbols_ar_001 = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ar_AE.
    - */
    -goog.labs.i18n.ListFormatSymbols_ar_AE = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ar_BH.
    - */
    -goog.labs.i18n.ListFormatSymbols_ar_BH = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ar_DJ.
    - */
    -goog.labs.i18n.ListFormatSymbols_ar_DJ = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ar_DZ.
    - */
    -goog.labs.i18n.ListFormatSymbols_ar_DZ = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ar_EG.
    - */
    -goog.labs.i18n.ListFormatSymbols_ar_EG = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} و{1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ar_EH.
    - */
    -goog.labs.i18n.ListFormatSymbols_ar_EH = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ar_ER.
    - */
    -goog.labs.i18n.ListFormatSymbols_ar_ER = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ar_IL.
    - */
    -goog.labs.i18n.ListFormatSymbols_ar_IL = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ar_IQ.
    - */
    -goog.labs.i18n.ListFormatSymbols_ar_IQ = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ar_JO.
    - */
    -goog.labs.i18n.ListFormatSymbols_ar_JO = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ar_KM.
    - */
    -goog.labs.i18n.ListFormatSymbols_ar_KM = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ar_KW.
    - */
    -goog.labs.i18n.ListFormatSymbols_ar_KW = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ar_LB.
    - */
    -goog.labs.i18n.ListFormatSymbols_ar_LB = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ar_LY.
    - */
    -goog.labs.i18n.ListFormatSymbols_ar_LY = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ar_MA.
    - */
    -goog.labs.i18n.ListFormatSymbols_ar_MA = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ar_MR.
    - */
    -goog.labs.i18n.ListFormatSymbols_ar_MR = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ar_OM.
    - */
    -goog.labs.i18n.ListFormatSymbols_ar_OM = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ar_PS.
    - */
    -goog.labs.i18n.ListFormatSymbols_ar_PS = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ar_QA.
    - */
    -goog.labs.i18n.ListFormatSymbols_ar_QA = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ar_SA.
    - */
    -goog.labs.i18n.ListFormatSymbols_ar_SA = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ar_SD.
    - */
    -goog.labs.i18n.ListFormatSymbols_ar_SD = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ar_SO.
    - */
    -goog.labs.i18n.ListFormatSymbols_ar_SO = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ar_SS.
    - */
    -goog.labs.i18n.ListFormatSymbols_ar_SS = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ar_SY.
    - */
    -goog.labs.i18n.ListFormatSymbols_ar_SY = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ar_TD.
    - */
    -goog.labs.i18n.ListFormatSymbols_ar_TD = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ar_TN.
    - */
    -goog.labs.i18n.ListFormatSymbols_ar_TN = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ar_YE.
    - */
    -goog.labs.i18n.ListFormatSymbols_ar_YE = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale as.
    - */
    -goog.labs.i18n.ListFormatSymbols_as = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale as_IN.
    - */
    -goog.labs.i18n.ListFormatSymbols_as_IN = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale asa.
    - */
    -goog.labs.i18n.ListFormatSymbols_asa = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale asa_TZ.
    - */
    -goog.labs.i18n.ListFormatSymbols_asa_TZ = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale az_Cyrl.
    - */
    -goog.labs.i18n.ListFormatSymbols_az_Cyrl = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale az_Cyrl_AZ.
    - */
    -goog.labs.i18n.ListFormatSymbols_az_Cyrl_AZ = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale az_Latn.
    - */
    -goog.labs.i18n.ListFormatSymbols_az_Latn = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} və {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} və {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale az_Latn_AZ.
    - */
    -goog.labs.i18n.ListFormatSymbols_az_Latn_AZ = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} və {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} və {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale bas.
    - */
    -goog.labs.i18n.ListFormatSymbols_bas = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale bas_CM.
    - */
    -goog.labs.i18n.ListFormatSymbols_bas_CM = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale be.
    - */
    -goog.labs.i18n.ListFormatSymbols_be = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale be_BY.
    - */
    -goog.labs.i18n.ListFormatSymbols_be_BY = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale bem.
    - */
    -goog.labs.i18n.ListFormatSymbols_bem = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale bem_ZM.
    - */
    -goog.labs.i18n.ListFormatSymbols_bem_ZM = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale bez.
    - */
    -goog.labs.i18n.ListFormatSymbols_bez = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale bez_TZ.
    - */
    -goog.labs.i18n.ListFormatSymbols_bez_TZ = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale bg_BG.
    - */
    -goog.labs.i18n.ListFormatSymbols_bg_BG = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} и {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} и {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale bm.
    - */
    -goog.labs.i18n.ListFormatSymbols_bm = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale bm_Latn.
    - */
    -goog.labs.i18n.ListFormatSymbols_bm_Latn = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale bm_Latn_ML.
    - */
    -goog.labs.i18n.ListFormatSymbols_bm_Latn_ML = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale bn_BD.
    - */
    -goog.labs.i18n.ListFormatSymbols_bn_BD = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} এবং {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, এবং {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale bn_IN.
    - */
    -goog.labs.i18n.ListFormatSymbols_bn_IN = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} এবং {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, এবং {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale bo.
    - */
    -goog.labs.i18n.ListFormatSymbols_bo = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale bo_CN.
    - */
    -goog.labs.i18n.ListFormatSymbols_bo_CN = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale bo_IN.
    - */
    -goog.labs.i18n.ListFormatSymbols_bo_IN = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale br_FR.
    - */
    -goog.labs.i18n.ListFormatSymbols_br_FR = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale brx.
    - */
    -goog.labs.i18n.ListFormatSymbols_brx = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale brx_IN.
    - */
    -goog.labs.i18n.ListFormatSymbols_brx_IN = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale bs.
    - */
    -goog.labs.i18n.ListFormatSymbols_bs = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} i {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} i {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale bs_Cyrl.
    - */
    -goog.labs.i18n.ListFormatSymbols_bs_Cyrl = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} и {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} и {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale bs_Cyrl_BA.
    - */
    -goog.labs.i18n.ListFormatSymbols_bs_Cyrl_BA = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} и {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} и {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale bs_Latn.
    - */
    -goog.labs.i18n.ListFormatSymbols_bs_Latn = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} i {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} i {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale bs_Latn_BA.
    - */
    -goog.labs.i18n.ListFormatSymbols_bs_Latn_BA = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} i {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} i {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ca_AD.
    - */
    -goog.labs.i18n.ListFormatSymbols_ca_AD = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} i {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} i {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ca_ES.
    - */
    -goog.labs.i18n.ListFormatSymbols_ca_ES = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} i {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} i {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ca_FR.
    - */
    -goog.labs.i18n.ListFormatSymbols_ca_FR = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} i {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} i {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ca_IT.
    - */
    -goog.labs.i18n.ListFormatSymbols_ca_IT = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} i {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} i {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale cgg.
    - */
    -goog.labs.i18n.ListFormatSymbols_cgg = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale cgg_UG.
    - */
    -goog.labs.i18n.ListFormatSymbols_cgg_UG = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale chr_US.
    - */
    -goog.labs.i18n.ListFormatSymbols_chr_US = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale cs_CZ.
    - */
    -goog.labs.i18n.ListFormatSymbols_cs_CZ = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} a {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} a {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale cy_GB.
    - */
    -goog.labs.i18n.ListFormatSymbols_cy_GB = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale da_DK.
    - */
    -goog.labs.i18n.ListFormatSymbols_da_DK = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} og {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} og {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale da_GL.
    - */
    -goog.labs.i18n.ListFormatSymbols_da_GL = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} og {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} og {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale dav.
    - */
    -goog.labs.i18n.ListFormatSymbols_dav = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale dav_KE.
    - */
    -goog.labs.i18n.ListFormatSymbols_dav_KE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale de_BE.
    - */
    -goog.labs.i18n.ListFormatSymbols_de_BE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} und {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} und {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale de_DE.
    - */
    -goog.labs.i18n.ListFormatSymbols_de_DE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} und {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} und {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale de_LI.
    - */
    -goog.labs.i18n.ListFormatSymbols_de_LI = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} und {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} und {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale de_LU.
    - */
    -goog.labs.i18n.ListFormatSymbols_de_LU = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} und {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} und {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale dje.
    - */
    -goog.labs.i18n.ListFormatSymbols_dje = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale dje_NE.
    - */
    -goog.labs.i18n.ListFormatSymbols_dje_NE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale dsb.
    - */
    -goog.labs.i18n.ListFormatSymbols_dsb = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} a {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} a {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale dsb_DE.
    - */
    -goog.labs.i18n.ListFormatSymbols_dsb_DE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} a {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} a {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale dua.
    - */
    -goog.labs.i18n.ListFormatSymbols_dua = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale dua_CM.
    - */
    -goog.labs.i18n.ListFormatSymbols_dua_CM = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale dyo.
    - */
    -goog.labs.i18n.ListFormatSymbols_dyo = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale dyo_SN.
    - */
    -goog.labs.i18n.ListFormatSymbols_dyo_SN = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale dz.
    - */
    -goog.labs.i18n.ListFormatSymbols_dz = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} དང་ {1}',
    -  LIST_START: '{0} དང་ {1}',
    -  LIST_MIDDLE: '{0} དང་ {1}',
    -  LIST_END: '{0} དང་ {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale dz_BT.
    - */
    -goog.labs.i18n.ListFormatSymbols_dz_BT = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} དང་ {1}',
    -  LIST_START: '{0} དང་ {1}',
    -  LIST_MIDDLE: '{0} དང་ {1}',
    -  LIST_END: '{0} དང་ {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ebu.
    - */
    -goog.labs.i18n.ListFormatSymbols_ebu = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ebu_KE.
    - */
    -goog.labs.i18n.ListFormatSymbols_ebu_KE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ee.
    - */
    -goog.labs.i18n.ListFormatSymbols_ee = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} kple {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, kple {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ee_GH.
    - */
    -goog.labs.i18n.ListFormatSymbols_ee_GH = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} kple {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, kple {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ee_TG.
    - */
    -goog.labs.i18n.ListFormatSymbols_ee_TG = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} kple {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, kple {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale el_CY.
    - */
    -goog.labs.i18n.ListFormatSymbols_el_CY = {
    -  GENDER_STYLE: 1,
    -  LIST_TWO: '{0} και {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} και {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale el_GR.
    - */
    -goog.labs.i18n.ListFormatSymbols_el_GR = {
    -  GENDER_STYLE: 1,
    -  LIST_TWO: '{0} και {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} και {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_001.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_001 = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_150.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_150 = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_AG.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_AG = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_AI.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_AI = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_AS.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_AS = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_BB.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_BB = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_BE.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_BE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_BM.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_BM = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_BS.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_BS = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_BW.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_BW = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_BZ.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_BZ = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_CA.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_CA = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_CC.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_CC = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_CK.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_CK = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_CM.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_CM = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_CX.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_CX = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_DG.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_DG = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_DM.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_DM = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_ER.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_ER = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_FJ.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_FJ = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_FK.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_FK = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_FM.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_FM = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_GD.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_GD = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_GG.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_GG = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_GH.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_GH = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_GI.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_GI = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_GM.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_GM = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_GU.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_GU = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_GY.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_GY = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_HK.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_HK = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_IM.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_IM = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_IO.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_IO = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_JE.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_JE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_JM.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_JM = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_KE.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_KE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_KI.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_KI = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_KN.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_KN = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_KY.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_KY = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_LC.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_LC = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_LR.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_LR = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_LS.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_LS = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_MG.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_MG = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_MH.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_MH = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_MO.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_MO = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_MP.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_MP = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_MS.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_MS = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_MT.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_MT = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_MU.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_MU = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_MW.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_MW = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_MY.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_MY = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_NA.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_NA = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_NF.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_NF = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_NG.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_NG = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_NR.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_NR = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_NU.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_NU = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_NZ.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_NZ = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_PG.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_PG = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_PH.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_PH = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_PK.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_PK = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_PN.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_PN = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_PR.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_PR = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_PW.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_PW = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_RW.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_RW = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_SB.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_SB = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_SC.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_SC = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_SD.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_SD = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_SH.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_SH = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_SL.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_SL = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_SS.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_SS = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_SX.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_SX = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_SZ.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_SZ = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_TC.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_TC = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_TK.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_TK = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_TO.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_TO = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_TT.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_TT = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_TV.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_TV = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_TZ.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_TZ = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_UG.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_UG = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_UM.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_UM = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_US_POSIX.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_US_POSIX = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_VC.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_VC = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_VG.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_VG = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_VI.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_VI = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_VU.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_VU = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_WS.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_WS = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_ZM.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_ZM = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale en_ZW.
    - */
    -goog.labs.i18n.ListFormatSymbols_en_ZW = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale eo.
    - */
    -goog.labs.i18n.ListFormatSymbols_eo = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale es_AR.
    - */
    -goog.labs.i18n.ListFormatSymbols_es_AR = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} y {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} y {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale es_BO.
    - */
    -goog.labs.i18n.ListFormatSymbols_es_BO = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} y {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} y {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale es_CL.
    - */
    -goog.labs.i18n.ListFormatSymbols_es_CL = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} y {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} y {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale es_CO.
    - */
    -goog.labs.i18n.ListFormatSymbols_es_CO = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} y {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} y {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale es_CR.
    - */
    -goog.labs.i18n.ListFormatSymbols_es_CR = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} y {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} y {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale es_CU.
    - */
    -goog.labs.i18n.ListFormatSymbols_es_CU = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} y {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} y {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale es_DO.
    - */
    -goog.labs.i18n.ListFormatSymbols_es_DO = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} y {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} y {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale es_EA.
    - */
    -goog.labs.i18n.ListFormatSymbols_es_EA = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} y {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} y {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale es_EC.
    - */
    -goog.labs.i18n.ListFormatSymbols_es_EC = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} y {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} y {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale es_GQ.
    - */
    -goog.labs.i18n.ListFormatSymbols_es_GQ = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} y {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} y {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale es_GT.
    - */
    -goog.labs.i18n.ListFormatSymbols_es_GT = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} y {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} y {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale es_HN.
    - */
    -goog.labs.i18n.ListFormatSymbols_es_HN = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} y {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} y {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale es_IC.
    - */
    -goog.labs.i18n.ListFormatSymbols_es_IC = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} y {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} y {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale es_MX.
    - */
    -goog.labs.i18n.ListFormatSymbols_es_MX = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} y {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} y {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale es_NI.
    - */
    -goog.labs.i18n.ListFormatSymbols_es_NI = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} y {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} y {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale es_PA.
    - */
    -goog.labs.i18n.ListFormatSymbols_es_PA = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} y {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} y {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale es_PE.
    - */
    -goog.labs.i18n.ListFormatSymbols_es_PE = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} y {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} y {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale es_PH.
    - */
    -goog.labs.i18n.ListFormatSymbols_es_PH = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} y {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} y {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale es_PR.
    - */
    -goog.labs.i18n.ListFormatSymbols_es_PR = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} y {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} y {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale es_PY.
    - */
    -goog.labs.i18n.ListFormatSymbols_es_PY = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} y {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} y {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale es_SV.
    - */
    -goog.labs.i18n.ListFormatSymbols_es_SV = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} y {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} y {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale es_US.
    - */
    -goog.labs.i18n.ListFormatSymbols_es_US = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} y {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} y {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale es_UY.
    - */
    -goog.labs.i18n.ListFormatSymbols_es_UY = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} y {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} y {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale es_VE.
    - */
    -goog.labs.i18n.ListFormatSymbols_es_VE = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} y {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} y {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale et_EE.
    - */
    -goog.labs.i18n.ListFormatSymbols_et_EE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} ja {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} ja {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale eu_ES.
    - */
    -goog.labs.i18n.ListFormatSymbols_eu_ES = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} eta {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} eta {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ewo.
    - */
    -goog.labs.i18n.ListFormatSymbols_ewo = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ewo_CM.
    - */
    -goog.labs.i18n.ListFormatSymbols_ewo_CM = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fa_AF.
    - */
    -goog.labs.i18n.ListFormatSymbols_fa_AF = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}،‏ {1}',
    -  LIST_MIDDLE: '{0}،‏ {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fa_IR.
    - */
    -goog.labs.i18n.ListFormatSymbols_fa_IR = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} و {1}',
    -  LIST_START: '{0}،‏ {1}',
    -  LIST_MIDDLE: '{0}،‏ {1}',
    -  LIST_END: '{0}، و {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ff.
    - */
    -goog.labs.i18n.ListFormatSymbols_ff = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ff_CM.
    - */
    -goog.labs.i18n.ListFormatSymbols_ff_CM = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ff_GN.
    - */
    -goog.labs.i18n.ListFormatSymbols_ff_GN = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ff_MR.
    - */
    -goog.labs.i18n.ListFormatSymbols_ff_MR = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ff_SN.
    - */
    -goog.labs.i18n.ListFormatSymbols_ff_SN = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fi_FI.
    - */
    -goog.labs.i18n.ListFormatSymbols_fi_FI = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} ja {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} ja {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fil_PH.
    - */
    -goog.labs.i18n.ListFormatSymbols_fil_PH = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} at {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, at {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fo.
    - */
    -goog.labs.i18n.ListFormatSymbols_fo = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} og {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} og {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fo_FO.
    - */
    -goog.labs.i18n.ListFormatSymbols_fo_FO = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} og {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} og {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_BE.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_BE = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_BF.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_BF = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_BI.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_BI = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_BJ.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_BJ = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_BL.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_BL = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_CD.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_CD = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_CF.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_CF = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_CG.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_CG = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_CH.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_CH = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_CI.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_CI = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_CM.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_CM = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_DJ.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_DJ = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_DZ.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_DZ = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_FR.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_FR = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_GA.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_GA = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_GF.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_GF = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_GN.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_GN = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_GP.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_GP = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_GQ.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_GQ = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_HT.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_HT = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_KM.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_KM = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_LU.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_LU = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_MA.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_MA = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_MC.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_MC = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_MF.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_MF = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_MG.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_MG = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_ML.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_ML = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_MQ.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_MQ = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_MR.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_MR = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_MU.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_MU = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_NC.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_NC = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_NE.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_NE = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_PF.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_PF = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_PM.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_PM = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_RE.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_RE = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_RW.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_RW = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_SC.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_SC = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_SN.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_SN = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_SY.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_SY = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_TD.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_TD = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_TG.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_TG = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_TN.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_TN = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_VU.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_VU = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_WF.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_WF = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fr_YT.
    - */
    -goog.labs.i18n.ListFormatSymbols_fr_YT = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} et {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} et {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fur.
    - */
    -goog.labs.i18n.ListFormatSymbols_fur = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} e {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} e {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fur_IT.
    - */
    -goog.labs.i18n.ListFormatSymbols_fur_IT = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} e {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} e {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fy.
    - */
    -goog.labs.i18n.ListFormatSymbols_fy = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} en {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} en {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale fy_NL.
    - */
    -goog.labs.i18n.ListFormatSymbols_fy_NL = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} en {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} en {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ga_IE.
    - */
    -goog.labs.i18n.ListFormatSymbols_ga_IE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} agus {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, agus {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale gd.
    - */
    -goog.labs.i18n.ListFormatSymbols_gd = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} agus {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} agus {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale gd_GB.
    - */
    -goog.labs.i18n.ListFormatSymbols_gd_GB = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} agus {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} agus {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale gl_ES.
    - */
    -goog.labs.i18n.ListFormatSymbols_gl_ES = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} e {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} e {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale gsw_CH.
    - */
    -goog.labs.i18n.ListFormatSymbols_gsw_CH = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} und {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} und {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale gsw_FR.
    - */
    -goog.labs.i18n.ListFormatSymbols_gsw_FR = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} und {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} und {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale gsw_LI.
    - */
    -goog.labs.i18n.ListFormatSymbols_gsw_LI = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} und {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} und {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale gu_IN.
    - */
    -goog.labs.i18n.ListFormatSymbols_gu_IN = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} અને {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} અને {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale guz.
    - */
    -goog.labs.i18n.ListFormatSymbols_guz = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale guz_KE.
    - */
    -goog.labs.i18n.ListFormatSymbols_guz_KE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale gv.
    - */
    -goog.labs.i18n.ListFormatSymbols_gv = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale gv_IM.
    - */
    -goog.labs.i18n.ListFormatSymbols_gv_IM = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ha.
    - */
    -goog.labs.i18n.ListFormatSymbols_ha = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ha_Latn.
    - */
    -goog.labs.i18n.ListFormatSymbols_ha_Latn = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ha_Latn_GH.
    - */
    -goog.labs.i18n.ListFormatSymbols_ha_Latn_GH = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ha_Latn_NE.
    - */
    -goog.labs.i18n.ListFormatSymbols_ha_Latn_NE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ha_Latn_NG.
    - */
    -goog.labs.i18n.ListFormatSymbols_ha_Latn_NG = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale haw_US.
    - */
    -goog.labs.i18n.ListFormatSymbols_haw_US = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale he_IL.
    - */
    -goog.labs.i18n.ListFormatSymbols_he_IL = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} ו{1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} ו{1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale hi_IN.
    - */
    -goog.labs.i18n.ListFormatSymbols_hi_IN = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} और {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, और {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale hr_BA.
    - */
    -goog.labs.i18n.ListFormatSymbols_hr_BA = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} i {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} i {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale hr_HR.
    - */
    -goog.labs.i18n.ListFormatSymbols_hr_HR = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} i {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} i {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale hsb.
    - */
    -goog.labs.i18n.ListFormatSymbols_hsb = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} a {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} a {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale hsb_DE.
    - */
    -goog.labs.i18n.ListFormatSymbols_hsb_DE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} a {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} a {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale hu_HU.
    - */
    -goog.labs.i18n.ListFormatSymbols_hu_HU = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} és {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} és {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale hy_AM.
    - */
    -goog.labs.i18n.ListFormatSymbols_hy_AM = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} և {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} և {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale id_ID.
    - */
    -goog.labs.i18n.ListFormatSymbols_id_ID = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} dan {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, dan {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ig.
    - */
    -goog.labs.i18n.ListFormatSymbols_ig = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ig_NG.
    - */
    -goog.labs.i18n.ListFormatSymbols_ig_NG = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ii.
    - */
    -goog.labs.i18n.ListFormatSymbols_ii = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ii_CN.
    - */
    -goog.labs.i18n.ListFormatSymbols_ii_CN = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale is_IS.
    - */
    -goog.labs.i18n.ListFormatSymbols_is_IS = {
    -  GENDER_STYLE: 1,
    -  LIST_TWO: '{0} og {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} og {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale it_CH.
    - */
    -goog.labs.i18n.ListFormatSymbols_it_CH = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} e {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} e {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale it_IT.
    - */
    -goog.labs.i18n.ListFormatSymbols_it_IT = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} e {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} e {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale it_SM.
    - */
    -goog.labs.i18n.ListFormatSymbols_it_SM = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} e {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} e {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ja_JP.
    - */
    -goog.labs.i18n.ListFormatSymbols_ja_JP = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}、{1}',
    -  LIST_START: '{0}、{1}',
    -  LIST_MIDDLE: '{0}、{1}',
    -  LIST_END: '{0}、{1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale jgo.
    - */
    -goog.labs.i18n.ListFormatSymbols_jgo = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} pɔp {1}',
    -  LIST_START: '{0}, ŋ́gɛ {1}',
    -  LIST_MIDDLE: '{0}, ŋ́gɛ {1}',
    -  LIST_END: '{0}, ḿbɛn ŋ́gɛ {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale jgo_CM.
    - */
    -goog.labs.i18n.ListFormatSymbols_jgo_CM = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} pɔp {1}',
    -  LIST_START: '{0}, ŋ́gɛ {1}',
    -  LIST_MIDDLE: '{0}, ŋ́gɛ {1}',
    -  LIST_END: '{0}, ḿbɛn ŋ́gɛ {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale jmc.
    - */
    -goog.labs.i18n.ListFormatSymbols_jmc = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale jmc_TZ.
    - */
    -goog.labs.i18n.ListFormatSymbols_jmc_TZ = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ka_GE.
    - */
    -goog.labs.i18n.ListFormatSymbols_ka_GE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} და {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} და {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale kab.
    - */
    -goog.labs.i18n.ListFormatSymbols_kab = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale kab_DZ.
    - */
    -goog.labs.i18n.ListFormatSymbols_kab_DZ = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale kam.
    - */
    -goog.labs.i18n.ListFormatSymbols_kam = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale kam_KE.
    - */
    -goog.labs.i18n.ListFormatSymbols_kam_KE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale kde.
    - */
    -goog.labs.i18n.ListFormatSymbols_kde = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale kde_TZ.
    - */
    -goog.labs.i18n.ListFormatSymbols_kde_TZ = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale kea.
    - */
    -goog.labs.i18n.ListFormatSymbols_kea = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} y {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} y {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale kea_CV.
    - */
    -goog.labs.i18n.ListFormatSymbols_kea_CV = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} y {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} y {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale khq.
    - */
    -goog.labs.i18n.ListFormatSymbols_khq = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale khq_ML.
    - */
    -goog.labs.i18n.ListFormatSymbols_khq_ML = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ki.
    - */
    -goog.labs.i18n.ListFormatSymbols_ki = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ki_KE.
    - */
    -goog.labs.i18n.ListFormatSymbols_ki_KE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale kk_Cyrl.
    - */
    -goog.labs.i18n.ListFormatSymbols_kk_Cyrl = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} және {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale kk_Cyrl_KZ.
    - */
    -goog.labs.i18n.ListFormatSymbols_kk_Cyrl_KZ = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} және {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale kkj.
    - */
    -goog.labs.i18n.ListFormatSymbols_kkj = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale kkj_CM.
    - */
    -goog.labs.i18n.ListFormatSymbols_kkj_CM = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale kl.
    - */
    -goog.labs.i18n.ListFormatSymbols_kl = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale kl_GL.
    - */
    -goog.labs.i18n.ListFormatSymbols_kl_GL = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale kln.
    - */
    -goog.labs.i18n.ListFormatSymbols_kln = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale kln_KE.
    - */
    -goog.labs.i18n.ListFormatSymbols_kln_KE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale km_KH.
    - */
    -goog.labs.i18n.ListFormatSymbols_km_KH = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} និង​{1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale kn_IN.
    - */
    -goog.labs.i18n.ListFormatSymbols_kn_IN = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} ಮತ್ತು {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, ಮತ್ತು {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ko_KP.
    - */
    -goog.labs.i18n.ListFormatSymbols_ko_KP = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} 및 {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} 및 {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ko_KR.
    - */
    -goog.labs.i18n.ListFormatSymbols_ko_KR = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} 및 {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} 및 {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale kok.
    - */
    -goog.labs.i18n.ListFormatSymbols_kok = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale kok_IN.
    - */
    -goog.labs.i18n.ListFormatSymbols_kok_IN = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ks.
    - */
    -goog.labs.i18n.ListFormatSymbols_ks = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ks_Arab.
    - */
    -goog.labs.i18n.ListFormatSymbols_ks_Arab = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ks_Arab_IN.
    - */
    -goog.labs.i18n.ListFormatSymbols_ks_Arab_IN = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ksb.
    - */
    -goog.labs.i18n.ListFormatSymbols_ksb = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ksb_TZ.
    - */
    -goog.labs.i18n.ListFormatSymbols_ksb_TZ = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ksf.
    - */
    -goog.labs.i18n.ListFormatSymbols_ksf = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ksf_CM.
    - */
    -goog.labs.i18n.ListFormatSymbols_ksf_CM = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ksh.
    - */
    -goog.labs.i18n.ListFormatSymbols_ksh = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} un {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} un {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ksh_DE.
    - */
    -goog.labs.i18n.ListFormatSymbols_ksh_DE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} un {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} un {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale kw.
    - */
    -goog.labs.i18n.ListFormatSymbols_kw = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale kw_GB.
    - */
    -goog.labs.i18n.ListFormatSymbols_kw_GB = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ky_Cyrl.
    - */
    -goog.labs.i18n.ListFormatSymbols_ky_Cyrl = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} жана {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} жана {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ky_Cyrl_KG.
    - */
    -goog.labs.i18n.ListFormatSymbols_ky_Cyrl_KG = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} жана {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} жана {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale lag.
    - */
    -goog.labs.i18n.ListFormatSymbols_lag = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale lag_TZ.
    - */
    -goog.labs.i18n.ListFormatSymbols_lag_TZ = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale lb.
    - */
    -goog.labs.i18n.ListFormatSymbols_lb = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} a(n) {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} a(n) {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale lb_LU.
    - */
    -goog.labs.i18n.ListFormatSymbols_lb_LU = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} a(n) {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} a(n) {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale lg.
    - */
    -goog.labs.i18n.ListFormatSymbols_lg = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale lg_UG.
    - */
    -goog.labs.i18n.ListFormatSymbols_lg_UG = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale lkt.
    - */
    -goog.labs.i18n.ListFormatSymbols_lkt = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale lkt_US.
    - */
    -goog.labs.i18n.ListFormatSymbols_lkt_US = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ln_AO.
    - */
    -goog.labs.i18n.ListFormatSymbols_ln_AO = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ln_CD.
    - */
    -goog.labs.i18n.ListFormatSymbols_ln_CD = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ln_CF.
    - */
    -goog.labs.i18n.ListFormatSymbols_ln_CF = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ln_CG.
    - */
    -goog.labs.i18n.ListFormatSymbols_ln_CG = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale lo_LA.
    - */
    -goog.labs.i18n.ListFormatSymbols_lo_LA = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} ແລະ {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale lt_LT.
    - */
    -goog.labs.i18n.ListFormatSymbols_lt_LT = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} ir {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} ir {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale lu.
    - */
    -goog.labs.i18n.ListFormatSymbols_lu = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale lu_CD.
    - */
    -goog.labs.i18n.ListFormatSymbols_lu_CD = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale luo.
    - */
    -goog.labs.i18n.ListFormatSymbols_luo = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale luo_KE.
    - */
    -goog.labs.i18n.ListFormatSymbols_luo_KE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale luy.
    - */
    -goog.labs.i18n.ListFormatSymbols_luy = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale luy_KE.
    - */
    -goog.labs.i18n.ListFormatSymbols_luy_KE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale lv_LV.
    - */
    -goog.labs.i18n.ListFormatSymbols_lv_LV = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} un {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} un {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale mas.
    - */
    -goog.labs.i18n.ListFormatSymbols_mas = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale mas_KE.
    - */
    -goog.labs.i18n.ListFormatSymbols_mas_KE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale mas_TZ.
    - */
    -goog.labs.i18n.ListFormatSymbols_mas_TZ = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale mer.
    - */
    -goog.labs.i18n.ListFormatSymbols_mer = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale mer_KE.
    - */
    -goog.labs.i18n.ListFormatSymbols_mer_KE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale mfe.
    - */
    -goog.labs.i18n.ListFormatSymbols_mfe = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale mfe_MU.
    - */
    -goog.labs.i18n.ListFormatSymbols_mfe_MU = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale mg.
    - */
    -goog.labs.i18n.ListFormatSymbols_mg = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale mg_MG.
    - */
    -goog.labs.i18n.ListFormatSymbols_mg_MG = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale mgh.
    - */
    -goog.labs.i18n.ListFormatSymbols_mgh = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale mgh_MZ.
    - */
    -goog.labs.i18n.ListFormatSymbols_mgh_MZ = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale mgo.
    - */
    -goog.labs.i18n.ListFormatSymbols_mgo = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale mgo_CM.
    - */
    -goog.labs.i18n.ListFormatSymbols_mgo_CM = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale mk_MK.
    - */
    -goog.labs.i18n.ListFormatSymbols_mk_MK = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} и {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ml_IN.
    - */
    -goog.labs.i18n.ListFormatSymbols_ml_IN = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} കൂടാതെ {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1} എന്നിവ'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale mn_Cyrl.
    - */
    -goog.labs.i18n.ListFormatSymbols_mn_Cyrl = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale mn_Cyrl_MN.
    - */
    -goog.labs.i18n.ListFormatSymbols_mn_Cyrl_MN = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale mr_IN.
    - */
    -goog.labs.i18n.ListFormatSymbols_mr_IN = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} आणि {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} आणि {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ms_Latn.
    - */
    -goog.labs.i18n.ListFormatSymbols_ms_Latn = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} dan {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} dan {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ms_Latn_BN.
    - */
    -goog.labs.i18n.ListFormatSymbols_ms_Latn_BN = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} dan {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} dan {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ms_Latn_MY.
    - */
    -goog.labs.i18n.ListFormatSymbols_ms_Latn_MY = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} dan {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} dan {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ms_Latn_SG.
    - */
    -goog.labs.i18n.ListFormatSymbols_ms_Latn_SG = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} dan {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} dan {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale mt_MT.
    - */
    -goog.labs.i18n.ListFormatSymbols_mt_MT = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} u {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, u {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale mua.
    - */
    -goog.labs.i18n.ListFormatSymbols_mua = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale mua_CM.
    - */
    -goog.labs.i18n.ListFormatSymbols_mua_CM = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale my_MM.
    - */
    -goog.labs.i18n.ListFormatSymbols_my_MM = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}နှင့်{1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, နှင့်{1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale naq.
    - */
    -goog.labs.i18n.ListFormatSymbols_naq = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale naq_NA.
    - */
    -goog.labs.i18n.ListFormatSymbols_naq_NA = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale nb_NO.
    - */
    -goog.labs.i18n.ListFormatSymbols_nb_NO = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} og {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} og {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale nb_SJ.
    - */
    -goog.labs.i18n.ListFormatSymbols_nb_SJ = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} og {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} og {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale nd.
    - */
    -goog.labs.i18n.ListFormatSymbols_nd = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale nd_ZW.
    - */
    -goog.labs.i18n.ListFormatSymbols_nd_ZW = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ne_IN.
    - */
    -goog.labs.i18n.ListFormatSymbols_ne_IN = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} र {1}',
    -  LIST_START: '{0} र {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} र {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ne_NP.
    - */
    -goog.labs.i18n.ListFormatSymbols_ne_NP = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} र {1}',
    -  LIST_START: '{0} र {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} र {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale nl_AW.
    - */
    -goog.labs.i18n.ListFormatSymbols_nl_AW = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} en {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} en {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale nl_BE.
    - */
    -goog.labs.i18n.ListFormatSymbols_nl_BE = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} en {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} en {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale nl_BQ.
    - */
    -goog.labs.i18n.ListFormatSymbols_nl_BQ = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} en {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} en {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale nl_CW.
    - */
    -goog.labs.i18n.ListFormatSymbols_nl_CW = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} en {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} en {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale nl_NL.
    - */
    -goog.labs.i18n.ListFormatSymbols_nl_NL = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} en {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} en {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale nl_SR.
    - */
    -goog.labs.i18n.ListFormatSymbols_nl_SR = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} en {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} en {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale nl_SX.
    - */
    -goog.labs.i18n.ListFormatSymbols_nl_SX = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} en {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} en {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale nmg.
    - */
    -goog.labs.i18n.ListFormatSymbols_nmg = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale nmg_CM.
    - */
    -goog.labs.i18n.ListFormatSymbols_nmg_CM = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale nn.
    - */
    -goog.labs.i18n.ListFormatSymbols_nn = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} og {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} og {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale nn_NO.
    - */
    -goog.labs.i18n.ListFormatSymbols_nn_NO = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} og {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} og {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale nnh.
    - */
    -goog.labs.i18n.ListFormatSymbols_nnh = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale nnh_CM.
    - */
    -goog.labs.i18n.ListFormatSymbols_nnh_CM = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale nus.
    - */
    -goog.labs.i18n.ListFormatSymbols_nus = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale nus_SD.
    - */
    -goog.labs.i18n.ListFormatSymbols_nus_SD = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale nyn.
    - */
    -goog.labs.i18n.ListFormatSymbols_nyn = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale nyn_UG.
    - */
    -goog.labs.i18n.ListFormatSymbols_nyn_UG = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale om.
    - */
    -goog.labs.i18n.ListFormatSymbols_om = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale om_ET.
    - */
    -goog.labs.i18n.ListFormatSymbols_om_ET = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale om_KE.
    - */
    -goog.labs.i18n.ListFormatSymbols_om_KE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale or_IN.
    - */
    -goog.labs.i18n.ListFormatSymbols_or_IN = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale os.
    - */
    -goog.labs.i18n.ListFormatSymbols_os = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} ӕмӕ {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} ӕмӕ {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale os_GE.
    - */
    -goog.labs.i18n.ListFormatSymbols_os_GE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} ӕмӕ {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} ӕмӕ {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale os_RU.
    - */
    -goog.labs.i18n.ListFormatSymbols_os_RU = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} ӕмӕ {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} ӕмӕ {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale pa_Arab.
    - */
    -goog.labs.i18n.ListFormatSymbols_pa_Arab = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale pa_Arab_PK.
    - */
    -goog.labs.i18n.ListFormatSymbols_pa_Arab_PK = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale pa_Guru.
    - */
    -goog.labs.i18n.ListFormatSymbols_pa_Guru = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} ਅਤੇ {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} ਅਤੇ {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale pa_Guru_IN.
    - */
    -goog.labs.i18n.ListFormatSymbols_pa_Guru_IN = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} ਅਤੇ {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} ਅਤੇ {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale pl_PL.
    - */
    -goog.labs.i18n.ListFormatSymbols_pl_PL = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} i {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} i {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ps.
    - */
    -goog.labs.i18n.ListFormatSymbols_ps = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ps_AF.
    - */
    -goog.labs.i18n.ListFormatSymbols_ps_AF = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale pt_AO.
    - */
    -goog.labs.i18n.ListFormatSymbols_pt_AO = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} e {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} e {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale pt_CV.
    - */
    -goog.labs.i18n.ListFormatSymbols_pt_CV = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} e {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} e {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale pt_GW.
    - */
    -goog.labs.i18n.ListFormatSymbols_pt_GW = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} e {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} e {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale pt_MO.
    - */
    -goog.labs.i18n.ListFormatSymbols_pt_MO = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} e {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} e {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale pt_MZ.
    - */
    -goog.labs.i18n.ListFormatSymbols_pt_MZ = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} e {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} e {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale pt_ST.
    - */
    -goog.labs.i18n.ListFormatSymbols_pt_ST = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} e {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} e {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale pt_TL.
    - */
    -goog.labs.i18n.ListFormatSymbols_pt_TL = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} e {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} e {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale qu.
    - */
    -goog.labs.i18n.ListFormatSymbols_qu = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale qu_BO.
    - */
    -goog.labs.i18n.ListFormatSymbols_qu_BO = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale qu_EC.
    - */
    -goog.labs.i18n.ListFormatSymbols_qu_EC = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale qu_PE.
    - */
    -goog.labs.i18n.ListFormatSymbols_qu_PE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale rm.
    - */
    -goog.labs.i18n.ListFormatSymbols_rm = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale rm_CH.
    - */
    -goog.labs.i18n.ListFormatSymbols_rm_CH = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale rn.
    - */
    -goog.labs.i18n.ListFormatSymbols_rn = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale rn_BI.
    - */
    -goog.labs.i18n.ListFormatSymbols_rn_BI = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ro_MD.
    - */
    -goog.labs.i18n.ListFormatSymbols_ro_MD = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} și {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} și {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ro_RO.
    - */
    -goog.labs.i18n.ListFormatSymbols_ro_RO = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} și {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} și {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale rof.
    - */
    -goog.labs.i18n.ListFormatSymbols_rof = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale rof_TZ.
    - */
    -goog.labs.i18n.ListFormatSymbols_rof_TZ = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ru_BY.
    - */
    -goog.labs.i18n.ListFormatSymbols_ru_BY = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} и {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} и {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ru_KG.
    - */
    -goog.labs.i18n.ListFormatSymbols_ru_KG = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} и {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} и {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ru_KZ.
    - */
    -goog.labs.i18n.ListFormatSymbols_ru_KZ = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} и {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} и {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ru_MD.
    - */
    -goog.labs.i18n.ListFormatSymbols_ru_MD = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} и {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} и {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ru_RU.
    - */
    -goog.labs.i18n.ListFormatSymbols_ru_RU = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} и {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} и {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ru_UA.
    - */
    -goog.labs.i18n.ListFormatSymbols_ru_UA = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} и {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} и {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale rw.
    - */
    -goog.labs.i18n.ListFormatSymbols_rw = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale rw_RW.
    - */
    -goog.labs.i18n.ListFormatSymbols_rw_RW = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale rwk.
    - */
    -goog.labs.i18n.ListFormatSymbols_rwk = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale rwk_TZ.
    - */
    -goog.labs.i18n.ListFormatSymbols_rwk_TZ = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sah.
    - */
    -goog.labs.i18n.ListFormatSymbols_sah = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sah_RU.
    - */
    -goog.labs.i18n.ListFormatSymbols_sah_RU = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale saq.
    - */
    -goog.labs.i18n.ListFormatSymbols_saq = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale saq_KE.
    - */
    -goog.labs.i18n.ListFormatSymbols_saq_KE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sbp.
    - */
    -goog.labs.i18n.ListFormatSymbols_sbp = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sbp_TZ.
    - */
    -goog.labs.i18n.ListFormatSymbols_sbp_TZ = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale se.
    - */
    -goog.labs.i18n.ListFormatSymbols_se = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} ja {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} ja {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale se_FI.
    - */
    -goog.labs.i18n.ListFormatSymbols_se_FI = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} ja {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} ja {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale se_NO.
    - */
    -goog.labs.i18n.ListFormatSymbols_se_NO = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} ja {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} ja {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale se_SE.
    - */
    -goog.labs.i18n.ListFormatSymbols_se_SE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} ja {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} ja {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale seh.
    - */
    -goog.labs.i18n.ListFormatSymbols_seh = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale seh_MZ.
    - */
    -goog.labs.i18n.ListFormatSymbols_seh_MZ = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ses.
    - */
    -goog.labs.i18n.ListFormatSymbols_ses = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ses_ML.
    - */
    -goog.labs.i18n.ListFormatSymbols_ses_ML = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sg.
    - */
    -goog.labs.i18n.ListFormatSymbols_sg = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sg_CF.
    - */
    -goog.labs.i18n.ListFormatSymbols_sg_CF = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale shi.
    - */
    -goog.labs.i18n.ListFormatSymbols_shi = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale shi_Latn.
    - */
    -goog.labs.i18n.ListFormatSymbols_shi_Latn = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale shi_Latn_MA.
    - */
    -goog.labs.i18n.ListFormatSymbols_shi_Latn_MA = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale shi_Tfng.
    - */
    -goog.labs.i18n.ListFormatSymbols_shi_Tfng = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale shi_Tfng_MA.
    - */
    -goog.labs.i18n.ListFormatSymbols_shi_Tfng_MA = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale si_LK.
    - */
    -goog.labs.i18n.ListFormatSymbols_si_LK = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} සහ {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, සහ {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sk_SK.
    - */
    -goog.labs.i18n.ListFormatSymbols_sk_SK = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} a {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} a {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sl_SI.
    - */
    -goog.labs.i18n.ListFormatSymbols_sl_SI = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} in {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} in {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale smn.
    - */
    -goog.labs.i18n.ListFormatSymbols_smn = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale smn_FI.
    - */
    -goog.labs.i18n.ListFormatSymbols_smn_FI = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sn.
    - */
    -goog.labs.i18n.ListFormatSymbols_sn = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sn_ZW.
    - */
    -goog.labs.i18n.ListFormatSymbols_sn_ZW = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale so.
    - */
    -goog.labs.i18n.ListFormatSymbols_so = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale so_DJ.
    - */
    -goog.labs.i18n.ListFormatSymbols_so_DJ = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale so_ET.
    - */
    -goog.labs.i18n.ListFormatSymbols_so_ET = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale so_KE.
    - */
    -goog.labs.i18n.ListFormatSymbols_so_KE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale so_SO.
    - */
    -goog.labs.i18n.ListFormatSymbols_so_SO = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sq_AL.
    - */
    -goog.labs.i18n.ListFormatSymbols_sq_AL = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} dhe {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} dhe {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sq_MK.
    - */
    -goog.labs.i18n.ListFormatSymbols_sq_MK = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} dhe {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} dhe {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sq_XK.
    - */
    -goog.labs.i18n.ListFormatSymbols_sq_XK = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} dhe {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} dhe {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sr_Cyrl.
    - */
    -goog.labs.i18n.ListFormatSymbols_sr_Cyrl = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} и {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} и {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sr_Cyrl_BA.
    - */
    -goog.labs.i18n.ListFormatSymbols_sr_Cyrl_BA = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} и {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} и {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sr_Cyrl_ME.
    - */
    -goog.labs.i18n.ListFormatSymbols_sr_Cyrl_ME = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} и {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} и {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sr_Cyrl_RS.
    - */
    -goog.labs.i18n.ListFormatSymbols_sr_Cyrl_RS = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} и {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} и {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sr_Cyrl_XK.
    - */
    -goog.labs.i18n.ListFormatSymbols_sr_Cyrl_XK = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} и {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} и {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sr_Latn.
    - */
    -goog.labs.i18n.ListFormatSymbols_sr_Latn = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} i {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} i {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sr_Latn_BA.
    - */
    -goog.labs.i18n.ListFormatSymbols_sr_Latn_BA = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} i {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} i {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sr_Latn_ME.
    - */
    -goog.labs.i18n.ListFormatSymbols_sr_Latn_ME = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} i {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} i {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sr_Latn_RS.
    - */
    -goog.labs.i18n.ListFormatSymbols_sr_Latn_RS = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} i {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} i {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sr_Latn_XK.
    - */
    -goog.labs.i18n.ListFormatSymbols_sr_Latn_XK = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} i {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} i {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sv_AX.
    - */
    -goog.labs.i18n.ListFormatSymbols_sv_AX = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} och {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} och {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sv_FI.
    - */
    -goog.labs.i18n.ListFormatSymbols_sv_FI = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} och {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} och {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sv_SE.
    - */
    -goog.labs.i18n.ListFormatSymbols_sv_SE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} och {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} och {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sw_KE.
    - */
    -goog.labs.i18n.ListFormatSymbols_sw_KE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} na {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, na {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sw_TZ.
    - */
    -goog.labs.i18n.ListFormatSymbols_sw_TZ = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} na {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, na {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale sw_UG.
    - */
    -goog.labs.i18n.ListFormatSymbols_sw_UG = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} na {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, na {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale swc.
    - */
    -goog.labs.i18n.ListFormatSymbols_swc = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale swc_CD.
    - */
    -goog.labs.i18n.ListFormatSymbols_swc_CD = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ta_IN.
    - */
    -goog.labs.i18n.ListFormatSymbols_ta_IN = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} மற்றும் {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} மற்றும் {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ta_LK.
    - */
    -goog.labs.i18n.ListFormatSymbols_ta_LK = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} மற்றும் {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} மற்றும் {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ta_MY.
    - */
    -goog.labs.i18n.ListFormatSymbols_ta_MY = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} மற்றும் {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} மற்றும் {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ta_SG.
    - */
    -goog.labs.i18n.ListFormatSymbols_ta_SG = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} மற்றும் {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} மற்றும் {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale te_IN.
    - */
    -goog.labs.i18n.ListFormatSymbols_te_IN = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} మరియు {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} మరియు {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale teo.
    - */
    -goog.labs.i18n.ListFormatSymbols_teo = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale teo_KE.
    - */
    -goog.labs.i18n.ListFormatSymbols_teo_KE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale teo_UG.
    - */
    -goog.labs.i18n.ListFormatSymbols_teo_UG = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale th_TH.
    - */
    -goog.labs.i18n.ListFormatSymbols_th_TH = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}และ{1}',
    -  LIST_START: '{0} {1}',
    -  LIST_MIDDLE: '{0} {1}',
    -  LIST_END: '{0} และ{1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ti.
    - */
    -goog.labs.i18n.ListFormatSymbols_ti = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ti_ER.
    - */
    -goog.labs.i18n.ListFormatSymbols_ti_ER = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ti_ET.
    - */
    -goog.labs.i18n.ListFormatSymbols_ti_ET = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale to.
    - */
    -goog.labs.i18n.ListFormatSymbols_to = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} mo {1}',
    -  LIST_START: '{0} mo {1}',
    -  LIST_MIDDLE: '{0} mo {1}',
    -  LIST_END: '{0} mo {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale to_TO.
    - */
    -goog.labs.i18n.ListFormatSymbols_to_TO = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} mo {1}',
    -  LIST_START: '{0} mo {1}',
    -  LIST_MIDDLE: '{0} mo {1}',
    -  LIST_END: '{0} mo {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale tr_CY.
    - */
    -goog.labs.i18n.ListFormatSymbols_tr_CY = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} ve {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} ve {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale tr_TR.
    - */
    -goog.labs.i18n.ListFormatSymbols_tr_TR = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} ve {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} ve {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale twq.
    - */
    -goog.labs.i18n.ListFormatSymbols_twq = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale twq_NE.
    - */
    -goog.labs.i18n.ListFormatSymbols_twq_NE = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale tzm.
    - */
    -goog.labs.i18n.ListFormatSymbols_tzm = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale tzm_Latn.
    - */
    -goog.labs.i18n.ListFormatSymbols_tzm_Latn = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale tzm_Latn_MA.
    - */
    -goog.labs.i18n.ListFormatSymbols_tzm_Latn_MA = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ug.
    - */
    -goog.labs.i18n.ListFormatSymbols_ug = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ug_Arab.
    - */
    -goog.labs.i18n.ListFormatSymbols_ug_Arab = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ug_Arab_CN.
    - */
    -goog.labs.i18n.ListFormatSymbols_ug_Arab_CN = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} and {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, and {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale uk_UA.
    - */
    -goog.labs.i18n.ListFormatSymbols_uk_UA = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} і {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} і {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ur_IN.
    - */
    -goog.labs.i18n.ListFormatSymbols_ur_IN = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} اور {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، اور {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale ur_PK.
    - */
    -goog.labs.i18n.ListFormatSymbols_ur_PK = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0} اور {1}',
    -  LIST_START: '{0}، {1}',
    -  LIST_MIDDLE: '{0}، {1}',
    -  LIST_END: '{0}، اور {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale uz_Arab.
    - */
    -goog.labs.i18n.ListFormatSymbols_uz_Arab = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale uz_Arab_AF.
    - */
    -goog.labs.i18n.ListFormatSymbols_uz_Arab_AF = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale uz_Cyrl.
    - */
    -goog.labs.i18n.ListFormatSymbols_uz_Cyrl = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale uz_Cyrl_UZ.
    - */
    -goog.labs.i18n.ListFormatSymbols_uz_Cyrl_UZ = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale uz_Latn.
    - */
    -goog.labs.i18n.ListFormatSymbols_uz_Latn = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} va {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} va {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale uz_Latn_UZ.
    - */
    -goog.labs.i18n.ListFormatSymbols_uz_Latn_UZ = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} va {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} va {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale vai.
    - */
    -goog.labs.i18n.ListFormatSymbols_vai = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale vai_Latn.
    - */
    -goog.labs.i18n.ListFormatSymbols_vai_Latn = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale vai_Latn_LR.
    - */
    -goog.labs.i18n.ListFormatSymbols_vai_Latn_LR = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale vai_Vaii.
    - */
    -goog.labs.i18n.ListFormatSymbols_vai_Vaii = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale vai_Vaii_LR.
    - */
    -goog.labs.i18n.ListFormatSymbols_vai_Vaii_LR = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale vi_VN.
    - */
    -goog.labs.i18n.ListFormatSymbols_vi_VN = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} và {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} và {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale vun.
    - */
    -goog.labs.i18n.ListFormatSymbols_vun = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale vun_TZ.
    - */
    -goog.labs.i18n.ListFormatSymbols_vun_TZ = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale wae.
    - */
    -goog.labs.i18n.ListFormatSymbols_wae = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} und {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} und {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale wae_CH.
    - */
    -goog.labs.i18n.ListFormatSymbols_wae_CH = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0} und {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0} und {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale xog.
    - */
    -goog.labs.i18n.ListFormatSymbols_xog = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale xog_UG.
    - */
    -goog.labs.i18n.ListFormatSymbols_xog_UG = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale yav.
    - */
    -goog.labs.i18n.ListFormatSymbols_yav = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale yav_CM.
    - */
    -goog.labs.i18n.ListFormatSymbols_yav_CM = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale yi.
    - */
    -goog.labs.i18n.ListFormatSymbols_yi = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale yi_001.
    - */
    -goog.labs.i18n.ListFormatSymbols_yi_001 = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale yo.
    - */
    -goog.labs.i18n.ListFormatSymbols_yo = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale yo_BJ.
    - */
    -goog.labs.i18n.ListFormatSymbols_yo_BJ = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale yo_NG.
    - */
    -goog.labs.i18n.ListFormatSymbols_yo_NG = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale zgh.
    - */
    -goog.labs.i18n.ListFormatSymbols_zgh = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale zgh_MA.
    - */
    -goog.labs.i18n.ListFormatSymbols_zgh_MA = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: '{0}, {1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, {1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale zh_Hans.
    - */
    -goog.labs.i18n.ListFormatSymbols_zh_Hans = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0}和{1}',
    -  LIST_START: '{0}、{1}',
    -  LIST_MIDDLE: '{0}、{1}',
    -  LIST_END: '{0}和{1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale zh_Hans_CN.
    - */
    -goog.labs.i18n.ListFormatSymbols_zh_Hans_CN = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0}和{1}',
    -  LIST_START: '{0}、{1}',
    -  LIST_MIDDLE: '{0}、{1}',
    -  LIST_END: '{0}和{1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale zh_Hans_HK.
    - */
    -goog.labs.i18n.ListFormatSymbols_zh_Hans_HK = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0}和{1}',
    -  LIST_START: '{0}、{1}',
    -  LIST_MIDDLE: '{0}、{1}',
    -  LIST_END: '{0}和{1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale zh_Hans_MO.
    - */
    -goog.labs.i18n.ListFormatSymbols_zh_Hans_MO = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0}和{1}',
    -  LIST_START: '{0}、{1}',
    -  LIST_MIDDLE: '{0}、{1}',
    -  LIST_END: '{0}和{1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale zh_Hans_SG.
    - */
    -goog.labs.i18n.ListFormatSymbols_zh_Hans_SG = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0}和{1}',
    -  LIST_START: '{0}、{1}',
    -  LIST_MIDDLE: '{0}、{1}',
    -  LIST_END: '{0}和{1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale zh_Hant.
    - */
    -goog.labs.i18n.ListFormatSymbols_zh_Hant = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0}和{1}',
    -  LIST_START: '{0}、{1}',
    -  LIST_MIDDLE: '{0}、{1}',
    -  LIST_END: '{0}和{1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale zh_Hant_HK.
    - */
    -goog.labs.i18n.ListFormatSymbols_zh_Hant_HK = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0}和{1}',
    -  LIST_START: '{0}、{1}',
    -  LIST_MIDDLE: '{0}、{1}',
    -  LIST_END: '{0}和{1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale zh_Hant_MO.
    - */
    -goog.labs.i18n.ListFormatSymbols_zh_Hant_MO = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0}和{1}',
    -  LIST_START: '{0}、{1}',
    -  LIST_MIDDLE: '{0}、{1}',
    -  LIST_END: '{0}和{1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale zh_Hant_TW.
    - */
    -goog.labs.i18n.ListFormatSymbols_zh_Hant_TW = {
    -  GENDER_STYLE: 2,
    -  LIST_TWO: '{0}和{1}',
    -  LIST_START: '{0}、{1}',
    -  LIST_MIDDLE: '{0}、{1}',
    -  LIST_END: '{0}和{1}'
    -};
    -
    -
    -/**
    - * List formatting symbols for locale zu_ZA.
    - */
    -goog.labs.i18n.ListFormatSymbols_zu_ZA = {
    -  GENDER_STYLE: 0,
    -  LIST_TWO: 'I-{0} ne-{1}',
    -  LIST_START: '{0}, {1}',
    -  LIST_MIDDLE: '{0}, {1}',
    -  LIST_END: '{0}, ne-{1}'
    -};
    -
    -
    -/**
    - * Selecting symbols by locale.
    - */
    -if (goog.LOCALE == 'af_NA' || goog.LOCALE == 'af-NA') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_af_NA;
    -}
    -
    -if (goog.LOCALE == 'af_ZA' || goog.LOCALE == 'af-ZA') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_af_ZA;
    -}
    -
    -if (goog.LOCALE == 'agq') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_agq;
    -}
    -
    -if (goog.LOCALE == 'agq_CM' || goog.LOCALE == 'agq-CM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_agq_CM;
    -}
    -
    -if (goog.LOCALE == 'ak') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ak;
    -}
    -
    -if (goog.LOCALE == 'ak_GH' || goog.LOCALE == 'ak-GH') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ak_GH;
    -}
    -
    -if (goog.LOCALE == 'am_ET' || goog.LOCALE == 'am-ET') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_am_ET;
    -}
    -
    -if (goog.LOCALE == 'ar_001' || goog.LOCALE == 'ar-001') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ar_001;
    -}
    -
    -if (goog.LOCALE == 'ar_AE' || goog.LOCALE == 'ar-AE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ar_AE;
    -}
    -
    -if (goog.LOCALE == 'ar_BH' || goog.LOCALE == 'ar-BH') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ar_BH;
    -}
    -
    -if (goog.LOCALE == 'ar_DJ' || goog.LOCALE == 'ar-DJ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ar_DJ;
    -}
    -
    -if (goog.LOCALE == 'ar_DZ' || goog.LOCALE == 'ar-DZ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ar_DZ;
    -}
    -
    -if (goog.LOCALE == 'ar_EG' || goog.LOCALE == 'ar-EG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ar_EG;
    -}
    -
    -if (goog.LOCALE == 'ar_EH' || goog.LOCALE == 'ar-EH') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ar_EH;
    -}
    -
    -if (goog.LOCALE == 'ar_ER' || goog.LOCALE == 'ar-ER') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ar_ER;
    -}
    -
    -if (goog.LOCALE == 'ar_IL' || goog.LOCALE == 'ar-IL') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ar_IL;
    -}
    -
    -if (goog.LOCALE == 'ar_IQ' || goog.LOCALE == 'ar-IQ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ar_IQ;
    -}
    -
    -if (goog.LOCALE == 'ar_JO' || goog.LOCALE == 'ar-JO') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ar_JO;
    -}
    -
    -if (goog.LOCALE == 'ar_KM' || goog.LOCALE == 'ar-KM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ar_KM;
    -}
    -
    -if (goog.LOCALE == 'ar_KW' || goog.LOCALE == 'ar-KW') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ar_KW;
    -}
    -
    -if (goog.LOCALE == 'ar_LB' || goog.LOCALE == 'ar-LB') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ar_LB;
    -}
    -
    -if (goog.LOCALE == 'ar_LY' || goog.LOCALE == 'ar-LY') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ar_LY;
    -}
    -
    -if (goog.LOCALE == 'ar_MA' || goog.LOCALE == 'ar-MA') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ar_MA;
    -}
    -
    -if (goog.LOCALE == 'ar_MR' || goog.LOCALE == 'ar-MR') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ar_MR;
    -}
    -
    -if (goog.LOCALE == 'ar_OM' || goog.LOCALE == 'ar-OM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ar_OM;
    -}
    -
    -if (goog.LOCALE == 'ar_PS' || goog.LOCALE == 'ar-PS') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ar_PS;
    -}
    -
    -if (goog.LOCALE == 'ar_QA' || goog.LOCALE == 'ar-QA') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ar_QA;
    -}
    -
    -if (goog.LOCALE == 'ar_SA' || goog.LOCALE == 'ar-SA') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ar_SA;
    -}
    -
    -if (goog.LOCALE == 'ar_SD' || goog.LOCALE == 'ar-SD') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ar_SD;
    -}
    -
    -if (goog.LOCALE == 'ar_SO' || goog.LOCALE == 'ar-SO') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ar_SO;
    -}
    -
    -if (goog.LOCALE == 'ar_SS' || goog.LOCALE == 'ar-SS') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ar_SS;
    -}
    -
    -if (goog.LOCALE == 'ar_SY' || goog.LOCALE == 'ar-SY') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ar_SY;
    -}
    -
    -if (goog.LOCALE == 'ar_TD' || goog.LOCALE == 'ar-TD') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ar_TD;
    -}
    -
    -if (goog.LOCALE == 'ar_TN' || goog.LOCALE == 'ar-TN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ar_TN;
    -}
    -
    -if (goog.LOCALE == 'ar_YE' || goog.LOCALE == 'ar-YE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ar_YE;
    -}
    -
    -if (goog.LOCALE == 'as') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_as;
    -}
    -
    -if (goog.LOCALE == 'as_IN' || goog.LOCALE == 'as-IN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_as_IN;
    -}
    -
    -if (goog.LOCALE == 'asa') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_asa;
    -}
    -
    -if (goog.LOCALE == 'asa_TZ' || goog.LOCALE == 'asa-TZ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_asa_TZ;
    -}
    -
    -if (goog.LOCALE == 'az_Cyrl' || goog.LOCALE == 'az-Cyrl') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_az_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'az_Cyrl_AZ' || goog.LOCALE == 'az-Cyrl-AZ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_az_Cyrl_AZ;
    -}
    -
    -if (goog.LOCALE == 'az_Latn' || goog.LOCALE == 'az-Latn') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_az_Latn;
    -}
    -
    -if (goog.LOCALE == 'az_Latn_AZ' || goog.LOCALE == 'az-Latn-AZ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_az_Latn_AZ;
    -}
    -
    -if (goog.LOCALE == 'bas') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_bas;
    -}
    -
    -if (goog.LOCALE == 'bas_CM' || goog.LOCALE == 'bas-CM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_bas_CM;
    -}
    -
    -if (goog.LOCALE == 'be') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_be;
    -}
    -
    -if (goog.LOCALE == 'be_BY' || goog.LOCALE == 'be-BY') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_be_BY;
    -}
    -
    -if (goog.LOCALE == 'bem') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_bem;
    -}
    -
    -if (goog.LOCALE == 'bem_ZM' || goog.LOCALE == 'bem-ZM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_bem_ZM;
    -}
    -
    -if (goog.LOCALE == 'bez') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_bez;
    -}
    -
    -if (goog.LOCALE == 'bez_TZ' || goog.LOCALE == 'bez-TZ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_bez_TZ;
    -}
    -
    -if (goog.LOCALE == 'bg_BG' || goog.LOCALE == 'bg-BG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_bg_BG;
    -}
    -
    -if (goog.LOCALE == 'bm') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_bm;
    -}
    -
    -if (goog.LOCALE == 'bm_Latn' || goog.LOCALE == 'bm-Latn') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_bm_Latn;
    -}
    -
    -if (goog.LOCALE == 'bm_Latn_ML' || goog.LOCALE == 'bm-Latn-ML') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_bm_Latn_ML;
    -}
    -
    -if (goog.LOCALE == 'bn_BD' || goog.LOCALE == 'bn-BD') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_bn_BD;
    -}
    -
    -if (goog.LOCALE == 'bn_IN' || goog.LOCALE == 'bn-IN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_bn_IN;
    -}
    -
    -if (goog.LOCALE == 'bo') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_bo;
    -}
    -
    -if (goog.LOCALE == 'bo_CN' || goog.LOCALE == 'bo-CN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_bo_CN;
    -}
    -
    -if (goog.LOCALE == 'bo_IN' || goog.LOCALE == 'bo-IN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_bo_IN;
    -}
    -
    -if (goog.LOCALE == 'br_FR' || goog.LOCALE == 'br-FR') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_br_FR;
    -}
    -
    -if (goog.LOCALE == 'brx') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_brx;
    -}
    -
    -if (goog.LOCALE == 'brx_IN' || goog.LOCALE == 'brx-IN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_brx_IN;
    -}
    -
    -if (goog.LOCALE == 'bs') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_bs;
    -}
    -
    -if (goog.LOCALE == 'bs_Cyrl' || goog.LOCALE == 'bs-Cyrl') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_bs_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'bs_Cyrl_BA' || goog.LOCALE == 'bs-Cyrl-BA') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_bs_Cyrl_BA;
    -}
    -
    -if (goog.LOCALE == 'bs_Latn' || goog.LOCALE == 'bs-Latn') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_bs_Latn;
    -}
    -
    -if (goog.LOCALE == 'bs_Latn_BA' || goog.LOCALE == 'bs-Latn-BA') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_bs_Latn_BA;
    -}
    -
    -if (goog.LOCALE == 'ca_AD' || goog.LOCALE == 'ca-AD') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ca_AD;
    -}
    -
    -if (goog.LOCALE == 'ca_ES' || goog.LOCALE == 'ca-ES') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ca_ES;
    -}
    -
    -if (goog.LOCALE == 'ca_FR' || goog.LOCALE == 'ca-FR') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ca_FR;
    -}
    -
    -if (goog.LOCALE == 'ca_IT' || goog.LOCALE == 'ca-IT') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ca_IT;
    -}
    -
    -if (goog.LOCALE == 'cgg') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_cgg;
    -}
    -
    -if (goog.LOCALE == 'cgg_UG' || goog.LOCALE == 'cgg-UG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_cgg_UG;
    -}
    -
    -if (goog.LOCALE == 'chr_US' || goog.LOCALE == 'chr-US') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_chr_US;
    -}
    -
    -if (goog.LOCALE == 'cs_CZ' || goog.LOCALE == 'cs-CZ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_cs_CZ;
    -}
    -
    -if (goog.LOCALE == 'cy_GB' || goog.LOCALE == 'cy-GB') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_cy_GB;
    -}
    -
    -if (goog.LOCALE == 'da_DK' || goog.LOCALE == 'da-DK') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_da_DK;
    -}
    -
    -if (goog.LOCALE == 'da_GL' || goog.LOCALE == 'da-GL') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_da_GL;
    -}
    -
    -if (goog.LOCALE == 'dav') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_dav;
    -}
    -
    -if (goog.LOCALE == 'dav_KE' || goog.LOCALE == 'dav-KE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_dav_KE;
    -}
    -
    -if (goog.LOCALE == 'de_BE' || goog.LOCALE == 'de-BE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_de_BE;
    -}
    -
    -if (goog.LOCALE == 'de_DE' || goog.LOCALE == 'de-DE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_de_DE;
    -}
    -
    -if (goog.LOCALE == 'de_LI' || goog.LOCALE == 'de-LI') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_de_LI;
    -}
    -
    -if (goog.LOCALE == 'de_LU' || goog.LOCALE == 'de-LU') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_de_LU;
    -}
    -
    -if (goog.LOCALE == 'dje') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_dje;
    -}
    -
    -if (goog.LOCALE == 'dje_NE' || goog.LOCALE == 'dje-NE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_dje_NE;
    -}
    -
    -if (goog.LOCALE == 'dsb') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_dsb;
    -}
    -
    -if (goog.LOCALE == 'dsb_DE' || goog.LOCALE == 'dsb-DE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_dsb_DE;
    -}
    -
    -if (goog.LOCALE == 'dua') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_dua;
    -}
    -
    -if (goog.LOCALE == 'dua_CM' || goog.LOCALE == 'dua-CM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_dua_CM;
    -}
    -
    -if (goog.LOCALE == 'dyo') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_dyo;
    -}
    -
    -if (goog.LOCALE == 'dyo_SN' || goog.LOCALE == 'dyo-SN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_dyo_SN;
    -}
    -
    -if (goog.LOCALE == 'dz') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_dz;
    -}
    -
    -if (goog.LOCALE == 'dz_BT' || goog.LOCALE == 'dz-BT') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_dz_BT;
    -}
    -
    -if (goog.LOCALE == 'ebu') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ebu;
    -}
    -
    -if (goog.LOCALE == 'ebu_KE' || goog.LOCALE == 'ebu-KE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ebu_KE;
    -}
    -
    -if (goog.LOCALE == 'ee') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ee;
    -}
    -
    -if (goog.LOCALE == 'ee_GH' || goog.LOCALE == 'ee-GH') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ee_GH;
    -}
    -
    -if (goog.LOCALE == 'ee_TG' || goog.LOCALE == 'ee-TG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ee_TG;
    -}
    -
    -if (goog.LOCALE == 'el_CY' || goog.LOCALE == 'el-CY') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_el_CY;
    -}
    -
    -if (goog.LOCALE == 'el_GR' || goog.LOCALE == 'el-GR') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_el_GR;
    -}
    -
    -if (goog.LOCALE == 'en_001' || goog.LOCALE == 'en-001') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_001;
    -}
    -
    -if (goog.LOCALE == 'en_150' || goog.LOCALE == 'en-150') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_150;
    -}
    -
    -if (goog.LOCALE == 'en_AG' || goog.LOCALE == 'en-AG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_AG;
    -}
    -
    -if (goog.LOCALE == 'en_AI' || goog.LOCALE == 'en-AI') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_AI;
    -}
    -
    -if (goog.LOCALE == 'en_AS' || goog.LOCALE == 'en-AS') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_AS;
    -}
    -
    -if (goog.LOCALE == 'en_BB' || goog.LOCALE == 'en-BB') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_BB;
    -}
    -
    -if (goog.LOCALE == 'en_BE' || goog.LOCALE == 'en-BE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_BE;
    -}
    -
    -if (goog.LOCALE == 'en_BM' || goog.LOCALE == 'en-BM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_BM;
    -}
    -
    -if (goog.LOCALE == 'en_BS' || goog.LOCALE == 'en-BS') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_BS;
    -}
    -
    -if (goog.LOCALE == 'en_BW' || goog.LOCALE == 'en-BW') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_BW;
    -}
    -
    -if (goog.LOCALE == 'en_BZ' || goog.LOCALE == 'en-BZ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_BZ;
    -}
    -
    -if (goog.LOCALE == 'en_CA' || goog.LOCALE == 'en-CA') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_CA;
    -}
    -
    -if (goog.LOCALE == 'en_CC' || goog.LOCALE == 'en-CC') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_CC;
    -}
    -
    -if (goog.LOCALE == 'en_CK' || goog.LOCALE == 'en-CK') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_CK;
    -}
    -
    -if (goog.LOCALE == 'en_CM' || goog.LOCALE == 'en-CM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_CM;
    -}
    -
    -if (goog.LOCALE == 'en_CX' || goog.LOCALE == 'en-CX') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_CX;
    -}
    -
    -if (goog.LOCALE == 'en_DG' || goog.LOCALE == 'en-DG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_DG;
    -}
    -
    -if (goog.LOCALE == 'en_DM' || goog.LOCALE == 'en-DM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_DM;
    -}
    -
    -if (goog.LOCALE == 'en_ER' || goog.LOCALE == 'en-ER') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_ER;
    -}
    -
    -if (goog.LOCALE == 'en_FJ' || goog.LOCALE == 'en-FJ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_FJ;
    -}
    -
    -if (goog.LOCALE == 'en_FK' || goog.LOCALE == 'en-FK') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_FK;
    -}
    -
    -if (goog.LOCALE == 'en_FM' || goog.LOCALE == 'en-FM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_FM;
    -}
    -
    -if (goog.LOCALE == 'en_GD' || goog.LOCALE == 'en-GD') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_GD;
    -}
    -
    -if (goog.LOCALE == 'en_GG' || goog.LOCALE == 'en-GG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_GG;
    -}
    -
    -if (goog.LOCALE == 'en_GH' || goog.LOCALE == 'en-GH') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_GH;
    -}
    -
    -if (goog.LOCALE == 'en_GI' || goog.LOCALE == 'en-GI') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_GI;
    -}
    -
    -if (goog.LOCALE == 'en_GM' || goog.LOCALE == 'en-GM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_GM;
    -}
    -
    -if (goog.LOCALE == 'en_GU' || goog.LOCALE == 'en-GU') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_GU;
    -}
    -
    -if (goog.LOCALE == 'en_GY' || goog.LOCALE == 'en-GY') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_GY;
    -}
    -
    -if (goog.LOCALE == 'en_HK' || goog.LOCALE == 'en-HK') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_HK;
    -}
    -
    -if (goog.LOCALE == 'en_IM' || goog.LOCALE == 'en-IM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_IM;
    -}
    -
    -if (goog.LOCALE == 'en_IO' || goog.LOCALE == 'en-IO') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_IO;
    -}
    -
    -if (goog.LOCALE == 'en_JE' || goog.LOCALE == 'en-JE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_JE;
    -}
    -
    -if (goog.LOCALE == 'en_JM' || goog.LOCALE == 'en-JM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_JM;
    -}
    -
    -if (goog.LOCALE == 'en_KE' || goog.LOCALE == 'en-KE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_KE;
    -}
    -
    -if (goog.LOCALE == 'en_KI' || goog.LOCALE == 'en-KI') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_KI;
    -}
    -
    -if (goog.LOCALE == 'en_KN' || goog.LOCALE == 'en-KN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_KN;
    -}
    -
    -if (goog.LOCALE == 'en_KY' || goog.LOCALE == 'en-KY') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_KY;
    -}
    -
    -if (goog.LOCALE == 'en_LC' || goog.LOCALE == 'en-LC') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_LC;
    -}
    -
    -if (goog.LOCALE == 'en_LR' || goog.LOCALE == 'en-LR') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_LR;
    -}
    -
    -if (goog.LOCALE == 'en_LS' || goog.LOCALE == 'en-LS') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_LS;
    -}
    -
    -if (goog.LOCALE == 'en_MG' || goog.LOCALE == 'en-MG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_MG;
    -}
    -
    -if (goog.LOCALE == 'en_MH' || goog.LOCALE == 'en-MH') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_MH;
    -}
    -
    -if (goog.LOCALE == 'en_MO' || goog.LOCALE == 'en-MO') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_MO;
    -}
    -
    -if (goog.LOCALE == 'en_MP' || goog.LOCALE == 'en-MP') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_MP;
    -}
    -
    -if (goog.LOCALE == 'en_MS' || goog.LOCALE == 'en-MS') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_MS;
    -}
    -
    -if (goog.LOCALE == 'en_MT' || goog.LOCALE == 'en-MT') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_MT;
    -}
    -
    -if (goog.LOCALE == 'en_MU' || goog.LOCALE == 'en-MU') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_MU;
    -}
    -
    -if (goog.LOCALE == 'en_MW' || goog.LOCALE == 'en-MW') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_MW;
    -}
    -
    -if (goog.LOCALE == 'en_MY' || goog.LOCALE == 'en-MY') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_MY;
    -}
    -
    -if (goog.LOCALE == 'en_NA' || goog.LOCALE == 'en-NA') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_NA;
    -}
    -
    -if (goog.LOCALE == 'en_NF' || goog.LOCALE == 'en-NF') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_NF;
    -}
    -
    -if (goog.LOCALE == 'en_NG' || goog.LOCALE == 'en-NG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_NG;
    -}
    -
    -if (goog.LOCALE == 'en_NR' || goog.LOCALE == 'en-NR') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_NR;
    -}
    -
    -if (goog.LOCALE == 'en_NU' || goog.LOCALE == 'en-NU') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_NU;
    -}
    -
    -if (goog.LOCALE == 'en_NZ' || goog.LOCALE == 'en-NZ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_NZ;
    -}
    -
    -if (goog.LOCALE == 'en_PG' || goog.LOCALE == 'en-PG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_PG;
    -}
    -
    -if (goog.LOCALE == 'en_PH' || goog.LOCALE == 'en-PH') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_PH;
    -}
    -
    -if (goog.LOCALE == 'en_PK' || goog.LOCALE == 'en-PK') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_PK;
    -}
    -
    -if (goog.LOCALE == 'en_PN' || goog.LOCALE == 'en-PN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_PN;
    -}
    -
    -if (goog.LOCALE == 'en_PR' || goog.LOCALE == 'en-PR') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_PR;
    -}
    -
    -if (goog.LOCALE == 'en_PW' || goog.LOCALE == 'en-PW') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_PW;
    -}
    -
    -if (goog.LOCALE == 'en_RW' || goog.LOCALE == 'en-RW') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_RW;
    -}
    -
    -if (goog.LOCALE == 'en_SB' || goog.LOCALE == 'en-SB') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_SB;
    -}
    -
    -if (goog.LOCALE == 'en_SC' || goog.LOCALE == 'en-SC') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_SC;
    -}
    -
    -if (goog.LOCALE == 'en_SD' || goog.LOCALE == 'en-SD') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_SD;
    -}
    -
    -if (goog.LOCALE == 'en_SH' || goog.LOCALE == 'en-SH') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_SH;
    -}
    -
    -if (goog.LOCALE == 'en_SL' || goog.LOCALE == 'en-SL') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_SL;
    -}
    -
    -if (goog.LOCALE == 'en_SS' || goog.LOCALE == 'en-SS') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_SS;
    -}
    -
    -if (goog.LOCALE == 'en_SX' || goog.LOCALE == 'en-SX') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_SX;
    -}
    -
    -if (goog.LOCALE == 'en_SZ' || goog.LOCALE == 'en-SZ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_SZ;
    -}
    -
    -if (goog.LOCALE == 'en_TC' || goog.LOCALE == 'en-TC') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_TC;
    -}
    -
    -if (goog.LOCALE == 'en_TK' || goog.LOCALE == 'en-TK') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_TK;
    -}
    -
    -if (goog.LOCALE == 'en_TO' || goog.LOCALE == 'en-TO') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_TO;
    -}
    -
    -if (goog.LOCALE == 'en_TT' || goog.LOCALE == 'en-TT') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_TT;
    -}
    -
    -if (goog.LOCALE == 'en_TV' || goog.LOCALE == 'en-TV') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_TV;
    -}
    -
    -if (goog.LOCALE == 'en_TZ' || goog.LOCALE == 'en-TZ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_TZ;
    -}
    -
    -if (goog.LOCALE == 'en_UG' || goog.LOCALE == 'en-UG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_UG;
    -}
    -
    -if (goog.LOCALE == 'en_UM' || goog.LOCALE == 'en-UM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_UM;
    -}
    -
    -if (goog.LOCALE == 'en_US_POSIX' || goog.LOCALE == 'en-US-POSIX') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_US_POSIX;
    -}
    -
    -if (goog.LOCALE == 'en_VC' || goog.LOCALE == 'en-VC') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_VC;
    -}
    -
    -if (goog.LOCALE == 'en_VG' || goog.LOCALE == 'en-VG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_VG;
    -}
    -
    -if (goog.LOCALE == 'en_VI' || goog.LOCALE == 'en-VI') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_VI;
    -}
    -
    -if (goog.LOCALE == 'en_VU' || goog.LOCALE == 'en-VU') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_VU;
    -}
    -
    -if (goog.LOCALE == 'en_WS' || goog.LOCALE == 'en-WS') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_WS;
    -}
    -
    -if (goog.LOCALE == 'en_ZM' || goog.LOCALE == 'en-ZM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_ZM;
    -}
    -
    -if (goog.LOCALE == 'en_ZW' || goog.LOCALE == 'en-ZW') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_en_ZW;
    -}
    -
    -if (goog.LOCALE == 'eo') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_eo;
    -}
    -
    -if (goog.LOCALE == 'es_AR' || goog.LOCALE == 'es-AR') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_es_AR;
    -}
    -
    -if (goog.LOCALE == 'es_BO' || goog.LOCALE == 'es-BO') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_es_BO;
    -}
    -
    -if (goog.LOCALE == 'es_CL' || goog.LOCALE == 'es-CL') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_es_CL;
    -}
    -
    -if (goog.LOCALE == 'es_CO' || goog.LOCALE == 'es-CO') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_es_CO;
    -}
    -
    -if (goog.LOCALE == 'es_CR' || goog.LOCALE == 'es-CR') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_es_CR;
    -}
    -
    -if (goog.LOCALE == 'es_CU' || goog.LOCALE == 'es-CU') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_es_CU;
    -}
    -
    -if (goog.LOCALE == 'es_DO' || goog.LOCALE == 'es-DO') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_es_DO;
    -}
    -
    -if (goog.LOCALE == 'es_EA' || goog.LOCALE == 'es-EA') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_es_EA;
    -}
    -
    -if (goog.LOCALE == 'es_EC' || goog.LOCALE == 'es-EC') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_es_EC;
    -}
    -
    -if (goog.LOCALE == 'es_GQ' || goog.LOCALE == 'es-GQ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_es_GQ;
    -}
    -
    -if (goog.LOCALE == 'es_GT' || goog.LOCALE == 'es-GT') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_es_GT;
    -}
    -
    -if (goog.LOCALE == 'es_HN' || goog.LOCALE == 'es-HN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_es_HN;
    -}
    -
    -if (goog.LOCALE == 'es_IC' || goog.LOCALE == 'es-IC') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_es_IC;
    -}
    -
    -if (goog.LOCALE == 'es_MX' || goog.LOCALE == 'es-MX') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_es_MX;
    -}
    -
    -if (goog.LOCALE == 'es_NI' || goog.LOCALE == 'es-NI') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_es_NI;
    -}
    -
    -if (goog.LOCALE == 'es_PA' || goog.LOCALE == 'es-PA') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_es_PA;
    -}
    -
    -if (goog.LOCALE == 'es_PE' || goog.LOCALE == 'es-PE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_es_PE;
    -}
    -
    -if (goog.LOCALE == 'es_PH' || goog.LOCALE == 'es-PH') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_es_PH;
    -}
    -
    -if (goog.LOCALE == 'es_PR' || goog.LOCALE == 'es-PR') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_es_PR;
    -}
    -
    -if (goog.LOCALE == 'es_PY' || goog.LOCALE == 'es-PY') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_es_PY;
    -}
    -
    -if (goog.LOCALE == 'es_SV' || goog.LOCALE == 'es-SV') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_es_SV;
    -}
    -
    -if (goog.LOCALE == 'es_US' || goog.LOCALE == 'es-US') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_es_US;
    -}
    -
    -if (goog.LOCALE == 'es_UY' || goog.LOCALE == 'es-UY') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_es_UY;
    -}
    -
    -if (goog.LOCALE == 'es_VE' || goog.LOCALE == 'es-VE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_es_VE;
    -}
    -
    -if (goog.LOCALE == 'et_EE' || goog.LOCALE == 'et-EE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_et_EE;
    -}
    -
    -if (goog.LOCALE == 'eu_ES' || goog.LOCALE == 'eu-ES') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_eu_ES;
    -}
    -
    -if (goog.LOCALE == 'ewo') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ewo;
    -}
    -
    -if (goog.LOCALE == 'ewo_CM' || goog.LOCALE == 'ewo-CM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ewo_CM;
    -}
    -
    -if (goog.LOCALE == 'fa_AF' || goog.LOCALE == 'fa-AF') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fa_AF;
    -}
    -
    -if (goog.LOCALE == 'fa_IR' || goog.LOCALE == 'fa-IR') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fa_IR;
    -}
    -
    -if (goog.LOCALE == 'ff') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ff;
    -}
    -
    -if (goog.LOCALE == 'ff_CM' || goog.LOCALE == 'ff-CM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ff_CM;
    -}
    -
    -if (goog.LOCALE == 'ff_GN' || goog.LOCALE == 'ff-GN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ff_GN;
    -}
    -
    -if (goog.LOCALE == 'ff_MR' || goog.LOCALE == 'ff-MR') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ff_MR;
    -}
    -
    -if (goog.LOCALE == 'ff_SN' || goog.LOCALE == 'ff-SN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ff_SN;
    -}
    -
    -if (goog.LOCALE == 'fi_FI' || goog.LOCALE == 'fi-FI') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fi_FI;
    -}
    -
    -if (goog.LOCALE == 'fil_PH' || goog.LOCALE == 'fil-PH') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fil_PH;
    -}
    -
    -if (goog.LOCALE == 'fo') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fo;
    -}
    -
    -if (goog.LOCALE == 'fo_FO' || goog.LOCALE == 'fo-FO') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fo_FO;
    -}
    -
    -if (goog.LOCALE == 'fr_BE' || goog.LOCALE == 'fr-BE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_BE;
    -}
    -
    -if (goog.LOCALE == 'fr_BF' || goog.LOCALE == 'fr-BF') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_BF;
    -}
    -
    -if (goog.LOCALE == 'fr_BI' || goog.LOCALE == 'fr-BI') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_BI;
    -}
    -
    -if (goog.LOCALE == 'fr_BJ' || goog.LOCALE == 'fr-BJ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_BJ;
    -}
    -
    -if (goog.LOCALE == 'fr_BL' || goog.LOCALE == 'fr-BL') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_BL;
    -}
    -
    -if (goog.LOCALE == 'fr_CD' || goog.LOCALE == 'fr-CD') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_CD;
    -}
    -
    -if (goog.LOCALE == 'fr_CF' || goog.LOCALE == 'fr-CF') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_CF;
    -}
    -
    -if (goog.LOCALE == 'fr_CG' || goog.LOCALE == 'fr-CG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_CG;
    -}
    -
    -if (goog.LOCALE == 'fr_CH' || goog.LOCALE == 'fr-CH') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_CH;
    -}
    -
    -if (goog.LOCALE == 'fr_CI' || goog.LOCALE == 'fr-CI') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_CI;
    -}
    -
    -if (goog.LOCALE == 'fr_CM' || goog.LOCALE == 'fr-CM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_CM;
    -}
    -
    -if (goog.LOCALE == 'fr_DJ' || goog.LOCALE == 'fr-DJ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_DJ;
    -}
    -
    -if (goog.LOCALE == 'fr_DZ' || goog.LOCALE == 'fr-DZ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_DZ;
    -}
    -
    -if (goog.LOCALE == 'fr_FR' || goog.LOCALE == 'fr-FR') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_FR;
    -}
    -
    -if (goog.LOCALE == 'fr_GA' || goog.LOCALE == 'fr-GA') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_GA;
    -}
    -
    -if (goog.LOCALE == 'fr_GF' || goog.LOCALE == 'fr-GF') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_GF;
    -}
    -
    -if (goog.LOCALE == 'fr_GN' || goog.LOCALE == 'fr-GN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_GN;
    -}
    -
    -if (goog.LOCALE == 'fr_GP' || goog.LOCALE == 'fr-GP') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_GP;
    -}
    -
    -if (goog.LOCALE == 'fr_GQ' || goog.LOCALE == 'fr-GQ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_GQ;
    -}
    -
    -if (goog.LOCALE == 'fr_HT' || goog.LOCALE == 'fr-HT') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_HT;
    -}
    -
    -if (goog.LOCALE == 'fr_KM' || goog.LOCALE == 'fr-KM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_KM;
    -}
    -
    -if (goog.LOCALE == 'fr_LU' || goog.LOCALE == 'fr-LU') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_LU;
    -}
    -
    -if (goog.LOCALE == 'fr_MA' || goog.LOCALE == 'fr-MA') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_MA;
    -}
    -
    -if (goog.LOCALE == 'fr_MC' || goog.LOCALE == 'fr-MC') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_MC;
    -}
    -
    -if (goog.LOCALE == 'fr_MF' || goog.LOCALE == 'fr-MF') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_MF;
    -}
    -
    -if (goog.LOCALE == 'fr_MG' || goog.LOCALE == 'fr-MG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_MG;
    -}
    -
    -if (goog.LOCALE == 'fr_ML' || goog.LOCALE == 'fr-ML') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_ML;
    -}
    -
    -if (goog.LOCALE == 'fr_MQ' || goog.LOCALE == 'fr-MQ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_MQ;
    -}
    -
    -if (goog.LOCALE == 'fr_MR' || goog.LOCALE == 'fr-MR') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_MR;
    -}
    -
    -if (goog.LOCALE == 'fr_MU' || goog.LOCALE == 'fr-MU') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_MU;
    -}
    -
    -if (goog.LOCALE == 'fr_NC' || goog.LOCALE == 'fr-NC') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_NC;
    -}
    -
    -if (goog.LOCALE == 'fr_NE' || goog.LOCALE == 'fr-NE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_NE;
    -}
    -
    -if (goog.LOCALE == 'fr_PF' || goog.LOCALE == 'fr-PF') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_PF;
    -}
    -
    -if (goog.LOCALE == 'fr_PM' || goog.LOCALE == 'fr-PM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_PM;
    -}
    -
    -if (goog.LOCALE == 'fr_RE' || goog.LOCALE == 'fr-RE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_RE;
    -}
    -
    -if (goog.LOCALE == 'fr_RW' || goog.LOCALE == 'fr-RW') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_RW;
    -}
    -
    -if (goog.LOCALE == 'fr_SC' || goog.LOCALE == 'fr-SC') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_SC;
    -}
    -
    -if (goog.LOCALE == 'fr_SN' || goog.LOCALE == 'fr-SN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_SN;
    -}
    -
    -if (goog.LOCALE == 'fr_SY' || goog.LOCALE == 'fr-SY') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_SY;
    -}
    -
    -if (goog.LOCALE == 'fr_TD' || goog.LOCALE == 'fr-TD') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_TD;
    -}
    -
    -if (goog.LOCALE == 'fr_TG' || goog.LOCALE == 'fr-TG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_TG;
    -}
    -
    -if (goog.LOCALE == 'fr_TN' || goog.LOCALE == 'fr-TN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_TN;
    -}
    -
    -if (goog.LOCALE == 'fr_VU' || goog.LOCALE == 'fr-VU') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_VU;
    -}
    -
    -if (goog.LOCALE == 'fr_WF' || goog.LOCALE == 'fr-WF') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_WF;
    -}
    -
    -if (goog.LOCALE == 'fr_YT' || goog.LOCALE == 'fr-YT') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fr_YT;
    -}
    -
    -if (goog.LOCALE == 'fur') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fur;
    -}
    -
    -if (goog.LOCALE == 'fur_IT' || goog.LOCALE == 'fur-IT') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fur_IT;
    -}
    -
    -if (goog.LOCALE == 'fy') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fy;
    -}
    -
    -if (goog.LOCALE == 'fy_NL' || goog.LOCALE == 'fy-NL') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_fy_NL;
    -}
    -
    -if (goog.LOCALE == 'ga_IE' || goog.LOCALE == 'ga-IE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ga_IE;
    -}
    -
    -if (goog.LOCALE == 'gd') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_gd;
    -}
    -
    -if (goog.LOCALE == 'gd_GB' || goog.LOCALE == 'gd-GB') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_gd_GB;
    -}
    -
    -if (goog.LOCALE == 'gl_ES' || goog.LOCALE == 'gl-ES') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_gl_ES;
    -}
    -
    -if (goog.LOCALE == 'gsw_CH' || goog.LOCALE == 'gsw-CH') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_gsw_CH;
    -}
    -
    -if (goog.LOCALE == 'gsw_FR' || goog.LOCALE == 'gsw-FR') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_gsw_FR;
    -}
    -
    -if (goog.LOCALE == 'gsw_LI' || goog.LOCALE == 'gsw-LI') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_gsw_LI;
    -}
    -
    -if (goog.LOCALE == 'gu_IN' || goog.LOCALE == 'gu-IN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_gu_IN;
    -}
    -
    -if (goog.LOCALE == 'guz') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_guz;
    -}
    -
    -if (goog.LOCALE == 'guz_KE' || goog.LOCALE == 'guz-KE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_guz_KE;
    -}
    -
    -if (goog.LOCALE == 'gv') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_gv;
    -}
    -
    -if (goog.LOCALE == 'gv_IM' || goog.LOCALE == 'gv-IM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_gv_IM;
    -}
    -
    -if (goog.LOCALE == 'ha') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ha;
    -}
    -
    -if (goog.LOCALE == 'ha_Latn' || goog.LOCALE == 'ha-Latn') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ha_Latn;
    -}
    -
    -if (goog.LOCALE == 'ha_Latn_GH' || goog.LOCALE == 'ha-Latn-GH') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ha_Latn_GH;
    -}
    -
    -if (goog.LOCALE == 'ha_Latn_NE' || goog.LOCALE == 'ha-Latn-NE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ha_Latn_NE;
    -}
    -
    -if (goog.LOCALE == 'ha_Latn_NG' || goog.LOCALE == 'ha-Latn-NG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ha_Latn_NG;
    -}
    -
    -if (goog.LOCALE == 'haw_US' || goog.LOCALE == 'haw-US') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_haw_US;
    -}
    -
    -if (goog.LOCALE == 'he_IL' || goog.LOCALE == 'he-IL') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_he_IL;
    -}
    -
    -if (goog.LOCALE == 'hi_IN' || goog.LOCALE == 'hi-IN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_hi_IN;
    -}
    -
    -if (goog.LOCALE == 'hr_BA' || goog.LOCALE == 'hr-BA') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_hr_BA;
    -}
    -
    -if (goog.LOCALE == 'hr_HR' || goog.LOCALE == 'hr-HR') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_hr_HR;
    -}
    -
    -if (goog.LOCALE == 'hsb') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_hsb;
    -}
    -
    -if (goog.LOCALE == 'hsb_DE' || goog.LOCALE == 'hsb-DE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_hsb_DE;
    -}
    -
    -if (goog.LOCALE == 'hu_HU' || goog.LOCALE == 'hu-HU') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_hu_HU;
    -}
    -
    -if (goog.LOCALE == 'hy_AM' || goog.LOCALE == 'hy-AM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_hy_AM;
    -}
    -
    -if (goog.LOCALE == 'id_ID' || goog.LOCALE == 'id-ID') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_id_ID;
    -}
    -
    -if (goog.LOCALE == 'ig') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ig;
    -}
    -
    -if (goog.LOCALE == 'ig_NG' || goog.LOCALE == 'ig-NG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ig_NG;
    -}
    -
    -if (goog.LOCALE == 'ii') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ii;
    -}
    -
    -if (goog.LOCALE == 'ii_CN' || goog.LOCALE == 'ii-CN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ii_CN;
    -}
    -
    -if (goog.LOCALE == 'is_IS' || goog.LOCALE == 'is-IS') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_is_IS;
    -}
    -
    -if (goog.LOCALE == 'it_CH' || goog.LOCALE == 'it-CH') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_it_CH;
    -}
    -
    -if (goog.LOCALE == 'it_IT' || goog.LOCALE == 'it-IT') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_it_IT;
    -}
    -
    -if (goog.LOCALE == 'it_SM' || goog.LOCALE == 'it-SM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_it_SM;
    -}
    -
    -if (goog.LOCALE == 'ja_JP' || goog.LOCALE == 'ja-JP') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ja_JP;
    -}
    -
    -if (goog.LOCALE == 'jgo') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_jgo;
    -}
    -
    -if (goog.LOCALE == 'jgo_CM' || goog.LOCALE == 'jgo-CM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_jgo_CM;
    -}
    -
    -if (goog.LOCALE == 'jmc') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_jmc;
    -}
    -
    -if (goog.LOCALE == 'jmc_TZ' || goog.LOCALE == 'jmc-TZ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_jmc_TZ;
    -}
    -
    -if (goog.LOCALE == 'ka_GE' || goog.LOCALE == 'ka-GE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ka_GE;
    -}
    -
    -if (goog.LOCALE == 'kab') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_kab;
    -}
    -
    -if (goog.LOCALE == 'kab_DZ' || goog.LOCALE == 'kab-DZ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_kab_DZ;
    -}
    -
    -if (goog.LOCALE == 'kam') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_kam;
    -}
    -
    -if (goog.LOCALE == 'kam_KE' || goog.LOCALE == 'kam-KE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_kam_KE;
    -}
    -
    -if (goog.LOCALE == 'kde') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_kde;
    -}
    -
    -if (goog.LOCALE == 'kde_TZ' || goog.LOCALE == 'kde-TZ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_kde_TZ;
    -}
    -
    -if (goog.LOCALE == 'kea') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_kea;
    -}
    -
    -if (goog.LOCALE == 'kea_CV' || goog.LOCALE == 'kea-CV') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_kea_CV;
    -}
    -
    -if (goog.LOCALE == 'khq') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_khq;
    -}
    -
    -if (goog.LOCALE == 'khq_ML' || goog.LOCALE == 'khq-ML') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_khq_ML;
    -}
    -
    -if (goog.LOCALE == 'ki') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ki;
    -}
    -
    -if (goog.LOCALE == 'ki_KE' || goog.LOCALE == 'ki-KE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ki_KE;
    -}
    -
    -if (goog.LOCALE == 'kk_Cyrl' || goog.LOCALE == 'kk-Cyrl') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_kk_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'kk_Cyrl_KZ' || goog.LOCALE == 'kk-Cyrl-KZ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_kk_Cyrl_KZ;
    -}
    -
    -if (goog.LOCALE == 'kkj') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_kkj;
    -}
    -
    -if (goog.LOCALE == 'kkj_CM' || goog.LOCALE == 'kkj-CM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_kkj_CM;
    -}
    -
    -if (goog.LOCALE == 'kl') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_kl;
    -}
    -
    -if (goog.LOCALE == 'kl_GL' || goog.LOCALE == 'kl-GL') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_kl_GL;
    -}
    -
    -if (goog.LOCALE == 'kln') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_kln;
    -}
    -
    -if (goog.LOCALE == 'kln_KE' || goog.LOCALE == 'kln-KE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_kln_KE;
    -}
    -
    -if (goog.LOCALE == 'km_KH' || goog.LOCALE == 'km-KH') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_km_KH;
    -}
    -
    -if (goog.LOCALE == 'kn_IN' || goog.LOCALE == 'kn-IN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_kn_IN;
    -}
    -
    -if (goog.LOCALE == 'ko_KP' || goog.LOCALE == 'ko-KP') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ko_KP;
    -}
    -
    -if (goog.LOCALE == 'ko_KR' || goog.LOCALE == 'ko-KR') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ko_KR;
    -}
    -
    -if (goog.LOCALE == 'kok') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_kok;
    -}
    -
    -if (goog.LOCALE == 'kok_IN' || goog.LOCALE == 'kok-IN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_kok_IN;
    -}
    -
    -if (goog.LOCALE == 'ks') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ks;
    -}
    -
    -if (goog.LOCALE == 'ks_Arab' || goog.LOCALE == 'ks-Arab') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ks_Arab;
    -}
    -
    -if (goog.LOCALE == 'ks_Arab_IN' || goog.LOCALE == 'ks-Arab-IN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ks_Arab_IN;
    -}
    -
    -if (goog.LOCALE == 'ksb') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ksb;
    -}
    -
    -if (goog.LOCALE == 'ksb_TZ' || goog.LOCALE == 'ksb-TZ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ksb_TZ;
    -}
    -
    -if (goog.LOCALE == 'ksf') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ksf;
    -}
    -
    -if (goog.LOCALE == 'ksf_CM' || goog.LOCALE == 'ksf-CM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ksf_CM;
    -}
    -
    -if (goog.LOCALE == 'ksh') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ksh;
    -}
    -
    -if (goog.LOCALE == 'ksh_DE' || goog.LOCALE == 'ksh-DE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ksh_DE;
    -}
    -
    -if (goog.LOCALE == 'kw') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_kw;
    -}
    -
    -if (goog.LOCALE == 'kw_GB' || goog.LOCALE == 'kw-GB') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_kw_GB;
    -}
    -
    -if (goog.LOCALE == 'ky_Cyrl' || goog.LOCALE == 'ky-Cyrl') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ky_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'ky_Cyrl_KG' || goog.LOCALE == 'ky-Cyrl-KG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ky_Cyrl_KG;
    -}
    -
    -if (goog.LOCALE == 'lag') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_lag;
    -}
    -
    -if (goog.LOCALE == 'lag_TZ' || goog.LOCALE == 'lag-TZ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_lag_TZ;
    -}
    -
    -if (goog.LOCALE == 'lb') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_lb;
    -}
    -
    -if (goog.LOCALE == 'lb_LU' || goog.LOCALE == 'lb-LU') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_lb_LU;
    -}
    -
    -if (goog.LOCALE == 'lg') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_lg;
    -}
    -
    -if (goog.LOCALE == 'lg_UG' || goog.LOCALE == 'lg-UG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_lg_UG;
    -}
    -
    -if (goog.LOCALE == 'lkt') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_lkt;
    -}
    -
    -if (goog.LOCALE == 'lkt_US' || goog.LOCALE == 'lkt-US') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_lkt_US;
    -}
    -
    -if (goog.LOCALE == 'ln_AO' || goog.LOCALE == 'ln-AO') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ln_AO;
    -}
    -
    -if (goog.LOCALE == 'ln_CD' || goog.LOCALE == 'ln-CD') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ln_CD;
    -}
    -
    -if (goog.LOCALE == 'ln_CF' || goog.LOCALE == 'ln-CF') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ln_CF;
    -}
    -
    -if (goog.LOCALE == 'ln_CG' || goog.LOCALE == 'ln-CG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ln_CG;
    -}
    -
    -if (goog.LOCALE == 'lo_LA' || goog.LOCALE == 'lo-LA') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_lo_LA;
    -}
    -
    -if (goog.LOCALE == 'lt_LT' || goog.LOCALE == 'lt-LT') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_lt_LT;
    -}
    -
    -if (goog.LOCALE == 'lu') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_lu;
    -}
    -
    -if (goog.LOCALE == 'lu_CD' || goog.LOCALE == 'lu-CD') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_lu_CD;
    -}
    -
    -if (goog.LOCALE == 'luo') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_luo;
    -}
    -
    -if (goog.LOCALE == 'luo_KE' || goog.LOCALE == 'luo-KE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_luo_KE;
    -}
    -
    -if (goog.LOCALE == 'luy') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_luy;
    -}
    -
    -if (goog.LOCALE == 'luy_KE' || goog.LOCALE == 'luy-KE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_luy_KE;
    -}
    -
    -if (goog.LOCALE == 'lv_LV' || goog.LOCALE == 'lv-LV') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_lv_LV;
    -}
    -
    -if (goog.LOCALE == 'mas') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_mas;
    -}
    -
    -if (goog.LOCALE == 'mas_KE' || goog.LOCALE == 'mas-KE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_mas_KE;
    -}
    -
    -if (goog.LOCALE == 'mas_TZ' || goog.LOCALE == 'mas-TZ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_mas_TZ;
    -}
    -
    -if (goog.LOCALE == 'mer') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_mer;
    -}
    -
    -if (goog.LOCALE == 'mer_KE' || goog.LOCALE == 'mer-KE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_mer_KE;
    -}
    -
    -if (goog.LOCALE == 'mfe') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_mfe;
    -}
    -
    -if (goog.LOCALE == 'mfe_MU' || goog.LOCALE == 'mfe-MU') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_mfe_MU;
    -}
    -
    -if (goog.LOCALE == 'mg') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_mg;
    -}
    -
    -if (goog.LOCALE == 'mg_MG' || goog.LOCALE == 'mg-MG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_mg_MG;
    -}
    -
    -if (goog.LOCALE == 'mgh') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_mgh;
    -}
    -
    -if (goog.LOCALE == 'mgh_MZ' || goog.LOCALE == 'mgh-MZ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_mgh_MZ;
    -}
    -
    -if (goog.LOCALE == 'mgo') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_mgo;
    -}
    -
    -if (goog.LOCALE == 'mgo_CM' || goog.LOCALE == 'mgo-CM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_mgo_CM;
    -}
    -
    -if (goog.LOCALE == 'mk_MK' || goog.LOCALE == 'mk-MK') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_mk_MK;
    -}
    -
    -if (goog.LOCALE == 'ml_IN' || goog.LOCALE == 'ml-IN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ml_IN;
    -}
    -
    -if (goog.LOCALE == 'mn_Cyrl' || goog.LOCALE == 'mn-Cyrl') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_mn_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'mn_Cyrl_MN' || goog.LOCALE == 'mn-Cyrl-MN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_mn_Cyrl_MN;
    -}
    -
    -if (goog.LOCALE == 'mr_IN' || goog.LOCALE == 'mr-IN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_mr_IN;
    -}
    -
    -if (goog.LOCALE == 'ms_Latn' || goog.LOCALE == 'ms-Latn') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ms_Latn;
    -}
    -
    -if (goog.LOCALE == 'ms_Latn_BN' || goog.LOCALE == 'ms-Latn-BN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ms_Latn_BN;
    -}
    -
    -if (goog.LOCALE == 'ms_Latn_MY' || goog.LOCALE == 'ms-Latn-MY') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ms_Latn_MY;
    -}
    -
    -if (goog.LOCALE == 'ms_Latn_SG' || goog.LOCALE == 'ms-Latn-SG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ms_Latn_SG;
    -}
    -
    -if (goog.LOCALE == 'mt_MT' || goog.LOCALE == 'mt-MT') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_mt_MT;
    -}
    -
    -if (goog.LOCALE == 'mua') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_mua;
    -}
    -
    -if (goog.LOCALE == 'mua_CM' || goog.LOCALE == 'mua-CM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_mua_CM;
    -}
    -
    -if (goog.LOCALE == 'my_MM' || goog.LOCALE == 'my-MM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_my_MM;
    -}
    -
    -if (goog.LOCALE == 'naq') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_naq;
    -}
    -
    -if (goog.LOCALE == 'naq_NA' || goog.LOCALE == 'naq-NA') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_naq_NA;
    -}
    -
    -if (goog.LOCALE == 'nb_NO' || goog.LOCALE == 'nb-NO') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_nb_NO;
    -}
    -
    -if (goog.LOCALE == 'nb_SJ' || goog.LOCALE == 'nb-SJ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_nb_SJ;
    -}
    -
    -if (goog.LOCALE == 'nd') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_nd;
    -}
    -
    -if (goog.LOCALE == 'nd_ZW' || goog.LOCALE == 'nd-ZW') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_nd_ZW;
    -}
    -
    -if (goog.LOCALE == 'ne_IN' || goog.LOCALE == 'ne-IN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ne_IN;
    -}
    -
    -if (goog.LOCALE == 'ne_NP' || goog.LOCALE == 'ne-NP') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ne_NP;
    -}
    -
    -if (goog.LOCALE == 'nl_AW' || goog.LOCALE == 'nl-AW') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_nl_AW;
    -}
    -
    -if (goog.LOCALE == 'nl_BE' || goog.LOCALE == 'nl-BE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_nl_BE;
    -}
    -
    -if (goog.LOCALE == 'nl_BQ' || goog.LOCALE == 'nl-BQ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_nl_BQ;
    -}
    -
    -if (goog.LOCALE == 'nl_CW' || goog.LOCALE == 'nl-CW') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_nl_CW;
    -}
    -
    -if (goog.LOCALE == 'nl_NL' || goog.LOCALE == 'nl-NL') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_nl_NL;
    -}
    -
    -if (goog.LOCALE == 'nl_SR' || goog.LOCALE == 'nl-SR') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_nl_SR;
    -}
    -
    -if (goog.LOCALE == 'nl_SX' || goog.LOCALE == 'nl-SX') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_nl_SX;
    -}
    -
    -if (goog.LOCALE == 'nmg') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_nmg;
    -}
    -
    -if (goog.LOCALE == 'nmg_CM' || goog.LOCALE == 'nmg-CM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_nmg_CM;
    -}
    -
    -if (goog.LOCALE == 'nn') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_nn;
    -}
    -
    -if (goog.LOCALE == 'nn_NO' || goog.LOCALE == 'nn-NO') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_nn_NO;
    -}
    -
    -if (goog.LOCALE == 'nnh') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_nnh;
    -}
    -
    -if (goog.LOCALE == 'nnh_CM' || goog.LOCALE == 'nnh-CM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_nnh_CM;
    -}
    -
    -if (goog.LOCALE == 'nus') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_nus;
    -}
    -
    -if (goog.LOCALE == 'nus_SD' || goog.LOCALE == 'nus-SD') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_nus_SD;
    -}
    -
    -if (goog.LOCALE == 'nyn') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_nyn;
    -}
    -
    -if (goog.LOCALE == 'nyn_UG' || goog.LOCALE == 'nyn-UG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_nyn_UG;
    -}
    -
    -if (goog.LOCALE == 'om') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_om;
    -}
    -
    -if (goog.LOCALE == 'om_ET' || goog.LOCALE == 'om-ET') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_om_ET;
    -}
    -
    -if (goog.LOCALE == 'om_KE' || goog.LOCALE == 'om-KE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_om_KE;
    -}
    -
    -if (goog.LOCALE == 'or_IN' || goog.LOCALE == 'or-IN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_or_IN;
    -}
    -
    -if (goog.LOCALE == 'os') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_os;
    -}
    -
    -if (goog.LOCALE == 'os_GE' || goog.LOCALE == 'os-GE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_os_GE;
    -}
    -
    -if (goog.LOCALE == 'os_RU' || goog.LOCALE == 'os-RU') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_os_RU;
    -}
    -
    -if (goog.LOCALE == 'pa_Arab' || goog.LOCALE == 'pa-Arab') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_pa_Arab;
    -}
    -
    -if (goog.LOCALE == 'pa_Arab_PK' || goog.LOCALE == 'pa-Arab-PK') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_pa_Arab_PK;
    -}
    -
    -if (goog.LOCALE == 'pa_Guru' || goog.LOCALE == 'pa-Guru') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_pa_Guru;
    -}
    -
    -if (goog.LOCALE == 'pa_Guru_IN' || goog.LOCALE == 'pa-Guru-IN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_pa_Guru_IN;
    -}
    -
    -if (goog.LOCALE == 'pl_PL' || goog.LOCALE == 'pl-PL') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_pl_PL;
    -}
    -
    -if (goog.LOCALE == 'ps') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ps;
    -}
    -
    -if (goog.LOCALE == 'ps_AF' || goog.LOCALE == 'ps-AF') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ps_AF;
    -}
    -
    -if (goog.LOCALE == 'pt_AO' || goog.LOCALE == 'pt-AO') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_pt_AO;
    -}
    -
    -if (goog.LOCALE == 'pt_CV' || goog.LOCALE == 'pt-CV') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_pt_CV;
    -}
    -
    -if (goog.LOCALE == 'pt_GW' || goog.LOCALE == 'pt-GW') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_pt_GW;
    -}
    -
    -if (goog.LOCALE == 'pt_MO' || goog.LOCALE == 'pt-MO') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_pt_MO;
    -}
    -
    -if (goog.LOCALE == 'pt_MZ' || goog.LOCALE == 'pt-MZ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_pt_MZ;
    -}
    -
    -if (goog.LOCALE == 'pt_ST' || goog.LOCALE == 'pt-ST') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_pt_ST;
    -}
    -
    -if (goog.LOCALE == 'pt_TL' || goog.LOCALE == 'pt-TL') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_pt_TL;
    -}
    -
    -if (goog.LOCALE == 'qu') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_qu;
    -}
    -
    -if (goog.LOCALE == 'qu_BO' || goog.LOCALE == 'qu-BO') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_qu_BO;
    -}
    -
    -if (goog.LOCALE == 'qu_EC' || goog.LOCALE == 'qu-EC') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_qu_EC;
    -}
    -
    -if (goog.LOCALE == 'qu_PE' || goog.LOCALE == 'qu-PE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_qu_PE;
    -}
    -
    -if (goog.LOCALE == 'rm') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_rm;
    -}
    -
    -if (goog.LOCALE == 'rm_CH' || goog.LOCALE == 'rm-CH') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_rm_CH;
    -}
    -
    -if (goog.LOCALE == 'rn') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_rn;
    -}
    -
    -if (goog.LOCALE == 'rn_BI' || goog.LOCALE == 'rn-BI') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_rn_BI;
    -}
    -
    -if (goog.LOCALE == 'ro_MD' || goog.LOCALE == 'ro-MD') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ro_MD;
    -}
    -
    -if (goog.LOCALE == 'ro_RO' || goog.LOCALE == 'ro-RO') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ro_RO;
    -}
    -
    -if (goog.LOCALE == 'rof') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_rof;
    -}
    -
    -if (goog.LOCALE == 'rof_TZ' || goog.LOCALE == 'rof-TZ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_rof_TZ;
    -}
    -
    -if (goog.LOCALE == 'ru_BY' || goog.LOCALE == 'ru-BY') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ru_BY;
    -}
    -
    -if (goog.LOCALE == 'ru_KG' || goog.LOCALE == 'ru-KG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ru_KG;
    -}
    -
    -if (goog.LOCALE == 'ru_KZ' || goog.LOCALE == 'ru-KZ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ru_KZ;
    -}
    -
    -if (goog.LOCALE == 'ru_MD' || goog.LOCALE == 'ru-MD') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ru_MD;
    -}
    -
    -if (goog.LOCALE == 'ru_RU' || goog.LOCALE == 'ru-RU') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ru_RU;
    -}
    -
    -if (goog.LOCALE == 'ru_UA' || goog.LOCALE == 'ru-UA') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ru_UA;
    -}
    -
    -if (goog.LOCALE == 'rw') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_rw;
    -}
    -
    -if (goog.LOCALE == 'rw_RW' || goog.LOCALE == 'rw-RW') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_rw_RW;
    -}
    -
    -if (goog.LOCALE == 'rwk') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_rwk;
    -}
    -
    -if (goog.LOCALE == 'rwk_TZ' || goog.LOCALE == 'rwk-TZ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_rwk_TZ;
    -}
    -
    -if (goog.LOCALE == 'sah') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sah;
    -}
    -
    -if (goog.LOCALE == 'sah_RU' || goog.LOCALE == 'sah-RU') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sah_RU;
    -}
    -
    -if (goog.LOCALE == 'saq') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_saq;
    -}
    -
    -if (goog.LOCALE == 'saq_KE' || goog.LOCALE == 'saq-KE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_saq_KE;
    -}
    -
    -if (goog.LOCALE == 'sbp') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sbp;
    -}
    -
    -if (goog.LOCALE == 'sbp_TZ' || goog.LOCALE == 'sbp-TZ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sbp_TZ;
    -}
    -
    -if (goog.LOCALE == 'se') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_se;
    -}
    -
    -if (goog.LOCALE == 'se_FI' || goog.LOCALE == 'se-FI') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_se_FI;
    -}
    -
    -if (goog.LOCALE == 'se_NO' || goog.LOCALE == 'se-NO') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_se_NO;
    -}
    -
    -if (goog.LOCALE == 'se_SE' || goog.LOCALE == 'se-SE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_se_SE;
    -}
    -
    -if (goog.LOCALE == 'seh') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_seh;
    -}
    -
    -if (goog.LOCALE == 'seh_MZ' || goog.LOCALE == 'seh-MZ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_seh_MZ;
    -}
    -
    -if (goog.LOCALE == 'ses') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ses;
    -}
    -
    -if (goog.LOCALE == 'ses_ML' || goog.LOCALE == 'ses-ML') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ses_ML;
    -}
    -
    -if (goog.LOCALE == 'sg') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sg;
    -}
    -
    -if (goog.LOCALE == 'sg_CF' || goog.LOCALE == 'sg-CF') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sg_CF;
    -}
    -
    -if (goog.LOCALE == 'shi') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_shi;
    -}
    -
    -if (goog.LOCALE == 'shi_Latn' || goog.LOCALE == 'shi-Latn') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_shi_Latn;
    -}
    -
    -if (goog.LOCALE == 'shi_Latn_MA' || goog.LOCALE == 'shi-Latn-MA') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_shi_Latn_MA;
    -}
    -
    -if (goog.LOCALE == 'shi_Tfng' || goog.LOCALE == 'shi-Tfng') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_shi_Tfng;
    -}
    -
    -if (goog.LOCALE == 'shi_Tfng_MA' || goog.LOCALE == 'shi-Tfng-MA') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_shi_Tfng_MA;
    -}
    -
    -if (goog.LOCALE == 'si_LK' || goog.LOCALE == 'si-LK') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_si_LK;
    -}
    -
    -if (goog.LOCALE == 'sk_SK' || goog.LOCALE == 'sk-SK') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sk_SK;
    -}
    -
    -if (goog.LOCALE == 'sl_SI' || goog.LOCALE == 'sl-SI') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sl_SI;
    -}
    -
    -if (goog.LOCALE == 'smn') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_smn;
    -}
    -
    -if (goog.LOCALE == 'smn_FI' || goog.LOCALE == 'smn-FI') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_smn_FI;
    -}
    -
    -if (goog.LOCALE == 'sn') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sn;
    -}
    -
    -if (goog.LOCALE == 'sn_ZW' || goog.LOCALE == 'sn-ZW') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sn_ZW;
    -}
    -
    -if (goog.LOCALE == 'so') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_so;
    -}
    -
    -if (goog.LOCALE == 'so_DJ' || goog.LOCALE == 'so-DJ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_so_DJ;
    -}
    -
    -if (goog.LOCALE == 'so_ET' || goog.LOCALE == 'so-ET') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_so_ET;
    -}
    -
    -if (goog.LOCALE == 'so_KE' || goog.LOCALE == 'so-KE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_so_KE;
    -}
    -
    -if (goog.LOCALE == 'so_SO' || goog.LOCALE == 'so-SO') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_so_SO;
    -}
    -
    -if (goog.LOCALE == 'sq_AL' || goog.LOCALE == 'sq-AL') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sq_AL;
    -}
    -
    -if (goog.LOCALE == 'sq_MK' || goog.LOCALE == 'sq-MK') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sq_MK;
    -}
    -
    -if (goog.LOCALE == 'sq_XK' || goog.LOCALE == 'sq-XK') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sq_XK;
    -}
    -
    -if (goog.LOCALE == 'sr_Cyrl' || goog.LOCALE == 'sr-Cyrl') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sr_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'sr_Cyrl_BA' || goog.LOCALE == 'sr-Cyrl-BA') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sr_Cyrl_BA;
    -}
    -
    -if (goog.LOCALE == 'sr_Cyrl_ME' || goog.LOCALE == 'sr-Cyrl-ME') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sr_Cyrl_ME;
    -}
    -
    -if (goog.LOCALE == 'sr_Cyrl_RS' || goog.LOCALE == 'sr-Cyrl-RS') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sr_Cyrl_RS;
    -}
    -
    -if (goog.LOCALE == 'sr_Cyrl_XK' || goog.LOCALE == 'sr-Cyrl-XK') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sr_Cyrl_XK;
    -}
    -
    -if (goog.LOCALE == 'sr_Latn' || goog.LOCALE == 'sr-Latn') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sr_Latn;
    -}
    -
    -if (goog.LOCALE == 'sr_Latn_BA' || goog.LOCALE == 'sr-Latn-BA') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sr_Latn_BA;
    -}
    -
    -if (goog.LOCALE == 'sr_Latn_ME' || goog.LOCALE == 'sr-Latn-ME') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sr_Latn_ME;
    -}
    -
    -if (goog.LOCALE == 'sr_Latn_RS' || goog.LOCALE == 'sr-Latn-RS') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sr_Latn_RS;
    -}
    -
    -if (goog.LOCALE == 'sr_Latn_XK' || goog.LOCALE == 'sr-Latn-XK') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sr_Latn_XK;
    -}
    -
    -if (goog.LOCALE == 'sv_AX' || goog.LOCALE == 'sv-AX') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sv_AX;
    -}
    -
    -if (goog.LOCALE == 'sv_FI' || goog.LOCALE == 'sv-FI') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sv_FI;
    -}
    -
    -if (goog.LOCALE == 'sv_SE' || goog.LOCALE == 'sv-SE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sv_SE;
    -}
    -
    -if (goog.LOCALE == 'sw_KE' || goog.LOCALE == 'sw-KE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sw_KE;
    -}
    -
    -if (goog.LOCALE == 'sw_TZ' || goog.LOCALE == 'sw-TZ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sw_TZ;
    -}
    -
    -if (goog.LOCALE == 'sw_UG' || goog.LOCALE == 'sw-UG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_sw_UG;
    -}
    -
    -if (goog.LOCALE == 'swc') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_swc;
    -}
    -
    -if (goog.LOCALE == 'swc_CD' || goog.LOCALE == 'swc-CD') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_swc_CD;
    -}
    -
    -if (goog.LOCALE == 'ta_IN' || goog.LOCALE == 'ta-IN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ta_IN;
    -}
    -
    -if (goog.LOCALE == 'ta_LK' || goog.LOCALE == 'ta-LK') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ta_LK;
    -}
    -
    -if (goog.LOCALE == 'ta_MY' || goog.LOCALE == 'ta-MY') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ta_MY;
    -}
    -
    -if (goog.LOCALE == 'ta_SG' || goog.LOCALE == 'ta-SG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ta_SG;
    -}
    -
    -if (goog.LOCALE == 'te_IN' || goog.LOCALE == 'te-IN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_te_IN;
    -}
    -
    -if (goog.LOCALE == 'teo') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_teo;
    -}
    -
    -if (goog.LOCALE == 'teo_KE' || goog.LOCALE == 'teo-KE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_teo_KE;
    -}
    -
    -if (goog.LOCALE == 'teo_UG' || goog.LOCALE == 'teo-UG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_teo_UG;
    -}
    -
    -if (goog.LOCALE == 'th_TH' || goog.LOCALE == 'th-TH') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_th_TH;
    -}
    -
    -if (goog.LOCALE == 'ti') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ti;
    -}
    -
    -if (goog.LOCALE == 'ti_ER' || goog.LOCALE == 'ti-ER') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ti_ER;
    -}
    -
    -if (goog.LOCALE == 'ti_ET' || goog.LOCALE == 'ti-ET') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ti_ET;
    -}
    -
    -if (goog.LOCALE == 'to') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_to;
    -}
    -
    -if (goog.LOCALE == 'to_TO' || goog.LOCALE == 'to-TO') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_to_TO;
    -}
    -
    -if (goog.LOCALE == 'tr_CY' || goog.LOCALE == 'tr-CY') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_tr_CY;
    -}
    -
    -if (goog.LOCALE == 'tr_TR' || goog.LOCALE == 'tr-TR') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_tr_TR;
    -}
    -
    -if (goog.LOCALE == 'twq') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_twq;
    -}
    -
    -if (goog.LOCALE == 'twq_NE' || goog.LOCALE == 'twq-NE') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_twq_NE;
    -}
    -
    -if (goog.LOCALE == 'tzm') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_tzm;
    -}
    -
    -if (goog.LOCALE == 'tzm_Latn' || goog.LOCALE == 'tzm-Latn') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_tzm_Latn;
    -}
    -
    -if (goog.LOCALE == 'tzm_Latn_MA' || goog.LOCALE == 'tzm-Latn-MA') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_tzm_Latn_MA;
    -}
    -
    -if (goog.LOCALE == 'ug') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ug;
    -}
    -
    -if (goog.LOCALE == 'ug_Arab' || goog.LOCALE == 'ug-Arab') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ug_Arab;
    -}
    -
    -if (goog.LOCALE == 'ug_Arab_CN' || goog.LOCALE == 'ug-Arab-CN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ug_Arab_CN;
    -}
    -
    -if (goog.LOCALE == 'uk_UA' || goog.LOCALE == 'uk-UA') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_uk_UA;
    -}
    -
    -if (goog.LOCALE == 'ur_IN' || goog.LOCALE == 'ur-IN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ur_IN;
    -}
    -
    -if (goog.LOCALE == 'ur_PK' || goog.LOCALE == 'ur-PK') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_ur_PK;
    -}
    -
    -if (goog.LOCALE == 'uz_Arab' || goog.LOCALE == 'uz-Arab') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_uz_Arab;
    -}
    -
    -if (goog.LOCALE == 'uz_Arab_AF' || goog.LOCALE == 'uz-Arab-AF') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_uz_Arab_AF;
    -}
    -
    -if (goog.LOCALE == 'uz_Cyrl' || goog.LOCALE == 'uz-Cyrl') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_uz_Cyrl;
    -}
    -
    -if (goog.LOCALE == 'uz_Cyrl_UZ' || goog.LOCALE == 'uz-Cyrl-UZ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_uz_Cyrl_UZ;
    -}
    -
    -if (goog.LOCALE == 'uz_Latn' || goog.LOCALE == 'uz-Latn') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_uz_Latn;
    -}
    -
    -if (goog.LOCALE == 'uz_Latn_UZ' || goog.LOCALE == 'uz-Latn-UZ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_uz_Latn_UZ;
    -}
    -
    -if (goog.LOCALE == 'vai') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_vai;
    -}
    -
    -if (goog.LOCALE == 'vai_Latn' || goog.LOCALE == 'vai-Latn') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_vai_Latn;
    -}
    -
    -if (goog.LOCALE == 'vai_Latn_LR' || goog.LOCALE == 'vai-Latn-LR') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_vai_Latn_LR;
    -}
    -
    -if (goog.LOCALE == 'vai_Vaii' || goog.LOCALE == 'vai-Vaii') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_vai_Vaii;
    -}
    -
    -if (goog.LOCALE == 'vai_Vaii_LR' || goog.LOCALE == 'vai-Vaii-LR') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_vai_Vaii_LR;
    -}
    -
    -if (goog.LOCALE == 'vi_VN' || goog.LOCALE == 'vi-VN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_vi_VN;
    -}
    -
    -if (goog.LOCALE == 'vun') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_vun;
    -}
    -
    -if (goog.LOCALE == 'vun_TZ' || goog.LOCALE == 'vun-TZ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_vun_TZ;
    -}
    -
    -if (goog.LOCALE == 'wae') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_wae;
    -}
    -
    -if (goog.LOCALE == 'wae_CH' || goog.LOCALE == 'wae-CH') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_wae_CH;
    -}
    -
    -if (goog.LOCALE == 'xog') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_xog;
    -}
    -
    -if (goog.LOCALE == 'xog_UG' || goog.LOCALE == 'xog-UG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_xog_UG;
    -}
    -
    -if (goog.LOCALE == 'yav') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_yav;
    -}
    -
    -if (goog.LOCALE == 'yav_CM' || goog.LOCALE == 'yav-CM') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_yav_CM;
    -}
    -
    -if (goog.LOCALE == 'yi') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_yi;
    -}
    -
    -if (goog.LOCALE == 'yi_001' || goog.LOCALE == 'yi-001') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_yi_001;
    -}
    -
    -if (goog.LOCALE == 'yo') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_yo;
    -}
    -
    -if (goog.LOCALE == 'yo_BJ' || goog.LOCALE == 'yo-BJ') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_yo_BJ;
    -}
    -
    -if (goog.LOCALE == 'yo_NG' || goog.LOCALE == 'yo-NG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_yo_NG;
    -}
    -
    -if (goog.LOCALE == 'zgh') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_zgh;
    -}
    -
    -if (goog.LOCALE == 'zgh_MA' || goog.LOCALE == 'zgh-MA') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_zgh_MA;
    -}
    -
    -if (goog.LOCALE == 'zh_Hans' || goog.LOCALE == 'zh-Hans') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_zh_Hans;
    -}
    -
    -if (goog.LOCALE == 'zh_Hans_CN' || goog.LOCALE == 'zh-Hans-CN') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_zh_Hans_CN;
    -}
    -
    -if (goog.LOCALE == 'zh_Hans_HK' || goog.LOCALE == 'zh-Hans-HK') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_zh_Hans_HK;
    -}
    -
    -if (goog.LOCALE == 'zh_Hans_MO' || goog.LOCALE == 'zh-Hans-MO') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_zh_Hans_MO;
    -}
    -
    -if (goog.LOCALE == 'zh_Hans_SG' || goog.LOCALE == 'zh-Hans-SG') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_zh_Hans_SG;
    -}
    -
    -if (goog.LOCALE == 'zh_Hant' || goog.LOCALE == 'zh-Hant') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_zh_Hant;
    -}
    -
    -if (goog.LOCALE == 'zh_Hant_HK' || goog.LOCALE == 'zh-Hant-HK') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_zh_Hant_HK;
    -}
    -
    -if (goog.LOCALE == 'zh_Hant_MO' || goog.LOCALE == 'zh-Hant-MO') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_zh_Hant_MO;
    -}
    -
    -if (goog.LOCALE == 'zh_Hant_TW' || goog.LOCALE == 'zh-Hant-TW') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_zh_Hant_TW;
    -}
    -
    -if (goog.LOCALE == 'zu_ZA' || goog.LOCALE == 'zu-ZA') {
    -  goog.labs.i18n.ListFormatSymbols = goog.labs.i18n.ListFormatSymbols_zu_ZA;
    -}
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/iterable/iterable.js b/src/database/third_party/closure-library/closure/goog/labs/iterable/iterable.js
    deleted file mode 100644
    index df001d648df..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/iterable/iterable.js
    +++ /dev/null
    @@ -1,139 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Utilities for working with ES6 iterables.
    - * Note that this file is written ES5-only.
    - * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/The_Iterator_protocol
    - */
    -
    -goog.module('goog.labs.iterable');
    -
    -
    -/**
    - * Get the iterator for an iterable.
    - * @param {!Iterable<VALUE>} iterable
    - * @return {!Iterator<VALUE>}
    - * @template VALUE
    - */
    -exports.getIterator = function(iterable) {
    -  return iterable[goog.global.Symbol.iterator]();
    -};
    -
    -
    -/**
    - * Call a function with every value of an iterable.
    - *
    - * Warning: this function will never halt if given an iterable that
    - * is never exhausted.
    - *
    - * @param {!function(VALUE): void} f
    - * @param {!Iterable<VALUE>} iterable
    - * @template VALUE
    - */
    -exports.forEach = function(f, iterable) {
    -  var iterator = exports.getIterator(iterable);
    -  while (true) {
    -    var next = iterator.next();
    -    if (next.done) {
    -      return;
    -    }
    -    f(next.value);
    -  }
    -};
    -
    -
    -/**
    - * Maps the values of one iterable to create another iterable.
    - *
    - * When next() is called on the returned iterable, it will call the given
    - * function {@code f} with the next value of the given iterable
    - * {@code iterable} until the given iterable is exhausted.
    - *
    - * @param {!function(this: THIS, VALUE): RESULT} f
    - * @param {!Iterable<VALUE>} iterable
    - * @return {!Iterable<RESULT>} The created iterable that gives the mapped
    - *     values.
    - * @template THIS, VALUE, RESULT
    - */
    -exports.map = function(f, iterable) {
    -  return new FactoryIterable(function() {
    -    var iterator = exports.getIterator(iterable);
    -    return new MapIterator(f, iterator);
    -  });
    -};
    -
    -
    -
    -/**
    - * Helper class for {@code map}.
    - * @param {!function(VALUE): RESULT} f
    - * @param {!Iterator<VALUE>} iterator
    - * @constructor
    - * @implements {Iterator<RESULT>}
    - * @template VALUE, RESULT
    - */
    -var MapIterator = function(f, iterator) {
    -  /** @private */
    -  this.func_ = f;
    -  /** @private */
    -  this.iterator_ = iterator;
    -};
    -
    -
    -/**
    - * @override
    - */
    -MapIterator.prototype.next = function() {
    -  var nextObj = this.iterator_.next();
    -
    -  if (nextObj.done) {
    -    return {done: true, value: undefined};
    -  }
    -
    -  var mappedValue = this.func_(nextObj.value);
    -  return {
    -    done: false,
    -    value: mappedValue
    -  };
    -};
    -
    -
    -
    -/**
    - * Helper class to create an iterable with a given iterator factory.
    - * @param {function():!Iterator<VALUE>} iteratorFactory
    - * @constructor
    - * @implements {Iterable<VALUE>}
    - * @template VALUE
    - */
    -var FactoryIterable = function(iteratorFactory) {
    -  /**
    -   * @private
    -   */
    -  this.iteratorFactory_ = iteratorFactory;
    -};
    -
    -
    -// TODO(nnaze): For now, this section is not run if Symbol is not defined,
    -// since goog.global.Symbol.iterator will not be defined below.
    -// Determine best course of action if "Symbol" is not available.
    -if (goog.global.Symbol) {
    -  /**
    -   * @return {!Iterator<VALUE>}
    -   */
    -  FactoryIterable.prototype[goog.global.Symbol.iterator] = function() {
    -    return this.iteratorFactory_();
    -  };
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/iterable/iterable_test.js b/src/database/third_party/closure-library/closure/goog/labs/iterable/iterable_test.js
    deleted file mode 100644
    index 339790d0525..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/iterable/iterable_test.js
    +++ /dev/null
    @@ -1,146 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Tests for goog.labs.iterable
    - */
    -
    -goog.module('goog.labs.iterableTest');
    -
    -goog.module.declareTestMethods();
    -goog.setTestOnly();
    -
    -goog.require('goog.testing.jsunit');
    -
    -var iterable = goog.require('goog.labs.iterable');
    -var recordFunction = goog.require('goog.testing.recordFunction');
    -
    -
    -/**
    - * Create an iterator starting at "start" and increments up to
    - * (but not including) "stop".
    - */
    -function createRangeIterator(start, stop) {
    -  var value = start;
    -  var next = function() {
    -    if (value < stop) {
    -      return {
    -        value: value++,
    -        done: false
    -      };
    -    }
    -
    -    return {
    -      value: undefined,
    -      done: true
    -    };
    -  };
    -
    -  return {
    -    next: next
    -  };
    -}
    -
    -function createRangeIterable(start, stop) {
    -  var obj = {};
    -
    -  // Refer to goog.global['Symbol'] because otherwise this
    -  // is a parse error in earlier IEs.
    -  obj[goog.global['Symbol'].iterator] = function() {
    -    return createRangeIterator(start, stop);
    -  };
    -  return obj;
    -}
    -
    -function isSymbolDefined() {
    -  return !!goog.global['Symbol'];
    -}
    -
    -exports.testCreateRangeIterable = function() {
    -  // Do not run if Symbol does not exist in this browser.
    -  if (!isSymbolDefined()) {
    -    return;
    -  }
    -
    -  var rangeIterator = createRangeIterator(0, 3);
    -
    -  for (var i = 0; i < 3; i++) {
    -    assertObjectEquals({
    -      value: i,
    -      done: false
    -    }, rangeIterator.next());
    -  }
    -
    -  for (var i = 0; i < 3; i++) {
    -    assertObjectEquals({
    -      value: undefined,
    -      done: true
    -    }, rangeIterator.next());
    -  }
    -};
    -
    -exports.testForEach = function() {
    -  // Do not run if Symbol does not exist in this browser.
    -  if (!isSymbolDefined()) {
    -    return;
    -  }
    -
    -  var range = createRangeIterable(0, 3);
    -
    -  var callback = recordFunction();
    -  iterable.forEach(callback, range, self);
    -
    -  callback.assertCallCount(3);
    -
    -  var calls = callback.getCalls();
    -  for (var i = 0; i < calls.length; i++) {
    -    var call = calls[i];
    -    assertArrayEquals([i], call.getArguments());
    -  }
    -};
    -
    -exports.testMap = function() {
    -  // Do not run if Symbol does not exist in this browser.
    -  if (!isSymbolDefined()) {
    -    return;
    -  }
    -
    -  var range = createRangeIterable(0, 3);
    -
    -  function addTwo(i) {
    -    return i + 2;
    -  }
    -
    -  var newIterable = iterable.map(addTwo, range);
    -  var newIterator = iterable.getIterator(newIterable);
    -
    -  var nextObj = newIterator.next();
    -  assertEquals(2, nextObj.value);
    -  assertFalse(nextObj.done);
    -
    -  nextObj = newIterator.next();
    -  assertEquals(3, nextObj.value);
    -  assertFalse(nextObj.done);
    -
    -  nextObj = newIterator.next();
    -  assertEquals(4, nextObj.value);
    -  assertFalse(nextObj.done);
    -
    -  // Check that the iterator repeatedly signals done.
    -  for (var i = 0; i < 3; i++) {
    -    nextObj = newIterator.next();
    -    assertUndefined(nextObj.value);
    -    assertTrue(nextObj.done);
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/mock/mock.js b/src/database/third_party/closure-library/closure/goog/labs/mock/mock.js
    deleted file mode 100644
    index 436734f1f87..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/mock/mock.js
    +++ /dev/null
    @@ -1,861 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides a mocking framework in Closure to make unit tests easy
    - * to write and understand. The methods provided here can be used to replace
    - * implementations of existing objects with 'mock' objects to abstract out
    - * external services and dependencies thereby isolating the code under test.
    - * Apart from mocking, methods are also provided to just monitor calls to an
    - * object (spying) and returning specific values for some or all the inputs to
    - * methods (stubbing).
    - *
    - * Design doc : http://go/closuremock
    - *
    - */
    -
    -
    -goog.provide('goog.labs.mock');
    -goog.provide('goog.labs.mock.VerificationError');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.debug');
    -goog.require('goog.debug.Error');
    -goog.require('goog.functions');
    -goog.require('goog.object');
    -
    -
    -/**
    - * Mocks a given object or class.
    - *
    - * @param {!Object} objectOrClass An instance or a constructor of a class to be
    - *     mocked.
    - * @return {!Object} The mocked object.
    - */
    -goog.labs.mock.mock = function(objectOrClass) {
    -  // Go over properties of 'objectOrClass' and create a MockManager to
    -  // be used for stubbing out calls to methods.
    -  var mockObjectManager = new goog.labs.mock.MockObjectManager_(objectOrClass);
    -  var mockedObject = mockObjectManager.getMockedItem();
    -  goog.asserts.assertObject(mockedObject);
    -  return /** @type {!Object} */ (mockedObject);
    -};
    -
    -
    -/**
    - * Mocks a given function.
    - *
    - * @param {!Function} func A function to be mocked.
    - * @return {!Function} The mocked function.
    - */
    -goog.labs.mock.mockFunction = function(func) {
    -  var mockFuncManager = new goog.labs.mock.MockFunctionManager_(func);
    -  var mockedFunction = mockFuncManager.getMockedItem();
    -  goog.asserts.assertFunction(mockedFunction);
    -  return /** @type {!Function} */ (mockedFunction);
    -};
    -
    -
    -/**
    - * Spies on a given object.
    - *
    - * @param {!Object} obj The object to be spied on.
    - * @return {!Object} The spy object.
    - */
    -goog.labs.mock.spy = function(obj) {
    -  // Go over properties of 'obj' and create a MockSpyManager_ to
    -  // be used for spying on calls to methods.
    -  var mockSpyManager = new goog.labs.mock.MockSpyManager_(obj);
    -  var spyObject = mockSpyManager.getMockedItem();
    -  goog.asserts.assert(spyObject);
    -  return spyObject;
    -};
    -
    -
    -/**
    - * Returns an object that can be used to verify calls to specific methods of a
    - * given mock.
    - *
    - * @param {!Object} obj The mocked object.
    - * @return {!Object} The verifier.
    - */
    -goog.labs.mock.verify = function(obj) {
    -  return obj.$callVerifier;
    -};
    -
    -
    -/**
    - * Returns a name to identify a function. Named functions return their names,
    - * unnamed functions return a string of the form '#anonymous{ID}' where ID is
    - * a unique identifier for each anonymous function.
    - * @private
    - * @param {!Function} func The function.
    - * @return {string} The function name.
    - */
    -goog.labs.mock.getFunctionName_ = function(func) {
    -  var funcName = goog.debug.getFunctionName(func);
    -  if (funcName == '' || funcName == '[Anonymous]') {
    -    funcName = '#anonymous' + goog.labs.mock.getUid(func);
    -  }
    -  return funcName;
    -};
    -
    -
    -/**
    - * Returns a nicely formatted, readble representation of a method call.
    - * @private
    - * @param {string} methodName The name of the method.
    - * @param {Array<?>=} opt_args The method arguments.
    - * @return {string} The string representation of the method call.
    - */
    -goog.labs.mock.formatMethodCall_ = function(methodName, opt_args) {
    -  opt_args = opt_args || [];
    -  opt_args = goog.array.map(opt_args, function(arg) {
    -    if (goog.isFunction(arg)) {
    -      var funcName = goog.labs.mock.getFunctionName_(arg);
    -      return '<function ' + funcName + '>';
    -    } else {
    -      var isObjectWithClass = goog.isObject(arg) &&
    -          !goog.isFunction(arg) && !goog.isArray(arg) &&
    -          arg.constructor != Object;
    -
    -      if (isObjectWithClass) {
    -        return arg.toString();
    -      }
    -
    -      return goog.labs.mock.formatValue_(arg);
    -    }
    -  });
    -  return methodName + '(' + opt_args.join(', ') + ')';
    -};
    -
    -
    -/**
    - * An array to store objects for unique id generation.
    - * @private
    - * @type {!Array<!Object>}
    - */
    -goog.labs.mock.uid_ = [];
    -
    -
    -/**
    - * A unique Id generator that does not modify the object.
    - * @param {Object!} obj The object whose unique ID we want to generate.
    - * @return {number} an unique id for the object.
    - */
    -goog.labs.mock.getUid = function(obj) {
    -  var index = goog.array.indexOf(goog.labs.mock.uid_, obj);
    -  if (index == -1) {
    -    index = goog.labs.mock.uid_.length;
    -    goog.labs.mock.uid_.push(obj);
    -  }
    -  return index;
    -};
    -
    -
    -/**
    - * This is just another implementation of goog.debug.deepExpose with a more
    - * compact format.
    - * @private
    - * @param {*} obj The object whose string representation will be returned.
    - * @param {boolean=} opt_id Whether to include the id of objects or not.
    - *     Defaults to true.
    - * @return {string} The string representation of the object.
    - */
    -goog.labs.mock.formatValue_ = function(obj, opt_id) {
    -  var id = goog.isDef(opt_id) ? opt_id : true;
    -  var previous = [];
    -  var output = [];
    -
    -  var helper = function(obj) {
    -    var indentMultiline = function(output) {
    -      return output.replace(/\n/g, '\n');
    -    };
    -
    -    /** @preserveTry */
    -    try {
    -      if (!goog.isDef(obj)) {
    -        output.push('undefined');
    -      } else if (goog.isNull(obj)) {
    -        output.push('NULL');
    -      } else if (goog.isString(obj)) {
    -        output.push('"' + indentMultiline(obj) + '"');
    -      } else if (goog.isFunction(obj)) {
    -        var funcName = goog.labs.mock.getFunctionName_(obj);
    -        output.push('<function ' + funcName + '>');
    -      } else if (goog.isObject(obj)) {
    -        if (goog.array.contains(previous, obj)) {
    -          if (id) {
    -            output.push('<recursive/dupe obj_' +
    -                goog.labs.mock.getUid(obj) + '>');
    -          } else {
    -            output.push('<recursive/dupe>');
    -          }
    -        } else {
    -          previous.push(obj);
    -          output.push('{');
    -          var inner_obj = [];
    -          for (var x in obj) {
    -            output.push(' ');
    -            output.push('"' + x + '"' + ':');
    -            helper(obj[x]);
    -          }
    -          if (id) {
    -            output.push(' _id:' + goog.labs.mock.getUid(obj));
    -          }
    -          output.push('}');
    -        }
    -      } else {
    -        output.push(obj);
    -      }
    -    } catch (e) {
    -      output.push('*** ' + e + ' ***');
    -    }
    -  };
    -
    -  helper(obj);
    -  return output.join('').replace(/"closure_uid_\d+"/g, '_id')
    -      .replace(/{ /g, '{');
    -
    -};
    -
    -
    -
    -/**
    - * Error thrown when verification failed.
    - *
    - * @param {Array<!goog.labs.mock.MethodBinding_>} recordedCalls
    - *     The recorded calls that didn't match the expectation.
    - * @param {!string} methodName The expected method call.
    - * @param {!Array<?>} args The expected arguments.
    - * @constructor
    - * @extends {goog.debug.Error}
    - * @final
    - */
    -goog.labs.mock.VerificationError = function(recordedCalls, methodName, args) {
    -  var msg = goog.labs.mock.VerificationError.getVerificationErrorMsg_(
    -      recordedCalls, methodName, args);
    -  goog.labs.mock.VerificationError.base(this, 'constructor', msg);
    -};
    -goog.inherits(goog.labs.mock.VerificationError, goog.debug.Error);
    -
    -
    -/** @override */
    -goog.labs.mock.VerificationError.prototype.name = 'VerificationError';
    -
    -
    -/**
    - * This array contains the name of the functions that are part of the base
    - * Object prototype.
    - * Basically a copy of goog.object.PROTOTYPE_FIELDS_.
    - * @const
    - * @type {!Array<string>}
    - * @private
    - */
    -goog.labs.mock.PROTOTYPE_FIELDS_ = [
    -  'constructor',
    -  'hasOwnProperty',
    -  'isPrototypeOf',
    -  'propertyIsEnumerable',
    -  'toLocaleString',
    -  'toString',
    -  'valueOf'
    -];
    -
    -
    -/**
    - * Constructs a descriptive error message for an expected method call.
    - * @private
    - * @param {Array<!goog.labs.mock.MethodBinding_>} recordedCalls
    - *     The recorded calls that didn't match the expectation.
    - * @param {!string} methodName The expected method call.
    - * @param {!Array<?>} args The expected arguments.
    - * @return {string} The error message.
    - */
    -goog.labs.mock.VerificationError.getVerificationErrorMsg_ =
    -    function(recordedCalls, methodName, args) {
    -
    -  recordedCalls = goog.array.filter(recordedCalls, function(binding) {
    -    return binding.getMethodName() == methodName;
    -  });
    -
    -  var expected = goog.labs.mock.formatMethodCall_(methodName, args);
    -
    -  var msg = '\nExpected: ' + expected.toString();
    -  msg += '\nRecorded: ';
    -
    -  if (recordedCalls.length > 0) {
    -    msg += recordedCalls.join(',\n          ');
    -  } else {
    -    msg += 'No recorded calls';
    -  }
    -
    -  return msg;
    -};
    -
    -
    -
    -/**
    - * Base class that provides basic functionality for creating, adding and
    - * finding bindings, offering an executor method that is called when a call to
    - * the stub is made, an array to hold the bindings and the mocked item, among
    - * other things.
    - *
    - * @constructor
    - * @struct
    - * @private
    - */
    -goog.labs.mock.MockManager_ = function() {
    -  /**
    -   * Proxies the methods for the mocked object or class to execute the stubs.
    -   * @type {!Object}
    -   * @protected
    -   */
    -  this.mockedItem = {};
    -
    -  /**
    -   * A reference to the object or function being mocked.
    -   * @type {Object|Function}
    -   * @protected
    -   */
    -  this.mockee = null;
    -
    -  /**
    -   * Holds the stub bindings established so far.
    -   * @protected
    -   */
    -  this.methodBindings = [];
    -
    -  /**
    -   * Holds a reference to the binder used to define stubs.
    -   * @protected
    -   */
    -  this.$stubBinder = null;
    -
    -  /**
    -   * Record method calls with no stub definitions.
    -   * @type {!Array<!goog.labs.mock.MethodBinding_>}
    -   * @private
    -   */
    -  this.callRecords_ = [];
    -};
    -
    -
    -/**
    - * Handles the first step in creating a stub, returning a stub-binder that
    - * is later used to bind a stub for a method.
    - *
    - * @param {string} methodName The name of the method being bound.
    - * @param {...*} var_args The arguments to the method.
    - * @return {!goog.labs.mock.StubBinder_} The stub binder.
    - * @private
    - */
    -goog.labs.mock.MockManager_.prototype.handleMockCall_ =
    -    function(methodName, var_args) {
    -  var args = goog.array.slice(arguments, 1);
    -  return new goog.labs.mock.StubBinder_(this, methodName, args);
    -};
    -
    -
    -/**
    - * Returns the mock object. This should have a stubbed method for each method
    - * on the object being mocked.
    - *
    - * @return {!Object|!Function} The mock object.
    - */
    -goog.labs.mock.MockManager_.prototype.getMockedItem = function() {
    -  return this.mockedItem;
    -};
    -
    -
    -/**
    - * Adds a binding for the method name and arguments to be stubbed.
    - *
    - * @param {?string} methodName The name of the stubbed method.
    - * @param {!Array<?>} args The arguments passed to the method.
    - * @param {!Function} func The stub function.
    - *
    - */
    -goog.labs.mock.MockManager_.prototype.addBinding =
    -    function(methodName, args, func) {
    -  var binding = new goog.labs.mock.MethodBinding_(methodName, args, func);
    -  this.methodBindings.push(binding);
    -};
    -
    -
    -/**
    - * Returns a stub, if defined, for the method name and arguments passed in.
    - * If there are multiple stubs for this method name and arguments, then
    - * the first one is returned and removed from the list.
    - *
    - * @param {string} methodName The name of the stubbed method.
    - * @param {!Array<?>} args The arguments passed to the method.
    - * @return {Function} The stub function or undefined.
    - * @protected
    - */
    -goog.labs.mock.MockManager_.prototype.getNextBinding =
    -    function(methodName, args) {
    -  var first = -1;
    -  var count = 0;
    -  var stub = null;
    -  goog.array.forEach(this.methodBindings, function(binding, i) {
    -    if (binding.matches(methodName, args, false /* isVerification */)) {
    -      count++;
    -      if (goog.isNull(stub)) {
    -        first = i;
    -        stub = binding;
    -      }
    -    }
    -  });
    -  if (count > 1) {
    -    goog.array.removeAt(this.methodBindings, first);
    -  }
    -  return stub && stub.getStub();
    -};
    -
    -
    -/**
    - * Returns a stub, if defined, for the method name and arguments passed in as
    - * parameters.
    - *
    - * @param {string} methodName The name of the stubbed method.
    - * @param {!Array<?>} args The arguments passed to the method.
    - * @return {Function} The stub function or undefined.
    - * @protected
    - */
    -goog.labs.mock.MockManager_.prototype.getExecutor = function(methodName, args) {
    -  return this.getNextBinding(methodName, args);
    -};
    -
    -
    -/**
    - * Looks up the list of stubs defined on the mock object and executes the
    - * function associated with that stub.
    - *
    - * @param {string} methodName The name of the method to execute.
    - * @param {...*} var_args The arguments passed to the method.
    - * @return {*} Value returned by the stub function.
    - * @protected
    - */
    -goog.labs.mock.MockManager_.prototype.executeStub =
    -    function(methodName, var_args) {
    -  var args = goog.array.slice(arguments, 1);
    -
    -  // Record this call
    -  this.recordCall_(methodName, args);
    -
    -  var func = this.getExecutor(methodName, args);
    -  if (func) {
    -    return func.apply(null, args);
    -  }
    -};
    -
    -
    -/**
    - * Records a call to 'methodName' with arguments 'args'.
    - *
    - * @param {string} methodName The name of the called method.
    - * @param {!Array<?>} args The array of arguments.
    - * @private
    - */
    -goog.labs.mock.MockManager_.prototype.recordCall_ =
    -    function(methodName, args) {
    -  var callRecord = new goog.labs.mock.MethodBinding_(methodName, args,
    -      goog.nullFunction);
    -
    -  this.callRecords_.push(callRecord);
    -};
    -
    -
    -/**
    - * Verify invocation of a method with specific arguments.
    - *
    - * @param {string} methodName The name of the method.
    - * @param {...*} var_args The arguments passed.
    - * @protected
    - */
    -goog.labs.mock.MockManager_.prototype.verifyInvocation =
    -    function(methodName, var_args) {
    -  var args = goog.array.slice(arguments, 1);
    -  var binding = goog.array.find(this.callRecords_, function(binding) {
    -    return binding.matches(methodName, args, true /* isVerification */);
    -  });
    -
    -  if (!binding) {
    -    throw new goog.labs.mock.VerificationError(
    -        this.callRecords_, methodName, args);
    -  }
    -};
    -
    -
    -
    -/**
    - * Sets up mock for the given object (or class), stubbing out all the defined
    - * methods. By default, all stubs return {@code undefined}, though stubs can be
    - * later defined using {@code goog.labs.mock.when}.
    - *
    - * @param {!Object|!Function} objOrClass The object or class to set up the mock
    - *     for. A class is a constructor function.
    - *
    - * @constructor
    - * @struct
    - * @extends {goog.labs.mock.MockManager_}
    - * @private
    - */
    -goog.labs.mock.MockObjectManager_ = function(objOrClass) {
    -  goog.labs.mock.MockObjectManager_.base(this, 'constructor');
    -
    -  /**
    -   * Proxies the calls to establish the first step of the stub bindings (object
    -   * and method name)
    -   * @private
    -   */
    -  this.objectStubBinder_ = {};
    -
    -  this.mockee = objOrClass;
    -
    -  /**
    -   * The call verifier is used to verify the calls. It maps property names to
    -   * the method that does call verification.
    -   * @type {!Object<string, function(string, ...)>}
    -   * @private
    -   */
    -  this.objectCallVerifier_ = {};
    -
    -  var obj;
    -  if (goog.isFunction(objOrClass)) {
    -    // Create a temporary subclass with a no-op constructor so that we can
    -    // create an instance and determine what methods it has.
    -    /**
    - * @constructor
    - * @final
    - */
    -    var tempCtor = function() {};
    -    goog.inherits(tempCtor, objOrClass);
    -    obj = new tempCtor();
    -  } else {
    -    obj = objOrClass;
    -  }
    -
    -  // Put the object being mocked in the prototype chain of the mock so that
    -  // it has all the correct properties and instanceof works.
    -  /**
    - * @constructor
    - * @final
    - */
    -  var mockedItemCtor = function() {};
    -  mockedItemCtor.prototype = obj;
    -  this.mockedItem = new mockedItemCtor();
    -
    -  var enumerableProperties = goog.object.getKeys(obj);
    -  // The non enumerable properties are added due to the fact that IE8 does not
    -  // enumerate any of the prototype Object functions even when overriden and
    -  // mocking these is sometimes needed.
    -  for (var i = 0; i < goog.labs.mock.PROTOTYPE_FIELDS_.length; i++) {
    -    var prop = goog.labs.mock.PROTOTYPE_FIELDS_[i];
    -    if (!goog.array.contains(enumerableProperties, prop)) {
    -      enumerableProperties.push(prop);
    -    }
    -  }
    -
    -  // Adds the properties to the mock, creating a proxy stub for each method on
    -  // the instance.
    -  for (var i = 0; i < enumerableProperties.length; i++) {
    -    var prop = enumerableProperties[i];
    -    if (goog.isFunction(obj[prop])) {
    -      this.mockedItem[prop] = goog.bind(this.executeStub, this, prop);
    -      // The stub binder used to create bindings.
    -      this.objectStubBinder_[prop] =
    -          goog.bind(this.handleMockCall_, this, prop);
    -      // The verifier verifies the calls.
    -      this.objectCallVerifier_[prop] =
    -          goog.bind(this.verifyInvocation, this, prop);
    -    }
    -  }
    -  // The alias for stub binder exposed to the world.
    -  this.mockedItem.$stubBinder = this.objectStubBinder_;
    -
    -  // The alias for verifier for the world.
    -  this.mockedItem.$callVerifier = this.objectCallVerifier_;
    -};
    -goog.inherits(goog.labs.mock.MockObjectManager_,
    -              goog.labs.mock.MockManager_);
    -
    -
    -
    -/**
    - * Sets up the spying behavior for the given object.
    - *
    - * @param {!Object} obj The object to be spied on.
    - *
    - * @constructor
    - * @struct
    - * @extends {goog.labs.mock.MockObjectManager_}
    - * @private
    - */
    -goog.labs.mock.MockSpyManager_ = function(obj) {
    -  goog.labs.mock.MockSpyManager_.base(this, 'constructor', obj);
    -};
    -goog.inherits(goog.labs.mock.MockSpyManager_,
    -              goog.labs.mock.MockObjectManager_);
    -
    -
    -/**
    - * Return a stub, if defined, for the method and arguments passed in. If we lack
    - * a stub, instead look for a call record that matches the method and arguments.
    - *
    - * @return {!Function} The stub or the invocation logger, if defined.
    - * @override
    - */
    -goog.labs.mock.MockSpyManager_.prototype.getNextBinding =
    -    function(methodName, args) {
    -  var stub = goog.labs.mock.MockSpyManager_.base(
    -      this, 'getNextBinding', methodName, args);
    -
    -  if (!stub) {
    -    stub = goog.bind(this.mockee[methodName], this.mockee);
    -  }
    -
    -  return stub;
    -};
    -
    -
    -
    -/**
    - * Sets up mock for the given function, stubbing out. By default, all stubs
    - * return {@code undefined}, though stubs can be later defined using
    - * {@code goog.labs.mock.when}.
    - *
    - * @param {!Function} func The function to set up the mock for.
    - *
    - * @constructor
    - * @struct
    - * @extends {goog.labs.mock.MockManager_}
    - * @private
    - */
    -goog.labs.mock.MockFunctionManager_ = function(func) {
    -  goog.labs.mock.MockFunctionManager_.base(this, 'constructor');
    -
    -  this.func_ = func;
    -
    -  /**
    -   * The stub binder used to create bindings.
    -   * Sets the first argument of handleMockCall_ to the function name.
    -   * @type {!Function}
    -   * @private
    -   */
    -  this.functionStubBinder_ = this.useMockedFunctionName_(this.handleMockCall_);
    -
    -  this.mockedItem = this.useMockedFunctionName_(this.executeStub);
    -  this.mockedItem.$stubBinder = this.functionStubBinder_;
    -
    -  /**
    -   * The call verifier is used to verify function invocations.
    -   * Sets the first argument of verifyInvocation to the function name.
    -   * @type {!Function}
    -   */
    -  this.mockedItem.$callVerifier =
    -      this.useMockedFunctionName_(this.verifyInvocation);
    -};
    -goog.inherits(goog.labs.mock.MockFunctionManager_,
    -              goog.labs.mock.MockManager_);
    -
    -
    -/**
    - * Given a method, returns a new function that calls the first one setting
    - * the first argument to the mocked function name.
    - * This is used to dynamically override the stub binders and call verifiers.
    - * @private
    - * @param {Function} nextFunc The function to override.
    - * @return {!Function} The overloaded function.
    - */
    -goog.labs.mock.MockFunctionManager_.prototype.useMockedFunctionName_ =
    -    function(nextFunc) {
    -  return goog.bind(function(var_args) {
    -    var args = goog.array.slice(arguments, 0);
    -    var name =
    -        '#mockFor<' + goog.labs.mock.getFunctionName_(this.func_) + '>';
    -    goog.array.insertAt(args, name, 0);
    -    return nextFunc.apply(this, args);
    -  }, this);
    -};
    -
    -
    -
    -/**
    - * The stub binder is the object that helps define the stubs by binding
    - * method name to the stub method.
    - *
    - * @param {!goog.labs.mock.MockManager_}
    - *   mockManager The mock manager.
    - * @param {?string} name The method name.
    - * @param {!Array<?>} args The other arguments to the method.
    - *
    - * @constructor
    - * @struct
    - * @private
    - */
    -goog.labs.mock.StubBinder_ = function(mockManager, name, args) {
    -  /**
    -   * The mock manager instance.
    -   * @type {!goog.labs.mock.MockManager_}
    -   * @private
    -   */
    -  this.mockManager_ = mockManager;
    -
    -  /**
    -   * Holds the name of the method to be bound.
    -   * @type {?string}
    -   * @private
    -   */
    -  this.name_ = name;
    -
    -  /**
    -   * Holds the arguments for the method.
    -   * @type {!Array<?>}
    -   * @private
    -   */
    -  this.args_ = args;
    -};
    -
    -
    -/**
    - * Defines the stub to be called for the method name and arguments bound
    - * earlier.
    - * TODO(user): Add support for the 'Answer' interface.
    - *
    - * @param {!Function} func The stub.
    - */
    -goog.labs.mock.StubBinder_.prototype.then = function(func) {
    -  this.mockManager_.addBinding(this.name_, this.args_, func);
    -};
    -
    -
    -/**
    - * Defines the stub to return a specific value for a method name and arguments.
    - *
    - * @param {*} value The value to return.
    - */
    -goog.labs.mock.StubBinder_.prototype.thenReturn = function(value) {
    -  this.mockManager_.addBinding(this.name_, this.args_,
    -                               goog.functions.constant(value));
    -};
    -
    -
    -/**
    - * Facilitates (and is the first step in) setting up stubs. Obtains an object
    - * on which, the method to be mocked is called to create a stub. Sample usage:
    - *
    - * var mockObj = goog.labs.mock.mock(objectBeingMocked);
    - * goog.labs.mock.when(mockObj).getFoo(3).thenReturn(4);
    - *
    - * @param {!Object} mockObject The mocked object.
    - * @return {!goog.labs.mock.StubBinder_} The property binder.
    - */
    -goog.labs.mock.when = function(mockObject) {
    -  goog.asserts.assert(mockObject.$stubBinder, 'Stub binder cannot be null!');
    -  return mockObject.$stubBinder;
    -};
    -
    -
    -
    -/**
    - * Represents a binding between a method name, args and a stub.
    - *
    - * @param {?string} methodName The name of the method being stubbed.
    - * @param {!Array<?>} args The arguments passed to the method.
    - * @param {!Function} stub The stub function to be called for the given method.
    - * @constructor
    - * @struct
    - * @private
    - */
    -goog.labs.mock.MethodBinding_ = function(methodName, args, stub) {
    -  /**
    -   * The name of the method being stubbed.
    -   * @type {?string}
    -   * @private
    -   */
    -  this.methodName_ = methodName;
    -
    -  /**
    -   * The arguments for the method being stubbed.
    -   * @type {!Array<?>}
    -   * @private
    -   */
    -  this.args_ = args;
    -
    -  /**
    -   * The stub function.
    -   * @type {!Function}
    -   * @private
    -   */
    -  this.stub_ = stub;
    -};
    -
    -
    -/**
    - * @return {!Function} The stub to be executed.
    - */
    -goog.labs.mock.MethodBinding_.prototype.getStub = function() {
    -  return this.stub_;
    -};
    -
    -
    -/**
    - * @override
    - * @return {string} A readable string representation of the binding
    - *  as a method call.
    - */
    -goog.labs.mock.MethodBinding_.prototype.toString = function() {
    -  return goog.labs.mock.formatMethodCall_(this.methodName_ || '', this.args_);
    -};
    -
    -
    -/**
    - * @return {string} The method name for this binding.
    - */
    -goog.labs.mock.MethodBinding_.prototype.getMethodName = function() {
    -  return this.methodName_ || '';
    -};
    -
    -
    -/**
    - * Determines whether the given args match the stored args_. Used to determine
    - * which stub to invoke for a method.
    - *
    - * @param {string} methodName The name of the method being stubbed.
    - * @param {!Array<?>} args An array of arguments.
    - * @param {boolean} isVerification Whether this is a function verification call
    - *     or not.
    - * @return {boolean} If it matches the stored arguments.
    - */
    -goog.labs.mock.MethodBinding_.prototype.matches = function(
    -    methodName, args, isVerification) {
    -  var specs = isVerification ? args : this.args_;
    -  var calls = isVerification ? this.args_ : args;
    -
    -  //TODO(user): More elaborate argument matching. Think about matching
    -  //    objects.
    -  return this.methodName_ == methodName &&
    -      goog.array.equals(calls, specs, function(arg, spec) {
    -        // Duck-type to see if this is an object that implements the
    -        // goog.labs.testing.Matcher interface.
    -        if (goog.isFunction(spec.matches)) {
    -          return spec.matches(arg);
    -        } else {
    -          return goog.array.defaultCompareEquality(spec, arg);
    -        }
    -      });
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/mock/mock_test.html b/src/database/third_party/closure-library/closure/goog/labs/mock/mock_test.html
    deleted file mode 100644
    index aa39e5ada0d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/mock/mock_test.html
    +++ /dev/null
    @@ -1,21 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.labs.mock
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.labs.mockTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/mock/mock_test.js b/src/database/third_party/closure-library/closure/goog/labs/mock/mock_test.js
    deleted file mode 100644
    index 7d57038d8a7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/mock/mock_test.js
    +++ /dev/null
    @@ -1,517 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.labs.mockTest');
    -goog.setTestOnly('goog.labs.mockTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.labs.mock');
    -goog.require('goog.labs.mock.VerificationError');
    -/** @suppress {extraRequire} */
    -goog.require('goog.labs.testing.AnythingMatcher');
    -/** @suppress {extraRequire} */
    -goog.require('goog.labs.testing.GreaterThanMatcher');
    -goog.require('goog.string');
    -goog.require('goog.testing.jsunit');
    -
    -var ParentClass = function() {};
    -ParentClass.prototype.method1 = function() {};
    -ParentClass.prototype.x = 1;
    -ParentClass.prototype.val = 0;
    -ParentClass.prototype.incrementVal = function() { this.val++; };
    -
    -var ChildClass = function() {};
    -goog.inherits(ChildClass, ParentClass);
    -ChildClass.prototype.method2 = function() {};
    -ChildClass.prototype.y = 2;
    -
    -function testParentClass() {
    -  var parentMock = goog.labs.mock.mock(ParentClass);
    -
    -  assertNotUndefined(parentMock.method1);
    -  assertUndefined(parentMock.method1());
    -  assertUndefined(parentMock.method2);
    -  assertNotUndefined(parentMock.x);
    -  assertUndefined(parentMock.y);
    -  assertTrue('Mock should be an instance of the mocked class.',
    -      parentMock instanceof ParentClass);
    -}
    -
    -function testChildClass() {
    -  var childMock = goog.labs.mock.mock(ChildClass);
    -
    -  assertNotUndefined(childMock.method1);
    -  assertUndefined(childMock.method1());
    -  assertNotUndefined(childMock.method2);
    -  assertUndefined(childMock.method2());
    -  assertNotUndefined(childMock.x);
    -  assertNotUndefined(childMock.y);
    -  assertTrue('Mock should be an instance of the mocked class.',
    -      childMock instanceof ChildClass);
    -}
    -
    -function testParentClassInstance() {
    -  var parentMock = goog.labs.mock.mock(new ParentClass());
    -
    -  assertNotUndefined(parentMock.method1);
    -  assertUndefined(parentMock.method1());
    -  assertUndefined(parentMock.method2);
    -  assertNotUndefined(parentMock.x);
    -  assertUndefined(parentMock.y);
    -  assertTrue('Mock should be an instance of the mocked class.',
    -      parentMock instanceof ParentClass);
    -}
    -
    -function testChildClassInstance() {
    -  var childMock = goog.labs.mock.mock(new ChildClass());
    -
    -  assertNotUndefined(childMock.method1);
    -  assertUndefined(childMock.method1());
    -  assertNotUndefined(childMock.method2);
    -  assertUndefined(childMock.method2());
    -  assertNotUndefined(childMock.x);
    -  assertNotUndefined(childMock.y);
    -  assertTrue('Mock should be an instance of the mocked class.',
    -      childMock instanceof ParentClass);
    -}
    -
    -function testNonEnumerableProperties() {
    -  var mockObject = goog.labs.mock.mock({});
    -  assertNotUndefined(mockObject.toString);
    -  goog.labs.mock.when(mockObject).toString().then(function() {
    -    return 'toString';
    -  });
    -  assertEquals('toString', mockObject.toString());
    -}
    -
    -function testBasicStubbing() {
    -  var obj = {
    -    method1: function(i) {
    -      return 2 * i;
    -    },
    -    method2: function(i, str) {
    -      return str;
    -    },
    -    method3: function(x) {
    -      return x;
    -    }
    -  };
    -
    -  var mockObj = goog.labs.mock.mock(obj);
    -  goog.labs.mock.when(mockObj).method1(2).then(function(i) {return i;});
    -
    -  assertEquals(4, obj.method1(2));
    -  assertEquals(2, mockObj.method1(2));
    -  assertUndefined(mockObj.method1(4));
    -
    -  goog.labs.mock.when(mockObj).method2(1, 'hi').then(function(i) {return 'oh'});
    -  assertEquals('hi', obj.method2(1, 'hi'));
    -  assertEquals('oh', mockObj.method2(1, 'hi'));
    -  assertUndefined(mockObj.method2(3, 'foo'));
    -
    -  goog.labs.mock.when(mockObj).method3(4).thenReturn(10);
    -  assertEquals(4, obj.method3(4));
    -  assertEquals(10, mockObj.method3(4));
    -  goog.labs.mock.verify(mockObj).method3(4);
    -  assertUndefined(mockObj.method3(5));
    -}
    -
    -function testMockFunctions() {
    -  function x(i) { return i; }
    -
    -  var mockedFunc = goog.labs.mock.mockFunction(x);
    -  goog.labs.mock.when(mockedFunc)(100).thenReturn(10);
    -  goog.labs.mock.when(mockedFunc)(50).thenReturn(25);
    -
    -  assertEquals(100, x(100));
    -  assertEquals(10, mockedFunc(100));
    -  assertEquals(25, mockedFunc(50));
    -}
    -
    -function testStubbingConsecutiveCalls() {
    -  var obj = {
    -    method: function(i) {
    -      return i * 42;
    -    }
    -  };
    -
    -  var mockObj = goog.labs.mock.mock(obj);
    -  goog.labs.mock.when(mockObj).method(1).thenReturn(3);
    -  goog.labs.mock.when(mockObj).method(1).thenReturn(4);
    -
    -  assertEquals(42, obj.method(1));
    -  assertEquals(3, mockObj.method(1));
    -  assertEquals(4, mockObj.method(1));
    -  assertEquals(4, mockObj.method(1));
    -
    -  var x = function(i) { return i; };
    -  var mockedFunc = goog.labs.mock.mockFunction(x);
    -  goog.labs.mock.when(mockedFunc)(100).thenReturn(10);
    -  goog.labs.mock.when(mockedFunc)(100).thenReturn(25);
    -
    -  assertEquals(100, x(100));
    -  assertEquals(10, mockedFunc(100));
    -  assertEquals(25, mockedFunc(100));
    -  assertEquals(25, mockedFunc(100));
    -}
    -
    -function testSpying() {
    -  var obj = {
    -    method1: function(i) {
    -      return 2 * i;
    -    },
    -    method2: function(i) {
    -      return 5 * i;
    -    }
    -  };
    -
    -  var spyObj = goog.labs.mock.spy(obj);
    -  goog.labs.mock.when(spyObj).method1(2).thenReturn(5);
    -
    -  assertEquals(2, obj.method1(1));
    -  assertEquals(5, spyObj.method1(2));
    -  goog.labs.mock.verify(spyObj).method1(2);
    -  assertEquals(2, spyObj.method1(1));
    -  goog.labs.mock.verify(spyObj).method1(1);
    -  assertEquals(20, spyObj.method2(4));
    -  goog.labs.mock.verify(spyObj).method2(4);
    -}
    -
    -function testSpyParentClassInstance() {
    -  var parent = new ParentClass();
    -  var parentMock = goog.labs.mock.spy(parent);
    -
    -  assertNotUndefined(parentMock.method1);
    -  assertUndefined(parentMock.method1());
    -  assertUndefined(parentMock.method2);
    -  assertNotUndefined(parentMock.x);
    -  assertUndefined(parentMock.y);
    -  assertTrue('Mock should be an instance of the mocked class.',
    -      parentMock instanceof ParentClass);
    -  var incrementedOrigVal = parent.val + 1;
    -  parentMock.incrementVal();
    -  assertEquals('Changes in the spied object should reflect in the spy.',
    -      incrementedOrigVal, parentMock.val);
    -}
    -
    -function testSpyChildClassInstance() {
    -  var child = new ChildClass();
    -  var childMock = goog.labs.mock.spy(child);
    -
    -  assertNotUndefined(childMock.method1);
    -  assertUndefined(childMock.method1());
    -  assertNotUndefined(childMock.method2);
    -  assertUndefined(childMock.method2());
    -  assertNotUndefined(childMock.x);
    -  assertNotUndefined(childMock.y);
    -  assertTrue('Mock should be an instance of the mocked class.',
    -      childMock instanceof ParentClass);
    -  var incrementedOrigVal = child.val + 1;
    -  childMock.incrementVal();
    -  assertEquals('Changes in the spied object should reflect in the spy.',
    -      incrementedOrigVal, childMock.val);
    -}
    -
    -function testVerifyForObjects() {
    -  var obj = {
    -    method1: function(i) {
    -      return 2 * i;
    -    },
    -    method2: function(i) {
    -      return 5 * i;
    -    }
    -  };
    -
    -  var mockObj = goog.labs.mock.mock(obj);
    -  goog.labs.mock.when(mockObj).method1(2).thenReturn(5);
    -
    -  assertEquals(5, mockObj.method1(2));
    -  goog.labs.mock.verify(mockObj).method1(2);
    -  var e = assertThrows(goog.bind(goog.labs.mock.verify(mockObj).method1, 2));
    -  assertTrue(e instanceof goog.labs.mock.VerificationError);
    -}
    -
    -function testVerifyForFunctions() {
    -  var func = function(i) {
    -    return i;
    -  };
    -
    -  var mockFunc = goog.labs.mock.mockFunction(func);
    -  goog.labs.mock.when(mockFunc)(2).thenReturn(55);
    -  assertEquals(55, mockFunc(2));
    -  goog.labs.mock.verify(mockFunc)(2);
    -  goog.labs.mock.verify(mockFunc)(lessThan(3));
    -
    -  var e = assertThrows(goog.bind(goog.labs.mock.verify(mockFunc), 3));
    -  assertTrue(e instanceof goog.labs.mock.VerificationError);
    -}
    -
    -
    -/**
    -* When a function invocation verification fails, it should show the failed
    -* expectation call, as well as the recorded calls to the same method.
    -*/
    -function testVerificationErrorMessages() {
    -  var mock = goog.labs.mock.mock({
    -    method: function(i) {
    -      return i;
    -    }
    -  });
    -
    -  // Failure when there are no recorded calls.
    -  var e = assertThrows(function() { goog.labs.mock.verify(mock).method(4); });
    -  assertTrue(e instanceof goog.labs.mock.VerificationError);
    -  var expected = '\nExpected: method(4)\n' +
    -      'Recorded: No recorded calls';
    -  assertEquals(expected, e.message);
    -
    -
    -  // Failure when there are recorded calls with ints and functions
    -  // as arguments.
    -  var callback = function() {};
    -  var callbackId = goog.labs.mock.getUid(callback);
    -
    -  mock.method(1);
    -  mock.method(2);
    -  mock.method(callback);
    -
    -  e = assertThrows(function() { goog.labs.mock.verify(mock).method(3); });
    -  assertTrue(e instanceof goog.labs.mock.VerificationError);
    -
    -  expected = '\nExpected: method(3)\n' +
    -      'Recorded: method(1),\n' +
    -      '          method(2),\n' +
    -      '          method(<function #anonymous' + callbackId + '>)';
    -  assertEquals(expected, e.message);
    -
    -  // With mockFunctions
    -  var mockCallback = goog.labs.mock.mockFunction(callback);
    -  e = assertThrows(function() { goog.labs.mock.verify(mockCallback)(5);});
    -  expected = '\nExpected: #mockFor<#anonymous' + callbackId + '>(5)\n' +
    -      'Recorded: No recorded calls';
    -
    -  mockCallback(8);
    -  goog.labs.mock.verify(mockCallback)(8);
    -  assertEquals(expected, e.message);
    -
    -  // Objects with circular references should not fail.
    -  var obj = {x: 1};
    -  obj.y = obj;
    -
    -  mockCallback(obj);
    -  e = assertThrows(function() { goog.labs.mock.verify(mockCallback)(5);});
    -  assertTrue(e instanceof goog.labs.mock.VerificationError);
    -
    -  // Should respect string representation of different custom classes.
    -  var myClass = function() {};
    -  myClass.prototype.toString = function() { return '<superClass>'; };
    -
    -  var mockFunction = goog.labs.mock.mockFunction(function f() {});
    -  mockFunction(new myClass());
    -
    -  e = assertThrows(function() { goog.labs.mock.verify(mockFunction)(5);});
    -  expected = '\nExpected: #mockFor<f>(5)\n' +
    -      'Recorded: #mockFor<f>(<superClass>)';
    -  assertEquals(expected, e.message);
    -}
    -
    -
    -/**
    -* Asserts that the given string contains a list of others strings
    -* in the given order.
    -*/
    -function assertContainsInOrder(str, var_args) {
    -  var expected = goog.array.splice(arguments, 1);
    -  var indices = goog.array.map(expected, function(val) {
    -    return str.indexOf(val);
    -  });
    -
    -  for (var i = 0; i < expected.length; i++) {
    -    var msg = 'Missing "' + expected[i] + '" from "' + str + '"';
    -    assertTrue(msg, indices[i] != -1);
    -
    -    if (i > 0) {
    -      msg = '"' + expected[i - 1] + '" should come before "' + expected[i] +
    -          '" in "' + str + '"';
    -      assertTrue(msg, indices[i] > indices[i - 1]);
    -    }
    -  }
    -}
    -
    -function testMatchers() {
    -  var obj = {
    -    method1: function(i) {
    -      return 2 * i;
    -    },
    -    method2: function(i) {
    -      return 5 * i;
    -    }
    -  };
    -
    -  var mockObj = goog.labs.mock.mock(obj);
    -
    -  goog.labs.mock.when(mockObj).method1(greaterThan(4)).thenReturn(100);
    -  goog.labs.mock.when(mockObj).method1(lessThan(4)).thenReturn(40);
    -
    -  assertEquals(100, mockObj.method1(5));
    -  assertEquals(100, mockObj.method1(6));
    -  assertEquals(40, mockObj.method1(2));
    -  assertEquals(40, mockObj.method1(1));
    -  assertUndefined(mockObj.method1(4));
    -}
    -
    -function testMatcherVerify() {
    -  var obj = {
    -    method: function(i) {
    -      return 2 * i;
    -    }
    -  };
    -
    -  // Using spy objects.
    -  var spy = goog.labs.mock.spy(obj);
    -
    -  spy.method(6);
    -
    -  goog.labs.mock.verify(spy).method(greaterThan(4));
    -  var e = assertThrows(
    -      goog.bind(goog.labs.mock.verify(spy).method, lessThan(4)));
    -  assertTrue(e instanceof goog.labs.mock.VerificationError);
    -
    -  // Using mocks
    -  var mockObj = goog.labs.mock.mock(obj);
    -
    -  mockObj.method(8);
    -
    -  goog.labs.mock.verify(mockObj).method(greaterThan(7));
    -  var e = assertThrows(
    -      goog.bind(goog.labs.mock.verify(mockObj).method, lessThan(7)));
    -  assertTrue(e instanceof goog.labs.mock.VerificationError);
    -}
    -
    -function testMatcherVerifyCollision() {
    -  var obj = {
    -    method: function(i) {
    -      return 2 * i;
    -    }
    -  };
    -  var mockObj = goog.labs.mock.mock(obj);
    -
    -  goog.labs.mock.when(mockObj).method(5).thenReturn(100);
    -  assertNotEquals(100, mockObj.method(greaterThan(2)));
    -}
    -
    -function testMatcherVerifyCollisionBetweenMatchers() {
    -  var obj = {
    -    method: function(i) {
    -      return 2 * i;
    -    }
    -  };
    -  var mockObj = goog.labs.mock.mock(obj);
    -
    -  goog.labs.mock.when(mockObj).method(anything()).thenReturn(100);
    -
    -  var e = assertThrows(
    -      goog.bind(goog.labs.mock.verify(mockObj).method, anything()));
    -  assertTrue(e instanceof goog.labs.mock.VerificationError);
    -}
    -
    -function testVerifyForUnmockedMethods() {
    -  var Task = function() {};
    -  Task.prototype.run = function() {};
    -
    -  var mockTask = goog.labs.mock.mock(Task);
    -  mockTask.run();
    -
    -  goog.labs.mock.verify(mockTask).run();
    -}
    -
    -function testFormatMethodCall() {
    -  var formatMethodCall = goog.labs.mock.formatMethodCall_;
    -  assertEquals('alert()', formatMethodCall('alert'));
    -  assertEquals('sum(2, 4)', formatMethodCall('sum', [2, 4]));
    -  assertEquals('sum("2", "4")', formatMethodCall('sum', ['2', '4']));
    -  assertEquals('call(<function unicorn>)',
    -      formatMethodCall('call', [function unicorn() {}]));
    -
    -  var arg = {x: 1, y: {hello: 'world'}};
    -  assertEquals('call(' + goog.labs.mock.formatValue_(arg) + ')',
    -      formatMethodCall('call', [arg]));
    -}
    -
    -function testGetFunctionName() {
    -  var f1 = function() {};
    -  var f2 = function() {};
    -  var named = function myName() {};
    -
    -  assert(goog.string.startsWith(
    -      goog.labs.mock.getFunctionName_(f1), '#anonymous'));
    -  assert(goog.string.startsWith(
    -      goog.labs.mock.getFunctionName_(f2), '#anonymous'));
    -  assertNotEquals(
    -      goog.labs.mock.getFunctionName_(f1), goog.labs.mock.getFunctionName_(f2));
    -  assertEquals('myName', goog.labs.mock.getFunctionName_(named));
    -}
    -
    -function testFormatObject() {
    -  var obj, obj2, obj3;
    -
    -  obj = {x: 1};
    -  assertEquals(
    -      '{"x":1 _id:' + goog.labs.mock.getUid(obj) + '}',
    -      goog.labs.mock.formatValue_(obj)
    -  );
    -  assertEquals('{"x":1}', goog.labs.mock.formatValue_(obj, false /* id */));
    -
    -  obj = {x: 'hello'};
    -  assertEquals(
    -      '{"x":"hello" _id:' + goog.labs.mock.getUid(obj) + '}',
    -      goog.labs.mock.formatValue_(obj)
    -  );
    -  assertEquals('{"x":"hello"}',
    -      goog.labs.mock.formatValue_(obj, false /* id */));
    -
    -  obj3 = {};
    -  obj2 = {y: obj3};
    -  obj3.x = obj2;
    -  assertEquals(
    -      '{"x":{"y":<recursive/dupe obj_' + goog.labs.mock.getUid(obj3) + '> ' +
    -      '_id:' + goog.labs.mock.getUid(obj2) + '} ' +
    -      '_id:' + goog.labs.mock.getUid(obj3) + '}',
    -      goog.labs.mock.formatValue_(obj3)
    -  );
    -  assertEquals('{"x":{"y":<recursive/dupe>}}',
    -      goog.labs.mock.formatValue_(obj3, false /* id */)
    -  );
    -
    -
    -  obj = {x: function y() {} };
    -  assertEquals('{"x":<function y> _id:' + goog.labs.mock.getUid(obj) + '}',
    -      goog.labs.mock.formatValue_(obj));
    -  assertEquals('{"x":<function y>}',
    -      goog.labs.mock.formatValue_(obj, false /* id */));
    -
    -}
    -
    -function testGetUid() {
    -  var obj1 = {};
    -  var obj2 = {};
    -  var func1 = function() {};
    -  var func2 = function() {};
    -
    -  assertNotEquals(goog.labs.mock.getUid(obj1), goog.labs.mock.getUid(obj2));
    -  assertNotEquals(goog.labs.mock.getUid(func1), goog.labs.mock.getUid(func2));
    -  assertNotEquals(goog.labs.mock.getUid(obj1), goog.labs.mock.getUid(func2));
    -  assertEquals(goog.labs.mock.getUid(obj1), goog.labs.mock.getUid(obj1));
    -  assertEquals(goog.labs.mock.getUid(func1), goog.labs.mock.getUid(func1));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/image.js b/src/database/third_party/closure-library/closure/goog/labs/net/image.js
    deleted file mode 100644
    index e9e34fe3e58..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/image.js
    +++ /dev/null
    @@ -1,94 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Simple image loader, used for preloading.
    - * @author nnaze@google.com (Nathan Naze)
    - */
    -
    -goog.provide('goog.labs.net.image');
    -
    -goog.require('goog.Promise');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventType');
    -goog.require('goog.net.EventType');
    -goog.require('goog.userAgent');
    -
    -
    -/**
    - * Loads a single image.  Useful for preloading images.
    - *
    - * @param {string} uri URI of the image.
    - * @param {(!Image|function(): !Image)=} opt_image If present, instead of
    - *     creating a new Image instance the function will use the passed Image
    - *     instance or the result of calling the Image factory respectively. This
    - *     can be used to control exactly how Image instances are created, for
    - *     example if they should be created in a particular document element, or
    - *     have fields that will trigger CORS image fetches.
    - * @return {!goog.Promise<!Image>} A Promise that will be resolved with the
    - *     given image if the image successfully loads.
    - */
    -goog.labs.net.image.load = function(uri, opt_image) {
    -  return new goog.Promise(function(resolve, reject) {
    -    var image;
    -    if (!goog.isDef(opt_image)) {
    -      image = new Image();
    -    } else if (goog.isFunction(opt_image)) {
    -      image = opt_image();
    -    } else {
    -      image = opt_image;
    -    }
    -
    -    // IE's load event on images can be buggy.  For older browsers, wait for
    -    // readystatechange events and check if readyState is 'complete'.
    -    // See:
    -    // http://msdn.microsoft.com/en-us/library/ie/ms536957(v=vs.85).aspx
    -    // http://msdn.microsoft.com/en-us/library/ie/ms534359(v=vs.85).aspx
    -    //
    -    // Starting with IE11, start using standard 'load' events.
    -    // See:
    -    // http://msdn.microsoft.com/en-us/library/ie/dn467845(v=vs.85).aspx
    -    var loadEvent = (goog.userAgent.IE && goog.userAgent.VERSION < 11) ?
    -        goog.net.EventType.READY_STATE_CHANGE : goog.events.EventType.LOAD;
    -
    -    var handler = new goog.events.EventHandler();
    -    handler.listen(
    -        image,
    -        [loadEvent, goog.net.EventType.ABORT, goog.net.EventType.ERROR],
    -        function(e) {
    -
    -          // We only registered listeners for READY_STATE_CHANGE for IE.
    -          // If readyState is now COMPLETE, the image has loaded.
    -          // See related comment above.
    -          if (e.type == goog.net.EventType.READY_STATE_CHANGE &&
    -              image.readyState != goog.net.EventType.COMPLETE) {
    -            return;
    -          }
    -
    -          // At this point, we know whether the image load was successful
    -          // and no longer care about image events.
    -          goog.dispose(handler);
    -
    -          // Whether the image successfully loaded.
    -          if (e.type == loadEvent) {
    -            resolve(image);
    -          } else {
    -            reject(null);
    -          }
    -        });
    -
    -    // Initiate the image request.
    -    image.src = uri;
    -  });
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/image_test.html b/src/database/third_party/closure-library/closure/goog/labs/net/image_test.html
    deleted file mode 100644
    index 32d529af93e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/image_test.html
    +++ /dev/null
    @@ -1,21 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -  Author: nnaze@google.com (Nathan Naze)
    --->
    -<head>
    -<title>Closure Unit Tests - goog.labs.net.image</title>
    -<script src="../../base.js"></script>
    -</head>
    -<body>
    -<script>
    -goog.require('goog.labs.net.imageTest');
    -</script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/image_test.js b/src/database/third_party/closure-library/closure/goog/labs/net/image_test.js
    deleted file mode 100644
    index c973b5bfbd1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/image_test.js
    +++ /dev/null
    @@ -1,87 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.labs.net.Image.
    - *
    - * @author nnaze@google.com (Nathan Naze)
    - */
    -
    -
    -/** @suppress {extraProvide} */
    -goog.provide('goog.labs.net.imageTest');
    -
    -goog.require('goog.labs.net.image');
    -goog.require('goog.string');
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -
    -goog.setTestOnly('goog.labs.net.ImageTest');
    -
    -var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall();
    -
    -function testValidImage() {
    -  var url = 'testdata/cleardot.gif';
    -
    -  asyncTestCase.waitForAsync('image load');
    -
    -  goog.labs.net.image.load(url).then(function(value) {
    -    assertEquals('IMG', value.tagName);
    -    assertTrue(goog.string.endsWith(value.src, url));
    -    asyncTestCase.continueTesting();
    -  });
    -}
    -
    -function testInvalidImage() {
    -
    -  var url = 'testdata/invalid.gif'; // This file does not exist.
    -
    -  asyncTestCase.waitForAsync('image load');
    -
    -  goog.labs.net.image.load(url).then(
    -      fail /* opt_onResolved */,
    -      function() {
    -        asyncTestCase.continueTesting();
    -      });
    -}
    -
    -function testImageFactory() {
    -  var returnedImage = new Image();
    -  var factory = function() {
    -    return returnedImage;
    -  };
    -  var countedFactory = goog.testing.recordFunction(factory);
    -
    -  var url = 'testdata/cleardot.gif';
    -
    -  asyncTestCase.waitForAsync('image load');
    -  goog.labs.net.image.load(url, countedFactory).then(function(value) {
    -    assertEquals(returnedImage, value);
    -    assertEquals(1, countedFactory.getCallCount());
    -    asyncTestCase.continueTesting();
    -  });
    -}
    -
    -function testExistingImage() {
    -  var image = new Image();
    -
    -  var url = 'testdata/cleardot.gif';
    -
    -  asyncTestCase.waitForAsync('image load');
    -  goog.labs.net.image.load(url, image).then(function(value) {
    -    assertEquals(image, value);
    -    asyncTestCase.continueTesting();
    -  });
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/testdata/cleardot.gif b/src/database/third_party/closure-library/closure/goog/labs/net/testdata/cleardot.gif
    deleted file mode 100644
    index 1d11fa9ada9..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/labs/net/testdata/cleardot.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/testdata/xhr_test_json.data b/src/database/third_party/closure-library/closure/goog/labs/net/testdata/xhr_test_json.data
    deleted file mode 100644
    index 44afb24defb..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/testdata/xhr_test_json.data
    +++ /dev/null
    @@ -1,2 +0,0 @@
    -while(1);
    -{"stat":"ok","count":12345}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/testdata/xhr_test_text.data b/src/database/third_party/closure-library/closure/goog/labs/net/testdata/xhr_test_text.data
    deleted file mode 100644
    index b7f2f0e9072..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/testdata/xhr_test_text.data
    +++ /dev/null
    @@ -1 +0,0 @@
    -Just some data.
    \ No newline at end of file
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel.js b/src/database/third_party/closure-library/closure/goog/labs/net/webchannel.js
    deleted file mode 100644
    index 212b6e1eec4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel.js
    +++ /dev/null
    @@ -1,311 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview The API spec for the WebChannel messaging library.
    - *
    - * Similar to HTML5 WebSocket and Closure BrowserChannel, WebChannel
    - * offers an abstraction for point-to-point socket-like communication between
    - * a browser client and a remote origin.
    - *
    - * WebChannels are created via <code>WebChannel</code>. Multiple WebChannels
    - * may be multiplexed over the same WebChannelTransport, which represents
    - * the underlying physical connectivity over standard wire protocols
    - * such as HTTP and SPDY.
    - *
    - * A WebChannels in turn represents a logical communication channel between
    - * the client and server end point. A WebChannel remains open for
    - * as long as the client or server end-point allows.
    - *
    - * Messages may be delivered in-order or out-of-order, reliably or unreliably
    - * over the same WebChannel. Message delivery guarantees of a WebChannel is
    - * to be specified by the application code; and the choice of the
    - * underlying wire protocols is completely transparent to the API users.
    - *
    - * Client-to-client messaging via WebRTC based transport may also be support
    - * via the same WebChannel API in future.
    - *
    - * Note that we have no immediate plan to move this API out of labs. While
    - * the implementation is production ready, the API is subject to change
    - * (addition):
    - * 1. Completely new W3C APIs for Web messaging may emerge in near future.
    - * 2. New programming models for cloud (on the server-side) may require
    - *    new APIs to be defined.
    - * 3. WebRTC DataChannel alignment
    - * Lastly, we also want to white-list all internal use cases. As a general rule,
    - * we expect most applications to rely on stateless/RPC services.
    - *
    - */
    -
    -goog.provide('goog.net.WebChannel');
    -
    -goog.require('goog.events');
    -goog.require('goog.events.Event');
    -
    -
    -
    -/**
    - * A WebChannel represents a logical bi-directional channel over which the
    - * client communicates with a remote server that holds the other endpoint
    - * of the channel. A WebChannel is always created in the context of a shared
    - * {@link WebChannelTransport} instance. It is up to the underlying client-side
    - * and server-side implementations to decide how or when multiplexing is
    - * to be enabled.
    - *
    - * @interface
    - * @extends {EventTarget}
    - */
    -goog.net.WebChannel = function() {};
    -
    -
    -/**
    - * Configuration spec for newly created WebChannel instances.
    - *
    - * WebChannels are configured in the context of the containing
    - * {@link WebChannelTransport}. The configuration parameters are specified
    - * when a new instance of WebChannel is created via {@link WebChannelTransport}.
    - *
    - * messageHeaders: custom headers to be added to every message sent to the
    - * server. This object is mutable, and custom headers may be changed, removed,
    - * or added during the runtime after a channel has been opened.
    - *
    - * messageUrlParams: custom url query parameters to be added to every message
    - * sent to the server. This object is mutable, and custom parameters may be
    - * changed, removed or added during the runtime after a channel has been opened.
    - *
    - * clientProtocolHeaderRequired: whether a special header should be added to
    - * each message so that the server can dispatch webchannel messages without
    - * knowing the URL path prefix. Defaults to false.
    - *
    - * concurrentRequestLimit: the maximum number of in-flight HTTP requests allowed
    - * when SPDY is enabled. Currently we only detect SPDY in Chrome.
    - * This parameter defaults to 10. When SPDY is not enabled, this parameter
    - * will have no effect.
    - *
    - * supportsCrossDomainXhr: setting this to true to allow the use of sub-domains
    - * (as configured by the server) to send XHRs with the CORS withCredentials
    - * bit set to true.
    - *
    - * testUrl: the test URL for detecting connectivity during the initial
    - * handshake. This parameter defaults to "/<channel_url>/test".
    - *
    - *
    - * @typedef {{
    - *   messageHeaders: (!Object<string, string>|undefined),
    - *   messageUrlParams: (!Object<string, string>|undefined),
    - *   clientProtocolHeaderRequired: (boolean|undefined),
    - *   concurrentRequestLimit: (number|undefined),
    - *   supportsCrossDomainXhr: (boolean|undefined),
    - *   testUrl: (string|undefined)
    - * }}
    - */
    -goog.net.WebChannel.Options;
    -
    -
    -/**
    - * Types that are allowed as message data.
    - *
    - * @typedef {(ArrayBuffer|Blob|Object<string, string>|Array)}
    - */
    -goog.net.WebChannel.MessageData;
    -
    -
    -/**
    - * Open the WebChannel against the URI specified in the constructor.
    - */
    -goog.net.WebChannel.prototype.open = goog.abstractMethod;
    -
    -
    -/**
    - * Close the WebChannel.
    - */
    -goog.net.WebChannel.prototype.close = goog.abstractMethod;
    -
    -
    -/**
    - * Sends a message to the server that maintains the other end point of
    - * the WebChannel.
    - *
    - * @param {!goog.net.WebChannel.MessageData} message The message to send.
    - */
    -goog.net.WebChannel.prototype.send = goog.abstractMethod;
    -
    -
    -/**
    - * Common events fired by WebChannels.
    - * @enum {string}
    - */
    -goog.net.WebChannel.EventType = {
    -  /** Dispatched when the channel is opened. */
    -  OPEN: goog.events.getUniqueId('open'),
    -
    -  /** Dispatched when the channel is closed. */
    -  CLOSE: goog.events.getUniqueId('close'),
    -
    -  /** Dispatched when the channel is aborted due to errors. */
    -  ERROR: goog.events.getUniqueId('error'),
    -
    -  /** Dispatched when the channel has received a new message. */
    -  MESSAGE: goog.events.getUniqueId('message')
    -};
    -
    -
    -
    -/**
    - * The event interface for the MESSAGE event.
    - *
    - * @constructor
    - * @extends {goog.events.Event}
    - */
    -goog.net.WebChannel.MessageEvent = function() {
    -  goog.net.WebChannel.MessageEvent.base(
    -      this, 'constructor', goog.net.WebChannel.EventType.MESSAGE);
    -};
    -goog.inherits(goog.net.WebChannel.MessageEvent, goog.events.Event);
    -
    -
    -/**
    - * The content of the message received from the server.
    - *
    - * @type {!goog.net.WebChannel.MessageData}
    - */
    -goog.net.WebChannel.MessageEvent.prototype.data;
    -
    -
    -/**
    - * WebChannel level error conditions.
    - * @enum {number}
    - */
    -goog.net.WebChannel.ErrorStatus = {
    -  /** No error has occurred. */
    -  OK: 0,
    -
    -  /** Communication to the server has failed. */
    -  NETWORK_ERROR: 1,
    -
    -  /** The server fails to accept the WebChannel. */
    -  SERVER_ERROR: 2
    -};
    -
    -
    -
    -/**
    - * The event interface for the ERROR event.
    - *
    - * @constructor
    - * @extends {goog.events.Event}
    - */
    -goog.net.WebChannel.ErrorEvent = function() {
    -  goog.net.WebChannel.ErrorEvent.base(
    -      this, 'constructor', goog.net.WebChannel.EventType.ERROR);
    -};
    -goog.inherits(goog.net.WebChannel.ErrorEvent, goog.events.Event);
    -
    -
    -/**
    - * The error status.
    - *
    - * @type {!goog.net.WebChannel.ErrorStatus}
    - */
    -goog.net.WebChannel.ErrorEvent.prototype.status;
    -
    -
    -/**
    - * @return {!goog.net.WebChannel.RuntimeProperties} The runtime properties
    - * of the WebChannel instance.
    - */
    -goog.net.WebChannel.prototype.getRuntimeProperties = goog.abstractMethod;
    -
    -
    -
    -/**
    - * The runtime properties of the WebChannel instance.
    - *
    - * This class is defined for debugging and monitoring purposes, as well as for
    - * runtime functions that the application may choose to manage by itself.
    - *
    - * @interface
    - */
    -goog.net.WebChannel.RuntimeProperties = function() {};
    -
    -
    -/**
    - * @return {number} The effective limit for the number of concurrent HTTP
    - * requests that are allowed to be made for sending messages from the client
    - * to the server. When SPDY is not enabled, this limit will be one.
    - */
    -goog.net.WebChannel.RuntimeProperties.prototype.getConcurrentRequestLimit =
    -    goog.abstractMethod;
    -
    -
    -/**
    - * For applications that need support multiple channels (e.g. from
    - * different tabs) to the same origin, use this method to decide if SPDY is
    - * enabled and therefore it is safe to open multiple channels.
    - *
    - * If SPDY is disabled, the application may choose to limit the number of active
    - * channels to one or use other means such as sub-domains to work around
    - * the browser connection limit.
    - *
    - * @return {boolean} Whether SPDY is enabled for the origin against which
    - * the channel is created.
    - */
    -goog.net.WebChannel.RuntimeProperties.prototype.isSpdyEnabled =
    -    goog.abstractMethod;
    -
    -
    -/**
    - * This method may be used by the application to stop ack of received messages
    - * as a means of enabling or disabling flow-control on the server-side.
    - *
    - * @param {boolean} enabled If true, enable flow-control behavior on the
    - * server side. Setting it to false will cancel ay previous enabling action.
    - */
    -goog.net.WebChannel.RuntimeProperties.prototype.setServerFlowControl =
    -    goog.abstractMethod;
    -
    -
    -/**
    - * This method may be used by the application to throttle the rate of outgoing
    - * messages, as a means of sender initiated flow-control.
    - *
    - * @return {number} The total number of messages that have not received
    - * ack from the server and therefore remain in the buffer.
    - */
    -goog.net.WebChannel.RuntimeProperties.prototype.getNonAckedMessageCount =
    -    goog.abstractMethod;
    -
    -
    -/**
    - * @return {number} The last HTTP status code received by the channel.
    - */
    -goog.net.WebChannel.RuntimeProperties.prototype.getLastStatusCode =
    -    goog.abstractMethod;
    -
    -
    -/**
    - * A special header to indicate to the server what messaging protocol
    - * each HTTP message is speaking.
    - *
    - * @type {string}
    - */
    -goog.net.WebChannel.X_CLIENT_PROTOCOL = 'X-Client-Protocol';
    -
    -
    -/**
    - * The value for x-client-protocol when the messaging protocol is WebChannel.
    - *
    - * @type {string}
    - */
    -goog.net.WebChannel.X_CLIENT_PROTOCOL_WEB_CHANNEL = 'webchannel';
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/basetestchannel.js b/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/basetestchannel.js
    deleted file mode 100644
    index d7df296abd6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/basetestchannel.js
    +++ /dev/null
    @@ -1,457 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Base TestChannel implementation.
    - *
    - */
    -
    -
    -goog.provide('goog.labs.net.webChannel.BaseTestChannel');
    -
    -goog.require('goog.labs.net.webChannel.Channel');
    -goog.require('goog.labs.net.webChannel.ChannelRequest');
    -goog.require('goog.labs.net.webChannel.requestStats');
    -goog.require('goog.labs.net.webChannel.requestStats.Stat');
    -
    -
    -
    -/**
    - * A TestChannel is used during the first part of channel negotiation
    - * with the server to create the channel. It helps us determine whether we're
    - * behind a buffering proxy.
    - *
    - * @constructor
    - * @struct
    - * @param {!goog.labs.net.webChannel.Channel} channel The channel
    - *     that owns this test channel.
    - * @param {!goog.labs.net.webChannel.WebChannelDebug} channelDebug A
    - *     WebChannelDebug instance to use for logging.
    - * @implements {goog.labs.net.webChannel.Channel}
    - */
    -goog.labs.net.webChannel.BaseTestChannel = function(channel, channelDebug) {
    -  /**
    -   * The channel that owns this test channel
    -   * @private {!goog.labs.net.webChannel.Channel}
    -   */
    -  this.channel_ = channel;
    -
    -  /**
    -   * The channel debug to use for logging
    -   * @private {!goog.labs.net.webChannel.WebChannelDebug}
    -   */
    -  this.channelDebug_ = channelDebug;
    -
    -  /**
    -   * Extra HTTP headers to add to all the requests sent to the server.
    -   * @private {Object}
    -   */
    -  this.extraHeaders_ = null;
    -
    -  /**
    -   * The test request.
    -   * @private {goog.labs.net.webChannel.ChannelRequest}
    -   */
    -  this.request_ = null;
    -
    -  /**
    -   * Whether we have received the first result as an intermediate result. This
    -   * helps us determine whether we're behind a buffering proxy.
    -   * @private {boolean}
    -   */
    -  this.receivedIntermediateResult_ = false;
    -
    -  /**
    -   * The relative path for test requests.
    -   * @private {?string}
    -   */
    -  this.path_ = null;
    -
    -  /**
    -   * The last status code received.
    -   * @private {number}
    -   */
    -  this.lastStatusCode_ = -1;
    -
    -  /**
    -   * A subdomain prefix for using a subdomain in IE for the backchannel
    -   * requests.
    -   * @private {?string}
    -   */
    -  this.hostPrefix_ = null;
    -
    -  /**
    -   * The effective client protocol as indicated by the initial handshake
    -   * response via the x-client-wire-protocol header.
    -   *
    -   * @private {?string}
    -   */
    -  this.clientProtocol_ = null;
    -};
    -
    -
    -goog.scope(function() {
    -var BaseTestChannel = goog.labs.net.webChannel.BaseTestChannel;
    -var WebChannelDebug = goog.labs.net.webChannel.WebChannelDebug;
    -var ChannelRequest = goog.labs.net.webChannel.ChannelRequest;
    -var requestStats = goog.labs.net.webChannel.requestStats;
    -var Channel = goog.labs.net.webChannel.Channel;
    -
    -
    -/**
    - * Enum type for the test channel state machine
    - * @enum {number}
    - * @private
    - */
    -BaseTestChannel.State_ = {
    -  /**
    -   * The state for the TestChannel state machine where we making the
    -   * initial call to get the server configured parameters.
    -   */
    -  INIT: 0,
    -
    -  /**
    -   * The  state for the TestChannel state machine where we're checking to
    -   * se if we're behind a buffering proxy.
    -   */
    -  CONNECTION_TESTING: 1
    -};
    -
    -
    -/**
    - * The state of the state machine for this object.
    - *
    - * @private {?BaseTestChannel.State_}
    - */
    -BaseTestChannel.prototype.state_ = null;
    -
    -
    -/**
    - * Sets extra HTTP headers to add to all the requests sent to the server.
    - *
    - * @param {Object} extraHeaders The HTTP headers.
    - */
    -BaseTestChannel.prototype.setExtraHeaders = function(extraHeaders) {
    -  this.extraHeaders_ = extraHeaders;
    -};
    -
    -
    -/**
    - * Starts the test channel. This initiates connections to the server.
    - *
    - * @param {string} path The relative uri for the test connection.
    - */
    -BaseTestChannel.prototype.connect = function(path) {
    -  this.path_ = path;
    -  var sendDataUri = this.channel_.getForwardChannelUri(this.path_);
    -
    -  requestStats.notifyStatEvent(requestStats.Stat.TEST_STAGE_ONE_START);
    -
    -  // If the channel already has the result of the handshake, then skip it.
    -  var handshakeResult = this.channel_.getConnectionState().handshakeResult;
    -  if (goog.isDefAndNotNull(handshakeResult)) {
    -    this.hostPrefix_ = this.channel_.correctHostPrefix(handshakeResult[0]);
    -    this.state_ = BaseTestChannel.State_.CONNECTION_TESTING;
    -    this.checkBufferingProxy_();
    -    return;
    -  }
    -
    -  // the first request returns server specific parameters
    -  sendDataUri.setParameterValues('MODE', 'init');
    -  this.request_ = ChannelRequest.createChannelRequest(this, this.channelDebug_);
    -  this.request_.setExtraHeaders(this.extraHeaders_);
    -  this.request_.xmlHttpGet(sendDataUri, false /* decodeChunks */,
    -      null /* hostPrefix */, true /* opt_noClose */);
    -  this.state_ = BaseTestChannel.State_.INIT;
    -};
    -
    -
    -/**
    - * Begins the second stage of the test channel where we test to see if we're
    - * behind a buffering proxy. The server sends back a multi-chunked response
    - * with the first chunk containing the content '1' and then two seconds later
    - * sending the second chunk containing the content '2'. Depending on how we
    - * receive the content, we can tell if we're behind a buffering proxy.
    - * @private
    - */
    -BaseTestChannel.prototype.checkBufferingProxy_ = function() {
    -  this.channelDebug_.debug('TestConnection: starting stage 2');
    -
    -  // If the test result is already available, skip its execution.
    -  var bufferingProxyResult =
    -      this.channel_.getConnectionState().bufferingProxyResult;
    -  if (goog.isDefAndNotNull(bufferingProxyResult)) {
    -    this.channelDebug_.debug(
    -        'TestConnection: skipping stage 2, precomputed result is ' +
    -        bufferingProxyResult ? 'Buffered' : 'Unbuffered');
    -    requestStats.notifyStatEvent(requestStats.Stat.TEST_STAGE_TWO_START);
    -    if (bufferingProxyResult) { // Buffered/Proxy connection
    -      requestStats.notifyStatEvent(requestStats.Stat.PROXY);
    -      this.channel_.testConnectionFinished(this, false);
    -    } else { // Unbuffered/NoProxy connection
    -      requestStats.notifyStatEvent(requestStats.Stat.NOPROXY);
    -      this.channel_.testConnectionFinished(this, true);
    -    }
    -    return; // Skip the test
    -  }
    -  this.request_ = ChannelRequest.createChannelRequest(this, this.channelDebug_);
    -  this.request_.setExtraHeaders(this.extraHeaders_);
    -  var recvDataUri = this.channel_.getBackChannelUri(this.hostPrefix_,
    -      /** @type {string} */ (this.path_));
    -
    -  requestStats.notifyStatEvent(requestStats.Stat.TEST_STAGE_TWO_START);
    -  recvDataUri.setParameterValues('TYPE', 'xmlhttp');
    -  this.request_.xmlHttpGet(recvDataUri, false /** decodeChunks */,
    -      this.hostPrefix_, false /** opt_noClose */);
    -};
    -
    -
    -/**
    - * @override
    - */
    -BaseTestChannel.prototype.createXhrIo = function(hostPrefix) {
    -  return this.channel_.createXhrIo(hostPrefix);
    -};
    -
    -
    -/**
    - * Aborts the test channel.
    - */
    -BaseTestChannel.prototype.abort = function() {
    -  if (this.request_) {
    -    this.request_.cancel();
    -    this.request_ = null;
    -  }
    -  this.lastStatusCode_ = -1;
    -};
    -
    -
    -/**
    - * Returns whether the test channel is closed. The ChannelRequest object expects
    - * this method to be implemented on its handler.
    - *
    - * @return {boolean} Whether the channel is closed.
    - * @override
    - */
    -BaseTestChannel.prototype.isClosed = function() {
    -  return false;
    -};
    -
    -
    -/**
    - * Callback from ChannelRequest for when new data is received
    - *
    - * @param {ChannelRequest} req The request object.
    - * @param {string} responseText The text of the response.
    - * @override
    - */
    -BaseTestChannel.prototype.onRequestData = function(req, responseText) {
    -  this.lastStatusCode_ = req.getLastStatusCode();
    -  if (this.state_ == BaseTestChannel.State_.INIT) {
    -    this.channelDebug_.debug('TestConnection: Got data for stage 1');
    -    if (!responseText) {
    -      this.channelDebug_.debug('TestConnection: Null responseText');
    -      // The server should always send text; something is wrong here
    -      this.channel_.testConnectionFailure(this, ChannelRequest.Error.BAD_DATA);
    -      return;
    -    }
    -    /** @preserveTry */
    -    try {
    -      var respArray = this.channel_.getWireCodec().decodeMessage(responseText);
    -    } catch (e) {
    -      this.channelDebug_.dumpException(e);
    -      this.channel_.testConnectionFailure(this, ChannelRequest.Error.BAD_DATA);
    -      return;
    -    }
    -    this.hostPrefix_ = this.channel_.correctHostPrefix(respArray[0]);
    -  } else if (this.state_ == BaseTestChannel.State_.CONNECTION_TESTING) {
    -    if (this.receivedIntermediateResult_) {
    -      requestStats.notifyStatEvent(requestStats.Stat.TEST_STAGE_TWO_DATA_TWO);
    -    } else {
    -      // '11111' is used instead of '1' to prevent a small amount of buffering
    -      // by Safari.
    -      if (responseText == '11111') {
    -        requestStats.notifyStatEvent(requestStats.Stat.TEST_STAGE_TWO_DATA_ONE);
    -        this.receivedIntermediateResult_ = true;
    -        if (this.checkForEarlyNonBuffered_()) {
    -          // If early chunk detection is on, and we passed the tests,
    -          // assume HTTP_OK, cancel the test and turn on noproxy mode.
    -          this.lastStatusCode_ = 200;
    -          this.request_.cancel();
    -          this.channelDebug_.debug(
    -              'Test connection succeeded; using streaming connection');
    -          requestStats.notifyStatEvent(requestStats.Stat.NOPROXY);
    -          this.channel_.testConnectionFinished(this, true);
    -        }
    -      } else {
    -        requestStats.notifyStatEvent(
    -            requestStats.Stat.TEST_STAGE_TWO_DATA_BOTH);
    -        this.receivedIntermediateResult_ = false;
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Callback from ChannelRequest that indicates a request has completed.
    - *
    - * @param {!ChannelRequest} req The request object.
    - * @override
    - */
    -BaseTestChannel.prototype.onRequestComplete = function(req) {
    -  this.lastStatusCode_ = this.request_.getLastStatusCode();
    -  if (!this.request_.getSuccess()) {
    -    this.channelDebug_.debug(
    -        'TestConnection: request failed, in state ' + this.state_);
    -    if (this.state_ == BaseTestChannel.State_.INIT) {
    -      requestStats.notifyStatEvent(requestStats.Stat.TEST_STAGE_ONE_FAILED);
    -    } else if (this.state_ == BaseTestChannel.State_.CONNECTION_TESTING) {
    -      requestStats.notifyStatEvent(requestStats.Stat.TEST_STAGE_TWO_FAILED);
    -    }
    -    this.channel_.testConnectionFailure(this,
    -        /** @type {ChannelRequest.Error} */
    -        (this.request_.getLastError()));
    -    return;
    -  }
    -
    -  if (this.state_ == BaseTestChannel.State_.INIT) {
    -    this.recordClientProtocol_(req);
    -    this.state_ = BaseTestChannel.State_.CONNECTION_TESTING;
    -
    -    this.channelDebug_.debug(
    -        'TestConnection: request complete for initial check');
    -
    -    this.checkBufferingProxy_();
    -  } else if (this.state_ == BaseTestChannel.State_.CONNECTION_TESTING) {
    -    this.channelDebug_.debug('TestConnection: request complete for stage 2');
    -
    -    var goodConn = this.receivedIntermediateResult_;
    -    if (goodConn) {
    -      this.channelDebug_.debug(
    -          'Test connection succeeded; using streaming connection');
    -      requestStats.notifyStatEvent(requestStats.Stat.NOPROXY);
    -      this.channel_.testConnectionFinished(this, true);
    -    } else {
    -      this.channelDebug_.debug(
    -          'Test connection failed; not using streaming');
    -      requestStats.notifyStatEvent(requestStats.Stat.PROXY);
    -      this.channel_.testConnectionFinished(this, false);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Record the client protocol header from the initial handshake response.
    - *
    - * @param {!ChannelRequest} req The request object.
    - * @private
    - */
    -BaseTestChannel.prototype.recordClientProtocol_ = function(req) {
    -  var xmlHttp = req.getXhr();
    -  if (xmlHttp) {
    -    var protocolHeader = xmlHttp.getResponseHeader('x-client-wire-protocol');
    -    this.clientProtocol_ = protocolHeader ? protocolHeader : null;
    -  }
    -};
    -
    -
    -/**
    - * @return {?string} The client protocol as recorded with the init handshake
    - *     request.
    - */
    -BaseTestChannel.prototype.getClientProtocol = function() {
    -  return this.clientProtocol_;
    -};
    -
    -
    -/**
    - * Returns the last status code received for a request.
    - * @return {number} The last status code received for a request.
    - */
    -BaseTestChannel.prototype.getLastStatusCode = function() {
    -  return this.lastStatusCode_;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether we should be using secondary domains when the
    - *     server instructs us to do so.
    - * @override
    - */
    -BaseTestChannel.prototype.shouldUseSecondaryDomains = function() {
    -  return this.channel_.shouldUseSecondaryDomains();
    -};
    -
    -
    -/**
    - * @override
    - */
    -BaseTestChannel.prototype.isActive = function() {
    -  return this.channel_.isActive();
    -};
    -
    -
    -/**
    - * @return {boolean} True if test stage 2 detected a non-buffered
    - *     channel early and early no buffering detection is enabled.
    - * @private
    - */
    -BaseTestChannel.prototype.checkForEarlyNonBuffered_ = function() {
    -  return ChannelRequest.supportsXhrStreaming();
    -};
    -
    -
    -/**
    - * @override
    - */
    -BaseTestChannel.prototype.getForwardChannelUri = goog.abstractMethod;
    -
    -
    -/**
    - * @override
    - */
    -BaseTestChannel.prototype.getBackChannelUri = goog.abstractMethod;
    -
    -
    -/**
    - * @override
    - */
    -BaseTestChannel.prototype.correctHostPrefix = goog.abstractMethod;
    -
    -
    -/**
    - * @override
    - */
    -BaseTestChannel.prototype.createDataUri = goog.abstractMethod;
    -
    -
    -/**
    - * @override
    - */
    -BaseTestChannel.prototype.testConnectionFinished = goog.abstractMethod;
    -
    -
    -/**
    - * @override
    - */
    -BaseTestChannel.prototype.testConnectionFailure = goog.abstractMethod;
    -
    -
    -/**
    - * @override
    - */
    -BaseTestChannel.prototype.getConnectionState = goog.abstractMethod;
    -});  // goog.scope
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/channel.js b/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/channel.js
    deleted file mode 100644
    index 52281223a9d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/channel.js
    +++ /dev/null
    @@ -1,181 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A shared interface for WebChannelBase and BaseTestChannel.
    - *
    - * @visibility {:internal}
    - */
    -
    -
    -goog.provide('goog.labs.net.webChannel.Channel');
    -
    -
    -
    -/**
    - * Shared interface between Channel and TestChannel to support callbacks
    - * between WebChannelBase and BaseTestChannel and between Channel and
    - * ChannelRequest.
    - *
    - * @interface
    - */
    -goog.labs.net.webChannel.Channel = function() {};
    -
    -
    -goog.scope(function() {
    -var Channel = goog.labs.net.webChannel.Channel;
    -
    -
    -/**
    - * Determines whether to use a secondary domain when the server gives us
    - * a host prefix. This allows us to work around browser per-domain
    - * connection limits.
    - *
    - * If you need to use secondary domains on different browsers and IE10,
    - * you have two choices:
    - *     1) If you only care about browsers that support CORS
    - *        (https://developer.mozilla.org/en-US/docs/HTTP_access_control), you
    - *        can use {@link #setSupportsCrossDomainXhrs} and set the appropriate
    - *        CORS response headers on the server.
    - *     2) Or, override this method in a subclass, and make sure that those
    - *        browsers use some messaging mechanism that works cross-domain (e.g
    - *        iframes and window.postMessage).
    - *
    - * @return {boolean} Whether to use secondary domains.
    - * @see http://code.google.com/p/closure-library/issues/detail?id=339
    - */
    -Channel.prototype.shouldUseSecondaryDomains = goog.abstractMethod;
    -
    -
    -/**
    - * Called when creating an XhrIo object.  Override in a subclass if
    - * you need to customize the behavior, for example to enable the creation of
    - * XHR's capable of calling a secondary domain. Will also allow calling
    - * a secondary domain if withCredentials (CORS) is enabled.
    - * @param {?string} hostPrefix The host prefix, if we need an XhrIo object
    - *     capable of calling a secondary domain.
    - * @return {!goog.net.XhrIo} A new XhrIo object.
    - */
    -Channel.prototype.createXhrIo = goog.abstractMethod;
    -
    -
    -/**
    - * Callback from ChannelRequest that indicates a request has completed.
    - * @param {!goog.labs.net.webChannel.ChannelRequest} request
    - *     The request object.
    - */
    -Channel.prototype.onRequestComplete = goog.abstractMethod;
    -
    -
    -/**
    - * Returns whether the channel is closed
    - * @return {boolean} true if the channel is closed.
    - */
    -Channel.prototype.isClosed = goog.abstractMethod;
    -
    -
    -/**
    - * Callback from ChannelRequest for when new data is received
    - * @param {goog.labs.net.webChannel.ChannelRequest} request
    - *     The request object.
    - * @param {string} responseText The text of the response.
    - */
    -Channel.prototype.onRequestData = goog.abstractMethod;
    -
    -
    -/**
    - * Gets whether this channel is currently active. This is used to determine the
    - * length of time to wait before retrying. This call delegates to the handler.
    - * @return {boolean} Whether the channel is currently active.
    - */
    -Channel.prototype.isActive = goog.abstractMethod;
    -
    -
    -/**
    - * Not needed for testchannel.
    - *
    - * Gets the Uri used for the connection that sends data to the server.
    - * @param {string} path The path on the host.
    - * @return {goog.Uri} The forward channel URI.
    - */
    -Channel.prototype.getForwardChannelUri = goog.abstractMethod;
    -
    -
    -/**
    - * Not needed for testchannel.
    - *
    - * Gets the Uri used for the connection that receives data from the server.
    - * @param {?string} hostPrefix The host prefix.
    - * @param {string} path The path on the host.
    - * @return {goog.Uri} The back channel URI.
    - */
    -Channel.prototype.getBackChannelUri = goog.abstractMethod;
    -
    -
    -/**
    - * Not needed for testchannel.
    - *
    - * Allows the handler to override a host prefix provided by the server.  Will
    - * be called whenever the channel has received such a prefix and is considering
    - * its use.
    - * @param {?string} serverHostPrefix The host prefix provided by the server.
    - * @return {?string} The host prefix the client should use.
    - */
    -Channel.prototype.correctHostPrefix = goog.abstractMethod;
    -
    -
    -/**
    - * Not needed for testchannel.
    - *
    - * Creates a data Uri applying logic for secondary hostprefix, port
    - * overrides, and versioning.
    - * @param {?string} hostPrefix The host prefix.
    - * @param {string} path The path on the host (may be absolute or relative).
    - * @param {number=} opt_overridePort Optional override port.
    - * @return {goog.Uri} The data URI.
    - */
    -Channel.prototype.createDataUri = goog.abstractMethod;
    -
    -
    -/**
    - * Not needed for testchannel.
    - *
    - * Callback from TestChannel for when the channel is finished.
    - * @param {goog.labs.net.webChannel.BaseTestChannel} testChannel
    - *     The TestChannel.
    - * @param {boolean} useChunked  Whether we can chunk responses.
    - */
    -Channel.prototype.testConnectionFinished = goog.abstractMethod;
    -
    -
    -/**
    - * Not needed for testchannel.
    - *
    - * Callback from TestChannel for when the channel has an error.
    - * @param {goog.labs.net.webChannel.BaseTestChannel} testChannel
    - *     The TestChannel.
    - * @param {goog.labs.net.webChannel.ChannelRequest.Error} errorCode
    - *     The error code of the failure.
    - */
    -Channel.prototype.testConnectionFailure = goog.abstractMethod;
    -
    -
    -/**
    - * Not needed for testchannel.
    - * Gets the result of previous connectivity tests.
    - *
    - * @return {!goog.labs.net.webChannel.ConnectionState} The connectivity state.
    - */
    -Channel.prototype.getConnectionState = goog.abstractMethod;
    -});  // goog.scope
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/channelrequest.js b/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/channelrequest.js
    deleted file mode 100644
    index 0077d934404..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/channelrequest.js
    +++ /dev/null
    @@ -1,1084 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Definition of the ChannelRequest class. The request
    - * object encapsulates the logic for making a single request, either for the
    - * forward channel, back channel, or test channel, to the server. It contains
    - * the logic for the two types of transports we use:
    - * XMLHTTP and Image request. It provides timeout detection. More transports
    - * to be added in future, such as Fetch, WebSocket.
    - *
    - * @visibility {:internal}
    - */
    -
    -
    -goog.provide('goog.labs.net.webChannel.ChannelRequest');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.async.Throttle');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.labs.net.webChannel.requestStats');
    -goog.require('goog.labs.net.webChannel.requestStats.ServerReachability');
    -goog.require('goog.labs.net.webChannel.requestStats.Stat');
    -goog.require('goog.net.ErrorCode');
    -goog.require('goog.net.EventType');
    -goog.require('goog.net.XmlHttp');
    -goog.require('goog.object');
    -goog.require('goog.uri.utils.StandardQueryParam');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * A new ChannelRequest is created for each request to the server.
    - *
    - * @param {goog.labs.net.webChannel.Channel} channel
    - *     The channel that owns this request.
    - * @param {goog.labs.net.webChannel.WebChannelDebug} channelDebug A
    - *     WebChannelDebug to use for logging.
    - * @param {string=} opt_sessionId The session id for the channel.
    - * @param {string|number=} opt_requestId The request id for this request.
    - * @param {number=} opt_retryId The retry id for this request.
    - * @constructor
    - * @struct
    - * @final
    - */
    -goog.labs.net.webChannel.ChannelRequest = function(channel, channelDebug,
    -    opt_sessionId, opt_requestId, opt_retryId) {
    -  /**
    -   * The channel object that owns the request.
    -   * @private {goog.labs.net.webChannel.Channel}
    -   */
    -  this.channel_ = channel;
    -
    -  /**
    -   * The channel debug to use for logging
    -   * @private {goog.labs.net.webChannel.WebChannelDebug}
    -   */
    -  this.channelDebug_ = channelDebug;
    -
    -  /**
    -   * The Session ID for the channel.
    -   * @private {string|undefined}
    -   */
    -  this.sid_ = opt_sessionId;
    -
    -  /**
    -   * The RID (request ID) for the request.
    -   * @private {string|number|undefined}
    -   */
    -  this.rid_ = opt_requestId;
    -
    -  /**
    -   * The attempt number of the current request.
    -   * @private {number}
    -   */
    -  this.retryId_ = opt_retryId || 1;
    -
    -  /**
    -   * An object to keep track of the channel request event listeners.
    -   * @private {!goog.events.EventHandler<
    -   *     !goog.labs.net.webChannel.ChannelRequest>}
    -   */
    -  this.eventHandler_ = new goog.events.EventHandler(this);
    -
    -  /**
    -   * The timeout in ms before failing the request.
    -   * @private {number}
    -   */
    -  this.timeout_ = goog.labs.net.webChannel.ChannelRequest.TIMEOUT_MS_;
    -
    -  /**
    -   * A timer for polling responseText in browsers that don't fire
    -   * onreadystatechange during incremental loading of responseText.
    -   * @private {goog.Timer}
    -   */
    -  this.pollingTimer_ = new goog.Timer();
    -
    -  this.pollingTimer_.setInterval(
    -      goog.labs.net.webChannel.ChannelRequest.POLLING_INTERVAL_MS_);
    -
    -  /**
    -   * Extra HTTP headers to add to all the requests sent to the server.
    -   * @private {Object}
    -   */
    -  this.extraHeaders_ = null;
    -
    -
    -  /**
    -   * Whether the request was successful. This is only set to true after the
    -   * request successfully completes.
    -   * @private {boolean}
    -   */
    -  this.successful_ = false;
    -
    -
    -  /**
    -   * The TimerID of the timer used to detect if the request has timed-out.
    -   * @type {?number}
    -   * @private
    -   */
    -  this.watchDogTimerId_ = null;
    -
    -  /**
    -   * The time in the future when the request will timeout.
    -   * @private {?number}
    -   */
    -  this.watchDogTimeoutTime_ = null;
    -
    -  /**
    -   * The time the request started.
    -   * @private {?number}
    -   */
    -  this.requestStartTime_ = null;
    -
    -  /**
    -   * The type of request (XMLHTTP, IMG)
    -   * @private {?number}
    -   */
    -  this.type_ = null;
    -
    -  /**
    -   * The base Uri for the request. The includes all the parameters except the
    -   * one that indicates the retry number.
    -   * @private {goog.Uri}
    -   */
    -  this.baseUri_ = null;
    -
    -  /**
    -   * The request Uri that was actually used for the most recent request attempt.
    -   * @private {goog.Uri}
    -   */
    -  this.requestUri_ = null;
    -
    -  /**
    -   * The post data, if the request is a post.
    -   * @private {?string}
    -   */
    -  this.postData_ = null;
    -
    -  /**
    -   * The XhrLte request if the request is using XMLHTTP
    -   * @private {goog.net.XhrIo}
    -   */
    -  this.xmlHttp_ = null;
    -
    -  /**
    -   * The position of where the next unprocessed chunk starts in the response
    -   * text.
    -   * @private {number}
    -   */
    -  this.xmlHttpChunkStart_ = 0;
    -
    -  /**
    -   * The verb (Get or Post) for the request.
    -   * @private {?string}
    -   */
    -  this.verb_ = null;
    -
    -  /**
    -   * The last error if the request failed.
    -   * @private {?goog.labs.net.webChannel.ChannelRequest.Error}
    -   */
    -  this.lastError_ = null;
    -
    -  /**
    -   * The last status code received.
    -   * @private {number}
    -   */
    -  this.lastStatusCode_ = -1;
    -
    -  /**
    -   * Whether to send the Connection:close header as part of the request.
    -   * @private {boolean}
    -   */
    -  this.sendClose_ = true;
    -
    -  /**
    -   * Whether the request has been cancelled due to a call to cancel.
    -   * @private {boolean}
    -   */
    -  this.cancelled_ = false;
    -
    -  /**
    -   * A throttle time in ms for readystatechange events for the backchannel.
    -   * Useful for throttling when ready state is INTERACTIVE (partial data).
    -   * If set to zero no throttle is used.
    -   *
    -   * See WebChannelBase.prototype.readyStateChangeThrottleMs_
    -   *
    -   * @private {number}
    -   */
    -  this.readyStateChangeThrottleMs_ = 0;
    -
    -  /**
    -   * The throttle for readystatechange events for the current request, or null
    -   * if there is none.
    -   * @private {goog.async.Throttle}
    -   */
    -  this.readyStateChangeThrottle_ = null;
    -
    -
    -  /**
    -   * Whether to the result is expected to be encoded for chunking and thus
    -   * requires decoding.
    -   * @private {boolean}
    -   */
    -  this.decodeChunks_ = false;
    -};
    -
    -
    -goog.scope(function() {
    -var Channel = goog.labs.net.webChannel.Channel;
    -var ChannelRequest = goog.labs.net.webChannel.ChannelRequest;
    -var requestStats = goog.labs.net.webChannel.requestStats;
    -var WebChannelDebug = goog.labs.net.webChannel.WebChannelDebug;
    -
    -
    -/**
    - * Default timeout in MS for a request. The server must return data within this
    - * time limit for the request to not timeout.
    - * @private {number}
    - */
    -ChannelRequest.TIMEOUT_MS_ = 45 * 1000;
    -
    -
    -/**
    - * How often to poll (in MS) for changes to responseText in browsers that don't
    - * fire onreadystatechange during incremental loading of responseText.
    - * @private {number}
    - */
    -ChannelRequest.POLLING_INTERVAL_MS_ = 250;
    -
    -
    -/**
    - * Enum for channel requests type
    - * @enum {number}
    - * @private
    - */
    -ChannelRequest.Type_ = {
    -  /**
    -   * XMLHTTP requests.
    -   */
    -  XML_HTTP: 1,
    -
    -  /**
    -   * IMG requests.
    -   */
    -  IMG: 2
    -};
    -
    -
    -/**
    - * Enum type for identifying an error.
    - * @enum {number}
    - */
    -ChannelRequest.Error = {
    -  /**
    -   * Errors due to a non-200 status code.
    -   */
    -  STATUS: 0,
    -
    -  /**
    -   * Errors due to no data being returned.
    -   */
    -  NO_DATA: 1,
    -
    -  /**
    -   * Errors due to a timeout.
    -   */
    -  TIMEOUT: 2,
    -
    -  /**
    -   * Errors due to the server returning an unknown.
    -   */
    -  UNKNOWN_SESSION_ID: 3,
    -
    -  /**
    -   * Errors due to bad data being received.
    -   */
    -  BAD_DATA: 4,
    -
    -  /**
    -   * Errors due to the handler throwing an exception.
    -   */
    -  HANDLER_EXCEPTION: 5,
    -
    -  /**
    -   * The browser declared itself offline during the request.
    -   */
    -  BROWSER_OFFLINE: 6
    -};
    -
    -
    -/**
    - * Returns a useful error string for debugging based on the specified error
    - * code.
    - * @param {?ChannelRequest.Error} errorCode The error code.
    - * @param {number} statusCode The HTTP status code.
    - * @return {string} The error string for the given code combination.
    - */
    -ChannelRequest.errorStringFromCode = function(errorCode, statusCode) {
    -  switch (errorCode) {
    -    case ChannelRequest.Error.STATUS:
    -      return 'Non-200 return code (' + statusCode + ')';
    -    case ChannelRequest.Error.NO_DATA:
    -      return 'XMLHTTP failure (no data)';
    -    case ChannelRequest.Error.TIMEOUT:
    -      return 'HttpConnection timeout';
    -    default:
    -      return 'Unknown error';
    -  }
    -};
    -
    -
    -/**
    - * Sentinel value used to indicate an invalid chunk in a multi-chunk response.
    - * @private {Object}
    - */
    -ChannelRequest.INVALID_CHUNK_ = {};
    -
    -
    -/**
    - * Sentinel value used to indicate an incomplete chunk in a multi-chunk
    - * response.
    - * @private {Object}
    - */
    -ChannelRequest.INCOMPLETE_CHUNK_ = {};
    -
    -
    -/**
    - * Returns whether XHR streaming is supported on this browser.
    - *
    - * @return {boolean} Whether XHR streaming is supported.
    - * @see http://code.google.com/p/closure-library/issues/detail?id=346
    - */
    -ChannelRequest.supportsXhrStreaming = function() {
    -  return !goog.userAgent.IE || goog.userAgent.isDocumentModeOrHigher(10);
    -};
    -
    -
    -/**
    - * Sets extra HTTP headers to add to all the requests sent to the server.
    - *
    - * @param {Object} extraHeaders The HTTP headers.
    - */
    -ChannelRequest.prototype.setExtraHeaders = function(extraHeaders) {
    -  this.extraHeaders_ = extraHeaders;
    -};
    -
    -
    -/**
    - * Sets the timeout for a request
    - *
    - * @param {number} timeout   The timeout in MS for when we fail the request.
    - */
    -ChannelRequest.prototype.setTimeout = function(timeout) {
    -  this.timeout_ = timeout;
    -};
    -
    -
    -/**
    - * Sets the throttle for handling onreadystatechange events for the request.
    - *
    - * @param {number} throttle The throttle in ms.  A value of zero indicates
    - *     no throttle.
    - */
    -ChannelRequest.prototype.setReadyStateChangeThrottle = function(throttle) {
    -  this.readyStateChangeThrottleMs_ = throttle;
    -};
    -
    -
    -/**
    - * Uses XMLHTTP to send an HTTP POST to the server.
    - *
    - * @param {goog.Uri} uri  The uri of the request.
    - * @param {string} postData  The data for the post body.
    - * @param {boolean} decodeChunks  Whether to the result is expected to be
    - *     encoded for chunking and thus requires decoding.
    - */
    -ChannelRequest.prototype.xmlHttpPost = function(uri, postData, decodeChunks) {
    -  this.type_ = ChannelRequest.Type_.XML_HTTP;
    -  this.baseUri_ = uri.clone().makeUnique();
    -  this.postData_ = postData;
    -  this.decodeChunks_ = decodeChunks;
    -  this.sendXmlHttp_(null /* hostPrefix */);
    -};
    -
    -
    -/**
    - * Uses XMLHTTP to send an HTTP GET to the server.
    - *
    - * @param {goog.Uri} uri  The uri of the request.
    - * @param {boolean} decodeChunks  Whether to the result is expected to be
    - *     encoded for chunking and thus requires decoding.
    - * @param {?string} hostPrefix  The host prefix, if we might be using a
    - *     secondary domain.  Note that it should also be in the URL, adding this
    - *     won't cause it to be added to the URL.
    - * @param {boolean=} opt_noClose   Whether to request that the tcp/ip connection
    - *     should be closed.
    - * @param {boolean=} opt_duplicateRandom   Whether to duplicate the randomness
    - *     parameter which is only required for the initial handshake. This allows
    - *     a server to break compatibility with old version clients.
    - */
    -ChannelRequest.prototype.xmlHttpGet = function(uri, decodeChunks,
    -    hostPrefix, opt_noClose, opt_duplicateRandom) {
    -  this.type_ = ChannelRequest.Type_.XML_HTTP;
    -  this.baseUri_ = uri.clone().makeUnique();
    -  this.postData_ = null;
    -  this.decodeChunks_ = decodeChunks;
    -  if (opt_noClose) {
    -    this.sendClose_ = false;
    -  }
    -
    -  // TODO(user): clean this up once we phase out all BrowserChannel clients,
    -  if (opt_duplicateRandom) {
    -    var randomParam = this.baseUri_.getParameterValue(
    -        goog.uri.utils.StandardQueryParam.RANDOM);
    -    this.baseUri_.setParameterValue(  // baseUri_ reusable for future requests
    -        goog.uri.utils.StandardQueryParam.RANDOM + '1',  // 'zx1'
    -        randomParam);
    -  }
    -
    -  this.sendXmlHttp_(hostPrefix);
    -};
    -
    -
    -/**
    - * Sends a request via XMLHTTP according to the current state of the request
    - * object.
    - *
    - * @param {?string} hostPrefix The host prefix, if we might be using a secondary
    - *     domain.
    - * @private
    - */
    -ChannelRequest.prototype.sendXmlHttp_ = function(hostPrefix) {
    -  this.requestStartTime_ = goog.now();
    -  this.ensureWatchDogTimer_();
    -
    -  // clone the base URI to create the request URI. The request uri has the
    -  // attempt number as a parameter which helps in debugging.
    -  this.requestUri_ = this.baseUri_.clone();
    -  this.requestUri_.setParameterValues('t', this.retryId_);
    -
    -  // send the request either as a POST or GET
    -  this.xmlHttpChunkStart_ = 0;
    -  var useSecondaryDomains = this.channel_.shouldUseSecondaryDomains();
    -  this.xmlHttp_ = this.channel_.createXhrIo(useSecondaryDomains ?
    -      hostPrefix : null);
    -
    -  if (this.readyStateChangeThrottleMs_ > 0) {
    -    this.readyStateChangeThrottle_ = new goog.async.Throttle(
    -        goog.bind(this.xmlHttpHandler_, this, this.xmlHttp_),
    -        this.readyStateChangeThrottleMs_);
    -  }
    -
    -  this.eventHandler_.listen(this.xmlHttp_,
    -      goog.net.EventType.READY_STATE_CHANGE,
    -      this.readyStateChangeHandler_);
    -
    -  var headers = this.extraHeaders_ ? goog.object.clone(this.extraHeaders_) : {};
    -  if (this.postData_) {
    -    this.verb_ = 'POST';
    -    headers['Content-Type'] = 'application/x-www-form-urlencoded';
    -    this.xmlHttp_.send(this.requestUri_, this.verb_, this.postData_, headers);
    -  } else {
    -    this.verb_ = 'GET';
    -
    -    // If the user agent is webkit, we cannot send the close header since it is
    -    // disallowed by the browser.  If we attempt to set the "Connection: close"
    -    // header in WEBKIT browser, it will actually causes an error message.
    -    if (this.sendClose_ && !goog.userAgent.WEBKIT) {
    -      headers['Connection'] = 'close';
    -    }
    -    this.xmlHttp_.send(this.requestUri_, this.verb_, null, headers);
    -  }
    -  requestStats.notifyServerReachabilityEvent(
    -      requestStats.ServerReachability.REQUEST_MADE);
    -  this.channelDebug_.xmlHttpChannelRequest(this.verb_,
    -      this.requestUri_, this.rid_, this.retryId_,
    -      this.postData_);
    -};
    -
    -
    -/**
    - * Handles a readystatechange event.
    - * @param {goog.events.Event} evt The event.
    - * @private
    - */
    -ChannelRequest.prototype.readyStateChangeHandler_ = function(evt) {
    -  var xhr = /** @type {goog.net.XhrIo} */ (evt.target);
    -  var throttle = this.readyStateChangeThrottle_;
    -  if (throttle &&
    -      xhr.getReadyState() == goog.net.XmlHttp.ReadyState.INTERACTIVE) {
    -    // Only throttle in the partial data case.
    -    this.channelDebug_.debug('Throttling readystatechange.');
    -    throttle.fire();
    -  } else {
    -    // If we haven't throttled, just handle response directly.
    -    this.xmlHttpHandler_(xhr);
    -  }
    -};
    -
    -
    -/**
    - * XmlHttp handler
    - * @param {goog.net.XhrIo} xmlhttp The XhrIo object for the current request.
    - * @private
    - */
    -ChannelRequest.prototype.xmlHttpHandler_ = function(xmlhttp) {
    -  requestStats.onStartExecution();
    -
    -  /** @preserveTry */
    -  try {
    -    if (xmlhttp == this.xmlHttp_) {
    -      this.onXmlHttpReadyStateChanged_();
    -    } else {
    -      this.channelDebug_.warning('Called back with an ' +
    -                                     'unexpected xmlhttp');
    -    }
    -  } catch (ex) {
    -    this.channelDebug_.debug('Failed call to OnXmlHttpReadyStateChanged_');
    -    if (this.xmlHttp_ && this.xmlHttp_.getResponseText()) {
    -      this.channelDebug_.dumpException(ex,
    -          'ResponseText: ' + this.xmlHttp_.getResponseText());
    -    } else {
    -      this.channelDebug_.dumpException(ex, 'No response text');
    -    }
    -  } finally {
    -    requestStats.onEndExecution();
    -  }
    -};
    -
    -
    -/**
    - * Called by the readystate handler for XMLHTTP requests.
    - *
    - * @private
    - */
    -ChannelRequest.prototype.onXmlHttpReadyStateChanged_ = function() {
    -  var readyState = this.xmlHttp_.getReadyState();
    -  var errorCode = this.xmlHttp_.getLastErrorCode();
    -  var statusCode = this.xmlHttp_.getStatus();
    -
    -  // we get partial results in browsers that support ready state interactive.
    -  // We also make sure that getResponseText is not null in interactive mode
    -  // before we continue.  However, we don't do it in Opera because it only
    -  // fire readyState == INTERACTIVE once.  We need the following code to poll
    -  if (readyState < goog.net.XmlHttp.ReadyState.INTERACTIVE ||
    -      readyState == goog.net.XmlHttp.ReadyState.INTERACTIVE &&
    -      !goog.userAgent.OPERA && !this.xmlHttp_.getResponseText()) {
    -    // not yet ready
    -    return;
    -  }
    -
    -  // Dispatch any appropriate network events.
    -  if (!this.cancelled_ && readyState == goog.net.XmlHttp.ReadyState.COMPLETE &&
    -      errorCode != goog.net.ErrorCode.ABORT) {
    -
    -    // Pretty conservative, these are the only known scenarios which we'd
    -    // consider indicative of a truly non-functional network connection.
    -    if (errorCode == goog.net.ErrorCode.TIMEOUT ||
    -        statusCode <= 0) {
    -      requestStats.notifyServerReachabilityEvent(
    -          requestStats.ServerReachability.REQUEST_FAILED);
    -    } else {
    -      requestStats.notifyServerReachabilityEvent(
    -          requestStats.ServerReachability.REQUEST_SUCCEEDED);
    -    }
    -  }
    -
    -  // got some data so cancel the watchdog timer
    -  this.cancelWatchDogTimer_();
    -
    -  var status = this.xmlHttp_.getStatus();
    -  this.lastStatusCode_ = status;
    -  var responseText = this.xmlHttp_.getResponseText();
    -  if (!responseText) {
    -    this.channelDebug_.debug('No response text for uri ' +
    -        this.requestUri_ + ' status ' + status);
    -  }
    -  this.successful_ = (status == 200);
    -
    -  this.channelDebug_.xmlHttpChannelResponseMetaData(
    -      /** @type {string} */ (this.verb_),
    -      this.requestUri_, this.rid_, this.retryId_, readyState,
    -      status);
    -
    -  if (!this.successful_) {
    -    if (status == 400 &&
    -        responseText.indexOf('Unknown SID') > 0) {
    -      // the server error string will include 'Unknown SID' which indicates the
    -      // server doesn't know about the session (maybe it got restarted, maybe
    -      // the user got moved to another server, etc.,). Handlers can special
    -      // case this error
    -      this.lastError_ = ChannelRequest.Error.UNKNOWN_SESSION_ID;
    -      requestStats.notifyStatEvent(
    -          requestStats.Stat.REQUEST_UNKNOWN_SESSION_ID);
    -      this.channelDebug_.warning('XMLHTTP Unknown SID (' + this.rid_ + ')');
    -    } else {
    -      this.lastError_ = ChannelRequest.Error.STATUS;
    -      requestStats.notifyStatEvent(requestStats.Stat.REQUEST_BAD_STATUS);
    -      this.channelDebug_.warning(
    -          'XMLHTTP Bad status ' + status + ' (' + this.rid_ + ')');
    -    }
    -    this.cleanup_();
    -    this.dispatchFailure_();
    -    return;
    -  }
    -
    -  if (readyState == goog.net.XmlHttp.ReadyState.COMPLETE) {
    -    this.cleanup_();
    -  }
    -
    -  if (this.decodeChunks_) {
    -    this.decodeNextChunks_(readyState, responseText);
    -    if (goog.userAgent.OPERA && this.successful_ &&
    -        readyState == goog.net.XmlHttp.ReadyState.INTERACTIVE) {
    -      this.startPolling_();
    -    }
    -  } else {
    -    this.channelDebug_.xmlHttpChannelResponseText(
    -        this.rid_, responseText, null);
    -    this.safeOnRequestData_(responseText);
    -  }
    -
    -  if (!this.successful_) {
    -    return;
    -  }
    -
    -  if (!this.cancelled_) {
    -    if (readyState == goog.net.XmlHttp.ReadyState.COMPLETE) {
    -      this.channel_.onRequestComplete(this);
    -    } else {
    -      // The default is false, the result from this callback shouldn't carry
    -      // over to the next callback, otherwise the request looks successful if
    -      // the watchdog timer gets called
    -      this.successful_ = false;
    -      this.ensureWatchDogTimer_();
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Decodes the next set of available chunks in the response.
    - * @param {number} readyState The value of readyState.
    - * @param {string} responseText The value of responseText.
    - * @private
    - */
    -ChannelRequest.prototype.decodeNextChunks_ = function(readyState,
    -    responseText) {
    -  var decodeNextChunksSuccessful = true;
    -  while (!this.cancelled_ &&
    -         this.xmlHttpChunkStart_ < responseText.length) {
    -    var chunkText = this.getNextChunk_(responseText);
    -    if (chunkText == ChannelRequest.INCOMPLETE_CHUNK_) {
    -      if (readyState == goog.net.XmlHttp.ReadyState.COMPLETE) {
    -        // should have consumed entire response when the request is done
    -        this.lastError_ = ChannelRequest.Error.BAD_DATA;
    -        requestStats.notifyStatEvent(
    -            requestStats.Stat.REQUEST_INCOMPLETE_DATA);
    -        decodeNextChunksSuccessful = false;
    -      }
    -      this.channelDebug_.xmlHttpChannelResponseText(
    -          this.rid_, null, '[Incomplete Response]');
    -      break;
    -    } else if (chunkText == ChannelRequest.INVALID_CHUNK_) {
    -      this.lastError_ = ChannelRequest.Error.BAD_DATA;
    -      requestStats.notifyStatEvent(requestStats.Stat.REQUEST_BAD_DATA);
    -      this.channelDebug_.xmlHttpChannelResponseText(
    -          this.rid_, responseText, '[Invalid Chunk]');
    -      decodeNextChunksSuccessful = false;
    -      break;
    -    } else {
    -      this.channelDebug_.xmlHttpChannelResponseText(
    -          this.rid_, /** @type {string} */ (chunkText), null);
    -      this.safeOnRequestData_(/** @type {string} */ (chunkText));
    -    }
    -  }
    -  if (readyState == goog.net.XmlHttp.ReadyState.COMPLETE &&
    -      responseText.length == 0) {
    -    // also an error if we didn't get any response
    -    this.lastError_ = ChannelRequest.Error.NO_DATA;
    -    requestStats.notifyStatEvent(requestStats.Stat.REQUEST_NO_DATA);
    -    decodeNextChunksSuccessful = false;
    -  }
    -  this.successful_ = this.successful_ && decodeNextChunksSuccessful;
    -  if (!decodeNextChunksSuccessful) {
    -    // malformed response - we make this trigger retry logic
    -    this.channelDebug_.xmlHttpChannelResponseText(
    -        this.rid_, responseText, '[Invalid Chunked Response]');
    -    this.cleanup_();
    -    this.dispatchFailure_();
    -  }
    -};
    -
    -
    -/**
    - * Polls the response for new data.
    - * @private
    - */
    -ChannelRequest.prototype.pollResponse_ = function() {
    -  var readyState = this.xmlHttp_.getReadyState();
    -  var responseText = this.xmlHttp_.getResponseText();
    -  if (this.xmlHttpChunkStart_ < responseText.length) {
    -    this.cancelWatchDogTimer_();
    -    this.decodeNextChunks_(readyState, responseText);
    -    if (this.successful_ &&
    -        readyState != goog.net.XmlHttp.ReadyState.COMPLETE) {
    -      this.ensureWatchDogTimer_();
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Starts a polling interval for changes to responseText of the
    - * XMLHttpRequest, for browsers that don't fire onreadystatechange
    - * as data comes in incrementally.  This timer is disabled in
    - * cleanup_().
    - * @private
    - */
    -ChannelRequest.prototype.startPolling_ = function() {
    -  this.eventHandler_.listen(this.pollingTimer_, goog.Timer.TICK,
    -      this.pollResponse_);
    -  this.pollingTimer_.start();
    -};
    -
    -
    -/**
    - * Returns the next chunk of a chunk-encoded response. This is not standard
    - * HTTP chunked encoding because browsers don't expose the chunk boundaries to
    - * the application through XMLHTTP. So we have an additional chunk encoding at
    - * the application level that lets us tell where the beginning and end of
    - * individual responses are so that we can only try to eval a complete JS array.
    - *
    - * The encoding is the size of the chunk encoded as a decimal string followed
    - * by a newline followed by the data.
    - *
    - * @param {string} responseText The response text from the XMLHTTP response.
    - * @return {string|Object} The next chunk string or a sentinel object
    - *                         indicating a special condition.
    - * @private
    - */
    -ChannelRequest.prototype.getNextChunk_ = function(responseText) {
    -  var sizeStartIndex = this.xmlHttpChunkStart_;
    -  var sizeEndIndex = responseText.indexOf('\n', sizeStartIndex);
    -  if (sizeEndIndex == -1) {
    -    return ChannelRequest.INCOMPLETE_CHUNK_;
    -  }
    -
    -  var sizeAsString = responseText.substring(sizeStartIndex, sizeEndIndex);
    -  var size = Number(sizeAsString);
    -  if (isNaN(size)) {
    -    return ChannelRequest.INVALID_CHUNK_;
    -  }
    -
    -  var chunkStartIndex = sizeEndIndex + 1;
    -  if (chunkStartIndex + size > responseText.length) {
    -    return ChannelRequest.INCOMPLETE_CHUNK_;
    -  }
    -
    -  var chunkText = responseText.substr(chunkStartIndex, size);
    -  this.xmlHttpChunkStart_ = chunkStartIndex + size;
    -  return chunkText;
    -};
    -
    -
    -/**
    - * Uses an IMG tag to send an HTTP get to the server. This is only currently
    - * used to terminate the connection, as an IMG tag is the most reliable way to
    - * send something to the server while the page is getting torn down.
    - * @param {goog.Uri} uri The uri to send a request to.
    - */
    -ChannelRequest.prototype.sendUsingImgTag = function(uri) {
    -  this.type_ = ChannelRequest.Type_.IMG;
    -  this.baseUri_ = uri.clone().makeUnique();
    -  this.imgTagGet_();
    -};
    -
    -
    -/**
    - * Starts the IMG request.
    - *
    - * @private
    - */
    -ChannelRequest.prototype.imgTagGet_ = function() {
    -  var eltImg = new Image();
    -  eltImg.src = this.baseUri_;
    -  this.requestStartTime_ = goog.now();
    -  this.ensureWatchDogTimer_();
    -};
    -
    -
    -/**
    - * Cancels the request no matter what the underlying transport is.
    - */
    -ChannelRequest.prototype.cancel = function() {
    -  this.cancelled_ = true;
    -  this.cleanup_();
    -};
    -
    -
    -/**
    - * Ensures that there is watchdog timeout which is used to ensure that
    - * the connection completes in time.
    - *
    - * @private
    - */
    -ChannelRequest.prototype.ensureWatchDogTimer_ = function() {
    -  this.watchDogTimeoutTime_ = goog.now() + this.timeout_;
    -  this.startWatchDogTimer_(this.timeout_);
    -};
    -
    -
    -/**
    - * Starts the watchdog timer which is used to ensure that the connection
    - * completes in time.
    - * @param {number} time The number of milliseconds to wait.
    - * @private
    - */
    -ChannelRequest.prototype.startWatchDogTimer_ = function(time) {
    -  if (this.watchDogTimerId_ != null) {
    -    // assertion
    -    throw Error('WatchDog timer not null');
    -  }
    -  this.watchDogTimerId_ = requestStats.setTimeout(
    -      goog.bind(this.onWatchDogTimeout_, this), time);
    -};
    -
    -
    -/**
    - * Cancels the watchdog timer if it has been started.
    - *
    - * @private
    - */
    -ChannelRequest.prototype.cancelWatchDogTimer_ = function() {
    -  if (this.watchDogTimerId_) {
    -    goog.global.clearTimeout(this.watchDogTimerId_);
    -    this.watchDogTimerId_ = null;
    -  }
    -};
    -
    -
    -/**
    - * Called when the watchdog timer is triggered. It also handles a case where it
    - * is called too early which we suspect may be happening sometimes
    - * (not sure why)
    - *
    - * @private
    - */
    -ChannelRequest.prototype.onWatchDogTimeout_ = function() {
    -  this.watchDogTimerId_ = null;
    -  var now = goog.now();
    -  if (now - this.watchDogTimeoutTime_ >= 0) {
    -    this.handleTimeout_();
    -  } else {
    -    // got called too early for some reason
    -    this.channelDebug_.warning('WatchDog timer called too early');
    -    this.startWatchDogTimer_(this.watchDogTimeoutTime_ - now);
    -  }
    -};
    -
    -
    -/**
    - * Called when the request has actually timed out. Will cleanup and notify the
    - * channel of the failure.
    - *
    - * @private
    - */
    -ChannelRequest.prototype.handleTimeout_ = function() {
    -  if (this.successful_) {
    -    // Should never happen.
    -    this.channelDebug_.severe(
    -        'Received watchdog timeout even though request loaded successfully');
    -  }
    -
    -  this.channelDebug_.timeoutResponse(this.requestUri_);
    -  // IMG requests never notice if they were successful, and always 'time out'.
    -  // This fact says nothing about reachability.
    -  if (this.type_ != ChannelRequest.Type_.IMG) {
    -    requestStats.notifyServerReachabilityEvent(
    -        requestStats.ServerReachability.REQUEST_FAILED);
    -  }
    -  this.cleanup_();
    -
    -  // set error and dispatch failure
    -  this.lastError_ = ChannelRequest.Error.TIMEOUT;
    -  requestStats.notifyStatEvent(requestStats.Stat.REQUEST_TIMEOUT);
    -  this.dispatchFailure_();
    -};
    -
    -
    -/**
    - * Notifies the channel that this request failed.
    - * @private
    - */
    -ChannelRequest.prototype.dispatchFailure_ = function() {
    -  if (this.channel_.isClosed() || this.cancelled_) {
    -    return;
    -  }
    -
    -  this.channel_.onRequestComplete(this);
    -};
    -
    -
    -/**
    - * Cleans up the objects used to make the request. This function is
    - * idempotent.
    - *
    - * @private
    - */
    -ChannelRequest.prototype.cleanup_ = function() {
    -  this.cancelWatchDogTimer_();
    -
    -  goog.dispose(this.readyStateChangeThrottle_);
    -  this.readyStateChangeThrottle_ = null;
    -
    -  // Stop the polling timer, if necessary.
    -  this.pollingTimer_.stop();
    -
    -  // Unhook all event handlers.
    -  this.eventHandler_.removeAll();
    -
    -  if (this.xmlHttp_) {
    -    // clear out this.xmlHttp_ before aborting so we handle getting reentered
    -    // inside abort
    -    var xmlhttp = this.xmlHttp_;
    -    this.xmlHttp_ = null;
    -    xmlhttp.abort();
    -    xmlhttp.dispose();
    -  }
    -};
    -
    -
    -/**
    - * Indicates whether the request was successful. Only valid after the handler
    - * is called to indicate completion of the request.
    - *
    - * @return {boolean} True if the request succeeded.
    - */
    -ChannelRequest.prototype.getSuccess = function() {
    -  return this.successful_;
    -};
    -
    -
    -/**
    - * If the request was not successful, returns the reason.
    - *
    - * @return {?ChannelRequest.Error}  The last error.
    - */
    -ChannelRequest.prototype.getLastError = function() {
    -  return this.lastError_;
    -};
    -
    -
    -/**
    - * Returns the status code of the last request.
    - * @return {number} The status code of the last request.
    - */
    -ChannelRequest.prototype.getLastStatusCode = function() {
    -  return this.lastStatusCode_;
    -};
    -
    -
    -/**
    - * Returns the session id for this channel.
    - *
    - * @return {string|undefined} The session ID.
    - */
    -ChannelRequest.prototype.getSessionId = function() {
    -  return this.sid_;
    -};
    -
    -
    -/**
    - * Returns the request id for this request. Each request has a unique request
    - * id and the request IDs are a sequential increasing count.
    - *
    - * @return {string|number|undefined} The request ID.
    - */
    -ChannelRequest.prototype.getRequestId = function() {
    -  return this.rid_;
    -};
    -
    -
    -/**
    - * Returns the data for a post, if this request is a post.
    - *
    - * @return {?string} The POST data provided by the request initiator.
    - */
    -ChannelRequest.prototype.getPostData = function() {
    -  return this.postData_;
    -};
    -
    -
    -/**
    - * Returns the XhrIo request object.
    - *
    - * @return {?goog.net.XhrIo} Any XhrIo request created for this object.
    - */
    -ChannelRequest.prototype.getXhr = function() {
    -  return this.xmlHttp_;
    -};
    -
    -
    -/**
    - * Returns the time that the request started, if it has started.
    - *
    - * @return {?number} The time the request started, as returned by goog.now().
    - */
    -ChannelRequest.prototype.getRequestStartTime = function() {
    -  return this.requestStartTime_;
    -};
    -
    -
    -/**
    - * Helper to call the callback's onRequestData, which catches any
    - * exception and cleans up the request.
    - * @param {string} data The request data.
    - * @private
    - */
    -ChannelRequest.prototype.safeOnRequestData_ = function(data) {
    -  /** @preserveTry */
    -  try {
    -    this.channel_.onRequestData(this, data);
    -    var stats = requestStats.ServerReachability;
    -    requestStats.notifyServerReachabilityEvent(stats.BACK_CHANNEL_ACTIVITY);
    -  } catch (e) {
    -    // Dump debug info, but keep going without closing the channel.
    -    this.channelDebug_.dumpException(
    -        e, 'Error in httprequest callback');
    -  }
    -};
    -
    -
    -/**
    - * Convenience factory method.
    - *
    - * @param {Channel} channel The channel object that owns this request.
    - * @param {WebChannelDebug} channelDebug A WebChannelDebug to use for logging.
    - * @param {string=} opt_sessionId  The session id for the channel.
    - * @param {string|number=} opt_requestId  The request id for this request.
    - * @param {number=} opt_retryId  The retry id for this request.
    - * @return {!ChannelRequest} The created channel request.
    - */
    -ChannelRequest.createChannelRequest = function(channel, channelDebug,
    -    opt_sessionId, opt_requestId, opt_retryId) {
    -  return new ChannelRequest(channel, channelDebug, opt_sessionId, opt_requestId,
    -      opt_retryId);
    -};
    -});  // goog.scope
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/channelrequest_test.html b/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/channelrequest_test.html
    deleted file mode 100644
    index bf08e98dec8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/channelrequest_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.labs.net.webChannel.ChannelRequest</title>
    -<script src="../../../base.js"></script>
    -</head>
    -<body>
    -<script>
    -goog.require('goog.labs.net.webChannel.channelRequestTest');
    -</script>
    -<div id="debug" style="font-size: small"></div>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/channelrequest_test.js b/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/channelrequest_test.js
    deleted file mode 100644
    index 8d31c8eec5d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/channelrequest_test.js
    +++ /dev/null
    @@ -1,300 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.labs.net.webChannel.ChannelRequest.
    - *
    - */
    -
    -
    -goog.provide('goog.labs.net.webChannel.channelRequestTest');
    -
    -goog.require('goog.Uri');
    -goog.require('goog.functions');
    -goog.require('goog.labs.net.webChannel.ChannelRequest');
    -goog.require('goog.labs.net.webChannel.WebChannelDebug');
    -goog.require('goog.labs.net.webChannel.requestStats');
    -goog.require('goog.labs.net.webChannel.requestStats.ServerReachability');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.net.XhrIo');
    -goog.require('goog.testing.recordFunction');
    -
    -goog.setTestOnly('goog.labs.net.webChannel.channelRequestTest');
    -
    -
    -var channelRequest;
    -var mockChannel;
    -var mockClock;
    -var stubs;
    -var xhrIo;
    -var reachabilityEvents;
    -
    -
    -/**
    - * Time to wait for a network request to time out, before aborting.
    - */
    -var WATCHDOG_TIME = 2000;
    -
    -
    -/**
    - * Time to throttle readystatechange events.
    - */
    -var THROTTLE_TIME = 500;
    -
    -
    -/**
    - * A really long time - used to make sure no more timeouts will fire.
    - */
    -var ALL_DAY_MS = 1000 * 60 * 60 * 24;
    -
    -
    -function shouldRunTests() {
    -  return goog.labs.net.webChannel.ChannelRequest.supportsXhrStreaming();
    -}
    -
    -
    -function setUp() {
    -  mockClock = new goog.testing.MockClock();
    -  mockClock.install();
    -  reachabilityEvents = {};
    -  stubs = new goog.testing.PropertyReplacer();
    -
    -  // Mock out the stat notification code.
    -  var notifyServerReachabilityEvent = function(reachabilityType) {
    -    if (!reachabilityEvents[reachabilityType]) {
    -      reachabilityEvents[reachabilityType] = 0;
    -    }
    -    reachabilityEvents[reachabilityType]++;
    -  };
    -  stubs.set(goog.labs.net.webChannel.requestStats,
    -      'notifyServerReachabilityEvent', notifyServerReachabilityEvent);
    -}
    -
    -
    -function tearDown() {
    -  stubs.reset();
    -  mockClock.uninstall();
    -}
    -
    -
    -
    -/**
    - * Constructs a duck-type WebChannelBase that tracks the completed requests.
    - * @constructor
    - * @struct
    - * @final
    - */
    -function MockWebChannelBase() {
    -  this.isClosed = function() {
    -    return false;
    -  };
    -  this.isActive = function() {
    -    return true;
    -  };
    -  this.shouldUseSecondaryDomains = function() {
    -    return false;
    -  };
    -  this.completedRequests = [];
    -  this.onRequestComplete = function(request) {
    -    this.completedRequests.push(request);
    -  };
    -  this.onRequestData = function(request, data) {};
    -}
    -
    -
    -/**
    - * Creates a real ChannelRequest object, with some modifications for
    - * testability:
    - * <ul>
    - * <li>The channel is a mock channel.
    - * <li>The new watchdogTimeoutCallCount property tracks onWatchDogTimeout_()
    - *     calls.
    - * <li>The timeout is set to WATCHDOG_TIME.
    - * </ul>
    - */
    -function createChannelRequest() {
    -  xhrIo = new goog.testing.net.XhrIo();
    -  xhrIo.abort = xhrIo.abort || function() {
    -    this.active_ = false;
    -  };
    -
    -  // Install mock channel and no-op debug logger.
    -  mockChannel = new MockWebChannelBase();
    -  channelRequest = new goog.labs.net.webChannel.ChannelRequest(
    -      mockChannel,
    -      new goog.labs.net.webChannel.WebChannelDebug());
    -
    -  // Install test XhrIo.
    -  mockChannel.createXhrIo = function() {
    -    return xhrIo;
    -  };
    -
    -  // Install watchdogTimeoutCallCount.
    -  channelRequest.watchdogTimeoutCallCount = 0;
    -  channelRequest.originalOnWatchDogTimeout = channelRequest.onWatchDogTimeout_;
    -  channelRequest.onWatchDogTimeout_ = function() {
    -    channelRequest.watchdogTimeoutCallCount++;
    -    return channelRequest.originalOnWatchDogTimeout();
    -  };
    -
    -  channelRequest.setTimeout(WATCHDOG_TIME);
    -}
    -
    -
    -/**
    - * Run through the lifecycle of a long lived request, checking that the right
    - * network events are reported.
    - */
    -function testNetworkEvents() {
    -  createChannelRequest();
    -
    -  channelRequest.xmlHttpPost(new goog.Uri('some_uri'), 'some_postdata', true);
    -  checkReachabilityEvents(1, 0, 0, 0);
    -  if (goog.labs.net.webChannel.ChannelRequest.supportsXhrStreaming()) {
    -    xhrIo.simulatePartialResponse('17\nI am a BC Message');
    -    checkReachabilityEvents(1, 0, 0, 1);
    -    xhrIo.simulatePartialResponse('23\nI am another BC Message');
    -    checkReachabilityEvents(1, 0, 0, 2);
    -    xhrIo.simulateResponse(200, '16\Final BC Message');
    -    checkReachabilityEvents(1, 1, 0, 2);
    -  } else {
    -    xhrIo.simulateResponse(200, '16\Final BC Message');
    -    checkReachabilityEvents(1, 1, 0, 0);
    -  }
    -}
    -
    -
    -/**
    - * Test throttling of readystatechange events.
    - */
    -function testNetworkEvents_throttleReadyStateChange() {
    -  createChannelRequest();
    -  channelRequest.setReadyStateChangeThrottle(THROTTLE_TIME);
    -
    -  var recordedHandler =
    -      goog.testing.recordFunction(channelRequest.xmlHttpHandler_);
    -  stubs.set(channelRequest, 'xmlHttpHandler_', recordedHandler);
    -
    -  channelRequest.xmlHttpPost(new goog.Uri('some_uri'), 'some_postdata', true);
    -  assertEquals(1, recordedHandler.getCallCount());
    -
    -  checkReachabilityEvents(1, 0, 0, 0);
    -  if (goog.labs.net.webChannel.ChannelRequest.supportsXhrStreaming()) {
    -    xhrIo.simulatePartialResponse('17\nI am a BC Message');
    -    checkReachabilityEvents(1, 0, 0, 1);
    -    assertEquals(3, recordedHandler.getCallCount());
    -
    -    // Second event should be throttled
    -    xhrIo.simulatePartialResponse('23\nI am another BC Message');
    -    assertEquals(3, recordedHandler.getCallCount());
    -
    -    xhrIo.simulatePartialResponse('27\nI am yet another BC Message');
    -    assertEquals(3, recordedHandler.getCallCount());
    -    mockClock.tick(THROTTLE_TIME);
    -
    -    checkReachabilityEvents(1, 0, 0, 3);
    -    // Only one more call because of throttling.
    -    assertEquals(4, recordedHandler.getCallCount());
    -
    -    xhrIo.simulateResponse(200, '16\Final BC Message');
    -    checkReachabilityEvents(1, 1, 0, 3);
    -    assertEquals(5, recordedHandler.getCallCount());
    -  } else {
    -    xhrIo.simulateResponse(200, '16\Final BC Message');
    -    checkReachabilityEvents(1, 1, 0, 0);
    -  }
    -}
    -
    -
    -/**
    - * Make sure that the request "completes" with an error when the timeout
    - * expires.
    - */
    -function testRequestTimeout() {
    -  createChannelRequest();
    -
    -  channelRequest.xmlHttpPost(new goog.Uri('some_uri'), 'some_postdata', true);
    -  assertEquals(0, channelRequest.watchdogTimeoutCallCount);
    -  assertEquals(0, channelRequest.channel_.completedRequests.length);
    -
    -  // Watchdog timeout.
    -  mockClock.tick(WATCHDOG_TIME);
    -  assertEquals(1, channelRequest.watchdogTimeoutCallCount);
    -  assertEquals(1, channelRequest.channel_.completedRequests.length);
    -  assertFalse(channelRequest.getSuccess());
    -
    -  // Make sure no more timers are firing.
    -  mockClock.tick(ALL_DAY_MS);
    -  assertEquals(1, channelRequest.watchdogTimeoutCallCount);
    -  assertEquals(1, channelRequest.channel_.completedRequests.length);
    -
    -  checkReachabilityEvents(1, 0, 1, 0);
    -}
    -
    -
    -function testRequestTimeoutWithUnexpectedException() {
    -  createChannelRequest();
    -  channelRequest.channel_.createXhrIo = goog.functions.error('Weird error');
    -
    -  try {
    -    channelRequest.xmlHttpGet(new goog.Uri('some_uri'), true, null);
    -    fail('Expected error');
    -  } catch (e) {
    -    assertEquals('Weird error', e.message);
    -  }
    -
    -  assertEquals(0, channelRequest.watchdogTimeoutCallCount);
    -  assertEquals(0, channelRequest.channel_.completedRequests.length);
    -
    -  // Watchdog timeout.
    -  mockClock.tick(WATCHDOG_TIME);
    -  assertEquals(1, channelRequest.watchdogTimeoutCallCount);
    -  assertEquals(1, channelRequest.channel_.completedRequests.length);
    -  assertFalse(channelRequest.getSuccess());
    -
    -  // Make sure no more timers are firing.
    -  mockClock.tick(ALL_DAY_MS);
    -  assertEquals(1, channelRequest.watchdogTimeoutCallCount);
    -  assertEquals(1, channelRequest.channel_.completedRequests.length);
    -
    -  checkReachabilityEvents(0, 0, 1, 0);
    -}
    -
    -
    -function checkReachabilityEvents(reqMade, reqSucceeded, reqFail, backChannel) {
    -  var Reachability =
    -      goog.labs.net.webChannel.requestStats.ServerReachability;
    -  assertEquals(reqMade,
    -      reachabilityEvents[Reachability.REQUEST_MADE] || 0);
    -  assertEquals(reqSucceeded,
    -      reachabilityEvents[Reachability.REQUEST_SUCCEEDED] || 0);
    -  assertEquals(reqFail,
    -      reachabilityEvents[Reachability.REQUEST_FAILED] || 0);
    -  assertEquals(backChannel,
    -      reachabilityEvents[Reachability.BACK_CHANNEL_ACTIVITY] || 0);
    -}
    -
    -
    -function testDuplicatedRandomParams() {
    -  createChannelRequest();
    -  channelRequest.xmlHttpGet(new goog.Uri('some_uri'), true, null, true,
    -      true /* opt_duplicateRandom */);
    -  var z = xhrIo.getLastUri().getParameterValue('zx');
    -  var z1 = xhrIo.getLastUri().getParameterValue('zx1');
    -  assertTrue(goog.isDefAndNotNull(z));
    -  assertTrue(goog.isDefAndNotNull(z1));
    -  assertEquals(z1, z);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/connectionstate.js b/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/connectionstate.js
    deleted file mode 100644
    index 10a43bdf233..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/connectionstate.js
    +++ /dev/null
    @@ -1,50 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview This class manages the network connectivity state.
    - *
    - * Some of the connectivity state may be exposed to the client code in future,
    - * e.g. the initial handshake state, in order to save one RTT when a channel
    - * has to be reestablished. TODO(user).
    - *
    - * @visibility {:internal}
    - */
    -
    -
    -goog.provide('goog.labs.net.webChannel.ConnectionState');
    -
    -
    -
    -/**
    - * The connectivity state of the channel.
    - *
    - * @constructor
    - * @struct
    - */
    -goog.labs.net.webChannel.ConnectionState = function() {
    -  /**
    -   * Handshake result.
    -   * @type {Array<string>}
    -   */
    -  this.handshakeResult = null;
    -
    -  /**
    -   * The result of checking if there is a buffering proxy in the network.
    -   * True means the connection is buffered, False means unbuffered,
    -   * null means that the result is not available.
    -   * @type {?boolean}
    -   */
    -  this.bufferingProxyResult = null;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/forwardchannelrequestpool.js b/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/forwardchannelrequestpool.js
    deleted file mode 100644
    index 22f3d916532..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/forwardchannelrequestpool.js
    +++ /dev/null
    @@ -1,279 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A pool of forward channel requests to enable real-time
    - * messaging from the client to server.
    - *
    - * @visibility {:internal}
    - */
    -
    -
    -goog.provide('goog.labs.net.webChannel.ForwardChannelRequestPool');
    -
    -goog.require('goog.array');
    -goog.require('goog.string');
    -goog.require('goog.structs.Set');
    -
    -goog.scope(function() {
    -// type checking only (no require)
    -var ChannelRequest = goog.labs.net.webChannel.ChannelRequest;
    -
    -
    -
    -/**
    - * This class represents the state of all forward channel requests.
    - *
    - * @param {number=} opt_maxPoolSize The maximum pool size.
    - *
    - * @constructor
    - * @final
    - */
    -goog.labs.net.webChannel.ForwardChannelRequestPool = function(opt_maxPoolSize) {
    -  /**
    -   * THe max pool size as configured.
    -   *
    -   * @private {number}
    -   */
    -  this.maxPoolSizeConfigured_ = opt_maxPoolSize ||
    -          goog.labs.net.webChannel.ForwardChannelRequestPool.MAX_POOL_SIZE_;
    -
    -  /**
    -   * The current size limit of the request pool. This limit is meant to be
    -   * read-only after the channel is fully opened.
    -   *
    -   * If SPDY is enabled, set it to the max pool size, which is also
    -   * configurable.
    -   *
    -   * @private {number}
    -   */
    -  this.maxSize_ = ForwardChannelRequestPool.isSpdyEnabled_() ?
    -      this.maxPoolSizeConfigured_ : 1;
    -
    -  /**
    -   * The container for all the pending request objects.
    -   *
    -   * @private {goog.structs.Set<ChannelRequest>}
    -   */
    -  this.requestPool_ = null;
    -
    -  if (this.maxSize_ > 1) {
    -    this.requestPool_ = new goog.structs.Set();
    -  }
    -
    -  /**
    -   * The single request object when the pool size is limited to one.
    -   *
    -   * @private {ChannelRequest}
    -   */
    -  this.request_ = null;
    -};
    -
    -var ForwardChannelRequestPool =
    -    goog.labs.net.webChannel.ForwardChannelRequestPool;
    -
    -
    -/**
    - * The default size limit of the request pool.
    - *
    - * @private {number}
    - */
    -ForwardChannelRequestPool.MAX_POOL_SIZE_ = 10;
    -
    -
    -/**
    - * @return {boolean} True if SPDY is enabled for the current page using
    - *     chrome specific APIs.
    - * @private
    - */
    -ForwardChannelRequestPool.isSpdyEnabled_ = function() {
    -  return !!(goog.global.chrome && goog.global.chrome.loadTimes &&
    -      goog.global.chrome.loadTimes() &&
    -      goog.global.chrome.loadTimes().wasFetchedViaSpdy);
    -};
    -
    -
    -/**
    - * Once we know the client protocol (from the handshake), check if we need
    - * enable the request pool accordingly. This is more robust than using
    - * browser-internal APIs (specific to Chrome).
    - *
    - * @param {string} clientProtocol The client protocol
    - */
    -ForwardChannelRequestPool.prototype.applyClientProtocol = function(
    -    clientProtocol) {
    -  if (this.requestPool_) {
    -    return;
    -  }
    -
    -  if (goog.string.contains(clientProtocol, 'spdy') ||
    -      goog.string.contains(clientProtocol, 'quic')) {
    -    this.maxSize_ = this.maxPoolSizeConfigured_;
    -    this.requestPool_ = new goog.structs.Set();
    -    if (this.request_) {
    -      this.addRequest(this.request_);
    -      this.request_ = null;
    -    }
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} True if the pool is full.
    - */
    -ForwardChannelRequestPool.prototype.isFull = function() {
    -  if (this.request_) {
    -    return true;
    -  }
    -
    -  if (this.requestPool_) {
    -    return this.requestPool_.getCount() >= this.maxSize_;
    -  }
    -
    -  return false;
    -};
    -
    -
    -/**
    - * @return {number} The current size limit.
    - */
    -ForwardChannelRequestPool.prototype.getMaxSize = function() {
    -  return this.maxSize_;
    -};
    -
    -
    -/**
    - * @return {number} The number of pending requests in the pool.
    - */
    -ForwardChannelRequestPool.prototype.getRequestCount = function() {
    -  if (this.request_) {
    -    return 1;
    -  }
    -
    -  if (this.requestPool_) {
    -    return this.requestPool_.getCount();
    -  }
    -
    -  return 0;
    -};
    -
    -
    -/**
    - * @param {ChannelRequest} req The channel request.
    - * @return {boolean} True if the request is a included inside the pool.
    - */
    -ForwardChannelRequestPool.prototype.hasRequest = function(req) {
    -  if (this.request_) {
    -    return this.request_ == req;
    -  }
    -
    -  if (this.requestPool_) {
    -    return this.requestPool_.contains(req);
    -  }
    -
    -  return false;
    -};
    -
    -
    -/**
    - * Adds a new request to the pool.
    - *
    - * @param {!ChannelRequest} req The new channel request.
    - */
    -ForwardChannelRequestPool.prototype.addRequest = function(req) {
    -  if (this.requestPool_) {
    -    this.requestPool_.add(req);
    -  } else {
    -    this.request_ = req;
    -  }
    -};
    -
    -
    -/**
    - * Removes the given request from the pool.
    - *
    - * @param {ChannelRequest} req The channel request.
    - * @return {boolean} Whether the request has been removed from the pool.
    - */
    -ForwardChannelRequestPool.prototype.removeRequest = function(req) {
    -  if (this.request_ && this.request_ == req) {
    -    this.request_ = null;
    -    return true;
    -  }
    -
    -  if (this.requestPool_ && this.requestPool_.contains(req)) {
    -    this.requestPool_.remove(req);
    -    return true;
    -  }
    -
    -  return false;
    -};
    -
    -
    -/**
    - * Clears the pool and cancel all the pending requests.
    - */
    -ForwardChannelRequestPool.prototype.cancel = function() {
    -  if (this.request_) {
    -    this.request_.cancel();
    -    this.request_ = null;
    -    return;
    -  }
    -
    -  if (this.requestPool_ && !this.requestPool_.isEmpty()) {
    -    goog.array.forEach(this.requestPool_.getValues(), function(val) {
    -      val.cancel();
    -    });
    -    this.requestPool_.clear();
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} Whether there are any pending requests.
    - */
    -ForwardChannelRequestPool.prototype.hasPendingRequest = function() {
    -  return (this.request_ != null) ||
    -      (this.requestPool_ != null && !this.requestPool_.isEmpty());
    -};
    -
    -
    -/**
    - * Cancels all pending requests and force the completion of channel requests.
    - *
    - * Need go through the standard onRequestComplete logic to expose the max-retry
    - * failure in the standard way.
    - *
    - * @param {!function(!ChannelRequest)} onComplete The completion callback.
    - * @return {boolean} true if any request has been forced to complete.
    - */
    -ForwardChannelRequestPool.prototype.forceComplete = function(onComplete) {
    -  if (this.request_ != null) {
    -    this.request_.cancel();
    -    onComplete(this.request_);
    -    return true;
    -  }
    -
    -  if (this.requestPool_ && !this.requestPool_.isEmpty()) {
    -    goog.array.forEach(this.requestPool_.getValues(),
    -        function(val) {
    -          val.cancel();
    -          onComplete(val);
    -        });
    -    return true;
    -  }
    -
    -  return false;
    -};
    -});  // goog.scope
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/forwardchannelrequestpool_test.html b/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/forwardchannelrequestpool_test.html
    deleted file mode 100644
    index 04a6dced45b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/forwardchannelrequestpool_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.labs.net.webChannel.ForwardChannelRequestPool</title>
    -<script src="../../../base.js"></script>
    -</head>
    -<body>
    -<script>
    -goog.require('goog.labs.net.webChannel.forwardChannelRequestPoolTest');
    -</script>
    -<div id="debug" style="font-size: small"></div>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/forwardchannelrequestpool_test.js b/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/forwardchannelrequestpool_test.js
    deleted file mode 100644
    index e2a207e7a12..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/forwardchannelrequestpool_test.js
    +++ /dev/null
    @@ -1,124 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for
    - * goog.labs.net.webChannel.ForwardChannelRequestPool.
    - * @suppress {accessControls} Private methods are accessed for test purposes.
    - *
    - */
    -
    -
    -goog.provide('goog.labs.net.webChannel.forwardChannelRequestPoolTest');
    -
    -goog.require('goog.labs.net.webChannel.ChannelRequest');
    -goog.require('goog.labs.net.webChannel.ForwardChannelRequestPool');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.asserts');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.labs.net.webChannel.forwardChannelRequestPoolTest');
    -
    -
    -var propertyReplacer = new goog.testing.PropertyReplacer();
    -var req = new goog.labs.net.webChannel.ChannelRequest(null, null);
    -
    -
    -function shouldRunTests() {
    -  return goog.labs.net.webChannel.ChannelRequest.supportsXhrStreaming();
    -}
    -
    -
    -function setUp() {
    -}
    -
    -
    -function tearDown() {
    -  propertyReplacer.reset();
    -}
    -
    -
    -function stubSpdyCheck(spdyEnabled) {
    -  propertyReplacer.set(goog.labs.net.webChannel.ForwardChannelRequestPool,
    -      'isSpdyEnabled_',
    -      function() {
    -        return spdyEnabled;
    -      });
    -}
    -
    -
    -function testSpdyEnabled() {
    -  stubSpdyCheck(true);
    -
    -  var pool = new goog.labs.net.webChannel.ForwardChannelRequestPool();
    -  assertFalse(pool.isFull());
    -  assertEquals(0, pool.getRequestCount());
    -  pool.addRequest(req);
    -  assertTrue(pool.hasPendingRequest());
    -  assertTrue(pool.hasRequest(req));
    -  pool.removeRequest(req);
    -  assertFalse(pool.hasPendingRequest());
    -
    -  for (var i = 0; i < pool.getMaxSize(); i++) {
    -    pool.addRequest(new goog.labs.net.webChannel.ChannelRequest(null, null));
    -  }
    -  assertTrue(pool.isFull());
    -
    -  // do not fail
    -  pool.addRequest(req);
    -  assertTrue(pool.isFull());
    -}
    -
    -
    -function testSpdyNotEnabled() {
    -  stubSpdyCheck(false);
    -
    -  var pool = new goog.labs.net.webChannel.ForwardChannelRequestPool();
    -  assertFalse(pool.isFull());
    -  assertEquals(0, pool.getRequestCount());
    -  pool.addRequest(req);
    -  assertTrue(pool.hasPendingRequest());
    -  assertTrue(pool.hasRequest(req));
    -  assertTrue(pool.isFull());
    -  pool.removeRequest(req);
    -  assertFalse(pool.hasPendingRequest());
    -
    -  // do not fail
    -  pool.addRequest(req);
    -  assertTrue(pool.isFull());
    -}
    -
    -
    -function testApplyClientProtocol() {
    -  stubSpdyCheck(false);
    -
    -  var pool = new goog.labs.net.webChannel.ForwardChannelRequestPool();
    -  assertEquals(1, pool.getMaxSize());
    -  pool.applyClientProtocol('spdy/3');
    -  assertTrue(pool.getMaxSize() > 1);
    -  pool.applyClientProtocol('foo-bar');   // no effect
    -  assertTrue(pool.getMaxSize() > 1);
    -
    -  pool = new goog.labs.net.webChannel.ForwardChannelRequestPool();
    -  assertEquals(1, pool.getMaxSize());
    -  pool.applyClientProtocol('quic/x');
    -  assertTrue(pool.getMaxSize() > 1);
    -
    -  stubSpdyCheck(true);
    -
    -  pool = new goog.labs.net.webChannel.ForwardChannelRequestPool();
    -  assertTrue(pool.getMaxSize() > 1);
    -  pool.applyClientProtocol('foo/3');  // no effect
    -  assertTrue(pool.getMaxSize() > 1);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/netutils.js b/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/netutils.js
    deleted file mode 100644
    index 5b9d7fba682..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/netutils.js
    +++ /dev/null
    @@ -1,162 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Utility functions for managing networking, such as
    - * testing network connectivity.
    - *
    - * @visibility {:internal}
    - */
    -
    -
    -goog.provide('goog.labs.net.webChannel.netUtils');
    -
    -goog.require('goog.Uri');
    -goog.require('goog.labs.net.webChannel.WebChannelDebug');
    -
    -goog.scope(function() {
    -var netUtils = goog.labs.net.webChannel.netUtils;
    -var WebChannelDebug = goog.labs.net.webChannel.WebChannelDebug;
    -
    -
    -/**
    - * Default timeout to allow for URI pings.
    - * @type {number}
    - */
    -netUtils.NETWORK_TIMEOUT = 10000;
    -
    -
    -/**
    - * Pings the network with an image URI to check if an error is a server error
    - * or user's network error.
    - *
    - * The caller needs to add a 'rand' parameter to make sure the response is
    - * not fulfilled by browser cache.
    - *
    - * @param {function(boolean)} callback The function to call back with results.
    - * @param {goog.Uri=} opt_imageUri The URI (of an image) to use for the network
    - *     test.
    - */
    -netUtils.testNetwork = function(callback, opt_imageUri) {
    -  var uri = opt_imageUri;
    -  if (!uri) {
    -    // default google.com image
    -    uri = new goog.Uri('//www.google.com/images/cleardot.gif');
    -
    -    if (!(goog.global.location && goog.global.location.protocol == 'http')) {
    -      uri.setScheme('https');  // e.g. chrome-extension
    -    }
    -    uri.makeUnique();
    -  }
    -
    -  netUtils.testLoadImage(uri.toString(), netUtils.NETWORK_TIMEOUT, callback);
    -};
    -
    -
    -/**
    - * Test loading the given image, retrying if necessary.
    - * @param {string} url URL to the image.
    - * @param {number} timeout Milliseconds before giving up.
    - * @param {function(boolean)} callback Function to call with results.
    - * @param {number} retries The number of times to retry.
    - * @param {number=} opt_pauseBetweenRetriesMS Optional number of milliseconds
    - *     between retries - defaults to 0.
    - */
    -netUtils.testLoadImageWithRetries = function(url, timeout, callback,
    -    retries, opt_pauseBetweenRetriesMS) {
    -  var channelDebug = new WebChannelDebug();
    -  channelDebug.debug('TestLoadImageWithRetries: ' + opt_pauseBetweenRetriesMS);
    -  if (retries == 0) {
    -    // no more retries, give up
    -    callback(false);
    -    return;
    -  }
    -
    -  var pauseBetweenRetries = opt_pauseBetweenRetriesMS || 0;
    -  retries--;
    -  netUtils.testLoadImage(url, timeout, function(succeeded) {
    -    if (succeeded) {
    -      callback(true);
    -    } else {
    -      // try again
    -      goog.global.setTimeout(function() {
    -        netUtils.testLoadImageWithRetries(url, timeout, callback,
    -            retries, pauseBetweenRetries);
    -      }, pauseBetweenRetries);
    -    }
    -  });
    -};
    -
    -
    -/**
    - * Test loading the given image.
    - * @param {string} url URL to the image.
    - * @param {number} timeout Milliseconds before giving up.
    - * @param {function(boolean)} callback Function to call with results.
    - */
    -netUtils.testLoadImage = function(url, timeout, callback) {
    -  var channelDebug = new WebChannelDebug();
    -  channelDebug.debug('TestLoadImage: loading ' + url);
    -  var img = new Image();
    -  img.onload = goog.partial(netUtils.imageCallback_, channelDebug, img,
    -      'TestLoadImage: loaded', true, callback);
    -  img.onerror = goog.partial(netUtils.imageCallback_, channelDebug, img,
    -      'TestLoadImage: error', false, callback);
    -  img.onabort = goog.partial(netUtils.imageCallback_, channelDebug, img,
    -      'TestLoadImage: abort', false, callback);
    -  img.ontimeout = goog.partial(netUtils.imageCallback_, channelDebug, img,
    -      'TestLoadImage: timeout', false, callback);
    -
    -  goog.global.setTimeout(function() {
    -    if (img.ontimeout) {
    -      img.ontimeout();
    -    }
    -  }, timeout);
    -  img.src = url;
    -};
    -
    -
    -/**
    - * Wrap the image callback with debug and cleanup logic.
    - * @param {!WebChannelDebug} channelDebug The WebChannelDebug object.
    - * @param {!Image} img The image element.
    - * @param {string} debugText The debug text.
    - * @param {boolean} result The result of image loading.
    - * @param {function(boolean)} callback The image callback.
    - * @private
    - */
    -netUtils.imageCallback_ = function(channelDebug, img, debugText, result,
    -    callback) {
    -  try {
    -    channelDebug.debug(debugText);
    -    netUtils.clearImageCallbacks_(img);
    -    callback(result);
    -  } catch (e) {
    -    channelDebug.dumpException(e);
    -  }
    -};
    -
    -
    -/**
    - * Clears handlers to avoid memory leaks.
    - * @param {Image} img The image to clear handlers from.
    - * @private
    - */
    -netUtils.clearImageCallbacks_ = function(img) {
    -  img.onload = null;
    -  img.onerror = null;
    -  img.onabort = null;
    -  img.ontimeout = null;
    -};
    -});  // goog.scope
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/requeststats.js b/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/requeststats.js
    deleted file mode 100644
    index ff733ce24c8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/requeststats.js
    +++ /dev/null
    @@ -1,383 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Static utilities for collecting stats associated with
    - * ChannelRequest.
    - *
    - * @visibility {:internal}
    - */
    -
    -
    -goog.provide('goog.labs.net.webChannel.requestStats');
    -goog.provide('goog.labs.net.webChannel.requestStats.Event');
    -goog.provide('goog.labs.net.webChannel.requestStats.ServerReachability');
    -goog.provide('goog.labs.net.webChannel.requestStats.ServerReachabilityEvent');
    -goog.provide('goog.labs.net.webChannel.requestStats.Stat');
    -goog.provide('goog.labs.net.webChannel.requestStats.StatEvent');
    -goog.provide('goog.labs.net.webChannel.requestStats.TimingEvent');
    -
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventTarget');
    -
    -
    -goog.scope(function() {
    -var requestStats = goog.labs.net.webChannel.requestStats;
    -
    -
    -/**
    - * Events fired.
    - * @const
    - */
    -requestStats.Event = {};
    -
    -
    -/**
    - * Singleton event target for firing stat events
    - * @type {goog.events.EventTarget}
    - * @private
    - */
    -requestStats.statEventTarget_ = new goog.events.EventTarget();
    -
    -
    -/**
    - * The type of event that occurs every time some information about how reachable
    - * the server is is discovered.
    - */
    -requestStats.Event.SERVER_REACHABILITY_EVENT = 'serverreachability';
    -
    -
    -/**
    - * Types of events which reveal information about the reachability of the
    - * server.
    - * @enum {number}
    - */
    -requestStats.ServerReachability = {
    -  REQUEST_MADE: 1,
    -  REQUEST_SUCCEEDED: 2,
    -  REQUEST_FAILED: 3,
    -  BACK_CHANNEL_ACTIVITY: 4
    -};
    -
    -
    -
    -/**
    - * Event class for SERVER_REACHABILITY_EVENT.
    - *
    - * @param {goog.events.EventTarget} target The stat event target for
    -       the channel.
    - * @param {requestStats.ServerReachability} reachabilityType
    - *     The reachability event type.
    - * @constructor
    - * @extends {goog.events.Event}
    - */
    -requestStats.ServerReachabilityEvent = function(target, reachabilityType) {
    -  goog.events.Event.call(this,
    -      requestStats.Event.SERVER_REACHABILITY_EVENT, target);
    -
    -  /**
    -   * @type {requestStats.ServerReachability}
    -   */
    -  this.reachabilityType = reachabilityType;
    -};
    -goog.inherits(requestStats.ServerReachabilityEvent, goog.events.Event);
    -
    -
    -/**
    - * Notify the channel that a particular fine grained network event has occurred.
    - * Should be considered package-private.
    - * @param {requestStats.ServerReachability} reachabilityType
    - *     The reachability event type.
    - */
    -requestStats.notifyServerReachabilityEvent = function(reachabilityType) {
    -  var target = requestStats.statEventTarget_;
    -  target.dispatchEvent(
    -      new requestStats.ServerReachabilityEvent(target, reachabilityType));
    -};
    -
    -
    -/**
    - * Stat Event that fires when things of interest happen that may be useful for
    - * applications to know about for stats or debugging purposes.
    - */
    -requestStats.Event.STAT_EVENT = 'statevent';
    -
    -
    -/**
    - * Enum that identifies events for statistics that are interesting to track.
    - * @enum {number}
    - */
    -requestStats.Stat = {
    -  /** Event indicating a new connection attempt. */
    -  CONNECT_ATTEMPT: 0,
    -
    -  /** Event indicating a connection error due to a general network problem. */
    -  ERROR_NETWORK: 1,
    -
    -  /**
    -   * Event indicating a connection error that isn't due to a general network
    -   * problem.
    -   */
    -  ERROR_OTHER: 2,
    -
    -  /** Event indicating the start of test stage one. */
    -  TEST_STAGE_ONE_START: 3,
    -
    -  /** Event indicating the start of test stage two. */
    -  TEST_STAGE_TWO_START: 4,
    -
    -  /** Event indicating the first piece of test data was received. */
    -  TEST_STAGE_TWO_DATA_ONE: 5,
    -
    -  /**
    -   * Event indicating that the second piece of test data was received and it was
    -   * recieved separately from the first.
    -   */
    -  TEST_STAGE_TWO_DATA_TWO: 6,
    -
    -  /** Event indicating both pieces of test data were received simultaneously. */
    -  TEST_STAGE_TWO_DATA_BOTH: 7,
    -
    -  /** Event indicating stage one of the test request failed. */
    -  TEST_STAGE_ONE_FAILED: 8,
    -
    -  /** Event indicating stage two of the test request failed. */
    -  TEST_STAGE_TWO_FAILED: 9,
    -
    -  /**
    -   * Event indicating that a buffering proxy is likely between the client and
    -   * the server.
    -   */
    -  PROXY: 10,
    -
    -  /**
    -   * Event indicating that no buffering proxy is likely between the client and
    -   * the server.
    -   */
    -  NOPROXY: 11,
    -
    -  /** Event indicating an unknown SID error. */
    -  REQUEST_UNKNOWN_SESSION_ID: 12,
    -
    -  /** Event indicating a bad status code was received. */
    -  REQUEST_BAD_STATUS: 13,
    -
    -  /** Event indicating incomplete data was received */
    -  REQUEST_INCOMPLETE_DATA: 14,
    -
    -  /** Event indicating bad data was received */
    -  REQUEST_BAD_DATA: 15,
    -
    -  /** Event indicating no data was received when data was expected. */
    -  REQUEST_NO_DATA: 16,
    -
    -  /** Event indicating a request timeout. */
    -  REQUEST_TIMEOUT: 17,
    -
    -  /**
    -   * Event indicating that the server never received our hanging GET and so it
    -   * is being retried.
    -   */
    -  BACKCHANNEL_MISSING: 18,
    -
    -  /**
    -   * Event indicating that we have determined that our hanging GET is not
    -   * receiving data when it should be. Thus it is dead dead and will be retried.
    -   */
    -  BACKCHANNEL_DEAD: 19,
    -
    -  /**
    -   * The browser declared itself offline during the lifetime of a request, or
    -   * was offline when a request was initially made.
    -   */
    -  BROWSER_OFFLINE: 20
    -};
    -
    -
    -
    -/**
    - * Event class for STAT_EVENT.
    - *
    - * @param {goog.events.EventTarget} eventTarget The stat event target for
    -       the channel.
    - * @param {requestStats.Stat} stat The stat.
    - * @constructor
    - * @extends {goog.events.Event}
    - */
    -requestStats.StatEvent = function(eventTarget, stat) {
    -  goog.events.Event.call(this, requestStats.Event.STAT_EVENT, eventTarget);
    -
    -  /**
    -   * The stat
    -   * @type {requestStats.Stat}
    -   */
    -  this.stat = stat;
    -
    -};
    -goog.inherits(requestStats.StatEvent, goog.events.Event);
    -
    -
    -/**
    - * Returns the singleton event target for stat events.
    - * @return {goog.events.EventTarget} The event target for stat events.
    - */
    -requestStats.getStatEventTarget = function() {
    -  return requestStats.statEventTarget_;
    -};
    -
    -
    -/**
    - * Helper function to call the stat event callback.
    - * @param {requestStats.Stat} stat The stat.
    - */
    -requestStats.notifyStatEvent = function(stat) {
    -  var target = requestStats.statEventTarget_;
    -  target.dispatchEvent(new requestStats.StatEvent(target, stat));
    -};
    -
    -
    -/**
    - * An event that fires when POST requests complete successfully, indicating
    - * the size of the POST and the round trip time.
    - */
    -requestStats.Event.TIMING_EVENT = 'timingevent';
    -
    -
    -
    -/**
    - * Event class for requestStats.Event.TIMING_EVENT
    - *
    - * @param {goog.events.EventTarget} target The stat event target for
    -       the channel.
    - * @param {number} size The number of characters in the POST data.
    - * @param {number} rtt The total round trip time from POST to response in MS.
    - * @param {number} retries The number of times the POST had to be retried.
    - * @constructor
    - * @extends {goog.events.Event}
    - */
    -requestStats.TimingEvent = function(target, size, rtt, retries) {
    -  goog.events.Event.call(this,
    -      requestStats.Event.TIMING_EVENT, target);
    -
    -  /**
    -   * @type {number}
    -   */
    -  this.size = size;
    -
    -  /**
    -   * @type {number}
    -   */
    -  this.rtt = rtt;
    -
    -  /**
    -   * @type {number}
    -   */
    -  this.retries = retries;
    -
    -};
    -goog.inherits(requestStats.TimingEvent, goog.events.Event);
    -
    -
    -/**
    - * Helper function to notify listeners about POST request performance.
    - *
    - * @param {number} size Number of characters in the POST data.
    - * @param {number} rtt The amount of time from POST start to response.
    - * @param {number} retries The number of times the POST had to be retried.
    - */
    -requestStats.notifyTimingEvent = function(size, rtt, retries) {
    -  var target = requestStats.statEventTarget_;
    -  target.dispatchEvent(
    -      new requestStats.TimingEvent(
    -          target, size, rtt, retries));
    -};
    -
    -
    -/**
    - * Allows the application to set an execution hooks for when a channel
    - * starts processing requests. This is useful to track timing or logging
    - * special information. The function takes no parameters and return void.
    - * @param {Function} startHook  The function for the start hook.
    - */
    -requestStats.setStartThreadExecutionHook = function(startHook) {
    -  requestStats.startExecutionHook_ = startHook;
    -};
    -
    -
    -/**
    - * Allows the application to set an execution hooks for when a channel
    - * stops processing requests. This is useful to track timing or logging
    - * special information. The function takes no parameters and return void.
    - * @param {Function} endHook  The function for the end hook.
    - */
    -requestStats.setEndThreadExecutionHook = function(endHook) {
    -  requestStats.endExecutionHook_ = endHook;
    -};
    -
    -
    -/**
    - * Application provided execution hook for the start hook.
    - *
    - * @type {Function}
    - * @private
    - */
    -requestStats.startExecutionHook_ = function() { };
    -
    -
    -/**
    - * Application provided execution hook for the end hook.
    - *
    - * @type {Function}
    - * @private
    - */
    -requestStats.endExecutionHook_ = function() { };
    -
    -
    -/**
    - * Helper function to call the start hook
    - */
    -requestStats.onStartExecution = function() {
    -  requestStats.startExecutionHook_();
    -};
    -
    -
    -/**
    - * Helper function to call the end hook
    - */
    -requestStats.onEndExecution = function() {
    -  requestStats.endExecutionHook_();
    -};
    -
    -
    -/**
    - * Wrapper around SafeTimeout which calls the start and end execution hooks
    - * with a try...finally block.
    - * @param {Function} fn The callback function.
    - * @param {number} ms The time in MS for the timer.
    - * @return {number} The ID of the timer.
    - */
    -requestStats.setTimeout = function(fn, ms) {
    -  if (!goog.isFunction(fn)) {
    -    throw Error('Fn must not be null and must be a function');
    -  }
    -  return goog.global.setTimeout(function() {
    -    requestStats.onStartExecution();
    -    try {
    -      fn();
    -    } finally {
    -      requestStats.onEndExecution();
    -    }
    -  }, ms);
    -};
    -});  // goog.scope
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/webchannelbase.js b/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/webchannelbase.js
    deleted file mode 100644
    index 4ef274a565b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/webchannelbase.js
    +++ /dev/null
    @@ -1,2084 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Base WebChannel implementation.
    - *
    - */
    -
    -
    -goog.provide('goog.labs.net.webChannel.WebChannelBase');
    -
    -goog.require('goog.Uri');
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.debug.TextFormatter');
    -goog.require('goog.json');
    -goog.require('goog.labs.net.webChannel.BaseTestChannel');
    -goog.require('goog.labs.net.webChannel.Channel');
    -goog.require('goog.labs.net.webChannel.ChannelRequest');
    -goog.require('goog.labs.net.webChannel.ConnectionState');
    -goog.require('goog.labs.net.webChannel.ForwardChannelRequestPool');
    -goog.require('goog.labs.net.webChannel.WebChannelDebug');
    -goog.require('goog.labs.net.webChannel.Wire');
    -goog.require('goog.labs.net.webChannel.WireV8');
    -goog.require('goog.labs.net.webChannel.netUtils');
    -goog.require('goog.labs.net.webChannel.requestStats');
    -goog.require('goog.labs.net.webChannel.requestStats.Stat');
    -goog.require('goog.log');
    -goog.require('goog.net.XhrIo');
    -goog.require('goog.object');
    -goog.require('goog.string');
    -goog.require('goog.structs');
    -goog.require('goog.structs.CircularBuffer');
    -
    -goog.scope(function() {
    -var BaseTestChannel = goog.labs.net.webChannel.BaseTestChannel;
    -var ChannelRequest = goog.labs.net.webChannel.ChannelRequest;
    -var ConnectionState = goog.labs.net.webChannel.ConnectionState;
    -var ForwardChannelRequestPool =
    -    goog.labs.net.webChannel.ForwardChannelRequestPool;
    -var WebChannelDebug = goog.labs.net.webChannel.WebChannelDebug;
    -var Wire = goog.labs.net.webChannel.Wire;
    -var WireV8 = goog.labs.net.webChannel.WireV8;
    -var netUtils = goog.labs.net.webChannel.netUtils;
    -var requestStats = goog.labs.net.webChannel.requestStats;
    -
    -
    -
    -/**
    - * This WebChannel implementation is branched off goog.net.BrowserChannel
    - * for now. Ongoing changes to goog.net.BrowserChannel will be back
    - * ported to this implementation as needed.
    - *
    - * @param {!goog.net.WebChannel.Options=} opt_options Configuration for the
    - *        WebChannel instance.
    - * @param {string=} opt_clientVersion An application-specific version number
    - *        that is sent to the server when connected.
    - * @param {!ConnectionState=} opt_conn Previously determined connection
    - *        conditions.
    - * @constructor
    - * @struct
    - * @implements {goog.labs.net.webChannel.Channel}
    - */
    -goog.labs.net.webChannel.WebChannelBase = function(opt_options,
    -    opt_clientVersion, opt_conn) {
    -  /**
    -   * The application specific version that is passed to the server.
    -   * @private {?string}
    -   */
    -  this.clientVersion_ = opt_clientVersion || null;
    -
    -  /**
    -   * An array of queued maps that need to be sent to the server.
    -   * @private {!Array<Wire.QueuedMap>}
    -   */
    -  this.outgoingMaps_ = [];
    -
    -  /**
    -   * An array of dequeued maps that we have either received a non-successful
    -   * response for, or no response at all, and which therefore may or may not
    -   * have been received by the server.
    -   * @private {!Array<Wire.QueuedMap>}
    -   */
    -  this.pendingMaps_ = [];
    -
    -  /**
    -   * The channel debug used for logging
    -   * @private {!WebChannelDebug}
    -   */
    -  this.channelDebug_ = new WebChannelDebug();
    -
    -  /**
    -   * Previous connectivity test results.
    -   * @private {!ConnectionState}
    -   */
    -  this.ConnState_ = opt_conn || new ConnectionState();
    -
    -  /**
    -   * Extra HTTP headers to add to all the requests sent to the server.
    -   * @private {Object}
    -   */
    -  this.extraHeaders_ = null;
    -
    -  /**
    -   * Extra parameters to add to all the requests sent to the server.
    -   * @private {Object}
    -   */
    -  this.extraParams_ = null;
    -
    -  /**
    -   * The ChannelRequest object for the backchannel.
    -   * @private {ChannelRequest}
    -   */
    -  this.backChannelRequest_ = null;
    -
    -  /**
    -   * The relative path (in the context of the the page hosting the browser
    -   * channel) for making requests to the server.
    -   * @private {?string}
    -   */
    -  this.path_ = null;
    -
    -  /**
    -   * The absolute URI for the forwardchannel request.
    -   * @private {goog.Uri}
    -   */
    -  this.forwardChannelUri_ = null;
    -
    -  /**
    -   * The absolute URI for the backchannel request.
    -   * @private {goog.Uri}
    -   */
    -  this.backChannelUri_ = null;
    -
    -  /**
    -   * A subdomain prefix for using a subdomain in IE for the backchannel
    -   * requests.
    -   * @private {?string}
    -   */
    -  this.hostPrefix_ = null;
    -
    -  /**
    -   * Whether we allow the use of a subdomain in IE for the backchannel requests.
    -   * @private {boolean}
    -   */
    -  this.allowHostPrefix_ = true;
    -
    -  /**
    -   * The next id to use for the RID (request identifier) parameter. This
    -   * identifier uniquely identifies the forward channel request.
    -   * @private {number}
    -   */
    -  this.nextRid_ = 0;
    -
    -  /**
    -   * The id to use for the next outgoing map. This identifier uniquely
    -   * identifies a sent map.
    -   * @private {number}
    -   */
    -  this.nextMapId_ = 0;
    -
    -  /**
    -   * Whether to fail forward-channel requests after one try or a few tries.
    -   * @private {boolean}
    -   */
    -  this.failFast_ = false;
    -
    -  /**
    -   * The handler that receive callbacks for state changes and data.
    -   * @private {goog.labs.net.webChannel.WebChannelBase.Handler}
    -   */
    -  this.handler_ = null;
    -
    -  /**
    -   * Timer identifier for asynchronously making a forward channel request.
    -   * @private {?number}
    -   */
    -  this.forwardChannelTimerId_ = null;
    -
    -  /**
    -   * Timer identifier for asynchronously making a back channel request.
    -   * @private {?number}
    -   */
    -  this.backChannelTimerId_ = null;
    -
    -  /**
    -   * Timer identifier for the timer that waits for us to retry the backchannel
    -   * in the case where it is dead and no longer receiving data.
    -   * @private {?number}
    -   */
    -  this.deadBackChannelTimerId_ = null;
    -
    -  /**
    -   * The TestChannel object which encapsulates the logic for determining
    -   * interesting network conditions about the client.
    -   * @private {BaseTestChannel}
    -   */
    -  this.connectionTest_ = null;
    -
    -  /**
    -   * Whether the client's network conditions can support chunked responses.
    -   * @private {?boolean}
    -   */
    -  this.useChunked_ = null;
    -
    -  /**
    -   * Whether chunked mode is allowed. In certain debugging situations, it's
    -   * useful to disable this.
    -   * @private {boolean}
    -   */
    -  this.allowChunkedMode_ = true;
    -
    -  /**
    -   * The array identifier of the last array received from the server for the
    -   * backchannel request.
    -   * @private {number}
    -   */
    -  this.lastArrayId_ = -1;
    -
    -  /**
    -   * The array id of the last array sent by the server that we know about.
    -   * @private {number}
    -   */
    -  this.lastPostResponseArrayId_ = -1;
    -
    -  /**
    -   * The last status code received.
    -   * @private {number}
    -   */
    -  this.lastStatusCode_ = -1;
    -
    -  /**
    -   * Number of times we have retried the current forward channel request.
    -   * @private {number}
    -   */
    -  this.forwardChannelRetryCount_ = 0;
    -
    -  /**
    -   * Number of times in a row that we have retried the current back channel
    -   * request and received no data.
    -   * @private {number}
    -   */
    -  this.backChannelRetryCount_ = 0;
    -
    -  /**
    -   * The attempt id for the current back channel request. Starts at 1 and
    -   * increments for each reconnect. The server uses this to log if our
    -   * connection is flaky or not.
    -   * @private {number}
    -   */
    -  this.backChannelAttemptId_ = 0;
    -
    -  /**
    -   * The base part of the time before firing next retry request. Default is 5
    -   * seconds. Note that a random delay is added (see {@link retryDelaySeedMs_})
    -   * for all retries, and linear backoff is applied to the sum for subsequent
    -   * retries.
    -   * @private {number}
    -   */
    -  this.baseRetryDelayMs_ = 5 * 1000;
    -
    -  /**
    -   * A random time between 0 and this number of MS is added to the
    -   * {@link baseRetryDelayMs_}. Default is 10 seconds.
    -   * @private {number}
    -   */
    -  this.retryDelaySeedMs_ = 10 * 1000;
    -
    -  /**
    -   * Maximum number of attempts to connect to the server for forward channel
    -   * requests. Defaults to 2.
    -   * @private {number}
    -   */
    -  this.forwardChannelMaxRetries_ = 2;
    -
    -  /**
    -   * The timeout in milliseconds for a forward channel request. Defaults to 20
    -   * seconds. Note that part of this timeout can be randomized.
    -   * @private {number}
    -   */
    -  this.forwardChannelRequestTimeoutMs_ = 20 * 1000;
    -
    -  /**
    -   * A throttle time in ms for readystatechange events for the backchannel.
    -   * Useful for throttling when ready state is INTERACTIVE (partial data).
    -   *
    -   * This throttle is useful if the server sends large data chunks down the
    -   * backchannel.  It prevents examining XHR partial data on every readystate
    -   * change event.  This is useful because large chunks can trigger hundreds
    -   * of readystatechange events, each of which takes ~5ms or so to handle,
    -   * in turn making the UI unresponsive for a significant period.
    -   *
    -   * If set to zero no throttle is used.
    -   * @private {number}
    -   */
    -  this.readyStateChangeThrottleMs_ = 0;
    -
    -  /**
    -   * Whether cross origin requests are supported for the channel.
    -   *
    -   * See {@link goog.net.XhrIo#setWithCredentials}.
    -   * @private {boolean}
    -   */
    -  this.supportsCrossDomainXhrs_ = false;
    -
    -  /**
    -   * The current session id.
    -   * @private {string}
    -   */
    -  this.sid_ = '';
    -
    -  /**
    -   * The current ChannelRequest pool for the forward channel.
    -   * @private {!ForwardChannelRequestPool}
    -   */
    -  this.forwardChannelRequestPool_ = new ForwardChannelRequestPool(
    -      opt_options && opt_options.concurrentRequestLimit);
    -
    -  /**
    -   * The V8 codec.
    -   * @private {!WireV8}
    -   */
    -  this.wireCodec_ = new WireV8();
    -};
    -
    -var WebChannelBase = goog.labs.net.webChannel.WebChannelBase;
    -
    -
    -/**
    - * The channel version that we negotiated with the server for this session.
    - * Starts out as the version we request, and then is changed to the negotiated
    - * version after the initial open.
    - * @private {number}
    - */
    -WebChannelBase.prototype.channelVersion_ = Wire.LATEST_CHANNEL_VERSION;
    -
    -
    -/**
    - * Enum type for the channel state machine.
    - * @enum {number}
    - */
    -WebChannelBase.State = {
    -  /** The channel is closed. */
    -  CLOSED: 0,
    -
    -  /** The channel has been initialized but hasn't yet initiated a connection. */
    -  INIT: 1,
    -
    -  /** The channel is in the process of opening a connection to the server. */
    -  OPENING: 2,
    -
    -  /** The channel is open. */
    -  OPENED: 3
    -};
    -
    -
    -/**
    - * The current state of the WebChannel.
    - * @private {!WebChannelBase.State}
    - */
    -WebChannelBase.prototype.state_ = WebChannelBase.State.INIT;
    -
    -
    -/**
    - * The timeout in milliseconds for a forward channel request.
    - * @type {number}
    - */
    -WebChannelBase.FORWARD_CHANNEL_RETRY_TIMEOUT = 20 * 1000;
    -
    -
    -/**
    - * Maximum number of attempts to connect to the server for back channel
    - * requests.
    - * @type {number}
    - */
    -WebChannelBase.BACK_CHANNEL_MAX_RETRIES = 3;
    -
    -
    -/**
    - * A number in MS of how long we guess the maxmium amount of time a round trip
    - * to the server should take. In the future this could be substituted with a
    - * real measurement of the RTT.
    - * @type {number}
    - */
    -WebChannelBase.RTT_ESTIMATE = 3 * 1000;
    -
    -
    -/**
    - * When retrying for an inactive channel, we will multiply the total delay by
    - * this number.
    - * @type {number}
    - */
    -WebChannelBase.INACTIVE_CHANNEL_RETRY_FACTOR = 2;
    -
    -
    -/**
    - * Enum type for identifying an error.
    - * @enum {number}
    - */
    -WebChannelBase.Error = {
    -  /** Value that indicates no error has occurred. */
    -  OK: 0,
    -
    -  /** An error due to a request failing. */
    -  REQUEST_FAILED: 2,
    -
    -  /** An error due to the user being logged out. */
    -  LOGGED_OUT: 4,
    -
    -  /** An error due to server response which contains no data. */
    -  NO_DATA: 5,
    -
    -  /** An error due to a server response indicating an unknown session id */
    -  UNKNOWN_SESSION_ID: 6,
    -
    -  /** An error due to a server response requesting to stop the channel. */
    -  STOP: 7,
    -
    -  /** A general network error. */
    -  NETWORK: 8,
    -
    -  /** An error due to bad data being returned from the server. */
    -  BAD_DATA: 10,
    -
    -  /** An error due to a response that is not parsable. */
    -  BAD_RESPONSE: 11
    -};
    -
    -
    -/**
    - * Internal enum type for the two channel types.
    - * @enum {number}
    - * @private
    - */
    -WebChannelBase.ChannelType_ = {
    -  FORWARD_CHANNEL: 1,
    -
    -  BACK_CHANNEL: 2
    -};
    -
    -
    -/**
    - * The maximum number of maps that can be sent in one POST. Should match
    - * MAX_MAPS_PER_REQUEST on the server code.
    - * @type {number}
    - * @private
    - */
    -WebChannelBase.MAX_MAPS_PER_REQUEST_ = 1000;
    -
    -
    -/**
    - * A guess at a cutoff at which to no longer assume the backchannel is dead
    - * when we are slow to receive data. Number in bytes.
    - *
    - * Assumption: The worst bandwidth we work on is 50 kilobits/sec
    - * 50kbits/sec * (1 byte / 8 bits) * 6 sec dead backchannel timeout
    - * @type {number}
    - */
    -WebChannelBase.OUTSTANDING_DATA_BACKCHANNEL_RETRY_CUTOFF = 37500;
    -
    -
    -/**
    - * @return {!ForwardChannelRequestPool} The forward channel request pool.
    - */
    -WebChannelBase.prototype.getForwardChannelRequestPool = function() {
    -  return this.forwardChannelRequestPool_;
    -};
    -
    -
    -/**
    - * @return {!Object} The codec object, to be used for the test channel.
    - */
    -WebChannelBase.prototype.getWireCodec = function() {
    -  return this.wireCodec_;
    -};
    -
    -
    -/**
    - * Returns the logger.
    - *
    - * @return {!WebChannelDebug} The channel debug object.
    - */
    -WebChannelBase.prototype.getChannelDebug = function() {
    -  return this.channelDebug_;
    -};
    -
    -
    -/**
    - * Sets the logger.
    - *
    - * @param {!WebChannelDebug} channelDebug The channel debug object.
    - */
    -WebChannelBase.prototype.setChannelDebug = function(channelDebug) {
    -  this.channelDebug_ = channelDebug;
    -};
    -
    -
    -/**
    - * Starts the channel. This initiates connections to the server.
    - *
    - * @param {string} testPath  The path for the test connection.
    - * @param {string} channelPath  The path for the channel connection.
    - * @param {!Object=} opt_extraParams Extra parameter keys and values to add to
    - *     the requests.
    - * @param {string=} opt_oldSessionId  Session ID from a previous session.
    - * @param {number=} opt_oldArrayId  The last array ID from a previous session.
    - */
    -WebChannelBase.prototype.connect = function(testPath, channelPath,
    -    opt_extraParams, opt_oldSessionId, opt_oldArrayId) {
    -  this.channelDebug_.debug('connect()');
    -
    -  requestStats.notifyStatEvent(requestStats.Stat.CONNECT_ATTEMPT);
    -
    -  this.path_ = channelPath;
    -  this.extraParams_ = opt_extraParams || {};
    -
    -  // Attach parameters about the previous session if reconnecting.
    -  if (opt_oldSessionId && goog.isDef(opt_oldArrayId)) {
    -    this.extraParams_['OSID'] = opt_oldSessionId;
    -    this.extraParams_['OAID'] = opt_oldArrayId;
    -  }
    -
    -  this.connectTest_(testPath);
    -};
    -
    -
    -/**
    - * Disconnects and closes the channel.
    - */
    -WebChannelBase.prototype.disconnect = function() {
    -  this.channelDebug_.debug('disconnect()');
    -
    -  this.cancelRequests_();
    -
    -  if (this.state_ == WebChannelBase.State.OPENED) {
    -    var rid = this.nextRid_++;
    -    var uri = this.forwardChannelUri_.clone();
    -    uri.setParameterValue('SID', this.sid_);
    -    uri.setParameterValue('RID', rid);
    -    uri.setParameterValue('TYPE', 'terminate');
    -
    -    // Add the reconnect parameters.
    -    this.addAdditionalParams_(uri);
    -
    -    var request = ChannelRequest.createChannelRequest(
    -        this, this.channelDebug_, this.sid_, rid);
    -    request.sendUsingImgTag(uri);
    -  }
    -
    -  this.onClose_();
    -};
    -
    -
    -/**
    - * Returns the session id of the channel. Only available after the
    - * channel has been opened.
    - * @return {string} Session ID.
    - */
    -WebChannelBase.prototype.getSessionId = function() {
    -  return this.sid_;
    -};
    -
    -
    -/**
    - * Starts the test channel to determine network conditions.
    - *
    - * @param {string} testPath  The relative PATH for the test connection.
    - * @private
    - */
    -WebChannelBase.prototype.connectTest_ = function(testPath) {
    -  this.channelDebug_.debug('connectTest_()');
    -  if (!this.okToMakeRequest_()) {
    -    return; // channel is cancelled
    -  }
    -  this.connectionTest_ = new BaseTestChannel(this, this.channelDebug_);
    -  this.connectionTest_.setExtraHeaders(this.extraHeaders_);
    -  this.connectionTest_.connect(testPath);
    -};
    -
    -
    -/**
    - * Starts the regular channel which is run after the test channel is complete.
    - * @private
    - */
    -WebChannelBase.prototype.connectChannel_ = function() {
    -  this.channelDebug_.debug('connectChannel_()');
    -  this.ensureInState_(WebChannelBase.State.INIT, WebChannelBase.State.CLOSED);
    -  this.forwardChannelUri_ =
    -      this.getForwardChannelUri(/** @type {string} */ (this.path_));
    -  this.ensureForwardChannel_();
    -};
    -
    -
    -/**
    - * Cancels all outstanding requests.
    - * @private
    - */
    -WebChannelBase.prototype.cancelRequests_ = function() {
    -  if (this.connectionTest_) {
    -    this.connectionTest_.abort();
    -    this.connectionTest_ = null;
    -  }
    -
    -  if (this.backChannelRequest_) {
    -    this.backChannelRequest_.cancel();
    -    this.backChannelRequest_ = null;
    -  }
    -
    -  if (this.backChannelTimerId_) {
    -    goog.global.clearTimeout(this.backChannelTimerId_);
    -    this.backChannelTimerId_ = null;
    -  }
    -
    -  this.clearDeadBackchannelTimer_();
    -
    -  this.forwardChannelRequestPool_.cancel();
    -
    -  if (this.forwardChannelTimerId_) {
    -    goog.global.clearTimeout(this.forwardChannelTimerId_);
    -    this.forwardChannelTimerId_ = null;
    -  }
    -};
    -
    -
    -/**
    - * Returns the extra HTTP headers to add to all the requests sent to the server.
    - *
    - * @return {Object} The HTTP headers, or null.
    - */
    -WebChannelBase.prototype.getExtraHeaders = function() {
    -  return this.extraHeaders_;
    -};
    -
    -
    -/**
    - * Sets extra HTTP headers to add to all the requests sent to the server.
    - *
    - * @param {Object} extraHeaders The HTTP headers, or null.
    - */
    -WebChannelBase.prototype.setExtraHeaders = function(extraHeaders) {
    -  this.extraHeaders_ = extraHeaders;
    -};
    -
    -
    -/**
    - * Sets the throttle for handling onreadystatechange events for the request.
    - *
    - * @param {number} throttle The throttle in ms.  A value of zero indicates
    - *     no throttle.
    - */
    -WebChannelBase.prototype.setReadyStateChangeThrottle = function(throttle) {
    -  this.readyStateChangeThrottleMs_ = throttle;
    -};
    -
    -
    -/**
    - * Sets whether cross origin requests are supported for the channel.
    - *
    - * Setting this allows the creation of requests to secondary domains and
    - * sends XHRs with the CORS withCredentials bit set to true.
    - *
    - * In order for cross-origin requests to work, the server will also need to set
    - * CORS response headers as per:
    - * https://developer.mozilla.org/en-US/docs/HTTP_access_control
    - *
    - * See {@link goog.net.XhrIo#setWithCredentials}.
    - * @param {boolean} supportCrossDomain Whether cross domain XHRs are supported.
    - */
    -WebChannelBase.prototype.setSupportsCrossDomainXhrs =
    -    function(supportCrossDomain) {
    -  this.supportsCrossDomainXhrs_ = supportCrossDomain;
    -};
    -
    -
    -/**
    - * Returns the handler used for channel callback events.
    - *
    - * @return {WebChannelBase.Handler} The handler.
    - */
    -WebChannelBase.prototype.getHandler = function() {
    -  return this.handler_;
    -};
    -
    -
    -/**
    - * Sets the handler used for channel callback events.
    - * @param {WebChannelBase.Handler} handler The handler to set.
    - */
    -WebChannelBase.prototype.setHandler = function(handler) {
    -  this.handler_ = handler;
    -};
    -
    -
    -/**
    - * Returns whether the channel allows the use of a subdomain. There may be
    - * cases where this isn't allowed.
    - * @return {boolean} Whether a host prefix is allowed.
    - */
    -WebChannelBase.prototype.getAllowHostPrefix = function() {
    -  return this.allowHostPrefix_;
    -};
    -
    -
    -/**
    - * Sets whether the channel allows the use of a subdomain. There may be cases
    - * where this isn't allowed, for example, logging in with troutboard where
    - * using a subdomain causes Apache to force the user to authenticate twice.
    - * @param {boolean} allowHostPrefix Whether a host prefix is allowed.
    - */
    -WebChannelBase.prototype.setAllowHostPrefix = function(allowHostPrefix) {
    -  this.allowHostPrefix_ = allowHostPrefix;
    -};
    -
    -
    -/**
    - * Returns whether the channel is buffered or not. This state is valid for
    - * querying only after the test connection has completed. This may be
    - * queried in the WebChannelBase.okToMakeRequest() callback.
    - * A channel may be buffered if the test connection determines that
    - * a chunked response could not be sent down within a suitable time.
    - * @return {boolean} Whether the channel is buffered.
    - */
    -WebChannelBase.prototype.isBuffered = function() {
    -  return !this.useChunked_;
    -};
    -
    -
    -/**
    - * Returns whether chunked mode is allowed. In certain debugging situations,
    - * it's useful for the application to have a way to disable chunked mode for a
    - * user.
    -
    - * @return {boolean} Whether chunked mode is allowed.
    - */
    -WebChannelBase.prototype.getAllowChunkedMode = function() {
    -  return this.allowChunkedMode_;
    -};
    -
    -
    -/**
    - * Sets whether chunked mode is allowed. In certain debugging situations, it's
    - * useful for the application to have a way to disable chunked mode for a user.
    - * @param {boolean} allowChunkedMode  Whether chunked mode is allowed.
    - */
    -WebChannelBase.prototype.setAllowChunkedMode = function(allowChunkedMode) {
    -  this.allowChunkedMode_ = allowChunkedMode;
    -};
    -
    -
    -/**
    - * Sends a request to the server. The format of the request is a Map data
    - * structure of key/value pairs. These maps are then encoded in a format
    - * suitable for the wire and then reconstituted as a Map data structure that
    - * the server can process.
    - * @param {!Object|!goog.structs.Map} map The map to send.
    - * @param {!Object=} opt_context The context associated with the map.
    - */
    -WebChannelBase.prototype.sendMap = function(map, opt_context) {
    -  goog.asserts.assert(this.state_ != WebChannelBase.State.CLOSED,
    -      'Invalid operation: sending map when state is closed');
    -
    -  // We can only send 1000 maps per POST, but typically we should never have
    -  // that much to send, so warn if we exceed that (we still send all the maps).
    -  if (this.outgoingMaps_.length == WebChannelBase.MAX_MAPS_PER_REQUEST_) {
    -    // severe() is temporary so that we get these uploaded and can figure out
    -    // what's causing them. Afterwards can change to warning().
    -    this.channelDebug_.severe(
    -        'Already have ' + WebChannelBase.MAX_MAPS_PER_REQUEST_ +
    -        ' queued maps upon queueing ' + goog.json.serialize(map));
    -  }
    -
    -  this.outgoingMaps_.push(
    -      new Wire.QueuedMap(this.nextMapId_++, map, opt_context));
    -  if (this.state_ == WebChannelBase.State.OPENING ||
    -      this.state_ == WebChannelBase.State.OPENED) {
    -    this.ensureForwardChannel_();
    -  }
    -};
    -
    -
    -/**
    - * When set to true, this changes the behavior of the forward channel so it
    - * will not retry requests; it will fail after one network failure, and if
    - * there was already one network failure, the request will fail immediately.
    - * @param {boolean} failFast  Whether or not to fail fast.
    - */
    -WebChannelBase.prototype.setFailFast = function(failFast) {
    -  this.failFast_ = failFast;
    -  this.channelDebug_.info('setFailFast: ' + failFast);
    -  if ((this.forwardChannelRequestPool_.hasPendingRequest() ||
    -       this.forwardChannelTimerId_) &&
    -      this.forwardChannelRetryCount_ > this.getForwardChannelMaxRetries()) {
    -    this.channelDebug_.info(
    -        'Retry count ' + this.forwardChannelRetryCount_ +
    -        ' > new maxRetries ' + this.getForwardChannelMaxRetries() +
    -        '. Fail immediately!');
    -
    -    if (!this.forwardChannelRequestPool_.forceComplete(
    -        goog.bind(this.onRequestComplete, this))) {
    -      // i.e., this.forwardChannelTimerId_
    -      goog.global.clearTimeout(this.forwardChannelTimerId_);
    -      this.forwardChannelTimerId_ = null;
    -      // The error code from the last failed request is gone, so just use a
    -      // generic one.
    -      this.signalError_(WebChannelBase.Error.REQUEST_FAILED);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * @return {number} The max number of forward-channel retries, which will be 0
    - * in fail-fast mode.
    - */
    -WebChannelBase.prototype.getForwardChannelMaxRetries = function() {
    -  return this.failFast_ ? 0 : this.forwardChannelMaxRetries_;
    -};
    -
    -
    -/**
    - * Sets the maximum number of attempts to connect to the server for forward
    - * channel requests.
    - * @param {number} retries The maximum number of attempts.
    - */
    -WebChannelBase.prototype.setForwardChannelMaxRetries = function(retries) {
    -  this.forwardChannelMaxRetries_ = retries;
    -};
    -
    -
    -/**
    - * Sets the timeout for a forward channel request.
    - * @param {number} timeoutMs The timeout in milliseconds.
    - */
    -WebChannelBase.prototype.setForwardChannelRequestTimeout = function(timeoutMs) {
    -  this.forwardChannelRequestTimeoutMs_ = timeoutMs;
    -};
    -
    -
    -/**
    - * @return {number} The max number of back-channel retries, which is a constant.
    - */
    -WebChannelBase.prototype.getBackChannelMaxRetries = function() {
    -  // Back-channel retries is a constant.
    -  return WebChannelBase.BACK_CHANNEL_MAX_RETRIES;
    -};
    -
    -
    -/**
    - * @override
    - */
    -WebChannelBase.prototype.isClosed = function() {
    -  return this.state_ == WebChannelBase.State.CLOSED;
    -};
    -
    -
    -/**
    - * Returns the channel state.
    - * @return {WebChannelBase.State} The current state of the channel.
    - */
    -WebChannelBase.prototype.getState = function() {
    -  return this.state_;
    -};
    -
    -
    -/**
    - * Return the last status code received for a request.
    - * @return {number} The last status code received for a request.
    - */
    -WebChannelBase.prototype.getLastStatusCode = function() {
    -  return this.lastStatusCode_;
    -};
    -
    -
    -/**
    - * @return {number} The last array id received.
    - */
    -WebChannelBase.prototype.getLastArrayId = function() {
    -  return this.lastArrayId_;
    -};
    -
    -
    -/**
    - * Returns whether there are outstanding requests servicing the channel.
    - * @return {boolean} true if there are outstanding requests.
    - */
    -WebChannelBase.prototype.hasOutstandingRequests = function() {
    -  return this.getOutstandingRequests_() != 0;
    -};
    -
    -
    -/**
    - * Returns the number of outstanding requests.
    - * @return {number} The number of outstanding requests to the server.
    - * @private
    - */
    -WebChannelBase.prototype.getOutstandingRequests_ = function() {
    -  var count = 0;
    -  if (this.backChannelRequest_) {
    -    count++;
    -  }
    -  count += this.forwardChannelRequestPool_.getRequestCount();
    -  return count;
    -};
    -
    -
    -/**
    - * Ensures that a forward channel request is scheduled.
    - * @private
    - */
    -WebChannelBase.prototype.ensureForwardChannel_ = function() {
    -  if (this.forwardChannelRequestPool_.isFull()) {
    -    // enough connection in process - no need to start a new request
    -    return;
    -  }
    -
    -  if (this.forwardChannelTimerId_) {
    -    // no need to start a new request - one is already scheduled
    -    return;
    -  }
    -
    -  this.forwardChannelTimerId_ = requestStats.setTimeout(
    -      goog.bind(this.onStartForwardChannelTimer_, this), 0);
    -  this.forwardChannelRetryCount_ = 0;
    -};
    -
    -
    -/**
    - * Schedules a forward-channel retry for the specified request, unless the max
    - * retries has been reached.
    - * @param {ChannelRequest} request The failed request to retry.
    - * @return {boolean} true iff a retry was scheduled.
    - * @private
    - */
    -WebChannelBase.prototype.maybeRetryForwardChannel_ =
    -    function(request) {
    -  if (this.forwardChannelRequestPool_.isFull() || this.forwardChannelTimerId_) {
    -    // Should be impossible to be called in this state.
    -    this.channelDebug_.severe('Request already in progress');
    -    return false;
    -  }
    -
    -  if (this.state_ == WebChannelBase.State.INIT ||  // no retry open_()
    -      (this.forwardChannelRetryCount_ >= this.getForwardChannelMaxRetries())) {
    -    return false;
    -  }
    -
    -  this.channelDebug_.debug('Going to retry POST');
    -
    -  this.forwardChannelTimerId_ = requestStats.setTimeout(
    -      goog.bind(this.onStartForwardChannelTimer_, this, request),
    -      this.getRetryTime_(this.forwardChannelRetryCount_));
    -  this.forwardChannelRetryCount_++;
    -  return true;
    -};
    -
    -
    -/**
    - * Timer callback for ensureForwardChannel
    - * @param {ChannelRequest=} opt_retryRequest A failed request
    - * to retry.
    - * @private
    - */
    -WebChannelBase.prototype.onStartForwardChannelTimer_ = function(
    -    opt_retryRequest) {
    -  this.forwardChannelTimerId_ = null;
    -  this.startForwardChannel_(opt_retryRequest);
    -};
    -
    -
    -/**
    - * Begins a new forward channel operation to the server.
    - * @param {ChannelRequest=} opt_retryRequest A failed request to retry.
    - * @private
    - */
    -WebChannelBase.prototype.startForwardChannel_ = function(
    -    opt_retryRequest) {
    -  this.channelDebug_.debug('startForwardChannel_');
    -  if (!this.okToMakeRequest_()) {
    -    return; // channel is cancelled
    -  } else if (this.state_ == WebChannelBase.State.INIT) {
    -    if (opt_retryRequest) {
    -      this.channelDebug_.severe('Not supposed to retry the open');
    -      return;
    -    }
    -    this.open_();
    -    this.state_ = WebChannelBase.State.OPENING;
    -  } else if (this.state_ == WebChannelBase.State.OPENED) {
    -    if (opt_retryRequest) {
    -      this.makeForwardChannelRequest_(opt_retryRequest);
    -      return;
    -    }
    -
    -    if (this.outgoingMaps_.length == 0) {
    -      this.channelDebug_.debug('startForwardChannel_ returned: ' +
    -                                   'nothing to send');
    -      // no need to start a new forward channel request
    -      return;
    -    }
    -
    -    if (this.forwardChannelRequestPool_.isFull()) {
    -      // Should be impossible to be called in this state.
    -      this.channelDebug_.severe('startForwardChannel_ returned: ' +
    -          'connection already in progress');
    -      return;
    -    }
    -
    -    this.makeForwardChannelRequest_();
    -    this.channelDebug_.debug('startForwardChannel_ finished, sent request');
    -  }
    -};
    -
    -
    -/**
    - * Establishes a new channel session with the the server.
    - * @private
    - */
    -WebChannelBase.prototype.open_ = function() {
    -  this.channelDebug_.debug('open_()');
    -  this.nextRid_ = Math.floor(Math.random() * 100000);
    -
    -  var rid = this.nextRid_++;
    -  var request = ChannelRequest.createChannelRequest(
    -      this, this.channelDebug_, '', rid);
    -  request.setExtraHeaders(this.extraHeaders_);
    -  var requestText = this.dequeueOutgoingMaps_();
    -  var uri = this.forwardChannelUri_.clone();
    -  uri.setParameterValue('RID', rid);
    -  if (this.clientVersion_) {
    -    uri.setParameterValue('CVER', this.clientVersion_);
    -  }
    -
    -  // Add the reconnect parameters.
    -  this.addAdditionalParams_(uri);
    -
    -  this.forwardChannelRequestPool_.addRequest(request);
    -  request.xmlHttpPost(uri, requestText, true);
    -};
    -
    -
    -/**
    - * Makes a forward channel request using XMLHTTP.
    - * @param {!ChannelRequest=} opt_retryRequest A failed request to retry.
    - * @private
    - */
    -WebChannelBase.prototype.makeForwardChannelRequest_ =
    -    function(opt_retryRequest) {
    -  var rid;
    -  var requestText;
    -  if (opt_retryRequest) {
    -    this.requeuePendingMaps_();
    -    rid = this.nextRid_ - 1;  // Must use last RID
    -    requestText = this.dequeueOutgoingMaps_();
    -  } else {
    -    rid = this.nextRid_++;
    -    requestText = this.dequeueOutgoingMaps_();
    -  }
    -
    -  var uri = this.forwardChannelUri_.clone();
    -  uri.setParameterValue('SID', this.sid_);
    -  uri.setParameterValue('RID', rid);
    -  uri.setParameterValue('AID', this.lastArrayId_);
    -  // Add the additional reconnect parameters.
    -  this.addAdditionalParams_(uri);
    -
    -  var request = ChannelRequest.createChannelRequest(this, this.channelDebug_,
    -      this.sid_, rid, this.forwardChannelRetryCount_ + 1);
    -  request.setExtraHeaders(this.extraHeaders_);
    -
    -  // Randomize from 50%-100% of the forward channel timeout to avoid
    -  // a big hit if servers happen to die at once.
    -  request.setTimeout(
    -      Math.round(this.forwardChannelRequestTimeoutMs_ * 0.50) +
    -      Math.round(this.forwardChannelRequestTimeoutMs_ * 0.50 * Math.random()));
    -  this.forwardChannelRequestPool_.addRequest(request);
    -  request.xmlHttpPost(uri, requestText, true);
    -};
    -
    -
    -/**
    - * Adds the additional parameters from the handler to the given URI.
    - * @param {!goog.Uri} uri The URI to add the parameters to.
    - * @private
    - */
    -WebChannelBase.prototype.addAdditionalParams_ = function(uri) {
    -  // Add the additional reconnect parameters as needed.
    -  if (this.handler_) {
    -    var params = this.handler_.getAdditionalParams(this);
    -    if (params) {
    -      goog.structs.forEach(params, function(value, key, coll) {
    -        uri.setParameterValue(key, value);
    -      });
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Returns the request text from the outgoing maps and resets it.
    - * @return {string} The encoded request text created from all the currently
    - *                  queued outgoing maps.
    - * @private
    - */
    -WebChannelBase.prototype.dequeueOutgoingMaps_ = function() {
    -  var count = Math.min(this.outgoingMaps_.length,
    -                       WebChannelBase.MAX_MAPS_PER_REQUEST_);
    -  var badMapHandler = this.handler_ ?
    -      goog.bind(this.handler_.badMapError, this.handler_, this) : null;
    -  var result = this.wireCodec_.encodeMessageQueue(
    -      this.outgoingMaps_, count, badMapHandler);
    -  this.pendingMaps_ = this.pendingMaps_.concat(
    -      this.outgoingMaps_.splice(0, count));
    -  return result;
    -};
    -
    -
    -/**
    - * Requeues unacknowledged sent arrays for retransmission in the next forward
    - * channel request.
    - * @private
    - */
    -WebChannelBase.prototype.requeuePendingMaps_ = function() {
    -  this.outgoingMaps_ = this.pendingMaps_.concat(this.outgoingMaps_);
    -  this.pendingMaps_.length = 0;
    -};
    -
    -
    -/**
    - * Ensures there is a backchannel request for receiving data from the server.
    - * @private
    - */
    -WebChannelBase.prototype.ensureBackChannel_ = function() {
    -  if (this.backChannelRequest_) {
    -    // already have one
    -    return;
    -  }
    -
    -  if (this.backChannelTimerId_) {
    -    // no need to start a new request - one is already scheduled
    -    return;
    -  }
    -
    -  this.backChannelAttemptId_ = 1;
    -  this.backChannelTimerId_ = requestStats.setTimeout(
    -      goog.bind(this.onStartBackChannelTimer_, this), 0);
    -  this.backChannelRetryCount_ = 0;
    -};
    -
    -
    -/**
    - * Schedules a back-channel retry, unless the max retries has been reached.
    - * @return {boolean} true iff a retry was scheduled.
    - * @private
    - */
    -WebChannelBase.prototype.maybeRetryBackChannel_ = function() {
    -  if (this.backChannelRequest_ || this.backChannelTimerId_) {
    -    // Should be impossible to be called in this state.
    -    this.channelDebug_.severe('Request already in progress');
    -    return false;
    -  }
    -
    -  if (this.backChannelRetryCount_ >= this.getBackChannelMaxRetries()) {
    -    return false;
    -  }
    -
    -  this.channelDebug_.debug('Going to retry GET');
    -
    -  this.backChannelAttemptId_++;
    -  this.backChannelTimerId_ = requestStats.setTimeout(
    -      goog.bind(this.onStartBackChannelTimer_, this),
    -      this.getRetryTime_(this.backChannelRetryCount_));
    -  this.backChannelRetryCount_++;
    -  return true;
    -};
    -
    -
    -/**
    - * Timer callback for ensureBackChannel_.
    - * @private
    - */
    -WebChannelBase.prototype.onStartBackChannelTimer_ = function() {
    -  this.backChannelTimerId_ = null;
    -  this.startBackChannel_();
    -};
    -
    -
    -/**
    - * Begins a new back channel operation to the server.
    - * @private
    - */
    -WebChannelBase.prototype.startBackChannel_ = function() {
    -  if (!this.okToMakeRequest_()) {
    -    // channel is cancelled
    -    return;
    -  }
    -
    -  this.channelDebug_.debug('Creating new HttpRequest');
    -  this.backChannelRequest_ = ChannelRequest.createChannelRequest(this,
    -      this.channelDebug_, this.sid_, 'rpc', this.backChannelAttemptId_);
    -  this.backChannelRequest_.setExtraHeaders(this.extraHeaders_);
    -  this.backChannelRequest_.setReadyStateChangeThrottle(
    -      this.readyStateChangeThrottleMs_);
    -  var uri = this.backChannelUri_.clone();
    -  uri.setParameterValue('RID', 'rpc');
    -  uri.setParameterValue('SID', this.sid_);
    -  uri.setParameterValue('CI', this.useChunked_ ? '0' : '1');
    -  uri.setParameterValue('AID', this.lastArrayId_);
    -
    -  // Add the reconnect parameters.
    -  this.addAdditionalParams_(uri);
    -
    -  uri.setParameterValue('TYPE', 'xmlhttp');
    -  this.backChannelRequest_.xmlHttpGet(uri, true /* decodeChunks */,
    -      this.hostPrefix_, false /* opt_noClose */);
    -
    -  this.channelDebug_.debug('New Request created');
    -};
    -
    -
    -/**
    - * Gives the handler a chance to return an error code and stop channel
    - * execution. A handler might want to do this to check that the user is still
    - * logged in, for example.
    - * @private
    - * @return {boolean} If it's OK to make a request.
    - */
    -WebChannelBase.prototype.okToMakeRequest_ = function() {
    -  if (this.handler_) {
    -    var result = this.handler_.okToMakeRequest(this);
    -    if (result != WebChannelBase.Error.OK) {
    -      this.channelDebug_.debug(
    -          'Handler returned error code from okToMakeRequest');
    -      this.signalError_(result);
    -      return false;
    -    }
    -  }
    -  return true;
    -};
    -
    -
    -/**
    - * @override
    - */
    -WebChannelBase.prototype.testConnectionFinished =
    -    function(testChannel, useChunked) {
    -  this.channelDebug_.debug('Test Connection Finished');
    -
    -  // Forward channel will not be used prior to this method is called
    -  var clientProtocol = testChannel.getClientProtocol();
    -  if (clientProtocol) {
    -    this.forwardChannelRequestPool_.applyClientProtocol(clientProtocol);
    -  }
    -
    -  this.useChunked_ = this.allowChunkedMode_ && useChunked;
    -  this.lastStatusCode_ = testChannel.getLastStatusCode();
    -
    -  this.connectChannel_();
    -};
    -
    -
    -/**
    - * @override
    - */
    -WebChannelBase.prototype.testConnectionFailure =
    -    function(testChannel, errorCode) {
    -  this.channelDebug_.debug('Test Connection Failed');
    -  this.lastStatusCode_ = testChannel.getLastStatusCode();
    -  this.signalError_(WebChannelBase.Error.REQUEST_FAILED);
    -};
    -
    -
    -/**
    - * @override
    - */
    -WebChannelBase.prototype.onRequestData = function(request, responseText) {
    -  if (this.state_ == WebChannelBase.State.CLOSED ||
    -      (this.backChannelRequest_ != request &&
    -       !this.forwardChannelRequestPool_.hasRequest(request))) {
    -    // either CLOSED or a request we don't know about (perhaps an old request)
    -    return;
    -  }
    -  this.lastStatusCode_ = request.getLastStatusCode();
    -
    -  if (this.forwardChannelRequestPool_.hasRequest(request) &&
    -      this.state_ == WebChannelBase.State.OPENED) {
    -    var response;
    -    try {
    -      response = this.wireCodec_.decodeMessage(responseText);
    -    } catch (ex) {
    -      response = null;
    -    }
    -    if (goog.isArray(response) && response.length == 3) {
    -      this.handlePostResponse_(/** @type {!Array<?>} */ (response), request);
    -    } else {
    -      this.channelDebug_.debug('Bad POST response data returned');
    -      this.signalError_(WebChannelBase.Error.BAD_RESPONSE);
    -    }
    -  } else {
    -    if (this.backChannelRequest_ == request) {
    -      this.clearDeadBackchannelTimer_();
    -    }
    -    if (!goog.string.isEmptyOrWhitespace(responseText)) {
    -      var response = this.wireCodec_.decodeMessage(responseText);
    -      this.onInput_(/** @type {!Array<?>} */ (response));
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Handles a POST response from the server.
    - * @param {Array<number>} responseValues The key value pairs in
    - *     the POST response.
    - * @param {!ChannelRequest} forwardReq The forward channel request that
    - * triggers this function call.
    - * @private
    - */
    -WebChannelBase.prototype.handlePostResponse_ = function(
    -    responseValues, forwardReq) {
    -  // The first response value is set to 0 if server is missing backchannel.
    -  if (responseValues[0] == 0) {
    -    this.handleBackchannelMissing_(forwardReq);
    -    return;
    -  }
    -  this.lastPostResponseArrayId_ = responseValues[1];
    -  var outstandingArrays = this.lastPostResponseArrayId_ - this.lastArrayId_;
    -  if (0 < outstandingArrays) {
    -    var numOutstandingBackchannelBytes = responseValues[2];
    -    this.channelDebug_.debug(numOutstandingBackchannelBytes + ' bytes (in ' +
    -        outstandingArrays + ' arrays) are outstanding on the BackChannel');
    -    if (!this.shouldRetryBackChannel_(numOutstandingBackchannelBytes)) {
    -      return;
    -    }
    -    if (!this.deadBackChannelTimerId_) {
    -      // We expect to receive data within 2 RTTs or we retry the backchannel.
    -      this.deadBackChannelTimerId_ = requestStats.setTimeout(
    -          goog.bind(this.onBackChannelDead_, this),
    -          2 * WebChannelBase.RTT_ESTIMATE);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Handles a POST response from the server telling us that it has detected that
    - * we have no hanging GET connection.
    - * @param {!ChannelRequest} forwardReq The forward channel request that
    - * triggers this function call.
    - * @private
    - */
    -WebChannelBase.prototype.handleBackchannelMissing_ = function(forwardReq) {
    -  // As long as the back channel was started before the POST was sent,
    -  // we should retry the backchannel. We give a slight buffer of RTT_ESTIMATE
    -  // so as not to excessively retry the backchannel
    -  this.channelDebug_.debug('Server claims our backchannel is missing.');
    -  if (this.backChannelTimerId_) {
    -    this.channelDebug_.debug('But we are currently starting the request.');
    -    return;
    -  } else if (!this.backChannelRequest_) {
    -    this.channelDebug_.warning(
    -        'We do not have a BackChannel established');
    -  } else if (this.backChannelRequest_.getRequestStartTime() +
    -      WebChannelBase.RTT_ESTIMATE < forwardReq.getRequestStartTime()) {
    -    this.clearDeadBackchannelTimer_();
    -    this.backChannelRequest_.cancel();
    -    this.backChannelRequest_ = null;
    -  } else {
    -    return;
    -  }
    -  this.maybeRetryBackChannel_();
    -  requestStats.notifyStatEvent(requestStats.Stat.BACKCHANNEL_MISSING);
    -};
    -
    -
    -/**
    - * Determines whether we should start the process of retrying a possibly
    - * dead backchannel.
    - * @param {number} outstandingBytes The number of bytes for which the server has
    - *     not yet received acknowledgement.
    - * @return {boolean} Whether to start the backchannel retry timer.
    - * @private
    - */
    -WebChannelBase.prototype.shouldRetryBackChannel_ = function(
    -    outstandingBytes) {
    -  // Not too many outstanding bytes, not buffered and not after a retry.
    -  return outstandingBytes <
    -      WebChannelBase.OUTSTANDING_DATA_BACKCHANNEL_RETRY_CUTOFF &&
    -      !this.isBuffered() &&
    -      this.backChannelRetryCount_ == 0;
    -};
    -
    -
    -/**
    - * Decides which host prefix should be used, if any.  If there is a handler,
    - * allows the handler to validate a host prefix provided by the server, and
    - * optionally override it.
    - * @param {?string} serverHostPrefix The host prefix provided by the server.
    - * @return {?string} The host prefix to actually use, if any. Will return null
    - *     if the use of host prefixes was disabled via setAllowHostPrefix().
    - * @override
    - */
    -WebChannelBase.prototype.correctHostPrefix = function(serverHostPrefix) {
    -  if (this.allowHostPrefix_) {
    -    if (this.handler_) {
    -      return this.handler_.correctHostPrefix(serverHostPrefix);
    -    }
    -    return serverHostPrefix;
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * Handles the timer that indicates that our backchannel is no longer able to
    - * successfully receive data from the server.
    - * @private
    - */
    -WebChannelBase.prototype.onBackChannelDead_ = function() {
    -  if (goog.isDefAndNotNull(this.deadBackChannelTimerId_)) {
    -    this.deadBackChannelTimerId_ = null;
    -    this.backChannelRequest_.cancel();
    -    this.backChannelRequest_ = null;
    -    this.maybeRetryBackChannel_();
    -    requestStats.notifyStatEvent(requestStats.Stat.BACKCHANNEL_DEAD);
    -  }
    -};
    -
    -
    -/**
    - * Clears the timer that indicates that our backchannel is no longer able to
    - * successfully receive data from the server.
    - * @private
    - */
    -WebChannelBase.prototype.clearDeadBackchannelTimer_ = function() {
    -  if (goog.isDefAndNotNull(this.deadBackChannelTimerId_)) {
    -    goog.global.clearTimeout(this.deadBackChannelTimerId_);
    -    this.deadBackChannelTimerId_ = null;
    -  }
    -};
    -
    -
    -/**
    - * Returns whether or not the given error/status combination is fatal or not.
    - * On fatal errors we immediately close the session rather than retrying the
    - * failed request.
    - * @param {?ChannelRequest.Error} error The error code for the
    - * failed request.
    - * @param {number} statusCode The last HTTP status code.
    - * @return {boolean} Whether or not the error is fatal.
    - * @private
    - */
    -WebChannelBase.isFatalError_ = function(error, statusCode) {
    -  return error == ChannelRequest.Error.UNKNOWN_SESSION_ID ||
    -      (error == ChannelRequest.Error.STATUS &&
    -       statusCode > 0);
    -};
    -
    -
    -/**
    - * @override
    - */
    -WebChannelBase.prototype.onRequestComplete = function(request) {
    -  this.channelDebug_.debug('Request complete');
    -  var type;
    -  if (this.backChannelRequest_ == request) {
    -    this.clearDeadBackchannelTimer_();
    -    this.backChannelRequest_ = null;
    -    type = WebChannelBase.ChannelType_.BACK_CHANNEL;
    -  } else if (this.forwardChannelRequestPool_.hasRequest(request)) {
    -    this.forwardChannelRequestPool_.removeRequest(request);
    -    type = WebChannelBase.ChannelType_.FORWARD_CHANNEL;
    -  } else {
    -    // return if it was an old request from a previous session
    -    return;
    -  }
    -
    -  this.lastStatusCode_ = request.getLastStatusCode();
    -
    -  if (this.state_ == WebChannelBase.State.CLOSED) {
    -    return;
    -  }
    -
    -  if (request.getSuccess()) {
    -    // Yay!
    -    if (type == WebChannelBase.ChannelType_.FORWARD_CHANNEL) {
    -      var size = request.getPostData() ? request.getPostData().length : 0;
    -      requestStats.notifyTimingEvent(size,
    -          goog.now() - request.getRequestStartTime(),
    -          this.forwardChannelRetryCount_);
    -      this.ensureForwardChannel_();
    -      this.onSuccess_();
    -      this.pendingMaps_.length = 0;
    -    } else {  // i.e., back-channel
    -      this.ensureBackChannel_();
    -    }
    -    return;
    -  }
    -  // Else unsuccessful. Fall through.
    -
    -  var lastError = request.getLastError();
    -  if (!WebChannelBase.isFatalError_(lastError, this.lastStatusCode_)) {
    -    // Maybe retry.
    -    this.channelDebug_.debug('Maybe retrying, last error: ' +
    -        ChannelRequest.errorStringFromCode(lastError, this.lastStatusCode_));
    -    if (type == WebChannelBase.ChannelType_.FORWARD_CHANNEL) {
    -      if (this.maybeRetryForwardChannel_(request)) {
    -        return;
    -      }
    -    }
    -    if (type == WebChannelBase.ChannelType_.BACK_CHANNEL) {
    -      if (this.maybeRetryBackChannel_()) {
    -        return;
    -      }
    -    }
    -    // Else exceeded max retries. Fall through.
    -    this.channelDebug_.debug('Exceeded max number of retries');
    -  } else {
    -    // Else fatal error. Fall through and mark the pending maps as failed.
    -    this.channelDebug_.debug('Not retrying due to error type');
    -  }
    -
    -
    -  // Can't save this session. :(
    -  this.channelDebug_.debug('Error: HTTP request failed');
    -  switch (lastError) {
    -    case ChannelRequest.Error.NO_DATA:
    -      this.signalError_(WebChannelBase.Error.NO_DATA);
    -      break;
    -    case ChannelRequest.Error.BAD_DATA:
    -      this.signalError_(WebChannelBase.Error.BAD_DATA);
    -      break;
    -    case ChannelRequest.Error.UNKNOWN_SESSION_ID:
    -      this.signalError_(WebChannelBase.Error.UNKNOWN_SESSION_ID);
    -      break;
    -    default:
    -      this.signalError_(WebChannelBase.Error.REQUEST_FAILED);
    -      break;
    -  }
    -};
    -
    -
    -/**
    - * @param {number} retryCount Number of retries so far.
    - * @return {number} Time in ms before firing next retry request.
    - * @private
    - */
    -WebChannelBase.prototype.getRetryTime_ = function(retryCount) {
    -  var retryTime = this.baseRetryDelayMs_ +
    -      Math.floor(Math.random() * this.retryDelaySeedMs_);
    -  if (!this.isActive()) {
    -    this.channelDebug_.debug('Inactive channel');
    -    retryTime =
    -        retryTime * WebChannelBase.INACTIVE_CHANNEL_RETRY_FACTOR;
    -  }
    -  // Backoff for subsequent retries
    -  retryTime *= retryCount;
    -  return retryTime;
    -};
    -
    -
    -/**
    - * @param {number} baseDelayMs The base part of the retry delay, in ms.
    - * @param {number} delaySeedMs A random delay between 0 and this is added to
    - *     the base part.
    - */
    -WebChannelBase.prototype.setRetryDelay = function(baseDelayMs, delaySeedMs) {
    -  this.baseRetryDelayMs_ = baseDelayMs;
    -  this.retryDelaySeedMs_ = delaySeedMs;
    -};
    -
    -
    -/**
    - * Processes the data returned by the server.
    - * @param {!Array<!Array<?>>} respArray The response array returned
    - *     by the server.
    - * @private
    - */
    -WebChannelBase.prototype.onInput_ = function(respArray) {
    -  var batch = this.handler_ && this.handler_.channelHandleMultipleArrays ?
    -      [] : null;
    -  for (var i = 0; i < respArray.length; i++) {
    -    var nextArray = respArray[i];
    -    this.lastArrayId_ = nextArray[0];
    -    nextArray = nextArray[1];
    -    if (this.state_ == WebChannelBase.State.OPENING) {
    -      if (nextArray[0] == 'c') {
    -        this.sid_ = nextArray[1];
    -        this.hostPrefix_ = this.correctHostPrefix(nextArray[2]);
    -        var negotiatedVersion = nextArray[3];
    -        if (goog.isDefAndNotNull(negotiatedVersion)) {
    -          this.channelVersion_ = negotiatedVersion;
    -        }
    -        this.state_ = WebChannelBase.State.OPENED;
    -        if (this.handler_) {
    -          this.handler_.channelOpened(this);
    -        }
    -        this.backChannelUri_ = this.getBackChannelUri(
    -            this.hostPrefix_, /** @type {string} */ (this.path_));
    -        // Open connection to receive data
    -        this.ensureBackChannel_();
    -      } else if (nextArray[0] == 'stop') {
    -        this.signalError_(WebChannelBase.Error.STOP);
    -      }
    -    } else if (this.state_ == WebChannelBase.State.OPENED) {
    -      if (nextArray[0] == 'stop') {
    -        if (batch && !goog.array.isEmpty(batch)) {
    -          this.handler_.channelHandleMultipleArrays(this, batch);
    -          batch.length = 0;
    -        }
    -        this.signalError_(WebChannelBase.Error.STOP);
    -      } else if (nextArray[0] == 'noop') {
    -        // ignore - noop to keep connection happy
    -      } else {
    -        if (batch) {
    -          batch.push(nextArray);
    -        } else if (this.handler_) {
    -          this.handler_.channelHandleArray(this, nextArray);
    -        }
    -      }
    -      // We have received useful data on the back-channel, so clear its retry
    -      // count. We do this because back-channels by design do not complete
    -      // quickly, so on a flaky connection we could have many fail to complete
    -      // fully but still deliver a lot of data before they fail. We don't want
    -      // to count such failures towards the retry limit, because we don't want
    -      // to give up on a session if we can still receive data.
    -      this.backChannelRetryCount_ = 0;
    -    }
    -  }
    -  if (batch && !goog.array.isEmpty(batch)) {
    -    this.handler_.channelHandleMultipleArrays(this, batch);
    -  }
    -};
    -
    -
    -/**
    - * Helper to ensure the channel is in the expected state.
    - * @param {...number} var_args The channel must be in one of the indicated
    - *     states.
    - * @private
    - */
    -WebChannelBase.prototype.ensureInState_ = function(var_args) {
    -  goog.asserts.assert(goog.array.contains(arguments, this.state_),
    -      'Unexpected channel state: %s', this.state_);
    -};
    -
    -
    -/**
    - * Signals an error has occurred.
    - * @param {WebChannelBase.Error} error The error code for the failure.
    - * @private
    - */
    -WebChannelBase.prototype.signalError_ = function(error) {
    -  this.channelDebug_.info('Error code ' + error);
    -  if (error == WebChannelBase.Error.REQUEST_FAILED) {
    -    // Create a separate Internet connection to check
    -    // if it's a server error or user's network error.
    -    var imageUri = null;
    -    if (this.handler_) {
    -      imageUri = this.handler_.getNetworkTestImageUri(this);
    -    }
    -    netUtils.testNetwork(goog.bind(this.testNetworkCallback_, this), imageUri);
    -  } else {
    -    requestStats.notifyStatEvent(requestStats.Stat.ERROR_OTHER);
    -  }
    -  this.onError_(error);
    -};
    -
    -
    -/**
    - * Callback for netUtils.testNetwork during error handling.
    - * @param {boolean} networkUp Whether the network is up.
    - * @private
    - */
    -WebChannelBase.prototype.testNetworkCallback_ = function(networkUp) {
    -  if (networkUp) {
    -    this.channelDebug_.info('Successfully pinged google.com');
    -    requestStats.notifyStatEvent(requestStats.Stat.ERROR_OTHER);
    -  } else {
    -    this.channelDebug_.info('Failed to ping google.com');
    -    requestStats.notifyStatEvent(requestStats.Stat.ERROR_NETWORK);
    -    // We call onError_ here instead of signalError_ because the latter just
    -    // calls notifyStatEvent, and we don't want to have another stat event.
    -    this.onError_(WebChannelBase.Error.NETWORK);
    -  }
    -};
    -
    -
    -/**
    - * Called when messages have been successfully sent from the queue.
    - * @private
    - */
    -WebChannelBase.prototype.onSuccess_ = function() {
    -  // TODO(user): optimize for request pool (>1)
    -  if (this.handler_) {
    -    this.handler_.channelSuccess(this, this.pendingMaps_);
    -  }
    -};
    -
    -
    -/**
    - * Called when we've determined the final error for a channel. It closes the
    - * notifiers the handler of the error and closes the channel.
    - * @param {WebChannelBase.Error} error  The error code for the failure.
    - * @private
    - */
    -WebChannelBase.prototype.onError_ = function(error) {
    -  this.channelDebug_.debug('HttpChannel: error - ' + error);
    -  this.state_ = WebChannelBase.State.CLOSED;
    -  if (this.handler_) {
    -    this.handler_.channelError(this, error);
    -  }
    -  this.onClose_();
    -  this.cancelRequests_();
    -};
    -
    -
    -/**
    - * Called when the channel has been closed. It notifiers the handler of the
    - * event, and reports any pending or undelivered maps.
    - * @private
    - */
    -WebChannelBase.prototype.onClose_ = function() {
    -  this.state_ = WebChannelBase.State.CLOSED;
    -  this.lastStatusCode_ = -1;
    -  if (this.handler_) {
    -    if (this.pendingMaps_.length == 0 && this.outgoingMaps_.length == 0) {
    -      this.handler_.channelClosed(this);
    -    } else {
    -      this.channelDebug_.debug('Number of undelivered maps' +
    -          ', pending: ' + this.pendingMaps_.length +
    -          ', outgoing: ' + this.outgoingMaps_.length);
    -
    -      var copyOfPendingMaps = goog.array.clone(this.pendingMaps_);
    -      var copyOfUndeliveredMaps = goog.array.clone(this.outgoingMaps_);
    -      this.pendingMaps_.length = 0;
    -      this.outgoingMaps_.length = 0;
    -
    -      this.handler_.channelClosed(this, copyOfPendingMaps,
    -          copyOfUndeliveredMaps);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * @override
    - */
    -WebChannelBase.prototype.getForwardChannelUri = function(path) {
    -  var uri = this.createDataUri(null, path);
    -  this.channelDebug_.debug('GetForwardChannelUri: ' + uri);
    -  return uri;
    -};
    -
    -
    -/**
    - * @override
    - */
    -WebChannelBase.prototype.getConnectionState = function() {
    -  return this.ConnState_;
    -};
    -
    -
    -/**
    - * @override
    - */
    -WebChannelBase.prototype.getBackChannelUri = function(hostPrefix, path) {
    -  var uri = this.createDataUri(this.shouldUseSecondaryDomains() ?
    -      hostPrefix : null, path);
    -  this.channelDebug_.debug('GetBackChannelUri: ' + uri);
    -  return uri;
    -};
    -
    -
    -/**
    - * @override
    - */
    -WebChannelBase.prototype.createDataUri =
    -    function(hostPrefix, path, opt_overridePort) {
    -  var uri = goog.Uri.parse(path);
    -  var uriAbsolute = (uri.getDomain() != '');
    -  if (uriAbsolute) {
    -    if (hostPrefix) {
    -      uri.setDomain(hostPrefix + '.' + uri.getDomain());
    -    }
    -
    -    uri.setPort(opt_overridePort || uri.getPort());
    -  } else {
    -    var locationPage = goog.global.location;
    -    var hostName;
    -    if (hostPrefix) {
    -      hostName = hostPrefix + '.' + locationPage.hostname;
    -    } else {
    -      hostName = locationPage.hostname;
    -    }
    -
    -    var port = opt_overridePort || locationPage.port;
    -
    -    uri = goog.Uri.create(locationPage.protocol, null, hostName, port, path);
    -  }
    -
    -  if (this.extraParams_) {
    -    goog.object.forEach(this.extraParams_, function(value, key) {
    -      uri.setParameterValue(key, value);
    -    });
    -  }
    -
    -  // Add the protocol version to the URI.
    -  uri.setParameterValue('VER', this.channelVersion_);
    -
    -  // Add the reconnect parameters.
    -  this.addAdditionalParams_(uri);
    -
    -  return uri;
    -};
    -
    -
    -/**
    - * @override
    - */
    -WebChannelBase.prototype.createXhrIo = function(hostPrefix) {
    -  if (hostPrefix && !this.supportsCrossDomainXhrs_) {
    -    throw Error('Can\'t create secondary domain capable XhrIo object.');
    -  }
    -  var xhr = new goog.net.XhrIo();
    -  xhr.setWithCredentials(this.supportsCrossDomainXhrs_);
    -  return xhr;
    -};
    -
    -
    -/**
    - * @override
    - */
    -WebChannelBase.prototype.isActive = function() {
    -  return !!this.handler_ && this.handler_.isActive(this);
    -};
    -
    -
    -/**
    - * @override
    - */
    -WebChannelBase.prototype.shouldUseSecondaryDomains = function() {
    -  return this.supportsCrossDomainXhrs_;
    -};
    -
    -
    -/**
    - * A LogSaver that can be used to accumulate all the debug logs so they
    - * can be sent to the server when a problem is detected.
    - */
    -WebChannelBase.LogSaver = {};
    -
    -
    -/**
    - * Buffer for accumulating the debug log
    - * @type {goog.structs.CircularBuffer}
    - * @private
    - */
    -WebChannelBase.LogSaver.buffer_ = new goog.structs.CircularBuffer(1000);
    -
    -
    -/**
    - * Whether we're currently accumulating the debug log.
    - * @type {boolean}
    - * @private
    - */
    -WebChannelBase.LogSaver.enabled_ = false;
    -
    -
    -/**
    - * Formatter for saving logs.
    - * @type {goog.debug.Formatter}
    - * @private
    - */
    -WebChannelBase.LogSaver.formatter_ = new goog.debug.TextFormatter();
    -
    -
    -/**
    - * Returns whether the LogSaver is enabled.
    - * @return {boolean} Whether saving is enabled or disabled.
    - */
    -WebChannelBase.LogSaver.isEnabled = function() {
    -  return WebChannelBase.LogSaver.enabled_;
    -};
    -
    -
    -/**
    - * Enables of disables the LogSaver.
    - * @param {boolean} enable Whether to enable or disable saving.
    - */
    -WebChannelBase.LogSaver.setEnabled = function(enable) {
    -  if (enable == WebChannelBase.LogSaver.enabled_) {
    -    return;
    -  }
    -
    -  var fn = WebChannelBase.LogSaver.addLogRecord;
    -  var logger = goog.log.getLogger('goog.net');
    -  if (enable) {
    -    goog.log.addHandler(logger, fn);
    -  } else {
    -    goog.log.removeHandler(logger, fn);
    -  }
    -};
    -
    -
    -/**
    - * Adds a log record.
    - * @param {goog.log.LogRecord} logRecord the LogRecord.
    - */
    -WebChannelBase.LogSaver.addLogRecord = function(logRecord) {
    -  WebChannelBase.LogSaver.buffer_.add(
    -      WebChannelBase.LogSaver.formatter_.formatRecord(logRecord));
    -};
    -
    -
    -/**
    - * Returns the log as a single string.
    - * @return {string} The log as a single string.
    - */
    -WebChannelBase.LogSaver.getBuffer = function() {
    -  return WebChannelBase.LogSaver.buffer_.getValues().join('');
    -};
    -
    -
    -/**
    - * Clears the buffer
    - */
    -WebChannelBase.LogSaver.clearBuffer = function() {
    -  WebChannelBase.LogSaver.buffer_.clear();
    -};
    -
    -
    -
    -/**
    - * Abstract base class for the channel handler
    - * @constructor
    - * @struct
    - */
    -WebChannelBase.Handler = function() {};
    -
    -
    -/**
    - * Callback handler for when a batch of response arrays is received from the
    - * server. When null, batched dispatching is disabled.
    - * @type {?function(!WebChannelBase, !Array<!Array<?>>)}
    - */
    -WebChannelBase.Handler.prototype.channelHandleMultipleArrays = null;
    -
    -
    -/**
    - * Whether it's okay to make a request to the server. A handler can return
    - * false if the channel should fail. For example, if the user has logged out,
    - * the handler may want all requests to fail immediately.
    - * @param {WebChannelBase} channel The channel.
    - * @return {WebChannelBase.Error} An error code. The code should
    - * return WebChannelBase.Error.OK to indicate it's okay. Any other
    - * error code will cause a failure.
    - */
    -WebChannelBase.Handler.prototype.okToMakeRequest = function(channel) {
    -  return WebChannelBase.Error.OK;
    -};
    -
    -
    -/**
    - * Indicates the WebChannel has successfully negotiated with the server
    - * and can now send and receive data.
    - * @param {WebChannelBase} channel The channel.
    - */
    -WebChannelBase.Handler.prototype.channelOpened = function(channel) {
    -};
    -
    -
    -/**
    - * New input is available for the application to process.
    - *
    - * @param {WebChannelBase} channel The channel.
    - * @param {Array<?>} array The data array.
    - */
    -WebChannelBase.Handler.prototype.channelHandleArray = function(channel, array) {
    -};
    -
    -
    -/**
    - * Indicates maps were successfully sent on the channel.
    - *
    - * @param {WebChannelBase} channel The channel.
    - * @param {Array<Wire.QueuedMap>} deliveredMaps The
    - *     array of maps that have been delivered to the server. This is a direct
    - *     reference to the internal array, so a copy should be made
    - *     if the caller desires a reference to the data.
    - */
    -WebChannelBase.Handler.prototype.channelSuccess =
    -    function(channel, deliveredMaps) {
    -};
    -
    -
    -/**
    - * Indicates an error occurred on the WebChannel.
    - *
    - * @param {WebChannelBase} channel The channel.
    - * @param {WebChannelBase.Error} error The error code.
    - */
    -WebChannelBase.Handler.prototype.channelError = function(channel, error) {
    -};
    -
    -
    -/**
    - * Indicates the WebChannel is closed. Also notifies about which maps,
    - * if any, that may not have been delivered to the server.
    - * @param {WebChannelBase} channel The channel.
    - * @param {Array<Wire.QueuedMap>=} opt_pendingMaps The
    - *     array of pending maps, which may or may not have been delivered to the
    - *     server.
    - * @param {Array<Wire.QueuedMap>=} opt_undeliveredMaps
    - *     The array of undelivered maps, which have definitely not been delivered
    - *     to the server.
    - */
    -WebChannelBase.Handler.prototype.channelClosed =
    -    function(channel, opt_pendingMaps, opt_undeliveredMaps) {
    -};
    -
    -
    -/**
    - * Gets any parameters that should be added at the time another connection is
    - * made to the server.
    - * @param {WebChannelBase} channel The channel.
    - * @return {!Object} Extra parameter keys and values to add to the requests.
    - */
    -WebChannelBase.Handler.prototype.getAdditionalParams = function(channel) {
    -  return {};
    -};
    -
    -
    -/**
    - * Gets the URI of an image that can be used to test network connectivity.
    - * @param {WebChannelBase} channel The channel.
    - * @return {goog.Uri?} A custom URI to load for the network test.
    - */
    -WebChannelBase.Handler.prototype.getNetworkTestImageUri = function(channel) {
    -  return null;
    -};
    -
    -
    -/**
    - * Gets whether this channel is currently active. This is used to determine the
    - * length of time to wait before retrying.
    - * @param {WebChannelBase} channel The channel.
    - * @return {boolean} Whether the channel is currently active.
    - */
    -WebChannelBase.Handler.prototype.isActive = function(channel) {
    -  return true;
    -};
    -
    -
    -/**
    - * Called by the channel if enumeration of the map throws an exception.
    - * @param {WebChannelBase} channel The channel.
    - * @param {Object} map The map that can't be enumerated.
    - */
    -WebChannelBase.Handler.prototype.badMapError = function(channel, map) {
    -};
    -
    -
    -/**
    - * Allows the handler to override a host prefix provided by the server. Will
    - * be called whenever the channel has received such a prefix and is considering
    - * its use.
    - * @param {?string} serverHostPrefix The host prefix provided by the server.
    - * @return {?string} The host prefix the client should use.
    - */
    -WebChannelBase.Handler.prototype.correctHostPrefix =
    -    function(serverHostPrefix) {
    -  return serverHostPrefix;
    -};
    -});  // goog.scope
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/webchannelbase_test.html b/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/webchannelbase_test.html
    deleted file mode 100644
    index 58918a60d40..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/webchannelbase_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.labs.net.webChannel.WebChannelBase</title>
    -<script src="../../../base.js"></script>
    -</head>
    -<body>
    -<script>
    -goog.require('goog.labs.net.webChannel.webChannelBaseTest');
    -</script>
    -<div id="debug" style="font-size: small"></div>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/webchannelbase_test.js b/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/webchannelbase_test.js
    deleted file mode 100644
    index 7b370fe67da..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/webchannelbase_test.js
    +++ /dev/null
    @@ -1,1485 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.labs.net.webChannel.WebChannelBase.
    - * @suppress {accessControls} Private methods are accessed for test purposes.
    - *
    - */
    -
    -
    -goog.provide('goog.labs.net.webChannel.webChannelBaseTest');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.functions');
    -goog.require('goog.json');
    -goog.require('goog.labs.net.webChannel.ChannelRequest');
    -goog.require('goog.labs.net.webChannel.ForwardChannelRequestPool');
    -goog.require('goog.labs.net.webChannel.WebChannelBase');
    -goog.require('goog.labs.net.webChannel.WebChannelBaseTransport');
    -goog.require('goog.labs.net.webChannel.WebChannelDebug');
    -goog.require('goog.labs.net.webChannel.Wire');
    -goog.require('goog.labs.net.webChannel.netUtils');
    -goog.require('goog.labs.net.webChannel.requestStats');
    -goog.require('goog.labs.net.webChannel.requestStats.Stat');
    -goog.require('goog.structs.Map');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.asserts');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.labs.net.webChannel.webChannelBaseTest');
    -
    -
    -/**
    - * Delay between a network failure and the next network request.
    - */
    -var RETRY_TIME = 1000;
    -
    -
    -/**
    - * A really long time - used to make sure no more timeouts will fire.
    - */
    -var ALL_DAY_MS = 1000 * 60 * 60 * 24;
    -
    -var stubs = new goog.testing.PropertyReplacer();
    -
    -var channel;
    -var deliveredMaps;
    -var handler;
    -var mockClock;
    -var gotError;
    -var numStatEvents;
    -var lastStatEvent;
    -var numTimingEvents;
    -var lastPostSize;
    -var lastPostRtt;
    -var lastPostRetryCount;
    -
    -// Set to true to see the channel debug output in the browser window.
    -var debug = false;
    -// Debug message to print out when debug is true.
    -var debugMessage = '';
    -
    -function debugToWindow(message) {
    -  if (debug) {
    -    debugMessage += message + '<br>';
    -    goog.dom.getElement('debug').innerHTML = debugMessage;
    -  }
    -}
    -
    -
    -/**
    - * Stubs goog.labs.net.webChannel.netUtils to always time out. It maintains the
    - * contract given by goog.labs.net.webChannel.netUtils.testNetwork, but always
    - * times out (calling callback(false)).
    - *
    - * stubNetUtils should be called in tests that require it before
    - * a call to testNetwork happens. It is reset at tearDown.
    - */
    -function stubNetUtils() {
    -  stubs.set(goog.labs.net.webChannel.netUtils, 'testLoadImage',
    -      function(url, timeout, callback) {
    -        goog.Timer.callOnce(goog.partial(callback, false), timeout);
    -      });
    -}
    -
    -
    -/**
    - * Stubs goog.labs.net.webChannel.ForwardChannelRequestPool.isSpdyEnabled_
    - * to manage the max pool size for the forward channel.
    - *
    - * @param {boolean} spdyEnabled Whether SPDY is enabled for the test.
    - */
    -function stubSpdyCheck(spdyEnabled) {
    -  stubs.set(goog.labs.net.webChannel.ForwardChannelRequestPool,
    -      'isSpdyEnabled_',
    -      function() {
    -        return spdyEnabled;
    -      });
    -}
    -
    -
    -
    -/**
    - * Mock ChannelRequest.
    - * @constructor
    - * @struct
    - * @final
    - */
    -var MockChannelRequest = function(channel, channelDebug, opt_sessionId,
    -    opt_requestId, opt_retryId) {
    -  this.channel_ = channel;
    -  this.channelDebug_ = channelDebug;
    -  this.sessionId_ = opt_sessionId;
    -  this.requestId_ = opt_requestId;
    -  this.successful_ = true;
    -  this.lastError_ = null;
    -  this.lastStatusCode_ = 200;
    -
    -  // For debugging, keep track of whether this is a back or forward channel.
    -  this.isBack = !!(opt_requestId == 'rpc');
    -  this.isForward = !this.isBack;
    -};
    -
    -MockChannelRequest.prototype.postData_ = null;
    -
    -MockChannelRequest.prototype.requestStartTime_ = null;
    -
    -MockChannelRequest.prototype.setExtraHeaders = function(extraHeaders) {};
    -
    -MockChannelRequest.prototype.setTimeout = function(timeout) {};
    -
    -MockChannelRequest.prototype.setReadyStateChangeThrottle =
    -    function(throttle) {};
    -
    -MockChannelRequest.prototype.xmlHttpPost = function(uri, postData,
    -    decodeChunks) {
    -  this.channelDebug_.debug('---> POST: ' + uri + ', ' + postData + ', ' +
    -      decodeChunks);
    -  this.postData_ = postData;
    -  this.requestStartTime_ = goog.now();
    -};
    -
    -MockChannelRequest.prototype.xmlHttpGet = function(uri, decodeChunks,
    -    opt_noClose) {
    -  this.channelDebug_.debug('<--- GET: ' + uri + ', ' + decodeChunks + ', ' +
    -      opt_noClose);
    -  this.requestStartTime_ = goog.now();
    -};
    -
    -MockChannelRequest.prototype.sendUsingImgTag = function(uri) {
    -  this.requestStartTime_ = goog.now();
    -};
    -
    -MockChannelRequest.prototype.cancel = function() {
    -  this.successful_ = false;
    -};
    -
    -MockChannelRequest.prototype.getSuccess = function() {
    -  return this.successful_;
    -};
    -
    -MockChannelRequest.prototype.getLastError = function() {
    -  return this.lastError_;
    -};
    -
    -MockChannelRequest.prototype.getLastStatusCode = function() {
    -  return this.lastStatusCode_;
    -};
    -
    -MockChannelRequest.prototype.getSessionId = function() {
    -  return this.sessionId_;
    -};
    -
    -MockChannelRequest.prototype.getRequestId = function() {
    -  return this.requestId_;
    -};
    -
    -MockChannelRequest.prototype.getPostData = function() {
    -  return this.postData_;
    -};
    -
    -MockChannelRequest.prototype.getRequestStartTime = function() {
    -  return this.requestStartTime_;
    -};
    -
    -MockChannelRequest.prototype.getXhr = function() {
    -  return null;
    -};
    -
    -
    -function shouldRunTests() {
    -  return goog.labs.net.webChannel.ChannelRequest.supportsXhrStreaming();
    -}
    -
    -
    -/**
    - * @suppress {invalidCasts} The cast from MockChannelRequest to
    - * ChannelRequest is invalid and will not compile.
    - */
    -function setUpPage() {
    -  // Use our MockChannelRequests instead of the real ones.
    -  goog.labs.net.webChannel.ChannelRequest.createChannelRequest = function(
    -      channel, channelDebug, opt_sessionId, opt_requestId, opt_retryId) {
    -    return /** @type {!goog.labs.net.webChannel.ChannelRequest} */ (
    -        new MockChannelRequest(channel, channelDebug, opt_sessionId,
    -            opt_requestId, opt_retryId));
    -  };
    -
    -  // Mock out the stat notification code.
    -  goog.labs.net.webChannel.requestStats.notifyStatEvent = function(
    -      stat) {
    -    numStatEvents++;
    -    lastStatEvent = stat;
    -  };
    -
    -  goog.labs.net.webChannel.requestStats.notifyTimingEvent = function(
    -      size, rtt, retries) {
    -    numTimingEvents++;
    -    lastPostSize = size;
    -    lastPostRtt = rtt;
    -    lastPostRetryCount = retries;
    -  };
    -}
    -
    -function setUp() {
    -  numTimingEvents = 0;
    -  lastPostSize = null;
    -  lastPostRtt = null;
    -  lastPostRetryCount = null;
    -
    -  mockClock = new goog.testing.MockClock(true);
    -  channel = new goog.labs.net.webChannel.WebChannelBase('1');
    -  gotError = false;
    -
    -  handler = new goog.labs.net.webChannel.WebChannelBase.Handler();
    -  handler.channelOpened = function() {};
    -  handler.channelError = function(channel, error) {
    -    gotError = true;
    -  };
    -  handler.channelSuccess = function(channel, maps) {
    -    deliveredMaps = goog.array.clone(maps);
    -  };
    -
    -  /**
    -   * @suppress {checkTypes} The callback function type declaration is skipped.
    -   */
    -  handler.channelClosed = function(
    -      channel, opt_pendingMaps, opt_undeliveredMaps) {
    -    // Mock out the handler, and let it set a formatted user readable string
    -    // of the undelivered maps which we can use when verifying our assertions.
    -    if (opt_pendingMaps) {
    -      handler.pendingMapsString = formatArrayOfMaps(opt_pendingMaps);
    -    }
    -    if (opt_undeliveredMaps) {
    -      handler.undeliveredMapsString = formatArrayOfMaps(opt_undeliveredMaps);
    -    }
    -  };
    -  handler.channelHandleMultipleArrays = function() {};
    -  handler.channelHandleArray = function() {};
    -
    -  channel.setHandler(handler);
    -
    -  // Provide a predictable retry time for testing.
    -  channel.getRetryTime_ = function(retryCount) {
    -    return RETRY_TIME;
    -  };
    -
    -  var channelDebug = new goog.labs.net.webChannel.WebChannelDebug();
    -  channelDebug.debug = function(message) {
    -    debugToWindow(message);
    -  };
    -  channel.setChannelDebug(channelDebug);
    -
    -  numStatEvents = 0;
    -  lastStatEvent = null;
    -}
    -
    -
    -function tearDown() {
    -  mockClock.dispose();
    -  stubs.reset();
    -  debugToWindow('<hr>');
    -}
    -
    -
    -function getSingleForwardRequest() {
    -  var pool = channel.forwardChannelRequestPool_;
    -  if (!pool.hasPendingRequest()) {
    -    return null;
    -  }
    -  return pool.request_ || pool.requestPool_.getValues()[0];
    -}
    -
    -
    -/**
    - * Helper function to return a formatted string representing an array of maps.
    - */
    -function formatArrayOfMaps(arrayOfMaps) {
    -  var result = [];
    -  for (var i = 0; i < arrayOfMaps.length; i++) {
    -    var map = arrayOfMaps[i];
    -    var keys = map.map.getKeys();
    -    for (var j = 0; j < keys.length; j++) {
    -      var tmp = keys[j] + ':' + map.map.get(keys[j]) + (map.context ?
    -          ':' + map.context : '');
    -      result.push(tmp);
    -    }
    -  }
    -  return result.join(', ');
    -}
    -
    -
    -function testFormatArrayOfMaps() {
    -  // This function is used in a non-trivial test, so let's verify that it works.
    -  var map1 = new goog.structs.Map();
    -  map1.set('k1', 'v1');
    -  map1.set('k2', 'v2');
    -  var map2 = new goog.structs.Map();
    -  map2.set('k3', 'v3');
    -  var map3 = new goog.structs.Map();
    -  map3.set('k4', 'v4');
    -  map3.set('k5', 'v5');
    -  map3.set('k6', 'v6');
    -
    -  // One map.
    -  var a = [];
    -  a.push(new goog.labs.net.webChannel.Wire.QueuedMap(0, map1));
    -  assertEquals('k1:v1, k2:v2',
    -      formatArrayOfMaps(a));
    -
    -  // Many maps.
    -  var b = [];
    -  b.push(new goog.labs.net.webChannel.Wire.QueuedMap(0, map1));
    -  b.push(new goog.labs.net.webChannel.Wire.QueuedMap(0, map2));
    -  b.push(new goog.labs.net.webChannel.Wire.QueuedMap(0, map3));
    -  assertEquals('k1:v1, k2:v2, k3:v3, k4:v4, k5:v5, k6:v6',
    -      formatArrayOfMaps(b));
    -
    -  // One map with a context.
    -  var c = [];
    -  c.push(new goog.labs.net.webChannel.Wire.QueuedMap(
    -      0, map1, new String('c1')));
    -  assertEquals('k1:v1:c1, k2:v2:c1',
    -      formatArrayOfMaps(c));
    -}
    -
    -
    -/**
    - * @param {number=} opt_serverVersion
    - * @param {string=} opt_hostPrefix
    - * @param {string=} opt_uriPrefix
    - * @param {boolean=} opt_spdyEnabled
    - */
    -function connectForwardChannel(
    -    opt_serverVersion, opt_hostPrefix, opt_uriPrefix, opt_spdyEnabled) {
    -  stubSpdyCheck(!!opt_spdyEnabled);
    -  var uriPrefix = opt_uriPrefix || '';
    -  channel.connect(uriPrefix + '/test', uriPrefix + '/bind', null);
    -  mockClock.tick(0);
    -  completeTestConnection();
    -  completeForwardChannel(opt_serverVersion, opt_hostPrefix);
    -}
    -
    -
    -/**
    - * @param {number=} opt_serverVersion
    - * @param {string=} opt_hostPrefix
    - * @param {string=} opt_uriPrefix
    - * @param {boolean=} opt_spdyEnabled
    - */
    -function connect(opt_serverVersion, opt_hostPrefix, opt_uriPrefix,
    -    opt_spdyEnabled) {
    -  connectForwardChannel(opt_serverVersion, opt_hostPrefix, opt_uriPrefix,
    -      opt_spdyEnabled);
    -  completeBackChannel();
    -}
    -
    -
    -function disconnect() {
    -  channel.disconnect();
    -  mockClock.tick(0);
    -}
    -
    -
    -function completeTestConnection() {
    -  completeForwardTestConnection();
    -  completeBackTestConnection();
    -  assertEquals(goog.labs.net.webChannel.WebChannelBase.State.OPENING,
    -      channel.getState());
    -}
    -
    -
    -function completeForwardTestConnection() {
    -  channel.connectionTest_.onRequestData(
    -      channel.connectionTest_.request_,
    -      '["b"]');
    -  channel.connectionTest_.onRequestComplete(
    -      channel.connectionTest_.request_);
    -  mockClock.tick(0);
    -}
    -
    -
    -function completeBackTestConnection() {
    -  channel.connectionTest_.onRequestData(
    -      channel.connectionTest_.request_,
    -      '11111');
    -  mockClock.tick(0);
    -}
    -
    -
    -/**
    - * @param {number=} opt_serverVersion
    - * @param {string=} opt_hostPrefix
    - */
    -function completeForwardChannel(opt_serverVersion, opt_hostPrefix) {
    -  var responseData = '[[0,["c","1234567890ABCDEF",' +
    -      (opt_hostPrefix ? '"' + opt_hostPrefix + '"' : 'null') +
    -      (opt_serverVersion ? ',' + opt_serverVersion : '') +
    -      ']]]';
    -  channel.onRequestData(
    -      getSingleForwardRequest(),
    -      responseData);
    -  channel.onRequestComplete(
    -      getSingleForwardRequest());
    -  mockClock.tick(0);
    -}
    -
    -
    -function completeBackChannel() {
    -  channel.onRequestData(
    -      channel.backChannelRequest_,
    -      '[[1,["foo"]]]');
    -  channel.onRequestComplete(
    -      channel.backChannelRequest_);
    -  mockClock.tick(0);
    -}
    -
    -
    -function responseDone() {
    -  channel.onRequestData(
    -      getSingleForwardRequest(),
    -      '[1,0,0]');  // mock data
    -  channel.onRequestComplete(
    -      getSingleForwardRequest());
    -  mockClock.tick(0);
    -}
    -
    -
    -/**
    - *
    - * @param {number=} opt_lastArrayIdSentFromServer
    - * @param {number=} opt_outstandingDataSize
    - */
    -function responseNoBackchannel(
    -    opt_lastArrayIdSentFromServer, opt_outstandingDataSize) {
    -  var responseData = goog.json.serialize(
    -      [0, opt_lastArrayIdSentFromServer, opt_outstandingDataSize]);
    -  channel.onRequestData(
    -      getSingleForwardRequest(),
    -      responseData);
    -  channel.onRequestComplete(
    -      getSingleForwardRequest());
    -  mockClock.tick(0);
    -}
    -
    -function response(lastArrayIdSentFromServer, outstandingDataSize) {
    -  var responseData = goog.json.serialize(
    -      [1, lastArrayIdSentFromServer, outstandingDataSize]);
    -  channel.onRequestData(
    -      getSingleForwardRequest(),
    -      responseData
    -  );
    -  channel.onRequestComplete(
    -      getSingleForwardRequest());
    -  mockClock.tick(0);
    -}
    -
    -
    -function receive(data) {
    -  channel.onRequestData(
    -      channel.backChannelRequest_,
    -      '[[1,' + data + ']]');
    -  channel.onRequestComplete(
    -      channel.backChannelRequest_);
    -  mockClock.tick(0);
    -}
    -
    -
    -function responseTimeout() {
    -  getSingleForwardRequest().lastError_ =
    -      goog.labs.net.webChannel.ChannelRequest.Error.TIMEOUT;
    -  getSingleForwardRequest().successful_ = false;
    -  channel.onRequestComplete(
    -      getSingleForwardRequest());
    -  mockClock.tick(0);
    -}
    -
    -
    -/**
    - * @param {number=} opt_statusCode
    - */
    -function responseRequestFailed(opt_statusCode) {
    -  getSingleForwardRequest().lastError_ =
    -      goog.labs.net.webChannel.ChannelRequest.Error.STATUS;
    -  getSingleForwardRequest().lastStatusCode_ =
    -      opt_statusCode || 503;
    -  getSingleForwardRequest().successful_ = false;
    -  channel.onRequestComplete(
    -      getSingleForwardRequest());
    -  mockClock.tick(0);
    -}
    -
    -
    -function responseUnknownSessionId() {
    -  getSingleForwardRequest().lastError_ =
    -      goog.labs.net.webChannel.ChannelRequest.Error.UNKNOWN_SESSION_ID;
    -  getSingleForwardRequest().successful_ = false;
    -  channel.onRequestComplete(
    -      getSingleForwardRequest());
    -  mockClock.tick(0);
    -}
    -
    -
    -/**
    - * @param {string} key
    - * @param {string} value
    - * @param {string=} opt_context
    - */
    -function sendMap(key, value, opt_context) {
    -  var map = new goog.structs.Map();
    -  map.set(key, value);
    -  channel.sendMap(map, opt_context);
    -  mockClock.tick(0);
    -}
    -
    -
    -function hasForwardChannel() {
    -  return !!getSingleForwardRequest();
    -}
    -
    -
    -function hasBackChannel() {
    -  return !!channel.backChannelRequest_;
    -}
    -
    -
    -function hasDeadBackChannelTimer() {
    -  return goog.isDefAndNotNull(channel.deadBackChannelTimerId_);
    -}
    -
    -
    -function assertHasForwardChannel() {
    -  assertTrue('Forward channel missing.', hasForwardChannel());
    -}
    -
    -
    -function assertHasBackChannel() {
    -  assertTrue('Back channel missing.', hasBackChannel());
    -}
    -
    -
    -function testConnect() {
    -  connect();
    -  assertEquals(goog.labs.net.webChannel.WebChannelBase.State.OPENED,
    -      channel.getState());
    -  // If the server specifies no version, the client assumes the latest version
    -  assertEquals(goog.labs.net.webChannel.Wire.LATEST_CHANNEL_VERSION,
    -               channel.channelVersion_);
    -  assertFalse(channel.isBuffered());
    -}
    -
    -function testConnect_backChannelEstablished() {
    -  connect();
    -  assertHasBackChannel();
    -}
    -
    -function testConnect_withServerHostPrefix() {
    -  connect(undefined, 'serverHostPrefix');
    -  assertEquals('serverHostPrefix', channel.hostPrefix_);
    -}
    -
    -function testConnect_withClientHostPrefix() {
    -  handler.correctHostPrefix = function(hostPrefix) {
    -    return 'clientHostPrefix';
    -  };
    -  connect();
    -  assertEquals('clientHostPrefix', channel.hostPrefix_);
    -}
    -
    -function testConnect_overrideServerHostPrefix() {
    -  handler.correctHostPrefix = function(hostPrefix) {
    -    return 'clientHostPrefix';
    -  };
    -  connect(undefined, 'serverHostPrefix');
    -  assertEquals('clientHostPrefix', channel.hostPrefix_);
    -}
    -
    -function testConnect_withServerVersion() {
    -  connect(8);
    -  assertEquals(8, channel.channelVersion_);
    -}
    -
    -function testConnect_notOkToMakeRequestForTest() {
    -  handler.okToMakeRequest = goog.functions.constant(
    -      goog.labs.net.webChannel.WebChannelBase.Error.NETWORK);
    -  channel.connect('/test', '/bind', null);
    -  mockClock.tick(0);
    -  assertEquals(goog.labs.net.webChannel.WebChannelBase.State.CLOSED,
    -               channel.getState());
    -}
    -
    -function testConnect_notOkToMakeRequestForBind() {
    -  channel.connect('/test', '/bind', null);
    -  mockClock.tick(0);
    -  completeTestConnection();
    -  handler.okToMakeRequest = goog.functions.constant(
    -      goog.labs.net.webChannel.WebChannelBase.Error.NETWORK);
    -  completeForwardChannel();
    -  assertEquals(goog.labs.net.webChannel.WebChannelBase.State.CLOSED,
    -               channel.getState());
    -}
    -
    -
    -function testSendMap() {
    -  connect();
    -  sendMapOnce();
    -}
    -
    -
    -function testSendMapWithSpdyEnabled() {
    -  connect(undefined, undefined, undefined, true);
    -  sendMapOnce();
    -}
    -
    -
    -function sendMapOnce() {
    -  assertEquals(1, numTimingEvents);
    -  sendMap('foo', 'bar');
    -  responseDone();
    -  assertEquals(2, numTimingEvents);
    -  assertEquals('foo:bar', formatArrayOfMaps(deliveredMaps));
    -}
    -
    -
    -function testSendMap_twice() {
    -  connect();
    -  sendMapTwice();
    -}
    -
    -
    -function testSendMap_twiceWithSpdyEnabled() {
    -  connect(undefined, undefined, undefined, true);
    -  sendMapTwice();
    -}
    -
    -
    -function sendMapTwice() {
    -  sendMap('foo1', 'bar1');
    -  responseDone();
    -  assertEquals('foo1:bar1', formatArrayOfMaps(deliveredMaps));
    -  sendMap('foo2', 'bar2');
    -  responseDone();
    -  assertEquals('foo2:bar2', formatArrayOfMaps(deliveredMaps));
    -}
    -
    -
    -function testSendMap_andReceive() {
    -  connect();
    -  sendMap('foo', 'bar');
    -  responseDone();
    -  receive('["the server reply"]');
    -}
    -
    -
    -function testReceive() {
    -  connect();
    -  receive('["message from server"]');
    -  assertHasBackChannel();
    -}
    -
    -
    -function testReceive_twice() {
    -  connect();
    -  receive('["message one from server"]');
    -  receive('["message two from server"]');
    -  assertHasBackChannel();
    -}
    -
    -
    -function testReceive_andSendMap() {
    -  connect();
    -  receive('["the server reply"]');
    -  sendMap('foo', 'bar');
    -  responseDone();
    -  assertHasBackChannel();
    -}
    -
    -
    -function testBackChannelRemainsEstablished_afterSingleSendMap() {
    -  connect();
    -
    -  sendMap('foo', 'bar');
    -  responseDone();
    -  receive('["ack"]');
    -
    -  assertHasBackChannel();
    -}
    -
    -
    -function testBackChannelRemainsEstablished_afterDoubleSendMap() {
    -  connect();
    -
    -  sendMap('foo1', 'bar1');
    -  sendMap('foo2', 'bar2');
    -  responseDone();
    -  receive('["ack"]');
    -
    -  // This assertion would fail prior to CL 13302660.
    -  assertHasBackChannel();
    -}
    -
    -
    -function testTimingEvent() {
    -  connect();
    -  assertEquals(1, numTimingEvents);
    -  sendMap('', '');
    -  assertEquals(1, numTimingEvents);
    -  mockClock.tick(20);
    -  var expSize = getSingleForwardRequest().getPostData().length;
    -  responseDone();
    -
    -  assertEquals(2, numTimingEvents);
    -  assertEquals(expSize, lastPostSize);
    -  assertEquals(20, lastPostRtt);
    -  assertEquals(0, lastPostRetryCount);
    -
    -  sendMap('abcdefg', '123456');
    -  expSize = getSingleForwardRequest().getPostData().length;
    -  responseTimeout();
    -  assertEquals(2, numTimingEvents);
    -  mockClock.tick(RETRY_TIME + 1);
    -  responseDone();
    -  assertEquals(3, numTimingEvents);
    -  assertEquals(expSize, lastPostSize);
    -  assertEquals(1, lastPostRetryCount);
    -  assertEquals(1, lastPostRtt);
    -
    -}
    -
    -
    -/**
    - * Make sure that dropping the forward channel retry limit below the retry count
    - * reports an error, and prevents another request from firing.
    - */
    -function testSetFailFastWhileWaitingForRetry() {
    -  stubNetUtils();
    -
    -  connect();
    -  setFailFastWhileWaitingForRetry();
    -}
    -
    -
    -function testSetFailFastWhileWaitingForRetryWithSpdyEnabled() {
    -  stubNetUtils();
    -
    -  connect(undefined, undefined, undefined, true);
    -  setFailFastWhileWaitingForRetry();
    -}
    -
    -
    -function setFailFastWhileWaitingForRetry() {
    -  assertEquals(1, numTimingEvents);
    -
    -  sendMap('foo', 'bar');
    -  assertNull(channel.forwardChannelTimerId_);
    -  assertNotNull(getSingleForwardRequest());
    -  assertEquals(0, channel.forwardChannelRetryCount_);
    -
    -  // Watchdog timeout.
    -  responseTimeout();
    -  assertNotNull(channel.forwardChannelTimerId_);
    -  assertNull(getSingleForwardRequest());
    -  assertEquals(1, channel.forwardChannelRetryCount_);
    -
    -  // Almost finish the between-retry timeout.
    -  mockClock.tick(RETRY_TIME - 1);
    -  assertNotNull(channel.forwardChannelTimerId_);
    -  assertNull(getSingleForwardRequest());
    -  assertEquals(1, channel.forwardChannelRetryCount_);
    -
    -  // Setting max retries to 0 should cancel the timer and raise an error.
    -  channel.setFailFast(true);
    -  assertNull(channel.forwardChannelTimerId_);
    -  assertNull(getSingleForwardRequest());
    -  assertEquals(1, channel.forwardChannelRetryCount_);
    -
    -  assertTrue(gotError);
    -  assertEquals(0, deliveredMaps.length);
    -  // We get the error immediately before starting to ping google.com.
    -  // Simulate that timing out. We should get a network error in addition to the
    -  // initial failure.
    -  gotError = false;
    -  mockClock.tick(goog.labs.net.webChannel.netUtils.NETWORK_TIMEOUT);
    -  assertTrue('No error after network ping timed out.', gotError);
    -
    -  // Make sure no more retry timers are firing.
    -  mockClock.tick(ALL_DAY_MS);
    -  assertNull(channel.forwardChannelTimerId_);
    -  assertNull(getSingleForwardRequest());
    -  assertEquals(1, channel.forwardChannelRetryCount_);
    -  assertEquals(1, numTimingEvents);
    -}
    -
    -
    -/**
    - * Make sure that dropping the forward channel retry limit below the retry count
    - * reports an error, and prevents another request from firing.
    - */
    -function testSetFailFastWhileRetryXhrIsInFlight() {
    -  stubNetUtils();
    -
    -  connect();
    -  setFailFastWhileRetryXhrIsInFlight();
    -}
    -
    -
    -function testSetFailFastWhileRetryXhrIsInFlightWithSpdyEnabled() {
    -  stubNetUtils();
    -
    -  connect(undefined, undefined, undefined, true);
    -  setFailFastWhileRetryXhrIsInFlight();
    -}
    -
    -
    -function setFailFastWhileRetryXhrIsInFlight() {
    -  assertEquals(1, numTimingEvents);
    -
    -  sendMap('foo', 'bar');
    -  assertNull(channel.forwardChannelTimerId_);
    -  assertNotNull(getSingleForwardRequest());
    -  assertEquals(0, channel.forwardChannelRetryCount_);
    -
    -  // Watchdog timeout.
    -  responseTimeout();
    -  assertNotNull(channel.forwardChannelTimerId_);
    -  assertNull(getSingleForwardRequest());
    -  assertEquals(1, channel.forwardChannelRetryCount_);
    -
    -  // Wait for the between-retry timeout.
    -  mockClock.tick(RETRY_TIME);
    -  assertNull(channel.forwardChannelTimerId_);
    -  assertNotNull(getSingleForwardRequest());
    -  assertEquals(1, channel.forwardChannelRetryCount_);
    -
    -  // Simulate a second watchdog timeout.
    -  responseTimeout();
    -  assertNotNull(channel.forwardChannelTimerId_);
    -  assertNull(getSingleForwardRequest());
    -  assertEquals(2, channel.forwardChannelRetryCount_);
    -
    -  // Wait for another between-retry timeout.
    -  mockClock.tick(RETRY_TIME);
    -  // Now the third req is in flight.
    -  assertNull(channel.forwardChannelTimerId_);
    -  assertNotNull(getSingleForwardRequest());
    -  assertEquals(2, channel.forwardChannelRetryCount_);
    -
    -  // Set fail fast, killing the request
    -  channel.setFailFast(true);
    -  assertNull(channel.forwardChannelTimerId_);
    -  assertNull(getSingleForwardRequest());
    -  assertEquals(2, channel.forwardChannelRetryCount_);
    -
    -  assertTrue(gotError);
    -  // We get the error immediately before starting to ping google.com.
    -  // Simulate that timing out. We should get a network error in addition to the
    -  gotError = false;
    -  mockClock.tick(goog.labs.net.webChannel.netUtils.NETWORK_TIMEOUT);
    -  assertTrue('No error after network ping timed out.', gotError);
    -
    -  // Make sure no more retry timers are firing.
    -  mockClock.tick(ALL_DAY_MS);
    -  assertNull(channel.forwardChannelTimerId_);
    -  assertNull(getSingleForwardRequest());
    -  assertEquals(2, channel.forwardChannelRetryCount_);
    -  assertEquals(1, numTimingEvents);
    -}
    -
    -
    -/**
    - * Makes sure that setting fail fast while not retrying doesn't cause a failure.
    - */
    -function testSetFailFastAtRetryCount() {
    -  stubNetUtils();
    -
    -  connect();
    -  assertEquals(1, numTimingEvents);
    -
    -  sendMap('foo', 'bar');
    -  assertNull(channel.forwardChannelTimerId_);
    -  assertNotNull(getSingleForwardRequest());
    -  assertEquals(0, channel.forwardChannelRetryCount_);
    -
    -  // Set fail fast.
    -  channel.setFailFast(true);
    -  // Request should still be alive.
    -  assertNull(channel.forwardChannelTimerId_);
    -  assertNotNull(getSingleForwardRequest());
    -  assertEquals(0, channel.forwardChannelRetryCount_);
    -
    -  // Watchdog timeout. Now we should get an error.
    -  responseTimeout();
    -  assertNull(channel.forwardChannelTimerId_);
    -  assertNull(getSingleForwardRequest());
    -  assertEquals(0, channel.forwardChannelRetryCount_);
    -
    -  assertTrue(gotError);
    -  // We get the error immediately before starting to ping google.com.
    -  // Simulate that timing out. We should get a network error in addition to the
    -  // initial failure.
    -  gotError = false;
    -  mockClock.tick(goog.labs.net.webChannel.netUtils.NETWORK_TIMEOUT);
    -  assertTrue('No error after network ping timed out.', gotError);
    -
    -  // Make sure no more retry timers are firing.
    -  mockClock.tick(ALL_DAY_MS);
    -  assertNull(channel.forwardChannelTimerId_);
    -  assertNull(getSingleForwardRequest());
    -  assertEquals(0, channel.forwardChannelRetryCount_);
    -  assertEquals(1, numTimingEvents);
    -}
    -
    -
    -function testRequestFailedClosesChannel() {
    -  stubNetUtils();
    -
    -  connect();
    -  requestFailedClosesChannel();
    -}
    -
    -
    -function testRequestFailedClosesChannelWithSpdyEnabled() {
    -  stubNetUtils();
    -
    -  connect(undefined, undefined, undefined, true);
    -  requestFailedClosesChannel();
    -}
    -
    -
    -function requestFailedClosesChannel() {
    -  assertEquals(1, numTimingEvents);
    -
    -  sendMap('foo', 'bar');
    -  responseRequestFailed();
    -
    -  assertEquals('Should be closed immediately after request failed.',
    -      goog.labs.net.webChannel.WebChannelBase.State.CLOSED, channel.getState());
    -
    -  mockClock.tick(goog.labs.net.webChannel.netUtils.NETWORK_TIMEOUT);
    -
    -  assertEquals('Should remain closed after the ping timeout.',
    -      goog.labs.net.webChannel.WebChannelBase.State.CLOSED, channel.getState());
    -  assertEquals(1, numTimingEvents);
    -}
    -
    -
    -function testStatEventReportedOnlyOnce() {
    -  stubNetUtils();
    -
    -  connect();
    -  sendMap('foo', 'bar');
    -  numStatEvents = 0;
    -  lastStatEvent = null;
    -  responseUnknownSessionId();
    -
    -  assertEquals(1, numStatEvents);
    -  assertEquals(goog.labs.net.webChannel.requestStats.Stat.ERROR_OTHER,
    -      lastStatEvent);
    -
    -  numStatEvents = 0;
    -  mockClock.tick(goog.labs.net.webChannel.netUtils.NETWORK_TIMEOUT);
    -  assertEquals('No new stat events should be reported.', 0, numStatEvents);
    -}
    -
    -
    -function testStatEventReportedOnlyOnce_onNetworkUp() {
    -  stubNetUtils();
    -
    -  connect();
    -  sendMap('foo', 'bar');
    -  numStatEvents = 0;
    -  lastStatEvent = null;
    -  responseRequestFailed();
    -
    -  assertEquals('No stat event should be reported before we know the reason.',
    -      0, numStatEvents);
    -
    -  // Let the ping time out.
    -  mockClock.tick(goog.labs.net.webChannel.netUtils.NETWORK_TIMEOUT);
    -
    -  // Assert we report the correct stat event.
    -  assertEquals(1, numStatEvents);
    -  assertEquals(
    -      goog.labs.net.webChannel.requestStats.Stat.ERROR_NETWORK,
    -      lastStatEvent);
    -}
    -
    -
    -function testStatEventReportedOnlyOnce_onNetworkDown() {
    -  stubNetUtils();
    -
    -  connect();
    -  sendMap('foo', 'bar');
    -  numStatEvents = 0;
    -  lastStatEvent = null;
    -  responseRequestFailed();
    -
    -  assertEquals('No stat event should be reported before we know the reason.',
    -      0, numStatEvents);
    -
    -  // Wait half the ping timeout period, and then fake the network being up.
    -  mockClock.tick(goog.labs.net.webChannel.netUtils.NETWORK_TIMEOUT / 2);
    -  channel.testNetworkCallback_(true);
    -
    -  // Assert we report the correct stat event.
    -  assertEquals(1, numStatEvents);
    -  assertEquals(goog.labs.net.webChannel.requestStats.Stat.ERROR_OTHER,
    -      lastStatEvent);
    -}
    -
    -
    -function testOutgoingMapsAwaitsResponse() {
    -  connect();
    -  outgoingMapsAwaitsResponse();
    -}
    -
    -
    -function testOutgoingMapsAwaitsResponseWithSpdyEnabled() {
    -  connect(undefined, undefined, undefined, true);
    -  outgoingMapsAwaitsResponse();
    -}
    -
    -
    -function outgoingMapsAwaitsResponse() {
    -  assertEquals(0, channel.outgoingMaps_.length);
    -
    -  sendMap('foo1', 'bar');
    -  assertEquals(0, channel.outgoingMaps_.length);
    -  sendMap('foo2', 'bar');
    -  assertEquals(1, channel.outgoingMaps_.length);
    -  sendMap('foo3', 'bar');
    -  assertEquals(2, channel.outgoingMaps_.length);
    -  sendMap('foo4', 'bar');
    -  assertEquals(3, channel.outgoingMaps_.length);
    -
    -  responseDone();
    -  // Now the forward channel request is completed and a new started, so all maps
    -  // are dequeued from the array of outgoing maps into this new forward request.
    -  assertEquals(0, channel.outgoingMaps_.length);
    -}
    -
    -
    -function testUndeliveredMaps_doesNotNotifyWhenSuccessful() {
    -  /**
    -   * @suppress {checkTypes} The callback function type declaration is skipped.
    -   */
    -  handler.channelClosed = function(
    -      channel, opt_pendingMaps, opt_undeliveredMaps) {
    -    if (opt_pendingMaps || opt_undeliveredMaps) {
    -      fail('No pending or undelivered maps should be reported.');
    -    }
    -  };
    -
    -  connect();
    -  sendMap('foo1', 'bar1');
    -  responseDone();
    -  sendMap('foo2', 'bar2');
    -  responseDone();
    -  disconnect();
    -}
    -
    -
    -function testUndeliveredMaps_doesNotNotifyIfNothingWasSent() {
    -  /**
    -   * @suppress {checkTypes} The callback function type declaration is skipped.
    -   */
    -  handler.channelClosed = function(
    -      channel, opt_pendingMaps, opt_undeliveredMaps) {
    -    if (opt_pendingMaps || opt_undeliveredMaps) {
    -      fail('No pending or undelivered maps should be reported.');
    -    }
    -  };
    -
    -  connect();
    -  mockClock.tick(ALL_DAY_MS);
    -  disconnect();
    -}
    -
    -
    -function testUndeliveredMaps_clearsPendingMapsAfterNotifying() {
    -  connect();
    -  sendMap('foo1', 'bar1');
    -  sendMap('foo2', 'bar2');
    -  sendMap('foo3', 'bar3');
    -
    -  assertEquals(1, channel.pendingMaps_.length);
    -  assertEquals(2, channel.outgoingMaps_.length);
    -
    -  disconnect();
    -
    -  assertEquals(0, channel.pendingMaps_.length);
    -  assertEquals(0, channel.outgoingMaps_.length);
    -}
    -
    -
    -function testUndeliveredMaps_notifiesWithContext() {
    -  connect();
    -
    -  // First send two messages that succeed.
    -  sendMap('foo1', 'bar1', 'context1');
    -  responseDone();
    -  sendMap('foo2', 'bar2', 'context2');
    -  responseDone();
    -
    -  // Pretend the server hangs and no longer responds.
    -  sendMap('foo3', 'bar3', 'context3');
    -  sendMap('foo4', 'bar4', 'context4');
    -  sendMap('foo5', 'bar5', 'context5');
    -
    -  // Give up.
    -  disconnect();
    -
    -  // Assert that we are informed of any undelivered messages; both about
    -  // #3 that was sent but which we don't know if the server received, and
    -  // #4 and #5 which remain in the outgoing maps and have not yet been sent.
    -  assertEquals('foo3:bar3:context3', handler.pendingMapsString);
    -  assertEquals('foo4:bar4:context4, foo5:bar5:context5',
    -      handler.undeliveredMapsString);
    -}
    -
    -
    -function testUndeliveredMaps_serviceUnavailable() {
    -  // Send a few maps, and let one fail.
    -  connect();
    -  sendMap('foo1', 'bar1');
    -  responseDone();
    -  sendMap('foo2', 'bar2');
    -  responseRequestFailed();
    -
    -  // After a failure, the channel should be closed.
    -  disconnect();
    -
    -  assertEquals('foo2:bar2', handler.pendingMapsString);
    -  assertEquals('', handler.undeliveredMapsString);
    -}
    -
    -
    -function testUndeliveredMaps_onPingTimeout() {
    -  stubNetUtils();
    -
    -  connect();
    -
    -  // Send a message.
    -  sendMap('foo1', 'bar1');
    -
    -  // Fake REQUEST_FAILED, triggering a ping to check the network.
    -  responseRequestFailed();
    -
    -  // Let the ping time out, unsuccessfully.
    -  mockClock.tick(goog.labs.net.webChannel.netUtils.NETWORK_TIMEOUT);
    -
    -  // Assert channel is closed.
    -  assertEquals(goog.labs.net.webChannel.WebChannelBase.State.CLOSED,
    -      channel.getState());
    -
    -  // Assert that the handler is notified about the undelivered messages.
    -  assertEquals('foo1:bar1', handler.pendingMapsString);
    -  assertEquals('', handler.undeliveredMapsString);
    -}
    -
    -
    -function testResponseNoBackchannelPostNotBeforeBackchannel() {
    -  connect(8);
    -  sendMap('foo1', 'bar1');
    -
    -  mockClock.tick(10);
    -  assertFalse(channel.backChannelRequest_.getRequestStartTime() <
    -      getSingleForwardRequest().getRequestStartTime());
    -  responseNoBackchannel();
    -  assertNotEquals(
    -      goog.labs.net.webChannel.requestStats.Stat.BACKCHANNEL_MISSING,
    -      lastStatEvent);
    -}
    -
    -
    -function testResponseNoBackchannel() {
    -  connect(8);
    -  sendMap('foo1', 'bar1');
    -  response(-1, 0);
    -  mockClock.tick(goog.labs.net.webChannel.WebChannelBase.RTT_ESTIMATE + 1);
    -  sendMap('foo2', 'bar2');
    -  assertTrue(channel.backChannelRequest_.getRequestStartTime() +
    -      goog.labs.net.webChannel.WebChannelBase.RTT_ESTIMATE <
    -      getSingleForwardRequest().getRequestStartTime());
    -  responseNoBackchannel();
    -  assertEquals(
    -      goog.labs.net.webChannel.requestStats.Stat.BACKCHANNEL_MISSING,
    -      lastStatEvent);
    -}
    -
    -
    -function testResponseNoBackchannelWithNoBackchannel() {
    -  connect(8);
    -  sendMap('foo1', 'bar1');
    -  assertNull(channel.backChannelTimerId_);
    -  channel.backChannelRequest_.cancel();
    -  channel.backChannelRequest_ = null;
    -  responseNoBackchannel();
    -  assertEquals(
    -      goog.labs.net.webChannel.requestStats.Stat.BACKCHANNEL_MISSING,
    -      lastStatEvent);
    -}
    -
    -
    -function testResponseNoBackchannelWithStartTimer() {
    -  connect(8);
    -  sendMap('foo1', 'bar1');
    -
    -  channel.backChannelRequest_.cancel();
    -  channel.backChannelRequest_ = null;
    -  channel.backChannelTimerId_ = 123;
    -  responseNoBackchannel();
    -  assertNotEquals(
    -      goog.labs.net.webChannel.requestStats.Stat.BACKCHANNEL_MISSING,
    -      lastStatEvent);
    -}
    -
    -
    -function testResponseWithNoArraySent() {
    -  connect(8);
    -  sendMap('foo1', 'bar1');
    -
    -  // Send a response as if the server hasn't sent down an array.
    -  response(-1, 0);
    -
    -  // POST response with an array ID lower than our last received is OK.
    -  assertEquals(1, channel.lastArrayId_);
    -  assertEquals(-1, channel.lastPostResponseArrayId_);
    -}
    -
    -
    -function testResponseWithArraysMissing() {
    -  connect(8);
    -  sendMap('foo1', 'bar1');
    -  assertEquals(-1, channel.lastPostResponseArrayId_);
    -
    -  // Send a response as if the server has sent down seven arrays.
    -  response(7, 111);
    -
    -  assertEquals(1, channel.lastArrayId_);
    -  assertEquals(7, channel.lastPostResponseArrayId_);
    -  mockClock.tick(goog.labs.net.webChannel.WebChannelBase.RTT_ESTIMATE * 2);
    -  assertEquals(
    -      goog.labs.net.webChannel.requestStats.Stat.BACKCHANNEL_DEAD,
    -      lastStatEvent);
    -}
    -
    -
    -function testMultipleResponsesWithArraysMissing() {
    -  connect(8);
    -  sendMap('foo1', 'bar1');
    -  assertEquals(-1, channel.lastPostResponseArrayId_);
    -
    -  // Send a response as if the server has sent down seven arrays.
    -  response(7, 111);
    -
    -  assertEquals(1, channel.lastArrayId_);
    -  assertEquals(7, channel.lastPostResponseArrayId_);
    -  sendMap('foo2', 'bar2');
    -  mockClock.tick(goog.labs.net.webChannel.WebChannelBase.RTT_ESTIMATE);
    -  response(8, 119);
    -  mockClock.tick(goog.labs.net.webChannel.WebChannelBase.RTT_ESTIMATE);
    -  // The original timer should still fire.
    -  assertEquals(
    -      goog.labs.net.webChannel.requestStats.Stat.BACKCHANNEL_DEAD,
    -      lastStatEvent);
    -}
    -
    -
    -function testOnlyRetryOnceBasedOnResponse() {
    -  connect(8);
    -  sendMap('foo1', 'bar1');
    -  assertEquals(-1, channel.lastPostResponseArrayId_);
    -
    -  // Send a response as if the server has sent down seven arrays.
    -  response(7, 111);
    -
    -  assertEquals(1, channel.lastArrayId_);
    -  assertEquals(7, channel.lastPostResponseArrayId_);
    -  assertTrue(hasDeadBackChannelTimer());
    -  mockClock.tick(goog.labs.net.webChannel.WebChannelBase.RTT_ESTIMATE * 2);
    -  assertEquals(
    -      goog.labs.net.webChannel.requestStats.Stat.BACKCHANNEL_DEAD,
    -      lastStatEvent);
    -  assertEquals(1, channel.backChannelRetryCount_);
    -  mockClock.tick(goog.labs.net.webChannel.WebChannelBase.RTT_ESTIMATE);
    -  sendMap('foo2', 'bar2');
    -  assertFalse(hasDeadBackChannelTimer());
    -  response(8, 119);
    -  assertFalse(hasDeadBackChannelTimer());
    -}
    -
    -
    -function testResponseWithArraysMissingAndLiveChannel() {
    -  connect(8);
    -  sendMap('foo1', 'bar1');
    -  assertEquals(-1, channel.lastPostResponseArrayId_);
    -
    -  // Send a response as if the server has sent down seven arrays.
    -  response(7, 111);
    -
    -  assertEquals(1, channel.lastArrayId_);
    -  assertEquals(7, channel.lastPostResponseArrayId_);
    -  mockClock.tick(goog.labs.net.webChannel.WebChannelBase.RTT_ESTIMATE);
    -  assertTrue(hasDeadBackChannelTimer());
    -  receive('["ack"]');
    -  assertFalse(hasDeadBackChannelTimer());
    -  mockClock.tick(goog.labs.net.webChannel.WebChannelBase.RTT_ESTIMATE);
    -  assertNotEquals(
    -      goog.labs.net.webChannel.requestStats.Stat.BACKCHANNEL_DEAD,
    -      lastStatEvent);
    -}
    -
    -
    -function testResponseWithBigOutstandingData() {
    -  connect(8);
    -  sendMap('foo1', 'bar1');
    -  assertEquals(-1, channel.lastPostResponseArrayId_);
    -
    -  // Send a response as if the server has sent down seven arrays and 50kbytes.
    -  response(7, 50000);
    -
    -  assertEquals(1, channel.lastArrayId_);
    -  assertEquals(7, channel.lastPostResponseArrayId_);
    -  assertFalse(hasDeadBackChannelTimer());
    -  mockClock.tick(goog.labs.net.webChannel.WebChannelBase.RTT_ESTIMATE * 2);
    -  assertNotEquals(
    -      goog.labs.net.webChannel.requestStats.Stat.BACKCHANNEL_DEAD,
    -      lastStatEvent);
    -}
    -
    -
    -function testResponseInBufferedMode() {
    -  connect(8);
    -  channel.useChunked_ = false;
    -  sendMap('foo1', 'bar1');
    -  assertEquals(-1, channel.lastPostResponseArrayId_);
    -  response(7, 111);
    -
    -  assertEquals(1, channel.lastArrayId_);
    -  assertEquals(7, channel.lastPostResponseArrayId_);
    -  assertFalse(hasDeadBackChannelTimer());
    -  mockClock.tick(goog.labs.net.webChannel.WebChannelBase.RTT_ESTIMATE * 2);
    -  assertNotEquals(
    -      goog.labs.net.webChannel.requestStats.Stat.BACKCHANNEL_DEAD,
    -      lastStatEvent);
    -}
    -
    -
    -function testResponseWithGarbage() {
    -  connect(8);
    -  sendMap('foo1', 'bar1');
    -  channel.onRequestData(
    -      getSingleForwardRequest(),
    -      'garbage'
    -  );
    -  assertEquals(goog.labs.net.webChannel.WebChannelBase.State.CLOSED,
    -      channel.getState());
    -}
    -
    -
    -function testResponseWithGarbageInArray() {
    -  connect(8);
    -  sendMap('foo1', 'bar1');
    -  channel.onRequestData(
    -      getSingleForwardRequest(),
    -      '["garbage"]'
    -  );
    -  assertEquals(goog.labs.net.webChannel.WebChannelBase.State.CLOSED,
    -      channel.getState());
    -}
    -
    -
    -function testResponseWithEvilData() {
    -  connect(8);
    -  sendMap('foo1', 'bar1');
    -  channel.onRequestData(
    -      getSingleForwardRequest(),
    -      'foo=<script>evil()\<\/script>&' + 'bar=<script>moreEvil()\<\/script>');
    -  assertEquals(goog.labs.net.webChannel.WebChannelBase.State.CLOSED,
    -      channel.getState());
    -}
    -
    -
    -function testPathAbsolute() {
    -  connect(8, undefined, '/talkgadget');
    -  assertEquals(channel.backChannelUri_.getDomain(),
    -      window.location.hostname);
    -  assertEquals(channel.forwardChannelUri_.getDomain(),
    -      window.location.hostname);
    -}
    -
    -
    -function testPathRelative() {
    -  connect(8, undefined, 'talkgadget');
    -  assertEquals(channel.backChannelUri_.getDomain(),
    -      window.location.hostname);
    -  assertEquals(channel.forwardChannelUri_.getDomain(),
    -      window.location.hostname);
    -}
    -
    -
    -function testPathWithHost() {
    -  connect(8, undefined, 'https://example.com');
    -  assertEquals(channel.backChannelUri_.getScheme(), 'https');
    -  assertEquals(channel.backChannelUri_.getDomain(), 'example.com');
    -  assertEquals(channel.forwardChannelUri_.getScheme(), 'https');
    -  assertEquals(channel.forwardChannelUri_.getDomain(), 'example.com');
    -}
    -
    -function testCreateXhrIo() {
    -  var xhr = channel.createXhrIo(null);
    -  assertFalse(xhr.getWithCredentials());
    -
    -  assertThrows(
    -      'Error connection to different host without CORS',
    -      goog.bind(channel.createXhrIo, channel, 'some_host'));
    -
    -  channel.setSupportsCrossDomainXhrs(true);
    -
    -  xhr = channel.createXhrIo(null);
    -  assertTrue(xhr.getWithCredentials());
    -
    -  xhr = channel.createXhrIo('some_host');
    -  assertTrue(xhr.getWithCredentials());
    -}
    -
    -function testSpdyLimitOption() {
    -  var webChannelTransport =
    -      new goog.labs.net.webChannel.WebChannelBaseTransport();
    -  stubSpdyCheck(true);
    -  var webChannelDefault = webChannelTransport.createWebChannel('/foo');
    -  assertEquals(10,
    -      webChannelDefault.getRuntimeProperties().getConcurrentRequestLimit());
    -  assertTrue(webChannelDefault.getRuntimeProperties().isSpdyEnabled());
    -
    -  var options = {'concurrentRequestLimit': 100};
    -
    -  stubSpdyCheck(false);
    -  var webChannelDisabled = webChannelTransport.createWebChannel(
    -      '/foo', options);
    -  assertEquals(1,
    -      webChannelDisabled.getRuntimeProperties().getConcurrentRequestLimit());
    -  assertFalse(webChannelDisabled.getRuntimeProperties().isSpdyEnabled());
    -
    -  stubSpdyCheck(true);
    -  var webChannelEnabled = webChannelTransport.createWebChannel('/foo', options);
    -  assertEquals(100,
    -      webChannelEnabled.getRuntimeProperties().getConcurrentRequestLimit());
    -  assertTrue(webChannelEnabled.getRuntimeProperties().isSpdyEnabled());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/webchannelbasetransport.js b/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/webchannelbasetransport.js
    deleted file mode 100644
    index 5b2ea653d73..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/webchannelbasetransport.js
    +++ /dev/null
    @@ -1,379 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Implementation of a WebChannel transport using WebChannelBase.
    - *
    - * When WebChannelBase is used as the underlying transport, the capabilities
    - * of the WebChannel are limited to what's supported by the implementation.
    - * Particularly, multiplexing is not possible, and only strings are
    - * supported as message types.
    - *
    - */
    -
    -goog.provide('goog.labs.net.webChannel.WebChannelBaseTransport');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.labs.net.webChannel.ChannelRequest');
    -goog.require('goog.labs.net.webChannel.WebChannelBase');
    -goog.require('goog.log');
    -goog.require('goog.net.WebChannel');
    -goog.require('goog.net.WebChannelTransport');
    -goog.require('goog.object');
    -goog.require('goog.string.path');
    -
    -
    -
    -/**
    - * Implementation of {@link goog.net.WebChannelTransport} with
    - * {@link goog.labs.net.webChannel.WebChannelBase} as the underlying channel
    - * implementation.
    - *
    - * @constructor
    - * @struct
    - * @implements {goog.net.WebChannelTransport}
    - * @final
    - */
    -goog.labs.net.webChannel.WebChannelBaseTransport = function() {
    -  if (!goog.labs.net.webChannel.ChannelRequest.supportsXhrStreaming()) {
    -    throw new Error('Environmental error: no available transport.');
    -  }
    -};
    -
    -
    -goog.scope(function() {
    -var WebChannelBaseTransport = goog.labs.net.webChannel.WebChannelBaseTransport;
    -var WebChannelBase = goog.labs.net.webChannel.WebChannelBase;
    -
    -
    -/**
    - * @override
    - */
    -WebChannelBaseTransport.prototype.createWebChannel = function(
    -    url, opt_options) {
    -  return new WebChannelBaseTransport.Channel(url, opt_options);
    -};
    -
    -
    -
    -/**
    - * Implementation of the {@link goog.net.WebChannel} interface.
    - *
    - * @param {string} url The URL path for the new WebChannel instance.
    - * @param {!goog.net.WebChannel.Options=} opt_options Configuration for the
    - *     new WebChannel instance.
    - *
    - * @constructor
    - * @implements {goog.net.WebChannel}
    - * @extends {goog.events.EventTarget}
    - * @final
    - */
    -WebChannelBaseTransport.Channel = function(url, opt_options) {
    -  WebChannelBaseTransport.Channel.base(this, 'constructor');
    -
    -  /**
    -   * The underlying channel object.
    -   *
    -   * @private {!WebChannelBase}
    -   */
    -  this.channel_ = new WebChannelBase(opt_options);
    -
    -  /**
    -   * The URL of the target server end-point.
    -   *
    -   * @private {string}
    -   */
    -  this.url_ = url;
    -
    -  /**
    -   * The test URL of the target server end-point. This value defaults to
    -   * this.url_ + '/test'.
    -   *
    -   * @private {string}
    -   */
    -  this.testUrl_ = (opt_options && opt_options.testUrl) ? opt_options.testUrl :
    -      goog.string.path.join(this.url_, 'test');
    -
    -  /**
    -   * The logger for this class.
    -   * @private {goog.log.Logger}
    -   */
    -  this.logger_ = goog.log.getLogger(
    -      'goog.labs.net.webChannel.WebChannelBaseTransport');
    -
    -  /**
    -   * @private {Object<string, string>} messageUrlParams_ Extra URL parameters
    -   * to be added to each HTTP request.
    -   */
    -  this.messageUrlParams_ =
    -      (opt_options && opt_options.messageUrlParams) || null;
    -
    -  var messageHeaders = (opt_options && opt_options.messageHeaders) || null;
    -
    -  // default is false
    -  if (opt_options && opt_options.clientProtocolHeaderRequired) {
    -    if (messageHeaders) {
    -      goog.object.set(messageHeaders,
    -          goog.net.WebChannel.X_CLIENT_PROTOCOL,
    -          goog.net.WebChannel.X_CLIENT_PROTOCOL_WEB_CHANNEL);
    -    } else {
    -      messageHeaders = goog.object.create(
    -          goog.net.WebChannel.X_CLIENT_PROTOCOL,
    -          goog.net.WebChannel.X_CLIENT_PROTOCOL_WEB_CHANNEL);
    -    }
    -  }
    -
    -  this.channel_.setExtraHeaders(messageHeaders);
    -
    -  /**
    -   * @private {boolean} supportsCrossDomainXhr_ Whether to enable CORS.
    -   */
    -  this.supportsCrossDomainXhr_ =
    -      (opt_options && opt_options.supportsCrossDomainXhr) || false;
    -
    -  /**
    -   * The channel handler.
    -   *
    -   * @type {WebChannelBaseTransport.Channel.Handler_}
    -   * @private
    -   */
    -  this.channelHandler_ = new WebChannelBaseTransport.Channel.Handler_(this);
    -};
    -goog.inherits(WebChannelBaseTransport.Channel, goog.events.EventTarget);
    -
    -
    -/**
    - * Test path is always set to "/url/test".
    - *
    - * @override
    - */
    -WebChannelBaseTransport.Channel.prototype.open = function() {
    -  this.channel_.setHandler(this.channelHandler_);
    -  this.channel_.connect(this.testUrl_, this.url_,
    -      (this.messageUrlParams_ || undefined));
    -
    -  if (this.supportsCrossDomainXhr_) {
    -    this.channel_.setSupportsCrossDomainXhrs(true);
    -  }
    -};
    -
    -
    -/**
    - * @override
    - */
    -WebChannelBaseTransport.Channel.prototype.close = function() {
    -  this.channel_.disconnect();
    -};
    -
    -
    -/**
    - * The WebChannelBase only supports object types.
    - *
    - * @param {!goog.net.WebChannel.MessageData} message The message to send.
    - * @override
    - */
    -WebChannelBaseTransport.Channel.prototype.send = function(message) {
    -  goog.asserts.assert(goog.isObject(message), 'only object type expected');
    -  this.channel_.sendMap(message);
    -};
    -
    -
    -/**
    - * @override
    - */
    -WebChannelBaseTransport.Channel.prototype.disposeInternal = function() {
    -  this.channel_.setHandler(null);
    -  delete this.channelHandler_;
    -  this.channel_.disconnect();
    -  delete this.channel_;
    -
    -  WebChannelBaseTransport.Channel.base(this, 'disposeInternal');
    -};
    -
    -
    -
    -/**
    - * The message event.
    - *
    - * @param {!Array<?>} array The data array from the underlying channel.
    - * @constructor
    - * @extends {goog.net.WebChannel.MessageEvent}
    - * @final
    - */
    -WebChannelBaseTransport.Channel.MessageEvent = function(array) {
    -  WebChannelBaseTransport.Channel.MessageEvent.base(this, 'constructor');
    -
    -  this.data = array;
    -};
    -goog.inherits(WebChannelBaseTransport.Channel.MessageEvent,
    -              goog.net.WebChannel.MessageEvent);
    -
    -
    -
    -/**
    - * The error event.
    - *
    - * @param {WebChannelBase.Error} error The error code.
    - * @constructor
    - * @extends {goog.net.WebChannel.ErrorEvent}
    - * @final
    - */
    -WebChannelBaseTransport.Channel.ErrorEvent = function(error) {
    -  WebChannelBaseTransport.Channel.ErrorEvent.base(this, 'constructor');
    -
    -  /**
    -   * Transport specific error code is not to be propagated with the event.
    -   */
    -  this.status = goog.net.WebChannel.ErrorStatus.NETWORK_ERROR;
    -};
    -goog.inherits(WebChannelBaseTransport.Channel.ErrorEvent,
    -              goog.net.WebChannel.ErrorEvent);
    -
    -
    -
    -/**
    - * Implementation of {@link WebChannelBase.Handler} interface.
    - *
    - * @param {!WebChannelBaseTransport.Channel} channel The enclosing WebChannel.
    - *
    - * @constructor
    - * @extends {WebChannelBase.Handler}
    - * @private
    - */
    -WebChannelBaseTransport.Channel.Handler_ = function(channel) {
    -  WebChannelBaseTransport.Channel.Handler_.base(this, 'constructor');
    -
    -  /**
    -   * @type {!WebChannelBaseTransport.Channel}
    -   * @private
    -   */
    -  this.channel_ = channel;
    -};
    -goog.inherits(WebChannelBaseTransport.Channel.Handler_, WebChannelBase.Handler);
    -
    -
    -/**
    - * @override
    - */
    -WebChannelBaseTransport.Channel.Handler_.prototype.channelOpened = function(
    -    channel) {
    -  goog.log.info(this.channel_.logger_,
    -      'WebChannel opened on ' + this.channel_.url_);
    -  this.channel_.dispatchEvent(goog.net.WebChannel.EventType.OPEN);
    -};
    -
    -
    -/**
    - * @override
    - */
    -WebChannelBaseTransport.Channel.Handler_.prototype.channelHandleArray =
    -    function(channel, array) {
    -  goog.asserts.assert(array, 'array expected to be defined');
    -  this.channel_.dispatchEvent(
    -      new WebChannelBaseTransport.Channel.MessageEvent(array));
    -};
    -
    -
    -/**
    - * @override
    - */
    -WebChannelBaseTransport.Channel.Handler_.prototype.channelError = function(
    -    channel, error) {
    -  goog.log.info(this.channel_.logger_,
    -      'WebChannel aborted on ' + this.channel_.url_ +
    -      ' due to channel error: ' + error);
    -  this.channel_.dispatchEvent(
    -      new WebChannelBaseTransport.Channel.ErrorEvent(error));
    -};
    -
    -
    -/**
    - * @override
    - */
    -WebChannelBaseTransport.Channel.Handler_.prototype.channelClosed = function(
    -    channel, opt_pendingMaps, opt_undeliveredMaps) {
    -  goog.log.info(this.channel_.logger_,
    -      'WebChannel closed on ' + this.channel_.url_);
    -  this.channel_.dispatchEvent(goog.net.WebChannel.EventType.CLOSE);
    -};
    -
    -
    -/**
    - * @override
    - */
    -WebChannelBaseTransport.Channel.prototype.getRuntimeProperties = function() {
    -  return new WebChannelBaseTransport.ChannelProperties(this.channel_);
    -};
    -
    -
    -
    -/**
    - * Implementation of the {@link goog.net.WebChannel.RuntimeProperties}.
    - *
    - * @param {!WebChannelBase} channel The underlying channel object.
    - *
    - * @constructor
    - * @implements {goog.net.WebChannel.RuntimeProperties}
    - * @final
    - */
    -WebChannelBaseTransport.ChannelProperties = function(channel) {
    -  /**
    -   * The underlying channel object.
    -   *
    -   * @private {!WebChannelBase}
    -   */
    -  this.channel_ = channel;
    -
    -};
    -
    -
    -/**
    - * @override
    - */
    -WebChannelBaseTransport.ChannelProperties.prototype.getConcurrentRequestLimit =
    -    function() {
    -  return this.channel_.getForwardChannelRequestPool().getMaxSize();
    -};
    -
    -
    -/**
    - * @override
    - */
    -WebChannelBaseTransport.ChannelProperties.prototype.isSpdyEnabled =
    -    function() {
    -  return this.getConcurrentRequestLimit() > 1;
    -};
    -
    -
    -/**
    - * @override
    - */
    -WebChannelBaseTransport.ChannelProperties.prototype.setServerFlowControl =
    -    goog.abstractMethod;
    -
    -
    -/**
    - * @override
    - */
    -WebChannelBaseTransport.ChannelProperties.prototype.getNonAckedMessageCount =
    -    goog.abstractMethod;
    -
    -
    -/** @override */
    -WebChannelBaseTransport.ChannelProperties.prototype.getLastStatusCode =
    -    function() {
    -  return this.channel_.getLastStatusCode();
    -};
    -});  // goog.scope
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/webchannelbasetransport_test.html b/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/webchannelbasetransport_test.html
    deleted file mode 100644
    index 2096e5ee573..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/webchannelbasetransport_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.labs.net.webChannel.WebChannelBaseTransport</title>
    -<script src="../../../base.js"></script>
    -</head>
    -<body>
    -<script>
    -goog.require('goog.labs.net.webChannel.webChannelBaseTransportTest');
    -</script>
    -<div id="debug" style="font-size: small"></div>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/webchannelbasetransport_test.js b/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/webchannelbasetransport_test.js
    deleted file mode 100644
    index b643d1ac568..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/webchannelbasetransport_test.js
    +++ /dev/null
    @@ -1,287 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.labs.net.webChannel.WebChannelBase.
    - * @suppress {accessControls} Private methods are accessed for test purposes.
    - *
    - */
    -
    -
    -goog.provide('goog.labs.net.webChannel.webChannelBaseTransportTest');
    -
    -goog.require('goog.events');
    -goog.require('goog.functions');
    -goog.require('goog.labs.net.webChannel.ChannelRequest');
    -goog.require('goog.labs.net.webChannel.WebChannelBaseTransport');
    -goog.require('goog.net.WebChannel');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -
    -
    -goog.setTestOnly('goog.labs.net.webChannel.webChannelBaseTransportTest');
    -
    -
    -var webChannel;
    -var channelUrl = 'http://127.0.0.1:8080/channel';
    -
    -var stubs = new goog.testing.PropertyReplacer();
    -
    -
    -function shouldRunTests() {
    -  return goog.labs.net.webChannel.ChannelRequest.supportsXhrStreaming();
    -}
    -
    -
    -function setUp() {
    -}
    -
    -
    -function tearDown() {
    -  goog.dispose(webChannel);
    -  stubs.reset();
    -}
    -
    -
    -/**
    - * Stubs goog.labs.net.webChannel.ChannelRequest.
    - */
    -function stubChannelRequest() {
    -  stubs.set(goog.labs.net.webChannel.ChannelRequest, 'supportsXhrStreaming',
    -      goog.functions.FALSE);
    -}
    -
    -
    -function testUnsupportedTransports() {
    -  stubChannelRequest();
    -
    -  var err = assertThrows(function() {
    -    var webChannelTransport =
    -        new goog.labs.net.webChannel.WebChannelBaseTransport();
    -  });
    -  assertContains('error', err.message);
    -}
    -
    -function testOpenWithUrl() {
    -  var webChannelTransport =
    -      new goog.labs.net.webChannel.WebChannelBaseTransport();
    -  webChannel = webChannelTransport.createWebChannel(channelUrl);
    -
    -  var eventFired = false;
    -  goog.events.listen(webChannel, goog.net.WebChannel.EventType.OPEN,
    -      function(e) {
    -        eventFired = true;
    -      });
    -
    -  webChannel.open();
    -  assertFalse(eventFired);
    -
    -  var channel = webChannel.channel_;
    -  assertNotNull(channel);
    -
    -  simulateOpenEvent(channel);
    -  assertTrue(eventFired);
    -}
    -
    -function testOpenWithTestUrl() {
    -  var webChannelTransport =
    -      new goog.labs.net.webChannel.WebChannelBaseTransport();
    -  var options = {'testUrl': channelUrl + '/footest'};
    -  webChannel = webChannelTransport.createWebChannel(channelUrl, options);
    -  webChannel.open();
    -
    -  var testPath = webChannel.channel_.connectionTest_.path_;
    -  assertNotNullNorUndefined(testPath);
    -}
    -
    -function testOpenWithCustomHeaders() {
    -  var webChannelTransport =
    -      new goog.labs.net.webChannel.WebChannelBaseTransport();
    -  var options = {'messageHeaders': {'foo-key': 'foo-value'}};
    -  webChannel = webChannelTransport.createWebChannel(channelUrl, options);
    -  webChannel.open();
    -
    -  var extraHeaders_ = webChannel.channel_.extraHeaders_;
    -  assertNotNullNorUndefined(extraHeaders_);
    -  assertEquals('foo-value', extraHeaders_['foo-key']);
    -  assertEquals(undefined, extraHeaders_['X-Client-Protocol']);
    -}
    -
    -function testClientProtocolHeaderRequired() {
    -  var webChannelTransport =
    -      new goog.labs.net.webChannel.WebChannelBaseTransport();
    -  var options = {'clientProtocolHeaderRequired': true};
    -  webChannel = webChannelTransport.createWebChannel(channelUrl, options);
    -  webChannel.open();
    -
    -  var extraHeaders_ = webChannel.channel_.extraHeaders_;
    -  assertNotNullNorUndefined(extraHeaders_);
    -  assertEquals('webchannel', extraHeaders_['X-Client-Protocol']);
    -}
    -
    -function testClientProtocolHeaderNotRequiredByDefault() {
    -  var webChannelTransport =
    -      new goog.labs.net.webChannel.WebChannelBaseTransport();
    -  webChannel = webChannelTransport.createWebChannel(channelUrl);
    -  webChannel.open();
    -
    -  var extraHeaders_ = webChannel.channel_.extraHeaders_;
    -  assertNull(extraHeaders_);
    -}
    -
    -function testClientProtocolHeaderRequiredWithCustomHeader() {
    -  var webChannelTransport =
    -      new goog.labs.net.webChannel.WebChannelBaseTransport();
    -  var options = {
    -    'clientProtocolHeaderRequired': true,
    -    'messageHeaders': {'foo-key': 'foo-value'}
    -  };
    -  webChannel = webChannelTransport.createWebChannel(channelUrl, options);
    -  webChannel.open();
    -
    -  var extraHeaders_ = webChannel.channel_.extraHeaders_;
    -  assertNotNullNorUndefined(extraHeaders_);
    -  assertEquals('foo-value', extraHeaders_['foo-key']);
    -  assertEquals('webchannel', extraHeaders_['X-Client-Protocol']);
    -}
    -
    -function testOpenWithCustomParams() {
    -  var webChannelTransport =
    -      new goog.labs.net.webChannel.WebChannelBaseTransport();
    -  var options = {'messageUrlParams': {'foo-key': 'foo-value'}};
    -  webChannel = webChannelTransport.createWebChannel(channelUrl, options);
    -  webChannel.open();
    -
    -  var extraParams = webChannel.channel_.extraParams_;
    -  assertNotNullNorUndefined(extraParams);
    -}
    -
    -function testOpenWithCorsEnabled() {
    -  var webChannelTransport =
    -      new goog.labs.net.webChannel.WebChannelBaseTransport();
    -  var options = {'supportsCrossDomainXhr': true};
    -  webChannel = webChannelTransport.createWebChannel(channelUrl, options);
    -  webChannel.open();
    -
    -  assertTrue(webChannel.channel_.supportsCrossDomainXhrs_);
    -}
    -
    -function testOpenThenCloseChannel() {
    -  var webChannelTransport =
    -      new goog.labs.net.webChannel.WebChannelBaseTransport();
    -  webChannel = webChannelTransport.createWebChannel(channelUrl);
    -
    -  var eventFired = false;
    -  goog.events.listen(webChannel, goog.net.WebChannel.EventType.CLOSE,
    -      function(e) {
    -        eventFired = true;
    -      });
    -
    -  webChannel.open();
    -  assertFalse(eventFired);
    -
    -  var channel = webChannel.channel_;
    -  assertNotNull(channel);
    -
    -  simulateCloseEvent(channel);
    -  assertTrue(eventFired);
    -}
    -
    -
    -function testChannelError() {
    -  var webChannelTransport =
    -      new goog.labs.net.webChannel.WebChannelBaseTransport();
    -  webChannel = webChannelTransport.createWebChannel(channelUrl);
    -
    -  var eventFired = false;
    -  goog.events.listen(webChannel, goog.net.WebChannel.EventType.ERROR,
    -      function(e) {
    -        eventFired = true;
    -        assertEquals(goog.net.WebChannel.ErrorStatus.NETWORK_ERROR, e.status);
    -      });
    -
    -  webChannel.open();
    -  assertFalse(eventFired);
    -
    -  var channel = webChannel.channel_;
    -  assertNotNull(channel);
    -
    -  simulateErrorEvent(channel);
    -  assertTrue(eventFired);
    -}
    -
    -
    -function testChannelMessage() {
    -  var webChannelTransport =
    -      new goog.labs.net.webChannel.WebChannelBaseTransport();
    -  webChannel = webChannelTransport.createWebChannel(channelUrl);
    -
    -  var eventFired = false;
    -  var data = 'foo';
    -  goog.events.listen(webChannel, goog.net.WebChannel.EventType.MESSAGE,
    -      function(e) {
    -        eventFired = true;
    -        assertEquals(e.data, data);
    -      });
    -
    -  webChannel.open();
    -  assertFalse(eventFired);
    -
    -  var channel = webChannel.channel_;
    -  assertNotNull(channel);
    -
    -  simulateMessageEvent(channel, data);
    -  assertTrue(eventFired);
    -}
    -
    -
    -/**
    - * Simulates the WebChannelBase firing the open event for the given channel.
    - * @param {!goog.labs.net.webChannel.WebChannelBase} channel The WebChannelBase.
    - */
    -function simulateOpenEvent(channel) {
    -  assertNotNull(channel.getHandler());
    -  channel.getHandler().channelOpened();
    -}
    -
    -
    -/**
    - * Simulates the WebChannelBase firing the close event for the given channel.
    - * @param {!goog.labs.net.webChannel.WebChannelBase} channel The WebChannelBase.
    - */
    -function simulateCloseEvent(channel) {
    -  assertNotNull(channel.getHandler());
    -  channel.getHandler().channelClosed();
    -}
    -
    -
    -/**
    - * Simulates the WebChannelBase firing the error event for the given channel.
    - * @param {!goog.labs.net.webChannel.WebChannelBase} channel The WebChannelBase.
    - */
    -function simulateErrorEvent(channel) {
    -  assertNotNull(channel.getHandler());
    -  channel.getHandler().channelError();
    -}
    -
    -
    -/**
    - * Simulates the WebChannelBase firing the message event for the given channel.
    - * @param {!goog.labs.net.webChannel.WebChannelBase} channel The WebChannelBase.
    - * @param {String} data The message data.
    - */
    -function simulateMessageEvent(channel, data) {
    -  assertNotNull(channel.getHandler());
    -  channel.getHandler().channelHandleArray(channel, data);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/webchanneldebug.js b/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/webchanneldebug.js
    deleted file mode 100644
    index 205e283e3c2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/webchanneldebug.js
    +++ /dev/null
    @@ -1,260 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides a utility for tracing and debugging WebChannel
    - *     requests.
    - *
    - * @visibility {:internal}
    - */
    -
    -
    -goog.provide('goog.labs.net.webChannel.WebChannelDebug');
    -
    -goog.require('goog.json');
    -goog.require('goog.log');
    -
    -
    -
    -/**
    - * Logs and keeps a buffer of debugging info for the Channel.
    - *
    - * @constructor
    - * @struct
    - * @final
    - */
    -goog.labs.net.webChannel.WebChannelDebug = function() {
    -  /**
    -   * The logger instance.
    -   * @const
    -   * @private
    -   */
    -  this.logger_ = goog.log.getLogger('goog.labs.net.webChannel.WebChannelDebug');
    -};
    -
    -
    -goog.scope(function() {
    -var WebChannelDebug = goog.labs.net.webChannel.WebChannelDebug;
    -
    -
    -/**
    - * Gets the logger used by this ChannelDebug.
    - * @return {goog.debug.Logger} The logger used by this WebChannelDebug.
    - */
    -WebChannelDebug.prototype.getLogger = function() {
    -  return this.logger_;
    -};
    -
    -
    -/**
    - * Logs that the browser went offline during the lifetime of a request.
    - * @param {goog.Uri} url The URL being requested.
    - */
    -WebChannelDebug.prototype.browserOfflineResponse = function(url) {
    -  this.info('BROWSER_OFFLINE: ' + url);
    -};
    -
    -
    -/**
    - * Logs an XmlHttp request..
    - * @param {string} verb The request type (GET/POST).
    - * @param {goog.Uri} uri The request destination.
    - * @param {string|number|undefined} id The request id.
    - * @param {number} attempt Which attempt # the request was.
    - * @param {?string} postData The data posted in the request.
    - */
    -WebChannelDebug.prototype.xmlHttpChannelRequest =
    -    function(verb, uri, id, attempt, postData) {
    -  this.info(
    -      'XMLHTTP REQ (' + id + ') [attempt ' + attempt + ']: ' +
    -      verb + '\n' + uri + '\n' +
    -      this.maybeRedactPostData_(postData));
    -};
    -
    -
    -/**
    - * Logs the meta data received from an XmlHttp request.
    - * @param {string} verb The request type (GET/POST).
    - * @param {goog.Uri} uri The request destination.
    - * @param {string|number|undefined} id The request id.
    - * @param {number} attempt Which attempt # the request was.
    - * @param {goog.net.XmlHttp.ReadyState} readyState The ready state.
    - * @param {number} statusCode The HTTP status code.
    - */
    -WebChannelDebug.prototype.xmlHttpChannelResponseMetaData =
    -    function(verb, uri, id, attempt, readyState, statusCode)  {
    -  this.info(
    -      'XMLHTTP RESP (' + id + ') [ attempt ' + attempt + ']: ' +
    -      verb + '\n' + uri + '\n' + readyState + ' ' + statusCode);
    -};
    -
    -
    -/**
    - * Logs the response data received from an XmlHttp request.
    - * @param {string|number|undefined} id The request id.
    - * @param {?string} responseText The response text.
    - * @param {?string=} opt_desc Optional request description.
    - */
    -WebChannelDebug.prototype.xmlHttpChannelResponseText =
    -    function(id, responseText, opt_desc) {
    -  this.info(
    -      'XMLHTTP TEXT (' + id + '): ' +
    -      this.redactResponse_(responseText) +
    -      (opt_desc ? ' ' + opt_desc : ''));
    -};
    -
    -
    -/**
    - * Logs a request timeout.
    - * @param {goog.Uri} uri The uri that timed out.
    - */
    -WebChannelDebug.prototype.timeoutResponse = function(uri) {
    -  this.info('TIMEOUT: ' + uri);
    -};
    -
    -
    -/**
    - * Logs a debug message.
    - * @param {string} text The message.
    - */
    -WebChannelDebug.prototype.debug = function(text) {
    -  this.info(text);
    -};
    -
    -
    -/**
    - * Logs an exception
    - * @param {Error} e The error or error event.
    - * @param {string=} opt_msg The optional message, defaults to 'Exception'.
    - */
    -WebChannelDebug.prototype.dumpException = function(e, opt_msg) {
    -  this.severe((opt_msg || 'Exception') + e);
    -};
    -
    -
    -/**
    - * Logs an info message.
    - * @param {string} text The message.
    - */
    -WebChannelDebug.prototype.info = function(text) {
    -  goog.log.info(this.logger_, text);
    -};
    -
    -
    -/**
    - * Logs a warning message.
    - * @param {string} text The message.
    - */
    -WebChannelDebug.prototype.warning = function(text) {
    -  goog.log.warning(this.logger_, text);
    -};
    -
    -
    -/**
    - * Logs a severe message.
    - * @param {string} text The message.
    - */
    -WebChannelDebug.prototype.severe = function(text) {
    -  goog.log.error(this.logger_, text);
    -};
    -
    -
    -/**
    - * Removes potentially private data from a response so that we don't
    - * accidentally save private and personal data to the server logs.
    - * @param {?string} responseText A JSON response to clean.
    - * @return {?string} The cleaned response.
    - * @private
    - */
    -WebChannelDebug.prototype.redactResponse_ = function(responseText) {
    -  if (!responseText) {
    -    return null;
    -  }
    -  /** @preserveTry */
    -  try {
    -    var responseArray = goog.json.unsafeParse(responseText);
    -    if (responseArray) {
    -      for (var i = 0; i < responseArray.length; i++) {
    -        if (goog.isArray(responseArray[i])) {
    -          this.maybeRedactArray_(responseArray[i]);
    -        }
    -      }
    -    }
    -
    -    return goog.json.serialize(responseArray);
    -  } catch (e) {
    -    this.debug('Exception parsing expected JS array - probably was not JS');
    -    return responseText;
    -  }
    -};
    -
    -
    -/**
    - * Removes data from a response array that may be sensitive.
    - * @param {!Array<?>} array The array to clean.
    - * @private
    - */
    -WebChannelDebug.prototype.maybeRedactArray_ = function(array) {
    -  if (array.length < 2) {
    -    return;
    -  }
    -  var dataPart = array[1];
    -  if (!goog.isArray(dataPart)) {
    -    return;
    -  }
    -  if (dataPart.length < 1) {
    -    return;
    -  }
    -
    -  var type = dataPart[0];
    -  if (type != 'noop' && type != 'stop') {
    -    // redact all fields in the array
    -    for (var i = 1; i < dataPart.length; i++) {
    -      dataPart[i] = '';
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Removes potentially private data from a request POST body so that we don't
    - * accidentally save private and personal data to the server logs.
    - * @param {?string} data The data string to clean.
    - * @return {?string} The data string with sensitive data replaced by 'redacted'.
    - * @private
    - */
    -WebChannelDebug.prototype.maybeRedactPostData_ = function(data) {
    -  if (!data) {
    -    return null;
    -  }
    -  var out = '';
    -  var params = data.split('&');
    -  for (var i = 0; i < params.length; i++) {
    -    var param = params[i];
    -    var keyValue = param.split('=');
    -    if (keyValue.length > 1) {
    -      var key = keyValue[0];
    -      var value = keyValue[1];
    -
    -      var keyParts = key.split('_');
    -      if (keyParts.length >= 2 && keyParts[1] == 'type') {
    -        out += key + '=' + value + '&';
    -      } else {
    -        out += key + '=' + 'redacted' + '&';
    -      }
    -    }
    -  }
    -  return out;
    -};
    -});  // goog.scope
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/wire.js b/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/wire.js
    deleted file mode 100644
    index 78bee596a16..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/wire.js
    +++ /dev/null
    @@ -1,75 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Interface and shared data structures for implementing
    - * different wire protocol versions.
    - * @visibility {//closure/goog/bin/sizetests:__pkg__}
    - */
    -
    -
    -goog.provide('goog.labs.net.webChannel.Wire');
    -
    -
    -
    -/**
    - * The interface class.
    - *
    - * @interface
    - */
    -goog.labs.net.webChannel.Wire = function() {};
    -
    -
    -goog.scope(function() {
    -var Wire = goog.labs.net.webChannel.Wire;
    -
    -
    -/**
    - * The latest protocol version that this class supports. We request this version
    - * from the server when opening the connection. Should match
    - * LATEST_CHANNEL_VERSION on the server code.
    - * @type {number}
    - */
    -Wire.LATEST_CHANNEL_VERSION = 8;
    -
    -
    -
    -/**
    - * Simple container class for a (mapId, map) pair.
    - * @param {number} mapId The id for this map.
    - * @param {!Object|!goog.structs.Map} map The map itself.
    - * @param {!Object=} opt_context The context associated with the map.
    - * @constructor
    - * @struct
    - */
    -Wire.QueuedMap = function(mapId, map, opt_context) {
    -  /**
    -   * The id for this map.
    -   * @type {number}
    -   */
    -  this.mapId = mapId;
    -
    -  /**
    -   * The map itself.
    -   * @type {!Object|!goog.structs.Map}
    -   */
    -  this.map = map;
    -
    -  /**
    -   * The context for the map.
    -   * @type {Object}
    -   */
    -  this.context = opt_context || null;
    -};
    -});  // goog.scope
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/wirev8.js b/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/wirev8.js
    deleted file mode 100644
    index 58a5cd5ce16..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/wirev8.js
    +++ /dev/null
    @@ -1,136 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Codec functions of the v8 wire protocol. Eventually we'd want
    - * to support pluggable wire-format to improve wire efficiency and to enable
    - * binary encoding. Such support will require an interface class, which
    - * will be added later.
    - *
    - * @visibility {:internal}
    - */
    -
    -
    -goog.provide('goog.labs.net.webChannel.WireV8');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.json');
    -goog.require('goog.json.NativeJsonProcessor');
    -goog.require('goog.structs');
    -
    -
    -
    -/**
    - * The v8 codec class.
    - *
    - * @constructor
    - * @struct
    - */
    -goog.labs.net.webChannel.WireV8 = function() {
    -  /**
    -   * Parser for a response payload. The parser should return an array.
    -   * @private {!goog.string.Parser}
    -   */
    -  this.parser_ = new goog.json.NativeJsonProcessor();
    -};
    -
    -
    -goog.scope(function() {
    -var WireV8 = goog.labs.net.webChannel.WireV8;
    -var Wire = goog.labs.net.webChannel.Wire;
    -
    -
    -/**
    - * Encodes a standalone message into the wire format.
    - *
    - * May throw exception if the message object contains any invalid elements.
    - *
    - * @param {!Object|!goog.structs.Map} message The message data.
    - *     V8 only support JS objects (or Map).
    - * @param {!Array<string>} buffer The text buffer to write the message to.
    - * @param {string=} opt_prefix The prefix for each field of the object.
    - */
    -WireV8.prototype.encodeMessage = function(message, buffer, opt_prefix) {
    -  var prefix = opt_prefix || '';
    -  try {
    -    goog.structs.forEach(message, function(value, key) {
    -      var encodedValue = value;
    -      if (goog.isObject(value)) {
    -        encodedValue = goog.json.serialize(value);
    -      }  // keep the fast-path for primitive types
    -      buffer.push(prefix + key + '=' + encodeURIComponent(encodedValue));
    -    });
    -  } catch (ex) {
    -    // We send a map here because lots of the retry logic relies on map IDs,
    -    // so we have to send something (possibly redundant).
    -    buffer.push(prefix + 'type' + '=' + encodeURIComponent('_badmap'));
    -    throw ex;
    -  }
    -};
    -
    -
    -/**
    - * Encodes all the buffered messages of the forward channel.
    - *
    - * @param {!Array<Wire.QueuedMap>} messageQueue The message data.
    - *     V8 only support JS objects.
    - * @param {number} count The number of messages to be encoded.
    - * @param {?function(!Object)} badMapHandler Callback for bad messages.
    - */
    -WireV8.prototype.encodeMessageQueue = function(messageQueue, count,
    -    badMapHandler) {
    -  var sb = ['count=' + count];
    -  var offset;
    -  if (count > 0) {
    -    // To save a bit of bandwidth, specify the base mapId and the rest as
    -    // offsets from it.
    -    offset = messageQueue[0].mapId;
    -    sb.push('ofs=' + offset);
    -  } else {
    -    offset = 0;
    -  }
    -  for (var i = 0; i < count; i++) {
    -    var mapId = messageQueue[i].mapId;
    -    var map = messageQueue[i].map;
    -    mapId -= offset;
    -    try {
    -      this.encodeMessage(map, sb, 'req' + mapId + '_');
    -    } catch (ex) {
    -      if (badMapHandler) {
    -        badMapHandler(map);
    -      }
    -    }
    -  }
    -  return sb.join('&');
    -};
    -
    -
    -/**
    - * Decodes a standalone message received from the wire. May throw exception
    - * if text is ill-formatted.
    - *
    - * Must be valid JSON as it is insecure to use eval() to decode JS literals;
    - * and eval() is disallowed in Chrome apps too.
    - *
    - * Invalid JS literals include null array elements, quotas etc.
    - *
    - * @param {string} messageText The string content as received from the wire.
    - * @return {*} The decoded message object.
    - */
    -WireV8.prototype.decodeMessage = function(messageText) {
    -  var response = this.parser_.parse(messageText);
    -  goog.asserts.assert(goog.isArray(response));  // throw exception
    -  return response;
    -};
    -});  // goog.scope
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/wirev8_test.html b/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/wirev8_test.html
    deleted file mode 100644
    index 4635b436546..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/wirev8_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.labs.net.webChannel.WireV8</title>
    -<script src="../../../base.js"></script>
    -</head>
    -<body>
    -<script>
    -goog.require('goog.labs.net.webChannel.WireV8Test');
    -</script>
    -<div id="debug" style="font-size: small"></div>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/wirev8_test.js b/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/wirev8_test.js
    deleted file mode 100644
    index 678a48110f1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/webchannel/wirev8_test.js
    +++ /dev/null
    @@ -1,99 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.labs.net.webChannel.WireV8.
    - *
    - */
    -
    -
    -goog.provide('goog.labs.net.webChannel.WireV8Test');
    -
    -goog.require('goog.labs.net.webChannel.WireV8');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.labs.net.webChannel.WireV8Test');
    -
    -
    -var wireCodec;
    -
    -
    -function setUp() {
    -  wireCodec = new goog.labs.net.webChannel.WireV8();
    -}
    -
    -function tearDown() {
    -}
    -
    -
    -function testEncodeSimpleMessage() {
    -  // scalar types only
    -  var message = {
    -    a: 'a',
    -    b: 'b'
    -  };
    -  var buff = [];
    -  wireCodec.encodeMessage(message, buff, 'prefix_');
    -  assertEquals(2, buff.length);
    -  assertEquals('prefix_a=a', buff[0]);
    -  assertEquals('prefix_b=b', buff[1]);
    -}
    -
    -
    -function testEncodeComplexMessage() {
    -  var message = {
    -    a: 'a',
    -    b: {
    -      x: 1,
    -      y: 2
    -    }
    -  };
    -  var buff = [];
    -  wireCodec.encodeMessage(message, buff, 'prefix_');
    -  assertEquals(2, buff.length);
    -  assertEquals('prefix_a=a', buff[0]);
    -  // a round-trip URI codec
    -  assertEquals('prefix_b={\"x\":1,\"y\":2}', decodeURIComponent(buff[1]));
    -}
    -
    -
    -function testEncodeMessageQueue() {
    -  var message1 = {
    -    a: 'a'
    -  };
    -  var queuedMessage1 = {
    -    map: message1,
    -    mapId: 3
    -  };
    -  var message2 = {
    -    b: 'b'
    -  };
    -  var queuedMessage2 = {
    -    map: message2,
    -    mapId: 4
    -  };
    -  var queue = [queuedMessage1, queuedMessage2];
    -  var result = wireCodec.encodeMessageQueue(queue, 2, null);
    -  assertEquals('count=2&ofs=3&req0_a=a&req1_b=b', result);
    -}
    -
    -
    -function testDecodeMessage() {
    -  var message = wireCodec.decodeMessage('[{"a":"a", "x":1}, {"b":"b"}]');
    -  assertTrue(goog.isArray(message));
    -  assertEquals(2, message.length);
    -  assertEquals('a', message[0].a);
    -  assertEquals(1, message[0].x);
    -  assertEquals('b', message[1].b);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/webchanneltransport.js b/src/database/third_party/closure-library/closure/goog/labs/net/webchanneltransport.js
    deleted file mode 100644
    index 5c955b57ff1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/webchanneltransport.js
    +++ /dev/null
    @@ -1,75 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Transport support for WebChannel.
    - *
    - * The <code>WebChannelTransport</code> implementation serves as the factory
    - * for <code>WebChannel</code>, which offers an abstraction for
    - * point-to-point socket-like communication similar to what BrowserChannel
    - * or HTML5 WebSocket offers.
    - *
    - */
    -
    -goog.provide('goog.net.WebChannelTransport');
    -
    -
    -
    -/**
    - * A WebChannelTransport instance represents a shared context of logical
    - * connectivity between a browser client and a remote origin.
    - *
    - * Over a single WebChannelTransport instance, multiple WebChannels may be
    - * created against different URLs, which may all share the same
    - * underlying connectivity (i.e. TCP connection) whenever possible.
    - *
    - * When multi-domains are supported, such as CORS, multiple origins may be
    - * supported over a single WebChannelTransport instance at the same time.
    - *
    - * Sharing between different window contexts such as tabs is not addressed
    - * by WebChannelTransport. Applications may choose HTML5 shared workers
    - * or other techniques to access the same transport instance
    - * across different window contexts.
    - *
    - * @interface
    - */
    -goog.net.WebChannelTransport = function() {};
    -
    -
    -/**
    - * The latest protocol version. The protocol version is requested
    - * from the server which is responsible for terminating the underlying
    - * wire protocols.
    - *
    - * @const
    - * @type {number}
    - * @private
    - */
    -goog.net.WebChannelTransport.LATEST_VERSION_ = 0;
    -
    -
    -/**
    - * Create a new WebChannel instance.
    - *
    - * The new WebChannel is to be opened against the server-side resource
    - * as specified by the given URL. See {@link goog.net.WebChannel} for detailed
    - * semantics.
    - *
    - * @param {string} url The URL path for the new WebChannel instance.
    - * @param {!goog.net.WebChannel.Options=} opt_options Configuration for the
    - *     new WebChannel instance. The configuration object is reusable after
    - *     the new channel instance is created.
    - * @return {!goog.net.WebChannel} the newly created WebChannel instance.
    - */
    -goog.net.WebChannelTransport.prototype.createWebChannel = goog.abstractMethod;
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/webchanneltransportfactory.js b/src/database/third_party/closure-library/closure/goog/labs/net/webchanneltransportfactory.js
    deleted file mode 100644
    index 487cdfb4d4f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/webchanneltransportfactory.js
    +++ /dev/null
    @@ -1,37 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Default factory for <code>WebChannelTransport</code> to
    - * avoid exposing concrete classes to clients.
    - *
    - */
    -
    -goog.provide('goog.net.createWebChannelTransport');
    -
    -goog.require('goog.functions');
    -goog.require('goog.labs.net.webChannel.WebChannelBaseTransport');
    -
    -
    -/**
    - * Create a new WebChannelTransport instance using the default implementation.
    - * Throws an error message if no default transport available in the current
    - * environment.
    - *
    - * @return {!goog.net.WebChannelTransport} the newly created transport instance.
    - */
    -goog.net.createWebChannelTransport =
    -    /** @type {function(): !goog.net.WebChannelTransport} */ (
    -    goog.partial(goog.functions.create,
    -                 goog.labs.net.webChannel.WebChannelBaseTransport));
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/xhr.js b/src/database/third_party/closure-library/closure/goog/labs/net/xhr.js
    deleted file mode 100644
    index 0b83b7d3515..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/xhr.js
    +++ /dev/null
    @@ -1,468 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Offered as an alternative to XhrIo as a way for making requests
    - * via XMLHttpRequest.  Instead of mirroring the XHR interface and exposing
    - * events, results are used as a way to pass a "promise" of the response to
    - * interested parties.
    - *
    - */
    -
    -goog.provide('goog.labs.net.xhr');
    -goog.provide('goog.labs.net.xhr.Error');
    -goog.provide('goog.labs.net.xhr.HttpError');
    -goog.provide('goog.labs.net.xhr.Options');
    -goog.provide('goog.labs.net.xhr.PostData');
    -goog.provide('goog.labs.net.xhr.ResponseType');
    -goog.provide('goog.labs.net.xhr.TimeoutError');
    -
    -goog.require('goog.Promise');
    -goog.require('goog.debug.Error');
    -goog.require('goog.json');
    -goog.require('goog.net.HttpStatus');
    -goog.require('goog.net.XmlHttp');
    -goog.require('goog.string');
    -goog.require('goog.uri.utils');
    -goog.require('goog.userAgent');
    -
    -
    -
    -goog.scope(function() {
    -var xhr = goog.labs.net.xhr;
    -var HttpStatus = goog.net.HttpStatus;
    -
    -
    -/**
    - * Configuration options for an XMLHttpRequest.
    - * - headers: map of header key/value pairs.
    - * - timeoutMs: number of milliseconds after which the request will be timed
    - *      out by the client. Default is to allow the browser to handle timeouts.
    - * - withCredentials: whether user credentials are to be included in a
    - *      cross-origin request. See:
    - *      http://www.w3.org/TR/XMLHttpRequest/#the-withcredentials-attribute
    - * - mimeType: allows the caller to override the content-type and charset for
    - *      the request. See:
    - *      http://www.w3.org/TR/XMLHttpRequest/#dom-xmlhttprequest-overridemimetype
    - * - responseType: may be set to change the response type to an arraybuffer or
    - *      blob for downloading binary data. See:
    - *      http://www.w3.org/TR/XMLHttpRequest/#dom-xmlhttprequest-responsetype]
    - * - xmlHttpFactory: allows the caller to override the factory used to create
    - *      XMLHttpRequest objects.
    - * - xssiPrefix: Prefix used for protecting against XSSI attacks, which should
    - *      be removed before parsing the response as JSON.
    - *
    - * @typedef {{
    - *   headers: (Object<string>|undefined),
    - *   mimeType: (string|undefined),
    - *   responseType: (xhr.ResponseType|undefined),
    - *   timeoutMs: (number|undefined),
    - *   withCredentials: (boolean|undefined),
    - *   xmlHttpFactory: (goog.net.XmlHttpFactory|undefined),
    - *   xssiPrefix: (string|undefined)
    - * }}
    - */
    -xhr.Options;
    -
    -
    -/**
    - * Defines the types that are allowed as post data.
    - * @typedef {(ArrayBuffer|Blob|Document|FormData|null|string|undefined)}
    - */
    -xhr.PostData;
    -
    -
    -/**
    - * The Content-Type HTTP header name.
    - * @type {string}
    - */
    -xhr.CONTENT_TYPE_HEADER = 'Content-Type';
    -
    -
    -/**
    - * The Content-Type HTTP header value for a url-encoded form.
    - * @type {string}
    - */
    -xhr.FORM_CONTENT_TYPE = 'application/x-www-form-urlencoded;charset=utf-8';
    -
    -
    -/**
    - * Supported data types for the responseType field.
    - * See: http://www.w3.org/TR/XMLHttpRequest/#dom-xmlhttprequest-response
    - * @enum {string}
    - */
    -xhr.ResponseType = {
    -  ARRAYBUFFER: 'arraybuffer',
    -  BLOB: 'blob',
    -  DOCUMENT: 'document',
    -  JSON: 'json',
    -  TEXT: 'text'
    -};
    -
    -
    -/**
    - * Sends a get request, returning a promise that will be resolved
    - * with the response text once the request completes.
    - *
    - * @param {string} url The URL to request.
    - * @param {xhr.Options=} opt_options Configuration options for the request.
    - * @return {!goog.Promise<string>} A promise that will be resolved with the
    - *     response text once the request completes.
    - */
    -xhr.get = function(url, opt_options) {
    -  return xhr.send('GET', url, null, opt_options).then(function(request) {
    -    return request.responseText;
    -  });
    -};
    -
    -
    -/**
    - * Sends a post request, returning a promise that will be resolved
    - * with the response text once the request completes.
    - *
    - * @param {string} url The URL to request.
    - * @param {xhr.PostData} data The body of the post request.
    - * @param {xhr.Options=} opt_options Configuration options for the request.
    - * @return {!goog.Promise<string>} A promise that will be resolved with the
    - *     response text once the request completes.
    - */
    -xhr.post = function(url, data, opt_options) {
    -  return xhr.send('POST', url, data, opt_options).then(function(request) {
    -    return request.responseText;
    -  });
    -};
    -
    -
    -/**
    - * Sends a get request, returning a promise that will be resolved with
    - * the parsed response text once the request completes.
    - *
    - * @param {string} url The URL to request.
    - * @param {xhr.Options=} opt_options Configuration options for the request.
    - * @return {!goog.Promise<Object>} A promise that will be resolved with the
    - *     response JSON once the request completes.
    - */
    -xhr.getJson = function(url, opt_options) {
    -  return xhr.send('GET', url, null, opt_options).then(function(request) {
    -    return xhr.parseJson_(request.responseText, opt_options);
    -  });
    -};
    -
    -
    -/**
    - * Sends a get request, returning a promise that will be resolved with the
    - * response as an array of bytes.
    - *
    - * Supported in all XMLHttpRequest level 2 browsers, as well as IE9. IE8 and
    - * earlier are not supported.
    - *
    - * @param {string} url The URL to request.
    - * @param {xhr.Options=} opt_options Configuration options for the request. The
    - *     responseType will be overwritten to 'arraybuffer' if it was set.
    - * @return {!goog.Promise<!Uint8Array|!Array<number>>} A promise that will be
    - *     resolved with an array of bytes once the request completes.
    - */
    -xhr.getBytes = function(url, opt_options) {
    -  if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9)) {
    -    throw new Error('getBytes is not supported in this browser.');
    -  }
    -
    -  var options = opt_options || {};
    -  options.responseType = xhr.ResponseType.ARRAYBUFFER;
    -
    -  return xhr.send('GET', url, null, options).then(function(request) {
    -    // Use the ArrayBuffer response in browsers that support XMLHttpRequest2.
    -    // This covers nearly all modern browsers: http://caniuse.com/xhr2
    -    if (request.response) {
    -      return new Uint8Array(/** @type {!ArrayBuffer} */ (request.response));
    -    }
    -
    -    // Fallback for IE9: the response may be accessed as an array of bytes with
    -    // the non-standard responseBody property, which can only be accessed as a
    -    // VBArray. IE7 and IE8 require significant amounts of VBScript to extract
    -    // the bytes.
    -    // See: http://stackoverflow.com/questions/1919972/
    -    if (goog.global['VBArray']) {
    -      return new goog.global['VBArray'](request['responseBody']).toArray();
    -    }
    -
    -    // Nearly all common browsers are covered by the cases above. If downloading
    -    // binary files in older browsers is necessary, the MDN article "Sending and
    -    // Receiving Binary Data" provides techniques that may work with
    -    // XMLHttpRequest level 1 browsers: http://goo.gl/7lEuGN
    -    throw new xhr.Error(
    -        'getBytes is not supported in this browser.', url, request);
    -  });
    -};
    -
    -
    -/**
    - * Sends a post request, returning a promise that will be resolved with
    - * the parsed response text once the request completes.
    - *
    - * @param {string} url The URL to request.
    - * @param {xhr.PostData} data The body of the post request.
    - * @param {xhr.Options=} opt_options Configuration options for the request.
    - * @return {!goog.Promise<Object>} A promise that will be resolved with the
    - *     response JSON once the request completes.
    - */
    -xhr.postJson = function(url, data, opt_options) {
    -  return xhr.send('POST', url, data, opt_options).then(function(request) {
    -    return xhr.parseJson_(request.responseText, opt_options);
    -  });
    -};
    -
    -
    -/**
    - * Sends a request, returning a promise that will be resolved
    - * with the XHR object once the request completes.
    - *
    - * If content type hasn't been set in opt_options headers, and hasn't been
    - * explicitly set to null, default to form-urlencoded/UTF8 for POSTs.
    - *
    - * @param {string} method The HTTP method for the request.
    - * @param {string} url The URL to request.
    - * @param {xhr.PostData} data The body of the post request.
    - * @param {xhr.Options=} opt_options Configuration options for the request.
    - * @return {!goog.Promise<!goog.net.XhrLike.OrNative>} A promise that will be
    - *     resolved with the XHR object once the request completes.
    - */
    -xhr.send = function(method, url, data, opt_options) {
    -  return new goog.Promise(function(resolve, reject) {
    -    var options = opt_options || {};
    -    var timer;
    -
    -    var request = options.xmlHttpFactory ?
    -        options.xmlHttpFactory.createInstance() : goog.net.XmlHttp();
    -    try {
    -      request.open(method, url, true);
    -    } catch (e) {
    -      // XMLHttpRequest.open may throw when 'open' is called, for example, IE7
    -      // throws "Access Denied" for cross-origin requests.
    -      reject(new xhr.Error('Error opening XHR: ' + e.message, url, request));
    -    }
    -
    -    // So sad that IE doesn't support onload and onerror.
    -    request.onreadystatechange = function() {
    -      if (request.readyState == goog.net.XmlHttp.ReadyState.COMPLETE) {
    -        goog.global.clearTimeout(timer);
    -        // Note: When developing locally, XHRs to file:// schemes return
    -        // a status code of 0. We mark that case as a success too.
    -        if (HttpStatus.isSuccess(request.status) ||
    -            request.status === 0 && !xhr.isEffectiveSchemeHttp_(url)) {
    -          resolve(request);
    -        } else {
    -          reject(new xhr.HttpError(request.status, url, request));
    -        }
    -      }
    -    };
    -    request.onerror = function() {
    -      reject(new xhr.Error('Network error', url, request));
    -    };
    -
    -    // Set the headers.
    -    var contentType;
    -    if (options.headers) {
    -      for (var key in options.headers) {
    -        var value = options.headers[key];
    -        if (goog.isDefAndNotNull(value)) {
    -          request.setRequestHeader(key, value);
    -        }
    -      }
    -      contentType = options.headers[xhr.CONTENT_TYPE_HEADER];
    -    }
    -
    -    // Browsers will automatically set the content type to multipart/form-data
    -    // when passed a FormData object.
    -    var dataIsFormData = (goog.global['FormData'] &&
    -        (data instanceof goog.global['FormData']));
    -    // If a content type hasn't been set, it hasn't been explicitly set to null,
    -    // and the data isn't a FormData, default to form-urlencoded/UTF8 for POSTs.
    -    // This is because some proxies have been known to reject posts without a
    -    // content-type.
    -    if (method == 'POST' && contentType === undefined && !dataIsFormData) {
    -      request.setRequestHeader(xhr.CONTENT_TYPE_HEADER, xhr.FORM_CONTENT_TYPE);
    -    }
    -
    -    // Set whether to include cookies with cross-domain requests. See:
    -    // http://www.w3.org/TR/XMLHttpRequest/#the-withcredentials-attribute
    -    if (options.withCredentials) {
    -      request.withCredentials = options.withCredentials;
    -    }
    -
    -    // Allows setting an alternative response type, such as an ArrayBuffer. See:
    -    // http://www.w3.org/TR/XMLHttpRequest/#dom-xmlhttprequest-responsetype
    -    if (options.responseType) {
    -      request.responseType = options.responseType;
    -    }
    -
    -    // Allow the request to override the MIME type of the response. See:
    -    // http://www.w3.org/TR/XMLHttpRequest/#dom-xmlhttprequest-overridemimetype
    -    if (options.mimeType) {
    -      request.overrideMimeType(options.mimeType);
    -    }
    -
    -    // Handle timeouts, if requested.
    -    if (options.timeoutMs > 0) {
    -      timer = goog.global.setTimeout(function() {
    -        // Clear event listener before aborting so the errback will not be
    -        // called twice.
    -        request.onreadystatechange = goog.nullFunction;
    -        request.abort();
    -        reject(new xhr.TimeoutError(url, request));
    -      }, options.timeoutMs);
    -    }
    -
    -    // Trigger the send.
    -    try {
    -      request.send(data);
    -    } catch (e) {
    -      // XMLHttpRequest.send is known to throw on some versions of FF,
    -      // for example if a cross-origin request is disallowed.
    -      request.onreadystatechange = goog.nullFunction;
    -      goog.global.clearTimeout(timer);
    -      reject(new xhr.Error('Error sending XHR: ' + e.message, url, request));
    -    }
    -  });
    -};
    -
    -
    -/**
    - * @param {string} url The URL to test.
    - * @return {boolean} Whether the effective scheme is HTTP or HTTPs.
    - * @private
    - */
    -xhr.isEffectiveSchemeHttp_ = function(url) {
    -  var scheme = goog.uri.utils.getEffectiveScheme(url);
    -  // NOTE(user): Empty-string is for the case under FF3.5 when the location
    -  // is not defined inside a web worker.
    -  return scheme == 'http' || scheme == 'https' || scheme == '';
    -};
    -
    -
    -/**
    - * JSON-parses the given response text, returning an Object.
    - *
    - * @param {string} responseText Response text.
    - * @param {xhr.Options|undefined} options The options object.
    - * @return {Object} The JSON-parsed value of the original responseText.
    - * @private
    - */
    -xhr.parseJson_ = function(responseText, options) {
    -  var prefixStrippedResult = responseText;
    -  if (options && options.xssiPrefix) {
    -    prefixStrippedResult = xhr.stripXssiPrefix_(
    -        options.xssiPrefix, prefixStrippedResult);
    -  }
    -  return goog.json.parse(prefixStrippedResult);
    -};
    -
    -
    -/**
    - * Strips the XSSI prefix from the input string.
    - *
    - * @param {string} prefix The XSSI prefix.
    - * @param {string} string The string to strip the prefix from.
    - * @return {string} The input string without the prefix.
    - * @private
    - */
    -xhr.stripXssiPrefix_ = function(prefix, string) {
    -  if (goog.string.startsWith(string, prefix)) {
    -    string = string.substring(prefix.length);
    -  }
    -  return string;
    -};
    -
    -
    -
    -/**
    - * Generic error that may occur during a request.
    - *
    - * @param {string} message The error message.
    - * @param {string} url The URL that was being requested.
    - * @param {!goog.net.XhrLike.OrNative} request The XHR that failed.
    - * @extends {goog.debug.Error}
    - * @constructor
    - */
    -xhr.Error = function(message, url, request) {
    -  xhr.Error.base(this, 'constructor', message + ', url=' + url);
    -
    -  /**
    -   * The URL that was requested.
    -   * @type {string}
    -   */
    -  this.url = url;
    -
    -  /**
    -   * The XMLHttpRequest corresponding with the failed request.
    -   * @type {!goog.net.XhrLike.OrNative}
    -   */
    -  this.xhr = request;
    -};
    -goog.inherits(xhr.Error, goog.debug.Error);
    -
    -
    -/** @override */
    -xhr.Error.prototype.name = 'XhrError';
    -
    -
    -
    -/**
    - * Class for HTTP errors.
    - *
    - * @param {number} status The HTTP status code of the response.
    - * @param {string} url The URL that was being requested.
    - * @param {!goog.net.XhrLike.OrNative} request The XHR that failed.
    - * @extends {xhr.Error}
    - * @constructor
    - * @final
    - */
    -xhr.HttpError = function(status, url, request) {
    -  xhr.HttpError.base(
    -      this, 'constructor', 'Request Failed, status=' + status, url, request);
    -
    -  /**
    -   * The HTTP status code for the error.
    -   * @type {number}
    -   */
    -  this.status = status;
    -};
    -goog.inherits(xhr.HttpError, xhr.Error);
    -
    -
    -/** @override */
    -xhr.HttpError.prototype.name = 'XhrHttpError';
    -
    -
    -
    -/**
    - * Class for Timeout errors.
    - *
    - * @param {string} url The URL that timed out.
    - * @param {!goog.net.XhrLike.OrNative} request The XHR that failed.
    - * @extends {xhr.Error}
    - * @constructor
    - * @final
    - */
    -xhr.TimeoutError = function(url, request) {
    -  xhr.TimeoutError.base(this, 'constructor', 'Request timed out', url, request);
    -};
    -goog.inherits(xhr.TimeoutError, xhr.Error);
    -
    -
    -/** @override */
    -xhr.TimeoutError.prototype.name = 'XhrTimeoutError';
    -
    -});  // goog.scope
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/xhr_test.html b/src/database/third_party/closure-library/closure/goog/labs/net/xhr_test.html
    deleted file mode 100644
    index 02d348a23ad..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/xhr_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.labs.net.xhr
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.labs.net.xhrTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/net/xhr_test.js b/src/database/third_party/closure-library/closure/goog/labs/net/xhr_test.js
    deleted file mode 100644
    index b8d43002e23..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/net/xhr_test.js
    +++ /dev/null
    @@ -1,462 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.labs.net.xhrTest');
    -goog.setTestOnly('goog.labs.net.xhrTest');
    -
    -goog.require('goog.Promise');
    -goog.require('goog.labs.net.xhr');
    -goog.require('goog.net.WrapperXmlHttpFactory');
    -goog.require('goog.net.XmlHttp');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -function stubXhrToReturn(status, opt_responseText, opt_latency) {
    -
    -  if (goog.isDefAndNotNull(opt_latency)) {
    -    mockClock = new goog.testing.MockClock(true);
    -  }
    -
    -  var stubXhr = {
    -    sent: false,
    -    aborted: false,
    -    status: 0,
    -    headers: {},
    -    open: function(method, url, async) {
    -      this.method = method;
    -      this.url = url;
    -      this.async = async;
    -    },
    -    setRequestHeader: function(key, value) {
    -      this.headers[key] = value;
    -    },
    -    overrideMimeType: function(mimeType) {
    -      this.mimeType = mimeType;
    -    },
    -    abort: function() {
    -      this.aborted = true;
    -      this.load(0);
    -    },
    -    send: function(data) {
    -      if (mockClock) {
    -        mockClock.tick(opt_latency);
    -      }
    -      this.data = data;
    -      this.sent = true;
    -      this.load(status);
    -    },
    -    load: function(status) {
    -      this.status = status;
    -      if (goog.isDefAndNotNull(opt_responseText)) {
    -        this.responseText = opt_responseText;
    -      }
    -      this.readyState = 4;
    -      if (this.onreadystatechange) this.onreadystatechange();
    -    }
    -  };
    -
    -  stubXmlHttpWith(stubXhr);
    -}
    -
    -function stubXhrToThrow(err) {
    -  stubXmlHttpWith(buildThrowingStubXhr(err));
    -}
    -
    -function buildThrowingStubXhr(err) {
    -  return {
    -    sent: false,
    -    aborted: false,
    -    status: 0,
    -    headers: {},
    -    open: function(method, url, async) {
    -      this.method = method;
    -      this.url = url;
    -      this.async = async;
    -    },
    -    setRequestHeader: function(key, value) {
    -      this.headers[key] = value;
    -    },
    -    overrideMimeType: function(mimeType) {
    -      this.mimeType = mimeType;
    -    },
    -    send: function(data) {
    -      throw err;
    -    }
    -  };
    -}
    -
    -function stubXmlHttpWith(stubXhr) {
    -  goog.net.XmlHttp = function() {
    -    return stubXhr;
    -  };
    -  for (var x in originalXmlHttp) {
    -    goog.net.XmlHttp[x] = originalXmlHttp[x];
    -  }
    -}
    -
    -var xhr = goog.labs.net.xhr;
    -var originalXmlHttp = goog.net.XmlHttp;
    -var mockClock;
    -
    -function tearDown() {
    -  if (mockClock) {
    -    mockClock.dispose();
    -    mockClock = null;
    -  }
    -  goog.net.XmlHttp = originalXmlHttp;
    -}
    -
    -
    -/**
    - * Tests whether the test was loaded from a file: protocol. Tests that use a
    - * real network request cannot be run from the local file system due to
    - * cross-origin restrictions, but will run if the tests are hosted on a server.
    - * A log message is added to the test case to warn users that the a test was
    - * skipped.
    - *
    - * @return {boolean} Whether the test is running on a local file system.
    - */
    -function isRunningLocally() {
    -  if (window.location.protocol == 'file:') {
    -    var testCase = goog.global['G_testRunner'].testCase;
    -    testCase.saveMessage('Test skipped while running on local file system.');
    -    return true;
    -  }
    -  return false;
    -}
    -
    -function testSimpleRequest() {
    -  if (isRunningLocally()) return;
    -
    -  return xhr.send('GET', 'testdata/xhr_test_text.data').then(function(xhr) {
    -    assertEquals('Just some data.', xhr.responseText);
    -    assertEquals(200, xhr.status);
    -  });
    -}
    -
    -function testGetText() {
    -  if (isRunningLocally()) return;
    -
    -  return xhr.get('testdata/xhr_test_text.data').then(function(responseText) {
    -    assertEquals('Just some data.', responseText);
    -  });
    -}
    -
    -function testGetTextWithJson() {
    -  if (isRunningLocally()) return;
    -
    -  return xhr.get('testdata/xhr_test_json.data').then(function(responseText) {
    -    assertEquals('while(1);\n{"stat":"ok","count":12345}\n', responseText);
    -  });
    -}
    -
    -function testPostText() {
    -  if (isRunningLocally()) return;
    -
    -  return xhr.post('testdata/xhr_test_text.data', 'post-data').then(
    -      function(responseText) {
    -        // No good way to test post-data gets transported.
    -        assertEquals('Just some data.', responseText);
    -      });
    -}
    -
    -function testGetJson() {
    -  if (isRunningLocally()) return;
    -
    -  return xhr.getJson(
    -      'testdata/xhr_test_json.data', {xssiPrefix: 'while(1);\n'}).then(
    -      function(responseObj) {
    -        assertEquals('ok', responseObj['stat']);
    -        assertEquals(12345, responseObj['count']);
    -      });
    -}
    -
    -function testGetBytes() {
    -  if (isRunningLocally()) return;
    -
    -  // IE8 requires a VBScript fallback to read the bytes from the response.
    -  if (goog.userAgent.IE && !goog.userAgent.isDocumentMode(9)) {
    -    return;
    -  }
    -
    -  return xhr.getBytes('testdata/cleardot.gif').then(function(bytes) {
    -    assertElementsEquals([
    -      0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x01, 0x00, 0x01, 0x00, 0x80, 0xFF,
    -      0x00, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x21, 0xF9, 0x04, 0x01, 0x00,
    -      0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
    -      0x00, 0x02, 0x02, 0x44, 0x01, 0x00, 0x3B
    -    ], bytes);
    -  });
    -}
    -
    -function testSerialRequests() {
    -  if (isRunningLocally()) return;
    -
    -  return xhr.get('testdata/xhr_test_text.data').
    -      then(function(response) {
    -        return xhr.getJson(
    -            'testdata/xhr_test_json.data', {xssiPrefix: 'while(1);\n'});
    -      }).then(function(responseObj) {
    -        // Data that comes through to callbacks should be from the 2nd request.
    -        assertEquals('ok', responseObj['stat']);
    -        assertEquals(12345, responseObj['count']);
    -      });
    -}
    -
    -function testBadUrlDetectedAsError() {
    -  if (isRunningLocally()) return;
    -
    -  return xhr.getJson('unknown-file.dat').then(
    -      fail /* opt_onFulfilled */,
    -      function(err) {
    -        assertTrue(
    -            'Error should be an HTTP error', err instanceof xhr.HttpError);
    -        assertEquals(404, err.status);
    -        assertNotNull(err.xhr);
    -      });
    -}
    -
    -function testBadOriginTriggersOnErrorHandler() {
    -  return xhr.get('http://www.google.com').then(
    -      fail /* opt_onFulfilled */,
    -      function(err) {
    -        // In IE this will be a goog.labs.net.xhr.Error since it is thrown
    -        //  when calling xhr.open(), other browsers will raise an HttpError.
    -        assertTrue('Error should be an xhr error', err instanceof xhr.Error);
    -        assertNotNull(err.xhr);
    -      });
    -}
    -
    -//============================================================================
    -// The following tests use a stubbed out XMLHttpRequest.
    -//============================================================================
    -
    -function testAbortRequest() {
    -  stubXhrToReturn(200);
    -  var promise = xhr.send('GET', 'test-url', null).thenCatch(
    -      function(error) {
    -        assertTrue(error instanceof goog.Promise.CancellationError);
    -      });
    -  promise.cancel();
    -  return promise;
    -}
    -
    -function testSendNoOptions() {
    -  var called = false;
    -  stubXhrToReturn(200);
    -  assertFalse('Callback should not yet have been called', called);
    -  return xhr.send('GET', 'test-url', null).then(function(stubXhr) {
    -    called = true;
    -    assertEquals('GET', stubXhr.method);
    -    assertEquals('test-url', stubXhr.url);
    -  });
    -}
    -
    -function testSendPostSetsDefaultHeader() {
    -  stubXhrToReturn(200);
    -  return xhr.send('POST', 'test-url', null).then(function(stubXhr) {
    -    assertEquals('POST', stubXhr.method);
    -    assertEquals('test-url', stubXhr.url);
    -    assertEquals('application/x-www-form-urlencoded;charset=utf-8',
    -        stubXhr.headers['Content-Type']);
    -  });
    -}
    -
    -function testSendPostDoesntSetHeaderWithFormData() {
    -  if (!goog.global['FormData']) { return; }
    -  var formData = new goog.global['FormData']();
    -  formData.append('name', 'value');
    -
    -  stubXhrToReturn(200);
    -  return xhr.send('POST', 'test-url', formData).then(function(stubXhr) {
    -    assertEquals('POST', stubXhr.method);
    -    assertEquals('test-url', stubXhr.url);
    -    assertEquals(undefined, stubXhr.headers['Content-Type']);
    -  });
    -}
    -
    -function testSendPostHeaders() {
    -  stubXhrToReturn(200);
    -  return xhr.send('POST', 'test-url', null,
    -      { headers: {'Content-Type': 'text/plain', 'X-Made-Up': 'FooBar'} }).
    -      then(function(stubXhr) {
    -        assertEquals('POST', stubXhr.method);
    -        assertEquals('test-url', stubXhr.url);
    -        assertEquals('text/plain', stubXhr.headers['Content-Type']);
    -        assertEquals('FooBar', stubXhr.headers['X-Made-Up']);
    -      });
    -}
    -
    -function testSendPostHeadersWithFormData() {
    -  if (!goog.global['FormData']) { return; }
    -  var formData = new goog.global['FormData']();
    -  formData.append('name', 'value');
    -
    -  stubXhrToReturn(200);
    -  return xhr.send('POST', 'test-url', formData,
    -      { headers: {'Content-Type': 'text/plain', 'X-Made-Up': 'FooBar'} }).
    -      then(function(stubXhr) {
    -        assertEquals('POST', stubXhr.method);
    -        assertEquals('test-url', stubXhr.url);
    -        assertEquals('text/plain', stubXhr.headers['Content-Type']);
    -        assertEquals('FooBar', stubXhr.headers['X-Made-Up']);
    -      });
    -}
    -
    -function testSendNullPostHeaders() {
    -  stubXhrToReturn(200);
    -  return xhr.send('POST', 'test-url', null, {
    -    headers: {
    -      'Content-Type': null,
    -      'X-Made-Up': 'FooBar',
    -      'Y-Made-Up': null
    -    }
    -  }).then(function(stubXhr) {
    -    assertEquals('POST', stubXhr.method);
    -    assertEquals('test-url', stubXhr.url);
    -    assertEquals(undefined, stubXhr.headers['Content-Type']);
    -    assertEquals('FooBar', stubXhr.headers['X-Made-Up']);
    -    assertEquals(undefined, stubXhr.headers['Y-Made-Up']);
    -  });
    -}
    -
    -function testSendNullPostHeadersWithFormData() {
    -  if (!goog.global['FormData']) { return; }
    -  var formData = new goog.global['FormData']();
    -  formData.append('name', 'value');
    -
    -  stubXhrToReturn(200);
    -  return xhr.send('POST', 'test-url', formData, {
    -    headers: {
    -      'Content-Type': null,
    -      'X-Made-Up': 'FooBar',
    -      'Y-Made-Up': null
    -    }
    -  }).then(function(stubXhr) {
    -    assertEquals('POST', stubXhr.method);
    -    assertEquals('test-url', stubXhr.url);
    -    assertEquals(undefined, stubXhr.headers['Content-Type']);
    -    assertEquals('FooBar', stubXhr.headers['X-Made-Up']);
    -    assertEquals(undefined, stubXhr.headers['Y-Made-Up']);
    -  });
    -}
    -
    -function testSendWithCredentials() {
    -  stubXhrToReturn(200);
    -  return xhr.send('POST', 'test-url', null, {withCredentials: true}).
    -      then(function(stubXhr) {
    -        assertTrue('XHR should have been sent', stubXhr.sent);
    -        assertTrue(stubXhr.withCredentials);
    -      });
    -}
    -
    -function testSendWithMimeType() {
    -  stubXhrToReturn(200);
    -  return xhr.send('POST', 'test-url', null, {mimeType: 'text/plain'}).
    -      then(function(stubXhr) {
    -        assertTrue('XHR should have been sent', stubXhr.sent);
    -        assertEquals('text/plain', stubXhr.mimeType);
    -      });
    -}
    -
    -function testSendWithHttpError() {
    -  stubXhrToReturn(500);
    -  return xhr.send('POST', 'test-url', null).then(
    -      fail /* opt_onResolved */,
    -      function(err) {
    -        assertTrue(err instanceof xhr.HttpError);
    -        assertTrue(err.xhr.sent);
    -        assertEquals(500, err.status);
    -      });
    -}
    -
    -function testSendWithTimeoutNotHit() {
    -  stubXhrToReturn(200, null /* opt_responseText */, 1400 /* opt_latency */);
    -  return xhr.send('POST', 'test-url', null, {timeoutMs: 1500}).
    -      then(function(stubXhr) {
    -        assertTrue(mockClock.getTimeoutsMade() > 0);
    -        assertTrue('XHR should have been sent', stubXhr.sent);
    -        assertFalse('XHR should not have been aborted', stubXhr.aborted);
    -      });
    -}
    -
    -function testSendWithTimeoutHit() {
    -  stubXhrToReturn(200, null /* opt_responseText */, 50 /* opt_latency */);
    -  return xhr.send('POST', 'test-url', null, {timeoutMs: 50}).then(
    -      fail /* opt_onResolved */,
    -      function(err) {
    -        assertTrue('XHR should have been sent', err.xhr.sent);
    -        assertTrue('XHR should have been aborted', err.xhr.aborted);
    -        assertTrue(err instanceof xhr.TimeoutError);
    -      });
    -}
    -
    -function testCancelRequest() {
    -  stubXhrToReturn(200, null /* opt_responseText */, 25);
    -  var promise = xhr.send('GET', 'test-url', null, {timeoutMs: 50});
    -  promise.then(
    -      fail /* opt_onResolved */,
    -      function(error) {
    -        assertTrue('XHR should have been sent', error.xhr.sent);
    -        if (error instanceof goog.Promise.CancellationError) {
    -          error.xhr.abort();
    -        }
    -        assertTrue('XHR should have been aborted', error.xhr.aborted);
    -        assertTrue(error instanceof goog.Promise.CancellationError);
    -      });
    -  promise.cancel();
    -  return promise;
    -}
    -
    -function testGetJson() {
    -  var stubXhr = stubXhrToReturn(200, '{"a": 1, "b": 2}');
    -  xhr.getJson('test-url').then(function(responseObj) {
    -    assertObjectEquals({a: 1, b: 2}, responseObj);
    -  });
    -}
    -
    -function testGetJsonWithXssiPrefix() {
    -  stubXhrToReturn(200, 'while(1);\n{"a": 1, "b": 2}');
    -  return xhr.getJson('test-url', {xssiPrefix: 'while(1);\n'}).then(
    -      function(responseObj) {
    -        assertObjectEquals({a: 1, b: 2}, responseObj);
    -      });
    -}
    -
    -function testSendWithClientException() {
    -  stubXhrToThrow(new Error('CORS XHR with file:// schemas not allowed.'));
    -  return xhr.send('POST', 'file://test-url', null).then(
    -      fail /* opt_onResolved */,
    -      function(err) {
    -        assertFalse('XHR should not have been sent', err.xhr.sent);
    -        assertTrue(err instanceof Error);
    -        assertTrue(
    -            /CORS XHR with file:\/\/ schemas not allowed./.test(err.message));
    -      });
    -}
    -
    -function testSendWithFactory() {
    -  stubXhrToReturn(200);
    -  var options = {
    -    xmlHttpFactory: new goog.net.WrapperXmlHttpFactory(
    -        goog.partial(buildThrowingStubXhr, new Error('Bad factory')),
    -        goog.net.XmlHttp.getOptions)
    -  };
    -  return xhr.send('POST', 'file://test-url', null, options).then(
    -      fail /* opt_onResolved */,
    -      function(err) {
    -        assertTrue(err instanceof Error);
    -      });
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/object/object.js b/src/database/third_party/closure-library/closure/goog/labs/object/object.js
    deleted file mode 100644
    index ff961c7c6a6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/object/object.js
    +++ /dev/null
    @@ -1,47 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A labs location for functions destined for Closure's
    - * {@code goog.object} namespace.
    - * @author chrishenry@google.com (Chris Henry)
    - */
    -
    -goog.provide('goog.labs.object');
    -
    -
    -/**
    - * Whether two values are not observably distinguishable. This
    - * correctly detects that 0 is not the same as -0 and two NaNs are
    - * practically equivalent.
    - *
    - * The implementation is as suggested by harmony:egal proposal.
    - *
    - * @param {*} v The first value to compare.
    - * @param {*} v2 The second value to compare.
    - * @return {boolean} Whether two values are not observably distinguishable.
    - * @see http://wiki.ecmascript.org/doku.php?id=harmony:egal
    - */
    -goog.labs.object.is = function(v, v2) {
    -  if (v === v2) {
    -    // 0 === -0, but they are not identical.
    -    // We need the cast because the compiler requires that v2 is a
    -    // number (although 1/v2 works with non-number). We cast to ? to
    -    // stop the compiler from type-checking this statement.
    -    return v !== 0 || 1 / v === 1 / /** @type {?} */ (v2);
    -  }
    -
    -  // NaN is non-reflexive: NaN !== NaN, although they are identical.
    -  return v !== v && v2 !== v2;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/object/object_test.html b/src/database/third_party/closure-library/closure/goog/labs/object/object_test.html
    deleted file mode 100644
    index 0a86b6036e1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/object/object_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -  Author: chrishenry@google.com (Chris Henry)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.labs.object
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.labs.objectTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/object/object_test.js b/src/database/third_party/closure-library/closure/goog/labs/object/object_test.js
    deleted file mode 100644
    index f4db2f521f6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/object/object_test.js
    +++ /dev/null
    @@ -1,52 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.labs.objectTest');
    -goog.setTestOnly('goog.labs.objectTest');
    -
    -goog.require('goog.labs.object');
    -goog.require('goog.testing.jsunit');
    -
    -function testIs() {
    -  var object = {};
    -  assertTrue(goog.labs.object.is(object, object));
    -  assertFalse(goog.labs.object.is(object, {}));
    -
    -  assertTrue(goog.labs.object.is(NaN, NaN));
    -  assertTrue(goog.labs.object.is(0, 0));
    -  assertTrue(goog.labs.object.is(1, 1));
    -  assertTrue(goog.labs.object.is(-1, -1));
    -  assertTrue(goog.labs.object.is(123, 123));
    -  assertFalse(goog.labs.object.is(0, -0));
    -  assertFalse(goog.labs.object.is(-0, 0));
    -  assertFalse(goog.labs.object.is(0, 1));
    -
    -  assertTrue(goog.labs.object.is(true, true));
    -  assertTrue(goog.labs.object.is(false, false));
    -  assertFalse(goog.labs.object.is(true, false));
    -  assertFalse(goog.labs.object.is(false, true));
    -
    -  assertTrue(goog.labs.object.is('', ''));
    -  assertTrue(goog.labs.object.is('a', 'a'));
    -  assertFalse(goog.labs.object.is('', 'a'));
    -  assertFalse(goog.labs.object.is('a', ''));
    -  assertFalse(goog.labs.object.is('a', 'b'));
    -
    -  assertFalse(goog.labs.object.is(true, 'true'));
    -  assertFalse(goog.labs.object.is('true', true));
    -  assertFalse(goog.labs.object.is(false, 'false'));
    -  assertFalse(goog.labs.object.is('false', false));
    -  assertFalse(goog.labs.object.is(0, '0'));
    -  assertFalse(goog.labs.object.is('0', 0));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/pubsub/broadcastpubsub.js b/src/database/third_party/closure-library/closure/goog/labs/pubsub/broadcastpubsub.js
    deleted file mode 100644
    index 08de9d0366e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/pubsub/broadcastpubsub.js
    +++ /dev/null
    @@ -1,564 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.labs.pubsub.BroadcastPubSub');
    -
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.Timer');
    -goog.require('goog.array');
    -goog.require('goog.async.run');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventType');
    -goog.require('goog.json');
    -goog.require('goog.log');
    -goog.require('goog.math');
    -goog.require('goog.pubsub.PubSub');
    -goog.require('goog.storage.Storage');
    -goog.require('goog.storage.mechanism.HTML5LocalStorage');
    -goog.require('goog.string');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Topic-based publish/subscribe messaging implementation that provides
    - * communication between browsing contexts that share the same origin.
    - *
    - * Wrapper around PubSub that utilizes localStorage to broadcast publications to
    - * all browser windows with the same origin as the publishing context. This
    - * allows for topic-based publish/subscribe implementation of strings shared by
    - * all browser contexts that share the same origin.
    - *
    - * Delivery is guaranteed on all browsers except IE8 where topics expire after a
    - * timeout. Publishing of a topic within a callback function provides no
    - * guarantee on ordering in that there is a possiblilty that separate origin
    - * contexts may see topics in a different order.
    - *
    - * This class is not secure and in certain cases (e.g., a browser crash) data
    - * that is published can persist in localStorage indefinitely. Do not use this
    - * class to communicate private or confidential information.
    - *
    - * On IE8, localStorage is shared by the http and https origins. An attacker
    - * could possibly leverage this to publish to the secure origin.
    - *
    - * goog.labs.pubsub.BroadcastPubSub wraps an instance of PubSub rather than
    - * subclassing because the base PubSub class allows publishing of arbitrary
    - * objects.
    - *
    - * Special handling is done for the IE8 browsers. See the IE8_EVENTS_KEY_
    - * constant and the {@code publish} function for more information.
    - *
    - *
    - * @constructor @struct @extends {goog.Disposable}
    - * @suppress {checkStructDictInheritance}
    - */
    -goog.labs.pubsub.BroadcastPubSub = function() {
    -  goog.labs.pubsub.BroadcastPubSub.base(this, 'constructor');
    -  goog.labs.pubsub.BroadcastPubSub.instances_.push(this);
    -
    -  /** @private @const */
    -  this.pubSub_ = new goog.pubsub.PubSub();
    -  this.registerDisposable(this.pubSub_);
    -
    -  /** @private @const */
    -  this.handler_ = new goog.events.EventHandler(this);
    -  this.registerDisposable(this.handler_);
    -
    -  /** @private @const */
    -  this.logger_ = goog.log.getLogger('goog.labs.pubsub.BroadcastPubSub');
    -
    -  /** @private @const */
    -  this.mechanism_ = new goog.storage.mechanism.HTML5LocalStorage();
    -
    -  /** @private {goog.storage.Storage} */
    -  this.storage_ = null;
    -
    -  /** @private {Object<string, number>} */
    -  this.ie8LastEventTimes_ = null;
    -
    -  /** @private {number} */
    -  this.ie8StartupTimestamp_ = goog.now() - 1;
    -
    -  if (this.mechanism_.isAvailable()) {
    -    this.storage_ = new goog.storage.Storage(this.mechanism_);
    -
    -    var target = window;
    -    if (goog.labs.pubsub.BroadcastPubSub.IS_IE8_) {
    -      this.ie8LastEventTimes_ = {};
    -
    -      target = document;
    -    }
    -    this.handler_.listen(target,
    -        goog.events.EventType.STORAGE,
    -        this.handleStorageEvent_);
    -  }
    -};
    -goog.inherits(goog.labs.pubsub.BroadcastPubSub, goog.Disposable);
    -
    -
    -/** @private @const {!Array<!goog.labs.pubsub.BroadcastPubSub>} */
    -goog.labs.pubsub.BroadcastPubSub.instances_ = [];
    -
    -
    -/**
    - * SitePubSub namespace for localStorage.
    - * @private @const
    - */
    -goog.labs.pubsub.BroadcastPubSub.STORAGE_KEY_ = '_closure_bps';
    -
    -
    -/**
    - * Handle the storage event and possibly dispatch topics.
    - * @param {!goog.events.Event} e Event object.
    - * @private
    - */
    -goog.labs.pubsub.BroadcastPubSub.prototype.handleStorageEvent_ =
    -    function(e) {
    -  if (goog.labs.pubsub.BroadcastPubSub.IS_IE8_) {
    -    // Even though we have the event, IE8 doesn't update our localStorage until
    -    // after we handle the actual event.
    -    goog.async.run(this.handleIe8StorageEvent_, this);
    -    return;
    -  }
    -
    -  var browserEvent = e.getBrowserEvent();
    -  if (browserEvent.key !=
    -      goog.labs.pubsub.BroadcastPubSub.STORAGE_KEY_) {
    -    return;
    -  }
    -
    -  var data = goog.json.parse(browserEvent.newValue);
    -  var args = goog.isObject(data) && data['args'];
    -  if (goog.isArray(args) && goog.array.every(args, goog.isString)) {
    -    this.dispatch_(args);
    -  } else {
    -    goog.log.warning(this.logger_, 'storage event contained invalid arguments');
    -  }
    -};
    -
    -
    -/**
    - * Dispatches args on the internal pubsub queue.
    - * @param {!Array<string>} args The arguments to publish.
    - * @private
    - */
    -goog.labs.pubsub.BroadcastPubSub.prototype.dispatch_ = function(args) {
    -  goog.pubsub.PubSub.prototype.publish.apply(this.pubSub_, args);
    -};
    -
    -
    -/**
    - * Publishes a message to a topic. Remote subscriptions in other tabs/windows
    - * are dispatched via local storage events. Local subscriptions are called
    - * asynchronously via Timer event in order to simulate remote behavior locally.
    - * @param {string} topic Topic to publish to.
    - * @param {...string} var_args String arguments that are applied to each
    - *     subscription function.
    - */
    -goog.labs.pubsub.BroadcastPubSub.prototype.publish =
    -    function(topic, var_args) {
    -  var args = goog.array.toArray(arguments);
    -
    -  // Dispatch to localStorage.
    -  if (this.storage_) {
    -    // Update topics to use the optional prefix.
    -    var now = goog.now();
    -    var data = {
    -      'args': args,
    -      'timestamp': now
    -    };
    -
    -    if (!goog.labs.pubsub.BroadcastPubSub.IS_IE8_) {
    -      // Generated events will contain all the data in modern browsers.
    -      this.storage_.set(goog.labs.pubsub.BroadcastPubSub.STORAGE_KEY_, data);
    -      this.storage_.remove(goog.labs.pubsub.BroadcastPubSub.STORAGE_KEY_);
    -    } else {
    -      // With IE8 we need to manage our own events queue.
    -      var events = null;
    -      /** @preserveTry */
    -      try {
    -        events = this.storage_.get(
    -            goog.labs.pubsub.BroadcastPubSub.IE8_EVENTS_KEY_);
    -      } catch (ex) {
    -        goog.log.error(this.logger_,
    -            'publish encountered invalid event queue at ' +
    -            goog.labs.pubsub.BroadcastPubSub.IE8_EVENTS_KEY_);
    -      }
    -      if (!goog.isArray(events)) {
    -        events = [];
    -      }
    -      // Avoid a race condition where we're publishing in the same
    -      // millisecond that another event that may be getting
    -      // processed. In short, we try go guarantee that whatever event
    -      // we put on the event queue has a timestamp that is older than
    -      // any other timestamp in the queue.
    -      var lastEvent = events[events.length - 1];
    -      var lastTimestamp = lastEvent && lastEvent['timestamp'] ||
    -          this.ie8StartupTimestamp_;
    -      if (lastTimestamp >= now) {
    -        now = lastTimestamp +
    -            goog.labs.pubsub.BroadcastPubSub.IE8_TIMESTAMP_UNIQUE_OFFSET_MS_;
    -        data['timestamp'] = now;
    -      }
    -      events.push(data);
    -      this.storage_.set(
    -          goog.labs.pubsub.BroadcastPubSub.IE8_EVENTS_KEY_, events);
    -
    -      // Cleanup this event in IE8_EVENT_LIFETIME_MS_ milliseconds.
    -      goog.Timer.callOnce(goog.bind(this.cleanupIe8StorageEvents_, this, now),
    -          goog.labs.pubsub.BroadcastPubSub.IE8_EVENT_LIFETIME_MS_);
    -    }
    -  }
    -
    -  // W3C spec is to not dispatch the storage event to the same window that
    -  // modified localStorage. For conforming browsers we have to manually dispatch
    -  // the publish event to subscriptions on instances of BroadcastPubSub in the
    -  // current window.
    -  if (!goog.userAgent.IE) {
    -    // Dispatch the publish event to local instances asynchronously to fix some
    -    // quirks with timings. The result is that all subscriptions are dispatched
    -    // before any future publishes are processed. The effect is that
    -    // subscriptions in the same window are dispatched as if they are the result
    -    // of a publish from another tab.
    -    goog.array.forEach(goog.labs.pubsub.BroadcastPubSub.instances_,
    -        function(instance) {
    -          goog.async.run(goog.bind(instance.dispatch_, instance, args));
    -        });
    -  }
    -};
    -
    -
    -/**
    - * Unsubscribes a function from a topic. Only deletes the first match found.
    - * Returns a Boolean indicating whether a subscription was removed.
    - * @param {string} topic Topic to unsubscribe from.
    - * @param {Function} fn Function to unsubscribe.
    - * @param {Object=} opt_context Object in whose context the function was to be
    - *     called (the global scope if none).
    - * @return {boolean} Whether a matching subscription was removed.
    - */
    -goog.labs.pubsub.BroadcastPubSub.prototype.unsubscribe =
    -    function(topic, fn, opt_context) {
    -  return this.pubSub_.unsubscribe(topic, fn, opt_context);
    -};
    -
    -
    -/**
    - * Removes a subscription based on the key returned by {@link #subscribe}. No-op
    - * if no matching subscription is found. Returns a Boolean indicating whether a
    - * subscription was removed.
    - * @param {number} key Subscription key.
    - * @return {boolean} Whether a matching subscription was removed.
    - */
    -goog.labs.pubsub.BroadcastPubSub.prototype.unsubscribeByKey = function(key) {
    -  return this.pubSub_.unsubscribeByKey(key);
    -};
    -
    -
    -/**
    - * Subscribes a function to a topic. The function is invoked as a method on the
    - * given {@code opt_context} object, or in the global scope if no context is
    - * specified. Subscribing the same function to the same topic multiple times
    - * will result in multiple function invocations while publishing. Returns a
    - * subscription key that can be used to unsubscribe the function from the topic
    - * via {@link #unsubscribeByKey}.
    - * @param {string} topic Topic to subscribe to.
    - * @param {Function} fn Function to be invoked when a message is published to
    - *     the given topic.
    - * @param {Object=} opt_context Object in whose context the function is to be
    - *     called (the global scope if none).
    - * @return {number} Subscription key.
    - */
    -goog.labs.pubsub.BroadcastPubSub.prototype.subscribe =
    -    function(topic, fn, opt_context) {
    -  return this.pubSub_.subscribe(topic, fn, opt_context);
    -};
    -
    -
    -/**
    - * Subscribes a single-use function to a topic. The function is invoked as a
    - * method on the given {@code opt_context} object, or in the global scope if no
    - * context is specified, and is then unsubscribed. Returns a subscription key
    - * that can be used to unsubscribe the function from the topic via {@link
    - * #unsubscribeByKey}.
    - * @param {string} topic Topic to subscribe to.
    - * @param {Function} fn Function to be invoked once and then unsubscribed when
    - *     a message is published to the given topic.
    - * @param {Object=} opt_context Object in whose context the function is to be
    - *     called (the global scope if none).
    - * @return {number} Subscription key.
    - */
    -goog.labs.pubsub.BroadcastPubSub.prototype.subscribeOnce =
    -    function(topic, fn, opt_context) {
    -  return this.pubSub_.subscribeOnce(topic, fn, opt_context);
    -};
    -
    -
    -/**
    - * Returns the number of subscriptions to the given topic (or all topics if
    - * unspecified).
    - * @param {string=} opt_topic The topic (all topics if unspecified).
    - * @return {number} Number of subscriptions to the topic.
    - */
    -goog.labs.pubsub.BroadcastPubSub.prototype.getCount = function(opt_topic) {
    -  return this.pubSub_.getCount(opt_topic);
    -};
    -
    -
    -/**
    - * Clears the subscription list for a topic, or all topics if unspecified.
    - * @param {string=} opt_topic Topic to clear (all topics if unspecified).
    - */
    -goog.labs.pubsub.BroadcastPubSub.prototype.clear = function(opt_topic) {
    -  this.pubSub_.clear(opt_topic);
    -};
    -
    -
    -/** @override */
    -goog.labs.pubsub.BroadcastPubSub.prototype.disposeInternal = function() {
    -  goog.array.remove(goog.labs.pubsub.BroadcastPubSub.instances_, this);
    -  if (goog.labs.pubsub.BroadcastPubSub.IS_IE8_ &&
    -      goog.isDefAndNotNull(this.storage_) &&
    -      goog.labs.pubsub.BroadcastPubSub.instances_.length == 0) {
    -    this.storage_.remove(
    -        goog.labs.pubsub.BroadcastPubSub.IE8_EVENTS_KEY_);
    -  }
    -  goog.labs.pubsub.BroadcastPubSub.base(this, 'disposeInternal');
    -};
    -
    -
    -/**
    - * Prefix for IE8 storage event queue keys.
    - * @private @const
    - */
    -goog.labs.pubsub.BroadcastPubSub.IE8_EVENTS_KEY_PREFIX_ = '_closure_bps_ie8evt';
    -
    -
    -/**
    - * Time (in milliseconds) that IE8 events should live. If they are not
    - * processed by other windows in this time they will be removed.
    - * @private @const
    - */
    -goog.labs.pubsub.BroadcastPubSub.IE8_EVENT_LIFETIME_MS_ = 1000 * 10;
    -
    -
    -/**
    - * Time (in milliseconds) that the IE8 event queue should live.
    - * @private @const
    - */
    -goog.labs.pubsub.BroadcastPubSub.IE8_QUEUE_LIFETIME_MS_ = 1000 * 30;
    -
    -
    -/**
    - * Time delta that is used to distinguish between timestamps of events that
    - * happen in the same millisecond.
    - * @private @const
    - */
    -goog.labs.pubsub.BroadcastPubSub.IE8_TIMESTAMP_UNIQUE_OFFSET_MS_ = .01;
    -
    -
    -/**
    - * Name for this window/tab's storage key that stores its IE8 event queue.
    - *
    - * The browsers storage events are supposed to track the key which was changed,
    - * the previous value for that key, and the new value of that key. Our
    - * implementation is dependent on this information but IE8 doesn't provide it.
    - * We implement our own event queue using local storage to track this
    - * information in IE8. Since all instances share the same localStorage context
    - * in a particular tab, we share the events queue.
    - *
    - * This key is a static member shared by all instances of BroadcastPubSub in the
    - * same Window context. To avoid read-update-write contention, this key is only
    - * written in a single context in the cleanupIe8StorageEvents_ function. Since
    - * instances in other contexts will read this key there is code in the {@code
    - * publish} function to make sure timestamps are unique even within the same
    - * millisecond.
    - *
    - * @private @const
    - */
    -goog.labs.pubsub.BroadcastPubSub.IE8_EVENTS_KEY_ =
    -    goog.labs.pubsub.BroadcastPubSub.IE8_EVENTS_KEY_PREFIX_ +
    -        goog.math.randomInt(1e9);
    -
    -
    -/**
    - * All instances of this object should access elements using strings and not
    - * attributes. Since we are communicating across browser tabs we could be
    - * dealing with different versions of javascript and thus may have different
    - * obfuscation in each tab.
    - * @private @typedef {{'timestamp': number, 'args': !Array<string>}}
    - */
    -goog.labs.pubsub.BroadcastPubSub.Ie8Event_;
    -
    -
    -/** @private @const */
    -goog.labs.pubsub.BroadcastPubSub.IS_IE8_ =
    -    goog.userAgent.IE && goog.userAgent.DOCUMENT_MODE == 8;
    -
    -
    -/**
    - * Validates an event object.
    - * @param {!Object} obj The object to validate as an Event.
    - * @return {?goog.labs.pubsub.BroadcastPubSub.Ie8Event_} A valid
    - *     event object or null if the object is invalid.
    - * @private
    - */
    -goog.labs.pubsub.BroadcastPubSub.validateIe8Event_ = function(obj) {
    -  if (goog.isObject(obj) && goog.isNumber(obj['timestamp']) &&
    -      goog.array.every(obj['args'], goog.isString)) {
    -    return {'timestamp': obj['timestamp'], 'args': obj['args']};
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * Returns an array of valid IE8 events.
    - * @param {!Array<!Object>} events Possible IE8 events.
    - * @return {!Array<!goog.labs.pubsub.BroadcastPubSub.Ie8Event_>}
    - *     Valid IE8 events.
    - * @private
    - */
    -goog.labs.pubsub.BroadcastPubSub.filterValidIe8Events_ = function(events) {
    -  return goog.array.filter(goog.array.map(events,
    -      goog.labs.pubsub.BroadcastPubSub.validateIe8Event_),
    -      goog.isDefAndNotNull);
    -};
    -
    -
    -/**
    - * Returns the IE8 events that have a timestamp later than the provided
    - * timestamp.
    - * @param {number} timestamp Expired timestamp.
    - * @param {!Array<!goog.labs.pubsub.BroadcastPubSub.Ie8Event_>} events
    - *     Possible IE8 events.
    - * @return {!Array<!goog.labs.pubsub.BroadcastPubSub.Ie8Event_>}
    - *     Unexpired IE8 events.
    - * @private
    - */
    -goog.labs.pubsub.BroadcastPubSub.filterNewIe8Events_ =
    -    function(timestamp, events) {
    -  return goog.array.filter(events, function(event) {
    -    return event['timestamp'] > timestamp;
    -  });
    -};
    -
    -
    -/**
    - * Processes the events array for key if all elements are valid IE8 events.
    - * @param {string} key The key in localStorage where the event queue is stored.
    - * @param {!Array<!Object>} events Array of possible events stored at key.
    - * @return {boolean} Return true if all elements in the array are valid
    - *     events, false otherwise.
    - * @private
    - */
    -goog.labs.pubsub.BroadcastPubSub.prototype.maybeProcessIe8Events_ =
    -    function(key, events) {
    -  if (!events.length) {
    -    return false;
    -  }
    -
    -  var validEvents =
    -      goog.labs.pubsub.BroadcastPubSub.filterValidIe8Events_(events);
    -  if (validEvents.length == events.length) {
    -    var lastTimestamp = goog.array.peek(validEvents)['timestamp'];
    -    var previousTime =
    -        this.ie8LastEventTimes_[key] || this.ie8StartupTimestamp_;
    -    if (lastTimestamp > previousTime -
    -        goog.labs.pubsub.BroadcastPubSub.IE8_QUEUE_LIFETIME_MS_) {
    -      this.ie8LastEventTimes_[key] = lastTimestamp;
    -      validEvents = goog.labs.pubsub.BroadcastPubSub.filterNewIe8Events_(
    -          previousTime, validEvents);
    -      for (var i = 0, event; event = validEvents[i]; i++) {
    -        this.dispatch_(event['args']);
    -      }
    -      return true;
    -    }
    -  } else {
    -    goog.log.warning(this.logger_, 'invalid events found in queue ' + key);
    -  }
    -
    -  return false;
    -};
    -
    -
    -/**
    - * Handle the storage event and possibly dispatch events. Looks through all keys
    - * in localStorage for valid keys.
    - * @private
    - */
    -goog.labs.pubsub.BroadcastPubSub.prototype.handleIe8StorageEvent_ = function() {
    -  var numKeys = this.mechanism_.getCount();
    -  for (var idx = 0; idx < numKeys; idx++) {
    -    var key = this.mechanism_.key(idx);
    -    // Don't process events we generated. The W3C standard says that storage
    -    // events should be queued by the browser for each window whose document's
    -    // storage object is affected by a change in localStorage. Chrome, Firefox,
    -    // and modern IE don't dispatch the event to the window which made the
    -    // change. This code simulates that behavior in IE8.
    -    if (!(goog.isString(key) && goog.string.startsWith(
    -        key, goog.labs.pubsub.BroadcastPubSub.IE8_EVENTS_KEY_PREFIX_))) {
    -      continue;
    -    }
    -
    -    var events = null;
    -    /** @preserveTry */
    -    try {
    -      events = this.storage_.get(key);
    -    } catch (ex) {
    -      goog.log.warning(this.logger_, 'invalid remote event queue ' + key);
    -    }
    -
    -    if (!(goog.isArray(events) && this.maybeProcessIe8Events_(key, events))) {
    -      // Events is not an array, empty, contains invalid events, or expired.
    -      this.storage_.remove(key);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Cleanup our IE8 event queue by removing any events that come at or before the
    - * given timestamp.
    - * @param {number} timestamp Maximum timestamp to remove from the queue.
    - * @private
    - */
    -goog.labs.pubsub.BroadcastPubSub.prototype.cleanupIe8StorageEvents_ =
    -    function(timestamp) {
    -  var events = null;
    -  /** @preserveTry */
    -  try {
    -    events = this.storage_.get(
    -        goog.labs.pubsub.BroadcastPubSub.IE8_EVENTS_KEY_);
    -  } catch (ex) {
    -    goog.log.error(this.logger_,
    -        'cleanup encountered invalid event queue key ' +
    -        goog.labs.pubsub.BroadcastPubSub.IE8_EVENTS_KEY_);
    -  }
    -  if (!goog.isArray(events)) {
    -    this.storage_.remove(goog.labs.pubsub.BroadcastPubSub.IE8_EVENTS_KEY_);
    -    return;
    -  }
    -
    -  events = goog.labs.pubsub.BroadcastPubSub.filterNewIe8Events_(
    -      timestamp, goog.labs.pubsub.BroadcastPubSub.filterValidIe8Events_(
    -          events));
    -
    -  if (events.length > 0) {
    -    this.storage_.set(goog.labs.pubsub.BroadcastPubSub.IE8_EVENTS_KEY_, events);
    -  } else {
    -    this.storage_.remove(goog.labs.pubsub.BroadcastPubSub.IE8_EVENTS_KEY_);
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/pubsub/broadcastpubsub_test.js b/src/database/third_party/closure-library/closure/goog/labs/pubsub/broadcastpubsub_test.js
    deleted file mode 100644
    index a63005b9397..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/pubsub/broadcastpubsub_test.js
    +++ /dev/null
    @@ -1,1059 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.labs.pubsub.BroadcastPubSubTest');
    -goog.setTestOnly('goog.labs.pubsub.BroadcastPubSubTest');
    -
    -
    -goog.require('goog.array');
    -goog.require('goog.debug.Logger');
    -goog.require('goog.json');
    -goog.require('goog.labs.pubsub.BroadcastPubSub');
    -goog.require('goog.storage.Storage');
    -goog.require('goog.structs.Map');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.events.Event');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.mockmatchers');
    -goog.require('goog.testing.mockmatchers.ArgumentMatcher');
    -goog.require('goog.testing.recordFunction');
    -goog.require('goog.userAgent');
    -
    -
    -/** @type {goog.labs.pubsub.BroadcastPubSub} */
    -var broadcastPubSub;
    -
    -
    -/** @type {goog.testing.MockControl} */
    -var mockControl;
    -
    -
    -/** @type {goog.testing.MockClock} */
    -var mockClock;
    -
    -
    -/** @type {goog.testing.MockInterface} */
    -var mockStorage;
    -
    -
    -/** @type {goog.testing.MockInterface} */
    -var mockStorageCtor;
    -
    -
    -/** @type {goog.structs.Map} */
    -var mockHtml5LocalStorage;
    -
    -
    -/** @type {goog.testing.MockInterface} */
    -var mockHTML5LocalStorageCtor;
    -
    -
    -/** @const {boolean} */
    -var isIe8 = goog.userAgent.IE && goog.userAgent.DOCUMENT_MODE == 8;
    -
    -
    -/**
    - * Sends a remote storage event with special handling for IE8. With IE8 an
    - * event is pushed to the event queue stored in local storage as a result of
    - * behaviour by the mockHtml5LocalStorage instanciated when using IE8 an event
    - * is automatically generated in the local browser context. For other browsers
    - * this simply creates a new browser event.
    - * @param {{'args': !Array<string>, 'timestamp': number}} data Value stored
    - *     in localStorage which generated the remote event.
    - */
    -function remoteStorageEvent(data) {
    -  if (!isIe8) {
    -    var event = new goog.testing.events.Event('storage', window);
    -    event.key = goog.labs.pubsub.BroadcastPubSub.STORAGE_KEY_;
    -    event.newValue = goog.json.serialize(data);
    -    goog.testing.events.fireBrowserEvent(event);
    -  } else {
    -    var uniqueKey =
    -        goog.labs.pubsub.BroadcastPubSub.IE8_EVENTS_KEY_PREFIX_ +
    -        '1234567890';
    -    var ie8Events = mockHtml5LocalStorage.get(uniqueKey);
    -    if (goog.isDefAndNotNull(ie8Events)) {
    -      ie8Events = goog.json.parse(ie8Events);
    -      // Events should never overlap in IE8 mode.
    -      if (ie8Events.length > 0 &&
    -          ie8Events[ie8Events.length - 1]['timestamp'] >=
    -          data['timestamp']) {
    -        data['timestamp'] =
    -            ie8Events[ie8Events.length - 1]['timestamp'] +
    -            goog.labs.pubsub.BroadcastPubSub.
    -            IE8_TIMESTAMP_UNIQUE_OFFSET_MS_;
    -      }
    -    } else {
    -      ie8Events = [];
    -    }
    -    ie8Events.push(data);
    -    // This will cause an event.
    -    mockHtml5LocalStorage.set(uniqueKey, goog.json.serialize(ie8Events));
    -  }
    -}
    -
    -function setUp() {
    -  mockControl = new goog.testing.MockControl();
    -
    -  mockClock = new goog.testing.MockClock(true);
    -  // Time should never be 0...
    -  mockClock.tick();
    -  /** @suppress {missingRequire} */
    -  mockHTML5LocalStorageCtor = mockControl.createConstructorMock(
    -      goog.storage.mechanism, 'HTML5LocalStorage');
    -
    -  mockHtml5LocalStorage = new goog.structs.Map();
    -
    -  // The builtin localStorage returns null instead of undefined.
    -  var originalGetFn = goog.bind(mockHtml5LocalStorage.get,
    -      mockHtml5LocalStorage);
    -  mockHtml5LocalStorage.get = function(key) {
    -    var value = originalGetFn(key);
    -    if (!goog.isDef(value)) {
    -      return null;
    -    }
    -    return value;
    -  };
    -  mockHtml5LocalStorage.key = function(idx) {
    -    return mockHtml5LocalStorage.getKeys()[idx];
    -  };
    -  mockHtml5LocalStorage.isAvailable = function() {
    -    return true;
    -  };
    -
    -
    -  // IE has problems. IE9+ still dispatches storage events locally. IE8 also
    -  // doesn't include the key/value information. So for IE, everytime we get a
    -  // "set" on localStorage we simulate for the appropriate browser.
    -  if (goog.userAgent.IE) {
    -    var target = isIe8 ? document : window;
    -    var originalSetFn = goog.bind(mockHtml5LocalStorage.set,
    -        mockHtml5LocalStorage);
    -    mockHtml5LocalStorage.set = function(key, value) {
    -      originalSetFn(key, value);
    -      var event = new goog.testing.events.Event('storage', target);
    -      if (!isIe8) {
    -        event.key = key;
    -        event.newValue = value;
    -      }
    -      goog.testing.events.fireBrowserEvent(event);
    -    };
    -  }
    -
    -}
    -
    -function tearDown() {
    -  mockControl.$tearDown();
    -  mockClock.dispose();
    -  broadcastPubSub = undefined;
    -}
    -
    -
    -function testConstructor() {
    -  mockHTML5LocalStorageCtor().$returns(mockHtml5LocalStorage);
    -  mockControl.$replayAll();
    -  broadcastPubSub = new goog.labs.pubsub.BroadcastPubSub();
    -  broadcastPubSub.logger_.setLevel(goog.debug.Logger.Level.OFF);
    -  assertNotNullNorUndefined(
    -      'BroadcastChannel instance must not be null', broadcastPubSub);
    -  assertTrue('BroadcastChannel instance must have the expected type',
    -      broadcastPubSub instanceof goog.labs.pubsub.BroadcastPubSub);
    -  assertArrayEquals(
    -      goog.labs.pubsub.BroadcastPubSub.instances_, [broadcastPubSub]);
    -  broadcastPubSub.dispose();
    -  mockControl.$verifyAll();
    -  assertNotNullNorUndefined(
    -      'Storage should not be undefined or null in broadcastPubSub.',
    -      broadcastPubSub.storage_);
    -  assertArrayEquals(goog.labs.pubsub.BroadcastPubSub.instances_, []);
    -}
    -
    -
    -function testConstructor_noLocalStorage() {
    -  mockHTML5LocalStorageCtor().$returns({isAvailable: function() {
    -    return false;
    -  }});
    -  mockControl.$replayAll();
    -  broadcastPubSub = new goog.labs.pubsub.BroadcastPubSub();
    -  broadcastPubSub.logger_.setLevel(goog.debug.Logger.Level.OFF);
    -  assertNotNullNorUndefined(
    -      'BroadcastChannel instance must not be null', broadcastPubSub);
    -  assertTrue('BroadcastChannel instance must have the expected type',
    -      broadcastPubSub instanceof goog.labs.pubsub.BroadcastPubSub);
    -  assertArrayEquals(
    -      goog.labs.pubsub.BroadcastPubSub.instances_, [broadcastPubSub]);
    -  broadcastPubSub.dispose();
    -  mockControl.$verifyAll();
    -  assertNull(
    -      'Storage should be null in broadcastPubSub.', broadcastPubSub.storage_);
    -  assertArrayEquals(goog.labs.pubsub.BroadcastPubSub.instances_, []);
    -}
    -
    -
    -/** Verify we cleanup after ourselves. */
    -function testDispose() {
    -  mockHTML5LocalStorageCtor().$returns(mockHtml5LocalStorage);
    -  mockHTML5LocalStorageCtor().$returns(mockHtml5LocalStorage);
    -  var mockStorage = mockControl.createLooseMock(goog.storage.Storage);
    -
    -  var mockStorageCtor = mockControl.createConstructorMock(
    -      goog.storage, 'Storage');
    -
    -  mockStorageCtor(mockHtml5LocalStorage).$returns(mockStorage);
    -  mockStorageCtor(mockHtml5LocalStorage).$returns(mockStorage);
    -
    -  if (isIe8) {
    -    mockStorage.remove(
    -        goog.labs.pubsub.BroadcastPubSub.IE8_EVENTS_KEY_);
    -  }
    -
    -  mockControl.$replayAll();
    -  broadcastPubSub = new goog.labs.pubsub.BroadcastPubSub();
    -  broadcastPubSub.logger_.setLevel(goog.debug.Logger.Level.OFF);
    -
    -  var broadcastPubSubExtra = new goog.labs.pubsub.BroadcastPubSub();
    -  assertArrayEquals(goog.labs.pubsub.BroadcastPubSub.instances_,
    -      [broadcastPubSub, broadcastPubSubExtra]);
    -
    -  assertFalse('BroadcastChannel extra instance must not have been disposed of',
    -      broadcastPubSubExtra.isDisposed());
    -  broadcastPubSubExtra.dispose();
    -  assertTrue('BroadcastChannel extra instance must have been disposed of',
    -      broadcastPubSubExtra.isDisposed());
    -  assertFalse('BroadcastChannel instance must not have been disposed of',
    -      broadcastPubSub.isDisposed());
    -
    -  assertArrayEquals(
    -      goog.labs.pubsub.BroadcastPubSub.instances_, [broadcastPubSub]);
    -  assertFalse('BroadcastChannel instance must not have been disposed of',
    -      broadcastPubSub.isDisposed());
    -  broadcastPubSub.dispose();
    -  assertTrue('BroadcastChannel instance must have been disposed of',
    -      broadcastPubSub.isDisposed());
    -  assertArrayEquals(goog.labs.pubsub.BroadcastPubSub.instances_, []);
    -  mockControl.$verifyAll();
    -}
    -
    -
    -/**
    - * Tests related to remote events that an instance of BroadcastChannel
    - * should handle.
    - */
    -function testHandleRemoteEvent() {
    -  mockHTML5LocalStorageCtor().$returns(mockHtml5LocalStorage);
    -  var foo = mockControl.createFunctionMock();
    -  foo('x', 'y').$times(2);
    -
    -  var context = {'foo': 'bar'};
    -  var bar = goog.testing.recordFunction();
    -
    -  mockControl.$replayAll();
    -  broadcastPubSub = new goog.labs.pubsub.BroadcastPubSub();
    -  broadcastPubSub.logger_.setLevel(goog.debug.Logger.Level.OFF);
    -  var eventData = {
    -    'args': ['someTopic', 'x', 'y'],
    -    'timestamp': goog.now()
    -  };
    -
    -  broadcastPubSub.subscribe('someTopic', foo);
    -  broadcastPubSub.subscribe('someTopic', bar, context);
    -
    -  remoteStorageEvent(eventData);
    -  mockClock.tick();
    -
    -  assertEquals(1, bar.getCallCount());
    -  assertEquals(context, bar.getLastCall().getThis());
    -  assertArrayEquals(['x', 'y'], bar.getLastCall().getArguments());
    -
    -  broadcastPubSub.unsubscribe('someTopic', foo);
    -  eventData['timestamp'] = goog.now();
    -  remoteStorageEvent(eventData);
    -  mockClock.tick();
    -
    -  assertEquals(2, bar.getCallCount());
    -  assertEquals(context, bar.getLastCall().getThis());
    -  assertArrayEquals(['x', 'y'], bar.getLastCall().getArguments());
    -
    -  broadcastPubSub.subscribe('someTopic', foo);
    -  broadcastPubSub.unsubscribe('someTopic', bar, context);
    -  eventData['timestamp'] = goog.now();
    -  remoteStorageEvent(eventData);
    -  mockClock.tick();
    -
    -  assertEquals(2, bar.getCallCount());
    -  broadcastPubSub.dispose();
    -  mockControl.$verifyAll();
    -}
    -
    -
    -function testHandleRemoteEventSubscribeOnce() {
    -  mockHTML5LocalStorageCtor().$returns(mockHtml5LocalStorage);
    -  var foo = mockControl.createFunctionMock();
    -  foo('x', 'y');
    -
    -  mockControl.$replayAll();
    -  broadcastPubSub = new goog.labs.pubsub.BroadcastPubSub();
    -  broadcastPubSub.logger_.setLevel(goog.debug.Logger.Level.OFF);
    -
    -  broadcastPubSub.subscribeOnce('someTopic', foo);
    -  assertEquals('BroadcastChannel must have one subscriber',
    -      1, broadcastPubSub.getCount());
    -
    -  remoteStorageEvent({
    -    'args': ['someTopic', 'x', 'y'],
    -    'timestamp': goog.now()
    -  });
    -  mockClock.tick();
    -
    -  assertEquals(
    -      'BroadcastChannel must have no subscribers after receiving the event',
    -      0, broadcastPubSub.getCount());
    -  broadcastPubSub.dispose();
    -  mockControl.$verifyAll();
    -}
    -
    -
    -function testHandleQueuedRemoteEvents() {
    -  mockHTML5LocalStorageCtor().$returns(mockHtml5LocalStorage);
    -  var foo = mockControl.createFunctionMock();
    -  var bar = mockControl.createFunctionMock();
    -
    -  foo('x', 'y');
    -  bar('d', 'c');
    -
    -  mockControl.$replayAll();
    -
    -  broadcastPubSub = new goog.labs.pubsub.BroadcastPubSub();
    -  broadcastPubSub.logger_.setLevel(goog.debug.Logger.Level.OFF);
    -  broadcastPubSub.subscribe('fooTopic', foo);
    -  broadcastPubSub.subscribe('barTopic', bar);
    -
    -  var eventData = {
    -    'args': ['fooTopic', 'x', 'y'],
    -    'timestamp': goog.now()
    -  };
    -  remoteStorageEvent(eventData);
    -
    -  var eventData = {
    -    'args': ['barTopic', 'd', 'c'],
    -    'timestamp': goog.now()
    -  };
    -  remoteStorageEvent(eventData);
    -  mockClock.tick();
    -
    -  broadcastPubSub.dispose();
    -  mockControl.$verifyAll();
    -}
    -
    -
    -function testHandleRemoteEventsUnsubscribe() {
    -  mockHTML5LocalStorageCtor().$returns(mockHtml5LocalStorage);
    -  var foo = mockControl.createFunctionMock();
    -  var bar = mockControl.createFunctionMock();
    -
    -  foo('x', 'y').$does(function() {
    -    broadcastPubSub.unsubscribe('barTopic', bar);
    -  });
    -
    -  mockControl.$replayAll();
    -
    -  broadcastPubSub = new goog.labs.pubsub.BroadcastPubSub();
    -  broadcastPubSub.logger_.setLevel(goog.debug.Logger.Level.OFF);
    -  broadcastPubSub.subscribe('fooTopic', foo);
    -  broadcastPubSub.subscribe('barTopic', bar);
    -
    -  var eventData = {
    -    'args': ['fooTopic', 'x', 'y'],
    -    'timestamp': goog.now()
    -  };
    -  remoteStorageEvent(eventData);
    -  mockClock.tick();
    -
    -  var eventData = {
    -    'args': ['barTopic', 'd', 'c'],
    -    'timestamp': goog.now()
    -  };
    -  remoteStorageEvent(eventData);
    -  mockClock.tick();
    -
    -  broadcastPubSub.dispose();
    -  mockControl.$verifyAll();
    -}
    -
    -
    -function testHandleRemoteEventsCalledOnce() {
    -  mockHTML5LocalStorageCtor().$returns(mockHtml5LocalStorage);
    -  var foo = mockControl.createFunctionMock();
    -  foo('x', 'y');
    -
    -  mockControl.$replayAll();
    -
    -  broadcastPubSub = new goog.labs.pubsub.BroadcastPubSub();
    -  broadcastPubSub.logger_.setLevel(goog.debug.Logger.Level.OFF);
    -  broadcastPubSub.subscribeOnce('someTopic', foo);
    -
    -  var eventData = {
    -    'args': ['someTopic', 'x', 'y'],
    -    'timestamp': goog.now()
    -  };
    -  remoteStorageEvent(eventData);
    -  mockClock.tick();
    -
    -  var eventData = {
    -    'args': ['someTopic', 'x', 'y'],
    -    'timestamp': goog.now()
    -  };
    -  remoteStorageEvent(eventData);
    -  mockClock.tick();
    -
    -  broadcastPubSub.dispose();
    -  mockControl.$verifyAll();
    -}
    -
    -
    -function testHandleRemoteEventNestedPublish() {
    -  mockHTML5LocalStorageCtor().$returns(mockHtml5LocalStorage);
    -  var foo1 = mockControl.createFunctionMock();
    -  foo1().$does(function() {
    -    remoteStorageEvent({
    -      'args': ['bar'],
    -      'timestamp': goog.now()
    -    });
    -  });
    -  var foo2 = mockControl.createFunctionMock();
    -  foo2();
    -  var bar1 = mockControl.createFunctionMock();
    -  bar1().$does(function() {
    -    broadcastPubSub.publish('baz');
    -  });
    -  var bar2 = mockControl.createFunctionMock();
    -  bar2();
    -  var baz1 = mockControl.createFunctionMock();
    -  baz1();
    -  var baz2 = mockControl.createFunctionMock();
    -  baz2();
    -
    -  mockControl.$replayAll();
    -  broadcastPubSub = new goog.labs.pubsub.BroadcastPubSub();
    -  broadcastPubSub.logger_.setLevel(goog.debug.Logger.Level.OFF);
    -
    -  broadcastPubSub.subscribe('foo', foo1);
    -  broadcastPubSub.subscribe('foo', foo2);
    -  broadcastPubSub.subscribe('bar', bar1);
    -  broadcastPubSub.subscribe('bar', bar2);
    -  broadcastPubSub.subscribe('baz', baz1);
    -  broadcastPubSub.subscribe('baz', baz2);
    -
    -  remoteStorageEvent({
    -    'args': ['foo'],
    -    'timestamp': goog.now()
    -  });
    -  mockClock.tick();
    -  broadcastPubSub.dispose();
    -  mockControl.$verifyAll();
    -}
    -
    -
    -/**
    - * Local publish that originated from another instance of BroadcastChannel
    - * in the same Javascript context.
    - */
    -function testSecondInstancePublish() {
    -  mockHTML5LocalStorageCtor().$returns(mockHtml5LocalStorage).$times(2);
    -  var foo = mockControl.createFunctionMock();
    -  foo('x', 'y');
    -  var context = {'foo': 'bar'};
    -  var bar = goog.testing.recordFunction();
    -
    -  mockControl.$replayAll();
    -
    -  broadcastPubSub = new goog.labs.pubsub.BroadcastPubSub();
    -  broadcastPubSub.logger_.setLevel(goog.debug.Logger.Level.OFF);
    -  broadcastPubSub.subscribe('someTopic', foo);
    -  broadcastPubSub.subscribe('someTopic', bar, context);
    -
    -  var broadcastPubSub2 = new goog.labs.pubsub.BroadcastPubSub();
    -  broadcastPubSub2.publish('someTopic', 'x', 'y');
    -  mockClock.tick();
    -
    -  assertEquals(1, bar.getCallCount());
    -  assertEquals(context, bar.getLastCall().getThis());
    -  assertArrayEquals(['x', 'y'], bar.getLastCall().getArguments());
    -
    -  broadcastPubSub.dispose();
    -  mockControl.$verifyAll();
    -}
    -
    -
    -function testSecondInstanceNestedPublish() {
    -  mockHTML5LocalStorageCtor().$returns(mockHtml5LocalStorage).$times(2);
    -  var foo = mockControl.createFunctionMock();
    -  foo('m', 'n').$does(function() {
    -    broadcastPubSub.publish('barTopic', 'd', 'c');
    -  });
    -  var bar = mockControl.createFunctionMock();
    -  bar('d', 'c');
    -
    -  mockControl.$replayAll();
    -
    -  broadcastPubSub = new goog.labs.pubsub.BroadcastPubSub();
    -  broadcastPubSub.logger_.setLevel(goog.debug.Logger.Level.OFF);
    -  broadcastPubSub.subscribe('fooTopic', foo);
    -
    -  var broadcastPubSub2 = new goog.labs.pubsub.BroadcastPubSub();
    -  broadcastPubSub2.subscribe('barTopic', bar);
    -  broadcastPubSub2.publish('fooTopic', 'm', 'n');
    -  mockClock.tick();
    -  mockClock.tick();
    -
    -  broadcastPubSub.dispose();
    -  mockControl.$verifyAll();
    -}
    -
    -
    -/**
    - * Validate the localStorage data is being set as we expect.
    - */
    -function testLocalStorageData() {
    -  var topic = 'someTopic';
    -  var anotherTopic = 'anotherTopic';
    -  var now = goog.now();
    -
    -  mockHTML5LocalStorageCtor().$returns(mockHtml5LocalStorage);
    -  var mockStorage = mockControl.createLooseMock(goog.storage.Storage);
    -
    -  var mockStorageCtor = mockControl.createConstructorMock(
    -      goog.storage, 'Storage');
    -
    -  mockStorageCtor(mockHtml5LocalStorage).$returns(mockStorage);
    -  if (!isIe8) {
    -    mockStorage.set(goog.labs.pubsub.BroadcastPubSub.STORAGE_KEY_,
    -        {'args': [topic, '10'], 'timestamp': now});
    -    mockStorage.remove(goog.labs.pubsub.BroadcastPubSub.STORAGE_KEY_);
    -    mockStorage.set(goog.labs.pubsub.BroadcastPubSub.STORAGE_KEY_,
    -        {'args': [anotherTopic, '13'], 'timestamp': now});
    -    mockStorage.remove(goog.labs.pubsub.BroadcastPubSub.STORAGE_KEY_);
    -  } else {
    -    var firstEventArray = [
    -      {'args': [topic, '10'], 'timestamp': now}
    -    ];
    -    var secondEventArray = [
    -      {'args': [topic, '10'], 'timestamp': now},
    -      {'args': [anotherTopic, '13'], 'timestamp': now +
    -            goog.labs.pubsub.BroadcastPubSub.
    -            IE8_TIMESTAMP_UNIQUE_OFFSET_MS_}
    -    ];
    -
    -    mockStorage.get(goog.labs.pubsub.BroadcastPubSub.IE8_EVENTS_KEY_).
    -        $returns(null);
    -    mockStorage.set(goog.labs.pubsub.BroadcastPubSub.IE8_EVENTS_KEY_,
    -        new goog.testing.mockmatchers.ArgumentMatcher(function(val) {
    -          return goog.testing.mockmatchers.flexibleArrayMatcher(
    -              firstEventArray, val);
    -        }, 'First event array'));
    -
    -    // Make sure to clone or you're going to have a bad time.
    -    mockStorage.get(goog.labs.pubsub.BroadcastPubSub.IE8_EVENTS_KEY_).
    -        $returns(goog.array.clone(firstEventArray));
    -
    -    mockStorage.set(goog.labs.pubsub.BroadcastPubSub.IE8_EVENTS_KEY_,
    -        new goog.testing.mockmatchers.ArgumentMatcher(function(val) {
    -          return goog.testing.mockmatchers.flexibleArrayMatcher(
    -              secondEventArray, val);
    -        }, 'Second event array'));
    -
    -    mockStorage.remove(
    -        goog.labs.pubsub.BroadcastPubSub.IE8_EVENTS_KEY_);
    -  }
    -
    -  var fn = goog.testing.recordFunction();
    -  fn('10');
    -  mockControl.$replayAll();
    -
    -  broadcastPubSub = new goog.labs.pubsub.BroadcastPubSub();
    -  broadcastPubSub.logger_.setLevel(goog.debug.Logger.Level.OFF);
    -  broadcastPubSub.subscribe(topic, fn);
    -
    -  broadcastPubSub.publish(topic, '10');
    -  broadcastPubSub.publish(anotherTopic, '13');
    -
    -  mockClock.tick();
    -
    -  broadcastPubSub.dispose();
    -  mockControl.$verifyAll();
    -}
    -
    -
    -function testBrokenTimestamp() {
    -  mockHTML5LocalStorageCtor().$returns(mockHtml5LocalStorage);
    -  var fn = mockControl.createFunctionMock();
    -  mockControl.$replayAll();
    -
    -  broadcastPubSub = new goog.labs.pubsub.BroadcastPubSub();
    -  broadcastPubSub.logger_.setLevel(goog.debug.Logger.Level.OFF);
    -
    -  broadcastPubSub.subscribe('someTopic', fn);
    -
    -  remoteStorageEvent({
    -    'args': 'WAT?',
    -    'timestamp': 'wat?'
    -  });
    -  mockClock.tick();
    -
    -  broadcastPubSub.dispose();
    -  mockControl.$verifyAll();
    -}
    -
    -
    -/** Test response to bad localStorage data. */
    -function testBrokenEvent() {
    -  mockHTML5LocalStorageCtor().$returns(mockHtml5LocalStorage);
    -  var fn = mockControl.createFunctionMock();
    -  mockControl.$replayAll();
    -
    -  broadcastPubSub = new goog.labs.pubsub.BroadcastPubSub();
    -  broadcastPubSub.logger_.setLevel(goog.debug.Logger.Level.OFF);
    -  broadcastPubSub.subscribe('someTopic', fn);
    -
    -  if (!isIe8) {
    -    var event = new goog.testing.events.Event('storage', window);
    -    event.key = 'FooBarBaz';
    -    event.newValue = goog.json.serialize({'keyby': 'word'});
    -    goog.testing.events.fireBrowserEvent(event);
    -  } else {
    -    var uniqueKey =
    -        goog.labs.pubsub.BroadcastPubSub.IE8_EVENTS_KEY_PREFIX_ +
    -        '1234567890';
    -    // This will cause an event.
    -    mockHtml5LocalStorage.set(uniqueKey, 'Toothpaste!');
    -  }
    -  mockClock.tick();
    -
    -  broadcastPubSub.dispose();
    -  mockControl.$verifyAll();
    -}
    -
    -
    -/**
    - * The following tests are duplicated from pubsub because they depend
    - * on functionality (mostly "publish") that has changed in BroadcastChannel.
    - */
    -function testPublish() {
    -  mockHTML5LocalStorageCtor().$returns(mockHtml5LocalStorage);
    -  var foo = mockControl.createFunctionMock();
    -  foo('x', 'y');
    -
    -  var context = {'foo': 'bar'};
    -  var bar = goog.testing.recordFunction();
    -
    -  var baz = mockControl.createFunctionMock();
    -  baz('d', 'c');
    -
    -  mockControl.$replayAll();
    -  broadcastPubSub = new goog.labs.pubsub.BroadcastPubSub();
    -  broadcastPubSub.logger_.setLevel(goog.debug.Logger.Level.OFF);
    -
    -  broadcastPubSub.subscribe('someTopic', foo);
    -  broadcastPubSub.subscribe('someTopic', bar, context);
    -  broadcastPubSub.subscribe('anotherTopic', baz, context);
    -
    -  broadcastPubSub.publish('someTopic', 'x', 'y');
    -  mockClock.tick();
    -
    -  assertTrue(broadcastPubSub.unsubscribe('someTopic', foo));
    -
    -  broadcastPubSub.publish('anotherTopic', 'd', 'c');
    -  broadcastPubSub.publish('someTopic', 'x', 'y');
    -  mockClock.tick();
    -
    -  broadcastPubSub.subscribe('differentTopic', foo);
    -
    -  broadcastPubSub.publish('someTopic', 'x', 'y');
    -  mockClock.tick();
    -
    -  assertEquals(3, bar.getCallCount());
    -  goog.array.forEach(bar.getCalls(), function(call) {
    -    assertArrayEquals(['x', 'y'], call.getArguments());
    -    assertEquals(context, call.getThis());
    -  });
    -  broadcastPubSub.dispose();
    -  mockControl.$verifyAll();
    -}
    -
    -
    -function testPublishEmptyTopic() {
    -  mockHTML5LocalStorageCtor().$returns(mockHtml5LocalStorage);
    -  var foo = mockControl.createFunctionMock();
    -  foo();
    -
    -  mockControl.$replayAll();
    -  broadcastPubSub = new goog.labs.pubsub.BroadcastPubSub();
    -  broadcastPubSub.logger_.setLevel(goog.debug.Logger.Level.OFF);
    -
    -  broadcastPubSub.publish('someTopic');
    -  mockClock.tick();
    -
    -  broadcastPubSub.subscribe('someTopic', foo);
    -  broadcastPubSub.publish('someTopic');
    -  mockClock.tick();
    -
    -  broadcastPubSub.unsubscribe('someTopic', foo);
    -  broadcastPubSub.publish('someTopic');
    -  mockClock.tick();
    -
    -  broadcastPubSub.dispose();
    -  mockControl.$verifyAll();
    -}
    -
    -
    -function testSubscribeWhilePublishing() {
    -  mockHTML5LocalStorageCtor().$returns(mockHtml5LocalStorage);
    -  // It's OK for a subscriber to add a new subscriber to its own topic,
    -  // but the newly added subscriber shouldn't be called until the next
    -  // publish cycle.
    -
    -  var fn1 = mockControl.createFunctionMock();
    -  var fn2 = mockControl.createFunctionMock();
    -  fn1().$does(function() {
    -    broadcastPubSub.subscribe('someTopic', fn2);
    -  }).$times(2);
    -  fn2();
    -
    -  mockControl.$replayAll();
    -  broadcastPubSub = new goog.labs.pubsub.BroadcastPubSub();
    -  broadcastPubSub.logger_.setLevel(goog.debug.Logger.Level.OFF);
    -
    -  broadcastPubSub.subscribe('someTopic', fn1);
    -  assertEquals('Topic must have one subscriber', 1,
    -      broadcastPubSub.getCount('someTopic'));
    -
    -  broadcastPubSub.publish('someTopic');
    -  mockClock.tick();
    -
    -  assertEquals('Topic must have two subscribers', 2,
    -      broadcastPubSub.getCount('someTopic'));
    -
    -  broadcastPubSub.publish('someTopic');
    -  mockClock.tick();
    -
    -  assertEquals('Topic must have three subscribers', 3,
    -      broadcastPubSub.getCount('someTopic'));
    -  broadcastPubSub.dispose();
    -  mockControl.$verifyAll();
    -}
    -
    -
    -function testUnsubscribeWhilePublishing() {
    -  mockHTML5LocalStorageCtor().$returns(mockHtml5LocalStorage);
    -  // It's OK for a subscriber to unsubscribe another subscriber from its
    -  // own topic, but the subscriber in question won't actually be removed
    -  // until after publishing is complete.
    -
    -
    -  var fn1 = mockControl.createFunctionMock();
    -  var fn2 = mockControl.createFunctionMock();
    -  var fn3 = mockControl.createFunctionMock();
    -
    -  fn1().$does(function() {
    -    assertFalse('unsubscribe() must return false during publishing',
    -        broadcastPubSub.unsubscribe('X', fn2));
    -    assertEquals('Topic "X" must still have 3 subscribers', 3,
    -        broadcastPubSub.getCount('X'));
    -  });
    -  fn2().$does(function() {
    -    assertEquals('Topic "X" must still have 3 subscribers', 3,
    -        broadcastPubSub.getCount('X'));
    -  });
    -  fn3().$does(function() {
    -    assertFalse('unsubscribe() must return false during publishing',
    -        broadcastPubSub.unsubscribe('X', fn1));
    -    assertEquals('Topic "X" must still have 3 subscribers', 3,
    -        broadcastPubSub.getCount('X'));
    -  });
    -
    -  mockControl.$replayAll();
    -  broadcastPubSub = new goog.labs.pubsub.BroadcastPubSub();
    -  broadcastPubSub.logger_.setLevel(goog.debug.Logger.Level.OFF);
    -
    -  broadcastPubSub.subscribe('X', fn1);
    -  broadcastPubSub.subscribe('X', fn2);
    -  broadcastPubSub.subscribe('X', fn3);
    -
    -  assertEquals('Topic "X" must have 3 subscribers', 3,
    -      broadcastPubSub.getCount('X'));
    -
    -  broadcastPubSub.publish('X');
    -  mockClock.tick();
    -
    -  assertEquals('Topic "X" must have 1 subscriber after publishing', 1,
    -      broadcastPubSub.getCount('X'));
    -  assertEquals(
    -      'BroadcastChannel must not have any subscriptions pending removal',
    -      0, broadcastPubSub.pubSub_.pendingKeys_.length);
    -  broadcastPubSub.dispose();
    -  mockControl.$verifyAll();
    -}
    -
    -
    -function testUnsubscribeSelfWhilePublishing() {
    -  mockHTML5LocalStorageCtor().$returns(mockHtml5LocalStorage);
    -  // It's OK for a subscriber to unsubscribe itself, but it won't actually
    -  // be removed until after publishing is complete.
    -
    -  var fn = mockControl.createFunctionMock();
    -  fn().$does(function() {
    -    assertFalse('unsubscribe() must return false during publishing',
    -        broadcastPubSub.unsubscribe('someTopic', fn));
    -    assertEquals('Topic must still have 1 subscriber', 1,
    -        broadcastPubSub.getCount('someTopic'));
    -  });
    -
    -  mockControl.$replayAll();
    -  broadcastPubSub = new goog.labs.pubsub.BroadcastPubSub();
    -  broadcastPubSub.logger_.setLevel(goog.debug.Logger.Level.OFF);
    -
    -  broadcastPubSub.subscribe('someTopic', fn);
    -  assertEquals('Topic must have 1 subscriber', 1,
    -      broadcastPubSub.getCount('someTopic'));
    -
    -  broadcastPubSub.publish('someTopic');
    -  mockClock.tick();
    -
    -  assertEquals('Topic must have no subscribers after publishing', 0,
    -      broadcastPubSub.getCount('someTopic'));
    -  assertEquals(
    -      'BroadcastChannel must not have any subscriptions pending removal',
    -      0, broadcastPubSub.pubSub_.pendingKeys_.length);
    -  broadcastPubSub.dispose();
    -  mockControl.$verifyAll();
    -}
    -
    -
    -function testNestedPublish() {
    -  mockHTML5LocalStorageCtor().$returns(mockHtml5LocalStorage);
    -  var xFn1 = mockControl.createFunctionMock();
    -  xFn1().$does(function() {
    -    broadcastPubSub.publish('Y');
    -    broadcastPubSub.unsubscribe('X', arguments.callee);
    -  });
    -  var xFn2 = mockControl.createFunctionMock();
    -  xFn2();
    -
    -  var yFn1 = mockControl.createFunctionMock();
    -  yFn1().$does(function() {
    -    broadcastPubSub.unsubscribe('Y', arguments.callee);
    -  });
    -  var yFn2 = mockControl.createFunctionMock();
    -  yFn2();
    -
    -  mockControl.$replayAll();
    -
    -  broadcastPubSub = new goog.labs.pubsub.BroadcastPubSub();
    -  broadcastPubSub.logger_.setLevel(goog.debug.Logger.Level.OFF);
    -  broadcastPubSub.subscribe('X', xFn1);
    -  broadcastPubSub.subscribe('X', xFn2);
    -  broadcastPubSub.subscribe('Y', yFn1);
    -  broadcastPubSub.subscribe('Y', yFn2);
    -
    -  broadcastPubSub.publish('X');
    -  mockClock.tick();
    -
    -  broadcastPubSub.dispose();
    -  mockControl.$verifyAll();
    -}
    -
    -
    -function testSubscribeOnce() {
    -  mockHTML5LocalStorageCtor().$returns(mockHtml5LocalStorage);
    -  var fn = goog.testing.recordFunction();
    -
    -  mockControl.$replayAll();
    -  broadcastPubSub = new goog.labs.pubsub.BroadcastPubSub();
    -  broadcastPubSub.logger_.setLevel(goog.debug.Logger.Level.OFF);
    -  broadcastPubSub.subscribeOnce('someTopic', fn);
    -
    -  assertEquals('Topic must have one subscriber', 1,
    -      broadcastPubSub.getCount('someTopic'));
    -
    -  broadcastPubSub.publish('someTopic');
    -  mockClock.tick();
    -
    -  assertEquals('Topic must have no subscribers', 0,
    -      broadcastPubSub.getCount('someTopic'));
    -
    -  var context = {'foo': 'bar'};
    -  broadcastPubSub.subscribeOnce('someTopic', fn, context);
    -  assertEquals('Topic must have one subscriber', 1,
    -      broadcastPubSub.getCount('someTopic'));
    -  assertEquals('Subscriber must not have been called yet',
    -      1, fn.getCallCount());
    -
    -  broadcastPubSub.publish('someTopic');
    -  mockClock.tick();
    -
    -  assertEquals('Topic must have no subscribers', 0,
    -      broadcastPubSub.getCount('someTopic'));
    -  assertEquals('Subscriber must have been called',
    -      2, fn.getCallCount());
    -  assertEquals(context, fn.getLastCall().getThis());
    -  assertArrayEquals([], fn.getLastCall().getArguments());
    -
    -  context = {'foo': 'bar'};
    -  broadcastPubSub.subscribeOnce('someTopic', fn, context);
    -  assertEquals('Topic must have one subscriber', 1,
    -      broadcastPubSub.getCount('someTopic'));
    -  assertEquals('Subscriber must not have been called',
    -      2, fn.getCallCount());
    -
    -  broadcastPubSub.publish('someTopic', '17');
    -  mockClock.tick();
    -
    -  assertEquals('Topic must have no subscribers', 0,
    -      broadcastPubSub.getCount('someTopic'));
    -  assertEquals(context, fn.getLastCall().getThis());
    -  assertEquals('Subscriber must have been called',
    -      3, fn.getCallCount());
    -  assertArrayEquals(['17'], fn.getLastCall().getArguments());
    -  broadcastPubSub.dispose();
    -  mockControl.$verifyAll();
    -}
    -
    -
    -function testSubscribeOnce_boundFn() {
    -  mockHTML5LocalStorageCtor().$returns(mockHtml5LocalStorage);
    -  var fn = goog.testing.recordFunction();
    -  var context = {'foo': 'bar'};
    -
    -  mockControl.$replayAll();
    -  broadcastPubSub = new goog.labs.pubsub.BroadcastPubSub();
    -  broadcastPubSub.logger_.setLevel(goog.debug.Logger.Level.OFF);
    -
    -  broadcastPubSub.subscribeOnce('someTopic', goog.bind(fn, context));
    -  assertEquals('Topic must have one subscriber', 1,
    -      broadcastPubSub.getCount('someTopic'));
    -  assertNull('Subscriber must not have been called yet',
    -      fn.getLastCall());
    -
    -  broadcastPubSub.publish('someTopic', '17');
    -  mockClock.tick();
    -  assertEquals('Topic must have no subscribers', 0,
    -      broadcastPubSub.getCount('someTopic'));
    -  assertEquals('Subscriber must have been called', 1, fn.getCallCount());
    -  assertEquals('Must receive correct argument.',
    -      '17', fn.getLastCall().getArgument(0));
    -  assertEquals('Must have appropriate context.',
    -      context, fn.getLastCall().getThis());
    -
    -  broadcastPubSub.dispose();
    -  mockControl.$verifyAll();
    -}
    -
    -
    -function testSubscribeOnce_partialFn() {
    -  mockHTML5LocalStorageCtor().$returns(mockHtml5LocalStorage);
    -  var fullFn = mockControl.createFunctionMock();
    -  fullFn(true, '17');
    -
    -  mockControl.$replayAll();
    -  broadcastPubSub = new goog.labs.pubsub.BroadcastPubSub();
    -  broadcastPubSub.logger_.setLevel(goog.debug.Logger.Level.OFF);
    -
    -  broadcastPubSub.subscribeOnce('someTopic', goog.partial(fullFn, true));
    -  assertEquals('Topic must have one subscriber', 1,
    -      broadcastPubSub.getCount('someTopic'));
    -
    -  broadcastPubSub.publish('someTopic', '17');
    -  mockClock.tick();
    -
    -  assertEquals('Topic must have no subscribers', 0,
    -      broadcastPubSub.getCount('someTopic'));
    -  broadcastPubSub.dispose();
    -  mockControl.$verifyAll();
    -}
    -
    -
    -function testSelfResubscribe() {
    -  mockHTML5LocalStorageCtor().$returns(mockHtml5LocalStorage);
    -  var resubscribeFn = mockControl.createFunctionMock();
    -  var resubscribe = function() {
    -    broadcastPubSub.subscribeOnce('someTopic', resubscribeFn);
    -  };
    -  resubscribeFn('foo').$does(resubscribe);
    -  resubscribeFn('bar').$does(resubscribe);
    -  resubscribeFn('baz').$does(resubscribe);
    -
    -  mockControl.$replayAll();
    -  broadcastPubSub = new goog.labs.pubsub.BroadcastPubSub();
    -  broadcastPubSub.logger_.setLevel(goog.debug.Logger.Level.OFF);
    -
    -  broadcastPubSub.subscribeOnce('someTopic', resubscribeFn);
    -  assertEquals('Topic must have 1 subscriber', 1,
    -      broadcastPubSub.getCount('someTopic'));
    -
    -  broadcastPubSub.publish('someTopic', 'foo');
    -  mockClock.tick();
    -  assertEquals('Topic must have 1 subscriber', 1,
    -      broadcastPubSub.getCount('someTopic'));
    -  assertEquals('BroadcastChannel must not have any pending unsubscribe keys', 0,
    -      broadcastPubSub.pubSub_.pendingKeys_.length);
    -
    -  broadcastPubSub.publish('someTopic', 'bar');
    -  mockClock.tick();
    -  assertEquals('Topic must have 1 subscriber', 1,
    -      broadcastPubSub.getCount('someTopic'));
    -  assertEquals('BroadcastChannel must not have any pending unsubscribe keys', 0,
    -      broadcastPubSub.pubSub_.pendingKeys_.length);
    -
    -  broadcastPubSub.publish('someTopic', 'baz');
    -  mockClock.tick();
    -  assertEquals('Topic must have 1 subscriber', 1,
    -      broadcastPubSub.getCount('someTopic'));
    -  assertEquals('BroadcastChannel must not have any pending unsubscribe keys', 0,
    -      broadcastPubSub.pubSub_.pendingKeys_.length);
    -  broadcastPubSub.dispose();
    -  mockControl.$verifyAll();
    -}
    -
    -
    -function testClear() {
    -  mockHTML5LocalStorageCtor().$returns(mockHtml5LocalStorage);
    -  var fn = mockControl.createFunctionMock();
    -  mockControl.$replayAll();
    -  broadcastPubSub = new goog.labs.pubsub.BroadcastPubSub();
    -  broadcastPubSub.logger_.setLevel(goog.debug.Logger.Level.OFF);
    -
    -  goog.array.forEach(['V', 'W', 'X', 'Y', 'Z'], function(topic) {
    -    broadcastPubSub.subscribe(topic, fn);
    -  });
    -  assertEquals('BroadcastChannel must have 5 subscribers', 5,
    -      broadcastPubSub.getCount());
    -
    -  broadcastPubSub.clear('W');
    -  assertEquals('BroadcastChannel must have 4 subscribers', 4,
    -      broadcastPubSub.getCount());
    -
    -  goog.array.forEach(['X', 'Y'], function(topic) {
    -    broadcastPubSub.clear(topic);
    -  });
    -  assertEquals('BroadcastChannel must have 2 subscriber', 2,
    -      broadcastPubSub.getCount());
    -
    -  broadcastPubSub.clear();
    -  assertEquals('BroadcastChannel must have no subscribers', 0,
    -      broadcastPubSub.getCount());
    -  broadcastPubSub.dispose();
    -  mockControl.$verifyAll();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/storage/boundedcollectablestorage.js b/src/database/third_party/closure-library/closure/goog/labs/storage/boundedcollectablestorage.js
    deleted file mode 100644
    index 5a6bfdcdd89..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/storage/boundedcollectablestorage.js
    +++ /dev/null
    @@ -1,284 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides a convenient API for data persistence with data
    - * expiration and number of items limit.
    - *
    - * Setting and removing values keeps a max number of items invariant.
    - * Collecting values can be user initiated. If oversize, first removes
    - * expired items, if still oversize than removes the oldest items until a size
    - * constraint is fulfilled.
    - *
    - */
    -
    -goog.provide('goog.labs.storage.BoundedCollectableStorage');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.iter');
    -goog.require('goog.storage.CollectableStorage');
    -goog.require('goog.storage.ErrorCode');
    -goog.require('goog.storage.ExpiringStorage');
    -
    -
    -goog.scope(function() {
    -var storage = goog.labs.storage;
    -
    -
    -
    -/**
    - * Provides a storage with bounded number of elements, expiring keys and
    - * a collection method.
    - *
    - * @param {!goog.storage.mechanism.IterableMechanism} mechanism The underlying
    - *     storage mechanism.
    - * @param {number} maxItems Maximum number of items in storage.
    - * @constructor
    - * @extends {goog.storage.CollectableStorage}
    - * @final
    - */
    -storage.BoundedCollectableStorage = function(mechanism, maxItems) {
    -  storage.BoundedCollectableStorage.base(this, 'constructor', mechanism);
    -
    -  /**
    -   * A maximum number of items that should be stored.
    -   * @private {number}
    -   */
    -  this.maxItems_ = maxItems;
    -};
    -goog.inherits(storage.BoundedCollectableStorage,
    -              goog.storage.CollectableStorage);
    -
    -
    -/**
    - * An item key used to store a list of keys.
    - * @const
    - * @private
    - */
    -storage.BoundedCollectableStorage.KEY_LIST_KEY_ = 'bounded-collectable-storage';
    -
    -
    -/**
    - * Recreates a list of keys in order of creation.
    - *
    - * @return {!Array<string>} a list of unexpired keys.
    - * @private
    - */
    -storage.BoundedCollectableStorage.prototype.rebuildIndex_ = function() {
    -  var keys = [];
    -  goog.iter.forEach(this.mechanism.__iterator__(true), function(key) {
    -    if (storage.BoundedCollectableStorage.KEY_LIST_KEY_ == key) {
    -      return;
    -    }
    -
    -    var wrapper;
    -    /** @preserveTry */
    -    try {
    -      wrapper = this.getWrapper(key, true);
    -    } catch (ex) {
    -      if (ex == goog.storage.ErrorCode.INVALID_VALUE) {
    -        // Skip over bad wrappers and continue.
    -        return;
    -      }
    -      // Unknown error, escalate.
    -      throw ex;
    -    }
    -    goog.asserts.assert(wrapper);
    -
    -    var creationTime = goog.storage.ExpiringStorage.getCreationTime(wrapper);
    -    keys.push({key: key, created: creationTime});
    -  }, this);
    -
    -  goog.array.sort(keys, function(a, b) {
    -    return a.created - b.created;
    -  });
    -
    -  return goog.array.map(keys, function(v) {
    -    return v.key;
    -  });
    -};
    -
    -
    -/**
    - * Gets key list from a local storage. If an item does not exist,
    - * may recreate it.
    - *
    - * @param {boolean} rebuild Whether to rebuild a index if no index item exists.
    - * @return {!Array<string>} a list of keys if index exist, otherwise undefined.
    - * @private
    - */
    -storage.BoundedCollectableStorage.prototype.getKeys_ = function(rebuild) {
    -  var keys = storage.BoundedCollectableStorage.superClass_.get.call(this,
    -      storage.BoundedCollectableStorage.KEY_LIST_KEY_) || null;
    -  if (!keys || !goog.isArray(keys)) {
    -    if (rebuild) {
    -      keys = this.rebuildIndex_();
    -    } else {
    -      keys = [];
    -    }
    -  }
    -  return /** @type {!Array<string>} */ (keys);
    -};
    -
    -
    -/**
    - * Saves a list of keys in a local storage.
    - *
    - * @param {Array<string>} keys a list of keys to save.
    - * @private
    - */
    -storage.BoundedCollectableStorage.prototype.setKeys_ = function(keys) {
    -  storage.BoundedCollectableStorage.superClass_.set.call(this,
    -      storage.BoundedCollectableStorage.KEY_LIST_KEY_, keys);
    -};
    -
    -
    -/**
    - * Remove subsequence from a sequence.
    - *
    - * @param {!Array<string>} keys is a sequence.
    - * @param {!Array<string>} keysToRemove subsequence of keys, the order must
    - *     be kept.
    - * @return {!Array<string>} a keys sequence after removing keysToRemove.
    - * @private
    - */
    -storage.BoundedCollectableStorage.removeSubsequence_ =
    -    function(keys, keysToRemove) {
    -  if (keysToRemove.length == 0) {
    -    return goog.array.clone(keys);
    -  }
    -  var keysToKeep = [];
    -  var keysIdx = 0;
    -  var keysToRemoveIdx = 0;
    -
    -  while (keysToRemoveIdx < keysToRemove.length && keysIdx < keys.length) {
    -    var key = keysToRemove[keysToRemoveIdx];
    -    while (keysIdx < keys.length && keys[keysIdx] != key) {
    -      keysToKeep.push(keys[keysIdx]);
    -      ++keysIdx;
    -    }
    -    ++keysToRemoveIdx;
    -  }
    -
    -  goog.asserts.assert(keysToRemoveIdx == keysToRemove.length);
    -  goog.asserts.assert(keysIdx < keys.length);
    -  return goog.array.concat(keysToKeep, goog.array.slice(keys, keysIdx + 1));
    -};
    -
    -
    -/**
    - * Keeps the number of items in storage under maxItems. Removes elements in the
    - * order of creation.
    - *
    - * @param {!Array<string>} keys a list of keys in order of creation.
    - * @param {number} maxSize a number of items to keep.
    - * @return {!Array<string>} keys left after removing oversize data.
    - * @private
    - */
    -storage.BoundedCollectableStorage.prototype.collectOversize_ =
    -    function(keys, maxSize) {
    -  if (keys.length <= maxSize) {
    -    return goog.array.clone(keys);
    -  }
    -  var keysToRemove = goog.array.slice(keys, 0, keys.length - maxSize);
    -  goog.array.forEach(keysToRemove, function(key) {
    -    storage.BoundedCollectableStorage.superClass_.remove.call(this, key);
    -  }, this);
    -  return storage.BoundedCollectableStorage.removeSubsequence_(
    -      keys, keysToRemove);
    -};
    -
    -
    -/**
    - * Cleans up the storage by removing expired keys.
    - *
    - * @param {boolean=} opt_strict Also remove invalid keys.
    - * @override
    - */
    -storage.BoundedCollectableStorage.prototype.collect =
    -    function(opt_strict) {
    -  var keys = this.getKeys_(true);
    -  var keysToRemove = this.collectInternal(keys, opt_strict);
    -  keys = storage.BoundedCollectableStorage.removeSubsequence_(
    -      keys, keysToRemove);
    -  this.setKeys_(keys);
    -};
    -
    -
    -/**
    - * Ensures that we keep only maxItems number of items in a local storage.
    - * @param {boolean=} opt_skipExpired skip removing expired items first.
    - * @param {boolean=} opt_strict Also remove invalid keys.
    - */
    -storage.BoundedCollectableStorage.prototype.collectOversize =
    -    function(opt_skipExpired, opt_strict) {
    -  var keys = this.getKeys_(true);
    -  if (!opt_skipExpired) {
    -    var keysToRemove = this.collectInternal(keys, opt_strict);
    -    keys = storage.BoundedCollectableStorage.removeSubsequence_(
    -        keys, keysToRemove);
    -  }
    -  keys = this.collectOversize_(keys, this.maxItems_);
    -  this.setKeys_(keys);
    -};
    -
    -
    -/**
    - * Set an item in the storage.
    - *
    - * @param {string} key The key to set.
    - * @param {*} value The value to serialize to a string and save.
    - * @param {number=} opt_expiration The number of miliseconds since epoch
    - *     (as in goog.now()) when the value is to expire. If the expiration
    - *     time is not provided, the value will persist as long as possible.
    - * @override
    - */
    -storage.BoundedCollectableStorage.prototype.set =
    -    function(key, value, opt_expiration) {
    -  storage.BoundedCollectableStorage.base(
    -      this, 'set', key, value, opt_expiration);
    -  var keys = this.getKeys_(true);
    -  goog.array.remove(keys, key);
    -
    -  if (goog.isDef(value)) {
    -    keys.push(key);
    -    if (keys.length >= this.maxItems_) {
    -      var keysToRemove = this.collectInternal(keys);
    -      keys = storage.BoundedCollectableStorage.removeSubsequence_(
    -          keys, keysToRemove);
    -      keys = this.collectOversize_(keys, this.maxItems_);
    -    }
    -  }
    -  this.setKeys_(keys);
    -};
    -
    -
    -/**
    - * Remove an item from the data storage.
    - *
    - * @param {string} key The key to remove.
    - * @override
    - */
    -storage.BoundedCollectableStorage.prototype.remove = function(key) {
    -  storage.BoundedCollectableStorage.base(this, 'remove', key);
    -
    -  var keys = this.getKeys_(false);
    -  if (goog.isDef(keys)) {
    -    goog.array.remove(keys, key);
    -    this.setKeys_(keys);
    -  }
    -};
    -
    -});  // goog.scope
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/storage/boundedcollectablestorage_test.html b/src/database/third_party/closure-library/closure/goog/labs/storage/boundedcollectablestorage_test.html
    deleted file mode 100644
    index e17eb0aa714..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/storage/boundedcollectablestorage_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.labs.storage.BoundedCollectableStorage
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.labs.storage.BoundedCollectableStorageTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/storage/boundedcollectablestorage_test.js b/src/database/third_party/closure-library/closure/goog/labs/storage/boundedcollectablestorage_test.js
    deleted file mode 100644
    index 4646be721da..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/storage/boundedcollectablestorage_test.js
    +++ /dev/null
    @@ -1,74 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.labs.storage.BoundedCollectableStorageTest');
    -goog.setTestOnly('goog.labs.storage.BoundedCollectableStorageTest');
    -
    -goog.require('goog.labs.storage.BoundedCollectableStorage');
    -goog.require('goog.storage.collectableStorageTester');
    -goog.require('goog.storage.storage_test');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.storage.FakeMechanism');
    -
    -function testBasicOperations() {
    -  var mechanism = new goog.testing.storage.FakeMechanism();
    -  var storage = new goog.labs.storage.BoundedCollectableStorage(mechanism, 5);
    -  goog.storage.storage_test.runBasicTests(storage);
    -}
    -
    -function testExpiredKeyCollection() {
    -  var mechanism = new goog.testing.storage.FakeMechanism();
    -  var clock = new goog.testing.MockClock(true);
    -  var storage = new goog.labs.storage.BoundedCollectableStorage(mechanism, 15);
    -
    -  goog.storage.collectableStorageTester.runBasicTests(mechanism, clock,
    -      storage);
    -}
    -
    -function testLimitingNumberOfItems() {
    -  var mechanism = new goog.testing.storage.FakeMechanism();
    -  var clock = new goog.testing.MockClock(true);
    -  var storage = new goog.labs.storage.BoundedCollectableStorage(mechanism, 2);
    -
    -  // First item should fit.
    -  storage.set('item-1', 'one', 10000);
    -  clock.tick(100);
    -  assertEquals('one', storage.get('item-1'));
    -
    -  // Second item should fit.
    -  storage.set('item-2', 'two', 10000);
    -  assertEquals('one', storage.get('item-1'));
    -  assertEquals('two', storage.get('item-2'));
    -
    -  // Third item is too much, 'item-1' should be removed.
    -  storage.set('item-3', 'three', 5000);
    -  clock.tick(100);
    -  assertUndefined(storage.get('item-1'));
    -  assertEquals('two', storage.get('item-2'));
    -  assertEquals('three', storage.get('item-3'));
    -
    -  clock.tick(5000);
    -  // 'item-3' item has expired, should be removed instead an older 'item-2'.
    -  storage.set('item-4', 'four', 10000);
    -  assertUndefined(storage.get('item-1'));
    -  assertUndefined(storage.get('item-3'));
    -  assertEquals('two', storage.get('item-2'));
    -  assertEquals('four', storage.get('item-4'));
    -
    -  storage.remove('item-2');
    -  storage.remove('item-4');
    -
    -  clock.uninstall();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/structs/map.js b/src/database/third_party/closure-library/closure/goog/labs/structs/map.js
    deleted file mode 100644
    index 2ea217bd1b1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/structs/map.js
    +++ /dev/null
    @@ -1,348 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A map data structure that offers a convenient API to
    - * manipulate a key, value map. The key must be a string.
    - *
    - * This implementation also ensure that you can use keys that would
    - * not be usable using a normal object literal {}. Some examples
    - * include __proto__ (all newer browsers), toString/hasOwnProperty (IE
    - * <= 8).
    - * @author chrishenry@google.com (Chris Henry)
    - */
    -
    -goog.provide('goog.labs.structs.Map');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.labs.object');
    -goog.require('goog.object');
    -
    -
    -
    -/**
    - * Creates a new map.
    - * @constructor
    - * @struct
    - * @final
    - */
    -goog.labs.structs.Map = function() {
    -  // clear() initializes the map to the empty state.
    -  this.clear();
    -};
    -
    -
    -/**
    - * @type {function(this: Object, string): boolean}
    - * @private
    - */
    -goog.labs.structs.Map.objectPropertyIsEnumerable_ =
    -    Object.prototype.propertyIsEnumerable;
    -
    -
    -/**
    - * @type {function(this: Object, string): boolean}
    - * @private
    - */
    -goog.labs.structs.Map.objectHasOwnProperty_ =
    -    Object.prototype.hasOwnProperty;
    -
    -
    -/**
    - * Primary backing store of this map.
    - * @type {!Object}
    - * @private
    - */
    -goog.labs.structs.Map.prototype.map_;
    -
    -
    -/**
    - * Secondary backing store for keys. The index corresponds to the
    - * index for secondaryStoreValues_.
    - * @type {!Array<string>}
    - * @private
    - */
    -goog.labs.structs.Map.prototype.secondaryStoreKeys_;
    -
    -
    -/**
    - * Secondary backing store for keys. The index corresponds to the
    - * index for secondaryStoreValues_.
    - * @type {!Array<*>}
    - * @private
    - */
    -goog.labs.structs.Map.prototype.secondaryStoreValues_;
    -
    -
    -/**
    - * @private {number}
    - */
    -goog.labs.structs.Map.prototype.count_;
    -
    -
    -/**
    - * Adds the (key, value) pair, overriding previous entry with the same
    - * key, if any.
    - * @param {string} key The key.
    - * @param {*} value The value.
    - */
    -goog.labs.structs.Map.prototype.set = function(key, value) {
    -  this.assertKeyIsString_(key);
    -
    -  var newKey = !this.hasKeyInPrimaryStore_(key);
    -  this.map_[key] = value;
    -
    -  // __proto__ is not settable on object.
    -  if (key == '__proto__' ||
    -      // Shadows for built-in properties are not enumerable in IE <= 8 .
    -      (!goog.labs.structs.Map.BrowserFeature.OBJECT_CREATE_SUPPORTED &&
    -       !goog.labs.structs.Map.objectPropertyIsEnumerable_.call(
    -           this.map_, key))) {
    -    delete this.map_[key];
    -    var index = goog.array.indexOf(this.secondaryStoreKeys_, key);
    -    if ((newKey = index < 0)) {
    -      index = this.secondaryStoreKeys_.length;
    -    }
    -
    -    this.secondaryStoreKeys_[index] = key;
    -    this.secondaryStoreValues_[index] = value;
    -  }
    -
    -  if (newKey) this.count_++;
    -};
    -
    -
    -/**
    - * Gets the value for the given key.
    - * @param {string} key The key whose value we want to retrieve.
    - * @param {*=} opt_default The default value to return if the key does
    - *     not exist in the map, default to undefined.
    - * @return {*} The value corresponding to the given key, or opt_default
    - *     if the key does not exist in this map.
    - */
    -goog.labs.structs.Map.prototype.get = function(key, opt_default) {
    -  this.assertKeyIsString_(key);
    -
    -  if (this.hasKeyInPrimaryStore_(key)) {
    -    return this.map_[key];
    -  }
    -
    -  var index = goog.array.indexOf(this.secondaryStoreKeys_, key);
    -  return index >= 0 ? this.secondaryStoreValues_[index] : opt_default;
    -};
    -
    -
    -/**
    - * Removes the map entry with the given key.
    - * @param {string} key The key to remove.
    - * @return {boolean} True if the entry is removed.
    - */
    -goog.labs.structs.Map.prototype.remove = function(key) {
    -  this.assertKeyIsString_(key);
    -
    -  if (this.hasKeyInPrimaryStore_(key)) {
    -    this.count_--;
    -    delete this.map_[key];
    -    return true;
    -  } else {
    -    var index = goog.array.indexOf(this.secondaryStoreKeys_, key);
    -    if (index >= 0) {
    -      this.count_--;
    -      goog.array.removeAt(this.secondaryStoreKeys_, index);
    -      goog.array.removeAt(this.secondaryStoreValues_, index);
    -      return true;
    -    }
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Adds the content of the map to this map. If a new entry uses a key
    - * that already exists in this map, the existing key is replaced.
    - * @param {!goog.labs.structs.Map} map The map to add.
    - */
    -goog.labs.structs.Map.prototype.addAll = function(map) {
    -  goog.array.forEach(map.getKeys(), function(key) {
    -    this.set(key, map.get(key));
    -  }, this);
    -};
    -
    -
    -/**
    - * @return {boolean} True if the map is empty.
    - */
    -goog.labs.structs.Map.prototype.isEmpty = function() {
    -  return !this.count_;
    -};
    -
    -
    -/**
    - * @return {number} The number of the entries in this map.
    - */
    -goog.labs.structs.Map.prototype.getCount = function() {
    -  return this.count_;
    -};
    -
    -
    -/**
    - * @param {string} key The key to check.
    - * @return {boolean} True if the map contains the given key.
    - */
    -goog.labs.structs.Map.prototype.containsKey = function(key) {
    -  this.assertKeyIsString_(key);
    -  return this.hasKeyInPrimaryStore_(key) ||
    -      goog.array.contains(this.secondaryStoreKeys_, key);
    -};
    -
    -
    -/**
    - * Whether the map contains the given value. The comparison is done
    - * using !== comparator. Also returns true if the passed value is NaN
    - * and a NaN value exists in the map.
    - * @param {*} value Value to check.
    - * @return {boolean} True if the map contains the given value.
    - */
    -goog.labs.structs.Map.prototype.containsValue = function(value) {
    -  var found = goog.object.some(this.map_, function(v, k) {
    -    return this.hasKeyInPrimaryStore_(k) &&
    -        goog.labs.object.is(v, value);
    -  }, this);
    -  return found || goog.array.contains(this.secondaryStoreValues_, value);
    -};
    -
    -
    -/**
    - * @return {!Array<string>} An array of all the keys contained in this map.
    - */
    -goog.labs.structs.Map.prototype.getKeys = function() {
    -  var keys;
    -  if (goog.labs.structs.Map.BrowserFeature.OBJECT_KEYS_SUPPORTED) {
    -    keys = goog.array.clone(Object.keys(this.map_));
    -  } else {
    -    keys = [];
    -    for (var key in this.map_) {
    -      if (goog.labs.structs.Map.objectHasOwnProperty_.call(this.map_, key)) {
    -        keys.push(key);
    -      }
    -    }
    -  }
    -
    -  goog.array.extend(keys, this.secondaryStoreKeys_);
    -  return keys;
    -};
    -
    -
    -/**
    - * @return {!Array<*>} An array of all the values contained in this map.
    - *     There may be duplicates.
    - */
    -goog.labs.structs.Map.prototype.getValues = function() {
    -  var values = [];
    -  var keys = this.getKeys();
    -  for (var i = 0; i < keys.length; i++) {
    -    values.push(this.get(keys[i]));
    -  }
    -  return values;
    -};
    -
    -
    -/**
    - * @return {!Array<Array<?>>} An array of entries. Each entry is of the
    - *     form [key, value]. Do not rely on consistent ordering of entries.
    - */
    -goog.labs.structs.Map.prototype.getEntries = function() {
    -  var entries = [];
    -  var keys = this.getKeys();
    -  for (var i = 0; i < keys.length; i++) {
    -    var key = keys[i];
    -    entries.push([key, this.get(key)]);
    -  }
    -  return entries;
    -};
    -
    -
    -/**
    - * Clears the map to the initial state.
    - */
    -goog.labs.structs.Map.prototype.clear = function() {
    -  this.map_ = goog.labs.structs.Map.BrowserFeature.OBJECT_CREATE_SUPPORTED ?
    -      Object.create(null) : {};
    -  this.secondaryStoreKeys_ = [];
    -  this.secondaryStoreValues_ = [];
    -  this.count_ = 0;
    -};
    -
    -
    -/**
    - * Clones this map.
    - * @return {!goog.labs.structs.Map} The clone of this map.
    - */
    -goog.labs.structs.Map.prototype.clone = function() {
    -  var map = new goog.labs.structs.Map();
    -  map.addAll(this);
    -  return map;
    -};
    -
    -
    -/**
    - * @param {string} key The key to check.
    - * @return {boolean} True if the given key has been added successfully
    - *     to the primary store.
    - * @private
    - */
    -goog.labs.structs.Map.prototype.hasKeyInPrimaryStore_ = function(key) {
    -  // New browsers that support Object.create do not allow setting of
    -  // __proto__. In other browsers, hasOwnProperty will return true for
    -  // __proto__ for object created with literal {}, so we need to
    -  // special case it.
    -  if (key == '__proto__') {
    -    return false;
    -  }
    -
    -  if (goog.labs.structs.Map.BrowserFeature.OBJECT_CREATE_SUPPORTED) {
    -    return key in this.map_;
    -  }
    -
    -  return goog.labs.structs.Map.objectHasOwnProperty_.call(this.map_, key);
    -};
    -
    -
    -/**
    - * Asserts that the given key is a string.
    - * @param {string} key The key to check.
    - * @private
    - */
    -goog.labs.structs.Map.prototype.assertKeyIsString_ = function(key) {
    -  goog.asserts.assert(goog.isString(key), 'key must be a string.');
    -};
    -
    -
    -/**
    - * Browser feature enum necessary for map.
    - * @enum {boolean}
    - */
    -goog.labs.structs.Map.BrowserFeature = {
    -  // TODO(chrishenry): Replace with goog.userAgent detection.
    -  /**
    -   * Whether Object.create method is supported.
    -   */
    -  OBJECT_CREATE_SUPPORTED: !!Object.create,
    -
    -  /**
    -   * Whether Object.keys method is supported.
    -   */
    -  OBJECT_KEYS_SUPPORTED: !!Object.keys
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/structs/map_perf.js b/src/database/third_party/closure-library/closure/goog/labs/structs/map_perf.js
    deleted file mode 100644
    index 7e7a8975964..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/structs/map_perf.js
    +++ /dev/null
    @@ -1,204 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Performance test for goog.structs.Map and
    - * goog.labs.structs.Map. To run this test fairly, you would have to
    - * compile this via JsCompiler (with --export_test_functions), and
    - * pull the compiled JS into an empty HTML file.
    - * @author chrishenry@google.com (Chris Henry)
    - */
    -
    -goog.provide('goog.labs.structs.MapPerf');
    -goog.setTestOnly('goog.labs.structs.MapPerf');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.labs.structs.Map');
    -goog.require('goog.structs.Map');
    -goog.require('goog.testing.PerformanceTable');
    -goog.require('goog.testing.jsunit');
    -
    -goog.scope(function() {
    -var MapPerf = goog.labs.structs.MapPerf;
    -
    -
    -/**
    - * @typedef {goog.labs.structs.Map|goog.structs.Map}
    - */
    -MapPerf.MapType;
    -
    -
    -/**
    - * @type {goog.testing.PerformanceTable}
    - */
    -MapPerf.perfTable;
    -
    -
    -/**
    - * A key list. This maps loop index to key name to be used during
    - * benchmark. This ensure that we do not need to pay the cost of
    - * string concatenation/GC whenever we derive a key from loop index.
    - *
    - * This is filled once in setUpPage and then remain unchanged for the
    - * rest of the test case.
    - *
    - * @type {!Array<string>}
    - */
    -MapPerf.keyList = [];
    -
    -
    -/**
    - * Maxium number of keys in keyList (and, by extension, the map under
    - * test).
    - * @type {number}
    - */
    -MapPerf.MAX_NUM_KEY = 10000;
    -
    -
    -/**
    - * Fills the given map with generated key-value pair.
    - * @param {MapPerf.MapType} map The map to fill.
    - * @param {number} numKeys The number of key-value pair to fill.
    - */
    -MapPerf.fillMap = function(map, numKeys) {
    -  goog.asserts.assert(numKeys <= MapPerf.MAX_NUM_KEY);
    -
    -  for (var i = 0; i < numKeys; ++i) {
    -    map.set(MapPerf.keyList[i], i);
    -  }
    -};
    -
    -
    -/**
    - * Primes the given map with deletion of keys.
    - * @param {MapPerf.MapType} map The map to prime.
    - * @return {MapPerf.MapType} The primed map (for chaining).
    - */
    -MapPerf.primeMapWithDeletion = function(map) {
    -  for (var i = 0; i < 1000; ++i) {
    -    map.set(MapPerf.keyList[i], i);
    -  }
    -  for (var i = 0; i < 1000; ++i) {
    -    map.remove(MapPerf.keyList[i]);
    -  }
    -  return map;
    -};
    -
    -
    -/**
    - * Runs performance test for Map#get with the given map.
    - * @param {MapPerf.MapType} map The map to stress.
    - * @param {string} message Message to be put in performance table.
    - */
    -MapPerf.runPerformanceTestForMapGet = function(map, message) {
    -  MapPerf.fillMap(map, 10000);
    -
    -  MapPerf.perfTable.run(
    -      function() {
    -        // Creates local alias for map and keyList.
    -        var localMap = map;
    -        var localKeyList = MapPerf.keyList;
    -
    -        for (var i = 0; i < 500; ++i) {
    -          var sum = 0;
    -          for (var j = 0; j < 10000; ++j) {
    -            sum += localMap.get(localKeyList[j]);
    -          }
    -        }
    -      },
    -      message);
    -};
    -
    -
    -/**
    - * Runs performance test for Map#set with the given map.
    - * @param {MapPerf.MapType} map The map to stress.
    - * @param {string} message Message to be put in performance table.
    - */
    -MapPerf.runPerformanceTestForMapSet = function(map, message) {
    -  MapPerf.perfTable.run(
    -      function() {
    -        // Creates local alias for map and keyList.
    -        var localMap = map;
    -        var localKeyList = MapPerf.keyList;
    -
    -        for (var i = 0; i < 500; ++i) {
    -          for (var j = 0; j < 10000; ++j) {
    -            localMap.set(localKeyList[i], i);
    -          }
    -        }
    -      },
    -      message);
    -};
    -
    -
    -goog.global['setUpPage'] = function() {
    -  var content = goog.dom.createDom('div');
    -  goog.dom.insertChildAt(document.body, content, 0);
    -  var ua = navigator.userAgent;
    -  content.innerHTML =
    -      '<h1>Closure Performance Tests - Map</h1>' +
    -      '<p><strong>User-agent: </strong><span id="ua">' + ua + '</span></p>' +
    -      '<div id="perf-table"></div>' +
    -      '<hr>';
    -
    -  MapPerf.perfTable = new goog.testing.PerformanceTable(
    -      goog.dom.getElement('perf-table'));
    -
    -  // Fills keyList.
    -  for (var i = 0; i < MapPerf.MAX_NUM_KEY; ++i) {
    -    MapPerf.keyList.push('k' + i);
    -  }
    -};
    -
    -
    -goog.global['testGetFromLabsMap'] = function() {
    -  MapPerf.runPerformanceTestForMapGet(
    -      new goog.labs.structs.Map(), '#get: no previous deletion (Labs)');
    -};
    -
    -
    -goog.global['testGetFromOriginalMap'] = function() {
    -  MapPerf.runPerformanceTestForMapGet(
    -      new goog.structs.Map(), '#get: no previous deletion (Original)');
    -};
    -
    -
    -goog.global['testGetWithPreviousDeletionFromLabsMap'] = function() {
    -  MapPerf.runPerformanceTestForMapGet(
    -      MapPerf.primeMapWithDeletion(new goog.labs.structs.Map()),
    -      '#get: with previous deletion (Labs)');
    -};
    -
    -
    -goog.global['testGetWithPreviousDeletionFromOriginalMap'] = function() {
    -  MapPerf.runPerformanceTestForMapGet(
    -      MapPerf.primeMapWithDeletion(new goog.structs.Map()),
    -      '#get: with previous deletion (Original)');
    -};
    -
    -
    -goog.global['testSetFromLabsMap'] = function() {
    -  MapPerf.runPerformanceTestForMapSet(
    -      new goog.labs.structs.Map(), '#set: no previous deletion (Labs)');
    -};
    -
    -
    -goog.global['testSetFromOriginalMap'] = function() {
    -  MapPerf.runPerformanceTestForMapSet(
    -      new goog.structs.Map(), '#set: no previous deletion (Original)');
    -};
    -
    -});  // goog.scope
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/structs/map_test.html b/src/database/third_party/closure-library/closure/goog/labs/structs/map_test.html
    deleted file mode 100644
    index aded3ed2cd0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/structs/map_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -  Author: chrishenry@google.com (Chris Henry)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.labs.structs.Map
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.labs.structs.MapTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/structs/map_test.js b/src/database/third_party/closure-library/closure/goog/labs/structs/map_test.js
    deleted file mode 100644
    index bf2a61d22be..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/structs/map_test.js
    +++ /dev/null
    @@ -1,432 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.labs.structs.MapTest');
    -goog.setTestOnly('goog.labs.structs.MapTest');
    -
    -goog.require('goog.labs.structs.Map');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -
    -var map;
    -var stubs;
    -
    -function setUpPage() {
    -  stubs = new goog.testing.PropertyReplacer();
    -}
    -
    -function setUp() {
    -  map = new goog.labs.structs.Map();
    -}
    -
    -
    -function testSet() {
    -  var key = 'test';
    -  var value = 'value';
    -  map.set(key, value);
    -  assertEquals(value, map.get(key));
    -}
    -
    -
    -function testSetsWithSameKey() {
    -  var key = 'test';
    -  var value = 'value';
    -  var value2 = 'value2';
    -  map.set(key, value);
    -  map.set(key, value2);
    -  assertEquals(value2, map.get(key));
    -}
    -
    -
    -function testSetWithUndefinedValue() {
    -  var key = 'test';
    -  map.set(key, undefined);
    -  assertUndefined(map.get(key));
    -}
    -
    -
    -function testSetWithUnderUnderProtoUnderUnder() {
    -  var key = '__proto__';
    -  var value = 'value';
    -  var value2 = 'value2';
    -
    -  map.set(key, value);
    -  assertEquals(value, map.get(key));
    -
    -  map.set(key, value2);
    -  assertEquals(value2, map.get(key));
    -}
    -
    -
    -function testSetWithBuiltInPropertyShadows() {
    -  var key = 'toString';
    -  var value = 'value';
    -  var key2 = 'hasOwnProperty';
    -  var value2 = 'value2';
    -
    -  map.set(key, value);
    -  map.set(key2, value2);
    -  assertEquals(value, map.get(key));
    -  assertEquals(value2, map.get(key2));
    -
    -  map.set(key, value2);
    -  map.set(key2, value);
    -  assertEquals(value2, map.get(key));
    -  assertEquals(value, map.get(key2));
    -}
    -
    -
    -function testGetBeforeSetOfUnderUnderProtoUnderUnder() {
    -  assertUndefined(map.get('__proto__'));
    -}
    -
    -
    -function testContainsKey() {
    -  assertFalse(map.containsKey('key'));
    -  assertFalse(map.containsKey('__proto__'));
    -  assertFalse(map.containsKey('toString'));
    -  assertFalse(map.containsKey('hasOwnProperty'));
    -  assertFalse(map.containsKey('key2'));
    -  assertFalse(map.containsKey('key3'));
    -  assertFalse(map.containsKey('key4'));
    -
    -  map.set('key', 'v');
    -  map.set('__proto__', 'v');
    -  map.set('toString', 'v');
    -  map.set('hasOwnProperty', 'v');
    -  map.set('key2', undefined);
    -  map.set('key3', null);
    -  map.set('key4', '');
    -
    -  assertTrue(map.containsKey('key'));
    -  assertTrue(map.containsKey('__proto__'));
    -  assertTrue(map.containsKey('toString'));
    -  assertTrue(map.containsKey('hasOwnProperty'));
    -  assertTrue(map.containsKey('key2'));
    -  assertTrue(map.containsKey('key3'));
    -  assertTrue(map.containsKey('key4'));
    -}
    -
    -
    -function testContainsValueWithShadowKeys() {
    -  assertFalse(map.containsValue('v2'));
    -  assertFalse(map.containsValue('v3'));
    -  assertFalse(map.containsValue('v4'));
    -
    -  map.set('__proto__', 'v2');
    -  map.set('toString', 'v3');
    -  map.set('hasOwnProperty', 'v4');
    -
    -  assertTrue(map.containsValue('v2'));
    -  assertTrue(map.containsValue('v3'));
    -  assertTrue(map.containsValue('v4'));
    -
    -  assertFalse(map.containsValue(Object.prototype.toString));
    -  assertFalse(map.containsValue(Object.prototype.hasOwnProperty));
    -}
    -
    -
    -function testContainsValueWithNullAndUndefined() {
    -  assertFalse(map.containsValue(undefined));
    -  assertFalse(map.containsValue(null));
    -
    -  map.set('key2', undefined);
    -  map.set('key3', null);
    -
    -  assertTrue(map.containsValue(undefined));
    -  assertTrue(map.containsValue(null));
    -}
    -
    -
    -function testContainsValueWithNumber() {
    -  assertFalse(map.containsValue(-1));
    -  assertFalse(map.containsValue(0));
    -  assertFalse(map.containsValue(1));
    -  map.set('key', -1);
    -  map.set('key2', 0);
    -  map.set('key3', 1);
    -  assertTrue(map.containsValue(-1));
    -  assertTrue(map.containsValue(0));
    -  assertTrue(map.containsValue(1));
    -}
    -
    -
    -function testContainsValueWithNaN() {
    -  assertFalse(map.containsValue(NaN));
    -  map.set('key', NaN);
    -  assertTrue(map.containsValue(NaN));
    -}
    -
    -
    -function testContainsValueWithNegativeZero() {
    -  assertFalse(map.containsValue(-0));
    -  map.set('key', -0);
    -  assertTrue(map.containsValue(-0));
    -  assertFalse(map.containsValue(0));
    -
    -  map.set('key', 0);
    -  assertFalse(map.containsValue(-0));
    -  assertTrue(map.containsValue(0));
    -}
    -
    -
    -function testContainsValueWithStrings() {
    -  assertFalse(map.containsValue(''));
    -  assertFalse(map.containsValue('v'));
    -  map.set('key', '');
    -  map.set('key2', 'v');
    -  assertTrue(map.containsValue(''));
    -  assertTrue(map.containsValue('v'));
    -}
    -
    -function testRemove() {
    -  map.set('key', 'v');
    -  map.set('__proto__', 'v2');
    -  map.set('toString', 'v3');
    -  map.set('hasOwnProperty', 'v4');
    -  map.set('key2', undefined);
    -  map.set('key3', null);
    -  map.set('key4', '');
    -
    -  assertFalse(map.remove('key do not exist'));
    -
    -  assertTrue(map.remove('key'));
    -  assertFalse(map.containsKey('key'));
    -  assertFalse(map.remove('key'));
    -
    -  assertTrue(map.remove('__proto__'));
    -  assertFalse(map.containsKey('__proto__'));
    -  assertFalse(map.remove('__proto__'));
    -
    -  assertTrue(map.remove('toString'));
    -  assertFalse(map.containsKey('toString'));
    -  assertFalse(map.remove('toString'));
    -
    -  assertTrue(map.remove('hasOwnProperty'));
    -  assertFalse(map.containsKey('hasOwnProperty'));
    -  assertFalse(map.remove('hasOwnProperty'));
    -
    -  assertTrue(map.remove('key2'));
    -  assertFalse(map.containsKey('key2'));
    -  assertFalse(map.remove('key2'));
    -
    -  assertTrue(map.remove('key3'));
    -  assertFalse(map.containsKey('key3'));
    -  assertFalse(map.remove('key3'));
    -
    -  assertTrue('', map.remove('key4'));
    -  assertFalse(map.containsKey('key4'));
    -  assertFalse(map.remove('key4'));
    -}
    -
    -
    -function testGetCountAndIsEmpty() {
    -  assertEquals(0, map.getCount());
    -  assertTrue(map.isEmpty());
    -
    -  map.set('key', 'v');
    -  assertEquals(1, map.getCount());
    -  map.set('__proto__', 'v2');
    -  assertEquals(2, map.getCount());
    -  map.set('toString', 'v3');
    -  assertEquals(3, map.getCount());
    -  map.set('hasOwnProperty', 'v4');
    -  assertEquals(4, map.getCount());
    -
    -  map.set('key', 'a');
    -  assertEquals(4, map.getCount());
    -  map.set('__proto__', 'a2');
    -  assertEquals(4, map.getCount());
    -  map.set('toString', 'a3');
    -  assertEquals(4, map.getCount());
    -  map.set('hasOwnProperty', 'a4');
    -  assertEquals(4, map.getCount());
    -
    -  map.remove('key');
    -  assertEquals(3, map.getCount());
    -  map.remove('__proto__');
    -  assertEquals(2, map.getCount());
    -  map.remove('toString');
    -  assertEquals(1, map.getCount());
    -  map.remove('hasOwnProperty');
    -  assertEquals(0, map.getCount());
    -}
    -
    -
    -function testClear() {
    -  map.set('key', 'v');
    -  map.set('__proto__', 'v');
    -  map.set('toString', 'v');
    -  map.set('hasOwnProperty', 'v');
    -  map.set('key2', undefined);
    -  map.set('key3', null);
    -  map.set('key4', '');
    -
    -  map.clear();
    -
    -  assertFalse(map.containsKey('key'));
    -  assertFalse(map.containsKey('__proto__'));
    -  assertFalse(map.containsKey('toString'));
    -  assertFalse(map.containsKey('hasOwnProperty'));
    -  assertFalse(map.containsKey('key2'));
    -  assertFalse(map.containsKey('key3'));
    -  assertFalse(map.containsKey('key4'));
    -}
    -
    -
    -function testGetEntries() {
    -  map.set('key', 'v');
    -  map.set('__proto__', 'v');
    -  map.set('toString', 'v');
    -  map.set('hasOwnProperty', 'v');
    -  map.set('key2', undefined);
    -  map.set('key3', null);
    -  map.set('key4', '');
    -
    -  var entries = map.getEntries();
    -  assertEquals(7, entries.length);
    -  assertContainsEntry(['key', 'v'], entries);
    -  assertContainsEntry(['__proto__', 'v'], entries);
    -  assertContainsEntry(['toString', 'v'], entries);
    -  assertContainsEntry(['hasOwnProperty', 'v'], entries);
    -  assertContainsEntry(['key2', undefined], entries);
    -  assertContainsEntry(['key3', null], entries);
    -  assertContainsEntry(['key4', ''], entries);
    -}
    -
    -
    -function testGetKeys() {
    -  map.set('key', 'v');
    -  map.set('__proto__', 'v');
    -  map.set('toString', 'v');
    -  map.set('hasOwnProperty', 'v');
    -  map.set('key2', undefined);
    -  map.set('key3', null);
    -  map.set('k4', '');
    -
    -  var values = map.getKeys();
    -  assertSameElements(
    -      ['key', '__proto__', 'toString', 'hasOwnProperty', 'key2', 'key3', 'k4'],
    -      values);
    -}
    -
    -
    -function testGetValues() {
    -  map.set('key', 'v');
    -  map.set('__proto__', 'v');
    -  map.set('toString', 'v');
    -  map.set('hasOwnProperty', 'v');
    -  map.set('key2', undefined);
    -  map.set('key3', null);
    -  map.set('key4', '');
    -
    -  var values = map.getValues();
    -  assertSameElements(['v', 'v', 'v', 'v', undefined, null, ''], values);
    -}
    -
    -
    -function testAddAllToEmptyMap() {
    -  map.set('key', 'v');
    -  map.set('key2', 'v2');
    -  map.set('key3', 'v3');
    -  map.set('key4', 'v4');
    -
    -  var map2 = new goog.labs.structs.Map();
    -  map2.addAll(map);
    -
    -  assertEquals(4, map2.getCount());
    -  assertEquals('v', map2.get('key'));
    -  assertEquals('v2', map2.get('key2'));
    -  assertEquals('v3', map2.get('key3'));
    -  assertEquals('v4', map2.get('key4'));
    -}
    -
    -
    -function testAddAllToNonEmptyMap() {
    -  map.set('key', 'v');
    -  map.set('key2', 'v2');
    -  map.set('key3', 'v3');
    -  map.set('key4', 'v4');
    -
    -  var map2 = new goog.labs.structs.Map();
    -  map2.set('key0', 'o');
    -  map2.set('key', 'o');
    -  map2.set('key2', 'o2');
    -  map2.set('key3', 'o3');
    -  map2.addAll(map);
    -
    -  assertEquals(5, map2.getCount());
    -  assertEquals('o', map2.get('key0'));
    -  assertEquals('v', map2.get('key'));
    -  assertEquals('v2', map2.get('key2'));
    -  assertEquals('v3', map2.get('key3'));
    -  assertEquals('v4', map2.get('key4'));
    -}
    -
    -
    -function testClone() {
    -  map.set('key', 'v');
    -  map.set('key2', 'v2');
    -  map.set('key3', 'v3');
    -  map.set('key4', 'v4');
    -
    -  var map2 = map.clone();
    -
    -  assertEquals(4, map2.getCount());
    -  assertEquals('v', map2.get('key'));
    -  assertEquals('v2', map2.get('key2'));
    -  assertEquals('v3', map2.get('key3'));
    -  assertEquals('v4', map2.get('key4'));
    -}
    -
    -
    -function testMapWithModifiedObjectPrototype() {
    -  stubs.set(Object.prototype, 'toString', function() {});
    -  stubs.set(Object.prototype, 'foo', function() {});
    -  stubs.set(Object.prototype, 'field', 100);
    -  stubs.set(Object.prototype, 'fooKey', function() {});
    -
    -  map = new goog.labs.structs.Map();
    -  map.set('key', 'v');
    -  map.set('key2', 'v2');
    -  map.set('fooKey', 'v3');
    -
    -  assertTrue(map.containsKey('key'));
    -  assertTrue(map.containsKey('key2'));
    -  assertTrue(map.containsKey('fooKey'));
    -  assertFalse(map.containsKey('toString'));
    -  assertFalse(map.containsKey('foo'));
    -  assertFalse(map.containsKey('field'));
    -
    -  assertTrue(map.containsValue('v'));
    -  assertTrue(map.containsValue('v2'));
    -  assertTrue(map.containsValue('v3'));
    -  assertFalse(map.containsValue(100));
    -
    -  var entries = map.getEntries();
    -  assertEquals(3, entries.length);
    -  assertContainsEntry(['key', 'v'], entries);
    -  assertContainsEntry(['key2', 'v2'], entries);
    -  assertContainsEntry(['fooKey', 'v3'], entries);
    -}
    -
    -
    -function assertContainsEntry(entry, entryList) {
    -  for (var i = 0; i < entryList.length; ++i) {
    -    if (entry[0] == entryList[i][0] && entry[1] === entryList[i][1]) {
    -      return;
    -    }
    -  }
    -  fail('Did not find entry: ' + entry + ' in: ' + entryList);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/structs/multimap.js b/src/database/third_party/closure-library/closure/goog/labs/structs/multimap.js
    deleted file mode 100644
    index ff73f431e14..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/structs/multimap.js
    +++ /dev/null
    @@ -1,282 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A collection similar to
    - * {@code goog.labs.structs.Map}, but also allows associating multiple
    - * values with a single key.
    - *
    - * This implementation ensures that you can use any string keys.
    - *
    - * @author chrishenry@google.com (Chris Henry)
    - */
    -
    -goog.provide('goog.labs.structs.Multimap');
    -
    -goog.require('goog.array');
    -goog.require('goog.labs.object');
    -goog.require('goog.labs.structs.Map');
    -
    -
    -
    -/**
    - * Creates a new multimap.
    - * @constructor
    - * @struct
    - * @final
    - */
    -goog.labs.structs.Multimap = function() {
    -  this.clear();
    -};
    -
    -
    -/**
    - * The backing map.
    - * @type {!goog.labs.structs.Map}
    - * @private
    - */
    -goog.labs.structs.Multimap.prototype.map_;
    -
    -
    -/**
    - * @type {number}
    - * @private
    - */
    -goog.labs.structs.Multimap.prototype.count_ = 0;
    -
    -
    -/**
    - * Clears the multimap.
    - */
    -goog.labs.structs.Multimap.prototype.clear = function() {
    -  this.count_ = 0;
    -  this.map_ = new goog.labs.structs.Map();
    -};
    -
    -
    -/**
    - * Clones this multimap.
    - * @return {!goog.labs.structs.Multimap} A multimap that contains all
    - *     the mapping this multimap has.
    - */
    -goog.labs.structs.Multimap.prototype.clone = function() {
    -  var map = new goog.labs.structs.Multimap();
    -  map.addAllFromMultimap(this);
    -  return map;
    -};
    -
    -
    -/**
    - * Adds the given (key, value) pair to the map. The (key, value) pair
    - * is guaranteed to be added.
    - * @param {string} key The key to add.
    - * @param {*} value The value to add.
    - */
    -goog.labs.structs.Multimap.prototype.add = function(key, value) {
    -  var values = this.map_.get(key);
    -  if (!values) {
    -    this.map_.set(key, (values = []));
    -  }
    -
    -  values.push(value);
    -  this.count_++;
    -};
    -
    -
    -/**
    - * Stores a collection of values to the given key. Does not replace
    - * existing (key, value) pairs.
    - * @param {string} key The key to add.
    - * @param {!Array<*>} values The values to add.
    - */
    -goog.labs.structs.Multimap.prototype.addAllValues = function(key, values) {
    -  goog.array.forEach(values, function(v) {
    -    this.add(key, v);
    -  }, this);
    -};
    -
    -
    -/**
    - * Adds the contents of the given map/multimap to this multimap.
    - * @param {!(goog.labs.structs.Map|goog.labs.structs.Multimap)} map The
    - *     map to add.
    - */
    -goog.labs.structs.Multimap.prototype.addAllFromMultimap = function(map) {
    -  goog.array.forEach(map.getEntries(), function(entry) {
    -    this.add(entry[0], entry[1]);
    -  }, this);
    -};
    -
    -
    -/**
    - * Replaces all the values for the given key with the given values.
    - * @param {string} key The key whose values are to be replaced.
    - * @param {!Array<*>} values The new values. If empty, this is
    - *     equivalent to {@code removaAll(key)}.
    - */
    -goog.labs.structs.Multimap.prototype.replaceValues = function(key, values) {
    -  this.removeAll(key);
    -  this.addAllValues(key, values);
    -};
    -
    -
    -/**
    - * Gets the values correspond to the given key.
    - * @param {string} key The key to retrieve.
    - * @return {!Array<*>} An array of values corresponding to the given
    - *     key. May be empty. Note that the ordering of values are not
    - *     guaranteed to be consistent.
    - */
    -goog.labs.structs.Multimap.prototype.get = function(key) {
    -  var values = /** @type {Array<*>} */ (this.map_.get(key));
    -  return values ? goog.array.clone(values) : [];
    -};
    -
    -
    -/**
    - * Removes a single occurrence of (key, value) pair.
    - * @param {string} key The key to remove.
    - * @param {*} value The value to remove.
    - * @return {boolean} Whether any matching (key, value) pair is removed.
    - */
    -goog.labs.structs.Multimap.prototype.remove = function(key, value) {
    -  var values = /** @type {Array<*>} */ (this.map_.get(key));
    -  if (!values) {
    -    return false;
    -  }
    -
    -  var removed = goog.array.removeIf(values, function(v) {
    -    return goog.labs.object.is(value, v);
    -  });
    -
    -  if (removed) {
    -    this.count_--;
    -    if (values.length == 0) {
    -      this.map_.remove(key);
    -    }
    -  }
    -  return removed;
    -};
    -
    -
    -/**
    - * Removes all values corresponding to the given key.
    - * @param {string} key The key whose values are to be removed.
    - * @return {boolean} Whether any value is removed.
    - */
    -goog.labs.structs.Multimap.prototype.removeAll = function(key) {
    -  // We have to first retrieve the values from the backing map because
    -  // we need to keep track of count (and correctly calculates the
    -  // return value). values may be undefined.
    -  var values = this.map_.get(key);
    -  if (this.map_.remove(key)) {
    -    this.count_ -= values.length;
    -    return true;
    -  }
    -
    -  return false;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the multimap is empty.
    - */
    -goog.labs.structs.Multimap.prototype.isEmpty = function() {
    -  return !this.count_;
    -};
    -
    -
    -/**
    - * @return {number} The count of (key, value) pairs in the map.
    - */
    -goog.labs.structs.Multimap.prototype.getCount = function() {
    -  return this.count_;
    -};
    -
    -
    -/**
    - * @param {string} key The key to check.
    - * @param {*} value The value to check.
    - * @return {boolean} Whether the (key, value) pair exists in the multimap.
    - */
    -goog.labs.structs.Multimap.prototype.containsEntry = function(key, value) {
    -  var values = /** @type {Array<*>} */ (this.map_.get(key));
    -  if (!values) {
    -    return false;
    -  }
    -
    -  var index = goog.array.findIndex(values, function(v) {
    -    return goog.labs.object.is(v, value);
    -  });
    -  return index >= 0;
    -};
    -
    -
    -/**
    - * @param {string} key The key to check.
    - * @return {boolean} Whether the multimap contains at least one (key,
    - *     value) pair with the given key.
    - */
    -goog.labs.structs.Multimap.prototype.containsKey = function(key) {
    -  return this.map_.containsKey(key);
    -};
    -
    -
    -/**
    - * @param {*} value The value to check.
    - * @return {boolean} Whether the multimap contains at least one (key,
    - *     value) pair with the given value.
    - */
    -goog.labs.structs.Multimap.prototype.containsValue = function(value) {
    -  return goog.array.some(this.map_.getValues(),
    -      function(values) {
    -        return goog.array.some(/** @type {Array<?>} */ (values), function(v) {
    -          return goog.labs.object.is(v, value);
    -        });
    -      });
    -};
    -
    -
    -/**
    - * @return {!Array<string>} An array of unique keys.
    - */
    -goog.labs.structs.Multimap.prototype.getKeys = function() {
    -  return this.map_.getKeys();
    -};
    -
    -
    -/**
    - * @return {!Array<*>} An array of values. There may be duplicates.
    - */
    -goog.labs.structs.Multimap.prototype.getValues = function() {
    -  return goog.array.flatten(this.map_.getValues());
    -};
    -
    -
    -/**
    - * @return {!Array<!Array<?>>} An array of entries. Each entry is of the
    - *     form [key, value].
    - */
    -goog.labs.structs.Multimap.prototype.getEntries = function() {
    -  var keys = this.getKeys();
    -  var entries = [];
    -  for (var i = 0; i < keys.length; i++) {
    -    var key = keys[i];
    -    var values = this.get(key);
    -    for (var j = 0; j < values.length; j++) {
    -      entries.push([key, values[j]]);
    -    }
    -  }
    -  return entries;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/structs/multimap_test.html b/src/database/third_party/closure-library/closure/goog/labs/structs/multimap_test.html
    deleted file mode 100644
    index cb483fabaf4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/structs/multimap_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -  Author: chrishenry@google.com (Chris Henry)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.labs.structs.Multimap
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.labs.structs.MultimapTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/structs/multimap_test.js b/src/database/third_party/closure-library/closure/goog/labs/structs/multimap_test.js
    deleted file mode 100644
    index 085ccacc131..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/structs/multimap_test.js
    +++ /dev/null
    @@ -1,328 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.labs.structs.MultimapTest');
    -goog.setTestOnly('goog.labs.structs.MultimapTest');
    -
    -goog.require('goog.labs.structs.Map');
    -goog.require('goog.labs.structs.Multimap');
    -goog.require('goog.testing.jsunit');
    -
    -var map;
    -
    -
    -function setUp() {
    -  map = new goog.labs.structs.Multimap();
    -}
    -
    -
    -function testGetCountWithEmptyMultimap() {
    -  assertEquals(0, map.getCount());
    -  assertTrue(map.isEmpty());
    -}
    -
    -
    -function testClone() {
    -  map.add('k', 'v');
    -  map.addAllValues('k2', ['v', 'v1', 'v2']);
    -
    -  var map2 = map.clone();
    -
    -  assertSameElements(['v'], map.get('k'));
    -  assertSameElements(['v', 'v1', 'v2'], map.get('k2'));
    -}
    -
    -
    -function testAdd() {
    -  map.add('key', 'v');
    -  assertEquals(1, map.getCount());
    -  map.add('key', 'v2');
    -  assertEquals(2, map.getCount());
    -  map.add('key', 'v3');
    -  assertEquals(3, map.getCount());
    -
    -  var values = map.get('key');
    -  assertEquals(3, values.length);
    -  assertContains('v', values);
    -  assertContains('v2', values);
    -  assertContains('v3', values);
    -}
    -
    -
    -function testAddValues() {
    -  map.addAllValues('key', ['v', 'v2', 'v3']);
    -  assertSameElements(['v', 'v2', 'v3'], map.get('key'));
    -
    -  map.add('key2', 'a');
    -  map.addAllValues('key2', ['v', 'v2', 'v3']);
    -  assertSameElements(['a', 'v', 'v2', 'v3'], map.get('key2'));
    -}
    -
    -
    -function testAddAllWithMultimap() {
    -  map.add('k', 'v');
    -  map.addAllValues('k2', ['v', 'v1', 'v2']);
    -
    -  var map2 = new goog.labs.structs.Multimap();
    -  map2.add('k2', 'v');
    -  map2.addAllValues('k3', ['a', 'a1', 'a2']);
    -
    -  map.addAllFromMultimap(map2);
    -  assertSameElements(['v'], map.get('k'));
    -  assertSameElements(['v', 'v1', 'v2', 'v'], map.get('k2'));
    -  assertSameElements(['a', 'a1', 'a2'], map.get('k3'));
    -}
    -
    -
    -function testAddAllWithMap() {
    -  map.add('k', 'v');
    -  map.addAllValues('k2', ['v', 'v1', 'v2']);
    -
    -  var map2 = new goog.labs.structs.Map();
    -  map2.set('k2', 'v');
    -  map2.set('k3', 'a');
    -
    -  map.addAllFromMultimap(map2);
    -  assertSameElements(['v'], map.get('k'));
    -  assertSameElements(['v', 'v1', 'v2', 'v'], map.get('k2'));
    -  assertSameElements(['a'], map.get('k3'));
    -}
    -
    -
    -function testReplaceValues() {
    -  map.add('key', 'v');
    -  map.add('key', 'v2');
    -
    -  map.replaceValues('key', [0, 1, 2]);
    -  assertSameElements([0, 1, 2], map.get('key'));
    -  assertEquals(3, map.getCount());
    -
    -  map.replaceValues('key', ['v']);
    -  assertSameElements(['v'], map.get('key'));
    -  assertEquals(1, map.getCount());
    -
    -  map.replaceValues('key', []);
    -  assertSameElements([], map.get('key'));
    -  assertEquals(0, map.getCount());
    -}
    -
    -
    -function testRemove() {
    -  map.add('key', 'v');
    -  map.add('key', 'v2');
    -  map.add('key', 'v3');
    -
    -  assertTrue(map.remove('key', 'v'));
    -  var values = map.get('key');
    -  assertEquals(2, map.getCount());
    -  assertEquals(2, values.length);
    -  assertContains('v2', values);
    -  assertContains('v3', values);
    -  assertFalse(map.remove('key', 'v'));
    -
    -  assertTrue(map.remove('key', 'v2'));
    -  values = map.get('key');
    -  assertEquals(1, map.getCount());
    -  assertEquals(1, values.length);
    -  assertContains('v3', values);
    -  assertFalse(map.remove('key', 'v2'));
    -
    -  assertTrue(map.remove('key', 'v3'));
    -  map.remove('key', 'v3');
    -  assertTrue(map.isEmpty());
    -  assertEquals(0, map.get('key').length);
    -  assertFalse(map.remove('key', 'v2'));
    -}
    -
    -
    -function testRemoveWithNaN() {
    -  map.add('key', NaN);
    -  map.add('key', NaN);
    -
    -  assertTrue(map.remove('key', NaN));
    -  var values = map.get('key');
    -  assertEquals(1, values.length);
    -  assertTrue(isNaN(values[0]));
    -
    -  assertTrue(map.remove('key', NaN));
    -  assertEquals(0, map.get('key').length);
    -  assertFalse(map.remove('key', NaN));
    -}
    -
    -
    -function testRemoveWithNegativeZero() {
    -  map.add('key', 0);
    -  map.add('key', -0);
    -
    -  assertTrue(map.remove('key', -0));
    -  var values = map.get('key');
    -  assertEquals(1, values.length);
    -  assertTrue(1 / values[0] === 1 / 0);
    -  assertFalse(map.remove('key', -0));
    -
    -  map.add('key', -0);
    -
    -  assertTrue(map.remove('key', 0));
    -  var values = map.get('key');
    -  assertEquals(1, values.length);
    -  assertTrue(1 / values[0] === 1 / -0);
    -  assertFalse(map.remove('key', 0));
    -
    -  assertTrue(map.remove('key', -0));
    -  assertEquals(0, map.get('key').length);
    -}
    -
    -
    -function testRemoveAll() {
    -  map.add('key', 'v');
    -  map.add('key', 'v2');
    -  map.add('key', 'v3');
    -  map.add('key', 'v4');
    -  map.add('key2', 'v');
    -
    -  assertTrue(map.removeAll('key'));
    -  assertSameElements([], map.get('key'));
    -  assertSameElements(['v'], map.get('key2'));
    -  assertFalse(map.removeAll('key'));
    -  assertEquals(1, map.getCount());
    -
    -  assertTrue(map.removeAll('key2'));
    -  assertSameElements([], map.get('key2'));
    -  assertFalse(map.removeAll('key2'));
    -  assertTrue(map.isEmpty());
    -}
    -
    -
    -function testAddWithDuplicateValue() {
    -  map.add('key', 'v');
    -  map.add('key', 'v');
    -  map.add('key', 'v');
    -  assertArrayEquals(['v', 'v', 'v'], map.get('key'));
    -}
    -
    -
    -function testContainsEntry() {
    -  assertFalse(map.containsEntry('k', 'v'));
    -  assertFalse(map.containsEntry('k', 'v2'));
    -  assertFalse(map.containsEntry('k2', 'v'));
    -
    -  map.add('k', 'v');
    -  assertTrue(map.containsEntry('k', 'v'));
    -  assertFalse(map.containsEntry('k', 'v2'));
    -  assertFalse(map.containsEntry('k2', 'v'));
    -
    -  map.add('k', 'v2');
    -  assertTrue(map.containsEntry('k', 'v'));
    -  assertTrue(map.containsEntry('k', 'v2'));
    -  assertFalse(map.containsEntry('k2', 'v'));
    -
    -  map.add('k2', 'v');
    -  assertTrue(map.containsEntry('k', 'v'));
    -  assertTrue(map.containsEntry('k', 'v2'));
    -  assertTrue(map.containsEntry('k2', 'v'));
    -}
    -
    -
    -function testContainsKey() {
    -  assertFalse(map.containsKey('k'));
    -  assertFalse(map.containsKey('k2'));
    -
    -  map.add('k', 'v');
    -  assertTrue(map.containsKey('k'));
    -  map.add('k2', 'v');
    -  assertTrue(map.containsKey('k2'));
    -
    -  map.remove('k', 'v');
    -  assertFalse(map.containsKey('k'));
    -  map.remove('k2', 'v');
    -  assertFalse(map.containsKey('k2'));
    -}
    -
    -
    -function testContainsValue() {
    -  assertFalse(map.containsValue('v'));
    -  assertFalse(map.containsValue('v2'));
    -
    -  map.add('key', 'v');
    -  assertTrue(map.containsValue('v'));
    -  map.add('key', 'v2');
    -  assertTrue(map.containsValue('v2'));
    -}
    -
    -
    -function testGetEntries() {
    -  map.add('key', 'v');
    -  map.add('key', 'v2');
    -  map.add('key2', 'v3');
    -
    -  var entries = map.getEntries();
    -  assertEquals(3, entries.length);
    -  assertContainsEntry(['key', 'v'], entries);
    -  assertContainsEntry(['key', 'v2'], entries);
    -  assertContainsEntry(['key2', 'v3'], entries);
    -}
    -
    -
    -function testGetKeys() {
    -  map.add('key', 'v');
    -  map.add('key', 'v2');
    -  map.add('key2', 'v3');
    -  map.add('key3', 'v4');
    -  map.removeAll('key3');
    -
    -  assertSameElements(['key', 'key2'], map.getKeys());
    -}
    -
    -
    -function testGetKeys() {
    -  map.add('key', 'v');
    -  map.add('key', 'v2');
    -  map.add('key2', 'v2');
    -  map.add('key3', 'v4');
    -  map.removeAll('key3');
    -
    -  assertSameElements(['v', 'v2', 'v2'], map.getValues());
    -}
    -
    -
    -function testGetReturnsDefensiveCopyOfUnderlyingData() {
    -  map.add('key', 'v');
    -  map.add('key', 'v2');
    -  map.add('key', 'v3');
    -
    -  var values = map.get('key');
    -  values.push('v4');
    -  assertFalse(map.containsEntry('key', 'v4'));
    -}
    -
    -
    -function testClear() {
    -  map.add('key', 'v');
    -  map.add('key', 'v2');
    -  map.add('key2', 'v3');
    -
    -  map.clear();
    -  assertTrue(map.isEmpty());
    -  assertSameElements([], map.getEntries());
    -}
    -
    -
    -function assertContainsEntry(entry, entryList) {
    -  for (var i = 0; i < entryList.length; ++i) {
    -    if (entry[0] == entryList[i][0] && entry[1] === entryList[i][1]) {
    -      return;
    -    }
    -  }
    -  fail('Did not find entry: ' + entry + ' in: ' + entryList);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/style/pixeldensitymonitor.js b/src/database/third_party/closure-library/closure/goog/labs/style/pixeldensitymonitor.js
    deleted file mode 100644
    index bc38b237c52..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/style/pixeldensitymonitor.js
    +++ /dev/null
    @@ -1,179 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Utility class that monitors pixel density ratio changes.
    - *
    - * @see ../demos/pixeldensitymonitor.html
    - */
    -
    -goog.provide('goog.labs.style.PixelDensityMonitor');
    -goog.provide('goog.labs.style.PixelDensityMonitor.Density');
    -goog.provide('goog.labs.style.PixelDensityMonitor.EventType');
    -
    -goog.require('goog.events');
    -goog.require('goog.events.EventTarget');
    -
    -
    -
    -/**
    - * Monitors the window for changes to the ratio between device and screen
    - * pixels, e.g. when the user moves the window from a high density screen to a
    - * screen with normal density. Dispatches
    - * goog.labs.style.PixelDensityMonitor.EventType.CHANGE events when the density
    - * changes between the two predefined values NORMAL and HIGH.
    - *
    - * This class uses the window.devicePixelRatio value which is supported in
    - * WebKit and FF18. If the value does not exist, it will always return a
    - * NORMAL density. It requires support for MediaQueryList to detect changes to
    - * the devicePixelRatio.
    - *
    - * @param {!goog.dom.DomHelper=} opt_domHelper The DomHelper which contains the
    - *     document associated with the window to listen to. Defaults to the one in
    - *     which this code is executing.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - * @final
    - */
    -goog.labs.style.PixelDensityMonitor = function(opt_domHelper) {
    -  goog.labs.style.PixelDensityMonitor.base(this, 'constructor');
    -
    -  /**
    -   * @type {Window}
    -   * @private
    -   */
    -  this.window_ = opt_domHelper ? opt_domHelper.getWindow() : window;
    -
    -  /**
    -   * The last density that was reported so that changes can be detected.
    -   * @type {goog.labs.style.PixelDensityMonitor.Density}
    -   * @private
    -   */
    -  this.lastDensity_ = this.getDensity();
    -
    -  /**
    -   * @type {function (MediaQueryList)}
    -   * @private
    -   */
    -  this.listener_ = goog.bind(this.handleMediaQueryChange_, this);
    -
    -  /**
    -   * The media query list for a query that detects high density, if supported
    -   * by the browser. Because matchMedia returns a new object for every call, it
    -   * needs to be saved here so the listener can be removed when disposing.
    -   * @type {?MediaQueryList}
    -   * @private
    -   */
    -  this.mediaQueryList_ = this.window_.matchMedia ? this.window_.matchMedia(
    -      goog.labs.style.PixelDensityMonitor.HIGH_DENSITY_QUERY_) : null;
    -};
    -goog.inherits(goog.labs.style.PixelDensityMonitor, goog.events.EventTarget);
    -
    -
    -/**
    - * The two different pixel density modes on which the various ratios between
    - * physical and device pixels are mapped.
    - * @enum {number}
    - */
    -goog.labs.style.PixelDensityMonitor.Density = {
    -  /**
    -   * Mode for older portable devices and desktop screens, defined as having a
    -   * device pixel ratio of less than 1.5.
    -   */
    -  NORMAL: 1,
    -
    -  /**
    -   * Mode for newer portable devices with a high resolution screen, defined as
    -   * having a device pixel ratio of more than 1.5.
    -   */
    -  HIGH: 2
    -};
    -
    -
    -/**
    - * The events fired by the PixelDensityMonitor.
    - * @enum {string}
    - */
    -goog.labs.style.PixelDensityMonitor.EventType = {
    -  /**
    -   * Dispatched when density changes between NORMAL and HIGH.
    -   */
    -  CHANGE: goog.events.getUniqueId('change')
    -};
    -
    -
    -/**
    - * Minimum ratio between device and screen pixel needed for high density mode.
    - * @type {number}
    - * @private
    - */
    -goog.labs.style.PixelDensityMonitor.HIGH_DENSITY_RATIO_ = 1.5;
    -
    -
    -/**
    - * Media query that matches for high density.
    - * @type {string}
    - * @private
    - */
    -goog.labs.style.PixelDensityMonitor.HIGH_DENSITY_QUERY_ =
    -    '(min-resolution: 1.5dppx), (-webkit-min-device-pixel-ratio: 1.5)';
    -
    -
    -/**
    - * Starts monitoring for changes in pixel density.
    - */
    -goog.labs.style.PixelDensityMonitor.prototype.start = function() {
    -  if (this.mediaQueryList_) {
    -    this.mediaQueryList_.addListener(this.listener_);
    -  }
    -};
    -
    -
    -/**
    - * @return {goog.labs.style.PixelDensityMonitor.Density} The density for the
    - *     window.
    - */
    -goog.labs.style.PixelDensityMonitor.prototype.getDensity = function() {
    -  if (this.window_.devicePixelRatio >=
    -      goog.labs.style.PixelDensityMonitor.HIGH_DENSITY_RATIO_) {
    -    return goog.labs.style.PixelDensityMonitor.Density.HIGH;
    -  } else {
    -    return goog.labs.style.PixelDensityMonitor.Density.NORMAL;
    -  }
    -};
    -
    -
    -/**
    - * Handles a change to the media query and checks whether the density has
    - * changed since the last call.
    - * @param {MediaQueryList} mql The list of changed media queries.
    - * @private
    - */
    -goog.labs.style.PixelDensityMonitor.prototype.handleMediaQueryChange_ =
    -    function(mql) {
    -  var newDensity = this.getDensity();
    -  if (this.lastDensity_ != newDensity) {
    -    this.lastDensity_ = newDensity;
    -    this.dispatchEvent(goog.labs.style.PixelDensityMonitor.EventType.CHANGE);
    -  }
    -};
    -
    -
    -/** @override */
    -goog.labs.style.PixelDensityMonitor.prototype.disposeInternal = function() {
    -  if (this.mediaQueryList_) {
    -    this.mediaQueryList_.removeListener(this.listener_);
    -  }
    -  goog.labs.style.PixelDensityMonitor.base(this, 'disposeInternal');
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/style/pixeldensitymonitor_test.html b/src/database/third_party/closure-library/closure/goog/labs/style/pixeldensitymonitor_test.html
    deleted file mode 100644
    index 0eb8d9e5b0c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/style/pixeldensitymonitor_test.html
    +++ /dev/null
    @@ -1,17 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<title>Tests for goog.labs.style.PixelDensityMonitor</title>
    -<script src="../../base.js"></script>
    -<script>
    -goog.require('goog.labs.style.PixelDensityMonitorTest');
    -</script>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/style/pixeldensitymonitor_test.js b/src/database/third_party/closure-library/closure/goog/labs/style/pixeldensitymonitor_test.js
    deleted file mode 100644
    index a3b1f209fae..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/style/pixeldensitymonitor_test.js
    +++ /dev/null
    @@ -1,146 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Tests for goog.labs.style.PixelDensityMonitor.
    - *
    - */
    -
    -goog.provide('goog.labs.style.PixelDensityMonitorTest');
    -goog.setTestOnly('goog.labs.style.PixelDensityMonitorTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.dom.DomHelper');
    -goog.require('goog.events');
    -goog.require('goog.labs.style.PixelDensityMonitor');
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -
    -var fakeWindow;
    -var recordFunction;
    -var monitor;
    -var mockControl;
    -var mediaQueryLists;
    -
    -function setUp() {
    -  recordFunction = goog.testing.recordFunction();
    -  mediaQueryLists = [];
    -  mockControl = new goog.testing.MockControl();
    -}
    -
    -function tearDown() {
    -  mockControl.$verifyAll();
    -  goog.dispose(monitor);
    -  goog.dispose(recordFunction);
    -}
    -
    -function setUpMonitor(initialRatio, hasMatchMedia) {
    -  fakeWindow = {
    -    devicePixelRatio: initialRatio
    -  };
    -
    -  if (hasMatchMedia) {
    -    // Every call to matchMedia should return a new media query list with its
    -    // own set of listeners.
    -    fakeWindow.matchMedia = function(query) {
    -      var listeners = [];
    -      var newList = {
    -        addListener: function(listener) {
    -          listeners.push(listener);
    -        },
    -        removeListener: function(listener) {
    -          goog.array.remove(listeners, listener);
    -        },
    -        callListeners: function() {
    -          for (var i = 0; i < listeners.length; i++) {
    -            listeners[i]();
    -          }
    -        },
    -        getListenerCount: function() {
    -          return listeners.length;
    -        }
    -      };
    -      mediaQueryLists.push(newList);
    -      return newList;
    -    };
    -  }
    -
    -  var domHelper = mockControl.createStrictMock(goog.dom.DomHelper);
    -  domHelper.getWindow().$returns(fakeWindow);
    -  mockControl.$replayAll();
    -
    -  monitor = new goog.labs.style.PixelDensityMonitor(domHelper);
    -  goog.events.listen(monitor,
    -      goog.labs.style.PixelDensityMonitor.EventType.CHANGE, recordFunction);
    -}
    -
    -function setNewRatio(newRatio) {
    -  fakeWindow.devicePixelRatio = newRatio;
    -  for (var i = 0; i < mediaQueryLists.length; i++) {
    -    mediaQueryLists[i].callListeners();
    -  }
    -}
    -
    -function testNormalDensity() {
    -  setUpMonitor(1, false);
    -  assertEquals(goog.labs.style.PixelDensityMonitor.Density.NORMAL,
    -      monitor.getDensity());
    -}
    -
    -function testHighDensity() {
    -  setUpMonitor(1.5, false);
    -  assertEquals(goog.labs.style.PixelDensityMonitor.Density.HIGH,
    -      monitor.getDensity());
    -}
    -
    -function testNormalDensityIfUndefined() {
    -  setUpMonitor(undefined, false);
    -  assertEquals(goog.labs.style.PixelDensityMonitor.Density.NORMAL,
    -      monitor.getDensity());
    -}
    -
    -function testChangeEvent() {
    -  setUpMonitor(1, true);
    -  assertEquals(goog.labs.style.PixelDensityMonitor.Density.NORMAL,
    -      monitor.getDensity());
    -  monitor.start();
    -
    -  setNewRatio(2);
    -  var call = recordFunction.popLastCall();
    -  assertEquals(goog.labs.style.PixelDensityMonitor.Density.HIGH,
    -      call.getArgument(0).target.getDensity());
    -  assertEquals(goog.labs.style.PixelDensityMonitor.Density.HIGH,
    -      monitor.getDensity());
    -
    -  setNewRatio(1);
    -  call = recordFunction.popLastCall();
    -  assertEquals(goog.labs.style.PixelDensityMonitor.Density.NORMAL,
    -      call.getArgument(0).target.getDensity());
    -  assertEquals(goog.labs.style.PixelDensityMonitor.Density.NORMAL,
    -      monitor.getDensity());
    -}
    -
    -function testListenerIsDisposed() {
    -  setUpMonitor(1, true);
    -  monitor.start();
    -
    -  assertEquals(1, mediaQueryLists.length);
    -  assertEquals(1, mediaQueryLists[0].getListenerCount());
    -
    -  goog.dispose(monitor);
    -
    -  assertEquals(1, mediaQueryLists.length);
    -  assertEquals(0, mediaQueryLists[0].getListenerCount());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/testing/assertthat.js b/src/database/third_party/closure-library/closure/goog/labs/testing/assertthat.js
    deleted file mode 100644
    index d0843eb2b25..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/testing/assertthat.js
    +++ /dev/null
    @@ -1,58 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides main functionality of assertThat. assertThat calls the
    - * matcher's matches method to test if a matcher matches assertThat's arguments.
    - */
    -
    -
    -goog.provide('goog.labs.testing.MatcherError');
    -goog.provide('goog.labs.testing.assertThat');
    -
    -goog.require('goog.debug.Error');
    -
    -
    -/**
    - * Asserts that the actual value evaluated by the matcher is true.
    - *
    - * @param {*} actual The object to assert by the matcher.
    - * @param {!goog.labs.testing.Matcher} matcher A matcher to verify values.
    - * @param {string=} opt_reason Description of what is asserted.
    - *
    - */
    -goog.labs.testing.assertThat = function(actual, matcher, opt_reason) {
    -  if (!matcher.matches(actual)) {
    -    // Prefix the error description with a reason from the assert ?
    -    var prefix = opt_reason ? opt_reason + ': ' : '';
    -    var desc = prefix + matcher.describe(actual);
    -
    -    // some sort of failure here
    -    throw new goog.labs.testing.MatcherError(desc);
    -  }
    -};
    -
    -
    -
    -/**
    - * Error thrown when a Matcher fails to match the input value.
    - * @param {string=} opt_message The error message.
    - * @constructor
    - * @extends {goog.debug.Error}
    - * @final
    - */
    -goog.labs.testing.MatcherError = function(opt_message) {
    -  goog.labs.testing.MatcherError.base(this, 'constructor', opt_message);
    -};
    -goog.inherits(goog.labs.testing.MatcherError, goog.debug.Error);
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/testing/assertthat_test.html b/src/database/third_party/closure-library/closure/goog/labs/testing/assertthat_test.html
    deleted file mode 100644
    index a22ca62f5bb..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/testing/assertthat_test.html
    +++ /dev/null
    @@ -1,21 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.labs.testing.assertThat
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.labs.testing.assertThatTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/testing/assertthat_test.js b/src/database/third_party/closure-library/closure/goog/labs/testing/assertthat_test.js
    deleted file mode 100644
    index 6a054bcabc5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/testing/assertthat_test.js
    +++ /dev/null
    @@ -1,69 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.labs.testing.assertThatTest');
    -goog.setTestOnly('goog.labs.testing.assertThatTest');
    -
    -goog.require('goog.labs.testing.MatcherError');
    -goog.require('goog.labs.testing.assertThat');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -
    -var successMatchesFn, failureMatchesFn, describeFn, successTestMatcher;
    -var failureTestMatcher;
    -
    -function setUp() {
    -  successMatchesFn = new goog.testing.recordFunction(function() {return true;});
    -  failureMatchesFn =
    -      new goog.testing.recordFunction(function() {return false;});
    -  describeFn = new goog.testing.recordFunction();
    -
    -  successTestMatcher = function() {
    -    return { matches: successMatchesFn, describe: describeFn };
    -  };
    -  failureTestMatcher = function() {
    -    return { matches: failureMatchesFn, describe: describeFn };
    -  };
    -}
    -
    -function testAssertthatAlwaysCallsMatches() {
    -  var value = 7;
    -  goog.labs.testing.assertThat(value, successTestMatcher(),
    -      'matches is called on success');
    -
    -  assertEquals(1, successMatchesFn.getCallCount());
    -  var matchesCall = successMatchesFn.popLastCall();
    -  assertEquals(value, matchesCall.getArgument(0));
    -
    -  var e = assertThrows(goog.bind(goog.labs.testing.assertThat, null,
    -      value, failureTestMatcher(), 'matches is called on failure'));
    -
    -  assertTrue(e instanceof goog.labs.testing.MatcherError);
    -
    -  assertEquals(1, failureMatchesFn.getCallCount());
    -}
    -
    -function testAssertthatCallsDescribeOnFailure() {
    -  var value = 7;
    -  var e = assertThrows(goog.bind(goog.labs.testing.assertThat, null,
    -      value, failureTestMatcher(), 'describe is called on failure'));
    -
    -  assertTrue(e instanceof goog.labs.testing.MatcherError);
    -
    -  assertEquals(1, failureMatchesFn.getCallCount());
    -  assertEquals(1, describeFn.getCallCount());
    -
    -  var matchesCall = describeFn.popLastCall();
    -  assertEquals(value, matchesCall.getArgument(0));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/testing/decoratormatcher.js b/src/database/third_party/closure-library/closure/goog/labs/testing/decoratormatcher.js
    deleted file mode 100644
    index d0ad753afa1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/testing/decoratormatcher.js
    +++ /dev/null
    @@ -1,95 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides the built-in decorators: is, describedAs, anything.
    - */
    -
    -
    -
    -goog.provide('goog.labs.testing.AnythingMatcher');
    -
    -
    -goog.require('goog.labs.testing.Matcher');
    -
    -
    -
    -/**
    - * The Anything matcher. Matches all possible inputs.
    - *
    - * @constructor
    - * @implements {goog.labs.testing.Matcher}
    - * @final
    - */
    -goog.labs.testing.AnythingMatcher = function() {};
    -
    -
    -/**
    - * Matches anything. Useful if one doesn't care what the object under test is.
    - *
    - * @override
    - */
    -goog.labs.testing.AnythingMatcher.prototype.matches =
    -    function(actualObject) {
    -  return true;
    -};
    -
    -
    -/**
    - * This method is never called but is needed so AnythingMatcher implements the
    - * Matcher interface.
    - *
    - * @override
    - */
    -goog.labs.testing.AnythingMatcher.prototype.describe =
    -    function(actualObject) {
    -  throw Error('AnythingMatcher should never fail!');
    -};
    -
    -
    -/**
    - * Returns a matcher that matches anything.
    - *
    - * @return {!goog.labs.testing.AnythingMatcher} A AnythingMatcher.
    - */
    -function anything() {
    -  return new goog.labs.testing.AnythingMatcher();
    -}
    -
    -
    -/**
    - * Returnes any matcher that is passed to it (aids readability).
    - *
    - * @param {!goog.labs.testing.Matcher} matcher A matcher.
    - * @return {!goog.labs.testing.Matcher} The wrapped matcher.
    - */
    -function is(matcher) {
    -  return matcher;
    -}
    -
    -
    -/**
    - * Returns a matcher with a customized description for the given matcher.
    - *
    - * @param {string} description The custom description for the matcher.
    - * @param {!goog.labs.testing.Matcher} matcher The matcher.
    - *
    - * @return {!goog.labs.testing.Matcher} The matcher with custom description.
    - */
    -function describedAs(description, matcher) {
    -  matcher.describe = function(value) {
    -    return description;
    -  };
    -  return matcher;
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/testing/decoratormatcher_test.html b/src/database/third_party/closure-library/closure/goog/labs/testing/decoratormatcher_test.html
    deleted file mode 100644
    index ac29d26b8a5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/testing/decoratormatcher_test.html
    +++ /dev/null
    @@ -1,21 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - Decorator matchers
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.labs.testing.decoratorMatcherTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/testing/decoratormatcher_test.js b/src/database/third_party/closure-library/closure/goog/labs/testing/decoratormatcher_test.js
    deleted file mode 100644
    index 4f8792ecef1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/testing/decoratormatcher_test.js
    +++ /dev/null
    @@ -1,41 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.labs.testing.decoratorMatcherTest');
    -goog.setTestOnly('goog.labs.testing.decoratorMatcherTest');
    -
    -/** @suppress {extraRequire} */
    -goog.require('goog.labs.testing.AnythingMatcher');
    -/** @suppress {extraRequire} */
    -goog.require('goog.labs.testing.GreaterThanMatcher');
    -goog.require('goog.labs.testing.MatcherError');
    -goog.require('goog.labs.testing.assertThat');
    -goog.require('goog.testing.jsunit');
    -
    -function testAnythingMatcher() {
    -  goog.labs.testing.assertThat(true, anything(), 'anything matches true');
    -  goog.labs.testing.assertThat(false, anything(), 'false matches anything');
    -}
    -
    -function testIs() {
    -  goog.labs.testing.assertThat(5, is(greaterThan(4)), '5 is > 4');
    -}
    -
    -function testDescribedAs() {
    -  var e = assertThrows(function() {
    -    goog.labs.testing.assertThat(4, describedAs('this is a test',
    -        greaterThan(6)))});
    -  assertTrue(e instanceof goog.labs.testing.MatcherError);
    -  assertEquals('this is a test', e.message);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/testing/dictionarymatcher.js b/src/database/third_party/closure-library/closure/goog/labs/testing/dictionarymatcher.js
    deleted file mode 100644
    index cfddd74ed6c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/testing/dictionarymatcher.js
    +++ /dev/null
    @@ -1,273 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides the built-in dictionary matcher methods like
    - *     hasEntry, hasEntries, hasKey, hasValue, etc.
    - */
    -
    -
    -
    -goog.provide('goog.labs.testing.HasEntriesMatcher');
    -goog.provide('goog.labs.testing.HasEntryMatcher');
    -goog.provide('goog.labs.testing.HasKeyMatcher');
    -goog.provide('goog.labs.testing.HasValueMatcher');
    -
    -
    -goog.require('goog.asserts');
    -goog.require('goog.labs.testing.Matcher');
    -goog.require('goog.object');
    -
    -
    -
    -/**
    - * The HasEntries matcher.
    - *
    - * @param {!Object} entries The entries to check in the object.
    - *
    - * @constructor
    - * @struct
    - * @implements {goog.labs.testing.Matcher}
    - * @final
    - */
    -goog.labs.testing.HasEntriesMatcher = function(entries) {
    -  /**
    -   * @type {Object}
    -   * @private
    -   */
    -  this.entries_ = entries;
    -};
    -
    -
    -/**
    - * Determines if an object has particular entries.
    - *
    - * @override
    - */
    -goog.labs.testing.HasEntriesMatcher.prototype.matches =
    -    function(actualObject) {
    -  goog.asserts.assertObject(actualObject, 'Expected an Object');
    -  var object = /** @type {!Object} */(actualObject);
    -  return goog.object.every(this.entries_, function(value, key) {
    -    return goog.object.containsKey(object, key) &&
    -           object[key] === value;
    -  });
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.labs.testing.HasEntriesMatcher.prototype.describe =
    -    function(actualObject) {
    -  goog.asserts.assertObject(actualObject, 'Expected an Object');
    -  var object = /** @type {!Object} */(actualObject);
    -  var errorString = 'Input object did not contain the following entries:\n';
    -  goog.object.forEach(this.entries_, function(value, key) {
    -    if (!goog.object.containsKey(object, key) ||
    -        object[key] !== value) {
    -      errorString += key + ': ' + value + '\n';
    -    }
    -  });
    -  return errorString;
    -};
    -
    -
    -
    -/**
    - * The HasEntry matcher.
    - *
    - * @param {string} key The key for the entry.
    - * @param {*} value The value for the key.
    - *
    - * @constructor
    - * @struct
    - * @implements {goog.labs.testing.Matcher}
    - * @final
    - */
    -goog.labs.testing.HasEntryMatcher = function(key, value) {
    -  /**
    -   * @type {string}
    -   * @private
    -   */
    -  this.key_ = key;
    -  /**
    -   * @type {*}
    -   * @private
    -   */
    -  this.value_ = value;
    -};
    -
    -
    -/**
    - * Determines if an object has a particular entry.
    - *
    - * @override
    - */
    -goog.labs.testing.HasEntryMatcher.prototype.matches =
    -    function(actualObject) {
    -  goog.asserts.assertObject(actualObject);
    -  return goog.object.containsKey(actualObject, this.key_) &&
    -         actualObject[this.key_] === this.value_;
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.labs.testing.HasEntryMatcher.prototype.describe =
    -    function(actualObject) {
    -  goog.asserts.assertObject(actualObject);
    -  var errorMsg;
    -  if (goog.object.containsKey(actualObject, this.key_)) {
    -    errorMsg = 'Input object did not contain key: ' + this.key_;
    -  } else {
    -    errorMsg = 'Value for key did not match value: ' + this.value_;
    -  }
    -  return errorMsg;
    -};
    -
    -
    -
    -/**
    - * The HasKey matcher.
    - *
    - * @param {string} key The key to check in the object.
    - *
    - * @constructor
    - * @struct
    - * @implements {goog.labs.testing.Matcher}
    - * @final
    - */
    -goog.labs.testing.HasKeyMatcher = function(key) {
    -  /**
    -   * @type {string}
    -   * @private
    -   */
    -  this.key_ = key;
    -};
    -
    -
    -/**
    - * Determines if an object has a key.
    - *
    - * @override
    - */
    -goog.labs.testing.HasKeyMatcher.prototype.matches =
    -    function(actualObject) {
    -  goog.asserts.assertObject(actualObject);
    -  return goog.object.containsKey(actualObject, this.key_);
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.labs.testing.HasKeyMatcher.prototype.describe =
    -    function(actualObject) {
    -  goog.asserts.assertObject(actualObject);
    -  return 'Input object did not contain the key: ' + this.key_;
    -};
    -
    -
    -
    -/**
    - * The HasValue matcher.
    - *
    - * @param {*} value The value to check in the object.
    - *
    - * @constructor
    - * @struct
    - * @implements {goog.labs.testing.Matcher}
    - * @final
    - */
    -goog.labs.testing.HasValueMatcher = function(value) {
    -  /**
    -   * @type {*}
    -   * @private
    -   */
    -  this.value_ = value;
    -};
    -
    -
    -/**
    - * Determines if an object contains a value
    - *
    - * @override
    - */
    -goog.labs.testing.HasValueMatcher.prototype.matches =
    -    function(actualObject) {
    -  goog.asserts.assertObject(actualObject, 'Expected an Object');
    -  var object = /** @type {!Object} */(actualObject);
    -  return goog.object.containsValue(object, this.value_);
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.labs.testing.HasValueMatcher.prototype.describe =
    -    function(actualObject) {
    -  return 'Input object did not contain the value: ' + this.value_;
    -};
    -
    -
    -/**
    - * Gives a matcher that asserts an object contains all the given key-value pairs
    - * in the input object.
    - *
    - * @param {!Object} entries The entries to check for presence in the object.
    - *
    - * @return {!goog.labs.testing.HasEntriesMatcher} A HasEntriesMatcher.
    - */
    -function hasEntries(entries) {
    -  return new goog.labs.testing.HasEntriesMatcher(entries);
    -}
    -
    -
    -/**
    - * Gives a matcher that asserts an object contains the given key-value pair.
    - *
    - * @param {string} key The key to check for presence in the object.
    - * @param {*} value The value to check for presence in the object.
    - *
    - * @return {!goog.labs.testing.HasEntryMatcher} A HasEntryMatcher.
    - */
    -function hasEntry(key, value) {
    -  return new goog.labs.testing.HasEntryMatcher(key, value);
    -}
    -
    -
    -/**
    - * Gives a matcher that asserts an object contains the given key.
    - *
    - * @param {string} key The key to check for presence in the object.
    - *
    - * @return {!goog.labs.testing.HasKeyMatcher} A HasKeyMatcher.
    - */
    -function hasKey(key) {
    -  return new goog.labs.testing.HasKeyMatcher(key);
    -}
    -
    -
    -/**
    - * Gives a matcher that asserts an object contains the given value.
    - *
    - * @param {*} value The value to check for presence in the object.
    - *
    - * @return {!goog.labs.testing.HasValueMatcher} A HasValueMatcher.
    - */
    -function hasValue(value) {
    -  return new goog.labs.testing.HasValueMatcher(value);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/testing/dictionarymatcher_test.html b/src/database/third_party/closure-library/closure/goog/labs/testing/dictionarymatcher_test.html
    deleted file mode 100644
    index 785e367cd18..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/testing/dictionarymatcher_test.html
    +++ /dev/null
    @@ -1,21 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - Object matchers
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.labs.testing.dictionaryMatcherTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/testing/dictionarymatcher_test.js b/src/database/third_party/closure-library/closure/goog/labs/testing/dictionarymatcher_test.js
    deleted file mode 100644
    index 615c78d877f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/testing/dictionarymatcher_test.js
    +++ /dev/null
    @@ -1,65 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.labs.testing.dictionaryMatcherTest');
    -goog.setTestOnly('goog.labs.testing.dictionaryMatcherTest');
    -
    -/** @suppress {extraRequire} */
    -goog.require('goog.labs.testing.HasEntryMatcher');
    -goog.require('goog.labs.testing.MatcherError');
    -goog.require('goog.labs.testing.assertThat');
    -goog.require('goog.testing.jsunit');
    -
    -function testHasEntries() {
    -  var obj1 = {x: 1, y: 2, z: 3};
    -  goog.labs.testing.assertThat(obj1, hasEntries({x: 1, y: 2}),
    -      'obj1 has entries: {x:1, y:2}');
    -
    -  assertMatcherError(function() {
    -    goog.labs.testing.assertThat(obj1, hasEntries({z: 5, a: 4}));
    -  }, 'hasEntries should throw exception when it fails');
    -}
    -
    -function testHasEntry() {
    -  var obj1 = {x: 1, y: 2, z: 3};
    -  goog.labs.testing.assertThat(obj1, hasEntry('x', 1),
    -      'obj1 has entry: {x:1}');
    -
    -  assertMatcherError(function() {
    -    goog.labs.testing.assertThat(obj1, hasEntry('z', 5));
    -  }, 'hasEntry should throw exception when it fails');
    -}
    -
    -function testHasKey() {
    -  var obj1 = {x: 1};
    -  goog.labs.testing.assertThat(obj1, hasKey('x'), 'obj1 has key x');
    -
    -  assertMatcherError(function() {
    -    goog.labs.testing.assertThat(obj1, hasKey('z'));
    -  }, 'hasKey should throw exception when it fails');
    -}
    -
    -function testHasValue() {
    -  var obj1 = {x: 1};
    -  goog.labs.testing.assertThat(obj1, hasValue(1), 'obj1 has value 1');
    -
    -  assertMatcherError(function() {
    -    goog.labs.testing.assertThat(obj1, hasValue(2));
    -  }, 'hasValue should throw exception when it fails');
    -}
    -
    -function assertMatcherError(callable, errorString) {
    -  var e = assertThrows(errorString || 'callable throws exception', callable);
    -  assertTrue(e instanceof goog.labs.testing.MatcherError);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/testing/environment.js b/src/database/third_party/closure-library/closure/goog/labs/testing/environment.js
    deleted file mode 100644
    index a3468e4e83f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/testing/environment.js
    +++ /dev/null
    @@ -1,293 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.labs.testing.Environment');
    -
    -goog.require('goog.array');
    -goog.require('goog.debug.Console');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.TestCase');
    -goog.require('goog.testing.jsunit');
    -
    -
    -/**
    - * JsUnit environments allow developers to customize the existing testing
    - * lifecycle by hitching additional setUp and tearDown behaviors to tests.
    - *
    - * Environments will run their setUp steps in the order in which they
    - * are instantiated and registered. During tearDown, the environments will
    - * unwind the setUp and execute in reverse order.
    - *
    - * See http://go/jsunit-env for more information.
    - */
    -goog.labs.testing.Environment = goog.defineClass(null, {
    -  /** @constructor */
    -  constructor: function() {
    -    goog.labs.testing.EnvironmentTestCase_.getInstance().
    -        registerEnvironment_(this);
    -
    -    /** @type {goog.testing.MockControl} */
    -    this.mockControl = null;
    -
    -    /** @type {goog.testing.MockClock} */
    -    this.mockClock = null;
    -
    -    /** @private {boolean} */
    -    this.shouldMakeMockControl_ = false;
    -
    -    /** @private {boolean} */
    -    this.shouldMakeMockClock_ = false;
    -
    -    /** @const {!goog.debug.Console} */
    -    this.console = goog.labs.testing.Environment.console_;
    -  },
    -
    -
    -  /** Runs immediately before the setUpPage phase of JsUnit tests. */
    -  setUpPage: function() {
    -    if (this.mockClock && this.mockClock.isDisposed()) {
    -      this.mockClock = new goog.testing.MockClock(true);
    -    }
    -  },
    -
    -
    -  /** Runs immediately after the tearDownPage phase of JsUnit tests. */
    -  tearDownPage: function() {
    -    // If we created the mockClock, we'll also dispose it.
    -    if (this.shouldMakeMockClock_) {
    -      this.mockClock.dispose();
    -    }
    -  },
    -
    -  /** Runs immediately before the setUp phase of JsUnit tests. */
    -  setUp: goog.nullFunction,
    -
    -  /** Runs immediately after the tearDown phase of JsUnit tests. */
    -  tearDown: function() {
    -    // Make sure promises and other stuff that may still be scheduled, get a
    -    // chance to run (and throw errors).
    -    if (this.mockClock) {
    -      for (var i = 0; i < 100; i++) {
    -        this.mockClock.tick(1000);
    -      }
    -      // If we created the mockClock, we'll also reset it.
    -      if (this.shouldMakeMockClock_) {
    -        this.mockClock.reset();
    -      }
    -    }
    -    // Make sure the user did not forget to call $replayAll & $verifyAll in
    -    // their test. This is a noop if they did.
    -    // This is important because:
    -    // - Engineers thinks that not all their tests need to replay and verify.
    -    //   That lets tests sneak in that call mocks but never replay those calls.
    -    // - Then some well meaning maintenance engineer wants to update the test
    -    //   with some new mock, adds a replayAll and BOOM the test fails
    -    //   because completely unrelated mocks now get replayed.
    -    if (this.mockControl) {
    -      try {
    -        this.mockControl.$verifyAll();
    -        this.mockControl.$replayAll();
    -        this.mockControl.$verifyAll();
    -      } finally {
    -        this.mockControl.$resetAll();
    -      }
    -      if (this.shouldMakeMockControl_) {
    -        // If we created the mockControl, we'll also tear it down.
    -        this.mockControl.$tearDown();
    -      }
    -    }
    -    // Verifying the mockControl may throw, so if cleanup needs to happen,
    -    // add it further up in the function.
    -  },
    -
    -
    -  /**
    -   * Create a new {@see goog.testing.MockControl} accessible via
    -   * {@code env.mockControl} for each test. If your test has more than one
    -   * testing environment, don't call this on more than one of them.
    -   * @return {!goog.labs.testing.Environment} For chaining.
    -   */
    -  withMockControl: function() {
    -    if (!this.shouldMakeMockControl_) {
    -      this.shouldMakeMockControl_ = true;
    -      this.mockControl = new goog.testing.MockControl();
    -    }
    -    return this;
    -  },
    -
    -
    -  /**
    -   * Create a {@see goog.testing.MockClock} for each test. The clock will be
    -   * installed (override i.e. setTimeout) by default. It can be accessed
    -   * using {@code env.mockClock}. If your test has more than one testing
    -   * environment, don't call this on more than one of them.
    -   * @return {!goog.labs.testing.Environment} For chaining.
    -   */
    -  withMockClock: function() {
    -    if (!this.shouldMakeMockClock_) {
    -      this.shouldMakeMockClock_ = true;
    -      this.mockClock = new goog.testing.MockClock(true);
    -    }
    -    return this;
    -  },
    -
    -
    -  /**
    -   * Creates a basic strict mock of a {@code toMock}. For more advanced mocking,
    -   * please use the MockControl directly.
    -   * @param {Function} toMock
    -   * @return {!goog.testing.StrictMock}
    -   */
    -  mock: function(toMock) {
    -    if (!this.shouldMakeMockControl_) {
    -      throw new Error('MockControl not available on this environment. ' +
    -                      'Call withMockControl if this environment is expected ' +
    -                      'to contain a MockControl.');
    -    }
    -    return this.mockControl.createStrictMock(toMock);
    -  }
    -});
    -
    -
    -/** @private @const {!goog.debug.Console} */
    -goog.labs.testing.Environment.console_ = new goog.debug.Console();
    -
    -
    -// Activate logging to the browser's console by default.
    -goog.labs.testing.Environment.console_.setCapturing(true);
    -
    -
    -
    -/**
    - * An internal TestCase used to hook environments into the JsUnit test runner.
    - * Environments cannot be used in conjunction with custom TestCases for JsUnit.
    - * @private @final @constructor
    - * @extends {goog.testing.TestCase}
    - */
    -goog.labs.testing.EnvironmentTestCase_ = function() {
    -  goog.labs.testing.EnvironmentTestCase_.base(this, 'constructor');
    -
    -  /** @private {!Array<!goog.labs.testing.Environment>}> */
    -  this.environments_ = [];
    -
    -  // Automatically install this TestCase when any environment is used in a test.
    -  goog.testing.TestCase.initializeTestRunner(this);
    -};
    -goog.inherits(goog.labs.testing.EnvironmentTestCase_, goog.testing.TestCase);
    -goog.addSingletonGetter(goog.labs.testing.EnvironmentTestCase_);
    -
    -
    -/**
    - * Override the default global scope discovery of lifecycle functions to prevent
    - * overriding the custom environment setUp(Page)/tearDown(Page) logic.
    - * @override
    - */
    -goog.labs.testing.EnvironmentTestCase_.prototype.autoDiscoverLifecycle =
    -    function() {
    -  if (goog.global['runTests']) {
    -    this.runTests = goog.bind(goog.global['runTests'], goog.global);
    -  }
    -  if (goog.global['shouldRunTests']) {
    -    this.shouldRunTests = goog.bind(goog.global['shouldRunTests'], goog.global);
    -  }
    -};
    -
    -
    -/**
    - * Adds an environment to the JsUnit test.
    - * @param {!goog.labs.testing.Environment} env
    - * @private
    - */
    -goog.labs.testing.EnvironmentTestCase_.prototype.registerEnvironment_ =
    -    function(env) {
    -  this.environments_.push(env);
    -};
    -
    -
    -/** @override */
    -goog.labs.testing.EnvironmentTestCase_.prototype.setUpPage = function() {
    -  goog.array.forEach(this.environments_, function(env) {
    -    env.setUpPage();
    -  });
    -
    -  // User defined setUpPage method.
    -  if (goog.global['setUpPage']) {
    -    goog.global['setUpPage']();
    -  }
    -};
    -
    -
    -/** @override */
    -goog.labs.testing.EnvironmentTestCase_.prototype.setUp = function() {
    -  // User defined configure method.
    -  if (goog.global['configureEnvironment']) {
    -    goog.global['configureEnvironment']();
    -  }
    -
    -  goog.array.forEach(this.environments_, function(env) {
    -    env.setUp();
    -  }, this);
    -
    -  // User defined setUp method.
    -  if (goog.global['setUp']) {
    -    goog.global['setUp']();
    -  }
    -};
    -
    -
    -/** @override */
    -goog.labs.testing.EnvironmentTestCase_.prototype.tearDown = function() {
    -  var firstException;
    -  // User defined tearDown method.
    -  if (goog.global['tearDown']) {
    -    try {
    -      goog.global['tearDown']();
    -    } catch (e) {
    -      if (!firstException) {
    -        firstException = e;
    -      }
    -    }
    -  }
    -
    -  // Execute the tearDown methods for the environment in the reverse order
    -  // in which they were registered to "unfold" the setUp.
    -  goog.array.forEachRight(this.environments_, function(env) {
    -    // For tearDowns between tests make sure they run as much as possible to
    -    // avoid interference between tests.
    -    try {
    -      env.tearDown();
    -    } catch (e) {
    -      if (!firstException) {
    -        firstException = e;
    -      }
    -    }
    -  });
    -  if (firstException) {
    -    throw firstException;
    -  }
    -};
    -
    -
    -/** @override */
    -goog.labs.testing.EnvironmentTestCase_.prototype.tearDownPage = function() {
    -  // User defined tearDownPage method.
    -  if (goog.global['tearDownPage']) {
    -    goog.global['tearDownPage']();
    -  }
    -
    -  goog.array.forEachRight(this.environments_, function(env) {
    -    env.tearDownPage();
    -  });
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/testing/environment_test.html b/src/database/third_party/closure-library/closure/goog/labs/testing/environment_test.html
    deleted file mode 100644
    index c8d4ab0e2d2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/testing/environment_test.html
    +++ /dev/null
    @@ -1,21 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - JsUnit Environments
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.labs.testing.environmentTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/testing/environment_test.js b/src/database/third_party/closure-library/closure/goog/labs/testing/environment_test.js
    deleted file mode 100644
    index 8f3fdf259ac..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/testing/environment_test.js
    +++ /dev/null
    @@ -1,210 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.labs.testing.environmentTest');
    -goog.setTestOnly('goog.labs.testing.environmentTest');
    -
    -goog.require('goog.labs.testing.Environment');
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.TestCase');
    -goog.require('goog.testing.jsunit');
    -
    -var testCase = null;
    -var mockControl = null;
    -
    -// Use this flag to control whether the global JsUnit lifecycle events are being
    -// called as part of the test lifecycle or as part of the "mocked" environment.
    -var testing = false;
    -
    -function setUp() {
    -  if (testing) {
    -    return;
    -  }
    -
    -  // Temporarily override the initializeTestRunner method to avoid installing
    -  // our "test" TestCase.
    -  var initFn = goog.testing.TestCase.initializeTestRunner;
    -  goog.testing.TestCase.initializeTestRunner = function() {};
    -  testCase = new goog.labs.testing.EnvironmentTestCase_();
    -  goog.labs.testing.EnvironmentTestCase_.getInstance = function() {
    -    return testCase;
    -  };
    -  goog.testing.TestCase.initializeTestRunner = initFn;
    -
    -  mockControl = new goog.testing.MockControl();
    -}
    -
    -function tearDown() {
    -  if (testing) {
    -    return;
    -  }
    -
    -  mockControl.$resetAll();
    -  mockControl.$tearDown();
    -}
    -
    -function testLifecycle() {
    -  testing = true;
    -
    -  var envOne = mockControl.createStrictMock(goog.labs.testing.Environment);
    -  var envTwo = mockControl.createStrictMock(goog.labs.testing.Environment);
    -  var envThree = mockControl.createStrictMock(goog.labs.testing.Environment);
    -  var testMethod = mockControl.createFunctionMock('testMethod');
    -
    -  testCase.addNewTest('testFake', testMethod);
    -
    -  testCase.registerEnvironment_(envOne);
    -  testCase.registerEnvironment_(envTwo);
    -  testCase.registerEnvironment_(envThree);
    -
    -  envOne.setUpPage();
    -  envTwo.setUpPage();
    -  envThree.setUpPage();
    -
    -  envOne.setUp();
    -  envTwo.setUp();
    -  envThree.setUp();
    -
    -  testMethod();
    -
    -  envThree.tearDown();
    -  envTwo.tearDown();
    -  envOne.tearDown();
    -
    -  envThree.tearDownPage();
    -  envTwo.tearDownPage();
    -  envOne.tearDownPage();
    -
    -  mockControl.$replayAll();
    -  testCase.runTests();
    -  mockControl.$verifyAll();
    -
    -  testing = false;
    -}
    -
    -function testTearDownWithMockControl() {
    -  testing = true;
    -
    -  var envWith = new goog.labs.testing.Environment();
    -  var envWithout = new goog.labs.testing.Environment();
    -
    -  var mockControlMock = mockControl.createStrictMock(goog.testing.MockControl);
    -  var mockControlCtorMock = mockControl.createMethodMock(goog.testing,
    -      'MockControl');
    -  mockControlCtorMock().$times(1).$returns(mockControlMock);
    -  // Expecting verify / reset calls twice since two environments use the same
    -  // mockControl, but only one created it and is allowed to tear it down.
    -  mockControlMock.$verifyAll();
    -  mockControlMock.$replayAll();
    -  mockControlMock.$verifyAll();
    -  mockControlMock.$resetAll();
    -  mockControlMock.$tearDown().$times(1);
    -  mockControlMock.$verifyAll();
    -  mockControlMock.$replayAll();
    -  mockControlMock.$verifyAll();
    -  mockControlMock.$resetAll();
    -
    -  mockControl.$replayAll();
    -  envWith.withMockControl();
    -  envWithout.mockControl = mockControlMock;
    -  envWith.tearDown();
    -  envWithout.tearDown();
    -  mockControl.$verifyAll();
    -  mockControl.$resetAll();
    -
    -  testing = false;
    -}
    -
    -function testAutoDiscoverTests() {
    -  testing = true;
    -
    -  var setUpPageFn = testCase.setUpPage;
    -  var setUpFn = testCase.setUp;
    -  var tearDownFn = testCase.tearDownFn;
    -  var tearDownPageFn = testCase.tearDownPageFn;
    -
    -  testCase.autoDiscoverTests();
    -
    -  assertEquals(setUpPageFn, testCase.setUpPage);
    -  assertEquals(setUpFn, testCase.setUp);
    -  assertEquals(tearDownFn, testCase.tearDownFn);
    -  assertEquals(tearDownPageFn, testCase.tearDownPageFn);
    -
    -  // Note that this number changes when more tests are added to this file as
    -  // the environment reflects on the window global scope for JsUnit.
    -  assertEquals(6, testCase.tests_.length);
    -
    -  testing = false;
    -}
    -
    -function testMockClock() {
    -  testing = true;
    -
    -  var env = new goog.labs.testing.Environment().withMockClock();
    -
    -  testCase.addNewTest('testThatThrowsEventually', function() {
    -    setTimeout(function() {
    -      throw new Error('LateErrorMessage');
    -    }, 200);
    -  });
    -
    -  testCase.runTests();
    -  assertTestFailure(testCase, 'testThatThrowsEventually', 'LateErrorMessage');
    -
    -  testing = false;
    -}
    -
    -function testMockControl() {
    -  testing = true;
    -
    -  var env = new goog.labs.testing.Environment().withMockControl();
    -  var test = env.mockControl.createFunctionMock('test');
    -
    -  testCase.addNewTest('testWithoutVerify', function() {
    -    test();
    -    env.mockControl.$replayAll();
    -    test();
    -  });
    -
    -  testCase.runTests();
    -  assertNull(env.mockClock);
    -
    -  testing = false;
    -}
    -
    -function testMock() {
    -  testing = true;
    -
    -  var env = new goog.labs.testing.Environment().withMockControl();
    -  var mock = env.mock({
    -    test: function() {}
    -  });
    -
    -  testCase.addNewTest('testMockCalled', function() {
    -    mock.test().$times(2);
    -
    -    env.mockControl.$replayAll();
    -    mock.test();
    -    mock.test();
    -    env.mockControl.verifyAll();
    -  });
    -
    -  testCase.runTests();
    -
    -  testing = false;
    -}
    -
    -function assertTestFailure(testCase, name, message) {
    -  assertContains(message, testCase.result_.resultsByName[name][0]);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/testing/environment_usage_test.js b/src/database/third_party/closure-library/closure/goog/labs/testing/environment_usage_test.js
    deleted file mode 100644
    index 443958ce18a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/testing/environment_usage_test.js
    +++ /dev/null
    @@ -1,45 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.labs.testing.environmentUsageTest');
    -goog.setTestOnly('goog.labs.testing.environmentUsageTest');
    -
    -goog.require('goog.labs.testing.Environment');
    -
    -var testing = false;
    -var env = new goog.labs.testing.Environment();
    -
    -function setUpPage() {
    -  assertFalse(testing);
    -}
    -
    -function setUp() {
    -  testing = true;
    -}
    -
    -function testOne() {
    -  assertTrue(testing);
    -}
    -
    -function testTwo() {
    -  assertTrue(testing);
    -}
    -
    -function tearDown() {
    -  testing = false;
    -}
    -
    -function tearDownPage() {
    -  assertFalse(testing);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/testing/logicmatcher.js b/src/database/third_party/closure-library/closure/goog/labs/testing/logicmatcher.js
    deleted file mode 100644
    index 09148e3c45a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/testing/logicmatcher.js
    +++ /dev/null
    @@ -1,212 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides the built-in logic matchers: anyOf, allOf, and isNot.
    - *
    - */
    -
    -
    -goog.provide('goog.labs.testing.AllOfMatcher');
    -goog.provide('goog.labs.testing.AnyOfMatcher');
    -goog.provide('goog.labs.testing.IsNotMatcher');
    -
    -
    -goog.require('goog.array');
    -goog.require('goog.labs.testing.Matcher');
    -
    -
    -
    -/**
    - * The AllOf matcher.
    - *
    - * @param {!Array<!goog.labs.testing.Matcher>} matchers Input matchers.
    - *
    - * @constructor
    - * @struct
    - * @implements {goog.labs.testing.Matcher}
    - * @final
    - */
    -goog.labs.testing.AllOfMatcher = function(matchers) {
    -  /**
    -   * @type {!Array<!goog.labs.testing.Matcher>}
    -   * @private
    -   */
    -  this.matchers_ = matchers;
    -};
    -
    -
    -/**
    - * Determines if all of the matchers match the input value.
    - *
    - * @override
    - */
    -goog.labs.testing.AllOfMatcher.prototype.matches = function(actualValue) {
    -  return goog.array.every(this.matchers_, function(matcher) {
    -    return matcher.matches(actualValue);
    -  });
    -};
    -
    -
    -/**
    - * Describes why the matcher failed. The returned string is a concatenation of
    - * all the failed matchers' error strings.
    - *
    - * @override
    - */
    -goog.labs.testing.AllOfMatcher.prototype.describe =
    -    function(actualValue) {
    -  // TODO(user) : Optimize this to remove duplication with matches ?
    -  var errorString = '';
    -  goog.array.forEach(this.matchers_, function(matcher) {
    -    if (!matcher.matches(actualValue)) {
    -      errorString += matcher.describe(actualValue) + '\n';
    -    }
    -  });
    -  return errorString;
    -};
    -
    -
    -
    -/**
    - * The AnyOf matcher.
    - *
    - * @param {!Array<!goog.labs.testing.Matcher>} matchers Input matchers.
    - *
    - * @constructor
    - * @struct
    - * @implements {goog.labs.testing.Matcher}
    - * @final
    - */
    -goog.labs.testing.AnyOfMatcher = function(matchers) {
    -  /**
    -   * @type {!Array<!goog.labs.testing.Matcher>}
    -   * @private
    -   */
    -  this.matchers_ = matchers;
    -};
    -
    -
    -/**
    - * Determines if any of the matchers matches the input value.
    - *
    - * @override
    - */
    -goog.labs.testing.AnyOfMatcher.prototype.matches = function(actualValue) {
    -  return goog.array.some(this.matchers_, function(matcher) {
    -    return matcher.matches(actualValue);
    -  });
    -};
    -
    -
    -/**
    - * Describes why the matcher failed.
    - *
    - * @override
    - */
    -goog.labs.testing.AnyOfMatcher.prototype.describe =
    -    function(actualValue) {
    -  // TODO(user) : Optimize this to remove duplication with matches ?
    -  var errorString = '';
    -  goog.array.forEach(this.matchers_, function(matcher) {
    -    if (!matcher.matches(actualValue)) {
    -      errorString += matcher.describe(actualValue) + '\n';
    -    }
    -  });
    -  return errorString;
    -};
    -
    -
    -
    -/**
    - * The IsNot matcher.
    - *
    - * @param {!goog.labs.testing.Matcher} matcher The matcher to negate.
    - *
    - * @constructor
    - * @struct
    - * @implements {goog.labs.testing.Matcher}
    - * @final
    - */
    -goog.labs.testing.IsNotMatcher = function(matcher) {
    -  /**
    -   * @type {!goog.labs.testing.Matcher}
    -   * @private
    -   */
    -  this.matcher_ = matcher;
    -};
    -
    -
    -/**
    - * Determines if the input value doesn't satisfy a matcher.
    - *
    - * @override
    - */
    -goog.labs.testing.IsNotMatcher.prototype.matches = function(actualValue) {
    -  return !this.matcher_.matches(actualValue);
    -};
    -
    -
    -/**
    - * Describes why the matcher failed.
    - *
    - * @override
    - */
    -goog.labs.testing.IsNotMatcher.prototype.describe =
    -    function(actualValue) {
    -  return 'The following is false: ' + this.matcher_.describe(actualValue);
    -};
    -
    -
    -/**
    - * Creates a matcher that will succeed only if all of the given matchers
    - * succeed.
    - *
    - * @param {...goog.labs.testing.Matcher} var_args The matchers to test
    - *     against.
    - *
    - * @return {!goog.labs.testing.AllOfMatcher} The AllOf matcher.
    - */
    -function allOf(var_args) {
    -  var matchers = goog.array.toArray(arguments);
    -  return new goog.labs.testing.AllOfMatcher(matchers);
    -}
    -
    -
    -/**
    - * Accepts a set of matchers and returns a matcher which matches
    - * values which satisfy the constraints of any of the given matchers.
    - *
    - * @param {...goog.labs.testing.Matcher} var_args The matchers to test
    - *     against.
    - *
    - * @return {!goog.labs.testing.AnyOfMatcher} The AnyOf matcher.
    - */
    -function anyOf(var_args) {
    -  var matchers = goog.array.toArray(arguments);
    -  return new goog.labs.testing.AnyOfMatcher(matchers);
    -}
    -
    -
    -/**
    - * Returns a matcher that negates the input matcher. The returned
    - * matcher matches the values not matched by the input matcher and vice-versa.
    - *
    - * @param {!goog.labs.testing.Matcher} matcher The matcher to test against.
    - *
    - * @return {!goog.labs.testing.IsNotMatcher} The IsNot matcher.
    - */
    -function isNot(matcher) {
    -  return new goog.labs.testing.IsNotMatcher(matcher);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/testing/logicmatcher_test.html b/src/database/third_party/closure-library/closure/goog/labs/testing/logicmatcher_test.html
    deleted file mode 100644
    index d760323d984..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/testing/logicmatcher_test.html
    +++ /dev/null
    @@ -1,21 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - Logic matchers
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.labs.testing.logicMatcherTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/testing/logicmatcher_test.js b/src/database/third_party/closure-library/closure/goog/labs/testing/logicmatcher_test.js
    deleted file mode 100644
    index 509338be490..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/testing/logicmatcher_test.js
    +++ /dev/null
    @@ -1,57 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.labs.testing.logicMatcherTest');
    -goog.setTestOnly('goog.labs.testing.logicMatcherTest');
    -
    -/** @suppress {extraRequire} */
    -goog.require('goog.labs.testing.AllOfMatcher');
    -/** @suppress {extraRequire} */
    -goog.require('goog.labs.testing.GreaterThanMatcher');
    -goog.require('goog.labs.testing.MatcherError');
    -goog.require('goog.labs.testing.assertThat');
    -goog.require('goog.testing.jsunit');
    -
    -function testAnyOf() {
    -  goog.labs.testing.assertThat(5, anyOf(greaterThan(4), lessThan(3)),
    -      '5 > 4 || 5 < 3');
    -  goog.labs.testing.assertThat(2, anyOf(greaterThan(4), lessThan(3)),
    -      '2 > 4 || 2 < 3');
    -
    -  assertMatcherError(function() {
    -    goog.labs.testing.assertThat(4, anyOf(greaterThan(5), lessThan(2)));
    -  }, 'anyOf should throw exception when it fails');
    -}
    -
    -function testAllOf() {
    -  goog.labs.testing.assertThat(5, allOf(greaterThan(4), lessThan(6)),
    -      '5 > 4 && 5 < 6');
    -
    -  assertMatcherError(function() {
    -    goog.labs.testing.assertThat(4, allOf(lessThan(5), lessThan(3)));
    -  }, 'allOf should throw exception when it fails');
    -}
    -
    -function testIsNot() {
    -  goog.labs.testing.assertThat(5, isNot(greaterThan(6)), '5 !> 6');
    -
    -  assertMatcherError(function() {
    -    goog.labs.testing.assertThat(4, isNot(greaterThan(3)));
    -  }, 'isNot should throw exception when it fails');
    -}
    -
    -function assertMatcherError(callable, errorString) {
    -  var e = assertThrows(errorString || 'callable throws exception', callable);
    -  assertTrue(e instanceof goog.labs.testing.MatcherError);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/testing/matcher.js b/src/database/third_party/closure-library/closure/goog/labs/testing/matcher.js
    deleted file mode 100644
    index f8dd211231b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/testing/matcher.js
    +++ /dev/null
    @@ -1,80 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides the base Matcher interface. User code should use the
    - * matchers through assertThat statements and not directly.
    - */
    -
    -
    -goog.provide('goog.labs.testing.Matcher');
    -
    -
    -
    -/**
    - * A matcher object to be used in assertThat statements.
    - * @interface
    - */
    -goog.labs.testing.Matcher = function() {};
    -
    -
    -/**
    - * Determines whether a value matches the constraints of the match.
    - *
    - * @param {*} value The object to match.
    - * @return {boolean} Whether the input value matches this matcher.
    - */
    -goog.labs.testing.Matcher.prototype.matches = function(value) {};
    -
    -
    -/**
    - * Describes why the matcher failed.
    - *
    - * @param {*} value The value that didn't match.
    - * @param {string=} opt_description A partial description to which the reason
    - *     will be appended.
    - *
    - * @return {string} Description of why the matcher failed.
    - */
    -goog.labs.testing.Matcher.prototype.describe =
    -    function(value, opt_description) {};
    -
    -
    -/**
    - * Generates a Matcher from the ‘matches’ and ‘describe’ functions passed in.
    - *
    - * @param {!Function} matchesFunction The ‘matches’ function.
    - * @param {Function=} opt_describeFunction The ‘describe’ function.
    - * @return {!Function} The custom matcher.
    - */
    -goog.labs.testing.Matcher.makeMatcher =
    -    function(matchesFunction, opt_describeFunction) {
    -
    -  /**
    -   * @constructor
    -   * @implements {goog.labs.testing.Matcher}
    -   * @final
    -   */
    -  var matcherConstructor = function() {};
    -
    -  /** @override */
    -  matcherConstructor.prototype.matches = matchesFunction;
    -
    -  if (opt_describeFunction) {
    -    /** @override */
    -    matcherConstructor.prototype.describe = opt_describeFunction;
    -  }
    -
    -  return matcherConstructor;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/testing/numbermatcher.js b/src/database/third_party/closure-library/closure/goog/labs/testing/numbermatcher.js
    deleted file mode 100644
    index d9c67b339ed..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/testing/numbermatcher.js
    +++ /dev/null
    @@ -1,346 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides the built-in number matchers like lessThan,
    - * greaterThan, etc.
    - */
    -
    -
    -goog.provide('goog.labs.testing.CloseToMatcher');
    -goog.provide('goog.labs.testing.EqualToMatcher');
    -goog.provide('goog.labs.testing.GreaterThanEqualToMatcher');
    -goog.provide('goog.labs.testing.GreaterThanMatcher');
    -goog.provide('goog.labs.testing.LessThanEqualToMatcher');
    -goog.provide('goog.labs.testing.LessThanMatcher');
    -
    -
    -goog.require('goog.asserts');
    -goog.require('goog.labs.testing.Matcher');
    -
    -
    -
    -/**
    - * The GreaterThan matcher.
    - *
    - * @param {number} value The value to compare.
    - *
    - * @constructor
    - * @struct
    - * @implements {goog.labs.testing.Matcher}
    - * @final
    - */
    -goog.labs.testing.GreaterThanMatcher = function(value) {
    -  /**
    -   * @type {number}
    -   * @private
    -   */
    -  this.value_ = value;
    -};
    -
    -
    -/**
    - * Determines if input value is greater than the expected value.
    - *
    - * @override
    - */
    -goog.labs.testing.GreaterThanMatcher.prototype.matches = function(actualValue) {
    -  goog.asserts.assertNumber(actualValue);
    -  return actualValue > this.value_;
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.labs.testing.GreaterThanMatcher.prototype.describe =
    -    function(actualValue) {
    -  goog.asserts.assertNumber(actualValue);
    -  return actualValue + ' is not greater than ' + this.value_;
    -};
    -
    -
    -
    -/**
    - * The lessThan matcher.
    - *
    - * @param {number} value The value to compare.
    - *
    - * @constructor
    - * @struct
    - * @implements {goog.labs.testing.Matcher}
    - * @final
    - */
    -goog.labs.testing.LessThanMatcher = function(value) {
    -  /**
    -   * @type {number}
    -   * @private
    -   */
    -  this.value_ = value;
    -};
    -
    -
    -/**
    - * Determines if the input value is less than the expected value.
    - *
    - * @override
    - */
    -goog.labs.testing.LessThanMatcher.prototype.matches = function(actualValue) {
    -  goog.asserts.assertNumber(actualValue);
    -  return actualValue < this.value_;
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.labs.testing.LessThanMatcher.prototype.describe =
    -    function(actualValue) {
    -  goog.asserts.assertNumber(actualValue);
    -  return actualValue + ' is not less than ' + this.value_;
    -};
    -
    -
    -
    -/**
    - * The GreaterThanEqualTo matcher.
    - *
    - * @param {number} value The value to compare.
    - *
    - * @constructor
    - * @struct
    - * @implements {goog.labs.testing.Matcher}
    - * @final
    - */
    -goog.labs.testing.GreaterThanEqualToMatcher = function(value) {
    -  /**
    -   * @type {number}
    -   * @private
    -   */
    -  this.value_ = value;
    -};
    -
    -
    -/**
    - * Determines if the input value is greater than equal to the expected value.
    - *
    - * @override
    - */
    -goog.labs.testing.GreaterThanEqualToMatcher.prototype.matches =
    -    function(actualValue) {
    -  goog.asserts.assertNumber(actualValue);
    -  return actualValue >= this.value_;
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.labs.testing.GreaterThanEqualToMatcher.prototype.describe =
    -    function(actualValue) {
    -  goog.asserts.assertNumber(actualValue);
    -  return actualValue + ' is not greater than equal to ' + this.value_;
    -};
    -
    -
    -
    -/**
    - * The LessThanEqualTo matcher.
    - *
    - * @param {number} value The value to compare.
    - *
    - * @constructor
    - * @struct
    - * @implements {goog.labs.testing.Matcher}
    - * @final
    - */
    -goog.labs.testing.LessThanEqualToMatcher = function(value) {
    -  /**
    -   * @type {number}
    -   * @private
    -   */
    -  this.value_ = value;
    -};
    -
    -
    -/**
    - * Determines if the input value is less than or equal to the expected value.
    - *
    - * @override
    - */
    -goog.labs.testing.LessThanEqualToMatcher.prototype.matches =
    -    function(actualValue) {
    -  goog.asserts.assertNumber(actualValue);
    -  return actualValue <= this.value_;
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.labs.testing.LessThanEqualToMatcher.prototype.describe =
    -    function(actualValue) {
    -  goog.asserts.assertNumber(actualValue);
    -  return actualValue + ' is not less than equal to ' + this.value_;
    -};
    -
    -
    -
    -/**
    - * The EqualTo matcher.
    - *
    - * @param {number} value The value to compare.
    - *
    - * @constructor
    - * @struct
    - * @implements {goog.labs.testing.Matcher}
    - * @final
    - */
    -goog.labs.testing.EqualToMatcher = function(value) {
    -  /**
    -   * @type {number}
    -   * @private
    -   */
    -  this.value_ = value;
    -};
    -
    -
    -/**
    - * Determines if the input value is equal to the expected value.
    - *
    - * @override
    - */
    -goog.labs.testing.EqualToMatcher.prototype.matches = function(actualValue) {
    -  goog.asserts.assertNumber(actualValue);
    -  return actualValue === this.value_;
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.labs.testing.EqualToMatcher.prototype.describe =
    -    function(actualValue) {
    -  goog.asserts.assertNumber(actualValue);
    -  return actualValue + ' is not equal to ' + this.value_;
    -};
    -
    -
    -
    -/**
    - * The CloseTo matcher.
    - *
    - * @param {number} value The value to compare.
    - * @param {number} range The range to check within.
    - *
    - * @constructor
    - * @struct
    - * @implements {goog.labs.testing.Matcher}
    - * @final
    - */
    -goog.labs.testing.CloseToMatcher = function(value, range) {
    -  /**
    -   * @type {number}
    -   * @private
    -   */
    -  this.value_ = value;
    -  /**
    -   * @type {number}
    -   * @private
    -   */
    -  this.range_ = range;
    -};
    -
    -
    -/**
    - * Determines if input value is within a certain range of the expected value.
    - *
    - * @override
    - */
    -goog.labs.testing.CloseToMatcher.prototype.matches = function(actualValue) {
    -  goog.asserts.assertNumber(actualValue);
    -  return Math.abs(this.value_ - actualValue) < this.range_;
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.labs.testing.CloseToMatcher.prototype.describe =
    -    function(actualValue) {
    -  goog.asserts.assertNumber(actualValue);
    -  return actualValue + ' is not close to(' + this.range_ + ') ' + this.value_;
    -};
    -
    -
    -/**
    - * @param {number} value The expected value.
    - *
    - * @return {!goog.labs.testing.GreaterThanMatcher} A GreaterThanMatcher.
    - */
    -function greaterThan(value) {
    -  return new goog.labs.testing.GreaterThanMatcher(value);
    -}
    -
    -
    -/**
    - * @param {number} value The expected value.
    - *
    - * @return {!goog.labs.testing.GreaterThanEqualToMatcher} A
    - *     GreaterThanEqualToMatcher.
    - */
    -function greaterThanEqualTo(value) {
    -  return new goog.labs.testing.GreaterThanEqualToMatcher(value);
    -}
    -
    -
    -/**
    - * @param {number} value The expected value.
    - *
    - * @return {!goog.labs.testing.LessThanMatcher} A LessThanMatcher.
    - */
    -function lessThan(value) {
    -  return new goog.labs.testing.LessThanMatcher(value);
    -}
    -
    -
    -/**
    - * @param {number} value The expected value.
    - *
    - * @return {!goog.labs.testing.LessThanEqualToMatcher} A LessThanEqualToMatcher.
    - */
    -function lessThanEqualTo(value) {
    -  return new goog.labs.testing.LessThanEqualToMatcher(value);
    -}
    -
    -
    -/**
    - * @param {number} value The expected value.
    - *
    - * @return {!goog.labs.testing.EqualToMatcher} An EqualToMatcher.
    - */
    -function equalTo(value) {
    -  return new goog.labs.testing.EqualToMatcher(value);
    -}
    -
    -
    -/**
    - * @param {number} value The expected value.
    - * @param {number} range The maximum allowed difference from the expected value.
    - *
    - * @return {!goog.labs.testing.CloseToMatcher} A CloseToMatcher.
    - */
    -function closeTo(value, range) {
    -  return new goog.labs.testing.CloseToMatcher(value, range);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/testing/numbermatcher_test.html b/src/database/third_party/closure-library/closure/goog/labs/testing/numbermatcher_test.html
    deleted file mode 100644
    index b1ec361fc03..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/testing/numbermatcher_test.html
    +++ /dev/null
    @@ -1,21 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - Number matchers
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.labs.testing.numberMatcherTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/testing/numbermatcher_test.js b/src/database/third_party/closure-library/closure/goog/labs/testing/numbermatcher_test.js
    deleted file mode 100644
    index 4365b18e6a9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/testing/numbermatcher_test.js
    +++ /dev/null
    @@ -1,71 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.labs.testing.numberMatcherTest');
    -goog.setTestOnly('goog.labs.testing.numberMatcherTest');
    -
    -/** @suppress {extraRequire} */
    -goog.require('goog.labs.testing.LessThanMatcher');
    -goog.require('goog.labs.testing.MatcherError');
    -goog.require('goog.labs.testing.assertThat');
    -goog.require('goog.testing.jsunit');
    -
    -function testGreaterThan() {
    -  goog.labs.testing.assertThat(4, greaterThan(3), '4 > 3');
    -  assertMatcherError(function() {
    -    goog.labs.testing.assertThat(2, greaterThan(3));
    -  }, '2 > 3');
    -}
    -
    -function testGreaterThanEqualTo() {
    -  goog.labs.testing.assertThat(5, greaterThanEqualTo(4), '5 >= 4');
    -  goog.labs.testing.assertThat(5, greaterThanEqualTo(5), '5 >= 5');
    -  assertMatcherError(function() {
    -    goog.labs.testing.assertThat(3, greaterThanEqualTo(5));
    -  }, '3 >= 5');
    -}
    -
    -function testLessThan() {
    -  goog.labs.testing.assertThat(6, lessThan(7), '6 < 7');
    -  assertMatcherError(function() {
    -    goog.labs.testing.assertThat(7, lessThan(5));
    -  }, '7 < 5');
    -}
    -
    -function testLessThanEqualTo() {
    -  goog.labs.testing.assertThat(8, lessThanEqualTo(8), '8 <= 8');
    -  goog.labs.testing.assertThat(8, lessThanEqualTo(9), '8 <= 9');
    -  assertMatcherError(function() {
    -    goog.labs.testing.assertThat(7, lessThanEqualTo(5));
    -  }, '7 <= 5');
    -}
    -
    -function testEqualTo() {
    -  goog.labs.testing.assertThat(7, equalTo(7), '7 equals 7');
    -  assertMatcherError(function() {
    -    goog.labs.testing.assertThat(7, equalTo(5));
    -  }, '7 == 5');
    -}
    -
    -function testCloseTo() {
    -  goog.labs.testing.assertThat(7, closeTo(10, 4), '7 within range(4) of 10');
    -  assertMatcherError(function() {
    -    goog.labs.testing.assertThat(5, closeTo(10, 3));
    -  }, '5 within range(3) of 10');
    -}
    -
    -function assertMatcherError(callable, errorString) {
    -  var e = assertThrows(errorString || 'callable throws exception', callable);
    -  assertTrue(e instanceof goog.labs.testing.MatcherError);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/testing/objectmatcher.js b/src/database/third_party/closure-library/closure/goog/labs/testing/objectmatcher.js
    deleted file mode 100644
    index a9474fe6d2b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/testing/objectmatcher.js
    +++ /dev/null
    @@ -1,317 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides the built-in object matchers like equalsObject,
    - *     hasProperty, instanceOf, etc.
    - */
    -
    -
    -
    -goog.provide('goog.labs.testing.HasPropertyMatcher');
    -goog.provide('goog.labs.testing.InstanceOfMatcher');
    -goog.provide('goog.labs.testing.IsNullMatcher');
    -goog.provide('goog.labs.testing.IsNullOrUndefinedMatcher');
    -goog.provide('goog.labs.testing.IsUndefinedMatcher');
    -goog.provide('goog.labs.testing.ObjectEqualsMatcher');
    -
    -
    -goog.require('goog.labs.testing.Matcher');
    -
    -
    -
    -/**
    - * The Equals matcher.
    - *
    - * @param {!Object} expectedObject The expected object.
    - *
    - * @constructor
    - * @struct
    - * @implements {goog.labs.testing.Matcher}
    - * @final
    - */
    -goog.labs.testing.ObjectEqualsMatcher = function(expectedObject) {
    -  /**
    -   * @type {!Object}
    -   * @private
    -   */
    -  this.object_ = expectedObject;
    -};
    -
    -
    -/**
    - * Determines if two objects are the same.
    - *
    - * @override
    - */
    -goog.labs.testing.ObjectEqualsMatcher.prototype.matches =
    -    function(actualObject) {
    -  return actualObject === this.object_;
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.labs.testing.ObjectEqualsMatcher.prototype.describe =
    -    function(actualObject) {
    -  return 'Input object is not the same as the expected object.';
    -};
    -
    -
    -
    -/**
    - * The HasProperty matcher.
    - *
    - * @param {string} property Name of the property to test.
    - *
    - * @constructor
    - * @struct
    - * @implements {goog.labs.testing.Matcher}
    - * @final
    - */
    -goog.labs.testing.HasPropertyMatcher = function(property) {
    -  /**
    -   * @type {string}
    -   * @private
    -   */
    -  this.property_ = property;
    -};
    -
    -
    -/**
    - * Determines if an object has a property.
    - *
    - * @override
    - */
    -goog.labs.testing.HasPropertyMatcher.prototype.matches =
    -    function(actualObject) {
    -  return this.property_ in actualObject;
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.labs.testing.HasPropertyMatcher.prototype.describe =
    -    function(actualObject) {
    -  return 'Object does not have property: ' + this.property_;
    -};
    -
    -
    -
    -/**
    - * The InstanceOf matcher.
    - *
    - * @param {!Object} object The expected class object.
    - *
    - * @constructor
    - * @struct
    - * @implements {goog.labs.testing.Matcher}
    - * @final
    - */
    -goog.labs.testing.InstanceOfMatcher = function(object) {
    -  /**
    -   * @type {!Object}
    -   * @private
    -   */
    -  this.object_ = object;
    -};
    -
    -
    -/**
    - * Determines if an object is an instance of another object.
    - *
    - * @override
    - */
    -goog.labs.testing.InstanceOfMatcher.prototype.matches =
    -    function(actualObject) {
    -  return actualObject instanceof this.object_;
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.labs.testing.InstanceOfMatcher.prototype.describe =
    -    function(actualObject) {
    -  return 'Input object is not an instance of the expected object';
    -};
    -
    -
    -
    -/**
    - * The IsNullOrUndefined matcher.
    - *
    - * @constructor
    - * @struct
    - * @implements {goog.labs.testing.Matcher}
    - * @final
    - */
    -goog.labs.testing.IsNullOrUndefinedMatcher = function() {};
    -
    -
    -/**
    - * Determines if input value is null or undefined.
    - *
    - * @override
    - */
    -goog.labs.testing.IsNullOrUndefinedMatcher.prototype.matches =
    -    function(actualValue) {
    -  return !goog.isDefAndNotNull(actualValue);
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.labs.testing.IsNullOrUndefinedMatcher.prototype.describe =
    -    function(actualValue) {
    -  return actualValue + ' is not null or undefined.';
    -};
    -
    -
    -
    -/**
    - * The IsNull matcher.
    - *
    - * @constructor
    - * @struct
    - * @implements {goog.labs.testing.Matcher}
    - * @final
    - */
    -goog.labs.testing.IsNullMatcher = function() {};
    -
    -
    -/**
    - * Determines if input value is null.
    - *
    - * @override
    - */
    -goog.labs.testing.IsNullMatcher.prototype.matches =
    -    function(actualValue) {
    -  return goog.isNull(actualValue);
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.labs.testing.IsNullMatcher.prototype.describe =
    -    function(actualValue) {
    -  return actualValue + ' is not null.';
    -};
    -
    -
    -
    -/**
    - * The IsUndefined matcher.
    - *
    - * @constructor
    - * @struct
    - * @implements {goog.labs.testing.Matcher}
    - * @final
    - */
    -goog.labs.testing.IsUndefinedMatcher = function() {};
    -
    -
    -/**
    - * Determines if input value is undefined.
    - *
    - * @override
    - */
    -goog.labs.testing.IsUndefinedMatcher.prototype.matches =
    -    function(actualValue) {
    -  return !goog.isDef(actualValue);
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.labs.testing.IsUndefinedMatcher.prototype.describe =
    -    function(actualValue) {
    -  return actualValue + ' is not undefined.';
    -};
    -
    -
    -/**
    - * Returns a matcher that matches objects that are equal to the input object.
    - * Equality in this case means the two objects are references to the same
    - * object.
    - *
    - * @param {!Object} object The expected object.
    - *
    - * @return {!goog.labs.testing.ObjectEqualsMatcher} A
    - *     ObjectEqualsMatcher.
    - */
    -function equalsObject(object) {
    -  return new goog.labs.testing.ObjectEqualsMatcher(object);
    -}
    -
    -
    -/**
    - * Returns a matcher that matches objects that contain the input property.
    - *
    - * @param {string} property The property name to check.
    - *
    - * @return {!goog.labs.testing.HasPropertyMatcher} A HasPropertyMatcher.
    - */
    -function hasProperty(property) {
    -  return new goog.labs.testing.HasPropertyMatcher(property);
    -}
    -
    -
    -/**
    - * Returns a matcher that matches instances of the input class.
    - *
    - * @param {!Object} object The class object.
    - *
    - * @return {!goog.labs.testing.InstanceOfMatcher} A
    - *     InstanceOfMatcher.
    - */
    -function instanceOfClass(object) {
    -  return new goog.labs.testing.InstanceOfMatcher(object);
    -}
    -
    -
    -/**
    - * Returns a matcher that matches all null values.
    - *
    - * @return {!goog.labs.testing.IsNullMatcher} A IsNullMatcher.
    - */
    -function isNull() {
    -  return new goog.labs.testing.IsNullMatcher();
    -}
    -
    -
    -/**
    - * Returns a matcher that matches all null and undefined values.
    - *
    - * @return {!goog.labs.testing.IsNullOrUndefinedMatcher} A
    - *     IsNullOrUndefinedMatcher.
    - */
    -function isNullOrUndefined() {
    -  return new goog.labs.testing.IsNullOrUndefinedMatcher();
    -}
    -
    -
    -/**
    - * Returns a matcher that matches undefined values.
    - *
    - * @return {!goog.labs.testing.IsUndefinedMatcher} A IsUndefinedMatcher.
    - */
    -function isUndefined() {
    -  return new goog.labs.testing.IsUndefinedMatcher();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/testing/objectmatcher_test.html b/src/database/third_party/closure-library/closure/goog/labs/testing/objectmatcher_test.html
    deleted file mode 100644
    index d21e2a12e4d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/testing/objectmatcher_test.html
    +++ /dev/null
    @@ -1,21 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - Object matchers
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.labs.testing.objectMatcherTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/testing/objectmatcher_test.js b/src/database/third_party/closure-library/closure/goog/labs/testing/objectmatcher_test.js
    deleted file mode 100644
    index 3781dfbb086..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/testing/objectmatcher_test.js
    +++ /dev/null
    @@ -1,95 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.labs.testing.objectMatcherTest');
    -goog.setTestOnly('goog.labs.testing.objectMatcherTest');
    -
    -goog.require('goog.labs.testing.MatcherError');
    -/** @suppress {extraRequire} */
    -goog.require('goog.labs.testing.ObjectEqualsMatcher');
    -goog.require('goog.labs.testing.assertThat');
    -goog.require('goog.testing.jsunit');
    -
    -function testObjectEquals() {
    -  var obj1 = {x: 1};
    -  var obj2 = obj1;
    -  goog.labs.testing.assertThat(obj1, equalsObject(obj2), 'obj1 equals obj2');
    -
    -  assertMatcherError(function() {
    -    goog.labs.testing.assertThat({x: 1}, equalsObject({}));
    -  }, 'equalsObject does not throw exception on failure');
    -}
    -
    -function testInstanceOf() {
    -  function expected() {
    -    this.x = 1;
    -  }
    -  var input = new expected();
    -  goog.labs.testing.assertThat(input, instanceOfClass(expected),
    -      'input is an instance of expected');
    -
    -  assertMatcherError(function() {
    -    goog.labs.testing.assertThat(5, instanceOfClass(function() {}));
    -  }, 'instanceOfClass does not throw exception on failure');
    -}
    -
    -function testHasProperty() {
    -  goog.labs.testing.assertThat({x: 1}, hasProperty('x'),
    -      '{x:1} has property x}');
    -
    -  assertMatcherError(function() {
    -    goog.labs.testing.assertThat({x: 1}, hasProperty('y'));
    -  }, 'hasProperty does not throw exception on failure');
    -}
    -
    -function testIsNull() {
    -  goog.labs.testing.assertThat(null, isNull(), 'null is null');
    -
    -  assertMatcherError(function() {
    -    goog.labs.testing.assertThat(5, isNull());
    -  }, 'isNull does not throw exception on failure');
    -}
    -
    -function testIsNullOrUndefined() {
    -  var x;
    -  goog.labs.testing.assertThat(undefined, isNullOrUndefined(),
    -      'undefined is null or undefined');
    -  goog.labs.testing.assertThat(x, isNullOrUndefined(),
    -      'undefined is null or undefined');
    -  x = null;
    -  goog.labs.testing.assertThat(null, isNullOrUndefined(),
    -      'null is null or undefined');
    -  goog.labs.testing.assertThat(x, isNullOrUndefined(),
    -      'null is null or undefined');
    -
    -  assertMatcherError(function() {
    -    goog.labs.testing.assertThat(5, isNullOrUndefined());
    -  }, 'isNullOrUndefined does not throw exception on failure');
    -}
    -
    -function testIsUndefined() {
    -  var x;
    -  goog.labs.testing.assertThat(undefined, isUndefined(),
    -      'undefined is undefined');
    -  goog.labs.testing.assertThat(x, isUndefined(), 'undefined is undefined');
    -
    -  assertMatcherError(function() {
    -    goog.labs.testing.assertThat(5, isUndefined());
    -  }, 'isUndefined does not throw exception on failure');
    -}
    -
    -function assertMatcherError(callable, errorString) {
    -  var e = assertThrows(errorString || 'callable throws exception', callable);
    -  assertTrue(e instanceof goog.labs.testing.MatcherError);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/testing/stringmatcher.js b/src/database/third_party/closure-library/closure/goog/labs/testing/stringmatcher.js
    deleted file mode 100644
    index 2cc5b67ba6e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/testing/stringmatcher.js
    +++ /dev/null
    @@ -1,415 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides the built-in string matchers like containsString,
    - *     startsWith, endsWith, etc.
    - */
    -
    -
    -goog.provide('goog.labs.testing.ContainsStringMatcher');
    -goog.provide('goog.labs.testing.EndsWithMatcher');
    -goog.provide('goog.labs.testing.EqualToIgnoringWhitespaceMatcher');
    -goog.provide('goog.labs.testing.EqualsMatcher');
    -goog.provide('goog.labs.testing.RegexMatcher');
    -goog.provide('goog.labs.testing.StartsWithMatcher');
    -goog.provide('goog.labs.testing.StringContainsInOrderMatcher');
    -
    -
    -goog.require('goog.asserts');
    -goog.require('goog.labs.testing.Matcher');
    -goog.require('goog.string');
    -
    -
    -
    -/**
    - * The ContainsString matcher.
    - *
    - * @param {string} value The expected string.
    - *
    - * @constructor
    - * @struct
    - * @implements {goog.labs.testing.Matcher}
    - * @final
    - */
    -goog.labs.testing.ContainsStringMatcher = function(value) {
    -  /**
    -   * @type {string}
    -   * @private
    -   */
    -  this.value_ = value;
    -};
    -
    -
    -/**
    - * Determines if input string contains the expected string.
    - *
    - * @override
    - */
    -goog.labs.testing.ContainsStringMatcher.prototype.matches =
    -    function(actualValue) {
    -  goog.asserts.assertString(actualValue);
    -  return goog.string.contains(actualValue, this.value_);
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.labs.testing.ContainsStringMatcher.prototype.describe =
    -    function(actualValue) {
    -  return actualValue + ' does not contain ' + this.value_;
    -};
    -
    -
    -
    -/**
    - * The EndsWith matcher.
    - *
    - * @param {string} value The expected string.
    - *
    - * @constructor
    - * @struct
    - * @implements {goog.labs.testing.Matcher}
    - * @final
    - */
    -goog.labs.testing.EndsWithMatcher = function(value) {
    -  /**
    -   * @type {string}
    -   * @private
    -   */
    -  this.value_ = value;
    -};
    -
    -
    -/**
    - * Determines if input string ends with the expected string.
    - *
    - * @override
    - */
    -goog.labs.testing.EndsWithMatcher.prototype.matches = function(actualValue) {
    -  goog.asserts.assertString(actualValue);
    -  return goog.string.endsWith(actualValue, this.value_);
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.labs.testing.EndsWithMatcher.prototype.describe =
    -    function(actualValue) {
    -  return actualValue + ' does not end with ' + this.value_;
    -};
    -
    -
    -
    -/**
    - * The EqualToIgnoringWhitespace matcher.
    - *
    - * @param {string} value The expected string.
    - *
    - * @constructor
    - * @struct
    - * @implements {goog.labs.testing.Matcher}
    - * @final
    - */
    -goog.labs.testing.EqualToIgnoringWhitespaceMatcher = function(value) {
    -  /**
    -   * @type {string}
    -   * @private
    -   */
    -  this.value_ = value;
    -};
    -
    -
    -/**
    - * Determines if input string contains the expected string.
    - *
    - * @override
    - */
    -goog.labs.testing.EqualToIgnoringWhitespaceMatcher.prototype.matches =
    -    function(actualValue) {
    -  goog.asserts.assertString(actualValue);
    -  var string1 = goog.string.collapseWhitespace(actualValue);
    -
    -  return goog.string.caseInsensitiveCompare(this.value_, string1) === 0;
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.labs.testing.EqualToIgnoringWhitespaceMatcher.prototype.describe =
    -    function(actualValue) {
    -  return actualValue + ' is not equal(ignoring whitespace) to ' + this.value_;
    -};
    -
    -
    -
    -/**
    - * The Equals matcher.
    - *
    - * @param {string} value The expected string.
    - *
    - * @constructor
    - * @struct
    - * @implements {goog.labs.testing.Matcher}
    - * @final
    - */
    -goog.labs.testing.EqualsMatcher = function(value) {
    -  /**
    -   * @type {string}
    -   * @private
    -   */
    -  this.value_ = value;
    -};
    -
    -
    -/**
    - * Determines if input string is equal to the expected string.
    - *
    - * @override
    - */
    -goog.labs.testing.EqualsMatcher.prototype.matches = function(actualValue) {
    -  goog.asserts.assertString(actualValue);
    -  return this.value_ === actualValue;
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.labs.testing.EqualsMatcher.prototype.describe =
    -    function(actualValue) {
    -  return actualValue + ' is not equal to ' + this.value_;
    -};
    -
    -
    -
    -/**
    - * The MatchesRegex matcher.
    - *
    - * @param {!RegExp} regex The expected regex.
    - *
    - * @constructor
    - * @struct
    - * @implements {goog.labs.testing.Matcher}
    - * @final
    - */
    -goog.labs.testing.RegexMatcher = function(regex) {
    -  /**
    -   * @type {!RegExp}
    -   * @private
    -   */
    -  this.regex_ = regex;
    -};
    -
    -
    -/**
    - * Determines if input string is equal to the expected string.
    - *
    - * @override
    - */
    -goog.labs.testing.RegexMatcher.prototype.matches = function(
    -    actualValue) {
    -  goog.asserts.assertString(actualValue);
    -  return this.regex_.test(actualValue);
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.labs.testing.RegexMatcher.prototype.describe =
    -    function(actualValue) {
    -  return actualValue + ' does not match ' + this.regex_;
    -};
    -
    -
    -
    -/**
    - * The StartsWith matcher.
    - *
    - * @param {string} value The expected string.
    - *
    - * @constructor
    - * @struct
    - * @implements {goog.labs.testing.Matcher}
    - * @final
    - */
    -goog.labs.testing.StartsWithMatcher = function(value) {
    -  /**
    -   * @type {string}
    -   * @private
    -   */
    -  this.value_ = value;
    -};
    -
    -
    -/**
    - * Determines if input string starts with the expected string.
    - *
    - * @override
    - */
    -goog.labs.testing.StartsWithMatcher.prototype.matches = function(actualValue) {
    -  goog.asserts.assertString(actualValue);
    -  return goog.string.startsWith(actualValue, this.value_);
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.labs.testing.StartsWithMatcher.prototype.describe =
    -    function(actualValue) {
    -  return actualValue + ' does not start with ' + this.value_;
    -};
    -
    -
    -
    -/**
    - * The StringContainsInOrdermatcher.
    - *
    - * @param {Array<string>} values The expected string values.
    - *
    - * @constructor
    - * @struct
    - * @implements {goog.labs.testing.Matcher}
    - * @final
    - */
    -goog.labs.testing.StringContainsInOrderMatcher = function(values) {
    -  /**
    -   * @type {Array<string>}
    -   * @private
    -   */
    -  this.values_ = values;
    -};
    -
    -
    -/**
    - * Determines if input string contains, in order, the expected array of strings.
    - *
    - * @override
    - */
    -goog.labs.testing.StringContainsInOrderMatcher.prototype.matches =
    -    function(actualValue) {
    -  goog.asserts.assertString(actualValue);
    -  var currentIndex, previousIndex = 0;
    -  for (var i = 0; i < this.values_.length; i++) {
    -    currentIndex = goog.string.contains(actualValue, this.values_[i]);
    -    if (currentIndex < 0 || currentIndex < previousIndex) {
    -      return false;
    -    }
    -    previousIndex = currentIndex;
    -  }
    -  return true;
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.labs.testing.StringContainsInOrderMatcher.prototype.describe =
    -    function(actualValue) {
    -  return actualValue + ' does not contain the expected values in order.';
    -};
    -
    -
    -/**
    - * Matches a string containing the given string.
    - *
    - * @param {string} value The expected value.
    - *
    - * @return {!goog.labs.testing.ContainsStringMatcher} A
    - *     ContainsStringMatcher.
    - */
    -function containsString(value) {
    -  return new goog.labs.testing.ContainsStringMatcher(value);
    -}
    -
    -
    -/**
    - * Matches a string that ends with the given string.
    - *
    - * @param {string} value The expected value.
    - *
    - * @return {!goog.labs.testing.EndsWithMatcher} A
    - *     EndsWithMatcher.
    - */
    -function endsWith(value) {
    -  return new goog.labs.testing.EndsWithMatcher(value);
    -}
    -
    -
    -/**
    - * Matches a string that equals (ignoring whitespace) the given string.
    - *
    - * @param {string} value The expected value.
    - *
    - * @return {!goog.labs.testing.EqualToIgnoringWhitespaceMatcher} A
    - *     EqualToIgnoringWhitespaceMatcher.
    - */
    -function equalToIgnoringWhitespace(value) {
    -  return new goog.labs.testing.EqualToIgnoringWhitespaceMatcher(value);
    -}
    -
    -
    -/**
    - * Matches a string that equals the given string.
    - *
    - * @param {string} value The expected value.
    - *
    - * @return {!goog.labs.testing.EqualsMatcher} A EqualsMatcher.
    - */
    -function equals(value) {
    -  return new goog.labs.testing.EqualsMatcher(value);
    -}
    -
    -
    -/**
    - * Matches a string against a regular expression.
    - *
    - * @param {!RegExp} regex The expected regex.
    - *
    - * @return {!goog.labs.testing.RegexMatcher} A RegexMatcher.
    - */
    -function matchesRegex(regex) {
    -  return new goog.labs.testing.RegexMatcher(regex);
    -}
    -
    -
    -/**
    - * Matches a string that starts with the given string.
    - *
    - * @param {string} value The expected value.
    - *
    - * @return {!goog.labs.testing.StartsWithMatcher} A
    - *     StartsWithMatcher.
    - */
    -function startsWith(value) {
    -  return new goog.labs.testing.StartsWithMatcher(value);
    -}
    -
    -
    -/**
    - * Matches a string that contains the given strings in order.
    - *
    - * @param {Array<string>} values The expected value.
    - *
    - * @return {!goog.labs.testing.StringContainsInOrderMatcher} A
    - *     StringContainsInOrderMatcher.
    - */
    -function stringContainsInOrder(values) {
    -  return new goog.labs.testing.StringContainsInOrderMatcher(values);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/testing/stringmatcher_test.html b/src/database/third_party/closure-library/closure/goog/labs/testing/stringmatcher_test.html
    deleted file mode 100644
    index 2fd5b5532f2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/testing/stringmatcher_test.html
    +++ /dev/null
    @@ -1,21 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - String matchers
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.labs.testing.stringMatcherTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/testing/stringmatcher_test.js b/src/database/third_party/closure-library/closure/goog/labs/testing/stringmatcher_test.js
    deleted file mode 100644
    index b4692bb4311..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/testing/stringmatcher_test.js
    +++ /dev/null
    @@ -1,92 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.labs.testing.stringMatcherTest');
    -goog.setTestOnly('goog.labs.testing.stringMatcherTest');
    -
    -goog.require('goog.labs.testing.MatcherError');
    -/** @suppress {extraRequire} */
    -goog.require('goog.labs.testing.StringContainsInOrderMatcher');
    -goog.require('goog.labs.testing.assertThat');
    -goog.require('goog.testing.jsunit');
    -
    -function testContainsString() {
    -  goog.labs.testing.assertThat('hello', containsString('ell'),
    -      'hello contains ell');
    -
    -  assertMatcherError(function() {
    -    goog.labs.testing.assertThat('hello', containsString('world!'));
    -  }, 'containsString should throw exception when it fails');
    -}
    -
    -function testEndsWith() {
    -  goog.labs.testing.assertThat('hello', endsWith('llo'), 'hello ends with llo');
    -
    -  assertMatcherError(function() {
    -    goog.labs.testing.assertThat('minutes', endsWith('midnight'));
    -  }, 'endsWith should throw exception when it fails');
    -}
    -
    -function testEqualToIgnoringWhitespace() {
    -  goog.labs.testing.assertThat('    h\n   EL L\tO',
    -      equalToIgnoringWhitespace('h el l o'),
    -      '"   h   EL L\tO   " is equal to "h el l o"');
    -
    -  assertMatcherError(function() {
    -    goog.labs.testing.assertThat('hybrid', equalToIgnoringWhitespace('theory'));
    -  }, 'equalToIgnoringWhitespace should throw exception when it fails');
    -}
    -
    -function testEquals() {
    -  goog.labs.testing.assertThat('hello', equals('hello'),
    -      'hello equals hello');
    -
    -  assertMatcherError(function() {
    -    goog.labs.testing.assertThat('thousand', equals('suns'));
    -  }, 'equals should throw exception when it fails');
    -}
    -
    -function testStartsWith() {
    -  goog.labs.testing.assertThat('hello', startsWith('hel'),
    -      'hello starts with hel');
    -
    -  assertMatcherError(function() {
    -    goog.labs.testing.assertThat('linkin', startsWith('park'));
    -  }, 'startsWith should throw exception when it fails');
    -}
    -
    -function testStringContainsInOrder() {
    -  goog.labs.testing.assertThat('hello',
    -      stringContainsInOrder(['h', 'el', 'el', 'l', 'o']),
    -      'hello contains in order: [h, el, l, o]');
    -
    -  assertMatcherError(function() {
    -    goog.labs.testing.assertThat('hybrid', stringContainsInOrder(['hy', 'brid',
    -      'theory']));
    -  }, 'stringContainsInOrder should throw exception when it fails');
    -}
    -
    -function testMatchesRegex() {
    -  goog.labs.testing.assertThat('foobar', matchesRegex(/foobar/));
    -  goog.labs.testing.assertThat('foobar', matchesRegex(/oobar/));
    -
    -  assertMatcherError(function() {
    -    goog.labs.testing.assertThat('foo', matchesRegex(/^foobar$/));
    -  }, 'matchesRegex should throw exception when it fails');
    -}
    -
    -function assertMatcherError(callable, errorString) {
    -  var e = assertThrows(errorString || 'callable throws exception', callable);
    -  assertTrue(e instanceof goog.labs.testing.MatcherError);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/useragent/browser.js b/src/database/third_party/closure-library/closure/goog/labs/useragent/browser.js
    deleted file mode 100644
    index 880eb4c04dd..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/useragent/browser.js
    +++ /dev/null
    @@ -1,319 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Closure user agent detection (Browser).
    - * @see <a href="http://www.useragentstring.com/">User agent strings</a>
    - * For more information on rendering engine, platform, or device see the other
    - * sub-namespaces in goog.labs.userAgent, goog.labs.userAgent.platform,
    - * goog.labs.userAgent.device respectively.)
    - *
    - * @author martone@google.com (Andy Martone)
    - */
    -
    -goog.provide('goog.labs.userAgent.browser');
    -
    -goog.require('goog.array');
    -goog.require('goog.labs.userAgent.util');
    -goog.require('goog.object');
    -goog.require('goog.string');
    -
    -
    -// TODO(nnaze): Refactor to remove excessive exclusion logic in matching
    -// functions.
    -
    -
    -/**
    - * @return {boolean} Whether the user's browser is Opera.
    - * @private
    - */
    -goog.labs.userAgent.browser.matchOpera_ = function() {
    -  return goog.labs.userAgent.util.matchUserAgent('Opera') ||
    -      goog.labs.userAgent.util.matchUserAgent('OPR');
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the user's browser is IE.
    - * @private
    - */
    -goog.labs.userAgent.browser.matchIE_ = function() {
    -  return goog.labs.userAgent.util.matchUserAgent('Trident') ||
    -      goog.labs.userAgent.util.matchUserAgent('MSIE');
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the user's browser is Firefox.
    - * @private
    - */
    -goog.labs.userAgent.browser.matchFirefox_ = function() {
    -  return goog.labs.userAgent.util.matchUserAgent('Firefox');
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the user's browser is Safari.
    - * @private
    - */
    -goog.labs.userAgent.browser.matchSafari_ = function() {
    -  return goog.labs.userAgent.util.matchUserAgent('Safari') &&
    -      !(goog.labs.userAgent.browser.matchChrome_() ||
    -        goog.labs.userAgent.browser.matchCoast_() ||
    -        goog.labs.userAgent.browser.matchOpera_() ||
    -        goog.labs.userAgent.browser.isSilk() ||
    -        goog.labs.userAgent.util.matchUserAgent('Android'));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the user's browser is Coast (Opera's Webkit-based
    - *     iOS browser).
    - * @private
    - */
    -goog.labs.userAgent.browser.matchCoast_ = function() {
    -  return goog.labs.userAgent.util.matchUserAgent('Coast');
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the user's browser is iOS Webview.
    - * @private
    - */
    -goog.labs.userAgent.browser.matchIosWebview_ = function() {
    -  // iOS Webview does not show up as Chrome or Safari. Also check for Opera's
    -  // WebKit-based iOS browser, Coast.
    -  return (goog.labs.userAgent.util.matchUserAgent('iPad') ||
    -          goog.labs.userAgent.util.matchUserAgent('iPhone')) &&
    -      !goog.labs.userAgent.browser.matchSafari_() &&
    -      !goog.labs.userAgent.browser.matchChrome_() &&
    -      !goog.labs.userAgent.browser.matchCoast_() &&
    -      goog.labs.userAgent.util.matchUserAgent('AppleWebKit');
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the user's browser is Chrome.
    - * @private
    - */
    -goog.labs.userAgent.browser.matchChrome_ = function() {
    -  return (goog.labs.userAgent.util.matchUserAgent('Chrome') ||
    -      goog.labs.userAgent.util.matchUserAgent('CriOS')) &&
    -      !goog.labs.userAgent.browser.matchOpera_();
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the user's browser is the Android browser.
    - * @private
    - */
    -goog.labs.userAgent.browser.matchAndroidBrowser_ = function() {
    -  // Android can appear in the user agent string for Chrome on Android.
    -  // This is not the Android standalone browser if it does.
    -  return goog.labs.userAgent.util.matchUserAgent('Android') &&
    -      !(goog.labs.userAgent.browser.isChrome() ||
    -        goog.labs.userAgent.browser.isFirefox() ||
    -        goog.labs.userAgent.browser.isOpera() ||
    -        goog.labs.userAgent.browser.isSilk());
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the user's browser is Opera.
    - */
    -goog.labs.userAgent.browser.isOpera = goog.labs.userAgent.browser.matchOpera_;
    -
    -
    -/**
    - * @return {boolean} Whether the user's browser is IE.
    - */
    -goog.labs.userAgent.browser.isIE = goog.labs.userAgent.browser.matchIE_;
    -
    -
    -/**
    - * @return {boolean} Whether the user's browser is Firefox.
    - */
    -goog.labs.userAgent.browser.isFirefox =
    -    goog.labs.userAgent.browser.matchFirefox_;
    -
    -
    -/**
    - * @return {boolean} Whether the user's browser is Safari.
    - */
    -goog.labs.userAgent.browser.isSafari =
    -    goog.labs.userAgent.browser.matchSafari_;
    -
    -
    -/**
    - * @return {boolean} Whether the user's browser is Coast (Opera's Webkit-based
    - *     iOS browser).
    - */
    -goog.labs.userAgent.browser.isCoast =
    -    goog.labs.userAgent.browser.matchCoast_;
    -
    -
    -/**
    - * @return {boolean} Whether the user's browser is iOS Webview.
    - */
    -goog.labs.userAgent.browser.isIosWebview =
    -    goog.labs.userAgent.browser.matchIosWebview_;
    -
    -
    -/**
    - * @return {boolean} Whether the user's browser is Chrome.
    - */
    -goog.labs.userAgent.browser.isChrome =
    -    goog.labs.userAgent.browser.matchChrome_;
    -
    -
    -/**
    - * @return {boolean} Whether the user's browser is the Android browser.
    - */
    -goog.labs.userAgent.browser.isAndroidBrowser =
    -    goog.labs.userAgent.browser.matchAndroidBrowser_;
    -
    -
    -/**
    - * For more information, see:
    - * http://docs.aws.amazon.com/silk/latest/developerguide/user-agent.html
    - * @return {boolean} Whether the user's browser is Silk.
    - */
    -goog.labs.userAgent.browser.isSilk = function() {
    -  return goog.labs.userAgent.util.matchUserAgent('Silk');
    -};
    -
    -
    -/**
    - * @return {string} The browser version or empty string if version cannot be
    - *     determined. Note that for Internet Explorer, this returns the version of
    - *     the browser, not the version of the rendering engine. (IE 8 in
    - *     compatibility mode will return 8.0 rather than 7.0. To determine the
    - *     rendering engine version, look at document.documentMode instead. See
    - *     http://msdn.microsoft.com/en-us/library/cc196988(v=vs.85).aspx for more
    - *     details.)
    - */
    -goog.labs.userAgent.browser.getVersion = function() {
    -  var userAgentString = goog.labs.userAgent.util.getUserAgent();
    -  // Special case IE since IE's version is inside the parenthesis and
    -  // without the '/'.
    -  if (goog.labs.userAgent.browser.isIE()) {
    -    return goog.labs.userAgent.browser.getIEVersion_(userAgentString);
    -  }
    -
    -  var versionTuples = goog.labs.userAgent.util.extractVersionTuples(
    -      userAgentString);
    -
    -  // Construct a map for easy lookup.
    -  var versionMap = {};
    -  goog.array.forEach(versionTuples, function(tuple) {
    -    // Note that the tuple is of length three, but we only care about the
    -    // first two.
    -    var key = tuple[0];
    -    var value = tuple[1];
    -    versionMap[key] = value;
    -  });
    -
    -  var versionMapHasKey = goog.partial(goog.object.containsKey, versionMap);
    -
    -  // Gives the value with the first key it finds, otherwise empty string.
    -  function lookUpValueWithKeys(keys) {
    -    var key = goog.array.find(keys, versionMapHasKey);
    -    return versionMap[key] || '';
    -  }
    -
    -  // Check Opera before Chrome since Opera 15+ has "Chrome" in the string.
    -  // See
    -  // http://my.opera.com/ODIN/blog/2013/07/15/opera-user-agent-strings-opera-15-and-beyond
    -  if (goog.labs.userAgent.browser.isOpera()) {
    -    // Opera 10 has Version/10.0 but Opera/9.8, so look for "Version" first.
    -    // Opera uses 'OPR' for more recent UAs.
    -    return lookUpValueWithKeys(['Version', 'Opera', 'OPR']);
    -  }
    -
    -  if (goog.labs.userAgent.browser.isChrome()) {
    -    return lookUpValueWithKeys(['Chrome', 'CriOS']);
    -  }
    -
    -  // Usually products browser versions are in the third tuple after "Mozilla"
    -  // and the engine.
    -  var tuple = versionTuples[2];
    -  return tuple && tuple[1] || '';
    -};
    -
    -
    -/**
    - * @param {string|number} version The version to check.
    - * @return {boolean} Whether the browser version is higher or the same as the
    - *     given version.
    - */
    -goog.labs.userAgent.browser.isVersionOrHigher = function(version) {
    -  return goog.string.compareVersions(goog.labs.userAgent.browser.getVersion(),
    -                                     version) >= 0;
    -};
    -
    -
    -/**
    - * Determines IE version. More information:
    - * http://msdn.microsoft.com/en-us/library/ie/bg182625(v=vs.85).aspx#uaString
    - * http://msdn.microsoft.com/en-us/library/hh869301(v=vs.85).aspx
    - * http://blogs.msdn.com/b/ie/archive/2010/03/23/introducing-ie9-s-user-agent-string.aspx
    - * http://blogs.msdn.com/b/ie/archive/2009/01/09/the-internet-explorer-8-user-agent-string-updated-edition.aspx
    - *
    - * @param {string} userAgent the User-Agent.
    - * @return {string}
    - * @private
    - */
    -goog.labs.userAgent.browser.getIEVersion_ = function(userAgent) {
    -  // IE11 may identify itself as MSIE 9.0 or MSIE 10.0 due to an IE 11 upgrade
    -  // bug. Example UA:
    -  // Mozilla/5.0 (MSIE 9.0; Windows NT 6.1; WOW64; Trident/7.0; rv:11.0)
    -  // like Gecko.
    -  // See http://www.whatismybrowser.com/developers/unknown-user-agent-fragments.
    -  var rv = /rv: *([\d\.]*)/.exec(userAgent);
    -  if (rv && rv[1]) {
    -    return rv[1];
    -  }
    -
    -  var version = '';
    -  var msie = /MSIE +([\d\.]+)/.exec(userAgent);
    -  if (msie && msie[1]) {
    -    // IE in compatibility mode usually identifies itself as MSIE 7.0; in this
    -    // case, use the Trident version to determine the version of IE. For more
    -    // details, see the links above.
    -    var tridentVersion = /Trident\/(\d.\d)/.exec(userAgent);
    -    if (msie[1] == '7.0') {
    -      if (tridentVersion && tridentVersion[1]) {
    -        switch (tridentVersion[1]) {
    -          case '4.0':
    -            version = '8.0';
    -            break;
    -          case '5.0':
    -            version = '9.0';
    -            break;
    -          case '6.0':
    -            version = '10.0';
    -            break;
    -          case '7.0':
    -            version = '11.0';
    -            break;
    -        }
    -      } else {
    -        version = '7.0';
    -      }
    -    } else {
    -      version = msie[1];
    -    }
    -  }
    -  return version;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/useragent/browser_test.html b/src/database/third_party/closure-library/closure/goog/labs/useragent/browser_test.html
    deleted file mode 100644
    index 1181d1f5f64..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/useragent/browser_test.html
    +++ /dev/null
    @@ -1,21 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.labs.userAgent.browser</title>
    -<script src="../../base.js"></script>
    -<script>
    -  goog.require('goog.labs.userAgent.browserTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/useragent/browser_test.js b/src/database/third_party/closure-library/closure/goog/labs/useragent/browser_test.js
    deleted file mode 100644
    index 54c11888002..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/useragent/browser_test.js
    +++ /dev/null
    @@ -1,341 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.labs.userAgent.browser.
    - */
    -
    -goog.provide('goog.labs.userAgent.browserTest');
    -
    -goog.require('goog.labs.userAgent.browser');
    -goog.require('goog.labs.userAgent.testAgents');
    -goog.require('goog.labs.userAgent.util');
    -goog.require('goog.object');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.labs.userAgent.browserTest');
    -
    -/*
    - * Map of browser name to checking method.
    - * Used by assertBrowser() to verify that only one is true at a time.
    - */
    -var Browser = {
    -  ANDROID_BROWSER: goog.labs.userAgent.browser.isAndroidBrowser,
    -  CHROME: goog.labs.userAgent.browser.isChrome,
    -  COAST: goog.labs.userAgent.browser.isCoast,
    -  FIREFOX: goog.labs.userAgent.browser.isFirefox,
    -  OPERA: goog.labs.userAgent.browser.isOpera,
    -  IE: goog.labs.userAgent.browser.isIE,
    -  IOS_WEBVIEW: goog.labs.userAgent.browser.isIosWebview,
    -  SAFARI: goog.labs.userAgent.browser.isSafari,
    -  SILK: goog.labs.userAgent.browser.isSilk
    -};
    -
    -
    -/*
    - * Assert that the given browser is true and the others are false.
    - */
    -function assertBrowser(browser) {
    -  assertTrue(
    -      'Supplied argument "browser" not in Browser object',
    -      goog.object.containsValue(Browser, browser));
    -
    -  // Verify that the method is true for the given browser
    -  // and false for all others.
    -  goog.object.forEach(Browser, function(f, name) {
    -    if (f == browser) {
    -      assertTrue('Value for browser ' + name, f());
    -    } else {
    -      assertFalse('Value for browser ' + name, f());
    -    }
    -  });
    -}
    -
    -function setUp() {
    -  goog.labs.userAgent.util.setUserAgent(null);
    -}
    -
    -function testOpera10() {
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.OPERA_10);
    -  assertBrowser(Browser.OPERA);
    -  assertVersion('10.00');
    -  assertVersionBetween('10.00', '10.10');
    -}
    -
    -function testOperaMac() {
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.OPERA_MAC);
    -  assertBrowser(Browser.OPERA);
    -  assertVersion('11.52');
    -  assertVersionBetween('11.50', '12.00');
    -}
    -
    -function testOperaLinux() {
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.OPERA_LINUX);
    -  assertBrowser(Browser.OPERA);
    -  assertVersion('11.50');
    -  assertVersionBetween('11.00', '12.00');
    -}
    -
    -function testOpera15() {
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.OPERA_15);
    -  assertBrowser(Browser.OPERA);
    -  assertVersion('15.0.1147.100');
    -  assertVersionBetween('15.00', '16.00');
    -}
    -
    -function testIE6() {
    -  goog.labs.userAgent.util.setUserAgent(goog.labs.userAgent.testAgents.IE_6);
    -  assertBrowser(Browser.IE);
    -  assertVersion('6.0');
    -  assertVersionBetween('5.0', '7.0');
    -}
    -
    -function testIE7() {
    -  goog.labs.userAgent.util.setUserAgent(goog.labs.userAgent.testAgents.IE_7);
    -  assertBrowser(Browser.IE);
    -  assertVersion('7.0');
    -}
    -
    -function testIE8() {
    -  goog.labs.userAgent.util.setUserAgent(goog.labs.userAgent.testAgents.IE_8);
    -  assertBrowser(Browser.IE);
    -  assertVersion('8.0');
    -  assertVersionBetween('7.0', '9.0');
    -}
    -
    -function testIE8Compatibility() {
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.IE_8_COMPATIBILITY);
    -  assertBrowser(Browser.IE);
    -  assertVersion('8.0');
    -}
    -
    -function testIE9() {
    -  goog.labs.userAgent.util.setUserAgent(goog.labs.userAgent.testAgents.IE_9);
    -  assertBrowser(Browser.IE);
    -  assertVersion('9.0');
    -  assertVersionBetween('8.0', '10.0');
    -}
    -
    -function testIE9Compatibility() {
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.IE_9_COMPATIBILITY);
    -  assertBrowser(Browser.IE);
    -  assertVersion('9.0');
    -}
    -
    -function testIE10() {
    -  goog.labs.userAgent.util.setUserAgent(goog.labs.userAgent.testAgents.IE_10);
    -  assertBrowser(Browser.IE);
    -  assertVersion('10.0');
    -  assertVersionBetween('10.0', '11.0');
    -}
    -
    -function testIE10Compatibility() {
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.IE_10_COMPATIBILITY);
    -  assertBrowser(Browser.IE);
    -  assertVersion('10.0');
    -}
    -
    -function testIE10Mobile() {
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.IE_10_MOBILE);
    -  assertBrowser(Browser.IE);
    -  assertVersion('10.0');
    -}
    -
    -function testIE11() {
    -  goog.labs.userAgent.util.setUserAgent(goog.labs.userAgent.testAgents.IE_11);
    -  assertBrowser(Browser.IE);
    -  assertVersion('11.0');
    -  assertVersionBetween('10.0', '12.0');
    -}
    -
    -function testIE11CompatibilityMSIE7() {
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.IE_11_COMPATIBILITY_MSIE_7);
    -  assertBrowser(Browser.IE);
    -  assertVersion('11.0');
    -}
    -
    -function testIE11CompatibilityMSIE9() {
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.IE_11_COMPATIBILITY_MSIE_9);
    -  assertBrowser(Browser.IE);
    -  assertVersion('11.0');
    -}
    -
    -function testFirefox19() {
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.FIREFOX_19);
    -  assertBrowser(Browser.FIREFOX);
    -  assertVersion('19.0');
    -  assertVersionBetween('18.0', '20.0');
    -}
    -
    -function testFirefoxWindows() {
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.FIREFOX_WINDOWS);
    -  assertBrowser(Browser.FIREFOX);
    -  assertVersion('14.0.1');
    -  assertVersionBetween('14.0', '15.0');
    -}
    -
    -function testFirefoxLinux() {
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.FIREFOX_LINUX);
    -  assertBrowser(Browser.FIREFOX);
    -  assertTrue(goog.labs.userAgent.browser.isFirefox());
    -  assertVersion('15.0.1');
    -}
    -
    -function testChromeAndroid() {
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.CHROME_ANDROID);
    -  assertBrowser(Browser.CHROME);
    -  assertTrue(goog.labs.userAgent.browser.isChrome());
    -  assertVersion('18.0.1025.133');
    -  assertVersionBetween('18.0', '19.0');
    -  assertVersionBetween('17.0', '18.1');
    -}
    -
    -function testChromeIphone() {
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.CHROME_IPHONE);
    -  assertBrowser(Browser.CHROME);
    -  assertTrue(goog.labs.userAgent.browser.isChrome());
    -  assertVersion('22.0.1194.0');
    -  assertVersionBetween('22.0', '23.0');
    -  assertVersionBetween('22.0', '22.10');
    -}
    -
    -function testChromeMac() {
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.CHROME_MAC);
    -  assertBrowser(Browser.CHROME);
    -  assertTrue(goog.labs.userAgent.browser.isChrome());
    -  assertVersion('24.0.1309.0');
    -  assertVersionBetween('24.0', '25.0');
    -  assertVersionBetween('24.0', '24.10');
    -}
    -
    -function testSafariIpad() {
    -  goog.labs.userAgent.util.setUserAgent(goog.labs.userAgent.testAgents.IPAD_6);
    -  assertBrowser(Browser.SAFARI);
    -  assertTrue(goog.labs.userAgent.browser.isSafari());
    -  assertVersion('6.0');
    -  assertVersionBetween('5.1', '7.0');
    -}
    -
    -function testSafari6() {
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.SAFARI_6);
    -  assertBrowser(Browser.SAFARI);
    -  assertTrue(goog.labs.userAgent.browser.isSafari());
    -  assertVersion('6.0');
    -  assertVersionBetween('6.0', '7.0');
    -}
    -
    -function testSafariIphone() {
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.SAFARI_IPHONE_6);
    -  assertBrowser(Browser.SAFARI);
    -  assertTrue(goog.labs.userAgent.browser.isSafari());
    -  assertVersion('6.0');
    -  assertVersionBetween('5.0', '7.0');
    -}
    -
    -function testCoast() {
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.COAST);
    -  assertBrowser(Browser.COAST);
    -}
    -
    -function testWebviewIOS() {
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.WEBVIEW_IPHONE);
    -  assertBrowser(Browser.IOS_WEBVIEW);
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.WEBVIEW_IPAD);
    -  assertBrowser(Browser.IOS_WEBVIEW);
    -}
    -
    -function testAndroidBrowser235() {
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.ANDROID_BROWSER_235);
    -  assertBrowser(Browser.ANDROID_BROWSER);
    -  assertVersion('4.0');
    -  assertVersionBetween('3.0', '5.0');
    -}
    -
    -function testAndroidBrowser403() {
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.ANDROID_BROWSER_403);
    -  assertBrowser(Browser.ANDROID_BROWSER);
    -  assertVersion('4.0');
    -  assertVersionBetween('3.0', '5.0');
    -}
    -
    -function testAndroidBrowser233() {
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.ANDROID_BROWSER_233);
    -  assertBrowser(Browser.ANDROID_BROWSER);
    -  assertVersion('4.0');
    -  assertVersionBetween('3.0', '5.0');
    -}
    -
    -function testAndroidWebView411() {
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.ANDROID_WEB_VIEW_4_1_1);
    -  assertBrowser(Browser.ANDROID_BROWSER);
    -  assertVersion('4.0');
    -  assertVersionBetween('3.0', '5.0');
    -}
    -
    -function testAndroidWebView44() {
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.ANDROID_WEB_VIEW_4_4);
    -  assertBrowser(Browser.CHROME);
    -  assertVersion('30.0.0.0');
    -  assertVersionBetween('29.0', '31.0');
    -}
    -
    -function testSilk() {
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.KINDLE_FIRE);
    -  assertBrowser(Browser.SILK);
    -  assertVersion('2.1');
    -}
    -
    -function testFirefoxOnAndroidTablet() {
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.FIREFOX_ANDROID_TABLET);
    -  assertBrowser(Browser.FIREFOX);
    -  assertVersion('28.0');
    -  assertVersionBetween('27.0', '29.0');
    -}
    -
    -function assertVersion(version) {
    -  assertEquals(version, goog.labs.userAgent.browser.getVersion());
    -}
    -
    -function assertVersionBetween(lowVersion, highVersion) {
    -  assertTrue(goog.labs.userAgent.browser.isVersionOrHigher(lowVersion));
    -  assertFalse(goog.labs.userAgent.browser.isVersionOrHigher(highVersion));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/useragent/device.js b/src/database/third_party/closure-library/closure/goog/labs/useragent/device.js
    deleted file mode 100644
    index f1c2b76c6f9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/useragent/device.js
    +++ /dev/null
    @@ -1,65 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Closure user device detection (based on user agent).
    - * @see http://en.wikipedia.org/wiki/User_agent
    - * For more information on browser brand, platform, or engine see the other
    - * sub-namespaces in goog.labs.userAgent (browser, platform, and engine).
    - *
    - */
    -
    -goog.provide('goog.labs.userAgent.device');
    -
    -goog.require('goog.labs.userAgent.util');
    -
    -
    -/**
    - * Currently we detect the iPhone, iPod and Android mobiles (devices that have
    - * both Android and Mobile in the user agent string).
    - *
    - * @return {boolean} Whether the user is using a mobile device.
    - */
    -goog.labs.userAgent.device.isMobile = function() {
    -  return !goog.labs.userAgent.device.isTablet() &&
    -      (goog.labs.userAgent.util.matchUserAgent('iPod') ||
    -       goog.labs.userAgent.util.matchUserAgent('iPhone') ||
    -       goog.labs.userAgent.util.matchUserAgent('Android') ||
    -       goog.labs.userAgent.util.matchUserAgent('IEMobile'));
    -};
    -
    -
    -/**
    - * Currently we detect Kindle Fire, iPad, and Android tablets (devices that have
    - * Android but not Mobile in the user agent string).
    - *
    - * @return {boolean} Whether the user is using a tablet.
    - */
    -goog.labs.userAgent.device.isTablet = function() {
    -  return goog.labs.userAgent.util.matchUserAgent('iPad') ||
    -      (goog.labs.userAgent.util.matchUserAgent('Android') &&
    -       !goog.labs.userAgent.util.matchUserAgent('Mobile')) ||
    -      goog.labs.userAgent.util.matchUserAgent('Silk');
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the user is using a desktop computer (which we
    - *     assume to be the case if they are not using either a mobile or tablet
    - *     device).
    - */
    -goog.labs.userAgent.device.isDesktop = function() {
    -  return !goog.labs.userAgent.device.isMobile() &&
    -      !goog.labs.userAgent.device.isTablet();
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/useragent/device_test.html b/src/database/third_party/closure-library/closure/goog/labs/useragent/device_test.html
    deleted file mode 100644
    index 887333356cf..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/useragent/device_test.html
    +++ /dev/null
    @@ -1,21 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.labs.userAgent</title>
    -<script src="../../base.js"></script>
    -<script>
    -  goog.require('goog.labs.userAgent.deviceTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/useragent/device_test.js b/src/database/third_party/closure-library/closure/goog/labs/useragent/device_test.js
    deleted file mode 100644
    index 4bf8e7da08e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/useragent/device_test.js
    +++ /dev/null
    @@ -1,73 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.labs.userAgent.device.
    - */
    -
    -goog.provide('goog.labs.userAgent.deviceTest');
    -
    -goog.require('goog.labs.userAgent.device');
    -goog.require('goog.labs.userAgent.testAgents');
    -goog.require('goog.labs.userAgent.util');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.labs.userAgent.deviceTest');
    -
    -function setUp() {
    -  goog.labs.userAgent.util.setUserAgent(null);
    -}
    -
    -function testMobile() {
    -  assertIsMobile(goog.labs.userAgent.testAgents.ANDROID_BROWSER_235);
    -  assertIsMobile(goog.labs.userAgent.testAgents.CHROME_ANDROID);
    -  assertIsMobile(goog.labs.userAgent.testAgents.SAFARI_IPHONE_6);
    -  assertIsMobile(goog.labs.userAgent.testAgents.IE_10_MOBILE);
    -}
    -
    -function testTablet() {
    -  assertIsTablet(goog.labs.userAgent.testAgents.CHROME_ANDROID_TABLET);
    -  assertIsTablet(goog.labs.userAgent.testAgents.KINDLE_FIRE);
    -  assertIsTablet(goog.labs.userAgent.testAgents.IPAD_6);
    -}
    -
    -function testDesktop() {
    -  assertIsDesktop(goog.labs.userAgent.testAgents.CHROME_25);
    -  assertIsDesktop(goog.labs.userAgent.testAgents.OPERA_10);
    -  assertIsDesktop(goog.labs.userAgent.testAgents.FIREFOX_19);
    -  assertIsDesktop(goog.labs.userAgent.testAgents.IE_9);
    -  assertIsDesktop(goog.labs.userAgent.testAgents.IE_10);
    -  assertIsDesktop(goog.labs.userAgent.testAgents.IE_11);
    -}
    -
    -function assertIsMobile(uaString) {
    -  goog.labs.userAgent.util.setUserAgent(uaString);
    -  assertTrue(goog.labs.userAgent.device.isMobile());
    -  assertFalse(goog.labs.userAgent.device.isTablet());
    -  assertFalse(goog.labs.userAgent.device.isDesktop());
    -}
    -
    -function assertIsTablet(uaString) {
    -  goog.labs.userAgent.util.setUserAgent(uaString);
    -  assertTrue(goog.labs.userAgent.device.isTablet());
    -  assertFalse(goog.labs.userAgent.device.isMobile());
    -  assertFalse(goog.labs.userAgent.device.isDesktop());
    -}
    -
    -function assertIsDesktop(uaString) {
    -  goog.labs.userAgent.util.setUserAgent(uaString);
    -  assertTrue(goog.labs.userAgent.device.isDesktop());
    -  assertFalse(goog.labs.userAgent.device.isMobile());
    -  assertFalse(goog.labs.userAgent.device.isTablet());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/useragent/engine.js b/src/database/third_party/closure-library/closure/goog/labs/useragent/engine.js
    deleted file mode 100644
    index 8aa1bfa1d58..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/useragent/engine.js
    +++ /dev/null
    @@ -1,130 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Closure user agent detection.
    - * @see http://en.wikipedia.org/wiki/User_agent
    - * For more information on browser brand, platform, or device see the other
    - * sub-namespaces in goog.labs.userAgent (browser, platform, and device).
    - *
    - */
    -
    -goog.provide('goog.labs.userAgent.engine');
    -
    -goog.require('goog.array');
    -goog.require('goog.labs.userAgent.util');
    -goog.require('goog.string');
    -
    -
    -/**
    - * @return {boolean} Whether the rendering engine is Presto.
    - */
    -goog.labs.userAgent.engine.isPresto = function() {
    -  return goog.labs.userAgent.util.matchUserAgent('Presto');
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the rendering engine is Trident.
    - */
    -goog.labs.userAgent.engine.isTrident = function() {
    -  // IE only started including the Trident token in IE8.
    -  return goog.labs.userAgent.util.matchUserAgent('Trident') ||
    -      goog.labs.userAgent.util.matchUserAgent('MSIE');
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the rendering engine is WebKit.
    - */
    -goog.labs.userAgent.engine.isWebKit = function() {
    -  return goog.labs.userAgent.util.matchUserAgentIgnoreCase('WebKit');
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the rendering engine is Gecko.
    - */
    -goog.labs.userAgent.engine.isGecko = function() {
    -  return goog.labs.userAgent.util.matchUserAgent('Gecko') &&
    -      !goog.labs.userAgent.engine.isWebKit() &&
    -      !goog.labs.userAgent.engine.isTrident();
    -};
    -
    -
    -/**
    - * @return {string} The rendering engine's version or empty string if version
    - *     can't be determined.
    - */
    -goog.labs.userAgent.engine.getVersion = function() {
    -  var userAgentString = goog.labs.userAgent.util.getUserAgent();
    -  if (userAgentString) {
    -    var tuples = goog.labs.userAgent.util.extractVersionTuples(
    -        userAgentString);
    -
    -    var engineTuple = tuples[1];
    -    if (engineTuple) {
    -      // In Gecko, the version string is either in the browser info or the
    -      // Firefox version.  See Gecko user agent string reference:
    -      // http://goo.gl/mULqa
    -      if (engineTuple[0] == 'Gecko') {
    -        return goog.labs.userAgent.engine.getVersionForKey_(
    -            tuples, 'Firefox');
    -      }
    -
    -      return engineTuple[1];
    -    }
    -
    -    // IE has only one version identifier, and the Trident version is
    -    // specified in the parenthetical.
    -    var browserTuple = tuples[0];
    -    var info;
    -    if (browserTuple && (info = browserTuple[2])) {
    -      var match = /Trident\/([^\s;]+)/.exec(info);
    -      if (match) {
    -        return match[1];
    -      }
    -    }
    -  }
    -  return '';
    -};
    -
    -
    -/**
    - * @param {string|number} version The version to check.
    - * @return {boolean} Whether the rendering engine version is higher or the same
    - *     as the given version.
    - */
    -goog.labs.userAgent.engine.isVersionOrHigher = function(version) {
    -  return goog.string.compareVersions(goog.labs.userAgent.engine.getVersion(),
    -                                     version) >= 0;
    -};
    -
    -
    -/**
    - * @param {!Array<!Array<string>>} tuples Version tuples.
    - * @param {string} key The key to look for.
    - * @return {string} The version string of the given key, if present.
    - *     Otherwise, the empty string.
    - * @private
    - */
    -goog.labs.userAgent.engine.getVersionForKey_ = function(tuples, key) {
    -  // TODO(nnaze): Move to util if useful elsewhere.
    -
    -  var pair = goog.array.find(tuples, function(pair) {
    -    return key == pair[0];
    -  });
    -
    -  return pair && pair[1] || '';
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/useragent/engine_test.html b/src/database/third_party/closure-library/closure/goog/labs/useragent/engine_test.html
    deleted file mode 100644
    index 6fc561cb4b3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/useragent/engine_test.html
    +++ /dev/null
    @@ -1,21 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.labs.userAgent</title>
    -<script src="../../base.js"></script>
    -<script>
    -  goog.require('goog.labs.userAgent.engineTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/useragent/engine_test.js b/src/database/third_party/closure-library/closure/goog/labs/useragent/engine_test.js
    deleted file mode 100644
    index fc299c09550..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/useragent/engine_test.js
    +++ /dev/null
    @@ -1,148 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.labs.userAgent.engine.
    - */
    -
    -goog.provide('goog.labs.userAgent.engineTest');
    -
    -goog.require('goog.labs.userAgent.engine');
    -goog.require('goog.labs.userAgent.testAgents');
    -goog.require('goog.labs.userAgent.util');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.labs.userAgent.engineTest');
    -
    -var testAgents = goog.labs.userAgent.testAgents;
    -
    -function setUp() {
    -  goog.labs.userAgent.util.setUserAgent(null);
    -}
    -
    -function assertVersion(version) {
    -  assertEquals(version, goog.labs.userAgent.engine.getVersion());
    -}
    -
    -function assertLowAndHighVersions(lowVersion, highVersion) {
    -  assertTrue(goog.labs.userAgent.engine.isVersionOrHigher(lowVersion));
    -  assertFalse(goog.labs.userAgent.engine.isVersionOrHigher(highVersion));
    -}
    -
    -function testPresto() {
    -  goog.labs.userAgent.util.setUserAgent(testAgents.OPERA_LINUX);
    -  assertTrue(goog.labs.userAgent.engine.isPresto());
    -  assertFalse(goog.labs.userAgent.engine.isGecko());
    -  assertVersion('2.9.168');
    -  assertLowAndHighVersions('2.9', '2.10');
    -
    -  goog.labs.userAgent.util.setUserAgent(testAgents.OPERA_MAC);
    -  assertTrue(goog.labs.userAgent.engine.isPresto());
    -  assertFalse(goog.labs.userAgent.engine.isGecko());
    -  assertVersion('2.9.168');
    -  assertLowAndHighVersions('2.9', '2.10');
    -}
    -
    -function testTrident() {
    -  goog.labs.userAgent.util.setUserAgent(testAgents.IE_6);
    -  assertTrue(goog.labs.userAgent.engine.isTrident());
    -  assertFalse(goog.labs.userAgent.engine.isGecko());
    -  assertVersion('');
    -
    -  goog.labs.userAgent.util.setUserAgent(testAgents.IE_10);
    -  assertTrue(goog.labs.userAgent.engine.isTrident());
    -  assertFalse(goog.labs.userAgent.engine.isGecko());
    -  assertVersion('6.0');
    -  assertLowAndHighVersions('6.0', '7.0');
    -
    -  goog.labs.userAgent.util.setUserAgent(testAgents.IE_8);
    -  assertTrue(goog.labs.userAgent.engine.isTrident());
    -  assertFalse(goog.labs.userAgent.engine.isGecko());
    -  assertVersion('4.0');
    -  assertLowAndHighVersions('4.0', '5.0');
    -
    -  goog.labs.userAgent.util.setUserAgent(testAgents.IE_9_COMPATIBILITY);
    -  assertTrue(goog.labs.userAgent.engine.isTrident());
    -  assertFalse(goog.labs.userAgent.engine.isGecko());
    -  assertVersion('5.0');
    -  assertLowAndHighVersions('5.0', '6.0');
    -
    -  goog.labs.userAgent.util.setUserAgent(goog.labs.userAgent.testAgents.IE_11);
    -  assertTrue(goog.labs.userAgent.engine.isTrident());
    -  assertFalse(goog.labs.userAgent.engine.isGecko());
    -  assertVersion('7.0');
    -  assertLowAndHighVersions('6.0', '8.0');
    -
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.IE_10_MOBILE);
    -  assertTrue(goog.labs.userAgent.engine.isTrident());
    -  assertVersion('6.0');
    -}
    -
    -function testWebKit() {
    -  goog.labs.userAgent.util.setUserAgent(testAgents.ANDROID_BROWSER_235);
    -  assertTrue(goog.labs.userAgent.engine.isWebKit());
    -  assertFalse(goog.labs.userAgent.engine.isGecko());
    -  assertVersion('533.1');
    -  assertLowAndHighVersions('533.0', '534.0');
    -
    -  goog.labs.userAgent.util.setUserAgent(testAgents.ANDROID_BROWSER_403_ALT);
    -  assertTrue(goog.labs.userAgent.engine.isWebKit());
    -  assertFalse(goog.labs.userAgent.engine.isGecko());
    -  assertVersion('534.30');
    -  assertLowAndHighVersions('533.0', '535.0');
    -
    -  goog.labs.userAgent.util.setUserAgent(testAgents.CHROME_25);
    -  assertTrue(goog.labs.userAgent.engine.isWebKit());
    -  assertFalse(goog.labs.userAgent.engine.isGecko());
    -  assertVersion('535.8');
    -  assertLowAndHighVersions('535.0', '536.0');
    -
    -  goog.labs.userAgent.util.setUserAgent(testAgents.SAFARI_6);
    -  assertTrue(goog.labs.userAgent.engine.isWebKit());
    -  assertFalse(goog.labs.userAgent.engine.isGecko());
    -  assertVersion('536.25');
    -  assertLowAndHighVersions('536.0', '537.0');
    -
    -  goog.labs.userAgent.util.setUserAgent(testAgents.SAFARI_IPHONE_6);
    -  assertTrue(goog.labs.userAgent.engine.isWebKit());
    -  assertFalse(goog.labs.userAgent.engine.isGecko());
    -  assertVersion('536.26');
    -  assertLowAndHighVersions('536.0', '537.0');
    -}
    -
    -function testOpera15() {
    -  goog.labs.userAgent.util.setUserAgent(testAgents.OPERA_15);
    -  assertTrue(goog.labs.userAgent.engine.isWebKit());
    -  assertFalse(goog.labs.userAgent.engine.isPresto());
    -  assertVersion('537.36');
    -}
    -
    -function testGecko() {
    -  goog.labs.userAgent.util.setUserAgent(testAgents.FIREFOX_LINUX);
    -  assertTrue(goog.labs.userAgent.engine.isGecko());
    -  assertVersion('15.0.1');
    -  assertLowAndHighVersions('14.0', '16.0');
    -
    -  goog.labs.userAgent.util.setUserAgent(testAgents.FIREFOX_19);
    -  assertTrue(goog.labs.userAgent.engine.isGecko());
    -  assertVersion('19.0');
    -  assertLowAndHighVersions('18.0', '20.0');
    -
    -  goog.labs.userAgent.util.setUserAgent(testAgents.FIREFOX_WINDOWS);
    -  assertTrue(goog.labs.userAgent.engine.isGecko());
    -  assertVersion('14.0.1');
    -  assertLowAndHighVersions('14.0', '15.0');
    -}
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/useragent/platform.js b/src/database/third_party/closure-library/closure/goog/labs/useragent/platform.js
    deleted file mode 100644
    index ece7c07ea1a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/useragent/platform.js
    +++ /dev/null
    @@ -1,160 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Closure user agent platform detection.
    - * @see <a href="http://www.useragentstring.com/">User agent strings</a>
    - * For more information on browser brand, rendering engine, or device see the
    - * other sub-namespaces in goog.labs.userAgent (browser, engine, and device
    - * respectively).
    - *
    - */
    -
    -goog.provide('goog.labs.userAgent.platform');
    -
    -goog.require('goog.labs.userAgent.util');
    -goog.require('goog.string');
    -
    -
    -/**
    - * @return {boolean} Whether the platform is Android.
    - */
    -goog.labs.userAgent.platform.isAndroid = function() {
    -  return goog.labs.userAgent.util.matchUserAgent('Android');
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the platform is iPod.
    - */
    -goog.labs.userAgent.platform.isIpod = function() {
    -  return goog.labs.userAgent.util.matchUserAgent('iPod');
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the platform is iPhone.
    - */
    -goog.labs.userAgent.platform.isIphone = function() {
    -  return goog.labs.userAgent.util.matchUserAgent('iPhone') &&
    -      !goog.labs.userAgent.util.matchUserAgent('iPod') &&
    -      !goog.labs.userAgent.util.matchUserAgent('iPad');
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the platform is iPad.
    - */
    -goog.labs.userAgent.platform.isIpad = function() {
    -  return goog.labs.userAgent.util.matchUserAgent('iPad');
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the platform is iOS.
    - */
    -goog.labs.userAgent.platform.isIos = function() {
    -  return goog.labs.userAgent.platform.isIphone() ||
    -      goog.labs.userAgent.platform.isIpad() ||
    -      goog.labs.userAgent.platform.isIpod();
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the platform is Mac.
    - */
    -goog.labs.userAgent.platform.isMacintosh = function() {
    -  return goog.labs.userAgent.util.matchUserAgent('Macintosh');
    -};
    -
    -
    -/**
    - * Note: ChromeOS is not considered to be Linux as it does not report itself
    - * as Linux in the user agent string.
    - * @return {boolean} Whether the platform is Linux.
    - */
    -goog.labs.userAgent.platform.isLinux = function() {
    -  return goog.labs.userAgent.util.matchUserAgent('Linux');
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the platform is Windows.
    - */
    -goog.labs.userAgent.platform.isWindows = function() {
    -  return goog.labs.userAgent.util.matchUserAgent('Windows');
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the platform is ChromeOS.
    - */
    -goog.labs.userAgent.platform.isChromeOS = function() {
    -  return goog.labs.userAgent.util.matchUserAgent('CrOS');
    -};
    -
    -
    -/**
    - * The version of the platform. We only determine the version for Windows,
    - * Mac, and Chrome OS. It doesn't make much sense on Linux. For Windows, we only
    - * look at the NT version. Non-NT-based versions (e.g. 95, 98, etc.) are given
    - * version 0.0.
    - *
    - * @return {string} The platform version or empty string if version cannot be
    - *     determined.
    - */
    -goog.labs.userAgent.platform.getVersion = function() {
    -  var userAgentString = goog.labs.userAgent.util.getUserAgent();
    -  var version = '', re;
    -  if (goog.labs.userAgent.platform.isWindows()) {
    -    re = /Windows (?:NT|Phone) ([0-9.]+)/;
    -    var match = re.exec(userAgentString);
    -    if (match) {
    -      version = match[1];
    -    } else {
    -      version = '0.0';
    -    }
    -  } else if (goog.labs.userAgent.platform.isIos()) {
    -    re = /(?:iPhone|iPod|iPad|CPU)\s+OS\s+(\S+)/;
    -    var match = re.exec(userAgentString);
    -    // Report the version as x.y.z and not x_y_z
    -    version = match && match[1].replace(/_/g, '.');
    -  } else if (goog.labs.userAgent.platform.isMacintosh()) {
    -    re = /Mac OS X ([0-9_.]+)/;
    -    var match = re.exec(userAgentString);
    -    // Note: some old versions of Camino do not report an OSX version.
    -    // Default to 10.
    -    version = match ? match[1].replace(/_/g, '.') : '10';
    -  } else if (goog.labs.userAgent.platform.isAndroid()) {
    -    re = /Android\s+([^\);]+)(\)|;)/;
    -    var match = re.exec(userAgentString);
    -    version = match && match[1];
    -  } else if (goog.labs.userAgent.platform.isChromeOS()) {
    -    re = /(?:CrOS\s+(?:i686|x86_64)\s+([0-9.]+))/;
    -    var match = re.exec(userAgentString);
    -    version = match && match[1];
    -  }
    -  return version || '';
    -};
    -
    -
    -/**
    - * @param {string|number} version The version to check.
    - * @return {boolean} Whether the browser version is higher or the same as the
    - *     given version.
    - */
    -goog.labs.userAgent.platform.isVersionOrHigher = function(version) {
    -  return goog.string.compareVersions(goog.labs.userAgent.platform.getVersion(),
    -                                     version) >= 0;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/useragent/platform_test.html b/src/database/third_party/closure-library/closure/goog/labs/useragent/platform_test.html
    deleted file mode 100644
    index 23d14b33985..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/useragent/platform_test.html
    +++ /dev/null
    @@ -1,21 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.labs.userAgent.platform</title>
    -<script src="../../base.js"></script>
    -<script>
    -  goog.require('goog.labs.userAgent.platformTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/useragent/platform_test.js b/src/database/third_party/closure-library/closure/goog/labs/useragent/platform_test.js
    deleted file mode 100644
    index 1d11cd96302..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/useragent/platform_test.js
    +++ /dev/null
    @@ -1,247 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.labs.userAgent.platform.
    - */
    -
    -goog.provide('goog.labs.userAgent.platformTest');
    -
    -goog.require('goog.labs.userAgent.platform');
    -goog.require('goog.labs.userAgent.testAgents');
    -goog.require('goog.labs.userAgent.util');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.labs.userAgent.platformTest');
    -
    -function setUp() {
    -  goog.labs.userAgent.util.setUserAgent(null);
    -}
    -
    -function testAndroid() {
    -  var uaString = goog.labs.userAgent.testAgents.ANDROID_BROWSER_233;
    -
    -  goog.labs.userAgent.util.setUserAgent(uaString);
    -  assertTrue(goog.labs.userAgent.platform.isAndroid());
    -  assertVersion('2.3.3');
    -  assertVersionBetween('2.3.0', '2.3.5');
    -  assertVersionBetween('2.3', '2.4');
    -  assertVersionBetween('2', '3');
    -
    -  uaString = goog.labs.userAgent.testAgents.ANDROID_BROWSER_221;
    -
    -  goog.labs.userAgent.util.setUserAgent(uaString);
    -  assertTrue(goog.labs.userAgent.platform.isAndroid());
    -  assertVersion('2.2.1');
    -  assertVersionBetween('2.2.0', '2.2.5');
    -  assertVersionBetween('2.2', '2.3');
    -  assertVersionBetween('2', '3');
    -
    -  uaString = goog.labs.userAgent.testAgents.CHROME_ANDROID;
    -
    -  goog.labs.userAgent.util.setUserAgent(uaString);
    -  assertTrue(goog.labs.userAgent.platform.isAndroid());
    -  assertVersion('4.0.2');
    -  assertVersionBetween('4.0.0', '4.1.0');
    -  assertVersionBetween('4.0', '4.1');
    -  assertVersionBetween('4', '5');
    -}
    -
    -function testKindleFire() {
    -  uaString = goog.labs.userAgent.testAgents.KINDLE_FIRE;
    -  goog.labs.userAgent.util.setUserAgent(uaString);
    -  assertTrue(goog.labs.userAgent.platform.isAndroid());
    -  assertVersion('4.0.3');
    -}
    -
    -function testIpod() {
    -  var uaString = goog.labs.userAgent.testAgents.SAFARI_IPOD;
    -
    -  goog.labs.userAgent.util.setUserAgent(uaString);
    -  assertTrue(goog.labs.userAgent.platform.isIpod());
    -  assertTrue(goog.labs.userAgent.platform.isIos());
    -  assertVersion('');
    -}
    -
    -function testIphone() {
    -  var uaString = goog.labs.userAgent.testAgents.SAFARI_IPHONE_421;
    -  goog.labs.userAgent.util.setUserAgent(uaString);
    -  assertTrue(goog.labs.userAgent.platform.isIphone());
    -  assertTrue(goog.labs.userAgent.platform.isIos());
    -  assertVersion('4.2.1');
    -  assertVersionBetween('4', '5');
    -  assertVersionBetween('4.2', '4.3');
    -
    -  uaString = goog.labs.userAgent.testAgents.SAFARI_IPHONE_6;
    -  goog.labs.userAgent.util.setUserAgent(uaString);
    -  assertTrue(goog.labs.userAgent.platform.isIphone());
    -  assertTrue(goog.labs.userAgent.platform.isIos());
    -  assertVersion('6.0');
    -  assertVersionBetween('5', '7');
    -
    -  uaString = goog.labs.userAgent.testAgents.SAFARI_IPHONE_32;
    -  goog.labs.userAgent.util.setUserAgent(uaString);
    -  assertTrue(goog.labs.userAgent.platform.isIphone());
    -  assertTrue(goog.labs.userAgent.platform.isIos());
    -  assertVersion('3.2');
    -  assertVersionBetween('3', '4');
    -
    -  uaString = goog.labs.userAgent.testAgents.WEBVIEW_IPAD;
    -  goog.labs.userAgent.util.setUserAgent(uaString);
    -  assertFalse(goog.labs.userAgent.platform.isIphone());
    -  assertTrue(goog.labs.userAgent.platform.isIpad());
    -  assertTrue(goog.labs.userAgent.platform.isIos());
    -  assertVersion('6.0');
    -  assertVersionBetween('5', '7');
    -}
    -
    -function testIpad() {
    -  var uaString = goog.labs.userAgent.testAgents.IPAD_4;
    -
    -  goog.labs.userAgent.util.setUserAgent(uaString);
    -  assertTrue(goog.labs.userAgent.platform.isIpad());
    -  assertTrue(goog.labs.userAgent.platform.isIos());
    -  assertVersion('3.2');
    -  assertVersionBetween('3', '4');
    -  assertVersionBetween('3.1', '4');
    -
    -  uaString = goog.labs.userAgent.testAgents.IPAD_5;
    -
    -  goog.labs.userAgent.util.setUserAgent(uaString);
    -  assertTrue(goog.labs.userAgent.platform.isIpad());
    -  assertTrue(goog.labs.userAgent.platform.isIos());
    -  assertVersion('5.1');
    -  assertVersionBetween('5', '6');
    -
    -  uaString = goog.labs.userAgent.testAgents.IPAD_6;
    -
    -  goog.labs.userAgent.util.setUserAgent(uaString);
    -  assertTrue(goog.labs.userAgent.platform.isIpad());
    -  assertTrue(goog.labs.userAgent.platform.isIos());
    -  assertVersion('6.0');
    -  assertVersionBetween('5', '7');
    -}
    -
    -function testMac() {
    -  var uaString = goog.labs.userAgent.testAgents.CHROME_MAC;
    -  var platform = 'IntelMac';
    -  goog.labs.userAgent.util.setUserAgent(uaString, platform);
    -  assertTrue(goog.labs.userAgent.platform.isMacintosh());
    -  assertVersion('10.8.2');
    -  assertVersionBetween('10', '11');
    -  assertVersionBetween('10.8', '10.9');
    -  assertVersionBetween('10.8.1', '10.8.3');
    -
    -  uaString = goog.labs.userAgent.testAgents.OPERA_MAC;
    -  goog.labs.userAgent.util.setUserAgent(uaString, platform);
    -  assertTrue(goog.labs.userAgent.platform.isMacintosh());
    -  assertVersion('10.6.8');
    -  assertVersionBetween('10', '11');
    -  assertVersionBetween('10.6', '10.7');
    -  assertVersionBetween('10.6.5', '10.7.0');
    -
    -  uaString = goog.labs.userAgent.testAgents.SAFARI_MAC;
    -  goog.labs.userAgent.util.setUserAgent(uaString, platform);
    -  assertTrue(goog.labs.userAgent.platform.isMacintosh());
    -  assertVersionBetween('10', '11');
    -  assertVersionBetween('10.6', '10.7');
    -  assertVersionBetween('10.6.5', '10.7.0');
    -
    -  uaString = goog.labs.userAgent.testAgents.FIREFOX_MAC;
    -  goog.labs.userAgent.util.setUserAgent(uaString, platform);
    -  assertTrue(goog.labs.userAgent.platform.isMacintosh());
    -  assertVersion('11.7.9');
    -  assertVersionBetween('11', '12');
    -  assertVersionBetween('11.7', '11.8');
    -  assertVersionBetween('11.7.9', '11.8.0');
    -}
    -
    -function testLinux() {
    -  var uaString = goog.labs.userAgent.testAgents.FIREFOX_LINUX;
    -  goog.labs.userAgent.util.setUserAgent(uaString);
    -  assertTrue(goog.labs.userAgent.platform.isLinux());
    -  assertVersion('');
    -
    -  uaString = goog.labs.userAgent.testAgents.CHROME_LINUX;
    -  goog.labs.userAgent.util.setUserAgent(uaString);
    -  assertTrue(goog.labs.userAgent.platform.isLinux());
    -  assertVersion('');
    -
    -  uaString = goog.labs.userAgent.testAgents.OPERA_LINUX;
    -  goog.labs.userAgent.util.setUserAgent(uaString);
    -  assertTrue(goog.labs.userAgent.platform.isLinux());
    -  assertVersion('');
    -}
    -
    -function testWindows() {
    -  var uaString = goog.labs.userAgent.testAgents.SAFARI_WINDOWS;
    -  goog.labs.userAgent.util.setUserAgent(uaString);
    -  assertTrue(goog.labs.userAgent.platform.isWindows());
    -  assertVersion('6.1');
    -  assertVersionBetween('6', '7');
    -
    -  uaString = goog.labs.userAgent.testAgents.IE_10;
    -  goog.labs.userAgent.util.setUserAgent(uaString);
    -  assertTrue(goog.labs.userAgent.platform.isWindows());
    -  assertVersion('6.2');
    -  assertVersionBetween('6', '6.5');
    -
    -  uaString = goog.labs.userAgent.testAgents.CHROME_25;
    -  goog.labs.userAgent.util.setUserAgent(uaString);
    -  assertTrue(goog.labs.userAgent.platform.isWindows());
    -  assertVersion('5.1');
    -  assertVersionBetween('5', '6');
    -
    -  uaString = goog.labs.userAgent.testAgents.FIREFOX_WINDOWS;
    -  goog.labs.userAgent.util.setUserAgent(uaString);
    -  assertTrue(goog.labs.userAgent.platform.isWindows());
    -  assertVersion('6.1');
    -  assertVersionBetween('6', '7');
    -
    -  uaString = goog.labs.userAgent.testAgents.IE_11;
    -  goog.labs.userAgent.util.setUserAgent(uaString);
    -  assertTrue(goog.labs.userAgent.platform.isWindows());
    -  assertVersion('6.3');
    -  assertVersionBetween('6', '6.5');
    -
    -  uaString = goog.labs.userAgent.testAgents.IE_10_MOBILE;
    -  goog.labs.userAgent.util.setUserAgent(uaString);
    -  assertTrue(goog.labs.userAgent.platform.isWindows());
    -  assertVersion('8.0');
    -}
    -
    -function testChromeOS() {
    -  var uaString = goog.labs.userAgent.testAgents.CHROME_OS_910;
    -
    -  goog.labs.userAgent.util.setUserAgent(uaString);
    -  assertTrue(goog.labs.userAgent.platform.isChromeOS());
    -  assertVersion('9.10.0');
    -  assertVersionBetween('9', '10');
    -
    -  uaString = goog.labs.userAgent.testAgents.CHROME_OS;
    -
    -  goog.labs.userAgent.util.setUserAgent(uaString);
    -  assertTrue(goog.labs.userAgent.platform.isChromeOS());
    -  assertVersion('3701.62.0');
    -  assertVersionBetween('3701', '3702');
    -}
    -
    -function assertVersion(version) {
    -  assertEquals(version, goog.labs.userAgent.platform.getVersion());
    -}
    -
    -function assertVersionBetween(lowVersion, highVersion) {
    -  assertTrue(goog.labs.userAgent.platform.isVersionOrHigher(lowVersion));
    -  assertFalse(goog.labs.userAgent.platform.isVersionOrHigher(highVersion));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/useragent/test_agents.js b/src/database/third_party/closure-library/closure/goog/labs/useragent/test_agents.js
    deleted file mode 100644
    index 38b7802dea8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/useragent/test_agents.js
    +++ /dev/null
    @@ -1,377 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the 'License');
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an 'AS-IS' BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Various User-Agent strings.
    - * See http://go/useragentexamples and http://www.useragentstring.com/ for
    - * examples.
    - *
    - * @author martone@google.com (Andy Martone)
    - */
    -
    -goog.provide('goog.labs.userAgent.testAgents');
    -goog.setTestOnly('goog.labs.userAgent.testAgents');
    -
    -goog.scope(function() {
    -var testAgents = goog.labs.userAgent.testAgents;
    -
    -
    -/** @const {string} */
    -testAgents.ANDROID_BROWSER_235 =
    -    'Mozilla/5.0 (Linux; U; Android 2.3.5; en-us; ' +
    -    'HTC Vision Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) ' +
    -    'Version/4.0 Mobile Safari/533.1';
    -
    -
    -/** @const {string} */
    -testAgents.ANDROID_BROWSER_221 =
    -    'Mozilla/5.0 (Linux; U; Android 2.2.1; en-ca; LG-P505R Build/FRG83)' +
    -    ' AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1';
    -
    -
    -/** @const {string} */
    -testAgents.ANDROID_BROWSER_233 =
    -    'Mozilla/5.0 (Linux; U; Android 2.3.3; en-us; HTC_DesireS_S510e' +
    -    ' Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0' +
    -    ' Mobile Safari/533.1';
    -
    -
    -/** @const {string} */
    -testAgents.ANDROID_BROWSER_403 =
    -    'Mozilla/5.0 (Linux; U; Android 4.0.3; de-ch; HTC Sensation Build/IML74K)' +
    -    ' AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30';
    -
    -
    -/** @const {string} */
    -// User agent retrieved from dremel queries for cases matching b/13222688
    -testAgents.ANDROID_BROWSER_403_ALT =
    -    'Mozilla/5.0 (Linux; U; Android 4.0.3; ko-kr; LG-L160L Build/IML74K)' +
    -    ' AppleWebkit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30';
    -
    -
    -// Chromium for Android. Found in Android 4.4+ devices based on AOSP, but never
    -// in the 'Google' devices (where only Google Chrome is shipped).
    -// UA string matches Chromium based WebView exactly, see ANDROID_WEB_VIEW_4_4.
    -/** @const {string} */
    -testAgents.ANDROID_BROWSER_4_4 =
    -    'Mozilla/5.0 (Linux; Android 4.4.2; S8 Build/KOT49H) ' +
    -    'AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 ' +
    -    'Chrome/30.0.0.0 Mobile Safari/537.36';
    -
    -
    -// See https://developer.chrome.com/multidevice/user-agent
    -/** @const {string} */
    -testAgents.ANDROID_WEB_VIEW_4_1_1 =
    -    'Mozilla/5.0 (Linux; U; Android 4.1.1; en-gb; Build/KLP) ' +
    -    'AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30';
    -
    -
    -// See https://developer.chrome.com/multidevice/user-agent
    -/** @const {string} */
    -testAgents.ANDROID_WEB_VIEW_4_4 =
    -    'Mozilla/5.0 (Linux; Android 4.4; Nexus 5 Build/_BuildID_) ' +
    -    'AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 ' +
    -    'Chrome/30.0.0.0 Mobile Safari/537.36';
    -
    -
    -/** @const {string} */
    -testAgents.IE_6 =
    -    'Mozilla/5.0 (Windows; U; MSIE 6.0; Windows NT 5.1; SV1;' +
    -    '.NET CLR 2.0.50727)';
    -
    -
    -/** @const {string} */
    -testAgents.IE_7 =
    -    'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)';
    -
    -
    -/** @const {string} */
    -testAgents.IE_8 =
    -    'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)';
    -
    -
    -/** @const {string} */
    -testAgents.IE_8_COMPATIBILITY =
    -    'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/4.0)';
    -
    -
    -/** @const {string} */
    -testAgents.IE_9 =
    -    'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)';
    -
    -
    -/** @const {string} */
    -testAgents.IE_9_COMPATIBILITY =
    -    'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/5.0)';
    -
    -
    -/** @const {string} */
    -testAgents.IE_10 =
    -    'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)';
    -
    -
    -/** @const {string} */
    -testAgents.IE_10_COMPATIBILITY =
    -    'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/6.0)';
    -
    -
    -/**
    - * http://blogs.windows.com/windows_phone/b/wpdev/archive/2012/10/17/getting-websites-ready-for-internet-explorer-10-on-windows-phone-8.aspx
    - * @const {string}
    - */
    -testAgents.IE_10_MOBILE =
    -    'Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; ' +
    -    'IEMobile/10.0; ARM; Touch; NOKIA; Lumia 820)';
    -
    -
    -/** @const {string} */
    -testAgents.IE_11 =
    -    'Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko';
    -
    -
    -/** @const {string} */
    -testAgents.IE_11_COMPATIBILITY_MSIE_7 =
    -    'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; Trident/7.0; ' +
    -    '.NET4.0E; .NET4.0C)';
    -
    -
    -/** @const {string} */
    -testAgents.IE_11_COMPATIBILITY_MSIE_9 =
    -    'Mozilla/5.0 (MSIE 9.0; Windows NT 6.1; WOW64; Trident/7.0; ' +
    -    'rv:11.0) like Gecko';
    -
    -
    -/** @const {string} */
    -testAgents.FIREFOX_19 =
    -    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:19.0) ' +
    -    'Gecko/20100101 Firefox/19.0';
    -
    -
    -/** @const {string} */
    -testAgents.FIREFOX_LINUX =
    -    'Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:15.0) Gecko/20100101' +
    -    ' Firefox/15.0.1';
    -
    -
    -/** @const {string} */
    -testAgents.FIREFOX_MAC =
    -    'Mozilla/6.0 (Macintosh; I; Intel Mac OS X 11_7_9; de-LI; rv:1.9b4)' +
    -    ' Gecko/2012010317 Firefox/10.0a4';
    -
    -
    -/** @const {string} */
    -testAgents.FIREFOX_WINDOWS =
    -    'Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20120403211507' +
    -    ' Firefox/14.0.1';
    -
    -
    -/** @const {string} */
    -testAgents.SAFARI_6 =
    -    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_1) ' +
    -    'AppleWebKit/536.25 (KHTML, like Gecko) ' +
    -    'Version/6.0 Safari/536.25';
    -
    -
    -/** @const {string} */
    -testAgents.SAFARI_IPHONE_32 =
    -    'Mozilla/5.0(iPhone; U; CPU iPhone OS 3_2 like Mac OS X; en-us)' +
    -    ' AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B314' +
    -    ' Safari/531.21.10';
    -
    -
    -/** @const {string} */
    -testAgents.SAFARI_IPHONE_421 =
    -    'Mozilla/5.0 (iPhone; U; ru; CPU iPhone OS 4_2_1 like Mac OS X; ru)' +
    -    ' AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148a' +
    -    ' Safari/6533.18.5';
    -
    -
    -/** @const {string} */
    -testAgents.SAFARI_IPHONE_431 =
    -    'Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_1 like Mac OS X; zh-tw)' +
    -    ' AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8G4' +
    -    ' Safari/6533.18.5';
    -
    -
    -/** @const {string} */
    -testAgents.SAFARI_IPHONE_6 =
    -    'Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X)' +
    -    ' AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e' +
    -    ' Safari/8536.25';
    -
    -
    -/** @const {string} */
    -testAgents.SAFARI_IPOD =
    -    'Mozila/5.0 (iPod; U; CPU like Mac OS X; en) AppleWebKit/420.1' +
    -    ' (KHTML, like Gecko) Version/3.0 Mobile/3A101a Safari/419.3';
    -
    -
    -/** @const {string} */
    -testAgents.SAFARI_MAC =
    -    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.13+' +
    -    ' (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2';
    -
    -
    -/** @const {string} */
    -testAgents.SAFARI_WINDOWS =
    -    'Mozilla/5.0 (Windows; U; Windows NT 6.1; tr-TR) AppleWebKit/533.20.25' +
    -    ' (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27';
    -
    -
    -/** @const {string} */
    -testAgents.COAST =
    -    'Mozilla/5.0 (iPad; CPU OS 7_0_2 like Mac OS X) AppleWebKit/537.51.1' +
    -    ' (KHTML like Gecko) Coast/1.1.2.64598 Mobile/11B511 Safari/7534.48.3';
    -
    -
    -/** @const {string} */
    -testAgents.WEBVIEW_IPHONE =
    -    'Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26' +
    -    ' (KHTML, like Gecko) Mobile/10A403';
    -
    -
    -/** @const {string} */
    -testAgents.WEBVIEW_IPAD =
    -    'Mozilla/5.0 (iPad; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26' +
    -    ' (KHTML, like Gecko) Mobile/10A403';
    -
    -
    -/** @const {string} */
    -testAgents.OPERA_10 =
    -    'Opera/9.80 (S60; SymbOS; Opera Mobi/447; U; en) ' +
    -    'Presto/2.4.18 Version/10.00';
    -
    -
    -/** @const {string} */
    -testAgents.OPERA_LINUX =
    -    'Opera/9.80 (X11; Linux x86_64; U; fr) Presto/2.9.168 Version/11.50';
    -
    -
    -/** @const {string} */
    -testAgents.OPERA_MAC =
    -    'Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168' +
    -    ' Version/11.52';
    -
    -
    -/** @const {string} */
    -testAgents.OPERA_15 =
    -    'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 ' +
    -    '(KHTML, like Gecko) Chrome/28.0.1500.52 Safari/537.36 OPR/15.0.1147.100';
    -
    -
    -/** @const {string} */
    -testAgents.IPAD_4 =
    -    'Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us)' +
    -    ' AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b' +
    -    ' Safari/531.21.10';
    -
    -
    -/** @const {string} */
    -testAgents.IPAD_5 =
    -    'Mozilla/5.0 (iPad; CPU OS 5_1 like Mac OS X; en-us) AppleWebKit/534.46' +
    -    ' (KHTML, like Gecko) Version/5.1 Mobile/9B176 Safari/7534.48.3';
    -
    -
    -/** @const {string} */
    -testAgents.IPAD_6 =
    -    'Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) ' +
    -    'AppleWebKit/536.26 (KHTML, like Gecko) ' +
    -    'Version/6.0 Mobile/10A403 Safari/8536.25';
    -
    -
    -/** @const {string} */
    -testAgents.CHROME_25 =
    -    'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) ' +
    -    'AppleWebKit/535.8 (KHTML, like Gecko) ' +
    -    'Chrome/25.0.1000.10 Safari/535.8';
    -
    -
    -/** @const {string} */
    -testAgents.CHROME_ANDROID =
    -    'Mozilla/5.0 (Linux; U; Android 4.0.2; en-us; Galaxy Nexus Build/ICL53F) ' +
    -    'AppleWebKit/535.7 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile ' +
    -    'Safari/535.7';
    -
    -
    -/** @const {string} */
    -testAgents.CHROME_ANDROID_PHONE_4_4 =
    -    'Mozilla/5.0 (Linux; Android 4.4.2; S8 Build/KOT49H) ' +
    -    'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.93 Mobile ' +
    -    'Safari/537.36';
    -
    -
    -/** @const {string} */
    -testAgents.CHROME_ANDROID_TABLET =
    -    'Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) ' +
    -    'AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Safari/535.19';
    -
    -
    -/** @const {string} */
    -testAgents.CHROME_ANDROID_TABLET_4_4 =
    -    'Mozilla/5.0 (Linux; Android 4.4.4; Nexus 7 Build/KTU84P) ' +
    -    'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.93 Safari/537.36';
    -
    -
    -/** @const {string} */
    -testAgents.CHROME_IPHONE =
    -    'Mozilla/5.0 (iPhone; CPU iPhone OS 5_1_1 like Mac OS X; en-us) ' +
    -    'AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/22.0.1194.0 Mobile/11E53 ' +
    -    'Safari/7534.48.3';
    -
    -
    -/** @const {string} */
    -testAgents.CHROME_LINUX =
    -    'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.31 (KHTML, like Gecko)' +
    -    ' Chrome/26.0.1410.33 Safari/537.31';
    -
    -
    -/**
    - * We traditionally use Appversion to detect X11
    - * @const {string}
    - */
    -testAgents.CHROME_LINUX_APPVERVERSION =
    -    '5.0 (X11; Linux x86_64) AppleWebKit/537.31 (KHTML, like Gecko)' +
    -    ' Chrome/26.0.1410.33 Safari/537.31';
    -
    -
    -/** @const {string} */
    -testAgents.CHROME_MAC =
    -    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17' +
    -    ' (KHTML, like Gecko) Chrome/24.0.1309.0 Safari/537.17';
    -
    -
    -/** @const {string} */
    -testAgents.CHROME_OS =
    -    'Mozilla/5.0 (X11; CrOS x86_64 3701.62.0) AppleWebKit/537.31 ' +
    -    '(KHTML, like Gecko) Chrome/26.0.1410.40 Safari/537.31';
    -
    -
    -/** @const {string} */
    -testAgents.CHROME_OS_910 =
    -    'Mozilla/5.0 (X11; U; CrOS i686 9.10.0; en-US) AppleWebKit/532.5' +
    -    ' (KHTML, like Gecko) Chrome/4.0.253.0 Safari/532.5';
    -
    -
    -/** @const {string} */
    -testAgents.KINDLE_FIRE =
    -    'Mozilla/5.0 (Linux; U; Android 4.0.3; en-us; KFTT Build/IML74K)' +
    -    ' AppleWebKit/535.19 (KHTML, like Gecko) Silk/2.1 Mobile Safari/535.19' +
    -    ' Silk-Accelerated=true';
    -
    -
    -/** @const {string} */
    -testAgents.FIREFOX_ANDROID_TABLET =
    -    'Mozilla/5.0 (Android; Tablet; rv:28.0) Gecko/28.0 Firefox/28.0';
    -
    -});  // goog.scope
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/useragent/util.js b/src/database/third_party/closure-library/closure/goog/labs/useragent/util.js
    deleted file mode 100644
    index ebba9b540c2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/useragent/util.js
    +++ /dev/null
    @@ -1,148 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Utilities used by goog.labs.userAgent tools. These functions
    - * should not be used outside of goog.labs.userAgent.*.
    - *
    - *
    - * @author nnaze@google.com (Nathan Naze)
    - */
    -
    -goog.provide('goog.labs.userAgent.util');
    -
    -goog.require('goog.string');
    -
    -
    -/**
    - * Gets the native userAgent string from navigator if it exists.
    - * If navigator or navigator.userAgent string is missing, returns an empty
    - * string.
    - * @return {string}
    - * @private
    - */
    -goog.labs.userAgent.util.getNativeUserAgentString_ = function() {
    -  var navigator = goog.labs.userAgent.util.getNavigator_();
    -  if (navigator) {
    -    var userAgent = navigator.userAgent;
    -    if (userAgent) {
    -      return userAgent;
    -    }
    -  }
    -  return '';
    -};
    -
    -
    -/**
    - * Getter for the native navigator.
    - * This is a separate function so it can be stubbed out in testing.
    - * @return {Navigator}
    - * @private
    - */
    -goog.labs.userAgent.util.getNavigator_ = function() {
    -  return goog.global.navigator;
    -};
    -
    -
    -/**
    - * A possible override for applications which wish to not check
    - * navigator.userAgent but use a specified value for detection instead.
    - * @private {string}
    - */
    -goog.labs.userAgent.util.userAgent_ =
    -    goog.labs.userAgent.util.getNativeUserAgentString_();
    -
    -
    -/**
    - * Applications may override browser detection on the built in
    - * navigator.userAgent object by setting this string. Set to null to use the
    - * browser object instead.
    - * @param {?string=} opt_userAgent The User-Agent override.
    - */
    -goog.labs.userAgent.util.setUserAgent = function(opt_userAgent) {
    -  goog.labs.userAgent.util.userAgent_ = opt_userAgent ||
    -      goog.labs.userAgent.util.getNativeUserAgentString_();
    -};
    -
    -
    -/**
    - * @return {string} The user agent string.
    - */
    -goog.labs.userAgent.util.getUserAgent = function() {
    -  return goog.labs.userAgent.util.userAgent_;
    -};
    -
    -
    -/**
    - * @param {string} str
    - * @return {boolean} Whether the user agent contains the given string, ignoring
    - *     case.
    - */
    -goog.labs.userAgent.util.matchUserAgent = function(str) {
    -  var userAgent = goog.labs.userAgent.util.getUserAgent();
    -  return goog.string.contains(userAgent, str);
    -};
    -
    -
    -/**
    - * @param {string} str
    - * @return {boolean} Whether the user agent contains the given string.
    - */
    -goog.labs.userAgent.util.matchUserAgentIgnoreCase = function(str) {
    -  var userAgent = goog.labs.userAgent.util.getUserAgent();
    -  return goog.string.caseInsensitiveContains(userAgent, str);
    -};
    -
    -
    -/**
    - * Parses the user agent into tuples for each section.
    - * @param {string} userAgent
    - * @return {!Array<!Array<string>>} Tuples of key, version, and the contents
    - *     of the parenthetical.
    - */
    -goog.labs.userAgent.util.extractVersionTuples = function(userAgent) {
    -  // Matches each section of a user agent string.
    -  // Example UA:
    -  // Mozilla/5.0 (iPad; U; CPU OS 3_2_1 like Mac OS X; en-us)
    -  // AppleWebKit/531.21.10 (KHTML, like Gecko) Mobile/7B405
    -  // This has three version tuples: Mozilla, AppleWebKit, and Mobile.
    -
    -  var versionRegExp = new RegExp(
    -      // Key. Note that a key may have a space.
    -      // (i.e. 'Mobile Safari' in 'Mobile Safari/5.0')
    -      '(\\w[\\w ]+)' +
    -
    -      '/' +                // slash
    -      '([^\\s]+)' +        // version (i.e. '5.0b')
    -      '\\s*' +             // whitespace
    -      '(?:\\((.*?)\\))?',  // parenthetical info. parentheses not matched.
    -      'g');
    -
    -  var data = [];
    -  var match;
    -
    -  // Iterate and collect the version tuples.  Each iteration will be the
    -  // next regex match.
    -  while (match = versionRegExp.exec(userAgent)) {
    -    data.push([
    -      match[1],  // key
    -      match[2],  // value
    -      // || undefined as this is not undefined in IE7 and IE8
    -      match[3] || undefined  // info
    -    ]);
    -  }
    -
    -  return data;
    -};
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/useragent/util_test.html b/src/database/third_party/closure-library/closure/goog/labs/useragent/util_test.html
    deleted file mode 100644
    index 24c6d9e3fd3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/useragent/util_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -  Author: nnaze@google.com (Nathan Naze)
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.labs.userAgent.util</title>
    -<script src="../../base.js"></script>
    -<script>
    -goog.require('goog.labs.userAgent.utilTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/labs/useragent/util_test.js b/src/database/third_party/closure-library/closure/goog/labs/useragent/util_test.js
    deleted file mode 100644
    index c6ee28c91cc..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/labs/useragent/util_test.js
    +++ /dev/null
    @@ -1,105 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file frexcept in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.labs.userAgent.engine.
    - */
    -
    -goog.provide('goog.labs.userAgent.utilTest');
    -
    -goog.require('goog.functions');
    -goog.require('goog.labs.userAgent.testAgents');
    -goog.require('goog.labs.userAgent.util');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.labs.userAgent.utilTest');
    -
    -
    -var stubs = new goog.testing.PropertyReplacer();
    -
    -function tearDown() {
    -  stubs.reset();
    -}
    -
    -
    -/**
    - * Tests parsing a few example UA strings.
    - */
    -function testExtractVersionTuples() {
    -  // Old Android
    -  var tuples = goog.labs.userAgent.util.extractVersionTuples(
    -      goog.labs.userAgent.testAgents.ANDROID_BROWSER_235);
    -
    -  assertEquals(4, tuples.length);
    -  assertSameElements(
    -      ['Mozilla', '5.0',
    -       'Linux; U; Android 2.3.5; en-us; HTC Vision Build/GRI40'], tuples[0]);
    -  assertSameElements(['AppleWebKit', '533.1', 'KHTML, like Gecko'], tuples[1]);
    -  assertSameElements(['Version', '4.0', undefined], tuples[2]);
    -  assertSameElements(['Mobile Safari', '533.1', undefined], tuples[3]);
    -
    -  // IE 9
    -  tuples = goog.labs.userAgent.util.extractVersionTuples(
    -      goog.labs.userAgent.testAgents.IE_9);
    -  assertEquals(1, tuples.length);
    -  assertSameElements(
    -      ['Mozilla', '5.0',
    -       'compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0'], tuples[0]);
    -
    -  // Opera
    -  tuples = goog.labs.userAgent.util.extractVersionTuples(
    -      goog.labs.userAgent.testAgents.OPERA_10);
    -  assertEquals(3, tuples.length);
    -  assertSameElements(['Opera', '9.80', 'S60; SymbOS; Opera Mobi/447; U; en'],
    -                     tuples[0]);
    -  assertSameElements(['Presto', '2.4.18', undefined], tuples[1]);
    -  assertSameElements(['Version', '10.00', undefined], tuples[2]);
    -}
    -
    -function testSetUserAgent() {
    -  var ua = 'Five Finger Death Punch';
    -  goog.labs.userAgent.util.setUserAgent(ua);
    -  assertEquals(ua, goog.labs.userAgent.util.getUserAgent());
    -  assertTrue(goog.labs.userAgent.util.matchUserAgent('Punch'));
    -  assertFalse(goog.labs.userAgent.util.matchUserAgent('punch'));
    -  assertFalse(goog.labs.userAgent.util.matchUserAgent('Mozilla'));
    -}
    -
    -function testSetUserAgentIgnoreCase() {
    -  var ua = 'Five Finger Death Punch';
    -  goog.labs.userAgent.util.setUserAgent(ua);
    -  assertEquals(ua, goog.labs.userAgent.util.getUserAgent());
    -  assertTrue(goog.labs.userAgent.util.matchUserAgentIgnoreCase('Punch'));
    -  assertTrue(goog.labs.userAgent.util.matchUserAgentIgnoreCase('punch'));
    -  assertFalse(goog.labs.userAgent.util.matchUserAgentIgnoreCase('Mozilla'));
    -}
    -
    -function testNoNavigator() {
    -  stubs.set(goog.labs.userAgent.util, 'getNavigator_',
    -            goog.functions.constant(undefined));
    -  assertEquals('', goog.labs.userAgent.util.getNativeUserAgentString_());
    -}
    -
    -function testNavigatorWithNoUserAgent() {
    -  stubs.set(goog.labs.userAgent.util, 'getNavigator_',
    -            goog.functions.constant(undefined));
    -  assertEquals('', goog.labs.userAgent.util.getNativeUserAgentString_());
    -}
    -
    -function testNavigatorWithUserAgent() {
    -  stubs.set(goog.labs.userAgent.util, 'getNavigator_',
    -            goog.functions.constant({'userAgent': 'moose'}));
    -  assertEquals('moose', goog.labs.userAgent.util.getNativeUserAgentString_());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/locale/countries.js b/src/database/third_party/closure-library/closure/goog/locale/countries.js
    deleted file mode 100644
    index 880a50283d3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/locale/countries.js
    +++ /dev/null
    @@ -1,291 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Current list of countries of the world. This list uses
    - * CLDR xml files for data. Algorithm is to list all country codes
    - * that are not containments (representing a group of countries) and does
    - * have a territory alias (old countries).
    - *
    - * Warning: this file is automatically generated from CLDR.
    - * Please contact i18n team or change the script and regenerate data.
    - * Code location: http://go/cldr_scripts:generate_countries
    - *
    - */
    -
    -
    -/**
    - * Namespace for current country codes.
    - */
    -goog.provide('goog.locale.countries');
    -
    -/**
    - * List of codes for countries valid today.
    - * @type {!Array<string>}
    - */
    -
    -/* ~!@# Countries #@!~ (special comment meaningful to generation script) */
    -goog.locale.countries = [
    -  'AD',
    -  'AE',
    -  'AF',
    -  'AG',
    -  'AI',
    -  'AL',
    -  'AM',
    -  'AO',
    -  'AQ',
    -  'AR',
    -  'AS',
    -  'AT',
    -  'AU',
    -  'AW',
    -  'AX',
    -  'AZ',
    -  'BA',
    -  'BB',
    -  'BD',
    -  'BE',
    -  'BF',
    -  'BG',
    -  'BH',
    -  'BI',
    -  'BJ',
    -  'BL',
    -  'BM',
    -  'BN',
    -  'BO',
    -  'BQ',
    -  'BR',
    -  'BS',
    -  'BT',
    -  'BV',
    -  'BW',
    -  'BY',
    -  'BZ',
    -  'CA',
    -  'CC',
    -  'CD',
    -  'CF',
    -  'CG',
    -  'CH',
    -  'CI',
    -  'CK',
    -  'CL',
    -  'CM',
    -  'CN',
    -  'CO',
    -  'CR',
    -  'CU',
    -  'CV',
    -  'CW',
    -  'CX',
    -  'CY',
    -  'CZ',
    -  'DE',
    -  'DJ',
    -  'DK',
    -  'DM',
    -  'DO',
    -  'DZ',
    -  'EC',
    -  'EE',
    -  'EG',
    -  'EH',
    -  'ER',
    -  'ES',
    -  'ET',
    -  'FI',
    -  'FJ',
    -  'FK',
    -  'FM',
    -  'FO',
    -  'FR',
    -  'GA',
    -  'GB',
    -  'GD',
    -  'GE',
    -  'GF',
    -  'GG',
    -  'GH',
    -  'GI',
    -  'GL',
    -  'GM',
    -  'GN',
    -  'GP',
    -  'GQ',
    -  'GR',
    -  'GS',
    -  'GT',
    -  'GU',
    -  'GW',
    -  'GY',
    -  'HK',
    -  'HM',
    -  'HN',
    -  'HR',
    -  'HT',
    -  'HU',
    -  'ID',
    -  'IE',
    -  'IL',
    -  'IM',
    -  'IN',
    -  'IO',
    -  'IQ',
    -  'IR',
    -  'IS',
    -  'IT',
    -  'JE',
    -  'JM',
    -  'JO',
    -  'JP',
    -  'KE',
    -  'KG',
    -  'KH',
    -  'KI',
    -  'KM',
    -  'KN',
    -  'KP',
    -  'KR',
    -  'KW',
    -  'KY',
    -  'KZ',
    -  'LA',
    -  'LB',
    -  'LC',
    -  'LI',
    -  'LK',
    -  'LR',
    -  'LS',
    -  'LT',
    -  'LU',
    -  'LV',
    -  'LY',
    -  'MA',
    -  'MC',
    -  'MD',
    -  'ME',
    -  'MF',
    -  'MG',
    -  'MH',
    -  'MK',
    -  'ML',
    -  'MM',
    -  'MN',
    -  'MO',
    -  'MP',
    -  'MQ',
    -  'MR',
    -  'MS',
    -  'MT',
    -  'MU',
    -  'MV',
    -  'MW',
    -  'MX',
    -  'MY',
    -  'MZ',
    -  'NA',
    -  'NC',
    -  'NE',
    -  'NF',
    -  'NG',
    -  'NI',
    -  'NL',
    -  'NO',
    -  'NP',
    -  'NR',
    -  'NU',
    -  'NZ',
    -  'OM',
    -  'PA',
    -  'PE',
    -  'PF',
    -  'PG',
    -  'PH',
    -  'PK',
    -  'PL',
    -  'PM',
    -  'PN',
    -  'PR',
    -  'PS',
    -  'PT',
    -  'PW',
    -  'PY',
    -  'QA',
    -  'RE',
    -  'RO',
    -  'RS',
    -  'RU',
    -  'RW',
    -  'SA',
    -  'SB',
    -  'SC',
    -  'SD',
    -  'SE',
    -  'SG',
    -  'SH',
    -  'SI',
    -  'SJ',
    -  'SK',
    -  'SL',
    -  'SM',
    -  'SN',
    -  'SO',
    -  'SR',
    -  'SS',
    -  'ST',
    -  'SV',
    -  'SX',
    -  'SY',
    -  'SZ',
    -  'TC',
    -  'TD',
    -  'TF',
    -  'TG',
    -  'TH',
    -  'TJ',
    -  'TK',
    -  'TL',
    -  'TM',
    -  'TN',
    -  'TO',
    -  'TR',
    -  'TT',
    -  'TV',
    -  'TW',
    -  'TZ',
    -  'UA',
    -  'UG',
    -  'UM',
    -  'US',
    -  'UY',
    -  'UZ',
    -  'VA',
    -  'VC',
    -  'VE',
    -  'VG',
    -  'VI',
    -  'VN',
    -  'VU',
    -  'WF',
    -  'WS',
    -  'YE',
    -  'YT',
    -  'ZA',
    -  'ZM',
    -  'ZW'
    -];
    -
    -/* ~!@# END #@!~ */
    diff --git a/src/database/third_party/closure-library/closure/goog/locale/countrylanguagenames_test.html b/src/database/third_party/closure-library/closure/goog/locale/countrylanguagenames_test.html
    deleted file mode 100644
    index 269e2118fe9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/locale/countrylanguagenames_test.html
    +++ /dev/null
    @@ -1,26 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.locale.LocaleNameConstants
    -  </title>
    -  <!-- UTF-8 needed for character encoding -->
    -  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.locale.countryLanguageNamesTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/locale/countrylanguagenames_test.js b/src/database/third_party/closure-library/closure/goog/locale/countrylanguagenames_test.js
    deleted file mode 100644
    index 83e66f98266..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/locale/countrylanguagenames_test.js
    +++ /dev/null
    @@ -1,231 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.locale.countryLanguageNamesTest');
    -goog.setTestOnly('goog.locale.countryLanguageNamesTest');
    -
    -goog.require('goog.locale');
    -goog.require('goog.testing.jsunit');
    -
    -var LocaleNameConstants_en;
    -
    -function setUpPage() {
    -  // Test data from //googledata/i18n/js_locale_data/LocaleNameConstants__de.js
    -  var LocaleNameConstants_de = {
    -    LANGUAGE: {
    -      'cad': 'Caddo',
    -      'fr': 'Franz\u00f6sisch',
    -      'fr_CA': 'Canadian French',
    -      'fr_CH': 'Swiss French', 'zh': 'Chinesisch',
    -      'zh_Hans': 'Chinesisch (vereinfacht)',
    -      'zh_Hant': 'Chinesisch (traditionell)'
    -    },
    -    COUNTRY: {
    -      'CN': 'China',
    -      'ES': 'Spanien',
    -      'FR': 'Frankreich'
    -    }
    -  };
    -  registerLocalNameConstants(LocaleNameConstants_de, 'de');
    -
    -  // Test data from //googledata/i18n/js_locale_data/LocaleNameConstants__en.js
    -  LocaleNameConstants_en = {
    -    LANGUAGE: {
    -      'cad': 'Caddo',
    -      'fr': 'French',
    -      'fr_CA': 'Canadian French',
    -      'fr_CH': 'Swiss French',
    -      'zh': 'Chinese',
    -      'zh_Hans': 'Simplified Chinese',
    -      'zh_Hant': 'Traditional Chinese'
    -    },
    -    COUNTRY: {
    -      'CN': 'China',
    -      'ES': 'Spain',
    -      'FR': 'France'
    -    }
    -  };
    -  registerLocalNameConstants(LocaleNameConstants_en, 'en');
    -
    -  goog.locale.setLocale('de');
    -}
    -
    -function testLoadLoacleSymbols() {
    -  var result = goog.locale.getLocalizedCountryName('fr-FR');
    -  assertEquals('Frankreich', result);
    -}
    -
    -function testGetNativeCountryName() {
    -  var result = goog.locale.getNativeCountryName('de-DE');
    -  assertEquals('Deutschland', result);
    -
    -  result = goog.locale.getNativeCountryName('de_DE');
    -  assertEquals('Deutschland', result);
    -
    -  result = goog.locale.getNativeCountryName('und');
    -  assertEquals('und', result);
    -
    -  result = goog.locale.getNativeCountryName('de-CH');
    -  assertEquals('Schweiz', result);
    -
    -  result = goog.locale.getNativeCountryName('fr-CH');
    -  assertEquals('Suisse', result);
    -
    -  result = goog.locale.getNativeCountryName('it-CH');
    -  assertEquals('Svizzera', result);
    -}
    -
    -function testGetLocalizedCountryName() {
    -  var result = goog.locale.getLocalizedCountryName('es-ES');
    -  assertEquals('Spanien', result);
    -
    -  result = goog.locale.getLocalizedCountryName('es-ES', LocaleNameConstants_en);
    -  assertEquals('Spain', result);
    -
    -  result = goog.locale.getLocalizedCountryName('zh-CN-cmn');
    -  assertEquals('China', result);
    -
    -  result = goog.locale.getLocalizedCountryName('zh_CN_cmn');
    -  assertEquals('China', result);
    -
    -  // 'und' is a non-existing locale, default behavior is to
    -  // return the locale name itself if no mapping is found.
    -  result = goog.locale.getLocalizedCountryName('und');
    -  assertEquals('und', result);
    -}
    -
    -function testGetNativeLanguageName() {
    -  var result = goog.locale.getNativeLanguageName('fr');
    -  assertEquals('fran\u00E7ais', result);
    -
    -  result = goog.locale.getNativeLanguageName('fr-latn-FR');
    -  assertEquals('fran\u00E7ais', result);
    -
    -  result = goog.locale.getNativeLanguageName('fr_FR');
    -  assertEquals('fran\u00E7ais', result);
    -
    -  result = goog.locale.getNativeLanguageName('error');
    -  assertEquals('error', result);
    -}
    -
    -function testGetLocalizedLanguageName() {
    -  var result = goog.locale.getLocalizedLanguageName('fr');
    -  assertEquals('Franz\u00F6sisch', result);
    -
    -  result = goog.locale.getLocalizedLanguageName('fr',
    -      LocaleNameConstants_en);
    -  assertEquals('French', result);
    -
    -  result = goog.locale.getLocalizedLanguageName('fr-latn-FR');
    -  assertEquals('Franz\u00F6sisch', result);
    -
    -  result = goog.locale.getLocalizedLanguageName('fr_FR');
    -  assertEquals('Franz\u00F6sisch', result);
    -
    -  result = goog.locale.getLocalizedLanguageName('cad');
    -  assertEquals('Caddo', result);
    -
    -  result = goog.locale.getLocalizedLanguageName('error');
    -  assertEquals('error', result);
    -
    -  result = goog.locale.getLocalizedLanguageName('zh_Hans',
    -      LocaleNameConstants_en);
    -  assertEquals('Simplified Chinese', result);
    -}
    -
    -
    -function testGetLocalizedLanguageNameForGivenSymbolset() {
    -  var result = goog.locale.getLocalizedCountryName('fr-FR');
    -  assertEquals('Frankreich', result);
    -
    -  result = goog.locale.getLocalizedCountryName(
    -      'fr-FR',
    -      LocaleNameConstants_en);
    -  assertEquals('France', result);
    -
    -  result = goog.locale.getLocalizedCountryName('fr-FR');
    -  assertEquals('Frankreich', result);
    -}
    -
    -/**
    - * Valid combination of sub tags:
    - *  1)  LanguageSubtag'-'RegionSubtag
    - *  2)  LanguageSubtag'-'ScriptSubtag'-'RegionSubtag
    - *  3)  LanguageSubtag'-'RegionSubtag'-'VariantSubtag
    - *  4)  LanguageSubtag'-'ScriptSubTag'-'RegionSubtag'-'VariantSubtag
    - */
    -
    -function testGetRegionSubTag() {
    -
    -  var result = goog.locale.getRegionSubTag('de-CH');
    -  assertEquals('CH', result);
    -
    -  result = goog.locale.getRegionSubTag('de-latn-CH');
    -  assertEquals('CH', result);
    -
    -  result = goog.locale.getRegionSubTag('de_latn_CH');
    -  assertEquals('CH', result);
    -
    -  result = goog.locale.getRegionSubTag('de-CH-xxx');
    -  assertEquals('CH', result);
    -
    -  result = goog.locale.getRegionSubTag('de-latn-CH-xxx');
    -  assertEquals('CH', result);
    -
    -  result = goog.locale.getRegionSubTag('es-latn-419-xxx');
    -  assertEquals('419', result);
    -
    -  result = goog.locale.getRegionSubTag('es_latn_419_xxx');
    -  assertEquals('419', result);
    -
    -  // No region sub tag present
    -  result = goog.locale.getRegionSubTag('de');
    -  assertEquals('', result);
    -}
    -
    -function testGetLanguageSubTag() {
    -
    -  var result = goog.locale.getLanguageSubTag('de');
    -  assertEquals('de', result);
    -
    -  result = goog.locale.getLanguageSubTag('de-DE');
    -  assertEquals('de', result);
    -
    -  result = goog.locale.getLanguageSubTag('de-latn-DE-xxx');
    -  assertEquals('de', result);
    -
    -  result = goog.locale.getLanguageSubTag('nds');
    -  assertEquals('nds', result);
    -
    -  result = goog.locale.getLanguageSubTag('nds-DE');
    -  assertEquals('nds', result);
    -}
    -
    -function testGetScriptSubTag() {
    -
    -  var result = goog.locale.getScriptSubTag('fr');
    -  assertEquals('', result);
    -
    -  result = goog.locale.getScriptSubTag('fr-Latn');
    -  assertEquals('Latn', result);
    -
    -  result = goog.locale.getScriptSubTag('fr-Arab-AA');
    -  assertEquals('Arab', result);
    -
    -  result = goog.locale.getScriptSubTag('de-Latin-DE');
    -  assertEquals('', result);
    -
    -  result = goog.locale.getScriptSubTag('srn-Ar-DE');
    -  assertEquals('', result);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/locale/defaultlocalenameconstants.js b/src/database/third_party/closure-library/closure/goog/locale/defaultlocalenameconstants.js
    deleted file mode 100644
    index 5a39f4b71e0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/locale/defaultlocalenameconstants.js
    +++ /dev/null
    @@ -1,940 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Default list of locale specific country and language names.
    - *
    - * Warning: this file is automatically generated from CLDR.
    - * File generated from CLDR ver. 26
    - * Please contact i18n team or change the script and regenerate data.
    - * Code location: http://go/generate_js_lang_country_constants
    - *
    - */
    -
    -/**
    - * Namespace for locale specific country and lanugage names
    - */
    -
    -goog.provide('goog.locale.defaultLocaleNameConstants');
    -
    -/**
    - * Default list of locale specific country and language names
    - */
    -
    -goog.locale.defaultLocaleNameConstants = {
    -  'COUNTRY': {
    -    '001': 'World',
    -    '002': 'Africa',
    -    '003': 'North America',
    -    '005': 'South America',
    -    '009': 'Oceania',
    -    '011': 'Western Africa',
    -    '013': 'Central America',
    -    '014': 'Eastern Africa',
    -    '015': 'Northern Africa',
    -    '017': 'Middle Africa',
    -    '018': 'Southern Africa',
    -    '019': 'Americas',
    -    '021': 'Northern America',
    -    '029': 'Caribbean',
    -    '030': 'Eastern Asia',
    -    '034': 'Southern Asia',
    -    '035': 'Southeast Asia',
    -    '039': 'Southern Europe',
    -    '053': 'Australasia',
    -    '054': 'Melanesia',
    -    '057': 'Micronesian Region',
    -    '061': 'Polynesia',
    -    '142': 'Asia',
    -    '143': 'Central Asia',
    -    '145': 'Western Asia',
    -    '150': 'Europe',
    -    '151': 'Eastern Europe',
    -    '154': 'Northern Europe',
    -    '155': 'Western Europe',
    -    '419': 'Latin America',
    -    'AC': 'Ascension Island',
    -    'AD': 'Andorra',
    -    'AE': 'United Arab Emirates',
    -    'AF': 'Afghanistan',
    -    'AG': 'Antigua & Barbuda',
    -    'AI': 'Anguilla',
    -    'AL': 'Albania',
    -    'AM': 'Armenia',
    -    'AN': 'Netherlands Antilles',
    -    'AO': 'Angola',
    -    'AQ': 'Antarctica',
    -    'AR': 'Argentina',
    -    'AS': 'American Samoa',
    -    'AT': 'Austria',
    -    'AU': 'Australia',
    -    'AW': 'Aruba',
    -    'AX': '\u00c5land Islands',
    -    'AZ': 'Azerbaijan',
    -    'BA': 'Bosnia & Herzegovina',
    -    'BB': 'Barbados',
    -    'BD': 'Bangladesh',
    -    'BE': 'Belgium',
    -    'BF': 'Burkina Faso',
    -    'BG': 'Bulgaria',
    -    'BH': 'Bahrain',
    -    'BI': 'Burundi',
    -    'BJ': 'Benin',
    -    'BL': 'St. Barth\u00e9lemy',
    -    'BM': 'Bermuda',
    -    'BN': 'Brunei',
    -    'BO': 'Bolivia',
    -    'BQ': 'Caribbean Netherlands',
    -    'BR': 'Brazil',
    -    'BS': 'Bahamas',
    -    'BT': 'Bhutan',
    -    'BV': 'Bouvet Island',
    -    'BW': 'Botswana',
    -    'BY': 'Belarus',
    -    'BZ': 'Belize',
    -    'CA': 'Canada',
    -    'CC': 'Cocos (Keeling) Islands',
    -    'CD': 'Congo (DRC)',
    -    'CF': 'Central African Republic',
    -    'CG': 'Congo (Republic)',
    -    'CH': 'Switzerland',
    -    'CI': 'C\u00f4te d\u2019Ivoire',
    -    'CK': 'Cook Islands',
    -    'CL': 'Chile',
    -    'CM': 'Cameroon',
    -    'CN': 'China',
    -    'CO': 'Colombia',
    -    'CP': 'Clipperton Island',
    -    'CR': 'Costa Rica',
    -    'CU': 'Cuba',
    -    'CV': 'Cape Verde',
    -    'CW': 'Cura\u00e7ao',
    -    'CX': 'Christmas Island',
    -    'CY': 'Cyprus',
    -    'CZ': 'Czech Republic',
    -    'DE': 'Germany',
    -    'DG': 'Diego Garcia',
    -    'DJ': 'Djibouti',
    -    'DK': 'Denmark',
    -    'DM': 'Dominica',
    -    'DO': 'Dominican Republic',
    -    'DZ': 'Algeria',
    -    'EA': 'Ceuta & Melilla',
    -    'EC': 'Ecuador',
    -    'EE': 'Estonia',
    -    'EG': 'Egypt',
    -    'EH': 'Western Sahara',
    -    'ER': 'Eritrea',
    -    'ES': 'Spain',
    -    'ET': 'Ethiopia',
    -    'EU': 'European Union',
    -    'FI': 'Finland',
    -    'FJ': 'Fiji',
    -    'FK': 'Falkland Islands (Islas Malvinas)',
    -    'FM': 'Micronesia',
    -    'FO': 'Faroe Islands',
    -    'FR': 'France',
    -    'GA': 'Gabon',
    -    'GB': 'United Kingdom',
    -    'GD': 'Grenada',
    -    'GE': 'Georgia',
    -    'GF': 'French Guiana',
    -    'GG': 'Guernsey',
    -    'GH': 'Ghana',
    -    'GI': 'Gibraltar',
    -    'GL': 'Greenland',
    -    'GM': 'Gambia',
    -    'GN': 'Guinea',
    -    'GP': 'Guadeloupe',
    -    'GQ': 'Equatorial Guinea',
    -    'GR': 'Greece',
    -    'GS': 'South Georgia & South Sandwich Islands',
    -    'GT': 'Guatemala',
    -    'GU': 'Guam',
    -    'GW': 'Guinea-Bissau',
    -    'GY': 'Guyana',
    -    'HK': 'Hong Kong',
    -    'HM': 'Heard & McDonald Islands',
    -    'HN': 'Honduras',
    -    'HR': 'Croatia',
    -    'HT': 'Haiti',
    -    'HU': 'Hungary',
    -    'IC': 'Canary Islands',
    -    'ID': 'Indonesia',
    -    'IE': 'Ireland',
    -    'IL': 'Israel',
    -    'IM': 'Isle of Man',
    -    'IN': 'India',
    -    'IO': 'British Indian Ocean Territory',
    -    'IQ': 'Iraq',
    -    'IR': 'Iran',
    -    'IS': 'Iceland',
    -    'IT': 'Italy',
    -    'JE': 'Jersey',
    -    'JM': 'Jamaica',
    -    'JO': 'Jordan',
    -    'JP': 'Japan',
    -    'KE': 'Kenya',
    -    'KG': 'Kyrgyzstan',
    -    'KH': 'Cambodia',
    -    'KI': 'Kiribati',
    -    'KM': 'Comoros',
    -    'KN': 'St. Kitts & Nevis',
    -    'KP': 'North Korea',
    -    'KR': 'South Korea',
    -    'KW': 'Kuwait',
    -    'KY': 'Cayman Islands',
    -    'KZ': 'Kazakhstan',
    -    'LA': 'Laos',
    -    'LB': 'Lebanon',
    -    'LC': 'St. Lucia',
    -    'LI': 'Liechtenstein',
    -    'LK': 'Sri Lanka',
    -    'LR': 'Liberia',
    -    'LS': 'Lesotho',
    -    'LT': 'Lithuania',
    -    'LU': 'Luxembourg',
    -    'LV': 'Latvia',
    -    'LY': 'Libya',
    -    'MA': 'Morocco',
    -    'MC': 'Monaco',
    -    'MD': 'Moldova',
    -    'ME': 'Montenegro',
    -    'MF': 'St. Martin',
    -    'MG': 'Madagascar',
    -    'MH': 'Marshall Islands',
    -    'MK': 'Macedonia (FYROM)',
    -    'ML': 'Mali',
    -    'MM': 'Myanmar (Burma)',
    -    'MN': 'Mongolia',
    -    'MO': 'Macau',
    -    'MP': 'Northern Mariana Islands',
    -    'MQ': 'Martinique',
    -    'MR': 'Mauritania',
    -    'MS': 'Montserrat',
    -    'MT': 'Malta',
    -    'MU': 'Mauritius',
    -    'MV': 'Maldives',
    -    'MW': 'Malawi',
    -    'MX': 'Mexico',
    -    'MY': 'Malaysia',
    -    'MZ': 'Mozambique',
    -    'NA': 'Namibia',
    -    'NC': 'New Caledonia',
    -    'NE': 'Niger',
    -    'NF': 'Norfolk Island',
    -    'NG': 'Nigeria',
    -    'NI': 'Nicaragua',
    -    'NL': 'Netherlands',
    -    'NO': 'Norway',
    -    'NP': 'Nepal',
    -    'NR': 'Nauru',
    -    'NU': 'Niue',
    -    'NZ': 'New Zealand',
    -    'OM': 'Oman',
    -    'PA': 'Panama',
    -    'PE': 'Peru',
    -    'PF': 'French Polynesia',
    -    'PG': 'Papua New Guinea',
    -    'PH': 'Philippines',
    -    'PK': 'Pakistan',
    -    'PL': 'Poland',
    -    'PM': 'St. Pierre & Miquelon',
    -    'PN': 'Pitcairn Islands',
    -    'PR': 'Puerto Rico',
    -    'PS': 'Palestine',
    -    'PT': 'Portugal',
    -    'PW': 'Palau',
    -    'PY': 'Paraguay',
    -    'QA': 'Qatar',
    -    'QO': 'Outlying Oceania',
    -    'RE': 'R\u00e9union',
    -    'RO': 'Romania',
    -    'RS': 'Serbia',
    -    'RU': 'Russia',
    -    'RW': 'Rwanda',
    -    'SA': 'Saudi Arabia',
    -    'SB': 'Solomon Islands',
    -    'SC': 'Seychelles',
    -    'SD': 'Sudan',
    -    'SE': 'Sweden',
    -    'SG': 'Singapore',
    -    'SH': 'St. Helena',
    -    'SI': 'Slovenia',
    -    'SJ': 'Svalbard & Jan Mayen',
    -    'SK': 'Slovakia',
    -    'SL': 'Sierra Leone',
    -    'SM': 'San Marino',
    -    'SN': 'Senegal',
    -    'SO': 'Somalia',
    -    'SR': 'Suriname',
    -    'SS': 'South Sudan',
    -    'ST': 'S\u00e3o Tom\u00e9 & Pr\u00edncipe',
    -    'SV': 'El Salvador',
    -    'SX': 'Sint Maarten',
    -    'SY': 'Syria',
    -    'SZ': 'Swaziland',
    -    'TA': 'Tristan da Cunha',
    -    'TC': 'Turks & Caicos Islands',
    -    'TD': 'Chad',
    -    'TF': 'French Southern Territories',
    -    'TG': 'Togo',
    -    'TH': 'Thailand',
    -    'TJ': 'Tajikistan',
    -    'TK': 'Tokelau',
    -    'TL': 'Timor-Leste',
    -    'TM': 'Turkmenistan',
    -    'TN': 'Tunisia',
    -    'TO': 'Tonga',
    -    'TR': 'Turkey',
    -    'TT': 'Trinidad & Tobago',
    -    'TV': 'Tuvalu',
    -    'TW': 'Taiwan',
    -    'TZ': 'Tanzania',
    -    'UA': 'Ukraine',
    -    'UG': 'Uganda',
    -    'UM': 'U.S. Outlying Islands',
    -    'US': 'United States',
    -    'UY': 'Uruguay',
    -    'UZ': 'Uzbekistan',
    -    'VA': 'Vatican City',
    -    'VC': 'St. Vincent & Grenadines',
    -    'VE': 'Venezuela',
    -    'VG': 'British Virgin Islands',
    -    'VI': 'U.S. Virgin Islands',
    -    'VN': 'Vietnam',
    -    'VU': 'Vanuatu',
    -    'WF': 'Wallis & Futuna',
    -    'WS': 'Samoa',
    -    'XK': 'Kosovo',
    -    'YE': 'Yemen',
    -    'YT': 'Mayotte',
    -    'ZA': 'South Africa',
    -    'ZM': 'Zambia',
    -    'ZW': 'Zimbabwe',
    -    'ZZ': 'Unknown Region'
    -  },
    -  'LANGUAGE': {
    -    'aa': 'Afar',
    -    'ab': 'Abkhazian',
    -    'ace': 'Achinese',
    -    'ach': 'Acoli',
    -    'ada': 'Adangme',
    -    'ady': 'Adyghe',
    -    'ae': 'Avestan',
    -    'aeb': 'Tunisian Arabic',
    -    'af': 'Afrikaans',
    -    'afh': 'Afrihili',
    -    'agq': 'Aghem',
    -    'ain': 'Ainu',
    -    'ak': 'Akan',
    -    'akk': 'Akkadian',
    -    'akz': 'Alabama',
    -    'ale': 'Aleut',
    -    'aln': 'Gheg Albanian',
    -    'alt': 'Southern Altai',
    -    'am': 'Amharic',
    -    'an': 'Aragonese',
    -    'ang': 'Old English',
    -    'anp': 'Angika',
    -    'ar': 'Arabic',
    -    'ar_001': 'Modern Standard Arabic',
    -    'arc': 'Aramaic',
    -    'arn': 'Mapuche',
    -    'aro': 'Araona',
    -    'arp': 'Arapaho',
    -    'arq': 'Algerian Arabic',
    -    'arw': 'Arawak',
    -    'ary': 'Moroccan Arabic',
    -    'arz': 'Egyptian Arabic',
    -    'as': 'Assamese',
    -    'asa': 'Asu',
    -    'ase': 'American Sign Language',
    -    'ast': 'Asturian',
    -    'av': 'Avaric',
    -    'avk': 'Kotava',
    -    'awa': 'Awadhi',
    -    'ay': 'Aymara',
    -    'az': 'Azerbaijani',
    -    'azb': 'South Azerbaijani',
    -    'ba': 'Bashkir',
    -    'bal': 'Baluchi',
    -    'ban': 'Balinese',
    -    'bar': 'Bavarian',
    -    'bas': 'Basaa',
    -    'bax': 'Bamun',
    -    'bbc': 'Batak Toba',
    -    'bbj': 'Ghomala',
    -    'be': 'Belarusian',
    -    'bej': 'Beja',
    -    'bem': 'Bemba',
    -    'bew': 'Betawi',
    -    'bez': 'Bena',
    -    'bfd': 'Bafut',
    -    'bfq': 'Badaga',
    -    'bg': 'Bulgarian',
    -    'bho': 'Bhojpuri',
    -    'bi': 'Bislama',
    -    'bik': 'Bikol',
    -    'bin': 'Bini',
    -    'bjn': 'Banjar',
    -    'bkm': 'Kom',
    -    'bla': 'Siksika',
    -    'bm': 'Bambara',
    -    'bn': 'Bengali',
    -    'bo': 'Tibetan',
    -    'bpy': 'Bishnupriya',
    -    'bqi': 'Bakhtiari',
    -    'br': 'Breton',
    -    'bra': 'Braj',
    -    'brh': 'Brahui',
    -    'brx': 'Bodo',
    -    'bs': 'Bosnian',
    -    'bss': 'Akoose',
    -    'bua': 'Buriat',
    -    'bug': 'Buginese',
    -    'bum': 'Bulu',
    -    'byn': 'Blin',
    -    'byv': 'Medumba',
    -    'ca': 'Catalan',
    -    'cad': 'Caddo',
    -    'car': 'Carib',
    -    'cay': 'Cayuga',
    -    'cch': 'Atsam',
    -    'ce': 'Chechen',
    -    'ceb': 'Cebuano',
    -    'cgg': 'Chiga',
    -    'ch': 'Chamorro',
    -    'chb': 'Chibcha',
    -    'chg': 'Chagatai',
    -    'chk': 'Chuukese',
    -    'chm': 'Mari',
    -    'chn': 'Chinook Jargon',
    -    'cho': 'Choctaw',
    -    'chp': 'Chipewyan',
    -    'chr': 'Cherokee',
    -    'chy': 'Cheyenne',
    -    'ckb': 'Sorani Kurdish',
    -    'co': 'Corsican',
    -    'cop': 'Coptic',
    -    'cps': 'Capiznon',
    -    'cr': 'Cree',
    -    'crh': 'Crimean Turkish',
    -    'cs': 'Czech',
    -    'csb': 'Kashubian',
    -    'cu': 'Church Slavic',
    -    'cv': 'Chuvash',
    -    'cy': 'Welsh',
    -    'da': 'Danish',
    -    'dak': 'Dakota',
    -    'dar': 'Dargwa',
    -    'dav': 'Taita',
    -    'de': 'German',
    -    'de_AT': 'Austrian German',
    -    'de_CH': 'Swiss High German',
    -    'del': 'Delaware',
    -    'den': 'Slave',
    -    'dgr': 'Dogrib',
    -    'din': 'Dinka',
    -    'dje': 'Zarma',
    -    'doi': 'Dogri',
    -    'dsb': 'Lower Sorbian',
    -    'dtp': 'Central Dusun',
    -    'dua': 'Duala',
    -    'dum': 'Middle Dutch',
    -    'dv': 'Divehi',
    -    'dyo': 'Jola-Fonyi',
    -    'dyu': 'Dyula',
    -    'dz': 'Dzongkha',
    -    'dzg': 'Dazaga',
    -    'ebu': 'Embu',
    -    'ee': 'Ewe',
    -    'efi': 'Efik',
    -    'egl': 'Emilian',
    -    'egy': 'Ancient Egyptian',
    -    'eka': 'Ekajuk',
    -    'el': 'Greek',
    -    'elx': 'Elamite',
    -    'en': 'English',
    -    'en_AU': 'Australian English',
    -    'en_CA': 'Canadian English',
    -    'en_GB': 'British English',
    -    'en_US': 'American English',
    -    'enm': 'Middle English',
    -    'eo': 'Esperanto',
    -    'es': 'Spanish',
    -    'es_419': 'Latin American Spanish',
    -    'es_ES': 'European Spanish',
    -    'es_MX': 'Mexican Spanish',
    -    'esu': 'Central Yupik',
    -    'et': 'Estonian',
    -    'eu': 'Basque',
    -    'ewo': 'Ewondo',
    -    'ext': 'Extremaduran',
    -    'fa': 'Persian',
    -    'fan': 'Fang',
    -    'fat': 'Fanti',
    -    'ff': 'Fulah',
    -    'fi': 'Finnish',
    -    'fil': 'Filipino',
    -    'fit': 'Tornedalen Finnish',
    -    'fj': 'Fijian',
    -    'fo': 'Faroese',
    -    'fon': 'Fon',
    -    'fr': 'French',
    -    'fr_CA': 'Canadian French',
    -    'fr_CH': 'Swiss French',
    -    'frc': 'Cajun French',
    -    'frm': 'Middle French',
    -    'fro': 'Old French',
    -    'frp': 'Arpitan',
    -    'frr': 'Northern Frisian',
    -    'frs': 'Eastern Frisian',
    -    'fur': 'Friulian',
    -    'fy': 'Western Frisian',
    -    'ga': 'Irish',
    -    'gaa': 'Ga',
    -    'gag': 'Gagauz',
    -    'gan': 'Gan Chinese',
    -    'gay': 'Gayo',
    -    'gba': 'Gbaya',
    -    'gbz': 'Zoroastrian Dari',
    -    'gd': 'Scottish Gaelic',
    -    'gez': 'Geez',
    -    'gil': 'Gilbertese',
    -    'gl': 'Galician',
    -    'glk': 'Gilaki',
    -    'gmh': 'Middle High German',
    -    'gn': 'Guarani',
    -    'goh': 'Old High German',
    -    'gom': 'Goan Konkani',
    -    'gon': 'Gondi',
    -    'gor': 'Gorontalo',
    -    'got': 'Gothic',
    -    'grb': 'Grebo',
    -    'grc': 'Ancient Greek',
    -    'gsw': 'Swiss German',
    -    'gu': 'Gujarati',
    -    'guc': 'Wayuu',
    -    'gur': 'Frafra',
    -    'guz': 'Gusii',
    -    'gv': 'Manx',
    -    'gwi': 'Gwich\u02bcin',
    -    'ha': 'Hausa',
    -    'hai': 'Haida',
    -    'hak': 'Hakka Chinese',
    -    'haw': 'Hawaiian',
    -    'he': 'Hebrew',
    -    'hi': 'Hindi',
    -    'hif': 'Fiji Hindi',
    -    'hil': 'Hiligaynon',
    -    'hit': 'Hittite',
    -    'hmn': 'Hmong',
    -    'ho': 'Hiri Motu',
    -    'hr': 'Croatian',
    -    'hsb': 'Upper Sorbian',
    -    'hsn': 'Xiang Chinese',
    -    'ht': 'Haitian',
    -    'hu': 'Hungarian',
    -    'hup': 'Hupa',
    -    'hy': 'Armenian',
    -    'hz': 'Herero',
    -    'ia': 'Interlingua',
    -    'iba': 'Iban',
    -    'ibb': 'Ibibio',
    -    'id': 'Indonesian',
    -    'ie': 'Interlingue',
    -    'ig': 'Igbo',
    -    'ii': 'Sichuan Yi',
    -    'ik': 'Inupiaq',
    -    'ilo': 'Iloko',
    -    'in': 'Indonesian',
    -    'inh': 'Ingush',
    -    'io': 'Ido',
    -    'is': 'Icelandic',
    -    'it': 'Italian',
    -    'iu': 'Inuktitut',
    -    'iw': 'Hebrew',
    -    'izh': 'Ingrian',
    -    'ja': 'Japanese',
    -    'jam': 'Jamaican Creole English',
    -    'jbo': 'Lojban',
    -    'jgo': 'Ngomba',
    -    'jmc': 'Machame',
    -    'jpr': 'Judeo-Persian',
    -    'jrb': 'Judeo-Arabic',
    -    'jut': 'Jutish',
    -    'jv': 'Javanese',
    -    'ka': 'Georgian',
    -    'kaa': 'Kara-Kalpak',
    -    'kab': 'Kabyle',
    -    'kac': 'Kachin',
    -    'kaj': 'Jju',
    -    'kam': 'Kamba',
    -    'kaw': 'Kawi',
    -    'kbd': 'Kabardian',
    -    'kbl': 'Kanembu',
    -    'kcg': 'Tyap',
    -    'kde': 'Makonde',
    -    'kea': 'Kabuverdianu',
    -    'ken': 'Kenyang',
    -    'kfo': 'Koro',
    -    'kg': 'Kongo',
    -    'kgp': 'Kaingang',
    -    'kha': 'Khasi',
    -    'kho': 'Khotanese',
    -    'khq': 'Koyra Chiini',
    -    'khw': 'Khowar',
    -    'ki': 'Kikuyu',
    -    'kiu': 'Kirmanjki',
    -    'kj': 'Kuanyama',
    -    'kk': 'Kazakh',
    -    'kkj': 'Kako',
    -    'kl': 'Kalaallisut',
    -    'kln': 'Kalenjin',
    -    'km': 'Khmer',
    -    'kmb': 'Kimbundu',
    -    'kn': 'Kannada',
    -    'ko': 'Korean',
    -    'koi': 'Komi-Permyak',
    -    'kok': 'Konkani',
    -    'kos': 'Kosraean',
    -    'kpe': 'Kpelle',
    -    'kr': 'Kanuri',
    -    'krc': 'Karachay-Balkar',
    -    'kri': 'Krio',
    -    'krj': 'Kinaray-a',
    -    'krl': 'Karelian',
    -    'kru': 'Kurukh',
    -    'ks': 'Kashmiri',
    -    'ksb': 'Shambala',
    -    'ksf': 'Bafia',
    -    'ksh': 'Colognian',
    -    'ku': 'Kurdish',
    -    'kum': 'Kumyk',
    -    'kut': 'Kutenai',
    -    'kv': 'Komi',
    -    'kw': 'Cornish',
    -    'ky': 'Kyrgyz',
    -    'la': 'Latin',
    -    'lad': 'Ladino',
    -    'lag': 'Langi',
    -    'lah': 'Lahnda',
    -    'lam': 'Lamba',
    -    'lb': 'Luxembourgish',
    -    'lez': 'Lezghian',
    -    'lfn': 'Lingua Franca Nova',
    -    'lg': 'Ganda',
    -    'li': 'Limburgish',
    -    'lij': 'Ligurian',
    -    'liv': 'Livonian',
    -    'lkt': 'Lakota',
    -    'lmo': 'Lombard',
    -    'ln': 'Lingala',
    -    'lo': 'Lao',
    -    'lol': 'Mongo',
    -    'loz': 'Lozi',
    -    'lt': 'Lithuanian',
    -    'ltg': 'Latgalian',
    -    'lu': 'Luba-Katanga',
    -    'lua': 'Luba-Lulua',
    -    'lui': 'Luiseno',
    -    'lun': 'Lunda',
    -    'luo': 'Luo',
    -    'lus': 'Mizo',
    -    'luy': 'Luyia',
    -    'lv': 'Latvian',
    -    'lzh': 'Literary Chinese',
    -    'lzz': 'Laz',
    -    'mad': 'Madurese',
    -    'maf': 'Mafa',
    -    'mag': 'Magahi',
    -    'mai': 'Maithili',
    -    'mak': 'Makasar',
    -    'man': 'Mandingo',
    -    'mas': 'Masai',
    -    'mde': 'Maba',
    -    'mdf': 'Moksha',
    -    'mdr': 'Mandar',
    -    'men': 'Mende',
    -    'mer': 'Meru',
    -    'mfe': 'Morisyen',
    -    'mg': 'Malagasy',
    -    'mga': 'Middle Irish',
    -    'mgh': 'Makhuwa-Meetto',
    -    'mgo': 'Meta\u02bc',
    -    'mh': 'Marshallese',
    -    'mi': 'Maori',
    -    'mic': 'Micmac',
    -    'min': 'Minangkabau',
    -    'mk': 'Macedonian',
    -    'ml': 'Malayalam',
    -    'mn': 'Mongolian',
    -    'mnc': 'Manchu',
    -    'mni': 'Manipuri',
    -    'moh': 'Mohawk',
    -    'mos': 'Mossi',
    -    'mr': 'Marathi',
    -    'mrj': 'Western Mari',
    -    'ms': 'Malay',
    -    'mt': 'Maltese',
    -    'mua': 'Mundang',
    -    'mul': 'Multiple Languages',
    -    'mus': 'Creek',
    -    'mwl': 'Mirandese',
    -    'mwr': 'Marwari',
    -    'mwv': 'Mentawai',
    -    'my': 'Burmese',
    -    'mye': 'Myene',
    -    'myv': 'Erzya',
    -    'mzn': 'Mazanderani',
    -    'na': 'Nauru',
    -    'nan': 'Min Nan Chinese',
    -    'nap': 'Neapolitan',
    -    'naq': 'Nama',
    -    'nb': 'Norwegian Bokm\u00e5l',
    -    'nd': 'North Ndebele',
    -    'nds': 'Low German',
    -    'ne': 'Nepali',
    -    'new': 'Newari',
    -    'ng': 'Ndonga',
    -    'nia': 'Nias',
    -    'niu': 'Niuean',
    -    'njo': 'Ao Naga',
    -    'nl': 'Dutch',
    -    'nl_BE': 'Flemish',
    -    'nmg': 'Kwasio',
    -    'nn': 'Norwegian Nynorsk',
    -    'nnh': 'Ngiemboon',
    -    'no': 'Norwegian',
    -    'nog': 'Nogai',
    -    'non': 'Old Norse',
    -    'nov': 'Novial',
    -    'nqo': 'N\u02bcKo',
    -    'nr': 'South Ndebele',
    -    'nso': 'Northern Sotho',
    -    'nus': 'Nuer',
    -    'nv': 'Navajo',
    -    'nwc': 'Classical Newari',
    -    'ny': 'Nyanja',
    -    'nym': 'Nyamwezi',
    -    'nyn': 'Nyankole',
    -    'nyo': 'Nyoro',
    -    'nzi': 'Nzima',
    -    'oc': 'Occitan',
    -    'oj': 'Ojibwa',
    -    'om': 'Oromo',
    -    'or': 'Oriya',
    -    'os': 'Ossetic',
    -    'osa': 'Osage',
    -    'ota': 'Ottoman Turkish',
    -    'pa': 'Punjabi',
    -    'pag': 'Pangasinan',
    -    'pal': 'Pahlavi',
    -    'pam': 'Pampanga',
    -    'pap': 'Papiamento',
    -    'pau': 'Palauan',
    -    'pcd': 'Picard',
    -    'pdc': 'Pennsylvania German',
    -    'pdt': 'Plautdietsch',
    -    'peo': 'Old Persian',
    -    'pfl': 'Palatine German',
    -    'phn': 'Phoenician',
    -    'pi': 'Pali',
    -    'pl': 'Polish',
    -    'pms': 'Piedmontese',
    -    'pnt': 'Pontic',
    -    'pon': 'Pohnpeian',
    -    'prg': 'Prussian',
    -    'pro': 'Old Proven\u00e7al',
    -    'ps': 'Pashto',
    -    'pt': 'Portuguese',
    -    'pt_BR': 'Brazilian Portuguese',
    -    'pt_PT': 'European Portuguese',
    -    'qu': 'Quechua',
    -    'quc': 'K\u02bciche\u02bc',
    -    'qug': 'Chimborazo Highland Quichua',
    -    'raj': 'Rajasthani',
    -    'rap': 'Rapanui',
    -    'rar': 'Rarotongan',
    -    'rgn': 'Romagnol',
    -    'rif': 'Riffian',
    -    'rm': 'Romansh',
    -    'rn': 'Rundi',
    -    'ro': 'Romanian',
    -    'ro_MD': 'Moldavian',
    -    'rof': 'Rombo',
    -    'rom': 'Romany',
    -    'root': 'Root',
    -    'rtm': 'Rotuman',
    -    'ru': 'Russian',
    -    'rue': 'Rusyn',
    -    'rug': 'Roviana',
    -    'rup': 'Aromanian',
    -    'rw': 'Kinyarwanda',
    -    'rwk': 'Rwa',
    -    'sa': 'Sanskrit',
    -    'sad': 'Sandawe',
    -    'sah': 'Sakha',
    -    'sam': 'Samaritan Aramaic',
    -    'saq': 'Samburu',
    -    'sas': 'Sasak',
    -    'sat': 'Santali',
    -    'saz': 'Saurashtra',
    -    'sba': 'Ngambay',
    -    'sbp': 'Sangu',
    -    'sc': 'Sardinian',
    -    'scn': 'Sicilian',
    -    'sco': 'Scots',
    -    'sd': 'Sindhi',
    -    'sdc': 'Sassarese Sardinian',
    -    'se': 'Northern Sami',
    -    'see': 'Seneca',
    -    'seh': 'Sena',
    -    'sei': 'Seri',
    -    'sel': 'Selkup',
    -    'ses': 'Koyraboro Senni',
    -    'sg': 'Sango',
    -    'sga': 'Old Irish',
    -    'sgs': 'Samogitian',
    -    'sh': 'Serbo-Croatian',
    -    'shi': 'Tachelhit',
    -    'shn': 'Shan',
    -    'shu': 'Chadian Arabic',
    -    'si': 'Sinhala',
    -    'sid': 'Sidamo',
    -    'sk': 'Slovak',
    -    'sl': 'Slovenian',
    -    'sli': 'Lower Silesian',
    -    'sly': 'Selayar',
    -    'sm': 'Samoan',
    -    'sma': 'Southern Sami',
    -    'smj': 'Lule Sami',
    -    'smn': 'Inari Sami',
    -    'sms': 'Skolt Sami',
    -    'sn': 'Shona',
    -    'snk': 'Soninke',
    -    'so': 'Somali',
    -    'sog': 'Sogdien',
    -    'sq': 'Albanian',
    -    'sr': 'Serbian',
    -    'srn': 'Sranan Tongo',
    -    'srr': 'Serer',
    -    'ss': 'Swati',
    -    'ssy': 'Saho',
    -    'st': 'Southern Sotho',
    -    'stq': 'Saterland Frisian',
    -    'su': 'Sundanese',
    -    'suk': 'Sukuma',
    -    'sus': 'Susu',
    -    'sux': 'Sumerian',
    -    'sv': 'Swedish',
    -    'sw': 'Swahili',
    -    'swb': 'Comorian',
    -    'swc': 'Congo Swahili',
    -    'syc': 'Classical Syriac',
    -    'syr': 'Syriac',
    -    'szl': 'Silesian',
    -    'ta': 'Tamil',
    -    'tcy': 'Tulu',
    -    'te': 'Telugu',
    -    'tem': 'Timne',
    -    'teo': 'Teso',
    -    'ter': 'Tereno',
    -    'tet': 'Tetum',
    -    'tg': 'Tajik',
    -    'th': 'Thai',
    -    'ti': 'Tigrinya',
    -    'tig': 'Tigre',
    -    'tiv': 'Tiv',
    -    'tk': 'Turkmen',
    -    'tkl': 'Tokelau',
    -    'tkr': 'Tsakhur',
    -    'tl': 'Tagalog',
    -    'tlh': 'Klingon',
    -    'tli': 'Tlingit',
    -    'tly': 'Talysh',
    -    'tmh': 'Tamashek',
    -    'tn': 'Tswana',
    -    'to': 'Tongan',
    -    'tog': 'Nyasa Tonga',
    -    'tpi': 'Tok Pisin',
    -    'tr': 'Turkish',
    -    'tru': 'Turoyo',
    -    'trv': 'Taroko',
    -    'ts': 'Tsonga',
    -    'tsd': 'Tsakonian',
    -    'tsi': 'Tsimshian',
    -    'tt': 'Tatar',
    -    'ttt': 'Muslim Tat',
    -    'tum': 'Tumbuka',
    -    'tvl': 'Tuvalu',
    -    'tw': 'Twi',
    -    'twq': 'Tasawaq',
    -    'ty': 'Tahitian',
    -    'tyv': 'Tuvinian',
    -    'tzm': 'Central Atlas Tamazight',
    -    'udm': 'Udmurt',
    -    'ug': 'Uyghur',
    -    'uga': 'Ugaritic',
    -    'uk': 'Ukrainian',
    -    'umb': 'Umbundu',
    -    'und': 'Unknown Language',
    -    'ur': 'Urdu',
    -    'uz': 'Uzbek',
    -    'vai': 'Vai',
    -    've': 'Venda',
    -    'vec': 'Venetian',
    -    'vep': 'Veps',
    -    'vi': 'Vietnamese',
    -    'vls': 'West Flemish',
    -    'vmf': 'Main-Franconian',
    -    'vo': 'Volap\u00fck',
    -    'vot': 'Votic',
    -    'vro': 'V\u00f5ro',
    -    'vun': 'Vunjo',
    -    'wa': 'Walloon',
    -    'wae': 'Walser',
    -    'wal': 'Wolaytta',
    -    'war': 'Waray',
    -    'was': 'Washo',
    -    'wo': 'Wolof',
    -    'wuu': 'Wu Chinese',
    -    'xal': 'Kalmyk',
    -    'xh': 'Xhosa',
    -    'xmf': 'Mingrelian',
    -    'xog': 'Soga',
    -    'yao': 'Yao',
    -    'yap': 'Yapese',
    -    'yav': 'Yangben',
    -    'ybb': 'Yemba',
    -    'yi': 'Yiddish',
    -    'yo': 'Yoruba',
    -    'yrl': 'Nheengatu',
    -    'yue': 'Cantonese',
    -    'za': 'Zhuang',
    -    'zap': 'Zapotec',
    -    'zbl': 'Blissymbols',
    -    'zea': 'Zeelandic',
    -    'zen': 'Zenaga',
    -    'zgh': 'Standard Moroccan Tamazight',
    -    'zh': 'Chinese',
    -    'zh_Hans': 'Simplified Chinese',
    -    'zh_Hant': 'Traditional Chinese',
    -    'zu': 'Zulu',
    -    'zun': 'Zuni',
    -    'zxx': 'No linguistic content',
    -    'zza': 'Zaza'
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/locale/genericfontnames.js b/src/database/third_party/closure-library/closure/goog/locale/genericfontnames.js
    deleted file mode 100644
    index 49d124aee9c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/locale/genericfontnames.js
    +++ /dev/null
    @@ -1,73 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Functions to list locale-specific font list and generic name.
    - * Generic name used for a font family would be locale dependant. For example,
    - * for 'zh'(Chinese) users, the name for Serif family would be in Chinese.
    - * Further documentation at: http://go/genericfontnames.
    - */
    -
    -goog.provide('goog.locale.genericFontNames');
    -
    -
    -/**
    - * This object maps (resourceName, localeName) to a resourceObj.
    - * @type {Object}
    - * @private
    - */
    -goog.locale.genericFontNames.data_ = {};
    -
    -
    -/**
    - * Normalizes the given locale id to standard form. eg: zh_Hant_TW.
    - * Many a times, input locale would be like: zh-tw, zh-hant-tw.
    - * @param {string} locale The locale id to be normalized.
    - * @return {string} Normalized locale id.
    - * @private
    - */
    -goog.locale.genericFontNames.normalize_ = function(locale) {
    -  locale = locale.replace(/-/g, '_');
    -  locale = locale.replace(/_[a-z]{2}$/,
    -      function(str) {
    -        return str.toUpperCase();
    -      });
    -
    -  locale = locale.replace(/[a-z]{4}/,
    -      function(str) {
    -        return str.substring(0, 1).toUpperCase() +
    -               str.substring(1);
    -      });
    -  return locale;
    -};
    -
    -
    -/**
    - * Gets the list of fonts and their generic names for the given locale.
    - * @param {string} locale The locale for which font lists and font family names
    - *     to be produced. The expected locale id is as described in
    - *     http://wiki/Main/IIISynonyms in all lowercase for easy matching.
    - *     Smallest possible id is expected.
    - *     Examples: 'zh', 'zh-tw', 'iw' instead of 'zh-CN', 'zh-Hant-TW', 'he'.
    - * @return {Array<Object>} List of objects with generic name as 'caption' and
    - *     corresponding font name lists as 'value' property.
    - */
    -goog.locale.genericFontNames.getList = function(locale) {
    -
    -  locale = goog.locale.genericFontNames.normalize_(locale);
    -  if (locale in goog.locale.genericFontNames.data_) {
    -    return goog.locale.genericFontNames.data_[locale];
    -  }
    -  return [];
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/locale/genericfontnames_test.html b/src/database/third_party/closure-library/closure/goog/locale/genericfontnames_test.html
    deleted file mode 100644
    index 26e9bdeaac9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/locale/genericfontnames_test.html
    +++ /dev/null
    @@ -1,26 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.locale.genericFontNames
    -  </title>
    -  <!-- UTF-8 needed for character encoding -->
    -  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.locale.genericFontNamesTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/locale/genericfontnames_test.js b/src/database/third_party/closure-library/closure/goog/locale/genericfontnames_test.js
    deleted file mode 100644
    index 6bd99c9e606..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/locale/genericfontnames_test.js
    +++ /dev/null
    @@ -1,93 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.locale.genericFontNamesTest');
    -goog.setTestOnly('goog.locale.genericFontNamesTest');
    -
    -goog.require('goog.locale.genericFontNames');
    -goog.require('goog.testing.jsunit');
    -
    -goog.locale.genericFontNames.data_['zh_TW'] = [
    -  {
    -    'caption': '\u5fae\u8edf\u6b63\u9ed1\u9ad4',
    -    'value': 'Microsoft JhengHei,\u5fae\u8edf\u6b63\u9ed1\u9ad4,SimHei,' +
    -        '\u9ed1\u4f53,MS Hei,STHeiti,\u534e\u6587\u9ed1\u4f53,Apple ' +
    -        'LiGothic Medium,\u860b\u679c\u5137\u4e2d\u9ed1,LiHei Pro Medium,' +
    -        '\u5137\u9ed1 Pro,STHeiti Light,\u534e\u6587\u7ec6\u9ed1,AR PL ' +
    -        'ZenKai Uni,\u6587\u9f0ePL\u4e2d\u6977Uni,FreeSans,sans-serif'
    -  },
    -  {
    -    'caption': '\u5fae\u8f6f\u96c5\u9ed1\u5b57\u4f53',
    -    'value': 'Microsoft YaHei,\u5fae\u8f6f\u96c5\u9ed1\u5b57\u4f53,FreeSans,' +
    -        'sans-serif'
    -  },
    -  {
    -    'caption': '\u65b0\u7d30\u660e\u9ad4',
    -    'value': 'SimSun,\u5b8b\u4f53,MS Song,STSong,\u534e\u6587\u5b8b\u4f53,' +
    -        'Apple LiSung Light,\u860b\u679c\u5137\u7d30\u5b8b,LiSong Pro Light,' +
    -        '\u5137\u5b8b Pro,STFangSong,\u534e\u6587\u4eff\u5b8b,AR PL ' +
    -        'ShanHeiSun Uni,\u6587\u9f0eP' +
    -        'L\u7ec6\u4e0a\u6d77\u5b8bUni,AR PL New Sung,\u6587\u9f0e PL \u65b0' +
    -        '\u5b8b,FreeSerif,serif'
    -  },
    -  {
    -    'caption': '\u7d30\u660e\u9ad4',
    -    'value': 'NSimsun,\u65b0\u5b8b\u4f53,FreeMono,monospace'
    -  }
    -];
    -
    -function testNormalize() {
    -  var result = goog.locale.genericFontNames.normalize_('zh');
    -  assertEquals('zh', result);
    -  var result = goog.locale.genericFontNames.normalize_('zh-hant');
    -  assertEquals('zh_Hant', result);
    -  var result = goog.locale.genericFontNames.normalize_('zh-hant-tw');
    -  assertEquals('zh_Hant_TW', result);
    -}
    -
    -function testInvalid() {
    -  var result = goog.locale.genericFontNames.getList('invalid');
    -  assertArrayEquals([], result);
    -}
    -
    -function testZhHant() {
    -  var result = goog.locale.genericFontNames.getList('zh-tw');
    -  assertObjectEquals([
    -    {
    -      'caption': '\u5fae\u8edf\u6b63\u9ed1\u9ad4',
    -      'value': 'Microsoft JhengHei,\u5fae\u8edf\u6b63\u9ed1\u9ad4,SimHei,' +
    -          '\u9ed1\u4f53,MS Hei,STHeiti,\u534e\u6587\u9ed1\u4f53,Apple ' +
    -          'LiGothic Medium,\u860b\u679c\u5137\u4e2d\u9ed1,LiHei Pro Medium,' +
    -          '\u5137\u9ed1 Pro,STHeiti Light,\u534e\u6587\u7ec6\u9ed1,AR PL ' +
    -          'ZenKai Uni,\u6587\u9f0ePL\u4e2d\u6977Uni,FreeSans,sans-serif'
    -    },
    -    {
    -      'caption': '\u5fae\u8f6f\u96c5\u9ed1\u5b57\u4f53',
    -      'value': 'Microsoft YaHei,\u5fae\u8f6f\u96c5\u9ed1\u5b57\u4f53,' +
    -          'FreeSans,sans-serif'
    -    },
    -    {
    -      'caption': '\u65b0\u7d30\u660e\u9ad4',
    -      'value': 'SimSun,\u5b8b\u4f53,MS Song,STSong,\u534e\u6587\u5b8b\u4f53,' +
    -          'Apple LiSung Light,\u860b\u679c\u5137\u7d30\u5b8b,LiSong Pro ' +
    -          'Light,\u5137\u5b8b Pro,STFangSong,\u534e\u6587\u4eff\u5b8b,AR PL ' +
    -          'ShanHeiSun Uni,\u6587\u9f0ePL\u7ec6\u4e0a\u6d77\u5b8bUni,AR PL New' +
    -          ' Sung,\u6587\u9f0e PL \u65b0\u5b8b,FreeSerif,serif'
    -    },
    -    {
    -      'caption': '\u7d30\u660e\u9ad4',
    -      'value': 'NSimsun,\u65b0\u5b8b\u4f53,FreeMono,monospace'
    -    }],
    -  result);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/locale/genericfontnamesdata.js b/src/database/third_party/closure-library/closure/goog/locale/genericfontnamesdata.js
    deleted file mode 100644
    index 0b2e211f2da..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/locale/genericfontnamesdata.js
    +++ /dev/null
    @@ -1,327 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview List of generic font names and font fallbacks.
    - * This file lists the font fallback for each font family for each locale or
    - * script. In this map, each value is an array of pair. The pair is stored
    - * as an array of two elements.
    - *
    - * First element of the pair is the generic name
    - * for the font family in that locale. In case of script indexed entries,
    - * It will be just font family name. Second element in the pair is a string
    - * comma seperated list of font names. API to access this data is provided
    - * thru goog.locale.genericFontNames.
    - *
    - * Warning: this file is automatically generated from CLDR.
    - * Please contact i18n team or change the script and regenerate data.
    - * Code location: http://go/generate_genericfontnames
    - *
    - */
    -
    -
    -/**
    - * Namespace for Generic Font Names
    - */
    -goog.provide('goog.locale.genericFontNamesData');
    -
    -
    -/**
    - * Map from script code or language code to list of pairs of (generic name,
    - * font name fallback list).
    - * @const {!Object<string, !Array<!Array<string>>>}
    - */
    -
    -/* ~!@# genmethods.genericFontNamesData() #@!~ */
    -goog.locale.genericFontNamesData = {
    -  'Arab': [
    -    [
    -      'sans-serif',
    -      'Arial,Al Bayan'
    -    ],
    -    [
    -      'serif',
    -      'Arabic Typesetting,Times New Roman'
    -    ]
    -  ],
    -  'Armn': [[
    -    'serif',
    -    'Sylfaen,Mshtakan'
    -  ]],
    -  'Beng': [[
    -    'sans-serif',
    -    'Vrinda,Lohit Bengali'
    -  ]],
    -  'Cans': [[
    -    'sans-serif',
    -    'Euphemia,Euphemia UCAS'
    -  ]],
    -  'Cher': [[
    -    'serif',
    -    'Plantagenet,Plantagenet Cherokee'
    -  ]],
    -  'Deva': [
    -    [
    -      'sans-serif',
    -      'Mangal,Lohit Hindi'
    -    ],
    -    [
    -      'serif',
    -      'Arial Unicode MS,Devanagari'
    -    ]
    -  ],
    -  'Ethi': [[
    -    'serif',
    -    'Nyala'
    -  ]],
    -  'Geor': [[
    -    'serif',
    -    'Sylfaen'
    -  ]],
    -  'Gujr': [
    -    [
    -      'sans-serif',
    -      'Shruti,Lohit Gujarati'
    -    ],
    -    [
    -      'serif',
    -      'Gujarati'
    -    ]
    -  ],
    -  'Guru': [
    -    [
    -      'sans-serif',
    -      'Raavi,Lohit Punjabi'
    -    ],
    -    [
    -      'serif',
    -      'Gurmukhi'
    -    ]
    -  ],
    -  'Hebr': [
    -    [
    -      'sans-serif',
    -      'Gisha,Aharoni,Arial Hebrew'
    -    ],
    -    [
    -      'serif',
    -      'David'
    -    ],
    -    [
    -      'monospace',
    -      'Miriam Fixed'
    -    ]
    -  ],
    -  'Khmr': [
    -    [
    -      'sans-serif',
    -      'MoolBoran,Khmer OS'
    -    ],
    -    [
    -      'serif',
    -      'DaunPenh'
    -    ]
    -  ],
    -  'Knda': [
    -    [
    -      'sans-serif',
    -      'Tunga'
    -    ],
    -    [
    -      'serif',
    -      'Kedage'
    -    ]
    -  ],
    -  'Laoo': [[
    -    'sans-serif',
    -    'DokChampa,Phetsarath OT'
    -  ]],
    -  'Mlym': [
    -    [
    -      'sans-serif',
    -      'AnjaliOldLipi,Kartika'
    -    ],
    -    [
    -      'serif',
    -      'Rachana'
    -    ]
    -  ],
    -  'Mong': [[
    -    'serif',
    -    'Mongolian Baiti'
    -  ]],
    -  'Nkoo': [[
    -    'serif',
    -    'Conakry'
    -  ]],
    -  'Orya': [[
    -    'sans-serif',
    -    'Kalinga,utkal'
    -  ]],
    -  'Sinh': [[
    -    'serif',
    -    'Iskoola Pota,Malithi Web'
    -  ]],
    -  'Syrc': [[
    -    'sans-serif',
    -    'Estrangelo Edessa'
    -  ]],
    -  'Taml': [
    -    [
    -      'sans-serif',
    -      'Latha,Lohit Tamil'
    -    ],
    -    [
    -      'serif',
    -      'Inai Mathi'
    -    ]
    -  ],
    -  'Telu': [
    -    [
    -      'sans-serif',
    -      'Gautami'
    -    ],
    -    [
    -      'serif',
    -      'Pothana'
    -    ]
    -  ],
    -  'Thaa': [[
    -    'sans-serif',
    -    'MV Boli'
    -  ]],
    -  'Thai': [
    -    [
    -      'sans-serif',
    -      'Tahoma,Thonburi'
    -    ],
    -    [
    -      'monospace',
    -      'Tahoma,Ayuthaya'
    -    ]
    -  ],
    -  'Tibt': [[
    -    'serif',
    -    'Microsoft Himalaya'
    -  ]],
    -  'Yiii': [[
    -    'sans-serif',
    -    'Microsoft Yi Baiti'
    -  ]],
    -  'Zsym': [[
    -    'sans-serif',
    -    'Apple Symbols'
    -  ]],
    -  'jp': [
    -    [
    -      '\uff30\u30b4\u30b7\u30c3\u30af',
    -      'MS PGothic,\uff2d\uff33 \uff30\u30b4\u30b7\u30c3\u30af,Hiragino Kaku G' +
    -     'othic Pro,\u30d2\u30e9\u30ae\u30ce\u89d2\u30b4 Pro W3,Sazanami Gothic' +
    -     ',\u3055\u3056\u306a\u307f\u30b4\u30b7\u30c3\u30af,sans-serif'
    -    ],
    -    [
    -      '\u30e1\u30a4\u30ea\u30aa',
    -      'Meiryo,\u30e1\u30a4\u30ea\u30aa,sans-serif'
    -    ],
    -    [
    -      '\uff30\u660e\u671d',
    -      'MS PMincho,\uff2d\uff33 \uff30\u660e\u671d,Hiragino Mincho Pro,\u30d2' +
    -     '\u30e9\u30ae\u30ce\u660e\u671d Pro W3,Sazanami Mincho,\u3055\u3056' +
    -     '\u306a\u307f\u660e\u671d,serif'
    -    ],
    -    [
    -      '\u7b49\u5e45',
    -      'MS Gothic,\uff2d\uff33 \u30b4\u30b7\u30c3\u30af,Osaka-Mono,Osaka\uff0d' +
    -     '\u7b49\u5e45,monospace'
    -    ]
    -  ],
    -  'ko': [
    -    [
    -      '\uace0\ub515',
    -      'Gulim,\uad74\ub9bc,AppleGothic,\uc560\ud50c\uace0\ub515,UnDotum,\uc740' +
    -     ' \ub3cb\uc6c0,Baekmuk Gulim,\ubc31\ubb35 \uad74\ub9bc,sans-serif'
    -    ],
    -    [
    -      '\ub9d1\uc740\uace0\ub515',
    -      'Malgun Gothic,\ub9d1\uc740\uace0\ub515,sans-serif'
    -    ],
    -    [
    -      '\ubc14\ud0d5',
    -      'Batang,\ubc14\ud0d5,AppleMyungjo,\uc560\ud50c\uba85\uc870,UnBatang,' +
    -     '\uc740 \ubc14\ud0d5,Baekmuk Batang,\ubc31\ubb35 \ubc14\ud0d5,serif'
    -    ],
    -    [
    -      '\uad81\uc11c',
    -      'Gungseo,\uad81\uc11c,serif'
    -    ],
    -    [
    -      '\uace0\uc815\ud3ed',
    -      'GulimChe,\uad74\ub9bc\uccb4,AppleGothic,\uc560\ud50c\uace0\ub515,monos' +
    -     'pace'
    -    ]
    -  ],
    -  'root': [
    -    [
    -      'sans-serif',
    -      'FreeSans'
    -    ],
    -    [
    -      'serif',
    -      'FreeSerif'
    -    ],
    -    [
    -      'monospace',
    -      'FreeMono'
    -    ]
    -  ],
    -  'transpose': {
    -    'zh': {
    -      'zh_Hant': {
    -        '\u5b8b\u4f53': '\u65b0\u7d30\u660e\u9ad4',
    -        '\u9ed1\u4f53': '\u5fae\u8edf\u6b63\u9ed1\u9ad4'
    -      }
    -    }
    -  },
    -  'ug': [[
    -    'serif',
    -    'Microsoft Uighur'
    -  ]],
    -  'zh': [
    -    [
    -      '\u9ed1\u4f53',
    -      'Microsoft JhengHei,\u5fae\u8edf\u6b63\u9ed1\u9ad4,SimHei,\u9ed1\u4f53,' +
    -     'MS Hei,STHeiti,\u534e\u6587\u9ed1\u4f53,Apple LiGothic Medium,\u860b' +
    -     '\u679c\u5137\u4e2d\u9ed1,LiHei Pro Medium,\u5137\u9ed1 Pro,STHeiti Li' +
    -     'ght,\u534e\u6587\u7ec6\u9ed1,AR PL ZenKai Uni,\u6587\u9f0ePL\u4e2d' +
    -     '\u6977Uni,sans-serif'
    -    ],
    -    [
    -      '\u5fae\u8f6f\u96c5\u9ed1\u5b57\u4f53',
    -      'Microsoft YaHei,\u5fae\u8f6f\u96c5\u9ed1\u5b57\u4f53,sans-serif'
    -    ],
    -    [
    -      '\u5b8b\u4f53',
    -      'SimSun,\u5b8b\u4f53,MS Song,STSong,\u534e\u6587\u5b8b\u4f53,Apple LiSu' +
    -     'ng Light,\u860b\u679c\u5137\u7d30\u5b8b,LiSong Pro Light,\u5137\u5b8b' +
    -     ' Pro,STFangSong,\u534e\u6587\u4eff\u5b8b,AR PL ShanHeiSun Uni,\u6587' +
    -     '\u9f0ePL\u7ec6\u4e0a\u6d77\u5b8bUni,AR PL New Sung,\u6587\u9f0e PL ' +
    -     '\u65b0\u5b8b,serif'
    -    ],
    -    [
    -      '\u7d30\u660e\u9ad4',
    -      'NSimsun,\u65b0\u5b8b\u4f53,monospace'
    -    ]
    -  ]
    -};
    -/* ~!@# END #@!~ */
    diff --git a/src/database/third_party/closure-library/closure/goog/locale/locale.js b/src/database/third_party/closure-library/closure/goog/locale/locale.js
    deleted file mode 100644
    index 5763b4ed7a6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/locale/locale.js
    +++ /dev/null
    @@ -1,403 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Functions for dealing with Date formatting & Parsing,
    - * County and language name, TimeZone list.
    - * @suppress {deprecated} Use goog.i18n instead.
    - */
    -
    -
    -/**
    - * Namespace for locale related functions.
    - */
    -goog.provide('goog.locale');
    -
    -goog.require('goog.locale.nativeNameConstants');
    -
    -
    -/**
    - * Set currnet locale to the specified one.
    - * @param {string} localeName Locale name string. We are following the usage
    - *     in CLDR, but can make a few compromise for existing name compatibility.
    - */
    -goog.locale.setLocale = function(localeName) {
    -  // it is common to see people use '-' as locale part separator, normalize it.
    -  localeName = localeName.replace(/-/g, '_');
    -  goog.locale.activeLocale_ = localeName;
    -};
    -
    -
    -/**
    - * Retrieve the current locale
    - * @return {string} Current locale name string.
    - * @deprecated Use goog.LOCALE and goog.i18n instead.
    - */
    -goog.locale.getLocale = function() {
    -  if (!goog.locale.activeLocale_) {
    -    goog.locale.activeLocale_ = 'en';
    -  }
    -  return goog.locale.activeLocale_;
    -};
    -
    -
    -// Couple of constants to represent predefined Date/Time format type.
    -/**
    - * Enum of resources that can be registered.
    - * @enum {string}
    - */
    -goog.locale.Resource = {
    -  DATE_TIME_CONSTANTS: 'DateTimeConstants',
    -  NUMBER_FORMAT_CONSTANTS: 'NumberFormatConstants',
    -  TIME_ZONE_CONSTANTS: 'TimeZoneConstants',
    -  LOCAL_NAME_CONSTANTS: 'LocaleNameConstants',
    -
    -  TIME_ZONE_SELECTED_IDS: 'TimeZoneSelectedIds',
    -  TIME_ZONE_SELECTED_SHORT_NAMES: 'TimeZoneSelectedShortNames',
    -  TIME_ZONE_SELECTED_LONG_NAMES: 'TimeZoneSelectedLongNames',
    -  TIME_ZONE_ALL_LONG_NAMES: 'TimeZoneAllLongNames'
    -};
    -
    -
    -// BCP 47 language code:
    -//
    -// LanguageCode := LanguageSubtag
    -//                ("-" ScriptSubtag)?
    -//                ("-" RegionSubtag)?
    -//                ("-" VariantSubtag)?
    -//                ("@" Keyword "=" Value ("," Keyword "=" Value)* )?
    -//
    -// e.g. en-Latn-GB
    -//
    -// NOTICE:
    -// No special format checking is performed. If you pass a none valid
    -// language code as parameter to the following functions,
    -// you might get an unexpected result.
    -
    -
    -/**
    - * Returns the language-subtag of the given language code.
    - *
    - * @param {string} languageCode Language code to extract language subtag from.
    - * @return {string} Language subtag (in lowercase).
    - */
    -goog.locale.getLanguageSubTag = function(languageCode) {
    -  var result = languageCode.match(/^\w{2,3}([-_]|$)/);
    -  return result ? result[0].replace(/[_-]/g, '') : '';
    -};
    -
    -
    -/**
    - * Returns the region-sub-tag of the given language code.
    - *
    - * @param {string} languageCode Language code to extract region subtag from.
    - * @return {string} Region sub-tag (in uppercase).
    - */
    -goog.locale.getRegionSubTag = function(languageCode) {
    -  var result = languageCode.match(/[-_]([a-zA-Z]{2}|\d{3})([-_]|$)/);
    -  return result ? result[0].replace(/[_-]/g, '') : '';
    -};
    -
    -
    -/**
    - * Returns the script subtag of the locale with the first alphabet in uppercase
    - * and the rest 3 characters in lower case.
    - *
    - * @param {string} languageCode Language Code to extract script subtag from.
    - * @return {string} Script subtag.
    - */
    -goog.locale.getScriptSubTag = function(languageCode) {
    -  var result = languageCode.split(/[-_]/g);
    -  return result.length > 1 && result[1].match(/^[a-zA-Z]{4}$/) ?
    -      result[1] : '';
    -};
    -
    -
    -/**
    - * Returns the variant-sub-tag of the given language code.
    - *
    - * @param {string} languageCode Language code to extract variant subtag from.
    - * @return {string} Variant sub-tag.
    - */
    -goog.locale.getVariantSubTag = function(languageCode) {
    -  var result = languageCode.match(/[-_]([a-z]{2,})/);
    -  return result ? result[1] : '';
    -};
    -
    -
    -/**
    - * Returns the country name of the provided language code in its native
    - * language.
    - *
    - * This method depends on goog.locale.nativeNameConstants available from
    - * nativenameconstants.js. User of this method has to add dependency to this.
    - *
    - * @param {string} countryCode Code to lookup the country name for.
    - *
    - * @return {string} Country name for the provided language code.
    - */
    -goog.locale.getNativeCountryName = function(countryCode) {
    -  var key = goog.locale.getLanguageSubTag(countryCode) + '_' +
    -            goog.locale.getRegionSubTag(countryCode);
    -  return key in goog.locale.nativeNameConstants['COUNTRY'] ?
    -      goog.locale.nativeNameConstants['COUNTRY'][key] : countryCode;
    -};
    -
    -
    -/**
    - * Returns the localized country name for the provided language code in the
    - * current or provided locale symbols set.
    - *
    - * This method depends on goog.locale.LocaleNameConstants__<locale> available
    - * from http://go/js_locale_data. User of this method has to add dependency to
    - * this.
    - *
    - * @param {string} languageCode Language code to lookup the country name for.
    - * @param {Object=} opt_localeSymbols If omitted the current locale symbol
    - *     set is used.
    - *
    - * @return {string} Localized country name.
    - */
    -goog.locale.getLocalizedCountryName = function(languageCode,
    -                                               opt_localeSymbols) {
    -  if (!opt_localeSymbols) {
    -    opt_localeSymbols = goog.locale.getResource('LocaleNameConstants',
    -        goog.locale.getLocale());
    -  }
    -  var code = goog.locale.getRegionSubTag(languageCode);
    -  return code in opt_localeSymbols['COUNTRY'] ?
    -      opt_localeSymbols['COUNTRY'][code] : languageCode;
    -};
    -
    -
    -/**
    - * Returns the language name of the provided language code in its native
    - * language.
    - *
    - * This method depends on goog.locale.nativeNameConstants available from
    - * nativenameconstants.js. User of this method has to add dependency to this.
    - *
    - * @param {string} languageCode Language code to lookup the language name for.
    - *
    - * @return {string} Language name for the provided language code.
    - */
    -goog.locale.getNativeLanguageName = function(languageCode) {
    -  if (languageCode in goog.locale.nativeNameConstants['LANGUAGE'])
    -    return goog.locale.nativeNameConstants['LANGUAGE'][languageCode];
    -  var code = goog.locale.getLanguageSubTag(languageCode);
    -  return code in goog.locale.nativeNameConstants['LANGUAGE'] ?
    -      goog.locale.nativeNameConstants['LANGUAGE'][code] : languageCode;
    -};
    -
    -
    -/**
    - * Returns the localized language name for the provided language code in
    - * the current or provided locale symbols set.
    - *
    - * This method depends on goog.locale.LocaleNameConstants__<locale> available
    - * from http://go/js_locale_data. User of this method has to add dependency to
    - * this.
    - *
    - * @param {string} languageCode Language code to lookup the language name for.
    - * @param {Object=} opt_localeSymbols locale symbol set if given.
    - *
    - * @return {string} Localized language name of the provided language code.
    - */
    -goog.locale.getLocalizedLanguageName = function(languageCode,
    -                                                opt_localeSymbols) {
    -  if (!opt_localeSymbols) {
    -    opt_localeSymbols = goog.locale.getResource('LocaleNameConstants',
    -        goog.locale.getLocale());
    -  }
    -  if (languageCode in opt_localeSymbols['LANGUAGE'])
    -    return opt_localeSymbols['LANGUAGE'][languageCode];
    -  var code = goog.locale.getLanguageSubTag(languageCode);
    -  return code in opt_localeSymbols['LANGUAGE'] ?
    -      opt_localeSymbols['LANGUAGE'][code] : languageCode;
    -};
    -
    -
    -/**
    - * Register a resource object for certain locale.
    - * @param {Object} dataObj The resource object being registered.
    - * @param {goog.locale.Resource|string} resourceName String that represents
    - *     the type of resource.
    - * @param {string} localeName Locale ID.
    - */
    -goog.locale.registerResource = function(dataObj, resourceName, localeName) {
    -  if (!goog.locale.resourceRegistry_[resourceName]) {
    -    goog.locale.resourceRegistry_[resourceName] = {};
    -  }
    -  goog.locale.resourceRegistry_[resourceName][localeName] = dataObj;
    -  // the first registered locale becomes active one. Usually there will be
    -  // only one locale per js binary bundle.
    -  if (!goog.locale.activeLocale_) {
    -    goog.locale.activeLocale_ = localeName;
    -  }
    -};
    -
    -
    -/**
    - * Returns true if the required resource has already been registered.
    - * @param {goog.locale.Resource|string} resourceName String that represents
    - *     the type of resource.
    - * @param {string} localeName Locale ID.
    - * @return {boolean} Whether the required resource has already been registered.
    - */
    -goog.locale.isResourceRegistered = function(resourceName, localeName) {
    -  return resourceName in goog.locale.resourceRegistry_ &&
    -      localeName in goog.locale.resourceRegistry_[resourceName];
    -};
    -
    -
    -/**
    - * This object maps (resourceName, localeName) to a resourceObj.
    - * @type {Object}
    - * @private
    - */
    -goog.locale.resourceRegistry_ = {};
    -
    -
    -/**
    - * Registers the timezone constants object for a given locale name.
    - * @param {Object} dataObj The resource object.
    - * @param {string} localeName Locale ID.
    - * @deprecated Use goog.i18n.TimeZone, no longer need this.
    - */
    -goog.locale.registerTimeZoneConstants = function(dataObj, localeName) {
    -  goog.locale.registerResource(
    -      dataObj, goog.locale.Resource.TIME_ZONE_CONSTANTS, localeName);
    -};
    -
    -
    -/**
    - * Registers the LocaleNameConstants constants object for a given locale name.
    - * @param {Object} dataObj The resource object.
    - * @param {string} localeName Locale ID.
    - */
    -goog.locale.registerLocaleNameConstants = function(dataObj, localeName) {
    -  goog.locale.registerResource(
    -      dataObj, goog.locale.Resource.LOCAL_NAME_CONSTANTS, localeName);
    -};
    -
    -
    -/**
    - * Registers the TimeZoneSelectedIds constants object for a given locale name.
    - * @param {Object} dataObj The resource object.
    - * @param {string} localeName Locale ID.
    - */
    -goog.locale.registerTimeZoneSelectedIds = function(dataObj, localeName) {
    -  goog.locale.registerResource(
    -      dataObj, goog.locale.Resource.TIME_ZONE_SELECTED_IDS, localeName);
    -};
    -
    -
    -/**
    - * Registers the TimeZoneSelectedShortNames constants object for a given
    - *     locale name.
    - * @param {Object} dataObj The resource object.
    - * @param {string} localeName Locale ID.
    - */
    -goog.locale.registerTimeZoneSelectedShortNames = function(dataObj, localeName) {
    -  goog.locale.registerResource(
    -      dataObj, goog.locale.Resource.TIME_ZONE_SELECTED_SHORT_NAMES, localeName);
    -};
    -
    -
    -/**
    - * Registers the TimeZoneSelectedLongNames constants object for a given locale
    - *     name.
    - * @param {Object} dataObj The resource object.
    - * @param {string} localeName Locale ID.
    - */
    -goog.locale.registerTimeZoneSelectedLongNames = function(dataObj, localeName) {
    -  goog.locale.registerResource(
    -      dataObj, goog.locale.Resource.TIME_ZONE_SELECTED_LONG_NAMES, localeName);
    -};
    -
    -
    -/**
    - * Registers the TimeZoneAllLongNames constants object for a given locale name.
    - * @param {Object} dataObj The resource object.
    - * @param {string} localeName Locale ID.
    - */
    -goog.locale.registerTimeZoneAllLongNames = function(dataObj, localeName) {
    -  goog.locale.registerResource(
    -      dataObj, goog.locale.Resource.TIME_ZONE_ALL_LONG_NAMES, localeName);
    -};
    -
    -
    -/**
    - * Retrieve specified resource for certain locale.
    - * @param {string} resourceName String that represents the type of resource.
    - * @param {string=} opt_locale Locale ID, if not given, current locale
    - *     will be assumed.
    - * @return {Object|undefined} The resource object that hold all the resource
    - *     data, or undefined if not available.
    - */
    -goog.locale.getResource = function(resourceName, opt_locale) {
    -  var locale = opt_locale ? opt_locale : goog.locale.getLocale();
    -
    -  if (!(resourceName in goog.locale.resourceRegistry_)) {
    -    return undefined;
    -  }
    -  return goog.locale.resourceRegistry_[resourceName][locale];
    -};
    -
    -
    -/**
    - * Retrieve specified resource for certain locale with fallback. For example,
    - * request of 'zh_CN' will be resolved in following order: zh_CN, zh, en.
    - * If none of the above succeeds, of if the resource as indicated by
    - * resourceName does not exist at all, undefined will be returned.
    - *
    - * @param {string} resourceName String that represents the type of resource.
    - * @param {string=} opt_locale locale ID, if not given, current locale
    - *     will be assumed.
    - * @return {Object|undefined} The resource object for desired locale.
    - */
    -goog.locale.getResourceWithFallback = function(resourceName, opt_locale) {
    -  var locale = opt_locale ? opt_locale : goog.locale.getLocale();
    -
    -  if (!(resourceName in goog.locale.resourceRegistry_)) {
    -    return undefined;
    -  }
    -
    -  if (locale in goog.locale.resourceRegistry_[resourceName]) {
    -    return goog.locale.resourceRegistry_[resourceName][locale];
    -  }
    -
    -  // if locale has multiple parts (2 atmost in reality), fallback to base part.
    -  var locale_parts = locale.split('_');
    -  if (locale_parts.length > 1 &&
    -      locale_parts[0] in goog.locale.resourceRegistry_[resourceName]) {
    -    return goog.locale.resourceRegistry_[resourceName][locale_parts[0]];
    -  }
    -
    -  // otherwise, fallback to 'en'
    -  return goog.locale.resourceRegistry_[resourceName]['en'];
    -};
    -
    -
    -// Export global functions that are used by the date time constants files.
    -// See http://go/js_locale_data
    -var registerLocalNameConstants = goog.locale.registerLocaleNameConstants;
    -
    -var registerTimeZoneSelectedIds = goog.locale.registerTimeZoneSelectedIds;
    -var registerTimeZoneSelectedShortNames =
    -    goog.locale.registerTimeZoneSelectedShortNames;
    -var registerTimeZoneSelectedLongNames =
    -    goog.locale.registerTimeZoneSelectedLongNames;
    -var registerTimeZoneAllLongNames = goog.locale.registerTimeZoneAllLongNames;
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/locale/nativenameconstants.js b/src/database/third_party/closure-library/closure/goog/locale/nativenameconstants.js
    deleted file mode 100644
    index c5171016350..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/locale/nativenameconstants.js
    +++ /dev/null
    @@ -1,1354 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview list of native country and language names.
    - *
    - * Warning: this file is automatically generated from CLDR.
    - * Please contact i18n team or change the script and regenerate data.
    - * Code location: http://go/generate_js_native_names.py
    - *
    - */
    -
    -
    -/**
    - * Namespace for native country and lanugage names
    - */
    -goog.provide('goog.locale.nativeNameConstants');
    -
    -/**
    - * Native country and language names
    - * @const {!Object<string, !Object<string, string>>}
    - */
    -
    -/* ~!@# genmethods.NativeDictAsJson() #@!~ */
    -goog.locale.nativeNameConstants = {
    -  'COUNTRY': {
    -    'AD': 'Andorra',
    -    'AE': '\u0627\u0644\u0627\u0645\u0627\u0631\u0627\u062a \u0627' +
    -        '\u0644\u0639\u0631\u0628\u064a\u0629 \u0627\u0644' +
    -        '\u0645\u062a\u062d\u062f\u0629',
    -    'AF': '\u0627\u0641\u063a\u0627\u0646\u0633\u062a\u0627\u0646',
    -    'AG': 'Antigua and Barbuda',
    -    'AI': 'Anguilla',
    -    'AL': 'Shqip\u00ebria',
    -    'AM': '\u0540\u0561\u0575\u0561\u057d\u057f\u0561\u0576\u056b ' +
    -        '\u0540\u0561\u0576\u0580\u0561\u057a\u0565\u057f\u0578' +
    -        '\u0582\u0569\u056b\u0582\u0576',
    -    'AN': 'Nederlandse Antillen',
    -    'AO': 'Angola',
    -    'AQ': 'Antarctica',
    -    'AR': 'Argentina',
    -    'AS': 'American Samoa',
    -    'AT': '\u00d6sterreich',
    -    'AU': 'Australia',
    -    'AW': 'Aruba',
    -    'AX': '\u00c5land',
    -    'AZ': 'Az\u0259rbaycan',
    -    'BA': 'Bosna i Hercegovina',
    -    'BB': 'Barbados',
    -    'BD': '\u09ac\u09be\u0982\u09b2\u09be\u09a6\u09c7\u09b6',
    -    'BE': 'Belgi\u00eb',
    -    'BF': 'Burkina Faso',
    -    'BG': '\u0411\u044a\u043b\u0433\u0430\u0440\u0438\u044f',
    -    'BH': '\u0627\u0644\u0628\u062d\u0631\u064a\u0646',
    -    'BI': 'Burundi',
    -    'BJ': 'B\u00e9nin',
    -    'BM': 'Bermuda',
    -    'BN': 'Brunei',
    -    'BO': 'Bolivia',
    -    'BR': 'Brasil',
    -    'BS': 'Bahamas',
    -    'BT': '\u092d\u0942\u091f\u093e\u0928',
    -    'BV': 'Bouvet Island',
    -    'BW': 'Botswana',
    -    'BY': '\u0411\u0435\u043b\u0430\u0440\u0443\u0441\u044c',
    -    'BZ': 'Belize',
    -    'CA': 'Canada',
    -    'CC': 'Cocos (Keeling) Islands',
    -    'CD': 'R\u00e9publique d\u00e9mocratique du Congo',
    -    'CF': 'R\u00e9publique centrafricaine',
    -    'CG': 'Congo',
    -    'CH': 'Schweiz',
    -    'CI': 'C\u00f4te d\u2019Ivoire',
    -    'CK': 'Cook Islands',
    -    'CL': 'Chile',
    -    'CM': 'Cameroun',
    -    'CN': '\u4e2d\u56fd',
    -    'CO': 'Colombia',
    -    'CR': 'Costa Rica',
    -    'CS': 'Serbia and Montenegro',
    -    'CU': 'Cuba',
    -    'CV': 'Cabo Verde',
    -    'CX': 'Christmas Island',
    -    'CY': '\u039a\u03cd\u03c0\u03c1\u03bf\u03c2',
    -    'CZ': '\u010cesk\u00e1 republika',
    -    'DD': 'East Germany',
    -    'DE': 'Deutschland',
    -    'DJ': 'Jabuuti',
    -    'DK': 'Danmark',
    -    'DM': 'Dominica',
    -    'DO': 'Rep\u00fablica Dominicana',
    -    'DZ': '\u0627\u0644\u062c\u0632\u0627\u0626\u0631',
    -    'EC': 'Ecuador',
    -    'EE': 'Eesti',
    -    'EG': '\u0645\u0635\u0631',
    -    'EH': '\u0627\u0644\u0635\u062d\u0631\u0627\u0621 \u0627\u0644' +
    -        '\u063a\u0631\u0628\u064a\u0629',
    -    'ER': '\u0627\u0631\u064a\u062a\u0631\u064a\u0627',
    -    'ES': 'Espa\u00f1a',
    -    'ET': '\u12a2\u1275\u12ee\u1335\u12eb',
    -    'FI': 'Suomi',
    -    'FJ': '\u092b\u093f\u091c\u0940',
    -    'FK': 'Falkland Islands',
    -    'FM': 'Micronesia',
    -    'FO': 'F\u00f8royar',
    -    'FR': 'France',
    -    'FX': 'Metropolitan France',
    -    'GA': 'Gabon',
    -    'GB': 'United Kingdom',
    -    'GD': 'Grenada',
    -    'GE': '\u10e1\u10d0\u10e5\u10d0\u10e0\u10d7\u10d5\u10d4\u10da' +
    -        '\u10dd',
    -    'GF': 'Guyane fran\u00e7aise',
    -    'GG': 'Guernsey',
    -    'GH': 'Ghana',
    -    'GI': 'Gibraltar',
    -    'GL': 'Kalaallit Nunaat',
    -    'GM': 'Gambia',
    -    'GN': 'Guin\u00e9e',
    -    'GP': 'Guadeloupe',
    -    'GQ': 'Guin\u00e9e \u00e9quatoriale',
    -    'GR': '\u0395\u03bb\u03bb\u03ac\u03b4\u03b1',
    -    'GS': 'South Georgia and the South Sandwich Islands',
    -    'GT': 'Guatemala',
    -    'GU': 'Guam',
    -    'GW': 'Guin\u00e9 Bissau',
    -    'GY': 'Guyana',
    -    'HK': '\u9999\u6e2f',
    -    'HM': 'Heard Island and McDonald Islands',
    -    'HN': 'Honduras',
    -    'HR': 'Hrvatska',
    -    'HT': 'Ha\u00efti',
    -    'HU': 'Magyarorsz\u00e1g',
    -    'ID': 'Indonesia',
    -    'IE': 'Ireland',
    -    'IL': '\u05d9\u05e9\u05e8\u05d0\u05dc',
    -    'IM': 'Isle of Man',
    -    'IN': '\u092d\u093e\u0930\u0924',
    -    'IO': 'British Indian Ocean Territory',
    -    'IQ': '\u0627\u0644\u0639\u0631\u0627\u0642',
    -    'IR': '\u0627\u06cc\u0631\u0627\u0646',
    -    'IS': '\u00cdsland',
    -    'IT': 'Italia',
    -    'JE': 'Jersey',
    -    'JM': 'Jamaica',
    -    'JO': '\u0627\u0644\u0623\u0631\u062f\u0646',
    -    'JP': '\u65e5\u672c',
    -    'KE': 'Kenya',
    -    'KG': '\u041a\u044b\u0440\u0433\u044b\u0437\u0441\u0442\u0430' +
    -        '\u043d',
    -    'KH': '\u1780\u1798\u17d2\u1796\u17bb\u1787\u17b6',
    -    'KI': 'Kiribati',
    -    'KM': '\u062c\u0632\u0631 \u0627\u0644\u0642\u0645\u0631',
    -    'KN': 'Saint Kitts and Nevis',
    -    'KP': '\uc870\uc120 \ubbfc\uc8fc\uc8fc\uc758 \uc778\ubbfc ' +
    -        '\uacf5\ud654\uad6d',
    -    'KR': '\ub300\ud55c\ubbfc\uad6d',
    -    'KW': '\u0627\u0644\u0643\u0648\u064a\u062a',
    -    'KY': 'Cayman Islands',
    -    'KZ': '\u041a\u0430\u0437\u0430\u0445\u0441\u0442\u0430\u043d',
    -    'LA': '\u0e25\u0e32\u0e27',
    -    'LB': '\u0644\u0628\u0646\u0627\u0646',
    -    'LC': 'Saint Lucia',
    -    'LI': 'Liechtenstein',
    -    'LK': '\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8',
    -    'LR': 'Liberia',
    -    'LS': 'Lesotho',
    -    'LT': 'Lietuva',
    -    'LU': 'Luxembourg',
    -    'LV': 'Latvija',
    -    'LY': '\u0644\u064a\u0628\u064a\u0627',
    -    'MA': '\u0627\u0644\u0645\u063a\u0631\u0628',
    -    'MC': 'Monaco',
    -    'MD': 'Moldova, Republica',
    -    'ME': '\u0426\u0440\u043d\u0430 \u0413\u043e\u0440\u0430',
    -    'MG': 'Madagascar',
    -    'MH': 'Marshall Islands',
    -    'MK': '\u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0438\u0458' +
    -        '\u0430',
    -    'ML': '\u0645\u0627\u0644\u064a',
    -    'MM': 'Myanmar',
    -    'MN': '\u8499\u53e4',
    -    'MO': '\u6fb3\u95e8',
    -    'MP': 'Northern Mariana Islands',
    -    'MQ': 'Martinique',
    -    'MR': '\u0645\u0648\u0631\u064a\u062a\u0627\u0646\u064a\u0627',
    -    'MS': 'Montserrat',
    -    'MT': 'Malta',
    -    'MU': 'Mauritius',
    -    'MV': 'Maldives',
    -    'MW': 'Malawi',
    -    'MX': 'M\u00e9xico',
    -    'MY': 'Malaysia',
    -    'MZ': 'Mo\u00e7ambique',
    -    'NA': 'Namibia',
    -    'NC': 'Nouvelle-Cal\u00e9donie',
    -    'NE': 'Niger',
    -    'NF': 'Norfolk Island',
    -    'NG': 'Nigeria',
    -    'NI': 'Nicaragua',
    -    'NL': 'Nederland',
    -    'NO': 'Norge',
    -    'NP': '\u0928\u0947\u092a\u093e\u0932',
    -    'NR': 'Nauru',
    -    'NT': 'Neutral Zone',
    -    'NU': 'Niue',
    -    'NZ': 'New Zealand',
    -    'OM': '\u0639\u0645\u0627\u0646',
    -    'PA': 'Panam\u00e1',
    -    'PE': 'Per\u00fa',
    -    'PF': 'Polyn\u00e9sie fran\u00e7aise',
    -    'PG': 'Papua New Guinea',
    -    'PH': 'Philippines',
    -    'PK': '\u067e\u0627\u06a9\u0633\u062a\u0627\u0646',
    -    'PL': 'Polska',
    -    'PM': 'Saint-Pierre-et-Miquelon',
    -    'PN': 'Pitcairn',
    -    'PR': 'Puerto Rico',
    -    'PS': '\u0641\u0644\u0633\u0637\u064a\u0646',
    -    'PT': 'Portugal',
    -    'PW': 'Palau',
    -    'PY': 'Paraguay',
    -    'QA': '\u0642\u0637\u0631',
    -    'QO': 'Outlying Oceania',
    -    'QU': 'European Union',
    -    'RE': 'R\u00e9union',
    -    'RO': 'Rom\u00e2nia',
    -    'RS': '\u0421\u0440\u0431\u0438\u0458\u0430',
    -    'RU': '\u0420\u043e\u0441\u0441\u0438\u044f',
    -    'RW': 'Rwanda',
    -    'SA': '\u0627\u0644\u0645\u0645\u0644\u0643\u0629 \u0627\u0644' +
    -        '\u0639\u0631\u0628\u064a\u0629 \u0627\u0644\u0633' +
    -        '\u0639\u0648\u062f\u064a\u0629',
    -    'SB': 'Solomon Islands',
    -    'SC': 'Seychelles',
    -    'SD': '\u0627\u0644\u0633\u0648\u062f\u0627\u0646',
    -    'SE': 'Sverige',
    -    'SG': '\u65b0\u52a0\u5761',
    -    'SH': 'Saint Helena',
    -    'SI': 'Slovenija',
    -    'SJ': 'Svalbard og Jan Mayen',
    -    'SK': 'Slovensk\u00e1 republika',
    -    'SL': 'Sierra Leone',
    -    'SM': 'San Marino',
    -    'SN': 'S\u00e9n\u00e9gal',
    -    'SO': 'Somali',
    -    'SR': 'Suriname',
    -    'ST': 'S\u00e3o Tom\u00e9 e Pr\u00edncipe',
    -    'SU': 'Union of Soviet Socialist Republics',
    -    'SV': 'El Salvador',
    -    'SY': '\u0633\u0648\u0631\u064a\u0627',
    -    'SZ': 'Swaziland',
    -    'TC': 'Turks and Caicos Islands',
    -    'TD': '\u062a\u0634\u0627\u062f',
    -    'TF': 'French Southern Territories',
    -    'TG': 'Togo',
    -    'TH': '\u0e1b\u0e23\u0e30\u0e40\u0e17\u0e28\u0e44\u0e17\u0e22',
    -    'TJ': '\u062a\u0627\u062c\u06cc\u06a9\u0633\u062a\u0627\u0646',
    -    'TK': 'Tokelau',
    -    'TL': 'Timor Leste',
    -    'TM': '\u0422\u0443\u0440\u043a\u043c\u0435\u043d\u0438\u0441' +
    -        '\u0442\u0430\u043d',
    -    'TN': '\u062a\u0648\u0646\u0633',
    -    'TO': 'Tonga',
    -    'TR': 'T\u00fcrkiye',
    -    'TT': 'Trinidad y Tobago',
    -    'TV': 'Tuvalu',
    -    'TW': '\u53f0\u6e7e',
    -    'TZ': 'Tanzania',
    -    'UA': '\u0423\u043a\u0440\u0430\u0457\u043d\u0430',
    -    'UG': 'Uganda',
    -    'UM': 'United States Minor Outlying Islands',
    -    'US': 'United States',
    -    'UY': 'Uruguay',
    -    'UZ': '\u040e\u0437\u0431\u0435\u043a\u0438\u0441\u0442\u043e' +
    -        '\u043d',
    -    'VA': 'Vaticano',
    -    'VC': 'Saint Vincent and the Grenadines',
    -    'VE': 'Venezuela',
    -    'VG': 'British Virgin Islands',
    -    'VI': 'U.S. Virgin Islands',
    -    'VN': 'Vi\u1ec7t Nam',
    -    'VU': 'Vanuatu',
    -    'WF': 'Wallis-et-Futuna',
    -    'WS': 'Samoa',
    -    'YD': 'People\'s Democratic Republic of Yemen',
    -    'YE': '\u0627\u0644\u064a\u0645\u0646',
    -    'YT': 'Mayotte',
    -    'ZA': 'South Africa',
    -    'ZM': 'Zambia',
    -    'ZW': 'Zimbabwe',
    -    'ZZ': 'Unknown or Invalid Region',
    -    'aa_DJ': 'Jabuuti',
    -    'aa_ER': '\u00c9rythr\u00e9e',
    -    'aa_ER_SAAHO': '\u00c9rythr\u00e9e',
    -    'aa_ET': 'Itoophiyaa',
    -    'af_NA': 'Namibi\u00eb',
    -    'af_ZA': 'Suid-Afrika',
    -    'ak_GH': 'Ghana',
    -    'am_ET': '\u12a2\u1275\u12ee\u1335\u12eb',
    -    'ar_AE': '\u0627\u0644\u0627\u0645\u0627\u0631\u0627\u062a ' +
    -        '\u0627\u0644\u0639\u0631\u0628\u064a\u0629 \u0627' +
    -        '\u0644\u0645\u062a\u062d\u062f\u0629',
    -    'ar_BH': '\u0627\u0644\u0628\u062d\u0631\u064a\u0646',
    -    'ar_DJ': '\u062c\u064a\u0628\u0648\u062a\u064a',
    -    'ar_DZ': '\u0627\u0644\u062c\u0632\u0627\u0626\u0631',
    -    'ar_EG': '\u0645\u0635\u0631',
    -    'ar_EH': '\u0627\u0644\u0635\u062d\u0631\u0627\u0621 \u0627' +
    -        '\u0644\u063a\u0631\u0628\u064a\u0629',
    -    'ar_ER': '\u0627\u0631\u064a\u062a\u0631\u064a\u0627',
    -    'ar_IL': '\u0627\u0633\u0631\u0627\u0626\u064a\u0644',
    -    'ar_IQ': '\u0627\u0644\u0639\u0631\u0627\u0642',
    -    'ar_JO': '\u0627\u0644\u0623\u0631\u062f\u0646',
    -    'ar_KM': '\u062c\u0632\u0631 \u0627\u0644\u0642\u0645\u0631',
    -    'ar_KW': '\u0627\u0644\u0643\u0648\u064a\u062a',
    -    'ar_LB': '\u0644\u0628\u0646\u0627\u0646',
    -    'ar_LY': '\u0644\u064a\u0628\u064a\u0627',
    -    'ar_MA': '\u0627\u0644\u0645\u063a\u0631\u0628',
    -    'ar_MR': '\u0645\u0648\u0631\u064a\u062a\u0627\u0646\u064a' +
    -        '\u0627',
    -    'ar_OM': '\u0639\u0645\u0627\u0646',
    -    'ar_PS': '\u0641\u0644\u0633\u0637\u064a\u0646',
    -    'ar_QA': '\u0642\u0637\u0631',
    -    'ar_SA': '\u0627\u0644\u0645\u0645\u0644\u0643\u0629 \u0627' +
    -        '\u0644\u0639\u0631\u0628\u064a\u0629 \u0627\u0644' +
    -        '\u0633\u0639\u0648\u062f\u064a\u0629',
    -    'ar_SD': '\u0627\u0644\u0633\u0648\u062f\u0627\u0646',
    -    'ar_SY': '\u0633\u0648\u0631\u064a\u0627',
    -    'ar_TD': '\u062a\u0634\u0627\u062f',
    -    'ar_TN': '\u062a\u0648\u0646\u0633',
    -    'ar_YE': '\u0627\u0644\u064a\u0645\u0646',
    -    'as_IN': '\u09ad\u09be\u09f0\u09a4',
    -    'ay_BO': 'Bolivia',
    -    'az_AZ': 'Az\u0259rbaycan',
    -    'az_Cyrl_AZ': '\u0410\u0437\u04d9\u0440\u0431\u0430\u0458' +
    -        '\u04b9\u0430\u043d',
    -    'az_Latn_AZ': 'Azerbaycan',
    -    'be_BY': '\u0411\u0435\u043b\u0430\u0440\u0443\u0441\u044c',
    -    'bg_BG': '\u0411\u044a\u043b\u0433\u0430\u0440\u0438\u044f',
    -    'bi_VU': 'Vanuatu',
    -    'bn_BD': '\u09ac\u09be\u0982\u09b2\u09be\u09a6\u09c7\u09b6',
    -    'bn_IN': '\u09ad\u09be\u09b0\u09a4',
    -    'bo_CN': '\u0f62\u0f92\u0fb1\u0f0b\u0f53\u0f42',
    -    'bo_IN': '\u0f62\u0f92\u0fb1\u0f0b\u0f42\u0f62\u0f0b',
    -    'bs_BA': 'Bosna i Hercegovina',
    -    'byn_ER': '\u12a4\u122d\u1275\u122b',
    -    'ca_AD': 'Andorra',
    -    'ca_ES': 'Espanya',
    -    'cch_NG': 'Nigeria',
    -    'ch_GU': 'Guam',
    -    'chk_FM': 'Micronesia',
    -    'cop_Arab_EG': '\u0645\u0635\u0631',
    -    'cop_Arab_US': '\u0627\u0644\u0648\u0644\u0627\u064a\u0627' +
    -        '\u062a \u0627\u0644\u0645\u062a\u062d\u062f' +
    -        '\u0629 \u0627\u0644\u0623\u0645\u0631\u064a' +
    -        '\u0643\u064a\u0629',
    -    'cop_EG': '\u0645\u0635\u0631',
    -    'cop_US': '\u0627\u0644\u0648\u0644\u0627\u064a\u0627\u062a ' +
    -        '\u0627\u0644\u0645\u062a\u062d\u062f\u0629 \u0627' +
    -        '\u0644\u0623\u0645\u0631\u064a\u0643\u064a\u0629',
    -    'cs_CZ': '\u010cesk\u00e1 republika',
    -    'cy_GB': 'Prydain Fawr',
    -    'da_DK': 'Danmark',
    -    'da_GL': 'Gr\u00f8nland',
    -    'de_AT': '\u00d6sterreich',
    -    'de_BE': 'Belgien',
    -    'de_CH': 'Schweiz',
    -    'de_DE': 'Deutschland',
    -    'de_LI': 'Liechtenstein',
    -    'de_LU': 'Luxemburg',
    -    'dv_MV': 'Maldives',
    -    'dz_BT': 'Bhutan',
    -    'ee_GH': 'Ghana',
    -    'ee_TG': 'Togo',
    -    'efi_NG': 'Nigeria',
    -    'el_CY': '\u039a\u03cd\u03c0\u03c1\u03bf\u03c2',
    -    'el_GR': '\u0395\u03bb\u03bb\u03ac\u03b4\u03b1',
    -    'en_AG': 'Antigua and Barbuda',
    -    'en_AI': 'Anguilla',
    -    'en_AS': 'American Samoa',
    -    'en_AU': 'Australia',
    -    'en_BB': 'Barbados',
    -    'en_BE': 'Belgium',
    -    'en_BM': 'Bermuda',
    -    'en_BS': 'Bahamas',
    -    'en_BW': 'Botswana',
    -    'en_BZ': 'Belize',
    -    'en_CA': 'Canada',
    -    'en_CC': 'Cocos Islands',
    -    'en_CK': 'Cook Islands',
    -    'en_CM': 'Cameroon',
    -    'en_CX': 'Christmas Island',
    -    'en_DM': 'Dominica',
    -    'en_FJ': 'Fiji',
    -    'en_FK': 'Falkland Islands',
    -    'en_FM': 'Micronesia',
    -    'en_GB': 'United Kingdom',
    -    'en_GD': 'Grenada',
    -    'en_GG': 'Guernsey',
    -    'en_GH': 'Ghana',
    -    'en_GI': 'Gibraltar',
    -    'en_GM': 'Gambia',
    -    'en_GU': 'Guam',
    -    'en_GY': 'Guyana',
    -    'en_HK': 'Hong Kong',
    -    'en_HN': 'Honduras',
    -    'en_IE': 'Ireland',
    -    'en_IM': 'Isle of Man',
    -    'en_IN': 'India',
    -    'en_JE': 'Jersey',
    -    'en_JM': 'Jamaica',
    -    'en_KE': 'Kenya',
    -    'en_KI': 'Kiribati',
    -    'en_KN': 'Saint Kitts and Nevis',
    -    'en_KY': 'Cayman Islands',
    -    'en_LC': 'Saint Lucia',
    -    'en_LR': 'Liberia',
    -    'en_LS': 'Lesotho',
    -    'en_MH': 'Marshall Islands',
    -    'en_MP': 'Northern Mariana Islands',
    -    'en_MS': 'Montserrat',
    -    'en_MT': 'Malta',
    -    'en_MU': 'Mauritius',
    -    'en_MW': 'Malawi',
    -    'en_NA': 'Namibia',
    -    'en_NF': 'Norfolk Island',
    -    'en_NG': 'Nigeria',
    -    'en_NR': 'Nauru',
    -    'en_NU': 'Niue',
    -    'en_NZ': 'New Zealand',
    -    'en_PG': 'Papua New Guinea',
    -    'en_PH': 'Philippines',
    -    'en_PK': 'Pakistan',
    -    'en_PN': 'Pitcairn',
    -    'en_PR': 'Puerto Rico',
    -    'en_RW': 'Rwanda',
    -    'en_SB': 'Solomon Islands',
    -    'en_SC': 'Seychelles',
    -    'en_SG': 'Singapore',
    -    'en_SH': 'Saint Helena',
    -    'en_SL': 'Sierra Leone',
    -    'en_SZ': 'Swaziland',
    -    'en_TC': 'Turks and Caicos Islands',
    -    'en_TK': 'Tokelau',
    -    'en_TO': 'Tonga',
    -    'en_TT': 'Trinidad and Tobago',
    -    'en_TV': 'Tuvalu',
    -    'en_TZ': 'Tanzania',
    -    'en_UG': 'Uganda',
    -    'en_UM': 'United States Minor Outlying Islands',
    -    'en_US': 'United States',
    -    'en_US_POSIX': 'United States',
    -    'en_VC': 'Saint Vincent and the Grenadines',
    -    'en_VG': 'British Virgin Islands',
    -    'en_VI': 'U.S. Virgin Islands',
    -    'en_VU': 'Vanuatu',
    -    'en_WS': 'Samoa',
    -    'en_ZA': 'South Africa',
    -    'en_ZM': 'Zambia',
    -    'en_ZW': 'Zimbabwe',
    -    'es_AR': 'Argentina',
    -    'es_BO': 'Bolivia',
    -    'es_CL': 'Chile',
    -    'es_CO': 'Colombia',
    -    'es_CR': 'Costa Rica',
    -    'es_CU': 'Cuba',
    -    'es_DO': 'Rep\u00fablica Dominicana',
    -    'es_EC': 'Ecuador',
    -    'es_ES': 'Espa\u00f1a',
    -    'es_GQ': 'Guinea Ecuatorial',
    -    'es_GT': 'Guatemala',
    -    'es_HN': 'Honduras',
    -    'es_MX': 'M\u00e9xico',
    -    'es_NI': 'Nicaragua',
    -    'es_PA': 'Panam\u00e1',
    -    'es_PE': 'Per\u00fa',
    -    'es_PH': 'Filipinas',
    -    'es_PR': 'Puerto Rico',
    -    'es_PY': 'Paraguay',
    -    'es_SV': 'El Salvador',
    -    'es_US': 'Estados Unidos',
    -    'es_UY': 'Uruguay',
    -    'es_VE': 'Venezuela',
    -    'et_EE': 'Eesti',
    -    'eu_ES': 'Espainia',
    -    'fa_AF': '\u0627\u0641\u063a\u0627\u0646\u0633\u062a\u0627' +
    -        '\u0646',
    -    'fa_IR': '\u0627\u06cc\u0631\u0627\u0646',
    -    'fi_FI': 'Suomi',
    -    'fil_PH': 'Philippines',
    -    'fj_FJ': 'Fiji',
    -    'fo_FO': 'F\u00f8royar',
    -    'fr_BE': 'Belgique',
    -    'fr_BF': 'Burkina Faso',
    -    'fr_BI': 'Burundi',
    -    'fr_BJ': 'B\u00e9nin',
    -    'fr_CA': 'Canada',
    -    'fr_CD': 'R\u00e9publique d\u00e9mocratique du Congo',
    -    'fr_CF': 'R\u00e9publique centrafricaine',
    -    'fr_CG': 'Congo',
    -    'fr_CH': 'Suisse',
    -    'fr_CI': 'C\u00f4te d\u2019Ivoire',
    -    'fr_CM': 'Cameroun',
    -    'fr_DJ': 'Djibouti',
    -    'fr_DZ': 'Alg\u00e9rie',
    -    'fr_FR': 'France',
    -    'fr_GA': 'Gabon',
    -    'fr_GF': 'Guyane fran\u00e7aise',
    -    'fr_GN': 'Guin\u00e9e',
    -    'fr_GP': 'Guadeloupe',
    -    'fr_GQ': 'Guin\u00e9e \u00e9quatoriale',
    -    'fr_HT': 'Ha\u00efti',
    -    'fr_KM': 'Comores',
    -    'fr_LU': 'Luxembourg',
    -    'fr_MA': 'Maroc',
    -    'fr_MC': 'Monaco',
    -    'fr_MG': 'Madagascar',
    -    'fr_ML': 'Mali',
    -    'fr_MQ': 'Martinique',
    -    'fr_MU': 'Maurice',
    -    'fr_NC': 'Nouvelle-Cal\u00e9donie',
    -    'fr_NE': 'Niger',
    -    'fr_PF': 'Polyn\u00e9sie fran\u00e7aise',
    -    'fr_PM': 'Saint-Pierre-et-Miquelon',
    -    'fr_RE': 'R\u00e9union',
    -    'fr_RW': 'Rwanda',
    -    'fr_SC': 'Seychelles',
    -    'fr_SN': 'S\u00e9n\u00e9gal',
    -    'fr_SY': 'Syrie',
    -    'fr_TD': 'Tchad',
    -    'fr_TG': 'Togo',
    -    'fr_TN': 'Tunisie',
    -    'fr_VU': 'Vanuatu',
    -    'fr_WF': 'Wallis-et-Futuna',
    -    'fr_YT': 'Mayotte',
    -    'fur_IT': 'Italia',
    -    'ga_IE': '\u00c9ire',
    -    'gaa_GH': 'Ghana',
    -    'gez_ER': '\u12a4\u122d\u1275\u122b',
    -    'gez_ET': '\u12a2\u1275\u12ee\u1335\u12eb',
    -    'gil_KI': 'Kiribati',
    -    'gl_ES': 'Espa\u00f1a',
    -    'gn_PY': 'Paraguay',
    -    'gu_IN': '\u0aad\u0abe\u0ab0\u0aa4',
    -    'gv_GB': 'Rywvaneth Unys',
    -    'ha_Arab_NG': '\u0646\u064a\u062c\u064a\u0631\u064a\u0627',
    -    'ha_GH': '\u063a\u0627\u0646\u0627',
    -    'ha_Latn_GH': 'Ghana',
    -    'ha_Latn_NE': 'Niger',
    -    'ha_Latn_NG': 'Nig\u00e9ria',
    -    'ha_NE': '\u0627\u0644\u0646\u064a\u062c\u0631',
    -    'ha_NG': '\u0646\u064a\u062c\u064a\u0631\u064a\u0627',
    -    'haw_US': '\u02bbAmelika Hui P\u016b \u02bbIa',
    -    'he_IL': '\u05d9\u05e9\u05e8\u05d0\u05dc',
    -    'hi_IN': '\u092d\u093e\u0930\u0924',
    -    'ho_PG': 'Papua New Guinea',
    -    'hr_BA': 'Bosna i Hercegovina',
    -    'hr_HR': 'Hrvatska',
    -    'ht_HT': 'Ha\u00efti',
    -    'hu_HU': 'Magyarorsz\u00e1g',
    -    'hy_AM': '\u0540\u0561\u0575\u0561\u057d\u057f\u0561\u0576' +
    -        '\u056b \u0540\u0561\u0576\u0580\u0561\u057a\u0565' +
    -        '\u057f\u0578\u0582\u0569\u056b\u0582\u0576',
    -    'hy_AM_REVISED': '\u0540\u0561\u0575\u0561\u057d\u057f\u0561' +
    -        '\u0576\u056b \u0540\u0561\u0576\u0580\u0561' +
    -        '\u057a\u0565\u057f\u0578\u0582\u0569\u056b' +
    -        '\u0582\u0576',
    -    'id_ID': 'Indonesia',
    -    'ig_NG': 'Nigeria',
    -    'ii_CN': '\ua34f\ua1e9',
    -    'is_IS': '\u00cdsland',
    -    'it_CH': 'Svizzera',
    -    'it_IT': 'Italia',
    -    'it_SM': 'San Marino',
    -    'ja_JP': '\u65e5\u672c',
    -    'ka_GE': '\u10e1\u10d0\u10e5\u10d0\u10e0\u10d7\u10d5\u10d4' +
    -        '\u10da\u10dd',
    -    'kaj_NG': 'Nigeria',
    -    'kam_KE': 'Kenya',
    -    'kcg_NG': 'Nigeria',
    -    'kfo_NG': 'Nig\u00e9ria',
    -    'kk_KZ': '\u049a\u0430\u0437\u0430\u049b\u0441\u0442\u0430' +
    -        '\u043d',
    -    'kl_GL': 'Kalaallit Nunaat',
    -    'km_KH': '\u1780\u1798\u17d2\u1796\u17bb\u1787\u17b6',
    -    'kn_IN': '\u0cad\u0cbe\u0cb0\u0ca4',
    -    'ko_KP': '\uc870\uc120 \ubbfc\uc8fc\uc8fc\uc758 \uc778\ubbfc ' +
    -        '\uacf5\ud654\uad6d',
    -    'ko_KR': '\ub300\ud55c\ubbfc\uad6d',
    -    'kok_IN': '\u092d\u093e\u0930\u0924',
    -    'kos_FM': 'Micronesia',
    -    'kpe_GN': 'Guin\u00e9e',
    -    'kpe_LR': 'Lib\u00e9ria',
    -    'ks_IN': '\u092d\u093e\u0930\u0924',
    -    'ku_IQ': 'Irak',
    -    'ku_IR': '\u0130ran',
    -    'ku_Latn_IQ': 'Irak',
    -    'ku_Latn_IR': '\u0130ran',
    -    'ku_Latn_SY': 'Suriye',
    -    'ku_Latn_TR': 'T\u00fcrkiye',
    -    'ku_SY': 'Suriye',
    -    'ku_TR': 'T\u00fcrkiye',
    -    'kw_GB': 'Rywvaneth Unys',
    -    'ky_Cyrl_KG': '\u041a\u044b\u0440\u0433\u044b\u0437\u0441' +
    -        '\u0442\u0430\u043d',
    -    'ky_KG': 'K\u0131rg\u0131zistan',
    -    'la_VA': 'Vaticano',
    -    'lb_LU': 'Luxembourg',
    -    'ln_CD': 'R\u00e9publique d\u00e9mocratique du Congo',
    -    'ln_CG': 'Kongo',
    -    'lo_LA': 'Laos',
    -    'lt_LT': 'Lietuva',
    -    'lv_LV': 'Latvija',
    -    'mg_MG': 'Madagascar',
    -    'mh_MH': 'Marshall Islands',
    -    'mi_NZ': 'New Zealand',
    -    'mk_MK': '\u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0438' +
    -        '\u0458\u0430',
    -    'ml_IN': '\u0d07\u0d28\u0d4d\u0d24\u0d4d\u0d2f',
    -    'mn_Cyrl_MN': '\u041c\u043e\u043d\u0433\u043e\u043b\u0438' +
    -        '\u044f',
    -    'mn_MN': '\u041c\u043e\u043d\u0433\u043e\u043b\u0438\u044f',
    -    'mr_IN': '\u092d\u093e\u0930\u0924',
    -    'ms_BN': 'Brunei',
    -    'ms_MY': 'Malaysia',
    -    'ms_SG': 'Singapura',
    -    'mt_MT': 'Malta',
    -    'my_MM': 'Myanmar',
    -    'na_NR': 'Nauru',
    -    'nb_NO': 'Norge',
    -    'nb_SJ': 'Svalbard og Jan Mayen',
    -    'ne_NP': '\u0928\u0947\u092a\u093e\u0932',
    -    'niu_NU': 'Niue',
    -    'nl_AN': 'Nederlandse Antillen',
    -    'nl_AW': 'Aruba',
    -    'nl_BE': 'Belgi\u00eb',
    -    'nl_NL': 'Nederland',
    -    'nl_SR': 'Suriname',
    -    'nn_NO': 'Noreg',
    -    'nr_ZA': 'South Africa',
    -    'nso_ZA': 'South Africa',
    -    'ny_MW': 'Malawi',
    -    'om_ET': 'Itoophiyaa',
    -    'om_KE': 'Keeniyaa',
    -    'or_IN': '\u0b2d\u0b3e\u0b30\u0b24',
    -    'pa_Arab_PK': '\u067e\u0627\u06a9\u0633\u062a\u0627\u0646',
    -    'pa_Guru_IN': '\u0a2d\u0a3e\u0a30\u0a24',
    -    'pa_IN': '\u0a2d\u0a3e\u0a30\u0a24',
    -    'pa_PK': '\u067e\u0627\u06a9\u0633\u062a\u0627\u0646',
    -    'pap_AN': 'Nederlandse Antillen',
    -    'pau_PW': 'Palau',
    -    'pl_PL': 'Polska',
    -    'pon_FM': 'Micronesia',
    -    'ps_AF': '\u0627\u0641\u063a\u0627\u0646\u0633\u062a\u0627' +
    -        '\u0646',
    -    'pt_AO': 'Angola',
    -    'pt_BR': 'Brasil',
    -    'pt_CV': 'Cabo Verde',
    -    'pt_GW': 'Guin\u00e9 Bissau',
    -    'pt_MZ': 'Mo\u00e7ambique',
    -    'pt_PT': 'Portugal',
    -    'pt_ST': 'S\u00e3o Tom\u00e9 e Pr\u00edncipe',
    -    'pt_TL': 'Timor Leste',
    -    'qu_BO': 'Bolivia',
    -    'qu_PE': 'Per\u00fa',
    -    'rm_CH': 'Schweiz',
    -    'rn_BI': 'Burundi',
    -    'ro_MD': 'Moldova, Republica',
    -    'ro_RO': 'Rom\u00e2nia',
    -    'ru_BY': '\u0411\u0435\u043b\u0430\u0440\u0443\u0441\u044c',
    -    'ru_KG': '\u041a\u044b\u0440\u0433\u044b\u0437\u0441\u0442' +
    -        '\u0430\u043d',
    -    'ru_KZ': '\u041a\u0430\u0437\u0430\u0445\u0441\u0442\u0430' +
    -        '\u043d',
    -    'ru_RU': '\u0420\u043e\u0441\u0441\u0438\u044f',
    -    'ru_UA': '\u0423\u043a\u0440\u0430\u0438\u043d\u0430',
    -    'rw_RW': 'Rwanda',
    -    'sa_IN': '\u092d\u093e\u0930\u0924',
    -    'sd_Deva_IN': '\u092d\u093e\u0930\u0924',
    -    'sd_IN': '\u092d\u093e\u0930\u0924',
    -    'se_FI': 'Finland',
    -    'se_NO': 'Norge',
    -    'sg_CF': 'R\u00e9publique centrafricaine',
    -    'sh_BA': 'Bosnia and Herzegovina',
    -    'sh_CS': 'Serbia and Montenegro',
    -    'si_LK': 'Sri Lanka',
    -    'sid_ET': 'Itoophiyaa',
    -    'sk_SK': 'Slovensk\u00e1 republika',
    -    'sl_SI': 'Slovenija',
    -    'sm_AS': 'American Samoa',
    -    'sm_WS': 'Samoa',
    -    'so_DJ': 'Jabuuti',
    -    'so_ET': 'Itoobiya',
    -    'so_KE': 'Kiiniya',
    -    'so_SO': 'Soomaaliya',
    -    'sq_AL': 'Shqip\u00ebria',
    -    'sr_BA': '\u0411\u043e\u0441\u043d\u0430 \u0438 \u0425\u0435' +
    -        '\u0440\u0446\u0435\u0433\u043e\u0432\u0438\u043d' +
    -        '\u0430',
    -    'sr_CS': '\u0421\u0440\u0431\u0438\u0458\u0430 \u0438 \u0426' +
    -        '\u0440\u043d\u0430 \u0413\u043e\u0440\u0430',
    -    'sr_Cyrl_BA': '\u0411\u043e\u0441\u043d\u0438\u044f',
    -    'sr_Cyrl_CS': '\u0421\u0435\u0440\u0431\u0438\u044f \u0438 ' +
    -        '\u0427\u0435\u0440\u043d\u043e\u0433\u043e' +
    -        '\u0440\u0438\u044f',
    -    'sr_Cyrl_ME': '\u0427\u0435\u0440\u043d\u043e\u0433\u043e' +
    -        '\u0440\u0438\u044f',
    -    'sr_Cyrl_RS': '\u0421\u0435\u0440\u0431\u0438\u044f',
    -    'sr_Latn_BA': 'Bosna i Hercegovina',
    -    'sr_Latn_CS': 'Srbija i Crna Gora',
    -    'sr_Latn_ME': 'Crna Gora',
    -    'sr_Latn_RS': 'Srbija',
    -    'sr_ME': '\u0426\u0440\u043d\u0430 \u0413\u043e\u0440\u0430',
    -    'sr_RS': '\u0421\u0440\u0431\u0438\u0458\u0430',
    -    'ss_SZ': 'Swaziland',
    -    'ss_ZA': 'South Africa',
    -    'st_LS': 'Lesotho',
    -    'st_ZA': 'South Africa',
    -    'su_ID': 'Indonesia',
    -    'sv_AX': '\u00c5land',
    -    'sv_FI': 'Finland',
    -    'sv_SE': 'Sverige',
    -    'sw_KE': 'Kenya',
    -    'sw_TZ': 'Tanzania',
    -    'sw_UG': 'Uganda',
    -    'swb_KM': '\u062c\u0632\u0631 \u0627\u0644\u0642\u0645\u0631',
    -    'syr_SY': 'Syria',
    -    'ta_IN': '\u0b87\u0ba8\u0bcd\u0ba4\u0bbf\u0baf\u0bbe',
    -    'ta_LK': '\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8',
    -    'ta_SG': '\u0b9a\u0bbf\u0b99\u0bcd\u0b95\u0baa\u0bcd\u0baa' +
    -        '\u0bc2\u0bb0\u0bcd',
    -    'te_IN': '\u0c2d\u0c3e\u0c30\u0c24 \u0c26\u0c47\u0c33\u0c02',
    -    'tet_TL': 'Timor Leste',
    -    'tg_Cyrl_TJ': '\u0422\u0430\u0434\u0436\u0438\u043a\u0438' +
    -        '\u0441\u0442\u0430\u043d',
    -    'tg_TJ': '\u062a\u0627\u062c\u06a9\u0633\u062a\u0627\u0646',
    -    'th_TH': '\u0e1b\u0e23\u0e30\u0e40\u0e17\u0e28\u0e44\u0e17' +
    -        '\u0e22',
    -    'ti_ER': '\u12a4\u122d\u1275\u122b',
    -    'ti_ET': '\u12a2\u1275\u12ee\u1335\u12eb',
    -    'tig_ER': '\u12a4\u122d\u1275\u122b',
    -    'tk_TM': '\u062a\u0631\u06a9\u0645\u0646\u0633\u062a\u0627' +
    -        '\u0646',
    -    'tkl_TK': 'Tokelau',
    -    'tn_BW': 'Botswana',
    -    'tn_ZA': 'South Africa',
    -    'to_TO': 'Tonga',
    -    'tpi_PG': 'Papua New Guinea',
    -    'tr_CY': 'G\u00fcney K\u0131br\u0131s Rum Kesimi',
    -    'tr_TR': 'T\u00fcrkiye',
    -    'ts_ZA': 'South Africa',
    -    'tt_RU': '\u0420\u043e\u0441\u0441\u0438\u044f',
    -    'tvl_TV': 'Tuvalu',
    -    'ty_PF': 'Polyn\u00e9sie fran\u00e7aise',
    -    'uk_UA': '\u0423\u043a\u0440\u0430\u0457\u043d\u0430',
    -    'uli_FM': 'Micronesia',
    -    'und_ZZ': 'Unknown or Invalid Region',
    -    'ur_IN': '\u0628\u06be\u0627\u0631\u062a',
    -    'ur_PK': '\u067e\u0627\u06a9\u0633\u062a\u0627\u0646',
    -    'uz_AF': 'Afganistan',
    -    'uz_Arab_AF': '\u0627\u0641\u063a\u0627\u0646\u0633\u062a' +
    -        '\u0627\u0646',
    -    'uz_Cyrl_UZ': '\u0423\u0437\u0431\u0435\u043a\u0438\u0441' +
    -        '\u0442\u0430\u043d',
    -    'uz_Latn_UZ': 'O\u02bfzbekiston',
    -    'uz_UZ': '\u040e\u0437\u0431\u0435\u043a\u0438\u0441\u0442' +
    -        '\u043e\u043d',
    -    've_ZA': 'South Africa',
    -    'vi_VN': 'Vi\u1ec7t Nam',
    -    'wal_ET': '\u12a2\u1275\u12ee\u1335\u12eb',
    -    'wo_Arab_SN': '\u0627\u0644\u0633\u0646\u063a\u0627\u0644',
    -    'wo_Latn_SN': 'S\u00e9n\u00e9gal',
    -    'wo_SN': 'S\u00e9n\u00e9gal',
    -    'xh_ZA': 'South Africa',
    -    'yap_FM': 'Micronesia',
    -    'yo_NG': 'Nigeria',
    -    'zh_CN': '\u4e2d\u56fd',
    -    'zh_HK': '\u9999\u6e2f',
    -    'zh_Hans_CN': '\u4e2d\u56fd',
    -    'zh_Hans_SG': '\u65b0\u52a0\u5761',
    -    'zh_Hant_HK': '\u4e2d\u83ef\u4eba\u6c11\u5171\u548c\u570b' +
    -        '\u9999\u6e2f\u7279\u5225\u884c\u653f\u5340',
    -    'zh_Hant_MO': '\u6fb3\u9580',
    -    'zh_Hant_TW': '\u81fa\u7063',
    -    'zh_MO': '\u6fb3\u95e8',
    -    'zh_SG': '\u65b0\u52a0\u5761',
    -    'zh_TW': '\u53f0\u6e7e',
    -    'zu_ZA': 'South Africa'
    -  },
    -  'LANGUAGE': {
    -    'aa': 'afar',
    -    'ab': '\u0430\u0431\u0445\u0430\u0437\u0441\u043a\u0438\u0439',
    -    'ace': 'Aceh',
    -    'ach': 'Acoli',
    -    'ada': 'Adangme',
    -    'ady': '\u0430\u0434\u044b\u0433\u0435\u0439\u0441\u043a' +
    -        '\u0438\u0439',
    -    'ae': 'Avestan',
    -    'af': 'Afrikaans',
    -    'afa': 'Afro-Asiatic Language',
    -    'afh': 'Afrihili',
    -    'ain': 'Ainu',
    -    'ak': 'Akan',
    -    'akk': 'Akkadian',
    -    'ale': 'Aleut',
    -    'alg': 'Algonquian Language',
    -    'alt': 'Southern Altai',
    -    'am': '\u12a0\u121b\u122d\u129b',
    -    'an': 'Aragonese',
    -    'ang': 'Old English',
    -    'anp': 'Angika',
    -    'apa': 'Apache Language',
    -    'ar': '\u0627\u0644\u0639\u0631\u0628\u064a\u0629',
    -    'arc': 'Aramaic',
    -    'arn': 'Araucanian',
    -    'arp': 'Arapaho',
    -    'art': 'Artificial Language',
    -    'arw': 'Arawak',
    -    'as': '\u0985\u09b8\u09ae\u09c0\u09af\u09bc\u09be',
    -    'ast': 'asturiano',
    -    'ath': 'Athapascan Language',
    -    'aus': 'Australian Language',
    -    'av': '\u0430\u0432\u0430\u0440\u0441\u043a\u0438\u0439',
    -    'awa': 'Awadhi',
    -    'ay': 'aimara',
    -    'az': 'az\u0259rbaycanca',
    -    'az_Arab': '\u062a\u0631\u06a9\u06cc \u0622\u0630\u0631\u0628' +
    -        '\u0627\u06cc\u062c\u0627\u0646\u06cc',
    -    'az_Cyrl': '\u0410\u0437\u04d9\u0440\u0431\u0430\u0458\u04b9' +
    -        '\u0430\u043d',
    -    'az_Latn': 'Azerice',
    -    'ba': '\u0431\u0430\u0448\u043a\u0438\u0440\u0441\u043a\u0438' +
    -        '\u0439',
    -    'bad': 'Banda',
    -    'bai': 'Bamileke Language',
    -    'bal': '\u0628\u0644\u0648\u0686\u06cc',
    -    'ban': 'Balin',
    -    'bas': 'Basa',
    -    'bat': 'Baltic Language',
    -    'be': '\u0431\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430' +
    -        '\u044f',
    -    'bej': 'Beja',
    -    'bem': 'Bemba',
    -    'ber': 'Berber',
    -    'bg': '\u0431\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438',
    -    'bh': '\u092c\u093f\u0939\u093e\u0930\u0940',
    -    'bho': 'Bhojpuri',
    -    'bi': 'bichelamar ; bislama',
    -    'bik': 'Bikol',
    -    'bin': 'Bini',
    -    'bla': 'Siksika',
    -    'bm': 'bambara',
    -    'bn': '\u09ac\u09be\u0982\u09b2\u09be',
    -    'bnt': 'Bantu',
    -    'bo': '\u0f54\u0f7c\u0f51\u0f0b\u0f66\u0f90\u0f51\u0f0b',
    -    'br': 'breton',
    -    'bra': 'Braj',
    -    'bs': 'Bosanski',
    -    'btk': 'Batak',
    -    'bua': 'Buriat',
    -    'bug': 'Bugis',
    -    'byn': '\u1265\u120a\u1295',
    -    'ca': 'catal\u00e0',
    -    'cad': 'Caddo',
    -    'cai': 'Central American Indian Language',
    -    'car': 'Carib',
    -    'cau': 'Caucasian Language',
    -    'cch': 'Atsam',
    -    'ce': '\u0447\u0435\u0447\u0435\u043d\u0441\u043a\u0438\u0439',
    -    'ceb': 'Cebuano',
    -    'cel': 'Celtic Language',
    -    'ch': 'Chamorro',
    -    'chb': 'Chibcha',
    -    'chg': 'Chagatai',
    -    'chk': 'Chuukese',
    -    'chm': '\u043c\u0430\u0440\u0438\u0439\u0441\u043a\u0438' +
    -        '\u0439 (\u0447\u0435\u0440\u0435\u043c\u0438\u0441' +
    -        '\u0441\u043a\u0438\u0439)',
    -    'chn': 'Chinook Jargon',
    -    'cho': 'Choctaw',
    -    'chp': 'Chipewyan',
    -    'chr': 'Cherokee',
    -    'chy': 'Cheyenne',
    -    'cmc': 'Chamic Language',
    -    'co': 'corse',
    -    'cop': '\u0642\u0628\u0637\u064a\u0629',
    -    'cop_Arab': '\u0642\u0628\u0637\u064a\u0629',
    -    'cpe': 'English-based Creole or Pidgin',
    -    'cpf': 'French-based Creole or Pidgin',
    -    'cpp': 'Portuguese-based Creole or Pidgin',
    -    'cr': 'Cree',
    -    'crh': 'Crimean Turkish',
    -    'crp': 'Creole or Pidgin',
    -    'cs': '\u010de\u0161tina',
    -    'csb': 'Kashubian',
    -    'cu': 'Church Slavic',
    -    'cus': 'Cushitic Language',
    -    'cv': '\u0447\u0443\u0432\u0430\u0448\u0441\u043a\u0438\u0439',
    -    'cy': 'Cymraeg',
    -    'da': 'dansk',
    -    'dak': 'Dakota',
    -    'dar': '\u0434\u0430\u0440\u0433\u0432\u0430',
    -    'day': 'Dayak',
    -    'de': 'Deutsch',
    -    'del': 'Delaware',
    -    'den': 'Slave',
    -    'dgr': 'Dogrib',
    -    'din': 'Dinka',
    -    'doi': '\u0627\u0644\u062f\u0648\u062c\u0631\u0649',
    -    'dra': 'Dravidian Language',
    -    'dsb': 'Lower Sorbian',
    -    'dua': 'Duala',
    -    'dum': 'Middle Dutch',
    -    'dv': 'Divehi',
    -    'dyu': 'dioula',
    -    'dz': '\u0f62\u0fab\u0f7c\u0f44\u0f0b\u0f41',
    -    'ee': 'Ewe',
    -    'efi': 'Efik',
    -    'egy': 'Ancient Egyptian',
    -    'eka': 'Ekajuk',
    -    'el': '\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac',
    -    'elx': 'Elamite',
    -    'en': 'English',
    -    'enm': 'Middle English',
    -    'eo': 'esperanto',
    -    'es': 'espa\u00f1ol',
    -    'et': 'eesti',
    -    'eu': 'euskara',
    -    'ewo': 'Ewondo',
    -    'fa': '\u0641\u0627\u0631\u0633\u06cc',
    -    'fan': 'fang',
    -    'fat': 'Fanti',
    -    'ff': 'Fulah',
    -    'fi': 'suomi',
    -    'fil': 'Filipino',
    -    'fiu': 'Finno-Ugrian Language',
    -    'fj': 'Fijian',
    -    'fo': 'f\u00f8royskt',
    -    'fon': 'Fon',
    -    'fr': 'fran\u00e7ais',
    -    'frm': 'Middle French',
    -    'fro': 'Old French',
    -    'frr': 'Northern Frisian',
    -    'frs': 'Eastern Frisian',
    -    'fur': 'friulano',
    -    'fy': 'Fries',
    -    'ga': 'Gaeilge',
    -    'gaa': 'Ga',
    -    'gay': 'Gayo',
    -    'gba': 'Gbaya',
    -    'gd': 'Scottish Gaelic',
    -    'gem': 'Germanic Language',
    -    'gez': '\u130d\u12d5\u12dd\u129b',
    -    'gil': 'Gilbertese',
    -    'gl': 'galego',
    -    'gmh': 'Middle High German',
    -    'gn': 'guaran\u00ed',
    -    'goh': 'Old High German',
    -    'gon': 'Gondi',
    -    'gor': 'Gorontalo',
    -    'got': 'Gothic',
    -    'grb': 'Grebo',
    -    'grc': '\u0391\u03c1\u03c7\u03b1\u03af\u03b1 \u0395\u03bb' +
    -        '\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac',
    -    'gsw': 'Schweizerdeutsch',
    -    'gu': '\u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0',
    -    'gv': 'Gaelg',
    -    'gwi': 'Gwich\u02bcin',
    -    'ha': '\u0627\u0644\u0647\u0648\u0633\u0627',
    -    'ha_Arab': '\u0627\u0644\u0647\u0648\u0633\u0627',
    -    'ha_Latn': 'haoussa',
    -    'hai': 'Haida',
    -    'haw': '\u02bb\u014dlelo Hawai\u02bbi',
    -    'he': '\u05e2\u05d1\u05e8\u05d9\u05ea',
    -    'hi': '\u0939\u093f\u0902\u0926\u0940',
    -    'hil': 'Hiligaynon',
    -    'him': 'Himachali',
    -    'hit': 'Hittite',
    -    'hmn': 'Hmong',
    -    'ho': 'Hiri Motu',
    -    'hr': 'hrvatski',
    -    'hsb': 'Upper Sorbian',
    -    'ht': 'ha\u00eftien',
    -    'hu': 'magyar',
    -    'hup': 'Hupa',
    -    'hy': '\u0540\u0561\u0575\u0565\u0580\u0567\u0576',
    -    'hz': 'Herero',
    -    'ia': 'interlingvao',
    -    'iba': 'Iban',
    -    'id': 'Bahasa Indonesia',
    -    'ie': 'Interlingue',
    -    'ig': 'Igbo',
    -    'ii': '\ua188\ua320\ua259',
    -    'ijo': 'Ijo',
    -    'ik': 'Inupiaq',
    -    'ilo': 'Iloko',
    -    'inc': 'Indic Language',
    -    'ine': 'Indo-European Language',
    -    'inh': '\u0438\u043d\u0433\u0443\u0448\u0441\u043a\u0438' +
    -        '\u0439',
    -    'io': 'Ido',
    -    'ira': 'Iranian Language',
    -    'iro': 'Iroquoian Language',
    -    'is': '\u00edslenska',
    -    'it': 'italiano',
    -    'iu': 'Inuktitut',
    -    'ja': '\u65e5\u672c\u8a9e',
    -    'jbo': 'Lojban',
    -    'jpr': 'Judeo-Persian',
    -    'jrb': 'Judeo-Arabic',
    -    'jv': 'Jawa',
    -    'ka': '\u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8',
    -    'kaa': '\u043a\u0430\u0440\u0430\u043a\u0430\u043b\u043f' +
    -        '\u0430\u043a\u0441\u043a\u0438\u0439',
    -    'kab': 'kabyle',
    -    'kac': 'Kachin',
    -    'kaj': 'Jju',
    -    'kam': 'Kamba',
    -    'kar': 'Karen',
    -    'kaw': 'Kawi',
    -    'kbd': '\u043a\u0430\u0431\u0430\u0440\u0434\u0438\u043d' +
    -        '\u0441\u043a\u0438\u0439',
    -    'kcg': 'Tyap',
    -    'kfo': 'koro',
    -    'kg': 'Kongo',
    -    'kha': 'Khasi',
    -    'khi': 'Khoisan Language',
    -    'kho': 'Khotanese',
    -    'ki': 'Kikuyu',
    -    'kj': 'Kuanyama',
    -    'kk': '\u049a\u0430\u0437\u0430\u049b',
    -    'kl': 'kalaallisut',
    -    'km': '\u1797\u17b6\u179f\u17b6\u1781\u17d2\u1798\u17c2\u179a',
    -    'kmb': 'quimbundo',
    -    'kn': '\u0c95\u0ca8\u0ccd\u0ca8\u0ca1',
    -    'ko': '\ud55c\uad6d\uc5b4',
    -    'kok': '\u0915\u094b\u0902\u0915\u0923\u0940',
    -    'kos': 'Kosraean',
    -    'kpe': 'kpell\u00e9',
    -    'kr': 'Kanuri',
    -    'krc': '\u043a\u0430\u0440\u0430\u0447\u0430\u0435\u0432' +
    -        '\u043e-\u0431\u0430\u043b\u043a\u0430\u0440\u0441' +
    -        '\u043a\u0438\u0439',
    -    'krl': '\u043a\u0430\u0440\u0435\u043b\u044c\u0441\u043a' +
    -        '\u0438\u0439',
    -    'kro': 'Kru',
    -    'kru': 'Kurukh',
    -    'ks': '\u0915\u093e\u0936\u094d\u092e\u093f\u0930\u0940',
    -    'ku': 'K\u00fcrt\u00e7e',
    -    'ku_Arab': '\u0627\u0644\u0643\u0631\u062f\u064a\u0629',
    -    'ku_Latn': 'K\u00fcrt\u00e7e',
    -    'kum': '\u043a\u0443\u043c\u044b\u043a\u0441\u043a\u0438' +
    -        '\u0439',
    -    'kut': 'Kutenai',
    -    'kv': 'Komi',
    -    'kw': 'kernewek',
    -    'ky': 'K\u0131rg\u0131zca',
    -    'ky_Arab': '\u0627\u0644\u0642\u064a\u0631\u063a\u0633\u062a' +
    -        '\u0627\u0646\u064a\u0629',
    -    'ky_Cyrl': '\u043a\u0438\u0440\u0433\u0438\u0437\u0441\u043a' +
    -        '\u0438\u0439',
    -    'la': 'latino',
    -    'lad': '\u05dc\u05d3\u05d9\u05e0\u05d5',
    -    'lah': '\u0644\u0627\u0647\u0646\u062f\u0627',
    -    'lam': 'Lamba',
    -    'lb': 'luxembourgeois',
    -    'lez': '\u043b\u0435\u0437\u0433\u0438\u043d\u0441\u043a' +
    -        '\u0438\u0439',
    -    'lg': 'Ganda',
    -    'li': 'Limburgs',
    -    'ln': 'lingala',
    -    'lo': 'Lao',
    -    'lol': 'mongo',
    -    'loz': 'Lozi',
    -    'lt': 'lietuvi\u0173',
    -    'lu': 'luba-katanga',
    -    'lua': 'luba-lulua',
    -    'lui': 'Luiseno',
    -    'lun': 'Lunda',
    -    'luo': 'Luo',
    -    'lus': 'Lushai',
    -    'lv': 'latvie\u0161u',
    -    'mad': 'Madura',
    -    'mag': 'Magahi',
    -    'mai': 'Maithili',
    -    'mak': 'Makassar',
    -    'man': 'Mandingo',
    -    'map': 'Austronesian',
    -    'mas': 'Masai',
    -    'mdf': '\u043c\u043e\u043a\u0448\u0430',
    -    'mdr': 'Mandar',
    -    'men': 'Mende',
    -    'mg': 'malgache',
    -    'mga': 'Middle Irish',
    -    'mh': 'Marshallese',
    -    'mi': 'Maori',
    -    'mic': 'Micmac',
    -    'min': 'Minangkabau',
    -    'mis': 'Miscellaneous Language',
    -    'mk': '\u043c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a' +
    -        '\u0438',
    -    'mkh': 'Mon-Khmer Language',
    -    'ml': '\u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02',
    -    'mn': '\u043c\u043e\u043d\u0433\u043e\u043b\u044c\u0441\u043a' +
    -        '\u0438\u0439',
    -    'mn_Cyrl': '\u043c\u043e\u043d\u0433\u043e\u043b\u044c\u0441' +
    -        '\u043a\u0438\u0439',
    -    'mn_Mong': '\u043c\u043e\u043d\u0433\u043e\u043b\u044c\u0441' +
    -        '\u043a\u0438\u0439',
    -    'mnc': 'Manchu',
    -    'mni': 'Manipuri',
    -    'mno': 'Manobo Language',
    -    'mo': 'Moldavian',
    -    'moh': 'Mohawk',
    -    'mos': 'mor\u00e9 ; mossi',
    -    'mr': '\u092e\u0930\u093e\u0920\u0940',
    -    'ms': 'Bahasa Melayu',
    -    'mt': 'Malti',
    -    'mul': 'Multiple Languages',
    -    'mun': 'Munda Language',
    -    'mus': 'Creek',
    -    'mwl': 'Mirandese',
    -    'mwr': 'Marwari',
    -    'my': 'Burmese',
    -    'myn': 'Mayan Language',
    -    'myv': '\u044d\u0440\u0437\u044f',
    -    'na': 'Nauru',
    -    'nah': 'Nahuatl',
    -    'nai': 'North American Indian Language',
    -    'nap': 'napoletano',
    -    'nb': 'norsk bokm\u00e5l',
    -    'nd': 'North Ndebele',
    -    'nds': 'Low German',
    -    'ne': '\u0928\u0947\u092a\u093e\u0932\u0940',
    -    'new': 'Newari',
    -    'ng': 'Ndonga',
    -    'nia': 'Nias',
    -    'nic': 'Niger-Kordofanian Language',
    -    'niu': 'Niuean',
    -    'nl': 'Nederlands',
    -    'nn': 'nynorsk',
    -    'no': 'Norwegian',
    -    'nog': '\u043d\u043e\u0433\u0430\u0439\u0441\u043a\u0438' +
    -        '\u0439',
    -    'non': 'Old Norse',
    -    'nqo': 'N\u2019Ko',
    -    'nr': 'South Ndebele',
    -    'nso': 'Northern Sotho',
    -    'nub': 'Nubian Language',
    -    'nv': 'Navajo',
    -    'nwc': 'Classical Newari',
    -    'ny': 'nianja; chicheua; cheua',
    -    'nym': 'Nyamwezi',
    -    'nyn': 'Nyankole',
    -    'nyo': 'Nyoro',
    -    'nzi': 'Nzima',
    -    'oc': 'occitan',
    -    'oj': 'Ojibwa',
    -    'om': 'Oromoo',
    -    'or': '\u0b13\u0b21\u0b3c\u0b3f\u0b06',
    -    'os': '\u043e\u0441\u0435\u0442\u0438\u043d\u0441\u043a\u0438' +
    -        '\u0439',
    -    'osa': 'Osage',
    -    'ota': 'Ottoman Turkish',
    -    'oto': 'Otomian Language',
    -    'pa': '\u0a2a\u0a70\u0a1c\u0a3e\u0a2c\u0a40',
    -    'pa_Arab': '\u067e\u0646\u062c\u0627\u0628',
    -    'pa_Guru': '\u0a2a\u0a70\u0a1c\u0a3e\u0a2c\u0a40',
    -    'paa': 'Papuan Language',
    -    'pag': 'Pangasinan',
    -    'pal': 'Pahlavi',
    -    'pam': 'Pampanga',
    -    'pap': 'Papiamento',
    -    'pau': 'Palauan',
    -    'peo': 'Old Persian',
    -    'phi': 'Philippine Language',
    -    'phn': 'Phoenician',
    -    'pi': '\u0e1a\u0e32\u0e25\u0e35',
    -    'pl': 'polski',
    -    'pon': 'Pohnpeian',
    -    'pra': 'Prakrit Language',
    -    'pro': 'Old Proven\u00e7al',
    -    'ps': '\u067e\u069a\u062a\u0648',
    -    'pt': 'portugu\u00eas',
    -    'qu': 'quechua',
    -    'raj': 'Rajasthani',
    -    'rap': 'Rapanui',
    -    'rar': 'Rarotongan',
    -    'rm': 'R\u00e4toromanisch',
    -    'rn': 'roundi',
    -    'ro': 'rom\u00e2n\u0103',
    -    'roa': 'Romance Language',
    -    'rom': 'Romany',
    -    'ru': '\u0440\u0443\u0441\u0441\u043a\u0438\u0439',
    -    'rup': 'Aromanian',
    -    'rw': 'rwanda',
    -    'sa': '\u0938\u0902\u0938\u094d\u0915\u0943\u0924 \u092d' +
    -        '\u093e\u0937\u093e',
    -    'sad': 'Sandawe',
    -    'sah': '\u044f\u043a\u0443\u0442\u0441\u043a\u0438\u0439',
    -    'sai': 'South American Indian Language',
    -    'sal': 'Salishan Language',
    -    'sam': '\u05d0\u05e8\u05de\u05d9\u05ea \u05e9\u05d5\u05de' +
    -        '\u05e8\u05d5\u05e0\u05d9\u05ea',
    -    'sas': 'Sasak',
    -    'sat': 'Santali',
    -    'sc': 'Sardinian',
    -    'scn': 'siciliano',
    -    'sco': 'Scots',
    -    'sd': '\u0938\u093f\u0928\u094d\u0927\u0940',
    -    'sd_Arab': '\u0633\u0646\u062f\u06cc',
    -    'sd_Deva': '\u0938\u093f\u0928\u094d\u0927\u0940',
    -    'se': 'nordsamiska',
    -    'sel': '\u0441\u0435\u043b\u044c\u043a\u0443\u043f\u0441' +
    -        '\u043a\u0438\u0439',
    -    'sem': 'Semitic Language',
    -    'sg': 'sangho',
    -    'sga': 'Old Irish',
    -    'sgn': 'Sign Language',
    -    'sh': 'Serbo-Croatian',
    -    'shn': 'Shan',
    -    'si': 'Sinhalese',
    -    'sid': 'Sidamo',
    -    'sio': 'Siouan Language',
    -    'sit': 'Sino-Tibetan Language',
    -    'sk': 'slovensk\u00fd',
    -    'sl': 'sloven\u0161\u010dina',
    -    'sla': 'Slavic Language',
    -    'sm': 'Samoan',
    -    'sma': 'sydsamiska',
    -    'smi': 'Sami Language',
    -    'smj': 'lulesamiska',
    -    'smn': 'Inari Sami',
    -    'sms': 'Skolt Sami',
    -    'sn': 'Shona',
    -    'snk': 'sonink\u00e9',
    -    'so': 'Soomaali',
    -    'sog': 'Sogdien',
    -    'son': 'Songhai',
    -    'sq': 'shqipe',
    -    'sr': '\u0421\u0440\u043f\u0441\u043a\u0438',
    -    'sr_Cyrl': '\u0441\u0435\u0440\u0431\u0441\u043a\u0438\u0439',
    -    'sr_Latn': 'Srpski',
    -    'srn': 'Sranantongo',
    -    'srr': 's\u00e9r\u00e8re',
    -    'ss': 'Swati',
    -    'ssa': 'Nilo-Saharan Language',
    -    'st': 'Sesotho',
    -    'su': 'Sundan',
    -    'suk': 'Sukuma',
    -    'sus': 'soussou',
    -    'sux': 'Sumerian',
    -    'sv': 'svenska',
    -    'sw': 'Kiswahili',
    -    'syc': 'Classical Syriac',
    -    'syr': 'Syriac',
    -    'ta': '\u0ba4\u0bae\u0bbf\u0bb4\u0bcd',
    -    'tai': 'Tai Language',
    -    'te': '\u0c24\u0c46\u0c32\u0c41\u0c17\u0c41',
    -    'tem': 'Timne',
    -    'ter': 'Tereno',
    -    'tet': 't\u00e9tum',
    -    'tg': '\u062a\u0627\u062c\u06a9',
    -    'tg_Arab': '\u062a\u0627\u062c\u06a9',
    -    'tg_Cyrl': '\u0442\u0430\u0434\u0436\u0438\u043a\u0441\u043a' +
    -        '\u0438\u0439',
    -    'th': '\u0e44\u0e17\u0e22',
    -    'ti': '\u1275\u130d\u122d\u129b',
    -    'tig': '\u1275\u130d\u1228',
    -    'tiv': 'Tiv',
    -    'tk': '\u062a\u0631\u06a9\u0645\u0646\u06cc',
    -    'tkl': 'Tokelau',
    -    'tl': 'Tagalog',
    -    'tlh': 'Klingon',
    -    'tli': 'Tlingit',
    -    'tmh': 'tamacheq',
    -    'tn': 'Tswana',
    -    'to': 'Tonga',
    -    'tog': 'Nyasa Tonga',
    -    'tpi': 'Tok Pisin',
    -    'tr': 'T\u00fcrk\u00e7e',
    -    'ts': 'Tsonga',
    -    'tsi': 'Tsimshian',
    -    'tt': '\u0442\u0430\u0442\u0430\u0440\u0441\u043a\u0438\u0439',
    -    'tum': 'Tumbuka',
    -    'tup': 'Tupi Language',
    -    'tut': '\u0430\u043b\u0442\u0430\u0439\u0441\u043a\u0438' +
    -        '\u0435 (\u0434\u0440\u0443\u0433\u0438\u0435)',
    -    'tvl': 'Tuvalu',
    -    'tw': 'Twi',
    -    'ty': 'tahitien',
    -    'tyv': '\u0442\u0443\u0432\u0438\u043d\u0441\u043a\u0438' +
    -        '\u0439',
    -    'udm': '\u0443\u0434\u043c\u0443\u0440\u0442\u0441\u043a' +
    -        '\u0438\u0439',
    -    'ug': '\u0443\u0439\u0433\u0443\u0440\u0441\u043a\u0438\u0439',
    -    'uga': 'Ugaritic',
    -    'uk': '\u0443\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a' +
    -        '\u0430',
    -    'umb': 'umbundu',
    -    'und': 'English',
    -    'ur': '\u0627\u0631\u062f\u0648',
    -    'uz': '\u040e\u0437\u0431\u0435\u043a',
    -    'uz_Arab': '\u0627\u06c9\u0632\u0628\u06d0\u06a9',
    -    'uz_Cyrl': '\u0443\u0437\u0431\u0435\u043a\u0441\u043a\u0438' +
    -        '\u0439',
    -    'uz_Latn': 'o\'zbekcha',
    -    'vai': 'Vai',
    -    've': 'Venda',
    -    'vi': 'Ti\u1ebfng Vi\u1ec7t',
    -    'vo': 'volapuko',
    -    'vot': 'Votic',
    -    'wa': 'Wallonisch',
    -    'wak': 'Wakashan Language',
    -    'wal': 'Walamo',
    -    'war': 'Waray',
    -    'was': 'Washo',
    -    'wen': 'Sorbian Language',
    -    'wo': 'wolof',
    -    'wo_Arab': '\u0627\u0644\u0648\u0644\u0648\u0641',
    -    'wo_Latn': 'wolof',
    -    'xal': '\u043a\u0430\u043b\u043c\u044b\u0446\u043a\u0438' +
    -        '\u0439',
    -    'xh': 'Xhosa',
    -    'yao': 'iao',
    -    'yap': 'Yapese',
    -    'yi': '\u05d9\u05d9\u05d3\u05d9\u05e9',
    -    'yo': 'Yoruba',
    -    'ypk': 'Yupik Language',
    -    'za': 'Zhuang',
    -    'zap': 'Zapotec',
    -    'zen': 'Zenaga',
    -    'zh': '\u4e2d\u6587',
    -    'zh_Hans': '\u4e2d\u6587',
    -    'zh_Hant': '\u4e2d\u6587',
    -    'znd': 'Zande',
    -    'zu': 'Zulu',
    -    'zun': 'Zuni',
    -    'zxx': 'No linguistic content',
    -    'zza': 'Zaza'
    -  }
    -};
    -/* ~!@# END #@!~ */
    diff --git a/src/database/third_party/closure-library/closure/goog/locale/scriptToLanguages.js b/src/database/third_party/closure-library/closure/goog/locale/scriptToLanguages.js
    deleted file mode 100644
    index 9be7304555b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/locale/scriptToLanguages.js
    +++ /dev/null
    @@ -1,482 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Script to Languages mapping. Typically, one script is used by
    - * many languages of the world. This map captures that information as a mapping
    - * from script to array of two letter or three letter language codes.
    - *
    - * This map is used by goog.locale.genericFontNames for listing
    - * font fallbacks for a font family for a locale. That file
    - * uses this map in conjunction with goog.locale.genericFontNamesData.
    - *
    - * Warning: this file is automatically generated from CLDR.
    - * Please contact i18n team or change the script and regenerate data.
    - * Code location: http://go/generate_genericfontnames.py
    - *
    - */
    -
    -
    -/**
    - * Namespace for Script to Languages mapping
    - */
    -goog.provide('goog.locale.scriptToLanguages');
    -
    -goog.require('goog.locale');
    -
    -/**
    - * The script code to list of language codes map.
    - * @type {!Object<string, !Array<string>>}
    - */
    -
    -/* ~!@# genmethods.scriptToLanguages() #@!~ */
    -goog.locale.scriptToLanguages = {
    -  'Arab': [
    -    'prd',
    -    'doi',
    -    'lah',
    -    'uz',
    -    'cjm',
    -    'swb',
    -    'az',
    -    'ps',
    -    'ur',
    -    'ks',
    -    'fa',
    -    'ar',
    -    'tk',
    -    'ku',
    -    'tg',
    -    'bal',
    -    'ha',
    -    'ky',
    -    'ug',
    -    'sd'
    -  ],
    -  'Armn': ['hy'],
    -  'Beng': [
    -    'mni',
    -    'grt',
    -    'bn',
    -    'syl',
    -    'as',
    -    'ril',
    -    'ccp'
    -  ],
    -  'Blis': ['zbl'],
    -  'Cans': [
    -    'cr',
    -    'iu',
    -    'cwd',
    -    'crk'
    -  ],
    -  'Cham': ['cja'],
    -  'Cher': ['chr'],
    -  'Cyrl': [
    -    'ab',
    -    'rom',
    -    'mns',
    -    'mdf',
    -    'ce',
    -    'myv',
    -    'ude',
    -    'sah',
    -    'inh',
    -    'uk',
    -    'tab',
    -    'av',
    -    'yrk',
    -    'az',
    -    'cv',
    -    'koi',
    -    'ru',
    -    'dng',
    -    'sel',
    -    'tt',
    -    'chm',
    -    'ady',
    -    'tyv',
    -    'abq',
    -    'kum',
    -    'xal',
    -    'tg',
    -    'cjs',
    -    'tk',
    -    'be',
    -    'kaa',
    -    'bg',
    -    'kca',
    -    'ba',
    -    'nog',
    -    'krl',
    -    'bxr',
    -    'kbd',
    -    'dar',
    -    'krc',
    -    'lez',
    -    'ttt',
    -    'udm',
    -    'evn',
    -    'kpv',
    -    'uz',
    -    'kk',
    -    'kpy',
    -    'kjh',
    -    'mn',
    -    'gld',
    -    'mk',
    -    'ckt',
    -    'aii',
    -    'kv',
    -    'ku',
    -    'sr',
    -    'lbe',
    -    'ky',
    -    'os'
    -  ],
    -  'Deva': [
    -    'btv',
    -    'kfr',
    -    'bho',
    -    'mr',
    -    'bhb',
    -    'bjj',
    -    'hi',
    -    'mag',
    -    'mai',
    -    'awa',
    -    'lif',
    -    'xsr',
    -    'mwr',
    -    'kok',
    -    'gon',
    -    'hne',
    -    'hoc',
    -    'gbm',
    -    'hoj',
    -    'ne',
    -    'kru',
    -    'ks',
    -    'bra',
    -    'bft',
    -    'new',
    -    'bfy',
    -    'sd'
    -  ],
    -  'Ethi': [
    -    'byn',
    -    'wal',
    -    'ti',
    -    'tig',
    -    'am'
    -  ],
    -  'Geor': ['ka'],
    -  'Grek': ['el'],
    -  'Gujr': ['gu'],
    -  'Guru': ['pa'],
    -  'Hans': [
    -    'zh',
    -    'za'
    -  ],
    -  'Hant': ['zh'],
    -  'Hebr': [
    -    'lad',
    -    'yi',
    -    'he'
    -  ],
    -  'Jpan': ['ja'],
    -  'Khmr': ['km'],
    -  'Knda': [
    -    'kn',
    -    'tcy'
    -  ],
    -  'Kore': ['ko'],
    -  'Laoo': ['lo'],
    -  'Latn': [
    -    'gv',
    -    'sco',
    -    'scn',
    -    'mfe',
    -    'hnn',
    -    'suk',
    -    'tkl',
    -    'gd',
    -    'ga',
    -    'gn',
    -    'gl',
    -    'rom',
    -    'hai',
    -    'lb',
    -    'la',
    -    'ln',
    -    'tsg',
    -    'tr',
    -    'ts',
    -    'li',
    -    'lv',
    -    'to',
    -    'lt',
    -    'lu',
    -    'tk',
    -    'tg',
    -    'fo',
    -    'fil',
    -    'bya',
    -    'bin',
    -    'kcg',
    -    'ceb',
    -    'amo',
    -    'yao',
    -    'mos',
    -    'dyu',
    -    'de',
    -    'tbw',
    -    'da',
    -    'fan',
    -    'st',
    -    'hil',
    -    'fon',
    -    'efi',
    -    'tl',
    -    'qu',
    -    'uz',
    -    'kpe',
    -    'ban',
    -    'bal',
    -    'gor',
    -    'tru',
    -    'mo',
    -    'mdh',
    -    'en',
    -    'tem',
    -    'ee',
    -    'tvl',
    -    'cr',
    -    'eu',
    -    'et',
    -    'tet',
    -    'nbf',
    -    'es',
    -    'rw',
    -    'lut',
    -    'kmb',
    -    'ast',
    -    'sms',
    -    'lua',
    -    'sus',
    -    'smj',
    -    'fy',
    -    'tmh',
    -    'rm',
    -    'rn',
    -    'ro',
    -    'dsb',
    -    'sma',
    -    'luo',
    -    'hsb',
    -    'wa',
    -    'lg',
    -    'wo',
    -    'bm',
    -    'jv',
    -    'men',
    -    'bi',
    -    'tum',
    -    'br',
    -    'bs',
    -    'smn',
    -    'om',
    -    'ace',
    -    'ilo',
    -    'ty',
    -    'oc',
    -    'srr',
    -    'krl',
    -    'tw',
    -    'nds',
    -    'os',
    -    'xh',
    -    'ch',
    -    'co',
    -    'nso',
    -    'ca',
    -    'sn',
    -    'eo',
    -    'son',
    -    'pon',
    -    'cy',
    -    'cs',
    -    'kfo',
    -    'fj',
    -    'tn',
    -    'srn',
    -    'pt',
    -    'sm',
    -    'chk',
    -    'bbc',
    -    'chm',
    -    'lol',
    -    'frs',
    -    'frr',
    -    'chr',
    -    'yap',
    -    'vi',
    -    'kos',
    -    'gil',
    -    'ak',
    -    'pl',
    -    'sid',
    -    'hr',
    -    'ht',
    -    'hu',
    -    'hmn',
    -    'ho',
    -    'gag',
    -    'buc',
    -    'ha',
    -    'bug',
    -    'gaa',
    -    'mg',
    -    'fur',
    -    'bem',
    -    'ibb',
    -    'mi',
    -    'mh',
    -    'war',
    -    'mt',
    -    'uli',
    -    'ms',
    -    'sr',
    -    'haw',
    -    'sq',
    -    'aa',
    -    've',
    -    'af',
    -    'gwi',
    -    'is',
    -    'it',
    -    'sv',
    -    'ii',
    -    'sas',
    -    'ik',
    -    'tpi',
    -    'zu',
    -    'ay',
    -    'kha',
    -    'az',
    -    'tzm',
    -    'id',
    -    'ig',
    -    'pap',
    -    'nl',
    -    'pau',
    -    'nn',
    -    'no',
    -    'na',
    -    'nb',
    -    'nd',
    -    'umb',
    -    'ng',
    -    'ny',
    -    'nap',
    -    'gcr',
    -    'nyn',
    -    'hop',
    -    'lis',
    -    'so',
    -    'nr',
    -    'pam',
    -    'nv',
    -    'kv',
    -    'kab',
    -    'fr',
    -    'nym',
    -    'kaj',
    -    'rcf',
    -    'yo',
    -    'snk',
    -    'kam',
    -    'dgr',
    -    'mad',
    -    'fi',
    -    'mak',
    -    'niu',
    -    'kg',
    -    'pag',
    -    'gsw',
    -    'ss',
    -    'kj',
    -    'ki',
    -    'min',
    -    'sw',
    -    'cpe',
    -    'su',
    -    'kl',
    -    'sk',
    -    'kr',
    -    'kw',
    -    'cch',
    -    'ku',
    -    'sl',
    -    'sg',
    -    'tiv',
    -    'se'
    -  ],
    -  'Lepc': ['lep'],
    -  'Limb': ['lif'],
    -  'Mlym': ['ml'],
    -  'Mong': [
    -    'mnc',
    -    'mn'
    -  ],
    -  'Mymr': [
    -    'my',
    -    'kht',
    -    'shn',
    -    'mnw'
    -  ],
    -  'Nkoo': [
    -    'nqo',
    -    'emk'
    -  ],
    -  'Orya': ['or'],
    -  'Sinh': ['si'],
    -  'Tale': ['tdd'],
    -  'Talu': ['khb'],
    -  'Taml': [
    -    'bfq',
    -    'ta'
    -  ],
    -  'Telu': [
    -    'te',
    -    'gon',
    -    'lmn'
    -  ],
    -  'Tfng': ['tzm'],
    -  'Thaa': ['dv'],
    -  'Thai': [
    -    'tts',
    -    'lwl',
    -    'th',
    -    'kdt',
    -    'lcp'
    -  ],
    -  'Tibt': [
    -    'bo',
    -    'dz'
    -  ],
    -  'Yiii': ['ii'],
    -  'und': ['sat']
    -};
    -/* ~!@# END #@!~ */
    diff --git a/src/database/third_party/closure-library/closure/goog/locale/timezonedetection.js b/src/database/third_party/closure-library/closure/goog/locale/timezonedetection.js
    deleted file mode 100644
    index 3e6f5d24d8c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/locale/timezonedetection.js
    +++ /dev/null
    @@ -1,116 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Functions for detecting user's time zone.
    - * This work is based on Charlie Luo and Hong Yan's time zone detection work
    - * for CBG.
    - */
    -goog.provide('goog.locale.timeZoneDetection');
    -
    -goog.require('goog.locale.TimeZoneFingerprint');
    -
    -
    -/**
    - * Array of time instances for checking the time zone offset.
    - * @type {Array<number>}
    - * @private
    - */
    -goog.locale.timeZoneDetection.TZ_POKE_POINTS_ = [
    -  1109635200, 1128902400, 1130657000, 1143333000, 1143806400, 1145000000,
    -  1146380000, 1152489600, 1159800000, 1159500000, 1162095000, 1162075000,
    -  1162105500];
    -
    -
    -/**
    - * Calculates time zone fingerprint by poking time zone offsets for 13
    - * preselected time points.
    - * See {@link goog.locale.timeZoneDetection.TZ_POKE_POINTS_}
    - * @param {Date} date Date for calculating the fingerprint.
    - * @return {number} Fingerprint of user's time zone setting.
    - */
    -goog.locale.timeZoneDetection.getFingerprint = function(date) {
    -  var hash = 0;
    -  var stdOffset;
    -  var isComplex = false;
    -  for (var i = 0;
    -       i < goog.locale.timeZoneDetection.TZ_POKE_POINTS_.length; i++) {
    -    date.setTime(goog.locale.timeZoneDetection.TZ_POKE_POINTS_[i] * 1000);
    -    var offset = date.getTimezoneOffset() / 30 + 48;
    -    if (i == 0) {
    -      stdOffset = offset;
    -    } else if (stdOffset != offset) {
    -      isComplex = true;
    -    }
    -    hash = (hash << 2) ^ offset;
    -  }
    -  return isComplex ? hash : /** @type {number} */ (stdOffset);
    -};
    -
    -
    -/**
    - * Detects browser's time zone setting. If user's country is known, a better
    - * time zone choice could be guessed.
    - * @param {string=} opt_country Two-letter ISO 3166 country code.
    - * @param {Date=} opt_date Date for calculating the fingerprint. Defaults to the
    - *     current date.
    - * @return {string} Time zone ID of best guess.
    - */
    -goog.locale.timeZoneDetection.detectTimeZone = function(opt_country, opt_date) {
    -  var date = opt_date || new Date();
    -  var fingerprint = goog.locale.timeZoneDetection.getFingerprint(date);
    -  var timeZoneList = goog.locale.TimeZoneFingerprint[fingerprint];
    -  // Timezones in goog.locale.TimeZoneDetection.TimeZoneMap are in the format
    -  // US-America/Los_Angeles. Country code needs to be stripped before a
    -  // timezone is returned.
    -  if (timeZoneList) {
    -    if (opt_country) {
    -      for (var i = 0; i < timeZoneList.length; ++i) {
    -        if (timeZoneList[i].indexOf(opt_country) == 0) {
    -          return timeZoneList[i].substring(3);
    -        }
    -      }
    -    }
    -    return timeZoneList[0].substring(3);
    -  }
    -  return '';
    -};
    -
    -
    -/**
    - * Returns an array of time zones that are consistent with user's platform
    - * setting. If user's country is given, only the time zone for that country is
    - * returned.
    - * @param {string=} opt_country 2 letter ISO 3166 country code. Helps in making
    - *     a better guess for user's time zone.
    - * @param {Date=} opt_date Date for retrieving timezone list. Defaults to the
    - *     current date.
    - * @return {!Array<string>} Array of time zone IDs.
    - */
    -goog.locale.timeZoneDetection.getTimeZoneList = function(opt_country,
    -    opt_date) {
    -  var date = opt_date || new Date();
    -  var fingerprint = goog.locale.timeZoneDetection.getFingerprint(date);
    -  var timeZoneList = goog.locale.TimeZoneFingerprint[fingerprint];
    -  if (!timeZoneList) {
    -    return [];
    -  }
    -  var chosenList = [];
    -  for (var i = 0; i < timeZoneList.length; i++) {
    -    if (!opt_country || timeZoneList[i].indexOf(opt_country) == 0) {
    -      chosenList.push(timeZoneList[i].substring(3));
    -    }
    -  }
    -  return chosenList;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/locale/timezonedetection_test.html b/src/database/third_party/closure-library/closure/goog/locale/timezonedetection_test.html
    deleted file mode 100644
    index 0e132a69d8e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/locale/timezonedetection_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.locale.timeZoneDetection
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -  goog.require('goog.locale.timeZoneDetectionTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/locale/timezonedetection_test.js b/src/database/third_party/closure-library/closure/goog/locale/timezonedetection_test.js
    deleted file mode 100644
    index 93f661252b0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/locale/timezonedetection_test.js
    +++ /dev/null
    @@ -1,130 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -goog.provide('goog.locale.timeZoneDetectionTest');
    -goog.setTestOnly('goog.locale.timeZoneDetectionTest');
    -
    -goog.require('goog.locale.timeZoneDetection');
    -goog.require('goog.testing.jsunit');
    -
    -
    -
    -/**
    - * Mock date class with simplified properties of Date class for testing.
    - * @constructor
    - */
    -function MockDate() {
    -  /**
    -   * Time zone offset. For time zones with daylight saving, the different
    -   * offsets are represented as array of offsets.
    -   * @type {Array<number>}
    -   * @private
    -   */
    -  this.timezoneOffset_ = [];
    -  /**
    -   * Counter storing the index of next offset value to be returned from the
    -   * array of offset values.
    -   * @type {number}
    -   * @private
    -   */
    -  this.offsetArrayCounter_ = 0;
    -}
    -
    -
    -/**
    - * Does nothing because setting the time to calculate offset is not needed
    - * in the mock class.
    - * @param {number} ms Ignored.
    - */
    -MockDate.prototype.setTime = function(ms) {
    -  // Do nothing.
    -};
    -
    -
    -/**
    - * Sets the time zone offset.
    - * @param {Array<number>} offset Time zone offset.
    - */
    -MockDate.prototype.setTimezoneOffset = function(offset) {
    -  this.timezoneOffset_ = offset;
    -};
    -
    -
    -/**
    - * Returns consecutive offsets from array of time zone offsets on each call.
    - * @return {number} Time zone offset.
    - */
    -MockDate.prototype.getTimezoneOffset = function() {
    -  return this.timezoneOffset_.length > 1 ?
    -      this.timezoneOffset_[this.offsetArrayCounter_++] :
    -      this.timezoneOffset_[0];
    -};
    -
    -function testGetFingerprint() {
    -  var mockDate = new MockDate();
    -  mockDate.setTimezoneOffset([-480]);
    -  var fingerprint = goog.locale.timeZoneDetection.getFingerprint(mockDate);
    -  assertEquals(32, fingerprint);
    -
    -  mockDate = new MockDate();
    -  mockDate.setTimezoneOffset(
    -      [480, 420, 420, 480, 480, 420, 420, 420, 420, 420, 420, 420, 420]);
    -  fingerprint = goog.locale.timeZoneDetection.getFingerprint(mockDate);
    -  assertEquals(1294772902, fingerprint);
    -}
    -
    -function testDetectTimeZone() {
    -  var mockDate = new MockDate();
    -  mockDate.setTimezoneOffset([-480]);
    -  var timeZoneId =
    -      goog.locale.timeZoneDetection.detectTimeZone(undefined, mockDate);
    -  assertEquals('Asia/Hong_Kong', timeZoneId);
    -
    -  mockDate = new MockDate();
    -  mockDate.setTimezoneOffset(
    -      [480, 420, 420, 480, 480, 420, 420, 420, 420, 420, 420, 420, 420]);
    -  timeZoneId = goog.locale.timeZoneDetection.detectTimeZone('US', mockDate);
    -  assertEquals('America/Los_Angeles', timeZoneId);
    -
    -  mockDate = new MockDate();
    -  mockDate.setTimezoneOffset(
    -      [480, 420, 420, 480, 480, 420, 420, 420, 420, 420, 420, 420, 420]);
    -  timeZoneId = goog.locale.timeZoneDetection.detectTimeZone('CA', mockDate);
    -  assertEquals('America/Dawson', timeZoneId);
    -}
    -
    -function testGetTimeZoneList() {
    -  var mockDate = new MockDate();
    -  mockDate.setTimezoneOffset(
    -      [480, 420, 420, 480, 480, 420, 420, 420, 420, 420, 420, 420, 420]);
    -  var timeZoneList =
    -      goog.locale.timeZoneDetection.getTimeZoneList(undefined, mockDate);
    -  assertEquals('America/Los_Angeles', timeZoneList[0]);
    -  assertEquals('America/Whitehorse', timeZoneList[4]);
    -  assertEquals(5, timeZoneList.length);
    -
    -  mockDate = new MockDate();
    -  mockDate.setTimezoneOffset([-480]);
    -  timeZoneList =
    -      goog.locale.timeZoneDetection.getTimeZoneList(undefined, mockDate);
    -  assertEquals('Asia/Hong_Kong', timeZoneList[0]);
    -  assertEquals('Asia/Chongqing', timeZoneList[7]);
    -  assertEquals(16, timeZoneList.length);
    -
    -  timeZoneList =
    -      goog.locale.timeZoneDetection.getTimeZoneList('AU', mockDate);
    -  assertEquals(1, timeZoneList.length);
    -  assertEquals('Australia/Perth', timeZoneList[0]);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/locale/timezonefingerprint.js b/src/database/third_party/closure-library/closure/goog/locale/timezonefingerprint.js
    deleted file mode 100644
    index 5317288006d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/locale/timezonefingerprint.js
    +++ /dev/null
    @@ -1,248 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Data for time zone detection.
    - *
    - * The following code was generated by the timezone_detect.py script in:
    - * http://go/i18n_tools which uses following files in this directory:
    - * http://go/timezone_data
    - * Files: olson2fingerprint.txt, country2olsons.txt, popular_olsons.txt
    - *
    - * After automatic generation, we added some manual editing. Projecting on
    - * future changes, it is very unlikely that we will need to change the time
    - * zone ID groups. Most of the further modifications will be about relative
    - * time zone order in each time zone group. The easiest way to do that is
    - * to modify this code directly, and that's what we decide to do.
    - *
    - */
    -
    -
    -goog.provide('goog.locale.TimeZoneFingerprint');
    -
    -
    -/**
    - * Time zone fingerprint mapping to time zone list.
    - * @enum {!Array<string>}
    - */
    -goog.locale.TimeZoneFingerprint = {
    -  919994368: ['CA-America/Halifax', 'CA-America/Glace_Bay', 'GL-America/Thule',
    -    'BM-Atlantic/Bermuda'],
    -  6: ['AQ-Antarctica/Rothera'],
    -  8: ['GY-America/Guyana'],
    -  839516172: ['US-America/Denver', 'MX-America/Chihuahua', 'US-America/Boise',
    -    'CA-America/Cambridge_Bay', 'CA-America/Edmonton', 'CA-America/Inuvik',
    -    'MX-America/Mazatlan', 'US-America/Shiprock', 'CA-America/Yellowknife'],
    -  983564836: ['UY-America/Montevideo'],
    -  487587858: ['AU-Australia/Lord_Howe'],
    -  20: ['KI-Pacific/Kiritimati'],
    -  22: ['TO-Pacific/Tongatapu', 'KI-Pacific/Enderbury'],
    -  24: ['FJ-Pacific/Fiji', 'TV-Pacific/Funafuti', 'MH-Pacific/Kwajalein',
    -    'MH-Pacific/Majuro', 'NR-Pacific/Nauru', 'KI-Pacific/Tarawa',
    -    'UM-Pacific/Wake', 'WF-Pacific/Wallis'],
    -  25: ['NF-Pacific/Norfolk'],
    -  26: ['RU-Asia/Magadan', 'VU-Pacific/Efate', 'SB-Pacific/Guadalcanal',
    -    'FM-Pacific/Kosrae', 'NC-Pacific/Noumea', 'FM-Pacific/Ponape'],
    -  28: ['AQ-Antarctica/DumontDUrville', 'AU-Australia/Brisbane',
    -    'AU-Australia/Lindeman', 'GU-Pacific/Guam', 'PG-Pacific/Port_Moresby',
    -    'MP-Pacific/Saipan', 'FM-Pacific/Truk'],
    -  931091802: ['US-America/New_York', 'US-America/Detroit', 'CA-America/Iqaluit',
    -    'US-America/Kentucky/Monticello', 'US-America/Louisville',
    -    'CA-America/Montreal', 'BS-America/Nassau', 'CA-America/Nipigon',
    -    'CA-America/Pangnirtung', 'CA-America/Thunder_Bay', 'CA-America/Toronto'],
    -  30: ['JP-Asia/Tokyo', 'KR-Asia/Seoul', 'TL-Asia/Dili', 'ID-Asia/Jayapura',
    -    'KP-Asia/Pyongyang', 'PW-Pacific/Palau'],
    -  32: ['HK-Asia/Hong_Kong', 'CN-Asia/Shanghai', 'AU-Australia/Perth',
    -    'TW-Asia/Taipei', 'SG-Asia/Singapore', 'AQ-Antarctica/Casey',
    -    'BN-Asia/Brunei', 'CN-Asia/Chongqing', 'CN-Asia/Harbin',
    -    'CN-Asia/Kashgar', 'MY-Asia/Kuala_Lumpur', 'MY-Asia/Kuching',
    -    'MO-Asia/Macau', 'ID-Asia/Makassar', 'PH-Asia/Manila', 'CN-Asia/Urumqi'],
    -  34: ['TH-Asia/Bangkok', 'AQ-Antarctica/Davis', 'ID-Asia/Jakarta',
    -    'KH-Asia/Phnom_Penh', 'ID-Asia/Pontianak', 'VN-Asia/Saigon',
    -    'LA-Asia/Vientiane', 'CX-Indian/Christmas'],
    -  35: ['MM-Asia/Rangoon', 'CC-Indian/Cocos'],
    -  941621262: ['BR-America/Sao_Paulo'],
    -  37: ['IN-Asia/Calcutta'],
    -  38: ['PK-Asia/Karachi', 'KZ-Asia/Aqtobe', 'TM-Asia/Ashgabat',
    -    'TJ-Asia/Dushanbe', 'UZ-Asia/Samarkand', 'UZ-Asia/Tashkent',
    -    'TF-Indian/Kerguelen', 'MV-Indian/Maldives'],
    -  39: ['AF-Asia/Kabul'],
    -  40: ['OM-Asia/Muscat', 'AE-Asia/Dubai', 'SC-Indian/Mahe',
    -    'MU-Indian/Mauritius', 'RE-Indian/Reunion'],
    -  626175324: ['JO-Asia/Amman'],
    -  42: ['KE-Africa/Nairobi', 'SA-Asia/Riyadh', 'ET-Africa/Addis_Ababa',
    -    'ER-Africa/Asmera', 'TZ-Africa/Dar_es_Salaam', 'DJ-Africa/Djibouti',
    -    'UG-Africa/Kampala', 'SD-Africa/Khartoum', 'SO-Africa/Mogadishu',
    -    'AQ-Antarctica/Syowa', 'YE-Asia/Aden', 'BH-Asia/Bahrain',
    -    'KW-Asia/Kuwait', 'QA-Asia/Qatar', 'MG-Indian/Antananarivo',
    -    'KM-Indian/Comoro', 'YT-Indian/Mayotte'],
    -  44: ['ZA-Africa/Johannesburg', 'IL-Asia/Jerusalem', 'MW-Africa/Blantyre',
    -    'BI-Africa/Bujumbura', 'BW-Africa/Gaborone', 'ZW-Africa/Harare',
    -    'RW-Africa/Kigali', 'CD-Africa/Lubumbashi', 'ZM-Africa/Lusaka',
    -    'MZ-Africa/Maputo', 'LS-Africa/Maseru', 'SZ-Africa/Mbabane',
    -    'LY-Africa/Tripoli'],
    -  46: ['NG-Africa/Lagos', 'DZ-Africa/Algiers', 'CF-Africa/Bangui',
    -    'CG-Africa/Brazzaville', 'CM-Africa/Douala', 'CD-Africa/Kinshasa',
    -    'GA-Africa/Libreville', 'AO-Africa/Luanda', 'GQ-Africa/Malabo',
    -    'TD-Africa/Ndjamena', 'NE-Africa/Niamey', 'BJ-Africa/Porto-Novo'],
    -  48: ['MA-Africa/Casablanca', 'CI-Africa/Abidjan', 'GH-Africa/Accra',
    -    'ML-Africa/Bamako', 'GM-Africa/Banjul', 'GW-Africa/Bissau',
    -    'GN-Africa/Conakry', 'SN-Africa/Dakar', 'EH-Africa/El_Aaiun',
    -    'SL-Africa/Freetown', 'TG-Africa/Lome', 'LR-Africa/Monrovia',
    -    'MR-Africa/Nouakchott', 'BF-Africa/Ouagadougou', 'ST-Africa/Sao_Tome',
    -    'GL-America/Danmarkshavn', 'IS-Atlantic/Reykjavik',
    -    'SH-Atlantic/St_Helena'],
    -  570425352: ['GE-Asia/Tbilisi'],
    -  50: ['CV-Atlantic/Cape_Verde'],
    -  52: ['GS-Atlantic/South_Georgia', 'BR-America/Noronha'],
    -  54: ['AR-America/Buenos_Aires', 'BR-America/Araguaina',
    -    'AR-America/Argentina/La_Rioja', 'AR-America/Argentina/Rio_Gallegos',
    -    'AR-America/Argentina/San_Juan', 'AR-America/Argentina/Tucuman',
    -    'AR-America/Argentina/Ushuaia', 'BR-America/Bahia', 'BR-America/Belem',
    -    'AR-America/Catamarca', 'GF-America/Cayenne', 'AR-America/Cordoba',
    -    'BR-America/Fortaleza', 'AR-America/Jujuy', 'BR-America/Maceio',
    -    'AR-America/Mendoza', 'SR-America/Paramaribo', 'BR-America/Recife',
    -    'AQ-Antarctica/Rothera'],
    -  56: ['VE-America/Caracas', 'AI-America/Anguilla', 'AG-America/Antigua',
    -    'AW-America/Aruba', 'BB-America/Barbados', 'BR-America/Boa_Vista',
    -    'AN-America/Curacao', 'DM-America/Dominica', 'GD-America/Grenada',
    -    'GP-America/Guadeloupe', 'GY-America/Guyana', 'CU-America/Havana',
    -    'BO-America/La_Paz', 'BR-America/Manaus', 'MQ-America/Martinique',
    -    'MS-America/Montserrat', 'TT-America/Port_of_Spain',
    -    'BR-America/Porto_Velho', 'PR-America/Puerto_Rico',
    -    'DO-America/Santo_Domingo', 'KN-America/St_Kitts', 'LC-America/St_Lucia',
    -    'VI-America/St_Thomas', 'VC-America/St_Vincent', 'VG-America/Tortola'],
    -  58: ['US-America/Indianapolis', 'US-America/Indianapolis',
    -    'CO-America/Bogota', 'KY-America/Cayman', 'CA-America/Coral_Harbour',
    -    'BR-America/Eirunepe', 'EC-America/Guayaquil', 'US-America/Indiana/Knox',
    -    'JM-America/Jamaica', 'PE-America/Lima', 'PA-America/Panama',
    -    'BR-America/Rio_Branco'],
    -  60: ['NI-America/Managua', 'CA-America/Regina', 'BZ-America/Belize',
    -    'CR-America/Costa_Rica', 'SV-America/El_Salvador',
    -    'CA-America/Swift_Current', 'EC-Pacific/Galapagos'],
    -  62: ['US-America/Phoenix', 'CA-America/Dawson_Creek',
    -    'MX-America/Hermosillo'],
    -  64: ['PN-Pacific/Pitcairn'],
    -  66: ['PF-Pacific/Gambier'],
    -  67: ['PF-Pacific/Marquesas'],
    -  68: ['US-Pacific/Honolulu', 'TK-Pacific/Fakaofo', 'UM-Pacific/Johnston',
    -    'KI-Pacific/Kiritimati', 'CK-Pacific/Rarotonga', 'PF-Pacific/Tahiti'],
    -  70: ['UM-Pacific/Midway', 'WS-Pacific/Apia', 'KI-Pacific/Enderbury',
    -    'NU-Pacific/Niue', 'AS-Pacific/Pago_Pago'],
    -  72: ['MH-Pacific/Kwajalein'],
    -  49938444: ['MX-America/Chihuahua'],
    -  905969678: ['CA-America/Halifax'],
    -  626339164: ['EG-Africa/Cairo'],
    -  939579406: ['FK-Atlantic/Stanley'],
    -  487915538: ['AU-Australia/Lord_Howe'],
    -  937427058: ['CL-Pacific/Easter'],
    -  778043508: ['RU-Asia/Novosibirsk', 'RU-Asia/Omsk'],
    -  474655352: ['RU-Asia/Anadyr', 'RU-Asia/Kamchatka'],
    -  269133956: ['NZ-Pacific/Chatham'],
    -  948087430: ['GL-America/Godthab'],
    -  671787146: ['MN-Asia/Hovd'],
    -  617261764: ['TR-Europe/Istanbul', 'RU-Europe/Kaliningrad', 'BY-Europe/Minsk'],
    -  830603252: ['MX-America/Mexico_City', 'US-America/Chicago',
    -    'MX-America/Cancun', 'US-America/Menominee', 'MX-America/Merida',
    -    'MX-America/Monterrey', 'US-America/North_Dakota/Center',
    -    'CA-America/Rainy_River', 'CA-America/Rankin_Inlet'],
    -  805300897: ['LK-Asia/Colombo'],
    -  805312524: ['MX-America/Mexico_City', 'HN-America/Tegucigalpa'],
    -  984437412: ['GS-Atlantic/South_Georgia'],
    -  850043558: ['MX-America/Chihuahua'],
    -  29: ['AU-Australia/Darwin'],
    -  710950176: ['MN-Asia/Ulaanbaatar'],
    -  617786052: ['RO-Europe/Bucharest', 'FI-Europe/Helsinki', 'CY-Asia/Nicosia',
    -    'GR-Europe/Athens', 'MD-Europe/Chisinau', 'TR-Europe/Istanbul',
    -    'UA-Europe/Kiev', 'LV-Europe/Riga', 'UA-Europe/Simferopol',
    -    'BG-Europe/Sofia', 'EE-Europe/Tallinn', 'UA-Europe/Uzhgorod',
    -    'LT-Europe/Vilnius', 'UA-Europe/Zaporozhye'],
    -  105862464: ['US-America/Juneau'],
    -  581567010: ['IQ-Asia/Baghdad'],
    -  1294772902: ['US-America/Los_Angeles', 'CA-America/Dawson',
    -    'MX-America/Tijuana', 'CA-America/Vancouver', 'CA-America/Whitehorse'],
    -  483044050: ['AU-Australia/Sydney', 'AU-Australia/Melbourne'],
    -  491433170: ['AU-Australia/Hobart'],
    -  36: ['NP-Asia/Katmandu', 'LK-Asia/Colombo', 'BD-Asia/Dhaka',
    -    'AQ-Antarctica/Mawson', 'AQ-Antarctica/Vostok', 'KZ-Asia/Almaty',
    -    'KZ-Asia/Qyzylorda', 'BT-Asia/Thimphu', 'IO-Indian/Chagos'],
    -  626175196: ['IL-Asia/Jerusalem'],
    -  919994592: ['CA-America/Goose_Bay'],
    -  946339336: ['GB-Europe/London', 'ES-Atlantic/Canary', 'FO-Atlantic/Faeroe',
    -    'PT-Atlantic/Madeira', 'IE-Europe/Dublin', 'PT-Europe/Lisbon'],
    -  1037565906: ['PT-Atlantic/Azores', 'GL-America/Scoresbysund'],
    -  670913918: ['TN-Africa/Tunis'],
    -  41: ['IR-Asia/Tehran'],
    -  572522538: ['RU-Europe/Moscow'],
    -  403351686: ['MN-Asia/Choibalsan'],
    -  626338524: ['PS-Asia/Gaza'],
    -  411740806: ['RU-Asia/Yakutsk'],
    -  635437856: ['RU-Asia/Irkutsk'],
    -  617261788: ['RO-Europe/Bucharest', 'LB-Asia/Beirut'],
    -  947956358: ['GL-America/Godthab', 'PM-America/Miquelon'],
    -  12: ['EC-Pacific/Galapagos'],
    -  626306268: ['SY-Asia/Damascus'],
    -  497024903: ['AU-Australia/Adelaide', 'AU-Australia/Broken_Hill'],
    -  456480044: ['RU-Asia/Vladivostok', 'RU-Asia/Sakhalin'],
    -  312471854: ['NZ-Pacific/Auckland', 'AQ-Antarctica/McMurdo'],
    -  626347356: ['EG-Africa/Cairo'],
    -  897537370: ['CU-America/Havana'],
    -  680176266: ['RU-Asia/Krasnoyarsk'],
    -  1465210176: ['US-America/Anchorage'],
    -  805312908: ['NI-America/Managua'],
    -  492088530: ['AU-Australia/Currie', 'AU-Australia/Hobart'],
    -  901076366: ['BR-America/Campo_Grande', 'BR-America/Cuiaba'],
    -  943019406: ['CL-America/Santiago', 'AQ-Antarctica/Palmer'],
    -  928339288: ['US-America/New_York', 'CA-America/Montreal',
    -    'CA-America/Toronto', 'US-America/Detroit'],
    -  939480410: ['US-America/Indiana/Marengo', 'US-America/Indiana/Vevay'],
    -  626392412: ['NA-Africa/Windhoek'],
    -  559943005: ['IR-Asia/Tehran'],
    -  592794974: ['KZ-Asia/Aqtau', 'KZ-Asia/Oral'],
    -  76502378: ['CA-America/Pangnirtung'],
    -  838860812: ['US-America/Denver', 'CA-America/Edmonton'],
    -  931091834: ['TC-America/Grand_Turk', 'HT-America/Port-au-Prince'],
    -  662525310: ['FR-Europe/Paris', 'DE-Europe/Berlin', 'BA-Europe/Sarajevo',
    -    'CS-Europe/Belgrade', 'ES-Africa/Ceuta', 'NL-Europe/Amsterdam',
    -    'AD-Europe/Andorra', 'SK-Europe/Bratislava', 'BE-Europe/Brussels',
    -    'HU-Europe/Budapest', 'DK-Europe/Copenhagen', 'GI-Europe/Gibraltar',
    -    'SI-Europe/Ljubljana', 'LU-Europe/Luxembourg', 'ES-Europe/Madrid',
    -    'MT-Europe/Malta', 'MC-Europe/Monaco', 'NO-Europe/Oslo',
    -    'CZ-Europe/Prague', 'IT-Europe/Rome', 'MK-Europe/Skopje',
    -    'SE-Europe/Stockholm', 'AL-Europe/Tirane', 'LI-Europe/Vaduz',
    -    'AT-Europe/Vienna', 'PL-Europe/Warsaw', 'HR-Europe/Zagreb',
    -    'CH-Europe/Zurich'],
    -  1465865536: ['US-America/Anchorage', 'US-America/Juneau',
    -    'US-America/Nome', 'US-America/Yakutat'],
    -  495058823: ['AU-Australia/Adelaide', 'AU-Australia/Broken_Hill'],
    -  599086472: ['GE-Asia/Tbilisi', 'AM-Asia/Yerevan', 'RU-Europe/Samara'],
    -  805337484: ['GT-America/Guatemala'],
    -  1001739662: ['PY-America/Asuncion'],
    -  836894706: ['CA-America/Winnipeg'],
    -  599086512: ['AZ-Asia/Baku'],
    -  836894708: ['CA-America/Winnipeg'],
    -  41025476: ['US-America/Menominee'],
    -  501219282: ['RU-Asia/Magadan'],
    -  970325971: ['CA-America/St_Johns'],
    -  769654750: ['RU-Asia/Yekaterinburg'],
    -  1286253222: ['US-America/Los_Angeles', 'CA-America/Vancouver',
    -    'CA-America/Whitehorse'],
    -  1373765610: ['US-America/Adak'],
    -  973078513: ['CA-America/St_Johns'],
    -  838860786: ['US-America/Chicago', 'CA-America/Winnipeg'],
    -  970326003: ['CA-America/St_Johns'],
    -  771751924: ['KG-Asia/Bishkek'],
    -  952805774: ['AQ-Antarctica/Palmer'],
    -  483699410: ['AU-Australia/Sydney', 'AU-Australia/Melbourne']
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/locale/timezonelist.js b/src/database/third_party/closure-library/closure/goog/locale/timezonelist.js
    deleted file mode 100644
    index 143ab1eaa1d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/locale/timezonelist.js
    +++ /dev/null
    @@ -1,131 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Functions for listing timezone names.
    - * @suppress {deprecated} Use goog.i18n instead.
    - */
    -
    -/** @suppress {extraProvide} */
    -goog.provide('goog.locale.TimeZoneList');
    -
    -goog.require('goog.locale');
    -
    -
    -/**
    - * Returns the displayable list of short timezone names paired with its id for
    - * the current locale, selected based on the region or language provided.
    - *
    - * This method depends on goog.locale.TimeZone*__<locale> available
    - * from http://go/js_locale_data. Users of this method must add a dependency on
    - * this.
    - *
    - * @param {string=} opt_regionOrLang If region tag is provided, timezone ids
    - *    specific this region are considered. If language is provided, all regions
    - *    for which this language is defacto official is considered. If
    - *    this parameter is not speficied, current locale is used to
    - *    extract this information.
    - *
    - * @return {!Array<Object>} Localized and relevant list of timezone names
    - *    and ids.
    - */
    -goog.locale.getTimeZoneSelectedShortNames = function(opt_regionOrLang) {
    -  return goog.locale.getTimeZoneNameList_('TimeZoneSelectedShortNames',
    -      opt_regionOrLang);
    -};
    -
    -
    -/**
    - * Returns the displayable list of long timezone names paired with its id for
    - * the current locale, selected based on the region or language provided.
    - *
    - * This method depends on goog.locale.TimeZone*__<locale> available
    - * from http://go/js_locale_data. Users of this method must add a dependency on
    - * this.
    - *
    - * @param {string=} opt_regionOrLang If region tag is provided, timezone ids
    - *    specific this region are considered. If language is provided, all regions
    - *    for which this language is defacto official is considered. If
    - *    this parameter is not speficied, current locale is used to
    - *    extract this information.
    - *
    - * @return {!Array<Object>} Localized and relevant list of timezone names
    - *    and ids.
    - */
    -goog.locale.getTimeZoneSelectedLongNames = function(opt_regionOrLang) {
    -  return goog.locale.getTimeZoneNameList_('TimeZoneSelectedLongNames',
    -      opt_regionOrLang);
    -};
    -
    -
    -/**
    - * Returns the displayable list of long timezone names paired with its id for
    - * the current locale.
    - *
    - * This method depends on goog.locale.TimeZoneAllLongNames__<locale> available
    - * from http://go/js_locale_data. Users of this method must add a dependency on
    - * this.
    - *
    - * @return {Array<Object>} localized and relevant list of timezone names
    - *    and ids.
    - */
    -goog.locale.getTimeZoneAllLongNames = function() {
    -  var locale = goog.locale.getLocale();
    -  return /** @type {Array<Object>} */ (
    -      goog.locale.getResource('TimeZoneAllLongNames', locale));
    -};
    -
    -
    -/**
    - * Returns the displayable list of timezone names paired with its id for
    - * the current locale, selected based on the region or language provided.
    - *
    - * This method depends on goog.locale.TimeZone*__<locale> available
    - * from http://go/js_locale_data. Users of this method must add a dependency on
    - * this.
    - *
    - * @param {string} nameType Resource name to be loaded to get the names.
    - *
    - * @param {string=} opt_resource If resource is region tag, timezone ids
    - *    specific this region are considered. If it is language, all regions
    - *    for which this language is defacto official is considered. If it is
    - *    undefined, current locale is used to extract this information.
    - *
    - * @return {!Array<Object>} Localized and relevant list of timezone names
    - *    and ids.
    - * @private
    - */
    -goog.locale.getTimeZoneNameList_ = function(nameType, opt_resource) {
    -  var locale = goog.locale.getLocale();
    -
    -  if (!opt_resource) {
    -    opt_resource = goog.locale.getRegionSubTag(locale);
    -  }
    -  // if there is no region subtag, use the language itself as the resource
    -  if (!opt_resource) {
    -    opt_resource = locale;
    -  }
    -
    -  var names = goog.locale.getResource(nameType, locale);
    -  var ids = goog.locale.getResource('TimeZoneSelectedIds', opt_resource);
    -  var len = ids.length;
    -  var result = [];
    -
    -  for (var i = 0; i < len; i++) {
    -    var id = ids[i];
    -    result.push({'id': id, 'name': names[id]});
    -  }
    -  return result;
    -};
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/locale/timezonelist_test.html b/src/database/third_party/closure-library/closure/goog/locale/timezonelist_test.html
    deleted file mode 100644
    index 2f609190a21..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/locale/timezonelist_test.html
    +++ /dev/null
    @@ -1,26 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.locale.TimeZoneConstants
    -  </title>
    -  <!-- UTF-8 needed for character encoding -->
    -  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.locale.TimeZoneListTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/locale/timezonelist_test.js b/src/database/third_party/closure-library/closure/goog/locale/timezonelist_test.js
    deleted file mode 100644
    index e182a04587e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/locale/timezonelist_test.js
    +++ /dev/null
    @@ -1,158 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.locale.TimeZoneListTest');
    -goog.setTestOnly('goog.locale.TimeZoneListTest');
    -
    -goog.require('goog.locale');
    -/** @suppress {extraRequire} */
    -goog.require('goog.locale.TimeZoneList');
    -goog.require('goog.testing.jsunit');
    -
    -function setUpPage() {
    -  // Test data files are in in http://go/js_locale_data
    -
    -  // Test data from TimeZoneSelectedIds__FR.js
    -  var TimeZoneSelectedIds__FR = [
    -    'Etc/GMT+12',
    -    'Pacific/Midway',
    -    'America/Adak',
    -    'Pacific/Honolulu'
    -  ];
    -  goog.locale.registerTimeZoneSelectedIds(TimeZoneSelectedIds__FR, 'FR');
    -
    -  // Test data from TimeZoneSelectedShortNames__de_DE.js
    -  var TimeZoneSelectedShortNames__de_DE = {
    -    'Etc/GMT+12': 'GMT-12:00',
    -    'Etc/GMT+11': 'GMT-11:00',
    -    'Pacific/Pago_Pago': 'Amerikanisch-Samoa',
    -    'Pacific/Midway': 'Midway (Amerikanisch-Ozeanien)',
    -    'Pacific/Honolulu': 'Honolulu (Vereinigte Staaten)',
    -    'Etc/GMT+10': 'GMT-10:00',
    -    'America/Adak': 'Adak (Vereinigte Staaten)'
    -  };
    -  goog.locale.registerTimeZoneSelectedShortNames(
    -      TimeZoneSelectedShortNames__de_DE, 'de_DE');
    -
    -  // Test data from TimeZoneSelectedLongNames__de_DE.js
    -  var TimeZoneSelectedLongNames__de_DE = {
    -    'Etc/GMT+12': 'GMT-12:00',
    -    'Etc/GMT+11': 'GMT-11:00',
    -    'Pacific/Pago_Pago': 'GMT-11:00 Amerikanisch-Samoa',
    -    'Pacific/Midway': 'GMT-11:00 Midway (Amerikanisch-Ozeanien)',
    -    'Pacific/Honolulu': 'GMT-10:00 Honolulu (Vereinigte Staaten)',
    -    'Etc/GMT+10': 'GMT-10:00',
    -    'America/Adak': 'GMT-10:00 Adak (Vereinigte Staaten)'
    -  };
    -  goog.locale.registerTimeZoneSelectedLongNames(
    -      TimeZoneSelectedLongNames__de_DE, 'de_DE');
    -
    -  // Test data from TimeZoneSelectedIds__en.js
    -  var TimeZoneSelectedIds__en = [
    -    'Etc/GMT+12',
    -    'Pacific/Midway',
    -    'America/Adak',
    -    'Pacific/Honolulu'
    -  ];
    -  goog.locale.registerTimeZoneSelectedIds(TimeZoneSelectedIds__en, 'en');
    -
    -  // Test data from TimeZoneSelectedIds__DE.js
    -  var TimeZoneSelectedIds__DE = [
    -    'Etc/GMT+12',
    -    'Pacific/Midway',
    -    'America/Adak',
    -    'Pacific/Honolulu'
    -  ];
    -  goog.locale.registerTimeZoneSelectedIds(TimeZoneSelectedIds__DE, 'DE');
    -
    -  // Test data from TimeZoneAllLongNames__de_DE.js
    -  var TimeZoneAllLongNames__de_DE = [
    -    {id: 'Etc/GMT+12', name: 'GMT-12:00'},
    -    {id: 'Pacific/Apia', name: 'GMT-11:00 Samoa'},
    -    {id: 'Pacific/Midway', name: 'GMT-11:00 Midway (Amerikanisch-Ozeanien)'},
    -    {id: 'Pacific/Niue', name: 'GMT-11:00 Niue'},
    -    {id: 'Pacific/Pago_Pago', name: 'GMT-11:00 Amerikanisch-Samoa'},
    -    {id: 'Etc/GMT+11', name: 'GMT-11:00'},
    -    {id: 'America/Adak', name: 'GMT-10:00 Adak (Vereinigte Staaten)'},
    -    {id: 'Pacific/Fakaofo', name: 'GMT-10:00 Tokelau'}
    -  ];
    -  goog.locale.registerTimeZoneAllLongNames(TimeZoneAllLongNames__de_DE,
    -      'de_DE');
    -
    -  goog.locale.setLocale('de_DE');
    -}
    -
    -/* Uncomment to display complete listing in the unit tested invocations.
    -
    -document.write('Shortnames in German for France:<br>');
    -
    -var idlist = goog.locale.getTimeZoneSelectedShortNames('FR');
    -
    -for (var i = 0; i < idlist.length; i++) {
    -  document.write(i + ') ' + idlist[i].id + ' = ' + idlist[i].name + '<br>');
    -}
    -
    -document.write('<hr>');
    -
    -document.write('long names in German for all en speakers:<br>');
    -var idlist = goog.locale.getTimeZoneSelectedLongNames('en');
    -
    -for (var i = 0; i < idlist.length; i++) {
    -  document.write(i + ') ' + idlist[i].id + ' = ' + idlist[i].name + '<br>');
    -}
    -
    -document.write('<hr>');
    -
    -document.write('Longnames in German for germans:<br>');
    -var idlist = goog.locale.getTimeZoneSelectedLongNames();
    -
    -for (var i = 0; i < idlist.length; i++) {
    -  document.write(i + ') ' + idlist[i].id + ' = ' + idlist[i].name + '<br>');
    -}
    -
    -document.write('<hr>');
    -
    -document.write('All longnames in German:<br>');
    -var idlist = goog.locale.getTimeZoneAllLongNames();
    -
    -for (var i = 0; i < idlist.length; i++) {
    -  var pair = idlist[i];
    -  document.write(i + ') ' + pair.id + ' = ' + pair.name + '<br>');
    -}
    -
    -document.write('<hr>');
    -*/
    -
    -// Test cases.
    -function testTimeZoneSelectedShortNames() {
    -  // Shortnames in German for France.
    -  var result = goog.locale.getTimeZoneSelectedShortNames('FR');
    -  assertEquals('Honolulu (Vereinigte Staaten)', result[3].name);
    -}
    -
    -function testTimeZoneSelectedLongNames() {
    -  // Long names in German for all English speaking regions.
    -  var result = goog.locale.getTimeZoneSelectedLongNames('en');
    -  assertEquals('GMT-11:00 Midway (Amerikanisch-Ozeanien)', result[1].name);
    -
    -  // Long names in German for germans.
    -  var result = goog.locale.getTimeZoneSelectedLongNames();
    -  assertEquals('GMT-10:00 Adak (Vereinigte Staaten)', result[2].name);
    -}
    -
    -function testTimeZoneAllLongNames() {
    -  // All longnames in German
    -  var result = goog.locale.getTimeZoneAllLongNames();
    -  assertEquals('GMT-10:00 Tokelau', result[7].name);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/log/log.js b/src/database/third_party/closure-library/closure/goog/log/log.js
    deleted file mode 100644
    index b93d835f2fb..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/log/log.js
    +++ /dev/null
    @@ -1,197 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Basic strippable logging definitions.
    - * @see http://go/closurelogging
    - *
    - * @author johnlenz@google.com (John Lenz)
    - */
    -
    -goog.provide('goog.log');
    -goog.provide('goog.log.Level');
    -goog.provide('goog.log.LogRecord');
    -goog.provide('goog.log.Logger');
    -
    -goog.require('goog.debug');
    -goog.require('goog.debug.LogManager');
    -goog.require('goog.debug.LogRecord');
    -goog.require('goog.debug.Logger');
    -
    -
    -/** @define {boolean} Whether logging is enabled. */
    -goog.define('goog.log.ENABLED', goog.debug.LOGGING_ENABLED);
    -
    -
    -/** @const */
    -goog.log.ROOT_LOGGER_NAME = goog.debug.Logger.ROOT_LOGGER_NAME;
    -
    -
    -
    -/**
    - * @constructor
    - * @final
    - */
    -goog.log.Logger = goog.debug.Logger;
    -
    -
    -
    -/**
    - * @constructor
    - * @final
    - */
    -goog.log.Level = goog.debug.Logger.Level;
    -
    -
    -
    -/**
    - * @constructor
    - * @final
    - */
    -goog.log.LogRecord = goog.debug.LogRecord;
    -
    -
    -/**
    - * Finds or creates a logger for a named subsystem. If a logger has already been
    - * created with the given name it is returned. Otherwise a new logger is
    - * created. If a new logger is created its log level will be configured based
    - * on the goog.debug.LogManager configuration and it will configured to also
    - * send logging output to its parent's handlers.
    - * @see goog.debug.LogManager
    - *
    - * @param {string} name A name for the logger. This should be a dot-separated
    - *     name and should normally be based on the package name or class name of
    - *     the subsystem, such as goog.net.BrowserChannel.
    - * @param {goog.log.Level=} opt_level If provided, override the
    - *     default logging level with the provided level.
    - * @return {goog.log.Logger} The named logger or null if logging is disabled.
    - */
    -goog.log.getLogger = function(name, opt_level) {
    -  if (goog.log.ENABLED) {
    -    var logger = goog.debug.LogManager.getLogger(name);
    -    if (opt_level && logger) {
    -      logger.setLevel(opt_level);
    -    }
    -    return logger;
    -  } else {
    -    return null;
    -  }
    -};
    -
    -
    -// TODO(johnlenz): try to tighten the types to these functions.
    -/**
    - * Adds a handler to the logger. This doesn't use the event system because
    - * we want to be able to add logging to the event system.
    - * @param {goog.log.Logger} logger
    - * @param {Function} handler Handler function to add.
    - */
    -goog.log.addHandler = function(logger, handler) {
    -  if (goog.log.ENABLED && logger) {
    -    logger.addHandler(handler);
    -  }
    -};
    -
    -
    -/**
    - * Removes a handler from the logger. This doesn't use the event system because
    - * we want to be able to add logging to the event system.
    - * @param {goog.log.Logger} logger
    - * @param {Function} handler Handler function to remove.
    - * @return {boolean} Whether the handler was removed.
    - */
    -goog.log.removeHandler = function(logger, handler) {
    -  if (goog.log.ENABLED && logger) {
    -    return logger.removeHandler(handler);
    -  } else {
    -    return false;
    -  }
    -};
    -
    -
    -/**
    - * Logs a message. If the logger is currently enabled for the
    - * given message level then the given message is forwarded to all the
    - * registered output Handler objects.
    - * @param {goog.log.Logger} logger
    - * @param {goog.log.Level} level One of the level identifiers.
    - * @param {goog.debug.Loggable} msg The message to log.
    - * @param {Error|Object=} opt_exception An exception associated with the
    - *     message.
    - */
    -goog.log.log = function(logger, level, msg, opt_exception) {
    -  if (goog.log.ENABLED && logger) {
    -    logger.log(level, msg, opt_exception);
    -  }
    -};
    -
    -
    -/**
    - * Logs a message at the Level.SEVERE level.
    - * If the logger is currently enabled for the given message level then the
    - * given message is forwarded to all the registered output Handler objects.
    - * @param {goog.log.Logger} logger
    - * @param {goog.debug.Loggable} msg The message to log.
    - * @param {Error=} opt_exception An exception associated with the message.
    - */
    -goog.log.error = function(logger, msg, opt_exception) {
    -  if (goog.log.ENABLED && logger) {
    -    logger.severe(msg, opt_exception);
    -  }
    -};
    -
    -
    -/**
    - * Logs a message at the Level.WARNING level.
    - * If the logger is currently enabled for the given message level then the
    - * given message is forwarded to all the registered output Handler objects.
    - * @param {goog.log.Logger} logger
    - * @param {goog.debug.Loggable} msg The message to log.
    - * @param {Error=} opt_exception An exception associated with the message.
    - */
    -goog.log.warning = function(logger, msg, opt_exception) {
    -  if (goog.log.ENABLED && logger) {
    -    logger.warning(msg, opt_exception);
    -  }
    -};
    -
    -
    -/**
    - * Logs a message at the Level.INFO level.
    - * If the logger is currently enabled for the given message level then the
    - * given message is forwarded to all the registered output Handler objects.
    - * @param {goog.log.Logger} logger
    - * @param {goog.debug.Loggable} msg The message to log.
    - * @param {Error=} opt_exception An exception associated with the message.
    - */
    -goog.log.info = function(logger, msg, opt_exception) {
    -  if (goog.log.ENABLED && logger) {
    -    logger.info(msg, opt_exception);
    -  }
    -};
    -
    -
    -/**
    - * Logs a message at the Level.Fine level.
    - * If the logger is currently enabled for the given message level then the
    - * given message is forwarded to all the registered output Handler objects.
    - * @param {goog.log.Logger} logger
    - * @param {goog.debug.Loggable} msg The message to log.
    - * @param {Error=} opt_exception An exception associated with the message.
    - */
    -goog.log.fine = function(logger, msg, opt_exception) {
    -  if (goog.log.ENABLED && logger) {
    -    logger.fine(msg, opt_exception);
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/log/log_test.js b/src/database/third_party/closure-library/closure/goog/log/log_test.js
    deleted file mode 100644
    index 65f0ac01d58..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/log/log_test.js
    +++ /dev/null
    @@ -1,187 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.log.
    - */
    -
    -/** @suppress {extraProvide} */
    -goog.provide('goog.logTest');
    -
    -goog.require('goog.debug.LogManager');
    -goog.require('goog.log');
    -goog.require('goog.log.Level');
    -goog.require('goog.testing.jsunit');
    -
    -
    -
    -goog.setTestOnly('goog.logTest');
    -
    -
    -
    -/**
    - * A simple log handler that remembers the last record published.
    - * @constructor
    - * @private
    - */
    -function TestHandler_() {
    -  this.logRecord = null;
    -}
    -
    -TestHandler_.prototype.onPublish = function(logRecord) {
    -  this.logRecord = logRecord;
    -};
    -
    -
    -TestHandler_.prototype.reset = function() {
    -  this.logRecord = null;
    -};
    -
    -
    -function testParents() {
    -  var logger2sibling1 = goog.log.getLogger('goog.test');
    -  var logger2sibling2 = goog.log.getLogger('goog.bar');
    -  var logger3sibling1 = goog.log.getLogger('goog.bar.foo');
    -  var logger3siblint2 = goog.log.getLogger('goog.bar.baaz');
    -  var rootLogger = goog.debug.LogManager.getRoot();
    -  var googLogger = goog.log.getLogger('goog');
    -  assertEquals(rootLogger, googLogger.getParent());
    -  assertEquals(googLogger, logger2sibling1.getParent());
    -  assertEquals(googLogger, logger2sibling2.getParent());
    -  assertEquals(logger2sibling2, logger3sibling1.getParent());
    -  assertEquals(logger2sibling2, logger3siblint2.getParent());
    -}
    -
    -function testLogging1() {
    -  var root = goog.debug.LogManager.getRoot();
    -  var handler = new TestHandler_();
    -  var f = goog.bind(handler.onPublish, handler);
    -  goog.log.addHandler(root, f);
    -  var logger = goog.log.getLogger('goog.bar.baaz');
    -  goog.log.log(logger, goog.log.Level.WARNING, 'foo');
    -  assertNotNull(handler.logRecord);
    -  assertEquals(goog.log.Level.WARNING, handler.logRecord.getLevel());
    -  assertEquals('foo', handler.logRecord.getMessage());
    -  handler.logRecord = null;
    -
    -  goog.log.removeHandler(root, f);
    -  goog.log.log(logger, goog.log.Level.WARNING, 'foo');
    -  assertNull(handler.logRecord);
    -}
    -
    -function testLogging2() {
    -  var root = goog.debug.LogManager.getRoot();
    -  var handler = new TestHandler_();
    -  var f = goog.bind(handler.onPublish, handler);
    -  goog.log.addHandler(root, f);
    -  var logger = goog.log.getLogger('goog.bar.baaz');
    -  goog.log.warning(logger, 'foo');
    -  assertNotNull(handler.logRecord);
    -  assertEquals(goog.log.Level.WARNING, handler.logRecord.getLevel());
    -  assertEquals('foo', handler.logRecord.getMessage());
    -  handler.logRecord = null;
    -
    -  goog.log.removeHandler(root, f);
    -  goog.log.log(logger, goog.log.Level.WARNING, 'foo');
    -  assertNull(handler.logRecord);
    -}
    -
    -
    -function testFiltering() {
    -  var root = goog.debug.LogManager.getRoot();
    -  var handler = new TestHandler_();
    -  var f = goog.bind(handler.onPublish, handler);
    -  root.addHandler(f);
    -  var logger1 = goog.log.getLogger('goog.bar.foo', goog.log.Level.WARNING);
    -  var logger2 = goog.log.getLogger('goog.bar.baaz', goog.log.Level.INFO);
    -  goog.log.warning(logger2, 'foo');
    -  assertNotNull(handler.logRecord);
    -  assertEquals(goog.log.Level.WARNING, handler.logRecord.getLevel());
    -  assertEquals('foo', handler.logRecord.getMessage());
    -  handler.reset();
    -  goog.log.info(logger1, 'bar');
    -  assertNull(handler.logRecord);
    -  goog.log.warning(logger1, 'baaz');
    -  assertNotNull(handler.logRecord);
    -  handler.reset();
    -  goog.log.error(logger1, 'baaz');
    -  assertNotNull(handler.logRecord);
    -}
    -
    -
    -function testException() {
    -  var root = goog.debug.LogManager.getRoot();
    -  var handler = new TestHandler_();
    -  var f = goog.bind(handler.onPublish, handler);
    -  root.addHandler(f);
    -  var logger = goog.log.getLogger('goog.debug.logger_test');
    -  var ex = Error('boo!');
    -  goog.log.error(logger, 'hello', ex);
    -  assertNotNull(handler.logRecord);
    -  assertEquals(goog.log.Level.SEVERE, handler.logRecord.getLevel());
    -  assertEquals('hello', handler.logRecord.getMessage());
    -  assertEquals(ex, handler.logRecord.getException());
    -}
    -
    -
    -function testMessageCallbacks() {
    -  var root = goog.debug.LogManager.getRoot();
    -  var handler = new TestHandler_();
    -  var f = goog.bind(handler.onPublish, handler);
    -  root.addHandler(f);
    -  var logger = goog.log.getLogger('goog.bar.foo');
    -  logger.setLevel(goog.log.Level.WARNING);
    -
    -  logger.log(goog.log.Level.INFO, function() {
    -    throw "Message callback shouldn't be called when below logger's level!";
    -  });
    -  assertNull(handler.logRecord);
    -
    -  logger.log(goog.log.Level.WARNING, function() {return 'heya'});
    -  assertNotNull(handler.logRecord);
    -  assertEquals(goog.log.Level.WARNING, handler.logRecord.getLevel());
    -  assertEquals('heya', handler.logRecord.getMessage());
    -}
    -
    -
    -function testGetLogRecord() {
    -  var name = 'test.get.log.record';
    -  var level = goog.log.Level.FINE;
    -  var msg = 'msg';
    -
    -  var logger = goog.log.getLogger(name);
    -  var logRecord = logger.getLogRecord(level, msg);
    -
    -  assertEquals(name, logRecord.getLoggerName());
    -  assertEquals(level, logRecord.getLevel());
    -  assertEquals(msg, logRecord.getMessage());
    -
    -  assertNull(logRecord.getException());
    -}
    -
    -function testGetLogRecordWithException() {
    -  var name = 'test.get.log.record';
    -  var level = goog.log.Level.FINE;
    -  var msg = 'msg';
    -  var ex = Error('Hi');
    -
    -  var logger = goog.log.getLogger(name);
    -  var logRecord = logger.getLogRecord(level, msg, ex);
    -
    -  assertEquals(name, logRecord.getLoggerName());
    -  assertEquals(level, logRecord.getLevel());
    -  assertEquals(msg, logRecord.getMessage());
    -  assertEquals(ex, logRecord.getException());
    -}
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/math/affinetransform.js b/src/database/third_party/closure-library/closure/goog/math/affinetransform.js
    deleted file mode 100644
    index b40f96a7fbd..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/affinetransform.js
    +++ /dev/null
    @@ -1,589 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Provides an object representation of an AffineTransform and
    - * methods for working with it.
    - */
    -
    -
    -goog.provide('goog.math.AffineTransform');
    -
    -goog.require('goog.math');
    -
    -
    -
    -/**
    - * Creates a 2D affine transform. An affine transform performs a linear
    - * mapping from 2D coordinates to other 2D coordinates that preserves the
    - * "straightness" and "parallelness" of lines.
    - *
    - * Such a coordinate transformation can be represented by a 3 row by 3 column
    - * matrix with an implied last row of [ 0 0 1 ]. This matrix transforms source
    - * coordinates (x,y) into destination coordinates (x',y') by considering them
    - * to be a column vector and multiplying the coordinate vector by the matrix
    - * according to the following process:
    - * <pre>
    - *      [ x']   [  m00  m01  m02  ] [ x ]   [ m00x + m01y + m02 ]
    - *      [ y'] = [  m10  m11  m12  ] [ y ] = [ m10x + m11y + m12 ]
    - *      [ 1 ]   [   0    0    1   ] [ 1 ]   [         1         ]
    - * </pre>
    - *
    - * This class is optimized for speed and minimizes calculations based on its
    - * knowledge of the underlying matrix (as opposed to say simply performing
    - * matrix multiplication).
    - *
    - * @param {number=} opt_m00 The m00 coordinate of the transform.
    - * @param {number=} opt_m10 The m10 coordinate of the transform.
    - * @param {number=} opt_m01 The m01 coordinate of the transform.
    - * @param {number=} opt_m11 The m11 coordinate of the transform.
    - * @param {number=} opt_m02 The m02 coordinate of the transform.
    - * @param {number=} opt_m12 The m12 coordinate of the transform.
    - * @struct
    - * @constructor
    - * @final
    - */
    -goog.math.AffineTransform = function(opt_m00, opt_m10, opt_m01,
    -    opt_m11, opt_m02, opt_m12) {
    -  if (arguments.length == 6) {
    -    this.setTransform(/** @type {number} */ (opt_m00),
    -                      /** @type {number} */ (opt_m10),
    -                      /** @type {number} */ (opt_m01),
    -                      /** @type {number} */ (opt_m11),
    -                      /** @type {number} */ (opt_m02),
    -                      /** @type {number} */ (opt_m12));
    -  } else if (arguments.length != 0) {
    -    throw Error('Insufficient matrix parameters');
    -  } else {
    -    this.m00_ = this.m11_ = 1;
    -    this.m10_ = this.m01_ = this.m02_ = this.m12_ = 0;
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} Whether this transform is the identity transform.
    - */
    -goog.math.AffineTransform.prototype.isIdentity = function() {
    -  return this.m00_ == 1 && this.m10_ == 0 && this.m01_ == 0 &&
    -      this.m11_ == 1 && this.m02_ == 0 && this.m12_ == 0;
    -};
    -
    -
    -/**
    - * @return {!goog.math.AffineTransform} A copy of this transform.
    - */
    -goog.math.AffineTransform.prototype.clone = function() {
    -  return new goog.math.AffineTransform(this.m00_, this.m10_, this.m01_,
    -      this.m11_, this.m02_, this.m12_);
    -};
    -
    -
    -/**
    - * Sets this transform to the matrix specified by the 6 values.
    - *
    - * @param {number} m00 The m00 coordinate of the transform.
    - * @param {number} m10 The m10 coordinate of the transform.
    - * @param {number} m01 The m01 coordinate of the transform.
    - * @param {number} m11 The m11 coordinate of the transform.
    - * @param {number} m02 The m02 coordinate of the transform.
    - * @param {number} m12 The m12 coordinate of the transform.
    - * @return {!goog.math.AffineTransform} This affine transform.
    - */
    -goog.math.AffineTransform.prototype.setTransform = function(m00, m10, m01,
    -    m11, m02, m12) {
    -  if (!goog.isNumber(m00) || !goog.isNumber(m10) || !goog.isNumber(m01) ||
    -      !goog.isNumber(m11) || !goog.isNumber(m02) || !goog.isNumber(m12)) {
    -    throw Error('Invalid transform parameters');
    -  }
    -  this.m00_ = m00;
    -  this.m10_ = m10;
    -  this.m01_ = m01;
    -  this.m11_ = m11;
    -  this.m02_ = m02;
    -  this.m12_ = m12;
    -  return this;
    -};
    -
    -
    -/**
    - * Sets this transform to be identical to the given transform.
    - *
    - * @param {!goog.math.AffineTransform} tx The transform to copy.
    - * @return {!goog.math.AffineTransform} This affine transform.
    - */
    -goog.math.AffineTransform.prototype.copyFrom = function(tx) {
    -  this.m00_ = tx.m00_;
    -  this.m10_ = tx.m10_;
    -  this.m01_ = tx.m01_;
    -  this.m11_ = tx.m11_;
    -  this.m02_ = tx.m02_;
    -  this.m12_ = tx.m12_;
    -  return this;
    -};
    -
    -
    -/**
    - * Concatenates this transform with a scaling transformation.
    - *
    - * @param {number} sx The x-axis scaling factor.
    - * @param {number} sy The y-axis scaling factor.
    - * @return {!goog.math.AffineTransform} This affine transform.
    - */
    -goog.math.AffineTransform.prototype.scale = function(sx, sy) {
    -  this.m00_ *= sx;
    -  this.m10_ *= sx;
    -  this.m01_ *= sy;
    -  this.m11_ *= sy;
    -  return this;
    -};
    -
    -
    -/**
    - * Pre-concatenates this transform with a scaling transformation,
    - * i.e. calculates the following matrix product:
    - *
    - * <pre>
    - * [sx  0 0] [m00 m01 m02]
    - * [ 0 sy 0] [m10 m11 m12]
    - * [ 0  0 1] [  0   0   1]
    - * </pre>
    - *
    - * @param {number} sx The x-axis scaling factor.
    - * @param {number} sy The y-axis scaling factor.
    - * @return {!goog.math.AffineTransform} This affine transform.
    - */
    -goog.math.AffineTransform.prototype.preScale = function(sx, sy) {
    -  this.m00_ *= sx;
    -  this.m01_ *= sx;
    -  this.m02_ *= sx;
    -  this.m10_ *= sy;
    -  this.m11_ *= sy;
    -  this.m12_ *= sy;
    -  return this;
    -};
    -
    -
    -/**
    - * Concatenates this transform with a translate transformation.
    - *
    - * @param {number} dx The distance to translate in the x direction.
    - * @param {number} dy The distance to translate in the y direction.
    - * @return {!goog.math.AffineTransform} This affine transform.
    - */
    -goog.math.AffineTransform.prototype.translate = function(dx, dy) {
    -  this.m02_ += dx * this.m00_ + dy * this.m01_;
    -  this.m12_ += dx * this.m10_ + dy * this.m11_;
    -  return this;
    -};
    -
    -
    -/**
    - * Pre-concatenates this transform with a translate transformation,
    - * i.e. calculates the following matrix product:
    - *
    - * <pre>
    - * [1 0 dx] [m00 m01 m02]
    - * [0 1 dy] [m10 m11 m12]
    - * [0 0  1] [  0   0   1]
    - * </pre>
    - *
    - * @param {number} dx The distance to translate in the x direction.
    - * @param {number} dy The distance to translate in the y direction.
    - * @return {!goog.math.AffineTransform} This affine transform.
    - */
    -goog.math.AffineTransform.prototype.preTranslate = function(dx, dy) {
    -  this.m02_ += dx;
    -  this.m12_ += dy;
    -  return this;
    -};
    -
    -
    -/**
    - * Concatenates this transform with a rotation transformation around an anchor
    - * point.
    - *
    - * @param {number} theta The angle of rotation measured in radians.
    - * @param {number} x The x coordinate of the anchor point.
    - * @param {number} y The y coordinate of the anchor point.
    - * @return {!goog.math.AffineTransform} This affine transform.
    - */
    -goog.math.AffineTransform.prototype.rotate = function(theta, x, y) {
    -  return this.concatenate(
    -      goog.math.AffineTransform.getRotateInstance(theta, x, y));
    -};
    -
    -
    -/**
    - * Pre-concatenates this transform with a rotation transformation around an
    - * anchor point.
    - *
    - * @param {number} theta The angle of rotation measured in radians.
    - * @param {number} x The x coordinate of the anchor point.
    - * @param {number} y The y coordinate of the anchor point.
    - * @return {!goog.math.AffineTransform} This affine transform.
    - */
    -goog.math.AffineTransform.prototype.preRotate = function(theta, x, y) {
    -  return this.preConcatenate(
    -      goog.math.AffineTransform.getRotateInstance(theta, x, y));
    -};
    -
    -
    -/**
    - * Concatenates this transform with a shear transformation.
    - *
    - * @param {number} shx The x shear factor.
    - * @param {number} shy The y shear factor.
    - * @return {!goog.math.AffineTransform} This affine transform.
    - */
    -goog.math.AffineTransform.prototype.shear = function(shx, shy) {
    -  var m00 = this.m00_;
    -  var m10 = this.m10_;
    -  this.m00_ += shy * this.m01_;
    -  this.m10_ += shy * this.m11_;
    -  this.m01_ += shx * m00;
    -  this.m11_ += shx * m10;
    -  return this;
    -};
    -
    -
    -/**
    - * Pre-concatenates this transform with a shear transformation.
    - * i.e. calculates the following matrix product:
    - *
    - * <pre>
    - * [  1 shx 0] [m00 m01 m02]
    - * [shy   1 0] [m10 m11 m12]
    - * [  0   0 1] [  0   0   1]
    - * </pre>
    - *
    - * @param {number} shx The x shear factor.
    - * @param {number} shy The y shear factor.
    - * @return {!goog.math.AffineTransform} This affine transform.
    - */
    -goog.math.AffineTransform.prototype.preShear = function(shx, shy) {
    -  var m00 = this.m00_;
    -  var m01 = this.m01_;
    -  var m02 = this.m02_;
    -  this.m00_ += shx * this.m10_;
    -  this.m01_ += shx * this.m11_;
    -  this.m02_ += shx * this.m12_;
    -  this.m10_ += shy * m00;
    -  this.m11_ += shy * m01;
    -  this.m12_ += shy * m02;
    -  return this;
    -};
    -
    -
    -/**
    - * @return {string} A string representation of this transform. The format of
    - *     of the string is compatible with SVG matrix notation, i.e.
    - *     "matrix(a,b,c,d,e,f)".
    - * @override
    - */
    -goog.math.AffineTransform.prototype.toString = function() {
    -  return 'matrix(' +
    -      [this.m00_, this.m10_, this.m01_, this.m11_, this.m02_, this.m12_].join(
    -          ',') +
    -      ')';
    -};
    -
    -
    -/**
    - * @return {number} The scaling factor in the x-direction (m00).
    - */
    -goog.math.AffineTransform.prototype.getScaleX = function() {
    -  return this.m00_;
    -};
    -
    -
    -/**
    - * @return {number} The scaling factor in the y-direction (m11).
    - */
    -goog.math.AffineTransform.prototype.getScaleY = function() {
    -  return this.m11_;
    -};
    -
    -
    -/**
    - * @return {number} The translation in the x-direction (m02).
    - */
    -goog.math.AffineTransform.prototype.getTranslateX = function() {
    -  return this.m02_;
    -};
    -
    -
    -/**
    - * @return {number} The translation in the y-direction (m12).
    - */
    -goog.math.AffineTransform.prototype.getTranslateY = function() {
    -  return this.m12_;
    -};
    -
    -
    -/**
    - * @return {number} The shear factor in the x-direction (m01).
    - */
    -goog.math.AffineTransform.prototype.getShearX = function() {
    -  return this.m01_;
    -};
    -
    -
    -/**
    - * @return {number} The shear factor in the y-direction (m10).
    - */
    -goog.math.AffineTransform.prototype.getShearY = function() {
    -  return this.m10_;
    -};
    -
    -
    -/**
    - * Concatenates an affine transform to this transform.
    - *
    - * @param {!goog.math.AffineTransform} tx The transform to concatenate.
    - * @return {!goog.math.AffineTransform} This affine transform.
    - */
    -goog.math.AffineTransform.prototype.concatenate = function(tx) {
    -  var m0 = this.m00_;
    -  var m1 = this.m01_;
    -  this.m00_ = tx.m00_ * m0 + tx.m10_ * m1;
    -  this.m01_ = tx.m01_ * m0 + tx.m11_ * m1;
    -  this.m02_ += tx.m02_ * m0 + tx.m12_ * m1;
    -
    -  m0 = this.m10_;
    -  m1 = this.m11_;
    -  this.m10_ = tx.m00_ * m0 + tx.m10_ * m1;
    -  this.m11_ = tx.m01_ * m0 + tx.m11_ * m1;
    -  this.m12_ += tx.m02_ * m0 + tx.m12_ * m1;
    -  return this;
    -};
    -
    -
    -/**
    - * Pre-concatenates an affine transform to this transform.
    - *
    - * @param {!goog.math.AffineTransform} tx The transform to preconcatenate.
    - * @return {!goog.math.AffineTransform} This affine transform.
    - */
    -goog.math.AffineTransform.prototype.preConcatenate = function(tx) {
    -  var m0 = this.m00_;
    -  var m1 = this.m10_;
    -  this.m00_ = tx.m00_ * m0 + tx.m01_ * m1;
    -  this.m10_ = tx.m10_ * m0 + tx.m11_ * m1;
    -
    -  m0 = this.m01_;
    -  m1 = this.m11_;
    -  this.m01_ = tx.m00_ * m0 + tx.m01_ * m1;
    -  this.m11_ = tx.m10_ * m0 + tx.m11_ * m1;
    -
    -  m0 = this.m02_;
    -  m1 = this.m12_;
    -  this.m02_ = tx.m00_ * m0 + tx.m01_ * m1 + tx.m02_;
    -  this.m12_ = tx.m10_ * m0 + tx.m11_ * m1 + tx.m12_;
    -  return this;
    -};
    -
    -
    -/**
    - * Transforms an array of coordinates by this transform and stores the result
    - * into a destination array.
    - *
    - * @param {!Array<number>} src The array containing the source points
    - *     as x, y value pairs.
    - * @param {number} srcOff The offset to the first point to be transformed.
    - * @param {!Array<number>} dst The array into which to store the transformed
    - *     point pairs.
    - * @param {number} dstOff The offset of the location of the first transformed
    - *     point in the destination array.
    - * @param {number} numPts The number of points to tranform.
    - */
    -goog.math.AffineTransform.prototype.transform = function(src, srcOff, dst,
    -    dstOff, numPts) {
    -  var i = srcOff;
    -  var j = dstOff;
    -  var srcEnd = srcOff + 2 * numPts;
    -  while (i < srcEnd) {
    -    var x = src[i++];
    -    var y = src[i++];
    -    dst[j++] = x * this.m00_ + y * this.m01_ + this.m02_;
    -    dst[j++] = x * this.m10_ + y * this.m11_ + this.m12_;
    -  }
    -};
    -
    -
    -/**
    - * @return {number} The determinant of this transform.
    - */
    -goog.math.AffineTransform.prototype.getDeterminant = function() {
    -  return this.m00_ * this.m11_ - this.m01_ * this.m10_;
    -};
    -
    -
    -/**
    - * Returns whether the transform is invertible. A transform is not invertible
    - * if the determinant is 0 or any value is non-finite or NaN.
    - *
    - * @return {boolean} Whether the transform is invertible.
    - */
    -goog.math.AffineTransform.prototype.isInvertible = function() {
    -  var det = this.getDeterminant();
    -  return goog.math.isFiniteNumber(det) &&
    -      goog.math.isFiniteNumber(this.m02_) &&
    -      goog.math.isFiniteNumber(this.m12_) &&
    -      det != 0;
    -};
    -
    -
    -/**
    - * @return {!goog.math.AffineTransform} An AffineTransform object
    - *     representing the inverse transformation.
    - */
    -goog.math.AffineTransform.prototype.createInverse = function() {
    -  var det = this.getDeterminant();
    -  return new goog.math.AffineTransform(
    -      this.m11_ / det,
    -      -this.m10_ / det,
    -      -this.m01_ / det,
    -      this.m00_ / det,
    -      (this.m01_ * this.m12_ - this.m11_ * this.m02_) / det,
    -      (this.m10_ * this.m02_ - this.m00_ * this.m12_) / det);
    -};
    -
    -
    -/**
    - * Creates a transform representing a scaling transformation.
    - *
    - * @param {number} sx The x-axis scaling factor.
    - * @param {number} sy The y-axis scaling factor.
    - * @return {!goog.math.AffineTransform} A transform representing a scaling
    - *     transformation.
    - */
    -goog.math.AffineTransform.getScaleInstance = function(sx, sy) {
    -  return new goog.math.AffineTransform().setToScale(sx, sy);
    -};
    -
    -
    -/**
    - * Creates a transform representing a translation transformation.
    - *
    - * @param {number} dx The distance to translate in the x direction.
    - * @param {number} dy The distance to translate in the y direction.
    - * @return {!goog.math.AffineTransform} A transform representing a
    - *     translation transformation.
    - */
    -goog.math.AffineTransform.getTranslateInstance = function(dx, dy) {
    -  return new goog.math.AffineTransform().setToTranslation(dx, dy);
    -};
    -
    -
    -/**
    - * Creates a transform representing a shearing transformation.
    - *
    - * @param {number} shx The x-axis shear factor.
    - * @param {number} shy The y-axis shear factor.
    - * @return {!goog.math.AffineTransform} A transform representing a shearing
    - *     transformation.
    - */
    -goog.math.AffineTransform.getShearInstance = function(shx, shy) {
    -  return new goog.math.AffineTransform().setToShear(shx, shy);
    -};
    -
    -
    -/**
    - * Creates a transform representing a rotation transformation.
    - *
    - * @param {number} theta The angle of rotation measured in radians.
    - * @param {number} x The x coordinate of the anchor point.
    - * @param {number} y The y coordinate of the anchor point.
    - * @return {!goog.math.AffineTransform} A transform representing a rotation
    - *     transformation.
    - */
    -goog.math.AffineTransform.getRotateInstance = function(theta, x, y) {
    -  return new goog.math.AffineTransform().setToRotation(theta, x, y);
    -};
    -
    -
    -/**
    - * Sets this transform to a scaling transformation.
    - *
    - * @param {number} sx The x-axis scaling factor.
    - * @param {number} sy The y-axis scaling factor.
    - * @return {!goog.math.AffineTransform} This affine transform.
    - */
    -goog.math.AffineTransform.prototype.setToScale = function(sx, sy) {
    -  return this.setTransform(sx, 0, 0, sy, 0, 0);
    -};
    -
    -
    -/**
    - * Sets this transform to a translation transformation.
    - *
    - * @param {number} dx The distance to translate in the x direction.
    - * @param {number} dy The distance to translate in the y direction.
    - * @return {!goog.math.AffineTransform} This affine transform.
    - */
    -goog.math.AffineTransform.prototype.setToTranslation = function(dx, dy) {
    -  return this.setTransform(1, 0, 0, 1, dx, dy);
    -};
    -
    -
    -/**
    - * Sets this transform to a shearing transformation.
    - *
    - * @param {number} shx The x-axis shear factor.
    - * @param {number} shy The y-axis shear factor.
    - * @return {!goog.math.AffineTransform} This affine transform.
    - */
    -goog.math.AffineTransform.prototype.setToShear = function(shx, shy) {
    -  return this.setTransform(1, shy, shx, 1, 0, 0);
    -};
    -
    -
    -/**
    - * Sets this transform to a rotation transformation.
    - *
    - * @param {number} theta The angle of rotation measured in radians.
    - * @param {number} x The x coordinate of the anchor point.
    - * @param {number} y The y coordinate of the anchor point.
    - * @return {!goog.math.AffineTransform} This affine transform.
    - */
    -goog.math.AffineTransform.prototype.setToRotation = function(theta, x, y) {
    -  var cos = Math.cos(theta);
    -  var sin = Math.sin(theta);
    -  return this.setTransform(cos, sin, -sin, cos,
    -      x - x * cos + y * sin, y - x * sin - y * cos);
    -};
    -
    -
    -/**
    - * Compares two affine transforms for equality.
    - *
    - * @param {goog.math.AffineTransform} tx The other affine transform.
    - * @return {boolean} whether the two transforms are equal.
    - */
    -goog.math.AffineTransform.prototype.equals = function(tx) {
    -  if (this == tx) {
    -    return true;
    -  }
    -  if (!tx) {
    -    return false;
    -  }
    -  return this.m00_ == tx.m00_ &&
    -      this.m01_ == tx.m01_ &&
    -      this.m02_ == tx.m02_ &&
    -      this.m10_ == tx.m10_ &&
    -      this.m11_ == tx.m11_ &&
    -      this.m12_ == tx.m12_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/math/affinetransform_test.html b/src/database/third_party/closure-library/closure/goog/math/affinetransform_test.html
    deleted file mode 100644
    index 95857eab387..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/affinetransform_test.html
    +++ /dev/null
    @@ -1,19 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.math.AffineTransform</title>
    -<script src="../base.js"></script>
    -<script>
    -goog.require('goog.math.AffineTransformTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/math/affinetransform_test.js b/src/database/third_party/closure-library/closure/goog/math/affinetransform_test.js
    deleted file mode 100644
    index b71e0f38806..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/affinetransform_test.js
    +++ /dev/null
    @@ -1,359 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.math.AffineTransformTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.math');
    -goog.require('goog.math.AffineTransform');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.math.AffineTransformTest');
    -
    -function testGetTranslateInstance() {
    -  var tx = goog.math.AffineTransform.getTranslateInstance(2, 4);
    -  assertEquals(1, tx.getScaleX());
    -  assertEquals(0, tx.getShearY());
    -  assertEquals(0, tx.getShearX());
    -  assertEquals(1, tx.getScaleY());
    -  assertEquals(2, tx.getTranslateX());
    -  assertEquals(4, tx.getTranslateY());
    -}
    -
    -function testGetScaleInstance() {
    -  var tx = goog.math.AffineTransform.getScaleInstance(2, 4);
    -  assertEquals(2, tx.getScaleX());
    -  assertEquals(0, tx.getShearY());
    -  assertEquals(0, tx.getShearX());
    -  assertEquals(4, tx.getScaleY());
    -  assertEquals(0, tx.getTranslateX());
    -  assertEquals(0, tx.getTranslateY());
    -}
    -
    -function testGetRotateInstance() {
    -  var tx = goog.math.AffineTransform.getRotateInstance(Math.PI / 2, 1, 2);
    -  assertRoughlyEquals(0, tx.getScaleX(), 1e-9);
    -  assertRoughlyEquals(1, tx.getShearY(), 1e-9);
    -  assertRoughlyEquals(-1, tx.getShearX(), 1e-9);
    -  assertRoughlyEquals(0, tx.getScaleY(), 1e-9);
    -  assertRoughlyEquals(3, tx.getTranslateX(), 1e-9);
    -  assertRoughlyEquals(1, tx.getTranslateY(), 1e-9);
    -}
    -
    -function testGetShearInstance() {
    -  var tx = goog.math.AffineTransform.getShearInstance(2, 4);
    -  assertEquals(1, tx.getScaleX());
    -  assertEquals(4, tx.getShearY());
    -  assertEquals(2, tx.getShearX());
    -  assertEquals(1, tx.getScaleY());
    -  assertEquals(0, tx.getTranslateX());
    -  assertEquals(0, tx.getTranslateY());
    -}
    -
    -function testConstructor() {
    -  assertThrows(function() {
    -    new goog.math.AffineTransform([0, 0]);
    -  });
    -  assertThrows(function() {
    -    new goog.math.AffineTransform({});
    -  });
    -  assertThrows(function() {
    -    new goog.math.AffineTransform(0, 0, 0, 'a', 0, 0);
    -  });
    -
    -  var tx = new goog.math.AffineTransform(1, 2, 3, 4, 5, 6);
    -  assertEquals(1, tx.getScaleX());
    -  assertEquals(2, tx.getShearY());
    -  assertEquals(3, tx.getShearX());
    -  assertEquals(4, tx.getScaleY());
    -  assertEquals(5, tx.getTranslateX());
    -  assertEquals(6, tx.getTranslateY());
    -
    -  tx = new goog.math.AffineTransform();
    -  assert(tx.isIdentity());
    -}
    -
    -function testIsIdentity() {
    -  var tx = new goog.math.AffineTransform(1, 2, 3, 4, 5, 6);
    -  assertFalse(tx.isIdentity());
    -  tx.setTransform(1, 0, 0, 1, 0, 0);
    -  assert(tx.isIdentity());
    -}
    -
    -function testClone() {
    -  var tx = new goog.math.AffineTransform(1, 2, 3, 4, 5, 6);
    -  var copy = tx.clone();
    -  assertEquals(copy.getScaleX(), tx.getScaleX());
    -  assertEquals(copy.getShearY(), tx.getShearY());
    -  assertEquals(copy.getShearX(), tx.getShearX());
    -  assertEquals(copy.getScaleY(), tx.getScaleY());
    -  assertEquals(copy.getTranslateX(), tx.getTranslateX());
    -  assertEquals(copy.getTranslateY(), tx.getTranslateY());
    -}
    -
    -function testSetTransform() {
    -  var tx = new goog.math.AffineTransform();
    -  assertThrows(function() {
    -    tx.setTransform(1, 2, 3, 4, 6);
    -  });
    -  assertThrows(function() {
    -    tx.setTransform('a', 2, 3, 4, 5, 6);
    -  });
    -
    -  tx.setTransform(1, 2, 3, 4, 5, 6);
    -  assertEquals(1, tx.getScaleX());
    -  assertEquals(2, tx.getShearY());
    -  assertEquals(3, tx.getShearX());
    -  assertEquals(4, tx.getScaleY());
    -  assertEquals(5, tx.getTranslateX());
    -  assertEquals(6, tx.getTranslateY());
    -}
    -
    -function testScale() {
    -  var tx = new goog.math.AffineTransform(1, 2, 3, 4, 5, 6);
    -  tx.scale(2, 3);
    -  assertEquals(2, tx.getScaleX());
    -  assertEquals(4, tx.getShearY());
    -  assertEquals(9, tx.getShearX());
    -  assertEquals(12, tx.getScaleY());
    -  assertEquals(5, tx.getTranslateX());
    -  assertEquals(6, tx.getTranslateY());
    -}
    -
    -function testPreScale() {
    -  var tx = new goog.math.AffineTransform(1, 2, 3, 4, 5, 6);
    -  tx.preScale(2, 3);
    -  assertEquals(2, tx.getScaleX());
    -  assertEquals(6, tx.getShearY());
    -  assertEquals(6, tx.getShearX());
    -  assertEquals(12, tx.getScaleY());
    -  assertEquals(10, tx.getTranslateX());
    -  assertEquals(18, tx.getTranslateY());
    -}
    -
    -function testTranslate() {
    -  var tx = new goog.math.AffineTransform(1, 2, 3, 4, 5, 6);
    -  tx.translate(2, 3);
    -  assertEquals(1, tx.getScaleX());
    -  assertEquals(2, tx.getShearY());
    -  assertEquals(3, tx.getShearX());
    -  assertEquals(4, tx.getScaleY());
    -  assertEquals(16, tx.getTranslateX());
    -  assertEquals(22, tx.getTranslateY());
    -}
    -
    -function testPreTranslate() {
    -  var tx = new goog.math.AffineTransform(1, 2, 3, 4, 5, 6);
    -  tx.preTranslate(2, 3);
    -  assertEquals(1, tx.getScaleX());
    -  assertEquals(2, tx.getShearY());
    -  assertEquals(3, tx.getShearX());
    -  assertEquals(4, tx.getScaleY());
    -  assertEquals(7, tx.getTranslateX());
    -  assertEquals(9, tx.getTranslateY());
    -}
    -
    -function testRotate() {
    -  var tx = new goog.math.AffineTransform(1, 2, 3, 4, 5, 6);
    -  tx.rotate(Math.PI / 2, 1, 1);
    -  assertRoughlyEquals(3, tx.getScaleX(), 1e-9);
    -  assertRoughlyEquals(4, tx.getShearY(), 1e-9);
    -  assertRoughlyEquals(-1, tx.getShearX(), 1e-9);
    -  assertRoughlyEquals(-2, tx.getScaleY(), 1e-9);
    -  assertRoughlyEquals(7, tx.getTranslateX(), 1e-9);
    -  assertRoughlyEquals(10, tx.getTranslateY(), 1e-9);
    -}
    -
    -function testPreRotate() {
    -  var tx = new goog.math.AffineTransform(1, 2, 3, 4, 5, 6);
    -  tx.preRotate(Math.PI / 2, 1, 1);
    -  assertRoughlyEquals(-2, tx.getScaleX(), 1e-9);
    -  assertRoughlyEquals(1, tx.getShearY(), 1e-9);
    -  assertRoughlyEquals(-4, tx.getShearX(), 1e-9);
    -  assertRoughlyEquals(3, tx.getScaleY(), 1e-9);
    -  assertRoughlyEquals(-4, tx.getTranslateX(), 1e-9);
    -  assertRoughlyEquals(5, tx.getTranslateY(), 1e-9);
    -}
    -
    -function testShear() {
    -  var tx = new goog.math.AffineTransform(1, 2, 3, 4, 5, 6);
    -  tx.shear(2, 3);
    -  assertEquals(10, tx.getScaleX());
    -  assertEquals(14, tx.getShearY());
    -  assertEquals(5, tx.getShearX());
    -  assertEquals(8, tx.getScaleY());
    -  assertEquals(5, tx.getTranslateX());
    -  assertEquals(6, tx.getTranslateY());
    -}
    -
    -function testPreShear() {
    -  var tx = new goog.math.AffineTransform(1, 2, 3, 4, 5, 6);
    -  tx.preShear(2, 3);
    -  assertEquals(5, tx.getScaleX());
    -  assertEquals(5, tx.getShearY());
    -  assertEquals(11, tx.getShearX());
    -  assertEquals(13, tx.getScaleY());
    -  assertEquals(17, tx.getTranslateX());
    -  assertEquals(21, tx.getTranslateY());
    -}
    -
    -function testConcatentate() {
    -  var tx = new goog.math.AffineTransform(1, 2, 3, 4, 5, 6);
    -  tx.concatenate(new goog.math.AffineTransform(2, 1, 6, 5, 4, 3));
    -  assertEquals(5, tx.getScaleX());
    -  assertEquals(8, tx.getShearY());
    -  assertEquals(21, tx.getShearX());
    -  assertEquals(32, tx.getScaleY());
    -  assertEquals(18, tx.getTranslateX());
    -  assertEquals(26, tx.getTranslateY());
    -}
    -
    -function testPreConcatentate() {
    -  var tx = new goog.math.AffineTransform(1, 2, 3, 4, 5, 6);
    -  tx.preConcatenate(new goog.math.AffineTransform(2, 1, 6, 5, 4, 3));
    -  assertEquals(14, tx.getScaleX());
    -  assertEquals(11, tx.getShearY());
    -  assertEquals(30, tx.getShearX());
    -  assertEquals(23, tx.getScaleY());
    -  assertEquals(50, tx.getTranslateX());
    -  assertEquals(38, tx.getTranslateY());
    -}
    -
    -function testAssociativeConcatenate() {
    -  var x = new goog.math.AffineTransform(2, 3, 5, 7, 11, 13).concatenate(
    -      new goog.math.AffineTransform(17, 19, 23, 29, 31, 37));
    -  var y = new goog.math.AffineTransform(17, 19, 23, 29, 31, 37)
    -      .preConcatenate(new goog.math.AffineTransform(2, 3, 5, 7, 11, 13));
    -  assertEquals(x.getScaleX(), y.getScaleX());
    -  assertEquals(x.getShearY(), y.getShearY());
    -  assertEquals(x.getShearX(), y.getShearX());
    -  assertEquals(x.getScaleY(), y.getScaleY());
    -  assertEquals(x.getTranslateX(), y.getTranslateX());
    -  assertEquals(x.getTranslateY(), y.getTranslateY());
    -}
    -
    -function testTransform() {
    -  var srcPts = [0, 0, 1, 0, 1, 1, 0, 1];
    -  var dstPts = [];
    -  var tx = goog.math.AffineTransform.getScaleInstance(2, 3);
    -  tx.translate(5, 10);
    -  tx.rotate(Math.PI / 4, 5, 10);
    -  tx.transform(srcPts, 0, dstPts, 0, 4);
    -  assert(goog.array.equals(
    -      [27.071068, 28.180195, 28.485281, 30.301516,
    -       27.071068, 32.422836, 25.656855, 30.301516],
    -      dstPts,
    -      goog.math.nearlyEquals));
    -}
    -
    -function testGetDeterminant() {
    -  var tx = goog.math.AffineTransform.getScaleInstance(2, 3);
    -  tx.translate(5, 10);
    -  tx.rotate(Math.PI / 4, 5, 10);
    -  assertRoughlyEquals(6, tx.getDeterminant(), 0.001);
    -}
    -
    -function testIsInvertible() {
    -  assertTrue(new goog.math.AffineTransform(2, 3, 4, 5, 6, 7).
    -      isInvertible());
    -  assertTrue(new goog.math.AffineTransform(1, 0, 0, 1, 0, 0).
    -      isInvertible());
    -  assertFalse(new goog.math.AffineTransform(NaN, 0, 0, 1, 0, 0).
    -      isInvertible());
    -  assertFalse(new goog.math.AffineTransform(1, NaN, 0, 1, 0, 0).
    -      isInvertible());
    -  assertFalse(new goog.math.AffineTransform(1, 0, NaN, 1, 0, 0).
    -      isInvertible());
    -  assertFalse(new goog.math.AffineTransform(1, 0, 0, NaN, 0, 0).
    -      isInvertible());
    -  assertFalse(new goog.math.AffineTransform(1, 0, 0, 1, NaN, 0).
    -      isInvertible());
    -  assertFalse(new goog.math.AffineTransform(1, 0, 0, 1, 0, NaN).
    -      isInvertible());
    -  assertFalse(new goog.math.AffineTransform(Infinity, 0, 0, 1, 0, 0).
    -      isInvertible());
    -  assertFalse(new goog.math.AffineTransform(1, Infinity, 0, 1, 0, 0).
    -      isInvertible());
    -  assertFalse(new goog.math.AffineTransform(1, 0, Infinity, 1, 0, 0).
    -      isInvertible());
    -  assertFalse(new goog.math.AffineTransform(1, 0, 0, Infinity, 0, 0).
    -      isInvertible());
    -  assertFalse(new goog.math.AffineTransform(1, 0, 0, 1, Infinity, 0).
    -      isInvertible());
    -  assertFalse(new goog.math.AffineTransform(1, 0, 0, 1, 0, Infinity).
    -      isInvertible());
    -  assertFalse(new goog.math.AffineTransform(0, 0, 0, 0, 1, 0).
    -      isInvertible());
    -}
    -
    -function testCreateInverse() {
    -  var tx = goog.math.AffineTransform.getScaleInstance(2, 3);
    -  tx.translate(5, 10);
    -  tx.rotate(Math.PI / 4, 5, 10);
    -  var inverse = tx.createInverse();
    -  assert(goog.math.nearlyEquals(0.353553, inverse.getScaleX()));
    -  assert(goog.math.nearlyEquals(-0.353553, inverse.getShearY()));
    -  assert(goog.math.nearlyEquals(0.235702, inverse.getShearX()));
    -  assert(goog.math.nearlyEquals(0.235702, inverse.getScaleY()));
    -  assert(goog.math.nearlyEquals(-16.213203, inverse.getTranslateX()));
    -  assert(goog.math.nearlyEquals(2.928932, inverse.getTranslateY()));
    -}
    -
    -function testCopyFrom() {
    -  var from = new goog.math.AffineTransform(1, 2, 3, 4, 5, 6);
    -  var to = new goog.math.AffineTransform();
    -  to.copyFrom(from);
    -  assertEquals(from.getScaleX(), to.getScaleX());
    -  assertEquals(from.getShearY(), to.getShearY());
    -  assertEquals(from.getShearX(), to.getShearX());
    -  assertEquals(from.getScaleY(), to.getScaleY());
    -  assertEquals(from.getTranslateX(), to.getTranslateX());
    -  assertEquals(from.getTranslateY(), to.getTranslateY());
    -}
    -
    -function testToString() {
    -  var tx = new goog.math.AffineTransform(1, 2, 3, 4, 5, 6);
    -  assertEquals('matrix(1,2,3,4,5,6)', tx.toString());
    -}
    -
    -function testEquals() {
    -  var tx1 = new goog.math.AffineTransform(1, 2, 3, 4, 5, 6);
    -  var tx2 = new goog.math.AffineTransform(1, 2, 3, 4, 5, 6);
    -  assertEqualsMethod(tx1, tx2, true);
    -
    -  tx2 = new goog.math.AffineTransform(-1, 2, 3, 4, 5, 6);
    -  assertEqualsMethod(tx1, tx2, false);
    -
    -  tx2 = new goog.math.AffineTransform(1, -1, 3, 4, 5, 6);
    -  assertEqualsMethod(tx1, tx2, false);
    -
    -  tx2 = new goog.math.AffineTransform(1, 2, -3, 4, 5, 6);
    -  assertEqualsMethod(tx1, tx2, false);
    -
    -  tx2 = new goog.math.AffineTransform(1, 2, 3, -4, 5, 6);
    -  assertEqualsMethod(tx1, tx2, false);
    -
    -  tx2 = new goog.math.AffineTransform(1, 2, 3, 4, -5, 6);
    -  assertEqualsMethod(tx1, tx2, false);
    -
    -  tx2 = new goog.math.AffineTransform(1, 2, 3, 4, 5, -6);
    -  assertEqualsMethod(tx1, tx2, false);
    -}
    -
    -function assertEqualsMethod(tx1, tx2, expected) {
    -  assertEquals(expected, tx1.equals(tx2));
    -  assertEquals(expected, tx2.equals(tx1));
    -  assertEquals(true, tx1.equals(tx1));
    -  assertEquals(true, tx2.equals(tx2));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/math/bezier.js b/src/database/third_party/closure-library/closure/goog/math/bezier.js
    deleted file mode 100644
    index 8aaa93375eb..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/bezier.js
    +++ /dev/null
    @@ -1,340 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Represents a cubic Bezier curve.
    - *
    - * Uses the deCasteljau algorithm to compute points on the curve.
    - * http://en.wikipedia.org/wiki/De_Casteljau's_algorithm
    - *
    - * Currently it uses an unrolled version of the algorithm for speed.  Eventually
    - * it may be useful to use the loop form of the algorithm in order to support
    - * curves of arbitrary degree.
    - *
    - * @author robbyw@google.com (Robby Walker)
    - */
    -
    -goog.provide('goog.math.Bezier');
    -
    -goog.require('goog.math');
    -goog.require('goog.math.Coordinate');
    -
    -
    -
    -/**
    - * Object representing a cubic bezier curve.
    - * @param {number} x0 X coordinate of the start point.
    - * @param {number} y0 Y coordinate of the start point.
    - * @param {number} x1 X coordinate of the first control point.
    - * @param {number} y1 Y coordinate of the first control point.
    - * @param {number} x2 X coordinate of the second control point.
    - * @param {number} y2 Y coordinate of the second control point.
    - * @param {number} x3 X coordinate of the end point.
    - * @param {number} y3 Y coordinate of the end point.
    - * @struct
    - * @constructor
    - * @final
    - */
    -goog.math.Bezier = function(x0, y0, x1, y1, x2, y2, x3, y3) {
    -  /**
    -   * X coordinate of the first point.
    -   * @type {number}
    -   */
    -  this.x0 = x0;
    -
    -  /**
    -   * Y coordinate of the first point.
    -   * @type {number}
    -   */
    -  this.y0 = y0;
    -
    -  /**
    -   * X coordinate of the first control point.
    -   * @type {number}
    -   */
    -  this.x1 = x1;
    -
    -  /**
    -   * Y coordinate of the first control point.
    -   * @type {number}
    -   */
    -  this.y1 = y1;
    -
    -  /**
    -   * X coordinate of the second control point.
    -   * @type {number}
    -   */
    -  this.x2 = x2;
    -
    -  /**
    -   * Y coordinate of the second control point.
    -   * @type {number}
    -   */
    -  this.y2 = y2;
    -
    -  /**
    -   * X coordinate of the end point.
    -   * @type {number}
    -   */
    -  this.x3 = x3;
    -
    -  /**
    -   * Y coordinate of the end point.
    -   * @type {number}
    -   */
    -  this.y3 = y3;
    -};
    -
    -
    -/**
    - * Constant used to approximate ellipses.
    - * See: http://canvaspaint.org/blog/2006/12/ellipse/
    - * @type {number}
    - */
    -goog.math.Bezier.KAPPA = 4 * (Math.sqrt(2) - 1) / 3;
    -
    -
    -/**
    - * @return {!goog.math.Bezier} A copy of this curve.
    - */
    -goog.math.Bezier.prototype.clone = function() {
    -  return new goog.math.Bezier(this.x0, this.y0, this.x1, this.y1, this.x2,
    -      this.y2, this.x3, this.y3);
    -};
    -
    -
    -/**
    - * Test if the given curve is exactly the same as this one.
    - * @param {goog.math.Bezier} other The other curve.
    - * @return {boolean} Whether the given curve is the same as this one.
    - */
    -goog.math.Bezier.prototype.equals = function(other) {
    -  return this.x0 == other.x0 && this.y0 == other.y0 && this.x1 == other.x1 &&
    -         this.y1 == other.y1 && this.x2 == other.x2 && this.y2 == other.y2 &&
    -         this.x3 == other.x3 && this.y3 == other.y3;
    -};
    -
    -
    -/**
    - * Modifies the curve in place to progress in the opposite direction.
    - */
    -goog.math.Bezier.prototype.flip = function() {
    -  var temp = this.x0;
    -  this.x0 = this.x3;
    -  this.x3 = temp;
    -  temp = this.y0;
    -  this.y0 = this.y3;
    -  this.y3 = temp;
    -
    -  temp = this.x1;
    -  this.x1 = this.x2;
    -  this.x2 = temp;
    -  temp = this.y1;
    -  this.y1 = this.y2;
    -  this.y2 = temp;
    -};
    -
    -
    -/**
    - * Computes the curve's X coordinate at a point between 0 and 1.
    - * @param {number} t The point on the curve to find.
    - * @return {number} The computed coordinate.
    - */
    -goog.math.Bezier.prototype.getPointX = function(t) {
    -  // Special case start and end.
    -  if (t == 0) {
    -    return this.x0;
    -  } else if (t == 1) {
    -    return this.x3;
    -  }
    -
    -  // Step one - from 4 points to 3
    -  var ix0 = goog.math.lerp(this.x0, this.x1, t);
    -  var ix1 = goog.math.lerp(this.x1, this.x2, t);
    -  var ix2 = goog.math.lerp(this.x2, this.x3, t);
    -
    -  // Step two - from 3 points to 2
    -  ix0 = goog.math.lerp(ix0, ix1, t);
    -  ix1 = goog.math.lerp(ix1, ix2, t);
    -
    -  // Final step - last point
    -  return goog.math.lerp(ix0, ix1, t);
    -};
    -
    -
    -/**
    - * Computes the curve's Y coordinate at a point between 0 and 1.
    - * @param {number} t The point on the curve to find.
    - * @return {number} The computed coordinate.
    - */
    -goog.math.Bezier.prototype.getPointY = function(t) {
    -  // Special case start and end.
    -  if (t == 0) {
    -    return this.y0;
    -  } else if (t == 1) {
    -    return this.y3;
    -  }
    -
    -  // Step one - from 4 points to 3
    -  var iy0 = goog.math.lerp(this.y0, this.y1, t);
    -  var iy1 = goog.math.lerp(this.y1, this.y2, t);
    -  var iy2 = goog.math.lerp(this.y2, this.y3, t);
    -
    -  // Step two - from 3 points to 2
    -  iy0 = goog.math.lerp(iy0, iy1, t);
    -  iy1 = goog.math.lerp(iy1, iy2, t);
    -
    -  // Final step - last point
    -  return goog.math.lerp(iy0, iy1, t);
    -};
    -
    -
    -/**
    - * Computes the curve at a point between 0 and 1.
    - * @param {number} t The point on the curve to find.
    - * @return {!goog.math.Coordinate} The computed coordinate.
    - */
    -goog.math.Bezier.prototype.getPoint = function(t) {
    -  return new goog.math.Coordinate(this.getPointX(t), this.getPointY(t));
    -};
    -
    -
    -/**
    - * Changes this curve in place to be the portion of itself from [t, 1].
    - * @param {number} t The start of the desired portion of the curve.
    - */
    -goog.math.Bezier.prototype.subdivideLeft = function(t) {
    -  if (t == 1) {
    -    return;
    -  }
    -
    -  // Step one - from 4 points to 3
    -  var ix0 = goog.math.lerp(this.x0, this.x1, t);
    -  var iy0 = goog.math.lerp(this.y0, this.y1, t);
    -
    -  var ix1 = goog.math.lerp(this.x1, this.x2, t);
    -  var iy1 = goog.math.lerp(this.y1, this.y2, t);
    -
    -  var ix2 = goog.math.lerp(this.x2, this.x3, t);
    -  var iy2 = goog.math.lerp(this.y2, this.y3, t);
    -
    -  // Collect our new x1 and y1
    -  this.x1 = ix0;
    -  this.y1 = iy0;
    -
    -  // Step two - from 3 points to 2
    -  ix0 = goog.math.lerp(ix0, ix1, t);
    -  iy0 = goog.math.lerp(iy0, iy1, t);
    -
    -  ix1 = goog.math.lerp(ix1, ix2, t);
    -  iy1 = goog.math.lerp(iy1, iy2, t);
    -
    -  // Collect our new x2 and y2
    -  this.x2 = ix0;
    -  this.y2 = iy0;
    -
    -  // Final step - last point
    -  this.x3 = goog.math.lerp(ix0, ix1, t);
    -  this.y3 = goog.math.lerp(iy0, iy1, t);
    -};
    -
    -
    -/**
    - * Changes this curve in place to be the portion of itself from [0, t].
    - * @param {number} t The end of the desired portion of the curve.
    - */
    -goog.math.Bezier.prototype.subdivideRight = function(t) {
    -  this.flip();
    -  this.subdivideLeft(1 - t);
    -  this.flip();
    -};
    -
    -
    -/**
    - * Changes this curve in place to be the portion of itself from [s, t].
    - * @param {number} s The start of the desired portion of the curve.
    - * @param {number} t The end of the desired portion of the curve.
    - */
    -goog.math.Bezier.prototype.subdivide = function(s, t) {
    -  this.subdivideRight(s);
    -  this.subdivideLeft((t - s) / (1 - s));
    -};
    -
    -
    -/**
    - * Computes the position t of a point on the curve given its x coordinate.
    - * That is, for an input xVal, finds t s.t. getPointX(t) = xVal.
    - * As such, the following should always be true up to some small epsilon:
    - * t ~ solvePositionFromXValue(getPointX(t)) for t in [0, 1].
    - * @param {number} xVal The x coordinate of the point to find on the curve.
    - * @return {number} The position t.
    - */
    -goog.math.Bezier.prototype.solvePositionFromXValue = function(xVal) {
    -  // Desired precision on the computation.
    -  var epsilon = 1e-6;
    -
    -  // Initial estimate of t using linear interpolation.
    -  var t = (xVal - this.x0) / (this.x3 - this.x0);
    -  if (t <= 0) {
    -    return 0;
    -  } else if (t >= 1) {
    -    return 1;
    -  }
    -
    -  // Try gradient descent to solve for t. If it works, it is very fast.
    -  var tMin = 0;
    -  var tMax = 1;
    -  for (var i = 0; i < 8; i++) {
    -    var value = this.getPointX(t);
    -    var derivative = (this.getPointX(t + epsilon) - value) / epsilon;
    -    if (Math.abs(value - xVal) < epsilon) {
    -      return t;
    -    } else if (Math.abs(derivative) < epsilon) {
    -      break;
    -    } else {
    -      if (value < xVal) {
    -        tMin = t;
    -      } else {
    -        tMax = t;
    -      }
    -      t -= (value - xVal) / derivative;
    -    }
    -  }
    -
    -  // If the gradient descent got stuck in a local minimum, e.g. because
    -  // the derivative was close to 0, use a Dichotomy refinement instead.
    -  // We limit the number of interations to 8.
    -  for (var i = 0; Math.abs(value - xVal) > epsilon && i < 8; i++) {
    -    if (value < xVal) {
    -      tMin = t;
    -      t = (t + tMax) / 2;
    -    } else {
    -      tMax = t;
    -      t = (t + tMin) / 2;
    -    }
    -    value = this.getPointX(t);
    -  }
    -  return t;
    -};
    -
    -
    -/**
    - * Computes the y coordinate of a point on the curve given its x coordinate.
    - * @param {number} xVal The x coordinate of the point on the curve.
    - * @return {number} The y coordinate of the point on the curve.
    - */
    -goog.math.Bezier.prototype.solveYValueFromXValue = function(xVal) {
    -  return this.getPointY(this.solvePositionFromXValue(xVal));
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/math/bezier_test.html b/src/database/third_party/closure-library/closure/goog/math/bezier_test.html
    deleted file mode 100644
    index 17c50ac936f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/bezier_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.math.Bezier
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.math.BezierTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/math/bezier_test.js b/src/database/third_party/closure-library/closure/goog/math/bezier_test.js
    deleted file mode 100644
    index 662fc9c4746..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/bezier_test.js
    +++ /dev/null
    @@ -1,126 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.math.BezierTest');
    -goog.setTestOnly('goog.math.BezierTest');
    -
    -goog.require('goog.math');
    -goog.require('goog.math.Bezier');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.testing.jsunit');
    -
    -function testEquals() {
    -  var input = new goog.math.Bezier(1, 2, 3, 4, 5, 6, 7, 8);
    -
    -  assert(input.equals(input));
    -}
    -
    -function testClone() {
    -  var input = new goog.math.Bezier(1, 2, 3, 4, 5, 6, 7, 8);
    -
    -  assertNotEquals('Clone returns a new object', input, input.clone());
    -  assert('Contents of clone match original', input.equals(input.clone()));
    -}
    -
    -function testFlip() {
    -  var input = new goog.math.Bezier(1, 1, 2, 2, 3, 3, 4, 4);
    -  var compare = new goog.math.Bezier(4, 4, 3, 3, 2, 2, 1, 1);
    -
    -  var flipped = input.clone();
    -  flipped.flip();
    -  assert('Flipped behaves as expected', compare.equals(flipped));
    -
    -  flipped.flip();
    -  assert('Flipping twice gives original', input.equals(flipped));
    -}
    -
    -function testGetPoint() {
    -  var input = new goog.math.Bezier(0, 1, 1, 2, 2, 3, 3, 4);
    -
    -  assert(goog.math.Coordinate.equals(input.getPoint(0),
    -      new goog.math.Coordinate(0, 1)));
    -  assert(goog.math.Coordinate.equals(input.getPoint(1),
    -      new goog.math.Coordinate(3, 4)));
    -  assert(goog.math.Coordinate.equals(input.getPoint(0.5),
    -      new goog.math.Coordinate(1.5, 2.5)));
    -}
    -
    -function testGetPointX() {
    -  var input = new goog.math.Bezier(0, 1, 1, 2, 2, 3, 3, 4);
    -
    -  assert(goog.math.nearlyEquals(input.getPointX(0), 0));
    -  assert(goog.math.nearlyEquals(input.getPointX(1), 3));
    -  assert(goog.math.nearlyEquals(input.getPointX(0.5), 1.5));
    -}
    -
    -function testGetPointY() {
    -  var input = new goog.math.Bezier(0, 1, 1, 2, 2, 3, 3, 4);
    -
    -  assert(goog.math.nearlyEquals(input.getPointY(0), 1));
    -  assert(goog.math.nearlyEquals(input.getPointY(1), 4));
    -  assert(goog.math.nearlyEquals(input.getPointY(0.5), 2.5));
    -}
    -
    -function testSubdivide() {
    -  var input = new goog.math.Bezier(0, 1, 1, 2, 2, 3, 3, 4);
    -
    -  input.subdivide(1 / 3, 2 / 3);
    -
    -  assert(goog.math.nearlyEquals(1, input.x0));
    -  assert(goog.math.nearlyEquals(2, input.y0));
    -  assert(goog.math.nearlyEquals(2, input.x3));
    -  assert(goog.math.nearlyEquals(3, input.y3));
    -}
    -
    -function testSolvePositionFromXValue() {
    -  var eps = 1e-6;
    -  var bezier = new goog.math.Bezier(0, 0, 0.25, 0.1, 0.25, 1, 1, 1);
    -  var pt = bezier.getPoint(0.5);
    -  assertRoughlyEquals(0.3125, pt.x, eps);
    -  assertRoughlyEquals(0.5375, pt.y, eps);
    -  assertRoughlyEquals(0.321,
    -      bezier.solvePositionFromXValue(bezier.getPoint(0.321).x), eps);
    -}
    -
    -function testSolveYValueFromXValue() {
    -  var eps = 1e-6;
    -  // The following example is taken from
    -  // http://www.netzgesta.de/dev/cubic-bezier-timing-function.html.
    -  // The timing values shown in that page are 1 - <value> so the
    -  // bezier curves in this test are constructed with 1 - ctrl points.
    -  // E.g. ctrl points (0, 0, 0.25, 0.1, 0.25, 1, 1, 1) become
    -  // (1, 1, 0.75, 0, 0.75, 0.9, 0, 0) here. Since chanding the order of
    -  // the ctrl points does not affect the shape of the curve, once can also
    -  // have (0, 0, 0.75, 0.9, 0.75, 0, 1, 1).
    -
    -  // netzgesta example.
    -  var bezier = new goog.math.Bezier(1, 1, 0.75, 0.9, 0.75, 0, 0, 0);
    -  assertRoughlyEquals(0.024374631, bezier.solveYValueFromXValue(0.2), eps);
    -  assertRoughlyEquals(0.317459494, bezier.solveYValueFromXValue(0.6), eps);
    -  assertRoughlyEquals(0.905205002, bezier.solveYValueFromXValue(0.9), eps);
    -
    -  // netzgesta example with ctrl points in the reverse order so that 1st and
    -  // last ctrl points are (0, 0) and (1, 1). Note the result is exactly the
    -  // same.
    -  bezier = new goog.math.Bezier(0, 0, 0.75, 0, 0.75, 0.9, 1, 1);
    -  assertRoughlyEquals(0.024374631, bezier.solveYValueFromXValue(0.2), eps);
    -  assertRoughlyEquals(0.317459494, bezier.solveYValueFromXValue(0.6), eps);
    -  assertRoughlyEquals(0.905205002, bezier.solveYValueFromXValue(0.9), eps);
    -
    -  // Ease-out css animation timing in webkit.
    -  bezier = new goog.math.Bezier(0, 0, 0, 0, 0.58, 1, 1, 1);
    -  assertRoughlyEquals(0.308366667, bezier.solveYValueFromXValue(0.2), eps);
    -  assertRoughlyEquals(0.785139061, bezier.solveYValueFromXValue(0.6), eps);
    -  assertRoughlyEquals(0.982973389, bezier.solveYValueFromXValue(0.9), eps);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/math/box.js b/src/database/third_party/closure-library/closure/goog/math/box.js
    deleted file mode 100644
    index 63ebc0dc92a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/box.js
    +++ /dev/null
    @@ -1,389 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A utility class for representing a numeric box.
    - */
    -
    -
    -goog.provide('goog.math.Box');
    -
    -goog.require('goog.math.Coordinate');
    -
    -
    -
    -/**
    - * Class for representing a box. A box is specified as a top, right, bottom,
    - * and left. A box is useful for representing margins and padding.
    - *
    - * This class assumes 'screen coordinates': larger Y coordinates are further
    - * from the top of the screen.
    - *
    - * @param {number} top Top.
    - * @param {number} right Right.
    - * @param {number} bottom Bottom.
    - * @param {number} left Left.
    - * @struct
    - * @constructor
    - */
    -goog.math.Box = function(top, right, bottom, left) {
    -  /**
    -   * Top
    -   * @type {number}
    -   */
    -  this.top = top;
    -
    -  /**
    -   * Right
    -   * @type {number}
    -   */
    -  this.right = right;
    -
    -  /**
    -   * Bottom
    -   * @type {number}
    -   */
    -  this.bottom = bottom;
    -
    -  /**
    -   * Left
    -   * @type {number}
    -   */
    -  this.left = left;
    -};
    -
    -
    -/**
    - * Creates a Box by bounding a collection of goog.math.Coordinate objects
    - * @param {...goog.math.Coordinate} var_args Coordinates to be included inside
    - *     the box.
    - * @return {!goog.math.Box} A Box containing all the specified Coordinates.
    - */
    -goog.math.Box.boundingBox = function(var_args) {
    -  var box = new goog.math.Box(arguments[0].y, arguments[0].x,
    -                              arguments[0].y, arguments[0].x);
    -  for (var i = 1; i < arguments.length; i++) {
    -    var coord = arguments[i];
    -    box.top = Math.min(box.top, coord.y);
    -    box.right = Math.max(box.right, coord.x);
    -    box.bottom = Math.max(box.bottom, coord.y);
    -    box.left = Math.min(box.left, coord.x);
    -  }
    -  return box;
    -};
    -
    -
    -/**
    - * @return {number} width The width of this Box.
    - */
    -goog.math.Box.prototype.getWidth = function() {
    -  return this.right - this.left;
    -};
    -
    -
    -/**
    - * @return {number} height The height of this Box.
    - */
    -goog.math.Box.prototype.getHeight = function() {
    -  return this.bottom - this.top;
    -};
    -
    -
    -/**
    - * Creates a copy of the box with the same dimensions.
    - * @return {!goog.math.Box} A clone of this Box.
    - */
    -goog.math.Box.prototype.clone = function() {
    -  return new goog.math.Box(this.top, this.right, this.bottom, this.left);
    -};
    -
    -
    -if (goog.DEBUG) {
    -  /**
    -   * Returns a nice string representing the box.
    -   * @return {string} In the form (50t, 73r, 24b, 13l).
    -   * @override
    -   */
    -  goog.math.Box.prototype.toString = function() {
    -    return '(' + this.top + 't, ' + this.right + 'r, ' + this.bottom + 'b, ' +
    -           this.left + 'l)';
    -  };
    -}
    -
    -
    -/**
    - * Returns whether the box contains a coordinate or another box.
    - *
    - * @param {goog.math.Coordinate|goog.math.Box} other A Coordinate or a Box.
    - * @return {boolean} Whether the box contains the coordinate or other box.
    - */
    -goog.math.Box.prototype.contains = function(other) {
    -  return goog.math.Box.contains(this, other);
    -};
    -
    -
    -/**
    - * Expands box with the given margins.
    - *
    - * @param {number|goog.math.Box} top Top margin or box with all margins.
    - * @param {number=} opt_right Right margin.
    - * @param {number=} opt_bottom Bottom margin.
    - * @param {number=} opt_left Left margin.
    - * @return {!goog.math.Box} A reference to this Box.
    - */
    -goog.math.Box.prototype.expand = function(top, opt_right, opt_bottom,
    -    opt_left) {
    -  if (goog.isObject(top)) {
    -    this.top -= top.top;
    -    this.right += top.right;
    -    this.bottom += top.bottom;
    -    this.left -= top.left;
    -  } else {
    -    this.top -= top;
    -    this.right += opt_right;
    -    this.bottom += opt_bottom;
    -    this.left -= opt_left;
    -  }
    -
    -  return this;
    -};
    -
    -
    -/**
    - * Expand this box to include another box.
    - * NOTE(user): This is used in code that needs to be very fast, please don't
    - * add functionality to this function at the expense of speed (variable
    - * arguments, accepting multiple argument types, etc).
    - * @param {goog.math.Box} box The box to include in this one.
    - */
    -goog.math.Box.prototype.expandToInclude = function(box) {
    -  this.left = Math.min(this.left, box.left);
    -  this.top = Math.min(this.top, box.top);
    -  this.right = Math.max(this.right, box.right);
    -  this.bottom = Math.max(this.bottom, box.bottom);
    -};
    -
    -
    -/**
    - * Compares boxes for equality.
    - * @param {goog.math.Box} a A Box.
    - * @param {goog.math.Box} b A Box.
    - * @return {boolean} True iff the boxes are equal, or if both are null.
    - */
    -goog.math.Box.equals = function(a, b) {
    -  if (a == b) {
    -    return true;
    -  }
    -  if (!a || !b) {
    -    return false;
    -  }
    -  return a.top == b.top && a.right == b.right &&
    -         a.bottom == b.bottom && a.left == b.left;
    -};
    -
    -
    -/**
    - * Returns whether a box contains a coordinate or another box.
    - *
    - * @param {goog.math.Box} box A Box.
    - * @param {goog.math.Coordinate|goog.math.Box} other A Coordinate or a Box.
    - * @return {boolean} Whether the box contains the coordinate or other box.
    - */
    -goog.math.Box.contains = function(box, other) {
    -  if (!box || !other) {
    -    return false;
    -  }
    -
    -  if (other instanceof goog.math.Box) {
    -    return other.left >= box.left && other.right <= box.right &&
    -        other.top >= box.top && other.bottom <= box.bottom;
    -  }
    -
    -  // other is a Coordinate.
    -  return other.x >= box.left && other.x <= box.right &&
    -         other.y >= box.top && other.y <= box.bottom;
    -};
    -
    -
    -/**
    - * Returns the relative x position of a coordinate compared to a box.  Returns
    - * zero if the coordinate is inside the box.
    - *
    - * @param {goog.math.Box} box A Box.
    - * @param {goog.math.Coordinate} coord A Coordinate.
    - * @return {number} The x position of {@code coord} relative to the nearest
    - *     side of {@code box}, or zero if {@code coord} is inside {@code box}.
    - */
    -goog.math.Box.relativePositionX = function(box, coord) {
    -  if (coord.x < box.left) {
    -    return coord.x - box.left;
    -  } else if (coord.x > box.right) {
    -    return coord.x - box.right;
    -  }
    -  return 0;
    -};
    -
    -
    -/**
    - * Returns the relative y position of a coordinate compared to a box.  Returns
    - * zero if the coordinate is inside the box.
    - *
    - * @param {goog.math.Box} box A Box.
    - * @param {goog.math.Coordinate} coord A Coordinate.
    - * @return {number} The y position of {@code coord} relative to the nearest
    - *     side of {@code box}, or zero if {@code coord} is inside {@code box}.
    - */
    -goog.math.Box.relativePositionY = function(box, coord) {
    -  if (coord.y < box.top) {
    -    return coord.y - box.top;
    -  } else if (coord.y > box.bottom) {
    -    return coord.y - box.bottom;
    -  }
    -  return 0;
    -};
    -
    -
    -/**
    - * Returns the distance between a coordinate and the nearest corner/side of a
    - * box. Returns zero if the coordinate is inside the box.
    - *
    - * @param {goog.math.Box} box A Box.
    - * @param {goog.math.Coordinate} coord A Coordinate.
    - * @return {number} The distance between {@code coord} and the nearest
    - *     corner/side of {@code box}, or zero if {@code coord} is inside
    - *     {@code box}.
    - */
    -goog.math.Box.distance = function(box, coord) {
    -  var x = goog.math.Box.relativePositionX(box, coord);
    -  var y = goog.math.Box.relativePositionY(box, coord);
    -  return Math.sqrt(x * x + y * y);
    -};
    -
    -
    -/**
    - * Returns whether two boxes intersect.
    - *
    - * @param {goog.math.Box} a A Box.
    - * @param {goog.math.Box} b A second Box.
    - * @return {boolean} Whether the boxes intersect.
    - */
    -goog.math.Box.intersects = function(a, b) {
    -  return (a.left <= b.right && b.left <= a.right &&
    -          a.top <= b.bottom && b.top <= a.bottom);
    -};
    -
    -
    -/**
    - * Returns whether two boxes would intersect with additional padding.
    - *
    - * @param {goog.math.Box} a A Box.
    - * @param {goog.math.Box} b A second Box.
    - * @param {number} padding The additional padding.
    - * @return {boolean} Whether the boxes intersect.
    - */
    -goog.math.Box.intersectsWithPadding = function(a, b, padding) {
    -  return (a.left <= b.right + padding && b.left <= a.right + padding &&
    -          a.top <= b.bottom + padding && b.top <= a.bottom + padding);
    -};
    -
    -
    -/**
    - * Rounds the fields to the next larger integer values.
    - *
    - * @return {!goog.math.Box} This box with ceil'd fields.
    - */
    -goog.math.Box.prototype.ceil = function() {
    -  this.top = Math.ceil(this.top);
    -  this.right = Math.ceil(this.right);
    -  this.bottom = Math.ceil(this.bottom);
    -  this.left = Math.ceil(this.left);
    -  return this;
    -};
    -
    -
    -/**
    - * Rounds the fields to the next smaller integer values.
    - *
    - * @return {!goog.math.Box} This box with floored fields.
    - */
    -goog.math.Box.prototype.floor = function() {
    -  this.top = Math.floor(this.top);
    -  this.right = Math.floor(this.right);
    -  this.bottom = Math.floor(this.bottom);
    -  this.left = Math.floor(this.left);
    -  return this;
    -};
    -
    -
    -/**
    - * Rounds the fields to nearest integer values.
    - *
    - * @return {!goog.math.Box} This box with rounded fields.
    - */
    -goog.math.Box.prototype.round = function() {
    -  this.top = Math.round(this.top);
    -  this.right = Math.round(this.right);
    -  this.bottom = Math.round(this.bottom);
    -  this.left = Math.round(this.left);
    -  return this;
    -};
    -
    -
    -/**
    - * Translates this box by the given offsets. If a {@code goog.math.Coordinate}
    - * is given, then the left and right values are translated by the coordinate's
    - * x value and the top and bottom values are translated by the coordinate's y
    - * value.  Otherwise, {@code tx} and {@code opt_ty} are used to translate the x
    - * and y dimension values.
    - *
    - * @param {number|goog.math.Coordinate} tx The value to translate the x
    - *     dimension values by or the the coordinate to translate this box by.
    - * @param {number=} opt_ty The value to translate y dimension values by.
    - * @return {!goog.math.Box} This box after translating.
    - */
    -goog.math.Box.prototype.translate = function(tx, opt_ty) {
    -  if (tx instanceof goog.math.Coordinate) {
    -    this.left += tx.x;
    -    this.right += tx.x;
    -    this.top += tx.y;
    -    this.bottom += tx.y;
    -  } else {
    -    this.left += tx;
    -    this.right += tx;
    -    if (goog.isNumber(opt_ty)) {
    -      this.top += opt_ty;
    -      this.bottom += opt_ty;
    -    }
    -  }
    -  return this;
    -};
    -
    -
    -/**
    - * Scales this coordinate by the given scale factors. The x and y dimension
    - * values are scaled by {@code sx} and {@code opt_sy} respectively.
    - * If {@code opt_sy} is not given, then {@code sx} is used for both x and y.
    - *
    - * @param {number} sx The scale factor to use for the x dimension.
    - * @param {number=} opt_sy The scale factor to use for the y dimension.
    - * @return {!goog.math.Box} This box after scaling.
    - */
    -goog.math.Box.prototype.scale = function(sx, opt_sy) {
    -  var sy = goog.isNumber(opt_sy) ? opt_sy : sx;
    -  this.left *= sx;
    -  this.right *= sx;
    -  this.top *= sy;
    -  this.bottom *= sy;
    -  return this;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/math/box_test.html b/src/database/third_party/closure-library/closure/goog/math/box_test.html
    deleted file mode 100644
    index afc64390aea..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/box_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.math.Box
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.math.BoxTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/math/box_test.js b/src/database/third_party/closure-library/closure/goog/math/box_test.js
    deleted file mode 100644
    index a33e85d56c4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/box_test.js
    +++ /dev/null
    @@ -1,321 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.math.BoxTest');
    -goog.setTestOnly('goog.math.BoxTest');
    -
    -goog.require('goog.math.Box');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.testing.jsunit');
    -
    -function testBoxEquals() {
    -  var a = new goog.math.Box(1, 2, 3, 4);
    -  var b = new goog.math.Box(1, 2, 3, 4);
    -  assertTrue(goog.math.Box.equals(a, a));
    -  assertTrue(goog.math.Box.equals(a, b));
    -  assertTrue(goog.math.Box.equals(b, a));
    -
    -  assertFalse('Box should not equal null.', goog.math.Box.equals(a, null));
    -  assertFalse('Box should not equal null.', goog.math.Box.equals(null, a));
    -
    -  assertFalse(goog.math.Box.equals(a, new goog.math.Box(4, 2, 3, 4)));
    -  assertFalse(goog.math.Box.equals(a, new goog.math.Box(1, 4, 3, 4)));
    -  assertFalse(goog.math.Box.equals(a, new goog.math.Box(1, 2, 4, 4)));
    -  assertFalse(goog.math.Box.equals(a, new goog.math.Box(1, 2, 3, 1)));
    -
    -  assertTrue('Null boxes should be equal.', goog.math.Box.equals(null, null));
    -}
    -
    -function testBoxClone() {
    -  var b = new goog.math.Box(0, 0, 0, 0);
    -  assertTrue(goog.math.Box.equals(b, b.clone()));
    -
    -  b.left = 0;
    -  b.top = 1;
    -  b.right = 2;
    -  b.bottom = 3;
    -  assertTrue(goog.math.Box.equals(b, b.clone()));
    -}
    -
    -function testBoxRelativePositionX() {
    -  var box = new goog.math.Box(50, 100, 100, 50);
    -
    -  assertEquals(0,
    -      goog.math.Box.relativePositionX(box, new goog.math.Coordinate(75, 0)));
    -  assertEquals(0,
    -      goog.math.Box.relativePositionX(box, new goog.math.Coordinate(75, 75)));
    -  assertEquals(0,
    -      goog.math.Box.relativePositionX(box, new goog.math.Coordinate(75, 105)));
    -  assertEquals(-5,
    -      goog.math.Box.relativePositionX(box, new goog.math.Coordinate(45, 75)));
    -  assertEquals(5,
    -      goog.math.Box.relativePositionX(box, new goog.math.Coordinate(105, 75)));
    -}
    -
    -function testBoxRelativePositionY() {
    -  var box = new goog.math.Box(50, 100, 100, 50);
    -
    -  assertEquals(0,
    -      goog.math.Box.relativePositionY(box, new goog.math.Coordinate(0, 75)));
    -  assertEquals(0,
    -      goog.math.Box.relativePositionY(box, new goog.math.Coordinate(75, 75)));
    -  assertEquals(0,
    -      goog.math.Box.relativePositionY(box, new goog.math.Coordinate(105, 75)));
    -  assertEquals(-5,
    -      goog.math.Box.relativePositionY(box, new goog.math.Coordinate(75, 45)));
    -  assertEquals(5,
    -      goog.math.Box.relativePositionY(box, new goog.math.Coordinate(75, 105)));
    -}
    -
    -function testBoxDistance() {
    -  var box = new goog.math.Box(50, 100, 100, 50);
    -
    -  assertEquals(0,
    -               goog.math.Box.distance(box, new goog.math.Coordinate(75, 75)));
    -  assertEquals(25,
    -               goog.math.Box.distance(box, new goog.math.Coordinate(75, 25)));
    -  assertEquals(10,
    -               goog.math.Box.distance(box, new goog.math.Coordinate(40, 80)));
    -  assertEquals(5,
    -               goog.math.Box.distance(box, new goog.math.Coordinate(46, 47)));
    -  assertEquals(10,
    -               goog.math.Box.distance(box, new goog.math.Coordinate(106, 108)));
    -}
    -
    -function testBoxContains() {
    -  var box = new goog.math.Box(50, 100, 100, 50);
    -
    -  assertTrue(goog.math.Box.contains(box, new goog.math.Coordinate(75, 75)));
    -  assertTrue(goog.math.Box.contains(box, new goog.math.Coordinate(50, 100)));
    -  assertTrue(goog.math.Box.contains(box, new goog.math.Coordinate(100, 99)));
    -  assertFalse(goog.math.Box.contains(box, new goog.math.Coordinate(100, 101)));
    -  assertFalse(goog.math.Box.contains(box, new goog.math.Coordinate(49, 50)));
    -  assertFalse(goog.math.Box.contains(box, new goog.math.Coordinate(25, 25)));
    -}
    -
    -function testBoxContainsBox() {
    -  var box = new goog.math.Box(50, 100, 100, 50);
    -
    -  function assertContains(boxB) {
    -    assertTrue(box + ' expected to contain ' + boxB,
    -        goog.math.Box.contains(box, boxB));
    -  }
    -
    -  function assertNotContains(boxB) {
    -    assertFalse(box + ' expected to not contain ' + boxB,
    -        goog.math.Box.contains(box, boxB));
    -  }
    -
    -  assertContains(new goog.math.Box(60, 90, 90, 60));
    -  assertNotContains(new goog.math.Box(1, 3, 4, 2));
    -  assertNotContains(new goog.math.Box(30, 90, 60, 60));
    -  assertNotContains(new goog.math.Box(60, 110, 60, 60));
    -  assertNotContains(new goog.math.Box(60, 90, 110, 60));
    -  assertNotContains(new goog.math.Box(60, 90, 60, 40));
    -}
    -
    -function testBoxesIntersect() {
    -  var box = new goog.math.Box(50, 100, 100, 50);
    -
    -  function assertIntersects(boxB) {
    -    assertTrue(box + ' expected to intersect ' + boxB,
    -        goog.math.Box.intersects(box, boxB));
    -  }
    -  function assertNotIntersects(boxB) {
    -    assertFalse(box + ' expected to not intersect ' + boxB,
    -        goog.math.Box.intersects(box, boxB));
    -  }
    -
    -  assertIntersects(box);
    -  assertIntersects(new goog.math.Box(20, 80, 80, 20));
    -  assertIntersects(new goog.math.Box(50, 80, 100, 20));
    -  assertIntersects(new goog.math.Box(80, 80, 120, 20));
    -  assertIntersects(new goog.math.Box(20, 100, 80, 50));
    -  assertIntersects(new goog.math.Box(80, 100, 120, 50));
    -  assertIntersects(new goog.math.Box(20, 120, 80, 80));
    -  assertIntersects(new goog.math.Box(50, 120, 100, 80));
    -  assertIntersects(new goog.math.Box(80, 120, 120, 80));
    -  assertIntersects(new goog.math.Box(20, 120, 120, 20));
    -  assertIntersects(new goog.math.Box(70, 80, 80, 70));
    -  assertNotIntersects(new goog.math.Box(10, 30, 30, 10));
    -  assertNotIntersects(new goog.math.Box(10, 70, 30, 30));
    -  assertNotIntersects(new goog.math.Box(10, 100, 30, 50));
    -  assertNotIntersects(new goog.math.Box(10, 120, 30, 80));
    -  assertNotIntersects(new goog.math.Box(10, 140, 30, 120));
    -  assertNotIntersects(new goog.math.Box(30, 30, 70, 10));
    -  assertNotIntersects(new goog.math.Box(30, 140, 70, 120));
    -  assertNotIntersects(new goog.math.Box(50, 30, 100, 10));
    -  assertNotIntersects(new goog.math.Box(50, 140, 100, 120));
    -  assertNotIntersects(new goog.math.Box(80, 30, 120, 10));
    -  assertNotIntersects(new goog.math.Box(80, 140, 120, 120));
    -  assertNotIntersects(new goog.math.Box(120, 30, 140, 10));
    -  assertNotIntersects(new goog.math.Box(120, 70, 140, 30));
    -  assertNotIntersects(new goog.math.Box(120, 100, 140, 50));
    -  assertNotIntersects(new goog.math.Box(120, 120, 140, 80));
    -  assertNotIntersects(new goog.math.Box(120, 140, 140, 120));
    -}
    -
    -function testBoxesIntersectWithPadding() {
    -  var box = new goog.math.Box(50, 100, 100, 50);
    -
    -  function assertIntersects(boxB, padding) {
    -    assertTrue(box + ' expected to intersect ' + boxB + ' with padding ' +
    -        padding, goog.math.Box.intersectsWithPadding(box, boxB, padding));
    -  }
    -  function assertNotIntersects(boxB, padding) {
    -    assertFalse(box + ' expected to not intersect ' + boxB + ' with padding ' +
    -        padding, goog.math.Box.intersectsWithPadding(box, boxB, padding));
    -  }
    -
    -  assertIntersects(box, 10);
    -  assertIntersects(new goog.math.Box(20, 80, 80, 20), 10);
    -  assertIntersects(new goog.math.Box(50, 80, 100, 20), 10);
    -  assertIntersects(new goog.math.Box(80, 80, 120, 20), 10);
    -  assertIntersects(new goog.math.Box(20, 100, 80, 50), 10);
    -  assertIntersects(new goog.math.Box(80, 100, 120, 50), 10);
    -  assertIntersects(new goog.math.Box(20, 120, 80, 80), 10);
    -  assertIntersects(new goog.math.Box(50, 120, 100, 80), 10);
    -  assertIntersects(new goog.math.Box(80, 120, 120, 80), 10);
    -  assertIntersects(new goog.math.Box(20, 120, 120, 20), 10);
    -  assertIntersects(new goog.math.Box(70, 80, 80, 70), 10);
    -  assertIntersects(new goog.math.Box(10, 30, 30, 10), 20);
    -  assertIntersects(new goog.math.Box(10, 70, 30, 30), 20);
    -  assertIntersects(new goog.math.Box(10, 100, 30, 50), 20);
    -  assertIntersects(new goog.math.Box(10, 120, 30, 80), 20);
    -  assertIntersects(new goog.math.Box(10, 140, 30, 120), 20);
    -  assertIntersects(new goog.math.Box(30, 30, 70, 10), 20);
    -  assertIntersects(new goog.math.Box(30, 140, 70, 120), 20);
    -  assertIntersects(new goog.math.Box(50, 30, 100, 10), 20);
    -  assertIntersects(new goog.math.Box(50, 140, 100, 120), 20);
    -  assertIntersects(new goog.math.Box(80, 30, 120, 10), 20);
    -  assertIntersects(new goog.math.Box(80, 140, 120, 120), 20);
    -  assertIntersects(new goog.math.Box(120, 30, 140, 10), 20);
    -  assertIntersects(new goog.math.Box(120, 70, 140, 30), 20);
    -  assertIntersects(new goog.math.Box(120, 100, 140, 50), 20);
    -  assertIntersects(new goog.math.Box(120, 120, 140, 80), 20);
    -  assertIntersects(new goog.math.Box(120, 140, 140, 120), 20);
    -  assertNotIntersects(new goog.math.Box(10, 30, 30, 10), 10);
    -  assertNotIntersects(new goog.math.Box(10, 70, 30, 30), 10);
    -  assertNotIntersects(new goog.math.Box(10, 100, 30, 50), 10);
    -  assertNotIntersects(new goog.math.Box(10, 120, 30, 80), 10);
    -  assertNotIntersects(new goog.math.Box(10, 140, 30, 120), 10);
    -  assertNotIntersects(new goog.math.Box(30, 30, 70, 10), 10);
    -  assertNotIntersects(new goog.math.Box(30, 140, 70, 120), 10);
    -  assertNotIntersects(new goog.math.Box(50, 30, 100, 10), 10);
    -  assertNotIntersects(new goog.math.Box(50, 140, 100, 120), 10);
    -  assertNotIntersects(new goog.math.Box(80, 30, 120, 10), 10);
    -  assertNotIntersects(new goog.math.Box(80, 140, 120, 120), 10);
    -  assertNotIntersects(new goog.math.Box(120, 30, 140, 10), 10);
    -  assertNotIntersects(new goog.math.Box(120, 70, 140, 30), 10);
    -  assertNotIntersects(new goog.math.Box(120, 100, 140, 50), 10);
    -  assertNotIntersects(new goog.math.Box(120, 120, 140, 80), 10);
    -  assertNotIntersects(new goog.math.Box(120, 140, 140, 120), 10);
    -}
    -
    -function testExpandToInclude() {
    -  var box = new goog.math.Box(10, 50, 50, 10);
    -  box.expandToInclude(new goog.math.Box(60, 70, 70, 60));
    -  assertEquals(10, box.left);
    -  assertEquals(10, box.top);
    -  assertEquals(70, box.right);
    -  assertEquals(70, box.bottom);
    -  box.expandToInclude(new goog.math.Box(30, 40, 40, 30));
    -  assertEquals(10, box.left);
    -  assertEquals(10, box.top);
    -  assertEquals(70, box.right);
    -  assertEquals(70, box.bottom);
    -  box.expandToInclude(new goog.math.Box(0, 100, 100, 0));
    -  assertEquals(0, box.left);
    -  assertEquals(0, box.top);
    -  assertEquals(100, box.right);
    -  assertEquals(100, box.bottom);
    -}
    -
    -function testGetWidth() {
    -  var box = new goog.math.Box(10, 50, 30, 25);
    -  assertEquals(25, box.getWidth());
    -}
    -
    -function testGetHeight() {
    -  var box = new goog.math.Box(10, 50, 30, 25);
    -  assertEquals(20, box.getHeight());
    -}
    -
    -function testBoundingBox() {
    -  assertObjectEquals(
    -      new goog.math.Box(1, 10, 11, 0),
    -      goog.math.Box.boundingBox(
    -          new goog.math.Coordinate(5, 5),
    -          new goog.math.Coordinate(5, 11),
    -          new goog.math.Coordinate(0, 5),
    -          new goog.math.Coordinate(5, 1),
    -          new goog.math.Coordinate(10, 5)));
    -}
    -
    -function testBoxCeil() {
    -  var box = new goog.math.Box(11.4, 26.6, 17.8, 9.2);
    -  assertEquals('The function should return the target instance',
    -      box, box.ceil());
    -  assertObjectEquals(new goog.math.Box(12, 27, 18, 10), box);
    -}
    -
    -function testBoxFloor() {
    -  var box = new goog.math.Box(11.4, 26.6, 17.8, 9.2);
    -  assertEquals('The function should return the target instance',
    -      box, box.floor());
    -  assertObjectEquals(new goog.math.Box(11, 26, 17, 9), box);
    -}
    -
    -function testBoxRound() {
    -  var box = new goog.math.Box(11.4, 26.6, 17.8, 9.2);
    -  assertEquals('The function should return the target instance',
    -      box, box.round());
    -  assertObjectEquals(new goog.math.Box(11, 27, 18, 9), box);
    -}
    -
    -function testBoxTranslateCoordinate() {
    -  var box = new goog.math.Box(10, 30, 20, 5);
    -  var c = new goog.math.Coordinate(10, 5);
    -  assertEquals('The function should return the target instance',
    -      box, box.translate(c));
    -  assertObjectEquals(new goog.math.Box(15, 40, 25, 15), box);
    -}
    -
    -function testBoxTranslateXY() {
    -  var box = new goog.math.Box(10, 30, 20, 5);
    -  assertEquals('The function should return the target instance',
    -      box, box.translate(5, 2));
    -  assertObjectEquals(new goog.math.Box(12, 35, 22, 10), box);
    -}
    -
    -function testBoxTranslateX() {
    -  var box = new goog.math.Box(10, 30, 20, 5);
    -  assertEquals('The function should return the target instance',
    -      box, box.translate(3));
    -  assertObjectEquals(new goog.math.Box(10, 33, 20, 8), box);
    -}
    -
    -function testBoxScaleXY() {
    -  var box = new goog.math.Box(10, 20, 30, 5);
    -  assertEquals('The function should return the target instance',
    -      box, box.scale(2, 3));
    -  assertObjectEquals(new goog.math.Box(30, 40, 90, 10), box);
    -}
    -
    -function testBoxScaleFactor() {
    -  var box = new goog.math.Box(10, 20, 30, 5);
    -  assertEquals('The function should return the target instance',
    -      box, box.scale(2));
    -  assertObjectEquals(new goog.math.Box(20, 40, 60, 10), box);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/math/coordinate.js b/src/database/third_party/closure-library/closure/goog/math/coordinate.js
    deleted file mode 100644
    index 798d3851acd..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/coordinate.js
    +++ /dev/null
    @@ -1,268 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A utility class for representing two-dimensional positions.
    - */
    -
    -
    -goog.provide('goog.math.Coordinate');
    -
    -goog.require('goog.math');
    -
    -
    -
    -/**
    - * Class for representing coordinates and positions.
    - * @param {number=} opt_x Left, defaults to 0.
    - * @param {number=} opt_y Top, defaults to 0.
    - * @struct
    - * @constructor
    - */
    -goog.math.Coordinate = function(opt_x, opt_y) {
    -  /**
    -   * X-value
    -   * @type {number}
    -   */
    -  this.x = goog.isDef(opt_x) ? opt_x : 0;
    -
    -  /**
    -   * Y-value
    -   * @type {number}
    -   */
    -  this.y = goog.isDef(opt_y) ? opt_y : 0;
    -};
    -
    -
    -/**
    - * Returns a new copy of the coordinate.
    - * @return {!goog.math.Coordinate} A clone of this coordinate.
    - */
    -goog.math.Coordinate.prototype.clone = function() {
    -  return new goog.math.Coordinate(this.x, this.y);
    -};
    -
    -
    -if (goog.DEBUG) {
    -  /**
    -   * Returns a nice string representing the coordinate.
    -   * @return {string} In the form (50, 73).
    -   * @override
    -   */
    -  goog.math.Coordinate.prototype.toString = function() {
    -    return '(' + this.x + ', ' + this.y + ')';
    -  };
    -}
    -
    -
    -/**
    - * Compares coordinates for equality.
    - * @param {goog.math.Coordinate} a A Coordinate.
    - * @param {goog.math.Coordinate} b A Coordinate.
    - * @return {boolean} True iff the coordinates are equal, or if both are null.
    - */
    -goog.math.Coordinate.equals = function(a, b) {
    -  if (a == b) {
    -    return true;
    -  }
    -  if (!a || !b) {
    -    return false;
    -  }
    -  return a.x == b.x && a.y == b.y;
    -};
    -
    -
    -/**
    - * Returns the distance between two coordinates.
    - * @param {!goog.math.Coordinate} a A Coordinate.
    - * @param {!goog.math.Coordinate} b A Coordinate.
    - * @return {number} The distance between {@code a} and {@code b}.
    - */
    -goog.math.Coordinate.distance = function(a, b) {
    -  var dx = a.x - b.x;
    -  var dy = a.y - b.y;
    -  return Math.sqrt(dx * dx + dy * dy);
    -};
    -
    -
    -/**
    - * Returns the magnitude of a coordinate.
    - * @param {!goog.math.Coordinate} a A Coordinate.
    - * @return {number} The distance between the origin and {@code a}.
    - */
    -goog.math.Coordinate.magnitude = function(a) {
    -  return Math.sqrt(a.x * a.x + a.y * a.y);
    -};
    -
    -
    -/**
    - * Returns the angle from the origin to a coordinate.
    - * @param {!goog.math.Coordinate} a A Coordinate.
    - * @return {number} The angle, in degrees, clockwise from the positive X
    - *     axis to {@code a}.
    - */
    -goog.math.Coordinate.azimuth = function(a) {
    -  return goog.math.angle(0, 0, a.x, a.y);
    -};
    -
    -
    -/**
    - * Returns the squared distance between two coordinates. Squared distances can
    - * be used for comparisons when the actual value is not required.
    - *
    - * Performance note: eliminating the square root is an optimization often used
    - * in lower-level languages, but the speed difference is not nearly as
    - * pronounced in JavaScript (only a few percent.)
    - *
    - * @param {!goog.math.Coordinate} a A Coordinate.
    - * @param {!goog.math.Coordinate} b A Coordinate.
    - * @return {number} The squared distance between {@code a} and {@code b}.
    - */
    -goog.math.Coordinate.squaredDistance = function(a, b) {
    -  var dx = a.x - b.x;
    -  var dy = a.y - b.y;
    -  return dx * dx + dy * dy;
    -};
    -
    -
    -/**
    - * Returns the difference between two coordinates as a new
    - * goog.math.Coordinate.
    - * @param {!goog.math.Coordinate} a A Coordinate.
    - * @param {!goog.math.Coordinate} b A Coordinate.
    - * @return {!goog.math.Coordinate} A Coordinate representing the difference
    - *     between {@code a} and {@code b}.
    - */
    -goog.math.Coordinate.difference = function(a, b) {
    -  return new goog.math.Coordinate(a.x - b.x, a.y - b.y);
    -};
    -
    -
    -/**
    - * Returns the sum of two coordinates as a new goog.math.Coordinate.
    - * @param {!goog.math.Coordinate} a A Coordinate.
    - * @param {!goog.math.Coordinate} b A Coordinate.
    - * @return {!goog.math.Coordinate} A Coordinate representing the sum of the two
    - *     coordinates.
    - */
    -goog.math.Coordinate.sum = function(a, b) {
    -  return new goog.math.Coordinate(a.x + b.x, a.y + b.y);
    -};
    -
    -
    -/**
    - * Rounds the x and y fields to the next larger integer values.
    - * @return {!goog.math.Coordinate} This coordinate with ceil'd fields.
    - */
    -goog.math.Coordinate.prototype.ceil = function() {
    -  this.x = Math.ceil(this.x);
    -  this.y = Math.ceil(this.y);
    -  return this;
    -};
    -
    -
    -/**
    - * Rounds the x and y fields to the next smaller integer values.
    - * @return {!goog.math.Coordinate} This coordinate with floored fields.
    - */
    -goog.math.Coordinate.prototype.floor = function() {
    -  this.x = Math.floor(this.x);
    -  this.y = Math.floor(this.y);
    -  return this;
    -};
    -
    -
    -/**
    - * Rounds the x and y fields to the nearest integer values.
    - * @return {!goog.math.Coordinate} This coordinate with rounded fields.
    - */
    -goog.math.Coordinate.prototype.round = function() {
    -  this.x = Math.round(this.x);
    -  this.y = Math.round(this.y);
    -  return this;
    -};
    -
    -
    -/**
    - * Translates this box by the given offsets. If a {@code goog.math.Coordinate}
    - * is given, then the x and y values are translated by the coordinate's x and y.
    - * Otherwise, x and y are translated by {@code tx} and {@code opt_ty}
    - * respectively.
    - * @param {number|goog.math.Coordinate} tx The value to translate x by or the
    - *     the coordinate to translate this coordinate by.
    - * @param {number=} opt_ty The value to translate y by.
    - * @return {!goog.math.Coordinate} This coordinate after translating.
    - */
    -goog.math.Coordinate.prototype.translate = function(tx, opt_ty) {
    -  if (tx instanceof goog.math.Coordinate) {
    -    this.x += tx.x;
    -    this.y += tx.y;
    -  } else {
    -    this.x += tx;
    -    if (goog.isNumber(opt_ty)) {
    -      this.y += opt_ty;
    -    }
    -  }
    -  return this;
    -};
    -
    -
    -/**
    - * Scales this coordinate by the given scale factors. The x and y values are
    - * scaled by {@code sx} and {@code opt_sy} respectively.  If {@code opt_sy}
    - * is not given, then {@code sx} is used for both x and y.
    - * @param {number} sx The scale factor to use for the x dimension.
    - * @param {number=} opt_sy The scale factor to use for the y dimension.
    - * @return {!goog.math.Coordinate} This coordinate after scaling.
    - */
    -goog.math.Coordinate.prototype.scale = function(sx, opt_sy) {
    -  var sy = goog.isNumber(opt_sy) ? opt_sy : sx;
    -  this.x *= sx;
    -  this.y *= sy;
    -  return this;
    -};
    -
    -
    -/**
    - * Rotates this coordinate clockwise about the origin (or, optionally, the given
    - * center) by the given angle, in radians.
    - * @param {number} radians The angle by which to rotate this coordinate
    - *     clockwise about the given center, in radians.
    - * @param {!goog.math.Coordinate=} opt_center The center of rotation. Defaults
    - *     to (0, 0) if not given.
    - */
    -goog.math.Coordinate.prototype.rotateRadians = function(radians, opt_center) {
    -  var center = opt_center || new goog.math.Coordinate(0, 0);
    -
    -  var x = this.x;
    -  var y = this.y;
    -  var cos = Math.cos(radians);
    -  var sin = Math.sin(radians);
    -
    -  this.x = (x - center.x) * cos - (y - center.y) * sin + center.x;
    -  this.y = (x - center.x) * sin + (y - center.y) * cos + center.y;
    -};
    -
    -
    -/**
    - * Rotates this coordinate clockwise about the origin (or, optionally, the given
    - * center) by the given angle, in degrees.
    - * @param {number} degrees The angle by which to rotate this coordinate
    - *     clockwise about the given center, in degrees.
    - * @param {!goog.math.Coordinate=} opt_center The center of rotation. Defaults
    - *     to (0, 0) if not given.
    - */
    -goog.math.Coordinate.prototype.rotateDegrees = function(degrees, opt_center) {
    -  this.rotateRadians(goog.math.toRadians(degrees), opt_center);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/math/coordinate3.js b/src/database/third_party/closure-library/closure/goog/math/coordinate3.js
    deleted file mode 100644
    index 04a5a69af29..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/coordinate3.js
    +++ /dev/null
    @@ -1,170 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A utility class for representing three-dimensional points.
    - *
    - * Based heavily on coordinate.js by:
    - */
    -
    -goog.provide('goog.math.Coordinate3');
    -
    -
    -
    -/**
    - * Class for representing coordinates and positions in 3 dimensions.
    - *
    - * @param {number=} opt_x X coordinate, defaults to 0.
    - * @param {number=} opt_y Y coordinate, defaults to 0.
    - * @param {number=} opt_z Z coordinate, defaults to 0.
    - * @struct
    - * @constructor
    - */
    -goog.math.Coordinate3 = function(opt_x, opt_y, opt_z) {
    -  /**
    -   * X-value
    -   * @type {number}
    -   */
    -  this.x = goog.isDef(opt_x) ? opt_x : 0;
    -
    -  /**
    -   * Y-value
    -   * @type {number}
    -   */
    -  this.y = goog.isDef(opt_y) ? opt_y : 0;
    -
    -  /**
    -   * Z-value
    -   * @type {number}
    -   */
    -  this.z = goog.isDef(opt_z) ? opt_z : 0;
    -};
    -
    -
    -/**
    - * Returns a new copy of the coordinate.
    - *
    - * @return {!goog.math.Coordinate3} A clone of this coordinate.
    - */
    -goog.math.Coordinate3.prototype.clone = function() {
    -  return new goog.math.Coordinate3(this.x, this.y, this.z);
    -};
    -
    -
    -if (goog.DEBUG) {
    -  /**
    -   * Returns a nice string representing the coordinate.
    -   *
    -   * @return {string} In the form (50, 73, 31).
    -   * @override
    -   */
    -  goog.math.Coordinate3.prototype.toString = function() {
    -    return '(' + this.x + ', ' + this.y + ', ' + this.z + ')';
    -  };
    -}
    -
    -
    -/**
    - * Compares coordinates for equality.
    - *
    - * @param {goog.math.Coordinate3} a A Coordinate3.
    - * @param {goog.math.Coordinate3} b A Coordinate3.
    - * @return {boolean} True iff the coordinates are equal, or if both are null.
    - */
    -goog.math.Coordinate3.equals = function(a, b) {
    -  if (a == b) {
    -    return true;
    -  }
    -  if (!a || !b) {
    -    return false;
    -  }
    -  return a.x == b.x && a.y == b.y && a.z == b.z;
    -};
    -
    -
    -/**
    - * Returns the distance between two coordinates.
    - *
    - * @param {goog.math.Coordinate3} a A Coordinate3.
    - * @param {goog.math.Coordinate3} b A Coordinate3.
    - * @return {number} The distance between {@code a} and {@code b}.
    - */
    -goog.math.Coordinate3.distance = function(a, b) {
    -  var dx = a.x - b.x;
    -  var dy = a.y - b.y;
    -  var dz = a.z - b.z;
    -  return Math.sqrt(dx * dx + dy * dy + dz * dz);
    -};
    -
    -
    -/**
    - * Returns the squared distance between two coordinates. Squared distances can
    - * be used for comparisons when the actual value is not required.
    - *
    - * Performance note: eliminating the square root is an optimization often used
    - * in lower-level languages, but the speed difference is not nearly as
    - * pronounced in JavaScript (only a few percent.)
    - *
    - * @param {goog.math.Coordinate3} a A Coordinate3.
    - * @param {goog.math.Coordinate3} b A Coordinate3.
    - * @return {number} The squared distance between {@code a} and {@code b}.
    - */
    -goog.math.Coordinate3.squaredDistance = function(a, b) {
    -  var dx = a.x - b.x;
    -  var dy = a.y - b.y;
    -  var dz = a.z - b.z;
    -  return dx * dx + dy * dy + dz * dz;
    -};
    -
    -
    -/**
    - * Returns the difference between two coordinates as a new
    - * goog.math.Coordinate3.
    - *
    - * @param {goog.math.Coordinate3} a A Coordinate3.
    - * @param {goog.math.Coordinate3} b A Coordinate3.
    - * @return {!goog.math.Coordinate3} A Coordinate3 representing the difference
    - *     between {@code a} and {@code b}.
    - */
    -goog.math.Coordinate3.difference = function(a, b) {
    -  return new goog.math.Coordinate3(a.x - b.x, a.y - b.y, a.z - b.z);
    -};
    -
    -
    -/**
    - * Returns the contents of this coordinate as a 3 value Array.
    - *
    - * @return {!Array<number>} A new array.
    - */
    -goog.math.Coordinate3.prototype.toArray = function() {
    -  return [this.x, this.y, this.z];
    -};
    -
    -
    -/**
    - * Converts a three element array into a Coordinate3 object.  If the value
    - * passed in is not an array, not array-like, or not of the right length, an
    - * error is thrown.
    - *
    - * @param {Array<number>} a Array of numbers to become a coordinate.
    - * @return {!goog.math.Coordinate3} A new coordinate from the array values.
    - * @throws {Error} When the oject passed in is not valid.
    - */
    -goog.math.Coordinate3.fromArray = function(a) {
    -  if (a.length <= 3) {
    -    return new goog.math.Coordinate3(a[0], a[1], a[2]);
    -  }
    -
    -  throw Error('Conversion from an array requires an array of length 3');
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/math/coordinate3_test.html b/src/database/third_party/closure-library/closure/goog/math/coordinate3_test.html
    deleted file mode 100644
    index 5e37a62c0c5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/coordinate3_test.html
    +++ /dev/null
    @@ -1,26 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -
    -  Coordinate3 Unit Tests
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.math.Coordinate3
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.math.Coordinate3Test');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/math/coordinate3_test.js b/src/database/third_party/closure-library/closure/goog/math/coordinate3_test.js
    deleted file mode 100644
    index 27d5a2a9b29..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/coordinate3_test.js
    +++ /dev/null
    @@ -1,196 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.math.Coordinate3Test');
    -goog.setTestOnly('goog.math.Coordinate3Test');
    -
    -goog.require('goog.math.Coordinate3');
    -goog.require('goog.testing.jsunit');
    -
    -function assertCoordinate3Equals(a, b) {
    -  assertTrue(b + ' should be equal to ' + a,
    -             goog.math.Coordinate3.equals(a, b));
    -}
    -
    -
    -function testCoordinate3MissingXYZ() {
    -  var noXYZ = new goog.math.Coordinate3();
    -  assertEquals(0, noXYZ.x);
    -  assertEquals(0, noXYZ.y);
    -  assertEquals(0, noXYZ.z);
    -  assertCoordinate3Equals(noXYZ, new goog.math.Coordinate3());
    -}
    -
    -
    -function testCoordinate3MissingYZ() {
    -  var noYZ = new goog.math.Coordinate3(10);
    -  assertEquals(10, noYZ.x);
    -  assertEquals(0, noYZ.y);
    -  assertEquals(0, noYZ.z);
    -  assertCoordinate3Equals(noYZ, new goog.math.Coordinate3(10));
    -}
    -
    -
    -function testCoordinate3MissingZ() {
    -  var noZ = new goog.math.Coordinate3(10, 20);
    -  assertEquals(10, noZ.x);
    -  assertEquals(20, noZ.y);
    -  assertEquals(0, noZ.z);
    -  assertCoordinate3Equals(noZ, new goog.math.Coordinate3(10, 20));
    -}
    -
    -
    -function testCoordinate3IntegerValues() {
    -  var intCoord = new goog.math.Coordinate3(10, 20, -19);
    -  assertEquals(10, intCoord.x);
    -  assertEquals(20, intCoord.y);
    -  assertEquals(-19, intCoord.z);
    -  assertCoordinate3Equals(intCoord, new goog.math.Coordinate3(10, 20, -19));
    -}
    -
    -
    -function testCoordinate3FloatValues() {
    -  var floatCoord = new goog.math.Coordinate3(10.5, 20.897, -71.385);
    -  assertEquals(10.5, floatCoord.x);
    -  assertEquals(20.897, floatCoord.y);
    -  assertEquals(-71.385, floatCoord.z);
    -  assertCoordinate3Equals(floatCoord,
    -      new goog.math.Coordinate3(10.5, 20.897, -71.385));
    -}
    -
    -
    -function testCoordinate3OneNonNumericValue() {
    -  var dim5 = new goog.math.Coordinate3('ten', 1000, 85);
    -  assertTrue(isNaN(dim5.x));
    -  assertEquals(1000, dim5.y);
    -  assertEquals(85, dim5.z);
    -}
    -
    -
    -function testCoordinate3AllNonNumericValues() {
    -  var nonNumeric = new goog.math.Coordinate3('ten',
    -                                             {woop: 'test'},
    -                                             Math.sqrt(-1));
    -  assertTrue(isNaN(nonNumeric.x));
    -  assertTrue(isNaN(nonNumeric.y));
    -  assertTrue(isNaN(nonNumeric.z));
    -}
    -
    -
    -function testCoordinate3Origin() {
    -  var origin = new goog.math.Coordinate3(0, 0, 0);
    -  assertEquals(0, origin.x);
    -  assertEquals(0, origin.y);
    -  assertEquals(0, origin.z);
    -  assertCoordinate3Equals(origin, new goog.math.Coordinate3(0, 0, 0));
    -}
    -
    -
    -function testCoordinate3Clone() {
    -  var c = new goog.math.Coordinate3();
    -  assertCoordinate3Equals(c, c.clone());
    -  c.x = -12;
    -  c.y = 13;
    -  c.z = 5;
    -  assertCoordinate3Equals(c, c.clone());
    -}
    -
    -
    -function testToString() {
    -  assertEquals('(0, 0, 0)', new
    -               goog.math.Coordinate3().toString());
    -  assertEquals('(1, 0, 0)', new
    -               goog.math.Coordinate3(1).toString());
    -  assertEquals('(1, 2, 0)', new
    -               goog.math.Coordinate3(1, 2).toString());
    -  assertEquals('(0, 0, 0)', new goog.math.Coordinate3(0, 0, 0).toString());
    -  assertEquals('(1, 2, 3)', new goog.math.Coordinate3(1, 2, 3).toString());
    -  assertEquals('(-4, 5, -3)', new goog.math.Coordinate3(-4, 5, -3).toString());
    -  assertEquals('(11.25, -71.935, 2.8)',
    -               new goog.math.Coordinate3(11.25, -71.935, 2.8).toString());
    -}
    -
    -
    -function testEquals() {
    -  var a = new goog.math.Coordinate3(3, 4, 5);
    -  var b = new goog.math.Coordinate3(3, 4, 5);
    -  var c = new goog.math.Coordinate3(-3, 4, -5);
    -
    -  assertTrue(goog.math.Coordinate3.equals(null, null));
    -  assertFalse(goog.math.Coordinate3.equals(a, null));
    -  assertTrue(goog.math.Coordinate3.equals(a, a));
    -  assertTrue(goog.math.Coordinate3.equals(a, b));
    -  assertFalse(goog.math.Coordinate3.equals(a, c));
    -}
    -
    -
    -function testCoordinate3Distance() {
    -  var a = new goog.math.Coordinate3(-2, -3, 1);
    -  var b = new goog.math.Coordinate3(2, 0, 1);
    -  assertEquals(5, goog.math.Coordinate3.distance(a, b));
    -}
    -
    -
    -function testCoordinate3SquaredDistance() {
    -  var a = new goog.math.Coordinate3(7, 11, 1);
    -  var b = new goog.math.Coordinate3(3, -1, 1);
    -  assertEquals(160, goog.math.Coordinate3.squaredDistance(a, b));
    -}
    -
    -
    -function testCoordinate3Difference() {
    -  var a = new goog.math.Coordinate3(7, 11, 1);
    -  var b = new goog.math.Coordinate3(3, -1, 1);
    -  assertCoordinate3Equals(goog.math.Coordinate3.difference(a, b),
    -                          new goog.math.Coordinate3(4, 12, 0));
    -}
    -
    -
    -function testToArray() {
    -  var a = new goog.math.Coordinate3(7, 11, 1);
    -  var b = a.toArray();
    -  assertEquals(b.length, 3);
    -  assertEquals(b[0], 7);
    -  assertEquals(b[1], 11);
    -  assertEquals(b[2], 1);
    -
    -  var c = new goog.math.Coordinate3('abc', 'def', 'xyz');
    -  var result = c.toArray();
    -  assertTrue(isNaN(result[0]));
    -  assertTrue(isNaN(result[1]));
    -  assertTrue(isNaN(result[2]));
    -}
    -
    -
    -function testFromArray() {
    -  var a = [1, 2, 3];
    -  var b = goog.math.Coordinate3.fromArray(a);
    -  assertEquals('(1, 2, 3)', b.toString());
    -
    -  var c = [1, 2];
    -  var d = goog.math.Coordinate3.fromArray(c);
    -  assertEquals('(1, 2, 0)', d.toString());
    -
    -  var e = [1];
    -  var f = goog.math.Coordinate3.fromArray(e);
    -  assertEquals('(1, 0, 0)', f.toString());
    -
    -  var g = [];
    -  var h = goog.math.Coordinate3.fromArray(g);
    -  assertEquals('(0, 0, 0)', h.toString());
    -
    -  var tooLong = [1, 2, 3, 4, 5, 6];
    -  assertThrows('Error should be thrown attempting to convert an invalid type.',
    -      goog.partial(goog.math.Coordinate3.fromArray, tooLong));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/math/coordinate_test.html b/src/database/third_party/closure-library/closure/goog/math/coordinate_test.html
    deleted file mode 100644
    index 2c9598d6451..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/coordinate_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.math.Coordinate
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.math.CoordinateTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/math/coordinate_test.js b/src/database/third_party/closure-library/closure/goog/math/coordinate_test.js
    deleted file mode 100644
    index e802bdc8db2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/coordinate_test.js
    +++ /dev/null
    @@ -1,170 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.math.CoordinateTest');
    -goog.setTestOnly('goog.math.CoordinateTest');
    -
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.testing.jsunit');
    -
    -function testCoordinate1() {
    -  var dim1 = new goog.math.Coordinate();
    -  assertEquals(0, dim1.x);
    -  assertEquals(0, dim1.y);
    -  assertEquals('(0, 0)', dim1.toString());
    -}
    -
    -function testCoordinate2() {
    -  var dim2 = new goog.math.Coordinate(10);
    -  assertEquals(10, dim2.x);
    -  assertEquals(0, dim2.y);
    -  assertEquals('(10, 0)', dim2.toString());
    -}
    -
    -function testCoordinate3() {
    -  var dim3 = new goog.math.Coordinate(10, 20);
    -  assertEquals(10, dim3.x);
    -  assertEquals(20, dim3.y);
    -  assertEquals('(10, 20)', dim3.toString());
    -}
    -
    -function testCoordinate4() {
    -  var dim4 = new goog.math.Coordinate(10.5, 20.897);
    -  assertEquals(10.5, dim4.x);
    -  assertEquals(20.897, dim4.y);
    -  assertEquals('(10.5, 20.897)', dim4.toString());
    -}
    -
    -function testCoordinate5() {
    -  var dim5 = new goog.math.Coordinate(NaN, 1000);
    -  assertTrue(isNaN(dim5.x));
    -  assertEquals(1000, dim5.y);
    -  assertEquals('(NaN, 1000)', dim5.toString());
    -}
    -
    -function testCoordinateSquaredDistance() {
    -  var a = new goog.math.Coordinate(7, 11);
    -  var b = new goog.math.Coordinate(3, -1);
    -  assertEquals(160, goog.math.Coordinate.squaredDistance(a, b));
    -}
    -
    -function testCoordinateDistance() {
    -  var a = new goog.math.Coordinate(-2, -3);
    -  var b = new goog.math.Coordinate(2, 0);
    -  assertEquals(5, goog.math.Coordinate.distance(a, b));
    -}
    -
    -function testCoordinateMagnitude() {
    -  var a = new goog.math.Coordinate(5, 5);
    -  assertEquals(Math.sqrt(50), goog.math.Coordinate.magnitude(a));
    -}
    -
    -function testCoordinateAzimuth() {
    -  var a = new goog.math.Coordinate(5, 5);
    -  assertEquals(45, goog.math.Coordinate.azimuth(a));
    -}
    -
    -function testCoordinateClone() {
    -  var c = new goog.math.Coordinate();
    -  assertEquals(c.toString(), c.clone().toString());
    -  c.x = -12;
    -  c.y = 13;
    -  assertEquals(c.toString(), c.clone().toString());
    -}
    -
    -function testCoordinateDifference() {
    -  assertObjectEquals(new goog.math.Coordinate(3, -40),
    -      goog.math.Coordinate.difference(
    -          new goog.math.Coordinate(5, 10),
    -          new goog.math.Coordinate(2, 50)));
    -}
    -
    -function testCoordinateSum() {
    -  assertObjectEquals(new goog.math.Coordinate(7, 60),
    -      goog.math.Coordinate.sum(
    -          new goog.math.Coordinate(5, 10),
    -          new goog.math.Coordinate(2, 50)));
    -}
    -
    -function testCoordinateCeil() {
    -  var c = new goog.math.Coordinate(5.2, 7.6);
    -  assertObjectEquals(new goog.math.Coordinate(6, 8), c.ceil());
    -  c = new goog.math.Coordinate(-1.2, -3.9);
    -  assertObjectEquals(new goog.math.Coordinate(-1, -3), c.ceil());
    -}
    -
    -function testCoordinateFloor() {
    -  var c = new goog.math.Coordinate(5.2, 7.6);
    -  assertObjectEquals(new goog.math.Coordinate(5, 7), c.floor());
    -  c = new goog.math.Coordinate(-1.2, -3.9);
    -  assertObjectEquals(new goog.math.Coordinate(-2, -4), c.floor());
    -}
    -
    -function testCoordinateRound() {
    -  var c = new goog.math.Coordinate(5.2, 7.6);
    -  assertObjectEquals(new goog.math.Coordinate(5, 8), c.round());
    -  c = new goog.math.Coordinate(-1.2, -3.9);
    -  assertObjectEquals(new goog.math.Coordinate(-1, -4), c.round());
    -}
    -
    -function testCoordinateTranslateCoordinate() {
    -  var c = new goog.math.Coordinate(10, 20);
    -  var t = new goog.math.Coordinate(5, 10);
    -  // The translate function modifies the coordinate instead of
    -  // returning a new one.
    -  assertEquals(c, c.translate(t));
    -  assertObjectEquals(new goog.math.Coordinate(15, 30), c);
    -}
    -
    -function testCoordinateTranslateXY() {
    -  var c = new goog.math.Coordinate(10, 20);
    -  // The translate function modifies the coordinate instead of
    -  // returning a new one.
    -  assertEquals(c, c.translate(25, 5));
    -  assertObjectEquals(new goog.math.Coordinate(35, 25), c);
    -}
    -
    -function testCoordinateTranslateX() {
    -  var c = new goog.math.Coordinate(10, 20);
    -  // The translate function modifies the coordinate instead of
    -  // returning a new one.
    -  assertEquals(c, c.translate(5));
    -  assertObjectEquals(new goog.math.Coordinate(15, 20), c);
    -}
    -
    -function testCoordinateScaleXY() {
    -  var c = new goog.math.Coordinate(10, 15);
    -  // The scale function modifies the coordinate instead of returning a new one.
    -  assertEquals(c, c.scale(2, 3));
    -  assertObjectEquals(new goog.math.Coordinate(20, 45), c);
    -}
    -
    -function testCoordinateScaleFactor() {
    -  var c = new goog.math.Coordinate(10, 15);
    -  // The scale function modifies the coordinate instead of returning a new one.
    -  assertEquals(c, c.scale(2));
    -  assertObjectEquals(new goog.math.Coordinate(20, 30), c);
    -}
    -
    -function testCoordinateRotateRadians() {
    -  var c = new goog.math.Coordinate(15, 75);
    -  c.rotateRadians(Math.PI / 2, new goog.math.Coordinate(10, 70));
    -  assertObjectEquals(new goog.math.Coordinate(5, 75), c);
    -}
    -
    -function testCoordinateRotateDegrees() {
    -  var c = new goog.math.Coordinate(15, 75);
    -  c.rotateDegrees(90, new goog.math.Coordinate(10, 70));
    -  assertObjectEquals(new goog.math.Coordinate(5, 75), c);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/math/exponentialbackoff.js b/src/database/third_party/closure-library/closure/goog/math/exponentialbackoff.js
    deleted file mode 100644
    index 952f4746b35..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/exponentialbackoff.js
    +++ /dev/null
    @@ -1,104 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Utility class to manage the mathematics behind computing an
    - * exponential backoff model.  Given an initial backoff value and a maximum
    - * backoff value, every call to backoff() will double the value until maximum
    - * backoff value is reached.
    - *
    - */
    -
    -
    -goog.provide('goog.math.ExponentialBackoff');
    -
    -goog.require('goog.asserts');
    -
    -
    -
    -/**
    - * @struct
    - * @constructor
    - *
    - * @param {number} initialValue The initial backoff value.
    - * @param {number} maxValue The maximum backoff value.
    - */
    -goog.math.ExponentialBackoff = function(initialValue, maxValue) {
    -  goog.asserts.assert(initialValue > 0,
    -      'Initial value must be greater than zero.');
    -  goog.asserts.assert(maxValue >= initialValue,
    -      'Max value should be at least as large as initial value.');
    -
    -  /**
    -   * @type {number}
    -   * @private
    -   */
    -  this.initialValue_ = initialValue;
    -
    -  /**
    -   * @type {number}
    -   * @private
    -   */
    -  this.maxValue_ = maxValue;
    -
    -  /**
    -   * The current backoff value.
    -   * @type {number}
    -   * @private
    -   */
    -  this.currValue_ = initialValue;
    -};
    -
    -
    -/**
    - * The number of backoffs that have happened.
    - * @type {number}
    - * @private
    - */
    -goog.math.ExponentialBackoff.prototype.currCount_ = 0;
    -
    -
    -/**
    - * Resets the backoff value to its initial value.
    - */
    -goog.math.ExponentialBackoff.prototype.reset = function() {
    -  this.currValue_ = this.initialValue_;
    -  this.currCount_ = 0;
    -};
    -
    -
    -/**
    - * @return {number} The current backoff value.
    - */
    -goog.math.ExponentialBackoff.prototype.getValue = function() {
    -  return this.currValue_;
    -};
    -
    -
    -/**
    - * @return {number} The number of times this class has backed off.
    - */
    -goog.math.ExponentialBackoff.prototype.getBackoffCount = function() {
    -  return this.currCount_;
    -};
    -
    -
    -/**
    - * Initiates a backoff.
    - */
    -goog.math.ExponentialBackoff.prototype.backoff = function() {
    -  this.currValue_ = Math.min(this.maxValue_, this.currValue_ * 2);
    -  this.currCount_++;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/math/exponentialbackoff_test.html b/src/database/third_party/closure-library/closure/goog/math/exponentialbackoff_test.html
    deleted file mode 100644
    index 3edcf3c0b37..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/exponentialbackoff_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.math.ExponentialBackoff
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.math.ExponentialBackoffTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/math/exponentialbackoff_test.js b/src/database/third_party/closure-library/closure/goog/math/exponentialbackoff_test.js
    deleted file mode 100644
    index 33a84aa02b8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/exponentialbackoff_test.js
    +++ /dev/null
    @@ -1,63 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.math.ExponentialBackoffTest');
    -goog.setTestOnly('goog.math.ExponentialBackoffTest');
    -
    -goog.require('goog.math.ExponentialBackoff');
    -goog.require('goog.testing.jsunit');
    -
    -var INITIAL_VALUE = 1;
    -
    -var MAX_VALUE = 10;
    -
    -function assertValueAndCount(value, count, backoff) {
    -  assertEquals('Wrong value', value, backoff.getValue());
    -  assertEquals('Wrong backoff count', count, backoff.getBackoffCount());
    -}
    -
    -
    -function createBackoff() {
    -  return new goog.math.ExponentialBackoff(INITIAL_VALUE, MAX_VALUE);
    -}
    -
    -
    -function testInitialState() {
    -  var backoff = createBackoff();
    -  assertValueAndCount(INITIAL_VALUE, 0, backoff);
    -}
    -
    -
    -function testBackoff() {
    -  var backoff = createBackoff();
    -  backoff.backoff();
    -  assertValueAndCount(2 /* value */, 1 /* count */, backoff);
    -  backoff.backoff();
    -  assertValueAndCount(4 /* value */, 2 /* count */, backoff);
    -  backoff.backoff();
    -  assertValueAndCount(8 /* value */, 3 /* count */, backoff);
    -  backoff.backoff();
    -  assertValueAndCount(MAX_VALUE, 4 /* count */, backoff);
    -  backoff.backoff();
    -  assertValueAndCount(MAX_VALUE, 5 /* count */, backoff);
    -}
    -
    -
    -function testReset() {
    -  var backoff = createBackoff();
    -  backoff.backoff();
    -  backoff.reset();
    -  assertValueAndCount(INITIAL_VALUE, 0 /* count */, backoff);
    -
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/math/integer.js b/src/database/third_party/closure-library/closure/goog/math/integer.js
    deleted file mode 100644
    index 92f047e6567..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/integer.js
    +++ /dev/null
    @@ -1,739 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Defines an Integer class for representing (potentially)
    - * infinite length two's-complement integer values.
    - *
    - * For the specific case of 64-bit integers, use goog.math.Long, which is more
    - * efficient.
    - *
    - */
    -
    -goog.provide('goog.math.Integer');
    -
    -
    -
    -/**
    - * Constructs a two's-complement integer an array containing bits of the
    - * integer in 32-bit (signed) pieces, given in little-endian order (i.e.,
    - * lowest-order bits in the first piece), and the sign of -1 or 0.
    - *
    - * See the from* functions below for other convenient ways of constructing
    - * Integers.
    - *
    - * The internal representation of an integer is an array of 32-bit signed
    - * pieces, along with a sign (0 or -1) that indicates the contents of all the
    - * other 32-bit pieces out to infinity.  We use 32-bit pieces because these are
    - * the size of integers on which Javascript performs bit-operations.  For
    - * operations like addition and multiplication, we split each number into 16-bit
    - * pieces, which can easily be multiplied within Javascript's floating-point
    - * representation without overflow or change in sign.
    - *
    - * @struct
    - * @constructor
    - * @param {Array<number>} bits Array containing the bits of the number.
    - * @param {number} sign The sign of the number: -1 for negative and 0 positive.
    - * @final
    - */
    -goog.math.Integer = function(bits, sign) {
    -  /**
    -   * @type {!Array<number>}
    -   * @private
    -   */
    -  this.bits_ = [];
    -
    -  /**
    -   * @type {number}
    -   * @private
    -   */
    -  this.sign_ = sign;
    -
    -  // Copy the 32-bit signed integer values passed in.  We prune out those at the
    -  // top that equal the sign since they are redundant.
    -  var top = true;
    -  for (var i = bits.length - 1; i >= 0; i--) {
    -    var val = bits[i] | 0;
    -    if (!top || val != sign) {
    -      this.bits_[i] = val;
    -      top = false;
    -    }
    -  }
    -};
    -
    -
    -// NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the
    -// from* methods on which they depend.
    -
    -
    -/**
    - * A cache of the Integer representations of small integer values.
    - * @type {!Object}
    - * @private
    - */
    -goog.math.Integer.IntCache_ = {};
    -
    -
    -/**
    - * Returns an Integer representing the given (32-bit) integer value.
    - * @param {number} value A 32-bit integer value.
    - * @return {!goog.math.Integer} The corresponding Integer value.
    - */
    -goog.math.Integer.fromInt = function(value) {
    -  if (-128 <= value && value < 128) {
    -    var cachedObj = goog.math.Integer.IntCache_[value];
    -    if (cachedObj) {
    -      return cachedObj;
    -    }
    -  }
    -
    -  var obj = new goog.math.Integer([value | 0], value < 0 ? -1 : 0);
    -  if (-128 <= value && value < 128) {
    -    goog.math.Integer.IntCache_[value] = obj;
    -  }
    -  return obj;
    -};
    -
    -
    -/**
    - * Returns an Integer representing the given value, provided that it is a finite
    - * number.  Otherwise, zero is returned.
    - * @param {number} value The value in question.
    - * @return {!goog.math.Integer} The corresponding Integer value.
    - */
    -goog.math.Integer.fromNumber = function(value) {
    -  if (isNaN(value) || !isFinite(value)) {
    -    return goog.math.Integer.ZERO;
    -  } else if (value < 0) {
    -    return goog.math.Integer.fromNumber(-value).negate();
    -  } else {
    -    var bits = [];
    -    var pow = 1;
    -    for (var i = 0; value >= pow; i++) {
    -      bits[i] = (value / pow) | 0;
    -      pow *= goog.math.Integer.TWO_PWR_32_DBL_;
    -    }
    -    return new goog.math.Integer(bits, 0);
    -  }
    -};
    -
    -
    -/**
    - * Returns a Integer representing the value that comes by concatenating the
    - * given entries, each is assumed to be 32 signed bits, given in little-endian
    - * order (lowest order bits in the lowest index), and sign-extending the highest
    - * order 32-bit value.
    - * @param {Array<number>} bits The bits of the number, in 32-bit signed pieces,
    - *     in little-endian order.
    - * @return {!goog.math.Integer} The corresponding Integer value.
    - */
    -goog.math.Integer.fromBits = function(bits) {
    -  var high = bits[bits.length - 1];
    -  return new goog.math.Integer(bits, high & (1 << 31) ? -1 : 0);
    -};
    -
    -
    -/**
    - * Returns an Integer representation of the given string, written using the
    - * given radix.
    - * @param {string} str The textual representation of the Integer.
    - * @param {number=} opt_radix The radix in which the text is written.
    - * @return {!goog.math.Integer} The corresponding Integer value.
    - */
    -goog.math.Integer.fromString = function(str, opt_radix) {
    -  if (str.length == 0) {
    -    throw Error('number format error: empty string');
    -  }
    -
    -  var radix = opt_radix || 10;
    -  if (radix < 2 || 36 < radix) {
    -    throw Error('radix out of range: ' + radix);
    -  }
    -
    -  if (str.charAt(0) == '-') {
    -    return goog.math.Integer.fromString(str.substring(1), radix).negate();
    -  } else if (str.indexOf('-') >= 0) {
    -    throw Error('number format error: interior "-" character');
    -  }
    -
    -  // Do several (8) digits each time through the loop, so as to
    -  // minimize the calls to the very expensive emulated div.
    -  var radixToPower = goog.math.Integer.fromNumber(Math.pow(radix, 8));
    -
    -  var result = goog.math.Integer.ZERO;
    -  for (var i = 0; i < str.length; i += 8) {
    -    var size = Math.min(8, str.length - i);
    -    var value = parseInt(str.substring(i, i + size), radix);
    -    if (size < 8) {
    -      var power = goog.math.Integer.fromNumber(Math.pow(radix, size));
    -      result = result.multiply(power).add(goog.math.Integer.fromNumber(value));
    -    } else {
    -      result = result.multiply(radixToPower);
    -      result = result.add(goog.math.Integer.fromNumber(value));
    -    }
    -  }
    -  return result;
    -};
    -
    -
    -/**
    - * A number used repeatedly in calculations.  This must appear before the first
    - * call to the from* functions below.
    - * @type {number}
    - * @private
    - */
    -goog.math.Integer.TWO_PWR_32_DBL_ = (1 << 16) * (1 << 16);
    -
    -
    -/** @type {!goog.math.Integer} */
    -goog.math.Integer.ZERO = goog.math.Integer.fromInt(0);
    -
    -
    -/** @type {!goog.math.Integer} */
    -goog.math.Integer.ONE = goog.math.Integer.fromInt(1);
    -
    -
    -/**
    - * @type {!goog.math.Integer}
    - * @private
    - */
    -goog.math.Integer.TWO_PWR_24_ = goog.math.Integer.fromInt(1 << 24);
    -
    -
    -/**
    - * Returns the value, assuming it is a 32-bit integer.
    - * @return {number} The corresponding int value.
    - */
    -goog.math.Integer.prototype.toInt = function() {
    -  return this.bits_.length > 0 ? this.bits_[0] : this.sign_;
    -};
    -
    -
    -/** @return {number} The closest floating-point representation to this value. */
    -goog.math.Integer.prototype.toNumber = function() {
    -  if (this.isNegative()) {
    -    return -this.negate().toNumber();
    -  } else {
    -    var val = 0;
    -    var pow = 1;
    -    for (var i = 0; i < this.bits_.length; i++) {
    -      val += this.getBitsUnsigned(i) * pow;
    -      pow *= goog.math.Integer.TWO_PWR_32_DBL_;
    -    }
    -    return val;
    -  }
    -};
    -
    -
    -/**
    - * @param {number=} opt_radix The radix in which the text should be written.
    - * @return {string} The textual representation of this value.
    - * @override
    - */
    -goog.math.Integer.prototype.toString = function(opt_radix) {
    -  var radix = opt_radix || 10;
    -  if (radix < 2 || 36 < radix) {
    -    throw Error('radix out of range: ' + radix);
    -  }
    -
    -  if (this.isZero()) {
    -    return '0';
    -  } else if (this.isNegative()) {
    -    return '-' + this.negate().toString(radix);
    -  }
    -
    -  // Do several (6) digits each time through the loop, so as to
    -  // minimize the calls to the very expensive emulated div.
    -  var radixToPower = goog.math.Integer.fromNumber(Math.pow(radix, 6));
    -
    -  var rem = this;
    -  var result = '';
    -  while (true) {
    -    var remDiv = rem.divide(radixToPower);
    -    var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt();
    -    var digits = intval.toString(radix);
    -
    -    rem = remDiv;
    -    if (rem.isZero()) {
    -      return digits + result;
    -    } else {
    -      while (digits.length < 6) {
    -        digits = '0' + digits;
    -      }
    -      result = '' + digits + result;
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Returns the index-th 32-bit (signed) piece of the Integer according to
    - * little-endian order (i.e., index 0 contains the smallest bits).
    - * @param {number} index The index in question.
    - * @return {number} The requested 32-bits as a signed number.
    - */
    -goog.math.Integer.prototype.getBits = function(index) {
    -  if (index < 0) {
    -    return 0;  // Allowing this simplifies bit shifting operations below...
    -  } else if (index < this.bits_.length) {
    -    return this.bits_[index];
    -  } else {
    -    return this.sign_;
    -  }
    -};
    -
    -
    -/**
    - * Returns the index-th 32-bit piece as an unsigned number.
    - * @param {number} index The index in question.
    - * @return {number} The requested 32-bits as an unsigned number.
    - */
    -goog.math.Integer.prototype.getBitsUnsigned = function(index) {
    -  var val = this.getBits(index);
    -  return val >= 0 ? val : goog.math.Integer.TWO_PWR_32_DBL_ + val;
    -};
    -
    -
    -/** @return {number} The sign bit of this number, -1 or 0. */
    -goog.math.Integer.prototype.getSign = function() {
    -  return this.sign_;
    -};
    -
    -
    -/** @return {boolean} Whether this value is zero. */
    -goog.math.Integer.prototype.isZero = function() {
    -  if (this.sign_ != 0) {
    -    return false;
    -  }
    -  for (var i = 0; i < this.bits_.length; i++) {
    -    if (this.bits_[i] != 0) {
    -      return false;
    -    }
    -  }
    -  return true;
    -};
    -
    -
    -/** @return {boolean} Whether this value is negative. */
    -goog.math.Integer.prototype.isNegative = function() {
    -  return this.sign_ == -1;
    -};
    -
    -
    -/** @return {boolean} Whether this value is odd. */
    -goog.math.Integer.prototype.isOdd = function() {
    -  return (this.bits_.length == 0) && (this.sign_ == -1) ||
    -         (this.bits_.length > 0) && ((this.bits_[0] & 1) != 0);
    -};
    -
    -
    -/**
    - * @param {goog.math.Integer} other Integer to compare against.
    - * @return {boolean} Whether this Integer equals the other.
    - */
    -goog.math.Integer.prototype.equals = function(other) {
    -  if (this.sign_ != other.sign_) {
    -    return false;
    -  }
    -  var len = Math.max(this.bits_.length, other.bits_.length);
    -  for (var i = 0; i < len; i++) {
    -    if (this.getBits(i) != other.getBits(i)) {
    -      return false;
    -    }
    -  }
    -  return true;
    -};
    -
    -
    -/**
    - * @param {goog.math.Integer} other Integer to compare against.
    - * @return {boolean} Whether this Integer does not equal the other.
    - */
    -goog.math.Integer.prototype.notEquals = function(other) {
    -  return !this.equals(other);
    -};
    -
    -
    -/**
    - * @param {goog.math.Integer} other Integer to compare against.
    - * @return {boolean} Whether this Integer is greater than the other.
    - */
    -goog.math.Integer.prototype.greaterThan = function(other) {
    -  return this.compare(other) > 0;
    -};
    -
    -
    -/**
    - * @param {goog.math.Integer} other Integer to compare against.
    - * @return {boolean} Whether this Integer is greater than or equal to the other.
    - */
    -goog.math.Integer.prototype.greaterThanOrEqual = function(other) {
    -  return this.compare(other) >= 0;
    -};
    -
    -
    -/**
    - * @param {goog.math.Integer} other Integer to compare against.
    - * @return {boolean} Whether this Integer is less than the other.
    - */
    -goog.math.Integer.prototype.lessThan = function(other) {
    -  return this.compare(other) < 0;
    -};
    -
    -
    -/**
    - * @param {goog.math.Integer} other Integer to compare against.
    - * @return {boolean} Whether this Integer is less than or equal to the other.
    - */
    -goog.math.Integer.prototype.lessThanOrEqual = function(other) {
    -  return this.compare(other) <= 0;
    -};
    -
    -
    -/**
    - * Compares this Integer with the given one.
    - * @param {goog.math.Integer} other Integer to compare against.
    - * @return {number} 0 if they are the same, 1 if the this is greater, and -1
    - *     if the given one is greater.
    - */
    -goog.math.Integer.prototype.compare = function(other) {
    -  var diff = this.subtract(other);
    -  if (diff.isNegative()) {
    -    return -1;
    -  } else if (diff.isZero()) {
    -    return 0;
    -  } else {
    -    return +1;
    -  }
    -};
    -
    -
    -/**
    - * Returns an integer with only the first numBits bits of this value, sign
    - * extended from the final bit.
    - * @param {number} numBits The number of bits by which to shift.
    - * @return {!goog.math.Integer} The shorted integer value.
    - */
    -goog.math.Integer.prototype.shorten = function(numBits) {
    -  var arr_index = (numBits - 1) >> 5;
    -  var bit_index = (numBits - 1) % 32;
    -  var bits = [];
    -  for (var i = 0; i < arr_index; i++) {
    -    bits[i] = this.getBits(i);
    -  }
    -  var sigBits = bit_index == 31 ? 0xFFFFFFFF : (1 << (bit_index + 1)) - 1;
    -  var val = this.getBits(arr_index) & sigBits;
    -  if (val & (1 << bit_index)) {
    -    val |= 0xFFFFFFFF - sigBits;
    -    bits[arr_index] = val;
    -    return new goog.math.Integer(bits, -1);
    -  } else {
    -    bits[arr_index] = val;
    -    return new goog.math.Integer(bits, 0);
    -  }
    -};
    -
    -
    -/** @return {!goog.math.Integer} The negation of this value. */
    -goog.math.Integer.prototype.negate = function() {
    -  return this.not().add(goog.math.Integer.ONE);
    -};
    -
    -
    -/**
    - * Returns the sum of this and the given Integer.
    - * @param {goog.math.Integer} other The Integer to add to this.
    - * @return {!goog.math.Integer} The Integer result.
    - */
    -goog.math.Integer.prototype.add = function(other) {
    -  var len = Math.max(this.bits_.length, other.bits_.length);
    -  var arr = [];
    -  var carry = 0;
    -
    -  for (var i = 0; i <= len; i++) {
    -    var a1 = this.getBits(i) >>> 16;
    -    var a0 = this.getBits(i) & 0xFFFF;
    -
    -    var b1 = other.getBits(i) >>> 16;
    -    var b0 = other.getBits(i) & 0xFFFF;
    -
    -    var c0 = carry + a0 + b0;
    -    var c1 = (c0 >>> 16) + a1 + b1;
    -    carry = c1 >>> 16;
    -    c0 &= 0xFFFF;
    -    c1 &= 0xFFFF;
    -    arr[i] = (c1 << 16) | c0;
    -  }
    -  return goog.math.Integer.fromBits(arr);
    -};
    -
    -
    -/**
    - * Returns the difference of this and the given Integer.
    - * @param {goog.math.Integer} other The Integer to subtract from this.
    - * @return {!goog.math.Integer} The Integer result.
    - */
    -goog.math.Integer.prototype.subtract = function(other) {
    -  return this.add(other.negate());
    -};
    -
    -
    -/**
    - * Returns the product of this and the given Integer.
    - * @param {goog.math.Integer} other The Integer to multiply against this.
    - * @return {!goog.math.Integer} The product of this and the other.
    - */
    -goog.math.Integer.prototype.multiply = function(other) {
    -  if (this.isZero()) {
    -    return goog.math.Integer.ZERO;
    -  } else if (other.isZero()) {
    -    return goog.math.Integer.ZERO;
    -  }
    -
    -  if (this.isNegative()) {
    -    if (other.isNegative()) {
    -      return this.negate().multiply(other.negate());
    -    } else {
    -      return this.negate().multiply(other).negate();
    -    }
    -  } else if (other.isNegative()) {
    -    return this.multiply(other.negate()).negate();
    -  }
    -
    -  // If both numbers are small, use float multiplication
    -  if (this.lessThan(goog.math.Integer.TWO_PWR_24_) &&
    -      other.lessThan(goog.math.Integer.TWO_PWR_24_)) {
    -    return goog.math.Integer.fromNumber(this.toNumber() * other.toNumber());
    -  }
    -
    -  // Fill in an array of 16-bit products.
    -  var len = this.bits_.length + other.bits_.length;
    -  var arr = [];
    -  for (var i = 0; i < 2 * len; i++) {
    -    arr[i] = 0;
    -  }
    -  for (var i = 0; i < this.bits_.length; i++) {
    -    for (var j = 0; j < other.bits_.length; j++) {
    -      var a1 = this.getBits(i) >>> 16;
    -      var a0 = this.getBits(i) & 0xFFFF;
    -
    -      var b1 = other.getBits(j) >>> 16;
    -      var b0 = other.getBits(j) & 0xFFFF;
    -
    -      arr[2 * i + 2 * j] += a0 * b0;
    -      goog.math.Integer.carry16_(arr, 2 * i + 2 * j);
    -      arr[2 * i + 2 * j + 1] += a1 * b0;
    -      goog.math.Integer.carry16_(arr, 2 * i + 2 * j + 1);
    -      arr[2 * i + 2 * j + 1] += a0 * b1;
    -      goog.math.Integer.carry16_(arr, 2 * i + 2 * j + 1);
    -      arr[2 * i + 2 * j + 2] += a1 * b1;
    -      goog.math.Integer.carry16_(arr, 2 * i + 2 * j + 2);
    -    }
    -  }
    -
    -  // Combine the 16-bit values into 32-bit values.
    -  for (var i = 0; i < len; i++) {
    -    arr[i] = (arr[2 * i + 1] << 16) | arr[2 * i];
    -  }
    -  for (var i = len; i < 2 * len; i++) {
    -    arr[i] = 0;
    -  }
    -  return new goog.math.Integer(arr, 0);
    -};
    -
    -
    -/**
    - * Carries any overflow from the given index into later entries.
    - * @param {Array<number>} bits Array of 16-bit values in little-endian order.
    - * @param {number} index The index in question.
    - * @private
    - */
    -goog.math.Integer.carry16_ = function(bits, index) {
    -  while ((bits[index] & 0xFFFF) != bits[index]) {
    -    bits[index + 1] += bits[index] >>> 16;
    -    bits[index] &= 0xFFFF;
    -  }
    -};
    -
    -
    -/**
    - * Returns this Integer divided by the given one.
    - * @param {goog.math.Integer} other Th Integer to divide this by.
    - * @return {!goog.math.Integer} This value divided by the given one.
    - */
    -goog.math.Integer.prototype.divide = function(other) {
    -  if (other.isZero()) {
    -    throw Error('division by zero');
    -  } else if (this.isZero()) {
    -    return goog.math.Integer.ZERO;
    -  }
    -
    -  if (this.isNegative()) {
    -    if (other.isNegative()) {
    -      return this.negate().divide(other.negate());
    -    } else {
    -      return this.negate().divide(other).negate();
    -    }
    -  } else if (other.isNegative()) {
    -    return this.divide(other.negate()).negate();
    -  }
    -
    -  // Repeat the following until the remainder is less than other:  find a
    -  // floating-point that approximates remainder / other *from below*, add this
    -  // into the result, and subtract it from the remainder.  It is critical that
    -  // the approximate value is less than or equal to the real value so that the
    -  // remainder never becomes negative.
    -  var res = goog.math.Integer.ZERO;
    -  var rem = this;
    -  while (rem.greaterThanOrEqual(other)) {
    -    // Approximate the result of division. This may be a little greater or
    -    // smaller than the actual value.
    -    var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber()));
    -
    -    // We will tweak the approximate result by changing it in the 48-th digit or
    -    // the smallest non-fractional digit, whichever is larger.
    -    var log2 = Math.ceil(Math.log(approx) / Math.LN2);
    -    var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48);
    -
    -    // Decrease the approximation until it is smaller than the remainder.  Note
    -    // that if it is too large, the product overflows and is negative.
    -    var approxRes = goog.math.Integer.fromNumber(approx);
    -    var approxRem = approxRes.multiply(other);
    -    while (approxRem.isNegative() || approxRem.greaterThan(rem)) {
    -      approx -= delta;
    -      approxRes = goog.math.Integer.fromNumber(approx);
    -      approxRem = approxRes.multiply(other);
    -    }
    -
    -    // We know the answer can't be zero... and actually, zero would cause
    -    // infinite recursion since we would make no progress.
    -    if (approxRes.isZero()) {
    -      approxRes = goog.math.Integer.ONE;
    -    }
    -
    -    res = res.add(approxRes);
    -    rem = rem.subtract(approxRem);
    -  }
    -  return res;
    -};
    -
    -
    -/**
    - * Returns this Integer modulo the given one.
    - * @param {goog.math.Integer} other The Integer by which to mod.
    - * @return {!goog.math.Integer} This value modulo the given one.
    - */
    -goog.math.Integer.prototype.modulo = function(other) {
    -  return this.subtract(this.divide(other).multiply(other));
    -};
    -
    -
    -/** @return {!goog.math.Integer} The bitwise-NOT of this value. */
    -goog.math.Integer.prototype.not = function() {
    -  var len = this.bits_.length;
    -  var arr = [];
    -  for (var i = 0; i < len; i++) {
    -    arr[i] = ~this.bits_[i];
    -  }
    -  return new goog.math.Integer(arr, ~this.sign_);
    -};
    -
    -
    -/**
    - * Returns the bitwise-AND of this Integer and the given one.
    - * @param {goog.math.Integer} other The Integer to AND with this.
    - * @return {!goog.math.Integer} The bitwise-AND of this and the other.
    - */
    -goog.math.Integer.prototype.and = function(other) {
    -  var len = Math.max(this.bits_.length, other.bits_.length);
    -  var arr = [];
    -  for (var i = 0; i < len; i++) {
    -    arr[i] = this.getBits(i) & other.getBits(i);
    -  }
    -  return new goog.math.Integer(arr, this.sign_ & other.sign_);
    -};
    -
    -
    -/**
    - * Returns the bitwise-OR of this Integer and the given one.
    - * @param {goog.math.Integer} other The Integer to OR with this.
    - * @return {!goog.math.Integer} The bitwise-OR of this and the other.
    - */
    -goog.math.Integer.prototype.or = function(other) {
    -  var len = Math.max(this.bits_.length, other.bits_.length);
    -  var arr = [];
    -  for (var i = 0; i < len; i++) {
    -    arr[i] = this.getBits(i) | other.getBits(i);
    -  }
    -  return new goog.math.Integer(arr, this.sign_ | other.sign_);
    -};
    -
    -
    -/**
    - * Returns the bitwise-XOR of this Integer and the given one.
    - * @param {goog.math.Integer} other The Integer to XOR with this.
    - * @return {!goog.math.Integer} The bitwise-XOR of this and the other.
    - */
    -goog.math.Integer.prototype.xor = function(other) {
    -  var len = Math.max(this.bits_.length, other.bits_.length);
    -  var arr = [];
    -  for (var i = 0; i < len; i++) {
    -    arr[i] = this.getBits(i) ^ other.getBits(i);
    -  }
    -  return new goog.math.Integer(arr, this.sign_ ^ other.sign_);
    -};
    -
    -
    -/**
    - * Returns this value with bits shifted to the left by the given amount.
    - * @param {number} numBits The number of bits by which to shift.
    - * @return {!goog.math.Integer} This shifted to the left by the given amount.
    - */
    -goog.math.Integer.prototype.shiftLeft = function(numBits) {
    -  var arr_delta = numBits >> 5;
    -  var bit_delta = numBits % 32;
    -  var len = this.bits_.length + arr_delta + (bit_delta > 0 ? 1 : 0);
    -  var arr = [];
    -  for (var i = 0; i < len; i++) {
    -    if (bit_delta > 0) {
    -      arr[i] = (this.getBits(i - arr_delta) << bit_delta) |
    -               (this.getBits(i - arr_delta - 1) >>> (32 - bit_delta));
    -    } else {
    -      arr[i] = this.getBits(i - arr_delta);
    -    }
    -  }
    -  return new goog.math.Integer(arr, this.sign_);
    -};
    -
    -
    -/**
    - * Returns this value with bits shifted to the right by the given amount.
    - * @param {number} numBits The number of bits by which to shift.
    - * @return {!goog.math.Integer} This shifted to the right by the given amount.
    - */
    -goog.math.Integer.prototype.shiftRight = function(numBits) {
    -  var arr_delta = numBits >> 5;
    -  var bit_delta = numBits % 32;
    -  var len = this.bits_.length - arr_delta;
    -  var arr = [];
    -  for (var i = 0; i < len; i++) {
    -    if (bit_delta > 0) {
    -      arr[i] = (this.getBits(i + arr_delta) >>> bit_delta) |
    -               (this.getBits(i + arr_delta + 1) << (32 - bit_delta));
    -    } else {
    -      arr[i] = this.getBits(i + arr_delta);
    -    }
    -  }
    -  return new goog.math.Integer(arr, this.sign_);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/math/integer_test.html b/src/database/third_party/closure-library/closure/goog/math/integer_test.html
    deleted file mode 100644
    index b9a065bbf1f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/integer_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.math.Integer
    -  </title>
    -  <script src="../base.js" type="text/javascript">
    -  </script>
    -  <script type="text/javascript">
    -   goog.require('goog.math.IntegerTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/math/integer_test.js b/src/database/third_party/closure-library/closure/goog/math/integer_test.js
    deleted file mode 100644
    index fac05286818..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/integer_test.js
    +++ /dev/null
    @@ -1,1651 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.math.IntegerTest');
    -goog.setTestOnly('goog.math.IntegerTest');
    -
    -goog.require('goog.math.Integer');
    -goog.require('goog.testing.jsunit');
    -
    -// Interprets the given numbers as the bits of a 32-bit int.  In particular,
    -// this takes care of the 32-bit being interpretted as the sign.
    -function toInt32s(arr) {
    -  for (var i = 0; i < arr.length; ++i) {
    -    arr[i] = arr[i] & 0xFFFFFFFF;
    -  }
    -}
    -
    -// Note that these are in numerical order.
    -var TEST_BITS = [0x80000000, 0x00000000,
    -  0xb776d5f5, 0x5634e2db,
    -  0xffefffff, 0xffffffff,
    -  0xfff00000, 0x00000000,
    -  0xfffeffff, 0xffffffff,
    -  0xffff0000, 0x00000000,
    -  0xfffffffe, 0xffffffff,
    -  0xffffffff, 0x00000000,
    -  0xffffffff, 0xfeffffff,
    -  0xffffffff, 0xff000000,
    -  0xffffffff, 0xfffeffff,
    -  0xffffffff, 0xffff0000,
    -  0xffffffff, 0xffff7fff,
    -  0xffffffff, 0xffff8000,
    -  0xffffffff, 0xfffffffe,
    -  0xffffffff, 0xffffffff,
    -  0x00000000, 0x00000000,
    -  0x00000000, 0x00000001,
    -  0x00000000, 0x00000002,
    -  0x00000000, 0x00007fff,
    -  0x00000000, 0x00008000,
    -  0x00000000, 0x0000ffff,
    -  0x00000000, 0x00010000,
    -  0x00000000, 0x00ffffff,
    -  0x00000000, 0x01000000,
    -  0x00000000, 0x5634e2db,
    -  0x00000000, 0xb776d5f5,
    -  0x00000000, 0xffffffff,
    -  0x00000001, 0x00000000,
    -  0x0000ffff, 0xffffffff,
    -  0x00010000, 0x00000000,
    -  0x000fffff, 0xffffffff,
    -  0x00100000, 0x00000000,
    -  0x5634e2db, 0xb776d5f5,
    -  0x7fffffff, 0xffffffff];
    -toInt32s(TEST_BITS);
    -
    -var TEST_ADD_BITS = [
    -  0x3776d5f5, 0x5634e2db, 0x7fefffff, 0xffffffff, 0xb766d5f5, 0x5634e2da,
    -  0x7ff00000, 0x00000000, 0xb766d5f5, 0x5634e2db, 0xffdfffff, 0xffffffff,
    -  0x7ffeffff, 0xffffffff, 0xb775d5f5, 0x5634e2da, 0xffeeffff, 0xfffffffe,
    -  0xffeeffff, 0xffffffff, 0x7fff0000, 0x00000000, 0xb775d5f5, 0x5634e2db,
    -  0xffeeffff, 0xffffffff, 0xffef0000, 0x00000000, 0xfffdffff, 0xffffffff,
    -  0x7ffffffe, 0xffffffff, 0xb776d5f4, 0x5634e2da, 0xffeffffe, 0xfffffffe,
    -  0xffeffffe, 0xffffffff, 0xfffefffe, 0xfffffffe, 0xfffefffe, 0xffffffff,
    -  0x7fffffff, 0x00000000, 0xb776d5f4, 0x5634e2db, 0xffeffffe, 0xffffffff,
    -  0xffefffff, 0x00000000, 0xfffefffe, 0xffffffff, 0xfffeffff, 0x00000000,
    -  0xfffffffd, 0xffffffff, 0x7fffffff, 0xfeffffff, 0xb776d5f5, 0x5534e2da,
    -  0xffefffff, 0xfefffffe, 0xffefffff, 0xfeffffff, 0xfffeffff, 0xfefffffe,
    -  0xfffeffff, 0xfeffffff, 0xfffffffe, 0xfefffffe, 0xfffffffe, 0xfeffffff,
    -  0x7fffffff, 0xff000000, 0xb776d5f5, 0x5534e2db, 0xffefffff, 0xfeffffff,
    -  0xffefffff, 0xff000000, 0xfffeffff, 0xfeffffff, 0xfffeffff, 0xff000000,
    -  0xfffffffe, 0xfeffffff, 0xfffffffe, 0xff000000, 0xffffffff, 0xfdffffff,
    -  0x7fffffff, 0xfffeffff, 0xb776d5f5, 0x5633e2da, 0xffefffff, 0xfffefffe,
    -  0xffefffff, 0xfffeffff, 0xfffeffff, 0xfffefffe, 0xfffeffff, 0xfffeffff,
    -  0xfffffffe, 0xfffefffe, 0xfffffffe, 0xfffeffff, 0xffffffff, 0xfefefffe,
    -  0xffffffff, 0xfefeffff, 0x7fffffff, 0xffff0000, 0xb776d5f5, 0x5633e2db,
    -  0xffefffff, 0xfffeffff, 0xffefffff, 0xffff0000, 0xfffeffff, 0xfffeffff,
    -  0xfffeffff, 0xffff0000, 0xfffffffe, 0xfffeffff, 0xfffffffe, 0xffff0000,
    -  0xffffffff, 0xfefeffff, 0xffffffff, 0xfeff0000, 0xffffffff, 0xfffdffff,
    -  0x7fffffff, 0xffff7fff, 0xb776d5f5, 0x563462da, 0xffefffff, 0xffff7ffe,
    -  0xffefffff, 0xffff7fff, 0xfffeffff, 0xffff7ffe, 0xfffeffff, 0xffff7fff,
    -  0xfffffffe, 0xffff7ffe, 0xfffffffe, 0xffff7fff, 0xffffffff, 0xfeff7ffe,
    -  0xffffffff, 0xfeff7fff, 0xffffffff, 0xfffe7ffe, 0xffffffff, 0xfffe7fff,
    -  0x7fffffff, 0xffff8000, 0xb776d5f5, 0x563462db, 0xffefffff, 0xffff7fff,
    -  0xffefffff, 0xffff8000, 0xfffeffff, 0xffff7fff, 0xfffeffff, 0xffff8000,
    -  0xfffffffe, 0xffff7fff, 0xfffffffe, 0xffff8000, 0xffffffff, 0xfeff7fff,
    -  0xffffffff, 0xfeff8000, 0xffffffff, 0xfffe7fff, 0xffffffff, 0xfffe8000,
    -  0xffffffff, 0xfffeffff, 0x7fffffff, 0xfffffffe, 0xb776d5f5, 0x5634e2d9,
    -  0xffefffff, 0xfffffffd, 0xffefffff, 0xfffffffe, 0xfffeffff, 0xfffffffd,
    -  0xfffeffff, 0xfffffffe, 0xfffffffe, 0xfffffffd, 0xfffffffe, 0xfffffffe,
    -  0xffffffff, 0xfefffffd, 0xffffffff, 0xfefffffe, 0xffffffff, 0xfffefffd,
    -  0xffffffff, 0xfffefffe, 0xffffffff, 0xffff7ffd, 0xffffffff, 0xffff7ffe,
    -  0x7fffffff, 0xffffffff, 0xb776d5f5, 0x5634e2da, 0xffefffff, 0xfffffffe,
    -  0xffefffff, 0xffffffff, 0xfffeffff, 0xfffffffe, 0xfffeffff, 0xffffffff,
    -  0xfffffffe, 0xfffffffe, 0xfffffffe, 0xffffffff, 0xffffffff, 0xfefffffe,
    -  0xffffffff, 0xfeffffff, 0xffffffff, 0xfffefffe, 0xffffffff, 0xfffeffff,
    -  0xffffffff, 0xffff7ffe, 0xffffffff, 0xffff7fff, 0xffffffff, 0xfffffffd,
    -  0x80000000, 0x00000000, 0xb776d5f5, 0x5634e2db, 0xffefffff, 0xffffffff,
    -  0xfff00000, 0x00000000, 0xfffeffff, 0xffffffff, 0xffff0000, 0x00000000,
    -  0xfffffffe, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xfeffffff,
    -  0xffffffff, 0xff000000, 0xffffffff, 0xfffeffff, 0xffffffff, 0xffff0000,
    -  0xffffffff, 0xffff7fff, 0xffffffff, 0xffff8000, 0xffffffff, 0xfffffffe,
    -  0xffffffff, 0xffffffff, 0x80000000, 0x00000001, 0xb776d5f5, 0x5634e2dc,
    -  0xfff00000, 0x00000000, 0xfff00000, 0x00000001, 0xffff0000, 0x00000000,
    -  0xffff0000, 0x00000001, 0xffffffff, 0x00000000, 0xffffffff, 0x00000001,
    -  0xffffffff, 0xff000000, 0xffffffff, 0xff000001, 0xffffffff, 0xffff0000,
    -  0xffffffff, 0xffff0001, 0xffffffff, 0xffff8000, 0xffffffff, 0xffff8001,
    -  0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
    -  0x80000000, 0x00000002, 0xb776d5f5, 0x5634e2dd, 0xfff00000, 0x00000001,
    -  0xfff00000, 0x00000002, 0xffff0000, 0x00000001, 0xffff0000, 0x00000002,
    -  0xffffffff, 0x00000001, 0xffffffff, 0x00000002, 0xffffffff, 0xff000001,
    -  0xffffffff, 0xff000002, 0xffffffff, 0xffff0001, 0xffffffff, 0xffff0002,
    -  0xffffffff, 0xffff8001, 0xffffffff, 0xffff8002, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000001, 0x00000000, 0x00000002, 0x00000000, 0x00000003,
    -  0x80000000, 0x00007fff, 0xb776d5f5, 0x563562da, 0xfff00000, 0x00007ffe,
    -  0xfff00000, 0x00007fff, 0xffff0000, 0x00007ffe, 0xffff0000, 0x00007fff,
    -  0xffffffff, 0x00007ffe, 0xffffffff, 0x00007fff, 0xffffffff, 0xff007ffe,
    -  0xffffffff, 0xff007fff, 0xffffffff, 0xffff7ffe, 0xffffffff, 0xffff7fff,
    -  0xffffffff, 0xfffffffe, 0xffffffff, 0xffffffff, 0x00000000, 0x00007ffd,
    -  0x00000000, 0x00007ffe, 0x00000000, 0x00007fff, 0x00000000, 0x00008000,
    -  0x00000000, 0x00008001, 0x80000000, 0x00008000, 0xb776d5f5, 0x563562db,
    -  0xfff00000, 0x00007fff, 0xfff00000, 0x00008000, 0xffff0000, 0x00007fff,
    -  0xffff0000, 0x00008000, 0xffffffff, 0x00007fff, 0xffffffff, 0x00008000,
    -  0xffffffff, 0xff007fff, 0xffffffff, 0xff008000, 0xffffffff, 0xffff7fff,
    -  0xffffffff, 0xffff8000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
    -  0x00000000, 0x00007ffe, 0x00000000, 0x00007fff, 0x00000000, 0x00008000,
    -  0x00000000, 0x00008001, 0x00000000, 0x00008002, 0x00000000, 0x0000ffff,
    -  0x80000000, 0x0000ffff, 0xb776d5f5, 0x5635e2da, 0xfff00000, 0x0000fffe,
    -  0xfff00000, 0x0000ffff, 0xffff0000, 0x0000fffe, 0xffff0000, 0x0000ffff,
    -  0xffffffff, 0x0000fffe, 0xffffffff, 0x0000ffff, 0xffffffff, 0xff00fffe,
    -  0xffffffff, 0xff00ffff, 0xffffffff, 0xfffffffe, 0xffffffff, 0xffffffff,
    -  0x00000000, 0x00007ffe, 0x00000000, 0x00007fff, 0x00000000, 0x0000fffd,
    -  0x00000000, 0x0000fffe, 0x00000000, 0x0000ffff, 0x00000000, 0x00010000,
    -  0x00000000, 0x00010001, 0x00000000, 0x00017ffe, 0x00000000, 0x00017fff,
    -  0x80000000, 0x00010000, 0xb776d5f5, 0x5635e2db, 0xfff00000, 0x0000ffff,
    -  0xfff00000, 0x00010000, 0xffff0000, 0x0000ffff, 0xffff0000, 0x00010000,
    -  0xffffffff, 0x0000ffff, 0xffffffff, 0x00010000, 0xffffffff, 0xff00ffff,
    -  0xffffffff, 0xff010000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
    -  0x00000000, 0x00007fff, 0x00000000, 0x00008000, 0x00000000, 0x0000fffe,
    -  0x00000000, 0x0000ffff, 0x00000000, 0x00010000, 0x00000000, 0x00010001,
    -  0x00000000, 0x00010002, 0x00000000, 0x00017fff, 0x00000000, 0x00018000,
    -  0x00000000, 0x0001ffff, 0x80000000, 0x00ffffff, 0xb776d5f5, 0x5734e2da,
    -  0xfff00000, 0x00fffffe, 0xfff00000, 0x00ffffff, 0xffff0000, 0x00fffffe,
    -  0xffff0000, 0x00ffffff, 0xffffffff, 0x00fffffe, 0xffffffff, 0x00ffffff,
    -  0xffffffff, 0xfffffffe, 0xffffffff, 0xffffffff, 0x00000000, 0x00fefffe,
    -  0x00000000, 0x00feffff, 0x00000000, 0x00ff7ffe, 0x00000000, 0x00ff7fff,
    -  0x00000000, 0x00fffffd, 0x00000000, 0x00fffffe, 0x00000000, 0x00ffffff,
    -  0x00000000, 0x01000000, 0x00000000, 0x01000001, 0x00000000, 0x01007ffe,
    -  0x00000000, 0x01007fff, 0x00000000, 0x0100fffe, 0x00000000, 0x0100ffff,
    -  0x80000000, 0x01000000, 0xb776d5f5, 0x5734e2db, 0xfff00000, 0x00ffffff,
    -  0xfff00000, 0x01000000, 0xffff0000, 0x00ffffff, 0xffff0000, 0x01000000,
    -  0xffffffff, 0x00ffffff, 0xffffffff, 0x01000000, 0xffffffff, 0xffffffff,
    -  0x00000000, 0x00000000, 0x00000000, 0x00feffff, 0x00000000, 0x00ff0000,
    -  0x00000000, 0x00ff7fff, 0x00000000, 0x00ff8000, 0x00000000, 0x00fffffe,
    -  0x00000000, 0x00ffffff, 0x00000000, 0x01000000, 0x00000000, 0x01000001,
    -  0x00000000, 0x01000002, 0x00000000, 0x01007fff, 0x00000000, 0x01008000,
    -  0x00000000, 0x0100ffff, 0x00000000, 0x01010000, 0x00000000, 0x01ffffff,
    -  0x80000000, 0x5634e2db, 0xb776d5f5, 0xac69c5b6, 0xfff00000, 0x5634e2da,
    -  0xfff00000, 0x5634e2db, 0xffff0000, 0x5634e2da, 0xffff0000, 0x5634e2db,
    -  0xffffffff, 0x5634e2da, 0xffffffff, 0x5634e2db, 0x00000000, 0x5534e2da,
    -  0x00000000, 0x5534e2db, 0x00000000, 0x5633e2da, 0x00000000, 0x5633e2db,
    -  0x00000000, 0x563462da, 0x00000000, 0x563462db, 0x00000000, 0x5634e2d9,
    -  0x00000000, 0x5634e2da, 0x00000000, 0x5634e2db, 0x00000000, 0x5634e2dc,
    -  0x00000000, 0x5634e2dd, 0x00000000, 0x563562da, 0x00000000, 0x563562db,
    -  0x00000000, 0x5635e2da, 0x00000000, 0x5635e2db, 0x00000000, 0x5734e2da,
    -  0x00000000, 0x5734e2db, 0x80000000, 0xb776d5f5, 0xb776d5f6, 0x0dabb8d0,
    -  0xfff00000, 0xb776d5f4, 0xfff00000, 0xb776d5f5, 0xffff0000, 0xb776d5f4,
    -  0xffff0000, 0xb776d5f5, 0xffffffff, 0xb776d5f4, 0xffffffff, 0xb776d5f5,
    -  0x00000000, 0xb676d5f4, 0x00000000, 0xb676d5f5, 0x00000000, 0xb775d5f4,
    -  0x00000000, 0xb775d5f5, 0x00000000, 0xb77655f4, 0x00000000, 0xb77655f5,
    -  0x00000000, 0xb776d5f3, 0x00000000, 0xb776d5f4, 0x00000000, 0xb776d5f5,
    -  0x00000000, 0xb776d5f6, 0x00000000, 0xb776d5f7, 0x00000000, 0xb77755f4,
    -  0x00000000, 0xb77755f5, 0x00000000, 0xb777d5f4, 0x00000000, 0xb777d5f5,
    -  0x00000000, 0xb876d5f4, 0x00000000, 0xb876d5f5, 0x00000001, 0x0dabb8d0,
    -  0x80000000, 0xffffffff, 0xb776d5f6, 0x5634e2da, 0xfff00000, 0xfffffffe,
    -  0xfff00000, 0xffffffff, 0xffff0000, 0xfffffffe, 0xffff0000, 0xffffffff,
    -  0xffffffff, 0xfffffffe, 0xffffffff, 0xffffffff, 0x00000000, 0xfefffffe,
    -  0x00000000, 0xfeffffff, 0x00000000, 0xfffefffe, 0x00000000, 0xfffeffff,
    -  0x00000000, 0xffff7ffe, 0x00000000, 0xffff7fff, 0x00000000, 0xfffffffd,
    -  0x00000000, 0xfffffffe, 0x00000000, 0xffffffff, 0x00000001, 0x00000000,
    -  0x00000001, 0x00000001, 0x00000001, 0x00007ffe, 0x00000001, 0x00007fff,
    -  0x00000001, 0x0000fffe, 0x00000001, 0x0000ffff, 0x00000001, 0x00fffffe,
    -  0x00000001, 0x00ffffff, 0x00000001, 0x5634e2da, 0x00000001, 0xb776d5f4,
    -  0x80000001, 0x00000000, 0xb776d5f6, 0x5634e2db, 0xfff00000, 0xffffffff,
    -  0xfff00001, 0x00000000, 0xffff0000, 0xffffffff, 0xffff0001, 0x00000000,
    -  0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xfeffffff,
    -  0x00000000, 0xff000000, 0x00000000, 0xfffeffff, 0x00000000, 0xffff0000,
    -  0x00000000, 0xffff7fff, 0x00000000, 0xffff8000, 0x00000000, 0xfffffffe,
    -  0x00000000, 0xffffffff, 0x00000001, 0x00000000, 0x00000001, 0x00000001,
    -  0x00000001, 0x00000002, 0x00000001, 0x00007fff, 0x00000001, 0x00008000,
    -  0x00000001, 0x0000ffff, 0x00000001, 0x00010000, 0x00000001, 0x00ffffff,
    -  0x00000001, 0x01000000, 0x00000001, 0x5634e2db, 0x00000001, 0xb776d5f5,
    -  0x00000001, 0xffffffff, 0x8000ffff, 0xffffffff, 0xb777d5f5, 0x5634e2da,
    -  0xfff0ffff, 0xfffffffe, 0xfff0ffff, 0xffffffff, 0xffffffff, 0xfffffffe,
    -  0xffffffff, 0xffffffff, 0x0000fffe, 0xfffffffe, 0x0000fffe, 0xffffffff,
    -  0x0000ffff, 0xfefffffe, 0x0000ffff, 0xfeffffff, 0x0000ffff, 0xfffefffe,
    -  0x0000ffff, 0xfffeffff, 0x0000ffff, 0xffff7ffe, 0x0000ffff, 0xffff7fff,
    -  0x0000ffff, 0xfffffffd, 0x0000ffff, 0xfffffffe, 0x0000ffff, 0xffffffff,
    -  0x00010000, 0x00000000, 0x00010000, 0x00000001, 0x00010000, 0x00007ffe,
    -  0x00010000, 0x00007fff, 0x00010000, 0x0000fffe, 0x00010000, 0x0000ffff,
    -  0x00010000, 0x00fffffe, 0x00010000, 0x00ffffff, 0x00010000, 0x5634e2da,
    -  0x00010000, 0xb776d5f4, 0x00010000, 0xfffffffe, 0x00010000, 0xffffffff,
    -  0x80010000, 0x00000000, 0xb777d5f5, 0x5634e2db, 0xfff0ffff, 0xffffffff,
    -  0xfff10000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
    -  0x0000fffe, 0xffffffff, 0x0000ffff, 0x00000000, 0x0000ffff, 0xfeffffff,
    -  0x0000ffff, 0xff000000, 0x0000ffff, 0xfffeffff, 0x0000ffff, 0xffff0000,
    -  0x0000ffff, 0xffff7fff, 0x0000ffff, 0xffff8000, 0x0000ffff, 0xfffffffe,
    -  0x0000ffff, 0xffffffff, 0x00010000, 0x00000000, 0x00010000, 0x00000001,
    -  0x00010000, 0x00000002, 0x00010000, 0x00007fff, 0x00010000, 0x00008000,
    -  0x00010000, 0x0000ffff, 0x00010000, 0x00010000, 0x00010000, 0x00ffffff,
    -  0x00010000, 0x01000000, 0x00010000, 0x5634e2db, 0x00010000, 0xb776d5f5,
    -  0x00010000, 0xffffffff, 0x00010001, 0x00000000, 0x0001ffff, 0xffffffff,
    -  0x800fffff, 0xffffffff, 0xb786d5f5, 0x5634e2da, 0xffffffff, 0xfffffffe,
    -  0xffffffff, 0xffffffff, 0x000effff, 0xfffffffe, 0x000effff, 0xffffffff,
    -  0x000ffffe, 0xfffffffe, 0x000ffffe, 0xffffffff, 0x000fffff, 0xfefffffe,
    -  0x000fffff, 0xfeffffff, 0x000fffff, 0xfffefffe, 0x000fffff, 0xfffeffff,
    -  0x000fffff, 0xffff7ffe, 0x000fffff, 0xffff7fff, 0x000fffff, 0xfffffffd,
    -  0x000fffff, 0xfffffffe, 0x000fffff, 0xffffffff, 0x00100000, 0x00000000,
    -  0x00100000, 0x00000001, 0x00100000, 0x00007ffe, 0x00100000, 0x00007fff,
    -  0x00100000, 0x0000fffe, 0x00100000, 0x0000ffff, 0x00100000, 0x00fffffe,
    -  0x00100000, 0x00ffffff, 0x00100000, 0x5634e2da, 0x00100000, 0xb776d5f4,
    -  0x00100000, 0xfffffffe, 0x00100000, 0xffffffff, 0x0010ffff, 0xfffffffe,
    -  0x0010ffff, 0xffffffff, 0x80100000, 0x00000000, 0xb786d5f5, 0x5634e2db,
    -  0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x000effff, 0xffffffff,
    -  0x000f0000, 0x00000000, 0x000ffffe, 0xffffffff, 0x000fffff, 0x00000000,
    -  0x000fffff, 0xfeffffff, 0x000fffff, 0xff000000, 0x000fffff, 0xfffeffff,
    -  0x000fffff, 0xffff0000, 0x000fffff, 0xffff7fff, 0x000fffff, 0xffff8000,
    -  0x000fffff, 0xfffffffe, 0x000fffff, 0xffffffff, 0x00100000, 0x00000000,
    -  0x00100000, 0x00000001, 0x00100000, 0x00000002, 0x00100000, 0x00007fff,
    -  0x00100000, 0x00008000, 0x00100000, 0x0000ffff, 0x00100000, 0x00010000,
    -  0x00100000, 0x00ffffff, 0x00100000, 0x01000000, 0x00100000, 0x5634e2db,
    -  0x00100000, 0xb776d5f5, 0x00100000, 0xffffffff, 0x00100001, 0x00000000,
    -  0x0010ffff, 0xffffffff, 0x00110000, 0x00000000, 0x001fffff, 0xffffffff,
    -  0xd634e2db, 0xb776d5f5, 0x0dabb8d1, 0x0dabb8d0, 0x5624e2db, 0xb776d5f4,
    -  0x5624e2db, 0xb776d5f5, 0x5633e2db, 0xb776d5f4, 0x5633e2db, 0xb776d5f5,
    -  0x5634e2da, 0xb776d5f4, 0x5634e2da, 0xb776d5f5, 0x5634e2db, 0xb676d5f4,
    -  0x5634e2db, 0xb676d5f5, 0x5634e2db, 0xb775d5f4, 0x5634e2db, 0xb775d5f5,
    -  0x5634e2db, 0xb77655f4, 0x5634e2db, 0xb77655f5, 0x5634e2db, 0xb776d5f3,
    -  0x5634e2db, 0xb776d5f4, 0x5634e2db, 0xb776d5f5, 0x5634e2db, 0xb776d5f6,
    -  0x5634e2db, 0xb776d5f7, 0x5634e2db, 0xb77755f4, 0x5634e2db, 0xb77755f5,
    -  0x5634e2db, 0xb777d5f4, 0x5634e2db, 0xb777d5f5, 0x5634e2db, 0xb876d5f4,
    -  0x5634e2db, 0xb876d5f5, 0x5634e2dc, 0x0dabb8d0, 0x5634e2dc, 0x6eedabea,
    -  0x5634e2dc, 0xb776d5f4, 0x5634e2dc, 0xb776d5f5, 0x5635e2db, 0xb776d5f4,
    -  0x5635e2db, 0xb776d5f5, 0x5644e2db, 0xb776d5f4, 0x5644e2db, 0xb776d5f5,
    -  0xffffffff, 0xffffffff, 0x3776d5f5, 0x5634e2da, 0x7fefffff, 0xfffffffe,
    -  0x7fefffff, 0xffffffff, 0x7ffeffff, 0xfffffffe, 0x7ffeffff, 0xffffffff,
    -  0x7ffffffe, 0xfffffffe, 0x7ffffffe, 0xffffffff, 0x7fffffff, 0xfefffffe,
    -  0x7fffffff, 0xfeffffff, 0x7fffffff, 0xfffefffe, 0x7fffffff, 0xfffeffff,
    -  0x7fffffff, 0xffff7ffe, 0x7fffffff, 0xffff7fff, 0x7fffffff, 0xfffffffd,
    -  0x7fffffff, 0xfffffffe, 0x7fffffff, 0xffffffff, 0x80000000, 0x00000000,
    -  0x80000000, 0x00000001, 0x80000000, 0x00007ffe, 0x80000000, 0x00007fff,
    -  0x80000000, 0x0000fffe, 0x80000000, 0x0000ffff, 0x80000000, 0x00fffffe,
    -  0x80000000, 0x00ffffff, 0x80000000, 0x5634e2da, 0x80000000, 0xb776d5f4,
    -  0x80000000, 0xfffffffe, 0x80000000, 0xffffffff, 0x8000ffff, 0xfffffffe,
    -  0x8000ffff, 0xffffffff, 0x800fffff, 0xfffffffe, 0x800fffff, 0xffffffff,
    -  0xd634e2db, 0xb776d5f4
    -];
    -toInt32s(TEST_ADD_BITS);
    -
    -var TEST_SUB_BITS = [
    -  0x00000000, 0x00000000, 0xc8892a0a, 0xa9cb1d25, 0x80100000, 0x00000001,
    -  0x80100000, 0x00000000, 0x80010000, 0x00000001, 0x80010000, 0x00000000,
    -  0x80000001, 0x00000001, 0x80000001, 0x00000000, 0x80000000, 0x01000001,
    -  0x80000000, 0x01000000, 0x80000000, 0x00010001, 0x80000000, 0x00010000,
    -  0x80000000, 0x00008001, 0x80000000, 0x00008000, 0x80000000, 0x00000002,
    -  0x80000000, 0x00000001, 0x80000000, 0x00000000, 0x7fffffff, 0xffffffff,
    -  0x7fffffff, 0xfffffffe, 0x7fffffff, 0xffff8001, 0x7fffffff, 0xffff8000,
    -  0x7fffffff, 0xffff0001, 0x7fffffff, 0xffff0000, 0x7fffffff, 0xff000001,
    -  0x7fffffff, 0xff000000, 0x7fffffff, 0xa9cb1d25, 0x7fffffff, 0x48892a0b,
    -  0x7fffffff, 0x00000001, 0x7fffffff, 0x00000000, 0x7fff0000, 0x00000001,
    -  0x7fff0000, 0x00000000, 0x7ff00000, 0x00000001, 0x7ff00000, 0x00000000,
    -  0x29cb1d24, 0x48892a0b, 0x00000000, 0x00000001, 0x3776d5f5, 0x5634e2db,
    -  0x00000000, 0x00000000, 0xb786d5f5, 0x5634e2dc, 0xb786d5f5, 0x5634e2db,
    -  0xb777d5f5, 0x5634e2dc, 0xb777d5f5, 0x5634e2db, 0xb776d5f6, 0x5634e2dc,
    -  0xb776d5f6, 0x5634e2db, 0xb776d5f5, 0x5734e2dc, 0xb776d5f5, 0x5734e2db,
    -  0xb776d5f5, 0x5635e2dc, 0xb776d5f5, 0x5635e2db, 0xb776d5f5, 0x563562dc,
    -  0xb776d5f5, 0x563562db, 0xb776d5f5, 0x5634e2dd, 0xb776d5f5, 0x5634e2dc,
    -  0xb776d5f5, 0x5634e2db, 0xb776d5f5, 0x5634e2da, 0xb776d5f5, 0x5634e2d9,
    -  0xb776d5f5, 0x563462dc, 0xb776d5f5, 0x563462db, 0xb776d5f5, 0x5633e2dc,
    -  0xb776d5f5, 0x5633e2db, 0xb776d5f5, 0x5534e2dc, 0xb776d5f5, 0x5534e2db,
    -  0xb776d5f5, 0x00000000, 0xb776d5f4, 0x9ebe0ce6, 0xb776d5f4, 0x5634e2dc,
    -  0xb776d5f4, 0x5634e2db, 0xb775d5f5, 0x5634e2dc, 0xb775d5f5, 0x5634e2db,
    -  0xb766d5f5, 0x5634e2dc, 0xb766d5f5, 0x5634e2db, 0x6141f319, 0x9ebe0ce6,
    -  0x3776d5f5, 0x5634e2dc, 0x7fefffff, 0xffffffff, 0x48792a0a, 0xa9cb1d24,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xfff10000, 0x00000000,
    -  0xfff0ffff, 0xffffffff, 0xfff00001, 0x00000000, 0xfff00000, 0xffffffff,
    -  0xfff00000, 0x01000000, 0xfff00000, 0x00ffffff, 0xfff00000, 0x00010000,
    -  0xfff00000, 0x0000ffff, 0xfff00000, 0x00008000, 0xfff00000, 0x00007fff,
    -  0xfff00000, 0x00000001, 0xfff00000, 0x00000000, 0xffefffff, 0xffffffff,
    -  0xffefffff, 0xfffffffe, 0xffefffff, 0xfffffffd, 0xffefffff, 0xffff8000,
    -  0xffefffff, 0xffff7fff, 0xffefffff, 0xffff0000, 0xffefffff, 0xfffeffff,
    -  0xffefffff, 0xff000000, 0xffefffff, 0xfeffffff, 0xffefffff, 0xa9cb1d24,
    -  0xffefffff, 0x48892a0a, 0xffefffff, 0x00000000, 0xffeffffe, 0xffffffff,
    -  0xffef0000, 0x00000000, 0xffeeffff, 0xffffffff, 0xffe00000, 0x00000000,
    -  0xffdfffff, 0xffffffff, 0xa9bb1d24, 0x48892a0a, 0x7ff00000, 0x00000000,
    -  0x7ff00000, 0x00000000, 0x48792a0a, 0xa9cb1d25, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xfff10000, 0x00000001, 0xfff10000, 0x00000000,
    -  0xfff00001, 0x00000001, 0xfff00001, 0x00000000, 0xfff00000, 0x01000001,
    -  0xfff00000, 0x01000000, 0xfff00000, 0x00010001, 0xfff00000, 0x00010000,
    -  0xfff00000, 0x00008001, 0xfff00000, 0x00008000, 0xfff00000, 0x00000002,
    -  0xfff00000, 0x00000001, 0xfff00000, 0x00000000, 0xffefffff, 0xffffffff,
    -  0xffefffff, 0xfffffffe, 0xffefffff, 0xffff8001, 0xffefffff, 0xffff8000,
    -  0xffefffff, 0xffff0001, 0xffefffff, 0xffff0000, 0xffefffff, 0xff000001,
    -  0xffefffff, 0xff000000, 0xffefffff, 0xa9cb1d25, 0xffefffff, 0x48892a0b,
    -  0xffefffff, 0x00000001, 0xffefffff, 0x00000000, 0xffef0000, 0x00000001,
    -  0xffef0000, 0x00000000, 0xffe00000, 0x00000001, 0xffe00000, 0x00000000,
    -  0xa9bb1d24, 0x48892a0b, 0x7ff00000, 0x00000001, 0x7ffeffff, 0xffffffff,
    -  0x48882a0a, 0xa9cb1d24, 0x000f0000, 0x00000000, 0x000effff, 0xffffffff,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffff0001, 0x00000000,
    -  0xffff0000, 0xffffffff, 0xffff0000, 0x01000000, 0xffff0000, 0x00ffffff,
    -  0xffff0000, 0x00010000, 0xffff0000, 0x0000ffff, 0xffff0000, 0x00008000,
    -  0xffff0000, 0x00007fff, 0xffff0000, 0x00000001, 0xffff0000, 0x00000000,
    -  0xfffeffff, 0xffffffff, 0xfffeffff, 0xfffffffe, 0xfffeffff, 0xfffffffd,
    -  0xfffeffff, 0xffff8000, 0xfffeffff, 0xffff7fff, 0xfffeffff, 0xffff0000,
    -  0xfffeffff, 0xfffeffff, 0xfffeffff, 0xff000000, 0xfffeffff, 0xfeffffff,
    -  0xfffeffff, 0xa9cb1d24, 0xfffeffff, 0x48892a0a, 0xfffeffff, 0x00000000,
    -  0xfffefffe, 0xffffffff, 0xfffe0000, 0x00000000, 0xfffdffff, 0xffffffff,
    -  0xffef0000, 0x00000000, 0xffeeffff, 0xffffffff, 0xa9ca1d24, 0x48892a0a,
    -  0x7fff0000, 0x00000000, 0x7fff0000, 0x00000000, 0x48882a0a, 0xa9cb1d25,
    -  0x000f0000, 0x00000001, 0x000f0000, 0x00000000, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xffff0001, 0x00000001, 0xffff0001, 0x00000000,
    -  0xffff0000, 0x01000001, 0xffff0000, 0x01000000, 0xffff0000, 0x00010001,
    -  0xffff0000, 0x00010000, 0xffff0000, 0x00008001, 0xffff0000, 0x00008000,
    -  0xffff0000, 0x00000002, 0xffff0000, 0x00000001, 0xffff0000, 0x00000000,
    -  0xfffeffff, 0xffffffff, 0xfffeffff, 0xfffffffe, 0xfffeffff, 0xffff8001,
    -  0xfffeffff, 0xffff8000, 0xfffeffff, 0xffff0001, 0xfffeffff, 0xffff0000,
    -  0xfffeffff, 0xff000001, 0xfffeffff, 0xff000000, 0xfffeffff, 0xa9cb1d25,
    -  0xfffeffff, 0x48892a0b, 0xfffeffff, 0x00000001, 0xfffeffff, 0x00000000,
    -  0xfffe0000, 0x00000001, 0xfffe0000, 0x00000000, 0xffef0000, 0x00000001,
    -  0xffef0000, 0x00000000, 0xa9ca1d24, 0x48892a0b, 0x7fff0000, 0x00000001,
    -  0x7ffffffe, 0xffffffff, 0x48892a09, 0xa9cb1d24, 0x000fffff, 0x00000000,
    -  0x000ffffe, 0xffffffff, 0x0000ffff, 0x00000000, 0x0000fffe, 0xffffffff,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0x01000000,
    -  0xffffffff, 0x00ffffff, 0xffffffff, 0x00010000, 0xffffffff, 0x0000ffff,
    -  0xffffffff, 0x00008000, 0xffffffff, 0x00007fff, 0xffffffff, 0x00000001,
    -  0xffffffff, 0x00000000, 0xfffffffe, 0xffffffff, 0xfffffffe, 0xfffffffe,
    -  0xfffffffe, 0xfffffffd, 0xfffffffe, 0xffff8000, 0xfffffffe, 0xffff7fff,
    -  0xfffffffe, 0xffff0000, 0xfffffffe, 0xfffeffff, 0xfffffffe, 0xff000000,
    -  0xfffffffe, 0xfeffffff, 0xfffffffe, 0xa9cb1d24, 0xfffffffe, 0x48892a0a,
    -  0xfffffffe, 0x00000000, 0xfffffffd, 0xffffffff, 0xfffeffff, 0x00000000,
    -  0xfffefffe, 0xffffffff, 0xffefffff, 0x00000000, 0xffeffffe, 0xffffffff,
    -  0xa9cb1d23, 0x48892a0a, 0x7fffffff, 0x00000000, 0x7fffffff, 0x00000000,
    -  0x48892a09, 0xa9cb1d25, 0x000fffff, 0x00000001, 0x000fffff, 0x00000000,
    -  0x0000ffff, 0x00000001, 0x0000ffff, 0x00000000, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xffffffff, 0x01000001, 0xffffffff, 0x01000000,
    -  0xffffffff, 0x00010001, 0xffffffff, 0x00010000, 0xffffffff, 0x00008001,
    -  0xffffffff, 0x00008000, 0xffffffff, 0x00000002, 0xffffffff, 0x00000001,
    -  0xffffffff, 0x00000000, 0xfffffffe, 0xffffffff, 0xfffffffe, 0xfffffffe,
    -  0xfffffffe, 0xffff8001, 0xfffffffe, 0xffff8000, 0xfffffffe, 0xffff0001,
    -  0xfffffffe, 0xffff0000, 0xfffffffe, 0xff000001, 0xfffffffe, 0xff000000,
    -  0xfffffffe, 0xa9cb1d25, 0xfffffffe, 0x48892a0b, 0xfffffffe, 0x00000001,
    -  0xfffffffe, 0x00000000, 0xfffeffff, 0x00000001, 0xfffeffff, 0x00000000,
    -  0xffefffff, 0x00000001, 0xffefffff, 0x00000000, 0xa9cb1d23, 0x48892a0b,
    -  0x7fffffff, 0x00000001, 0x7fffffff, 0xfeffffff, 0x48892a0a, 0xa8cb1d24,
    -  0x000fffff, 0xff000000, 0x000fffff, 0xfeffffff, 0x0000ffff, 0xff000000,
    -  0x0000ffff, 0xfeffffff, 0x00000000, 0xff000000, 0x00000000, 0xfeffffff,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xff010000,
    -  0xffffffff, 0xff00ffff, 0xffffffff, 0xff008000, 0xffffffff, 0xff007fff,
    -  0xffffffff, 0xff000001, 0xffffffff, 0xff000000, 0xffffffff, 0xfeffffff,
    -  0xffffffff, 0xfefffffe, 0xffffffff, 0xfefffffd, 0xffffffff, 0xfeff8000,
    -  0xffffffff, 0xfeff7fff, 0xffffffff, 0xfeff0000, 0xffffffff, 0xfefeffff,
    -  0xffffffff, 0xfe000000, 0xffffffff, 0xfdffffff, 0xffffffff, 0xa8cb1d24,
    -  0xffffffff, 0x47892a0a, 0xfffffffe, 0xff000000, 0xfffffffe, 0xfeffffff,
    -  0xfffeffff, 0xff000000, 0xfffeffff, 0xfeffffff, 0xffefffff, 0xff000000,
    -  0xffefffff, 0xfeffffff, 0xa9cb1d24, 0x47892a0a, 0x7fffffff, 0xff000000,
    -  0x7fffffff, 0xff000000, 0x48892a0a, 0xa8cb1d25, 0x000fffff, 0xff000001,
    -  0x000fffff, 0xff000000, 0x0000ffff, 0xff000001, 0x0000ffff, 0xff000000,
    -  0x00000000, 0xff000001, 0x00000000, 0xff000000, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xffffffff, 0xff010001, 0xffffffff, 0xff010000,
    -  0xffffffff, 0xff008001, 0xffffffff, 0xff008000, 0xffffffff, 0xff000002,
    -  0xffffffff, 0xff000001, 0xffffffff, 0xff000000, 0xffffffff, 0xfeffffff,
    -  0xffffffff, 0xfefffffe, 0xffffffff, 0xfeff8001, 0xffffffff, 0xfeff8000,
    -  0xffffffff, 0xfeff0001, 0xffffffff, 0xfeff0000, 0xffffffff, 0xfe000001,
    -  0xffffffff, 0xfe000000, 0xffffffff, 0xa8cb1d25, 0xffffffff, 0x47892a0b,
    -  0xfffffffe, 0xff000001, 0xfffffffe, 0xff000000, 0xfffeffff, 0xff000001,
    -  0xfffeffff, 0xff000000, 0xffefffff, 0xff000001, 0xffefffff, 0xff000000,
    -  0xa9cb1d24, 0x47892a0b, 0x7fffffff, 0xff000001, 0x7fffffff, 0xfffeffff,
    -  0x48892a0a, 0xa9ca1d24, 0x000fffff, 0xffff0000, 0x000fffff, 0xfffeffff,
    -  0x0000ffff, 0xffff0000, 0x0000ffff, 0xfffeffff, 0x00000000, 0xffff0000,
    -  0x00000000, 0xfffeffff, 0x00000000, 0x00ff0000, 0x00000000, 0x00feffff,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff8000,
    -  0xffffffff, 0xffff7fff, 0xffffffff, 0xffff0001, 0xffffffff, 0xffff0000,
    -  0xffffffff, 0xfffeffff, 0xffffffff, 0xfffefffe, 0xffffffff, 0xfffefffd,
    -  0xffffffff, 0xfffe8000, 0xffffffff, 0xfffe7fff, 0xffffffff, 0xfffe0000,
    -  0xffffffff, 0xfffdffff, 0xffffffff, 0xfeff0000, 0xffffffff, 0xfefeffff,
    -  0xffffffff, 0xa9ca1d24, 0xffffffff, 0x48882a0a, 0xfffffffe, 0xffff0000,
    -  0xfffffffe, 0xfffeffff, 0xfffeffff, 0xffff0000, 0xfffeffff, 0xfffeffff,
    -  0xffefffff, 0xffff0000, 0xffefffff, 0xfffeffff, 0xa9cb1d24, 0x48882a0a,
    -  0x7fffffff, 0xffff0000, 0x7fffffff, 0xffff0000, 0x48892a0a, 0xa9ca1d25,
    -  0x000fffff, 0xffff0001, 0x000fffff, 0xffff0000, 0x0000ffff, 0xffff0001,
    -  0x0000ffff, 0xffff0000, 0x00000000, 0xffff0001, 0x00000000, 0xffff0000,
    -  0x00000000, 0x00ff0001, 0x00000000, 0x00ff0000, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffff8001, 0xffffffff, 0xffff8000,
    -  0xffffffff, 0xffff0002, 0xffffffff, 0xffff0001, 0xffffffff, 0xffff0000,
    -  0xffffffff, 0xfffeffff, 0xffffffff, 0xfffefffe, 0xffffffff, 0xfffe8001,
    -  0xffffffff, 0xfffe8000, 0xffffffff, 0xfffe0001, 0xffffffff, 0xfffe0000,
    -  0xffffffff, 0xfeff0001, 0xffffffff, 0xfeff0000, 0xffffffff, 0xa9ca1d25,
    -  0xffffffff, 0x48882a0b, 0xfffffffe, 0xffff0001, 0xfffffffe, 0xffff0000,
    -  0xfffeffff, 0xffff0001, 0xfffeffff, 0xffff0000, 0xffefffff, 0xffff0001,
    -  0xffefffff, 0xffff0000, 0xa9cb1d24, 0x48882a0b, 0x7fffffff, 0xffff0001,
    -  0x7fffffff, 0xffff7fff, 0x48892a0a, 0xa9ca9d24, 0x000fffff, 0xffff8000,
    -  0x000fffff, 0xffff7fff, 0x0000ffff, 0xffff8000, 0x0000ffff, 0xffff7fff,
    -  0x00000000, 0xffff8000, 0x00000000, 0xffff7fff, 0x00000000, 0x00ff8000,
    -  0x00000000, 0x00ff7fff, 0x00000000, 0x00008000, 0x00000000, 0x00007fff,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff8001,
    -  0xffffffff, 0xffff8000, 0xffffffff, 0xffff7fff, 0xffffffff, 0xffff7ffe,
    -  0xffffffff, 0xffff7ffd, 0xffffffff, 0xffff0000, 0xffffffff, 0xfffeffff,
    -  0xffffffff, 0xfffe8000, 0xffffffff, 0xfffe7fff, 0xffffffff, 0xfeff8000,
    -  0xffffffff, 0xfeff7fff, 0xffffffff, 0xa9ca9d24, 0xffffffff, 0x4888aa0a,
    -  0xfffffffe, 0xffff8000, 0xfffffffe, 0xffff7fff, 0xfffeffff, 0xffff8000,
    -  0xfffeffff, 0xffff7fff, 0xffefffff, 0xffff8000, 0xffefffff, 0xffff7fff,
    -  0xa9cb1d24, 0x4888aa0a, 0x7fffffff, 0xffff8000, 0x7fffffff, 0xffff8000,
    -  0x48892a0a, 0xa9ca9d25, 0x000fffff, 0xffff8001, 0x000fffff, 0xffff8000,
    -  0x0000ffff, 0xffff8001, 0x0000ffff, 0xffff8000, 0x00000000, 0xffff8001,
    -  0x00000000, 0xffff8000, 0x00000000, 0x00ff8001, 0x00000000, 0x00ff8000,
    -  0x00000000, 0x00008001, 0x00000000, 0x00008000, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffff8002, 0xffffffff, 0xffff8001,
    -  0xffffffff, 0xffff8000, 0xffffffff, 0xffff7fff, 0xffffffff, 0xffff7ffe,
    -  0xffffffff, 0xffff0001, 0xffffffff, 0xffff0000, 0xffffffff, 0xfffe8001,
    -  0xffffffff, 0xfffe8000, 0xffffffff, 0xfeff8001, 0xffffffff, 0xfeff8000,
    -  0xffffffff, 0xa9ca9d25, 0xffffffff, 0x4888aa0b, 0xfffffffe, 0xffff8001,
    -  0xfffffffe, 0xffff8000, 0xfffeffff, 0xffff8001, 0xfffeffff, 0xffff8000,
    -  0xffefffff, 0xffff8001, 0xffefffff, 0xffff8000, 0xa9cb1d24, 0x4888aa0b,
    -  0x7fffffff, 0xffff8001, 0x7fffffff, 0xfffffffe, 0x48892a0a, 0xa9cb1d23,
    -  0x000fffff, 0xffffffff, 0x000fffff, 0xfffffffe, 0x0000ffff, 0xffffffff,
    -  0x0000ffff, 0xfffffffe, 0x00000000, 0xffffffff, 0x00000000, 0xfffffffe,
    -  0x00000000, 0x00ffffff, 0x00000000, 0x00fffffe, 0x00000000, 0x0000ffff,
    -  0x00000000, 0x0000fffe, 0x00000000, 0x00007fff, 0x00000000, 0x00007ffe,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffffe,
    -  0xffffffff, 0xfffffffd, 0xffffffff, 0xfffffffc, 0xffffffff, 0xffff7fff,
    -  0xffffffff, 0xffff7ffe, 0xffffffff, 0xfffeffff, 0xffffffff, 0xfffefffe,
    -  0xffffffff, 0xfeffffff, 0xffffffff, 0xfefffffe, 0xffffffff, 0xa9cb1d23,
    -  0xffffffff, 0x48892a09, 0xfffffffe, 0xffffffff, 0xfffffffe, 0xfffffffe,
    -  0xfffeffff, 0xffffffff, 0xfffeffff, 0xfffffffe, 0xffefffff, 0xffffffff,
    -  0xffefffff, 0xfffffffe, 0xa9cb1d24, 0x48892a09, 0x7fffffff, 0xffffffff,
    -  0x7fffffff, 0xffffffff, 0x48892a0a, 0xa9cb1d24, 0x00100000, 0x00000000,
    -  0x000fffff, 0xffffffff, 0x00010000, 0x00000000, 0x0000ffff, 0xffffffff,
    -  0x00000001, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0x01000000,
    -  0x00000000, 0x00ffffff, 0x00000000, 0x00010000, 0x00000000, 0x0000ffff,
    -  0x00000000, 0x00008000, 0x00000000, 0x00007fff, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffffe,
    -  0xffffffff, 0xfffffffd, 0xffffffff, 0xffff8000, 0xffffffff, 0xffff7fff,
    -  0xffffffff, 0xffff0000, 0xffffffff, 0xfffeffff, 0xffffffff, 0xff000000,
    -  0xffffffff, 0xfeffffff, 0xffffffff, 0xa9cb1d24, 0xffffffff, 0x48892a0a,
    -  0xffffffff, 0x00000000, 0xfffffffe, 0xffffffff, 0xffff0000, 0x00000000,
    -  0xfffeffff, 0xffffffff, 0xfff00000, 0x00000000, 0xffefffff, 0xffffffff,
    -  0xa9cb1d24, 0x48892a0a, 0x80000000, 0x00000000, 0x80000000, 0x00000000,
    -  0x48892a0a, 0xa9cb1d25, 0x00100000, 0x00000001, 0x00100000, 0x00000000,
    -  0x00010000, 0x00000001, 0x00010000, 0x00000000, 0x00000001, 0x00000001,
    -  0x00000001, 0x00000000, 0x00000000, 0x01000001, 0x00000000, 0x01000000,
    -  0x00000000, 0x00010001, 0x00000000, 0x00010000, 0x00000000, 0x00008001,
    -  0x00000000, 0x00008000, 0x00000000, 0x00000002, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffffe,
    -  0xffffffff, 0xffff8001, 0xffffffff, 0xffff8000, 0xffffffff, 0xffff0001,
    -  0xffffffff, 0xffff0000, 0xffffffff, 0xff000001, 0xffffffff, 0xff000000,
    -  0xffffffff, 0xa9cb1d25, 0xffffffff, 0x48892a0b, 0xffffffff, 0x00000001,
    -  0xffffffff, 0x00000000, 0xffff0000, 0x00000001, 0xffff0000, 0x00000000,
    -  0xfff00000, 0x00000001, 0xfff00000, 0x00000000, 0xa9cb1d24, 0x48892a0b,
    -  0x80000000, 0x00000001, 0x80000000, 0x00000001, 0x48892a0a, 0xa9cb1d26,
    -  0x00100000, 0x00000002, 0x00100000, 0x00000001, 0x00010000, 0x00000002,
    -  0x00010000, 0x00000001, 0x00000001, 0x00000002, 0x00000001, 0x00000001,
    -  0x00000000, 0x01000002, 0x00000000, 0x01000001, 0x00000000, 0x00010002,
    -  0x00000000, 0x00010001, 0x00000000, 0x00008002, 0x00000000, 0x00008001,
    -  0x00000000, 0x00000003, 0x00000000, 0x00000002, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff8002,
    -  0xffffffff, 0xffff8001, 0xffffffff, 0xffff0002, 0xffffffff, 0xffff0001,
    -  0xffffffff, 0xff000002, 0xffffffff, 0xff000001, 0xffffffff, 0xa9cb1d26,
    -  0xffffffff, 0x48892a0c, 0xffffffff, 0x00000002, 0xffffffff, 0x00000001,
    -  0xffff0000, 0x00000002, 0xffff0000, 0x00000001, 0xfff00000, 0x00000002,
    -  0xfff00000, 0x00000001, 0xa9cb1d24, 0x48892a0c, 0x80000000, 0x00000002,
    -  0x80000000, 0x00000002, 0x48892a0a, 0xa9cb1d27, 0x00100000, 0x00000003,
    -  0x00100000, 0x00000002, 0x00010000, 0x00000003, 0x00010000, 0x00000002,
    -  0x00000001, 0x00000003, 0x00000001, 0x00000002, 0x00000000, 0x01000003,
    -  0x00000000, 0x01000002, 0x00000000, 0x00010003, 0x00000000, 0x00010002,
    -  0x00000000, 0x00008003, 0x00000000, 0x00008002, 0x00000000, 0x00000004,
    -  0x00000000, 0x00000003, 0x00000000, 0x00000002, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffff8003, 0xffffffff, 0xffff8002,
    -  0xffffffff, 0xffff0003, 0xffffffff, 0xffff0002, 0xffffffff, 0xff000003,
    -  0xffffffff, 0xff000002, 0xffffffff, 0xa9cb1d27, 0xffffffff, 0x48892a0d,
    -  0xffffffff, 0x00000003, 0xffffffff, 0x00000002, 0xffff0000, 0x00000003,
    -  0xffff0000, 0x00000002, 0xfff00000, 0x00000003, 0xfff00000, 0x00000002,
    -  0xa9cb1d24, 0x48892a0d, 0x80000000, 0x00000003, 0x80000000, 0x00007fff,
    -  0x48892a0a, 0xa9cb9d24, 0x00100000, 0x00008000, 0x00100000, 0x00007fff,
    -  0x00010000, 0x00008000, 0x00010000, 0x00007fff, 0x00000001, 0x00008000,
    -  0x00000001, 0x00007fff, 0x00000000, 0x01008000, 0x00000000, 0x01007fff,
    -  0x00000000, 0x00018000, 0x00000000, 0x00017fff, 0x00000000, 0x00010000,
    -  0x00000000, 0x0000ffff, 0x00000000, 0x00008001, 0x00000000, 0x00008000,
    -  0x00000000, 0x00007fff, 0x00000000, 0x00007ffe, 0x00000000, 0x00007ffd,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff8000,
    -  0xffffffff, 0xffff7fff, 0xffffffff, 0xff008000, 0xffffffff, 0xff007fff,
    -  0xffffffff, 0xa9cb9d24, 0xffffffff, 0x4889aa0a, 0xffffffff, 0x00008000,
    -  0xffffffff, 0x00007fff, 0xffff0000, 0x00008000, 0xffff0000, 0x00007fff,
    -  0xfff00000, 0x00008000, 0xfff00000, 0x00007fff, 0xa9cb1d24, 0x4889aa0a,
    -  0x80000000, 0x00008000, 0x80000000, 0x00008000, 0x48892a0a, 0xa9cb9d25,
    -  0x00100000, 0x00008001, 0x00100000, 0x00008000, 0x00010000, 0x00008001,
    -  0x00010000, 0x00008000, 0x00000001, 0x00008001, 0x00000001, 0x00008000,
    -  0x00000000, 0x01008001, 0x00000000, 0x01008000, 0x00000000, 0x00018001,
    -  0x00000000, 0x00018000, 0x00000000, 0x00010001, 0x00000000, 0x00010000,
    -  0x00000000, 0x00008002, 0x00000000, 0x00008001, 0x00000000, 0x00008000,
    -  0x00000000, 0x00007fff, 0x00000000, 0x00007ffe, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffff8001, 0xffffffff, 0xffff8000,
    -  0xffffffff, 0xff008001, 0xffffffff, 0xff008000, 0xffffffff, 0xa9cb9d25,
    -  0xffffffff, 0x4889aa0b, 0xffffffff, 0x00008001, 0xffffffff, 0x00008000,
    -  0xffff0000, 0x00008001, 0xffff0000, 0x00008000, 0xfff00000, 0x00008001,
    -  0xfff00000, 0x00008000, 0xa9cb1d24, 0x4889aa0b, 0x80000000, 0x00008001,
    -  0x80000000, 0x0000ffff, 0x48892a0a, 0xa9cc1d24, 0x00100000, 0x00010000,
    -  0x00100000, 0x0000ffff, 0x00010000, 0x00010000, 0x00010000, 0x0000ffff,
    -  0x00000001, 0x00010000, 0x00000001, 0x0000ffff, 0x00000000, 0x01010000,
    -  0x00000000, 0x0100ffff, 0x00000000, 0x00020000, 0x00000000, 0x0001ffff,
    -  0x00000000, 0x00018000, 0x00000000, 0x00017fff, 0x00000000, 0x00010001,
    -  0x00000000, 0x00010000, 0x00000000, 0x0000ffff, 0x00000000, 0x0000fffe,
    -  0x00000000, 0x0000fffd, 0x00000000, 0x00008000, 0x00000000, 0x00007fff,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xff010000,
    -  0xffffffff, 0xff00ffff, 0xffffffff, 0xa9cc1d24, 0xffffffff, 0x488a2a0a,
    -  0xffffffff, 0x00010000, 0xffffffff, 0x0000ffff, 0xffff0000, 0x00010000,
    -  0xffff0000, 0x0000ffff, 0xfff00000, 0x00010000, 0xfff00000, 0x0000ffff,
    -  0xa9cb1d24, 0x488a2a0a, 0x80000000, 0x00010000, 0x80000000, 0x00010000,
    -  0x48892a0a, 0xa9cc1d25, 0x00100000, 0x00010001, 0x00100000, 0x00010000,
    -  0x00010000, 0x00010001, 0x00010000, 0x00010000, 0x00000001, 0x00010001,
    -  0x00000001, 0x00010000, 0x00000000, 0x01010001, 0x00000000, 0x01010000,
    -  0x00000000, 0x00020001, 0x00000000, 0x00020000, 0x00000000, 0x00018001,
    -  0x00000000, 0x00018000, 0x00000000, 0x00010002, 0x00000000, 0x00010001,
    -  0x00000000, 0x00010000, 0x00000000, 0x0000ffff, 0x00000000, 0x0000fffe,
    -  0x00000000, 0x00008001, 0x00000000, 0x00008000, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xffffffff, 0xff010001, 0xffffffff, 0xff010000,
    -  0xffffffff, 0xa9cc1d25, 0xffffffff, 0x488a2a0b, 0xffffffff, 0x00010001,
    -  0xffffffff, 0x00010000, 0xffff0000, 0x00010001, 0xffff0000, 0x00010000,
    -  0xfff00000, 0x00010001, 0xfff00000, 0x00010000, 0xa9cb1d24, 0x488a2a0b,
    -  0x80000000, 0x00010001, 0x80000000, 0x00ffffff, 0x48892a0a, 0xaacb1d24,
    -  0x00100000, 0x01000000, 0x00100000, 0x00ffffff, 0x00010000, 0x01000000,
    -  0x00010000, 0x00ffffff, 0x00000001, 0x01000000, 0x00000001, 0x00ffffff,
    -  0x00000000, 0x02000000, 0x00000000, 0x01ffffff, 0x00000000, 0x01010000,
    -  0x00000000, 0x0100ffff, 0x00000000, 0x01008000, 0x00000000, 0x01007fff,
    -  0x00000000, 0x01000001, 0x00000000, 0x01000000, 0x00000000, 0x00ffffff,
    -  0x00000000, 0x00fffffe, 0x00000000, 0x00fffffd, 0x00000000, 0x00ff8000,
    -  0x00000000, 0x00ff7fff, 0x00000000, 0x00ff0000, 0x00000000, 0x00feffff,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xaacb1d24,
    -  0xffffffff, 0x49892a0a, 0xffffffff, 0x01000000, 0xffffffff, 0x00ffffff,
    -  0xffff0000, 0x01000000, 0xffff0000, 0x00ffffff, 0xfff00000, 0x01000000,
    -  0xfff00000, 0x00ffffff, 0xa9cb1d24, 0x49892a0a, 0x80000000, 0x01000000,
    -  0x80000000, 0x01000000, 0x48892a0a, 0xaacb1d25, 0x00100000, 0x01000001,
    -  0x00100000, 0x01000000, 0x00010000, 0x01000001, 0x00010000, 0x01000000,
    -  0x00000001, 0x01000001, 0x00000001, 0x01000000, 0x00000000, 0x02000001,
    -  0x00000000, 0x02000000, 0x00000000, 0x01010001, 0x00000000, 0x01010000,
    -  0x00000000, 0x01008001, 0x00000000, 0x01008000, 0x00000000, 0x01000002,
    -  0x00000000, 0x01000001, 0x00000000, 0x01000000, 0x00000000, 0x00ffffff,
    -  0x00000000, 0x00fffffe, 0x00000000, 0x00ff8001, 0x00000000, 0x00ff8000,
    -  0x00000000, 0x00ff0001, 0x00000000, 0x00ff0000, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xffffffff, 0xaacb1d25, 0xffffffff, 0x49892a0b,
    -  0xffffffff, 0x01000001, 0xffffffff, 0x01000000, 0xffff0000, 0x01000001,
    -  0xffff0000, 0x01000000, 0xfff00000, 0x01000001, 0xfff00000, 0x01000000,
    -  0xa9cb1d24, 0x49892a0b, 0x80000000, 0x01000001, 0x80000000, 0x5634e2db,
    -  0x48892a0b, 0x00000000, 0x00100000, 0x5634e2dc, 0x00100000, 0x5634e2db,
    -  0x00010000, 0x5634e2dc, 0x00010000, 0x5634e2db, 0x00000001, 0x5634e2dc,
    -  0x00000001, 0x5634e2db, 0x00000000, 0x5734e2dc, 0x00000000, 0x5734e2db,
    -  0x00000000, 0x5635e2dc, 0x00000000, 0x5635e2db, 0x00000000, 0x563562dc,
    -  0x00000000, 0x563562db, 0x00000000, 0x5634e2dd, 0x00000000, 0x5634e2dc,
    -  0x00000000, 0x5634e2db, 0x00000000, 0x5634e2da, 0x00000000, 0x5634e2d9,
    -  0x00000000, 0x563462dc, 0x00000000, 0x563462db, 0x00000000, 0x5633e2dc,
    -  0x00000000, 0x5633e2db, 0x00000000, 0x5534e2dc, 0x00000000, 0x5534e2db,
    -  0x00000000, 0x00000000, 0xffffffff, 0x9ebe0ce6, 0xffffffff, 0x5634e2dc,
    -  0xffffffff, 0x5634e2db, 0xffff0000, 0x5634e2dc, 0xffff0000, 0x5634e2db,
    -  0xfff00000, 0x5634e2dc, 0xfff00000, 0x5634e2db, 0xa9cb1d24, 0x9ebe0ce6,
    -  0x80000000, 0x5634e2dc, 0x80000000, 0xb776d5f5, 0x48892a0b, 0x6141f31a,
    -  0x00100000, 0xb776d5f6, 0x00100000, 0xb776d5f5, 0x00010000, 0xb776d5f6,
    -  0x00010000, 0xb776d5f5, 0x00000001, 0xb776d5f6, 0x00000001, 0xb776d5f5,
    -  0x00000000, 0xb876d5f6, 0x00000000, 0xb876d5f5, 0x00000000, 0xb777d5f6,
    -  0x00000000, 0xb777d5f5, 0x00000000, 0xb77755f6, 0x00000000, 0xb77755f5,
    -  0x00000000, 0xb776d5f7, 0x00000000, 0xb776d5f6, 0x00000000, 0xb776d5f5,
    -  0x00000000, 0xb776d5f4, 0x00000000, 0xb776d5f3, 0x00000000, 0xb77655f6,
    -  0x00000000, 0xb77655f5, 0x00000000, 0xb775d5f6, 0x00000000, 0xb775d5f5,
    -  0x00000000, 0xb676d5f6, 0x00000000, 0xb676d5f5, 0x00000000, 0x6141f31a,
    -  0x00000000, 0x00000000, 0xffffffff, 0xb776d5f6, 0xffffffff, 0xb776d5f5,
    -  0xffff0000, 0xb776d5f6, 0xffff0000, 0xb776d5f5, 0xfff00000, 0xb776d5f6,
    -  0xfff00000, 0xb776d5f5, 0xa9cb1d25, 0x00000000, 0x80000000, 0xb776d5f6,
    -  0x80000000, 0xffffffff, 0x48892a0b, 0xa9cb1d24, 0x00100001, 0x00000000,
    -  0x00100000, 0xffffffff, 0x00010001, 0x00000000, 0x00010000, 0xffffffff,
    -  0x00000002, 0x00000000, 0x00000001, 0xffffffff, 0x00000001, 0x01000000,
    -  0x00000001, 0x00ffffff, 0x00000001, 0x00010000, 0x00000001, 0x0000ffff,
    -  0x00000001, 0x00008000, 0x00000001, 0x00007fff, 0x00000001, 0x00000001,
    -  0x00000001, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0xfffffffe,
    -  0x00000000, 0xfffffffd, 0x00000000, 0xffff8000, 0x00000000, 0xffff7fff,
    -  0x00000000, 0xffff0000, 0x00000000, 0xfffeffff, 0x00000000, 0xff000000,
    -  0x00000000, 0xfeffffff, 0x00000000, 0xa9cb1d24, 0x00000000, 0x48892a0a,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffff0001, 0x00000000,
    -  0xffff0000, 0xffffffff, 0xfff00001, 0x00000000, 0xfff00000, 0xffffffff,
    -  0xa9cb1d25, 0x48892a0a, 0x80000001, 0x00000000, 0x80000001, 0x00000000,
    -  0x48892a0b, 0xa9cb1d25, 0x00100001, 0x00000001, 0x00100001, 0x00000000,
    -  0x00010001, 0x00000001, 0x00010001, 0x00000000, 0x00000002, 0x00000001,
    -  0x00000002, 0x00000000, 0x00000001, 0x01000001, 0x00000001, 0x01000000,
    -  0x00000001, 0x00010001, 0x00000001, 0x00010000, 0x00000001, 0x00008001,
    -  0x00000001, 0x00008000, 0x00000001, 0x00000002, 0x00000001, 0x00000001,
    -  0x00000001, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0xfffffffe,
    -  0x00000000, 0xffff8001, 0x00000000, 0xffff8000, 0x00000000, 0xffff0001,
    -  0x00000000, 0xffff0000, 0x00000000, 0xff000001, 0x00000000, 0xff000000,
    -  0x00000000, 0xa9cb1d25, 0x00000000, 0x48892a0b, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xffff0001, 0x00000001, 0xffff0001, 0x00000000,
    -  0xfff00001, 0x00000001, 0xfff00001, 0x00000000, 0xa9cb1d25, 0x48892a0b,
    -  0x80000001, 0x00000001, 0x8000ffff, 0xffffffff, 0x488a2a0a, 0xa9cb1d24,
    -  0x00110000, 0x00000000, 0x0010ffff, 0xffffffff, 0x00020000, 0x00000000,
    -  0x0001ffff, 0xffffffff, 0x00010001, 0x00000000, 0x00010000, 0xffffffff,
    -  0x00010000, 0x01000000, 0x00010000, 0x00ffffff, 0x00010000, 0x00010000,
    -  0x00010000, 0x0000ffff, 0x00010000, 0x00008000, 0x00010000, 0x00007fff,
    -  0x00010000, 0x00000001, 0x00010000, 0x00000000, 0x0000ffff, 0xffffffff,
    -  0x0000ffff, 0xfffffffe, 0x0000ffff, 0xfffffffd, 0x0000ffff, 0xffff8000,
    -  0x0000ffff, 0xffff7fff, 0x0000ffff, 0xffff0000, 0x0000ffff, 0xfffeffff,
    -  0x0000ffff, 0xff000000, 0x0000ffff, 0xfeffffff, 0x0000ffff, 0xa9cb1d24,
    -  0x0000ffff, 0x48892a0a, 0x0000ffff, 0x00000000, 0x0000fffe, 0xffffffff,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xfff10000, 0x00000000,
    -  0xfff0ffff, 0xffffffff, 0xa9cc1d24, 0x48892a0a, 0x80010000, 0x00000000,
    -  0x80010000, 0x00000000, 0x488a2a0a, 0xa9cb1d25, 0x00110000, 0x00000001,
    -  0x00110000, 0x00000000, 0x00020000, 0x00000001, 0x00020000, 0x00000000,
    -  0x00010001, 0x00000001, 0x00010001, 0x00000000, 0x00010000, 0x01000001,
    -  0x00010000, 0x01000000, 0x00010000, 0x00010001, 0x00010000, 0x00010000,
    -  0x00010000, 0x00008001, 0x00010000, 0x00008000, 0x00010000, 0x00000002,
    -  0x00010000, 0x00000001, 0x00010000, 0x00000000, 0x0000ffff, 0xffffffff,
    -  0x0000ffff, 0xfffffffe, 0x0000ffff, 0xffff8001, 0x0000ffff, 0xffff8000,
    -  0x0000ffff, 0xffff0001, 0x0000ffff, 0xffff0000, 0x0000ffff, 0xff000001,
    -  0x0000ffff, 0xff000000, 0x0000ffff, 0xa9cb1d25, 0x0000ffff, 0x48892a0b,
    -  0x0000ffff, 0x00000001, 0x0000ffff, 0x00000000, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xfff10000, 0x00000001, 0xfff10000, 0x00000000,
    -  0xa9cc1d24, 0x48892a0b, 0x80010000, 0x00000001, 0x800fffff, 0xffffffff,
    -  0x48992a0a, 0xa9cb1d24, 0x00200000, 0x00000000, 0x001fffff, 0xffffffff,
    -  0x00110000, 0x00000000, 0x0010ffff, 0xffffffff, 0x00100001, 0x00000000,
    -  0x00100000, 0xffffffff, 0x00100000, 0x01000000, 0x00100000, 0x00ffffff,
    -  0x00100000, 0x00010000, 0x00100000, 0x0000ffff, 0x00100000, 0x00008000,
    -  0x00100000, 0x00007fff, 0x00100000, 0x00000001, 0x00100000, 0x00000000,
    -  0x000fffff, 0xffffffff, 0x000fffff, 0xfffffffe, 0x000fffff, 0xfffffffd,
    -  0x000fffff, 0xffff8000, 0x000fffff, 0xffff7fff, 0x000fffff, 0xffff0000,
    -  0x000fffff, 0xfffeffff, 0x000fffff, 0xff000000, 0x000fffff, 0xfeffffff,
    -  0x000fffff, 0xa9cb1d24, 0x000fffff, 0x48892a0a, 0x000fffff, 0x00000000,
    -  0x000ffffe, 0xffffffff, 0x000f0000, 0x00000000, 0x000effff, 0xffffffff,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xa9db1d24, 0x48892a0a,
    -  0x80100000, 0x00000000, 0x80100000, 0x00000000, 0x48992a0a, 0xa9cb1d25,
    -  0x00200000, 0x00000001, 0x00200000, 0x00000000, 0x00110000, 0x00000001,
    -  0x00110000, 0x00000000, 0x00100001, 0x00000001, 0x00100001, 0x00000000,
    -  0x00100000, 0x01000001, 0x00100000, 0x01000000, 0x00100000, 0x00010001,
    -  0x00100000, 0x00010000, 0x00100000, 0x00008001, 0x00100000, 0x00008000,
    -  0x00100000, 0x00000002, 0x00100000, 0x00000001, 0x00100000, 0x00000000,
    -  0x000fffff, 0xffffffff, 0x000fffff, 0xfffffffe, 0x000fffff, 0xffff8001,
    -  0x000fffff, 0xffff8000, 0x000fffff, 0xffff0001, 0x000fffff, 0xffff0000,
    -  0x000fffff, 0xff000001, 0x000fffff, 0xff000000, 0x000fffff, 0xa9cb1d25,
    -  0x000fffff, 0x48892a0b, 0x000fffff, 0x00000001, 0x000fffff, 0x00000000,
    -  0x000f0000, 0x00000001, 0x000f0000, 0x00000000, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xa9db1d24, 0x48892a0b, 0x80100000, 0x00000001,
    -  0xd634e2db, 0xb776d5f5, 0x9ebe0ce6, 0x6141f31a, 0x5644e2db, 0xb776d5f6,
    -  0x5644e2db, 0xb776d5f5, 0x5635e2db, 0xb776d5f6, 0x5635e2db, 0xb776d5f5,
    -  0x5634e2dc, 0xb776d5f6, 0x5634e2dc, 0xb776d5f5, 0x5634e2db, 0xb876d5f6,
    -  0x5634e2db, 0xb876d5f5, 0x5634e2db, 0xb777d5f6, 0x5634e2db, 0xb777d5f5,
    -  0x5634e2db, 0xb77755f6, 0x5634e2db, 0xb77755f5, 0x5634e2db, 0xb776d5f7,
    -  0x5634e2db, 0xb776d5f6, 0x5634e2db, 0xb776d5f5, 0x5634e2db, 0xb776d5f4,
    -  0x5634e2db, 0xb776d5f3, 0x5634e2db, 0xb77655f6, 0x5634e2db, 0xb77655f5,
    -  0x5634e2db, 0xb775d5f6, 0x5634e2db, 0xb775d5f5, 0x5634e2db, 0xb676d5f6,
    -  0x5634e2db, 0xb676d5f5, 0x5634e2db, 0x6141f31a, 0x5634e2db, 0x00000000,
    -  0x5634e2da, 0xb776d5f6, 0x5634e2da, 0xb776d5f5, 0x5633e2db, 0xb776d5f6,
    -  0x5633e2db, 0xb776d5f5, 0x5624e2db, 0xb776d5f6, 0x5624e2db, 0xb776d5f5,
    -  0x00000000, 0x00000000, 0xd634e2db, 0xb776d5f6, 0xffffffff, 0xffffffff,
    -  0xc8892a0a, 0xa9cb1d24, 0x80100000, 0x00000000, 0x800fffff, 0xffffffff,
    -  0x80010000, 0x00000000, 0x8000ffff, 0xffffffff, 0x80000001, 0x00000000,
    -  0x80000000, 0xffffffff, 0x80000000, 0x01000000, 0x80000000, 0x00ffffff,
    -  0x80000000, 0x00010000, 0x80000000, 0x0000ffff, 0x80000000, 0x00008000,
    -  0x80000000, 0x00007fff, 0x80000000, 0x00000001, 0x80000000, 0x00000000,
    -  0x7fffffff, 0xffffffff, 0x7fffffff, 0xfffffffe, 0x7fffffff, 0xfffffffd,
    -  0x7fffffff, 0xffff8000, 0x7fffffff, 0xffff7fff, 0x7fffffff, 0xffff0000,
    -  0x7fffffff, 0xfffeffff, 0x7fffffff, 0xff000000, 0x7fffffff, 0xfeffffff,
    -  0x7fffffff, 0xa9cb1d24, 0x7fffffff, 0x48892a0a, 0x7fffffff, 0x00000000,
    -  0x7ffffffe, 0xffffffff, 0x7fff0000, 0x00000000, 0x7ffeffff, 0xffffffff,
    -  0x7ff00000, 0x00000000, 0x7fefffff, 0xffffffff, 0x29cb1d24, 0x48892a0a,
    -  0x00000000, 0x00000000
    -];
    -toInt32s(TEST_SUB_BITS);
    -
    -var TEST_MUL_BITS = [
    -  0x80000000, 0x00000000, 0x80000000, 0x00000000, 0x1ad92a0a, 0xa9cb1d25,
    -  0x00000000, 0x00000000, 0xd2500000, 0x00000000, 0x00100000, 0x00000000,
    -  0x80000000, 0x00000000, 0x65ae2a0a, 0xa9cb1d25, 0x00110000, 0x00000001,
    -  0x00100000, 0x00000000, 0x00000000, 0x00000000, 0x1d250000, 0x00000000,
    -  0x00010000, 0x00000000, 0x00000000, 0x00000000, 0x00010000, 0x00000000,
    -  0x80000000, 0x00000000, 0xf254472f, 0xa9cb1d25, 0x00100001, 0x00000001,
    -  0x00100000, 0x00000000, 0x00010001, 0x00000001, 0x00010000, 0x00000000,
    -  0x00000000, 0x00000000, 0xa9cb1d25, 0x00000000, 0x00000001, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000001, 0x00000000, 0x80000000, 0x00000000, 0x5332f527, 0xcecb1d25,
    -  0x00100000, 0x01000001, 0x00100000, 0x00000000, 0x00010000, 0x01000001,
    -  0x00010000, 0x00000000, 0x01000001, 0x01000001, 0x01000001, 0x00000000,
    -  0x00000000, 0x00000000, 0x0aa9cb1d, 0x25000000, 0x00000000, 0x01000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x01000000, 0x00000000, 0x00000000,
    -  0x01000000, 0x01000000, 0x01000000, 0x00000000, 0x00010000, 0x01000000,
    -  0x80000000, 0x00000000, 0x7293d3d5, 0xc6f01d25, 0x00100000, 0x00010001,
    -  0x00100000, 0x00000000, 0x00010000, 0x00010001, 0x00010000, 0x00000000,
    -  0x00010001, 0x00010001, 0x00010001, 0x00000000, 0x00000100, 0x01010001,
    -  0x00000100, 0x01000000, 0x00000000, 0x00000000, 0x2a0aa9cb, 0x1d250000,
    -  0x00000000, 0x00010000, 0x00000000, 0x00000000, 0x00000000, 0x00010000,
    -  0x00000000, 0x00000000, 0x00010000, 0x00010000, 0x00010000, 0x00000000,
    -  0x00000100, 0x00010000, 0x00000100, 0x00000000, 0x00000001, 0x00010000,
    -  0x80000000, 0x00000000, 0xdd8e7ef0, 0x385d9d25, 0x00100000, 0x00008001,
    -  0x00100000, 0x00000000, 0x80010000, 0x00008001, 0x80010000, 0x00000000,
    -  0x00008001, 0x00008001, 0x00008001, 0x00000000, 0x00000080, 0x01008001,
    -  0x00000080, 0x01000000, 0x00000000, 0x80018001, 0x00000000, 0x80010000,
    -  0x00000000, 0x00000000, 0x950554e5, 0x8e928000, 0x00000000, 0x00008000,
    -  0x00000000, 0x00000000, 0x80000000, 0x00008000, 0x80000000, 0x00000000,
    -  0x00008000, 0x00008000, 0x00008000, 0x00000000, 0x00000080, 0x00008000,
    -  0x00000080, 0x00000000, 0x00000000, 0x80008000, 0x00000000, 0x80000000,
    -  0x00000000, 0x40008000, 0x00000000, 0x00000000, 0x91125415, 0x53963a4a,
    -  0x00200000, 0x00000002, 0x00200000, 0x00000000, 0x00020000, 0x00000002,
    -  0x00020000, 0x00000000, 0x00000002, 0x00000002, 0x00000002, 0x00000000,
    -  0x00000000, 0x02000002, 0x00000000, 0x02000000, 0x00000000, 0x00020002,
    -  0x00000000, 0x00020000, 0x00000000, 0x00010002, 0x00000000, 0x00010000,
    -  0x80000000, 0x00000000, 0x48892a0a, 0xa9cb1d25, 0x00100000, 0x00000001,
    -  0x00100000, 0x00000000, 0x00010000, 0x00000001, 0x00010000, 0x00000000,
    -  0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x01000001,
    -  0x00000000, 0x01000000, 0x00000000, 0x00010001, 0x00000000, 0x00010000,
    -  0x00000000, 0x00008001, 0x00000000, 0x00008000, 0x00000000, 0x00000002,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x80000000, 0x00000000, 0xb776d5f5, 0x5634e2db,
    -  0xffefffff, 0xffffffff, 0xfff00000, 0x00000000, 0xfffeffff, 0xffffffff,
    -  0xffff0000, 0x00000000, 0xfffffffe, 0xffffffff, 0xffffffff, 0x00000000,
    -  0xffffffff, 0xfeffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xfffeffff,
    -  0xffffffff, 0xffff0000, 0xffffffff, 0xffff7fff, 0xffffffff, 0xffff8000,
    -  0xffffffff, 0xfffffffe, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x6eedabea, 0xac69c5b6, 0xffdfffff, 0xfffffffe,
    -  0xffe00000, 0x00000000, 0xfffdffff, 0xfffffffe, 0xfffe0000, 0x00000000,
    -  0xfffffffd, 0xfffffffe, 0xfffffffe, 0x00000000, 0xffffffff, 0xfdfffffe,
    -  0xffffffff, 0xfe000000, 0xffffffff, 0xfffdfffe, 0xffffffff, 0xfffe0000,
    -  0xffffffff, 0xfffefffe, 0xffffffff, 0xffff0000, 0xffffffff, 0xfffffffc,
    -  0xffffffff, 0xfffffffe, 0x00000000, 0x00000000, 0x00000000, 0x00000002,
    -  0x80000000, 0x00000000, 0xb383d525, 0x1b389d25, 0x000fffff, 0xffff8001,
    -  0x00100000, 0x00000000, 0x8000ffff, 0xffff8001, 0x80010000, 0x00000000,
    -  0xffff8000, 0xffff8001, 0xffff8001, 0x00000000, 0xffffff80, 0x00ff8001,
    -  0xffffff80, 0x01000000, 0xffffffff, 0x80008001, 0xffffffff, 0x80010000,
    -  0xffffffff, 0xc0000001, 0xffffffff, 0xc0008000, 0xffffffff, 0xffff0002,
    -  0xffffffff, 0xffff8001, 0x00000000, 0x00000000, 0x00000000, 0x00007fff,
    -  0x00000000, 0x0000fffe, 0x00000000, 0x00000000, 0x6afaab1a, 0x716d8000,
    -  0xffffffff, 0xffff8000, 0x00000000, 0x00000000, 0x7fffffff, 0xffff8000,
    -  0x80000000, 0x00000000, 0xffff7fff, 0xffff8000, 0xffff8000, 0x00000000,
    -  0xffffff7f, 0xffff8000, 0xffffff80, 0x00000000, 0xffffffff, 0x7fff8000,
    -  0xffffffff, 0x80000000, 0xffffffff, 0xbfff8000, 0xffffffff, 0xc0000000,
    -  0xffffffff, 0xffff0000, 0xffffffff, 0xffff8000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00008000, 0x00000000, 0x00010000, 0x00000000, 0x3fff8000,
    -  0x80000000, 0x00000000, 0x1e7e803f, 0x8ca61d25, 0x000fffff, 0xffff0001,
    -  0x00100000, 0x00000000, 0x0000ffff, 0xffff0001, 0x00010000, 0x00000000,
    -  0xffff0000, 0xffff0001, 0xffff0001, 0x00000000, 0xffffff00, 0x00ff0001,
    -  0xffffff00, 0x01000000, 0xffffffff, 0x00000001, 0xffffffff, 0x00010000,
    -  0xffffffff, 0x7fff8001, 0xffffffff, 0x80008000, 0xffffffff, 0xfffe0002,
    -  0xffffffff, 0xffff0001, 0x00000000, 0x00000000, 0x00000000, 0x0000ffff,
    -  0x00000000, 0x0001fffe, 0x00000000, 0x7ffe8001, 0x00000000, 0x7fff8000,
    -  0x00000000, 0x00000000, 0xd5f55634, 0xe2db0000, 0xffffffff, 0xffff0000,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffff0000, 0x00000000, 0x00000000,
    -  0xfffeffff, 0xffff0000, 0xffff0000, 0x00000000, 0xfffffeff, 0xffff0000,
    -  0xffffff00, 0x00000000, 0xfffffffe, 0xffff0000, 0xffffffff, 0x00000000,
    -  0xffffffff, 0x7fff0000, 0xffffffff, 0x80000000, 0xffffffff, 0xfffe0000,
    -  0xffffffff, 0xffff0000, 0x00000000, 0x00000000, 0x00000000, 0x00010000,
    -  0x00000000, 0x00020000, 0x00000000, 0x7fff0000, 0x00000000, 0x80000000,
    -  0x00000000, 0xffff0000, 0x80000000, 0x00000000, 0x3ddf5eed, 0x84cb1d25,
    -  0x000fffff, 0xff000001, 0x00100000, 0x00000000, 0x0000ffff, 0xff000001,
    -  0x00010000, 0x00000000, 0xff000000, 0xff000001, 0xff000001, 0x00000000,
    -  0xffff0000, 0x00000001, 0xffff0000, 0x01000000, 0xfffffeff, 0xff010001,
    -  0xffffff00, 0x00010000, 0xffffff7f, 0xff008001, 0xffffff80, 0x00008000,
    -  0xffffffff, 0xfe000002, 0xffffffff, 0xff000001, 0x00000000, 0x00000000,
    -  0x00000000, 0x00ffffff, 0x00000000, 0x01fffffe, 0x0000007f, 0xfeff8001,
    -  0x0000007f, 0xffff8000, 0x000000ff, 0xfeff0001, 0x000000ff, 0xffff0000,
    -  0x00000000, 0x00000000, 0xf55634e2, 0xdb000000, 0xffffffff, 0xff000000,
    -  0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0x00000000, 0x00000000,
    -  0xfeffffff, 0xff000000, 0xff000000, 0x00000000, 0xfffeffff, 0xff000000,
    -  0xffff0000, 0x00000000, 0xfffffeff, 0xff000000, 0xffffff00, 0x00000000,
    -  0xffffff7f, 0xff000000, 0xffffff80, 0x00000000, 0xffffffff, 0xfe000000,
    -  0xffffffff, 0xff000000, 0x00000000, 0x00000000, 0x00000000, 0x01000000,
    -  0x00000000, 0x02000000, 0x0000007f, 0xff000000, 0x00000080, 0x00000000,
    -  0x000000ff, 0xff000000, 0x00000100, 0x00000000, 0x0000ffff, 0xff000000,
    -  0x80000000, 0x00000000, 0xbc56e5ef, 0x15ff6759, 0xd24fffff, 0xa9cb1d25,
    -  0xd2500000, 0x00000000, 0x1d24ffff, 0xa9cb1d25, 0x1d250000, 0x00000000,
    -  0xa9cb1d24, 0xa9cb1d25, 0xa9cb1d25, 0x00000000, 0xffa9cb1c, 0xcecb1d25,
    -  0xffa9cb1d, 0x25000000, 0xffffa9ca, 0xc6f01d25, 0xffffa9cb, 0x1d250000,
    -  0xffffd4e5, 0x385d9d25, 0xffffd4e5, 0x8e928000, 0xffffffff, 0x53963a4a,
    -  0xffffffff, 0xa9cb1d25, 0x00000000, 0x00000000, 0x00000000, 0x5634e2db,
    -  0x00000000, 0xac69c5b6, 0x00002b1a, 0x1b389d25, 0x00002b1a, 0x716d8000,
    -  0x00005634, 0x8ca61d25, 0x00005634, 0xe2db0000, 0x005634e2, 0x84cb1d25,
    -  0x005634e2, 0xdb000000, 0x80000000, 0x00000000, 0x74756f10, 0x9f4f5297,
    -  0xa0afffff, 0x48892a0b, 0xa0b00000, 0x00000000, 0x2a0affff, 0x48892a0b,
    -  0x2a0b0000, 0x00000000, 0x48892a0a, 0x48892a0b, 0x48892a0b, 0x00000000,
    -  0xff488929, 0x53892a0b, 0xff48892a, 0x0b000000, 0xffff4888, 0x72942a0b,
    -  0xffff4889, 0x2a0b0000, 0xffffa443, 0xdd8eaa0b, 0xffffa444, 0x95058000,
    -  0xfffffffe, 0x91125416, 0xffffffff, 0x48892a0b, 0x00000000, 0x00000000,
    -  0x00000000, 0xb776d5f5, 0x00000001, 0x6eedabea, 0x00005bba, 0xb383aa0b,
    -  0x00005bbb, 0x6afa8000, 0x0000b776, 0x1e7e2a0b, 0x0000b776, 0xd5f50000,
    -  0x00b776d5, 0x3d892a0b, 0x00b776d5, 0xf5000000, 0x3dc7d297, 0x9f4f5297,
    -  0x80000000, 0x00000000, 0x9ebe0ce5, 0xa9cb1d25, 0x000fffff, 0x00000001,
    -  0x00100000, 0x00000000, 0x0000ffff, 0x00000001, 0x00010000, 0x00000000,
    -  0x00000000, 0x00000001, 0x00000001, 0x00000000, 0xfeffffff, 0x01000001,
    -  0xff000000, 0x01000000, 0xfffeffff, 0x00010001, 0xffff0000, 0x00010000,
    -  0xffff7fff, 0x00008001, 0xffff8000, 0x00008000, 0xfffffffe, 0x00000002,
    -  0xffffffff, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
    -  0x00000001, 0xfffffffe, 0x00007ffe, 0xffff8001, 0x00007fff, 0xffff8000,
    -  0x0000fffe, 0xffff0001, 0x0000ffff, 0xffff0000, 0x00fffffe, 0xff000001,
    -  0x00ffffff, 0xff000000, 0x5634e2da, 0xa9cb1d25, 0xb776d5f4, 0x48892a0b,
    -  0x00000000, 0x00000000, 0x5634e2db, 0x00000000, 0xffffffff, 0x00000000,
    -  0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
    -  0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xfeffffff, 0x00000000,
    -  0xff000000, 0x00000000, 0xfffeffff, 0x00000000, 0xffff0000, 0x00000000,
    -  0xffff7fff, 0x00000000, 0xffff8000, 0x00000000, 0xfffffffe, 0x00000000,
    -  0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000,
    -  0x00000002, 0x00000000, 0x00007fff, 0x00000000, 0x00008000, 0x00000000,
    -  0x0000ffff, 0x00000000, 0x00010000, 0x00000000, 0x00ffffff, 0x00000000,
    -  0x01000000, 0x00000000, 0x5634e2db, 0x00000000, 0xb776d5f5, 0x00000000,
    -  0xffffffff, 0x00000000, 0x80000000, 0x00000000, 0x2b642a0a, 0xa9cb1d25,
    -  0x000f0000, 0x00000001, 0x00100000, 0x00000000, 0x00000000, 0x00000001,
    -  0x00010000, 0x00000000, 0xffff0001, 0x00000001, 0x00000001, 0x00000000,
    -  0xffff0000, 0x01000001, 0x00000000, 0x01000000, 0xffff0000, 0x00010001,
    -  0x00000000, 0x00010000, 0x7fff0000, 0x00008001, 0x80000000, 0x00008000,
    -  0xfffe0000, 0x00000002, 0xffff0000, 0x00000001, 0x00000000, 0x00000000,
    -  0x0000ffff, 0xffffffff, 0x0001ffff, 0xfffffffe, 0x7ffeffff, 0xffff8001,
    -  0x7fffffff, 0xffff8000, 0xfffeffff, 0xffff0001, 0xffffffff, 0xffff0000,
    -  0xfffeffff, 0xff000001, 0xffffffff, 0xff000000, 0xe2daffff, 0xa9cb1d25,
    -  0xd5f4ffff, 0x48892a0b, 0xfffeffff, 0x00000001, 0xffffffff, 0x00000000,
    -  0x00000000, 0x00000000, 0xe2db0000, 0x00000000, 0xffff0000, 0x00000000,
    -  0x00000000, 0x00000000, 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
    -  0xffff0000, 0x00000000, 0x00000000, 0x00000000, 0xffff0000, 0x00000000,
    -  0x00000000, 0x00000000, 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
    -  0x7fff0000, 0x00000000, 0x80000000, 0x00000000, 0xfffe0000, 0x00000000,
    -  0xffff0000, 0x00000000, 0x00000000, 0x00000000, 0x00010000, 0x00000000,
    -  0x00020000, 0x00000000, 0x7fff0000, 0x00000000, 0x80000000, 0x00000000,
    -  0xffff0000, 0x00000000, 0x00000000, 0x00000000, 0xffff0000, 0x00000000,
    -  0x00000000, 0x00000000, 0xe2db0000, 0x00000000, 0xd5f50000, 0x00000000,
    -  0xffff0000, 0x00000000, 0x00000000, 0x00000000, 0xffff0000, 0x00000000,
    -  0x80000000, 0x00000000, 0x76392a0a, 0xa9cb1d25, 0x00000000, 0x00000001,
    -  0x00100000, 0x00000000, 0xfff10000, 0x00000001, 0x00010000, 0x00000000,
    -  0xfff00001, 0x00000001, 0x00000001, 0x00000000, 0xfff00000, 0x01000001,
    -  0x00000000, 0x01000000, 0xfff00000, 0x00010001, 0x00000000, 0x00010000,
    -  0xfff00000, 0x00008001, 0x00000000, 0x00008000, 0xffe00000, 0x00000002,
    -  0xfff00000, 0x00000001, 0x00000000, 0x00000000, 0x000fffff, 0xffffffff,
    -  0x001fffff, 0xfffffffe, 0xffefffff, 0xffff8001, 0xffffffff, 0xffff8000,
    -  0xffefffff, 0xffff0001, 0xffffffff, 0xffff0000, 0xffefffff, 0xff000001,
    -  0xffffffff, 0xff000000, 0x2dafffff, 0xa9cb1d25, 0x5f4fffff, 0x48892a0b,
    -  0xffefffff, 0x00000001, 0xffffffff, 0x00000000, 0xffef0000, 0x00000001,
    -  0xffff0000, 0x00000000, 0x00000000, 0x00000000, 0x2db00000, 0x00000000,
    -  0xfff00000, 0x00000000, 0x00000000, 0x00000000, 0xfff00000, 0x00000000,
    -  0x00000000, 0x00000000, 0xfff00000, 0x00000000, 0x00000000, 0x00000000,
    -  0xfff00000, 0x00000000, 0x00000000, 0x00000000, 0xfff00000, 0x00000000,
    -  0x00000000, 0x00000000, 0xfff00000, 0x00000000, 0x00000000, 0x00000000,
    -  0xffe00000, 0x00000000, 0xfff00000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00100000, 0x00000000, 0x00200000, 0x00000000, 0xfff00000, 0x00000000,
    -  0x00000000, 0x00000000, 0xfff00000, 0x00000000, 0x00000000, 0x00000000,
    -  0xfff00000, 0x00000000, 0x00000000, 0x00000000, 0x2db00000, 0x00000000,
    -  0x5f500000, 0x00000000, 0xfff00000, 0x00000000, 0x00000000, 0x00000000,
    -  0xfff00000, 0x00000000, 0x00000000, 0x00000000, 0xfff00000, 0x00000000,
    -  0x80000000, 0x00000000, 0x8a74d669, 0x9f4f5297, 0x4a7b1d24, 0x48892a0b,
    -  0xa0b00000, 0x00000000, 0xd3d61d24, 0x48892a0b, 0x2a0b0000, 0x00000000,
    -  0xf254472f, 0x48892a0b, 0x48892a0b, 0x00000000, 0xce13a64e, 0x53892a0b,
    -  0x2448892a, 0x0b000000, 0xc6ef65ad, 0x72942a0b, 0x1d244889, 0x2a0b0000,
    -  0x385d4168, 0xdd8eaa0b, 0x8e922444, 0x95058000, 0x53963a48, 0x91125416,
    -  0xa9cb1d24, 0x48892a0b, 0x00000000, 0x00000000, 0x5634e2db, 0xb776d5f5,
    -  0xac69c5b7, 0x6eedabea, 0x1b38f8df, 0xb383aa0b, 0x716ddbbb, 0x6afa8000,
    -  0x8ca6d49b, 0x1e7e2a0b, 0xe2dbb776, 0xd5f50000, 0x858293fa, 0x3d892a0b,
    -  0xdbb776d5, 0xf5000000, 0x53c739f0, 0x9f4f5297, 0x22ca6fa5, 0x36ad9c79,
    -  0x6141f319, 0x48892a0b, 0xb776d5f5, 0x00000000, 0x7fc01d24, 0x48892a0b,
    -  0xd5f50000, 0x00000000, 0x091b1d24, 0x48892a0b, 0x5f500000, 0x00000000,
    -  0x80000000, 0x00000000, 0xc8892a0a, 0xa9cb1d25, 0x80100000, 0x00000001,
    -  0x00100000, 0x00000000, 0x80010000, 0x00000001, 0x00010000, 0x00000000,
    -  0x80000001, 0x00000001, 0x00000001, 0x00000000, 0x80000000, 0x01000001,
    -  0x00000000, 0x01000000, 0x80000000, 0x00010001, 0x00000000, 0x00010000,
    -  0x80000000, 0x00008001, 0x00000000, 0x00008000, 0x00000000, 0x00000002,
    -  0x80000000, 0x00000001, 0x00000000, 0x00000000, 0x7fffffff, 0xffffffff,
    -  0xffffffff, 0xfffffffe, 0x7fffffff, 0xffff8001, 0xffffffff, 0xffff8000,
    -  0x7fffffff, 0xffff0001, 0xffffffff, 0xffff0000, 0x7fffffff, 0xff000001,
    -  0xffffffff, 0xff000000, 0x7fffffff, 0xa9cb1d25, 0x7fffffff, 0x48892a0b,
    -  0x7fffffff, 0x00000001, 0xffffffff, 0x00000000, 0x7fff0000, 0x00000001,
    -  0xffff0000, 0x00000000, 0x7ff00000, 0x00000001, 0xfff00000, 0x00000000,
    -  0x29cb1d24, 0x48892a0b
    -];
    -toInt32s(TEST_MUL_BITS);
    -
    -var TEST_DIV_BITS = [
    -  0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x000007ff,
    -  0x00000000, 0x00000800, 0x00000000, 0x00007fff, 0x00000000, 0x00008000,
    -  0x00000000, 0x7fffffff, 0x00000000, 0x80000000, 0x0000007f, 0xffff8000,
    -  0x00000080, 0x00000000, 0x00007fff, 0x80007fff, 0x00008000, 0x00000000,
    -  0x0000fffe, 0x0003fff8, 0x00010000, 0x00000000, 0x40000000, 0x00000000,
    -  0x80000000, 0x00000000, 0x80000000, 0x00000000, 0xc0000000, 0x00000000,
    -  0xfffefffd, 0xfffbfff8, 0xffff0000, 0x00000000, 0xffff7fff, 0x7fff8000,
    -  0xffff8000, 0x00000000, 0xffffff7f, 0xffff8000, 0xffffff80, 0x00000000,
    -  0xfffffffe, 0x83e3cc1a, 0xffffffff, 0x4d64985a, 0xffffffff, 0x80000000,
    -  0xffffffff, 0x80000000, 0xffffffff, 0xffff8000, 0xffffffff, 0xffff8000,
    -  0xffffffff, 0xfffff800, 0xffffffff, 0xfffff800, 0xffffffff, 0xffffffff,
    -  0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000488, 0x00000000, 0x00000488, 0x00000000, 0x00004889,
    -  0x00000000, 0x00004889, 0x00000000, 0x48892a0a, 0x00000000, 0x48892a0a,
    -  0x00000048, 0x8929c220, 0x00000048, 0x892a0aa9, 0x00004888, 0xe181c849,
    -  0x00004889, 0x2a0aa9cb, 0x00009111, 0x31f2efb0, 0x00009112, 0x54155396,
    -  0x24449505, 0x54e58e92, 0x48892a0a, 0xa9cb1d25, 0xb776d5f5, 0x5634e2db,
    -  0xdbbb6afa, 0xab1a716e, 0xffff6eec, 0x89c3bff2, 0xffff6eed, 0xabeaac6a,
    -  0xffffb776, 0x8d6be3a1, 0xffffb776, 0xd5f55635, 0xffffffb7, 0x76d5acce,
    -  0xffffffb7, 0x76d5f557, 0xffffffff, 0x2898cfc6, 0xffffffff, 0x9ac930b4,
    -  0xffffffff, 0xb776d5f6, 0xffffffff, 0xb776d5f6, 0xffffffff, 0xffffb777,
    -  0xffffffff, 0xffffb777, 0xffffffff, 0xfffffb78, 0xffffffff, 0xfffffb78,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000001,
    -  0x00000000, 0x0000000f, 0x00000000, 0x00000010, 0x00000000, 0x000fffff,
    -  0x00000000, 0x00100000, 0x00000000, 0x0ffffff0, 0x00000000, 0x10000000,
    -  0x0000000f, 0xfff0000f, 0x00000010, 0x00000000, 0x0000001f, 0xffc0007f,
    -  0x00000020, 0x00000000, 0x00080000, 0x00000000, 0x00100000, 0x00000001,
    -  0xffefffff, 0xffffffff, 0xfff80000, 0x00000000, 0xffffffdf, 0xffbfff80,
    -  0xffffffe0, 0x00000000, 0xffffffef, 0xffeffff0, 0xfffffff0, 0x00000000,
    -  0xffffffff, 0xeffffff0, 0xffffffff, 0xf0000000, 0xffffffff, 0xffd07c7a,
    -  0xffffffff, 0xffe9ac94, 0xffffffff, 0xfff00000, 0xffffffff, 0xfff00000,
    -  0xffffffff, 0xfffffff0, 0xffffffff, 0xfffffff0, 0xffffffff, 0xffffffff,
    -  0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000001, 0x00000000, 0x0000000f, 0x00000000, 0x00000010,
    -  0x00000000, 0x000fffff, 0x00000000, 0x00100000, 0x00000000, 0x0ffffff0,
    -  0x00000000, 0x10000000, 0x0000000f, 0xfff0000f, 0x00000010, 0x00000000,
    -  0x0000001f, 0xffc0007f, 0x00000020, 0x00000000, 0x00080000, 0x00000000,
    -  0x00100000, 0x00000000, 0xfff00000, 0x00000000, 0xfff80000, 0x00000000,
    -  0xffffffdf, 0xffbfff80, 0xffffffe0, 0x00000000, 0xffffffef, 0xffeffff0,
    -  0xfffffff0, 0x00000000, 0xffffffff, 0xeffffff0, 0xffffffff, 0xf0000000,
    -  0xffffffff, 0xffd07c7a, 0xffffffff, 0xffe9ac94, 0xffffffff, 0xfff00000,
    -  0xffffffff, 0xfff00000, 0xffffffff, 0xfffffff0, 0xffffffff, 0xfffffff0,
    -  0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000001, 0x00000000, 0x0000ffff, 0x00000000, 0x00010000,
    -  0x00000000, 0x00ffffff, 0x00000000, 0x01000000, 0x00000000, 0xffff0001,
    -  0x00000001, 0x00000000, 0x00000001, 0xfffc0007, 0x00000002, 0x00000000,
    -  0x00008000, 0x00000000, 0x00010000, 0x00000001, 0xfffeffff, 0xffffffff,
    -  0xffff8000, 0x00000000, 0xfffffffd, 0xfffbfff8, 0xfffffffe, 0x00000000,
    -  0xfffffffe, 0xfffeffff, 0xffffffff, 0x00000000, 0xffffffff, 0xfeffffff,
    -  0xffffffff, 0xff000000, 0xffffffff, 0xfffd07c8, 0xffffffff, 0xfffe9aca,
    -  0xffffffff, 0xffff0000, 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
    -  0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0000ffff,
    -  0x00000000, 0x00010000, 0x00000000, 0x00ffffff, 0x00000000, 0x01000000,
    -  0x00000000, 0xffff0000, 0x00000001, 0x00000000, 0x00000001, 0xfffc0007,
    -  0x00000002, 0x00000000, 0x00008000, 0x00000000, 0x00010000, 0x00000000,
    -  0xffff0000, 0x00000000, 0xffff8000, 0x00000000, 0xfffffffd, 0xfffbfff8,
    -  0xfffffffe, 0x00000000, 0xfffffffe, 0xfffeffff, 0xffffffff, 0x00000000,
    -  0xffffffff, 0xfeffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xfffd07c8,
    -  0xffffffff, 0xfffe9aca, 0xffffffff, 0xffff0000, 0xffffffff, 0xffff0000,
    -  0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x000000ff,
    -  0x00000000, 0x00000100, 0x00000000, 0x0000ffff, 0x00000000, 0x00010000,
    -  0x00000000, 0x0001fffc, 0x00000000, 0x00020000, 0x00000000, 0x80000000,
    -  0x00000001, 0x00000001, 0xfffffffe, 0xffffffff, 0xffffffff, 0x80000000,
    -  0xffffffff, 0xfffdfffc, 0xffffffff, 0xfffe0000, 0xffffffff, 0xfffeffff,
    -  0xffffffff, 0xffff0000, 0xffffffff, 0xffffff00, 0xffffffff, 0xffffff00,
    -  0xffffffff, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
    -  0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
    -  0x00000000, 0x000000ff, 0x00000000, 0x00000100, 0x00000000, 0x0000ffff,
    -  0x00000000, 0x00010000, 0x00000000, 0x0001fffc, 0x00000000, 0x00020000,
    -  0x00000000, 0x80000000, 0x00000001, 0x00000000, 0xffffffff, 0x00000000,
    -  0xffffffff, 0x80000000, 0xffffffff, 0xfffdfffc, 0xffffffff, 0xfffe0000,
    -  0xffffffff, 0xfffeffff, 0xffffffff, 0xffff0000, 0xffffffff, 0xffffff00,
    -  0xffffffff, 0xffffff00, 0xffffffff, 0xfffffffe, 0xffffffff, 0xffffffff,
    -  0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000001,
    -  0x00000000, 0x000000ff, 0x00000000, 0x00000100, 0x00000000, 0x000001ff,
    -  0x00000000, 0x00000200, 0x00000000, 0x00800000, 0x00000000, 0x01000001,
    -  0xffffffff, 0xfeffffff, 0xffffffff, 0xff800000, 0xffffffff, 0xfffffe00,
    -  0xffffffff, 0xfffffe00, 0xffffffff, 0xffffff00, 0xffffffff, 0xffffff00,
    -  0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000001, 0x00000000, 0x000000ff, 0x00000000, 0x00000100,
    -  0x00000000, 0x000001ff, 0x00000000, 0x00000200, 0x00000000, 0x00800000,
    -  0x00000000, 0x01000000, 0xffffffff, 0xff000000, 0xffffffff, 0xff800000,
    -  0xffffffff, 0xfffffe00, 0xffffffff, 0xfffffe00, 0xffffffff, 0xffffff00,
    -  0xffffffff, 0xffffff00, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x00000002,
    -  0x00000000, 0x00008000, 0x00000000, 0x00010001, 0xffffffff, 0xfffeffff,
    -  0xffffffff, 0xffff8000, 0xffffffff, 0xfffffffe, 0xffffffff, 0xfffffffe,
    -  0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000002, 0x00000000, 0x00008000, 0x00000000, 0x00010000,
    -  0xffffffff, 0xffff0000, 0xffffffff, 0xffff8000, 0xffffffff, 0xfffffffe,
    -  0xffffffff, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x00004000,
    -  0x00000000, 0x00008001, 0xffffffff, 0xffff7fff, 0xffffffff, 0xffffc000,
    -  0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
    -  0x00000000, 0x00004000, 0x00000000, 0x00008000, 0xffffffff, 0xffff8000,
    -  0xffffffff, 0xffffc000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000002,
    -  0xffffffff, 0xfffffffe, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000001, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
    -  0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
    -  0xffffffff, 0xfffffffe, 0x00000000, 0x00000002, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0xffffffff, 0xffffc001, 0xffffffff, 0xffff8001, 0x00000000, 0x00007fff,
    -  0x00000000, 0x00003fff, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0xffffffff, 0xffffffff, 0xffffffff, 0xffffc000, 0xffffffff, 0xffff8000,
    -  0x00000000, 0x00008000, 0x00000000, 0x00004000, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff8001,
    -  0xffffffff, 0xffff0001, 0x00000000, 0x0000ffff, 0x00000000, 0x00007fff,
    -  0x00000000, 0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffffe,
    -  0xffffffff, 0xffff8000, 0xffffffff, 0xffff0000, 0x00000000, 0x00010000,
    -  0x00000000, 0x00008000, 0x00000000, 0x00000002, 0x00000000, 0x00000002,
    -  0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0xffffffff, 0xffffff01, 0xffffffff, 0xffffff01, 0xffffffff, 0xfffffe01,
    -  0xffffffff, 0xfffffe01, 0xffffffff, 0xff800001, 0xffffffff, 0xff000001,
    -  0x00000000, 0x00ffffff, 0x00000000, 0x007fffff, 0x00000000, 0x00000200,
    -  0x00000000, 0x000001ff, 0x00000000, 0x00000100, 0x00000000, 0x000000ff,
    -  0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0xffffffff, 0xffffffff, 0xffffffff, 0xffffff01, 0xffffffff, 0xffffff00,
    -  0xffffffff, 0xfffffe01, 0xffffffff, 0xfffffe00, 0xffffffff, 0xff800000,
    -  0xffffffff, 0xff000000, 0x00000000, 0x01000000, 0x00000000, 0x00800000,
    -  0x00000000, 0x00000200, 0x00000000, 0x00000200, 0x00000000, 0x00000100,
    -  0x00000000, 0x00000100, 0x00000000, 0x00000001, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0xffffffff, 0xffffffaa, 0xffffffff, 0xffffffaa, 0xffffffff, 0xffffa9cc,
    -  0xffffffff, 0xffffa9cc, 0xffffffff, 0xffff5398, 0xffffffff, 0xffff5397,
    -  0xffffffff, 0xd4e58e93, 0xffffffff, 0xa9cb1d25, 0x00000000, 0x5634e2db,
    -  0x00000000, 0x2b1a716d, 0x00000000, 0x0000ac6b, 0x00000000, 0x0000ac69,
    -  0x00000000, 0x00005635, 0x00000000, 0x00005634, 0x00000000, 0x00000056,
    -  0x00000000, 0x00000056, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffff49, 0xffffffff, 0xffffff49,
    -  0xffffffff, 0xffff488a, 0xffffffff, 0xffff488a, 0xffffffff, 0xfffe9116,
    -  0xffffffff, 0xfffe9113, 0xffffffff, 0xa4449506, 0xffffffff, 0x48892a0b,
    -  0x00000000, 0xb776d5f5, 0x00000000, 0x5bbb6afa, 0x00000000, 0x00016ef0,
    -  0x00000000, 0x00016eed, 0x00000000, 0x0000b777, 0x00000000, 0x0000b776,
    -  0x00000000, 0x000000b7, 0x00000000, 0x000000b7, 0x00000000, 0x00000002,
    -  0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffff01,
    -  0xffffffff, 0xffffff01, 0xffffffff, 0xffff0001, 0xffffffff, 0xffff0001,
    -  0xffffffff, 0xfffe0004, 0xffffffff, 0xfffe0001, 0xffffffff, 0x80000001,
    -  0xffffffff, 0x00000001, 0x00000000, 0xffffffff, 0x00000000, 0x7fffffff,
    -  0x00000000, 0x00020004, 0x00000000, 0x0001ffff, 0x00000000, 0x00010001,
    -  0x00000000, 0x0000ffff, 0x00000000, 0x00000100, 0x00000000, 0x000000ff,
    -  0x00000000, 0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
    -  0xffffffff, 0xffffff01, 0xffffffff, 0xffffff00, 0xffffffff, 0xffff0001,
    -  0xffffffff, 0xffff0000, 0xffffffff, 0xfffe0004, 0xffffffff, 0xfffe0000,
    -  0xffffffff, 0x80000000, 0xffffffff, 0x00000000, 0x00000001, 0x00000000,
    -  0x00000000, 0x80000000, 0x00000000, 0x00020004, 0x00000000, 0x00020000,
    -  0x00000000, 0x00010001, 0x00000000, 0x00010000, 0x00000000, 0x00000100,
    -  0x00000000, 0x00000100, 0x00000000, 0x00000002, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffff0001,
    -  0xffffffff, 0xffff0001, 0xffffffff, 0xff000001, 0xffffffff, 0xff000001,
    -  0xffffffff, 0x00010000, 0xffffffff, 0x00000001, 0xfffffffe, 0x0003fff9,
    -  0xfffffffe, 0x00000001, 0xffff8000, 0x00000001, 0xffff0000, 0x00000001,
    -  0x0000ffff, 0xffffffff, 0x00007fff, 0xffffffff, 0x00000002, 0x00040008,
    -  0x00000001, 0xffffffff, 0x00000001, 0x00010001, 0x00000000, 0xffffffff,
    -  0x00000000, 0x01000001, 0x00000000, 0x00ffffff, 0x00000000, 0x0002f838,
    -  0x00000000, 0x00016536, 0x00000000, 0x00010000, 0x00000000, 0x0000ffff,
    -  0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
    -  0xffffffff, 0xffff0001, 0xffffffff, 0xffff0000, 0xffffffff, 0xff000001,
    -  0xffffffff, 0xff000000, 0xffffffff, 0x00010000, 0xffffffff, 0x00000000,
    -  0xfffffffe, 0x0003fff9, 0xfffffffe, 0x00000000, 0xffff8000, 0x00000000,
    -  0xffff0000, 0x00000000, 0x00010000, 0x00000000, 0x00008000, 0x00000000,
    -  0x00000002, 0x00040008, 0x00000002, 0x00000000, 0x00000001, 0x00010001,
    -  0x00000001, 0x00000000, 0x00000000, 0x01000001, 0x00000000, 0x01000000,
    -  0x00000000, 0x0002f838, 0x00000000, 0x00016536, 0x00000000, 0x00010000,
    -  0x00000000, 0x00010000, 0x00000000, 0x00000001, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xfffffff1,
    -  0xffffffff, 0xfffffff1, 0xffffffff, 0xfff00001, 0xffffffff, 0xfff00001,
    -  0xffffffff, 0xf0000010, 0xffffffff, 0xf0000001, 0xfffffff0, 0x000ffff1,
    -  0xfffffff0, 0x00000001, 0xffffffe0, 0x003fff81, 0xffffffe0, 0x00000001,
    -  0xfff80000, 0x00000001, 0xfff00000, 0x00000001, 0x000fffff, 0xffffffff,
    -  0x0007ffff, 0xffffffff, 0x00000020, 0x00400080, 0x0000001f, 0xffffffff,
    -  0x00000010, 0x00100010, 0x0000000f, 0xffffffff, 0x00000000, 0x10000010,
    -  0x00000000, 0x0fffffff, 0x00000000, 0x002f8386, 0x00000000, 0x0016536c,
    -  0x00000000, 0x00100000, 0x00000000, 0x000fffff, 0x00000000, 0x00000010,
    -  0x00000000, 0x0000000f, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
    -  0xffffffff, 0xfffffff1, 0xffffffff, 0xfffffff0, 0xffffffff, 0xfff00001,
    -  0xffffffff, 0xfff00000, 0xffffffff, 0xf0000010, 0xffffffff, 0xf0000000,
    -  0xfffffff0, 0x000ffff1, 0xfffffff0, 0x00000000, 0xffffffe0, 0x003fff81,
    -  0xffffffe0, 0x00000000, 0xfff80000, 0x00000000, 0xfff00000, 0x00000000,
    -  0x00100000, 0x00000000, 0x00080000, 0x00000000, 0x00000020, 0x00400080,
    -  0x00000020, 0x00000000, 0x00000010, 0x00100010, 0x00000010, 0x00000000,
    -  0x00000000, 0x10000010, 0x00000000, 0x10000000, 0x00000000, 0x002f8386,
    -  0x00000000, 0x0016536c, 0x00000000, 0x00100000, 0x00000000, 0x00100000,
    -  0x00000000, 0x00000010, 0x00000000, 0x00000010, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffa9d,
    -  0xffffffff, 0xfffffa9d, 0xffffffff, 0xffffa9cc, 0xffffffff, 0xffffa9cc,
    -  0xffffffff, 0xa9cb1d25, 0xffffffff, 0xa9cb1d25, 0xffffffa9, 0xcb1d7a7e,
    -  0xffffffa9, 0xcb1d2449, 0xffffa9cb, 0x7358d531, 0xffffa9cb, 0x1d24488a,
    -  0xffff5397, 0x93196ae0, 0xffff5396, 0x3a489113, 0xd4e58e92, 0x24449506,
    -  0xa9cb1d24, 0x48892a0b, 0x5634e2db, 0xb776d5f5, 0x2b1a716d, 0xdbbb6afa,
    -  0x0000ac6b, 0x1e8dac09, 0x0000ac69, 0xc5b76eed, 0x00005635, 0x3910f087,
    -  0x00005634, 0xe2dbb776, 0x00000056, 0x34e331ec, 0x00000056, 0x34e2dbb7,
    -  0x00000001, 0x00000002, 0x00000000, 0x784a3552, 0x00000000, 0x5634e2dc,
    -  0x00000000, 0x5634e2db, 0x00000000, 0x00005634, 0x00000000, 0x00005634,
    -  0x00000000, 0x00000563, 0x00000000, 0x00000563, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
    -  0xffffffff, 0xfffff801, 0xffffffff, 0xfffff801, 0xffffffff, 0xffff8001,
    -  0xffffffff, 0xffff8001, 0xffffffff, 0x80000001, 0xffffffff, 0x80000001,
    -  0xffffff80, 0x00008000, 0xffffff80, 0x00000001, 0xffff8000, 0x7fff8001,
    -  0xffff8000, 0x00000001, 0xffff0001, 0xfffc0008, 0xffff0000, 0x00000001,
    -  0xc0000000, 0x00000001, 0x80000000, 0x00000001, 0x7fffffff, 0xffffffff,
    -  0x3fffffff, 0xffffffff, 0x00010002, 0x00040008, 0x0000ffff, 0xffffffff,
    -  0x00008000, 0x80008000, 0x00007fff, 0xffffffff, 0x00000080, 0x00008000,
    -  0x0000007f, 0xffffffff, 0x00000001, 0x7c1c33e6, 0x00000000, 0xb29b67a6,
    -  0x00000000, 0x80000000, 0x00000000, 0x7fffffff, 0x00000000, 0x00008000,
    -  0x00000000, 0x00007fff, 0x00000000, 0x00000800, 0x00000000, 0x000007ff,
    -  0x00000000, 0x00000001, 0x00000000, 0x00000001
    -];
    -toInt32s(TEST_DIV_BITS);
    -
    -var TEST_STRINGS = [
    -  '-9223372036854775808',
    -  '-5226755067826871589',
    -  '-4503599627370497',
    -  '-4503599627370496',
    -  '-281474976710657',
    -  '-281474976710656',
    -  '-4294967297',
    -  '-4294967296',
    -  '-16777217',
    -  '-16777216',
    -  '-65537',
    -  '-65536',
    -  '-32769',
    -  '-32768',
    -  '-2',
    -  '-1',
    -  '0',
    -  '1',
    -  '2',
    -  '32767',
    -  '32768',
    -  '65535',
    -  '65536',
    -  '16777215',
    -  '16777216',
    -  '1446306523',
    -  '3078018549',
    -  '4294967295',
    -  '4294967296',
    -  '281474976710655',
    -  '281474976710656',
    -  '4503599627370495',
    -  '4503599627370496',
    -  '6211839219354490357',
    -  '9223372036854775807'
    -];
    -
    -function testToFromBits() {
    -  for (var i = 0; i < TEST_BITS.length; i += 2) {
    -    var val = goog.math.Integer.fromBits([TEST_BITS[i + 1], TEST_BITS[i]]);
    -    assertEquals(TEST_BITS[i], val.getBits(1));
    -    assertEquals(TEST_BITS[i + 1], val.getBits(0));
    -  }
    -}
    -
    -function testToFromInt() {
    -  for (var i = 0; i < TEST_BITS.length; i += 1) {
    -    var val = goog.math.Integer.fromInt(TEST_BITS[i]);
    -    assertEquals(TEST_BITS[i], val.toInt());
    -  }
    -}
    -
    -function testToFromNumber() {
    -  for (var i = 0; i < TEST_BITS.length; i += 2) {
    -    var num = TEST_BITS[i] * Math.pow(2, 32) + TEST_BITS[i + 1] >= 0 ?
    -        TEST_BITS[i + 1] : Math.pow(2, 32) + TEST_BITS[i + 1];
    -    var val = goog.math.Integer.fromNumber(num);
    -    assertEquals(num, val.toNumber());
    -  }
    -}
    -
    -function testShorten() {
    -  for (var i = 0; i < TEST_BITS.length; i += 2) {
    -    var val = new goog.math.Integer([TEST_BITS[i + 1], TEST_BITS[i]], 0);
    -    val = val.shorten(64);
    -    assertEquals(TEST_BITS[i], val.getBits(1));
    -    assertEquals(TEST_BITS[i + 1], val.getBits(0));
    -  }
    -
    -  val = new goog.math.Integer.fromBits([0x20000000, 0x01010000], 0);
    -
    -  var val58 = val.shorten(58);
    -  assertEquals(0x01010000 | 0, val58.getBits(1));
    -  assertEquals(0x20000000 | 0, val58.getBits(0));
    -
    -  var val57 = val.shorten(57);
    -  assertEquals(0xFF010000 | 0, val57.getBits(1));
    -  assertEquals(0x20000000 | 0, val57.getBits(0));
    -
    -  var val56 = val.shorten(56);
    -  assertEquals(0x00010000 | 0, val56.getBits(1));
    -  assertEquals(0x20000000 | 0, val56.getBits(0));
    -
    -  var val50 = val.shorten(50);
    -  assertEquals(0x00010000 | 0, val50.getBits(1));
    -  assertEquals(0x20000000 | 0, val50.getBits(0));
    -
    -  var val49 = val.shorten(49);
    -  assertEquals(0xFFFF0000 | 0, val49.getBits(1));
    -  assertEquals(0x20000000 | 0, val49.getBits(0));
    -
    -  var val32 = val.shorten(32);
    -  assertEquals(0x00000000 | 0, val32.getBits(1));
    -  assertEquals(0x20000000 | 0, val32.getBits(0));
    -
    -  var val31 = val.shorten(31);
    -  assertEquals(0x00000000 | 0, val31.getBits(1));
    -  assertEquals(0x20000000 | 0, val31.getBits(0));
    -
    -  var val30 = val.shorten(30);
    -  assertEquals(0xFFFFFFFF | 0, val30.getBits(1));
    -  assertEquals(0xE0000000 | 0, val30.getBits(0));
    -
    -  var val29 = val.shorten(29);
    -  assertEquals(0x00000000 | 0, val29.getBits(1));
    -  assertEquals(0x00000000 | 0, val29.getBits(0));
    -}
    -
    -function testIsZero() {
    -  for (var i = 0; i < TEST_BITS.length; i += 2) {
    -    var val = goog.math.Integer.fromBits([TEST_BITS[i + 1], TEST_BITS[i]]);
    -    assertEquals(TEST_BITS[i] == 0 && TEST_BITS[i + 1] == 0, val.isZero());
    -  }
    -}
    -
    -function testIsNegative() {
    -  for (var i = 0; i < TEST_BITS.length; i += 2) {
    -    var val = goog.math.Integer.fromBits([TEST_BITS[i + 1], TEST_BITS[i]]);
    -    assertEquals((TEST_BITS[i] >> 31) != 0, val.isNegative());
    -  }
    -}
    -
    -function testIsOdd() {
    -  for (var i = 0; i < TEST_BITS.length; i += 2) {
    -    var val = goog.math.Integer.fromBits([TEST_BITS[i + 1], TEST_BITS[i]]);
    -    assertEquals((TEST_BITS[i + 1] & 1) != 0, val.isOdd());
    -  }
    -}
    -
    -function createTestComparisons(i) {
    -  return function() {
    -    var vi = goog.math.Integer.fromBits([TEST_BITS[i + 1], TEST_BITS[i]]);
    -    for (var j = 0; j < TEST_BITS.length; j += 2) {
    -      var vj = goog.math.Integer.fromBits([TEST_BITS[j + 1], TEST_BITS[j]]);
    -      assertEquals(i == j, vi.equals(vj));
    -      assertEquals(i != j, vi.notEquals(vj));
    -      assertEquals(i < j, vi.lessThan(vj));
    -      assertEquals(i <= j, vi.lessThanOrEqual(vj));
    -      assertEquals(i > j, vi.greaterThan(vj));
    -      assertEquals(i >= j, vi.greaterThanOrEqual(vj));
    -    }
    -  };
    -}
    -
    -// Here and below, we translate one conceptual test (e.g., "testComparisons")
    -// into a number of test functions that will be run separately by jsunit. This
    -// is necessary because, in some testing configurations, the full combined test
    -// can take so long that it times out. These smaller tests run much faster.
    -for (var i = 0; i < TEST_BITS.length; i += 2) {
    -  goog.global['testComparisons' + i] = createTestComparisons(i);
    -}
    -
    -function createTestBitOperations(i) {
    -  return function() {
    -    var vi = goog.math.Integer.fromBits([TEST_BITS[i + 1], TEST_BITS[i]]);
    -    assertEquals(~TEST_BITS[i], vi.not().getBits(1));
    -    assertEquals(~TEST_BITS[i + 1], vi.not().getBits(0));
    -
    -    for (var j = 0; j < TEST_BITS.length; j += 2) {
    -      var vj = goog.math.Integer.fromBits([TEST_BITS[j + 1], TEST_BITS[j]]);
    -      assertEquals(TEST_BITS[i] & TEST_BITS[j], vi.and(vj).getBits(1));
    -      assertEquals(TEST_BITS[i + 1] & TEST_BITS[j + 1], vi.and(vj).getBits(0));
    -      assertEquals(TEST_BITS[i] | TEST_BITS[j], vi.or(vj).getBits(1));
    -      assertEquals(TEST_BITS[i + 1] | TEST_BITS[j + 1], vi.or(vj).getBits(0));
    -      assertEquals(TEST_BITS[i] ^ TEST_BITS[j], vi.xor(vj).getBits(1));
    -      assertEquals(TEST_BITS[i + 1] ^ TEST_BITS[j + 1], vi.xor(vj).getBits(0));
    -    }
    -
    -    assertEquals(TEST_BITS[i], vi.shiftLeft(0).getBits(1));
    -    assertEquals(TEST_BITS[i + 1], vi.shiftLeft(0).getBits(0));
    -    assertEquals(TEST_BITS[i], vi.shiftRight(0).getBits(1));
    -    assertEquals(TEST_BITS[i + 1], vi.shiftRight(0).getBits(0));
    -
    -    for (var len = 1; len < 64; ++len) {
    -      if (len < 32) {
    -        assertEquals((TEST_BITS[i] << len) | (TEST_BITS[i + 1] >>> (32 - len)),
    -                     vi.shiftLeft(len).getBits(1));
    -        assertEquals(TEST_BITS[i + 1] << len, vi.shiftLeft(len).getBits(0));
    -
    -        assertEquals(TEST_BITS[i] >> len, vi.shiftRight(len).getBits(1));
    -        assertEquals((TEST_BITS[i + 1] >>> len) | (TEST_BITS[i] << (32 - len)),
    -                     vi.shiftRight(len).getBits(0));
    -      } else {
    -        assertEquals(TEST_BITS[i + 1] << (len - 32),
    -                     vi.shiftLeft(len).getBits(1));
    -        assertEquals(0, vi.shiftLeft(len).getBits(0));
    -
    -        assertEquals(TEST_BITS[i] >= 0 ? 0 : -1, vi.shiftRight(len).getBits(1));
    -        assertEquals(TEST_BITS[i] >> (len - 32), vi.shiftRight(len).getBits(0));
    -      }
    -    }
    -
    -    assertEquals(0, vi.shiftLeft(64).getBits(1));
    -    assertEquals(0, vi.shiftLeft(64).getBits(0));
    -    assertEquals(TEST_BITS[i] & (1 << 31) ? -1 : 0,
    -                 vi.shiftRight(64).getBits(1));
    -    assertEquals(TEST_BITS[i] & (1 << 31) ? -1 : 0,
    -                 vi.shiftRight(64).getBits(0));
    -  };
    -}
    -
    -for (var i = 0; i < TEST_BITS.length; i += 2) {
    -  goog.global['testBitOperations' + i] = createTestBitOperations(i);
    -}
    -
    -function testNegation() {
    -  for (var i = 0; i < TEST_BITS.length; i += 2) {
    -    var vi = goog.math.Integer.fromBits([TEST_BITS[i + 1], TEST_BITS[i]]);
    -    if (TEST_BITS[i + 1] == 0) {
    -      assertEquals((~TEST_BITS[i] + 1) | 0, vi.negate().getBits(1));
    -      assertEquals(0, vi.negate().getBits(0));
    -    } else {
    -      assertEquals(~TEST_BITS[i], vi.negate().getBits(1));
    -      assertEquals((~TEST_BITS[i + 1] + 1) | 0, vi.negate().getBits(0));
    -    }
    -  }
    -}
    -
    -function createTestAdd(i, count) {
    -  return function() {
    -    var vi = goog.math.Integer.fromBits([TEST_BITS[i + 1], TEST_BITS[i]]);
    -    for (var j = 0; j < i; j += 2) {
    -      var vj = goog.math.Integer.fromBits([TEST_BITS[j + 1], TEST_BITS[j]]);
    -      var result = vi.add(vj);
    -      assertEquals(TEST_ADD_BITS[count++], result.getBits(1));
    -      assertEquals(TEST_ADD_BITS[count++], result.getBits(0));
    -    }
    -  };
    -}
    -
    -var countAdd = 0;
    -for (var i = 0; i < TEST_BITS.length; i += 2) {
    -  goog.global['testAdd' + i] = createTestAdd(i, countAdd);
    -  countAdd += i;
    -}
    -
    -function createTestSubtract(i, count) {
    -  return function() {
    -    var vi = goog.math.Integer.fromBits([TEST_BITS[i + 1], TEST_BITS[i]]);
    -    for (var j = 0; j < TEST_BITS.length; j += 2) {
    -      var vj = goog.math.Integer.fromBits([TEST_BITS[j + 1], TEST_BITS[j]]);
    -      var result = vi.subtract(vj);
    -      assertEquals(TEST_SUB_BITS[count++], result.getBits(1));
    -      assertEquals(TEST_SUB_BITS[count++], result.getBits(0));
    -    }
    -  };
    -}
    -
    -var countSubtract = 0;
    -for (var i = 0; i < TEST_BITS.length; i += 2) {
    -  goog.global['testSubtract' + i] = createTestSubtract(i, countSubtract);
    -  countSubtract += TEST_BITS.length;
    -}
    -
    -function createTestMultiply(i, count) {
    -  return function() {
    -    var vi = goog.math.Integer.fromBits([TEST_BITS[i + 1], TEST_BITS[i]]);
    -    for (var j = 0; j < i; j += 2) {
    -      var vj = goog.math.Integer.fromBits([TEST_BITS[j + 1], TEST_BITS[j]]);
    -      var result = vi.multiply(vj);
    -      assertEquals(TEST_MUL_BITS[count++], result.getBits(1));
    -      assertEquals(TEST_MUL_BITS[count++], result.getBits(0));
    -    }
    -  };
    -}
    -
    -var countMultiply = 0;
    -for (var i = 0; i < TEST_BITS.length; i += 2) {
    -  goog.global['testMultiply' + i] = createTestMultiply(i, countMultiply);
    -  countMultiply += i;
    -}
    -
    -function createTestDivMod(i, count) {
    -  return function() {
    -    var vi = goog.math.Integer.fromBits([TEST_BITS[i + 1], TEST_BITS[i]]);
    -    for (var j = 0; j < TEST_BITS.length; j += 2) {
    -      var vj = goog.math.Integer.fromBits([TEST_BITS[j + 1], TEST_BITS[j]]);
    -      if (!vj.isZero()) {
    -        var divResult = vi.divide(vj);
    -        assertEquals(TEST_DIV_BITS[count++], divResult.getBits(1));
    -        assertEquals(TEST_DIV_BITS[count++], divResult.getBits(0));
    -
    -        var modResult = vi.modulo(vj);
    -        var combinedResult = divResult.multiply(vj).add(modResult);
    -        assertTrue(vi.equals(combinedResult));
    -      }
    -    }
    -  };
    -}
    -
    -var countPerDivModCall = 0;
    -for (var j = 0; j < TEST_BITS.length; j += 2) {
    -  var vj = goog.math.Integer.fromBits([TEST_BITS[j + 1], TEST_BITS[j]]);
    -  if (!vj.isZero()) {
    -    countPerDivModCall += 2;
    -  }
    -}
    -
    -var countDivMod = 0;
    -for (var i = 0; i < TEST_BITS.length; i += 2) {
    -  goog.global['testDivMod' + i] = createTestDivMod(i, countDivMod);
    -  countDivMod += countPerDivModCall;
    -}
    -
    -function createTestToFromString(i) {
    -  return function() {
    -    var vi = goog.math.Integer.fromBits([TEST_BITS[i + 1], TEST_BITS[i]]);
    -    var str = vi.toString(10);
    -    assertEquals(TEST_STRINGS[i / 2], str);
    -    assertEquals(TEST_BITS[i],
    -                 goog.math.Integer.fromString(str, 10).getBits(1));
    -    assertEquals(TEST_BITS[i + 1],
    -                 goog.math.Integer.fromString(str, 10).getBits(0));
    -
    -    for (var radix = 2; radix <= 36; ++radix) {
    -      var result = vi.toString(radix);
    -      assertEquals(TEST_BITS[i],
    -                   goog.math.Integer.fromString(result, radix).getBits(1));
    -      assertEquals(TEST_BITS[i + 1],
    -                   goog.math.Integer.fromString(result, radix).getBits(0));
    -    }
    -  };
    -}
    -
    -for (var i = 0; i < TEST_BITS.length; i += 2) {
    -  goog.global['testToFromString' + i] = createTestToFromString(i);
    -}
    -
    -function testBigMultiply() {
    -  var a = goog.math.Integer.fromString('2389428394283434234234');
    -  var b = goog.math.Integer.fromString('895489472863784783');
    -  assertEquals('2139707973242632227811083664960586861222',
    -               a.multiply(b).toString());
    -  assertEquals('2139707973242632227811083664960586861222',
    -               b.multiply(a).toString());
    -
    -  a = goog.math.Integer.fromString('123940932409302930429304');
    -  b = goog.math.Integer.fromString('-23940239409234');
    -  assertEquals('-2967175594482401511466585794961793136',
    -               a.multiply(b).toString());
    -
    -  a = goog.math.Integer.fromString('-4895849540949');
    -  b = goog.math.Integer.fromString('5906390354334334989');
    -  assertEquals('-28916798504933355408364838964561',
    -               a.multiply(b).toString());
    -
    -  a = goog.math.Integer.fromString('-23489238492334893');
    -  b = goog.math.Integer.fromString('-2930482394829348293489234');
    -  assertEquals('68834799869735267747353413198446618041962',
    -               a.multiply(b).toString());
    -
    -  a = goog.math.Integer.fromString('-39403940');
    -  b = goog.math.Integer.fromString('-90689586573473848347384834');
    -  assertEquals('3573527027965969111849451155845960',
    -               a.multiply(b).toString());
    -}
    -
    -function testBigShift() {
    -  var a = goog.math.Integer.fromString('3735928559');
    -  assertEquals('591981510028266767381876356163880091648',
    -               a.shiftLeft(97).toString());
    -  assertEquals('-591981510028266767381876356163880091648',
    -               a.negate().shiftLeft(97).toString());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/math/interpolator/interpolator1.js b/src/database/third_party/closure-library/closure/goog/math/interpolator/interpolator1.js
    deleted file mode 100644
    index d6549790114..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/interpolator/interpolator1.js
    +++ /dev/null
    @@ -1,64 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview The base interface for one-dimensional data interpolation.
    - *
    - */
    -
    -goog.provide('goog.math.interpolator.Interpolator1');
    -
    -
    -
    -/**
    - * An interface for one dimensional data interpolation.
    - * @interface
    - */
    -goog.math.interpolator.Interpolator1 = function() {
    -};
    -
    -
    -/**
    - * Sets the data to be interpolated. Note that the data points are expected
    - * to be sorted according to their abscissa values and not have duplicate
    - * values. E.g. calling setData([0, 0, 1], [1, 1, 3]) may give undefined
    - * results, the correct call should be setData([0, 1], [1, 3]).
    - * Calling setData multiple times does not merge the data samples. The last
    - * call to setData is the one used when computing the interpolation.
    - * @param {!Array<number>} x The abscissa of the data points.
    - * @param {!Array<number>} y The ordinate of the data points.
    - */
    -goog.math.interpolator.Interpolator1.prototype.setData;
    -
    -
    -/**
    - * Computes the interpolated value at abscissa x. If x is outside the range
    - * of the data points passed in setData, the value is extrapolated.
    - * @param {number} x The abscissa to sample at.
    - * @return {number} The interpolated value at abscissa x.
    - */
    -goog.math.interpolator.Interpolator1.prototype.interpolate;
    -
    -
    -/**
    - * Computes the inverse interpolator. That is, it returns invInterp s.t.
    - * this.interpolate(invInterp.interpolate(t))) = t. Note that the inverse
    - * interpolator is only well defined if the data being interpolated is
    - * 'invertible', i.e. it represents a bijective function.
    - * In addition, the returned interpolator is only guaranteed to give the exact
    - * inverse at the input data passed in getData.
    - * If 'this' has no data, the returned Interpolator will be empty as well.
    - * @return {!goog.math.interpolator.Interpolator1} The inverse interpolator.
    - */
    -goog.math.interpolator.Interpolator1.prototype.getInverse;
    diff --git a/src/database/third_party/closure-library/closure/goog/math/interpolator/linear1.js b/src/database/third_party/closure-library/closure/goog/math/interpolator/linear1.js
    deleted file mode 100644
    index ba4824f735d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/interpolator/linear1.js
    +++ /dev/null
    @@ -1,84 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A one dimensional linear interpolator.
    - *
    - */
    -
    -goog.provide('goog.math.interpolator.Linear1');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.math');
    -goog.require('goog.math.interpolator.Interpolator1');
    -
    -
    -
    -/**
    - * A one dimensional linear interpolator.
    - * @implements {goog.math.interpolator.Interpolator1}
    - * @constructor
    - * @final
    - */
    -goog.math.interpolator.Linear1 = function() {
    -  /**
    -   * The abscissa of the data points.
    -   * @type {!Array<number>}
    -   * @private
    -   */
    -  this.x_ = [];
    -
    -  /**
    -   * The ordinate of the data points.
    -   * @type {!Array<number>}
    -   * @private
    -   */
    -  this.y_ = [];
    -};
    -
    -
    -/** @override */
    -goog.math.interpolator.Linear1.prototype.setData = function(x, y) {
    -  goog.asserts.assert(x.length == y.length,
    -      'input arrays to setData should have the same length');
    -  if (x.length == 1) {
    -    this.x_ = [x[0], x[0] + 1];
    -    this.y_ = [y[0], y[0]];
    -  } else {
    -    this.x_ = x.slice();
    -    this.y_ = y.slice();
    -  }
    -};
    -
    -
    -/** @override */
    -goog.math.interpolator.Linear1.prototype.interpolate = function(x) {
    -  var pos = goog.array.binarySearch(this.x_, x);
    -  if (pos < 0) {
    -    pos = -pos - 2;
    -  }
    -  pos = goog.math.clamp(pos, 0, this.x_.length - 2);
    -
    -  var progress = (x - this.x_[pos]) / (this.x_[pos + 1] - this.x_[pos]);
    -  return goog.math.lerp(this.y_[pos], this.y_[pos + 1], progress);
    -};
    -
    -
    -/** @override */
    -goog.math.interpolator.Linear1.prototype.getInverse = function() {
    -  var interpolator = new goog.math.interpolator.Linear1();
    -  interpolator.setData(this.y_, this.x_);
    -  return interpolator;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/math/interpolator/linear1_test.html b/src/database/third_party/closure-library/closure/goog/math/interpolator/linear1_test.html
    deleted file mode 100644
    index 3ab7978f540..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/interpolator/linear1_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.math.interpolator.Linear1
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.math.interpolator.Linear1Test');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/math/interpolator/linear1_test.js b/src/database/third_party/closure-library/closure/goog/math/interpolator/linear1_test.js
    deleted file mode 100644
    index 472c991b502..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/interpolator/linear1_test.js
    +++ /dev/null
    @@ -1,84 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.math.interpolator.Linear1Test');
    -goog.setTestOnly('goog.math.interpolator.Linear1Test');
    -
    -goog.require('goog.math.interpolator.Linear1');
    -goog.require('goog.testing.jsunit');
    -
    -function testLinear() {
    -  // Test special case with no data to interpolate.
    -  var x = [];
    -  var y = [];
    -  var interp = new goog.math.interpolator.Linear1();
    -  interp.setData(x, y);
    -  assertTrue(isNaN(interp.interpolate(1)));
    -
    -  // Test special case with 1 data point.
    -  x = [0];
    -  y = [3];
    -  interp = new goog.math.interpolator.Linear1();
    -  interp.setData(x, y);
    -  assertRoughlyEquals(3, interp.interpolate(1), 1e-4);
    -
    -  // Test general case.
    -  x = [0, 1, 3, 6, 7];
    -  y = [0, 0, 0, 0, 0];
    -  for (var i = 0; i < x.length; ++i) {
    -    y[i] = Math.sin(x[i]);
    -  }
    -  interp = new goog.math.interpolator.Linear1();
    -  interp.setData(x, y);
    -
    -  var xi = [0, 0.5, 1, 2, 3, 4, 5, 6, 7];
    -  var expected = [0, 0.4207, 0.8415, 0.4913, 0.1411, 0.0009, -0.1392,
    -    -0.2794, 0.657];
    -  var result = [0, 0, 0, 0, 0, 0, 0, 0, 0];
    -  for (var i = 0; i < xi.length; ++i) {
    -    result[i] = interp.interpolate(xi[i]);
    -  }
    -  assertElementsRoughlyEqual(expected, result, 1e-4);
    -}
    -
    -
    -function testOutOfBounds() {
    -  var x = [0, 1, 2];
    -  var y = [2, 5, 4];
    -  var interp = new goog.math.interpolator.Linear1();
    -  interp.setData(x, y);
    -  assertRoughlyEquals(interp.interpolate(-1), -1, 1e-4);
    -  assertRoughlyEquals(interp.interpolate(4), 2, 1e-4);
    -}
    -
    -
    -function testInverse() {
    -  var x = [0, 1, 3, 6, 7];
    -  var y = [0, 2, 7, 8, 10];
    -
    -  var interp = new goog.math.interpolator.Linear1();
    -  interp.setData(x, y);
    -  var invInterp = interp.getInverse();
    -
    -  var xi = [0, 0.5, 1, 2, 3, 4, 5, 6, 7];
    -  var yi = [0, 1, 2, 4.5, 7, 7.3333, 7.6667, 8, 10];
    -  var resultX = [0, 0, 0, 0, 0, 0, 0, 0, 0];
    -  var resultY = [0, 0, 0, 0, 0, 0, 0, 0, 0];
    -  for (var i = 0; i < xi.length; ++i) {
    -    resultY[i] = interp.interpolate(xi[i]);
    -    resultX[i] = invInterp.interpolate(yi[i]);
    -  }
    -  assertElementsRoughlyEqual(xi, resultX, 1e-4);
    -  assertElementsRoughlyEqual(yi, resultY, 1e-4);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/math/interpolator/pchip1.js b/src/database/third_party/closure-library/closure/goog/math/interpolator/pchip1.js
    deleted file mode 100644
    index 0c3a56ea38f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/interpolator/pchip1.js
    +++ /dev/null
    @@ -1,82 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A one dimensional monotone cubic spline interpolator.
    - *
    - * See http://en.wikipedia.org/wiki/Monotone_cubic_interpolation.
    - *
    - */
    -
    -goog.provide('goog.math.interpolator.Pchip1');
    -
    -goog.require('goog.math');
    -goog.require('goog.math.interpolator.Spline1');
    -
    -
    -
    -/**
    - * A one dimensional monotone cubic spline interpolator.
    - * @extends {goog.math.interpolator.Spline1}
    - * @constructor
    - * @final
    - */
    -goog.math.interpolator.Pchip1 = function() {
    -  goog.math.interpolator.Pchip1.base(this, 'constructor');
    -};
    -goog.inherits(goog.math.interpolator.Pchip1, goog.math.interpolator.Spline1);
    -
    -
    -/** @override */
    -goog.math.interpolator.Pchip1.prototype.computeDerivatives = function(
    -    dx, slope) {
    -  var len = dx.length;
    -  var deriv = new Array(len + 1);
    -  for (var i = 1; i < len; ++i) {
    -    if (goog.math.sign(slope[i - 1]) * goog.math.sign(slope[i]) <= 0) {
    -      deriv[i] = 0;
    -    } else {
    -      var w1 = 2 * dx[i] + dx[i - 1];
    -      var w2 = dx[i] + 2 * dx[i - 1];
    -      deriv[i] = (w1 + w2) / (w1 / slope[i - 1] + w2 / slope[i]);
    -    }
    -  }
    -  deriv[0] = this.computeDerivativeAtBoundary_(
    -      dx[0], dx[1], slope[0], slope[1]);
    -  deriv[len] = this.computeDerivativeAtBoundary_(
    -      dx[len - 1], dx[len - 2], slope[len - 1], slope[len - 2]);
    -  return deriv;
    -};
    -
    -
    -/**
    - * Computes the derivative of a data point at a boundary.
    - * @param {number} dx0 The spacing of the 1st data point.
    - * @param {number} dx1 The spacing of the 2nd data point.
    - * @param {number} slope0 The slope of the 1st data point.
    - * @param {number} slope1 The slope of the 2nd data point.
    - * @return {number} The derivative at the 1st data point.
    - * @private
    - */
    -goog.math.interpolator.Pchip1.prototype.computeDerivativeAtBoundary_ = function(
    -    dx0, dx1, slope0, slope1) {
    -  var deriv = ((2 * dx0 + dx1) * slope0 - dx0 * slope1) / (dx0 + dx1);
    -  if (goog.math.sign(deriv) != goog.math.sign(slope0)) {
    -    deriv = 0;
    -  } else if (goog.math.sign(slope0) != goog.math.sign(slope1) &&
    -      Math.abs(deriv) > Math.abs(3 * slope0)) {
    -    deriv = 3 * slope0;
    -  }
    -  return deriv;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/math/interpolator/pchip1_test.html b/src/database/third_party/closure-library/closure/goog/math/interpolator/pchip1_test.html
    deleted file mode 100644
    index 236648dccc5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/interpolator/pchip1_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.math.interpolator.Pchip1
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.math.interpolator.Pchip1Test');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/math/interpolator/pchip1_test.js b/src/database/third_party/closure-library/closure/goog/math/interpolator/pchip1_test.js
    deleted file mode 100644
    index f7920bbd7e9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/interpolator/pchip1_test.js
    +++ /dev/null
    @@ -1,71 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.math.interpolator.Pchip1Test');
    -goog.setTestOnly('goog.math.interpolator.Pchip1Test');
    -
    -goog.require('goog.math.interpolator.Pchip1');
    -goog.require('goog.testing.jsunit');
    -
    -function testSpline() {
    -  var x = [0, 1, 3, 6, 7];
    -  var y = [0, 0, 0, 0, 0];
    -
    -  for (var i = 0; i < x.length; ++i) {
    -    y[i] = Math.sin(x[i]);
    -  }
    -  var interp = new goog.math.interpolator.Pchip1();
    -  interp.setData(x, y);
    -
    -  var xi = [0, 0.5, 1, 2, 3, 4, 5, 6, 7];
    -  var expected = [0, 0.5756, 0.8415, 0.5428, 0.1411, -0.0595, -0.2162,
    -    -0.2794, 0.657];
    -  var result = [0, 0, 0, 0, 0, 0, 0, 0, 0];
    -  for (var i = 0; i < xi.length; ++i) {
    -    result[i] = interp.interpolate(xi[i]);
    -  }
    -  assertElementsRoughlyEqual(expected, result, 1e-4);
    -}
    -
    -
    -function testOutOfBounds() {
    -  var x = [0, 1, 2, 4];
    -  var y = [2, 5, 4, 2];
    -  var interp = new goog.math.interpolator.Pchip1();
    -  interp.setData(x, y);
    -  assertRoughlyEquals(-3, interp.interpolate(-1), 1e-4);
    -  assertRoughlyEquals(1, interp.interpolate(5), 1e-4);
    -}
    -
    -
    -function testInverse() {
    -  var x = [0, 1, 3, 6, 7];
    -  var y = [0, 2, 7, 8, 10];
    -
    -  var interp = new goog.math.interpolator.Pchip1();
    -  interp.setData(x, y);
    -  var invInterp = interp.getInverse();
    -
    -  var xi = [0, 0.5, 1, 2, 3, 4, 5, 6, 7];
    -  var yi = [0, 0.9548, 2, 4.8938, 7, 7.3906, 7.5902, 8, 10];
    -  var expectedX = [0, 0.888, 1, 0.2852, 3, 4.1206, 4.7379, 6, 7];
    -  var resultX = [0, 0, 0, 0, 0, 0, 0, 0, 0];
    -  var resultY = [0, 0, 0, 0, 0, 0, 0, 0, 0];
    -  for (var i = 0; i < xi.length; ++i) {
    -    resultY[i] = interp.interpolate(xi[i]);
    -    resultX[i] = invInterp.interpolate(yi[i]);
    -  }
    -  assertElementsRoughlyEqual(expectedX, resultX, 1e-4);
    -  assertElementsRoughlyEqual(yi, resultY, 1e-4);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/math/interpolator/spline1.js b/src/database/third_party/closure-library/closure/goog/math/interpolator/spline1.js
    deleted file mode 100644
    index c0a4435b0b0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/interpolator/spline1.js
    +++ /dev/null
    @@ -1,203 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A one dimensional cubic spline interpolator with not-a-knot
    - * boundary conditions.
    - *
    - * See http://en.wikipedia.org/wiki/Spline_interpolation.
    - *
    - */
    -
    -goog.provide('goog.math.interpolator.Spline1');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.math');
    -goog.require('goog.math.interpolator.Interpolator1');
    -goog.require('goog.math.tdma');
    -
    -
    -
    -/**
    - * A one dimensional cubic spline interpolator with natural boundary conditions.
    - * @implements {goog.math.interpolator.Interpolator1}
    - * @constructor
    - */
    -goog.math.interpolator.Spline1 = function() {
    -  /**
    -   * The abscissa of the data points.
    -   * @type {!Array<number>}
    -   * @private
    -   */
    -  this.x_ = [];
    -
    -  /**
    -   * The spline interval coefficients.
    -   * Note that, in general, the length of coeffs and x is not the same.
    -   * @type {!Array<!Array<number>>}
    -   * @private
    -   */
    -  this.coeffs_ = [[0, 0, 0, Number.NaN]];
    -};
    -
    -
    -/** @override */
    -goog.math.interpolator.Spline1.prototype.setData = function(x, y) {
    -  goog.asserts.assert(x.length == y.length,
    -      'input arrays to setData should have the same length');
    -  if (x.length > 0) {
    -    this.coeffs_ = this.computeSplineCoeffs_(x, y);
    -    this.x_ = x.slice();
    -  } else {
    -    this.coeffs_ = [[0, 0, 0, Number.NaN]];
    -    this.x_ = [];
    -  }
    -};
    -
    -
    -/** @override */
    -goog.math.interpolator.Spline1.prototype.interpolate = function(x) {
    -  var pos = goog.array.binarySearch(this.x_, x);
    -  if (pos < 0) {
    -    pos = -pos - 2;
    -  }
    -  pos = goog.math.clamp(pos, 0, this.coeffs_.length - 1);
    -
    -  var d = x - this.x_[pos];
    -  var d2 = d * d;
    -  var d3 = d2 * d;
    -  var coeffs = this.coeffs_[pos];
    -  return coeffs[0] * d3 + coeffs[1] * d2 + coeffs[2] * d + coeffs[3];
    -};
    -
    -
    -/**
    - * Solve for the spline coefficients such that the spline precisely interpolates
    - * the data points.
    - * @param {Array<number>} x The abscissa of the spline data points.
    - * @param {Array<number>} y The ordinate of the spline data points.
    - * @return {!Array<!Array<number>>} The spline interval coefficients.
    - * @private
    - */
    -goog.math.interpolator.Spline1.prototype.computeSplineCoeffs_ = function(x, y) {
    -  var nIntervals = x.length - 1;
    -  var dx = new Array(nIntervals);
    -  var delta = new Array(nIntervals);
    -  for (var i = 0; i < nIntervals; ++i) {
    -    dx[i] = x[i + 1] - x[i];
    -    delta[i] = (y[i + 1] - y[i]) / dx[i];
    -  }
    -
    -  // Compute the spline coefficients from the 1st order derivatives.
    -  var coeffs = [];
    -  if (nIntervals == 0) {
    -    // Nearest neighbor interpolation.
    -    coeffs[0] = [0, 0, 0, y[0]];
    -  } else if (nIntervals == 1) {
    -    // Straight line interpolation.
    -    coeffs[0] = [0, 0, delta[0], y[0]];
    -  } else if (nIntervals == 2) {
    -    // Parabola interpolation.
    -    var c3 = 0;
    -    var c2 = (delta[1] - delta[0]) / (dx[0] + dx[1]);
    -    var c1 = delta[0] - c2 * dx[0];
    -    var c0 = y[0];
    -    coeffs[0] = [c3, c2, c1, c0];
    -  } else {
    -    // General Spline interpolation. Compute the 1st order derivatives from
    -    // the Spline equations.
    -    var deriv = this.computeDerivatives(dx, delta);
    -    for (var i = 0; i < nIntervals; ++i) {
    -      var c3 = (deriv[i] - 2 * delta[i] + deriv[i + 1]) / (dx[i] * dx[i]);
    -      var c2 = (3 * delta[i] - 2 * deriv[i] - deriv[i + 1]) / dx[i];
    -      var c1 = deriv[i];
    -      var c0 = y[i];
    -      coeffs[i] = [c3, c2, c1, c0];
    -    }
    -  }
    -  return coeffs;
    -};
    -
    -
    -/**
    - * Computes the derivative at each point of the spline such that
    - * the curve is C2. It uses not-a-knot boundary conditions.
    - * @param {Array<number>} dx The spacing between consecutive data points.
    - * @param {Array<number>} slope The slopes between consecutive data points.
    - * @return {!Array<number>} The Spline derivative at each data point.
    - * @protected
    - */
    -goog.math.interpolator.Spline1.prototype.computeDerivatives = function(
    -    dx, slope) {
    -  var nIntervals = dx.length;
    -
    -  // Compute the main diagonal of the system of equations.
    -  var mainDiag = new Array(nIntervals + 1);
    -  mainDiag[0] = dx[1];
    -  for (var i = 1; i < nIntervals; ++i) {
    -    mainDiag[i] = 2 * (dx[i] + dx[i - 1]);
    -  }
    -  mainDiag[nIntervals] = dx[nIntervals - 2];
    -
    -  // Compute the sub diagonal of the system of equations.
    -  var subDiag = new Array(nIntervals);
    -  for (var i = 0; i < nIntervals; ++i) {
    -    subDiag[i] = dx[i + 1];
    -  }
    -  subDiag[nIntervals - 1] = dx[nIntervals - 2] + dx[nIntervals - 1];
    -
    -  // Compute the super diagonal of the system of equations.
    -  var supDiag = new Array(nIntervals);
    -  supDiag[0] = dx[0] + dx[1];
    -  for (var i = 1; i < nIntervals; ++i) {
    -    supDiag[i] = dx[i - 1];
    -  }
    -
    -  // Compute the right vector of the system of equations.
    -  var vecRight = new Array(nIntervals + 1);
    -  vecRight[0] = ((dx[0] + 2 * supDiag[0]) * dx[1] * slope[0] +
    -      dx[0] * dx[0] * slope[1]) / supDiag[0];
    -  for (var i = 1; i < nIntervals; ++i) {
    -    vecRight[i] = 3 * (dx[i] * slope[i - 1] + dx[i - 1] * slope[i]);
    -  }
    -  vecRight[nIntervals] = (dx[nIntervals - 1] * dx[nIntervals - 1] *
    -      slope[nIntervals - 2] + (2 * subDiag[nIntervals - 1] +
    -      dx[nIntervals - 1]) * dx[nIntervals - 2] * slope[nIntervals - 1]) /
    -      subDiag[nIntervals - 1];
    -
    -  // Solve the system of equations.
    -  var deriv = goog.math.tdma.solve(
    -      subDiag, mainDiag, supDiag, vecRight);
    -
    -  return deriv;
    -};
    -
    -
    -/**
    - * Note that the inverse of a cubic spline is not a cubic spline in general.
    - * As a result the inverse implementation is only approximate. In
    - * particular, it only guarantees the exact inverse at the original input data
    - * points passed to setData.
    - * @override
    - */
    -goog.math.interpolator.Spline1.prototype.getInverse = function() {
    -  var interpolator = new goog.math.interpolator.Spline1();
    -  var y = [];
    -  for (var i = 0; i < this.x_.length; i++) {
    -    y[i] = this.interpolate(this.x_[i]);
    -  }
    -  interpolator.setData(y, this.x_);
    -  return interpolator;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/math/interpolator/spline1_test.html b/src/database/third_party/closure-library/closure/goog/math/interpolator/spline1_test.html
    deleted file mode 100644
    index 91a17011e8c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/interpolator/spline1_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.math.interpolator.Spline1
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.math.interpolator.Spline1Test');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/math/interpolator/spline1_test.js b/src/database/third_party/closure-library/closure/goog/math/interpolator/spline1_test.js
    deleted file mode 100644
    index 0c7383e5c3a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/interpolator/spline1_test.js
    +++ /dev/null
    @@ -1,100 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.math.interpolator.Spline1Test');
    -goog.setTestOnly('goog.math.interpolator.Spline1Test');
    -
    -goog.require('goog.math.interpolator.Spline1');
    -goog.require('goog.testing.jsunit');
    -
    -function testSpline() {
    -  // Test special case with no data to interpolate.
    -  var x = [];
    -  var y = [];
    -  var interp = new goog.math.interpolator.Spline1();
    -  interp.setData(x, y);
    -  assertTrue(isNaN(interp.interpolate(1)));
    -
    -  // Test special case with 1 data point.
    -  x = [0];
    -  y = [2];
    -  interp = new goog.math.interpolator.Spline1();
    -  interp.setData(x, y);
    -  assertRoughlyEquals(2, interp.interpolate(1), 1e-4);
    -
    -  // Test special case with 2 data points.
    -  x = [0, 1];
    -  y = [2, 5];
    -  interp = new goog.math.interpolator.Spline1();
    -  interp.setData(x, y);
    -  assertRoughlyEquals(3.5, interp.interpolate(.5), 1e-4);
    -
    -  // Test special case with 3 data points.
    -  x = [0, 1, 2];
    -  y = [2, 5, 4];
    -  interp = new goog.math.interpolator.Spline1();
    -  interp.setData(x, y);
    -  assertRoughlyEquals(4, interp.interpolate(.5), 1e-4);
    -  assertRoughlyEquals(-1, interp.interpolate(3), 1e-4);
    -
    -  // Test general case.
    -  x = [0, 1, 3, 6, 7];
    -  y = [0, 0, 0, 0, 0];
    -  for (var i = 0; i < x.length; ++i) {
    -    y[i] = Math.sin(x[i]);
    -  }
    -  interp = new goog.math.interpolator.Spline1();
    -  interp.setData(x, y);
    -
    -  var xi = [0, 0.5, 1, 2, 3, 4, 5, 6, 7];
    -  var expected = [0, 0.5775, 0.8415, 0.7047, 0.1411, -0.3601, -0.55940,
    -    -0.2794, 0.6570];
    -  var result = [0, 0, 0, 0, 0, 0, 0, 0, 0];
    -  for (var i = 0; i < xi.length; ++i) {
    -    result[i] = interp.interpolate(xi[i]);
    -  }
    -  assertElementsRoughlyEqual(expected, result, 1e-4);
    -}
    -
    -
    -function testOutOfBounds() {
    -  var x = [0, 1, 2, 4];
    -  var y = [2, 5, 4, 1];
    -  var interp = new goog.math.interpolator.Spline1();
    -  interp.setData(x, y);
    -  assertRoughlyEquals(-7.75, interp.interpolate(-1), 1e-4);
    -  assertRoughlyEquals(4.5, interp.interpolate(5), 1e-4);
    -}
    -
    -
    -function testInverse() {
    -  var x = [0, 1, 3, 6, 7];
    -  var y = [0, 2, 7, 8, 10];
    -
    -  var interp = new goog.math.interpolator.Spline1();
    -  interp.setData(x, y);
    -  var invInterp = interp.getInverse();
    -
    -  var xi = [0, 0.5, 1, 2, 3, 4, 5, 6, 7];
    -  var yi = [0, 0.8159, 2, 4.7892, 7, 7.6912, 7.6275, 8, 10];
    -  var expectedX = [0, 0.8142, 1, 0.2638, 3, 5.0534, 4.8544, 6, 7];
    -  var resultX = [0, 0, 0, 0, 0, 0, 0, 0, 0];
    -  var resultY = [0, 0, 0, 0, 0, 0, 0, 0, 0];
    -  for (var i = 0; i < xi.length; ++i) {
    -    resultY[i] = interp.interpolate(xi[i]);
    -    resultX[i] = invInterp.interpolate(yi[i]);
    -  }
    -  assertElementsRoughlyEqual(expectedX, resultX, 1e-4);
    -  assertElementsRoughlyEqual(yi, resultY, 1e-4);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/math/line.js b/src/database/third_party/closure-library/closure/goog/math/line.js
    deleted file mode 100644
    index fe4e45c4c9e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/line.js
    +++ /dev/null
    @@ -1,179 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Represents a line in 2D space.
    - *
    - * @author robbyw@google.com (Robby Walker)
    - */
    -
    -goog.provide('goog.math.Line');
    -
    -goog.require('goog.math');
    -goog.require('goog.math.Coordinate');
    -
    -
    -
    -/**
    - * Object representing a line.
    - * @param {number} x0 X coordinate of the start point.
    - * @param {number} y0 Y coordinate of the start point.
    - * @param {number} x1 X coordinate of the end point.
    - * @param {number} y1 Y coordinate of the end point.
    - * @struct
    - * @constructor
    - * @final
    - */
    -goog.math.Line = function(x0, y0, x1, y1) {
    -  /**
    -   * X coordinate of the first point.
    -   * @type {number}
    -   */
    -  this.x0 = x0;
    -
    -  /**
    -   * Y coordinate of the first point.
    -   * @type {number}
    -   */
    -  this.y0 = y0;
    -
    -  /**
    -   * X coordinate of the first control point.
    -   * @type {number}
    -   */
    -  this.x1 = x1;
    -
    -  /**
    -   * Y coordinate of the first control point.
    -   * @type {number}
    -   */
    -  this.y1 = y1;
    -};
    -
    -
    -/**
    - * @return {!goog.math.Line} A copy of this line.
    - */
    -goog.math.Line.prototype.clone = function() {
    -  return new goog.math.Line(this.x0, this.y0, this.x1, this.y1);
    -};
    -
    -
    -/**
    - * Tests whether the given line is exactly the same as this one.
    - * @param {goog.math.Line} other The other line.
    - * @return {boolean} Whether the given line is the same as this one.
    - */
    -goog.math.Line.prototype.equals = function(other) {
    -  return this.x0 == other.x0 && this.y0 == other.y0 &&
    -         this.x1 == other.x1 && this.y1 == other.y1;
    -};
    -
    -
    -/**
    - * @return {number} The squared length of the line segment used to define the
    - *     line.
    - */
    -goog.math.Line.prototype.getSegmentLengthSquared = function() {
    -  var xdist = this.x1 - this.x0;
    -  var ydist = this.y1 - this.y0;
    -  return xdist * xdist + ydist * ydist;
    -};
    -
    -
    -/**
    - * @return {number} The length of the line segment used to define the line.
    - */
    -goog.math.Line.prototype.getSegmentLength = function() {
    -  return Math.sqrt(this.getSegmentLengthSquared());
    -};
    -
    -
    -/**
    - * Computes the interpolation parameter for the point on the line closest to
    - * a given point.
    - * @param {number|goog.math.Coordinate} x The x coordinate of the point, or
    - *     a coordinate object.
    - * @param {number=} opt_y The y coordinate of the point - required if x is a
    - *     number, ignored if x is a goog.math.Coordinate.
    - * @return {number} The interpolation parameter of the point on the line
    - *     closest to the given point.
    - * @private
    - */
    -goog.math.Line.prototype.getClosestLinearInterpolation_ = function(x, opt_y) {
    -  var y;
    -  if (x instanceof goog.math.Coordinate) {
    -    y = x.y;
    -    x = x.x;
    -  } else {
    -    y = opt_y;
    -  }
    -
    -  var x0 = this.x0;
    -  var y0 = this.y0;
    -
    -  var xChange = this.x1 - x0;
    -  var yChange = this.y1 - y0;
    -
    -  return ((x - x0) * xChange + (y - y0) * yChange) /
    -      this.getSegmentLengthSquared();
    -};
    -
    -
    -/**
    - * Returns the point on the line segment proportional to t, where for t = 0 we
    - * return the starting point and for t = 1 we return the end point.  For t < 0
    - * or t > 1 we extrapolate along the line defined by the line segment.
    - * @param {number} t The interpolation parameter along the line segment.
    - * @return {!goog.math.Coordinate} The point on the line segment at t.
    - */
    -goog.math.Line.prototype.getInterpolatedPoint = function(t) {
    -  return new goog.math.Coordinate(
    -      goog.math.lerp(this.x0, this.x1, t),
    -      goog.math.lerp(this.y0, this.y1, t));
    -};
    -
    -
    -/**
    - * Computes the point on the line closest to a given point.  Note that a line
    - * in this case is defined as the infinite line going through the start and end
    - * points.  To find the closest point on the line segment itself see
    - * {@see #getClosestSegmentPoint}.
    - * @param {number|goog.math.Coordinate} x The x coordinate of the point, or
    - *     a coordinate object.
    - * @param {number=} opt_y The y coordinate of the point - required if x is a
    - *     number, ignored if x is a goog.math.Coordinate.
    - * @return {!goog.math.Coordinate} The point on the line closest to the given
    - *     point.
    - */
    -goog.math.Line.prototype.getClosestPoint = function(x, opt_y) {
    -  return this.getInterpolatedPoint(
    -      this.getClosestLinearInterpolation_(x, opt_y));
    -};
    -
    -
    -/**
    - * Computes the point on the line segment closest to a given point.
    - * @param {number|goog.math.Coordinate} x The x coordinate of the point, or
    - *     a coordinate object.
    - * @param {number=} opt_y The y coordinate of the point - required if x is a
    - *     number, ignored if x is a goog.math.Coordinate.
    - * @return {!goog.math.Coordinate} The point on the line segment closest to the
    - *     given point.
    - */
    -goog.math.Line.prototype.getClosestSegmentPoint = function(x, opt_y) {
    -  return this.getInterpolatedPoint(
    -      goog.math.clamp(this.getClosestLinearInterpolation_(x, opt_y), 0, 1));
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/math/line_test.html b/src/database/third_party/closure-library/closure/goog/math/line_test.html
    deleted file mode 100644
    index f73ecadf0af..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/line_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.math.Line
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.math.LineTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/math/line_test.js b/src/database/third_party/closure-library/closure/goog/math/line_test.js
    deleted file mode 100644
    index 13e613bc89c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/line_test.js
    +++ /dev/null
    @@ -1,59 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.math.LineTest');
    -goog.setTestOnly('goog.math.LineTest');
    -
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.math.Line');
    -goog.require('goog.testing.jsunit');
    -
    -function testEquals() {
    -  var input = new goog.math.Line(1, 2, 3, 4);
    -
    -  assert(input.equals(input));
    -}
    -
    -function testClone() {
    -  var input = new goog.math.Line(1, 2, 3, 4);
    -
    -  assertNotEquals('Clone returns a new object', input, input.clone());
    -  assertTrue('Contents of clone match original', input.equals(input.clone()));
    -}
    -
    -function testGetLength() {
    -  var input = new goog.math.Line(0, 0, Math.sqrt(2), Math.sqrt(2));
    -  assertRoughlyEquals(input.getSegmentLengthSquared(), 4, 1e-10);
    -  assertRoughlyEquals(input.getSegmentLength(), 2, 1e-10);
    -}
    -
    -function testGetClosestPoint() {
    -  var input = new goog.math.Line(0, 1, 1, 2);
    -
    -  var point = input.getClosestPoint(0, 3);
    -  assertRoughlyEquals(point.x, 1, 1e-10);
    -  assertRoughlyEquals(point.y, 2, 1e-10);
    -}
    -
    -function testGetClosestSegmentPoint() {
    -  var input = new goog.math.Line(0, 1, 2, 3);
    -
    -  var point = input.getClosestSegmentPoint(4, 4);
    -  assertRoughlyEquals(point.x, 2, 1e-10);
    -  assertRoughlyEquals(point.y, 3, 1e-10);
    -
    -  point = input.getClosestSegmentPoint(new goog.math.Coordinate(-1, -10));
    -  assertRoughlyEquals(point.x, 0, 1e-10);
    -  assertRoughlyEquals(point.y, 1, 1e-10);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/math/long.js b/src/database/third_party/closure-library/closure/goog/math/long.js
    deleted file mode 100644
    index 1bb4be9b318..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/long.js
    +++ /dev/null
    @@ -1,804 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Defines a Long class for representing a 64-bit two's-complement
    - * integer value, which faithfully simulates the behavior of a Java "long". This
    - * implementation is derived from LongLib in GWT.
    - *
    - */
    -
    -goog.provide('goog.math.Long');
    -
    -
    -
    -/**
    - * Constructs a 64-bit two's-complement integer, given its low and high 32-bit
    - * values as *signed* integers.  See the from* functions below for more
    - * convenient ways of constructing Longs.
    - *
    - * The internal representation of a long is the two given signed, 32-bit values.
    - * We use 32-bit pieces because these are the size of integers on which
    - * Javascript performs bit-operations.  For operations like addition and
    - * multiplication, we split each number into 16-bit pieces, which can easily be
    - * multiplied within Javascript's floating-point representation without overflow
    - * or change in sign.
    - *
    - * In the algorithms below, we frequently reduce the negative case to the
    - * positive case by negating the input(s) and then post-processing the result.
    - * Note that we must ALWAYS check specially whether those values are MIN_VALUE
    - * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as
    - * a positive number, it overflows back into a negative).  Not handling this
    - * case would often result in infinite recursion.
    - *
    - * @param {number} low  The low (signed) 32 bits of the long.
    - * @param {number} high  The high (signed) 32 bits of the long.
    - * @struct
    - * @constructor
    - * @final
    - */
    -goog.math.Long = function(low, high) {
    -  /**
    -   * @type {number}
    -   * @private
    -   */
    -  this.low_ = low | 0;  // force into 32 signed bits.
    -
    -  /**
    -   * @type {number}
    -   * @private
    -   */
    -  this.high_ = high | 0;  // force into 32 signed bits.
    -};
    -
    -
    -// NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the
    -// from* methods on which they depend.
    -
    -
    -/**
    - * A cache of the Long representations of small integer values.
    - * @type {!Object}
    - * @private
    - */
    -goog.math.Long.IntCache_ = {};
    -
    -
    -/**
    - * Returns a Long representing the given (32-bit) integer value.
    - * @param {number} value The 32-bit integer in question.
    - * @return {!goog.math.Long} The corresponding Long value.
    - */
    -goog.math.Long.fromInt = function(value) {
    -  if (-128 <= value && value < 128) {
    -    var cachedObj = goog.math.Long.IntCache_[value];
    -    if (cachedObj) {
    -      return cachedObj;
    -    }
    -  }
    -
    -  var obj = new goog.math.Long(value | 0, value < 0 ? -1 : 0);
    -  if (-128 <= value && value < 128) {
    -    goog.math.Long.IntCache_[value] = obj;
    -  }
    -  return obj;
    -};
    -
    -
    -/**
    - * Returns a Long representing the given value, provided that it is a finite
    - * number.  Otherwise, zero is returned.
    - * @param {number} value The number in question.
    - * @return {!goog.math.Long} The corresponding Long value.
    - */
    -goog.math.Long.fromNumber = function(value) {
    -  if (isNaN(value) || !isFinite(value)) {
    -    return goog.math.Long.ZERO;
    -  } else if (value <= -goog.math.Long.TWO_PWR_63_DBL_) {
    -    return goog.math.Long.MIN_VALUE;
    -  } else if (value + 1 >= goog.math.Long.TWO_PWR_63_DBL_) {
    -    return goog.math.Long.MAX_VALUE;
    -  } else if (value < 0) {
    -    return goog.math.Long.fromNumber(-value).negate();
    -  } else {
    -    return new goog.math.Long(
    -        (value % goog.math.Long.TWO_PWR_32_DBL_) | 0,
    -        (value / goog.math.Long.TWO_PWR_32_DBL_) | 0);
    -  }
    -};
    -
    -
    -/**
    - * Returns a Long representing the 64-bit integer that comes by concatenating
    - * the given high and low bits.  Each is assumed to use 32 bits.
    - * @param {number} lowBits The low 32-bits.
    - * @param {number} highBits The high 32-bits.
    - * @return {!goog.math.Long} The corresponding Long value.
    - */
    -goog.math.Long.fromBits = function(lowBits, highBits) {
    -  return new goog.math.Long(lowBits, highBits);
    -};
    -
    -
    -/**
    - * Returns a Long representation of the given string, written using the given
    - * radix.
    - * @param {string} str The textual representation of the Long.
    - * @param {number=} opt_radix The radix in which the text is written.
    - * @return {!goog.math.Long} The corresponding Long value.
    - */
    -goog.math.Long.fromString = function(str, opt_radix) {
    -  if (str.length == 0) {
    -    throw Error('number format error: empty string');
    -  }
    -
    -  var radix = opt_radix || 10;
    -  if (radix < 2 || 36 < radix) {
    -    throw Error('radix out of range: ' + radix);
    -  }
    -
    -  if (str.charAt(0) == '-') {
    -    return goog.math.Long.fromString(str.substring(1), radix).negate();
    -  } else if (str.indexOf('-') >= 0) {
    -    throw Error('number format error: interior "-" character: ' + str);
    -  }
    -
    -  // Do several (8) digits each time through the loop, so as to
    -  // minimize the calls to the very expensive emulated div.
    -  var radixToPower = goog.math.Long.fromNumber(Math.pow(radix, 8));
    -
    -  var result = goog.math.Long.ZERO;
    -  for (var i = 0; i < str.length; i += 8) {
    -    var size = Math.min(8, str.length - i);
    -    var value = parseInt(str.substring(i, i + size), radix);
    -    if (size < 8) {
    -      var power = goog.math.Long.fromNumber(Math.pow(radix, size));
    -      result = result.multiply(power).add(goog.math.Long.fromNumber(value));
    -    } else {
    -      result = result.multiply(radixToPower);
    -      result = result.add(goog.math.Long.fromNumber(value));
    -    }
    -  }
    -  return result;
    -};
    -
    -
    -// NOTE: the compiler should inline these constant values below and then remove
    -// these variables, so there should be no runtime penalty for these.
    -
    -
    -/**
    - * Number used repeated below in calculations.  This must appear before the
    - * first call to any from* function below.
    - * @type {number}
    - * @private
    - */
    -goog.math.Long.TWO_PWR_16_DBL_ = 1 << 16;
    -
    -
    -/**
    - * @type {number}
    - * @private
    - */
    -goog.math.Long.TWO_PWR_24_DBL_ = 1 << 24;
    -
    -
    -/**
    - * @type {number}
    - * @private
    - */
    -goog.math.Long.TWO_PWR_32_DBL_ =
    -    goog.math.Long.TWO_PWR_16_DBL_ * goog.math.Long.TWO_PWR_16_DBL_;
    -
    -
    -/**
    - * @type {number}
    - * @private
    - */
    -goog.math.Long.TWO_PWR_31_DBL_ =
    -    goog.math.Long.TWO_PWR_32_DBL_ / 2;
    -
    -
    -/**
    - * @type {number}
    - * @private
    - */
    -goog.math.Long.TWO_PWR_48_DBL_ =
    -    goog.math.Long.TWO_PWR_32_DBL_ * goog.math.Long.TWO_PWR_16_DBL_;
    -
    -
    -/**
    - * @type {number}
    - * @private
    - */
    -goog.math.Long.TWO_PWR_64_DBL_ =
    -    goog.math.Long.TWO_PWR_32_DBL_ * goog.math.Long.TWO_PWR_32_DBL_;
    -
    -
    -/**
    - * @type {number}
    - * @private
    - */
    -goog.math.Long.TWO_PWR_63_DBL_ =
    -    goog.math.Long.TWO_PWR_64_DBL_ / 2;
    -
    -
    -/** @type {!goog.math.Long} */
    -goog.math.Long.ZERO = goog.math.Long.fromInt(0);
    -
    -
    -/** @type {!goog.math.Long} */
    -goog.math.Long.ONE = goog.math.Long.fromInt(1);
    -
    -
    -/** @type {!goog.math.Long} */
    -goog.math.Long.NEG_ONE = goog.math.Long.fromInt(-1);
    -
    -
    -/** @type {!goog.math.Long} */
    -goog.math.Long.MAX_VALUE =
    -    goog.math.Long.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0);
    -
    -
    -/** @type {!goog.math.Long} */
    -goog.math.Long.MIN_VALUE = goog.math.Long.fromBits(0, 0x80000000 | 0);
    -
    -
    -/**
    - * @type {!goog.math.Long}
    - * @private
    - */
    -goog.math.Long.TWO_PWR_24_ = goog.math.Long.fromInt(1 << 24);
    -
    -
    -/** @return {number} The value, assuming it is a 32-bit integer. */
    -goog.math.Long.prototype.toInt = function() {
    -  return this.low_;
    -};
    -
    -
    -/** @return {number} The closest floating-point representation to this value. */
    -goog.math.Long.prototype.toNumber = function() {
    -  return this.high_ * goog.math.Long.TWO_PWR_32_DBL_ +
    -         this.getLowBitsUnsigned();
    -};
    -
    -
    -/**
    - * @param {number=} opt_radix The radix in which the text should be written.
    - * @return {string} The textual representation of this value.
    - * @override
    - */
    -goog.math.Long.prototype.toString = function(opt_radix) {
    -  var radix = opt_radix || 10;
    -  if (radix < 2 || 36 < radix) {
    -    throw Error('radix out of range: ' + radix);
    -  }
    -
    -  if (this.isZero()) {
    -    return '0';
    -  }
    -
    -  if (this.isNegative()) {
    -    if (this.equals(goog.math.Long.MIN_VALUE)) {
    -      // We need to change the Long value before it can be negated, so we remove
    -      // the bottom-most digit in this base and then recurse to do the rest.
    -      var radixLong = goog.math.Long.fromNumber(radix);
    -      var div = this.div(radixLong);
    -      var rem = div.multiply(radixLong).subtract(this);
    -      return div.toString(radix) + rem.toInt().toString(radix);
    -    } else {
    -      return '-' + this.negate().toString(radix);
    -    }
    -  }
    -
    -  // Do several (6) digits each time through the loop, so as to
    -  // minimize the calls to the very expensive emulated div.
    -  var radixToPower = goog.math.Long.fromNumber(Math.pow(radix, 6));
    -
    -  var rem = this;
    -  var result = '';
    -  while (true) {
    -    var remDiv = rem.div(radixToPower);
    -    var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt();
    -    var digits = intval.toString(radix);
    -
    -    rem = remDiv;
    -    if (rem.isZero()) {
    -      return digits + result;
    -    } else {
    -      while (digits.length < 6) {
    -        digits = '0' + digits;
    -      }
    -      result = '' + digits + result;
    -    }
    -  }
    -};
    -
    -
    -/** @return {number} The high 32-bits as a signed value. */
    -goog.math.Long.prototype.getHighBits = function() {
    -  return this.high_;
    -};
    -
    -
    -/** @return {number} The low 32-bits as a signed value. */
    -goog.math.Long.prototype.getLowBits = function() {
    -  return this.low_;
    -};
    -
    -
    -/** @return {number} The low 32-bits as an unsigned value. */
    -goog.math.Long.prototype.getLowBitsUnsigned = function() {
    -  return (this.low_ >= 0) ?
    -      this.low_ : goog.math.Long.TWO_PWR_32_DBL_ + this.low_;
    -};
    -
    -
    -/**
    - * @return {number} Returns the number of bits needed to represent the absolute
    - *     value of this Long.
    - */
    -goog.math.Long.prototype.getNumBitsAbs = function() {
    -  if (this.isNegative()) {
    -    if (this.equals(goog.math.Long.MIN_VALUE)) {
    -      return 64;
    -    } else {
    -      return this.negate().getNumBitsAbs();
    -    }
    -  } else {
    -    var val = this.high_ != 0 ? this.high_ : this.low_;
    -    for (var bit = 31; bit > 0; bit--) {
    -      if ((val & (1 << bit)) != 0) {
    -        break;
    -      }
    -    }
    -    return this.high_ != 0 ? bit + 33 : bit + 1;
    -  }
    -};
    -
    -
    -/** @return {boolean} Whether this value is zero. */
    -goog.math.Long.prototype.isZero = function() {
    -  return this.high_ == 0 && this.low_ == 0;
    -};
    -
    -
    -/** @return {boolean} Whether this value is negative. */
    -goog.math.Long.prototype.isNegative = function() {
    -  return this.high_ < 0;
    -};
    -
    -
    -/** @return {boolean} Whether this value is odd. */
    -goog.math.Long.prototype.isOdd = function() {
    -  return (this.low_ & 1) == 1;
    -};
    -
    -
    -/**
    - * @param {goog.math.Long} other Long to compare against.
    - * @return {boolean} Whether this Long equals the other.
    - */
    -goog.math.Long.prototype.equals = function(other) {
    -  return (this.high_ == other.high_) && (this.low_ == other.low_);
    -};
    -
    -
    -/**
    - * @param {goog.math.Long} other Long to compare against.
    - * @return {boolean} Whether this Long does not equal the other.
    - */
    -goog.math.Long.prototype.notEquals = function(other) {
    -  return (this.high_ != other.high_) || (this.low_ != other.low_);
    -};
    -
    -
    -/**
    - * @param {goog.math.Long} other Long to compare against.
    - * @return {boolean} Whether this Long is less than the other.
    - */
    -goog.math.Long.prototype.lessThan = function(other) {
    -  return this.compare(other) < 0;
    -};
    -
    -
    -/**
    - * @param {goog.math.Long} other Long to compare against.
    - * @return {boolean} Whether this Long is less than or equal to the other.
    - */
    -goog.math.Long.prototype.lessThanOrEqual = function(other) {
    -  return this.compare(other) <= 0;
    -};
    -
    -
    -/**
    - * @param {goog.math.Long} other Long to compare against.
    - * @return {boolean} Whether this Long is greater than the other.
    - */
    -goog.math.Long.prototype.greaterThan = function(other) {
    -  return this.compare(other) > 0;
    -};
    -
    -
    -/**
    - * @param {goog.math.Long} other Long to compare against.
    - * @return {boolean} Whether this Long is greater than or equal to the other.
    - */
    -goog.math.Long.prototype.greaterThanOrEqual = function(other) {
    -  return this.compare(other) >= 0;
    -};
    -
    -
    -/**
    - * Compares this Long with the given one.
    - * @param {goog.math.Long} other Long to compare against.
    - * @return {number} 0 if they are the same, 1 if the this is greater, and -1
    - *     if the given one is greater.
    - */
    -goog.math.Long.prototype.compare = function(other) {
    -  if (this.equals(other)) {
    -    return 0;
    -  }
    -
    -  var thisNeg = this.isNegative();
    -  var otherNeg = other.isNegative();
    -  if (thisNeg && !otherNeg) {
    -    return -1;
    -  }
    -  if (!thisNeg && otherNeg) {
    -    return 1;
    -  }
    -
    -  // at this point, the signs are the same, so subtraction will not overflow
    -  if (this.subtract(other).isNegative()) {
    -    return -1;
    -  } else {
    -    return 1;
    -  }
    -};
    -
    -
    -/** @return {!goog.math.Long} The negation of this value. */
    -goog.math.Long.prototype.negate = function() {
    -  if (this.equals(goog.math.Long.MIN_VALUE)) {
    -    return goog.math.Long.MIN_VALUE;
    -  } else {
    -    return this.not().add(goog.math.Long.ONE);
    -  }
    -};
    -
    -
    -/**
    - * Returns the sum of this and the given Long.
    - * @param {goog.math.Long} other Long to add to this one.
    - * @return {!goog.math.Long} The sum of this and the given Long.
    - */
    -goog.math.Long.prototype.add = function(other) {
    -  // Divide each number into 4 chunks of 16 bits, and then sum the chunks.
    -
    -  var a48 = this.high_ >>> 16;
    -  var a32 = this.high_ & 0xFFFF;
    -  var a16 = this.low_ >>> 16;
    -  var a00 = this.low_ & 0xFFFF;
    -
    -  var b48 = other.high_ >>> 16;
    -  var b32 = other.high_ & 0xFFFF;
    -  var b16 = other.low_ >>> 16;
    -  var b00 = other.low_ & 0xFFFF;
    -
    -  var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
    -  c00 += a00 + b00;
    -  c16 += c00 >>> 16;
    -  c00 &= 0xFFFF;
    -  c16 += a16 + b16;
    -  c32 += c16 >>> 16;
    -  c16 &= 0xFFFF;
    -  c32 += a32 + b32;
    -  c48 += c32 >>> 16;
    -  c32 &= 0xFFFF;
    -  c48 += a48 + b48;
    -  c48 &= 0xFFFF;
    -  return goog.math.Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32);
    -};
    -
    -
    -/**
    - * Returns the difference of this and the given Long.
    - * @param {goog.math.Long} other Long to subtract from this.
    - * @return {!goog.math.Long} The difference of this and the given Long.
    - */
    -goog.math.Long.prototype.subtract = function(other) {
    -  return this.add(other.negate());
    -};
    -
    -
    -/**
    - * Returns the product of this and the given long.
    - * @param {goog.math.Long} other Long to multiply with this.
    - * @return {!goog.math.Long} The product of this and the other.
    - */
    -goog.math.Long.prototype.multiply = function(other) {
    -  if (this.isZero()) {
    -    return goog.math.Long.ZERO;
    -  } else if (other.isZero()) {
    -    return goog.math.Long.ZERO;
    -  }
    -
    -  if (this.equals(goog.math.Long.MIN_VALUE)) {
    -    return other.isOdd() ? goog.math.Long.MIN_VALUE : goog.math.Long.ZERO;
    -  } else if (other.equals(goog.math.Long.MIN_VALUE)) {
    -    return this.isOdd() ? goog.math.Long.MIN_VALUE : goog.math.Long.ZERO;
    -  }
    -
    -  if (this.isNegative()) {
    -    if (other.isNegative()) {
    -      return this.negate().multiply(other.negate());
    -    } else {
    -      return this.negate().multiply(other).negate();
    -    }
    -  } else if (other.isNegative()) {
    -    return this.multiply(other.negate()).negate();
    -  }
    -
    -  // If both longs are small, use float multiplication
    -  if (this.lessThan(goog.math.Long.TWO_PWR_24_) &&
    -      other.lessThan(goog.math.Long.TWO_PWR_24_)) {
    -    return goog.math.Long.fromNumber(this.toNumber() * other.toNumber());
    -  }
    -
    -  // Divide each long into 4 chunks of 16 bits, and then add up 4x4 products.
    -  // We can skip products that would overflow.
    -
    -  var a48 = this.high_ >>> 16;
    -  var a32 = this.high_ & 0xFFFF;
    -  var a16 = this.low_ >>> 16;
    -  var a00 = this.low_ & 0xFFFF;
    -
    -  var b48 = other.high_ >>> 16;
    -  var b32 = other.high_ & 0xFFFF;
    -  var b16 = other.low_ >>> 16;
    -  var b00 = other.low_ & 0xFFFF;
    -
    -  var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
    -  c00 += a00 * b00;
    -  c16 += c00 >>> 16;
    -  c00 &= 0xFFFF;
    -  c16 += a16 * b00;
    -  c32 += c16 >>> 16;
    -  c16 &= 0xFFFF;
    -  c16 += a00 * b16;
    -  c32 += c16 >>> 16;
    -  c16 &= 0xFFFF;
    -  c32 += a32 * b00;
    -  c48 += c32 >>> 16;
    -  c32 &= 0xFFFF;
    -  c32 += a16 * b16;
    -  c48 += c32 >>> 16;
    -  c32 &= 0xFFFF;
    -  c32 += a00 * b32;
    -  c48 += c32 >>> 16;
    -  c32 &= 0xFFFF;
    -  c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48;
    -  c48 &= 0xFFFF;
    -  return goog.math.Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32);
    -};
    -
    -
    -/**
    - * Returns this Long divided by the given one.
    - * @param {goog.math.Long} other Long by which to divide.
    - * @return {!goog.math.Long} This Long divided by the given one.
    - */
    -goog.math.Long.prototype.div = function(other) {
    -  if (other.isZero()) {
    -    throw Error('division by zero');
    -  } else if (this.isZero()) {
    -    return goog.math.Long.ZERO;
    -  }
    -
    -  if (this.equals(goog.math.Long.MIN_VALUE)) {
    -    if (other.equals(goog.math.Long.ONE) ||
    -        other.equals(goog.math.Long.NEG_ONE)) {
    -      return goog.math.Long.MIN_VALUE;  // recall that -MIN_VALUE == MIN_VALUE
    -    } else if (other.equals(goog.math.Long.MIN_VALUE)) {
    -      return goog.math.Long.ONE;
    -    } else {
    -      // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|.
    -      var halfThis = this.shiftRight(1);
    -      var approx = halfThis.div(other).shiftLeft(1);
    -      if (approx.equals(goog.math.Long.ZERO)) {
    -        return other.isNegative() ? goog.math.Long.ONE : goog.math.Long.NEG_ONE;
    -      } else {
    -        var rem = this.subtract(other.multiply(approx));
    -        var result = approx.add(rem.div(other));
    -        return result;
    -      }
    -    }
    -  } else if (other.equals(goog.math.Long.MIN_VALUE)) {
    -    return goog.math.Long.ZERO;
    -  }
    -
    -  if (this.isNegative()) {
    -    if (other.isNegative()) {
    -      return this.negate().div(other.negate());
    -    } else {
    -      return this.negate().div(other).negate();
    -    }
    -  } else if (other.isNegative()) {
    -    return this.div(other.negate()).negate();
    -  }
    -
    -  // Repeat the following until the remainder is less than other:  find a
    -  // floating-point that approximates remainder / other *from below*, add this
    -  // into the result, and subtract it from the remainder.  It is critical that
    -  // the approximate value is less than or equal to the real value so that the
    -  // remainder never becomes negative.
    -  var res = goog.math.Long.ZERO;
    -  var rem = this;
    -  while (rem.greaterThanOrEqual(other)) {
    -    // Approximate the result of division. This may be a little greater or
    -    // smaller than the actual value.
    -    var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber()));
    -
    -    // We will tweak the approximate result by changing it in the 48-th digit or
    -    // the smallest non-fractional digit, whichever is larger.
    -    var log2 = Math.ceil(Math.log(approx) / Math.LN2);
    -    var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48);
    -
    -    // Decrease the approximation until it is smaller than the remainder.  Note
    -    // that if it is too large, the product overflows and is negative.
    -    var approxRes = goog.math.Long.fromNumber(approx);
    -    var approxRem = approxRes.multiply(other);
    -    while (approxRem.isNegative() || approxRem.greaterThan(rem)) {
    -      approx -= delta;
    -      approxRes = goog.math.Long.fromNumber(approx);
    -      approxRem = approxRes.multiply(other);
    -    }
    -
    -    // We know the answer can't be zero... and actually, zero would cause
    -    // infinite recursion since we would make no progress.
    -    if (approxRes.isZero()) {
    -      approxRes = goog.math.Long.ONE;
    -    }
    -
    -    res = res.add(approxRes);
    -    rem = rem.subtract(approxRem);
    -  }
    -  return res;
    -};
    -
    -
    -/**
    - * Returns this Long modulo the given one.
    - * @param {goog.math.Long} other Long by which to mod.
    - * @return {!goog.math.Long} This Long modulo the given one.
    - */
    -goog.math.Long.prototype.modulo = function(other) {
    -  return this.subtract(this.div(other).multiply(other));
    -};
    -
    -
    -/** @return {!goog.math.Long} The bitwise-NOT of this value. */
    -goog.math.Long.prototype.not = function() {
    -  return goog.math.Long.fromBits(~this.low_, ~this.high_);
    -};
    -
    -
    -/**
    - * Returns the bitwise-AND of this Long and the given one.
    - * @param {goog.math.Long} other The Long with which to AND.
    - * @return {!goog.math.Long} The bitwise-AND of this and the other.
    - */
    -goog.math.Long.prototype.and = function(other) {
    -  return goog.math.Long.fromBits(this.low_ & other.low_,
    -                                 this.high_ & other.high_);
    -};
    -
    -
    -/**
    - * Returns the bitwise-OR of this Long and the given one.
    - * @param {goog.math.Long} other The Long with which to OR.
    - * @return {!goog.math.Long} The bitwise-OR of this and the other.
    - */
    -goog.math.Long.prototype.or = function(other) {
    -  return goog.math.Long.fromBits(this.low_ | other.low_,
    -                                 this.high_ | other.high_);
    -};
    -
    -
    -/**
    - * Returns the bitwise-XOR of this Long and the given one.
    - * @param {goog.math.Long} other The Long with which to XOR.
    - * @return {!goog.math.Long} The bitwise-XOR of this and the other.
    - */
    -goog.math.Long.prototype.xor = function(other) {
    -  return goog.math.Long.fromBits(this.low_ ^ other.low_,
    -                                 this.high_ ^ other.high_);
    -};
    -
    -
    -/**
    - * Returns this Long with bits shifted to the left by the given amount.
    - * @param {number} numBits The number of bits by which to shift.
    - * @return {!goog.math.Long} This shifted to the left by the given amount.
    - */
    -goog.math.Long.prototype.shiftLeft = function(numBits) {
    -  numBits &= 63;
    -  if (numBits == 0) {
    -    return this;
    -  } else {
    -    var low = this.low_;
    -    if (numBits < 32) {
    -      var high = this.high_;
    -      return goog.math.Long.fromBits(
    -          low << numBits,
    -          (high << numBits) | (low >>> (32 - numBits)));
    -    } else {
    -      return goog.math.Long.fromBits(0, low << (numBits - 32));
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Returns this Long with bits shifted to the right by the given amount.
    - * @param {number} numBits The number of bits by which to shift.
    - * @return {!goog.math.Long} This shifted to the right by the given amount.
    - */
    -goog.math.Long.prototype.shiftRight = function(numBits) {
    -  numBits &= 63;
    -  if (numBits == 0) {
    -    return this;
    -  } else {
    -    var high = this.high_;
    -    if (numBits < 32) {
    -      var low = this.low_;
    -      return goog.math.Long.fromBits(
    -          (low >>> numBits) | (high << (32 - numBits)),
    -          high >> numBits);
    -    } else {
    -      return goog.math.Long.fromBits(
    -          high >> (numBits - 32),
    -          high >= 0 ? 0 : -1);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Returns this Long with bits shifted to the right by the given amount, with
    - * zeros placed into the new leading bits.
    - * @param {number} numBits The number of bits by which to shift.
    - * @return {!goog.math.Long} This shifted to the right by the given amount, with
    - *     zeros placed into the new leading bits.
    - */
    -goog.math.Long.prototype.shiftRightUnsigned = function(numBits) {
    -  numBits &= 63;
    -  if (numBits == 0) {
    -    return this;
    -  } else {
    -    var high = this.high_;
    -    if (numBits < 32) {
    -      var low = this.low_;
    -      return goog.math.Long.fromBits(
    -          (low >>> numBits) | (high << (32 - numBits)),
    -          high >>> numBits);
    -    } else if (numBits == 32) {
    -      return goog.math.Long.fromBits(high, 0);
    -    } else {
    -      return goog.math.Long.fromBits(high >>> (numBits - 32), 0);
    -    }
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/math/long_test.html b/src/database/third_party/closure-library/closure/goog/math/long_test.html
    deleted file mode 100644
    index f9feebddff2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/long_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.math.Long
    -  </title>
    -  <script src="../base.js" type="text/javascript">
    -  </script>
    -  <script type="text/javascript">
    -    goog.require('goog.math.LongTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/math/long_test.js b/src/database/third_party/closure-library/closure/goog/math/long_test.js
    deleted file mode 100644
    index 7639819051f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/long_test.js
    +++ /dev/null
    @@ -1,1571 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.math.LongTest');
    -goog.setTestOnly('goog.math.LongTest');
    -
    -goog.require('goog.math.Long');
    -goog.require('goog.testing.jsunit');
    -
    -// Interprets the given numbers as the bits of a 32-bit int.  In particular,
    -// this takes care of the 32-bit being interpretted as the sign.
    -function toInt32s(arr) {
    -  for (var i = 0; i < arr.length; ++i) {
    -    arr[i] = arr[i] & 0xFFFFFFFF;
    -  }
    -}
    -
    -// Note that these are in numerical order.
    -var TEST_BITS = [0x80000000, 0x00000000,
    -  0xb776d5f5, 0x5634e2db,
    -  0xffefffff, 0xffffffff,
    -  0xfff00000, 0x00000000,
    -  0xfffeffff, 0xffffffff,
    -  0xffff0000, 0x00000000,
    -  0xfffffffe, 0xffffffff,
    -  0xffffffff, 0x00000000,
    -  0xffffffff, 0xfeffffff,
    -  0xffffffff, 0xff000000,
    -  0xffffffff, 0xfffeffff,
    -  0xffffffff, 0xffff0000,
    -  0xffffffff, 0xffff7fff,
    -  0xffffffff, 0xffff8000,
    -  0xffffffff, 0xfffffffe,
    -  0xffffffff, 0xffffffff,
    -  0x00000000, 0x00000000,
    -  0x00000000, 0x00000001,
    -  0x00000000, 0x00000002,
    -  0x00000000, 0x00007fff,
    -  0x00000000, 0x00008000,
    -  0x00000000, 0x0000ffff,
    -  0x00000000, 0x00010000,
    -  0x00000000, 0x00ffffff,
    -  0x00000000, 0x01000000,
    -  0x00000000, 0x5634e2db,
    -  0x00000000, 0xb776d5f5,
    -  0x00000000, 0xffffffff,
    -  0x00000001, 0x00000000,
    -  0x0000ffff, 0xffffffff,
    -  0x00010000, 0x00000000,
    -  0x000fffff, 0xffffffff,
    -  0x00100000, 0x00000000,
    -  0x5634e2db, 0xb776d5f5,
    -  0x7fffffff, 0xffffffff];
    -toInt32s(TEST_BITS);
    -
    -var TEST_ADD_BITS = [
    -  0x3776d5f5, 0x5634e2db, 0x7fefffff, 0xffffffff, 0xb766d5f5, 0x5634e2da,
    -  0x7ff00000, 0x00000000, 0xb766d5f5, 0x5634e2db, 0xffdfffff, 0xffffffff,
    -  0x7ffeffff, 0xffffffff, 0xb775d5f5, 0x5634e2da, 0xffeeffff, 0xfffffffe,
    -  0xffeeffff, 0xffffffff, 0x7fff0000, 0x00000000, 0xb775d5f5, 0x5634e2db,
    -  0xffeeffff, 0xffffffff, 0xffef0000, 0x00000000, 0xfffdffff, 0xffffffff,
    -  0x7ffffffe, 0xffffffff, 0xb776d5f4, 0x5634e2da, 0xffeffffe, 0xfffffffe,
    -  0xffeffffe, 0xffffffff, 0xfffefffe, 0xfffffffe, 0xfffefffe, 0xffffffff,
    -  0x7fffffff, 0x00000000, 0xb776d5f4, 0x5634e2db, 0xffeffffe, 0xffffffff,
    -  0xffefffff, 0x00000000, 0xfffefffe, 0xffffffff, 0xfffeffff, 0x00000000,
    -  0xfffffffd, 0xffffffff, 0x7fffffff, 0xfeffffff, 0xb776d5f5, 0x5534e2da,
    -  0xffefffff, 0xfefffffe, 0xffefffff, 0xfeffffff, 0xfffeffff, 0xfefffffe,
    -  0xfffeffff, 0xfeffffff, 0xfffffffe, 0xfefffffe, 0xfffffffe, 0xfeffffff,
    -  0x7fffffff, 0xff000000, 0xb776d5f5, 0x5534e2db, 0xffefffff, 0xfeffffff,
    -  0xffefffff, 0xff000000, 0xfffeffff, 0xfeffffff, 0xfffeffff, 0xff000000,
    -  0xfffffffe, 0xfeffffff, 0xfffffffe, 0xff000000, 0xffffffff, 0xfdffffff,
    -  0x7fffffff, 0xfffeffff, 0xb776d5f5, 0x5633e2da, 0xffefffff, 0xfffefffe,
    -  0xffefffff, 0xfffeffff, 0xfffeffff, 0xfffefffe, 0xfffeffff, 0xfffeffff,
    -  0xfffffffe, 0xfffefffe, 0xfffffffe, 0xfffeffff, 0xffffffff, 0xfefefffe,
    -  0xffffffff, 0xfefeffff, 0x7fffffff, 0xffff0000, 0xb776d5f5, 0x5633e2db,
    -  0xffefffff, 0xfffeffff, 0xffefffff, 0xffff0000, 0xfffeffff, 0xfffeffff,
    -  0xfffeffff, 0xffff0000, 0xfffffffe, 0xfffeffff, 0xfffffffe, 0xffff0000,
    -  0xffffffff, 0xfefeffff, 0xffffffff, 0xfeff0000, 0xffffffff, 0xfffdffff,
    -  0x7fffffff, 0xffff7fff, 0xb776d5f5, 0x563462da, 0xffefffff, 0xffff7ffe,
    -  0xffefffff, 0xffff7fff, 0xfffeffff, 0xffff7ffe, 0xfffeffff, 0xffff7fff,
    -  0xfffffffe, 0xffff7ffe, 0xfffffffe, 0xffff7fff, 0xffffffff, 0xfeff7ffe,
    -  0xffffffff, 0xfeff7fff, 0xffffffff, 0xfffe7ffe, 0xffffffff, 0xfffe7fff,
    -  0x7fffffff, 0xffff8000, 0xb776d5f5, 0x563462db, 0xffefffff, 0xffff7fff,
    -  0xffefffff, 0xffff8000, 0xfffeffff, 0xffff7fff, 0xfffeffff, 0xffff8000,
    -  0xfffffffe, 0xffff7fff, 0xfffffffe, 0xffff8000, 0xffffffff, 0xfeff7fff,
    -  0xffffffff, 0xfeff8000, 0xffffffff, 0xfffe7fff, 0xffffffff, 0xfffe8000,
    -  0xffffffff, 0xfffeffff, 0x7fffffff, 0xfffffffe, 0xb776d5f5, 0x5634e2d9,
    -  0xffefffff, 0xfffffffd, 0xffefffff, 0xfffffffe, 0xfffeffff, 0xfffffffd,
    -  0xfffeffff, 0xfffffffe, 0xfffffffe, 0xfffffffd, 0xfffffffe, 0xfffffffe,
    -  0xffffffff, 0xfefffffd, 0xffffffff, 0xfefffffe, 0xffffffff, 0xfffefffd,
    -  0xffffffff, 0xfffefffe, 0xffffffff, 0xffff7ffd, 0xffffffff, 0xffff7ffe,
    -  0x7fffffff, 0xffffffff, 0xb776d5f5, 0x5634e2da, 0xffefffff, 0xfffffffe,
    -  0xffefffff, 0xffffffff, 0xfffeffff, 0xfffffffe, 0xfffeffff, 0xffffffff,
    -  0xfffffffe, 0xfffffffe, 0xfffffffe, 0xffffffff, 0xffffffff, 0xfefffffe,
    -  0xffffffff, 0xfeffffff, 0xffffffff, 0xfffefffe, 0xffffffff, 0xfffeffff,
    -  0xffffffff, 0xffff7ffe, 0xffffffff, 0xffff7fff, 0xffffffff, 0xfffffffd,
    -  0x80000000, 0x00000000, 0xb776d5f5, 0x5634e2db, 0xffefffff, 0xffffffff,
    -  0xfff00000, 0x00000000, 0xfffeffff, 0xffffffff, 0xffff0000, 0x00000000,
    -  0xfffffffe, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xfeffffff,
    -  0xffffffff, 0xff000000, 0xffffffff, 0xfffeffff, 0xffffffff, 0xffff0000,
    -  0xffffffff, 0xffff7fff, 0xffffffff, 0xffff8000, 0xffffffff, 0xfffffffe,
    -  0xffffffff, 0xffffffff, 0x80000000, 0x00000001, 0xb776d5f5, 0x5634e2dc,
    -  0xfff00000, 0x00000000, 0xfff00000, 0x00000001, 0xffff0000, 0x00000000,
    -  0xffff0000, 0x00000001, 0xffffffff, 0x00000000, 0xffffffff, 0x00000001,
    -  0xffffffff, 0xff000000, 0xffffffff, 0xff000001, 0xffffffff, 0xffff0000,
    -  0xffffffff, 0xffff0001, 0xffffffff, 0xffff8000, 0xffffffff, 0xffff8001,
    -  0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
    -  0x80000000, 0x00000002, 0xb776d5f5, 0x5634e2dd, 0xfff00000, 0x00000001,
    -  0xfff00000, 0x00000002, 0xffff0000, 0x00000001, 0xffff0000, 0x00000002,
    -  0xffffffff, 0x00000001, 0xffffffff, 0x00000002, 0xffffffff, 0xff000001,
    -  0xffffffff, 0xff000002, 0xffffffff, 0xffff0001, 0xffffffff, 0xffff0002,
    -  0xffffffff, 0xffff8001, 0xffffffff, 0xffff8002, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000001, 0x00000000, 0x00000002, 0x00000000, 0x00000003,
    -  0x80000000, 0x00007fff, 0xb776d5f5, 0x563562da, 0xfff00000, 0x00007ffe,
    -  0xfff00000, 0x00007fff, 0xffff0000, 0x00007ffe, 0xffff0000, 0x00007fff,
    -  0xffffffff, 0x00007ffe, 0xffffffff, 0x00007fff, 0xffffffff, 0xff007ffe,
    -  0xffffffff, 0xff007fff, 0xffffffff, 0xffff7ffe, 0xffffffff, 0xffff7fff,
    -  0xffffffff, 0xfffffffe, 0xffffffff, 0xffffffff, 0x00000000, 0x00007ffd,
    -  0x00000000, 0x00007ffe, 0x00000000, 0x00007fff, 0x00000000, 0x00008000,
    -  0x00000000, 0x00008001, 0x80000000, 0x00008000, 0xb776d5f5, 0x563562db,
    -  0xfff00000, 0x00007fff, 0xfff00000, 0x00008000, 0xffff0000, 0x00007fff,
    -  0xffff0000, 0x00008000, 0xffffffff, 0x00007fff, 0xffffffff, 0x00008000,
    -  0xffffffff, 0xff007fff, 0xffffffff, 0xff008000, 0xffffffff, 0xffff7fff,
    -  0xffffffff, 0xffff8000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
    -  0x00000000, 0x00007ffe, 0x00000000, 0x00007fff, 0x00000000, 0x00008000,
    -  0x00000000, 0x00008001, 0x00000000, 0x00008002, 0x00000000, 0x0000ffff,
    -  0x80000000, 0x0000ffff, 0xb776d5f5, 0x5635e2da, 0xfff00000, 0x0000fffe,
    -  0xfff00000, 0x0000ffff, 0xffff0000, 0x0000fffe, 0xffff0000, 0x0000ffff,
    -  0xffffffff, 0x0000fffe, 0xffffffff, 0x0000ffff, 0xffffffff, 0xff00fffe,
    -  0xffffffff, 0xff00ffff, 0xffffffff, 0xfffffffe, 0xffffffff, 0xffffffff,
    -  0x00000000, 0x00007ffe, 0x00000000, 0x00007fff, 0x00000000, 0x0000fffd,
    -  0x00000000, 0x0000fffe, 0x00000000, 0x0000ffff, 0x00000000, 0x00010000,
    -  0x00000000, 0x00010001, 0x00000000, 0x00017ffe, 0x00000000, 0x00017fff,
    -  0x80000000, 0x00010000, 0xb776d5f5, 0x5635e2db, 0xfff00000, 0x0000ffff,
    -  0xfff00000, 0x00010000, 0xffff0000, 0x0000ffff, 0xffff0000, 0x00010000,
    -  0xffffffff, 0x0000ffff, 0xffffffff, 0x00010000, 0xffffffff, 0xff00ffff,
    -  0xffffffff, 0xff010000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
    -  0x00000000, 0x00007fff, 0x00000000, 0x00008000, 0x00000000, 0x0000fffe,
    -  0x00000000, 0x0000ffff, 0x00000000, 0x00010000, 0x00000000, 0x00010001,
    -  0x00000000, 0x00010002, 0x00000000, 0x00017fff, 0x00000000, 0x00018000,
    -  0x00000000, 0x0001ffff, 0x80000000, 0x00ffffff, 0xb776d5f5, 0x5734e2da,
    -  0xfff00000, 0x00fffffe, 0xfff00000, 0x00ffffff, 0xffff0000, 0x00fffffe,
    -  0xffff0000, 0x00ffffff, 0xffffffff, 0x00fffffe, 0xffffffff, 0x00ffffff,
    -  0xffffffff, 0xfffffffe, 0xffffffff, 0xffffffff, 0x00000000, 0x00fefffe,
    -  0x00000000, 0x00feffff, 0x00000000, 0x00ff7ffe, 0x00000000, 0x00ff7fff,
    -  0x00000000, 0x00fffffd, 0x00000000, 0x00fffffe, 0x00000000, 0x00ffffff,
    -  0x00000000, 0x01000000, 0x00000000, 0x01000001, 0x00000000, 0x01007ffe,
    -  0x00000000, 0x01007fff, 0x00000000, 0x0100fffe, 0x00000000, 0x0100ffff,
    -  0x80000000, 0x01000000, 0xb776d5f5, 0x5734e2db, 0xfff00000, 0x00ffffff,
    -  0xfff00000, 0x01000000, 0xffff0000, 0x00ffffff, 0xffff0000, 0x01000000,
    -  0xffffffff, 0x00ffffff, 0xffffffff, 0x01000000, 0xffffffff, 0xffffffff,
    -  0x00000000, 0x00000000, 0x00000000, 0x00feffff, 0x00000000, 0x00ff0000,
    -  0x00000000, 0x00ff7fff, 0x00000000, 0x00ff8000, 0x00000000, 0x00fffffe,
    -  0x00000000, 0x00ffffff, 0x00000000, 0x01000000, 0x00000000, 0x01000001,
    -  0x00000000, 0x01000002, 0x00000000, 0x01007fff, 0x00000000, 0x01008000,
    -  0x00000000, 0x0100ffff, 0x00000000, 0x01010000, 0x00000000, 0x01ffffff,
    -  0x80000000, 0x5634e2db, 0xb776d5f5, 0xac69c5b6, 0xfff00000, 0x5634e2da,
    -  0xfff00000, 0x5634e2db, 0xffff0000, 0x5634e2da, 0xffff0000, 0x5634e2db,
    -  0xffffffff, 0x5634e2da, 0xffffffff, 0x5634e2db, 0x00000000, 0x5534e2da,
    -  0x00000000, 0x5534e2db, 0x00000000, 0x5633e2da, 0x00000000, 0x5633e2db,
    -  0x00000000, 0x563462da, 0x00000000, 0x563462db, 0x00000000, 0x5634e2d9,
    -  0x00000000, 0x5634e2da, 0x00000000, 0x5634e2db, 0x00000000, 0x5634e2dc,
    -  0x00000000, 0x5634e2dd, 0x00000000, 0x563562da, 0x00000000, 0x563562db,
    -  0x00000000, 0x5635e2da, 0x00000000, 0x5635e2db, 0x00000000, 0x5734e2da,
    -  0x00000000, 0x5734e2db, 0x80000000, 0xb776d5f5, 0xb776d5f6, 0x0dabb8d0,
    -  0xfff00000, 0xb776d5f4, 0xfff00000, 0xb776d5f5, 0xffff0000, 0xb776d5f4,
    -  0xffff0000, 0xb776d5f5, 0xffffffff, 0xb776d5f4, 0xffffffff, 0xb776d5f5,
    -  0x00000000, 0xb676d5f4, 0x00000000, 0xb676d5f5, 0x00000000, 0xb775d5f4,
    -  0x00000000, 0xb775d5f5, 0x00000000, 0xb77655f4, 0x00000000, 0xb77655f5,
    -  0x00000000, 0xb776d5f3, 0x00000000, 0xb776d5f4, 0x00000000, 0xb776d5f5,
    -  0x00000000, 0xb776d5f6, 0x00000000, 0xb776d5f7, 0x00000000, 0xb77755f4,
    -  0x00000000, 0xb77755f5, 0x00000000, 0xb777d5f4, 0x00000000, 0xb777d5f5,
    -  0x00000000, 0xb876d5f4, 0x00000000, 0xb876d5f5, 0x00000001, 0x0dabb8d0,
    -  0x80000000, 0xffffffff, 0xb776d5f6, 0x5634e2da, 0xfff00000, 0xfffffffe,
    -  0xfff00000, 0xffffffff, 0xffff0000, 0xfffffffe, 0xffff0000, 0xffffffff,
    -  0xffffffff, 0xfffffffe, 0xffffffff, 0xffffffff, 0x00000000, 0xfefffffe,
    -  0x00000000, 0xfeffffff, 0x00000000, 0xfffefffe, 0x00000000, 0xfffeffff,
    -  0x00000000, 0xffff7ffe, 0x00000000, 0xffff7fff, 0x00000000, 0xfffffffd,
    -  0x00000000, 0xfffffffe, 0x00000000, 0xffffffff, 0x00000001, 0x00000000,
    -  0x00000001, 0x00000001, 0x00000001, 0x00007ffe, 0x00000001, 0x00007fff,
    -  0x00000001, 0x0000fffe, 0x00000001, 0x0000ffff, 0x00000001, 0x00fffffe,
    -  0x00000001, 0x00ffffff, 0x00000001, 0x5634e2da, 0x00000001, 0xb776d5f4,
    -  0x80000001, 0x00000000, 0xb776d5f6, 0x5634e2db, 0xfff00000, 0xffffffff,
    -  0xfff00001, 0x00000000, 0xffff0000, 0xffffffff, 0xffff0001, 0x00000000,
    -  0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xfeffffff,
    -  0x00000000, 0xff000000, 0x00000000, 0xfffeffff, 0x00000000, 0xffff0000,
    -  0x00000000, 0xffff7fff, 0x00000000, 0xffff8000, 0x00000000, 0xfffffffe,
    -  0x00000000, 0xffffffff, 0x00000001, 0x00000000, 0x00000001, 0x00000001,
    -  0x00000001, 0x00000002, 0x00000001, 0x00007fff, 0x00000001, 0x00008000,
    -  0x00000001, 0x0000ffff, 0x00000001, 0x00010000, 0x00000001, 0x00ffffff,
    -  0x00000001, 0x01000000, 0x00000001, 0x5634e2db, 0x00000001, 0xb776d5f5,
    -  0x00000001, 0xffffffff, 0x8000ffff, 0xffffffff, 0xb777d5f5, 0x5634e2da,
    -  0xfff0ffff, 0xfffffffe, 0xfff0ffff, 0xffffffff, 0xffffffff, 0xfffffffe,
    -  0xffffffff, 0xffffffff, 0x0000fffe, 0xfffffffe, 0x0000fffe, 0xffffffff,
    -  0x0000ffff, 0xfefffffe, 0x0000ffff, 0xfeffffff, 0x0000ffff, 0xfffefffe,
    -  0x0000ffff, 0xfffeffff, 0x0000ffff, 0xffff7ffe, 0x0000ffff, 0xffff7fff,
    -  0x0000ffff, 0xfffffffd, 0x0000ffff, 0xfffffffe, 0x0000ffff, 0xffffffff,
    -  0x00010000, 0x00000000, 0x00010000, 0x00000001, 0x00010000, 0x00007ffe,
    -  0x00010000, 0x00007fff, 0x00010000, 0x0000fffe, 0x00010000, 0x0000ffff,
    -  0x00010000, 0x00fffffe, 0x00010000, 0x00ffffff, 0x00010000, 0x5634e2da,
    -  0x00010000, 0xb776d5f4, 0x00010000, 0xfffffffe, 0x00010000, 0xffffffff,
    -  0x80010000, 0x00000000, 0xb777d5f5, 0x5634e2db, 0xfff0ffff, 0xffffffff,
    -  0xfff10000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
    -  0x0000fffe, 0xffffffff, 0x0000ffff, 0x00000000, 0x0000ffff, 0xfeffffff,
    -  0x0000ffff, 0xff000000, 0x0000ffff, 0xfffeffff, 0x0000ffff, 0xffff0000,
    -  0x0000ffff, 0xffff7fff, 0x0000ffff, 0xffff8000, 0x0000ffff, 0xfffffffe,
    -  0x0000ffff, 0xffffffff, 0x00010000, 0x00000000, 0x00010000, 0x00000001,
    -  0x00010000, 0x00000002, 0x00010000, 0x00007fff, 0x00010000, 0x00008000,
    -  0x00010000, 0x0000ffff, 0x00010000, 0x00010000, 0x00010000, 0x00ffffff,
    -  0x00010000, 0x01000000, 0x00010000, 0x5634e2db, 0x00010000, 0xb776d5f5,
    -  0x00010000, 0xffffffff, 0x00010001, 0x00000000, 0x0001ffff, 0xffffffff,
    -  0x800fffff, 0xffffffff, 0xb786d5f5, 0x5634e2da, 0xffffffff, 0xfffffffe,
    -  0xffffffff, 0xffffffff, 0x000effff, 0xfffffffe, 0x000effff, 0xffffffff,
    -  0x000ffffe, 0xfffffffe, 0x000ffffe, 0xffffffff, 0x000fffff, 0xfefffffe,
    -  0x000fffff, 0xfeffffff, 0x000fffff, 0xfffefffe, 0x000fffff, 0xfffeffff,
    -  0x000fffff, 0xffff7ffe, 0x000fffff, 0xffff7fff, 0x000fffff, 0xfffffffd,
    -  0x000fffff, 0xfffffffe, 0x000fffff, 0xffffffff, 0x00100000, 0x00000000,
    -  0x00100000, 0x00000001, 0x00100000, 0x00007ffe, 0x00100000, 0x00007fff,
    -  0x00100000, 0x0000fffe, 0x00100000, 0x0000ffff, 0x00100000, 0x00fffffe,
    -  0x00100000, 0x00ffffff, 0x00100000, 0x5634e2da, 0x00100000, 0xb776d5f4,
    -  0x00100000, 0xfffffffe, 0x00100000, 0xffffffff, 0x0010ffff, 0xfffffffe,
    -  0x0010ffff, 0xffffffff, 0x80100000, 0x00000000, 0xb786d5f5, 0x5634e2db,
    -  0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x000effff, 0xffffffff,
    -  0x000f0000, 0x00000000, 0x000ffffe, 0xffffffff, 0x000fffff, 0x00000000,
    -  0x000fffff, 0xfeffffff, 0x000fffff, 0xff000000, 0x000fffff, 0xfffeffff,
    -  0x000fffff, 0xffff0000, 0x000fffff, 0xffff7fff, 0x000fffff, 0xffff8000,
    -  0x000fffff, 0xfffffffe, 0x000fffff, 0xffffffff, 0x00100000, 0x00000000,
    -  0x00100000, 0x00000001, 0x00100000, 0x00000002, 0x00100000, 0x00007fff,
    -  0x00100000, 0x00008000, 0x00100000, 0x0000ffff, 0x00100000, 0x00010000,
    -  0x00100000, 0x00ffffff, 0x00100000, 0x01000000, 0x00100000, 0x5634e2db,
    -  0x00100000, 0xb776d5f5, 0x00100000, 0xffffffff, 0x00100001, 0x00000000,
    -  0x0010ffff, 0xffffffff, 0x00110000, 0x00000000, 0x001fffff, 0xffffffff,
    -  0xd634e2db, 0xb776d5f5, 0x0dabb8d1, 0x0dabb8d0, 0x5624e2db, 0xb776d5f4,
    -  0x5624e2db, 0xb776d5f5, 0x5633e2db, 0xb776d5f4, 0x5633e2db, 0xb776d5f5,
    -  0x5634e2da, 0xb776d5f4, 0x5634e2da, 0xb776d5f5, 0x5634e2db, 0xb676d5f4,
    -  0x5634e2db, 0xb676d5f5, 0x5634e2db, 0xb775d5f4, 0x5634e2db, 0xb775d5f5,
    -  0x5634e2db, 0xb77655f4, 0x5634e2db, 0xb77655f5, 0x5634e2db, 0xb776d5f3,
    -  0x5634e2db, 0xb776d5f4, 0x5634e2db, 0xb776d5f5, 0x5634e2db, 0xb776d5f6,
    -  0x5634e2db, 0xb776d5f7, 0x5634e2db, 0xb77755f4, 0x5634e2db, 0xb77755f5,
    -  0x5634e2db, 0xb777d5f4, 0x5634e2db, 0xb777d5f5, 0x5634e2db, 0xb876d5f4,
    -  0x5634e2db, 0xb876d5f5, 0x5634e2dc, 0x0dabb8d0, 0x5634e2dc, 0x6eedabea,
    -  0x5634e2dc, 0xb776d5f4, 0x5634e2dc, 0xb776d5f5, 0x5635e2db, 0xb776d5f4,
    -  0x5635e2db, 0xb776d5f5, 0x5644e2db, 0xb776d5f4, 0x5644e2db, 0xb776d5f5,
    -  0xffffffff, 0xffffffff, 0x3776d5f5, 0x5634e2da, 0x7fefffff, 0xfffffffe,
    -  0x7fefffff, 0xffffffff, 0x7ffeffff, 0xfffffffe, 0x7ffeffff, 0xffffffff,
    -  0x7ffffffe, 0xfffffffe, 0x7ffffffe, 0xffffffff, 0x7fffffff, 0xfefffffe,
    -  0x7fffffff, 0xfeffffff, 0x7fffffff, 0xfffefffe, 0x7fffffff, 0xfffeffff,
    -  0x7fffffff, 0xffff7ffe, 0x7fffffff, 0xffff7fff, 0x7fffffff, 0xfffffffd,
    -  0x7fffffff, 0xfffffffe, 0x7fffffff, 0xffffffff, 0x80000000, 0x00000000,
    -  0x80000000, 0x00000001, 0x80000000, 0x00007ffe, 0x80000000, 0x00007fff,
    -  0x80000000, 0x0000fffe, 0x80000000, 0x0000ffff, 0x80000000, 0x00fffffe,
    -  0x80000000, 0x00ffffff, 0x80000000, 0x5634e2da, 0x80000000, 0xb776d5f4,
    -  0x80000000, 0xfffffffe, 0x80000000, 0xffffffff, 0x8000ffff, 0xfffffffe,
    -  0x8000ffff, 0xffffffff, 0x800fffff, 0xfffffffe, 0x800fffff, 0xffffffff,
    -  0xd634e2db, 0xb776d5f4
    -];
    -toInt32s(TEST_ADD_BITS);
    -
    -var TEST_SUB_BITS = [
    -  0x00000000, 0x00000000, 0xc8892a0a, 0xa9cb1d25, 0x80100000, 0x00000001,
    -  0x80100000, 0x00000000, 0x80010000, 0x00000001, 0x80010000, 0x00000000,
    -  0x80000001, 0x00000001, 0x80000001, 0x00000000, 0x80000000, 0x01000001,
    -  0x80000000, 0x01000000, 0x80000000, 0x00010001, 0x80000000, 0x00010000,
    -  0x80000000, 0x00008001, 0x80000000, 0x00008000, 0x80000000, 0x00000002,
    -  0x80000000, 0x00000001, 0x80000000, 0x00000000, 0x7fffffff, 0xffffffff,
    -  0x7fffffff, 0xfffffffe, 0x7fffffff, 0xffff8001, 0x7fffffff, 0xffff8000,
    -  0x7fffffff, 0xffff0001, 0x7fffffff, 0xffff0000, 0x7fffffff, 0xff000001,
    -  0x7fffffff, 0xff000000, 0x7fffffff, 0xa9cb1d25, 0x7fffffff, 0x48892a0b,
    -  0x7fffffff, 0x00000001, 0x7fffffff, 0x00000000, 0x7fff0000, 0x00000001,
    -  0x7fff0000, 0x00000000, 0x7ff00000, 0x00000001, 0x7ff00000, 0x00000000,
    -  0x29cb1d24, 0x48892a0b, 0x00000000, 0x00000001, 0x3776d5f5, 0x5634e2db,
    -  0x00000000, 0x00000000, 0xb786d5f5, 0x5634e2dc, 0xb786d5f5, 0x5634e2db,
    -  0xb777d5f5, 0x5634e2dc, 0xb777d5f5, 0x5634e2db, 0xb776d5f6, 0x5634e2dc,
    -  0xb776d5f6, 0x5634e2db, 0xb776d5f5, 0x5734e2dc, 0xb776d5f5, 0x5734e2db,
    -  0xb776d5f5, 0x5635e2dc, 0xb776d5f5, 0x5635e2db, 0xb776d5f5, 0x563562dc,
    -  0xb776d5f5, 0x563562db, 0xb776d5f5, 0x5634e2dd, 0xb776d5f5, 0x5634e2dc,
    -  0xb776d5f5, 0x5634e2db, 0xb776d5f5, 0x5634e2da, 0xb776d5f5, 0x5634e2d9,
    -  0xb776d5f5, 0x563462dc, 0xb776d5f5, 0x563462db, 0xb776d5f5, 0x5633e2dc,
    -  0xb776d5f5, 0x5633e2db, 0xb776d5f5, 0x5534e2dc, 0xb776d5f5, 0x5534e2db,
    -  0xb776d5f5, 0x00000000, 0xb776d5f4, 0x9ebe0ce6, 0xb776d5f4, 0x5634e2dc,
    -  0xb776d5f4, 0x5634e2db, 0xb775d5f5, 0x5634e2dc, 0xb775d5f5, 0x5634e2db,
    -  0xb766d5f5, 0x5634e2dc, 0xb766d5f5, 0x5634e2db, 0x6141f319, 0x9ebe0ce6,
    -  0x3776d5f5, 0x5634e2dc, 0x7fefffff, 0xffffffff, 0x48792a0a, 0xa9cb1d24,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xfff10000, 0x00000000,
    -  0xfff0ffff, 0xffffffff, 0xfff00001, 0x00000000, 0xfff00000, 0xffffffff,
    -  0xfff00000, 0x01000000, 0xfff00000, 0x00ffffff, 0xfff00000, 0x00010000,
    -  0xfff00000, 0x0000ffff, 0xfff00000, 0x00008000, 0xfff00000, 0x00007fff,
    -  0xfff00000, 0x00000001, 0xfff00000, 0x00000000, 0xffefffff, 0xffffffff,
    -  0xffefffff, 0xfffffffe, 0xffefffff, 0xfffffffd, 0xffefffff, 0xffff8000,
    -  0xffefffff, 0xffff7fff, 0xffefffff, 0xffff0000, 0xffefffff, 0xfffeffff,
    -  0xffefffff, 0xff000000, 0xffefffff, 0xfeffffff, 0xffefffff, 0xa9cb1d24,
    -  0xffefffff, 0x48892a0a, 0xffefffff, 0x00000000, 0xffeffffe, 0xffffffff,
    -  0xffef0000, 0x00000000, 0xffeeffff, 0xffffffff, 0xffe00000, 0x00000000,
    -  0xffdfffff, 0xffffffff, 0xa9bb1d24, 0x48892a0a, 0x7ff00000, 0x00000000,
    -  0x7ff00000, 0x00000000, 0x48792a0a, 0xa9cb1d25, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xfff10000, 0x00000001, 0xfff10000, 0x00000000,
    -  0xfff00001, 0x00000001, 0xfff00001, 0x00000000, 0xfff00000, 0x01000001,
    -  0xfff00000, 0x01000000, 0xfff00000, 0x00010001, 0xfff00000, 0x00010000,
    -  0xfff00000, 0x00008001, 0xfff00000, 0x00008000, 0xfff00000, 0x00000002,
    -  0xfff00000, 0x00000001, 0xfff00000, 0x00000000, 0xffefffff, 0xffffffff,
    -  0xffefffff, 0xfffffffe, 0xffefffff, 0xffff8001, 0xffefffff, 0xffff8000,
    -  0xffefffff, 0xffff0001, 0xffefffff, 0xffff0000, 0xffefffff, 0xff000001,
    -  0xffefffff, 0xff000000, 0xffefffff, 0xa9cb1d25, 0xffefffff, 0x48892a0b,
    -  0xffefffff, 0x00000001, 0xffefffff, 0x00000000, 0xffef0000, 0x00000001,
    -  0xffef0000, 0x00000000, 0xffe00000, 0x00000001, 0xffe00000, 0x00000000,
    -  0xa9bb1d24, 0x48892a0b, 0x7ff00000, 0x00000001, 0x7ffeffff, 0xffffffff,
    -  0x48882a0a, 0xa9cb1d24, 0x000f0000, 0x00000000, 0x000effff, 0xffffffff,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffff0001, 0x00000000,
    -  0xffff0000, 0xffffffff, 0xffff0000, 0x01000000, 0xffff0000, 0x00ffffff,
    -  0xffff0000, 0x00010000, 0xffff0000, 0x0000ffff, 0xffff0000, 0x00008000,
    -  0xffff0000, 0x00007fff, 0xffff0000, 0x00000001, 0xffff0000, 0x00000000,
    -  0xfffeffff, 0xffffffff, 0xfffeffff, 0xfffffffe, 0xfffeffff, 0xfffffffd,
    -  0xfffeffff, 0xffff8000, 0xfffeffff, 0xffff7fff, 0xfffeffff, 0xffff0000,
    -  0xfffeffff, 0xfffeffff, 0xfffeffff, 0xff000000, 0xfffeffff, 0xfeffffff,
    -  0xfffeffff, 0xa9cb1d24, 0xfffeffff, 0x48892a0a, 0xfffeffff, 0x00000000,
    -  0xfffefffe, 0xffffffff, 0xfffe0000, 0x00000000, 0xfffdffff, 0xffffffff,
    -  0xffef0000, 0x00000000, 0xffeeffff, 0xffffffff, 0xa9ca1d24, 0x48892a0a,
    -  0x7fff0000, 0x00000000, 0x7fff0000, 0x00000000, 0x48882a0a, 0xa9cb1d25,
    -  0x000f0000, 0x00000001, 0x000f0000, 0x00000000, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xffff0001, 0x00000001, 0xffff0001, 0x00000000,
    -  0xffff0000, 0x01000001, 0xffff0000, 0x01000000, 0xffff0000, 0x00010001,
    -  0xffff0000, 0x00010000, 0xffff0000, 0x00008001, 0xffff0000, 0x00008000,
    -  0xffff0000, 0x00000002, 0xffff0000, 0x00000001, 0xffff0000, 0x00000000,
    -  0xfffeffff, 0xffffffff, 0xfffeffff, 0xfffffffe, 0xfffeffff, 0xffff8001,
    -  0xfffeffff, 0xffff8000, 0xfffeffff, 0xffff0001, 0xfffeffff, 0xffff0000,
    -  0xfffeffff, 0xff000001, 0xfffeffff, 0xff000000, 0xfffeffff, 0xa9cb1d25,
    -  0xfffeffff, 0x48892a0b, 0xfffeffff, 0x00000001, 0xfffeffff, 0x00000000,
    -  0xfffe0000, 0x00000001, 0xfffe0000, 0x00000000, 0xffef0000, 0x00000001,
    -  0xffef0000, 0x00000000, 0xa9ca1d24, 0x48892a0b, 0x7fff0000, 0x00000001,
    -  0x7ffffffe, 0xffffffff, 0x48892a09, 0xa9cb1d24, 0x000fffff, 0x00000000,
    -  0x000ffffe, 0xffffffff, 0x0000ffff, 0x00000000, 0x0000fffe, 0xffffffff,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0x01000000,
    -  0xffffffff, 0x00ffffff, 0xffffffff, 0x00010000, 0xffffffff, 0x0000ffff,
    -  0xffffffff, 0x00008000, 0xffffffff, 0x00007fff, 0xffffffff, 0x00000001,
    -  0xffffffff, 0x00000000, 0xfffffffe, 0xffffffff, 0xfffffffe, 0xfffffffe,
    -  0xfffffffe, 0xfffffffd, 0xfffffffe, 0xffff8000, 0xfffffffe, 0xffff7fff,
    -  0xfffffffe, 0xffff0000, 0xfffffffe, 0xfffeffff, 0xfffffffe, 0xff000000,
    -  0xfffffffe, 0xfeffffff, 0xfffffffe, 0xa9cb1d24, 0xfffffffe, 0x48892a0a,
    -  0xfffffffe, 0x00000000, 0xfffffffd, 0xffffffff, 0xfffeffff, 0x00000000,
    -  0xfffefffe, 0xffffffff, 0xffefffff, 0x00000000, 0xffeffffe, 0xffffffff,
    -  0xa9cb1d23, 0x48892a0a, 0x7fffffff, 0x00000000, 0x7fffffff, 0x00000000,
    -  0x48892a09, 0xa9cb1d25, 0x000fffff, 0x00000001, 0x000fffff, 0x00000000,
    -  0x0000ffff, 0x00000001, 0x0000ffff, 0x00000000, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xffffffff, 0x01000001, 0xffffffff, 0x01000000,
    -  0xffffffff, 0x00010001, 0xffffffff, 0x00010000, 0xffffffff, 0x00008001,
    -  0xffffffff, 0x00008000, 0xffffffff, 0x00000002, 0xffffffff, 0x00000001,
    -  0xffffffff, 0x00000000, 0xfffffffe, 0xffffffff, 0xfffffffe, 0xfffffffe,
    -  0xfffffffe, 0xffff8001, 0xfffffffe, 0xffff8000, 0xfffffffe, 0xffff0001,
    -  0xfffffffe, 0xffff0000, 0xfffffffe, 0xff000001, 0xfffffffe, 0xff000000,
    -  0xfffffffe, 0xa9cb1d25, 0xfffffffe, 0x48892a0b, 0xfffffffe, 0x00000001,
    -  0xfffffffe, 0x00000000, 0xfffeffff, 0x00000001, 0xfffeffff, 0x00000000,
    -  0xffefffff, 0x00000001, 0xffefffff, 0x00000000, 0xa9cb1d23, 0x48892a0b,
    -  0x7fffffff, 0x00000001, 0x7fffffff, 0xfeffffff, 0x48892a0a, 0xa8cb1d24,
    -  0x000fffff, 0xff000000, 0x000fffff, 0xfeffffff, 0x0000ffff, 0xff000000,
    -  0x0000ffff, 0xfeffffff, 0x00000000, 0xff000000, 0x00000000, 0xfeffffff,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xff010000,
    -  0xffffffff, 0xff00ffff, 0xffffffff, 0xff008000, 0xffffffff, 0xff007fff,
    -  0xffffffff, 0xff000001, 0xffffffff, 0xff000000, 0xffffffff, 0xfeffffff,
    -  0xffffffff, 0xfefffffe, 0xffffffff, 0xfefffffd, 0xffffffff, 0xfeff8000,
    -  0xffffffff, 0xfeff7fff, 0xffffffff, 0xfeff0000, 0xffffffff, 0xfefeffff,
    -  0xffffffff, 0xfe000000, 0xffffffff, 0xfdffffff, 0xffffffff, 0xa8cb1d24,
    -  0xffffffff, 0x47892a0a, 0xfffffffe, 0xff000000, 0xfffffffe, 0xfeffffff,
    -  0xfffeffff, 0xff000000, 0xfffeffff, 0xfeffffff, 0xffefffff, 0xff000000,
    -  0xffefffff, 0xfeffffff, 0xa9cb1d24, 0x47892a0a, 0x7fffffff, 0xff000000,
    -  0x7fffffff, 0xff000000, 0x48892a0a, 0xa8cb1d25, 0x000fffff, 0xff000001,
    -  0x000fffff, 0xff000000, 0x0000ffff, 0xff000001, 0x0000ffff, 0xff000000,
    -  0x00000000, 0xff000001, 0x00000000, 0xff000000, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xffffffff, 0xff010001, 0xffffffff, 0xff010000,
    -  0xffffffff, 0xff008001, 0xffffffff, 0xff008000, 0xffffffff, 0xff000002,
    -  0xffffffff, 0xff000001, 0xffffffff, 0xff000000, 0xffffffff, 0xfeffffff,
    -  0xffffffff, 0xfefffffe, 0xffffffff, 0xfeff8001, 0xffffffff, 0xfeff8000,
    -  0xffffffff, 0xfeff0001, 0xffffffff, 0xfeff0000, 0xffffffff, 0xfe000001,
    -  0xffffffff, 0xfe000000, 0xffffffff, 0xa8cb1d25, 0xffffffff, 0x47892a0b,
    -  0xfffffffe, 0xff000001, 0xfffffffe, 0xff000000, 0xfffeffff, 0xff000001,
    -  0xfffeffff, 0xff000000, 0xffefffff, 0xff000001, 0xffefffff, 0xff000000,
    -  0xa9cb1d24, 0x47892a0b, 0x7fffffff, 0xff000001, 0x7fffffff, 0xfffeffff,
    -  0x48892a0a, 0xa9ca1d24, 0x000fffff, 0xffff0000, 0x000fffff, 0xfffeffff,
    -  0x0000ffff, 0xffff0000, 0x0000ffff, 0xfffeffff, 0x00000000, 0xffff0000,
    -  0x00000000, 0xfffeffff, 0x00000000, 0x00ff0000, 0x00000000, 0x00feffff,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff8000,
    -  0xffffffff, 0xffff7fff, 0xffffffff, 0xffff0001, 0xffffffff, 0xffff0000,
    -  0xffffffff, 0xfffeffff, 0xffffffff, 0xfffefffe, 0xffffffff, 0xfffefffd,
    -  0xffffffff, 0xfffe8000, 0xffffffff, 0xfffe7fff, 0xffffffff, 0xfffe0000,
    -  0xffffffff, 0xfffdffff, 0xffffffff, 0xfeff0000, 0xffffffff, 0xfefeffff,
    -  0xffffffff, 0xa9ca1d24, 0xffffffff, 0x48882a0a, 0xfffffffe, 0xffff0000,
    -  0xfffffffe, 0xfffeffff, 0xfffeffff, 0xffff0000, 0xfffeffff, 0xfffeffff,
    -  0xffefffff, 0xffff0000, 0xffefffff, 0xfffeffff, 0xa9cb1d24, 0x48882a0a,
    -  0x7fffffff, 0xffff0000, 0x7fffffff, 0xffff0000, 0x48892a0a, 0xa9ca1d25,
    -  0x000fffff, 0xffff0001, 0x000fffff, 0xffff0000, 0x0000ffff, 0xffff0001,
    -  0x0000ffff, 0xffff0000, 0x00000000, 0xffff0001, 0x00000000, 0xffff0000,
    -  0x00000000, 0x00ff0001, 0x00000000, 0x00ff0000, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffff8001, 0xffffffff, 0xffff8000,
    -  0xffffffff, 0xffff0002, 0xffffffff, 0xffff0001, 0xffffffff, 0xffff0000,
    -  0xffffffff, 0xfffeffff, 0xffffffff, 0xfffefffe, 0xffffffff, 0xfffe8001,
    -  0xffffffff, 0xfffe8000, 0xffffffff, 0xfffe0001, 0xffffffff, 0xfffe0000,
    -  0xffffffff, 0xfeff0001, 0xffffffff, 0xfeff0000, 0xffffffff, 0xa9ca1d25,
    -  0xffffffff, 0x48882a0b, 0xfffffffe, 0xffff0001, 0xfffffffe, 0xffff0000,
    -  0xfffeffff, 0xffff0001, 0xfffeffff, 0xffff0000, 0xffefffff, 0xffff0001,
    -  0xffefffff, 0xffff0000, 0xa9cb1d24, 0x48882a0b, 0x7fffffff, 0xffff0001,
    -  0x7fffffff, 0xffff7fff, 0x48892a0a, 0xa9ca9d24, 0x000fffff, 0xffff8000,
    -  0x000fffff, 0xffff7fff, 0x0000ffff, 0xffff8000, 0x0000ffff, 0xffff7fff,
    -  0x00000000, 0xffff8000, 0x00000000, 0xffff7fff, 0x00000000, 0x00ff8000,
    -  0x00000000, 0x00ff7fff, 0x00000000, 0x00008000, 0x00000000, 0x00007fff,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff8001,
    -  0xffffffff, 0xffff8000, 0xffffffff, 0xffff7fff, 0xffffffff, 0xffff7ffe,
    -  0xffffffff, 0xffff7ffd, 0xffffffff, 0xffff0000, 0xffffffff, 0xfffeffff,
    -  0xffffffff, 0xfffe8000, 0xffffffff, 0xfffe7fff, 0xffffffff, 0xfeff8000,
    -  0xffffffff, 0xfeff7fff, 0xffffffff, 0xa9ca9d24, 0xffffffff, 0x4888aa0a,
    -  0xfffffffe, 0xffff8000, 0xfffffffe, 0xffff7fff, 0xfffeffff, 0xffff8000,
    -  0xfffeffff, 0xffff7fff, 0xffefffff, 0xffff8000, 0xffefffff, 0xffff7fff,
    -  0xa9cb1d24, 0x4888aa0a, 0x7fffffff, 0xffff8000, 0x7fffffff, 0xffff8000,
    -  0x48892a0a, 0xa9ca9d25, 0x000fffff, 0xffff8001, 0x000fffff, 0xffff8000,
    -  0x0000ffff, 0xffff8001, 0x0000ffff, 0xffff8000, 0x00000000, 0xffff8001,
    -  0x00000000, 0xffff8000, 0x00000000, 0x00ff8001, 0x00000000, 0x00ff8000,
    -  0x00000000, 0x00008001, 0x00000000, 0x00008000, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffff8002, 0xffffffff, 0xffff8001,
    -  0xffffffff, 0xffff8000, 0xffffffff, 0xffff7fff, 0xffffffff, 0xffff7ffe,
    -  0xffffffff, 0xffff0001, 0xffffffff, 0xffff0000, 0xffffffff, 0xfffe8001,
    -  0xffffffff, 0xfffe8000, 0xffffffff, 0xfeff8001, 0xffffffff, 0xfeff8000,
    -  0xffffffff, 0xa9ca9d25, 0xffffffff, 0x4888aa0b, 0xfffffffe, 0xffff8001,
    -  0xfffffffe, 0xffff8000, 0xfffeffff, 0xffff8001, 0xfffeffff, 0xffff8000,
    -  0xffefffff, 0xffff8001, 0xffefffff, 0xffff8000, 0xa9cb1d24, 0x4888aa0b,
    -  0x7fffffff, 0xffff8001, 0x7fffffff, 0xfffffffe, 0x48892a0a, 0xa9cb1d23,
    -  0x000fffff, 0xffffffff, 0x000fffff, 0xfffffffe, 0x0000ffff, 0xffffffff,
    -  0x0000ffff, 0xfffffffe, 0x00000000, 0xffffffff, 0x00000000, 0xfffffffe,
    -  0x00000000, 0x00ffffff, 0x00000000, 0x00fffffe, 0x00000000, 0x0000ffff,
    -  0x00000000, 0x0000fffe, 0x00000000, 0x00007fff, 0x00000000, 0x00007ffe,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffffe,
    -  0xffffffff, 0xfffffffd, 0xffffffff, 0xfffffffc, 0xffffffff, 0xffff7fff,
    -  0xffffffff, 0xffff7ffe, 0xffffffff, 0xfffeffff, 0xffffffff, 0xfffefffe,
    -  0xffffffff, 0xfeffffff, 0xffffffff, 0xfefffffe, 0xffffffff, 0xa9cb1d23,
    -  0xffffffff, 0x48892a09, 0xfffffffe, 0xffffffff, 0xfffffffe, 0xfffffffe,
    -  0xfffeffff, 0xffffffff, 0xfffeffff, 0xfffffffe, 0xffefffff, 0xffffffff,
    -  0xffefffff, 0xfffffffe, 0xa9cb1d24, 0x48892a09, 0x7fffffff, 0xffffffff,
    -  0x7fffffff, 0xffffffff, 0x48892a0a, 0xa9cb1d24, 0x00100000, 0x00000000,
    -  0x000fffff, 0xffffffff, 0x00010000, 0x00000000, 0x0000ffff, 0xffffffff,
    -  0x00000001, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0x01000000,
    -  0x00000000, 0x00ffffff, 0x00000000, 0x00010000, 0x00000000, 0x0000ffff,
    -  0x00000000, 0x00008000, 0x00000000, 0x00007fff, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffffe,
    -  0xffffffff, 0xfffffffd, 0xffffffff, 0xffff8000, 0xffffffff, 0xffff7fff,
    -  0xffffffff, 0xffff0000, 0xffffffff, 0xfffeffff, 0xffffffff, 0xff000000,
    -  0xffffffff, 0xfeffffff, 0xffffffff, 0xa9cb1d24, 0xffffffff, 0x48892a0a,
    -  0xffffffff, 0x00000000, 0xfffffffe, 0xffffffff, 0xffff0000, 0x00000000,
    -  0xfffeffff, 0xffffffff, 0xfff00000, 0x00000000, 0xffefffff, 0xffffffff,
    -  0xa9cb1d24, 0x48892a0a, 0x80000000, 0x00000000, 0x80000000, 0x00000000,
    -  0x48892a0a, 0xa9cb1d25, 0x00100000, 0x00000001, 0x00100000, 0x00000000,
    -  0x00010000, 0x00000001, 0x00010000, 0x00000000, 0x00000001, 0x00000001,
    -  0x00000001, 0x00000000, 0x00000000, 0x01000001, 0x00000000, 0x01000000,
    -  0x00000000, 0x00010001, 0x00000000, 0x00010000, 0x00000000, 0x00008001,
    -  0x00000000, 0x00008000, 0x00000000, 0x00000002, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffffe,
    -  0xffffffff, 0xffff8001, 0xffffffff, 0xffff8000, 0xffffffff, 0xffff0001,
    -  0xffffffff, 0xffff0000, 0xffffffff, 0xff000001, 0xffffffff, 0xff000000,
    -  0xffffffff, 0xa9cb1d25, 0xffffffff, 0x48892a0b, 0xffffffff, 0x00000001,
    -  0xffffffff, 0x00000000, 0xffff0000, 0x00000001, 0xffff0000, 0x00000000,
    -  0xfff00000, 0x00000001, 0xfff00000, 0x00000000, 0xa9cb1d24, 0x48892a0b,
    -  0x80000000, 0x00000001, 0x80000000, 0x00000001, 0x48892a0a, 0xa9cb1d26,
    -  0x00100000, 0x00000002, 0x00100000, 0x00000001, 0x00010000, 0x00000002,
    -  0x00010000, 0x00000001, 0x00000001, 0x00000002, 0x00000001, 0x00000001,
    -  0x00000000, 0x01000002, 0x00000000, 0x01000001, 0x00000000, 0x00010002,
    -  0x00000000, 0x00010001, 0x00000000, 0x00008002, 0x00000000, 0x00008001,
    -  0x00000000, 0x00000003, 0x00000000, 0x00000002, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff8002,
    -  0xffffffff, 0xffff8001, 0xffffffff, 0xffff0002, 0xffffffff, 0xffff0001,
    -  0xffffffff, 0xff000002, 0xffffffff, 0xff000001, 0xffffffff, 0xa9cb1d26,
    -  0xffffffff, 0x48892a0c, 0xffffffff, 0x00000002, 0xffffffff, 0x00000001,
    -  0xffff0000, 0x00000002, 0xffff0000, 0x00000001, 0xfff00000, 0x00000002,
    -  0xfff00000, 0x00000001, 0xa9cb1d24, 0x48892a0c, 0x80000000, 0x00000002,
    -  0x80000000, 0x00000002, 0x48892a0a, 0xa9cb1d27, 0x00100000, 0x00000003,
    -  0x00100000, 0x00000002, 0x00010000, 0x00000003, 0x00010000, 0x00000002,
    -  0x00000001, 0x00000003, 0x00000001, 0x00000002, 0x00000000, 0x01000003,
    -  0x00000000, 0x01000002, 0x00000000, 0x00010003, 0x00000000, 0x00010002,
    -  0x00000000, 0x00008003, 0x00000000, 0x00008002, 0x00000000, 0x00000004,
    -  0x00000000, 0x00000003, 0x00000000, 0x00000002, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffff8003, 0xffffffff, 0xffff8002,
    -  0xffffffff, 0xffff0003, 0xffffffff, 0xffff0002, 0xffffffff, 0xff000003,
    -  0xffffffff, 0xff000002, 0xffffffff, 0xa9cb1d27, 0xffffffff, 0x48892a0d,
    -  0xffffffff, 0x00000003, 0xffffffff, 0x00000002, 0xffff0000, 0x00000003,
    -  0xffff0000, 0x00000002, 0xfff00000, 0x00000003, 0xfff00000, 0x00000002,
    -  0xa9cb1d24, 0x48892a0d, 0x80000000, 0x00000003, 0x80000000, 0x00007fff,
    -  0x48892a0a, 0xa9cb9d24, 0x00100000, 0x00008000, 0x00100000, 0x00007fff,
    -  0x00010000, 0x00008000, 0x00010000, 0x00007fff, 0x00000001, 0x00008000,
    -  0x00000001, 0x00007fff, 0x00000000, 0x01008000, 0x00000000, 0x01007fff,
    -  0x00000000, 0x00018000, 0x00000000, 0x00017fff, 0x00000000, 0x00010000,
    -  0x00000000, 0x0000ffff, 0x00000000, 0x00008001, 0x00000000, 0x00008000,
    -  0x00000000, 0x00007fff, 0x00000000, 0x00007ffe, 0x00000000, 0x00007ffd,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff8000,
    -  0xffffffff, 0xffff7fff, 0xffffffff, 0xff008000, 0xffffffff, 0xff007fff,
    -  0xffffffff, 0xa9cb9d24, 0xffffffff, 0x4889aa0a, 0xffffffff, 0x00008000,
    -  0xffffffff, 0x00007fff, 0xffff0000, 0x00008000, 0xffff0000, 0x00007fff,
    -  0xfff00000, 0x00008000, 0xfff00000, 0x00007fff, 0xa9cb1d24, 0x4889aa0a,
    -  0x80000000, 0x00008000, 0x80000000, 0x00008000, 0x48892a0a, 0xa9cb9d25,
    -  0x00100000, 0x00008001, 0x00100000, 0x00008000, 0x00010000, 0x00008001,
    -  0x00010000, 0x00008000, 0x00000001, 0x00008001, 0x00000001, 0x00008000,
    -  0x00000000, 0x01008001, 0x00000000, 0x01008000, 0x00000000, 0x00018001,
    -  0x00000000, 0x00018000, 0x00000000, 0x00010001, 0x00000000, 0x00010000,
    -  0x00000000, 0x00008002, 0x00000000, 0x00008001, 0x00000000, 0x00008000,
    -  0x00000000, 0x00007fff, 0x00000000, 0x00007ffe, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffff8001, 0xffffffff, 0xffff8000,
    -  0xffffffff, 0xff008001, 0xffffffff, 0xff008000, 0xffffffff, 0xa9cb9d25,
    -  0xffffffff, 0x4889aa0b, 0xffffffff, 0x00008001, 0xffffffff, 0x00008000,
    -  0xffff0000, 0x00008001, 0xffff0000, 0x00008000, 0xfff00000, 0x00008001,
    -  0xfff00000, 0x00008000, 0xa9cb1d24, 0x4889aa0b, 0x80000000, 0x00008001,
    -  0x80000000, 0x0000ffff, 0x48892a0a, 0xa9cc1d24, 0x00100000, 0x00010000,
    -  0x00100000, 0x0000ffff, 0x00010000, 0x00010000, 0x00010000, 0x0000ffff,
    -  0x00000001, 0x00010000, 0x00000001, 0x0000ffff, 0x00000000, 0x01010000,
    -  0x00000000, 0x0100ffff, 0x00000000, 0x00020000, 0x00000000, 0x0001ffff,
    -  0x00000000, 0x00018000, 0x00000000, 0x00017fff, 0x00000000, 0x00010001,
    -  0x00000000, 0x00010000, 0x00000000, 0x0000ffff, 0x00000000, 0x0000fffe,
    -  0x00000000, 0x0000fffd, 0x00000000, 0x00008000, 0x00000000, 0x00007fff,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xff010000,
    -  0xffffffff, 0xff00ffff, 0xffffffff, 0xa9cc1d24, 0xffffffff, 0x488a2a0a,
    -  0xffffffff, 0x00010000, 0xffffffff, 0x0000ffff, 0xffff0000, 0x00010000,
    -  0xffff0000, 0x0000ffff, 0xfff00000, 0x00010000, 0xfff00000, 0x0000ffff,
    -  0xa9cb1d24, 0x488a2a0a, 0x80000000, 0x00010000, 0x80000000, 0x00010000,
    -  0x48892a0a, 0xa9cc1d25, 0x00100000, 0x00010001, 0x00100000, 0x00010000,
    -  0x00010000, 0x00010001, 0x00010000, 0x00010000, 0x00000001, 0x00010001,
    -  0x00000001, 0x00010000, 0x00000000, 0x01010001, 0x00000000, 0x01010000,
    -  0x00000000, 0x00020001, 0x00000000, 0x00020000, 0x00000000, 0x00018001,
    -  0x00000000, 0x00018000, 0x00000000, 0x00010002, 0x00000000, 0x00010001,
    -  0x00000000, 0x00010000, 0x00000000, 0x0000ffff, 0x00000000, 0x0000fffe,
    -  0x00000000, 0x00008001, 0x00000000, 0x00008000, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xffffffff, 0xff010001, 0xffffffff, 0xff010000,
    -  0xffffffff, 0xa9cc1d25, 0xffffffff, 0x488a2a0b, 0xffffffff, 0x00010001,
    -  0xffffffff, 0x00010000, 0xffff0000, 0x00010001, 0xffff0000, 0x00010000,
    -  0xfff00000, 0x00010001, 0xfff00000, 0x00010000, 0xa9cb1d24, 0x488a2a0b,
    -  0x80000000, 0x00010001, 0x80000000, 0x00ffffff, 0x48892a0a, 0xaacb1d24,
    -  0x00100000, 0x01000000, 0x00100000, 0x00ffffff, 0x00010000, 0x01000000,
    -  0x00010000, 0x00ffffff, 0x00000001, 0x01000000, 0x00000001, 0x00ffffff,
    -  0x00000000, 0x02000000, 0x00000000, 0x01ffffff, 0x00000000, 0x01010000,
    -  0x00000000, 0x0100ffff, 0x00000000, 0x01008000, 0x00000000, 0x01007fff,
    -  0x00000000, 0x01000001, 0x00000000, 0x01000000, 0x00000000, 0x00ffffff,
    -  0x00000000, 0x00fffffe, 0x00000000, 0x00fffffd, 0x00000000, 0x00ff8000,
    -  0x00000000, 0x00ff7fff, 0x00000000, 0x00ff0000, 0x00000000, 0x00feffff,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xaacb1d24,
    -  0xffffffff, 0x49892a0a, 0xffffffff, 0x01000000, 0xffffffff, 0x00ffffff,
    -  0xffff0000, 0x01000000, 0xffff0000, 0x00ffffff, 0xfff00000, 0x01000000,
    -  0xfff00000, 0x00ffffff, 0xa9cb1d24, 0x49892a0a, 0x80000000, 0x01000000,
    -  0x80000000, 0x01000000, 0x48892a0a, 0xaacb1d25, 0x00100000, 0x01000001,
    -  0x00100000, 0x01000000, 0x00010000, 0x01000001, 0x00010000, 0x01000000,
    -  0x00000001, 0x01000001, 0x00000001, 0x01000000, 0x00000000, 0x02000001,
    -  0x00000000, 0x02000000, 0x00000000, 0x01010001, 0x00000000, 0x01010000,
    -  0x00000000, 0x01008001, 0x00000000, 0x01008000, 0x00000000, 0x01000002,
    -  0x00000000, 0x01000001, 0x00000000, 0x01000000, 0x00000000, 0x00ffffff,
    -  0x00000000, 0x00fffffe, 0x00000000, 0x00ff8001, 0x00000000, 0x00ff8000,
    -  0x00000000, 0x00ff0001, 0x00000000, 0x00ff0000, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xffffffff, 0xaacb1d25, 0xffffffff, 0x49892a0b,
    -  0xffffffff, 0x01000001, 0xffffffff, 0x01000000, 0xffff0000, 0x01000001,
    -  0xffff0000, 0x01000000, 0xfff00000, 0x01000001, 0xfff00000, 0x01000000,
    -  0xa9cb1d24, 0x49892a0b, 0x80000000, 0x01000001, 0x80000000, 0x5634e2db,
    -  0x48892a0b, 0x00000000, 0x00100000, 0x5634e2dc, 0x00100000, 0x5634e2db,
    -  0x00010000, 0x5634e2dc, 0x00010000, 0x5634e2db, 0x00000001, 0x5634e2dc,
    -  0x00000001, 0x5634e2db, 0x00000000, 0x5734e2dc, 0x00000000, 0x5734e2db,
    -  0x00000000, 0x5635e2dc, 0x00000000, 0x5635e2db, 0x00000000, 0x563562dc,
    -  0x00000000, 0x563562db, 0x00000000, 0x5634e2dd, 0x00000000, 0x5634e2dc,
    -  0x00000000, 0x5634e2db, 0x00000000, 0x5634e2da, 0x00000000, 0x5634e2d9,
    -  0x00000000, 0x563462dc, 0x00000000, 0x563462db, 0x00000000, 0x5633e2dc,
    -  0x00000000, 0x5633e2db, 0x00000000, 0x5534e2dc, 0x00000000, 0x5534e2db,
    -  0x00000000, 0x00000000, 0xffffffff, 0x9ebe0ce6, 0xffffffff, 0x5634e2dc,
    -  0xffffffff, 0x5634e2db, 0xffff0000, 0x5634e2dc, 0xffff0000, 0x5634e2db,
    -  0xfff00000, 0x5634e2dc, 0xfff00000, 0x5634e2db, 0xa9cb1d24, 0x9ebe0ce6,
    -  0x80000000, 0x5634e2dc, 0x80000000, 0xb776d5f5, 0x48892a0b, 0x6141f31a,
    -  0x00100000, 0xb776d5f6, 0x00100000, 0xb776d5f5, 0x00010000, 0xb776d5f6,
    -  0x00010000, 0xb776d5f5, 0x00000001, 0xb776d5f6, 0x00000001, 0xb776d5f5,
    -  0x00000000, 0xb876d5f6, 0x00000000, 0xb876d5f5, 0x00000000, 0xb777d5f6,
    -  0x00000000, 0xb777d5f5, 0x00000000, 0xb77755f6, 0x00000000, 0xb77755f5,
    -  0x00000000, 0xb776d5f7, 0x00000000, 0xb776d5f6, 0x00000000, 0xb776d5f5,
    -  0x00000000, 0xb776d5f4, 0x00000000, 0xb776d5f3, 0x00000000, 0xb77655f6,
    -  0x00000000, 0xb77655f5, 0x00000000, 0xb775d5f6, 0x00000000, 0xb775d5f5,
    -  0x00000000, 0xb676d5f6, 0x00000000, 0xb676d5f5, 0x00000000, 0x6141f31a,
    -  0x00000000, 0x00000000, 0xffffffff, 0xb776d5f6, 0xffffffff, 0xb776d5f5,
    -  0xffff0000, 0xb776d5f6, 0xffff0000, 0xb776d5f5, 0xfff00000, 0xb776d5f6,
    -  0xfff00000, 0xb776d5f5, 0xa9cb1d25, 0x00000000, 0x80000000, 0xb776d5f6,
    -  0x80000000, 0xffffffff, 0x48892a0b, 0xa9cb1d24, 0x00100001, 0x00000000,
    -  0x00100000, 0xffffffff, 0x00010001, 0x00000000, 0x00010000, 0xffffffff,
    -  0x00000002, 0x00000000, 0x00000001, 0xffffffff, 0x00000001, 0x01000000,
    -  0x00000001, 0x00ffffff, 0x00000001, 0x00010000, 0x00000001, 0x0000ffff,
    -  0x00000001, 0x00008000, 0x00000001, 0x00007fff, 0x00000001, 0x00000001,
    -  0x00000001, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0xfffffffe,
    -  0x00000000, 0xfffffffd, 0x00000000, 0xffff8000, 0x00000000, 0xffff7fff,
    -  0x00000000, 0xffff0000, 0x00000000, 0xfffeffff, 0x00000000, 0xff000000,
    -  0x00000000, 0xfeffffff, 0x00000000, 0xa9cb1d24, 0x00000000, 0x48892a0a,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffff0001, 0x00000000,
    -  0xffff0000, 0xffffffff, 0xfff00001, 0x00000000, 0xfff00000, 0xffffffff,
    -  0xa9cb1d25, 0x48892a0a, 0x80000001, 0x00000000, 0x80000001, 0x00000000,
    -  0x48892a0b, 0xa9cb1d25, 0x00100001, 0x00000001, 0x00100001, 0x00000000,
    -  0x00010001, 0x00000001, 0x00010001, 0x00000000, 0x00000002, 0x00000001,
    -  0x00000002, 0x00000000, 0x00000001, 0x01000001, 0x00000001, 0x01000000,
    -  0x00000001, 0x00010001, 0x00000001, 0x00010000, 0x00000001, 0x00008001,
    -  0x00000001, 0x00008000, 0x00000001, 0x00000002, 0x00000001, 0x00000001,
    -  0x00000001, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0xfffffffe,
    -  0x00000000, 0xffff8001, 0x00000000, 0xffff8000, 0x00000000, 0xffff0001,
    -  0x00000000, 0xffff0000, 0x00000000, 0xff000001, 0x00000000, 0xff000000,
    -  0x00000000, 0xa9cb1d25, 0x00000000, 0x48892a0b, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xffff0001, 0x00000001, 0xffff0001, 0x00000000,
    -  0xfff00001, 0x00000001, 0xfff00001, 0x00000000, 0xa9cb1d25, 0x48892a0b,
    -  0x80000001, 0x00000001, 0x8000ffff, 0xffffffff, 0x488a2a0a, 0xa9cb1d24,
    -  0x00110000, 0x00000000, 0x0010ffff, 0xffffffff, 0x00020000, 0x00000000,
    -  0x0001ffff, 0xffffffff, 0x00010001, 0x00000000, 0x00010000, 0xffffffff,
    -  0x00010000, 0x01000000, 0x00010000, 0x00ffffff, 0x00010000, 0x00010000,
    -  0x00010000, 0x0000ffff, 0x00010000, 0x00008000, 0x00010000, 0x00007fff,
    -  0x00010000, 0x00000001, 0x00010000, 0x00000000, 0x0000ffff, 0xffffffff,
    -  0x0000ffff, 0xfffffffe, 0x0000ffff, 0xfffffffd, 0x0000ffff, 0xffff8000,
    -  0x0000ffff, 0xffff7fff, 0x0000ffff, 0xffff0000, 0x0000ffff, 0xfffeffff,
    -  0x0000ffff, 0xff000000, 0x0000ffff, 0xfeffffff, 0x0000ffff, 0xa9cb1d24,
    -  0x0000ffff, 0x48892a0a, 0x0000ffff, 0x00000000, 0x0000fffe, 0xffffffff,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xfff10000, 0x00000000,
    -  0xfff0ffff, 0xffffffff, 0xa9cc1d24, 0x48892a0a, 0x80010000, 0x00000000,
    -  0x80010000, 0x00000000, 0x488a2a0a, 0xa9cb1d25, 0x00110000, 0x00000001,
    -  0x00110000, 0x00000000, 0x00020000, 0x00000001, 0x00020000, 0x00000000,
    -  0x00010001, 0x00000001, 0x00010001, 0x00000000, 0x00010000, 0x01000001,
    -  0x00010000, 0x01000000, 0x00010000, 0x00010001, 0x00010000, 0x00010000,
    -  0x00010000, 0x00008001, 0x00010000, 0x00008000, 0x00010000, 0x00000002,
    -  0x00010000, 0x00000001, 0x00010000, 0x00000000, 0x0000ffff, 0xffffffff,
    -  0x0000ffff, 0xfffffffe, 0x0000ffff, 0xffff8001, 0x0000ffff, 0xffff8000,
    -  0x0000ffff, 0xffff0001, 0x0000ffff, 0xffff0000, 0x0000ffff, 0xff000001,
    -  0x0000ffff, 0xff000000, 0x0000ffff, 0xa9cb1d25, 0x0000ffff, 0x48892a0b,
    -  0x0000ffff, 0x00000001, 0x0000ffff, 0x00000000, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xfff10000, 0x00000001, 0xfff10000, 0x00000000,
    -  0xa9cc1d24, 0x48892a0b, 0x80010000, 0x00000001, 0x800fffff, 0xffffffff,
    -  0x48992a0a, 0xa9cb1d24, 0x00200000, 0x00000000, 0x001fffff, 0xffffffff,
    -  0x00110000, 0x00000000, 0x0010ffff, 0xffffffff, 0x00100001, 0x00000000,
    -  0x00100000, 0xffffffff, 0x00100000, 0x01000000, 0x00100000, 0x00ffffff,
    -  0x00100000, 0x00010000, 0x00100000, 0x0000ffff, 0x00100000, 0x00008000,
    -  0x00100000, 0x00007fff, 0x00100000, 0x00000001, 0x00100000, 0x00000000,
    -  0x000fffff, 0xffffffff, 0x000fffff, 0xfffffffe, 0x000fffff, 0xfffffffd,
    -  0x000fffff, 0xffff8000, 0x000fffff, 0xffff7fff, 0x000fffff, 0xffff0000,
    -  0x000fffff, 0xfffeffff, 0x000fffff, 0xff000000, 0x000fffff, 0xfeffffff,
    -  0x000fffff, 0xa9cb1d24, 0x000fffff, 0x48892a0a, 0x000fffff, 0x00000000,
    -  0x000ffffe, 0xffffffff, 0x000f0000, 0x00000000, 0x000effff, 0xffffffff,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xa9db1d24, 0x48892a0a,
    -  0x80100000, 0x00000000, 0x80100000, 0x00000000, 0x48992a0a, 0xa9cb1d25,
    -  0x00200000, 0x00000001, 0x00200000, 0x00000000, 0x00110000, 0x00000001,
    -  0x00110000, 0x00000000, 0x00100001, 0x00000001, 0x00100001, 0x00000000,
    -  0x00100000, 0x01000001, 0x00100000, 0x01000000, 0x00100000, 0x00010001,
    -  0x00100000, 0x00010000, 0x00100000, 0x00008001, 0x00100000, 0x00008000,
    -  0x00100000, 0x00000002, 0x00100000, 0x00000001, 0x00100000, 0x00000000,
    -  0x000fffff, 0xffffffff, 0x000fffff, 0xfffffffe, 0x000fffff, 0xffff8001,
    -  0x000fffff, 0xffff8000, 0x000fffff, 0xffff0001, 0x000fffff, 0xffff0000,
    -  0x000fffff, 0xff000001, 0x000fffff, 0xff000000, 0x000fffff, 0xa9cb1d25,
    -  0x000fffff, 0x48892a0b, 0x000fffff, 0x00000001, 0x000fffff, 0x00000000,
    -  0x000f0000, 0x00000001, 0x000f0000, 0x00000000, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0xa9db1d24, 0x48892a0b, 0x80100000, 0x00000001,
    -  0xd634e2db, 0xb776d5f5, 0x9ebe0ce6, 0x6141f31a, 0x5644e2db, 0xb776d5f6,
    -  0x5644e2db, 0xb776d5f5, 0x5635e2db, 0xb776d5f6, 0x5635e2db, 0xb776d5f5,
    -  0x5634e2dc, 0xb776d5f6, 0x5634e2dc, 0xb776d5f5, 0x5634e2db, 0xb876d5f6,
    -  0x5634e2db, 0xb876d5f5, 0x5634e2db, 0xb777d5f6, 0x5634e2db, 0xb777d5f5,
    -  0x5634e2db, 0xb77755f6, 0x5634e2db, 0xb77755f5, 0x5634e2db, 0xb776d5f7,
    -  0x5634e2db, 0xb776d5f6, 0x5634e2db, 0xb776d5f5, 0x5634e2db, 0xb776d5f4,
    -  0x5634e2db, 0xb776d5f3, 0x5634e2db, 0xb77655f6, 0x5634e2db, 0xb77655f5,
    -  0x5634e2db, 0xb775d5f6, 0x5634e2db, 0xb775d5f5, 0x5634e2db, 0xb676d5f6,
    -  0x5634e2db, 0xb676d5f5, 0x5634e2db, 0x6141f31a, 0x5634e2db, 0x00000000,
    -  0x5634e2da, 0xb776d5f6, 0x5634e2da, 0xb776d5f5, 0x5633e2db, 0xb776d5f6,
    -  0x5633e2db, 0xb776d5f5, 0x5624e2db, 0xb776d5f6, 0x5624e2db, 0xb776d5f5,
    -  0x00000000, 0x00000000, 0xd634e2db, 0xb776d5f6, 0xffffffff, 0xffffffff,
    -  0xc8892a0a, 0xa9cb1d24, 0x80100000, 0x00000000, 0x800fffff, 0xffffffff,
    -  0x80010000, 0x00000000, 0x8000ffff, 0xffffffff, 0x80000001, 0x00000000,
    -  0x80000000, 0xffffffff, 0x80000000, 0x01000000, 0x80000000, 0x00ffffff,
    -  0x80000000, 0x00010000, 0x80000000, 0x0000ffff, 0x80000000, 0x00008000,
    -  0x80000000, 0x00007fff, 0x80000000, 0x00000001, 0x80000000, 0x00000000,
    -  0x7fffffff, 0xffffffff, 0x7fffffff, 0xfffffffe, 0x7fffffff, 0xfffffffd,
    -  0x7fffffff, 0xffff8000, 0x7fffffff, 0xffff7fff, 0x7fffffff, 0xffff0000,
    -  0x7fffffff, 0xfffeffff, 0x7fffffff, 0xff000000, 0x7fffffff, 0xfeffffff,
    -  0x7fffffff, 0xa9cb1d24, 0x7fffffff, 0x48892a0a, 0x7fffffff, 0x00000000,
    -  0x7ffffffe, 0xffffffff, 0x7fff0000, 0x00000000, 0x7ffeffff, 0xffffffff,
    -  0x7ff00000, 0x00000000, 0x7fefffff, 0xffffffff, 0x29cb1d24, 0x48892a0a,
    -  0x00000000, 0x00000000
    -];
    -toInt32s(TEST_SUB_BITS);
    -
    -var TEST_MUL_BITS = [
    -  0x80000000, 0x00000000, 0x80000000, 0x00000000, 0x1ad92a0a, 0xa9cb1d25,
    -  0x00000000, 0x00000000, 0xd2500000, 0x00000000, 0x00100000, 0x00000000,
    -  0x80000000, 0x00000000, 0x65ae2a0a, 0xa9cb1d25, 0x00110000, 0x00000001,
    -  0x00100000, 0x00000000, 0x00000000, 0x00000000, 0x1d250000, 0x00000000,
    -  0x00010000, 0x00000000, 0x00000000, 0x00000000, 0x00010000, 0x00000000,
    -  0x80000000, 0x00000000, 0xf254472f, 0xa9cb1d25, 0x00100001, 0x00000001,
    -  0x00100000, 0x00000000, 0x00010001, 0x00000001, 0x00010000, 0x00000000,
    -  0x00000000, 0x00000000, 0xa9cb1d25, 0x00000000, 0x00000001, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000001, 0x00000000, 0x80000000, 0x00000000, 0x5332f527, 0xcecb1d25,
    -  0x00100000, 0x01000001, 0x00100000, 0x00000000, 0x00010000, 0x01000001,
    -  0x00010000, 0x00000000, 0x01000001, 0x01000001, 0x01000001, 0x00000000,
    -  0x00000000, 0x00000000, 0x0aa9cb1d, 0x25000000, 0x00000000, 0x01000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x01000000, 0x00000000, 0x00000000,
    -  0x01000000, 0x01000000, 0x01000000, 0x00000000, 0x00010000, 0x01000000,
    -  0x80000000, 0x00000000, 0x7293d3d5, 0xc6f01d25, 0x00100000, 0x00010001,
    -  0x00100000, 0x00000000, 0x00010000, 0x00010001, 0x00010000, 0x00000000,
    -  0x00010001, 0x00010001, 0x00010001, 0x00000000, 0x00000100, 0x01010001,
    -  0x00000100, 0x01000000, 0x00000000, 0x00000000, 0x2a0aa9cb, 0x1d250000,
    -  0x00000000, 0x00010000, 0x00000000, 0x00000000, 0x00000000, 0x00010000,
    -  0x00000000, 0x00000000, 0x00010000, 0x00010000, 0x00010000, 0x00000000,
    -  0x00000100, 0x00010000, 0x00000100, 0x00000000, 0x00000001, 0x00010000,
    -  0x80000000, 0x00000000, 0xdd8e7ef0, 0x385d9d25, 0x00100000, 0x00008001,
    -  0x00100000, 0x00000000, 0x80010000, 0x00008001, 0x80010000, 0x00000000,
    -  0x00008001, 0x00008001, 0x00008001, 0x00000000, 0x00000080, 0x01008001,
    -  0x00000080, 0x01000000, 0x00000000, 0x80018001, 0x00000000, 0x80010000,
    -  0x00000000, 0x00000000, 0x950554e5, 0x8e928000, 0x00000000, 0x00008000,
    -  0x00000000, 0x00000000, 0x80000000, 0x00008000, 0x80000000, 0x00000000,
    -  0x00008000, 0x00008000, 0x00008000, 0x00000000, 0x00000080, 0x00008000,
    -  0x00000080, 0x00000000, 0x00000000, 0x80008000, 0x00000000, 0x80000000,
    -  0x00000000, 0x40008000, 0x00000000, 0x00000000, 0x91125415, 0x53963a4a,
    -  0x00200000, 0x00000002, 0x00200000, 0x00000000, 0x00020000, 0x00000002,
    -  0x00020000, 0x00000000, 0x00000002, 0x00000002, 0x00000002, 0x00000000,
    -  0x00000000, 0x02000002, 0x00000000, 0x02000000, 0x00000000, 0x00020002,
    -  0x00000000, 0x00020000, 0x00000000, 0x00010002, 0x00000000, 0x00010000,
    -  0x80000000, 0x00000000, 0x48892a0a, 0xa9cb1d25, 0x00100000, 0x00000001,
    -  0x00100000, 0x00000000, 0x00010000, 0x00000001, 0x00010000, 0x00000000,
    -  0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x01000001,
    -  0x00000000, 0x01000000, 0x00000000, 0x00010001, 0x00000000, 0x00010000,
    -  0x00000000, 0x00008001, 0x00000000, 0x00008000, 0x00000000, 0x00000002,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x80000000, 0x00000000, 0xb776d5f5, 0x5634e2db,
    -  0xffefffff, 0xffffffff, 0xfff00000, 0x00000000, 0xfffeffff, 0xffffffff,
    -  0xffff0000, 0x00000000, 0xfffffffe, 0xffffffff, 0xffffffff, 0x00000000,
    -  0xffffffff, 0xfeffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xfffeffff,
    -  0xffffffff, 0xffff0000, 0xffffffff, 0xffff7fff, 0xffffffff, 0xffff8000,
    -  0xffffffff, 0xfffffffe, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x6eedabea, 0xac69c5b6, 0xffdfffff, 0xfffffffe,
    -  0xffe00000, 0x00000000, 0xfffdffff, 0xfffffffe, 0xfffe0000, 0x00000000,
    -  0xfffffffd, 0xfffffffe, 0xfffffffe, 0x00000000, 0xffffffff, 0xfdfffffe,
    -  0xffffffff, 0xfe000000, 0xffffffff, 0xfffdfffe, 0xffffffff, 0xfffe0000,
    -  0xffffffff, 0xfffefffe, 0xffffffff, 0xffff0000, 0xffffffff, 0xfffffffc,
    -  0xffffffff, 0xfffffffe, 0x00000000, 0x00000000, 0x00000000, 0x00000002,
    -  0x80000000, 0x00000000, 0xb383d525, 0x1b389d25, 0x000fffff, 0xffff8001,
    -  0x00100000, 0x00000000, 0x8000ffff, 0xffff8001, 0x80010000, 0x00000000,
    -  0xffff8000, 0xffff8001, 0xffff8001, 0x00000000, 0xffffff80, 0x00ff8001,
    -  0xffffff80, 0x01000000, 0xffffffff, 0x80008001, 0xffffffff, 0x80010000,
    -  0xffffffff, 0xc0000001, 0xffffffff, 0xc0008000, 0xffffffff, 0xffff0002,
    -  0xffffffff, 0xffff8001, 0x00000000, 0x00000000, 0x00000000, 0x00007fff,
    -  0x00000000, 0x0000fffe, 0x00000000, 0x00000000, 0x6afaab1a, 0x716d8000,
    -  0xffffffff, 0xffff8000, 0x00000000, 0x00000000, 0x7fffffff, 0xffff8000,
    -  0x80000000, 0x00000000, 0xffff7fff, 0xffff8000, 0xffff8000, 0x00000000,
    -  0xffffff7f, 0xffff8000, 0xffffff80, 0x00000000, 0xffffffff, 0x7fff8000,
    -  0xffffffff, 0x80000000, 0xffffffff, 0xbfff8000, 0xffffffff, 0xc0000000,
    -  0xffffffff, 0xffff0000, 0xffffffff, 0xffff8000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00008000, 0x00000000, 0x00010000, 0x00000000, 0x3fff8000,
    -  0x80000000, 0x00000000, 0x1e7e803f, 0x8ca61d25, 0x000fffff, 0xffff0001,
    -  0x00100000, 0x00000000, 0x0000ffff, 0xffff0001, 0x00010000, 0x00000000,
    -  0xffff0000, 0xffff0001, 0xffff0001, 0x00000000, 0xffffff00, 0x00ff0001,
    -  0xffffff00, 0x01000000, 0xffffffff, 0x00000001, 0xffffffff, 0x00010000,
    -  0xffffffff, 0x7fff8001, 0xffffffff, 0x80008000, 0xffffffff, 0xfffe0002,
    -  0xffffffff, 0xffff0001, 0x00000000, 0x00000000, 0x00000000, 0x0000ffff,
    -  0x00000000, 0x0001fffe, 0x00000000, 0x7ffe8001, 0x00000000, 0x7fff8000,
    -  0x00000000, 0x00000000, 0xd5f55634, 0xe2db0000, 0xffffffff, 0xffff0000,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffff0000, 0x00000000, 0x00000000,
    -  0xfffeffff, 0xffff0000, 0xffff0000, 0x00000000, 0xfffffeff, 0xffff0000,
    -  0xffffff00, 0x00000000, 0xfffffffe, 0xffff0000, 0xffffffff, 0x00000000,
    -  0xffffffff, 0x7fff0000, 0xffffffff, 0x80000000, 0xffffffff, 0xfffe0000,
    -  0xffffffff, 0xffff0000, 0x00000000, 0x00000000, 0x00000000, 0x00010000,
    -  0x00000000, 0x00020000, 0x00000000, 0x7fff0000, 0x00000000, 0x80000000,
    -  0x00000000, 0xffff0000, 0x80000000, 0x00000000, 0x3ddf5eed, 0x84cb1d25,
    -  0x000fffff, 0xff000001, 0x00100000, 0x00000000, 0x0000ffff, 0xff000001,
    -  0x00010000, 0x00000000, 0xff000000, 0xff000001, 0xff000001, 0x00000000,
    -  0xffff0000, 0x00000001, 0xffff0000, 0x01000000, 0xfffffeff, 0xff010001,
    -  0xffffff00, 0x00010000, 0xffffff7f, 0xff008001, 0xffffff80, 0x00008000,
    -  0xffffffff, 0xfe000002, 0xffffffff, 0xff000001, 0x00000000, 0x00000000,
    -  0x00000000, 0x00ffffff, 0x00000000, 0x01fffffe, 0x0000007f, 0xfeff8001,
    -  0x0000007f, 0xffff8000, 0x000000ff, 0xfeff0001, 0x000000ff, 0xffff0000,
    -  0x00000000, 0x00000000, 0xf55634e2, 0xdb000000, 0xffffffff, 0xff000000,
    -  0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0x00000000, 0x00000000,
    -  0xfeffffff, 0xff000000, 0xff000000, 0x00000000, 0xfffeffff, 0xff000000,
    -  0xffff0000, 0x00000000, 0xfffffeff, 0xff000000, 0xffffff00, 0x00000000,
    -  0xffffff7f, 0xff000000, 0xffffff80, 0x00000000, 0xffffffff, 0xfe000000,
    -  0xffffffff, 0xff000000, 0x00000000, 0x00000000, 0x00000000, 0x01000000,
    -  0x00000000, 0x02000000, 0x0000007f, 0xff000000, 0x00000080, 0x00000000,
    -  0x000000ff, 0xff000000, 0x00000100, 0x00000000, 0x0000ffff, 0xff000000,
    -  0x80000000, 0x00000000, 0xbc56e5ef, 0x15ff6759, 0xd24fffff, 0xa9cb1d25,
    -  0xd2500000, 0x00000000, 0x1d24ffff, 0xa9cb1d25, 0x1d250000, 0x00000000,
    -  0xa9cb1d24, 0xa9cb1d25, 0xa9cb1d25, 0x00000000, 0xffa9cb1c, 0xcecb1d25,
    -  0xffa9cb1d, 0x25000000, 0xffffa9ca, 0xc6f01d25, 0xffffa9cb, 0x1d250000,
    -  0xffffd4e5, 0x385d9d25, 0xffffd4e5, 0x8e928000, 0xffffffff, 0x53963a4a,
    -  0xffffffff, 0xa9cb1d25, 0x00000000, 0x00000000, 0x00000000, 0x5634e2db,
    -  0x00000000, 0xac69c5b6, 0x00002b1a, 0x1b389d25, 0x00002b1a, 0x716d8000,
    -  0x00005634, 0x8ca61d25, 0x00005634, 0xe2db0000, 0x005634e2, 0x84cb1d25,
    -  0x005634e2, 0xdb000000, 0x80000000, 0x00000000, 0x74756f10, 0x9f4f5297,
    -  0xa0afffff, 0x48892a0b, 0xa0b00000, 0x00000000, 0x2a0affff, 0x48892a0b,
    -  0x2a0b0000, 0x00000000, 0x48892a0a, 0x48892a0b, 0x48892a0b, 0x00000000,
    -  0xff488929, 0x53892a0b, 0xff48892a, 0x0b000000, 0xffff4888, 0x72942a0b,
    -  0xffff4889, 0x2a0b0000, 0xffffa443, 0xdd8eaa0b, 0xffffa444, 0x95058000,
    -  0xfffffffe, 0x91125416, 0xffffffff, 0x48892a0b, 0x00000000, 0x00000000,
    -  0x00000000, 0xb776d5f5, 0x00000001, 0x6eedabea, 0x00005bba, 0xb383aa0b,
    -  0x00005bbb, 0x6afa8000, 0x0000b776, 0x1e7e2a0b, 0x0000b776, 0xd5f50000,
    -  0x00b776d5, 0x3d892a0b, 0x00b776d5, 0xf5000000, 0x3dc7d297, 0x9f4f5297,
    -  0x80000000, 0x00000000, 0x9ebe0ce5, 0xa9cb1d25, 0x000fffff, 0x00000001,
    -  0x00100000, 0x00000000, 0x0000ffff, 0x00000001, 0x00010000, 0x00000000,
    -  0x00000000, 0x00000001, 0x00000001, 0x00000000, 0xfeffffff, 0x01000001,
    -  0xff000000, 0x01000000, 0xfffeffff, 0x00010001, 0xffff0000, 0x00010000,
    -  0xffff7fff, 0x00008001, 0xffff8000, 0x00008000, 0xfffffffe, 0x00000002,
    -  0xffffffff, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
    -  0x00000001, 0xfffffffe, 0x00007ffe, 0xffff8001, 0x00007fff, 0xffff8000,
    -  0x0000fffe, 0xffff0001, 0x0000ffff, 0xffff0000, 0x00fffffe, 0xff000001,
    -  0x00ffffff, 0xff000000, 0x5634e2da, 0xa9cb1d25, 0xb776d5f4, 0x48892a0b,
    -  0x00000000, 0x00000000, 0x5634e2db, 0x00000000, 0xffffffff, 0x00000000,
    -  0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
    -  0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xfeffffff, 0x00000000,
    -  0xff000000, 0x00000000, 0xfffeffff, 0x00000000, 0xffff0000, 0x00000000,
    -  0xffff7fff, 0x00000000, 0xffff8000, 0x00000000, 0xfffffffe, 0x00000000,
    -  0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000,
    -  0x00000002, 0x00000000, 0x00007fff, 0x00000000, 0x00008000, 0x00000000,
    -  0x0000ffff, 0x00000000, 0x00010000, 0x00000000, 0x00ffffff, 0x00000000,
    -  0x01000000, 0x00000000, 0x5634e2db, 0x00000000, 0xb776d5f5, 0x00000000,
    -  0xffffffff, 0x00000000, 0x80000000, 0x00000000, 0x2b642a0a, 0xa9cb1d25,
    -  0x000f0000, 0x00000001, 0x00100000, 0x00000000, 0x00000000, 0x00000001,
    -  0x00010000, 0x00000000, 0xffff0001, 0x00000001, 0x00000001, 0x00000000,
    -  0xffff0000, 0x01000001, 0x00000000, 0x01000000, 0xffff0000, 0x00010001,
    -  0x00000000, 0x00010000, 0x7fff0000, 0x00008001, 0x80000000, 0x00008000,
    -  0xfffe0000, 0x00000002, 0xffff0000, 0x00000001, 0x00000000, 0x00000000,
    -  0x0000ffff, 0xffffffff, 0x0001ffff, 0xfffffffe, 0x7ffeffff, 0xffff8001,
    -  0x7fffffff, 0xffff8000, 0xfffeffff, 0xffff0001, 0xffffffff, 0xffff0000,
    -  0xfffeffff, 0xff000001, 0xffffffff, 0xff000000, 0xe2daffff, 0xa9cb1d25,
    -  0xd5f4ffff, 0x48892a0b, 0xfffeffff, 0x00000001, 0xffffffff, 0x00000000,
    -  0x00000000, 0x00000000, 0xe2db0000, 0x00000000, 0xffff0000, 0x00000000,
    -  0x00000000, 0x00000000, 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
    -  0xffff0000, 0x00000000, 0x00000000, 0x00000000, 0xffff0000, 0x00000000,
    -  0x00000000, 0x00000000, 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
    -  0x7fff0000, 0x00000000, 0x80000000, 0x00000000, 0xfffe0000, 0x00000000,
    -  0xffff0000, 0x00000000, 0x00000000, 0x00000000, 0x00010000, 0x00000000,
    -  0x00020000, 0x00000000, 0x7fff0000, 0x00000000, 0x80000000, 0x00000000,
    -  0xffff0000, 0x00000000, 0x00000000, 0x00000000, 0xffff0000, 0x00000000,
    -  0x00000000, 0x00000000, 0xe2db0000, 0x00000000, 0xd5f50000, 0x00000000,
    -  0xffff0000, 0x00000000, 0x00000000, 0x00000000, 0xffff0000, 0x00000000,
    -  0x80000000, 0x00000000, 0x76392a0a, 0xa9cb1d25, 0x00000000, 0x00000001,
    -  0x00100000, 0x00000000, 0xfff10000, 0x00000001, 0x00010000, 0x00000000,
    -  0xfff00001, 0x00000001, 0x00000001, 0x00000000, 0xfff00000, 0x01000001,
    -  0x00000000, 0x01000000, 0xfff00000, 0x00010001, 0x00000000, 0x00010000,
    -  0xfff00000, 0x00008001, 0x00000000, 0x00008000, 0xffe00000, 0x00000002,
    -  0xfff00000, 0x00000001, 0x00000000, 0x00000000, 0x000fffff, 0xffffffff,
    -  0x001fffff, 0xfffffffe, 0xffefffff, 0xffff8001, 0xffffffff, 0xffff8000,
    -  0xffefffff, 0xffff0001, 0xffffffff, 0xffff0000, 0xffefffff, 0xff000001,
    -  0xffffffff, 0xff000000, 0x2dafffff, 0xa9cb1d25, 0x5f4fffff, 0x48892a0b,
    -  0xffefffff, 0x00000001, 0xffffffff, 0x00000000, 0xffef0000, 0x00000001,
    -  0xffff0000, 0x00000000, 0x00000000, 0x00000000, 0x2db00000, 0x00000000,
    -  0xfff00000, 0x00000000, 0x00000000, 0x00000000, 0xfff00000, 0x00000000,
    -  0x00000000, 0x00000000, 0xfff00000, 0x00000000, 0x00000000, 0x00000000,
    -  0xfff00000, 0x00000000, 0x00000000, 0x00000000, 0xfff00000, 0x00000000,
    -  0x00000000, 0x00000000, 0xfff00000, 0x00000000, 0x00000000, 0x00000000,
    -  0xffe00000, 0x00000000, 0xfff00000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00100000, 0x00000000, 0x00200000, 0x00000000, 0xfff00000, 0x00000000,
    -  0x00000000, 0x00000000, 0xfff00000, 0x00000000, 0x00000000, 0x00000000,
    -  0xfff00000, 0x00000000, 0x00000000, 0x00000000, 0x2db00000, 0x00000000,
    -  0x5f500000, 0x00000000, 0xfff00000, 0x00000000, 0x00000000, 0x00000000,
    -  0xfff00000, 0x00000000, 0x00000000, 0x00000000, 0xfff00000, 0x00000000,
    -  0x80000000, 0x00000000, 0x8a74d669, 0x9f4f5297, 0x4a7b1d24, 0x48892a0b,
    -  0xa0b00000, 0x00000000, 0xd3d61d24, 0x48892a0b, 0x2a0b0000, 0x00000000,
    -  0xf254472f, 0x48892a0b, 0x48892a0b, 0x00000000, 0xce13a64e, 0x53892a0b,
    -  0x2448892a, 0x0b000000, 0xc6ef65ad, 0x72942a0b, 0x1d244889, 0x2a0b0000,
    -  0x385d4168, 0xdd8eaa0b, 0x8e922444, 0x95058000, 0x53963a48, 0x91125416,
    -  0xa9cb1d24, 0x48892a0b, 0x00000000, 0x00000000, 0x5634e2db, 0xb776d5f5,
    -  0xac69c5b7, 0x6eedabea, 0x1b38f8df, 0xb383aa0b, 0x716ddbbb, 0x6afa8000,
    -  0x8ca6d49b, 0x1e7e2a0b, 0xe2dbb776, 0xd5f50000, 0x858293fa, 0x3d892a0b,
    -  0xdbb776d5, 0xf5000000, 0x53c739f0, 0x9f4f5297, 0x22ca6fa5, 0x36ad9c79,
    -  0x6141f319, 0x48892a0b, 0xb776d5f5, 0x00000000, 0x7fc01d24, 0x48892a0b,
    -  0xd5f50000, 0x00000000, 0x091b1d24, 0x48892a0b, 0x5f500000, 0x00000000,
    -  0x80000000, 0x00000000, 0xc8892a0a, 0xa9cb1d25, 0x80100000, 0x00000001,
    -  0x00100000, 0x00000000, 0x80010000, 0x00000001, 0x00010000, 0x00000000,
    -  0x80000001, 0x00000001, 0x00000001, 0x00000000, 0x80000000, 0x01000001,
    -  0x00000000, 0x01000000, 0x80000000, 0x00010001, 0x00000000, 0x00010000,
    -  0x80000000, 0x00008001, 0x00000000, 0x00008000, 0x00000000, 0x00000002,
    -  0x80000000, 0x00000001, 0x00000000, 0x00000000, 0x7fffffff, 0xffffffff,
    -  0xffffffff, 0xfffffffe, 0x7fffffff, 0xffff8001, 0xffffffff, 0xffff8000,
    -  0x7fffffff, 0xffff0001, 0xffffffff, 0xffff0000, 0x7fffffff, 0xff000001,
    -  0xffffffff, 0xff000000, 0x7fffffff, 0xa9cb1d25, 0x7fffffff, 0x48892a0b,
    -  0x7fffffff, 0x00000001, 0xffffffff, 0x00000000, 0x7fff0000, 0x00000001,
    -  0xffff0000, 0x00000000, 0x7ff00000, 0x00000001, 0xfff00000, 0x00000000,
    -  0x29cb1d24, 0x48892a0b
    -];
    -toInt32s(TEST_MUL_BITS);
    -
    -var TEST_DIV_BITS = [
    -  0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x000007ff,
    -  0x00000000, 0x00000800, 0x00000000, 0x00007fff, 0x00000000, 0x00008000,
    -  0x00000000, 0x7fffffff, 0x00000000, 0x80000000, 0x0000007f, 0xffff8000,
    -  0x00000080, 0x00000000, 0x00007fff, 0x80007fff, 0x00008000, 0x00000000,
    -  0x0000fffe, 0x0003fff8, 0x00010000, 0x00000000, 0x40000000, 0x00000000,
    -  0x80000000, 0x00000000, 0x80000000, 0x00000000, 0xc0000000, 0x00000000,
    -  0xfffefffd, 0xfffbfff8, 0xffff0000, 0x00000000, 0xffff7fff, 0x7fff8000,
    -  0xffff8000, 0x00000000, 0xffffff7f, 0xffff8000, 0xffffff80, 0x00000000,
    -  0xfffffffe, 0x83e3cc1a, 0xffffffff, 0x4d64985a, 0xffffffff, 0x80000000,
    -  0xffffffff, 0x80000000, 0xffffffff, 0xffff8000, 0xffffffff, 0xffff8000,
    -  0xffffffff, 0xfffff800, 0xffffffff, 0xfffff800, 0xffffffff, 0xffffffff,
    -  0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000488, 0x00000000, 0x00000488, 0x00000000, 0x00004889,
    -  0x00000000, 0x00004889, 0x00000000, 0x48892a0a, 0x00000000, 0x48892a0a,
    -  0x00000048, 0x8929c220, 0x00000048, 0x892a0aa9, 0x00004888, 0xe181c849,
    -  0x00004889, 0x2a0aa9cb, 0x00009111, 0x31f2efb0, 0x00009112, 0x54155396,
    -  0x24449505, 0x54e58e92, 0x48892a0a, 0xa9cb1d25, 0xb776d5f5, 0x5634e2db,
    -  0xdbbb6afa, 0xab1a716e, 0xffff6eec, 0x89c3bff2, 0xffff6eed, 0xabeaac6a,
    -  0xffffb776, 0x8d6be3a1, 0xffffb776, 0xd5f55635, 0xffffffb7, 0x76d5acce,
    -  0xffffffb7, 0x76d5f557, 0xffffffff, 0x2898cfc6, 0xffffffff, 0x9ac930b4,
    -  0xffffffff, 0xb776d5f6, 0xffffffff, 0xb776d5f6, 0xffffffff, 0xffffb777,
    -  0xffffffff, 0xffffb777, 0xffffffff, 0xfffffb78, 0xffffffff, 0xfffffb78,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000001,
    -  0x00000000, 0x0000000f, 0x00000000, 0x00000010, 0x00000000, 0x000fffff,
    -  0x00000000, 0x00100000, 0x00000000, 0x0ffffff0, 0x00000000, 0x10000000,
    -  0x0000000f, 0xfff0000f, 0x00000010, 0x00000000, 0x0000001f, 0xffc0007f,
    -  0x00000020, 0x00000000, 0x00080000, 0x00000000, 0x00100000, 0x00000001,
    -  0xffefffff, 0xffffffff, 0xfff80000, 0x00000000, 0xffffffdf, 0xffbfff80,
    -  0xffffffe0, 0x00000000, 0xffffffef, 0xffeffff0, 0xfffffff0, 0x00000000,
    -  0xffffffff, 0xeffffff0, 0xffffffff, 0xf0000000, 0xffffffff, 0xffd07c7a,
    -  0xffffffff, 0xffe9ac94, 0xffffffff, 0xfff00000, 0xffffffff, 0xfff00000,
    -  0xffffffff, 0xfffffff0, 0xffffffff, 0xfffffff0, 0xffffffff, 0xffffffff,
    -  0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000001, 0x00000000, 0x0000000f, 0x00000000, 0x00000010,
    -  0x00000000, 0x000fffff, 0x00000000, 0x00100000, 0x00000000, 0x0ffffff0,
    -  0x00000000, 0x10000000, 0x0000000f, 0xfff0000f, 0x00000010, 0x00000000,
    -  0x0000001f, 0xffc0007f, 0x00000020, 0x00000000, 0x00080000, 0x00000000,
    -  0x00100000, 0x00000000, 0xfff00000, 0x00000000, 0xfff80000, 0x00000000,
    -  0xffffffdf, 0xffbfff80, 0xffffffe0, 0x00000000, 0xffffffef, 0xffeffff0,
    -  0xfffffff0, 0x00000000, 0xffffffff, 0xeffffff0, 0xffffffff, 0xf0000000,
    -  0xffffffff, 0xffd07c7a, 0xffffffff, 0xffe9ac94, 0xffffffff, 0xfff00000,
    -  0xffffffff, 0xfff00000, 0xffffffff, 0xfffffff0, 0xffffffff, 0xfffffff0,
    -  0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000001, 0x00000000, 0x0000ffff, 0x00000000, 0x00010000,
    -  0x00000000, 0x00ffffff, 0x00000000, 0x01000000, 0x00000000, 0xffff0001,
    -  0x00000001, 0x00000000, 0x00000001, 0xfffc0007, 0x00000002, 0x00000000,
    -  0x00008000, 0x00000000, 0x00010000, 0x00000001, 0xfffeffff, 0xffffffff,
    -  0xffff8000, 0x00000000, 0xfffffffd, 0xfffbfff8, 0xfffffffe, 0x00000000,
    -  0xfffffffe, 0xfffeffff, 0xffffffff, 0x00000000, 0xffffffff, 0xfeffffff,
    -  0xffffffff, 0xff000000, 0xffffffff, 0xfffd07c8, 0xffffffff, 0xfffe9aca,
    -  0xffffffff, 0xffff0000, 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
    -  0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x0000ffff,
    -  0x00000000, 0x00010000, 0x00000000, 0x00ffffff, 0x00000000, 0x01000000,
    -  0x00000000, 0xffff0000, 0x00000001, 0x00000000, 0x00000001, 0xfffc0007,
    -  0x00000002, 0x00000000, 0x00008000, 0x00000000, 0x00010000, 0x00000000,
    -  0xffff0000, 0x00000000, 0xffff8000, 0x00000000, 0xfffffffd, 0xfffbfff8,
    -  0xfffffffe, 0x00000000, 0xfffffffe, 0xfffeffff, 0xffffffff, 0x00000000,
    -  0xffffffff, 0xfeffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xfffd07c8,
    -  0xffffffff, 0xfffe9aca, 0xffffffff, 0xffff0000, 0xffffffff, 0xffff0000,
    -  0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x000000ff,
    -  0x00000000, 0x00000100, 0x00000000, 0x0000ffff, 0x00000000, 0x00010000,
    -  0x00000000, 0x0001fffc, 0x00000000, 0x00020000, 0x00000000, 0x80000000,
    -  0x00000001, 0x00000001, 0xfffffffe, 0xffffffff, 0xffffffff, 0x80000000,
    -  0xffffffff, 0xfffdfffc, 0xffffffff, 0xfffe0000, 0xffffffff, 0xfffeffff,
    -  0xffffffff, 0xffff0000, 0xffffffff, 0xffffff00, 0xffffffff, 0xffffff00,
    -  0xffffffff, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
    -  0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
    -  0x00000000, 0x000000ff, 0x00000000, 0x00000100, 0x00000000, 0x0000ffff,
    -  0x00000000, 0x00010000, 0x00000000, 0x0001fffc, 0x00000000, 0x00020000,
    -  0x00000000, 0x80000000, 0x00000001, 0x00000000, 0xffffffff, 0x00000000,
    -  0xffffffff, 0x80000000, 0xffffffff, 0xfffdfffc, 0xffffffff, 0xfffe0000,
    -  0xffffffff, 0xfffeffff, 0xffffffff, 0xffff0000, 0xffffffff, 0xffffff00,
    -  0xffffffff, 0xffffff00, 0xffffffff, 0xfffffffe, 0xffffffff, 0xffffffff,
    -  0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000001,
    -  0x00000000, 0x000000ff, 0x00000000, 0x00000100, 0x00000000, 0x000001ff,
    -  0x00000000, 0x00000200, 0x00000000, 0x00800000, 0x00000000, 0x01000001,
    -  0xffffffff, 0xfeffffff, 0xffffffff, 0xff800000, 0xffffffff, 0xfffffe00,
    -  0xffffffff, 0xfffffe00, 0xffffffff, 0xffffff00, 0xffffffff, 0xffffff00,
    -  0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000001, 0x00000000, 0x000000ff, 0x00000000, 0x00000100,
    -  0x00000000, 0x000001ff, 0x00000000, 0x00000200, 0x00000000, 0x00800000,
    -  0x00000000, 0x01000000, 0xffffffff, 0xff000000, 0xffffffff, 0xff800000,
    -  0xffffffff, 0xfffffe00, 0xffffffff, 0xfffffe00, 0xffffffff, 0xffffff00,
    -  0xffffffff, 0xffffff00, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x00000002,
    -  0x00000000, 0x00008000, 0x00000000, 0x00010001, 0xffffffff, 0xfffeffff,
    -  0xffffffff, 0xffff8000, 0xffffffff, 0xfffffffe, 0xffffffff, 0xfffffffe,
    -  0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000002, 0x00000000, 0x00008000, 0x00000000, 0x00010000,
    -  0xffffffff, 0xffff0000, 0xffffffff, 0xffff8000, 0xffffffff, 0xfffffffe,
    -  0xffffffff, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x00004000,
    -  0x00000000, 0x00008001, 0xffffffff, 0xffff7fff, 0xffffffff, 0xffffc000,
    -  0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
    -  0x00000000, 0x00004000, 0x00000000, 0x00008000, 0xffffffff, 0xffff8000,
    -  0xffffffff, 0xffffc000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000002,
    -  0xffffffff, 0xfffffffe, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000001, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
    -  0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
    -  0xffffffff, 0xfffffffe, 0x00000000, 0x00000002, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0xffffffff, 0xffffc001, 0xffffffff, 0xffff8001, 0x00000000, 0x00007fff,
    -  0x00000000, 0x00003fff, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0xffffffff, 0xffffffff, 0xffffffff, 0xffffc000, 0xffffffff, 0xffff8000,
    -  0x00000000, 0x00008000, 0x00000000, 0x00004000, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff8001,
    -  0xffffffff, 0xffff0001, 0x00000000, 0x0000ffff, 0x00000000, 0x00007fff,
    -  0x00000000, 0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffffe,
    -  0xffffffff, 0xffff8000, 0xffffffff, 0xffff0000, 0x00000000, 0x00010000,
    -  0x00000000, 0x00008000, 0x00000000, 0x00000002, 0x00000000, 0x00000002,
    -  0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0xffffffff, 0xffffff01, 0xffffffff, 0xffffff01, 0xffffffff, 0xfffffe01,
    -  0xffffffff, 0xfffffe01, 0xffffffff, 0xff800001, 0xffffffff, 0xff000001,
    -  0x00000000, 0x00ffffff, 0x00000000, 0x007fffff, 0x00000000, 0x00000200,
    -  0x00000000, 0x000001ff, 0x00000000, 0x00000100, 0x00000000, 0x000000ff,
    -  0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0xffffffff, 0xffffffff, 0xffffffff, 0xffffff01, 0xffffffff, 0xffffff00,
    -  0xffffffff, 0xfffffe01, 0xffffffff, 0xfffffe00, 0xffffffff, 0xff800000,
    -  0xffffffff, 0xff000000, 0x00000000, 0x01000000, 0x00000000, 0x00800000,
    -  0x00000000, 0x00000200, 0x00000000, 0x00000200, 0x00000000, 0x00000100,
    -  0x00000000, 0x00000100, 0x00000000, 0x00000001, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0xffffffff, 0xffffffaa, 0xffffffff, 0xffffffaa, 0xffffffff, 0xffffa9cc,
    -  0xffffffff, 0xffffa9cc, 0xffffffff, 0xffff5398, 0xffffffff, 0xffff5397,
    -  0xffffffff, 0xd4e58e93, 0xffffffff, 0xa9cb1d25, 0x00000000, 0x5634e2db,
    -  0x00000000, 0x2b1a716d, 0x00000000, 0x0000ac6b, 0x00000000, 0x0000ac69,
    -  0x00000000, 0x00005635, 0x00000000, 0x00005634, 0x00000000, 0x00000056,
    -  0x00000000, 0x00000056, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffff49, 0xffffffff, 0xffffff49,
    -  0xffffffff, 0xffff488a, 0xffffffff, 0xffff488a, 0xffffffff, 0xfffe9116,
    -  0xffffffff, 0xfffe9113, 0xffffffff, 0xa4449506, 0xffffffff, 0x48892a0b,
    -  0x00000000, 0xb776d5f5, 0x00000000, 0x5bbb6afa, 0x00000000, 0x00016ef0,
    -  0x00000000, 0x00016eed, 0x00000000, 0x0000b777, 0x00000000, 0x0000b776,
    -  0x00000000, 0x000000b7, 0x00000000, 0x000000b7, 0x00000000, 0x00000002,
    -  0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffff01,
    -  0xffffffff, 0xffffff01, 0xffffffff, 0xffff0001, 0xffffffff, 0xffff0001,
    -  0xffffffff, 0xfffe0004, 0xffffffff, 0xfffe0001, 0xffffffff, 0x80000001,
    -  0xffffffff, 0x00000001, 0x00000000, 0xffffffff, 0x00000000, 0x7fffffff,
    -  0x00000000, 0x00020004, 0x00000000, 0x0001ffff, 0x00000000, 0x00010001,
    -  0x00000000, 0x0000ffff, 0x00000000, 0x00000100, 0x00000000, 0x000000ff,
    -  0x00000000, 0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
    -  0xffffffff, 0xffffff01, 0xffffffff, 0xffffff00, 0xffffffff, 0xffff0001,
    -  0xffffffff, 0xffff0000, 0xffffffff, 0xfffe0004, 0xffffffff, 0xfffe0000,
    -  0xffffffff, 0x80000000, 0xffffffff, 0x00000000, 0x00000001, 0x00000000,
    -  0x00000000, 0x80000000, 0x00000000, 0x00020004, 0x00000000, 0x00020000,
    -  0x00000000, 0x00010001, 0x00000000, 0x00010000, 0x00000000, 0x00000100,
    -  0x00000000, 0x00000100, 0x00000000, 0x00000002, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffff0001,
    -  0xffffffff, 0xffff0001, 0xffffffff, 0xff000001, 0xffffffff, 0xff000001,
    -  0xffffffff, 0x00010000, 0xffffffff, 0x00000001, 0xfffffffe, 0x0003fff9,
    -  0xfffffffe, 0x00000001, 0xffff8000, 0x00000001, 0xffff0000, 0x00000001,
    -  0x0000ffff, 0xffffffff, 0x00007fff, 0xffffffff, 0x00000002, 0x00040008,
    -  0x00000001, 0xffffffff, 0x00000001, 0x00010001, 0x00000000, 0xffffffff,
    -  0x00000000, 0x01000001, 0x00000000, 0x00ffffff, 0x00000000, 0x0002f838,
    -  0x00000000, 0x00016536, 0x00000000, 0x00010000, 0x00000000, 0x0000ffff,
    -  0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
    -  0xffffffff, 0xffff0001, 0xffffffff, 0xffff0000, 0xffffffff, 0xff000001,
    -  0xffffffff, 0xff000000, 0xffffffff, 0x00010000, 0xffffffff, 0x00000000,
    -  0xfffffffe, 0x0003fff9, 0xfffffffe, 0x00000000, 0xffff8000, 0x00000000,
    -  0xffff0000, 0x00000000, 0x00010000, 0x00000000, 0x00008000, 0x00000000,
    -  0x00000002, 0x00040008, 0x00000002, 0x00000000, 0x00000001, 0x00010001,
    -  0x00000001, 0x00000000, 0x00000000, 0x01000001, 0x00000000, 0x01000000,
    -  0x00000000, 0x0002f838, 0x00000000, 0x00016536, 0x00000000, 0x00010000,
    -  0x00000000, 0x00010000, 0x00000000, 0x00000001, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xfffffff1,
    -  0xffffffff, 0xfffffff1, 0xffffffff, 0xfff00001, 0xffffffff, 0xfff00001,
    -  0xffffffff, 0xf0000010, 0xffffffff, 0xf0000001, 0xfffffff0, 0x000ffff1,
    -  0xfffffff0, 0x00000001, 0xffffffe0, 0x003fff81, 0xffffffe0, 0x00000001,
    -  0xfff80000, 0x00000001, 0xfff00000, 0x00000001, 0x000fffff, 0xffffffff,
    -  0x0007ffff, 0xffffffff, 0x00000020, 0x00400080, 0x0000001f, 0xffffffff,
    -  0x00000010, 0x00100010, 0x0000000f, 0xffffffff, 0x00000000, 0x10000010,
    -  0x00000000, 0x0fffffff, 0x00000000, 0x002f8386, 0x00000000, 0x0016536c,
    -  0x00000000, 0x00100000, 0x00000000, 0x000fffff, 0x00000000, 0x00000010,
    -  0x00000000, 0x0000000f, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
    -  0xffffffff, 0xfffffff1, 0xffffffff, 0xfffffff0, 0xffffffff, 0xfff00001,
    -  0xffffffff, 0xfff00000, 0xffffffff, 0xf0000010, 0xffffffff, 0xf0000000,
    -  0xfffffff0, 0x000ffff1, 0xfffffff0, 0x00000000, 0xffffffe0, 0x003fff81,
    -  0xffffffe0, 0x00000000, 0xfff80000, 0x00000000, 0xfff00000, 0x00000000,
    -  0x00100000, 0x00000000, 0x00080000, 0x00000000, 0x00000020, 0x00400080,
    -  0x00000020, 0x00000000, 0x00000010, 0x00100010, 0x00000010, 0x00000000,
    -  0x00000000, 0x10000010, 0x00000000, 0x10000000, 0x00000000, 0x002f8386,
    -  0x00000000, 0x0016536c, 0x00000000, 0x00100000, 0x00000000, 0x00100000,
    -  0x00000000, 0x00000010, 0x00000000, 0x00000010, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    -  0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffa9d,
    -  0xffffffff, 0xfffffa9d, 0xffffffff, 0xffffa9cc, 0xffffffff, 0xffffa9cc,
    -  0xffffffff, 0xa9cb1d25, 0xffffffff, 0xa9cb1d25, 0xffffffa9, 0xcb1d7a7e,
    -  0xffffffa9, 0xcb1d2449, 0xffffa9cb, 0x7358d531, 0xffffa9cb, 0x1d24488a,
    -  0xffff5397, 0x93196ae0, 0xffff5396, 0x3a489113, 0xd4e58e92, 0x24449506,
    -  0xa9cb1d24, 0x48892a0b, 0x5634e2db, 0xb776d5f5, 0x2b1a716d, 0xdbbb6afa,
    -  0x0000ac6b, 0x1e8dac09, 0x0000ac69, 0xc5b76eed, 0x00005635, 0x3910f087,
    -  0x00005634, 0xe2dbb776, 0x00000056, 0x34e331ec, 0x00000056, 0x34e2dbb7,
    -  0x00000001, 0x00000002, 0x00000000, 0x784a3552, 0x00000000, 0x5634e2dc,
    -  0x00000000, 0x5634e2db, 0x00000000, 0x00005634, 0x00000000, 0x00005634,
    -  0x00000000, 0x00000563, 0x00000000, 0x00000563, 0x00000000, 0x00000001,
    -  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
    -  0xffffffff, 0xfffff801, 0xffffffff, 0xfffff801, 0xffffffff, 0xffff8001,
    -  0xffffffff, 0xffff8001, 0xffffffff, 0x80000001, 0xffffffff, 0x80000001,
    -  0xffffff80, 0x00008000, 0xffffff80, 0x00000001, 0xffff8000, 0x7fff8001,
    -  0xffff8000, 0x00000001, 0xffff0001, 0xfffc0008, 0xffff0000, 0x00000001,
    -  0xc0000000, 0x00000001, 0x80000000, 0x00000001, 0x7fffffff, 0xffffffff,
    -  0x3fffffff, 0xffffffff, 0x00010002, 0x00040008, 0x0000ffff, 0xffffffff,
    -  0x00008000, 0x80008000, 0x00007fff, 0xffffffff, 0x00000080, 0x00008000,
    -  0x0000007f, 0xffffffff, 0x00000001, 0x7c1c33e6, 0x00000000, 0xb29b67a6,
    -  0x00000000, 0x80000000, 0x00000000, 0x7fffffff, 0x00000000, 0x00008000,
    -  0x00000000, 0x00007fff, 0x00000000, 0x00000800, 0x00000000, 0x000007ff,
    -  0x00000000, 0x00000001, 0x00000000, 0x00000001
    -];
    -toInt32s(TEST_DIV_BITS);
    -
    -var TEST_STRINGS = [
    -  '-9223372036854775808',
    -  '-5226755067826871589',
    -  '-4503599627370497',
    -  '-4503599627370496',
    -  '-281474976710657',
    -  '-281474976710656',
    -  '-4294967297',
    -  '-4294967296',
    -  '-16777217',
    -  '-16777216',
    -  '-65537',
    -  '-65536',
    -  '-32769',
    -  '-32768',
    -  '-2',
    -  '-1',
    -  '0',
    -  '1',
    -  '2',
    -  '32767',
    -  '32768',
    -  '65535',
    -  '65536',
    -  '16777215',
    -  '16777216',
    -  '1446306523',
    -  '3078018549',
    -  '4294967295',
    -  '4294967296',
    -  '281474976710655',
    -  '281474976710656',
    -  '4503599627370495',
    -  '4503599627370496',
    -  '6211839219354490357',
    -  '9223372036854775807'
    -];
    -
    -function testToFromBits() {
    -  for (var i = 0; i < TEST_BITS.length; i += 2) {
    -    var val = goog.math.Long.fromBits(TEST_BITS[i + 1], TEST_BITS[i]);
    -    assertEquals(TEST_BITS[i], val.getHighBits());
    -    assertEquals(TEST_BITS[i + 1], val.getLowBits());
    -  }
    -}
    -
    -function testToFromInt() {
    -  for (var i = 0; i < TEST_BITS.length; i += 1) {
    -    var val = goog.math.Long.fromInt(TEST_BITS[i]);
    -    assertEquals(TEST_BITS[i], val.toInt());
    -  }
    -}
    -
    -function testToFromNumber() {
    -  for (var i = 0; i < TEST_BITS.length; i += 2) {
    -    var num = TEST_BITS[i] * Math.pow(2, 32) + TEST_BITS[i + 1] >= 0 ?
    -        TEST_BITS[i + 1] : Math.pow(2, 32) + TEST_BITS[i + 1];
    -    var val = goog.math.Long.fromNumber(num);
    -    assertEquals(num, val.toNumber());
    -  }
    -}
    -
    -function testIsZero() {
    -  for (var i = 0; i < TEST_BITS.length; i += 2) {
    -    var val = goog.math.Long.fromBits(TEST_BITS[i + 1], TEST_BITS[i]);
    -    assertEquals(TEST_BITS[i] == 0 && TEST_BITS[i + 1] == 0, val.isZero());
    -  }
    -}
    -
    -function testIsNegative() {
    -  for (var i = 0; i < TEST_BITS.length; i += 2) {
    -    var val = goog.math.Long.fromBits(TEST_BITS[i + 1], TEST_BITS[i]);
    -    assertEquals((TEST_BITS[i] >> 31) != 0, val.isNegative());
    -  }
    -}
    -
    -function testIsOdd() {
    -  for (var i = 0; i < TEST_BITS.length; i += 2) {
    -    var val = goog.math.Long.fromBits(TEST_BITS[i + 1], TEST_BITS[i]);
    -    assertEquals((TEST_BITS[i + 1] & 1) != 0, val.isOdd());
    -  }
    -}
    -
    -function createTestComparisons(i) {
    -  return function() {
    -    var vi = goog.math.Long.fromBits(TEST_BITS[i + 1], TEST_BITS[i]);
    -    for (var j = 0; j < TEST_BITS.length; j += 2) {
    -      var vj = goog.math.Long.fromBits(TEST_BITS[j + 1], TEST_BITS[j]);
    -      assertEquals(i == j, vi.equals(vj));
    -      assertEquals(i != j, vi.notEquals(vj));
    -      assertEquals(i < j, vi.lessThan(vj));
    -      assertEquals(i <= j, vi.lessThanOrEqual(vj));
    -      assertEquals(i > j, vi.greaterThan(vj));
    -      assertEquals(i >= j, vi.greaterThanOrEqual(vj));
    -    }
    -  };
    -}
    -
    -// Here and below, we translate one conceptual test (e.g., "testComparisons")
    -// into a number of test functions that will be run separately by jsunit. This
    -// is necessary because, in some testing configurations, the full combined test
    -// can take so long that it times out. These smaller tests run much faster.
    -for (var i = 0; i < TEST_BITS.length; i += 2) {
    -  goog.global['testComparisons' + i] = createTestComparisons(i);
    -}
    -
    -function createTestBitOperations(i) {
    -  return function() {
    -    var vi = goog.math.Long.fromBits(TEST_BITS[i + 1], TEST_BITS[i]);
    -    assertEquals(~TEST_BITS[i], vi.not().getHighBits());
    -    assertEquals(~TEST_BITS[i + 1], vi.not().getLowBits());
    -
    -    for (var j = 0; j < TEST_BITS.length; j += 2) {
    -      var vj = goog.math.Long.fromBits(TEST_BITS[j + 1], TEST_BITS[j]);
    -      assertEquals(TEST_BITS[i] & TEST_BITS[j], vi.and(vj).getHighBits());
    -      assertEquals(
    -          TEST_BITS[i + 1] & TEST_BITS[j + 1], vi.and(vj).getLowBits());
    -      assertEquals(TEST_BITS[i] | TEST_BITS[j], vi.or(vj).getHighBits());
    -      assertEquals(TEST_BITS[i + 1] | TEST_BITS[j + 1], vi.or(vj).getLowBits());
    -      assertEquals(TEST_BITS[i] ^ TEST_BITS[j], vi.xor(vj).getHighBits());
    -      assertEquals(
    -          TEST_BITS[i + 1] ^ TEST_BITS[j + 1], vi.xor(vj).getLowBits());
    -    }
    -
    -    assertEquals(TEST_BITS[i], vi.shiftLeft(0).getHighBits());
    -    assertEquals(TEST_BITS[i + 1], vi.shiftLeft(0).getLowBits());
    -    assertEquals(TEST_BITS[i], vi.shiftRight(0).getHighBits());
    -    assertEquals(TEST_BITS[i + 1], vi.shiftRight(0).getLowBits());
    -    assertEquals(TEST_BITS[i], vi.shiftRightUnsigned(0).getHighBits());
    -    assertEquals(TEST_BITS[i + 1], vi.shiftRightUnsigned(0).getLowBits());
    -
    -    for (var len = 1; len < 64; ++len) {
    -      if (len < 32) {
    -        assertEquals((TEST_BITS[i] << len) | (TEST_BITS[i + 1] >>> (32 - len)),
    -                     vi.shiftLeft(len).getHighBits());
    -        assertEquals(TEST_BITS[i + 1] << len, vi.shiftLeft(len).getLowBits());
    -
    -        assertEquals(TEST_BITS[i] >> len, vi.shiftRight(len).getHighBits());
    -        assertEquals((TEST_BITS[i + 1] >>> len) | (TEST_BITS[i] << (32 - len)),
    -                     vi.shiftRight(len).getLowBits());
    -
    -        assertEquals(TEST_BITS[i] >>> len,
    -                     vi.shiftRightUnsigned(len).getHighBits());
    -        assertEquals((TEST_BITS[i + 1] >>> len) | (TEST_BITS[i] << (32 - len)),
    -                     vi.shiftRightUnsigned(len).getLowBits());
    -      } else {
    -        assertEquals(TEST_BITS[i + 1] << (len - 32),
    -                     vi.shiftLeft(len).getHighBits());
    -        assertEquals(0, vi.shiftLeft(len).getLowBits());
    -
    -        assertEquals(TEST_BITS[i] >= 0 ? 0 : -1,
    -                     vi.shiftRight(len).getHighBits());
    -        assertEquals(TEST_BITS[i] >> (len - 32),
    -                     vi.shiftRight(len).getLowBits());
    -
    -        assertEquals(0, vi.shiftRightUnsigned(len).getHighBits());
    -        if (len == 32) {
    -          assertEquals(TEST_BITS[i], vi.shiftRightUnsigned(len).getLowBits());
    -        } else {
    -          assertEquals(TEST_BITS[i] >>> (len - 32),
    -                       vi.shiftRightUnsigned(len).getLowBits());
    -        }
    -      }
    -    }
    -
    -    assertEquals(TEST_BITS[i], vi.shiftLeft(64).getHighBits());
    -    assertEquals(TEST_BITS[i + 1], vi.shiftLeft(64).getLowBits());
    -    assertEquals(TEST_BITS[i], vi.shiftRight(64).getHighBits());
    -    assertEquals(TEST_BITS[i + 1], vi.shiftRight(64).getLowBits());
    -    assertEquals(TEST_BITS[i], vi.shiftRightUnsigned(64).getHighBits());
    -    assertEquals(TEST_BITS[i + 1], vi.shiftRightUnsigned(64).getLowBits());
    -  };
    -}
    -
    -for (var i = 0; i < TEST_BITS.length; i += 2) {
    -  goog.global['testBitOperations' + i] = createTestBitOperations(i);
    -}
    -
    -function testNegation() {
    -  for (var i = 0; i < TEST_BITS.length; i += 2) {
    -    var vi = goog.math.Long.fromBits(TEST_BITS[i + 1], TEST_BITS[i]);
    -    if (TEST_BITS[i + 1] == 0) {
    -      assertEquals((~TEST_BITS[i] + 1) | 0, vi.negate().getHighBits());
    -      assertEquals(0, vi.negate().getLowBits());
    -    } else {
    -      assertEquals(~TEST_BITS[i], vi.negate().getHighBits());
    -      assertEquals((~TEST_BITS[i + 1] + 1) | 0, vi.negate().getLowBits());
    -    }
    -  }
    -}
    -
    -function testAdd() {
    -  var count = 0;
    -  for (var i = 0; i < TEST_BITS.length; i += 2) {
    -    var vi = goog.math.Long.fromBits(TEST_BITS[i + 1], TEST_BITS[i]);
    -    for (var j = 0; j < i; j += 2) {
    -      var vj = goog.math.Long.fromBits(TEST_BITS[j + 1], TEST_BITS[j]);
    -      var result = vi.add(vj);
    -      assertEquals(TEST_ADD_BITS[count++], result.getHighBits());
    -      assertEquals(TEST_ADD_BITS[count++], result.getLowBits());
    -    }
    -  }
    -}
    -
    -function testSubtract() {
    -  var count = 0;
    -  for (var i = 0; i < TEST_BITS.length; i += 2) {
    -    var vi = goog.math.Long.fromBits(TEST_BITS[i + 1], TEST_BITS[i]);
    -    for (var j = 0; j < TEST_BITS.length; j += 2) {
    -      var vj = goog.math.Long.fromBits(TEST_BITS[j + 1], TEST_BITS[j]);
    -      var result = vi.subtract(vj);
    -      assertEquals(TEST_SUB_BITS[count++], result.getHighBits());
    -      assertEquals(TEST_SUB_BITS[count++], result.getLowBits());
    -    }
    -  }
    -}
    -
    -function testMultiply() {
    -  var count = 0;
    -  for (var i = 0; i < TEST_BITS.length; i += 2) {
    -    var vi = goog.math.Long.fromBits(TEST_BITS[i + 1], TEST_BITS[i]);
    -    for (var j = 0; j < i; j += 2) {
    -      var vj = goog.math.Long.fromBits(TEST_BITS[j + 1], TEST_BITS[j]);
    -      var result = vi.multiply(vj);
    -      assertEquals(TEST_MUL_BITS[count++], result.getHighBits());
    -      assertEquals(TEST_MUL_BITS[count++], result.getLowBits());
    -    }
    -  }
    -}
    -
    -function createTestDivMod(i, count) {
    -  return function() {
    -    var vi = goog.math.Long.fromBits(TEST_BITS[i + 1], TEST_BITS[i]);
    -    for (var j = 0; j < TEST_BITS.length; j += 2) {
    -      var vj = goog.math.Long.fromBits(TEST_BITS[j + 1], TEST_BITS[j]);
    -      if (!vj.isZero()) {
    -        var divResult = vi.div(vj);
    -        assertEquals(TEST_DIV_BITS[count++], divResult.getHighBits());
    -        assertEquals(TEST_DIV_BITS[count++], divResult.getLowBits());
    -
    -        var modResult = vi.modulo(vj);
    -        var combinedResult = divResult.multiply(vj).add(modResult);
    -        assertTrue(vi.equals(combinedResult));
    -      }
    -    }
    -  }
    -}
    -
    -var countPerDivModCall = 0;
    -for (var j = 0; j < TEST_BITS.length; j += 2) {
    -  var vj = goog.math.Long.fromBits(TEST_BITS[j + 1], TEST_BITS[j]);
    -  if (!vj.isZero()) {
    -    countPerDivModCall += 2;
    -  }
    -}
    -
    -var countDivMod = 0;
    -for (var i = 0; i < TEST_BITS.length; i += 2) {
    -  goog.global['testDivMod' + i] = createTestDivMod(i, countDivMod);
    -  countDivMod += countPerDivModCall;
    -}
    -
    -function createTestToFromString(i) {
    -  return function() {
    -    var vi = goog.math.Long.fromBits(TEST_BITS[i + 1], TEST_BITS[i]);
    -    var str = vi.toString(10);
    -    assertEquals(TEST_STRINGS[i / 2], str);
    -    assertEquals(TEST_BITS[i],
    -                 goog.math.Long.fromString(str, 10).getHighBits());
    -    assertEquals(TEST_BITS[i + 1],
    -                 goog.math.Long.fromString(str, 10).getLowBits());
    -
    -    for (var radix = 2; radix <= 36; ++radix) {
    -      var result = vi.toString(radix);
    -      assertEquals(TEST_BITS[i],
    -                   goog.math.Long.fromString(result, radix).getHighBits());
    -      assertEquals(TEST_BITS[i + 1],
    -                   goog.math.Long.fromString(result, radix).getLowBits());
    -    }
    -  }
    -}
    -
    -for (var i = 0; i < TEST_BITS.length; i += 2) {
    -  goog.global['testToFromString' + i] = createTestToFromString(i);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/math/math.js b/src/database/third_party/closure-library/closure/goog/math/math.js
    deleted file mode 100644
    index 2947cf8f71c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/math.js
    +++ /dev/null
    @@ -1,435 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Additional mathematical functions.
    - */
    -
    -goog.provide('goog.math');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -
    -
    -/**
    - * Returns a random integer greater than or equal to 0 and less than {@code a}.
    - * @param {number} a  The upper bound for the random integer (exclusive).
    - * @return {number} A random integer N such that 0 <= N < a.
    - */
    -goog.math.randomInt = function(a) {
    -  return Math.floor(Math.random() * a);
    -};
    -
    -
    -/**
    - * Returns a random number greater than or equal to {@code a} and less than
    - * {@code b}.
    - * @param {number} a  The lower bound for the random number (inclusive).
    - * @param {number} b  The upper bound for the random number (exclusive).
    - * @return {number} A random number N such that a <= N < b.
    - */
    -goog.math.uniformRandom = function(a, b) {
    -  return a + Math.random() * (b - a);
    -};
    -
    -
    -/**
    - * Takes a number and clamps it to within the provided bounds.
    - * @param {number} value The input number.
    - * @param {number} min The minimum value to return.
    - * @param {number} max The maximum value to return.
    - * @return {number} The input number if it is within bounds, or the nearest
    - *     number within the bounds.
    - */
    -goog.math.clamp = function(value, min, max) {
    -  return Math.min(Math.max(value, min), max);
    -};
    -
    -
    -/**
    - * The % operator in JavaScript returns the remainder of a / b, but differs from
    - * some other languages in that the result will have the same sign as the
    - * dividend. For example, -1 % 8 == -1, whereas in some other languages
    - * (such as Python) the result would be 7. This function emulates the more
    - * correct modulo behavior, which is useful for certain applications such as
    - * calculating an offset index in a circular list.
    - *
    - * @param {number} a The dividend.
    - * @param {number} b The divisor.
    - * @return {number} a % b where the result is between 0 and b (either 0 <= x < b
    - *     or b < x <= 0, depending on the sign of b).
    - */
    -goog.math.modulo = function(a, b) {
    -  var r = a % b;
    -  // If r and b differ in sign, add b to wrap the result to the correct sign.
    -  return (r * b < 0) ? r + b : r;
    -};
    -
    -
    -/**
    - * Performs linear interpolation between values a and b. Returns the value
    - * between a and b proportional to x (when x is between 0 and 1. When x is
    - * outside this range, the return value is a linear extrapolation).
    - * @param {number} a A number.
    - * @param {number} b A number.
    - * @param {number} x The proportion between a and b.
    - * @return {number} The interpolated value between a and b.
    - */
    -goog.math.lerp = function(a, b, x) {
    -  return a + x * (b - a);
    -};
    -
    -
    -/**
    - * Tests whether the two values are equal to each other, within a certain
    - * tolerance to adjust for floating point errors.
    - * @param {number} a A number.
    - * @param {number} b A number.
    - * @param {number=} opt_tolerance Optional tolerance range. Defaults
    - *     to 0.000001. If specified, should be greater than 0.
    - * @return {boolean} Whether {@code a} and {@code b} are nearly equal.
    - */
    -goog.math.nearlyEquals = function(a, b, opt_tolerance) {
    -  return Math.abs(a - b) <= (opt_tolerance || 0.000001);
    -};
    -
    -
    -// TODO(user): Rename to normalizeAngle, retaining old name as deprecated
    -// alias.
    -/**
    - * Normalizes an angle to be in range [0-360). Angles outside this range will
    - * be normalized to be the equivalent angle with that range.
    - * @param {number} angle Angle in degrees.
    - * @return {number} Standardized angle.
    - */
    -goog.math.standardAngle = function(angle) {
    -  return goog.math.modulo(angle, 360);
    -};
    -
    -
    -/**
    - * Normalizes an angle to be in range [0-2*PI). Angles outside this range will
    - * be normalized to be the equivalent angle with that range.
    - * @param {number} angle Angle in radians.
    - * @return {number} Standardized angle.
    - */
    -goog.math.standardAngleInRadians = function(angle) {
    -  return goog.math.modulo(angle, 2 * Math.PI);
    -};
    -
    -
    -/**
    - * Converts degrees to radians.
    - * @param {number} angleDegrees Angle in degrees.
    - * @return {number} Angle in radians.
    - */
    -goog.math.toRadians = function(angleDegrees) {
    -  return angleDegrees * Math.PI / 180;
    -};
    -
    -
    -/**
    - * Converts radians to degrees.
    - * @param {number} angleRadians Angle in radians.
    - * @return {number} Angle in degrees.
    - */
    -goog.math.toDegrees = function(angleRadians) {
    -  return angleRadians * 180 / Math.PI;
    -};
    -
    -
    -/**
    - * For a given angle and radius, finds the X portion of the offset.
    - * @param {number} degrees Angle in degrees (zero points in +X direction).
    - * @param {number} radius Radius.
    - * @return {number} The x-distance for the angle and radius.
    - */
    -goog.math.angleDx = function(degrees, radius) {
    -  return radius * Math.cos(goog.math.toRadians(degrees));
    -};
    -
    -
    -/**
    - * For a given angle and radius, finds the Y portion of the offset.
    - * @param {number} degrees Angle in degrees (zero points in +X direction).
    - * @param {number} radius Radius.
    - * @return {number} The y-distance for the angle and radius.
    - */
    -goog.math.angleDy = function(degrees, radius) {
    -  return radius * Math.sin(goog.math.toRadians(degrees));
    -};
    -
    -
    -/**
    - * Computes the angle between two points (x1,y1) and (x2,y2).
    - * Angle zero points in the +X direction, 90 degrees points in the +Y
    - * direction (down) and from there we grow clockwise towards 360 degrees.
    - * @param {number} x1 x of first point.
    - * @param {number} y1 y of first point.
    - * @param {number} x2 x of second point.
    - * @param {number} y2 y of second point.
    - * @return {number} Standardized angle in degrees of the vector from
    - *     x1,y1 to x2,y2.
    - */
    -goog.math.angle = function(x1, y1, x2, y2) {
    -  return goog.math.standardAngle(goog.math.toDegrees(Math.atan2(y2 - y1,
    -                                                                x2 - x1)));
    -};
    -
    -
    -/**
    - * Computes the difference between startAngle and endAngle (angles in degrees).
    - * @param {number} startAngle  Start angle in degrees.
    - * @param {number} endAngle  End angle in degrees.
    - * @return {number} The number of degrees that when added to
    - *     startAngle will result in endAngle. Positive numbers mean that the
    - *     direction is clockwise. Negative numbers indicate a counter-clockwise
    - *     direction.
    - *     The shortest route (clockwise vs counter-clockwise) between the angles
    - *     is used.
    - *     When the difference is 180 degrees, the function returns 180 (not -180)
    - *     angleDifference(30, 40) is 10, and angleDifference(40, 30) is -10.
    - *     angleDifference(350, 10) is 20, and angleDifference(10, 350) is -20.
    - */
    -goog.math.angleDifference = function(startAngle, endAngle) {
    -  var d = goog.math.standardAngle(endAngle) -
    -          goog.math.standardAngle(startAngle);
    -  if (d > 180) {
    -    d = d - 360;
    -  } else if (d <= -180) {
    -    d = 360 + d;
    -  }
    -  return d;
    -};
    -
    -
    -/**
    - * Returns the sign of a number as per the "sign" or "signum" function.
    - * @param {number} x The number to take the sign of.
    - * @return {number} -1 when negative, 1 when positive, 0 when 0.
    - */
    -goog.math.sign = function(x) {
    -  return x == 0 ? 0 : (x < 0 ? -1 : 1);
    -};
    -
    -
    -/**
    - * JavaScript implementation of Longest Common Subsequence problem.
    - * http://en.wikipedia.org/wiki/Longest_common_subsequence
    - *
    - * Returns the longest possible array that is subarray of both of given arrays.
    - *
    - * @param {Array<Object>} array1 First array of objects.
    - * @param {Array<Object>} array2 Second array of objects.
    - * @param {Function=} opt_compareFn Function that acts as a custom comparator
    - *     for the array ojects. Function should return true if objects are equal,
    - *     otherwise false.
    - * @param {Function=} opt_collectorFn Function used to decide what to return
    - *     as a result subsequence. It accepts 2 arguments: index of common element
    - *     in the first array and index in the second. The default function returns
    - *     element from the first array.
    - * @return {!Array<Object>} A list of objects that are common to both arrays
    - *     such that there is no common subsequence with size greater than the
    - *     length of the list.
    - */
    -goog.math.longestCommonSubsequence = function(
    -    array1, array2, opt_compareFn, opt_collectorFn) {
    -
    -  var compare = opt_compareFn || function(a, b) {
    -    return a == b;
    -  };
    -
    -  var collect = opt_collectorFn || function(i1, i2) {
    -    return array1[i1];
    -  };
    -
    -  var length1 = array1.length;
    -  var length2 = array2.length;
    -
    -  var arr = [];
    -  for (var i = 0; i < length1 + 1; i++) {
    -    arr[i] = [];
    -    arr[i][0] = 0;
    -  }
    -
    -  for (var j = 0; j < length2 + 1; j++) {
    -    arr[0][j] = 0;
    -  }
    -
    -  for (i = 1; i <= length1; i++) {
    -    for (j = 1; j <= length2; j++) {
    -      if (compare(array1[i - 1], array2[j - 1])) {
    -        arr[i][j] = arr[i - 1][j - 1] + 1;
    -      } else {
    -        arr[i][j] = Math.max(arr[i - 1][j], arr[i][j - 1]);
    -      }
    -    }
    -  }
    -
    -  // Backtracking
    -  var result = [];
    -  var i = length1, j = length2;
    -  while (i > 0 && j > 0) {
    -    if (compare(array1[i - 1], array2[j - 1])) {
    -      result.unshift(collect(i - 1, j - 1));
    -      i--;
    -      j--;
    -    } else {
    -      if (arr[i - 1][j] > arr[i][j - 1]) {
    -        i--;
    -      } else {
    -        j--;
    -      }
    -    }
    -  }
    -
    -  return result;
    -};
    -
    -
    -/**
    - * Returns the sum of the arguments.
    - * @param {...number} var_args Numbers to add.
    - * @return {number} The sum of the arguments (0 if no arguments were provided,
    - *     {@code NaN} if any of the arguments is not a valid number).
    - */
    -goog.math.sum = function(var_args) {
    -  return /** @type {number} */ (goog.array.reduce(arguments,
    -      function(sum, value) {
    -        return sum + value;
    -      }, 0));
    -};
    -
    -
    -/**
    - * Returns the arithmetic mean of the arguments.
    - * @param {...number} var_args Numbers to average.
    - * @return {number} The average of the arguments ({@code NaN} if no arguments
    - *     were provided or any of the arguments is not a valid number).
    - */
    -goog.math.average = function(var_args) {
    -  return goog.math.sum.apply(null, arguments) / arguments.length;
    -};
    -
    -
    -/**
    - * Returns the unbiased sample variance of the arguments. For a definition,
    - * see e.g. http://en.wikipedia.org/wiki/Variance
    - * @param {...number} var_args Number samples to analyze.
    - * @return {number} The unbiased sample variance of the arguments (0 if fewer
    - *     than two samples were provided, or {@code NaN} if any of the samples is
    - *     not a valid number).
    - */
    -goog.math.sampleVariance = function(var_args) {
    -  var sampleSize = arguments.length;
    -  if (sampleSize < 2) {
    -    return 0;
    -  }
    -
    -  var mean = goog.math.average.apply(null, arguments);
    -  var variance = goog.math.sum.apply(null, goog.array.map(arguments,
    -      function(val) {
    -        return Math.pow(val - mean, 2);
    -      })) / (sampleSize - 1);
    -
    -  return variance;
    -};
    -
    -
    -/**
    - * Returns the sample standard deviation of the arguments.  For a definition of
    - * sample standard deviation, see e.g.
    - * http://en.wikipedia.org/wiki/Standard_deviation
    - * @param {...number} var_args Number samples to analyze.
    - * @return {number} The sample standard deviation of the arguments (0 if fewer
    - *     than two samples were provided, or {@code NaN} if any of the samples is
    - *     not a valid number).
    - */
    -goog.math.standardDeviation = function(var_args) {
    -  return Math.sqrt(goog.math.sampleVariance.apply(null, arguments));
    -};
    -
    -
    -/**
    - * Returns whether the supplied number represents an integer, i.e. that is has
    - * no fractional component.  No range-checking is performed on the number.
    - * @param {number} num The number to test.
    - * @return {boolean} Whether {@code num} is an integer.
    - */
    -goog.math.isInt = function(num) {
    -  return isFinite(num) && num % 1 == 0;
    -};
    -
    -
    -/**
    - * Returns whether the supplied number is finite and not NaN.
    - * @param {number} num The number to test.
    - * @return {boolean} Whether {@code num} is a finite number.
    - */
    -goog.math.isFiniteNumber = function(num) {
    -  return isFinite(num) && !isNaN(num);
    -};
    -
    -
    -/**
    - * Returns the precise value of floor(log10(num)).
    - * Simpler implementations didn't work because of floating point rounding
    - * errors. For example
    - * <ul>
    - * <li>Math.floor(Math.log(num) / Math.LN10) is off by one for num == 1e+3.
    - * <li>Math.floor(Math.log(num) * Math.LOG10E) is off by one for num == 1e+15.
    - * <li>Math.floor(Math.log10(num)) is off by one for num == 1e+15 - 1.
    - * </ul>
    - * @param {number} num A floating point number.
    - * @return {number} Its logarithm to base 10 rounded down to the nearest
    - *     integer if num > 0. -Infinity if num == 0. NaN if num < 0.
    - */
    -goog.math.log10Floor = function(num) {
    -  if (num > 0) {
    -    var x = Math.round(Math.log(num) * Math.LOG10E);
    -    return x - (parseFloat('1e' + x) > num);
    -  }
    -  return num == 0 ? -Infinity : NaN;
    -};
    -
    -
    -/**
    - * A tweaked variant of {@code Math.floor} which tolerates if the passed number
    - * is infinitesimally smaller than the closest integer. It often happens with
    - * the results of floating point calculations because of the finite precision
    - * of the intermediate results. For example {@code Math.floor(Math.log(1000) /
    - * Math.LN10) == 2}, not 3 as one would expect.
    - * @param {number} num A number.
    - * @param {number=} opt_epsilon An infinitesimally small positive number, the
    - *     rounding error to tolerate.
    - * @return {number} The largest integer less than or equal to {@code num}.
    - */
    -goog.math.safeFloor = function(num, opt_epsilon) {
    -  goog.asserts.assert(!goog.isDef(opt_epsilon) || opt_epsilon > 0);
    -  return Math.floor(num + (opt_epsilon || 2e-15));
    -};
    -
    -
    -/**
    - * A tweaked variant of {@code Math.ceil}. See {@code goog.math.safeFloor} for
    - * details.
    - * @param {number} num A number.
    - * @param {number=} opt_epsilon An infinitesimally small positive number, the
    - *     rounding error to tolerate.
    - * @return {number} The smallest integer greater than or equal to {@code num}.
    - */
    -goog.math.safeCeil = function(num, opt_epsilon) {
    -  goog.asserts.assert(!goog.isDef(opt_epsilon) || opt_epsilon > 0);
    -  return Math.ceil(num - (opt_epsilon || 2e-15));
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/math/math_test.html b/src/database/third_party/closure-library/closure/goog/math/math_test.html
    deleted file mode 100644
    index 400c0b93cf8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/math_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.math
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.mathTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/math/math_test.js b/src/database/third_party/closure-library/closure/goog/math/math_test.js
    deleted file mode 100644
    index c3f31eb3bc7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/math_test.js
    +++ /dev/null
    @@ -1,332 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.mathTest');
    -goog.setTestOnly('goog.mathTest');
    -
    -goog.require('goog.math');
    -goog.require('goog.testing.jsunit');
    -
    -function testRandomInt() {
    -  assertEquals(0, goog.math.randomInt(0));
    -  assertEquals(0, goog.math.randomInt(1));
    -
    -  var r = goog.math.randomInt(3);
    -  assertTrue(0 <= r && r < 3);
    -}
    -
    -function testUniformRandom() {
    -  assertEquals(5.2, goog.math.uniformRandom(5.2, 5.2));
    -  assertEquals(-6, goog.math.uniformRandom(-6, -6));
    -
    -  var r = goog.math.uniformRandom(-0.5, 0.5);
    -  assertTrue(-0.5 <= r && r < 0.5);
    -}
    -
    -function testClamp() {
    -  assertEquals(3, goog.math.clamp(3, -5, 5));
    -  assertEquals(5, goog.math.clamp(5, -5, 5));
    -  assertEquals(-5, goog.math.clamp(-5, -5, 5));
    -
    -  assertEquals(-5, goog.math.clamp(-22, -5, 5));
    -  assertEquals(5, goog.math.clamp(6, -5, 5));
    -}
    -
    -function testModulo() {
    -  assertEquals(0, goog.math.modulo(256, 8));
    -
    -  assertEquals(7, goog.math.modulo(7, 8));
    -  assertEquals(7, goog.math.modulo(23, 8));
    -  assertEquals(7, goog.math.modulo(-1, 8));
    -
    -  // Safari 5.1.7 has a bug in its JS engine where modulo is computed
    -  // incorrectly when using variables. We avoid using
    -  // goog.testing.ExpectedFailure here since it pulls in a bunch of
    -  // extra dependencies for maintaining a DOM console.
    -  var a = 1;
    -  var b = -5;
    -  if (a % b === 1 % -5) {
    -    assertEquals(-4, goog.math.modulo(1, -5));
    -    assertEquals(-4, goog.math.modulo(6, -5));
    -  }
    -  assertEquals(-4, goog.math.modulo(-4, -5));
    -}
    -
    -function testLerp() {
    -  assertEquals(0, goog.math.lerp(0, 0, 0));
    -  assertEquals(3, goog.math.lerp(0, 6, 0.5));
    -  assertEquals(3, goog.math.lerp(-1, 1, 2));
    -}
    -
    -function testNearlyEquals() {
    -  assertTrue('Numbers inside default tolerance should be equal',
    -             goog.math.nearlyEquals(0.000001, 0.000001001));
    -  assertFalse('Numbers outside default tolerance should be unequal',
    -              goog.math.nearlyEquals(0.000001, 0.000003));
    -  assertTrue('Numbers inside custom tolerance should be equal',
    -             goog.math.nearlyEquals(0.001, 0.002, 0.1));
    -  assertFalse('Numbers outside custom tolerance should be unequal',
    -              goog.math.nearlyEquals(0.001, -0.1, 0.1));
    -  assertTrue('Integer tolerance greater than one should succeed',
    -             goog.math.nearlyEquals(87, 85, 3));
    -}
    -
    -function testStandardAngleInRadians() {
    -  assertRoughlyEquals(0, goog.math.standardAngleInRadians(2 * Math.PI), 1e-10);
    -  assertRoughlyEquals(
    -      Math.PI, goog.math.standardAngleInRadians(Math.PI), 1e-10);
    -  assertRoughlyEquals(
    -      Math.PI, goog.math.standardAngleInRadians(-1 * Math.PI), 1e-10);
    -  assertRoughlyEquals(
    -      Math.PI / 2, goog.math.standardAngleInRadians(-1.5 * Math.PI), 1e-10);
    -  assertRoughlyEquals(
    -      Math.PI, goog.math.standardAngleInRadians(5 * Math.PI), 1e-10);
    -  assertEquals(0.01, goog.math.standardAngleInRadians(0.01));
    -  assertEquals(0, goog.math.standardAngleInRadians(0));
    -}
    -
    -function testStandardAngle() {
    -  assertEquals(359.5, goog.math.standardAngle(-360.5));
    -  assertEquals(0, goog.math.standardAngle(-360));
    -  assertEquals(359.5, goog.math.standardAngle(-0.5));
    -  assertEquals(0, goog.math.standardAngle(0));
    -  assertEquals(0.5, goog.math.standardAngle(0.5));
    -  assertEquals(0, goog.math.standardAngle(360));
    -  assertEquals(1, goog.math.standardAngle(721));
    -}
    -
    -function testToRadians() {
    -  assertEquals(-Math.PI, goog.math.toRadians(-180));
    -  assertEquals(0, goog.math.toRadians(0));
    -  assertEquals(Math.PI, goog.math.toRadians(180));
    -}
    -
    -function testToDegrees() {
    -  assertEquals(-180, goog.math.toDegrees(-Math.PI));
    -  assertEquals(0, goog.math.toDegrees(0));
    -  assertEquals(180, goog.math.toDegrees(Math.PI));
    -}
    -
    -function testAngleDx() {
    -  assertRoughlyEquals(0, goog.math.angleDx(0, 0), 1e-10);
    -  assertRoughlyEquals(0, goog.math.angleDx(90, 0), 1e-10);
    -  assertRoughlyEquals(100, goog.math.angleDx(0, 100), 1e-10);
    -  assertRoughlyEquals(0, goog.math.angleDx(90, 100), 1e-10);
    -  assertRoughlyEquals(-100, goog.math.angleDx(180, 100), 1e-10);
    -  assertRoughlyEquals(0, goog.math.angleDx(270, 100), 1e-10);
    -}
    -
    -function testAngleDy() {
    -  assertRoughlyEquals(0, goog.math.angleDy(0, 0), 1e-10);
    -  assertRoughlyEquals(0, goog.math.angleDy(90, 0), 1e-10);
    -  assertRoughlyEquals(0, goog.math.angleDy(0, 100), 1e-10);
    -  assertRoughlyEquals(100, goog.math.angleDy(90, 100), 1e-10);
    -  assertRoughlyEquals(0, goog.math.angleDy(180, 100), 1e-10);
    -  assertRoughlyEquals(-100, goog.math.angleDy(270, 100), 1e-10);
    -}
    -
    -function testAngle() {
    -  assertRoughlyEquals(0, goog.math.angle(10, 10, 20, 10), 1e-10);
    -  assertRoughlyEquals(90, goog.math.angle(10, 10, 10, 20), 1e-10);
    -  assertRoughlyEquals(225, goog.math.angle(10, 10, 0, 0), 1e-10);
    -  assertRoughlyEquals(270, goog.math.angle(10, 10, 10, 0), 1e-10);
    -
    -  // 0 is the conventional result, but mathematically this is undefined.
    -  assertEquals(0, goog.math.angle(10, 10, 10, 10));
    -}
    -
    -function testAngleDifference() {
    -  assertEquals(10, goog.math.angleDifference(30, 40));
    -  assertEquals(-10, goog.math.angleDifference(40, 30));
    -  assertEquals(180, goog.math.angleDifference(10, 190));
    -  assertEquals(180, goog.math.angleDifference(190, 10));
    -  assertEquals(20, goog.math.angleDifference(350, 10));
    -  assertEquals(-20, goog.math.angleDifference(10, 350));
    -  assertEquals(100, goog.math.angleDifference(350, 90));
    -  assertEquals(-80, goog.math.angleDifference(350, 270));
    -  assertEquals(0, goog.math.angleDifference(15, 15));
    -}
    -
    -function testSign() {
    -  assertEquals(-1, goog.math.sign(-1));
    -  assertEquals(1, goog.math.sign(1));
    -  assertEquals(0, goog.math.sign(0));
    -  assertEquals(0, goog.math.sign(-0));
    -  assertEquals(1, goog.math.sign(0.0001));
    -  assertEquals(-1, goog.math.sign(-0.0001));
    -  assertEquals(-1, goog.math.sign(-Infinity));
    -  assertEquals(1, goog.math.sign(Infinity));
    -  assertEquals(1, goog.math.sign(3141592653589793));
    -}
    -
    -function testLongestCommonSubsequence() {
    -  var func = goog.math.longestCommonSubsequence;
    -
    -  assertArrayEquals([2], func([1, 2], [2, 1]));
    -  assertArrayEquals([1, 2], func([1, 2, 5], [2, 1, 2]));
    -  assertArrayEquals([1, 2, 3, 4, 5],
    -      func([1, 0, 2, 3, 8, 4, 9, 5], [8, 1, 2, 4, 3, 6, 4, 5]));
    -  assertArrayEquals([1, 1, 1, 1, 1], func([1, 1, 1, 1, 1], [1, 1, 1, 1, 1]));
    -  assertArrayEquals([5], func([1, 2, 3, 4, 5], [5, 4, 3, 2, 1]));
    -  assertArrayEquals([1, 8, 11],
    -      func([1, 6, 8, 11, 13], [1, 3, 5, 8, 9, 11, 12]));
    -}
    -
    -function testLongestCommonSubsequenceWithCustomComparator() {
    -  var func = goog.math.longestCommonSubsequence;
    -
    -  var compareFn = function(a, b) {
    -    return a.field == b.field;
    -  };
    -
    -  var a1 = {field: 'a1', field2: 'hello'};
    -  var a2 = {field: 'a2', field2: 33};
    -  var a3 = {field: 'a3'};
    -  var a4 = {field: 'a3'};
    -
    -  assertArrayEquals([a1, a2], func([a1, a2, a3], [a3, a1, a2], compareFn));
    -  assertArrayEquals([a1, a3], func([a1, a3], [a1, a4], compareFn));
    -  // testing the same arrays without compare function
    -  assertArrayEquals([a1], func([a1, a3], [a1, a4]));
    -}
    -
    -function testLongestCommonSubsequenceWithCustomCollector() {
    -  var func = goog.math.longestCommonSubsequence;
    -
    -  var collectorFn = function(a, b) {
    -    return b;
    -  };
    -
    -  assertArrayEquals([1, 2, 4, 6, 7],
    -      func([1, 0, 2, 3, 8, 4, 9, 5], [8, 1, 2, 4, 3, 6, 4, 5],
    -      null, collectorFn));
    -}
    -
    -function testSum() {
    -  assertEquals('sum() must return 0 if there are no arguments',
    -      0, goog.math.sum());
    -  assertEquals('sum() must return its argument if there is only one',
    -      17, goog.math.sum(17));
    -  assertEquals('sum() must handle positive integers',
    -      10, goog.math.sum(1, 2, 3, 4));
    -  assertEquals('sum() must handle real numbers',
    -      -2.5, goog.math.sum(1, -2, 3, -4.5));
    -  assertTrue('sum() must return NaN if one of the arguments isn\'t numeric',
    -      isNaN(goog.math.sum(1, 2, 'foo', 3)));
    -}
    -
    -function testAverage() {
    -  assertTrue('average() must return NaN if there are no arguments',
    -      isNaN(goog.math.average()));
    -  assertEquals('average() must return its argument if there is only one',
    -      17, goog.math.average(17));
    -  assertEquals('average() must handle positive integers',
    -      3, goog.math.average(1, 2, 3, 4, 5));
    -  assertEquals('average() must handle real numbers',
    -      -0.625, goog.math.average(1, -2, 3, -4.5));
    -  assertTrue('average() must return NaN if one of the arguments isn\'t ' +
    -      'numeric', isNaN(goog.math.average(1, 2, 'foo', 3)));
    -}
    -
    -function testSampleVariance() {
    -  assertEquals('sampleVariance() must return 0 if there are no samples',
    -      0, goog.math.sampleVariance());
    -  assertEquals('sampleVariance() must return 0 if there is only one ' +
    -      'sample', 0, goog.math.sampleVariance(17));
    -  assertRoughlyEquals('sampleVariance() must handle positive integers',
    -      48, goog.math.sampleVariance(3, 7, 7, 19),
    -      0.0001);
    -  assertRoughlyEquals('sampleVariance() must handle real numbers',
    -      12.0138, goog.math.sampleVariance(1.23, -2.34, 3.14, -4.56),
    -      0.0001);
    -}
    -
    -function testStandardDeviation() {
    -  assertEquals('standardDeviation() must return 0 if there are no samples',
    -      0, goog.math.standardDeviation());
    -  assertEquals('standardDeviation() must return 0 if there is only one ' +
    -      'sample', 0, goog.math.standardDeviation(17));
    -  assertRoughlyEquals('standardDeviation() must handle positive integers',
    -      6.9282, goog.math.standardDeviation(3, 7, 7, 19),
    -      0.0001);
    -  assertRoughlyEquals('standardDeviation() must handle real numbers',
    -      3.4660, goog.math.standardDeviation(1.23, -2.34, 3.14, -4.56),
    -      0.0001);
    -}
    -
    -function testIsInt() {
    -  assertFalse(goog.math.isInt(12345.67));
    -  assertFalse(goog.math.isInt(0.123));
    -  assertFalse(goog.math.isInt(.1));
    -  assertFalse(goog.math.isInt(-23.43));
    -  assertFalse(goog.math.isInt(-.1));
    -  assertFalse(goog.math.isInt(1e-1));
    -  assertTrue(goog.math.isInt(1));
    -  assertTrue(goog.math.isInt(0));
    -  assertTrue(goog.math.isInt(-2));
    -  assertTrue(goog.math.isInt(-2.0));
    -  assertTrue(goog.math.isInt(10324231));
    -  assertTrue(goog.math.isInt(1.));
    -  assertTrue(goog.math.isInt(1e3));
    -}
    -
    -function testIsFiniteNumber() {
    -  assertFalse(goog.math.isFiniteNumber(NaN));
    -  assertFalse(goog.math.isFiniteNumber(-Infinity));
    -  assertFalse(goog.math.isFiniteNumber(+Infinity));
    -  assertTrue(goog.math.isFiniteNumber(0));
    -  assertTrue(goog.math.isFiniteNumber(1));
    -  assertTrue(goog.math.isFiniteNumber(Math.PI));
    -}
    -
    -function testLog10Floor() {
    -  // The greatest floating point number that is less than 1.
    -  var oneMinusEpsilon = 1 - Math.pow(2, -53);
    -  for (var i = -30; i <= 30; i++) {
    -    assertEquals(i, goog.math.log10Floor(parseFloat('1e' + i)));
    -    assertEquals(i - 1,
    -        goog.math.log10Floor(parseFloat('1e' + i) * oneMinusEpsilon));
    -  }
    -  assertEquals(-Infinity, goog.math.log10Floor(0));
    -  assertTrue(isNaN(goog.math.log10Floor(-1)));
    -}
    -
    -function testSafeFloor() {
    -  assertEquals(0, goog.math.safeFloor(0));
    -  assertEquals(0, goog.math.safeFloor(1e-15));
    -  assertEquals(0, goog.math.safeFloor(-1e-15));
    -  assertEquals(-1, goog.math.safeFloor(-3e-15));
    -  assertEquals(4, goog.math.safeFloor(5 - 3e-15));
    -  assertEquals(5, goog.math.safeFloor(5 - 1e-15));
    -  assertEquals(-5, goog.math.safeFloor(-5 - 1e-15));
    -  assertEquals(-6, goog.math.safeFloor(-5 - 3e-15));
    -  assertEquals(3, goog.math.safeFloor(2.91, 0.1));
    -  assertEquals(2, goog.math.safeFloor(2.89, 0.1));
    -  // Tests some real life examples with the default epsilon value.
    -  assertEquals(0, goog.math.safeFloor(Math.log(1000) / Math.LN10 - 3));
    -  assertEquals(21, goog.math.safeFloor(Math.log(1e+21) / Math.LN10));
    -}
    -
    -function testSafeCeil() {
    -  assertEquals(0, goog.math.safeCeil(0));
    -  assertEquals(0, goog.math.safeCeil(1e-15));
    -  assertEquals(0, goog.math.safeCeil(-1e-15));
    -  assertEquals(1, goog.math.safeCeil(3e-15));
    -  assertEquals(6, goog.math.safeCeil(5 + 3e-15));
    -  assertEquals(5, goog.math.safeCeil(5 + 1e-15));
    -  assertEquals(-4, goog.math.safeCeil(-5 + 3e-15));
    -  assertEquals(-5, goog.math.safeCeil(-5 + 1e-15));
    -  assertEquals(3, goog.math.safeCeil(3.09, 0.1));
    -  assertEquals(4, goog.math.safeCeil(3.11, 0.1));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/math/matrix.js b/src/database/third_party/closure-library/closure/goog/math/matrix.js
    deleted file mode 100644
    index 4f67fa49f6f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/matrix.js
    +++ /dev/null
    @@ -1,681 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Class for representing matrices and static helper functions.
    - */
    -
    -goog.provide('goog.math.Matrix');
    -
    -goog.require('goog.array');
    -goog.require('goog.math');
    -goog.require('goog.math.Size');
    -goog.require('goog.string');
    -
    -
    -
    -/**
    - * Class for representing and manipulating matrices.
    - *
    - * The entry that lies in the i-th row and the j-th column of a matrix is
    - * typically referred to as the i,j entry of the matrix.
    - *
    - * The m-by-n matrix A would have its entries referred to as:
    - *   [ a0,0   a0,1   a0,2   ...   a0,j  ...  a0,n ]
    - *   [ a1,0   a1,1   a1,2   ...   a1,j  ...  a1,n ]
    - *   [ a2,0   a2,1   a2,2   ...   a2,j  ...  a2,n ]
    - *   [  .      .      .            .          .   ]
    - *   [  .      .      .            .          .   ]
    - *   [  .      .      .            .          .   ]
    - *   [ ai,0   ai,1   ai,2   ...   ai,j  ...  ai,n ]
    - *   [  .      .      .            .          .   ]
    - *   [  .      .      .            .          .   ]
    - *   [  .      .      .            .          .   ]
    - *   [ am,0   am,1   am,2   ...   am,j  ...  am,n ]
    - *
    - * @param {!goog.math.Matrix|!Array<!Array<number>>|!goog.math.Size|number} m
    - *     A matrix to copy, a 2D-array to take as a template, a size object for
    - *     dimensions, or the number of rows.
    - * @param {number=} opt_n Number of columns of the matrix (only applicable if
    - *     the first argument is also numeric).
    - * @struct
    - * @constructor
    - * @final
    - */
    -goog.math.Matrix = function(m, opt_n) {
    -  if (m instanceof goog.math.Matrix) {
    -    this.array_ = m.toArray();
    -  } else if (goog.isArrayLike(m) &&
    -             goog.math.Matrix.isValidArray(
    -                 /** @type {!Array<!Array<number>>} */ (m))) {
    -    this.array_ = goog.array.clone(/** @type {!Array<!Array<number>>} */ (m));
    -  } else if (m instanceof goog.math.Size) {
    -    this.array_ = goog.math.Matrix.createZeroPaddedArray_(m.height, m.width);
    -  } else if (goog.isNumber(m) && goog.isNumber(opt_n) && m > 0 && opt_n > 0) {
    -    this.array_ = goog.math.Matrix.createZeroPaddedArray_(
    -        /** @type {number} */ (m), opt_n);
    -  } else {
    -    throw Error('Invalid argument(s) for Matrix contructor');
    -  }
    -
    -  this.size_ = new goog.math.Size(this.array_[0].length, this.array_.length);
    -};
    -
    -
    -/**
    - * Creates a square identity matrix. i.e. for n = 3:
    - * <pre>
    - * [ 1 0 0 ]
    - * [ 0 1 0 ]
    - * [ 0 0 1 ]
    - * </pre>
    - * @param {number} n The size of the square identity matrix.
    - * @return {!goog.math.Matrix} Identity matrix of width and height {@code n}.
    - */
    -goog.math.Matrix.createIdentityMatrix = function(n) {
    -  var rv = [];
    -  for (var i = 0; i < n; i++) {
    -    rv[i] = [];
    -    for (var j = 0; j < n; j++) {
    -      rv[i][j] = i == j ? 1 : 0;
    -    }
    -  }
    -  return new goog.math.Matrix(rv);
    -};
    -
    -
    -/**
    - * Calls a function for each cell in a matrix.
    - * @param {goog.math.Matrix} matrix The matrix to iterate over.
    - * @param {function(this:T, number, number, number, !goog.math.Matrix)} fn
    - *     The function to call for every element. This function
    - *     takes 4 arguments (value, i, j, and the matrix)
    - *     and the return value is irrelevant.
    - * @param {T=} opt_obj The object to be used as the value of 'this'
    - *     within {@code fn}.
    - * @template T
    - */
    -goog.math.Matrix.forEach = function(matrix, fn, opt_obj) {
    -  for (var i = 0; i < matrix.getSize().height; i++) {
    -    for (var j = 0; j < matrix.getSize().width; j++) {
    -      fn.call(opt_obj, matrix.array_[i][j], i, j, matrix);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Tests whether an array is a valid matrix.  A valid array is an array of
    - * arrays where all arrays are of the same length and all elements are numbers.
    - * @param {!Array<!Array<number>>} arr An array to test.
    - * @return {boolean} Whether the array is a valid matrix.
    - */
    -goog.math.Matrix.isValidArray = function(arr) {
    -  var len = 0;
    -  for (var i = 0; i < arr.length; i++) {
    -    if (!goog.isArrayLike(arr[i]) || len > 0 && arr[i].length != len) {
    -      return false;
    -    }
    -    for (var j = 0; j < arr[i].length; j++) {
    -      if (!goog.isNumber(arr[i][j])) {
    -        return false;
    -      }
    -    }
    -    if (len == 0) {
    -      len = arr[i].length;
    -    }
    -  }
    -  return len != 0;
    -};
    -
    -
    -/**
    - * Calls a function for every cell in a matrix and inserts the result into a
    - * new matrix of equal dimensions.
    - * @param {!goog.math.Matrix} matrix The matrix to iterate over.
    - * @param {function(this:T, number, number, number, !goog.math.Matrix): number}
    - *     fn The function to call for every element. This function
    - *     takes 4 arguments (value, i, j and the matrix)
    - *     and should return a number, which will be inserted into a new matrix.
    - * @param {T=} opt_obj The object to be used as the value of 'this'
    - *     within {@code fn}.
    - * @return {!goog.math.Matrix} A new matrix with the results from {@code fn}.
    - * @template T
    - */
    -goog.math.Matrix.map = function(matrix, fn, opt_obj) {
    -  var m = new goog.math.Matrix(matrix.getSize());
    -  goog.math.Matrix.forEach(matrix, function(value, i, j) {
    -    m.array_[i][j] = fn.call(opt_obj, value, i, j, matrix);
    -  });
    -  return m;
    -};
    -
    -
    -/**
    - * Creates a new zero padded matix.
    - * @param {number} m Height of matrix.
    - * @param {number} n Width of matrix.
    - * @return {!Array<!Array<number>>} The new zero padded matrix.
    - * @private
    - */
    -goog.math.Matrix.createZeroPaddedArray_ = function(m, n) {
    -  var rv = [];
    -  for (var i = 0; i < m; i++) {
    -    rv[i] = [];
    -    for (var j = 0; j < n; j++) {
    -      rv[i][j] = 0;
    -    }
    -  }
    -  return rv;
    -};
    -
    -
    -/**
    - * Internal array representing the matrix.
    - * @type {!Array<!Array<number>>}
    - * @private
    - */
    -goog.math.Matrix.prototype.array_;
    -
    -
    -/**
    - * After construction the Matrix's size is constant and stored in this object.
    - * @type {!goog.math.Size}
    - * @private
    - */
    -goog.math.Matrix.prototype.size_;
    -
    -
    -/**
    - * Returns a new matrix that is the sum of this and the provided matrix.
    - * @param {goog.math.Matrix} m The matrix to add to this one.
    - * @return {!goog.math.Matrix} Resultant sum.
    - */
    -goog.math.Matrix.prototype.add = function(m) {
    -  if (!goog.math.Size.equals(this.size_, m.getSize())) {
    -    throw Error('Matrix summation is only supported on arrays of equal size');
    -  }
    -  return goog.math.Matrix.map(this, function(val, i, j) {
    -    return val + m.array_[i][j];
    -  });
    -};
    -
    -
    -/**
    - * Appends the given matrix to the right side of this matrix.
    - * @param {goog.math.Matrix} m The matrix to augment this matrix with.
    - * @return {!goog.math.Matrix} A new matrix with additional columns on the
    - *     right.
    - */
    -goog.math.Matrix.prototype.appendColumns = function(m) {
    -  if (this.size_.height != m.getSize().height) {
    -    throw Error('The given matrix has height ' + m.size_.height + ', but ' +
    -        ' needs to have height ' + this.size_.height + '.');
    -  }
    -  var result = new goog.math.Matrix(this.size_.height,
    -      this.size_.width + m.size_.width);
    -  goog.math.Matrix.forEach(this, function(value, i, j) {
    -    result.array_[i][j] = value;
    -  });
    -  goog.math.Matrix.forEach(m, function(value, i, j) {
    -    result.array_[i][this.size_.width + j] = value;
    -  }, this);
    -  return result;
    -};
    -
    -
    -/**
    - * Appends the given matrix to the bottom of this matrix.
    - * @param {goog.math.Matrix} m The matrix to augment this matrix with.
    - * @return {!goog.math.Matrix} A new matrix with added columns on the bottom.
    - */
    -goog.math.Matrix.prototype.appendRows = function(m) {
    -  if (this.size_.width != m.getSize().width) {
    -    throw Error('The given matrix has width ' + m.size_.width + ', but ' +
    -        ' needs to have width ' + this.size_.width + '.');
    -  }
    -  var result = new goog.math.Matrix(this.size_.height + m.size_.height,
    -      this.size_.width);
    -  goog.math.Matrix.forEach(this, function(value, i, j) {
    -    result.array_[i][j] = value;
    -  });
    -  goog.math.Matrix.forEach(m, function(value, i, j) {
    -    result.array_[this.size_.height + i][j] = value;
    -  }, this);
    -  return result;
    -};
    -
    -
    -/**
    - * Returns whether the given matrix equals this matrix.
    - * @param {goog.math.Matrix} m The matrix to compare to this one.
    - * @param {number=} opt_tolerance The tolerance when comparing array entries.
    - * @return {boolean} Whether the given matrix equals this matrix.
    - */
    -goog.math.Matrix.prototype.equals = function(m, opt_tolerance) {
    -  if (this.size_.width != m.size_.width) {
    -    return false;
    -  }
    -  if (this.size_.height != m.size_.height) {
    -    return false;
    -  }
    -
    -  var tolerance = opt_tolerance || 0;
    -  for (var i = 0; i < this.size_.height; i++) {
    -    for (var j = 0; j < this.size_.width; j++) {
    -      if (!goog.math.nearlyEquals(this.array_[i][j], m.array_[i][j],
    -          tolerance)) {
    -        return false;
    -      }
    -    }
    -  }
    -
    -  return true;
    -};
    -
    -
    -/**
    - * Returns the determinant of this matrix.  The determinant of a matrix A is
    - * often denoted as |A| and can only be applied to a square matrix.
    - * @return {number} The determinant of this matrix.
    - */
    -goog.math.Matrix.prototype.getDeterminant = function() {
    -  if (!this.isSquare()) {
    -    throw Error('A determinant can only be take on a square matrix');
    -  }
    -
    -  return this.getDeterminant_();
    -};
    -
    -
    -/**
    - * Returns the inverse of this matrix if it exists or null if the matrix is
    - * not invertible.
    - * @return {goog.math.Matrix} A new matrix which is the inverse of this matrix.
    - */
    -goog.math.Matrix.prototype.getInverse = function() {
    -  if (!this.isSquare()) {
    -    throw Error('An inverse can only be taken on a square matrix.');
    -  }
    -  if (this.getSize().width == 1) {
    -    var a = this.getValueAt(0, 0);
    -    return a == 0 ? null : new goog.math.Matrix([[1 / a]]);
    -  }
    -  var identity = goog.math.Matrix.createIdentityMatrix(this.size_.height);
    -  var mi = this.appendColumns(identity).getReducedRowEchelonForm();
    -  var i = mi.getSubmatrixByCoordinates_(
    -      0, 0, identity.size_.width - 1, identity.size_.height - 1);
    -  if (!i.equals(identity)) {
    -    return null;  // This matrix was not invertible
    -  }
    -  return mi.getSubmatrixByCoordinates_(0, identity.size_.width);
    -};
    -
    -
    -/**
    - * Transforms this matrix into reduced row echelon form.
    - * @return {!goog.math.Matrix} A new matrix reduced row echelon form.
    - */
    -goog.math.Matrix.prototype.getReducedRowEchelonForm = function() {
    -  var result = new goog.math.Matrix(this);
    -  var col = 0;
    -  // Each iteration puts one row in reduced row echelon form
    -  for (var row = 0; row < result.size_.height; row++) {
    -    if (col >= result.size_.width) {
    -      return result;
    -    }
    -
    -    // Scan each column starting from this row on down for a non-zero value
    -    var i = row;
    -    while (result.array_[i][col] == 0) {
    -      i++;
    -      if (i == result.size_.height) {
    -        i = row;
    -        col++;
    -        if (col == result.size_.width) {
    -          return result;
    -        }
    -      }
    -    }
    -
    -    // Make the row we found the current row with a leading 1
    -    this.swapRows_(i, row);
    -    var divisor = result.array_[row][col];
    -    for (var j = col; j < result.size_.width; j++) {
    -      result.array_[row][j] = result.array_[row][j] / divisor;
    -    }
    -
    -    // Subtract a multiple of this row from each other row
    -    // so that all the other entries in this column are 0
    -    for (i = 0; i < result.size_.height; i++) {
    -      if (i != row) {
    -        var multiple = result.array_[i][col];
    -        for (var j = col; j < result.size_.width; j++) {
    -          result.array_[i][j] -= multiple * result.array_[row][j];
    -        }
    -      }
    -    }
    -
    -    // Move on to the next column
    -    col++;
    -  }
    -  return result;
    -};
    -
    -
    -/**
    - * @return {!goog.math.Size} The dimensions of the matrix.
    - */
    -goog.math.Matrix.prototype.getSize = function() {
    -  return this.size_;
    -};
    -
    -
    -/**
    - * Return the transpose of this matrix.  For an m-by-n matrix, the transpose
    - * is the n-by-m matrix which results from turning rows into columns and columns
    - * into rows
    - * @return {!goog.math.Matrix} A new matrix A^T.
    - */
    -goog.math.Matrix.prototype.getTranspose = function() {
    -  var m = new goog.math.Matrix(this.size_.width, this.size_.height);
    -  goog.math.Matrix.forEach(this, function(value, i, j) {
    -    m.array_[j][i] = value;
    -  });
    -  return m;
    -};
    -
    -
    -/**
    - * Retrieves the value of a particular coordinate in the matrix or null if the
    - * requested coordinates are out of range.
    - * @param {number} i The i index of the coordinate.
    - * @param {number} j The j index of the coordinate.
    - * @return {?number} The value at the specified coordinate.
    - */
    -goog.math.Matrix.prototype.getValueAt = function(i, j) {
    -  if (!this.isInBounds_(i, j)) {
    -    return null;
    -  }
    -  return this.array_[i][j];
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the horizontal and vertical dimensions of this
    - *     matrix are the same.
    - */
    -goog.math.Matrix.prototype.isSquare = function() {
    -  return this.size_.width == this.size_.height;
    -};
    -
    -
    -/**
    - * Sets the value at a particular coordinate (if the coordinate is within the
    - * bounds of the matrix).
    - * @param {number} i The i index of the coordinate.
    - * @param {number} j The j index of the coordinate.
    - * @param {number} value The new value for the coordinate.
    - */
    -goog.math.Matrix.prototype.setValueAt = function(i, j, value) {
    -  if (!this.isInBounds_(i, j)) {
    -    throw Error(
    -        'Index out of bounds when setting matrix value, (' + i + ',' + j +
    -        ') in size (' + this.size_.height + ',' + this.size_.width + ')');
    -  }
    -  this.array_[i][j] = value;
    -};
    -
    -
    -/**
    - * Performs matrix or scalar multiplication on a matrix and returns the
    - * resultant matrix.
    - *
    - * Matrix multiplication is defined between two matrices only if the number of
    - * columns of the first matrix is the same as the number of rows of the second
    - * matrix. If A is an m-by-n matrix and B is an n-by-p matrix, then their
    - * product AB is an m-by-p matrix
    - *
    - * Scalar multiplication returns a matrix of the same size as the original,
    - * each value multiplied by the given value.
    - *
    - * @param {goog.math.Matrix|number} m Matrix/number to multiply the matrix by.
    - * @return {!goog.math.Matrix} Resultant product.
    - */
    -goog.math.Matrix.prototype.multiply = function(m) {
    -  if (m instanceof goog.math.Matrix) {
    -    if (this.size_.width != m.getSize().height) {
    -      throw Error('Invalid matrices for multiplication. Second matrix ' +
    -          'should have the same number of rows as the first has columns.');
    -    }
    -    return this.matrixMultiply_(/** @type {!goog.math.Matrix} */ (m));
    -  } else if (goog.isNumber(m)) {
    -    return this.scalarMultiply_(/** @type {number} */ (m));
    -  } else {
    -    throw Error('A matrix can only be multiplied by' +
    -        ' a number or another matrix.');
    -  }
    -};
    -
    -
    -/**
    - * Returns a new matrix that is the difference of this and the provided matrix.
    - * @param {goog.math.Matrix} m The matrix to subtract from this one.
    - * @return {!goog.math.Matrix} Resultant difference.
    - */
    -goog.math.Matrix.prototype.subtract = function(m) {
    -  if (!goog.math.Size.equals(this.size_, m.getSize())) {
    -    throw Error(
    -        'Matrix subtraction is only supported on arrays of equal size.');
    -  }
    -  return goog.math.Matrix.map(this, function(val, i, j) {
    -    return val - m.array_[i][j];
    -  });
    -};
    -
    -
    -/**
    - * @return {!Array<!Array<number>>} A 2D internal array representing this
    - *     matrix.  Not a clone.
    - */
    -goog.math.Matrix.prototype.toArray = function() {
    -  return this.array_;
    -};
    -
    -
    -if (goog.DEBUG) {
    -  /**
    -   * Returns a string representation of the matrix.  e.g.
    -   * <pre>
    -   * [ 12  5  9  1 ]
    -   * [  4 16  0 17 ]
    -   * [ 12  5  1 23 ]
    -   * </pre>
    -   *
    -   * @return {string} A string representation of this matrix.
    -   * @override
    -   */
    -  goog.math.Matrix.prototype.toString = function() {
    -    // Calculate correct padding for optimum display of matrix
    -    var maxLen = 0;
    -    goog.math.Matrix.forEach(this, function(val) {
    -      var len = String(val).length;
    -      if (len > maxLen) {
    -        maxLen = len;
    -      }
    -    });
    -
    -    // Build the string
    -    var sb = [];
    -    goog.array.forEach(this.array_, function(row, x) {
    -      sb.push('[ ');
    -      goog.array.forEach(row, function(val, y) {
    -        var strval = String(val);
    -        sb.push(goog.string.repeat(' ', maxLen - strval.length) + strval + ' ');
    -      });
    -      sb.push(']\n');
    -    });
    -
    -    return sb.join('');
    -  };
    -}
    -
    -
    -/**
    - * Returns the signed minor.
    - * @param {number} i The row index.
    - * @param {number} j The column index.
    - * @return {number} The cofactor C[i,j] of this matrix.
    - * @private
    - */
    -goog.math.Matrix.prototype.getCofactor_ = function(i, j) {
    -  return (i + j % 2 == 0 ? 1 : -1) * this.getMinor_(i, j);
    -};
    -
    -
    -/**
    - * Returns the determinant of this matrix.  The determinant of a matrix A is
    - * often denoted as |A| and can only be applied to a square matrix.  Same as
    - * public method but without validation.  Implemented using Laplace's formula.
    - * @return {number} The determinant of this matrix.
    - * @private
    - */
    -goog.math.Matrix.prototype.getDeterminant_ = function() {
    -  if (this.getSize().area() == 1) {
    -    return this.array_[0][0];
    -  }
    -
    -  // We might want to use matrix decomposition to improve running time
    -  // For now we'll do a Laplace expansion along the first row
    -  var determinant = 0;
    -  for (var j = 0; j < this.size_.width; j++) {
    -    determinant += (this.array_[0][j] * this.getCofactor_(0, j));
    -  }
    -  return determinant;
    -};
    -
    -
    -/**
    - * Returns the determinant of the submatrix resulting from the deletion of row i
    - * and column j.
    - * @param {number} i The row to delete.
    - * @param {number} j The column to delete.
    - * @return {number} The first minor M[i,j] of this matrix.
    - * @private
    - */
    -goog.math.Matrix.prototype.getMinor_ = function(i, j) {
    -  return this.getSubmatrixByDeletion_(i, j).getDeterminant_();
    -};
    -
    -
    -/**
    - * Returns a submatrix contained within this matrix.
    - * @param {number} i1 The upper row index.
    - * @param {number} j1 The left column index.
    - * @param {number=} opt_i2 The lower row index.
    - * @param {number=} opt_j2 The right column index.
    - * @return {!goog.math.Matrix} The submatrix contained within the given bounds.
    - * @private
    - */
    -goog.math.Matrix.prototype.getSubmatrixByCoordinates_ =
    -    function(i1, j1, opt_i2, opt_j2) {
    -  var i2 = opt_i2 ? opt_i2 : this.size_.height - 1;
    -  var j2 = opt_j2 ? opt_j2 : this.size_.width - 1;
    -  var result = new goog.math.Matrix(i2 - i1 + 1, j2 - j1 + 1);
    -  goog.math.Matrix.forEach(result, function(value, i, j) {
    -    result.array_[i][j] = this.array_[i1 + i][j1 + j];
    -  }, this);
    -  return result;
    -};
    -
    -
    -/**
    - * Returns a new matrix equal to this one, but with row i and column j deleted.
    - * @param {number} i The row index of the coordinate.
    - * @param {number} j The column index of the coordinate.
    - * @return {!goog.math.Matrix} The value at the specified coordinate.
    - * @private
    - */
    -goog.math.Matrix.prototype.getSubmatrixByDeletion_ = function(i, j) {
    -  var m = new goog.math.Matrix(this.size_.width - 1, this.size_.height - 1);
    -  goog.math.Matrix.forEach(m, function(value, x, y) {
    -    m.setValueAt(x, y, this.array_[x >= i ? x + 1 : x][y >= j ? y + 1 : y]);
    -  }, this);
    -  return m;
    -};
    -
    -
    -/**
    - * Returns whether the given coordinates are contained within the bounds of the
    - * matrix.
    - * @param {number} i The i index of the coordinate.
    - * @param {number} j The j index of the coordinate.
    - * @return {boolean} The value at the specified coordinate.
    - * @private
    - */
    -goog.math.Matrix.prototype.isInBounds_ = function(i, j) {
    -  return i >= 0 && i < this.size_.height &&
    -         j >= 0 && j < this.size_.width;
    -};
    -
    -
    -/**
    - * Matrix multiplication is defined between two matrices only if the number of
    - * columns of the first matrix is the same as the number of rows of the second
    - * matrix. If A is an m-by-n matrix and B is an n-by-p matrix, then their
    - * product AB is an m-by-p matrix
    - *
    - * @param {goog.math.Matrix} m Matrix to multiply the matrix by.
    - * @return {!goog.math.Matrix} Resultant product.
    - * @private
    - */
    -goog.math.Matrix.prototype.matrixMultiply_ = function(m) {
    -  var resultMatrix = new goog.math.Matrix(this.size_.height, m.getSize().width);
    -  goog.math.Matrix.forEach(resultMatrix, function(val, x, y) {
    -    var newVal = 0;
    -    for (var i = 0; i < this.size_.width; i++) {
    -      newVal += this.getValueAt(x, i) * m.getValueAt(i, y);
    -    }
    -    resultMatrix.setValueAt(x, y, newVal);
    -  }, this);
    -  return resultMatrix;
    -};
    -
    -
    -/**
    - * Scalar multiplication returns a matrix of the same size as the original,
    - * each value multiplied by the given value.
    - *
    - * @param {number} m number to multiply the matrix by.
    - * @return {!goog.math.Matrix} Resultant product.
    - * @private
    - */
    -goog.math.Matrix.prototype.scalarMultiply_ = function(m) {
    -  return goog.math.Matrix.map(this, function(val, x, y) {
    -    return val * m;
    -  });
    -};
    -
    -
    -/**
    - * Swaps two rows.
    - * @param {number} i1 The index of the first row to swap.
    - * @param {number} i2 The index of the second row to swap.
    - * @private
    - */
    -goog.math.Matrix.prototype.swapRows_ = function(i1, i2) {
    -  var tmp = this.array_[i1];
    -  this.array_[i1] = this.array_[i2];
    -  this.array_[i2] = tmp;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/math/matrix_test.html b/src/database/third_party/closure-library/closure/goog/math/matrix_test.html
    deleted file mode 100644
    index 832316ebd27..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/matrix_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.math.Matrix
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.math.MatrixTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/math/matrix_test.js b/src/database/third_party/closure-library/closure/goog/math/matrix_test.js
    deleted file mode 100644
    index 181ebea4026..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/matrix_test.js
    +++ /dev/null
    @@ -1,429 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.math.MatrixTest');
    -goog.setTestOnly('goog.math.MatrixTest');
    -
    -goog.require('goog.math.Matrix');
    -goog.require('goog.testing.jsunit');
    -
    -function testConstuctorWithGoodArray() {
    -  var a1 = [[1, 2], [2, 3], [4, 5]];
    -  var m1 = new goog.math.Matrix(a1);
    -  assertArrayEquals('1. Internal array should be the same', m1.toArray(), a1);
    -  assertEquals(3, m1.getSize().height);
    -  assertEquals(2, m1.getSize().width);
    -
    -  var a2 = [[-61, 45, 123], [11112, 343, 1235]];
    -  var m2 = new goog.math.Matrix(a2);
    -  assertArrayEquals('2. Internal array should be the same', m2.toArray(), a2);
    -  assertEquals(2, m2.getSize().height);
    -  assertEquals(3, m2.getSize().width);
    -
    -  var a3 = [[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3], [4, 4, 4, 4]];
    -  var m3 = new goog.math.Matrix(a3);
    -  assertArrayEquals('3. Internal array should be the same', m3.toArray(), a3);
    -  assertEquals(4, m3.getSize().height);
    -  assertEquals(4, m3.getSize().width);
    -}
    -
    -
    -function testConstructorWithBadArray() {
    -  assertThrows('1. All arrays should be of equal length', function() {
    -    new goog.math.Matrix([[1, 2, 3], [1, 2], [1]]);
    -  });
    -
    -  assertThrows('2. All arrays should be of equal length', function() {
    -    new goog.math.Matrix([[1, 2], [1, 2], [1, 2, 3, 4]]);
    -  });
    -
    -  assertThrows('3. Arrays should contain only numeric values', function() {
    -    new goog.math.Matrix([[1, 2], [1, 2], [1, 'a']]);
    -  });
    -
    -  assertThrows('4. Arrays should contain only numeric values', function() {
    -    new goog.math.Matrix([[1, 2], [1, 2], [1, {a: 3}]]);
    -  });
    -
    -  assertThrows('5. Arrays should contain only numeric values', function() {
    -    new goog.math.Matrix([[1, 2], [1, 2], [1, [1, 2, 3]]]);
    -  });
    -}
    -
    -
    -function testConstructorWithGoodNumbers() {
    -  var m1 = new goog.math.Matrix(2, 2);
    -  assertEquals('Height should be 2', 2, m1.getSize().height);
    -  assertEquals('Width should be 2', 2, m1.getSize().width);
    -
    -  var m2 = new goog.math.Matrix(4, 2);
    -  assertEquals('Height should be 4', 4, m2.getSize().height);
    -  assertEquals('Width should be 2', 2, m2.getSize().width);
    -
    -  var m3 = new goog.math.Matrix(4, 6);
    -  assertEquals('Height should be 4', 4, m3.getSize().height);
    -  assertEquals('Width should be 6', 6, m3.getSize().width);
    -}
    -
    -
    -function testConstructorWithBadNumbers() {
    -  assertThrows('1. Negative argument should have errored', function() {
    -    new goog.math.Matrix(-4, 6);
    -  });
    -
    -  assertThrows('2. Negative argument should have errored', function() {
    -    new goog.math.Matrix(4, -6);
    -  });
    -
    -  assertThrows('3. Zero argument should have errored', function() {
    -    new goog.math.Matrix(4, 0);
    -  });
    -
    -  assertThrows('4. Zero argument should have errored', function() {
    -    new goog.math.Matrix(0, 1);
    -  });
    -}
    -
    -
    -function testConstructorWithMatrix() {
    -  var a1 = [[1, 2], [2, 3], [4, 5]];
    -  var m1 = new goog.math.Matrix(a1);
    -  var m2 = new goog.math.Matrix(m1);
    -  assertArrayEquals(
    -      'Internal arrays should be the same', m1.toArray(), m2.toArray());
    -  assertNotEquals(
    -      'Should be different objects', goog.getUid(m1), goog.getUid(m2));
    -}
    -
    -
    -function testCreateIdentityMatrix() {
    -  var m1 = goog.math.Matrix.createIdentityMatrix(3);
    -  assertArrayEquals([[1, 0, 0], [0, 1, 0], [0, 0, 1]], m1.toArray());
    -
    -  var m2 = goog.math.Matrix.createIdentityMatrix(4);
    -  assertArrayEquals(
    -      [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]], m2.toArray());
    -}
    -
    -
    -function testIsValidArrayWithGoodArrays() {
    -  var fn = goog.math.Matrix.isValidArray;
    -  assertTrue('2x2 array should be fine', fn([[1, 2], [3, 5]]));
    -  assertTrue('3x2 array should be fine', fn([[1, 2, 3], [3, 5, 6]]));
    -  assertTrue(
    -      '3x3 array should be fine', fn([[1, 2, 3], [3, 5, 6], [10, 10, 10]]));
    -  assertTrue('[[1]] should be fine', fn([[1]]));
    -  assertTrue('1D array should work', fn([[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]));
    -  assertTrue('Negs and decimals should be ok',
    -      fn([[0], [-4], [-10], [1.2345], [123.53]]));
    -  assertTrue('Hex, Es and decimals are ok', fn([[0x100, 10E-2], [1.213, 213]]));
    -}
    -
    -
    -function testIsValidArrayWithBadArrays() {
    -  var fn = goog.math.Matrix.isValidArray;
    -  assertFalse('Arrays should have same size', fn([[1, 2], [3]]));
    -  assertFalse('Arrays should have same size 2', fn([[1, 2], [3, 4, 5]]));
    -  assertFalse('2D arrays are ok', fn([[1, 2], [3, 4], []]));
    -  assertFalse('Values should be numeric', fn([[1, 2], [3, 'a']]));
    -  assertFalse('Values can not be strings', fn([['bah'], ['foo']]));
    -  assertFalse('Flat array not supported', fn([1, 2, 3, 4, 5]));
    -}
    -
    -
    -function testForEach() {
    -  var m = new goog.math.Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]);
    -  var count = 0, sum = 0, xs = '', ys = '';
    -  goog.math.Matrix.forEach(m, function(val, x, y) {
    -    count++;
    -    sum += val;
    -    xs += x;
    -    ys += y;
    -  });
    -  assertEquals('forEach should have visited every item', 9, count);
    -  assertEquals('forEach should have summed all values', 45, sum);
    -  assertEquals('Xs should have been visited in order', '000111222', xs);
    -  assertEquals('Ys should have been visited sequentially', '012012012', ys);
    -}
    -
    -
    -function testMap() {
    -  var m1 = new goog.math.Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]);
    -  var m2 = goog.math.Matrix.map(m1, function(val, x, y) {
    -    return val + 1;
    -  });
    -  assertArrayEquals([[2, 3, 4], [5, 6, 7], [8, 9, 10]], m2.toArray());
    -}
    -
    -
    -function testSetValueAt() {
    -  var m = new goog.math.Matrix(3, 3);
    -  for (var x = 0; x < 3; x++) {
    -    for (var y = 0; y < 3; y++) {
    -      m.setValueAt(x, y, 3 * x - y);
    -    }
    -  }
    -  assertArrayEquals([[0, -1, -2], [3, 2, 1], [6, 5, 4]], m.toArray());
    -}
    -
    -
    -function testGetValueAt() {
    -  var m = new goog.math.Matrix([[0, -1, -2], [3, 2, 1], [6, 5, 4]]);
    -  for (var x = 0; x < 3; x++) {
    -    for (var y = 0; y < 3; y++) {
    -      assertEquals(
    -          'Value at (x, y) should equal 3x - y',
    -          3 * x - y, m.getValueAt(x, y));
    -    }
    -  }
    -  assertNull('Out of bounds value should be null', m.getValueAt(-1, 2));
    -  assertNull('Out of bounds value should be null', m.getValueAt(-1, 0));
    -  assertNull('Out of bounds value should be null', m.getValueAt(0, 4));
    -}
    -
    -
    -function testSum1() {
    -  var m1 = new goog.math.Matrix([[1, 1, 1], [2, 2, 2], [3, 3, 3]]);
    -  var m2 = new goog.math.Matrix([[3, 3, 3], [2, 2, 2], [1, 1, 1]]);
    -  assertArrayEquals('Sum should be all the 4s',
    -      [[4, 4, 4], [4, 4, 4], [4, 4, 4]], m1.add(m2).toArray());
    -  assertArrayEquals('Addition should be commutative',
    -      m1.add(m2).toArray(), m2.add(m1).toArray());
    -}
    -
    -
    -function testSum2() {
    -  var m1 = new goog.math.Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]);
    -  var m2 = new goog.math.Matrix([[-1, -2, -3], [-4, -5, -6], [-7, -8, -9]]);
    -  assertArrayEquals('Sum should be all 0s',
    -      [[0, 0, 0], [0, 0, 0], [0, 0, 0]], m1.add(m2).toArray());
    -  assertArrayEquals('Addition should be commutative',
    -      m1.add(m2).toArray(), m2.add(m1).toArray());
    -}
    -
    -
    -function testSubtract1() {
    -  var m1 = new goog.math.Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]);
    -  var m2 = new goog.math.Matrix([[5, 5, 5], [5, 5, 5], [5, 5, 5]]);
    -
    -  assertArrayEquals([[-4, -3, -2], [-1, 0, 1], [2, 3, 4]],
    -                    m1.subtract(m2).toArray());
    -  assertArrayEquals([[4, 3, 2], [1, 0, -1], [-2, -3, -4]],
    -                    m2.subtract(m1).toArray());
    -}
    -
    -
    -function testSubtract2() {
    -  var m1 = new goog.math.Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]);
    -  var m2 = new goog.math.Matrix([[-1, -2, -3], [-4, -5, -6], [-7, -8, -9]]);
    -  assertArrayEquals([[2, 4, 6], [8, 10, 12], [14, 16, 18]],
    -                    m1.subtract(m2).toArray());
    -  assertArrayEquals([[-2, -4, -6], [-8, -10, -12], [-14, -16, -18]],
    -                    m2.subtract(m1).toArray());
    -}
    -
    -
    -function testScalarMultiplication() {
    -  var m1 = new goog.math.Matrix([[1, 1, 1], [2, 2, 2], [3, 3, 3]]);
    -  assertArrayEquals(
    -      [[2, 2, 2], [4, 4, 4], [6, 6, 6]], m1.multiply(2).toArray());
    -  assertArrayEquals(
    -      [[3, 3, 3], [6, 6, 6], [9, 9, 9]], m1.multiply(3).toArray());
    -  assertArrayEquals(
    -      [[4, 4, 4], [8, 8, 8], [12, 12, 12]], m1.multiply(4).toArray());
    -
    -  var m2 = new goog.math.Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]);
    -  assertArrayEquals(
    -      [[2, 4, 6], [8, 10, 12], [14, 16, 18]], m2.multiply(2).toArray());
    -}
    -
    -
    -function testMatrixMultiplication() {
    -  var m1 = new goog.math.Matrix([[1, 2], [3, 4]]);
    -  var m2 = new goog.math.Matrix([[3, 4], [5, 6]]);
    -  // m1 * m2
    -  assertArrayEquals([[1 * 3 + 2 * 5, 1 * 4 + 2 * 6],
    -                     [3 * 3 + 4 * 5, 3 * 4 + 4 * 6]],
    -                    m1.multiply(m2).toArray());
    -  // m2 * m1 != m1 * m2
    -  assertArrayEquals([[3 * 1 + 4 * 3, 3 * 2 + 4 * 4],
    -                     [5 * 1 + 6 * 3, 5 * 2 + 6 * 4]],
    -                    m2.multiply(m1).toArray());
    -  var m3 = new goog.math.Matrix([[1, 2, 3, 4],
    -                                 [5, 6, 7, 8]]);
    -  var m4 = new goog.math.Matrix([[1, 2, 3],
    -                                 [4, 5, 6],
    -                                 [7, 8, 9],
    -                                 [10, 11, 12]]);
    -  // m3 * m4
    -  assertArrayEquals([[1 * 1 + 2 * 4 + 3 * 7 + 4 * 10,
    -                      1 * 2 + 2 * 5 + 3 * 8 + 4 * 11,
    -                      1 * 3 + 2 * 6 + 3 * 9 + 4 * 12],
    -  [5 * 1 + 6 * 4 + 7 * 7 + 8 * 10,
    -   5 * 2 + 6 * 5 + 7 * 8 + 8 * 11,
    -   5 * 3 + 6 * 6 + 7 * 9 + 8 * 12]],
    -  m3.multiply(m4).toArray());
    -  assertThrows('Matrix dimensions should not line up.',
    -               function() { m4.multiply(m3); });
    -}
    -
    -function testMatrixMultiplicationIsAssociative() {
    -  var A = new goog.math.Matrix([[1, 2], [3, 4]]);
    -  var B = new goog.math.Matrix([[3, 4], [5, 6]]);
    -  var C = new goog.math.Matrix([[2, 7], [9, 1]]);
    -
    -  assertArrayEquals('A(BC) == (AB)C',
    -                    A.multiply(B.multiply(C)).toArray(),
    -                    A.multiply(B).multiply(C).toArray());
    -}
    -
    -
    -function testMatrixMultiplicationIsDistributive() {
    -  var A = new goog.math.Matrix([[1, 2], [3, 4]]);
    -  var B = new goog.math.Matrix([[3, 4], [5, 6]]);
    -  var C = new goog.math.Matrix([[2, 7], [9, 1]]);
    -
    -  assertArrayEquals('A(B + C) = AB + AC',
    -                    A.multiply(B.add(C)).toArray(),
    -                    A.multiply(B).add(A.multiply(C)).toArray());
    -
    -  assertArrayEquals('(A + B)C = AC + BC',
    -                    A.add(B).multiply(C).toArray(),
    -                    A.multiply(C).add(B.multiply(C)).toArray());
    -}
    -
    -
    -function testTranspose() {
    -  var m = new goog.math.Matrix([[1, 3, 1], [0, -6, 0]]);
    -  var t = [[1, 0], [3, -6], [1, 0]];
    -  assertArrayEquals(t, m.getTranspose().toArray());
    -}
    -
    -
    -function testAppendColumns() {
    -  var m = new goog.math.Matrix([[1, 3, 2], [2, 0, 1], [5, 2, 2]]);
    -  var b = new goog.math.Matrix([[4], [3], [1]]);
    -  var result = [[1, 3, 2, 4], [2, 0, 1, 3], [5, 2, 2, 1]];
    -  assertArrayEquals(result, m.appendColumns(b).toArray());
    -}
    -
    -
    -function testAppendRows() {
    -  var m = new goog.math.Matrix([[1, 3, 2], [2, 0, 1], [5, 2, 2]]);
    -  var b = new goog.math.Matrix([[4, 3, 1]]);
    -  var result = [[1, 3, 2], [2, 0, 1], [5, 2, 2], [4, 3, 1]];
    -  assertArrayEquals(result, m.appendRows(b).toArray());
    -}
    -
    -
    -function testSubmatrixByDeletion() {
    -  var m = new goog.math.Matrix([[1, 2, 3, 4], [5, 6, 7, 8],
    -        [9, 10, 11, 12], [13, 14, 15, 16]]);
    -  var arr = [[1, 2, 3], [5, 6, 7], [13, 14, 15]];
    -  assertArrayEquals(arr, m.getSubmatrixByDeletion_(2, 3).toArray());
    -}
    -
    -
    -function testMinor() {
    -  var m = new goog.math.Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]);
    -  assertEquals(-3, m.getMinor_(0, 0));
    -}
    -
    -
    -function testCofactor() {
    -  var m = new goog.math.Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]);
    -  assertEquals(6, m.getCofactor_(0, 1));
    -}
    -
    -
    -function testDeterminantForOneByOneMatrix() {
    -  var m = new goog.math.Matrix([[3]]);
    -  assertEquals(3, m.getDeterminant());
    -}
    -
    -
    -function testDeterminant() {
    -  var m = new goog.math.Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]);
    -  assertEquals(0, m.getDeterminant());
    -}
    -
    -
    -function testGetSubmatrix() {
    -  var m = new goog.math.Matrix([[2, -1, 0, 1, 0, 0],
    -                                [-1, 2, -1, 0, 1, 0],
    -                                [0, -1, 2, 0, 0, 1]]);
    -  var sub1 = [[2, -1, 0], [-1, 2, -1], [0, -1, 2]];
    -  assertArrayEquals(sub1,
    -                    m.getSubmatrixByCoordinates_(0, 0, 2, 2).toArray());
    -
    -  var sub2 = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
    -  assertArrayEquals(sub2, m.getSubmatrixByCoordinates_(0, 3).toArray());
    -}
    -
    -
    -function testGetReducedRowEchelonForm() {
    -  var m = new goog.math.Matrix([[2, -1, 0, 1, 0, 0],
    -                                [-1, 2, -1, 0, 1, 0],
    -                                [0, -1, 2, 0, 0, 1]]);
    -
    -  var expected = new goog.math.Matrix([[1, 0, 0, .75, .5, .25],
    -                                       [0, 1, 0, .5, 1, .5],
    -                                       [0, 0, 1, .25, .5, .75]]);
    -
    -  assertTrue(expected.equals(m.getReducedRowEchelonForm()));
    -}
    -
    -
    -function testInverse() {
    -  var m1 = new goog.math.Matrix([[2, -1, 0],
    -                                 [-1, 2, -1],
    -                                 [0, -1, 2]]);
    -  var expected1 = new goog.math.Matrix([[.75, .5, .25],
    -                                        [.5, 1, .5],
    -                                        [.25, .5, .75]]);
    -  assertTrue(expected1.equals(m1.getInverse()));
    -
    -  var m2 = new goog.math.Matrix([[4, 8],
    -                                 [7, -2]]);
    -  var expected2 = new goog.math.Matrix([[.03125, .125],
    -                                        [.10936, -.0625]]);
    -  assertTrue(expected2.equals(m2.getInverse(), .0001));
    -  var m3 = new goog.math.Matrix([[0, 0],
    -                                 [0, 0]]);
    -  assertNull(m3.getInverse());
    -  var m4 = new goog.math.Matrix([[2]]);
    -  var expected4 = new goog.math.Matrix([[.5]]);
    -  assertTrue(expected4.equals(m4.getInverse(), .0001));
    -  var m5 = new goog.math.Matrix([[0]]);
    -  assertNull(m5.getInverse());
    -}
    -
    -
    -function testEquals() {
    -  var a1 = new goog.math.Matrix([[1, 0, 0, .75, .5, .25],
    -                                 [0, 1, 0, .5, 1, .5],
    -                                 [0, 0, 1, .25, .5, .75]]);
    -
    -  var a2 = new goog.math.Matrix([[1, 0, 0, .75, .5, .25],
    -                                 [0, 1, 0, .5, 1, .5],
    -                                 [0, 0, 1, .25, .5, .75]]);
    -
    -  var a3 = new goog.math.Matrix([[1, 0, 0, .749, .5, .25],
    -                                 [0, 1, 0, .5, 1, .5],
    -                                 [0, 0, 1, .25, .5, .75]]);
    -
    -  assertTrue(a1.equals(a2));
    -  assertTrue(a1.equals(a3, .01));
    -  assertFalse(a1.equals(a3, .001));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/math/path.js b/src/database/third_party/closure-library/closure/goog/math/path.js
    deleted file mode 100644
    index 3eae7b0bf20..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/path.js
    +++ /dev/null
    @@ -1,598 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Represents a path used with a Graphics implementation.
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -goog.provide('goog.math.Path');
    -goog.provide('goog.math.Path.Segment');
    -
    -goog.require('goog.array');
    -goog.require('goog.math');
    -
    -
    -
    -/**
    - * Creates a path object. A path is a sequence of segments and may be open or
    - * closed. Path uses the EVEN-ODD fill rule for determining the interior of the
    - * path. A path must start with a moveTo command.
    - *
    - * A "simple" path does not contain any arcs and may be transformed using
    - * the {@code transform} method.
    - *
    - * @struct
    - * @constructor
    - * @final
    - */
    -goog.math.Path = function() {
    -  /**
    -   * The segment types that constitute this path.
    -   * @private {!Array<goog.math.Path.Segment>}
    -   */
    -  this.segments_ = [];
    -
    -  /**
    -   * The number of repeated segments of the current type.
    -   * @type {!Array<number>}
    -   * @private
    -   */
    -  this.count_ = [];
    -
    -  /**
    -   * The arguments corresponding to each of the segments.
    -   * @type {!Array<number>}
    -   * @private
    -   */
    -  this.arguments_ = [];
    -
    -  /**
    -   * The coordinates of the point which closes the path (the point of the
    -   * last moveTo command).
    -   * @type {Array<number>?}
    -   * @private
    -   */
    -  this.closePoint_ = null;
    -
    -  /**
    -   * The coordinates most recently added to the end of the path.
    -   * @type {Array<number>?}
    -   * @private
    -   */
    -  this.currentPoint_ = null;
    -
    -  /**
    -   * Flag for whether this is a simple path (contains no arc segments).
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.simple_ = true;
    -};
    -
    -
    -/**
    - * Path segment types.
    - * @enum {number}
    - */
    -goog.math.Path.Segment = {
    -  MOVETO: 0,
    -  LINETO: 1,
    -  CURVETO: 2,
    -  ARCTO: 3,
    -  CLOSE: 4
    -};
    -
    -
    -/**
    - * The number of points for each segment type.
    - * @type {!Array<number>}
    - * @private
    - */
    -goog.math.Path.segmentArgCounts_ = (function() {
    -  var counts = [];
    -  counts[goog.math.Path.Segment.MOVETO] = 2;
    -  counts[goog.math.Path.Segment.LINETO] = 2;
    -  counts[goog.math.Path.Segment.CURVETO] = 6;
    -  counts[goog.math.Path.Segment.ARCTO] = 6;
    -  counts[goog.math.Path.Segment.CLOSE] = 0;
    -  return counts;
    -})();
    -
    -
    -/**
    - * Returns an array of the segment types in this path, in the order of their
    - * appearance. Adjacent segments of the same type are collapsed into a single
    - * entry in the array. The returned array is a copy; modifications are not
    - * reflected in the Path object.
    - * @return {!Array<number>}
    - */
    -goog.math.Path.prototype.getSegmentTypes = function() {
    -  return this.segments_.concat();
    -};
    -
    -
    -/**
    - * Returns an array of the number of times each segment type repeats in this
    - * path, in order. The returned array is a copy; modifications are not reflected
    - * in the Path object.
    - * @return {!Array<number>}
    - */
    -goog.math.Path.prototype.getSegmentCounts = function() {
    -  return this.count_.concat();
    -};
    -
    -
    -/**
    - * Returns an array of all arguments for the segments of this path object, in
    - * order. The returned array is a copy; modifications are not reflected in the
    - * Path object.
    - * @return {!Array<number>}
    - */
    -goog.math.Path.prototype.getSegmentArgs = function() {
    -  return this.arguments_.concat();
    -};
    -
    -
    -/**
    - * Returns the number of points for a segment type.
    - *
    - * @param {number} segment The segment type.
    - * @return {number} The number of points.
    - */
    -goog.math.Path.getSegmentCount = function(segment) {
    -  return goog.math.Path.segmentArgCounts_[segment];
    -};
    -
    -
    -/**
    - * Appends another path to the end of this path.
    - *
    - * @param {!goog.math.Path} path The path to append.
    - * @return {!goog.math.Path} This path.
    - */
    -goog.math.Path.prototype.appendPath = function(path) {
    -  if (path.currentPoint_) {
    -    Array.prototype.push.apply(this.segments_, path.segments_);
    -    Array.prototype.push.apply(this.count_, path.count_);
    -    Array.prototype.push.apply(this.arguments_, path.arguments_);
    -    this.currentPoint_ = path.currentPoint_.concat();
    -    this.closePoint_ = path.closePoint_.concat();
    -    this.simple_ = this.simple_ && path.simple_;
    -  }
    -  return this;
    -};
    -
    -
    -/**
    - * Clears the path.
    - *
    - * @return {!goog.math.Path} The path itself.
    - */
    -goog.math.Path.prototype.clear = function() {
    -  this.segments_.length = 0;
    -  this.count_.length = 0;
    -  this.arguments_.length = 0;
    -  this.closePoint_ = null;
    -  this.currentPoint_ = null;
    -  this.simple_ = true;
    -  return this;
    -};
    -
    -
    -/**
    - * Adds a point to the path by moving to the specified point. Repeated moveTo
    - * commands are collapsed into a single moveTo.
    - *
    - * @param {number} x X coordinate of destination point.
    - * @param {number} y Y coordinate of destination point.
    - * @return {!goog.math.Path} The path itself.
    - */
    -goog.math.Path.prototype.moveTo = function(x, y) {
    -  if (goog.array.peek(this.segments_) == goog.math.Path.Segment.MOVETO) {
    -    this.arguments_.length -= 2;
    -  } else {
    -    this.segments_.push(goog.math.Path.Segment.MOVETO);
    -    this.count_.push(1);
    -  }
    -  this.arguments_.push(x, y);
    -  this.currentPoint_ = this.closePoint_ = [x, y];
    -  return this;
    -};
    -
    -
    -/**
    - * Adds points to the path by drawing a straight line to each point.
    - *
    - * @param {...number} var_args The coordinates of each destination point as x, y
    - *     value pairs.
    - * @return {!goog.math.Path} The path itself.
    - */
    -goog.math.Path.prototype.lineTo = function(var_args) {
    -  return this.lineTo_(arguments);
    -};
    -
    -
    -/**
    - * Adds points to the path by drawing a straight line to each point.
    - *
    - * @param {!Array<number>} coordinates The coordinates of each
    - *     destination point as x, y value pairs.
    - * @return {!goog.math.Path} The path itself.
    - */
    -goog.math.Path.prototype.lineToFromArray = function(coordinates) {
    -  return this.lineTo_(coordinates);
    -};
    -
    -
    -/**
    - * Adds points to the path by drawing a straight line to each point.
    - *
    - * @param {!Array<number>|Arguments} coordinates The coordinates of each
    - *     destination point as x, y value pairs.
    - * @return {!goog.math.Path} The path itself.
    - * @private
    - */
    -goog.math.Path.prototype.lineTo_ = function(coordinates) {
    -  var lastSegment = goog.array.peek(this.segments_);
    -  if (lastSegment == null) {
    -    throw Error('Path cannot start with lineTo');
    -  }
    -  if (lastSegment != goog.math.Path.Segment.LINETO) {
    -    this.segments_.push(goog.math.Path.Segment.LINETO);
    -    this.count_.push(0);
    -  }
    -  for (var i = 0; i < coordinates.length; i += 2) {
    -    var x = coordinates[i];
    -    var y = coordinates[i + 1];
    -    this.arguments_.push(x, y);
    -  }
    -  this.count_[this.count_.length - 1] += i / 2;
    -  this.currentPoint_ = [x, y];
    -  return this;
    -};
    -
    -
    -/**
    - * Adds points to the path by drawing cubic Bezier curves. Each curve is
    - * specified using 3 points (6 coordinates) - two control points and the end
    - * point of the curve.
    - *
    - * @param {...number} var_args The coordinates specifiying each curve in sets of
    - *     6 points: {@code [x1, y1]} the first control point, {@code [x2, y2]} the
    - *     second control point and {@code [x, y]} the end point.
    - * @return {!goog.math.Path} The path itself.
    - */
    -goog.math.Path.prototype.curveTo = function(var_args) {
    -  return this.curveTo_(arguments);
    -};
    -
    -
    -/**
    - * Adds points to the path by drawing cubic Bezier curves. Each curve is
    - * specified using 3 points (6 coordinates) - two control points and the end
    - * point of the curve.
    - *
    - * @param {!Array<number>} coordinates The coordinates specifiying
    - *     each curve in sets of 6 points: {@code [x1, y1]} the first control point,
    - *     {@code [x2, y2]} the second control point and {@code [x, y]} the end
    - *     point.
    - * @return {!goog.math.Path} The path itself.
    - */
    -goog.math.Path.prototype.curveToFromArray = function(coordinates) {
    -  return this.curveTo_(coordinates);
    -};
    -
    -
    -/**
    - * Adds points to the path by drawing cubic Bezier curves. Each curve is
    - * specified using 3 points (6 coordinates) - two control points and the end
    - * point of the curve.
    - *
    - * @param {!Array<number>|Arguments} coordinates The coordinates specifiying
    - *     each curve in sets of 6 points: {@code [x1, y1]} the first control point,
    - *     {@code [x2, y2]} the second control point and {@code [x, y]} the end
    - *     point.
    - * @return {!goog.math.Path} The path itself.
    - * @private
    - */
    -goog.math.Path.prototype.curveTo_ = function(coordinates) {
    -  var lastSegment = goog.array.peek(this.segments_);
    -  if (lastSegment == null) {
    -    throw Error('Path cannot start with curve');
    -  }
    -  if (lastSegment != goog.math.Path.Segment.CURVETO) {
    -    this.segments_.push(goog.math.Path.Segment.CURVETO);
    -    this.count_.push(0);
    -  }
    -  for (var i = 0; i < coordinates.length; i += 6) {
    -    var x = coordinates[i + 4];
    -    var y = coordinates[i + 5];
    -    this.arguments_.push(coordinates[i], coordinates[i + 1],
    -        coordinates[i + 2], coordinates[i + 3], x, y);
    -  }
    -  this.count_[this.count_.length - 1] += i / 6;
    -  this.currentPoint_ = [x, y];
    -  return this;
    -};
    -
    -
    -/**
    - * Adds a path command to close the path by connecting the
    - * last point to the first point.
    - *
    - * @return {!goog.math.Path} The path itself.
    - */
    -goog.math.Path.prototype.close = function() {
    -  var lastSegment = goog.array.peek(this.segments_);
    -  if (lastSegment == null) {
    -    throw Error('Path cannot start with close');
    -  }
    -  if (lastSegment != goog.math.Path.Segment.CLOSE) {
    -    this.segments_.push(goog.math.Path.Segment.CLOSE);
    -    this.count_.push(1);
    -    this.currentPoint_ = this.closePoint_;
    -  }
    -  return this;
    -};
    -
    -
    -/**
    - * Adds a path command to draw an arc centered at the point {@code (cx, cy)}
    - * with radius {@code rx} along the x-axis and {@code ry} along the y-axis from
    - * {@code startAngle} through {@code extent} degrees. Positive rotation is in
    - * the direction from positive x-axis to positive y-axis.
    - *
    - * @param {number} cx X coordinate of center of ellipse.
    - * @param {number} cy Y coordinate of center of ellipse.
    - * @param {number} rx Radius of ellipse on x axis.
    - * @param {number} ry Radius of ellipse on y axis.
    - * @param {number} fromAngle Starting angle measured in degrees from the
    - *     positive x-axis.
    - * @param {number} extent The span of the arc in degrees.
    - * @param {boolean} connect If true, the starting point of the arc is connected
    - *     to the current point.
    - * @return {!goog.math.Path} The path itself.
    - * @deprecated Use {@code arcTo} or {@code arcToAsCurves} instead.
    - */
    -goog.math.Path.prototype.arc = function(cx, cy, rx, ry,
    -    fromAngle, extent, connect) {
    -  var startX = cx + goog.math.angleDx(fromAngle, rx);
    -  var startY = cy + goog.math.angleDy(fromAngle, ry);
    -  if (connect) {
    -    if (!this.currentPoint_ || startX != this.currentPoint_[0] ||
    -        startY != this.currentPoint_[1]) {
    -      this.lineTo(startX, startY);
    -    }
    -  } else {
    -    this.moveTo(startX, startY);
    -  }
    -  return this.arcTo(rx, ry, fromAngle, extent);
    -};
    -
    -
    -/**
    - * Adds a path command to draw an arc starting at the path's current point,
    - * with radius {@code rx} along the x-axis and {@code ry} along the y-axis from
    - * {@code startAngle} through {@code extent} degrees. Positive rotation is in
    - * the direction from positive x-axis to positive y-axis.
    - *
    - * This method makes the path non-simple.
    - *
    - * @param {number} rx Radius of ellipse on x axis.
    - * @param {number} ry Radius of ellipse on y axis.
    - * @param {number} fromAngle Starting angle measured in degrees from the
    - *     positive x-axis.
    - * @param {number} extent The span of the arc in degrees.
    - * @return {!goog.math.Path} The path itself.
    - */
    -goog.math.Path.prototype.arcTo = function(rx, ry, fromAngle, extent) {
    -  var cx = this.currentPoint_[0] - goog.math.angleDx(fromAngle, rx);
    -  var cy = this.currentPoint_[1] - goog.math.angleDy(fromAngle, ry);
    -  var ex = cx + goog.math.angleDx(fromAngle + extent, rx);
    -  var ey = cy + goog.math.angleDy(fromAngle + extent, ry);
    -  this.segments_.push(goog.math.Path.Segment.ARCTO);
    -  this.count_.push(1);
    -  this.arguments_.push(rx, ry, fromAngle, extent, ex, ey);
    -  this.simple_ = false;
    -  this.currentPoint_ = [ex, ey];
    -  return this;
    -};
    -
    -
    -/**
    - * Same as {@code arcTo}, but approximates the arc using bezier curves.
    -.* As a result, this method does not affect the simplified status of this path.
    - * The algorithm is adapted from {@code java.awt.geom.ArcIterator}.
    - *
    - * @param {number} rx Radius of ellipse on x axis.
    - * @param {number} ry Radius of ellipse on y axis.
    - * @param {number} fromAngle Starting angle measured in degrees from the
    - *     positive x-axis.
    - * @param {number} extent The span of the arc in degrees.
    - * @return {!goog.math.Path} The path itself.
    - */
    -goog.math.Path.prototype.arcToAsCurves = function(
    -    rx, ry, fromAngle, extent) {
    -  var cx = this.currentPoint_[0] - goog.math.angleDx(fromAngle, rx);
    -  var cy = this.currentPoint_[1] - goog.math.angleDy(fromAngle, ry);
    -  var extentRad = goog.math.toRadians(extent);
    -  var arcSegs = Math.ceil(Math.abs(extentRad) / Math.PI * 2);
    -  var inc = extentRad / arcSegs;
    -  var angle = goog.math.toRadians(fromAngle);
    -  for (var j = 0; j < arcSegs; j++) {
    -    var relX = Math.cos(angle);
    -    var relY = Math.sin(angle);
    -    var z = 4 / 3 * Math.sin(inc / 2) / (1 + Math.cos(inc / 2));
    -    var c0 = cx + (relX - z * relY) * rx;
    -    var c1 = cy + (relY + z * relX) * ry;
    -    angle += inc;
    -    relX = Math.cos(angle);
    -    relY = Math.sin(angle);
    -    this.curveTo(c0, c1,
    -        cx + (relX + z * relY) * rx,
    -        cy + (relY - z * relX) * ry,
    -        cx + relX * rx,
    -        cy + relY * ry);
    -  }
    -  return this;
    -};
    -
    -
    -/**
    - * Iterates over the path calling the supplied callback once for each path
    - * segment. The arguments to the callback function are the segment type and
    - * an array of its arguments.
    - *
    - * The {@code LINETO} and {@code CURVETO} arrays can contain multiple
    - * segments of the same type. The number of segments is the length of the
    - * array divided by the segment length (2 for lines, 6 for  curves).
    - *
    - * As a convenience the {@code ARCTO} segment also includes the end point as the
    - * last two arguments: {@code rx, ry, fromAngle, extent, x, y}.
    - *
    - * @param {function(!goog.math.Path.Segment, !Array<number>)} callback
    - *     The function to call with each path segment.
    - */
    -goog.math.Path.prototype.forEachSegment = function(callback) {
    -  var points = this.arguments_;
    -  var index = 0;
    -  for (var i = 0, length = this.segments_.length; i < length; i++) {
    -    var seg = this.segments_[i];
    -    var n = goog.math.Path.segmentArgCounts_[seg] * this.count_[i];
    -    callback(seg, points.slice(index, index + n));
    -    index += n;
    -  }
    -};
    -
    -
    -/**
    - * Returns the coordinates most recently added to the end of the path.
    - *
    - * @return {Array<number>?} An array containing the ending coordinates of the
    - *     path of the form {@code [x, y]}.
    - */
    -goog.math.Path.prototype.getCurrentPoint = function() {
    -  return this.currentPoint_ && this.currentPoint_.concat();
    -};
    -
    -
    -/**
    - * @return {!goog.math.Path} A copy of this path.
    - */
    -goog.math.Path.prototype.clone = function() {
    -  var path = new goog.math.Path();
    -  path.segments_ = this.segments_.concat();
    -  path.count_ = this.count_.concat();
    -  path.arguments_ = this.arguments_.concat();
    -  path.closePoint_ = this.closePoint_ && this.closePoint_.concat();
    -  path.currentPoint_ = this.currentPoint_ && this.currentPoint_.concat();
    -  path.simple_ = this.simple_;
    -  return path;
    -};
    -
    -
    -/**
    - * Returns true if this path contains no arcs. Simplified paths can be
    - * created using {@code createSimplifiedPath}.
    - *
    - * @return {boolean} True if the path contains no arcs.
    - */
    -goog.math.Path.prototype.isSimple = function() {
    -  return this.simple_;
    -};
    -
    -
    -/**
    - * A map from segment type to the path function to call to simplify a path.
    - * @private {!Object<goog.math.Path.Segment, function(this: goog.math.Path)>}
    - */
    -goog.math.Path.simplifySegmentMap_ = (function() {
    -  var map = {};
    -  map[goog.math.Path.Segment.MOVETO] = goog.math.Path.prototype.moveTo;
    -  map[goog.math.Path.Segment.LINETO] = goog.math.Path.prototype.lineTo;
    -  map[goog.math.Path.Segment.CLOSE] = goog.math.Path.prototype.close;
    -  map[goog.math.Path.Segment.CURVETO] =
    -      goog.math.Path.prototype.curveTo;
    -  map[goog.math.Path.Segment.ARCTO] =
    -      goog.math.Path.prototype.arcToAsCurves;
    -  return map;
    -})();
    -
    -
    -/**
    - * Creates a copy of the given path, replacing {@code arcTo} with
    - * {@code arcToAsCurves}. The resulting path is simplified and can
    - * be transformed.
    - *
    - * @param {!goog.math.Path} src The path to simplify.
    - * @return {!goog.math.Path} A new simplified path.
    - */
    -goog.math.Path.createSimplifiedPath = function(src) {
    -  if (src.isSimple()) {
    -    return src.clone();
    -  }
    -  var path = new goog.math.Path();
    -  src.forEachSegment(function(segment, args) {
    -    goog.math.Path.simplifySegmentMap_[segment].apply(path, args);
    -  });
    -  return path;
    -};
    -
    -
    -// TODO(chrisn): Delete this method
    -/**
    - * Creates a transformed copy of this path. The path is simplified
    - * {@see #createSimplifiedPath} prior to transformation.
    - *
    - * @param {!goog.math.AffineTransform} tx The transformation to perform.
    - * @return {!goog.math.Path} A new, transformed path.
    - */
    -goog.math.Path.prototype.createTransformedPath = function(tx) {
    -  var path = goog.math.Path.createSimplifiedPath(this);
    -  path.transform(tx);
    -  return path;
    -};
    -
    -
    -/**
    - * Transforms the path. Only simple paths are transformable. Attempting
    - * to transform a non-simple path will throw an error.
    - *
    - * @param {!goog.math.AffineTransform} tx The transformation to perform.
    - * @return {!goog.math.Path} The path itself.
    - */
    -goog.math.Path.prototype.transform = function(tx) {
    -  if (!this.isSimple()) {
    -    throw Error('Non-simple path');
    -  }
    -  tx.transform(this.arguments_, 0, this.arguments_, 0,
    -      this.arguments_.length / 2);
    -  if (this.closePoint_) {
    -    tx.transform(this.closePoint_, 0, this.closePoint_, 0, 1);
    -  }
    -  if (this.currentPoint_ && this.closePoint_ != this.currentPoint_) {
    -    tx.transform(this.currentPoint_, 0, this.currentPoint_, 0, 1);
    -  }
    -  return this;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the path is empty.
    - */
    -goog.math.Path.prototype.isEmpty = function() {
    -  return this.segments_.length == 0;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/math/path_test.html b/src/database/third_party/closure-library/closure/goog/math/path_test.html
    deleted file mode 100644
    index 9370915c525..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/path_test.html
    +++ /dev/null
    @@ -1,19 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.math.Path</title>
    -<script src="../base.js"></script>
    -<script>
    -goog.require('goog.math.PathTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/math/path_test.js b/src/database/third_party/closure-library/closure/goog/math/path_test.js
    deleted file mode 100644
    index 830f5d9dd9e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/path_test.js
    +++ /dev/null
    @@ -1,518 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.math.PathTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.math.AffineTransform');
    -goog.require('goog.math.Path');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.math.PathTest');
    -
    -
    -/**
    - * Array mapping numeric segment constant to a descriptive character.
    - * @type {!Array<string>}
    - * @private
    - */
    -var SEGMENT_NAMES_ = function() {
    -  var arr = [];
    -  arr[goog.math.Path.Segment.MOVETO] = 'M';
    -  arr[goog.math.Path.Segment.LINETO] = 'L';
    -  arr[goog.math.Path.Segment.CURVETO] = 'C';
    -  arr[goog.math.Path.Segment.ARCTO] = 'A';
    -  arr[goog.math.Path.Segment.CLOSE] = 'X';
    -  return arr;
    -}();
    -
    -
    -/**
    - * Test if the given path matches the expected array of commands and parameters.
    - * @param {Array<string|number>} expected The expected array of commands and
    - *     parameters.
    - * @param {goog.math.Path} path The path to test against.
    - */
    -var assertPathEquals = function(expected, path) {
    -  var actual = [];
    -  path.forEachSegment(function(seg, args) {
    -    actual.push(SEGMENT_NAMES_[seg]);
    -    Array.prototype.push.apply(actual, args);
    -  });
    -  assertEquals(expected.length, actual.length);
    -  for (var i = 0; i < expected.length; i++) {
    -    if (goog.isNumber(expected[i])) {
    -      assertTrue(goog.isNumber(actual[i]));
    -      assertRoughlyEquals(expected[i], actual[i], 0.01);
    -    } else {
    -      assertEquals(expected[i], actual[i]);
    -    }
    -  }
    -};
    -
    -
    -function testConstructor() {
    -  var path = new goog.math.Path();
    -  assertTrue(path.isSimple());
    -  assertNull(path.getCurrentPoint());
    -  assertPathEquals([], path);
    -}
    -
    -
    -function testGetSegmentCount() {
    -  assertArrayEquals([2, 2, 6, 6, 0], goog.array.map([
    -    goog.math.Path.Segment.MOVETO,
    -    goog.math.Path.Segment.LINETO,
    -    goog.math.Path.Segment.CURVETO,
    -    goog.math.Path.Segment.ARCTO,
    -    goog.math.Path.Segment.CLOSE
    -  ], goog.math.Path.getSegmentCount));
    -}
    -
    -
    -function testSimpleMoveTo() {
    -  var path = new goog.math.Path();
    -  path.moveTo(30, 50);
    -  assertTrue(path.isSimple());
    -  assertObjectEquals([30, 50], path.getCurrentPoint());
    -  assertPathEquals(['M', 30, 50], path);
    -}
    -
    -
    -function testRepeatedMoveTo() {
    -  var path = new goog.math.Path();
    -  path.moveTo(30, 50);
    -  path.moveTo(40, 60);
    -  assertTrue(path.isSimple());
    -  assertObjectEquals([40, 60], path.getCurrentPoint());
    -  assertPathEquals(['M', 40, 60], path);
    -}
    -
    -
    -function testSimpleLineTo_fromArgs() {
    -  var path = new goog.math.Path();
    -  var e = assertThrows(function() {
    -    path.lineTo(30, 50);
    -  });
    -  assertEquals('Path cannot start with lineTo', e.message);
    -  path.moveTo(0, 0);
    -  path.lineTo(30, 50);
    -  assertTrue(path.isSimple());
    -  assertObjectEquals([30, 50], path.getCurrentPoint());
    -  assertPathEquals(['M', 0, 0, 'L', 30, 50], path);
    -}
    -
    -
    -function testSimpleLineTo_fromArray() {
    -  var path = new goog.math.Path();
    -  var e = assertThrows(function() {
    -    path.lineToFromArray([30, 50]);
    -  });
    -  assertEquals('Path cannot start with lineTo', e.message);
    -  path.moveTo(0, 0);
    -  path.lineToFromArray([30, 50]);
    -  assertTrue(path.isSimple());
    -  assertObjectEquals([30, 50], path.getCurrentPoint());
    -  assertPathEquals(['M', 0, 0, 'L', 30, 50], path);
    -}
    -
    -
    -function testMultiArgLineTo_fromArgs() {
    -  var path = new goog.math.Path();
    -  path.moveTo(0, 0);
    -  path.lineTo(30, 50, 40 , 60);
    -  assertTrue(path.isSimple());
    -  assertObjectEquals([40, 60], path.getCurrentPoint());
    -  assertPathEquals(['M', 0, 0, 'L', 30, 50, 40, 60], path);
    -}
    -
    -
    -function testMultiArgLineTo_fromArray() {
    -  var path = new goog.math.Path();
    -  path.moveTo(0, 0);
    -  path.lineToFromArray([30, 50, 40 , 60]);
    -  assertTrue(path.isSimple());
    -  assertObjectEquals([40, 60], path.getCurrentPoint());
    -  assertPathEquals(['M', 0, 0, 'L', 30, 50, 40, 60], path);
    -}
    -
    -
    -function testRepeatedLineTo_fromArgs() {
    -  var path = new goog.math.Path();
    -  path.moveTo(0, 0);
    -  path.lineTo(30, 50);
    -  path.lineTo(40, 60);
    -  assertTrue(path.isSimple());
    -  assertObjectEquals([40, 60], path.getCurrentPoint());
    -  assertPathEquals(['M', 0, 0, 'L', 30, 50, 40, 60], path);
    -}
    -
    -
    -function testRepeatedLineTo_fromArray() {
    -  var path = new goog.math.Path();
    -  path.moveTo(0, 0);
    -  path.lineToFromArray([30, 50]);
    -  path.lineToFromArray([40, 60]);
    -  assertTrue(path.isSimple());
    -  assertObjectEquals([40, 60], path.getCurrentPoint());
    -  assertPathEquals(['M', 0, 0, 'L', 30, 50, 40, 60], path);
    -}
    -
    -
    -function testSimpleCurveTo_fromArgs() {
    -  var path = new goog.math.Path();
    -  var e = assertThrows(function() {
    -    path.curveTo(10, 20, 30, 40, 50, 60);
    -  });
    -  assertEquals('Path cannot start with curve', e.message);
    -  path.moveTo(0, 0);
    -  path.curveTo(10, 20, 30, 40, 50, 60);
    -  assertTrue(path.isSimple());
    -  assertObjectEquals([50, 60], path.getCurrentPoint());
    -  assertPathEquals(['M', 0, 0, 'C', 10, 20, 30, 40, 50, 60], path);
    -}
    -
    -
    -function testSimpleCurveTo_fromArray() {
    -  var path = new goog.math.Path();
    -  var e = assertThrows(function() {
    -    path.curveToFromArray([10, 20, 30, 40, 50, 60]);
    -  });
    -  assertEquals('Path cannot start with curve', e.message);
    -  path.moveTo(0, 0);
    -  path.curveToFromArray([10, 20, 30, 40, 50, 60]);
    -  assertTrue(path.isSimple());
    -  assertObjectEquals([50, 60], path.getCurrentPoint());
    -  assertPathEquals(['M', 0, 0, 'C', 10, 20, 30, 40, 50, 60], path);
    -}
    -
    -
    -function testMultiCurveTo_fromArgs() {
    -  var path = new goog.math.Path();
    -  path.moveTo(0, 0);
    -  path.curveTo(10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120);
    -  assertTrue(path.isSimple());
    -  assertObjectEquals([110, 120], path.getCurrentPoint());
    -  assertPathEquals(
    -      ['M', 0, 0, 'C', 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120],
    -      path);
    -}
    -
    -
    -function testMultiCurveTo_fromArray() {
    -  var path = new goog.math.Path();
    -  path.moveTo(0, 0);
    -  path.curveToFromArray([10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120]);
    -  assertTrue(path.isSimple());
    -  assertObjectEquals([110, 120], path.getCurrentPoint());
    -  assertPathEquals(
    -      ['M', 0, 0, 'C', 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120],
    -      path);
    -}
    -
    -
    -function testRepeatedCurveTo_fromArgs() {
    -  var path = new goog.math.Path();
    -  path.moveTo(0, 0);
    -  path.curveTo(10, 20, 30, 40, 50, 60);
    -  path.curveTo(70, 80, 90, 100, 110, 120);
    -  assertTrue(path.isSimple());
    -  assertObjectEquals([110, 120], path.getCurrentPoint());
    -  assertPathEquals(
    -      ['M', 0, 0, 'C', 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120],
    -      path);
    -}
    -
    -
    -function testRepeatedCurveTo_fromArray() {
    -  var path = new goog.math.Path();
    -  path.moveTo(0, 0);
    -  path.curveToFromArray([10, 20, 30, 40, 50, 60]);
    -  path.curveToFromArray([70, 80, 90, 100, 110, 120]);
    -  assertTrue(path.isSimple());
    -  assertObjectEquals([110, 120], path.getCurrentPoint());
    -  assertPathEquals(
    -      ['M', 0, 0, 'C', 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120],
    -      path);
    -}
    -
    -
    -function testSimpleArc() {
    -  var path = new goog.math.Path();
    -  path.arc(50, 60, 10, 20, 30, 30, false);
    -  assertFalse(path.isSimple());
    -  var p = path.getCurrentPoint();
    -  assertEquals(55, p[0]);
    -  assertRoughlyEquals(77.32, p[1], 0.01);
    -  assertPathEquals(
    -      ['M', 58.66, 70, 'A', 10, 20, 30, 30, 55, 77.32], path);
    -}
    -
    -
    -function testArcNonConnectClose() {
    -  var path = new goog.math.Path();
    -  path.moveTo(0, 0);
    -  path.arc(10, 10, 10, 10, -90, 180, false);
    -  assertObjectEquals([10, 20], path.getCurrentPoint());
    -  path.close();
    -  assertObjectEquals([10, 0], path.getCurrentPoint());
    -}
    -
    -
    -function testRepeatedArc() {
    -  var path = new goog.math.Path();
    -  path.arc(50, 60, 10, 20, 30, 30, false);
    -  path.arc(50, 60, 10, 20, 60, 30, false);
    -  assertFalse(path.isSimple());
    -  assertObjectEquals([50, 80], path.getCurrentPoint());
    -  assertPathEquals(['M', 58.66, 70,
    -    'A', 10, 20, 30, 30, 55, 77.32,
    -    'M', 55, 77.32,
    -    'A', 10, 20, 60, 30, 50, 80], path);
    -}
    -
    -
    -function testRepeatedArc2() {
    -  var path = new goog.math.Path();
    -  path.arc(50, 60, 10, 20, 30, 30, false);
    -  path.arc(50, 60, 10, 20, 60, 30, true);
    -  assertPathEquals(['M', 58.66, 70,
    -    'A', 10, 20, 30, 30, 55, 77.32,
    -    'A', 10, 20, 60, 30, 50, 80], path);
    -}
    -
    -
    -function testCompleteCircle() {
    -  var path = new goog.math.Path();
    -  path.arc(0, 0, 10, 10, 0, 360, false);
    -  assertFalse(path.isSimple());
    -  var p = path.getCurrentPoint();
    -  assertRoughlyEquals(10, p[0], 0.01);
    -  assertRoughlyEquals(0, p[1], 0.01);
    -  assertPathEquals(
    -      ['M', 10, 0, 'A', 10, 10, 0, 360, 10, 0], path);
    -}
    -
    -
    -function testClose() {
    -  var path = new goog.math.Path();
    -  assertThrows('Path cannot start with close',
    -      function() {
    -        path.close();
    -      });
    -
    -  path.moveTo(0, 0);
    -  path.lineTo(10, 20, 30, 40, 50, 60);
    -  path.close();
    -  assertTrue(path.isSimple());
    -  assertObjectEquals([0, 0], path.getCurrentPoint());
    -  assertPathEquals(
    -      ['M', 0, 0, 'L', 10, 20, 30, 40, 50, 60, 'X'], path);
    -}
    -
    -
    -function testClear() {
    -  var path = new goog.math.Path();
    -  path.moveTo(0, 0);
    -  path.arc(50, 60, 10, 20, 30, 30, false);
    -  path.clear();
    -  assertTrue(path.isSimple());
    -  assertNull(path.getCurrentPoint());
    -  assertPathEquals([], path);
    -}
    -
    -
    -function testCreateSimplifiedPath() {
    -  var path = new goog.math.Path();
    -  path.moveTo(0, 0);
    -  path.arc(50, 60, 10, 20, 30, 30, false);
    -  assertFalse(path.isSimple());
    -  path = goog.math.Path.createSimplifiedPath(path);
    -  assertTrue(path.isSimple());
    -  var p = path.getCurrentPoint();
    -  assertEquals(55, p[0]);
    -  assertRoughlyEquals(77.32, p[1], 0.01);
    -  assertPathEquals(['M', 58.66, 70,
    -    'C', 57.78, 73.04, 56.52, 75.57, 55, 77.32], path);
    -}
    -
    -
    -function testCreateSimplifiedPath2() {
    -  var path = new goog.math.Path();
    -  path.arc(50, 60, 10, 20, 30, 30, false);
    -  path.arc(50, 60, 10, 20, 60, 30, false);
    -  assertFalse(path.isSimple());
    -  path = goog.math.Path.createSimplifiedPath(path);
    -  assertTrue(path.isSimple());
    -  assertPathEquals(['M', 58.66, 70,
    -    'C', 57.78, 73.04, 56.52, 75.57, 55, 77.32,
    -    'M', 55, 77.32,
    -    'C', 53.48, 79.08, 51.76, 80, 50, 80], path);
    -}
    -
    -
    -function testCreateSimplifiedPath3() {
    -  var path = new goog.math.Path();
    -  path.arc(50, 60, 10, 20, 30, 30, false);
    -  path.arc(50, 60, 10, 20, 60, 30, true);
    -  path.close();
    -  path = goog.math.Path.createSimplifiedPath(path);
    -  assertPathEquals(['M', 58.66, 70,
    -    'C', 57.78, 73.04, 56.52, 75.57, 55, 77.32,
    -    53.48, 79.08, 51.76, 80, 50, 80, 'X'], path);
    -  var p = path.getCurrentPoint();
    -  assertRoughlyEquals(58.66, p[0], 0.01);
    -  assertRoughlyEquals(70, p[1], 0.01);
    -}
    -
    -
    -function testArcToAsCurves() {
    -  var path = new goog.math.Path();
    -  path.moveTo(58.66, 70);
    -  path.arcToAsCurves(10, 20, 30, 30);
    -  assertPathEquals(['M', 58.66, 70,
    -    'C', 57.78, 73.04, 56.52, 75.57, 55, 77.32], path);
    -}
    -
    -
    -function testCreateTransformedPath() {
    -  var path = new goog.math.Path();
    -  path.moveTo(0, 0);
    -  path.lineTo(0, 10, 10, 10, 10, 0);
    -  path.close();
    -  var tx = new goog.math.AffineTransform(2, 0, 0, 3, 10, 20);
    -  var path2 = path.createTransformedPath(tx);
    -  assertPathEquals(
    -      ['M', 0, 0, 'L', 0, 10, 10, 10, 10, 0, 'X'], path);
    -  assertPathEquals(
    -      ['M', 10, 20, 'L', 10, 50, 30, 50, 30, 20, 'X'], path2);
    -}
    -
    -
    -function testTransform() {
    -  var path = new goog.math.Path();
    -  path.moveTo(0, 0);
    -  path.lineTo(0, 10, 10, 10, 10, 0);
    -  path.close();
    -  var tx = new goog.math.AffineTransform(2, 0, 0, 3, 10, 20);
    -  var path2 = path.transform(tx);
    -  assertTrue(path === path2);
    -  assertPathEquals(
    -      ['M', 10, 20, 'L', 10, 50, 30, 50, 30, 20, 'X'], path2);
    -}
    -
    -
    -function testTransformCurrentAndClosePoints() {
    -  var path = new goog.math.Path();
    -  path.moveTo(0, 0);
    -  assertObjectEquals([0, 0], path.getCurrentPoint());
    -  path.transform(new goog.math.AffineTransform(1, 0, 0, 1, 10, 20));
    -  assertObjectEquals([10, 20], path.getCurrentPoint());
    -  path.lineTo(50, 50);
    -  path.close();
    -  assertObjectEquals([10, 20], path.getCurrentPoint());
    -}
    -
    -
    -function testTransformNonSimple() {
    -  var path = new goog.math.Path();
    -  path.arc(50, 60, 10, 20, 30, 30, false);
    -  assertThrows(function() {
    -    path.transform(new goog.math.AffineTransform(1, 0, 0, 1, 10, 20));
    -  });
    -}
    -
    -
    -function testAppendPath() {
    -  var path1 = new goog.math.Path();
    -  path1.moveTo(0, 0);
    -  path1.lineTo(0, 10, 10, 10, 10, 0);
    -  path1.close();
    -
    -  var path2 = new goog.math.Path();
    -  path2.arc(50, 60, 10, 20, 30, 30, false);
    -
    -  assertTrue(path1.isSimple());
    -  path1.appendPath(path2);
    -  assertFalse(path1.isSimple());
    -  assertPathEquals([
    -    'M', 0, 0, 'L', 0, 10, 10, 10, 10, 0, 'X',
    -    'M', 58.66, 70, 'A', 10, 20, 30, 30, 55, 77.32
    -  ], path1);
    -}
    -
    -
    -function testIsEmpty() {
    -  var path = new goog.math.Path();
    -  assertTrue('Initially path is empty', path.isEmpty());
    -
    -  path.moveTo(0, 0);
    -  assertFalse('After command addition, path is not empty', path.isEmpty());
    -
    -  path.clear();
    -  assertTrue('After clear, path is empty again', path.isEmpty());
    -}
    -
    -
    -function testGetSegmentTypes() {
    -  var path = new goog.math.Path();
    -  path.moveTo(0, 0);
    -  path.lineTo(10, 20, 30, 40);
    -  path.close();
    -
    -  var Segment = goog.math.Path.Segment;
    -  var segmentTypes = path.getSegmentTypes();
    -  assertArrayEquals(
    -      'The returned segment types do not match the expected values',
    -      [Segment.MOVETO, Segment.LINETO, Segment.CLOSE], segmentTypes);
    -
    -  segmentTypes[2] = Segment.LINETO;
    -  assertArrayEquals('Modifying the returned segment types changed the path',
    -      [Segment.MOVETO, Segment.LINETO, Segment.CLOSE], path.getSegmentTypes());
    -}
    -
    -
    -function testGetSegmentCounts() {
    -  var path = new goog.math.Path();
    -  path.moveTo(0, 0);
    -  path.lineTo(10, 20, 30, 40);
    -  path.close();
    -
    -  var segmentTypes = path.getSegmentCounts();
    -  assertArrayEquals(
    -      'The returned segment counts do not match the expected values',
    -      [1, 2, 1], segmentTypes);
    -
    -  segmentTypes[1] = 3;
    -  assertArrayEquals('Modifying the returned segment counts changed the path',
    -      [1, 2, 1], path.getSegmentCounts());
    -}
    -
    -
    -function testGetSegmentArgs() {
    -  var path = new goog.math.Path();
    -  path.moveTo(0, 0);
    -  path.lineTo(10, 20, 30, 40);
    -  path.close();
    -
    -  var segmentTypes = path.getSegmentArgs();
    -  assertArrayEquals(
    -      'The returned segment args do not match the expected values',
    -      [0, 0, 10, 20, 30, 40], segmentTypes);
    -
    -  segmentTypes[1] = -10;
    -  assertArrayEquals(
    -      'Modifying the returned segment args changed the path',
    -      [0, 0, 10, 20, 30, 40], path.getSegmentArgs());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/math/paths.js b/src/database/third_party/closure-library/closure/goog/math/paths.js
    deleted file mode 100644
    index 26c740bbcde..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/paths.js
    +++ /dev/null
    @@ -1,86 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Factories for common path types.
    - * @author nicksantos@google.com (Nick Santos)
    - */
    -
    -
    -goog.provide('goog.math.paths');
    -
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.math.Path');
    -
    -
    -/**
    - * Defines a regular n-gon by specifing the center, a vertex, and the total
    - * number of vertices.
    - * @param {goog.math.Coordinate} center The center point.
    - * @param {goog.math.Coordinate} vertex The vertex, which implicitly defines
    - *     a radius as well.
    - * @param {number} n The number of vertices.
    - * @return {!goog.math.Path} The path.
    - */
    -goog.math.paths.createRegularNGon = function(center, vertex, n) {
    -  var path = new goog.math.Path();
    -  path.moveTo(vertex.x, vertex.y);
    -
    -  var startAngle = Math.atan2(vertex.y - center.y, vertex.x - center.x);
    -  var radius = goog.math.Coordinate.distance(center, vertex);
    -  for (var i = 1; i < n; i++) {
    -    var angle = startAngle + 2 * Math.PI * (i / n);
    -    path.lineTo(center.x + radius * Math.cos(angle),
    -                center.y + radius * Math.sin(angle));
    -  }
    -  path.close();
    -  return path;
    -};
    -
    -
    -/**
    - * Defines an arrow.
    - * @param {goog.math.Coordinate} a Point A.
    - * @param {goog.math.Coordinate} b Point B.
    - * @param {?number} aHead The size of the arrow head at point A.
    - *     0 omits the head.
    - * @param {?number} bHead The size of the arrow head at point B.
    - *     0 omits the head.
    - * @return {!goog.math.Path} The path.
    - */
    -goog.math.paths.createArrow = function(a, b, aHead, bHead) {
    -  var path = new goog.math.Path();
    -  path.moveTo(a.x, a.y);
    -  path.lineTo(b.x, b.y);
    -
    -  var angle = Math.atan2(b.y - a.y, b.x - a.x);
    -  if (aHead) {
    -    path.appendPath(
    -        goog.math.paths.createRegularNGon(
    -            new goog.math.Coordinate(
    -                a.x + aHead * Math.cos(angle),
    -                a.y + aHead * Math.sin(angle)),
    -            a, 3));
    -  }
    -  if (bHead) {
    -    path.appendPath(
    -        goog.math.paths.createRegularNGon(
    -            new goog.math.Coordinate(
    -                b.x + bHead * Math.cos(angle + Math.PI),
    -                b.y + bHead * Math.sin(angle + Math.PI)),
    -            b, 3));
    -  }
    -  return path;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/math/paths_test.html b/src/database/third_party/closure-library/closure/goog/math/paths_test.html
    deleted file mode 100644
    index 3cbc159ff50..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/paths_test.html
    +++ /dev/null
    @@ -1,21 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    -Author: nicksantos@google.com (Nick Santos)
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>JsUnit tests for goog.math.paths</title>
    -<script src="../base.js"></script>
    -<script>
    -goog.require('goog.math.pathsTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/math/paths_test.js b/src/database/third_party/closure-library/closure/goog/math/paths_test.js
    deleted file mode 100644
    index 2f8baf30c04..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/paths_test.js
    +++ /dev/null
    @@ -1,50 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.math.paths.
    - */
    -
    -goog.provide('goog.math.pathsTest');
    -
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.math.paths');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.math.pathsTest');
    -
    -
    -var regularNGon = goog.math.paths.createRegularNGon;
    -var arrow = goog.math.paths.createArrow;
    -
    -function testSquare() {
    -  var square = regularNGon(
    -      $coord(10, 10), $coord(0, 10), 4);
    -  assertArrayRoughlyEquals(
    -      [0, 10, 10, 0, 20, 10, 10, 20], square.arguments_, 0.05);
    -}
    -
    -function assertArrayRoughlyEquals(expected, actual, delta) {
    -  var message = 'Expected: ' + expected + ', Actual: ' + actual;
    -  assertEquals('Wrong length. ' + message, expected.length, actual.length);
    -  for (var i = 0; i < expected.length; i++) {
    -    assertRoughlyEquals(
    -        'Wrong item at ' + i + '. ' + message,
    -        expected[i], actual[i], delta);
    -  }
    -}
    -
    -function $coord(x, y) {
    -  return new goog.math.Coordinate(x, y);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/math/range.js b/src/database/third_party/closure-library/closure/goog/math/range.js
    deleted file mode 100644
    index 5812bffe1a5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/range.js
    +++ /dev/null
    @@ -1,186 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A utility class for representing a numeric range.
    - */
    -
    -
    -goog.provide('goog.math.Range');
    -
    -goog.require('goog.asserts');
    -
    -
    -
    -/**
    - * A number range.
    - * @param {number} a One end of the range.
    - * @param {number} b The other end of the range.
    - * @struct
    - * @constructor
    - */
    -goog.math.Range = function(a, b) {
    -  /**
    -   * The lowest value in the range.
    -   * @type {number}
    -   */
    -  this.start = a < b ? a : b;
    -
    -  /**
    -   * The highest value in the range.
    -   * @type {number}
    -   */
    -  this.end = a < b ? b : a;
    -};
    -
    -
    -/**
    - * Creates a goog.math.Range from an array of two numbers.
    - * @param {!Array<number>} pair
    - * @return {!goog.math.Range}
    - */
    -goog.math.Range.fromPair = function(pair) {
    -  goog.asserts.assert(pair.length == 2);
    -  return new goog.math.Range(pair[0], pair[1]);
    -};
    -
    -
    -/**
    - * @return {!goog.math.Range} A clone of this Range.
    - */
    -goog.math.Range.prototype.clone = function() {
    -  return new goog.math.Range(this.start, this.end);
    -};
    -
    -
    -/**
    - * @return {number} Length of the range.
    - */
    -goog.math.Range.prototype.getLength = function() {
    -  return this.end - this.start;
    -};
    -
    -
    -/**
    - * Extends this range to include the given point.
    - * @param {number} point
    - */
    -goog.math.Range.prototype.includePoint = function(point) {
    -  this.start = Math.min(this.start, point);
    -  this.end = Math.max(this.end, point);
    -};
    -
    -
    -/**
    - * Extends this range to include the given range.
    - * @param {!goog.math.Range} range
    - */
    -goog.math.Range.prototype.includeRange = function(range) {
    -  this.start = Math.min(this.start, range.start);
    -  this.end = Math.max(this.end, range.end);
    -};
    -
    -
    -if (goog.DEBUG) {
    -  /**
    -   * Returns a string representing the range.
    -   * @return {string} In the form [-3.5, 8.13].
    -   * @override
    -   */
    -  goog.math.Range.prototype.toString = function() {
    -    return '[' + this.start + ', ' + this.end + ']';
    -  };
    -}
    -
    -
    -/**
    - * Compares ranges for equality.
    - * @param {goog.math.Range} a A Range.
    - * @param {goog.math.Range} b A Range.
    - * @return {boolean} True iff both the starts and the ends of the ranges are
    - *     equal, or if both ranges are null.
    - */
    -goog.math.Range.equals = function(a, b) {
    -  if (a == b) {
    -    return true;
    -  }
    -  if (!a || !b) {
    -    return false;
    -  }
    -  return a.start == b.start && a.end == b.end;
    -};
    -
    -
    -/**
    - * Given two ranges on the same dimension, this method returns the intersection
    - * of those ranges.
    - * @param {goog.math.Range} a A Range.
    - * @param {goog.math.Range} b A Range.
    - * @return {goog.math.Range} A new Range representing the intersection of two
    - *     ranges, or null if there is no intersection. Ranges are assumed to
    - *     include their end points, and the intersection can be a point.
    - */
    -goog.math.Range.intersection = function(a, b) {
    -  var c0 = Math.max(a.start, b.start);
    -  var c1 = Math.min(a.end, b.end);
    -  return (c0 <= c1) ? new goog.math.Range(c0, c1) : null;
    -};
    -
    -
    -/**
    - * Given two ranges on the same dimension, determines whether they intersect.
    - * @param {goog.math.Range} a A Range.
    - * @param {goog.math.Range} b A Range.
    - * @return {boolean} Whether they intersect.
    - */
    -goog.math.Range.hasIntersection = function(a, b) {
    -  return Math.max(a.start, b.start) <= Math.min(a.end, b.end);
    -};
    -
    -
    -/**
    - * Given two ranges on the same dimension, this returns a range that covers
    - * both ranges.
    - * @param {goog.math.Range} a A Range.
    - * @param {goog.math.Range} b A Range.
    - * @return {!goog.math.Range} A new Range representing the bounding
    - *     range.
    - */
    -goog.math.Range.boundingRange = function(a, b) {
    -  return new goog.math.Range(Math.min(a.start, b.start),
    -                             Math.max(a.end, b.end));
    -};
    -
    -
    -/**
    - * Given two ranges, returns true if the first range completely overlaps the
    - * second.
    - * @param {goog.math.Range} a The first Range.
    - * @param {goog.math.Range} b The second Range.
    - * @return {boolean} True if b is contained inside a, false otherwise.
    - */
    -goog.math.Range.contains = function(a, b) {
    -  return a.start <= b.start && a.end >= b.end;
    -};
    -
    -
    -/**
    - * Given a range and a point, returns true if the range contains the point.
    - * @param {goog.math.Range} range The range.
    - * @param {number} p The point.
    - * @return {boolean} True if p is contained inside range, false otherwise.
    - */
    -goog.math.Range.containsPoint = function(range, p) {
    -  return range.start <= p && range.end >= p;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/math/range_test.html b/src/database/third_party/closure-library/closure/goog/math/range_test.html
    deleted file mode 100644
    index 3f1c925fc05..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/range_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.math.Range
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.math.RangeTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/math/range_test.js b/src/database/third_party/closure-library/closure/goog/math/range_test.js
    deleted file mode 100644
    index ba771bc880e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/range_test.js
    +++ /dev/null
    @@ -1,142 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.math.RangeTest');
    -goog.setTestOnly('goog.math.RangeTest');
    -
    -goog.require('goog.math.Range');
    -goog.require('goog.testing.jsunit');
    -
    -
    -/**
    - * Produce legible assertion results. If two ranges are not equal, the error
    - * message will be of the form
    - * "Expected <[1, 2]> (Object) but was <[3, 4]> (Object)"
    - */
    -function assertRangesEqual(expected, actual) {
    -  if (!goog.math.Range.equals(expected, actual)) {
    -    assertEquals(expected, actual);
    -  }
    -}
    -
    -function createRange(a) {
    -  return a ? new goog.math.Range(a[0], a[1]) : null;
    -}
    -
    -function testFromPair() {
    -  var range = goog.math.Range.fromPair([1, 2]);
    -  assertEquals(1, range.start);
    -  assertEquals(2, range.end);
    -  range = goog.math.Range.fromPair([2, 1]);
    -  assertEquals(1, range.start);
    -  assertEquals(2, range.end);
    -}
    -
    -function testRangeIntersection() {
    -  var tests = [[[1, 2], [3, 4], null],
    -               [[1, 3], [2, 4], [2, 3]],
    -               [[1, 4], [2, 3], [2, 3]],
    -               [[-1, 2], [-1, 2], [-1, 2]],
    -               [[1, 2], [2, 3], [2, 2]],
    -               [[1, 1], [1, 1], [1, 1]]];
    -  for (var i = 0; i < tests.length; ++i) {
    -    var t = tests[i];
    -    var r0 = createRange(t[0]);
    -    var r1 = createRange(t[1]);
    -    var expected = createRange(t[2]);
    -    assertRangesEqual(expected, goog.math.Range.intersection(r0, r1));
    -    assertRangesEqual(expected, goog.math.Range.intersection(r1, r0));
    -
    -    assertEquals(expected != null, goog.math.Range.hasIntersection(r0, r1));
    -    assertEquals(expected != null, goog.math.Range.hasIntersection(r1, r0));
    -  }
    -}
    -
    -function testBoundingRange() {
    -  var tests = [[[1, 2], [3, 4], [1, 4]],
    -               [[1, 3], [2, 4], [1, 4]],
    -               [[1, 4], [2, 3], [1, 4]],
    -               [[-1, 2], [-1, 2], [-1, 2]],
    -               [[1, 2], [2, 3], [1, 3]],
    -               [[1, 1], [1, 1], [1, 1]]];
    -  for (var i = 0; i < tests.length; ++i) {
    -    var t = tests[i];
    -    var r0 = createRange(t[0]);
    -    var r1 = createRange(t[1]);
    -    var expected = createRange(t[2]);
    -    assertRangesEqual(expected, goog.math.Range.boundingRange(r0, r1));
    -    assertRangesEqual(expected, goog.math.Range.boundingRange(r1, r0));
    -  }
    -}
    -
    -function testRangeContains() {
    -  var tests = [[[0, 4], [2, 1], true],
    -               [[-4, -1], [-2, -3], true],
    -               [[1, 3], [2, 4], false],
    -               [[-1, 0], [0, 1], false],
    -               [[0, 2], [3, 5], false]];
    -  for (var i = 0; i < tests.length; ++i) {
    -    var t = tests[i];
    -    var r0 = createRange(t[0]);
    -    var r1 = createRange(t[1]);
    -    var expected = t[2];
    -    assertEquals(expected, goog.math.Range.contains(r0, r1));
    -  }
    -}
    -
    -function testRangeClone() {
    -  var r = new goog.math.Range(5.6, -3.4);
    -  assertRangesEqual(r, r.clone());
    -}
    -
    -function testGetLength() {
    -  assertEquals(2, new goog.math.Range(1, 3).getLength());
    -  assertEquals(2, new goog.math.Range(3, 1).getLength());
    -}
    -
    -function testRangeContainsPoint() {
    -  var r = new goog.math.Range(0, 1);
    -  assert(goog.math.Range.containsPoint(r, 0));
    -  assert(goog.math.Range.containsPoint(r, 1));
    -  assertFalse(goog.math.Range.containsPoint(r, -1));
    -  assertFalse(goog.math.Range.containsPoint(r, 2));
    -}
    -
    -function testIncludePoint() {
    -  var r = new goog.math.Range(0, 2);
    -  r.includePoint(0);
    -  assertObjectEquals(new goog.math.Range(0, 2), r);
    -  r.includePoint(1);
    -  assertObjectEquals(new goog.math.Range(0, 2), r);
    -  r.includePoint(2);
    -  assertObjectEquals(new goog.math.Range(0, 2), r);
    -  r.includePoint(-1);
    -  assertObjectEquals(new goog.math.Range(-1, 2), r);
    -  r.includePoint(3);
    -  assertObjectEquals(new goog.math.Range(-1, 3), r);
    -}
    -
    -function testIncludeRange() {
    -  var r = new goog.math.Range(0, 4);
    -  r.includeRange(r);
    -  assertObjectEquals(new goog.math.Range(0, 4), r);
    -  r.includeRange(new goog.math.Range(1, 3));
    -  assertObjectEquals(new goog.math.Range(0, 4), r);
    -  r.includeRange(new goog.math.Range(-1, 2));
    -  assertObjectEquals(new goog.math.Range(-1, 4), r);
    -  r.includeRange(new goog.math.Range(2, 5));
    -  assertObjectEquals(new goog.math.Range(-1, 5), r);
    -  r.includeRange(new goog.math.Range(-2, 6));
    -  assertObjectEquals(new goog.math.Range(-2, 6), r);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/math/rangeset.js b/src/database/third_party/closure-library/closure/goog/math/rangeset.js
    deleted file mode 100644
    index b21138825d9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/rangeset.js
    +++ /dev/null
    @@ -1,396 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A RangeSet is a structure that manages a list of ranges.
    - * Numeric ranges may be added and removed from the RangeSet, and the set may
    - * be queried for the presence or absence of individual values or ranges of
    - * values.
    - *
    - * This may be used, for example, to track the availability of sparse elements
    - * in an array without iterating over the entire array.
    - *
    - * @author brenneman@google.com (Shawn Brenneman)
    - */
    -
    -goog.provide('goog.math.RangeSet');
    -
    -goog.require('goog.array');
    -goog.require('goog.iter.Iterator');
    -goog.require('goog.iter.StopIteration');
    -goog.require('goog.math.Range');
    -
    -
    -
    -/**
    - * Constructs a new RangeSet, which can store numeric ranges.
    - *
    - * Ranges are treated as half-closed: that is, they are exclusive of their end
    - * value [start, end).
    - *
    - * New ranges added to the set which overlap the values in one or more existing
    - * ranges will be merged.
    - *
    - * @struct
    - * @constructor
    - * @final
    - */
    -goog.math.RangeSet = function() {
    -  /**
    -   * A sorted list of ranges that represent the values in the set.
    -   * @type {!Array<!goog.math.Range>}
    -   * @private
    -   */
    -  this.ranges_ = [];
    -};
    -
    -
    -if (goog.DEBUG) {
    -  /**
    -   * @return {string} A debug string in the form [[1, 5], [8, 9], [15, 30]].
    -   * @override
    -   */
    -  goog.math.RangeSet.prototype.toString = function() {
    -    return '[' + this.ranges_.join(', ') + ']';
    -  };
    -}
    -
    -
    -/**
    - * Compares two sets for equality.
    - *
    - * @param {goog.math.RangeSet} a A range set.
    - * @param {goog.math.RangeSet} b A range set.
    - * @return {boolean} Whether both sets contain the same values.
    - */
    -goog.math.RangeSet.equals = function(a, b) {
    -  // Fast check for object equality. Also succeeds if a and b are both null.
    -  return a == b || !!(a && b && goog.array.equals(a.ranges_, b.ranges_,
    -      goog.math.Range.equals));
    -};
    -
    -
    -/**
    - * @return {!goog.math.RangeSet} A new RangeSet containing the same values as
    - *      this one.
    - */
    -goog.math.RangeSet.prototype.clone = function() {
    -  var set = new goog.math.RangeSet();
    -
    -  for (var i = this.ranges_.length; i--;) {
    -    set.ranges_[i] = this.ranges_[i].clone();
    -  }
    -
    -  return set;
    -};
    -
    -
    -/**
    - * Adds a range to the set. If the new range overlaps existing values, those
    - * ranges will be merged.
    - *
    - * @param {goog.math.Range} a The range to add.
    - */
    -goog.math.RangeSet.prototype.add = function(a) {
    -  if (a.end <= a.start) {
    -    // Empty ranges are ignored.
    -    return;
    -  }
    -
    -  a = a.clone();
    -
    -  // Find the insertion point.
    -  for (var i = 0, b; b = this.ranges_[i]; i++) {
    -    if (a.start <= b.end) {
    -      a.start = Math.min(a.start, b.start);
    -      break;
    -    }
    -  }
    -
    -  var insertionPoint = i;
    -
    -  for (; b = this.ranges_[i]; i++) {
    -    if (a.end < b.start) {
    -      break;
    -    }
    -    a.end = Math.max(a.end, b.end);
    -  }
    -
    -  this.ranges_.splice(insertionPoint, i - insertionPoint, a);
    -};
    -
    -
    -/**
    - * Removes a range of values from the set.
    - *
    - * @param {goog.math.Range} a The range to remove.
    - */
    -goog.math.RangeSet.prototype.remove = function(a) {
    -  if (a.end <= a.start) {
    -    // Empty ranges are ignored.
    -    return;
    -  }
    -
    -  // Find the insertion point.
    -  for (var i = 0, b; b = this.ranges_[i]; i++) {
    -    if (a.start < b.end) {
    -      break;
    -    }
    -  }
    -
    -  if (!b || a.end < b.start) {
    -    // The range being removed doesn't overlap any existing range. Exit early.
    -    return;
    -  }
    -
    -  var insertionPoint = i;
    -
    -  if (a.start > b.start) {
    -    // There is an overlap with the nearest range. Modify it accordingly.
    -    insertionPoint++;
    -
    -    if (a.end < b.end) {
    -      goog.array.insertAt(this.ranges_,
    -                          new goog.math.Range(a.end, b.end),
    -                          insertionPoint);
    -    }
    -    b.end = a.start;
    -  }
    -
    -  for (i = insertionPoint; b = this.ranges_[i]; i++) {
    -    b.start = Math.max(a.end, b.start);
    -    if (a.end < b.end) {
    -      break;
    -    }
    -  }
    -
    -  this.ranges_.splice(insertionPoint, i - insertionPoint);
    -};
    -
    -
    -/**
    - * Determines whether a given range is in the set. Only succeeds if the entire
    - * range is available.
    - *
    - * @param {goog.math.Range} a The query range.
    - * @return {boolean} Whether the entire requested range is set.
    - */
    -goog.math.RangeSet.prototype.contains = function(a) {
    -  if (a.end <= a.start) {
    -    return false;
    -  }
    -
    -  for (var i = 0, b; b = this.ranges_[i]; i++) {
    -    if (a.start < b.end) {
    -      if (a.end >= b.start) {
    -        return goog.math.Range.contains(b, a);
    -      }
    -      break;
    -    }
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Determines whether a given value is set in the RangeSet.
    - *
    - * @param {number} value The value to test.
    - * @return {boolean} Whether the given value is in the set.
    - */
    -goog.math.RangeSet.prototype.containsValue = function(value) {
    -  for (var i = 0, b; b = this.ranges_[i]; i++) {
    -    if (value < b.end) {
    -      if (value >= b.start) {
    -        return true;
    -      }
    -      break;
    -    }
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Returns the union of this RangeSet with another.
    - *
    - * @param {goog.math.RangeSet} set Another RangeSet.
    - * @return {!goog.math.RangeSet} A new RangeSet containing all values from
    - *     either set.
    - */
    -goog.math.RangeSet.prototype.union = function(set) {
    -  // TODO(brenneman): A linear-time merge would be preferable if it is ever a
    -  // bottleneck.
    -  set = set.clone();
    -
    -  for (var i = 0, a; a = this.ranges_[i]; i++) {
    -    set.add(a);
    -  }
    -
    -  return set;
    -};
    -
    -
    -/**
    - * Subtracts the ranges of another set from this one, returning the result
    - * as a new RangeSet.
    - *
    - * @param {!goog.math.RangeSet} set The RangeSet to subtract.
    - * @return {!goog.math.RangeSet} A new RangeSet containing all values in this
    - *     set minus the values of the input set.
    - */
    -goog.math.RangeSet.prototype.difference = function(set) {
    -  var ret = this.clone();
    -
    -  for (var i = 0, a; a = set.ranges_[i]; i++) {
    -    ret.remove(a);
    -  }
    -
    -  return ret;
    -};
    -
    -
    -/**
    - * Intersects this RangeSet with another.
    - *
    - * @param {goog.math.RangeSet} set The RangeSet to intersect with.
    - * @return {!goog.math.RangeSet} A new RangeSet containing all values set in
    - *     both this and the input set.
    - */
    -goog.math.RangeSet.prototype.intersection = function(set) {
    -  if (this.isEmpty() || set.isEmpty()) {
    -    return new goog.math.RangeSet();
    -  }
    -
    -  return this.difference(set.inverse(this.getBounds()));
    -};
    -
    -
    -/**
    - * Creates a subset of this set over the input range.
    - *
    - * @param {goog.math.Range} range The range to copy into the slice.
    - * @return {!goog.math.RangeSet} A new RangeSet with a copy of the values in the
    - *     input range.
    - */
    -goog.math.RangeSet.prototype.slice = function(range) {
    -  var set = new goog.math.RangeSet();
    -  if (range.start >= range.end) {
    -    return set;
    -  }
    -
    -  for (var i = 0, b; b = this.ranges_[i]; i++) {
    -    if (b.end <= range.start) {
    -      continue;
    -    }
    -    if (b.start > range.end) {
    -      break;
    -    }
    -
    -    set.add(new goog.math.Range(Math.max(range.start, b.start),
    -                                Math.min(range.end, b.end)));
    -  }
    -
    -  return set;
    -};
    -
    -
    -/**
    - * Creates an inverted slice of this set over the input range.
    - *
    - * @param {goog.math.Range} range The range to copy into the slice.
    - * @return {!goog.math.RangeSet} A new RangeSet containing inverted values from
    - *     the original over the input range.
    - */
    -goog.math.RangeSet.prototype.inverse = function(range) {
    -  var set = new goog.math.RangeSet();
    -
    -  set.add(range);
    -  for (var i = 0, b; b = this.ranges_[i]; i++) {
    -    if (range.start >= b.end) {
    -      continue;
    -    }
    -    if (range.end < b.start) {
    -      break;
    -    }
    -
    -    set.remove(b);
    -  }
    -
    -  return set;
    -};
    -
    -
    -/**
    - * @return {number} The sum of the lengths of ranges covered in the set.
    - */
    -goog.math.RangeSet.prototype.coveredLength = function() {
    -  return /** @type {number} */ (goog.array.reduce(
    -      this.ranges_,
    -      function(res, range) {
    -        return res + range.end - range.start;
    -      }, 0));
    -};
    -
    -
    -/**
    - * @return {goog.math.Range} The total range this set covers, ignoring any
    - *     gaps between ranges.
    - */
    -goog.math.RangeSet.prototype.getBounds = function() {
    -  if (this.ranges_.length) {
    -    return new goog.math.Range(this.ranges_[0].start,
    -                               goog.array.peek(this.ranges_).end);
    -  }
    -
    -  return null;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether any ranges are currently in the set.
    - */
    -goog.math.RangeSet.prototype.isEmpty = function() {
    -  return this.ranges_.length == 0;
    -};
    -
    -
    -/**
    - * Removes all values in the set.
    - */
    -goog.math.RangeSet.prototype.clear = function() {
    -  this.ranges_.length = 0;
    -};
    -
    -
    -/**
    - * Returns an iterator that iterates over the ranges in the RangeSet.
    - *
    - * @param {boolean=} opt_keys Ignored for RangeSets.
    - * @return {!goog.iter.Iterator} An iterator over the values in the set.
    - */
    -goog.math.RangeSet.prototype.__iterator__ = function(opt_keys) {
    -  var i = 0;
    -  var list = this.ranges_;
    -
    -  var iterator = new goog.iter.Iterator();
    -  iterator.next = function() {
    -    if (i >= list.length) {
    -      throw goog.iter.StopIteration;
    -    }
    -    return list[i++].clone();
    -  };
    -
    -  return iterator;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/math/rangeset_test.html b/src/database/third_party/closure-library/closure/goog/math/rangeset_test.html
    deleted file mode 100644
    index 53adb50140c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/rangeset_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.math.RangeSet
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.math.RangeSetTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/math/rangeset_test.js b/src/database/third_party/closure-library/closure/goog/math/rangeset_test.js
    deleted file mode 100644
    index 3c072418da3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/rangeset_test.js
    +++ /dev/null
    @@ -1,660 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.math.RangeSetTest');
    -goog.setTestOnly('goog.math.RangeSetTest');
    -
    -goog.require('goog.iter');
    -goog.require('goog.math.Range');
    -goog.require('goog.math.RangeSet');
    -goog.require('goog.testing.jsunit');
    -
    -
    -/**
    - * Produce legible assertion results for comparing ranges. The expected range
    - * may be defined as a goog.math.Range or as a two-element array of numbers. If
    - * two ranges are not equal, the error message will be in the format:
    - * "Expected <[1, 2]> (Object) but was <[3, 4]> (Object)"
    - *
    - * @param {!goog.math.Range|!Array<number>|string} a A descriptive string or
    - *     the expected range.
    - * @param {!goog.math.Range|!Array<number>} b The expected range when a
    - *     descriptive string is present, or the range to compare.
    - * @param {goog.math.Range=} opt_c The range to compare when a descriptive
    - *     string is present.
    - */
    -function assertRangesEqual(a, b, opt_c) {
    -  var message = opt_c ? a : '';
    -  var expected = opt_c ? b : a;
    -  var actual = opt_c ? opt_c : b;
    -
    -  if (goog.isArray(expected)) {
    -    assertEquals(message + '\n' +
    -                 'Expected ranges must be specified as goog.math.Range ' +
    -                 'objects or as 2-element number arrays. Found [' +
    -                 expected.join(', ') + ']',
    -                 2, expected.length);
    -    expected = new goog.math.Range(expected[0], expected[1]);
    -  }
    -
    -  if (!goog.math.Range.equals(/** @type {!goog.math.Range} */ (expected),
    -                              /** @type {!goog.math.Range} */ (actual))) {
    -    if (message) {
    -      assertEquals(message, expected, actual);
    -    } else {
    -      assertEquals(expected, actual);
    -    }
    -  }
    -}
    -
    -
    -/**
    - * Produce legible assertion results for comparing two lists of ranges. Expected
    - * lists may be specified as a list of goog.math.Ranges, or as a list of
    - * two-element arrays of numbers.
    - *
    - * @param {Array<goog.math.Range|Array<number>>|string} a A help
    - *     string or the list of expected ranges.
    - * @param {Array<goog.math.Range|Array<number>>} b The list of
    - *     expected ranges when a descriptive string is present, or the list of
    - *     ranges to compare.
    - * @param {Array<goog.math.Range>=} opt_c The list of ranges to compare when a
    - *     descriptive string is present.
    - */
    -function assertRangeListsEqual(a, b, opt_c) {
    -  var message = opt_c ? a + '\n' : '';
    -  var expected = opt_c ? b : a;
    -  var actual = opt_c ? opt_c : b;
    -
    -  assertEquals(message + 'Array lengths unequal.',
    -               expected.length, actual.length);
    -
    -  for (var i = 0; i < expected.length; i++) {
    -    assertRangesEqual(message + 'Range ' + i + ' mismatch.',
    -                      expected[i], actual[i]);
    -  }
    -}
    -
    -
    -function testClone() {
    -  var r = new goog.math.RangeSet();
    -
    -  var test = new goog.math.RangeSet(r);
    -  assertRangeListsEqual([], test.ranges_);
    -
    -  r.add(new goog.math.Range(-10, -2));
    -  r.add(new goog.math.Range(2.72, 3.14));
    -  r.add(new goog.math.Range(8, 11));
    -
    -  test = r.clone();
    -  assertRangeListsEqual([[-10, -2], [2.72, 3.14], [8, 11]], test.ranges_);
    -
    -  var test2 = r.clone();
    -  assertRangeListsEqual(test.ranges_, test2.ranges_);
    -
    -  assertNotEquals('The clones should not share the same list reference.',
    -                  test.ranges_, test2.ranges_);
    -
    -  for (var i = 0; i < test.ranges_.length; i++) {
    -    assertNotEquals('The clones should not share references to ranges.',
    -                    test.ranges_[i], test2.ranges_[i]);
    -  }
    -}
    -
    -
    -function testAddNoCorruption() {
    -  var r = new goog.math.RangeSet();
    -
    -  var range = new goog.math.Range(1, 2);
    -  r.add(range);
    -
    -  assertNotEquals('Only a copy of the input range should be stored.',
    -                  range, r.ranges_[0]);
    -
    -  range.end = 5;
    -  assertRangeListsEqual('Modifying an input range after use should not ' +
    -                        'affect the set.',
    -                        [[1, 2]], r.ranges_);
    -}
    -
    -
    -function testAdd() {
    -  var r = new goog.math.RangeSet();
    -
    -  r.add(new goog.math.Range(7, 12));
    -  assertRangeListsEqual([[7, 12]], r.ranges_);
    -
    -  r.add(new goog.math.Range(1, 3));
    -  assertRangeListsEqual([[1, 3], [7, 12]], r.ranges_);
    -
    -  r.add(new goog.math.Range(13, 18));
    -  assertRangeListsEqual([[1, 3], [7, 12], [13, 18]], r.ranges_);
    -
    -  r.add(new goog.math.Range(5, 5));
    -  assertRangeListsEqual('Zero length ranges should be ignored.',
    -                        [[1, 3], [7, 12], [13, 18]], r.ranges_);
    -
    -  var badRange = new goog.math.Range(5, 5);
    -  badRange.end = 4;
    -  r.add(badRange);
    -  assertRangeListsEqual('Negative length ranges should be ignored.',
    -                        [[1, 3], [7, 12], [13, 18]], r.ranges_);
    -
    -  r.add(new goog.math.Range(-22, -15));
    -  assertRangeListsEqual('Negative ranges should work fine.',
    -                        [[-22, -15], [1, 3], [7, 12], [13, 18]], r.ranges_);
    -
    -  r.add(new goog.math.Range(3.1, 6.9));
    -  assertRangeListsEqual('Non-integer ranges should work fine.',
    -                        [[-22, -15], [1, 3], [3.1, 6.9], [7, 12], [13, 18]],
    -                        r.ranges_);
    -}
    -
    -
    -function testAddWithOverlaps() {
    -  var r = new goog.math.RangeSet();
    -
    -  r.add(new goog.math.Range(7, 12));
    -  r.add(new goog.math.Range(5, 8));
    -  assertRangeListsEqual([[5, 12]], r.ranges_);
    -
    -  r.add(new goog.math.Range(15, 20));
    -  r.add(new goog.math.Range(18, 25));
    -  assertRangeListsEqual([[5, 12], [15, 25]], r.ranges_);
    -
    -  r.add(new goog.math.Range(10, 17));
    -  assertRangeListsEqual([[5, 25]], r.ranges_);
    -
    -  r.add(new goog.math.Range(-4, 4.5));
    -  assertRangeListsEqual([[-4, 4.5], [5, 25]], r.ranges_);
    -
    -  r.add(new goog.math.Range(4.2, 5.3));
    -  assertRangeListsEqual([[-4, 25]], r.ranges_);
    -}
    -
    -
    -function testAddWithAdjacentSpans() {
    -  var r = new goog.math.RangeSet();
    -
    -  r.add(new goog.math.Range(7, 12));
    -  r.add(new goog.math.Range(13, 19));
    -  assertRangeListsEqual([[7, 12], [13, 19]], r.ranges_);
    -
    -  r.add(new goog.math.Range(4, 6));
    -  assertRangeListsEqual([[4, 6], [7, 12], [13, 19]], r.ranges_);
    -
    -  r.add(new goog.math.Range(6, 7));
    -  assertRangeListsEqual([[4, 12], [13, 19]], r.ranges_);
    -
    -  r.add(new goog.math.Range(12, 13));
    -  assertRangeListsEqual([[4, 19]], r.ranges_);
    -
    -  r.add(new goog.math.Range(19.1, 22));
    -  assertRangeListsEqual([[4, 19], [19.1, 22]], r.ranges_);
    -
    -  r.add(new goog.math.Range(19, 19.1));
    -  assertRangeListsEqual([[4, 22]], r.ranges_);
    -
    -  r.add(new goog.math.Range(-3, -2));
    -  assertRangeListsEqual([[-3, -2], [4, 22]], r.ranges_);
    -
    -  r.add(new goog.math.Range(-2, 4));
    -  assertRangeListsEqual([[-3, 22]], r.ranges_);
    -}
    -
    -
    -function testAddWithSubsets() {
    -  var r = new goog.math.RangeSet();
    -
    -  r.add(new goog.math.Range(7, 12));
    -  assertRangeListsEqual([[7, 12]], r.ranges_);
    -
    -  r.add(new goog.math.Range(7, 12));
    -  assertRangeListsEqual([[7, 12]], r.ranges_);
    -
    -  r.add(new goog.math.Range(8, 11));
    -  assertRangeListsEqual([[7, 12]], r.ranges_);
    -
    -  for (var i = 20; i < 30; i += 2) {
    -    r.add(new goog.math.Range(i, i + 1));
    -  }
    -  assertRangeListsEqual(
    -      [[7, 12], [20, 21], [22, 23], [24, 25], [26, 27], [28, 29]],
    -      r.ranges_);
    -
    -  r.add(new goog.math.Range(1, 30));
    -  assertRangeListsEqual([[1, 30]], r.ranges_);
    -}
    -
    -
    -function testRemove() {
    -  var r = new goog.math.RangeSet();
    -
    -  r.add(new goog.math.Range(1, 3));
    -  r.add(new goog.math.Range(7, 8));
    -  r.add(new goog.math.Range(10, 20));
    -
    -  r.remove(new goog.math.Range(3, 6));
    -  assertRangeListsEqual([[1, 3], [7, 8], [10, 20]], r.ranges_);
    -
    -  r.remove(new goog.math.Range(7, 8));
    -  assertRangeListsEqual([[1, 3], [10, 20]], r.ranges_);
    -
    -  r.remove(new goog.math.Range(1, 3));
    -  assertRangeListsEqual([[10, 20]], r.ranges_);
    -
    -  r.remove(new goog.math.Range(8, 11));
    -  assertRangeListsEqual([[11, 20]], r.ranges_);
    -
    -  r.remove(new goog.math.Range(18, 25));
    -  assertRangeListsEqual([[11, 18]], r.ranges_);
    -
    -  r.remove(new goog.math.Range(15, 16));
    -  assertRangeListsEqual([[11, 15], [16, 18]], r.ranges_);
    -
    -  r.remove(new goog.math.Range(11, 15));
    -  assertRangeListsEqual([[16, 18]], r.ranges_);
    -
    -  r.remove(new goog.math.Range(16, 16));
    -  assertRangeListsEqual('Empty ranges should be ignored.',
    -                        [[16, 18]], r.ranges_);
    -
    -  r.remove(new goog.math.Range(16, 17));
    -  assertRangeListsEqual([[17, 18]], r.ranges_);
    -
    -  r.remove(new goog.math.Range(17, 18));
    -  assertRangeListsEqual([], r.ranges_);
    -}
    -
    -
    -function testRemoveWithNonOverlappingRanges() {
    -  var r = new goog.math.RangeSet();
    -
    -  r.add(new goog.math.Range(10, 20));
    -
    -  r.remove(new goog.math.Range(5, 8));
    -  assertRangeListsEqual('Non-overlapping ranges should be ignored.',
    -                        [[10, 20]], r.ranges_);
    -
    -  r.remove(new goog.math.Range(20, 30));
    -  assertRangeListsEqual('Non-overlapping ranges should be ignored.',
    -                        [[10, 20]], r.ranges_);
    -
    -  r.remove(new goog.math.Range(15, 15));
    -  assertRangeListsEqual('Zero-length ranges should be ignored.',
    -                        [[10, 20]], r.ranges_);
    -}
    -
    -
    -function testRemoveWithIdenticalRanges() {
    -  var r = new goog.math.RangeSet();
    -
    -  r.add(new goog.math.Range(10, 20));
    -  r.add(new goog.math.Range(30, 40));
    -  r.add(new goog.math.Range(50, 60));
    -  assertRangeListsEqual([[10, 20], [30, 40], [50, 60]], r.ranges_);
    -
    -  r.remove(new goog.math.Range(30, 40));
    -  assertRangeListsEqual([[10, 20], [50, 60]], r.ranges_);
    -
    -  r.remove(new goog.math.Range(50, 60));
    -  assertRangeListsEqual([[10, 20]], r.ranges_);
    -
    -  r.remove(new goog.math.Range(10, 20));
    -  assertRangeListsEqual([], r.ranges_);
    -}
    -
    -
    -function testRemoveWithOverlappingSubsets() {
    -  var r = new goog.math.RangeSet();
    -
    -  r.add(new goog.math.Range(1, 10));
    -
    -  r.remove(new goog.math.Range(1, 4));
    -  assertRangeListsEqual([[4, 10]], r.ranges_);
    -
    -  r.remove(new goog.math.Range(8, 10));
    -  assertRangeListsEqual([[4, 8]], r.ranges_);
    -}
    -
    -
    -function testRemoveMultiple() {
    -  var r = new goog.math.RangeSet();
    -
    -  r.add(new goog.math.Range(5, 8));
    -  r.add(new goog.math.Range(10, 20));
    -  r.add(new goog.math.Range(30, 35));
    -
    -  for (var i = 20; i < 30; i += 2) {
    -    r.add(new goog.math.Range(i, i + 1));
    -  }
    -
    -  assertRangeListsEqual(
    -      'Setting up the test data seems to have failed, how embarrassing.',
    -      [[5, 8], [10, 21], [22, 23], [24, 25], [26, 27], [28, 29], [30, 35]],
    -      r.ranges_);
    -
    -  r.remove(new goog.math.Range(15, 32));
    -  assertRangeListsEqual([[5, 8], [10, 15], [32, 35]],
    -                        r.ranges_);
    -}
    -
    -
    -function testRemoveWithRealNumbers() {
    -  var r = new goog.math.RangeSet();
    -
    -  r.add(new goog.math.Range(2, 4));
    -
    -  r.remove(new goog.math.Range(1.1, 2.72));
    -  assertRangeListsEqual([[2.72, 4]], r.ranges_);
    -
    -  r.remove(new goog.math.Range(3.14, 5));
    -  assertRangeListsEqual([[2.72, 3.14]], r.ranges_);
    -
    -  r.remove(new goog.math.Range(2.8, 3));
    -  assertRangeListsEqual([[2.72, 2.8], [3, 3.14]], r.ranges_);
    -}
    -
    -
    -function testEquals() {
    -  var a = new goog.math.RangeSet();
    -  var b = new goog.math.RangeSet();
    -
    -  assertTrue(goog.math.RangeSet.equals(a, b));
    -
    -  a.add(new goog.math.Range(3, 9));
    -  assertFalse(goog.math.RangeSet.equals(a, b));
    -
    -  b.add(new goog.math.Range(4, 9));
    -  assertFalse(goog.math.RangeSet.equals(a, b));
    -
    -  b.add(new goog.math.Range(3, 4));
    -  assertTrue(goog.math.RangeSet.equals(a, b));
    -
    -  a.add(new goog.math.Range(12, 14));
    -  b.add(new goog.math.Range(11, 14));
    -  assertFalse(goog.math.RangeSet.equals(a, b));
    -
    -  a.add(new goog.math.Range(11, 12));
    -  assertTrue(goog.math.RangeSet.equals(a, b));
    -}
    -
    -
    -function testContains() {
    -  var r = new goog.math.RangeSet();
    -
    -  assertFalse(r.contains(7, 9));
    -
    -  r.add(new goog.math.Range(5, 6));
    -  r.add(new goog.math.Range(10, 20));
    -
    -  assertFalse(r.contains(new goog.math.Range(7, 9)));
    -  assertFalse(r.contains(new goog.math.Range(9, 11)));
    -  assertFalse(r.contains(new goog.math.Range(18, 22)));
    -
    -  assertTrue(r.contains(new goog.math.Range(17, 19)));
    -  assertTrue(r.contains(new goog.math.Range(5, 6)));
    -
    -  assertTrue(r.contains(new goog.math.Range(5.9, 5.999)));
    -
    -  assertFalse('An empty input range should always return false.',
    -              r.contains(new goog.math.Range(15, 15)));
    -
    -  var badRange = new goog.math.Range(15, 15);
    -  badRange.end = 14;
    -  assertFalse('An invalid range should always return false.',
    -              r.contains(badRange));
    -}
    -
    -
    -function testContainsValue() {
    -  var r = new goog.math.RangeSet();
    -
    -  assertFalse(r.containsValue(5));
    -
    -  r.add(new goog.math.Range(1, 4));
    -  r.add(new goog.math.Range(10, 20));
    -
    -  assertFalse(r.containsValue(0));
    -  assertFalse(r.containsValue(0.999));
    -  assertFalse(r.containsValue(5));
    -  assertFalse(r.containsValue(25));
    -  assertFalse(r.containsValue(20));
    -
    -  assertTrue(r.containsValue(3));
    -  assertTrue(r.containsValue(10));
    -  assertTrue(r.containsValue(19));
    -  assertTrue(r.containsValue(19.999));
    -}
    -
    -
    -function testUnion() {
    -  var a = new goog.math.RangeSet();
    -
    -  a.add(new goog.math.Range(1, 5));
    -  a.add(new goog.math.Range(10, 11));
    -  a.add(new goog.math.Range(15, 20));
    -
    -  var b = new goog.math.RangeSet();
    -
    -  b.add(new goog.math.Range(0, 5));
    -  b.add(new goog.math.Range(8, 18));
    -
    -  var test = a.union(b);
    -  assertRangeListsEqual([[0, 5], [8, 20]], test.ranges_);
    -
    -  var test = b.union(a);
    -  assertRangeListsEqual([[0, 5], [8, 20]], test.ranges_);
    -
    -  var test = a.union(a);
    -  assertRangeListsEqual(a.ranges_, test.ranges_);
    -}
    -
    -
    -function testDifference() {
    -  var a = new goog.math.RangeSet();
    -
    -  a.add(new goog.math.Range(1, 5));
    -  a.add(new goog.math.Range(10, 11));
    -  a.add(new goog.math.Range(15, 20));
    -
    -  var b = new goog.math.RangeSet();
    -
    -  b.add(new goog.math.Range(0, 5));
    -  b.add(new goog.math.Range(8, 18));
    -
    -  var test = a.difference(b);
    -  assertRangeListsEqual([[18, 20]], test.ranges_);
    -
    -  var test = b.difference(a);
    -  assertRangeListsEqual([[0, 1], [8, 10], [11, 15]], test.ranges_);
    -
    -  var test = a.difference(a);
    -  assertRangeListsEqual([], test.ranges_);
    -
    -  var test = b.difference(b);
    -  assertRangeListsEqual([], test.ranges_);
    -}
    -
    -
    -function testIntersection() {
    -  var a = new goog.math.RangeSet();
    -
    -  a.add(new goog.math.Range(1, 5));
    -  a.add(new goog.math.Range(10, 11));
    -  a.add(new goog.math.Range(15, 20));
    -
    -  var b = new goog.math.RangeSet();
    -
    -  b.add(new goog.math.Range(0, 5));
    -  b.add(new goog.math.Range(8, 18));
    -
    -  var test = a.intersection(b);
    -  assertRangeListsEqual([[1, 5], [10, 11], [15, 18]], test.ranges_);
    -
    -  var test = b.intersection(a);
    -  assertRangeListsEqual([[1, 5], [10, 11], [15, 18]], test.ranges_);
    -
    -  var test = a.intersection(a);
    -  assertRangeListsEqual(a.ranges_, test.ranges_);
    -}
    -
    -
    -function testSlice() {
    -  var r = new goog.math.RangeSet();
    -
    -  r.add(new goog.math.Range(2, 4));
    -  r.add(new goog.math.Range(5, 6));
    -  r.add(new goog.math.Range(9, 15));
    -
    -  var test = r.slice(new goog.math.Range(0, 2));
    -  assertRangeListsEqual([], test.ranges_);
    -
    -  test = r.slice(new goog.math.Range(2, 4));
    -  assertRangeListsEqual([[2, 4]], test.ranges_);
    -
    -  test = r.slice(new goog.math.Range(7, 20));
    -  assertRangeListsEqual([[9, 15]], test.ranges_);
    -
    -  test = r.slice(new goog.math.Range(4, 30));
    -  assertRangeListsEqual([[5, 6], [9, 15]], test.ranges_);
    -
    -  test = r.slice(new goog.math.Range(2, 15));
    -  assertRangeListsEqual([[2, 4], [5, 6], [9, 15]], test.ranges_);
    -
    -  test = r.slice(new goog.math.Range(10, 10));
    -  assertRangeListsEqual('An empty range should produce an empty set.',
    -                        [], test.ranges_);
    -
    -  var badRange = new goog.math.Range(10, 10);
    -  badRange.end = 9;
    -  test = r.slice(badRange);
    -  assertRangeListsEqual('An invalid range should produce an empty set.',
    -                        [], test.ranges_);
    -}
    -
    -
    -function testInverse() {
    -  var r = new goog.math.RangeSet();
    -
    -  r.add(new goog.math.Range(1, 3));
    -  r.add(new goog.math.Range(5, 6));
    -  r.add(new goog.math.Range(8, 10));
    -
    -  var test = r.inverse(new goog.math.Range(10, 20));
    -  assertRangeListsEqual([[10, 20]], test.ranges_);
    -
    -  test = r.inverse(new goog.math.Range(1, 3));
    -  assertRangeListsEqual([], test.ranges_);
    -
    -  test = r.inverse(new goog.math.Range(0, 2));
    -  assertRangeListsEqual([[0, 1]], test.ranges_);
    -
    -  test = r.inverse(new goog.math.Range(9, 12));
    -  assertRangeListsEqual([[10, 12]], test.ranges_);
    -
    -  test = r.inverse(new goog.math.Range(2, 9));
    -  assertRangeListsEqual([[3, 5], [6, 8]], test.ranges_);
    -
    -  test = r.inverse(new goog.math.Range(4, 9));
    -  assertRangeListsEqual([[4, 5], [6, 8]], test.ranges_);
    -
    -  test = r.inverse(new goog.math.Range(9, 9));
    -  assertRangeListsEqual('An empty range should produce an empty set.',
    -                        [], test.ranges_);
    -
    -  var badRange = new goog.math.Range(9, 9);
    -  badRange.end = 8;
    -  test = r.inverse(badRange);
    -  assertRangeListsEqual('An invalid range should produce an empty set.',
    -                        [], test.ranges_);
    -}
    -
    -
    -function testCoveredLength() {
    -  var r = new goog.math.RangeSet();
    -  assertEquals(0, r.coveredLength());
    -
    -  r.add(new goog.math.Range(5, 9));
    -  assertEquals(4, r.coveredLength());
    -
    -  r.add(new goog.math.Range(0, 3));
    -  r.add(new goog.math.Range(12, 13));
    -  assertEquals(8, r.coveredLength());
    -
    -  r.add(new goog.math.Range(-1, 13));
    -  assertEquals(14, r.coveredLength());
    -
    -  r.add(new goog.math.Range(13, 13.5));
    -  assertEquals(14.5, r.coveredLength());
    -}
    -
    -
    -function testGetBounds() {
    -  var r = new goog.math.RangeSet();
    -
    -  assertNull(r.getBounds());
    -
    -  r.add(new goog.math.Range(12, 54));
    -  assertRangesEqual([12, 54], r.getBounds());
    -
    -  r.add(new goog.math.Range(108, 139));
    -  assertRangesEqual([12, 139], r.getBounds());
    -}
    -
    -
    -function testIsEmpty() {
    -  var r = new goog.math.RangeSet();
    -  assertTrue(r.isEmpty());
    -
    -  r.add(new goog.math.Range(0, 1));
    -  assertFalse(r.isEmpty());
    -
    -  r.remove(new goog.math.Range(0, 1));
    -  assertTrue(r.isEmpty());
    -}
    -
    -
    -function testClear() {
    -  var r = new goog.math.RangeSet();
    -
    -  r.add(new goog.math.Range(1, 2));
    -  r.add(new goog.math.Range(3, 5));
    -  r.add(new goog.math.Range(8, 13));
    -
    -  assertFalse(r.isEmpty());
    -
    -  r.clear();
    -  assertTrue(r.isEmpty());
    -}
    -
    -
    -function testIter() {
    -  var r = new goog.math.RangeSet();
    -
    -  r.add(new goog.math.Range(1, 3));
    -  r.add(new goog.math.Range(5, 6));
    -  r.add(new goog.math.Range(8, 10));
    -
    -  assertRangeListsEqual([[1, 3], [5, 6], [8, 10]], goog.iter.toArray(r));
    -
    -  var i = 0;
    -  goog.iter.forEach(r, function(testRange) {
    -    assertRangesEqual('Iterated set values should match the originals.',
    -                      r.ranges_[i], testRange);
    -    assertNotEquals('Iterated range should not be a reference to the original.',
    -                    r.ranges_[i], testRange);
    -    i++;
    -  });
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/math/rect.js b/src/database/third_party/closure-library/closure/goog/math/rect.js
    deleted file mode 100644
    index c44b80e8419..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/rect.js
    +++ /dev/null
    @@ -1,464 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A utility class for representing rectangles.
    - */
    -
    -goog.provide('goog.math.Rect');
    -
    -goog.require('goog.math.Box');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.math.Size');
    -
    -
    -
    -/**
    - * Class for representing rectangular regions.
    - * @param {number} x Left.
    - * @param {number} y Top.
    - * @param {number} w Width.
    - * @param {number} h Height.
    - * @struct
    - * @constructor
    - */
    -goog.math.Rect = function(x, y, w, h) {
    -  /** @type {number} */
    -  this.left = x;
    -
    -  /** @type {number} */
    -  this.top = y;
    -
    -  /** @type {number} */
    -  this.width = w;
    -
    -  /** @type {number} */
    -  this.height = h;
    -};
    -
    -
    -/**
    - * @return {!goog.math.Rect} A new copy of this Rectangle.
    - */
    -goog.math.Rect.prototype.clone = function() {
    -  return new goog.math.Rect(this.left, this.top, this.width, this.height);
    -};
    -
    -
    -/**
    - * Returns a new Box object with the same position and dimensions as this
    - * rectangle.
    - * @return {!goog.math.Box} A new Box representation of this Rectangle.
    - */
    -goog.math.Rect.prototype.toBox = function() {
    -  var right = this.left + this.width;
    -  var bottom = this.top + this.height;
    -  return new goog.math.Box(this.top,
    -                           right,
    -                           bottom,
    -                           this.left);
    -};
    -
    -
    -/**
    - * Creates a new Rect object with the same position and dimensions as a given
    - * Box.  Note that this is only the inverse of toBox if left/top are defined.
    - * @param {goog.math.Box} box A box.
    - * @return {!goog.math.Rect} A new Rect initialized with the box's position
    - *     and size.
    - */
    -goog.math.Rect.createFromBox = function(box) {
    -  return new goog.math.Rect(box.left, box.top,
    -      box.right - box.left, box.bottom - box.top);
    -};
    -
    -
    -if (goog.DEBUG) {
    -  /**
    -   * Returns a nice string representing size and dimensions of rectangle.
    -   * @return {string} In the form (50, 73 - 75w x 25h).
    -   * @override
    -   */
    -  goog.math.Rect.prototype.toString = function() {
    -    return '(' + this.left + ', ' + this.top + ' - ' + this.width + 'w x ' +
    -           this.height + 'h)';
    -  };
    -}
    -
    -
    -/**
    - * Compares rectangles for equality.
    - * @param {goog.math.Rect} a A Rectangle.
    - * @param {goog.math.Rect} b A Rectangle.
    - * @return {boolean} True iff the rectangles have the same left, top, width,
    - *     and height, or if both are null.
    - */
    -goog.math.Rect.equals = function(a, b) {
    -  if (a == b) {
    -    return true;
    -  }
    -  if (!a || !b) {
    -    return false;
    -  }
    -  return a.left == b.left && a.width == b.width &&
    -         a.top == b.top && a.height == b.height;
    -};
    -
    -
    -/**
    - * Computes the intersection of this rectangle and the rectangle parameter.  If
    - * there is no intersection, returns false and leaves this rectangle as is.
    - * @param {goog.math.Rect} rect A Rectangle.
    - * @return {boolean} True iff this rectangle intersects with the parameter.
    - */
    -goog.math.Rect.prototype.intersection = function(rect) {
    -  var x0 = Math.max(this.left, rect.left);
    -  var x1 = Math.min(this.left + this.width, rect.left + rect.width);
    -
    -  if (x0 <= x1) {
    -    var y0 = Math.max(this.top, rect.top);
    -    var y1 = Math.min(this.top + this.height, rect.top + rect.height);
    -
    -    if (y0 <= y1) {
    -      this.left = x0;
    -      this.top = y0;
    -      this.width = x1 - x0;
    -      this.height = y1 - y0;
    -
    -      return true;
    -    }
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Returns the intersection of two rectangles. Two rectangles intersect if they
    - * touch at all, for example, two zero width and height rectangles would
    - * intersect if they had the same top and left.
    - * @param {goog.math.Rect} a A Rectangle.
    - * @param {goog.math.Rect} b A Rectangle.
    - * @return {goog.math.Rect} A new intersection rect (even if width and height
    - *     are 0), or null if there is no intersection.
    - */
    -goog.math.Rect.intersection = function(a, b) {
    -  // There is no nice way to do intersection via a clone, because any such
    -  // clone might be unnecessary if this function returns null.  So, we duplicate
    -  // code from above.
    -
    -  var x0 = Math.max(a.left, b.left);
    -  var x1 = Math.min(a.left + a.width, b.left + b.width);
    -
    -  if (x0 <= x1) {
    -    var y0 = Math.max(a.top, b.top);
    -    var y1 = Math.min(a.top + a.height, b.top + b.height);
    -
    -    if (y0 <= y1) {
    -      return new goog.math.Rect(x0, y0, x1 - x0, y1 - y0);
    -    }
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * Returns whether two rectangles intersect. Two rectangles intersect if they
    - * touch at all, for example, two zero width and height rectangles would
    - * intersect if they had the same top and left.
    - * @param {goog.math.Rect} a A Rectangle.
    - * @param {goog.math.Rect} b A Rectangle.
    - * @return {boolean} Whether a and b intersect.
    - */
    -goog.math.Rect.intersects = function(a, b) {
    -  return (a.left <= b.left + b.width && b.left <= a.left + a.width &&
    -      a.top <= b.top + b.height && b.top <= a.top + a.height);
    -};
    -
    -
    -/**
    - * Returns whether a rectangle intersects this rectangle.
    - * @param {goog.math.Rect} rect A rectangle.
    - * @return {boolean} Whether rect intersects this rectangle.
    - */
    -goog.math.Rect.prototype.intersects = function(rect) {
    -  return goog.math.Rect.intersects(this, rect);
    -};
    -
    -
    -/**
    - * Computes the difference regions between two rectangles. The return value is
    - * an array of 0 to 4 rectangles defining the remaining regions of the first
    - * rectangle after the second has been subtracted.
    - * @param {goog.math.Rect} a A Rectangle.
    - * @param {goog.math.Rect} b A Rectangle.
    - * @return {!Array<!goog.math.Rect>} An array with 0 to 4 rectangles which
    - *     together define the difference area of rectangle a minus rectangle b.
    - */
    -goog.math.Rect.difference = function(a, b) {
    -  var intersection = goog.math.Rect.intersection(a, b);
    -  if (!intersection || !intersection.height || !intersection.width) {
    -    return [a.clone()];
    -  }
    -
    -  var result = [];
    -
    -  var top = a.top;
    -  var height = a.height;
    -
    -  var ar = a.left + a.width;
    -  var ab = a.top + a.height;
    -
    -  var br = b.left + b.width;
    -  var bb = b.top + b.height;
    -
    -  // Subtract off any area on top where A extends past B
    -  if (b.top > a.top) {
    -    result.push(new goog.math.Rect(a.left, a.top, a.width, b.top - a.top));
    -    top = b.top;
    -    // If we're moving the top down, we also need to subtract the height diff.
    -    height -= b.top - a.top;
    -  }
    -  // Subtract off any area on bottom where A extends past B
    -  if (bb < ab) {
    -    result.push(new goog.math.Rect(a.left, bb, a.width, ab - bb));
    -    height = bb - top;
    -  }
    -  // Subtract any area on left where A extends past B
    -  if (b.left > a.left) {
    -    result.push(new goog.math.Rect(a.left, top, b.left - a.left, height));
    -  }
    -  // Subtract any area on right where A extends past B
    -  if (br < ar) {
    -    result.push(new goog.math.Rect(br, top, ar - br, height));
    -  }
    -
    -  return result;
    -};
    -
    -
    -/**
    - * Computes the difference regions between this rectangle and {@code rect}. The
    - * return value is an array of 0 to 4 rectangles defining the remaining regions
    - * of this rectangle after the other has been subtracted.
    - * @param {goog.math.Rect} rect A Rectangle.
    - * @return {!Array<!goog.math.Rect>} An array with 0 to 4 rectangles which
    - *     together define the difference area of rectangle a minus rectangle b.
    - */
    -goog.math.Rect.prototype.difference = function(rect) {
    -  return goog.math.Rect.difference(this, rect);
    -};
    -
    -
    -/**
    - * Expand this rectangle to also include the area of the given rectangle.
    - * @param {goog.math.Rect} rect The other rectangle.
    - */
    -goog.math.Rect.prototype.boundingRect = function(rect) {
    -  // We compute right and bottom before we change left and top below.
    -  var right = Math.max(this.left + this.width, rect.left + rect.width);
    -  var bottom = Math.max(this.top + this.height, rect.top + rect.height);
    -
    -  this.left = Math.min(this.left, rect.left);
    -  this.top = Math.min(this.top, rect.top);
    -
    -  this.width = right - this.left;
    -  this.height = bottom - this.top;
    -};
    -
    -
    -/**
    - * Returns a new rectangle which completely contains both input rectangles.
    - * @param {goog.math.Rect} a A rectangle.
    - * @param {goog.math.Rect} b A rectangle.
    - * @return {goog.math.Rect} A new bounding rect, or null if either rect is
    - *     null.
    - */
    -goog.math.Rect.boundingRect = function(a, b) {
    -  if (!a || !b) {
    -    return null;
    -  }
    -
    -  var clone = a.clone();
    -  clone.boundingRect(b);
    -
    -  return clone;
    -};
    -
    -
    -/**
    - * Tests whether this rectangle entirely contains another rectangle or
    - * coordinate.
    - *
    - * @param {goog.math.Rect|goog.math.Coordinate} another The rectangle or
    - *     coordinate to test for containment.
    - * @return {boolean} Whether this rectangle contains given rectangle or
    - *     coordinate.
    - */
    -goog.math.Rect.prototype.contains = function(another) {
    -  if (another instanceof goog.math.Rect) {
    -    return this.left <= another.left &&
    -           this.left + this.width >= another.left + another.width &&
    -           this.top <= another.top &&
    -           this.top + this.height >= another.top + another.height;
    -  } else { // (another instanceof goog.math.Coordinate)
    -    return another.x >= this.left &&
    -           another.x <= this.left + this.width &&
    -           another.y >= this.top &&
    -           another.y <= this.top + this.height;
    -  }
    -};
    -
    -
    -/**
    - * @param {!goog.math.Coordinate} point A coordinate.
    - * @return {number} The squared distance between the point and the closest
    - *     point inside the rectangle. Returns 0 if the point is inside the
    - *     rectangle.
    - */
    -goog.math.Rect.prototype.squaredDistance = function(point) {
    -  var dx = point.x < this.left ?
    -      this.left - point.x : Math.max(point.x - (this.left + this.width), 0);
    -  var dy = point.y < this.top ?
    -      this.top - point.y : Math.max(point.y - (this.top + this.height), 0);
    -  return dx * dx + dy * dy;
    -};
    -
    -
    -/**
    - * @param {!goog.math.Coordinate} point A coordinate.
    - * @return {number} The distance between the point and the closest point
    - *     inside the rectangle. Returns 0 if the point is inside the rectangle.
    - */
    -goog.math.Rect.prototype.distance = function(point) {
    -  return Math.sqrt(this.squaredDistance(point));
    -};
    -
    -
    -/**
    - * @return {!goog.math.Size} The size of this rectangle.
    - */
    -goog.math.Rect.prototype.getSize = function() {
    -  return new goog.math.Size(this.width, this.height);
    -};
    -
    -
    -/**
    - * @return {!goog.math.Coordinate} A new coordinate for the top-left corner of
    - *     the rectangle.
    - */
    -goog.math.Rect.prototype.getTopLeft = function() {
    -  return new goog.math.Coordinate(this.left, this.top);
    -};
    -
    -
    -/**
    - * @return {!goog.math.Coordinate} A new coordinate for the center of the
    - *     rectangle.
    - */
    -goog.math.Rect.prototype.getCenter = function() {
    -  return new goog.math.Coordinate(
    -      this.left + this.width / 2, this.top + this.height / 2);
    -};
    -
    -
    -/**
    - * @return {!goog.math.Coordinate} A new coordinate for the bottom-right corner
    - *     of the rectangle.
    - */
    -goog.math.Rect.prototype.getBottomRight = function() {
    -  return new goog.math.Coordinate(
    -      this.left + this.width, this.top + this.height);
    -};
    -
    -
    -/**
    - * Rounds the fields to the next larger integer values.
    - * @return {!goog.math.Rect} This rectangle with ceil'd fields.
    - */
    -goog.math.Rect.prototype.ceil = function() {
    -  this.left = Math.ceil(this.left);
    -  this.top = Math.ceil(this.top);
    -  this.width = Math.ceil(this.width);
    -  this.height = Math.ceil(this.height);
    -  return this;
    -};
    -
    -
    -/**
    - * Rounds the fields to the next smaller integer values.
    - * @return {!goog.math.Rect} This rectangle with floored fields.
    - */
    -goog.math.Rect.prototype.floor = function() {
    -  this.left = Math.floor(this.left);
    -  this.top = Math.floor(this.top);
    -  this.width = Math.floor(this.width);
    -  this.height = Math.floor(this.height);
    -  return this;
    -};
    -
    -
    -/**
    - * Rounds the fields to nearest integer values.
    - * @return {!goog.math.Rect} This rectangle with rounded fields.
    - */
    -goog.math.Rect.prototype.round = function() {
    -  this.left = Math.round(this.left);
    -  this.top = Math.round(this.top);
    -  this.width = Math.round(this.width);
    -  this.height = Math.round(this.height);
    -  return this;
    -};
    -
    -
    -/**
    - * Translates this rectangle by the given offsets. If a
    - * {@code goog.math.Coordinate} is given, then the left and top values are
    - * translated by the coordinate's x and y values. Otherwise, top and left are
    - * translated by {@code tx} and {@code opt_ty} respectively.
    - * @param {number|goog.math.Coordinate} tx The value to translate left by or the
    - *     the coordinate to translate this rect by.
    - * @param {number=} opt_ty The value to translate top by.
    - * @return {!goog.math.Rect} This rectangle after translating.
    - */
    -goog.math.Rect.prototype.translate = function(tx, opt_ty) {
    -  if (tx instanceof goog.math.Coordinate) {
    -    this.left += tx.x;
    -    this.top += tx.y;
    -  } else {
    -    this.left += tx;
    -    if (goog.isNumber(opt_ty)) {
    -      this.top += opt_ty;
    -    }
    -  }
    -  return this;
    -};
    -
    -
    -/**
    - * Scales this rectangle by the given scale factors. The left and width values
    - * are scaled by {@code sx} and the top and height values are scaled by
    - * {@code opt_sy}.  If {@code opt_sy} is not given, then all fields are scaled
    - * by {@code sx}.
    - * @param {number} sx The scale factor to use for the x dimension.
    - * @param {number=} opt_sy The scale factor to use for the y dimension.
    - * @return {!goog.math.Rect} This rectangle after scaling.
    - */
    -goog.math.Rect.prototype.scale = function(sx, opt_sy) {
    -  var sy = goog.isNumber(opt_sy) ? opt_sy : sx;
    -  this.left *= sx;
    -  this.width *= sx;
    -  this.top *= sy;
    -  this.height *= sy;
    -  return this;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/math/rect_test.html b/src/database/third_party/closure-library/closure/goog/math/rect_test.html
    deleted file mode 100644
    index aacd9d32672..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/rect_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.math.Rect
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.math.RectTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/math/rect_test.js b/src/database/third_party/closure-library/closure/goog/math/rect_test.js
    deleted file mode 100644
    index 849fae43b7a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/rect_test.js
    +++ /dev/null
    @@ -1,441 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.math.RectTest');
    -goog.setTestOnly('goog.math.RectTest');
    -
    -goog.require('goog.math.Box');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.math.Rect');
    -goog.require('goog.math.Size');
    -goog.require('goog.testing.jsunit');
    -
    -
    -/**
    - * Produce legible assertion results. If two rects are not equal, the error
    - * message will be of the form
    - * "Expected <(1, 2 - 10 x 10)> (Object) but was <(3, 4 - 20 x 20)> (Object)"
    - */
    -function assertRectsEqual(expected, actual) {
    -  if (!goog.math.Rect.equals(expected, actual)) {
    -    assertEquals(expected, actual);
    -  }
    -}
    -
    -function createRect(a) {
    -  return a ? new goog.math.Rect(a[0], a[1], a[2] - a[0], a[3] - a[1]) : null;
    -}
    -
    -function testRectClone() {
    -  var r = new goog.math.Rect(0, 0, 0, 0);
    -  assertRectsEqual(r, r.clone());
    -  r.left = -10;
    -  r.top = -20;
    -  r.width = 10;
    -  r.height = 20;
    -  assertRectsEqual(r, r.clone());
    -}
    -
    -function testRectIntersection() {
    -  var tests = [[[10, 10, 20, 20], [15, 15, 25, 25], [15, 15, 20, 20]],
    -               [[10, 10, 20, 20], [20, 0, 30, 10], [20, 10, 20, 10]],
    -               [[0, 0, 1, 1], [10, 11, 12, 13], null],
    -               [[11, 12, 98, 99], [22, 23, 34, 35], [22, 23, 34, 35]]];
    -  for (var i = 0; i < tests.length; ++i) {
    -    var t = tests[i];
    -    var r0 = createRect(t[0]);
    -    var r1 = createRect(t[1]);
    -
    -    var expected = createRect(t[2]);
    -
    -    assertRectsEqual(expected, goog.math.Rect.intersection(r0, r1));
    -    assertRectsEqual(expected, goog.math.Rect.intersection(r1, r0));
    -
    -    // Test in place methods.
    -    var clone = r0.clone();
    -
    -    assertRectsEqual(expected, clone.intersection(r1) ? clone : null);
    -    assertRectsEqual(expected, r1.intersection(r0) ? r1 : null);
    -  }
    -}
    -
    -function testRectIntersects() {
    -  var r0 = createRect([10, 10, 20, 20]);
    -  var r1 = createRect([15, 15, 25, 25]);
    -  var r2 = createRect([0, 0, 1, 1]);
    -
    -  assertTrue(goog.math.Rect.intersects(r0, r1));
    -  assertTrue(goog.math.Rect.intersects(r1, r0));
    -  assertTrue(r0.intersects(r1));
    -  assertTrue(r1.intersects(r0));
    -
    -  assertFalse(goog.math.Rect.intersects(r0, r2));
    -  assertFalse(goog.math.Rect.intersects(r2, r0));
    -  assertFalse(r0.intersects(r2));
    -  assertFalse(r2.intersects(r0));
    -}
    -
    -function testRectBoundingRect() {
    -  var tests = [[[10, 10, 20, 20], [15, 15, 25, 25], [10, 10, 25, 25]],
    -               [[10, 10, 20, 20], [20, 0, 30, 10], [10, 0, 30, 20]],
    -               [[0, 0, 1, 1], [10, 11, 12, 13], [0, 0, 12, 13]],
    -               [[11, 12, 98, 99], [22, 23, 34, 35], [11, 12, 98, 99]]];
    -  for (var i = 0; i < tests.length; ++i) {
    -    var t = tests[i];
    -    var r0 = createRect(t[0]);
    -    var r1 = createRect(t[1]);
    -    var expected = createRect(t[2]);
    -    assertRectsEqual(expected, goog.math.Rect.boundingRect(r0, r1));
    -    assertRectsEqual(expected, goog.math.Rect.boundingRect(r1, r0));
    -
    -    // Test in place methods.
    -    var clone = r0.clone();
    -
    -    clone.boundingRect(r1);
    -    assertRectsEqual(expected, clone);
    -
    -    r1.boundingRect(r0);
    -    assertRectsEqual(expected, r1);
    -  }
    -}
    -
    -function testRectDifference() {
    -  // B is the same as A.
    -  assertDifference([10, 10, 20, 20], [10, 10, 20, 20], []);
    -  // B does not touch A.
    -  assertDifference([10, 10, 20, 20], [0, 0, 5, 5], [[10, 10, 20, 20]]);
    -  // B overlaps top half of A.
    -  assertDifference([10, 10, 20, 20], [5, 15, 25, 25],
    -      [[10, 10, 20, 15]]);
    -  // B overlaps bottom half of A.
    -  assertDifference([10, 10, 20, 20], [5, 5, 25, 15],
    -      [[10, 15, 20, 20]]);
    -  // B overlaps right half of A.
    -  assertDifference([10, 10, 20, 20], [15, 5, 25, 25],
    -      [[10, 10, 15, 20]]);
    -  // B overlaps left half of A.
    -  assertDifference([10, 10, 20, 20], [5, 5, 15, 25],
    -      [[15, 10, 20, 20]]);
    -  // B touches A at its bottom right corner
    -  assertDifference([10, 10, 20, 20], [20, 20, 30, 30],
    -      [[10, 10, 20, 20]]);
    -  // B touches A at its top left corner
    -  assertDifference([10, 10, 20, 20], [5, 5, 10, 10],
    -      [[10, 10, 20, 20]]);
    -  // B touches A along its bottom edge
    -  assertDifference([10, 10, 20, 20], [12, 20, 17, 25],
    -      [[10, 10, 20, 20]]);
    -  // B splits A horizontally.
    -  assertDifference([10, 10, 20, 20], [5, 12, 25, 18],
    -      [[10, 10, 20, 12], [10, 18, 20, 20]]);
    -  // B splits A vertically.
    -  assertDifference([10, 10, 20, 20], [12, 5, 18, 25],
    -      [[10, 10, 12, 20], [18, 10, 20, 20]]);
    -  // B subtracts a notch from the top of A.
    -  assertDifference([10, 10, 20, 20], [12, 5, 18, 15],
    -      [[10, 15, 20, 20], [10, 10, 12, 15], [18, 10, 20, 15]]);
    -  // B subtracts a notch from the bottom left of A
    -  assertDifference([1, 6, 3, 9], [1, 7, 2, 9],
    -      [[1, 6, 3, 7], [2, 7, 3, 9]]);
    -  // B subtracts a notch from the bottom right of A
    -  assertDifference([1, 6, 3, 9], [2, 7, 3, 9],
    -      [[1, 6, 3, 7], [1, 7, 2, 9]]);
    -  // B subtracts a notch from the top left of A
    -  assertDifference([1, 6, 3, 9], [1, 6, 2, 8],
    -      [[1, 8, 3, 9], [2, 6, 3, 8]]);
    -  // B subtracts a notch from the top left of A (no coinciding edge)
    -  assertDifference([1, 6, 3, 9], [0, 5, 2, 8],
    -      [[1, 8, 3, 9], [2, 6, 3, 8]]);
    -  // B subtracts a hole from the center of A.
    -  assertDifference([-20, -20, -10, -10], [-18, -18, -12, -12],
    -      [[-20, -20, -10, -18], [-20, -12, -10, -10],
    -       [-20, -18, -18, -12], [-12, -18, -10, -12]]);
    -}
    -
    -function assertDifference(a, b, expected) {
    -  var r0 = createRect(a);
    -  var r1 = createRect(b);
    -  var diff = goog.math.Rect.difference(r0, r1);
    -
    -  assertEquals('Wrong number of rectangles in difference ',
    -      expected.length, diff.length);
    -
    -  for (var j = 0; j < expected.length; ++j) {
    -    var e = createRect(expected[j]);
    -    if (!goog.math.Rect.equals(e, diff[j])) {
    -      alert(j + ': ' + e + ' != ' + diff[j]);
    -    }
    -    assertRectsEqual(e, diff[j]);
    -  }
    -
    -  // Test in place version
    -  var diff = r0.difference(r1);
    -
    -  assertEquals('Wrong number of rectangles in in-place difference ',
    -      expected.length, diff.length);
    -
    -  for (var j = 0; j < expected.length; ++j) {
    -    var e = createRect(expected[j]);
    -    if (!goog.math.Rect.equals(e, diff[j])) {
    -      alert(j + ': ' + e + ' != ' + diff[j]);
    -    }
    -    assertRectsEqual(e, diff[j]);
    -  }
    -}
    -
    -function testRectToBox() {
    -  var r = new goog.math.Rect(0, 0, 0, 0);
    -  assertObjectEquals(new goog.math.Box(0, 0, 0, 0), r.toBox());
    -
    -  r.top = 10;
    -  r.left = 10;
    -  r.width = 20;
    -  r.height = 20;
    -  assertObjectEquals(new goog.math.Box(10, 30, 30, 10), r.toBox());
    -
    -  r.top = -10;
    -  r.left = 0;
    -  r.width = 10;
    -  r.height = 10;
    -  assertObjectEquals(new goog.math.Box(-10, 10, 0, 0), r.toBox());
    -}
    -
    -function testBoxToRect() {
    -  var box = new goog.math.Box(0, 0, 0, 0);
    -  assertObjectEquals(new goog.math.Rect(0, 0, 0, 0),
    -                     goog.math.Rect.createFromBox(box));
    -
    -  box.top = 10;
    -  box.left = 15;
    -  box.right = 23;
    -  box.bottom = 27;
    -  assertObjectEquals(new goog.math.Rect(15, 10, 8, 17),
    -                     goog.math.Rect.createFromBox(box));
    -
    -  box.top = -10;
    -  box.left = 3;
    -  box.right = 12;
    -  box.bottom = 7;
    -  assertObjectEquals(new goog.math.Rect(3, -10, 9, 17),
    -                     goog.math.Rect.createFromBox(box));
    -}
    -
    -function testBoxToRectAndBack() {
    -  rectToBoxAndBackTest(new goog.math.Rect(8, 11, 20, 23));
    -  rectToBoxAndBackTest(new goog.math.Rect(9, 13, NaN, NaN));
    -  rectToBoxAndBackTest(new goog.math.Rect(10, 13, NaN, 21));
    -  rectToBoxAndBackTest(new goog.math.Rect(5, 7, 14, NaN));
    -}
    -
    -function rectToBoxAndBackTest(rect) {
    -  var box = rect.toBox();
    -  var rect2 = goog.math.Rect.createFromBox(box);
    -
    -  // Use toString for this test since otherwise NaN != NaN.
    -  assertObjectEquals(rect.toString(), rect2.toString());
    -}
    -
    -function testRectToBoxAndBack() {
    -  // This doesn't work if left or top is undefined.
    -  boxToRectAndBackTest(new goog.math.Box(11, 13, 20, 17));
    -  boxToRectAndBackTest(new goog.math.Box(10, NaN, NaN, 11));
    -  boxToRectAndBackTest(new goog.math.Box(9, 14, NaN, 11));
    -  boxToRectAndBackTest(new goog.math.Box(10, NaN, 22, 15));
    -}
    -
    -function boxToRectAndBackTest(box) {
    -  var rect = goog.math.Rect.createFromBox(box);
    -  var box2 = rect.toBox();
    -
    -  // Use toString for this test since otherwise NaN != NaN.
    -  assertEquals(box.toString(), box2.toString());
    -}
    -
    -function testRectContainsRect() {
    -  var r = new goog.math.Rect(-10, 0, 20, 10);
    -  assertTrue(r.contains(r));
    -  assertFalse(r.contains(new goog.math.Rect(NaN, NaN, NaN, NaN)));
    -  var r2 = new goog.math.Rect(0, 2, 5, 5);
    -  assertTrue(r.contains(r2));
    -  assertFalse(r2.contains(r));
    -  r2.left = -11;
    -  assertFalse(r.contains(r2));
    -  r2.left = 0;
    -  r2.width = 15;
    -  assertFalse(r.contains(r2));
    -  r2.width = 5;
    -  r2.height = 10;
    -  assertFalse(r.contains(r2));
    -  r2.top = 0;
    -  assertTrue(r.contains(r2));
    -}
    -
    -function testRectContainsCoordinate() {
    -  var r = new goog.math.Rect(20, 40, 60, 80);
    -
    -  // Test middle.
    -  assertTrue(r.contains(new goog.math.Coordinate(50, 80)));
    -
    -  // Test edges.
    -  assertTrue(r.contains(new goog.math.Coordinate(20, 40)));
    -  assertTrue(r.contains(new goog.math.Coordinate(50, 40)));
    -  assertTrue(r.contains(new goog.math.Coordinate(80, 40)));
    -  assertTrue(r.contains(new goog.math.Coordinate(80, 80)));
    -  assertTrue(r.contains(new goog.math.Coordinate(80, 120)));
    -  assertTrue(r.contains(new goog.math.Coordinate(50, 120)));
    -  assertTrue(r.contains(new goog.math.Coordinate(20, 120)));
    -  assertTrue(r.contains(new goog.math.Coordinate(20, 80)));
    -
    -  // Test outside.
    -  assertFalse(r.contains(new goog.math.Coordinate(0, 0)));
    -  assertFalse(r.contains(new goog.math.Coordinate(50, 0)));
    -  assertFalse(r.contains(new goog.math.Coordinate(100, 0)));
    -  assertFalse(r.contains(new goog.math.Coordinate(100, 80)));
    -  assertFalse(r.contains(new goog.math.Coordinate(100, 160)));
    -  assertFalse(r.contains(new goog.math.Coordinate(50, 160)));
    -  assertFalse(r.contains(new goog.math.Coordinate(0, 160)));
    -  assertFalse(r.contains(new goog.math.Coordinate(0, 80)));
    -}
    -
    -function testGetSize() {
    -  assertObjectEquals(new goog.math.Size(60, 80),
    -                     new goog.math.Rect(20, 40, 60, 80).getSize());
    -}
    -
    -function testGetBottomRight() {
    -  assertObjectEquals(new goog.math.Coordinate(40, 60),
    -                     new goog.math.Rect(10, 20, 30, 40).getBottomRight());
    -}
    -
    -function testGetCenter() {
    -  assertObjectEquals(new goog.math.Coordinate(25, 40),
    -                     new goog.math.Rect(10, 20, 30, 40).getCenter());
    -}
    -
    -function testGetTopLeft() {
    -  assertObjectEquals(new goog.math.Coordinate(10, 20),
    -                     new goog.math.Rect(10, 20, 30, 40).getTopLeft());
    -}
    -
    -function testRectCeil() {
    -  var rect = new goog.math.Rect(11.4, 26.6, 17.8, 9.2);
    -  assertEquals('The function should return the target instance',
    -      rect, rect.ceil());
    -  assertRectsEqual(new goog.math.Rect(12, 27, 18, 10), rect);
    -}
    -
    -function testRectFloor() {
    -  var rect = new goog.math.Rect(11.4, 26.6, 17.8, 9.2);
    -  assertEquals('The function should return the target instance',
    -      rect, rect.floor());
    -  assertRectsEqual(new goog.math.Rect(11, 26, 17, 9), rect);
    -}
    -
    -function testRectRound() {
    -  var rect = new goog.math.Rect(11.4, 26.6, 17.8, 9.2);
    -  assertEquals('The function should return the target instance',
    -      rect, rect.round());
    -  assertRectsEqual(new goog.math.Rect(11, 27, 18, 9), rect);
    -}
    -
    -function testRectTranslateCoordinate() {
    -  var rect = new goog.math.Rect(10, 40, 30, 20);
    -  var c = new goog.math.Coordinate(10, 5);
    -  assertEquals('The function should return the target instance',
    -      rect, rect.translate(c));
    -  assertRectsEqual(new goog.math.Rect(20, 45, 30, 20), rect);
    -}
    -
    -function testRectTranslateXY() {
    -  var rect = new goog.math.Rect(10, 20, 40, 35);
    -  assertEquals('The function should return the target instance',
    -      rect, rect.translate(15, 10));
    -  assertRectsEqual(new goog.math.Rect(25, 30, 40, 35), rect);
    -}
    -
    -function testRectTranslateX() {
    -  var rect = new goog.math.Rect(12, 34, 113, 88);
    -  assertEquals('The function should return the target instance',
    -      rect, rect.translate(10));
    -  assertRectsEqual(new goog.math.Rect(22, 34, 113, 88), rect);
    -}
    -
    -function testRectScaleXY() {
    -  var rect = new goog.math.Rect(10, 30, 100, 60);
    -  assertEquals('The function should return the target instance',
    -      rect, rect.scale(2, 5));
    -  assertRectsEqual(new goog.math.Rect(20, 150, 200, 300), rect);
    -}
    -
    -function testRectScaleFactor() {
    -  var rect = new goog.math.Rect(12, 34, 113, 88);
    -  assertEquals('The function should return the target instance',
    -      rect, rect.scale(10));
    -  assertRectsEqual(new goog.math.Rect(120, 340, 1130, 880), rect);
    -}
    -
    -function testSquaredDistance() {
    -  var rect = new goog.math.Rect(-10, -20, 15, 25);
    -
    -  // Test regions:
    -  // 1  2  3
    -  //   +-+
    -  // 4 |5| 6
    -  //   +-+
    -  // 7  8  9
    -
    -  // Region 5 (inside the rectangle).
    -  assertEquals(0, rect.squaredDistance(new goog.math.Coordinate(-10, 5)));
    -  assertEquals(0, rect.squaredDistance(new goog.math.Coordinate(5, -20)));
    -
    -  // 1, 2, and 3.
    -  assertEquals(25, rect.squaredDistance(new goog.math.Coordinate(9, 8)));
    -  assertEquals(36, rect.squaredDistance(new goog.math.Coordinate(2, 11)));
    -  assertEquals(53, rect.squaredDistance(new goog.math.Coordinate(12, 7)));
    -
    -  // 4 and 6.
    -  assertEquals(81, rect.squaredDistance(new goog.math.Coordinate(-19, -10)));
    -  assertEquals(64, rect.squaredDistance(new goog.math.Coordinate(13, 0)));
    -
    -  // 7, 8, and 9.
    -  assertEquals(20, rect.squaredDistance(new goog.math.Coordinate(-12, -24)));
    -  assertEquals(9, rect.squaredDistance(new goog.math.Coordinate(0, -23)));
    -  assertEquals(34, rect.squaredDistance(new goog.math.Coordinate(8, -25)));
    -}
    -
    -
    -function testDistance() {
    -  var rect = new goog.math.Rect(2, 4, 8, 16);
    -
    -  // Region 5 (inside the rectangle).
    -  assertEquals(0, rect.distance(new goog.math.Coordinate(2, 4)));
    -  assertEquals(0, rect.distance(new goog.math.Coordinate(10, 20)));
    -
    -  // 1, 2, and 3.
    -  assertRoughlyEquals(
    -      Math.sqrt(8), rect.distance(new goog.math.Coordinate(0, 22)), .0001);
    -  assertEquals(8, rect.distance(new goog.math.Coordinate(9, 28)));
    -  assertRoughlyEquals(
    -      Math.sqrt(50), rect.distance(new goog.math.Coordinate(15, 25)), .0001);
    -
    -  // 4 and 6.
    -  assertEquals(7, rect.distance(new goog.math.Coordinate(-5, 6)));
    -  assertEquals(10, rect.distance(new goog.math.Coordinate(20, 10)));
    -
    -  // 7, 8, and 9.
    -  assertEquals(5, rect.distance(new goog.math.Coordinate(-2, 1)));
    -  assertEquals(2, rect.distance(new goog.math.Coordinate(5, 2)));
    -  assertRoughlyEquals(
    -      Math.sqrt(10), rect.distance(new goog.math.Coordinate(1, 1)), .0001);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/math/size.js b/src/database/third_party/closure-library/closure/goog/math/size.js
    deleted file mode 100644
    index f5c379b72b0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/size.js
    +++ /dev/null
    @@ -1,227 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A utility class for representing two-dimensional sizes.
    - * @author brenneman@google.com (Shawn Brenneman)
    - */
    -
    -
    -goog.provide('goog.math.Size');
    -
    -
    -
    -/**
    - * Class for representing sizes consisting of a width and height. Undefined
    - * width and height support is deprecated and results in compiler warning.
    - * @param {number} width Width.
    - * @param {number} height Height.
    - * @struct
    - * @constructor
    - */
    -goog.math.Size = function(width, height) {
    -  /**
    -   * Width
    -   * @type {number}
    -   */
    -  this.width = width;
    -
    -  /**
    -   * Height
    -   * @type {number}
    -   */
    -  this.height = height;
    -};
    -
    -
    -/**
    - * Compares sizes for equality.
    - * @param {goog.math.Size} a A Size.
    - * @param {goog.math.Size} b A Size.
    - * @return {boolean} True iff the sizes have equal widths and equal
    - *     heights, or if both are null.
    - */
    -goog.math.Size.equals = function(a, b) {
    -  if (a == b) {
    -    return true;
    -  }
    -  if (!a || !b) {
    -    return false;
    -  }
    -  return a.width == b.width && a.height == b.height;
    -};
    -
    -
    -/**
    - * @return {!goog.math.Size} A new copy of the Size.
    - */
    -goog.math.Size.prototype.clone = function() {
    -  return new goog.math.Size(this.width, this.height);
    -};
    -
    -
    -if (goog.DEBUG) {
    -  /**
    -   * Returns a nice string representing size.
    -   * @return {string} In the form (50 x 73).
    -   * @override
    -   */
    -  goog.math.Size.prototype.toString = function() {
    -    return '(' + this.width + ' x ' + this.height + ')';
    -  };
    -}
    -
    -
    -/**
    - * @return {number} The longer of the two dimensions in the size.
    - */
    -goog.math.Size.prototype.getLongest = function() {
    -  return Math.max(this.width, this.height);
    -};
    -
    -
    -/**
    - * @return {number} The shorter of the two dimensions in the size.
    - */
    -goog.math.Size.prototype.getShortest = function() {
    -  return Math.min(this.width, this.height);
    -};
    -
    -
    -/**
    - * @return {number} The area of the size (width * height).
    - */
    -goog.math.Size.prototype.area = function() {
    -  return this.width * this.height;
    -};
    -
    -
    -/**
    - * @return {number} The perimeter of the size (width + height) * 2.
    - */
    -goog.math.Size.prototype.perimeter = function() {
    -  return (this.width + this.height) * 2;
    -};
    -
    -
    -/**
    - * @return {number} The ratio of the size's width to its height.
    - */
    -goog.math.Size.prototype.aspectRatio = function() {
    -  return this.width / this.height;
    -};
    -
    -
    -/**
    - * @return {boolean} True if the size has zero area, false if both dimensions
    - *     are non-zero numbers.
    - */
    -goog.math.Size.prototype.isEmpty = function() {
    -  return !this.area();
    -};
    -
    -
    -/**
    - * Clamps the width and height parameters upward to integer values.
    - * @return {!goog.math.Size} This size with ceil'd components.
    - */
    -goog.math.Size.prototype.ceil = function() {
    -  this.width = Math.ceil(this.width);
    -  this.height = Math.ceil(this.height);
    -  return this;
    -};
    -
    -
    -/**
    - * @param {!goog.math.Size} target The target size.
    - * @return {boolean} True if this Size is the same size or smaller than the
    - *     target size in both dimensions.
    - */
    -goog.math.Size.prototype.fitsInside = function(target) {
    -  return this.width <= target.width && this.height <= target.height;
    -};
    -
    -
    -/**
    - * Clamps the width and height parameters downward to integer values.
    - * @return {!goog.math.Size} This size with floored components.
    - */
    -goog.math.Size.prototype.floor = function() {
    -  this.width = Math.floor(this.width);
    -  this.height = Math.floor(this.height);
    -  return this;
    -};
    -
    -
    -/**
    - * Rounds the width and height parameters to integer values.
    - * @return {!goog.math.Size} This size with rounded components.
    - */
    -goog.math.Size.prototype.round = function() {
    -  this.width = Math.round(this.width);
    -  this.height = Math.round(this.height);
    -  return this;
    -};
    -
    -
    -/**
    - * Scales this size by the given scale factors. The width and height are scaled
    - * by {@code sx} and {@code opt_sy} respectively.  If {@code opt_sy} is not
    - * given, then {@code sx} is used for both the width and height.
    - * @param {number} sx The scale factor to use for the width.
    - * @param {number=} opt_sy The scale factor to use for the height.
    - * @return {!goog.math.Size} This Size object after scaling.
    - */
    -goog.math.Size.prototype.scale = function(sx, opt_sy) {
    -  var sy = goog.isNumber(opt_sy) ? opt_sy : sx;
    -  this.width *= sx;
    -  this.height *= sy;
    -  return this;
    -};
    -
    -
    -/**
    - * Uniformly scales the size to perfectly cover the dimensions of a given size.
    - * If the size is already larger than the target, it will be scaled down to the
    - * minimum size at which it still covers the entire target. The original aspect
    - * ratio will be preserved.
    - *
    - * This function assumes that both Sizes contain strictly positive dimensions.
    - * @param {!goog.math.Size} target The target size.
    - * @return {!goog.math.Size} This Size object, after optional scaling.
    - */
    -goog.math.Size.prototype.scaleToCover = function(target) {
    -  var s = this.aspectRatio() <= target.aspectRatio() ?
    -      target.width / this.width :
    -      target.height / this.height;
    -
    -  return this.scale(s);
    -};
    -
    -
    -/**
    - * Uniformly scales the size to fit inside the dimensions of a given size. The
    - * original aspect ratio will be preserved.
    - *
    - * This function assumes that both Sizes contain strictly positive dimensions.
    - * @param {!goog.math.Size} target The target size.
    - * @return {!goog.math.Size} This Size object, after optional scaling.
    - */
    -goog.math.Size.prototype.scaleToFit = function(target) {
    -  var s = this.aspectRatio() > target.aspectRatio() ?
    -      target.width / this.width :
    -      target.height / this.height;
    -
    -  return this.scale(s);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/math/size_test.html b/src/database/third_party/closure-library/closure/goog/math/size_test.html
    deleted file mode 100644
    index 209ce840c2e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/size_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.math.Size
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.math.SizeTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/math/size_test.js b/src/database/third_party/closure-library/closure/goog/math/size_test.js
    deleted file mode 100644
    index 04b4d20e798..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/size_test.js
    +++ /dev/null
    @@ -1,192 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.math.SizeTest');
    -goog.setTestOnly('goog.math.SizeTest');
    -
    -goog.require('goog.math.Size');
    -goog.require('goog.testing.jsunit');
    -
    -function testSize1() {
    -  var s = new goog.math.Size(undefined, undefined);
    -  assertUndefined(s.width);
    -  assertUndefined(s.height);
    -  assertEquals('(undefined x undefined)', s.toString());
    -}
    -
    -function testSize3() {
    -  var s = new goog.math.Size(10, 20);
    -  assertEquals(10, s.width);
    -  assertEquals(20, s.height);
    -  assertEquals('(10 x 20)', s.toString());
    -}
    -
    -function testSize4() {
    -  var s = new goog.math.Size(10.5, 20.897);
    -  assertEquals(10.5, s.width);
    -  assertEquals(20.897, s.height);
    -  assertEquals('(10.5 x 20.897)', s.toString());
    -}
    -
    -function testSizeClone() {
    -  var s = new goog.math.Size(undefined, undefined);
    -  assertEquals(s.toString(), s.clone().toString());
    -  s.width = 4;
    -  s.height = 5;
    -  assertEquals(s.toString(), s.clone().toString());
    -}
    -
    -function testSizeEquals() {
    -  var a = new goog.math.Size(4, 5);
    -
    -  assertTrue(goog.math.Size.equals(a, a));
    -  assertFalse(goog.math.Size.equals(a, null));
    -  assertFalse(goog.math.Size.equals(null, a));
    -
    -  var b = new goog.math.Size(4, 5);
    -  var c = new goog.math.Size(4, 6);
    -  assertTrue(goog.math.Size.equals(a, b));
    -  assertFalse(goog.math.Size.equals(a, c));
    -}
    -
    -function testSizeArea() {
    -  var s = new goog.math.Size(4, 5);
    -  assertEquals(20, s.area());
    -}
    -
    -function testSizePerimeter() {
    -  var s = new goog.math.Size(4, 5);
    -  assertEquals(18, s.perimeter());
    -}
    -
    -function testSizeAspectRatio() {
    -  var s = new goog.math.Size(undefined, undefined);
    -  assertNaN(s.aspectRatio());
    -
    -  s.width = 4;
    -  s.height = 0;
    -  assertEquals(Infinity, s.aspectRatio());
    -
    -  s.height = 5;
    -  assertEquals(0.8, s.aspectRatio());
    -}
    -
    -function testSizeFitsInside() {
    -  var target = new goog.math.Size(10, 10);
    -
    -  var a = new goog.math.Size(5, 8);
    -  var b = new goog.math.Size(5, 12);
    -  var c = new goog.math.Size(19, 7);
    -
    -
    -  assertTrue(a.fitsInside(target));
    -  assertFalse(b.fitsInside(target));
    -  assertFalse(c.fitsInside(target));
    -}
    -
    -function testSizeScaleToCover() {
    -  var target = new goog.math.Size(512, 640);
    -
    -  var a = new goog.math.Size(1000, 1600);
    -  var b = new goog.math.Size(1600, 1000);
    -  var c = new goog.math.Size(500, 800);
    -  var d = new goog.math.Size(undefined, undefined);
    -
    -  assertEquals('(512 x 819.2)', a.scaleToCover(target).toString());
    -  assertEquals('(1024 x 640)', b.scaleToCover(target).toString());
    -  assertEquals('(512 x 819.2)', c.scaleToCover(target).toString());
    -  assertEquals('(512 x 640)', target.scaleToCover(target).toString());
    -
    -  assertEquals('(NaN x NaN)', d.scaleToCover(target).toString());
    -  assertEquals('(NaN x NaN)', a.scaleToCover(d).toString());
    -}
    -
    -function testSizeScaleToFit() {
    -  var target = new goog.math.Size(512, 640);
    -
    -  var a = new goog.math.Size(1600, 1200);
    -  var b = new goog.math.Size(1200, 1600);
    -  var c = new goog.math.Size(400, 300);
    -  var d = new goog.math.Size(undefined, undefined);
    -
    -  assertEquals('(512 x 384)', a.scaleToFit(target).toString());
    -  assertEquals('(480 x 640)', b.scaleToFit(target).toString());
    -  assertEquals('(512 x 384)', c.scaleToFit(target).toString());
    -  assertEquals('(512 x 640)', target.scaleToFit(target).toString());
    -
    -  assertEquals('(NaN x NaN)', d.scaleToFit(target).toString());
    -  assertEquals('(NaN x NaN)', a.scaleToFit(d).toString());
    -}
    -
    -function testSizeIsEmpty() {
    -  var s = new goog.math.Size(undefined, undefined);
    -  assertTrue(s.isEmpty());
    -  s.width = 0;
    -  s.height = 5;
    -  assertTrue(s.isEmpty());
    -  s.width = 4;
    -  assertFalse(s.isEmpty());
    -}
    -
    -function testSizeScaleFactor() {
    -  var s = new goog.math.Size(4, 5);
    -  assertEquals('(8 x 10)', s.scale(2).toString());
    -  assertEquals('(0.8 x 1)', s.scale(0.1).toString());
    -}
    -
    -function testSizeCeil() {
    -  var s = new goog.math.Size(2.3, 4.7);
    -  assertEquals('(3 x 5)', s.ceil().toString());
    -}
    -
    -function testSizeFloor() {
    -  var s = new goog.math.Size(2.3, 4.7);
    -  assertEquals('(2 x 4)', s.floor().toString());
    -}
    -
    -function testSizeRound() {
    -  var s = new goog.math.Size(2.3, 4.7);
    -  assertEquals('(2 x 5)', s.round().toString());
    -}
    -
    -function testSizeGetLongest() {
    -  var s = new goog.math.Size(3, 4);
    -  assertEquals(4, s.getLongest());
    -
    -  s.height = 3;
    -  assertEquals(3, s.getLongest());
    -
    -  s.height = 2;
    -  assertEquals(3, s.getLongest());
    -
    -  assertNaN(new goog.math.Size(undefined, undefined).getLongest());
    -}
    -
    -function testSizeGetShortest() {
    -  var s = new goog.math.Size(3, 4);
    -  assertEquals(3, s.getShortest());
    -
    -  s.height = 3;
    -  assertEquals(3, s.getShortest());
    -
    -  s.height = 2;
    -  assertEquals(2, s.getShortest());
    -
    -  assertNaN(new goog.math.Size(undefined, undefined).getShortest());
    -}
    -
    -function testSizeScaleXY() {
    -  var s = new goog.math.Size(5, 10);
    -  assertEquals('(20 x 30)', s.scale(4, 3).toString());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/math/tdma.js b/src/database/third_party/closure-library/closure/goog/math/tdma.js
    deleted file mode 100644
    index 6f2f5e81155..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/tdma.js
    +++ /dev/null
    @@ -1,73 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview The Tridiagonal matrix algorithm solver solves a special
    - * version of a sparse linear system Ax = b where A is tridiagonal.
    - *
    - * See http://en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm
    - *
    - */
    -
    -goog.provide('goog.math.tdma');
    -
    -
    -/**
    - * Solves a linear system where the matrix is square tri-diagonal. That is,
    - * given a system of equations:
    - *
    - * A * result = vecRight,
    - *
    - * this class computes result = inv(A) * vecRight, where A has the special form
    - * of a tri-diagonal matrix:
    - *
    - *    |dia(0) sup(0)   0    0     ...   0|
    - *    |sub(0) dia(1) sup(1) 0     ...   0|
    - * A =|                ...               |
    - *    |0 ... 0 sub(n-2) dia(n-1) sup(n-1)|
    - *    |0 ... 0    0     sub(n-1)   dia(n)|
    - *
    - * @param {!Array<number>} subDiag The sub diagonal of the matrix.
    - * @param {!Array<number>} mainDiag The main diagonal of the matrix.
    - * @param {!Array<number>} supDiag The super diagonal of the matrix.
    - * @param {!Array<number>} vecRight The right vector of the system
    - *     of equations.
    - * @param {Array<number>=} opt_result The optional array to store the result.
    - * @return {!Array<number>} The vector that is the solution to the system.
    - */
    -goog.math.tdma.solve = function(
    -    subDiag, mainDiag, supDiag, vecRight, opt_result) {
    -  // Make a local copy of the main diagonal and the right vector.
    -  mainDiag = mainDiag.slice();
    -  vecRight = vecRight.slice();
    -
    -  // The dimension of the matrix.
    -  var nDim = mainDiag.length;
    -
    -  // Construct a modified linear system of equations with the same solution
    -  // as the input one.
    -  for (var i = 1; i < nDim; ++i) {
    -    var m = subDiag[i - 1] / mainDiag[i - 1];
    -    mainDiag[i] = mainDiag[i] - m * supDiag[i - 1];
    -    vecRight[i] = vecRight[i] - m * vecRight[i - 1];
    -  }
    -
    -  // Solve the new system of equations by simple back-substitution.
    -  var result = opt_result || new Array(vecRight.length);
    -  result[nDim - 1] = vecRight[nDim - 1] / mainDiag[nDim - 1];
    -  for (i = nDim - 2; i >= 0; --i) {
    -    result[i] = (vecRight[i] - supDiag[i] * result[i + 1]) / mainDiag[i];
    -  }
    -  return result;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/math/tdma_test.html b/src/database/third_party/closure-library/closure/goog/math/tdma_test.html
    deleted file mode 100644
    index 3b7131b97a8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/tdma_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.math.tdma
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.math.tdmaTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/math/tdma_test.js b/src/database/third_party/closure-library/closure/goog/math/tdma_test.js
    deleted file mode 100644
    index 5338980b54b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/tdma_test.js
    +++ /dev/null
    @@ -1,30 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.math.tdmaTest');
    -goog.setTestOnly('goog.math.tdmaTest');
    -
    -goog.require('goog.math.tdma');
    -goog.require('goog.testing.jsunit');
    -
    -function testTdmaSolver() {
    -  var supDiag = [1, 1, 1, 1, 1];
    -  var mainDiag = [-1, -2, -2, -2, -2, -2];
    -  var subDiag = [1, 1, 1, 1, 1];
    -  var vecRight = [1, 2, 3, 4, 5, 6];
    -  var expected = [-56, -55, -52, -46, -36, -21];
    -  var result = [];
    -  goog.math.tdma.solve(subDiag, mainDiag, supDiag, vecRight, result);
    -  assertElementsEquals(expected, result);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/math/vec2.js b/src/database/third_party/closure-library/closure/goog/math/vec2.js
    deleted file mode 100644
    index 9b47a3a5927..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/vec2.js
    +++ /dev/null
    @@ -1,284 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Defines a 2-element vector class that can be used for
    - * coordinate math, useful for animation systems and point manipulation.
    - *
    - * Vec2 objects inherit from goog.math.Coordinate and may be used wherever a
    - * Coordinate is required. Where appropriate, Vec2 functions accept both Vec2
    - * and Coordinate objects as input.
    - *
    - * @author brenneman@google.com (Shawn Brenneman)
    - */
    -
    -goog.provide('goog.math.Vec2');
    -
    -goog.require('goog.math');
    -goog.require('goog.math.Coordinate');
    -
    -
    -
    -/**
    - * Class for a two-dimensional vector object and assorted functions useful for
    - * manipulating points.
    - *
    - * @param {number} x The x coordinate for the vector.
    - * @param {number} y The y coordinate for the vector.
    - * @struct
    - * @constructor
    - * @extends {goog.math.Coordinate}
    - */
    -goog.math.Vec2 = function(x, y) {
    -  /**
    -   * X-value
    -   * @type {number}
    -   */
    -  this.x = x;
    -
    -  /**
    -   * Y-value
    -   * @type {number}
    -   */
    -  this.y = y;
    -};
    -goog.inherits(goog.math.Vec2, goog.math.Coordinate);
    -
    -
    -/**
    - * @return {!goog.math.Vec2} A random unit-length vector.
    - */
    -goog.math.Vec2.randomUnit = function() {
    -  var angle = Math.random() * Math.PI * 2;
    -  return new goog.math.Vec2(Math.cos(angle), Math.sin(angle));
    -};
    -
    -
    -/**
    - * @return {!goog.math.Vec2} A random vector inside the unit-disc.
    - */
    -goog.math.Vec2.random = function() {
    -  var mag = Math.sqrt(Math.random());
    -  var angle = Math.random() * Math.PI * 2;
    -
    -  return new goog.math.Vec2(Math.cos(angle) * mag, Math.sin(angle) * mag);
    -};
    -
    -
    -/**
    - * Returns a new Vec2 object from a given coordinate.
    - * @param {!goog.math.Coordinate} a The coordinate.
    - * @return {!goog.math.Vec2} A new vector object.
    - */
    -goog.math.Vec2.fromCoordinate = function(a) {
    -  return new goog.math.Vec2(a.x, a.y);
    -};
    -
    -
    -/**
    - * @return {!goog.math.Vec2} A new vector with the same coordinates as this one.
    - * @override
    - */
    -goog.math.Vec2.prototype.clone = function() {
    -  return new goog.math.Vec2(this.x, this.y);
    -};
    -
    -
    -/**
    - * Returns the magnitude of the vector measured from the origin.
    - * @return {number} The length of the vector.
    - */
    -goog.math.Vec2.prototype.magnitude = function() {
    -  return Math.sqrt(this.x * this.x + this.y * this.y);
    -};
    -
    -
    -/**
    - * Returns the squared magnitude of the vector measured from the origin.
    - * NOTE(brenneman): Leaving out the square root is not a significant
    - * optimization in JavaScript.
    - * @return {number} The length of the vector, squared.
    - */
    -goog.math.Vec2.prototype.squaredMagnitude = function() {
    -  return this.x * this.x + this.y * this.y;
    -};
    -
    -
    -/**
    - * @return {!goog.math.Vec2} This coordinate after scaling.
    - * @override
    - */
    -goog.math.Vec2.prototype.scale =
    -    /** @type {function(number, number=):!goog.math.Vec2} */
    -    (goog.math.Coordinate.prototype.scale);
    -
    -
    -/**
    - * Reverses the sign of the vector. Equivalent to scaling the vector by -1.
    - * @return {!goog.math.Vec2} The inverted vector.
    - */
    -goog.math.Vec2.prototype.invert = function() {
    -  this.x = -this.x;
    -  this.y = -this.y;
    -  return this;
    -};
    -
    -
    -/**
    - * Normalizes the current vector to have a magnitude of 1.
    - * @return {!goog.math.Vec2} The normalized vector.
    - */
    -goog.math.Vec2.prototype.normalize = function() {
    -  return this.scale(1 / this.magnitude());
    -};
    -
    -
    -/**
    - * Adds another vector to this vector in-place.
    - * @param {!goog.math.Coordinate} b The vector to add.
    - * @return {!goog.math.Vec2}  This vector with {@code b} added.
    - */
    -goog.math.Vec2.prototype.add = function(b) {
    -  this.x += b.x;
    -  this.y += b.y;
    -  return this;
    -};
    -
    -
    -/**
    - * Subtracts another vector from this vector in-place.
    - * @param {!goog.math.Coordinate} b The vector to subtract.
    - * @return {!goog.math.Vec2} This vector with {@code b} subtracted.
    - */
    -goog.math.Vec2.prototype.subtract = function(b) {
    -  this.x -= b.x;
    -  this.y -= b.y;
    -  return this;
    -};
    -
    -
    -/**
    - * Rotates this vector in-place by a given angle, specified in radians.
    - * @param {number} angle The angle, in radians.
    - * @return {!goog.math.Vec2} This vector rotated {@code angle} radians.
    - */
    -goog.math.Vec2.prototype.rotate = function(angle) {
    -  var cos = Math.cos(angle);
    -  var sin = Math.sin(angle);
    -  var newX = this.x * cos - this.y * sin;
    -  var newY = this.y * cos + this.x * sin;
    -  this.x = newX;
    -  this.y = newY;
    -  return this;
    -};
    -
    -
    -/**
    - * Rotates a vector by a given angle, specified in radians, relative to a given
    - * axis rotation point. The returned vector is a newly created instance - no
    - * in-place changes are done.
    - * @param {!goog.math.Vec2} v A vector.
    - * @param {!goog.math.Vec2} axisPoint The rotation axis point.
    - * @param {number} angle The angle, in radians.
    - * @return {!goog.math.Vec2} The rotated vector in a newly created instance.
    - */
    -goog.math.Vec2.rotateAroundPoint = function(v, axisPoint, angle) {
    -  var res = v.clone();
    -  return res.subtract(axisPoint).rotate(angle).add(axisPoint);
    -};
    -
    -
    -/**
    - * Compares this vector with another for equality.
    - * @param {!goog.math.Vec2} b The other vector.
    - * @return {boolean} Whether this vector has the same x and y as the given
    - *     vector.
    - */
    -goog.math.Vec2.prototype.equals = function(b) {
    -  return this == b || !!b && this.x == b.x && this.y == b.y;
    -};
    -
    -
    -/**
    - * Returns the distance between two vectors.
    - * @param {!goog.math.Coordinate} a The first vector.
    - * @param {!goog.math.Coordinate} b The second vector.
    - * @return {number} The distance.
    - */
    -goog.math.Vec2.distance = goog.math.Coordinate.distance;
    -
    -
    -/**
    - * Returns the squared distance between two vectors.
    - * @param {!goog.math.Coordinate} a The first vector.
    - * @param {!goog.math.Coordinate} b The second vector.
    - * @return {number} The squared distance.
    - */
    -goog.math.Vec2.squaredDistance = goog.math.Coordinate.squaredDistance;
    -
    -
    -/**
    - * Compares vectors for equality.
    - * @param {!goog.math.Coordinate} a The first vector.
    - * @param {!goog.math.Coordinate} b The second vector.
    - * @return {boolean} Whether the vectors have the same x and y coordinates.
    - */
    -goog.math.Vec2.equals = goog.math.Coordinate.equals;
    -
    -
    -/**
    - * Returns the sum of two vectors as a new Vec2.
    - * @param {!goog.math.Coordinate} a The first vector.
    - * @param {!goog.math.Coordinate} b The second vector.
    - * @return {!goog.math.Vec2} The sum vector.
    - */
    -goog.math.Vec2.sum = function(a, b) {
    -  return new goog.math.Vec2(a.x + b.x, a.y + b.y);
    -};
    -
    -
    -/**
    - * Returns the difference between two vectors as a new Vec2.
    - * @param {!goog.math.Coordinate} a The first vector.
    - * @param {!goog.math.Coordinate} b The second vector.
    - * @return {!goog.math.Vec2} The difference vector.
    - */
    -goog.math.Vec2.difference = function(a, b) {
    -  return new goog.math.Vec2(a.x - b.x, a.y - b.y);
    -};
    -
    -
    -/**
    - * Returns the dot-product of two vectors.
    - * @param {!goog.math.Coordinate} a The first vector.
    - * @param {!goog.math.Coordinate} b The second vector.
    - * @return {number} The dot-product of the two vectors.
    - */
    -goog.math.Vec2.dot = function(a, b) {
    -  return a.x * b.x + a.y * b.y;
    -};
    -
    -
    -/**
    - * Returns a new Vec2 that is the linear interpolant between vectors a and b at
    - * scale-value x.
    - * @param {!goog.math.Coordinate} a Vector a.
    - * @param {!goog.math.Coordinate} b Vector b.
    - * @param {number} x The proportion between a and b.
    - * @return {!goog.math.Vec2} The interpolated vector.
    - */
    -goog.math.Vec2.lerp = function(a, b, x) {
    -  return new goog.math.Vec2(goog.math.lerp(a.x, b.x, x),
    -                            goog.math.lerp(a.y, b.y, x));
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/math/vec2_test.html b/src/database/third_party/closure-library/closure/goog/math/vec2_test.html
    deleted file mode 100644
    index c9ff08a0489..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/vec2_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.math.Vec2
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.math.Vec2Test');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/math/vec2_test.js b/src/database/third_party/closure-library/closure/goog/math/vec2_test.js
    deleted file mode 100644
    index 571e716387d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/vec2_test.js
    +++ /dev/null
    @@ -1,220 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.math.Vec2Test');
    -goog.setTestOnly('goog.math.Vec2Test');
    -
    -goog.require('goog.math.Vec2');
    -goog.require('goog.testing.jsunit');
    -
    -function assertVectorEquals(a, b) {
    -  assertTrue(b + ' should be equal to ' + a, goog.math.Vec2.equals(a, b));
    -}
    -
    -
    -function testVec2() {
    -  var v = new goog.math.Vec2(3.14, 2.78);
    -  assertEquals(3.14, v.x);
    -  assertEquals(2.78, v.y);
    -}
    -
    -
    -function testRandomUnit() {
    -  var a = goog.math.Vec2.randomUnit();
    -  assertRoughlyEquals(1.0, a.magnitude(), 1e-10);
    -}
    -
    -
    -function testRandom() {
    -  var a = goog.math.Vec2.random();
    -  assertTrue(a.magnitude() <= 1.0);
    -}
    -
    -
    -function testClone() {
    -  var a = new goog.math.Vec2(1, 2);
    -  var b = a.clone();
    -
    -  assertEquals(a.x, b.x);
    -  assertEquals(a.y, b.y);
    -}
    -
    -
    -function testMagnitude() {
    -  var a = new goog.math.Vec2(0, 10);
    -  var b = new goog.math.Vec2(3, 4);
    -
    -  assertEquals(10, a.magnitude());
    -  assertEquals(5, b.magnitude());
    -}
    -
    -
    -function testSquaredMagnitude() {
    -  var a = new goog.math.Vec2(-3, -4);
    -  assertEquals(25, a.squaredMagnitude());
    -}
    -
    -
    -function testScaleFactor() {
    -  var a = new goog.math.Vec2(1, 2);
    -  var scaled = a.scale(0.5);
    -
    -  assertTrue('The type of the return value should be goog.math.Vec2',
    -      scaled instanceof goog.math.Vec2);
    -  assertVectorEquals(new goog.math.Vec2(0.5, 1), a);
    -}
    -
    -
    -function testScaleXY() {
    -  var a = new goog.math.Vec2(10, 15);
    -  var scaled = a.scale(2, 3);
    -  assertEquals('The function should return the target instance', a, scaled);
    -  assertTrue('The type of the return value should be goog.math.Vec2',
    -      scaled instanceof goog.math.Vec2);
    -  assertVectorEquals(new goog.math.Vec2(20, 45), a);
    -}
    -
    -
    -function testInvert() {
    -  var a = new goog.math.Vec2(3, 4);
    -  a.invert();
    -
    -  assertEquals(-3, a.x);
    -  assertEquals(-4, a.y);
    -}
    -
    -
    -function testNormalize() {
    -  var a = new goog.math.Vec2(5, 5);
    -  a.normalize();
    -  assertRoughlyEquals(1.0, a.magnitude(), 1e-10);
    -}
    -
    -
    -function testAdd() {
    -  var a = new goog.math.Vec2(1, -1);
    -  a.add(new goog.math.Vec2(3, 3));
    -  assertVectorEquals(new goog.math.Vec2(4, 2), a);
    -}
    -
    -
    -function testSubtract() {
    -  var a = new goog.math.Vec2(1, -1);
    -  a.subtract(new goog.math.Vec2(3, 3));
    -  assertVectorEquals(new goog.math.Vec2(-2, -4), a);
    -}
    -
    -
    -function testRotate() {
    -  var a = new goog.math.Vec2(1, -1);
    -  a.rotate(Math.PI / 2);
    -  assertRoughlyEquals(1, a.x, 0.000001);
    -  assertRoughlyEquals(1, a.y, 0.000001);
    -  a.rotate(-Math.PI);
    -  assertRoughlyEquals(-1, a.x, 0.000001);
    -  assertRoughlyEquals(-1, a.y, 0.000001);
    -}
    -
    -
    -function testRotateAroundPoint() {
    -  var a = goog.math.Vec2.rotateAroundPoint(
    -      new goog.math.Vec2(1, -1), new goog.math.Vec2(1, 0), Math.PI / 2);
    -  assertRoughlyEquals(2, a.x, 0.000001);
    -  assertRoughlyEquals(0, a.y, 0.000001);
    -}
    -
    -
    -function testEquals() {
    -  var a = new goog.math.Vec2(1, 2);
    -
    -  assertFalse(a.equals(null));
    -  assertFalse(a.equals(new goog.math.Vec2(1, 3)));
    -  assertFalse(a.equals(new goog.math.Vec2(2, 2)));
    -
    -  assertTrue(a.equals(a));
    -  assertTrue(a.equals(new goog.math.Vec2(1, 2)));
    -}
    -
    -
    -function testSum() {
    -  var a = new goog.math.Vec2(0.5, 0.25);
    -  var b = new goog.math.Vec2(0.5, 0.75);
    -
    -  var c = goog.math.Vec2.sum(a, b);
    -  assertVectorEquals(new goog.math.Vec2(1, 1), c);
    -}
    -
    -
    -function testDifference() {
    -  var a = new goog.math.Vec2(0.5, 0.25);
    -  var b = new goog.math.Vec2(0.5, 0.75);
    -
    -  var c = goog.math.Vec2.difference(a, b);
    -  assertVectorEquals(new goog.math.Vec2(0, -0.5), c);
    -}
    -
    -
    -function testDistance() {
    -  var a = new goog.math.Vec2(3, 4);
    -  var b = new goog.math.Vec2(-3, -4);
    -
    -  assertEquals(10, goog.math.Vec2.distance(a, b));
    -}
    -
    -
    -function testSquaredDistance() {
    -  var a = new goog.math.Vec2(3, 4);
    -  var b = new goog.math.Vec2(-3, -4);
    -
    -  assertEquals(100, goog.math.Vec2.squaredDistance(a, b));
    -}
    -
    -
    -function testVec2Equals() {
    -  assertTrue(goog.math.Vec2.equals(null, null));
    -  assertFalse(goog.math.Vec2.equals(null, new goog.math.Vec2()));
    -
    -  var a = new goog.math.Vec2(1, 3);
    -  assertTrue(goog.math.Vec2.equals(a, a));
    -  assertTrue(goog.math.Vec2.equals(a, new goog.math.Vec2(1, 3)));
    -  assertFalse(goog.math.Vec2.equals(1, new goog.math.Vec2(3, 1)));
    -}
    -
    -
    -function testDot() {
    -  var a = new goog.math.Vec2(0, 5);
    -  var b = new goog.math.Vec2(3, 0);
    -  assertEquals(0, goog.math.Vec2.dot(a, b));
    -
    -  var c = new goog.math.Vec2(-5, -5);
    -  var d = new goog.math.Vec2(0, 7);
    -  assertEquals(-35, goog.math.Vec2.dot(c, d));
    -}
    -
    -
    -function testLerp() {
    -  var a = new goog.math.Vec2(0, 0);
    -  var b = new goog.math.Vec2(10, 10);
    -
    -  for (var i = 0; i <= 10; i++) {
    -    var c = goog.math.Vec2.lerp(a, b, i / 10);
    -    assertEquals(i, c.x);
    -    assertEquals(i, c.y);
    -  }
    -}
    -
    -
    -function testToString() {
    -  testEquals('(0, 0)', new goog.math.Vec2(0, 0).toString());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/math/vec3.js b/src/database/third_party/closure-library/closure/goog/math/vec3.js
    deleted file mode 100644
    index 253a66f5c50..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/vec3.js
    +++ /dev/null
    @@ -1,310 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Defines a 3-element vector class that can be used for
    - * coordinate math, useful for animation systems and point manipulation.
    - *
    - * Based heavily on code originally by:
    - * @author brenneman@google.com (Shawn Brenneman)
    - */
    -
    -
    -goog.provide('goog.math.Vec3');
    -
    -goog.require('goog.math');
    -goog.require('goog.math.Coordinate3');
    -
    -
    -
    -/**
    - * Class for a three-dimensional vector object and assorted functions useful for
    - * manipulation.
    - *
    - * Inherits from goog.math.Coordinate3 so that a Vec3 may be passed in to any
    - * function that requires a Coordinate.
    - *
    - * @param {number} x The x value for the vector.
    - * @param {number} y The y value for the vector.
    - * @param {number} z The z value for the vector.
    - * @struct
    - * @constructor
    - * @extends {goog.math.Coordinate3}
    - */
    -goog.math.Vec3 = function(x, y, z) {
    -  /**
    -   * X-value
    -   * @type {number}
    -   */
    -  this.x = x;
    -
    -  /**
    -   * Y-value
    -   * @type {number}
    -   */
    -  this.y = y;
    -
    -  /**
    -   * Z-value
    -   * @type {number}
    -   */
    -  this.z = z;
    -};
    -goog.inherits(goog.math.Vec3, goog.math.Coordinate3);
    -
    -
    -/**
    - * Generates a random unit vector.
    - *
    - * http://mathworld.wolfram.com/SpherePointPicking.html
    - * Using (6), (7), and (8) to generate coordinates.
    - * @return {!goog.math.Vec3} A random unit-length vector.
    - */
    -goog.math.Vec3.randomUnit = function() {
    -  var theta = Math.random() * Math.PI * 2;
    -  var phi = Math.random() * Math.PI * 2;
    -
    -  var z = Math.cos(phi);
    -  var x = Math.sqrt(1 - z * z) * Math.cos(theta);
    -  var y = Math.sqrt(1 - z * z) * Math.sin(theta);
    -
    -  return new goog.math.Vec3(x, y, z);
    -};
    -
    -
    -/**
    - * Generates a random vector inside the unit sphere.
    - *
    - * @return {!goog.math.Vec3} A random vector.
    - */
    -goog.math.Vec3.random = function() {
    -  return goog.math.Vec3.randomUnit().scale(Math.random());
    -};
    -
    -
    -/**
    - * Returns a new Vec3 object from a given coordinate.
    - *
    - * @param {goog.math.Coordinate3} a The coordinate.
    - * @return {!goog.math.Vec3} A new vector object.
    - */
    -goog.math.Vec3.fromCoordinate3 = function(a) {
    -  return new goog.math.Vec3(a.x, a.y, a.z);
    -};
    -
    -
    -/**
    - * Creates a new copy of this Vec3.
    - *
    - * @return {!goog.math.Vec3} A new vector with the same coordinates as this one.
    - * @override
    - */
    -goog.math.Vec3.prototype.clone = function() {
    -  return new goog.math.Vec3(this.x, this.y, this.z);
    -};
    -
    -
    -/**
    - * Returns the magnitude of the vector measured from the origin.
    - *
    - * @return {number} The length of the vector.
    - */
    -goog.math.Vec3.prototype.magnitude = function() {
    -  return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
    -};
    -
    -
    -/**
    - * Returns the squared magnitude of the vector measured from the origin.
    - * NOTE(brenneman): Leaving out the square root is not a significant
    - * optimization in JavaScript.
    - *
    - * @return {number} The length of the vector, squared.
    - */
    -goog.math.Vec3.prototype.squaredMagnitude = function() {
    -  return this.x * this.x + this.y * this.y + this.z * this.z;
    -};
    -
    -
    -/**
    - * Scales the current vector by a constant.
    - *
    - * @param {number} s The scale factor.
    - * @return {!goog.math.Vec3} This vector, scaled.
    - */
    -goog.math.Vec3.prototype.scale = function(s) {
    -  this.x *= s;
    -  this.y *= s;
    -  this.z *= s;
    -  return this;
    -};
    -
    -
    -/**
    - * Reverses the sign of the vector. Equivalent to scaling the vector by -1.
    - *
    - * @return {!goog.math.Vec3} This vector, inverted.
    - */
    -goog.math.Vec3.prototype.invert = function() {
    -  this.x = -this.x;
    -  this.y = -this.y;
    -  this.z = -this.z;
    -  return this;
    -};
    -
    -
    -/**
    - * Normalizes the current vector to have a magnitude of 1.
    - *
    - * @return {!goog.math.Vec3} This vector, normalized.
    - */
    -goog.math.Vec3.prototype.normalize = function() {
    -  return this.scale(1 / this.magnitude());
    -};
    -
    -
    -/**
    - * Adds another vector to this vector in-place.
    - *
    - * @param {goog.math.Vec3} b The vector to add.
    - * @return {!goog.math.Vec3} This vector with {@code b} added.
    - */
    -goog.math.Vec3.prototype.add = function(b) {
    -  this.x += b.x;
    -  this.y += b.y;
    -  this.z += b.z;
    -  return this;
    -};
    -
    -
    -/**
    - * Subtracts another vector from this vector in-place.
    - *
    - * @param {goog.math.Vec3} b The vector to subtract.
    - * @return {!goog.math.Vec3} This vector with {@code b} subtracted.
    - */
    -goog.math.Vec3.prototype.subtract = function(b) {
    -  this.x -= b.x;
    -  this.y -= b.y;
    -  this.z -= b.z;
    -  return this;
    -};
    -
    -
    -/**
    - * Compares this vector with another for equality.
    - *
    - * @param {goog.math.Vec3} b The other vector.
    - * @return {boolean} True if this vector's x, y and z equal the given vector's
    - *     x, y, and z, respectively.
    - */
    -goog.math.Vec3.prototype.equals = function(b) {
    -  return this == b || !!b && this.x == b.x && this.y == b.y && this.z == b.z;
    -};
    -
    -
    -/**
    - * Returns the distance between two vectors.
    - *
    - * @param {goog.math.Vec3} a The first vector.
    - * @param {goog.math.Vec3} b The second vector.
    - * @return {number} The distance.
    - */
    -goog.math.Vec3.distance = goog.math.Coordinate3.distance;
    -
    -
    -/**
    - * Returns the squared distance between two vectors.
    - *
    - * @param {goog.math.Vec3} a The first vector.
    - * @param {goog.math.Vec3} b The second vector.
    - * @return {number} The squared distance.
    - */
    -goog.math.Vec3.squaredDistance = goog.math.Coordinate3.squaredDistance;
    -
    -
    -/**
    - * Compares vectors for equality.
    - *
    - * @param {goog.math.Vec3} a The first vector.
    - * @param {goog.math.Vec3} b The second vector.
    - * @return {boolean} True if the vectors have equal x, y, and z coordinates.
    - */
    -goog.math.Vec3.equals = goog.math.Coordinate3.equals;
    -
    -
    -/**
    - * Returns the sum of two vectors as a new Vec3.
    - *
    - * @param {goog.math.Vec3} a The first vector.
    - * @param {goog.math.Vec3} b The second vector.
    - * @return {!goog.math.Vec3} The sum vector.
    - */
    -goog.math.Vec3.sum = function(a, b) {
    -  return new goog.math.Vec3(a.x + b.x, a.y + b.y, a.z + b.z);
    -};
    -
    -
    -/**
    - * Returns the difference of two vectors as a new Vec3.
    - *
    - * @param {goog.math.Vec3} a The first vector.
    - * @param {goog.math.Vec3} b The second vector.
    - * @return {!goog.math.Vec3} The difference vector.
    - */
    -goog.math.Vec3.difference = function(a, b) {
    -  return new goog.math.Vec3(a.x - b.x, a.y - b.y, a.z - b.z);
    -};
    -
    -
    -/**
    - * Returns the dot-product of two vectors.
    - *
    - * @param {goog.math.Vec3} a The first vector.
    - * @param {goog.math.Vec3} b The second vector.
    - * @return {number} The dot-product of the two vectors.
    - */
    -goog.math.Vec3.dot = function(a, b) {
    -  return a.x * b.x + a.y * b.y + a.z * b.z;
    -};
    -
    -
    -/**
    - * Returns the cross-product of two vectors.
    - *
    - * @param {goog.math.Vec3} a The first vector.
    - * @param {goog.math.Vec3} b The second vector.
    - * @return {!goog.math.Vec3} The cross-product of the two vectors.
    - */
    -goog.math.Vec3.cross = function(a, b) {
    -  return new goog.math.Vec3(a.y * b.z - a.z * b.y,
    -                            a.z * b.x - a.x * b.z,
    -                            a.x * b.y - a.y * b.x);
    -};
    -
    -
    -/**
    - * Returns a new Vec3 that is the linear interpolant between vectors a and b at
    - * scale-value x.
    - *
    - * @param {goog.math.Vec3} a Vector a.
    - * @param {goog.math.Vec3} b Vector b.
    - * @param {number} x The proportion between a and b.
    - * @return {!goog.math.Vec3} The interpolated vector.
    - */
    -goog.math.Vec3.lerp = function(a, b, x) {
    -  return new goog.math.Vec3(goog.math.lerp(a.x, b.x, x),
    -                            goog.math.lerp(a.y, b.y, x),
    -                            goog.math.lerp(a.z, b.z, x));
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/math/vec3_test.html b/src/database/third_party/closure-library/closure/goog/math/vec3_test.html
    deleted file mode 100644
    index be3c632aaf2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/vec3_test.html
    +++ /dev/null
    @@ -1,26 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -
    -  Vec3 Unit Tests
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.math.Vec3
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.math.Vec3Test');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/math/vec3_test.js b/src/database/third_party/closure-library/closure/goog/math/vec3_test.js
    deleted file mode 100644
    index ce0216abb61..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/math/vec3_test.js
    +++ /dev/null
    @@ -1,212 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.math.Vec3Test');
    -goog.setTestOnly('goog.math.Vec3Test');
    -
    -goog.require('goog.math.Coordinate3');
    -goog.require('goog.math.Vec3');
    -goog.require('goog.testing.jsunit');
    -
    -function assertVec3Equals(a, b) {
    -  assertTrue(b + ' should be equal to ' + a, goog.math.Vec3.equals(a, b));
    -}
    -
    -function testVec3() {
    -  var v = new goog.math.Vec3(3.14, 2.78, -7.21);
    -  assertEquals(3.14, v.x);
    -  assertEquals(2.78, v.y);
    -  assertEquals(-7.21, v.z);
    -}
    -
    -
    -function testRandomUnit() {
    -  var a = goog.math.Vec3.randomUnit();
    -  assertRoughlyEquals(1.0, a.magnitude(), 1e-10);
    -}
    -
    -
    -function testRandom() {
    -  var a = goog.math.Vec3.random();
    -  assertTrue(a.magnitude() <= 1.0);
    -}
    -
    -
    -function testFromCoordinate3() {
    -  var a = new goog.math.Coordinate3(-2, 10, 4);
    -  var b = goog.math.Vec3.fromCoordinate3(a);
    -  assertEquals(-2, b.x);
    -  assertEquals(10, b.y);
    -  assertEquals(4, b.z);
    -}
    -
    -
    -function testClone() {
    -  var a = new goog.math.Vec3(1, 2, 5);
    -  var b = a.clone();
    -
    -  assertEquals(a.x, b.x);
    -  assertEquals(a.y, b.y);
    -  assertEquals(a.z, b.z);
    -}
    -
    -
    -function testMagnitude() {
    -  var a = new goog.math.Vec3(0, 10, 0);
    -  var b = new goog.math.Vec3(3, 4, 5);
    -  var c = new goog.math.Vec3(-4, 3, 8);
    -
    -  assertEquals(10, a.magnitude());
    -  assertEquals(Math.sqrt(50), b.magnitude());
    -  assertEquals(Math.sqrt(89), c.magnitude());
    -}
    -
    -
    -function testSquaredMagnitude() {
    -  var a = new goog.math.Vec3(-3, -4, -5);
    -  assertEquals(50, a.squaredMagnitude());
    -}
    -
    -
    -function testScale() {
    -  var a = new goog.math.Vec3(1, 2, 3);
    -  a.scale(0.5);
    -
    -  assertEquals(0.5, a.x);
    -  assertEquals(1, a.y);
    -  assertEquals(1.5, a.z);
    -}
    -
    -
    -function testInvert() {
    -  var a = new goog.math.Vec3(3, 4, 5);
    -  a.invert();
    -
    -  assertEquals(-3, a.x);
    -  assertEquals(-4, a.y);
    -  assertEquals(-5, a.z);
    -}
    -
    -
    -function testNormalize() {
    -  var a = new goog.math.Vec3(5, 5, 5);
    -  a.normalize();
    -  assertRoughlyEquals(1.0, a.magnitude(), 1e-10);
    -}
    -
    -
    -function testAdd() {
    -  var a = new goog.math.Vec3(1, -1, 7);
    -  a.add(new goog.math.Vec3(3, 3, 3));
    -  assertVec3Equals(new goog.math.Vec3(4, 2, 10), a);
    -}
    -
    -
    -function testSubtract() {
    -  var a = new goog.math.Vec3(1, -1, 4);
    -  a.subtract(new goog.math.Vec3(3, 3, 3));
    -  assertVec3Equals(new goog.math.Vec3(-2, -4, 1), a);
    -}
    -
    -
    -function testEquals() {
    -  var a = new goog.math.Vec3(1, 2, 5);
    -
    -  assertFalse(a.equals(null));
    -  assertFalse(a.equals(new goog.math.Vec3(1, 3, 5)));
    -  assertFalse(a.equals(new goog.math.Vec3(2, 2, 2)));
    -
    -  assertTrue(a.equals(a));
    -  assertTrue(a.equals(new goog.math.Vec3(1, 2, 5)));
    -}
    -
    -
    -function testSum() {
    -  var a = new goog.math.Vec3(0.5, 0.25, 1.2);
    -  var b = new goog.math.Vec3(0.5, 0.75, -0.6);
    -
    -  var c = goog.math.Vec3.sum(a, b);
    -  assertVec3Equals(new goog.math.Vec3(1, 1, 0.6), c);
    -}
    -
    -
    -function testDifference() {
    -  var a = new goog.math.Vec3(0.5, 0.25, 3);
    -  var b = new goog.math.Vec3(0.5, 0.75, 5);
    -
    -  var c = goog.math.Vec3.difference(a, b);
    -  assertVec3Equals(new goog.math.Vec3(0, -0.5, -2), c);
    -}
    -
    -
    -function testDistance() {
    -  var a = new goog.math.Vec3(3, 4, 5);
    -  var b = new goog.math.Vec3(-3, -4, 5);
    -
    -  assertEquals(10, goog.math.Vec3.distance(a, b));
    -}
    -
    -
    -function testSquaredDistance() {
    -  var a = new goog.math.Vec3(3, 4, 5);
    -  var b = new goog.math.Vec3(-3, -4, 5);
    -
    -  assertEquals(100, goog.math.Vec3.squaredDistance(a, b));
    -}
    -
    -
    -function testVec3Equals() {
    -  assertTrue(goog.math.Vec3.equals(null, null, null));
    -  assertFalse(goog.math.Vec3.equals(null, new goog.math.Vec3()));
    -
    -  var a = new goog.math.Vec3(1, 3, 5);
    -  assertTrue(goog.math.Vec3.equals(a, a));
    -  assertTrue(goog.math.Vec3.equals(a, new goog.math.Vec3(1, 3, 5)));
    -  assertFalse(goog.math.Vec3.equals(1, new goog.math.Vec3(3, 1, 5)));
    -}
    -
    -
    -function testDot() {
    -  var a = new goog.math.Vec3(0, 5, 2);
    -  var b = new goog.math.Vec3(3, 0, 5);
    -  assertEquals(10, goog.math.Vec3.dot(a, b));
    -
    -  var c = new goog.math.Vec3(-5, -5, 5);
    -  var d = new goog.math.Vec3(0, 7, -2);
    -  assertEquals(-45, goog.math.Vec3.dot(c, d));
    -}
    -
    -
    -function testCross() {
    -  var a = new goog.math.Vec3(3, 0, 0);
    -  var b = new goog.math.Vec3(0, 2, 0);
    -  assertVec3Equals(new goog.math.Vec3(0, 0, 6), goog.math.Vec3.cross(a, b));
    -
    -  var c = new goog.math.Vec3(1, 2, 3);
    -  var d = new goog.math.Vec3(4, 5, 6);
    -  assertVec3Equals(new goog.math.Vec3(-3, 6, -3), goog.math.Vec3.cross(c, d));
    -}
    -
    -
    -function testLerp() {
    -  var a = new goog.math.Vec3(0, 0, 0);
    -  var b = new goog.math.Vec3(10, 10, 10);
    -
    -  for (var i = 0; i <= 10; i++) {
    -    var c = goog.math.Vec3.lerp(a, b, i / 10);
    -    assertEquals(i, c.x);
    -    assertEquals(i, c.y);
    -    assertEquals(i, c.z);
    -  }
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/memoize/memoize.js b/src/database/third_party/closure-library/closure/goog/memoize/memoize.js
    deleted file mode 100644
    index cd7df3be023..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/memoize/memoize.js
    +++ /dev/null
    @@ -1,104 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Tool for caching the result of expensive deterministic
    - * functions.
    - *
    - * @see http://en.wikipedia.org/wiki/Memoization
    - *
    - */
    -
    -goog.provide('goog.memoize');
    -
    -
    -/**
    - * Decorator around functions that caches the inner function's return values.
    - *
    - * To cache parameterless functions, see goog.functions.cacheReturnValue.
    - *
    - * @param {Function} f The function to wrap. Its return value may only depend
    - *     on its arguments and 'this' context. There may be further restrictions
    - *     on the arguments depending on the capabilities of the serializer used.
    - * @param {function(number, Object): string=} opt_serializer A function to
    - *     serialize f's arguments. It must have the same signature as
    - *     goog.memoize.simpleSerializer. It defaults to that function.
    - * @this {Object} The object whose function is being wrapped.
    - * @return {!Function} The wrapped function.
    - */
    -goog.memoize = function(f, opt_serializer) {
    -  var serializer = opt_serializer || goog.memoize.simpleSerializer;
    -
    -  return function() {
    -    if (goog.memoize.ENABLE_MEMOIZE) {
    -      // In the strict mode, when this function is called as a global function,
    -      // the value of 'this' is undefined instead of a global object. See:
    -      // https://developer.mozilla.org/en/JavaScript/Strict_mode
    -      var thisOrGlobal = this || goog.global;
    -      // Maps the serialized list of args to the corresponding return value.
    -      var cache = thisOrGlobal[goog.memoize.CACHE_PROPERTY_] ||
    -          (thisOrGlobal[goog.memoize.CACHE_PROPERTY_] = {});
    -      var key = serializer(goog.getUid(f), arguments);
    -      return cache.hasOwnProperty(key) ? cache[key] :
    -          (cache[key] = f.apply(this, arguments));
    -    } else {
    -      return f.apply(this, arguments);
    -    }
    -  };
    -};
    -
    -
    -/**
    - * @define {boolean} Flag to disable memoization in unit tests.
    - */
    -goog.define('goog.memoize.ENABLE_MEMOIZE', true);
    -
    -
    -/**
    - * Clears the memoization cache on the given object.
    - * @param {Object} cacheOwner The owner of the cache. This is the {@code this}
    - *     context of the memoized function.
    - */
    -goog.memoize.clearCache = function(cacheOwner) {
    -  cacheOwner[goog.memoize.CACHE_PROPERTY_] = {};
    -};
    -
    -
    -/**
    - * Name of the property used by goog.memoize as cache.
    - * @type {string}
    - * @private
    - */
    -goog.memoize.CACHE_PROPERTY_ = 'closure_memoize_cache_';
    -
    -
    -/**
    - * Simple and fast argument serializer function for goog.memoize.
    - * Supports string, number, boolean, null and undefined arguments. Doesn't
    - * support \x0B characters in the strings.
    - * @param {number} functionUid Unique identifier of the function whose result
    - *     is cached.
    - * @param {Object} args The arguments that the function to memoize is called
    - *     with. Note: it is an array-like object, because supports indexing and
    - *     has the length property.
    - * @return {string} The list of arguments with type information concatenated
    - *     with the functionUid argument, serialized as \x0B-separated string.
    - */
    -goog.memoize.simpleSerializer = function(functionUid, args) {
    -  var context = [functionUid];
    -  for (var i = args.length - 1; i >= 0; --i) {
    -    context.push(typeof args[i], args[i]);
    -  }
    -  return context.join('\x0B');
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/memoize/memoize_test.html b/src/database/third_party/closure-library/closure/goog/memoize/memoize_test.html
    deleted file mode 100644
    index e7560e0550e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/memoize/memoize_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.memoize
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.memoizeTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/memoize/memoize_test.js b/src/database/third_party/closure-library/closure/goog/memoize/memoize_test.js
    deleted file mode 100644
    index ce986e954d0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/memoize/memoize_test.js
    +++ /dev/null
    @@ -1,153 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.memoizeTest');
    -goog.setTestOnly('goog.memoizeTest');
    -
    -goog.require('goog.memoize');
    -goog.require('goog.testing.jsunit');
    -
    -function testNoArgs() {
    -  var called = 0;
    -  var f = goog.memoize(function() {
    -    called++;
    -    return 10;
    -  });
    -
    -  assertEquals('f() 1st call', 10, f());
    -  assertEquals('f() 2nd call', 10, f());
    -  assertEquals('f() 3rd call', 10, f.call());
    -  assertEquals('f() called once', 1, called);
    -}
    -
    -function testOneOptionalArgSimple() {
    -  var called = 0;
    -  var f = goog.memoize(function(opt_x) {
    -    called++;
    -    return arguments.length == 0 ? 'no args' : opt_x;
    -  });
    -
    -  assertEquals('f() 1st call', 'no args', f());
    -  assertEquals('f() 2nd call', 'no args', f());
    -  assertEquals('f(0) 1st call', 0, f(0));
    -  assertEquals('f(0) 2nd call', 0, f(0));
    -  assertEquals('f("") 1st call', '', f(''));
    -  assertEquals('f("") 2nd call', '', f(''));
    -  assertEquals('f("0") 1st call', '0', f('0'));
    -  assertEquals('f("0") 1st call', '0', f('0'));
    -  assertEquals('f(null) 1st call', null, f(null));
    -  assertEquals('f(null) 2nd call', null, f(null));
    -  assertEquals('f(undefined) 1st call', undefined, f(undefined));
    -  assertEquals('f(undefined) 2nd call', undefined, f(undefined));
    -
    -  assertEquals('f(opt_x) called 6 times', 6, called);
    -}
    -
    -function testProtoFunctions() {
    -  var fcalled = 0;
    -  var gcalled = 0;
    -  var Class = function(x) {
    -    this.x = x;
    -    this.f = goog.memoize(function(y) {
    -      fcalled++;
    -      return this.x + y;
    -    });
    -  };
    -  Class.prototype.g = goog.memoize(function(z) {
    -    gcalled++;
    -    return this.x - z;
    -  });
    -
    -  var obj1 = new Class(10);
    -  var obj2 = new Class(20);
    -
    -  assertEquals('10+1', 11, obj1.f(1));
    -  assertEquals('10+2', 12, obj1.f(2));
    -  assertEquals('10+2 again', 12, obj1.f(2));
    -  assertEquals('f called twice', 2, fcalled);
    -
    -  assertEquals('10-1', 9, obj1.g(1));
    -  assertEquals('10-2', 8, obj1.g(2));
    -  assertEquals('10-2 again', 8, obj1.g(2));
    -  assertEquals('g called twice', 2, gcalled);
    -
    -  assertEquals('20+1', 21, obj2.f(1));
    -  assertEquals('20+2', 22, obj2.f(2));
    -  assertEquals('20+2 again', 22, obj2.f(2));
    -  assertEquals('f called 4 times', 4, fcalled);
    -
    -  assertEquals('20-1', 19, obj2.g(1));
    -  assertEquals('20-2', 18, obj2.g(2));
    -  assertEquals('20-2 again', 18, obj2.g(2));
    -  assertEquals('g called 4 times', 4, gcalled);
    -}
    -
    -function testCustomSerializer() {
    -  var called = 0;
    -  var serializer = function(this_context, args) {
    -    return String(args[0].getTime());
    -  };
    -  var getYear = goog.memoize(function(date) {
    -    called++;
    -    return date.getFullYear();
    -  }, serializer);
    -
    -  assertEquals('getYear(2008, 0, 1), 1st', 2008, getYear(new Date(2008, 0, 1)));
    -  assertEquals('getYear(2008, 0, 1), 2nd', 2008, getYear(new Date(2008, 0, 1)));
    -  assertEquals('getYear called once', 1, called);
    -
    -  assertEquals('getYear(2007, 0, 1)', 2007, getYear(new Date(2007, 0, 1)));
    -  assertEquals('getYear called twice', 2, called);
    -}
    -
    -function testClearCache() {
    -  var computed = 0;
    -  var identity = goog.memoize(function(x) {
    -    computed++;
    -    return x;
    -  });
    -  assertEquals('identity(1)==1', 1, identity(1));
    -  assertEquals('identity(1)==1', 1, identity(1));
    -  assertEquals('identity(1)==1', 1, identity(1));
    -  assertEquals('Expected memozation', 1, computed);
    -
    -  goog.memoize.clearCache(goog.global);
    -  assertEquals('identity(1)==1', 1, identity(1));
    -  assertEquals('identity(1)==1', 1, identity(1));
    -  assertEquals('Expected cleared memoization cache', 2, computed);
    -}
    -
    -function testDisableMemoize() {
    -  var computed = 0;
    -  var identity = goog.memoize(function(x) {
    -    computed++;
    -    return x;
    -  });
    -
    -  assertEquals('return value on first call', 1, identity(1));
    -  assertEquals('return value on second call (memoized)', 1, identity(1));
    -  assertEquals('computed once', 1, computed);
    -
    -  goog.memoize.ENABLE_MEMOIZE = false;
    -
    -  try {
    -    assertEquals('return value after disabled memoization', 1, identity(1));
    -    assertEquals('computed again', 2, computed);
    -  } finally {
    -    goog.memoize.ENABLE_MEMOIZE = true;
    -  }
    -
    -  assertEquals('return value after reenabled memoization', 1, identity(1));
    -  assertEquals('not computed again', 2, computed);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/abstractchannel.js b/src/database/third_party/closure-library/closure/goog/messaging/abstractchannel.js
    deleted file mode 100644
    index ea5440a64d0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/abstractchannel.js
    +++ /dev/null
    @@ -1,209 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview An abstract superclass for message channels that handles the
    - * repetitive details of registering and dispatching to services. This is more
    - * useful for full-fledged channels than for decorators, since decorators
    - * generally delegate service registering anyway.
    - *
    - */
    -
    -
    -goog.provide('goog.messaging.AbstractChannel');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.json');
    -goog.require('goog.log');
    -goog.require('goog.messaging.MessageChannel'); // interface
    -
    -
    -
    -/**
    - * Creates an abstract message channel.
    - *
    - * @constructor
    - * @extends {goog.Disposable}
    - * @implements {goog.messaging.MessageChannel}
    - */
    -goog.messaging.AbstractChannel = function() {
    -  goog.messaging.AbstractChannel.base(this, 'constructor');
    -
    -  /**
    -   * The services registered for this channel.
    -   * @type {Object<string, {callback: function((string|!Object)),
    -                             objectPayload: boolean}>}
    -   * @private
    -   */
    -  this.services_ = {};
    -};
    -goog.inherits(goog.messaging.AbstractChannel, goog.Disposable);
    -
    -
    -/**
    - * The default service to be run when no other services match.
    - *
    - * @type {?function(string, (string|!Object))}
    - * @private
    - */
    -goog.messaging.AbstractChannel.prototype.defaultService_;
    -
    -
    -/**
    - * Logger for this class.
    - * @type {goog.log.Logger}
    - * @protected
    - */
    -goog.messaging.AbstractChannel.prototype.logger =
    -    goog.log.getLogger('goog.messaging.AbstractChannel');
    -
    -
    -/**
    - * Immediately calls opt_connectCb if given, and is otherwise a no-op. If
    - * subclasses have configuration that needs to happen before the channel is
    - * connected, they should override this and {@link #isConnected}.
    - * @override
    - */
    -goog.messaging.AbstractChannel.prototype.connect = function(opt_connectCb) {
    -  if (opt_connectCb) {
    -    opt_connectCb();
    -  }
    -};
    -
    -
    -/**
    - * Always returns true. If subclasses have configuration that needs to happen
    - * before the channel is connected, they should override this and
    - * {@link #connect}.
    - * @override
    - */
    -goog.messaging.AbstractChannel.prototype.isConnected = function() {
    -  return true;
    -};
    -
    -
    -/** @override */
    -goog.messaging.AbstractChannel.prototype.registerService =
    -    function(serviceName, callback, opt_objectPayload) {
    -  this.services_[serviceName] = {
    -    callback: callback,
    -    objectPayload: !!opt_objectPayload
    -  };
    -};
    -
    -
    -/** @override */
    -goog.messaging.AbstractChannel.prototype.registerDefaultService =
    -    function(callback) {
    -  this.defaultService_ = callback;
    -};
    -
    -
    -/** @override */
    -goog.messaging.AbstractChannel.prototype.send = goog.abstractMethod;
    -
    -
    -/**
    - * Delivers a message to the appropriate service. This is meant to be called by
    - * subclasses when they receive messages.
    - *
    - * This method takes into account both explicitly-registered and default
    - * services, as well as making sure that JSON payloads are decoded when
    - * necessary. If the subclass is capable of passing objects as payloads, those
    - * objects can be passed in to this method directly. Otherwise, the (potentially
    - * JSON-encoded) strings should be passed in.
    - *
    - * @param {string} serviceName The name of the service receiving the message.
    - * @param {string|!Object} payload The contents of the message.
    - * @protected
    - */
    -goog.messaging.AbstractChannel.prototype.deliver = function(
    -    serviceName, payload) {
    -  var service = this.getService(serviceName, payload);
    -  if (!service) {
    -    return;
    -  }
    -
    -  var decodedPayload =
    -      this.decodePayload(serviceName, payload, service.objectPayload);
    -  if (goog.isDefAndNotNull(decodedPayload)) {
    -    service.callback(decodedPayload);
    -  }
    -};
    -
    -
    -/**
    - * Find the service object for a given service name. If there's no service
    - * explicitly registered, but there is a default service, a service object is
    - * constructed for it.
    - *
    - * @param {string} serviceName The name of the service receiving the message.
    - * @param {string|!Object} payload The contents of the message.
    - * @return {?{callback: function((string|!Object)), objectPayload: boolean}} The
    - *     service object for the given service, or null if none was found.
    - * @protected
    - */
    -goog.messaging.AbstractChannel.prototype.getService = function(
    -    serviceName, payload) {
    -  var service = this.services_[serviceName];
    -  if (service) {
    -    return service;
    -  } else if (this.defaultService_) {
    -    var callback = goog.partial(this.defaultService_, serviceName);
    -    var objectPayload = goog.isObject(payload);
    -    return {callback: callback, objectPayload: objectPayload};
    -  }
    -
    -  goog.log.warning(this.logger, 'Unknown service name "' + serviceName + '"');
    -  return null;
    -};
    -
    -
    -/**
    - * Converts the message payload into the format expected by the registered
    - * service (either JSON or string).
    - *
    - * @param {string} serviceName The name of the service receiving the message.
    - * @param {string|!Object} payload The contents of the message.
    - * @param {boolean} objectPayload Whether the service expects an object or a
    - *     plain string.
    - * @return {string|Object} The payload in the format expected by the service, or
    - *     null if something went wrong.
    - * @protected
    - */
    -goog.messaging.AbstractChannel.prototype.decodePayload = function(
    -    serviceName, payload, objectPayload) {
    -  if (objectPayload && goog.isString(payload)) {
    -    try {
    -      return goog.json.parse(payload);
    -    } catch (err) {
    -      goog.log.warning(this.logger,
    -          'Expected JSON payload for ' + serviceName +
    -          ', was "' + payload + '"');
    -      return null;
    -    }
    -  } else if (!objectPayload && !goog.isString(payload)) {
    -    return goog.json.serialize(payload);
    -  }
    -  return payload;
    -};
    -
    -
    -/** @override */
    -goog.messaging.AbstractChannel.prototype.disposeInternal = function() {
    -  goog.messaging.AbstractChannel.base(this, 'disposeInternal');
    -  delete this.logger;
    -  delete this.services_;
    -  delete this.defaultService_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/abstractchannel_test.html b/src/database/third_party/closure-library/closure/goog/messaging/abstractchannel_test.html
    deleted file mode 100644
    index bcf70796498..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/abstractchannel_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.messaging.AbstractChannel
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.messaging.AbstractChannelTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/abstractchannel_test.js b/src/database/third_party/closure-library/closure/goog/messaging/abstractchannel_test.js
    deleted file mode 100644
    index 6d7e22722a9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/abstractchannel_test.js
    +++ /dev/null
    @@ -1,82 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.messaging.AbstractChannelTest');
    -goog.setTestOnly('goog.messaging.AbstractChannelTest');
    -
    -goog.require('goog.messaging.AbstractChannel');
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.async.MockControl');
    -goog.require('goog.testing.jsunit');
    -
    -var mockControl;
    -var mockWorker;
    -var asyncMockControl;
    -var channel;
    -
    -function setUp() {
    -  mockControl = new goog.testing.MockControl();
    -  asyncMockControl = new goog.testing.async.MockControl(mockControl);
    -  channel = new goog.messaging.AbstractChannel();
    -}
    -
    -function tearDown() {
    -  channel.dispose();
    -  mockControl.$verifyAll();
    -}
    -
    -function testConnect() {
    -  channel.connect(
    -      asyncMockControl.createCallbackMock('connectCallback', function() {}));
    -}
    -
    -function testIsConnected() {
    -  assertTrue('Channel should be connected by default', channel.isConnected());
    -}
    -
    -function testDeliverString() {
    -  channel.registerService(
    -      'foo',
    -      asyncMockControl.asyncAssertEquals(
    -          'should pass string to service', 'bar'),
    -      false /* opt_json */);
    -  channel.deliver('foo', 'bar');
    -}
    -
    -function testDeliverDeserializedString() {
    -  channel.registerService(
    -      'foo',
    -      asyncMockControl.asyncAssertEquals(
    -          'should pass string to service', '{"bar":"baz"}'),
    -      false /* opt_json */);
    -  channel.deliver('foo', {bar: 'baz'});
    -}
    -
    -function testDeliverObject() {
    -  channel.registerService(
    -      'foo',
    -      asyncMockControl.asyncAssertEquals(
    -          'should pass string to service', {bar: 'baz'}),
    -      true /* opt_json */);
    -  channel.deliver('foo', {bar: 'baz'});
    -}
    -
    -function testDeliverSerializedObject() {
    -  channel.registerService(
    -      'foo',
    -      asyncMockControl.asyncAssertEquals(
    -          'should pass string to service', {bar: 'baz'}),
    -      true /* opt_json */);
    -  channel.deliver('foo', '{"bar":"baz"}');
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/bufferedchannel.js b/src/database/third_party/closure-library/closure/goog/messaging/bufferedchannel.js
    deleted file mode 100644
    index a0593250003..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/bufferedchannel.js
    +++ /dev/null
    @@ -1,287 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A wrapper for asynchronous message-passing channels that buffer
    - * their output until both ends of the channel are connected.
    - *
    - */
    -
    -goog.provide('goog.messaging.BufferedChannel');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.Timer');
    -goog.require('goog.events');
    -goog.require('goog.log');
    -goog.require('goog.messaging.MessageChannel');
    -goog.require('goog.messaging.MultiChannel');
    -
    -
    -
    -/**
    - * Creates a new BufferedChannel, which operates like its underlying channel
    - * except that it buffers calls to send until it receives a message from its
    - * peer claiming that the peer is ready to receive.  The peer is also expected
    - * to be a BufferedChannel, though this is not enforced.
    - *
    - * @param {!goog.messaging.MessageChannel} messageChannel The MessageChannel
    - *     we're wrapping.
    - * @param {number=} opt_interval Polling interval for sending ready
    - *     notifications to peer, in ms.  Default is 50.
    - * @constructor
    - * @extends {goog.Disposable}
    - * @implements {goog.messaging.MessageChannel};
    - * @final
    - */
    -goog.messaging.BufferedChannel = function(messageChannel, opt_interval) {
    -  goog.Disposable.call(this);
    -
    -  /**
    -   * Buffer of messages to be sent when the channel's peer is ready.
    -   *
    -   * @type {Array<Object>}
    -   * @private
    -   */
    -  this.buffer_ = [];
    -
    -  /**
    -   * Channel dispatcher wrapping the underlying delegate channel.
    -   *
    -   * @type {!goog.messaging.MultiChannel}
    -   * @private
    -   */
    -  this.multiChannel_ = new goog.messaging.MultiChannel(messageChannel);
    -
    -  /**
    -   * Virtual channel for carrying the user's messages.
    -   *
    -   * @type {!goog.messaging.MessageChannel}
    -   * @private
    -   */
    -  this.userChannel_ = this.multiChannel_.createVirtualChannel(
    -      goog.messaging.BufferedChannel.USER_CHANNEL_NAME_);
    -
    -  /**
    -   * Virtual channel for carrying control messages for BufferedChannel.
    -   *
    -   * @type {!goog.messaging.MessageChannel}
    -   * @private
    -   */
    -  this.controlChannel_ = this.multiChannel_.createVirtualChannel(
    -      goog.messaging.BufferedChannel.CONTROL_CHANNEL_NAME_);
    -
    -  /**
    -   * Timer for the peer ready ping loop.
    -   *
    -   * @type {goog.Timer}
    -   * @private
    -   */
    -  this.timer_ = new goog.Timer(
    -      opt_interval || goog.messaging.BufferedChannel.DEFAULT_INTERVAL_MILLIS_);
    -
    -  this.timer_.start();
    -  goog.events.listen(
    -      this.timer_, goog.Timer.TICK, this.sendReadyPing_, false, this);
    -
    -  this.controlChannel_.registerService(
    -      goog.messaging.BufferedChannel.PEER_READY_SERVICE_NAME_,
    -      goog.bind(this.setPeerReady_, this));
    -};
    -goog.inherits(goog.messaging.BufferedChannel, goog.Disposable);
    -
    -
    -/**
    - * Default polling interval (in ms) for setPeerReady_ notifications.
    - *
    - * @type {number}
    - * @const
    - * @private
    - */
    -goog.messaging.BufferedChannel.DEFAULT_INTERVAL_MILLIS_ = 50;
    -
    -
    -/**
    - * The name of the private service which handles peer ready pings.  The
    - * service registered with this name is bound to this.setPeerReady_, an internal
    - * part of BufferedChannel's implementation that clients should not send to
    - * directly.
    - *
    - * @type {string}
    - * @const
    - * @private
    - */
    -goog.messaging.BufferedChannel.PEER_READY_SERVICE_NAME_ = 'setPeerReady_';
    -
    -
    -/**
    - * The name of the virtual channel along which user messages are sent.
    - *
    - * @type {string}
    - * @const
    - * @private
    - */
    -goog.messaging.BufferedChannel.USER_CHANNEL_NAME_ = 'user';
    -
    -
    -/**
    - * The name of the virtual channel along which internal control messages are
    - * sent.
    - *
    - * @type {string}
    - * @const
    - * @private
    - */
    -goog.messaging.BufferedChannel.CONTROL_CHANNEL_NAME_ = 'control';
    -
    -
    -/** @override */
    -goog.messaging.BufferedChannel.prototype.connect = function(opt_connectCb) {
    -  if (opt_connectCb) {
    -    opt_connectCb();
    -  }
    -};
    -
    -
    -/** @override */
    -goog.messaging.BufferedChannel.prototype.isConnected = function() {
    -  return true;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the channel's peer is ready.
    - */
    -goog.messaging.BufferedChannel.prototype.isPeerReady = function() {
    -  return this.peerReady_;
    -};
    -
    -
    -/**
    - * Logger.
    - *
    - * @type {goog.log.Logger}
    - * @const
    - * @private
    - */
    -goog.messaging.BufferedChannel.prototype.logger_ = goog.log.getLogger(
    -    'goog.messaging.bufferedchannel');
    -
    -
    -/**
    - * Handles one tick of our peer ready notification loop.  This entails sending a
    - * ready ping to the peer and shutting down the loop if we've received a ping
    - * ourselves.
    - *
    - * @private
    - */
    -goog.messaging.BufferedChannel.prototype.sendReadyPing_ = function() {
    -  try {
    -    this.controlChannel_.send(
    -        goog.messaging.BufferedChannel.PEER_READY_SERVICE_NAME_,
    -        /* payload */ this.isPeerReady() ? '1' : '');
    -  } catch (e) {
    -    this.timer_.stop();  // So we don't keep calling send and re-throwing.
    -    throw e;
    -  }
    -};
    -
    -
    -/**
    -  * Whether or not the peer channel is ready to receive messages.
    -  *
    -  * @type {boolean}
    -  * @private
    -  */
    -goog.messaging.BufferedChannel.prototype.peerReady_;
    -
    -
    -/** @override */
    -goog.messaging.BufferedChannel.prototype.registerService = function(
    -    serviceName, callback, opt_objectPayload) {
    -  this.userChannel_.registerService(serviceName, callback, opt_objectPayload);
    -};
    -
    -
    -/** @override */
    -goog.messaging.BufferedChannel.prototype.registerDefaultService = function(
    -    callback) {
    -  this.userChannel_.registerDefaultService(callback);
    -};
    -
    -
    -/**
    - * Send a message over the channel.  If the peer is not ready, the message will
    - * be buffered and sent once we've received a ready message from our peer.
    - *
    - * @param {string} serviceName The name of the service this message should be
    - *     delivered to.
    - * @param {string|!Object} payload The value of the message. If this is an
    - *     Object, it is serialized to JSON before sending.  It's the responsibility
    - *     of implementors of this class to perform the serialization.
    - * @see goog.net.xpc.BufferedChannel.send
    - * @override
    - */
    -goog.messaging.BufferedChannel.prototype.send = function(serviceName, payload) {
    -  if (this.isPeerReady()) {
    -    this.userChannel_.send(serviceName, payload);
    -  } else {
    -    goog.log.fine(goog.messaging.BufferedChannel.prototype.logger_,
    -        'buffering message ' + serviceName);
    -    this.buffer_.push({serviceName: serviceName, payload: payload});
    -  }
    -};
    -
    -
    -/**
    - * Marks the channel's peer as ready, then sends buffered messages and nulls the
    - * buffer.  Subsequent calls to setPeerReady_ have no effect.
    - *
    - * @param {(!Object|string)} peerKnowsWeKnowItsReady Passed by the peer to
    - *     indicate whether it knows that we've received its ping and that it's
    - *     ready.  Non-empty if true, empty if false.
    - * @private
    - */
    -goog.messaging.BufferedChannel.prototype.setPeerReady_ = function(
    -    peerKnowsWeKnowItsReady) {
    -  if (peerKnowsWeKnowItsReady) {
    -    this.timer_.stop();
    -  } else {
    -    // Our peer doesn't know we're ready, so restart (or continue) pinging.
    -    // Restarting may be needed if the peer iframe was reloaded after the
    -    // connection was first established.
    -    this.timer_.start();
    -  }
    -
    -  if (this.peerReady_) {
    -    return;
    -  }
    -  this.peerReady_ = true;
    -  // Send one last ping so that the peer knows we know it's ready.
    -  this.sendReadyPing_();
    -  for (var i = 0; i < this.buffer_.length; i++) {
    -    var message = this.buffer_[i];
    -    goog.log.fine(goog.messaging.BufferedChannel.prototype.logger_,
    -        'sending buffered message ' + message.serviceName);
    -    this.userChannel_.send(message.serviceName, message.payload);
    -  }
    -  this.buffer_ = null;
    -};
    -
    -
    -/** @override */
    -goog.messaging.BufferedChannel.prototype.disposeInternal = function() {
    -  goog.dispose(this.multiChannel_);
    -  goog.dispose(this.timer_);
    -  goog.messaging.BufferedChannel.base(this, 'disposeInternal');
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/bufferedchannel_test.html b/src/database/third_party/closure-library/closure/goog/messaging/bufferedchannel_test.html
    deleted file mode 100644
    index acbc0a9ec09..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/bufferedchannel_test.html
    +++ /dev/null
    @@ -1,34 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.messaging.BufferedChannel
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.messaging.BufferedChannelTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="debug-container"
    -       style="border: 1px solid black; font-size: small; font-family: courier;">
    -   Debug Window
    -  [
    -   <a href="#" onclick="document.getElementById('debug-div').innerHTML = '';">
    -    clear
    -   </a>
    -   ]
    -   <div id="debug-div">
    -   </div>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/bufferedchannel_test.js b/src/database/third_party/closure-library/closure/goog/messaging/bufferedchannel_test.js
    deleted file mode 100644
    index 25eb7386f08..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/bufferedchannel_test.js
    +++ /dev/null
    @@ -1,268 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.messaging.BufferedChannelTest');
    -goog.setTestOnly('goog.messaging.BufferedChannelTest');
    -
    -goog.require('goog.debug.Console');
    -goog.require('goog.dom');
    -goog.require('goog.log');
    -goog.require('goog.log.Level');
    -goog.require('goog.messaging.BufferedChannel');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.async.MockControl');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.messaging.MockMessageChannel');
    -
    -var clock;
    -var messages = [
    -  {serviceName: 'firstService', payload: 'firstPayload'},
    -  {serviceName: 'secondService', payload: 'secondPayload'}
    -];
    -var mockControl;
    -var asyncMockControl;
    -
    -function setUpPage() {
    -  if (goog.global.console) {
    -    new goog.debug.Console().setCapturing(true);
    -  }
    -  var logger = goog.log.getLogger('goog.messaging');
    -  logger.setLevel(goog.log.Level.ALL);
    -  goog.log.addHandler(logger, function(logRecord) {
    -    var msg = goog.dom.createDom('div');
    -    msg.innerHTML = logRecord.getMessage();
    -    goog.dom.appendChild(goog.dom.getElement('debug-div'), msg);
    -  });
    -  clock = new goog.testing.MockClock();
    -  mockControl = new goog.testing.MockControl();
    -  asyncMockControl = new goog.testing.async.MockControl(mockControl);
    -}
    -
    -
    -function setUp() {
    -  clock.install();
    -}
    -
    -
    -function tearDown() {
    -  clock.uninstall();
    -  mockControl.$tearDown();
    -}
    -
    -
    -function assertMessageArraysEqual(ma1, ma2) {
    -  assertEquals('message array lengths differ', ma1.length, ma2.length);
    -  for (var i = 0; i < ma1.length; i++) {
    -    assertEquals(
    -        'message array serviceNames differ',
    -        ma1[i].serviceName, ma2[i].serviceName);
    -    assertEquals(
    -        'message array payloads differ',
    -        ma1[i].payload, ma2[i].payload);
    -  }
    -}
    -
    -
    -function testDelegationToWrappedChannel() {
    -  var mockChannel = new goog.testing.messaging.MockMessageChannel(mockControl);
    -  var channel = new goog.messaging.BufferedChannel(mockChannel);
    -
    -  channel.registerDefaultService(
    -      asyncMockControl.asyncAssertEquals(
    -          'default service should be delegated',
    -          'defaultServiceName', 'default service payload'));
    -  channel.registerService(
    -      'normalServiceName',
    -      asyncMockControl.asyncAssertEquals(
    -          'normal service should be delegated',
    -          'normal service payload'));
    -  mockChannel.send(
    -      goog.messaging.BufferedChannel.USER_CHANNEL_NAME_ + ':message',
    -      'payload');
    -
    -  mockControl.$replayAll();
    -  channel.peerReady_ = true;  // Prevent buffering so we delegate send calls.
    -  mockChannel.receive(
    -      goog.messaging.BufferedChannel.USER_CHANNEL_NAME_ + ':defaultServiceName',
    -      'default service payload');
    -  mockChannel.receive(
    -      goog.messaging.BufferedChannel.USER_CHANNEL_NAME_ + ':normalServiceName',
    -      'normal service payload');
    -  channel.send('message', 'payload');
    -  mockControl.$verifyAll();
    -}
    -
    -
    -function testOptionalConnectCallbackExecutes() {
    -  var mockChannel = new goog.testing.messaging.MockMessageChannel(mockControl);
    -  var channel = new goog.messaging.BufferedChannel(mockChannel);
    -  var mockConnectCb = mockControl.createFunctionMock('mockConnectCb');
    -  mockConnectCb();
    -
    -  mockControl.$replayAll();
    -  channel.connect(mockConnectCb);
    -  mockControl.$verifyAll();
    -}
    -
    -
    -function testSendExceptionsInSendReadyPingStopsTimerAndReraises() {
    -  var mockChannel = new goog.testing.messaging.MockMessageChannel(mockControl);
    -  var channel = new goog.messaging.BufferedChannel(mockChannel);
    -
    -  var errorMessage = 'errorMessage';
    -  mockChannel.send(
    -      goog.messaging.BufferedChannel.CONTROL_CHANNEL_NAME_ + ':' +
    -      goog.messaging.BufferedChannel.PEER_READY_SERVICE_NAME_,
    -      /* payload */ '').$throws(Error(errorMessage));
    -  channel.timer_.enabled = true;
    -
    -  mockControl.$replayAll();
    -  var exception = assertThrows(function() {
    -    channel.sendReadyPing_();
    -  });
    -  assertContains(errorMessage, exception.message);
    -  assertFalse(channel.timer_.enabled);
    -  mockControl.$verifyAll();
    -}
    -
    -
    -function testPollingIntervalDefaultAndOverride() {
    -  var mockChannel = new goog.testing.messaging.MockMessageChannel(mockControl);
    -  var channel = new goog.messaging.BufferedChannel(mockChannel);
    -
    -  assertEquals(
    -      goog.messaging.BufferedChannel.DEFAULT_INTERVAL_MILLIS_,
    -      channel.timer_.getInterval());
    -  var interval = 100;
    -  var longIntervalChannel = new goog.messaging.BufferedChannel(
    -      new goog.testing.messaging.MockMessageChannel(mockControl), interval);
    -  assertEquals(interval, longIntervalChannel.timer_.getInterval());
    -}
    -
    -
    -function testBidirectionalCommunicationBuffersUntilReadyPingsSucceed() {
    -  var mockChannel1 = new goog.testing.messaging.MockMessageChannel(mockControl);
    -  var mockChannel2 = new goog.testing.messaging.MockMessageChannel(mockControl);
    -  var bufferedChannel1 = new goog.messaging.BufferedChannel(mockChannel1);
    -  var bufferedChannel2 = new goog.messaging.BufferedChannel(mockChannel2);
    -  mockChannel1.send(
    -      goog.messaging.BufferedChannel.CONTROL_CHANNEL_NAME_ + ':setPeerReady_',
    -      '').$does(function() {
    -    bufferedChannel2.setPeerReady_('');
    -  });
    -  mockChannel2.send(
    -      goog.messaging.BufferedChannel.CONTROL_CHANNEL_NAME_ + ':setPeerReady_',
    -      '1').$does(function() {
    -    bufferedChannel1.setPeerReady_('1');
    -  });
    -  mockChannel1.send(
    -      goog.messaging.BufferedChannel.CONTROL_CHANNEL_NAME_ + ':setPeerReady_',
    -      '1').$does(function() {
    -    bufferedChannel2.setPeerReady_('1');
    -  });
    -  mockChannel1.send(goog.messaging.BufferedChannel.USER_CHANNEL_NAME_ + ':' +
    -                    messages[0].serviceName,
    -                    messages[0].payload);
    -  mockChannel2.send(goog.messaging.BufferedChannel.USER_CHANNEL_NAME_ + ':' +
    -                    messages[1].serviceName,
    -                    messages[1].payload);
    -
    -  mockControl.$replayAll();
    -  bufferedChannel1.send(messages[0].serviceName, messages[0].payload);
    -  bufferedChannel2.send(messages[1].serviceName, messages[1].payload);
    -  assertMessageArraysEqual([messages[0]], bufferedChannel1.buffer_);
    -  assertMessageArraysEqual([messages[1]], bufferedChannel2.buffer_);
    -  // First tick causes setPeerReady_ to fire, which in turn flushes the buffers.
    -  clock.tick(goog.messaging.BufferedChannel.DEFAULT_INTERVAL_MILLIS_);
    -  assertEquals(bufferedChannel1.buffer_, null);
    -  assertEquals(bufferedChannel2.buffer_, null);
    -  // Now that peers are ready, a second tick causes no more sends.
    -  clock.tick(goog.messaging.BufferedChannel.DEFAULT_INTERVAL_MILLIS_);
    -  mockControl.$verifyAll();
    -}
    -
    -
    -function testBidirectionalCommunicationReconnectsAfterOneSideRestarts() {
    -  var mockChannel1 = new goog.testing.messaging.MockMessageChannel(mockControl);
    -  var mockChannel2 = new goog.testing.messaging.MockMessageChannel(mockControl);
    -  var mockChannel3 = new goog.testing.messaging.MockMessageChannel(mockControl);
    -  var bufferedChannel1 = new goog.messaging.BufferedChannel(mockChannel1);
    -  var bufferedChannel2 = new goog.messaging.BufferedChannel(mockChannel2);
    -  var bufferedChannel3 = new goog.messaging.BufferedChannel(mockChannel3);
    -
    -  // First tick
    -  mockChannel1.send(
    -      goog.messaging.BufferedChannel.CONTROL_CHANNEL_NAME_ + ':setPeerReady_',
    -      '').$does(function() {
    -    bufferedChannel2.setPeerReady_('');
    -  });
    -  mockChannel2.send(
    -      goog.messaging.BufferedChannel.CONTROL_CHANNEL_NAME_ + ':setPeerReady_',
    -      '1').$does(function() {
    -    bufferedChannel1.setPeerReady_('1');
    -  });
    -  mockChannel1.send(
    -      goog.messaging.BufferedChannel.CONTROL_CHANNEL_NAME_ + ':setPeerReady_',
    -      '1').$does(function() {
    -    bufferedChannel2.setPeerReady_('1');
    -  });
    -  mockChannel3.send(
    -      goog.messaging.BufferedChannel.CONTROL_CHANNEL_NAME_ + ':setPeerReady_',
    -      '');  // pretend it's not ready to connect yet
    -
    -  // Second tick
    -  mockChannel3.send(
    -      goog.messaging.BufferedChannel.CONTROL_CHANNEL_NAME_ + ':setPeerReady_',
    -      '').$does(function() {
    -    bufferedChannel1.setPeerReady_('');
    -  });
    -
    -  // Third tick
    -  mockChannel1.send(
    -      goog.messaging.BufferedChannel.CONTROL_CHANNEL_NAME_ + ':setPeerReady_',
    -      '1').$does(function() {
    -    bufferedChannel3.setPeerReady_('1');
    -  });
    -  mockChannel3.send(
    -      goog.messaging.BufferedChannel.CONTROL_CHANNEL_NAME_ + ':setPeerReady_',
    -      '1').$does(function() {
    -    bufferedChannel1.setPeerReady_('1');
    -  });
    -
    -  mockChannel1.send(goog.messaging.BufferedChannel.USER_CHANNEL_NAME_ + ':' +
    -                    messages[0].serviceName,
    -                    messages[0].payload);
    -  mockChannel3.send(goog.messaging.BufferedChannel.USER_CHANNEL_NAME_ + ':' +
    -                    messages[1].serviceName,
    -                    messages[1].payload);
    -
    -  mockControl.$replayAll();
    -  // First tick causes setPeerReady_ to fire, which sets up the connection
    -  // between channels 1 and 2.
    -  clock.tick(goog.messaging.BufferedChannel.DEFAULT_INTERVAL_MILLIS_);
    -  assertTrue(bufferedChannel1.peerReady_);
    -  assertTrue(bufferedChannel2.peerReady_);
    -  // Now pretend that channel 2 went down and was replaced by channel 3, which
    -  // is trying to connect with channel 1.
    -  clock.tick(goog.messaging.BufferedChannel.DEFAULT_INTERVAL_MILLIS_);
    -  assertTrue(bufferedChannel1.peerReady_);
    -  clock.tick(goog.messaging.BufferedChannel.DEFAULT_INTERVAL_MILLIS_);
    -  assertTrue(bufferedChannel3.peerReady_);
    -  bufferedChannel1.send(messages[0].serviceName, messages[0].payload);
    -  bufferedChannel3.send(messages[1].serviceName, messages[1].payload);
    -  // All timers stopped, nothing happens on the fourth tick.
    -  clock.tick(goog.messaging.BufferedChannel.DEFAULT_INTERVAL_MILLIS_);
    -  mockControl.$verifyAll();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/deferredchannel.js b/src/database/third_party/closure-library/closure/goog/messaging/deferredchannel.js
    deleted file mode 100644
    index 5baac690387..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/deferredchannel.js
    +++ /dev/null
    @@ -1,98 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A MessageChannel decorator that wraps a deferred MessageChannel
    - * and enqueues messages and service registrations until that channel exists.
    - *
    - */
    -
    -goog.provide('goog.messaging.DeferredChannel');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.messaging.MessageChannel'); // interface
    -
    -
    -
    -/**
    - * Creates a new DeferredChannel, which wraps a deferred MessageChannel and
    - * enqueues messages to be sent once the wrapped channel is resolved.
    - *
    - * @param {!goog.async.Deferred} deferredChannel The underlying deferred
    - *     MessageChannel.
    - * @constructor
    - * @extends {goog.Disposable}
    - * @implements {goog.messaging.MessageChannel}
    - * @final
    - */
    -goog.messaging.DeferredChannel = function(deferredChannel) {
    -  goog.messaging.DeferredChannel.base(this, 'constructor');
    -  this.deferred_ = deferredChannel;
    -};
    -goog.inherits(goog.messaging.DeferredChannel, goog.Disposable);
    -
    -
    -/**
    - * Cancels the wrapped Deferred.
    - */
    -goog.messaging.DeferredChannel.prototype.cancel = function() {
    -  this.deferred_.cancel();
    -};
    -
    -
    -/** @override */
    -goog.messaging.DeferredChannel.prototype.connect = function(opt_connectCb) {
    -  if (opt_connectCb) {
    -    opt_connectCb();
    -  }
    -};
    -
    -
    -/** @override */
    -goog.messaging.DeferredChannel.prototype.isConnected = function() {
    -  return true;
    -};
    -
    -
    -/** @override */
    -goog.messaging.DeferredChannel.prototype.registerService = function(
    -    serviceName, callback, opt_objectPayload) {
    -  this.deferred_.addCallback(function(resolved) {
    -    resolved.registerService(serviceName, callback, opt_objectPayload);
    -  });
    -};
    -
    -
    -/** @override */
    -goog.messaging.DeferredChannel.prototype.registerDefaultService =
    -    function(callback) {
    -  this.deferred_.addCallback(function(resolved) {
    -    resolved.registerDefaultService(callback);
    -  });
    -};
    -
    -
    -/** @override */
    -goog.messaging.DeferredChannel.prototype.send = function(serviceName, payload) {
    -  this.deferred_.addCallback(function(resolved) {
    -    resolved.send(serviceName, payload);
    -  });
    -};
    -
    -
    -/** @override */
    -goog.messaging.DeferredChannel.prototype.disposeInternal = function() {
    -  this.cancel();
    -  goog.messaging.DeferredChannel.base(this, 'disposeInternal');
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/deferredchannel_test.html b/src/database/third_party/closure-library/closure/goog/messaging/deferredchannel_test.html
    deleted file mode 100644
    index 954a0d00c44..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/deferredchannel_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.messaging.DeferredChannel
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.messaging.DeferredChannelTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/deferredchannel_test.js b/src/database/third_party/closure-library/closure/goog/messaging/deferredchannel_test.js
    deleted file mode 100644
    index 9a1cabafca6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/deferredchannel_test.js
    +++ /dev/null
    @@ -1,106 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.messaging.DeferredChannelTest');
    -goog.setTestOnly('goog.messaging.DeferredChannelTest');
    -
    -goog.require('goog.async.Deferred');
    -goog.require('goog.messaging.DeferredChannel');
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.async.MockControl');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.messaging.MockMessageChannel');
    -
    -var mockControl, asyncMockControl;
    -var mockChannel, deferredChannel;
    -var cancelled;
    -var deferred;
    -
    -function setUp() {
    -  mockControl = new goog.testing.MockControl();
    -  asyncMockControl = new goog.testing.async.MockControl(mockControl);
    -  mockChannel = new goog.testing.messaging.MockMessageChannel(mockControl);
    -  cancelled = false;
    -  deferred = new goog.async.Deferred(function() { cancelled = true; });
    -  deferredChannel = new goog.messaging.DeferredChannel(deferred);
    -}
    -
    -function tearDown() {
    -  mockControl.$verifyAll();
    -}
    -
    -function testDeferredResolvedBeforeSend() {
    -  mockChannel.send('test', 'val');
    -  mockControl.$replayAll();
    -  deferred.callback(mockChannel);
    -  deferredChannel.send('test', 'val');
    -}
    -
    -function testDeferredResolvedBeforeRegister() {
    -  deferred.callback(mockChannel);
    -  deferredChannel.registerService(
    -      'test', asyncMockControl.asyncAssertEquals('passes on register', 'val'));
    -  mockChannel.receive('test', 'val');
    -}
    -
    -function testDeferredResolvedBeforeRegisterObject() {
    -  deferred.callback(mockChannel);
    -  deferredChannel.registerService(
    -      'test',
    -      asyncMockControl.asyncAssertEquals('passes on register', {'key': 'val'}),
    -      true);
    -  mockChannel.receive('test', {'key': 'val'});
    -}
    -
    -function testDeferredResolvedBeforeRegisterDefault() {
    -  deferred.callback(mockChannel);
    -  deferredChannel.registerDefaultService(
    -      asyncMockControl.asyncAssertEquals('passes on register', 'test', 'val'));
    -  mockChannel.receive('test', 'val');
    -}
    -
    -function testDeferredResolvedAfterSend() {
    -  mockChannel.send('test', 'val');
    -  mockControl.$replayAll();
    -  deferredChannel.send('test', 'val');
    -  deferred.callback(mockChannel);
    -}
    -
    -function testDeferredResolvedAfterRegister() {
    -  deferredChannel.registerService(
    -      'test', asyncMockControl.asyncAssertEquals('passes on register', 'val'));
    -  deferred.callback(mockChannel);
    -  mockChannel.receive('test', 'val');
    -}
    -
    -function testDeferredResolvedAfterRegisterObject() {
    -  deferredChannel.registerService(
    -      'test',
    -      asyncMockControl.asyncAssertEquals('passes on register', {'key': 'val'}),
    -      true);
    -  deferred.callback(mockChannel);
    -  mockChannel.receive('test', {'key': 'val'});
    -}
    -
    -function testDeferredResolvedAfterRegisterDefault() {
    -  deferredChannel.registerDefaultService(
    -      asyncMockControl.asyncAssertEquals('passes on register', 'test', 'val'));
    -  deferred.callback(mockChannel);
    -  mockChannel.receive('test', 'val');
    -}
    -
    -function testCancel() {
    -  deferredChannel.cancel();
    -  assertTrue(cancelled);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/loggerclient.js b/src/database/third_party/closure-library/closure/goog/messaging/loggerclient.js
    deleted file mode 100644
    index 52e276c7918..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/loggerclient.js
    +++ /dev/null
    @@ -1,132 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview This class sends logging messages over a message channel to a
    - * server on the main page that prints them using standard logging mechanisms.
    - *
    - */
    -
    -goog.provide('goog.messaging.LoggerClient');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.debug');
    -goog.require('goog.debug.LogManager');
    -goog.require('goog.debug.Logger');
    -
    -
    -
    -/**
    - * Creates a logger client that sends messages along a message channel for the
    - * remote end to log. The remote end of the channel should use a
    - * {goog.messaging.LoggerServer} with the same service name.
    - *
    - * @param {!goog.messaging.MessageChannel} channel The channel that on which to
    - *     send the log messages.
    - * @param {string} serviceName The name of the logging service to use.
    - * @constructor
    - * @extends {goog.Disposable}
    - * @final
    - */
    -goog.messaging.LoggerClient = function(channel, serviceName) {
    -  if (goog.messaging.LoggerClient.instance_) {
    -    return goog.messaging.LoggerClient.instance_;
    -  }
    -
    -  goog.messaging.LoggerClient.base(this, 'constructor');
    -
    -  /**
    -   * The channel on which to send the log messages.
    -   * @type {!goog.messaging.MessageChannel}
    -   * @private
    -   */
    -  this.channel_ = channel;
    -
    -  /**
    -   * The name of the logging service to use.
    -   * @type {string}
    -   * @private
    -   */
    -  this.serviceName_ = serviceName;
    -
    -  /**
    -   * The bound handler function for handling log messages. This is kept in a
    -   * variable so that it can be deregistered when the logger client is disposed.
    -   * @type {Function}
    -   * @private
    -   */
    -  this.publishHandler_ = goog.bind(this.sendLog_, this);
    -  goog.debug.LogManager.getRoot().addHandler(this.publishHandler_);
    -
    -  goog.messaging.LoggerClient.instance_ = this;
    -};
    -goog.inherits(goog.messaging.LoggerClient, goog.Disposable);
    -
    -
    -/**
    - * The singleton instance, if any.
    - * @type {goog.messaging.LoggerClient}
    - * @private
    - */
    -goog.messaging.LoggerClient.instance_ = null;
    -
    -
    -/**
    - * Sends a log message through the channel.
    - * @param {!goog.debug.LogRecord} logRecord The log message.
    - * @private
    - */
    -goog.messaging.LoggerClient.prototype.sendLog_ = function(logRecord) {
    -  var name = logRecord.getLoggerName();
    -  var level = logRecord.getLevel();
    -  var msg = logRecord.getMessage();
    -  var originalException = logRecord.getException();
    -
    -  var exception;
    -  if (originalException) {
    -    var normalizedException =
    -        goog.debug.normalizeErrorObject(originalException);
    -    exception = {
    -      'name': normalizedException.name,
    -      'message': normalizedException.message,
    -      'lineNumber': normalizedException.lineNumber,
    -      'fileName': normalizedException.fileName,
    -      // Normalized exceptions without a stack have 'stack' set to 'Not
    -      // available', so we check for the existance of 'stack' on the original
    -      // exception instead.
    -      'stack': originalException.stack ||
    -          goog.debug.getStacktrace(goog.debug.Logger.prototype.log)
    -    };
    -
    -    if (goog.isObject(originalException)) {
    -      // Add messageN to the exception in case it was added using
    -      // goog.debug.enhanceError.
    -      for (var i = 0; 'message' + i in originalException; i++) {
    -        exception['message' + i] = String(originalException['message' + i]);
    -      }
    -    }
    -  }
    -  this.channel_.send(this.serviceName_, {
    -    'name': name, 'level': level.value, 'message': msg, 'exception': exception
    -  });
    -};
    -
    -
    -/** @override */
    -goog.messaging.LoggerClient.prototype.disposeInternal = function() {
    -  goog.messaging.LoggerClient.base(this, 'disposeInternal');
    -  goog.debug.LogManager.getRoot().removeHandler(this.publishHandler_);
    -  delete this.channel_;
    -  goog.messaging.LoggerClient.instance_ = null;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/loggerclient_test.html b/src/database/third_party/closure-library/closure/goog/messaging/loggerclient_test.html
    deleted file mode 100644
    index 0d629322dbf..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/loggerclient_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.messaging.LoggerClient
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.messaging.LoggerClientTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/loggerclient_test.js b/src/database/third_party/closure-library/closure/goog/messaging/loggerclient_test.js
    deleted file mode 100644
    index cf5f4faa58c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/loggerclient_test.js
    +++ /dev/null
    @@ -1,97 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.messaging.LoggerClientTest');
    -goog.setTestOnly('goog.messaging.LoggerClientTest');
    -
    -goog.require('goog.debug');
    -goog.require('goog.debug.Logger');
    -goog.require('goog.messaging.LoggerClient');
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.messaging.MockMessageChannel');
    -
    -var mockControl;
    -var channel;
    -var client;
    -var logger;
    -
    -function setUp() {
    -  mockControl = new goog.testing.MockControl();
    -  channel = new goog.testing.messaging.MockMessageChannel(mockControl);
    -  client = new goog.messaging.LoggerClient(channel, 'log');
    -  logger = goog.debug.Logger.getLogger('test.logging.Object');
    -}
    -
    -function tearDown() {
    -  channel.dispose();
    -  client.dispose();
    -}
    -
    -function testCommand() {
    -  channel.send('log', {
    -    name: 'test.logging.Object',
    -    level: goog.debug.Logger.Level.WARNING.value,
    -    message: 'foo bar',
    -    exception: undefined
    -  });
    -  mockControl.$replayAll();
    -  logger.warning('foo bar');
    -  mockControl.$verifyAll();
    -}
    -
    -function testCommandWithException() {
    -  var ex = Error('oh no');
    -  ex.stack = ['one', 'two'];
    -  ex.message0 = 'message 0';
    -  ex.message1 = 'message 1';
    -  ex.ignoredProperty = 'ignored';
    -
    -  channel.send('log', {
    -    name: 'test.logging.Object',
    -    level: goog.debug.Logger.Level.WARNING.value,
    -    message: 'foo bar',
    -    exception: {
    -      name: 'Error',
    -      message: ex.message,
    -      stack: ex.stack,
    -      lineNumber: ex.lineNumber || 'Not available',
    -      fileName: ex.fileName || window.location.href,
    -      message0: ex.message0,
    -      message1: ex.message1
    -    }
    -  });
    -  mockControl.$replayAll();
    -  logger.warning('foo bar', ex);
    -  mockControl.$verifyAll();
    -}
    -
    -function testCommandWithStringException() {
    -  channel.send('log', {
    -    name: 'test.logging.Object',
    -    level: goog.debug.Logger.Level.WARNING.value,
    -    message: 'foo bar',
    -    exception: {
    -      name: 'Unknown error',
    -      message: 'oh no',
    -      stack: '[Anonymous](object, foo bar, oh no)\n' +
    -          '[Anonymous](foo bar, oh no)\n' + goog.debug.getStacktrace(),
    -      lineNumber: 'Not available',
    -      fileName: window.location.href
    -    }
    -  });
    -  mockControl.$replayAll();
    -  logger.warning('foo bar', 'oh no');
    -  mockControl.$verifyAll();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/loggerserver.js b/src/database/third_party/closure-library/closure/goog/messaging/loggerserver.js
    deleted file mode 100644
    index 3bd4e4903da..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/loggerserver.js
    +++ /dev/null
    @@ -1,100 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview This class listens on a message channel for logger commands and
    - * logs them on the local page. This is useful when dealing with message
    - * channels to contexts that don't have access to their own logging facilities.
    - *
    - */
    -
    -goog.provide('goog.messaging.LoggerServer');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.log');
    -goog.require('goog.log.Level');
    -
    -
    -
    -/**
    - * Creates a logger server that logs messages on behalf of the remote end of a
    - * message channel. The remote end of the channel should use a
    - * {goog.messaging.LoggerClient} with the same service name.
    - *
    - * @param {!goog.messaging.MessageChannel} channel The channel that is sending
    - *     the log messages.
    - * @param {string} serviceName The name of the logging service to listen for.
    - * @param {string=} opt_channelName The name of this channel. Used to help
    - *     distinguish this client's messages.
    - * @constructor
    - * @extends {goog.Disposable}
    - * @final
    - */
    -goog.messaging.LoggerServer = function(channel, serviceName, opt_channelName) {
    -  goog.messaging.LoggerServer.base(this, 'constructor');
    -
    -  /**
    -   * The channel that is sending the log messages.
    -   * @type {!goog.messaging.MessageChannel}
    -   * @private
    -   */
    -  this.channel_ = channel;
    -
    -  /**
    -   * The name of the logging service to listen for.
    -   * @type {string}
    -   * @private
    -   */
    -  this.serviceName_ = serviceName;
    -
    -  /**
    -   * The name of the channel.
    -   * @type {string}
    -   * @private
    -   */
    -  this.channelName_ = opt_channelName || 'remote logger';
    -
    -  this.channel_.registerService(
    -      this.serviceName_, goog.bind(this.log_, this), true /* opt_json */);
    -};
    -goog.inherits(goog.messaging.LoggerServer, goog.Disposable);
    -
    -
    -/**
    - * Handles logging messages from the client.
    - * @param {!Object|string} message
    - *     The logging information from the client.
    - * @private
    - */
    -goog.messaging.LoggerServer.prototype.log_ = function(message) {
    -  var args =
    -      /**
    -       * @type {{level: number, message: string,
    -       *           name: string, exception: Object}}
    -       */ (message);
    -  var level = goog.log.Level.getPredefinedLevelByValue(args['level']);
    -  if (level) {
    -    var msg = '[' + this.channelName_ + '] ' + args['message'];
    -    goog.log.getLogger(args['name'])
    -        .log(level, msg, args['exception']);
    -  }
    -};
    -
    -
    -/** @override */
    -goog.messaging.LoggerServer.prototype.disposeInternal = function() {
    -  goog.messaging.LoggerServer.base(this, 'disposeInternal');
    -  this.channel_.registerService(this.serviceName_, goog.nullFunction, true);
    -  delete this.channel_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/loggerserver_test.html b/src/database/third_party/closure-library/closure/goog/messaging/loggerserver_test.html
    deleted file mode 100644
    index ed4de99bdb7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/loggerserver_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.messaging.LoggerServer
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.messaging.LoggerServerTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/loggerserver_test.js b/src/database/third_party/closure-library/closure/goog/messaging/loggerserver_test.js
    deleted file mode 100644
    index 98ac7e2a96b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/loggerserver_test.js
    +++ /dev/null
    @@ -1,101 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.messaging.LoggerServerTest');
    -goog.setTestOnly('goog.messaging.LoggerServerTest');
    -
    -goog.require('goog.debug.LogManager');
    -goog.require('goog.debug.Logger');
    -goog.require('goog.log');
    -goog.require('goog.log.Level');
    -goog.require('goog.messaging.LoggerServer');
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.messaging.MockMessageChannel');
    -
    -var mockControl;
    -var channel;
    -var stubs;
    -
    -function setUpPage() {
    -  stubs = new goog.testing.PropertyReplacer();
    -}
    -
    -function setUp() {
    -  mockControl = new goog.testing.MockControl();
    -  channel = new goog.testing.messaging.MockMessageChannel(mockControl);
    -  stubs.set(goog.debug.LogManager, 'getLogger',
    -            mockControl.createFunctionMock('goog.log.getLogger'));
    -}
    -
    -function tearDown() {
    -  channel.dispose();
    -  stubs.reset();
    -}
    -
    -function testCommandWithoutChannelName() {
    -  var mockLogger = mockControl.createStrictMock(goog.debug.Logger);
    -  goog.log.getLogger('test.object.Name').$returns(mockLogger);
    -  goog.log.log(mockLogger,
    -      goog.log.Level.SEVERE, '[remote logger] foo bar', null);
    -  mockControl.$replayAll();
    -
    -  var server = new goog.messaging.LoggerServer(channel, 'log');
    -  channel.receive('log', {
    -    name: 'test.object.Name',
    -    level: goog.log.Level.SEVERE.value,
    -    message: 'foo bar',
    -    exception: null
    -  });
    -  mockControl.$verifyAll();
    -  server.dispose();
    -}
    -
    -function testCommandWithChannelName() {
    -  var mockLogger = mockControl.createStrictMock(goog.debug.Logger);
    -  goog.log.getLogger('test.object.Name').$returns(mockLogger);
    -  goog.log.log(mockLogger,
    -      goog.log.Level.SEVERE, '[some channel] foo bar', null);
    -  mockControl.$replayAll();
    -
    -  var server = new goog.messaging.LoggerServer(channel, 'log', 'some channel');
    -  channel.receive('log', {
    -    name: 'test.object.Name',
    -    level: goog.log.Level.SEVERE.value,
    -    message: 'foo bar',
    -    exception: null
    -  });
    -  mockControl.$verifyAll();
    -  server.dispose();
    -}
    -
    -function testCommandWithException() {
    -  var mockLogger = mockControl.createStrictMock(goog.debug.Logger);
    -  goog.log.getLogger('test.object.Name').$returns(mockLogger);
    -  goog.log.log(mockLogger,
    -      goog.log.Level.SEVERE, '[some channel] foo bar',
    -      {message: 'Bad things', stack: ['foo', 'bar']});
    -  mockControl.$replayAll();
    -
    -  var server = new goog.messaging.LoggerServer(channel, 'log', 'some channel');
    -  channel.receive('log', {
    -    name: 'test.object.Name',
    -    level: goog.log.Level.SEVERE.value,
    -    message: 'foo bar',
    -    exception: {message: 'Bad things', stack: ['foo', 'bar']}
    -  });
    -  mockControl.$verifyAll();
    -  server.dispose();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/messagechannel.js b/src/database/third_party/closure-library/closure/goog/messaging/messagechannel.js
    deleted file mode 100644
    index 8f994719310..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/messagechannel.js
    +++ /dev/null
    @@ -1,116 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview An interface for asynchronous message-passing channels.
    - *
    - * This interface is useful for writing code in a message-passing style that's
    - * independent of the underlying communication medium. It's also useful for
    - * adding decorators that wrap message channels and add extra functionality on
    - * top. For example, {@link goog.messaging.BufferedChannel} enqueues messages
    - * until communication is established, while {@link goog.messaging.MultiChannel}
    - * splits a single underlying channel into multiple virtual ones.
    - *
    - * Decorators should be passed their underlying channel(s) in the constructor,
    - * and should assume that those channels are already connected. Decorators are
    - * responsible for disposing of the channels they wrap when the decorators
    - * themselves are disposed. Decorators should also follow the APIs of the
    - * individual methods listed below.
    - *
    - */
    -
    -
    -goog.provide('goog.messaging.MessageChannel');
    -
    -
    -
    -/**
    - * @interface
    - */
    -goog.messaging.MessageChannel = function() {};
    -
    -
    -/**
    - * Initiates the channel connection. When this method is called, all the
    - * information needed to connect the channel has to be available.
    - *
    - * Implementers should only require this method to be called if the channel
    - * needs to be configured in some way between when it's created and when it
    - * becomes active. Otherwise, the channel should be immediately active and this
    - * method should do nothing but immediately call opt_connectCb.
    - *
    - * @param {Function=} opt_connectCb Called when the channel has been connected
    - *     and is ready to use.
    - */
    -goog.messaging.MessageChannel.prototype.connect = function(opt_connectCb) {};
    -
    -
    -/**
    - * Gets whether the channel is connected.
    - *
    - * If {@link #connect} is not required for this class, this should always return
    - * true. Otherwise, this should return true by the time the callback passed to
    - * {@link #connect} has been called and always after that.
    - *
    - * @return {boolean} Whether the channel is connected.
    - */
    -goog.messaging.MessageChannel.prototype.isConnected = function() {};
    -
    -
    -/**
    - * Registers a service to be called when a message is received.
    - *
    - * Implementers shouldn't impose any restrictions on the service names that may
    - * be registered. If some services are needed as control codes,
    - * {@link goog.messaging.MultiMessageChannel} can be used to safely split the
    - * channel into "public" and "control" virtual channels.
    - *
    - * @param {string} serviceName The name of the service.
    - * @param {function((string|!Object))} callback The callback to process the
    - *     incoming messages. Passed the payload. If opt_objectPayload is set, the
    - *     payload is decoded and passed as an object.
    - * @param {boolean=} opt_objectPayload If true, incoming messages for this
    - *     service are expected to contain an object, and will be deserialized from
    - *     a string automatically if necessary. It's the responsibility of
    - *     implementors of this class to perform the deserialization.
    - */
    -goog.messaging.MessageChannel.prototype.registerService =
    -    function(serviceName, callback, opt_objectPayload) {};
    -
    -
    -/**
    - * Registers a service to be called when a message is received that doesn't
    - * match any other services.
    - *
    - * @param {function(string, (string|!Object))} callback The callback to process
    - *     the incoming messages. Passed the service name and the payload. Since
    - *     some channels can pass objects natively, the payload may be either an
    - *     object or a string.
    - */
    -goog.messaging.MessageChannel.prototype.registerDefaultService =
    -    function(callback) {};
    -
    -
    -/**
    - * Sends a message over the channel.
    - *
    - * @param {string} serviceName The name of the service this message should be
    - *     delivered to.
    - * @param {string|!Object} payload The value of the message. If this is an
    - *     Object, it is serialized to a string before sending if necessary. It's
    - *     the responsibility of implementors of this class to perform the
    - *     serialization.
    - */
    -goog.messaging.MessageChannel.prototype.send =
    -    function(serviceName, payload) {};
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/messaging.js b/src/database/third_party/closure-library/closure/goog/messaging/messaging.js
    deleted file mode 100644
    index d96d67a1e47..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/messaging.js
    +++ /dev/null
    @@ -1,32 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Functions for manipulating message channels.
    - *
    - */
    -
    -goog.provide('goog.messaging');
    -
    -
    -/**
    - * Creates a bidirectional pipe between two message channels.
    - *
    - * @param {goog.messaging.MessageChannel} channel1 The first channel.
    - * @param {goog.messaging.MessageChannel} channel2 The second channel.
    - */
    -goog.messaging.pipe = function(channel1, channel2) {
    -  channel1.registerDefaultService(goog.bind(channel2.send, channel2));
    -  channel2.registerDefaultService(goog.bind(channel1.send, channel1));
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/messaging_test.html b/src/database/third_party/closure-library/closure/goog/messaging/messaging_test.html
    deleted file mode 100644
    index e7dd63eb542..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/messaging_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.messaging
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.messaging.MockMessageChannelTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/messaging_test.js b/src/database/third_party/closure-library/closure/goog/messaging/messaging_test.js
    deleted file mode 100644
    index a3610cc2623..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/messaging_test.js
    +++ /dev/null
    @@ -1,35 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.messaging.MockMessageChannelTest');
    -goog.setTestOnly('goog.testing.messaging.MockMessageChannelTest');
    -
    -goog.require('goog.messaging');
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.messaging.MockMessageChannel');
    -
    -function testPipe() {
    -  var mockControl = new goog.testing.MockControl();
    -  var ch1 = new goog.testing.messaging.MockMessageChannel(mockControl);
    -  var ch2 = new goog.testing.messaging.MockMessageChannel(mockControl);
    -  ch1.send('ping', 'HELLO');
    -  ch2.send('pong', {key: 'value'});
    -  goog.messaging.pipe(ch1, ch2);
    -
    -  mockControl.$replayAll();
    -  ch2.receive('ping', 'HELLO');
    -  ch1.receive('pong', {key: 'value'});
    -  mockControl.$verifyAll();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/multichannel.js b/src/database/third_party/closure-library/closure/goog/messaging/multichannel.js
    deleted file mode 100644
    index b3bf68474f3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/multichannel.js
    +++ /dev/null
    @@ -1,303 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Definition of goog.messaging.MultiChannel, which uses a
    - * single underlying MessageChannel to carry several independent virtual message
    - * channels.
    - *
    - */
    -
    -
    -goog.provide('goog.messaging.MultiChannel');
    -goog.provide('goog.messaging.MultiChannel.VirtualChannel');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.log');
    -goog.require('goog.messaging.MessageChannel'); // interface
    -goog.require('goog.object');
    -
    -
    -
    -/**
    - * Creates a new MultiChannel wrapping a single MessageChannel. The
    - * underlying channel shouldn't have any other listeners registered, but it
    - * should be connected.
    - *
    - * Note that the other side of the channel should also be connected to a
    - * MultiChannel with the same number of virtual channels.
    - *
    - * @param {goog.messaging.MessageChannel} underlyingChannel The underlying
    - *     channel to use as transport for the virtual channels.
    - * @constructor
    - * @extends {goog.Disposable}
    - * @final
    - */
    -goog.messaging.MultiChannel = function(underlyingChannel) {
    -  goog.messaging.MultiChannel.base(this, 'constructor');
    -
    -  /**
    -   * The underlying channel across which all requests are sent.
    -   * @type {goog.messaging.MessageChannel}
    -   * @private
    -   */
    -  this.underlyingChannel_ = underlyingChannel;
    -
    -  /**
    -   * All the virtual channels that are registered for this MultiChannel.
    -   * These are null if they've been disposed.
    -   * @type {Object<?goog.messaging.MultiChannel.VirtualChannel>}
    -   * @private
    -   */
    -  this.virtualChannels_ = {};
    -
    -  this.underlyingChannel_.registerDefaultService(
    -      goog.bind(this.handleDefault_, this));
    -};
    -goog.inherits(goog.messaging.MultiChannel, goog.Disposable);
    -
    -
    -/**
    - * Logger object for goog.messaging.MultiChannel.
    - * @type {goog.log.Logger}
    - * @private
    - */
    -goog.messaging.MultiChannel.prototype.logger_ =
    -    goog.log.getLogger('goog.messaging.MultiChannel');
    -
    -
    -/**
    - * Creates a new virtual channel that will communicate across the underlying
    - * channel.
    - * @param {string} name The name of the virtual channel. Must be unique for this
    - *     MultiChannel. Cannot contain colons.
    - * @return {!goog.messaging.MultiChannel.VirtualChannel} The new virtual
    - *     channel.
    - */
    -goog.messaging.MultiChannel.prototype.createVirtualChannel = function(name) {
    -  if (name.indexOf(':') != -1) {
    -    throw Error(
    -        'Virtual channel name "' + name + '" should not contain colons');
    -  }
    -
    -  if (name in this.virtualChannels_) {
    -    throw Error('Virtual channel "' + name + '" was already created for ' +
    -                'this multichannel.');
    -  }
    -
    -  var channel =
    -      new goog.messaging.MultiChannel.VirtualChannel(this, name);
    -  this.virtualChannels_[name] = channel;
    -  return channel;
    -};
    -
    -
    -/**
    - * Handles the default service for the underlying channel. This dispatches any
    - * unrecognized services to the appropriate virtual channel.
    - *
    - * @param {string} serviceName The name of the service being called.
    - * @param {string|!Object} payload The message payload.
    - * @private
    - */
    -goog.messaging.MultiChannel.prototype.handleDefault_ = function(
    -    serviceName, payload) {
    -  var match = serviceName.match(/^([^:]*):(.*)/);
    -  if (!match) {
    -    goog.log.warning(this.logger_,
    -        'Invalid service name "' + serviceName + '": no ' +
    -        'virtual channel specified');
    -    return;
    -  }
    -
    -  var channelName = match[1];
    -  serviceName = match[2];
    -  if (!(channelName in this.virtualChannels_)) {
    -    goog.log.warning(this.logger_,
    -        'Virtual channel "' + channelName + ' does not ' +
    -        'exist, but a message was received for it: "' + serviceName + '"');
    -    return;
    -  }
    -
    -  var virtualChannel = this.virtualChannels_[channelName];
    -  if (!virtualChannel) {
    -    goog.log.warning(this.logger_,
    -        'Virtual channel "' + channelName + ' has been ' +
    -        'disposed, but a message was received for it: "' + serviceName + '"');
    -    return;
    -  }
    -
    -  if (!virtualChannel.defaultService_) {
    -    goog.log.warning(this.logger_,
    -        'Service "' + serviceName + '" is not registered ' +
    -        'on virtual channel "' + channelName + '"');
    -    return;
    -  }
    -
    -  virtualChannel.defaultService_(serviceName, payload);
    -};
    -
    -
    -/** @override */
    -goog.messaging.MultiChannel.prototype.disposeInternal = function() {
    -  goog.object.forEach(this.virtualChannels_, function(channel) {
    -    goog.dispose(channel);
    -  });
    -  goog.dispose(this.underlyingChannel_);
    -  delete this.virtualChannels_;
    -  delete this.underlyingChannel_;
    -};
    -
    -
    -
    -/**
    - * A message channel that proxies its messages over another underlying channel.
    - *
    - * @param {goog.messaging.MultiChannel} parent The MultiChannel
    - *     which created this channel, and which contains the underlying
    - *     MessageChannel that's used as the transport.
    - * @param {string} name The name of this virtual channel. Unique among the
    - *     virtual channels in parent.
    - * @constructor
    - * @implements {goog.messaging.MessageChannel}
    - * @extends {goog.Disposable}
    - * @final
    - */
    -goog.messaging.MultiChannel.VirtualChannel = function(parent, name) {
    -  goog.messaging.MultiChannel.VirtualChannel.base(this, 'constructor');
    -
    -  /**
    -   * The MultiChannel containing the underlying transport channel.
    -   * @type {goog.messaging.MultiChannel}
    -   * @private
    -   */
    -  this.parent_ = parent;
    -
    -  /**
    -   * The name of this virtual channel.
    -   * @type {string}
    -   * @private
    -   */
    -  this.name_ = name;
    -};
    -goog.inherits(goog.messaging.MultiChannel.VirtualChannel,
    -              goog.Disposable);
    -
    -
    -/**
    - * The default service to run if no other services match.
    - * @type {?function(string, (string|!Object))}
    - * @private
    - */
    -goog.messaging.MultiChannel.VirtualChannel.prototype.defaultService_;
    -
    -
    -/**
    - * Logger object for goog.messaging.MultiChannel.VirtualChannel.
    - * @type {goog.log.Logger}
    - * @private
    - */
    -goog.messaging.MultiChannel.VirtualChannel.prototype.logger_ =
    -    goog.log.getLogger(
    -        'goog.messaging.MultiChannel.VirtualChannel');
    -
    -
    -/**
    - * This is a no-op, since the underlying channel is expected to already be
    - * initialized when it's passed in.
    - *
    - * @override
    - */
    -goog.messaging.MultiChannel.VirtualChannel.prototype.connect =
    -    function(opt_connectCb) {
    -  if (opt_connectCb) {
    -    opt_connectCb();
    -  }
    -};
    -
    -
    -/**
    - * This always returns true, since the underlying channel is expected to already
    - * be initialized when it's passed in.
    - *
    - * @override
    - */
    -goog.messaging.MultiChannel.VirtualChannel.prototype.isConnected =
    -    function() {
    -  return true;
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.messaging.MultiChannel.VirtualChannel.prototype.registerService =
    -    function(serviceName, callback, opt_objectPayload) {
    -  this.parent_.underlyingChannel_.registerService(
    -      this.name_ + ':' + serviceName,
    -      goog.bind(this.doCallback_, this, callback),
    -      opt_objectPayload);
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.messaging.MultiChannel.VirtualChannel.prototype.
    -    registerDefaultService = function(callback) {
    -  this.defaultService_ = goog.bind(this.doCallback_, this, callback);
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.messaging.MultiChannel.VirtualChannel.prototype.send =
    -    function(serviceName, payload) {
    -  if (this.isDisposed()) {
    -    throw Error('#send called for disposed VirtualChannel.');
    -  }
    -
    -  this.parent_.underlyingChannel_.send(this.name_ + ':' + serviceName,
    -                                       payload);
    -};
    -
    -
    -/**
    - * Wraps a callback with a function that will log a warning and abort if it's
    - * called when this channel is disposed.
    - *
    - * @param {function()} callback The callback to wrap.
    - * @param {...*} var_args Other arguments, passed to the callback.
    - * @private
    - */
    -goog.messaging.MultiChannel.VirtualChannel.prototype.doCallback_ =
    -    function(callback, var_args) {
    -  if (this.isDisposed()) {
    -    goog.log.warning(this.logger_,
    -        'Virtual channel "' + this.name_ + '" received ' +
    -        ' a message after being disposed.');
    -    return;
    -  }
    -
    -  callback.apply({}, Array.prototype.slice.call(arguments, 1));
    -};
    -
    -
    -/** @override */
    -goog.messaging.MultiChannel.VirtualChannel.prototype.disposeInternal =
    -    function() {
    -  this.parent_.virtualChannels_[this.name_] = null;
    -  this.parent_ = null;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/multichannel_test.html b/src/database/third_party/closure-library/closure/goog/messaging/multichannel_test.html
    deleted file mode 100644
    index ac61e0952eb..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/multichannel_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.messaging.MultiChannel
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.messaging.MultiChannelTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/multichannel_test.js b/src/database/third_party/closure-library/closure/goog/messaging/multichannel_test.js
    deleted file mode 100644
    index ddea8efe87c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/multichannel_test.js
    +++ /dev/null
    @@ -1,116 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.messaging.MultiChannelTest');
    -goog.setTestOnly('goog.messaging.MultiChannelTest');
    -
    -goog.require('goog.messaging.MultiChannel');
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.messaging.MockMessageChannel');
    -goog.require('goog.testing.mockmatchers.IgnoreArgument');
    -
    -var mockControl;
    -var mockChannel;
    -var multiChannel;
    -var channel1;
    -var channel2;
    -
    -function setUp() {
    -  mockControl = new goog.testing.MockControl();
    -  mockChannel = new goog.testing.messaging.MockMessageChannel(mockControl);
    -  multiChannel = new goog.messaging.MultiChannel(mockChannel);
    -  channel0 = multiChannel.createVirtualChannel('foo');
    -  channel1 = multiChannel.createVirtualChannel('bar');
    -}
    -
    -function expectedFn(name, callback) {
    -  var ignored = new goog.testing.mockmatchers.IgnoreArgument();
    -  var fn = mockControl.createFunctionMock(name);
    -  fn(ignored).$does(function(args) {
    -    callback.apply(this, args);
    -  });
    -  return function() { fn(arguments); };
    -}
    -
    -function notExpectedFn() {
    -  return mockControl.createFunctionMock('notExpectedFn');
    -}
    -
    -function assertEqualsFn() {
    -  var expectedArgs = Array.prototype.slice.call(arguments);
    -  return expectedFn('assertEqualsFn', function() {
    -    assertObjectEquals(expectedArgs, Array.prototype.slice.call(arguments));
    -  });
    -}
    -
    -function tearDown() {
    -  multiChannel.dispose();
    -  mockControl.$verifyAll();
    -  assertTrue(mockChannel.disposed);
    -}
    -
    -function testSend0() {
    -  mockChannel.send('foo:fooBar', {foo: 'bar'});
    -  mockControl.$replayAll();
    -  channel0.send('fooBar', {foo: 'bar'});
    -}
    -
    -function testSend1() {
    -  mockChannel.send('bar:fooBar', {foo: 'bar'});
    -  mockControl.$replayAll();
    -  channel1.send('fooBar', {foo: 'bar'});
    -}
    -
    -function testReceive0() {
    -  channel0.registerService('fooBar', assertEqualsFn('Baz bang'));
    -  channel1.registerService('fooBar', notExpectedFn());
    -  mockControl.$replayAll();
    -  mockChannel.receive('foo:fooBar', 'Baz bang');
    -}
    -
    -function testReceive1() {
    -  channel1.registerService('fooBar', assertEqualsFn('Baz bang'));
    -  channel0.registerService('fooBar', notExpectedFn());
    -  mockControl.$replayAll();
    -  mockChannel.receive('bar:fooBar', 'Baz bang');
    -}
    -
    -function testDefaultReceive0() {
    -  channel0.registerDefaultService(assertEqualsFn('fooBar', 'Baz bang'));
    -  channel1.registerDefaultService(notExpectedFn());
    -  mockControl.$replayAll();
    -  mockChannel.receive('foo:fooBar', 'Baz bang');
    -}
    -
    -function testDefaultReceive1() {
    -  channel1.registerDefaultService(assertEqualsFn('fooBar', 'Baz bang'));
    -  channel0.registerDefaultService(notExpectedFn());
    -  mockControl.$replayAll();
    -  mockChannel.receive('bar:fooBar', 'Baz bang');
    -}
    -
    -function testReceiveAfterDisposed() {
    -  channel0.registerService('fooBar', notExpectedFn());
    -  mockControl.$replayAll();
    -  channel0.dispose();
    -  mockChannel.receive('foo:fooBar', 'Baz bang');
    -}
    -
    -function testReceiveAfterParentDisposed() {
    -  channel0.registerService('fooBar', notExpectedFn());
    -  mockControl.$replayAll();
    -  multiChannel.dispose();
    -  mockChannel.receive('foo:fooBar', 'Baz bang');
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/portcaller.js b/src/database/third_party/closure-library/closure/goog/messaging/portcaller.js
    deleted file mode 100644
    index 7a9f7a4b59e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/portcaller.js
    +++ /dev/null
    @@ -1,152 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview The leaf node of a {@link goog.messaging.PortNetwork}. Callers
    - * connect to the operator, and request connections with other contexts from it.
    - *
    - */
    -
    -goog.provide('goog.messaging.PortCaller');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.async.Deferred');
    -goog.require('goog.messaging.DeferredChannel');
    -goog.require('goog.messaging.PortChannel');
    -goog.require('goog.messaging.PortNetwork'); // interface
    -goog.require('goog.object');
    -
    -
    -
    -/**
    - * The leaf node of a network.
    - *
    - * @param {!goog.messaging.MessageChannel} operatorPort The channel for
    - *     communicating with the operator. The other side of this channel should be
    - *     passed to {@link goog.messaging.PortOperator#addPort}. Must be either a
    - *     {@link goog.messaging.PortChannel} or a decorator wrapping a PortChannel;
    - *     in particular, it must be able to send and receive {@link MessagePort}s.
    - * @constructor
    - * @extends {goog.Disposable}
    - * @implements {goog.messaging.PortNetwork}
    - * @final
    - */
    -goog.messaging.PortCaller = function(operatorPort) {
    -  goog.messaging.PortCaller.base(this, 'constructor');
    -
    -  /**
    -   * The channel to the {@link goog.messaging.PortOperator} for this network.
    -   *
    -   * @type {!goog.messaging.MessageChannel}
    -   * @private
    -   */
    -  this.operatorPort_ = operatorPort;
    -
    -  /**
    -   * The collection of channels for communicating with other contexts in the
    -   * network. Each value can contain a {@link goog.aync.Deferred} and/or a
    -   * {@link goog.messaging.MessageChannel}.
    -   *
    -   * If the value contains a Deferred, then the channel is a
    -   * {@link goog.messaging.DeferredChannel} wrapping that Deferred. The Deferred
    -   * will be resolved with a {@link goog.messaging.PortChannel} once we receive
    -   * the appropriate port from the operator. This is the situation when this
    -   * caller requests a connection to another context; the DeferredChannel is
    -   * used to queue up messages until we receive the port from the operator.
    -   *
    -   * If the value does not contain a Deferred, then the channel is simply a
    -   * {@link goog.messaging.PortChannel} communicating with the given context.
    -   * This is the situation when this context received a port for the other
    -   * context before it was requested.
    -   *
    -   * If a value exists for a given key, it must contain a channel, but it
    -   * doesn't necessarily contain a Deferred.
    -   *
    -   * @type {!Object<{deferred: goog.async.Deferred,
    -   *                  channel: !goog.messaging.MessageChannel}>}
    -   * @private
    -   */
    -  this.connections_ = {};
    -
    -  this.operatorPort_.registerService(
    -      goog.messaging.PortNetwork.GRANT_CONNECTION_SERVICE,
    -      goog.bind(this.connectionGranted_, this),
    -      true /* opt_json */);
    -};
    -goog.inherits(goog.messaging.PortCaller, goog.Disposable);
    -
    -
    -/** @override */
    -goog.messaging.PortCaller.prototype.dial = function(name) {
    -  if (name in this.connections_) {
    -    return this.connections_[name].channel;
    -  }
    -
    -  this.operatorPort_.send(
    -      goog.messaging.PortNetwork.REQUEST_CONNECTION_SERVICE, name);
    -  var deferred = new goog.async.Deferred();
    -  var channel = new goog.messaging.DeferredChannel(deferred);
    -  this.connections_[name] = {deferred: deferred, channel: channel};
    -  return channel;
    -};
    -
    -
    -/**
    - * Registers a connection to another context in the network. This is called when
    - * the operator sends us one end of a {@link MessageChannel}, either because
    - * this caller requested a connection with another context, or because that
    - * context requested a connection with this caller.
    - *
    - * It's possible that the remote context and this one request each other roughly
    - * concurrently. The operator doesn't keep track of which contexts have been
    - * connected, so it will create two separate {@link MessageChannel}s in this
    - * case. However, the first channel created will reach both contexts first, so
    - * we simply ignore all connections with a given context after the first.
    - *
    - * @param {!Object|string} message The name of the context
    - *     being connected and the port connecting the context.
    - * @private
    - */
    -goog.messaging.PortCaller.prototype.connectionGranted_ = function(message) {
    -  var args = /** @type {{name: string, port: MessagePort}} */ (message);
    -  var port = args['port'];
    -  var entry = this.connections_[args['name']];
    -  if (entry && (!entry.deferred || entry.deferred.hasFired())) {
    -    // If two PortCallers request one another at the same time, the operator may
    -    // send out a channel for connecting them multiple times. Since both callers
    -    // will receive the first channel's ports first, we can safely ignore and
    -    // close any future ports.
    -    port.close();
    -  } else if (!args['success']) {
    -    throw Error(args['message']);
    -  } else {
    -    port.start();
    -    var channel = new goog.messaging.PortChannel(port);
    -    if (entry) {
    -      entry.deferred.callback(channel);
    -    } else {
    -      this.connections_[args['name']] = {channel: channel, deferred: null};
    -    }
    -  }
    -};
    -
    -
    -/** @override */
    -goog.messaging.PortCaller.prototype.disposeInternal = function() {
    -  goog.dispose(this.operatorPort_);
    -  goog.object.forEach(this.connections_, goog.dispose);
    -  delete this.operatorPort_;
    -  delete this.connections_;
    -  goog.messaging.PortCaller.base(this, 'disposeInternal');
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/portcaller_test.html b/src/database/third_party/closure-library/closure/goog/messaging/portcaller_test.html
    deleted file mode 100644
    index 2bf256574f3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/portcaller_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.messaging.PortCaller
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.messaging.PortCallerTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/portcaller_test.js b/src/database/third_party/closure-library/closure/goog/messaging/portcaller_test.js
    deleted file mode 100644
    index 3f4a002427d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/portcaller_test.js
    +++ /dev/null
    @@ -1,58 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.messaging.PortCallerTest');
    -goog.setTestOnly('goog.messaging.PortCallerTest');
    -
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.messaging.PortCaller');
    -goog.require('goog.messaging.PortNetwork');
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.messaging.MockMessageChannel');
    -
    -var mockControl;
    -var mockChannel;
    -var caller;
    -
    -function setUp() {
    -  mockControl = new goog.testing.MockControl();
    -  mockChannel = new goog.testing.messaging.MockMessageChannel(mockControl);
    -  caller = new goog.messaging.PortCaller(mockChannel);
    -}
    -
    -function tearDown() {
    -  goog.dispose(caller);
    -  mockControl.$verifyAll();
    -}
    -
    -function MockMessagePort(index, port) {
    -  goog.base(this);
    -  this.index = index;
    -  this.port = port;
    -  this.started = false;
    -}
    -goog.inherits(MockMessagePort, goog.events.EventTarget);
    -
    -
    -MockMessagePort.prototype.start = function() {
    -  this.started = true;
    -};
    -
    -function testGetPort() {
    -  mockChannel.send(
    -      goog.messaging.PortNetwork.REQUEST_CONNECTION_SERVICE, 'foo');
    -  mockControl.$replayAll();
    -  caller.dial('foo');
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/portchannel.js b/src/database/third_party/closure-library/closure/goog/messaging/portchannel.js
    deleted file mode 100644
    index 1904a476ec8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/portchannel.js
    +++ /dev/null
    @@ -1,401 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A class that wraps several types of HTML5 message-passing
    - * entities ({@link MessagePort}s, {@link WebWorker}s, and {@link Window}s),
    - * providing a unified interface.
    - *
    - * This is tested under Chrome, Safari, and Firefox. Since Firefox 3.6 has an
    - * incomplete implementation of web workers, it doesn't support sending ports
    - * over Window connections. IE has no web worker support at all, and so is
    - * unsupported by this class.
    - *
    - */
    -
    -goog.provide('goog.messaging.PortChannel');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.array');
    -goog.require('goog.async.Deferred');
    -goog.require('goog.debug');
    -goog.require('goog.events');
    -goog.require('goog.events.EventType');
    -goog.require('goog.json');
    -goog.require('goog.log');
    -goog.require('goog.messaging.AbstractChannel');
    -goog.require('goog.messaging.DeferredChannel');
    -goog.require('goog.object');
    -goog.require('goog.string');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * A wrapper for several types of HTML5 message-passing entities
    - * ({@link MessagePort}s and {@link WebWorker}s). This class implements the
    - * {@link goog.messaging.MessageChannel} interface.
    - *
    - * This class can be used in conjunction with other communication on the port.
    - * It sets {@link goog.messaging.PortChannel.FLAG} to true on all messages it
    - * sends.
    - *
    - * @param {!MessagePort|!WebWorker} underlyingPort The message-passing
    - *     entity to wrap. If this is a {@link MessagePort}, it should be started.
    - *     The remote end should also be wrapped in a PortChannel. This will be
    - *     disposed along with the PortChannel; this means terminating it if it's a
    - *     worker or removing it from the DOM if it's an iframe.
    - * @constructor
    - * @extends {goog.messaging.AbstractChannel}
    - * @final
    - */
    -goog.messaging.PortChannel = function(underlyingPort) {
    -  goog.messaging.PortChannel.base(this, 'constructor');
    -
    -  /**
    -   * The wrapped message-passing entity.
    -   * @type {!MessagePort|!WebWorker}
    -   * @private
    -   */
    -  this.port_ = underlyingPort;
    -
    -  /**
    -   * The key for the event listener.
    -   * @type {goog.events.Key}
    -   * @private
    -   */
    -  this.listenerKey_ = goog.events.listen(
    -      this.port_, goog.events.EventType.MESSAGE, this.deliver_, false, this);
    -};
    -goog.inherits(goog.messaging.PortChannel, goog.messaging.AbstractChannel);
    -
    -
    -/**
    - * Create a PortChannel that communicates with a window embedded in the current
    - * page (e.g. an iframe contentWindow). The code within the window should call
    - * {@link forGlobalWindow} to establish the connection.
    - *
    - * It's possible to use this channel in conjunction with other messages to the
    - * embedded window. However, only one PortChannel should be used for a given
    - * window at a time.
    - *
    - * @param {!Window} window The window object to communicate with.
    - * @param {string} peerOrigin The expected origin of the window. See
    - *     http://dev.w3.org/html5/postmsg/#dom-window-postmessage.
    - * @param {goog.Timer=} opt_timer The timer that regulates how often the initial
    - *     connection message is attempted. This will be automatically disposed once
    - *     the connection is established, or when the connection is cancelled.
    - * @return {!goog.messaging.DeferredChannel} The PortChannel. Although this is
    - *     not actually an instance of the PortChannel class, it will behave like
    - *     one in that MessagePorts may be sent across it. The DeferredChannel may
    - *     be cancelled before a connection is established in order to abort the
    - *     attempt to make a connection.
    - */
    -goog.messaging.PortChannel.forEmbeddedWindow = function(
    -    window, peerOrigin, opt_timer) {
    -  var timer = opt_timer || new goog.Timer(50);
    -
    -  var disposeTimer = goog.partial(goog.dispose, timer);
    -  var deferred = new goog.async.Deferred(disposeTimer);
    -  deferred.addBoth(disposeTimer);
    -
    -  timer.start();
    -  // Every tick, attempt to set up a connection by sending in one end of an
    -  // HTML5 MessageChannel. If the inner window posts a response along a channel,
    -  // then we'll use that channel to create the PortChannel.
    -  //
    -  // As per http://dev.w3.org/html5/postmsg/#ports-and-garbage-collection, any
    -  // ports that are not ultimately used to set up the channel will be garbage
    -  // collected (since there are no references in this context, and the remote
    -  // context hasn't seen them).
    -  goog.events.listen(timer, goog.Timer.TICK, function() {
    -    var channel = new MessageChannel();
    -    var gotMessage = function(e) {
    -      channel.port1.removeEventListener(
    -          goog.events.EventType.MESSAGE, gotMessage, true);
    -      // If the connection has been cancelled, don't create the channel.
    -      if (!timer.isDisposed()) {
    -        deferred.callback(new goog.messaging.PortChannel(channel.port1));
    -      }
    -    };
    -    channel.port1.start();
    -    // Don't use goog.events because we don't want any lingering references to
    -    // the ports to prevent them from getting GCed. Only modern browsers support
    -    // these APIs anyway, so we don't need to worry about event API
    -    // compatibility.
    -    channel.port1.addEventListener(
    -        goog.events.EventType.MESSAGE, gotMessage, true);
    -
    -    var msg = {};
    -    msg[goog.messaging.PortChannel.FLAG] = true;
    -    window.postMessage(msg, peerOrigin, [channel.port2]);
    -  });
    -
    -  return new goog.messaging.DeferredChannel(deferred);
    -};
    -
    -
    -/**
    - * Create a PortChannel that communicates with the document in which this window
    - * is embedded (e.g. within an iframe). The enclosing document should call
    - * {@link forEmbeddedWindow} to establish the connection.
    - *
    - * It's possible to use this channel in conjunction with other messages posted
    - * to the global window. However, only one PortChannel should be used for the
    - * global window at a time.
    - *
    - * @param {string} peerOrigin The expected origin of the enclosing document. See
    - *     http://dev.w3.org/html5/postmsg/#dom-window-postmessage.
    - * @return {!goog.messaging.MessageChannel} The PortChannel. Although this may
    - *     not actually be an instance of the PortChannel class, it will behave like
    - *     one in that MessagePorts may be sent across it.
    - */
    -goog.messaging.PortChannel.forGlobalWindow = function(peerOrigin) {
    -  var deferred = new goog.async.Deferred();
    -  // Wait for the external page to post a message containing the message port
    -  // which we'll use to set up the PortChannel. Ignore all other messages. Once
    -  // we receive the port, notify the other end and then set up the PortChannel.
    -  var key = goog.events.listen(
    -      window, goog.events.EventType.MESSAGE, function(e) {
    -        var browserEvent = e.getBrowserEvent();
    -        var data = browserEvent.data;
    -        if (!goog.isObject(data) || !data[goog.messaging.PortChannel.FLAG]) {
    -          return;
    -        }
    -
    -        if (peerOrigin != '*' && peerOrigin != browserEvent.origin) {
    -          return;
    -        }
    -
    -        var port = browserEvent.ports[0];
    -        // Notify the other end of the channel that we've received our port
    -        port.postMessage({});
    -
    -        port.start();
    -        deferred.callback(new goog.messaging.PortChannel(port));
    -        goog.events.unlistenByKey(key);
    -      });
    -  return new goog.messaging.DeferredChannel(deferred);
    -};
    -
    -
    -/**
    - * The flag added to messages that are sent by a PortChannel, and are meant to
    - * be handled by one on the other side.
    - * @type {string}
    - */
    -goog.messaging.PortChannel.FLAG = '--goog.messaging.PortChannel';
    -
    -
    -/**
    - * Whether the messages sent across the channel must be JSON-serialized. This is
    - * required for older versions of Webkit, which can only send string messages.
    - *
    - * Although Safari and Chrome have separate implementations of message passing,
    - * both of them support passing objects by Webkit 533.
    - *
    - * @type {boolean}
    - * @private
    - */
    -goog.messaging.PortChannel.REQUIRES_SERIALIZATION_ = goog.userAgent.WEBKIT &&
    -    goog.string.compareVersions(goog.userAgent.VERSION, '533') < 0;
    -
    -
    -/**
    - * Logger for this class.
    - * @type {goog.log.Logger}
    - * @protected
    - * @override
    - */
    -goog.messaging.PortChannel.prototype.logger =
    -    goog.log.getLogger('goog.messaging.PortChannel');
    -
    -
    -/**
    - * Sends a message over the channel.
    - *
    - * As an addition to the basic MessageChannel send API, PortChannels can send
    - * objects that contain MessagePorts. Note that only plain Objects and Arrays,
    - * not their subclasses, can contain MessagePorts.
    - *
    - * As per {@link http://www.w3.org/TR/html5/comms.html#clone-a-port}, once a
    - * port is copied to be sent across a channel, the original port will cease
    - * being able to send or receive messages.
    - *
    - * @override
    - * @param {string} serviceName The name of the service this message should be
    - *     delivered to.
    - * @param {string|!Object|!MessagePort} payload The value of the message. May
    - *     contain MessagePorts or be a MessagePort.
    - */
    -goog.messaging.PortChannel.prototype.send = function(serviceName, payload) {
    -  var ports = [];
    -  payload = this.extractPorts_(ports, payload);
    -  var message = {'serviceName': serviceName, 'payload': payload};
    -  message[goog.messaging.PortChannel.FLAG] = true;
    -
    -  if (goog.messaging.PortChannel.REQUIRES_SERIALIZATION_) {
    -    message = goog.json.serialize(message);
    -  }
    -
    -  this.port_.postMessage(message, ports);
    -};
    -
    -
    -/**
    - * Delivers a message to the appropriate service handler. If this message isn't
    - * a GearsWorkerChannel message, it's ignored and passed on to other handlers.
    - *
    - * @param {goog.events.Event} e The event.
    - * @private
    - */
    -goog.messaging.PortChannel.prototype.deliver_ = function(e) {
    -  var browserEvent = e.getBrowserEvent();
    -  var data = browserEvent.data;
    -
    -  if (goog.messaging.PortChannel.REQUIRES_SERIALIZATION_) {
    -    try {
    -      data = goog.json.parse(data);
    -    } catch (error) {
    -      // Ignore any non-JSON messages.
    -      return;
    -    }
    -  }
    -
    -  if (!goog.isObject(data) || !data[goog.messaging.PortChannel.FLAG]) {
    -    return;
    -  }
    -
    -  if (this.validateMessage_(data)) {
    -    var serviceName = data['serviceName'];
    -    var payload = data['payload'];
    -    var service = this.getService(serviceName, payload);
    -    if (!service) {
    -      return;
    -    }
    -
    -    payload = this.decodePayload(
    -        serviceName,
    -        this.injectPorts_(browserEvent.ports || [], payload),
    -        service.objectPayload);
    -    if (goog.isDefAndNotNull(payload)) {
    -      service.callback(payload);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Checks whether the message is invalid in some way.
    - *
    - * @param {Object} data The contents of the message.
    - * @return {boolean} True if the message is valid, false otherwise.
    - * @private
    - */
    -goog.messaging.PortChannel.prototype.validateMessage_ = function(data) {
    -  if (!('serviceName' in data)) {
    -    goog.log.warning(this.logger,
    -        'Message object doesn\'t contain service name: ' +
    -        goog.debug.deepExpose(data));
    -    return false;
    -  }
    -
    -  if (!('payload' in data)) {
    -    goog.log.warning(this.logger,
    -        'Message object doesn\'t contain payload: ' +
    -        goog.debug.deepExpose(data));
    -    return false;
    -  }
    -
    -  return true;
    -};
    -
    -
    -/**
    - * Extracts all MessagePort objects from a message to be sent into an array.
    - *
    - * The message ports are replaced by placeholder objects that will be replaced
    - * with the ports again on the other side of the channel.
    - *
    - * @param {Array<MessagePort>} ports The array that will contain ports
    - *     extracted from the message. Will be destructively modified. Should be
    - *     empty initially.
    - * @param {string|!Object} message The message from which ports will be
    - *     extracted.
    - * @return {string|!Object} The message with ports extracted.
    - * @private
    - */
    -goog.messaging.PortChannel.prototype.extractPorts_ = function(ports, message) {
    -  // Can't use instanceof here because MessagePort is undefined in workers
    -  if (message &&
    -      Object.prototype.toString.call(/** @type {!Object} */ (message)) ==
    -      '[object MessagePort]') {
    -    ports.push(message);
    -    return {'_port': {'type': 'real', 'index': ports.length - 1}};
    -  } else if (goog.isArray(message)) {
    -    return goog.array.map(message, goog.bind(this.extractPorts_, this, ports));
    -  // We want to compare the exact constructor here because we only want to
    -  // recurse into object literals, not native objects like Date.
    -  } else if (message && message.constructor == Object) {
    -    return goog.object.map(/** @type {!Object} */(message), function(val, key) {
    -      val = this.extractPorts_(ports, val);
    -      return key == '_port' ? {'type': 'escaped', 'val': val} : val;
    -    }, this);
    -  } else {
    -    return message;
    -  }
    -};
    -
    -
    -/**
    - * Injects MessagePorts back into a message received from across the channel.
    - *
    - * @param {Array<MessagePort>} ports The array of ports to be injected into the
    - *     message.
    - * @param {string|!Object} message The message into which the ports will be
    - *     injected.
    - * @return {string|!Object} The message with ports injected.
    - * @private
    - */
    -goog.messaging.PortChannel.prototype.injectPorts_ = function(ports, message) {
    -  if (goog.isArray(message)) {
    -    return goog.array.map(message, goog.bind(this.injectPorts_, this, ports));
    -  } else if (message && message.constructor == Object) {
    -    message = /** @type {!Object} */ (message);
    -    if (message['_port'] && message['_port']['type'] == 'real') {
    -      return /** @type {!MessagePort} */ (ports[message['_port']['index']]);
    -    }
    -    return goog.object.map(message, function(val, key) {
    -      return this.injectPorts_(ports, key == '_port' ? val['val'] : val);
    -    }, this);
    -  } else {
    -    return message;
    -  }
    -};
    -
    -
    -/** @override */
    -goog.messaging.PortChannel.prototype.disposeInternal = function() {
    -  goog.events.unlistenByKey(this.listenerKey_);
    -  // Can't use instanceof here because MessagePort is undefined in workers and
    -  // in Firefox
    -  if (Object.prototype.toString.call(this.port_) == '[object MessagePort]') {
    -    this.port_.close();
    -  // Worker is undefined in workers as well as of Chrome 9
    -  } else if (Object.prototype.toString.call(this.port_) == '[object Worker]') {
    -    this.port_.terminate();
    -  }
    -  delete this.port_;
    -  goog.messaging.PortChannel.base(this, 'disposeInternal');
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/portchannel_test.html b/src/database/third_party/closure-library/closure/goog/messaging/portchannel_test.html
    deleted file mode 100644
    index d0f6f5f3746..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/portchannel_test.html
    +++ /dev/null
    @@ -1,392 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    -<head>
    -<title>
    -  Closure Unit Tests - goog.messaging.PortChannel
    -</title>
    -<script src="../base.js"></script>
    -<script>
    -goog.require('goog.Timer');
    -goog.require('goog.dom');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.json');
    -goog.require('goog.messaging.PortChannel');
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.async.MockControl');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.messaging.MockMessageEvent');
    -goog.require('goog.userAgent.product');
    -</script>
    -</head>
    -<body>
    -<div id="frame"></div>
    -<script>
    -
    -var mockControl;
    -var asyncMockControl;
    -var mockPort;
    -var portChannel;
    -
    -var workerChannel;
    -var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall();
    -var timer;
    -
    -// Use a relatively long timeout because workers can take a while to start up.
    -asyncTestCase.stepTimeout = 3 * 1000;
    -
    -function setUpPage() {
    -  if (!('Worker' in goog.global)) {
    -    return;
    -  }
    -  workerChannel = new goog.messaging.PortChannel(
    -      new Worker('testdata/portchannel_worker.js'));
    -}
    -
    -function tearDownPage() {
    -  goog.dispose(workerChannel);
    -}
    -
    -function setUp() {
    -  timer = new goog.Timer(50);
    -  mockControl = new goog.testing.MockControl();
    -  asyncMockControl = new goog.testing.async.MockControl(mockControl);
    -  mockPort = new goog.events.EventTarget();
    -  mockPort.postMessage = mockControl.createFunctionMock('postMessage');
    -  portChannel = new goog.messaging.PortChannel(mockPort);
    -}
    -
    -function tearDown() {
    -  goog.dispose(timer);
    -  portChannel.dispose();
    -  mockControl.$verifyAll();
    -}
    -
    -function makeMessage(serviceName, payload) {
    -  var msg = {'serviceName': serviceName, 'payload': payload};
    -  msg[goog.messaging.PortChannel.FLAG] = true;
    -  if (goog.messaging.PortChannel.REQUIRES_SERIALIZATION_) {
    -    msg = goog.json.serialize(msg);
    -  }
    -  return msg;
    -}
    -
    -function expectNoMessage() {
    -  portChannel.registerDefaultService(
    -    mockControl.createFunctionMock('expectNoMessage'));
    -}
    -
    -function receiveMessage(serviceName, payload, opt_origin, opt_ports) {
    -  mockPort.dispatchEvent(
    -      goog.testing.messaging.MockMessageEvent.wrap(
    -          makeMessage(serviceName, payload),
    -          opt_origin || 'http://google.com',
    -          undefined, undefined, opt_ports));
    -}
    -
    -function receiveNonChannelMessage(data) {
    -  if (goog.messaging.PortChannel.REQUIRES_SERIALIZATION_ &&
    -      !goog.isString(data)) {
    -    data = goog.json.serialize(data);
    -  }
    -  mockPort.dispatchEvent(
    -      goog.testing.messaging.MockMessageEvent.wrap(
    -          data, 'http://google.com'));
    -}
    -
    -function testPostMessage() {
    -  mockPort.postMessage(makeMessage('foobar', 'This is a value'), []);
    -  mockControl.$replayAll();
    -  portChannel.send('foobar', 'This is a value');
    -}
    -
    -function testPostMessageWithPorts() {
    -  if (!('MessageChannel' in goog.global)) {
    -    return;
    -  }
    -  var channel = new MessageChannel();
    -  var port1 = channel.port1;
    -  var port2 = channel.port2;
    -  mockPort.postMessage(makeMessage('foobar', {'val': [
    -    {'_port': {'type': 'real', 'index': 0}},
    -    {'_port': {'type': 'real', 'index': 1}}
    -  ]}), [port1, port2]);
    -  mockControl.$replayAll();
    -  portChannel.send('foobar', {'val': [port1, port2]});
    -}
    -
    -function testReceiveMessage() {
    -  portChannel.registerService(
    -      'foobar', asyncMockControl.asyncAssertEquals(
    -          'testReceiveMessage', 'This is a string'));
    -  mockControl.$replayAll();
    -  receiveMessage('foobar', 'This is a string');
    -}
    -
    -function testReceiveMessageWithPorts() {
    -  if (!('MessageChannel' in goog.global)) {
    -    return;
    -  }
    -  var channel = new MessageChannel();
    -  var port1 = channel.port1;
    -  var port2 = channel.port2;
    -  portChannel.registerService(
    -      'foobar', asyncMockControl.asyncAssertEquals(
    -          'testReceiveMessage', {'val': [port1, port2]}),
    -      true);
    -  mockControl.$replayAll();
    -  receiveMessage('foobar', {'val': [
    -    {'_port': {'type': 'real', 'index': 0}},
    -    {'_port': {'type': 'real', 'index': 1}}
    -  ]}, null, [port1, port2]);
    -}
    -
    -function testReceiveNonChannelMessageWithStringBody() {
    -  expectNoMessage();
    -  mockControl.$replayAll();
    -  receiveNonChannelMessage('Foo bar');
    -}
    -
    -function testReceiveNonChannelMessageWithArrayBody() {
    -  expectNoMessage();
    -  mockControl.$replayAll();
    -  receiveNonChannelMessage([5, 'Foo bar']);
    -}
    -
    -function testReceiveNonChannelMessageWithNoFlag() {
    -  expectNoMessage();
    -  mockControl.$replayAll();
    -  receiveNonChannelMessage({
    -    serviceName: 'foobar',
    -    payload: 'this is a payload'
    -  });
    -}
    -
    -function testReceiveNonChannelMessageWithFalseFlag() {
    -  expectNoMessage();
    -  mockControl.$replayAll();
    -  var body = {
    -    serviceName: 'foobar',
    -    payload: 'this is a payload'
    -  };
    -  body[goog.messaging.PortChannel.FLAG] = false;
    -  receiveNonChannelMessage(body);
    -}
    -
    -// Integration tests
    -
    -function testWorker() {
    -  if (!('Worker' in goog.global)) {
    -    return;
    -  }
    -  workerChannel.registerService('pong', function(msg) {
    -    assertObjectEquals({'val': 'fizzbang'}, msg);
    -    asyncTestCase.continueTesting();
    -  }, true);
    -  workerChannel.send('ping', {'val': 'fizzbang'});
    -  asyncTestCase.waitForAsync('worker response');
    -}
    -
    -function testWorkerWithPorts() {
    -  if (!('Worker' in goog.global) || !('MessageChannel' in goog.global)) {
    -    return;
    -  }
    -  var messageChannel = new MessageChannel();
    -  workerChannel.registerService('pong', function(msg) {
    -    assertPortsEntangled(msg['port'], messageChannel.port2, function() {
    -      asyncTestCase.continueTesting();
    -    });
    -  }, true);
    -  workerChannel.send('ping', {'port': messageChannel.port1});
    -  asyncTestCase.waitForAsync('worker response');
    -}
    -
    -function testPort() {
    -  if (!('Worker' in goog.global) || !('MessageChannel' in goog.global)) {
    -    return;
    -  }
    -  var messageChannel = new MessageChannel();
    -  workerChannel.send('addPort', messageChannel.port1);
    -  messageChannel.port2.start();
    -  var realPortChannel = new goog.messaging.PortChannel(messageChannel.port2);
    -  realPortChannel.registerService('pong', function(msg) {
    -    assertObjectEquals({'val': 'fizzbang'}, msg);
    -
    -    messageChannel.port2.close();
    -    realPortChannel.dispose();
    -    asyncTestCase.continueTesting();
    -  }, true);
    -  realPortChannel.send('ping', {'val': 'fizzbang'});
    -  asyncTestCase.waitForAsync('port response');
    -}
    -
    -function testPortIgnoresOrigin() {
    -  if (!('Worker' in goog.global) || !('MessageChannel' in goog.global)) {
    -    return;
    -  }
    -  var messageChannel = new MessageChannel();
    -  workerChannel.send('addPort', messageChannel.port1);
    -  messageChannel.port2.start();
    -  var realPortChannel = new goog.messaging.PortChannel(
    -      messageChannel.port2, 'http://somewhere-else.com');
    -  realPortChannel.registerService('pong', function(msg) {
    -    assertObjectEquals({'val': 'fizzbang'}, msg);
    -
    -    messageChannel.port2.close();
    -    realPortChannel.dispose();
    -    asyncTestCase.continueTesting();
    -  }, true);
    -  realPortChannel.send('ping', {'val': 'fizzbang'});
    -  asyncTestCase.waitForAsync('port response');
    -}
    -
    -function testWindow() {
    -  if (!('Worker' in goog.global) || !('MessageChannel' in goog.global)) {
    -    return;
    -  }
    -
    -  // NOTE(nicksantos): This test is having problems in Safari4 on the
    -  // test farm, but no one can reproduce them locally. Just turn it off.
    -  if (goog.userAgent.product.SAFARI) {
    -    return;
    -  }
    -
    -  withIframe(function() {
    -    var iframeChannel = goog.messaging.PortChannel.forEmbeddedWindow(
    -        window.frames['inner'], '*', timer);
    -    iframeChannel.registerService('pong', function(msg) {
    -      assertEquals('fizzbang', msg);
    -
    -      goog.dispose(iframeChannel);
    -      asyncTestCase.continueTesting();
    -    });
    -    iframeChannel.send('ping', 'fizzbang');
    -    asyncTestCase.waitForAsync('window response');
    -  });
    -}
    -
    -function testWindowCancelled() {
    -  if (!('Worker' in goog.global) || !('MessageChannel' in goog.global)) {
    -    return;
    -  }
    -  withIframe(function() {
    -    var iframeChannel = goog.messaging.PortChannel.forEmbeddedWindow(
    -        window.frames['inner'], '*', timer);
    -    iframeChannel.cancel();
    -
    -    iframeChannel.registerService('pong', function(msg) {
    -      fail('no messages should be received due to cancellation');
    -      goog.dispose(iframeChannel);
    -      asyncTestCase.continueTesting();
    -    });
    -
    -    iframeChannel.send('ping', 'fizzbang');
    -    asyncTestCase.waitForAsync('window response');
    -
    -    // Leave plenty of time for the connection to be made if the test fails, but
    -    // stop the test before the asyncTestCase timeout is hit.
    -    setTimeout(goog.bind(asyncTestCase.continueTesting, asyncTestCase),
    -               asyncTestCase.stepTimeout / 3);
    -  });
    -}
    -
    -function testWindowWontSendToWrongOrigin() {
    -  if (!('Worker' in goog.global) || !('MessageChannel' in goog.global)) {
    -    return;
    -  }
    -  withIframe(function() {
    -    var iframeChannel = goog.messaging.PortChannel.forEmbeddedWindow(
    -        window.frames['inner'], 'http://somewhere-else.com', timer);
    -    iframeChannel.registerService('pong', function(msg) {
    -      fail('Should not receive pong from unexpected origin');
    -      iframeChannel.dispose();
    -      asyncTestCase.continueTesting();
    -    });
    -    iframeChannel.send('ping', 'fizzbang');
    -
    -    setTimeout(function() {
    -      iframeChannel.dispose();
    -      asyncTestCase.continueTesting();
    -    }, asyncTestCase.stepTimeout - 500);
    -    asyncTestCase.waitForAsync('window response');
    -  });
    -}
    -
    -function testWindowWontReceiveFromWrongOrigin() {
    -  if (!('Worker' in goog.global) || !('MessageChannel' in goog.global)) {
    -    return;
    -  }
    -  withIframe(function() {
    -    var iframeChannel = goog.messaging.PortChannel.forEmbeddedWindow(
    -        window.frames['inner'], '*', timer);
    -    iframeChannel.registerService('pong', function(msg) {
    -      fail('Should not receive pong from unexpected origin');
    -      iframeChannel.dispose();
    -      asyncTestCase.continueTesting();
    -    });
    -    iframeChannel.send('ping', 'fizzbang');
    -
    -    setTimeout(function() {
    -      iframeChannel.dispose();
    -      asyncTestCase.continueTesting();
    -    }, asyncTestCase.stepTimeout - 500);
    -    asyncTestCase.waitForAsync('window response');
    -  }, 'testdata/portchannel_wrong_origin_inner.html');
    -}
    -
    -/**
    - * Assert that two HTML5 MessagePorts are entangled by posting messages from
    - * each to the other.
    - *
    - * @param {!MessagePort} port1
    - * @param {!MessagePort} port2
    - * @param {function()} callback Called when the assertion is finished.
    - */
    -function assertPortsEntangled(port1, port2, callback) {
    -  port1.onmessage = function(e) {
    -    assertEquals('port 2 should send messages to port 1',
    -                 'port2 to port1', e.data);
    -    callback();
    -  };
    -
    -  port2.onmessage = function(e) {
    -    assertEquals('port 1 should send messages to port 2',
    -                 'port1 to port2', e.data);
    -    port2.postMessage('port2 to port1');
    -    asyncTestCase.waitForAsync('port 1 receiving message');
    -  };
    -
    -  port1.postMessage('port1 to port2');
    -  asyncTestCase.waitForAsync('port 2 receiving message');
    -}
    -
    -function withIframe(callback, opt_url) {
    -  var frameDiv = goog.dom.getElement('frame');
    -  goog.dom.removeChildren(frameDiv);
    -  goog.dom.appendChild(frameDiv, goog.dom.createDom('iframe', {
    -    style: 'display: none',
    -    name: 'inner',
    -    id: 'inner',
    -    src: opt_url || 'testdata/portchannel_inner.html'
    -  }));
    -
    -  asyncTestCase.waitForAsync('creating iframe');
    -  // We need to pass control back to the event loop to give the iframe a chance
    -  // to load.
    -  setTimeout(function() {
    -    asyncTestCase.continueTesting();
    -    callback();
    -  }, 0);
    -}
    -
    -</script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/portnetwork.js b/src/database/third_party/closure-library/closure/goog/messaging/portnetwork.js
    deleted file mode 100644
    index 758d699298e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/portnetwork.js
    +++ /dev/null
    @@ -1,78 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview An interface for classes that connect a collection of HTML5
    - * message-passing entities ({@link MessagePort}s, {@link Worker}s, and
    - * {@link Window}s) and allow them to seamlessly communicate with one another.
    - *
    - * Conceptually, a PortNetwork is a collection of JS contexts, such as pages (in
    - * or outside of iframes) or web workers. Each context has a unique name, and
    - * each one can communicate with any of the others in the same network. This
    - * communication takes place through a {@link goog.messaging.PortChannel} that
    - * is retrieved via {#link goog.messaging.PortNetwork#dial}.
    - *
    - * One context (usually the main page) has a
    - * {@link goog.messaging.PortOperator}, which is in charge of connecting each
    - * context to each other context. All other contexts have
    - * {@link goog.messaging.PortCaller}s which connect to the operator.
    - *
    - */
    -
    -goog.provide('goog.messaging.PortNetwork');
    -
    -
    -
    -/**
    - * @interface
    - */
    -goog.messaging.PortNetwork = function() {};
    -
    -
    -/**
    - * Returns a message channel that communicates with the named context. If no
    - * such port exists, an error will either be thrown immediately or after a round
    - * trip with the operator, depending on whether this pool is the operator or a
    - * caller.
    - *
    - * If context A calls dial('B') and context B calls dial('A'), the two
    - * ports returned will be connected to one another.
    - *
    - * @param {string} name The name of the context to get.
    - * @return {goog.messaging.MessageChannel} The channel communicating with the
    - *     given context. This is either a {@link goog.messaging.PortChannel} or a
    - *     decorator around a PortChannel, so it's safe to send {@link MessagePorts}
    - *     across it. This will be disposed along with the PortNetwork.
    - */
    -goog.messaging.PortNetwork.prototype.dial = function(name) {};
    -
    -
    -/**
    - * The name of the service exported by the operator for creating a connection
    - * between two callers.
    - *
    - * @type {string}
    - * @const
    - */
    -goog.messaging.PortNetwork.REQUEST_CONNECTION_SERVICE = 'requestConnection';
    -
    -
    -/**
    - * The name of the service exported by the callers for adding a connection to
    - * another context.
    - *
    - * @type {string}
    - * @const
    - */
    -goog.messaging.PortNetwork.GRANT_CONNECTION_SERVICE = 'grantConnection';
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/portnetwork_test.html b/src/database/third_party/closure-library/closure/goog/messaging/portnetwork_test.html
    deleted file mode 100644
    index 59452590057..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/portnetwork_test.html
    +++ /dev/null
    @@ -1,74 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    -<head>
    -<title>
    -  Closure Unit Tests - goog.messaging.PortNetwork
    -</title>
    -<script src="../base.js"></script>
    -<script>
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.messaging.PortChannel');
    -goog.require('goog.messaging.PortOperator');
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.async.MockControl');
    -goog.require('goog.testing.messaging.MockMessageEvent');
    -goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -<iframe style="display: none;" name="inner" id="inner"
    -        src="testdata/portnetwork_inner.html"></iframe>
    -<script>
    -
    -var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall();
    -
    -// Use a relatively long timeout because workers can take a while to start up.
    -asyncTestCase.stepTimeout = 5 * 1000;
    -
    -var timer;
    -
    -function setUp() {
    -  timer = new goog.Timer(50);
    -}
    -
    -function tearDown() {
    -  goog.dispose(timer);
    -}
    -
    -function testRouteMessageThroughWorkers() {
    -  if (!('MessageChannel' in goog.global)) {
    -    return;
    -  }
    -
    -  var master = new goog.messaging.PortOperator('main');
    -  master.addPort('worker1', new goog.messaging.PortChannel(
    -      new Worker('testdata/portnetwork_worker1.js')));
    -  master.addPort('worker2', new goog.messaging.PortChannel(
    -      new Worker('testdata/portnetwork_worker2.js')));
    -  master.addPort(
    -      'frame', goog.messaging.PortChannel.forEmbeddedWindow(
    -          window.frames['inner'], '*', timer));
    -
    -  master.dial('worker1').registerService('result', function(msg) {
    -    assertArrayEquals(['main', 'worker2', 'frame', 'worker1'], msg);
    -    master.dispose();
    -    asyncTestCase.continueTesting();
    -  }, true);
    -
    -  master.dial('worker2').send('sendToFrame', ['main']);
    -
    -  asyncTestCase.waitForAsync('routing messages');
    -}
    -
    -</script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/portoperator.js b/src/database/third_party/closure-library/closure/goog/messaging/portoperator.js
    deleted file mode 100644
    index 90e02aeba91..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/portoperator.js
    +++ /dev/null
    @@ -1,198 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview The central node of a {@link goog.messaging.PortNetwork}. The
    - * operator is responsible for providing the two-way communication channels (via
    - * {@link MessageChannel}s) between each pair of nodes in the network that need
    - * to communicate with one another. Each network should have one and only one
    - * operator.
    - *
    - */
    -
    -goog.provide('goog.messaging.PortOperator');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.asserts');
    -goog.require('goog.log');
    -goog.require('goog.messaging.PortChannel');
    -goog.require('goog.messaging.PortNetwork'); // interface
    -goog.require('goog.object');
    -
    -
    -
    -/**
    - * The central node of a PortNetwork.
    - *
    - * @param {string} name The name of this node.
    - * @constructor
    - * @extends {goog.Disposable}
    - * @implements {goog.messaging.PortNetwork}
    - * @final
    - */
    -goog.messaging.PortOperator = function(name) {
    -  goog.messaging.PortOperator.base(this, 'constructor');
    -
    -  /**
    -   * The collection of channels for communicating with other contexts in the
    -   * network. These are the channels that are returned to the user, as opposed
    -   * to the channels used for internal network communication. This is lazily
    -   * populated as the user requests communication with other contexts, or other
    -   * contexts request communication with the operator.
    -   *
    -   * @type {!Object<!goog.messaging.PortChannel>}
    -   * @private
    -   */
    -  this.connections_ = {};
    -
    -  /**
    -   * The collection of channels for internal network communication with other
    -   * contexts. This is not lazily populated, and always contains entries for
    -   * each member of the network.
    -   *
    -   * @type {!Object<!goog.messaging.MessageChannel>}
    -   * @private
    -   */
    -  this.switchboard_ = {};
    -
    -  /**
    -   * The name of the operator context.
    -   *
    -   * @type {string}
    -   * @private
    -   */
    -  this.name_ = name;
    -};
    -goog.inherits(goog.messaging.PortOperator, goog.Disposable);
    -
    -
    -/**
    - * The logger for PortOperator.
    - * @type {goog.log.Logger}
    - * @private
    - */
    -goog.messaging.PortOperator.prototype.logger_ =
    -    goog.log.getLogger('goog.messaging.PortOperator');
    -
    -
    -/** @override */
    -goog.messaging.PortOperator.prototype.dial = function(name) {
    -  this.connectSelfToPort_(name);
    -  return this.connections_[name];
    -};
    -
    -
    -/**
    - * Adds a caller to the network with the given name. This port should have no
    - * services registered on it. It will be disposed along with the PortOperator.
    - *
    - * @param {string} name The name of the port to add.
    - * @param {!goog.messaging.MessageChannel} port The port to add. Must be either
    - *     a {@link goog.messaging.PortChannel} or a decorator wrapping a
    - *     PortChannel; in particular, it must be able to send and receive
    - *     {@link MessagePort}s.
    - */
    -goog.messaging.PortOperator.prototype.addPort = function(name, port) {
    -  this.switchboard_[name] = port;
    -  port.registerService(goog.messaging.PortNetwork.REQUEST_CONNECTION_SERVICE,
    -                       goog.bind(this.requestConnection_, this, name));
    -};
    -
    -
    -/**
    - * Connects two contexts by creating a {@link MessageChannel} and sending one
    - * end to one context and the other end to the other. Called when we receive a
    - * request from a caller to connect it to another context (including potentially
    - * the operator).
    - *
    - * @param {string} sourceName The name of the context requesting the connection.
    - * @param {!Object|string} message The name of the context to which
    - *     the connection is requested.
    - * @private
    - */
    -goog.messaging.PortOperator.prototype.requestConnection_ = function(
    -    sourceName, message) {
    -  var requestedName = /** @type {string} */ (message);
    -  if (requestedName == this.name_) {
    -    this.connectSelfToPort_(sourceName);
    -    return;
    -  }
    -
    -  var sourceChannel = this.switchboard_[sourceName];
    -  var requestedChannel = this.switchboard_[requestedName];
    -
    -  goog.asserts.assert(goog.isDefAndNotNull(sourceChannel));
    -  if (!requestedChannel) {
    -    var err = 'Port "' + sourceName + '" requested a connection to port "' +
    -        requestedName + '", which doesn\'t exist';
    -    goog.log.warning(this.logger_, err);
    -    sourceChannel.send(goog.messaging.PortNetwork.GRANT_CONNECTION_SERVICE,
    -                       {'success': false, 'message': err});
    -    return;
    -  }
    -
    -  var messageChannel = new MessageChannel();
    -  sourceChannel.send(goog.messaging.PortNetwork.GRANT_CONNECTION_SERVICE, {
    -    'success': true,
    -    'name': requestedName,
    -    'port': messageChannel.port1
    -  });
    -  requestedChannel.send(goog.messaging.PortNetwork.GRANT_CONNECTION_SERVICE, {
    -    'success': true,
    -    'name': sourceName,
    -    'port': messageChannel.port2
    -  });
    -};
    -
    -
    -/**
    - * Connects together the operator and a caller by creating a
    - * {@link MessageChannel} and sending one end to the remote context.
    - *
    - * @param {string} contextName The name of the context to which to connect the
    - *     operator.
    - * @private
    - */
    -goog.messaging.PortOperator.prototype.connectSelfToPort_ = function(
    -    contextName) {
    -  if (contextName in this.connections_) {
    -    // We've already established a connection with this port.
    -    return;
    -  }
    -
    -  var contextChannel = this.switchboard_[contextName];
    -  if (!contextChannel) {
    -    throw Error('Port "' + contextName + '" doesn\'t exist');
    -  }
    -
    -  var messageChannel = new MessageChannel();
    -  contextChannel.send(goog.messaging.PortNetwork.GRANT_CONNECTION_SERVICE, {
    -    'success': true,
    -    'name': this.name_,
    -    'port': messageChannel.port1
    -  });
    -  messageChannel.port2.start();
    -  this.connections_[contextName] =
    -      new goog.messaging.PortChannel(messageChannel.port2);
    -};
    -
    -
    -/** @override */
    -goog.messaging.PortOperator.prototype.disposeInternal = function() {
    -  goog.object.forEach(this.switchboard_, goog.dispose);
    -  goog.object.forEach(this.connections_, goog.dispose);
    -  delete this.switchboard_;
    -  delete this.connections_;
    -  goog.messaging.PortOperator.base(this, 'disposeInternal');
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/portoperator_test.html b/src/database/third_party/closure-library/closure/goog/messaging/portoperator_test.html
    deleted file mode 100644
    index 9b0b6ae03f1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/portoperator_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.messaging.PortOperator
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.messaging.PortOperatorTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/portoperator_test.js b/src/database/third_party/closure-library/closure/goog/messaging/portoperator_test.js
    deleted file mode 100644
    index 05656fe7c97..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/portoperator_test.js
    +++ /dev/null
    @@ -1,107 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.messaging.PortOperatorTest');
    -goog.setTestOnly('goog.messaging.PortOperatorTest');
    -
    -goog.require('goog.messaging.PortNetwork');
    -goog.require('goog.messaging.PortOperator');
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.messaging.MockMessageChannel');
    -goog.require('goog.testing.messaging.MockMessagePort');
    -
    -var stubs;
    -
    -var mockControl;
    -var mockChannel1;
    -var mockChannel2;
    -var operator;
    -
    -function setUpPage() {
    -  stubs = new goog.testing.PropertyReplacer();
    -}
    -
    -function setUp() {
    -  mockControl = new goog.testing.MockControl();
    -  var index = 0;
    -  stubs.set(goog.global, 'MessageChannel', function() {
    -    this.port1 = makeMockPort(index, 1);
    -    this.port2 = makeMockPort(index, 2);
    -    index += 1;
    -  });
    -
    -  mockChannel1 = new goog.testing.messaging.MockMessageChannel(mockControl);
    -  mockChannel2 = new goog.testing.messaging.MockMessageChannel(mockControl);
    -  operator = new goog.messaging.PortOperator('operator');
    -  operator.addPort('1', mockChannel1);
    -  operator.addPort('2', mockChannel2);
    -}
    -
    -function tearDown() {
    -  goog.dispose(operator);
    -  mockControl.$verifyAll();
    -  stubs.reset();
    -}
    -
    -function makeMockPort(index, port) {
    -  return new goog.testing.messaging.MockMessagePort(
    -      {index: index, port: port}, mockControl);
    -}
    -
    -function testConnectSelfToPortViaRequestConnection() {
    -  mockChannel1.send(goog.messaging.PortNetwork.GRANT_CONNECTION_SERVICE, {
    -    success: true, name: 'operator', port: makeMockPort(0, 1)
    -  });
    -  mockControl.$replayAll();
    -  mockChannel1.receive(
    -      goog.messaging.PortNetwork.REQUEST_CONNECTION_SERVICE, 'operator');
    -  var port = operator.dial('1').port_;
    -  assertObjectEquals({index: 0, port: 2}, port.id);
    -  assertEquals(true, port.started);
    -}
    -
    -function testConnectSelfToPortViaGetPort() {
    -  mockChannel1.send(goog.messaging.PortNetwork.GRANT_CONNECTION_SERVICE, {
    -    success: true, name: 'operator', port: makeMockPort(0, 1)
    -  });
    -  mockControl.$replayAll();
    -  var port = operator.dial('1').port_;
    -  assertObjectEquals({index: 0, port: 2}, port.id);
    -  assertEquals(true, port.started);
    -}
    -
    -function testConnectTwoCallers() {
    -  mockChannel1.send(goog.messaging.PortNetwork.GRANT_CONNECTION_SERVICE, {
    -    success: true, name: '2', port: makeMockPort(0, 1)
    -  });
    -  mockChannel2.send(goog.messaging.PortNetwork.GRANT_CONNECTION_SERVICE, {
    -    success: true, name: '1', port: makeMockPort(0, 2)
    -  });
    -  mockControl.$replayAll();
    -  mockChannel1.receive(
    -      goog.messaging.PortNetwork.REQUEST_CONNECTION_SERVICE, '2');
    -}
    -
    -function testConnectCallerToNonexistentCaller() {
    -  mockChannel1.send(goog.messaging.PortNetwork.GRANT_CONNECTION_SERVICE, {
    -    success: false,
    -    message: 'Port "1" requested a connection to port "no", which doesn\'t ' +
    -        'exist'
    -  });
    -  mockControl.$replayAll();
    -  mockChannel1.receive(
    -      goog.messaging.PortNetwork.REQUEST_CONNECTION_SERVICE, 'no');
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/respondingchannel.js b/src/database/third_party/closure-library/closure/goog/messaging/respondingchannel.js
    deleted file mode 100644
    index 678205ab717..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/respondingchannel.js
    +++ /dev/null
    @@ -1,234 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Definition of goog.messaging.RespondingChannel, which wraps a
    - * MessageChannel and allows the user to get the response from the services.
    - *
    - */
    -
    -
    -goog.provide('goog.messaging.RespondingChannel');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.log');
    -goog.require('goog.messaging.MultiChannel');
    -
    -
    -
    -/**
    - * Creates a new RespondingChannel wrapping a single MessageChannel.
    - * @param {goog.messaging.MessageChannel} messageChannel The messageChannel to
    - *     to wrap and allow for responses. This channel must not have any existing
    - *     services registered. All service registration must be done through the
    - *     {@link RespondingChannel#registerService} api instead. The other end of
    - *     channel must also be a RespondingChannel.
    - * @constructor
    - * @extends {goog.Disposable}
    - */
    -goog.messaging.RespondingChannel = function(messageChannel) {
    -  goog.messaging.RespondingChannel.base(this, 'constructor');
    -
    -  /**
    -   * The message channel wrapped in a MultiChannel so we can send private and
    -   * public messages on it.
    -   * @type {goog.messaging.MultiChannel}
    -   * @private
    -   */
    -  this.messageChannel_ = new goog.messaging.MultiChannel(messageChannel);
    -
    -  /**
    -   * Map of invocation signatures to function callbacks. These are used to keep
    -   * track of the asyncronous service invocations so the result of a service
    -   * call can be passed back to a callback in the calling frame.
    -   * @type {Object<number, function(Object)>}
    -   * @private
    -   */
    -  this.sigCallbackMap_ = {};
    -
    -  /**
    -   * The virtual channel to send private messages on.
    -   * @type {goog.messaging.MultiChannel.VirtualChannel}
    -   * @private
    -   */
    -  this.privateChannel_ = this.messageChannel_.createVirtualChannel(
    -      goog.messaging.RespondingChannel.PRIVATE_CHANNEL_);
    -
    -  /**
    -   * The virtual channel to send public messages on.
    -   * @type {goog.messaging.MultiChannel.VirtualChannel}
    -   * @private
    -   */
    -  this.publicChannel_ = this.messageChannel_.createVirtualChannel(
    -      goog.messaging.RespondingChannel.PUBLIC_CHANNEL_);
    -
    -  this.privateChannel_.registerService(
    -      goog.messaging.RespondingChannel.CALLBACK_SERVICE_,
    -      goog.bind(this.callbackServiceHandler_, this),
    -      true);
    -};
    -goog.inherits(goog.messaging.RespondingChannel, goog.Disposable);
    -
    -
    -/**
    - * The name of the method invocation callback service (used internally).
    - * @type {string}
    - * @const
    - * @private
    - */
    -goog.messaging.RespondingChannel.CALLBACK_SERVICE_ = 'mics';
    -
    -
    -/**
    - * The name of the channel to send private control messages on.
    - * @type {string}
    - * @const
    - * @private
    - */
    -goog.messaging.RespondingChannel.PRIVATE_CHANNEL_ = 'private';
    -
    -
    -/**
    - * The name of the channel to send public messages on.
    - * @type {string}
    - * @const
    - * @private
    - */
    -goog.messaging.RespondingChannel.PUBLIC_CHANNEL_ = 'public';
    -
    -
    -/**
    - * The next signature index to save the callback against.
    - * @type {number}
    - * @private
    - */
    -goog.messaging.RespondingChannel.prototype.nextSignatureIndex_ = 0;
    -
    -
    -/**
    - * Logger object for goog.messaging.RespondingChannel.
    - * @type {goog.log.Logger}
    - * @private
    - */
    -goog.messaging.RespondingChannel.prototype.logger_ =
    -    goog.log.getLogger('goog.messaging.RespondingChannel');
    -
    -
    -/**
    - * Gets a random number to use for method invocation results.
    - * @return {number} A unique random signature.
    - * @private
    - */
    -goog.messaging.RespondingChannel.prototype.getNextSignature_ = function() {
    -  return this.nextSignatureIndex_++;
    -};
    -
    -
    -/** @override */
    -goog.messaging.RespondingChannel.prototype.disposeInternal = function() {
    -  goog.dispose(this.messageChannel_);
    -  delete this.messageChannel_;
    -  // Note: this.publicChannel_ and this.privateChannel_ get disposed by
    -  //     this.messageChannel_
    -  delete this.publicChannel_;
    -  delete this.privateChannel_;
    -};
    -
    -
    -/**
    - * Sends a message over the channel.
    - * @param {string} serviceName The name of the service this message should be
    - *     delivered to.
    - * @param {string|!Object} payload The value of the message. If this is an
    - *     Object, it is serialized to a string before sending if necessary.
    - * @param {function(?Object)} callback The callback invoked with
    - *     the result of the service call.
    - */
    -goog.messaging.RespondingChannel.prototype.send = function(
    -    serviceName,
    -    payload,
    -    callback) {
    -
    -  var signature = this.getNextSignature_();
    -  this.sigCallbackMap_[signature] = callback;
    -
    -  var message = {};
    -  message['signature'] = signature;
    -  message['data'] = payload;
    -
    -  this.publicChannel_.send(serviceName, message);
    -};
    -
    -
    -/**
    - * Receives the results of the peer's service results.
    - * @param {!Object|string} message The results from the remote service
    - *     invocation.
    - * @private
    - */
    -goog.messaging.RespondingChannel.prototype.callbackServiceHandler_ = function(
    -    message) {
    -
    -  var signature = message['signature'];
    -  var result = message['data'];
    -
    -  if (signature in this.sigCallbackMap_) {
    -    var callback = /** @type {function(Object)} */ (this.sigCallbackMap_[
    -        signature]);
    -    callback(result);
    -    delete this.sigCallbackMap_[signature];
    -  } else {
    -    goog.log.warning(this.logger_, 'Received signature is invalid');
    -  }
    -};
    -
    -
    -/**
    - * Registers a service to be called when a message is received.
    - * @param {string} serviceName The name of the service.
    - * @param {function(!Object)} callback The callback to process the
    - *     incoming messages. Passed the payload.
    - */
    -goog.messaging.RespondingChannel.prototype.registerService = function(
    -    serviceName, callback) {
    -  this.publicChannel_.registerService(
    -      serviceName,
    -      goog.bind(this.callbackProxy_, this, callback),
    -      true);
    -};
    -
    -
    -/**
    - * A intermediary proxy for service callbacks to be invoked and return their
    - * their results to the remote caller's callback.
    - * @param {function((string|!Object))} callback The callback to process the
    - *     incoming messages. Passed the payload.
    - * @param {!Object|string} message The message containing the signature and
    - *     the data to invoke the service callback with.
    - * @private
    - */
    -goog.messaging.RespondingChannel.prototype.callbackProxy_ = function(
    -    callback, message) {
    -
    -  var resultMessage = {};
    -  resultMessage['data'] = callback(message['data']);
    -  resultMessage['signature'] = message['signature'];
    -  // The callback invoked above may have disposed the channel so check if it
    -  // exists.
    -  if (this.privateChannel_) {
    -    this.privateChannel_.send(
    -        goog.messaging.RespondingChannel.CALLBACK_SERVICE_,
    -        resultMessage);
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/respondingchannel_test.html b/src/database/third_party/closure-library/closure/goog/messaging/respondingchannel_test.html
    deleted file mode 100644
    index d04c081bb77..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/respondingchannel_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.messaging
    -  </title>
    -  <script type="text/javascript" src="../base.js">
    -  </script>
    -  <script type="text/javascript">
    -    goog.require('goog.messaging.RespondingChannelTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/respondingchannel_test.js b/src/database/third_party/closure-library/closure/goog/messaging/respondingchannel_test.js
    deleted file mode 100644
    index e271f3b139b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/respondingchannel_test.js
    +++ /dev/null
    @@ -1,152 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.messaging.RespondingChannelTest');
    -goog.setTestOnly('goog.messaging.RespondingChannelTest');
    -
    -goog.require('goog.messaging.RespondingChannel');
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.messaging.MockMessageChannel');
    -
    -var CH1_REQUEST = {'request': 'quux1'};
    -var CH2_REQUEST = {'request': 'quux2'};
    -var CH1_RESPONSE = {'response': 'baz1'};
    -var CH2_RESPONSE = {'response': 'baz2'};
    -var SERVICE_NAME = 'serviceName';
    -
    -var mockControl;
    -var ch1;
    -var ch2;
    -var respondingCh1;
    -var respondingCh2;
    -
    -function setUp() {
    -  mockControl = new goog.testing.MockControl();
    -
    -  ch1 = new goog.testing.messaging.MockMessageChannel(mockControl);
    -  ch2 = new goog.testing.messaging.MockMessageChannel(mockControl);
    -
    -  respondingCh1 = new goog.messaging.RespondingChannel(ch1);
    -  respondingCh2 = new goog.messaging.RespondingChannel(ch2);
    -}
    -
    -function tearDown() {
    -  respondingCh1.dispose();
    -  respondingCh2.dispose();
    -  mockControl.$verifyAll();
    -}
    -
    -function testSendWithSignature() {
    -  // 1 to 2 and back.
    -  var message1Ch1Request = {'data': CH1_REQUEST,
    -    'signature': 0};
    -  var message1Ch2Response = {'data': CH2_RESPONSE,
    -    'signature': 0};
    -  var message2Ch1Request = {'data': CH1_REQUEST,
    -    'signature': 1};
    -  var message2Ch2Response = {'data': CH2_RESPONSE,
    -    'signature': 1};
    -  // 2 to 1 and back.
    -  var message3Ch2Request = {'data': CH2_REQUEST,
    -    'signature': 0};
    -  var message3Ch1Response = {'data': CH1_RESPONSE,
    -    'signature': 0};
    -  var message4Ch2Request = {'data': CH2_REQUEST,
    -    'signature': 1};
    -  var message4Ch1Response = {'data': CH1_RESPONSE,
    -    'signature': 1};
    -
    -  // 1 to 2 and back.
    -  ch1.send(
    -      'public:' + SERVICE_NAME,
    -      message1Ch1Request);
    -  ch2.send(
    -      'private:mics',
    -      message1Ch2Response);
    -  ch1.send(
    -      'public:' + SERVICE_NAME,
    -      message2Ch1Request);
    -  ch2.send(
    -      'private:mics',
    -      message2Ch2Response);
    -
    -  // 2 to 1 and back.
    -  ch2.send(
    -      'public:' + SERVICE_NAME,
    -      message3Ch2Request);
    -  ch1.send(
    -      'private:mics',
    -      message3Ch1Response);
    -  ch2.send(
    -      'public:' + SERVICE_NAME,
    -      message4Ch2Request);
    -  ch1.send(
    -      'private:mics',
    -      message4Ch1Response);
    -
    -  mockControl.$replayAll();
    -
    -  var hasInvokedCh1 = false;
    -  var hasInvokedCh2 = false;
    -  var hasReturnedFromCh1 = false;
    -  var hasReturnedFromCh2 = false;
    -
    -  var serviceCallback1 = function(message) {
    -    hasInvokedCh1 = true;
    -    assertObjectEquals(CH2_REQUEST, message);
    -    return CH1_RESPONSE;
    -  };
    -
    -  var serviceCallback2 = function(message) {
    -    hasInvokedCh2 = true;
    -    assertObjectEquals(CH1_REQUEST, message);
    -    return CH2_RESPONSE;
    -  };
    -
    -  var invocationCallback1 = function(message) {
    -    hasReturnedFromCh2 = true;
    -    assertObjectEquals(CH2_RESPONSE, message);
    -  };
    -
    -  var invocationCallback2 = function(message) {
    -    hasReturnedFromCh1 = true;
    -    assertObjectEquals(CH1_RESPONSE, message);
    -  };
    -
    -  respondingCh1.registerService(SERVICE_NAME, serviceCallback1);
    -  respondingCh2.registerService(SERVICE_NAME, serviceCallback2);
    -
    -  respondingCh1.send(SERVICE_NAME, CH1_REQUEST, invocationCallback1);
    -  ch2.receive('public:' + SERVICE_NAME, message1Ch1Request);
    -  ch1.receive('private:mics', message1Ch2Response);
    -
    -  respondingCh1.send(SERVICE_NAME, CH1_REQUEST, invocationCallback1);
    -  ch2.receive('public:' + SERVICE_NAME, message2Ch1Request);
    -  ch1.receive('private:mics', message2Ch2Response);
    -
    -  respondingCh2.send(SERVICE_NAME, CH2_REQUEST, invocationCallback2);
    -  ch1.receive('public:' + SERVICE_NAME, message3Ch2Request);
    -  ch2.receive('private:mics', message3Ch1Response);
    -
    -  respondingCh2.send(SERVICE_NAME, CH2_REQUEST, invocationCallback2);
    -  ch1.receive('public:' + SERVICE_NAME, message4Ch2Request);
    -  ch2.receive('private:mics', message4Ch1Response);
    -
    -  assertTrue(
    -      hasInvokedCh1 &&
    -      hasInvokedCh2 &&
    -      hasReturnedFromCh1 &&
    -      hasReturnedFromCh2);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/testdata/portchannel_inner.html b/src/database/third_party/closure-library/closure/goog/messaging/testdata/portchannel_inner.html
    deleted file mode 100644
    index 6c9a09e4896..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/testdata/portchannel_inner.html
    +++ /dev/null
    @@ -1,28 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    -<head>
    -<title>PortChannel test inner document</title>
    -<script src="../../base.js"></script>
    -<script>
    -goog.require('goog.messaging.PortChannel');
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -var channel = goog.messaging.PortChannel.forGlobalWindow('*');
    -channel.registerService('ping', function(msg) {
    -  channel.send('pong', msg);
    -});
    -
    -</script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/testdata/portchannel_worker.js b/src/database/third_party/closure-library/closure/goog/messaging/testdata/portchannel_worker.js
    deleted file mode 100644
    index cba4b884bee..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/testdata/portchannel_worker.js
    +++ /dev/null
    @@ -1,37 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -// Use of this source code is governed by the Apache License, Version 2.0.
    -// See the COPYING file for details.
    -
    -/**
    - * @fileoverview A web worker for integration testing the PortChannel class.
    - *
    - * @nocompile
    - */
    -
    -self.CLOSURE_BASE_PATH = '../../';
    -importScripts('../../bootstrap/webworkers.js');
    -importScripts('../../base.js');
    -
    -// The provide is necessary to stop the jscompiler from thinking this is an
    -// entry point and adding it into the manifest incorrectly.
    -goog.provide('goog.messaging.testdata.portchannel_worker');
    -goog.require('goog.messaging.PortChannel');
    -
    -function registerPing(channel) {
    -  channel.registerService('ping', function(msg) {
    -    channel.send('pong', msg);
    -  }, true);
    -}
    -
    -function startListening() {
    -  var channel = new goog.messaging.PortChannel(self);
    -  registerPing(channel);
    -
    -  channel.registerService('addPort', function(port) {
    -    port.start();
    -    registerPing(new goog.messaging.PortChannel(port));
    -  }, true);
    -}
    -
    -startListening();
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/testdata/portchannel_wrong_origin_inner.html b/src/database/third_party/closure-library/closure/goog/messaging/testdata/portchannel_wrong_origin_inner.html
    deleted file mode 100644
    index 344d8c65fbf..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/testdata/portchannel_wrong_origin_inner.html
    +++ /dev/null
    @@ -1,29 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    -<head>
    -<title>PortChannel test inner document</title>
    -<script src="../../base.js"></script>
    -<script>
    -goog.require('goog.messaging.PortChannel');
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -var channel = goog.messaging.PortChannel.forGlobalWindow(
    -    'http://somewhere-else.com');
    -channel.registerService('ping', function(msg) {
    -  channel.send('pong', msg);
    -});
    -
    -</script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/testdata/portnetwork_inner.html b/src/database/third_party/closure-library/closure/goog/messaging/testdata/portnetwork_inner.html
    deleted file mode 100644
    index c24407e40a8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/testdata/portnetwork_inner.html
    +++ /dev/null
    @@ -1,34 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    -<head>
    -<title>
    -  Closure Unit Tests - goog.messaging.PortNetwork iframe page
    -</title>
    -<script src="../../base.js"></script>
    -<script>
    -goog.require('goog.messaging.PortCaller');
    -goog.require('goog.messaging.PortChannel');
    -</script>
    -</head>
    -<body>
    -<script>
    -var caller = new goog.messaging.PortCaller(
    -    goog.messaging.PortChannel.forGlobalWindow('*'));
    -
    -caller.dial('worker2').registerService('sendToWorker1', function(msg) {
    -  msg.push('frame');
    -  caller.dial('worker1').send('sendToMain', msg);
    -}, true);
    -
    -</script>
    -</body>
    -</html>
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/testdata/portnetwork_worker1.js b/src/database/third_party/closure-library/closure/goog/messaging/testdata/portnetwork_worker1.js
    deleted file mode 100644
    index e7248a51b70..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/testdata/portnetwork_worker1.js
    +++ /dev/null
    @@ -1,32 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -// Use of this source code is governed by the Apache License, Version 2.0.
    -// See the COPYING file for details.
    -
    -/**
    - * @fileoverview A web worker for integration testing the PortPool class.
    - *
    - * @nocompile
    - */
    -
    -self.CLOSURE_BASE_PATH = '../../';
    -importScripts('../../bootstrap/webworkers.js');
    -importScripts('../../base.js');
    -
    -// The provide is necessary to stop the jscompiler from thinking this is an
    -// entry point and adding it into the manifest incorrectly.
    -goog.provide('goog.messaging.testdata.portnetwork_worker1');
    -goog.require('goog.messaging.PortCaller');
    -goog.require('goog.messaging.PortChannel');
    -
    -function startListening() {
    -  var caller = new goog.messaging.PortCaller(
    -      new goog.messaging.PortChannel(self));
    -
    -  caller.dial('frame').registerService('sendToMain', function(msg) {
    -    msg.push('worker1');
    -    caller.dial('main').send('result', msg);
    -  }, true);
    -}
    -
    -startListening();
    diff --git a/src/database/third_party/closure-library/closure/goog/messaging/testdata/portnetwork_worker2.js b/src/database/third_party/closure-library/closure/goog/messaging/testdata/portnetwork_worker2.js
    deleted file mode 100644
    index 97adc932534..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/messaging/testdata/portnetwork_worker2.js
    +++ /dev/null
    @@ -1,32 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -// Use of this source code is governed by the Apache License, Version 2.0.
    -// See the COPYING file for details.
    -
    -/**
    - * @fileoverview A web worker for integration testing the PortPool class.
    - *
    - * @nocompile
    - */
    -
    -self.CLOSURE_BASE_PATH = '../../';
    -importScripts('../../bootstrap/webworkers.js');
    -importScripts('../../base.js');
    -
    -// The provide is necessary to stop the jscompiler from thinking this is an
    -// entry point and adding it into the manifest incorrectly.
    -goog.provide('goog.messaging.testdata.portnetwork_worker2');
    -goog.require('goog.messaging.PortCaller');
    -goog.require('goog.messaging.PortChannel');
    -
    -function startListening() {
    -  var caller = new goog.messaging.PortCaller(
    -      new goog.messaging.PortChannel(self));
    -
    -  caller.dial('main').registerService('sendToFrame', function(msg) {
    -    msg.push('worker2');
    -    caller.dial('frame').send('sendToWorker1', msg);
    -  }, true);
    -}
    -
    -startListening();
    diff --git a/src/database/third_party/closure-library/closure/goog/module/abstractmoduleloader.js b/src/database/third_party/closure-library/closure/goog/module/abstractmoduleloader.js
    deleted file mode 100644
    index e280af06ea6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/module/abstractmoduleloader.js
    +++ /dev/null
    @@ -1,58 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview An interface for module loading.
    - *
    - */
    -
    -goog.provide('goog.module.AbstractModuleLoader');
    -
    -/** @suppress {extraRequire} */
    -goog.require('goog.module');
    -
    -
    -/**
    - * An interface that loads JavaScript modules.
    - * @interface
    - */
    -goog.module.AbstractModuleLoader = function() {};
    -
    -
    -/**
    - * Loads a list of JavaScript modules.
    - *
    - * @param {Array<string>} ids The module ids in dependency order.
    - * @param {Object} moduleInfoMap A mapping from module id to ModuleInfo object.
    - * @param {function()?=} opt_successFn The callback if module loading is a
    - *     success.
    - * @param {function(?number)?=} opt_errorFn The callback if module loading is an
    - *     error.
    - * @param {function()?=} opt_timeoutFn The callback if module loading times out.
    - * @param {boolean=} opt_forceReload Whether to bypass cache while loading the
    - *     module.
    - */
    -goog.module.AbstractModuleLoader.prototype.loadModules = function(
    -    ids, moduleInfoMap, opt_successFn, opt_errorFn, opt_timeoutFn,
    -    opt_forceReload) {};
    -
    -
    -/**
    - * Pre-fetches a JavaScript module.
    - *
    - * @param {string} id The module id.
    - * @param {!goog.module.ModuleInfo} moduleInfo The module info.
    - */
    -goog.module.AbstractModuleLoader.prototype.prefetchModule = function(
    -    id, moduleInfo) {};
    diff --git a/src/database/third_party/closure-library/closure/goog/module/basemodule.js b/src/database/third_party/closure-library/closure/goog/module/basemodule.js
    deleted file mode 100644
    index f0d924a4b06..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/module/basemodule.js
    +++ /dev/null
    @@ -1,47 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Defines the base class for a module. This is used to allow the
    - * code to be modularized, giving the benefits of lazy loading and loading on
    - * demand.
    - *
    - */
    -
    -goog.provide('goog.module.BaseModule');
    -
    -goog.require('goog.Disposable');
    -/** @suppress {extraRequire} */
    -goog.require('goog.module');
    -
    -
    -
    -/**
    - * A basic module object that represents a module of Javascript code that can
    - * be dynamically loaded.
    - *
    - * @constructor
    - * @extends {goog.Disposable}
    - */
    -goog.module.BaseModule = function() {
    -  goog.Disposable.call(this);
    -};
    -goog.inherits(goog.module.BaseModule, goog.Disposable);
    -
    -
    -/**
    - * Performs any load-time initialization that the module requires.
    - * @param {Object} context The module context.
    - */
    -goog.module.BaseModule.prototype.initialize = function(context) {};
    diff --git a/src/database/third_party/closure-library/closure/goog/module/loader.js b/src/database/third_party/closure-library/closure/goog/module/loader.js
    deleted file mode 100644
    index decf39ac6c2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/module/loader.js
    +++ /dev/null
    @@ -1,345 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - *
    - * @fileoverview This class supports the dynamic loading of compiled
    - * javascript modules at runtime, as descibed in the designdoc.
    - *
    - *   <http://go/js_modules_design>
    - *
    - */
    -
    -goog.provide('goog.module.Loader');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -/** @suppress {extraRequire} */
    -goog.require('goog.module');
    -goog.require('goog.object');
    -
    -
    -
    -/**
    - * The dynamic loading functionality is defined as a class. The class
    - * will be used as singleton. There is, however, a two step
    - * initialization procedure because parameters need to be passed to
    - * the goog.module.Loader instance.
    - *
    - * @constructor
    - * @final
    - */
    -goog.module.Loader = function() {
    -  /**
    -   * Map of module name/array of {symbol name, callback} pairs that are pending
    -   * to be loaded.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.pending_ = {};
    -
    -  /**
    -   * Provides associative access to each module and the symbols of each module
    -   * that have aready been loaded (one lookup for the module, another lookup
    -   * on the module for the symbol).
    -   * @type {Object}
    -   * @private
    -   */
    -  this.modules_ = {};
    -
    -  /**
    -   * Map of module name to module url. Used to avoid fetching the same URL
    -   * twice by keeping track of in-flight URLs.
    -   * Note: this allows two modules to be bundled into the same file.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.pendingModuleUrls_ = {};
    -
    -  /**
    -   * The base url to load modules from. This property will be set in init().
    -   * @type {?string}
    -   * @private
    -   */
    -  this.urlBase_ = null;
    -
    -  /**
    -   * Array of modules that have been requested before init() was called.
    -   * If require() is called before init() was called, the required
    -   * modules can obviously not yet be loaded, because their URL is
    -   * unknown. The modules that are requested before init() are
    -   * therefore stored in this array, and they are loaded at init()
    -   * time.
    -   * @type {Array<string>}
    -   * @private
    -   */
    -  this.pendingBeforeInit_ = [];
    -};
    -goog.addSingletonGetter(goog.module.Loader);
    -
    -
    -/**
    - * Wrapper of goog.module.Loader.require() for use in modules.
    - * See method goog.module.Loader.require() for
    - * explanation of params.
    - *
    - * @param {string} module The name of the module. Usually, the value
    - *     is defined as a constant whose name starts with MOD_.
    - * @param {number|string} symbol The ID of the symbol. Usually, the value is
    - *     defined as a constant whose name starts with SYM_.
    - * @param {Function} callback This function will be called with the
    - *     resolved symbol as the argument once the module is loaded.
    - */
    -goog.module.Loader.require = function(module, symbol, callback) {
    -  goog.module.Loader.getInstance().require(module, symbol, callback);
    -};
    -
    -
    -/**
    - * Wrapper of goog.module.Loader.provide() for use in modules
    - * See method goog.module.Loader.provide() for explanation of params.
    - *
    - * @param {string} module The name of the module. Cf. parameter module
    - *     of method require().
    - * @param {number|string=} opt_symbol The symbol being defined, or nothing
    - *     when all symbols of the module are defined. Cf. parameter symbol of
    - *     method require().
    - * @param {Object=} opt_object The object bound to the symbol, or nothing when
    - *     all symbols of the module are defined.
    - */
    -goog.module.Loader.provide = function(module, opt_symbol, opt_object) {
    -  goog.module.Loader.getInstance().provide(
    -      module, opt_symbol, opt_object);
    -};
    -
    -
    -/**
    - * Wrapper of init() so that we only need to export this single
    - * identifier instead of three. See method goog.module.Loader.init() for
    - * explanation of param.
    - *
    - * @param {string} urlBase The URL of the base library.
    - * @param {Function=} opt_urlFunction Function that creates the URL for the
    - *     module file. It will be passed the base URL for module files and the
    - *     module name and should return the fully-formed URL to the module file to
    - *     load.
    - */
    -goog.module.Loader.init = function(urlBase, opt_urlFunction) {
    -  goog.module.Loader.getInstance().init(urlBase, opt_urlFunction);
    -};
    -
    -
    -/**
    - * Produces a function that delegates all its arguments to a
    - * dynamically loaded function. This is used to export dynamically
    - * loaded functions.
    - *
    - * @param {string} module The module to load from.
    - * @param {number|string} symbol The ID of the symbol to load from the module.
    - *     This symbol must resolve to a function.
    - * @return {!Function} A function that forwards all its arguments to
    - *     the dynamically loaded function specified by module and symbol.
    - */
    -goog.module.Loader.loaderCall = function(module, symbol) {
    -  return function() {
    -    var args = arguments;
    -    goog.module.Loader.require(module, symbol, function(f) {
    -      f.apply(null, args);
    -    });
    -  };
    -};
    -
    -
    -/**
    - * Creates a full URL to the compiled module code given a base URL and a
    - * module name. By default it's urlBase + '_' + module + '.js'.
    - * @param {string} urlBase URL to the module files.
    - * @param {string} module Module name.
    - * @return {string} The full url to the module binary.
    - * @private
    - */
    -goog.module.Loader.prototype.getModuleUrl_ = function(urlBase, module) {
    -  return urlBase + '_' + module + '.js';
    -};
    -
    -
    -/**
    - * The globally exported name of the load callback. Matches the
    - * definition in the js_modular_binary() BUILD rule.
    - * @type {string}
    - */
    -goog.module.Loader.LOAD_CALLBACK = '__gjsload__';
    -
    -
    -/**
    - * Loads the module by evaluating the javascript text in the current
    - * scope. Uncompiled, base identifiers are visible in the global scope;
    - * when compiled they are visible in the closure of the anonymous
    - * namespace. Notice that this cannot be replaced by the global eval,
    - * because the global eval isn't in the scope of the anonymous
    - * namespace function that the jscompiled code lives in.
    - *
    - * @param {string} t_ The javascript text to evaluate. IMPORTANT: The
    - *   name of the identifier is chosen so that it isn't compiled and
    - *   hence cannot shadow compiled identifiers in the surrounding scope.
    - * @private
    - */
    -goog.module.Loader.loaderEval_ = function(t_) {
    -  eval(t_);
    -};
    -
    -
    -/**
    - * Initializes the Loader to be fully functional. Also executes load
    - * requests that were received before initialization. Must be called
    - * exactly once, with the URL of the base library. Module URLs are
    - * derived from the URL of the base library by inserting the module
    - * name, preceded by a period, before the .js prefix of the base URL.
    - *
    - * @param {string} baseUrl The URL of the base library.
    - * @param {Function=} opt_urlFunction Function that creates the URL for the
    - *     module file. It will be passed the base URL for module files and the
    - *     module name and should return the fully-formed URL to the module file to
    - *     load.
    - */
    -goog.module.Loader.prototype.init = function(baseUrl, opt_urlFunction) {
    -  // For the use by the module wrappers, loaderEval_ is exported to
    -  // the page. Note that, despite the name, this is not part of the
    -  // API, so it is here and not in api_app.js. Cf. BUILD. Note this is
    -  // done before the first load requests are sent.
    -  goog.exportSymbol(goog.module.Loader.LOAD_CALLBACK,
    -      goog.module.Loader.loaderEval_);
    -
    -  this.urlBase_ = baseUrl.replace(/\.js$/, '');
    -  if (opt_urlFunction) {
    -    this.getModuleUrl_ = opt_urlFunction;
    -  }
    -
    -  goog.array.forEach(this.pendingBeforeInit_, function(module) {
    -    this.load_(module);
    -  }, this);
    -  goog.array.clear(this.pendingBeforeInit_);
    -};
    -
    -
    -/**
    - * Requests the loading of a symbol from a module. When the module is
    - * loaded, the requested symbol will be passed as argument to the
    - * function callback.
    - *
    - * @param {string} module The name of the module. Usually, the value
    - *     is defined as a constant whose name starts with MOD_.
    - * @param {number|string} symbol The ID of the symbol. Usually, the value is
    - *     defined as a constant whose name starts with SYM_.
    - * @param {Function} callback This function will be called with the
    - *     resolved symbol as the argument once the module is loaded.
    - */
    -goog.module.Loader.prototype.require = function(module, symbol, callback) {
    -  var pending = this.pending_;
    -  var modules = this.modules_;
    -  if (modules[module]) {
    -    // already loaded
    -    callback(modules[module][symbol]);
    -  } else if (pending[module]) {
    -    // loading is pending from another require of the same module
    -    pending[module].push([symbol, callback]);
    -  } else {
    -    // not loaded, and not requested
    -    pending[module] = [[symbol, callback]];  // Yes, really [[ ]].
    -    // Defer loading to initialization if Loader is not yet
    -    // initialized, otherwise load the module.
    -    if (goog.isString(this.urlBase_)) {
    -      this.load_(module);
    -    } else {
    -      this.pendingBeforeInit_.push(module);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Registers a symbol in a loaded module. When called without symbol,
    - * registers the module to be fully loaded and executes all callbacks
    - * from pending require() callbacks for this module.
    - *
    - * @param {string} module The name of the module. Cf. parameter module
    - *     of method require().
    - * @param {number|string=} opt_symbol The symbol being defined, or nothing when
    - *     all symbols of the module are defined. Cf. parameter symbol of method
    - *     require().
    - * @param {Object=} opt_object The object bound to the symbol, or nothing when
    - *     all symbols of the module are defined.
    - */
    -goog.module.Loader.prototype.provide = function(
    -    module, opt_symbol, opt_object) {
    -  var modules = this.modules_;
    -  var pending = this.pending_;
    -  if (!modules[module]) {
    -    modules[module] = {};
    -  }
    -  if (opt_object) {
    -    // When an object is provided, just register it.
    -    modules[module][opt_symbol] = opt_object;
    -  } else if (pending[module]) {
    -    // When no object is provided, and there are pending require()
    -    // callbacks for this module, execute them.
    -    for (var i = 0; i < pending[module].length; ++i) {
    -      var symbol = pending[module][i][0];
    -      var callback = pending[module][i][1];
    -      callback(modules[module][symbol]);
    -    }
    -    delete pending[module];
    -    delete this.pendingModuleUrls_[module];
    -  }
    -};
    -
    -
    -/**
    - * Starts to load a module. Assumes that init() was called.
    - *
    - * @param {string} module The name of the module.
    - * @private
    - */
    -goog.module.Loader.prototype.load_ = function(module) {
    -  // NOTE(user): If the module request happens inside a click handler
    -  // (presumably inside any user event handler, but the onload event
    -  // handler is fine), IE will load the script but not execute
    -  // it. Thus we break out of the current flow of control before we do
    -  // the load. For the record, for IE it would have been enough to
    -  // just defer the assignment to src. Safari doesn't execute the
    -  // script if the assignment to src happens *after* the script
    -  // element is inserted into the DOM.
    -  goog.Timer.callOnce(function() {
    -    // The module might have been registered in the interim (if fetched as part
    -    // of another module fetch because they share the same url)
    -    if (this.modules_[module]) {
    -      return;
    -    }
    -
    -    goog.asserts.assertString(this.urlBase_);
    -    var url = this.getModuleUrl_(this.urlBase_, module);
    -
    -    // Check if specified URL is already in flight
    -    var urlInFlight = goog.object.containsValue(this.pendingModuleUrls_, url);
    -    this.pendingModuleUrls_[module] = url;
    -    if (urlInFlight) {
    -      return;
    -    }
    -
    -    var s = goog.dom.createDom('script',
    -        {'type': 'text/javascript', 'src': url});
    -    document.body.appendChild(s);
    -  }, 0, this);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/module/module.js b/src/database/third_party/closure-library/closure/goog/module/module.js
    deleted file mode 100644
    index 689e0396e0e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/module/module.js
    +++ /dev/null
    @@ -1,33 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - *
    - * @fileoverview This class supports the dynamic loading of compiled
    - * javascript modules at runtime, as descibed in the designdoc.
    - *
    - *   <http://go/js_modules_design>
    - *
    - */
    -
    -goog.provide('goog.module');
    -
    -// TODO(johnlenz): Here we explicitly initialize the namespace to avoid
    -// problems with the goog.module method in base.js.  Once the goog.module has
    -// landed and compiler updated and released and everyone is on that release
    -// we can remove this file.
    -//
    -// Alternately, we can move everthing out of the goog.module namespace.
    -//
    -goog.module = goog.module || {};
    diff --git a/src/database/third_party/closure-library/closure/goog/module/moduleinfo.js b/src/database/third_party/closure-library/closure/goog/module/moduleinfo.js
    deleted file mode 100644
    index cdb12079b5d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/module/moduleinfo.js
    +++ /dev/null
    @@ -1,341 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Defines the goog.module.ModuleInfo class.
    - *
    - */
    -
    -goog.provide('goog.module.ModuleInfo');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.async.throwException');
    -goog.require('goog.functions');
    -/** @suppress {extraRequire} */
    -goog.require('goog.module');
    -goog.require('goog.module.BaseModule');
    -goog.require('goog.module.ModuleLoadCallback');
    -
    -
    -
    -/**
    - * A ModuleInfo object is used by the ModuleManager to hold information about a
    - * module of js code that may or may not yet be loaded into the environment.
    - *
    - * @param {Array<string>} deps Ids of the modules that must be loaded before
    - *     this one. The ids must be in dependency order (i.e. if the ith module
    - *     depends on the jth module, then i > j).
    - * @param {string} id The module's ID.
    - * @constructor
    - * @extends {goog.Disposable}
    - * @final
    - */
    -goog.module.ModuleInfo = function(deps, id) {
    -  goog.Disposable.call(this);
    -
    -  /**
    -   * A list of the ids of the modules that must be loaded before this module.
    -   * @type {Array<string>}
    -   * @private
    -   */
    -  this.deps_ = deps;
    -
    -  /**
    -   * The module's ID.
    -   * @type {string}
    -   * @private
    -   */
    -  this.id_ = id;
    -
    -  /**
    -   * Callbacks to execute once this module is loaded.
    -   * @type {Array<goog.module.ModuleLoadCallback>}
    -   * @private
    -   */
    -  this.onloadCallbacks_ = [];
    -
    -  /**
    -   * Callbacks to execute if the module load errors.
    -   * @type {Array<goog.module.ModuleLoadCallback>}
    -   * @private
    -   */
    -  this.onErrorCallbacks_ = [];
    -
    -  /**
    -   * Early callbacks to execute once this module is loaded. Called after
    -   * module initialization but before regular onload callbacks.
    -   * @type {Array<goog.module.ModuleLoadCallback>}
    -   * @private
    -   */
    -  this.earlyOnloadCallbacks_ = [];
    -};
    -goog.inherits(goog.module.ModuleInfo, goog.Disposable);
    -
    -
    -/**
    - * The uris that can be used to retrieve this module's code.
    - * @type {Array<string>?}
    - * @private
    - */
    -goog.module.ModuleInfo.prototype.uris_ = null;
    -
    -
    -/**
    - * The constructor to use to instantiate the module object after the module
    - * code is loaded. This must be either goog.module.BaseModule or a subclass of
    - * it.
    - * @type {Function}
    - * @private
    - */
    -goog.module.ModuleInfo.prototype.moduleConstructor_ = goog.module.BaseModule;
    -
    -
    -/**
    - * The module object. This will be null until the module is loaded.
    - * @type {goog.module.BaseModule?}
    - * @private
    - */
    -goog.module.ModuleInfo.prototype.module_ = null;
    -
    -
    -/**
    - * Gets the dependencies of this module.
    - * @return {Array<string>} The ids of the modules that this module depends on.
    - */
    -goog.module.ModuleInfo.prototype.getDependencies = function() {
    -  return this.deps_;
    -};
    -
    -
    -/**
    - * Gets the ID of this module.
    - * @return {string} The ID.
    - */
    -goog.module.ModuleInfo.prototype.getId = function() {
    -  return this.id_;
    -};
    -
    -
    -/**
    - * Sets the uris of this module.
    - * @param {Array<string>} uris Uris for this module's code.
    - */
    -goog.module.ModuleInfo.prototype.setUris = function(uris) {
    -  this.uris_ = uris;
    -};
    -
    -
    -/**
    - * Gets the uris of this module.
    - * @return {Array<string>?} Uris for this module's code.
    - */
    -goog.module.ModuleInfo.prototype.getUris = function() {
    -  return this.uris_;
    -};
    -
    -
    -/**
    - * Sets the constructor to use to instantiate the module object after the
    - * module code is loaded.
    - * @param {Function} constructor The constructor of a goog.module.BaseModule
    - *     subclass.
    - */
    -goog.module.ModuleInfo.prototype.setModuleConstructor = function(
    -    constructor) {
    -  if (this.moduleConstructor_ === goog.module.BaseModule) {
    -    this.moduleConstructor_ = constructor;
    -  } else {
    -    throw Error('Cannot set module constructor more than once.');
    -  }
    -};
    -
    -
    -/**
    - * Registers a function that should be called after the module is loaded. These
    - * early callbacks are called after {@link Module#initialize} is called but
    - * before the other callbacks are called.
    - * @param {Function} fn A callback function that takes a single argument which
    - *    is the module context.
    - * @param {Object=} opt_handler Optional handler under whose scope to execute
    - *     the callback.
    - * @return {!goog.module.ModuleLoadCallback} Reference to the callback
    - *     object.
    - */
    -goog.module.ModuleInfo.prototype.registerEarlyCallback = function(
    -    fn, opt_handler) {
    -  return this.registerCallback_(this.earlyOnloadCallbacks_, fn, opt_handler);
    -};
    -
    -
    -/**
    - * Registers a function that should be called after the module is loaded.
    - * @param {Function} fn A callback function that takes a single argument which
    - *    is the module context.
    - * @param {Object=} opt_handler Optional handler under whose scope to execute
    - *     the callback.
    - * @return {!goog.module.ModuleLoadCallback} Reference to the callback
    - *     object.
    - */
    -goog.module.ModuleInfo.prototype.registerCallback = function(
    -    fn, opt_handler) {
    -  return this.registerCallback_(this.onloadCallbacks_, fn, opt_handler);
    -};
    -
    -
    -/**
    - * Registers a function that should be called if the module load fails.
    - * @param {Function} fn A callback function that takes a single argument which
    - *    is the failure type.
    - * @param {Object=} opt_handler Optional handler under whose scope to execute
    - *     the callback.
    - * @return {!goog.module.ModuleLoadCallback} Reference to the callback
    - *     object.
    - */
    -goog.module.ModuleInfo.prototype.registerErrback = function(
    -    fn, opt_handler) {
    -  return this.registerCallback_(this.onErrorCallbacks_, fn, opt_handler);
    -};
    -
    -
    -/**
    - * Registers a function that should be called after the module is loaded.
    - * @param {Array<goog.module.ModuleLoadCallback>} callbacks The array to
    - *     add the callback to.
    - * @param {Function} fn A callback function that takes a single argument which
    - *     is the module context.
    - * @param {Object=} opt_handler Optional handler under whose scope to execute
    - *     the callback.
    - * @return {!goog.module.ModuleLoadCallback} Reference to the callback
    - *     object.
    - * @private
    - */
    -goog.module.ModuleInfo.prototype.registerCallback_ = function(
    -    callbacks, fn, opt_handler) {
    -  var callback = new goog.module.ModuleLoadCallback(fn, opt_handler);
    -  callbacks.push(callback);
    -  return callback;
    -};
    -
    -
    -/**
    - * Determines whether the module has been loaded.
    - * @return {boolean} Whether the module has been loaded.
    - */
    -goog.module.ModuleInfo.prototype.isLoaded = function() {
    -  return !!this.module_;
    -};
    -
    -
    -/**
    - * Gets the module.
    - * @return {goog.module.BaseModule?} The module if it has been loaded.
    - *     Otherwise, null.
    - */
    -goog.module.ModuleInfo.prototype.getModule = function() {
    -  return this.module_;
    -};
    -
    -
    -/**
    - * Sets this module as loaded.
    - * @param {function() : Object} contextProvider A function that provides the
    - *     module context.
    - * @return {boolean} Whether any errors occurred while executing the onload
    - *     callbacks.
    - */
    -goog.module.ModuleInfo.prototype.onLoad = function(contextProvider) {
    -  // Instantiate and initialize the module object.
    -  var module = new this.moduleConstructor_;
    -  module.initialize(contextProvider());
    -
    -  // Keep an internal reference to the module.
    -  this.module_ = module;
    -
    -  // Fire any early callbacks that were waiting for the module to be loaded.
    -  var errors =
    -      !!this.callCallbacks_(this.earlyOnloadCallbacks_, contextProvider());
    -
    -  // Fire any callbacks that were waiting for the module to be loaded.
    -  errors = errors ||
    -      !!this.callCallbacks_(this.onloadCallbacks_, contextProvider());
    -
    -  if (!errors) {
    -    // Clear the errbacks.
    -    this.onErrorCallbacks_.length = 0;
    -  }
    -
    -  return errors;
    -};
    -
    -
    -/**
    - * Calls the error callbacks for the module.
    - * @param {goog.module.ModuleManager.FailureType} cause What caused the error.
    - */
    -goog.module.ModuleInfo.prototype.onError = function(cause) {
    -  var result = this.callCallbacks_(this.onErrorCallbacks_, cause);
    -  if (result) {
    -    // Throw an exception asynchronously. Do not let the exception leak
    -    // up to the caller, or it will blow up the module loading framework.
    -    window.setTimeout(
    -        goog.functions.error('Module errback failures: ' + result), 0);
    -  }
    -  this.earlyOnloadCallbacks_.length = 0;
    -  this.onloadCallbacks_.length = 0;
    -};
    -
    -
    -/**
    - * Helper to call the callbacks after module load.
    - * @param {Array<goog.module.ModuleLoadCallback>} callbacks The callbacks
    - *     to call and then clear.
    - * @param {*} context The module context.
    - * @return {Array<*>} Any errors encountered while calling the callbacks,
    - *     or null if there were no errors.
    - * @private
    - */
    -goog.module.ModuleInfo.prototype.callCallbacks_ = function(callbacks, context) {
    -  // NOTE(nicksantos):
    -  // In practice, there are two error-handling scenarios:
    -  // 1) The callback does some mandatory initialization of the module.
    -  // 2) The callback is for completion of some optional UI event.
    -  // There's no good way to handle both scenarios.
    -  //
    -  // Our strategy here is to protect module manager from exceptions, so that
    -  // the failure of one module doesn't affect the loading of other modules.
    -  // Errors are thrown outside of the current stack frame, so they still
    -  // get reported but don't interrupt execution.
    -
    -  // Call each callback in the order they were registered
    -  var errors = [];
    -  for (var i = 0; i < callbacks.length; i++) {
    -    try {
    -      callbacks[i].execute(context);
    -    } catch (e) {
    -      goog.async.throwException(e);
    -      errors.push(e);
    -    }
    -  }
    -
    -  // Clear the list of callbacks.
    -  callbacks.length = 0;
    -  return errors.length ? errors : null;
    -};
    -
    -
    -/** @override */
    -goog.module.ModuleInfo.prototype.disposeInternal = function() {
    -  goog.module.ModuleInfo.superClass_.disposeInternal.call(this);
    -  goog.dispose(this.module_);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/module/moduleinfo_test.html b/src/database/third_party/closure-library/closure/goog/module/moduleinfo_test.html
    deleted file mode 100644
    index 8351b9171fd..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/module/moduleinfo_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.module.ModuleInfo
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -  goog.require('goog.module.ModuleInfoTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/module/moduleinfo_test.js b/src/database/third_party/closure-library/closure/goog/module/moduleinfo_test.js
    deleted file mode 100644
    index b0c23596bbd..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/module/moduleinfo_test.js
    +++ /dev/null
    @@ -1,135 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.module.ModuleInfoTest');
    -goog.setTestOnly('goog.module.ModuleInfoTest');
    -
    -goog.require('goog.module.BaseModule');
    -goog.require('goog.module.ModuleInfo');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.jsunit');
    -
    -
    -
    -var mockClock;
    -
    -
    -function setUp() {
    -  mockClock = new goog.testing.MockClock(true);
    -}
    -
    -
    -function tearDown() {
    -  mockClock.uninstall();
    -}
    -
    -
    -/**
    - * Test initial state of module info.
    - */
    -function testNotLoadedAtStart() {
    -  var m = new goog.module.ModuleInfo();
    -  assertFalse('Shouldn\'t be loaded', m.isLoaded());
    -}
    -
    -var TestModule = function() {
    -  goog.module.BaseModule.call(this);
    -};
    -goog.inherits(TestModule, goog.module.BaseModule);
    -
    -
    -/**
    - * Test loaded module info.
    - */
    -function testOnLoad() {
    -  var m = new goog.module.ModuleInfo();
    -
    -  m.setModuleConstructor(TestModule);
    -  m.onLoad(goog.nullFunction);
    -  assertTrue(m.isLoaded());
    -
    -  var module = m.getModule();
    -  assertNotNull(module);
    -  assertTrue(module instanceof TestModule);
    -
    -  m.dispose();
    -  assertTrue(m.isDisposed());
    -  assertTrue('Disposing of ModuleInfo should dispose of its module',
    -      module.isDisposed());
    -}
    -
    -
    -/**
    - * Test callbacks on module load.
    - */
    -function testCallbacks() {
    -  var m = new goog.module.ModuleInfo();
    -  m.setModuleConstructor(TestModule);
    -  var index = 0;
    -  var a = -1, b = -1, c = -1, d = -1;
    -  var ca = m.registerCallback(function() { a = index++; });
    -  var cb = m.registerCallback(function() { b = index++; });
    -  var cc = m.registerCallback(function() { c = index++; });
    -  var cd = m.registerEarlyCallback(function() { d = index++; });
    -  cb.abort();
    -  m.onLoad(goog.nullFunction);
    -
    -  assertTrue('callback A should have fired', a >= 0);
    -  assertFalse('callback B should have been aborted', b >= 0);
    -  assertTrue('callback C should have fired', c >= 0);
    -  assertTrue('early callback d should have fired', d >= 0);
    -
    -  assertEquals('ordering of callbacks was wrong', 0, d);
    -  assertEquals('ordering of callbacks was wrong', 1, a);
    -  assertEquals('ordering of callbacks was wrong', 2, c);
    -}
    -
    -
    -function testErrorsInCallbacks() {
    -  var m = new goog.module.ModuleInfo();
    -  m.setModuleConstructor(TestModule);
    -  m.registerCallback(function() { throw new Error('boom1'); });
    -  m.registerCallback(function() { throw new Error('boom2'); });
    -  var hadError = m.onLoad(goog.nullFunction);
    -  assertTrue(hadError);
    -
    -  var e = assertThrows(function() {
    -    mockClock.tick();
    -  });
    -
    -  assertEquals('boom1', e.message);
    -}
    -
    -
    -/**
    - * Tests the error callbacks.
    - */
    -function testErrbacks() {
    -  var m = new goog.module.ModuleInfo();
    -  m.setModuleConstructor(TestModule);
    -  var index = 0;
    -  var a = -1, b = -1, c = -1, d = -1;
    -  var ca = m.registerErrback(function() { a = index++; });
    -  var cb = m.registerErrback(function() { b = index++; });
    -  var cc = m.registerErrback(function() { c = index++; });
    -  m.onError('foo');
    -
    -  assertTrue('callback A should have fired', a >= 0);
    -  assertTrue('callback B should have fired', b >= 0);
    -  assertTrue('callback C should have fired', c >= 0);
    -
    -  assertEquals('ordering of callbacks was wrong', 0, a);
    -  assertEquals('ordering of callbacks was wrong', 1, b);
    -  assertEquals('ordering of callbacks was wrong', 2, c);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/module/moduleloadcallback.js b/src/database/third_party/closure-library/closure/goog/module/moduleloadcallback.js
    deleted file mode 100644
    index bd7c1d72b76..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/module/moduleloadcallback.js
    +++ /dev/null
    @@ -1,87 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A simple callback mechanism for notification about module
    - * loads. Should be considered package-private to goog.module.
    - *
    - */
    -
    -goog.provide('goog.module.ModuleLoadCallback');
    -
    -goog.require('goog.debug.entryPointRegistry');
    -goog.require('goog.debug.errorHandlerWeakDep');
    -/** @suppress {extraRequire} */
    -goog.require('goog.module');
    -
    -
    -
    -/**
    - * Class used to encapsulate the callbacks to be called when a module loads.
    - * @param {Function} fn Callback function.
    - * @param {Object=} opt_handler Optional handler under whose scope to execute
    - *     the callback.
    - * @constructor
    - * @final
    - */
    -goog.module.ModuleLoadCallback = function(fn, opt_handler) {
    -  /**
    -   * Callback function.
    -   * @type {Function}
    -   * @private
    -   */
    -  this.fn_ = fn;
    -
    -  /**
    -   * Optional handler under whose scope to execute the callback.
    -   * @type {Object|undefined}
    -   * @private
    -   */
    -  this.handler_ = opt_handler;
    -};
    -
    -
    -/**
    - * Completes the operation and calls the callback function if appropriate.
    - * @param {*} context The module context.
    - */
    -goog.module.ModuleLoadCallback.prototype.execute = function(context) {
    -  if (this.fn_) {
    -    this.fn_.call(this.handler_ || null, context);
    -    this.handler_ = null;
    -    this.fn_ = null;
    -  }
    -};
    -
    -
    -/**
    - * Abort the callback, but not the actual module load.
    - */
    -goog.module.ModuleLoadCallback.prototype.abort = function() {
    -  this.fn_ = null;
    -  this.handler_ = null;
    -};
    -
    -
    -// Register the browser event handler as an entry point, so that
    -// it can be monitored for exception handling, etc.
    -goog.debug.entryPointRegistry.register(
    -    /**
    -     * @param {function(!Function): !Function} transformer The transforming
    -     *     function.
    -     */
    -    function(transformer) {
    -      goog.module.ModuleLoadCallback.prototype.execute =
    -          transformer(goog.module.ModuleLoadCallback.prototype.execute);
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/module/moduleloadcallback_test.html b/src/database/third_party/closure-library/closure/goog/module/moduleloadcallback_test.html
    deleted file mode 100644
    index f7a1b9eefc9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/module/moduleloadcallback_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    -Author: nicksantos@google.com (Nick Santos)
    --->
    -<html>
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   JsUnit tests for goog.module.ModuleLoadCallback
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.module.ModuleLoadCallbackTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/module/moduleloadcallback_test.js b/src/database/third_party/closure-library/closure/goog/module/moduleloadcallback_test.js
    deleted file mode 100644
    index 72ca9281389..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/module/moduleloadcallback_test.js
    +++ /dev/null
    @@ -1,45 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.module.ModuleLoadCallbackTest');
    -goog.setTestOnly('goog.module.ModuleLoadCallbackTest');
    -
    -goog.require('goog.debug.ErrorHandler');
    -goog.require('goog.debug.entryPointRegistry');
    -goog.require('goog.functions');
    -goog.require('goog.module.ModuleLoadCallback');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -
    -function testProtectEntryPoint() {
    -  // Test a callback created before the protect method is called.
    -  var callback1 = new goog.module.ModuleLoadCallback(
    -      goog.functions.error('callback1'));
    -
    -  var errorFn = goog.testing.recordFunction();
    -  var errorHandler = new goog.debug.ErrorHandler(errorFn);
    -  goog.debug.entryPointRegistry.monitorAll(errorHandler);
    -
    -  assertEquals(0, errorFn.getCallCount());
    -  assertThrows(goog.bind(callback1.execute, callback1));
    -  assertEquals(1, errorFn.getCallCount());
    -  assertContains('callback1', errorFn.getLastCall().getArguments()[0].message);
    -
    -  // Test a callback created after the protect method is called.
    -  var callback2 = new goog.module.ModuleLoadCallback(
    -      goog.functions.error('callback2'));
    -  assertThrows(goog.bind(callback1.execute, callback2));
    -  assertEquals(2, errorFn.getCallCount());
    -  assertContains('callback2', errorFn.getLastCall().getArguments()[0].message);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/module/moduleloader.js b/src/database/third_party/closure-library/closure/goog/module/moduleloader.js
    deleted file mode 100644
    index 7e3496d392f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/module/moduleloader.js
    +++ /dev/null
    @@ -1,461 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview The module loader for loading modules across the network.
    - *
    - * Browsers do not guarantee that scripts appended to the document
    - * are executed in the order they are added. For production mode, we use
    - * XHRs to load scripts, because they do not have this problem and they
    - * have superior mechanisms for handling failure. However, XHR-evaled
    - * scripts are harder to debug.
    - *
    - * In debugging mode, we use normal script tags. In order to make this work,
    - * we load the scripts in serial: we do not execute script B to the document
    - * until we are certain that script A is finished loading.
    - *
    - */
    -
    -goog.provide('goog.module.ModuleLoader');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.array');
    -goog.require('goog.events');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.log');
    -goog.require('goog.module.AbstractModuleLoader');
    -goog.require('goog.net.BulkLoader');
    -goog.require('goog.net.EventType');
    -goog.require('goog.net.jsloader');
    -goog.require('goog.userAgent');
    -goog.require('goog.userAgent.product');
    -
    -
    -
    -/**
    - * A class that loads Javascript modules.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - * @implements {goog.module.AbstractModuleLoader}
    - */
    -goog.module.ModuleLoader = function() {
    -  goog.module.ModuleLoader.base(this, 'constructor');
    -
    -  /**
    -   * Event handler for managing handling events.
    -   * @type {goog.events.EventHandler<!goog.module.ModuleLoader>}
    -   * @private
    -   */
    -  this.eventHandler_ = new goog.events.EventHandler(this);
    -
    -  /**
    -   * A map from module IDs to goog.module.ModuleLoader.LoadStatus.
    -   * @type {!Object<Array<string>, goog.module.ModuleLoader.LoadStatus>}
    -   * @private
    -   */
    -  this.loadingModulesStatus_ = {};
    -};
    -goog.inherits(goog.module.ModuleLoader, goog.events.EventTarget);
    -
    -
    -/**
    - * A logger.
    - * @type {goog.log.Logger}
    - * @protected
    - */
    -goog.module.ModuleLoader.prototype.logger = goog.log.getLogger(
    -    'goog.module.ModuleLoader');
    -
    -
    -/**
    - * Whether debug mode is enabled.
    - * @type {boolean}
    - * @private
    - */
    -goog.module.ModuleLoader.prototype.debugMode_ = false;
    -
    -
    -/**
    - * Whether source url injection is enabled.
    - * @type {boolean}
    - * @private
    - */
    -goog.module.ModuleLoader.prototype.sourceUrlInjection_ = false;
    -
    -
    -/**
    - * @return {boolean} Whether sourceURL affects stack traces.
    - *     Chrome is currently the only browser that does this, but
    - *     we believe other browsers are working on this.
    - * @see http://bugzilla.mozilla.org/show_bug.cgi?id=583083
    - */
    -goog.module.ModuleLoader.supportsSourceUrlStackTraces = function() {
    -  return goog.userAgent.product.CHROME;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether sourceURL affects the debugger.
    - */
    -goog.module.ModuleLoader.supportsSourceUrlDebugger = function() {
    -  return goog.userAgent.product.CHROME || goog.userAgent.GECKO;
    -};
    -
    -
    -/**
    - * Gets the debug mode for the loader.
    - * @return {boolean} Whether the debug mode is enabled.
    - */
    -goog.module.ModuleLoader.prototype.getDebugMode = function() {
    -  return this.debugMode_;
    -};
    -
    -
    -/**
    - * Sets the debug mode for the loader.
    - * @param {boolean} debugMode Whether the debug mode is enabled.
    - */
    -goog.module.ModuleLoader.prototype.setDebugMode = function(debugMode) {
    -  this.debugMode_ = debugMode;
    -};
    -
    -
    -/**
    - * When enabled, we will add a sourceURL comment to the end of all scripts
    - * to mark their origin.
    - *
    - * On WebKit, stack traces will refect the sourceURL comment, so this is
    - * useful for debugging webkit stack traces in production.
    - *
    - * Notice that in debug mode, we will use source url injection + eval rather
    - * then appending script nodes to the DOM, because the scripts will load far
    - * faster.  (Appending script nodes is very slow, because we can't parallelize
    - * the downloading and evaling of the script).
    - *
    - * The cost of appending sourceURL information is negligible when compared to
    - * the cost of evaling the script. Almost all clients will want this on.
    - *
    - * TODO(nicksantos): Turn this on by default. We may want to turn this off
    - * for clients that inject their own sourceURL.
    - *
    - * @param {boolean} enabled Whether source url injection is enabled.
    - */
    -goog.module.ModuleLoader.prototype.setSourceUrlInjection = function(enabled) {
    -  this.sourceUrlInjection_ = enabled;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether we're using source url injection.
    - * @private
    - */
    -goog.module.ModuleLoader.prototype.usingSourceUrlInjection_ = function() {
    -  return this.sourceUrlInjection_ ||
    -      (this.getDebugMode() &&
    -       goog.module.ModuleLoader.supportsSourceUrlStackTraces());
    -};
    -
    -
    -/** @override */
    -goog.module.ModuleLoader.prototype.loadModules = function(
    -    ids, moduleInfoMap, opt_successFn, opt_errorFn, opt_timeoutFn,
    -    opt_forceReload) {
    -  var loadStatus = this.loadingModulesStatus_[ids] ||
    -      new goog.module.ModuleLoader.LoadStatus();
    -  loadStatus.loadRequested = true;
    -  loadStatus.successFn = opt_successFn || null;
    -  loadStatus.errorFn = opt_errorFn || null;
    -
    -  if (!this.loadingModulesStatus_[ids]) {
    -    // Modules were not prefetched.
    -    this.loadingModulesStatus_[ids] = loadStatus;
    -    this.downloadModules_(ids, moduleInfoMap);
    -    // TODO(user): Need to handle timeouts in the module loading code.
    -  } else if (goog.isDefAndNotNull(loadStatus.responseTexts)) {
    -    // Modules prefetch is complete.
    -    this.evaluateCode_(ids);
    -  }
    -  // Otherwise modules prefetch is in progress, and these modules will be
    -  // executed after the prefetch is complete.
    -};
    -
    -
    -/**
    - * Evaluate the JS code.
    - * @param {Array<string>} moduleIds The module ids.
    - * @private
    - */
    -goog.module.ModuleLoader.prototype.evaluateCode_ = function(moduleIds) {
    -  this.dispatchEvent(new goog.module.ModuleLoader.Event(
    -      goog.module.ModuleLoader.EventType.REQUEST_SUCCESS, moduleIds));
    -
    -  goog.log.info(this.logger, 'evaluateCode ids:' + moduleIds);
    -  var success = true;
    -  var loadStatus = this.loadingModulesStatus_[moduleIds];
    -  var uris = loadStatus.requestUris;
    -  var texts = loadStatus.responseTexts;
    -  try {
    -    if (this.usingSourceUrlInjection_()) {
    -      for (var i = 0; i < uris.length; i++) {
    -        var uri = uris[i];
    -        goog.globalEval(texts[i] + ' //@ sourceURL=' + uri);
    -      }
    -    } else {
    -      goog.globalEval(texts.join('\n'));
    -    }
    -  } catch (e) {
    -    success = false;
    -    // TODO(user): Consider throwing an exception here.
    -    goog.log.warning(this.logger, 'Loaded incomplete code for module(s): ' +
    -        moduleIds, e);
    -  }
    -
    -  this.dispatchEvent(
    -      new goog.module.ModuleLoader.Event(
    -          goog.module.ModuleLoader.EventType.EVALUATE_CODE, moduleIds));
    -
    -  if (!success) {
    -    this.handleErrorHelper_(moduleIds, loadStatus.errorFn, null /* status */);
    -  } else if (loadStatus.successFn) {
    -    loadStatus.successFn();
    -  }
    -  delete this.loadingModulesStatus_[moduleIds];
    -};
    -
    -
    -/**
    - * Handles a successful response to a request for prefetch or load one or more
    - * modules.
    - *
    - * @param {goog.net.BulkLoader} bulkLoader The bulk loader.
    - * @param {Array<string>} moduleIds The ids of the modules requested.
    - * @private
    - */
    -goog.module.ModuleLoader.prototype.handleSuccess_ = function(
    -    bulkLoader, moduleIds) {
    -  goog.log.info(this.logger, 'Code loaded for module(s): ' + moduleIds);
    -
    -  var loadStatus = this.loadingModulesStatus_[moduleIds];
    -  loadStatus.responseTexts = bulkLoader.getResponseTexts();
    -
    -  if (loadStatus.loadRequested) {
    -    this.evaluateCode_(moduleIds);
    -  }
    -
    -  // NOTE: A bulk loader instance is used for loading a set of module ids.
    -  // Once these modules have been loaded successfully or in error the bulk
    -  // loader should be disposed as it is not needed anymore. A new bulk loader
    -  // is instantiated for any new modules to be loaded. The dispose is called
    -  // on a timer so that the bulkloader has a chance to release its
    -  // objects.
    -  goog.Timer.callOnce(bulkLoader.dispose, 5, bulkLoader);
    -};
    -
    -
    -/** @override */
    -goog.module.ModuleLoader.prototype.prefetchModule = function(
    -    id, moduleInfo) {
    -  // Do not prefetch in debug mode.
    -  if (this.getDebugMode()) {
    -    return;
    -  }
    -  var loadStatus = this.loadingModulesStatus_[[id]];
    -  if (loadStatus) {
    -    return;
    -  }
    -
    -  var moduleInfoMap = {};
    -  moduleInfoMap[id] = moduleInfo;
    -  this.loadingModulesStatus_[[id]] = new goog.module.ModuleLoader.LoadStatus();
    -  this.downloadModules_([id], moduleInfoMap);
    -};
    -
    -
    -/**
    - * Downloads a list of JavaScript modules.
    - *
    - * @param {Array<string>} ids The module ids in dependency order.
    - * @param {Object} moduleInfoMap A mapping from module id to ModuleInfo object.
    - * @private
    - */
    -goog.module.ModuleLoader.prototype.downloadModules_ = function(
    -    ids, moduleInfoMap) {
    -  var uris = [];
    -  for (var i = 0; i < ids.length; i++) {
    -    goog.array.extend(uris, moduleInfoMap[ids[i]].getUris());
    -  }
    -  goog.log.info(this.logger, 'downloadModules ids:' + ids + ' uris:' + uris);
    -
    -  if (this.getDebugMode() &&
    -      !this.usingSourceUrlInjection_()) {
    -    // In debug mode use <script> tags rather than XHRs to load the files.
    -    // This makes it possible to debug and inspect stack traces more easily.
    -    // It's also possible to use it to load JavaScript files that are hosted on
    -    // another domain.
    -    // The scripts need to load serially, so this is much slower than parallel
    -    // script loads with source url injection.
    -    goog.net.jsloader.loadMany(uris);
    -  } else {
    -    var loadStatus = this.loadingModulesStatus_[ids];
    -    loadStatus.requestUris = uris;
    -
    -    var bulkLoader = new goog.net.BulkLoader(uris);
    -
    -    var eventHandler = this.eventHandler_;
    -    eventHandler.listen(
    -        bulkLoader,
    -        goog.net.EventType.SUCCESS,
    -        goog.bind(this.handleSuccess_, this, bulkLoader, ids));
    -    eventHandler.listen(
    -        bulkLoader,
    -        goog.net.EventType.ERROR,
    -        goog.bind(this.handleError_, this, bulkLoader, ids));
    -    bulkLoader.load();
    -  }
    -};
    -
    -
    -/**
    - * Handles an error during a request for one or more modules.
    - * @param {goog.net.BulkLoader} bulkLoader The bulk loader.
    - * @param {Array<string>} moduleIds The ids of the modules requested.
    - * @param {number} status The response status.
    - * @private
    - */
    -goog.module.ModuleLoader.prototype.handleError_ = function(
    -    bulkLoader, moduleIds, status) {
    -  var loadStatus = this.loadingModulesStatus_[moduleIds];
    -  // The bulk loader doesn't cancel other requests when a request fails. We will
    -  // delete the loadStatus in the first failure, so it will be undefined in
    -  // subsequent errors.
    -  if (loadStatus) {
    -    delete this.loadingModulesStatus_[moduleIds];
    -    this.handleErrorHelper_(moduleIds, loadStatus.errorFn, status);
    -  }
    -
    -  // NOTE: A bulk loader instance is used for loading a set of module ids. Once
    -  // these modules have been loaded successfully or in error the bulk loader
    -  // should be disposed as it is not needed anymore. A new bulk loader is
    -  // instantiated for any new modules to be loaded. The dispose is called
    -  // on another thread so that the bulkloader has a chance to release its
    -  // objects.
    -  goog.Timer.callOnce(bulkLoader.dispose, 5, bulkLoader);
    -};
    -
    -
    -/**
    - * Handles an error during a request for one or more modules.
    - * @param {Array<string>} moduleIds The ids of the modules requested.
    - * @param {?function(?number)} errorFn The function to call on failure.
    - * @param {?number} status The response status.
    - * @private
    - */
    -goog.module.ModuleLoader.prototype.handleErrorHelper_ = function(
    -    moduleIds, errorFn, status) {
    -  this.dispatchEvent(
    -      new goog.module.ModuleLoader.Event(
    -          goog.module.ModuleLoader.EventType.REQUEST_ERROR, moduleIds));
    -
    -  goog.log.warning(this.logger, 'Request failed for module(s): ' + moduleIds);
    -
    -  if (errorFn) {
    -    errorFn(status);
    -  }
    -};
    -
    -
    -/** @override */
    -goog.module.ModuleLoader.prototype.disposeInternal = function() {
    -  goog.module.ModuleLoader.superClass_.disposeInternal.call(this);
    -
    -  this.eventHandler_.dispose();
    -  this.eventHandler_ = null;
    -};
    -
    -
    -/**
    - * @enum {string}
    - */
    -goog.module.ModuleLoader.EventType = {
    -  /** Called after the code for a module is evaluated. */
    -  EVALUATE_CODE: goog.events.getUniqueId('evaluateCode'),
    -
    -  /** Called when the BulkLoader finishes successfully. */
    -  REQUEST_SUCCESS: goog.events.getUniqueId('requestSuccess'),
    -
    -  /** Called when the BulkLoader fails, or code loading fails. */
    -  REQUEST_ERROR: goog.events.getUniqueId('requestError')
    -};
    -
    -
    -
    -/**
    - * @param {goog.module.ModuleLoader.EventType} type The type.
    - * @param {Array<string>} moduleIds The ids of the modules being evaluated.
    - * @constructor
    - * @extends {goog.events.Event}
    - * @final
    - */
    -goog.module.ModuleLoader.Event = function(type, moduleIds) {
    -  goog.module.ModuleLoader.Event.base(this, 'constructor', type);
    -
    -  /**
    -   * @type {Array<string>}
    -   */
    -  this.moduleIds = moduleIds;
    -};
    -goog.inherits(goog.module.ModuleLoader.Event, goog.events.Event);
    -
    -
    -
    -/**
    - * A class that keeps the state of the module during the loading process. It is
    - * used to save loading information between modules download and evaluation.
    - * @constructor
    - * @final
    - */
    -goog.module.ModuleLoader.LoadStatus = function() {
    -  /**
    -   * The request uris.
    -   * @type {Array<string>}
    -   */
    -  this.requestUris = null;
    -
    -  /**
    -   * The response texts.
    -   * @type {Array<string>}
    -   */
    -  this.responseTexts = null;
    -
    -  /**
    -   * Whether loadModules was called for the set of modules referred by this
    -   * status.
    -   * @type {boolean}
    -   */
    -  this.loadRequested = false;
    -
    -  /**
    -   * Success callback.
    -   * @type {?function()}
    -   */
    -  this.successFn = null;
    -
    -  /**
    -   * Error callback.
    -   * @type {?function(?number)}
    -   */
    -  this.errorFn = null;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/module/moduleloader_test.html b/src/database/third_party/closure-library/closure/goog/module/moduleloader_test.html
    deleted file mode 100644
    index 221505d4734..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/module/moduleloader_test.html
    +++ /dev/null
    @@ -1,30 +0,0 @@
    -<html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -
    -<!--
    -  A regression test for goog.module.ModuleLoader.
    -
    -  Unlike the unit tests for goog.module.ModuleManager, this uses
    -  asynchronous test cases and real XHRs.
    -
    -  Author: nicksantos@google.com (Nick Santos)
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>JsUnit tests for goog.module.ModuleLoader</title>
    -<script src='../base.js'></script>
    -<script>
    -goog.require('goog.module.ModuleLoaderTest');
    -</script>
    -</head>
    -<body>
    -<b>Note:</b>: If you are running this test off local disk on Chrome, it
    -will fail unless you start Chrome with
    -<code>--allow-file-access-from-files</code>.
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/module/moduleloader_test.js b/src/database/third_party/closure-library/closure/goog/module/moduleloader_test.js
    deleted file mode 100644
    index fe4866b58fe..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/module/moduleloader_test.js
    +++ /dev/null
    @@ -1,443 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Tests for goog.module.ModuleLoader.
    - * @author nicksantos@google.com (Nick Santos)
    - */
    -
    -goog.provide('goog.module.ModuleLoaderTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.functions');
    -goog.require('goog.module.ModuleLoader');
    -goog.require('goog.module.ModuleManager');
    -goog.require('goog.net.BulkLoader');
    -goog.require('goog.net.XmlHttp');
    -goog.require('goog.object');
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.events.EventObserver');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -goog.setTestOnly('goog.module.ModuleLoaderTest');
    -
    -
    -var modA1Loaded = false;
    -var modA2Loaded = false;
    -var modB1Loaded = false;
    -
    -var moduleLoader = null;
    -var moduleManager = null;
    -var stubs = new goog.testing.PropertyReplacer();
    -
    -var testCase = goog.testing.AsyncTestCase.createAndInstall(document.title);
    -testCase.stepTimeout = 5 * 1000; // 5 seconds
    -
    -var EventType = goog.module.ModuleLoader.EventType;
    -var observer;
    -
    -testCase.setUp = function() {
    -  modA1Loaded = false;
    -  modA2Loaded = false;
    -  modB1Loaded = false;
    -
    -  goog.provide = goog.nullFunction;
    -  moduleManager = goog.module.ModuleManager.getInstance();
    -  stubs.replace(moduleManager, 'getBackOff_', goog.functions.constant(0));
    -
    -  moduleLoader = new goog.module.ModuleLoader();
    -  observer = new goog.testing.events.EventObserver();
    -
    -  goog.events.listen(
    -      moduleLoader, goog.object.getValues(EventType), observer);
    -
    -  moduleManager.setLoader(moduleLoader);
    -  moduleManager.setAllModuleInfo({
    -    'modA': [],
    -    'modB': ['modA']
    -  });
    -  moduleManager.setModuleUris({
    -    'modA': ['testdata/modA_1.js', 'testdata/modA_2.js'],
    -    'modB': ['testdata/modB_1.js']
    -  });
    -
    -  assertNotLoaded('modA');
    -  assertNotLoaded('modB');
    -  assertFalse(modA1Loaded);
    -};
    -
    -testCase.tearDown = function() {
    -  stubs.reset();
    -
    -  // Ensure that the module manager was created.
    -  assertNotNull(goog.module.ModuleManager.getInstance());
    -  moduleManager = goog.module.ModuleManager.instance_ = null;
    -
    -  // tear down the module loaded flag.
    -  modA1Loaded = false;
    -
    -  // Remove all the fake scripts.
    -  var scripts = goog.array.clone(
    -      document.getElementsByTagName('SCRIPT'));
    -  for (var i = 0; i < scripts.length; i++) {
    -    if (scripts[i].src.indexOf('testdata') != -1) {
    -      goog.dom.removeNode(scripts[i]);
    -    }
    -  }
    -};
    -
    -function testLoadModuleA() {
    -  testCase.waitForAsync('wait for module A load');
    -  moduleManager.execOnLoad('modA', function() {
    -    testCase.continueTesting();
    -    assertLoaded('modA');
    -    assertNotLoaded('modB');
    -    assertTrue(modA1Loaded);
    -
    -    assertEquals('EVALUATE_CODE',
    -        0, observer.getEvents(EventType.EVALUATE_CODE).length);
    -    assertEquals('REQUEST_SUCCESS',
    -        1, observer.getEvents(EventType.REQUEST_SUCCESS).length);
    -    assertArrayEquals(
    -        ['modA'], observer.getEvents(EventType.REQUEST_SUCCESS)[0].moduleIds);
    -    assertEquals('REQUEST_ERROR',
    -        0, observer.getEvents(EventType.REQUEST_ERROR).length);
    -  });
    -}
    -
    -function testLoadModuleB() {
    -  testCase.waitForAsync('wait for module B load');
    -  moduleManager.execOnLoad('modB', function() {
    -    testCase.continueTesting();
    -    assertLoaded('modA');
    -    assertLoaded('modB');
    -    assertTrue(modA1Loaded);
    -  });
    -}
    -
    -function testLoadDebugModuleA() {
    -  testCase.waitForAsync('wait for module A load');
    -  moduleLoader.setDebugMode(true);
    -  moduleManager.execOnLoad('modA', function() {
    -    testCase.continueTesting();
    -    assertLoaded('modA');
    -    assertNotLoaded('modB');
    -    assertTrue(modA1Loaded);
    -  });
    -}
    -
    -function testLoadDebugModuleB() {
    -  testCase.waitForAsync('wait for module B load');
    -  moduleLoader.setDebugMode(true);
    -  moduleManager.execOnLoad('modB', function() {
    -    testCase.continueTesting();
    -    assertLoaded('modA');
    -    assertLoaded('modB');
    -    assertTrue(modA1Loaded);
    -  });
    -}
    -
    -function testLoadDebugModuleAThenB() {
    -  // Swap the script tags of module A, to introduce a race condition.
    -  // See the comments on this in ModuleLoader's debug loader.
    -  moduleManager.setModuleUris({
    -    'modA': ['testdata/modA_2.js', 'testdata/modA_1.js'],
    -    'modB': ['testdata/modB_1.js']
    -  });
    -  testCase.waitForAsync('wait for module B load');
    -  moduleLoader.setDebugMode(true);
    -  moduleManager.execOnLoad('modB', function() {
    -    testCase.continueTesting();
    -    assertLoaded('modA');
    -    assertLoaded('modB');
    -
    -    var scripts = goog.array.clone(
    -        document.getElementsByTagName('SCRIPT'));
    -    var seenLastScriptOfModuleA = false;
    -    for (var i = 0; i < scripts.length; i++) {
    -      var uri = scripts[i].src;
    -      if (uri.indexOf('modA_1.js') >= 0) {
    -        seenLastScriptOfModuleA = true;
    -      } else if (uri.indexOf('modB') >= 0) {
    -        assertTrue(seenLastScriptOfModuleA);
    -      }
    -    }
    -  });
    -}
    -
    -function testSourceInjection() {
    -  moduleLoader.setSourceUrlInjection(true);
    -  assertSourceInjection();
    -}
    -
    -function testSourceInjectionViaDebugMode() {
    -  moduleLoader.setDebugMode(true);
    -  assertSourceInjection();
    -}
    -
    -function assertSourceInjection() {
    -  testCase.waitForAsync('wait for module B load');
    -
    -  moduleManager.execOnLoad('modB', function() {
    -    testCase.continueTesting();
    -
    -    assertTrue(!!throwErrorInModuleB);
    -
    -    var ex = assertThrows(function() {
    -      throwErrorInModuleB();
    -    });
    -
    -    if (!ex.stack) {
    -      return;
    -    }
    -
    -    var stackTrace = ex.stack.toString();
    -    var expectedString = 'testdata/modB_1.js';
    -
    -    if (goog.module.ModuleLoader.supportsSourceUrlStackTraces()) {
    -      // Source URL should be added in eval or in jsloader.
    -      assertContains(expectedString, stackTrace);
    -    } else if (moduleLoader.getDebugMode()) {
    -      // Browsers used jsloader, thus URLs are present.
    -      assertContains(expectedString, stackTrace);
    -    } else {
    -      // Browser used eval, does not support source URL.
    -      assertNotContains(expectedString, stackTrace);
    -    }
    -  });
    -}
    -
    -function testModuleLoaderRecursesTooDeep(opt_numModules) {
    -  // There was a bug in the module loader where it would retry recursively
    -  // whenever there was a synchronous failure in the module load. When you
    -  // asked for modB, it would try to load its dependency modA. When modA
    -  // failed, it would move onto modB, and then start over, repeating until it
    -  // ran out of stack.
    -  var numModules = opt_numModules || 1;
    -  var uris = {};
    -  var deps = {};
    -  var mods = [];
    -  for (var num = 0; num < numModules; num++) {
    -    var modName = 'mod' + num;
    -    mods.unshift(modName);
    -    uris[modName] = [];
    -    deps[modName] = num ? ['mod' + (num - 1)] : [];
    -    for (var i = 0; i < 5; i++) {
    -      uris[modName].push(
    -          'http://www.google.com/crossdomain' + num + 'x' + i + '.js');
    -    }
    -  }
    -
    -  moduleManager.setAllModuleInfo(deps);
    -  moduleManager.setModuleUris(uris);
    -
    -  // Make all XHRs throw an error, so that we test the error-handling
    -  // functionality.
    -  var oldXmlHttp = goog.net.XmlHttp;
    -  stubs.set(goog.net, 'XmlHttp', function() {
    -    return {
    -      open: goog.functions.error('mock error'),
    -      abort: goog.nullFunction
    -    };
    -  });
    -  goog.object.extend(goog.net.XmlHttp, oldXmlHttp);
    -
    -  var errorCount = 0;
    -  var errorIds = [];
    -  var errorHandler = function(ignored, modId) {
    -    errorCount++;
    -    errorIds.push(modId);
    -  };
    -  moduleManager.registerCallback(
    -      goog.module.ModuleManager.CallbackType.ERROR,
    -      errorHandler);
    -
    -  moduleManager.execOnLoad(mods[0], function() {
    -    fail('modB should not load successfully');
    -  });
    -
    -  assertEquals(mods.length, errorCount);
    -
    -  goog.array.sort(mods);
    -  goog.array.sort(errorIds);
    -  assertArrayEquals(mods, errorIds);
    -
    -  assertArrayEquals([], moduleManager.requestedModuleIdsQueue_);
    -  assertArrayEquals([], moduleManager.userInitiatedLoadingModuleIds_);
    -}
    -
    -function testModuleLoaderRecursesTooDeep2modules() {
    -  testModuleLoaderRecursesTooDeep(2);
    -}
    -
    -function testModuleLoaderRecursesTooDeep3modules() {
    -  testModuleLoaderRecursesTooDeep(3);
    -}
    -
    -function testModuleLoaderRecursesTooDeep4modules() {
    -  testModuleLoaderRecursesTooDeep(3);
    -}
    -
    -function testErrback() {
    -  // Don't run this test on IE, because the way the test runner catches
    -  // errors on IE plays badly with the simulated errors in the test.
    -  if (goog.userAgent.IE) return;
    -
    -  // Modules will throw an exception if this boolean is set to true.
    -  modA1Loaded = true;
    -
    -  var errorHandler = function() {
    -    testCase.continueTesting();
    -    assertNotLoaded('modA');
    -  };
    -  moduleManager.registerCallback(
    -      goog.module.ModuleManager.CallbackType.ERROR,
    -      errorHandler);
    -
    -  moduleManager.execOnLoad('modA', function() {
    -    fail('modA should not load successfully');
    -  });
    -
    -  testCase.waitForAsync('wait for the error callback');
    -}
    -
    -function testPrefetchThenLoadModuleA() {
    -  moduleManager.prefetchModule('modA');
    -  stubs.set(goog.net.BulkLoader.prototype, 'load', function() {
    -    fail('modA should not be reloaded');
    -  });
    -
    -  testCase.waitForAsync('wait for module A load');
    -  moduleManager.execOnLoad('modA', function() {
    -    testCase.continueTesting();
    -    assertLoaded('modA');
    -    assertEquals('REQUEST_SUCCESS',
    -        1, observer.getEvents(EventType.REQUEST_SUCCESS).length);
    -    assertArrayEquals(
    -        ['modA'], observer.getEvents(EventType.REQUEST_SUCCESS)[0].moduleIds);
    -    assertEquals('REQUEST_ERROR',
    -        0, observer.getEvents(EventType.REQUEST_ERROR).length);
    -  });
    -}
    -
    -function testPrefetchThenLoadModuleB() {
    -  moduleManager.prefetchModule('modB');
    -  stubs.set(goog.net.BulkLoader.prototype, 'load', function() {
    -    fail('modA and modB should not be reloaded');
    -  });
    -
    -  testCase.waitForAsync('wait for module B load');
    -  moduleManager.execOnLoad('modB', function() {
    -    testCase.continueTesting();
    -    assertLoaded('modA');
    -    assertLoaded('modB');
    -    assertEquals('REQUEST_SUCCESS',
    -        2, observer.getEvents(EventType.REQUEST_SUCCESS).length);
    -    assertArrayEquals(
    -        ['modA'], observer.getEvents(EventType.REQUEST_SUCCESS)[0].moduleIds);
    -    assertArrayEquals(
    -        ['modB'], observer.getEvents(EventType.REQUEST_SUCCESS)[1].moduleIds);
    -    assertEquals('REQUEST_ERROR',
    -        0, observer.getEvents(EventType.REQUEST_ERROR).length);
    -  });
    -}
    -
    -function testPrefetchModuleAThenLoadModuleB() {
    -  moduleManager.prefetchModule('modA');
    -
    -  testCase.waitForAsync('wait for module A load');
    -  moduleManager.execOnLoad('modB', function() {
    -    testCase.continueTesting();
    -    assertLoaded('modA');
    -    assertLoaded('modB');
    -    assertEquals('REQUEST_SUCCESS',
    -        2, observer.getEvents(EventType.REQUEST_SUCCESS).length);
    -    assertArrayEquals(
    -        ['modA'], observer.getEvents(EventType.REQUEST_SUCCESS)[0].moduleIds);
    -    assertArrayEquals(
    -        ['modB'], observer.getEvents(EventType.REQUEST_SUCCESS)[1].moduleIds);
    -    assertEquals('REQUEST_ERROR',
    -        0, observer.getEvents(EventType.REQUEST_ERROR).length);
    -  });
    -}
    -
    -function testLoadModuleBThenPrefetchModuleA() {
    -  testCase.waitForAsync('wait for module A load');
    -  moduleManager.execOnLoad('modB', function() {
    -    testCase.continueTesting();
    -    assertLoaded('modA');
    -    assertLoaded('modB');
    -    assertEquals('REQUEST_SUCCESS',
    -        2, observer.getEvents(EventType.REQUEST_SUCCESS).length);
    -    assertArrayEquals(
    -        ['modA'], observer.getEvents(EventType.REQUEST_SUCCESS)[0].moduleIds);
    -    assertArrayEquals(
    -        ['modB'], observer.getEvents(EventType.REQUEST_SUCCESS)[1].moduleIds);
    -    assertEquals('REQUEST_ERROR',
    -        0, observer.getEvents(EventType.REQUEST_ERROR).length);
    -    assertThrows('Module load already requested: modB',
    -        function() {
    -          moduleManager.prefetchModule('modA');
    -        });
    -  });
    -}
    -
    -function testPrefetchModuleWithBatchModeEnabled() {
    -  moduleManager.setBatchModeEnabled(true);
    -  assertThrows('Modules prefetching is not supported in batch mode',
    -      function() {
    -        moduleManager.prefetchModule('modA');
    -      });
    -}
    -
    -function testLoadErrorCallbackExecutedWhenPrefetchFails() {
    -  // Make all XHRs throw an error, so that we test the error-handling
    -  // functionality.
    -  var oldXmlHttp = goog.net.XmlHttp;
    -  stubs.set(goog.net, 'XmlHttp', function() {
    -    return {
    -      open: goog.functions.error('mock error'),
    -      abort: goog.nullFunction
    -    };
    -  });
    -  goog.object.extend(goog.net.XmlHttp, oldXmlHttp);
    -
    -  var errorCount = 0;
    -  var errorHandler = function() {
    -    errorCount++;
    -  };
    -  moduleManager.registerCallback(
    -      goog.module.ModuleManager.CallbackType.ERROR,
    -      errorHandler);
    -
    -  moduleLoader.prefetchModule('modA', moduleManager.moduleInfoMap_['modA']);
    -  moduleLoader.loadModules(['modA'], moduleManager.moduleInfoMap_,
    -      function() {
    -        fail('modA should not load successfully');
    -      }, errorHandler);
    -
    -  assertEquals(1, errorCount);
    -}
    -
    -function assertLoaded(id) {
    -  assertTrue(moduleManager.getModuleInfo(id).isLoaded());
    -}
    -
    -function assertNotLoaded(id) {
    -  assertFalse(moduleManager.getModuleInfo(id).isLoaded());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/module/modulemanager.js b/src/database/third_party/closure-library/closure/goog/module/modulemanager.js
    deleted file mode 100644
    index 58723b1b39f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/module/modulemanager.js
    +++ /dev/null
    @@ -1,1358 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A singleton object for managing Javascript code modules.
    - *
    - */
    -
    -goog.provide('goog.module.ModuleManager');
    -goog.provide('goog.module.ModuleManager.CallbackType');
    -goog.provide('goog.module.ModuleManager.FailureType');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.async.Deferred');
    -goog.require('goog.debug.Trace');
    -/** @suppress {extraRequire} */
    -goog.require('goog.dispose');
    -goog.require('goog.log');
    -/** @suppress {extraRequire} */
    -goog.require('goog.module');
    -goog.require('goog.module.ModuleInfo');
    -goog.require('goog.module.ModuleLoadCallback');
    -goog.require('goog.object');
    -
    -
    -
    -/**
    - * The ModuleManager keeps track of all modules in the environment.
    - * Since modules may not have their code loaded, we must keep track of them.
    - * @constructor
    - * @extends {goog.Disposable}
    - * @struct
    - * @suppress {checkStructDictInheritance}
    - */
    -goog.module.ModuleManager = function() {
    -  goog.module.ModuleManager.base(this, 'constructor');
    -
    -  /**
    -   * A mapping from module id to ModuleInfo object.
    -   * @private {Object<string, !goog.module.ModuleInfo>}
    -   */
    -  this.moduleInfoMap_ = {};
    -
    -  // TODO (malteubl): Switch this to a reentrant design.
    -  /**
    -   * The ids of the currently loading modules. If batch mode is disabled, then
    -   * this array will never contain more than one element at a time.
    -   * @type {Array<string>}
    -   * @private
    -   */
    -  this.loadingModuleIds_ = [];
    -
    -  /**
    -   * The requested ids of the currently loading modules. This does not include
    -   * module dependencies that may also be loading.
    -   * @type {Array<string>}
    -   * @private
    -   */
    -  this.requestedLoadingModuleIds_ = [];
    -
    -  // TODO(user): Make these and other arrays that are used as sets be
    -  // actual sets.
    -  /**
    -   * All module ids that have ever been requested. In concurrent loading these
    -   * are the ones to subtract from future requests.
    -   * @type {!Array<string>}
    -   * @private
    -   */
    -  this.requestedModuleIds_ = [];
    -
    -  /**
    -   * A queue of the ids of requested but not-yet-loaded modules. The zero
    -   * position is the front of the queue. This is a 2-D array to group modules
    -   * together with other modules that should be batch loaded with them, if
    -   * batch loading is enabled.
    -   * @type {Array<Array<string>>}
    -   * @private
    -   */
    -  this.requestedModuleIdsQueue_ = [];
    -
    -  /**
    -   * The ids of the currently loading modules which have been initiated by user
    -   * actions.
    -   * @type {Array<string>}
    -   * @private
    -   */
    -  this.userInitiatedLoadingModuleIds_ = [];
    -
    -  /**
    -   * A map of callback types to the functions to call for the specified
    -   * callback type.
    -   * @type {Object<goog.module.ModuleManager.CallbackType, Array<Function>>}
    -   * @private
    -   */
    -  this.callbackMap_ = {};
    -
    -  /**
    -   * Module info for the base module (the one that contains the module
    -   * manager code), which we set as the loading module so one can
    -   * register initialization callbacks in the base module.
    -   *
    -   * The base module is considered loaded when #setAllModuleInfo is called or
    -   * #setModuleContext is called, whichever comes first.
    -   *
    -   * @type {goog.module.ModuleInfo}
    -   * @private
    -   */
    -  this.baseModuleInfo_ = new goog.module.ModuleInfo([], '');
    -
    -  /**
    -   * The module that is currently loading, or null if not loading anything.
    -   * @type {goog.module.ModuleInfo}
    -   * @private
    -   */
    -  this.currentlyLoadingModule_ = this.baseModuleInfo_;
    -
    -  /**
    -   * The id of the last requested initial module. When it loaded
    -   * the deferred in {@code this.initialModulesLoaded_} resolves.
    -   * @private {?string}
    -   */
    -  this.lastInitialModuleId_ = null;
    -
    -  /**
    -   * Deferred for when all initial modules have loaded. We currently block
    -   * sending additional module requests until this deferred resolves. In a
    -   * future optimization it may be possible to use the initial modules as
    -   * seeds for the module loader "requested module ids" and start making new
    -   * requests even sooner.
    -   * @private {!goog.async.Deferred}
    -   */
    -  this.initialModulesLoaded_ = new goog.async.Deferred();
    -
    -  /**
    -   * A logger.
    -   * @private {goog.log.Logger}
    -   */
    -  this.logger_ = goog.log.getLogger('goog.module.ModuleManager');
    -
    -  /**
    -   * Whether the batch mode (i.e. the loading of multiple modules with just one
    -   * request) has been enabled.
    -   * @private {boolean}
    -   */
    -  this.batchModeEnabled_ = false;
    -
    -  /**
    -   * Whether the module requests may be sent out of order.
    -   * @private {boolean}
    -   */
    -  this.concurrentLoadingEnabled_ = false;
    -
    -  /**
    -   * A loader for the modules that implements loadModules(ids, moduleInfoMap,
    -   * opt_successFn, opt_errorFn, opt_timeoutFn, opt_forceReload) method.
    -   * @private {goog.module.AbstractModuleLoader}
    -   */
    -  this.loader_ = null;
    -
    -  // TODO(user): Remove tracer.
    -  /**
    -   * Tracer that measures how long it takes to load a module.
    -   * @private {?number}
    -   */
    -  this.loadTracer_ = null;
    -
    -  /**
    -   * The number of consecutive failures that have happened upon module load
    -   * requests.
    -   * @private {number}
    -   */
    -  this.consecutiveFailures_ = 0;
    -
    -  /**
    -   * Determines if the module manager was just active before the processing of
    -   * the last data.
    -   * @private {boolean}
    -   */
    -  this.lastActive_ = false;
    -
    -  /**
    -   * Determines if the module manager was just user active before the processing
    -   * of the last data. The module manager is user active if any of the
    -   * user-initiated modules are loading or queued up to load.
    -   * @private {boolean}
    -   */
    -  this.userLastActive_ = false;
    -
    -  /**
    -   * The module context needed for module initialization.
    -   * @private {Object}
    -   */
    -  this.moduleContext_ = null;
    -};
    -goog.inherits(goog.module.ModuleManager, goog.Disposable);
    -goog.addSingletonGetter(goog.module.ModuleManager);
    -
    -
    -/**
    -* The type of callbacks that can be registered with the module manager,.
    -* @enum {string}
    -*/
    -goog.module.ModuleManager.CallbackType = {
    -  /**
    -   * Fired when an error has occurred.
    -   */
    -  ERROR: 'error',
    -
    -  /**
    -   * Fired when it becomes idle and has no more module loads to process.
    -   */
    -  IDLE: 'idle',
    -
    -  /**
    -   * Fired when it becomes active and has module loads to process.
    -   */
    -  ACTIVE: 'active',
    -
    -  /**
    -   * Fired when it becomes idle and has no more user-initiated module loads to
    -   * process.
    -   */
    -  USER_IDLE: 'userIdle',
    -
    -  /**
    -   * Fired when it becomes active and has user-initiated module loads to
    -   * process.
    -   */
    -  USER_ACTIVE: 'userActive'
    -};
    -
    -
    -/**
    - * A non-HTTP status code indicating a corruption in loaded module.
    - * This should be used by a ModuleLoader as a replacement for the HTTP code
    - * given to the error handler function to indicated that the module was
    - * corrupted.
    - * This will set the forceReload flag on the loadModules method when retrying
    - * module loading.
    - * @type {number}
    - */
    -goog.module.ModuleManager.CORRUPT_RESPONSE_STATUS_CODE = 8001;
    -
    -
    -/**
    - * Sets the batch mode as enabled or disabled for the module manager.
    - * @param {boolean} enabled Whether the batch mode is to be enabled or not.
    - */
    -goog.module.ModuleManager.prototype.setBatchModeEnabled = function(
    -    enabled) {
    -  this.batchModeEnabled_ = enabled;
    -};
    -
    -
    -/**
    - * Sets the concurrent loading mode as enabled or disabled for the module
    - * manager. Requires a moduleloader implementation that supports concurrent
    - * loads. The default {@see goog.module.ModuleLoader} does not.
    - * @param {boolean} enabled
    - */
    -goog.module.ModuleManager.prototype.setConcurrentLoadingEnabled = function(
    -    enabled) {
    -  this.concurrentLoadingEnabled_ = enabled;
    -};
    -
    -
    -/**
    - * Sets the module info for all modules. Should only be called once.
    - *
    - * @param {Object<Array<string>>} infoMap An object that contains a mapping
    - *    from module id (String) to list of required module ids (Array).
    - */
    -goog.module.ModuleManager.prototype.setAllModuleInfo = function(infoMap) {
    -  for (var id in infoMap) {
    -    this.moduleInfoMap_[id] = new goog.module.ModuleInfo(infoMap[id], id);
    -  }
    -  if (!this.initialModulesLoaded_.hasFired()) {
    -    this.initialModulesLoaded_.callback();
    -  }
    -  this.maybeFinishBaseLoad_();
    -};
    -
    -
    -/**
    - * Sets the module info for all modules. Should only be called once. Also
    - * marks modules that are currently being loaded.
    - *
    - * @param {string=} opt_info A string representation of the module dependency
    - *      graph, in the form: module1:dep1,dep2/module2:dep1,dep2 etc.
    - *     Where depX is the base-36 encoded position of the dep in the module list.
    - * @param {Array<string>=} opt_loadingModuleIds A list of moduleIds that
    - *     are currently being loaded.
    - */
    -goog.module.ModuleManager.prototype.setAllModuleInfoString = function(
    -    opt_info, opt_loadingModuleIds) {
    -  if (!goog.isString(opt_info)) {
    -    // The call to this method is generated in two steps, the argument is added
    -    // after some of the compilation passes.  This means that the initial code
    -    // doesn't have any arguments and causes compiler errors.  We make it
    -    // optional to satisfy this constraint.
    -    return;
    -  }
    -
    -  var modules = opt_info.split('/');
    -  var moduleIds = [];
    -
    -  // Split the string into the infoMap of id->deps
    -  for (var i = 0; i < modules.length; i++) {
    -    var parts = modules[i].split(':');
    -    var id = parts[0];
    -    var deps;
    -    if (parts[1]) {
    -      deps = parts[1].split(',');
    -      for (var j = 0; j < deps.length; j++) {
    -        var index = parseInt(deps[j], 36);
    -        goog.asserts.assert(
    -            moduleIds[index], 'No module @ %s, dep of %s @ %s', index, id, i);
    -        deps[j] = moduleIds[index];
    -      }
    -    } else {
    -      deps = [];
    -    }
    -    moduleIds.push(id);
    -    this.moduleInfoMap_[id] = new goog.module.ModuleInfo(deps, id);
    -  }
    -  if (opt_loadingModuleIds && opt_loadingModuleIds.length) {
    -    goog.array.extend(this.loadingModuleIds_, opt_loadingModuleIds);
    -    // The last module in the list of initial modules. When it has loaded all
    -    // initial modules have loaded.
    -    this.lastInitialModuleId_ = /** @type {?string}  */ (
    -        goog.array.peek(opt_loadingModuleIds));
    -  } else {
    -    if (!this.initialModulesLoaded_.hasFired()) {
    -      this.initialModulesLoaded_.callback();
    -    }
    -  }
    -  this.maybeFinishBaseLoad_();
    -};
    -
    -
    -/**
    - * Gets a module info object by id.
    - * @param {string} id A module identifier.
    - * @return {!goog.module.ModuleInfo} The module info.
    - */
    -goog.module.ModuleManager.prototype.getModuleInfo = function(id) {
    -  return this.moduleInfoMap_[id];
    -};
    -
    -
    -/**
    - * Sets the module uris.
    - *
    - * @param {Object} moduleUriMap The map of id/uris pairs for each module.
    - */
    -goog.module.ModuleManager.prototype.setModuleUris = function(moduleUriMap) {
    -  for (var id in moduleUriMap) {
    -    this.moduleInfoMap_[id].setUris(moduleUriMap[id]);
    -  }
    -};
    -
    -
    -/**
    - * Gets the application-specific module loader.
    - * @return {goog.module.AbstractModuleLoader} An object that has a
    - *     loadModules(ids, moduleInfoMap, opt_successFn, opt_errFn,
    - *         opt_timeoutFn, opt_forceReload) method.
    - */
    -goog.module.ModuleManager.prototype.getLoader = function() {
    -  return this.loader_;
    -};
    -
    -
    -/**
    - * Sets the application-specific module loader.
    - * @param {goog.module.AbstractModuleLoader} loader An object that has a
    - *     loadModules(ids, moduleInfoMap, opt_successFn, opt_errFn,
    - *         opt_timeoutFn, opt_forceReload) method.
    - */
    -goog.module.ModuleManager.prototype.setLoader = function(loader) {
    -  this.loader_ = loader;
    -};
    -
    -
    -/**
    - * Gets the module context to use to initialize the module.
    - * @return {Object} The context.
    - */
    -goog.module.ModuleManager.prototype.getModuleContext = function() {
    -  return this.moduleContext_;
    -};
    -
    -
    -/**
    - * Sets the module context to use to initialize the module.
    - * @param {Object} context The context.
    - */
    -goog.module.ModuleManager.prototype.setModuleContext = function(context) {
    -  this.moduleContext_ = context;
    -  this.maybeFinishBaseLoad_();
    -};
    -
    -
    -/**
    - * Determines if the ModuleManager is active
    - * @return {boolean} TRUE iff the ModuleManager is active (i.e., not idle).
    - */
    -goog.module.ModuleManager.prototype.isActive = function() {
    -  return this.loadingModuleIds_.length > 0;
    -};
    -
    -
    -/**
    - * Determines if the ModuleManager is user active
    - * @return {boolean} TRUE iff the ModuleManager is user active (i.e., not idle).
    - */
    -goog.module.ModuleManager.prototype.isUserActive = function() {
    -  return this.userInitiatedLoadingModuleIds_.length > 0;
    -};
    -
    -
    -/**
    - * Dispatches an ACTIVE or IDLE event if necessary.
    - * @private
    - */
    -goog.module.ModuleManager.prototype.dispatchActiveIdleChangeIfNeeded_ =
    -    function() {
    -  var lastActive = this.lastActive_;
    -  var active = this.isActive();
    -  if (active != lastActive) {
    -    this.executeCallbacks_(active ?
    -        goog.module.ModuleManager.CallbackType.ACTIVE :
    -        goog.module.ModuleManager.CallbackType.IDLE);
    -
    -    // Flip the last active value.
    -    this.lastActive_ = active;
    -  }
    -
    -  // Check if the module manager is user active i.e., there are user initiated
    -  // modules being loaded or queued up to be loaded.
    -  var userLastActive = this.userLastActive_;
    -  var userActive = this.isUserActive();
    -  if (userActive != userLastActive) {
    -    this.executeCallbacks_(userActive ?
    -        goog.module.ModuleManager.CallbackType.USER_ACTIVE :
    -        goog.module.ModuleManager.CallbackType.USER_IDLE);
    -
    -    // Flip the last user active value.
    -    this.userLastActive_ = userActive;
    -  }
    -};
    -
    -
    -/**
    - * Preloads a module after a short delay.
    - *
    - * @param {string} id The id of the module to preload.
    - * @param {number=} opt_timeout The number of ms to wait before adding the
    - *     module id to the loading queue (defaults to 0 ms). Note that the module
    - *     will be loaded asynchronously regardless of the value of this parameter.
    - * @return {!goog.async.Deferred} A deferred object.
    - */
    -goog.module.ModuleManager.prototype.preloadModule = function(
    -    id, opt_timeout) {
    -  var d = new goog.async.Deferred();
    -  window.setTimeout(
    -      goog.bind(this.addLoadModule_, this, id, d),
    -      opt_timeout || 0);
    -  return d;
    -};
    -
    -
    -/**
    - * Prefetches a JavaScript module and its dependencies, which means that the
    - * module will be downloaded, but not evaluated. To complete the module load,
    - * the caller should also call load or execOnLoad after prefetching the module.
    - *
    - * @param {string} id The id of the module to prefetch.
    - */
    -goog.module.ModuleManager.prototype.prefetchModule = function(id) {
    -  var moduleInfo = this.getModuleInfo(id);
    -  if (moduleInfo.isLoaded() || this.isModuleLoading(id)) {
    -    throw Error('Module load already requested: ' + id);
    -  } else if (this.batchModeEnabled_) {
    -    throw Error('Modules prefetching is not supported in batch mode');
    -  } else {
    -    var idWithDeps = this.getNotYetLoadedTransitiveDepIds_(id);
    -    for (var i = 0; i < idWithDeps.length; i++) {
    -      this.loader_.prefetchModule(idWithDeps[i],
    -          this.moduleInfoMap_[idWithDeps[i]]);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Loads a single module for use with a given deferred.
    - *
    - * @param {string} id The id of the module to load.
    - * @param {goog.async.Deferred} d A deferred object.
    - * @private
    - */
    -goog.module.ModuleManager.prototype.addLoadModule_ = function(id, d) {
    -  var moduleInfo = this.getModuleInfo(id);
    -  if (moduleInfo.isLoaded()) {
    -    d.callback(this.moduleContext_);
    -    return;
    -  }
    -
    -  this.registerModuleLoadCallbacks_(id, moduleInfo, false, d);
    -  if (!this.isModuleLoading(id)) {
    -    this.loadModulesOrEnqueue_([id]);
    -  }
    -};
    -
    -
    -/**
    - * Loads a list of modules or, if some other module is currently being loaded,
    - * appends the ids to the queue of requested module ids. Registers callbacks a
    - * module that is currently loading and returns a fired deferred for a module
    - * that is already loaded.
    - *
    - * @param {Array<string>} ids The id of the module to load.
    - * @param {boolean=} opt_userInitiated If the load is a result of a user action.
    - * @return {!Object<string, !goog.async.Deferred>} A mapping from id (String)
    - *     to deferred objects that will callback or errback when the load for that
    - *     id is finished.
    - * @private
    - */
    -goog.module.ModuleManager.prototype.loadModulesOrEnqueueIfNotLoadedOrLoading_ =
    -    function(ids, opt_userInitiated) {
    -  var uniqueIds = [];
    -  goog.array.removeDuplicates(ids, uniqueIds);
    -  var idsToLoad = [];
    -  var deferredMap = {};
    -  for (var i = 0; i < uniqueIds.length; i++) {
    -    var id = uniqueIds[i];
    -    var moduleInfo = this.getModuleInfo(id);
    -    if (!moduleInfo) {
    -      throw new Error('Unknown module: ' + id);
    -    }
    -    var d = new goog.async.Deferred();
    -    deferredMap[id] = d;
    -    if (moduleInfo.isLoaded()) {
    -      d.callback(this.moduleContext_);
    -    } else {
    -      this.registerModuleLoadCallbacks_(id, moduleInfo, !!opt_userInitiated, d);
    -      if (!this.isModuleLoading(id)) {
    -        idsToLoad.push(id);
    -      }
    -    }
    -  }
    -
    -  // If there are ids to load, load them, otherwise, they are all loading or
    -  // loaded.
    -  if (idsToLoad.length > 0) {
    -    this.loadModulesOrEnqueue_(idsToLoad);
    -  }
    -  return deferredMap;
    -};
    -
    -
    -/**
    - * Registers the callbacks and handles logic if it is a user initiated module
    - * load.
    - *
    - * @param {string} id The id of the module to possibly load.
    - * @param {!goog.module.ModuleInfo} moduleInfo The module identifier for the
    - *     given id.
    - * @param {boolean} userInitiated If the load was user initiated.
    - * @param {goog.async.Deferred} d A deferred object.
    - * @private
    - */
    -goog.module.ModuleManager.prototype.registerModuleLoadCallbacks_ =
    -    function(id, moduleInfo, userInitiated, d) {
    -  moduleInfo.registerCallback(d.callback, d);
    -  moduleInfo.registerErrback(function(err) { d.errback(Error(err)); });
    -  // If it's already loading, we don't have to do anything besides handle
    -  // if it was user initiated
    -  if (this.isModuleLoading(id)) {
    -    if (userInitiated) {
    -      goog.log.info(this.logger_,
    -          'User initiated module already loading: ' + id);
    -      this.addUserInitiatedLoadingModule_(id);
    -      this.dispatchActiveIdleChangeIfNeeded_();
    -    }
    -  } else {
    -    if (userInitiated) {
    -      goog.log.info(this.logger_, 'User initiated module load: ' + id);
    -      this.addUserInitiatedLoadingModule_(id);
    -    } else {
    -      goog.log.info(this.logger_, 'Initiating module load: ' + id);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Initiates loading of a list of modules or, if a module is currently being
    - * loaded, appends the modules to the queue of requested module ids.
    - *
    - * The caller should verify that the requested modules are not already loaded or
    - * loading. {@link #loadModulesOrEnqueueIfNotLoadedOrLoading_} is a more lenient
    - * alternative to this method.
    - *
    - * @param {Array<string>} ids The ids of the modules to load.
    - * @private
    - */
    -goog.module.ModuleManager.prototype.loadModulesOrEnqueue_ = function(ids) {
    -  // With concurrent loading we always just send off the request.
    -  if (this.concurrentLoadingEnabled_) {
    -    // For now we wait for initial modules to have downloaded as this puts the
    -    // loader in a good state for calculating the needed deps of additional
    -    // loads.
    -    // TODO(user): Make this wait unnecessary.
    -    this.initialModulesLoaded_.addCallback(
    -        goog.bind(this.loadModules_, this, ids));
    -  } else {
    -    if (goog.array.isEmpty(this.loadingModuleIds_)) {
    -      this.loadModules_(ids);
    -    } else {
    -      this.requestedModuleIdsQueue_.push(ids);
    -      this.dispatchActiveIdleChangeIfNeeded_();
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Gets the amount of delay to wait before sending a request for more modules.
    - * If a certain module request fails, we backoff a little bit and try again.
    - * @return {number} Delay, in ms.
    - * @private
    - */
    -goog.module.ModuleManager.prototype.getBackOff_ = function() {
    -  // 5 seconds after one error, 20 seconds after 2.
    -  return Math.pow(this.consecutiveFailures_, 2) * 5000;
    -};
    -
    -
    -/**
    - * Loads a list of modules and any of their not-yet-loaded prerequisites.
    - * If batch mode is enabled, the prerequisites will be loaded together with the
    - * requested modules and all requested modules will be loaded at the same time.
    - *
    - * The caller should verify that the requested modules are not already loaded
    - * and that no modules are currently loading before calling this method.
    - *
    - * @param {Array<string>} ids The ids of the modules to load.
    - * @param {boolean=} opt_isRetry If the load is a retry of a previous load
    - *     attempt.
    - * @param {boolean=} opt_forceReload Whether to bypass cache while loading the
    - *     module.
    - * @private
    - */
    -goog.module.ModuleManager.prototype.loadModules_ = function(
    -    ids, opt_isRetry, opt_forceReload) {
    -  if (!opt_isRetry) {
    -    this.consecutiveFailures_ = 0;
    -  }
    -
    -  // Not all modules may be loaded immediately if batch mode is not enabled.
    -  var idsToLoadImmediately = this.processModulesForLoad_(ids);
    -
    -  goog.log.info(this.logger_, 'Loading module(s): ' + idsToLoadImmediately);
    -  this.loadingModuleIds_ = idsToLoadImmediately;
    -
    -  if (this.batchModeEnabled_) {
    -    this.requestedLoadingModuleIds_ = ids;
    -  } else {
    -    // If batch mode is disabled, we treat each dependency load as a separate
    -    // load.
    -    this.requestedLoadingModuleIds_ = goog.array.clone(idsToLoadImmediately);
    -  }
    -
    -  // Dispatch an active/idle change if needed.
    -  this.dispatchActiveIdleChangeIfNeeded_();
    -
    -  if (goog.array.isEmpty(idsToLoadImmediately)) {
    -    // All requested modules and deps have been either loaded already or have
    -    // already been requested.
    -    return;
    -  }
    -
    -  this.requestedModuleIds_.push.apply(this.requestedModuleIds_,
    -      idsToLoadImmediately);
    -
    -  var loadFn = goog.bind(this.loader_.loadModules, this.loader_,
    -      goog.array.clone(idsToLoadImmediately),
    -      this.moduleInfoMap_,
    -      null,
    -      goog.bind(this.handleLoadError_, this, this.requestedLoadingModuleIds_,
    -          idsToLoadImmediately),
    -      goog.bind(this.handleLoadTimeout_, this),
    -      !!opt_forceReload);
    -
    -  var delay = this.getBackOff_();
    -  if (delay) {
    -    window.setTimeout(loadFn, delay);
    -  } else {
    -    loadFn();
    -  }
    -};
    -
    -
    -/**
    - * Processes a list of module ids for loading. Checks if any of the modules are
    - * already loaded and then gets transitive deps. Queues any necessary modules
    - * if batch mode is not enabled. Returns the list of ids that should be loaded.
    - *
    - * @param {Array<string>} ids The ids that need to be loaded.
    - * @return {!Array<string>} The ids to load, including dependencies.
    - * @throws {Error} If the module is already loaded.
    - * @private
    - */
    -goog.module.ModuleManager.prototype.processModulesForLoad_ = function(ids) {
    -  for (var i = 0; i < ids.length; i++) {
    -    var moduleInfo = this.moduleInfoMap_[ids[i]];
    -    if (moduleInfo.isLoaded()) {
    -      throw Error('Module already loaded: ' + ids[i]);
    -    }
    -  }
    -
    -  // Build a list of the ids of this module and any of its not-yet-loaded
    -  // prerequisite modules in dependency order.
    -  var idsWithDeps = [];
    -  for (var i = 0; i < ids.length; i++) {
    -    idsWithDeps = idsWithDeps.concat(
    -        this.getNotYetLoadedTransitiveDepIds_(ids[i]));
    -  }
    -  goog.array.removeDuplicates(idsWithDeps);
    -
    -  if (!this.batchModeEnabled_ && idsWithDeps.length > 1) {
    -    var idToLoad = idsWithDeps.shift();
    -    goog.log.info(this.logger_,
    -        'Must load ' + idToLoad + ' module before ' + ids);
    -
    -    // Insert the requested module id and any other not-yet-loaded prereqs
    -    // that it has at the front of the queue.
    -    var queuedModules = goog.array.map(idsWithDeps, function(id) {
    -      return [id];
    -    });
    -    this.requestedModuleIdsQueue_ = queuedModules.concat(
    -        this.requestedModuleIdsQueue_);
    -    return [idToLoad];
    -  } else {
    -    return idsWithDeps;
    -  }
    -};
    -
    -
    -/**
    - * Builds a list of the ids of the not-yet-loaded modules that a particular
    - * module transitively depends on, including itself.
    - *
    - * @param {string} id The id of a not-yet-loaded module.
    - * @return {!Array<string>} An array of module ids in dependency order that's
    - *     guaranteed to end with the provided module id.
    - * @private
    - */
    -goog.module.ModuleManager.prototype.getNotYetLoadedTransitiveDepIds_ =
    -    function(id) {
    -  // NOTE(user): We want the earliest occurrance of a module, not the first
    -  // dependency we find. Therefore we strip duplicates at the end rather than
    -  // during.  See the tests for concrete examples.
    -  var ids = [];
    -  if (!goog.array.contains(this.requestedModuleIds_, id)) {
    -    ids.push(id);
    -  }
    -  var depIds = goog.array.clone(this.getModuleInfo(id).getDependencies());
    -  while (depIds.length) {
    -    var depId = depIds.pop();
    -    if (!this.getModuleInfo(depId).isLoaded() &&
    -        !goog.array.contains(this.requestedModuleIds_, depId)) {
    -      ids.unshift(depId);
    -      // We need to process direct dependencies first.
    -      Array.prototype.unshift.apply(depIds,
    -          this.getModuleInfo(depId).getDependencies());
    -    }
    -  }
    -  goog.array.removeDuplicates(ids);
    -  return ids;
    -};
    -
    -
    -/**
    - * If we are still loading the base module, consider the load complete.
    - * @private
    - */
    -goog.module.ModuleManager.prototype.maybeFinishBaseLoad_ = function() {
    -  if (this.currentlyLoadingModule_ == this.baseModuleInfo_) {
    -    this.currentlyLoadingModule_ = null;
    -    var error = this.baseModuleInfo_.onLoad(
    -        goog.bind(this.getModuleContext, this));
    -    if (error) {
    -      this.dispatchModuleLoadFailed_(
    -          goog.module.ModuleManager.FailureType.INIT_ERROR);
    -    }
    -
    -    this.dispatchActiveIdleChangeIfNeeded_();
    -  }
    -};
    -
    -
    -/**
    - * Records that a module was loaded. Also initiates loading the next module if
    - * any module requests are queued. This method is called by code that is
    - * generated and appended to each dynamic module's code at compilation time.
    - *
    - * @param {string} id A module id.
    - */
    -goog.module.ModuleManager.prototype.setLoaded = function(id) {
    -  if (this.isDisposed()) {
    -    goog.log.warning(this.logger_,
    -        'Module loaded after module manager was disposed: ' + id);
    -    return;
    -  }
    -
    -  goog.log.info(this.logger_, 'Module loaded: ' + id);
    -
    -  var error = this.moduleInfoMap_[id].onLoad(
    -      goog.bind(this.getModuleContext, this));
    -  if (error) {
    -    this.dispatchModuleLoadFailed_(
    -        goog.module.ModuleManager.FailureType.INIT_ERROR);
    -  }
    -
    -  // Remove the module id from the user initiated set if it existed there.
    -  goog.array.remove(this.userInitiatedLoadingModuleIds_, id);
    -
    -  // Remove the module id from the loading modules if it exists there.
    -  goog.array.remove(this.loadingModuleIds_, id);
    -
    -  if (goog.array.isEmpty(this.loadingModuleIds_)) {
    -    // No more modules are currently being loaded (e.g. arriving later in the
    -    // same HTTP response), so proceed to load the next module in the queue.
    -    this.loadNextModules_();
    -  }
    -
    -  if (this.lastInitialModuleId_ && id == this.lastInitialModuleId_) {
    -    if (!this.initialModulesLoaded_.hasFired()) {
    -      this.initialModulesLoaded_.callback();
    -    }
    -  }
    -
    -  // Dispatch an active/idle change if needed.
    -  this.dispatchActiveIdleChangeIfNeeded_();
    -};
    -
    -
    -/**
    - * Gets whether a module is currently loading or in the queue, waiting to be
    - * loaded.
    - * @param {string} id A module id.
    - * @return {boolean} TRUE iff the module is loading.
    - */
    -goog.module.ModuleManager.prototype.isModuleLoading = function(id) {
    -  if (goog.array.contains(this.loadingModuleIds_, id)) {
    -    return true;
    -  }
    -  for (var i = 0; i < this.requestedModuleIdsQueue_.length; i++) {
    -    if (goog.array.contains(this.requestedModuleIdsQueue_[i], id)) {
    -      return true;
    -    }
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Requests that a function be called once a particular module is loaded.
    - * Client code can use this method to safely call into modules that may not yet
    - * be loaded. For consistency, this method always calls the function
    - * asynchronously -- even if the module is already loaded. Initiates loading of
    - * the module if necessary, unless opt_noLoad is true.
    - *
    - * @param {string} moduleId A module id.
    - * @param {Function} fn Function to execute when the module has loaded.
    - * @param {Object=} opt_handler Optional handler under whose scope to execute
    - *     the callback.
    - * @param {boolean=} opt_noLoad TRUE iff not to initiate loading of the module.
    - * @param {boolean=} opt_userInitiated TRUE iff the loading of the module was
    - *     user initiated.
    - * @param {boolean=} opt_preferSynchronous TRUE iff the function should be
    - *     executed synchronously if the module has already been loaded.
    - * @return {!goog.module.ModuleLoadCallback} A callback wrapper that exposes
    - *     an abort and execute method.
    - */
    -goog.module.ModuleManager.prototype.execOnLoad = function(
    -    moduleId, fn, opt_handler, opt_noLoad,
    -    opt_userInitiated, opt_preferSynchronous) {
    -  var moduleInfo = this.moduleInfoMap_[moduleId];
    -  var callbackWrapper;
    -
    -  if (moduleInfo.isLoaded()) {
    -    goog.log.info(this.logger_, moduleId + ' module already loaded');
    -    // Call async so that code paths don't change between loaded and unloaded
    -    // cases.
    -    callbackWrapper = new goog.module.ModuleLoadCallback(fn, opt_handler);
    -    if (opt_preferSynchronous) {
    -      callbackWrapper.execute(this.moduleContext_);
    -    } else {
    -      window.setTimeout(
    -          goog.bind(callbackWrapper.execute, callbackWrapper), 0);
    -    }
    -  } else if (this.isModuleLoading(moduleId)) {
    -    goog.log.info(this.logger_, moduleId + ' module already loading');
    -    callbackWrapper = moduleInfo.registerCallback(fn, opt_handler);
    -    if (opt_userInitiated) {
    -      goog.log.info(this.logger_,
    -          'User initiated module already loading: ' + moduleId);
    -      this.addUserInitiatedLoadingModule_(moduleId);
    -      this.dispatchActiveIdleChangeIfNeeded_();
    -    }
    -  } else {
    -    goog.log.info(this.logger_,
    -        'Registering callback for module: ' + moduleId);
    -    callbackWrapper = moduleInfo.registerCallback(fn, opt_handler);
    -    if (!opt_noLoad) {
    -      if (opt_userInitiated) {
    -        goog.log.info(this.logger_, 'User initiated module load: ' + moduleId);
    -        this.addUserInitiatedLoadingModule_(moduleId);
    -      }
    -      goog.log.info(this.logger_, 'Initiating module load: ' + moduleId);
    -      this.loadModulesOrEnqueue_([moduleId]);
    -    }
    -  }
    -  return callbackWrapper;
    -};
    -
    -
    -/**
    - * Loads a module, returning a goog.async.Deferred for keeping track of the
    - * result.
    - *
    - * @param {string} moduleId A module id.
    - * @param {boolean=} opt_userInitiated If the load is a result of a user action.
    - * @return {goog.async.Deferred} A deferred object.
    - */
    -goog.module.ModuleManager.prototype.load = function(
    -    moduleId, opt_userInitiated) {
    -  return this.loadModulesOrEnqueueIfNotLoadedOrLoading_(
    -      [moduleId], opt_userInitiated)[moduleId];
    -};
    -
    -
    -/**
    - * Loads a list of modules, returning a goog.async.Deferred for keeping track of
    - * the result.
    - *
    - * @param {Array<string>} moduleIds A list of module ids.
    - * @param {boolean=} opt_userInitiated If the load is a result of a user action.
    - * @return {!Object<string, !goog.async.Deferred>} A mapping from id (String)
    - *     to deferred objects that will callback or errback when the load for that
    - *     id is finished.
    - */
    -goog.module.ModuleManager.prototype.loadMultiple = function(
    -    moduleIds, opt_userInitiated) {
    -  return this.loadModulesOrEnqueueIfNotLoadedOrLoading_(
    -      moduleIds, opt_userInitiated);
    -};
    -
    -
    -/**
    - * Ensures that the module with the given id is listed as a user-initiated
    - * module that is being loaded. This method guarantees that a module will never
    - * get listed more than once.
    - * @param {string} id Identifier of the module.
    - * @private
    - */
    -goog.module.ModuleManager.prototype.addUserInitiatedLoadingModule_ = function(
    -    id) {
    -  if (!goog.array.contains(this.userInitiatedLoadingModuleIds_, id)) {
    -    this.userInitiatedLoadingModuleIds_.push(id);
    -  }
    -};
    -
    -
    -/**
    - * Method called just before a module code is loaded.
    - * @param {string} id Identifier of the module.
    - */
    -goog.module.ModuleManager.prototype.beforeLoadModuleCode = function(id) {
    -  this.loadTracer_ = goog.debug.Trace.startTracer('Module Load: ' + id,
    -      'Module Load');
    -  if (this.currentlyLoadingModule_) {
    -    goog.log.error(this.logger_,
    -        'beforeLoadModuleCode called with module "' + id +
    -        '" while module "' +
    -        this.currentlyLoadingModule_.getId() +
    -        '" is loading');
    -  }
    -  this.currentlyLoadingModule_ = this.getModuleInfo(id);
    -};
    -
    -
    -/**
    - * Method called just after module code is loaded
    - * @param {string} id Identifier of the module.
    - */
    -goog.module.ModuleManager.prototype.afterLoadModuleCode = function(id) {
    -  if (!this.currentlyLoadingModule_ ||
    -      id != this.currentlyLoadingModule_.getId()) {
    -    goog.log.error(this.logger_,
    -        'afterLoadModuleCode called with module "' + id +
    -        '" while loading module "' +
    -        (this.currentlyLoadingModule_ &&
    -        this.currentlyLoadingModule_.getId()) + '"');
    -
    -  }
    -  this.currentlyLoadingModule_ = null;
    -  goog.debug.Trace.stopTracer(this.loadTracer_);
    -};
    -
    -
    -/**
    - * Register an initialization callback for the currently loading module. This
    - * should only be called by script that is executed during the evaluation of
    - * a module's javascript. This is almost equivalent to calling the function
    - * inline, but ensures that all the code from the currently loading module
    - * has been loaded. This makes it cleaner and more robust than calling the
    - * function inline.
    - *
    - * If this function is called from the base module (the one that contains
    - * the module manager code), the callback is held until #setAllModuleInfo
    - * is called, or until #setModuleContext is called, whichever happens first.
    - *
    - * @param {Function} fn A callback function that takes a single argument
    - *    which is the module context.
    - * @param {Object=} opt_handler Optional handler under whose scope to execute
    - *     the callback.
    - */
    -goog.module.ModuleManager.prototype.registerInitializationCallback = function(
    -    fn, opt_handler) {
    -  if (!this.currentlyLoadingModule_) {
    -    goog.log.error(this.logger_, 'No module is currently loading');
    -  } else {
    -    this.currentlyLoadingModule_.registerEarlyCallback(fn, opt_handler);
    -  }
    -};
    -
    -
    -/**
    - * Register a late initialization callback for the currently loading module.
    - * Callbacks registered via this function are executed similar to
    - * {@see registerInitializationCallback}, but they are fired after all
    - * initialization callbacks are called.
    - *
    - * @param {Function} fn A callback function that takes a single argument
    - *    which is the module context.
    - * @param {Object=} opt_handler Optional handler under whose scope to execute
    - *     the callback.
    - */
    -goog.module.ModuleManager.prototype.registerLateInitializationCallback =
    -    function(fn, opt_handler) {
    -  if (!this.currentlyLoadingModule_) {
    -    goog.log.error(this.logger_, 'No module is currently loading');
    -  } else {
    -    this.currentlyLoadingModule_.registerCallback(fn, opt_handler);
    -  }
    -};
    -
    -
    -/**
    - * Sets the constructor to use for the module object for the currently
    - * loading module. The constructor should derive from {@see
    - * goog.module.BaseModule}.
    - * @param {Function} fn The constructor function.
    - */
    -goog.module.ModuleManager.prototype.setModuleConstructor = function(fn) {
    -  if (!this.currentlyLoadingModule_) {
    -    goog.log.error(this.logger_, 'No module is currently loading');
    -    return;
    -  }
    -  this.currentlyLoadingModule_.setModuleConstructor(fn);
    -};
    -
    -
    -/**
    - * The possible reasons for a module load failure callback being fired.
    - * @enum {number}
    - */
    -goog.module.ModuleManager.FailureType = {
    -  /** 401 Status. */
    -  UNAUTHORIZED: 0,
    -
    -  /** Error status (not 401) returned multiple times. */
    -  CONSECUTIVE_FAILURES: 1,
    -
    -  /** Request timeout. */
    -  TIMEOUT: 2,
    -
    -  /** 410 status, old code gone. */
    -  OLD_CODE_GONE: 3,
    -
    -  /** The onLoad callbacks failed. */
    -  INIT_ERROR: 4
    -};
    -
    -
    -/**
    - * Handles a module load failure.
    - *
    - * @param {!Array<string>} requestedLoadingModuleIds Modules ids that were
    - *     requested in failed request. Does not included calculated dependencies.
    - * @param {!Array<string>} requestedModuleIdsWithDeps All module ids requested
    - *     in the failed request including all dependencies.
    - * @param {?number} status The error status.
    - * @private
    - */
    -goog.module.ModuleManager.prototype.handleLoadError_ = function(
    -    requestedLoadingModuleIds, requestedModuleIdsWithDeps, status) {
    -  this.consecutiveFailures_++;
    -  // Module manager was not designed to be reentrant. Reinstate the instance
    -  // var with actual value when request failed (Other requests may have
    -  // started already.)
    -  this.requestedLoadingModuleIds_ = requestedLoadingModuleIds;
    -  // Pretend we never requested the failed modules.
    -  goog.array.forEach(requestedModuleIdsWithDeps,
    -      goog.partial(goog.array.remove, this.requestedModuleIds_), this);
    -
    -  if (status == 401) {
    -    // The user is not logged in. They've cleared their cookies or logged out
    -    // from another window.
    -    goog.log.info(this.logger_, 'Module loading unauthorized');
    -    this.dispatchModuleLoadFailed_(
    -        goog.module.ModuleManager.FailureType.UNAUTHORIZED);
    -    // Drop any additional module requests.
    -    this.requestedModuleIdsQueue_.length = 0;
    -  } else if (status == 410) {
    -    // The requested module js is old and not available.
    -    this.requeueBatchOrDispatchFailure_(
    -        goog.module.ModuleManager.FailureType.OLD_CODE_GONE);
    -    this.loadNextModules_();
    -  } else if (this.consecutiveFailures_ >= 3) {
    -    goog.log.info(this.logger_, 'Aborting after failure to load: ' +
    -                      this.loadingModuleIds_);
    -    this.requeueBatchOrDispatchFailure_(
    -        goog.module.ModuleManager.FailureType.CONSECUTIVE_FAILURES);
    -    this.loadNextModules_();
    -  } else {
    -    goog.log.info(this.logger_, 'Retrying after failure to load: ' +
    -                      this.loadingModuleIds_);
    -    var forceReload =
    -        status == goog.module.ModuleManager.CORRUPT_RESPONSE_STATUS_CODE;
    -    this.loadModules_(this.requestedLoadingModuleIds_, true, forceReload);
    -  }
    -};
    -
    -
    -/**
    - * Handles a module load timeout.
    - * @private
    - */
    -goog.module.ModuleManager.prototype.handleLoadTimeout_ = function() {
    -  goog.log.info(this.logger_,
    -      'Aborting after timeout: ' + this.loadingModuleIds_);
    -  this.requeueBatchOrDispatchFailure_(
    -      goog.module.ModuleManager.FailureType.TIMEOUT);
    -  this.loadNextModules_();
    -};
    -
    -
    -/**
    - * Requeues batch loads that had more than one requested module
    - * (i.e. modules that were not included as dependencies) as separate loads or
    - * if there was only one requested module, fails that module with the received
    - * cause.
    - * @param {goog.module.ModuleManager.FailureType} cause The reason for the
    - *     failure.
    - * @private
    - */
    -goog.module.ModuleManager.prototype.requeueBatchOrDispatchFailure_ =
    -    function(cause) {
    -  // The load failed, so if there are more than one requested modules, then we
    -  // need to retry each one as a separate load. Otherwise, if there is only one
    -  // requested module, remove it and its dependencies from the queue.
    -  if (this.requestedLoadingModuleIds_.length > 1) {
    -    var queuedModules = goog.array.map(this.requestedLoadingModuleIds_,
    -        function(id) {
    -          return [id];
    -        });
    -    this.requestedModuleIdsQueue_ = queuedModules.concat(
    -        this.requestedModuleIdsQueue_);
    -  } else {
    -    this.dispatchModuleLoadFailed_(cause);
    -  }
    -};
    -
    -
    -/**
    - * Handles when a module load failed.
    - * @param {goog.module.ModuleManager.FailureType} cause The reason for the
    - *     failure.
    - * @private
    - */
    -goog.module.ModuleManager.prototype.dispatchModuleLoadFailed_ = function(
    -    cause) {
    -  var failedIds = this.requestedLoadingModuleIds_;
    -  this.loadingModuleIds_.length = 0;
    -  // If any pending modules depend on the id that failed,
    -  // they need to be removed from the queue.
    -  var idsToCancel = [];
    -  for (var i = 0; i < this.requestedModuleIdsQueue_.length; i++) {
    -    var dependentModules = goog.array.filter(
    -        this.requestedModuleIdsQueue_[i],
    -        /**
    -         * Returns true if the requestedId has dependencies on the modules that
    -         * just failed to load.
    -         * @param {string} requestedId The module to check for dependencies.
    -         * @return {boolean} True if the module depends on failed modules.
    -         */
    -        function(requestedId) {
    -          var requestedDeps = this.getNotYetLoadedTransitiveDepIds_(
    -              requestedId);
    -          return goog.array.some(failedIds, function(id) {
    -            return goog.array.contains(requestedDeps, id);
    -          });
    -        }, this);
    -    goog.array.extend(idsToCancel, dependentModules);
    -  }
    -
    -  // Also insert the ids that failed to load as ids to cancel.
    -  for (var i = 0; i < failedIds.length; i++) {
    -    goog.array.insert(idsToCancel, failedIds[i]);
    -  }
    -
    -  // Remove ids to cancel from the queues.
    -  for (var i = 0; i < idsToCancel.length; i++) {
    -    for (var j = 0; j < this.requestedModuleIdsQueue_.length; j++) {
    -      goog.array.remove(this.requestedModuleIdsQueue_[j], idsToCancel[i]);
    -    }
    -    goog.array.remove(this.userInitiatedLoadingModuleIds_, idsToCancel[i]);
    -  }
    -
    -  // Call the functions for error notification.
    -  var errorCallbacks = this.callbackMap_[
    -      goog.module.ModuleManager.CallbackType.ERROR];
    -  if (errorCallbacks) {
    -    for (var i = 0; i < errorCallbacks.length; i++) {
    -      var callback = errorCallbacks[i];
    -      for (var j = 0; j < idsToCancel.length; j++) {
    -        callback(goog.module.ModuleManager.CallbackType.ERROR, idsToCancel[j],
    -            cause);
    -      }
    -    }
    -  }
    -
    -  // Call the errbacks on the module info.
    -  for (var i = 0; i < failedIds.length; i++) {
    -    if (this.moduleInfoMap_[failedIds[i]]) {
    -      this.moduleInfoMap_[failedIds[i]].onError(cause);
    -    }
    -  }
    -
    -  // Clear the requested loading module ids.
    -  this.requestedLoadingModuleIds_.length = 0;
    -
    -  this.dispatchActiveIdleChangeIfNeeded_();
    -};
    -
    -
    -/**
    - * Loads the next modules on the queue.
    - * @private
    - */
    -goog.module.ModuleManager.prototype.loadNextModules_ = function() {
    -  while (this.requestedModuleIdsQueue_.length) {
    -    // Remove modules that are already loaded.
    -    var nextIds = goog.array.filter(this.requestedModuleIdsQueue_.shift(),
    -        /** @param {string} id The module id. */
    -        function(id) {
    -          return !this.getModuleInfo(id).isLoaded();
    -        }, this);
    -    if (nextIds.length > 0) {
    -      this.loadModules_(nextIds);
    -      return;
    -    }
    -  }
    -
    -  // Dispatch an active/idle change if needed.
    -  this.dispatchActiveIdleChangeIfNeeded_();
    -};
    -
    -
    -/**
    - * The function to call if the module manager is in error.
    - * @param {goog.module.ModuleManager.CallbackType|Array<goog.module.ModuleManager.CallbackType>} types
    - *  The callback type.
    - * @param {Function} fn The function to register as a callback.
    - */
    -goog.module.ModuleManager.prototype.registerCallback = function(
    -    types, fn) {
    -  if (!goog.isArray(types)) {
    -    types = [types];
    -  }
    -
    -  for (var i = 0; i < types.length; i++) {
    -    this.registerCallback_(types[i], fn);
    -  }
    -};
    -
    -
    -/**
    - * Register a callback for the specified callback type.
    - * @param {goog.module.ModuleManager.CallbackType} type The callback type.
    - * @param {Function} fn The callback function.
    - * @private
    - */
    -goog.module.ModuleManager.prototype.registerCallback_ = function(type, fn) {
    -  var callbackMap = this.callbackMap_;
    -  if (!callbackMap[type]) {
    -    callbackMap[type] = [];
    -  }
    -  callbackMap[type].push(fn);
    -};
    -
    -
    -/**
    - * Call the callback functions of the specified type.
    - * @param {goog.module.ModuleManager.CallbackType} type The callback type.
    - * @private
    - */
    -goog.module.ModuleManager.prototype.executeCallbacks_ = function(type) {
    -  var callbacks = this.callbackMap_[type];
    -  for (var i = 0; callbacks && i < callbacks.length; i++) {
    -    callbacks[i](type);
    -  }
    -};
    -
    -
    -/** @override */
    -goog.module.ModuleManager.prototype.disposeInternal = function() {
    -  goog.module.ModuleManager.base(this, 'disposeInternal');
    -
    -  // Dispose of each ModuleInfo object.
    -  goog.disposeAll(
    -      goog.object.getValues(this.moduleInfoMap_), this.baseModuleInfo_);
    -  this.moduleInfoMap_ = null;
    -  this.loadingModuleIds_ = null;
    -  this.requestedLoadingModuleIds_ = null;
    -  this.userInitiatedLoadingModuleIds_ = null;
    -  this.requestedModuleIdsQueue_ = null;
    -  this.callbackMap_ = null;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/module/modulemanager_test.html b/src/database/third_party/closure-library/closure/goog/module/modulemanager_test.html
    deleted file mode 100644
    index e8804c419f3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/module/modulemanager_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.module.ModuleManager
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.module.ModuleManagerTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/module/modulemanager_test.js b/src/database/third_party/closure-library/closure/goog/module/modulemanager_test.js
    deleted file mode 100644
    index 184ab3346c0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/module/modulemanager_test.js
    +++ /dev/null
    @@ -1,2210 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.module.ModuleManagerTest');
    -goog.setTestOnly('goog.module.ModuleManagerTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.functions');
    -goog.require('goog.module.BaseModule');
    -goog.require('goog.module.ModuleManager');
    -goog.require('goog.testing');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -
    -
    -
    -var clock;
    -var requestCount = 0;
    -
    -
    -function tearDown() {
    -  clock.dispose();
    -}
    -
    -function setUp() {
    -  clock = new goog.testing.MockClock(true);
    -  requestCount = 0;
    -}
    -
    -function getModuleManager(infoMap) {
    -  var mm = new goog.module.ModuleManager();
    -  mm.setAllModuleInfo(infoMap);
    -
    -  mm.isModuleLoaded = function(id) {
    -    return this.getModuleInfo(id).isLoaded();
    -  };
    -  return mm;
    -}
    -
    -function createSuccessfulBatchLoader(moduleMgr) {
    -  return {
    -    loadModules: function(ids, moduleInfoMap, opt_successFn, opt_errFn,
    -        opt_timeoutFn) {
    -      requestCount++;
    -      setTimeout(goog.bind(this.onLoad, this, ids.concat(), 0), 5);
    -    },
    -    onLoad: function(ids, idxLoaded) {
    -      moduleMgr.beforeLoadModuleCode(ids[idxLoaded]);
    -      moduleMgr.setLoaded(ids[idxLoaded]);
    -      moduleMgr.afterLoadModuleCode(ids[idxLoaded]);
    -      var idx = idxLoaded + 1;
    -      if (idx < ids.length) {
    -        setTimeout(goog.bind(this.onLoad, this, ids, idx), 2);
    -      }
    -    }};
    -}
    -
    -function createSuccessfulNonBatchLoader(moduleMgr) {
    -  return {
    -    loadModules: function(ids, moduleInfoMap, opt_successFn, opt_errFn,
    -        opt_timeoutFn) {
    -      requestCount++;
    -      setTimeout(function() {
    -        moduleMgr.beforeLoadModuleCode(ids[0]);
    -        moduleMgr.setLoaded(ids[0]);
    -        moduleMgr.afterLoadModuleCode(ids[0]);
    -        if (opt_successFn) {
    -          opt_successFn();
    -        }
    -      }, 5);
    -    }};
    -}
    -
    -function createUnsuccessfulLoader(moduleMgr, status) {
    -  return {
    -    loadModules: function(ids, moduleInfoMap, opt_successFn, opt_errFn,
    -        opt_timeoutFn) {
    -      moduleMgr.beforeLoadModuleCode(ids[0]);
    -      setTimeout(function() { opt_errFn(status); }, 5);
    -    }};
    -}
    -
    -function createUnsuccessfulBatchLoader(moduleMgr, status) {
    -  return {
    -    loadModules: function(ids, moduleInfoMap, opt_successFn, opt_errFn,
    -        opt_timeoutFn) {
    -      setTimeout(function() { opt_errFn(status); }, 5);
    -    }};
    -}
    -
    -function createTimeoutLoader(moduleMgr, status) {
    -  return {
    -    loadModules: function(ids, moduleInfoMap, opt_successFn, opt_errFn,
    -        opt_timeoutFn) {
    -      setTimeout(function() { opt_timeoutFn(status); }, 5);
    -    }};
    -}
    -
    -
    -/**
    - * Tests loading a module under different conditions i.e. unloaded
    - * module, already loaded module, module loaded through user initiated
    - * actions, synchronous callback for a module that has been already
    - * loaded. Test both batch and non-batch loaders.
    - */
    -function testExecOnLoad() {
    -  var mm = getModuleManager({'a': [], 'b': [], 'c': []});
    -  mm.setLoader(createSuccessfulNonBatchLoader(mm));
    -  execOnLoad_(mm);
    -
    -  mm = getModuleManager({'a': [], 'b': [], 'c': []});
    -  mm.setLoader(createSuccessfulBatchLoader(mm));
    -  mm.setBatchModeEnabled(true);
    -  execOnLoad_(mm);
    -}
    -
    -
    -/**
    - * Tests execOnLoad with the specified module manager.
    - * @param {goog.module.ModuleManager} mm The module manager.
    - */
    -function execOnLoad_(mm) {
    -  // When module is unloaded, execOnLoad is async.
    -  var execCalled1 = false;
    -  mm.execOnLoad('a', function() { execCalled1 = true; });
    -  assertFalse('module "a" should not be loaded', mm.isModuleLoaded('a'));
    -  assertTrue('module "a" should be loading', mm.isModuleLoading('a'));
    -  assertFalse('execCalled1 should not be set yet', execCalled1);
    -  assertTrue('ModuleManager should be active', mm.isActive());
    -  assertFalse(
    -      'ModuleManager should not be user active', mm.isUserActive());
    -  clock.tick(5);
    -  assertTrue('module "a" should be loaded', mm.isModuleLoaded('a'));
    -  assertFalse(
    -      'module "a" should not be loading', mm.isModuleLoading('a'));
    -  assertTrue('execCalled1 should be set', execCalled1);
    -  assertFalse('ModuleManager should not be active', mm.isActive());
    -  assertFalse(
    -      'ModuleManager should not be user active', mm.isUserActive());
    -
    -  // When module is already loaded, execOnLoad is still async unless
    -  // specified otherwise.
    -  var execCalled2 = false;
    -  mm.execOnLoad('a', function() { execCalled2 = true; });
    -  assertTrue('module "a" should be loaded', mm.isModuleLoaded('a'));
    -  assertFalse(
    -      'module "a" should not be loading', mm.isModuleLoading('a'));
    -  assertFalse('execCalled2 should not be set yet', execCalled2);
    -  clock.tick(5);
    -  assertTrue('execCalled2 should be set', execCalled2);
    -
    -  // When module is unloaded, execOnLoad is async (user active).
    -  var execCalled5 = false;
    -  mm.execOnLoad('c',
    -      function() { execCalled5 = true; }, null, null, true);
    -  assertFalse('module "c" should not be loaded', mm.isModuleLoaded('c'));
    -  assertTrue('module "c" should be loading', mm.isModuleLoading('c'));
    -  assertFalse('execCalled1 should not be set yet', execCalled5);
    -  assertTrue('ModuleManager should be active', mm.isActive());
    -  assertTrue('ModuleManager should be user active', mm.isUserActive());
    -  clock.tick(5);
    -  assertTrue('module "c" should be loaded', mm.isModuleLoaded('c'));
    -  assertFalse(
    -      'module "c" should not be loading', mm.isModuleLoading('c'));
    -  assertTrue('execCalled1 should be set', execCalled5);
    -  assertFalse('ModuleManager should not be active', mm.isActive());
    -  assertFalse(
    -      'ModuleManager should not be user active', mm.isUserActive());
    -
    -  // When module is already loaded, execOnLoad is still synchronous when
    -  // so specified
    -  var execCalled6 = false;
    -  mm.execOnLoad('c', function() { execCalled6 = true; },
    -      undefined, undefined, undefined, true);
    -  assertTrue('module "c" should be loaded', mm.isModuleLoaded('c'));
    -  assertFalse(
    -      'module "c" should not be loading', mm.isModuleLoading('c'));
    -  assertTrue('execCalled6 should be set', execCalled6);
    -  clock.tick(5);
    -  assertTrue('execCalled6 should still be set', execCalled6);
    -
    -}
    -
    -
    -/**
    - * Test aborting the callback called on module load.
    - */
    -function testExecOnLoadAbort() {
    -  var mm = getModuleManager({'a': [], 'b': [], 'c': []});
    -  mm.setLoader(createSuccessfulNonBatchLoader(mm));
    -
    -  // When module is unloaded and abort is called, module still gets
    -  // loaded, but callback is cancelled.
    -  var execCalled1 = false;
    -  var callback1 = mm.execOnLoad('b', function() { execCalled1 = true; });
    -  callback1.abort();
    -  clock.tick(5);
    -  assertTrue('module "b" should be loaded', mm.isModuleLoaded('b'));
    -  assertFalse('execCalled3 should not be set', execCalled1);
    -
    -  // When module is already loaded, execOnLoad is still async, so calling
    -  // abort should still cancel the callback.
    -  var execCalled2 = false;
    -  var callback2 = mm.execOnLoad('a', function() { execCalled2 = true; });
    -  callback2.abort();
    -  clock.tick(5);
    -  assertFalse('execCalled2 should not be set', execCalled2);
    -}
    -
    -
    -/**
    - * Test preloading modules and ensure that the before load, after load
    - * and set load called are called only once per module.
    - */
    -function testExecOnLoadWhilePreloadingAndViceVersa() {
    -  var mm = getModuleManager({'c': [], 'd': []});
    -  mm.setLoader(createSuccessfulNonBatchLoader(mm));
    -  execOnLoadWhilePreloadingAndViceVersa_(mm);
    -
    -  mm = getModuleManager({'c': [], 'd': []});
    -  mm.setLoader(createSuccessfulBatchLoader(mm));
    -  mm.setBatchModeEnabled(true);
    -  execOnLoadWhilePreloadingAndViceVersa_(mm);
    -}
    -
    -
    -/**
    - * Perform tests with the specified module manager.
    - * @param {goog.module.ModuleManager} mm The module manager.
    - */
    -function execOnLoadWhilePreloadingAndViceVersa_(mm) {
    -  var mm = getModuleManager({'c': [], 'd': []});
    -  mm.setLoader(createSuccessfulNonBatchLoader(mm));
    -
    -  var origSetLoaded = mm.setLoaded;
    -  var calls = [0, 0, 0];
    -  mm.beforeLoadModuleCode = function(id) {
    -    calls[0]++;
    -  };
    -  mm.setLoaded = function(id) {
    -    calls[1]++;
    -    origSetLoaded.call(mm, id);
    -  };
    -  mm.afterLoadModuleCode = function(id) {
    -    calls[2]++;
    -  };
    -
    -  mm.preloadModule('c', 2);
    -  assertFalse(
    -      'module "c" should not be loading yet', mm.isModuleLoading('c'));
    -  clock.tick(2);
    -  assertTrue(
    -      'module "c" should now be loading', mm.isModuleLoading('c'));
    -  mm.execOnLoad('c', function() {});
    -  assertTrue(
    -      'module "c" should still be loading', mm.isModuleLoading('c'));
    -  clock.tick(5);
    -  assertFalse(
    -      'module "c" should be done loading', mm.isModuleLoading('c'));
    -  assertEquals(
    -      'beforeLoad should only be called once for "c"', 1, calls[0]);
    -  assertEquals(
    -      'setLoaded should only be called once for "c"', 1, calls[1]);
    -  assertEquals(
    -      'afterLoad should only be called once for "c"', 1, calls[2]);
    -
    -  mm.execOnLoad('d', function() {});
    -  assertTrue(
    -      'module "d" should now be loading', mm.isModuleLoading('d'));
    -  mm.preloadModule('d', 2);
    -  clock.tick(5);
    -  assertFalse(
    -      'module "d" should be done loading', mm.isModuleLoading('d'));
    -  assertTrue(
    -      'module "d" should now be loaded', mm.isModuleLoaded('d'));
    -  assertEquals(
    -      'beforeLoad should only be called once for "d"', 2, calls[0]);
    -  assertEquals(
    -      'setLoaded should only be called once for "d"', 2, calls[1]);
    -  assertEquals(
    -      'afterLoad should only be called once for "d"', 2, calls[2]);
    -}
    -
    -
    -/**
    - * Tests that multiple callbacks on the same module don't cause
    - * confusion about the active state after the module is finally loaded.
    - */
    -function testUserInitiatedExecOnLoadEventuallyLeavesManagerIdle() {
    -  var mm = getModuleManager({'c': [], 'd': []});
    -  mm.setLoader(createSuccessfulNonBatchLoader(mm));
    -
    -  var calledBack1 = false;
    -  var calledBack2 = false;
    -
    -  mm.execOnLoad(
    -      'c',
    -      function() {
    -        calledBack1 = true;
    -      },
    -      undefined,
    -      undefined,
    -      true);
    -  mm.execOnLoad(
    -      'c',
    -      function() {
    -        calledBack2 = true;
    -      },
    -      undefined,
    -      undefined,
    -      true);
    -  mm.load('c');
    -
    -  assertTrue(
    -      'Manager should be active while waiting for load', mm.isUserActive());
    -
    -  clock.tick(5);
    -
    -  assertTrue('First callback should be called', calledBack1);
    -  assertTrue('Second callback should be called', calledBack2);
    -  assertFalse(
    -      'Manager should be inactive after loading is complete',
    -      mm.isUserActive());
    -}
    -
    -
    -/**
    - * Tests loading a module by requesting a Deferred object.
    - */
    -function testLoad() {
    -  var mm = getModuleManager({'a': [], 'b': [], 'c': []});
    -  mm.setLoader(createSuccessfulNonBatchLoader(mm));
    -
    -  var calledBack = false;
    -  var error = null;
    -
    -  var d = mm.load('a');
    -  d.addCallback(function(ctx) {
    -    calledBack = true;
    -  });
    -  d.addErrback(function(err) {
    -    error = err;
    -  });
    -
    -  assertFalse(calledBack);
    -  assertNull(error);
    -  assertFalse(mm.isUserActive());
    -
    -  clock.tick(5);
    -
    -  assertTrue(calledBack);
    -  assertNull(error);
    -}
    -
    -
    -/**
    - * Tests loading 2 modules asserting that the loads happen in parallel
    - * in one unit of time.
    - */
    -function testLoad_concurrent() {
    -  var mm = getModuleManager({'a': [], 'b': [], 'c': []});
    -  mm.setConcurrentLoadingEnabled(true);
    -  mm.setLoader(createSuccessfulNonBatchLoader(mm));
    -
    -  var calledBack = false;
    -  var error = null;
    -
    -  mm.load('a');
    -  mm.load('b');
    -  assertEquals(2, requestCount);
    -  // Only time for one serialized download.
    -  clock.tick(5);
    -
    -  assertTrue(mm.getModuleInfo('a').isLoaded());
    -  assertTrue(mm.getModuleInfo('b').isLoaded());
    -}
    -
    -function testLoad_concurrentSecondIsDepOfFist() {
    -  var mm = getModuleManager({'a': [], 'b': [], 'c': []});
    -  mm.setBatchModeEnabled(true);
    -  mm.setConcurrentLoadingEnabled(true);
    -  mm.setLoader(createSuccessfulBatchLoader(mm));
    -
    -  var calledBack = false;
    -  var error = null;
    -
    -  mm.loadMultiple(['a', 'b']);
    -  mm.load('b');
    -  assertEquals('No 2nd request expected', 1, requestCount);
    -  // Only time for one serialized download.
    -  clock.tick(5);
    -  clock.tick(2); // Makes second module come in from batch requst.
    -
    -  assertTrue(mm.getModuleInfo('a').isLoaded());
    -  assertTrue(mm.getModuleInfo('b').isLoaded());
    -}
    -
    -function testLoad_nonConcurrent() {
    -  var mm = getModuleManager({'a': [], 'b': [], 'c': []});
    -  mm.setLoader(createSuccessfulNonBatchLoader(mm));
    -
    -  var calledBack = false;
    -  var error = null;
    -
    -  mm.load('a');
    -  mm.load('b');
    -  assertEquals(1, requestCount);
    -  // Only time for one serialized download.
    -  clock.tick(5);
    -
    -  assertTrue(mm.getModuleInfo('a').isLoaded());
    -  assertFalse(mm.getModuleInfo('b').isLoaded());
    -}
    -
    -function testLoadUnknown() {
    -  var mm = getModuleManager({'a': [], 'b': [], 'c': []});
    -  mm.setLoader(createSuccessfulNonBatchLoader(mm));
    -  var e = assertThrows(function() {
    -    mm.load('DoesNotExist');
    -  });
    -  assertEquals('Unknown module: DoesNotExist', e.message);
    -}
    -
    -
    -/**
    - * Tests loading multiple modules by requesting a Deferred object.
    - */
    -function testLoadMultiple() {
    -  var mm = getModuleManager({'a': [], 'b': [], 'c': []});
    -  mm.setBatchModeEnabled(true);
    -  mm.setLoader(createSuccessfulBatchLoader(mm));
    -
    -  var calledBack = false;
    -  var error = null;
    -  var calledBack2 = false;
    -  var error2 = null;
    -
    -  var dMap = mm.loadMultiple(['a', 'b']);
    -  dMap['a'].addCallback(function(ctx) {
    -    calledBack = true;
    -  });
    -  dMap['a'].addErrback(function(err) {
    -    error = err;
    -  });
    -  dMap['b'].addCallback(function(ctx) {
    -    calledBack2 = true;
    -  });
    -  dMap['b'].addErrback(function(err) {
    -    error2 = err;
    -  });
    -
    -  assertFalse(calledBack);
    -  assertFalse(calledBack2);
    -
    -  clock.tick(5);
    -  assertTrue(calledBack);
    -  assertFalse(calledBack2);
    -  assertTrue('module "a" should be loaded', mm.isModuleLoaded('a'));
    -  assertFalse('module "b" should not be loaded', mm.isModuleLoaded('b'));
    -  assertFalse('module "c" should not be loaded', mm.isModuleLoaded('c'));
    -
    -  clock.tick(2);
    -
    -  assertTrue(calledBack);
    -  assertTrue(calledBack2);
    -  assertTrue('module "a" should be loaded', mm.isModuleLoaded('a'));
    -  assertTrue('module "b" should be loaded', mm.isModuleLoaded('b'));
    -  assertFalse('module "c" should not be loaded', mm.isModuleLoaded('c'));
    -  assertNull(error);
    -  assertNull(error2);
    -}
    -
    -
    -/**
    - * Tests loading multiple modules with deps by requesting a Deferred object.
    - */
    -function testLoadMultipleWithDeps() {
    -  var mm = getModuleManager({'a': [], 'b': ['c'], 'c': []});
    -  mm.setBatchModeEnabled(true);
    -  mm.setLoader(createSuccessfulBatchLoader(mm));
    -
    -  var calledBack = false;
    -  var error = null;
    -  var calledBack2 = false;
    -  var error2 = null;
    -
    -  var dMap = mm.loadMultiple(['a', 'b']);
    -  dMap['a'].addCallback(function(ctx) {
    -    calledBack = true;
    -  });
    -  dMap['a'].addErrback(function(err) {
    -    error = err;
    -  });
    -  dMap['b'].addCallback(function(ctx) {
    -    calledBack2 = true;
    -  });
    -  dMap['b'].addErrback(function(err) {
    -    error2 = err;
    -  });
    -
    -  assertFalse(calledBack);
    -  assertFalse(calledBack2);
    -
    -  clock.tick(5);
    -  assertTrue(calledBack);
    -  assertFalse(calledBack2);
    -  assertTrue('module "a" should be loaded', mm.isModuleLoaded('a'));
    -  assertFalse('module "b" should not be loaded', mm.isModuleLoaded('b'));
    -  assertFalse('module "c" should not be loaded', mm.isModuleLoaded('c'));
    -
    -  clock.tick(2);
    -
    -  assertFalse(calledBack2);
    -  assertTrue('module "a" should be loaded', mm.isModuleLoaded('a'));
    -  assertFalse('module "b" should not be loaded', mm.isModuleLoaded('b'));
    -  assertTrue('module "c" should be loaded', mm.isModuleLoaded('c'));
    -
    -  clock.tick(2);
    -
    -  assertTrue(calledBack2);
    -  assertTrue('module "a" should be loaded', mm.isModuleLoaded('a'));
    -  assertTrue('module "b" should be loaded', mm.isModuleLoaded('b'));
    -  assertTrue('module "c" should be loaded', mm.isModuleLoaded('c'));
    -  assertNull(error);
    -  assertNull(error2);
    -}
    -
    -
    -/**
    - * Tests loading multiple modules by requesting a Deferred object when
    - * a server error occurs.
    - */
    -function testLoadMultipleWithErrors() {
    -  var mm = getModuleManager({'a': [], 'b': [], 'c': []});
    -  mm.setBatchModeEnabled(true);
    -  mm.setLoader(createUnsuccessfulLoader(mm, 500));
    -
    -  var calledBack = false;
    -  var error = null;
    -  var calledBack2 = false;
    -  var error2 = null;
    -  var calledBack3 = false;
    -  var error3 = null;
    -
    -  var dMap = mm.loadMultiple(['a', 'b', 'c']);
    -  dMap['a'].addCallback(function(ctx) {
    -    calledBack = true;
    -  });
    -  dMap['a'].addErrback(function(err) {
    -    error = err;
    -  });
    -  dMap['b'].addCallback(function(ctx) {
    -    calledBack2 = true;
    -  });
    -  dMap['b'].addErrback(function(err) {
    -    error2 = err;
    -  });
    -  dMap['c'].addCallback(function(ctx) {
    -    calledBack3 = true;
    -  });
    -  dMap['c'].addErrback(function(err) {
    -    error3 = err;
    -  });
    -
    -  assertFalse(calledBack);
    -  assertFalse(calledBack2);
    -  assertFalse(calledBack3);
    -
    -  clock.tick(4);
    -
    -  // A module request is now underway using the unsuccessful loader.
    -  // We substitute a successful loader for future module load requests.
    -  mm.setLoader(createSuccessfulBatchLoader(mm));
    -
    -  clock.tick(1);
    -
    -  assertFalse(calledBack);
    -  assertFalse(calledBack2);
    -  assertFalse(calledBack3);
    -  assertFalse('module "a" should not be loaded', mm.isModuleLoaded('a'));
    -  assertFalse('module "b" should not be loaded', mm.isModuleLoaded('b'));
    -  assertFalse('module "c" should not be loaded', mm.isModuleLoaded('c'));
    -
    -  // Retry should happen after a backoff
    -  clock.tick(5 + mm.getBackOff_());
    -
    -  assertTrue(calledBack);
    -  assertFalse(calledBack2);
    -  assertFalse(calledBack3);
    -  assertTrue('module "a" should be loaded', mm.isModuleLoaded('a'));
    -  assertFalse('module "b" should not be loaded', mm.isModuleLoaded('b'));
    -  assertFalse('module "c" should not be loaded', mm.isModuleLoaded('c'));
    -
    -  clock.tick(2);
    -  assertTrue(calledBack2);
    -  assertFalse(calledBack3);
    -  assertTrue('module "b" should be loaded', mm.isModuleLoaded('b'));
    -  assertFalse('module "c" should not be loaded', mm.isModuleLoaded('c'));
    -
    -  clock.tick(2);
    -  assertTrue(calledBack3);
    -  assertTrue('module "c" should be loaded', mm.isModuleLoaded('c'));
    -
    -  assertNull(error);
    -  assertNull(error2);
    -  assertNull(error3);
    -}
    -
    -
    -/**
    - * Tests loading multiple modules by requesting a Deferred object when
    - * consecutive server error occur and the loader falls back to serial
    - * loads.
    - */
    -function testLoadMultipleWithErrorsFallbackOnSerial() {
    -  var mm = getModuleManager({'a': [], 'b': [], 'c': []});
    -  mm.setBatchModeEnabled(true);
    -  mm.setLoader(createUnsuccessfulLoader(mm, 500));
    -
    -  var calledBack = false;
    -  var error = null;
    -  var calledBack2 = false;
    -  var error2 = null;
    -  var calledBack3 = false;
    -  var error3 = null;
    -
    -  var dMap = mm.loadMultiple(['a', 'b', 'c']);
    -  dMap['a'].addCallback(function(ctx) {
    -    calledBack = true;
    -  });
    -  dMap['a'].addErrback(function(err) {
    -    error = err;
    -  });
    -  dMap['b'].addCallback(function(ctx) {
    -    calledBack2 = true;
    -  });
    -  dMap['b'].addErrback(function(err) {
    -    error2 = err;
    -  });
    -  dMap['c'].addCallback(function(ctx) {
    -    calledBack3 = true;
    -  });
    -  dMap['c'].addErrback(function(err) {
    -    error3 = err;
    -  });
    -
    -  assertFalse(calledBack);
    -  assertFalse(calledBack2);
    -  assertFalse(calledBack3);
    -
    -  clock.tick(5);
    -
    -  assertFalse(calledBack);
    -  assertFalse(calledBack2);
    -  assertFalse(calledBack3);
    -  assertFalse('module "a" should not be loaded', mm.isModuleLoaded('a'));
    -  assertFalse('module "b" should not be loaded', mm.isModuleLoaded('b'));
    -  assertFalse('module "c" should not be loaded', mm.isModuleLoaded('c'));
    -
    -  // Retry should happen and fail after a backoff
    -  clock.tick(5 + mm.getBackOff_());
    -  assertFalse(calledBack);
    -  assertFalse(calledBack2);
    -  assertFalse(calledBack3);
    -  assertFalse('module "a" should not be loaded', mm.isModuleLoaded('a'));
    -  assertFalse('module "b" should not be loaded', mm.isModuleLoaded('b'));
    -  assertFalse('module "c" should not be loaded', mm.isModuleLoaded('c'));
    -
    -  // A second retry should happen after a backoff
    -  clock.tick(4 + mm.getBackOff_());
    -  // The second retry is now underway using the unsuccessful loader.
    -  // We substitute a successful loader for future module load requests.
    -  mm.setLoader(createSuccessfulBatchLoader(mm));
    -
    -  clock.tick(1);
    -
    -  // A second retry should fail now
    -  assertFalse(calledBack);
    -  assertFalse(calledBack2);
    -  assertFalse(calledBack3);
    -  assertFalse('module "a" should not be loaded', mm.isModuleLoaded('a'));
    -  assertFalse('module "b" should not be loaded', mm.isModuleLoaded('b'));
    -  assertFalse('module "c" should not be loaded', mm.isModuleLoaded('c'));
    -
    -  // Each module should be loaded individually now, each taking 5 ticks
    -
    -  clock.tick(5);
    -  assertTrue(calledBack);
    -  assertFalse(calledBack2);
    -  assertFalse(calledBack3);
    -  assertTrue('module "a" should be loaded', mm.isModuleLoaded('a'));
    -  assertFalse('module "b" should not be loaded', mm.isModuleLoaded('b'));
    -  assertFalse('module "c" should not be loaded', mm.isModuleLoaded('c'));
    -
    -  clock.tick(5);
    -  assertTrue(calledBack2);
    -  assertFalse(calledBack3);
    -  assertTrue('module "b" should be loaded', mm.isModuleLoaded('b'));
    -  assertFalse('module "c" should not be loaded', mm.isModuleLoaded('c'));
    -
    -  clock.tick(5);
    -  assertTrue(calledBack3);
    -  assertTrue('module "c" should be loaded', mm.isModuleLoaded('c'));
    -
    -  assertNull(error);
    -  assertNull(error2);
    -  assertNull(error3);
    -}
    -
    -
    -/**
    - * Tests loading a module by user action by requesting a Deferred object.
    - */
    -function testLoadForUser() {
    -  var mm = getModuleManager({'a': [], 'b': [], 'c': []});
    -  mm.setLoader(createSuccessfulNonBatchLoader(mm));
    -
    -  var calledBack = false;
    -  var error = null;
    -
    -  var d = mm.load('a', true);
    -  d.addCallback(function(ctx) {
    -    calledBack = true;
    -  });
    -  d.addErrback(function(err) {
    -    error = err;
    -  });
    -
    -  assertFalse(calledBack);
    -  assertNull(error);
    -  assertTrue(mm.isUserActive());
    -
    -  clock.tick(5);
    -
    -  assertTrue(calledBack);
    -  assertNull(error);
    -}
    -
    -
    -/**
    - * Tests that preloading a module calls back the deferred object.
    - */
    -function testPreloadDeferredWhenNotLoaded() {
    -  var mm = getModuleManager({'a': []});
    -  mm.setLoader(createSuccessfulNonBatchLoader(mm));
    -
    -  var calledBack = false;
    -
    -  var d = mm.preloadModule('a');
    -  d.addCallback(function(ctx) {
    -    calledBack = true;
    -  });
    -
    -  // First load should take five ticks.
    -  assertFalse('module "a" should not be loaded yet', calledBack);
    -  clock.tick(5);
    -  assertTrue('module "a" should be loaded', calledBack);
    -}
    -
    -
    -/**
    - * Tests preloading an already loaded module.
    - */
    -function testPreloadDeferredWhenLoaded() {
    -  var mm = getModuleManager({'a': []});
    -  mm.setLoader(createSuccessfulNonBatchLoader(mm));
    -
    -  var calledBack = false;
    -
    -  mm.preloadModule('a');
    -  clock.tick(5);
    -
    -  var d = mm.preloadModule('a');
    -  d.addCallback(function(ctx) {
    -    calledBack = true;
    -  });
    -
    -  // Module is already loaded, should be called back after the setTimeout
    -  // in preloadModule.
    -  assertFalse('deferred for module "a" should not be called yet', calledBack);
    -  clock.tick(1);
    -  assertTrue('module "a" should be loaded', calledBack);
    -}
    -
    -
    -/**
    - * Tests preloading a module that is currently loading.
    - */
    -function testPreloadDeferredWhenLoading() {
    -  var mm = getModuleManager({'a': []});
    -  mm.setLoader(createSuccessfulNonBatchLoader(mm));
    -
    -  mm.preloadModule('a');
    -  clock.tick(1);
    -
    -  // 'b' is in the middle of loading, should get called back when it's done.
    -  var calledBack = false;
    -  var d = mm.preloadModule('a');
    -  d.addCallback(function(ctx) {
    -    calledBack = true;
    -  });
    -
    -  assertFalse('module "a" should not be loaded yet', calledBack);
    -  clock.tick(4);
    -  assertTrue('module "a" should be loaded', calledBack);
    -}
    -
    -
    -/**
    - * Tests that load doesn't trigger another load if a module is already
    - * preloading.
    - */
    -function testLoadWhenPreloading() {
    -  var mm = getModuleManager({'a': [], 'b': [], 'c': []});
    -  mm.setLoader(createSuccessfulNonBatchLoader(mm));
    -
    -  var origSetLoaded = mm.setLoaded;
    -  var calls = [0, 0, 0];
    -  mm.beforeLoadModuleCode = function(id) {
    -    calls[0]++;
    -  };
    -  mm.setLoaded = function(id) {
    -    calls[1]++;
    -    origSetLoaded.call(mm, id);
    -  };
    -  mm.afterLoadModuleCode = function(id) {
    -    calls[2]++;
    -  };
    -
    -  var calledBack = false;
    -  var error = null;
    -
    -  mm.preloadModule('c', 2);
    -  assertFalse(
    -      'module "c" should not be loading yet', mm.isModuleLoading('c'));
    -  clock.tick(2);
    -  assertTrue(
    -      'module "c" should now be loading', mm.isModuleLoading('c'));
    -
    -  var d = mm.load('c');
    -  d.addCallback(function(ctx) {
    -    calledBack = true;
    -  });
    -  d.addErrback(function(err) {
    -    error = err;
    -  });
    -
    -  assertTrue(
    -      'module "c" should still be loading', mm.isModuleLoading('c'));
    -  clock.tick(5);
    -  assertFalse(
    -      'module "c" should be done loading', mm.isModuleLoading('c'));
    -  assertEquals(
    -      'beforeLoad should only be called once for "c"', 1, calls[0]);
    -  assertEquals(
    -      'setLoaded should only be called once for "c"', 1, calls[1]);
    -  assertEquals(
    -      'afterLoad should only be called once for "c"', 1, calls[2]);
    -
    -  assertTrue(calledBack);
    -  assertNull(error);
    -}
    -
    -
    -/**
    - * Tests that load doesn't trigger another load if a module is already
    - * preloading.
    - */
    -function testLoadMultipleWhenPreloading() {
    -  var mm = getModuleManager({'a': [], 'b': ['d'], 'c': [], 'd': []});
    -  mm.setLoader(createSuccessfulBatchLoader(mm));
    -  mm.setBatchModeEnabled(true);
    -
    -  var origSetLoaded = mm.setLoaded;
    -  var calls = {'a': [0, 0, 0], 'b': [0, 0, 0],
    -    'c': [0, 0, 0], 'd': [0, 0, 0]};
    -  mm.beforeLoadModuleCode = function(id) {
    -    calls[id][0]++;
    -  };
    -  mm.setLoaded = function(id) {
    -    calls[id][1]++;
    -    origSetLoaded.call(mm, id);
    -  };
    -  mm.afterLoadModuleCode = function(id) {
    -    calls[id][2]++;
    -  };
    -
    -  var calledBack = false;
    -  var error = null;
    -  var calledBack2 = false;
    -  var error2 = null;
    -  var calledBack3 = false;
    -  var error3 = null;
    -
    -  mm.preloadModule('c', 2);
    -  mm.preloadModule('d', 3);
    -  assertFalse(
    -      'module "c" should not be loading yet', mm.isModuleLoading('c'));
    -  assertFalse(
    -      'module "d" should not be loading yet', mm.isModuleLoading('d'));
    -  clock.tick(2);
    -  assertTrue(
    -      'module "c" should now be loading', mm.isModuleLoading('c'));
    -  clock.tick(1);
    -  assertTrue(
    -      'module "d" should now be loading', mm.isModuleLoading('d'));
    -
    -  var dMap = mm.loadMultiple(['a', 'b', 'c']);
    -  dMap['a'].addCallback(function(ctx) {
    -    calledBack = true;
    -  });
    -  dMap['a'].addErrback(function(err) {
    -    error = err;
    -  });
    -  dMap['b'].addCallback(function(ctx) {
    -    calledBack2 = true;
    -  });
    -  dMap['b'].addErrback(function(err) {
    -    error2 = err;
    -  });
    -  dMap['c'].addCallback(function(ctx) {
    -    calledBack3 = true;
    -  });
    -  dMap['c'].addErrback(function(err) {
    -    error3 = err;
    -  });
    -
    -  assertTrue(
    -      'module "a" should be loading', mm.isModuleLoading('a'));
    -  assertTrue(
    -      'module "b" should be loading', mm.isModuleLoading('b'));
    -  assertTrue(
    -      'module "c" should still be loading', mm.isModuleLoading('c'));
    -  clock.tick(4);
    -  assertTrue(calledBack3);
    -
    -  assertFalse(
    -      'module "c" should be done loading', mm.isModuleLoading('c'));
    -  assertTrue(
    -      'module "d" should still be loading', mm.isModuleLoading('d'));
    -  clock.tick(5);
    -  assertFalse(
    -      'module "d" should be done loading', mm.isModuleLoading('d'));
    -
    -  assertFalse(calledBack);
    -  assertFalse(calledBack2);
    -  assertTrue(
    -      'module "a" should still be loading', mm.isModuleLoading('a'));
    -  assertTrue(
    -      'module "b" should still be loading', mm.isModuleLoading('b'));
    -  clock.tick(7);
    -
    -  assertTrue(calledBack);
    -  assertTrue(calledBack2);
    -  assertFalse(
    -      'module "a" should be done loading', mm.isModuleLoading('a'));
    -  assertFalse(
    -      'module "b" should be done loading', mm.isModuleLoading('b'));
    -
    -  assertEquals(
    -      'beforeLoad should only be called once for "a"', 1, calls['a'][0]);
    -  assertEquals(
    -      'setLoaded should only be called once for "a"', 1, calls['a'][1]);
    -  assertEquals(
    -      'afterLoad should only be called once for "a"', 1, calls['a'][2]);
    -  assertEquals(
    -      'beforeLoad should only be called once for "b"', 1, calls['b'][0]);
    -  assertEquals(
    -      'setLoaded should only be called once for "b"', 1, calls['b'][1]);
    -  assertEquals(
    -      'afterLoad should only be called once for "b"', 1, calls['b'][2]);
    -  assertEquals(
    -      'beforeLoad should only be called once for "c"', 1, calls['c'][0]);
    -  assertEquals(
    -      'setLoaded should only be called once for "c"', 1, calls['c'][1]);
    -  assertEquals(
    -      'afterLoad should only be called once for "c"', 1, calls['c'][2]);
    -  assertEquals(
    -      'beforeLoad should only be called once for "d"', 1, calls['d'][0]);
    -  assertEquals(
    -      'setLoaded should only be called once for "d"', 1, calls['d'][1]);
    -  assertEquals(
    -      'afterLoad should only be called once for "d"', 1, calls['d'][2]);
    -
    -  assertNull(error);
    -  assertNull(error2);
    -  assertNull(error3);
    -}
    -
    -
    -/**
    - * Tests that the deferred is still called when loadMultiple loads modules
    - * that are already preloading.
    - */
    -function testLoadMultipleWhenPreloadingSameModules() {
    -  var mm = getModuleManager({'a': [], 'b': ['d'], 'c': [], 'd': []});
    -  mm.setLoader(createSuccessfulBatchLoader(mm));
    -  mm.setBatchModeEnabled(true);
    -
    -  var origSetLoaded = mm.setLoaded;
    -  var calls = {'c': [0, 0, 0], 'd': [0, 0, 0]};
    -  mm.beforeLoadModuleCode = function(id) {
    -    calls[id][0]++;
    -  };
    -  mm.setLoaded = function(id) {
    -    calls[id][1]++;
    -    origSetLoaded.call(mm, id);
    -  };
    -  mm.afterLoadModuleCode = function(id) {
    -    calls[id][2]++;
    -  };
    -
    -  var calledBack = false;
    -  var error = null;
    -  var calledBack2 = false;
    -  var error2 = null;
    -
    -  mm.preloadModule('c', 2);
    -  mm.preloadModule('d', 3);
    -  assertFalse(
    -      'module "c" should not be loading yet', mm.isModuleLoading('c'));
    -  assertFalse(
    -      'module "d" should not be loading yet', mm.isModuleLoading('d'));
    -  clock.tick(2);
    -  assertTrue(
    -      'module "c" should now be loading', mm.isModuleLoading('c'));
    -  clock.tick(1);
    -  assertTrue(
    -      'module "d" should now be loading', mm.isModuleLoading('d'));
    -
    -  var dMap = mm.loadMultiple(['c', 'd']);
    -  dMap['c'].addCallback(function(ctx) {
    -    calledBack = true;
    -  });
    -  dMap['c'].addErrback(function(err) {
    -    error = err;
    -  });
    -  dMap['d'].addCallback(function(ctx) {
    -    calledBack2 = true;
    -  });
    -  dMap['d'].addErrback(function(err) {
    -    error2 = err;
    -  });
    -
    -  assertTrue(
    -      'module "c" should still be loading', mm.isModuleLoading('c'));
    -  clock.tick(4);
    -  assertFalse(
    -      'module "c" should be done loading', mm.isModuleLoading('c'));
    -  assertTrue(
    -      'module "d" should still be loading', mm.isModuleLoading('d'));
    -  clock.tick(5);
    -  assertFalse(
    -      'module "d" should be done loading', mm.isModuleLoading('d'));
    -
    -  assertTrue(calledBack);
    -  assertTrue(calledBack2);
    -
    -  assertEquals(
    -      'beforeLoad should only be called once for "c"', 1, calls['c'][0]);
    -  assertEquals(
    -      'setLoaded should only be called once for "c"', 1, calls['c'][1]);
    -  assertEquals(
    -      'afterLoad should only be called once for "c"', 1, calls['c'][2]);
    -  assertEquals(
    -      'beforeLoad should only be called once for "d"', 1, calls['d'][0]);
    -  assertEquals(
    -      'setLoaded should only be called once for "d"', 1, calls['d'][1]);
    -  assertEquals(
    -      'afterLoad should only be called once for "d"', 1, calls['d'][2]);
    -
    -  assertNull(error);
    -  assertNull(error2);
    -}
    -
    -
    -/**
    - * Tests loading a module via load when the module is already
    - * loaded.  The deferred's callback should be called immediately.
    - */
    -function testLoadWhenLoaded() {
    -  var mm = getModuleManager({'a': [], 'b': [], 'c': []});
    -  mm.setLoader(createSuccessfulNonBatchLoader(mm));
    -
    -  var calledBack = false;
    -  var error = null;
    -
    -  mm.preloadModule('b', 2);
    -  clock.tick(10);
    -
    -  assertFalse(
    -      'module "b" should be done loading', mm.isModuleLoading('b'));
    -
    -  var d = mm.load('b');
    -  d.addCallback(function(ctx) {
    -    calledBack = true;
    -  });
    -  d.addErrback(function(err) {
    -    error = err;
    -  });
    -
    -  assertTrue(calledBack);
    -  assertNull(error);
    -}
    -
    -
    -/**
    - * Tests that the deferred's errbacks are called if the module fails to load.
    - */
    -function testLoadWithFailingModule() {
    -  var mm = getModuleManager({'a': [], 'b': [], 'c': []});
    -  mm.setLoader(createUnsuccessfulLoader(mm, 401));
    -  mm.registerCallback(goog.module.ModuleManager.CallbackType.ERROR,
    -      function(callbackType, id, cause) {
    -        assertEquals('Failure cause was not as expected',
    -            goog.module.ModuleManager.FailureType.UNAUTHORIZED,
    -            cause);
    -        firedLoadFailed = true;
    -      });
    -  var calledBack = false;
    -  var error = null;
    -
    -  var d = mm.load('a');
    -  d.addCallback(function(ctx) {
    -    calledBack = true;
    -  });
    -  d.addErrback(function(err) {
    -    error = err;
    -  });
    -
    -  assertFalse(calledBack);
    -  assertNull(error);
    -
    -  clock.tick(500);
    -
    -  assertFalse(calledBack);
    -
    -  // NOTE: Deferred always calls errbacks with an Error object.  For now the
    -  // module manager just passes the FailureType which gets set as the Error
    -  // object's message.
    -  assertEquals('Failure cause was not as expected',
    -      goog.module.ModuleManager.FailureType.UNAUTHORIZED,
    -      Number(error.message));
    -}
    -
    -
    -/**
    - * Tests that the deferred's errbacks are called if a module fails to load.
    - */
    -function testLoadMultipleWithFailingModule() {
    -  var mm = getModuleManager({'a': [], 'b': [], 'c': []});
    -  mm.setLoader(createUnsuccessfulLoader(mm, 401));
    -  mm.setBatchModeEnabled(true);
    -  mm.registerCallback(goog.module.ModuleManager.CallbackType.ERROR,
    -      function(callbackType, id, cause) {
    -        assertEquals('Failure cause was not as expected',
    -            goog.module.ModuleManager.FailureType.UNAUTHORIZED,
    -            cause);
    -      });
    -  var calledBack11 = false;
    -  var error11 = null;
    -  var calledBack12 = false;
    -  var error12 = null;
    -  var calledBack21 = false;
    -  var error21 = null;
    -  var calledBack22 = false;
    -  var error22 = null;
    -
    -  var dMap = mm.loadMultiple(['a', 'b']);
    -  dMap['a'].addCallback(function(ctx) {
    -    calledBack11 = true;
    -  });
    -  dMap['a'].addErrback(function(err) {
    -    error11 = err;
    -  });
    -  dMap['b'].addCallback(function(ctx) {
    -    calledBack12 = true;
    -  });
    -  dMap['b'].addErrback(function(err) {
    -    error12 = err;
    -  });
    -
    -  var dMap2 = mm.loadMultiple(['b', 'c']);
    -  dMap2['b'].addCallback(function(ctx) {
    -    calledBack21 = true;
    -  });
    -  dMap2['b'].addErrback(function(err) {
    -    error21 = err;
    -  });
    -  dMap2['c'].addCallback(function(ctx) {
    -    calledBack22 = true;
    -  });
    -  dMap2['c'].addErrback(function(err) {
    -    error22 = err;
    -  });
    -
    -  assertFalse(calledBack11);
    -  assertFalse(calledBack12);
    -  assertFalse(calledBack21);
    -  assertFalse(calledBack22);
    -  assertNull(error11);
    -  assertNull(error12);
    -  assertNull(error21);
    -  assertNull(error22);
    -
    -  clock.tick(5);
    -
    -  assertFalse(calledBack11);
    -  assertFalse(calledBack12);
    -  assertFalse(calledBack21);
    -  assertFalse(calledBack22);
    -
    -  // NOTE: Deferred always calls errbacks with an Error object.  For now the
    -  // module manager just passes the FailureType which gets set as the Error
    -  // object's message.
    -  assertEquals('Failure cause was not as expected',
    -      goog.module.ModuleManager.FailureType.UNAUTHORIZED,
    -      Number(error11.message));
    -  assertEquals('Failure cause was not as expected',
    -      goog.module.ModuleManager.FailureType.UNAUTHORIZED,
    -      Number(error12.message));
    -
    -  // The first deferred of the second load should be called since it asks for
    -  // one of the failed modules.
    -  assertEquals('Failure cause was not as expected',
    -      goog.module.ModuleManager.FailureType.UNAUTHORIZED,
    -      Number(error21.message));
    -
    -  // The last deferred should be dropped so it is neither called back nor an
    -  // error.
    -  assertFalse(calledBack22);
    -  assertNull(error22);
    -}
    -
    -
    -/**
    - * Tests that the right dependencies are cancelled on a loadMultiple failure.
    - */
    -function testLoadMultipleWithFailingModuleDependencies() {
    -  var mm = getModuleManager(
    -      {'a': [], 'b': [], 'c': ['b'], 'd': ['c'], 'e': []});
    -  mm.setLoader(createUnsuccessfulLoader(mm, 401));
    -  mm.setBatchModeEnabled(true);
    -  var cancelledIds = [];
    -
    -  mm.registerCallback(goog.module.ModuleManager.CallbackType.ERROR,
    -      function(callbackType, id, cause) {
    -        assertEquals('Failure cause was not as expected',
    -            goog.module.ModuleManager.FailureType.UNAUTHORIZED,
    -            cause);
    -        cancelledIds.push(id);
    -      });
    -  var calledBack11 = false;
    -  var error11 = null;
    -  var calledBack12 = false;
    -  var error12 = null;
    -  var calledBack21 = false;
    -  var error21 = null;
    -  var calledBack22 = false;
    -  var error22 = null;
    -  var calledBack23 = false;
    -  var error23 = null;
    -
    -  var dMap = mm.loadMultiple(['a', 'b']);
    -  dMap['a'].addCallback(function(ctx) {
    -    calledBack11 = true;
    -  });
    -  dMap['a'].addErrback(function(err) {
    -    error11 = err;
    -  });
    -  dMap['b'].addCallback(function(ctx) {
    -    calledBack12 = true;
    -  });
    -  dMap['b'].addErrback(function(err) {
    -    error12 = err;
    -  });
    -
    -  var dMap2 = mm.loadMultiple(['c', 'd', 'e']);
    -  dMap2['c'].addCallback(function(ctx) {
    -    calledBack21 = true;
    -  });
    -  dMap2['c'].addErrback(function(err) {
    -    error21 = err;
    -  });
    -  dMap2['d'].addCallback(function(ctx) {
    -    calledBack22 = true;
    -  });
    -  dMap2['d'].addErrback(function(err) {
    -    error22 = err;
    -  });
    -  dMap2['e'].addCallback(function(ctx) {
    -    calledBack23 = true;
    -  });
    -  dMap2['e'].addErrback(function(err) {
    -    error23 = err;
    -  });
    -
    -  assertFalse(calledBack11);
    -  assertFalse(calledBack12);
    -  assertFalse(calledBack21);
    -  assertFalse(calledBack22);
    -  assertFalse(calledBack23);
    -  assertNull(error11);
    -  assertNull(error12);
    -  assertNull(error21);
    -  assertNull(error22);
    -  assertNull(error23);
    -
    -  clock.tick(5);
    -
    -  assertFalse(calledBack11);
    -  assertFalse(calledBack12);
    -  assertFalse(calledBack21);
    -  assertFalse(calledBack22);
    -  assertFalse(calledBack23);
    -
    -  // NOTE: Deferred always calls errbacks with an Error object.  For now the
    -  // module manager just passes the FailureType which gets set as the Error
    -  // object's message.
    -  assertEquals('Failure cause was not as expected',
    -      goog.module.ModuleManager.FailureType.UNAUTHORIZED,
    -      Number(error11.message));
    -  assertEquals('Failure cause was not as expected',
    -      goog.module.ModuleManager.FailureType.UNAUTHORIZED,
    -      Number(error12.message));
    -
    -  // Check that among the failed modules, 'c' and 'd' are also cancelled
    -  // due to dependencies.
    -  assertTrue(goog.array.equals(['a', 'b', 'c', 'd'], cancelledIds.sort()));
    -}
    -
    -
    -/**
    - * Tests that when loading multiple modules, the input array is not modified
    - * when it has duplicates.
    - */
    -function testLoadMultipleWithDuplicates() {
    -  var mm = getModuleManager({'a': [], 'b': []});
    -  mm.setBatchModeEnabled(true);
    -  mm.setLoader(createSuccessfulBatchLoader(mm));
    -
    -  var listWithDuplicates = ['a', 'a', 'b'];
    -  mm.loadMultiple(listWithDuplicates);
    -  assertArrayEquals('loadMultiple should not modify its input',
    -      ['a', 'a', 'b'], listWithDuplicates);
    -}
    -
    -
    -/**
    - * Test loading dependencies transitively.
    - */
    -function testLoadingDepsInNonBatchMode1() {
    -  var mm = getModuleManager({
    -    'i': [],
    -    'j': [],
    -    'k': ['j'],
    -    'l': ['i', 'j', 'k']});
    -  mm.setLoader(createSuccessfulNonBatchLoader(mm));
    -
    -  mm.preloadModule('j');
    -  clock.tick(5);
    -  assertTrue('module "j" should be loaded', mm.isModuleLoaded('j'));
    -  assertFalse(
    -      'module "i" should not be loaded (1)', mm.isModuleLoaded('i'));
    -  assertFalse(
    -      'module "k" should not be loaded (1)', mm.isModuleLoaded('k'));
    -  assertFalse(
    -      'module "l" should not be loaded (1)', mm.isModuleLoaded('l'));
    -
    -  // When loading a module in non-batch mode, its dependencies should be
    -  // requested independently, and in dependency order.
    -  mm.preloadModule('l');
    -  clock.tick(5);
    -  assertTrue('module "i" should be loaded', mm.isModuleLoaded('i'));
    -  assertFalse(
    -      'module "k" should not be loaded (2)', mm.isModuleLoaded('k'));
    -  assertFalse(
    -      'module "l" should not be loaded (2)', mm.isModuleLoaded('l'));
    -  clock.tick(5);
    -  assertTrue('module "k" should be loaded', mm.isModuleLoaded('k'));
    -  assertFalse(
    -      'module "l" should not be loaded (3)', mm.isModuleLoaded('l'));
    -  clock.tick(5);
    -  assertTrue(
    -      'module "l" should be loaded', mm.isModuleLoaded('l'));
    -}
    -
    -
    -/**
    - * Test loading dependencies transitively and in dependency order.
    - */
    -function testLoadingDepsInNonBatchMode2() {
    -  var mm = getModuleManager({
    -    'h': [],
    -    'i': ['h'],
    -    'j': ['i'],
    -    'k': ['j'],
    -    'l': ['i', 'j', 'k'],
    -    'm': ['l']});
    -  mm.setLoader(createSuccessfulNonBatchLoader(mm));
    -
    -  // When loading a module in non-batch mode, its dependencies should be
    -  // requested independently, and in dependency order. The order in this
    -  // case should be h,i,j,k,l,m.
    -  mm.preloadModule('m');
    -  clock.tick(5);
    -  assertTrue('module "h" should be loaded', mm.isModuleLoaded('h'));
    -  assertFalse(
    -      'module "i" should not be loaded (1)', mm.isModuleLoaded('i'));
    -  assertFalse(
    -      'module "j" should not be loaded (1)', mm.isModuleLoaded('j'));
    -  assertFalse(
    -      'module "k" should not be loaded (1)', mm.isModuleLoaded('k'));
    -  assertFalse(
    -      'module "l" should not be loaded (1)', mm.isModuleLoaded('l'));
    -  assertFalse(
    -      'module "m" should not be loaded (1)', mm.isModuleLoaded('m'));
    -
    -  clock.tick(5);
    -  assertTrue('module "i" should be loaded', mm.isModuleLoaded('i'));
    -  assertFalse(
    -      'module "j" should not be loaded (2)', mm.isModuleLoaded('j'));
    -  assertFalse(
    -      'module "k" should not be loaded (2)', mm.isModuleLoaded('k'));
    -  assertFalse(
    -      'module "l" should not be loaded (2)', mm.isModuleLoaded('l'));
    -  assertFalse(
    -      'module "m" should not be loaded (2)', mm.isModuleLoaded('m'));
    -
    -  clock.tick(5);
    -  assertTrue('module "j" should be loaded', mm.isModuleLoaded('j'));
    -  assertFalse(
    -      'module "k" should not be loaded (3)', mm.isModuleLoaded('k'));
    -  assertFalse(
    -      'module "l" should not be loaded (3)', mm.isModuleLoaded('l'));
    -  assertFalse(
    -      'module "m" should not be loaded (3)', mm.isModuleLoaded('m'));
    -
    -  clock.tick(5);
    -  assertTrue('module "k" should be loaded', mm.isModuleLoaded('k'));
    -  assertFalse(
    -      'module "l" should not be loaded (4)', mm.isModuleLoaded('l'));
    -  assertFalse(
    -      'module "m" should not be loaded (4)', mm.isModuleLoaded('m'));
    -
    -  clock.tick(5);
    -  assertTrue('module "l" should be loaded', mm.isModuleLoaded('l'));
    -  assertFalse(
    -      'module "m" should not be loaded (5)', mm.isModuleLoaded('m'));
    -
    -  clock.tick(5);
    -  assertTrue('module "m" should be loaded', mm.isModuleLoaded('m'));
    -}
    -
    -function testLoadingDepsInBatchMode() {
    -  var mm = getModuleManager({
    -    'e': [],
    -    'f': [],
    -    'g': ['f'],
    -    'h': ['e', 'f', 'g']});
    -  mm.setLoader(createSuccessfulBatchLoader(mm));
    -  mm.setBatchModeEnabled(true);
    -
    -  mm.preloadModule('f');
    -  clock.tick(5);
    -  assertTrue('module "f" should be loaded', mm.isModuleLoaded('f'));
    -  assertFalse(
    -      'module "e" should not be loaded (1)', mm.isModuleLoaded('e'));
    -  assertFalse(
    -      'module "g" should not be loaded (1)', mm.isModuleLoaded('g'));
    -  assertFalse(
    -      'module "h" should not be loaded (1)', mm.isModuleLoaded('h'));
    -
    -  // When loading a module in batch mode, its not-yet-loaded dependencies
    -  // should be requested at the same time, and in dependency order.
    -  mm.preloadModule('h');
    -  clock.tick(5);
    -  assertTrue('module "e" should be loaded', mm.isModuleLoaded('e'));
    -  assertFalse(
    -      'module "g" should not be loaded (2)', mm.isModuleLoaded('g'));
    -  assertFalse(
    -      'module "h" should not be loaded (2)', mm.isModuleLoaded('h'));
    -  clock.tick(2);
    -  assertTrue(
    -      'module "g" should be loaded', mm.isModuleLoaded('g'));
    -  assertFalse(
    -      'module "h" should not be loaded (3)', mm.isModuleLoaded('h'));
    -  clock.tick(2);
    -  assertTrue(
    -      'module "h" should be loaded', mm.isModuleLoaded('h'));
    -}
    -
    -
    -/**
    - * Test unauthorized errors while loading modules.
    - */
    -function testUnauthorizedLoading() {
    -  var mm = getModuleManager({
    -    'm': [],
    -    'n': [],
    -    'o': ['n']});
    -  mm.setLoader(createUnsuccessfulLoader(mm, 401));
    -
    -  // Callback checks for an unauthorized error
    -  var firedLoadFailed = false;
    -  mm.registerCallback(goog.module.ModuleManager.CallbackType.ERROR,
    -      function(callbackType, id, cause) {
    -        assertEquals('Failure cause was not as expected',
    -                     goog.module.ModuleManager.FailureType.UNAUTHORIZED,
    -                     cause);
    -        firedLoadFailed = true;
    -      });
    -  mm.execOnLoad('o', function() {});
    -  assertTrue('module "o" should be loading', mm.isModuleLoading('o'));
    -  assertTrue('module "n" should be loading', mm.isModuleLoading('n'));
    -  clock.tick(5);
    -  assertTrue(
    -      'should have called unauthorized module callback', firedLoadFailed);
    -  assertFalse(
    -      'module "o" should not be loaded', mm.isModuleLoaded('o'));
    -  assertFalse(
    -      'module "o" should not be loading', mm.isModuleLoading('o'));
    -  assertFalse(
    -      'module "n" should not be loaded', mm.isModuleLoaded('n'));
    -  assertFalse(
    -      'module "n" should not be loading', mm.isModuleLoading('n'));
    -}
    -
    -
    -/**
    - * Test error loading modules which are retried.
    - */
    -function testErrorLoadingModule() {
    -  var mm = getModuleManager({
    -    'p': ['q'],
    -    'q': [],
    -    'r': ['q', 'p']});
    -  mm.setLoader(createUnsuccessfulLoader(mm, 500));
    -
    -  mm.preloadModule('r');
    -  clock.tick(4);
    -
    -  // A module request is now underway using the unsuccessful loader.
    -  // We substitute a successful loader for future module load requests.
    -  mm.setLoader(createSuccessfulNonBatchLoader(mm));
    -  clock.tick(1);
    -  assertFalse(
    -      'module "q" should not be loaded (1)', mm.isModuleLoaded('q'));
    -  assertFalse(
    -      'module "p" should not be loaded (1)', mm.isModuleLoaded('p'));
    -  assertFalse(
    -      'module "r" should not be loaded (1)', mm.isModuleLoaded('r'));
    -
    -  // Failed loads are automatically retried after a backOff.
    -  clock.tick(5 + mm.getBackOff_());
    -  assertTrue('module "q" should be loaded', mm.isModuleLoaded('q'));
    -  assertFalse(
    -      'module "p" should not be loaded (2)', mm.isModuleLoaded('p'));
    -  assertFalse(
    -      'module "r" should not be loaded (2)', mm.isModuleLoaded('r'));
    -
    -  // A successful load decrements the backOff.
    -  clock.tick(5);
    -  assertTrue('module "p" should be loaded', mm.isModuleLoaded('p'));
    -  assertFalse(
    -      'module "r" should not be loaded (3)', mm.isModuleLoaded('r'));
    -  clock.tick(5);
    -  assertTrue(
    -      'module "r" should be loaded', mm.isModuleLoaded('r'));
    -}
    -
    -
    -/**
    - * Tests error loading modules which are retried.
    - */
    -function testErrorLoadingModule_batchMode() {
    -  var mm = getModuleManager({
    -    'p': ['q'],
    -    'q': [],
    -    'r': ['q', 'p']});
    -  mm.setLoader(createUnsuccessfulBatchLoader(mm, 500));
    -  mm.setBatchModeEnabled(true);
    -
    -  mm.preloadModule('r');
    -  clock.tick(4);
    -
    -  // A module request is now underway using the unsuccessful loader.
    -  // We substitute a successful loader for future module load requests.
    -  mm.setLoader(createSuccessfulBatchLoader(mm));
    -  clock.tick(1);
    -  assertFalse(
    -      'module "q" should not be loaded (1)', mm.isModuleLoaded('q'));
    -  assertFalse(
    -      'module "p" should not be loaded (1)', mm.isModuleLoaded('p'));
    -  assertFalse(
    -      'module "r" should not be loaded (1)', mm.isModuleLoaded('r'));
    -
    -  // Failed loads are automatically retried after a backOff.
    -  clock.tick(5 + mm.getBackOff_());
    -  assertTrue('module "q" should be loaded', mm.isModuleLoaded('q'));
    -  clock.tick(2);
    -  assertTrue(
    -      'module "p" should not be loaded (2)', mm.isModuleLoaded('p'));
    -  clock.tick(2);
    -  assertTrue(
    -      'module "r" should not be loaded (2)', mm.isModuleLoaded('r'));
    -}
    -
    -
    -/**
    - * Test consecutive errors in loading modules.
    - */
    -function testConsecutiveErrors() {
    -  var mm = getModuleManager({'s': []});
    -  mm.setLoader(createUnsuccessfulLoader(mm, 500));
    -
    -  // Register an error callback for consecutive failures.
    -  var firedLoadFailed = false;
    -  mm.registerCallback(goog.module.ModuleManager.CallbackType.ERROR,
    -      function(callbackType, id, cause) {
    -        assertEquals('Failure cause was not as expected',
    -            goog.module.ModuleManager.FailureType.CONSECUTIVE_FAILURES,
    -            cause);
    -        firedLoadFailed = true;
    -      });
    -
    -  mm.preloadModule('s');
    -  assertFalse(
    -      'module "s" should not be loaded (0)', mm.isModuleLoaded('s'));
    -
    -  // Fail twice.
    -  for (var i = 0; i < 2; i++) {
    -    clock.tick(5 + mm.getBackOff_());
    -    assertFalse(
    -        'module "s" should not be loaded (1)', mm.isModuleLoaded('s'));
    -    assertFalse(
    -        'should not fire failed callback (1)', firedLoadFailed);
    -  }
    -
    -  // Fail a third time and check that the callback is fired.
    -  clock.tick(5 + mm.getBackOff_());
    -  assertFalse(
    -      'module "s" should not be loaded (2)', mm.isModuleLoaded('s'));
    -  assertTrue(
    -      'should have fired failed callback', firedLoadFailed);
    -
    -  // Check that it doesn't attempt to load the module anymore after it has
    -  // failed.
    -  var triedLoad = false;
    -  mm.setLoader({
    -    loadModules: function(ids, moduleInfoMap, opt_successFn, opt_errFn) {
    -      triedLoad = true;
    -    }});
    -
    -  // Also reset the failed callback flag and make sure it isn't called
    -  // again.
    -  firedLoadFailed = false;
    -  clock.tick(10 + mm.getBackOff_());
    -  assertFalse(
    -      'module "s" should not be loaded (3)', mm.isModuleLoaded('s'));
    -  assertFalse('No more loads should have been tried', triedLoad);
    -  assertFalse('The load failed callback should be fired only once',
    -      firedLoadFailed);
    -}
    -
    -
    -/**
    - * Test loading errors due to old code.
    - */
    -function testOldCodeGoneError() {
    -  var mm = getModuleManager({'s': []});
    -  mm.setLoader(createUnsuccessfulLoader(mm, 410));
    -
    -  // Callback checks for an old code failure
    -  var firedLoadFailed = false;
    -  mm.registerCallback(goog.module.ModuleManager.CallbackType.ERROR,
    -      function(callbackType, id, cause) {
    -        assertEquals('Failure cause was not as expected',
    -            goog.module.ModuleManager.FailureType.OLD_CODE_GONE,
    -            cause);
    -        firedLoadFailed = true;
    -      });
    -
    -  mm.preloadModule('s', 0);
    -  assertFalse(
    -      'module "s" should not be loaded (0)', mm.isModuleLoaded('s'));
    -  clock.tick(5);
    -  assertFalse(
    -      'module "s" should not be loaded (1)', mm.isModuleLoaded('s'));
    -  assertTrue(
    -      'should have called old code gone callback', firedLoadFailed);
    -}
    -
    -
    -/**
    - * Test timeout.
    - */
    -function testTimeout() {
    -  var mm = getModuleManager({'s': []});
    -  mm.setLoader(createTimeoutLoader(mm));
    -
    -  // Callback checks for timeout
    -  var firedTimeout = false;
    -  mm.registerCallback(goog.module.ModuleManager.CallbackType.ERROR,
    -      function(callbackType, id, cause) {
    -        assertEquals('Failure cause was not as expected',
    -            goog.module.ModuleManager.FailureType.TIMEOUT,
    -            cause);
    -        firedTimeout = true;
    -      });
    -
    -  mm.preloadModule('s', 0);
    -  assertFalse(
    -      'module "s" should not be loaded (0)', mm.isModuleLoaded('s'));
    -  clock.tick(5);
    -  assertFalse(
    -      'module "s" should not be loaded (1)', mm.isModuleLoaded('s'));
    -  assertTrue(
    -      'should have called timeout callback', firedTimeout);
    -}
    -
    -
    -/**
    - * Tests that an error during execOnLoad will trigger the error callback.
    - */
    -function testExecOnLoadError() {
    -  // Expect two callbacks, each of which will be called with callback type
    -  // ERROR, the right module id and failure type INIT_ERROR.
    -  var errorCallback1 = goog.testing.createFunctionMock('callback1');
    -  errorCallback1(goog.module.ModuleManager.CallbackType.ERROR, 'b',
    -      goog.module.ModuleManager.FailureType.INIT_ERROR);
    -
    -  var errorCallback2 = goog.testing.createFunctionMock('callback2');
    -  errorCallback2(goog.module.ModuleManager.CallbackType.ERROR, 'b',
    -      goog.module.ModuleManager.FailureType.INIT_ERROR);
    -
    -  errorCallback1.$replay();
    -  errorCallback2.$replay();
    -
    -  var mm = new goog.module.ModuleManager();
    -  mm.setLoader(createSuccessfulNonBatchLoader(mm));
    -
    -  // Register the first callback before setting the module info map.
    -  mm.registerCallback(goog.module.ModuleManager.CallbackType.ERROR,
    -      errorCallback1);
    -
    -  mm.setAllModuleInfo({'a': [], 'b': [], 'c': []});
    -
    -  // Register the second callback after setting the module info map.
    -  mm.registerCallback(goog.module.ModuleManager.CallbackType.ERROR,
    -      errorCallback2);
    -
    -  var execOnLoadBCalled = false;
    -  mm.execOnLoad('b', function() {
    -    execOnLoadBCalled = true;
    -    throw new Error();
    -  });
    -
    -  assertThrows(function() {
    -    clock.tick(5);
    -  });
    -
    -  assertTrue('execOnLoad should have been called on module b.',
    -      execOnLoadBCalled);
    -  errorCallback1.$verify();
    -  errorCallback2.$verify();
    -}
    -
    -
    -/**
    - * Tests that an error during execOnLoad will trigger the error callback.
    - * Uses setAllModuleInfoString rather than setAllModuleInfo.
    - */
    -function testExecOnLoadErrorModuleInfoString() {
    -  // Expect a callback to be called with callback type ERROR, the right module
    -  // id and failure type INIT_ERROR.
    -  var errorCallback = goog.testing.createFunctionMock('callback');
    -  errorCallback(goog.module.ModuleManager.CallbackType.ERROR, 'b',
    -      goog.module.ModuleManager.FailureType.INIT_ERROR);
    -
    -  errorCallback.$replay();
    -
    -  var mm = new goog.module.ModuleManager();
    -  mm.setLoader(createSuccessfulNonBatchLoader(mm));
    -
    -  // Register the first callback before setting the module info map.
    -  mm.registerCallback(goog.module.ModuleManager.CallbackType.ERROR,
    -      errorCallback);
    -
    -  mm.setAllModuleInfoString('a/b/c');
    -
    -  var execOnLoadBCalled = false;
    -  mm.execOnLoad('b', function() {
    -    execOnLoadBCalled = true;
    -    throw new Error();
    -  });
    -
    -  assertThrows(function() {
    -    clock.tick(5);
    -  });
    -
    -  assertTrue('execOnLoad should have been called on module b.',
    -      execOnLoadBCalled);
    -  errorCallback.$verify();
    -}
    -
    -
    -/**
    - * Make sure ModuleInfo objects in moduleInfoMap_ get disposed.
    - */
    -function testDispose() {
    -  var mm = getModuleManager({'a': [], 'b': [], 'c': []});
    -
    -  var moduleInfoA = mm.getModuleInfo('a');
    -  assertNotNull(moduleInfoA);
    -  var moduleInfoB = mm.getModuleInfo('b');
    -  assertNotNull(moduleInfoB);
    -  var moduleInfoC = mm.getModuleInfo('c');
    -  assertNotNull(moduleInfoC);
    -
    -  mm.dispose();
    -  assertTrue(moduleInfoA.isDisposed());
    -  assertTrue(moduleInfoB.isDisposed());
    -  assertTrue(moduleInfoC.isDisposed());
    -}
    -
    -function testDependencyOrderingWithSimpleDeps() {
    -  var mm = getModuleManager({
    -    'a': ['b', 'c'],
    -    'b': ['d'],
    -    'c': ['e', 'f'],
    -    'd': [],
    -    'e': [],
    -    'f': []
    -  });
    -  var ids = mm.getNotYetLoadedTransitiveDepIds_('a');
    -  assertDependencyOrder(ids, mm);
    -  assertArrayEquals(['d', 'e', 'f', 'b', 'c', 'a'], ids);
    -}
    -
    -function testDependencyOrderingWithCommonDepsInDeps() {
    -  // Tests to make sure that if dependencies of the root are loaded before
    -  // their common dependencies.
    -  var mm = getModuleManager({
    -    'a': ['b', 'c'],
    -    'b': ['d'],
    -    'c': ['d'],
    -    'd': []
    -  });
    -  var ids = mm.getNotYetLoadedTransitiveDepIds_('a');
    -  assertDependencyOrder(ids, mm);
    -  assertArrayEquals(['d', 'b', 'c', 'a'], ids);
    -}
    -
    -function testDependencyOrderingWithCommonDepsInRoot1() {
    -  // Tests the case where a dependency of the root depends on another
    -  // dependency of the root.  Irregardless of ordering in the root's
    -  // deps.
    -  var mm = getModuleManager({
    -    'a': ['b', 'c'],
    -    'b': ['c'],
    -    'c': []
    -  });
    -  var ids = mm.getNotYetLoadedTransitiveDepIds_('a');
    -  assertDependencyOrder(ids, mm);
    -  assertArrayEquals(['c', 'b', 'a'], ids);
    -}
    -
    -function testDependencyOrderingWithCommonDepsInRoot2() {
    -  // Tests the case where a dependency of the root depends on another
    -  // dependency of the root.  Irregardless of ordering in the root's
    -  // deps.
    -  var mm = getModuleManager({
    -    'a': ['b', 'c'],
    -    'b': [],
    -    'c': ['b']
    -  });
    -  var ids = mm.getNotYetLoadedTransitiveDepIds_('a');
    -  assertDependencyOrder(ids, mm);
    -  assertArrayEquals(['b', 'c', 'a'], ids);
    -}
    -
    -function testDependencyOrderingWithGmailExample() {
    -  // Real dependency graph taken from gmail.
    -  var mm = getModuleManager({
    -    's': ['dp', 'ml', 'md'],
    -    'dp': ['a'],
    -    'ml': ['ld', 'm'],
    -    'ld': ['a'],
    -    'm': ['ad', 'mh', 'n'],
    -    'md': ['mh', 'ld'],
    -    'a': [],
    -    'mh': [],
    -    'ad': [],
    -    'n': []
    -  });
    -
    -  mm.setLoaded('a');
    -  mm.setLoaded('m');
    -  mm.setLoaded('n');
    -  mm.setLoaded('ad');
    -  mm.setLoaded('mh');
    -
    -  var ids = mm.getNotYetLoadedTransitiveDepIds_('s');
    -  assertDependencyOrder(ids, mm);
    -  assertArrayEquals(['ld', 'dp', 'ml', 'md', 's'], ids);
    -}
    -
    -function assertDependencyOrder(list, mm) {
    -  var seen = {};
    -  for (var i = 0; i < list.length; i++) {
    -    var id = list[i];
    -    seen[id] = true;
    -    var deps = mm.getModuleInfo(id).getDependencies();
    -    for (var j = 0; j < deps.length; j++) {
    -      var dep = deps[j];
    -      assertTrue('Unresolved dependency [' + dep + '] for [' + id + '].',
    -          seen[dep] || mm.getModuleInfo(dep).isLoaded());
    -    }
    -  }
    -}
    -
    -function testRegisterInitializationCallback() {
    -  var initCalled = 0;
    -  var mm = getModuleManager({'a': [], 'b': [], 'c': []});
    -  mm.setLoader(createSuccessfulNonBatchLoaderWithRegisterInitCallback(mm,
    -      function() {
    -        ++initCalled;
    -      }));
    -  execOnLoad_(mm);
    -  // execOnLoad_ loads modules a and c
    -  assertTrue(initCalled == 2);
    -}
    -
    -function createSuccessfulNonBatchLoaderWithRegisterInitCallback(
    -    moduleMgr, fn) {
    -  return {
    -    loadModules: function(ids, moduleInfoMap, opt_successFn, opt_errFn,
    -        opt_timeoutFn) {
    -      moduleMgr.beforeLoadModuleCode(ids[0]);
    -      moduleMgr.registerInitializationCallback(fn);
    -      setTimeout(function() {
    -        moduleMgr.setLoaded(ids[0]);
    -        moduleMgr.afterLoadModuleCode(ids[0]);
    -        if (opt_successFn) {
    -          opt_successFn();
    -        }
    -      }, 5);
    -    }};
    -}
    -
    -function testSetModuleConstructor() {
    -  var initCalled = 0;
    -  var mm = getModuleManager({'a': [], 'b': [], 'c': []});
    -  var info = {
    -    'a': { ctor: AModule, count: 0 },
    -    'b': { ctor: BModule, count: 0 },
    -    'c': { ctor: CModule, count: 0 }
    -  };
    -  function AModule() {
    -    ++info['a'].count;
    -    goog.module.BaseModule.call(this);
    -  }
    -  goog.inherits(AModule, goog.module.BaseModule);
    -  function BModule() {
    -    ++info['b'].count;
    -    goog.module.BaseModule.call(this);
    -  }
    -  goog.inherits(BModule, goog.module.BaseModule);
    -  function CModule() {
    -    ++info['c'].count;
    -    goog.module.BaseModule.call(this);
    -  }
    -  goog.inherits(CModule, goog.module.BaseModule);
    -
    -  mm.setLoader(createSuccessfulNonBatchLoaderWithConstructor(mm, info));
    -  execOnLoad_(mm);
    -  assertTrue(info['a'].count == 1);
    -  assertTrue(info['b'].count == 0);
    -  assertTrue(info['c'].count == 1);
    -  assertTrue(mm.getModuleInfo('a').getModule() instanceof AModule);
    -  assertTrue(mm.getModuleInfo('c').getModule() instanceof CModule);
    -}
    -
    -
    -/**
    - * Tests that a call to load the loading module during module initialization
    - * doesn't trigger a second load.
    - */
    -function testLoadWhenInitializing() {
    -  var mm = getModuleManager({'a': []});
    -  mm.setLoader(createSuccessfulNonBatchLoader(mm));
    -
    -  var info = {
    -    'a': { ctor: AModule, count: 0 }
    -  };
    -  function AModule() {
    -    ++info['a'].count;
    -    goog.module.BaseModule.call(this);
    -  }
    -  goog.inherits(AModule, goog.module.BaseModule);
    -  AModule.prototype.initialize = function() {
    -    mm.load('a');
    -  };
    -  mm.setLoader(createSuccessfulNonBatchLoaderWithConstructor(mm, info));
    -  mm.preloadModule('a');
    -  clock.tick(5);
    -  assertEquals(info['a'].count, 1);
    -}
    -
    -function testErrorInEarlyCallback() {
    -  var errback = goog.testing.recordFunction();
    -  var callback = goog.testing.recordFunction();
    -  var mm = getModuleManager({'a': [], 'b': ['a']});
    -  mm.getModuleInfo('a').registerEarlyCallback(goog.functions.error('error'));
    -  mm.getModuleInfo('a').registerCallback(callback);
    -  mm.getModuleInfo('a').registerErrback(errback);
    -
    -  mm.setLoader(createSuccessfulNonBatchLoaderWithConstructor(
    -      mm, createModulesFor('a', 'b')));
    -  mm.preloadModule('b');
    -  var e = assertThrows(function() {
    -    clock.tick(5);
    -  });
    -
    -  assertEquals('error', e.message);
    -  assertEquals(0, callback.getCallCount());
    -  assertEquals(1, errback.getCallCount());
    -  assertEquals(goog.module.ModuleManager.FailureType.INIT_ERROR,
    -      errback.getLastCall().getArguments()[0]);
    -  assertTrue(mm.getModuleInfo('a').isLoaded());
    -  assertFalse(mm.getModuleInfo('b').isLoaded());
    -
    -  clock.tick(5);
    -  assertTrue(mm.getModuleInfo('b').isLoaded());
    -}
    -
    -function testErrorInNormalCallback() {
    -  var earlyCallback = goog.testing.recordFunction();
    -  var errback = goog.testing.recordFunction();
    -  var mm = getModuleManager({'a': [], 'b': ['a']});
    -  mm.getModuleInfo('a').registerEarlyCallback(earlyCallback);
    -  mm.getModuleInfo('a').registerEarlyCallback(goog.functions.error('error'));
    -  mm.getModuleInfo('a').registerErrback(errback);
    -
    -  mm.setLoader(createSuccessfulNonBatchLoaderWithConstructor(
    -      mm, createModulesFor('a', 'b')));
    -  mm.preloadModule('b');
    -  var e = assertThrows(function() {
    -    clock.tick(10);
    -  });
    -  clock.tick(10);
    -
    -  assertEquals('error', e.message);
    -  assertEquals(1, errback.getCallCount());
    -  assertEquals(goog.module.ModuleManager.FailureType.INIT_ERROR,
    -      errback.getLastCall().getArguments()[0]);
    -  assertTrue(mm.getModuleInfo('a').isLoaded());
    -  assertTrue(mm.getModuleInfo('b').isLoaded());
    -}
    -
    -function testErrorInErrback() {
    -  var mm = getModuleManager({'a': [], 'b': ['a']});
    -  mm.getModuleInfo('a').registerCallback(goog.functions.error('error1'));
    -  mm.getModuleInfo('a').registerErrback(goog.functions.error('error2'));
    -
    -  mm.setLoader(createSuccessfulNonBatchLoaderWithConstructor(
    -      mm, createModulesFor('a', 'b')));
    -  mm.preloadModule('a');
    -  var e = assertThrows(function() {
    -    clock.tick(10);
    -  });
    -  assertEquals('error1', e.message);
    -  var e = assertThrows(function() {
    -    clock.tick(10);
    -  });
    -  assertEquals('error2', e.message);
    -  assertTrue(mm.getModuleInfo('a').isLoaded());
    -}
    -
    -function createModulesFor(var_args) {
    -  var result = {};
    -  for (var i = 0; i < arguments.length; i++) {
    -    var key = arguments[i];
    -    result[key] = {ctor: goog.module.BaseModule};
    -  }
    -  return result;
    -}
    -
    -function createSuccessfulNonBatchLoaderWithConstructor(moduleMgr, info) {
    -  return {
    -    loadModules: function(ids, moduleInfoMap, opt_successFn, opt_errFn,
    -        opt_timeoutFn) {
    -      setTimeout(function() {
    -        moduleMgr.beforeLoadModuleCode(ids[0]);
    -        moduleMgr.setModuleConstructor(info[ids[0]].ctor);
    -        moduleMgr.setLoaded(ids[0]);
    -        moduleMgr.afterLoadModuleCode(ids[0]);
    -        if (opt_successFn) {
    -          opt_successFn();
    -        }
    -      }, 5);
    -    }};
    -}
    -
    -function testInitCallbackInBaseModule() {
    -  var mm = new goog.module.ModuleManager();
    -  var called = false;
    -  var context;
    -  mm.registerInitializationCallback(function(mcontext) {
    -    called = true;
    -    context = mcontext;
    -  });
    -  mm.setAllModuleInfo({'a': [], 'b': ['a']});
    -  assertTrue('Base initialization not called', called);
    -  assertNull('Context should still be null', context);
    -
    -  var mm = new goog.module.ModuleManager();
    -  called = false;
    -  mm.registerInitializationCallback(function(mcontext) {
    -    called = true;
    -    context = mcontext;
    -  });
    -  var appContext = {};
    -  mm.setModuleContext(appContext);
    -  assertTrue('Base initialization not called after setModuleContext', called);
    -  assertEquals('Did not receive module context', appContext, context);
    -}
    -
    -function testSetAllModuleInfoString() {
    -  var info = 'base/one:0/two:0/three:0,1,2/four:0,3/five:';
    -  var mm = new goog.module.ModuleManager();
    -  mm.setAllModuleInfoString(info);
    -
    -  assertNotNull('Base should exist', mm.getModuleInfo('base'));
    -  assertNotNull('One should exist', mm.getModuleInfo('one'));
    -  assertNotNull('Two should exist', mm.getModuleInfo('two'));
    -  assertNotNull('Three should exist', mm.getModuleInfo('three'));
    -  assertNotNull('Four should exist', mm.getModuleInfo('four'));
    -  assertNotNull('Five should exist', mm.getModuleInfo('five'));
    -
    -  assertArrayEquals(['base', 'one', 'two'],
    -      mm.getModuleInfo('three').getDependencies());
    -  assertArrayEquals(['base', 'three'],
    -      mm.getModuleInfo('four').getDependencies());
    -  assertArrayEquals([],
    -      mm.getModuleInfo('five').getDependencies());
    -}
    -
    -function testSetAllModuleInfoStringWithEmptyString() {
    -  var mm = new goog.module.ModuleManager();
    -  var called = false;
    -  var context;
    -  mm.registerInitializationCallback(function(mcontext) {
    -    called = true;
    -    context = mcontext;
    -  });
    -  mm.setAllModuleInfoString('');
    -  assertTrue('Initialization not called', called);
    -}
    -
    -function testBackOffAmounts() {
    -  var mm = new goog.module.ModuleManager();
    -  assertEquals(0, mm.getBackOff_());
    -
    -  mm.consecutiveFailures_++;
    -  assertEquals(5000, mm.getBackOff_());
    -
    -  mm.consecutiveFailures_++;
    -  assertEquals(20000, mm.getBackOff_());
    -}
    -
    -
    -/**
    - * Tests that the IDLE callbacks are executed for active->idle transitions
    - * after setAllModuleInfoString with currently loading modules.
    - */
    -function testIdleCallbackWithInitialModules() {
    -  var callback = goog.testing.recordFunction();
    -
    -  var mm = new goog.module.ModuleManager();
    -  mm.setAllModuleInfoString('a', ['a']);
    -  mm.registerCallback(
    -      goog.module.ModuleManager.CallbackType.IDLE, callback);
    -
    -  assertTrue(mm.isActive());
    -
    -  mm.beforeLoadModuleCode('a');
    -
    -  assertEquals(0, callback.getCallCount());
    -
    -  mm.setLoaded('a');
    -  mm.afterLoadModuleCode('a');
    -
    -  assertFalse(mm.isActive());
    -
    -  assertEquals(1, callback.getCallCount());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/module/testdata/modA_1.js b/src/database/third_party/closure-library/closure/goog/module/testdata/modA_1.js
    deleted file mode 100644
    index 8a013b9aea4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/module/testdata/modA_1.js
    +++ /dev/null
    @@ -1,26 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -// All Rights Reserved
    -
    -/**
    - * @fileoverview File #1 of module A.
    - */
    -
    -goog.provide('goog.module.testdata.modA_1');
    -
    -
    -goog.setTestOnly('goog.module.testdata.modA_1');
    -
    -if (window.modA1Loaded) throw Error('modA_1 loaded twice');
    -window.modA1Loaded = true;
    diff --git a/src/database/third_party/closure-library/closure/goog/module/testdata/modA_2.js b/src/database/third_party/closure-library/closure/goog/module/testdata/modA_2.js
    deleted file mode 100644
    index 06c0828f1a2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/module/testdata/modA_2.js
    +++ /dev/null
    @@ -1,29 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -// All Rights Reserved
    -
    -/**
    - * @fileoverview File #2 of module A.
    - */
    -
    -goog.provide('goog.module.testdata.modA_2');
    -
    -goog.setTestOnly('goog.module.testdata.modA_2');
    -
    -goog.require('goog.module.ModuleManager');
    -
    -if (window.modA2Loaded) throw Error('modA_2 loaded twice');
    -window.modA2Loaded = true;
    -
    -goog.module.ModuleManager.getInstance().setLoaded('modA');
    diff --git a/src/database/third_party/closure-library/closure/goog/module/testdata/modB_1.js b/src/database/third_party/closure-library/closure/goog/module/testdata/modB_1.js
    deleted file mode 100644
    index 308913753bb..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/module/testdata/modB_1.js
    +++ /dev/null
    @@ -1,33 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -// All Rights Reserved
    -
    -/**
    - * @fileoverview File #1 of module B.
    - */
    -
    -goog.provide('goog.module.testdata.modB_1');
    -
    -goog.setTestOnly('goog.module.testdata.modB_1');
    -
    -goog.require('goog.module.ModuleManager');
    -
    -function throwErrorInModuleB() {
    -  throw Error();
    -}
    -
    -if (window.modB1Loaded) throw Error('modB_1 loaded twice');
    -window.modB1Loaded = true;
    -
    -goog.module.ModuleManager.getInstance().setLoaded('modB');
    diff --git a/src/database/third_party/closure-library/closure/goog/net/browserchannel.js b/src/database/third_party/closure-library/closure/goog/net/browserchannel.js
    deleted file mode 100644
    index 9ebfe93b5be..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/browserchannel.js
    +++ /dev/null
    @@ -1,2765 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Definition of the BrowserChannel class.  A BrowserChannel
    - * simulates a bidirectional socket over HTTP. It is the basis of the
    - * Gmail Chat IM connections to the server.
    - *
    - * Typical usage will look like
    - *  var handler = [handler object];
    - *  var channel = new BrowserChannel(clientVersion);
    - *  channel.setHandler(handler);
    - *  channel.connect('channel/test', 'channel/bind');
    - *
    - * See goog.net.BrowserChannel.Handler for the handler interface.
    - *
    - */
    -
    -
    -goog.provide('goog.net.BrowserChannel');
    -goog.provide('goog.net.BrowserChannel.Error');
    -goog.provide('goog.net.BrowserChannel.Event');
    -goog.provide('goog.net.BrowserChannel.Handler');
    -goog.provide('goog.net.BrowserChannel.LogSaver');
    -goog.provide('goog.net.BrowserChannel.QueuedMap');
    -goog.provide('goog.net.BrowserChannel.ServerReachability');
    -goog.provide('goog.net.BrowserChannel.ServerReachabilityEvent');
    -goog.provide('goog.net.BrowserChannel.Stat');
    -goog.provide('goog.net.BrowserChannel.StatEvent');
    -goog.provide('goog.net.BrowserChannel.State');
    -goog.provide('goog.net.BrowserChannel.TimingEvent');
    -
    -goog.require('goog.Uri');
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.debug.TextFormatter');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.json');
    -goog.require('goog.json.EvalJsonProcessor');
    -goog.require('goog.log');
    -goog.require('goog.net.BrowserTestChannel');
    -goog.require('goog.net.ChannelDebug');
    -goog.require('goog.net.ChannelRequest');
    -goog.require('goog.net.XhrIo');
    -goog.require('goog.net.tmpnetwork');
    -goog.require('goog.object');
    -goog.require('goog.string');
    -goog.require('goog.structs');
    -goog.require('goog.structs.CircularBuffer');
    -
    -
    -
    -/**
    - * Encapsulates the logic for a single BrowserChannel.
    - *
    - * @param {string=} opt_clientVersion An application-specific version number
    - *        that is sent to the server when connected.
    - * @param {Array<string>=} opt_firstTestResults Previously determined results
    - *        of the first browser channel test.
    - * @param {boolean=} opt_secondTestResults Previously determined results
    - *        of the second browser channel test.
    - * @constructor
    - */
    -goog.net.BrowserChannel = function(opt_clientVersion, opt_firstTestResults,
    -    opt_secondTestResults) {
    -  /**
    -   * The application specific version that is passed to the server.
    -   * @type {?string}
    -   * @private
    -   */
    -  this.clientVersion_ = opt_clientVersion || null;
    -
    -  /**
    -   * The current state of the BrowserChannel. It should be one of the
    -   * goog.net.BrowserChannel.State constants.
    -   * @type {!goog.net.BrowserChannel.State}
    -   * @private
    -   */
    -  this.state_ = goog.net.BrowserChannel.State.INIT;
    -
    -  /**
    -   * An array of queued maps that need to be sent to the server.
    -   * @type {Array<goog.net.BrowserChannel.QueuedMap>}
    -   * @private
    -   */
    -  this.outgoingMaps_ = [];
    -
    -  /**
    -   * An array of dequeued maps that we have either received a non-successful
    -   * response for, or no response at all, and which therefore may or may not
    -   * have been received by the server.
    -   * @type {Array<goog.net.BrowserChannel.QueuedMap>}
    -   * @private
    -   */
    -  this.pendingMaps_ = [];
    -
    -  /**
    -   * The channel debug used for browserchannel logging
    -   * @type {!goog.net.ChannelDebug}
    -   * @private
    -   */
    -  this.channelDebug_ = new goog.net.ChannelDebug();
    -
    -  /**
    -   * Parser for a response payload. Defaults to use
    -   * {@code goog.json.unsafeParse}. The parser should return an array.
    -   * @type {!goog.string.Parser}
    -   * @private
    -   */
    -  this.parser_ = new goog.json.EvalJsonProcessor(null, true);
    -
    -  /**
    -   * An array of results for the first browser channel test call.
    -   * @type {Array<string>}
    -   * @private
    -   */
    -  this.firstTestResults_ = opt_firstTestResults || null;
    -
    -  /**
    -   * The results of the second browser channel test. True implies the
    -   * connection is buffered, False means unbuffered, null means that
    -   * the results are not available.
    -   * @private
    -   */
    -  this.secondTestResults_ = goog.isDefAndNotNull(opt_secondTestResults) ?
    -      opt_secondTestResults : null;
    -};
    -
    -
    -
    -/**
    - * Simple container class for a (mapId, map) pair.
    - * @param {number} mapId The id for this map.
    - * @param {Object|goog.structs.Map} map The map itself.
    - * @param {Object=} opt_context The context associated with the map.
    - * @constructor
    - * @final
    - */
    -goog.net.BrowserChannel.QueuedMap = function(mapId, map, opt_context) {
    -  /**
    -   * The id for this map.
    -   * @type {number}
    -   */
    -  this.mapId = mapId;
    -
    -  /**
    -   * The map itself.
    -   * @type {Object|goog.structs.Map}
    -   */
    -  this.map = map;
    -
    -  /**
    -   * The context for the map.
    -   * @type {Object}
    -   */
    -  this.context = opt_context || null;
    -};
    -
    -
    -/**
    - * Extra HTTP headers to add to all the requests sent to the server.
    - * @type {Object}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.extraHeaders_ = null;
    -
    -
    -/**
    - * Extra parameters to add to all the requests sent to the server.
    - * @type {Object}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.extraParams_ = null;
    -
    -
    -/**
    - * The current ChannelRequest object for the forwardchannel.
    - * @type {goog.net.ChannelRequest?}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.forwardChannelRequest_ = null;
    -
    -
    -/**
    - * The ChannelRequest object for the backchannel.
    - * @type {goog.net.ChannelRequest?}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.backChannelRequest_ = null;
    -
    -
    -/**
    - * The relative path (in the context of the the page hosting the browser
    - * channel) for making requests to the server.
    - * @type {?string}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.path_ = null;
    -
    -
    -/**
    - * The absolute URI for the forwardchannel request.
    - * @type {goog.Uri}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.forwardChannelUri_ = null;
    -
    -
    -/**
    - * The absolute URI for the backchannel request.
    - * @type {goog.Uri}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.backChannelUri_ = null;
    -
    -
    -/**
    - * A subdomain prefix for using a subdomain in IE for the backchannel
    - * requests.
    - * @type {?string}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.hostPrefix_ = null;
    -
    -
    -/**
    - * Whether we allow the use of a subdomain in IE for the backchannel requests.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.allowHostPrefix_ = true;
    -
    -
    -/**
    - * The next id to use for the RID (request identifier) parameter. This
    - * identifier uniquely identifies the forward channel request.
    - * @type {number}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.nextRid_ = 0;
    -
    -
    -/**
    - * The id to use for the next outgoing map. This identifier uniquely
    - * identifies a sent map.
    - * @type {number}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.nextMapId_ = 0;
    -
    -
    -/**
    - * Whether to fail forward-channel requests after one try, or after a few tries.
    - * @type {boolean}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.failFast_ = false;
    -
    -
    -/**
    - * The handler that receive callbacks for state changes and data.
    - * @type {goog.net.BrowserChannel.Handler}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.handler_ = null;
    -
    -
    -/**
    - * Timer identifier for asynchronously making a forward channel request.
    - * @type {?number}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.forwardChannelTimerId_ = null;
    -
    -
    -/**
    - * Timer identifier for asynchronously making a back channel request.
    - * @type {?number}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.backChannelTimerId_ = null;
    -
    -
    -/**
    - * Timer identifier for the timer that waits for us to retry the backchannel in
    - * the case where it is dead and no longer receiving data.
    - * @type {?number}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.deadBackChannelTimerId_ = null;
    -
    -
    -/**
    - * The BrowserTestChannel object which encapsulates the logic for determining
    - * interesting network conditions about the client.
    - * @type {goog.net.BrowserTestChannel?}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.connectionTest_ = null;
    -
    -
    -/**
    - * Whether the client's network conditions can support chunked responses.
    - * @type {?boolean}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.useChunked_ = null;
    -
    -
    -/**
    - * Whether chunked mode is allowed. In certain debugging situations, it's
    - * useful to disable this.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.allowChunkedMode_ = true;
    -
    -
    -/**
    - * The array identifier of the last array received from the server for the
    - * backchannel request.
    - * @type {number}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.lastArrayId_ = -1;
    -
    -
    -/**
    - * The array identifier of the last array sent by the server that we know about.
    - * @type {number}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.lastPostResponseArrayId_ = -1;
    -
    -
    -/**
    - * The last status code received.
    - * @type {number}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.lastStatusCode_ = -1;
    -
    -
    -/**
    - * Number of times we have retried the current forward channel request.
    - * @type {number}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.forwardChannelRetryCount_ = 0;
    -
    -
    -/**
    - * Number of times it a row that we have retried the current back channel
    - * request and received no data.
    - * @type {number}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.backChannelRetryCount_ = 0;
    -
    -
    -/**
    - * The attempt id for the current back channel request. Starts at 1 and
    - * increments for each reconnect. The server uses this to log if our connection
    - * is flaky or not.
    - * @type {number}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.backChannelAttemptId_;
    -
    -
    -/**
    - * The base part of the time before firing next retry request. Default is 5
    - * seconds. Note that a random delay is added (see {@link retryDelaySeedMs_})
    - * for all retries, and linear backoff is applied to the sum for subsequent
    - * retries.
    - * @type {number}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.baseRetryDelayMs_ = 5 * 1000;
    -
    -
    -/**
    - * A random time between 0 and this number of MS is added to the
    - * {@link baseRetryDelayMs_}. Default is 10 seconds.
    - * @type {number}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.retryDelaySeedMs_ = 10 * 1000;
    -
    -
    -/**
    - * Maximum number of attempts to connect to the server for forward channel
    - * requests. Defaults to 2.
    - * @type {number}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.forwardChannelMaxRetries_ = 2;
    -
    -
    -/**
    - * The timeout in milliseconds for a forward channel request. Defaults to 20
    - * seconds. Note that part of this timeout can be randomized.
    - * @type {number}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.forwardChannelRequestTimeoutMs_ = 20 * 1000;
    -
    -
    -/**
    - * A throttle time in ms for readystatechange events for the backchannel.
    - * Useful for throttling when ready state is INTERACTIVE (partial data).
    - *
    - * This throttle is useful if the server sends large data chunks down the
    - * backchannel.  It prevents examining XHR partial data on every
    - * readystate change event.  This is useful because large chunks can
    - * trigger hundreds of readystatechange events, each of which takes ~5ms
    - * or so to handle, in turn making the UI unresponsive for a significant period.
    - *
    - * If set to zero no throttle is used.
    - * @type {number}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.readyStateChangeThrottleMs_ = 0;
    -
    -
    -/**
    - * Whether cross origin requests are supported for the browser channel.
    - *
    - * See {@link goog.net.XhrIo#setWithCredentials}.
    - * @type {boolean}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.supportsCrossDomainXhrs_ = false;
    -
    -
    -/**
    - * The latest protocol version that this class supports. We request this version
    - * from the server when opening the connection. Should match
    - * com.google.net.browserchannel.BrowserChannel.LATEST_CHANNEL_VERSION.
    - * @type {number}
    - */
    -goog.net.BrowserChannel.LATEST_CHANNEL_VERSION = 8;
    -
    -
    -/**
    - * The channel version that we negotiated with the server for this session.
    - * Starts out as the version we request, and then is changed to the negotiated
    - * version after the initial open.
    - * @type {number}
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.channelVersion_ =
    -    goog.net.BrowserChannel.LATEST_CHANNEL_VERSION;
    -
    -
    -/**
    - * Enum type for the browser channel state machine.
    - * @enum {number}
    - */
    -goog.net.BrowserChannel.State = {
    -  /** The channel is closed. */
    -  CLOSED: 0,
    -
    -  /** The channel has been initialized but hasn't yet initiated a connection. */
    -  INIT: 1,
    -
    -  /** The channel is in the process of opening a connection to the server. */
    -  OPENING: 2,
    -
    -  /** The channel is open. */
    -  OPENED: 3
    -};
    -
    -
    -/**
    - * The timeout in milliseconds for a forward channel request.
    - * @type {number}
    - */
    -goog.net.BrowserChannel.FORWARD_CHANNEL_RETRY_TIMEOUT = 20 * 1000;
    -
    -
    -/**
    - * Maximum number of attempts to connect to the server for back channel
    - * requests.
    - * @type {number}
    - */
    -goog.net.BrowserChannel.BACK_CHANNEL_MAX_RETRIES = 3;
    -
    -
    -/**
    - * A number in MS of how long we guess the maxmium amount of time a round trip
    - * to the server should take. In the future this could be substituted with a
    - * real measurement of the RTT.
    - * @type {number}
    - */
    -goog.net.BrowserChannel.RTT_ESTIMATE = 3 * 1000;
    -
    -
    -/**
    - * When retrying for an inactive channel, we will multiply the total delay by
    - * this number.
    - * @type {number}
    - */
    -goog.net.BrowserChannel.INACTIVE_CHANNEL_RETRY_FACTOR = 2;
    -
    -
    -/**
    - * Enum type for identifying a BrowserChannel error.
    - * @enum {number}
    - */
    -goog.net.BrowserChannel.Error = {
    -  /** Value that indicates no error has occurred. */
    -  OK: 0,
    -
    -  /** An error due to a request failing. */
    -  REQUEST_FAILED: 2,
    -
    -  /** An error due to the user being logged out. */
    -  LOGGED_OUT: 4,
    -
    -  /** An error due to server response which contains no data. */
    -  NO_DATA: 5,
    -
    -  /** An error due to a server response indicating an unknown session id */
    -  UNKNOWN_SESSION_ID: 6,
    -
    -  /** An error due to a server response requesting to stop the channel. */
    -  STOP: 7,
    -
    -  /** A general network error. */
    -  NETWORK: 8,
    -
    -  /** An error due to the channel being blocked by a network administrator. */
    -  BLOCKED: 9,
    -
    -  /** An error due to bad data being returned from the server. */
    -  BAD_DATA: 10,
    -
    -  /** An error due to a response that doesn't start with the magic cookie. */
    -  BAD_RESPONSE: 11,
    -
    -  /** ActiveX is blocked by the machine's admin settings. */
    -  ACTIVE_X_BLOCKED: 12
    -};
    -
    -
    -/**
    - * Internal enum type for the two browser channel channel types.
    - * @enum {number}
    - * @private
    - */
    -goog.net.BrowserChannel.ChannelType_ = {
    -  FORWARD_CHANNEL: 1,
    -
    -  BACK_CHANNEL: 2
    -};
    -
    -
    -/**
    - * The maximum number of maps that can be sent in one POST. Should match
    - * com.google.net.browserchannel.BrowserChannel.MAX_MAPS_PER_REQUEST.
    - * @type {number}
    - * @private
    - */
    -goog.net.BrowserChannel.MAX_MAPS_PER_REQUEST_ = 1000;
    -
    -
    -/**
    - * Singleton event target for firing stat events
    - * @type {goog.events.EventTarget}
    - * @private
    - */
    -goog.net.BrowserChannel.statEventTarget_ = new goog.events.EventTarget();
    -
    -
    -/**
    - * Events fired by BrowserChannel and associated objects
    - * @const
    - */
    -goog.net.BrowserChannel.Event = {};
    -
    -
    -/**
    - * Stat Event that fires when things of interest happen that may be useful for
    - * applications to know about for stats or debugging purposes. This event fires
    - * on the EventTarget returned by getStatEventTarget.
    - */
    -goog.net.BrowserChannel.Event.STAT_EVENT = 'statevent';
    -
    -
    -
    -/**
    - * Event class for goog.net.BrowserChannel.Event.STAT_EVENT
    - *
    - * @param {goog.events.EventTarget} eventTarget The stat event target for
    -       the browser channel.
    - * @param {goog.net.BrowserChannel.Stat} stat The stat.
    - * @constructor
    - * @extends {goog.events.Event}
    - * @final
    - */
    -goog.net.BrowserChannel.StatEvent = function(eventTarget, stat) {
    -  goog.events.Event.call(this, goog.net.BrowserChannel.Event.STAT_EVENT,
    -      eventTarget);
    -
    -  /**
    -   * The stat
    -   * @type {goog.net.BrowserChannel.Stat}
    -   */
    -  this.stat = stat;
    -
    -};
    -goog.inherits(goog.net.BrowserChannel.StatEvent, goog.events.Event);
    -
    -
    -/**
    - * An event that fires when POST requests complete successfully, indicating
    - * the size of the POST and the round trip time.
    - * This event fires on the EventTarget returned by getStatEventTarget.
    - */
    -goog.net.BrowserChannel.Event.TIMING_EVENT = 'timingevent';
    -
    -
    -
    -/**
    - * Event class for goog.net.BrowserChannel.Event.TIMING_EVENT
    - *
    - * @param {goog.events.EventTarget} target The stat event target for
    -       the browser channel.
    - * @param {number} size The number of characters in the POST data.
    - * @param {number} rtt The total round trip time from POST to response in MS.
    - * @param {number} retries The number of times the POST had to be retried.
    - * @constructor
    - * @extends {goog.events.Event}
    - * @final
    - */
    -goog.net.BrowserChannel.TimingEvent = function(target, size, rtt, retries) {
    -  goog.events.Event.call(this, goog.net.BrowserChannel.Event.TIMING_EVENT,
    -      target);
    -
    -  /**
    -   * @type {number}
    -   */
    -  this.size = size;
    -
    -  /**
    -   * @type {number}
    -   */
    -  this.rtt = rtt;
    -
    -  /**
    -   * @type {number}
    -   */
    -  this.retries = retries;
    -
    -};
    -goog.inherits(goog.net.BrowserChannel.TimingEvent, goog.events.Event);
    -
    -
    -/**
    - * The type of event that occurs every time some information about how reachable
    - * the server is is discovered.
    - */
    -goog.net.BrowserChannel.Event.SERVER_REACHABILITY_EVENT =
    -    'serverreachability';
    -
    -
    -/**
    - * Types of events which reveal information about the reachability of the
    - * server.
    - * @enum {number}
    - */
    -goog.net.BrowserChannel.ServerReachability = {
    -  REQUEST_MADE: 1,
    -  REQUEST_SUCCEEDED: 2,
    -  REQUEST_FAILED: 3,
    -  BACK_CHANNEL_ACTIVITY: 4
    -};
    -
    -
    -
    -/**
    - * Event class for goog.net.BrowserChannel.Event.SERVER_REACHABILITY_EVENT.
    - *
    - * @param {goog.events.EventTarget} target The stat event target for
    -       the browser channel.
    - * @param {goog.net.BrowserChannel.ServerReachability} reachabilityType The
    - *     reachability event type.
    - * @constructor
    - * @extends {goog.events.Event}
    - * @final
    - */
    -goog.net.BrowserChannel.ServerReachabilityEvent = function(target,
    -    reachabilityType) {
    -  goog.events.Event.call(this,
    -      goog.net.BrowserChannel.Event.SERVER_REACHABILITY_EVENT, target);
    -
    -  /**
    -   * @type {goog.net.BrowserChannel.ServerReachability}
    -   */
    -  this.reachabilityType = reachabilityType;
    -};
    -goog.inherits(goog.net.BrowserChannel.ServerReachabilityEvent,
    -    goog.events.Event);
    -
    -
    -/**
    - * Enum that identifies events for statistics that are interesting to track.
    - * TODO(user) - Change name not to use Event or use EventTarget
    - * @enum {number}
    - */
    -goog.net.BrowserChannel.Stat = {
    -  /** Event indicating a new connection attempt. */
    -  CONNECT_ATTEMPT: 0,
    -
    -  /** Event indicating a connection error due to a general network problem. */
    -  ERROR_NETWORK: 1,
    -
    -  /**
    -   * Event indicating a connection error that isn't due to a general network
    -   * problem.
    -   */
    -  ERROR_OTHER: 2,
    -
    -  /** Event indicating the start of test stage one. */
    -  TEST_STAGE_ONE_START: 3,
    -
    -
    -  /** Event indicating the channel is blocked by a network administrator. */
    -  CHANNEL_BLOCKED: 4,
    -
    -  /** Event indicating the start of test stage two. */
    -  TEST_STAGE_TWO_START: 5,
    -
    -  /** Event indicating the first piece of test data was received. */
    -  TEST_STAGE_TWO_DATA_ONE: 6,
    -
    -  /**
    -   * Event indicating that the second piece of test data was received and it was
    -   * recieved separately from the first.
    -   */
    -  TEST_STAGE_TWO_DATA_TWO: 7,
    -
    -  /** Event indicating both pieces of test data were received simultaneously. */
    -  TEST_STAGE_TWO_DATA_BOTH: 8,
    -
    -  /** Event indicating stage one of the test request failed. */
    -  TEST_STAGE_ONE_FAILED: 9,
    -
    -  /** Event indicating stage two of the test request failed. */
    -  TEST_STAGE_TWO_FAILED: 10,
    -
    -  /**
    -   * Event indicating that a buffering proxy is likely between the client and
    -   * the server.
    -   */
    -  PROXY: 11,
    -
    -  /**
    -   * Event indicating that no buffering proxy is likely between the client and
    -   * the server.
    -   */
    -  NOPROXY: 12,
    -
    -  /** Event indicating an unknown SID error. */
    -  REQUEST_UNKNOWN_SESSION_ID: 13,
    -
    -  /** Event indicating a bad status code was received. */
    -  REQUEST_BAD_STATUS: 14,
    -
    -  /** Event indicating incomplete data was received */
    -  REQUEST_INCOMPLETE_DATA: 15,
    -
    -  /** Event indicating bad data was received */
    -  REQUEST_BAD_DATA: 16,
    -
    -  /** Event indicating no data was received when data was expected. */
    -  REQUEST_NO_DATA: 17,
    -
    -  /** Event indicating a request timeout. */
    -  REQUEST_TIMEOUT: 18,
    -
    -  /**
    -   * Event indicating that the server never received our hanging GET and so it
    -   * is being retried.
    -   */
    -  BACKCHANNEL_MISSING: 19,
    -
    -  /**
    -   * Event indicating that we have determined that our hanging GET is not
    -   * receiving data when it should be. Thus it is dead dead and will be retried.
    -   */
    -  BACKCHANNEL_DEAD: 20,
    -
    -  /**
    -   * The browser declared itself offline during the lifetime of a request, or
    -   * was offline when a request was initially made.
    -   */
    -  BROWSER_OFFLINE: 21,
    -
    -  /** ActiveX is blocked by the machine's admin settings. */
    -  ACTIVE_X_BLOCKED: 22
    -};
    -
    -
    -/**
    - * The normal response for forward channel requests.
    - * Used only before version 8 of the protocol.
    - * @type {string}
    - */
    -goog.net.BrowserChannel.MAGIC_RESPONSE_COOKIE = 'y2f%';
    -
    -
    -/**
    - * A guess at a cutoff at which to no longer assume the backchannel is dead
    - * when we are slow to receive data. Number in bytes.
    - *
    - * Assumption: The worst bandwidth we work on is 50 kilobits/sec
    - * 50kbits/sec * (1 byte / 8 bits) * 6 sec dead backchannel timeout
    - * @type {number}
    - */
    -goog.net.BrowserChannel.OUTSTANDING_DATA_BACKCHANNEL_RETRY_CUTOFF = 37500;
    -
    -
    -/**
    - * Returns the browserchannel logger.
    - *
    - * @return {!goog.net.ChannelDebug} The channel debug object.
    - */
    -goog.net.BrowserChannel.prototype.getChannelDebug = function() {
    -  return this.channelDebug_;
    -};
    -
    -
    -/**
    - * Set the browserchannel logger.
    - * TODO(user): Add interface for channel loggers or remove this function.
    - *
    - * @param {goog.net.ChannelDebug} channelDebug The channel debug object.
    - */
    -goog.net.BrowserChannel.prototype.setChannelDebug = function(
    -    channelDebug) {
    -  if (goog.isDefAndNotNull(channelDebug)) {
    -    this.channelDebug_ = channelDebug;
    -  }
    -};
    -
    -
    -/**
    - * Allows the application to set an execution hooks for when BrowserChannel
    - * starts processing requests. This is useful to track timing or logging
    - * special information. The function takes no parameters and return void.
    - * @param {Function} startHook  The function for the start hook.
    - */
    -goog.net.BrowserChannel.setStartThreadExecutionHook = function(startHook) {
    -  goog.net.BrowserChannel.startExecutionHook_ = startHook;
    -};
    -
    -
    -/**
    - * Allows the application to set an execution hooks for when BrowserChannel
    - * stops processing requests. This is useful to track timing or logging
    - * special information. The function takes no parameters and return void.
    - * @param {Function} endHook  The function for the end hook.
    - */
    -goog.net.BrowserChannel.setEndThreadExecutionHook = function(endHook) {
    -  goog.net.BrowserChannel.endExecutionHook_ = endHook;
    -};
    -
    -
    -/**
    - * Application provided execution hook for the start hook.
    - *
    - * @type {Function}
    - * @private
    - */
    -goog.net.BrowserChannel.startExecutionHook_ = function() { };
    -
    -
    -/**
    - * Application provided execution hook for the end hook.
    - *
    - * @type {Function}
    - * @private
    - */
    -goog.net.BrowserChannel.endExecutionHook_ = function() { };
    -
    -
    -/**
    - * Instantiates a ChannelRequest with the given parameters. Overidden in tests.
    - *
    - * @param {goog.net.BrowserChannel|goog.net.BrowserTestChannel} channel
    - *     The BrowserChannel that owns this request.
    - * @param {goog.net.ChannelDebug} channelDebug A ChannelDebug to use for
    - *     logging.
    - * @param {string=} opt_sessionId  The session id for the channel.
    - * @param {string|number=} opt_requestId  The request id for this request.
    - * @param {number=} opt_retryId  The retry id for this request.
    - * @return {!goog.net.ChannelRequest} The created channel request.
    - */
    -goog.net.BrowserChannel.createChannelRequest = function(channel, channelDebug,
    -    opt_sessionId, opt_requestId, opt_retryId) {
    -  return new goog.net.ChannelRequest(
    -      channel,
    -      channelDebug,
    -      opt_sessionId,
    -      opt_requestId,
    -      opt_retryId);
    -};
    -
    -
    -/**
    - * Starts the channel. This initiates connections to the server.
    - *
    - * @param {string} testPath  The path for the test connection.
    - * @param {string} channelPath  The path for the channel connection.
    - * @param {Object=} opt_extraParams  Extra parameter keys and values to add to
    - *     the requests.
    - * @param {string=} opt_oldSessionId  Session ID from a previous session.
    - * @param {number=} opt_oldArrayId  The last array ID from a previous session.
    - */
    -goog.net.BrowserChannel.prototype.connect = function(testPath, channelPath,
    -    opt_extraParams, opt_oldSessionId, opt_oldArrayId) {
    -  this.channelDebug_.debug('connect()');
    -
    -  goog.net.BrowserChannel.notifyStatEvent(
    -      goog.net.BrowserChannel.Stat.CONNECT_ATTEMPT);
    -
    -  this.path_ = channelPath;
    -  this.extraParams_ = opt_extraParams || {};
    -
    -  // Attach parameters about the previous session if reconnecting.
    -  if (opt_oldSessionId && goog.isDef(opt_oldArrayId)) {
    -    this.extraParams_['OSID'] = opt_oldSessionId;
    -    this.extraParams_['OAID'] = opt_oldArrayId;
    -  }
    -
    -  this.connectTest_(testPath);
    -};
    -
    -
    -/**
    - * Disconnects and closes the channel.
    - */
    -goog.net.BrowserChannel.prototype.disconnect = function() {
    -  this.channelDebug_.debug('disconnect()');
    -
    -  this.cancelRequests_();
    -
    -  if (this.state_ == goog.net.BrowserChannel.State.OPENED) {
    -    var rid = this.nextRid_++;
    -    var uri = this.forwardChannelUri_.clone();
    -    uri.setParameterValue('SID', this.sid_);
    -    uri.setParameterValue('RID', rid);
    -    uri.setParameterValue('TYPE', 'terminate');
    -
    -    // Add the reconnect parameters.
    -    this.addAdditionalParams_(uri);
    -
    -    var request = goog.net.BrowserChannel.createChannelRequest(
    -        this, this.channelDebug_, this.sid_, rid);
    -    request.sendUsingImgTag(uri);
    -  }
    -
    -  this.onClose_();
    -};
    -
    -
    -/**
    - * Returns the session id of the channel. Only available after the
    - * channel has been opened.
    - * @return {string} Session ID.
    - */
    -goog.net.BrowserChannel.prototype.getSessionId = function() {
    -  return this.sid_;
    -};
    -
    -
    -/**
    - * Starts the test channel to determine network conditions.
    - *
    - * @param {string} testPath  The relative PATH for the test connection.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.connectTest_ = function(testPath) {
    -  this.channelDebug_.debug('connectTest_()');
    -  if (!this.okToMakeRequest_()) {
    -    return; // channel is cancelled
    -  }
    -  this.connectionTest_ = new goog.net.BrowserTestChannel(
    -      this, this.channelDebug_);
    -  this.connectionTest_.setExtraHeaders(this.extraHeaders_);
    -  this.connectionTest_.setParser(this.parser_);
    -  this.connectionTest_.connect(testPath);
    -};
    -
    -
    -/**
    - * Starts the regular channel which is run after the test channel is complete.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.connectChannel_ = function() {
    -  this.channelDebug_.debug('connectChannel_()');
    -  this.ensureInState_(goog.net.BrowserChannel.State.INIT,
    -      goog.net.BrowserChannel.State.CLOSED);
    -  this.forwardChannelUri_ =
    -      this.getForwardChannelUri(/** @type {string} */ (this.path_));
    -  this.ensureForwardChannel_();
    -};
    -
    -
    -/**
    - * Cancels all outstanding requests.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.cancelRequests_ = function() {
    -  if (this.connectionTest_) {
    -    this.connectionTest_.abort();
    -    this.connectionTest_ = null;
    -  }
    -
    -  if (this.backChannelRequest_) {
    -    this.backChannelRequest_.cancel();
    -    this.backChannelRequest_ = null;
    -  }
    -
    -  if (this.backChannelTimerId_) {
    -    goog.global.clearTimeout(this.backChannelTimerId_);
    -    this.backChannelTimerId_ = null;
    -  }
    -
    -  this.clearDeadBackchannelTimer_();
    -
    -  if (this.forwardChannelRequest_) {
    -    this.forwardChannelRequest_.cancel();
    -    this.forwardChannelRequest_ = null;
    -  }
    -
    -  if (this.forwardChannelTimerId_) {
    -    goog.global.clearTimeout(this.forwardChannelTimerId_);
    -    this.forwardChannelTimerId_ = null;
    -  }
    -};
    -
    -
    -/**
    - * Returns the extra HTTP headers to add to all the requests sent to the server.
    - *
    - * @return {Object} The HTTP headers, or null.
    - */
    -goog.net.BrowserChannel.prototype.getExtraHeaders = function() {
    -  return this.extraHeaders_;
    -};
    -
    -
    -/**
    - * Sets extra HTTP headers to add to all the requests sent to the server.
    - *
    - * @param {Object} extraHeaders The HTTP headers, or null.
    - */
    -goog.net.BrowserChannel.prototype.setExtraHeaders = function(extraHeaders) {
    -  this.extraHeaders_ = extraHeaders;
    -};
    -
    -
    -/**
    - * Sets the throttle for handling onreadystatechange events for the request.
    - *
    - * @param {number} throttle The throttle in ms.  A value of zero indicates
    - *     no throttle.
    - */
    -goog.net.BrowserChannel.prototype.setReadyStateChangeThrottle = function(
    -    throttle) {
    -  this.readyStateChangeThrottleMs_ = throttle;
    -};
    -
    -
    -/**
    - * Sets whether cross origin requests are supported for the browser channel.
    - *
    - * Setting this allows the creation of requests to secondary domains and
    - * sends XHRs with the CORS withCredentials bit set to true.
    - *
    - * In order for cross-origin requests to work, the server will also need to set
    - * CORS response headers as per:
    - * https://developer.mozilla.org/en-US/docs/HTTP_access_control
    - *
    - * See {@link goog.net.XhrIo#setWithCredentials}.
    - * @param {boolean} supportCrossDomain Whether cross domain XHRs are supported.
    - */
    -goog.net.BrowserChannel.prototype.setSupportsCrossDomainXhrs = function(
    -    supportCrossDomain) {
    -  this.supportsCrossDomainXhrs_ = supportCrossDomain;
    -};
    -
    -
    -/**
    - * Returns the handler used for channel callback events.
    - *
    - * @return {goog.net.BrowserChannel.Handler} The handler.
    - */
    -goog.net.BrowserChannel.prototype.getHandler = function() {
    -  return this.handler_;
    -};
    -
    -
    -/**
    - * Sets the handler used for channel callback events.
    - * @param {goog.net.BrowserChannel.Handler} handler The handler to set.
    - */
    -goog.net.BrowserChannel.prototype.setHandler = function(handler) {
    -  this.handler_ = handler;
    -};
    -
    -
    -/**
    - * Returns whether the channel allows the use of a subdomain. There may be
    - * cases where this isn't allowed.
    - * @return {boolean} Whether a host prefix is allowed.
    - */
    -goog.net.BrowserChannel.prototype.getAllowHostPrefix = function() {
    -  return this.allowHostPrefix_;
    -};
    -
    -
    -/**
    - * Sets whether the channel allows the use of a subdomain. There may be cases
    - * where this isn't allowed, for example, logging in with troutboard where
    - * using a subdomain causes Apache to force the user to authenticate twice.
    - * @param {boolean} allowHostPrefix Whether a host prefix is allowed.
    - */
    -goog.net.BrowserChannel.prototype.setAllowHostPrefix =
    -    function(allowHostPrefix) {
    -  this.allowHostPrefix_ = allowHostPrefix;
    -};
    -
    -
    -/**
    - * Returns whether the channel is buffered or not. This state is valid for
    - * querying only after the test connection has completed. This may be
    - * queried in the goog.net.BrowserChannel.okToMakeRequest() callback.
    - * A channel may be buffered if the test connection determines that
    - * a chunked response could not be sent down within a suitable time.
    - * @return {boolean} Whether the channel is buffered.
    - */
    -goog.net.BrowserChannel.prototype.isBuffered = function() {
    -  return !this.useChunked_;
    -};
    -
    -
    -/**
    - * Returns whether chunked mode is allowed. In certain debugging situations,
    - * it's useful for the application to have a way to disable chunked mode for a
    - * user.
    -
    - * @return {boolean} Whether chunked mode is allowed.
    - */
    -goog.net.BrowserChannel.prototype.getAllowChunkedMode =
    -    function() {
    -  return this.allowChunkedMode_;
    -};
    -
    -
    -/**
    - * Sets whether chunked mode is allowed. In certain debugging situations, it's
    - * useful for the application to have a way to disable chunked mode for a user.
    - * @param {boolean} allowChunkedMode  Whether chunked mode is allowed.
    - */
    -goog.net.BrowserChannel.prototype.setAllowChunkedMode =
    -    function(allowChunkedMode) {
    -  this.allowChunkedMode_ = allowChunkedMode;
    -};
    -
    -
    -/**
    - * Sends a request to the server. The format of the request is a Map data
    - * structure of key/value pairs. These maps are then encoded in a format
    - * suitable for the wire and then reconstituted as a Map data structure that
    - * the server can process.
    - * @param {Object|goog.structs.Map} map  The map to send.
    - * @param {?Object=} opt_context The context associated with the map.
    - */
    -goog.net.BrowserChannel.prototype.sendMap = function(map, opt_context) {
    -  if (this.state_ == goog.net.BrowserChannel.State.CLOSED) {
    -    throw Error('Invalid operation: sending map when state is closed');
    -  }
    -
    -  // We can only send 1000 maps per POST, but typically we should never have
    -  // that much to send, so warn if we exceed that (we still send all the maps).
    -  if (this.outgoingMaps_.length ==
    -      goog.net.BrowserChannel.MAX_MAPS_PER_REQUEST_) {
    -    // severe() is temporary so that we get these uploaded and can figure out
    -    // what's causing them. Afterwards can change to warning().
    -    this.channelDebug_.severe(
    -        'Already have ' + goog.net.BrowserChannel.MAX_MAPS_PER_REQUEST_ +
    -        ' queued maps upon queueing ' + goog.json.serialize(map));
    -  }
    -
    -  this.outgoingMaps_.push(
    -      new goog.net.BrowserChannel.QueuedMap(this.nextMapId_++, map,
    -                                            opt_context));
    -  if (this.state_ == goog.net.BrowserChannel.State.OPENING ||
    -      this.state_ == goog.net.BrowserChannel.State.OPENED) {
    -    this.ensureForwardChannel_();
    -  }
    -};
    -
    -
    -/**
    - * When set to true, this changes the behavior of the forward channel so it
    - * will not retry requests; it will fail after one network failure, and if
    - * there was already one network failure, the request will fail immediately.
    - * @param {boolean} failFast  Whether or not to fail fast.
    - */
    -goog.net.BrowserChannel.prototype.setFailFast = function(failFast) {
    -  this.failFast_ = failFast;
    -  this.channelDebug_.info('setFailFast: ' + failFast);
    -  if ((this.forwardChannelRequest_ || this.forwardChannelTimerId_) &&
    -      this.forwardChannelRetryCount_ > this.getForwardChannelMaxRetries()) {
    -    this.channelDebug_.info(
    -        'Retry count ' + this.forwardChannelRetryCount_ +
    -        ' > new maxRetries ' + this.getForwardChannelMaxRetries() +
    -        '. Fail immediately!');
    -    if (this.forwardChannelRequest_) {
    -      this.forwardChannelRequest_.cancel();
    -      // Go through the standard onRequestComplete logic to expose the max-retry
    -      // failure in the standard way.
    -      this.onRequestComplete(this.forwardChannelRequest_);
    -    } else {  // i.e., this.forwardChannelTimerId_
    -      goog.global.clearTimeout(this.forwardChannelTimerId_);
    -      this.forwardChannelTimerId_ = null;
    -      // The error code from the last failed request is gone, so just use a
    -      // generic one.
    -      this.signalError_(goog.net.BrowserChannel.Error.REQUEST_FAILED);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * @return {number} The max number of forward-channel retries, which will be 0
    - * in fail-fast mode.
    - */
    -goog.net.BrowserChannel.prototype.getForwardChannelMaxRetries = function() {
    -  return this.failFast_ ? 0 : this.forwardChannelMaxRetries_;
    -};
    -
    -
    -/**
    - * Sets the maximum number of attempts to connect to the server for forward
    - * channel requests.
    - * @param {number} retries The maximum number of attempts.
    - */
    -goog.net.BrowserChannel.prototype.setForwardChannelMaxRetries =
    -    function(retries) {
    -  this.forwardChannelMaxRetries_ = retries;
    -};
    -
    -
    -/**
    - * Sets the timeout for a forward channel request.
    - * @param {number} timeoutMs The timeout in milliseconds.
    - */
    -goog.net.BrowserChannel.prototype.setForwardChannelRequestTimeout =
    -    function(timeoutMs) {
    -  this.forwardChannelRequestTimeoutMs_ = timeoutMs;
    -};
    -
    -
    -/**
    - * @return {number} The max number of back-channel retries, which is a constant.
    - */
    -goog.net.BrowserChannel.prototype.getBackChannelMaxRetries = function() {
    -  // Back-channel retries is a constant.
    -  return goog.net.BrowserChannel.BACK_CHANNEL_MAX_RETRIES;
    -};
    -
    -
    -/**
    - * Returns whether the channel is closed
    - * @return {boolean} true if the channel is closed.
    - */
    -goog.net.BrowserChannel.prototype.isClosed = function() {
    -  return this.state_ == goog.net.BrowserChannel.State.CLOSED;
    -};
    -
    -
    -/**
    - * Returns the browser channel state.
    - * @return {goog.net.BrowserChannel.State} The current state of the browser
    - * channel.
    - */
    -goog.net.BrowserChannel.prototype.getState = function() {
    -  return this.state_;
    -};
    -
    -
    -/**
    - * Return the last status code received for a request.
    - * @return {number} The last status code received for a request.
    - */
    -goog.net.BrowserChannel.prototype.getLastStatusCode = function() {
    -  return this.lastStatusCode_;
    -};
    -
    -
    -/**
    - * @return {number} The last array id received.
    - */
    -goog.net.BrowserChannel.prototype.getLastArrayId = function() {
    -  return this.lastArrayId_;
    -};
    -
    -
    -/**
    - * Returns whether there are outstanding requests servicing the channel.
    - * @return {boolean} true if there are outstanding requests.
    - */
    -goog.net.BrowserChannel.prototype.hasOutstandingRequests = function() {
    -  return this.outstandingRequests_() != 0;
    -};
    -
    -
    -/**
    - * Sets a new parser for the response payload. A custom parser may be set to
    - * avoid using eval(), for example. By default, the parser uses
    - * {@code goog.json.unsafeParse}.
    - * @param {!goog.string.Parser} parser Parser.
    - */
    -goog.net.BrowserChannel.prototype.setParser = function(parser) {
    -  this.parser_ = parser;
    -};
    -
    -
    -/**
    - * Returns the number of outstanding requests.
    - * @return {number} The number of outstanding requests to the server.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.outstandingRequests_ = function() {
    -  var count = 0;
    -  if (this.backChannelRequest_) {
    -    count++;
    -  }
    -  if (this.forwardChannelRequest_) {
    -    count++;
    -  }
    -  return count;
    -};
    -
    -
    -/**
    - * Ensures that a forward channel request is scheduled.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.ensureForwardChannel_ = function() {
    -  if (this.forwardChannelRequest_) {
    -    // connection in process - no need to start a new request
    -    return;
    -  }
    -
    -  if (this.forwardChannelTimerId_) {
    -    // no need to start a new request - one is already scheduled
    -    return;
    -  }
    -
    -  this.forwardChannelTimerId_ = goog.net.BrowserChannel.setTimeout(
    -      goog.bind(this.onStartForwardChannelTimer_, this), 0);
    -  this.forwardChannelRetryCount_ = 0;
    -};
    -
    -
    -/**
    - * Schedules a forward-channel retry for the specified request, unless the max
    - * retries has been reached.
    - * @param {goog.net.ChannelRequest} request The failed request to retry.
    - * @return {boolean} true iff a retry was scheduled.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.maybeRetryForwardChannel_ =
    -    function(request) {
    -  if (this.forwardChannelRequest_ || this.forwardChannelTimerId_) {
    -    // Should be impossible to be called in this state.
    -    this.channelDebug_.severe('Request already in progress');
    -    return false;
    -  }
    -
    -  if (this.state_ == goog.net.BrowserChannel.State.INIT ||  // no retry open_()
    -      (this.forwardChannelRetryCount_ >= this.getForwardChannelMaxRetries())) {
    -    return false;
    -  }
    -
    -  this.channelDebug_.debug('Going to retry POST');
    -
    -  this.forwardChannelTimerId_ = goog.net.BrowserChannel.setTimeout(
    -      goog.bind(this.onStartForwardChannelTimer_, this, request),
    -      this.getRetryTime_(this.forwardChannelRetryCount_));
    -  this.forwardChannelRetryCount_++;
    -  return true;
    -};
    -
    -
    -/**
    - * Timer callback for ensureForwardChannel
    - * @param {goog.net.ChannelRequest=} opt_retryRequest A failed request to retry.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.onStartForwardChannelTimer_ = function(
    -    opt_retryRequest) {
    -  this.forwardChannelTimerId_ = null;
    -  this.startForwardChannel_(opt_retryRequest);
    -};
    -
    -
    -/**
    - * Begins a new forward channel operation to the server.
    - * @param {goog.net.ChannelRequest=} opt_retryRequest A failed request to retry.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.startForwardChannel_ = function(
    -    opt_retryRequest) {
    -  this.channelDebug_.debug('startForwardChannel_');
    -  if (!this.okToMakeRequest_()) {
    -    return; // channel is cancelled
    -  } else if (this.state_ == goog.net.BrowserChannel.State.INIT) {
    -    if (opt_retryRequest) {
    -      this.channelDebug_.severe('Not supposed to retry the open');
    -      return;
    -    }
    -    this.open_();
    -    this.state_ = goog.net.BrowserChannel.State.OPENING;
    -  } else if (this.state_ == goog.net.BrowserChannel.State.OPENED) {
    -    if (opt_retryRequest) {
    -      this.makeForwardChannelRequest_(opt_retryRequest);
    -      return;
    -    }
    -
    -    if (this.outgoingMaps_.length == 0) {
    -      this.channelDebug_.debug('startForwardChannel_ returned: ' +
    -                                   'nothing to send');
    -      // no need to start a new forward channel request
    -      return;
    -    }
    -
    -    if (this.forwardChannelRequest_) {
    -      // Should be impossible to be called in this state.
    -      this.channelDebug_.severe('startForwardChannel_ returned: ' +
    -                                    'connection already in progress');
    -      return;
    -    }
    -
    -    this.makeForwardChannelRequest_();
    -    this.channelDebug_.debug('startForwardChannel_ finished, sent request');
    -  }
    -};
    -
    -
    -/**
    - * Establishes a new channel session with the the server.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.open_ = function() {
    -  this.channelDebug_.debug('open_()');
    -  this.nextRid_ = Math.floor(Math.random() * 100000);
    -
    -  var rid = this.nextRid_++;
    -  var request = goog.net.BrowserChannel.createChannelRequest(
    -      this, this.channelDebug_, '', rid);
    -  request.setExtraHeaders(this.extraHeaders_);
    -  var requestText = this.dequeueOutgoingMaps_();
    -  var uri = this.forwardChannelUri_.clone();
    -  uri.setParameterValue('RID', rid);
    -  if (this.clientVersion_) {
    -    uri.setParameterValue('CVER', this.clientVersion_);
    -  }
    -
    -  // Add the reconnect parameters.
    -  this.addAdditionalParams_(uri);
    -
    -  request.xmlHttpPost(uri, requestText, true);
    -  this.forwardChannelRequest_ = request;
    -};
    -
    -
    -/**
    - * Makes a forward channel request using XMLHTTP.
    - * @param {goog.net.ChannelRequest=} opt_retryRequest A failed request to retry.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.makeForwardChannelRequest_ =
    -    function(opt_retryRequest) {
    -  var rid;
    -  var requestText;
    -  if (opt_retryRequest) {
    -    if (this.channelVersion_ > 6) {
    -      // In version 7 and up we can tack on new arrays to a retry.
    -      this.requeuePendingMaps_();
    -      rid = this.nextRid_ - 1;  // Must use last RID
    -      requestText = this.dequeueOutgoingMaps_();
    -    } else {
    -      // TODO(user): Remove this code and the opt_retryRequest passing
    -      // once server-side support for ver 7 is ubiquitous.
    -      rid = opt_retryRequest.getRequestId();
    -      requestText = /** @type {string} */ (opt_retryRequest.getPostData());
    -    }
    -  } else {
    -    rid = this.nextRid_++;
    -    requestText = this.dequeueOutgoingMaps_();
    -  }
    -
    -  var uri = this.forwardChannelUri_.clone();
    -  uri.setParameterValue('SID', this.sid_);
    -  uri.setParameterValue('RID', rid);
    -  uri.setParameterValue('AID', this.lastArrayId_);
    -  // Add the additional reconnect parameters.
    -  this.addAdditionalParams_(uri);
    -
    -  var request = goog.net.BrowserChannel.createChannelRequest(
    -      this,
    -      this.channelDebug_,
    -      this.sid_,
    -      rid,
    -      this.forwardChannelRetryCount_ + 1);
    -  request.setExtraHeaders(this.extraHeaders_);
    -
    -  // randomize from 50%-100% of the forward channel timeout to avoid
    -  // a big hit if servers happen to die at once.
    -  request.setTimeout(
    -      Math.round(this.forwardChannelRequestTimeoutMs_ * 0.50) +
    -      Math.round(this.forwardChannelRequestTimeoutMs_ * 0.50 * Math.random()));
    -  this.forwardChannelRequest_ = request;
    -  request.xmlHttpPost(uri, requestText, true);
    -};
    -
    -
    -/**
    - * Adds the additional parameters from the handler to the given URI.
    - * @param {goog.Uri} uri The URI to add the parameters to.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.addAdditionalParams_ = function(uri) {
    -  // Add the additional reconnect parameters as needed.
    -  if (this.handler_) {
    -    var params = this.handler_.getAdditionalParams(this);
    -    if (params) {
    -      goog.object.forEach(params, function(value, key) {
    -        uri.setParameterValue(key, value);
    -      });
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Returns the request text from the outgoing maps and resets it.
    - * @return {string} The encoded request text created from all the currently
    - *                  queued outgoing maps.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.dequeueOutgoingMaps_ = function() {
    -  var count = Math.min(this.outgoingMaps_.length,
    -                       goog.net.BrowserChannel.MAX_MAPS_PER_REQUEST_);
    -  var sb = ['count=' + count];
    -  var offset;
    -  if (this.channelVersion_ > 6 && count > 0) {
    -    // To save a bit of bandwidth, specify the base mapId and the rest as
    -    // offsets from it.
    -    offset = this.outgoingMaps_[0].mapId;
    -    sb.push('ofs=' + offset);
    -  } else {
    -    offset = 0;
    -  }
    -  for (var i = 0; i < count; i++) {
    -    var mapId = this.outgoingMaps_[i].mapId;
    -    var map = this.outgoingMaps_[i].map;
    -    if (this.channelVersion_ <= 6) {
    -      // Map IDs were not used in ver 6 and before, just indexes in the request.
    -      mapId = i;
    -    } else {
    -      mapId -= offset;
    -    }
    -    try {
    -      goog.structs.forEach(map, function(value, key, coll) {
    -        sb.push('req' + mapId + '_' + key + '=' + encodeURIComponent(value));
    -      });
    -    } catch (ex) {
    -      // We send a map here because lots of the retry logic relies on map IDs,
    -      // so we have to send something.
    -      sb.push('req' + mapId + '_' + 'type' + '=' +
    -              encodeURIComponent('_badmap'));
    -      if (this.handler_) {
    -        this.handler_.badMapError(this, map);
    -      }
    -    }
    -  }
    -  this.pendingMaps_ = this.pendingMaps_.concat(
    -      this.outgoingMaps_.splice(0, count));
    -  return sb.join('&');
    -};
    -
    -
    -/**
    - * Requeues unacknowledged sent arrays for retransmission in the next forward
    - * channel request.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.requeuePendingMaps_ = function() {
    -  this.outgoingMaps_ = this.pendingMaps_.concat(this.outgoingMaps_);
    -  this.pendingMaps_.length = 0;
    -};
    -
    -
    -/**
    - * Ensures there is a backchannel request for receiving data from the server.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.ensureBackChannel_ = function() {
    -  if (this.backChannelRequest_) {
    -    // already have one
    -    return;
    -  }
    -
    -  if (this.backChannelTimerId_) {
    -    // no need to start a new request - one is already scheduled
    -    return;
    -  }
    -
    -  this.backChannelAttemptId_ = 1;
    -  this.backChannelTimerId_ = goog.net.BrowserChannel.setTimeout(
    -      goog.bind(this.onStartBackChannelTimer_, this), 0);
    -  this.backChannelRetryCount_ = 0;
    -};
    -
    -
    -/**
    - * Schedules a back-channel retry, unless the max retries has been reached.
    - * @return {boolean} true iff a retry was scheduled.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.maybeRetryBackChannel_ = function() {
    -  if (this.backChannelRequest_ || this.backChannelTimerId_) {
    -    // Should be impossible to be called in this state.
    -    this.channelDebug_.severe('Request already in progress');
    -    return false;
    -  }
    -
    -  if (this.backChannelRetryCount_ >= this.getBackChannelMaxRetries()) {
    -    return false;
    -  }
    -
    -  this.channelDebug_.debug('Going to retry GET');
    -
    -  this.backChannelAttemptId_++;
    -  this.backChannelTimerId_ = goog.net.BrowserChannel.setTimeout(
    -      goog.bind(this.onStartBackChannelTimer_, this),
    -      this.getRetryTime_(this.backChannelRetryCount_));
    -  this.backChannelRetryCount_++;
    -  return true;
    -};
    -
    -
    -/**
    - * Timer callback for ensureBackChannel_.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.onStartBackChannelTimer_ = function() {
    -  this.backChannelTimerId_ = null;
    -  this.startBackChannel_();
    -};
    -
    -
    -/**
    - * Begins a new back channel operation to the server.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.startBackChannel_ = function() {
    -  if (!this.okToMakeRequest_()) {
    -    // channel is cancelled
    -    return;
    -  }
    -
    -  this.channelDebug_.debug('Creating new HttpRequest');
    -  this.backChannelRequest_ = goog.net.BrowserChannel.createChannelRequest(
    -      this,
    -      this.channelDebug_,
    -      this.sid_,
    -      'rpc',
    -      this.backChannelAttemptId_);
    -  this.backChannelRequest_.setExtraHeaders(this.extraHeaders_);
    -  this.backChannelRequest_.setReadyStateChangeThrottle(
    -      this.readyStateChangeThrottleMs_);
    -  var uri = this.backChannelUri_.clone();
    -  uri.setParameterValue('RID', 'rpc');
    -  uri.setParameterValue('SID', this.sid_);
    -  uri.setParameterValue('CI', this.useChunked_ ? '0' : '1');
    -  uri.setParameterValue('AID', this.lastArrayId_);
    -
    -  // Add the reconnect parameters.
    -  this.addAdditionalParams_(uri);
    -
    -  if (!goog.net.ChannelRequest.supportsXhrStreaming()) {
    -    uri.setParameterValue('TYPE', 'html');
    -    this.backChannelRequest_.tridentGet(uri, Boolean(this.hostPrefix_));
    -  } else {
    -    uri.setParameterValue('TYPE', 'xmlhttp');
    -    this.backChannelRequest_.xmlHttpGet(uri, true /* decodeChunks */,
    -        this.hostPrefix_, false /* opt_noClose */);
    -  }
    -  this.channelDebug_.debug('New Request created');
    -};
    -
    -
    -/**
    - * Gives the handler a chance to return an error code and stop channel
    - * execution. A handler might want to do this to check that the user is still
    - * logged in, for example.
    - * @private
    - * @return {boolean} If it's OK to make a request.
    - */
    -goog.net.BrowserChannel.prototype.okToMakeRequest_ = function() {
    -  if (this.handler_) {
    -    var result = this.handler_.okToMakeRequest(this);
    -    if (result != goog.net.BrowserChannel.Error.OK) {
    -      this.channelDebug_.debug('Handler returned error code from ' +
    -                                   'okToMakeRequest');
    -      this.signalError_(result);
    -      return false;
    -    }
    -  }
    -  return true;
    -};
    -
    -
    -/**
    - * Callback from BrowserTestChannel for when the channel is finished.
    - * @param {goog.net.BrowserTestChannel} testChannel The BrowserTestChannel.
    - * @param {boolean} useChunked  Whether we can chunk responses.
    - */
    -goog.net.BrowserChannel.prototype.testConnectionFinished =
    -    function(testChannel, useChunked) {
    -  this.channelDebug_.debug('Test Connection Finished');
    -
    -  this.useChunked_ = this.allowChunkedMode_ && useChunked;
    -  this.lastStatusCode_ = testChannel.getLastStatusCode();
    -  this.connectChannel_();
    -};
    -
    -
    -/**
    - * Callback from BrowserTestChannel for when the channel has an error.
    - * @param {goog.net.BrowserTestChannel} testChannel The BrowserTestChannel.
    - * @param {goog.net.ChannelRequest.Error} errorCode  The error code of the
    -       failure.
    - */
    -goog.net.BrowserChannel.prototype.testConnectionFailure =
    -    function(testChannel, errorCode) {
    -  this.channelDebug_.debug('Test Connection Failed');
    -  this.lastStatusCode_ = testChannel.getLastStatusCode();
    -  this.signalError_(goog.net.BrowserChannel.Error.REQUEST_FAILED);
    -};
    -
    -
    -/**
    - * Callback from BrowserTestChannel for when the channel is blocked.
    - * @param {goog.net.BrowserTestChannel} testChannel The BrowserTestChannel.
    - */
    -goog.net.BrowserChannel.prototype.testConnectionBlocked =
    -    function(testChannel) {
    -  this.channelDebug_.debug('Test Connection Blocked');
    -  this.lastStatusCode_ = this.connectionTest_.getLastStatusCode();
    -  this.signalError_(goog.net.BrowserChannel.Error.BLOCKED);
    -};
    -
    -
    -/**
    - * Callback from ChannelRequest for when new data is received
    - * @param {goog.net.ChannelRequest} request  The request object.
    - * @param {string} responseText The text of the response.
    - */
    -goog.net.BrowserChannel.prototype.onRequestData =
    -    function(request, responseText) {
    -  if (this.state_ == goog.net.BrowserChannel.State.CLOSED ||
    -      (this.backChannelRequest_ != request &&
    -       this.forwardChannelRequest_ != request)) {
    -    // either CLOSED or a request we don't know about (perhaps an old request)
    -    return;
    -  }
    -  this.lastStatusCode_ = request.getLastStatusCode();
    -
    -  if (this.forwardChannelRequest_ == request &&
    -      this.state_ == goog.net.BrowserChannel.State.OPENED) {
    -    if (this.channelVersion_ > 7) {
    -      var response;
    -      try {
    -        response = this.parser_.parse(responseText);
    -      } catch (ex) {
    -        response = null;
    -      }
    -      if (goog.isArray(response) && response.length == 3) {
    -        this.handlePostResponse_(response);
    -      } else {
    -        this.channelDebug_.debug('Bad POST response data returned');
    -        this.signalError_(goog.net.BrowserChannel.Error.BAD_RESPONSE);
    -      }
    -    } else if (responseText != goog.net.BrowserChannel.MAGIC_RESPONSE_COOKIE) {
    -      this.channelDebug_.debug('Bad data returned - missing/invald ' +
    -                                   'magic cookie');
    -      this.signalError_(goog.net.BrowserChannel.Error.BAD_RESPONSE);
    -    }
    -  } else {
    -    if (this.backChannelRequest_ == request) {
    -      this.clearDeadBackchannelTimer_();
    -    }
    -    if (!goog.string.isEmptyOrWhitespace(responseText)) {
    -      var response = this.parser_.parse(responseText);
    -      goog.asserts.assert(goog.isArray(response));
    -      this.onInput_(/** @type {!Array<?>} */ (response));
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Handles a POST response from the server.
    - * @param {Array<number>} responseValues The key value pairs in the POST
    - *     response.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.handlePostResponse_ = function(
    -    responseValues) {
    -  // The first response value is set to 0 if server is missing backchannel.
    -  if (responseValues[0] == 0) {
    -    this.handleBackchannelMissing_();
    -    return;
    -  }
    -  this.lastPostResponseArrayId_ = responseValues[1];
    -  var outstandingArrays = this.lastPostResponseArrayId_ - this.lastArrayId_;
    -  if (0 < outstandingArrays) {
    -    var numOutstandingBackchannelBytes = responseValues[2];
    -    this.channelDebug_.debug(numOutstandingBackchannelBytes + ' bytes (in ' +
    -        outstandingArrays + ' arrays) are outstanding on the BackChannel');
    -    if (!this.shouldRetryBackChannel_(numOutstandingBackchannelBytes)) {
    -      return;
    -    }
    -    if (!this.deadBackChannelTimerId_) {
    -      // We expect to receive data within 2 RTTs or we retry the backchannel.
    -      this.deadBackChannelTimerId_ = goog.net.BrowserChannel.setTimeout(
    -          goog.bind(this.onBackChannelDead_, this),
    -          2 * goog.net.BrowserChannel.RTT_ESTIMATE);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Handles a POST response from the server telling us that it has detected that
    - * we have no hanging GET connection.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.handleBackchannelMissing_ = function() {
    -  // As long as the back channel was started before the POST was sent,
    -  // we should retry the backchannel. We give a slight buffer of RTT_ESTIMATE
    -  // so as not to excessively retry the backchannel
    -  this.channelDebug_.debug('Server claims our backchannel is missing.');
    -  if (this.backChannelTimerId_) {
    -    this.channelDebug_.debug('But we are currently starting the request.');
    -    return;
    -  } else if (!this.backChannelRequest_) {
    -    this.channelDebug_.warning(
    -        'We do not have a BackChannel established');
    -  } else if (this.backChannelRequest_.getRequestStartTime() +
    -      goog.net.BrowserChannel.RTT_ESTIMATE <
    -      this.forwardChannelRequest_.getRequestStartTime()) {
    -    this.clearDeadBackchannelTimer_();
    -    this.backChannelRequest_.cancel();
    -    this.backChannelRequest_ = null;
    -  } else {
    -    return;
    -  }
    -  this.maybeRetryBackChannel_();
    -  goog.net.BrowserChannel.notifyStatEvent(
    -      goog.net.BrowserChannel.Stat.BACKCHANNEL_MISSING);
    -};
    -
    -
    -/**
    - * Determines whether we should start the process of retrying a possibly
    - * dead backchannel.
    - * @param {number} outstandingBytes The number of bytes for which the server has
    - *     not yet received acknowledgement.
    - * @return {boolean} Whether to start the backchannel retry timer.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.shouldRetryBackChannel_ = function(
    -    outstandingBytes) {
    -  // Not too many outstanding bytes, not buffered and not after a retry.
    -  return outstandingBytes <
    -      goog.net.BrowserChannel.OUTSTANDING_DATA_BACKCHANNEL_RETRY_CUTOFF &&
    -      !this.isBuffered() &&
    -      this.backChannelRetryCount_ == 0;
    -};
    -
    -
    -/**
    - * Decides which host prefix should be used, if any.  If there is a handler,
    - * allows the handler to validate a host prefix provided by the server, and
    - * optionally override it.
    - * @param {?string} serverHostPrefix The host prefix provided by the server.
    - * @return {?string} The host prefix to actually use, if any. Will return null
    - *     if the use of host prefixes was disabled via setAllowHostPrefix().
    - */
    -goog.net.BrowserChannel.prototype.correctHostPrefix = function(
    -    serverHostPrefix) {
    -  if (this.allowHostPrefix_) {
    -    if (this.handler_) {
    -      return this.handler_.correctHostPrefix(serverHostPrefix);
    -    }
    -    return serverHostPrefix;
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * Handles the timer that indicates that our backchannel is no longer able to
    - * successfully receive data from the server.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.onBackChannelDead_ = function() {
    -  if (goog.isDefAndNotNull(this.deadBackChannelTimerId_)) {
    -    this.deadBackChannelTimerId_ = null;
    -    this.backChannelRequest_.cancel();
    -    this.backChannelRequest_ = null;
    -    this.maybeRetryBackChannel_();
    -    goog.net.BrowserChannel.notifyStatEvent(
    -        goog.net.BrowserChannel.Stat.BACKCHANNEL_DEAD);
    -  }
    -};
    -
    -
    -/**
    - * Clears the timer that indicates that our backchannel is no longer able to
    - * successfully receive data from the server.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.clearDeadBackchannelTimer_ = function() {
    -  if (goog.isDefAndNotNull(this.deadBackChannelTimerId_)) {
    -    goog.global.clearTimeout(this.deadBackChannelTimerId_);
    -    this.deadBackChannelTimerId_ = null;
    -  }
    -};
    -
    -
    -/**
    - * Returns whether or not the given error/status combination is fatal or not.
    - * On fatal errors we immediately close the session rather than retrying the
    - * failed request.
    - * @param {goog.net.ChannelRequest.Error?} error The error code for the failed
    - * request.
    - * @param {number} statusCode The last HTTP status code.
    - * @return {boolean} Whether or not the error is fatal.
    - * @private
    - */
    -goog.net.BrowserChannel.isFatalError_ =
    -    function(error, statusCode) {
    -  return error == goog.net.ChannelRequest.Error.UNKNOWN_SESSION_ID ||
    -      error == goog.net.ChannelRequest.Error.ACTIVE_X_BLOCKED ||
    -      (error == goog.net.ChannelRequest.Error.STATUS &&
    -       statusCode > 0);
    -};
    -
    -
    -/**
    - * Callback from ChannelRequest that indicates a request has completed.
    - * @param {goog.net.ChannelRequest} request  The request object.
    - */
    -goog.net.BrowserChannel.prototype.onRequestComplete =
    -    function(request) {
    -  this.channelDebug_.debug('Request complete');
    -  var type;
    -  if (this.backChannelRequest_ == request) {
    -    this.clearDeadBackchannelTimer_();
    -    this.backChannelRequest_ = null;
    -    type = goog.net.BrowserChannel.ChannelType_.BACK_CHANNEL;
    -  } else if (this.forwardChannelRequest_ == request) {
    -    this.forwardChannelRequest_ = null;
    -    type = goog.net.BrowserChannel.ChannelType_.FORWARD_CHANNEL;
    -  } else {
    -    // return if it was an old request from a previous session
    -    return;
    -  }
    -
    -  this.lastStatusCode_ = request.getLastStatusCode();
    -
    -  if (this.state_ == goog.net.BrowserChannel.State.CLOSED) {
    -    return;
    -  }
    -
    -  if (request.getSuccess()) {
    -    // Yay!
    -    if (type == goog.net.BrowserChannel.ChannelType_.FORWARD_CHANNEL) {
    -      var size = request.getPostData() ? request.getPostData().length : 0;
    -      goog.net.BrowserChannel.notifyTimingEvent(size,
    -          goog.now() - request.getRequestStartTime(),
    -          this.forwardChannelRetryCount_);
    -      this.ensureForwardChannel_();
    -      this.onSuccess_();
    -      this.pendingMaps_.length = 0;
    -    } else {  // i.e., back-channel
    -      this.ensureBackChannel_();
    -    }
    -    return;
    -  }
    -  // Else unsuccessful. Fall through.
    -
    -  var lastError = request.getLastError();
    -  if (!goog.net.BrowserChannel.isFatalError_(lastError,
    -                                             this.lastStatusCode_)) {
    -    // Maybe retry.
    -    this.channelDebug_.debug('Maybe retrying, last error: ' +
    -        goog.net.ChannelRequest.errorStringFromCode(
    -            /** @type {goog.net.ChannelRequest.Error} */ (lastError),
    -            this.lastStatusCode_));
    -    if (type == goog.net.BrowserChannel.ChannelType_.FORWARD_CHANNEL) {
    -      if (this.maybeRetryForwardChannel_(request)) {
    -        return;
    -      }
    -    }
    -    if (type == goog.net.BrowserChannel.ChannelType_.BACK_CHANNEL) {
    -      if (this.maybeRetryBackChannel_()) {
    -        return;
    -      }
    -    }
    -    // Else exceeded max retries. Fall through.
    -    this.channelDebug_.debug('Exceeded max number of retries');
    -  } else {
    -    // Else fatal error. Fall through and mark the pending maps as failed.
    -    this.channelDebug_.debug('Not retrying due to error type');
    -  }
    -
    -
    -  // Can't save this session. :(
    -  this.channelDebug_.debug('Error: HTTP request failed');
    -  switch (lastError) {
    -    case goog.net.ChannelRequest.Error.NO_DATA:
    -      this.signalError_(goog.net.BrowserChannel.Error.NO_DATA);
    -      break;
    -    case goog.net.ChannelRequest.Error.BAD_DATA:
    -      this.signalError_(goog.net.BrowserChannel.Error.BAD_DATA);
    -      break;
    -    case goog.net.ChannelRequest.Error.UNKNOWN_SESSION_ID:
    -      this.signalError_(goog.net.BrowserChannel.Error.UNKNOWN_SESSION_ID);
    -      break;
    -    case goog.net.ChannelRequest.Error.ACTIVE_X_BLOCKED:
    -      this.signalError_(goog.net.BrowserChannel.Error.ACTIVE_X_BLOCKED);
    -      break;
    -    default:
    -      this.signalError_(goog.net.BrowserChannel.Error.REQUEST_FAILED);
    -      break;
    -  }
    -};
    -
    -
    -/**
    - * @param {number} retryCount Number of retries so far.
    - * @return {number} Time in ms before firing next retry request.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.getRetryTime_ = function(retryCount) {
    -  var retryTime = this.baseRetryDelayMs_ +
    -      Math.floor(Math.random() * this.retryDelaySeedMs_);
    -  if (!this.isActive()) {
    -    this.channelDebug_.debug('Inactive channel');
    -    retryTime =
    -        retryTime * goog.net.BrowserChannel.INACTIVE_CHANNEL_RETRY_FACTOR;
    -  }
    -  // Backoff for subsequent retries
    -  retryTime = retryTime * retryCount;
    -  return retryTime;
    -};
    -
    -
    -/**
    - * @param {number} baseDelayMs The base part of the retry delay, in ms.
    - * @param {number} delaySeedMs A random delay between 0 and this is added to
    - *     the base part.
    - */
    -goog.net.BrowserChannel.prototype.setRetryDelay = function(baseDelayMs,
    -    delaySeedMs) {
    -  this.baseRetryDelayMs_ = baseDelayMs;
    -  this.retryDelaySeedMs_ = delaySeedMs;
    -};
    -
    -
    -/**
    - * Processes the data returned by the server.
    - * @param {!Array<!Array<?>>} respArray The response array returned
    - *     by the server.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.onInput_ = function(respArray) {
    -  var batch = this.handler_ && this.handler_.channelHandleMultipleArrays ?
    -      [] : null;
    -  for (var i = 0; i < respArray.length; i++) {
    -    var nextArray = respArray[i];
    -    this.lastArrayId_ = nextArray[0];
    -    nextArray = nextArray[1];
    -    if (this.state_ == goog.net.BrowserChannel.State.OPENING) {
    -      if (nextArray[0] == 'c') {
    -        this.sid_ = nextArray[1];
    -        this.hostPrefix_ = this.correctHostPrefix(nextArray[2]);
    -        var negotiatedVersion = nextArray[3];
    -        if (goog.isDefAndNotNull(negotiatedVersion)) {
    -          this.channelVersion_ = negotiatedVersion;
    -        } else {
    -          // Servers prior to version 7 did not send this, so assume version 6.
    -          this.channelVersion_ = 6;
    -        }
    -        this.state_ = goog.net.BrowserChannel.State.OPENED;
    -        if (this.handler_) {
    -          this.handler_.channelOpened(this);
    -        }
    -        this.backChannelUri_ = this.getBackChannelUri(
    -            this.hostPrefix_, /** @type {string} */ (this.path_));
    -        // Open connection to receive data
    -        this.ensureBackChannel_();
    -      } else if (nextArray[0] == 'stop') {
    -        this.signalError_(goog.net.BrowserChannel.Error.STOP);
    -      }
    -    } else if (this.state_ == goog.net.BrowserChannel.State.OPENED) {
    -      if (nextArray[0] == 'stop') {
    -        if (batch && !goog.array.isEmpty(batch)) {
    -          this.handler_.channelHandleMultipleArrays(this, batch);
    -          batch.length = 0;
    -        }
    -        this.signalError_(goog.net.BrowserChannel.Error.STOP);
    -      } else if (nextArray[0] == 'noop') {
    -        // ignore - noop to keep connection happy
    -      } else {
    -        if (batch) {
    -          batch.push(nextArray);
    -        } else if (this.handler_) {
    -          this.handler_.channelHandleArray(this, nextArray);
    -        }
    -      }
    -      // We have received useful data on the back-channel, so clear its retry
    -      // count. We do this because back-channels by design do not complete
    -      // quickly, so on a flaky connection we could have many fail to complete
    -      // fully but still deliver a lot of data before they fail. We don't want
    -      // to count such failures towards the retry limit, because we don't want
    -      // to give up on a session if we can still receive data.
    -      this.backChannelRetryCount_ = 0;
    -    }
    -  }
    -  if (batch && !goog.array.isEmpty(batch)) {
    -    this.handler_.channelHandleMultipleArrays(this, batch);
    -  }
    -};
    -
    -
    -/**
    - * Helper to ensure the BrowserChannel is in the expected state.
    - * @param {...number} var_args The channel must be in one of the indicated
    - *     states.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.ensureInState_ = function(var_args) {
    -  if (!goog.array.contains(arguments, this.state_)) {
    -    throw Error('Unexpected channel state: ' + this.state_);
    -  }
    -};
    -
    -
    -/**
    - * Signals an error has occurred.
    - * @param {goog.net.BrowserChannel.Error} error  The error code for the failure.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.signalError_ = function(error) {
    -  this.channelDebug_.info('Error code ' + error);
    -  if (error == goog.net.BrowserChannel.Error.REQUEST_FAILED ||
    -      error == goog.net.BrowserChannel.Error.BLOCKED) {
    -    // Ping google to check if it's a server error or user's network error.
    -    var imageUri = null;
    -    if (this.handler_) {
    -      imageUri = this.handler_.getNetworkTestImageUri(this);
    -    }
    -    goog.net.tmpnetwork.testGoogleCom(
    -        goog.bind(this.testGoogleComCallback_, this), imageUri);
    -  } else {
    -    goog.net.BrowserChannel.notifyStatEvent(
    -        goog.net.BrowserChannel.Stat.ERROR_OTHER);
    -  }
    -  this.onError_(error);
    -};
    -
    -
    -/**
    - * Callback for testGoogleCom during error handling.
    - * @param {boolean} networkUp Whether the network is up.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.testGoogleComCallback_ = function(networkUp) {
    -  if (networkUp) {
    -    this.channelDebug_.info('Successfully pinged google.com');
    -    goog.net.BrowserChannel.notifyStatEvent(
    -        goog.net.BrowserChannel.Stat.ERROR_OTHER);
    -  } else {
    -    this.channelDebug_.info('Failed to ping google.com');
    -    goog.net.BrowserChannel.notifyStatEvent(
    -        goog.net.BrowserChannel.Stat.ERROR_NETWORK);
    -    // We call onError_ here instead of signalError_ because the latter just
    -    // calls notifyStatEvent, and we don't want to have another stat event.
    -    this.onError_(goog.net.BrowserChannel.Error.NETWORK);
    -  }
    -};
    -
    -
    -/**
    - * Called when messages have been successfully sent from the queue.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.onSuccess_ = function() {
    -  if (this.handler_) {
    -    this.handler_.channelSuccess(this, this.pendingMaps_);
    -  }
    -};
    -
    -
    -/**
    - * Called when we've determined the final error for a channel. It closes the
    - * notifiers the handler of the error and closes the channel.
    - * @param {goog.net.BrowserChannel.Error} error  The error code for the failure.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.onError_ = function(error) {
    -  this.channelDebug_.debug('HttpChannel: error - ' + error);
    -  this.state_ = goog.net.BrowserChannel.State.CLOSED;
    -  if (this.handler_) {
    -    this.handler_.channelError(this, error);
    -  }
    -  this.onClose_();
    -  this.cancelRequests_();
    -};
    -
    -
    -/**
    - * Called when the channel has been closed. It notifiers the handler of the
    - * event, and reports any pending or undelivered maps.
    - * @private
    - */
    -goog.net.BrowserChannel.prototype.onClose_ = function() {
    -  this.state_ = goog.net.BrowserChannel.State.CLOSED;
    -  this.lastStatusCode_ = -1;
    -  if (this.handler_) {
    -    if (this.pendingMaps_.length == 0 && this.outgoingMaps_.length == 0) {
    -      this.handler_.channelClosed(this);
    -    } else {
    -      this.channelDebug_.debug('Number of undelivered maps' +
    -          ', pending: ' + this.pendingMaps_.length +
    -          ', outgoing: ' + this.outgoingMaps_.length);
    -
    -      var copyOfPendingMaps = goog.array.clone(this.pendingMaps_);
    -      var copyOfUndeliveredMaps = goog.array.clone(this.outgoingMaps_);
    -      this.pendingMaps_.length = 0;
    -      this.outgoingMaps_.length = 0;
    -
    -      this.handler_.channelClosed(this,
    -          copyOfPendingMaps,
    -          copyOfUndeliveredMaps);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Gets the Uri used for the connection that sends data to the server.
    - * @param {string} path The path on the host.
    - * @return {!goog.Uri} The forward channel URI.
    - */
    -goog.net.BrowserChannel.prototype.getForwardChannelUri =
    -    function(path) {
    -  var uri = this.createDataUri(null, path);
    -  this.channelDebug_.debug('GetForwardChannelUri: ' + uri);
    -  return uri;
    -};
    -
    -
    -/**
    - * Gets the results for the first browser channel test
    - * @return {Array<string>} The results.
    - */
    -goog.net.BrowserChannel.prototype.getFirstTestResults =
    -    function() {
    -  return this.firstTestResults_;
    -};
    -
    -
    -/**
    - * Gets the results for the second browser channel test
    - * @return {?boolean} The results. True -> buffered connection,
    - *      False -> unbuffered, null -> unknown.
    - */
    -goog.net.BrowserChannel.prototype.getSecondTestResults = function() {
    -  return this.secondTestResults_;
    -};
    -
    -
    -/**
    - * Gets the Uri used for the connection that receives data from the server.
    - * @param {?string} hostPrefix The host prefix.
    - * @param {string} path The path on the host.
    - * @return {!goog.Uri} The back channel URI.
    - */
    -goog.net.BrowserChannel.prototype.getBackChannelUri =
    -    function(hostPrefix, path) {
    -  var uri = this.createDataUri(this.shouldUseSecondaryDomains() ?
    -      hostPrefix : null, path);
    -  this.channelDebug_.debug('GetBackChannelUri: ' + uri);
    -  return uri;
    -};
    -
    -
    -/**
    - * Creates a data Uri applying logic for secondary hostprefix, port
    - * overrides, and versioning.
    - * @param {?string} hostPrefix The host prefix.
    - * @param {string} path The path on the host (may be absolute or relative).
    - * @param {number=} opt_overridePort Optional override port.
    - * @return {!goog.Uri} The data URI.
    - */
    -goog.net.BrowserChannel.prototype.createDataUri =
    -    function(hostPrefix, path, opt_overridePort) {
    -  var uri = goog.Uri.parse(path);
    -  var uriAbsolute = (uri.getDomain() != '');
    -  if (uriAbsolute) {
    -    if (hostPrefix) {
    -      uri.setDomain(hostPrefix + '.' + uri.getDomain());
    -    }
    -
    -    uri.setPort(opt_overridePort || uri.getPort());
    -  } else {
    -    var locationPage = window.location;
    -    var hostName;
    -    if (hostPrefix) {
    -      hostName = hostPrefix + '.' + locationPage.hostname;
    -    } else {
    -      hostName = locationPage.hostname;
    -    }
    -
    -    var port = opt_overridePort || locationPage.port;
    -
    -    uri = goog.Uri.create(locationPage.protocol, null, hostName, port, path);
    -  }
    -
    -  if (this.extraParams_) {
    -    goog.object.forEach(this.extraParams_, function(value, key) {
    -      uri.setParameterValue(key, value);
    -    });
    -  }
    -
    -  // Add the protocol version to the URI.
    -  uri.setParameterValue('VER', this.channelVersion_);
    -
    -  // Add the reconnect parameters.
    -  this.addAdditionalParams_(uri);
    -
    -  return uri;
    -};
    -
    -
    -/**
    - * Called when BC needs to create an XhrIo object.  Override in a subclass if
    - * you need to customize the behavior, for example to enable the creation of
    - * XHR's capable of calling a secondary domain. Will also allow calling
    - * a secondary domain if withCredentials (CORS) is enabled.
    - * @param {?string} hostPrefix The host prefix, if we need an XhrIo object
    - *     capable of calling a secondary domain.
    - * @return {!goog.net.XhrIo} A new XhrIo object.
    - */
    -goog.net.BrowserChannel.prototype.createXhrIo = function(hostPrefix) {
    -  if (hostPrefix && !this.supportsCrossDomainXhrs_) {
    -    throw Error('Can\'t create secondary domain capable XhrIo object.');
    -  }
    -  var xhr = new goog.net.XhrIo();
    -  xhr.setWithCredentials(this.supportsCrossDomainXhrs_);
    -  return xhr;
    -};
    -
    -
    -/**
    - * Gets whether this channel is currently active. This is used to determine the
    - * length of time to wait before retrying. This call delegates to the handler.
    - * @return {boolean} Whether the channel is currently active.
    - */
    -goog.net.BrowserChannel.prototype.isActive = function() {
    -  return !!this.handler_ && this.handler_.isActive(this);
    -};
    -
    -
    -/**
    - * Wrapper around SafeTimeout which calls the start and end execution hooks
    - * with a try...finally block.
    - * @param {Function} fn The callback function.
    - * @param {number} ms The time in MS for the timer.
    - * @return {number} The ID of the timer.
    - */
    -goog.net.BrowserChannel.setTimeout = function(fn, ms) {
    -  if (!goog.isFunction(fn)) {
    -    throw Error('Fn must not be null and must be a function');
    -  }
    -  return goog.global.setTimeout(function() {
    -    goog.net.BrowserChannel.onStartExecution();
    -    try {
    -      fn();
    -    } finally {
    -      goog.net.BrowserChannel.onEndExecution();
    -    }
    -  }, ms);
    -};
    -
    -
    -/**
    - * Helper function to call the start hook
    - */
    -goog.net.BrowserChannel.onStartExecution = function() {
    -  goog.net.BrowserChannel.startExecutionHook_();
    -};
    -
    -
    -/**
    - * Helper function to call the end hook
    - */
    -goog.net.BrowserChannel.onEndExecution = function() {
    -  goog.net.BrowserChannel.endExecutionHook_();
    -};
    -
    -
    -/**
    - * Returns the singleton event target for stat events.
    - * @return {goog.events.EventTarget} The event target for stat events.
    - */
    -goog.net.BrowserChannel.getStatEventTarget = function() {
    -  return goog.net.BrowserChannel.statEventTarget_;
    -};
    -
    -
    -/**
    - * Notify the channel that a particular fine grained network event has occurred.
    - * Should be considered package-private.
    - * @param {goog.net.BrowserChannel.ServerReachability} reachabilityType The
    - *     reachability event type.
    - */
    -goog.net.BrowserChannel.prototype.notifyServerReachabilityEvent = function(
    -    reachabilityType) {
    -  var target = goog.net.BrowserChannel.statEventTarget_;
    -  target.dispatchEvent(new goog.net.BrowserChannel.ServerReachabilityEvent(
    -      target, reachabilityType));
    -};
    -
    -
    -/**
    - * Helper function to call the stat event callback.
    - * @param {goog.net.BrowserChannel.Stat} stat The stat.
    - */
    -goog.net.BrowserChannel.notifyStatEvent = function(stat) {
    -  var target = goog.net.BrowserChannel.statEventTarget_;
    -  target.dispatchEvent(
    -      new goog.net.BrowserChannel.StatEvent(target, stat));
    -};
    -
    -
    -/**
    - * Helper function to notify listeners about POST request performance.
    - *
    - * @param {number} size Number of characters in the POST data.
    - * @param {number} rtt The amount of time from POST start to response.
    - * @param {number} retries The number of times the POST had to be retried.
    - */
    -goog.net.BrowserChannel.notifyTimingEvent = function(size, rtt, retries) {
    -  var target = goog.net.BrowserChannel.statEventTarget_;
    -  target.dispatchEvent(
    -      new goog.net.BrowserChannel.TimingEvent(target, size, rtt, retries));
    -};
    -
    -
    -/**
    - * Determines whether to use a secondary domain when the server gives us
    - * a host prefix. This allows us to work around browser per-domain
    - * connection limits.
    - *
    - * Currently, we  use secondary domains when using Trident's ActiveXObject,
    - * because it supports cross-domain requests out of the box.  Note that in IE10
    - * we no longer use ActiveX since it's not supported in Metro mode and IE10
    - * supports XHR streaming.
    - *
    - * If you need to use secondary domains on other browsers and IE10,
    - * you have two choices:
    - *     1) If you only care about browsers that support CORS
    - *        (https://developer.mozilla.org/en-US/docs/HTTP_access_control), you
    - *        can use {@link #setSupportsCrossDomainXhrs} and set the appropriate
    - *        CORS response headers on the server.
    - *     2) Or, override this method in a subclass, and make sure that those
    - *        browsers use some messaging mechanism that works cross-domain (e.g
    - *        iframes and window.postMessage).
    - *
    - * @return {boolean} Whether to use secondary domains.
    - * @see http://code.google.com/p/closure-library/issues/detail?id=339
    - */
    -goog.net.BrowserChannel.prototype.shouldUseSecondaryDomains = function() {
    -  return this.supportsCrossDomainXhrs_ ||
    -      !goog.net.ChannelRequest.supportsXhrStreaming();
    -};
    -
    -
    -/**
    - * A LogSaver that can be used to accumulate all the debug logs for
    - * BrowserChannels so they can be sent to the server when a problem is
    - * detected.
    - * @const
    - */
    -goog.net.BrowserChannel.LogSaver = {};
    -
    -
    -/**
    - * Buffer for accumulating the debug log
    - * @type {goog.structs.CircularBuffer}
    - * @private
    - */
    -goog.net.BrowserChannel.LogSaver.buffer_ =
    -    new goog.structs.CircularBuffer(1000);
    -
    -
    -/**
    - * Whether we're currently accumulating the debug log.
    - * @type {boolean}
    - * @private
    - */
    -goog.net.BrowserChannel.LogSaver.enabled_ = false;
    -
    -
    -/**
    - * Formatter for saving logs.
    - * @type {goog.debug.Formatter}
    - * @private
    - */
    -goog.net.BrowserChannel.LogSaver.formatter_ = new goog.debug.TextFormatter();
    -
    -
    -/**
    - * Returns whether the LogSaver is enabled.
    - * @return {boolean} Whether saving is enabled or disabled.
    - */
    -goog.net.BrowserChannel.LogSaver.isEnabled = function() {
    -  return goog.net.BrowserChannel.LogSaver.enabled_;
    -};
    -
    -
    -/**
    - * Enables of disables the LogSaver.
    - * @param {boolean} enable Whether to enable or disable saving.
    - */
    -goog.net.BrowserChannel.LogSaver.setEnabled = function(enable) {
    -  if (enable == goog.net.BrowserChannel.LogSaver.enabled_) {
    -    return;
    -  }
    -
    -  var fn = goog.net.BrowserChannel.LogSaver.addLogRecord;
    -  var logger = goog.log.getLogger('goog.net');
    -  if (enable) {
    -    goog.log.addHandler(logger, fn);
    -  } else {
    -    goog.log.removeHandler(logger, fn);
    -  }
    -};
    -
    -
    -/**
    - * Adds a log record.
    - * @param {goog.log.LogRecord} logRecord the LogRecord.
    - */
    -goog.net.BrowserChannel.LogSaver.addLogRecord = function(logRecord) {
    -  goog.net.BrowserChannel.LogSaver.buffer_.add(
    -      goog.net.BrowserChannel.LogSaver.formatter_.formatRecord(logRecord));
    -};
    -
    -
    -/**
    - * Returns the log as a single string.
    - * @return {string} The log as a single string.
    - */
    -goog.net.BrowserChannel.LogSaver.getBuffer = function() {
    -  return goog.net.BrowserChannel.LogSaver.buffer_.getValues().join('');
    -};
    -
    -
    -/**
    - * Clears the buffer
    - */
    -goog.net.BrowserChannel.LogSaver.clearBuffer = function() {
    -  goog.net.BrowserChannel.LogSaver.buffer_.clear();
    -};
    -
    -
    -
    -/**
    - * Abstract base class for the browser channel handler
    - * @constructor
    - */
    -goog.net.BrowserChannel.Handler = function() {
    -};
    -
    -
    -/**
    - * Callback handler for when a batch of response arrays is received from the
    - * server.
    - * @type {?function(!goog.net.BrowserChannel, !Array<!Array<?>>)}
    - */
    -goog.net.BrowserChannel.Handler.prototype.channelHandleMultipleArrays = null;
    -
    -
    -/**
    - * Whether it's okay to make a request to the server. A handler can return
    - * false if the channel should fail. For example, if the user has logged out,
    - * the handler may want all requests to fail immediately.
    - * @param {goog.net.BrowserChannel} browserChannel The browser channel.
    - * @return {goog.net.BrowserChannel.Error} An error code. The code should
    - * return goog.net.BrowserChannel.Error.OK to indicate it's okay. Any other
    - * error code will cause a failure.
    - */
    -goog.net.BrowserChannel.Handler.prototype.okToMakeRequest =
    -    function(browserChannel) {
    -  return goog.net.BrowserChannel.Error.OK;
    -};
    -
    -
    -/**
    - * Indicates the BrowserChannel has successfully negotiated with the server
    - * and can now send and receive data.
    - * @param {goog.net.BrowserChannel} browserChannel The browser channel.
    - */
    -goog.net.BrowserChannel.Handler.prototype.channelOpened =
    -    function(browserChannel) {
    -};
    -
    -
    -/**
    - * New input is available for the application to process.
    - *
    - * @param {goog.net.BrowserChannel} browserChannel The browser channel.
    - * @param {Array<?>} array The data array.
    - */
    -goog.net.BrowserChannel.Handler.prototype.channelHandleArray =
    -    function(browserChannel, array) {
    -};
    -
    -
    -/**
    - * Indicates maps were successfully sent on the BrowserChannel.
    - *
    - * @param {goog.net.BrowserChannel} browserChannel The browser channel.
    - * @param {Array<goog.net.BrowserChannel.QueuedMap>} deliveredMaps The
    - *     array of maps that have been delivered to the server. This is a direct
    - *     reference to the internal BrowserChannel array, so a copy should be made
    - *     if the caller desires a reference to the data.
    - */
    -goog.net.BrowserChannel.Handler.prototype.channelSuccess =
    -    function(browserChannel, deliveredMaps) {
    -};
    -
    -
    -/**
    - * Indicates an error occurred on the BrowserChannel.
    - *
    - * @param {goog.net.BrowserChannel} browserChannel The browser channel.
    - * @param {goog.net.BrowserChannel.Error} error The error code.
    - */
    -goog.net.BrowserChannel.Handler.prototype.channelError =
    -    function(browserChannel, error) {
    -};
    -
    -
    -/**
    - * Indicates the BrowserChannel is closed. Also notifies about which maps,
    - * if any, that may not have been delivered to the server.
    - * @param {goog.net.BrowserChannel} browserChannel The browser channel.
    - * @param {Array<goog.net.BrowserChannel.QueuedMap>=} opt_pendingMaps The
    - *     array of pending maps, which may or may not have been delivered to the
    - *     server.
    - * @param {Array<goog.net.BrowserChannel.QueuedMap>=} opt_undeliveredMaps
    - *     The array of undelivered maps, which have definitely not been delivered
    - *     to the server.
    - */
    -goog.net.BrowserChannel.Handler.prototype.channelClosed =
    -    function(browserChannel, opt_pendingMaps, opt_undeliveredMaps) {
    -};
    -
    -
    -/**
    - * Gets any parameters that should be added at the time another connection is
    - * made to the server.
    - * @param {goog.net.BrowserChannel} browserChannel The browser channel.
    - * @return {Object} Extra parameter keys and values to add to the
    - *                  requests.
    - */
    -goog.net.BrowserChannel.Handler.prototype.getAdditionalParams =
    -    function(browserChannel) {
    -  return {};
    -};
    -
    -
    -/**
    - * Gets the URI of an image that can be used to test network connectivity.
    - * @param {goog.net.BrowserChannel} browserChannel The browser channel.
    - * @return {goog.Uri?} A custom URI to load for the network test.
    - */
    -goog.net.BrowserChannel.Handler.prototype.getNetworkTestImageUri =
    -    function(browserChannel) {
    -  return null;
    -};
    -
    -
    -/**
    - * Gets whether this channel is currently active. This is used to determine the
    - * length of time to wait before retrying.
    - * @param {goog.net.BrowserChannel} browserChannel The browser channel.
    - * @return {boolean} Whether the channel is currently active.
    - */
    -goog.net.BrowserChannel.Handler.prototype.isActive = function(browserChannel) {
    -  return true;
    -};
    -
    -
    -/**
    - * Called by the channel if enumeration of the map throws an exception.
    - * @param {goog.net.BrowserChannel} browserChannel The browser channel.
    - * @param {Object} map The map that can't be enumerated.
    - */
    -goog.net.BrowserChannel.Handler.prototype.badMapError =
    -    function(browserChannel, map) {
    -  return;
    -};
    -
    -
    -/**
    - * Allows the handler to override a host prefix provided by the server.  Will
    - * be called whenever the channel has received such a prefix and is considering
    - * its use.
    - * @param {?string} serverHostPrefix The host prefix provided by the server.
    - * @return {?string} The host prefix the client should use.
    - */
    -goog.net.BrowserChannel.Handler.prototype.correctHostPrefix =
    -    function(serverHostPrefix) {
    -  return serverHostPrefix;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/net/browserchannel_test.html b/src/database/third_party/closure-library/closure/goog/net/browserchannel_test.html
    deleted file mode 100644
    index b7bb6437e59..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/browserchannel_test.html
    +++ /dev/null
    @@ -1,26 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.net.BrowserChannel
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -  goog.require('goog.net.BrowserChannelTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="debug" style="font-size: small">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/browserchannel_test.js b/src/database/third_party/closure-library/closure/goog/net/browserchannel_test.js
    deleted file mode 100644
    index a7066acb89a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/browserchannel_test.js
    +++ /dev/null
    @@ -1,1325 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.net.BrowserChannelTest');
    -goog.setTestOnly('goog.net.BrowserChannelTest');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.functions');
    -goog.require('goog.json');
    -goog.require('goog.net.BrowserChannel');
    -goog.require('goog.net.ChannelDebug');
    -goog.require('goog.net.ChannelRequest');
    -goog.require('goog.net.tmpnetwork');
    -goog.require('goog.structs.Map');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.asserts');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -
    -
    -/**
    - * Delay between a network failure and the next network request.
    - */
    -var RETRY_TIME = 1000;
    -
    -
    -/**
    - * A really long time - used to make sure no more timeouts will fire.
    - */
    -var ALL_DAY_MS = 1000 * 60 * 60 * 24;
    -
    -var stubs = new goog.testing.PropertyReplacer();
    -
    -var browserChannel;
    -var deliveredMaps;
    -var handler;
    -var mockClock;
    -var gotError;
    -var numStatEvents;
    -var lastStatEvent;
    -var numTimingEvents;
    -var lastPostSize;
    -var lastPostRtt;
    -var lastPostRetryCount;
    -
    -// Set to true to see the channel debug output in the browser window.
    -var debug = false;
    -// Debug message to print out when debug is true.
    -var debugMessage = '';
    -
    -function debugToWindow(message) {
    -  if (debug) {
    -    debugMessage += message + '<br>';
    -    goog.dom.getElement('debug').innerHTML = debugMessage;
    -  }
    -}
    -
    -
    -/**
    - * Stubs goog.net.tmpnetwork to always time out. It maintains the
    - * contract given by goog.net.tmpnetwork.testGoogleCom, but always
    - * times out (calling callback(false)).
    - *
    - * stubTmpnetwork should be called in tests that require it before
    - * a call to testGoogleCom happens. It is reset at tearDown.
    - */
    -function stubTmpnetwork() {
    -  stubs.set(goog.net.tmpnetwork, 'testLoadImage',
    -      function(url, timeout, callback) {
    -        goog.Timer.callOnce(goog.partial(callback, false), timeout);
    -      });
    -}
    -
    -
    -
    -/**
    - * Mock ChannelRequest.
    - * @constructor
    - */
    -var MockChannelRequest = function(channel, channelDebug, opt_sessionId,
    -    opt_requestId, opt_retryId) {
    -  this.channel_ = channel;
    -  this.channelDebug_ = channelDebug;
    -  this.sessionId_ = opt_sessionId;
    -  this.requestId_ = opt_requestId;
    -  this.successful_ = true;
    -  this.lastError_ = null;
    -  this.lastStatusCode_ = 200;
    -
    -  // For debugging, keep track of whether this is a back or forward channel.
    -  this.isBack = !!(opt_requestId == 'rpc');
    -  this.isForward = !this.isBack;
    -};
    -
    -MockChannelRequest.prototype.postData_ = null;
    -
    -MockChannelRequest.prototype.requestStartTime_ = null;
    -
    -MockChannelRequest.prototype.setExtraHeaders = function(extraHeaders) {};
    -
    -MockChannelRequest.prototype.setTimeout = function(timeout) {};
    -
    -MockChannelRequest.prototype.setReadyStateChangeThrottle =
    -    function(throttle) {};
    -
    -MockChannelRequest.prototype.xmlHttpPost = function(uri, postData,
    -    decodeChunks) {
    -  this.channelDebug_.debug('---> POST: ' + uri + ', ' + postData + ', ' +
    -      decodeChunks);
    -  this.postData_ = postData;
    -  this.requestStartTime_ = goog.now();
    -};
    -
    -MockChannelRequest.prototype.xmlHttpGet = function(uri, decodeChunks,
    -    opt_noClose) {
    -  this.channelDebug_.debug('<--- GET: ' + uri + ', ' + decodeChunks + ', ' +
    -      opt_noClose);
    -  this.requestStartTime_ = goog.now();
    -};
    -
    -MockChannelRequest.prototype.tridentGet = function(uri, usingSecondaryDomain) {
    -  this.channelDebug_.debug('<---GET (T): ' + uri);
    -  this.requestStartTime_ = goog.now();
    -};
    -
    -MockChannelRequest.prototype.sendUsingImgTag = function(uri) {
    -  this.requestStartTime_ = goog.now();
    -};
    -
    -MockChannelRequest.prototype.cancel = function() {
    -  this.successful_ = false;
    -};
    -
    -MockChannelRequest.prototype.getSuccess = function() {
    -  return this.successful_;
    -};
    -
    -MockChannelRequest.prototype.getLastError = function() {
    -  return this.lastError_;
    -};
    -
    -MockChannelRequest.prototype.getLastStatusCode = function() {
    -  return this.lastStatusCode_;
    -};
    -
    -MockChannelRequest.prototype.getSessionId = function() {
    -  return this.sessionId_;
    -};
    -
    -MockChannelRequest.prototype.getRequestId = function() {
    -  return this.requestId_;
    -};
    -
    -MockChannelRequest.prototype.getPostData = function() {
    -  return this.postData_;
    -};
    -
    -MockChannelRequest.prototype.getRequestStartTime = function() {
    -  return this.requestStartTime_;
    -};
    -
    -
    -function setUpPage() {
    -  // Use our MockChannelRequests instead of the real ones.
    -  goog.net.BrowserChannel.createChannelRequest = function(
    -      channel, channelDebug, opt_sessionId, opt_requestId, opt_retryId) {
    -    return new MockChannelRequest(
    -        channel, channelDebug, opt_sessionId, opt_requestId, opt_retryId);
    -  };
    -
    -  // Mock out the stat notification code.
    -  goog.net.BrowserChannel.notifyStatEvent = function(stat) {
    -    numStatEvents++;
    -    lastStatEvent = stat;
    -  };
    -
    -  goog.net.BrowserChannel.notifyTimingEvent = function(size, rtt, retries) {
    -    numTimingEvents++;
    -    lastPostSize = size;
    -    lastPostRtt = rtt;
    -    lastPostRetryCount = retries;
    -  };
    -}
    -
    -
    -function setUp() {
    -  numTimingEvents = 0;
    -  lastPostSize = null;
    -  lastPostRtt = null;
    -  lastPostRetryCount = null;
    -
    -  mockClock = new goog.testing.MockClock(true);
    -  browserChannel = new goog.net.BrowserChannel('1');
    -  gotError = false;
    -
    -  handler = new goog.net.BrowserChannel.Handler();
    -  handler.channelOpened = function() {};
    -  handler.channelError = function(channel, error) {
    -    gotError = true;
    -  };
    -  handler.channelSuccess = function(channel, maps) {
    -    deliveredMaps = goog.array.clone(maps);
    -  };
    -  handler.channelClosed = function(
    -      channel, opt_pendingMaps, opt_undeliveredMaps) {
    -    // Mock out the handler, and let it set a formatted user readable string
    -    // of the undelivered maps which we can use when verifying our assertions.
    -    if (opt_pendingMaps) {
    -      this.pendingMapsString = formatArrayOfMaps(opt_pendingMaps);
    -    }
    -    if (opt_undeliveredMaps) {
    -      this.undeliveredMapsString = formatArrayOfMaps(opt_undeliveredMaps);
    -    }
    -  };
    -  handler.channelHandleMultipleArrays = function() {};
    -  handler.channelHandleArray = function() {};
    -
    -  browserChannel.setHandler(handler);
    -
    -  // Provide a predictable retry time for testing.
    -  browserChannel.getRetryTime_ = function(retryCount) {
    -    return RETRY_TIME;
    -  };
    -
    -  var channelDebug = new goog.net.ChannelDebug();
    -  channelDebug.debug = function(message) {
    -    debugToWindow(message);
    -  };
    -  browserChannel.setChannelDebug(channelDebug);
    -
    -  numStatEvents = 0;
    -  lastStatEvent = null;
    -}
    -
    -
    -function tearDown() {
    -  mockClock.dispose();
    -  stubs.reset();
    -  debugToWindow('<hr>');
    -}
    -
    -
    -/**
    - * Helper function to return a formatted string representing an array of maps.
    - */
    -function formatArrayOfMaps(arrayOfMaps) {
    -  var result = [];
    -  for (var i = 0; i < arrayOfMaps.length; i++) {
    -    var map = arrayOfMaps[i];
    -    var keys = map.map.getKeys();
    -    for (var j = 0; j < keys.length; j++) {
    -      var tmp = keys[j] + ':' + map.map.get(keys[j]) + (map.context ?
    -          ':' + map.context : '');
    -      result.push(tmp);
    -    }
    -  }
    -  return result.join(', ');
    -}
    -
    -
    -function testFormatArrayOfMaps() {
    -  // This function is used in a non-trivial test, so let's verify that it works.
    -  var map1 = new goog.structs.Map();
    -  map1.set('k1', 'v1');
    -  map1.set('k2', 'v2');
    -  var map2 = new goog.structs.Map();
    -  map2.set('k3', 'v3');
    -  var map3 = new goog.structs.Map();
    -  map3.set('k4', 'v4');
    -  map3.set('k5', 'v5');
    -  map3.set('k6', 'v6');
    -
    -  // One map.
    -  var a = [];
    -  a.push(new goog.net.BrowserChannel.QueuedMap(0, map1));
    -  assertEquals('k1:v1, k2:v2',
    -      formatArrayOfMaps(a));
    -
    -  // Many maps.
    -  var b = [];
    -  b.push(new goog.net.BrowserChannel.QueuedMap(0, map1));
    -  b.push(new goog.net.BrowserChannel.QueuedMap(0, map2));
    -  b.push(new goog.net.BrowserChannel.QueuedMap(0, map3));
    -  assertEquals('k1:v1, k2:v2, k3:v3, k4:v4, k5:v5, k6:v6',
    -      formatArrayOfMaps(b));
    -
    -  // One map with a context.
    -  var c = [];
    -  c.push(new goog.net.BrowserChannel.QueuedMap(0, map1, 'c1'));
    -  assertEquals('k1:v1:c1, k2:v2:c1',
    -      formatArrayOfMaps(c));
    -}
    -
    -
    -function connectForwardChannel(
    -    opt_serverVersion, opt_hostPrefix, opt_uriPrefix) {
    -  var uriPrefix = opt_uriPrefix || '';
    -  browserChannel.connect(uriPrefix + '/test', uriPrefix + '/bind', null);
    -  mockClock.tick(0);
    -  completeTestConnection();
    -  completeForwardChannel(opt_serverVersion, opt_hostPrefix);
    -}
    -
    -
    -function connect(opt_serverVersion, opt_hostPrefix, opt_uriPrefix) {
    -  connectForwardChannel(opt_serverVersion, opt_hostPrefix, opt_uriPrefix);
    -  completeBackChannel();
    -}
    -
    -
    -function disconnect() {
    -  browserChannel.disconnect();
    -  mockClock.tick(0);
    -}
    -
    -
    -function completeTestConnection() {
    -  completeForwardTestConnection();
    -  completeBackTestConnection();
    -  assertEquals(goog.net.BrowserChannel.State.OPENING,
    -      browserChannel.getState());
    -}
    -
    -
    -function completeForwardTestConnection() {
    -  browserChannel.connectionTest_.onRequestData(
    -      browserChannel.connectionTest_,
    -      '["b"]');
    -  browserChannel.connectionTest_.onRequestComplete(
    -      browserChannel.connectionTest_);
    -  mockClock.tick(0);
    -}
    -
    -
    -function completeBackTestConnection() {
    -  browserChannel.connectionTest_.onRequestData(
    -      browserChannel.connectionTest_,
    -      '11111');
    -  mockClock.tick(0);
    -}
    -
    -
    -function completeForwardChannel(opt_serverVersion, opt_hostPrefix) {
    -  var responseData = '[[0,["c","1234567890ABCDEF",' +
    -      (opt_hostPrefix ? '"' + opt_hostPrefix + '"' : 'null') +
    -      (opt_serverVersion ? ',' + opt_serverVersion : '') +
    -      ']]]';
    -  browserChannel.onRequestData(
    -      browserChannel.forwardChannelRequest_,
    -      responseData);
    -  browserChannel.onRequestComplete(
    -      browserChannel.forwardChannelRequest_);
    -  mockClock.tick(0);
    -}
    -
    -
    -function completeBackChannel() {
    -  browserChannel.onRequestData(
    -      browserChannel.backChannelRequest_,
    -      '[[1,["foo"]]]');
    -  browserChannel.onRequestComplete(
    -      browserChannel.backChannelRequest_);
    -  mockClock.tick(0);
    -}
    -
    -
    -function responseVersion7() {
    -  browserChannel.onRequestData(
    -      browserChannel.forwardChannelRequest_,
    -      goog.net.BrowserChannel.MAGIC_RESPONSE_COOKIE);
    -  browserChannel.onRequestComplete(
    -      browserChannel.forwardChannelRequest_);
    -  mockClock.tick(0);
    -}
    -
    -function responseNoBackchannel(lastArrayIdSentFromServer, outstandingDataSize) {
    -  responseData = goog.json.serialize(
    -      [0, lastArrayIdSentFromServer, outstandingDataSize]);
    -  browserChannel.onRequestData(
    -      browserChannel.forwardChannelRequest_,
    -      responseData);
    -  browserChannel.onRequestComplete(
    -      browserChannel.forwardChannelRequest_);
    -  mockClock.tick(0);
    -}
    -
    -function response(lastArrayIdSentFromServer, outstandingDataSize) {
    -  responseData = goog.json.serialize(
    -      [1, lastArrayIdSentFromServer, outstandingDataSize]);
    -  browserChannel.onRequestData(
    -      browserChannel.forwardChannelRequest_,
    -      responseData
    -  );
    -  browserChannel.onRequestComplete(
    -      browserChannel.forwardChannelRequest_);
    -  mockClock.tick(0);
    -}
    -
    -
    -function receive(data) {
    -  browserChannel.onRequestData(
    -      browserChannel.backChannelRequest_,
    -      '[[1,' + data + ']]');
    -  browserChannel.onRequestComplete(
    -      browserChannel.backChannelRequest_);
    -  mockClock.tick(0);
    -}
    -
    -
    -function responseTimeout() {
    -  browserChannel.forwardChannelRequest_lastError_ =
    -      goog.net.ChannelRequest.Error.TIMEOUT;
    -  browserChannel.forwardChannelRequest_.successful_ = false;
    -  browserChannel.onRequestComplete(
    -      browserChannel.forwardChannelRequest_);
    -  mockClock.tick(0);
    -}
    -
    -
    -function responseRequestFailed(opt_statusCode) {
    -  browserChannel.forwardChannelRequest_.lastError_ =
    -      goog.net.ChannelRequest.Error.STATUS;
    -  browserChannel.forwardChannelRequest_.lastStatusCode_ =
    -      opt_statusCode || 503;
    -  browserChannel.forwardChannelRequest_.successful_ = false;
    -  browserChannel.onRequestComplete(
    -      browserChannel.forwardChannelRequest_);
    -  mockClock.tick(0);
    -}
    -
    -
    -function responseUnknownSessionId() {
    -  browserChannel.forwardChannelRequest_.lastError_ =
    -      goog.net.ChannelRequest.Error.UNKNOWN_SESSION_ID;
    -  browserChannel.forwardChannelRequest_.successful_ = false;
    -  browserChannel.onRequestComplete(
    -      browserChannel.forwardChannelRequest_);
    -  mockClock.tick(0);
    -}
    -
    -
    -function responseActiveXBlocked() {
    -  browserChannel.backChannelRequest_.lastError_ =
    -      goog.net.ChannelRequest.Error.ACTIVE_X_BLOCKED;
    -  browserChannel.backChannelRequest_.successful_ = false;
    -  browserChannel.onRequestComplete(
    -      browserChannel.backChannelRequest_);
    -  mockClock.tick(0);
    -}
    -
    -
    -function sendMap(key, value, opt_context) {
    -  var map = new goog.structs.Map();
    -  map.set(key, value);
    -  browserChannel.sendMap(map, opt_context);
    -  mockClock.tick(0);
    -}
    -
    -
    -function hasForwardChannel() {
    -  return !!browserChannel.forwardChannelRequest_;
    -}
    -
    -
    -function hasBackChannel() {
    -  return !!browserChannel.backChannelRequest_;
    -}
    -
    -
    -function hasDeadBackChannelTimer() {
    -  return goog.isDefAndNotNull(browserChannel.deadBackChannelTimerId_);
    -}
    -
    -
    -function assertHasForwardChannel() {
    -  assertTrue('Forward channel missing.', hasForwardChannel());
    -}
    -
    -
    -function assertHasBackChannel() {
    -  assertTrue('Back channel missing.', hasBackChannel());
    -}
    -
    -
    -function testConnect() {
    -  connect();
    -  assertEquals(goog.net.BrowserChannel.State.OPENED,
    -      browserChannel.getState());
    -  // If the server specifies no version, the client assumes 6
    -  assertEquals(6, browserChannel.channelVersion_);
    -  assertFalse(browserChannel.isBuffered());
    -}
    -
    -function testConnect_backChannelEstablished() {
    -  connect();
    -  assertHasBackChannel();
    -}
    -
    -function testConnect_withServerHostPrefix() {
    -  connect(undefined, 'serverHostPrefix');
    -  assertEquals('serverHostPrefix', browserChannel.hostPrefix_);
    -}
    -
    -function testConnect_withClientHostPrefix() {
    -  handler.correctHostPrefix = function(hostPrefix) {
    -    return 'clientHostPrefix';
    -  };
    -  connect();
    -  assertEquals('clientHostPrefix', browserChannel.hostPrefix_);
    -}
    -
    -function testConnect_overrideServerHostPrefix() {
    -  handler.correctHostPrefix = function(hostPrefix) {
    -    return 'clientHostPrefix';
    -  };
    -  connect(undefined, 'serverHostPrefix');
    -  assertEquals('clientHostPrefix', browserChannel.hostPrefix_);
    -}
    -
    -function testConnect_withServerVersion() {
    -  connect(8);
    -  assertEquals(8, browserChannel.channelVersion_);
    -}
    -
    -function testConnect_notOkToMakeRequestForTest() {
    -  handler.okToMakeRequest =
    -      goog.functions.constant(goog.net.BrowserChannel.Error.NETWORK);
    -  browserChannel.connect('/test', '/bind', null);
    -  mockClock.tick(0);
    -  assertEquals(goog.net.BrowserChannel.State.CLOSED, browserChannel.getState());
    -}
    -
    -function testConnect_notOkToMakeRequestForBind() {
    -  browserChannel.connect('/test', '/bind', null);
    -  mockClock.tick(0);
    -  completeTestConnection();
    -  handler.okToMakeRequest =
    -      goog.functions.constant(goog.net.BrowserChannel.Error.NETWORK);
    -  completeForwardChannel();
    -  assertEquals(goog.net.BrowserChannel.State.CLOSED, browserChannel.getState());
    -}
    -
    -
    -function testSendMap() {
    -  connect();
    -  assertEquals(1, numTimingEvents);
    -  sendMap('foo', 'bar');
    -  responseVersion7();
    -  assertEquals(2, numTimingEvents);
    -  assertEquals('foo:bar', formatArrayOfMaps(deliveredMaps));
    -}
    -
    -
    -function testSendMap_twice() {
    -  connect();
    -  sendMap('foo1', 'bar1');
    -  responseVersion7();
    -  assertEquals('foo1:bar1', formatArrayOfMaps(deliveredMaps));
    -  sendMap('foo2', 'bar2');
    -  responseVersion7();
    -  assertEquals('foo2:bar2', formatArrayOfMaps(deliveredMaps));
    -}
    -
    -
    -function testSendMap_andReceive() {
    -  connect();
    -  sendMap('foo', 'bar');
    -  responseVersion7();
    -  receive('["the server reply"]');
    -}
    -
    -
    -function testReceive() {
    -  connect();
    -  receive('["message from server"]');
    -  assertHasBackChannel();
    -}
    -
    -
    -function testReceive_twice() {
    -  connect();
    -  receive('["message one from server"]');
    -  receive('["message two from server"]');
    -  assertHasBackChannel();
    -}
    -
    -
    -function testReceive_andSendMap() {
    -  connect();
    -  receive('["the server reply"]');
    -  sendMap('foo', 'bar');
    -  responseVersion7();
    -  assertHasBackChannel();
    -}
    -
    -
    -function testBackChannelRemainsEstablished_afterSingleSendMap() {
    -  connect();
    -
    -  sendMap('foo', 'bar');
    -  responseVersion7();
    -  receive('["ack"]');
    -
    -  assertHasBackChannel();
    -}
    -
    -
    -function testBackChannelRemainsEstablished_afterDoubleSendMap() {
    -  connect();
    -
    -  sendMap('foo1', 'bar1');
    -  sendMap('foo2', 'bar2');
    -  responseVersion7();
    -  receive('["ack"]');
    -
    -  // This assertion would fail prior to CL 13302660.
    -  assertHasBackChannel();
    -}
    -
    -
    -function testTimingEvent() {
    -  connect();
    -  assertEquals(1, numTimingEvents);
    -  sendMap('', '');
    -  assertEquals(1, numTimingEvents);
    -  mockClock.tick(20);
    -  var expSize = browserChannel.forwardChannelRequest_.getPostData().length;
    -  responseVersion7();
    -
    -  assertEquals(2, numTimingEvents);
    -  assertEquals(expSize, lastPostSize);
    -  assertEquals(20, lastPostRtt);
    -  assertEquals(0, lastPostRetryCount);
    -
    -  sendMap('abcdefg', '123456');
    -  expSize = browserChannel.forwardChannelRequest_.getPostData().length;
    -  responseTimeout();
    -  assertEquals(2, numTimingEvents);
    -  mockClock.tick(RETRY_TIME + 1);
    -  responseVersion7();
    -  assertEquals(3, numTimingEvents);
    -  assertEquals(expSize, lastPostSize);
    -  assertEquals(1, lastPostRetryCount);
    -  assertEquals(1, lastPostRtt);
    -
    -}
    -
    -
    -/**
    - * Make sure that dropping the forward channel retry limit below the retry count
    - * reports an error, and prevents another request from firing.
    - */
    -function testSetFailFastWhileWaitingForRetry() {
    -  stubTmpnetwork();
    -
    -  connect();
    -  assertEquals(1, numTimingEvents);
    -
    -  sendMap('foo', 'bar');
    -  assertNull(browserChannel.forwardChannelTimerId_);
    -  assertNotNull(browserChannel.forwardChannelRequest_);
    -  assertEquals(0, browserChannel.forwardChannelRetryCount_);
    -
    -  // Watchdog timeout.
    -  responseTimeout();
    -  assertNotNull(browserChannel.forwardChannelTimerId_);
    -  assertNull(browserChannel.forwardChannelRequest_);
    -  assertEquals(1, browserChannel.forwardChannelRetryCount_);
    -
    -  // Almost finish the between-retry timeout.
    -  mockClock.tick(RETRY_TIME - 1);
    -  assertNotNull(browserChannel.forwardChannelTimerId_);
    -  assertNull(browserChannel.forwardChannelRequest_);
    -  assertEquals(1, browserChannel.forwardChannelRetryCount_);
    -
    -  // Setting max retries to 0 should cancel the timer and raise an error.
    -  browserChannel.setFailFast(true);
    -  assertNull(browserChannel.forwardChannelTimerId_);
    -  assertNull(browserChannel.forwardChannelRequest_);
    -  assertEquals(1, browserChannel.forwardChannelRetryCount_);
    -
    -  assertTrue(gotError);
    -  assertEquals(0, deliveredMaps.length);
    -  // We get the error immediately before starting to ping google.com.
    -  // Simulate that timing out. We should get a network error in addition to the
    -  // initial failure.
    -  gotError = false;
    -  mockClock.tick(goog.net.tmpnetwork.GOOGLECOM_TIMEOUT);
    -  assertTrue('No error after tmpnetwork ping timed out.', gotError);
    -
    -  // Make sure no more retry timers are firing.
    -  mockClock.tick(ALL_DAY_MS);
    -  assertNull(browserChannel.forwardChannelTimerId_);
    -  assertNull(browserChannel.forwardChannelRequest_);
    -  assertEquals(1, browserChannel.forwardChannelRetryCount_);
    -  assertEquals(1, numTimingEvents);
    -}
    -
    -
    -/**
    - * Make sure that dropping the forward channel retry limit below the retry count
    - * reports an error, and prevents another request from firing.
    - */
    -function testSetFailFastWhileRetryXhrIsInFlight() {
    -  stubTmpnetwork();
    -
    -  connect();
    -  assertEquals(1, numTimingEvents);
    -
    -  sendMap('foo', 'bar');
    -  assertNull(browserChannel.forwardChannelTimerId_);
    -  assertNotNull(browserChannel.forwardChannelRequest_);
    -  assertEquals(0, browserChannel.forwardChannelRetryCount_);
    -
    -  // Watchdog timeout.
    -  responseTimeout();
    -  assertNotNull(browserChannel.forwardChannelTimerId_);
    -  assertNull(browserChannel.forwardChannelRequest_);
    -  assertEquals(1, browserChannel.forwardChannelRetryCount_);
    -
    -  // Wait for the between-retry timeout.
    -  mockClock.tick(RETRY_TIME);
    -  assertNull(browserChannel.forwardChannelTimerId_);
    -  assertNotNull(browserChannel.forwardChannelRequest_);
    -  assertEquals(1, browserChannel.forwardChannelRetryCount_);
    -
    -  // Simulate a second watchdog timeout.
    -  responseTimeout();
    -  assertNotNull(browserChannel.forwardChannelTimerId_);
    -  assertNull(browserChannel.forwardChannelRequest_);
    -  assertEquals(2, browserChannel.forwardChannelRetryCount_);
    -
    -  // Wait for another between-retry timeout.
    -  mockClock.tick(RETRY_TIME);
    -  // Now the third req is in flight.
    -  assertNull(browserChannel.forwardChannelTimerId_);
    -  assertNotNull(browserChannel.forwardChannelRequest_);
    -  assertEquals(2, browserChannel.forwardChannelRetryCount_);
    -
    -  // Set fail fast, killing the request
    -  browserChannel.setFailFast(true);
    -  assertNull(browserChannel.forwardChannelTimerId_);
    -  assertNull(browserChannel.forwardChannelRequest_);
    -  assertEquals(2, browserChannel.forwardChannelRetryCount_);
    -
    -  assertTrue(gotError);
    -  // We get the error immediately before starting to ping google.com.
    -  // Simulate that timing out. We should get a network error in addition to the
    -  gotError = false;
    -  mockClock.tick(goog.net.tmpnetwork.GOOGLECOM_TIMEOUT);
    -  assertTrue('No error after tmpnetwork ping timed out.', gotError);
    -
    -  // Make sure no more retry timers are firing.
    -  mockClock.tick(ALL_DAY_MS);
    -  assertNull(browserChannel.forwardChannelTimerId_);
    -  assertNull(browserChannel.forwardChannelRequest_);
    -  assertEquals(2, browserChannel.forwardChannelRetryCount_);
    -  assertEquals(1, numTimingEvents);
    -}
    -
    -
    -/**
    - * Makes sure that setting fail fast while not retrying doesn't cause a failure.
    - */
    -function testSetFailFastAtRetryCount() {
    -  stubTmpnetwork();
    -
    -  connect();
    -  assertEquals(1, numTimingEvents);
    -
    -  sendMap('foo', 'bar');
    -  assertNull(browserChannel.forwardChannelTimerId_);
    -  assertNotNull(browserChannel.forwardChannelRequest_);
    -  assertEquals(0, browserChannel.forwardChannelRetryCount_);
    -
    -  // Set fail fast.
    -  browserChannel.setFailFast(true);
    -  // Request should still be alive.
    -  assertNull(browserChannel.forwardChannelTimerId_);
    -  assertNotNull(browserChannel.forwardChannelRequest_);
    -  assertEquals(0, browserChannel.forwardChannelRetryCount_);
    -
    -  // Watchdog timeout. Now we should get an error.
    -  responseTimeout();
    -  assertNull(browserChannel.forwardChannelTimerId_);
    -  assertNull(browserChannel.forwardChannelRequest_);
    -  assertEquals(0, browserChannel.forwardChannelRetryCount_);
    -
    -  assertTrue(gotError);
    -  // We get the error immediately before starting to ping google.com.
    -  // Simulate that timing out. We should get a network error in addition to the
    -  // initial failure.
    -  gotError = false;
    -  mockClock.tick(goog.net.tmpnetwork.GOOGLECOM_TIMEOUT);
    -  assertTrue('No error after tmpnetwork ping timed out.', gotError);
    -
    -  // Make sure no more retry timers are firing.
    -  mockClock.tick(ALL_DAY_MS);
    -  assertNull(browserChannel.forwardChannelTimerId_);
    -  assertNull(browserChannel.forwardChannelRequest_);
    -  assertEquals(0, browserChannel.forwardChannelRetryCount_);
    -  assertEquals(1, numTimingEvents);
    -}
    -
    -
    -function testRequestFailedClosesChannel() {
    -  stubTmpnetwork();
    -
    -  connect();
    -  assertEquals(1, numTimingEvents);
    -
    -  sendMap('foo', 'bar');
    -  responseRequestFailed();
    -
    -  assertEquals('Should be closed immediately after request failed.',
    -      goog.net.BrowserChannel.State.CLOSED, browserChannel.getState());
    -
    -  mockClock.tick(goog.net.tmpnetwork.GOOGLECOM_TIMEOUT);
    -
    -  assertEquals('Should remain closed after the ping timeout.',
    -      goog.net.BrowserChannel.State.CLOSED, browserChannel.getState());
    -  assertEquals(1, numTimingEvents);
    -}
    -
    -
    -function testStatEventReportedOnlyOnce() {
    -  stubTmpnetwork();
    -
    -  connect();
    -  sendMap('foo', 'bar');
    -  numStatEvents = 0;
    -  lastStatEvent = null;
    -  responseUnknownSessionId();
    -
    -  assertEquals(1, numStatEvents);
    -  assertEquals(goog.net.BrowserChannel.Stat.ERROR_OTHER, lastStatEvent);
    -
    -  numStatEvents = 0;
    -  mockClock.tick(goog.net.tmpnetwork.GOOGLECOM_TIMEOUT);
    -  assertEquals('No new stat events should be reported.', 0, numStatEvents);
    -}
    -
    -
    -function testActiveXBlockedEventReportedOnlyOnce() {
    -  stubTmpnetwork();
    -
    -  connectForwardChannel();
    -  numStatEvents = 0;
    -  lastStatEvent = null;
    -  responseActiveXBlocked();
    -
    -  assertEquals(1, numStatEvents);
    -  assertEquals(goog.net.BrowserChannel.Stat.ERROR_OTHER, lastStatEvent);
    -
    -  mockClock.tick(goog.net.tmpnetwork.GOOGLECOM_TIMEOUT);
    -  assertEquals('No new stat events should be reported.', 1, numStatEvents);
    -}
    -
    -
    -function testStatEventReportedOnlyOnce_onNetworkUp() {
    -  stubTmpnetwork();
    -
    -  connect();
    -  sendMap('foo', 'bar');
    -  numStatEvents = 0;
    -  lastStatEvent = null;
    -  responseRequestFailed();
    -
    -  assertEquals('No stat event should be reported before we know the reason.',
    -      0, numStatEvents);
    -
    -  // Let the ping time out.
    -  mockClock.tick(goog.net.tmpnetwork.GOOGLECOM_TIMEOUT);
    -
    -  // Assert we report the correct stat event.
    -  assertEquals(1, numStatEvents);
    -  assertEquals(goog.net.BrowserChannel.Stat.ERROR_NETWORK, lastStatEvent);
    -}
    -
    -
    -function testStatEventReportedOnlyOnce_onNetworkDown() {
    -  stubTmpnetwork();
    -
    -  connect();
    -  sendMap('foo', 'bar');
    -  numStatEvents = 0;
    -  lastStatEvent = null;
    -  responseRequestFailed();
    -
    -  assertEquals('No stat event should be reported before we know the reason.',
    -      0, numStatEvents);
    -
    -  // Wait half the ping timeout period, and then fake the network being up.
    -  mockClock.tick(goog.net.tmpnetwork.GOOGLECOM_TIMEOUT / 2);
    -  browserChannel.testGoogleComCallback_(true);
    -
    -  // Assert we report the correct stat event.
    -  assertEquals(1, numStatEvents);
    -  assertEquals(goog.net.BrowserChannel.Stat.ERROR_OTHER, lastStatEvent);
    -}
    -
    -
    -function testOutgoingMapsAwaitsResponse() {
    -  connect();
    -  assertEquals(0, browserChannel.outgoingMaps_.length);
    -
    -  sendMap('foo1', 'bar');
    -  assertEquals(0, browserChannel.outgoingMaps_.length);
    -  sendMap('foo2', 'bar');
    -  assertEquals(1, browserChannel.outgoingMaps_.length);
    -  sendMap('foo3', 'bar');
    -  assertEquals(2, browserChannel.outgoingMaps_.length);
    -  sendMap('foo4', 'bar');
    -  assertEquals(3, browserChannel.outgoingMaps_.length);
    -
    -  responseVersion7();
    -  // Now the forward channel request is completed and a new started, so all maps
    -  // are dequeued from the array of outgoing maps into this new forward request.
    -  assertEquals(0, browserChannel.outgoingMaps_.length);
    -}
    -
    -
    -function testUndeliveredMaps_doesNotNotifyWhenSuccessful() {
    -  handler.channelClosed = function(
    -      channel, opt_pendingMaps, opt_undeliveredMaps) {
    -    if (opt_pendingMaps || opt_undeliveredMaps) {
    -      fail('No pending or undelivered maps should be reported.');
    -    }
    -  };
    -
    -  connect();
    -  sendMap('foo1', 'bar1');
    -  responseVersion7();
    -  sendMap('foo2', 'bar2');
    -  responseVersion7();
    -  disconnect();
    -}
    -
    -
    -function testUndeliveredMaps_doesNotNotifyIfNothingWasSent() {
    -  handler.channelClosed = function(
    -      channel, opt_pendingMaps, opt_undeliveredMaps) {
    -    if (opt_pendingMaps || opt_undeliveredMaps) {
    -      fail('No pending or undelivered maps should be reported.');
    -    }
    -  };
    -
    -  connect();
    -  mockClock.tick(ALL_DAY_MS);
    -  disconnect();
    -}
    -
    -
    -function testUndeliveredMaps_clearsPendingMapsAfterNotifying() {
    -  connect();
    -  sendMap('foo1', 'bar1');
    -  sendMap('foo2', 'bar2');
    -  sendMap('foo3', 'bar3');
    -
    -  assertEquals(1, browserChannel.pendingMaps_.length);
    -  assertEquals(2, browserChannel.outgoingMaps_.length);
    -
    -  disconnect();
    -
    -  assertEquals(0, browserChannel.pendingMaps_.length);
    -  assertEquals(0, browserChannel.outgoingMaps_.length);
    -}
    -
    -
    -function testUndeliveredMaps_notifiesWithContext() {
    -  connect();
    -
    -  // First send two messages that succeed.
    -  sendMap('foo1', 'bar1', 'context1');
    -  responseVersion7();
    -  sendMap('foo2', 'bar2', 'context2');
    -  responseVersion7();
    -
    -  // Pretend the server hangs and no longer responds.
    -  sendMap('foo3', 'bar3', 'context3');
    -  sendMap('foo4', 'bar4', 'context4');
    -  sendMap('foo5', 'bar5', 'context5');
    -
    -  // Give up.
    -  disconnect();
    -
    -  // Assert that we are informed of any undelivered messages; both about
    -  // #3 that was sent but which we don't know if the server received, and
    -  // #4 and #5 which remain in the outgoing maps and have not yet been sent.
    -  assertEquals('foo3:bar3:context3', handler.pendingMapsString);
    -  assertEquals('foo4:bar4:context4, foo5:bar5:context5',
    -      handler.undeliveredMapsString);
    -}
    -
    -
    -function testUndeliveredMaps_serviceUnavailable() {
    -  // Send a few maps, and let one fail.
    -  connect();
    -  sendMap('foo1', 'bar1');
    -  responseVersion7();
    -  sendMap('foo2', 'bar2');
    -  responseRequestFailed();
    -
    -  // After a failure, the channel should be closed.
    -  disconnect();
    -
    -  assertEquals('foo2:bar2', handler.pendingMapsString);
    -  assertEquals('', handler.undeliveredMapsString);
    -}
    -
    -
    -function testUndeliveredMaps_onPingTimeout() {
    -  stubTmpnetwork();
    -
    -  connect();
    -
    -  // Send a message.
    -  sendMap('foo1', 'bar1');
    -
    -  // Fake REQUEST_FAILED, triggering a ping to check the network.
    -  responseRequestFailed();
    -
    -  // Let the ping time out, unsuccessfully.
    -  mockClock.tick(goog.net.tmpnetwork.GOOGLECOM_TIMEOUT);
    -
    -  // Assert channel is closed.
    -  assertEquals(goog.net.BrowserChannel.State.CLOSED,
    -      browserChannel.getState());
    -
    -  // Assert that the handler is notified about the undelivered messages.
    -  assertEquals('foo1:bar1', handler.pendingMapsString);
    -  assertEquals('', handler.undeliveredMapsString);
    -}
    -
    -
    -function testResponseNoBackchannelPostNotBeforeBackchannel() {
    -  connect(8);
    -  sendMap('foo1', 'bar1');
    -
    -  mockClock.tick(10);
    -  assertFalse(browserChannel.backChannelRequest_.getRequestStartTime() <
    -      browserChannel.forwardChannelRequest_.getRequestStartTime());
    -  responseNoBackchannel();
    -  assertNotEquals(goog.net.BrowserChannel.Stat.BACKCHANNEL_MISSING,
    -      lastStatEvent);
    -}
    -
    -
    -function testResponseNoBackchannel() {
    -  connect(8);
    -  sendMap('foo1', 'bar1');
    -  response(-1, 0);
    -  mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE + 1);
    -  sendMap('foo2', 'bar2');
    -  assertTrue(browserChannel.backChannelRequest_.getRequestStartTime() +
    -      goog.net.BrowserChannel.RTT_ESTIMATE <
    -      browserChannel.forwardChannelRequest_.getRequestStartTime());
    -  responseNoBackchannel();
    -  assertEquals(goog.net.BrowserChannel.Stat.BACKCHANNEL_MISSING, lastStatEvent);
    -}
    -
    -
    -function testResponseNoBackchannelWithNoBackchannel() {
    -  connect(8);
    -  sendMap('foo1', 'bar1');
    -  assertNull(browserChannel.backChannelTimerId_);
    -  browserChannel.backChannelRequest_.cancel();
    -  browserChannel.backChannelRequest_ = null;
    -  responseNoBackchannel();
    -  assertEquals(goog.net.BrowserChannel.Stat.BACKCHANNEL_MISSING, lastStatEvent);
    -}
    -
    -
    -function testResponseNoBackchannelWithStartTimer() {
    -  connect(8);
    -  sendMap('foo1', 'bar1');
    -
    -  browserChannel.backChannelRequest_.cancel();
    -  browserChannel.backChannelRequest_ = null;
    -  browserChannel.backChannelTimerId_ = 123;
    -  responseNoBackchannel();
    -  assertNotEquals(goog.net.BrowserChannel.Stat.BACKCHANNEL_MISSING,
    -      lastStatEvent);
    -}
    -
    -
    -function testResponseWithNoArraySent() {
    -  connect(8);
    -  sendMap('foo1', 'bar1');
    -
    -  // Send a response as if the server hasn't sent down an array.
    -  response(-1, 0);
    -
    -  // POST response with an array ID lower than our last received is OK.
    -  assertEquals(1, browserChannel.lastArrayId_);
    -  assertEquals(-1, browserChannel.lastPostResponseArrayId_);
    -}
    -
    -
    -function testResponseWithArraysMissing() {
    -  connect(8);
    -  sendMap('foo1', 'bar1');
    -  assertEquals(-1, browserChannel.lastPostResponseArrayId_);
    -
    -  // Send a response as if the server has sent down seven arrays.
    -  response(7, 111);
    -
    -  assertEquals(1, browserChannel.lastArrayId_);
    -  assertEquals(7, browserChannel.lastPostResponseArrayId_);
    -  mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE * 2);
    -  assertEquals(goog.net.BrowserChannel.Stat.BACKCHANNEL_DEAD, lastStatEvent);
    -}
    -
    -
    -function testMultipleResponsesWithArraysMissing() {
    -  connect(8);
    -  sendMap('foo1', 'bar1');
    -  assertEquals(-1, browserChannel.lastPostResponseArrayId_);
    -
    -  // Send a response as if the server has sent down seven arrays.
    -  response(7, 111);
    -
    -  assertEquals(1, browserChannel.lastArrayId_);
    -  assertEquals(7, browserChannel.lastPostResponseArrayId_);
    -  sendMap('foo2', 'bar2');
    -  mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE);
    -  response(8, 119);
    -  mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE);
    -  // The original timer should still fire.
    -  assertEquals(goog.net.BrowserChannel.Stat.BACKCHANNEL_DEAD, lastStatEvent);
    -}
    -
    -
    -function testOnlyRetryOnceBasedOnResponse() {
    -  connect(8);
    -  sendMap('foo1', 'bar1');
    -  assertEquals(-1, browserChannel.lastPostResponseArrayId_);
    -
    -  // Send a response as if the server has sent down seven arrays.
    -  response(7, 111);
    -
    -  assertEquals(1, browserChannel.lastArrayId_);
    -  assertEquals(7, browserChannel.lastPostResponseArrayId_);
    -  assertTrue(hasDeadBackChannelTimer());
    -  mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE * 2);
    -  assertEquals(goog.net.BrowserChannel.Stat.BACKCHANNEL_DEAD, lastStatEvent);
    -  assertEquals(1, browserChannel.backChannelRetryCount_);
    -  mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE);
    -  sendMap('foo2', 'bar2');
    -  assertFalse(hasDeadBackChannelTimer());
    -  response(8, 119);
    -  assertFalse(hasDeadBackChannelTimer());
    -}
    -
    -
    -function testResponseWithArraysMissingAndLiveChannel() {
    -  connect(8);
    -  sendMap('foo1', 'bar1');
    -  assertEquals(-1, browserChannel.lastPostResponseArrayId_);
    -
    -  // Send a response as if the server has sent down seven arrays.
    -  response(7, 111);
    -
    -  assertEquals(1, browserChannel.lastArrayId_);
    -  assertEquals(7, browserChannel.lastPostResponseArrayId_);
    -  mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE);
    -  assertTrue(hasDeadBackChannelTimer());
    -  receive('["ack"]');
    -  assertFalse(hasDeadBackChannelTimer());
    -  mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE);
    -  assertNotEquals(goog.net.BrowserChannel.Stat.BACKCHANNEL_DEAD, lastStatEvent);
    -}
    -
    -
    -function testResponseWithBigOutstandingData() {
    -  connect(8);
    -  sendMap('foo1', 'bar1');
    -  assertEquals(-1, browserChannel.lastPostResponseArrayId_);
    -
    -  // Send a response as if the server has sent down seven arrays and 50kbytes.
    -  response(7, 50000);
    -
    -  assertEquals(1, browserChannel.lastArrayId_);
    -  assertEquals(7, browserChannel.lastPostResponseArrayId_);
    -  assertFalse(hasDeadBackChannelTimer());
    -  mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE * 2);
    -  assertNotEquals(goog.net.BrowserChannel.Stat.BACKCHANNEL_DEAD,
    -      lastStatEvent);
    -}
    -
    -
    -function testResponseInBufferedMode() {
    -  connect(8);
    -  browserChannel.useChunked_ = false;
    -  sendMap('foo1', 'bar1');
    -  assertEquals(-1, browserChannel.lastPostResponseArrayId_);
    -  response(7, 111);
    -
    -  assertEquals(1, browserChannel.lastArrayId_);
    -  assertEquals(7, browserChannel.lastPostResponseArrayId_);
    -  assertFalse(hasDeadBackChannelTimer());
    -  mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE * 2);
    -  assertNotEquals(goog.net.BrowserChannel.Stat.BACKCHANNEL_DEAD,
    -      lastStatEvent);
    -}
    -
    -
    -function testResponseWithGarbage() {
    -  connect(8);
    -  sendMap('foo1', 'bar1');
    -  browserChannel.onRequestData(
    -      browserChannel.forwardChannelRequest_,
    -      'garbage'
    -  );
    -  assertEquals(goog.net.BrowserChannel.State.CLOSED,
    -      browserChannel.getState());
    -}
    -
    -
    -function testResponseWithGarbageInArray() {
    -  connect(8);
    -  sendMap('foo1', 'bar1');
    -  browserChannel.onRequestData(
    -      browserChannel.forwardChannelRequest_,
    -      '["garbage"]'
    -  );
    -  assertEquals(goog.net.BrowserChannel.State.CLOSED,
    -      browserChannel.getState());
    -}
    -
    -
    -function testResponseWithEvilData() {
    -  connect(8);
    -  sendMap('foo1', 'bar1');
    -  browserChannel.onRequestData(
    -      browserChannel.forwardChannelRequest_,
    -      goog.net.BrowserChannel.LAST_ARRAY_ID_RESPONSE_PREFIX +
    -          '=<script>evil()\<\/script>&' +
    -      goog.net.BrowserChannel.OUTSTANDING_DATA_RESPONSE_PREFIX +
    -          '=<script>moreEvil()\<\/script>');
    -  assertEquals(goog.net.BrowserChannel.State.CLOSED,
    -      browserChannel.getState());
    -}
    -
    -
    -function testPathAbsolute() {
    -  connect(8, undefined, '/talkgadget');
    -  assertEquals(browserChannel.backChannelUri_.getDomain(),
    -      window.location.hostname);
    -  assertEquals(browserChannel.forwardChannelUri_.getDomain(),
    -      window.location.hostname);
    -}
    -
    -
    -function testPathRelative() {
    -  connect(8, undefined, 'talkgadget');
    -  assertEquals(browserChannel.backChannelUri_.getDomain(),
    -      window.location.hostname);
    -  assertEquals(browserChannel.forwardChannelUri_.getDomain(),
    -      window.location.hostname);
    -}
    -
    -
    -function testPathWithHost() {
    -  connect(8, undefined, 'https://example.com');
    -  assertEquals(browserChannel.backChannelUri_.getScheme(), 'https');
    -  assertEquals(browserChannel.backChannelUri_.getDomain(), 'example.com');
    -  assertEquals(browserChannel.forwardChannelUri_.getScheme(), 'https');
    -  assertEquals(browserChannel.forwardChannelUri_.getDomain(), 'example.com');
    -}
    -
    -function testCreateXhrIo() {
    -  var xhr = browserChannel.createXhrIo(null);
    -  assertFalse(xhr.getWithCredentials());
    -
    -  assertThrows(
    -      'Error connection to different host without CORS',
    -      goog.bind(browserChannel.createXhrIo, browserChannel, 'some_host'));
    -
    -  browserChannel.setSupportsCrossDomainXhrs(true);
    -
    -  xhr = browserChannel.createXhrIo(null);
    -  assertTrue(xhr.getWithCredentials());
    -
    -  xhr = browserChannel.createXhrIo('some_host');
    -  assertTrue(xhr.getWithCredentials());
    -}
    -
    -function testSetParser() {
    -  var recordUnsafeParse = goog.testing.recordFunction(
    -      goog.json.unsafeParse);
    -  var parser = {};
    -  parser.parse = recordUnsafeParse;
    -  browserChannel.setParser(parser);
    -
    -  connect();
    -  assertEquals(3, recordUnsafeParse.getCallCount());
    -
    -  var call3 = recordUnsafeParse.popLastCall();
    -  var call2 = recordUnsafeParse.popLastCall();
    -  var call1 = recordUnsafeParse.popLastCall();
    -
    -  assertEquals(1, call1.getArguments().length);
    -  assertEquals('["b"]', call1.getArgument(0));
    -
    -  assertEquals(1, call2.getArguments().length);
    -  assertEquals('[[0,["c","1234567890ABCDEF",null]]]', call2.getArgument(0));
    -
    -  assertEquals(1, call3.getArguments().length);
    -  assertEquals('[[1,["foo"]]]', call3.getArgument(0));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/net/browsertestchannel.js b/src/database/third_party/closure-library/closure/goog/net/browsertestchannel.js
    deleted file mode 100644
    index 0245800c5da..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/browsertestchannel.js
    +++ /dev/null
    @@ -1,619 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Definition of the BrowserTestChannel class.  A
    - * BrowserTestChannel is used during the first part of channel negotiation
    - * with the server to create the channel. It helps us determine whether we're
    - * behind a buffering proxy. It also runs the logic to see if the channel
    - * has been blocked by a network administrator. This class is part of the
    - * BrowserChannel implementation and is not for use by normal application code.
    - *
    - */
    -
    -
    -
    -goog.provide('goog.net.BrowserTestChannel');
    -
    -goog.require('goog.json.EvalJsonProcessor');
    -goog.require('goog.net.ChannelRequest');
    -goog.require('goog.net.ChannelRequest.Error');
    -goog.require('goog.net.tmpnetwork');
    -goog.require('goog.string.Parser');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Encapsulates the logic for a single BrowserTestChannel.
    - *
    - * @constructor
    - * @param {goog.net.BrowserChannel} channel  The BrowserChannel that owns this
    - *     test channel.
    - * @param {goog.net.ChannelDebug} channelDebug A ChannelDebug to use for
    - *     logging.
    - * @final
    - */
    -goog.net.BrowserTestChannel = function(channel, channelDebug) {
    -  /**
    -   * The BrowserChannel that owns this test channel
    -   * @type {goog.net.BrowserChannel}
    -   * @private
    -   */
    -  this.channel_ = channel;
    -
    -  /**
    -   * The channel debug to use for logging
    -   * @type {goog.net.ChannelDebug}
    -   * @private
    -   */
    -  this.channelDebug_ = channelDebug;
    -
    -  /**
    -   * Parser for a response payload. Defaults to use
    -   * {@code goog.json.unsafeParse}. The parser should return an array.
    -   * @type {goog.string.Parser}
    -   * @private
    -   */
    -  this.parser_ = new goog.json.EvalJsonProcessor(null, true);
    -};
    -
    -
    -/**
    - * Extra HTTP headers to add to all the requests sent to the server.
    - * @type {Object}
    - * @private
    - */
    -goog.net.BrowserTestChannel.prototype.extraHeaders_ = null;
    -
    -
    -/**
    - * The test request.
    - * @type {goog.net.ChannelRequest}
    - * @private
    - */
    -goog.net.BrowserTestChannel.prototype.request_ = null;
    -
    -
    -/**
    - * Whether we have received the first result as an intermediate result. This
    - * helps us determine whether we're behind a buffering proxy.
    - * @type {boolean}
    - * @private
    - */
    -goog.net.BrowserTestChannel.prototype.receivedIntermediateResult_ = false;
    -
    -
    -/**
    - * The time when the test request was started. We use timing in IE as
    - * a heuristic for whether we're behind a buffering proxy.
    - * @type {?number}
    - * @private
    - */
    -goog.net.BrowserTestChannel.prototype.startTime_ = null;
    -
    -
    -/**
    - * The time for of the first result part. We use timing in IE as a
    - * heuristic for whether we're behind a buffering proxy.
    - * @type {?number}
    - * @private
    - */
    -goog.net.BrowserTestChannel.prototype.firstTime_ = null;
    -
    -
    -/**
    - * The time for of the last result part. We use timing in IE as a
    - * heuristic for whether we're behind a buffering proxy.
    - * @type {?number}
    - * @private
    - */
    -goog.net.BrowserTestChannel.prototype.lastTime_ = null;
    -
    -
    -/**
    - * The relative path for test requests.
    - * @type {?string}
    - * @private
    - */
    -goog.net.BrowserTestChannel.prototype.path_ = null;
    -
    -
    -/**
    - * The state of the state machine for this object.
    - *
    - * @type {?number}
    - * @private
    - */
    -goog.net.BrowserTestChannel.prototype.state_ = null;
    -
    -
    -/**
    - * The last status code received.
    - * @type {number}
    - * @private
    - */
    -goog.net.BrowserTestChannel.prototype.lastStatusCode_ = -1;
    -
    -
    -/**
    - * A subdomain prefix for using a subdomain in IE for the backchannel
    - * requests.
    - * @type {?string}
    - * @private
    - */
    -goog.net.BrowserTestChannel.prototype.hostPrefix_ = null;
    -
    -
    -/**
    - * A subdomain prefix for testing whether the channel was disabled by
    - * a network administrator;
    - * @type {?string}
    - * @private
    - */
    -goog.net.BrowserTestChannel.prototype.blockedPrefix_ = null;
    -
    -
    -/**
    - * Enum type for the browser test channel state machine
    - * @enum {number}
    - * @private
    - */
    -goog.net.BrowserTestChannel.State_ = {
    -  /**
    -   * The state for the BrowserTestChannel state machine where we making the
    -   * initial call to get the server configured parameters.
    -   */
    -  INIT: 0,
    -
    -  /**
    -   * The state for the BrowserTestChannel state machine where we're checking to
    -   * see if the channel has been blocked.
    -   */
    -  CHECKING_BLOCKED: 1,
    -
    -  /**
    -   * The  state for the BrowserTestChannel state machine where we're checking to
    -   * se if we're behind a buffering proxy.
    -   */
    -  CONNECTION_TESTING: 2
    -};
    -
    -
    -/**
    - * Time in MS for waiting for the request to see if the channel is blocked.
    - * If the response takes longer than this many ms, we assume the request has
    - * failed.
    - * @type {number}
    - * @private
    - */
    -goog.net.BrowserTestChannel.BLOCKED_TIMEOUT_ = 5000;
    -
    -
    -/**
    - * Number of attempts to try to see if the check to see if we're blocked
    - * succeeds. Sometimes the request can fail because of flaky network conditions
    - * and checking multiple times reduces false positives.
    - * @type {number}
    - * @private
    - */
    -goog.net.BrowserTestChannel.BLOCKED_RETRIES_ = 3;
    -
    -
    -/**
    - * Time in ms between retries of the blocked request
    - * @type {number}
    - * @private
    - */
    -goog.net.BrowserTestChannel.BLOCKED_PAUSE_BETWEEN_RETRIES_ = 2000;
    -
    -
    -/**
    - * Time between chunks in the test connection that indicates that we
    - * are not behind a buffering proxy. This value should be less than or
    - * equals to the time between chunks sent from the server.
    - * @type {number}
    - * @private
    - */
    -goog.net.BrowserTestChannel.MIN_TIME_EXPECTED_BETWEEN_DATA_ = 500;
    -
    -
    -/**
    - * Sets extra HTTP headers to add to all the requests sent to the server.
    - *
    - * @param {Object} extraHeaders The HTTP headers.
    - */
    -goog.net.BrowserTestChannel.prototype.setExtraHeaders = function(extraHeaders) {
    -  this.extraHeaders_ = extraHeaders;
    -};
    -
    -
    -/**
    - * Sets a new parser for the response payload. A custom parser may be set to
    - * avoid using eval(), for example.
    - * By default, the parser uses {@code goog.json.unsafeParse}.
    - * @param {!goog.string.Parser} parser Parser.
    - */
    -goog.net.BrowserTestChannel.prototype.setParser = function(parser) {
    -  this.parser_ = parser;
    -};
    -
    -
    -/**
    - * Starts the test channel. This initiates connections to the server.
    - *
    - * @param {string} path The relative uri for the test connection.
    - */
    -goog.net.BrowserTestChannel.prototype.connect = function(path) {
    -  this.path_ = path;
    -  var sendDataUri = this.channel_.getForwardChannelUri(this.path_);
    -
    -  goog.net.BrowserChannel.notifyStatEvent(
    -      goog.net.BrowserChannel.Stat.TEST_STAGE_ONE_START);
    -  this.startTime_ = goog.now();
    -
    -  // If the channel already has the result of the first test, then skip it.
    -  var firstTestResults = this.channel_.getFirstTestResults();
    -  if (goog.isDefAndNotNull(firstTestResults)) {
    -    this.hostPrefix_ = this.channel_.correctHostPrefix(firstTestResults[0]);
    -    this.blockedPrefix_ = firstTestResults[1];
    -    if (this.blockedPrefix_) {
    -      this.state_ = goog.net.BrowserTestChannel.State_.CHECKING_BLOCKED;
    -      this.checkBlocked_();
    -    } else {
    -      this.state_ = goog.net.BrowserTestChannel.State_.CONNECTION_TESTING;
    -      this.connectStage2_();
    -    }
    -    return;
    -  }
    -
    -  // the first request returns server specific parameters
    -  sendDataUri.setParameterValues('MODE', 'init');
    -  this.request_ = goog.net.BrowserChannel.createChannelRequest(
    -      this, this.channelDebug_);
    -  this.request_.setExtraHeaders(this.extraHeaders_);
    -  this.request_.xmlHttpGet(sendDataUri, false /* decodeChunks */,
    -      null /* hostPrefix */, true /* opt_noClose */);
    -  this.state_ = goog.net.BrowserTestChannel.State_.INIT;
    -};
    -
    -
    -/**
    - * Checks to see whether the channel is blocked. This is for implementing the
    - * feature that allows network administrators to block Gmail Chat. The
    - * strategy to determine if we're blocked is to try to load an image off a
    - * special subdomain that network administrators will block access to if they
    - * are trying to block chat. For Gmail Chat, the subdomain is
    - * chatenabled.mail.google.com.
    - * @private
    - */
    -goog.net.BrowserTestChannel.prototype.checkBlocked_ = function() {
    -  var uri = this.channel_.createDataUri(this.blockedPrefix_,
    -      '/mail/images/cleardot.gif');
    -  uri.makeUnique();
    -  goog.net.tmpnetwork.testLoadImageWithRetries(uri.toString(),
    -      goog.net.BrowserTestChannel.BLOCKED_TIMEOUT_,
    -      goog.bind(this.checkBlockedCallback_, this),
    -      goog.net.BrowserTestChannel.BLOCKED_RETRIES_,
    -      goog.net.BrowserTestChannel.BLOCKED_PAUSE_BETWEEN_RETRIES_);
    -  this.notifyServerReachabilityEvent(
    -      goog.net.BrowserChannel.ServerReachability.REQUEST_MADE);
    -};
    -
    -
    -/**
    - * Callback for testLoadImageWithRetries to check if browser channel is
    - * blocked.
    - * @param {boolean} succeeded Whether the request succeeded.
    - * @private
    - */
    -goog.net.BrowserTestChannel.prototype.checkBlockedCallback_ = function(
    -    succeeded) {
    -  if (succeeded) {
    -    this.state_ = goog.net.BrowserTestChannel.State_.CONNECTION_TESTING;
    -    this.connectStage2_();
    -  } else {
    -    goog.net.BrowserChannel.notifyStatEvent(
    -        goog.net.BrowserChannel.Stat.CHANNEL_BLOCKED);
    -    this.channel_.testConnectionBlocked(this);
    -  }
    -
    -  // We don't dispatch a REQUEST_FAILED server reachability event when the
    -  // block request fails, as such a failure is not a good signal that the
    -  // server has actually become unreachable.
    -  if (succeeded) {
    -    this.notifyServerReachabilityEvent(
    -        goog.net.BrowserChannel.ServerReachability.REQUEST_SUCCEEDED);
    -  }
    -};
    -
    -
    -/**
    - * Begins the second stage of the test channel where we test to see if we're
    - * behind a buffering proxy. The server sends back a multi-chunked response
    - * with the first chunk containing the content '1' and then two seconds later
    - * sending the second chunk containing the content '2'. Depending on how we
    - * receive the content, we can tell if we're behind a buffering proxy.
    - * @private
    - */
    -goog.net.BrowserTestChannel.prototype.connectStage2_ = function() {
    -  this.channelDebug_.debug('TestConnection: starting stage 2');
    -
    -  // If the second test results are available, skip its execution.
    -  var secondTestResults = this.channel_.getSecondTestResults();
    -  if (goog.isDefAndNotNull(secondTestResults)) {
    -    this.channelDebug_.debug(
    -        'TestConnection: skipping stage 2, precomputed result is '
    -        + secondTestResults ? 'Buffered' : 'Unbuffered');
    -    goog.net.BrowserChannel.notifyStatEvent(
    -        goog.net.BrowserChannel.Stat.TEST_STAGE_TWO_START);
    -    if (secondTestResults) { // Buffered/Proxy connection
    -      goog.net.BrowserChannel.notifyStatEvent(
    -          goog.net.BrowserChannel.Stat.PROXY);
    -      this.channel_.testConnectionFinished(this, false);
    -    } else { // Unbuffered/NoProxy connection
    -      goog.net.BrowserChannel.notifyStatEvent(
    -          goog.net.BrowserChannel.Stat.NOPROXY);
    -      this.channel_.testConnectionFinished(this, true);
    -    }
    -    return; // Skip the test
    -  }
    -  this.request_ = goog.net.BrowserChannel.createChannelRequest(
    -      this, this.channelDebug_);
    -  this.request_.setExtraHeaders(this.extraHeaders_);
    -  var recvDataUri = this.channel_.getBackChannelUri(this.hostPrefix_,
    -      /** @type {string} */ (this.path_));
    -
    -  goog.net.BrowserChannel.notifyStatEvent(
    -      goog.net.BrowserChannel.Stat.TEST_STAGE_TWO_START);
    -  if (!goog.net.ChannelRequest.supportsXhrStreaming()) {
    -    recvDataUri.setParameterValues('TYPE', 'html');
    -    this.request_.tridentGet(recvDataUri, Boolean(this.hostPrefix_));
    -  } else {
    -    recvDataUri.setParameterValues('TYPE', 'xmlhttp');
    -    this.request_.xmlHttpGet(recvDataUri, false /** decodeChunks */,
    -        this.hostPrefix_, false /** opt_noClose */);
    -  }
    -};
    -
    -
    -/**
    - * Factory method for XhrIo objects.
    - * @param {?string} hostPrefix The host prefix, if we need an XhrIo object
    - *     capable of calling a secondary domain.
    - * @return {!goog.net.XhrIo} New XhrIo object.
    - */
    -goog.net.BrowserTestChannel.prototype.createXhrIo = function(hostPrefix) {
    -  return this.channel_.createXhrIo(hostPrefix);
    -};
    -
    -
    -/**
    - * Aborts the test channel.
    - */
    -goog.net.BrowserTestChannel.prototype.abort = function() {
    -  if (this.request_) {
    -    this.request_.cancel();
    -    this.request_ = null;
    -  }
    -  this.lastStatusCode_ = -1;
    -};
    -
    -
    -/**
    - * Returns whether the test channel is closed. The ChannelRequest object expects
    - * this method to be implemented on its handler.
    - *
    - * @return {boolean} Whether the channel is closed.
    - */
    -goog.net.BrowserTestChannel.prototype.isClosed = function() {
    -  return false;
    -};
    -
    -
    -/**
    - * Callback from ChannelRequest for when new data is received
    - *
    - * @param {goog.net.ChannelRequest} req  The request object.
    - * @param {string} responseText The text of the response.
    - */
    -goog.net.BrowserTestChannel.prototype.onRequestData =
    -    function(req, responseText) {
    -  this.lastStatusCode_ = req.getLastStatusCode();
    -  if (this.state_ == goog.net.BrowserTestChannel.State_.INIT) {
    -    this.channelDebug_.debug('TestConnection: Got data for stage 1');
    -    if (!responseText) {
    -      this.channelDebug_.debug('TestConnection: Null responseText');
    -      // The server should always send text; something is wrong here
    -      this.channel_.testConnectionFailure(this,
    -          goog.net.ChannelRequest.Error.BAD_DATA);
    -      return;
    -    }
    -    /** @preserveTry */
    -    try {
    -      var respArray = this.parser_.parse(responseText);
    -    } catch (e) {
    -      this.channelDebug_.dumpException(e);
    -      this.channel_.testConnectionFailure(this,
    -          goog.net.ChannelRequest.Error.BAD_DATA);
    -      return;
    -    }
    -    this.hostPrefix_ = this.channel_.correctHostPrefix(respArray[0]);
    -    this.blockedPrefix_ = respArray[1];
    -  } else if (this.state_ ==
    -             goog.net.BrowserTestChannel.State_.CONNECTION_TESTING) {
    -    if (this.receivedIntermediateResult_) {
    -      goog.net.BrowserChannel.notifyStatEvent(
    -          goog.net.BrowserChannel.Stat.TEST_STAGE_TWO_DATA_TWO);
    -      this.lastTime_ = goog.now();
    -    } else {
    -      // '11111' is used instead of '1' to prevent a small amount of buffering
    -      // by Safari.
    -      if (responseText == '11111') {
    -        goog.net.BrowserChannel.notifyStatEvent(
    -            goog.net.BrowserChannel.Stat.TEST_STAGE_TWO_DATA_ONE);
    -        this.receivedIntermediateResult_ = true;
    -        this.firstTime_ = goog.now();
    -        if (this.checkForEarlyNonBuffered_()) {
    -          // If early chunk detection is on, and we passed the tests,
    -          // assume HTTP_OK, cancel the test and turn on noproxy mode.
    -          this.lastStatusCode_ = 200;
    -          this.request_.cancel();
    -          this.channelDebug_.debug(
    -              'Test connection succeeded; using streaming connection');
    -          goog.net.BrowserChannel.notifyStatEvent(
    -              goog.net.BrowserChannel.Stat.NOPROXY);
    -          this.channel_.testConnectionFinished(this, true);
    -        }
    -      } else {
    -        goog.net.BrowserChannel.notifyStatEvent(
    -            goog.net.BrowserChannel.Stat.TEST_STAGE_TWO_DATA_BOTH);
    -        this.firstTime_ = this.lastTime_ = goog.now();
    -        this.receivedIntermediateResult_ = false;
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Callback from ChannelRequest that indicates a request has completed.
    - *
    - * @param {goog.net.ChannelRequest} req  The request object.
    - */
    -goog.net.BrowserTestChannel.prototype.onRequestComplete =
    -    function(req) {
    -  this.lastStatusCode_ = this.request_.getLastStatusCode();
    -  if (!this.request_.getSuccess()) {
    -    this.channelDebug_.debug(
    -        'TestConnection: request failed, in state ' + this.state_);
    -    if (this.state_ == goog.net.BrowserTestChannel.State_.INIT) {
    -      goog.net.BrowserChannel.notifyStatEvent(
    -          goog.net.BrowserChannel.Stat.TEST_STAGE_ONE_FAILED);
    -    } else if (this.state_ ==
    -               goog.net.BrowserTestChannel.State_.CONNECTION_TESTING) {
    -      goog.net.BrowserChannel.notifyStatEvent(
    -          goog.net.BrowserChannel.Stat.TEST_STAGE_TWO_FAILED);
    -    }
    -    this.channel_.testConnectionFailure(this,
    -        /** @type {goog.net.ChannelRequest.Error} */
    -        (this.request_.getLastError()));
    -    return;
    -  }
    -
    -  if (this.state_ == goog.net.BrowserTestChannel.State_.INIT) {
    -    this.channelDebug_.debug(
    -        'TestConnection: request complete for initial check');
    -    if (this.blockedPrefix_) {
    -      this.state_ = goog.net.BrowserTestChannel.State_.CHECKING_BLOCKED;
    -      this.checkBlocked_();
    -    } else {
    -      this.state_ = goog.net.BrowserTestChannel.State_.CONNECTION_TESTING;
    -      this.connectStage2_();
    -    }
    -  } else if (this.state_ ==
    -             goog.net.BrowserTestChannel.State_.CONNECTION_TESTING) {
    -    this.channelDebug_.debug('TestConnection: request complete for stage 2');
    -    var goodConn = false;
    -
    -    if (!goog.net.ChannelRequest.supportsXhrStreaming()) {
    -      // we always get Trident responses in separate calls to
    -      // onRequestData, so we have to check the time they came
    -      var ms = this.lastTime_ - this.firstTime_;
    -      if (ms < 200) {
    -        // TODO: need to empirically verify that this number is OK
    -        // for slow computers
    -        goodConn = false;
    -      } else {
    -        goodConn = true;
    -      }
    -    } else {
    -      goodConn = this.receivedIntermediateResult_;
    -    }
    -
    -    if (goodConn) {
    -      this.channelDebug_.debug(
    -          'Test connection succeeded; using streaming connection');
    -      goog.net.BrowserChannel.notifyStatEvent(
    -          goog.net.BrowserChannel.Stat.NOPROXY);
    -      this.channel_.testConnectionFinished(this, true);
    -    } else {
    -      this.channelDebug_.debug(
    -          'Test connection failed; not using streaming');
    -      goog.net.BrowserChannel.notifyStatEvent(
    -          goog.net.BrowserChannel.Stat.PROXY);
    -      this.channel_.testConnectionFinished(this, false);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Returns the last status code received for a request.
    - * @return {number} The last status code received for a request.
    - */
    -goog.net.BrowserTestChannel.prototype.getLastStatusCode = function() {
    -  return this.lastStatusCode_;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether we should be using secondary domains when the
    - *     server instructs us to do so.
    - */
    -goog.net.BrowserTestChannel.prototype.shouldUseSecondaryDomains = function() {
    -  return this.channel_.shouldUseSecondaryDomains();
    -};
    -
    -
    -/**
    - * Gets whether this channel is currently active. This is used to determine the
    - * length of time to wait before retrying.
    - *
    - * @param {goog.net.BrowserChannel} browserChannel The browser channel.
    - * @return {boolean} Whether the channel is currently active.
    - */
    -goog.net.BrowserTestChannel.prototype.isActive =
    -    function(browserChannel) {
    -  return this.channel_.isActive();
    -};
    -
    -
    -/**
    - * @return {boolean} True if test stage 2 detected a non-buffered
    - *     channel early and early no buffering detection is enabled.
    - * @private
    - */
    -goog.net.BrowserTestChannel.prototype.checkForEarlyNonBuffered_ =
    -    function() {
    -  var ms = this.firstTime_ - this.startTime_;
    -
    -  // we always get Trident responses in separate calls to
    -  // onRequestData, so we have to check the time that the first came in
    -  // and verify that the data arrived before the second portion could
    -  // have been sent. For all other browser's we skip the timing test.
    -  return goog.net.ChannelRequest.supportsXhrStreaming() ||
    -      ms < goog.net.BrowserTestChannel.MIN_TIME_EXPECTED_BETWEEN_DATA_;
    -};
    -
    -
    -/**
    - * Notifies the channel of a fine grained network event.
    - * @param {goog.net.BrowserChannel.ServerReachability} reachabilityType The
    - *     reachability event type.
    - */
    -goog.net.BrowserTestChannel.prototype.notifyServerReachabilityEvent =
    -    function(reachabilityType) {
    -  this.channel_.notifyServerReachabilityEvent(reachabilityType);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/net/bulkloader.js b/src/database/third_party/closure-library/closure/goog/net/bulkloader.js
    deleted file mode 100644
    index a42a4e97fe9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/bulkloader.js
    +++ /dev/null
    @@ -1,182 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Loads a list of URIs in bulk. All requests must be a success
    - * in order for the load to be considered a success.
    - *
    - */
    -
    -goog.provide('goog.net.BulkLoader');
    -
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.log');
    -goog.require('goog.net.BulkLoaderHelper');
    -goog.require('goog.net.EventType');
    -goog.require('goog.net.XhrIo');
    -
    -
    -
    -/**
    - * Class used to load multiple URIs.
    - * @param {Array<string|goog.Uri>} uris The URIs to load.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - * @final
    - */
    -goog.net.BulkLoader = function(uris) {
    -  goog.events.EventTarget.call(this);
    -
    -  /**
    -   * The bulk loader helper.
    -   * @type {goog.net.BulkLoaderHelper}
    -   * @private
    -   */
    -  this.helper_ = new goog.net.BulkLoaderHelper(uris);
    -
    -  /**
    -   * The handler for managing events.
    -   * @type {goog.events.EventHandler<!goog.net.BulkLoader>}
    -   * @private
    -   */
    -  this.eventHandler_ = new goog.events.EventHandler(this);
    -};
    -goog.inherits(goog.net.BulkLoader, goog.events.EventTarget);
    -
    -
    -/**
    - * A logger.
    - * @type {goog.log.Logger}
    - * @private
    - */
    -goog.net.BulkLoader.prototype.logger_ =
    -    goog.log.getLogger('goog.net.BulkLoader');
    -
    -
    -/**
    - * Gets the response texts, in order.
    - * @return {Array<string>} The response texts.
    - */
    -goog.net.BulkLoader.prototype.getResponseTexts = function() {
    -  return this.helper_.getResponseTexts();
    -};
    -
    -
    -/**
    - * Gets the request Uris.
    - * @return {Array<string>} The request URIs, in order.
    - */
    -goog.net.BulkLoader.prototype.getRequestUris = function() {
    -  return this.helper_.getUris();
    -};
    -
    -
    -/**
    - * Starts the process of loading the URIs.
    - */
    -goog.net.BulkLoader.prototype.load = function() {
    -  var eventHandler = this.eventHandler_;
    -  var uris = this.helper_.getUris();
    -  goog.log.info(this.logger_,
    -      'Starting load of code with ' + uris.length + ' uris.');
    -
    -  for (var i = 0; i < uris.length; i++) {
    -    var xhrIo = new goog.net.XhrIo();
    -    eventHandler.listen(xhrIo,
    -        goog.net.EventType.COMPLETE,
    -        goog.bind(this.handleEvent_, this, i));
    -
    -    xhrIo.send(uris[i]);
    -  }
    -};
    -
    -
    -/**
    - * Handles all events fired by the XhrManager.
    - * @param {number} id The id of the request.
    - * @param {goog.events.Event} e The event.
    - * @private
    - */
    -goog.net.BulkLoader.prototype.handleEvent_ = function(id, e) {
    -  goog.log.info(this.logger_, 'Received event "' + e.type + '" for id ' + id +
    -      ' with uri ' + this.helper_.getUri(id));
    -  var xhrIo = /** @type {goog.net.XhrIo} */ (e.target);
    -  if (xhrIo.isSuccess()) {
    -    this.handleSuccess_(id, xhrIo);
    -  } else {
    -    this.handleError_(id, xhrIo);
    -  }
    -};
    -
    -
    -/**
    - * Handles when a request is successful (i.e., completed and response received).
    - * Stores thhe responseText and checks if loading is complete.
    - * @param {number} id The id of the request.
    - * @param {goog.net.XhrIo} xhrIo The XhrIo objects that was used.
    - * @private
    - */
    -goog.net.BulkLoader.prototype.handleSuccess_ = function(
    -    id, xhrIo) {
    -  // Save the response text.
    -  this.helper_.setResponseText(id, xhrIo.getResponseText());
    -
    -  // Check if all response texts have been received.
    -  if (this.helper_.isLoadComplete()) {
    -    this.finishLoad_();
    -  }
    -  xhrIo.dispose();
    -};
    -
    -
    -/**
    - * Handles when a request has ended in error (i.e., all retries completed and
    - * none were successful). Cancels loading of the URI's.
    - * @param {number|string} id The id of the request.
    - * @param {goog.net.XhrIo} xhrIo The XhrIo objects that was used.
    - * @private
    - */
    -goog.net.BulkLoader.prototype.handleError_ = function(
    -    id, xhrIo) {
    -  // TODO(user): Abort all pending requests.
    -
    -  // Dispatch the ERROR event.
    -  this.dispatchEvent(goog.net.EventType.ERROR);
    -  xhrIo.dispose();
    -};
    -
    -
    -/**
    - * Finishes the load of the URI's. Dispatches the SUCCESS event.
    - * @private
    - */
    -goog.net.BulkLoader.prototype.finishLoad_ = function() {
    -  goog.log.info(this.logger_, 'All uris loaded.');
    -
    -  // Dispatch the SUCCESS event.
    -  this.dispatchEvent(goog.net.EventType.SUCCESS);
    -};
    -
    -
    -/** @override */
    -goog.net.BulkLoader.prototype.disposeInternal = function() {
    -  goog.net.BulkLoader.superClass_.disposeInternal.call(this);
    -
    -  this.eventHandler_.dispose();
    -  this.eventHandler_ = null;
    -
    -  this.helper_.dispose();
    -  this.helper_ = null;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/net/bulkloader_test.html b/src/database/third_party/closure-library/closure/goog/net/bulkloader_test.html
    deleted file mode 100644
    index 0dc5de1e1be..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/bulkloader_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.net.BulkLoader
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -  goog.require('goog.net.BulkLoaderTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/bulkloader_test.js b/src/database/third_party/closure-library/closure/goog/net/bulkloader_test.js
    deleted file mode 100644
    index 5426857537d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/bulkloader_test.js
    +++ /dev/null
    @@ -1,235 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.net.BulkLoaderTest');
    -goog.setTestOnly('goog.net.BulkLoaderTest');
    -
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.net.BulkLoader');
    -goog.require('goog.net.EventType');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.jsunit');
    -
    -
    -/**
    - * Test interval between sending uri requests to the server.
    - */
    -var DELAY_INTERVAL_BETWEEN_URI_REQUESTS = 5;
    -
    -
    -/**
    - * Test interval before a response is received for a URI request.
    - */
    -var DELAY_INTERVAL_FOR_URI_LOAD = 15;
    -
    -var clock;
    -var loadSuccess, loadError;
    -var successResponseTexts;
    -
    -function setUpPage() {
    -  clock = new goog.testing.MockClock(true);
    -}
    -
    -function tearDownPage() {
    -  clock.dispose();
    -}
    -
    -function setUp() {
    -  loadSuccess = false;
    -  loadError = false;
    -  successResponseTexts = [];
    -}
    -
    -
    -/**
    - * Gets the successful bulkloader for the specified uris with some
    - * modifications for testability.
    - * <ul>
    - *   <li> Added onSuccess methods to simulate success while loading uris.
    - *   <li> The send function of the XhrManager used by the bulkloader
    - *        calls the onSuccess function after a specified time interval.
    - * </ul>
    - * @param {Array<string>} uris The URIs.
    - */
    -function getSuccessfulBulkLoader(uris) {
    -  var bulkLoader = new goog.net.BulkLoader(uris);
    -  bulkLoader.load = function() {
    -    var uris = this.helper_.getUris();
    -    for (var i = 0; i < uris.length; i++) {
    -      // This clock tick simulates a delay for processing every URI.
    -      clock.tick(DELAY_INTERVAL_BETWEEN_URI_REQUESTS);
    -      // This timeout determines how many ticks after the send request
    -      // all the URIs will complete loading. This delays the load of
    -      // the first uri and every subsequent uri by 15 ticks.
    -      setTimeout(goog.bind(this.onSuccess, this, i, uris[i]),
    -          DELAY_INTERVAL_FOR_URI_LOAD);
    -    }
    -  };
    -
    -  bulkLoader.onSuccess = function(id, uri) {
    -    var xhrIo = {
    -      getResponseText: function() {return uri;},
    -      isSuccess: function() {return true;},
    -      dispose: function() {}
    -    };
    -    this.handleEvent_(id, new goog.events.Event(
    -        goog.net.EventType.COMPLETE, xhrIo));
    -  };
    -
    -  var eventHandler = new goog.events.EventHandler();
    -  eventHandler.listen(bulkLoader,
    -      goog.net.EventType.SUCCESS,
    -      handleSuccess);
    -  eventHandler.listen(bulkLoader,
    -      goog.net.EventType.ERROR,
    -      handleError);
    -
    -  return bulkLoader;
    -}
    -
    -
    -/**
    - * Gets the non-successful bulkloader for the specified uris with some
    - * modifications for testability.
    - * <ul>
    - *   <li> Added onSuccess and onError methods to simulate success and error
    - *        while loading uris.
    - *   <li> The send function of the XhrManager used by the bulkloader
    - *        calls the onSuccess or onError function after a specified time
    - *        interval.
    - * </ul>
    - * @param {Array<string>} uris The URIs.
    - */
    -function getNonSuccessfulBulkLoader(uris) {
    -  var bulkLoader = new goog.net.BulkLoader(uris);
    -  bulkLoader.load = function() {
    -    var uris = this.helper_.getUris();
    -    for (var i = 0; i < uris.length; i++) {
    -      // This clock tick simulates a delay for processing every URI.
    -      clock.tick(DELAY_INTERVAL_BETWEEN_URI_REQUESTS);
    -
    -      // This timeout determines how many ticks after the send request
    -      // all the URIs will complete loading in error. This delays the load
    -      // of the first uri and every subsequent uri by 15 ticks. The URI
    -      // with id == 2 is in error.
    -      if (i != 2) {
    -        setTimeout(goog.bind(this.onSuccess, this, i, uris[i]),
    -            DELAY_INTERVAL_FOR_URI_LOAD);
    -      } else {
    -        setTimeout(goog.bind(this.onError, this, i, uris[i]),
    -            DELAY_INTERVAL_FOR_URI_LOAD);
    -      }
    -    }
    -  };
    -
    -  bulkLoader.onSuccess = function(id, uri) {
    -    var xhrIo = {
    -      getResponseText: function() {return uri;},
    -      isSuccess: function() {return true;},
    -      dispose: function() {}
    -    };
    -    this.handleEvent_(id, new goog.events.Event(
    -        goog.net.EventType.COMPLETE, xhrIo));
    -  };
    -
    -  bulkLoader.onError = function(id) {
    -    var xhrIo = {
    -      getResponseText: function() {return null;},
    -      isSuccess: function() {return false;},
    -      dispose: function() {}
    -    };
    -    this.handleEvent_(id, new goog.events.Event(
    -        goog.net.EventType.ERROR, xhrIo));
    -  };
    -
    -  var eventHandler = new goog.events.EventHandler();
    -  eventHandler.listen(bulkLoader,
    -      goog.net.EventType.SUCCESS,
    -      handleSuccess);
    -  eventHandler.listen(bulkLoader,
    -      goog.net.EventType.ERROR,
    -      handleError);
    -
    -  return bulkLoader;
    -}
    -
    -function handleSuccess(e) {
    -  loadSuccess = true;
    -  successResponseTexts = e.target.getResponseTexts();
    -}
    -
    -function handleError(e) {
    -  loadError = true;
    -}
    -
    -
    -/**
    - * Test successful loading of URIs using the bulkloader.
    - */
    -function testBulkLoaderLoadSuccess() {
    -  var uris = ['a', 'b', 'c'];
    -  var bulkLoader = getSuccessfulBulkLoader(uris);
    -  assertArrayEquals(uris, bulkLoader.getRequestUris());
    -
    -  bulkLoader.load();
    -
    -  clock.tick(2);
    -  assertFalse(
    -      'The bulk loader is not yet loaded (after 2 ticks)', loadSuccess);
    -
    -  clock.tick(3);
    -  assertFalse(
    -      'The bulk loader is not yet loaded (after 5 ticks)', loadSuccess);
    -
    -  clock.tick(5);
    -  assertFalse(
    -      'The bulk loader is not yet loaded (after 10 ticks)', loadSuccess);
    -
    -  clock.tick(5);
    -  assertTrue('The bulk loader is loaded (after 15 ticks)', loadSuccess);
    -
    -  assertArrayEquals('Ensure that the response texts are present',
    -      successResponseTexts, uris);
    -}
    -
    -
    -/**
    - * Test error loading URIs using the bulkloader.
    - */
    -function testBulkLoaderLoadError() {
    -  var uris = ['a', 'b', 'c'];
    -  var bulkLoader = getNonSuccessfulBulkLoader(uris);
    -
    -  bulkLoader.load();
    -
    -  clock.tick(2);
    -  assertFalse(
    -      'The bulk loader is not yet loaded (after 2 ticks)', loadError);
    -
    -  clock.tick(3);
    -  assertFalse(
    -      'The bulk loader is not yet loaded (after 5 ticks)', loadError);
    -
    -  clock.tick(5);
    -  assertFalse(
    -      'The bulk loader is not yet loaded (after 10 ticks)', loadError);
    -
    -  clock.tick(5);
    -  assertFalse(
    -      'The bulk loader is not loaded successfully (after 15 ticks)',
    -      loadSuccess);
    -  assertTrue(
    -      'The bulk loader is loaded in error (after 15 ticks)', loadError);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/net/bulkloaderhelper.js b/src/database/third_party/closure-library/closure/goog/net/bulkloaderhelper.js
    deleted file mode 100644
    index 4ddd13c55e6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/bulkloaderhelper.js
    +++ /dev/null
    @@ -1,120 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Helper class to load a list of URIs in bulk. All URIs
    - * must be a successfully loaded in order for the entire load to be considered
    - * a success.
    - *
    - */
    -
    -goog.provide('goog.net.BulkLoaderHelper');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.log');
    -
    -
    -
    -/**
    - * Helper class used to load multiple URIs.
    - * @param {Array<string|goog.Uri>} uris The URIs to load.
    - * @constructor
    - * @extends {goog.Disposable}
    - * @final
    - */
    -goog.net.BulkLoaderHelper = function(uris) {
    -  goog.Disposable.call(this);
    -
    -  /**
    -   * The URIs to load.
    -   * @type {Array<string|goog.Uri>}
    -   * @private
    -   */
    -  this.uris_ = uris;
    -
    -  /**
    -   * The response from the XHR's.
    -   * @type {Array<string>}
    -   * @private
    -   */
    -  this.responseTexts_ = [];
    -};
    -goog.inherits(goog.net.BulkLoaderHelper, goog.Disposable);
    -
    -
    -
    -/**
    - * Gets the URI by id.
    - * @param {number} id The id.
    - * @return {string|goog.Uri} The URI specified by the id.
    - */
    -goog.net.BulkLoaderHelper.prototype.getUri = function(id) {
    -  return this.uris_[id];
    -};
    -
    -
    -/**
    - * Gets the URIs.
    - * @return {Array<string|goog.Uri>} The URIs.
    - */
    -goog.net.BulkLoaderHelper.prototype.getUris = function() {
    -  return this.uris_;
    -};
    -
    -
    -/**
    - * Gets the response texts.
    - * @return {Array<string>} The response texts.
    - */
    -goog.net.BulkLoaderHelper.prototype.getResponseTexts = function() {
    -  return this.responseTexts_;
    -};
    -
    -
    -/**
    - * Sets the response text by id.
    - * @param {number} id The id.
    - * @param {string} responseText The response texts.
    - */
    -goog.net.BulkLoaderHelper.prototype.setResponseText = function(
    -    id, responseText) {
    -  this.responseTexts_[id] = responseText;
    -};
    -
    -
    -/**
    - * Determines if the load of the URIs is complete.
    - * @return {boolean} TRUE iff the load is complete.
    - */
    -goog.net.BulkLoaderHelper.prototype.isLoadComplete = function() {
    -  var responseTexts = this.responseTexts_;
    -  if (responseTexts.length == this.uris_.length) {
    -    for (var i = 0; i < responseTexts.length; i++) {
    -      if (!goog.isDefAndNotNull(responseTexts[i])) {
    -        return false;
    -      }
    -    }
    -    return true;
    -  }
    -  return false;
    -};
    -
    -
    -/** @override */
    -goog.net.BulkLoaderHelper.prototype.disposeInternal = function() {
    -  goog.net.BulkLoaderHelper.superClass_.disposeInternal.call(this);
    -
    -  this.uris_ = null;
    -  this.responseTexts_ = null;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/net/channeldebug.js b/src/database/third_party/closure-library/closure/goog/net/channeldebug.js
    deleted file mode 100644
    index 9ea22390c27..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/channeldebug.js
    +++ /dev/null
    @@ -1,300 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Definition of the ChannelDebug class. ChannelDebug provides
    - * a utility for tracing and debugging the BrowserChannel requests.
    - *
    - */
    -
    -
    -/**
    - * Namespace for BrowserChannel
    - */
    -goog.provide('goog.net.ChannelDebug');
    -
    -goog.require('goog.json');
    -goog.require('goog.log');
    -
    -
    -
    -/**
    - * Logs and keeps a buffer of debugging info for the Channel.
    - *
    - * @constructor
    - */
    -goog.net.ChannelDebug = function() {
    -  /**
    -   * The logger instance.
    -   * @const
    -   * @private
    -   */
    -  this.logger_ = goog.log.getLogger('goog.net.BrowserChannel');
    -};
    -
    -
    -/**
    - * Gets the logger used by this ChannelDebug.
    - * @return {goog.debug.Logger} The logger used by this ChannelDebug.
    - */
    -goog.net.ChannelDebug.prototype.getLogger = function() {
    -  return this.logger_;
    -};
    -
    -
    -/**
    - * Logs that the browser went offline during the lifetime of a request.
    - * @param {goog.Uri} url The URL being requested.
    - */
    -goog.net.ChannelDebug.prototype.browserOfflineResponse = function(url) {
    -  this.info('BROWSER_OFFLINE: ' + url);
    -};
    -
    -
    -/**
    - * Logs an XmlHttp request..
    - * @param {string} verb The request type (GET/POST).
    - * @param {goog.Uri} uri The request destination.
    - * @param {string|number|undefined} id The request id.
    - * @param {number} attempt Which attempt # the request was.
    - * @param {?string} postData The data posted in the request.
    - */
    -goog.net.ChannelDebug.prototype.xmlHttpChannelRequest =
    -    function(verb, uri, id, attempt, postData) {
    -  this.info(
    -      'XMLHTTP REQ (' + id + ') [attempt ' + attempt + ']: ' +
    -      verb + '\n' + uri + '\n' +
    -      this.maybeRedactPostData_(postData));
    -};
    -
    -
    -/**
    - * Logs the meta data received from an XmlHttp request.
    - * @param {string} verb The request type (GET/POST).
    - * @param {goog.Uri} uri The request destination.
    - * @param {string|number|undefined} id The request id.
    - * @param {number} attempt Which attempt # the request was.
    - * @param {goog.net.XmlHttp.ReadyState} readyState The ready state.
    - * @param {number} statusCode The HTTP status code.
    - */
    -goog.net.ChannelDebug.prototype.xmlHttpChannelResponseMetaData =
    -    function(verb, uri, id, attempt, readyState, statusCode)  {
    -  this.info(
    -      'XMLHTTP RESP (' + id + ') [ attempt ' + attempt + ']: ' +
    -      verb + '\n' + uri + '\n' + readyState + ' ' + statusCode);
    -};
    -
    -
    -/**
    - * Logs the response data received from an XmlHttp request.
    - * @param {string|number|undefined} id The request id.
    - * @param {?string} responseText The response text.
    - * @param {?string=} opt_desc Optional request description.
    - */
    -goog.net.ChannelDebug.prototype.xmlHttpChannelResponseText =
    -    function(id, responseText, opt_desc) {
    -  this.info(
    -      'XMLHTTP TEXT (' + id + '): ' +
    -      this.redactResponse_(responseText) +
    -      (opt_desc ? ' ' + opt_desc : ''));
    -};
    -
    -
    -/**
    - * Logs a Trident ActiveX request.
    - * @param {string} verb The request type (GET/POST).
    - * @param {goog.Uri} uri The request destination.
    - * @param {string|number|undefined} id The request id.
    - * @param {number} attempt Which attempt # the request was.
    - */
    -goog.net.ChannelDebug.prototype.tridentChannelRequest =
    -    function(verb, uri, id, attempt) {
    -  this.info(
    -      'TRIDENT REQ (' + id + ') [ attempt ' + attempt + ']: ' +
    -      verb + '\n' + uri);
    -};
    -
    -
    -/**
    - * Logs the response text received from a Trident ActiveX request.
    - * @param {string|number|undefined} id The request id.
    - * @param {string} responseText The response text.
    - */
    -goog.net.ChannelDebug.prototype.tridentChannelResponseText =
    -    function(id, responseText) {
    -  this.info(
    -      'TRIDENT TEXT (' + id + '): ' +
    -      this.redactResponse_(responseText));
    -};
    -
    -
    -/**
    - * Logs the done response received from a Trident ActiveX request.
    - * @param {string|number|undefined} id The request id.
    - * @param {boolean} successful Whether the request was successful.
    - */
    -goog.net.ChannelDebug.prototype.tridentChannelResponseDone =
    -    function(id, successful) {
    -  this.info(
    -      'TRIDENT TEXT (' + id + '): ' + successful ? 'success' : 'failure');
    -};
    -
    -
    -/**
    - * Logs a request timeout.
    - * @param {goog.Uri} uri The uri that timed out.
    - */
    -goog.net.ChannelDebug.prototype.timeoutResponse = function(uri) {
    -  this.info('TIMEOUT: ' + uri);
    -};
    -
    -
    -/**
    - * Logs a debug message.
    - * @param {string} text The message.
    - */
    -goog.net.ChannelDebug.prototype.debug = function(text) {
    -  this.info(text);
    -};
    -
    -
    -/**
    - * Logs an exception
    - * @param {Error} e The error or error event.
    - * @param {string=} opt_msg The optional message, defaults to 'Exception'.
    - */
    -goog.net.ChannelDebug.prototype.dumpException = function(e, opt_msg) {
    -  this.severe((opt_msg || 'Exception') + e);
    -};
    -
    -
    -/**
    - * Logs an info message.
    - * @param {string} text The message.
    - */
    -goog.net.ChannelDebug.prototype.info = function(text) {
    -  goog.log.info(this.logger_, text);
    -};
    -
    -
    -/**
    - * Logs a warning message.
    - * @param {string} text The message.
    - */
    -goog.net.ChannelDebug.prototype.warning = function(text) {
    -  goog.log.warning(this.logger_, text);
    -};
    -
    -
    -/**
    - * Logs a severe message.
    - * @param {string} text The message.
    - */
    -goog.net.ChannelDebug.prototype.severe = function(text) {
    -  goog.log.error(this.logger_, text);
    -};
    -
    -
    -/**
    - * Removes potentially private data from a response so that we don't
    - * accidentally save private and personal data to the server logs.
    - * @param {?string} responseText A JSON response to clean.
    - * @return {?string} The cleaned response.
    - * @private
    - */
    -goog.net.ChannelDebug.prototype.redactResponse_ = function(responseText) {
    -  // first check if it's not JS - the only non-JS should be the magic cookie
    -  if (!responseText ||
    -      /** @suppress {missingRequire}.  The require creates a circular
    -       *  dependency.
    -       */
    -      responseText == goog.net.BrowserChannel.MAGIC_RESPONSE_COOKIE) {
    -    return responseText;
    -  }
    -  /** @preserveTry */
    -  try {
    -    var responseArray = goog.json.unsafeParse(responseText);
    -    if (responseArray) {
    -      for (var i = 0; i < responseArray.length; i++) {
    -        if (goog.isArray(responseArray[i])) {
    -          this.maybeRedactArray_(responseArray[i]);
    -        }
    -      }
    -    }
    -
    -    return goog.json.serialize(responseArray);
    -  } catch (e) {
    -    this.debug('Exception parsing expected JS array - probably was not JS');
    -    return responseText;
    -  }
    -};
    -
    -
    -/**
    - * Removes data from a response array that may be sensitive.
    - * @param {Array<?>} array The array to clean.
    - * @private
    - */
    -goog.net.ChannelDebug.prototype.maybeRedactArray_ = function(array) {
    -  if (array.length < 2) {
    -    return;
    -  }
    -  var dataPart = array[1];
    -  if (!goog.isArray(dataPart)) {
    -    return;
    -  }
    -  if (dataPart.length < 1) {
    -    return;
    -  }
    -
    -  var type = dataPart[0];
    -  if (type != 'noop' && type != 'stop') {
    -    // redact all fields in the array
    -    for (var i = 1; i < dataPart.length; i++) {
    -      dataPart[i] = '';
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Removes potentially private data from a request POST body so that we don't
    - * accidentally save private and personal data to the server logs.
    - * @param {?string} data The data string to clean.
    - * @return {?string} The data string with sensitive data replaced by 'redacted'.
    - * @private
    - */
    -goog.net.ChannelDebug.prototype.maybeRedactPostData_ = function(data) {
    -  if (!data) {
    -    return null;
    -  }
    -  var out = '';
    -  var params = data.split('&');
    -  for (var i = 0; i < params.length; i++) {
    -    var param = params[i];
    -    var keyValue = param.split('=');
    -    if (keyValue.length > 1) {
    -      var key = keyValue[0];
    -      var value = keyValue[1];
    -
    -      var keyParts = key.split('_');
    -      if (keyParts.length >= 2 && keyParts[1] == 'type') {
    -        out += key + '=' + value + '&';
    -      } else {
    -        out += key + '=' + 'redacted' + '&';
    -      }
    -    }
    -  }
    -  return out;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/net/channelrequest.js b/src/database/third_party/closure-library/closure/goog/net/channelrequest.js
    deleted file mode 100644
    index 8a60a8e2288..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/channelrequest.js
    +++ /dev/null
    @@ -1,1286 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Definition of the ChannelRequest class. The ChannelRequest
    - * object encapsulates the logic for making a single request, either for the
    - * forward channel, back channel, or test channel, to the server. It contains
    - * the logic for the three types of transports we use in the BrowserChannel:
    - * XMLHTTP, Trident ActiveX (ie only), and Image request. It provides timeout
    - * detection. This class is part of the BrowserChannel implementation and is not
    - * for use by normal application code.
    - *
    - */
    -
    -
    -goog.provide('goog.net.ChannelRequest');
    -goog.provide('goog.net.ChannelRequest.Error');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.async.Throttle');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.net.ErrorCode');
    -goog.require('goog.net.EventType');
    -goog.require('goog.net.XmlHttp');
    -goog.require('goog.object');
    -goog.require('goog.userAgent');
    -
    -// TODO(nnaze): This file depends on goog.net.BrowserChannel and vice versa (a
    -// circular dependency).  Usages of BrowserChannel are marked as
    -// "missingRequire" below for now.  This should be fixed through refactoring.
    -
    -
    -
    -/**
    - * Creates a ChannelRequest object which encapsulates a request to the server.
    - * A new ChannelRequest is created for each request to the server.
    - *
    - * @param {goog.net.BrowserChannel|goog.net.BrowserTestChannel} channel
    - *     The BrowserChannel that owns this request.
    - * @param {goog.net.ChannelDebug} channelDebug A ChannelDebug to use for
    - *     logging.
    - * @param {string=} opt_sessionId  The session id for the channel.
    - * @param {string|number=} opt_requestId  The request id for this request.
    - * @param {number=} opt_retryId  The retry id for this request.
    - * @constructor
    - */
    -goog.net.ChannelRequest = function(channel, channelDebug, opt_sessionId,
    -    opt_requestId, opt_retryId) {
    -  /**
    -   * The BrowserChannel object that owns the request.
    -   * @type {goog.net.BrowserChannel|goog.net.BrowserTestChannel}
    -   * @private
    -   */
    -  this.channel_ = channel;
    -
    -  /**
    -   * The channel debug to use for logging
    -   * @type {goog.net.ChannelDebug}
    -   * @private
    -   */
    -  this.channelDebug_ = channelDebug;
    -
    -  /**
    -   * The Session ID for the channel.
    -   * @type {string|undefined}
    -   * @private
    -   */
    -  this.sid_ = opt_sessionId;
    -
    -  /**
    -   * The RID (request ID) for the request.
    -   * @type {string|number|undefined}
    -   * @private
    -   */
    -  this.rid_ = opt_requestId;
    -
    -
    -  /**
    -   * The attempt number of the current request.
    -   * @type {number}
    -   * @private
    -   */
    -  this.retryId_ = opt_retryId || 1;
    -
    -
    -  /**
    -   * The timeout in ms before failing the request.
    -   * @type {number}
    -   * @private
    -   */
    -  this.timeout_ = goog.net.ChannelRequest.TIMEOUT_MS;
    -
    -  /**
    -   * An object to keep track of the channel request event listeners.
    -   * @type {!goog.events.EventHandler<!goog.net.ChannelRequest>}
    -   * @private
    -   */
    -  this.eventHandler_ = new goog.events.EventHandler(this);
    -
    -  /**
    -   * A timer for polling responseText in browsers that don't fire
    -   * onreadystatechange during incremental loading of responseText.
    -   * @type {goog.Timer}
    -   * @private
    -   */
    -  this.pollingTimer_ = new goog.Timer();
    -
    -  this.pollingTimer_.setInterval(goog.net.ChannelRequest.POLLING_INTERVAL_MS);
    -};
    -
    -
    -/**
    - * Extra HTTP headers to add to all the requests sent to the server.
    - * @type {Object}
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.extraHeaders_ = null;
    -
    -
    -/**
    - * Whether the request was successful. This is only set to true after the
    - * request successfuly completes.
    - * @type {boolean}
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.successful_ = false;
    -
    -
    -/**
    - * The TimerID of the timer used to detect if the request has timed-out.
    - * @type {?number}
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.watchDogTimerId_ = null;
    -
    -
    -/**
    - * The time in the future when the request will timeout.
    - * @type {?number}
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.watchDogTimeoutTime_ = null;
    -
    -
    -/**
    - * The time the request started.
    - * @type {?number}
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.requestStartTime_ = null;
    -
    -
    -/**
    - * The type of request (XMLHTTP, IMG, Trident)
    - * @type {?number}
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.type_ = null;
    -
    -
    -/**
    - * The base Uri for the request. The includes all the parameters except the
    - * one that indicates the retry number.
    - * @type {goog.Uri?}
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.baseUri_ = null;
    -
    -
    -/**
    - * The request Uri that was actually used for the most recent request attempt.
    - * @type {goog.Uri?}
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.requestUri_ = null;
    -
    -
    -/**
    - * The post data, if the request is a post.
    - * @type {?string}
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.postData_ = null;
    -
    -
    -/**
    - * The XhrLte request if the request is using XMLHTTP
    - * @type {goog.net.XhrIo}
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.xmlHttp_ = null;
    -
    -
    -/**
    - * The position of where the next unprocessed chunk starts in the response
    - * text.
    - * @type {number}
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.xmlHttpChunkStart_ = 0;
    -
    -
    -/**
    - * The Trident instance if the request is using Trident.
    - * @type {ActiveXObject}
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.trident_ = null;
    -
    -
    -/**
    - * The verb (Get or Post) for the request.
    - * @type {?string}
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.verb_ = null;
    -
    -
    -/**
    - * The last error if the request failed.
    - * @type {?goog.net.ChannelRequest.Error}
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.lastError_ = null;
    -
    -
    -/**
    - * The last status code received.
    - * @type {number}
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.lastStatusCode_ = -1;
    -
    -
    -/**
    - * Whether to send the Connection:close header as part of the request.
    - * @type {boolean}
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.sendClose_ = true;
    -
    -
    -/**
    - * Whether the request has been cancelled due to a call to cancel.
    - * @type {boolean}
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.cancelled_ = false;
    -
    -
    -/**
    - * A throttle time in ms for readystatechange events for the backchannel.
    - * Useful for throttling when ready state is INTERACTIVE (partial data).
    - * If set to zero no throttle is used.
    - *
    - * @see goog.net.BrowserChannel.prototype.readyStateChangeThrottleMs_
    - *
    - * @type {number}
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.readyStateChangeThrottleMs_ = 0;
    -
    -
    -/**
    - * The throttle for readystatechange events for the current request, or null
    - * if there is none.
    - * @type {goog.async.Throttle}
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.readyStateChangeThrottle_ = null;
    -
    -
    -/**
    - * Default timeout in MS for a request. The server must return data within this
    - * time limit for the request to not timeout.
    - * @type {number}
    - */
    -goog.net.ChannelRequest.TIMEOUT_MS = 45 * 1000;
    -
    -
    -/**
    - * How often to poll (in MS) for changes to responseText in browsers that don't
    - * fire onreadystatechange during incremental loading of responseText.
    - * @type {number}
    - */
    -goog.net.ChannelRequest.POLLING_INTERVAL_MS = 250;
    -
    -
    -/**
    - * Minimum version of Safari that receives a non-null responseText in ready
    - * state interactive.
    - * @type {string}
    - * @private
    - */
    -goog.net.ChannelRequest.MIN_WEBKIT_FOR_INTERACTIVE_ = '420+';
    -
    -
    -/**
    - * Enum for channel requests type
    - * @enum {number}
    - * @private
    - */
    -goog.net.ChannelRequest.Type_ = {
    -  /**
    -   * XMLHTTP requests.
    -   */
    -  XML_HTTP: 1,
    -
    -  /**
    -   * IMG requests.
    -   */
    -  IMG: 2,
    -
    -  /**
    -   * Requests that use the MSHTML ActiveX control.
    -   */
    -  TRIDENT: 3
    -};
    -
    -
    -/**
    - * Enum type for identifying a ChannelRequest error.
    - * @enum {number}
    - */
    -goog.net.ChannelRequest.Error = {
    -  /**
    -   * Errors due to a non-200 status code.
    -   */
    -  STATUS: 0,
    -
    -  /**
    -   * Errors due to no data being returned.
    -   */
    -  NO_DATA: 1,
    -
    -  /**
    -   * Errors due to a timeout.
    -   */
    -  TIMEOUT: 2,
    -
    -  /**
    -   * Errors due to the server returning an unknown.
    -   */
    -  UNKNOWN_SESSION_ID: 3,
    -
    -  /**
    -   * Errors due to bad data being received.
    -   */
    -  BAD_DATA: 4,
    -
    -  /**
    -   * Errors due to the handler throwing an exception.
    -   */
    -  HANDLER_EXCEPTION: 5,
    -
    -  /**
    -   * The browser declared itself offline during the request.
    -   */
    -  BROWSER_OFFLINE: 6,
    -
    -  /**
    -   * IE is blocking ActiveX streaming.
    -   */
    -  ACTIVE_X_BLOCKED: 7
    -};
    -
    -
    -/**
    - * Returns a useful error string for debugging based on the specified error
    - * code.
    - * @param {goog.net.ChannelRequest.Error} errorCode The error code.
    - * @param {number} statusCode The HTTP status code.
    - * @return {string} The error string for the given code combination.
    - */
    -goog.net.ChannelRequest.errorStringFromCode = function(errorCode, statusCode) {
    -  switch (errorCode) {
    -    case goog.net.ChannelRequest.Error.STATUS:
    -      return 'Non-200 return code (' + statusCode + ')';
    -    case goog.net.ChannelRequest.Error.NO_DATA:
    -      return 'XMLHTTP failure (no data)';
    -    case goog.net.ChannelRequest.Error.TIMEOUT:
    -      return 'HttpConnection timeout';
    -    default:
    -      return 'Unknown error';
    -  }
    -};
    -
    -
    -/**
    - * Sentinel value used to indicate an invalid chunk in a multi-chunk response.
    - * @type {Object}
    - * @private
    - */
    -goog.net.ChannelRequest.INVALID_CHUNK_ = {};
    -
    -
    -/**
    - * Sentinel value used to indicate an incomplete chunk in a multi-chunk
    - * response.
    - * @type {Object}
    - * @private
    - */
    -goog.net.ChannelRequest.INCOMPLETE_CHUNK_ = {};
    -
    -
    -/**
    - * Returns whether XHR streaming is supported on this browser.
    - *
    - * If XHR streaming is not supported, we will try to use an ActiveXObject
    - * to create a Forever IFrame.
    - *
    - * @return {boolean} Whether XHR streaming is supported.
    - * @see http://code.google.com/p/closure-library/issues/detail?id=346
    - */
    -goog.net.ChannelRequest.supportsXhrStreaming = function() {
    -  return !goog.userAgent.IE || goog.userAgent.isDocumentModeOrHigher(10);
    -};
    -
    -
    -/**
    - * Sets extra HTTP headers to add to all the requests sent to the server.
    - *
    - * @param {Object} extraHeaders The HTTP headers.
    - */
    -goog.net.ChannelRequest.prototype.setExtraHeaders = function(extraHeaders) {
    -  this.extraHeaders_ = extraHeaders;
    -};
    -
    -
    -/**
    - * Sets the timeout for a request
    - *
    - * @param {number} timeout   The timeout in MS for when we fail the request.
    - */
    -goog.net.ChannelRequest.prototype.setTimeout = function(timeout) {
    -  this.timeout_ = timeout;
    -};
    -
    -
    -/**
    - * Sets the throttle for handling onreadystatechange events for the request.
    - *
    - * @param {number} throttle The throttle in ms.  A value of zero indicates
    - *     no throttle.
    - */
    -goog.net.ChannelRequest.prototype.setReadyStateChangeThrottle = function(
    -    throttle) {
    -  this.readyStateChangeThrottleMs_ = throttle;
    -};
    -
    -
    -/**
    - * Uses XMLHTTP to send an HTTP POST to the server.
    - *
    - * @param {goog.Uri} uri  The uri of the request.
    - * @param {string} postData  The data for the post body.
    - * @param {boolean} decodeChunks  Whether to the result is expected to be
    - *     encoded for chunking and thus requires decoding.
    - */
    -goog.net.ChannelRequest.prototype.xmlHttpPost = function(uri, postData,
    -                                                         decodeChunks) {
    -  this.type_ = goog.net.ChannelRequest.Type_.XML_HTTP;
    -  this.baseUri_ = uri.clone().makeUnique();
    -  this.postData_ = postData;
    -  this.decodeChunks_ = decodeChunks;
    -  this.sendXmlHttp_(null /* hostPrefix */);
    -};
    -
    -
    -/**
    - * Uses XMLHTTP to send an HTTP GET to the server.
    - *
    - * @param {goog.Uri} uri  The uri of the request.
    - * @param {boolean} decodeChunks  Whether to the result is expected to be
    - *     encoded for chunking and thus requires decoding.
    - * @param {?string} hostPrefix  The host prefix, if we might be using a
    - *     secondary domain.  Note that it should also be in the URL, adding this
    - *     won't cause it to be added to the URL.
    - * @param {boolean=} opt_noClose   Whether to request that the tcp/ip connection
    - *     should be closed.
    - */
    -goog.net.ChannelRequest.prototype.xmlHttpGet = function(uri, decodeChunks,
    -    hostPrefix, opt_noClose) {
    -  this.type_ = goog.net.ChannelRequest.Type_.XML_HTTP;
    -  this.baseUri_ = uri.clone().makeUnique();
    -  this.postData_ = null;
    -  this.decodeChunks_ = decodeChunks;
    -  if (opt_noClose) {
    -    this.sendClose_ = false;
    -  }
    -  this.sendXmlHttp_(hostPrefix);
    -};
    -
    -
    -/**
    - * Sends a request via XMLHTTP according to the current state of the
    - * ChannelRequest object.
    - *
    - * @param {?string} hostPrefix The host prefix, if we might be using a secondary
    - *     domain.
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.sendXmlHttp_ = function(hostPrefix) {
    -  this.requestStartTime_ = goog.now();
    -  this.ensureWatchDogTimer_();
    -
    -  // clone the base URI to create the request URI. The request uri has the
    -  // attempt number as a parameter which helps in debugging.
    -  this.requestUri_ = this.baseUri_.clone();
    -  this.requestUri_.setParameterValues('t', this.retryId_);
    -
    -  // send the request either as a POST or GET
    -  this.xmlHttpChunkStart_ = 0;
    -  var useSecondaryDomains = this.channel_.shouldUseSecondaryDomains();
    -  this.xmlHttp_ = this.channel_.createXhrIo(useSecondaryDomains ?
    -      hostPrefix : null);
    -
    -  if (this.readyStateChangeThrottleMs_ > 0) {
    -    this.readyStateChangeThrottle_ = new goog.async.Throttle(
    -        goog.bind(this.xmlHttpHandler_, this, this.xmlHttp_),
    -        this.readyStateChangeThrottleMs_);
    -  }
    -
    -  this.eventHandler_.listen(this.xmlHttp_,
    -      goog.net.EventType.READY_STATE_CHANGE,
    -      this.readyStateChangeHandler_);
    -
    -  var headers = this.extraHeaders_ ? goog.object.clone(this.extraHeaders_) : {};
    -  if (this.postData_) {
    -    // todo (jonp) - use POST constant when Dan defines it
    -    this.verb_ = 'POST';
    -    headers['Content-Type'] = 'application/x-www-form-urlencoded';
    -    this.xmlHttp_.send(this.requestUri_, this.verb_, this.postData_, headers);
    -  } else {
    -    // todo (jonp) - use GET constant when Dan defines it
    -    this.verb_ = 'GET';
    -
    -    // If the user agent is webkit, we cannot send the close header since it is
    -    // disallowed by the browser.  If we attempt to set the "Connection: close"
    -    // header in WEBKIT browser, it will actually causes an error message.
    -    if (this.sendClose_ && !goog.userAgent.WEBKIT) {
    -      headers['Connection'] = 'close';
    -    }
    -    this.xmlHttp_.send(this.requestUri_, this.verb_, null, headers);
    -  }
    -  this.channel_.notifyServerReachabilityEvent(
    -      /** @suppress {missingRequire} */ (
    -      goog.net.BrowserChannel.ServerReachability.REQUEST_MADE));
    -  this.channelDebug_.xmlHttpChannelRequest(this.verb_,
    -      this.requestUri_, this.rid_, this.retryId_,
    -      this.postData_);
    -};
    -
    -
    -/**
    - * Handles a readystatechange event.
    - * @param {goog.events.Event} evt The event.
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.readyStateChangeHandler_ = function(evt) {
    -  var xhr = /** @type {goog.net.XhrIo} */ (evt.target);
    -  var throttle = this.readyStateChangeThrottle_;
    -  if (throttle &&
    -      xhr.getReadyState() == goog.net.XmlHttp.ReadyState.INTERACTIVE) {
    -    // Only throttle in the partial data case.
    -    this.channelDebug_.debug('Throttling readystatechange.');
    -    throttle.fire();
    -  } else {
    -    // If we haven't throttled, just handle response directly.
    -    this.xmlHttpHandler_(xhr);
    -  }
    -};
    -
    -
    -/**
    - * XmlHttp handler
    - * @param {goog.net.XhrIo} xmlhttp The XhrIo object for the current request.
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.xmlHttpHandler_ = function(xmlhttp) {
    -  /** @suppress {missingRequire} */
    -  goog.net.BrowserChannel.onStartExecution();
    -
    -  /** @preserveTry */
    -  try {
    -    if (xmlhttp == this.xmlHttp_) {
    -      this.onXmlHttpReadyStateChanged_();
    -    } else {
    -      this.channelDebug_.warning('Called back with an ' +
    -                                     'unexpected xmlhttp');
    -    }
    -  } catch (ex) {
    -    this.channelDebug_.debug('Failed call to OnXmlHttpReadyStateChanged_');
    -    if (this.xmlHttp_ && this.xmlHttp_.getResponseText()) {
    -      this.channelDebug_.dumpException(ex,
    -          'ResponseText: ' + this.xmlHttp_.getResponseText());
    -    } else {
    -      this.channelDebug_.dumpException(ex, 'No response text');
    -    }
    -  } finally {
    -    /** @suppress {missingRequire} */
    -    goog.net.BrowserChannel.onEndExecution();
    -  }
    -};
    -
    -
    -/**
    - * Called by the readystate handler for XMLHTTP requests.
    - *
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.onXmlHttpReadyStateChanged_ = function() {
    -  var readyState = this.xmlHttp_.getReadyState();
    -  var errorCode = this.xmlHttp_.getLastErrorCode();
    -  var statusCode = this.xmlHttp_.getStatus();
    -  // If it is Safari less than 420+, there is a bug that causes null to be
    -  // in the responseText on ready state interactive so we must wait for
    -  // ready state complete.
    -  if (!goog.net.ChannelRequest.supportsXhrStreaming() ||
    -      (goog.userAgent.WEBKIT &&
    -       !goog.userAgent.isVersionOrHigher(
    -           goog.net.ChannelRequest.MIN_WEBKIT_FOR_INTERACTIVE_))) {
    -    if (readyState < goog.net.XmlHttp.ReadyState.COMPLETE) {
    -      // not yet ready
    -      return;
    -    }
    -  } else {
    -    // we get partial results in browsers that support ready state interactive.
    -    // We also make sure that getResponseText is not null in interactive mode
    -    // before we continue.  However, we don't do it in Opera because it only
    -    // fire readyState == INTERACTIVE once.  We need the following code to poll
    -    if (readyState < goog.net.XmlHttp.ReadyState.INTERACTIVE ||
    -        readyState == goog.net.XmlHttp.ReadyState.INTERACTIVE &&
    -        !goog.userAgent.OPERA && !this.xmlHttp_.getResponseText()) {
    -      // not yet ready
    -      return;
    -    }
    -  }
    -
    -  // Dispatch any appropriate network events.
    -  if (!this.cancelled_ && readyState == goog.net.XmlHttp.ReadyState.COMPLETE &&
    -      errorCode != goog.net.ErrorCode.ABORT) {
    -
    -    // Pretty conservative, these are the only known scenarios which we'd
    -    // consider indicative of a truly non-functional network connection.
    -    if (errorCode == goog.net.ErrorCode.TIMEOUT ||
    -        statusCode <= 0) {
    -      this.channel_.notifyServerReachabilityEvent(
    -          /** @suppress {missingRequire} */
    -          goog.net.BrowserChannel.ServerReachability.REQUEST_FAILED);
    -    } else {
    -      this.channel_.notifyServerReachabilityEvent(
    -          /** @suppress {missingRequire} */
    -          goog.net.BrowserChannel.ServerReachability.REQUEST_SUCCEEDED);
    -    }
    -  }
    -
    -  // got some data so cancel the watchdog timer
    -  this.cancelWatchDogTimer_();
    -
    -  var status = this.xmlHttp_.getStatus();
    -  this.lastStatusCode_ = status;
    -  var responseText = this.xmlHttp_.getResponseText();
    -  if (!responseText) {
    -    this.channelDebug_.debug('No response text for uri ' +
    -        this.requestUri_ + ' status ' + status);
    -  }
    -  this.successful_ = (status == 200);
    -
    -  this.channelDebug_.xmlHttpChannelResponseMetaData(
    -      /** @type {string} */ (this.verb_),
    -      this.requestUri_, this.rid_, this.retryId_, readyState,
    -      status);
    -
    -  if (!this.successful_) {
    -    if (status == 400 &&
    -        responseText.indexOf('Unknown SID') > 0) {
    -      // the server error string will include 'Unknown SID' which indicates the
    -      // server doesn't know about the session (maybe it got restarted, maybe
    -      // the user got moved to another server, etc.,). Handlers can special
    -      // case this error
    -      this.lastError_ = goog.net.ChannelRequest.Error.UNKNOWN_SESSION_ID;
    -      /** @suppress {missingRequire} */
    -      goog.net.BrowserChannel.notifyStatEvent(
    -          /** @suppress {missingRequire} */
    -          goog.net.BrowserChannel.Stat.REQUEST_UNKNOWN_SESSION_ID);
    -      this.channelDebug_.warning('XMLHTTP Unknown SID (' + this.rid_ + ')');
    -    } else {
    -      this.lastError_ = goog.net.ChannelRequest.Error.STATUS;
    -      /** @suppress {missingRequire} */
    -      goog.net.BrowserChannel.notifyStatEvent(
    -          /** @suppress {missingRequire} */
    -          goog.net.BrowserChannel.Stat.REQUEST_BAD_STATUS);
    -      this.channelDebug_.warning(
    -          'XMLHTTP Bad status ' + status + ' (' + this.rid_ + ')');
    -    }
    -    this.cleanup_();
    -    this.dispatchFailure_();
    -    return;
    -  }
    -
    -  if (readyState == goog.net.XmlHttp.ReadyState.COMPLETE) {
    -    this.cleanup_();
    -  }
    -
    -  if (this.decodeChunks_) {
    -    this.decodeNextChunks_(readyState, responseText);
    -    if (goog.userAgent.OPERA && this.successful_ &&
    -        readyState == goog.net.XmlHttp.ReadyState.INTERACTIVE) {
    -      this.startPolling_();
    -    }
    -  } else {
    -    this.channelDebug_.xmlHttpChannelResponseText(
    -        this.rid_, responseText, null);
    -    this.safeOnRequestData_(responseText);
    -  }
    -
    -  if (!this.successful_) {
    -    return;
    -  }
    -
    -  if (!this.cancelled_) {
    -    if (readyState == goog.net.XmlHttp.ReadyState.COMPLETE) {
    -      this.channel_.onRequestComplete(this);
    -    } else {
    -      // The default is false, the result from this callback shouldn't carry
    -      // over to the next callback, otherwise the request looks successful if
    -      // the watchdog timer gets called
    -      this.successful_ = false;
    -      this.ensureWatchDogTimer_();
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Decodes the next set of available chunks in the response.
    - * @param {number} readyState The value of readyState.
    - * @param {string} responseText The value of responseText.
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.decodeNextChunks_ = function(readyState,
    -        responseText) {
    -  var decodeNextChunksSuccessful = true;
    -  while (!this.cancelled_ &&
    -         this.xmlHttpChunkStart_ < responseText.length) {
    -    var chunkText = this.getNextChunk_(responseText);
    -    if (chunkText == goog.net.ChannelRequest.INCOMPLETE_CHUNK_) {
    -      if (readyState == goog.net.XmlHttp.ReadyState.COMPLETE) {
    -        // should have consumed entire response when the request is done
    -        this.lastError_ = goog.net.ChannelRequest.Error.BAD_DATA;
    -        /** @suppress {missingRequire} */
    -        goog.net.BrowserChannel.notifyStatEvent(
    -            /** @suppress {missingRequire} */
    -            goog.net.BrowserChannel.Stat.REQUEST_INCOMPLETE_DATA);
    -        decodeNextChunksSuccessful = false;
    -      }
    -      this.channelDebug_.xmlHttpChannelResponseText(
    -          this.rid_, null, '[Incomplete Response]');
    -      break;
    -    } else if (chunkText == goog.net.ChannelRequest.INVALID_CHUNK_) {
    -      this.lastError_ = goog.net.ChannelRequest.Error.BAD_DATA;
    -      /** @suppress {missingRequire} */
    -      goog.net.BrowserChannel.notifyStatEvent(
    -          /** @suppress {missingRequire} */
    -          goog.net.BrowserChannel.Stat.REQUEST_BAD_DATA);
    -      this.channelDebug_.xmlHttpChannelResponseText(
    -          this.rid_, responseText, '[Invalid Chunk]');
    -      decodeNextChunksSuccessful = false;
    -      break;
    -    } else {
    -      this.channelDebug_.xmlHttpChannelResponseText(
    -          this.rid_, /** @type {string} */ (chunkText), null);
    -      this.safeOnRequestData_(/** @type {string} */ (chunkText));
    -    }
    -  }
    -  if (readyState == goog.net.XmlHttp.ReadyState.COMPLETE &&
    -      responseText.length == 0) {
    -    // also an error if we didn't get any response
    -    this.lastError_ = goog.net.ChannelRequest.Error.NO_DATA;
    -    /** @suppress {missingRequire} */
    -    goog.net.BrowserChannel.notifyStatEvent(
    -        /** @suppress {missingRequire} */
    -        goog.net.BrowserChannel.Stat.REQUEST_NO_DATA);
    -    decodeNextChunksSuccessful = false;
    -  }
    -  this.successful_ = this.successful_ && decodeNextChunksSuccessful;
    -  if (!decodeNextChunksSuccessful) {
    -    // malformed response - we make this trigger retry logic
    -    this.channelDebug_.xmlHttpChannelResponseText(
    -        this.rid_, responseText, '[Invalid Chunked Response]');
    -    this.cleanup_();
    -    this.dispatchFailure_();
    -  }
    -};
    -
    -
    -/**
    - * Polls the response for new data.
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.pollResponse_ = function() {
    -  var readyState = this.xmlHttp_.getReadyState();
    -  var responseText = this.xmlHttp_.getResponseText();
    -  if (this.xmlHttpChunkStart_ < responseText.length) {
    -    this.cancelWatchDogTimer_();
    -    this.decodeNextChunks_(readyState, responseText);
    -    if (this.successful_ &&
    -        readyState != goog.net.XmlHttp.ReadyState.COMPLETE) {
    -      this.ensureWatchDogTimer_();
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Starts a polling interval for changes to responseText of the
    - * XMLHttpRequest, for browsers that don't fire onreadystatechange
    - * as data comes in incrementally.  This timer is disabled in
    - * cleanup_().
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.startPolling_ = function() {
    -  this.eventHandler_.listen(this.pollingTimer_, goog.Timer.TICK,
    -      this.pollResponse_);
    -  this.pollingTimer_.start();
    -};
    -
    -
    -
    -/**
    - * Returns the next chunk of a chunk-encoded response. This is not standard
    - * HTTP chunked encoding because browsers don't expose the chunk boundaries to
    - * the application through XMLHTTP. So we have an additional chunk encoding at
    - * the application level that lets us tell where the beginning and end of
    - * individual responses are so that we can only try to eval a complete JS array.
    - *
    - * The encoding is the size of the chunk encoded as a decimal string followed
    - * by a newline followed by the data.
    - *
    - * @param {string} responseText The response text from the XMLHTTP response.
    - * @return {string|Object} The next chunk string or a sentinel object
    - *                         indicating a special condition.
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.getNextChunk_ = function(responseText) {
    -  var sizeStartIndex = this.xmlHttpChunkStart_;
    -  var sizeEndIndex = responseText.indexOf('\n', sizeStartIndex);
    -  if (sizeEndIndex == -1) {
    -    return goog.net.ChannelRequest.INCOMPLETE_CHUNK_;
    -  }
    -
    -  var sizeAsString = responseText.substring(sizeStartIndex, sizeEndIndex);
    -  var size = Number(sizeAsString);
    -  if (isNaN(size)) {
    -    return goog.net.ChannelRequest.INVALID_CHUNK_;
    -  }
    -
    -  var chunkStartIndex = sizeEndIndex + 1;
    -  if (chunkStartIndex + size > responseText.length) {
    -    return goog.net.ChannelRequest.INCOMPLETE_CHUNK_;
    -  }
    -
    -  var chunkText = responseText.substr(chunkStartIndex, size);
    -  this.xmlHttpChunkStart_ = chunkStartIndex + size;
    -  return chunkText;
    -};
    -
    -
    -/**
    - * Uses the Trident htmlfile ActiveX control to send a GET request in IE. This
    - * is the innovation discovered that lets us get intermediate results in
    - * Internet Explorer.  Thanks to http://go/kev
    - * @param {goog.Uri} uri The uri to request from.
    - * @param {boolean} usingSecondaryDomain Whether to use a secondary domain.
    - */
    -goog.net.ChannelRequest.prototype.tridentGet = function(uri,
    -    usingSecondaryDomain) {
    -  this.type_ = goog.net.ChannelRequest.Type_.TRIDENT;
    -  this.baseUri_ = uri.clone().makeUnique();
    -  this.tridentGet_(usingSecondaryDomain);
    -};
    -
    -
    -/**
    - * Starts the Trident request.
    - * @param {boolean} usingSecondaryDomain Whether to use a secondary domain.
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.tridentGet_ = function(usingSecondaryDomain) {
    -  this.requestStartTime_ = goog.now();
    -  this.ensureWatchDogTimer_();
    -
    -  var hostname = usingSecondaryDomain ? window.location.hostname : '';
    -  this.requestUri_ = this.baseUri_.clone();
    -  this.requestUri_.setParameterValue('DOMAIN', hostname);
    -  this.requestUri_.setParameterValue('t', this.retryId_);
    -
    -  try {
    -    this.trident_ = new ActiveXObject('htmlfile');
    -  } catch (e) {
    -    this.channelDebug_.severe('ActiveX blocked');
    -    this.cleanup_();
    -
    -    this.lastError_ = goog.net.ChannelRequest.Error.ACTIVE_X_BLOCKED;
    -    /** @suppress {missingRequire} */
    -    goog.net.BrowserChannel.notifyStatEvent(
    -        /** @suppress {missingRequire} */
    -        goog.net.BrowserChannel.Stat.ACTIVE_X_BLOCKED);
    -    this.dispatchFailure_();
    -    return;
    -  }
    -
    -  var body = '<html><body>';
    -  if (usingSecondaryDomain) {
    -    body += '<script>document.domain="' + hostname + '"</scr' + 'ipt>';
    -  }
    -  body += '</body></html>';
    -
    -  this.trident_.open();
    -  this.trident_.write(body);
    -  this.trident_.close();
    -
    -  this.trident_.parentWindow['m'] = goog.bind(this.onTridentRpcMessage_, this);
    -  this.trident_.parentWindow['d'] = goog.bind(this.onTridentDone_, this, true);
    -  this.trident_.parentWindow['rpcClose'] =
    -      goog.bind(this.onTridentDone_, this, false);
    -
    -  var div = this.trident_.createElement('div');
    -  this.trident_.parentWindow.document.body.appendChild(div);
    -  div.innerHTML = '<iframe src="' + this.requestUri_ + '"></iframe>';
    -  this.channelDebug_.tridentChannelRequest('GET',
    -      this.requestUri_, this.rid_, this.retryId_);
    -  this.channel_.notifyServerReachabilityEvent(
    -      /** @suppress {missingRequire} */
    -      goog.net.BrowserChannel.ServerReachability.REQUEST_MADE);
    -};
    -
    -
    -/**
    - * Callback from the Trident htmlfile ActiveX control for when a new message
    - * is received.
    - *
    - * @param {string} msg The data payload.
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.onTridentRpcMessage_ = function(msg) {
    -  // need to do async b/c this gets called off of the context of the ActiveX
    -  /** @suppress {missingRequire} */
    -  goog.net.BrowserChannel.setTimeout(
    -      goog.bind(this.onTridentRpcMessageAsync_, this, msg), 0);
    -};
    -
    -
    -/**
    - * Callback from the Trident htmlfile ActiveX control for when a new message
    - * is received.
    - *
    - * @param {string} msg  The data payload.
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.onTridentRpcMessageAsync_ = function(msg) {
    -  if (this.cancelled_) {
    -    return;
    -  }
    -  this.channelDebug_.tridentChannelResponseText(this.rid_, msg);
    -  this.cancelWatchDogTimer_();
    -  this.safeOnRequestData_(msg);
    -  this.ensureWatchDogTimer_();
    -};
    -
    -
    -/**
    - * Callback from the Trident htmlfile ActiveX control for when the request
    - * is complete
    - *
    - * @param {boolean} successful Whether the request successfully completed.
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.onTridentDone_ = function(successful) {
    -  // need to do async b/c this gets called off of the context of the ActiveX
    -  /** @suppress {missingRequire} */
    -  goog.net.BrowserChannel.setTimeout(
    -      goog.bind(this.onTridentDoneAsync_, this, successful), 0);
    -};
    -
    -
    -/**
    - * Callback from the Trident htmlfile ActiveX control for when the request
    - * is complete
    - *
    - * @param {boolean} successful Whether the request successfully completed.
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.onTridentDoneAsync_ = function(successful) {
    -  if (this.cancelled_) {
    -    return;
    -  }
    -  this.channelDebug_.tridentChannelResponseDone(
    -      this.rid_, successful);
    -  this.cleanup_();
    -  this.successful_ = successful;
    -  this.channel_.onRequestComplete(this);
    -  this.channel_.notifyServerReachabilityEvent(
    -      /** @suppress {missingRequire} */
    -      goog.net.BrowserChannel.ServerReachability.BACK_CHANNEL_ACTIVITY);
    -};
    -
    -
    -/**
    - * Uses an IMG tag to send an HTTP get to the server. This is only currently
    - * used to terminate the connection, as an IMG tag is the most reliable way to
    - * send something to the server while the page is getting torn down.
    - * @param {goog.Uri} uri The uri to send a request to.
    - */
    -goog.net.ChannelRequest.prototype.sendUsingImgTag = function(uri) {
    -  this.type_ = goog.net.ChannelRequest.Type_.IMG;
    -  this.baseUri_ = uri.clone().makeUnique();
    -  this.imgTagGet_();
    -};
    -
    -
    -/**
    - * Starts the IMG request.
    - *
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.imgTagGet_ = function() {
    -  var eltImg = new Image();
    -  eltImg.src = this.baseUri_;
    -  this.requestStartTime_ = goog.now();
    -  this.ensureWatchDogTimer_();
    -};
    -
    -
    -/**
    - * Cancels the request no matter what the underlying transport is.
    - */
    -goog.net.ChannelRequest.prototype.cancel = function() {
    -  this.cancelled_ = true;
    -  this.cleanup_();
    -};
    -
    -
    -/**
    - * Ensures that there is watchdog timeout which is used to ensure that
    - * the connection completes in time.
    - *
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.ensureWatchDogTimer_ = function() {
    -  this.watchDogTimeoutTime_ = goog.now() + this.timeout_;
    -  this.startWatchDogTimer_(this.timeout_);
    -};
    -
    -
    -/**
    - * Starts the watchdog timer which is used to ensure that the connection
    - * completes in time.
    - * @param {number} time The number of milliseconds to wait.
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.startWatchDogTimer_ = function(time) {
    -  if (this.watchDogTimerId_ != null) {
    -    // assertion
    -    throw Error('WatchDog timer not null');
    -  }
    -  this.watchDogTimerId_ =   /** @suppress {missingRequire} */ (
    -      goog.net.BrowserChannel.setTimeout(
    -          goog.bind(this.onWatchDogTimeout_, this), time));
    -};
    -
    -
    -/**
    - * Cancels the watchdog timer if it has been started.
    - *
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.cancelWatchDogTimer_ = function() {
    -  if (this.watchDogTimerId_) {
    -    goog.global.clearTimeout(this.watchDogTimerId_);
    -    this.watchDogTimerId_ = null;
    -  }
    -};
    -
    -
    -/**
    - * Called when the watchdog timer is triggered. It also handles a case where it
    - * is called too early which we suspect may be happening sometimes
    - * (not sure why)
    - *
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.onWatchDogTimeout_ = function() {
    -  this.watchDogTimerId_ = null;
    -  var now = goog.now();
    -  if (now - this.watchDogTimeoutTime_ >= 0) {
    -    this.handleTimeout_();
    -  } else {
    -    // got called too early for some reason
    -    this.channelDebug_.warning('WatchDog timer called too early');
    -    this.startWatchDogTimer_(this.watchDogTimeoutTime_ - now);
    -  }
    -};
    -
    -
    -/**
    - * Called when the request has actually timed out. Will cleanup and notify the
    - * channel of the failure.
    - *
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.handleTimeout_ = function() {
    -  if (this.successful_) {
    -    // Should never happen.
    -    this.channelDebug_.severe(
    -        'Received watchdog timeout even though request loaded successfully');
    -  }
    -
    -  this.channelDebug_.timeoutResponse(this.requestUri_);
    -  // IMG requests never notice if they were successful, and always 'time out'.
    -  // This fact says nothing about reachability.
    -  if (this.type_ != goog.net.ChannelRequest.Type_.IMG) {
    -    this.channel_.notifyServerReachabilityEvent(
    -        /** @suppress {missingRequire} */
    -        goog.net.BrowserChannel.ServerReachability.REQUEST_FAILED);
    -  }
    -  this.cleanup_();
    -
    -  // set error and dispatch failure
    -  this.lastError_ = goog.net.ChannelRequest.Error.TIMEOUT;
    -  /** @suppress {missingRequire} */
    -  goog.net.BrowserChannel.notifyStatEvent(
    -      /** @suppress {missingRequire} */
    -      goog.net.BrowserChannel.Stat.REQUEST_TIMEOUT);
    -  this.dispatchFailure_();
    -};
    -
    -
    -/**
    - * Notifies the channel that this request failed.
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.dispatchFailure_ = function() {
    -  if (this.channel_.isClosed() || this.cancelled_) {
    -    return;
    -  }
    -
    -  this.channel_.onRequestComplete(this);
    -};
    -
    -
    -/**
    - * Cleans up the objects used to make the request. This function is
    - * idempotent.
    - *
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.cleanup_ = function() {
    -  this.cancelWatchDogTimer_();
    -
    -  goog.dispose(this.readyStateChangeThrottle_);
    -  this.readyStateChangeThrottle_ = null;
    -
    -  // Stop the polling timer, if necessary.
    -  this.pollingTimer_.stop();
    -
    -  // Unhook all event handlers.
    -  this.eventHandler_.removeAll();
    -
    -  if (this.xmlHttp_) {
    -    // clear out this.xmlHttp_ before aborting so we handle getting reentered
    -    // inside abort
    -    var xmlhttp = this.xmlHttp_;
    -    this.xmlHttp_ = null;
    -    xmlhttp.abort();
    -    xmlhttp.dispose();
    -  }
    -
    -  if (this.trident_) {
    -    this.trident_ = null;
    -  }
    -};
    -
    -
    -/**
    - * Indicates whether the request was successful. Only valid after the handler
    - * is called to indicate completion of the request.
    - *
    - * @return {boolean} True if the request succeeded.
    - */
    -goog.net.ChannelRequest.prototype.getSuccess = function() {
    -  return this.successful_;
    -};
    -
    -
    -/**
    - * If the request was not successful, returns the reason.
    - *
    - * @return {?goog.net.ChannelRequest.Error}  The last error.
    - */
    -goog.net.ChannelRequest.prototype.getLastError = function() {
    -  return this.lastError_;
    -};
    -
    -
    -/**
    - * Returns the status code of the last request.
    - * @return {number} The status code of the last request.
    - */
    -goog.net.ChannelRequest.prototype.getLastStatusCode = function() {
    -  return this.lastStatusCode_;
    -};
    -
    -
    -/**
    - * Returns the session id for this channel.
    - *
    - * @return {string|undefined} The session ID.
    - */
    -goog.net.ChannelRequest.prototype.getSessionId = function() {
    -  return this.sid_;
    -};
    -
    -
    -/**
    - * Returns the request id for this request. Each request has a unique request
    - * id and the request IDs are a sequential increasing count.
    - *
    - * @return {string|number|undefined} The request ID.
    - */
    -goog.net.ChannelRequest.prototype.getRequestId = function() {
    -  return this.rid_;
    -};
    -
    -
    -/**
    - * Returns the data for a post, if this request is a post.
    - *
    - * @return {?string} The POST data provided by the request initiator.
    - */
    -goog.net.ChannelRequest.prototype.getPostData = function() {
    -  return this.postData_;
    -};
    -
    -
    -/**
    - * Returns the time that the request started, if it has started.
    - *
    - * @return {?number} The time the request started, as returned by goog.now().
    - */
    -goog.net.ChannelRequest.prototype.getRequestStartTime = function() {
    -  return this.requestStartTime_;
    -};
    -
    -
    -/**
    - * Helper to call the callback's onRequestData, which catches any
    - * exception and cleans up the request.
    - * @param {string} data The request data.
    - * @private
    - */
    -goog.net.ChannelRequest.prototype.safeOnRequestData_ = function(data) {
    -  /** @preserveTry */
    -  try {
    -    this.channel_.onRequestData(this, data);
    -    this.channel_.notifyServerReachabilityEvent(
    -        /** @suppress {missingRequire} */
    -        goog.net.BrowserChannel.ServerReachability.BACK_CHANNEL_ACTIVITY);
    -  } catch (e) {
    -    // Dump debug info, but keep going without closing the channel.
    -    this.channelDebug_.dumpException(
    -        e, 'Error in httprequest callback');
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/net/channelrequest_test.html b/src/database/third_party/closure-library/closure/goog/net/channelrequest_test.html
    deleted file mode 100644
    index 10fba0732d4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/channelrequest_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.net.ChannelRequest
    -  </title>
    -  <script src="../base.js" type="text/javascript">
    -  </script>
    -  <script type="text/javascript">
    -    goog.require('goog.net.ChannelRequestTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/channelrequest_test.js b/src/database/third_party/closure-library/closure/goog/net/channelrequest_test.js
    deleted file mode 100644
    index 75011ef0c6e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/channelrequest_test.js
    +++ /dev/null
    @@ -1,282 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.net.ChannelRequestTest');
    -goog.setTestOnly('goog.net.ChannelRequestTest');
    -
    -goog.require('goog.Uri');
    -goog.require('goog.functions');
    -goog.require('goog.net.BrowserChannel');
    -goog.require('goog.net.ChannelDebug');
    -goog.require('goog.net.ChannelRequest');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.net.XhrIo');
    -goog.require('goog.testing.recordFunction');
    -
    -var channelRequest;
    -var mockBrowserChannel;
    -var mockClock;
    -var stubs;
    -var xhrIo;
    -
    -
    -/**
    - * Time to wait for a network request to time out, before aborting.
    - */
    -var WATCHDOG_TIME = 2000;
    -
    -
    -/**
    - * Time to throttle readystatechange events.
    - */
    -var THROTTLE_TIME = 500;
    -
    -
    -/**
    - * A really long time - used to make sure no more timeouts will fire.
    - */
    -var ALL_DAY_MS = 1000 * 60 * 60 * 24;
    -
    -
    -function setUp() {
    -  mockClock = new goog.testing.MockClock();
    -  mockClock.install();
    -  stubs = new goog.testing.PropertyReplacer();
    -}
    -
    -
    -function tearDown() {
    -  stubs.reset();
    -  mockClock.uninstall();
    -}
    -
    -
    -
    -/**
    - * Constructs a duck-type BrowserChannel that tracks the completed requests.
    -  * @constructor
    - */
    -function MockBrowserChannel() {
    -  this.reachabilityEvents = {};
    -  this.isClosed = function() {
    -    return false;
    -  };
    -  this.isActive = function() {
    -    return true;
    -  };
    -  this.shouldUseSecondaryDomains = function() {
    -    return false;
    -  };
    -  this.completedRequests = [];
    -  this.notifyServerReachabilityEvent = function(reachabilityType) {
    -    if (!this.reachabilityEvents[reachabilityType]) {
    -      this.reachabilityEvents[reachabilityType] = 0;
    -    }
    -    this.reachabilityEvents[reachabilityType]++;
    -  };
    -  this.onRequestComplete = function(request) {
    -    this.completedRequests.push(request);
    -  };
    -  this.onRequestData = function(request, data) {};
    -}
    -
    -
    -/**
    - * Creates a real ChannelRequest object, with some modifications for
    - * testability:
    - * <ul>
    - * <li>The BrowserChannel is a MockBrowserChannel.
    - * <li>The new watchdogTimeoutCallCount property tracks onWatchDogTimeout_()
    - *     calls.
    - * <li>The timeout is set to WATCHDOG_TIME.
    - * </ul>
    - */
    -function createChannelRequest() {
    -  xhrIo = new goog.testing.net.XhrIo();
    -  xhrIo.abort = xhrIo.abort || function() {
    -    this.active_ = false;
    -  };
    -
    -  // Install mock browser channel and no-op debug logger.
    -  mockBrowserChannel = new MockBrowserChannel();
    -  channelRequest = new goog.net.ChannelRequest(
    -      mockBrowserChannel,
    -      new goog.net.ChannelDebug());
    -
    -  // Install test XhrIo.
    -  mockBrowserChannel.createXhrIo = function() {
    -    return xhrIo;
    -  };
    -
    -  // Install watchdogTimeoutCallCount.
    -  channelRequest.watchdogTimeoutCallCount = 0;
    -  channelRequest.originalOnWatchDogTimeout = channelRequest.onWatchDogTimeout_;
    -  channelRequest.onWatchDogTimeout_ = function() {
    -    this.watchdogTimeoutCallCount++;
    -    return this.originalOnWatchDogTimeout();
    -  };
    -
    -  channelRequest.setTimeout(WATCHDOG_TIME);
    -}
    -
    -
    -/**
    - * Run through the lifecycle of a long lived request, checking that the right
    - * network events are reported.
    - */
    -function testNetworkEvents() {
    -  createChannelRequest();
    -
    -  channelRequest.xmlHttpPost(new goog.Uri('some_uri'), 'some_postdata', true);
    -  checkReachabilityEvents(1, 0, 0, 0);
    -  if (goog.net.ChannelRequest.supportsXhrStreaming()) {
    -    xhrIo.simulatePartialResponse('17\nI am a BC Message');
    -    checkReachabilityEvents(1, 0, 0, 1);
    -    xhrIo.simulatePartialResponse('23\nI am another BC Message');
    -    checkReachabilityEvents(1, 0, 0, 2);
    -    xhrIo.simulateResponse(200, '16\Final BC Message');
    -    checkReachabilityEvents(1, 1, 0, 2);
    -  } else {
    -    xhrIo.simulateResponse(200, '16\Final BC Message');
    -    checkReachabilityEvents(1, 1, 0, 0);
    -  }
    -}
    -
    -
    -/**
    - * Test throttling of readystatechange events.
    - */
    -function testNetworkEvents_throttleReadyStateChange() {
    -  createChannelRequest();
    -  channelRequest.setReadyStateChangeThrottle(THROTTLE_TIME);
    -
    -  var recordedHandler =
    -      goog.testing.recordFunction(channelRequest.xmlHttpHandler_);
    -  stubs.set(channelRequest, 'xmlHttpHandler_', recordedHandler);
    -
    -  channelRequest.xmlHttpPost(new goog.Uri('some_uri'), 'some_postdata', true);
    -  assertEquals(1, recordedHandler.getCallCount());
    -
    -  checkReachabilityEvents(1, 0, 0, 0);
    -  if (goog.net.ChannelRequest.supportsXhrStreaming()) {
    -    xhrIo.simulatePartialResponse('17\nI am a BC Message');
    -    checkReachabilityEvents(1, 0, 0, 1);
    -    assertEquals(3, recordedHandler.getCallCount());
    -
    -    // Second event should be throttled
    -    xhrIo.simulatePartialResponse('23\nI am another BC Message');
    -    assertEquals(3, recordedHandler.getCallCount());
    -
    -    xhrIo.simulatePartialResponse('27\nI am yet another BC Message');
    -    assertEquals(3, recordedHandler.getCallCount());
    -    mockClock.tick(THROTTLE_TIME);
    -
    -    checkReachabilityEvents(1, 0, 0, 3);
    -    // Only one more call because of throttling.
    -    assertEquals(4, recordedHandler.getCallCount());
    -
    -    xhrIo.simulateResponse(200, '16\Final BC Message');
    -    checkReachabilityEvents(1, 1, 0, 3);
    -    assertEquals(5, recordedHandler.getCallCount());
    -  } else {
    -    xhrIo.simulateResponse(200, '16\Final BC Message');
    -    checkReachabilityEvents(1, 1, 0, 0);
    -  }
    -}
    -
    -
    -/**
    - * Make sure that the request "completes" with an error when the timeout
    - * expires.
    - */
    -function testRequestTimeout() {
    -  createChannelRequest();
    -
    -  channelRequest.xmlHttpPost(new goog.Uri('some_uri'), 'some_postdata', true);
    -  assertEquals(0, channelRequest.watchdogTimeoutCallCount);
    -  assertEquals(0, channelRequest.channel_.completedRequests.length);
    -
    -  // Watchdog timeout.
    -  mockClock.tick(WATCHDOG_TIME);
    -  assertEquals(1, channelRequest.watchdogTimeoutCallCount);
    -  assertEquals(1, channelRequest.channel_.completedRequests.length);
    -  assertFalse(channelRequest.getSuccess());
    -
    -  // Make sure no more timers are firing.
    -  mockClock.tick(ALL_DAY_MS);
    -  assertEquals(1, channelRequest.watchdogTimeoutCallCount);
    -  assertEquals(1, channelRequest.channel_.completedRequests.length);
    -
    -  checkReachabilityEvents(1, 0, 1, 0);
    -}
    -
    -
    -function testRequestTimeoutWithUnexpectedException() {
    -  createChannelRequest();
    -  channelRequest.channel_.createXhrIo = goog.functions.error('Weird error');
    -
    -  try {
    -    channelRequest.xmlHttpGet(new goog.Uri('some_uri'), true, null);
    -    fail('Expected error');
    -  } catch (e) {
    -    assertEquals('Weird error', e.message);
    -  }
    -
    -
    -  assertEquals(0, channelRequest.watchdogTimeoutCallCount);
    -  assertEquals(0, channelRequest.channel_.completedRequests.length);
    -
    -  // Watchdog timeout.
    -  mockClock.tick(WATCHDOG_TIME);
    -  assertEquals(1, channelRequest.watchdogTimeoutCallCount);
    -  assertEquals(1, channelRequest.channel_.completedRequests.length);
    -  assertFalse(channelRequest.getSuccess());
    -
    -  // Make sure no more timers are firing.
    -  mockClock.tick(ALL_DAY_MS);
    -  assertEquals(1, channelRequest.watchdogTimeoutCallCount);
    -  assertEquals(1, channelRequest.channel_.completedRequests.length);
    -
    -  checkReachabilityEvents(0, 0, 1, 0);
    -}
    -
    -function testActiveXBlocked() {
    -  createChannelRequest();
    -  stubs.set(goog.global, 'ActiveXObject',
    -      goog.functions.error('Active X blocked'));
    -
    -  channelRequest.tridentGet(new goog.Uri('some_uri'), false);
    -  assertFalse(channelRequest.getSuccess());
    -  assertEquals(goog.net.ChannelRequest.Error.ACTIVE_X_BLOCKED,
    -      channelRequest.getLastError());
    -
    -  checkReachabilityEvents(0, 0, 0, 0);
    -}
    -
    -function checkReachabilityEvents(reqMade, reqSucceeded, reqFail, backChannel) {
    -  var Reachability = goog.net.BrowserChannel.ServerReachability;
    -  assertEquals(reqMade,
    -      mockBrowserChannel.reachabilityEvents[Reachability.REQUEST_MADE] || 0);
    -  assertEquals(reqSucceeded,
    -      mockBrowserChannel.reachabilityEvents[Reachability.REQUEST_SUCCEEDED] ||
    -      0);
    -  assertEquals(reqFail,
    -      mockBrowserChannel.reachabilityEvents[Reachability.REQUEST_FAILED] || 0);
    -  assertEquals(backChannel,
    -      mockBrowserChannel.reachabilityEvents[
    -          Reachability.BACK_CHANNEL_ACTIVITY] ||
    -      0);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/net/cookies.js b/src/database/third_party/closure-library/closure/goog/net/cookies.js
    deleted file mode 100644
    index 16bc41981a3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/cookies.js
    +++ /dev/null
    @@ -1,371 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Functions for setting, getting and deleting cookies.
    - *
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -
    -goog.provide('goog.net.Cookies');
    -goog.provide('goog.net.cookies');
    -
    -
    -
    -/**
    - * A class for handling browser cookies.
    - * @param {Document} context The context document to get/set cookies on.
    - * @constructor
    - * @final
    - */
    -goog.net.Cookies = function(context) {
    -  /**
    -   * The context document to get/set cookies on
    -   * @type {Document}
    -   * @private
    -   */
    -  this.document_ = context;
    -};
    -
    -
    -/**
    - * Static constant for the size of cookies. Per the spec, there's a 4K limit
    - * to the size of a cookie. To make sure users can't break this limit, we
    - * should truncate long cookies at 3950 bytes, to be extra careful with dumb
    - * browsers/proxies that interpret 4K as 4000 rather than 4096.
    - * @type {number}
    - */
    -goog.net.Cookies.MAX_COOKIE_LENGTH = 3950;
    -
    -
    -/**
    - * RegExp used to split the cookies string.
    - * @type {RegExp}
    - * @private
    - */
    -goog.net.Cookies.SPLIT_RE_ = /\s*;\s*/;
    -
    -
    -/**
    - * Returns true if cookies are enabled.
    - * @return {boolean} True if cookies are enabled.
    - */
    -goog.net.Cookies.prototype.isEnabled = function() {
    -  return navigator.cookieEnabled;
    -};
    -
    -
    -/**
    - * We do not allow '=', ';', or white space in the name.
    - *
    - * NOTE: The following are allowed by this method, but should be avoided for
    - * cookies handled by the server.
    - * - any name starting with '$'
    - * - 'Comment'
    - * - 'Domain'
    - * - 'Expires'
    - * - 'Max-Age'
    - * - 'Path'
    - * - 'Secure'
    - * - 'Version'
    - *
    - * @param {string} name Cookie name.
    - * @return {boolean} Whether name is valid.
    - *
    - * @see <a href="http://tools.ietf.org/html/rfc2109">RFC 2109</a>
    - * @see <a href="http://tools.ietf.org/html/rfc2965">RFC 2965</a>
    - */
    -goog.net.Cookies.prototype.isValidName = function(name) {
    -  return !(/[;=\s]/.test(name));
    -};
    -
    -
    -/**
    - * We do not allow ';' or line break in the value.
    - *
    - * Spec does not mention any illegal characters, but in practice semi-colons
    - * break parsing and line breaks truncate the name.
    - *
    - * @param {string} value Cookie value.
    - * @return {boolean} Whether value is valid.
    - *
    - * @see <a href="http://tools.ietf.org/html/rfc2109">RFC 2109</a>
    - * @see <a href="http://tools.ietf.org/html/rfc2965">RFC 2965</a>
    - */
    -goog.net.Cookies.prototype.isValidValue = function(value) {
    -  return !(/[;\r\n]/.test(value));
    -};
    -
    -
    -/**
    - * Sets a cookie.  The max_age can be -1 to set a session cookie. To remove and
    - * expire cookies, use remove() instead.
    - *
    - * Neither the {@code name} nor the {@code value} are encoded in any way. It is
    - * up to the callers of {@code get} and {@code set} (as well as all the other
    - * methods) to handle any possible encoding and decoding.
    - *
    - * @throws {!Error} If the {@code name} fails #goog.net.cookies.isValidName.
    - * @throws {!Error} If the {@code value} fails #goog.net.cookies.isValidValue.
    - *
    - * @param {string} name  The cookie name.
    - * @param {string} value  The cookie value.
    - * @param {number=} opt_maxAge  The max age in seconds (from now). Use -1 to
    - *     set a session cookie. If not provided, the default is -1
    - *     (i.e. set a session cookie).
    - * @param {?string=} opt_path  The path of the cookie. If not present then this
    - *     uses the full request path.
    - * @param {?string=} opt_domain  The domain of the cookie, or null to not
    - *     specify a domain attribute (browser will use the full request host name).
    - *     If not provided, the default is null (i.e. let browser use full request
    - *     host name).
    - * @param {boolean=} opt_secure Whether the cookie should only be sent over
    - *     a secure channel.
    - */
    -goog.net.Cookies.prototype.set = function(
    -    name, value, opt_maxAge, opt_path, opt_domain, opt_secure) {
    -  if (!this.isValidName(name)) {
    -    throw Error('Invalid cookie name "' + name + '"');
    -  }
    -  if (!this.isValidValue(value)) {
    -    throw Error('Invalid cookie value "' + value + '"');
    -  }
    -
    -  if (!goog.isDef(opt_maxAge)) {
    -    opt_maxAge = -1;
    -  }
    -
    -  var domainStr = opt_domain ? ';domain=' + opt_domain : '';
    -  var pathStr = opt_path ? ';path=' + opt_path : '';
    -  var secureStr = opt_secure ? ';secure' : '';
    -
    -  var expiresStr;
    -
    -  // Case 1: Set a session cookie.
    -  if (opt_maxAge < 0) {
    -    expiresStr = '';
    -
    -  // Case 2: Remove the cookie.
    -  // Note: We don't tell people about this option in the function doc because
    -  // we prefer people to use remove() to remove cookies.
    -  } else if (opt_maxAge == 0) {
    -    // Note: Don't use Jan 1, 1970 for date because NS 4.76 will try to convert
    -    // it to local time, and if the local time is before Jan 1, 1970, then the
    -    // browser will ignore the Expires attribute altogether.
    -    var pastDate = new Date(1970, 1 /*Feb*/, 1);  // Feb 1, 1970
    -    expiresStr = ';expires=' + pastDate.toUTCString();
    -
    -  // Case 3: Set a persistent cookie.
    -  } else {
    -    var futureDate = new Date(goog.now() + opt_maxAge * 1000);
    -    expiresStr = ';expires=' + futureDate.toUTCString();
    -  }
    -
    -  this.setCookie_(name + '=' + value + domainStr + pathStr +
    -                  expiresStr + secureStr);
    -};
    -
    -
    -/**
    - * Returns the value for the first cookie with the given name.
    - * @param {string} name  The name of the cookie to get.
    - * @param {string=} opt_default  If not found this is returned instead.
    - * @return {string|undefined}  The value of the cookie. If no cookie is set this
    - *     returns opt_default or undefined if opt_default is not provided.
    - */
    -goog.net.Cookies.prototype.get = function(name, opt_default) {
    -  var nameEq = name + '=';
    -  var parts = this.getParts_();
    -  for (var i = 0, part; part = parts[i]; i++) {
    -    // startsWith
    -    if (part.lastIndexOf(nameEq, 0) == 0) {
    -      return part.substr(nameEq.length);
    -    }
    -    if (part == name) {
    -      return '';
    -    }
    -  }
    -  return opt_default;
    -};
    -
    -
    -/**
    - * Removes and expires a cookie.
    - * @param {string} name  The cookie name.
    - * @param {string=} opt_path  The path of the cookie, or null to expire a cookie
    - *     set at the full request path. If not provided, the default is '/'
    - *     (i.e. path=/).
    - * @param {string=} opt_domain  The domain of the cookie, or null to expire a
    - *     cookie set at the full request host name. If not provided, the default is
    - *     null (i.e. cookie at full request host name).
    - * @return {boolean} Whether the cookie existed before it was removed.
    - */
    -goog.net.Cookies.prototype.remove = function(name, opt_path, opt_domain) {
    -  var rv = this.containsKey(name);
    -  this.set(name, '', 0, opt_path, opt_domain);
    -  return rv;
    -};
    -
    -
    -/**
    - * Gets the names for all the cookies.
    - * @return {Array<string>} An array with the names of the cookies.
    - */
    -goog.net.Cookies.prototype.getKeys = function() {
    -  return this.getKeyValues_().keys;
    -};
    -
    -
    -/**
    - * Gets the values for all the cookies.
    - * @return {Array<string>} An array with the values of the cookies.
    - */
    -goog.net.Cookies.prototype.getValues = function() {
    -  return this.getKeyValues_().values;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether there are any cookies for this document.
    - */
    -goog.net.Cookies.prototype.isEmpty = function() {
    -  return !this.getCookie_();
    -};
    -
    -
    -/**
    - * @return {number} The number of cookies for this document.
    - */
    -goog.net.Cookies.prototype.getCount = function() {
    -  var cookie = this.getCookie_();
    -  if (!cookie) {
    -    return 0;
    -  }
    -  return this.getParts_().length;
    -};
    -
    -
    -/**
    - * Returns whether there is a cookie with the given name.
    - * @param {string} key The name of the cookie to test for.
    - * @return {boolean} Whether there is a cookie by that name.
    - */
    -goog.net.Cookies.prototype.containsKey = function(key) {
    -  // substring will return empty string if the key is not found, so the get
    -  // function will only return undefined
    -  return goog.isDef(this.get(key));
    -};
    -
    -
    -/**
    - * Returns whether there is a cookie with the given value. (This is an O(n)
    - * operation.)
    - * @param {string} value  The value to check for.
    - * @return {boolean} Whether there is a cookie with that value.
    - */
    -goog.net.Cookies.prototype.containsValue = function(value) {
    -  // this O(n) in any case so lets do the trivial thing.
    -  var values = this.getKeyValues_().values;
    -  for (var i = 0; i < values.length; i++) {
    -    if (values[i] == value) {
    -      return true;
    -    }
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Removes all cookies for this document.  Note that this will only remove
    - * cookies from the current path and domain.  If there are cookies set using a
    - * subpath and/or another domain these will still be there.
    - */
    -goog.net.Cookies.prototype.clear = function() {
    -  var keys = this.getKeyValues_().keys;
    -  for (var i = keys.length - 1; i >= 0; i--) {
    -    this.remove(keys[i]);
    -  }
    -};
    -
    -
    -/**
    - * Private helper function to allow testing cookies without depending on the
    - * browser.
    - * @param {string} s The cookie string to set.
    - * @private
    - */
    -goog.net.Cookies.prototype.setCookie_ = function(s) {
    -  this.document_.cookie = s;
    -};
    -
    -
    -/**
    - * Private helper function to allow testing cookies without depending on the
    - * browser. IE6 can return null here.
    - * @return {string} Returns the {@code document.cookie}.
    - * @private
    - */
    -goog.net.Cookies.prototype.getCookie_ = function() {
    -  return this.document_.cookie;
    -};
    -
    -
    -/**
    - * @return {!Array<string>} The cookie split on semi colons.
    - * @private
    - */
    -goog.net.Cookies.prototype.getParts_ = function() {
    -  return (this.getCookie_() || '').
    -      split(goog.net.Cookies.SPLIT_RE_);
    -};
    -
    -
    -/**
    - * Gets the names and values for all the cookies.
    - * @return {!Object} An object with keys and values.
    - * @private
    - */
    -goog.net.Cookies.prototype.getKeyValues_ = function() {
    -  var parts = this.getParts_();
    -  var keys = [], values = [], index, part;
    -  for (var i = 0; part = parts[i]; i++) {
    -    index = part.indexOf('=');
    -
    -    if (index == -1) { // empty name
    -      keys.push('');
    -      values.push(part);
    -    } else {
    -      keys.push(part.substring(0, index));
    -      values.push(part.substring(index + 1));
    -    }
    -  }
    -  return {keys: keys, values: values};
    -};
    -
    -
    -/**
    - * A static default instance.
    - * @type {goog.net.Cookies}
    - */
    -goog.net.cookies = new goog.net.Cookies(document);
    -
    -
    -/**
    - * Define the constant on the instance in order not to break many references to
    - * it.
    - * @type {number}
    - * @deprecated Use goog.net.Cookies.MAX_COOKIE_LENGTH instead.
    - */
    -goog.net.cookies.MAX_COOKIE_LENGTH = goog.net.Cookies.MAX_COOKIE_LENGTH;
    diff --git a/src/database/third_party/closure-library/closure/goog/net/cookies_test.html b/src/database/third_party/closure-library/closure/goog/net/cookies_test.html
    deleted file mode 100644
    index f8da4a2a619..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/cookies_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.net.cookies
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.net.cookiesTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/cookies_test.js b/src/database/third_party/closure-library/closure/goog/net/cookies_test.js
    deleted file mode 100644
    index 925bf2c845b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/cookies_test.js
    +++ /dev/null
    @@ -1,265 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.net.cookiesTest');
    -goog.setTestOnly('goog.net.cookiesTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.net.cookies');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -
    -var cookies = goog.net.cookies;
    -var baseCount = 0;
    -var stubs = new goog.testing.PropertyReplacer();
    -
    -function checkForCookies() {
    -  if (!cookies.isEnabled()) {
    -    var message = 'Cookies must be enabled to run this test.';
    -    if (location.protocol == 'file:') {
    -      message += '\nNote that cookies for local files are disabled in some ' +
    -          'browsers.\nThey can be enabled in Chrome with the ' +
    -          '--enable-file-cookies flag.';
    -    }
    -
    -    fail(message);
    -  }
    -}
    -
    -function setUp() {
    -  checkForCookies();
    -
    -  // Make sure there are no cookies set by previous, bad tests.
    -  cookies.clear();
    -  baseCount = cookies.getCount();
    -}
    -
    -function tearDown() {
    -  // Clear up after ourselves.
    -  cookies.clear();
    -  stubs.reset();
    -}
    -
    -function testIsEnabled() {
    -  assertEquals(navigator.cookieEnabled, cookies.isEnabled());
    -}
    -
    -function testCount() {
    -  // setUp empties the cookies
    -
    -  cookies.set('testa', 'A');
    -  assertEquals(baseCount + 1, cookies.getCount());
    -  cookies.set('testb', 'B');
    -  cookies.set('testc', 'C');
    -  assertEquals(baseCount + 3, cookies.getCount());
    -  cookies.remove('testa');
    -  cookies.remove('testb');
    -  assertEquals(baseCount + 1, cookies.getCount());
    -  cookies.remove('testc');
    -  assertEquals(baseCount + 0, cookies.getCount());
    -}
    -
    -function testSet() {
    -  cookies.set('testa', 'testb');
    -  assertEquals('testb', cookies.get('testa'));
    -  cookies.remove('testa');
    -  assertEquals(undefined, cookies.get('testa'));
    -  // check for invalid characters in name and value
    -}
    -
    -function testGetKeys() {
    -  cookies.set('testa', 'A');
    -  cookies.set('testb', 'B');
    -  cookies.set('testc', 'C');
    -  var keys = cookies.getKeys();
    -  assertTrue(goog.array.contains(keys, 'testa'));
    -  assertTrue(goog.array.contains(keys, 'testb'));
    -  assertTrue(goog.array.contains(keys, 'testc'));
    -}
    -
    -
    -function testGetValues() {
    -  cookies.set('testa', 'A');
    -  cookies.set('testb', 'B');
    -  cookies.set('testc', 'C');
    -  var values = cookies.getValues();
    -  assertTrue(goog.array.contains(values, 'A'));
    -  assertTrue(goog.array.contains(values, 'B'));
    -  assertTrue(goog.array.contains(values, 'C'));
    -}
    -
    -
    -function testContainsKey() {
    -  assertFalse(cookies.containsKey('testa'));
    -  cookies.set('testa', 'A');
    -  assertTrue(cookies.containsKey('testa'));
    -  cookies.set('testb', 'B');
    -  assertTrue(cookies.containsKey('testb'));
    -  cookies.remove('testb');
    -  assertFalse(cookies.containsKey('testb'));
    -  cookies.remove('testa');
    -  assertFalse(cookies.containsKey('testa'));
    -}
    -
    -
    -function testContainsValue() {
    -  assertFalse(cookies.containsValue('A'));
    -  cookies.set('testa', 'A');
    -  assertTrue(cookies.containsValue('A'));
    -  cookies.set('testb', 'B');
    -  assertTrue(cookies.containsValue('B'));
    -  cookies.remove('testb');
    -  assertFalse(cookies.containsValue('B'));
    -  cookies.remove('testa');
    -  assertFalse(cookies.containsValue('A'));
    -}
    -
    -
    -function testIsEmpty() {
    -  // we cannot guarantee that we have no cookies so testing for the true
    -  // case cannot be done without a mock document.cookie
    -  cookies.set('testa', 'A');
    -  assertFalse(cookies.isEmpty());
    -  cookies.set('testb', 'B');
    -  assertFalse(cookies.isEmpty());
    -  cookies.remove('testb');
    -  assertFalse(cookies.isEmpty());
    -  cookies.remove('testa');
    -}
    -
    -
    -function testRemove() {
    -  assertFalse(
    -      '1. Cookie should not contain "testa"', cookies.containsKey('testa'));
    -  cookies.set('testa', 'A', undefined, '/');
    -  assertTrue('2. Cookie should contain "testa"', cookies.containsKey('testa'));
    -  cookies.remove('testa', '/');
    -  assertFalse(
    -      '3. Cookie should not contain "testa"', cookies.containsKey('testa'));
    -
    -  cookies.set('testa', 'A');
    -  assertTrue('4. Cookie should contain "testa"', cookies.containsKey('testa'));
    -  cookies.remove('testa');
    -  assertFalse(
    -      '5. Cookie should not contain "testa"', cookies.containsKey('testa'));
    -}
    -
    -function testStrangeValue() {
    -  // This ensures that the pattern key2=value in the value does not match
    -  // the key2 cookie.
    -  var value = 'testb=bbb';
    -  var value2 = 'ccc';
    -
    -  cookies.set('testa', value);
    -  cookies.set('testb', value2);
    -
    -  assertEquals(value, cookies.get('testa'));
    -  assertEquals(value2, cookies.get('testb'));
    -}
    -
    -function testSetCookiePath() {
    -  assertEquals('foo=bar;path=/xyz',
    -      mockSetCookie('foo', 'bar', -1, '/xyz'));
    -}
    -
    -function testSetCookieDomain() {
    -  assertEquals('foo=bar;domain=google.com',
    -      mockSetCookie('foo', 'bar', -1, null, 'google.com'));
    -}
    -
    -function testSetCookieSecure() {
    -  assertEquals('foo=bar;secure',
    -      mockSetCookie('foo', 'bar', -1, null, null, true));
    -}
    -
    -function testSetCookieMaxAgeZero() {
    -  var result = mockSetCookie('foo', 'bar', 0);
    -  var pattern = new RegExp(
    -      'foo=bar;expires=' + new Date(1970, 1, 1).toUTCString());
    -  if (!result.match(pattern)) {
    -    fail('expected match against ' + pattern + ' got ' + result);
    -  }
    -}
    -
    -function testGetEmptyCookie() {
    -  var value = '';
    -
    -  cookies.set('test', value);
    -
    -  assertEquals(value, cookies.get('test'));
    -}
    -
    -function testGetEmptyCookieIE() {
    -  stubs.set(cookies, 'getCookie_', function() {
    -    return 'test1; test2; test3';
    -  });
    -
    -  assertEquals('', cookies.get('test1'));
    -  assertEquals('', cookies.get('test2'));
    -  assertEquals('', cookies.get('test3'));
    -}
    -
    -// TODO(chrisn): Testing max age > 0 requires a mock clock.
    -
    -function mockSetCookie(var_args) {
    -  var setCookie = cookies.setCookie_;
    -  try {
    -    var result;
    -    cookies.setCookie_ = function(arg) {
    -      result = arg;
    -    };
    -    cookies.set.apply(cookies, arguments);
    -    return result;
    -  } finally {
    -    cookies.setCookie_ = setCookie;
    -  }
    -}
    -
    -function assertValidName(name) {
    -  assertTrue(name + ' should be valid', cookies.isValidName(name));
    -}
    -
    -function assertInvalidName(name) {
    -  assertFalse(name + ' should be invalid', cookies.isValidName(name));
    -  assertThrows(function() {
    -    cookies.set(name, 'value');
    -  });
    -}
    -
    -function assertValidValue(val) {
    -  assertTrue(val + ' should be valid', cookies.isValidValue(val));
    -}
    -
    -function assertInvalidValue(val) {
    -  assertFalse(val + ' should be invalid', cookies.isValidValue(val));
    -  assertThrows(function() {
    -    cookies.set('name', val);
    -  });
    -}
    -
    -function testValidName() {
    -  assertValidName('foo');
    -  assertInvalidName('foo bar');
    -  assertInvalidName('foo=bar');
    -  assertInvalidName('foo;bar');
    -  assertInvalidName('foo\nbar');
    -}
    -
    -function testValidValue() {
    -  assertValidValue('foo');
    -  assertValidValue('foo bar');
    -  assertValidValue('foo=bar');
    -  assertInvalidValue('foo;bar');
    -  assertInvalidValue('foo\nbar');
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/net/corsxmlhttpfactory.js b/src/database/third_party/closure-library/closure/goog/net/corsxmlhttpfactory.js
    deleted file mode 100644
    index 4f8f1455dea..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/corsxmlhttpfactory.js
    +++ /dev/null
    @@ -1,272 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview This file contain classes that add support for cross-domain XHR
    - * requests (see http://www.w3.org/TR/cors/). Most modern browsers are able to
    - * use a regular XMLHttpRequest for that, but IE 8 use XDomainRequest object
    - * instead. This file provides an adapter from this object to a goog.net.XhrLike
    - * and a factory to allow using this with a goog.net.XhrIo instance.
    - *
    - * IE 7 and older versions are not supported (given that they do not support
    - * CORS requests).
    - */
    -goog.provide('goog.net.CorsXmlHttpFactory');
    -goog.provide('goog.net.IeCorsXhrAdapter');
    -
    -goog.require('goog.net.HttpStatus');
    -goog.require('goog.net.XhrLike');
    -goog.require('goog.net.XmlHttp');
    -goog.require('goog.net.XmlHttpFactory');
    -
    -
    -
    -/**
    - * A factory of XML http request objects that supports cross domain requests.
    - * This class should be instantiated and passed as the parameter of a
    - * goog.net.XhrIo constructor to allow cross-domain requests in every browser.
    - *
    - * @extends {goog.net.XmlHttpFactory}
    - * @constructor
    - * @final
    - */
    -goog.net.CorsXmlHttpFactory = function() {
    -  goog.net.XmlHttpFactory.call(this);
    -};
    -goog.inherits(goog.net.CorsXmlHttpFactory, goog.net.XmlHttpFactory);
    -
    -
    -/** @override */
    -goog.net.CorsXmlHttpFactory.prototype.createInstance = function() {
    -  var xhr = new XMLHttpRequest();
    -  if (('withCredentials' in xhr)) {
    -    return xhr;
    -  } else if (typeof XDomainRequest != 'undefined') {
    -    return new goog.net.IeCorsXhrAdapter();
    -  } else {
    -    throw Error('Unsupported browser');
    -  }
    -};
    -
    -
    -/** @override */
    -goog.net.CorsXmlHttpFactory.prototype.internalGetOptions = function() {
    -  return {};
    -};
    -
    -
    -
    -/**
    - * An adapter around Internet Explorer's XDomainRequest object that makes it
    - * look like a standard XMLHttpRequest. This can be used instead of
    - * XMLHttpRequest to support CORS.
    - *
    - * @implements {goog.net.XhrLike}
    - * @constructor
    - * @struct
    - * @final
    - */
    -goog.net.IeCorsXhrAdapter = function() {
    -  /**
    -   * The underlying XDomainRequest used to make the HTTP request.
    -   * @type {!XDomainRequest}
    -   * @private
    -   */
    -  this.xdr_ = new XDomainRequest();
    -
    -  /**
    -   * The simulated ready state.
    -   * @type {number}
    -   */
    -  this.readyState = goog.net.XmlHttp.ReadyState.UNINITIALIZED;
    -
    -  /**
    -   * The simulated ready state change callback function.
    -   * @type {Function}
    -   */
    -  this.onreadystatechange = null;
    -
    -  /**
    -   * The simulated response text parameter.
    -   * @type {?string}
    -   */
    -  this.responseText = null;
    -
    -  /**
    -   * The simulated status code
    -   * @type {number}
    -   */
    -  this.status = -1;
    -
    -  /** @override */
    -  this.responseXML = null;
    -
    -  /** @override */
    -  this.statusText = null;
    -
    -  this.xdr_.onload = goog.bind(this.handleLoad_, this);
    -  this.xdr_.onerror = goog.bind(this.handleError_, this);
    -  this.xdr_.onprogress = goog.bind(this.handleProgress_, this);
    -  this.xdr_.ontimeout = goog.bind(this.handleTimeout_, this);
    -};
    -
    -
    -/**
    - * Opens a connection to the provided URL.
    - * @param {string} method The HTTP method to use. Valid methods include GET and
    - *     POST.
    - * @param {string} url The URL to contact. The authority of this URL must match
    - *     the authority of the current page's URL (e.g. http or https).
    - * @param {?boolean=} opt_async Whether the request is asynchronous, defaulting
    - *     to true. XDomainRequest does not support syncronous requests, so setting
    - *     it to false will actually raise an exception.
    - * @override
    - */
    -goog.net.IeCorsXhrAdapter.prototype.open = function(method, url, opt_async) {
    -  if (goog.isDefAndNotNull(opt_async) && (!opt_async)) {
    -    throw new Error('Only async requests are supported.');
    -  }
    -  this.xdr_.open(method, url);
    -};
    -
    -
    -/**
    - * Sends the request to the remote server. Before calling this function, always
    - * call {@link open}.
    - * @param {(ArrayBuffer|ArrayBufferView|Blob|Document|FormData|null|string)=}
    - *     opt_content The content to send as POSTDATA, if any. Only string data is
    - *     supported by this implementation.
    - * @override
    - */
    -goog.net.IeCorsXhrAdapter.prototype.send = function(opt_content) {
    -  if (opt_content) {
    -    if (typeof opt_content == 'string') {
    -      this.xdr_.send(opt_content);
    -    } else {
    -      throw new Error('Only string data is supported');
    -    }
    -  } else {
    -    this.xdr_.send();
    -  }
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.net.IeCorsXhrAdapter.prototype.abort = function() {
    -  this.xdr_.abort();
    -};
    -
    -
    -/**
    - * Sets a request header to send to the remote server. Because this
    - * implementation does not support request headers, this function does nothing.
    - * @param {string} key The name of the HTTP header to set. Ignored.
    - * @param {string} value The value to set for the HTTP header. Ignored.
    - * @override
    - */
    -goog.net.IeCorsXhrAdapter.prototype.setRequestHeader = function(key, value) {
    -  // Unsupported; ignore the header.
    -};
    -
    -
    -/**
    - * Returns the value of the response header identified by key. This
    - * implementation only supports the 'content-type' header.
    - * @param {string} key The request header to fetch. If this parameter is set to
    - *     'content-type' (case-insensitive), this function returns the value of
    - *     the 'content-type' request header. If this parameter is set to any other
    - *     value, this function always returns an empty string.
    - * @return {string} The value of the response header, or an empty string if key
    - *     is not 'content-type' (case-insensitive).
    - * @override
    - */
    -goog.net.IeCorsXhrAdapter.prototype.getResponseHeader = function(key) {
    -  if (key.toLowerCase() == 'content-type') {
    -    return this.xdr_.contentType;
    -  }
    -  return '';
    -};
    -
    -
    -/**
    - * Handles a request that has fully loaded successfully.
    - * @private
    - */
    -goog.net.IeCorsXhrAdapter.prototype.handleLoad_ = function() {
    -  // IE only calls onload if the status is 200, so the status code must be OK.
    -  this.status = goog.net.HttpStatus.OK;
    -  this.responseText = this.xdr_.responseText;
    -  this.setReadyState_(goog.net.XmlHttp.ReadyState.COMPLETE);
    -};
    -
    -
    -/**
    - * Handles a request that has failed to load.
    - * @private
    - */
    -goog.net.IeCorsXhrAdapter.prototype.handleError_ = function() {
    -  // IE doesn't tell us what the status code actually is (other than the fact
    -  // that it is not 200), so simulate an INTERNAL_SERVER_ERROR.
    -  this.status = goog.net.HttpStatus.INTERNAL_SERVER_ERROR;
    -  this.responseText = null;
    -  this.setReadyState_(goog.net.XmlHttp.ReadyState.COMPLETE);
    -};
    -
    -
    -/**
    - * Handles a request that timed out.
    - * @private
    - */
    -goog.net.IeCorsXhrAdapter.prototype.handleTimeout_ = function() {
    -  this.handleError_();
    -};
    -
    -
    -/**
    - * Handles a request that is in the process of loading.
    - * @private
    - */
    -goog.net.IeCorsXhrAdapter.prototype.handleProgress_ = function() {
    -  // IE only calls onprogress if the status is 200, so the status code must be
    -  // OK.
    -  this.status = goog.net.HttpStatus.OK;
    -  this.setReadyState_(goog.net.XmlHttp.ReadyState.LOADING);
    -};
    -
    -
    -/**
    - * Sets this XHR's ready state and fires the onreadystatechange listener (if one
    - * is set).
    - * @param {number} readyState The new ready state.
    - * @private
    - */
    -goog.net.IeCorsXhrAdapter.prototype.setReadyState_ = function(readyState) {
    -  this.readyState = readyState;
    -  if (this.onreadystatechange) {
    -    this.onreadystatechange();
    -  }
    -};
    -
    -
    -/**
    - * Returns the response headers from the server. This implemntation only returns
    - * the 'content-type' header.
    - * @return {string} The headers returned from the server.
    - * @override
    - */
    -goog.net.IeCorsXhrAdapter.prototype.getAllResponseHeaders = function() {
    -  return 'content-type: ' + this.xdr_.contentType;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/net/corsxmlhttpfactory_test.html b/src/database/third_party/closure-library/closure/goog/net/corsxmlhttpfactory_test.html
    deleted file mode 100644
    index 9b192f06cfb..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/corsxmlhttpfactory_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.net.CorsXmlHttpFactory
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.net.CorsXmlHttpFactoryTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/corsxmlhttpfactory_test.js b/src/database/third_party/closure-library/closure/goog/net/corsxmlhttpfactory_test.js
    deleted file mode 100644
    index 7d38a5d92c2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/corsxmlhttpfactory_test.js
    +++ /dev/null
    @@ -1,44 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.net.CorsXmlHttpFactoryTest');
    -goog.setTestOnly('goog.net.CorsXmlHttpFactoryTest');
    -
    -goog.require('goog.net.CorsXmlHttpFactory');
    -goog.require('goog.net.IeCorsXhrAdapter');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -function testBrowserSupport() {
    -  var requestFactory = new goog.net.CorsXmlHttpFactory();
    -  if (goog.userAgent.IE) {
    -    if (goog.userAgent.isVersionOrHigher('10')) {
    -      // Continue: IE10 supports CORS requests using native XMLHttpRequest.
    -    } else if (goog.userAgent.isVersionOrHigher('8')) {
    -      assertTrue(
    -          requestFactory.createInstance() instanceof goog.net.IeCorsXhrAdapter);
    -      return;
    -    } else {
    -      try {
    -        requestFactory.createInstance();
    -        fail('Error expected.');
    -      } catch (e) {
    -        assertEquals('Unsupported browser', e.message);
    -        return;
    -      }
    -    }
    -  }
    -  // All other browsers support CORS requests using native XMLHttpRequest.
    -  assertTrue(requestFactory.createInstance() instanceof XMLHttpRequest);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/net/crossdomainrpc.js b/src/database/third_party/closure-library/closure/goog/net/crossdomainrpc.js
    deleted file mode 100644
    index 7ab768e4f32..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/crossdomainrpc.js
    +++ /dev/null
    @@ -1,893 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Cross domain RPC library using the <a
    - * href="http://go/xd2_design" target="_top">XD2 approach</a>.
    - *
    - * <h5>Protocol</h5>
    - * Client sends a request across domain via a form submission.  Server
    - * receives these parameters: "xdpe:request-id", "xdpe:dummy-uri" ("xdpe" for
    - * "cross domain parameter to echo back") and other user parameters prefixed
    - * with "xdp" (for "cross domain parameter").  Headers are passed as parameters
    - * prefixed with "xdh" (for "cross domain header").  Only strings are supported
    - * for parameters and headers.  A GET method is mapped to a form GET.  All
    - * other methods are mapped to a POST.  Server is expected to produce a
    - * HTML response such as the following:
    - * <pre>
    - * &lt;body&gt;
    - * &lt;script type="text/javascript"
    - *     src="path-to-crossdomainrpc.js"&gt;&lt;/script&gt;
    - * var currentDirectory = location.href.substring(
    - *     0, location.href.lastIndexOf('/')
    - * );
    - *
    - * // echo all parameters prefixed with "xdpe:"
    - * var echo = {};
    - * echo[goog.net.CrossDomainRpc.PARAM_ECHO_REQUEST_ID] =
    - *     &lt;value of parameter "xdpe:request-id"&gt;;
    - * echo[goog.net.CrossDomainRpc.PARAM_ECHO_DUMMY_URI] =
    - *     &lt;value of parameter "xdpe:dummy-uri"&gt;;
    - *
    - * goog.net.CrossDomainRpc.sendResponse(
    - *     '({"result":"&lt;responseInJSON"})',
    - *     true,    // is JSON
    - *     echo,    // parameters to echo back
    - *     status,  // response status code
    - *     headers  // response headers
    - * );
    - * &lt;/script&gt;
    - * &lt;/body&gt;
    - * </pre>
    - *
    - * <h5>Server Side</h5>
    - * For an example of the server side, refer to the following files:
    - * <ul>
    - * <li>http://go/xdservletfilter.java</li>
    - * <li>http://go/xdservletrequest.java</li>
    - * <li>http://go/xdservletresponse.java</li>
    - * </ul>
    - *
    - * <h5>System Requirements</h5>
    - * Tested on IE6, IE7, Firefox 2.0 and Safari nightly r23841.
    - *
    - */
    -
    -goog.provide('goog.net.CrossDomainRpc');
    -
    -goog.require('goog.Uri');
    -goog.require('goog.dom');
    -goog.require('goog.dom.safe');
    -goog.require('goog.events');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -goog.require('goog.html.legacyconversions');
    -goog.require('goog.json');
    -goog.require('goog.log');
    -goog.require('goog.net.EventType');
    -goog.require('goog.net.HttpStatus');
    -goog.require('goog.string');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Creates a new instance of cross domain RPC.
    - *
    - * This class makes use of goog.html.legacyconversions and provides no
    - * HTML-type-safe alternative. As such, it is not compatible with
    - * code that sets goog.html.legacyconversions.ALLOW_LEGACY_CONVERSIONS to
    - * false.
    - *
    - * @extends {goog.events.EventTarget}
    - * @constructor
    - * @final
    - */
    -goog.net.CrossDomainRpc = function() {
    -  goog.events.EventTarget.call(this);
    -};
    -goog.inherits(goog.net.CrossDomainRpc, goog.events.EventTarget);
    -
    -
    -/**
    - * Cross-domain response iframe marker.
    - * @type {string}
    - * @private
    - */
    -goog.net.CrossDomainRpc.RESPONSE_MARKER_ = 'xdrp';
    -
    -
    -/**
    - * Use a fallback dummy resource if none specified or detected.
    - * @type {boolean}
    - * @private
    - */
    -goog.net.CrossDomainRpc.useFallBackDummyResource_ = true;
    -
    -
    -/** @type {Object} */
    -goog.net.CrossDomainRpc.prototype.responseHeaders;
    -
    -
    -/** @type {string} */
    -goog.net.CrossDomainRpc.prototype.responseText;
    -
    -
    -/** @type {number} */
    -goog.net.CrossDomainRpc.prototype.status;
    -
    -
    -/** @type {number} */
    -goog.net.CrossDomainRpc.prototype.timeWaitedAfterResponseReady_;
    -
    -
    -/** @private {boolean} */
    -goog.net.CrossDomainRpc.prototype.responseTextIsJson_;
    -
    -
    -/** @private {boolean} */
    -goog.net.CrossDomainRpc.prototype.responseReady_;
    -
    -
    -/** @private {!HTMLIFrameElement} */
    -goog.net.CrossDomainRpc.prototype.requestFrame_;
    -
    -
    -/** @private {goog.events.Key} */
    -goog.net.CrossDomainRpc.prototype.loadListenerKey_;
    -
    -
    -/**
    - * Checks to see if we are executing inside a response iframe.  This is the
    - * case when this page is used as a dummy resource to gain caller's domain.
    - * @return {*} True if we are executing inside a response iframe; false
    - *     otherwise.
    - * @private
    - */
    -goog.net.CrossDomainRpc.isInResponseIframe_ = function() {
    -  return window.location && (window.location.hash.indexOf(
    -      goog.net.CrossDomainRpc.RESPONSE_MARKER_) == 1 ||
    -      window.location.search.indexOf(
    -          goog.net.CrossDomainRpc.RESPONSE_MARKER_) == 1);
    -};
    -
    -
    -/**
    - * Stops execution of the rest of the page if this page is loaded inside a
    - *    response iframe.
    - */
    -if (goog.net.CrossDomainRpc.isInResponseIframe_()) {
    -  if (goog.userAgent.IE) {
    -    document.execCommand('Stop');
    -  } else if (goog.userAgent.GECKO) {
    -    window.stop();
    -  } else {
    -    throw Error('stopped');
    -  }
    -}
    -
    -
    -/**
    - * Sets the URI for a dummy resource on caller's domain.  This function is
    - * used for specifying a particular resource to use rather than relying on
    - * auto detection.
    - * @param {string} dummyResourceUri URI to dummy resource on the same domain
    - *    of caller's page.
    - */
    -goog.net.CrossDomainRpc.setDummyResourceUri = function(dummyResourceUri) {
    -  goog.net.CrossDomainRpc.dummyResourceUri_ = dummyResourceUri;
    -};
    -
    -
    -/**
    - * Sets whether a fallback dummy resource ("/robots.txt" on Firefox and Safari
    - * and current page on IE) should be used when a suitable dummy resource is
    - * not available.
    - * @param {boolean} useFallBack Whether to use fallback or not.
    - */
    -goog.net.CrossDomainRpc.setUseFallBackDummyResource = function(useFallBack) {
    -  goog.net.CrossDomainRpc.useFallBackDummyResource_ = useFallBack;
    -};
    -
    -
    -/**
    - * Sends a request across domain.
    - * @param {string} uri Uri to make request to.
    - * @param {Function=} opt_continuation Continuation function to be called
    - *     when request is completed.  Takes one argument of an event object
    - *     whose target has the following properties: "status" is the HTTP
    - *     response status code, "responseText" is the response text,
    - *     and "headers" is an object with all response headers.  The event
    - *     target's getResponseJson() method returns a JavaScript object evaluated
    - *     from the JSON response or undefined if response is not JSON.
    - * @param {string=} opt_method Method of request. Default is POST.
    - * @param {Object=} opt_params Parameters. Each property is turned into a
    - *     request parameter.
    - * @param {Object=} opt_headers Map of headers of the request.
    - */
    -goog.net.CrossDomainRpc.send =
    -    function(uri, opt_continuation, opt_method, opt_params, opt_headers) {
    -  var xdrpc = new goog.net.CrossDomainRpc();
    -  if (opt_continuation) {
    -    goog.events.listen(xdrpc, goog.net.EventType.COMPLETE, opt_continuation);
    -  }
    -  goog.events.listen(xdrpc, goog.net.EventType.READY, xdrpc.reset);
    -  xdrpc.sendRequest(uri, opt_method, opt_params, opt_headers);
    -};
    -
    -
    -/**
    - * Sets debug mode to true or false.  When debug mode is on, response iframes
    - * are visible and left behind after their use is finished.
    - * @param {boolean} flag Flag to indicate intention to turn debug model on
    - *     (true) or off (false).
    - */
    -goog.net.CrossDomainRpc.setDebugMode = function(flag) {
    -  goog.net.CrossDomainRpc.debugMode_ = flag;
    -};
    -
    -
    -/**
    - * Logger for goog.net.CrossDomainRpc
    - * @type {goog.log.Logger}
    - * @private
    - */
    -goog.net.CrossDomainRpc.logger_ =
    -    goog.log.getLogger('goog.net.CrossDomainRpc');
    -
    -
    -/**
    - * Creates the HTML of an input element
    - * @param {string} name Name of input element.
    - * @param {*} value Value of input element.
    - * @return {string} HTML of input element with that name and value.
    - * @private
    - */
    -goog.net.CrossDomainRpc.createInputHtml_ = function(name, value) {
    -  return '<textarea name="' + name + '">' +
    -      goog.net.CrossDomainRpc.escapeAmpersand_(value) + '</textarea>';
    -};
    -
    -
    -/**
    - * Escapes ampersand so that XML/HTML entities are submitted as is because
    - * browser unescapes them when they are put into a text area.
    - * @param {*} value Value to escape.
    - * @return {*} Value with ampersand escaped, if value is a string;
    - *     otherwise the value itself is returned.
    - * @private
    - */
    -goog.net.CrossDomainRpc.escapeAmpersand_ = function(value) {
    -  return value && (goog.isString(value) || value.constructor == String) ?
    -      value.replace(/&/g, '&amp;') : value;
    -};
    -
    -
    -/**
    - * Finds a dummy resource that can be used by response to gain domain of
    - * requester's page.
    - * @return {string} URI of the resource to use.
    - * @private
    - */
    -goog.net.CrossDomainRpc.getDummyResourceUri_ = function() {
    -  if (goog.net.CrossDomainRpc.dummyResourceUri_) {
    -    return goog.net.CrossDomainRpc.dummyResourceUri_;
    -  }
    -
    -  // find a style sheet if not on IE, which will attempt to save style sheet
    -  if (goog.userAgent.GECKO) {
    -    var links = document.getElementsByTagName('link');
    -    for (var i = 0; i < links.length; i++) {
    -      var link = links[i];
    -      // find a link which is on the same domain as this page
    -      // cannot use one with '?' or '#' in its URL as it will confuse
    -      // goog.net.CrossDomainRpc.getFramePayload_()
    -      if (link.rel == 'stylesheet' &&
    -          goog.Uri.haveSameDomain(link.href, window.location.href) &&
    -          link.href.indexOf('?') < 0) {
    -        return goog.net.CrossDomainRpc.removeHash_(link.href);
    -      }
    -    }
    -  }
    -
    -  var images = document.getElementsByTagName('img');
    -  for (var i = 0; i < images.length; i++) {
    -    var image = images[i];
    -    // find a link which is on the same domain as this page
    -    // cannot use one with '?' or '#' in its URL as it will confuse
    -    // goog.net.CrossDomainRpc.getFramePayload_()
    -    if (goog.Uri.haveSameDomain(image.src, window.location.href) &&
    -        image.src.indexOf('?') < 0) {
    -      return goog.net.CrossDomainRpc.removeHash_(image.src);
    -    }
    -  }
    -
    -  if (!goog.net.CrossDomainRpc.useFallBackDummyResource_) {
    -    throw Error(
    -        'No suitable dummy resource specified or detected for this page');
    -  }
    -
    -  if (goog.userAgent.IE) {
    -    // use this page as the dummy resource; remove hash from URL if any
    -    return goog.net.CrossDomainRpc.removeHash_(window.location.href);
    -  } else {
    -    /**
    -     * Try to use "http://<this-domain>/robots.txt" which may exist.  Even if
    -     * it does not, an error page is returned and is a good dummy resource to
    -     * use on Firefox and Safari.  An existing resource is faster because it
    -     * is cached.
    -     */
    -    var locationHref = window.location.href;
    -    var rootSlash = locationHref.indexOf('/', locationHref.indexOf('//') + 2);
    -    var rootHref = locationHref.substring(0, rootSlash);
    -    return rootHref + '/robots.txt';
    -  }
    -};
    -
    -
    -/**
    - * Removes everything at and after hash from URI
    - * @param {string} uri Uri to to remove hash.
    - * @return {string} Uri with its hash and all characters after removed.
    - * @private
    - */
    -goog.net.CrossDomainRpc.removeHash_ = function(uri) {
    -  return uri.split('#')[0];
    -};
    -
    -
    -// ------------
    -// request side
    -
    -
    -/**
    - * next request id used to support multiple XD requests at the same time
    - * @type {number}
    - * @private
    - */
    -goog.net.CrossDomainRpc.nextRequestId_ = 0;
    -
    -
    -/**
    - * Header prefix.
    - * @type {string}
    - */
    -goog.net.CrossDomainRpc.HEADER = 'xdh:';
    -
    -
    -/**
    - * Parameter prefix.
    - * @type {string}
    - */
    -goog.net.CrossDomainRpc.PARAM = 'xdp:';
    -
    -
    -/**
    - * Parameter to echo prefix.
    - * @type {string}
    - */
    -goog.net.CrossDomainRpc.PARAM_ECHO = 'xdpe:';
    -
    -
    -/**
    - * Parameter to echo: request id
    - * @type {string}
    - */
    -goog.net.CrossDomainRpc.PARAM_ECHO_REQUEST_ID =
    -    goog.net.CrossDomainRpc.PARAM_ECHO + 'request-id';
    -
    -
    -/**
    - * Parameter to echo: dummy resource URI
    - * @type {string}
    - */
    -goog.net.CrossDomainRpc.PARAM_ECHO_DUMMY_URI =
    -    goog.net.CrossDomainRpc.PARAM_ECHO + 'dummy-uri';
    -
    -
    -/**
    - * Cross-domain request marker.
    - * @type {string}
    - * @private
    - */
    -goog.net.CrossDomainRpc.REQUEST_MARKER_ = 'xdrq';
    -
    -
    -/**
    - * Sends a request across domain.
    - * @param {string} uri Uri to make request to.
    - * @param {string=} opt_method Method of request. Default is POST.
    - * @param {Object=} opt_params Parameters. Each property is turned into a
    - *     request parameter.
    - * @param {Object=} opt_headers Map of headers of the request.
    - */
    -goog.net.CrossDomainRpc.prototype.sendRequest =
    -    function(uri, opt_method, opt_params, opt_headers) {
    -  // create request frame
    -  var requestFrame = this.requestFrame_ = /** @type {!HTMLIFrameElement} */ (
    -      document.createElement('iframe'));
    -  var requestId = goog.net.CrossDomainRpc.nextRequestId_++;
    -  requestFrame.id = goog.net.CrossDomainRpc.REQUEST_MARKER_ + '-' + requestId;
    -  if (!goog.net.CrossDomainRpc.debugMode_) {
    -    requestFrame.style.position = 'absolute';
    -    requestFrame.style.top = '-5000px';
    -    requestFrame.style.left = '-5000px';
    -  }
    -  document.body.appendChild(requestFrame);
    -
    -  // build inputs
    -  var inputs = [];
    -
    -  // add request id
    -  inputs.push(goog.net.CrossDomainRpc.createInputHtml_(
    -      goog.net.CrossDomainRpc.PARAM_ECHO_REQUEST_ID, requestId));
    -
    -  // add dummy resource uri
    -  var dummyUri = goog.net.CrossDomainRpc.getDummyResourceUri_();
    -  goog.log.fine(goog.net.CrossDomainRpc.logger_,
    -      'dummyUri: ' + dummyUri);
    -  inputs.push(goog.net.CrossDomainRpc.createInputHtml_(
    -      goog.net.CrossDomainRpc.PARAM_ECHO_DUMMY_URI, dummyUri));
    -
    -  // add parameters
    -  if (opt_params) {
    -    for (var name in opt_params) {
    -      var value = opt_params[name];
    -      inputs.push(goog.net.CrossDomainRpc.createInputHtml_(
    -          goog.net.CrossDomainRpc.PARAM + name, value));
    -    }
    -  }
    -
    -  // add headers
    -  if (opt_headers) {
    -    for (var name in opt_headers) {
    -      var value = opt_headers[name];
    -      inputs.push(goog.net.CrossDomainRpc.createInputHtml_(
    -          goog.net.CrossDomainRpc.HEADER + name, value));
    -    }
    -  }
    -
    -  var requestFrameContent = '<body><form method="' +
    -      (opt_method == 'GET' ? 'GET' : 'POST') + '" action="' +
    -      uri + '">' + inputs.join('') + '</form></body>';
    -  var requestFrameContentHtml = goog.html.legacyconversions.safeHtmlFromString(
    -      requestFrameContent);
    -  var requestFrameDoc = goog.dom.getFrameContentDocument(requestFrame);
    -  requestFrameDoc.open();
    -  goog.dom.safe.documentWrite(requestFrameDoc, requestFrameContentHtml);
    -  requestFrameDoc.close();
    -
    -  requestFrameDoc.forms[0].submit();
    -  requestFrameDoc = null;
    -
    -  this.loadListenerKey_ = goog.events.listen(
    -      requestFrame, goog.events.EventType.LOAD, function() {
    -        goog.log.fine(goog.net.CrossDomainRpc.logger_, 'response ready');
    -        this.responseReady_ = true;
    -      }, false, this);
    -
    -  this.receiveResponse_();
    -};
    -
    -
    -/**
    - * period of response polling (ms)
    - * @type {number}
    - * @private
    - */
    -goog.net.CrossDomainRpc.RESPONSE_POLLING_PERIOD_ = 50;
    -
    -
    -/**
    - * timeout from response comes back to sendResponse is called (ms)
    - * @type {number}
    - * @private
    - */
    -goog.net.CrossDomainRpc.SEND_RESPONSE_TIME_OUT_ = 500;
    -
    -
    -/**
    - * Receives response by polling to check readiness of response and then
    - *     reads response frames and assembles response data
    - * @private
    - */
    -goog.net.CrossDomainRpc.prototype.receiveResponse_ = function() {
    -  this.timeWaitedAfterResponseReady_ = 0;
    -  var responseDetectorHandle = window.setInterval(goog.bind(function() {
    -    this.detectResponse_(responseDetectorHandle);
    -  }, this), goog.net.CrossDomainRpc.RESPONSE_POLLING_PERIOD_);
    -};
    -
    -
    -/**
    - * Detects response inside request frame
    - * @param {number} responseDetectorHandle Handle of detector.
    - * @private
    - */
    -goog.net.CrossDomainRpc.prototype.detectResponse_ =
    -    function(responseDetectorHandle) {
    -  var requestFrameWindow = this.requestFrame_.contentWindow;
    -  var grandChildrenLength = requestFrameWindow.frames.length;
    -  var responseInfoFrame = null;
    -  if (grandChildrenLength > 0 &&
    -      goog.net.CrossDomainRpc.isResponseInfoFrame_(responseInfoFrame =
    -      requestFrameWindow.frames[grandChildrenLength - 1])) {
    -    goog.log.fine(goog.net.CrossDomainRpc.logger_,
    -        'xd response ready');
    -
    -    var responseInfoPayload = goog.net.CrossDomainRpc.getFramePayload_(
    -        responseInfoFrame).substring(1);
    -    var params = new goog.Uri.QueryData(responseInfoPayload);
    -
    -    var chunks = [];
    -    var numChunks = Number(params.get('n'));
    -    goog.log.fine(goog.net.CrossDomainRpc.logger_,
    -        'xd response number of chunks: ' + numChunks);
    -    for (var i = 0; i < numChunks; i++) {
    -      var responseFrame = requestFrameWindow.frames[i];
    -      if (!responseFrame || !responseFrame.location ||
    -          !responseFrame.location.href) {
    -        // On Safari 3.0, it is sometimes the case that the
    -        // iframe exists but doesn't have a same domain href yet.
    -        goog.log.fine(goog.net.CrossDomainRpc.logger_,
    -            'xd response iframe not ready');
    -        return;
    -      }
    -      var responseChunkPayload =
    -          goog.net.CrossDomainRpc.getFramePayload_(responseFrame);
    -      // go past "chunk="
    -      var chunkIndex = responseChunkPayload.indexOf(
    -          goog.net.CrossDomainRpc.PARAM_CHUNK_) +
    -          goog.net.CrossDomainRpc.PARAM_CHUNK_.length + 1;
    -      var chunk = responseChunkPayload.substring(chunkIndex);
    -      chunks.push(chunk);
    -    }
    -
    -    window.clearInterval(responseDetectorHandle);
    -
    -    var responseData = chunks.join('');
    -    // Payload is not encoded to begin with on IE. Decode in other cases only.
    -    if (!goog.userAgent.IE) {
    -      responseData = decodeURIComponent(responseData);
    -    }
    -
    -    this.status = Number(params.get('status'));
    -    this.responseText = responseData;
    -    this.responseTextIsJson_ = params.get('isDataJson') == 'true';
    -    this.responseHeaders = goog.json.unsafeParse(
    -        /** @type {string} */ (params.get('headers')));
    -
    -    this.dispatchEvent(goog.net.EventType.READY);
    -    this.dispatchEvent(goog.net.EventType.COMPLETE);
    -  } else {
    -    if (this.responseReady_) {
    -      /* The response has come back. But the first response iframe has not
    -       * been created yet. If this lasts long enough, it is an error.
    -       */
    -      this.timeWaitedAfterResponseReady_ +=
    -          goog.net.CrossDomainRpc.RESPONSE_POLLING_PERIOD_;
    -      if (this.timeWaitedAfterResponseReady_ >
    -          goog.net.CrossDomainRpc.SEND_RESPONSE_TIME_OUT_) {
    -        goog.log.fine(goog.net.CrossDomainRpc.logger_,
    -            'xd response timed out');
    -        window.clearInterval(responseDetectorHandle);
    -
    -        this.status = goog.net.HttpStatus.INTERNAL_SERVER_ERROR;
    -        this.responseText = 'response timed out';
    -
    -        this.dispatchEvent(goog.net.EventType.READY);
    -        this.dispatchEvent(goog.net.EventType.ERROR);
    -        this.dispatchEvent(goog.net.EventType.COMPLETE);
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Checks whether a frame is response info frame.
    - * @param {Object} frame Frame to check.
    - * @return {boolean} True if frame is a response info frame; false otherwise.
    - * @private
    - */
    -goog.net.CrossDomainRpc.isResponseInfoFrame_ = function(frame) {
    -  /** @preserveTry */
    -  try {
    -    return goog.net.CrossDomainRpc.getFramePayload_(frame).indexOf(
    -        goog.net.CrossDomainRpc.RESPONSE_INFO_MARKER_) == 1;
    -  } catch (e) {
    -    // frame not ready for same-domain access yet
    -    return false;
    -  }
    -};
    -
    -
    -/**
    - * Returns the payload of a frame (value after # or ? on the URL).  This value
    - * is URL encoded except IE, where the value is not encoded to begin with.
    - * @param {Object} frame Frame.
    - * @return {string} Payload of that frame.
    - * @private
    - */
    -goog.net.CrossDomainRpc.getFramePayload_ = function(frame) {
    -  var href = frame.location.href;
    -  var question = href.indexOf('?');
    -  var hash = href.indexOf('#');
    -  // On IE, beucase the URL is not encoded, we can have a case where ?
    -  // is the delimiter before payload and # in payload or # as the delimiter
    -  // and ? in payload.  So here we treat whoever is the first as the delimiter.
    -  var delimiter = question < 0 ? hash :
    -      hash < 0 ? question : Math.min(question, hash);
    -  return href.substring(delimiter);
    -};
    -
    -
    -/**
    - * If response is JSON, evaluates it to a JavaScript object and
    - * returns it; otherwise returns undefined.
    - * @return {Object|undefined} JavaScript object if response is in JSON
    - *     or undefined.
    - */
    -goog.net.CrossDomainRpc.prototype.getResponseJson = function() {
    -  return this.responseTextIsJson_ ?
    -      goog.json.unsafeParse(this.responseText) : undefined;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the request completed with a success.
    - */
    -goog.net.CrossDomainRpc.prototype.isSuccess = function() {
    -  // Definition similar to goog.net.XhrIo.prototype.isSuccess.
    -  switch (this.status) {
    -    case goog.net.HttpStatus.OK:
    -    case goog.net.HttpStatus.NOT_MODIFIED:
    -      return true;
    -
    -    default:
    -      return false;
    -  }
    -};
    -
    -
    -/**
    - * Removes request iframe used.
    - */
    -goog.net.CrossDomainRpc.prototype.reset = function() {
    -  if (!goog.net.CrossDomainRpc.debugMode_) {
    -    goog.log.fine(goog.net.CrossDomainRpc.logger_,
    -        'request frame removed: ' + this.requestFrame_.id);
    -    goog.events.unlistenByKey(this.loadListenerKey_);
    -    this.requestFrame_.parentNode.removeChild(this.requestFrame_);
    -  }
    -  delete this.requestFrame_;
    -};
    -
    -
    -// -------------
    -// response side
    -
    -
    -/**
    - * Name of response info iframe.
    - * @type {string}
    - * @private
    - */
    -goog.net.CrossDomainRpc.RESPONSE_INFO_MARKER_ =
    -    goog.net.CrossDomainRpc.RESPONSE_MARKER_ + '-info';
    -
    -
    -/**
    - * Maximal chunk size.  IE can only handle 4095 bytes on its URL.
    - * 16MB has been tested on Firefox.  But 1MB is a practical size.
    - * @type {number}
    - * @private
    - */
    -goog.net.CrossDomainRpc.MAX_CHUNK_SIZE_ =
    -    goog.userAgent.IE ? 4095 : 1024 * 1024;
    -
    -
    -/**
    - * Query parameter 'chunk'.
    - * @type {string}
    - * @private
    - */
    -goog.net.CrossDomainRpc.PARAM_CHUNK_ = 'chunk';
    -
    -
    -/**
    - * Prefix before data chunk for passing other parameters.
    - * type String
    - * @private
    - */
    -goog.net.CrossDomainRpc.CHUNK_PREFIX_ =
    -    goog.net.CrossDomainRpc.RESPONSE_MARKER_ + '=1&' +
    -    goog.net.CrossDomainRpc.PARAM_CHUNK_ + '=';
    -
    -
    -/**
    - * Makes response available for grandparent (requester)'s receiveResponse
    - * call to pick up by creating a series of iframes pointed to the dummy URI
    - * with a payload (value after either ? or #) carrying a chunk of response
    - * data and a response info iframe that tells the grandparent (requester) the
    - * readiness of response.
    - * @param {string} data Response data (string or JSON string).
    - * @param {boolean} isDataJson true if data is a JSON string; false if just a
    - *     string.
    - * @param {Object} echo Parameters to echo back
    - *     "xdpe:request-id": Server that produces the response needs to
    - *     copy it here to support multiple current XD requests on the same page.
    - *     "xdpe:dummy-uri": URI to a dummy resource that response
    - *     iframes point to to gain the domain of the client.  This can be an
    - *     image (IE) or a CSS file (FF) found on the requester's page.
    - *     Server should copy value from request parameter "xdpe:dummy-uri".
    - * @param {number} status HTTP response status code.
    - * @param {string} headers Response headers in JSON format.
    - */
    -goog.net.CrossDomainRpc.sendResponse =
    -    function(data, isDataJson, echo, status, headers) {
    -  var dummyUri = echo[goog.net.CrossDomainRpc.PARAM_ECHO_DUMMY_URI];
    -
    -  // since the dummy-uri can be specified by the user, verify that it doesn't
    -  // use any other protocols. (Specifically we don't want users to use a
    -  // dummy-uri beginning with "javascript:").
    -  if (!goog.string.caseInsensitiveStartsWith(dummyUri, 'http://') &&
    -      !goog.string.caseInsensitiveStartsWith(dummyUri, 'https://')) {
    -    dummyUri = 'http://' + dummyUri;
    -  }
    -
    -  // usable chunk size is max less dummy URI less chunk prefix length
    -  // TODO(user): Figure out why we need to do "- 1" below
    -  var chunkSize = goog.net.CrossDomainRpc.MAX_CHUNK_SIZE_ - dummyUri.length -
    -      1 - // payload delimiter ('#' or '?')
    -      goog.net.CrossDomainRpc.CHUNK_PREFIX_.length - 1;
    -
    -  /*
    -   * Here we used to do URI encoding of data before we divide it into chunks
    -   * and decode on the receiving end.  We don't do this any more on IE for the
    -   * following reasons.
    -   *
    -   * 1) On IE, calling decodeURIComponent on a relatively large string is
    -   *   extremely slow (~22s for 160KB).  So even a moderate amount of data
    -   *   makes this library pretty much useless.  Fortunately, we can actually
    -   *   put unencoded data on IE's URL and get it back reliably.  So we are
    -   *   completely skipping encoding and decoding on IE.  When we call
    -   *   getFrameHash_ to get it back, the value is still intact(*) and unencoded.
    -   * 2) On Firefox, we have to call decodeURIComponent because location.hash
    -   *   does decoding by itself.  Fortunately, decodeURIComponent is not slow
    -   *   on Firefox.
    -   * 3) Safari automatically encodes everything you put on URL and it does not
    -   *   automatically decode when you access it via location.hash or
    -   *   location.href.  So we encode it here and decode it in detectResponse_().
    -   *
    -   * Note(*): IE actually does encode only space to %20 and decodes that
    -   *   automatically when you do location.href or location.hash.
    -   */
    -  if (!goog.userAgent.IE) {
    -    data = encodeURIComponent(data);
    -  }
    -
    -  var numChunksToSend = Math.ceil(data.length / chunkSize);
    -  if (numChunksToSend == 0) {
    -    goog.net.CrossDomainRpc.createResponseInfo_(
    -        dummyUri, numChunksToSend, isDataJson, status, headers);
    -  } else {
    -    var numChunksSent = 0;
    -    var checkToCreateResponseInfo_ = function() {
    -      if (++numChunksSent == numChunksToSend) {
    -        goog.net.CrossDomainRpc.createResponseInfo_(
    -            dummyUri, numChunksToSend, isDataJson, status, headers);
    -      }
    -    };
    -
    -    for (var i = 0; i < numChunksToSend; i++) {
    -      var chunkStart = i * chunkSize;
    -      var chunkEnd = chunkStart + chunkSize;
    -      var chunk = chunkEnd > data.length ?
    -          data.substring(chunkStart) :
    -          data.substring(chunkStart, chunkEnd);
    -
    -      var responseFrame = document.createElement('iframe');
    -      responseFrame.src = dummyUri +
    -          goog.net.CrossDomainRpc.getPayloadDelimiter_(dummyUri) +
    -          goog.net.CrossDomainRpc.CHUNK_PREFIX_ + chunk;
    -      document.body.appendChild(responseFrame);
    -
    -      // We used to call the function below when handling load event of
    -      // responseFrame.  But that event does not fire on IE when current
    -      // page is used as the dummy resource (because its loading is stopped?).
    -      // It also does not fire sometimes on Firefox.  So now we call it
    -      // directly.
    -      checkToCreateResponseInfo_();
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Creates a response info iframe to indicate completion of sendResponse
    - * @param {string} dummyUri URI to a dummy resource.
    - * @param {number} numChunks Total number of chunks.
    - * @param {boolean} isDataJson Whether response is a JSON string or just string.
    - * @param {number} status HTTP response status code.
    - * @param {string} headers Response headers in JSON format.
    - * @private
    - */
    -goog.net.CrossDomainRpc.createResponseInfo_ =
    -    function(dummyUri, numChunks, isDataJson, status, headers) {
    -  var responseInfoFrame = document.createElement('iframe');
    -  document.body.appendChild(responseInfoFrame);
    -  responseInfoFrame.src = dummyUri +
    -      goog.net.CrossDomainRpc.getPayloadDelimiter_(dummyUri) +
    -      goog.net.CrossDomainRpc.RESPONSE_INFO_MARKER_ +
    -      '=1&n=' + numChunks + '&isDataJson=' + isDataJson + '&status=' + status +
    -      '&headers=' + encodeURIComponent(headers);
    -};
    -
    -
    -/**
    - * Returns payload delimiter, either "#" when caller's page is not used as
    - * the dummy resource or "?" when it is, in which case caching issues prevent
    - * response frames to gain the caller's domain.
    - * @param {string} dummyUri URI to resource being used as dummy resource.
    - * @return {string} Either "?" when caller's page is used as dummy resource or
    - *     "#" if it is not.
    - * @private
    - */
    -goog.net.CrossDomainRpc.getPayloadDelimiter_ = function(dummyUri) {
    -  return goog.net.CrossDomainRpc.REFERRER_ == dummyUri ? '?' : '#';
    -};
    -
    -
    -/**
    - * Removes all parameters (after ? or #) from URI.
    - * @param {string} uri URI to remove parameters from.
    - * @return {string} URI with all parameters removed.
    - * @private
    - */
    -goog.net.CrossDomainRpc.removeUriParams_ = function(uri) {
    -  // remove everything after question mark
    -  var question = uri.indexOf('?');
    -  if (question > 0) {
    -    uri = uri.substring(0, question);
    -  }
    -
    -  // remove everything after hash mark
    -  var hash = uri.indexOf('#');
    -  if (hash > 0) {
    -    uri = uri.substring(0, hash);
    -  }
    -
    -  return uri;
    -};
    -
    -
    -/**
    - * Gets a response header.
    - * @param {string} name Name of response header.
    - * @return {string|undefined} Value of response header; undefined if not found.
    - */
    -goog.net.CrossDomainRpc.prototype.getResponseHeader = function(name) {
    -  return goog.isObject(this.responseHeaders) ?
    -      this.responseHeaders[name] : undefined;
    -};
    -
    -
    -/**
    - * Referrer of current document with all parameters after "?" and "#" stripped.
    - * @type {string}
    - * @private
    - */
    -goog.net.CrossDomainRpc.REFERRER_ =
    -    goog.net.CrossDomainRpc.removeUriParams_(document.referrer);
    diff --git a/src/database/third_party/closure-library/closure/goog/net/crossdomainrpc_test.css b/src/database/third_party/closure-library/closure/goog/net/crossdomainrpc_test.css
    deleted file mode 100644
    index 73cc31122e9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/crossdomainrpc_test.css
    +++ /dev/null
    @@ -1,7 +0,0 @@
    -/*
    - * Copyright 2010 The Closure Library Authors. All Rights Reserved.
    - *
    - * Use of this source code is governed by the Apache License, Version 2.0.
    - * See the COPYING file for details.
    - */
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/net/crossdomainrpc_test.gif b/src/database/third_party/closure-library/closure/goog/net/crossdomainrpc_test.gif
    deleted file mode 100644
    index e69de29bb2d..00000000000
    diff --git a/src/database/third_party/closure-library/closure/goog/net/crossdomainrpc_test.html b/src/database/third_party/closure-library/closure/goog/net/crossdomainrpc_test.html
    deleted file mode 100644
    index dcc8920b381..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/crossdomainrpc_test.html
    +++ /dev/null
    @@ -1,30 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.net.CrossDomainRpc
    -  </title>
    -  <link href="CrossDomainRpc_test.css?123" rel="stylesheet" type="text/css" />
    -  <link href="CrossDomainRpc_test.css#123" rel="stylesheet" type="text/css" />
    -  <link href="CrossDomainRpc_test.css" rel="stylesheet" type="text/css" />
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -  goog.require('goog.net.CrossDomainRpcTest');
    -  </script>
    - </head>
    - <body>
    -  <img src="crossdomainrpc_test.gif?123" alt="dummy resource" />
    -  <img src="crossdomainrpc_test.gif#123" alt="dummy resource" />
    -  <img src="crossdomainrpc_test.gif" alt="dummy resource" />
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/crossdomainrpc_test.js b/src/database/third_party/closure-library/closure/goog/net/crossdomainrpc_test.js
    deleted file mode 100644
    index 1bd1f6f0ae1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/crossdomainrpc_test.js
    +++ /dev/null
    @@ -1,119 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.net.CrossDomainRpcTest');
    -goog.setTestOnly('goog.net.CrossDomainRpcTest');
    -
    -goog.require('goog.log');
    -goog.require('goog.log.Level');
    -goog.require('goog.net.CrossDomainRpc');
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -
    -var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall();
    -
    -function print(o) {
    -  if (Object.prototype.toSource) {
    -    return o.toSource();
    -  } else {
    -    var fragments = [];
    -    fragments.push('{');
    -    var first = true;
    -    for (var p in o) {
    -      if (!first) fragments.push(',');
    -      fragments.push(p);
    -      fragments.push(':"');
    -      fragments.push(o[p]);
    -      fragments.push('"');
    -      first = false;
    -    }
    -    return fragments.join('');
    -  }
    -}
    -
    -
    -function testNormalRequest() {
    -  var start = new Date();
    -  goog.net.CrossDomainRpc.send(
    -      'crossdomainrpc_test_response.html',
    -      goog.partial(continueTestNormalRequest, start),
    -      'POST',
    -      {xyz: '01234567891123456789'}
    -  );
    -
    -  asyncTestCase.waitForAsync('testNormalRequest');
    -}
    -
    -function continueTestNormalRequest(start, e) {
    -  asyncTestCase.continueTesting();
    -  if (e.target.status < 300) {
    -    var elapsed = new Date() - start;
    -    var responseData = eval(e.target.responseText);
    -    goog.log.log(goog.net.CrossDomainRpc.logger_, goog.log.Level.FINE,
    -                 elapsed + 'ms: [' + responseData.result.length + '] ' +
    -                     print(responseData));
    -    assertEquals(16 * 1024, responseData.result.length);
    -    assertEquals(e.target.status, 123);
    -    assertEquals(e.target.responseHeaders.a, 1);
    -    assertEquals(e.target.responseHeaders.b, '2');
    -  } else {
    -    goog.log.log(goog.net.CrossDomainRpc.logger_, goog.log.Level.FINE,
    -                 print(e));
    -    fail();
    -  }
    -}
    -
    -
    -function testErrorRequest() {
    -  // Firefox does not give a valid error event.
    -  if (goog.userAgent.GECKO) {
    -    return;
    -  }
    -
    -  goog.net.CrossDomainRpc.send(
    -      'http://hoodjimcwaadji.google.com/index.html',
    -      continueTestErrorRequest,
    -      'POST',
    -      {xyz: '01234567891123456789'}
    -  );
    -
    -  asyncTestCase.waitForAsync('testErrorRequest');
    -}
    -
    -function continueTestErrorRequest(e) {
    -  asyncTestCase.continueTesting();
    -
    -  if (e.target.status < 300) {
    -    fail('should have failed requesting a non-existent URI');
    -  } else {
    -    goog.log.log(goog.net.CrossDomainRpc.logger_, goog.log.Level.FINE,
    -                 'expected error seen; event=' + print(e));
    -  }
    -}
    -
    -function testGetDummyResourceUri() {
    -  var url = goog.net.CrossDomainRpc.getDummyResourceUri_();
    -  assertTrue(
    -      'dummy resource URL should not contain "?"', url.indexOf('?') < 0);
    -  assertTrue(
    -      'dummy resource URL should not contain "#"', url.indexOf('#') < 0);
    -}
    -
    -
    -function testRemoveHash() {
    -  assertEquals('abc', goog.net.CrossDomainRpc.removeHash_('abc#123'));
    -  assertEquals('abc', goog.net.CrossDomainRpc.removeHash_('abc#12#3'));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/net/crossdomainrpc_test_response.html b/src/database/third_party/closure-library/closure/goog/net/crossdomainrpc_test_response.html
    deleted file mode 100644
    index f05c9883022..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/crossdomainrpc_test_response.html
    +++ /dev/null
    @@ -1,59 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -
    -
    - In reality, this response comes from a different domain.  For simplicity of
    - testing, this response is one the same domain, while exercising the same
    - functionality.
    --->
    -<title>crossdomainrpc test response</title>
    -<body>
    -<script type="text/javascript" src="../base.js"></script>
    -<script type="text/javascript">
    -goog.require('goog.Uri.QueryData');
    -goog.require('goog.dom');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.json');
    -goog.require('goog.log');
    -goog.require('goog.net.EventType');
    -goog.require('goog.userAgent');
    -</script>
    -<script type="text/javascript" src="crossdomainrpc.js"></script>
    -<script type="text/javascript">
    -function createPayload(size) {
    -  var chars = [];
    -  for (var i = 0; i < size; i++) {
    -    chars.push('0');
    -  }
    -  return chars.join('');
    -};
    -
    -var payload = createPayload(16 * 1024);
    -
    -var currentDirectory = location.href.substring(
    -    0, location.href.lastIndexOf('/')
    -);
    -
    -var echo = {};
    -echo[goog.net.CrossDomainRpc.PARAM_ECHO_REQUEST_ID] = 0;
    -echo[goog.net.CrossDomainRpc.PARAM_ECHO_DUMMY_URI] = goog.userAgent.IE ?
    -    currentDirectory + '/crossdomainrpc_test.gif' :
    -    currentDirectory + '/crossdomainrpc_test.css';
    -
    -goog.net.CrossDomainRpc.sendResponse(
    -    '({"result":"' + payload + '"})',
    -    true,              // is JSON
    -    echo,              // parameters to echo back
    -    123,               // response code
    -    '{"a":1,"b":"2"}'  // response headers
    -);
    -</script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/errorcode.js b/src/database/third_party/closure-library/closure/goog/net/errorcode.js
    deleted file mode 100644
    index 4d6d834f899..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/errorcode.js
    +++ /dev/null
    @@ -1,130 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Error codes shared between goog.net.IframeIo and
    - * goog.net.XhrIo.
    - */
    -
    -goog.provide('goog.net.ErrorCode');
    -
    -
    -/**
    - * Error codes
    - * @enum {number}
    - */
    -goog.net.ErrorCode = {
    -
    -  /**
    -   * There is no error condition.
    -   */
    -  NO_ERROR: 0,
    -
    -  /**
    -   * The most common error from iframeio, unfortunately, is that the browser
    -   * responded with an error page that is classed as a different domain. The
    -   * situations, are when a browser error page  is shown -- 404, access denied,
    -   * DNS failure, connection reset etc.)
    -   *
    -   */
    -  ACCESS_DENIED: 1,
    -
    -  /**
    -   * Currently the only case where file not found will be caused is when the
    -   * code is running on the local file system and a non-IE browser makes a
    -   * request to a file that doesn't exist.
    -   */
    -  FILE_NOT_FOUND: 2,
    -
    -  /**
    -   * If Firefox shows a browser error page, such as a connection reset by
    -   * server or access denied, then it will fail silently without the error or
    -   * load handlers firing.
    -   */
    -  FF_SILENT_ERROR: 3,
    -
    -  /**
    -   * Custom error provided by the client through the error check hook.
    -   */
    -  CUSTOM_ERROR: 4,
    -
    -  /**
    -   * Exception was thrown while processing the request.
    -   */
    -  EXCEPTION: 5,
    -
    -  /**
    -   * The Http response returned a non-successful http status code.
    -   */
    -  HTTP_ERROR: 6,
    -
    -  /**
    -   * The request was aborted.
    -   */
    -  ABORT: 7,
    -
    -  /**
    -   * The request timed out.
    -   */
    -  TIMEOUT: 8,
    -
    -  /**
    -   * The resource is not available offline.
    -   */
    -  OFFLINE: 9
    -};
    -
    -
    -/**
    - * Returns a friendly error message for an error code. These messages are for
    - * debugging and are not localized.
    - * @param {goog.net.ErrorCode} errorCode An error code.
    - * @return {string} A message for debugging.
    - */
    -goog.net.ErrorCode.getDebugMessage = function(errorCode) {
    -  switch (errorCode) {
    -    case goog.net.ErrorCode.NO_ERROR:
    -      return 'No Error';
    -
    -    case goog.net.ErrorCode.ACCESS_DENIED:
    -      return 'Access denied to content document';
    -
    -    case goog.net.ErrorCode.FILE_NOT_FOUND:
    -      return 'File not found';
    -
    -    case goog.net.ErrorCode.FF_SILENT_ERROR:
    -      return 'Firefox silently errored';
    -
    -    case goog.net.ErrorCode.CUSTOM_ERROR:
    -      return 'Application custom error';
    -
    -    case goog.net.ErrorCode.EXCEPTION:
    -      return 'An exception occurred';
    -
    -    case goog.net.ErrorCode.HTTP_ERROR:
    -      return 'Http response at 400 or 500 level';
    -
    -    case goog.net.ErrorCode.ABORT:
    -      return 'Request was aborted';
    -
    -    case goog.net.ErrorCode.TIMEOUT:
    -      return 'Request timed out';
    -
    -    case goog.net.ErrorCode.OFFLINE:
    -      return 'The resource is not available offline';
    -
    -    default:
    -      return 'Unrecognized error code';
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/net/eventtype.js b/src/database/third_party/closure-library/closure/goog/net/eventtype.js
    deleted file mode 100644
    index ac869792f27..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/eventtype.js
    +++ /dev/null
    @@ -1,37 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Common events for the network classes.
    - */
    -
    -
    -goog.provide('goog.net.EventType');
    -
    -
    -/**
    - * Event names for network events
    - * @enum {string}
    - */
    -goog.net.EventType = {
    -  COMPLETE: 'complete',
    -  SUCCESS: 'success',
    -  ERROR: 'error',
    -  ABORT: 'abort',
    -  READY: 'ready',
    -  READY_STATE_CHANGE: 'readystatechange',
    -  TIMEOUT: 'timeout',
    -  INCREMENTAL_DATA: 'incrementaldata',
    -  PROGRESS: 'progress'
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/net/filedownloader.js b/src/database/third_party/closure-library/closure/goog/net/filedownloader.js
    deleted file mode 100644
    index 699d6b8c195..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/filedownloader.js
    +++ /dev/null
    @@ -1,746 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A class for downloading remote files and storing them
    - * locally using the HTML5 FileSystem API.
    - *
    - * The directory structure is of the form /HASH/URL/BASENAME:
    - *
    - * The HASH portion is a three-character slice of the hash of the URL. Since the
    - * filesystem has a limit of about 5000 files per directory, this should divide
    - * the downloads roughly evenly among about 5000 directories, thus allowing for
    - * at most 5000^2 downloads.
    - *
    - * The URL portion is the (sanitized) full URL used for downloading the file.
    - * This is used to ensure that each file ends up in a different location, even
    - * if the HASH and BASENAME are the same.
    - *
    - * The BASENAME portion is the basename of the URL. It's used for the filename
    - * proper so that the local filesystem: URL will be downloaded to a file with a
    - * recognizable name.
    - *
    - */
    -
    -goog.provide('goog.net.FileDownloader');
    -goog.provide('goog.net.FileDownloader.Error');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.asserts');
    -goog.require('goog.async.Deferred');
    -goog.require('goog.crypt.hash32');
    -goog.require('goog.debug.Error');
    -goog.require('goog.events');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.fs');
    -goog.require('goog.fs.DirectoryEntry');
    -goog.require('goog.fs.Error');
    -goog.require('goog.fs.FileSaver');
    -goog.require('goog.net.EventType');
    -goog.require('goog.net.XhrIo');
    -goog.require('goog.net.XhrIoPool');
    -goog.require('goog.object');
    -
    -
    -
    -/**
    - * A class for downloading remote files and storing them locally using the
    - * HTML5 filesystem API.
    - *
    - * @param {!goog.fs.DirectoryEntry} dir The directory in which the downloaded
    - *     files are stored. This directory should be solely managed by
    - *     FileDownloader.
    - * @param {goog.net.XhrIoPool=} opt_pool The pool of XhrIo objects to use for
    - *     downloading files.
    - * @constructor
    - * @extends {goog.Disposable}
    - * @final
    - */
    -goog.net.FileDownloader = function(dir, opt_pool) {
    -  goog.net.FileDownloader.base(this, 'constructor');
    -
    -  /**
    -   * The directory in which the downloaded files are stored.
    -   * @type {!goog.fs.DirectoryEntry}
    -   * @private
    -   */
    -  this.dir_ = dir;
    -
    -  /**
    -   * The pool of XHRs to use for capturing.
    -   * @type {!goog.net.XhrIoPool}
    -   * @private
    -   */
    -  this.pool_ = opt_pool || new goog.net.XhrIoPool();
    -
    -  /**
    -   * A map from URLs to active downloads running for those URLs.
    -   * @type {!Object<!goog.net.FileDownloader.Download_>}
    -   * @private
    -   */
    -  this.downloads_ = {};
    -
    -  /**
    -   * The handler for URL capturing events.
    -   * @type {!goog.events.EventHandler<!goog.net.FileDownloader>}
    -   * @private
    -   */
    -  this.eventHandler_ = new goog.events.EventHandler(this);
    -};
    -goog.inherits(goog.net.FileDownloader, goog.Disposable);
    -
    -
    -/**
    - * Download a remote file and save its contents to the filesystem. A given file
    - * is uniquely identified by its URL string; this means that the relative and
    - * absolute URLs for a single file are considered different for the purposes of
    - * the FileDownloader.
    - *
    - * Returns a Deferred that will contain the downloaded blob. If there's an error
    - * while downloading the URL, this Deferred will be passed the
    - * {@link goog.net.FileDownloader.Error} object as an errback.
    - *
    - * If a download is already in progress for the given URL, this will return the
    - * deferred blob for that download. If the URL has already been downloaded, this
    - * will fail once it tries to save the downloaded blob.
    - *
    - * When a download is in progress, all Deferreds returned for that download will
    - * be branches of a single parent. If all such branches are cancelled, or if one
    - * is cancelled with opt_deepCancel set, then the download will be cancelled as
    - * well.
    - *
    - * @param {string} url The URL of the file to download.
    - * @return {!goog.async.Deferred} The deferred result blob.
    - */
    -goog.net.FileDownloader.prototype.download = function(url) {
    -  if (this.isDownloading(url)) {
    -    return this.downloads_[url].deferred.branch(true /* opt_propagateCancel */);
    -  }
    -
    -  var download = new goog.net.FileDownloader.Download_(url, this);
    -  this.downloads_[url] = download;
    -  this.pool_.getObject(goog.bind(this.gotXhr_, this, download));
    -  return download.deferred.branch(true /* opt_propagateCancel */);
    -};
    -
    -
    -/**
    - * Return a Deferred that will fire once no download is active for a given URL.
    - * If there's no download active for that URL when this is called, the deferred
    - * will fire immediately; otherwise, it will fire once the download is complete,
    - * whether or not it succeeds.
    - *
    - * @param {string} url The URL of the download to wait for.
    - * @return {!goog.async.Deferred} The Deferred that will fire when the download
    - *     is complete.
    - */
    -goog.net.FileDownloader.prototype.waitForDownload = function(url) {
    -  var deferred = new goog.async.Deferred();
    -  if (this.isDownloading(url)) {
    -    this.downloads_[url].deferred.addBoth(function() {
    -      deferred.callback(null);
    -    }, this);
    -  } else {
    -    deferred.callback(null);
    -  }
    -  return deferred;
    -};
    -
    -
    -/**
    - * Returns whether or not there is an active download for a given URL.
    - *
    - * @param {string} url The URL of the download to check.
    - * @return {boolean} Whether or not there is an active download for the URL.
    - */
    -goog.net.FileDownloader.prototype.isDownloading = function(url) {
    -  return url in this.downloads_;
    -};
    -
    -
    -/**
    - * Load a downloaded blob from the filesystem. Will fire a deferred error if the
    - * given URL has not yet been downloaded.
    - *
    - * @param {string} url The URL of the blob to load.
    - * @return {!goog.async.Deferred} The deferred Blob object. The callback will be
    - *     passed the blob. If a file API error occurs while loading the blob, that
    - *     error will be passed to the errback.
    - */
    -goog.net.FileDownloader.prototype.getDownloadedBlob = function(url) {
    -  return this.getFile_(url).
    -      addCallback(function(fileEntry) { return fileEntry.file(); });
    -};
    -
    -
    -/**
    - * Get the local filesystem: URL for a downloaded file. This is different from
    - * the blob: URL that's available from getDownloadedBlob(). If the end user
    - * accesses the filesystem: URL, the resulting file's name will be determined by
    - * the download filename as opposed to an arbitrary GUID. In addition, the
    - * filesystem: URL is connected to a filesystem location, so if the download is
    - * removed then that URL will become invalid.
    - *
    - * Warning: in Chrome 12, some filesystem: URLs are opened inline. This means
    - * that e.g. HTML pages given to the user via filesystem: URLs will be opened
    - * and processed by the browser.
    - *
    - * @param {string} url The URL of the file to get the URL of.
    - * @return {!goog.async.Deferred} The deferred filesystem: URL. The callback
    - *     will be passed the URL. If a file API error occurs while loading the
    - *     blob, that error will be passed to the errback.
    - */
    -goog.net.FileDownloader.prototype.getLocalUrl = function(url) {
    -  return this.getFile_(url).
    -      addCallback(function(fileEntry) { return fileEntry.toUrl(); });
    -};
    -
    -
    -/**
    - * Return (deferred) whether or not a URL has been downloaded. Will fire a
    - * deferred error if something goes wrong when determining this.
    - *
    - * @param {string} url The URL to check.
    - * @return {!goog.async.Deferred} The deferred boolean. The callback will be
    - *     passed the boolean. If a file API error occurs while checking the
    - *     existence of the downloaded URL, that error will be passed to the
    - *     errback.
    - */
    -goog.net.FileDownloader.prototype.isDownloaded = function(url) {
    -  var deferred = new goog.async.Deferred();
    -  var blobDeferred = this.getDownloadedBlob(url);
    -  blobDeferred.addCallback(function() {
    -    deferred.callback(true);
    -  });
    -  blobDeferred.addErrback(function(err) {
    -    if (err.code == goog.fs.Error.ErrorCode.NOT_FOUND) {
    -      deferred.callback(false);
    -    } else {
    -      deferred.errback(err);
    -    }
    -  });
    -  return deferred;
    -};
    -
    -
    -/**
    - * Remove a URL from the FileDownloader.
    - *
    - * This returns a Deferred. If the removal is completed successfully, its
    - * callback will be called without any value. If the removal fails, its errback
    - * will be called with the {@link goog.fs.Error}.
    - *
    - * @param {string} url The URL to remove.
    - * @return {!goog.async.Deferred} The deferred used for registering callbacks on
    - *     success or on error.
    - */
    -goog.net.FileDownloader.prototype.remove = function(url) {
    -  return this.getDir_(url, goog.fs.DirectoryEntry.Behavior.DEFAULT).
    -      addCallback(function(dir) { return dir.removeRecursively(); });
    -};
    -
    -
    -/**
    - * Save a blob for a given URL. This works just as through the blob were
    - * downloaded form that URL, except you specify the blob and no HTTP request is
    - * made.
    - *
    - * If the URL is currently being downloaded, it's indeterminate whether the blob
    - * being set or the blob being downloaded will end up in the filesystem.
    - * Whichever one doesn't get saved will have an error. To ensure that one or the
    - * other takes precedence, use {@link #waitForDownload} to allow the download to
    - * complete before setting the blob.
    - *
    - * @param {string} url The URL at which to set the blob.
    - * @param {!Blob} blob The blob to set.
    - * @param {string=} opt_name The name of the file. If this isn't given, it's
    - *     determined from the URL.
    - * @return {!goog.async.Deferred} The deferred used for registering callbacks on
    - *     success or on error. This can be cancelled just like a {@link #download}
    - *     Deferred. The objects passed to the errback will be
    - *     {@link goog.net.FileDownloader.Error}s.
    - */
    -goog.net.FileDownloader.prototype.setBlob = function(url, blob, opt_name) {
    -  var name = this.sanitize_(opt_name || this.urlToName_(url));
    -  var download = new goog.net.FileDownloader.Download_(url, this);
    -  this.downloads_[url] = download;
    -  download.blob = blob;
    -  this.getDir_(download.url, goog.fs.DirectoryEntry.Behavior.CREATE_EXCLUSIVE).
    -      addCallback(function(dir) {
    -        return dir.getFile(
    -            name, goog.fs.DirectoryEntry.Behavior.CREATE_EXCLUSIVE);
    -      }).
    -      addCallback(goog.bind(this.fileSuccess_, this, download)).
    -      addErrback(goog.bind(this.error_, this, download));
    -  return download.deferred.branch(true /* opt_propagateCancel */);
    -};
    -
    -
    -/**
    - * The callback called when an XHR becomes available from the XHR pool.
    - *
    - * @param {!goog.net.FileDownloader.Download_} download The download object for
    - *     this download.
    - * @param {!goog.net.XhrIo} xhr The XhrIo object for downloading the page.
    - * @private
    - */
    -goog.net.FileDownloader.prototype.gotXhr_ = function(download, xhr) {
    -  if (download.cancelled) {
    -    this.freeXhr_(xhr);
    -    return;
    -  }
    -
    -  this.eventHandler_.listen(
    -      xhr, goog.net.EventType.SUCCESS,
    -      goog.bind(this.xhrSuccess_, this, download));
    -  this.eventHandler_.listen(
    -      xhr, [goog.net.EventType.ERROR, goog.net.EventType.ABORT],
    -      goog.bind(this.error_, this, download));
    -  this.eventHandler_.listen(
    -      xhr, goog.net.EventType.READY,
    -      goog.bind(this.freeXhr_, this, xhr));
    -
    -  download.xhr = xhr;
    -  xhr.setResponseType(goog.net.XhrIo.ResponseType.ARRAY_BUFFER);
    -  xhr.send(download.url);
    -};
    -
    -
    -/**
    - * The callback called when an XHR succeeds in downloading a remote file.
    - *
    - * @param {!goog.net.FileDownloader.Download_} download The download object for
    - *     this download.
    - * @private
    - */
    -goog.net.FileDownloader.prototype.xhrSuccess_ = function(download) {
    -  if (download.cancelled) {
    -    return;
    -  }
    -
    -  var name = this.sanitize_(this.getName_(
    -      /** @type {!goog.net.XhrIo} */ (download.xhr)));
    -  var resp = /** @type {ArrayBuffer} */ (download.xhr.getResponse());
    -  if (!resp) {
    -    // This should never happen - it indicates the XHR hasn't completed, has
    -    // failed or has been cleaned up.  If it does happen (eg. due to a bug
    -    // somewhere) we don't want to pass null to getBlob - it's not valid and
    -    // triggers a bug in some versions of WebKit causing it to crash.
    -    this.error_(download);
    -    return;
    -  }
    -
    -  download.blob = goog.fs.getBlob(resp);
    -  delete download.xhr;
    -
    -  this.getDir_(download.url, goog.fs.DirectoryEntry.Behavior.CREATE_EXCLUSIVE).
    -      addCallback(function(dir) {
    -        return dir.getFile(
    -            name, goog.fs.DirectoryEntry.Behavior.CREATE_EXCLUSIVE);
    -      }).
    -      addCallback(goog.bind(this.fileSuccess_, this, download)).
    -      addErrback(goog.bind(this.error_, this, download));
    -};
    -
    -
    -/**
    - * The callback called when a file that will be used for saving a file is
    - * successfully opened.
    - *
    - * @param {!goog.net.FileDownloader.Download_} download The download object for
    - *     this download.
    - * @param {!goog.fs.FileEntry} file The newly-opened file object.
    - * @private
    - */
    -goog.net.FileDownloader.prototype.fileSuccess_ = function(download, file) {
    -  if (download.cancelled) {
    -    file.remove();
    -    return;
    -  }
    -
    -  download.file = file;
    -  file.createWriter().
    -      addCallback(goog.bind(this.fileWriterSuccess_, this, download)).
    -      addErrback(goog.bind(this.error_, this, download));
    -};
    -
    -
    -/**
    - * The callback called when a file writer is succesfully created for writing a
    - * file to the filesystem.
    - *
    - * @param {!goog.net.FileDownloader.Download_} download The download object for
    - *     this download.
    - * @param {!goog.fs.FileWriter} writer The newly-created file writer object.
    - * @private
    - */
    -goog.net.FileDownloader.prototype.fileWriterSuccess_ = function(
    -    download, writer) {
    -  if (download.cancelled) {
    -    download.file.remove();
    -    return;
    -  }
    -
    -  download.writer = writer;
    -  writer.write(/** @type {!Blob} */ (download.blob));
    -  this.eventHandler_.listenOnce(
    -      writer,
    -      goog.fs.FileSaver.EventType.WRITE_END,
    -      goog.bind(this.writeEnd_, this, download));
    -};
    -
    -
    -/**
    - * The callback called when file writing ends, whether or not it's successful.
    - *
    - * @param {!goog.net.FileDownloader.Download_} download The download object for
    - *     this download.
    - * @private
    - */
    -goog.net.FileDownloader.prototype.writeEnd_ = function(download) {
    -  if (download.cancelled || download.writer.getError()) {
    -    this.error_(download, download.writer.getError());
    -    return;
    -  }
    -
    -  delete this.downloads_[download.url];
    -  download.deferred.callback(download.blob);
    -};
    -
    -
    -/**
    - * The error callback for all asynchronous operations. Ensures that all stages
    - * of a given download are cleaned up, and emits the error event.
    - *
    - * @param {!goog.net.FileDownloader.Download_} download The download object for
    - *     this download.
    - * @param {goog.fs.Error=} opt_err The file error object. Only defined if the
    - *     error was raised by the file API.
    - * @private
    - */
    -goog.net.FileDownloader.prototype.error_ = function(download, opt_err) {
    -  if (download.file) {
    -    download.file.remove();
    -  }
    -
    -  if (download.cancelled) {
    -    return;
    -  }
    -
    -  delete this.downloads_[download.url];
    -  download.deferred.errback(
    -      new goog.net.FileDownloader.Error(download, opt_err));
    -};
    -
    -
    -/**
    - * Abort the download of the given URL.
    - *
    - * @param {!goog.net.FileDownloader.Download_} download The download to abort.
    - * @private
    - */
    -goog.net.FileDownloader.prototype.cancel_ = function(download) {
    -  goog.dispose(download);
    -  delete this.downloads_[download.url];
    -};
    -
    -
    -/**
    - * Get the directory for a given URL. If the directory already exists when this
    - * is called, it will contain exactly one file: the downloaded file.
    - *
    - * This not only calls the FileSystem API's getFile method, but attempts to
    - * distribute the files so that they don't overload the filesystem. The spec
    - * says directories can't contain more than 5000 files
    - * (http://www.w3.org/TR/file-system-api/#directories), so this ensures that
    - * each file is put into a subdirectory based on its SHA1 hash.
    - *
    - * All parameters are the same as in the FileSystem API's Entry#getFile method.
    - *
    - * @param {string} url The URL corresponding to the directory to get.
    - * @param {goog.fs.DirectoryEntry.Behavior} behavior The behavior to pass to the
    - *     underlying method.
    - * @return {!goog.async.Deferred} The deferred DirectoryEntry object.
    - * @private
    - */
    -goog.net.FileDownloader.prototype.getDir_ = function(url, behavior) {
    -  // 3 hex digits provide 16**3 = 4096 different possible dirnames, which is
    -  // less than the maximum of 5000 entries. Downloaded files should be
    -  // distributed roughly evenly throughout the directories due to the hash
    -  // function, allowing many more than 5000 files to be downloaded.
    -  //
    -  // The leading ` ensures that no illegal dirnames are accidentally used. % was
    -  // previously used, but Chrome has a bug (as of 12.0.725.0 dev) where
    -  // filenames are URL-decoded before checking their validity, so filenames
    -  // containing e.g. '%3f' (the URL-encoding of :, an invalid character) are
    -  // rejected.
    -  var dirname = '`' + Math.abs(goog.crypt.hash32.encodeString(url)).
    -      toString(16).substring(0, 3);
    -
    -  return this.dir_.
    -      getDirectory(dirname, goog.fs.DirectoryEntry.Behavior.CREATE).
    -      addCallback(function(dir) {
    -        return dir.getDirectory(this.sanitize_(url), behavior);
    -      }, this);
    -};
    -
    -
    -/**
    - * Get the file for a given URL. This will only retrieve files that have already
    - * been saved; it shouldn't be used for creating the file in the first place.
    - * This is because the filename isn't necessarily determined by the URL, but by
    - * the headers of the XHR response.
    - *
    - * @param {string} url The URL corresponding to the file to get.
    - * @return {!goog.async.Deferred} The deferred FileEntry object.
    - * @private
    - */
    -goog.net.FileDownloader.prototype.getFile_ = function(url) {
    -  return this.getDir_(url, goog.fs.DirectoryEntry.Behavior.DEFAULT).
    -      addCallback(function(dir) {
    -        return dir.listDirectory().addCallback(function(files) {
    -          goog.asserts.assert(files.length == 1);
    -          // If the filesystem somehow gets corrupted and we end up with an
    -          // empty directory here, it makes sense to just return the normal
    -          // file-not-found error.
    -          return files[0] || dir.getFile('file');
    -        });
    -      });
    -};
    -
    -
    -/**
    - * Sanitize a string so it can be safely used as a file or directory name for
    - * the FileSystem API.
    - *
    - * @param {string} str The string to sanitize.
    - * @return {string} The sanitized string.
    - * @private
    - */
    -goog.net.FileDownloader.prototype.sanitize_ = function(str) {
    -  // Add a prefix, since certain prefixes are disallowed for paths. None of the
    -  // disallowed prefixes start with '`'. We use ` rather than % for escaping the
    -  // filename due to a Chrome bug (as of 12.0.725.0 dev) where filenames are
    -  // URL-decoded before checking their validity, so filenames containing e.g.
    -  // '%3f' (the URL-encoding of :, an invalid character) are rejected.
    -  return '`' + str.replace(/[\/\\<>:?*"|%`]/g, encodeURIComponent).
    -      replace(/%/g, '`');
    -};
    -
    -
    -/**
    - * Gets the filename specified by the XHR. This first attempts to parse the
    - * Content-Disposition header for a filename and, failing that, falls back on
    - * deriving the filename from the URL.
    - *
    - * @param {!goog.net.XhrIo} xhr The XHR containing the response headers.
    - * @return {string} The filename.
    - * @private
    - */
    -goog.net.FileDownloader.prototype.getName_ = function(xhr) {
    -  var disposition = xhr.getResponseHeader('Content-Disposition');
    -  var match = disposition &&
    -      disposition.match(/^attachment *; *filename="(.*)"$/i);
    -  if (match) {
    -    // The Content-Disposition header allows for arbitrary backslash-escaped
    -    // characters (usually " and \). We want to unescape them before using them
    -    // in the filename.
    -    return match[1].replace(/\\(.)/g, '$1');
    -  }
    -
    -  return this.urlToName_(xhr.getLastUri());
    -};
    -
    -
    -/**
    - * Extracts the basename from a URL.
    - *
    - * @param {string} url The URL.
    - * @return {string} The basename.
    - * @private
    - */
    -goog.net.FileDownloader.prototype.urlToName_ = function(url) {
    -  var segments = url.split('/');
    -  return segments[segments.length - 1];
    -};
    -
    -
    -/**
    - * Remove all event listeners for an XHR and release it back into the pool.
    - *
    - * @param {!goog.net.XhrIo} xhr The XHR to free.
    - * @private
    - */
    -goog.net.FileDownloader.prototype.freeXhr_ = function(xhr) {
    -  goog.events.removeAll(xhr);
    -  this.pool_.addFreeObject(xhr);
    -};
    -
    -
    -/** @override */
    -goog.net.FileDownloader.prototype.disposeInternal = function() {
    -  delete this.dir_;
    -  goog.dispose(this.eventHandler_);
    -  delete this.eventHandler_;
    -  goog.object.forEach(this.downloads_, function(download) {
    -    download.deferred.cancel();
    -  }, this);
    -  delete this.downloads_;
    -  goog.dispose(this.pool_);
    -  delete this.pool_;
    -
    -  goog.net.FileDownloader.base(this, 'disposeInternal');
    -};
    -
    -
    -
    -/**
    - * The error object for FileDownloader download errors.
    - *
    - * @param {!goog.net.FileDownloader.Download_} download The download object for
    - *     the download in question.
    - * @param {goog.fs.Error=} opt_fsErr The file error object, if this was a file
    - *     error.
    - *
    - * @constructor
    - * @extends {goog.debug.Error}
    - * @final
    - */
    -goog.net.FileDownloader.Error = function(download, opt_fsErr) {
    -  goog.net.FileDownloader.Error.base(
    -      this, 'constructor', 'Error capturing URL ' + download.url);
    -
    -  /**
    -   * The URL the event relates to.
    -   * @type {string}
    -   */
    -  this.url = download.url;
    -
    -  if (download.xhr) {
    -    this.xhrStatus = download.xhr.getStatus();
    -    this.xhrErrorCode = download.xhr.getLastErrorCode();
    -    this.message += ': XHR failed with status ' + this.xhrStatus +
    -        ' (error code ' + this.xhrErrorCode + ')';
    -  } else if (opt_fsErr) {
    -    this.fileError = opt_fsErr;
    -    this.message += ': file API failed (' + opt_fsErr.message + ')';
    -  }
    -};
    -goog.inherits(goog.net.FileDownloader.Error, goog.debug.Error);
    -
    -
    -/**
    - * The status of the XHR. Only set if the error was caused by an XHR failure.
    - * @type {number|undefined}
    - */
    -goog.net.FileDownloader.Error.prototype.xhrStatus;
    -
    -
    -/**
    - * The error code of the XHR. Only set if the error was caused by an XHR
    - * failure.
    - * @type {goog.net.ErrorCode|undefined}
    - */
    -goog.net.FileDownloader.Error.prototype.xhrErrorCode;
    -
    -
    -/**
    - * The file API error. Only set if the error was caused by the file API.
    - * @type {goog.fs.Error|undefined}
    - */
    -goog.net.FileDownloader.Error.prototype.fileError;
    -
    -
    -
    -/**
    - * A struct containing the data for a single download.
    - *
    - * @param {string} url The URL for the file being downloaded.
    - * @param {!goog.net.FileDownloader} downloader The parent FileDownloader.
    - * @extends {goog.Disposable}
    - * @constructor
    - * @private
    - */
    -goog.net.FileDownloader.Download_ = function(url, downloader) {
    -  goog.net.FileDownloader.Download_.base(this, 'constructor');
    -
    -  /**
    -   * The URL for the file being downloaded.
    -   * @type {string}
    -   */
    -  this.url = url;
    -
    -  /**
    -   * The Deferred that will be fired when the download is complete.
    -   * @type {!goog.async.Deferred}
    -   */
    -  this.deferred = new goog.async.Deferred(
    -      goog.bind(downloader.cancel_, downloader, this));
    -
    -  /**
    -   * Whether this download has been cancelled by the user.
    -   * @type {boolean}
    -   */
    -  this.cancelled = false;
    -
    -  /**
    -   * The XhrIo object for downloading the file. Only set once it's been
    -   * retrieved from the pool.
    -   * @type {goog.net.XhrIo}
    -   */
    -  this.xhr = null;
    -
    -  /**
    -   * The name of the blob being downloaded. Only sey once the XHR has completed,
    -   * if it completed successfully.
    -   * @type {?string}
    -   */
    -  this.name = null;
    -
    -  /**
    -   * The downloaded blob. Only set once the XHR has completed, if it completed
    -   * successfully.
    -   * @type {Blob}
    -   */
    -  this.blob = null;
    -
    -  /**
    -   * The file entry where the blob is to be stored. Only set once it's been
    -   * loaded from the filesystem.
    -   * @type {goog.fs.FileEntry}
    -   */
    -  this.file = null;
    -
    -  /**
    -   * The file writer for writing the blob to the filesystem. Only set once it's
    -   * been loaded from the filesystem.
    -   * @type {goog.fs.FileWriter}
    -   */
    -  this.writer = null;
    -};
    -goog.inherits(goog.net.FileDownloader.Download_, goog.Disposable);
    -
    -
    -/** @override */
    -goog.net.FileDownloader.Download_.prototype.disposeInternal = function() {
    -  this.cancelled = true;
    -  if (this.xhr) {
    -    this.xhr.abort();
    -  } else if (this.writer && this.writer.getReadyState() ==
    -             goog.fs.FileSaver.ReadyState.WRITING) {
    -    this.writer.abort();
    -  }
    -
    -  goog.net.FileDownloader.Download_.base(this, 'disposeInternal');
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/net/filedownloader_test.html b/src/database/third_party/closure-library/closure/goog/net/filedownloader_test.html
    deleted file mode 100644
    index fa72f0c57a0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/filedownloader_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.net.FileDownloader
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.net.FileDownloaderTest')
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/filedownloader_test.js b/src/database/third_party/closure-library/closure/goog/net/filedownloader_test.js
    deleted file mode 100644
    index d92c1f3ee1c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/filedownloader_test.js
    +++ /dev/null
    @@ -1,371 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.net.FileDownloaderTest');
    -goog.setTestOnly('goog.net.FileDownloaderTest');
    -
    -goog.require('goog.fs.Error');
    -goog.require('goog.net.ErrorCode');
    -goog.require('goog.net.FileDownloader');
    -goog.require('goog.net.XhrIo');
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.fs');
    -goog.require('goog.testing.fs.FileSystem');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.net.XhrIoPool');
    -
    -var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall();
    -var xhrIoPool, xhr, fs, dir, downloader;
    -
    -function setUpPage() {
    -  goog.testing.fs.install(new goog.testing.PropertyReplacer());
    -}
    -
    -function setUp() {
    -  xhrIoPool = new goog.testing.net.XhrIoPool();
    -  xhr = xhrIoPool.getXhr();
    -  fs = new goog.testing.fs.FileSystem();
    -  dir = fs.getRoot();
    -  downloader = new goog.net.FileDownloader(dir, xhrIoPool);
    -}
    -
    -function tearDown() {
    -  goog.dispose(downloader);
    -}
    -
    -function testDownload() {
    -  downloader.download('/foo/bar').addCallback(function(blob) {
    -    var fileEntry = dir.getFileSync('`3fa/``2Ffoo`2Fbar/`bar');
    -    assertEquals('data', blob.toString());
    -    assertEquals('data', fileEntry.fileSync().toString());
    -    asyncTestCase.continueTesting();
    -  }).addErrback(function(err) { throw err; });
    -
    -  assertEquals('/foo/bar', xhr.getLastUri());
    -  assertEquals(goog.net.XhrIo.ResponseType.ARRAY_BUFFER, xhr.getResponseType());
    -
    -  xhr.simulateResponse(200, 'data');
    -  asyncTestCase.waitForAsync('testDownload');
    -}
    -
    -function testGetDownloadedBlob() {
    -  downloader.download('/foo/bar').
    -      addCallback(function() {
    -        return downloader.getDownloadedBlob('/foo/bar');
    -      }).
    -      addCallback(function(blob) { assertEquals('data', blob.toString()); }).
    -      addCallback(goog.bind(asyncTestCase.continueTesting, asyncTestCase)).
    -      addErrback(function(err) { throw err; });
    -
    -  xhr.simulateResponse(200, 'data');
    -  asyncTestCase.waitForAsync('testGetDownloadedBlob');
    -}
    -
    -function testGetLocalUrl() {
    -  downloader.download('/foo/bar').
    -      addCallback(function() { return downloader.getLocalUrl('/foo/bar'); }).
    -      addCallback(function(url) { assertMatches(/\/`bar$/, url); }).
    -      addCallback(goog.bind(asyncTestCase.continueTesting, asyncTestCase)).
    -      addErrback(function(err) { throw err; });
    -
    -  xhr.simulateResponse(200, 'data');
    -  asyncTestCase.waitForAsync('testGetLocalUrl');
    -}
    -
    -function testLocalUrlWithContentDisposition() {
    -  downloader.download('/foo/bar').
    -      addCallback(function() { return downloader.getLocalUrl('/foo/bar'); }).
    -      addCallback(function(url) { assertMatches(/\/`qux`22bap$/, url); }).
    -      addCallback(goog.bind(asyncTestCase.continueTesting, asyncTestCase)).
    -      addErrback(function(err) { throw err; });
    -
    -  xhr.simulateResponse(
    -      200, 'data', {'Content-Disposition': 'attachment; filename="qux\\"bap"'});
    -  asyncTestCase.waitForAsync('testGetLocalUrl');
    -}
    -
    -function testIsDownloaded() {
    -  downloader.download('/foo/bar').
    -      addCallback(function() { return downloader.isDownloaded('/foo/bar'); }).
    -      addCallback(assertTrue).
    -      addCallback(function() { return downloader.isDownloaded('/foo/baz'); }).
    -      addCallback(assertFalse).
    -      addCallback(goog.bind(asyncTestCase.continueTesting, asyncTestCase)).
    -      addErrback(function(err) { throw err; });
    -
    -  xhr.simulateResponse(200, 'data');
    -  asyncTestCase.waitForAsync('testIsDownloaded');
    -}
    -
    -function testRemove() {
    -  downloader.download('/foo/bar').
    -      addCallback(function() { return downloader.remove('/foo/bar'); }).
    -      addCallback(function() { return downloader.isDownloaded('/foo/bar'); }).
    -      addCallback(assertFalse).
    -      addCallback(function() {
    -        return downloader.getDownloadedBlob('/foo/bar');
    -      }).
    -      addErrback(function(err) {
    -        assertEquals(goog.fs.Error.ErrorCode.NOT_FOUND, err.code);
    -        var download = downloader.download('/foo/bar');
    -        xhr.simulateResponse(200, 'more data');
    -        return download;
    -      }).
    -      addCallback(function() { return downloader.isDownloaded('/foo/bar'); }).
    -      addCallback(assertTrue).
    -      addCallback(function() {
    -        return downloader.getDownloadedBlob('/foo/bar');
    -      }).
    -      addCallback(function(blob) {
    -        assertEquals('more data', blob.toString());
    -      }).
    -      addCallback(goog.bind(asyncTestCase.continueTesting, asyncTestCase));
    -
    -  xhr.simulateResponse(200, 'data');
    -  asyncTestCase.waitForAsync('testRemove');
    -}
    -
    -function testSetBlob() {
    -  downloader.setBlob('/foo/bar', goog.testing.fs.getBlob('data')).
    -      addCallback(function() { return downloader.isDownloaded('/foo/bar'); }).
    -      addCallback(assertTrue).
    -      addCallback(function() {
    -        return downloader.getDownloadedBlob('/foo/bar');
    -      }).
    -      addCallback(function(blob) {
    -        assertEquals('data', blob.toString());
    -      }).
    -      addCallback(goog.bind(asyncTestCase.continueTesting, asyncTestCase)).
    -      addErrback(function(err) { throw err; });
    -
    -  asyncTestCase.waitForAsync('testSetBlob');
    -}
    -
    -function testSetBlobWithName() {
    -  downloader.setBlob('/foo/bar', goog.testing.fs.getBlob('data'), 'qux').
    -      addCallback(function() { return downloader.getLocalUrl('/foo/bar'); }).
    -      addCallback(function(url) { assertMatches(/\/`qux$/, url); }).
    -      addCallback(goog.bind(asyncTestCase.continueTesting, asyncTestCase)).
    -      addErrback(function(err) { throw err; });
    -
    -  asyncTestCase.waitForAsync('testSetBlob');
    -}
    -
    -function testDownloadDuringDownload() {
    -  var download1 = downloader.download('/foo/bar');
    -  var download2 = downloader.download('/foo/bar');
    -
    -  download1.
    -      addCallback(function() { return download2; }).
    -      addCallback(function() {
    -        return downloader.getDownloadedBlob('/foo/bar');
    -      }).
    -      addCallback(function(blob) { assertEquals('data', blob.toString()); }).
    -      addCallback(goog.bind(asyncTestCase.continueTesting, asyncTestCase));
    -
    -  // There should only need to be one response for both downloads, since the
    -  // second should return the same deferred as the first.
    -  xhr.simulateResponse(200, 'data');
    -  asyncTestCase.waitForAsync('testDownloadeduringDownload');
    -}
    -
    -function testGetDownloadedBlobDuringDownload() {
    -  var download = downloader.download('/foo/bar');
    -  downloader.waitForDownload('/foo/bar').addCallback(function() {
    -    return downloader.getDownloadedBlob('/foo/bar');
    -  }).addCallback(function(blob) {
    -    assertTrue(download.hasFired());
    -    assertEquals('data', blob.toString());
    -    asyncTestCase.continueTesting();
    -  });
    -
    -  xhr.simulateResponse(200, 'data');
    -  asyncTestCase.waitForAsync('testGetDownloadedBlobDuringDownload');
    -}
    -
    -function testIsDownloadedDuringDownload() {
    -  var download = downloader.download('/foo/bar');
    -  downloader.waitForDownload('/foo/bar').addCallback(function() {
    -    return downloader.isDownloaded('/foo/bar');
    -  }).addCallback(function(isDownloaded) {
    -    assertTrue(download.hasFired());
    -    assertTrue(isDownloaded);
    -    asyncTestCase.continueTesting();
    -  });
    -
    -  xhr.simulateResponse(200, 'data');
    -  asyncTestCase.waitForAsync('testIsDownloadedDuringDownload');
    -}
    -
    -function testRemoveDuringDownload() {
    -  var download = downloader.download('/foo/bar');
    -  downloader.
    -      waitForDownload('/foo/bar').
    -      addCallback(function() { return downloader.remove('/foo/bar'); }).
    -      addCallback(function() { assertTrue(download.hasFired()); }).
    -      addCallback(function() { return downloader.isDownloaded('/foo/bar'); }).
    -      addCallback(assertFalse).
    -      addCallback(goog.bind(asyncTestCase.continueTesting, asyncTestCase));
    -
    -  xhr.simulateResponse(200, 'data');
    -  asyncTestCase.waitForAsync('testRemoveDuringDownload');
    -}
    -
    -function testSetBlobDuringDownload() {
    -  var download = downloader.download('/foo/bar');
    -  downloader.
    -      waitForDownload('/foo/bar').
    -      addCallback(function() {
    -        return downloader.setBlob(
    -            '/foo/bar', goog.testing.fs.getBlob('blob data'));
    -      }).
    -      addErrback(function(err) {
    -        assertEquals(
    -            goog.fs.Error.ErrorCode.INVALID_MODIFICATION, err.fileError.code);
    -        return download;
    -      }).
    -      addCallback(function() {
    -        return downloader.getDownloadedBlob('/foo/bar');
    -      }).
    -      addCallback(function(b) { assertEquals('xhr data', b.toString()); }).
    -      addCallback(goog.bind(asyncTestCase.continueTesting, asyncTestCase));
    -
    -  xhr.simulateResponse(200, 'xhr data');
    -  asyncTestCase.waitForAsync('testSetBlobDuringDownload');
    -}
    -
    -function testDownloadCancelledBeforeXhr() {
    -  var download = downloader.download('/foo/bar');
    -  download.cancel();
    -
    -  download.
    -      addErrback(function() {
    -    assertEquals('/foo/bar', xhr.getLastUri());
    -    assertEquals(goog.net.ErrorCode.ABORT, xhr.getLastErrorCode());
    -    assertFalse(xhr.isActive());
    -
    -    return downloader.isDownloaded('/foo/bar');
    -  }).
    -      addCallback(assertFalse).
    -      addCallback(goog.bind(asyncTestCase.continueTesting, asyncTestCase));
    -
    -  asyncTestCase.waitForAsync('testDownloadCancelledBeforeXhr');
    -}
    -
    -function testDownloadCancelledAfterXhr() {
    -  var download = downloader.download('/foo/bar');
    -  xhr.simulateResponse(200, 'data');
    -  download.cancel();
    -
    -  download.
    -      addErrback(function() {
    -    assertEquals('/foo/bar', xhr.getLastUri());
    -    assertEquals(goog.net.ErrorCode.NO_ERROR, xhr.getLastErrorCode());
    -    assertFalse(xhr.isActive());
    -
    -    return downloader.isDownloaded('/foo/bar');
    -  }).
    -      addCallback(assertFalse).
    -      addCallback(goog.bind(asyncTestCase.continueTesting, asyncTestCase));
    -
    -  asyncTestCase.waitForAsync('testDownloadCancelledAfterXhr');
    -}
    -
    -function testFailedXhr() {
    -  downloader.download('/foo/bar').
    -      addErrback(function(err) {
    -        assertEquals('/foo/bar', err.url);
    -        assertEquals(404, err.xhrStatus);
    -        assertEquals(goog.net.ErrorCode.HTTP_ERROR, err.xhrErrorCode);
    -        assertUndefined(err.fileError);
    -
    -        return downloader.isDownloaded('/foo/bar');
    -      }).
    -      addCallback(assertFalse).
    -      addCallback(goog.bind(asyncTestCase.continueTesting, asyncTestCase));
    -
    -  xhr.simulateResponse(404);
    -  asyncTestCase.waitForAsync('testFailedXhr');
    -}
    -
    -function testFailedDownloadSave() {
    -  downloader.download('/foo/bar').
    -      addCallback(function() {
    -        var download = downloader.download('/foo/bar');
    -        xhr.simulateResponse(200, 'data');
    -        return download;
    -      }).
    -      addErrback(function(err) {
    -        assertEquals('/foo/bar', err.url);
    -        assertUndefined(err.xhrStatus);
    -        assertUndefined(err.xhrErrorCode);
    -        assertEquals(
    -            goog.fs.Error.ErrorCode.INVALID_MODIFICATION, err.fileError.code);
    -
    -        asyncTestCase.continueTesting();
    -      });
    -
    -  xhr.simulateResponse(200, 'data');
    -  asyncTestCase.waitForAsync('testFailedDownloadSave');
    -}
    -
    -function testFailedGetDownloadedBlob() {
    -  downloader.getDownloadedBlob('/foo/bar').
    -      addErrback(function(err) {
    -        assertEquals(goog.fs.Error.ErrorCode.NOT_FOUND, err.code);
    -        asyncTestCase.continueTesting();
    -      });
    -
    -  asyncTestCase.waitForAsync('testFailedGetDownloadedBlob');
    -}
    -
    -function testFailedRemove() {
    -  downloader.remove('/foo/bar').
    -      addErrback(function(err) {
    -        assertEquals(goog.fs.Error.ErrorCode.NOT_FOUND, err.code);
    -        asyncTestCase.continueTesting();
    -      });
    -
    -  asyncTestCase.waitForAsync('testFailedRemove');
    -}
    -
    -function testIsDownloading() {
    -  assertFalse(downloader.isDownloading('/foo/bar'));
    -  downloader.download('/foo/bar').addCallback(function() {
    -    assertFalse(downloader.isDownloading('/foo/bar'));
    -    asyncTestCase.continueTesting();
    -  });
    -
    -  assertTrue(downloader.isDownloading('/foo/bar'));
    -
    -  xhr.simulateResponse(200, 'data');
    -  asyncTestCase.waitForAsync('testIsDownloading');
    -}
    -
    -function testIsDownloadingWhenCancelled() {
    -  assertFalse(downloader.isDownloading('/foo/bar'));
    -  var deferred = downloader.download('/foo/bar').addErrback(function() {
    -    assertFalse(downloader.isDownloading('/foo/bar'));
    -  });
    -
    -  assertTrue(downloader.isDownloading('/foo/bar'));
    -  deferred.cancel();
    -}
    -
    -function assertMatches(expected, actual) {
    -  assert(
    -      'Expected "' + actual + '" to match ' + expected,
    -      expected.test(actual));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/net/httpstatus.js b/src/database/third_party/closure-library/closure/goog/net/httpstatus.js
    deleted file mode 100644
    index a525c0fa4f2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/httpstatus.js
    +++ /dev/null
    @@ -1,116 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Constants for HTTP status codes.
    - */
    -
    -goog.provide('goog.net.HttpStatus');
    -
    -
    -/**
    - * HTTP Status Codes defined in RFC 2616 and RFC 6585.
    - * @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
    - * @see http://tools.ietf.org/html/rfc6585
    - * @enum {number}
    - */
    -goog.net.HttpStatus = {
    -  // Informational 1xx
    -  CONTINUE: 100,
    -  SWITCHING_PROTOCOLS: 101,
    -
    -  // Successful 2xx
    -  OK: 200,
    -  CREATED: 201,
    -  ACCEPTED: 202,
    -  NON_AUTHORITATIVE_INFORMATION: 203,
    -  NO_CONTENT: 204,
    -  RESET_CONTENT: 205,
    -  PARTIAL_CONTENT: 206,
    -
    -  // Redirection 3xx
    -  MULTIPLE_CHOICES: 300,
    -  MOVED_PERMANENTLY: 301,
    -  FOUND: 302,
    -  SEE_OTHER: 303,
    -  NOT_MODIFIED: 304,
    -  USE_PROXY: 305,
    -  TEMPORARY_REDIRECT: 307,
    -
    -  // Client Error 4xx
    -  BAD_REQUEST: 400,
    -  UNAUTHORIZED: 401,
    -  PAYMENT_REQUIRED: 402,
    -  FORBIDDEN: 403,
    -  NOT_FOUND: 404,
    -  METHOD_NOT_ALLOWED: 405,
    -  NOT_ACCEPTABLE: 406,
    -  PROXY_AUTHENTICATION_REQUIRED: 407,
    -  REQUEST_TIMEOUT: 408,
    -  CONFLICT: 409,
    -  GONE: 410,
    -  LENGTH_REQUIRED: 411,
    -  PRECONDITION_FAILED: 412,
    -  REQUEST_ENTITY_TOO_LARGE: 413,
    -  REQUEST_URI_TOO_LONG: 414,
    -  UNSUPPORTED_MEDIA_TYPE: 415,
    -  REQUEST_RANGE_NOT_SATISFIABLE: 416,
    -  EXPECTATION_FAILED: 417,
    -  PRECONDITION_REQUIRED: 428,
    -  TOO_MANY_REQUESTS: 429,
    -  REQUEST_HEADER_FIELDS_TOO_LARGE: 431,
    -
    -  // Server Error 5xx
    -  INTERNAL_SERVER_ERROR: 500,
    -  NOT_IMPLEMENTED: 501,
    -  BAD_GATEWAY: 502,
    -  SERVICE_UNAVAILABLE: 503,
    -  GATEWAY_TIMEOUT: 504,
    -  HTTP_VERSION_NOT_SUPPORTED: 505,
    -  NETWORK_AUTHENTICATION_REQUIRED: 511,
    -
    -  /*
    -   * IE returns this code for 204 due to its use of URLMon, which returns this
    -   * code for 'Operation Aborted'. The status text is 'Unknown', the response
    -   * headers are ''. Known to occur on IE 6 on XP through IE9 on Win7.
    -   */
    -  QUIRK_IE_NO_CONTENT: 1223
    -};
    -
    -
    -/**
    - * Returns whether the given status should be considered successful.
    - *
    - * Successful codes are OK (200), CREATED (201), ACCEPTED (202),
    - * NO CONTENT (204), PARTIAL CONTENT (206), NOT MODIFIED (304),
    - * and IE's no content code (1223).
    - *
    - * @param {number} status The status code to test.
    - * @return {boolean} Whether the status code should be considered successful.
    - */
    -goog.net.HttpStatus.isSuccess = function(status) {
    -  switch (status) {
    -    case goog.net.HttpStatus.OK:
    -    case goog.net.HttpStatus.CREATED:
    -    case goog.net.HttpStatus.ACCEPTED:
    -    case goog.net.HttpStatus.NO_CONTENT:
    -    case goog.net.HttpStatus.PARTIAL_CONTENT:
    -    case goog.net.HttpStatus.NOT_MODIFIED:
    -    case goog.net.HttpStatus.QUIRK_IE_NO_CONTENT:
    -      return true;
    -
    -    default:
    -      return false;
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/net/iframe_xhr_test.html b/src/database/third_party/closure-library/closure/goog/net/iframe_xhr_test.html
    deleted file mode 100644
    index b54a22a576e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/iframe_xhr_test.html
    +++ /dev/null
    @@ -1,36 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - Iframe/XHR Execution Context
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -  goog.require('goog.net.iframeXhrTest');
    -  </script>
    - </head>
    - <body>
    -  <p>
    -   XmlHttpRequests that initiate from code executed in an iframe, that is then
    -    destroyed, result in an error in FireFox.  This test case is used to verify
    -    that Closure's IframeIo and XhrLite do not suffer from this problem.  See
    -   <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=369939">
    -    https://bugzilla.mozilla.org/show_bug.cgi?id=369939
    -   </a>
    -   .
    -  </p>
    -  <p>
    -   NOTE(pupius): 14/11/2011 The XhrMonitor code has been removed since the
    -    above bug doesn't manifest in any currently supported versions.  This test
    -    is left in place as a way of verifying the problem doesn't resurface.
    -  </p>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/iframe_xhr_test.js b/src/database/third_party/closure-library/closure/goog/net/iframe_xhr_test.js
    deleted file mode 100644
    index 7318ea7a970..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/iframe_xhr_test.js
    +++ /dev/null
    @@ -1,144 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.net.iframeXhrTest');
    -goog.setTestOnly('goog.net.iframeXhrTest');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.debug.Console');
    -goog.require('goog.debug.LogManager');
    -goog.require('goog.debug.Logger');
    -goog.require('goog.events');
    -goog.require('goog.net.IframeIo');
    -goog.require('goog.net.XhrIo');
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -var c = new goog.debug.Console;
    -c.setCapturing(true);
    -goog.debug.LogManager.getRoot().setLevel(goog.debug.Logger.Level.ALL);
    -
    -// Can't use exportSymbol if we want JsUnit support
    -top.GG_iframeFn = goog.net.IframeIo.handleIncrementalData;
    -
    -// Make the dispose time short enough that it will cause the bug to appear
    -goog.net.IframeIo.IFRAME_DISPOSE_DELAY_MS = 0;
    -
    -
    -var fileName = 'iframe_xhr_test_response.html';
    -var iframeio;
    -
    -// Create an async test case
    -var testCase = new goog.testing.AsyncTestCase(document.title);
    -testCase.stepTimeout = 4 * 1000;
    -testCase.resultCount = 0;
    -testCase.xhrCount = 0;
    -testCase.error = null;
    -
    -
    -/**
    - * Set up the iframe io and request the test response page.
    - * @this {goog.testing.AsyncTestCase}
    - */
    -testCase.setUpPage = function() {
    -  testCase.waitForAsync('setUpPage');
    -  iframeio = new goog.net.IframeIo();
    -  goog.events.listen(
    -      iframeio, 'incrementaldata', this.onIframeData, false, this);
    -  goog.events.listen(
    -      iframeio, 'ready', this.onIframeReady, false, this);
    -  iframeio.send(fileName);
    -};
    -
    -
    -/** Disposes the iframe object. */
    -testCase.tearDownPage = function() {
    -  iframeio.dispose();
    -};
    -
    -
    -/**
    - * Handles the packets received  from the Iframe incremental results.
    - * @this {goog.testing.AsyncTestCase}
    - */
    -testCase.onIframeData = function(e) {
    -  this.log('Data received  : ' + e.data);
    -  this.resultCount++;
    -  goog.net.XhrIo.send(fileName, goog.bind(this.onXhrData, this));
    -};
    -
    -
    -/**
    - * Handles the iframe becoming ready.
    - * @this {goog.testing.AsyncTestCase}
    - */
    -testCase.onIframeReady = function(e) {
    -  this.log('Iframe ready');
    -  var me = this;
    -  goog.net.XhrIo.send(fileName, goog.bind(this.onXhrData, this));
    -};
    -
    -
    -/**
    - * Handles the response from an Xhr request.
    - * @this {goog.testing.AsyncTestCase}
    - */
    -testCase.onXhrData = function(e) {
    -  this.xhrCount++;
    -  // We access status directly so that XhrLite doesn't mask the error that
    -  // would be thrown in FF if this worked correctly.
    -  try {
    -    this.log('Xhr Received: ' + e.target.xhr_.status);
    -  } catch (e) {
    -    this.log('ERROR: ' + e.message);
    -    this.error = e;
    -  }
    -  if (this.xhrCount == 4 && this.resultCount == 3) {
    -    // Wait for the async iframe disposal to fire.
    -    this.log('Test set up finished, waiting 500ms for iframe disposal');
    -    goog.Timer.callOnce(goog.bind(this.continueTesting, this), 0);
    -  }
    -};
    -
    -
    -/** The main test function that validates the results were as expected. */
    -testCase.addNewTest('testResults', function() {
    -  assertEquals('There should be 3 data packets', 3, this.resultCount);
    -  // 3 results + 1 ready
    -  assertEquals('There should be 4 XHR results', 4, this.xhrCount);
    -  if (this.error) {
    -    throw this.error;
    -  }
    -
    -  assertEquals('There should be no iframes left', 0,
    -      document.getElementsByTagName('iframe').length);
    -});
    -
    -
    -/** This test only runs on GECKO browsers. */
    -if (goog.userAgent.GECKO) {
    -  /** Used by the JsUnit test runner. */
    -  var testXhrMonitorWorksForIframeIoRequests = function() {
    -    testCase.reset();
    -    testCase.cycleTests();
    -  };
    -}
    -
    -// Standalone Closure Test Runner.
    -if (goog.userAgent.GECKO) {
    -  G_testRunner.initialize(testCase);
    -} else {
    -  G_testRunner.setStrict(false);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/net/iframe_xhr_test_response.html b/src/database/third_party/closure-library/closure/goog/net/iframe_xhr_test_response.html
    deleted file mode 100644
    index 3dafbefb20e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/iframe_xhr_test_response.html
    +++ /dev/null
    @@ -1,17 +0,0 @@
    -<html>
    -<!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -  <head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    -  </head>
    -  <body>
    -    <script>top.GG_iframeFn(window, [1, 1, 2, 4, 8]);</script>
    -    <script>top.GG_iframeFn(window, [12, 20, 32, 52, 84]);</script>
    -    <script>top.GG_iframeFn(window, [136, 220, 356, 576, 932]);</script>
    -  </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/iframeio.js b/src/database/third_party/closure-library/closure/goog/net/iframeio.js
    deleted file mode 100644
    index 4e020cb8521..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/iframeio.js
    +++ /dev/null
    @@ -1,1363 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Class for managing requests via iFrames.  Supports a number of
    - * methods of transfer.
    - *
    - * Gets and Posts can be performed and the resultant page read in as text,
    - * JSON, or from the HTML DOM.
    - *
    - * Using an iframe causes the throbber to spin, this is good for providing
    - * feedback to the user that an action has occurred.
    - *
    - * Requests do not affect the history stack, see goog.History if you require
    - * this behavior.
    - *
    - * The responseText and responseJson methods assume the response is plain,
    - * text.  You can access the Iframe's DOM through responseXml if you need
    - * access to the raw HTML.
    - *
    - * Tested:
    - *    + FF2.0 (Win Linux)
    - *    + IE6, IE7
    - *    + Opera 9.1,
    - *    + Chrome
    - *    - Opera 8.5 fails because of no textContent and buggy innerText support
    - *
    - * NOTE: Safari doesn't fire the onload handler when loading plain text files
    - *
    - * This has been tested with Drip in IE to ensure memory usage is as constant
    - * as possible. When making making thousands of requests, memory usage stays
    - * constant for a while but then starts increasing (<500k for 2000
    - * requests) -- this hasn't yet been tracked down yet, though it is cleared up
    - * after a refresh.
    - *
    - *
    - * BACKGROUND FILE UPLOAD:
    - * By posting an arbitrary form through an IframeIo object, it is possible to
    - * implement background file uploads.  Here's how to do it:
    - *
    - * - Create a form:
    - *   <pre>
    - *   &lt;form id="form" enctype="multipart/form-data" method="POST"&gt;
    - *      &lt;input name="userfile" type="file" /&gt;
    - *   &lt;/form&gt;
    - *   </pre>
    - *
    - * - Have the user click the file input
    - * - Create an IframeIo instance
    - *   <pre>
    - *   var io = new goog.net.IframeIo;
    - *   goog.events.listen(io, goog.net.EventType.COMPLETE,
    - *       function() { alert('Sent'); });
    - *   io.sendFromForm(document.getElementById('form'));
    - *   </pre>
    - *
    - *
    - * INCREMENTAL LOADING:
    - * Gmail sends down multiple script blocks which get executed as they are
    - * received by the client. This allows incremental rendering of the thread
    - * list and conversations.
    - *
    - * This requires collaboration with the server that is sending the requested
    - * page back.  To set incremental loading up, you should:
    - *
    - * A) In the application code there should be an externed reference to
    - * <code>handleIncrementalData()</code>.  e.g.
    - * goog.exportSymbol('GG_iframeFn', goog.net.IframeIo.handleIncrementalData);
    - *
    - * B) The response page should them call this method directly, an example
    - * response would look something like this:
    - * <pre>
    - *   &lt;html&gt;
    - *   &lt;head&gt;
    - *     &lt;meta content="text/html;charset=UTF-8" http-equiv="content-type"&gt;
    - *   &lt;/head&gt;
    - *   &lt;body&gt;
    - *     &lt;script&gt;
    - *       D = top.P ? function(d) { top.GG_iframeFn(window, d) } : function() {};
    - *     &lt;/script&gt;
    - *
    - *     &lt;script&gt;D([1, 2, 3, 4, 5]);&lt;/script&gt;
    - *     &lt;script&gt;D([6, 7, 8, 9, 10]);&lt;/script&gt;
    - *     &lt;script&gt;D([11, 12, 13, 14, 15]);&lt;/script&gt;
    - *   &lt;/body&gt;
    - *   &lt;/html&gt;
    - * </pre>
    - *
    - * Your application should then listen, on the IframeIo instance, to the event
    - * goog.net.EventType.INCREMENTAL_DATA.  The event object contains a
    - * 'data' member which is the content from the D() calls above.
    - *
    - * NOTE: There can be problems if you save a reference to the data object in IE.
    - * If you save an array, and the iframe is dispose, then the array looses its
    - * prototype and thus array methods like .join().  You can get around this by
    - * creating arrays using the parent window's Array constructor, or you can
    - * clone the array.
    - *
    - *
    - * EVENT MODEL:
    - * The various send methods work asynchronously. You can be notified about
    - * the current status of the request (completed, success or error) by
    - * listening for events on the IframeIo object itself. The following events
    - * will be sent:
    - * - goog.net.EventType.COMPLETE: when the request is completed
    - *   (either sucessfully or unsuccessfully). You can find out about the result
    - *   using the isSuccess() and getLastError
    - *   methods.
    - * - goog.net.EventType.SUCCESS</code>: when the request was completed
    - *   successfully
    - * - goog.net.EventType.ERROR: when the request failed
    - * - goog.net.EventType.ABORT: when the request has been aborted
    - *
    - * Example:
    - * <pre>
    - * var io = new goog.net.IframeIo();
    - * goog.events.listen(io, goog.net.EventType.COMPLETE,
    - *   function() { alert('request complete'); });
    - * io.sendFromForm(...);
    - * </pre>
    - *
    - */
    -
    -goog.provide('goog.net.IframeIo');
    -goog.provide('goog.net.IframeIo.IncrementalDataEvent');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.Uri');
    -goog.require('goog.asserts');
    -goog.require('goog.debug');
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -goog.require('goog.json');
    -goog.require('goog.log');
    -goog.require('goog.log.Level');
    -goog.require('goog.net.ErrorCode');
    -goog.require('goog.net.EventType');
    -goog.require('goog.reflect');
    -goog.require('goog.string');
    -goog.require('goog.structs');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Class for managing requests via iFrames.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - */
    -goog.net.IframeIo = function() {
    -  goog.net.IframeIo.base(this, 'constructor');
    -
    -  /**
    -   * Name for this IframeIo and frame
    -   * @type {string}
    -   * @private
    -   */
    -  this.name_ = goog.net.IframeIo.getNextName_();
    -
    -  /**
    -   * An array of iframes that have been finished with.  We need them to be
    -   * disposed async, so we don't confuse the browser (see below).
    -   * @type {Array<Element>}
    -   * @private
    -   */
    -  this.iframesForDisposal_ = [];
    -
    -  // Create a lookup from names to instances of IframeIo.  This is a helper
    -  // function to be used in conjunction with goog.net.IframeIo.getInstanceByName
    -  // to find the IframeIo object associated with a particular iframe.  Used in
    -  // incremental scripts etc.
    -  goog.net.IframeIo.instances_[this.name_] = this;
    -
    -};
    -goog.inherits(goog.net.IframeIo, goog.events.EventTarget);
    -
    -
    -/**
    - * Object used as a map to lookup instances of IframeIo objects by name.
    - * @type {Object}
    - * @private
    - */
    -goog.net.IframeIo.instances_ = {};
    -
    -
    -/**
    - * Prefix for frame names
    - * @type {string}
    - */
    -goog.net.IframeIo.FRAME_NAME_PREFIX = 'closure_frame';
    -
    -
    -/**
    - * Suffix that is added to inner frames used for sending requests in non-IE
    - * browsers
    - * @type {string}
    - */
    -goog.net.IframeIo.INNER_FRAME_SUFFIX = '_inner';
    -
    -
    -/**
    - * The number of milliseconds after a request is completed to dispose the
    - * iframes.  This can be done lazily so we wait long enough for any processing
    - * that occurred as a result of the response to finish.
    - * @type {number}
    - */
    -goog.net.IframeIo.IFRAME_DISPOSE_DELAY_MS = 2000;
    -
    -
    -/**
    - * Counter used when creating iframes
    - * @type {number}
    - * @private
    - */
    -goog.net.IframeIo.counter_ = 0;
    -
    -
    -/**
    - * Form element to post to.
    - * @type {HTMLFormElement}
    - * @private
    - */
    -goog.net.IframeIo.form_;
    -
    -
    -/**
    - * Static send that creates a short lived instance of IframeIo to send the
    - * request.
    - * @param {goog.Uri|string} uri Uri of the request, it is up the caller to
    - *     manage query string params.
    - * @param {Function=} opt_callback Event handler for when request is completed.
    - * @param {string=} opt_method Default is GET, POST uses a form to submit the
    - *     request.
    - * @param {boolean=} opt_noCache Append a timestamp to the request to avoid
    - *     caching.
    - * @param {Object|goog.structs.Map=} opt_data Map of key-value pairs that
    - *     will be posted to the server via the iframe's form.
    - */
    -goog.net.IframeIo.send = function(
    -    uri, opt_callback, opt_method, opt_noCache, opt_data) {
    -
    -  var io = new goog.net.IframeIo();
    -  goog.events.listen(io, goog.net.EventType.READY, io.dispose, false, io);
    -  if (opt_callback) {
    -    goog.events.listen(io, goog.net.EventType.COMPLETE, opt_callback);
    -  }
    -  io.send(uri, opt_method, opt_noCache, opt_data);
    -};
    -
    -
    -/**
    - * Find an iframe by name (assumes the context is goog.global since that is
    - * where IframeIo's iframes are kept).
    - * @param {string} fname The name to find.
    - * @return {HTMLIFrameElement} The iframe element with that name.
    - */
    -goog.net.IframeIo.getIframeByName = function(fname) {
    -  return window.frames[fname];
    -};
    -
    -
    -/**
    - * Find an instance of the IframeIo object by name.
    - * @param {string} fname The name to find.
    - * @return {goog.net.IframeIo} The instance of IframeIo.
    - */
    -goog.net.IframeIo.getInstanceByName = function(fname) {
    -  return goog.net.IframeIo.instances_[fname];
    -};
    -
    -
    -/**
    - * Handles incremental data and routes it to the correct iframeIo instance.
    - * The HTML page requested by the IframeIo instance should contain script blocks
    - * that call an externed reference to this method.
    - * @param {Window} win The window object.
    - * @param {Object} data The data object.
    - */
    -goog.net.IframeIo.handleIncrementalData = function(win, data) {
    -  // If this is the inner-frame, then we need to use the parent instead.
    -  var iframeName = goog.string.endsWith(win.name,
    -      goog.net.IframeIo.INNER_FRAME_SUFFIX) ? win.parent.name : win.name;
    -
    -  var iframeIoName = iframeName.substring(0, iframeName.lastIndexOf('_'));
    -  var iframeIo = goog.net.IframeIo.getInstanceByName(iframeIoName);
    -  if (iframeIo && iframeName == iframeIo.iframeName_) {
    -    iframeIo.handleIncrementalData_(data);
    -  } else {
    -    var logger = goog.log.getLogger('goog.net.IframeIo');
    -    goog.log.info(logger,
    -        'Incremental iframe data routed for unknown iframe');
    -  }
    -};
    -
    -
    -/**
    - * @return {string} The next iframe name.
    - * @private
    - */
    -goog.net.IframeIo.getNextName_ = function() {
    -  return goog.net.IframeIo.FRAME_NAME_PREFIX + goog.net.IframeIo.counter_++;
    -};
    -
    -
    -/**
    - * Gets a static form, one for all instances of IframeIo since IE6 leaks form
    - * nodes that are created/removed from the document.
    - * @return {!HTMLFormElement} The static form.
    - * @private
    - */
    -goog.net.IframeIo.getForm_ = function() {
    -  if (!goog.net.IframeIo.form_) {
    -    goog.net.IframeIo.form_ =
    -        /** @type {!HTMLFormElement} */(goog.dom.createDom('form'));
    -    goog.net.IframeIo.form_.acceptCharset = 'utf-8';
    -
    -    // Hide the form and move it off screen
    -    var s = goog.net.IframeIo.form_.style;
    -    s.position = 'absolute';
    -    s.visibility = 'hidden';
    -    s.top = s.left = '-10px';
    -    s.width = s.height = '10px';
    -    s.overflow = 'hidden';
    -
    -    goog.dom.getDocument().body.appendChild(goog.net.IframeIo.form_);
    -  }
    -  return goog.net.IframeIo.form_;
    -};
    -
    -
    -/**
    - * Adds the key value pairs from a map like data structure to a form
    - * @param {HTMLFormElement} form The form to add to.
    - * @param {Object|goog.structs.Map|goog.Uri.QueryData} data The data to add.
    - * @private
    - */
    -goog.net.IframeIo.addFormInputs_ = function(form, data) {
    -  var helper = goog.dom.getDomHelper(form);
    -  goog.structs.forEach(data, function(value, key) {
    -    var inp = helper.createDom('input',
    -        {'type': 'hidden', 'name': key, 'value': value});
    -    form.appendChild(inp);
    -  });
    -};
    -
    -
    -/**
    - * @return {boolean} Whether we can use readyState to monitor iframe loading.
    - * @private
    - */
    -goog.net.IframeIo.useIeReadyStateCodePath_ = function() {
    -  // ReadyState is only available on iframes up to IE10.
    -  return goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('11');
    -};
    -
    -
    -/**
    - * Reference to a logger for the IframeIo objects
    - * @type {goog.log.Logger}
    - * @private
    - */
    -goog.net.IframeIo.prototype.logger_ =
    -    goog.log.getLogger('goog.net.IframeIo');
    -
    -
    -/**
    - * Reference to form element that gets reused for requests to the iframe.
    - * @type {HTMLFormElement}
    - * @private
    - */
    -goog.net.IframeIo.prototype.form_ = null;
    -
    -
    -/**
    - * Reference to the iframe being used for the current request, or null if no
    - * request is currently active.
    - * @type {HTMLIFrameElement}
    - * @private
    - */
    -goog.net.IframeIo.prototype.iframe_ = null;
    -
    -
    -/**
    - * Name of the iframe being used for the current request, or null if no
    - * request is currently active.
    - * @type {?string}
    - * @private
    - */
    -goog.net.IframeIo.prototype.iframeName_ = null;
    -
    -
    -/**
    - * Next id so that iframe names are unique.
    - * @type {number}
    - * @private
    - */
    -goog.net.IframeIo.prototype.nextIframeId_ = 0;
    -
    -
    -/**
    - * Whether the object is currently active with a request.
    - * @type {boolean}
    - * @private
    - */
    -goog.net.IframeIo.prototype.active_ = false;
    -
    -
    -/**
    - * Whether the last request is complete.
    - * @type {boolean}
    - * @private
    - */
    -goog.net.IframeIo.prototype.complete_ = false;
    -
    -
    -/**
    - * Whether the last request was a success.
    - * @type {boolean}
    - * @private
    - */
    -goog.net.IframeIo.prototype.success_ = false;
    -
    -
    -/**
    - * The URI for the last request.
    - * @type {goog.Uri}
    - * @private
    - */
    -goog.net.IframeIo.prototype.lastUri_ = null;
    -
    -
    -/**
    - * The text content of the last request.
    - * @type {?string}
    - * @private
    - */
    -goog.net.IframeIo.prototype.lastContent_ = null;
    -
    -
    -/**
    - * Last error code
    - * @type {goog.net.ErrorCode}
    - * @private
    - */
    -goog.net.IframeIo.prototype.lastErrorCode_ = goog.net.ErrorCode.NO_ERROR;
    -
    -
    -
    -/**
    - * Window timeout ID used to detect when firefox silently fails.
    - * @type {?number}
    - * @private
    - */
    -goog.net.IframeIo.prototype.firefoxSilentErrorTimeout_ = null;
    -
    -
    -/**
    - * Window timeout ID used by the timer that disposes the iframes.
    - * @type {?number}
    - * @private
    - */
    -goog.net.IframeIo.prototype.iframeDisposalTimer_ = null;
    -
    -
    -/**
    - * This is used to ensure that we don't handle errors twice for the same error.
    - * We can reach the {@link #handleError_} method twice in IE if the form is
    - * submitted while IE is offline and the URL is not available.
    - * @type {boolean}
    - * @private
    - */
    -goog.net.IframeIo.prototype.errorHandled_;
    -
    -
    -/**
    - * Whether to suppress the listeners that determine when the iframe loads.
    - * @type {boolean}
    - * @private
    - */
    -goog.net.IframeIo.prototype.ignoreResponse_ = false;
    -
    -
    -/** @private {Function} */
    -goog.net.IframeIo.prototype.errorChecker_;
    -
    -
    -/** @private {Object} */
    -goog.net.IframeIo.prototype.lastCustomError_;
    -
    -
    -/** @private {?string} */
    -goog.net.IframeIo.prototype.lastContentHtml_;
    -
    -
    -/**
    - * Sends a request via an iframe.
    - *
    - * A HTML form is used and submitted to the iframe, this simplifies the
    - * difference between GET and POST requests. The iframe needs to be created and
    - * destroyed for each request otherwise the request will contribute to the
    - * history stack.
    - *
    - * sendFromForm does some clever trickery (thanks jlim) in non-IE browsers to
    - * stop a history entry being added for POST requests.
    - *
    - * @param {goog.Uri|string} uri Uri of the request.
    - * @param {string=} opt_method Default is GET, POST uses a form to submit the
    - *     request.
    - * @param {boolean=} opt_noCache Append a timestamp to the request to avoid
    - *     caching.
    - * @param {Object|goog.structs.Map=} opt_data Map of key-value pairs.
    - */
    -goog.net.IframeIo.prototype.send = function(
    -    uri, opt_method, opt_noCache, opt_data) {
    -
    -  if (this.active_) {
    -    throw Error('[goog.net.IframeIo] Unable to send, already active.');
    -  }
    -
    -  var uriObj = new goog.Uri(uri);
    -  this.lastUri_ = uriObj;
    -  var method = opt_method ? opt_method.toUpperCase() : 'GET';
    -
    -  if (opt_noCache) {
    -    uriObj.makeUnique();
    -  }
    -
    -  goog.log.info(this.logger_,
    -      'Sending iframe request: ' + uriObj + ' [' + method + ']');
    -
    -  // Build a form for this request
    -  this.form_ = goog.net.IframeIo.getForm_();
    -
    -  if (method == 'GET') {
    -    // For GET requests, we assume that the caller didn't want the queryparams
    -    // already specified in the URI to be clobbered by the form, so we add the
    -    // params here.
    -    goog.net.IframeIo.addFormInputs_(this.form_, uriObj.getQueryData());
    -  }
    -
    -  if (opt_data) {
    -    // Create form fields for each of the data values
    -    goog.net.IframeIo.addFormInputs_(this.form_, opt_data);
    -  }
    -
    -  // Set the URI that the form will be posted
    -  this.form_.action = uriObj.toString();
    -  this.form_.method = method;
    -
    -  this.sendFormInternal_();
    -  this.clearForm_();
    -};
    -
    -
    -/**
    - * Sends the data stored in an existing form to the server. The HTTP method
    - * should be specified on the form, the action can also be specified but can
    - * be overridden by the optional URI param.
    - *
    - * This can be used in conjunction will a file-upload input to upload a file in
    - * the background without affecting history.
    - *
    - * Example form:
    - * <pre>
    - *   &lt;form action="/server/" enctype="multipart/form-data" method="POST"&gt;
    - *     &lt;input name="userfile" type="file"&gt;
    - *   &lt;/form&gt;
    - * </pre>
    - *
    - * @param {HTMLFormElement} form Form element used to send the request to the
    - *     server.
    - * @param {string=} opt_uri Uri to set for the destination of the request, by
    - *     default the uri will come from the form.
    - * @param {boolean=} opt_noCache Append a timestamp to the request to avoid
    - *     caching.
    - */
    -goog.net.IframeIo.prototype.sendFromForm = function(form, opt_uri,
    -    opt_noCache) {
    -  if (this.active_) {
    -    throw Error('[goog.net.IframeIo] Unable to send, already active.');
    -  }
    -
    -  var uri = new goog.Uri(opt_uri || form.action);
    -  if (opt_noCache) {
    -    uri.makeUnique();
    -  }
    -
    -  goog.log.info(this.logger_, 'Sending iframe request from form: ' + uri);
    -
    -  this.lastUri_ = uri;
    -  this.form_ = form;
    -  this.form_.action = uri.toString();
    -  this.sendFormInternal_();
    -};
    -
    -
    -/**
    - * Abort the current Iframe request
    - * @param {goog.net.ErrorCode=} opt_failureCode Optional error code to use -
    - *     defaults to ABORT.
    - */
    -goog.net.IframeIo.prototype.abort = function(opt_failureCode) {
    -  if (this.active_) {
    -    goog.log.info(this.logger_, 'Request aborted');
    -    var requestIframe = this.getRequestIframe();
    -    goog.asserts.assert(requestIframe);
    -    goog.events.removeAll(requestIframe);
    -    this.complete_ = false;
    -    this.active_ = false;
    -    this.success_ = false;
    -    this.lastErrorCode_ = opt_failureCode || goog.net.ErrorCode.ABORT;
    -
    -    this.dispatchEvent(goog.net.EventType.ABORT);
    -
    -    this.makeReady_();
    -  }
    -};
    -
    -
    -/** @override */
    -goog.net.IframeIo.prototype.disposeInternal = function() {
    -  goog.log.fine(this.logger_, 'Disposing iframeIo instance');
    -
    -  // If there is an active request, abort it
    -  if (this.active_) {
    -    goog.log.fine(this.logger_, 'Aborting active request');
    -    this.abort();
    -  }
    -
    -  // Call super-classes implementation (remove listeners)
    -  goog.net.IframeIo.superClass_.disposeInternal.call(this);
    -
    -  // Add the current iframe to the list of iframes for disposal.
    -  if (this.iframe_) {
    -    this.scheduleIframeDisposal_();
    -  }
    -
    -  // Disposes of the form
    -  this.disposeForm_();
    -
    -  // Nullify anything that might cause problems and clear state
    -  delete this.errorChecker_;
    -  this.form_ = null;
    -  this.lastCustomError_ = this.lastContent_ = this.lastContentHtml_ = null;
    -  this.lastUri_ = null;
    -  this.lastErrorCode_ = goog.net.ErrorCode.NO_ERROR;
    -
    -  delete goog.net.IframeIo.instances_[this.name_];
    -};
    -
    -
    -/**
    - * @return {boolean} True if transfer is complete.
    - */
    -goog.net.IframeIo.prototype.isComplete = function() {
    -  return this.complete_;
    -};
    -
    -
    -/**
    - * @return {boolean} True if transfer was successful.
    - */
    -goog.net.IframeIo.prototype.isSuccess = function() {
    -  return this.success_;
    -};
    -
    -
    -/**
    - * @return {boolean} True if a transfer is in progress.
    - */
    -goog.net.IframeIo.prototype.isActive = function() {
    -  return this.active_;
    -};
    -
    -
    -/**
    - * Returns the last response text (i.e. the text content of the iframe).
    - * Assumes plain text!
    - * @return {?string} Result from the server.
    - */
    -goog.net.IframeIo.prototype.getResponseText = function() {
    -  return this.lastContent_;
    -};
    -
    -
    -/**
    - * Returns the last response html (i.e. the innerHtml of the iframe).
    - * @return {?string} Result from the server.
    - */
    -goog.net.IframeIo.prototype.getResponseHtml = function() {
    -  return this.lastContentHtml_;
    -};
    -
    -
    -/**
    - * Parses the content as JSON. This is a safe parse and may throw an error
    - * if the response is malformed.
    - * Use goog.json.unsafeparse(this.getResponseText()) if you are sure of the
    - * state of the returned content.
    - * @return {Object} The parsed content.
    - */
    -goog.net.IframeIo.prototype.getResponseJson = function() {
    -  return goog.json.parse(this.lastContent_);
    -};
    -
    -
    -/**
    - * Returns the document object from the last request.  Not truely XML, but
    - * used to mirror the XhrIo interface.
    - * @return {HTMLDocument} The document object from the last request.
    - */
    -goog.net.IframeIo.prototype.getResponseXml = function() {
    -  if (!this.iframe_) return null;
    -
    -  return this.getContentDocument_();
    -};
    -
    -
    -/**
    - * Get the uri of the last request.
    - * @return {goog.Uri} Uri of last request.
    - */
    -goog.net.IframeIo.prototype.getLastUri = function() {
    -  return this.lastUri_;
    -};
    -
    -
    -/**
    - * Gets the last error code.
    - * @return {goog.net.ErrorCode} Last error code.
    - */
    -goog.net.IframeIo.prototype.getLastErrorCode = function() {
    -  return this.lastErrorCode_;
    -};
    -
    -
    -/**
    - * Gets the last error message.
    - * @return {string} Last error message.
    - */
    -goog.net.IframeIo.prototype.getLastError = function() {
    -  return goog.net.ErrorCode.getDebugMessage(this.lastErrorCode_);
    -};
    -
    -
    -/**
    - * Gets the last custom error.
    - * @return {Object} Last custom error.
    - */
    -goog.net.IframeIo.prototype.getLastCustomError = function() {
    -  return this.lastCustomError_;
    -};
    -
    -
    -/**
    - * Sets the callback function used to check if a loaded IFrame is in an error
    - * state.
    - * @param {Function} fn Callback that expects a document object as it's single
    - *     argument.
    - */
    -goog.net.IframeIo.prototype.setErrorChecker = function(fn) {
    -  this.errorChecker_ = fn;
    -};
    -
    -
    -/**
    - * Gets the callback function used to check if a loaded IFrame is in an error
    - * state.
    - * @return {Function} A callback that expects a document object as it's single
    - *     argument.
    - */
    -goog.net.IframeIo.prototype.getErrorChecker = function() {
    -  return this.errorChecker_;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the server response is being ignored.
    - */
    -goog.net.IframeIo.prototype.isIgnoringResponse = function() {
    -  return this.ignoreResponse_;
    -};
    -
    -
    -/**
    - * Sets whether to ignore the response from the server by not adding any event
    - * handlers to fire when the iframe loads. This is necessary when using IframeIo
    - * to submit to a server on another domain, to avoid same-origin violations when
    - * trying to access the response. If this is set to true, the IframeIo instance
    - * will be a single-use instance that is only usable for one request.  It will
    - * only clean up its resources (iframes and forms) when it is disposed.
    - * @param {boolean} ignore Whether to ignore the server response.
    - */
    -goog.net.IframeIo.prototype.setIgnoreResponse = function(ignore) {
    -  this.ignoreResponse_ = ignore;
    -};
    -
    -
    -/**
    - * Submits the internal form to the iframe.
    - * @private
    - */
    -goog.net.IframeIo.prototype.sendFormInternal_ = function() {
    -  this.active_ = true;
    -  this.complete_ = false;
    -  this.lastErrorCode_ = goog.net.ErrorCode.NO_ERROR;
    -
    -  // Make Iframe
    -  this.createIframe_();
    -
    -  if (goog.net.IframeIo.useIeReadyStateCodePath_()) {
    -    // In IE<11 we simply create the frame, wait until it is ready, then post
    -    // the form to the iframe and wait for the readystate to change to
    -    // 'complete'
    -
    -    // Set the target to the iframe's name
    -    this.form_.target = this.iframeName_ || '';
    -    this.appendIframe_();
    -    if (!this.ignoreResponse_) {
    -      goog.events.listen(this.iframe_, goog.events.EventType.READYSTATECHANGE,
    -          this.onIeReadyStateChange_, false, this);
    -    }
    -
    -    /** @preserveTry */
    -    try {
    -      this.errorHandled_ = false;
    -      this.form_.submit();
    -    } catch (e) {
    -      // If submit threw an exception then it probably means the page that the
    -      // code is running on the local file system and the form's action was
    -      // pointing to a file that doesn't exist, causing the browser to fire an
    -      // exception.  IE also throws an exception when it is working offline and
    -      // the URL is not available.
    -
    -      if (!this.ignoreResponse_) {
    -        goog.events.unlisten(
    -            this.iframe_,
    -            goog.events.EventType.READYSTATECHANGE,
    -            this.onIeReadyStateChange_,
    -            false,
    -            this);
    -      }
    -
    -      this.handleError_(goog.net.ErrorCode.ACCESS_DENIED);
    -    }
    -
    -  } else {
    -    // For all other browsers we do some trickery to ensure that there is no
    -    // entry on the history stack. Thanks go to jlim for the prototype for this
    -
    -    goog.log.fine(this.logger_, 'Setting up iframes and cloning form');
    -
    -    this.appendIframe_();
    -
    -    var innerFrameName = this.iframeName_ +
    -                         goog.net.IframeIo.INNER_FRAME_SUFFIX;
    -
    -    // Open and document.write another iframe into the iframe
    -    var doc = goog.dom.getFrameContentDocument(this.iframe_);
    -    var html = '<body><iframe id=' + innerFrameName +
    -               ' name=' + innerFrameName + '></iframe>';
    -    if (document.baseURI) {
    -      // On Safari 4 and 5 the new iframe doesn't inherit the current baseURI.
    -      html = '<head><base href="' + goog.string.htmlEscape(document.baseURI) +
    -             '"></head>' + html;
    -    }
    -    if (goog.userAgent.OPERA) {
    -      // Opera adds a history entry when document.write is used.
    -      // Change the innerHTML of the page instead.
    -      doc.documentElement.innerHTML = html;
    -    } else {
    -      doc.write(html);
    -    }
    -
    -    // Listen for the iframe's load
    -    if (!this.ignoreResponse_) {
    -      goog.events.listen(doc.getElementById(innerFrameName),
    -          goog.events.EventType.LOAD, this.onIframeLoaded_, false, this);
    -    }
    -
    -    // Fix text areas, since importNode won't clone changes to the value
    -    var textareas = this.form_.getElementsByTagName('textarea');
    -    for (var i = 0, n = textareas.length; i < n; i++) {
    -      // The childnodes represent the initial child nodes for the text area
    -      // appending a text node essentially resets the initial value ready for
    -      // it to be clones - while maintaining HTML escaping.
    -      var value = textareas[i].value;
    -      if (goog.dom.getRawTextContent(textareas[i]) != value) {
    -        goog.dom.setTextContent(textareas[i], value);
    -        textareas[i].value = value;
    -      }
    -    }
    -
    -    // Append a cloned form to the iframe
    -    var clone = doc.importNode(this.form_, true);
    -    clone.target = innerFrameName;
    -    // Work around crbug.com/66987
    -    clone.action = this.form_.action;
    -    doc.body.appendChild(clone);
    -
    -    // Fix select boxes, importNode won't override the default value
    -    var selects = this.form_.getElementsByTagName('select');
    -    var clones = clone.getElementsByTagName('select');
    -    for (var i = 0, n = selects.length; i < n; i++) {
    -      var selectsOptions = selects[i].getElementsByTagName('option');
    -      var clonesOptions = clones[i].getElementsByTagName('option');
    -      for (var j = 0, m = selectsOptions.length; j < m; j++) {
    -        clonesOptions[j].selected = selectsOptions[j].selected;
    -      }
    -    }
    -
    -    // IE and some versions of Firefox (1.5 - 1.5.07?) fail to clone the value
    -    // attribute for <input type="file"> nodes, which results in an empty
    -    // upload if the clone is submitted.  Check, and if the clone failed, submit
    -    // using the original form instead.
    -    var inputs = this.form_.getElementsByTagName('input');
    -    var inputClones = clone.getElementsByTagName('input');
    -    for (var i = 0, n = inputs.length; i < n; i++) {
    -      if (inputs[i].type == 'file') {
    -        if (inputs[i].value != inputClones[i].value) {
    -          goog.log.fine(this.logger_,
    -              'File input value not cloned properly.  Will ' +
    -              'submit using original form.');
    -          this.form_.target = innerFrameName;
    -          clone = this.form_;
    -          break;
    -        }
    -      }
    -    }
    -
    -    goog.log.fine(this.logger_, 'Submitting form');
    -
    -    /** @preserveTry */
    -    try {
    -      this.errorHandled_ = false;
    -      clone.submit();
    -      doc.close();
    -
    -      if (goog.userAgent.GECKO) {
    -        // This tests if firefox silently fails, this can happen, for example,
    -        // when the server resets the connection because of a large file upload
    -        this.firefoxSilentErrorTimeout_ =
    -            goog.Timer.callOnce(this.testForFirefoxSilentError_, 250, this);
    -      }
    -
    -    } catch (e) {
    -      // If submit threw an exception then it probably means the page that the
    -      // code is running on the local file system and the form's action was
    -      // pointing to a file that doesn't exist, causing the browser to fire an
    -      // exception.
    -
    -      goog.log.error(this.logger_,
    -          'Error when submitting form: ' + goog.debug.exposeException(e));
    -
    -      if (!this.ignoreResponse_) {
    -        goog.events.unlisten(doc.getElementById(innerFrameName),
    -            goog.events.EventType.LOAD, this.onIframeLoaded_, false, this);
    -      }
    -
    -      doc.close();
    -
    -      this.handleError_(goog.net.ErrorCode.FILE_NOT_FOUND);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Handles the load event of the iframe for IE, determines if the request was
    - * successful or not, handles clean up and dispatching of appropriate events.
    - * @param {goog.events.BrowserEvent} e The browser event.
    - * @private
    - */
    -goog.net.IframeIo.prototype.onIeReadyStateChange_ = function(e) {
    -  if (this.iframe_.readyState == 'complete') {
    -    goog.events.unlisten(this.iframe_, goog.events.EventType.READYSTATECHANGE,
    -        this.onIeReadyStateChange_, false, this);
    -    var doc;
    -    /** @preserveTry */
    -    try {
    -      doc = goog.dom.getFrameContentDocument(this.iframe_);
    -
    -      // IE serves about:blank when it cannot load the resource while offline.
    -      if (goog.userAgent.IE && doc.location == 'about:blank' &&
    -          !navigator.onLine) {
    -        this.handleError_(goog.net.ErrorCode.OFFLINE);
    -        return;
    -      }
    -    } catch (ex) {
    -      this.handleError_(goog.net.ErrorCode.ACCESS_DENIED);
    -      return;
    -    }
    -    this.handleLoad_(/** @type {!HTMLDocument} */(doc));
    -  }
    -};
    -
    -
    -/**
    - * Handles the load event of the iframe for non-IE browsers.
    - * @param {goog.events.BrowserEvent} e The browser event.
    - * @private
    - */
    -goog.net.IframeIo.prototype.onIframeLoaded_ = function(e) {
    -  // In Opera, the default "about:blank" page of iframes fires an onload
    -  // event that we'd like to ignore.
    -  if (goog.userAgent.OPERA &&
    -      this.getContentDocument_().location == 'about:blank') {
    -    return;
    -  }
    -  goog.events.unlisten(this.getRequestIframe(),
    -      goog.events.EventType.LOAD, this.onIframeLoaded_, false, this);
    -  try {
    -    this.handleLoad_(this.getContentDocument_());
    -  } catch (ex) {
    -    this.handleError_(goog.net.ErrorCode.ACCESS_DENIED);
    -  }
    -};
    -
    -
    -/**
    - * Handles generic post-load
    - * @param {HTMLDocument} contentDocument The frame's document.
    - * @private
    - */
    -goog.net.IframeIo.prototype.handleLoad_ = function(contentDocument) {
    -  goog.log.fine(this.logger_, 'Iframe loaded');
    -
    -  this.complete_ = true;
    -  this.active_ = false;
    -
    -  var errorCode;
    -
    -  // Try to get the innerHTML.  If this fails then it can be an access denied
    -  // error or the document may just not have a body, typical case is if there
    -  // is an IE's default 404.
    -  /** @preserveTry */
    -  try {
    -    var body = contentDocument.body;
    -    this.lastContent_ = body.textContent || body.innerText;
    -    this.lastContentHtml_ = body.innerHTML;
    -  } catch (ex) {
    -    errorCode = goog.net.ErrorCode.ACCESS_DENIED;
    -  }
    -
    -  // Use a callback function, defined by the application, to analyse the
    -  // contentDocument and determine if it is an error page.  Applications
    -  // may send down markers in the document, define JS vars, or some other test.
    -  var customError;
    -  if (!errorCode && typeof this.errorChecker_ == 'function') {
    -    customError = this.errorChecker_(contentDocument);
    -    if (customError) {
    -      errorCode = goog.net.ErrorCode.CUSTOM_ERROR;
    -    }
    -  }
    -
    -  goog.log.log(this.logger_, goog.log.Level.FINER,
    -      'Last content: ' + this.lastContent_);
    -  goog.log.log(this.logger_, goog.log.Level.FINER,
    -      'Last uri: ' + this.lastUri_);
    -
    -  if (errorCode) {
    -    goog.log.fine(this.logger_, 'Load event occurred but failed');
    -    this.handleError_(errorCode, customError);
    -
    -  } else {
    -    goog.log.fine(this.logger_, 'Load succeeded');
    -    this.success_ = true;
    -    this.lastErrorCode_ = goog.net.ErrorCode.NO_ERROR;
    -    this.dispatchEvent(goog.net.EventType.COMPLETE);
    -    this.dispatchEvent(goog.net.EventType.SUCCESS);
    -
    -    this.makeReady_();
    -  }
    -};
    -
    -
    -/**
    - * Handles errors.
    - * @param {goog.net.ErrorCode} errorCode Error code.
    - * @param {Object=} opt_customError If error is CUSTOM_ERROR, this is the
    - *     client-provided custom error.
    - * @private
    - */
    -goog.net.IframeIo.prototype.handleError_ = function(errorCode,
    -                                                    opt_customError) {
    -  if (!this.errorHandled_) {
    -    this.success_ = false;
    -    this.active_ = false;
    -    this.complete_ = true;
    -    this.lastErrorCode_ = errorCode;
    -    if (errorCode == goog.net.ErrorCode.CUSTOM_ERROR) {
    -      goog.asserts.assert(goog.isDef(opt_customError));
    -      this.lastCustomError_ = opt_customError;
    -    }
    -    this.dispatchEvent(goog.net.EventType.COMPLETE);
    -    this.dispatchEvent(goog.net.EventType.ERROR);
    -
    -    this.makeReady_();
    -
    -    this.errorHandled_ = true;
    -  }
    -};
    -
    -
    -/**
    - * Dispatches an event indicating that the IframeIo instance has received a data
    - * packet via incremental loading.  The event object has a 'data' member.
    - * @param {Object} data Data.
    - * @private
    - */
    -goog.net.IframeIo.prototype.handleIncrementalData_ = function(data) {
    -  this.dispatchEvent(new goog.net.IframeIo.IncrementalDataEvent(data));
    -};
    -
    -
    -/**
    - * Finalizes the request, schedules the iframe for disposal, and maybe disposes
    - * the form.
    - * @private
    - */
    -goog.net.IframeIo.prototype.makeReady_ = function() {
    -  goog.log.info(this.logger_, 'Ready for new requests');
    -  this.scheduleIframeDisposal_();
    -  this.disposeForm_();
    -  this.dispatchEvent(goog.net.EventType.READY);
    -};
    -
    -
    -/**
    - * Creates an iframe to be used with a request.  We use a new iframe for each
    - * request so that requests don't create history entries.
    - * @private
    - */
    -goog.net.IframeIo.prototype.createIframe_ = function() {
    -  goog.log.fine(this.logger_, 'Creating iframe');
    -
    -  this.iframeName_ = this.name_ + '_' + (this.nextIframeId_++).toString(36);
    -
    -  var iframeAttributes = {'name': this.iframeName_, 'id': this.iframeName_};
    -  // Setting the source to javascript:"" is a fix to remove IE6 mixed content
    -  // warnings when being used in an https page.
    -  if (goog.userAgent.IE && goog.userAgent.VERSION < 7) {
    -    iframeAttributes.src = 'javascript:""';
    -  }
    -
    -  this.iframe_ = /** @type {!HTMLIFrameElement} */(
    -      goog.dom.getDomHelper(this.form_).createDom('iframe', iframeAttributes));
    -
    -  var s = this.iframe_.style;
    -  s.visibility = 'hidden';
    -  s.width = s.height = '10px';
    -  // Chrome sometimes shows scrollbars when visibility is hidden, but not when
    -  // display is none.
    -  s.display = 'none';
    -
    -  // There are reports that safari 2.0.3 has a bug where absolutely positioned
    -  // iframes can't have their src set.
    -  if (!goog.userAgent.WEBKIT) {
    -    s.position = 'absolute';
    -    s.top = s.left = '-10px';
    -  } else {
    -    s.marginTop = s.marginLeft = '-10px';
    -  }
    -};
    -
    -
    -/**
    - * Appends the Iframe to the document body.
    - * @private
    - */
    -goog.net.IframeIo.prototype.appendIframe_ = function() {
    -  goog.dom.getDomHelper(this.form_).getDocument().body.appendChild(
    -      this.iframe_);
    -};
    -
    -
    -/**
    - * Schedules an iframe for disposal, async.  We can't remove the iframes in the
    - * same execution context as the response, otherwise some versions of Firefox
    - * will not detect that the response has correctly finished and the loading bar
    - * will stay active forever.
    - * @private
    - */
    -goog.net.IframeIo.prototype.scheduleIframeDisposal_ = function() {
    -  var iframe = this.iframe_;
    -
    -  // There shouldn't be a case where the iframe is null and we get to this
    -  // stage, but the error reports in http://b/909448 indicate it is possible.
    -  if (iframe) {
    -    // NOTE(user): Stops Internet Explorer leaking the iframe object. This
    -    // shouldn't be needed, since the events have all been removed, which
    -    // should in theory clean up references.  Oh well...
    -    iframe.onreadystatechange = null;
    -    iframe.onload = null;
    -    iframe.onerror = null;
    -
    -    this.iframesForDisposal_.push(iframe);
    -  }
    -
    -  if (this.iframeDisposalTimer_) {
    -    goog.Timer.clear(this.iframeDisposalTimer_);
    -    this.iframeDisposalTimer_ = null;
    -  }
    -
    -  if (goog.userAgent.GECKO || goog.userAgent.OPERA) {
    -    // For FF and Opera, we must dispose the iframe async,
    -    // but it doesn't need to be done as soon as possible.
    -    // We therefore schedule it for 2s out, so as not to
    -    // affect any other actions that may have been triggered by the request.
    -    this.iframeDisposalTimer_ = goog.Timer.callOnce(
    -        this.disposeIframes_, goog.net.IframeIo.IFRAME_DISPOSE_DELAY_MS, this);
    -
    -  } else {
    -    // For non-Gecko browsers we dispose straight away.
    -    this.disposeIframes_();
    -  }
    -
    -  // Nullify reference
    -  this.iframe_ = null;
    -  this.iframeName_ = null;
    -};
    -
    -
    -/**
    - * Disposes any iframes.
    - * @private
    - */
    -goog.net.IframeIo.prototype.disposeIframes_ = function() {
    -  if (this.iframeDisposalTimer_) {
    -    // Clear the timer
    -    goog.Timer.clear(this.iframeDisposalTimer_);
    -    this.iframeDisposalTimer_ = null;
    -  }
    -
    -  while (this.iframesForDisposal_.length != 0) {
    -    var iframe = this.iframesForDisposal_.pop();
    -    goog.log.info(this.logger_, 'Disposing iframe');
    -    goog.dom.removeNode(iframe);
    -  }
    -};
    -
    -
    -/**
    - * Removes all the child nodes from the static form so it can be reused again.
    - * This should happen right after sending a request. Otherwise, there can be
    - * issues when another iframe uses this form right after the first iframe.
    - * @private
    - */
    -goog.net.IframeIo.prototype.clearForm_ = function() {
    -  if (this.form_ && this.form_ == goog.net.IframeIo.form_) {
    -    goog.dom.removeChildren(this.form_);
    -  }
    -};
    -
    -
    -/**
    - * Disposes of the Form.  Since IE6 leaks form nodes, this just cleans up the
    - * DOM and nullifies the instances reference so the form can be used for another
    - * request.
    - * @private
    - */
    -goog.net.IframeIo.prototype.disposeForm_ = function() {
    -  this.clearForm_();
    -  this.form_ = null;
    -};
    -
    -
    -/**
    - * @return {HTMLDocument} The appropriate content document.
    - * @private
    - */
    -goog.net.IframeIo.prototype.getContentDocument_ = function() {
    -  if (this.iframe_) {
    -    return /** @type {!HTMLDocument} */(goog.dom.getFrameContentDocument(
    -        this.getRequestIframe()));
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * @return {HTMLIFrameElement} The appropriate iframe to use for requests
    - *     (created in sendForm_).
    - */
    -goog.net.IframeIo.prototype.getRequestIframe = function() {
    -  if (this.iframe_) {
    -    return /** @type {HTMLIFrameElement} */(
    -        goog.net.IframeIo.useIeReadyStateCodePath_() ?
    -            this.iframe_ :
    -            goog.dom.getFrameContentDocument(this.iframe_).getElementById(
    -                this.iframeName_ + goog.net.IframeIo.INNER_FRAME_SUFFIX));
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * Tests for a silent failure by firefox that can occur when the connection is
    - * reset by the server or is made to an illegal URL.
    - * @private
    - */
    -goog.net.IframeIo.prototype.testForFirefoxSilentError_ = function() {
    -  if (this.active_) {
    -    var doc = this.getContentDocument_();
    -
    -    // This is a hack to test of the document has loaded with a page that
    -    // we can't access, such as a network error, that won't report onload
    -    // or onerror events.
    -    if (doc && !goog.reflect.canAccessProperty(doc, 'documentUri')) {
    -      if (!this.ignoreResponse_) {
    -        goog.events.unlisten(this.getRequestIframe(),
    -            goog.events.EventType.LOAD, this.onIframeLoaded_, false, this);
    -      }
    -
    -      if (navigator.onLine) {
    -        goog.log.warning(this.logger_, 'Silent Firefox error detected');
    -        this.handleError_(goog.net.ErrorCode.FF_SILENT_ERROR);
    -      } else {
    -        goog.log.warning(this.logger_,
    -            'Firefox is offline so report offline error ' +
    -            'instead of silent error');
    -        this.handleError_(goog.net.ErrorCode.OFFLINE);
    -      }
    -      return;
    -    }
    -    this.firefoxSilentErrorTimeout_ =
    -        goog.Timer.callOnce(this.testForFirefoxSilentError_, 250, this);
    -  }
    -};
    -
    -
    -
    -/**
    - * Class for representing incremental data events.
    - * @param {Object} data The data associated with the event.
    - * @extends {goog.events.Event}
    - * @constructor
    - * @final
    - */
    -goog.net.IframeIo.IncrementalDataEvent = function(data) {
    -  goog.events.Event.call(this, goog.net.EventType.INCREMENTAL_DATA);
    -
    -  /**
    -   * The data associated with the event.
    -   * @type {Object}
    -   */
    -  this.data = data;
    -};
    -goog.inherits(goog.net.IframeIo.IncrementalDataEvent, goog.events.Event);
    diff --git a/src/database/third_party/closure-library/closure/goog/net/iframeio_different_base_test.data b/src/database/third_party/closure-library/closure/goog/net/iframeio_different_base_test.data
    deleted file mode 100644
    index fed43572049..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/iframeio_different_base_test.data
    +++ /dev/null
    @@ -1,2 +0,0 @@
    -This is just a file that iframeio_different_base_test.html requests to test
    -iframeIo.
    diff --git a/src/database/third_party/closure-library/closure/goog/net/iframeio_different_base_test.html b/src/database/third_party/closure-library/closure/goog/net/iframeio_different_base_test.html
    deleted file mode 100644
    index f19c8207a5d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/iframeio_different_base_test.html
    +++ /dev/null
    @@ -1,27 +0,0 @@
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.net.IframeIo (with different base URL)
    -  </title>
    -  <script>
    -    // We use a different base to reproduce the conditions of crbug.com/66987
    -    var href = window.location.href;
    -    var newHref = href.replace(/net.*/, '');
    -    document.write('<base href="' + newHref + '">');
    -
    -    var baseScript = 'base.js';
    -    document.write('<script src="' + baseScript + '"><\/script>');
    -  </script>
    -  <script>
    -    goog.require('goog.net.iframeIoDifferentBaseTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/iframeio_different_base_test.js b/src/database/third_party/closure-library/closure/goog/net/iframeio_different_base_test.js
    deleted file mode 100644
    index b524b0e4072..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/iframeio_different_base_test.js
    +++ /dev/null
    @@ -1,36 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.net.iframeIoDifferentBaseTest');
    -goog.setTestOnly('goog.net.iframeIoDifferentBaseTest');
    -
    -goog.require('goog.events');
    -goog.require('goog.net.EventType');
    -goog.require('goog.net.IframeIo');
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.jsunit');
    -
    -var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall();
    -
    -function testDifferentBaseUri() {
    -  var io = new goog.net.IframeIo();
    -  goog.events.listen(io, goog.net.EventType.COMPLETE,
    -      function() {
    -        assertNotEquals('File should have expected content.',
    -            -1, io.getResponseText().indexOf('just a file'));
    -        asyncTestCase.continueTesting();
    -      });
    -  io.send('net/iframeio_different_base_test.data');
    -  asyncTestCase.waitForAsync('Waiting for iframeIo respons.');
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/net/iframeio_test.html b/src/database/third_party/closure-library/closure/goog/net/iframeio_test.html
    deleted file mode 100644
    index 4ca4781fc20..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/iframeio_test.html
    +++ /dev/null
    @@ -1,115 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.net.IframeIo
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.net.IframeIoTest');
    -  </script>
    -<style>
    -  html, body {
    -    width: 100%;
    -    height: 100%;
    -    overflow:hidden;
    -  }
    -
    -  #log {
    -    position: absolute;
    -    top: 0px;
    -    width: 50%;
    -    right: 0%;
    -    height: 100%;
    -    overflow: auto;
    -  }
    -
    -  p, input {
    -    font-family: verdana, helvetica, arial, sans-serif;
    -    font-size: small;
    -    margin: 0px;
    -  }
    -
    -  input {
    -    font-family: verdana, helvetica, arial, sans-serif;
    -    font-size: x-small;
    -  }
    -
    -  i {
    -    font-size: 85%;
    -  }
    -</style>
    -</head>
    -<body>
    -<p>
    -  <b>IframeIo manual tests:</b><br><br>
    -  <i>All operations should have no effect on history.</i><br>
    -  <br>
    -  <i>These tests require the ClosureTestServer<br>
    -  to be running with the IframeIoTestServlet.</i><br>
    -<br></p>
    -
    -<p>
    -  <a href="javascript:simpleGet()">Simple GET</a><br>
    -  <a href="javascript:simplePost()">Simple POST</a><br>
    -  <a href="javascript:jsonEcho('GET')">JSON echo (get)</a><br>
    -  <a href="javascript:jsonEcho('POST')">JSON echo (post)</a><br>
    -  <a href="javascript:abort()">Test abort</a>
    -</p>
    -<form id="uploadform" action="/iframeio/upload" enctype="multipart/form-data" method="POST">
    -  <p><a href="javascript:sendFromForm()">Upload</a> <input name="userfile" type="file"> (big files should fail)</p>
    -</form>
    -<p>
    -  <a href="javascript:incremental()">Incremental results</a><br>
    -  <a href="javascript:redirect1()">Redirect (google.com)</a><br>
    -  <a href="javascript:redirect2()">Redirect (/iframeio/ping)</a><br>
    -  <a href="javascript:localUrl1()">Local request (Win path)</a><br>
    -  <a href="javascript:localUrl2()">Local request (Linux path)</a><br>
    -  <a href="javascript:badUrl()">Out of domain request</a><br>
    -  <a href="javascript:getServerTime(false)">Test cache</a> (Date should stay the same for subsequent tests)<br>
    -  <a href="javascript:getServerTime(true)">Test no-cache</a><br>
    -  <a href="javascript:errorGse404()">GSE 404 Error</a><br>
    -  <a href="javascript:errorGfe()">Simulated GFE Error</a><br>
    -  <a href="javascript:errorGmail()">Simulated Gmail Server Error</a><br><br>
    -</p>
    -<form id="testfrm" action="/iframeio/jsonecho" method="POST">
    -  <p><b>Comprehensive Form Post Test:</b><br>
    -  <input name="textinput" type="text" value="Default"> Text Input<br>
    -  Text Area<br>
    -  <textarea name="textarea">Default</textarea><br>
    -  <input name="checkbox1" type="checkbox" checked="checked"> Checkbox, default on<br>
    -  <input name="checkbox2" type="checkbox"> Checkbox, default off<br>
    -  Radio: <input name="radio" type="radio" value="Default" checked="checked"> Default,
    -  <input name="radio" type="radio" value="Foo"> Foo,
    -  <input name="radio" type="radio" value="Bar"> Bar<br>
    -  <select name="select">
    -    <option>One</option>
    -    <option>Two</option>
    -    <option selected="selected">Three (Default)</option>
    -    <option>Four</option>
    -    <option>Five</option>
    -  </select><br>
    -  <select name="selectmultiple">
    -    <option>One</option>
    -    <option selected="selected">Two (Default checked)</option>
    -    <option selected="selected">Three (Default checked)</option>
    -    <option>Four</option>
    -  </select>
    -  <a href="javascript:postForm()">Submit this form</a>
    -  </p>
    -</form>
    -<p><br><br>
    -TODO(pupius):<br>
    -- Local timeout
    -</p>
    -<div id="log"></div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/iframeio_test.js b/src/database/third_party/closure-library/closure/goog/net/iframeio_test.js
    deleted file mode 100644
    index bfe880a592e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/iframeio_test.js
    +++ /dev/null
    @@ -1,310 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.net.IframeIoTest');
    -goog.setTestOnly('goog.net.IframeIoTest');
    -
    -goog.require('goog.debug');
    -goog.require('goog.debug.DivConsole');
    -goog.require('goog.debug.LogManager');
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.EventType');
    -goog.require('goog.log');
    -goog.require('goog.log.Level');
    -goog.require('goog.net.IframeIo');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.events.Event');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -// MANUAL TESTS - The tests should be run in the browser from the Closure Test
    -// Server
    -
    -// Set up a logger to track responses
    -goog.debug.LogManager.getRoot().setLevel(goog.log.Level.INFO);
    -var logconsole;
    -var testLogger = goog.log.getLogger('test');
    -
    -function setUpPage() {
    -  var logconsole = new goog.debug.DivConsole(document.getElementById('log'));
    -  logconsole.setCapturing(true);
    -}
    -
    -
    -/** Creates an iframeIo instance and sets up the test environment */
    -function getTestIframeIo() {
    -  logconsole.addSeparator();
    -  logconsole.getFormatter().resetRelativeTimeStart();
    -
    -  var io = new goog.net.IframeIo();
    -  io.setErrorChecker(checkForError);
    -
    -  goog.events.listen(io, 'success', onSuccess);
    -  goog.events.listen(io, 'error', onError);
    -  goog.events.listen(io, 'ready', onReady);
    -
    -  return io;
    -}
    -
    -
    -/**
    - * Checks for error strings returned by the GSE and error variables that
    - * the Gmail server and GFE set on certain errors.
    - */
    -function checkForError(doc) {
    -  var win = goog.dom.getWindow(doc);
    -  var text = doc.body.textContent || doc.body.innerText || '';
    -  var gseError = text.match(/([^\n]+)\nError ([0-9]{3})/);
    -  if (gseError) {
    -    return '(Error ' + gseError[2] + ') ' + gseError[1];
    -  } else if (win.gmail_error) {
    -    return win.gmail_error + 700;
    -  } else if (win.rc) {
    -    return 600 + win.rc % 100;
    -  } else {
    -    return null;
    -  }
    -}
    -
    -
    -/** Logs the status of an iframeIo object */
    -function logStatus(i) {
    -  goog.log.fine(testLogger, 'Is complete/success/active: ' +
    -      [i.isComplete(), i.isSuccess(), i.isActive()].join('/'));
    -}
    -
    -function onSuccess(e) {
    -  goog.log.warning(testLogger, 'Request Succeeded');
    -  logStatus(e.target);
    -}
    -
    -function onError(e) {
    -  goog.log.warning(testLogger, 'Request Errored: ' + e.target.getLastError());
    -  logStatus(e.target);
    -}
    -
    -function onReady(e) {
    -  goog.log.info(testLogger,
    -      'Test finished and iframe ready, disposing test object');
    -  e.target.dispose();
    -}
    -
    -
    -
    -function simpleGet() {
    -  var io = getTestIframeIo();
    -  goog.events.listen(io, 'complete', onSimpleTestComplete);
    -  io.send('/iframeio/ping', 'GET');
    -}
    -
    -
    -function simplePost() {
    -  var io = getTestIframeIo();
    -  goog.events.listen(io, 'complete', onSimpleTestComplete);
    -  io.send('/iframeio/ping', 'POST');
    -}
    -
    -function onSimpleTestComplete(e) {
    -  goog.log.info(testLogger, 'ResponseText: ' + e.target.getResponseText());
    -}
    -
    -function abort() {
    -  var io = getTestIframeIo();
    -  goog.events.listen(io, 'complete', onAbortComplete);
    -  goog.events.listen(io, 'abort', onAbort);
    -  io.send('/iframeio/ping', 'GET');
    -  io.abort();
    -}
    -
    -function onAbortComplete(e) {
    -  goog.log.info(testLogger, 'Hmm, request should have been aborted');
    -}
    -
    -function onAbort(e) {
    -  goog.log.info(testLogger, 'Request aborted');
    -}
    -
    -
    -function errorGse404() {
    -  var io = getTestIframeIo();
    -  io.send('/iframeio/404', 'GET');
    -}
    -
    -function jsonEcho(method) {
    -  var io = getTestIframeIo();
    -  goog.events.listen(io, 'complete', onJsonComplete);
    -  var data = {'p1': 'x', 'p2': 'y', 'p3': 'z', 'r': 10};
    -  io.send('/iframeio/jsonecho?q1=a&q2=b&q3=c&r=5', method, false, data);
    -}
    -
    -function onJsonComplete(e) {
    -  goog.log.info(testLogger, 'ResponseText: ' + e.target.getResponseText());
    -  var json = e.target.getResponseJson();
    -  goog.log.info(testLogger,
    -      'ResponseJson:\n' + goog.debug.deepExpose(json, true));
    -}
    -
    -
    -
    -function sendFromForm() {
    -  var io = getTestIframeIo();
    -  goog.events.listen(io, 'success', onUploadSuccess);
    -  goog.events.listen(io, 'error', onUploadError);
    -  io.sendFromForm(document.getElementById('uploadform'));
    -}
    -
    -function onUploadSuccess(e) {
    -  goog.log.log(testLogger, goog.log.Level.SHOUT, 'Upload Succeeded');
    -  goog.log.info(testLogger, 'ResponseText: ' + e.target.getResponseText());
    -}
    -
    -function onUploadError(e) {
    -  goog.log.log(testLogger, goog.log.Level.SHOUT, 'Upload Errored');
    -  goog.log.info(testLogger, 'ResponseText: ' + e.target.getResponseText());
    -}
    -
    -
    -function redirect1() {
    -  var io = getTestIframeIo();
    -  io.send('/iframeio/redirect', 'GET');
    -}
    -
    -function redirect2() {
    -  var io = getTestIframeIo();
    -  io.send('/iframeio/move', 'GET');
    -}
    -
    -function badUrl() {
    -  var io = getTestIframeIo();
    -  io.send('http://news.bbc.co.uk', 'GET');
    -}
    -
    -function localUrl1() {
    -  var io = getTestIframeIo();
    -  goog.events.listen(io, 'complete', onLocalSuccess);
    -  io.send('c:\test.txt', 'GET');
    -}
    -
    -function localUrl2() {
    -  var io = getTestIframeIo();
    -  goog.events.listen(io, 'success', onLocalSuccess);
    -  io.send('//test.txt', 'GET');
    -}
    -
    -function onLocalSuccess(e) {
    -  goog.log.info(testLogger,
    -      'The file was found:\n' + e.target.getResponseText());
    -}
    -
    -function getServerTime(noCache) {
    -  var io = getTestIframeIo();
    -  goog.events.listen(io, 'success', onTestCacheSuccess);
    -  io.send('/iframeio/datetime', 'GET', noCache);
    -}
    -
    -function onTestCacheSuccess(e) {
    -  goog.log.info(testLogger, 'Date reported: ' + e.target.getResponseText());
    -}
    -
    -
    -function errorGmail() {
    -  var io = getTestIframeIo();
    -  goog.events.listen(io, 'error', onGmailError);
    -  io.send('/iframeio/gmailerror', 'GET');
    -}
    -
    -function onGmailError(e) {
    -  goog.log.info(testLogger, 'Gmail error: ' + e.target.getLastError());
    -}
    -
    -
    -function errorGfe() {
    -  var io = getTestIframeIo();
    -  goog.events.listen(io, 'error', onGfeError);
    -  io.send('/iframeio/gfeerror', 'GET');
    -}
    -
    -function onGfeError(e) {
    -  goog.log.info(testLogger, 'GFE error: ' + e.target.getLastError());
    -}
    -
    -
    -
    -function incremental() {
    -  var io = getTestIframeIo();
    -  io.send('/iframeio/incremental', 'GET');
    -}
    -
    -window['P'] = function(iframe, data) {
    -  var iframeIo = goog.net.IframeIo.getInstanceByName(iframe.name);
    -  goog.log.info(testLogger, 'Data recieved - ' + data);
    -};
    -
    -
    -function postForm() {
    -  var io = getTestIframeIo();
    -  goog.events.listen(io, 'complete', onJsonComplete);
    -  io.sendFromForm(document.getElementById('testfrm'));
    -}
    -// UNIT TESTS - to be run via the JsUnit testRunner
    -
    -// TODO(user): How to unit test all of this?  Creating a MockIframe could
    -// help for the IE code path, but since the other browsers require weird
    -// behaviors this becomes very tricky.
    -
    -
    -function testGetForm() {
    -  var frm1 = goog.net.IframeIo.getForm_;
    -  var frm2 = goog.net.IframeIo.getForm_;
    -  assertEquals(frm1, frm2);
    -}
    -
    -
    -function testAddFormInputs() {
    -  var form = document.createElement('form');
    -  goog.net.IframeIo.addFormInputs_(form, {'a': 1, 'b': 2, 'c': 3});
    -  var inputs = form.getElementsByTagName('input');
    -  assertEquals(3, inputs.length);
    -  for (var i = 0; i < inputs.length; i++) {
    -    assertEquals('hidden', inputs[i].type);
    -    var n = inputs[i].name;
    -    assertEquals(n == 'a' ? '1' : n == 'b' ? '2' : '3', inputs[i].value);
    -  }
    -}
    -
    -function testNotIgnoringResponse() {
    -  // This test can't run in IE because we can't forge the check for
    -  // iframe.readyState = 'complete'.
    -  if (goog.userAgent.IE) {
    -    return;
    -  }
    -  var iframeIo = new goog.net.IframeIo();
    -  iframeIo.send('about:blank');
    -  // Simulate the frame finishing loading.
    -  goog.testing.events.fireBrowserEvent(new goog.testing.events.Event(
    -      goog.events.EventType.LOAD, iframeIo.getRequestIframe()));
    -  assertTrue(iframeIo.isComplete());
    -}
    -
    -function testIgnoreResponse() {
    -  var iframeIo = new goog.net.IframeIo();
    -  iframeIo.setIgnoreResponse(true);
    -  iframeIo.send('about:blank');
    -  // Simulate the frame finishing loading.
    -  goog.testing.events.fireBrowserEvent(new goog.testing.events.Event(
    -      goog.events.EventType.LOAD, iframeIo.getRequestIframe()));
    -  // Although the request is complete, the IframeIo isn't paying attention.
    -  assertFalse(iframeIo.isComplete());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/net/iframeloadmonitor.js b/src/database/third_party/closure-library/closure/goog/net/iframeloadmonitor.js
    deleted file mode 100644
    index 6172a601310..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/iframeloadmonitor.js
    +++ /dev/null
    @@ -1,204 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Class that can be used to determine when an iframe is loaded.
    - */
    -
    -goog.provide('goog.net.IframeLoadMonitor');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * The correct way to determine whether a same-domain iframe has completed
    - * loading is different in IE and Firefox.  This class abstracts above these
    - * differences, providing a consistent interface for:
    - * <ol>
    - * <li> Determing if an iframe is currently loaded
    - * <li> Listening for an iframe that is not currently loaded, to finish loading
    - * </ol>
    - *
    - * @param {HTMLIFrameElement} iframe An iframe.
    - * @param {boolean=} opt_hasContent Does the loaded iframe have content.
    - * @extends {goog.events.EventTarget}
    - * @constructor
    - * @final
    - */
    -goog.net.IframeLoadMonitor = function(iframe, opt_hasContent) {
    -  goog.net.IframeLoadMonitor.base(this, 'constructor');
    -
    -  /**
    -   * Iframe whose load state is monitored by this IframeLoadMonitor
    -   * @type {HTMLIFrameElement}
    -   * @private
    -   */
    -  this.iframe_ = iframe;
    -
    -  /**
    -   * Whether or not the loaded iframe has any content.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.hasContent_ = !!opt_hasContent;
    -
    -  /**
    -   * Whether or not the iframe is loaded.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.isLoaded_ = this.isLoadedHelper_();
    -
    -  if (!this.isLoaded_) {
    -    // IE 6 (and lower?) does not reliably fire load events, so listen to
    -    // readystatechange.
    -    // IE 7 does not reliably fire readystatechange events but listening on load
    -    // seems to work just fine.
    -    var isIe6OrLess =
    -        goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('7');
    -    var loadEvtType = isIe6OrLess ?
    -        goog.events.EventType.READYSTATECHANGE : goog.events.EventType.LOAD;
    -    this.onloadListenerKey_ = goog.events.listen(
    -        this.iframe_, loadEvtType, this.handleLoad_, false, this);
    -
    -    // Sometimes we still don't get the event callback, so we'll poll just to
    -    // be safe.
    -    this.intervalId_ = window.setInterval(
    -        goog.bind(this.handleLoad_, this),
    -        goog.net.IframeLoadMonitor.POLL_INTERVAL_MS_);
    -  }
    -};
    -goog.inherits(goog.net.IframeLoadMonitor, goog.events.EventTarget);
    -
    -
    -/**
    - * Event type dispatched by a goog.net.IframeLoadMonitor when it internal iframe
    - * finishes loading for the first time after construction of the
    - * goog.net.IframeLoadMonitor
    - * @type {string}
    - */
    -goog.net.IframeLoadMonitor.LOAD_EVENT = 'ifload';
    -
    -
    -/**
    - * Poll interval for polling iframe load states in milliseconds.
    - * @type {number}
    - * @private
    - */
    -goog.net.IframeLoadMonitor.POLL_INTERVAL_MS_ = 100;
    -
    -
    -/**
    - * Key for iframe load listener, or null if not currently listening on the
    - * iframe for a load event.
    - * @type {goog.events.Key}
    - * @private
    - */
    -goog.net.IframeLoadMonitor.prototype.onloadListenerKey_ = null;
    -
    -
    -/**
    - * Returns whether or not the iframe is loaded.
    - * @return {boolean} whether or not the iframe is loaded.
    - */
    -goog.net.IframeLoadMonitor.prototype.isLoaded = function() {
    -  return this.isLoaded_;
    -};
    -
    -
    -/**
    - * Stops the poll timer if this IframeLoadMonitor is currently polling.
    - * @private
    - */
    -goog.net.IframeLoadMonitor.prototype.maybeStopTimer_ = function() {
    -  if (this.intervalId_) {
    -    window.clearInterval(this.intervalId_);
    -    this.intervalId_ = null;
    -  }
    -};
    -
    -
    -/**
    - * Returns the iframe whose load state this IframeLoader monitors.
    - * @return {HTMLIFrameElement} the iframe whose load state this IframeLoader
    - *     monitors.
    - */
    -goog.net.IframeLoadMonitor.prototype.getIframe = function() {
    -  return this.iframe_;
    -};
    -
    -
    -/** @override */
    -goog.net.IframeLoadMonitor.prototype.disposeInternal = function() {
    -  delete this.iframe_;
    -  this.maybeStopTimer_();
    -  goog.events.unlistenByKey(this.onloadListenerKey_);
    -  goog.net.IframeLoadMonitor.superClass_.disposeInternal.call(this);
    -};
    -
    -
    -/**
    - * Returns whether or not the iframe is loaded.  Determines this by inspecting
    - * browser dependent properties of the iframe.
    - * @return {boolean} whether or not the iframe is loaded.
    - * @private
    - */
    -goog.net.IframeLoadMonitor.prototype.isLoadedHelper_ = function() {
    -  var isLoaded = false;
    -  /** @preserveTry */
    -  try {
    -    // IE versions before IE11 will reliably have readyState set to complete if
    -    // the iframe is loaded. For everything else, the iframe is loaded if there
    -    // is a body and if the body should have content the firstChild exists.
    -    // Firefox can fire the LOAD event and then a few hundred ms later replace
    -    // the contentDocument once the content is loaded.
    -    if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('11')) {
    -      isLoaded = this.iframe_.readyState == 'complete';
    -    } else {
    -      isLoaded = !!goog.dom.getFrameContentDocument(this.iframe_).body &&
    -          (!this.hasContent_ ||
    -          !!goog.dom.getFrameContentDocument(this.iframe_).body.firstChild);
    -    }
    -  } catch (e) {
    -    // Ignore these errors. This just means that the iframe is not loaded
    -    // IE will throw error reading readyState if the iframe is not appended
    -    // to the dom yet.
    -    // Firefox will throw error getting the iframe body if the iframe is not
    -    // fully loaded.
    -  }
    -  return isLoaded;
    -};
    -
    -
    -/**
    - * Handles an event indicating that the loading status of the iframe has
    - * changed.  In Firefox this is a goog.events.EventType.LOAD event, in IE
    - * this is a goog.events.EventType.READYSTATECHANGED
    - * @private
    - */
    -goog.net.IframeLoadMonitor.prototype.handleLoad_ = function() {
    -  // Only do the handler if the iframe is loaded.
    -  if (this.isLoadedHelper_()) {
    -    this.maybeStopTimer_();
    -    goog.events.unlistenByKey(this.onloadListenerKey_);
    -    this.onloadListenerKey_ = null;
    -    this.isLoaded_ = true;
    -    this.dispatchEvent(goog.net.IframeLoadMonitor.LOAD_EVENT);
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/net/iframeloadmonitor_test.html b/src/database/third_party/closure-library/closure/goog/net/iframeloadmonitor_test.html
    deleted file mode 100644
    index 81cf981931a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/iframeloadmonitor_test.html
    +++ /dev/null
    @@ -1,26 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.net.IframeLoadMonitor
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.net.IframeLoadMonitorTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="frame_parent">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/iframeloadmonitor_test.js b/src/database/third_party/closure-library/closure/goog/net/iframeloadmonitor_test.js
    deleted file mode 100644
    index 4c7850f2831..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/iframeloadmonitor_test.js
    +++ /dev/null
    @@ -1,105 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.net.IframeLoadMonitorTest');
    -goog.setTestOnly('goog.net.IframeLoadMonitorTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.net.IframeLoadMonitor');
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.jsunit');
    -
    -var TEST_FRAME_SRCS = ['iframeloadmonitor_test_frame.html',
    -  'iframeloadmonitor_test_frame2.html',
    -  'iframeloadmonitor_test_frame3.html'];
    -
    -// Create a new test case.
    -var iframeLoaderTestCase = new goog.testing.AsyncTestCase(document.title);
    -iframeLoaderTestCase.stepTimeout = 4 * 1000;
    -
    -// Array holding all iframe load monitors.
    -iframeLoaderTestCase.iframeLoadMonitors_ = [];
    -
    -// How many single frames finished loading
    -iframeLoaderTestCase.singleComplete_ = 0;
    -
    -
    -/**
    - * Sets up the test environment, adds tests and sets up the worker pools.
    - * @this {goog.testing.AsyncTestCase}
    - */
    -iframeLoaderTestCase.setUpPage = function() {
    -  this.log('Setting tests up');
    -  iframeLoaderTestCase.waitForAsync('loading iframes');
    -
    -  var dom = goog.dom.getDomHelper();
    -
    -  // Load single frame
    -  var frame = dom.createDom('iframe');
    -  this.iframeLoadMonitors_.push(new goog.net.IframeLoadMonitor(frame));
    -  goog.events.listen(this.iframeLoadMonitors_[0],
    -      goog.net.IframeLoadMonitor.LOAD_EVENT, this);
    -  var frameParent = dom.getElement('frame_parent');
    -  dom.appendChild(frameParent, frame);
    -  this.log('Loading frame at: ' + TEST_FRAME_SRCS[0]);
    -  frame.src = TEST_FRAME_SRCS[0];
    -
    -  // Load single frame with content check
    -  var frame1 = dom.createDom('iframe');
    -  this.iframeLoadMonitors_.push(new goog.net.IframeLoadMonitor(frame1, true));
    -  goog.events.listen(this.iframeLoadMonitors_[1],
    -      goog.net.IframeLoadMonitor.LOAD_EVENT, this);
    -  var frameParent = dom.getElement('frame_parent');
    -  dom.appendChild(frameParent, frame1);
    -  this.log('Loading frame with content check at: ' + TEST_FRAME_SRCS[0]);
    -  frame1.src = TEST_FRAME_SRCS[0];
    -};
    -
    -
    -/**
    - * Handles any events fired
    - * @this {goog.testing.AsyncTestCase}
    - */
    -iframeLoaderTestCase.handleEvent = function(e) {
    -  this.log('handleEvent, type: ' + e.type);
    -  if (e.type == goog.net.IframeLoadMonitor.LOAD_EVENT) {
    -    this.singleComplete_++;
    -    this.callbacksComplete();
    -  }
    -};
    -
    -
    -/**
    - * Checks if all the load callbacks are done
    - * @this {goog.testing.AsyncTestCase}
    - */
    -iframeLoaderTestCase.callbacksComplete = function() {
    -  if (this.singleComplete_ == 2) {
    -    iframeLoaderTestCase.continueTesting();
    -  }
    -};
    -
    -
    -/** Tests the results. */
    -iframeLoaderTestCase.addNewTest('testResults', function() {
    -  this.log('getting test results');
    -  for (var i = 0; i < this.iframeLoadMonitors_.length; i++) {
    -    assertTrue(this.iframeLoadMonitors_[i].isLoaded());
    -  }
    -});
    -
    -
    -/** Standalone Closure Test Runner. */
    -G_testRunner.initialize(iframeLoaderTestCase);
    diff --git a/src/database/third_party/closure-library/closure/goog/net/iframeloadmonitor_test_frame.html b/src/database/third_party/closure-library/closure/goog/net/iframeloadmonitor_test_frame.html
    deleted file mode 100644
    index 9fbcbfa9ee0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/iframeloadmonitor_test_frame.html
    +++ /dev/null
    @@ -1,12 +0,0 @@
    -<html>
    -<!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head><title>Iframe Load Test Frame 1</title></head>
    -<body>
    -  Iframe Load Test Frame 1
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/iframeloadmonitor_test_frame2.html b/src/database/third_party/closure-library/closure/goog/net/iframeloadmonitor_test_frame2.html
    deleted file mode 100644
    index 7d436e253c4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/iframeloadmonitor_test_frame2.html
    +++ /dev/null
    @@ -1,12 +0,0 @@
    -<html>
    -<!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head><title>Iframe Load Test Frame 2</title></head>
    -<body>
    -  Iframe Load Test Frame 2
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/iframeloadmonitor_test_frame3.html b/src/database/third_party/closure-library/closure/goog/net/iframeloadmonitor_test_frame3.html
    deleted file mode 100644
    index 910b639d403..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/iframeloadmonitor_test_frame3.html
    +++ /dev/null
    @@ -1,12 +0,0 @@
    -<html>
    -<!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head><title>Iframe Load Test Frame 3</title></head>
    -<body>
    -  Iframe Load Test Frame 3
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/imageloader.js b/src/database/third_party/closure-library/closure/goog/net/imageloader.js
    deleted file mode 100644
    index a9f93eee43f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/imageloader.js
    +++ /dev/null
    @@ -1,337 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Image loader utility class.  Useful when an application needs
    - * to preload multiple images, for example so they can be sized.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.net.ImageLoader');
    -
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -goog.require('goog.net.EventType');
    -goog.require('goog.object');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Image loader utility class.  Raises a {@link goog.events.EventType.LOAD}
    - * event for each image loaded, with an {@link Image} object as the target of
    - * the event, normalized to have {@code naturalHeight} and {@code naturalWidth}
    - * attributes.
    - *
    - * To use this class, run:
    - *
    - * <pre>
    - *   var imageLoader = new goog.net.ImageLoader();
    - *   goog.events.listen(imageLoader, goog.net.EventType.COMPLETE,
    - *       function(e) { ... });
    - *   imageLoader.addImage("image_id", "http://path/to/image.gif");
    - *   imageLoader.start();
    - * </pre>
    - *
    - * The start() method must be called to start image loading.  Images can be
    - * added and removed after loading has started, but only those images added
    - * before start() was called will be loaded until start() is called again.
    - * A goog.net.EventType.COMPLETE event will be dispatched only once all
    - * outstanding images have completed uploading.
    - *
    - * @param {Element=} opt_parent An optional parent element whose document object
    - *     should be used to load images.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - * @final
    - */
    -goog.net.ImageLoader = function(opt_parent) {
    -  goog.events.EventTarget.call(this);
    -
    -  /**
    -   * Map of image IDs to their request including their image src, used to keep
    -   * track of the images to load.  Once images have started loading, they're
    -   * removed from this map.
    -   * @type {!Object<!goog.net.ImageLoader.ImageRequest_>}
    -   * @private
    -   */
    -  this.imageIdToRequestMap_ = {};
    -
    -  /**
    -   * Map of image IDs to their image element, used only for images that are in
    -   * the process of loading.  Used to clean-up event listeners and to know
    -   * when we've completed loading images.
    -   * @type {!Object<string, !Element>}
    -   * @private
    -   */
    -  this.imageIdToImageMap_ = {};
    -
    -  /**
    -   * Event handler object, used to keep track of onload and onreadystatechange
    -   * listeners.
    -   * @type {!goog.events.EventHandler<!goog.net.ImageLoader>}
    -   * @private
    -   */
    -  this.handler_ = new goog.events.EventHandler(this);
    -
    -  /**
    -   * The parent element whose document object will be used to load images.
    -   * Useful if you want to load the images from a window other than the current
    -   * window in order to control the Referer header sent when the image is
    -   * loaded.
    -   * @type {Element|undefined}
    -   * @private
    -   */
    -  this.parent_ = opt_parent;
    -};
    -goog.inherits(goog.net.ImageLoader, goog.events.EventTarget);
    -
    -
    -/**
    - * The type of image request to dispatch, if this is a CORS-enabled image
    - * request. CORS-enabled images can be reused in canvas elements without them
    - * being tainted. The server hosting the image should include the appropriate
    - * CORS header.
    - * @see https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image
    - * @enum {string}
    - */
    -goog.net.ImageLoader.CorsRequestType = {
    -  ANONYMOUS: 'anonymous',
    -  USE_CREDENTIALS: 'use-credentials'
    -};
    -
    -
    -/**
    - * Describes a request for an image. This includes its URL and its CORS-request
    - * type, if any.
    - * @typedef {{
    - *   src: string,
    - *   corsRequestType: ?goog.net.ImageLoader.CorsRequestType
    - * }}
    - * @private
    - */
    -goog.net.ImageLoader.ImageRequest_;
    -
    -
    -/**
    - * An array of event types to listen to on images.  This is browser dependent.
    - *
    - * For IE 10 and below, Internet Explorer doesn't reliably raise LOAD events
    - * on images, so we must use READY_STATE_CHANGE.  Since the image is cached
    - * locally, IE won't fire the LOAD event while the onreadystate event is fired
    - * always. On the other hand, the ERROR event is always fired whenever the image
    - * is not loaded successfully no matter whether it's cached or not.
    - *
    - * In IE 11, onreadystatechange is removed and replaced with onload:
    - *
    - * http://msdn.microsoft.com/en-us/library/ie/ms536957(v=vs.85).aspx
    - * http://msdn.microsoft.com/en-us/library/ie/bg182625(v=vs.85).aspx
    - *
    - * @type {!Array<string>}
    - * @private
    - */
    -goog.net.ImageLoader.IMAGE_LOAD_EVENTS_ = [
    -  goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('11') ?
    -      goog.net.EventType.READY_STATE_CHANGE :
    -      goog.events.EventType.LOAD,
    -  goog.net.EventType.ABORT,
    -  goog.net.EventType.ERROR
    -];
    -
    -
    -/**
    - * Adds an image to the image loader, and associates it with the given ID
    - * string.  If an image with that ID already exists, it is silently replaced.
    - * When the image in question is loaded, the target of the LOAD event will be
    - * an {@code Image} object with {@code id} and {@code src} attributes based on
    - * these arguments.
    - * @param {string} id The ID of the image to load.
    - * @param {string|Image} image Either the source URL of the image or the HTML
    - *     image element itself (or any object with a {@code src} property, really).
    - * @param {!goog.net.ImageLoader.CorsRequestType=} opt_corsRequestType The type
    - *     of CORS request to use, if any.
    - */
    -goog.net.ImageLoader.prototype.addImage = function(
    -    id, image, opt_corsRequestType) {
    -  var src = goog.isString(image) ? image : image.src;
    -  if (src) {
    -    // For now, we just store the source URL for the image.
    -    this.imageIdToRequestMap_[id] = {
    -      src: src,
    -      corsRequestType: goog.isDef(opt_corsRequestType) ?
    -          opt_corsRequestType : null
    -    };
    -  }
    -};
    -
    -
    -/**
    - * Removes the image associated with the given ID string from the image loader.
    - * If the image was previously loading, removes any listeners for its events
    - * and dispatches a COMPLETE event if all remaining images have now completed.
    - * @param {string} id The ID of the image to remove.
    - */
    -goog.net.ImageLoader.prototype.removeImage = function(id) {
    -  delete this.imageIdToRequestMap_[id];
    -
    -  var image = this.imageIdToImageMap_[id];
    -  if (image) {
    -    delete this.imageIdToImageMap_[id];
    -
    -    // Stop listening for events on the image.
    -    this.handler_.unlisten(image, goog.net.ImageLoader.IMAGE_LOAD_EVENTS_,
    -        this.onNetworkEvent_);
    -
    -    // If this was the last image, raise a COMPLETE event.
    -    if (goog.object.isEmpty(this.imageIdToImageMap_) &&
    -        goog.object.isEmpty(this.imageIdToRequestMap_)) {
    -      this.dispatchEvent(goog.net.EventType.COMPLETE);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Starts loading all images in the image loader in parallel.  Raises a LOAD
    - * event each time an image finishes loading, and a COMPLETE event after all
    - * images have finished loading.
    - */
    -goog.net.ImageLoader.prototype.start = function() {
    -  // Iterate over the keys, rather than the full object, to essentially clone
    -  // the initial queued images in case any event handlers decide to add more
    -  // images before this loop has finished executing.
    -  var imageIdToRequestMap = this.imageIdToRequestMap_;
    -  goog.array.forEach(goog.object.getKeys(imageIdToRequestMap),
    -      function(id) {
    -        var imageRequest = imageIdToRequestMap[id];
    -        if (imageRequest) {
    -          delete imageIdToRequestMap[id];
    -          this.loadImage_(imageRequest, id);
    -        }
    -      }, this);
    -};
    -
    -
    -/**
    - * Creates an {@code Image} object with the specified ID and source URL, and
    - * listens for network events raised as the image is loaded.
    - * @param {!goog.net.ImageLoader.ImageRequest_} imageRequest The request data.
    - * @param {string} id The unique ID of the image to load.
    - * @private
    - */
    -goog.net.ImageLoader.prototype.loadImage_ = function(imageRequest, id) {
    -  if (this.isDisposed()) {
    -    // When loading an image in IE7 (and maybe IE8), the error handler
    -    // may fire before we yield JS control. If the error handler
    -    // dispose the ImageLoader, this method will throw exception.
    -    return;
    -  }
    -
    -  var image;
    -  if (this.parent_) {
    -    var dom = goog.dom.getDomHelper(this.parent_);
    -    image = dom.createDom('img');
    -  } else {
    -    image = new Image();
    -  }
    -
    -  if (imageRequest.corsRequestType) {
    -    image.crossOrigin = imageRequest.corsRequestType;
    -  }
    -
    -  this.handler_.listen(image, goog.net.ImageLoader.IMAGE_LOAD_EVENTS_,
    -      this.onNetworkEvent_);
    -  this.imageIdToImageMap_[id] = image;
    -
    -  image.id = id;
    -  image.src = imageRequest.src;
    -};
    -
    -
    -/**
    - * Handles net events (READY_STATE_CHANGE, LOAD, ABORT, and ERROR).
    - * @param {goog.events.Event} evt The network event to handle.
    - * @private
    - */
    -goog.net.ImageLoader.prototype.onNetworkEvent_ = function(evt) {
    -  var image = /** @type {Element} */ (evt.currentTarget);
    -
    -  if (!image) {
    -    return;
    -  }
    -
    -  if (evt.type == goog.net.EventType.READY_STATE_CHANGE) {
    -    // This implies that the user agent is IE; see loadImage_().
    -    // Noe that this block is used to check whether the image is ready to
    -    // dispatch the COMPLETE event.
    -    if (image.readyState == goog.net.EventType.COMPLETE) {
    -      // This is the IE equivalent of a LOAD event.
    -      evt.type = goog.events.EventType.LOAD;
    -    } else {
    -      // This may imply that the load failed.
    -      // Note that the image has only the following states:
    -      //   * uninitialized
    -      //   * loading
    -      //   * complete
    -      // When the ERROR or the ABORT event is fired, the readyState
    -      // will be either uninitialized or loading and we'd ignore those states
    -      // since they will be handled separately (eg: evt.type = 'ERROR').
    -
    -      // Notes from MSDN : The states through which an object passes are
    -      // determined by that object. An object can skip certain states
    -      // (for example, interactive) if the state does not apply to that object.
    -      // see http://msdn.microsoft.com/en-us/library/ms534359(VS.85).aspx
    -
    -      // The image is not loaded, ignore.
    -      return;
    -    }
    -  }
    -
    -  // Add natural width/height properties for non-Gecko browsers.
    -  if (typeof image.naturalWidth == 'undefined') {
    -    if (evt.type == goog.events.EventType.LOAD) {
    -      image.naturalWidth = image.width;
    -      image.naturalHeight = image.height;
    -    } else {
    -      // This implies that the image fails to be loaded.
    -      image.naturalWidth = 0;
    -      image.naturalHeight = 0;
    -    }
    -  }
    -
    -  // Redispatch the event on behalf of the image. Note that the external
    -  // listener may dispose this instance.
    -  this.dispatchEvent({type: evt.type, target: image});
    -
    -  if (this.isDisposed()) {
    -    // If instance was disposed by listener, exit this function.
    -    return;
    -  }
    -
    -  this.removeImage(image.id);
    -};
    -
    -
    -/** @override */
    -goog.net.ImageLoader.prototype.disposeInternal = function() {
    -  delete this.imageIdToRequestMap_;
    -  delete this.imageIdToImageMap_;
    -  goog.dispose(this.handler_);
    -
    -  goog.net.ImageLoader.superClass_.disposeInternal.call(this);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/net/imageloader_test.html b/src/database/third_party/closure-library/closure/goog/net/imageloader_test.html
    deleted file mode 100644
    index 7a816c21ff0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/imageloader_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -  Author: chrishenry@google.com (Chris Henry)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.net.ImageLoader
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.net.ImageLoaderTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/imageloader_test.js b/src/database/third_party/closure-library/closure/goog/net/imageloader_test.js
    deleted file mode 100644
    index 2aa9eee9ca2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/imageloader_test.js
    +++ /dev/null
    @@ -1,330 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.net.ImageLoaderTest');
    -goog.setTestOnly('goog.net.ImageLoaderTest');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.array');
    -goog.require('goog.dispose');
    -goog.require('goog.events');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventType');
    -goog.require('goog.net.EventType');
    -goog.require('goog.net.ImageLoader');
    -goog.require('goog.object');
    -goog.require('goog.string');
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -
    -var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall(document.title);
    -
    -// Set the AsyncTestCase timeout to larger value to allow more time
    -// for images to load.
    -asyncTestCase.stepTimeout = 5000;
    -
    -
    -var TEST_EVENT_TYPES = [
    -  goog.events.EventType.LOAD,
    -  goog.net.EventType.COMPLETE,
    -  goog.net.EventType.ERROR
    -];
    -
    -
    -/**
    - * Mapping from test image file name to:
    - * [expected width, expected height, expected event to be fired].
    - */
    -var TEST_IMAGES = {
    -  'imageloader_testimg1.gif': [20, 20, goog.events.EventType.LOAD],
    -  'imageloader_testimg2.gif': [20, 20, goog.events.EventType.LOAD],
    -  'imageloader_testimg3.gif': [32, 32, goog.events.EventType.LOAD],
    -
    -  'this-is-not-image-1.gif': [0, 0, goog.net.EventType.ERROR],
    -  'this-is-not-image-2.gif': [0, 0, goog.net.EventType.ERROR]
    -};
    -
    -
    -var startTime;
    -var loader;
    -
    -
    -function setUp() {
    -  startTime = goog.now();
    -
    -  loader = new goog.net.ImageLoader();
    -
    -  // Adds test images to the loader.
    -  var i = 0;
    -  for (var key in TEST_IMAGES) {
    -    var imageId = 'img_' + i++;
    -    loader.addImage(imageId, key);
    -  }
    -}
    -
    -
    -function tearDown() {
    -  goog.dispose(loader);
    -}
    -
    -
    -/**
    - * Tests loading image and disposing before loading completes.
    - */
    -function testDisposeInTheMiddleOfLoadingWorks() {
    -  goog.events.listen(loader, TEST_EVENT_TYPES,
    -      goog.partial(handleDisposalImageLoaderEvent, loader));
    -  // waitForAsync before starting loader just in case
    -  // handleDisposalImageLoaderEvent is called from within loader.start
    -  // (before we yield control). This may happen in IE7/IE8.
    -  asyncTestCase.waitForAsync('Waiting for loader handler to fire.');
    -  loader.start();
    -}
    -
    -
    -function handleDisposalImageLoaderEvent(loader, e) {
    -  assertFalse('Handler is still invoked after loader is disposed.',
    -      loader.isDisposed());
    -
    -  switch (e.type) {
    -    case goog.net.EventType.COMPLETE:
    -      fail('This test should never get COMPLETE event.');
    -      return;
    -
    -    case goog.events.EventType.LOAD:
    -    case goog.net.EventType.ERROR:
    -      loader.dispose();
    -      break;
    -  }
    -
    -  // Make sure that handler is never called again after disposal before
    -  // marking test as successful.
    -  asyncTestCase.waitForAsync('Wait to ensure that COMPLETE is never fired');
    -  goog.Timer.callOnce(function() {
    -    asyncTestCase.continueTesting();
    -  }, 500);
    -}
    -
    -
    -/**
    - * Tests loading of images until completion.
    - */
    -function testLoadingUntilCompletion() {
    -  var results = {};
    -  goog.events.listen(loader, TEST_EVENT_TYPES,
    -      function(e) {
    -        switch (e.type) {
    -          case goog.events.EventType.LOAD:
    -            var image = e.target;
    -            results[image.src.substring(image.src.lastIndexOf('/') + 1)] =
    -                [image.naturalWidth, image.naturalHeight, e.type];
    -            return;
    -
    -          case goog.net.EventType.ERROR:
    -            var image = e.target;
    -            results[image.src.substring(image.src.lastIndexOf('/') + 1)] =
    -                [image.naturalWidth, image.naturalHeight, e.type];
    -            return;
    -
    -          case goog.net.EventType.COMPLETE:
    -            // Test completes successfully.
    -            asyncTestCase.continueTesting();
    -
    -            assertImagesAreCorrect(results);
    -            return;
    -        }
    -      });
    -
    -  // waitForAsync before starting loader just in case handleImageLoaderEvent
    -  // is called from within loader.start (before we yield control).
    -  // This may happen in IE7/IE8.
    -  asyncTestCase.waitForAsync('Waiting for loader handler to fire.');
    -  loader.start();
    -}
    -
    -
    -function assertImagesAreCorrect(results) {
    -  assertEquals(
    -      goog.object.getCount(TEST_IMAGES), goog.object.getCount(results));
    -  goog.object.forEach(TEST_IMAGES, function(value, key) {
    -    // Check if fires the COMPLETE event.
    -    assertTrue('Image is not loaded completely.', key in results);
    -
    -    var image = results[key];
    -
    -    // Check image size.
    -    assertEquals('Image width is not correct', value[0], image[0]);
    -    assertEquals('Image length is not correct', value[1], image[1]);
    -
    -    // Check if fired the correct event.
    -    assertEquals('Event *' + value[2] + '* must be fired', value[2], image[2]);
    -  });
    -}
    -
    -
    -/**
    - * Overrides the loader's loadImage_ method so that it dispatches an image
    - * loaded event immediately, causing any event listners to receive them
    - * synchronously.  This allows tests to assume synchronous execution.
    - */
    -function makeLoaderSynchronous(loader) {
    -  var originalLoadImage = loader.loadImage_;
    -  loader.loadImage_ = function(request, id) {
    -    originalLoadImage.call(this, request, id);
    -
    -    var event = new goog.events.Event(goog.events.EventType.LOAD);
    -    event.currentTarget = this.imageIdToImageMap_[id];
    -    loader.onNetworkEvent_(event);
    -  };
    -
    -  // Make listen() a no-op.
    -  loader.handler_.listen = goog.nullFunction;
    -}
    -
    -
    -/**
    - * Verifies that if an additional image is added after start() was called, but
    - * before COMPLETE was dispatched, no COMPLETE event is sent.  Verifies COMPLETE
    - * is finally sent when .start() is called again and all images have now
    - * completed loading.
    - */
    -function testImagesAddedAfterStart() {
    -  // Use synchronous image loading.
    -  makeLoaderSynchronous(loader);
    -
    -  // Add another image once the first images finishes loading.
    -  goog.events.listenOnce(loader, goog.events.EventType.LOAD, function() {
    -    loader.addImage('extra_image', 'extra_image.gif');
    -  });
    -
    -  // Keep track of the total # of image loads.
    -  var loadRecordFn = goog.testing.recordFunction();
    -  goog.events.listen(loader, goog.events.EventType.LOAD, loadRecordFn);
    -
    -  // Keep track of how many times COMPLETE was dispatched.
    -  var completeRecordFn = goog.testing.recordFunction();
    -  goog.events.listen(loader, goog.net.EventType.COMPLETE, completeRecordFn);
    -
    -  // Start testing.
    -  loader.start();
    -  assertEquals(
    -      'COMPLETE event should not have been dispatched yet: An image was ' +
    -          'added after the initial batch was started.',
    -      0, completeRecordFn.getCallCount());
    -  assertEquals('Just the test images should have loaded',
    -      goog.object.getCount(TEST_IMAGES), loadRecordFn.getCallCount());
    -
    -  loader.start();
    -  assertEquals('COMPLETE should have been dispatched once.',
    -      1, completeRecordFn.getCallCount());
    -  assertEquals('All images should have been loaded',
    -      goog.object.getCount(TEST_IMAGES) + 1, loadRecordFn.getCallCount());
    -}
    -
    -
    -/**
    - * Verifies that more images can be added after an upload starts, and start()
    - * can be called for them, resulting in just one COMPLETE event once all the
    - * images have completed.
    - */
    -function testImagesAddedAndStartedAfterStart() {
    -  // Use synchronous image loading.
    -  makeLoaderSynchronous(loader);
    -
    -  // Keep track of the total # of image loads.
    -  var loadRecordFn = goog.testing.recordFunction();
    -  goog.events.listen(loader, goog.events.EventType.LOAD, loadRecordFn);
    -
    -  // Add more images once the first images finishes loading, and call start()
    -  // to get them going.
    -  goog.events.listenOnce(loader, goog.events.EventType.LOAD, function(e) {
    -    loader.addImage('extra_image', 'extra_image.gif');
    -    loader.addImage('extra_image2', 'extra_image2.gif');
    -    loader.start();
    -  });
    -
    -  // Keep track of how many times COMPLETE was dispatched.
    -  var completeRecordFn = goog.testing.recordFunction();
    -  goog.events.listen(loader, goog.net.EventType.COMPLETE, completeRecordFn);
    -
    -  // Start testing.  Make sure all 7 images loaded.
    -  loader.start();
    -  assertEquals('COMPLETE should have been dispatched once.',
    -      1, completeRecordFn.getCallCount());
    -  assertEquals('All images should have been loaded',
    -      goog.object.getCount(TEST_IMAGES) + 2, loadRecordFn.getCallCount());
    -}
    -
    -
    -/**
    - * Verifies that if images are removed after loading has started, COMPLETE
    - * is dispatched once the remaining images have finished.
    - */
    -function testImagesRemovedAfterStart() {
    -  // Use synchronous image loading.
    -  makeLoaderSynchronous(loader);
    -
    -  // Remove 2 images once the first image finishes loading.
    -  goog.events.listenOnce(loader, goog.events.EventType.LOAD, function(e) {
    -    loader.removeImage(
    -        goog.array.peek(goog.object.getKeys(this.imageIdToRequestMap_)));
    -    loader.removeImage(
    -        goog.array.peek(goog.object.getKeys(this.imageIdToRequestMap_)));
    -  });
    -
    -  // Keep track of the total # of image loads.
    -  var loadRecordFn = goog.testing.recordFunction();
    -  goog.events.listen(loader, goog.events.EventType.LOAD, loadRecordFn);
    -
    -  // Keep track of how many times COMPLETE was dispatched.
    -  var completeRecordFn = goog.testing.recordFunction();
    -  goog.events.listen(loader, goog.net.EventType.COMPLETE, completeRecordFn);
    -
    -  // Start testing.  Make sure only the 3 images remaining loaded.
    -  loader.start();
    -  assertEquals('COMPLETE should have been dispatched once.',
    -      1, completeRecordFn.getCallCount());
    -  assertEquals('All images should have been loaded',
    -      goog.object.getCount(TEST_IMAGES) - 2, loadRecordFn.getCallCount());
    -}
    -
    -
    -/**
    - * Verifies that the correct image attribute is set when using CORS requests.
    - */
    -function testSetsCorsAttribute() {
    -  // Use synchronous image loading.
    -  makeLoaderSynchronous(loader);
    -
    -  // Verify the crossOrigin attribute of the requested images.
    -  goog.events.listen(loader, goog.events.EventType.LOAD, function(e) {
    -    var image = e.target;
    -    if (image.id == 'cors_request') {
    -      assertEquals(
    -          'CORS requested image should have a crossOrigin attribute set',
    -          'anonymous', image.crossOrigin);
    -    } else {
    -      assertTrue(
    -          'Non-CORS requested images should not have a crossOrigin attribute',
    -          goog.string.isEmptyOrWhitespace(goog.string.makeSafe(image.crossOrigin)));
    -    }
    -  });
    -
    -  // Make a new request for one of the images, this time using CORS.
    -  var srcs = goog.object.getKeys(TEST_IMAGES);
    -  loader.addImage(
    -      'cors_request', srcs[0], goog.net.ImageLoader.CorsRequestType.ANONYMOUS);
    -  loader.start();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/net/imageloader_testimg1.gif b/src/database/third_party/closure-library/closure/goog/net/imageloader_testimg1.gif
    deleted file mode 100644
    index 18b295b3fce..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/net/imageloader_testimg1.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/net/imageloader_testimg2.gif b/src/database/third_party/closure-library/closure/goog/net/imageloader_testimg2.gif
    deleted file mode 100644
    index 691683264d4..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/net/imageloader_testimg2.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/net/imageloader_testimg3.gif b/src/database/third_party/closure-library/closure/goog/net/imageloader_testimg3.gif
    deleted file mode 100644
    index fe5e37883e1..00000000000
    Binary files a/src/database/third_party/closure-library/closure/goog/net/imageloader_testimg3.gif and /dev/null differ
    diff --git a/src/database/third_party/closure-library/closure/goog/net/ipaddress.js b/src/database/third_party/closure-library/closure/goog/net/ipaddress.js
    deleted file mode 100644
    index 24b93c82f7a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/ipaddress.js
    +++ /dev/null
    @@ -1,509 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview This file contains classes to handle IPv4 and IPv6 addresses.
    - * This implementation is mostly based on Google's project:
    - * http://code.google.com/p/ipaddr-py/.
    - *
    - */
    -
    -goog.provide('goog.net.IpAddress');
    -goog.provide('goog.net.Ipv4Address');
    -goog.provide('goog.net.Ipv6Address');
    -
    -goog.require('goog.array');
    -goog.require('goog.math.Integer');
    -goog.require('goog.object');
    -goog.require('goog.string');
    -
    -
    -
    -/**
    - * Abstract class defining an IP Address.
    - *
    - * Please use goog.net.IpAddress static methods or
    - * goog.net.Ipv4Address/Ipv6Address classes.
    - *
    - * @param {!goog.math.Integer} address The Ip Address.
    - * @param {number} version The version number (4, 6).
    - * @constructor
    - */
    -goog.net.IpAddress = function(address, version) {
    -  /**
    -   * The IP Address.
    -   * @type {!goog.math.Integer}
    -   * @private
    -   */
    -  this.ip_ = address;
    -
    -  /**
    -   * The IP Address version.
    -   * @type {number}
    -   * @private
    -   */
    -  this.version_ = version;
    -
    -};
    -
    -
    -/**
    - * @return {number} The IP Address version.
    - */
    -goog.net.IpAddress.prototype.getVersion = function() {
    -  return this.version_;
    -};
    -
    -
    -/**
    - * @param {!goog.net.IpAddress} other The other IP Address.
    - * @return {boolean} true if the IP Addresses are equal.
    - */
    -goog.net.IpAddress.prototype.equals = function(other) {
    -  return (this.version_ == other.getVersion() &&
    -          this.ip_.equals(other.toInteger()));
    -};
    -
    -
    -/**
    - * @return {!goog.math.Integer} The IP Address, as an Integer.
    - */
    -goog.net.IpAddress.prototype.toInteger = function() {
    -  return /** @type {!goog.math.Integer} */ (goog.object.clone(this.ip_));
    -};
    -
    -
    -/**
    - * @return {string} The IP Address, as an URI string following RFC 3986.
    - */
    -goog.net.IpAddress.prototype.toUriString = goog.abstractMethod;
    -
    -
    -/**
    - * @return {string} The IP Address, as a string.
    - * @override
    - */
    -goog.net.IpAddress.prototype.toString = goog.abstractMethod;
    -
    -
    -/**
    - * Parses an IP Address in a string.
    - * If the string is malformed, the function will simply return null
    - * instead of raising an exception.
    - *
    - * @param {string} address The IP Address.
    - * @see {goog.net.Ipv4Address}
    - * @see {goog.net.Ipv6Address}
    - * @return {goog.net.IpAddress} The IP Address or null.
    - */
    -goog.net.IpAddress.fromString = function(address) {
    -  try {
    -    if (address.indexOf(':') != -1) {
    -      return new goog.net.Ipv6Address(address);
    -    }
    -
    -    return new goog.net.Ipv4Address(address);
    -  } catch (e) {
    -    // Both constructors raise exception if the address is malformed (ie.
    -    // invalid). The user of this function should not care about catching
    -    // the exception, espcially if it's used to validate an user input.
    -    return null;
    -  }
    -};
    -
    -
    -/**
    - * Tries to parse a string represented as a host portion of an URI.
    - * See RFC 3986 for more details on IPv6 addresses inside URI.
    - * If the string is malformed, the function will simply return null
    - * instead of raising an exception.
    - *
    - * @param {string} address A RFC 3986 encoded IP address.
    - * @see {goog.net.Ipv4Address}
    - * @see {goog.net.Ipv6Address}
    - * @return {goog.net.IpAddress} The IP Address.
    - */
    -goog.net.IpAddress.fromUriString = function(address) {
    -  try {
    -    if (goog.string.startsWith(address, '[') &&
    -        goog.string.endsWith(address, ']')) {
    -      return new goog.net.Ipv6Address(
    -          address.substring(1, address.length - 1));
    -    }
    -
    -    return new goog.net.Ipv4Address(address);
    -  } catch (e) {
    -    // Both constructors raise exception if the address is malformed (ie.
    -    // invalid). The user of this function should not care about catching
    -    // the exception, espcially if it's used to validate an user input.
    -    return null;
    -  }
    -};
    -
    -
    -
    -/**
    - * Takes a string or a number and returns a IPv4 Address.
    - *
    - * This constructor accepts strings and instance of goog.math.Integer.
    - * If you pass a goog.math.Integer, make sure that its sign is set to positive.
    - * @param {(string|!goog.math.Integer)} address The address to store.
    - * @extends {goog.net.IpAddress}
    - * @constructor
    - * @final
    - */
    -goog.net.Ipv4Address = function(address) {
    -  var ip = goog.math.Integer.ZERO;
    -  if (address instanceof goog.math.Integer) {
    -    if (address.getSign() != 0 ||
    -        address.lessThan(goog.math.Integer.ZERO) ||
    -        address.greaterThan(goog.net.Ipv4Address.MAX_ADDRESS_)) {
    -      throw Error('The address does not look like an IPv4.');
    -    } else {
    -      ip = goog.object.clone(address);
    -    }
    -  } else {
    -    if (!goog.net.Ipv4Address.REGEX_.test(address)) {
    -      throw Error(address + ' does not look like an IPv4 address.');
    -    }
    -
    -    var octets = address.split('.');
    -    if (octets.length != 4) {
    -      throw Error(address + ' does not look like an IPv4 address.');
    -    }
    -
    -    for (var i = 0; i < octets.length; i++) {
    -      var parsedOctet = goog.string.toNumber(octets[i]);
    -      if (isNaN(parsedOctet) ||
    -          parsedOctet < 0 || parsedOctet > 255 ||
    -          (octets[i].length != 1 && goog.string.startsWith(octets[i], '0'))) {
    -        throw Error('In ' + address + ', octet ' + i + ' is not valid');
    -      }
    -      var intOctet = goog.math.Integer.fromNumber(parsedOctet);
    -      ip = ip.shiftLeft(8).or(intOctet);
    -    }
    -  }
    -  goog.net.Ipv4Address.base(
    -      this, 'constructor', /** @type {!goog.math.Integer} */ (ip), 4);
    -};
    -goog.inherits(goog.net.Ipv4Address, goog.net.IpAddress);
    -
    -
    -/**
    - * Regular expression matching all the allowed chars for IPv4.
    - * @type {RegExp}
    - * @private
    - * @const
    - */
    -goog.net.Ipv4Address.REGEX_ = /^[0-9.]*$/;
    -
    -
    -/**
    - * The Maximum length for a netmask (aka, the number of bits for IPv4).
    - * @type {number}
    - * @const
    - */
    -goog.net.Ipv4Address.MAX_NETMASK_LENGTH = 32;
    -
    -
    -/**
    - * The Maximum address possible for IPv4.
    - * @type {goog.math.Integer}
    - * @private
    - * @const
    - */
    -goog.net.Ipv4Address.MAX_ADDRESS_ = goog.math.Integer.ONE.shiftLeft(
    -    goog.net.Ipv4Address.MAX_NETMASK_LENGTH).subtract(goog.math.Integer.ONE);
    -
    -
    -/**
    - * @override
    - */
    -goog.net.Ipv4Address.prototype.toString = function() {
    -  if (this.ipStr_) {
    -    return this.ipStr_;
    -  }
    -
    -  var ip = this.ip_.getBitsUnsigned(0);
    -  var octets = [];
    -  for (var i = 3; i >= 0; i--) {
    -    octets[i] = String((ip & 0xff));
    -    ip = ip >>> 8;
    -  }
    -
    -  this.ipStr_ = octets.join('.');
    -
    -  return this.ipStr_;
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.net.Ipv4Address.prototype.toUriString = function() {
    -  return this.toString();
    -};
    -
    -
    -
    -/**
    - * Takes a string or a number and returns an IPv6 Address.
    - *
    - * This constructor accepts strings and instance of goog.math.Integer.
    - * If you pass a goog.math.Integer, make sure that its sign is set to positive.
    - * @param {(string|!goog.math.Integer)} address The address to store.
    - * @constructor
    - * @extends {goog.net.IpAddress}
    - * @final
    - */
    -goog.net.Ipv6Address = function(address) {
    -  var ip = goog.math.Integer.ZERO;
    -  if (address instanceof goog.math.Integer) {
    -    if (address.getSign() != 0 ||
    -        address.lessThan(goog.math.Integer.ZERO) ||
    -        address.greaterThan(goog.net.Ipv6Address.MAX_ADDRESS_)) {
    -      throw Error('The address does not look like a valid IPv6.');
    -    } else {
    -      ip = goog.object.clone(address);
    -    }
    -  } else {
    -    if (!goog.net.Ipv6Address.REGEX_.test(address)) {
    -      throw Error(address + ' is not a valid IPv6 address.');
    -    }
    -
    -    var splitColon = address.split(':');
    -    if (splitColon[splitColon.length - 1].indexOf('.') != -1) {
    -      var newHextets = goog.net.Ipv6Address.dottedQuadtoHextets_(
    -          splitColon[splitColon.length - 1]);
    -      goog.array.removeAt(splitColon, splitColon.length - 1);
    -      goog.array.extend(splitColon, newHextets);
    -      address = splitColon.join(':');
    -    }
    -
    -    var splitDoubleColon = address.split('::');
    -    if (splitDoubleColon.length > 2 ||
    -        (splitDoubleColon.length == 1 && splitColon.length != 8)) {
    -      throw Error(address + ' is not a valid IPv6 address.');
    -    }
    -
    -    var ipArr;
    -    if (splitDoubleColon.length > 1) {
    -      ipArr = goog.net.Ipv6Address.explode_(splitDoubleColon);
    -    } else {
    -      ipArr = splitColon;
    -    }
    -
    -    if (ipArr.length != 8) {
    -      throw Error(address + ' is not a valid IPv6 address');
    -    }
    -
    -    for (var i = 0; i < ipArr.length; i++) {
    -      var parsedHextet = goog.math.Integer.fromString(ipArr[i], 16);
    -      if (parsedHextet.lessThan(goog.math.Integer.ZERO) ||
    -          parsedHextet.greaterThan(goog.net.Ipv6Address.MAX_HEXTET_VALUE_)) {
    -        throw Error(ipArr[i] + ' in ' + address + ' is not a valid hextet.');
    -      }
    -      ip = ip.shiftLeft(16).or(parsedHextet);
    -    }
    -  }
    -  goog.net.Ipv6Address.base(
    -      this, 'constructor', /** @type {!goog.math.Integer} */ (ip), 6);
    -};
    -goog.inherits(goog.net.Ipv6Address, goog.net.IpAddress);
    -
    -
    -/**
    - * Regular expression matching all allowed chars for an IPv6.
    - * @type {RegExp}
    - * @private
    - * @const
    - */
    -goog.net.Ipv6Address.REGEX_ = /^([a-fA-F0-9]*:){2}[a-fA-F0-9:.]*$/;
    -
    -
    -/**
    - * The Maximum length for a netmask (aka, the number of bits for IPv6).
    - * @type {number}
    - * @const
    - */
    -goog.net.Ipv6Address.MAX_NETMASK_LENGTH = 128;
    -
    -
    -/**
    - * The maximum value of a hextet.
    - * @type {goog.math.Integer}
    - * @private
    - * @const
    - */
    -goog.net.Ipv6Address.MAX_HEXTET_VALUE_ = goog.math.Integer.fromInt(65535);
    -
    -
    -/**
    - * The Maximum address possible for IPv6.
    - * @type {goog.math.Integer}
    - * @private
    - * @const
    - */
    -goog.net.Ipv6Address.MAX_ADDRESS_ = goog.math.Integer.ONE.shiftLeft(
    -    goog.net.Ipv6Address.MAX_NETMASK_LENGTH).subtract(goog.math.Integer.ONE);
    -
    -
    -/**
    - * @override
    - */
    -goog.net.Ipv6Address.prototype.toString = function() {
    -  if (this.ipStr_) {
    -    return this.ipStr_;
    -  }
    -
    -  var outputArr = [];
    -  for (var i = 3; i >= 0; i--) {
    -    var bits = this.ip_.getBitsUnsigned(i);
    -    var firstHextet = bits >>> 16;
    -    var secondHextet = bits & 0xffff;
    -    outputArr.push(firstHextet.toString(16));
    -    outputArr.push(secondHextet.toString(16));
    -  }
    -
    -  outputArr = goog.net.Ipv6Address.compress_(outputArr);
    -  this.ipStr_ = outputArr.join(':');
    -  return this.ipStr_;
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.net.Ipv6Address.prototype.toUriString = function() {
    -  return '[' + this.toString() + ']';
    -};
    -
    -
    -/**
    - * This method is in charge of expanding/exploding an IPv6 string from its
    - * compressed form.
    - * @private
    - * @param {!Array<string>} address An IPv6 address split around '::'.
    - * @return {!Array<string>} The expanded version of the IPv6.
    - */
    -goog.net.Ipv6Address.explode_ = function(address) {
    -  var basePart = address[0].split(':');
    -  var secondPart = address[1].split(':');
    -
    -  if (basePart.length == 1 && basePart[0] == '') {
    -    basePart = [];
    -  }
    -  if (secondPart.length == 1 && secondPart[0] == '') {
    -    secondPart = [];
    -  }
    -
    -  // Now we fill the gap with 0.
    -  var gap = 8 - (basePart.length + secondPart.length);
    -
    -  if (gap < 1) {
    -    return [];
    -  }
    -
    -  goog.array.extend(basePart, goog.array.repeat('0', gap));
    -
    -  // Now we merge the basePart + gap + secondPart
    -  goog.array.extend(basePart, secondPart);
    -
    -  return basePart;
    -};
    -
    -
    -/**
    - * This method is in charge of compressing an expanded IPv6 array of hextets.
    - * @private
    - * @param {!Array<string>} hextets The array of hextet.
    - * @return {!Array<string>} The compressed version of this array.
    - */
    -goog.net.Ipv6Address.compress_ = function(hextets) {
    -  var bestStart = -1;
    -  var start = -1;
    -  var bestSize = 0;
    -  var size = 0;
    -  for (var i = 0; i < hextets.length; i++) {
    -    if (hextets[i] == '0') {
    -      size++;
    -      if (start == -1) {
    -        start = i;
    -      }
    -      if (size > bestSize) {
    -        bestSize = size;
    -        bestStart = start;
    -      }
    -    } else {
    -      start = -1;
    -      size = 0;
    -    }
    -  }
    -
    -  if (bestSize > 0) {
    -    if ((bestStart + bestSize) == hextets.length) {
    -      hextets.push('');
    -    }
    -    hextets.splice(bestStart, bestSize, '');
    -
    -    if (bestStart == 0) {
    -      hextets = [''].concat(hextets);
    -    }
    -  }
    -  return hextets;
    -};
    -
    -
    -/**
    - * This method will convert an IPv4 to a list of 2 hextets.
    - *
    - * For instance, 1.2.3.4 will be converted to ['0102', '0304'].
    - * @private
    - * @param {string} quads An IPv4 as a string.
    - * @return {!Array<string>} A list of 2 hextets.
    - */
    -goog.net.Ipv6Address.dottedQuadtoHextets_ = function(quads) {
    -  var ip4 = new goog.net.Ipv4Address(quads).toInteger();
    -  var bits = ip4.getBitsUnsigned(0);
    -  var hextets = [];
    -
    -  hextets.push(((bits >>> 16) & 0xffff).toString(16));
    -  hextets.push((bits & 0xffff).toString(16));
    -
    -  return hextets;
    -};
    -
    -
    -/**
    - * @return {boolean} true if the IPv6 contains a mapped IPv4.
    - */
    -goog.net.Ipv6Address.prototype.isMappedIpv4Address = function() {
    -  return (this.ip_.getBitsUnsigned(3) == 0 &&
    -          this.ip_.getBitsUnsigned(2) == 0 &&
    -          this.ip_.getBitsUnsigned(1) == 0xffff);
    -};
    -
    -
    -/**
    - * Will return the mapped IPv4 address in this IPv6 address.
    - * @return {goog.net.Ipv4Address} an IPv4 or null.
    - */
    -goog.net.Ipv6Address.prototype.getMappedIpv4Address = function() {
    -  if (!this.isMappedIpv4Address()) {
    -    return null;
    -  }
    -
    -  var newIpv4 = new goog.math.Integer([this.ip_.getBitsUnsigned(0)], 0);
    -  return new goog.net.Ipv4Address(newIpv4);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/net/ipaddress_test.html b/src/database/third_party/closure-library/closure/goog/net/ipaddress_test.html
    deleted file mode 100644
    index 2d7f426dfcd..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/ipaddress_test.html
    +++ /dev/null
    @@ -1,26 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    -Test suite inspired from http://code.google.com/p/ipaddr-py/ and
    -Google's Guava InetAddresses test suite available on
    -http://code.google.com/p/guava-libraries/
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Test - goog.net.IpAddress
    -  </title>
    -  <script src="../base.js" type="text/javascript">
    -  </script>
    -  <script type="text/javascript">
    -    goog.require('goog.net.IpAddressTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/ipaddress_test.js b/src/database/third_party/closure-library/closure/goog/net/ipaddress_test.js
    deleted file mode 100644
    index 1032c54fb00..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/ipaddress_test.js
    +++ /dev/null
    @@ -1,220 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.net.IpAddressTest');
    -goog.setTestOnly('goog.net.IpAddressTest');
    -
    -goog.require('goog.math.Integer');
    -goog.require('goog.net.IpAddress');
    -goog.require('goog.net.Ipv4Address');
    -goog.require('goog.net.Ipv6Address');
    -goog.require('goog.testing.jsunit');
    -
    -function testInvalidStrings() {
    -  assertEquals(null, goog.net.IpAddress.fromString(''));
    -  assertEquals(null, goog.net.IpAddress.fromString('016.016.016.016'));
    -  assertEquals(null, goog.net.IpAddress.fromString('016.016.016'));
    -  assertEquals(null, goog.net.IpAddress.fromString('016.016'));
    -  assertEquals(null, goog.net.IpAddress.fromString('016'));
    -  assertEquals(null, goog.net.IpAddress.fromString('000.000.000.000'));
    -  assertEquals(null, goog.net.IpAddress.fromString('000'));
    -  assertEquals(null,
    -      goog.net.IpAddress.fromString('0x0a.0x0a.0x0a.0x0a'));
    -  assertEquals(null, goog.net.IpAddress.fromString('0x0a.0x0a.0x0a'));
    -  assertEquals(null, goog.net.IpAddress.fromString('0x0a.0x0a'));
    -  assertEquals(null, goog.net.IpAddress.fromString('0x0a'));
    -  assertEquals(null, goog.net.IpAddress.fromString('42.42.42.42.42'));
    -  assertEquals(null, goog.net.IpAddress.fromString('42.42.42'));
    -  assertEquals(null, goog.net.IpAddress.fromString('42.42'));
    -  assertEquals(null, goog.net.IpAddress.fromString('42'));
    -  assertEquals(null, goog.net.IpAddress.fromString('42..42.42'));
    -  assertEquals(null, goog.net.IpAddress.fromString('42..42.42.42'));
    -  assertEquals(null, goog.net.IpAddress.fromString('42.42.42.42.'));
    -  assertEquals(null, goog.net.IpAddress.fromString('42.42.42.42...'));
    -  assertEquals(null, goog.net.IpAddress.fromString('.42.42.42.42'));
    -  assertEquals(null, goog.net.IpAddress.fromString('...42.42.42.42'));
    -  assertEquals(null, goog.net.IpAddress.fromString('42.42.42.-0'));
    -  assertEquals(null, goog.net.IpAddress.fromString('42.42.42.+0'));
    -  assertEquals(null, goog.net.IpAddress.fromString('.'));
    -  assertEquals(null, goog.net.IpAddress.fromString('...'));
    -  assertEquals(null, goog.net.IpAddress.fromString('bogus'));
    -  assertEquals(null, goog.net.IpAddress.fromString('bogus.com'));
    -  assertEquals(null, goog.net.IpAddress.fromString('192.168.0.1.com'));
    -  assertEquals(null,
    -      goog.net.IpAddress.fromString('12345.67899.-54321.-98765'));
    -  assertEquals(null, goog.net.IpAddress.fromString('257.0.0.0'));
    -  assertEquals(null, goog.net.IpAddress.fromString('42.42.42.-42'));
    -  assertEquals(null, goog.net.IpAddress.fromString('3ff3:::1'));
    -  assertEquals(null, goog.net.IpAddress.fromString('3ffe::1.net'));
    -  assertEquals(null, goog.net.IpAddress.fromString('3ffe::1::1'));
    -  assertEquals(null, goog.net.IpAddress.fromString('1::2::3::4:5'));
    -  assertEquals(null, goog.net.IpAddress.fromString('::7:6:5:4:3:2:'));
    -  assertEquals(null, goog.net.IpAddress.fromString(':6:5:4:3:2:1::'));
    -  assertEquals(null, goog.net.IpAddress.fromString('2001::db:::1'));
    -  assertEquals(null, goog.net.IpAddress.fromString('FEDC:9878'));
    -  assertEquals(null, goog.net.IpAddress.fromString('+1.+2.+3.4'));
    -  assertEquals(null, goog.net.IpAddress.fromString('1.2.3.4e0'));
    -  assertEquals(null, goog.net.IpAddress.fromString('::7:6:5:4:3:2:1:0'));
    -  assertEquals(null, goog.net.IpAddress.fromString('7:6:5:4:3:2:1:0::'));
    -  assertEquals(null, goog.net.IpAddress.fromString('9:8:7:6:5:4:3::2:1'));
    -  assertEquals(null, goog.net.IpAddress.fromString('0:1:2:3::4:5:6:7'));
    -  assertEquals(null,
    -      goog.net.IpAddress.fromString('3ffe:0:0:0:0:0:0:0:1'));
    -  assertEquals(null, goog.net.IpAddress.fromString('3ffe::10000'));
    -  assertEquals(null, goog.net.IpAddress.fromString('3ffe::goog'));
    -  assertEquals(null, goog.net.IpAddress.fromString('3ffe::-0'));
    -  assertEquals(null, goog.net.IpAddress.fromString('3ffe::+0'));
    -  assertEquals(null, goog.net.IpAddress.fromString('3ffe::-1'));
    -  assertEquals(null, goog.net.IpAddress.fromString(':'));
    -  assertEquals(null, goog.net.IpAddress.fromString(':::'));
    -  assertEquals(null, goog.net.IpAddress.fromString('a:'));
    -  assertEquals(null, goog.net.IpAddress.fromString('::a:'));
    -  assertEquals(null, goog.net.IpAddress.fromString('0xa::'));
    -  assertEquals(null, goog.net.IpAddress.fromString('::1.2.3'));
    -  assertEquals(null, goog.net.IpAddress.fromString('::1.2.3.4.5'));
    -  assertEquals(null, goog.net.IpAddress.fromString('::1.2.3.4:'));
    -  assertEquals(null, goog.net.IpAddress.fromString('1.2.3.4::'));
    -  assertEquals(null, goog.net.IpAddress.fromString('2001:db8::1:'));
    -  assertEquals(null, goog.net.IpAddress.fromString(':2001:db8::1'));
    -}
    -
    -function testVersion() {
    -  var ip4 = goog.net.IpAddress.fromString('1.2.3.4');
    -  assertEquals(ip4.getVersion(), 4);
    -
    -  var ip6 = goog.net.IpAddress.fromString('2001:dead::beef:1');
    -  assertEquals(ip6.getVersion(), 6);
    -
    -  ip6 = goog.net.IpAddress.fromString('::192.168.1.1');
    -  assertEquals(ip6.getVersion(), 6);
    -}
    -
    -function testStringIpv4Address() {
    -  assertEquals('192.168.1.1',
    -      new goog.net.Ipv4Address('192.168.1.1').toString());
    -  assertEquals('1.1.1.1',
    -      new goog.net.Ipv4Address('1.1.1.1').toString());
    -  assertEquals('224.56.33.2',
    -      new goog.net.Ipv4Address('224.56.33.2').toString());
    -  assertEquals('255.255.255.255',
    -      new goog.net.Ipv4Address('255.255.255.255').toString());
    -  assertEquals('0.0.0.0',
    -      new goog.net.Ipv4Address('0.0.0.0').toString());
    -}
    -
    -function testIntIpv4Address() {
    -  var ip4Str = new goog.net.Ipv4Address('1.1.1.1');
    -  var ip4Int = new goog.net.Ipv4Address(
    -      new goog.math.Integer([16843009], 0));
    -
    -  assertTrue(ip4Str.equals(ip4Int));
    -  assertEquals(ip4Str.toString(), ip4Int.toString());
    -
    -  assertThrows('Ipv4(-1)', goog.partial(goog.net.Ipv4Address,
    -                                        goog.math.Integer.fromInt(-1)));
    -  assertThrows('Ipv4(2**32)',
    -               goog.partial(goog.net.Ipv4Address,
    -                            goog.math.Integer.ONE.shiftLeft(32)));
    -}
    -
    -function testStringIpv6Address() {
    -  assertEquals('1:2:3:4:5:6:7:8',
    -      new goog.net.Ipv6Address('1:2:3:4:5:6:7:8').toString());
    -  assertEquals('::1:2:3:4:5:6:7',
    -      new goog.net.Ipv6Address('::1:2:3:4:5:6:7').toString());
    -  assertEquals('1:2:3:4:5:6:7::',
    -      new goog.net.Ipv6Address('1:2:3:4:5:6:7:0').toString());
    -  assertEquals('2001:0:0:4::8',
    -      new goog.net.Ipv6Address('2001:0:0:4:0:0:0:8').toString());
    -  assertEquals('2001::4:5:6:7:8',
    -      new goog.net.Ipv6Address('2001:0:0:4:5:6:7:8').toString());
    -  assertEquals('2001::3:4:5:6:7:8',
    -      new goog.net.Ipv6Address('2001:0:3:4:5:6:7:8').toString());
    -  assertEquals('0:0:3::ffff',
    -      new goog.net.Ipv6Address('0:0:3:0:0:0:0:ffff').toString());
    -  assertEquals('::4:0:0:0:ffff',
    -      new goog.net.Ipv6Address('0:0:0:4:0:0:0:ffff').toString());
    -  assertEquals('::5:0:0:ffff',
    -      new goog.net.Ipv6Address('0:0:0:0:5:0:0:ffff').toString());
    -  assertEquals('1::4:0:0:7:8',
    -      new goog.net.Ipv6Address('1:0:0:4:0:0:7:8').toString());
    -  assertEquals('::',
    -      new goog.net.Ipv6Address('0:0:0:0:0:0:0:0').toString());
    -  assertEquals('::1',
    -      new goog.net.Ipv6Address('0:0:0:0:0:0:0:1').toString());
    -  assertEquals('2001:658:22a:cafe::',
    -      new goog.net.Ipv6Address(
    -          '2001:0658:022a:cafe:0000:0000:0000:0000').toString());
    -  assertEquals('::102:304',
    -      new goog.net.Ipv6Address('::1.2.3.4').toString());
    -  assertEquals('::ffff:303:303',
    -      new goog.net.Ipv6Address('::ffff:3.3.3.3').toString());
    -  assertEquals('::ffff:ffff',
    -      new goog.net.Ipv6Address('::255.255.255.255').toString());
    -}
    -
    -function testIntIpv6Address() {
    -  var ip6Str = new goog.net.Ipv6Address('2001::dead:beef:1');
    -  var ip6Int = new goog.net.Ipv6Address(
    -      new goog.math.Integer([3203334145, 57005, 0, 536936448], 0));
    -
    -  assertTrue(ip6Str.equals(ip6Int));
    -  assertEquals(ip6Str.toString(), ip6Int.toString());
    -
    -  assertThrows('Ipv6(-1)', goog.partial(goog.net.Ipv6Address,
    -                                        goog.math.Integer.fromInt(-1)));
    -  assertThrows('Ipv6(2**128)',
    -               goog.partial(goog.net.Ipv6Address,
    -                            goog.math.Integer.ONE.shiftLeft(128)));
    -
    -}
    -
    -function testDottedQuadIpv6() {
    -  var ip6 = new goog.net.Ipv6Address('7::0.128.0.127');
    -  ip6 = new goog.net.Ipv6Address('7::0.128.0.128');
    -  ip6 = new goog.net.Ipv6Address('7::128.128.0.127');
    -  ip6 = new goog.net.Ipv6Address('7::0.128.128.127');
    -}
    -
    -function testMappedIpv4Address() {
    -  var testAddresses = ['::ffff:1.2.3.4', '::FFFF:102:304'];
    -  var ipv4Str = '1.2.3.4';
    -
    -  var ip1 = new goog.net.Ipv6Address(testAddresses[0]);
    -  var ip2 = new goog.net.Ipv6Address(testAddresses[1]);
    -  var ipv4 = new goog.net.Ipv4Address(ipv4Str);
    -
    -  assertTrue(ip1.isMappedIpv4Address());
    -  assertTrue(ip2.isMappedIpv4Address());
    -  assertTrue(ip1.equals(ip2));
    -  assertTrue(ipv4.equals(ip1.getMappedIpv4Address()));
    -  assertTrue(ipv4.equals(ip2.getMappedIpv4Address()));
    -}
    -
    -
    -function testUriString() {
    -  var ip4Str = '192.168.1.1';
    -  var ip4Uri = goog.net.IpAddress.fromUriString(ip4Str);
    -  var ip4 = goog.net.IpAddress.fromString(ip4Str);
    -  assertTrue(ip4Uri.equals(ip4));
    -
    -  var ip6Str = '2001:dead::beef:1';
    -  assertEquals(null, goog.net.IpAddress.fromUriString(ip6Str));
    -
    -  var ip6Uri = goog.net.IpAddress.fromUriString('[' + ip6Str + ']');
    -  var ip6 = goog.net.IpAddress.fromString(ip6Str);
    -  assertTrue(ip6Uri.equals(ip6));
    -  assertEquals(ip6Uri.toString(), ip6Str);
    -  assertEquals(ip6Uri.toUriString(), '[' + ip6Str + ']');
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/net/jsloader.js b/src/database/third_party/closure-library/closure/goog/net/jsloader.js
    deleted file mode 100644
    index 527e8b090a4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/jsloader.js
    +++ /dev/null
    @@ -1,367 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A utility to load JavaScript files via DOM script tags.
    - * Refactored from goog.net.Jsonp. Works cross-domain.
    - *
    - */
    -
    -goog.provide('goog.net.jsloader');
    -goog.provide('goog.net.jsloader.Error');
    -goog.provide('goog.net.jsloader.ErrorCode');
    -goog.provide('goog.net.jsloader.Options');
    -
    -goog.require('goog.array');
    -goog.require('goog.async.Deferred');
    -goog.require('goog.debug.Error');
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -
    -
    -/**
    - * The name of the property of goog.global under which the JavaScript
    - * verification object is stored by the loaded script.
    - * @type {string}
    - * @private
    - */
    -goog.net.jsloader.GLOBAL_VERIFY_OBJS_ = 'closure_verification';
    -
    -
    -/**
    - * The default length of time, in milliseconds, we are prepared to wait for a
    - * load request to complete.
    - * @type {number}
    - */
    -goog.net.jsloader.DEFAULT_TIMEOUT = 5000;
    -
    -
    -/**
    - * Optional parameters for goog.net.jsloader.send.
    - * timeout: The length of time, in milliseconds, we are prepared to wait
    - *     for a load request to complete. Default it 5 seconds.
    - * document: The HTML document under which to load the JavaScript. Default is
    - *     the current document.
    - * cleanupWhenDone: If true clean up the script tag after script completes to
    - *     load. This is important if you just want to read data from the JavaScript
    - *     and then throw it away. Default is false.
    - *
    - * @typedef {{
    - *   timeout: (number|undefined),
    - *   document: (HTMLDocument|undefined),
    - *   cleanupWhenDone: (boolean|undefined)
    - * }}
    - */
    -goog.net.jsloader.Options;
    -
    -
    -/**
    - * Scripts (URIs) waiting to be loaded.
    - * @type {Array<string>}
    - * @private
    - */
    -goog.net.jsloader.scriptsToLoad_ = [];
    -
    -
    -/**
    - * Loads and evaluates the JavaScript files at the specified URIs, guaranteeing
    - * the order of script loads.
    - *
    - * Because we have to load the scripts in serial (load script 1, exec script 1,
    - * load script 2, exec script 2, and so on), this will be slower than doing
    - * the network fetches in parallel.
    - *
    - * If you need to load a large number of scripts but dependency order doesn't
    - * matter, you should just call goog.net.jsloader.load N times.
    - *
    - * If you need to load a large number of scripts on the same domain,
    - * you may want to use goog.module.ModuleLoader.
    - *
    - * @param {Array<string>} uris The URIs to load.
    - * @param {goog.net.jsloader.Options=} opt_options Optional parameters. See
    - *     goog.net.jsloader.options documentation for details.
    - */
    -goog.net.jsloader.loadMany = function(uris, opt_options) {
    -  // Loading the scripts in serial introduces asynchronosity into the flow.
    -  // Therefore, there are race conditions where client A can kick off the load
    -  // sequence for client B, even though client A's scripts haven't all been
    -  // loaded yet.
    -  //
    -  // To work around this issue, all module loads share a queue.
    -  if (!uris.length) {
    -    return;
    -  }
    -
    -  var isAnotherModuleLoading = goog.net.jsloader.scriptsToLoad_.length;
    -  goog.array.extend(goog.net.jsloader.scriptsToLoad_, uris);
    -  if (isAnotherModuleLoading) {
    -    // jsloader is still loading some other scripts.
    -    // In order to prevent the race condition noted above, we just add
    -    // these URIs to the end of the scripts' queue and return.
    -    return;
    -  }
    -
    -  uris = goog.net.jsloader.scriptsToLoad_;
    -  var popAndLoadNextScript = function() {
    -    var uri = uris.shift();
    -    var deferred = goog.net.jsloader.load(uri, opt_options);
    -    if (uris.length) {
    -      deferred.addBoth(popAndLoadNextScript);
    -    }
    -  };
    -  popAndLoadNextScript();
    -};
    -
    -
    -/**
    - * Loads and evaluates a JavaScript file.
    - * When the script loads, a user callback is called.
    - * It is the client's responsibility to verify that the script ran successfully.
    - *
    - * @param {string} uri The URI of the JavaScript.
    - * @param {goog.net.jsloader.Options=} opt_options Optional parameters. See
    - *     goog.net.jsloader.Options documentation for details.
    - * @return {!goog.async.Deferred} The deferred result, that may be used to add
    - *     callbacks and/or cancel the transmission.
    - *     The error callback will be called with a single goog.net.jsloader.Error
    - *     parameter.
    - */
    -goog.net.jsloader.load = function(uri, opt_options) {
    -  var options = opt_options || {};
    -  var doc = options.document || document;
    -
    -  var script = goog.dom.createElement(goog.dom.TagName.SCRIPT);
    -  var request = {script_: script, timeout_: undefined};
    -  var deferred = new goog.async.Deferred(goog.net.jsloader.cancel_, request);
    -
    -  // Set a timeout.
    -  var timeout = null;
    -  var timeoutDuration = goog.isDefAndNotNull(options.timeout) ?
    -      options.timeout : goog.net.jsloader.DEFAULT_TIMEOUT;
    -  if (timeoutDuration > 0) {
    -    timeout = window.setTimeout(function() {
    -      goog.net.jsloader.cleanup_(script, true);
    -      deferred.errback(new goog.net.jsloader.Error(
    -          goog.net.jsloader.ErrorCode.TIMEOUT,
    -          'Timeout reached for loading script ' + uri));
    -    }, timeoutDuration);
    -    request.timeout_ = timeout;
    -  }
    -
    -  // Hang the user callback to be called when the script completes to load.
    -  // NOTE(user): This callback will be called in IE even upon error. In any
    -  // case it is the client's responsibility to verify that the script ran
    -  // successfully.
    -  script.onload = script.onreadystatechange = function() {
    -    if (!script.readyState || script.readyState == 'loaded' ||
    -        script.readyState == 'complete') {
    -      var removeScriptNode = options.cleanupWhenDone || false;
    -      goog.net.jsloader.cleanup_(script, removeScriptNode, timeout);
    -      deferred.callback(null);
    -    }
    -  };
    -
    -  // Add an error callback.
    -  // NOTE(user): Not supported in IE.
    -  script.onerror = function() {
    -    goog.net.jsloader.cleanup_(script, true, timeout);
    -    deferred.errback(new goog.net.jsloader.Error(
    -        goog.net.jsloader.ErrorCode.LOAD_ERROR,
    -        'Error while loading script ' + uri));
    -  };
    -
    -  // Add the script element to the document.
    -  goog.dom.setProperties(script, {
    -    'type': 'text/javascript',
    -    'charset': 'UTF-8',
    -    // NOTE(user): Safari never loads the script if we don't set
    -    // the src attribute before appending.
    -    'src': uri
    -  });
    -  var scriptParent = goog.net.jsloader.getScriptParentElement_(doc);
    -  scriptParent.appendChild(script);
    -
    -  return deferred;
    -};
    -
    -
    -/**
    - * Loads a JavaScript file and verifies it was evaluated successfully, using a
    - * verification object.
    - * The verification object is set by the loaded JavaScript at the end of the
    - * script.
    - * We verify this object was set and return its value in the success callback.
    - * If the object is not defined we trigger an error callback.
    - *
    - * @param {string} uri The URI of the JavaScript.
    - * @param {string} verificationObjName The name of the verification object that
    - *     the loaded script should set.
    - * @param {goog.net.jsloader.Options} options Optional parameters. See
    - *     goog.net.jsloader.Options documentation for details.
    - * @return {!goog.async.Deferred} The deferred result, that may be used to add
    - *     callbacks and/or cancel the transmission.
    - *     The success callback will be called with a single parameter containing
    - *     the value of the verification object.
    - *     The error callback will be called with a single goog.net.jsloader.Error
    - *     parameter.
    - */
    -goog.net.jsloader.loadAndVerify = function(uri, verificationObjName, options) {
    -  // Define the global objects variable.
    -  if (!goog.global[goog.net.jsloader.GLOBAL_VERIFY_OBJS_]) {
    -    goog.global[goog.net.jsloader.GLOBAL_VERIFY_OBJS_] = {};
    -  }
    -  var verifyObjs = goog.global[goog.net.jsloader.GLOBAL_VERIFY_OBJS_];
    -
    -  // Verify that the expected object does not exist yet.
    -  if (goog.isDef(verifyObjs[verificationObjName])) {
    -    // TODO(user): Error or reset variable?
    -    return goog.async.Deferred.fail(new goog.net.jsloader.Error(
    -        goog.net.jsloader.ErrorCode.VERIFY_OBJECT_ALREADY_EXISTS,
    -        'Verification object ' + verificationObjName + ' already defined.'));
    -  }
    -
    -  // Send request to load the JavaScript.
    -  var sendDeferred = goog.net.jsloader.load(uri, options);
    -
    -  // Create a deferred object wrapping the send result.
    -  var deferred = new goog.async.Deferred(
    -      goog.bind(sendDeferred.cancel, sendDeferred));
    -
    -  // Call user back with object that was set by the script.
    -  sendDeferred.addCallback(function() {
    -    var result = verifyObjs[verificationObjName];
    -    if (goog.isDef(result)) {
    -      deferred.callback(result);
    -      delete verifyObjs[verificationObjName];
    -    } else {
    -      // Error: script was not loaded properly.
    -      deferred.errback(new goog.net.jsloader.Error(
    -          goog.net.jsloader.ErrorCode.VERIFY_ERROR,
    -          'Script ' + uri + ' loaded, but verification object ' +
    -          verificationObjName + ' was not defined.'));
    -    }
    -  });
    -
    -  // Pass error to new deferred object.
    -  sendDeferred.addErrback(function(error) {
    -    if (goog.isDef(verifyObjs[verificationObjName])) {
    -      delete verifyObjs[verificationObjName];
    -    }
    -    deferred.errback(error);
    -  });
    -
    -  return deferred;
    -};
    -
    -
    -/**
    - * Gets the DOM element under which we should add new script elements.
    - * How? Take the first head element, and if not found take doc.documentElement,
    - * which always exists.
    - *
    - * @param {!HTMLDocument} doc The relevant document.
    - * @return {!Element} The script parent element.
    - * @private
    - */
    -goog.net.jsloader.getScriptParentElement_ = function(doc) {
    -  var headElements = doc.getElementsByTagName(goog.dom.TagName.HEAD);
    -  if (!headElements || goog.array.isEmpty(headElements)) {
    -    return doc.documentElement;
    -  } else {
    -    return headElements[0];
    -  }
    -};
    -
    -
    -/**
    - * Cancels a given request.
    - * @this {{script_: Element, timeout_: number}} The request context.
    - * @private
    - */
    -goog.net.jsloader.cancel_ = function() {
    -  var request = this;
    -  if (request && request.script_) {
    -    var scriptNode = request.script_;
    -    if (scriptNode && scriptNode.tagName == 'SCRIPT') {
    -      goog.net.jsloader.cleanup_(scriptNode, true, request.timeout_);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Removes the script node and the timeout.
    - *
    - * @param {Node} scriptNode The node to be cleaned up.
    - * @param {boolean} removeScriptNode If true completely remove the script node.
    - * @param {?number=} opt_timeout The timeout handler to cleanup.
    - * @private
    - */
    -goog.net.jsloader.cleanup_ = function(scriptNode, removeScriptNode,
    -                                      opt_timeout) {
    -  if (goog.isDefAndNotNull(opt_timeout)) {
    -    goog.global.clearTimeout(opt_timeout);
    -  }
    -
    -  scriptNode.onload = goog.nullFunction;
    -  scriptNode.onerror = goog.nullFunction;
    -  scriptNode.onreadystatechange = goog.nullFunction;
    -
    -  // Do this after a delay (removing the script node of a running script can
    -  // confuse older IEs).
    -  if (removeScriptNode) {
    -    window.setTimeout(function() {
    -      goog.dom.removeNode(scriptNode);
    -    }, 0);
    -  }
    -};
    -
    -
    -/**
    - * Possible error codes for jsloader.
    - * @enum {number}
    - */
    -goog.net.jsloader.ErrorCode = {
    -  LOAD_ERROR: 0,
    -  TIMEOUT: 1,
    -  VERIFY_ERROR: 2,
    -  VERIFY_OBJECT_ALREADY_EXISTS: 3
    -};
    -
    -
    -
    -/**
    - * A jsloader error.
    - *
    - * @param {goog.net.jsloader.ErrorCode} code The error code.
    - * @param {string=} opt_message Additional message.
    - * @constructor
    - * @extends {goog.debug.Error}
    - * @final
    - */
    -goog.net.jsloader.Error = function(code, opt_message) {
    -  var msg = 'Jsloader error (code #' + code + ')';
    -  if (opt_message) {
    -    msg += ': ' + opt_message;
    -  }
    -  goog.net.jsloader.Error.base(this, 'constructor', msg);
    -
    -  /**
    -   * The code for this error.
    -   *
    -   * @type {goog.net.jsloader.ErrorCode}
    -   */
    -  this.code = code;
    -};
    -goog.inherits(goog.net.jsloader.Error, goog.debug.Error);
    diff --git a/src/database/third_party/closure-library/closure/goog/net/jsloader_test.html b/src/database/third_party/closure-library/closure/goog/net/jsloader_test.html
    deleted file mode 100644
    index e584d6a9caf..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/jsloader_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.net.jsloader
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.net.jsloaderTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/jsloader_test.js b/src/database/third_party/closure-library/closure/goog/net/jsloader_test.js
    deleted file mode 100644
    index e423ab0bc96..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/jsloader_test.js
    +++ /dev/null
    @@ -1,137 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.net.jsloaderTest');
    -goog.setTestOnly('goog.net.jsloaderTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.net.jsloader');
    -goog.require('goog.net.jsloader.ErrorCode');
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.jsunit');
    -
    -// Initialize the AsyncTestCase.
    -var testCase = goog.testing.AsyncTestCase.createAndInstall(document.title);
    -testCase.stepTimeout = 5 * 1000; // 5 seconds
    -
    -
    -testCase.setUp = function() {
    -  goog.provide = goog.nullFunction;
    -};
    -
    -
    -testCase.tearDown = function() {
    -  // Remove all the fake scripts.
    -  var scripts = goog.array.clone(
    -      document.getElementsByTagName('SCRIPT'));
    -  for (var i = 0; i < scripts.length; i++) {
    -    if (scripts[i].src.indexOf('testdata') != -1) {
    -      goog.dom.removeNode(scripts[i]);
    -    }
    -  }
    -};
    -
    -
    -// Sunny day scenario for load function.
    -function testLoad() {
    -  testCase.waitForAsync('testLoad');
    -
    -  window.test1 = null;
    -  var testUrl = 'testdata/jsloader_test1.js';
    -  var result = goog.net.jsloader.load(testUrl);
    -  result.addCallback(function() {
    -    testCase.continueTesting();
    -
    -    var script = result.defaultScope_.script_;
    -
    -    assertNotNull('script created', script);
    -    assertEquals('encoding is utf-8', 'UTF-8', script.charset);
    -
    -    // Check that the URI matches ours.
    -    assertTrue('server URI', script.src.indexOf(testUrl) >= 0);
    -
    -    // Check that the script was really loaded.
    -    assertEquals('verification object', 'Test #1 loaded', window.test1);
    -  });
    -}
    -
    -
    -// Sunny day scenario for loadAndVerify function.
    -function testLoadAndVerify() {
    -  testCase.waitForAsync('testLoadAndVerify');
    -
    -  var testUrl = 'testdata/jsloader_test2.js';
    -  var result = goog.net.jsloader.loadAndVerify(testUrl, 'test2');
    -  result.addCallback(function(verifyObj) {
    -    testCase.continueTesting();
    -
    -    // Check that the verification object has passed ok.
    -    assertEquals('verification object', 'Test #2 loaded', verifyObj);
    -  });
    -}
    -
    -
    -// What happens when the verification object is not set by the loaded script?
    -function testLoadAndVerifyError() {
    -  testCase.waitForAsync('testLoadAndVerifyError');
    -
    -  var testUrl = 'testdata/jsloader_test2.js';
    -  var result = goog.net.jsloader.loadAndVerify(testUrl, 'fake');
    -  result.addErrback(function(error) {
    -    testCase.continueTesting();
    -
    -    // Check that the error code is right.
    -    assertEquals('verification error', goog.net.jsloader.ErrorCode.VERIFY_ERROR,
    -        error.code);
    -  });
    -}
    -
    -
    -// Tests that callers can cancel the deferred without error.
    -function testLoadAndVerifyCancelled() {
    -  var testUrl = 'testdata/jsloader_test2.js';
    -  var result = goog.net.jsloader.loadAndVerify(testUrl, 'test2');
    -  result.cancel();
    -}
    -
    -
    -// Test the loadMany function.
    -function testLoadMany() {
    -  testCase.waitForAsync('testLoadMany');
    -
    -  // Load test #3 and then #1.
    -  window.test1 = null;
    -  var testUrls1 = ['testdata/jsloader_test3.js', 'testdata/jsloader_test1.js'];
    -  goog.net.jsloader.loadMany(testUrls1);
    -
    -  window.test3Callback = function(msg) {
    -    testCase.continueTesting();
    -
    -    // Check that the 1st test was not loaded yet.
    -    assertEquals('verification object', null, window.test1);
    -
    -    // Load test #4, which is supposed to wait for #1 to load.
    -    testCase.waitForAsync('testLoadMany');
    -    var testUrls2 = ['testdata/jsloader_test4.js'];
    -    goog.net.jsloader.loadMany(testUrls2);
    -  };
    -
    -  window.test4Callback = function(msg) {
    -    testCase.continueTesting();
    -
    -    // Check that the 1st test was already loaded.
    -    assertEquals('verification object', 'Test #1 loaded', window.test1);
    -  };
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/net/jsonp.js b/src/database/third_party/closure-library/closure/goog/net/jsonp.js
    deleted file mode 100644
    index f4b1ea8a435..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/jsonp.js
    +++ /dev/null
    @@ -1,340 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -// The original file lives here: http://go/cross_domain_channel.js
    -
    -/**
    - * @fileoverview Implements a cross-domain communication channel. A
    - * typical web page is prevented by browser security from sending
    - * request, such as a XMLHttpRequest, to other servers than the ones
    - * from which it came. The Jsonp class provides a workaround by
    - * using dynamically generated script tags. Typical usage:.
    - *
    - * var jsonp = new goog.net.Jsonp(new goog.Uri('http://my.host.com/servlet'));
    - * var payload = { 'foo': 1, 'bar': true };
    - * jsonp.send(payload, function(reply) { alert(reply) });
    - *
    - * This script works in all browsers that are currently supported by
    - * the Google Maps API, which is IE 6.0+, Firefox 0.8+, Safari 1.2.4+,
    - * Netscape 7.1+, Mozilla 1.4+, Opera 8.02+.
    - *
    - */
    -
    -goog.provide('goog.net.Jsonp');
    -
    -goog.require('goog.Uri');
    -goog.require('goog.net.jsloader');
    -
    -// WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
    -//
    -// This class allows us (Google) to send data from non-Google and thus
    -// UNTRUSTED pages to our servers. Under NO CIRCUMSTANCES return
    -// anything sensitive, such as session or cookie specific data. Return
    -// only data that you want parties external to Google to have. Also
    -// NEVER use this method to send data from web pages to untrusted
    -// servers, or redirects to unknown servers (www.google.com/cache,
    -// /q=xx&btnl, /url, www.googlepages.com, etc.)
    -//
    -// WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
    -
    -
    -
    -/**
    - * Creates a new cross domain channel that sends data to the specified
    - * host URL. By default, if no reply arrives within 5s, the channel
    - * assumes the call failed to complete successfully.
    - *
    - * @param {goog.Uri|string} uri The Uri of the server side code that receives
    - *     data posted through this channel (e.g.,
    - *     "http://maps.google.com/maps/geo").
    - *
    - * @param {string=} opt_callbackParamName The parameter name that is used to
    - *     specify the callback. Defaults to "callback".
    - *
    - * @constructor
    - * @final
    - */
    -goog.net.Jsonp = function(uri, opt_callbackParamName) {
    -  /**
    -   * The uri_ object will be used to encode the payload that is sent to the
    -   * server.
    -   * @type {goog.Uri}
    -   * @private
    -   */
    -  this.uri_ = new goog.Uri(uri);
    -
    -  /**
    -   * This is the callback parameter name that is added to the uri.
    -   * @type {string}
    -   * @private
    -   */
    -  this.callbackParamName_ = opt_callbackParamName ?
    -      opt_callbackParamName : 'callback';
    -
    -  /**
    -   * The length of time, in milliseconds, this channel is prepared
    -   * to wait for for a request to complete. The default value is 5 seconds.
    -   * @type {number}
    -   * @private
    -   */
    -  this.timeout_ = 5000;
    -};
    -
    -
    -/**
    - * The name of the property of goog.global under which the callback is
    - * stored.
    - */
    -goog.net.Jsonp.CALLBACKS = '_callbacks_';
    -
    -
    -/**
    - * Used to generate unique callback IDs. The counter must be global because
    - * all channels share a common callback object.
    - * @private
    - */
    -goog.net.Jsonp.scriptCounter_ = 0;
    -
    -
    -/**
    - * Sets the length of time, in milliseconds, this channel is prepared
    - * to wait for for a request to complete. If the call is not competed
    - * within the set time span, it is assumed to have failed. To wait
    - * indefinitely for a request to complete set the timout to a negative
    - * number.
    - *
    - * @param {number} timeout The length of time before calls are
    - * interrupted.
    - */
    -goog.net.Jsonp.prototype.setRequestTimeout = function(timeout) {
    -  this.timeout_ = timeout;
    -};
    -
    -
    -/**
    - * Returns the current timeout value, in milliseconds.
    - *
    - * @return {number} The timeout value.
    - */
    -goog.net.Jsonp.prototype.getRequestTimeout = function() {
    -  return this.timeout_;
    -};
    -
    -
    -/**
    - * Sends the given payload to the URL specified at the construction
    - * time. The reply is delivered to the given replyCallback. If the
    - * errorCallback is specified and the reply does not arrive within the
    - * timeout period set on this channel, the errorCallback is invoked
    - * with the original payload.
    - *
    - * If no reply callback is specified, then the response is expected to
    - * consist of calls to globally registered functions. No &callback=
    - * URL parameter will be sent in the request, and the script element
    - * will be cleaned up after the timeout.
    - *
    - * @param {Object=} opt_payload Name-value pairs.  If given, these will be
    - *     added as parameters to the supplied URI as GET parameters to the
    - *     given server URI.
    - *
    - * @param {Function=} opt_replyCallback A function expecting one
    - *     argument, called when the reply arrives, with the response data.
    - *
    - * @param {Function=} opt_errorCallback A function expecting one
    - *     argument, called on timeout, with the payload (if given), otherwise
    - *     null.
    - *
    - * @param {string=} opt_callbackParamValue Value to be used as the
    - *     parameter value for the callback parameter (callbackParamName).
    - *     To be used when the value needs to be fixed by the client for a
    - *     particular request, to make use of the cached responses for the request.
    - *     NOTE: If multiple requests are made with the same
    - *     opt_callbackParamValue, only the last call will work whenever the
    - *     response comes back.
    - *
    - * @return {!Object} A request descriptor that may be used to cancel this
    - *     transmission, or null, if the message may not be cancelled.
    - */
    -goog.net.Jsonp.prototype.send = function(opt_payload,
    -                                         opt_replyCallback,
    -                                         opt_errorCallback,
    -                                         opt_callbackParamValue) {
    -
    -  var payload = opt_payload || null;
    -
    -  var id = opt_callbackParamValue ||
    -      '_' + (goog.net.Jsonp.scriptCounter_++).toString(36) +
    -      goog.now().toString(36);
    -
    -  if (!goog.global[goog.net.Jsonp.CALLBACKS]) {
    -    goog.global[goog.net.Jsonp.CALLBACKS] = {};
    -  }
    -
    -  // Create a new Uri object onto which this payload will be added
    -  var uri = this.uri_.clone();
    -  if (payload) {
    -    goog.net.Jsonp.addPayloadToUri_(payload, uri);
    -  }
    -
    -  if (opt_replyCallback) {
    -    var reply = goog.net.Jsonp.newReplyHandler_(id, opt_replyCallback);
    -    goog.global[goog.net.Jsonp.CALLBACKS][id] = reply;
    -
    -    uri.setParameterValues(this.callbackParamName_,
    -                           goog.net.Jsonp.CALLBACKS + '.' + id);
    -  }
    -
    -  var deferred = goog.net.jsloader.load(uri.toString(),
    -      {timeout: this.timeout_, cleanupWhenDone: true});
    -  var error = goog.net.Jsonp.newErrorHandler_(id, payload, opt_errorCallback);
    -  deferred.addErrback(error);
    -
    -  return {id_: id, deferred_: deferred};
    -};
    -
    -
    -/**
    - * Cancels a given request. The request must be exactly the object returned by
    - * the send method.
    - *
    - * @param {Object} request The request object returned by the send method.
    - */
    -goog.net.Jsonp.prototype.cancel = function(request) {
    -  if (request) {
    -    if (request.deferred_) {
    -      request.deferred_.cancel();
    -    }
    -    if (request.id_) {
    -      goog.net.Jsonp.cleanup_(request.id_, false);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Creates a timeout callback that calls the given timeoutCallback with the
    - * original payload.
    - *
    - * @param {string} id The id of the script node.
    - * @param {Object} payload The payload that was sent to the server.
    - * @param {Function=} opt_errorCallback The function called on timeout.
    - * @return {!Function} A zero argument function that handles callback duties.
    - * @private
    - */
    -goog.net.Jsonp.newErrorHandler_ = function(id,
    -                                           payload,
    -                                           opt_errorCallback) {
    -  /**
    -   * When we call across domains with a request, this function is the
    -   * timeout handler. Once it's done executing the user-specified
    -   * error-handler, it removes the script node and original function.
    -   */
    -  return function() {
    -    goog.net.Jsonp.cleanup_(id, false);
    -    if (opt_errorCallback) {
    -      opt_errorCallback(payload);
    -    }
    -  };
    -};
    -
    -
    -/**
    - * Creates a reply callback that calls the given replyCallback with data
    - * returned by the server.
    - *
    - * @param {string} id The id of the script node.
    - * @param {Function} replyCallback The function called on reply.
    - * @return {!Function} A reply callback function.
    - * @private
    - */
    -goog.net.Jsonp.newReplyHandler_ = function(id, replyCallback) {
    -  /**
    -   * This function is the handler for the all-is-well response. It
    -   * clears the error timeout handler, calls the user's handler, then
    -   * removes the script node and itself.
    -   *
    -   * @param {...Object} var_args The response data sent from the server.
    -   */
    -  var handler = function(var_args) {
    -    goog.net.Jsonp.cleanup_(id, true);
    -    replyCallback.apply(undefined, arguments);
    -  };
    -  return handler;
    -};
    -
    -
    -/**
    - * Removes the script node and reply handler with the given id.
    - *
    - * @param {string} id The id of the script node to be removed.
    - * @param {boolean} deleteReplyHandler If true, delete the reply handler
    - *     instead of setting it to nullFunction (if we know the callback could
    - *     never be called again).
    - * @private
    - */
    -goog.net.Jsonp.cleanup_ = function(id, deleteReplyHandler) {
    -  if (goog.global[goog.net.Jsonp.CALLBACKS][id]) {
    -    if (deleteReplyHandler) {
    -      delete goog.global[goog.net.Jsonp.CALLBACKS][id];
    -    } else {
    -      // Removing the script tag doesn't necessarily prevent the script
    -      // from firing, so we make the callback a noop.
    -      goog.global[goog.net.Jsonp.CALLBACKS][id] = goog.nullFunction;
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Returns URL encoded payload. The payload should be a map of name-value
    - * pairs, in the form {"foo": 1, "bar": true, ...}.  If the map is empty,
    - * the URI will be unchanged.
    - *
    - * <p>The method uses hasOwnProperty() to assure the properties are on the
    - * object, not on its prototype.
    - *
    - * @param {!Object} payload A map of value name pairs to be encoded.
    - *     A value may be specified as an array, in which case a query parameter
    - *     will be created for each value, e.g.:
    - *     {"foo": [1,2]} will encode to "foo=1&foo=2".
    - *
    - * @param {!goog.Uri} uri A Uri object onto which the payload key value pairs
    - *     will be encoded.
    - *
    - * @return {!goog.Uri} A reference to the Uri sent as a parameter.
    - * @private
    - */
    -goog.net.Jsonp.addPayloadToUri_ = function(payload, uri) {
    -  for (var name in payload) {
    -    // NOTE(user): Safari/1.3 doesn't have hasOwnProperty(). In that
    -    // case, we iterate over all properties as a very lame workaround.
    -    if (!payload.hasOwnProperty || payload.hasOwnProperty(name)) {
    -      uri.setParameterValues(name, payload[name]);
    -    }
    -  }
    -  return uri;
    -};
    -
    -
    -// WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
    -//
    -// This class allows us (Google) to send data from non-Google and thus
    -// UNTRUSTED pages to our servers. Under NO CIRCUMSTANCES return
    -// anything sensitive, such as session or cookie specific data. Return
    -// only data that you want parties external to Google to have. Also
    -// NEVER use this method to send data from web pages to untrusted
    -// servers, or redirects to unknown servers (www.google.com/cache,
    -// /q=xx&btnl, /url, www.googlepages.com, etc.)
    -//
    -// WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
    diff --git a/src/database/third_party/closure-library/closure/goog/net/jsonp_test.html b/src/database/third_party/closure-library/closure/goog/net/jsonp_test.html
    deleted file mode 100644
    index 45898f44210..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/jsonp_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.net.Jsonp
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.net.JsonpTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/jsonp_test.js b/src/database/third_party/closure-library/closure/goog/net/jsonp_test.js
    deleted file mode 100644
    index 0a1e19c98c7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/jsonp_test.js
    +++ /dev/null
    @@ -1,321 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.net.JsonpTest');
    -goog.setTestOnly('goog.net.JsonpTest');
    -
    -goog.require('goog.net.Jsonp');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -goog.require('goog.userAgent');
    -
    -// Global vars to facilitate a shared set up function.
    -
    -var timeoutWasCalled;
    -var timeoutHandler;
    -
    -var fakeUrl = 'http://fake-site.eek/';
    -
    -var originalTimeout;
    -function setUp() {
    -  timeoutWasCalled = false;
    -  timeoutHandler = null;
    -  originalTimeout = window.setTimeout;
    -  window.setTimeout = function(handler, time) {
    -    timeoutWasCalled = true;
    -    timeoutHandler = handler;
    -  };
    -}
    -
    -// Firefox throws a JS error when a script is not found.  We catch that here and
    -// ensure the test case doesn't fail because of it.
    -var originalOnError = window.onerror;
    -window.onerror = function(msg, url, line) {
    -  // TODO(user): Safari 3 on the farm returns an object instead of the typcial
    -  // params.  Pass through errors for safari for now.
    -  if (goog.userAgent.WEBKIT ||
    -      msg == 'Error loading script' && url.indexOf('fake-site') != -1) {
    -    return true;
    -  } else {
    -    return originalOnError && originalOnError(msg, url, line);
    -  }
    -};
    -
    -function tearDown() {
    -  window.setTimeout = originalTimeout;
    -}
    -
    -// Quick function records the before-state of the DOM, and then return a
    -// a function to check that XDC isn't leaving stuff behind.
    -function newCleanupGuard() {
    -  var bodyChildCount = document.body.childNodes.length;
    -
    -  return function() {
    -    // let any timeout queues finish before we check these:
    -    window.setTimeout(function() {
    -      var propCounter = 0;
    -
    -      // All callbacks should have been deleted or be the null function.
    -      for (var id in goog.global[goog.net.Jsonp.CALLBACKS]) {
    -        if (goog.global[goog.net.Jsonp.CALLBACKS][id] != goog.nullFunction) {
    -          propCounter++;
    -        }
    -      }
    -
    -      assertEquals(
    -          'script cleanup', bodyChildCount, document.body.childNodes.length);
    -      assertEquals('window jsonp array empty', 0, propCounter);
    -    }, 0);
    -  }
    -}
    -
    -function getScriptElement(result) {
    -  return result.deferred_.defaultScope_.script_;
    -}
    -
    -
    -// Check that send function is sane when things go well.
    -function testSend() {
    -  var replyReceived;
    -  var jsonp = new goog.net.Jsonp(fakeUrl);
    -
    -  var checkCleanup = newCleanupGuard();
    -
    -  var userCallback = function(data) {
    -    replyReceived = data;
    -  };
    -
    -  var payload = {atisket: 'atasket', basket: 'yellow'};
    -  var result = jsonp.send(payload, userCallback);
    -
    -  var script = getScriptElement(result);
    -
    -  assertNotNull('script created', script);
    -  assertEquals('encoding is utf-8', 'UTF-8', script.charset);
    -
    -  // Check that the URL matches our payload.
    -  assertTrue('payload in url', script.src.indexOf('basket=yellow') > -1);
    -  assertTrue('server url', script.src.indexOf(fakeUrl) == 0);
    -
    -  // Now, we have to track down the name of the callback function, so we can
    -  // call that to simulate a returned request + verify that the callback
    -  // function does not break if it receives a second unexpected parameter.
    -  var callbackName = /callback=([^&]+)/.exec(script.src)[1];
    -  var callbackFunc = eval(callbackName);
    -  callbackFunc({some: 'data', another: ['data', 'right', 'here']},
    -      'unexpected');
    -  assertEquals('input was received', 'right', replyReceived.another[1]);
    -
    -  // Because the callbackFunc calls cleanUp_ and that calls setTimeout which
    -  // we have overwritten, we have to call the timeoutHandler to actually do
    -  // the cleaning.
    -  timeoutHandler();
    -
    -  checkCleanup();
    -  timeoutHandler();
    -}
    -
    -
    -// Check that send function is sane when things go well.
    -function testSendWhenCallbackHasTwoParameters() {
    -  var replyReceived, replyReceived2;
    -  var jsonp = new goog.net.Jsonp(fakeUrl);
    -
    -  var checkCleanup = newCleanupGuard();
    -
    -  var userCallback = function(data, opt_data2) {
    -    replyReceived = data;
    -    replyReceived2 = opt_data2;
    -  };
    -
    -  var payload = {atisket: 'atasket', basket: 'yellow'};
    -  var result = jsonp.send(payload, userCallback);
    -  var script = getScriptElement(result);
    -
    -  // Test a callback function that receives two parameters.
    -  var callbackName = /callback=([^&]+)/.exec(script.src)[1];
    -  var callbackFunc = eval(callbackName);
    -  callbackFunc('param1', {some: 'data', another: ['data', 'right', 'here']});
    -  assertEquals('input was received', 'param1', replyReceived);
    -  assertEquals('second input was received', 'right',
    -      replyReceived2.another[1]);
    -
    -  // Because the callbackFunc calls cleanUp_ and that calls setTimeout which
    -  // we have overwritten, we have to call the timeoutHandler to actually do
    -  // the cleaning.
    -  timeoutHandler();
    -
    -  checkCleanup();
    -  timeoutHandler();
    -}
    -
    -// Check that send function works correctly when callback param value is
    -// specified.
    -function testSendWithCallbackParamValue() {
    -  var replyReceived;
    -  var jsonp = new goog.net.Jsonp(fakeUrl);
    -
    -  var checkCleanup = newCleanupGuard();
    -
    -  var userCallback = function(data) {
    -    replyReceived = data;
    -  };
    -
    -  var payload = {atisket: 'atasket', basket: 'yellow'};
    -  var result = jsonp.send(payload, userCallback, undefined, 'dummyId');
    -
    -  var script = getScriptElement(result);
    -
    -  assertNotNull('script created', script);
    -  assertEquals('encoding is utf-8', 'UTF-8', script.charset);
    -
    -  // Check that the URL matches our payload.
    -  assertTrue('payload in url', script.src.indexOf('basket=yellow') > -1);
    -  assertTrue('dummyId in url',
    -      script.src.indexOf('callback=_callbacks_.dummyId') > -1);
    -  assertTrue('server url', script.src.indexOf(fakeUrl) == 0);
    -
    -  // Now, we simulate a returned request using the known callback function
    -  // name.
    -  var callbackFunc = _callbacks_.dummyId;
    -  callbackFunc({some: 'data', another: ['data', 'right', 'here']});
    -  assertEquals('input was received', 'right', replyReceived.another[1]);
    -
    -  // Because the callbackFunc calls cleanUp_ and that calls setTimeout which
    -  // we have overwritten, we have to call the timeoutHandler to actually do
    -  // the cleaning.
    -  timeoutHandler();
    -
    -  checkCleanup();
    -  timeoutHandler();
    -}
    -
    -
    -// Check that the send function is sane when the thing goes south.
    -function testSendFailure() {
    -  var replyReceived = false;
    -  var errorReplyReceived = false;
    -
    -  var jsonp = new goog.net.Jsonp(fakeUrl);
    -
    -  var checkCleanup = newCleanupGuard();
    -
    -  var userCallback = function(data) {
    -    replyReceived = data;
    -  };
    -  var userErrorCallback = function(data) {
    -    errorReplyReceived = data;
    -  };
    -
    -  var payload = { justa: 'test' };
    -
    -  jsonp.send(payload, userCallback, userErrorCallback);
    -
    -  assertTrue('timeout called', timeoutWasCalled);
    -
    -  // Now, simulate the time running out, so we go into error mode.
    -  // After jsonp.send(), the timeoutHandler now is the Jsonp.cleanUp_ function.
    -  timeoutHandler();
    -  // But that function also calls a setTimeout(), so it changes the timeout
    -  // handler once again, so to actually clean up we have to call the
    -  // timeoutHandler() once again. Fun!
    -  timeoutHandler();
    -
    -  assertFalse('standard callback not called', replyReceived);
    -
    -  // The user's error handler should be called back with the same payload
    -  // passed back to it.
    -  assertEquals('error handler called', 'test', errorReplyReceived.justa);
    -
    -  // Check that the relevant cleanup has occurred.
    -  checkCleanup();
    -  // Check cleanup just calls setTimeout so we have to call the handler to
    -  // actually check that the cleanup worked.
    -  timeoutHandler();
    -}
    -
    -
    -// Check that a cancel call works and cleans up after itself.
    -function testCancel() {
    -  var checkCleanup = newCleanupGuard();
    -
    -  var successCalled = false;
    -  var successCallback = function() {
    -    successCalled = true;
    -  };
    -
    -  // Send and cancel a request, then make sure it was cleaned up.
    -  var jsonp = new goog.net.Jsonp(fakeUrl);
    -  var requestObject = jsonp.send({test: 'foo'}, successCallback);
    -  jsonp.cancel(requestObject);
    -
    -  for (var key in goog.global[goog.net.Jsonp.CALLBACKS]) {
    -    assertNotEquals('The success callback should have been removed',
    -                    goog.global[goog.net.Jsonp.CALLBACKS][key],
    -                    successCallback);
    -  }
    -
    -  // Make sure cancelling removes the script tag
    -  checkCleanup();
    -  timeoutHandler();
    -}
    -
    -function testPayloadParameters() {
    -  var checkCleanup = newCleanupGuard();
    -
    -  var jsonp = new goog.net.Jsonp(fakeUrl);
    -  var result = jsonp.send({
    -    'foo': 3,
    -    'bar': 'baz'
    -  });
    -
    -  var script = getScriptElement(result);
    -  assertEquals('Payload parameters should have been added to url.',
    -               fakeUrl + '?foo=3&bar=baz',
    -               script.src);
    -
    -  checkCleanup();
    -  timeoutHandler();
    -}
    -
    -function testOptionalPayload() {
    -  var checkCleanup = newCleanupGuard();
    -
    -  var errorCallback = goog.testing.recordFunction();
    -
    -  var stubs = new goog.testing.PropertyReplacer();
    -  stubs.set(goog.global, 'setTimeout', function(errorHandler) {
    -    errorHandler();
    -  });
    -
    -  var jsonp = new goog.net.Jsonp(fakeUrl);
    -  var result = jsonp.send(null, null, errorCallback);
    -
    -  var script = getScriptElement(result);
    -  assertEquals('Parameters should not have been added to url.',
    -               fakeUrl, script.src);
    -
    -  // Clear the script hooks because we triggered the error manually.
    -  script.onload = goog.nullFunction;
    -  script.onerror = goog.nullFunction;
    -  script.onreadystatechange = goog.nullFunction;
    -
    -  var errorCallbackArguments = errorCallback.getLastCall().getArguments();
    -  assertEquals(1, errorCallbackArguments.length);
    -  assertNull(errorCallbackArguments[0]);
    -
    -  checkCleanup();
    -  stubs.reset();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/net/mockiframeio.js b/src/database/third_party/closure-library/closure/goog/net/mockiframeio.js
    deleted file mode 100644
    index 058817abc6e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/mockiframeio.js
    +++ /dev/null
    @@ -1,308 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Mock of IframeIo for unit testing.
    - */
    -
    -goog.provide('goog.net.MockIFrameIo');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.json');
    -goog.require('goog.net.ErrorCode');
    -goog.require('goog.net.EventType');
    -goog.require('goog.net.IframeIo');
    -
    -
    -
    -/**
    - * Mock implenetation of goog.net.IframeIo. This doesn't provide a mock
    - * implementation for all cases, but it's not too hard to add them as needed.
    - * @param {goog.testing.TestQueue} testQueue Test queue for inserting test
    - *     events.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - * @final
    - */
    -goog.net.MockIFrameIo = function(testQueue) {
    -  goog.events.EventTarget.call(this);
    -
    -  /**
    -   * Queue of events write to
    -   * @type {goog.testing.TestQueue}
    -   * @private
    -   */
    -  this.testQueue_ = testQueue;
    -
    -};
    -goog.inherits(goog.net.MockIFrameIo, goog.events.EventTarget);
    -
    -
    -/**
    - * Whether MockIFrameIo is active.
    - * @type {boolean}
    - * @private
    - */
    -goog.net.MockIFrameIo.prototype.active_ = false;
    -
    -
    -/**
    - * Last content.
    - * @type {string}
    - * @private
    - */
    -goog.net.MockIFrameIo.prototype.lastContent_ = '';
    -
    -
    -/**
    - * Last error code.
    - * @type {goog.net.ErrorCode}
    - * @private
    - */
    -goog.net.MockIFrameIo.prototype.lastErrorCode_ = goog.net.ErrorCode.NO_ERROR;
    -
    -
    -/**
    - * Last error message.
    - * @type {string}
    - * @private
    - */
    -goog.net.MockIFrameIo.prototype.lastError_ = '';
    -
    -
    -/**
    - * Last custom error.
    - * @type {Object}
    - * @private
    - */
    -goog.net.MockIFrameIo.prototype.lastCustomError_ = null;
    -
    -
    -/**
    - * Last URI.
    - * @type {goog.Uri}
    - * @private
    - */
    -goog.net.MockIFrameIo.prototype.lastUri_ = null;
    -
    -
    -/** @private {Function} */
    -goog.net.MockIFrameIo.prototype.errorChecker_;
    -
    -
    -/** @private {boolean} */
    -goog.net.MockIFrameIo.prototype.success_;
    -
    -
    -/** @private {boolean} */
    -goog.net.MockIFrameIo.prototype.complete_;
    -
    -
    -/**
    - * Simulates the iframe send.
    - *
    - * @param {goog.Uri|string} uri Uri of the request.
    - * @param {string=} opt_method Default is GET, POST uses a form to submit the
    - *     request.
    - * @param {boolean=} opt_noCache Append a timestamp to the request to avoid
    - *     caching.
    - * @param {Object|goog.structs.Map=} opt_data Map of key-value pairs.
    - */
    -goog.net.MockIFrameIo.prototype.send = function(uri, opt_method, opt_noCache,
    -                                                opt_data) {
    -  if (this.active_) {
    -    throw Error('[goog.net.IframeIo] Unable to send, already active.');
    -  }
    -
    -  this.testQueue_.enqueue(['s', uri, opt_method, opt_noCache, opt_data]);
    -  this.complete_ = false;
    -  this.active_ = true;
    -};
    -
    -
    -/**
    - * Simulates the iframe send from a form.
    - * @param {Element} form Form element used to send the request to the server.
    - * @param {string=} opt_uri Uri to set for the destination of the request, by
    - *     default the uri will come from the form.
    - * @param {boolean=} opt_noCache Append a timestamp to the request to avoid
    - *     caching.
    - */
    -goog.net.MockIFrameIo.prototype.sendFromForm = function(form, opt_uri,
    -    opt_noCache) {
    -  if (this.active_) {
    -    throw Error('[goog.net.IframeIo] Unable to send, already active.');
    -  }
    -
    -  this.testQueue_.enqueue(['s', form, opt_uri, opt_noCache]);
    -  this.complete_ = false;
    -  this.active_ = true;
    -};
    -
    -
    -/**
    - * Simulates aborting the current Iframe request.
    - * @param {goog.net.ErrorCode=} opt_failureCode Optional error code to use -
    - *     defaults to ABORT.
    - */
    -goog.net.MockIFrameIo.prototype.abort = function(opt_failureCode) {
    -  if (this.active_) {
    -    this.testQueue_.enqueue(['a', opt_failureCode]);
    -    this.complete_ = false;
    -    this.active_ = false;
    -    this.success_ = false;
    -    this.lastErrorCode_ = opt_failureCode || goog.net.ErrorCode.ABORT;
    -    this.dispatchEvent(goog.net.EventType.ABORT);
    -    this.simulateReady();
    -  }
    -};
    -
    -
    -/**
    - * Simulates receive of incremental data.
    - * @param {Object} data Data.
    - */
    -goog.net.MockIFrameIo.prototype.simulateIncrementalData = function(data) {
    -  this.dispatchEvent(new goog.net.IframeIo.IncrementalDataEvent(data));
    -};
    -
    -
    -/**
    - * Simulates the iframe is done.
    - * @param {goog.net.ErrorCode} errorCode The error code for any error that
    - *     should be simulated.
    - */
    -goog.net.MockIFrameIo.prototype.simulateDone = function(errorCode) {
    -  if (errorCode) {
    -    this.success_ = false;
    -    this.lastErrorCode_ = goog.net.ErrorCode.HTTP_ERROR;
    -    this.lastError_ = this.getLastError();
    -    this.dispatchEvent(goog.net.EventType.ERROR);
    -  } else {
    -    this.success_ = true;
    -    this.lastErrorCode_ = goog.net.ErrorCode.NO_ERROR;
    -    this.dispatchEvent(goog.net.EventType.SUCCESS);
    -  }
    -  this.complete_ = true;
    -  this.dispatchEvent(goog.net.EventType.COMPLETE);
    -};
    -
    -
    -/**
    - * Simulates the IFrame is ready for the next request.
    - */
    -goog.net.MockIFrameIo.prototype.simulateReady = function() {
    -  this.dispatchEvent(goog.net.EventType.READY);
    -};
    -
    -
    -/**
    - * @return {boolean} True if transfer is complete.
    - */
    -goog.net.MockIFrameIo.prototype.isComplete = function() {
    -  return this.complete_;
    -};
    -
    -
    -/**
    - * @return {boolean} True if transfer was successful.
    - */
    -goog.net.MockIFrameIo.prototype.isSuccess = function() {
    -  return this.success_;
    -};
    -
    -
    -/**
    - * @return {boolean} True if a transfer is in progress.
    - */
    -goog.net.MockIFrameIo.prototype.isActive = function() {
    -  return this.active_;
    -};
    -
    -
    -/**
    - * Returns the last response text (i.e. the text content of the iframe).
    - * Assumes plain text!
    - * @return {string} Result from the server.
    - */
    -goog.net.MockIFrameIo.prototype.getResponseText = function() {
    -  return this.lastContent_;
    -};
    -
    -
    -/**
    - * Parses the content as JSON. This is a safe parse and may throw an error
    - * if the response is malformed.
    - * @return {Object} The parsed content.
    - */
    -goog.net.MockIFrameIo.prototype.getResponseJson = function() {
    -  return goog.json.parse(this.lastContent_);
    -};
    -
    -
    -/**
    - * Get the uri of the last request.
    - * @return {goog.Uri} Uri of last request.
    - */
    -goog.net.MockIFrameIo.prototype.getLastUri = function() {
    -  return this.lastUri_;
    -};
    -
    -
    -/**
    - * Gets the last error code.
    - * @return {goog.net.ErrorCode} Last error code.
    - */
    -goog.net.MockIFrameIo.prototype.getLastErrorCode = function() {
    -  return this.lastErrorCode_;
    -};
    -
    -
    -/**
    - * Gets the last error message.
    - * @return {string} Last error message.
    - */
    -goog.net.MockIFrameIo.prototype.getLastError = function() {
    -  return goog.net.ErrorCode.getDebugMessage(this.lastErrorCode_);
    -};
    -
    -
    -/**
    - * Gets the last custom error.
    - * @return {Object} Last custom error.
    - */
    -goog.net.MockIFrameIo.prototype.getLastCustomError = function() {
    -  return this.lastCustomError_;
    -};
    -
    -
    -/**
    - * Sets the callback function used to check if a loaded IFrame is in an error
    - * state.
    - * @param {Function} fn Callback that expects a document object as it's single
    - *     argument.
    - */
    -goog.net.MockIFrameIo.prototype.setErrorChecker = function(fn) {
    -  this.errorChecker_ = fn;
    -};
    -
    -
    -/**
    - * Gets the callback function used to check if a loaded IFrame is in an error
    - * state.
    - * @return {Function} A callback that expects a document object as it's single
    - *     argument.
    - */
    -goog.net.MockIFrameIo.prototype.getErrorChecker = function() {
    -  return this.errorChecker_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/net/multiiframeloadmonitor.js b/src/database/third_party/closure-library/closure/goog/net/multiiframeloadmonitor.js
    deleted file mode 100644
    index 76d0ae47b20..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/multiiframeloadmonitor.js
    +++ /dev/null
    @@ -1,118 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Class that can be used to determine when multiple iframes have
    - * been loaded. Refactored from static APIs in IframeLoadMonitor.
    - */
    -goog.provide('goog.net.MultiIframeLoadMonitor');
    -
    -goog.require('goog.events');
    -goog.require('goog.net.IframeLoadMonitor');
    -
    -
    -
    -/**
    - * Provides a wrapper around IframeLoadMonitor, to allow the caller to wait for
    - * multiple iframes to load.
    - *
    - * @param {Array<HTMLIFrameElement>} iframes Array of iframe elements to
    - *     wait until they are loaded.
    - * @param {function():void} callback The callback to invoke once the frames have
    - *     loaded.
    - * @param {boolean=} opt_hasContent true if the monitor should wait until the
    - *     iframes have content (body.firstChild != null).
    - * @constructor
    - * @final
    - */
    -goog.net.MultiIframeLoadMonitor = function(iframes, callback, opt_hasContent) {
    -  /**
    -   * Array of IframeLoadMonitors we use to track the loaded status of any
    -   * currently unloaded iframes.
    -   * @type {Array<goog.net.IframeLoadMonitor>}
    -   * @private
    -   */
    -  this.pendingIframeLoadMonitors_ = [];
    -
    -  /**
    -   * Callback which is invoked when all of the iframes are loaded.
    -   * @type {function():void}
    -   * @private
    -   */
    -  this.callback_ = callback;
    -
    -  for (var i = 0; i < iframes.length; i++) {
    -    var iframeLoadMonitor = new goog.net.IframeLoadMonitor(
    -        iframes[i], opt_hasContent);
    -    if (iframeLoadMonitor.isLoaded()) {
    -      // Already loaded - don't need to wait
    -      iframeLoadMonitor.dispose();
    -    } else {
    -      // Iframe isn't loaded yet - register to be notified when it is
    -      // loaded, and track this monitor so we can dispose later as
    -      // required.
    -      this.pendingIframeLoadMonitors_.push(iframeLoadMonitor);
    -      goog.events.listen(
    -          iframeLoadMonitor, goog.net.IframeLoadMonitor.LOAD_EVENT, this);
    -    }
    -  }
    -  if (!this.pendingIframeLoadMonitors_.length) {
    -    // All frames were already loaded
    -    this.callback_();
    -  }
    -};
    -
    -
    -/**
    - * Handles a pending iframe load monitor load event.
    - * @param {goog.events.Event} e The goog.net.IframeLoadMonitor.LOAD_EVENT event.
    - */
    -goog.net.MultiIframeLoadMonitor.prototype.handleEvent = function(e) {
    -  var iframeLoadMonitor = e.target;
    -  // iframeLoadMonitor is now loaded, remove it from the array of
    -  // pending iframe load monitors.
    -  for (var i = 0; i < this.pendingIframeLoadMonitors_.length; i++) {
    -    if (this.pendingIframeLoadMonitors_[i] == iframeLoadMonitor) {
    -      this.pendingIframeLoadMonitors_.splice(i, 1);
    -      break;
    -    }
    -  }
    -
    -  // Disposes of the iframe load monitor.  We created this iframe load monitor
    -  // and installed the single listener on it, so it is safe to dispose it
    -  // in the middle of this event handler.
    -  iframeLoadMonitor.dispose();
    -
    -  // If there are no more pending iframe load monitors, all the iframes
    -  // have loaded, and so we invoke the callback.
    -  if (!this.pendingIframeLoadMonitors_.length) {
    -    this.callback_();
    -  }
    -};
    -
    -
    -/**
    - * Stops monitoring the iframes, cleaning up any associated resources. In
    - * general, the object cleans up its own resources before invoking the
    - * callback, so this API should only be used if the caller wants to stop the
    - * monitoring before the iframes are loaded (for example, if the caller is
    - * implementing a timeout).
    - */
    -goog.net.MultiIframeLoadMonitor.prototype.stopMonitoring = function() {
    -  for (var i = 0; i < this.pendingIframeLoadMonitors_.length; i++) {
    -    this.pendingIframeLoadMonitors_[i].dispose();
    -  }
    -  this.pendingIframeLoadMonitors_.length = 0;
    -};
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/net/multiiframeloadmonitor_test.html b/src/database/third_party/closure-library/closure/goog/net/multiiframeloadmonitor_test.html
    deleted file mode 100644
    index 99a73a6b64a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/multiiframeloadmonitor_test.html
    +++ /dev/null
    @@ -1,26 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.net.MultiIframeLoadMonitor
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.net.MultiIframeLoadMonitorTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="frame_parent">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/multiiframeloadmonitor_test.js b/src/database/third_party/closure-library/closure/goog/net/multiiframeloadmonitor_test.js
    deleted file mode 100644
    index 0b58eec5676..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/multiiframeloadmonitor_test.js
    +++ /dev/null
    @@ -1,162 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.net.MultiIframeLoadMonitorTest');
    -goog.setTestOnly('goog.net.MultiIframeLoadMonitorTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.net.IframeLoadMonitor');
    -goog.require('goog.net.MultiIframeLoadMonitor');
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.jsunit');
    -
    -var TEST_FRAME_SRCS = ['iframeloadmonitor_test_frame.html',
    -  'iframeloadmonitor_test_frame2.html',
    -  'iframeloadmonitor_test_frame3.html'];
    -
    -// Create a new test case.
    -var iframeLoaderTestCase = new goog.testing.AsyncTestCase(document.title);
    -iframeLoaderTestCase.stepTimeout = 4 * 1000;
    -
    -// How many multpile frames finished loading
    -iframeLoaderTestCase.multipleComplete_ = 0;
    -
    -iframeLoaderTestCase.numMonitors = 0;
    -iframeLoaderTestCase.disposeCalled = 0;
    -
    -
    -/**
    - * Sets up the test environment, adds tests and sets up the worker pools.
    - * @this {goog.testing.AsyncTestCase}
    - */
    -iframeLoaderTestCase.setUpPage = function() {
    -  this.log('Setting tests up');
    -  iframeLoaderTestCase.waitForAsync('loading iframes');
    -
    -  var dom = goog.dom.getDomHelper();
    -
    -  // Load multiple with callback
    -  var frame1 = dom.createDom('iframe');
    -  var frame2 = dom.createDom('iframe');
    -  var multiMonitor = new goog.net.MultiIframeLoadMonitor(
    -      [frame1, frame2], goog.bind(this.multipleCallback, this));
    -  this.log('Loading frames at: ' + TEST_FRAME_SRCS[0] + ' and ' +
    -      TEST_FRAME_SRCS[1]);
    -  // Make sure they don't look loaded yet.
    -  assertEquals(0, this.multipleComplete_);
    -  var frameParent = dom.getElement('frame_parent');
    -  dom.appendChild(frameParent, frame1);
    -  frame1.src = TEST_FRAME_SRCS[0];
    -  dom.appendChild(frameParent, frame2);
    -  frame2.src = TEST_FRAME_SRCS[1];
    -
    -  // Load multiple with callback and content check
    -  var frame3 = dom.createDom('iframe');
    -  var frame4 = dom.createDom('iframe');
    -  var multiMonitor = new goog.net.MultiIframeLoadMonitor(
    -      [frame3, frame4], goog.bind(this.multipleContentCallback, this), true);
    -  this.log('Loading frames with content check at: ' + TEST_FRAME_SRCS[1] +
    -      ' and ' + TEST_FRAME_SRCS[2]);
    -  dom.appendChild(frameParent, frame3);
    -  frame3.src = TEST_FRAME_SRCS[1];
    -  dom.appendChild(frameParent, frame4);
    -  frame4.src = TEST_FRAME_SRCS[2];
    -
    -
    -};
    -
    -
    -/**
    - * Callback for the multiple frame load test case
    - * @this {goog.testing.AsyncTestCase}
    - */
    -iframeLoaderTestCase.multipleCallback = function() {
    -  this.log('multiple frames finished loading');
    -  this.multipleComplete_++;
    -  this.multipleCompleteNoContent_ = true;
    -  this.callbacksComplete();
    -};
    -
    -
    -/**
    - * Callback for the multiple frame with content load test case
    - * @this {goog.testing.AsyncTestCase}
    - */
    -iframeLoaderTestCase.multipleContentCallback = function() {
    -  this.log('multiple frames with content finished loading');
    -  this.multipleComplete_++;
    -  this.multipleCompleteContent_ = true;
    -  this.callbacksComplete();
    -};
    -
    -
    -/**
    - * Checks if all the load callbacks are done
    - * @this {goog.testing.AsyncTestCase}
    - */
    -iframeLoaderTestCase.callbacksComplete = function() {
    -  if (this.multipleComplete_ == 2) {
    -    iframeLoaderTestCase.continueTesting();
    -  }
    -};
    -
    -
    -/** Tests the results. */
    -iframeLoaderTestCase.addNewTest('testResults', function() {
    -  this.log('getting test results');
    -  assertTrue(this.multipleCompleteNoContent_);
    -  assertTrue(this.multipleCompleteContent_);
    -});
    -
    -iframeLoaderTestCase.fakeLoadMonitor = function() {
    -  // Replaces IframeLoadMonitor with a fake version that just tracks
    -  // instantiations/disposals
    -  this.loadMonitorConstructor = goog.net.IframeLoadMonitor;
    -  var that = this;
    -  goog.net.IframeLoadMonitor = function() {
    -    that.numMonitors++;
    -    return {
    -      isLoaded: function() { return false; },
    -      dispose: function() { that.disposeCalled++; },
    -      attachEvent: function() {}
    -    };
    -  };
    -  goog.net.IframeLoadMonitor.LOAD_EVENT = 'ifload';
    -};
    -
    -iframeLoaderTestCase.unfakeLoadMonitor = function() {
    -  goog.net.IframeLoadMonitor = this.loadMonitorConstructor;
    -};
    -
    -iframeLoaderTestCase.addNewTest('stopMonitoring', function() {
    -  // create two unloaded frames, make sure that load monitors are loaded
    -  // behind the scenes, then make sure they are disposed properly.
    -  this.fakeLoadMonitor();
    -  var dom = goog.dom.getDomHelper();
    -  var frames = [dom.createDom('iframe'), dom.createDom('iframe')];
    -  var multiMonitor = new goog.net.MultiIframeLoadMonitor(
    -      frames,
    -      function() {
    -        fail('should not invoke callback for unloaded rames');
    -      });
    -  assertEquals(frames.length, this.numMonitors);
    -  assertEquals(0, this.disposeCalled);
    -  multiMonitor.stopMonitoring();
    -  assertEquals(frames.length, this.disposeCalled);
    -  this.unfakeLoadMonitor();
    -});
    -
    -
    -/** Standalone Closure Test Runner. */
    -G_testRunner.initialize(iframeLoaderTestCase);
    diff --git a/src/database/third_party/closure-library/closure/goog/net/networkstatusmonitor.js b/src/database/third_party/closure-library/closure/goog/net/networkstatusmonitor.js
    deleted file mode 100644
    index b0f81d2b69e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/networkstatusmonitor.js
    +++ /dev/null
    @@ -1,47 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Base class for objects monitoring and exposing runtime
    - * network status information.
    - */
    -
    -goog.provide('goog.net.NetworkStatusMonitor');
    -
    -goog.require('goog.events.Listenable');
    -
    -
    -
    -/**
    - * Base class for network status information providers.
    - * @interface
    - * @extends {goog.events.Listenable}
    - */
    -goog.net.NetworkStatusMonitor = function() {};
    -
    -
    -/**
    - * Enum for the events dispatched by the OnlineHandler.
    - * @enum {string}
    - */
    -goog.net.NetworkStatusMonitor.EventType = {
    -  ONLINE: 'online',
    -  OFFLINE: 'offline'
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the system is online or otherwise.
    - */
    -goog.net.NetworkStatusMonitor.prototype.isOnline;
    diff --git a/src/database/third_party/closure-library/closure/goog/net/networktester.js b/src/database/third_party/closure-library/closure/goog/net/networktester.js
    deleted file mode 100644
    index eec925b8893..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/networktester.js
    +++ /dev/null
    @@ -1,397 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Definition of goog.net.NetworkTester.
    - */
    -
    -goog.provide('goog.net.NetworkTester');
    -goog.require('goog.Timer');
    -goog.require('goog.Uri');
    -goog.require('goog.log');
    -
    -
    -
    -/**
    - * Creates an instance of goog.net.NetworkTester which can be used to test
    - * for internet connectivity by seeing if an image can be loaded from
    - * google.com. It can also be tested with other URLs.
    - * @param {Function} callback Callback that is called when the test completes.
    - *     The callback takes a single boolean parameter. True indicates the URL
    - *     was reachable, false indicates it wasn't.
    - * @param {Object=} opt_handler Handler object for the callback.
    - * @param {goog.Uri=} opt_uri URI to use for testing.
    - * @constructor @struct
    - * @final
    - */
    -goog.net.NetworkTester = function(callback, opt_handler, opt_uri) {
    -  /**
    -   * Callback that is called when the test completes.
    -   * The callback takes a single boolean parameter. True indicates the URL was
    -   * reachable, false indicates it wasn't.
    -   * @type {Function}
    -   * @private
    -   */
    -  this.callback_ = callback;
    -
    -  /**
    -   * Handler object for the callback.
    -   * @type {Object|undefined}
    -   * @private
    -   */
    -  this.handler_ = opt_handler;
    -
    -  if (!opt_uri) {
    -    // set the default URI to be based on the cleardot image at google.com
    -    // We need to add a 'rand' to make sure the response is not fulfilled
    -    // by browser cache. Use protocol-relative URLs to avoid insecure content
    -    // warnings in IE.
    -    opt_uri = new goog.Uri('//www.google.com/images/cleardot.gif');
    -    opt_uri.makeUnique();
    -  }
    -
    -  /**
    -   * Uri to use for test. Defaults to using an image off of google.com
    -   * @type {goog.Uri}
    -   * @private
    -   */
    -  this.uri_ = opt_uri;
    -};
    -
    -
    -/**
    - * Default timeout
    - * @type {number}
    - */
    -goog.net.NetworkTester.DEFAULT_TIMEOUT_MS = 10000;
    -
    -
    -/**
    - * Logger object
    - * @type {goog.log.Logger}
    - * @private
    - */
    -goog.net.NetworkTester.prototype.logger_ =
    -    goog.log.getLogger('goog.net.NetworkTester');
    -
    -
    -/**
    - * Timeout for test
    - * @type {number}
    - * @private
    - */
    -goog.net.NetworkTester.prototype.timeoutMs_ =
    -    goog.net.NetworkTester.DEFAULT_TIMEOUT_MS;
    -
    -
    -/**
    - * Whether we've already started running.
    - * @type {boolean}
    - * @private
    - */
    -goog.net.NetworkTester.prototype.running_ = false;
    -
    -
    -/**
    - * Number of retries to attempt
    - * @type {number}
    - * @private
    - */
    -goog.net.NetworkTester.prototype.retries_ = 0;
    -
    -
    -/**
    - * Attempt number we're on
    - * @type {number}
    - * @private
    - */
    -goog.net.NetworkTester.prototype.attempt_ = 0;
    -
    -
    -/**
    - * Pause between retries in milliseconds.
    - * @type {number}
    - * @private
    - */
    -goog.net.NetworkTester.prototype.pauseBetweenRetriesMs_ = 0;
    -
    -
    -/**
    - * Timer for timeouts.
    - * @type {?number}
    - * @private
    - */
    -goog.net.NetworkTester.prototype.timeoutTimer_ = null;
    -
    -
    -/**
    - * Timer for pauses between retries.
    - * @type {?number}
    - * @private
    - */
    -goog.net.NetworkTester.prototype.pauseTimer_ = null;
    -
    -
    -/** @private {?Image} */
    -goog.net.NetworkTester.prototype.image_;
    -
    -
    -/**
    - * Returns the timeout in milliseconds.
    - * @return {number} Timeout in milliseconds.
    - */
    -goog.net.NetworkTester.prototype.getTimeout = function() {
    -  return this.timeoutMs_;
    -};
    -
    -
    -/**
    - * Sets the timeout in milliseconds.
    - * @param {number} timeoutMs Timeout in milliseconds.
    - */
    -goog.net.NetworkTester.prototype.setTimeout = function(timeoutMs) {
    -  this.timeoutMs_ = timeoutMs;
    -};
    -
    -
    -/**
    - * Returns the numer of retries to attempt.
    - * @return {number} Number of retries to attempt.
    - */
    -goog.net.NetworkTester.prototype.getNumRetries = function() {
    -  return this.retries_;
    -};
    -
    -
    -/**
    - * Sets the timeout in milliseconds.
    - * @param {number} retries Number of retries to attempt.
    - */
    -goog.net.NetworkTester.prototype.setNumRetries = function(retries) {
    -  this.retries_ = retries;
    -};
    -
    -
    -/**
    - * Returns the pause between retries in milliseconds.
    - * @return {number} Pause between retries in milliseconds.
    - */
    -goog.net.NetworkTester.prototype.getPauseBetweenRetries = function() {
    -  return this.pauseBetweenRetriesMs_;
    -};
    -
    -
    -/**
    - * Sets the pause between retries in milliseconds.
    - * @param {number} pauseMs Pause between retries in milliseconds.
    - */
    -goog.net.NetworkTester.prototype.setPauseBetweenRetries = function(pauseMs) {
    -  this.pauseBetweenRetriesMs_ = pauseMs;
    -};
    -
    -
    -/**
    - * Returns the uri to use for the test.
    - * @return {goog.Uri} The uri for the test.
    - */
    -goog.net.NetworkTester.prototype.getUri = function() {
    -  return this.uri_;
    -};
    -
    -
    -/**
    - * Returns the current attempt count.
    - * @return {number} The attempt count.
    - */
    -goog.net.NetworkTester.prototype.getAttemptCount = function() {
    -  return this.attempt_;
    -};
    -
    -
    -/**
    - * Sets the uri to use for the test.
    - * @param {goog.Uri} uri The uri for the test.
    - */
    -goog.net.NetworkTester.prototype.setUri = function(uri) {
    -  this.uri_ = uri;
    -};
    -
    -
    -/**
    - * Returns whether the tester is currently running.
    - * @return {boolean} True if it's running, false if it's not running.
    - */
    -goog.net.NetworkTester.prototype.isRunning = function() {
    -  return this.running_;
    -};
    -
    -
    -/**
    - * Starts the process of testing the network.
    - */
    -goog.net.NetworkTester.prototype.start = function() {
    -  if (this.running_) {
    -    throw Error('NetworkTester.start called when already running');
    -  }
    -  this.running_ = true;
    -
    -  goog.log.info(this.logger_, 'Starting');
    -  this.attempt_ = 0;
    -  this.startNextAttempt_();
    -};
    -
    -
    -/**
    - * Stops the testing of the network. This is a noop if not running.
    - */
    -goog.net.NetworkTester.prototype.stop = function() {
    -  this.cleanupCallbacks_();
    -  this.running_ = false;
    -};
    -
    -
    -/**
    - * Starts the next attempt to load an image.
    - * @private
    - */
    -goog.net.NetworkTester.prototype.startNextAttempt_ = function() {
    -  this.attempt_++;
    -
    -  if (goog.net.NetworkTester.getNavigatorOffline_()) {
    -    goog.log.info(this.logger_, 'Browser is set to work offline.');
    -    // Call in a timeout to make async like the rest.
    -    goog.Timer.callOnce(goog.bind(this.onResult, this, false), 0);
    -  } else {
    -    goog.log.info(this.logger_, 'Loading image (attempt ' + this.attempt_ +
    -                      ') at ' + this.uri_);
    -    this.image_ = new Image();
    -    this.image_.onload = goog.bind(this.onImageLoad_, this);
    -    this.image_.onerror = goog.bind(this.onImageError_, this);
    -    this.image_.onabort = goog.bind(this.onImageAbort_, this);
    -
    -    this.timeoutTimer_ = goog.Timer.callOnce(this.onImageTimeout_,
    -        this.timeoutMs_, this);
    -    this.image_.src = String(this.uri_);
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} Whether navigator.onLine returns false.
    - * @private
    - */
    -goog.net.NetworkTester.getNavigatorOffline_ = function() {
    -  return 'onLine' in navigator && !navigator.onLine;
    -};
    -
    -
    -/**
    - * Callback for the image successfully loading.
    - * @private
    - */
    -goog.net.NetworkTester.prototype.onImageLoad_ = function() {
    -  goog.log.info(this.logger_, 'Image loaded');
    -  this.onResult(true);
    -};
    -
    -
    -/**
    - * Callback for the image failing to load.
    - * @private
    - */
    -goog.net.NetworkTester.prototype.onImageError_ = function() {
    -  goog.log.info(this.logger_, 'Image load error');
    -  this.onResult(false);
    -};
    -
    -
    -/**
    - * Callback for the image load being aborted.
    - * @private
    - */
    -goog.net.NetworkTester.prototype.onImageAbort_ = function() {
    -  goog.log.info(this.logger_, 'Image load aborted');
    -  this.onResult(false);
    -};
    -
    -
    -/**
    - * Callback for the image load timing out.
    - * @private
    - */
    -goog.net.NetworkTester.prototype.onImageTimeout_ = function() {
    -  goog.log.info(this.logger_, 'Image load timed out');
    -  this.onResult(false);
    -};
    -
    -
    -/**
    - * Handles a successful or failed result.
    - * @param {boolean} succeeded Whether the image load succeeded.
    - */
    -goog.net.NetworkTester.prototype.onResult = function(succeeded) {
    -  this.cleanupCallbacks_();
    -
    -  if (succeeded) {
    -    this.running_ = false;
    -    this.callback_.call(this.handler_, true);
    -  } else {
    -    if (this.attempt_ <= this.retries_) {
    -      if (this.pauseBetweenRetriesMs_) {
    -        this.pauseTimer_ = goog.Timer.callOnce(this.onPauseFinished_,
    -            this.pauseBetweenRetriesMs_, this);
    -      } else {
    -        this.startNextAttempt_();
    -      }
    -    } else {
    -      this.running_ = false;
    -      this.callback_.call(this.handler_, false);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Callback for the pause between retry timer.
    - * @private
    - */
    -goog.net.NetworkTester.prototype.onPauseFinished_ = function() {
    -  this.pauseTimer_ = null;
    -  this.startNextAttempt_();
    -};
    -
    -
    -/**
    - * Cleans up the handlers and timer associated with the image.
    - * @private
    - */
    -goog.net.NetworkTester.prototype.cleanupCallbacks_ = function() {
    -  // clear handlers to avoid memory leaks
    -  // NOTE(user): Nullified individually to avoid compiler warnings
    -  // (BUG 658126)
    -  if (this.image_) {
    -    this.image_.onload = null;
    -    this.image_.onerror = null;
    -    this.image_.onabort = null;
    -    this.image_ = null;
    -  }
    -  if (this.timeoutTimer_) {
    -    goog.Timer.clear(this.timeoutTimer_);
    -    this.timeoutTimer_ = null;
    -  }
    -  if (this.pauseTimer_) {
    -    goog.Timer.clear(this.pauseTimer_);
    -    this.pauseTimer_ = null;
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/net/networktester_test.html b/src/database/third_party/closure-library/closure/goog/net/networktester_test.html
    deleted file mode 100644
    index 0d433a53df9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/networktester_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.net.NetworkTester
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -  goog.require('goog.net.NetworkTesterTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/networktester_test.js b/src/database/third_party/closure-library/closure/goog/net/networktester_test.js
    deleted file mode 100644
    index 85a3c5d087e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/networktester_test.js
    +++ /dev/null
    @@ -1,237 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.net.NetworkTesterTest');
    -goog.setTestOnly('goog.net.NetworkTesterTest');
    -
    -goog.require('goog.Uri');
    -goog.require('goog.net.NetworkTester');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.jsunit');
    -
    -var clock;
    -
    -function setUp() {
    -  clock = new goog.testing.MockClock(true);
    -}
    -
    -function tearDown() {
    -  clock.dispose();
    -}
    -
    -function testSuccess() {
    -  // set up the tster
    -  var handler = new Handler();
    -  var tester = new goog.net.NetworkTester(handler.callback, handler);
    -  assertFalse(tester.isRunning());
    -  tester.start();
    -  assertTrue(handler.isEmpty());
    -  assertTrue(tester.isRunning());
    -
    -  // simulate the image load and verify
    -  var image = tester.image_;
    -  assertEquals(String(tester.getUri()), image.src);
    -  assertTrue(handler.isEmpty());
    -  image.onload.call(null);
    -  assertTrue(handler.dequeue());
    -  assertFalse(tester.isRunning());
    -}
    -
    -function testFailure() {
    -  // set up the tester
    -  var handler = new Handler();
    -  var tester = new goog.net.NetworkTester(handler.callback, handler);
    -  assertFalse(tester.isRunning());
    -  tester.start();
    -  assertTrue(handler.isEmpty());
    -  assertTrue(tester.isRunning());
    -
    -  // simulate the image failure and verify
    -  var image = tester.image_;
    -  assertEquals(String(tester.getUri()), image.src);
    -  assertTrue(handler.isEmpty());
    -  image.onerror.call(null);
    -  assertFalse(handler.dequeue());
    -  assertFalse(tester.isRunning());
    -}
    -
    -function testAbort() {
    -  // set up the tester
    -  var handler = new Handler();
    -  var tester = new goog.net.NetworkTester(handler.callback, handler);
    -  assertFalse(tester.isRunning());
    -  tester.start();
    -  assertTrue(handler.isEmpty());
    -  assertTrue(tester.isRunning());
    -
    -  // simulate the image abort and verify
    -  var image = tester.image_;
    -  assertEquals(String(tester.getUri()), image.src);
    -  assertTrue(handler.isEmpty());
    -  image.onabort.call(null);
    -  assertFalse(handler.dequeue());
    -  assertFalse(tester.isRunning());
    -}
    -
    -function testTimeout() {
    -  // set up the tester
    -  var handler = new Handler();
    -  var tester = new goog.net.NetworkTester(handler.callback, handler);
    -  assertFalse(tester.isRunning());
    -  tester.start();
    -  assertTrue(handler.isEmpty());
    -  assertTrue(tester.isRunning());
    -
    -  // simulate the image timeout and verify
    -  var image = tester.image_;
    -  assertEquals(String(tester.getUri()), image.src);
    -  assertTrue(handler.isEmpty());
    -  clock.tick(10000);
    -  assertFalse(handler.dequeue());
    -  assertFalse(tester.isRunning());
    -}
    -
    -function testRetries() {
    -  // set up the tester
    -  var handler = new Handler();
    -  var tester = new goog.net.NetworkTester(handler.callback, handler);
    -  tester.setNumRetries(1);
    -  assertEquals(tester.getAttemptCount(), 0);
    -  assertFalse(tester.isRunning());
    -  tester.start();
    -  assertTrue(handler.isEmpty());
    -  assertTrue(tester.isRunning());
    -  assertEquals(tester.getAttemptCount(), 1);
    -
    -  // try number 1 fails
    -  var image = tester.image_;
    -  assertEquals(String(tester.getUri()), image.src);
    -  assertTrue(handler.isEmpty());
    -  image.onerror.call(null);
    -  assertTrue(handler.isEmpty());
    -  assertTrue(tester.isRunning());
    -  assertEquals(tester.getAttemptCount(), 2);
    -
    -  // try number 2 succeeds
    -  image = tester.image_;
    -  assertEquals(String(tester.getUri()), image.src);
    -  assertTrue(handler.isEmpty());
    -  image.onload.call(null);
    -  assertTrue(handler.dequeue());
    -  assertFalse(tester.isRunning());
    -  assertEquals(tester.getAttemptCount(), 2);
    -}
    -
    -function testPauseBetweenRetries() {
    -  // set up the tester
    -  var handler = new Handler();
    -  var tester = new goog.net.NetworkTester(handler.callback, handler);
    -  tester.setNumRetries(1);
    -  tester.setPauseBetweenRetries(1000);
    -  assertFalse(tester.isRunning());
    -  tester.start();
    -  assertTrue(handler.isEmpty());
    -  assertTrue(tester.isRunning());
    -
    -  // try number 1 fails
    -  var image = tester.image_;
    -  assertEquals(String(tester.getUri()), image.src);
    -  assertTrue(handler.isEmpty());
    -  image.onerror.call(null);
    -  assertTrue(handler.isEmpty());
    -  assertTrue(tester.isRunning());
    -
    -  // need to pause 1000 ms for the second attempt
    -  assertNull(tester.image_);
    -  clock.tick(1000);
    -
    -  // try number 2 succeeds
    -  image = tester.image_;
    -  assertEquals(String(tester.getUri()), image.src);
    -  assertTrue(handler.isEmpty());
    -  image.onload.call(null);
    -  assertTrue(handler.dequeue());
    -  assertFalse(tester.isRunning());
    -}
    -
    -function testNonDefaultUri() {
    -  var handler = new Handler();
    -  var newUri = new goog.Uri('//www.google.com/images/cleardot2.gif');
    -  var tester = new goog.net.NetworkTester(handler.callback, handler, newUri);
    -  var testerUri = tester.getUri();
    -  assertTrue(testerUri.toString().indexOf('cleardot2') > -1);
    -}
    -
    -function testOffline() {
    -
    -  // set up the tester
    -  var handler = new Handler();
    -  var tester = new goog.net.NetworkTester(handler.callback, handler);
    -  var orgGetNavigatorOffline = goog.net.NetworkTester.getNavigatorOffline_;
    -  goog.net.NetworkTester.getNavigatorOffline_ = function() {
    -    return true;
    -  };
    -  try {
    -    assertFalse(tester.isRunning());
    -    tester.start();
    -    assertTrue(handler.isEmpty());
    -    assertTrue(tester.isRunning());
    -
    -    // the call is done async
    -    clock.tick(1);
    -
    -    assertFalse(handler.dequeue());
    -    assertFalse(tester.isRunning());
    -  } finally {
    -    // Clean up!
    -    goog.net.NetworkTester.getNavigatorOffline_ = orgGetNavigatorOffline;
    -  }
    -}
    -
    -// Handler object for verifying callback
    -function Handler() {
    -  this.events_ = [];
    -}
    -
    -function testGetAttemptCount() {
    -  // set up the tester
    -  var handler = new Handler();
    -  var tester = new goog.net.NetworkTester(handler.callback, handler);
    -  assertEquals(tester.getAttemptCount(), 0);
    -  assertTrue(tester.attempt_ === tester.getAttemptCount());
    -  assertFalse(tester.isRunning());
    -  tester.start();
    -  assertTrue(tester.isRunning());
    -  assertTrue(tester.attempt_ === tester.getAttemptCount());
    -}
    -
    -Handler.prototype.callback = function(result) {
    -  this.events_.push(result);
    -};
    -
    -Handler.prototype.isEmpty = function() {
    -  return this.events_.length == 0;
    -};
    -
    -Handler.prototype.dequeue = function() {
    -  if (this.isEmpty()) {
    -    throw Error('Handler is empty');
    -  }
    -  return this.events_.shift();
    -};
    -
    -// override image constructor for test - can't use a real image due to
    -// async load of images - have to simulate it
    -function Image() {
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/net/testdata/jsloader_test1.js b/src/database/third_party/closure-library/closure/goog/net/testdata/jsloader_test1.js
    deleted file mode 100644
    index 59d21621bae..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/testdata/jsloader_test1.js
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -// All Rights Reserved
    -
    -/**
    - * @fileoverview Test #1 of jsloader.
    - */
    -
    -goog.provide('goog.net.testdata.jsloader_test1');
    -goog.setTestOnly('jsloader_test1');
    -
    -window['test1'] = 'Test #1 loaded';
    diff --git a/src/database/third_party/closure-library/closure/goog/net/testdata/jsloader_test2.js b/src/database/third_party/closure-library/closure/goog/net/testdata/jsloader_test2.js
    deleted file mode 100644
    index 8690539840e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/testdata/jsloader_test2.js
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -// All Rights Reserved
    -
    -/**
    - * @fileoverview Test #2 of jsloader.
    - */
    -
    -goog.provide('goog.net.testdata.jsloader_test2');
    -goog.setTestOnly('jsloader_test2');
    -
    -window['closure_verification']['test2'] = 'Test #2 loaded';
    diff --git a/src/database/third_party/closure-library/closure/goog/net/testdata/jsloader_test3.js b/src/database/third_party/closure-library/closure/goog/net/testdata/jsloader_test3.js
    deleted file mode 100644
    index 7c1181dcc1f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/testdata/jsloader_test3.js
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -// All Rights Reserved
    -
    -/**
    - * @fileoverview Test #3 of jsloader.
    - */
    -
    -goog.provide('goog.net.testdata.jsloader_test3');
    -goog.setTestOnly('jsloader_test3');
    -
    -window['test3Callback']('Test #3 loaded');
    diff --git a/src/database/third_party/closure-library/closure/goog/net/testdata/jsloader_test4.js b/src/database/third_party/closure-library/closure/goog/net/testdata/jsloader_test4.js
    deleted file mode 100644
    index 591209c2bb8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/testdata/jsloader_test4.js
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -// All Rights Reserved
    -
    -/**
    - * @fileoverview Test #4 of jsloader.
    - */
    -
    -goog.provide('goog.net.testdata.jsloader_test4');
    -goog.setTestOnly('jsloader_test4');
    -
    -window['test4Callback']('Test #4 loaded');
    diff --git a/src/database/third_party/closure-library/closure/goog/net/tmpnetwork.js b/src/database/third_party/closure-library/closure/goog/net/tmpnetwork.js
    deleted file mode 100644
    index 53954a6ca7a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/tmpnetwork.js
    +++ /dev/null
    @@ -1,164 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview tmpnetwork.js contains some temporary networking functions
    - * for browserchannel which will be moved at a later date.
    - */
    -
    -
    -/**
    - * Namespace for BrowserChannel
    - */
    -goog.provide('goog.net.tmpnetwork');
    -
    -goog.require('goog.Uri');
    -goog.require('goog.net.ChannelDebug');
    -
    -
    -/**
    - * Default timeout to allow for google.com pings.
    - * @type {number}
    - */
    -goog.net.tmpnetwork.GOOGLECOM_TIMEOUT = 10000;
    -
    -
    -/**
    - * Pings the network to check if an error is a server error or user's network
    - * error.
    - *
    - * @param {Function} callback The function to call back with results.
    - * @param {goog.Uri?=} opt_imageUri The URI of an image to use for the network
    - *     test. You *must* provide an image URI; the default behavior is provided
    - *     for compatibility with existing code, but the search team does not want
    - *     people using images served off of google.com for this purpose. The
    - *     default will go away when all usages have been changed.
    - */
    -goog.net.tmpnetwork.testGoogleCom = function(callback, opt_imageUri) {
    -  // We need to add a 'rand' to make sure the response is not fulfilled
    -  // by browser cache.
    -  var uri = opt_imageUri;
    -  if (!uri) {
    -    uri = new goog.Uri('//www.google.com/images/cleardot.gif');
    -    uri.makeUnique();
    -  }
    -  goog.net.tmpnetwork.testLoadImage(uri.toString(),
    -      goog.net.tmpnetwork.GOOGLECOM_TIMEOUT, callback);
    -};
    -
    -
    -/**
    - * Test loading the given image, retrying if necessary.
    - * @param {string} url URL to the iamge.
    - * @param {number} timeout Milliseconds before giving up.
    - * @param {Function} callback Function to call with results.
    - * @param {number} retries The number of times to retry.
    - * @param {number=} opt_pauseBetweenRetriesMS Optional number of milliseconds
    - *     between retries - defaults to 0.
    - */
    -goog.net.tmpnetwork.testLoadImageWithRetries = function(url, timeout, callback,
    -    retries, opt_pauseBetweenRetriesMS) {
    -  var channelDebug = new goog.net.ChannelDebug();
    -  channelDebug.debug('TestLoadImageWithRetries: ' + opt_pauseBetweenRetriesMS);
    -  if (retries == 0) {
    -    // no more retries, give up
    -    callback(false);
    -    return;
    -  }
    -
    -  var pauseBetweenRetries = opt_pauseBetweenRetriesMS || 0;
    -  retries--;
    -  goog.net.tmpnetwork.testLoadImage(url, timeout, function(succeeded) {
    -    if (succeeded) {
    -      callback(true);
    -    } else {
    -      // try again
    -      goog.global.setTimeout(function() {
    -        goog.net.tmpnetwork.testLoadImageWithRetries(url, timeout, callback,
    -            retries, pauseBetweenRetries);
    -      }, pauseBetweenRetries);
    -    }
    -  });
    -};
    -
    -
    -/**
    - * Test loading the given image.
    - * @param {string} url URL to the iamge.
    - * @param {number} timeout Milliseconds before giving up.
    - * @param {Function} callback Function to call with results.
    - */
    -goog.net.tmpnetwork.testLoadImage = function(url, timeout, callback) {
    -  var channelDebug = new goog.net.ChannelDebug();
    -  channelDebug.debug('TestLoadImage: loading ' + url);
    -  var img = new Image();
    -  img.onload = function() {
    -    try {
    -      channelDebug.debug('TestLoadImage: loaded');
    -      goog.net.tmpnetwork.clearImageCallbacks_(img);
    -      callback(true);
    -    } catch (e) {
    -      channelDebug.dumpException(e);
    -    }
    -  };
    -  img.onerror = function() {
    -    try {
    -      channelDebug.debug('TestLoadImage: error');
    -      goog.net.tmpnetwork.clearImageCallbacks_(img);
    -      callback(false);
    -    } catch (e) {
    -      channelDebug.dumpException(e);
    -    }
    -  };
    -  img.onabort = function() {
    -    try {
    -      channelDebug.debug('TestLoadImage: abort');
    -      goog.net.tmpnetwork.clearImageCallbacks_(img);
    -      callback(false);
    -    } catch (e) {
    -      channelDebug.dumpException(e);
    -    }
    -  };
    -  img.ontimeout = function() {
    -    try {
    -      channelDebug.debug('TestLoadImage: timeout');
    -      goog.net.tmpnetwork.clearImageCallbacks_(img);
    -      callback(false);
    -    } catch (e) {
    -      channelDebug.dumpException(e);
    -    }
    -  };
    -
    -  goog.global.setTimeout(function() {
    -    if (img.ontimeout) {
    -      img.ontimeout();
    -    }
    -  }, timeout);
    -  img.src = url;
    -};
    -
    -
    -/**
    - * Clear handlers to avoid memory leaks.
    - * @param {Image} img The image to clear handlers from.
    - * @private
    - */
    -goog.net.tmpnetwork.clearImageCallbacks_ = function(img) {
    -  // NOTE(user): Nullified individually to avoid compiler warnings
    -  // (BUG 658126)
    -  img.onload = null;
    -  img.onerror = null;
    -  img.onabort = null;
    -  img.ontimeout = null;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/net/websocket.js b/src/database/third_party/closure-library/closure/goog/net/websocket.js
    deleted file mode 100644
    index b3f7ace0974..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/websocket.js
    +++ /dev/null
    @@ -1,513 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Definition of the WebSocket class.  A WebSocket provides a
    - * bi-directional, full-duplex communications channel, over a single TCP socket.
    - *
    - * See http://dev.w3.org/html5/websockets/
    - * for the full HTML5 WebSocket API.
    - *
    - * Typical usage will look like this:
    - *
    - *  var ws = new goog.net.WebSocket();
    - *
    - *  var handler = new goog.events.EventHandler();
    - *  handler.listen(ws, goog.net.WebSocket.EventType.OPENED, onOpen);
    - *  handler.listen(ws, goog.net.WebSocket.EventType.MESSAGE, onMessage);
    - *
    - *  try {
    - *    ws.open('ws://127.0.0.1:4200');
    - *  } catch (e) {
    - *    ...
    - *  }
    - *
    - */
    -
    -goog.provide('goog.net.WebSocket');
    -goog.provide('goog.net.WebSocket.ErrorEvent');
    -goog.provide('goog.net.WebSocket.EventType');
    -goog.provide('goog.net.WebSocket.MessageEvent');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.asserts');
    -goog.require('goog.debug.entryPointRegistry');
    -goog.require('goog.events');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.log');
    -
    -
    -
    -/**
    - * Class encapsulating the logic for using a WebSocket.
    - *
    - * @param {boolean=} opt_autoReconnect True if the web socket should
    - *     automatically reconnect or not.  This is true by default.
    - * @param {function(number):number=} opt_getNextReconnect A function for
    - *     obtaining the time until the next reconnect attempt. Given the reconnect
    - *     attempt count (which is a positive integer), the function should return a
    - *     positive integer representing the milliseconds to the next reconnect
    - *     attempt.  The default function used is an exponential back-off. Note that
    - *     this function is never called if auto reconnect is disabled.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - */
    -goog.net.WebSocket = function(opt_autoReconnect, opt_getNextReconnect) {
    -  goog.net.WebSocket.base(this, 'constructor');
    -
    -  /**
    -   * True if the web socket should automatically reconnect or not.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.autoReconnect_ = goog.isDef(opt_autoReconnect) ?
    -      opt_autoReconnect : true;
    -
    -  /**
    -   * A function for obtaining the time until the next reconnect attempt.
    -   * Given the reconnect attempt count (which is a positive integer), the
    -   * function should return a positive integer representing the milliseconds to
    -   * the next reconnect attempt.
    -   * @type {function(number):number}
    -   * @private
    -   */
    -  this.getNextReconnect_ = opt_getNextReconnect ||
    -      goog.net.WebSocket.EXPONENTIAL_BACKOFF_;
    -
    -  /**
    -   * The time, in milliseconds, that must elapse before the next attempt to
    -   * reconnect.
    -   * @type {number}
    -   * @private
    -   */
    -  this.nextReconnect_ = this.getNextReconnect_(this.reconnectAttempt_);
    -};
    -goog.inherits(goog.net.WebSocket, goog.events.EventTarget);
    -
    -
    -/**
    - * The actual web socket that will be used to send/receive messages.
    - * @type {WebSocket}
    - * @private
    - */
    -goog.net.WebSocket.prototype.webSocket_ = null;
    -
    -
    -/**
    - * The URL to which the web socket will connect.
    - * @type {?string}
    - * @private
    - */
    -goog.net.WebSocket.prototype.url_ = null;
    -
    -
    -/**
    - * The subprotocol name used when establishing the web socket connection.
    - * @type {string|undefined}
    - * @private
    - */
    -goog.net.WebSocket.prototype.protocol_ = undefined;
    -
    -
    -/**
    - * True if a call to the close callback is expected or not.
    - * @type {boolean}
    - * @private
    - */
    -goog.net.WebSocket.prototype.closeExpected_ = false;
    -
    -
    -/**
    - * Keeps track of the number of reconnect attempts made since the last
    - * successful connection.
    - * @type {number}
    - * @private
    - */
    -goog.net.WebSocket.prototype.reconnectAttempt_ = 0;
    -
    -
    -/** @private {?number} */
    -goog.net.WebSocket.prototype.reconnectTimer_ = null;
    -
    -
    -/**
    - * The logger for this class.
    - * @type {goog.log.Logger}
    - * @private
    - */
    -goog.net.WebSocket.prototype.logger_ = goog.log.getLogger(
    -    'goog.net.WebSocket');
    -
    -
    -/**
    - * The events fired by the web socket.
    - * @enum {string} The event types for the web socket.
    - */
    -goog.net.WebSocket.EventType = {
    -
    -  /**
    -   * Fired when an attempt to open the WebSocket fails or there is a connection
    -   * failure after a successful connection has been established.
    -   */
    -  CLOSED: goog.events.getUniqueId('closed'),
    -
    -  /**
    -   * Fired when the WebSocket encounters an error.
    -   */
    -  ERROR: goog.events.getUniqueId('error'),
    -
    -  /**
    -   * Fired when a new message arrives from the WebSocket.
    -   */
    -  MESSAGE: goog.events.getUniqueId('message'),
    -
    -  /**
    -   * Fired when the WebSocket connection has been established.
    -   */
    -  OPENED: goog.events.getUniqueId('opened')
    -};
    -
    -
    -/**
    - * The various states of the web socket.
    - * @enum {number} The states of the web socket.
    - * @private
    - */
    -goog.net.WebSocket.ReadyState_ = {
    -  // This is the initial state during construction.
    -  CONNECTING: 0,
    -  // This is when the socket is actually open and ready for data.
    -  OPEN: 1,
    -  // This is when the socket is in the middle of a close handshake.
    -  // Note that this is a valid state even if the OPEN state was never achieved.
    -  CLOSING: 2,
    -  // This is when the socket is actually closed.
    -  CLOSED: 3
    -};
    -
    -
    -/**
    - * The maximum amount of time between reconnect attempts for the exponential
    - * back-off in milliseconds.
    - * @type {number}
    - * @private
    - */
    -goog.net.WebSocket.EXPONENTIAL_BACKOFF_CEILING_ = 60 * 1000;
    -
    -
    -/**
    - * Computes the next reconnect time given the number of reconnect attempts since
    - * the last successful connection.
    - *
    - * @param {number} attempt The number of reconnect attempts since the last
    - *     connection.
    - * @return {number} The time, in milliseconds, until the next reconnect attempt.
    - * @const
    - * @private
    - */
    -goog.net.WebSocket.EXPONENTIAL_BACKOFF_ = function(attempt) {
    -  var time = Math.pow(2, attempt) * 1000;
    -  return Math.min(time, goog.net.WebSocket.EXPONENTIAL_BACKOFF_CEILING_);
    -};
    -
    -
    -/**
    - * Installs exception protection for all entry points introduced by
    - * goog.net.WebSocket instances which are not protected by
    - * {@link goog.debug.ErrorHandler#protectWindowSetTimeout},
    - * {@link goog.debug.ErrorHandler#protectWindowSetInterval}, or
    - * {@link goog.events.protectBrowserEventEntryPoint}.
    - *
    - * @param {!goog.debug.ErrorHandler} errorHandler Error handler with which to
    - *     protect the entry points.
    - */
    -goog.net.WebSocket.protectEntryPoints = function(errorHandler) {
    -  goog.net.WebSocket.prototype.onOpen_ = errorHandler.protectEntryPoint(
    -      goog.net.WebSocket.prototype.onOpen_);
    -  goog.net.WebSocket.prototype.onClose_ = errorHandler.protectEntryPoint(
    -      goog.net.WebSocket.prototype.onClose_);
    -  goog.net.WebSocket.prototype.onMessage_ = errorHandler.protectEntryPoint(
    -      goog.net.WebSocket.prototype.onMessage_);
    -  goog.net.WebSocket.prototype.onError_ = errorHandler.protectEntryPoint(
    -      goog.net.WebSocket.prototype.onError_);
    -};
    -
    -
    -/**
    - * Creates and opens the actual WebSocket.  Only call this after attaching the
    - * appropriate listeners to this object.  If listeners aren't registered, then
    - * the {@code goog.net.WebSocket.EventType.OPENED} event might be missed.
    - *
    - * @param {string} url The URL to which to connect.
    - * @param {string=} opt_protocol The subprotocol to use.  The connection will
    - *     only be established if the server reports that it has selected this
    - *     subprotocol. The subprotocol name must all be a non-empty ASCII string
    - *     with no control characters and no spaces in them (i.e. only characters
    - *     in the range U+0021 to U+007E).
    - */
    -goog.net.WebSocket.prototype.open = function(url, opt_protocol) {
    -  // Sanity check.  This works only in modern browsers.
    -  goog.asserts.assert(goog.global['WebSocket'],
    -      'This browser does not support WebSocket');
    -
    -  // Don't do anything if the web socket is already open.
    -  goog.asserts.assert(!this.isOpen(), 'The WebSocket is already open');
    -
    -  // Clear any pending attempts to reconnect.
    -  this.clearReconnectTimer_();
    -
    -  // Construct the web socket.
    -  this.url_ = url;
    -  this.protocol_ = opt_protocol;
    -
    -  // This check has to be made otherwise you get protocol mismatch exceptions
    -  // for passing undefined, null, '', or [].
    -  if (this.protocol_) {
    -    goog.log.info(this.logger_, 'Opening the WebSocket on ' + this.url_ +
    -        ' with protocol ' + this.protocol_);
    -    this.webSocket_ = new WebSocket(this.url_, this.protocol_);
    -  } else {
    -    goog.log.info(this.logger_, 'Opening the WebSocket on ' + this.url_);
    -    this.webSocket_ = new WebSocket(this.url_);
    -  }
    -
    -  // Register the event handlers.  Note that it is not possible for these
    -  // callbacks to be missed because it is registered after the web socket is
    -  // instantiated.  Because of the synchronous nature of JavaScript, this code
    -  // will execute before the browser creates the resource and makes any calls
    -  // to these callbacks.
    -  this.webSocket_.onopen = goog.bind(this.onOpen_, this);
    -  this.webSocket_.onclose = goog.bind(this.onClose_, this);
    -  this.webSocket_.onmessage = goog.bind(this.onMessage_, this);
    -  this.webSocket_.onerror = goog.bind(this.onError_, this);
    -};
    -
    -
    -/**
    - * Closes the web socket connection.
    - */
    -goog.net.WebSocket.prototype.close = function() {
    -
    -  // Clear any pending attempts to reconnect.
    -  this.clearReconnectTimer_();
    -
    -  // Attempt to close only if the web socket was created.
    -  if (this.webSocket_) {
    -    goog.log.info(this.logger_, 'Closing the WebSocket.');
    -
    -    // Close is expected here since it was a direct call.  Close is considered
    -    // unexpected when opening the connection fails or there is some other form
    -    // of connection loss after being connected.
    -    this.closeExpected_ = true;
    -    this.webSocket_.close();
    -    this.webSocket_ = null;
    -  }
    -};
    -
    -
    -/**
    - * Sends the message over the web socket.
    - *
    - * @param {string} message The message to send.
    - */
    -goog.net.WebSocket.prototype.send = function(message) {
    -  // Make sure the socket is ready to go before sending a message.
    -  goog.asserts.assert(this.isOpen(), 'Cannot send without an open socket');
    -
    -  // Send the message and let onError_ be called if it fails thereafter.
    -  this.webSocket_.send(message);
    -};
    -
    -
    -/**
    - * Checks to see if the web socket is open or not.
    - *
    - * @return {boolean} True if the web socket is open, false otherwise.
    - */
    -goog.net.WebSocket.prototype.isOpen = function() {
    -  return !!this.webSocket_ &&
    -      this.webSocket_.readyState == goog.net.WebSocket.ReadyState_.OPEN;
    -};
    -
    -
    -/**
    - * Called when the web socket has connected.
    - *
    - * @private
    - */
    -goog.net.WebSocket.prototype.onOpen_ = function() {
    -  goog.log.info(this.logger_, 'WebSocket opened on ' + this.url_);
    -  this.dispatchEvent(goog.net.WebSocket.EventType.OPENED);
    -
    -  // Set the next reconnect interval.
    -  this.reconnectAttempt_ = 0;
    -  this.nextReconnect_ = this.getNextReconnect_(this.reconnectAttempt_);
    -};
    -
    -
    -/**
    - * Called when the web socket has closed.
    - *
    - * @param {!Event} event The close event.
    - * @private
    - */
    -goog.net.WebSocket.prototype.onClose_ = function(event) {
    -  goog.log.info(this.logger_, 'The WebSocket on ' + this.url_ + ' closed.');
    -
    -  // Firing this event allows handlers to query the URL.
    -  this.dispatchEvent(goog.net.WebSocket.EventType.CLOSED);
    -
    -  // Always clear out the web socket on a close event.
    -  this.webSocket_ = null;
    -
    -  // See if this is an expected call to onClose_.
    -  if (this.closeExpected_) {
    -    goog.log.info(this.logger_, 'The WebSocket closed normally.');
    -    // Only clear out the URL if this is a normal close.
    -    this.url_ = null;
    -    this.protocol_ = undefined;
    -  } else {
    -    // Unexpected, so try to reconnect.
    -    goog.log.error(this.logger_, 'The WebSocket disconnected unexpectedly: ' +
    -        event.data);
    -
    -    // Only try to reconnect if it is enabled.
    -    if (this.autoReconnect_) {
    -      // Log the reconnect attempt.
    -      var seconds = Math.floor(this.nextReconnect_ / 1000);
    -      goog.log.info(this.logger_,
    -          'Seconds until next reconnect attempt: ' + seconds);
    -
    -      // Actually schedule the timer.
    -      this.reconnectTimer_ = goog.Timer.callOnce(
    -          goog.bind(this.open, this, this.url_, this.protocol_),
    -          this.nextReconnect_, this);
    -
    -      // Set the next reconnect interval.
    -      this.reconnectAttempt_++;
    -      this.nextReconnect_ = this.getNextReconnect_(this.reconnectAttempt_);
    -    }
    -  }
    -  this.closeExpected_ = false;
    -};
    -
    -
    -/**
    - * Called when a new message arrives from the server.
    - *
    - * @param {MessageEvent<string>} event The web socket message event.
    - * @private
    - */
    -goog.net.WebSocket.prototype.onMessage_ = function(event) {
    -  var message = event.data;
    -  this.dispatchEvent(new goog.net.WebSocket.MessageEvent(message));
    -};
    -
    -
    -/**
    - * Called when there is any error in communication.
    - *
    - * @param {Event} event The error event containing the error data.
    - * @private
    - */
    -goog.net.WebSocket.prototype.onError_ = function(event) {
    -  var data = /** @type {string} */ (event.data);
    -  goog.log.error(this.logger_, 'An error occurred: ' + data);
    -  this.dispatchEvent(new goog.net.WebSocket.ErrorEvent(data));
    -};
    -
    -
    -/**
    - * Clears the reconnect timer.
    - *
    - * @private
    - */
    -goog.net.WebSocket.prototype.clearReconnectTimer_ = function() {
    -  if (goog.isDefAndNotNull(this.reconnectTimer_)) {
    -    goog.Timer.clear(this.reconnectTimer_);
    -  }
    -  this.reconnectTimer_ = null;
    -};
    -
    -
    -/** @override */
    -goog.net.WebSocket.prototype.disposeInternal = function() {
    -  goog.net.WebSocket.base(this, 'disposeInternal');
    -  this.close();
    -};
    -
    -
    -
    -/**
    - * Object representing a new incoming message event.
    - *
    - * @param {string} message The raw message coming from the web socket.
    - * @extends {goog.events.Event}
    - * @constructor
    - * @final
    - */
    -goog.net.WebSocket.MessageEvent = function(message) {
    -  goog.net.WebSocket.MessageEvent.base(
    -      this, 'constructor', goog.net.WebSocket.EventType.MESSAGE);
    -
    -  /**
    -   * The new message from the web socket.
    -   * @type {string}
    -   */
    -  this.message = message;
    -};
    -goog.inherits(goog.net.WebSocket.MessageEvent, goog.events.Event);
    -
    -
    -
    -/**
    - * Object representing an error event. This is fired whenever an error occurs
    - * on the web socket.
    - *
    - * @param {string} data The error data.
    - * @extends {goog.events.Event}
    - * @constructor
    - * @final
    - */
    -goog.net.WebSocket.ErrorEvent = function(data) {
    -  goog.net.WebSocket.ErrorEvent.base(
    -      this, 'constructor', goog.net.WebSocket.EventType.ERROR);
    -
    -  /**
    -   * The error data coming from the web socket.
    -   * @type {string}
    -   */
    -  this.data = data;
    -};
    -goog.inherits(goog.net.WebSocket.ErrorEvent, goog.events.Event);
    -
    -
    -// Register the WebSocket as an entry point, so that it can be monitored for
    -// exception handling, etc.
    -goog.debug.entryPointRegistry.register(
    -    /**
    -     * @param {function(!Function): !Function} transformer The transforming
    -     *     function.
    -     */
    -    function(transformer) {
    -      goog.net.WebSocket.prototype.onOpen_ =
    -          transformer(goog.net.WebSocket.prototype.onOpen_);
    -      goog.net.WebSocket.prototype.onClose_ =
    -          transformer(goog.net.WebSocket.prototype.onClose_);
    -      goog.net.WebSocket.prototype.onMessage_ =
    -          transformer(goog.net.WebSocket.prototype.onMessage_);
    -      goog.net.WebSocket.prototype.onError_ =
    -          transformer(goog.net.WebSocket.prototype.onError_);
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/net/websocket_test.html b/src/database/third_party/closure-library/closure/goog/net/websocket_test.html
    deleted file mode 100644
    index 1d5e8333e5e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/websocket_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.net.WebSocket
    -  </title>
    -  <script type="text/javascript" src="../base.js">
    -  </script>
    -  <script type="text/javascript">
    -    goog.require('goog.net.WebSocketTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/websocket_test.js b/src/database/third_party/closure-library/closure/goog/net/websocket_test.js
    deleted file mode 100644
    index 36539cc4ca5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/websocket_test.js
    +++ /dev/null
    @@ -1,363 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.net.WebSocketTest');
    -goog.setTestOnly('goog.net.WebSocketTest');
    -
    -goog.require('goog.debug.EntryPointMonitor');
    -goog.require('goog.debug.ErrorHandler');
    -goog.require('goog.debug.entryPointRegistry');
    -goog.require('goog.events');
    -goog.require('goog.functions');
    -goog.require('goog.net.WebSocket');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -
    -var webSocket;
    -var mockClock;
    -var pr;
    -var testUrl;
    -
    -var originalOnOpen = goog.net.WebSocket.prototype.onOpen_;
    -var originalOnClose = goog.net.WebSocket.prototype.onClose_;
    -var originalOnMessage = goog.net.WebSocket.prototype.onMessage_;
    -var originalOnError = goog.net.WebSocket.prototype.onError_;
    -
    -function setUp() {
    -  pr = new goog.testing.PropertyReplacer();
    -  pr.set(goog.global, 'WebSocket', MockWebSocket);
    -  mockClock = new goog.testing.MockClock(true);
    -  testUrl = 'ws://127.0.0.1:4200';
    -  testProtocol = 'xmpp';
    -}
    -
    -function tearDown() {
    -  pr.reset();
    -  goog.net.WebSocket.prototype.onOpen_ = originalOnOpen;
    -  goog.net.WebSocket.prototype.onClose_ = originalOnClose;
    -  goog.net.WebSocket.prototype.onMessage_ = originalOnMessage;
    -  goog.net.WebSocket.prototype.onError_ = originalOnError;
    -  goog.dispose(mockClock);
    -  goog.dispose(webSocket);
    -}
    -
    -function testOpenInUnsupportingBrowserThrowsException() {
    -  // Null out WebSocket to simulate lack of support.
    -  if (goog.global.WebSocket) {
    -    goog.global.WebSocket = null;
    -  }
    -
    -  webSocket = new goog.net.WebSocket();
    -  assertThrows('Open should fail if WebSocket is not defined.',
    -      function() {
    -        webSocket.open(testUrl);
    -      });
    -}
    -
    -function testOpenTwiceThrowsException() {
    -  webSocket = new goog.net.WebSocket();
    -  webSocket.open(testUrl);
    -  simulateOpenEvent(webSocket.webSocket_);
    -
    -  assertThrows('Attempting to open a second time should fail.',
    -      function() {
    -        webSocket.open(testUrl);
    -      });
    -}
    -
    -function testSendWithoutOpeningThrowsException() {
    -  webSocket = new goog.net.WebSocket();
    -
    -  assertThrows('Send should fail if the web socket was not first opened.',
    -      function() {
    -        webSocket.send('test message');
    -      });
    -}
    -
    -function testOpenWithProtocol() {
    -  webSocket = new goog.net.WebSocket();
    -  webSocket.open(testUrl, testProtocol);
    -  var ws = webSocket.webSocket_;
    -  simulateOpenEvent(ws);
    -  assertEquals(testUrl, ws.url);
    -  assertEquals(testProtocol, ws.protocol);
    -}
    -
    -function testOpenAndClose() {
    -  webSocket = new goog.net.WebSocket();
    -  assertFalse(webSocket.isOpen());
    -  webSocket.open(testUrl);
    -  var ws = webSocket.webSocket_;
    -  simulateOpenEvent(ws);
    -  assertTrue(webSocket.isOpen());
    -  assertEquals(testUrl, ws.url);
    -  webSocket.close();
    -  simulateCloseEvent(ws);
    -  assertFalse(webSocket.isOpen());
    -}
    -
    -function testReconnectionDisabled() {
    -  // Construct the web socket and disable reconnection.
    -  webSocket = new goog.net.WebSocket(false);
    -
    -  // Record how many times open is called.
    -  pr.set(webSocket, 'open', goog.testing.recordFunction(webSocket.open));
    -
    -  // Open the web socket.
    -  webSocket.open(testUrl);
    -  assertEquals(0, webSocket.reconnectAttempt_);
    -  assertEquals(1, webSocket.open.getCallCount());
    -  assertFalse(webSocket.isOpen());
    -
    -  // Simulate failure.
    -  var ws = webSocket.webSocket_;
    -  simulateCloseEvent(ws);
    -  assertFalse(webSocket.isOpen());
    -  assertEquals(0, webSocket.reconnectAttempt_);
    -  assertEquals(1, webSocket.open.getCallCount());
    -
    -  // Make sure a reconnection doesn't happen.
    -  mockClock.tick(100000);
    -  assertEquals(0, webSocket.reconnectAttempt_);
    -  assertEquals(1, webSocket.open.getCallCount());
    -}
    -
    -function testReconnectionWithFailureOnFirstOpen() {
    -  // Construct the web socket with a linear back-off.
    -  webSocket = new goog.net.WebSocket(true, linearBackOff);
    -
    -  // Record how many times open is called.
    -  pr.set(webSocket, 'open', goog.testing.recordFunction(webSocket.open));
    -
    -  // Open the web socket.
    -  webSocket.open(testUrl, testProtocol);
    -  assertEquals(0, webSocket.reconnectAttempt_);
    -  assertEquals(1, webSocket.open.getCallCount());
    -  assertFalse(webSocket.isOpen());
    -
    -  // Simulate failure.
    -  var ws = webSocket.webSocket_;
    -  simulateCloseEvent(ws);
    -  assertFalse(webSocket.isOpen());
    -  assertEquals(1, webSocket.reconnectAttempt_);
    -  assertEquals(1, webSocket.open.getCallCount());
    -
    -  // Make sure the reconnect doesn't happen before it should.
    -  mockClock.tick(linearBackOff(0) - 1);
    -  assertEquals(1, webSocket.open.getCallCount());
    -  mockClock.tick(1);
    -  assertEquals(2, webSocket.open.getCallCount());
    -
    -  // Simulate another failure.
    -  simulateCloseEvent(ws);
    -  assertFalse(webSocket.isOpen());
    -  assertEquals(2, webSocket.reconnectAttempt_);
    -  assertEquals(2, webSocket.open.getCallCount());
    -
    -  // Make sure the reconnect doesn't happen before it should.
    -  mockClock.tick(linearBackOff(1) - 1);
    -  assertEquals(2, webSocket.open.getCallCount());
    -  mockClock.tick(1);
    -  assertEquals(3, webSocket.open.getCallCount());
    -
    -  // Simulate connection success.
    -  simulateOpenEvent(ws);
    -  assertEquals(0, webSocket.reconnectAttempt_);
    -  assertEquals(3, webSocket.open.getCallCount());
    -
    -  // Make sure the reconnection has the same url and protocol.
    -  assertEquals(testUrl, ws.url);
    -  assertEquals(testProtocol, ws.protocol);
    -
    -  // Ensure no further calls to open are made.
    -  mockClock.tick(linearBackOff(10));
    -  assertEquals(3, webSocket.open.getCallCount());
    -}
    -
    -function testReconnectionWithFailureAfterOpen() {
    -  // Construct the web socket with a linear back-off.
    -  webSocket = new goog.net.WebSocket(true, fibonacciBackOff);
    -
    -  // Record how many times open is called.
    -  pr.set(webSocket, 'open', goog.testing.recordFunction(webSocket.open));
    -
    -  // Open the web socket.
    -  webSocket.open(testUrl);
    -  assertEquals(0, webSocket.reconnectAttempt_);
    -  assertEquals(1, webSocket.open.getCallCount());
    -  assertFalse(webSocket.isOpen());
    -
    -  // Simulate connection success.
    -  var ws = webSocket.webSocket_;
    -  simulateOpenEvent(ws);
    -  assertEquals(0, webSocket.reconnectAttempt_);
    -  assertEquals(1, webSocket.open.getCallCount());
    -
    -  // Let some time pass, then fail the connection.
    -  mockClock.tick(100000);
    -  simulateCloseEvent(ws);
    -  assertFalse(webSocket.isOpen());
    -  assertEquals(1, webSocket.reconnectAttempt_);
    -  assertEquals(1, webSocket.open.getCallCount());
    -
    -  // Make sure the reconnect doesn't happen before it should.
    -  mockClock.tick(fibonacciBackOff(0) - 1);
    -  assertEquals(1, webSocket.open.getCallCount());
    -  mockClock.tick(1);
    -  assertEquals(2, webSocket.open.getCallCount());
    -
    -  // Simulate connection success.
    -  ws = webSocket.webSocket_;
    -  simulateOpenEvent(ws);
    -  assertEquals(0, webSocket.reconnectAttempt_);
    -  assertEquals(2, webSocket.open.getCallCount());
    -
    -  // Ensure no further calls to open are made.
    -  mockClock.tick(fibonacciBackOff(10));
    -  assertEquals(2, webSocket.open.getCallCount());
    -}
    -
    -function testExponentialBackOff() {
    -  assertEquals(1000, goog.net.WebSocket.EXPONENTIAL_BACKOFF_(0));
    -  assertEquals(2000, goog.net.WebSocket.EXPONENTIAL_BACKOFF_(1));
    -  assertEquals(4000, goog.net.WebSocket.EXPONENTIAL_BACKOFF_(2));
    -  assertEquals(60000, goog.net.WebSocket.EXPONENTIAL_BACKOFF_(6));
    -  assertEquals(60000, goog.net.WebSocket.EXPONENTIAL_BACKOFF_(7));
    -}
    -
    -function testEntryPointRegistry() {
    -  var monitor = new goog.debug.EntryPointMonitor();
    -  var replacement = function() {};
    -  monitor.wrap = goog.testing.recordFunction(
    -      goog.functions.constant(replacement));
    -
    -  goog.debug.entryPointRegistry.monitorAll(monitor);
    -  assertTrue(monitor.wrap.getCallCount() >= 1);
    -  assertEquals(replacement, goog.net.WebSocket.prototype.onOpen_);
    -  assertEquals(replacement, goog.net.WebSocket.prototype.onClose_);
    -  assertEquals(replacement, goog.net.WebSocket.prototype.onMessage_);
    -  assertEquals(replacement, goog.net.WebSocket.prototype.onError_);
    -}
    -
    -function testErrorHandlerCalled() {
    -  var errorHandlerCalled = false;
    -  var errorHandler = new goog.debug.ErrorHandler(function() {
    -    errorHandlerCalled = true;
    -  });
    -  goog.net.WebSocket.protectEntryPoints(errorHandler);
    -
    -  webSocket = new goog.net.WebSocket();
    -  goog.events.listenOnce(webSocket, goog.net.WebSocket.EventType.OPENED,
    -      function() {
    -        throw Error();
    -      });
    -
    -  webSocket.open(testUrl);
    -  var ws = webSocket.webSocket_;
    -  assertThrows(function() {
    -    simulateOpenEvent(ws);
    -  });
    -
    -  assertTrue('Error handler callback should be called when registered as ' +
    -      'protecting the entry points.', errorHandlerCalled);
    -}
    -
    -
    -/**
    - * Simulates the browser firing the open event for the given web socket.
    - * @param {MockWebSocket} ws The mock web socket.
    - */
    -function simulateOpenEvent(ws) {
    -  ws.readyState = goog.net.WebSocket.ReadyState_.OPEN;
    -  ws.onopen();
    -}
    -
    -
    -/**
    - * Simulates the browser firing the close event for the given web socket.
    - * @param {MockWebSocket} ws The mock web socket.
    - */
    -function simulateCloseEvent(ws) {
    -  ws.readyState = goog.net.WebSocket.ReadyState_.CLOSED;
    -  ws.onclose({data: 'mock close event'});
    -}
    -
    -
    -/**
    - * Strategy for reconnection that backs off linearly with a 1 second offset.
    - * @param {number} attempt The number of reconnects since the last connection.
    - * @return {number} The amount of time to the next reconnect, in milliseconds.
    - */
    -function linearBackOff(attempt) {
    -  return (attempt * 1000) + 1000;
    -}
    -
    -
    -/**
    - * Strategy for reconnection that backs off with the fibonacci pattern.  It is
    - * offset by 5 seconds so the first attempt will happen after 5 seconds.
    - * @param {number} attempt The number of reconnects since the last connection.
    - * @return {number} The amount of time to the next reconnect, in milliseconds.
    - */
    -function fibonacciBackOff(attempt) {
    -  return (fibonacci(attempt) * 1000) + 5000;
    -}
    -
    -
    -/**
    - * Computes the desired fibonacci number.
    - * @param {number} n The nth desired fibonacci number.
    - * @return {number} The nth fibonacci number.
    - */
    -function fibonacci(n) {
    -  if (n == 0) {
    -    return 0;
    -  } else if (n == 1) {
    -    return 1;
    -  } else {
    -    return fibonacci(n - 2) + fibonacci(n - 1);
    -  }
    -}
    -
    -
    -
    -/**
    - * Mock WebSocket constructor.
    - * @param {string} url The url to the web socket server.
    - * @param {string} protocol The protocol to use.
    - * @constructor
    - */
    -MockWebSocket = function(url, protocol) {
    -  this.url = url;
    -  this.protocol = protocol;
    -  this.readyState = goog.net.WebSocket.ReadyState_.CONNECTING;
    -};
    -
    -
    -/**
    - * Mocks out the close method of the WebSocket.
    - */
    -MockWebSocket.prototype.close = function() {
    -  this.readyState = goog.net.WebSocket.ReadyState_.CLOSING;
    -};
    -
    -
    -/**
    - * Mocks out the send method of the WebSocket.
    - */
    -MockWebSocket.prototype.send = function() {
    -  // Nothing to do here.
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/net/wrapperxmlhttpfactory.js b/src/database/third_party/closure-library/closure/goog/net/wrapperxmlhttpfactory.js
    deleted file mode 100644
    index 76156932ef3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/wrapperxmlhttpfactory.js
    +++ /dev/null
    @@ -1,71 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Implementation of XmlHttpFactory which allows construction from
    - * simple factory methods.
    - * @author dbk@google.com (David Barrett-Kahn)
    - */
    -
    -goog.provide('goog.net.WrapperXmlHttpFactory');
    -
    -/** @suppress {extraRequire} Typedef. */
    -goog.require('goog.net.XhrLike');
    -goog.require('goog.net.XmlHttpFactory');
    -
    -
    -
    -/**
    - * An xhr factory subclass which can be constructed using two factory methods.
    - * This exists partly to allow the preservation of goog.net.XmlHttp.setFactory()
    - * with an unchanged signature.
    - * @param {function():!goog.net.XhrLike.OrNative} xhrFactory
    - *     A function which returns a new XHR object.
    - * @param {function():!Object} optionsFactory A function which returns the
    - *     options associated with xhr objects from this factory.
    - * @extends {goog.net.XmlHttpFactory}
    - * @constructor
    - * @final
    - */
    -goog.net.WrapperXmlHttpFactory = function(xhrFactory, optionsFactory) {
    -  goog.net.XmlHttpFactory.call(this);
    -
    -  /**
    -   * XHR factory method.
    -   * @type {function() : !goog.net.XhrLike.OrNative}
    -   * @private
    -   */
    -  this.xhrFactory_ = xhrFactory;
    -
    -  /**
    -   * Options factory method.
    -   * @type {function() : !Object}
    -   * @private
    -   */
    -  this.optionsFactory_ = optionsFactory;
    -};
    -goog.inherits(goog.net.WrapperXmlHttpFactory, goog.net.XmlHttpFactory);
    -
    -
    -/** @override */
    -goog.net.WrapperXmlHttpFactory.prototype.createInstance = function() {
    -  return this.xhrFactory_();
    -};
    -
    -
    -/** @override */
    -goog.net.WrapperXmlHttpFactory.prototype.getOptions = function() {
    -  return this.optionsFactory_();
    -};
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xhrio.js b/src/database/third_party/closure-library/closure/goog/net/xhrio.js
    deleted file mode 100644
    index 2edb794a584..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xhrio.js
    +++ /dev/null
    @@ -1,1224 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Wrapper class for handling XmlHttpRequests.
    - *
    - * One off requests can be sent through goog.net.XhrIo.send() or an
    - * instance can be created to send multiple requests.  Each request uses its
    - * own XmlHttpRequest object and handles clearing of the event callback to
    - * ensure no leaks.
    - *
    - * XhrIo is event based, it dispatches events when a request finishes, fails or
    - * succeeds or when the ready-state changes. The ready-state or timeout event
    - * fires first, followed by a generic completed event. Then the abort, error,
    - * or success event is fired as appropriate. Lastly, the ready event will fire
    - * to indicate that the object may be used to make another request.
    - *
    - * The error event may also be called before completed and
    - * ready-state-change if the XmlHttpRequest.open() or .send() methods throw.
    - *
    - * This class does not support multiple requests, queuing, or prioritization.
    - *
    - * Tested = IE6, FF1.5, Safari, Opera 8.5
    - *
    - * TODO(user): Error cases aren't playing nicely in Safari.
    - *
    - */
    -
    -
    -goog.provide('goog.net.XhrIo');
    -goog.provide('goog.net.XhrIo.ResponseType');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.array');
    -goog.require('goog.debug.entryPointRegistry');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.json');
    -goog.require('goog.log');
    -goog.require('goog.net.ErrorCode');
    -goog.require('goog.net.EventType');
    -goog.require('goog.net.HttpStatus');
    -goog.require('goog.net.XmlHttp');
    -goog.require('goog.object');
    -goog.require('goog.string');
    -goog.require('goog.structs');
    -goog.require('goog.structs.Map');
    -goog.require('goog.uri.utils');
    -goog.require('goog.userAgent');
    -
    -goog.forwardDeclare('goog.Uri');
    -
    -
    -
    -/**
    - * Basic class for handling XMLHttpRequests.
    - * @param {goog.net.XmlHttpFactory=} opt_xmlHttpFactory Factory to use when
    - *     creating XMLHttpRequest objects.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - */
    -goog.net.XhrIo = function(opt_xmlHttpFactory) {
    -  goog.net.XhrIo.base(this, 'constructor');
    -
    -  /**
    -   * Map of default headers to add to every request, use:
    -   * XhrIo.headers.set(name, value)
    -   * @type {!goog.structs.Map}
    -   */
    -  this.headers = new goog.structs.Map();
    -
    -  /**
    -   * Optional XmlHttpFactory
    -   * @private {goog.net.XmlHttpFactory}
    -   */
    -  this.xmlHttpFactory_ = opt_xmlHttpFactory || null;
    -
    -  /**
    -   * Whether XMLHttpRequest is active.  A request is active from the time send()
    -   * is called until onReadyStateChange() is complete, or error() or abort()
    -   * is called.
    -   * @private {boolean}
    -   */
    -  this.active_ = false;
    -
    -  /**
    -   * The XMLHttpRequest object that is being used for the transfer.
    -   * @private {?goog.net.XhrLike.OrNative}
    -   */
    -  this.xhr_ = null;
    -
    -  /**
    -   * The options to use with the current XMLHttpRequest object.
    -   * @private {Object}
    -   */
    -  this.xhrOptions_ = null;
    -
    -  /**
    -   * Last URL that was requested.
    -   * @private {string|goog.Uri}
    -   */
    -  this.lastUri_ = '';
    -
    -  /**
    -   * Method for the last request.
    -   * @private {string}
    -   */
    -  this.lastMethod_ = '';
    -
    -  /**
    -   * Last error code.
    -   * @private {!goog.net.ErrorCode}
    -   */
    -  this.lastErrorCode_ = goog.net.ErrorCode.NO_ERROR;
    -
    -  /**
    -   * Last error message.
    -   * @private {Error|string}
    -   */
    -  this.lastError_ = '';
    -
    -  /**
    -   * Used to ensure that we don't dispatch an multiple ERROR events. This can
    -   * happen in IE when it does a synchronous load and one error is handled in
    -   * the ready statte change and one is handled due to send() throwing an
    -   * exception.
    -   * @private {boolean}
    -   */
    -  this.errorDispatched_ = false;
    -
    -  /**
    -   * Used to make sure we don't fire the complete event from inside a send call.
    -   * @private {boolean}
    -   */
    -  this.inSend_ = false;
    -
    -  /**
    -   * Used in determining if a call to {@link #onReadyStateChange_} is from
    -   * within a call to this.xhr_.open.
    -   * @private {boolean}
    -   */
    -  this.inOpen_ = false;
    -
    -  /**
    -   * Used in determining if a call to {@link #onReadyStateChange_} is from
    -   * within a call to this.xhr_.abort.
    -   * @private {boolean}
    -   */
    -  this.inAbort_ = false;
    -
    -  /**
    -   * Number of milliseconds after which an incomplete request will be aborted
    -   * and a {@link goog.net.EventType.TIMEOUT} event raised; 0 means no timeout
    -   * is set.
    -   * @private {number}
    -   */
    -  this.timeoutInterval_ = 0;
    -
    -  /**
    -   * Timer to track request timeout.
    -   * @private {?number}
    -   */
    -  this.timeoutId_ = null;
    -
    -  /**
    -   * The requested type for the response. The empty string means use the default
    -   * XHR behavior.
    -   * @private {goog.net.XhrIo.ResponseType}
    -   */
    -  this.responseType_ = goog.net.XhrIo.ResponseType.DEFAULT;
    -
    -  /**
    -   * Whether a "credentialed" request is to be sent (one that is aware of
    -   * cookies and authentication). This is applicable only for cross-domain
    -   * requests and more recent browsers that support this part of the HTTP Access
    -   * Control standard.
    -   *
    -   * @see http://www.w3.org/TR/XMLHttpRequest/#the-withcredentials-attribute
    -   *
    -   * @private {boolean}
    -   */
    -  this.withCredentials_ = false;
    -
    -  /**
    -   * True if we can use XMLHttpRequest's timeout directly.
    -   * @private {boolean}
    -   */
    -  this.useXhr2Timeout_ = false;
    -};
    -goog.inherits(goog.net.XhrIo, goog.events.EventTarget);
    -
    -
    -/**
    - * Response types that may be requested for XMLHttpRequests.
    - * @enum {string}
    - * @see http://www.w3.org/TR/XMLHttpRequest/#the-responsetype-attribute
    - */
    -goog.net.XhrIo.ResponseType = {
    -  DEFAULT: '',
    -  TEXT: 'text',
    -  DOCUMENT: 'document',
    -  // Not supported as of Chrome 10.0.612.1 dev
    -  BLOB: 'blob',
    -  ARRAY_BUFFER: 'arraybuffer'
    -};
    -
    -
    -/**
    - * A reference to the XhrIo logger
    - * @private {goog.debug.Logger}
    - * @const
    - */
    -goog.net.XhrIo.prototype.logger_ =
    -    goog.log.getLogger('goog.net.XhrIo');
    -
    -
    -/**
    - * The Content-Type HTTP header name
    - * @type {string}
    - */
    -goog.net.XhrIo.CONTENT_TYPE_HEADER = 'Content-Type';
    -
    -
    -/**
    - * The pattern matching the 'http' and 'https' URI schemes
    - * @type {!RegExp}
    - */
    -goog.net.XhrIo.HTTP_SCHEME_PATTERN = /^https?$/i;
    -
    -
    -/**
    - * The methods that typically come along with form data.  We set different
    - * headers depending on whether the HTTP action is one of these.
    - */
    -goog.net.XhrIo.METHODS_WITH_FORM_DATA = ['POST', 'PUT'];
    -
    -
    -/**
    - * The Content-Type HTTP header value for a url-encoded form
    - * @type {string}
    - */
    -goog.net.XhrIo.FORM_CONTENT_TYPE =
    -    'application/x-www-form-urlencoded;charset=utf-8';
    -
    -
    -/**
    - * The XMLHttpRequest Level two timeout delay ms property name.
    - *
    - * @see http://www.w3.org/TR/XMLHttpRequest/#the-timeout-attribute
    - *
    - * @private {string}
    - * @const
    - */
    -goog.net.XhrIo.XHR2_TIMEOUT_ = 'timeout';
    -
    -
    -/**
    - * The XMLHttpRequest Level two ontimeout handler property name.
    - *
    - * @see http://www.w3.org/TR/XMLHttpRequest/#the-timeout-attribute
    - *
    - * @private {string}
    - * @const
    - */
    -goog.net.XhrIo.XHR2_ON_TIMEOUT_ = 'ontimeout';
    -
    -
    -/**
    - * All non-disposed instances of goog.net.XhrIo created
    - * by {@link goog.net.XhrIo.send} are in this Array.
    - * @see goog.net.XhrIo.cleanup
    - * @private {!Array<!goog.net.XhrIo>}
    - */
    -goog.net.XhrIo.sendInstances_ = [];
    -
    -
    -/**
    - * Static send that creates a short lived instance of XhrIo to send the
    - * request.
    - * @see goog.net.XhrIo.cleanup
    - * @param {string|goog.Uri} url Uri to make request to.
    - * @param {?function(this:goog.net.XhrIo, ?)=} opt_callback Callback function
    - *     for when request is complete.
    - * @param {string=} opt_method Send method, default: GET.
    - * @param {ArrayBuffer|ArrayBufferView|Blob|Document|FormData|string=}
    - *     opt_content Body data.
    - * @param {Object|goog.structs.Map=} opt_headers Map of headers to add to the
    - *     request.
    - * @param {number=} opt_timeoutInterval Number of milliseconds after which an
    - *     incomplete request will be aborted; 0 means no timeout is set.
    - * @param {boolean=} opt_withCredentials Whether to send credentials with the
    - *     request. Default to false. See {@link goog.net.XhrIo#setWithCredentials}.
    - * @return {!goog.net.XhrIo} The sent XhrIo.
    - */
    -goog.net.XhrIo.send = function(url, opt_callback, opt_method, opt_content,
    -                               opt_headers, opt_timeoutInterval,
    -                               opt_withCredentials) {
    -  var x = new goog.net.XhrIo();
    -  goog.net.XhrIo.sendInstances_.push(x);
    -  if (opt_callback) {
    -    x.listen(goog.net.EventType.COMPLETE, opt_callback);
    -  }
    -  x.listenOnce(goog.net.EventType.READY, x.cleanupSend_);
    -  if (opt_timeoutInterval) {
    -    x.setTimeoutInterval(opt_timeoutInterval);
    -  }
    -  if (opt_withCredentials) {
    -    x.setWithCredentials(opt_withCredentials);
    -  }
    -  x.send(url, opt_method, opt_content, opt_headers);
    -  return x;
    -};
    -
    -
    -/**
    - * Disposes all non-disposed instances of goog.net.XhrIo created by
    - * {@link goog.net.XhrIo.send}.
    - * {@link goog.net.XhrIo.send} cleans up the goog.net.XhrIo instance
    - * it creates when the request completes or fails.  However, if
    - * the request never completes, then the goog.net.XhrIo is not disposed.
    - * This can occur if the window is unloaded before the request completes.
    - * We could have {@link goog.net.XhrIo.send} return the goog.net.XhrIo
    - * it creates and make the client of {@link goog.net.XhrIo.send} be
    - * responsible for disposing it in this case.  However, this makes things
    - * significantly more complicated for the client, and the whole point
    - * of {@link goog.net.XhrIo.send} is that it's simple and easy to use.
    - * Clients of {@link goog.net.XhrIo.send} should call
    - * {@link goog.net.XhrIo.cleanup} when doing final
    - * cleanup on window unload.
    - */
    -goog.net.XhrIo.cleanup = function() {
    -  var instances = goog.net.XhrIo.sendInstances_;
    -  while (instances.length) {
    -    instances.pop().dispose();
    -  }
    -};
    -
    -
    -/**
    - * Installs exception protection for all entry point introduced by
    - * goog.net.XhrIo instances which are not protected by
    - * {@link goog.debug.ErrorHandler#protectWindowSetTimeout},
    - * {@link goog.debug.ErrorHandler#protectWindowSetInterval}, or
    - * {@link goog.events.protectBrowserEventEntryPoint}.
    - *
    - * @param {goog.debug.ErrorHandler} errorHandler Error handler with which to
    - *     protect the entry point(s).
    - */
    -goog.net.XhrIo.protectEntryPoints = function(errorHandler) {
    -  goog.net.XhrIo.prototype.onReadyStateChangeEntryPoint_ =
    -      errorHandler.protectEntryPoint(
    -          goog.net.XhrIo.prototype.onReadyStateChangeEntryPoint_);
    -};
    -
    -
    -/**
    - * Disposes of the specified goog.net.XhrIo created by
    - * {@link goog.net.XhrIo.send} and removes it from
    - * {@link goog.net.XhrIo.pendingStaticSendInstances_}.
    - * @private
    - */
    -goog.net.XhrIo.prototype.cleanupSend_ = function() {
    -  this.dispose();
    -  goog.array.remove(goog.net.XhrIo.sendInstances_, this);
    -};
    -
    -
    -/**
    - * Returns the number of milliseconds after which an incomplete request will be
    - * aborted, or 0 if no timeout is set.
    - * @return {number} Timeout interval in milliseconds.
    - */
    -goog.net.XhrIo.prototype.getTimeoutInterval = function() {
    -  return this.timeoutInterval_;
    -};
    -
    -
    -/**
    - * Sets the number of milliseconds after which an incomplete request will be
    - * aborted and a {@link goog.net.EventType.TIMEOUT} event raised; 0 means no
    - * timeout is set.
    - * @param {number} ms Timeout interval in milliseconds; 0 means none.
    - */
    -goog.net.XhrIo.prototype.setTimeoutInterval = function(ms) {
    -  this.timeoutInterval_ = Math.max(0, ms);
    -};
    -
    -
    -/**
    - * Sets the desired type for the response. At time of writing, this is only
    - * supported in very recent versions of WebKit (10.0.612.1 dev and later).
    - *
    - * If this is used, the response may only be accessed via {@link #getResponse}.
    - *
    - * @param {goog.net.XhrIo.ResponseType} type The desired type for the response.
    - */
    -goog.net.XhrIo.prototype.setResponseType = function(type) {
    -  this.responseType_ = type;
    -};
    -
    -
    -/**
    - * Gets the desired type for the response.
    - * @return {goog.net.XhrIo.ResponseType} The desired type for the response.
    - */
    -goog.net.XhrIo.prototype.getResponseType = function() {
    -  return this.responseType_;
    -};
    -
    -
    -/**
    - * Sets whether a "credentialed" request that is aware of cookie and
    - * authentication information should be made. This option is only supported by
    - * browsers that support HTTP Access Control. As of this writing, this option
    - * is not supported in IE.
    - *
    - * @param {boolean} withCredentials Whether this should be a "credentialed"
    - *     request.
    - */
    -goog.net.XhrIo.prototype.setWithCredentials = function(withCredentials) {
    -  this.withCredentials_ = withCredentials;
    -};
    -
    -
    -/**
    - * Gets whether a "credentialed" request is to be sent.
    - * @return {boolean} The desired type for the response.
    - */
    -goog.net.XhrIo.prototype.getWithCredentials = function() {
    -  return this.withCredentials_;
    -};
    -
    -
    -/**
    - * Instance send that actually uses XMLHttpRequest to make a server call.
    - * @param {string|goog.Uri} url Uri to make request to.
    - * @param {string=} opt_method Send method, default: GET.
    - * @param {ArrayBuffer|ArrayBufferView|Blob|Document|FormData|string=}
    - *     opt_content Body data.
    - * @param {Object|goog.structs.Map=} opt_headers Map of headers to add to the
    - *     request.
    - */
    -goog.net.XhrIo.prototype.send = function(url, opt_method, opt_content,
    -                                         opt_headers) {
    -  if (this.xhr_) {
    -    throw Error('[goog.net.XhrIo] Object is active with another request=' +
    -        this.lastUri_ + '; newUri=' + url);
    -  }
    -
    -  var method = opt_method ? opt_method.toUpperCase() : 'GET';
    -
    -  this.lastUri_ = url;
    -  this.lastError_ = '';
    -  this.lastErrorCode_ = goog.net.ErrorCode.NO_ERROR;
    -  this.lastMethod_ = method;
    -  this.errorDispatched_ = false;
    -  this.active_ = true;
    -
    -  // Use the factory to create the XHR object and options
    -  this.xhr_ = this.createXhr();
    -  this.xhrOptions_ = this.xmlHttpFactory_ ?
    -      this.xmlHttpFactory_.getOptions() : goog.net.XmlHttp.getOptions();
    -
    -  // Set up the onreadystatechange callback
    -  this.xhr_.onreadystatechange = goog.bind(this.onReadyStateChange_, this);
    -
    -  /**
    -   * Try to open the XMLHttpRequest (always async), if an error occurs here it
    -   * is generally permission denied
    -   * @preserveTry
    -   */
    -  try {
    -    goog.log.fine(this.logger_, this.formatMsg_('Opening Xhr'));
    -    this.inOpen_ = true;
    -    this.xhr_.open(method, String(url), true);  // Always async!
    -    this.inOpen_ = false;
    -  } catch (err) {
    -    goog.log.fine(this.logger_,
    -        this.formatMsg_('Error opening Xhr: ' + err.message));
    -    this.error_(goog.net.ErrorCode.EXCEPTION, err);
    -    return;
    -  }
    -
    -  // We can't use null since this won't allow requests with form data to have a
    -  // content length specified which will cause some proxies to return a 411
    -  // error.
    -  var content = opt_content || '';
    -
    -  var headers = this.headers.clone();
    -
    -  // Add headers specific to this request
    -  if (opt_headers) {
    -    goog.structs.forEach(opt_headers, function(value, key) {
    -      headers.set(key, value);
    -    });
    -  }
    -
    -  // Find whether a content type header is set, ignoring case.
    -  // HTTP header names are case-insensitive.  See:
    -  // http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
    -  var contentTypeKey = goog.array.find(headers.getKeys(),
    -      goog.net.XhrIo.isContentTypeHeader_);
    -
    -  var contentIsFormData = (goog.global['FormData'] &&
    -      (content instanceof goog.global['FormData']));
    -  if (goog.array.contains(goog.net.XhrIo.METHODS_WITH_FORM_DATA, method) &&
    -      !contentTypeKey && !contentIsFormData) {
    -    // For requests typically with form data, default to the url-encoded form
    -    // content type unless this is a FormData request.  For FormData,
    -    // the browser will automatically add a multipart/form-data content type
    -    // with an appropriate multipart boundary.
    -    headers.set(goog.net.XhrIo.CONTENT_TYPE_HEADER,
    -                goog.net.XhrIo.FORM_CONTENT_TYPE);
    -  }
    -
    -  // Add the headers to the Xhr object
    -  headers.forEach(function(value, key) {
    -    this.xhr_.setRequestHeader(key, value);
    -  }, this);
    -
    -  if (this.responseType_) {
    -    this.xhr_.responseType = this.responseType_;
    -  }
    -
    -  if (goog.object.containsKey(this.xhr_, 'withCredentials')) {
    -    this.xhr_.withCredentials = this.withCredentials_;
    -  }
    -
    -  /**
    -   * Try to send the request, or other wise report an error (404 not found).
    -   * @preserveTry
    -   */
    -  try {
    -    this.cleanUpTimeoutTimer_(); // Paranoid, should never be running.
    -    if (this.timeoutInterval_ > 0) {
    -      this.useXhr2Timeout_ = goog.net.XhrIo.shouldUseXhr2Timeout_(this.xhr_);
    -      goog.log.fine(this.logger_, this.formatMsg_('Will abort after ' +
    -          this.timeoutInterval_ + 'ms if incomplete, xhr2 ' +
    -          this.useXhr2Timeout_));
    -      if (this.useXhr2Timeout_) {
    -        this.xhr_[goog.net.XhrIo.XHR2_TIMEOUT_] = this.timeoutInterval_;
    -        this.xhr_[goog.net.XhrIo.XHR2_ON_TIMEOUT_] =
    -            goog.bind(this.timeout_, this);
    -      } else {
    -        this.timeoutId_ = goog.Timer.callOnce(this.timeout_,
    -            this.timeoutInterval_, this);
    -      }
    -    }
    -    goog.log.fine(this.logger_, this.formatMsg_('Sending request'));
    -    this.inSend_ = true;
    -    this.xhr_.send(content);
    -    this.inSend_ = false;
    -
    -  } catch (err) {
    -    goog.log.fine(this.logger_, this.formatMsg_('Send error: ' + err.message));
    -    this.error_(goog.net.ErrorCode.EXCEPTION, err);
    -  }
    -};
    -
    -
    -/**
    - * Determines if the argument is an XMLHttpRequest that supports the level 2
    - * timeout value and event.
    - *
    - * Currently, FF 21.0 OS X has the fields but won't actually call the timeout
    - * handler.  Perhaps the confusion in the bug referenced below hasn't
    - * entirely been resolved.
    - *
    - * @see http://www.w3.org/TR/XMLHttpRequest/#the-timeout-attribute
    - * @see https://bugzilla.mozilla.org/show_bug.cgi?id=525816
    - *
    - * @param {!goog.net.XhrLike.OrNative} xhr The request.
    - * @return {boolean} True if the request supports level 2 timeout.
    - * @private
    - */
    -goog.net.XhrIo.shouldUseXhr2Timeout_ = function(xhr) {
    -  return goog.userAgent.IE &&
    -      goog.userAgent.isVersionOrHigher(9) &&
    -      goog.isNumber(xhr[goog.net.XhrIo.XHR2_TIMEOUT_]) &&
    -      goog.isDef(xhr[goog.net.XhrIo.XHR2_ON_TIMEOUT_]);
    -};
    -
    -
    -/**
    - * @param {string} header An HTTP header key.
    - * @return {boolean} Whether the key is a content type header (ignoring
    - *     case.
    - * @private
    - */
    -goog.net.XhrIo.isContentTypeHeader_ = function(header) {
    -  return goog.string.caseInsensitiveEquals(
    -      goog.net.XhrIo.CONTENT_TYPE_HEADER, header);
    -};
    -
    -
    -/**
    - * Creates a new XHR object.
    - * @return {!goog.net.XhrLike.OrNative} The newly created XHR object.
    - * @protected
    - */
    -goog.net.XhrIo.prototype.createXhr = function() {
    -  return this.xmlHttpFactory_ ?
    -      this.xmlHttpFactory_.createInstance() : goog.net.XmlHttp();
    -};
    -
    -
    -/**
    - * The request didn't complete after {@link goog.net.XhrIo#timeoutInterval_}
    - * milliseconds; raises a {@link goog.net.EventType.TIMEOUT} event and aborts
    - * the request.
    - * @private
    - */
    -goog.net.XhrIo.prototype.timeout_ = function() {
    -  if (typeof goog == 'undefined') {
    -    // If goog is undefined then the callback has occurred as the application
    -    // is unloading and will error.  Thus we let it silently fail.
    -  } else if (this.xhr_) {
    -    this.lastError_ = 'Timed out after ' + this.timeoutInterval_ +
    -                      'ms, aborting';
    -    this.lastErrorCode_ = goog.net.ErrorCode.TIMEOUT;
    -    goog.log.fine(this.logger_, this.formatMsg_(this.lastError_));
    -    this.dispatchEvent(goog.net.EventType.TIMEOUT);
    -    this.abort(goog.net.ErrorCode.TIMEOUT);
    -  }
    -};
    -
    -
    -/**
    - * Something errorred, so inactivate, fire error callback and clean up
    - * @param {goog.net.ErrorCode} errorCode The error code.
    - * @param {Error} err The error object.
    - * @private
    - */
    -goog.net.XhrIo.prototype.error_ = function(errorCode, err) {
    -  this.active_ = false;
    -  if (this.xhr_) {
    -    this.inAbort_ = true;
    -    this.xhr_.abort();  // Ensures XHR isn't hung (FF)
    -    this.inAbort_ = false;
    -  }
    -  this.lastError_ = err;
    -  this.lastErrorCode_ = errorCode;
    -  this.dispatchErrors_();
    -  this.cleanUpXhr_();
    -};
    -
    -
    -/**
    - * Dispatches COMPLETE and ERROR in case of an error. This ensures that we do
    - * not dispatch multiple error events.
    - * @private
    - */
    -goog.net.XhrIo.prototype.dispatchErrors_ = function() {
    -  if (!this.errorDispatched_) {
    -    this.errorDispatched_ = true;
    -    this.dispatchEvent(goog.net.EventType.COMPLETE);
    -    this.dispatchEvent(goog.net.EventType.ERROR);
    -  }
    -};
    -
    -
    -/**
    - * Abort the current XMLHttpRequest
    - * @param {goog.net.ErrorCode=} opt_failureCode Optional error code to use -
    - *     defaults to ABORT.
    - */
    -goog.net.XhrIo.prototype.abort = function(opt_failureCode) {
    -  if (this.xhr_ && this.active_) {
    -    goog.log.fine(this.logger_, this.formatMsg_('Aborting'));
    -    this.active_ = false;
    -    this.inAbort_ = true;
    -    this.xhr_.abort();
    -    this.inAbort_ = false;
    -    this.lastErrorCode_ = opt_failureCode || goog.net.ErrorCode.ABORT;
    -    this.dispatchEvent(goog.net.EventType.COMPLETE);
    -    this.dispatchEvent(goog.net.EventType.ABORT);
    -    this.cleanUpXhr_();
    -  }
    -};
    -
    -
    -/**
    - * Nullifies all callbacks to reduce risks of leaks.
    - * @override
    - * @protected
    - */
    -goog.net.XhrIo.prototype.disposeInternal = function() {
    -  if (this.xhr_) {
    -    // We explicitly do not call xhr_.abort() unless active_ is still true.
    -    // This is to avoid unnecessarily aborting a successful request when
    -    // dispose() is called in a callback triggered by a complete response, but
    -    // in which browser cleanup has not yet finished.
    -    // (See http://b/issue?id=1684217.)
    -    if (this.active_) {
    -      this.active_ = false;
    -      this.inAbort_ = true;
    -      this.xhr_.abort();
    -      this.inAbort_ = false;
    -    }
    -    this.cleanUpXhr_(true);
    -  }
    -
    -  goog.net.XhrIo.base(this, 'disposeInternal');
    -};
    -
    -
    -/**
    - * Internal handler for the XHR object's readystatechange event.  This method
    - * checks the status and the readystate and fires the correct callbacks.
    - * If the request has ended, the handlers are cleaned up and the XHR object is
    - * nullified.
    - * @private
    - */
    -goog.net.XhrIo.prototype.onReadyStateChange_ = function() {
    -  if (this.isDisposed()) {
    -    // This method is the target of an untracked goog.Timer.callOnce().
    -    return;
    -  }
    -  if (!this.inOpen_ && !this.inSend_ && !this.inAbort_) {
    -    // Were not being called from within a call to this.xhr_.send
    -    // this.xhr_.abort, or this.xhr_.open, so this is an entry point
    -    this.onReadyStateChangeEntryPoint_();
    -  } else {
    -    this.onReadyStateChangeHelper_();
    -  }
    -};
    -
    -
    -/**
    - * Used to protect the onreadystatechange handler entry point.  Necessary
    - * as {#onReadyStateChange_} maybe called from within send or abort, this
    - * method is only called when {#onReadyStateChange_} is called as an
    - * entry point.
    - * {@see #protectEntryPoints}
    - * @private
    - */
    -goog.net.XhrIo.prototype.onReadyStateChangeEntryPoint_ = function() {
    -  this.onReadyStateChangeHelper_();
    -};
    -
    -
    -/**
    - * Helper for {@link #onReadyStateChange_}.  This is used so that
    - * entry point calls to {@link #onReadyStateChange_} can be routed through
    - * {@link #onReadyStateChangeEntryPoint_}.
    - * @private
    - */
    -goog.net.XhrIo.prototype.onReadyStateChangeHelper_ = function() {
    -  if (!this.active_) {
    -    // can get called inside abort call
    -    return;
    -  }
    -
    -  if (typeof goog == 'undefined') {
    -    // NOTE(user): If goog is undefined then the callback has occurred as the
    -    // application is unloading and will error.  Thus we let it silently fail.
    -
    -  } else if (
    -      this.xhrOptions_[goog.net.XmlHttp.OptionType.LOCAL_REQUEST_ERROR] &&
    -      this.getReadyState() == goog.net.XmlHttp.ReadyState.COMPLETE &&
    -      this.getStatus() == 2) {
    -    // NOTE(user): In IE if send() errors on a *local* request the readystate
    -    // is still changed to COMPLETE.  We need to ignore it and allow the
    -    // try/catch around send() to pick up the error.
    -    goog.log.fine(this.logger_, this.formatMsg_(
    -        'Local request error detected and ignored'));
    -
    -  } else {
    -
    -    // In IE when the response has been cached we sometimes get the callback
    -    // from inside the send call and this usually breaks code that assumes that
    -    // XhrIo is asynchronous.  If that is the case we delay the callback
    -    // using a timer.
    -    if (this.inSend_ &&
    -        this.getReadyState() == goog.net.XmlHttp.ReadyState.COMPLETE) {
    -      goog.Timer.callOnce(this.onReadyStateChange_, 0, this);
    -      return;
    -    }
    -
    -    this.dispatchEvent(goog.net.EventType.READY_STATE_CHANGE);
    -
    -    // readyState indicates the transfer has finished
    -    if (this.isComplete()) {
    -      goog.log.fine(this.logger_, this.formatMsg_('Request complete'));
    -
    -      this.active_ = false;
    -
    -      try {
    -        // Call the specific callbacks for success or failure. Only call the
    -        // success if the status is 200 (HTTP_OK) or 304 (HTTP_CACHED)
    -        if (this.isSuccess()) {
    -          this.dispatchEvent(goog.net.EventType.COMPLETE);
    -          this.dispatchEvent(goog.net.EventType.SUCCESS);
    -        } else {
    -          this.lastErrorCode_ = goog.net.ErrorCode.HTTP_ERROR;
    -          this.lastError_ =
    -              this.getStatusText() + ' [' + this.getStatus() + ']';
    -          this.dispatchErrors_();
    -        }
    -      } finally {
    -        this.cleanUpXhr_();
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Remove the listener to protect against leaks, and nullify the XMLHttpRequest
    - * object.
    - * @param {boolean=} opt_fromDispose If this is from the dispose (don't want to
    - *     fire any events).
    - * @private
    - */
    -goog.net.XhrIo.prototype.cleanUpXhr_ = function(opt_fromDispose) {
    -  if (this.xhr_) {
    -    // Cancel any pending timeout event handler.
    -    this.cleanUpTimeoutTimer_();
    -
    -    // Save reference so we can mark it as closed after the READY event.  The
    -    // READY event may trigger another request, thus we must nullify this.xhr_
    -    var xhr = this.xhr_;
    -    var clearedOnReadyStateChange =
    -        this.xhrOptions_[goog.net.XmlHttp.OptionType.USE_NULL_FUNCTION] ?
    -            goog.nullFunction : null;
    -    this.xhr_ = null;
    -    this.xhrOptions_ = null;
    -
    -    if (!opt_fromDispose) {
    -      this.dispatchEvent(goog.net.EventType.READY);
    -    }
    -
    -    try {
    -      // NOTE(user): Not nullifying in FireFox can still leak if the callbacks
    -      // are defined in the same scope as the instance of XhrIo. But, IE doesn't
    -      // allow you to set the onreadystatechange to NULL so nullFunction is
    -      // used.
    -      xhr.onreadystatechange = clearedOnReadyStateChange;
    -    } catch (e) {
    -      // This seems to occur with a Gears HTTP request. Delayed the setting of
    -      // this onreadystatechange until after READY is sent out and catching the
    -      // error to see if we can track down the problem.
    -      goog.log.error(this.logger_,
    -          'Problem encountered resetting onreadystatechange: ' + e.message);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Make sure the timeout timer isn't running.
    - * @private
    - */
    -goog.net.XhrIo.prototype.cleanUpTimeoutTimer_ = function() {
    -  if (this.xhr_ && this.useXhr2Timeout_) {
    -    this.xhr_[goog.net.XhrIo.XHR2_ON_TIMEOUT_] = null;
    -  }
    -  if (goog.isNumber(this.timeoutId_)) {
    -    goog.Timer.clear(this.timeoutId_);
    -    this.timeoutId_ = null;
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} Whether there is an active request.
    - */
    -goog.net.XhrIo.prototype.isActive = function() {
    -  return !!this.xhr_;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the request has completed.
    - */
    -goog.net.XhrIo.prototype.isComplete = function() {
    -  return this.getReadyState() == goog.net.XmlHttp.ReadyState.COMPLETE;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the request completed with a success.
    - */
    -goog.net.XhrIo.prototype.isSuccess = function() {
    -  var status = this.getStatus();
    -  // A zero status code is considered successful for local files.
    -  return goog.net.HttpStatus.isSuccess(status) ||
    -      status === 0 && !this.isLastUriEffectiveSchemeHttp_();
    -};
    -
    -
    -/**
    - * @return {boolean} whether the effective scheme of the last URI that was
    - *     fetched was 'http' or 'https'.
    - * @private
    - */
    -goog.net.XhrIo.prototype.isLastUriEffectiveSchemeHttp_ = function() {
    -  var scheme = goog.uri.utils.getEffectiveScheme(String(this.lastUri_));
    -  return goog.net.XhrIo.HTTP_SCHEME_PATTERN.test(scheme);
    -};
    -
    -
    -/**
    - * Get the readystate from the Xhr object
    - * Will only return correct result when called from the context of a callback
    - * @return {goog.net.XmlHttp.ReadyState} goog.net.XmlHttp.ReadyState.*.
    - */
    -goog.net.XhrIo.prototype.getReadyState = function() {
    -  return this.xhr_ ?
    -      /** @type {goog.net.XmlHttp.ReadyState} */ (this.xhr_.readyState) :
    -      goog.net.XmlHttp.ReadyState.UNINITIALIZED;
    -};
    -
    -
    -/**
    - * Get the status from the Xhr object
    - * Will only return correct result when called from the context of a callback
    - * @return {number} Http status.
    - */
    -goog.net.XhrIo.prototype.getStatus = function() {
    -  /**
    -   * IE doesn't like you checking status until the readystate is greater than 2
    -   * (i.e. it is receiving or complete).  The try/catch is used for when the
    -   * page is unloading and an ERROR_NOT_AVAILABLE may occur when accessing xhr_.
    -   * @preserveTry
    -   */
    -  try {
    -    return this.getReadyState() > goog.net.XmlHttp.ReadyState.LOADED ?
    -        this.xhr_.status : -1;
    -  } catch (e) {
    -    return -1;
    -  }
    -};
    -
    -
    -/**
    - * Get the status text from the Xhr object
    - * Will only return correct result when called from the context of a callback
    - * @return {string} Status text.
    - */
    -goog.net.XhrIo.prototype.getStatusText = function() {
    -  /**
    -   * IE doesn't like you checking status until the readystate is greater than 2
    -   * (i.e. it is recieving or complete).  The try/catch is used for when the
    -   * page is unloading and an ERROR_NOT_AVAILABLE may occur when accessing xhr_.
    -   * @preserveTry
    -   */
    -  try {
    -    return this.getReadyState() > goog.net.XmlHttp.ReadyState.LOADED ?
    -        this.xhr_.statusText : '';
    -  } catch (e) {
    -    goog.log.fine(this.logger_, 'Can not get status: ' + e.message);
    -    return '';
    -  }
    -};
    -
    -
    -/**
    - * Get the last Uri that was requested
    - * @return {string} Last Uri.
    - */
    -goog.net.XhrIo.prototype.getLastUri = function() {
    -  return String(this.lastUri_);
    -};
    -
    -
    -/**
    - * Get the response text from the Xhr object
    - * Will only return correct result when called from the context of a callback.
    - * @return {string} Result from the server, or '' if no result available.
    - */
    -goog.net.XhrIo.prototype.getResponseText = function() {
    -  /** @preserveTry */
    -  try {
    -    return this.xhr_ ? this.xhr_.responseText : '';
    -  } catch (e) {
    -    // http://www.w3.org/TR/XMLHttpRequest/#the-responsetext-attribute
    -    // states that responseText should return '' (and responseXML null)
    -    // when the state is not LOADING or DONE. Instead, IE can
    -    // throw unexpected exceptions, for example when a request is aborted
    -    // or no data is available yet.
    -    goog.log.fine(this.logger_, 'Can not get responseText: ' + e.message);
    -    return '';
    -  }
    -};
    -
    -
    -/**
    - * Get the response body from the Xhr object. This property is only available
    - * in IE since version 7 according to MSDN:
    - * http://msdn.microsoft.com/en-us/library/ie/ms534368(v=vs.85).aspx
    - * Will only return correct result when called from the context of a callback.
    - *
    - * One option is to construct a VBArray from the returned object and convert
    - * it to a JavaScript array using the toArray method:
    - * {@code (new window['VBArray'](xhrIo.getResponseBody())).toArray()}
    - * This will result in an array of numbers in the range of [0..255]
    - *
    - * Another option is to use the VBScript CStr method to convert it into a
    - * string as outlined in http://stackoverflow.com/questions/1919972
    - *
    - * @return {Object} Binary result from the server or null if not available.
    - */
    -goog.net.XhrIo.prototype.getResponseBody = function() {
    -  /** @preserveTry */
    -  try {
    -    if (this.xhr_ && 'responseBody' in this.xhr_) {
    -      return this.xhr_['responseBody'];
    -    }
    -  } catch (e) {
    -    // IE can throw unexpected exceptions, for example when a request is aborted
    -    // or no data is yet available.
    -    goog.log.fine(this.logger_, 'Can not get responseBody: ' + e.message);
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * Get the response XML from the Xhr object
    - * Will only return correct result when called from the context of a callback.
    - * @return {Document} The DOM Document representing the XML file, or null
    - * if no result available.
    - */
    -goog.net.XhrIo.prototype.getResponseXml = function() {
    -  /** @preserveTry */
    -  try {
    -    return this.xhr_ ? this.xhr_.responseXML : null;
    -  } catch (e) {
    -    goog.log.fine(this.logger_, 'Can not get responseXML: ' + e.message);
    -    return null;
    -  }
    -};
    -
    -
    -/**
    - * Get the response and evaluates it as JSON from the Xhr object
    - * Will only return correct result when called from the context of a callback
    - * @param {string=} opt_xssiPrefix Optional XSSI prefix string to use for
    - *     stripping of the response before parsing. This needs to be set only if
    - *     your backend server prepends the same prefix string to the JSON response.
    - * @return {Object|undefined} JavaScript object.
    - */
    -goog.net.XhrIo.prototype.getResponseJson = function(opt_xssiPrefix) {
    -  if (!this.xhr_) {
    -    return undefined;
    -  }
    -
    -  var responseText = this.xhr_.responseText;
    -  if (opt_xssiPrefix && responseText.indexOf(opt_xssiPrefix) == 0) {
    -    responseText = responseText.substring(opt_xssiPrefix.length);
    -  }
    -
    -  return goog.json.parse(responseText);
    -};
    -
    -
    -/**
    - * Get the response as the type specificed by {@link #setResponseType}. At time
    - * of writing, this is only directly supported in very recent versions of WebKit
    - * (10.0.612.1 dev and later). If the field is not supported directly, we will
    - * try to emulate it.
    - *
    - * Emulating the response means following the rules laid out at
    - * http://www.w3.org/TR/XMLHttpRequest/#the-response-attribute
    - *
    - * On browsers with no support for this (Chrome < 10, Firefox < 4, etc), only
    - * response types of DEFAULT or TEXT may be used, and the response returned will
    - * be the text response.
    - *
    - * On browsers with Mozilla's draft support for array buffers (Firefox 4, 5),
    - * only response types of DEFAULT, TEXT, and ARRAY_BUFFER may be used, and the
    - * response returned will be either the text response or the Mozilla
    - * implementation of the array buffer response.
    - *
    - * On browsers will full support, any valid response type supported by the
    - * browser may be used, and the response provided by the browser will be
    - * returned.
    - *
    - * @return {*} The response.
    - */
    -goog.net.XhrIo.prototype.getResponse = function() {
    -  /** @preserveTry */
    -  try {
    -    if (!this.xhr_) {
    -      return null;
    -    }
    -    if ('response' in this.xhr_) {
    -      return this.xhr_.response;
    -    }
    -    switch (this.responseType_) {
    -      case goog.net.XhrIo.ResponseType.DEFAULT:
    -      case goog.net.XhrIo.ResponseType.TEXT:
    -        return this.xhr_.responseText;
    -        // DOCUMENT and BLOB don't need to be handled here because they are
    -        // introduced in the same spec that adds the .response field, and would
    -        // have been caught above.
    -        // ARRAY_BUFFER needs an implementation for Firefox 4, where it was
    -        // implemented using a draft spec rather than the final spec.
    -      case goog.net.XhrIo.ResponseType.ARRAY_BUFFER:
    -        if ('mozResponseArrayBuffer' in this.xhr_) {
    -          return this.xhr_.mozResponseArrayBuffer;
    -        }
    -    }
    -    // Fell through to a response type that is not supported on this browser.
    -    goog.log.error(this.logger_,
    -        'Response type ' + this.responseType_ + ' is not ' +
    -        'supported on this browser');
    -    return null;
    -  } catch (e) {
    -    goog.log.fine(this.logger_, 'Can not get response: ' + e.message);
    -    return null;
    -  }
    -};
    -
    -
    -/**
    - * Get the value of the response-header with the given name from the Xhr object
    - * Will only return correct result when called from the context of a callback
    - * and the request has completed
    - * @param {string} key The name of the response-header to retrieve.
    - * @return {string|undefined} The value of the response-header named key.
    - */
    -goog.net.XhrIo.prototype.getResponseHeader = function(key) {
    -  return this.xhr_ && this.isComplete() ?
    -      this.xhr_.getResponseHeader(key) : undefined;
    -};
    -
    -
    -/**
    - * Gets the text of all the headers in the response.
    - * Will only return correct result when called from the context of a callback
    - * and the request has completed.
    - * @return {string} The value of the response headers or empty string.
    - */
    -goog.net.XhrIo.prototype.getAllResponseHeaders = function() {
    -  return this.xhr_ && this.isComplete() ?
    -      this.xhr_.getAllResponseHeaders() : '';
    -};
    -
    -
    -/**
    - * Returns all response headers as a key-value map.
    - * Multiple values for the same header key can be combined into one,
    - * separated by a comma and a space.
    - * Note that the native getResponseHeader method for retrieving a single header
    - * does a case insensitive match on the header name. This method does not
    - * include any case normalization logic, it will just return a key-value
    - * representation of the headers.
    - * See: http://www.w3.org/TR/XMLHttpRequest/#the-getresponseheader()-method
    - * @return {!Object<string, string>} An object with the header keys as keys
    - *     and header values as values.
    - */
    -goog.net.XhrIo.prototype.getResponseHeaders = function() {
    -  var headersObject = {};
    -  var headersArray = this.getAllResponseHeaders().split('\r\n');
    -  for (var i = 0; i < headersArray.length; i++) {
    -    if (goog.string.isEmptyOrWhitespace(headersArray[i])) {
    -      continue;
    -    }
    -    var keyValue = goog.string.splitLimit(headersArray[i], ': ', 2);
    -    if (headersObject[keyValue[0]]) {
    -      headersObject[keyValue[0]] += ', ' + keyValue[1];
    -    } else {
    -      headersObject[keyValue[0]] = keyValue[1];
    -    }
    -  }
    -  return headersObject;
    -};
    -
    -
    -/**
    - * Get the last error message
    - * @return {goog.net.ErrorCode} Last error code.
    - */
    -goog.net.XhrIo.prototype.getLastErrorCode = function() {
    -  return this.lastErrorCode_;
    -};
    -
    -
    -/**
    - * Get the last error message
    - * @return {string} Last error message.
    - */
    -goog.net.XhrIo.prototype.getLastError = function() {
    -  return goog.isString(this.lastError_) ? this.lastError_ :
    -      String(this.lastError_);
    -};
    -
    -
    -/**
    - * Adds the last method, status and URI to the message.  This is used to add
    - * this information to the logging calls.
    - * @param {string} msg The message text that we want to add the extra text to.
    - * @return {string} The message with the extra text appended.
    - * @private
    - */
    -goog.net.XhrIo.prototype.formatMsg_ = function(msg) {
    -  return msg + ' [' + this.lastMethod_ + ' ' + this.lastUri_ + ' ' +
    -      this.getStatus() + ']';
    -};
    -
    -
    -// Register the xhr handler as an entry point, so that
    -// it can be monitored for exception handling, etc.
    -goog.debug.entryPointRegistry.register(
    -    /**
    -     * @param {function(!Function): !Function} transformer The transforming
    -     *     function.
    -     */
    -    function(transformer) {
    -      goog.net.XhrIo.prototype.onReadyStateChangeEntryPoint_ =
    -          transformer(goog.net.XhrIo.prototype.onReadyStateChangeEntryPoint_);
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xhrio_test.html b/src/database/third_party/closure-library/closure/goog/net/xhrio_test.html
    deleted file mode 100644
    index 6c9745ba6ff..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xhrio_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -  Author: arv@google.com (Erik Arvidsson)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.net.XhrIo
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.net.XhrIoTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xhrio_test.js b/src/database/third_party/closure-library/closure/goog/net/xhrio_test.js
    deleted file mode 100644
    index 39801404c5a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xhrio_test.js
    +++ /dev/null
    @@ -1,794 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.net.XhrIoTest');
    -goog.setTestOnly('goog.net.XhrIoTest');
    -
    -goog.require('goog.Uri');
    -goog.require('goog.debug.EntryPointMonitor');
    -goog.require('goog.debug.ErrorHandler');
    -goog.require('goog.debug.entryPointRegistry');
    -goog.require('goog.events');
    -goog.require('goog.functions');
    -goog.require('goog.net.EventType');
    -goog.require('goog.net.WrapperXmlHttpFactory');
    -goog.require('goog.net.XhrIo');
    -goog.require('goog.net.XmlHttp');
    -goog.require('goog.object');
    -goog.require('goog.string');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.net.XhrIo');
    -goog.require('goog.testing.recordFunction');
    -
    -function MockXmlHttp() {
    -  /**
    -   * The headers for this XmlHttpRequest.
    -   * @type {!Object<string>}
    -   */
    -  this.headers = {};
    -}
    -
    -MockXmlHttp.prototype.readyState = goog.net.XmlHttp.ReadyState.UNINITIALIZED;
    -
    -MockXmlHttp.prototype.status = 200;
    -
    -MockXmlHttp.syncSend = false;
    -
    -MockXmlHttp.prototype.send = function(opt_data) {
    -  this.readyState = goog.net.XmlHttp.ReadyState.UNINITIALIZED;
    -
    -  if (MockXmlHttp.syncSend) {
    -    this.complete();
    -  }
    -
    -};
    -
    -MockXmlHttp.prototype.complete = function() {
    -  this.readyState = goog.net.XmlHttp.ReadyState.LOADING;
    -  this.onreadystatechange();
    -
    -  this.readyState = goog.net.XmlHttp.ReadyState.LOADED;
    -  this.onreadystatechange();
    -
    -  this.readyState = goog.net.XmlHttp.ReadyState.INTERACTIVE;
    -  this.onreadystatechange();
    -
    -  this.readyState = goog.net.XmlHttp.ReadyState.COMPLETE;
    -  this.onreadystatechange();
    -};
    -
    -
    -MockXmlHttp.prototype.open = function(verb, uri, async) {
    -};
    -
    -MockXmlHttp.prototype.abort = function() {};
    -
    -MockXmlHttp.prototype.setRequestHeader = function(key, value) {
    -  this.headers[key] = value;
    -};
    -
    -var lastMockXmlHttp;
    -goog.net.XmlHttp.setGlobalFactory(new goog.net.WrapperXmlHttpFactory(
    -    function() {
    -      lastMockXmlHttp = new MockXmlHttp();
    -      return lastMockXmlHttp;
    -    },
    -    function() {
    -      return {};
    -    }));
    -
    -
    -var propertyReplacer = new goog.testing.PropertyReplacer();
    -var clock;
    -var originalEntryPoint =
    -    goog.net.XhrIo.prototype.onReadyStateChangeEntryPoint_;
    -
    -function setUp() {
    -  lastMockXmlHttp = null;
    -  clock = new goog.testing.MockClock(true);
    -}
    -
    -function tearDown() {
    -  propertyReplacer.reset();
    -  clock.dispose();
    -  goog.net.XhrIo.prototype.onReadyStateChangeEntryPoint_ = originalEntryPoint;
    -}
    -
    -
    -function testSyncSend() {
    -  MockXmlHttp.syncSend = true;
    -  var count = 0;
    -
    -  var x = new goog.net.XhrIo;
    -  goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
    -    assertFalse('Should not fire complete from inside send', inSend);
    -    assertTrue('Should be succesful', e.target.isSuccess());
    -    count++;
    -
    -  });
    -
    -  var inSend = true;
    -  x.send('url');
    -  inSend = false;
    -
    -  clock.tick(1); // callOnce(f, 0, ...)
    -
    -  assertEquals('Complete should have been called once', 1, count);
    -}
    -
    -function testSyncSendFailure() {
    -  MockXmlHttp.syncSend = true;
    -  var count = 0;
    -
    -  var x = new goog.net.XhrIo;
    -  goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
    -    assertFalse('Should not fire complete from inside send', inSend);
    -    assertFalse('Should not be succesful', e.target.isSuccess());
    -    count++;
    -  });
    -
    -  var inSend = true;
    -  x.send('url');
    -  lastMockXmlHttp.status = 404;
    -  inSend = false;
    -
    -  clock.tick(1); // callOnce(f, 0, ...)
    -
    -  assertEquals('Complete should have been called once', 1, count);
    -}
    -
    -
    -function testSendRelativeZeroStatus() {
    -  MockXmlHttp.syncSend = true;
    -  var count = 0;
    -
    -  var x = new goog.net.XhrIo;
    -  goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
    -    assertFalse('Should not fire complete from inside send', inSend);
    -    assertEquals('Should be the same as ', e.target.isSuccess(),
    -        window.location.href.toLowerCase().indexOf('file:') == 0);
    -    count++;
    -  });
    -
    -  var inSend = true;
    -  x.send('relative');
    -  lastMockXmlHttp.status = 0;
    -  inSend = false;
    -
    -  clock.tick(1); // callOnce(f, 0, ...)
    -
    -  assertEquals('Complete should have been called once', 1, count);
    -}
    -
    -
    -function testSendRelativeUriZeroStatus() {
    -  MockXmlHttp.syncSend = true;
    -  var count = 0;
    -
    -  var x = new goog.net.XhrIo;
    -  goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
    -    assertFalse('Should not fire complete from inside send', inSend);
    -    assertEquals('Should be the same as ', e.target.isSuccess(),
    -        window.location.href.toLowerCase().indexOf('file:') == 0);
    -    count++;
    -  });
    -
    -  var inSend = true;
    -  x.send(goog.Uri.parse('relative'));
    -  lastMockXmlHttp.status = 0;
    -  inSend = false;
    -
    -  clock.tick(1); // callOnce(f, 0, ...)
    -
    -  assertEquals('Complete should have been called once', 1, count);
    -}
    -
    -
    -function testSendHttpZeroStatusFailure() {
    -  MockXmlHttp.syncSend = true;
    -  var count = 0;
    -
    -  var x = new goog.net.XhrIo;
    -  goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
    -    assertFalse('Should not fire complete from inside send', inSend);
    -    assertFalse('Should not be succesful', e.target.isSuccess());
    -    count++;
    -  });
    -
    -  var inSend = true;
    -  x.send('http://foo');
    -  lastMockXmlHttp.status = 0;
    -  inSend = false;
    -
    -  clock.tick(1); // callOnce(f, 0, ...)
    -
    -  assertEquals('Complete should have been called once', 1, count);
    -}
    -
    -
    -function testSendHttpUpperZeroStatusFailure() {
    -  MockXmlHttp.syncSend = true;
    -  var count = 0;
    -
    -  var x = new goog.net.XhrIo;
    -  goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
    -    assertFalse('Should not fire complete from inside send', inSend);
    -    assertFalse('Should not be succesful', e.target.isSuccess());
    -    count++;
    -  });
    -
    -  var inSend = true;
    -  x.send('HTTP://foo');
    -  lastMockXmlHttp.status = 0;
    -  inSend = false;
    -
    -  clock.tick(1); // callOnce(f, 0, ...)
    -
    -  assertEquals('Complete should have been called once', 1, count);
    -}
    -
    -
    -function testSendHttpUpperUriZeroStatusFailure() {
    -  MockXmlHttp.syncSend = true;
    -  var count = 0;
    -
    -  var x = new goog.net.XhrIo;
    -  goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
    -    assertFalse('Should not fire complete from inside send', inSend);
    -    assertFalse('Should not be succesful', e.target.isSuccess());
    -    count++;
    -  });
    -
    -  var inSend = true;
    -  x.send(goog.Uri.parse('HTTP://foo'));
    -  lastMockXmlHttp.status = 0;
    -  inSend = false;
    -
    -  clock.tick(1); // callOnce(f, 0, ...)
    -
    -  assertEquals('Complete should have been called once', 1, count);
    -}
    -
    -
    -function testSendHttpUriZeroStatusFailure() {
    -  MockXmlHttp.syncSend = true;
    -  var count = 0;
    -
    -  var x = new goog.net.XhrIo;
    -  goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
    -    assertFalse('Should not fire complete from inside send', inSend);
    -    assertFalse('Should not be succesful', e.target.isSuccess());
    -    count++;
    -  });
    -
    -  var inSend = true;
    -  x.send(goog.Uri.parse('http://foo'));
    -  lastMockXmlHttp.status = 0;
    -  inSend = false;
    -
    -  clock.tick(1); // callOnce(f, 0, ...)
    -
    -  assertEquals('Complete should have been called once', 1, count);
    -}
    -
    -
    -function testSendHttpUriZeroStatusFailure() {
    -  MockXmlHttp.syncSend = true;
    -  var count = 0;
    -
    -  var x = new goog.net.XhrIo;
    -  goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
    -    assertFalse('Should not fire complete from inside send', inSend);
    -    assertFalse('Should not be succesful', e.target.isSuccess());
    -    count++;
    -  });
    -
    -  var inSend = true;
    -  x.send(goog.Uri.parse('HTTP://foo'));
    -  lastMockXmlHttp.status = 0;
    -  inSend = false;
    -
    -  clock.tick(1); // callOnce(f, 0, ...)
    -
    -  assertEquals('Complete should have been called once', 1, count);
    -}
    -
    -
    -function testSendHttpsZeroStatusFailure() {
    -  MockXmlHttp.syncSend = true;
    -  var count = 0;
    -
    -  var x = new goog.net.XhrIo;
    -  goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
    -    assertFalse('Should not fire complete from inside send', inSend);
    -    assertFalse('Should not be succesful', e.target.isSuccess());
    -    count++;
    -  });
    -
    -  var inSend = true;
    -  x.send('https://foo');
    -  lastMockXmlHttp.status = 0;
    -  inSend = false;
    -
    -  clock.tick(1); // callOnce(f, 0, ...)
    -
    -  assertEquals('Complete should have been called once', 1, count);
    -}
    -
    -
    -function testSendFileUpperZeroStatusSuccess() {
    -  MockXmlHttp.syncSend = true;
    -  var count = 0;
    -
    -  var x = new goog.net.XhrIo;
    -  goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
    -    assertFalse('Should not fire complete from inside send', inSend);
    -    assertTrue('Should not be succesful', e.target.isSuccess());
    -    count++;
    -  });
    -
    -  var inSend = true;
    -  x.send('FILE:///foo');
    -  lastMockXmlHttp.status = 0;
    -  inSend = false;
    -
    -  clock.tick(1); // callOnce(f, 0, ...)
    -
    -  assertEquals('Complete should have been called once', 1, count);
    -}
    -
    -
    -function testSendFileUriZeroStatusSuccess() {
    -  MockXmlHttp.syncSend = true;
    -  var count = 0;
    -
    -  var x = new goog.net.XhrIo;
    -  goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
    -    assertFalse('Should not fire complete from inside send', inSend);
    -    assertTrue('Should not be succesful', e.target.isSuccess());
    -    count++;
    -  });
    -
    -  var inSend = true;
    -  x.send(goog.Uri.parse('file:///foo'));
    -  lastMockXmlHttp.status = 0;
    -  inSend = false;
    -
    -  clock.tick(1); // callOnce(f, 0, ...)
    -
    -  assertEquals('Complete should have been called once', 1, count);
    -}
    -
    -
    -function testSendDummyUriZeroStatusSuccess() {
    -  MockXmlHttp.syncSend = true;
    -  var count = 0;
    -
    -  var x = new goog.net.XhrIo;
    -  goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
    -    assertFalse('Should not fire complete from inside send', inSend);
    -    assertTrue('Should not be succesful', e.target.isSuccess());
    -    count++;
    -  });
    -
    -  var inSend = true;
    -  x.send(goog.Uri.parse('dummy:///foo'));
    -  lastMockXmlHttp.status = 0;
    -  inSend = false;
    -
    -  clock.tick(1); // callOnce(f, 0, ...)
    -
    -  assertEquals('Complete should have been called once', 1, count);
    -}
    -
    -
    -function testSendFileUpperUriZeroStatusSuccess() {
    -  MockXmlHttp.syncSend = true;
    -  var count = 0;
    -
    -  var x = new goog.net.XhrIo;
    -  goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
    -    assertFalse('Should not fire complete from inside send', inSend);
    -    assertTrue('Should not be succesful', e.target.isSuccess());
    -    count++;
    -  });
    -
    -  var inSend = true;
    -  x.send(goog.Uri.parse('FILE:///foo'));
    -  lastMockXmlHttp.status = 0;
    -  inSend = false;
    -
    -  clock.tick(1); // callOnce(f, 0, ...)
    -
    -  assertEquals('Complete should have been called once', 1, count);
    -}
    -
    -
    -function testSendFromListener() {
    -  MockXmlHttp.syncSend = true;
    -  var count = 0;
    -
    -  var x = new goog.net.XhrIo;
    -  goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
    -    count++;
    -
    -    var e = assertThrows(function() {
    -      x.send('url2');
    -    });
    -    assertEquals('[goog.net.XhrIo] Object is active with another request=url' +
    -        '; newUri=url2', e.message);
    -  });
    -
    -  x.send('url');
    -
    -  clock.tick(1); // callOnce(f, 0, ...)
    -
    -  assertEquals('Complete should have been called once', 1, count);
    -}
    -
    -
    -function testStatesDuringEvents() {
    -  MockXmlHttp.syncSend = true;
    -
    -  var x = new goog.net.XhrIo;
    -  var readyState = goog.net.XmlHttp.ReadyState.UNINITIALIZED;
    -  goog.events.listen(x, goog.net.EventType.READY_STATE_CHANGE, function(e) {
    -    readyState++;
    -    assertObjectEquals(e.target, x);
    -    assertEquals(x.getReadyState(), readyState);
    -    assertTrue(x.isActive());
    -  });
    -  goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
    -    assertObjectEquals(e.target, x);
    -    assertTrue(x.isActive());
    -  });
    -  goog.events.listen(x, goog.net.EventType.SUCCESS, function(e) {
    -    assertObjectEquals(e.target, x);
    -    assertTrue(x.isActive());
    -  });
    -  goog.events.listen(x, goog.net.EventType.READY, function(e) {
    -    assertObjectEquals(e.target, x);
    -    assertFalse(x.isActive());
    -  });
    -
    -  x.send('url');
    -
    -  clock.tick(1); // callOnce(f, 0, ...)
    -}
    -
    -
    -function testProtectEntryPointCalledOnAsyncSend() {
    -  MockXmlHttp.syncSend = false;
    -
    -  var errorHandlerCallbackCalled = false;
    -  var errorHandler = new goog.debug.ErrorHandler(function() {
    -    errorHandlerCallbackCalled = true;
    -  });
    -
    -  goog.net.XhrIo.protectEntryPoints(errorHandler);
    -
    -  var x = new goog.net.XhrIo;
    -  goog.events.listen(x, goog.net.EventType.READY_STATE_CHANGE, function(e) {
    -    throw Error();
    -  });
    -
    -  x.send('url');
    -  assertThrows(function() {
    -    lastMockXmlHttp.complete();
    -  });
    -
    -  assertTrue('Error handler callback should be called on async send.',
    -      errorHandlerCallbackCalled);
    -}
    -
    -function testXHRIsDiposedEvenIfAListenerThrowsAnExceptionOnComplete() {
    -  MockXmlHttp.syncSend = false;
    -
    -  var x = new goog.net.XhrIo;
    -
    -  goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
    -    throw Error();
    -  }, false, x);
    -
    -  x.send('url');
    -  assertThrows(function() {
    -    lastMockXmlHttp.complete();
    -  });
    -
    -  // The XHR should have been disposed, even though the listener threw an
    -  // exception.
    -  assertNull(x.xhr_);
    -}
    -
    -function testDisposeInternalDoesNotAbortXhrRequestObjectWhenActiveIsFalse() {
    -  MockXmlHttp.syncSend = false;
    -
    -  var xmlHttp = goog.net.XmlHttp;
    -  var abortCalled = false;
    -  var x = new goog.net.XhrIo;
    -
    -  goog.net.XmlHttp.prototype.abort = function() { abortCalled = true; };
    -
    -  goog.events.listen(x, goog.net.EventType.COMPLETE, function(e) {
    -    this.active_ = false;
    -    this.dispose();
    -  }, false, x);
    -
    -  x.send('url');
    -  lastMockXmlHttp.complete();
    -
    -  goog.net.XmlHttp = xmlHttp;
    -  assertFalse(abortCalled);
    -}
    -
    -function testCallingAbortFromWithinAbortCallbackDoesntLoop() {
    -  var x = new goog.net.XhrIo;
    -  goog.events.listen(x, goog.net.EventType.ABORT, function(e) {
    -    x.abort(); // Shouldn't get a stack overflow
    -  });
    -  x.send('url');
    -  x.abort();
    -}
    -
    -function testPostSetsContentTypeHeader() {
    -  var x = new goog.net.XhrIo;
    -
    -  x.send('url', 'POST', 'content');
    -  var headers = lastMockXmlHttp.headers;
    -  assertEquals(1, goog.object.getCount(headers));
    -  assertEquals(
    -      headers[goog.net.XhrIo.CONTENT_TYPE_HEADER],
    -      goog.net.XhrIo.FORM_CONTENT_TYPE);
    -}
    -
    -function testNonPostSetsContentTypeHeader() {
    -  var x = new goog.net.XhrIo;
    -
    -  x.send('url', 'PUT', 'content');
    -  headers = lastMockXmlHttp.headers;
    -  assertEquals(1, goog.object.getCount(headers));
    -  assertEquals(
    -      headers[goog.net.XhrIo.CONTENT_TYPE_HEADER],
    -      goog.net.XhrIo.FORM_CONTENT_TYPE);
    -}
    -
    -function testContentTypeIsTreatedCaseInsensitively() {
    -  var x = new goog.net.XhrIo;
    -
    -  x.send('url', 'POST', 'content', {'content-type': 'testing'});
    -
    -  assertObjectEquals(
    -      'Headers should not be modified since they already contain a ' +
    -      'content type definition',
    -      {'content-type': 'testing'},
    -      lastMockXmlHttp.headers);
    -}
    -
    -function testIsContentTypeHeader_() {
    -  assertTrue(goog.net.XhrIo.isContentTypeHeader_('content-type'));
    -  assertTrue(goog.net.XhrIo.isContentTypeHeader_('Content-type'));
    -  assertTrue(goog.net.XhrIo.isContentTypeHeader_('CONTENT-TYPE'));
    -  assertTrue(goog.net.XhrIo.isContentTypeHeader_('Content-Type'));
    -  assertFalse(goog.net.XhrIo.isContentTypeHeader_('Content Type'));
    -}
    -
    -function testPostFormDataDoesNotSetContentTypeHeader() {
    -  function FakeFormData() {}
    -
    -  propertyReplacer.set(goog.global, 'FormData', FakeFormData);
    -
    -  var x = new goog.net.XhrIo;
    -  x.send('url', 'POST', new FakeFormData());
    -  var headers = lastMockXmlHttp.headers;
    -  assertTrue(goog.object.isEmpty(headers));
    -}
    -
    -function testNonPostFormDataDoesNotSetContentTypeHeader() {
    -  function FakeFormData() {}
    -
    -  propertyReplacer.set(goog.global, 'FormData', FakeFormData);
    -
    -  var x = new goog.net.XhrIo;
    -  x.send('url', 'PUT', new FakeFormData());
    -  headers = lastMockXmlHttp.headers;
    -  assertTrue(goog.object.isEmpty(headers));
    -}
    -
    -function testFactoryInjection() {
    -  var xhr = new MockXmlHttp();
    -  var optionsFactoryCalled = 0;
    -  var xhrFactoryCalled = 0;
    -  var wrapperFactory = new goog.net.WrapperXmlHttpFactory(
    -      function() {
    -        xhrFactoryCalled++;
    -        return xhr;
    -      },
    -      function() {
    -        optionsFactoryCalled++;
    -        return {};
    -      });
    -  var xhrIo = new goog.net.XhrIo(wrapperFactory);
    -
    -  xhrIo.send('url');
    -
    -  assertEquals('XHR factory should have been called', 1, xhrFactoryCalled);
    -  assertEquals('Options factory should have been called', 1,
    -      optionsFactoryCalled);
    -}
    -
    -function testGoogTestingNetXhrIoIsInSync() {
    -  var xhrIo = new goog.net.XhrIo();
    -  var testingXhrIo = new goog.testing.net.XhrIo();
    -
    -  var propertyComparator = function(value, key, obj) {
    -    if (goog.string.endsWith(key, '_')) {
    -      // Ignore private properties/methods
    -      return true;
    -    } else if (typeof value == 'function' && typeof this[key] != 'function') {
    -      // Only type check is sufficient for functions
    -      fail('Mismatched property:' + key + ': gooo.net.XhrIo has:<' +
    -          value + '>; while goog.testing.net.XhrIo has:<' + this[key] + '>');
    -      return true;
    -    } else {
    -      // Ignore all other type of properties.
    -      return true;
    -    }
    -  };
    -
    -  goog.object.every(xhrIo, propertyComparator, testingXhrIo);
    -}
    -
    -function testEntryPointRegistry() {
    -  var monitor = new goog.debug.EntryPointMonitor();
    -  var replacement = function() {};
    -  monitor.wrap = goog.testing.recordFunction(
    -      goog.functions.constant(replacement));
    -
    -  goog.debug.entryPointRegistry.monitorAll(monitor);
    -  assertTrue(monitor.wrap.getCallCount() >= 1);
    -  assertEquals(
    -      replacement,
    -      goog.net.XhrIo.prototype.onReadyStateChangeEntryPoint_);
    -}
    -
    -function testSetWithCredentials() {
    -  // Test on XHR objects that don't have the withCredentials property (older
    -  // browsers).
    -  var x = new goog.net.XhrIo;
    -  x.setWithCredentials(true);
    -  x.send('url');
    -  assertFalse(
    -      'withCredentials should not be set on an XHR object if the property ' +
    -      'does not exist.',
    -      goog.object.containsKey(lastMockXmlHttp, 'withCredentials'));
    -
    -  // Test on XHR objects that have the withCredentials property.
    -  MockXmlHttp.prototype.withCredentials = false;
    -  x = new goog.net.XhrIo;
    -  x.setWithCredentials(true);
    -  x.send('url');
    -  assertTrue(
    -      'withCredentials should be set on an XHR object if the property exists',
    -      goog.object.containsKey(lastMockXmlHttp, 'withCredentials'));
    -
    -  assertTrue(
    -      'withCredentials value not set on XHR object',
    -      lastMockXmlHttp.withCredentials);
    -
    -  // Reset the prototype so it does not effect other tests.
    -  delete MockXmlHttp.prototype.withCredentials;
    -}
    -
    -function testGetResponse() {
    -  var x = new goog.net.XhrIo;
    -
    -  // No XHR yet
    -  assertEquals(null, x.getResponse());
    -
    -  // XHR with no .response and no response type, gets text.
    -  x.xhr_ = {};
    -  x.xhr_.responseText = 'text';
    -  assertEquals('text', x.getResponse());
    -
    -  // Response type of text gets text as well.
    -  x.setResponseType(goog.net.XhrIo.ResponseType.TEXT);
    -  x.xhr_.responseText = '';
    -  assertEquals('', x.getResponse());
    -
    -  // Response type of array buffer gets the array buffer.
    -  x.xhr_.mozResponseArrayBuffer = 'ab';
    -  x.setResponseType(goog.net.XhrIo.ResponseType.ARRAY_BUFFER);
    -  assertEquals('ab', x.getResponse());
    -
    -  // With a response field, it is returned no matter what value it has.
    -  x.xhr_.response = undefined;
    -  assertEquals(undefined, x.getResponse());
    -
    -  x.xhr_.response = null;
    -  assertEquals(null, x.getResponse());
    -
    -  x.xhr_.response = '';
    -  assertEquals('', x.getResponse());
    -
    -  x.xhr_.response = 'resp';
    -  assertEquals('resp', x.getResponse());
    -}
    -
    -function testGetResponseHeaders() {
    -  var x = new goog.net.XhrIo();
    -
    -  // No XHR yet
    -  assertEquals(0, goog.object.getCount(x.getResponseHeaders()));
    -
    -  // Simulate an XHR with 2 headers.
    -  var headersRaw = 'test1: foo\r\ntest2: bar';
    -
    -  propertyReplacer.set(x, 'getAllResponseHeaders',
    -                       goog.functions.constant(headersRaw));
    -
    -  var headers = x.getResponseHeaders();
    -  assertEquals(2, goog.object.getCount(headers));
    -  assertEquals('foo', headers['test1']);
    -  assertEquals('bar', headers['test2']);
    -}
    -
    -function testGetResponseHeadersWithColonInValue() {
    -  var x = new goog.net.XhrIo();
    -
    -  // Simulate an XHR with a colon in the http header value.
    -  var headersRaw = 'test1: f:o:o';
    -
    -  propertyReplacer.set(x, 'getAllResponseHeaders',
    -                       goog.functions.constant(headersRaw));
    -
    -  var headers = x.getResponseHeaders();
    -  assertEquals(1, goog.object.getCount(headers));
    -  assertEquals('f:o:o', headers['test1']);
    -}
    -
    -function testGetResponseHeadersMultipleValuesForOneKey() {
    -  var x = new goog.net.XhrIo();
    -
    -  // No XHR yet
    -  assertEquals(0, goog.object.getCount(x.getResponseHeaders()));
    -
    -  // Simulate an XHR with 2 headers.
    -  var headersRaw = 'test1: foo\r\ntest1: bar';
    -
    -  propertyReplacer.set(x, 'getAllResponseHeaders',
    -                       goog.functions.constant(headersRaw));
    -
    -  var headers = x.getResponseHeaders();
    -  assertEquals(1, goog.object.getCount(headers));
    -  assertEquals('foo, bar', headers['test1']);
    -}
    -
    -function testGetResponseHeadersEmptyHeader() {
    -  var x = new goog.net.XhrIo();
    -
    -  // No XHR yet
    -  assertEquals(0, goog.object.getCount(x.getResponseHeaders()));
    -
    -  // Simulate an XHR with 2 headers, the last of which is empty.
    -  var headersRaw = 'test2: bar\r\n';
    -
    -  propertyReplacer.set(x, 'getAllResponseHeaders',
    -                       goog.functions.constant(headersRaw));
    -
    -  var headers = x.getResponseHeaders();
    -  assertEquals(1, goog.object.getCount(headers));
    -  assertEquals('bar', headers['test2']);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xhriopool.js b/src/database/third_party/closure-library/closure/goog/net/xhriopool.js
    deleted file mode 100644
    index ffc61e16c23..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xhriopool.js
    +++ /dev/null
    @@ -1,79 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Creates a pool of XhrIo objects to use. This allows multiple
    - * XhrIo objects to be grouped together and requests will use next available
    - * XhrIo object.
    - *
    - */
    -
    -goog.provide('goog.net.XhrIoPool');
    -
    -goog.require('goog.net.XhrIo');
    -goog.require('goog.structs.PriorityPool');
    -
    -
    -
    -/**
    - * A pool of XhrIo objects.
    - * @param {goog.structs.Map=} opt_headers Map of default headers to add to every
    - *     request.
    - * @param {number=} opt_minCount Minimum number of objects (Default: 1).
    - * @param {number=} opt_maxCount Maximum number of objects (Default: 10).
    - * @constructor
    - * @extends {goog.structs.PriorityPool}
    - */
    -goog.net.XhrIoPool = function(opt_headers, opt_minCount, opt_maxCount) {
    -  goog.structs.PriorityPool.call(this, opt_minCount, opt_maxCount);
    -
    -  /**
    -   * Map of default headers to add to every request.
    -   * @type {goog.structs.Map|undefined}
    -   * @private
    -   */
    -  this.headers_ = opt_headers;
    -};
    -goog.inherits(goog.net.XhrIoPool, goog.structs.PriorityPool);
    -
    -
    -/**
    - * Creates an instance of an XhrIo object to use in the pool.
    - * @return {!goog.net.XhrIo} The created object.
    - * @override
    - */
    -goog.net.XhrIoPool.prototype.createObject = function() {
    -  var xhrIo = new goog.net.XhrIo();
    -  var headers = this.headers_;
    -  if (headers) {
    -    headers.forEach(function(value, key) {
    -      xhrIo.headers.set(key, value);
    -    });
    -  }
    -  return xhrIo;
    -};
    -
    -
    -/**
    - * Determine if an object has become unusable and should not be used.
    - * @param {Object} obj The object to test.
    - * @return {boolean} Whether the object can be reused, which is true if the
    - *     object is not disposed and not active.
    - * @override
    - */
    -goog.net.XhrIoPool.prototype.objectCanBeReused = function(obj) {
    -  // An active XhrIo object should never be used.
    -  var xhr = /** @type {goog.net.XhrIo} */ (obj);
    -  return !xhr.isDisposed() && !xhr.isActive();
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xhrlike.js b/src/database/third_party/closure-library/closure/goog/net/xhrlike.js
    deleted file mode 100644
    index 4cb26f26988..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xhrlike.js
    +++ /dev/null
    @@ -1,124 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.net.XhrLike');
    -
    -
    -
    -/**
    - * Interface for the common parts of XMLHttpRequest.
    - *
    - * Mostly copied from externs/w3c_xml.js.
    - *
    - * @interface
    - * @see http://www.w3.org/TR/XMLHttpRequest/
    - */
    -goog.net.XhrLike = function() {};
    -
    -
    -/**
    - * Typedef that refers to either native or custom-implemented XHR objects.
    - * @typedef {!goog.net.XhrLike|!XMLHttpRequest}
    - */
    -goog.net.XhrLike.OrNative;
    -
    -
    -/**
    - * @type {function()|null|undefined}
    - * @see http://www.w3.org/TR/XMLHttpRequest/#handler-xhr-onreadystatechange
    - */
    -goog.net.XhrLike.prototype.onreadystatechange;
    -
    -
    -/**
    - * @type {string}
    - * @see http://www.w3.org/TR/XMLHttpRequest/#the-responsetext-attribute
    - */
    -goog.net.XhrLike.prototype.responseText;
    -
    -
    -/**
    - * @type {Document}
    - * @see http://www.w3.org/TR/XMLHttpRequest/#the-responsexml-attribute
    - */
    -goog.net.XhrLike.prototype.responseXML;
    -
    -
    -/**
    - * @type {number}
    - * @see http://www.w3.org/TR/XMLHttpRequest/#readystate
    - */
    -goog.net.XhrLike.prototype.readyState;
    -
    -
    -/**
    - * @type {number}
    - * @see http://www.w3.org/TR/XMLHttpRequest/#status
    - */
    -goog.net.XhrLike.prototype.status;
    -
    -
    -/**
    - * @type {string}
    - * @see http://www.w3.org/TR/XMLHttpRequest/#statustext
    - */
    -goog.net.XhrLike.prototype.statusText;
    -
    -
    -/**
    - * @param {string} method
    - * @param {string} url
    - * @param {?boolean=} opt_async
    - * @param {?string=} opt_user
    - * @param {?string=} opt_password
    - * @see http://www.w3.org/TR/XMLHttpRequest/#the-open()-method
    - */
    -goog.net.XhrLike.prototype.open = function(method, url, opt_async, opt_user,
    -    opt_password) {};
    -
    -
    -/**
    - * @param {ArrayBuffer|ArrayBufferView|Blob|Document|FormData|string=} opt_data
    - * @see http://www.w3.org/TR/XMLHttpRequest/#the-send()-method
    - */
    -goog.net.XhrLike.prototype.send = function(opt_data) {};
    -
    -
    -/**
    - * @see http://www.w3.org/TR/XMLHttpRequest/#the-abort()-method
    - */
    -goog.net.XhrLike.prototype.abort = function() {};
    -
    -
    -/**
    - * @param {string} header
    - * @param {string} value
    - * @see http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader()-method
    - */
    -goog.net.XhrLike.prototype.setRequestHeader = function(header, value) {};
    -
    -
    -/**
    - * @param {string} header
    - * @return {string}
    - * @see http://www.w3.org/TR/XMLHttpRequest/#the-getresponseheader()-method
    - */
    -goog.net.XhrLike.prototype.getResponseHeader = function(header) {};
    -
    -
    -/**
    - * @return {string}
    - * @see http://www.w3.org/TR/XMLHttpRequest/#the-getallresponseheaders()-method
    - */
    -goog.net.XhrLike.prototype.getAllResponseHeaders = function() {};
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xhrmanager.js b/src/database/third_party/closure-library/closure/goog/net/xhrmanager.js
    deleted file mode 100644
    index 50f5229efd0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xhrmanager.js
    +++ /dev/null
    @@ -1,772 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Manages a pool of XhrIo's. This handles all the details of
    - * dealing with the XhrPool and provides a simple interface for sending requests
    - * and managing events.
    - *
    - * This class supports queueing & prioritization of requests (XhrIoPool
    - * handles this) and retrying of requests.
    - *
    - * The events fired by the XhrManager are an aggregation of the events of
    - * each of its XhrIo objects (with some filtering, i.e., ERROR only called
    - * when there are no more retries left). For this reason, all send requests have
    - * to have an id, so that the user of this object can know which event is for
    - * which request.
    - *
    - */
    -
    -goog.provide('goog.net.XhrManager');
    -goog.provide('goog.net.XhrManager.Event');
    -goog.provide('goog.net.XhrManager.Request');
    -
    -goog.require('goog.events');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.net.ErrorCode');
    -goog.require('goog.net.EventType');
    -goog.require('goog.net.XhrIo');
    -goog.require('goog.net.XhrIoPool');
    -goog.require('goog.structs.Map');
    -
    -// TODO(user): Add some time in between retries.
    -
    -
    -
    -/**
    - * A manager of an XhrIoPool.
    - * @param {number=} opt_maxRetries Max. number of retries (Default: 1).
    - * @param {goog.structs.Map=} opt_headers Map of default headers to add to every
    - *     request.
    - * @param {number=} opt_minCount Min. number of objects (Default: 1).
    - * @param {number=} opt_maxCount Max. number of objects (Default: 10).
    - * @param {number=} opt_timeoutInterval Timeout (in ms) before aborting an
    - *     attempt (Default: 0ms).
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - */
    -goog.net.XhrManager = function(
    -    opt_maxRetries,
    -    opt_headers,
    -    opt_minCount,
    -    opt_maxCount,
    -    opt_timeoutInterval) {
    -  goog.net.XhrManager.base(this, 'constructor');
    -
    -  /**
    -   * Maximum number of retries for a given request
    -   * @type {number}
    -   * @private
    -   */
    -  this.maxRetries_ = goog.isDef(opt_maxRetries) ? opt_maxRetries : 1;
    -
    -  /**
    -   * Timeout interval for an attempt of a given request.
    -   * @type {number}
    -   * @private
    -   */
    -  this.timeoutInterval_ =
    -      goog.isDef(opt_timeoutInterval) ? Math.max(0, opt_timeoutInterval) : 0;
    -
    -  /**
    -   * The pool of XhrIo's to use.
    -   * @type {goog.net.XhrIoPool}
    -   * @private
    -   */
    -  this.xhrPool_ = new goog.net.XhrIoPool(
    -      opt_headers, opt_minCount, opt_maxCount);
    -
    -  /**
    -   * Map of ID's to requests.
    -   * @type {goog.structs.Map<string, !goog.net.XhrManager.Request>}
    -   * @private
    -   */
    -  this.requests_ = new goog.structs.Map();
    -
    -  /**
    -   * The event handler.
    -   * @type {goog.events.EventHandler<!goog.net.XhrManager>}
    -   * @private
    -   */
    -  this.eventHandler_ = new goog.events.EventHandler(this);
    -};
    -goog.inherits(goog.net.XhrManager, goog.events.EventTarget);
    -
    -
    -/**
    - * Error to throw when a send is attempted with an ID that the manager already
    - * has registered for another request.
    - * @type {string}
    - * @private
    - */
    -goog.net.XhrManager.ERROR_ID_IN_USE_ = '[goog.net.XhrManager] ID in use';
    -
    -
    -/**
    - * The goog.net.EventType's to listen/unlisten for on the XhrIo object.
    - * @type {Array<goog.net.EventType>}
    - * @private
    - */
    -goog.net.XhrManager.XHR_EVENT_TYPES_ = [
    -  goog.net.EventType.READY,
    -  goog.net.EventType.COMPLETE,
    -  goog.net.EventType.SUCCESS,
    -  goog.net.EventType.ERROR,
    -  goog.net.EventType.ABORT,
    -  goog.net.EventType.TIMEOUT];
    -
    -
    -/**
    - * Sets the number of milliseconds after which an incomplete request will be
    - * aborted. Zero means no timeout is set.
    - * @param {number} ms Timeout interval in milliseconds; 0 means none.
    - */
    -goog.net.XhrManager.prototype.setTimeoutInterval = function(ms) {
    -  this.timeoutInterval_ = Math.max(0, ms);
    -};
    -
    -
    -/**
    - * Returns the number of requests either in flight, or waiting to be sent.
    - * The count will include the current request if used within a COMPLETE event
    - * handler or callback.
    - * @return {number} The number of requests in flight or pending send.
    - */
    -goog.net.XhrManager.prototype.getOutstandingCount = function() {
    -  return this.requests_.getCount();
    -};
    -
    -
    -/**
    - * Returns an array of request ids that are either in flight, or waiting to
    - * be sent. The id of the current request will be included if used within a
    - * COMPLETE event handler or callback.
    - * @return {!Array<string>} Request ids in flight or pending send.
    - */
    -goog.net.XhrManager.prototype.getOutstandingRequestIds = function() {
    -  return this.requests_.getKeys();
    -};
    -
    -
    -/**
    - * Registers the given request to be sent. Throws an error if a request
    - * already exists with the given ID.
    - * NOTE: It is not sent immediately. It is queued and will be sent when an
    - * XhrIo object becomes available, taking into account the request's
    - * priority.
    - * @param {string} id The id of the request.
    - * @param {string} url Uri to make the request too.
    - * @param {string=} opt_method Send method, default: GET.
    - * @param {ArrayBuffer|ArrayBufferView|Blob|Document|FormData|string=}
    - *     opt_content Post data.
    - * @param {Object|goog.structs.Map=} opt_headers Map of headers to add to the
    - *     request.
    - * @param {number=} opt_priority The priority of the request. A smaller value
    - *     means a higher priority.
    - * @param {Function=} opt_callback Callback function for when request is
    - *     complete. The only param is the event object from the COMPLETE event.
    - * @param {number=} opt_maxRetries The maximum number of times the request
    - *     should be retried.
    - * @param {goog.net.XhrIo.ResponseType=} opt_responseType The response type of
    - *     this request; defaults to goog.net.XhrIo.ResponseType.DEFAULT.
    - * @return {!goog.net.XhrManager.Request} The queued request object.
    - */
    -goog.net.XhrManager.prototype.send = function(
    -    id,
    -    url,
    -    opt_method,
    -    opt_content,
    -    opt_headers,
    -    opt_priority,
    -    opt_callback,
    -    opt_maxRetries,
    -    opt_responseType) {
    -  var requests = this.requests_;
    -  // Check if there is already a request with the given id.
    -  if (requests.get(id)) {
    -    throw Error(goog.net.XhrManager.ERROR_ID_IN_USE_);
    -  }
    -
    -  // Make the Request object.
    -  var request = new goog.net.XhrManager.Request(
    -      url,
    -      goog.bind(this.handleEvent_, this, id),
    -      opt_method,
    -      opt_content,
    -      opt_headers,
    -      opt_callback,
    -      goog.isDef(opt_maxRetries) ? opt_maxRetries : this.maxRetries_,
    -      opt_responseType);
    -  this.requests_.set(id, request);
    -
    -  // Setup the callback for the pool.
    -  var callback = goog.bind(this.handleAvailableXhr_, this, id);
    -  this.xhrPool_.getObject(callback, opt_priority);
    -
    -  return request;
    -};
    -
    -
    -/**
    - * Aborts the request associated with id.
    - * @param {string} id The id of the request to abort.
    - * @param {boolean=} opt_force If true, remove the id now so it can be reused.
    - *     No events are fired and the callback is not called when forced.
    - */
    -goog.net.XhrManager.prototype.abort = function(id, opt_force) {
    -  var request = this.requests_.get(id);
    -  if (request) {
    -    var xhrIo = request.xhrIo;
    -    request.setAborted(true);
    -    if (opt_force) {
    -      if (xhrIo) {
    -        // We remove listeners to make sure nothing gets called if a new request
    -        // with the same id is made.
    -        this.removeXhrListener_(xhrIo, request.getXhrEventCallback());
    -        goog.events.listenOnce(
    -            xhrIo,
    -            goog.net.EventType.READY,
    -            function() { this.xhrPool_.releaseObject(xhrIo); },
    -            false,
    -            this);
    -      }
    -      this.requests_.remove(id);
    -    }
    -    if (xhrIo) {
    -      xhrIo.abort();
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Handles when an XhrIo object becomes available. Sets up the events, fires
    - * the READY event, and starts the process to send the request.
    - * @param {string} id The id of the request the XhrIo is for.
    - * @param {goog.net.XhrIo} xhrIo The available XhrIo object.
    - * @private
    - */
    -goog.net.XhrManager.prototype.handleAvailableXhr_ = function(id, xhrIo) {
    -  var request = this.requests_.get(id);
    -  // Make sure the request doesn't already have an XhrIo attached. This can
    -  // happen if a forced abort occurs before an XhrIo is available, and a new
    -  // request with the same id is made.
    -  if (request && !request.xhrIo) {
    -    this.addXhrListener_(xhrIo, request.getXhrEventCallback());
    -
    -    // Set properties for the XhrIo.
    -    xhrIo.setTimeoutInterval(this.timeoutInterval_);
    -    xhrIo.setResponseType(request.getResponseType());
    -
    -    // Add a reference to the XhrIo object to the request.
    -    request.xhrIo = xhrIo;
    -
    -    // Notify the listeners.
    -    this.dispatchEvent(new goog.net.XhrManager.Event(
    -        goog.net.EventType.READY, this, id, xhrIo));
    -
    -    // Send the request.
    -    this.retry_(id, xhrIo);
    -
    -    // If the request was aborted before it got an XhrIo object, abort it now.
    -    if (request.getAborted()) {
    -      xhrIo.abort();
    -    }
    -  } else {
    -    // If the request has an XhrIo object already, or no request exists, just
    -    // return the XhrIo back to the pool.
    -    this.xhrPool_.releaseObject(xhrIo);
    -  }
    -};
    -
    -
    -/**
    - * Handles all events fired by the XhrIo object for a given request.
    - * @param {string} id The id of the request.
    - * @param {goog.events.Event} e The event.
    - * @return {Object} The return value from the handler, if any.
    - * @private
    - */
    -goog.net.XhrManager.prototype.handleEvent_ = function(id, e) {
    -  var xhrIo = /** @type {goog.net.XhrIo} */(e.target);
    -  switch (e.type) {
    -    case goog.net.EventType.READY:
    -      this.retry_(id, xhrIo);
    -      break;
    -
    -    case goog.net.EventType.COMPLETE:
    -      return this.handleComplete_(id, xhrIo, e);
    -
    -    case goog.net.EventType.SUCCESS:
    -      this.handleSuccess_(id, xhrIo);
    -      break;
    -
    -    // A timeout is handled like an error.
    -    case goog.net.EventType.TIMEOUT:
    -    case goog.net.EventType.ERROR:
    -      this.handleError_(id, xhrIo);
    -      break;
    -
    -    case goog.net.EventType.ABORT:
    -      this.handleAbort_(id, xhrIo);
    -      break;
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * Attempts to retry the given request. If the request has already attempted
    - * the maximum number of retries, then it removes the request and releases
    - * the XhrIo object back into the pool.
    - * @param {string} id The id of the request.
    - * @param {goog.net.XhrIo} xhrIo The XhrIo object.
    - * @private
    - */
    -goog.net.XhrManager.prototype.retry_ = function(id, xhrIo) {
    -  var request = this.requests_.get(id);
    -
    -  // If the request has not completed and it is below its max. retries.
    -  if (request && !request.getCompleted() && !request.hasReachedMaxRetries()) {
    -    request.increaseAttemptCount();
    -    xhrIo.send(request.getUrl(), request.getMethod(), request.getContent(),
    -        request.getHeaders());
    -  } else {
    -    if (request) {
    -      // Remove the events on the XhrIo objects.
    -      this.removeXhrListener_(xhrIo, request.getXhrEventCallback());
    -
    -      // Remove the request.
    -      this.requests_.remove(id);
    -    }
    -    // Release the XhrIo object back into the pool.
    -    this.xhrPool_.releaseObject(xhrIo);
    -  }
    -};
    -
    -
    -/**
    - * Handles the complete of a request. Dispatches the COMPLETE event and sets the
    - * the request as completed if the request has succeeded, or is done retrying.
    - * @param {string} id The id of the request.
    - * @param {goog.net.XhrIo} xhrIo The XhrIo object.
    - * @param {goog.events.Event} e The original event.
    - * @return {Object} The return value from the callback, if any.
    - * @private
    - */
    -goog.net.XhrManager.prototype.handleComplete_ = function(id, xhrIo, e) {
    -  // Only if the request is done processing should a COMPLETE event be fired.
    -  var request = this.requests_.get(id);
    -  if (xhrIo.getLastErrorCode() == goog.net.ErrorCode.ABORT ||
    -      xhrIo.isSuccess() || request.hasReachedMaxRetries()) {
    -    this.dispatchEvent(new goog.net.XhrManager.Event(
    -        goog.net.EventType.COMPLETE, this, id, xhrIo));
    -
    -    // If the request exists, we mark it as completed and call the callback
    -    if (request) {
    -      request.setCompleted(true);
    -      // Call the complete callback as if it was set as a COMPLETE event on the
    -      // XhrIo directly.
    -      if (request.getCompleteCallback()) {
    -        return request.getCompleteCallback().call(xhrIo, e);
    -      }
    -    }
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * Handles the abort of an underlying XhrIo object.
    - * @param {string} id The id of the request.
    - * @param {goog.net.XhrIo} xhrIo The XhrIo object.
    - * @private
    - */
    -goog.net.XhrManager.prototype.handleAbort_ = function(id, xhrIo) {
    -  // Fire event.
    -  // NOTE: The complete event should always be fired before the abort event, so
    -  // the bulk of the work is done in handleComplete.
    -  this.dispatchEvent(new goog.net.XhrManager.Event(
    -      goog.net.EventType.ABORT, this, id, xhrIo));
    -};
    -
    -
    -/**
    - * Handles the success of a request. Dispatches the SUCCESS event and sets the
    - * the request as completed.
    - * @param {string} id The id of the request.
    - * @param {goog.net.XhrIo} xhrIo The XhrIo object.
    - * @private
    - */
    -goog.net.XhrManager.prototype.handleSuccess_ = function(id, xhrIo) {
    -  // Fire event.
    -  // NOTE: We don't release the XhrIo object from the pool here.
    -  // It is released in the retry method, when we know it is back in the
    -  // ready state.
    -  this.dispatchEvent(new goog.net.XhrManager.Event(
    -      goog.net.EventType.SUCCESS, this, id, xhrIo));
    -};
    -
    -
    -/**
    - * Handles the error of a request. If the request has not reach its maximum
    - * number of retries, then it lets the request retry naturally (will let the
    - * request hit the READY state). Else, it dispatches the ERROR event.
    - * @param {string} id The id of the request.
    - * @param {goog.net.XhrIo} xhrIo The XhrIo object.
    - * @private
    - */
    -goog.net.XhrManager.prototype.handleError_ = function(id, xhrIo) {
    -  var request = this.requests_.get(id);
    -
    -  // If the maximum number of retries has been reached.
    -  if (request.hasReachedMaxRetries()) {
    -    // Fire event.
    -    // NOTE: We don't release the XhrIo object from the pool here.
    -    // It is released in the retry method, when we know it is back in the
    -    // ready state.
    -    this.dispatchEvent(new goog.net.XhrManager.Event(
    -        goog.net.EventType.ERROR, this, id, xhrIo));
    -  }
    -};
    -
    -
    -/**
    - * Remove listeners for XHR events on an XhrIo object.
    - * @param {goog.net.XhrIo} xhrIo The object to stop listenening to events on.
    - * @param {Function} func The callback to remove from event handling.
    - * @param {string|Array<string>=} opt_types Event types to remove listeners
    - *     for. Defaults to XHR_EVENT_TYPES_.
    - * @private
    - */
    -goog.net.XhrManager.prototype.removeXhrListener_ = function(xhrIo,
    -                                                            func,
    -                                                            opt_types) {
    -  var types = opt_types || goog.net.XhrManager.XHR_EVENT_TYPES_;
    -  this.eventHandler_.unlisten(xhrIo, types, func);
    -};
    -
    -
    -/**
    - * Adds a listener for XHR events on an XhrIo object.
    - * @param {goog.net.XhrIo} xhrIo The object listen to events on.
    - * @param {Function} func The callback when the event occurs.
    - * @param {string|Array<string>=} opt_types Event types to attach listeners to.
    - *     Defaults to XHR_EVENT_TYPES_.
    - * @private
    - */
    -goog.net.XhrManager.prototype.addXhrListener_ = function(xhrIo,
    -                                                         func,
    -                                                         opt_types) {
    -  var types = opt_types || goog.net.XhrManager.XHR_EVENT_TYPES_;
    -  this.eventHandler_.listen(xhrIo, types, func);
    -};
    -
    -
    -/** @override */
    -goog.net.XhrManager.prototype.disposeInternal = function() {
    -  goog.net.XhrManager.superClass_.disposeInternal.call(this);
    -
    -  this.xhrPool_.dispose();
    -  this.xhrPool_ = null;
    -
    -  this.eventHandler_.dispose();
    -  this.eventHandler_ = null;
    -
    -  this.requests_.clear();
    -  this.requests_ = null;
    -};
    -
    -
    -
    -/**
    - * An event dispatched by XhrManager.
    - *
    - * @param {goog.net.EventType} type Event Type.
    - * @param {goog.net.XhrManager} target Reference to the object that is the
    - *     target of this event.
    - * @param {string} id The id of the request this event is for.
    - * @param {goog.net.XhrIo} xhrIo The XhrIo object of the request.
    - * @constructor
    - * @extends {goog.events.Event}
    - * @final
    - */
    -goog.net.XhrManager.Event = function(type, target, id, xhrIo) {
    -  goog.events.Event.call(this, type, target);
    -
    -  /**
    -   * The id of the request this event is for.
    -   * @type {string}
    -   */
    -  this.id = id;
    -
    -  /**
    -   * The XhrIo object of the request.
    -   * @type {goog.net.XhrIo}
    -   */
    -  this.xhrIo = xhrIo;
    -};
    -goog.inherits(goog.net.XhrManager.Event, goog.events.Event);
    -
    -
    -
    -/**
    - * An encapsulation of everything needed to make a Xhr request.
    - * NOTE: This is used internal to the XhrManager.
    - *
    - * @param {string} url Uri to make the request too.
    - * @param {Function} xhrEventCallback Callback attached to the events of the
    - *     XhrIo object of the request.
    - * @param {string=} opt_method Send method, default: GET.
    - * @param {ArrayBuffer|ArrayBufferView|Blob|Document|FormData|string=}
    - *     opt_content Post data.
    - * @param {Object|goog.structs.Map=} opt_headers Map of headers to add to the
    - *     request.
    - * @param {Function=} opt_callback Callback function for when request is
    - *     complete. NOTE: Only 1 callback supported across all events.
    - * @param {number=} opt_maxRetries The maximum number of times the request
    - *     should be retried (Default: 1).
    - * @param {goog.net.XhrIo.ResponseType=} opt_responseType The response type of
    - *     this request; defaults to goog.net.XhrIo.ResponseType.DEFAULT.
    - *
    - * @constructor
    - * @final
    - */
    -goog.net.XhrManager.Request = function(url, xhrEventCallback, opt_method,
    -    opt_content, opt_headers, opt_callback, opt_maxRetries, opt_responseType) {
    -  /**
    -   * Uri to make the request too.
    -   * @type {string}
    -   * @private
    -   */
    -  this.url_ = url;
    -
    -  /**
    -   * Send method.
    -   * @type {string}
    -   * @private
    -   */
    -  this.method_ = opt_method || 'GET';
    -
    -  /**
    -   * Post data.
    -   * @type {ArrayBuffer|ArrayBufferView|Blob|Document|FormData|string|undefined}
    -   * @private
    -   */
    -  this.content_ = opt_content;
    -
    -  /**
    -   *  Map of headers
    -   * @type {Object|goog.structs.Map|null}
    -   * @private
    -   */
    -  this.headers_ = opt_headers || null;
    -
    -  /**
    -   * The maximum number of times the request should be retried.
    -   * @type {number}
    -   * @private
    -   */
    -  this.maxRetries_ = goog.isDef(opt_maxRetries) ? opt_maxRetries : 1;
    -
    -  /**
    -   * The number of attempts  so far.
    -   * @type {number}
    -   * @private
    -   */
    -  this.attemptCount_ = 0;
    -
    -  /**
    -   * Whether the request has been completed.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.completed_ = false;
    -
    -  /**
    -   * Whether the request has been aborted.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.aborted_ = false;
    -
    -  /**
    -   * Callback attached to the events of the XhrIo object.
    -   * @type {Function}
    -   * @private
    -   */
    -  this.xhrEventCallback_ = xhrEventCallback;
    -
    -  /**
    -   * Callback function called when request is complete.
    -   * @type {Function|undefined}
    -   * @private
    -   */
    -  this.completeCallback_ = opt_callback;
    -
    -  /**
    -   * A response type to set on this.xhrIo when it's populated.
    -   * @type {!goog.net.XhrIo.ResponseType}
    -   * @private
    -   */
    -  this.responseType_ = opt_responseType || goog.net.XhrIo.ResponseType.DEFAULT;
    -
    -  /**
    -   * The XhrIo instance handling this request. Set in handleAvailableXhr.
    -   * @type {goog.net.XhrIo}
    -   */
    -  this.xhrIo = null;
    -
    -};
    -
    -
    -/**
    - * Gets the uri.
    - * @return {string} The uri to make the request to.
    - */
    -goog.net.XhrManager.Request.prototype.getUrl = function() {
    -  return this.url_;
    -};
    -
    -
    -/**
    - * Gets the send method.
    - * @return {string} The send method.
    - */
    -goog.net.XhrManager.Request.prototype.getMethod = function() {
    -  return this.method_;
    -};
    -
    -
    -/**
    - * Gets the post data.
    - * @return {ArrayBuffer|ArrayBufferView|Blob|Document|FormData|string|undefined}
    - *     The post data.
    - */
    -goog.net.XhrManager.Request.prototype.getContent = function() {
    -  return this.content_;
    -};
    -
    -
    -/**
    - * Gets the map of headers.
    - * @return {Object|goog.structs.Map} The map of headers.
    - */
    -goog.net.XhrManager.Request.prototype.getHeaders = function() {
    -  return this.headers_;
    -};
    -
    -
    -/**
    - * Gets the maximum number of times the request should be retried.
    - * @return {number} The maximum number of times the request should be retried.
    - */
    -goog.net.XhrManager.Request.prototype.getMaxRetries = function() {
    -  return this.maxRetries_;
    -};
    -
    -
    -/**
    - * Gets the number of attempts so far.
    - * @return {number} The number of attempts so far.
    - */
    -goog.net.XhrManager.Request.prototype.getAttemptCount = function() {
    -  return this.attemptCount_;
    -};
    -
    -
    -/**
    - * Increases the number of attempts so far.
    - */
    -goog.net.XhrManager.Request.prototype.increaseAttemptCount = function() {
    -  this.attemptCount_++;
    -};
    -
    -
    -/**
    - * Returns whether the request has reached the maximum number of retries.
    - * @return {boolean} Whether the request has reached the maximum number of
    - *     retries.
    - */
    -goog.net.XhrManager.Request.prototype.hasReachedMaxRetries = function() {
    -  return this.attemptCount_ > this.maxRetries_;
    -};
    -
    -
    -/**
    - * Sets the completed status.
    - * @param {boolean} complete The completed status.
    - */
    -goog.net.XhrManager.Request.prototype.setCompleted = function(complete) {
    -  this.completed_ = complete;
    -};
    -
    -
    -/**
    - * Gets the completed status.
    - * @return {boolean} The completed status.
    - */
    -goog.net.XhrManager.Request.prototype.getCompleted = function() {
    -  return this.completed_;
    -};
    -
    -
    -/**
    - * Sets the aborted status.
    - * @param {boolean} aborted True if the request was aborted, otherwise False.
    - */
    -goog.net.XhrManager.Request.prototype.setAborted = function(aborted) {
    -  this.aborted_ = aborted;
    -};
    -
    -
    -/**
    - * Gets the aborted status.
    - * @return {boolean} True if request was aborted, otherwise False.
    - */
    -goog.net.XhrManager.Request.prototype.getAborted = function() {
    -  return this.aborted_;
    -};
    -
    -
    -/**
    - * Gets the callback attached to the events of the XhrIo object.
    - * @return {Function} The callback attached to the events of the
    - *     XhrIo object.
    - */
    -goog.net.XhrManager.Request.prototype.getXhrEventCallback = function() {
    -  return this.xhrEventCallback_;
    -};
    -
    -
    -/**
    - * Gets the callback for when the request is complete.
    - * @return {Function|undefined} The callback for when the request is complete.
    - */
    -goog.net.XhrManager.Request.prototype.getCompleteCallback = function() {
    -  return this.completeCallback_;
    -};
    -
    -
    -/**
    - * Gets the response type that will be set on this request's XhrIo when it's
    - * available.
    - * @return {!goog.net.XhrIo.ResponseType} The response type to be set
    - *     when an XhrIo becomes available to this request.
    - */
    -goog.net.XhrManager.Request.prototype.getResponseType = function() {
    -  return this.responseType_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xhrmanager_test.html b/src/database/third_party/closure-library/closure/goog/net/xhrmanager_test.html
    deleted file mode 100644
    index fed27129fb2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xhrmanager_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.net.XhrManager
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.net.XhrManagerTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xhrmanager_test.js b/src/database/third_party/closure-library/closure/goog/net/xhrmanager_test.js
    deleted file mode 100644
    index 1c85541c312..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xhrmanager_test.js
    +++ /dev/null
    @@ -1,120 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.net.XhrManagerTest');
    -goog.setTestOnly('goog.net.XhrManagerTest');
    -
    -goog.require('goog.events');
    -goog.require('goog.net.EventType');
    -goog.require('goog.net.XhrIo');
    -goog.require('goog.net.XhrManager');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.net.XhrIoPool');
    -goog.require('goog.testing.recordFunction');
    -
    -
    -/** @type {goog.net.XhrManager} */
    -var xhrManager;
    -
    -
    -/** @type {goog.testing.net.XhrIo} */
    -var xhrIo;
    -
    -
    -function setUp() {
    -  xhrManager = new goog.net.XhrManager();
    -  xhrManager.xhrPool_ = new goog.testing.net.XhrIoPool();
    -  xhrIo = xhrManager.xhrPool_.getXhr();
    -}
    -
    -
    -function tearDown() {
    -  goog.dispose(xhrManager);
    -}
    -
    -
    -function testGetOutstandingRequestIds() {
    -  assertArrayEquals(
    -      'No outstanding requests', [], xhrManager.getOutstandingRequestIds());
    -
    -  xhrManager.send('test1', '/test1');
    -  assertArrayEquals(
    -      'Single outstanding request', ['test1'],
    -      xhrManager.getOutstandingRequestIds());
    -
    -  xhrManager.send('test2', '/test2');
    -  assertArrayEquals(
    -      'Two outstanding requests', ['test1', 'test2'],
    -      xhrManager.getOutstandingRequestIds());
    -
    -  xhrIo.simulateResponse(200, 'data');
    -  assertArrayEquals(
    -      'Single outstanding request', ['test2'],
    -      xhrManager.getOutstandingRequestIds());
    -
    -  xhrIo.simulateResponse(200, 'data');
    -  assertArrayEquals(
    -      'No outstanding requests', [], xhrManager.getOutstandingRequestIds());
    -}
    -
    -
    -function testForceAbortQueuedRequest() {
    -  xhrManager.send('test', '/test');
    -  xhrManager.send('queued', '/queued');
    -
    -  assertNotThrows(
    -      'Forced abort of queued request should not throw an error',
    -      goog.bind(xhrManager.abort, xhrManager, 'queued', true));
    -
    -  assertNotThrows(
    -      'Forced abort of normal request should not throw an error',
    -      goog.bind(xhrManager.abort, xhrManager, 'test', true));
    -}
    -
    -
    -function testDefaultResponseType() {
    -  var callback = goog.testing.recordFunction(function(e) {
    -    assertEquals('test1', e.id);
    -    assertEquals(
    -        goog.net.XhrIo.ResponseType.DEFAULT, e.xhrIo.getResponseType());
    -    eventCalled = true;
    -  });
    -  goog.events.listenOnce(xhrManager, goog.net.EventType.READY, callback);
    -  xhrManager.send('test1', '/test2');
    -  assertEquals(1, callback.getCallCount());
    -
    -  xhrIo.simulateResponse(200, 'data');  // Do this to make tearDown() happy.
    -}
    -
    -
    -function testNonDefaultResponseType() {
    -  var callback = goog.testing.recordFunction(function(e) {
    -    assertEquals('test2', e.id);
    -    assertEquals(
    -        goog.net.XhrIo.ResponseType.ARRAY_BUFFER, e.xhrIo.getResponseType());
    -    eventCalled = true;
    -  });
    -  goog.events.listenOnce(xhrManager, goog.net.EventType.READY, callback);
    -  xhrManager.send('test2', '/test2',
    -      undefined /* opt_method */,
    -      undefined /* opt_content */,
    -      undefined /* opt_headers */,
    -      undefined /* opt_priority */,
    -      undefined /* opt_callback */,
    -      undefined /* opt_maxRetries */,
    -      goog.net.XhrIo.ResponseType.ARRAY_BUFFER);
    -  assertEquals(1, callback.getCallCount());
    -
    -  xhrIo.simulateResponse(200, 'data');  // Do this to make tearDown() happy.
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xmlhttp.js b/src/database/third_party/closure-library/closure/goog/net/xmlhttp.js
    deleted file mode 100644
    index 8d59f00ee2a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xmlhttp.js
    +++ /dev/null
    @@ -1,246 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Low level handling of XMLHttpRequest.
    - * @author arv@google.com (Erik Arvidsson)
    - * @author dbk@google.com (David Barrett-Kahn)
    - */
    -
    -goog.provide('goog.net.DefaultXmlHttpFactory');
    -goog.provide('goog.net.XmlHttp');
    -goog.provide('goog.net.XmlHttp.OptionType');
    -goog.provide('goog.net.XmlHttp.ReadyState');
    -goog.provide('goog.net.XmlHttpDefines');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.net.WrapperXmlHttpFactory');
    -goog.require('goog.net.XmlHttpFactory');
    -
    -
    -/**
    - * Static class for creating XMLHttpRequest objects.
    - * @return {!goog.net.XhrLike.OrNative} A new XMLHttpRequest object.
    - */
    -goog.net.XmlHttp = function() {
    -  return goog.net.XmlHttp.factory_.createInstance();
    -};
    -
    -
    -/**
    - * @define {boolean} Whether to assume XMLHttpRequest exists. Setting this to
    - *     true bypasses the ActiveX probing code.
    - * NOTE(ruilopes): Due to the way JSCompiler works, this define *will not* strip
    - * out the ActiveX probing code from binaries.  To achieve this, use
    - * {@code goog.net.XmlHttpDefines.ASSUME_NATIVE_XHR} instead.
    - * TODO(ruilopes): Collapse both defines.
    - */
    -goog.define('goog.net.XmlHttp.ASSUME_NATIVE_XHR', false);
    -
    -
    -/** @const */
    -goog.net.XmlHttpDefines = {};
    -
    -
    -/**
    - * @define {boolean} Whether to assume XMLHttpRequest exists. Setting this to
    - *     true eliminates the ActiveX probing code.
    - */
    -goog.define('goog.net.XmlHttpDefines.ASSUME_NATIVE_XHR', false);
    -
    -
    -/**
    - * Gets the options to use with the XMLHttpRequest objects obtained using
    - * the static methods.
    - * @return {Object} The options.
    - */
    -goog.net.XmlHttp.getOptions = function() {
    -  return goog.net.XmlHttp.factory_.getOptions();
    -};
    -
    -
    -/**
    - * Type of options that an XmlHttp object can have.
    - * @enum {number}
    - */
    -goog.net.XmlHttp.OptionType = {
    -  /**
    -   * Whether a goog.nullFunction should be used to clear the onreadystatechange
    -   * handler instead of null.
    -   */
    -  USE_NULL_FUNCTION: 0,
    -
    -  /**
    -   * NOTE(user): In IE if send() errors on a *local* request the readystate
    -   * is still changed to COMPLETE.  We need to ignore it and allow the
    -   * try/catch around send() to pick up the error.
    -   */
    -  LOCAL_REQUEST_ERROR: 1
    -};
    -
    -
    -/**
    - * Status constants for XMLHTTP, matches:
    - * http://msdn.microsoft.com/library/default.asp?url=/library/
    - *   en-us/xmlsdk/html/0e6a34e4-f90c-489d-acff-cb44242fafc6.asp
    - * @enum {number}
    - */
    -goog.net.XmlHttp.ReadyState = {
    -  /**
    -   * Constant for when xmlhttprequest.readyState is uninitialized
    -   */
    -  UNINITIALIZED: 0,
    -
    -  /**
    -   * Constant for when xmlhttprequest.readyState is loading.
    -   */
    -  LOADING: 1,
    -
    -  /**
    -   * Constant for when xmlhttprequest.readyState is loaded.
    -   */
    -  LOADED: 2,
    -
    -  /**
    -   * Constant for when xmlhttprequest.readyState is in an interactive state.
    -   */
    -  INTERACTIVE: 3,
    -
    -  /**
    -   * Constant for when xmlhttprequest.readyState is completed
    -   */
    -  COMPLETE: 4
    -};
    -
    -
    -/**
    - * The global factory instance for creating XMLHttpRequest objects.
    - * @type {goog.net.XmlHttpFactory}
    - * @private
    - */
    -goog.net.XmlHttp.factory_;
    -
    -
    -/**
    - * Sets the factories for creating XMLHttpRequest objects and their options.
    - * @param {Function} factory The factory for XMLHttpRequest objects.
    - * @param {Function} optionsFactory The factory for options.
    - * @deprecated Use setGlobalFactory instead.
    - */
    -goog.net.XmlHttp.setFactory = function(factory, optionsFactory) {
    -  goog.net.XmlHttp.setGlobalFactory(new goog.net.WrapperXmlHttpFactory(
    -      goog.asserts.assert(factory),
    -      goog.asserts.assert(optionsFactory)));
    -};
    -
    -
    -/**
    - * Sets the global factory object.
    - * @param {!goog.net.XmlHttpFactory} factory New global factory object.
    - */
    -goog.net.XmlHttp.setGlobalFactory = function(factory) {
    -  goog.net.XmlHttp.factory_ = factory;
    -};
    -
    -
    -
    -/**
    - * Default factory to use when creating xhr objects.  You probably shouldn't be
    - * instantiating this directly, but rather using it via goog.net.XmlHttp.
    - * @extends {goog.net.XmlHttpFactory}
    - * @constructor
    - */
    -goog.net.DefaultXmlHttpFactory = function() {
    -  goog.net.XmlHttpFactory.call(this);
    -};
    -goog.inherits(goog.net.DefaultXmlHttpFactory, goog.net.XmlHttpFactory);
    -
    -
    -/** @override */
    -goog.net.DefaultXmlHttpFactory.prototype.createInstance = function() {
    -  var progId = this.getProgId_();
    -  if (progId) {
    -    return new ActiveXObject(progId);
    -  } else {
    -    return new XMLHttpRequest();
    -  }
    -};
    -
    -
    -/** @override */
    -goog.net.DefaultXmlHttpFactory.prototype.internalGetOptions = function() {
    -  var progId = this.getProgId_();
    -  var options = {};
    -  if (progId) {
    -    options[goog.net.XmlHttp.OptionType.USE_NULL_FUNCTION] = true;
    -    options[goog.net.XmlHttp.OptionType.LOCAL_REQUEST_ERROR] = true;
    -  }
    -  return options;
    -};
    -
    -
    -/**
    - * The ActiveX PROG ID string to use to create xhr's in IE. Lazily initialized.
    - * @type {string|undefined}
    - * @private
    - */
    -goog.net.DefaultXmlHttpFactory.prototype.ieProgId_;
    -
    -
    -/**
    - * Initialize the private state used by other functions.
    - * @return {string} The ActiveX PROG ID string to use to create xhr's in IE.
    - * @private
    - */
    -goog.net.DefaultXmlHttpFactory.prototype.getProgId_ = function() {
    -  if (goog.net.XmlHttp.ASSUME_NATIVE_XHR ||
    -      goog.net.XmlHttpDefines.ASSUME_NATIVE_XHR) {
    -    return '';
    -  }
    -
    -  // The following blog post describes what PROG IDs to use to create the
    -  // XMLHTTP object in Internet Explorer:
    -  // http://blogs.msdn.com/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx
    -  // However we do not (yet) fully trust that this will be OK for old versions
    -  // of IE on Win9x so we therefore keep the last 2.
    -  if (!this.ieProgId_ && typeof XMLHttpRequest == 'undefined' &&
    -      typeof ActiveXObject != 'undefined') {
    -    // Candidate Active X types.
    -    var ACTIVE_X_IDENTS = ['MSXML2.XMLHTTP.6.0', 'MSXML2.XMLHTTP.3.0',
    -                           'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP'];
    -    for (var i = 0; i < ACTIVE_X_IDENTS.length; i++) {
    -      var candidate = ACTIVE_X_IDENTS[i];
    -      /** @preserveTry */
    -      try {
    -        new ActiveXObject(candidate);
    -        // NOTE(user): cannot assign progid and return candidate in one line
    -        // because JSCompiler complaings: BUG 658126
    -        this.ieProgId_ = candidate;
    -        return candidate;
    -      } catch (e) {
    -        // do nothing; try next choice
    -      }
    -    }
    -
    -    // couldn't find any matches
    -    throw Error('Could not create ActiveXObject. ActiveX might be disabled,' +
    -                ' or MSXML might not be installed');
    -  }
    -
    -  return /** @type {string} */ (this.ieProgId_);
    -};
    -
    -
    -//Set the global factory to an instance of the default factory.
    -goog.net.XmlHttp.setGlobalFactory(new goog.net.DefaultXmlHttpFactory());
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xmlhttpfactory.js b/src/database/third_party/closure-library/closure/goog/net/xmlhttpfactory.js
    deleted file mode 100644
    index 8187edb4718..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xmlhttpfactory.js
    +++ /dev/null
    @@ -1,67 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Interface for a factory for creating XMLHttpRequest objects
    - * and metadata about them.
    - * @author dbk@google.com (David Barrett-Kahn)
    - */
    -
    -goog.provide('goog.net.XmlHttpFactory');
    -
    -/** @suppress {extraRequire} Typedef. */
    -goog.require('goog.net.XhrLike');
    -
    -
    -
    -/**
    - * Abstract base class for an XmlHttpRequest factory.
    - * @constructor
    - */
    -goog.net.XmlHttpFactory = function() {
    -};
    -
    -
    -/**
    - * Cache of options - we only actually call internalGetOptions once.
    - * @type {Object}
    - * @private
    - */
    -goog.net.XmlHttpFactory.prototype.cachedOptions_ = null;
    -
    -
    -/**
    - * @return {!goog.net.XhrLike.OrNative} A new XhrLike instance.
    - */
    -goog.net.XmlHttpFactory.prototype.createInstance = goog.abstractMethod;
    -
    -
    -/**
    - * @return {Object} Options describing how xhr objects obtained from this
    - *     factory should be used.
    - */
    -goog.net.XmlHttpFactory.prototype.getOptions = function() {
    -  return this.cachedOptions_ ||
    -      (this.cachedOptions_ = this.internalGetOptions());
    -};
    -
    -
    -/**
    - * Override this method in subclasses to preserve the caching offered by
    - * getOptions().
    - * @return {Object} Options describing how xhr objects obtained from this
    - *     factory should be used.
    - * @protected
    - */
    -goog.net.XmlHttpFactory.prototype.internalGetOptions = goog.abstractMethod;
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xpc/crosspagechannel.js b/src/database/third_party/closure-library/closure/goog/net/xpc/crosspagechannel.js
    deleted file mode 100644
    index 35a9e86fd5a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xpc/crosspagechannel.js
    +++ /dev/null
    @@ -1,854 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides the class CrossPageChannel, the main class in
    - * goog.net.xpc.
    - *
    - * @see ../../demos/xpc/index.html
    - */
    -
    -goog.provide('goog.net.xpc.CrossPageChannel');
    -
    -goog.require('goog.Uri');
    -goog.require('goog.async.Deferred');
    -goog.require('goog.async.Delay');
    -goog.require('goog.dispose');
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventType');
    -goog.require('goog.json');
    -goog.require('goog.log');
    -goog.require('goog.messaging.AbstractChannel');
    -goog.require('goog.net.xpc');
    -goog.require('goog.net.xpc.CfgFields');
    -goog.require('goog.net.xpc.ChannelStates');
    -goog.require('goog.net.xpc.CrossPageChannelRole');
    -goog.require('goog.net.xpc.DirectTransport');
    -goog.require('goog.net.xpc.FrameElementMethodTransport');
    -goog.require('goog.net.xpc.IframePollingTransport');
    -goog.require('goog.net.xpc.IframeRelayTransport');
    -goog.require('goog.net.xpc.NativeMessagingTransport');
    -goog.require('goog.net.xpc.NixTransport');
    -goog.require('goog.net.xpc.TransportTypes');
    -goog.require('goog.net.xpc.UriCfgFields');
    -goog.require('goog.string');
    -goog.require('goog.uri.utils');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * A communication channel between two documents from different domains.
    - * Provides asynchronous messaging.
    - *
    - * @param {Object} cfg Channel configuration object.
    - * @param {goog.dom.DomHelper=} opt_domHelper The optional dom helper to
    - *     use for looking up elements in the dom.
    - * @constructor
    - * @extends {goog.messaging.AbstractChannel}
    - */
    -goog.net.xpc.CrossPageChannel = function(cfg, opt_domHelper) {
    -  goog.net.xpc.CrossPageChannel.base(this, 'constructor');
    -
    -  for (var i = 0, uriField; uriField = goog.net.xpc.UriCfgFields[i]; i++) {
    -    if (uriField in cfg && !/^https?:\/\//.test(cfg[uriField])) {
    -      throw Error('URI ' + cfg[uriField] + ' is invalid for field ' + uriField);
    -    }
    -  }
    -
    -  /**
    -   * The configuration for this channel.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.cfg_ = cfg;
    -
    -  /**
    -   * The name of the channel. Please use
    -   * <code>updateChannelNameAndCatalog</code> to change this from the transports
    -   * vs changing the property directly.
    -   * @type {string}
    -   */
    -  this.name = this.cfg_[goog.net.xpc.CfgFields.CHANNEL_NAME] ||
    -      goog.net.xpc.getRandomString(10);
    -
    -  /**
    -   * The dom helper to use for accessing the dom.
    -   * @type {goog.dom.DomHelper}
    -   * @private
    -   */
    -  this.domHelper_ = opt_domHelper || goog.dom.getDomHelper();
    -
    -  /**
    -   * Collects deferred function calls which will be made once the connection
    -   * has been fully set up.
    -   * @type {!Array<function()>}
    -   * @private
    -   */
    -  this.deferredDeliveries_ = [];
    -
    -  /**
    -   * An event handler used to listen for load events on peer iframes.
    -   * @type {!goog.events.EventHandler<!goog.net.xpc.CrossPageChannel>}
    -   * @private
    -   */
    -  this.peerLoadHandler_ = new goog.events.EventHandler(this);
    -
    -  // If LOCAL_POLL_URI or PEER_POLL_URI is not available, try using
    -  // robots.txt from that host.
    -  cfg[goog.net.xpc.CfgFields.LOCAL_POLL_URI] =
    -      cfg[goog.net.xpc.CfgFields.LOCAL_POLL_URI] ||
    -      goog.uri.utils.getHost(this.domHelper_.getWindow().location.href) +
    -          '/robots.txt';
    -  // PEER_URI is sometimes undefined in tests.
    -  cfg[goog.net.xpc.CfgFields.PEER_POLL_URI] =
    -      cfg[goog.net.xpc.CfgFields.PEER_POLL_URI] ||
    -      goog.uri.utils.getHost(cfg[goog.net.xpc.CfgFields.PEER_URI] || '') +
    -          '/robots.txt';
    -
    -  goog.net.xpc.channels[this.name] = this;
    -
    -  if (!goog.events.getListener(window, goog.events.EventType.UNLOAD,
    -      goog.net.xpc.CrossPageChannel.disposeAll_)) {
    -    // Set listener to dispose all registered channels on page unload.
    -    goog.events.listenOnce(window, goog.events.EventType.UNLOAD,
    -        goog.net.xpc.CrossPageChannel.disposeAll_);
    -  }
    -
    -  goog.log.info(goog.net.xpc.logger, 'CrossPageChannel created: ' + this.name);
    -};
    -goog.inherits(goog.net.xpc.CrossPageChannel, goog.messaging.AbstractChannel);
    -
    -
    -/**
    - * Regexp for escaping service names.
    - * @type {RegExp}
    - * @private
    - */
    -goog.net.xpc.CrossPageChannel.TRANSPORT_SERVICE_ESCAPE_RE_ =
    -    new RegExp('^%*' + goog.net.xpc.TRANSPORT_SERVICE_ + '$');
    -
    -
    -/**
    - * Regexp for unescaping service names.
    - * @type {RegExp}
    - * @private
    - */
    -goog.net.xpc.CrossPageChannel.TRANSPORT_SERVICE_UNESCAPE_RE_ =
    -    new RegExp('^%+' + goog.net.xpc.TRANSPORT_SERVICE_ + '$');
    -
    -
    -/**
    - * A delay between the transport reporting as connected and the calling of the
    - * connection callback.  Sometimes used to paper over timing vulnerabilities.
    - * @type {goog.async.Delay}
    - * @private
    - */
    -goog.net.xpc.CrossPageChannel.prototype.connectionDelay_ = null;
    -
    -
    -/**
    - * A deferred which is set to non-null while a peer iframe is being created
    - * but has not yet thrown its load event, and which fires when that load event
    - * arrives.
    - * @type {goog.async.Deferred}
    - * @private
    - */
    -goog.net.xpc.CrossPageChannel.prototype.peerWindowDeferred_ = null;
    -
    -
    -/**
    - * The transport.
    - * @type {goog.net.xpc.Transport?}
    - * @private
    - */
    -goog.net.xpc.CrossPageChannel.prototype.transport_ = null;
    -
    -
    -/**
    - * The channel state.
    - * @type {number}
    - * @private
    - */
    -goog.net.xpc.CrossPageChannel.prototype.state_ =
    -    goog.net.xpc.ChannelStates.NOT_CONNECTED;
    -
    -
    -/**
    - * @override
    - * @return {boolean} Whether the channel is connected.
    - */
    -goog.net.xpc.CrossPageChannel.prototype.isConnected = function() {
    -  return this.state_ == goog.net.xpc.ChannelStates.CONNECTED;
    -};
    -
    -
    -/**
    - * Reference to the window-object of the peer page.
    - * @type {Object}
    - * @private
    - */
    -goog.net.xpc.CrossPageChannel.prototype.peerWindowObject_ = null;
    -
    -
    -/**
    - * Reference to the iframe-element.
    - * @type {Object}
    - * @private
    - */
    -goog.net.xpc.CrossPageChannel.prototype.iframeElement_ = null;
    -
    -
    -/**
    - * Returns the configuration object for this channel.
    - * Package private. Do not call from outside goog.net.xpc.
    - *
    - * @return {Object} The configuration object for this channel.
    - */
    -goog.net.xpc.CrossPageChannel.prototype.getConfig = function() {
    -  return this.cfg_;
    -};
    -
    -
    -/**
    - * Returns a reference to the iframe-element.
    - * Package private. Do not call from outside goog.net.xpc.
    - *
    - * @return {Object} A reference to the iframe-element.
    - */
    -goog.net.xpc.CrossPageChannel.prototype.getIframeElement = function() {
    -  return this.iframeElement_;
    -};
    -
    -
    -/**
    - * Sets the window object the foreign document resides in.
    - *
    - * @param {Object} peerWindowObject The window object of the peer.
    - */
    -goog.net.xpc.CrossPageChannel.prototype.setPeerWindowObject =
    -    function(peerWindowObject) {
    -  this.peerWindowObject_ = peerWindowObject;
    -};
    -
    -
    -/**
    - * Returns the window object the foreign document resides in.
    - *
    - * @return {Object} The window object of the peer.
    - * @package
    - */
    -goog.net.xpc.CrossPageChannel.prototype.getPeerWindowObject = function() {
    -  return this.peerWindowObject_;
    -};
    -
    -
    -/**
    - * Determines whether the peer window is available (e.g. not closed).
    - *
    - * @return {boolean} Whether the peer window is available.
    - * @package
    - */
    -goog.net.xpc.CrossPageChannel.prototype.isPeerAvailable = function() {
    -  // NOTE(user): This check is not reliable in IE, where a document in an
    -  // iframe does not get unloaded when removing the iframe element from the DOM.
    -  // TODO(user): Find something that works in IE as well.
    -  // NOTE(user): "!this.peerWindowObject_.closed" evaluates to 'false' in IE9
    -  // sometimes even though typeof(this.peerWindowObject_.closed) is boolean and
    -  // this.peerWindowObject_.closed evaluates to 'false'. Casting it to a Boolean
    -  // results in sane evaluation. When this happens, it's in the inner iframe
    -  // when querying its parent's 'closed' status. Note that this is a different
    -  // case than mibuerge@'s note above.
    -  try {
    -    return !!this.peerWindowObject_ && !Boolean(this.peerWindowObject_.closed);
    -  } catch (e) {
    -    // If the window is closing, an error may be thrown.
    -    return false;
    -  }
    -};
    -
    -
    -/**
    - * Determine which transport type to use for this channel / useragent.
    - * @return {goog.net.xpc.TransportTypes|undefined} The best transport type.
    - * @private
    - */
    -goog.net.xpc.CrossPageChannel.prototype.determineTransportType_ = function() {
    -  var transportType;
    -  if (goog.isFunction(document.postMessage) ||
    -      goog.isFunction(window.postMessage) ||
    -      // IE8 supports window.postMessage, but
    -      // typeof window.postMessage returns "object"
    -      (goog.userAgent.IE && window.postMessage)) {
    -    transportType = goog.net.xpc.TransportTypes.NATIVE_MESSAGING;
    -  } else if (goog.userAgent.GECKO) {
    -    transportType = goog.net.xpc.TransportTypes.FRAME_ELEMENT_METHOD;
    -  } else if (goog.userAgent.IE &&
    -             this.cfg_[goog.net.xpc.CfgFields.PEER_RELAY_URI]) {
    -    transportType = goog.net.xpc.TransportTypes.IFRAME_RELAY;
    -  } else if (goog.userAgent.IE && goog.net.xpc.NixTransport.isNixSupported()) {
    -    transportType = goog.net.xpc.TransportTypes.NIX;
    -  } else {
    -    transportType = goog.net.xpc.TransportTypes.IFRAME_POLLING;
    -  }
    -  return transportType;
    -};
    -
    -
    -/**
    - * Creates the transport for this channel. Chooses from the available
    - * transport based on the user agent and the configuration.
    - * @private
    - */
    -goog.net.xpc.CrossPageChannel.prototype.createTransport_ = function() {
    -  // return, if the transport has already been created
    -  if (this.transport_) {
    -    return;
    -  }
    -
    -  // TODO(user): Use goog.scope.
    -  var CfgFields = goog.net.xpc.CfgFields;
    -
    -  if (!this.cfg_[CfgFields.TRANSPORT]) {
    -    this.cfg_[CfgFields.TRANSPORT] =
    -        this.determineTransportType_();
    -  }
    -
    -  switch (this.cfg_[CfgFields.TRANSPORT]) {
    -    case goog.net.xpc.TransportTypes.NATIVE_MESSAGING:
    -      var protocolVersion = this.cfg_[
    -          CfgFields.NATIVE_TRANSPORT_PROTOCOL_VERSION] || 2;
    -      this.transport_ = new goog.net.xpc.NativeMessagingTransport(
    -          this,
    -          this.cfg_[CfgFields.PEER_HOSTNAME],
    -          this.domHelper_,
    -          !!this.cfg_[CfgFields.ONE_SIDED_HANDSHAKE],
    -          protocolVersion);
    -      break;
    -    case goog.net.xpc.TransportTypes.NIX:
    -      this.transport_ = new goog.net.xpc.NixTransport(this, this.domHelper_);
    -      break;
    -    case goog.net.xpc.TransportTypes.FRAME_ELEMENT_METHOD:
    -      this.transport_ =
    -          new goog.net.xpc.FrameElementMethodTransport(this, this.domHelper_);
    -      break;
    -    case goog.net.xpc.TransportTypes.IFRAME_RELAY:
    -      this.transport_ =
    -          new goog.net.xpc.IframeRelayTransport(this, this.domHelper_);
    -      break;
    -    case goog.net.xpc.TransportTypes.IFRAME_POLLING:
    -      this.transport_ =
    -          new goog.net.xpc.IframePollingTransport(this, this.domHelper_);
    -      break;
    -    case goog.net.xpc.TransportTypes.DIRECT:
    -      if (this.peerWindowObject_ &&
    -          goog.net.xpc.DirectTransport.isSupported(/** @type {!Window} */ (
    -              this.peerWindowObject_))) {
    -        this.transport_ =
    -            new goog.net.xpc.DirectTransport(this, this.domHelper_);
    -      } else {
    -        goog.log.info(
    -            goog.net.xpc.logger,
    -            'DirectTransport not supported for this window, peer window in' +
    -            ' different security context or not set yet.');
    -      }
    -      break;
    -  }
    -
    -  if (this.transport_) {
    -    goog.log.info(goog.net.xpc.logger,
    -        'Transport created: ' + this.transport_.getName());
    -  } else {
    -    throw Error('CrossPageChannel: No suitable transport found!');
    -  }
    -};
    -
    -
    -/**
    - * Returns the transport type in use for this channel.
    - * @return {number} Transport-type identifier.
    - */
    -goog.net.xpc.CrossPageChannel.prototype.getTransportType = function() {
    -  return this.transport_.getType();
    -};
    -
    -
    -/**
    - * Returns the tranport name in use for this channel.
    - * @return {string} The transport name.
    - */
    -goog.net.xpc.CrossPageChannel.prototype.getTransportName = function() {
    -  return this.transport_.getName();
    -};
    -
    -
    -/**
    - * @return {!Object} Configuration-object to be used by the peer to
    - *     initialize the channel.
    - */
    -goog.net.xpc.CrossPageChannel.prototype.getPeerConfiguration = function() {
    -  var peerCfg = {};
    -  peerCfg[goog.net.xpc.CfgFields.CHANNEL_NAME] = this.name;
    -  peerCfg[goog.net.xpc.CfgFields.TRANSPORT] =
    -      this.cfg_[goog.net.xpc.CfgFields.TRANSPORT];
    -  peerCfg[goog.net.xpc.CfgFields.ONE_SIDED_HANDSHAKE] =
    -      this.cfg_[goog.net.xpc.CfgFields.ONE_SIDED_HANDSHAKE];
    -
    -  if (this.cfg_[goog.net.xpc.CfgFields.LOCAL_RELAY_URI]) {
    -    peerCfg[goog.net.xpc.CfgFields.PEER_RELAY_URI] =
    -        this.cfg_[goog.net.xpc.CfgFields.LOCAL_RELAY_URI];
    -  }
    -  if (this.cfg_[goog.net.xpc.CfgFields.LOCAL_POLL_URI]) {
    -    peerCfg[goog.net.xpc.CfgFields.PEER_POLL_URI] =
    -        this.cfg_[goog.net.xpc.CfgFields.LOCAL_POLL_URI];
    -  }
    -  if (this.cfg_[goog.net.xpc.CfgFields.PEER_POLL_URI]) {
    -    peerCfg[goog.net.xpc.CfgFields.LOCAL_POLL_URI] =
    -        this.cfg_[goog.net.xpc.CfgFields.PEER_POLL_URI];
    -  }
    -  var role = this.cfg_[goog.net.xpc.CfgFields.ROLE];
    -  if (role) {
    -    peerCfg[goog.net.xpc.CfgFields.ROLE] =
    -        role == goog.net.xpc.CrossPageChannelRole.INNER ?
    -            goog.net.xpc.CrossPageChannelRole.OUTER :
    -            goog.net.xpc.CrossPageChannelRole.INNER;
    -  }
    -
    -  return peerCfg;
    -};
    -
    -
    -/**
    - * Creates the iframe containing the peer page in a specified parent element.
    - * This method does not connect the channel, connect() still has to be called
    - * separately.
    - *
    - * @param {!Element} parentElm The container element the iframe is appended to.
    - * @param {Function=} opt_configureIframeCb If present, this function gets
    - *     called with the iframe element as parameter to allow setting properties
    - *     on it before it gets added to the DOM. If absent, the iframe's width and
    - *     height are set to '100%'.
    - * @param {boolean=} opt_addCfgParam Whether to add the peer configuration as
    - *     URL parameter (default: true).
    - * @return {!HTMLIFrameElement} The iframe element.
    - */
    -goog.net.xpc.CrossPageChannel.prototype.createPeerIframe = function(
    -    parentElm, opt_configureIframeCb, opt_addCfgParam) {
    -  goog.log.info(goog.net.xpc.logger, 'createPeerIframe()');
    -
    -  var iframeId = this.cfg_[goog.net.xpc.CfgFields.IFRAME_ID];
    -  if (!iframeId) {
    -    // Create a randomized ID for the iframe element to avoid
    -    // bfcache-related issues.
    -    iframeId = this.cfg_[goog.net.xpc.CfgFields.IFRAME_ID] =
    -        'xpcpeer' + goog.net.xpc.getRandomString(4);
    -  }
    -
    -  // TODO(user) Opera creates a history-entry when creating an iframe
    -  // programmatically as follows. Find a way which avoids this.
    -
    -  var iframeElm = goog.dom.getDomHelper(parentElm).createElement('IFRAME');
    -  iframeElm.id = iframeElm.name = iframeId;
    -  if (opt_configureIframeCb) {
    -    opt_configureIframeCb(iframeElm);
    -  } else {
    -    iframeElm.style.width = iframeElm.style.height = '100%';
    -  }
    -
    -  this.cleanUpIncompleteConnection_();
    -  this.peerWindowDeferred_ =
    -      new goog.async.Deferred(undefined, this);
    -  var peerUri = this.getPeerUri(opt_addCfgParam);
    -  this.peerLoadHandler_.listenOnceWithScope(iframeElm, 'load',
    -      this.peerWindowDeferred_.callback, false, this.peerWindowDeferred_);
    -
    -  if (goog.userAgent.GECKO || goog.userAgent.WEBKIT) {
    -    // Appending the iframe in a timeout to avoid a weird fastback issue, which
    -    // is present in Safari and Gecko.
    -    window.setTimeout(
    -        goog.bind(function() {
    -          parentElm.appendChild(iframeElm);
    -          iframeElm.src = peerUri.toString();
    -          goog.log.info(goog.net.xpc.logger,
    -              'peer iframe created (' + iframeId + ')');
    -        }, this), 1);
    -  } else {
    -    iframeElm.src = peerUri.toString();
    -    parentElm.appendChild(iframeElm);
    -    goog.log.info(goog.net.xpc.logger,
    -        'peer iframe created (' + iframeId + ')');
    -  }
    -
    -  return /** @type {!HTMLIFrameElement} */ (iframeElm);
    -};
    -
    -
    -/**
    - * Clean up after any incomplete attempt to establish and connect to a peer
    - * iframe.
    - * @private
    - */
    -goog.net.xpc.CrossPageChannel.prototype.cleanUpIncompleteConnection_ =
    -    function() {
    -  if (this.peerWindowDeferred_) {
    -    this.peerWindowDeferred_.cancel();
    -    this.peerWindowDeferred_ = null;
    -  }
    -  this.deferredDeliveries_.length = 0;
    -  this.peerLoadHandler_.removeAll();
    -};
    -
    -
    -/**
    - * Returns the peer URI, with an optional URL parameter for configuring the peer
    - * window.
    - *
    - * @param {boolean=} opt_addCfgParam Whether to add the peer configuration as
    - *     URL parameter (default: true).
    - * @return {!goog.Uri} The peer URI.
    - */
    -goog.net.xpc.CrossPageChannel.prototype.getPeerUri = function(opt_addCfgParam) {
    -  var peerUri = this.cfg_[goog.net.xpc.CfgFields.PEER_URI];
    -  if (goog.isString(peerUri)) {
    -    peerUri = this.cfg_[goog.net.xpc.CfgFields.PEER_URI] =
    -        new goog.Uri(peerUri);
    -  }
    -
    -  // Add the channel configuration used by the peer as URL parameter.
    -  if (opt_addCfgParam !== false) {
    -    peerUri.setParameterValue('xpc',
    -                              goog.json.serialize(
    -                                  this.getPeerConfiguration()));
    -  }
    -
    -  return peerUri;
    -};
    -
    -
    -/**
    - * Initiates connecting the channel. When this method is called, all the
    - * information needed to connect the channel has to be available.
    - *
    - * @override
    - * @param {Function=} opt_connectCb The function to be called when the
    - * channel has been connected and is ready to be used.
    - */
    -goog.net.xpc.CrossPageChannel.prototype.connect = function(opt_connectCb) {
    -  this.connectCb_ = opt_connectCb || goog.nullFunction;
    -
    -  // If this channel was previously closed, transition back to the NOT_CONNECTED
    -  // state to ensure that the connection can proceed (xpcDeliver blocks
    -  // transport messages while the connection state is CLOSED).
    -  if (this.state_ == goog.net.xpc.ChannelStates.CLOSED) {
    -    this.state_ = goog.net.xpc.ChannelStates.NOT_CONNECTED;
    -  }
    -
    -  // If we know of a peer window whose creation has been requested but is not
    -  // complete, peerWindowDeferred_ will be non-null, and we should block on it.
    -  if (this.peerWindowDeferred_) {
    -    this.peerWindowDeferred_.addCallback(this.continueConnection_);
    -  } else {
    -    this.continueConnection_();
    -  }
    -};
    -
    -
    -/**
    - * Continues the connection process once we're as sure as we can be that the
    - * peer iframe has been created.
    - * @private
    - */
    -goog.net.xpc.CrossPageChannel.prototype.continueConnection_ = function() {
    -  goog.log.info(goog.net.xpc.logger, 'continueConnection_()');
    -  this.peerWindowDeferred_ = null;
    -  if (this.cfg_[goog.net.xpc.CfgFields.IFRAME_ID]) {
    -    this.iframeElement_ = this.domHelper_.getElement(
    -        this.cfg_[goog.net.xpc.CfgFields.IFRAME_ID]);
    -  }
    -  if (this.iframeElement_) {
    -    var winObj = this.iframeElement_.contentWindow;
    -    // accessing the window using contentWindow doesn't work in safari
    -    if (!winObj) {
    -      winObj = window.frames[this.cfg_[goog.net.xpc.CfgFields.IFRAME_ID]];
    -    }
    -    this.setPeerWindowObject(winObj);
    -  }
    -
    -  // if the peer window object has not been set at this point, we assume
    -  // being in an iframe and the channel is meant to be to the containing page
    -  if (!this.peerWindowObject_) {
    -    // throw an error if we are in the top window (== not in an iframe)
    -    if (window == window.top) {
    -      throw Error(
    -          "CrossPageChannel: Can't connect, peer window-object not set.");
    -    } else {
    -      this.setPeerWindowObject(window.parent);
    -    }
    -  }
    -
    -  this.createTransport_();
    -
    -  this.transport_.connect();
    -
    -  // Now we run any deferred deliveries collected while connection was deferred.
    -  while (this.deferredDeliveries_.length > 0) {
    -    this.deferredDeliveries_.shift()();
    -  }
    -};
    -
    -
    -/**
    - * Closes the channel.
    - */
    -goog.net.xpc.CrossPageChannel.prototype.close = function() {
    -  this.cleanUpIncompleteConnection_();
    -  this.state_ = goog.net.xpc.ChannelStates.CLOSED;
    -  goog.dispose(this.transport_);
    -  this.transport_ = null;
    -  this.connectCb_ = null;
    -  goog.dispose(this.connectionDelay_);
    -  this.connectionDelay_ = null;
    -  goog.log.info(goog.net.xpc.logger, 'Channel "' + this.name + '" closed');
    -};
    -
    -
    -/**
    - * Package-private.
    - * Called by the transport when the channel is connected.
    - * @param {number=} opt_delay Delay this number of milliseconds before calling
    - *     the connection callback. Usage is discouraged, but can be used to paper
    - *     over timing vulnerabilities when there is no alternative.
    - */
    -goog.net.xpc.CrossPageChannel.prototype.notifyConnected = function(opt_delay) {
    -  if (this.isConnected() ||
    -      (this.connectionDelay_ && this.connectionDelay_.isActive())) {
    -    return;
    -  }
    -  this.state_ = goog.net.xpc.ChannelStates.CONNECTED;
    -  goog.log.info(goog.net.xpc.logger, 'Channel "' + this.name + '" connected');
    -  goog.dispose(this.connectionDelay_);
    -  if (goog.isDef(opt_delay)) {
    -    this.connectionDelay_ =
    -        new goog.async.Delay(this.connectCb_, opt_delay);
    -    this.connectionDelay_.start();
    -  } else {
    -    this.connectionDelay_ = null;
    -    this.connectCb_();
    -  }
    -};
    -
    -
    -
    -/**
    - * Called by the transport in case of an unrecoverable failure.
    - * Package private. Do not call from outside goog.net.xpc.
    - */
    -goog.net.xpc.CrossPageChannel.prototype.notifyTransportError = function() {
    -  goog.log.info(goog.net.xpc.logger, 'Transport Error');
    -  this.close();
    -};
    -
    -
    -/** @override */
    -goog.net.xpc.CrossPageChannel.prototype.send = function(serviceName, payload) {
    -  if (!this.isConnected()) {
    -    goog.log.error(goog.net.xpc.logger, 'Can\'t send. Channel not connected.');
    -    return;
    -  }
    -  // Check if the peer is still around.
    -  if (!this.isPeerAvailable()) {
    -    goog.log.error(goog.net.xpc.logger, 'Peer has disappeared.');
    -    this.close();
    -    return;
    -  }
    -  if (goog.isObject(payload)) {
    -    payload = goog.json.serialize(payload);
    -  }
    -
    -  // Partially URL-encode the service name because some characters (: and |) are
    -  // used as delimiters for some transports, and we want to allow those
    -  // characters in service names.
    -  this.transport_.send(this.escapeServiceName_(serviceName), payload);
    -};
    -
    -
    -/**
    - * Delivers messages to the appropriate service-handler. Named xpcDeliver to
    - * avoid name conflict with {@code deliver} function in superclass
    - * goog.messaging.AbstractChannel.
    - *
    - * @param {string} serviceName The name of the port.
    - * @param {string} payload The payload.
    - * @param {string=} opt_origin An optional origin for the message, where the
    - *     underlying transport makes that available.  If this is specified, and
    - *     the PEER_HOSTNAME parameter was provided, they must match or the message
    - *     will be rejected.
    - * @package
    - */
    -goog.net.xpc.CrossPageChannel.prototype.xpcDeliver = function(
    -    serviceName, payload, opt_origin) {
    -
    -  // This check covers the very rare (but producable) case where the inner frame
    -  // becomes ready and sends its setup message while the outer frame is
    -  // deferring its connect method waiting for the inner frame to be ready. The
    -  // resulting deferral ensures the message will not be processed until the
    -  // channel is fully configured.
    -  if (this.peerWindowDeferred_) {
    -    this.deferredDeliveries_.push(
    -        goog.bind(this.xpcDeliver, this, serviceName, payload, opt_origin));
    -    return;
    -  }
    -
    -  // Check whether the origin of the message is as expected.
    -  if (!this.isMessageOriginAcceptable_(opt_origin)) {
    -    goog.log.warning(goog.net.xpc.logger,
    -        'Message received from unapproved origin "' +
    -        opt_origin + '" - rejected.');
    -    return;
    -  }
    -
    -  // If there is another channel still open, the native transport's global
    -  // postMessage listener will still be active.  This will mean that messages
    -  // being sent to the now-closed channel will still be received and delivered,
    -  // such as transport service traffic from its previous correspondent in the
    -  // other frame.  Ensure these messages don't cause exceptions.
    -  // Example: http://b/12419303
    -  if (this.isDisposed() || this.state_ == goog.net.xpc.ChannelStates.CLOSED) {
    -    goog.log.warning(goog.net.xpc.logger,
    -        'CrossPageChannel::xpcDeliver(): Channel closed.');
    -  } else if (!serviceName ||
    -      serviceName == goog.net.xpc.TRANSPORT_SERVICE_) {
    -    this.transport_.transportServiceHandler(payload);
    -  } else {
    -    // only deliver messages if connected
    -    if (this.isConnected()) {
    -      this.deliver(this.unescapeServiceName_(serviceName), payload);
    -    } else {
    -      goog.log.info(goog.net.xpc.logger,
    -          'CrossPageChannel::xpcDeliver(): Not connected.');
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Escape the user-provided service name for sending across the channel. This
    - * URL-encodes certain special characters so they don't conflict with delimiters
    - * used by some of the transports, and adds a special prefix if the name
    - * conflicts with the reserved transport service name.
    - *
    - * This is the opposite of {@link #unescapeServiceName_}.
    - *
    - * @param {string} name The name of the service to escape.
    - * @return {string} The escaped service name.
    - * @private
    - */
    -goog.net.xpc.CrossPageChannel.prototype.escapeServiceName_ = function(name) {
    -  if (goog.net.xpc.CrossPageChannel.TRANSPORT_SERVICE_ESCAPE_RE_.test(name)) {
    -    name = '%' + name;
    -  }
    -  return name.replace(/[%:|]/g, encodeURIComponent);
    -};
    -
    -
    -/**
    - * Unescape the escaped service name that was sent across the channel. This is
    - * the opposite of {@link #escapeServiceName_}.
    - *
    - * @param {string} name The name of the service to unescape.
    - * @return {string} The unescaped service name.
    - * @private
    - */
    -goog.net.xpc.CrossPageChannel.prototype.unescapeServiceName_ = function(name) {
    -  name = name.replace(/%[0-9a-f]{2}/gi, decodeURIComponent);
    -  if (goog.net.xpc.CrossPageChannel.TRANSPORT_SERVICE_UNESCAPE_RE_.test(name)) {
    -    return name.substring(1);
    -  } else {
    -    return name;
    -  }
    -};
    -
    -
    -/**
    - * Returns the role of this channel (either inner or outer).
    - * @return {number} The role of this channel.
    - */
    -goog.net.xpc.CrossPageChannel.prototype.getRole = function() {
    -  var role = this.cfg_[goog.net.xpc.CfgFields.ROLE];
    -  if (goog.isNumber(role)) {
    -    return role;
    -  } else {
    -    return window.parent == this.peerWindowObject_ ?
    -        goog.net.xpc.CrossPageChannelRole.INNER :
    -        goog.net.xpc.CrossPageChannelRole.OUTER;
    -  }
    -};
    -
    -
    -/**
    - * Sets the channel name. Note, this doesn't establish a unique channel to
    - * communicate on.
    - * @param {string} name The new channel name.
    - */
    -goog.net.xpc.CrossPageChannel.prototype.updateChannelNameAndCatalog = function(
    -    name) {
    -  goog.log.fine(goog.net.xpc.logger, 'changing channel name to ' + name);
    -  delete goog.net.xpc.channels[this.name];
    -  this.name = name;
    -  goog.net.xpc.channels[name] = this;
    -};
    -
    -
    -/**
    - * Returns whether an incoming message with the given origin is acceptable.
    - * If an incoming request comes with a specified (non-empty) origin, and the
    - * PEER_HOSTNAME config parameter has also been provided, the two must match,
    - * or the message is unacceptable.
    - * @param {string=} opt_origin The origin associated with the incoming message.
    - * @return {boolean} Whether the message is acceptable.
    - * @private
    - */
    -goog.net.xpc.CrossPageChannel.prototype.isMessageOriginAcceptable_ = function(
    -    opt_origin) {
    -  var peerHostname = this.cfg_[goog.net.xpc.CfgFields.PEER_HOSTNAME];
    -  return goog.string.isEmptyOrWhitespace(goog.string.makeSafe(opt_origin)) ||
    -      goog.string.isEmptyOrWhitespace(goog.string.makeSafe(peerHostname)) ||
    -      opt_origin == this.cfg_[goog.net.xpc.CfgFields.PEER_HOSTNAME];
    -};
    -
    -
    -/** @override */
    -goog.net.xpc.CrossPageChannel.prototype.disposeInternal = function() {
    -  this.close();
    -
    -  this.peerWindowObject_ = null;
    -  this.iframeElement_ = null;
    -  delete goog.net.xpc.channels[this.name];
    -  goog.dispose(this.peerLoadHandler_);
    -  delete this.peerLoadHandler_;
    -  goog.net.xpc.CrossPageChannel.base(this, 'disposeInternal');
    -};
    -
    -
    -/**
    - * Disposes all channels.
    - * @private
    - */
    -goog.net.xpc.CrossPageChannel.disposeAll_ = function() {
    -  for (var name in goog.net.xpc.channels) {
    -    goog.dispose(goog.net.xpc.channels[name]);
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xpc/crosspagechannel_test.html b/src/database/third_party/closure-library/closure/goog/net/xpc/crosspagechannel_test.html
    deleted file mode 100644
    index 4ec5dc94a3e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xpc/crosspagechannel_test.html
    +++ /dev/null
    @@ -1,36 +0,0 @@
    -<!DOCTYPE html>
    -<!--
    -  Author: dbk@google.com (David Barrett-Kahn)
    --->
    -<html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   CrossPageChannel: End-to-End Test
    -  </title>
    -  <script type="text/javascript" src="../../base.js">
    -  </script>
    -  <script type="text/javascript">
    -    goog.require('goog.net.xpc.CrossPageChannelTest');
    -  </script>
    - </head>
    - <body>
    -  <!-- Debug box. -->
    -  <div style="position:absolute; float: right; top: 10px; right: 10px; width: 500px">
    -   Debug [
    -   <a href="#" onclick="document.getElementById('debugDiv').innerHTML = '';">
    -    clear
    -   </a>
    -   ]:
    -   <br />
    -   <div id="debugDiv" style="border: 1px #000000 solid; font-size:xx-small; background: #fff;">
    -   </div>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xpc/crosspagechannel_test.js b/src/database/third_party/closure-library/closure/goog/net/xpc/crosspagechannel_test.js
    deleted file mode 100644
    index 7d56ef853be..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xpc/crosspagechannel_test.js
    +++ /dev/null
    @@ -1,1081 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.net.xpc.CrossPageChannelTest');
    -goog.setTestOnly('goog.net.xpc.CrossPageChannelTest');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.Uri');
    -goog.require('goog.async.Deferred');
    -goog.require('goog.dom');
    -goog.require('goog.labs.userAgent.browser');
    -goog.require('goog.log');
    -goog.require('goog.log.Level');
    -goog.require('goog.net.xpc');
    -goog.require('goog.net.xpc.CfgFields');
    -goog.require('goog.net.xpc.CrossPageChannel');
    -goog.require('goog.net.xpc.CrossPageChannelRole');
    -goog.require('goog.net.xpc.TransportTypes');
    -goog.require('goog.object');
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -
    -// Set this to false when working on this test.  It needs to be true for
    -// automated testing, as some browsers (eg IE8) choke on the large numbers of
    -// iframes this test would otherwise leave active.
    -var CLEAN_UP_IFRAMES = true;
    -
    -var IFRAME_LOAD_WAIT_MS = 1000;
    -var stubs = new goog.testing.PropertyReplacer();
    -var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall(
    -    document.title);
    -var uniqueId = 0;
    -var driver;
    -var canAccessSameDomainIframe = true;
    -var accessCheckIframes = [];
    -
    -function setUpPage() {
    -  // This test is insanely slow on IE8 for some reason.
    -  asyncTestCase.stepTimeout = 20 * 1000;
    -
    -  // Show debug log
    -  var debugDiv = goog.dom.getElement('debugDiv');
    -  var logger = goog.log.getLogger('goog.net.xpc');
    -  logger.setLevel(goog.log.Level.ALL);
    -  goog.log.addHandler(logger, function(logRecord) {
    -    var msgElm = goog.dom.createDom('div');
    -    msgElm.innerHTML = logRecord.getMessage();
    -    goog.dom.appendChild(debugDiv, msgElm);
    -  });
    -  asyncTestCase.waitForAsync('Checking if we can access same domain iframes');
    -  checkSameDomainIframeAccess();
    -}
    -
    -
    -function setUp() {
    -  driver = new Driver();
    -}
    -
    -
    -function tearDown() {
    -  stubs.reset();
    -  driver.dispose();
    -}
    -
    -
    -function checkSameDomainIframeAccess() {
    -  accessCheckIframes.push(
    -      create1x1Iframe('nonexistant', 'testdata/i_am_non_existant.html'));
    -  window.setTimeout(function() {
    -    accessCheckIframes.push(
    -        create1x1Iframe('existant', 'testdata/access_checker.html'));
    -  }, 10);
    -}
    -
    -
    -function create1x1Iframe(iframeId, src) {
    -  var iframeAccessChecker = goog.dom.createElement('IFRAME');
    -  iframeAccessChecker.id = iframeAccessChecker.name = iframeId;
    -  iframeAccessChecker.style.width = iframeAccessChecker.style.height = '1px';
    -  iframeAccessChecker.src = src;
    -  document.body.insertBefore(iframeAccessChecker, document.body.firstChild);
    -  return iframeAccessChecker;
    -}
    -
    -
    -function sameDomainIframeAccessComplete(canAccess) {
    -  canAccessSameDomainIframe = canAccess;
    -  for (var i = 0; i < accessCheckIframes.length; i++) {
    -    document.body.removeChild(accessCheckIframes[i]);
    -  }
    -  asyncTestCase.continueTesting();
    -}
    -
    -
    -function testCreateIframeSpecifyId() {
    -  driver.createPeerIframe('new_iframe');
    -
    -  asyncTestCase.waitForAsync('iframe load');
    -  window.setTimeout(function() {
    -    driver.checkPeerIframe();
    -    asyncTestCase.continueTesting();
    -  }, IFRAME_LOAD_WAIT_MS);
    -}
    -
    -
    -function testCreateIframeRandomId() {
    -  driver.createPeerIframe();
    -
    -  asyncTestCase.waitForAsync('iframe load');
    -  window.setTimeout(function() {
    -    driver.checkPeerIframe();
    -    asyncTestCase.continueTesting();
    -  }, IFRAME_LOAD_WAIT_MS);
    -}
    -
    -
    -function testGetRole() {
    -  var cfg = {};
    -  cfg[goog.net.xpc.CfgFields.ROLE] = goog.net.xpc.CrossPageChannelRole.OUTER;
    -  var channel = new goog.net.xpc.CrossPageChannel(cfg);
    -  // If the configured role is ignored, this will cause the dynamicly
    -  // determined role to become INNER.
    -  channel.peerWindowObject_ = window.parent;
    -  assertEquals('Channel should use role from the config.',
    -      goog.net.xpc.CrossPageChannelRole.OUTER, channel.getRole());
    -  channel.dispose();
    -}
    -
    -
    -// The following batch of tests:
    -// * Establishes a peer iframe
    -// * Connects an XPC channel between the frames
    -// * From the connection callback in each frame, sends an 'echo' request, and
    -//   expects a 'response' response.
    -// * Reconnects the inner frame, sends an 'echo', expects a 'response'.
    -// * Optionally, reconnects the outer frame, sends an 'echo', expects a
    -//   'response'.
    -// * Optionally, reconnects the inner frame, but first reconfigures it to the
    -//   alternate protocol version, simulating an inner frame navigation that
    -//   picks up a new/old version.
    -//
    -// Every valid combination of protocol versions is tested, with both single and
    -// double ended handshakes.  Two timing scenarios are tested per combination,
    -// which is what the 'reverse' parameter distinguishes.
    -//
    -// Where single sided handshake is in use, reconnection by the outer frame is
    -// not supported, and therefore is not tested.
    -//
    -// The only known issue migrating to V2 is that once two V2 peers have
    -// connected, replacing either peer with a V1 peer will not work.  Upgrading V1
    -// peers to v2 is supported, as is replacing the only v2 peer in a connection
    -// with a v1.
    -
    -
    -function testLifeCycle_v1_v1() {
    -  checkLifeCycle(
    -      false /* oneSidedHandshake */,
    -      1 /* innerProtocolVersion */,
    -      1 /* outerProtocolVersion */,
    -      true /* outerFrameReconnectSupported */,
    -      true /* innerFrameMigrationSupported */,
    -      false /* reverse */);
    -}
    -
    -
    -function testLifeCycle_v1_v1_rev() {
    -  checkLifeCycle(
    -      false /* oneSidedHandshake */,
    -      1 /* innerProtocolVersion */,
    -      1 /* outerProtocolVersion */,
    -      true /* outerFrameReconnectSupported */,
    -      true /* innerFrameMigrationSupported */,
    -      true /* reverse */);
    -}
    -
    -
    -function testLifeCycle_v1_v1_onesided() {
    -  checkLifeCycle(
    -      true /* oneSidedHandshake */,
    -      1 /* innerProtocolVersion */,
    -      1 /* outerProtocolVersion */,
    -      false /* outerFrameReconnectSupported */,
    -      true /* innerFrameMigrationSupported */,
    -      false /* reverse */);
    -}
    -
    -
    -function testLifeCycle_v1_v1_onesided_rev() {
    -  checkLifeCycle(
    -      true /* oneSidedHandshake */,
    -      1 /* innerProtocolVersion */,
    -      1 /* outerProtocolVersion */,
    -      false /* outerFrameReconnectSupported */,
    -      true /* innerFrameMigrationSupported */,
    -      true /* reverse */);
    -}
    -
    -
    -function testLifeCycle_v1_v2() {
    -  checkLifeCycle(
    -      false /* oneSidedHandshake */,
    -      1 /* innerProtocolVersion */,
    -      2 /* outerProtocolVersion */,
    -      true /* outerFrameReconnectSupported */,
    -      true /* innerFrameMigrationSupported */,
    -      false /* reverse */);
    -}
    -
    -
    -function testLifeCycle_v1_v2_rev() {
    -  checkLifeCycle(
    -      false /* oneSidedHandshake */,
    -      1 /* innerProtocolVersion */,
    -      2 /* outerProtocolVersion */,
    -      true /* outerFrameReconnectSupported */,
    -      true /* innerFrameMigrationSupported */,
    -      true /* reverse */);
    -}
    -
    -
    -function testLifeCycle_v1_v2_onesided() {
    -  checkLifeCycle(
    -      true /* oneSidedHandshake */,
    -      1 /* innerProtocolVersion */,
    -      2 /* outerProtocolVersion */,
    -      false /* outerFrameReconnectSupported */,
    -      true /* innerFrameMigrationSupported */,
    -      false /* reverse */);
    -}
    -
    -
    -function testLifeCycle_v1_v2_onesided_rev() {
    -  checkLifeCycle(
    -      true /* oneSidedHandshake */,
    -      1 /* innerProtocolVersion */,
    -      2 /* outerProtocolVersion */,
    -      false /* outerFrameReconnectSupported */,
    -      true /* innerFrameMigrationSupported */,
    -      true /* reverse */);
    -}
    -
    -
    -function testLifeCycle_v2_v1() {
    -  checkLifeCycle(
    -      false /* oneSidedHandshake */,
    -      2 /* innerProtocolVersion */,
    -      1 /* outerProtocolVersion */,
    -      true /* outerFrameReconnectSupported */,
    -      true /* innerFrameMigrationSupported */,
    -      false /* reverse */);
    -}
    -
    -
    -function testLifeCycle_v2_v1_rev() {
    -  checkLifeCycle(
    -      false /* oneSidedHandshake */,
    -      2 /* innerProtocolVersion */,
    -      1 /* outerProtocolVersion */,
    -      true /* outerFrameReconnectSupported */,
    -      true /* innerFrameMigrationSupported */,
    -      true /* reverse */);
    -}
    -
    -
    -function testLifeCycle_v2_v1_onesided() {
    -  checkLifeCycle(
    -      true /* oneSidedHandshake */,
    -      2 /* innerProtocolVersion */,
    -      1 /* outerProtocolVersion */,
    -      false /* outerFrameReconnectSupported */,
    -      true /* innerFrameMigrationSupported */,
    -      false /* reverse */);
    -}
    -
    -
    -function testLifeCycle_v2_v1_onesided_rev() {
    -  checkLifeCycle(
    -      true /* oneSidedHandshake */,
    -      2 /* innerProtocolVersion */,
    -      1 /* outerProtocolVersion */,
    -      false /* outerFrameReconnectSupported */,
    -      true /* innerFrameMigrationSupported */,
    -      true /* reverse */);
    -}
    -
    -
    -function testLifeCycle_v2_v2() {
    -  checkLifeCycle(
    -      false /* oneSidedHandshake */,
    -      2 /* innerProtocolVersion */,
    -      2 /* outerProtocolVersion */,
    -      true /* outerFrameReconnectSupported */,
    -      false /* innerFrameMigrationSupported */,
    -      false /* reverse */);
    -}
    -
    -
    -function testLifeCycle_v2_v2_rev() {
    -  checkLifeCycle(
    -      false /* oneSidedHandshake */,
    -      2 /* innerProtocolVersion */,
    -      2 /* outerProtocolVersion */,
    -      true /* outerFrameReconnectSupported */,
    -      false /* innerFrameMigrationSupported */,
    -      true /* reverse */);
    -}
    -
    -
    -function testLifeCycle_v2_v2_onesided() {
    -  checkLifeCycle(
    -      true /* oneSidedHandshake */,
    -      2 /* innerProtocolVersion */,
    -      2 /* outerProtocolVersion */,
    -      false /* outerFrameReconnectSupported */,
    -      false /* innerFrameMigrationSupported */,
    -      false /* reverse */);
    -}
    -
    -
    -function testLifeCycle_v2_v2_onesided_rev() {
    -  checkLifeCycle(
    -      true /* oneSidedHandshake */,
    -      2 /* innerProtocolVersion */,
    -      2 /* outerProtocolVersion */,
    -      false /* outerFrameReconnectSupported */,
    -      false /* innerFrameMigrationSupported */,
    -      true /* reverse */);
    -}
    -
    -
    -function checkLifeCycle(oneSidedHandshake, innerProtocolVersion,
    -    outerProtocolVersion, outerFrameReconnectSupported,
    -    innerFrameMigrationSupported, reverse) {
    -  driver.createPeerIframe('new_iframe', oneSidedHandshake,
    -      innerProtocolVersion, outerProtocolVersion);
    -  driver.connect(true /* fullLifeCycleTest */, outerFrameReconnectSupported,
    -      innerFrameMigrationSupported, reverse);
    -}
    -
    -// testConnectMismatchedNames have been flaky on IEs.
    -// Flakiness is tracked in http://b/18595666
    -// For now, not running these tests on IE.
    -
    -function testConnectMismatchedNames_v1_v1() {
    -  if (goog.labs.userAgent.browser.isIE()) {
    -    return;
    -  }
    -
    -  checkConnectMismatchedNames(
    -      1 /* innerProtocolVersion */,
    -      1 /* outerProtocolVersion */,
    -      false /* reverse */);
    -}
    -
    -
    -function testConnectMismatchedNames_v1_v1_rev() {
    -  if (goog.labs.userAgent.browser.isIE()) {
    -    return;
    -  }
    -
    -  checkConnectMismatchedNames(
    -      1 /* innerProtocolVersion */,
    -      1 /* outerProtocolVersion */,
    -      true /* reverse */);
    -}
    -
    -
    -function testConnectMismatchedNames_v1_v2() {
    -  if (goog.labs.userAgent.browser.isIE()) {
    -    return;
    -  }
    -
    -  checkConnectMismatchedNames(
    -      1 /* innerProtocolVersion */,
    -      2 /* outerProtocolVersion */,
    -      false /* reverse */);
    -}
    -
    -
    -function testConnectMismatchedNames_v1_v2_rev() {
    -  if (goog.labs.userAgent.browser.isIE()) {
    -    return;
    -  }
    -
    -  checkConnectMismatchedNames(
    -      1 /* innerProtocolVersion */,
    -      2 /* outerProtocolVersion */,
    -      true /* reverse */);
    -}
    -
    -
    -function testConnectMismatchedNames_v2_v1() {
    -  if (goog.labs.userAgent.browser.isIE()) {
    -    return;
    -  }
    -
    -  checkConnectMismatchedNames(
    -      2 /* innerProtocolVersion */,
    -      1 /* outerProtocolVersion */,
    -      false /* reverse */);
    -}
    -
    -
    -function testConnectMismatchedNames_v2_v1_rev() {
    -  if (goog.labs.userAgent.browser.isIE()) {
    -    return;
    -  }
    -
    -  checkConnectMismatchedNames(
    -      2 /* innerProtocolVersion */,
    -      1 /* outerProtocolVersion */,
    -      true /* reverse */);
    -}
    -
    -
    -function testConnectMismatchedNames_v2_v2() {
    -  if (goog.labs.userAgent.browser.isIE()) {
    -    return;
    -  }
    -
    -  checkConnectMismatchedNames(
    -      2 /* innerProtocolVersion */,
    -      2 /* outerProtocolVersion */,
    -      false /* reverse */);
    -}
    -
    -
    -function testConnectMismatchedNames_v2_v2_rev() {
    -  if (goog.labs.userAgent.browser.isIE()) {
    -    return;
    -  }
    -
    -  checkConnectMismatchedNames(
    -      2 /* innerProtocolVersion */,
    -      2 /* outerProtocolVersion */,
    -      true /* reverse */);
    -}
    -
    -
    -function checkConnectMismatchedNames(innerProtocolVersion,
    -    outerProtocolVersion, reverse) {
    -  driver.createPeerIframe('new_iframe', false /* oneSidedHandshake */,
    -      innerProtocolVersion,
    -      outerProtocolVersion, true /* opt_randomChannelNames */);
    -  driver.connect(false /* fullLifeCycleTest */,
    -      false /* outerFrameReconnectSupported */,
    -      false /* innerFrameMigrationSupported */,
    -      reverse /* reverse */);
    -}
    -
    -
    -function testEscapeServiceName() {
    -  var escape = goog.net.xpc.CrossPageChannel.prototype.escapeServiceName_;
    -  assertEquals('Shouldn\'t escape alphanumeric name',
    -               'fooBar123', escape('fooBar123'));
    -  assertEquals('Shouldn\'t escape most non-alphanumeric characters',
    -               '`~!@#$^&*()_-=+ []{}\'";,<.>/?\\',
    -               escape('`~!@#$^&*()_-=+ []{}\'";,<.>/?\\'));
    -  assertEquals('Should escape %, |, and :',
    -               'foo%3ABar%7C123%25', escape('foo:Bar|123%'));
    -  assertEquals('Should escape tp', '%25tp', escape('tp'));
    -  assertEquals('Should escape %tp', '%25%25tp', escape('%tp'));
    -  assertEquals('Should not escape stp', 'stp', escape('stp'));
    -  assertEquals('Should not escape s%tp', 's%25tp', escape('s%tp'));
    -}
    -
    -
    -function testSameDomainCheck_noMessageOrigin() {
    -  var channel = new goog.net.xpc.CrossPageChannel(goog.object.create(
    -      goog.net.xpc.CfgFields.PEER_HOSTNAME, 'http://foo.com'));
    -  assertTrue(channel.isMessageOriginAcceptable_(undefined));
    -}
    -
    -
    -function testSameDomainCheck_noPeerHostname() {
    -  var channel = new goog.net.xpc.CrossPageChannel({});
    -  assertTrue(channel.isMessageOriginAcceptable_('http://foo.com'));
    -}
    -
    -
    -function testSameDomainCheck_unconfigured() {
    -  var channel = new goog.net.xpc.CrossPageChannel({});
    -  assertTrue(channel.isMessageOriginAcceptable_(undefined));
    -}
    -
    -
    -function testSameDomainCheck_originsMatch() {
    -  var channel = new goog.net.xpc.CrossPageChannel(goog.object.create(
    -      goog.net.xpc.CfgFields.PEER_HOSTNAME, 'http://foo.com'));
    -  assertTrue(channel.isMessageOriginAcceptable_('http://foo.com'));
    -}
    -
    -
    -function testSameDomainCheck_originsMismatch() {
    -  var channel = new goog.net.xpc.CrossPageChannel(goog.object.create(
    -      goog.net.xpc.CfgFields.PEER_HOSTNAME, 'http://foo.com'));
    -  assertFalse(channel.isMessageOriginAcceptable_('http://nasty.com'));
    -}
    -
    -
    -function testUnescapeServiceName() {
    -  var unescape = goog.net.xpc.CrossPageChannel.prototype.unescapeServiceName_;
    -  assertEquals('Shouldn\'t modify alphanumeric name',
    -               'fooBar123', unescape('fooBar123'));
    -  assertEquals('Shouldn\'t modify most non-alphanumeric characters',
    -               '`~!@#$^&*()_-=+ []{}\'";,<.>/?\\',
    -               unescape('`~!@#$^&*()_-=+ []{}\'";,<.>/?\\'));
    -  assertEquals('Should unescape URL-escapes',
    -               'foo:Bar|123%', unescape('foo%3ABar%7C123%25'));
    -  assertEquals('Should unescape tp', 'tp', unescape('%25tp'));
    -  assertEquals('Should unescape %tp', '%tp', unescape('%25%25tp'));
    -  assertEquals('Should not escape stp', 'stp', unescape('stp'));
    -  assertEquals('Should not escape s%tp', 's%tp', unescape('s%25tp'));
    -}
    -
    -
    -/**
    - * Tests the case where the channel is disposed before it is fully connected.
    - */
    -function testDisposeBeforeConnect() {
    -  asyncTestCase.waitForAsync('Checking disposal before connection.');
    -  driver.createPeerIframe('new_iframe', false /* oneSidedHandshake */,
    -      2 /* innerProtocolVersion */, 2 /* outerProtocolVersion */,
    -      true /* opt_randomChannelNames */);
    -  driver.connectOuterAndDispose();
    -}
    -
    -
    -
    -/**
    - * Driver for the tests for CrossPageChannel.
    - *
    - * @constructor
    - * @extends {goog.Disposable}
    - */
    -Driver = function() {
    -  goog.Disposable.call(this);
    -
    -  /**
    -   * The peer iframe.
    -   * @type {!Element}
    -   * @private
    -   */
    -  this.iframe_ = null;
    -
    -  /**
    -   * The channel to use.
    -   * @type {goog.net.xpc.CrossPageChannel}
    -   * @private
    -   */
    -  this.channel_ = null;
    -
    -  /**
    -   * Outer frame configuration object.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.outerFrameCfg_ = null;
    -
    -  /**
    -   * The initial name of the outer channel.
    -   * @type {?string}
    -   * @private
    -   */
    -  this.initialOuterChannelName_ = null;
    -
    -  /**
    -   * Inner frame configuration object.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.innerFrameCfg_ = null;
    -
    -  /**
    -   * The contents of the payload of the 'echo' request sent by the inner frame.
    -   * @type {?string}
    -   * @private
    -   */
    -  this.innerFrameEchoPayload_ = null;
    -
    -  /**
    -   * The contents of the payload of the 'echo' request sent by the outer frame.
    -   * @type {?string}
    -   * @private
    -   */
    -  this.outerFrameEchoPayload_ = null;
    -
    -  /**
    -   * A deferred which fires when the inner frame receives its echo response.
    -   * @type {goog.async.Deferred}
    -   * @private
    -   */
    -  this.innerFrameResponseReceived_ = new goog.async.Deferred();
    -
    -  /**
    -   * A deferred which fires when the outer frame receives its echo response.
    -   * @type {goog.async.Deferred}
    -   * @private
    -   */
    -  this.outerFrameResponseReceived_ = new goog.async.Deferred();
    -
    -};
    -goog.inherits(Driver, goog.Disposable);
    -
    -
    -/** @override */
    -Driver.prototype.disposeInternal = function() {
    -  // Required to make this test perform acceptably (and pass) on slow browsers,
    -  // esp IE8.
    -  if (CLEAN_UP_IFRAMES) {
    -    goog.dom.removeNode(this.iframe_);
    -    delete this.iframe_;
    -  }
    -  goog.dispose(this.channel_);
    -  this.innerFrameResponseReceived_.cancel();
    -  this.innerFrameResponseReceived_ = null;
    -  this.outerFrameResponseReceived_.cancel();
    -  this.outerFrameResponseReceived_ = null;
    -  Driver.base(this, 'disposeInternal');
    -};
    -
    -
    -/**
    - * Returns the child peer's window object.
    - * @return {Window} Child peer's window.
    - * @private
    - */
    -Driver.prototype.getInnerPeer_ = function() {
    -  return this.iframe_.contentWindow;
    -};
    -
    -
    -/**
    - * Sets up the configuration objects for the inner and outer frames.
    - * @param {string=} opt_iframeId If present, the ID of the iframe to use,
    - *     otherwise, tells the channel to generate an iframe ID.
    - * @param {boolean=} opt_oneSidedHandshake Whether the one sided handshake
    - *     config option should be set.
    - * @param {string=} opt_channelName The name of the channel to use, or null
    - *     to generate one.
    - * @param {number=} opt_innerProtocolVersion The native transport protocol
    - *     version used in the inner iframe.
    - * @param {number=} opt_outerProtocolVersion The native transport protocol
    - *     version used in the outer iframe.
    - * @param {boolean=} opt_randomChannelNames Whether the different ends of the
    - *     channel should be allowed to pick differing, random names.
    - * @return {string} The name of the created channel.
    - * @private
    - */
    -Driver.prototype.setConfiguration_ = function(opt_iframeId,
    -    opt_oneSidedHandshake, opt_channelName, opt_innerProtocolVersion,
    -    opt_outerProtocolVersion, opt_randomChannelNames) {
    -  var cfg = {};
    -  if (opt_iframeId) {
    -    cfg[goog.net.xpc.CfgFields.IFRAME_ID] = opt_iframeId;
    -  }
    -  cfg[goog.net.xpc.CfgFields.PEER_URI] = 'testdata/inner_peer.html';
    -  if (!opt_randomChannelNames) {
    -    var channelName = opt_channelName || 'test_channel' + uniqueId++;
    -    cfg[goog.net.xpc.CfgFields.CHANNEL_NAME] = channelName;
    -  }
    -  cfg[goog.net.xpc.CfgFields.LOCAL_POLL_URI] = 'does-not-exist.html';
    -  cfg[goog.net.xpc.CfgFields.PEER_POLL_URI] = 'does-not-exist.html';
    -  cfg[goog.net.xpc.CfgFields.ONE_SIDED_HANDSHAKE] = !!opt_oneSidedHandshake;
    -  cfg[goog.net.xpc.CfgFields.NATIVE_TRANSPORT_PROTOCOL_VERSION] =
    -      opt_outerProtocolVersion;
    -  function resolveUri(fieldName) {
    -    cfg[fieldName] =
    -        goog.Uri.resolve(window.location.href, cfg[fieldName]).toString();
    -  }
    -  resolveUri(goog.net.xpc.CfgFields.PEER_URI);
    -  resolveUri(goog.net.xpc.CfgFields.LOCAL_POLL_URI);
    -  resolveUri(goog.net.xpc.CfgFields.PEER_POLL_URI);
    -  this.outerFrameCfg_ = cfg;
    -  this.innerFrameCfg_ = goog.object.clone(cfg);
    -  this.innerFrameCfg_[
    -      goog.net.xpc.CfgFields.NATIVE_TRANSPORT_PROTOCOL_VERSION] =
    -      opt_innerProtocolVersion;
    -};
    -
    -
    -/**
    - * Creates an outer frame channel object.
    - * @private
    - */
    -Driver.prototype.createChannel_ = function() {
    -  if (this.channel_) {
    -    this.channel_.dispose();
    -  }
    -  this.channel_ = new goog.net.xpc.CrossPageChannel(this.outerFrameCfg_);
    -  this.channel_.registerService('echo',
    -      goog.bind(this.echoHandler_, this));
    -  this.channel_.registerService('response',
    -      goog.bind(this.responseHandler_, this));
    -
    -  return this.channel_.name;
    -};
    -
    -
    -/**
    - * Checks the names of the inner and outer frames meet expectations.
    - * @private
    - */
    -Driver.prototype.checkChannelNames_ = function() {
    -  var outerName = this.channel_.name;
    -  var innerName = this.getInnerPeer_().channel.name;
    -  var configName = this.innerFrameCfg_[goog.net.xpc.CfgFields.CHANNEL_NAME] ||
    -      null;
    -
    -  // The outer channel never changes its name.
    -  assertEquals(this.initialOuterChannelName_, outerName);
    -  // The name should be as configured, if it was configured.
    -  if (configName) {
    -    assertEquals(configName, innerName);
    -  }
    -  // The names of both ends of the channel should match.
    -  assertEquals(innerName, outerName);
    -  G_testRunner.log('Channel name: ' + innerName);
    -};
    -
    -
    -/**
    - * Returns the configuration of the xpc.
    - * @return {?Object} The configuration of the xpc.
    - */
    -Driver.prototype.getInnerFrameConfiguration = function() {
    -  return this.innerFrameCfg_;
    -};
    -
    -
    -/**
    - * Creates the peer iframe.
    - * @param {string=} opt_iframeId If present, the ID of the iframe to create,
    - *     otherwise, generates an iframe ID.
    - * @param {boolean=} opt_oneSidedHandshake Whether a one sided handshake is
    - *     specified.
    - * @param {number=} opt_innerProtocolVersion The native transport protocol
    - *     version used in the inner iframe.
    - * @param {number=} opt_outerProtocolVersion The native transport protocol
    - *     version used in the outer iframe.
    - * @param {boolean=} opt_randomChannelNames Whether the ends of the channel
    - *     should be allowed to pick differing, random names.
    - * @return {!Array<string>} The id of the created iframe and the name of the
    - *     created channel.
    - */
    -Driver.prototype.createPeerIframe = function(opt_iframeId,
    -    opt_oneSidedHandshake, opt_innerProtocolVersion, opt_outerProtocolVersion,
    -    opt_randomChannelNames) {
    -  var expectedIframeId;
    -
    -  if (opt_iframeId) {
    -    expectedIframeId = opt_iframeId = opt_iframeId + uniqueId++;
    -  } else {
    -    // Have createPeerIframe() generate an ID
    -    stubs.set(goog.net.xpc, 'getRandomString', function(length) {
    -      return '' + length;
    -    });
    -    expectedIframeId = 'xpcpeer4';
    -  }
    -  assertNull('element[id=' + expectedIframeId + '] exists',
    -      goog.dom.getElement(expectedIframeId));
    -
    -  this.setConfiguration_(opt_iframeId, opt_oneSidedHandshake,
    -      undefined /* opt_channelName */, opt_innerProtocolVersion,
    -      opt_outerProtocolVersion, opt_randomChannelNames);
    -  var channelName = this.createChannel_();
    -  this.initialOuterChannelName_ = channelName;
    -  this.iframe_ = this.channel_.createPeerIframe(document.body);
    -
    -  assertEquals(expectedIframeId, this.iframe_.id);
    -};
    -
    -
    -/**
    - * Checks if the peer iframe has been created.
    - */
    -Driver.prototype.checkPeerIframe = function() {
    -  assertNotNull(this.iframe_);
    -  var peer = this.getInnerPeer_();
    -  assertNotNull(peer);
    -  assertNotNull(peer.document);
    -};
    -
    -
    -/**
    - * Starts the connection. The connection happens asynchronously.
    - */
    -Driver.prototype.connect = function(fullLifeCycleTest,
    -    outerFrameReconnectSupported, innerFrameMigrationSupported, reverse) {
    -  if (!this.isTransportTestable_()) {
    -    asyncTestCase.continueTesting();
    -    return;
    -  }
    -
    -  asyncTestCase.waitForAsync('parent and child connect');
    -
    -  // Set the criteria for the initial handshake portion of the test.
    -  this.reinitializeDeferreds_();
    -  this.innerFrameResponseReceived_.awaitDeferred(
    -      this.outerFrameResponseReceived_);
    -  this.innerFrameResponseReceived_.addCallback(
    -      goog.bind(this.checkChannelNames_, this));
    -
    -  if (fullLifeCycleTest) {
    -    this.innerFrameResponseReceived_.addCallback(
    -        goog.bind(this.testReconnects_, this,
    -            outerFrameReconnectSupported, innerFrameMigrationSupported));
    -  } else {
    -    this.innerFrameResponseReceived_.addCallback(
    -        goog.bind(asyncTestCase.continueTesting, asyncTestCase));
    -  }
    -
    -  this.continueConnect_(reverse);
    -};
    -
    -
    -Driver.prototype.continueConnect_ = function(reverse) {
    -  // Wait until the peer is fully established.  Establishment is sometimes very
    -  // slow indeed, especially on virtual machines, so a fixed timeout is not
    -  // suitable.  This wait is required because we want to take precise control
    -  // of the channel startup timing, and shouldn't be needed in production use,
    -  // where the inner frame's channel is typically not started by a DOM call as
    -  // it is here.
    -  if (!this.getInnerPeer_() || !this.getInnerPeer_().instantiateChannel) {
    -    window.setTimeout(goog.bind(this.continueConnect_, this, reverse), 100);
    -    return;
    -  }
    -
    -  var connectFromOuterFrame = goog.bind(this.channel_.connect, this.channel_,
    -      goog.bind(this.outerFrameConnected_, this));
    -  var innerConfig = this.innerFrameCfg_;
    -  var connectFromInnerFrame = goog.bind(this.getInnerPeer_().instantiateChannel,
    -      this.getInnerPeer_(), innerConfig);
    -
    -  // Take control of the timing and reverse of each frame's first SETUP call. If
    -  // these happen to fire right on top of each other, that tends to mask
    -  // problems that reliably occur when there is a short delay.
    -  window.setTimeout(connectFromOuterFrame, reverse ? 1 : 10);
    -  window.setTimeout(connectFromInnerFrame, reverse ? 10 : 1);
    -};
    -
    -
    -/**
    - * Called by the outer frame connection callback.
    - * @private
    - */
    -Driver.prototype.outerFrameConnected_ = function() {
    -  var payload = this.outerFrameEchoPayload_ =
    -      goog.net.xpc.getRandomString(10);
    -  this.channel_.send('echo', payload);
    -};
    -
    -
    -/**
    - * Called by the inner frame connection callback.
    - */
    -Driver.prototype.innerFrameConnected = function() {
    -  var payload = this.innerFrameEchoPayload_ =
    -      goog.net.xpc.getRandomString(10);
    -  this.getInnerPeer_().sendEcho(payload);
    -};
    -
    -
    -/**
    - * The handler function for incoming echo requests.
    - * @param {string} payload The message payload.
    - * @private
    - */
    -Driver.prototype.echoHandler_ = function(payload) {
    -  assertTrue('outer frame should be connected', this.channel_.isConnected());
    -  var peer = this.getInnerPeer_();
    -  assertTrue('child should be connected', peer.isConnected());
    -  this.channel_.send('response', payload);
    -};
    -
    -
    -/**
    - * The handler function for incoming echo responses.
    - * @param {string} payload The message payload.
    - * @private
    - */
    -Driver.prototype.responseHandler_ = function(payload) {
    -  assertTrue('outer frame should be connected', this.channel_.isConnected());
    -  var peer = this.getInnerPeer_();
    -  assertTrue('child should be connected', peer.isConnected());
    -  assertEquals(this.outerFrameEchoPayload_, payload);
    -  this.outerFrameResponseReceived_.callback(true);
    -};
    -
    -
    -/**
    - * The handler function for incoming echo replies.
    - * @param {string} payload The message payload.
    - */
    -Driver.prototype.innerFrameGotResponse = function(payload) {
    -  assertTrue('outer frame should be connected', this.channel_.isConnected());
    -  var peer = this.getInnerPeer_();
    -  assertTrue('child should be connected', peer.isConnected());
    -  assertEquals(this.innerFrameEchoPayload_, payload);
    -  this.innerFrameResponseReceived_.callback(true);
    -};
    -
    -
    -/**
    - * The second phase of the standard test, where reconnections of both the inner
    - * and outer frames are performed.
    - * @param {boolean} outerFrameReconnectSupported Whether outer frame reconnects
    - *     are supported, and should be tested.
    - * @private
    - */
    -Driver.prototype.testReconnects_ = function(outerFrameReconnectSupported,
    -    innerFrameMigrationSupported) {
    -  G_testRunner.log('Performing inner frame reconnect');
    -  this.reinitializeDeferreds_();
    -  this.innerFrameResponseReceived_.addCallback(
    -      goog.bind(this.checkChannelNames_, this));
    -
    -  if (outerFrameReconnectSupported) {
    -    this.innerFrameResponseReceived_.addCallback(
    -        goog.bind(this.performOuterFrameReconnect_, this,
    -            innerFrameMigrationSupported));
    -  } else if (innerFrameMigrationSupported) {
    -    this.innerFrameResponseReceived_.addCallback(
    -        goog.bind(this.migrateInnerFrame_, this));
    -  } else {
    -    this.innerFrameResponseReceived_.addCallback(
    -        goog.bind(asyncTestCase.continueTesting, asyncTestCase));
    -  }
    -
    -  this.performInnerFrameReconnect_();
    -};
    -
    -
    -/**
    - * Initializes the deferreds and clears the echo payloads, ready for another
    - * sub-test.
    - * @private
    - */
    -Driver.prototype.reinitializeDeferreds_ = function() {
    -  this.innerFrameEchoPayload_ = null;
    -  this.outerFrameEchoPayload_ = null;
    -  this.innerFrameResponseReceived_.cancel();
    -  this.innerFrameResponseReceived_ = new goog.async.Deferred();
    -  this.outerFrameResponseReceived_.cancel();
    -  this.outerFrameResponseReceived_ = new goog.async.Deferred();
    -};
    -
    -
    -/**
    - * Get the inner frame to reconnect, and repeat the echo test.
    - * @private
    - */
    -Driver.prototype.performInnerFrameReconnect_ = function() {
    -  var peer = this.getInnerPeer_();
    -  peer.instantiateChannel(this.innerFrameCfg_);
    -};
    -
    -
    -/**
    - * Get the outer frame to reconnect, and repeat the echo test.
    - * @private
    - */
    -Driver.prototype.performOuterFrameReconnect_ = function(
    -    innerFrameMigrationSupported) {
    -  G_testRunner.log('Closing channel');
    -  this.channel_.close();
    -
    -  // If there is another channel still open, the native transport's global
    -  // postMessage listener will still be active.  This will mean that messages
    -  // being sent to the now-closed channel will still be received and delivered,
    -  // such as transport service traffic from its previous correspondent in the
    -  // other frame.  Ensure these messages don't cause exceptions.
    -  try {
    -    this.channel_.xpcDeliver(goog.net.xpc.TRANSPORT_SERVICE_, 'payload');
    -  } catch (e) {
    -    fail('Should not throw exception');
    -  }
    -
    -  G_testRunner.log('Reconnecting outer frame');
    -  this.reinitializeDeferreds_();
    -  this.innerFrameResponseReceived_.addCallback(
    -      goog.bind(this.checkChannelNames_, this));
    -  if (innerFrameMigrationSupported) {
    -    this.outerFrameResponseReceived_.addCallback(
    -        goog.bind(this.migrateInnerFrame_, this));
    -  } else {
    -    this.outerFrameResponseReceived_.addCallback(
    -        goog.bind(asyncTestCase.continueTesting, asyncTestCase));
    -  }
    -  this.channel_.connect(goog.bind(this.outerFrameConnected_, this));
    -};
    -
    -
    -/**
    - * Migrate the inner frame to the alternate protocol version and reconnect it.
    - * @private
    - */
    -Driver.prototype.migrateInnerFrame_ = function() {
    -  G_testRunner.log('Migrating inner frame');
    -  this.reinitializeDeferreds_();
    -  var innerFrameProtoVersion = this.innerFrameCfg_[
    -      goog.net.xpc.CfgFields.NATIVE_TRANSPORT_PROTOCOL_VERSION];
    -  this.innerFrameResponseReceived_.addCallback(
    -      goog.bind(this.checkChannelNames_, this));
    -  this.innerFrameResponseReceived_.addCallback(
    -      goog.bind(asyncTestCase.continueTesting, asyncTestCase));
    -  this.innerFrameCfg_[
    -      goog.net.xpc.CfgFields.NATIVE_TRANSPORT_PROTOCOL_VERSION] =
    -      innerFrameProtoVersion == 1 ? 2 : 1;
    -  this.performInnerFrameReconnect_();
    -};
    -
    -
    -/**
    - * Determines if the transport type for the channel is testable.
    - * Some transports are misusing global state or making other
    - * assumptions that cause connections to fail.
    - * @return {boolean} Whether the transport is testable.
    - * @private
    - */
    -Driver.prototype.isTransportTestable_ = function() {
    -  var testable = false;
    -
    -  var transportType = this.channel_.determineTransportType_();
    -  switch (transportType) {
    -    case goog.net.xpc.TransportTypes.IFRAME_RELAY:
    -    case goog.net.xpc.TransportTypes.IFRAME_POLLING:
    -      testable = canAccessSameDomainIframe;
    -      break;
    -    case goog.net.xpc.TransportTypes.NATIVE_MESSAGING:
    -    case goog.net.xpc.TransportTypes.FLASH:
    -    case goog.net.xpc.TransportTypes.DIRECT:
    -    case goog.net.xpc.TransportTypes.NIX:
    -      testable = true;
    -      break;
    -  }
    -
    -  return testable;
    -};
    -
    -
    -/**
    - * Connect the outer channel but not the inner one.  Wait a short time, then
    - * dispose the outer channel and make sure it was torn down properly.
    - */
    -Driver.prototype.connectOuterAndDispose = function() {
    -  this.channel_.connect();
    -  window.setTimeout(goog.bind(this.disposeAndCheck_, this), 2000);
    -};
    -
    -
    -/**
    - * Dispose the cross-page channel. Check that the transport was also
    - * disposed, and allow to run briefly to make sure no timers which will cause
    - * failures are still running.
    - * @private
    - */
    -Driver.prototype.disposeAndCheck_ = function() {
    -  assertFalse(this.channel_.isConnected());
    -  var transport = this.channel_.transport_;
    -  this.channel_.dispose();
    -  assertNull(this.channel_.transport_);
    -  assertTrue(this.channel_.isDisposed());
    -  assertTrue(transport.isDisposed());
    -
    -  // Let any errors caused by erroneous retries happen.
    -  window.setTimeout(goog.bind(asyncTestCase.continueTesting, asyncTestCase),
    -      2000);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xpc/crosspagechannelrole.js b/src/database/third_party/closure-library/closure/goog/net/xpc/crosspagechannelrole.js
    deleted file mode 100644
    index 0d31fe94056..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xpc/crosspagechannelrole.js
    +++ /dev/null
    @@ -1,30 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides the enum for the role of the CrossPageChannel.
    - *
    - */
    -
    -goog.provide('goog.net.xpc.CrossPageChannelRole');
    -
    -
    -/**
    - * The role of the peer.
    - * @enum {number}
    - */
    -goog.net.xpc.CrossPageChannelRole = {
    -  OUTER: 0,
    -  INNER: 1
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xpc/directtransport.js b/src/database/third_party/closure-library/closure/goog/net/xpc/directtransport.js
    deleted file mode 100644
    index cd504d0b118..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xpc/directtransport.js
    +++ /dev/null
    @@ -1,635 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides an implementation of a transport that can call methods
    - * directly on a frame. Useful if you want to use XPC for crossdomain messaging
    - * (using another transport), or same domain messaging (using this transport).
    - */
    -
    -
    -goog.provide('goog.net.xpc.DirectTransport');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.async.Deferred');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.log');
    -goog.require('goog.net.xpc');
    -goog.require('goog.net.xpc.CfgFields');
    -goog.require('goog.net.xpc.CrossPageChannelRole');
    -goog.require('goog.net.xpc.Transport');
    -goog.require('goog.net.xpc.TransportTypes');
    -goog.require('goog.object');
    -
    -
    -goog.scope(function() {
    -var CfgFields = goog.net.xpc.CfgFields;
    -var CrossPageChannelRole = goog.net.xpc.CrossPageChannelRole;
    -var Deferred = goog.async.Deferred;
    -var EventHandler = goog.events.EventHandler;
    -var Timer = goog.Timer;
    -var Transport = goog.net.xpc.Transport;
    -
    -
    -
    -/**
    - * A direct window to window method transport.
    - *
    - * If the windows are in the same security context, this transport calls
    - * directly into the other window without using any additional mechanism. This
    - * is mainly used in scenarios where you want to optionally use a cross domain
    - * transport in cross security context situations, or optionally use a direct
    - * transport in same security context situations.
    - *
    - * Note: Global properties are exported by using this transport. One to
    - * communicate with the other window by, currently crosswindowmessaging.channel,
    - * and by using goog.getUid on window, currently closure_uid_[0-9]+.
    - *
    - * @param {!goog.net.xpc.CrossPageChannel} channel The channel this
    - *     transport belongs to.
    - * @param {goog.dom.DomHelper=} opt_domHelper The dom helper to use for
    - *     finding the correct window/document. If omitted, uses the current
    - *     document.
    - * @constructor
    - * @extends {Transport}
    - */
    -goog.net.xpc.DirectTransport = function(channel, opt_domHelper) {
    -  goog.net.xpc.DirectTransport.base(this, 'constructor', opt_domHelper);
    -
    -  /**
    -   * The channel this transport belongs to.
    -   * @private {!goog.net.xpc.CrossPageChannel}
    -   */
    -  this.channel_ = channel;
    -
    -  /** @private {!EventHandler<!goog.net.xpc.DirectTransport>} */
    -  this.eventHandler_ = new EventHandler(this);
    -  this.registerDisposable(this.eventHandler_);
    -
    -  /**
    -   * Timer for connection reattempts.
    -   * @private {!Timer}
    -   */
    -  this.maybeAttemptToConnectTimer_ = new Timer(
    -      DirectTransport.CONNECTION_ATTEMPT_INTERVAL_MS_,
    -      this.getWindow());
    -  this.registerDisposable(this.maybeAttemptToConnectTimer_);
    -
    -  /**
    -   * Fires once we've received our SETUP_ACK message.
    -   * @private {!Deferred}
    -   */
    -  this.setupAckReceived_ = new Deferred();
    -
    -  /**
    -   * Fires once we've sent our SETUP_ACK message.
    -   * @private {!Deferred}
    -   */
    -  this.setupAckSent_ = new Deferred();
    -
    -  /**
    -   * Fires once we're marked connected.
    -   * @private {!Deferred}
    -   */
    -  this.connected_ = new Deferred();
    -
    -  /**
    -   * The unique ID of this side of the connection. Used to determine when a peer
    -   * is reloaded.
    -   * @private {string}
    -   */
    -  this.endpointId_ = goog.net.xpc.getRandomString(10);
    -
    -  /**
    -   * The unique ID of the peer. If we get a message from a peer with an ID we
    -   * don't expect, we reset the connection.
    -   * @private {?string}
    -   */
    -  this.peerEndpointId_ = null;
    -
    -  /**
    -   * The map of sending messages.
    -   * @private {Object}
    -   */
    -  this.asyncSendsMap_ = {};
    -
    -  /**
    -   * The original channel name.
    -   * @private {string}
    -   */
    -  this.originalChannelName_ = this.channel_.name;
    -
    -  // We reconfigure the channel name to include the role so that we can
    -  // communicate in the same window between the different roles on the
    -  // same channel.
    -  this.channel_.updateChannelNameAndCatalog(
    -      DirectTransport.getRoledChannelName_(this.channel_.name,
    -                                           this.channel_.getRole()));
    -
    -  /**
    -   * Flag indicating if this instance of the transport has been initialized.
    -   * @private {boolean}
    -   */
    -  this.initialized_ = false;
    -
    -  // We don't want to mark ourselves connected until we have sent whatever
    -  // message will cause our counterpart in the other frame to also declare
    -  // itself connected, if there is such a message.  Otherwise we risk a user
    -  // message being sent in advance of that message, and it being discarded.
    -
    -  // Two sided handshake:
    -  // SETUP_ACK has to have been received, and sent.
    -  this.connected_.awaitDeferred(this.setupAckReceived_);
    -  this.connected_.awaitDeferred(this.setupAckSent_);
    -
    -  this.connected_.addCallback(this.notifyConnected_, this);
    -  this.connected_.callback(true);
    -
    -  this.eventHandler_.
    -      listen(this.maybeAttemptToConnectTimer_, Timer.TICK,
    -          this.maybeAttemptToConnect_);
    -
    -  goog.log.info(
    -      goog.net.xpc.logger,
    -      'DirectTransport created. role=' + this.channel_.getRole());
    -};
    -goog.inherits(goog.net.xpc.DirectTransport, Transport);
    -var DirectTransport = goog.net.xpc.DirectTransport;
    -
    -
    -/**
    - * @private {number}
    - * @const
    - */
    -DirectTransport.CONNECTION_ATTEMPT_INTERVAL_MS_ = 100;
    -
    -
    -/**
    - * The delay to notify the xpc of a successful connection. This is used
    - * to allow both parties to be connected if one party's connection callback
    - * invokes an immediate send.
    - * @private {number}
    - * @const
    - */
    -DirectTransport.CONNECTION_DELAY_INTERVAL_MS_ = 0;
    -
    -
    -/**
    - * @param {!Window} peerWindow The peer window to check if DirectTranport is
    - *     supported on.
    - * @return {boolean} Whether this transport is supported.
    - */
    -DirectTransport.isSupported = function(peerWindow) {
    -  /** @preserveTry */
    -  try {
    -    return window.document.domain == peerWindow.document.domain;
    -  } catch (e) {
    -    return false;
    -  }
    -};
    -
    -
    -/**
    - * Tracks the number of DirectTransport channels that have been
    - * initialized but not disposed yet in a map keyed by the UID of the window
    - * object.  This allows for multiple windows to be initiallized and listening
    - * for messages.
    - * @private {!Object<number>}
    - */
    -DirectTransport.activeCount_ = {};
    -
    -
    -/**
    - * Path of global message proxy.
    - * @private {string}
    - * @const
    - */
    -// TODO(user): Make this configurable using the CfgFields.
    -DirectTransport.GLOBAL_TRANPORT_PATH_ = 'crosswindowmessaging.channel';
    -
    -
    -/**
    - * The delimiter used for transport service messages.
    - * @private {string}
    - * @const
    - */
    -DirectTransport.MESSAGE_DELIMITER_ = ',';
    -
    -
    -/**
    - * Initializes this transport. Registers a method for 'message'-events in the
    - * global scope.
    - * @param {!Window} listenWindow The window to listen to events on.
    - * @private
    - */
    -DirectTransport.initialize_ = function(listenWindow) {
    -  var uid = goog.getUid(listenWindow);
    -  var value = DirectTransport.activeCount_[uid] || 0;
    -  if (value == 0) {
    -    // Set up a handler on the window to proxy messages to class.
    -    var globalProxy = goog.getObjectByName(
    -        DirectTransport.GLOBAL_TRANPORT_PATH_,
    -        listenWindow);
    -    if (globalProxy == null) {
    -      goog.exportSymbol(
    -          DirectTransport.GLOBAL_TRANPORT_PATH_,
    -          DirectTransport.messageReceivedHandler_,
    -          listenWindow);
    -    }
    -  }
    -  DirectTransport.activeCount_[uid]++;
    -};
    -
    -
    -/**
    - * @param {string} channelName The channel name.
    - * @param {string|number} role The role.
    - * @return {string} The formatted channel name including role.
    - * @private
    - */
    -DirectTransport.getRoledChannelName_ = function(channelName, role) {
    -  return channelName + '_' + role;
    -};
    -
    -
    -/**
    - * @param {!Object} literal The literal unrenamed message.
    - * @return {boolean} Whether the message was successfully delivered to a
    - *     channel.
    - * @private
    - */
    -DirectTransport.messageReceivedHandler_ = function(literal) {
    -  var msg = DirectTransport.Message_.fromLiteral(literal);
    -
    -  var channelName = msg.channelName;
    -  var service = msg.service;
    -  var payload = msg.payload;
    -
    -  goog.log.fine(goog.net.xpc.logger,
    -      'messageReceived: channel=' + channelName +
    -      ', service=' + service + ', payload=' + payload);
    -
    -  // Attempt to deliver message to the channel. Keep in mind that it may not
    -  // exist for several reasons, including but not limited to:
    -  //  - a malformed message
    -  //  - the channel simply has not been created
    -  //  - channel was created in a different namespace
    -  //  - message was sent to the wrong window
    -  //  - channel has become stale (e.g. caching iframes and back clicks)
    -  var channel = goog.net.xpc.channels[channelName];
    -  if (channel) {
    -    channel.xpcDeliver(service, payload);
    -    return true;
    -  }
    -
    -  var transportMessageType = DirectTransport.parseTransportPayload_(payload)[0];
    -
    -  // Check if there are any stale channel names that can be updated.
    -  for (var staleChannelName in goog.net.xpc.channels) {
    -    var staleChannel = goog.net.xpc.channels[staleChannelName];
    -    if (staleChannel.getRole() == CrossPageChannelRole.INNER &&
    -        !staleChannel.isConnected() &&
    -        service == goog.net.xpc.TRANSPORT_SERVICE_ &&
    -        transportMessageType == goog.net.xpc.SETUP) {
    -      // Inner peer received SETUP message but channel names did not match.
    -      // Start using the channel name sent from outer peer. The channel name
    -      // of the inner peer can easily become out of date, as iframe's and their
    -      // JS state get cached in many browsers upon page reload or history
    -      // navigation (particularly Firefox 1.5+).
    -      staleChannel.updateChannelNameAndCatalog(channelName);
    -      staleChannel.xpcDeliver(service, payload);
    -      return true;
    -    }
    -  }
    -
    -  // Failed to find a channel to deliver this message to, so simply ignore it.
    -  goog.log.info(goog.net.xpc.logger, 'channel name mismatch; message ignored.');
    -  return false;
    -};
    -
    -
    -/**
    - * The transport type.
    - * @type {number}
    - * @override
    - */
    -DirectTransport.prototype.transportType = goog.net.xpc.TransportTypes.DIRECT;
    -
    -
    -/**
    - * Handles transport service messages.
    - * @param {string} payload The message content.
    - * @override
    - */
    -DirectTransport.prototype.transportServiceHandler = function(payload) {
    -  var transportParts = DirectTransport.parseTransportPayload_(payload);
    -  var transportMessageType = transportParts[0];
    -  var peerEndpointId = transportParts[1];
    -  switch (transportMessageType) {
    -    case goog.net.xpc.SETUP_ACK_:
    -      if (!this.setupAckReceived_.hasFired()) {
    -        this.setupAckReceived_.callback(true);
    -      }
    -      break;
    -    case goog.net.xpc.SETUP:
    -      this.sendSetupAckMessage_();
    -      if ((this.peerEndpointId_ != null) &&
    -          (this.peerEndpointId_ != peerEndpointId)) {
    -        // Send a new SETUP message since the peer has been replaced.
    -        goog.log.info(goog.net.xpc.logger,
    -            'Sending SETUP and changing peer ID to: ' + peerEndpointId);
    -        this.sendSetupMessage_();
    -      }
    -      this.peerEndpointId_ = peerEndpointId;
    -      break;
    -  }
    -};
    -
    -
    -/**
    - * Sends a SETUP transport service message.
    - * @private
    - */
    -DirectTransport.prototype.sendSetupMessage_ = function() {
    -  // Although we could send real objects, since some other transports are
    -  // limited to strings we also keep this requirement.
    -  var payload = goog.net.xpc.SETUP;
    -  payload += DirectTransport.MESSAGE_DELIMITER_;
    -  payload += this.endpointId_;
    -  this.send(goog.net.xpc.TRANSPORT_SERVICE_, payload);
    -};
    -
    -
    -/**
    - * Sends a SETUP_ACK transport service message.
    - * @private
    - */
    -DirectTransport.prototype.sendSetupAckMessage_ = function() {
    -  this.send(goog.net.xpc.TRANSPORT_SERVICE_, goog.net.xpc.SETUP_ACK_);
    -  if (!this.setupAckSent_.hasFired()) {
    -    this.setupAckSent_.callback(true);
    -  }
    -};
    -
    -
    -/** @override */
    -DirectTransport.prototype.connect = function() {
    -  var win = this.getWindow();
    -  if (win) {
    -    DirectTransport.initialize_(win);
    -    this.initialized_ = true;
    -    this.maybeAttemptToConnect_();
    -  } else {
    -    goog.log.fine(goog.net.xpc.logger, 'connect(): no window to initialize.');
    -  }
    -};
    -
    -
    -/**
    - * Connects to other peer. In the case of the outer peer, the setup messages are
    - * likely sent before the inner peer is ready to receive them. Therefore, this
    - * function will continue trying to send the SETUP message until the inner peer
    - * responds. In the case of the inner peer, it will occasionally have its
    - * channel name fall out of sync with the outer peer, particularly during
    - * soft-reloads and history navigations.
    - * @private
    - */
    -DirectTransport.prototype.maybeAttemptToConnect_ = function() {
    -  var outerRole = this.channel_.getRole() == CrossPageChannelRole.OUTER;
    -  if (this.channel_.isConnected()) {
    -    this.maybeAttemptToConnectTimer_.stop();
    -    return;
    -  }
    -  this.maybeAttemptToConnectTimer_.start();
    -  this.sendSetupMessage_();
    -};
    -
    -
    -/**
    - * Prepares to send a message.
    - * @param {string} service The name of the service the message is to be
    - *     delivered to.
    - * @param {string} payload The message content.
    - * @override
    - */
    -DirectTransport.prototype.send = function(service, payload) {
    -  if (!this.channel_.getPeerWindowObject()) {
    -    goog.log.fine(goog.net.xpc.logger, 'send(): window not ready');
    -    return;
    -  }
    -  var channelName = DirectTransport.getRoledChannelName_(
    -      this.originalChannelName_,
    -      this.getPeerRole_());
    -
    -  var message = new DirectTransport.Message_(
    -      channelName,
    -      service,
    -      payload);
    -
    -  if (this.channel_.getConfig()[CfgFields.DIRECT_TRANSPORT_SYNC_MODE]) {
    -    this.executeScheduledSend_(message);
    -  } else {
    -    // Note: goog.async.nextTick doesn't support cancelling or disposal so
    -    // leaving as 0ms timer, though this may have performance implications.
    -    this.asyncSendsMap_[goog.getUid(message)] =
    -        Timer.callOnce(goog.bind(this.executeScheduledSend_, this, message), 0);
    -  }
    -};
    -
    -
    -/**
    - * Sends the message.
    - * @param {!DirectTransport.Message_} message The message to send.
    - * @private
    - */
    -DirectTransport.prototype.executeScheduledSend_ = function(message) {
    -  var messageId = goog.getUid(message);
    -  if (this.asyncSendsMap_[messageId]) {
    -    delete this.asyncSendsMap_[messageId];
    -  }
    -
    -  /** @preserveTry */
    -  try {
    -    var peerProxy = goog.getObjectByName(
    -        DirectTransport.GLOBAL_TRANPORT_PATH_,
    -        this.channel_.getPeerWindowObject());
    -  } catch (error) {
    -    goog.log.warning(
    -        goog.net.xpc.logger,
    -        'Can\'t access other window, ignoring.',
    -        error);
    -    return;
    -  }
    -
    -  if (goog.isNull(peerProxy)) {
    -    goog.log.warning(
    -        goog.net.xpc.logger,
    -        'Peer window had no global function.');
    -    return;
    -  }
    -
    -  /** @preserveTry */
    -  try {
    -    peerProxy(message.toLiteral());
    -    goog.log.info(
    -        goog.net.xpc.logger,
    -        'send(): channelName=' + message.channelName +
    -        ' service=' + message.service +
    -        ' payload=' + message.payload);
    -  } catch (error) {
    -    goog.log.warning(
    -        goog.net.xpc.logger,
    -        'Error performing call, ignoring.',
    -        error);
    -  }
    -};
    -
    -
    -/**
    - * @return {goog.net.xpc.CrossPageChannelRole} The role of peer channel (either
    - *     inner or outer).
    - * @private
    - */
    -DirectTransport.prototype.getPeerRole_ = function() {
    -  var role = this.channel_.getRole();
    -  return role == goog.net.xpc.CrossPageChannelRole.OUTER ?
    -      goog.net.xpc.CrossPageChannelRole.INNER :
    -      goog.net.xpc.CrossPageChannelRole.OUTER;
    -};
    -
    -
    -/**
    - * Notifies the channel that this transport is connected.
    - * @private
    - */
    -DirectTransport.prototype.notifyConnected_ = function() {
    -  // Add a delay as the connection callback will break if this transport is
    -  // synchronous and the callback invokes send() immediately.
    -  this.channel_.notifyConnected(
    -      this.channel_.getConfig()[CfgFields.DIRECT_TRANSPORT_SYNC_MODE] ?
    -      DirectTransport.CONNECTION_DELAY_INTERVAL_MS_ : 0);
    -};
    -
    -
    -/** @override */
    -DirectTransport.prototype.disposeInternal = function() {
    -  if (this.initialized_) {
    -    var listenWindow = this.getWindow();
    -    var uid = goog.getUid(listenWindow);
    -    var value = --DirectTransport.activeCount_[uid];
    -    if (value == 1) {
    -      goog.exportSymbol(
    -          DirectTransport.GLOBAL_TRANPORT_PATH_,
    -          null,
    -          listenWindow);
    -    }
    -  }
    -
    -  if (this.asyncSendsMap_) {
    -    goog.object.forEach(this.asyncSendsMap_, function(timerId) {
    -      Timer.clear(timerId);
    -    });
    -    this.asyncSendsMap_ = null;
    -  }
    -
    -  // Deferred's aren't disposables.
    -  if (this.setupAckReceived_) {
    -    this.setupAckReceived_.cancel();
    -    delete this.setupAckReceived_;
    -  }
    -  if (this.setupAckSent_) {
    -    this.setupAckSent_.cancel();
    -    delete this.setupAckSent_;
    -  }
    -  if (this.connected_) {
    -    this.connected_.cancel();
    -    delete this.connected_;
    -  }
    -
    -  DirectTransport.base(this, 'disposeInternal');
    -};
    -
    -
    -/**
    - * Parses a transport service payload message.
    - * @param {string} payload The payload.
    - * @return {!Array<?string>} An array with the message type as the first member
    - *     and the endpoint id as the second, if one was sent, or null otherwise.
    - * @private
    - */
    -DirectTransport.parseTransportPayload_ = function(payload) {
    -  var transportParts = /** @type {!Array<?string>} */ (payload.split(
    -      DirectTransport.MESSAGE_DELIMITER_));
    -  transportParts[1] = transportParts[1] || null; // Usually endpointId.
    -  return transportParts;
    -};
    -
    -
    -
    -/**
    - * Message container that gets passed back and forth between windows.
    - * @param {string} channelName The channel name to tranport messages on.
    - * @param {string} service The service to send the payload to.
    - * @param {string} payload The payload to send.
    - * @constructor
    - * @struct
    - * @private
    - */
    -DirectTransport.Message_ = function(channelName, service, payload) {
    -  /**
    -   * The name of the channel.
    -   * @type {string}
    -   */
    -  this.channelName = channelName;
    -
    -  /**
    -   * The service on the channel.
    -   * @type {string}
    -   */
    -  this.service = service;
    -
    -  /**
    -   * The payload.
    -   * @type {string}
    -   */
    -  this.payload = payload;
    -};
    -
    -
    -/**
    - * Converts a message to a literal object.
    - * @return {!Object} The message as a literal object.
    - */
    -DirectTransport.Message_.prototype.toLiteral = function() {
    -  return {
    -    'channelName': this.channelName,
    -    'service': this.service,
    -    'payload': this.payload
    -  };
    -};
    -
    -
    -/**
    - * Creates a Message_ from a literal object.
    - * @param {!Object} literal The literal to convert to Message.
    - * @return {!DirectTransport.Message_} The Message.
    - */
    -DirectTransport.Message_.fromLiteral = function(literal) {
    -  return new DirectTransport.Message_(
    -      literal['channelName'],
    -      literal['service'],
    -      literal['payload']);
    -};
    -
    -});  // goog.scope
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xpc/directtransport_test.js b/src/database/third_party/closure-library/closure/goog/net/xpc/directtransport_test.js
    deleted file mode 100644
    index bf969e75986..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xpc/directtransport_test.js
    +++ /dev/null
    @@ -1,290 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Tests the direct transport.
    - */
    -
    -goog.provide('goog.net.xpc.DirectTransportTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.labs.userAgent.browser');
    -goog.require('goog.log');
    -goog.require('goog.log.Level');
    -goog.require('goog.net.xpc');
    -goog.require('goog.net.xpc.CfgFields');
    -goog.require('goog.net.xpc.CrossPageChannel');
    -goog.require('goog.net.xpc.CrossPageChannelRole');
    -goog.require('goog.net.xpc.TransportTypes');
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.jsunit');
    -goog.setTestOnly('goog.net.xpc.DirectTransportTest');
    -
    -var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall(
    -    'Direct transport tests.');
    -
    -
    -/**
    - * Echo service name.
    - * @type {string}
    - * @const
    - */
    -var ECHO_SERVICE_NAME = 'echo';
    -
    -
    -/**
    - * Response service name.
    - * @type {string}
    - * @const
    - */
    -var RESPONSE_SERVICE_NAME = 'response';
    -
    -
    -/**
    - * Test Payload.
    - * @type {string}
    - * @const
    - */
    -var MESSAGE_PAYLOAD_1 = 'This is message payload 1.';
    -
    -
    -/**
    - * The name id of the peer iframe.
    - * @type {string}
    - * @const
    - */
    -var PEER_IFRAME_ID = 'peer-iframe';
    -
    -
    -// Class aliases.
    -var CfgFields;
    -var CrossPageChannel;
    -var CrossPageChannelRole;
    -var TransportTypes;
    -
    -var outerXpc;
    -var innerXpc;
    -var peerIframe;
    -var channelName;
    -var messageIsSync = false;
    -
    -function setUpPage() {
    -  CfgFields = goog.net.xpc.CfgFields;
    -  CrossPageChannel = goog.net.xpc.CrossPageChannel;
    -  CrossPageChannelRole = goog.net.xpc.CrossPageChannelRole;
    -  TransportTypes = goog.net.xpc.TransportTypes;
    -
    -  // Show debug log
    -  var debugDiv = document.createElement('debugDiv');
    -  document.body.appendChild(debugDiv);
    -  var logger = goog.log.getLogger('goog.net.xpc');
    -  logger.setLevel(goog.log.Level.ALL);
    -  goog.log.addHandler(logger, function(logRecord) {
    -    var msgElm = goog.dom.createDom('div');
    -    msgElm.innerHTML = logRecord.getMessage();
    -    goog.dom.appendChild(debugDiv, msgElm);
    -  });
    -}
    -
    -
    -function tearDown() {
    -  if (peerIframe) {
    -    document.body.removeChild(peerIframe);
    -    peerIframe = null;
    -  }
    -  if (outerXpc) {
    -    outerXpc.dispose();
    -    outerXpc = null;
    -  }
    -  if (innerXpc) {
    -    innerXpc.dispose();
    -    innerXpc = null;
    -  }
    -  window.iframeLoadHandler = null;
    -  channelName = null;
    -  messageIsSync = false;
    -}
    -
    -
    -function createIframe() {
    -  peerIframe = document.createElement('iframe');
    -  peerIframe.id = PEER_IFRAME_ID;
    -  document.body.insertBefore(peerIframe, document.body.firstChild);
    -}
    -
    -
    -/**
    - * Tests 2 same domain frames using direct transport.
    - */
    -function testDirectTransport() {
    -  // This test has been flaky on IE 8-11 on Win7.
    -  // For now, disable.
    -  // Flakiness is tracked in http://b/18595666
    -  if (goog.labs.userAgent.browser.isIE()) {
    -    return;
    -  }
    -
    -  createIframe();
    -  channelName = goog.net.xpc.getRandomString(10);
    -  outerXpc = new CrossPageChannel(
    -      getConfiguration(CrossPageChannelRole.OUTER, PEER_IFRAME_ID));
    -  // Outgoing service.
    -  outerXpc.registerService(ECHO_SERVICE_NAME, goog.nullFunction);
    -  // Incoming service.
    -  outerXpc.registerService(
    -      RESPONSE_SERVICE_NAME,
    -      responseMessageHandler_testDirectTransport);
    -  asyncTestCase.waitForAsync('Waiting for xpc connect.');
    -  outerXpc.connect(onConnect_testDirectTransport);
    -  // inner_peer.html calls this method at end of html.
    -  window.iframeLoadHandler = onIframeLoaded_testDirectTransport;
    -  peerIframe.src = 'testdata/inner_peer.html';
    -}
    -
    -
    -function onIframeLoaded_testDirectTransport() {
    -  peerIframe.contentWindow.instantiateChannel(
    -      getConfiguration(CrossPageChannelRole.INNER));
    -}
    -
    -
    -function onConnect_testDirectTransport() {
    -  assertTrue('XPC over direct channel is connected', outerXpc.isConnected());
    -  outerXpc.send(ECHO_SERVICE_NAME, MESSAGE_PAYLOAD_1);
    -}
    -
    -
    -function responseMessageHandler_testDirectTransport(message) {
    -  assertEquals(
    -      'Received payload is equal to sent payload.',
    -      message,
    -      MESSAGE_PAYLOAD_1);
    -  asyncTestCase.continueTesting();
    -}
    -
    -
    -/**
    - * Tests 2 xpc's communicating with each other in the same window.
    - */
    -function testSameWindowDirectTransport() {
    -  channelName = goog.net.xpc.getRandomString(10);
    -
    -  outerXpc = new CrossPageChannel(getConfiguration(CrossPageChannelRole.OUTER));
    -  outerXpc.setPeerWindowObject(self);
    -
    -  // Outgoing service.
    -  outerXpc.registerService(ECHO_SERVICE_NAME, goog.nullFunction);
    -  // Incoming service.
    -  outerXpc.registerService(
    -      RESPONSE_SERVICE_NAME,
    -      outerResponseMessageHandler_testSameWindowDirectTransport);
    -  asyncTestCase.waitForAsync('Waiting for outer xpc connect.');
    -  outerXpc.connect(onOuterConnect_testSameWindowDirectTransport);
    -
    -  innerXpc = new CrossPageChannel(getConfiguration(CrossPageChannelRole.INNER));
    -  innerXpc.setPeerWindowObject(self);
    -  // Incoming service.
    -  innerXpc.registerService(
    -      ECHO_SERVICE_NAME,
    -      innerEchoMessageHandler_testSameWindowDirectTransport);
    -  // Outgoing service.
    -  innerXpc.registerService(
    -      RESPONSE_SERVICE_NAME,
    -      goog.nullFunction);
    -  innerXpc.connect();
    -}
    -
    -
    -function onOuterConnect_testSameWindowDirectTransport() {
    -  assertTrue(
    -      'XPC over direct channel, same window, is connected',
    -      outerXpc.isConnected());
    -  outerXpc.send(ECHO_SERVICE_NAME, MESSAGE_PAYLOAD_1);
    -}
    -
    -
    -function outerResponseMessageHandler_testSameWindowDirectTransport(message) {
    -  assertEquals(
    -      'Received payload is equal to sent payload.',
    -      message,
    -      MESSAGE_PAYLOAD_1);
    -  asyncTestCase.continueTesting();
    -}
    -
    -
    -function innerEchoMessageHandler_testSameWindowDirectTransport(message) {
    -  innerXpc.send(RESPONSE_SERVICE_NAME, message);
    -}
    -
    -
    -function getConfiguration(role, opt_peerFrameId) {
    -  var cfg = {};
    -  cfg[CfgFields.TRANSPORT] = TransportTypes.DIRECT;
    -  if (goog.isDefAndNotNull(opt_peerFrameId)) {
    -    cfg[CfgFields.IFRAME_ID] = opt_peerFrameId;
    -  }
    -  cfg[CfgFields.CHANNEL_NAME] = channelName;
    -  cfg[CfgFields.ROLE] = role;
    -  return cfg;
    -}
    -
    -
    -/**
    - * Tests 2 same domain frames using direct transport using sync mode.
    - */
    -function testSyncMode() {
    -  createIframe();
    -  channelName = goog.net.xpc.getRandomString(10);
    -
    -  var cfg = getConfiguration(CrossPageChannelRole.OUTER, PEER_IFRAME_ID);
    -  cfg[CfgFields.DIRECT_TRANSPORT_SYNC_MODE] = true;
    -
    -  outerXpc = new CrossPageChannel(cfg);
    -  // Outgoing service.
    -  outerXpc.registerService(ECHO_SERVICE_NAME, goog.nullFunction);
    -  // Incoming service.
    -  outerXpc.registerService(
    -      RESPONSE_SERVICE_NAME,
    -      responseMessageHandler_testSyncMode);
    -  asyncTestCase.waitForAsync('Waiting for xpc connect.');
    -  outerXpc.connect(onConnect_testSyncMode);
    -  // inner_peer.html calls this method at end of html.
    -  window.iframeLoadHandler = onIframeLoaded_testSyncMode;
    -  peerIframe.src = 'testdata/inner_peer.html';
    -}
    -
    -
    -function onIframeLoaded_testSyncMode() {
    -  var cfg = getConfiguration(CrossPageChannelRole.INNER);
    -  cfg[CfgFields.DIRECT_TRANSPORT_SYNC_MODE] = true;
    -  peerIframe.contentWindow.instantiateChannel(cfg);
    -}
    -
    -
    -function onConnect_testSyncMode() {
    -  assertTrue('XPC over direct channel is connected', outerXpc.isConnected());
    -  messageIsSync = true;
    -  outerXpc.send(ECHO_SERVICE_NAME, MESSAGE_PAYLOAD_1);
    -  messageIsSync = false;
    -}
    -
    -
    -function responseMessageHandler_testSyncMode(message) {
    -  assertTrue('The message response was syncronous', messageIsSync);
    -  assertEquals(
    -      'Received payload is equal to sent payload.',
    -      message,
    -      MESSAGE_PAYLOAD_1);
    -  asyncTestCase.continueTesting();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xpc/frameelementmethodtransport.js b/src/database/third_party/closure-library/closure/goog/net/xpc/frameelementmethodtransport.js
    deleted file mode 100644
    index 20aed4a4ce2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xpc/frameelementmethodtransport.js
    +++ /dev/null
    @@ -1,270 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Contains the frame element method transport for cross-domain
    - * communication. It exploits the fact that FF lets a page in an
    - * iframe call a method on the iframe-element it is contained in, even if the
    - * containing page is from a different domain.
    - *
    - */
    -
    -
    -goog.provide('goog.net.xpc.FrameElementMethodTransport');
    -
    -goog.require('goog.log');
    -goog.require('goog.net.xpc');
    -goog.require('goog.net.xpc.CrossPageChannelRole');
    -goog.require('goog.net.xpc.Transport');
    -goog.require('goog.net.xpc.TransportTypes');
    -
    -
    -
    -/**
    - * Frame-element method transport.
    - *
    - * Firefox allows a document within an iframe to call methods on the
    - * iframe-element added by the containing document.
    - * NOTE(user): Tested in all FF versions starting from 1.0
    - *
    - * @param {goog.net.xpc.CrossPageChannel} channel The channel this transport
    - *     belongs to.
    - * @param {goog.dom.DomHelper=} opt_domHelper The dom helper to use for finding
    - *     the correct window.
    - * @constructor
    - * @extends {goog.net.xpc.Transport}
    - * @final
    - */
    -goog.net.xpc.FrameElementMethodTransport = function(channel, opt_domHelper) {
    -  goog.net.xpc.FrameElementMethodTransport.base(
    -      this, 'constructor', opt_domHelper);
    -
    -  /**
    -   * The channel this transport belongs to.
    -   * @type {goog.net.xpc.CrossPageChannel}
    -   * @private
    -   */
    -  this.channel_ = channel;
    -
    -  // To transfer messages, this transport basically uses normal function calls,
    -  // which are synchronous. To avoid endless recursion, the delivery has to
    -  // be artificially made asynchronous.
    -
    -  /**
    -   * Array for queued messages.
    -   * @type {Array<{serviceName: string, payload: string}>}
    -   * @private
    -   */
    -  this.queue_ = [];
    -
    -  /**
    -   * Callback function which wraps deliverQueued_.
    -   * @type {Function}
    -   * @private
    -   */
    -  this.deliverQueuedCb_ = goog.bind(this.deliverQueued_, this);
    -};
    -goog.inherits(goog.net.xpc.FrameElementMethodTransport, goog.net.xpc.Transport);
    -
    -
    -/**
    - * The transport type.
    - * @type {number}
    - * @protected
    - * @override
    - */
    -goog.net.xpc.FrameElementMethodTransport.prototype.transportType =
    -    goog.net.xpc.TransportTypes.FRAME_ELEMENT_METHOD;
    -
    -
    -/** @private */
    -goog.net.xpc.FrameElementMethodTransport.prototype.attemptSetupCb_;
    -
    -
    -/** @private */
    -goog.net.xpc.FrameElementMethodTransport.prototype.outgoing_;
    -
    -
    -/** @private */
    -goog.net.xpc.FrameElementMethodTransport.prototype.iframeElm_;
    -
    -
    -/**
    - * Flag used to enforce asynchronous messaging semantics.
    - * @type {boolean}
    - * @private
    - */
    -goog.net.xpc.FrameElementMethodTransport.prototype.recursive_ = false;
    -
    -
    -/**
    - * Timer used to enforce asynchronous message delivery.
    - * @type {number}
    - * @private
    - */
    -goog.net.xpc.FrameElementMethodTransport.prototype.timer_ = 0;
    -
    -
    -/**
    - * Holds the function to send messages to the peer
    - * (once it becomes available).
    - * @type {Function}
    - * @private
    - */
    -goog.net.xpc.FrameElementMethodTransport.outgoing_ = null;
    -
    -
    -/**
    - * Connect this transport.
    - * @override
    - */
    -goog.net.xpc.FrameElementMethodTransport.prototype.connect = function() {
    -  if (this.channel_.getRole() == goog.net.xpc.CrossPageChannelRole.OUTER) {
    -    // get shortcut to iframe-element
    -    this.iframeElm_ = this.channel_.getIframeElement();
    -
    -    // add the gateway function to the iframe-element
    -    // (to be called by the peer)
    -    this.iframeElm_['XPC_toOuter'] = goog.bind(this.incoming_, this);
    -
    -    // at this point we just have to wait for a notification from the peer...
    -
    -  } else {
    -    this.attemptSetup_();
    -  }
    -};
    -
    -
    -/**
    - * Only used from within an iframe. Attempts to attach the method
    - * to be used for sending messages by the containing document. Has to
    - * wait until the containing document has finished. Therefore calls
    - * itself in a timeout if not successful.
    - * @private
    - */
    -goog.net.xpc.FrameElementMethodTransport.prototype.attemptSetup_ = function() {
    -  var retry = true;
    -  /** @preserveTry */
    -  try {
    -    if (!this.iframeElm_) {
    -      // throws security exception when called too early
    -      this.iframeElm_ = this.getWindow().frameElement;
    -    }
    -    // check if iframe-element and the gateway-function to the
    -    // outer-frame are present
    -    // TODO(user) Make sure the following code doesn't throw any exceptions
    -    if (this.iframeElm_ && this.iframeElm_['XPC_toOuter']) {
    -      // get a reference to the gateway function
    -      this.outgoing_ = this.iframeElm_['XPC_toOuter'];
    -      // attach the gateway function the other document will use
    -      this.iframeElm_['XPC_toOuter']['XPC_toInner'] =
    -          goog.bind(this.incoming_, this);
    -      // stop retrying
    -      retry = false;
    -      // notify outer frame
    -      this.send(goog.net.xpc.TRANSPORT_SERVICE_, goog.net.xpc.SETUP_ACK_);
    -      // notify channel that the transport is ready
    -      this.channel_.notifyConnected();
    -    }
    -  }
    -  catch (e) {
    -    goog.log.error(goog.net.xpc.logger,
    -        'exception caught while attempting setup: ' + e);
    -  }
    -  // retry necessary?
    -  if (retry) {
    -    if (!this.attemptSetupCb_) {
    -      this.attemptSetupCb_ = goog.bind(this.attemptSetup_, this);
    -    }
    -    this.getWindow().setTimeout(this.attemptSetupCb_, 100);
    -  }
    -};
    -
    -
    -/**
    - * Handles transport service messages.
    - * @param {string} payload The message content.
    - * @override
    - */
    -goog.net.xpc.FrameElementMethodTransport.prototype.transportServiceHandler =
    -    function(payload) {
    -  if (this.channel_.getRole() == goog.net.xpc.CrossPageChannelRole.OUTER &&
    -      !this.channel_.isConnected() && payload == goog.net.xpc.SETUP_ACK_) {
    -    // get a reference to the gateway function
    -    this.outgoing_ = this.iframeElm_['XPC_toOuter']['XPC_toInner'];
    -    // notify the channel we're ready
    -    this.channel_.notifyConnected();
    -  } else {
    -    throw Error('Got unexpected transport message.');
    -  }
    -};
    -
    -
    -/**
    - * Process incoming message.
    - * @param {string} serviceName The name of the service the message is to be
    - * delivered to.
    - * @param {string} payload The message to process.
    - * @private
    - */
    -goog.net.xpc.FrameElementMethodTransport.prototype.incoming_ =
    -    function(serviceName, payload) {
    -  if (!this.recursive_ && this.queue_.length == 0) {
    -    this.channel_.xpcDeliver(serviceName, payload);
    -  }
    -  else {
    -    this.queue_.push({serviceName: serviceName, payload: payload});
    -    if (this.queue_.length == 1) {
    -      this.timer_ = this.getWindow().setTimeout(this.deliverQueuedCb_, 1);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Delivers queued messages.
    - * @private
    - */
    -goog.net.xpc.FrameElementMethodTransport.prototype.deliverQueued_ =
    -    function() {
    -  while (this.queue_.length) {
    -    var msg = this.queue_.shift();
    -    this.channel_.xpcDeliver(msg.serviceName, msg.payload);
    -  }
    -};
    -
    -
    -/**
    - * Send a message
    - * @param {string} service The name off the service the message is to be
    - * delivered to.
    - * @param {string} payload The message content.
    - * @override
    - */
    -goog.net.xpc.FrameElementMethodTransport.prototype.send =
    -    function(service, payload) {
    -  this.recursive_ = true;
    -  this.outgoing_(service, payload);
    -  this.recursive_ = false;
    -};
    -
    -
    -/** @override */
    -goog.net.xpc.FrameElementMethodTransport.prototype.disposeInternal =
    -    function() {
    -  goog.net.xpc.FrameElementMethodTransport.superClass_.disposeInternal.call(
    -      this);
    -  this.outgoing_ = null;
    -  this.iframeElm_ = null;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xpc/iframepollingtransport.js b/src/database/third_party/closure-library/closure/goog/net/xpc/iframepollingtransport.js
    deleted file mode 100644
    index e92dcabf96f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xpc/iframepollingtransport.js
    +++ /dev/null
    @@ -1,984 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Contains the iframe polling transport.
    - */
    -
    -
    -goog.provide('goog.net.xpc.IframePollingTransport');
    -goog.provide('goog.net.xpc.IframePollingTransport.Receiver');
    -goog.provide('goog.net.xpc.IframePollingTransport.Sender');
    -
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.log');
    -goog.require('goog.log.Level');
    -goog.require('goog.net.xpc');
    -goog.require('goog.net.xpc.CfgFields');
    -goog.require('goog.net.xpc.CrossPageChannelRole');
    -goog.require('goog.net.xpc.Transport');
    -goog.require('goog.net.xpc.TransportTypes');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Iframe polling transport. Uses hidden iframes to transfer data
    - * in the fragment identifier of the URL. The peer polls the iframe's location
    - * for changes.
    - * Unfortunately, in Safari this screws up the history, because Safari doesn't
    - * allow to call location.replace() on a window containing a document from a
    - * different domain (last version tested: 2.0.4).
    - *
    - * @param {goog.net.xpc.CrossPageChannel} channel The channel this
    - *     transport belongs to.
    - * @param {goog.dom.DomHelper=} opt_domHelper The dom helper to use for finding
    - *     the correct window.
    - * @constructor
    - * @extends {goog.net.xpc.Transport}
    - * @final
    - */
    -goog.net.xpc.IframePollingTransport = function(channel, opt_domHelper) {
    -  goog.net.xpc.IframePollingTransport.base(this, 'constructor', opt_domHelper);
    -
    -  /**
    -   * The channel this transport belongs to.
    -   * @type {goog.net.xpc.CrossPageChannel}
    -   * @private
    -   */
    -  this.channel_ = channel;
    -
    -  /**
    -   * The URI used to send messages.
    -   * @type {string}
    -   * @private
    -   */
    -  this.sendUri_ =
    -      this.channel_.getConfig()[goog.net.xpc.CfgFields.PEER_POLL_URI];
    -
    -  /**
    -   * The URI which is polled for incoming messages.
    -   * @type {string}
    -   * @private
    -   */
    -  this.rcvUri_ =
    -      this.channel_.getConfig()[goog.net.xpc.CfgFields.LOCAL_POLL_URI];
    -
    -  /**
    -   * The queue to hold messages which can't be sent immediately.
    -   * @type {Array<string>}
    -   * @private
    -   */
    -  this.sendQueue_ = [];
    -};
    -goog.inherits(goog.net.xpc.IframePollingTransport, goog.net.xpc.Transport);
    -
    -
    -/**
    - * The number of times the inner frame will check for evidence of the outer
    - * frame before it tries its reconnection sequence.  These occur at 100ms
    - * intervals, making this an effective max waiting period of 500ms.
    - * @type {number}
    - * @private
    - */
    -goog.net.xpc.IframePollingTransport.prototype.pollsBeforeReconnect_ = 5;
    -
    -
    -/**
    - * The transport type.
    - * @type {number}
    - * @protected
    - * @override
    - */
    -goog.net.xpc.IframePollingTransport.prototype.transportType =
    -    goog.net.xpc.TransportTypes.IFRAME_POLLING;
    -
    -
    -/**
    - * Sequence counter.
    - * @type {number}
    - * @private
    - */
    -goog.net.xpc.IframePollingTransport.prototype.sequence_ = 0;
    -
    -
    -/**
    - * Flag indicating whether we are waiting for an acknoledgement.
    - * @type {boolean}
    - * @private
    - */
    -goog.net.xpc.IframePollingTransport.prototype.waitForAck_ = false;
    -
    -
    -/**
    - * Flag indicating if channel has been initialized.
    - * @type {boolean}
    - * @private
    - */
    -goog.net.xpc.IframePollingTransport.prototype.initialized_ = false;
    -
    -
    -/**
    - * Reconnection iframe created by inner peer.
    - * @type {Element}
    - * @private
    - */
    -goog.net.xpc.IframePollingTransport.prototype.reconnectFrame_ = null;
    -
    -
    -/** @private {goog.net.xpc.IframePollingTransport.Receiver} */
    -goog.net.xpc.IframePollingTransport.prototype.ackReceiver_;
    -
    -
    -/** @private {goog.net.xpc.IframePollingTransport.Sender} */
    -goog.net.xpc.IframePollingTransport.prototype.ackSender_;
    -
    -
    -/** @private */
    -goog.net.xpc.IframePollingTransport.prototype.ackIframeElm_;
    -
    -
    -/** @private */
    -goog.net.xpc.IframePollingTransport.prototype.ackWinObj_;
    -
    -
    -/** @private */
    -goog.net.xpc.IframePollingTransport.prototype.checkLocalFramesPresentCb_;
    -
    -
    -/** @private */
    -goog.net.xpc.IframePollingTransport.prototype.deliveryQueue_;
    -
    -
    -/** @private */
    -goog.net.xpc.IframePollingTransport.prototype.msgIframeElm_;
    -
    -
    -/** @private */
    -goog.net.xpc.IframePollingTransport.prototype.msgReceiver_;
    -
    -
    -/** @private */
    -goog.net.xpc.IframePollingTransport.prototype.msgSender_;
    -
    -
    -/** @private */
    -goog.net.xpc.IframePollingTransport.prototype.msgWinObj_;
    -
    -
    -/** @private */
    -goog.net.xpc.IframePollingTransport.prototype.rcvdConnectionSetupAck_;
    -
    -
    -/** @private */
    -goog.net.xpc.IframePollingTransport.prototype.sentConnectionSetupAck_;
    -
    -
    -/** @private {boolean} */
    -goog.net.xpc.IframePollingTransport.prototype.sentConnectionSetup_;
    -
    -
    -/** @private */
    -goog.net.xpc.IframePollingTransport.prototype.parts_;
    -
    -
    -/**
    - * The string used to prefix all iframe names and IDs.
    - * @type {string}
    - */
    -goog.net.xpc.IframePollingTransport.IFRAME_PREFIX = 'googlexpc';
    -
    -
    -/**
    - * Returns the name/ID of the message frame.
    - * @return {string} Name of message frame.
    - * @private
    - */
    -goog.net.xpc.IframePollingTransport.prototype.getMsgFrameName_ = function() {
    -  return goog.net.xpc.IframePollingTransport.IFRAME_PREFIX + '_' +
    -      this.channel_.name + '_msg';
    -};
    -
    -
    -/**
    - * Returns the name/ID of the ack frame.
    - * @return {string} Name of ack frame.
    - * @private
    - */
    -goog.net.xpc.IframePollingTransport.prototype.getAckFrameName_ = function() {
    -  return goog.net.xpc.IframePollingTransport.IFRAME_PREFIX + '_' +
    -      this.channel_.name + '_ack';
    -};
    -
    -
    -/**
    - * Determines whether the channel is still available. The channel is
    - * unavailable if the transport was disposed or the peer is no longer
    - * available.
    - * @return {boolean} Whether the channel is available.
    - */
    -goog.net.xpc.IframePollingTransport.prototype.isChannelAvailable = function() {
    -  return !this.isDisposed() && this.channel_.isPeerAvailable();
    -};
    -
    -
    -/**
    - * Safely retrieves the frames from the peer window. If an error is thrown
    - * (e.g. the window is closing) an empty frame object is returned.
    - * @return {!Object<!Window>} The frames from the peer window.
    - * @private
    - */
    -goog.net.xpc.IframePollingTransport.prototype.getPeerFrames_ = function() {
    -  try {
    -    if (this.isChannelAvailable()) {
    -      return this.channel_.getPeerWindowObject().frames || {};
    -    }
    -  } catch (e) {
    -    // An error may be thrown if the window is closing.
    -    goog.log.fine(goog.net.xpc.logger, 'error retrieving peer frames');
    -  }
    -  return {};
    -};
    -
    -
    -/**
    - * Safely retrieves the peer frame with the specified name.
    - * @param {string} frameName The name of the peer frame to retrieve.
    - * @return {!Window} The peer frame with the specified name.
    - * @private
    - */
    -goog.net.xpc.IframePollingTransport.prototype.getPeerFrame_ = function(
    -    frameName) {
    -  return this.getPeerFrames_()[frameName];
    -};
    -
    -
    -/**
    - * Connects this transport.
    - * @override
    - */
    -goog.net.xpc.IframePollingTransport.prototype.connect = function() {
    -  if (!this.isChannelAvailable()) {
    -    // When the channel is unavailable there is no peer to poll so stop trying
    -    // to connect.
    -    return;
    -  }
    -
    -  goog.log.fine(goog.net.xpc.logger, 'transport connect called');
    -  if (!this.initialized_) {
    -    goog.log.fine(goog.net.xpc.logger, 'initializing...');
    -    this.constructSenderFrames_();
    -    this.initialized_ = true;
    -  }
    -  this.checkForeignFramesReady_();
    -};
    -
    -
    -/**
    - * Creates the iframes which are used to send messages (and acknowledgements)
    - * to the peer. Sender iframes contain a document from a different origin and
    - * therefore their content can't be accessed.
    - * @private
    - */
    -goog.net.xpc.IframePollingTransport.prototype.constructSenderFrames_ =
    -    function() {
    -  var name = this.getMsgFrameName_();
    -  this.msgIframeElm_ = this.constructSenderFrame_(name);
    -  this.msgWinObj_ = this.getWindow().frames[name];
    -
    -  name = this.getAckFrameName_();
    -  this.ackIframeElm_ = this.constructSenderFrame_(name);
    -  this.ackWinObj_ = this.getWindow().frames[name];
    -};
    -
    -
    -/**
    - * Constructs a sending frame the the given id.
    - * @param {string} id The id.
    - * @return {!Element} The constructed frame.
    - * @private
    - */
    -goog.net.xpc.IframePollingTransport.prototype.constructSenderFrame_ =
    -    function(id) {
    -  goog.log.log(goog.net.xpc.logger, goog.log.Level.FINEST,
    -      'constructing sender frame: ' + id);
    -  var ifr = goog.dom.createElement('iframe');
    -  var s = ifr.style;
    -  s.position = 'absolute';
    -  s.top = '-10px'; s.left = '10px'; s.width = '1px'; s.height = '1px';
    -  ifr.id = ifr.name = id;
    -  ifr.src = this.sendUri_ + '#INITIAL';
    -  this.getWindow().document.body.appendChild(ifr);
    -  return ifr;
    -};
    -
    -
    -/**
    - * The protocol for reconnecting is for the inner frame to change channel
    - * names, and then communicate the new channel name to the outer peer.
    - * The outer peer looks in a predefined location for the channel name
    - * upate. It is important to use a completely new channel name, as this
    - * will ensure that all messaging iframes are not in the bfcache.
    - * Otherwise, Safari may pollute the history when modifying the location
    - * of bfcached iframes.
    - * @private
    - */
    -goog.net.xpc.IframePollingTransport.prototype.maybeInnerPeerReconnect_ =
    -    function() {
    -  // Reconnection has been found to not function on some browsers (eg IE7), so
    -  // it's important that the mechanism only be triggered as a last resort.  As
    -  // such, we poll a number of times to find the outer iframe before triggering
    -  // it.
    -  if (this.reconnectFrame_ || this.pollsBeforeReconnect_-- > 0) {
    -    return;
    -  }
    -
    -  goog.log.log(goog.net.xpc.logger, goog.log.Level.FINEST,
    -      'Inner peer reconnect triggered.');
    -  this.channel_.updateChannelNameAndCatalog(goog.net.xpc.getRandomString(10));
    -  goog.log.log(goog.net.xpc.logger, goog.log.Level.FINEST,
    -      'switching channels: ' + this.channel_.name);
    -  this.deconstructSenderFrames_();
    -  this.initialized_ = false;
    -  // Communicate new channel name to outer peer.
    -  this.reconnectFrame_ = this.constructSenderFrame_(
    -      goog.net.xpc.IframePollingTransport.IFRAME_PREFIX +
    -          '_reconnect_' + this.channel_.name);
    -};
    -
    -
    -/**
    - * Scans inner peer for a reconnect message, which will be used to update
    - * the outer peer's channel name. If a reconnect message is found, the
    - * sender frames will be cleaned up to make way for the new sender frames.
    - * Only called by the outer peer.
    - * @private
    - */
    -goog.net.xpc.IframePollingTransport.prototype.outerPeerReconnect_ = function() {
    -  goog.log.log(goog.net.xpc.logger, goog.log.Level.FINEST,
    -      'outerPeerReconnect called');
    -  var frames = this.getPeerFrames_();
    -  var length = frames.length;
    -  for (var i = 0; i < length; i++) {
    -    var frameName;
    -    try {
    -      if (frames[i] && frames[i].name) {
    -        frameName = frames[i].name;
    -      }
    -    } catch (e) {
    -      // Do nothing.
    -    }
    -    if (!frameName) {
    -      continue;
    -    }
    -    var message = frameName.split('_');
    -    if (message.length == 3 &&
    -        message[0] == goog.net.xpc.IframePollingTransport.IFRAME_PREFIX &&
    -        message[1] == 'reconnect') {
    -      // This is a legitimate reconnect message from the peer. Start using
    -      // the peer provided channel name, and start a connection over from
    -      // scratch.
    -      this.channel_.name = message[2];
    -      this.deconstructSenderFrames_();
    -      this.initialized_ = false;
    -      break;
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Cleans up the existing sender frames owned by this peer. Only called by
    - * the outer peer.
    - * @private
    - */
    -goog.net.xpc.IframePollingTransport.prototype.deconstructSenderFrames_ =
    -    function() {
    -  goog.log.log(goog.net.xpc.logger, goog.log.Level.FINEST,
    -      'deconstructSenderFrames called');
    -  if (this.msgIframeElm_) {
    -    this.msgIframeElm_.parentNode.removeChild(this.msgIframeElm_);
    -    this.msgIframeElm_ = null;
    -    this.msgWinObj_ = null;
    -  }
    -  if (this.ackIframeElm_) {
    -    this.ackIframeElm_.parentNode.removeChild(this.ackIframeElm_);
    -    this.ackIframeElm_ = null;
    -    this.ackWinObj_ = null;
    -  }
    -};
    -
    -
    -/**
    - * Checks if the frames in the peer's page are ready. These contain a
    - * document from the own domain and are the ones messages are received through.
    - * @private
    - */
    -goog.net.xpc.IframePollingTransport.prototype.checkForeignFramesReady_ =
    -    function() {
    -  // check if the connected iframe ready
    -  if (!(this.isRcvFrameReady_(this.getMsgFrameName_()) &&
    -        this.isRcvFrameReady_(this.getAckFrameName_()))) {
    -    goog.log.log(goog.net.xpc.logger, goog.log.Level.FINEST,
    -        'foreign frames not (yet) present');
    -
    -    if (this.channel_.getRole() == goog.net.xpc.CrossPageChannelRole.INNER) {
    -      // The outer peer might need a short time to get its frames ready, as
    -      // CrossPageChannel prevents them from getting created until the inner
    -      // peer's frame has thrown its loaded event.  This method is a noop for
    -      // the first few times it's called, and then allows the reconnection
    -      // sequence to begin.
    -      this.maybeInnerPeerReconnect_();
    -    } else if (this.channel_.getRole() ==
    -               goog.net.xpc.CrossPageChannelRole.OUTER) {
    -      // The inner peer is either not loaded yet, or the receiving
    -      // frames are simply missing. Since we cannot discern the two cases, we
    -      // should scan for a reconnect message from the inner peer.
    -      this.outerPeerReconnect_();
    -    }
    -
    -    // start a timer to check again
    -    this.getWindow().setTimeout(goog.bind(this.connect, this), 100);
    -  } else {
    -    goog.log.fine(goog.net.xpc.logger, 'foreign frames present');
    -
    -    // Create receivers.
    -    this.msgReceiver_ = new goog.net.xpc.IframePollingTransport.Receiver(
    -        this,
    -        this.getPeerFrame_(this.getMsgFrameName_()),
    -        goog.bind(this.processIncomingMsg, this));
    -    this.ackReceiver_ = new goog.net.xpc.IframePollingTransport.Receiver(
    -        this,
    -        this.getPeerFrame_(this.getAckFrameName_()),
    -        goog.bind(this.processIncomingAck, this));
    -
    -    this.checkLocalFramesPresent_();
    -  }
    -};
    -
    -
    -/**
    - * Checks if the receiving frame is ready.
    - * @param {string} frameName Which receiving frame to check.
    - * @return {boolean} Whether the receiving frame is ready.
    - * @private
    - */
    -goog.net.xpc.IframePollingTransport.prototype.isRcvFrameReady_ =
    -    function(frameName) {
    -  goog.log.log(goog.net.xpc.logger, goog.log.Level.FINEST,
    -      'checking for receive frame: ' + frameName);
    -  /** @preserveTry */
    -  try {
    -    var winObj = this.getPeerFrame_(frameName);
    -    if (!winObj || winObj.location.href.indexOf(this.rcvUri_) != 0) {
    -      return false;
    -    }
    -  } catch (e) {
    -    return false;
    -  }
    -  return true;
    -};
    -
    -
    -/**
    - * Checks if the iframes created in the own document are ready.
    - * @private
    - */
    -goog.net.xpc.IframePollingTransport.prototype.checkLocalFramesPresent_ =
    -    function() {
    -
    -  // Are the sender frames ready?
    -  // These contain a document from the peer's domain, therefore we can only
    -  // check if the frame itself is present.
    -  var frames = this.getPeerFrames_();
    -  if (!(frames[this.getAckFrameName_()] &&
    -        frames[this.getMsgFrameName_()])) {
    -    // start a timer to check again
    -    if (!this.checkLocalFramesPresentCb_) {
    -      this.checkLocalFramesPresentCb_ = goog.bind(
    -          this.checkLocalFramesPresent_, this);
    -    }
    -    this.getWindow().setTimeout(this.checkLocalFramesPresentCb_, 100);
    -    goog.log.fine(goog.net.xpc.logger, 'local frames not (yet) present');
    -  } else {
    -    // Create senders.
    -    this.msgSender_ = new goog.net.xpc.IframePollingTransport.Sender(
    -        this.sendUri_, this.msgWinObj_);
    -    this.ackSender_ = new goog.net.xpc.IframePollingTransport.Sender(
    -        this.sendUri_, this.ackWinObj_);
    -
    -    goog.log.fine(goog.net.xpc.logger, 'local frames ready');
    -
    -    this.getWindow().setTimeout(goog.bind(function() {
    -      this.msgSender_.send(goog.net.xpc.SETUP);
    -      this.sentConnectionSetup_ = true;
    -      this.waitForAck_ = true;
    -      goog.log.fine(goog.net.xpc.logger, 'SETUP sent');
    -    }, this), 100);
    -  }
    -};
    -
    -
    -/**
    - * Check if connection is ready.
    - * @private
    - */
    -goog.net.xpc.IframePollingTransport.prototype.checkIfConnected_ = function() {
    -  if (this.sentConnectionSetupAck_ && this.rcvdConnectionSetupAck_) {
    -    this.channel_.notifyConnected();
    -
    -    if (this.deliveryQueue_) {
    -      goog.log.fine(goog.net.xpc.logger, 'delivering queued messages ' +
    -          '(' + this.deliveryQueue_.length + ')');
    -
    -      for (var i = 0, m; i < this.deliveryQueue_.length; i++) {
    -        m = this.deliveryQueue_[i];
    -        this.channel_.xpcDeliver(m.service, m.payload);
    -      }
    -      delete this.deliveryQueue_;
    -    }
    -  } else {
    -    goog.log.log(goog.net.xpc.logger, goog.log.Level.FINEST,
    -        'checking if connected: ' +
    -        'ack sent:' + this.sentConnectionSetupAck_ +
    -        ', ack rcvd: ' + this.rcvdConnectionSetupAck_);
    -  }
    -};
    -
    -
    -/**
    - * Processes an incoming message.
    - * @param {string} raw The complete received string.
    - */
    -goog.net.xpc.IframePollingTransport.prototype.processIncomingMsg =
    -    function(raw) {
    -  goog.log.log(goog.net.xpc.logger, goog.log.Level.FINEST,
    -      'msg received: ' + raw);
    -
    -  if (raw == goog.net.xpc.SETUP) {
    -    if (!this.ackSender_) {
    -      // Got SETUP msg, but we can't send an ack.
    -      return;
    -    }
    -
    -    this.ackSender_.send(goog.net.xpc.SETUP_ACK_);
    -    goog.log.log(goog.net.xpc.logger, goog.log.Level.FINEST, 'SETUP_ACK sent');
    -
    -    this.sentConnectionSetupAck_ = true;
    -    this.checkIfConnected_();
    -
    -  } else if (this.channel_.isConnected() || this.sentConnectionSetupAck_) {
    -
    -    var pos = raw.indexOf('|');
    -    var head = raw.substring(0, pos);
    -    var frame = raw.substring(pos + 1);
    -
    -    // check if it is a framed message
    -    pos = head.indexOf(',');
    -    if (pos == -1) {
    -      var seq = head;
    -      // send acknowledgement
    -      this.ackSender_.send('ACK:' + seq);
    -      this.deliverPayload_(frame);
    -    } else {
    -      var seq = head.substring(0, pos);
    -      // send acknowledgement
    -      this.ackSender_.send('ACK:' + seq);
    -
    -      var partInfo = head.substring(pos + 1).split('/');
    -      var part0 = parseInt(partInfo[0], 10);
    -      var part1 = parseInt(partInfo[1], 10);
    -      // create an array to accumulate the parts if this is the
    -      // first frame of a message
    -      if (part0 == 1) {
    -        this.parts_ = [];
    -      }
    -      this.parts_.push(frame);
    -      // deliver the message if this was the last frame of a message
    -      if (part0 == part1) {
    -        this.deliverPayload_(this.parts_.join(''));
    -        delete this.parts_;
    -      }
    -    }
    -  } else {
    -    goog.log.warning(goog.net.xpc.logger,
    -        'received msg, but channel is not connected');
    -  }
    -};
    -
    -
    -/**
    - * Process an incoming acknowdedgement.
    - * @param {string} msgStr The incoming ack string to process.
    - */
    -goog.net.xpc.IframePollingTransport.prototype.processIncomingAck =
    -    function(msgStr) {
    -  goog.log.log(goog.net.xpc.logger, goog.log.Level.FINEST,
    -      'ack received: ' + msgStr);
    -
    -  if (msgStr == goog.net.xpc.SETUP_ACK_) {
    -    this.waitForAck_ = false;
    -    this.rcvdConnectionSetupAck_ = true;
    -    // send the next frame
    -    this.checkIfConnected_();
    -
    -  } else if (this.channel_.isConnected()) {
    -    if (!this.waitForAck_) {
    -      goog.log.warning(goog.net.xpc.logger, 'got unexpected ack');
    -      return;
    -    }
    -
    -    var seq = parseInt(msgStr.split(':')[1], 10);
    -    if (seq == this.sequence_) {
    -      this.waitForAck_ = false;
    -      this.sendNextFrame_();
    -    } else {
    -      goog.log.warning(goog.net.xpc.logger, 'got ack with wrong sequence');
    -    }
    -  } else {
    -    goog.log.warning(goog.net.xpc.logger,
    -        'received ack, but channel not connected');
    -  }
    -};
    -
    -
    -/**
    - * Sends a frame (message part).
    - * @private
    - */
    -goog.net.xpc.IframePollingTransport.prototype.sendNextFrame_ = function() {
    -  // do nothing if we are waiting for an acknowledgement or the
    -  // queue is emtpy
    -  if (this.waitForAck_ || !this.sendQueue_.length) {
    -    return;
    -  }
    -
    -  var s = this.sendQueue_.shift();
    -  ++this.sequence_;
    -  this.msgSender_.send(this.sequence_ + s);
    -  goog.log.log(goog.net.xpc.logger, goog.log.Level.FINEST,
    -      'msg sent: ' + this.sequence_ + s);
    -
    -
    -  this.waitForAck_ = true;
    -};
    -
    -
    -/**
    - * Delivers a message.
    - * @param {string} s The complete message string ("<service_name>:<payload>").
    - * @private
    - */
    -goog.net.xpc.IframePollingTransport.prototype.deliverPayload_ = function(s) {
    -  // determine the service name and the payload
    -  var pos = s.indexOf(':');
    -  var service = s.substr(0, pos);
    -  var payload = s.substring(pos + 1);
    -
    -  // deliver the message
    -  if (!this.channel_.isConnected()) {
    -    // as valid messages can come in before a SETUP_ACK has
    -    // been received (because subchannels for msgs and acks are independent),
    -    // delay delivery of early messages until after 'connect'-event
    -    (this.deliveryQueue_ || (this.deliveryQueue_ = [])).
    -        push({service: service, payload: payload});
    -    goog.log.log(goog.net.xpc.logger, goog.log.Level.FINEST,
    -        'queued delivery');
    -  } else {
    -    this.channel_.xpcDeliver(service, payload);
    -  }
    -};
    -
    -
    -// ---- send message ----
    -
    -
    -/**
    - * Maximal frame length.
    - * @type {number}
    - * @private
    - */
    -goog.net.xpc.IframePollingTransport.prototype.MAX_FRAME_LENGTH_ = 3800;
    -
    -
    -/**
    - * Sends a message. Splits it in multiple frames if too long (exceeds IE's
    - * URL-length maximum.
    - * Wireformat: <seq>[,<frame_no>/<#frames>]|<frame_content>
    - *
    - * @param {string} service Name of service this the message has to be delivered.
    - * @param {string} payload The message content.
    - * @override
    - */
    -goog.net.xpc.IframePollingTransport.prototype.send =
    -    function(service, payload) {
    -  var frame = service + ':' + payload;
    -  // put in queue
    -  if (!goog.userAgent.IE || payload.length <= this.MAX_FRAME_LENGTH_) {
    -    this.sendQueue_.push('|' + frame);
    -  }
    -  else {
    -    var l = payload.length;
    -    var num = Math.ceil(l / this.MAX_FRAME_LENGTH_); // number of frames
    -    var pos = 0;
    -    var i = 1;
    -    while (pos < l) {
    -      this.sendQueue_.push(',' + i + '/' + num + '|' +
    -                           frame.substr(pos, this.MAX_FRAME_LENGTH_));
    -      i++;
    -      pos += this.MAX_FRAME_LENGTH_;
    -    }
    -  }
    -  this.sendNextFrame_();
    -};
    -
    -
    -/** @override */
    -goog.net.xpc.IframePollingTransport.prototype.disposeInternal = function() {
    -  goog.net.xpc.IframePollingTransport.base(this, 'disposeInternal');
    -
    -  var receivers = goog.net.xpc.IframePollingTransport.receivers_;
    -  goog.array.remove(receivers, this.msgReceiver_);
    -  goog.array.remove(receivers, this.ackReceiver_);
    -  this.msgReceiver_ = this.ackReceiver_ = null;
    -
    -  goog.dom.removeNode(this.msgIframeElm_);
    -  goog.dom.removeNode(this.ackIframeElm_);
    -  this.msgIframeElm_ = this.ackIframeElm_ = null;
    -  this.msgWinObj_ = this.ackWinObj_ = null;
    -};
    -
    -
    -/**
    - * Array holding all Receiver-instances.
    - * @type {Array<goog.net.xpc.IframePollingTransport.Receiver>}
    - * @private
    - */
    -goog.net.xpc.IframePollingTransport.receivers_ = [];
    -
    -
    -/**
    - * Short polling interval.
    - * @type {number}
    - * @private
    - */
    -goog.net.xpc.IframePollingTransport.TIME_POLL_SHORT_ = 10;
    -
    -
    -/**
    - * Long polling interval.
    - * @type {number}
    - * @private
    - */
    -goog.net.xpc.IframePollingTransport.TIME_POLL_LONG_ = 100;
    -
    -
    -/**
    - * Period how long to use TIME_POLL_SHORT_ before raising polling-interval
    - * to TIME_POLL_LONG_ after an activity.
    - * @type {number}
    - * @private
    - */
    -goog.net.xpc.IframePollingTransport.TIME_SHORT_POLL_AFTER_ACTIVITY_ =
    -    1000;
    -
    -
    -/**
    - * Polls all receivers.
    - * @private
    - */
    -goog.net.xpc.IframePollingTransport.receive_ = function() {
    -  var receivers = goog.net.xpc.IframePollingTransport.receivers_;
    -  var receiver;
    -  var rcvd = false;
    -
    -  /** @preserveTry */
    -  try {
    -    for (var i = 0; receiver = receivers[i]; i++) {
    -      rcvd = rcvd || receiver.receive();
    -    }
    -  } catch (e) {
    -    goog.log.info(goog.net.xpc.logger, 'receive_() failed: ' + e);
    -
    -    // Notify the channel that the transport had an error.
    -    receiver.transport_.channel_.notifyTransportError();
    -
    -    // notifyTransportError() closes the channel and disposes the transport.
    -    // If there are no other channels present, this.receivers_ will now be empty
    -    // and there is no need to keep polling.
    -    if (!receivers.length) {
    -      return;
    -    }
    -  }
    -
    -  var now = goog.now();
    -  if (rcvd) {
    -    goog.net.xpc.IframePollingTransport.lastActivity_ = now;
    -  }
    -
    -  // Schedule next check.
    -  var t = now - goog.net.xpc.IframePollingTransport.lastActivity_ <
    -      goog.net.xpc.IframePollingTransport.TIME_SHORT_POLL_AFTER_ACTIVITY_ ?
    -      goog.net.xpc.IframePollingTransport.TIME_POLL_SHORT_ :
    -      goog.net.xpc.IframePollingTransport.TIME_POLL_LONG_;
    -  goog.net.xpc.IframePollingTransport.rcvTimer_ = window.setTimeout(
    -      goog.net.xpc.IframePollingTransport.receiveCb_, t);
    -};
    -
    -
    -/**
    - * Callback that wraps receive_ to be used in timers.
    - * @type {Function}
    - * @private
    - */
    -goog.net.xpc.IframePollingTransport.receiveCb_ = goog.bind(
    -    goog.net.xpc.IframePollingTransport.receive_,
    -    goog.net.xpc.IframePollingTransport);
    -
    -
    -/**
    - * Starts the polling loop.
    - * @private
    - */
    -goog.net.xpc.IframePollingTransport.startRcvTimer_ = function() {
    -  goog.log.fine(goog.net.xpc.logger, 'starting receive-timer');
    -  goog.net.xpc.IframePollingTransport.lastActivity_ = goog.now();
    -  if (goog.net.xpc.IframePollingTransport.rcvTimer_) {
    -    window.clearTimeout(goog.net.xpc.IframePollingTransport.rcvTimer_);
    -  }
    -  goog.net.xpc.IframePollingTransport.rcvTimer_ = window.setTimeout(
    -      goog.net.xpc.IframePollingTransport.receiveCb_,
    -      goog.net.xpc.IframePollingTransport.TIME_POLL_SHORT_);
    -};
    -
    -
    -
    -/**
    - * goog.net.xpc.IframePollingTransport.Sender
    - *
    - * Utility class to send message-parts to a document from a different origin.
    - *
    - * @constructor
    - * @param {string} url The url the other document will use for polling.
    - * @param {Object} windowObj The frame used for sending information to.
    - * @final
    - */
    -goog.net.xpc.IframePollingTransport.Sender = function(url, windowObj) {
    -  /**
    -   * The URI used to sending messages.
    -   * @type {string}
    -   * @private
    -   */
    -  this.sendUri_ = url;
    -
    -  /**
    -   * The window object of the iframe used to send messages.
    -   * The script instantiating the Sender won't have access to
    -   * the content of sendFrame_.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.sendFrame_ = windowObj;
    -
    -  /**
    -   * Cycle counter (used to make sure that sending two identical messages sent
    -   * in direct succession can be recognized as such by the receiver).
    -   * @type {number}
    -   * @private
    -   */
    -  this.cycle_ = 0;
    -};
    -
    -
    -/**
    - * Sends a message-part (frame) to the peer.
    - * The message-part is encoded and put in the fragment identifier
    - * of the URL used for sending (and belongs to the origin/domain of the peer).
    - * @param {string} payload The message to send.
    - */
    -goog.net.xpc.IframePollingTransport.Sender.prototype.send = function(payload) {
    -  this.cycle_ = ++this.cycle_ % 2;
    -
    -  var url = this.sendUri_ + '#' + this.cycle_ + encodeURIComponent(payload);
    -
    -  // TODO(user) Find out if try/catch is still needed
    -  /** @preserveTry */
    -  try {
    -    // safari doesn't allow to call location.replace()
    -    if (goog.userAgent.WEBKIT) {
    -      this.sendFrame_.location.href = url;
    -    } else {
    -      this.sendFrame_.location.replace(url);
    -    }
    -  } catch (e) {
    -    goog.log.error(goog.net.xpc.logger, 'sending failed', e);
    -  }
    -
    -  // Restart receiver timer on short polling interval, to support use-cases
    -  // where we need to capture responses quickly.
    -  goog.net.xpc.IframePollingTransport.startRcvTimer_();
    -};
    -
    -
    -
    -/**
    - * goog.net.xpc.IframePollingTransport.Receiver
    - *
    - * @constructor
    - * @param {goog.net.xpc.IframePollingTransport} transport The transport to
    - *     receive from.
    - * @param {Object} windowObj The window-object to poll for location-changes.
    - * @param {Function} callback The callback-function to be called when
    - *     location has changed.
    - * @final
    - */
    -goog.net.xpc.IframePollingTransport.Receiver = function(transport,
    -                                                        windowObj,
    -                                                        callback) {
    -  /**
    -   * The transport to receive from.
    -   * @type {goog.net.xpc.IframePollingTransport}
    -   * @private
    -   */
    -  this.transport_ = transport;
    -  this.rcvFrame_ = windowObj;
    -
    -  this.cb_ = callback;
    -  this.currentLoc_ = this.rcvFrame_.location.href.split('#')[0] + '#INITIAL';
    -
    -  goog.net.xpc.IframePollingTransport.receivers_.push(this);
    -  goog.net.xpc.IframePollingTransport.startRcvTimer_();
    -};
    -
    -
    -/**
    - * Polls the location of the receiver-frame for changes.
    - * @return {boolean} Whether a change has been detected.
    - */
    -goog.net.xpc.IframePollingTransport.Receiver.prototype.receive = function() {
    -  var loc = this.rcvFrame_.location.href;
    -
    -  if (loc != this.currentLoc_) {
    -    this.currentLoc_ = loc;
    -    var payload = loc.split('#')[1];
    -    if (payload) {
    -      payload = payload.substr(1); // discard first character (cycle)
    -      this.cb_(decodeURIComponent(payload));
    -    }
    -    return true;
    -  } else {
    -    return false;
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xpc/iframepollingtransport_test.html b/src/database/third_party/closure-library/closure/goog/net/xpc/iframepollingtransport_test.html
    deleted file mode 100644
    index d054daae581..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xpc/iframepollingtransport_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-IframePollingTransport-Compatible" content="IE=edge" />
    -  <title>
    -   NativeMessagingTransport Unit-Tests
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.net.xpc.IframePollingTransportTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xpc/iframepollingtransport_test.js b/src/database/third_party/closure-library/closure/goog/net/xpc/iframepollingtransport_test.js
    deleted file mode 100644
    index 912cb7847f9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xpc/iframepollingtransport_test.js
    +++ /dev/null
    @@ -1,289 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.net.xpc.IframePollingTransportTest');
    -goog.setTestOnly('goog.net.xpc.IframePollingTransportTest');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.functions');
    -goog.require('goog.net.xpc.CfgFields');
    -goog.require('goog.net.xpc.CrossPageChannel');
    -goog.require('goog.net.xpc.CrossPageChannelRole');
    -goog.require('goog.net.xpc.TransportTypes');
    -goog.require('goog.object');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -
    -var mockClock = null;
    -var outerChannel = null;
    -var innerChannel = null;
    -
    -function setUp() {
    -  mockClock = new goog.testing.MockClock(true /* opt_autoInstall */);
    -
    -  // Create the peer windows.
    -  var outerPeerHostName = 'https://www.youtube.com';
    -  var outerPeerWindow = createMockPeerWindow(outerPeerHostName);
    -
    -  var innerPeerHostName = 'https://www.google.com';
    -  var innerPeerWindow = createMockPeerWindow(innerPeerHostName);
    -
    -  // Create the channels.
    -  outerChannel = createChannel(goog.net.xpc.CrossPageChannelRole.OUTER, 'test',
    -      outerPeerHostName, outerPeerWindow, innerPeerHostName, innerPeerWindow);
    -  innerChannel = createChannel(goog.net.xpc.CrossPageChannelRole.INNER, 'test',
    -      innerPeerHostName, innerPeerWindow, outerPeerHostName, outerPeerWindow);
    -}
    -
    -
    -function tearDown() {
    -  outerChannel.dispose();
    -  innerChannel.dispose();
    -  mockClock.uninstall();
    -}
    -
    -
    -/** Tests that connection happens normally and callbacks are invoked. */
    -function testConnect() {
    -  var outerConnectCallback = goog.testing.recordFunction();
    -  var innerConnectCallback = goog.testing.recordFunction();
    -
    -  // Connect the two channels.
    -  outerChannel.connect(outerConnectCallback);
    -  innerChannel.connect(innerConnectCallback);
    -  mockClock.tick(1000);
    -
    -  // Check that channels were connected and callbacks invoked.
    -  assertEquals(1, outerConnectCallback.getCallCount());
    -  assertEquals(1, innerConnectCallback.getCallCount());
    -  assertTrue(outerChannel.isConnected());
    -  assertTrue(innerChannel.isConnected());
    -}
    -
    -
    -/** Tests that messages are successfully delivered to the inner peer. */
    -function testSend_outerToInner() {
    -  var serviceCallback = goog.testing.recordFunction();
    -
    -  // Register a service handler in the inner channel.
    -  innerChannel.registerService('svc', function(payload) {
    -    assertEquals('hello', payload);
    -    serviceCallback();
    -  });
    -
    -  // Connect the two channels.
    -  outerChannel.connect();
    -  innerChannel.connect();
    -  mockClock.tick(1000);
    -
    -  // Send a message.
    -  outerChannel.send('svc', 'hello');
    -  mockClock.tick(1000);
    -
    -  // Check that the message was handled.
    -  assertEquals(1, serviceCallback.getCallCount());
    -}
    -
    -
    -/** Tests that messages are successfully delivered to the outer peer. */
    -function testSend_innerToOuter() {
    -  var serviceCallback = goog.testing.recordFunction();
    -
    -  // Register a service handler in the inner channel.
    -  outerChannel.registerService('svc', function(payload) {
    -    assertEquals('hello', payload);
    -    serviceCallback();
    -  });
    -
    -  // Connect the two channels.
    -  outerChannel.connect();
    -  innerChannel.connect();
    -  mockClock.tick(1000);
    -
    -  // Send a message.
    -  innerChannel.send('svc', 'hello');
    -  mockClock.tick(1000);
    -
    -  // Check that the message was handled.
    -  assertEquals(1, serviceCallback.getCallCount());
    -}
    -
    -
    -/** Tests that closing the outer peer does not cause an error. */
    -function testSend_outerPeerClosed() {
    -  // Connect the inner channel.
    -  innerChannel.connect();
    -  mockClock.tick(1000);
    -
    -  // Close the outer peer before it has a chance to connect.
    -  closeWindow(innerChannel.getPeerWindowObject());
    -
    -  // Allow timers to execute (and fail).
    -  mockClock.tick(1000);
    -}
    -
    -
    -/** Tests that closing the inner peer does not cause an error. */
    -function testSend_innerPeerClosed() {
    -  // Connect the outer channel.
    -  outerChannel.connect();
    -  mockClock.tick(1000);
    -
    -  // Close the inner peer before it has a chance to connect.
    -  closeWindow(outerChannel.getPeerWindowObject());
    -
    -  // Allow timers to execute (and fail).
    -  mockClock.tick(1000);
    -}
    -
    -
    -/** Tests that partially closing the outer peer does not cause an error. */
    -function testSend_outerPeerClosing() {
    -  // Connect the inner channel.
    -  innerChannel.connect();
    -  mockClock.tick(1000);
    -
    -  // Close the outer peer before it has a chance to connect, but
    -  // leave closed set to false to simulate a partially closed window.
    -  closeWindow(innerChannel.getPeerWindowObject());
    -  innerChannel.getPeerWindowObject().closed = false;
    -
    -  // Allow timers to execute (and fail).
    -  mockClock.tick(1000);
    -}
    -
    -
    -/** Tests that partially closing the inner peer does not cause an error. */
    -function testSend_innerPeerClosing() {
    -  // Connect the outer channel.
    -  outerChannel.connect();
    -  mockClock.tick(1000);
    -
    -  // Close the inner peer before it has a chance to connect, but
    -  // leave closed set to false to simulate a partially closed window.
    -  closeWindow(outerChannel.getPeerWindowObject());
    -  outerChannel.getPeerWindowObject().closed = false;
    -
    -  // Allow timers to execute (and fail).
    -  mockClock.tick(1000);
    -}
    -
    -
    -/**
    - * Creates a channel with the specified configuration, using frame polling.
    - * @param {!goog.net.xpc.CrossPageChannelRole} role The channel role.
    - * @param {string} channelName The channel name.
    - * @param {string} fromHostName The host name of the window hosting the channel.
    - * @param {!Object} fromWindow The window hosting the channel.
    - * @param {string} toHostName The host name of the peer window.
    - * @param {!Object} toWindow The peer window.
    - */
    -function createChannel(role, channelName, fromHostName, fromWindow, toHostName,
    -    toWindow) {
    -
    -  // Build a channel config using frame polling.
    -  var channelConfig = goog.object.create(
    -      goog.net.xpc.CfgFields.ROLE,
    -      role,
    -      goog.net.xpc.CfgFields.PEER_HOSTNAME,
    -      toHostName,
    -      goog.net.xpc.CfgFields.CHANNEL_NAME,
    -      channelName,
    -      goog.net.xpc.CfgFields.LOCAL_POLL_URI,
    -      fromHostName + '/robots.txt',
    -      goog.net.xpc.CfgFields.PEER_POLL_URI,
    -      toHostName + '/robots.txt',
    -      goog.net.xpc.CfgFields.TRANSPORT,
    -      goog.net.xpc.TransportTypes.IFRAME_POLLING);
    -
    -  // Build the channel.
    -  var channel = new goog.net.xpc.CrossPageChannel(channelConfig);
    -  channel.setPeerWindowObject(toWindow);
    -
    -  // Update the transport's getWindow, to return the correct host window.
    -  channel.createTransport_();
    -  channel.transport_.getWindow = goog.functions.constant(fromWindow);
    -  return channel;
    -}
    -
    -
    -/**
    - * Creates a mock window to use as a peer. The peer window will host the frame
    - * elements.
    - * @param {string} url The peer window's initial URL.
    - */
    -function createMockPeerWindow(url) {
    -  var mockPeer = createMockWindow(url);
    -
    -  // Update the appendChild method to use a mock frame window.
    -  mockPeer.document.body.appendChild = function(el) {
    -    assertEquals(goog.dom.TagName.IFRAME, el.tagName);
    -    mockPeer.frames[el.name] = createMockWindow(el.src);
    -    mockPeer.document.body.element.appendChild(el);
    -  };
    -
    -  return mockPeer;
    -}
    -
    -
    -/**
    - * Creates a mock window.
    - * @param {string} url The window's initial URL.
    - */
    -function createMockWindow(url) {
    -  // Create the mock window, document and body.
    -  var mockWindow = {};
    -  var mockDocument = {};
    -  var mockBody = {};
    -  var mockLocation = {};
    -
    -  // Configure the mock window's document body.
    -  mockBody.element = goog.dom.createDom(goog.dom.TagName.BODY);
    -
    -  // Configure the mock window's document.
    -  mockDocument.body = mockBody;
    -
    -  // Configure the mock window's location.
    -  mockLocation.href = url;
    -  mockLocation.replace = function(value) { mockLocation.href = value; };
    -
    -  // Configure the mock window.
    -  mockWindow.document = mockDocument;
    -  mockWindow.frames = {};
    -  mockWindow.location = mockLocation;
    -  mockWindow.setTimeout = goog.Timer.callOnce;
    -
    -  return mockWindow;
    -}
    -
    -
    -/**
    - * Emulates closing the specified window by clearing frames, document and
    - * location.
    - */
    -function closeWindow(targetWindow) {
    -  // Close any child frame windows.
    -  for (var frameName in targetWindow.frames) {
    -    closeWindow(targetWindow.frames[frameName]);
    -  }
    -
    -  // Clear the target window, set closed to true.
    -  targetWindow.closed = true;
    -  targetWindow.frames = null;
    -  targetWindow.document = null;
    -  targetWindow.location = null;
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xpc/iframerelaytransport.js b/src/database/third_party/closure-library/closure/goog/net/xpc/iframerelaytransport.js
    deleted file mode 100644
    index 1342fc8999d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xpc/iframerelaytransport.js
    +++ /dev/null
    @@ -1,409 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Contains the iframe relay tranport.
    - */
    -
    -
    -goog.provide('goog.net.xpc.IframeRelayTransport');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.safe');
    -goog.require('goog.events');
    -goog.require('goog.html.SafeHtml');
    -goog.require('goog.log');
    -goog.require('goog.log.Level');
    -goog.require('goog.net.xpc');
    -goog.require('goog.net.xpc.CfgFields');
    -goog.require('goog.net.xpc.Transport');
    -goog.require('goog.net.xpc.TransportTypes');
    -goog.require('goog.string');
    -goog.require('goog.string.Const');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Iframe relay transport. Creates hidden iframes containing a document
    - * from the peer's origin. Data is transferred in the fragment identifier.
    - * Therefore the document loaded in the iframes can be served from the
    - * browser's cache.
    - *
    - * @param {goog.net.xpc.CrossPageChannel} channel The channel this
    - *     transport belongs to.
    - * @param {goog.dom.DomHelper=} opt_domHelper The dom helper to use for finding
    - *     the correct window.
    - * @constructor
    - * @extends {goog.net.xpc.Transport}
    - * @final
    - */
    -goog.net.xpc.IframeRelayTransport = function(channel, opt_domHelper) {
    -  goog.net.xpc.IframeRelayTransport.base(this, 'constructor', opt_domHelper);
    -
    -  /**
    -   * The channel this transport belongs to.
    -   * @type {goog.net.xpc.CrossPageChannel}
    -   * @private
    -   */
    -  this.channel_ = channel;
    -
    -  /**
    -   * The URI used to relay data to the peer.
    -   * @type {string}
    -   * @private
    -   */
    -  this.peerRelayUri_ =
    -      this.channel_.getConfig()[goog.net.xpc.CfgFields.PEER_RELAY_URI];
    -
    -  /**
    -   * The id of the iframe the peer page lives in.
    -   * @type {string}
    -   * @private
    -   */
    -  this.peerIframeId_ =
    -      this.channel_.getConfig()[goog.net.xpc.CfgFields.IFRAME_ID];
    -
    -  if (goog.userAgent.WEBKIT) {
    -    goog.net.xpc.IframeRelayTransport.startCleanupTimer_();
    -  }
    -};
    -goog.inherits(goog.net.xpc.IframeRelayTransport, goog.net.xpc.Transport);
    -
    -
    -if (goog.userAgent.WEBKIT) {
    -  /**
    -   * Array to keep references to the relay-iframes. Used only if
    -   * there is no way to detect when the iframes are loaded. In that
    -   * case the relay-iframes are removed after a timeout.
    -   * @type {Array<Object>}
    -   * @private
    -   */
    -  goog.net.xpc.IframeRelayTransport.iframeRefs_ = [];
    -
    -
    -  /**
    -   * Interval at which iframes are destroyed.
    -   * @type {number}
    -   * @private
    -   */
    -  goog.net.xpc.IframeRelayTransport.CLEANUP_INTERVAL_ = 1000;
    -
    -
    -  /**
    -   * Time after which a relay-iframe is destroyed.
    -   * @type {number}
    -   * @private
    -   */
    -  goog.net.xpc.IframeRelayTransport.IFRAME_MAX_AGE_ = 3000;
    -
    -
    -  /**
    -   * The cleanup timer id.
    -   * @type {number}
    -   * @private
    -   */
    -  goog.net.xpc.IframeRelayTransport.cleanupTimer_ = 0;
    -
    -
    -  /**
    -   * Starts the cleanup timer.
    -   * @private
    -   */
    -  goog.net.xpc.IframeRelayTransport.startCleanupTimer_ = function() {
    -    if (!goog.net.xpc.IframeRelayTransport.cleanupTimer_) {
    -      goog.net.xpc.IframeRelayTransport.cleanupTimer_ = window.setTimeout(
    -          function() { goog.net.xpc.IframeRelayTransport.cleanup_(); },
    -          goog.net.xpc.IframeRelayTransport.CLEANUP_INTERVAL_);
    -    }
    -  };
    -
    -
    -  /**
    -   * Remove all relay-iframes which are older than the maximal age.
    -   * @param {number=} opt_maxAge The maximal age in milliseconds.
    -   * @private
    -   */
    -  goog.net.xpc.IframeRelayTransport.cleanup_ = function(opt_maxAge) {
    -    var now = goog.now();
    -    var maxAge =
    -        opt_maxAge || goog.net.xpc.IframeRelayTransport.IFRAME_MAX_AGE_;
    -
    -    while (goog.net.xpc.IframeRelayTransport.iframeRefs_.length &&
    -           now - goog.net.xpc.IframeRelayTransport.iframeRefs_[0].timestamp >=
    -           maxAge) {
    -      var ifr = goog.net.xpc.IframeRelayTransport.iframeRefs_.
    -          shift().iframeElement;
    -      goog.dom.removeNode(ifr);
    -      goog.log.log(goog.net.xpc.logger, goog.log.Level.FINEST,
    -          'iframe removed');
    -    }
    -
    -    goog.net.xpc.IframeRelayTransport.cleanupTimer_ = window.setTimeout(
    -        goog.net.xpc.IframeRelayTransport.cleanupCb_,
    -        goog.net.xpc.IframeRelayTransport.CLEANUP_INTERVAL_);
    -  };
    -
    -
    -  /**
    -   * Function which wraps cleanup_().
    -   * @private
    -   */
    -  goog.net.xpc.IframeRelayTransport.cleanupCb_ = function() {
    -    goog.net.xpc.IframeRelayTransport.cleanup_();
    -  };
    -}
    -
    -
    -/**
    - * Maximum sendable size of a payload via a single iframe in IE.
    - * @type {number}
    - * @private
    - */
    -goog.net.xpc.IframeRelayTransport.IE_PAYLOAD_MAX_SIZE_ = 1800;
    -
    -
    -/**
    - * @typedef {{fragments: !Array<string>, received: number, expected: number}}
    - */
    -goog.net.xpc.IframeRelayTransport.FragmentInfo;
    -
    -
    -/**
    - * Used to track incoming payload fragments. The implementation can process
    - * incoming fragments from several channels at a time, even if data is
    - * out-of-order or interleaved.
    - *
    - * @type {!Object<string, !goog.net.xpc.IframeRelayTransport.FragmentInfo>}
    - * @private
    - */
    -goog.net.xpc.IframeRelayTransport.fragmentMap_ = {};
    -
    -
    -/**
    - * The transport type.
    - * @type {number}
    - * @override
    - */
    -goog.net.xpc.IframeRelayTransport.prototype.transportType =
    -    goog.net.xpc.TransportTypes.IFRAME_RELAY;
    -
    -
    -/**
    - * Connects this transport.
    - * @override
    - */
    -goog.net.xpc.IframeRelayTransport.prototype.connect = function() {
    -  if (!this.getWindow()['xpcRelay']) {
    -    this.getWindow()['xpcRelay'] =
    -        goog.net.xpc.IframeRelayTransport.receiveMessage_;
    -  }
    -
    -  this.send(goog.net.xpc.TRANSPORT_SERVICE_, goog.net.xpc.SETUP);
    -};
    -
    -
    -/**
    - * Processes an incoming message.
    - *
    - * @param {string} channelName The name of the channel.
    - * @param {string} frame The raw frame content.
    - * @private
    - */
    -goog.net.xpc.IframeRelayTransport.receiveMessage_ =
    -    function(channelName, frame) {
    -  var pos = frame.indexOf(':');
    -  var header = frame.substr(0, pos);
    -  var payload = frame.substr(pos + 1);
    -
    -  if (!goog.userAgent.IE || (pos = header.indexOf('|')) == -1) {
    -    // First, the easy case.
    -    var service = header;
    -  } else {
    -    // There was a fragment id in the header, so this is a message
    -    // fragment, not a whole message.
    -    var service = header.substr(0, pos);
    -    var fragmentIdStr = header.substr(pos + 1);
    -
    -    // Separate the message id string and the fragment number. Note that
    -    // there may be a single leading + in the argument to parseInt, but
    -    // this is harmless.
    -    pos = fragmentIdStr.indexOf('+');
    -    var messageIdStr = fragmentIdStr.substr(0, pos);
    -    var fragmentNum = parseInt(fragmentIdStr.substr(pos + 1), 10);
    -    var fragmentInfo =
    -        goog.net.xpc.IframeRelayTransport.fragmentMap_[messageIdStr];
    -    if (!fragmentInfo) {
    -      fragmentInfo =
    -          goog.net.xpc.IframeRelayTransport.fragmentMap_[messageIdStr] =
    -          {fragments: [], received: 0, expected: 0};
    -    }
    -
    -    if (goog.string.contains(fragmentIdStr, '++')) {
    -      fragmentInfo.expected = fragmentNum + 1;
    -    }
    -    fragmentInfo.fragments[fragmentNum] = payload;
    -    fragmentInfo.received++;
    -
    -    if (fragmentInfo.received != fragmentInfo.expected) {
    -      return;
    -    }
    -
    -    // We've received all outstanding fragments; combine what we've received
    -    // into payload and fall out to the call to xpcDeliver.
    -    payload = fragmentInfo.fragments.join('');
    -    delete goog.net.xpc.IframeRelayTransport.fragmentMap_[messageIdStr];
    -  }
    -
    -  goog.net.xpc.channels[channelName].
    -      xpcDeliver(service, decodeURIComponent(payload));
    -};
    -
    -
    -/**
    - * Handles transport service messages (internal signalling).
    - * @param {string} payload The message content.
    - * @override
    - */
    -goog.net.xpc.IframeRelayTransport.prototype.transportServiceHandler =
    -    function(payload) {
    -  if (payload == goog.net.xpc.SETUP) {
    -    // TODO(user) Safari swallows the SETUP_ACK from the iframe to the
    -    // container after hitting reload.
    -    this.send(goog.net.xpc.TRANSPORT_SERVICE_, goog.net.xpc.SETUP_ACK_);
    -    this.channel_.notifyConnected();
    -  }
    -  else if (payload == goog.net.xpc.SETUP_ACK_) {
    -    this.channel_.notifyConnected();
    -  }
    -};
    -
    -
    -/**
    - * Sends a message.
    - *
    - * @param {string} service Name of service this the message has to be delivered.
    - * @param {string} payload The message content.
    - * @override
    - */
    -goog.net.xpc.IframeRelayTransport.prototype.send = function(service, payload) {
    -  // If we're on IE and the post-encoding payload is large, split it
    -  // into multiple payloads and send each one separately. Otherwise,
    -  // just send the whole thing.
    -  var encodedPayload = encodeURIComponent(payload);
    -  var encodedLen = encodedPayload.length;
    -  var maxSize = goog.net.xpc.IframeRelayTransport.IE_PAYLOAD_MAX_SIZE_;
    -
    -  if (goog.userAgent.IE && encodedLen > maxSize) {
    -    // A probabilistically-unique string used to link together all fragments
    -    // in this message.
    -    var messageIdStr = goog.string.getRandomString();
    -
    -    for (var startIndex = 0, fragmentNum = 0; startIndex < encodedLen;
    -         fragmentNum++) {
    -      var payloadFragment = encodedPayload.substr(startIndex, maxSize);
    -      startIndex += maxSize;
    -      var fragmentIdStr =
    -          messageIdStr + (startIndex >= encodedLen ? '++' : '+') + fragmentNum;
    -      this.send_(service, payloadFragment, fragmentIdStr);
    -    }
    -  } else {
    -    this.send_(service, encodedPayload);
    -  }
    -};
    -
    -
    -/**
    - * Sends an encoded message or message fragment.
    - * @param {string} service Name of service this the message has to be delivered.
    - * @param {string} encodedPayload The message content, URI encoded.
    - * @param {string=} opt_fragmentIdStr If sending a fragment, a string that
    - *     identifies the fragment.
    - * @private
    - */
    -goog.net.xpc.IframeRelayTransport.prototype.send_ =
    -    function(service, encodedPayload, opt_fragmentIdStr) {
    -  // IE requires that we create the onload attribute inline, otherwise the
    -  // handler is not triggered
    -  if (goog.userAgent.IE) {
    -    var div = this.getWindow().document.createElement('div');
    -    // TODO(user): It might be possible to set the sandbox attribute
    -    // to restrict the privileges of the created iframe.
    -    goog.dom.safe.setInnerHtml(div,
    -        goog.html.SafeHtml.createIframe(null, null, {
    -          'onload': goog.string.Const.from('this.xpcOnload()'),
    -          'sandbox': null
    -        }));
    -    var ifr = div.childNodes[0];
    -    div = null;
    -    ifr['xpcOnload'] = goog.net.xpc.IframeRelayTransport.iframeLoadHandler_;
    -  } else {
    -    var ifr = this.getWindow().document.createElement('iframe');
    -
    -    if (goog.userAgent.WEBKIT) {
    -      // safari doesn't fire load-events on iframes.
    -      // keep a reference and remove after a timeout.
    -      goog.net.xpc.IframeRelayTransport.iframeRefs_.push({
    -        timestamp: goog.now(),
    -        iframeElement: ifr
    -      });
    -    } else {
    -      goog.events.listen(ifr, 'load',
    -                         goog.net.xpc.IframeRelayTransport.iframeLoadHandler_);
    -    }
    -  }
    -
    -  var style = ifr.style;
    -  style.visibility = 'hidden';
    -  style.width = ifr.style.height = '0px';
    -  style.position = 'absolute';
    -
    -  var url = this.peerRelayUri_;
    -  url += '#' + this.channel_.name;
    -  if (this.peerIframeId_) {
    -    url += ',' + this.peerIframeId_;
    -  }
    -  url += '|' + service;
    -  if (opt_fragmentIdStr) {
    -    url += '|' + opt_fragmentIdStr;
    -  }
    -  url += ':' + encodedPayload;
    -
    -  ifr.src = url;
    -
    -  this.getWindow().document.body.appendChild(ifr);
    -
    -  goog.log.log(goog.net.xpc.logger, goog.log.Level.FINEST, 'msg sent: ' + url);
    -};
    -
    -
    -/**
    - * The iframe load handler. Gets called as method on the iframe element.
    - * @private
    - * @this Element
    - */
    -goog.net.xpc.IframeRelayTransport.iframeLoadHandler_ = function() {
    -  goog.log.log(goog.net.xpc.logger, goog.log.Level.FINEST, 'iframe-load');
    -  goog.dom.removeNode(this);
    -  this.xpcOnload = null;
    -};
    -
    -
    -/** @override */
    -goog.net.xpc.IframeRelayTransport.prototype.disposeInternal = function() {
    -  goog.net.xpc.IframeRelayTransport.base(this, 'disposeInternal');
    -  if (goog.userAgent.WEBKIT) {
    -    goog.net.xpc.IframeRelayTransport.cleanup_(0);
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xpc/nativemessagingtransport.js b/src/database/third_party/closure-library/closure/goog/net/xpc/nativemessagingtransport.js
    deleted file mode 100644
    index 2a14ef0fad1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xpc/nativemessagingtransport.js
    +++ /dev/null
    @@ -1,648 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Contains the class which uses native messaging
    - * facilities for cross domain communication.
    - *
    - */
    -
    -
    -goog.provide('goog.net.xpc.NativeMessagingTransport');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.asserts');
    -goog.require('goog.async.Deferred');
    -goog.require('goog.events');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.log');
    -goog.require('goog.net.xpc');
    -goog.require('goog.net.xpc.CrossPageChannelRole');
    -goog.require('goog.net.xpc.Transport');
    -goog.require('goog.net.xpc.TransportTypes');
    -
    -
    -
    -/**
    - * The native messaging transport
    - *
    - * Uses document.postMessage() to send messages to other documents.
    - * Receiving is done by listening on 'message'-events on the document.
    - *
    - * @param {goog.net.xpc.CrossPageChannel} channel The channel this
    - *     transport belongs to.
    - * @param {string} peerHostname The hostname (protocol, domain, and port) of the
    - *     peer.
    - * @param {goog.dom.DomHelper=} opt_domHelper The dom helper to use for
    - *     finding the correct window/document.
    - * @param {boolean=} opt_oneSidedHandshake If this is true, only the outer
    - *     transport sends a SETUP message and expects a SETUP_ACK.  The inner
    - *     transport goes connected when it receives the SETUP.
    - * @param {number=} opt_protocolVersion Which version of its setup protocol the
    - *     transport should use.  The default is '2'.
    - * @constructor
    - * @extends {goog.net.xpc.Transport}
    - * @final
    - */
    -goog.net.xpc.NativeMessagingTransport = function(channel, peerHostname,
    -    opt_domHelper, opt_oneSidedHandshake, opt_protocolVersion) {
    -  goog.net.xpc.NativeMessagingTransport.base(
    -      this, 'constructor', opt_domHelper);
    -
    -  /**
    -   * The channel this transport belongs to.
    -   * @type {goog.net.xpc.CrossPageChannel}
    -   * @private
    -   */
    -  this.channel_ = channel;
    -
    -  /**
    -   * Which version of the transport's protocol should be used.
    -   * @type {number}
    -   * @private
    -   */
    -  this.protocolVersion_ = opt_protocolVersion || 2;
    -  goog.asserts.assert(this.protocolVersion_ >= 1);
    -  goog.asserts.assert(this.protocolVersion_ <= 2);
    -
    -  /**
    -   * The hostname of the peer. This parameterizes all calls to postMessage, and
    -   * should contain the precise protocol, domain, and port of the peer window.
    -   * @type {string}
    -   * @private
    -   */
    -  this.peerHostname_ = peerHostname || '*';
    -
    -  /**
    -   * The event handler.
    -   * @type {!goog.events.EventHandler<!goog.net.xpc.NativeMessagingTransport>}
    -   * @private
    -   */
    -  this.eventHandler_ = new goog.events.EventHandler(this);
    -
    -  /**
    -   * Timer for connection reattempts.
    -   * @type {!goog.Timer}
    -   * @private
    -   */
    -  this.maybeAttemptToConnectTimer_ = new goog.Timer(100, this.getWindow());
    -
    -  /**
    -   * Whether one-sided handshakes are enabled.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.oneSidedHandshake_ = !!opt_oneSidedHandshake;
    -
    -  /**
    -   * Fires once we've received our SETUP_ACK message.
    -   * @type {!goog.async.Deferred}
    -   * @private
    -   */
    -  this.setupAckReceived_ = new goog.async.Deferred();
    -
    -  /**
    -   * Fires once we've sent our SETUP_ACK message.
    -   * @type {!goog.async.Deferred}
    -   * @private
    -   */
    -  this.setupAckSent_ = new goog.async.Deferred();
    -
    -  /**
    -   * Fires once we're marked connected.
    -   * @type {!goog.async.Deferred}
    -   * @private
    -   */
    -  this.connected_ = new goog.async.Deferred();
    -
    -  /**
    -   * The unique ID of this side of the connection. Used to determine when a peer
    -   * is reloaded.
    -   * @type {string}
    -   * @private
    -   */
    -  this.endpointId_ = goog.net.xpc.getRandomString(10);
    -
    -  /**
    -   * The unique ID of the peer. If we get a message from a peer with an ID we
    -   * don't expect, we reset the connection.
    -   * @type {?string}
    -   * @private
    -   */
    -  this.peerEndpointId_ = null;
    -
    -  // We don't want to mark ourselves connected until we have sent whatever
    -  // message will cause our counterpart in the other frame to also declare
    -  // itself connected, if there is such a message.  Otherwise we risk a user
    -  // message being sent in advance of that message, and it being discarded.
    -  if (this.oneSidedHandshake_) {
    -    if (this.channel_.getRole() == goog.net.xpc.CrossPageChannelRole.INNER) {
    -      // One sided handshake, inner frame:
    -      // SETUP_ACK must be received.
    -      this.connected_.awaitDeferred(this.setupAckReceived_);
    -    } else {
    -      // One sided handshake, outer frame:
    -      // SETUP_ACK must be sent.
    -      this.connected_.awaitDeferred(this.setupAckSent_);
    -    }
    -  } else {
    -    // Two sided handshake:
    -    // SETUP_ACK has to have been received, and sent.
    -    this.connected_.awaitDeferred(this.setupAckReceived_);
    -    if (this.protocolVersion_ == 2) {
    -      this.connected_.awaitDeferred(this.setupAckSent_);
    -    }
    -  }
    -  this.connected_.addCallback(this.notifyConnected_, this);
    -  this.connected_.callback(true);
    -
    -  this.eventHandler_.
    -      listen(this.maybeAttemptToConnectTimer_, goog.Timer.TICK,
    -          this.maybeAttemptToConnect_);
    -
    -  goog.log.info(goog.net.xpc.logger, 'NativeMessagingTransport created.  ' +
    -      'protocolVersion=' + this.protocolVersion_ + ', oneSidedHandshake=' +
    -      this.oneSidedHandshake_ + ', role=' + this.channel_.getRole());
    -};
    -goog.inherits(goog.net.xpc.NativeMessagingTransport, goog.net.xpc.Transport);
    -
    -
    -/**
    - * Length of the delay in milliseconds between the channel being connected and
    - * the connection callback being called, in cases where coverage of timing flaws
    - * is required.
    - * @type {number}
    - * @private
    - */
    -goog.net.xpc.NativeMessagingTransport.CONNECTION_DELAY_MS_ = 200;
    -
    -
    -/**
    - * Current determination of peer's protocol version, or null for unknown.
    - * @type {?number}
    - * @private
    - */
    -goog.net.xpc.NativeMessagingTransport.prototype.peerProtocolVersion_ = null;
    -
    -
    -/**
    - * Flag indicating if this instance of the transport has been initialized.
    - * @type {boolean}
    - * @private
    - */
    -goog.net.xpc.NativeMessagingTransport.prototype.initialized_ = false;
    -
    -
    -/**
    - * The transport type.
    - * @type {number}
    - * @override
    - */
    -goog.net.xpc.NativeMessagingTransport.prototype.transportType =
    -    goog.net.xpc.TransportTypes.NATIVE_MESSAGING;
    -
    -
    -/**
    - * The delimiter used for transport service messages.
    - * @type {string}
    - * @private
    - */
    -goog.net.xpc.NativeMessagingTransport.MESSAGE_DELIMITER_ = ',';
    -
    -
    -/**
    - * Tracks the number of NativeMessagingTransport channels that have been
    - * initialized but not disposed yet in a map keyed by the UID of the window
    - * object.  This allows for multiple windows to be initiallized and listening
    - * for messages.
    - * @type {Object<number>}
    - * @private
    - */
    -goog.net.xpc.NativeMessagingTransport.activeCount_ = {};
    -
    -
    -/**
    - * Id of a timer user during postMessage sends.
    - * @type {number}
    - * @private
    - */
    -goog.net.xpc.NativeMessagingTransport.prototype.sendTimerId_ = 0;
    -
    -
    -/**
    - * Checks whether the peer transport protocol version could be as indicated.
    - * @param {number} version The version to check for.
    - * @return {boolean} Whether the peer transport protocol version is as
    - *     indicated, or null.
    - * @private
    - */
    -goog.net.xpc.NativeMessagingTransport.prototype.couldPeerVersionBe_ =
    -    function(version) {
    -  return this.peerProtocolVersion_ == null ||
    -      this.peerProtocolVersion_ == version;
    -};
    -
    -
    -/**
    - * Initializes this transport. Registers a listener for 'message'-events
    - * on the document.
    - * @param {Window} listenWindow The window to listen to events on.
    - * @private
    - */
    -goog.net.xpc.NativeMessagingTransport.initialize_ = function(listenWindow) {
    -  var uid = goog.getUid(listenWindow);
    -  var value = goog.net.xpc.NativeMessagingTransport.activeCount_[uid];
    -  if (!goog.isNumber(value)) {
    -    value = 0;
    -  }
    -  if (value == 0) {
    -    // Listen for message-events. These are fired on window in FF3 and on
    -    // document in Opera.
    -    goog.events.listen(
    -        listenWindow.postMessage ? listenWindow : listenWindow.document,
    -        'message',
    -        goog.net.xpc.NativeMessagingTransport.messageReceived_,
    -        false,
    -        goog.net.xpc.NativeMessagingTransport);
    -  }
    -  goog.net.xpc.NativeMessagingTransport.activeCount_[uid] = value + 1;
    -};
    -
    -
    -/**
    - * Processes an incoming message-event.
    - * @param {goog.events.BrowserEvent} msgEvt The message event.
    - * @return {boolean} True if message was successfully delivered to a channel.
    - * @private
    - */
    -goog.net.xpc.NativeMessagingTransport.messageReceived_ = function(msgEvt) {
    -  var data = msgEvt.getBrowserEvent().data;
    -
    -  if (!goog.isString(data)) {
    -    return false;
    -  }
    -
    -  var headDelim = data.indexOf('|');
    -  var serviceDelim = data.indexOf(':');
    -
    -  // make sure we got something reasonable
    -  if (headDelim == -1 || serviceDelim == -1) {
    -    return false;
    -  }
    -
    -  var channelName = data.substring(0, headDelim);
    -  var service = data.substring(headDelim + 1, serviceDelim);
    -  var payload = data.substring(serviceDelim + 1);
    -
    -  goog.log.fine(goog.net.xpc.logger,
    -      'messageReceived: channel=' + channelName +
    -      ', service=' + service + ', payload=' + payload);
    -
    -  // Attempt to deliver message to the channel. Keep in mind that it may not
    -  // exist for several reasons, including but not limited to:
    -  //  - a malformed message
    -  //  - the channel simply has not been created
    -  //  - channel was created in a different namespace
    -  //  - message was sent to the wrong window
    -  //  - channel has become stale (e.g. caching iframes and back clicks)
    -  var channel = goog.net.xpc.channels[channelName];
    -  if (channel) {
    -    channel.xpcDeliver(service, payload,
    -        /** @type {!MessageEvent} */ (msgEvt.getBrowserEvent()).origin);
    -    return true;
    -  }
    -
    -  var transportMessageType =
    -      goog.net.xpc.NativeMessagingTransport.parseTransportPayload_(payload)[0];
    -
    -  // Check if there are any stale channel names that can be updated.
    -  for (var staleChannelName in goog.net.xpc.channels) {
    -    var staleChannel = goog.net.xpc.channels[staleChannelName];
    -    if (staleChannel.getRole() == goog.net.xpc.CrossPageChannelRole.INNER &&
    -        !staleChannel.isConnected() &&
    -        service == goog.net.xpc.TRANSPORT_SERVICE_ &&
    -        (transportMessageType == goog.net.xpc.SETUP ||
    -        transportMessageType == goog.net.xpc.SETUP_NTPV2)) {
    -      // Inner peer received SETUP message but channel names did not match.
    -      // Start using the channel name sent from outer peer. The channel name
    -      // of the inner peer can easily become out of date, as iframe's and their
    -      // JS state get cached in many browsers upon page reload or history
    -      // navigation (particularly Firefox 1.5+). We can trust the outer peer,
    -      // since we only accept postMessage messages from the same hostname that
    -      // originally setup the channel.
    -      staleChannel.updateChannelNameAndCatalog(channelName);
    -      staleChannel.xpcDeliver(service, payload);
    -      return true;
    -    }
    -  }
    -
    -  // Failed to find a channel to deliver this message to, so simply ignore it.
    -  goog.log.info(goog.net.xpc.logger, 'channel name mismatch; message ignored"');
    -  return false;
    -};
    -
    -
    -/**
    - * Handles transport service messages.
    - * @param {string} payload The message content.
    - * @override
    - */
    -goog.net.xpc.NativeMessagingTransport.prototype.transportServiceHandler =
    -    function(payload) {
    -  var transportParts =
    -      goog.net.xpc.NativeMessagingTransport.parseTransportPayload_(payload);
    -  var transportMessageType = transportParts[0];
    -  var peerEndpointId = transportParts[1];
    -  switch (transportMessageType) {
    -    case goog.net.xpc.SETUP_ACK_:
    -      this.setPeerProtocolVersion_(1);
    -      if (!this.setupAckReceived_.hasFired()) {
    -        this.setupAckReceived_.callback(true);
    -      }
    -      break;
    -    case goog.net.xpc.SETUP_ACK_NTPV2:
    -      if (this.protocolVersion_ == 2) {
    -        this.setPeerProtocolVersion_(2);
    -        if (!this.setupAckReceived_.hasFired()) {
    -          this.setupAckReceived_.callback(true);
    -        }
    -      }
    -      break;
    -    case goog.net.xpc.SETUP:
    -      this.setPeerProtocolVersion_(1);
    -      this.sendSetupAckMessage_(1);
    -      break;
    -    case goog.net.xpc.SETUP_NTPV2:
    -      if (this.protocolVersion_ == 2) {
    -        var prevPeerProtocolVersion = this.peerProtocolVersion_;
    -        this.setPeerProtocolVersion_(2);
    -        this.sendSetupAckMessage_(2);
    -        if ((prevPeerProtocolVersion == 1 || this.peerEndpointId_ != null) &&
    -            this.peerEndpointId_ != peerEndpointId) {
    -          // Send a new SETUP message since the peer has been replaced.
    -          goog.log.info(goog.net.xpc.logger,
    -              'Sending SETUP and changing peer ID to: ' + peerEndpointId);
    -          this.sendSetupMessage_();
    -        }
    -        this.peerEndpointId_ = peerEndpointId;
    -      }
    -      break;
    -  }
    -};
    -
    -
    -/**
    - * Sends a SETUP transport service message of the correct protocol number for
    - * our current situation.
    - * @private
    - */
    -goog.net.xpc.NativeMessagingTransport.prototype.sendSetupMessage_ =
    -    function() {
    -  // 'real' (legacy) v1 transports don't know about there being v2 ones out
    -  // there, and we shouldn't either.
    -  goog.asserts.assert(!(this.protocolVersion_ == 1 &&
    -      this.peerProtocolVersion_ == 2));
    -
    -  if (this.protocolVersion_ == 2 && this.couldPeerVersionBe_(2)) {
    -    var payload = goog.net.xpc.SETUP_NTPV2;
    -    payload += goog.net.xpc.NativeMessagingTransport.MESSAGE_DELIMITER_;
    -    payload += this.endpointId_;
    -    this.send(goog.net.xpc.TRANSPORT_SERVICE_, payload);
    -  }
    -
    -  // For backward compatibility reasons, the V1 SETUP message can be sent by
    -  // both V1 and V2 transports.  Once a V2 transport has 'heard' another V2
    -  // transport it starts ignoring V1 messages, so the V2 message must be sent
    -  // first.
    -  if (this.couldPeerVersionBe_(1)) {
    -    this.send(goog.net.xpc.TRANSPORT_SERVICE_, goog.net.xpc.SETUP);
    -  }
    -};
    -
    -
    -/**
    - * Sends a SETUP_ACK transport service message of the correct protocol number
    - * for our current situation.
    - * @param {number} protocolVersion The protocol version of the SETUP message
    - *     which gave rise to this ack message.
    - * @private
    - */
    -goog.net.xpc.NativeMessagingTransport.prototype.sendSetupAckMessage_ =
    -    function(protocolVersion) {
    -  goog.asserts.assert(this.protocolVersion_ != 1 || protocolVersion != 2,
    -      'Shouldn\'t try to send a v2 setup ack in v1 mode.');
    -  if (this.protocolVersion_ == 2 && this.couldPeerVersionBe_(2) &&
    -      protocolVersion == 2) {
    -    this.send(goog.net.xpc.TRANSPORT_SERVICE_, goog.net.xpc.SETUP_ACK_NTPV2);
    -  } else if (this.couldPeerVersionBe_(1) && protocolVersion == 1) {
    -    this.send(goog.net.xpc.TRANSPORT_SERVICE_, goog.net.xpc.SETUP_ACK_);
    -  } else {
    -    return;
    -  }
    -
    -  if (!this.setupAckSent_.hasFired()) {
    -    this.setupAckSent_.callback(true);
    -  }
    -};
    -
    -
    -/**
    - * Attempts to set the peer protocol number.  Downgrades from 2 to 1 are not
    - * permitted.
    - * @param {number} version The new protocol number.
    - * @private
    - */
    -goog.net.xpc.NativeMessagingTransport.prototype.setPeerProtocolVersion_ =
    -    function(version) {
    -  if (version > this.peerProtocolVersion_) {
    -    this.peerProtocolVersion_ = version;
    -  }
    -  if (this.peerProtocolVersion_ == 1) {
    -    if (!this.setupAckSent_.hasFired() && !this.oneSidedHandshake_) {
    -      this.setupAckSent_.callback(true);
    -    }
    -    this.peerEndpointId_ = null;
    -  }
    -};
    -
    -
    -/**
    - * Connects this transport.
    - * @override
    - */
    -goog.net.xpc.NativeMessagingTransport.prototype.connect = function() {
    -  goog.net.xpc.NativeMessagingTransport.initialize_(this.getWindow());
    -  this.initialized_ = true;
    -  this.maybeAttemptToConnect_();
    -};
    -
    -
    -/**
    - * Connects to other peer. In the case of the outer peer, the setup messages are
    - * likely sent before the inner peer is ready to receive them. Therefore, this
    - * function will continue trying to send the SETUP message until the inner peer
    - * responds. In the case of the inner peer, it will occasionally have its
    - * channel name fall out of sync with the outer peer, particularly during
    - * soft-reloads and history navigations.
    - * @private
    - */
    -goog.net.xpc.NativeMessagingTransport.prototype.maybeAttemptToConnect_ =
    -    function() {
    -  // In a one-sided handshake, the outer frame does not send a SETUP message,
    -  // but the inner frame does.
    -  var outerFrame = this.channel_.getRole() ==
    -      goog.net.xpc.CrossPageChannelRole.OUTER;
    -  if ((this.oneSidedHandshake_ && outerFrame) ||
    -      this.channel_.isConnected() ||
    -      this.isDisposed()) {
    -    this.maybeAttemptToConnectTimer_.stop();
    -    return;
    -  }
    -  this.maybeAttemptToConnectTimer_.start();
    -  this.sendSetupMessage_();
    -};
    -
    -
    -/**
    - * Sends a message.
    - * @param {string} service The name off the service the message is to be
    - * delivered to.
    - * @param {string} payload The message content.
    - * @override
    - */
    -goog.net.xpc.NativeMessagingTransport.prototype.send = function(service,
    -                                                                payload) {
    -  var win = this.channel_.getPeerWindowObject();
    -  if (!win) {
    -    goog.log.fine(goog.net.xpc.logger, 'send(): window not ready');
    -    return;
    -  }
    -
    -  this.send = function(service, payload) {
    -    // In IE8 (and perhaps elsewhere), it seems like postMessage is sometimes
    -    // implemented as a synchronous call.  That is, calling it synchronously
    -    // calls whatever listeners it has, and control is not returned to the
    -    // calling thread until those listeners are run.  This produces different
    -    // ordering to all other browsers, and breaks this protocol.  This timer
    -    // callback is introduced to produce standard behavior across all browsers.
    -    var transport = this;
    -    var channelName = this.channel_.name;
    -    var sendFunctor = function() {
    -      transport.sendTimerId_ = 0;
    -
    -      try {
    -        // postMessage is a method of the window object, except in some
    -        // versions of Opera, where it is a method of the document object.  It
    -        // also seems that the appearance of postMessage on the peer window
    -        // object can sometimes be delayed.
    -        var obj = win.postMessage ? win : win.document;
    -        if (!obj.postMessage) {
    -          goog.log.warning(goog.net.xpc.logger,
    -              'Peer window had no postMessage function.');
    -          return;
    -        }
    -
    -        obj.postMessage(channelName + '|' + service + ':' + payload,
    -            transport.peerHostname_);
    -        goog.log.fine(goog.net.xpc.logger, 'send(): service=' + service +
    -            ' payload=' + payload + ' to hostname=' + transport.peerHostname_);
    -      } catch (error) {
    -        // There is some evidence (not totally convincing) that postMessage can
    -        // be missing or throw errors during a narrow timing window during
    -        // startup.  This protects against that.
    -        goog.log.warning(goog.net.xpc.logger,
    -            'Error performing postMessage, ignoring.', error);
    -      }
    -    };
    -    this.sendTimerId_ = goog.Timer.callOnce(sendFunctor, 0);
    -  };
    -  this.send(service, payload);
    -};
    -
    -
    -/**
    - * Notify the channel that this transport is connected.  If either transport is
    - * protocol v1, a short delay is required to paper over timing vulnerabilities
    - * in that protocol version.
    - * @private
    - */
    -goog.net.xpc.NativeMessagingTransport.prototype.notifyConnected_ =
    -    function() {
    -  var delay = (this.protocolVersion_ == 1 || this.peerProtocolVersion_ == 1) ?
    -      goog.net.xpc.NativeMessagingTransport.CONNECTION_DELAY_MS_ : undefined;
    -  this.channel_.notifyConnected(delay);
    -};
    -
    -
    -/** @override */
    -goog.net.xpc.NativeMessagingTransport.prototype.disposeInternal = function() {
    -  if (this.initialized_) {
    -    var listenWindow = this.getWindow();
    -    var uid = goog.getUid(listenWindow);
    -    var value = goog.net.xpc.NativeMessagingTransport.activeCount_[uid];
    -    goog.net.xpc.NativeMessagingTransport.activeCount_[uid] = value - 1;
    -    if (value == 1) {
    -      goog.events.unlisten(
    -          listenWindow.postMessage ? listenWindow : listenWindow.document,
    -          'message',
    -          goog.net.xpc.NativeMessagingTransport.messageReceived_,
    -          false,
    -          goog.net.xpc.NativeMessagingTransport);
    -    }
    -  }
    -
    -  if (this.sendTimerId_) {
    -    goog.Timer.clear(this.sendTimerId_);
    -    this.sendTimerId_ = 0;
    -  }
    -
    -  goog.dispose(this.eventHandler_);
    -  delete this.eventHandler_;
    -
    -  goog.dispose(this.maybeAttemptToConnectTimer_);
    -  delete this.maybeAttemptToConnectTimer_;
    -
    -  this.setupAckReceived_.cancel();
    -  delete this.setupAckReceived_;
    -  this.setupAckSent_.cancel();
    -  delete this.setupAckSent_;
    -  this.connected_.cancel();
    -  delete this.connected_;
    -
    -  // Cleaning up this.send as it is an instance method, created in
    -  // goog.net.xpc.NativeMessagingTransport.prototype.send and has a closure over
    -  // this.channel_.peerWindowObject_.
    -  delete this.send;
    -
    -  goog.net.xpc.NativeMessagingTransport.base(this, 'disposeInternal');
    -};
    -
    -
    -/**
    - * Parse a transport service payload message.  For v1, it is simply expected to
    - * be 'SETUP' or 'SETUP_ACK'.  For v2, an example setup message is
    - * 'SETUP_NTPV2,abc123', where the second part is the endpoint id.  The v2 setup
    - * ack message is simply 'SETUP_ACK_NTPV2'.
    - * @param {string} payload The payload.
    - * @return {!Array<?string>} An array with the message type as the first member
    - *     and the endpoint id as the second, if one was sent, or null otherwise.
    - * @private
    - */
    -goog.net.xpc.NativeMessagingTransport.parseTransportPayload_ =
    -    function(payload) {
    -  var transportParts = /** @type {!Array<?string>} */ (payload.split(
    -      goog.net.xpc.NativeMessagingTransport.MESSAGE_DELIMITER_));
    -  transportParts[1] = transportParts[1] || null;
    -  return transportParts;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xpc/nativemessagingtransport_test.html b/src/database/third_party/closure-library/closure/goog/net/xpc/nativemessagingtransport_test.html
    deleted file mode 100644
    index 4edcb262c1d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xpc/nativemessagingtransport_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<!--
    --->
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   NativeMessagingTransport Unit-Tests
    -  </title>
    -  <script src="../../base.js" type="text/javascript">
    -  </script>
    -  <script>
    -    goog.require('goog.net.xpc.NativeMessagingTransportTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xpc/nativemessagingtransport_test.js b/src/database/third_party/closure-library/closure/goog/net/xpc/nativemessagingtransport_test.js
    deleted file mode 100644
    index cc904c9980d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xpc/nativemessagingtransport_test.js
    +++ /dev/null
    @@ -1,300 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.net.xpc.NativeMessagingTransportTest');
    -goog.setTestOnly('goog.net.xpc.NativeMessagingTransportTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.net.xpc');
    -goog.require('goog.net.xpc.CfgFields');
    -goog.require('goog.net.xpc.CrossPageChannel');
    -goog.require('goog.net.xpc.CrossPageChannelRole');
    -goog.require('goog.net.xpc.NativeMessagingTransport');
    -goog.require('goog.testing.jsunit');
    -
    -// This test only tests the native messaing transport protocol version 2.
    -// Testing of previous versions and of backward/forward compatibility is done
    -// in crosspagechannel_test.html.
    -
    -
    -function tearDown() {
    -  goog.net.xpc.NativeMessagingTransport.activeCount_ = {};
    -  goog.events.removeAll(window.postMessage ? window : document, 'message');
    -}
    -
    -
    -function testConstructor() {
    -  var xpc = getTestChannel();
    -
    -  var t = new goog.net.xpc.NativeMessagingTransport(xpc, 'http://g.com:80',
    -      undefined /* opt_domHelper */, false /* opt_oneSidedHandshake */,
    -      2 /* opt_protocolVersion */);
    -  assertEquals('http://g.com:80', t.peerHostname_);
    -
    -  var t = new goog.net.xpc.NativeMessagingTransport(xpc,
    -      null /* peerHostName */, undefined /* opt_domHelper */,
    -      false /* opt_oneSidedHandshake */, 2 /* opt_protocolVersion */);
    -  assertEquals('*', t.peerHostname_);
    -  t.dispose();
    -}
    -
    -
    -function testConstructorDom() {
    -  var xpc = getTestChannel();
    -
    -  var t = new goog.net.xpc.NativeMessagingTransport(
    -      xpc, 'http://g.com:80', goog.dom.getDomHelper(),
    -      false /* opt_oneSidedHandshake */, 2 /* opt_protocolVersion */);
    -  assertEquals('http://g.com:80', t.peerHostname_);
    -
    -  var t = new goog.net.xpc.NativeMessagingTransport(xpc,
    -      null /* peerHostName */, false /* opt_oneSidedHandshake */,
    -      2 /* opt_protocolVersion */);
    -  assertEquals('*', t.peerHostname_);
    -  t.dispose();
    -}
    -
    -
    -function testDispose() {
    -  var xpc = getTestChannel();
    -  var listenedObj = window.postMessage ? window : document;
    -
    -  var t0 = new goog.net.xpc.NativeMessagingTransport(xpc,
    -      null /* peerHostName */, false /* opt_oneSidedHandshake */,
    -      2 /* opt_protocolVersion */);
    -  assertEquals(0, goog.events.removeAll(listenedObj, 'message'));
    -  t0.dispose();
    -  assertEquals(0, goog.events.removeAll(listenedObj, 'message'));
    -
    -  var t1 = new goog.net.xpc.NativeMessagingTransport(xpc,
    -      null /* peerHostName */, false /* opt_oneSidedHandshake */,
    -      2 /* opt_protocolVersion */);
    -  t1.connect();
    -  t1.dispose();
    -  assertEquals(0, goog.events.removeAll(listenedObj, 'message'));
    -
    -  var t2 = new goog.net.xpc.NativeMessagingTransport(xpc,
    -      null /* peerHostName */, false /* opt_oneSidedHandshake */,
    -      2 /* opt_protocolVersion */);
    -  var t3 = new goog.net.xpc.NativeMessagingTransport(xpc,
    -      null /* peerHostName */, false /* opt_oneSidedHandshake */,
    -      2 /* opt_protocolVersion */);
    -  t2.connect();
    -  t3.connect();
    -  t2.dispose();
    -  assertEquals(1, goog.events.removeAll(listenedObj, 'message'));
    -}
    -
    -
    -function testDisposeWithDom() {
    -  var xpc = getTestChannel(goog.dom.getDomHelper());
    -  var listenedObj = window.postMessage ? window : document;
    -
    -  var t0 = new goog.net.xpc.NativeMessagingTransport(xpc,
    -      null /* peerHostName */, false /* opt_oneSidedHandshake */,
    -      2 /* opt_protocolVersion */);
    -  assertEquals(0, goog.events.removeAll(listenedObj, 'message'));
    -  t0.dispose();
    -  assertEquals(0, goog.events.removeAll(listenedObj, 'message'));
    -
    -  var t1 = new goog.net.xpc.NativeMessagingTransport(xpc,
    -      null /* peerHostName */, false /* opt_oneSidedHandshake */,
    -      2 /* opt_protocolVersion */);
    -  t1.connect();
    -  t1.dispose();
    -  assertEquals(0, goog.events.removeAll(listenedObj, 'message'));
    -
    -  var t2 = new goog.net.xpc.NativeMessagingTransport(xpc,
    -      null /* peerHostName */, false /* opt_oneSidedHandshake */,
    -      2 /* opt_protocolVersion */);
    -  var t3 = new goog.net.xpc.NativeMessagingTransport(xpc,
    -      null /* peerHostName */, false /* opt_oneSidedHandshake */,
    -      2 /* opt_protocolVersion */);
    -  t2.connect();
    -  t3.connect();
    -  t2.dispose();
    -  assertEquals(1, goog.events.removeAll(listenedObj, 'message'));
    -}
    -
    -
    -function testBogusMessages() {
    -  var e = createMockEvent('bogus_message');
    -  assertFalse(goog.net.xpc.NativeMessagingTransport.messageReceived_(e));
    -
    -  e = createMockEvent('bogus|message');
    -  assertFalse(goog.net.xpc.NativeMessagingTransport.messageReceived_(e));
    -
    -  e = createMockEvent('bogus|message:data');
    -  assertFalse(goog.net.xpc.NativeMessagingTransport.messageReceived_(e));
    -}
    -
    -
    -function testSendingMessagesToUnconnectedInnerPeer() {
    -  var xpc = getTestChannel();
    -
    -  var serviceResult, payloadResult;
    -  xpc.xpcDeliver = function(service, payload) {
    -    serviceResult = service;
    -    payloadResult = payload;
    -  };
    -
    -  // Construct an unconnected inner peer.
    -  xpc.getRole = function() {
    -    return goog.net.xpc.CrossPageChannelRole.INNER;
    -  };
    -  xpc.isConnected = function() {
    -    return false;
    -  };
    -  var t = new goog.net.xpc.NativeMessagingTransport(xpc, 'http://g.com',
    -      false /* opt_oneSidedHandshake */, 2 /* opt_protocolVersion */);
    -
    -  // Test a valid message.
    -  var e = createMockEvent('test_channel|test_service:test_payload');
    -  assertTrue(goog.net.xpc.NativeMessagingTransport.messageReceived_(e));
    -  assertEquals('test_service', serviceResult);
    -  assertEquals('test_payload', payloadResult);
    -  assertEquals('Ensure channel name has not been changed.',
    -               'test_channel',
    -               t.channel_.name);
    -
    -  // Test updating a stale inner peer.
    -  var e = createMockEvent('new_channel|tp:SETUP');
    -  assertTrue(goog.net.xpc.NativeMessagingTransport.messageReceived_(e));
    -  assertEquals('tp', serviceResult);
    -  assertEquals('SETUP', payloadResult);
    -  assertEquals('Ensure channel name has been updated.',
    -               'new_channel',
    -               t.channel_.name);
    -  t.dispose();
    -}
    -
    -
    -function testSignalConnected_innerFrame() {
    -  checkSignalConnected(false /* oneSidedHandshake */,
    -      true /* innerFrame */);
    -}
    -
    -
    -function testSignalConnected_outerFrame() {
    -  checkSignalConnected(false /* oneSidedHandshake */,
    -      false /* innerFrame */);
    -}
    -
    -
    -function testSignalConnected_singleSided_innerFrame() {
    -  checkSignalConnected(true /* oneSidedHandshake */,
    -      true /* innerFrame */);
    -}
    -
    -
    -function testSignalConnected_singleSided_outerFrame() {
    -  checkSignalConnected(true /* oneSidedHandshake */,
    -      false /* innerFrame */);
    -}
    -
    -
    -function checkSignalConnected(oneSidedHandshake, innerFrame,
    -    peerProtocolVersion, protocolVersion) {
    -  var xpc = getTestChannel();
    -  var connected = false;
    -  xpc.notifyConnected = function() {
    -    if (connected) {
    -      fail();
    -    } else {
    -      connected = true;
    -    }
    -  };
    -  xpc.getRole = function() {
    -    return innerFrame ? goog.net.xpc.CrossPageChannelRole.INNER :
    -        goog.net.xpc.CrossPageChannelRole.OUTER;
    -  };
    -  xpc.isConnected = function() {
    -    return false;
    -  };
    -
    -  var transport = new goog.net.xpc.NativeMessagingTransport(xpc, 'http://g.com',
    -      undefined /* opt_domHelper */,
    -      oneSidedHandshake /* opt_oneSidedHandshake */,
    -      2 /* protocolVerion */);
    -  var sentPayloads = [];
    -  transport.send = function(service, payload) {
    -    assertEquals(goog.net.xpc.TRANSPORT_SERVICE_, service);
    -    sentPayloads.push(payload);
    -  };
    -  function assertSent(payloads) {
    -    assertArrayEquals(payloads, sentPayloads);
    -    sentPayloads = [];
    -  }
    -  var endpointId = transport.endpointId_;
    -  var peerEndpointId1 = 'abc123';
    -  var peerEndpointId2 = 'def234';
    -
    -  assertFalse(connected);
    -  if (!oneSidedHandshake || innerFrame) {
    -    transport.transportServiceHandler(goog.net.xpc.SETUP_NTPV2 + ',' +
    -        peerEndpointId1);
    -    transport.transportServiceHandler(goog.net.xpc.SETUP);
    -    assertSent([goog.net.xpc.SETUP_ACK_NTPV2]);
    -    assertFalse(connected);
    -    transport.transportServiceHandler(goog.net.xpc.SETUP_ACK_NTPV2);
    -    assertSent([]);
    -    assertTrue(connected);
    -  } else {
    -    transport.transportServiceHandler(goog.net.xpc.SETUP_ACK_NTPV2);
    -    assertSent([]);
    -    assertFalse(connected);
    -    transport.transportServiceHandler(goog.net.xpc.SETUP_NTPV2 + ',' +
    -        peerEndpointId1);
    -    transport.transportServiceHandler(goog.net.xpc.SETUP);
    -    assertSent([goog.net.xpc.SETUP_ACK_NTPV2]);
    -    assertTrue(connected);
    -  }
    -
    -  // Verify that additional transport service traffic doesn't cause duplicate
    -  // notifications.
    -  transport.transportServiceHandler(goog.net.xpc.SETUP_NTPV2 + ',' +
    -      peerEndpointId1);
    -  transport.transportServiceHandler(goog.net.xpc.SETUP);
    -  assertSent([goog.net.xpc.SETUP_ACK_NTPV2]);
    -  transport.transportServiceHandler(goog.net.xpc.SETUP_ACK_NTPV2);
    -  assertSent([]);
    -
    -  // Simulate a reconnection by sending a SETUP message from a frame with a
    -  // different endpoint id.  No further connection callbacks should fire, but
    -  // a new SETUP message should be triggered.
    -  transport.transportServiceHandler(goog.net.xpc.SETUP_NTPV2 + ',' +
    -      peerEndpointId2);
    -  transport.transportServiceHandler(goog.net.xpc.SETUP);
    -  assertSent([goog.net.xpc.SETUP_ACK_NTPV2, goog.net.xpc.SETUP_NTPV2 + ',' +
    -        endpointId]);
    -  transport.transportServiceHandler(goog.net.xpc.SETUP_ACK_NTPV2);
    -  assertSent([]);
    -}
    -
    -
    -function createMockEvent(data) {
    -  var event = {};
    -  event.getBrowserEvent = function() { return {data: data} };
    -  return event;
    -}
    -
    -
    -function getTestChannel(opt_domHelper) {
    -  var cfg = {};
    -  cfg[goog.net.xpc.CfgFields.CHANNEL_NAME] = 'test_channel';
    -  return new goog.net.xpc.CrossPageChannel(cfg, opt_domHelper,
    -      undefined /* opt_domHelper */, false /* opt_oneSidedHandshake */,
    -      2 /* opt_protocolVersion */);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xpc/nixtransport.js b/src/database/third_party/closure-library/closure/goog/net/xpc/nixtransport.js
    deleted file mode 100644
    index a7639c0c498..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xpc/nixtransport.js
    +++ /dev/null
    @@ -1,483 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Contains the NIX (Native IE XDC) method transport for
    - * cross-domain communication. It exploits the fact that Internet Explorer
    - * allows a window that is the parent of an iframe to set said iframe window's
    - * opener property to an object. This object can be a function that in turn
    - * can be used to send a message despite same-origin constraints. Note that
    - * this function, if a pure JavaScript object, opens up the possibilitiy of
    - * gaining a hold of the context of the other window and in turn, attacking
    - * it. This implementation therefore wraps the JavaScript objects used inside
    - * a VBScript class. Since VBScript objects are passed in JavaScript as a COM
    - * wrapper (like DOM objects), they are thus opaque to JavaScript
    - * (except for the interface they expose). This therefore provides a safe
    - * method of transport.
    - *
    - *
    - * Initially based on FrameElementTransport which shares some similarities
    - * to this method.
    - */
    -
    -goog.provide('goog.net.xpc.NixTransport');
    -
    -goog.require('goog.log');
    -goog.require('goog.net.xpc');
    -goog.require('goog.net.xpc.CfgFields');
    -goog.require('goog.net.xpc.CrossPageChannelRole');
    -goog.require('goog.net.xpc.Transport');
    -goog.require('goog.net.xpc.TransportTypes');
    -goog.require('goog.reflect');
    -
    -
    -
    -/**
    - * NIX method transport.
    - *
    - * NOTE(user): NIX method tested in all IE versions starting from 6.0.
    - *
    - * @param {goog.net.xpc.CrossPageChannel} channel The channel this transport
    - *     belongs to.
    - * @param {goog.dom.DomHelper=} opt_domHelper The dom helper to use for finding
    - *     the correct window.
    - * @constructor
    - * @extends {goog.net.xpc.Transport}
    - * @final
    - */
    -goog.net.xpc.NixTransport = function(channel, opt_domHelper) {
    -  goog.net.xpc.NixTransport.base(this, 'constructor', opt_domHelper);
    -
    -  /**
    -   * The channel this transport belongs to.
    -   * @type {goog.net.xpc.CrossPageChannel}
    -   * @private
    -   */
    -  this.channel_ = channel;
    -
    -  /**
    -   * The authorization token, if any, used by this transport.
    -   * @type {?string}
    -   * @private
    -   */
    -  this.authToken_ = channel[goog.net.xpc.CfgFields.AUTH_TOKEN] || '';
    -
    -  /**
    -   * The authorization token, if any, that must be sent by the other party
    -   * for setup to occur.
    -   * @type {?string}
    -   * @private
    -   */
    -  this.remoteAuthToken_ =
    -      channel[goog.net.xpc.CfgFields.REMOTE_AUTH_TOKEN] || '';
    -
    -  // Conduct the setup work for NIX in general, if need be.
    -  goog.net.xpc.NixTransport.conductGlobalSetup_(this.getWindow());
    -
    -  // Setup aliases so that VBScript can call these methods
    -  // on the transport class, even if they are renamed during
    -  // compression.
    -  this[goog.net.xpc.NixTransport.NIX_HANDLE_MESSAGE] = this.handleMessage_;
    -  this[goog.net.xpc.NixTransport.NIX_CREATE_CHANNEL] = this.createChannel_;
    -};
    -goog.inherits(goog.net.xpc.NixTransport, goog.net.xpc.Transport);
    -
    -
    -// Consts for NIX. VBScript doesn't allow items to start with _ for some
    -// reason, so we need to make these names quite unique, as they will go into
    -// the global namespace.
    -
    -
    -/**
    - * Global name of the Wrapper VBScript class.
    - * Note that this class will be stored in the *global*
    - * namespace (i.e. window in browsers).
    - * @type {string}
    - */
    -goog.net.xpc.NixTransport.NIX_WRAPPER = 'GCXPC____NIXVBS_wrapper';
    -
    -
    -/**
    - * Global name of the GetWrapper VBScript function. This
    - * constant is used by JavaScript to call this function.
    - * Note that this function will be stored in the *global*
    - * namespace (i.e. window in browsers).
    - * @type {string}
    - */
    -goog.net.xpc.NixTransport.NIX_GET_WRAPPER = 'GCXPC____NIXVBS_get_wrapper';
    -
    -
    -/**
    - * The name of the handle message method used by the wrapper class
    - * when calling the transport.
    - * @type {string}
    - */
    -goog.net.xpc.NixTransport.NIX_HANDLE_MESSAGE = 'GCXPC____NIXJS_handle_message';
    -
    -
    -/**
    - * The name of the create channel method used by the wrapper class
    - * when calling the transport.
    - * @type {string}
    - */
    -goog.net.xpc.NixTransport.NIX_CREATE_CHANNEL = 'GCXPC____NIXJS_create_channel';
    -
    -
    -/**
    - * A "unique" identifier that is stored in the wrapper
    - * class so that the wrapper can be distinguished from
    - * other objects easily.
    - * @type {string}
    - */
    -goog.net.xpc.NixTransport.NIX_ID_FIELD = 'GCXPC____NIXVBS_container';
    -
    -
    -/**
    - * Determines if the installed version of IE supports accessing window.opener
    - * after it has been set to a non-Window/null value. NIX relies on this being
    - * possible.
    - * @return {boolean} Whether window.opener behavior is compatible with NIX.
    - */
    -goog.net.xpc.NixTransport.isNixSupported = function() {
    -  var isSupported = false;
    -  try {
    -    var oldOpener = window.opener;
    -    // The compiler complains (as it should!) if we set window.opener to
    -    // something other than a window or null.
    -    window.opener = /** @type {Window} */ ({});
    -    isSupported = goog.reflect.canAccessProperty(window, 'opener');
    -    window.opener = oldOpener;
    -  } catch (e) { }
    -  return isSupported;
    -};
    -
    -
    -/**
    - * Conducts the global setup work for the NIX transport method.
    - * This function creates and then injects into the page the
    - * VBScript code necessary to create the NIX wrapper class.
    - * Note that this method can be called multiple times, as
    - * it internally checks whether the work is necessary before
    - * proceeding.
    - * @param {Window} listenWindow The window containing the affected page.
    - * @private
    - */
    -goog.net.xpc.NixTransport.conductGlobalSetup_ = function(listenWindow) {
    -  if (listenWindow['nix_setup_complete']) {
    -    return;
    -  }
    -
    -  // Inject the VBScript code needed.
    -  var vbscript =
    -      // We create a class to act as a wrapper for
    -      // a Javascript call, to prevent a break in of
    -      // the context.
    -      'Class ' + goog.net.xpc.NixTransport.NIX_WRAPPER + '\n ' +
    -
    -      // An internal member for keeping track of the
    -      // transport for which this wrapper exists.
    -      'Private m_Transport\n' +
    -
    -      // An internal member for keeping track of the
    -      // auth token associated with the context that
    -      // created this wrapper. Used for validation
    -      // purposes.
    -      'Private m_Auth\n' +
    -
    -      // Method for internally setting the value
    -      // of the m_Transport property. We have the
    -      // isEmpty check to prevent the transport
    -      // from being overridden with an illicit
    -      // object by a malicious party.
    -      'Public Sub SetTransport(transport)\n' +
    -      'If isEmpty(m_Transport) Then\n' +
    -      'Set m_Transport = transport\n' +
    -      'End If\n' +
    -      'End Sub\n' +
    -
    -      // Method for internally setting the value
    -      // of the m_Auth property. We have the
    -      // isEmpty check to prevent the transport
    -      // from being overridden with an illicit
    -      // object by a malicious party.
    -      'Public Sub SetAuth(auth)\n' +
    -      'If isEmpty(m_Auth) Then\n' +
    -      'm_Auth = auth\n' +
    -      'End If\n' +
    -      'End Sub\n' +
    -
    -      // Returns the auth token to the gadget, so it can
    -      // confirm a match before initiating the connection
    -      'Public Function GetAuthToken()\n ' +
    -      'GetAuthToken = m_Auth\n' +
    -      'End Function\n' +
    -
    -      // A wrapper method which causes a
    -      // message to be sent to the other context.
    -      'Public Sub SendMessage(service, payload)\n ' +
    -      'Call m_Transport.' +
    -      goog.net.xpc.NixTransport.NIX_HANDLE_MESSAGE + '(service, payload)\n' +
    -      'End Sub\n' +
    -
    -      // Method for setting up the inner->outer
    -      // channel.
    -      'Public Sub CreateChannel(channel)\n ' +
    -      'Call m_Transport.' +
    -      goog.net.xpc.NixTransport.NIX_CREATE_CHANNEL + '(channel)\n' +
    -      'End Sub\n' +
    -
    -      // An empty field with a unique identifier to
    -      // prevent the code from confusing this wrapper
    -      // with a run-of-the-mill value found in window.opener.
    -      'Public Sub ' + goog.net.xpc.NixTransport.NIX_ID_FIELD + '()\n ' +
    -      'End Sub\n' +
    -      'End Class\n ' +
    -
    -      // Function to get a reference to the wrapper.
    -      'Function ' +
    -      goog.net.xpc.NixTransport.NIX_GET_WRAPPER + '(transport, auth)\n' +
    -      'Dim wrap\n' +
    -      'Set wrap = New ' + goog.net.xpc.NixTransport.NIX_WRAPPER + '\n' +
    -      'wrap.SetTransport transport\n' +
    -      'wrap.SetAuth auth\n' +
    -      'Set ' + goog.net.xpc.NixTransport.NIX_GET_WRAPPER + ' = wrap\n' +
    -      'End Function';
    -
    -  try {
    -    listenWindow.execScript(vbscript, 'vbscript');
    -    listenWindow['nix_setup_complete'] = true;
    -  }
    -  catch (e) {
    -    goog.log.error(goog.net.xpc.logger,
    -        'exception caught while attempting global setup: ' + e);
    -  }
    -};
    -
    -
    -/**
    - * The transport type.
    - * @type {number}
    - * @protected
    - * @override
    - */
    -goog.net.xpc.NixTransport.prototype.transportType =
    -    goog.net.xpc.TransportTypes.NIX;
    -
    -
    -/**
    - * Keeps track of whether the local setup has completed (i.e.
    - * the initial work towards setting the channel up has been
    - * completed for this end).
    - * @type {boolean}
    - * @private
    - */
    -goog.net.xpc.NixTransport.prototype.localSetupCompleted_ = false;
    -
    -
    -/**
    - * The NIX channel used to talk to the other page. This
    - * object is in fact a reference to a VBScript class
    - * (see above) and as such, is in fact a COM wrapper.
    - * When using this object, make sure to not access methods
    - * without calling them, otherwise a COM error will be thrown.
    - * @type {Object}
    - * @private
    - */
    -goog.net.xpc.NixTransport.prototype.nixChannel_ = null;
    -
    -
    -/**
    - * Connect this transport.
    - * @override
    - */
    -goog.net.xpc.NixTransport.prototype.connect = function() {
    -  if (this.channel_.getRole() == goog.net.xpc.CrossPageChannelRole.OUTER) {
    -    this.attemptOuterSetup_();
    -  } else {
    -    this.attemptInnerSetup_();
    -  }
    -};
    -
    -
    -/**
    - * Attempts to setup the channel from the perspective
    - * of the outer (read: container) page. This method
    - * will attempt to create a NIX wrapper for this transport
    - * and place it into the "opener" property of the inner
    - * page's window object. If it fails, it will continue
    - * to loop until it does so.
    - *
    - * @private
    - */
    -goog.net.xpc.NixTransport.prototype.attemptOuterSetup_ = function() {
    -  if (this.localSetupCompleted_) {
    -    return;
    -  }
    -
    -  // Get shortcut to iframe-element that contains the inner
    -  // page.
    -  var innerFrame = this.channel_.getIframeElement();
    -
    -  try {
    -    // Attempt to place the NIX wrapper object into the inner
    -    // frame's opener property.
    -    var theWindow = this.getWindow();
    -    var getWrapper = theWindow[goog.net.xpc.NixTransport.NIX_GET_WRAPPER];
    -    innerFrame.contentWindow.opener = getWrapper(this, this.authToken_);
    -    this.localSetupCompleted_ = true;
    -  }
    -  catch (e) {
    -    goog.log.error(goog.net.xpc.logger,
    -        'exception caught while attempting setup: ' + e);
    -  }
    -
    -  // If the retry is necessary, reattempt this setup.
    -  if (!this.localSetupCompleted_) {
    -    this.getWindow().setTimeout(goog.bind(this.attemptOuterSetup_, this), 100);
    -  }
    -};
    -
    -
    -/**
    - * Attempts to setup the channel from the perspective
    - * of the inner (read: iframe) page. This method
    - * will attempt to *read* the opener object from the
    - * page's opener property. If it succeeds, this object
    - * is saved into nixChannel_ and the channel is confirmed
    - * with the container by calling CreateChannel with an instance
    - * of a wrapper for *this* page. Note that if this method
    - * fails, it will continue to loop until it succeeds.
    - *
    - * @private
    - */
    -goog.net.xpc.NixTransport.prototype.attemptInnerSetup_ = function() {
    -  if (this.localSetupCompleted_) {
    -    return;
    -  }
    -
    -  try {
    -    var opener = this.getWindow().opener;
    -
    -    // Ensure that the object contained inside the opener
    -    // property is in fact a NIX wrapper.
    -    if (opener && goog.net.xpc.NixTransport.NIX_ID_FIELD in opener) {
    -      this.nixChannel_ = opener;
    -
    -      // Ensure that the NIX channel given to use is valid.
    -      var remoteAuthToken = this.nixChannel_['GetAuthToken']();
    -
    -      if (remoteAuthToken != this.remoteAuthToken_) {
    -        goog.log.error(goog.net.xpc.logger,
    -            'Invalid auth token from other party');
    -        return;
    -      }
    -
    -      // Complete the construction of the channel by sending our own
    -      // wrapper to the container via the channel they gave us.
    -      var theWindow = this.getWindow();
    -      var getWrapper = theWindow[goog.net.xpc.NixTransport.NIX_GET_WRAPPER];
    -      this.nixChannel_['CreateChannel'](getWrapper(this, this.authToken_));
    -
    -      this.localSetupCompleted_ = true;
    -
    -      // Notify channel that the transport is ready.
    -      this.channel_.notifyConnected();
    -    }
    -  }
    -  catch (e) {
    -    goog.log.error(goog.net.xpc.logger,
    -        'exception caught while attempting setup: ' + e);
    -    return;
    -  }
    -
    -  // If the retry is necessary, reattempt this setup.
    -  if (!this.localSetupCompleted_) {
    -    this.getWindow().setTimeout(goog.bind(this.attemptInnerSetup_, this), 100);
    -  }
    -};
    -
    -
    -/**
    - * Internal method called by the inner page, via the
    - * NIX wrapper, to complete the setup of the channel.
    - *
    - * @param {Object} channel The NIX wrapper of the
    - *  inner page.
    - * @private
    - */
    -goog.net.xpc.NixTransport.prototype.createChannel_ = function(channel) {
    -  // Verify that the channel is in fact a NIX wrapper.
    -  if (typeof channel != 'unknown' ||
    -      !(goog.net.xpc.NixTransport.NIX_ID_FIELD in channel)) {
    -    goog.log.error(goog.net.xpc.logger,
    -        'Invalid NIX channel given to createChannel_');
    -  }
    -
    -  this.nixChannel_ = channel;
    -
    -  // Ensure that the NIX channel given to use is valid.
    -  var remoteAuthToken = this.nixChannel_['GetAuthToken']();
    -
    -  if (remoteAuthToken != this.remoteAuthToken_) {
    -    goog.log.error(goog.net.xpc.logger, 'Invalid auth token from other party');
    -    return;
    -  }
    -
    -  // Indicate to the CrossPageChannel that the channel is setup
    -  // and ready to use.
    -  this.channel_.notifyConnected();
    -};
    -
    -
    -/**
    - * Internal method called by the other page, via the NIX wrapper,
    - * to deliver a message.
    - * @param {string} serviceName The name of the service the message is to be
    - *   delivered to.
    - * @param {string} payload The message to process.
    - * @private
    - */
    -goog.net.xpc.NixTransport.prototype.handleMessage_ =
    -    function(serviceName, payload) {
    -  /** @this {goog.net.xpc.NixTransport} */
    -  var deliveryHandler = function() {
    -    this.channel_.xpcDeliver(serviceName, payload);
    -  };
    -  this.getWindow().setTimeout(goog.bind(deliveryHandler, this), 1);
    -};
    -
    -
    -/**
    - * Sends a message.
    - * @param {string} service The name of the service the message is to be
    - *   delivered to.
    - * @param {string} payload The message content.
    - * @override
    - */
    -goog.net.xpc.NixTransport.prototype.send = function(service, payload) {
    -  // Verify that the NIX channel we have is valid.
    -  if (typeof(this.nixChannel_) !== 'unknown') {
    -    goog.log.error(goog.net.xpc.logger, 'NIX channel not connected');
    -  }
    -
    -  // Send the message via the NIX wrapper object.
    -  this.nixChannel_['SendMessage'](service, payload);
    -};
    -
    -
    -/** @override */
    -goog.net.xpc.NixTransport.prototype.disposeInternal = function() {
    -  goog.net.xpc.NixTransport.base(this, 'disposeInternal');
    -  this.nixChannel_ = null;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xpc/relay.js b/src/database/third_party/closure-library/closure/goog/net/xpc/relay.js
    deleted file mode 100644
    index 03238b672e9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xpc/relay.js
    +++ /dev/null
    @@ -1,73 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Standalone script to be included in the relay-document
    - * used by goog.net.xpc.IframeRelayTransport. This script will decode the
    - * fragment identifier, determine the target window object and deliver
    - * the data to it.
    - *
    - */
    -
    -/** @suppress {extraProvide} */
    -goog.provide('goog.net.xpc.relay');
    -
    -(function() {
    -  // Decode the fragement identifier.
    -  // location.href is expected to be structured as follows:
    -  // <url>#<channel_name>[,<iframe_id>]|<data>
    -
    -  // Get the fragment identifier.
    -  var raw = window.location.hash;
    -  if (!raw) {
    -    return;
    -  }
    -  if (raw.charAt(0) == '#') {
    -    raw = raw.substring(1);
    -  }
    -  var pos = raw.indexOf('|');
    -  var head = raw.substring(0, pos).split(',');
    -  var channelName = head[0];
    -  var iframeId = head.length == 2 ? head[1] : null;
    -  var frame = raw.substring(pos + 1);
    -
    -  // Find the window object of the peer.
    -  //
    -  // The general structure of the frames looks like this:
    -  // - peer1
    -  //   - relay2
    -  //   - peer2
    -  //     - relay1
    -  //
    -  // We are either relay1 or relay2.
    -
    -  var win;
    -  if (iframeId) {
    -    // We are relay2 and need to deliver the data to peer2.
    -    win = window.parent.frames[iframeId];
    -  } else {
    -    // We are relay1 and need to deliver the data to peer1.
    -    win = window.parent.parent;
    -  }
    -
    -  // Deliver the data.
    -  try {
    -    win['xpcRelay'](channelName, frame);
    -  } catch (e) {
    -    // Nothing useful can be done here.
    -    // It would be great to inform the sender the delivery of this message
    -    // failed, but this is not possible because we are already in the receiver's
    -    // domain at this point.
    -  }
    -})();
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xpc/testdata/access_checker.html b/src/database/third_party/closure-library/closure/goog/net/xpc/testdata/access_checker.html
    deleted file mode 100644
    index 10a421e1676..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xpc/testdata/access_checker.html
    +++ /dev/null
    @@ -1,29 +0,0 @@
    -<!DOCTYPE html>
    -<!--
    -
    -   This file checks whether the current browser can access properties from same
    -   domain iframes. This is currently a problem on the matrix brower ie6 and xp.
    -   For some reason it can't access same domain iframes.
    -   TODO(user): Figure out why it can't.
    -  -->
    -<html>
    -  <!--
    -     Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -     Use of this source code is governed by the Apache License, Version 2.0.
    -     See the COPYING file for details.
    -    -->
    -  <head>
    -    <title>The access checking iframe</title>
    -  </head>
    -  <body>
    -    <script type="text/javascript">
    -      try {
    -        var sameDomainIframeHref = parent.frames['nonexistant'].location.href;
    -        parent.sameDomainIframeAccessComplete(true);
    -      } catch (e) {
    -        parent.sameDomainIframeAccessComplete(false);
    -      }
    -    </script>
    -  </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xpc/testdata/inner_peer.html b/src/database/third_party/closure-library/closure/goog/net/xpc/testdata/inner_peer.html
    deleted file mode 100644
    index ce6506a9a08..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xpc/testdata/inner_peer.html
    +++ /dev/null
    @@ -1,99 +0,0 @@
    -<!DOCTYPE html>
    -<!--
    -
    -  This file is responsible for setting up the inner peer half of an XPC
    -  communication channel. It instantiates a CrossPageChannel and attempts to
    -  connect to the outer peer. The XPC configuration should match that of the
    -  outer peer (i.e. same channel name, polling URIs, etc).
    --->
    -<html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -
    -<head>
    -<title>XPC test inner frame</title>
    -<script src="../../../base.js" type="text/javascript"></script>
    -<script type="text/javascript">
    -goog.require('goog.debug.Logger');
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.EventType');
    -goog.require('goog.net.xpc.CrossPageChannel');
    -</script>
    -<script type="text/javascript">
    -var channel;
    -var queuedMessage;
    -
    -var OBJECT_RESULT_FROM_SERVICE = {'favorites': 'pie'};
    -
    -function clearDebug() {
    -  document.getElementById('debugDiv').innerHTML = '';
    -}
    -
    -function instantiateChannel(cfg) {
    -  if (window.channel) {
    -    window.channel.dispose();
    -  }
    -  window.channel = new goog.net.xpc.CrossPageChannel(cfg);
    -  window.channel.registerService('echo', echoHandler);
    -  window.channel.registerService('response', responseHandler);
    -  connectChannel(
    -      parent.driver && parent.driver.innerFrameConnected ?
    -      goog.bind(parent.driver.innerFrameConnected, parent.driver) : null);
    -}
    -
    -function connectChannel(opt_callback) {
    -  window.channel.connect(opt_callback || goog.nullFunction);
    -}
    -
    -function sendEcho(payload) {
    -  window.channel.send('echo', payload);
    -}
    -
    -function echoHandler(payload) {
    -  window.channel.send('response', payload);
    -  return OBJECT_RESULT_FROM_SERVICE;
    -}
    -
    -function isConnected() {
    -  return window.channel && window.channel.isConnected();
    -}
    -
    -function responseHandler(payload) {
    -  if (parent.driver && parent.driver.innerFrameGotResponse) {
    -    parent.driver.innerFrameGotResponse(payload);
    -  }
    -}
    -
    -</script>
    -</head>
    -
    -<body>
    -
    -<div style="position:absolute">
    -  Debug [<a href="#" onclick="clearDebug()">clear</a>]: <br>
    -  <div id=debugDiv style="border: 1px #000000 solid; font-size:xx-small"></div>
    -</div>
    -
    -<script type="text/javascript">
    -var debugDiv = goog.dom.getElement('debugDiv');
    -var logger = goog.debug.Logger.getLogger('goog.net.xpc');
    -logger.setLevel(goog.debug.Logger.Level.ALL);
    -logger.addHandler(function(logRecord) {
    -  var msgElm = goog.dom.createDom('div');
    -  msgElm.innerHTML = logRecord.getMessage();
    -  goog.dom.appendChild(debugDiv, msgElm);
    -});
    -
    -if (parent && parent.iframeLoadHandler) {
    -  parent.iframeLoadHandler();
    -}
    -</script>
    -
    -</body>
    -
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xpc/transport.js b/src/database/third_party/closure-library/closure/goog/net/xpc/transport.js
    deleted file mode 100644
    index edb14611f8e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xpc/transport.js
    +++ /dev/null
    @@ -1,105 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Contains the base class for transports.
    - *
    - */
    -
    -
    -goog.provide('goog.net.xpc.Transport');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.dom');
    -goog.require('goog.net.xpc.TransportNames');
    -
    -
    -
    -/**
    - * The base class for transports.
    - * @param {goog.dom.DomHelper=} opt_domHelper The dom helper to use for
    - *     finding the window objects.
    - * @constructor
    - * @extends {goog.Disposable};
    - */
    -goog.net.xpc.Transport = function(opt_domHelper) {
    -  goog.Disposable.call(this);
    -
    -  /**
    -   * The dom helper to use for finding the window objects to reference.
    -   * @type {goog.dom.DomHelper}
    -   * @private
    -   */
    -  this.domHelper_ = opt_domHelper || goog.dom.getDomHelper();
    -};
    -goog.inherits(goog.net.xpc.Transport, goog.Disposable);
    -
    -
    -/**
    - * The transport type.
    - * @type {number}
    - * @protected
    - */
    -goog.net.xpc.Transport.prototype.transportType = 0;
    -
    -
    -/**
    - * @return {number} The transport type identifier.
    - */
    -goog.net.xpc.Transport.prototype.getType = function() {
    -  return this.transportType;
    -};
    -
    -
    -/**
    - * Returns the window associated with this transport instance.
    - * @return {!Window} The window to use.
    - */
    -goog.net.xpc.Transport.prototype.getWindow = function() {
    -  return this.domHelper_.getWindow();
    -};
    -
    -
    -/**
    - * Return the transport name.
    - * @return {string} the transport name.
    - */
    -goog.net.xpc.Transport.prototype.getName = function() {
    -  return goog.net.xpc.TransportNames[String(this.transportType)] || '';
    -};
    -
    -
    -/**
    - * Handles transport service messages (internal signalling).
    - * @param {string} payload The message content.
    - */
    -goog.net.xpc.Transport.prototype.transportServiceHandler = goog.abstractMethod;
    -
    -
    -/**
    - * Connects this transport.
    - * The transport implementation is expected to call
    - * CrossPageChannel.prototype.notifyConnected when the channel is ready
    - * to be used.
    - */
    -goog.net.xpc.Transport.prototype.connect = goog.abstractMethod;
    -
    -
    -/**
    - * Sends a message.
    - * @param {string} service The name off the service the message is to be
    - * delivered to.
    - * @param {string} payload The message content.
    - */
    -goog.net.xpc.Transport.prototype.send = goog.abstractMethod;
    diff --git a/src/database/third_party/closure-library/closure/goog/net/xpc/xpc.js b/src/database/third_party/closure-library/closure/goog/net/xpc/xpc.js
    deleted file mode 100644
    index a0fd2ff87e1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/net/xpc/xpc.js
    +++ /dev/null
    @@ -1,300 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides the namesspace for client-side communication
    - * between pages originating from different domains (it works also
    - * with pages from the same domain, but doing that is kinda
    - * pointless).
    - *
    - * The only publicly visible class is goog.net.xpc.CrossPageChannel.
    - *
    - * Note: The preferred name for the main class would have been
    - * CrossDomainChannel.  But as there already is a class named like
    - * that (which serves a different purpose) in the maps codebase,
    - * CrossPageChannel was chosen to avoid confusion.
    - *
    - * CrossPageChannel abstracts the underlying transport mechanism to
    - * provide a common interface in all browsers.
    - *
    - */
    -
    -/*
    -TODO(user)
    -- resolve fastback issues in Safari (IframeRelayTransport)
    - */
    -
    -
    -/**
    - * Namespace for CrossPageChannel
    - */
    -goog.provide('goog.net.xpc');
    -goog.provide('goog.net.xpc.CfgFields');
    -goog.provide('goog.net.xpc.ChannelStates');
    -goog.provide('goog.net.xpc.TransportNames');
    -goog.provide('goog.net.xpc.TransportTypes');
    -goog.provide('goog.net.xpc.UriCfgFields');
    -
    -goog.require('goog.log');
    -
    -
    -/**
    - * Enum used to identify transport types.
    - * @enum {number}
    - */
    -goog.net.xpc.TransportTypes = {
    -  NATIVE_MESSAGING: 1,
    -  FRAME_ELEMENT_METHOD: 2,
    -  IFRAME_RELAY: 3,
    -  IFRAME_POLLING: 4,
    -  FLASH: 5,
    -  NIX: 6,
    -  DIRECT: 7
    -};
    -
    -
    -/**
    - * Enum containing transport names. These need to correspond to the
    - * transport class names for createTransport_() to work.
    - * @const {!Object<string,string>}
    - */
    -goog.net.xpc.TransportNames = {
    -  '1': 'NativeMessagingTransport',
    -  '2': 'FrameElementMethodTransport',
    -  '3': 'IframeRelayTransport',
    -  '4': 'IframePollingTransport',
    -  '5': 'FlashTransport',
    -  '6': 'NixTransport',
    -  '7': 'DirectTransport'
    -};
    -
    -
    -// TODO(user): Add auth token support to other methods.
    -
    -
    -/**
    - * Field names used on configuration object.
    - * @const
    - */
    -goog.net.xpc.CfgFields = {
    -  /**
    -   * Channel name identifier.
    -   * Both peers have to be initialized with
    -   * the same channel name.  If not present, a channel name is
    -   * generated (which then has to transferred to the peer somehow).
    -   */
    -  CHANNEL_NAME: 'cn',
    -  /**
    -   * Authorization token. If set, NIX will use this authorization token
    -   * to validate the setup.
    -   */
    -  AUTH_TOKEN: 'at',
    -  /**
    -   * Remote party's authorization token. If set, NIX will validate this
    -   * authorization token against that sent by the other party.
    -   */
    -  REMOTE_AUTH_TOKEN: 'rat',
    -  /**
    -   * The URI of the peer page.
    -   */
    -  PEER_URI: 'pu',
    -  /**
    -   * Ifame-ID identifier.
    -   * The id of the iframe element the peer-document lives in.
    -   */
    -  IFRAME_ID: 'ifrid',
    -  /**
    -   * Transport type identifier.
    -   * The transport type to use. Possible values are entries from
    -   * goog.net.xpc.TransportTypes. If not present, the transport is
    -   * determined automatically based on the useragent's capabilities.
    -   */
    -  TRANSPORT: 'tp',
    -  /**
    -   * Local relay URI identifier (IframeRelayTransport-specific).
    -   * The URI (can't contain a fragment identifier) used by the peer to
    -   * relay data through.
    -   */
    -  LOCAL_RELAY_URI: 'lru',
    -  /**
    -   * Peer relay URI identifier (IframeRelayTransport-specific).
    -   * The URI (can't contain a fragment identifier) used to relay data
    -   * to the peer.
    -   */
    -  PEER_RELAY_URI: 'pru',
    -  /**
    -   * Local poll URI identifier (IframePollingTransport-specific).
    -   * The URI  (can't contain a fragment identifier)which is polled
    -   * to receive data from the peer.
    -   */
    -  LOCAL_POLL_URI: 'lpu',
    -  /**
    -   * Local poll URI identifier (IframePollingTransport-specific).
    -   * The URI (can't contain a fragment identifier) used to send data
    -   * to the peer.
    -   */
    -  PEER_POLL_URI: 'ppu',
    -  /**
    -   * The hostname of the peer window, including protocol, domain, and port
    -   * (if specified). Used for security sensitive applications that make
    -   * use of NativeMessagingTransport (i.e. most applications).
    -   */
    -  PEER_HOSTNAME: 'ph',
    -  /**
    -   * Usually both frames using a connection initially send a SETUP message to
    -   * each other, and each responds with a SETUP_ACK.  A frame marks itself
    -   * connected when it receives that SETUP_ACK.  If this parameter is true
    -   * however, the channel it is passed to will not send a SETUP, but rather will
    -   * wait for one from its peer and mark itself connected when that arrives.
    -   * Peer iframes created using such a channel will send SETUP however, and will
    -   * wait for SETUP_ACK before marking themselves connected.  The goal is to
    -   * cope with a situation where the availability of the URL for the peer frame
    -   * cannot be relied on, eg when the application is offline.  Without this
    -   * setting, the primary frame will attempt to send its SETUP message every
    -   * 100ms, forever.  This floods the javascript console with uncatchable
    -   * security warnings, and fruitlessly burns CPU.  There is one scenario this
    -   * mode will not support, and that is reconnection by the outer frame, ie the
    -   * creation of a new channel object to connect to a peer iframe which was
    -   * already communicating with a previous channel object of the same name.  If
    -   * that behavior is needed, this mode should not be used.  Reconnection by
    -   * inner frames is supported in this mode however.
    -   */
    -  ONE_SIDED_HANDSHAKE: 'osh',
    -  /**
    -   * The frame role (inner or outer). Used to explicitly indicate the role for
    -   * each peer whenever the role cannot be reliably determined (e.g. the two
    -   * peer windows are not parent/child frames). If unspecified, the role will
    -   * be dynamically determined, assuming a parent/child frame setup.
    -   */
    -  ROLE: 'role',
    -  /**
    -   * Which version of the native transport startup protocol should be used, the
    -   * default being '2'.  Version 1 had various timing vulnerabilities, which
    -   * had to be compensated for by introducing delays, and is deprecated.  V1
    -   * and V2 are broadly compatible, although the more robust timing and lack
    -   * of delays is not gained unless both sides are using V2.  The only
    -   * unsupported case of cross-protocol interoperation is where a connection
    -   * starts out with V2 at both ends, and one of the ends reconnects as a V1.
    -   * All other initial startup and reconnection scenarios are supported.
    -   */
    -  NATIVE_TRANSPORT_PROTOCOL_VERSION: 'nativeProtocolVersion',
    -  /**
    -   * Whether the direct transport runs in synchronous mode. The default is to
    -   * emulate the other transports and run asyncronously but there are some
    -   * circumstances where syncronous calls are required. If this property is
    -   * set to true, the transport will send the messages synchronously.
    -   */
    -  DIRECT_TRANSPORT_SYNC_MODE: 'directSyncMode'
    -};
    -
    -
    -/**
    - * Config properties that need to be URL sanitized.
    - * @type {Array<string>}
    - */
    -goog.net.xpc.UriCfgFields = [
    -  goog.net.xpc.CfgFields.PEER_URI,
    -  goog.net.xpc.CfgFields.LOCAL_RELAY_URI,
    -  goog.net.xpc.CfgFields.PEER_RELAY_URI,
    -  goog.net.xpc.CfgFields.LOCAL_POLL_URI,
    -  goog.net.xpc.CfgFields.PEER_POLL_URI
    -];
    -
    -
    -/**
    - * @enum {number}
    - */
    -goog.net.xpc.ChannelStates = {
    -  NOT_CONNECTED: 1,
    -  CONNECTED: 2,
    -  CLOSED: 3
    -};
    -
    -
    -/**
    - * The name of the transport service (used for internal signalling).
    - * @type {string}
    - * @suppress {underscore|visibility}
    - */
    -goog.net.xpc.TRANSPORT_SERVICE_ = 'tp';
    -
    -
    -/**
    - * Transport signaling message: setup.
    - * @type {string}
    - */
    -goog.net.xpc.SETUP = 'SETUP';
    -
    -
    -/**
    - * Transport signaling message: setup for native transport protocol v2.
    - * @type {string}
    - */
    -goog.net.xpc.SETUP_NTPV2 = 'SETUP_NTPV2';
    -
    -
    -/**
    - * Transport signaling message: setup acknowledgement.
    - * @type {string}
    - * @suppress {underscore|visibility}
    - */
    -goog.net.xpc.SETUP_ACK_ = 'SETUP_ACK';
    -
    -
    -/**
    - * Transport signaling message: setup acknowledgement.
    - * @type {string}
    - */
    -goog.net.xpc.SETUP_ACK_NTPV2 = 'SETUP_ACK_NTPV2';
    -
    -
    -/**
    - * Object holding active channels.
    - *
    - * @package {Object<string, goog.net.xpc.CrossPageChannel>}
    - */
    -goog.net.xpc.channels = {};
    -
    -
    -/**
    - * Returns a random string.
    - * @param {number} length How many characters the string shall contain.
    - * @param {string=} opt_characters The characters used.
    - * @return {string} The random string.
    - */
    -goog.net.xpc.getRandomString = function(length, opt_characters) {
    -  var chars = opt_characters || goog.net.xpc.randomStringCharacters_;
    -  var charsLength = chars.length;
    -  var s = '';
    -  while (length-- > 0) {
    -    s += chars.charAt(Math.floor(Math.random() * charsLength));
    -  }
    -  return s;
    -};
    -
    -
    -/**
    - * The default characters used for random string generation.
    - * @type {string}
    - * @private
    - */
    -goog.net.xpc.randomStringCharacters_ =
    -    'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    -
    -
    -/**
    - * The logger.
    - * @type {goog.log.Logger}
    - */
    -goog.net.xpc.logger = goog.log.getLogger('goog.net.xpc');
    diff --git a/src/database/third_party/closure-library/closure/goog/object/object.js b/src/database/third_party/closure-library/closure/goog/object/object.js
    deleted file mode 100644
    index 20a77f789a3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/object/object.js
    +++ /dev/null
    @@ -1,686 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Utilities for manipulating objects/maps/hashes.
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -goog.provide('goog.object');
    -
    -
    -/**
    - * Calls a function for each element in an object/map/hash.
    - *
    - * @param {Object<K,V>} obj The object over which to iterate.
    - * @param {function(this:T,V,?,Object<K,V>):?} f The function to call
    - *     for every element. This function takes 3 arguments (the element, the
    - *     index and the object) and the return value is ignored.
    - * @param {T=} opt_obj This is used as the 'this' object within f.
    - * @template T,K,V
    - */
    -goog.object.forEach = function(obj, f, opt_obj) {
    -  for (var key in obj) {
    -    f.call(opt_obj, obj[key], key, obj);
    -  }
    -};
    -
    -
    -/**
    - * Calls a function for each element in an object/map/hash. If that call returns
    - * true, adds the element to a new object.
    - *
    - * @param {Object<K,V>} obj The object over which to iterate.
    - * @param {function(this:T,V,?,Object<K,V>):boolean} f The function to call
    - *     for every element. This
    - *     function takes 3 arguments (the element, the index and the object)
    - *     and should return a boolean. If the return value is true the
    - *     element is added to the result object. If it is false the
    - *     element is not included.
    - * @param {T=} opt_obj This is used as the 'this' object within f.
    - * @return {!Object<K,V>} a new object in which only elements that passed the
    - *     test are present.
    - * @template T,K,V
    - */
    -goog.object.filter = function(obj, f, opt_obj) {
    -  var res = {};
    -  for (var key in obj) {
    -    if (f.call(opt_obj, obj[key], key, obj)) {
    -      res[key] = obj[key];
    -    }
    -  }
    -  return res;
    -};
    -
    -
    -/**
    - * For every element in an object/map/hash calls a function and inserts the
    - * result into a new object.
    - *
    - * @param {Object<K,V>} obj The object over which to iterate.
    - * @param {function(this:T,V,?,Object<K,V>):R} f The function to call
    - *     for every element. This function
    - *     takes 3 arguments (the element, the index and the object)
    - *     and should return something. The result will be inserted
    - *     into a new object.
    - * @param {T=} opt_obj This is used as the 'this' object within f.
    - * @return {!Object<K,R>} a new object with the results from f.
    - * @template T,K,V,R
    - */
    -goog.object.map = function(obj, f, opt_obj) {
    -  var res = {};
    -  for (var key in obj) {
    -    res[key] = f.call(opt_obj, obj[key], key, obj);
    -  }
    -  return res;
    -};
    -
    -
    -/**
    - * Calls a function for each element in an object/map/hash. If any
    - * call returns true, returns true (without checking the rest). If
    - * all calls return false, returns false.
    - *
    - * @param {Object<K,V>} obj The object to check.
    - * @param {function(this:T,V,?,Object<K,V>):boolean} f The function to
    - *     call for every element. This function
    - *     takes 3 arguments (the element, the index and the object) and should
    - *     return a boolean.
    - * @param {T=} opt_obj This is used as the 'this' object within f.
    - * @return {boolean} true if any element passes the test.
    - * @template T,K,V
    - */
    -goog.object.some = function(obj, f, opt_obj) {
    -  for (var key in obj) {
    -    if (f.call(opt_obj, obj[key], key, obj)) {
    -      return true;
    -    }
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Calls a function for each element in an object/map/hash. If
    - * all calls return true, returns true. If any call returns false, returns
    - * false at this point and does not continue to check the remaining elements.
    - *
    - * @param {Object<K,V>} obj The object to check.
    - * @param {?function(this:T,V,?,Object<K,V>):boolean} f The function to
    - *     call for every element. This function
    - *     takes 3 arguments (the element, the index and the object) and should
    - *     return a boolean.
    - * @param {T=} opt_obj This is used as the 'this' object within f.
    - * @return {boolean} false if any element fails the test.
    - * @template T,K,V
    - */
    -goog.object.every = function(obj, f, opt_obj) {
    -  for (var key in obj) {
    -    if (!f.call(opt_obj, obj[key], key, obj)) {
    -      return false;
    -    }
    -  }
    -  return true;
    -};
    -
    -
    -/**
    - * Returns the number of key-value pairs in the object map.
    - *
    - * @param {Object} obj The object for which to get the number of key-value
    - *     pairs.
    - * @return {number} The number of key-value pairs in the object map.
    - */
    -goog.object.getCount = function(obj) {
    -  // JS1.5 has __count__ but it has been deprecated so it raises a warning...
    -  // in other words do not use. Also __count__ only includes the fields on the
    -  // actual object and not in the prototype chain.
    -  var rv = 0;
    -  for (var key in obj) {
    -    rv++;
    -  }
    -  return rv;
    -};
    -
    -
    -/**
    - * Returns one key from the object map, if any exists.
    - * For map literals the returned key will be the first one in most of the
    - * browsers (a know exception is Konqueror).
    - *
    - * @param {Object} obj The object to pick a key from.
    - * @return {string|undefined} The key or undefined if the object is empty.
    - */
    -goog.object.getAnyKey = function(obj) {
    -  for (var key in obj) {
    -    return key;
    -  }
    -};
    -
    -
    -/**
    - * Returns one value from the object map, if any exists.
    - * For map literals the returned value will be the first one in most of the
    - * browsers (a know exception is Konqueror).
    - *
    - * @param {Object<K,V>} obj The object to pick a value from.
    - * @return {V|undefined} The value or undefined if the object is empty.
    - * @template K,V
    - */
    -goog.object.getAnyValue = function(obj) {
    -  for (var key in obj) {
    -    return obj[key];
    -  }
    -};
    -
    -
    -/**
    - * Whether the object/hash/map contains the given object as a value.
    - * An alias for goog.object.containsValue(obj, val).
    - *
    - * @param {Object<K,V>} obj The object in which to look for val.
    - * @param {V} val The object for which to check.
    - * @return {boolean} true if val is present.
    - * @template K,V
    - */
    -goog.object.contains = function(obj, val) {
    -  return goog.object.containsValue(obj, val);
    -};
    -
    -
    -/**
    - * Returns the values of the object/map/hash.
    - *
    - * @param {Object<K,V>} obj The object from which to get the values.
    - * @return {!Array<V>} The values in the object/map/hash.
    - * @template K,V
    - */
    -goog.object.getValues = function(obj) {
    -  var res = [];
    -  var i = 0;
    -  for (var key in obj) {
    -    res[i++] = obj[key];
    -  }
    -  return res;
    -};
    -
    -
    -/**
    - * Returns the keys of the object/map/hash.
    - *
    - * @param {Object} obj The object from which to get the keys.
    - * @return {!Array<string>} Array of property keys.
    - */
    -goog.object.getKeys = function(obj) {
    -  var res = [];
    -  var i = 0;
    -  for (var key in obj) {
    -    res[i++] = key;
    -  }
    -  return res;
    -};
    -
    -
    -/**
    - * Get a value from an object multiple levels deep.  This is useful for
    - * pulling values from deeply nested objects, such as JSON responses.
    - * Example usage: getValueByKeys(jsonObj, 'foo', 'entries', 3)
    - *
    - * @param {!Object} obj An object to get the value from.  Can be array-like.
    - * @param {...(string|number|!Array<number|string>)} var_args A number of keys
    - *     (as strings, or numbers, for array-like objects).  Can also be
    - *     specified as a single array of keys.
    - * @return {*} The resulting value.  If, at any point, the value for a key
    - *     is undefined, returns undefined.
    - */
    -goog.object.getValueByKeys = function(obj, var_args) {
    -  var isArrayLike = goog.isArrayLike(var_args);
    -  var keys = isArrayLike ? var_args : arguments;
    -
    -  // Start with the 2nd parameter for the variable parameters syntax.
    -  for (var i = isArrayLike ? 0 : 1; i < keys.length; i++) {
    -    obj = obj[keys[i]];
    -    if (!goog.isDef(obj)) {
    -      break;
    -    }
    -  }
    -
    -  return obj;
    -};
    -
    -
    -/**
    - * Whether the object/map/hash contains the given key.
    - *
    - * @param {Object} obj The object in which to look for key.
    - * @param {*} key The key for which to check.
    - * @return {boolean} true If the map contains the key.
    - */
    -goog.object.containsKey = function(obj, key) {
    -  return key in obj;
    -};
    -
    -
    -/**
    - * Whether the object/map/hash contains the given value. This is O(n).
    - *
    - * @param {Object<K,V>} obj The object in which to look for val.
    - * @param {V} val The value for which to check.
    - * @return {boolean} true If the map contains the value.
    - * @template K,V
    - */
    -goog.object.containsValue = function(obj, val) {
    -  for (var key in obj) {
    -    if (obj[key] == val) {
    -      return true;
    -    }
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Searches an object for an element that satisfies the given condition and
    - * returns its key.
    - * @param {Object<K,V>} obj The object to search in.
    - * @param {function(this:T,V,string,Object<K,V>):boolean} f The
    - *      function to call for every element. Takes 3 arguments (the value,
    - *     the key and the object) and should return a boolean.
    - * @param {T=} opt_this An optional "this" context for the function.
    - * @return {string|undefined} The key of an element for which the function
    - *     returns true or undefined if no such element is found.
    - * @template T,K,V
    - */
    -goog.object.findKey = function(obj, f, opt_this) {
    -  for (var key in obj) {
    -    if (f.call(opt_this, obj[key], key, obj)) {
    -      return key;
    -    }
    -  }
    -  return undefined;
    -};
    -
    -
    -/**
    - * Searches an object for an element that satisfies the given condition and
    - * returns its value.
    - * @param {Object<K,V>} obj The object to search in.
    - * @param {function(this:T,V,string,Object<K,V>):boolean} f The function
    - *     to call for every element. Takes 3 arguments (the value, the key
    - *     and the object) and should return a boolean.
    - * @param {T=} opt_this An optional "this" context for the function.
    - * @return {V} The value of an element for which the function returns true or
    - *     undefined if no such element is found.
    - * @template T,K,V
    - */
    -goog.object.findValue = function(obj, f, opt_this) {
    -  var key = goog.object.findKey(obj, f, opt_this);
    -  return key && obj[key];
    -};
    -
    -
    -/**
    - * Whether the object/map/hash is empty.
    - *
    - * @param {Object} obj The object to test.
    - * @return {boolean} true if obj is empty.
    - */
    -goog.object.isEmpty = function(obj) {
    -  for (var key in obj) {
    -    return false;
    -  }
    -  return true;
    -};
    -
    -
    -/**
    - * Removes all key value pairs from the object/map/hash.
    - *
    - * @param {Object} obj The object to clear.
    - */
    -goog.object.clear = function(obj) {
    -  for (var i in obj) {
    -    delete obj[i];
    -  }
    -};
    -
    -
    -/**
    - * Removes a key-value pair based on the key.
    - *
    - * @param {Object} obj The object from which to remove the key.
    - * @param {*} key The key to remove.
    - * @return {boolean} Whether an element was removed.
    - */
    -goog.object.remove = function(obj, key) {
    -  var rv;
    -  if ((rv = key in obj)) {
    -    delete obj[key];
    -  }
    -  return rv;
    -};
    -
    -
    -/**
    - * Adds a key-value pair to the object. Throws an exception if the key is
    - * already in use. Use set if you want to change an existing pair.
    - *
    - * @param {Object<K,V>} obj The object to which to add the key-value pair.
    - * @param {string} key The key to add.
    - * @param {V} val The value to add.
    - * @template K,V
    - */
    -goog.object.add = function(obj, key, val) {
    -  if (key in obj) {
    -    throw Error('The object already contains the key "' + key + '"');
    -  }
    -  goog.object.set(obj, key, val);
    -};
    -
    -
    -/**
    - * Returns the value for the given key.
    - *
    - * @param {Object<K,V>} obj The object from which to get the value.
    - * @param {string} key The key for which to get the value.
    - * @param {R=} opt_val The value to return if no item is found for the given
    - *     key (default is undefined).
    - * @return {V|R|undefined} The value for the given key.
    - * @template K,V,R
    - */
    -goog.object.get = function(obj, key, opt_val) {
    -  if (key in obj) {
    -    return obj[key];
    -  }
    -  return opt_val;
    -};
    -
    -
    -/**
    - * Adds a key-value pair to the object/map/hash.
    - *
    - * @param {Object<K,V>} obj The object to which to add the key-value pair.
    - * @param {string} key The key to add.
    - * @param {V} value The value to add.
    - * @template K,V
    - */
    -goog.object.set = function(obj, key, value) {
    -  obj[key] = value;
    -};
    -
    -
    -/**
    - * Adds a key-value pair to the object/map/hash if it doesn't exist yet.
    - *
    - * @param {Object<K,V>} obj The object to which to add the key-value pair.
    - * @param {string} key The key to add.
    - * @param {V} value The value to add if the key wasn't present.
    - * @return {V} The value of the entry at the end of the function.
    - * @template K,V
    - */
    -goog.object.setIfUndefined = function(obj, key, value) {
    -  return key in obj ? obj[key] : (obj[key] = value);
    -};
    -
    -
    -/**
    - * Sets a key and value to an object if the key is not set. The value will be
    - * the return value of the given function. If the key already exists, the
    - * object will not be changed and the function will not be called (the function
    - * will be lazily evaluated -- only called if necessary).
    - *
    - * This function is particularly useful for use with a map used a as a cache.
    - *
    - * @param {!Object<K,V>} obj The object to which to add the key-value pair.
    - * @param {string} key The key to add.
    - * @param {function():V} f The value to add if the key wasn't present.
    - * @return {V} The value of the entry at the end of the function.
    - * @template K,V
    - */
    -goog.object.setWithReturnValueIfNotSet = function(obj, key, f) {
    -  if (key in obj) {
    -    return obj[key];
    -  }
    -
    -  var val = f();
    -  obj[key] = val;
    -  return val;
    -};
    -
    -
    -/**
    - * Compares two objects for equality using === on the values.
    - *
    - * @param {!Object<K,V>} a
    - * @param {!Object<K,V>} b
    - * @return {boolean}
    - * @template K,V
    - */
    -goog.object.equals = function(a, b) {
    -  for (var k in a) {
    -    if (!(k in b) || a[k] !== b[k]) {
    -      return false;
    -    }
    -  }
    -  for (var k in b) {
    -    if (!(k in a)) {
    -      return false;
    -    }
    -  }
    -  return true;
    -};
    -
    -
    -/**
    - * Does a flat clone of the object.
    - *
    - * @param {Object<K,V>} obj Object to clone.
    - * @return {!Object<K,V>} Clone of the input object.
    - * @template K,V
    - */
    -goog.object.clone = function(obj) {
    -  // We cannot use the prototype trick because a lot of methods depend on where
    -  // the actual key is set.
    -
    -  var res = {};
    -  for (var key in obj) {
    -    res[key] = obj[key];
    -  }
    -  return res;
    -  // We could also use goog.mixin but I wanted this to be independent from that.
    -};
    -
    -
    -/**
    - * Clones a value. The input may be an Object, Array, or basic type. Objects and
    - * arrays will be cloned recursively.
    - *
    - * WARNINGS:
    - * <code>goog.object.unsafeClone</code> does not detect reference loops. Objects
    - * that refer to themselves will cause infinite recursion.
    - *
    - * <code>goog.object.unsafeClone</code> is unaware of unique identifiers, and
    - * copies UIDs created by <code>getUid</code> into cloned results.
    - *
    - * @param {*} obj The value to clone.
    - * @return {*} A clone of the input value.
    - */
    -goog.object.unsafeClone = function(obj) {
    -  var type = goog.typeOf(obj);
    -  if (type == 'object' || type == 'array') {
    -    if (obj.clone) {
    -      return obj.clone();
    -    }
    -    var clone = type == 'array' ? [] : {};
    -    for (var key in obj) {
    -      clone[key] = goog.object.unsafeClone(obj[key]);
    -    }
    -    return clone;
    -  }
    -
    -  return obj;
    -};
    -
    -
    -/**
    - * Returns a new object in which all the keys and values are interchanged
    - * (keys become values and values become keys). If multiple keys map to the
    - * same value, the chosen transposed value is implementation-dependent.
    - *
    - * @param {Object} obj The object to transpose.
    - * @return {!Object} The transposed object.
    - */
    -goog.object.transpose = function(obj) {
    -  var transposed = {};
    -  for (var key in obj) {
    -    transposed[obj[key]] = key;
    -  }
    -  return transposed;
    -};
    -
    -
    -/**
    - * The names of the fields that are defined on Object.prototype.
    - * @type {Array<string>}
    - * @private
    - */
    -goog.object.PROTOTYPE_FIELDS_ = [
    -  'constructor',
    -  'hasOwnProperty',
    -  'isPrototypeOf',
    -  'propertyIsEnumerable',
    -  'toLocaleString',
    -  'toString',
    -  'valueOf'
    -];
    -
    -
    -/**
    - * Extends an object with another object.
    - * This operates 'in-place'; it does not create a new Object.
    - *
    - * Example:
    - * var o = {};
    - * goog.object.extend(o, {a: 0, b: 1});
    - * o; // {a: 0, b: 1}
    - * goog.object.extend(o, {b: 2, c: 3});
    - * o; // {a: 0, b: 2, c: 3}
    - *
    - * @param {Object} target The object to modify. Existing properties will be
    - *     overwritten if they are also present in one of the objects in
    - *     {@code var_args}.
    - * @param {...Object} var_args The objects from which values will be copied.
    - */
    -goog.object.extend = function(target, var_args) {
    -  var key, source;
    -  for (var i = 1; i < arguments.length; i++) {
    -    source = arguments[i];
    -    for (key in source) {
    -      target[key] = source[key];
    -    }
    -
    -    // For IE the for-in-loop does not contain any properties that are not
    -    // enumerable on the prototype object (for example isPrototypeOf from
    -    // Object.prototype) and it will also not include 'replace' on objects that
    -    // extend String and change 'replace' (not that it is common for anyone to
    -    // extend anything except Object).
    -
    -    for (var j = 0; j < goog.object.PROTOTYPE_FIELDS_.length; j++) {
    -      key = goog.object.PROTOTYPE_FIELDS_[j];
    -      if (Object.prototype.hasOwnProperty.call(source, key)) {
    -        target[key] = source[key];
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Creates a new object built from the key-value pairs provided as arguments.
    - * @param {...*} var_args If only one argument is provided and it is an array
    - *     then this is used as the arguments,  otherwise even arguments are used as
    - *     the property names and odd arguments are used as the property values.
    - * @return {!Object} The new object.
    - * @throws {Error} If there are uneven number of arguments or there is only one
    - *     non array argument.
    - */
    -goog.object.create = function(var_args) {
    -  var argLength = arguments.length;
    -  if (argLength == 1 && goog.isArray(arguments[0])) {
    -    return goog.object.create.apply(null, arguments[0]);
    -  }
    -
    -  if (argLength % 2) {
    -    throw Error('Uneven number of arguments');
    -  }
    -
    -  var rv = {};
    -  for (var i = 0; i < argLength; i += 2) {
    -    rv[arguments[i]] = arguments[i + 1];
    -  }
    -  return rv;
    -};
    -
    -
    -/**
    - * Creates a new object where the property names come from the arguments but
    - * the value is always set to true
    - * @param {...*} var_args If only one argument is provided and it is an array
    - *     then this is used as the arguments,  otherwise the arguments are used
    - *     as the property names.
    - * @return {!Object} The new object.
    - */
    -goog.object.createSet = function(var_args) {
    -  var argLength = arguments.length;
    -  if (argLength == 1 && goog.isArray(arguments[0])) {
    -    return goog.object.createSet.apply(null, arguments[0]);
    -  }
    -
    -  var rv = {};
    -  for (var i = 0; i < argLength; i++) {
    -    rv[arguments[i]] = true;
    -  }
    -  return rv;
    -};
    -
    -
    -/**
    - * Creates an immutable view of the underlying object, if the browser
    - * supports immutable objects.
    - *
    - * In default mode, writes to this view will fail silently. In strict mode,
    - * they will throw an error.
    - *
    - * @param {!Object<K,V>} obj An object.
    - * @return {!Object<K,V>} An immutable view of that object, or the
    - *     original object if this browser does not support immutables.
    - * @template K,V
    - */
    -goog.object.createImmutableView = function(obj) {
    -  var result = obj;
    -  if (Object.isFrozen && !Object.isFrozen(obj)) {
    -    result = Object.create(obj);
    -    Object.freeze(result);
    -  }
    -  return result;
    -};
    -
    -
    -/**
    - * @param {!Object} obj An object.
    - * @return {boolean} Whether this is an immutable view of the object.
    - */
    -goog.object.isImmutableView = function(obj) {
    -  return !!Object.isFrozen && Object.isFrozen(obj);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/object/object_test.html b/src/database/third_party/closure-library/closure/goog/object/object_test.html
    deleted file mode 100644
    index 126eff7f9fc..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/object/object_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.object
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.objectTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/object/object_test.js b/src/database/third_party/closure-library/closure/goog/object/object_test.js
    deleted file mode 100644
    index 2c55aa0b9da..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/object/object_test.js
    +++ /dev/null
    @@ -1,530 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.objectTest');
    -goog.setTestOnly('goog.objectTest');
    -
    -goog.require('goog.functions');
    -goog.require('goog.object');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -
    -function stringifyObject(m) {
    -  var keys = goog.object.getKeys(m);
    -  var s = '';
    -  for (var i = 0; i < keys.length; i++) {
    -    s += keys[i] + goog.object.get(m, keys[i]);
    -  }
    -  return s;
    -}
    -
    -function getObject() {
    -  return {
    -    a: 0,
    -    b: 1,
    -    c: 2,
    -    d: 3
    -  };
    -}
    -
    -function testKeys() {
    -  var m = getObject();
    -  assertEquals('getKeys, The keys should be a,b,c',
    -               'a,b,c,d',
    -               goog.object.getKeys(m).join(','));
    -}
    -
    -function testValues() {
    -  var m = getObject();
    -  assertEquals('getValues, The values should be 0,1,2',
    -      '0,1,2,3', goog.object.getValues(m).join(','));
    -}
    -
    -function testGetAnyKey() {
    -  var m = getObject();
    -  assertTrue('getAnyKey, The key should be a,b,c or d',
    -             goog.object.getAnyKey(m) in m);
    -  assertUndefined('getAnyKey, The key should be undefined',
    -                  goog.object.getAnyKey({}));
    -}
    -
    -function testGetAnyValue() {
    -  var m = getObject();
    -  assertTrue('getAnyValue, The value should be 0,1,2 or 3',
    -             goog.object.containsValue(m, goog.object.getAnyValue(m)));
    -  assertUndefined('getAnyValue, The value should be undefined',
    -                  goog.object.getAnyValue({}));
    -}
    -
    -function testContainsKey() {
    -  var m = getObject();
    -  assertTrue("containsKey, Should contain the 'a' key",
    -             goog.object.containsKey(m, 'a'));
    -  assertFalse("containsKey, Should not contain the 'e' key",
    -              goog.object.containsKey(m, 'e'));
    -}
    -
    -function testContainsValue() {
    -  var m = getObject();
    -  assertTrue('containsValue, Should contain the value 0',
    -             goog.object.containsValue(m, 0));
    -  assertFalse('containsValue, Should not contain the value 4',
    -              goog.object.containsValue(m, 4));
    -  assertTrue('isEmpty, The map should not be empty', !goog.object.isEmpty(m));
    -}
    -
    -function testFindKey() {
    -  var dict = {'a': 1, 'b': 2, 'c': 3, 'd': 4};
    -  var key = goog.object.findKey(dict, function(v, k, d) {
    -    assertEquals('valid 3rd argument', dict, d);
    -    assertTrue('valid 1st argument', goog.object.containsValue(d, v));
    -    assertTrue('valid 2nd argument', k in d);
    -    return v % 3 == 0;
    -  });
    -  assertEquals('key "c" found', 'c', key);
    -
    -  var pred = function(value) {
    -    return value > 5;
    -  };
    -  assertUndefined('no match', goog.object.findKey(dict, pred));
    -}
    -
    -function testFindValue() {
    -  var dict = {'a': 1, 'b': 2, 'c': 3, 'd': 4};
    -  var value = goog.object.findValue(dict, function(v, k, d) {
    -    assertEquals('valid 3rd argument', dict, d);
    -    assertTrue('valid 1st argument', goog.object.containsValue(d, v));
    -    assertTrue('valid 2nd argument', k in d);
    -    return k.toUpperCase() == 'C';
    -  });
    -  assertEquals('value 3 found', 3, value);
    -
    -  var pred = function(value, key) {
    -    return key > 'd';
    -  };
    -  assertUndefined('no match', goog.object.findValue(dict, pred));
    -}
    -
    -function testClear() {
    -  var m = getObject();
    -  goog.object.clear(m);
    -  assertTrue('cleared so it should be empty', goog.object.isEmpty(m));
    -  assertFalse("cleared so it should not contain 'a' key",
    -              goog.object.containsKey(m, 'a'));
    -}
    -
    -function testClone() {
    -  var m = getObject();
    -  var m2 = goog.object.clone(m);
    -  assertFalse('clone so it should not be empty', goog.object.isEmpty(m2));
    -  assertTrue("clone so it should contain 'c' key",
    -             goog.object.containsKey(m2, 'c'));
    -}
    -
    -function testUnsafeClonePrimitive() {
    -  assertEquals('cloning a primitive should return an equal primitive',
    -      5, goog.object.unsafeClone(5));
    -}
    -
    -function testUnsafeCloneObjectThatHasACloneMethod() {
    -  var original = {
    -    name: 'original',
    -    clone: goog.functions.constant({name: 'clone'})
    -  };
    -
    -  var clone = goog.object.unsafeClone(original);
    -  assertEquals('original', original.name);
    -  assertEquals('clone', clone.name);
    -}
    -
    -function testUnsafeCloneFlatObject() {
    -  var original = {a: 1, b: 2, c: 3};
    -  var clone = goog.object.unsafeClone(original);
    -  assertNotEquals(original, clone);
    -  assertObjectEquals(original, clone);
    -}
    -
    -function testUnsafeCloneDeepObject() {
    -  var original = {
    -    a: 1,
    -    b: {c: 2, d: 3},
    -    e: {f: {g: 4, h: 5}}
    -  };
    -  var clone = goog.object.unsafeClone(original);
    -
    -  assertNotEquals(original, clone);
    -  assertNotEquals(original.b, clone.b);
    -  assertNotEquals(original.e, clone.e);
    -
    -  assertEquals(1, clone.a);
    -  assertEquals(2, clone.b.c);
    -  assertEquals(3, clone.b.d);
    -  assertEquals(4, clone.e.f.g);
    -  assertEquals(5, clone.e.f.h);
    -}
    -
    -function testUnsafeCloneFunctions() {
    -  var original = {
    -    f: goog.functions.constant('hi')
    -  };
    -  var clone = goog.object.unsafeClone(original);
    -
    -  assertNotEquals(original, clone);
    -  assertEquals('hi', clone.f());
    -  assertEquals(original.f, clone.f);
    -}
    -
    -function testForEach() {
    -  var m = getObject();
    -  var s = '';
    -  goog.object.forEach(m, function(val, key, m2) {
    -    assertNotUndefined(key);
    -    assertEquals(m, m2);
    -    s += key + val;
    -  });
    -  assertEquals(s, 'a0b1c2d3');
    -}
    -
    -function testFilter() {
    -  var m = getObject();
    -
    -  var m2 = goog.object.filter(m, function(val, key, m3) {
    -    assertNotUndefined(key);
    -    assertEquals(m, m3);
    -    return val > 1;
    -  });
    -  assertEquals(stringifyObject(m2), 'c2d3');
    -}
    -
    -
    -function testMap() {
    -  var m = getObject();
    -  var m2 = goog.object.map(m, function(val, key, m3) {
    -    assertNotUndefined(key);
    -    assertEquals(m, m3);
    -    return val * val;
    -  });
    -  assertEquals(stringifyObject(m2), 'a0b1c4d9');
    -}
    -
    -function testSome() {
    -  var m = getObject();
    -  var b = goog.object.some(m, function(val, key, m2) {
    -    assertNotUndefined(key);
    -    assertEquals(m, m2);
    -    return val > 1;
    -  });
    -  assertTrue(b);
    -  var b = goog.object.some(m, function(val, key, m2) {
    -    assertNotUndefined(key);
    -    assertEquals(m, m2);
    -    return val > 100;
    -  });
    -  assertFalse(b);
    -}
    -
    -function testEvery() {
    -  var m = getObject();
    -  var b = goog.object.every(m, function(val, key, m2) {
    -    assertNotUndefined(key);
    -    assertEquals(m, m2);
    -    return val >= 0;
    -  });
    -  assertTrue(b);
    -  b = goog.object.every(m, function(val, key, m2) {
    -    assertNotUndefined(key);
    -    assertEquals(m, m2);
    -    return val > 1;
    -  });
    -  assertFalse(b);
    -}
    -
    -function testContains() {
    -  var m = getObject();
    -  assertTrue(goog.object.contains(m, 3));
    -  assertFalse(goog.object.contains(m, 4));
    -}
    -
    -function testObjectProperties() {
    -  var m = {};
    -
    -  goog.object.set(m, 'toString', 'once');
    -  goog.object.set(m, 'valueOf', 'upon');
    -  goog.object.set(m, 'eval', 'a');
    -  goog.object.set(m, 'toSource', 'midnight');
    -  goog.object.set(m, 'prototype', 'dreary');
    -  goog.object.set(m, 'hasOwnProperty', 'dark');
    -
    -  assertEquals(goog.object.get(m, 'toString'), 'once');
    -  assertEquals(goog.object.get(m, 'valueOf'), 'upon');
    -  assertEquals(goog.object.get(m, 'eval'), 'a');
    -  assertEquals(goog.object.get(m, 'toSource'), 'midnight');
    -  assertEquals(goog.object.get(m, 'prototype'), 'dreary');
    -  assertEquals(goog.object.get(m, 'hasOwnProperty'), 'dark');
    -}
    -
    -function testSetDefault() {
    -  var dict = {};
    -  assertEquals(1, goog.object.setIfUndefined(dict, 'a', 1));
    -  assertEquals(1, dict['a']);
    -  assertEquals(1, goog.object.setIfUndefined(dict, 'a', 2));
    -  assertEquals(1, dict['a']);
    -}
    -
    -function createRecordedGetFoo() {
    -  return goog.testing.recordFunction(goog.functions.constant('foo'));
    -}
    -
    -function testSetWithReturnValueNotSet_KeyIsSet() {
    -  var f = createRecordedGetFoo();
    -  var obj = {};
    -  obj['key'] = 'bar';
    -  assertEquals(
    -      'bar',
    -      goog.object.setWithReturnValueIfNotSet(obj, 'key', f));
    -  f.assertCallCount(0);
    -}
    -
    -function testSetWithReturnValueNotSet_KeyIsNotSet() {
    -  var f = createRecordedGetFoo();
    -  var obj = {};
    -  assertEquals(
    -      'foo',
    -      goog.object.setWithReturnValueIfNotSet(obj, 'key', f));
    -  f.assertCallCount(1);
    -}
    -
    -function testSetWithReturnValueNotSet_KeySetValueIsUndefined() {
    -  var f = createRecordedGetFoo();
    -  var obj = {};
    -  obj['key'] = undefined;
    -  assertEquals(
    -      undefined,
    -      goog.object.setWithReturnValueIfNotSet(obj, 'key', f));
    -  f.assertCallCount(0);
    -}
    -
    -function testTranspose() {
    -  var m = getObject();
    -  var b = goog.object.transpose(m);
    -  assertEquals('a', b[0]);
    -  assertEquals('b', b[1]);
    -  assertEquals('c', b[2]);
    -  assertEquals('d', b[3]);
    -}
    -
    -function testExtend() {
    -  var o = {};
    -  var o2 = {a: 0, b: 1};
    -  goog.object.extend(o, o2);
    -  assertEquals(0, o.a);
    -  assertEquals(1, o.b);
    -  assertTrue('a' in o);
    -  assertTrue('b' in o);
    -
    -  o2 = {c: 2};
    -  goog.object.extend(o, o2);
    -  assertEquals(2, o.c);
    -  assertTrue('c' in o);
    -
    -  o2 = {c: 3};
    -  goog.object.extend(o, o2);
    -  assertEquals(3, o.c);
    -  assertTrue('c' in o);
    -
    -  o = {};
    -  o2 = {c: 2};
    -  var o3 = {c: 3};
    -  goog.object.extend(o, o2, o3);
    -  assertEquals(3, o.c);
    -  assertTrue('c' in o);
    -
    -  o = {};
    -  o2 = {a: 0, b: 1};
    -  o3 = {c: 2, d: 3};
    -  goog.object.extend(o, o2, o3);
    -  assertEquals(0, o.a);
    -  assertEquals(1, o.b);
    -  assertEquals(2, o.c);
    -  assertEquals(3, o.d);
    -  assertTrue('a' in o);
    -  assertTrue('b' in o);
    -  assertTrue('c' in o);
    -  assertTrue('d' in o);
    -
    -  o = {};
    -  o2 = {
    -    'constructor': 0,
    -    'hasOwnProperty': 1,
    -    'isPrototypeOf': 2,
    -    'propertyIsEnumerable': 3,
    -    'toLocaleString': 4,
    -    'toString': 5,
    -    'valueOf': 6
    -  };
    -  goog.object.extend(o, o2);
    -  assertEquals(0, o['constructor']);
    -  assertEquals(1, o['hasOwnProperty']);
    -  assertEquals(2, o['isPrototypeOf']);
    -  assertEquals(3, o['propertyIsEnumerable']);
    -  assertEquals(4, o['toLocaleString']);
    -  assertEquals(5, o['toString']);
    -  assertEquals(6, o['valueOf']);
    -  assertTrue('constructor' in o);
    -  assertTrue('hasOwnProperty' in o);
    -  assertTrue('isPrototypeOf' in o);
    -  assertTrue('propertyIsEnumerable' in o);
    -  assertTrue('toLocaleString' in o);
    -  assertTrue('toString' in o);
    -  assertTrue('valueOf' in o);
    -}
    -
    -function testCreate() {
    -  assertObjectEquals('With multiple arguments',
    -                     {a: 0, b: 1}, goog.object.create('a', 0, 'b', 1));
    -  assertObjectEquals('With an array argument',
    -                     {a: 0, b: 1}, goog.object.create(['a', 0, 'b', 1]));
    -
    -  assertObjectEquals('With no arguments',
    -                     {}, goog.object.create());
    -  assertObjectEquals('With an ampty array argument',
    -                     {}, goog.object.create([]));
    -
    -  assertThrows('Should throw due to uneven arguments', function() {
    -    goog.object.create('a');
    -  });
    -  assertThrows('Should throw due to uneven arguments', function() {
    -    goog.object.create('a', 0, 'b');
    -  });
    -  assertThrows('Should throw due to uneven length array', function() {
    -    goog.object.create(['a']);
    -  });
    -  assertThrows('Should throw due to uneven length array', function() {
    -    goog.object.create(['a', 0, 'b']);
    -  });
    -}
    -
    -function testCreateSet() {
    -  assertObjectEquals('With multiple arguments',
    -                     {a: true, b: true}, goog.object.createSet('a', 'b'));
    -  assertObjectEquals('With an array argument',
    -                     {a: true, b: true}, goog.object.createSet(['a', 'b']));
    -
    -  assertObjectEquals('With no arguments',
    -                     {}, goog.object.createSet());
    -  assertObjectEquals('With an ampty array argument',
    -                     {}, goog.object.createSet([]));
    -}
    -
    -function createTestDeepObject() {
    -  var obj = {};
    -  obj.a = {};
    -  obj.a.b = {};
    -  obj.a.b.c = {};
    -  obj.a.b.c.fooArr = [5, 6, 7, 8];
    -  obj.a.b.c.knownNull = null;
    -  return obj;
    -}
    -
    -function testGetValueByKeys() {
    -  var obj = createTestDeepObject();
    -  assertEquals(obj, goog.object.getValueByKeys(obj));
    -  assertEquals(obj.a, goog.object.getValueByKeys(obj, 'a'));
    -  assertEquals(obj.a.b, goog.object.getValueByKeys(obj, 'a', 'b'));
    -  assertEquals(obj.a.b.c, goog.object.getValueByKeys(obj, 'a', 'b', 'c'));
    -  assertEquals(obj.a.b.c.d,
    -               goog.object.getValueByKeys(obj, 'a', 'b', 'c', 'd'));
    -  assertEquals(8, goog.object.getValueByKeys(obj, 'a', 'b', 'c', 'fooArr', 3));
    -  assertNull(goog.object.getValueByKeys(obj, 'a', 'b', 'c', 'knownNull'));
    -  assertUndefined(goog.object.getValueByKeys(obj, 'e', 'f', 'g'));
    -}
    -
    -function testGetValueByKeysArraySyntax() {
    -  var obj = createTestDeepObject();
    -  assertEquals(obj, goog.object.getValueByKeys(obj, []));
    -  assertEquals(obj.a, goog.object.getValueByKeys(obj, ['a']));
    -
    -  assertEquals(obj.a.b, goog.object.getValueByKeys(obj, ['a', 'b']));
    -  assertEquals(obj.a.b.c, goog.object.getValueByKeys(obj, ['a', 'b', 'c']));
    -  assertEquals(obj.a.b.c.d,
    -      goog.object.getValueByKeys(obj, ['a', 'b', 'c', 'd']));
    -  assertEquals(8,
    -      goog.object.getValueByKeys(obj, ['a', 'b', 'c', 'fooArr', 3]));
    -  assertNull(goog.object.getValueByKeys(obj, ['a', 'b', 'c', 'knownNull']));
    -  assertUndefined(goog.object.getValueByKeys(obj, 'e', 'f', 'g'));
    -}
    -
    -function testImmutableView() {
    -  if (!Object.isFrozen) {
    -    return;
    -  }
    -  var x = {propA: 3};
    -  var y = goog.object.createImmutableView(x);
    -  x.propA = 4;
    -  x.propB = 6;
    -  y.propA = 5;
    -  y.propB = 7;
    -  assertEquals(4, x.propA);
    -  assertEquals(6, x.propB);
    -  assertFalse(goog.object.isImmutableView(x));
    -
    -  assertEquals(4, y.propA);
    -  assertEquals(6, y.propB);
    -  assertTrue(goog.object.isImmutableView(y));
    -
    -  assertFalse('x and y should be different references', x == y);
    -  assertTrue(
    -      'createImmutableView should not create a new view of an immutable object',
    -      y == goog.object.createImmutableView(y));
    -}
    -
    -function testImmutableViewStrict() {
    -  'use strict';
    -
    -  // IE9 supports isFrozen, but does not support strict mode. Exit early if we
    -  // are not actually running in strict mode.
    -  var isStrict = (function() { return !this; })();
    -
    -  if (!Object.isFrozen || !isStrict) {
    -    return;
    -  }
    -  var x = {propA: 3};
    -  var y = goog.object.createImmutableView(x);
    -  assertThrows(function() {
    -    y.propA = 4;
    -  });
    -  assertThrows(function() {
    -    y.propB = 4;
    -  });
    -}
    -
    -function testEmptyObjectsAreEqual() {
    -  assertTrue(goog.object.equals({}, {}));
    -}
    -
    -function testObjectsWithDifferentKeysAreUnequal() {
    -  assertFalse(goog.object.equals({'a': 1}, {'b': 1}));
    -}
    -
    -function testObjectsWithDifferentValuesAreUnequal() {
    -  assertFalse(goog.object.equals({'a': 1}, {'a': 2}));
    -}
    -
    -function testObjectsWithSameKeysAndValuesAreEqual() {
    -  assertTrue(goog.object.equals({'a': 1}, {'a': 1}));
    -}
    -
    -function testObjectsWithSameKeysInDifferentOrderAreEqual() {
    -  assertTrue(goog.object.equals({'a': 1, 'b': 2}, {'b': 2, 'a': 1}));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/positioning/absoluteposition.js b/src/database/third_party/closure-library/closure/goog/positioning/absoluteposition.js
    deleted file mode 100644
    index c5ff190377b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/positioning/absoluteposition.js
    +++ /dev/null
    @@ -1,73 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Client viewport positioning class.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - */
    -
    -goog.provide('goog.positioning.AbsolutePosition');
    -
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.positioning');
    -goog.require('goog.positioning.AbstractPosition');
    -
    -
    -
    -/**
    - * Encapsulates a popup position where the popup absolutely positioned by
    - * setting the left/top style elements directly to the specified values.
    - * The position is generally relative to the element's offsetParent. Normally,
    - * this is the document body, but can be another element if the popup element
    - * is scoped by an element with relative position.
    - *
    - * @param {number|!goog.math.Coordinate} arg1 Left position or coordinate.
    - * @param {number=} opt_arg2 Top position.
    - * @constructor
    - * @extends {goog.positioning.AbstractPosition}
    - */
    -goog.positioning.AbsolutePosition = function(arg1, opt_arg2) {
    -  /**
    -   * Coordinate to position popup at.
    -   * @type {goog.math.Coordinate}
    -   */
    -  this.coordinate = arg1 instanceof goog.math.Coordinate ? arg1 :
    -      new goog.math.Coordinate(/** @type {number} */ (arg1), opt_arg2);
    -};
    -goog.inherits(goog.positioning.AbsolutePosition,
    -              goog.positioning.AbstractPosition);
    -
    -
    -/**
    - * Repositions the popup according to the current state.
    - *
    - * @param {Element} movableElement The DOM element to position.
    - * @param {goog.positioning.Corner} movableCorner The corner of the movable
    - *     element that should be positioned at the specified position.
    - * @param {goog.math.Box=} opt_margin A margin specified in pixels.
    - * @param {goog.math.Size=} opt_preferredSize Prefered size of the
    - *     movableElement.
    - * @override
    - */
    -goog.positioning.AbsolutePosition.prototype.reposition = function(
    -    movableElement, movableCorner, opt_margin, opt_preferredSize) {
    -  goog.positioning.positionAtCoordinate(this.coordinate,
    -                                        movableElement,
    -                                        movableCorner,
    -                                        opt_margin,
    -                                        null,
    -                                        null,
    -                                        opt_preferredSize);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/positioning/abstractposition.js b/src/database/third_party/closure-library/closure/goog/positioning/abstractposition.js
    deleted file mode 100644
    index 439c4f18b77..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/positioning/abstractposition.js
    +++ /dev/null
    @@ -1,44 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Abstract base class for positioning implementations.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - */
    -
    -goog.provide('goog.positioning.AbstractPosition');
    -
    -
    -
    -/**
    - * Abstract position object. Encapsulates position and overflow handling.
    - *
    - * @constructor
    - */
    -goog.positioning.AbstractPosition = function() {};
    -
    -
    -/**
    - * Repositions the element. Abstract method, should be overloaded.
    - *
    - * @param {Element} movableElement Element to position.
    - * @param {goog.positioning.Corner} corner Corner of the movable element that
    - *     should be positioned adjacent to the anchored element.
    - * @param {goog.math.Box=} opt_margin A margin specified in pixels.
    - * @param {goog.math.Size=} opt_preferredSize PreferredSize of the
    - *     movableElement.
    - */
    -goog.positioning.AbstractPosition.prototype.reposition =
    -    function(movableElement, corner, opt_margin, opt_preferredSize) { };
    diff --git a/src/database/third_party/closure-library/closure/goog/positioning/anchoredposition.js b/src/database/third_party/closure-library/closure/goog/positioning/anchoredposition.js
    deleted file mode 100644
    index 7374860a8db..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/positioning/anchoredposition.js
    +++ /dev/null
    @@ -1,92 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Client positioning class.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - */
    -
    -goog.provide('goog.positioning.AnchoredPosition');
    -
    -goog.require('goog.positioning');
    -goog.require('goog.positioning.AbstractPosition');
    -
    -
    -
    -/**
    - * Encapsulates a popup position where the popup is anchored at a corner of
    - * an element.
    - *
    - * When using AnchoredPosition, it is recommended that the popup element
    - * specified in the Popup constructor or Popup.setElement be absolutely
    - * positioned.
    - *
    - * @param {Element} anchorElement Element the movable element should be
    - *     anchored against.
    - * @param {goog.positioning.Corner} corner Corner of anchored element the
    - *     movable element should be positioned at.
    - * @param {number=} opt_overflow Overflow handling mode. Defaults to IGNORE if
    - *     not specified. Bitmap, {@see goog.positioning.Overflow}.
    - * @constructor
    - * @extends {goog.positioning.AbstractPosition}
    - */
    -goog.positioning.AnchoredPosition = function(anchorElement,
    -                                             corner,
    -                                             opt_overflow) {
    -  /**
    -   * Element the movable element should be anchored against.
    -   * @type {Element}
    -   */
    -  this.element = anchorElement;
    -
    -  /**
    -   * Corner of anchored element the movable element should be positioned at.
    -   * @type {goog.positioning.Corner}
    -   */
    -  this.corner = corner;
    -
    -  /**
    -   * Overflow handling mode. Defaults to IGNORE if not specified.
    -   * Bitmap, {@see goog.positioning.Overflow}.
    -   * @type {number|undefined}
    -   * @private
    -   */
    -  this.overflow_ = opt_overflow;
    -};
    -goog.inherits(goog.positioning.AnchoredPosition,
    -              goog.positioning.AbstractPosition);
    -
    -
    -/**
    - * Repositions the movable element.
    - *
    - * @param {Element} movableElement Element to position.
    - * @param {goog.positioning.Corner} movableCorner Corner of the movable element
    - *     that should be positioned adjacent to the anchored element.
    - * @param {goog.math.Box=} opt_margin A margin specifin pixels.
    - * @param {goog.math.Size=} opt_preferredSize PreferredSize of the
    - *     movableElement (unused in this class).
    - * @override
    - */
    -goog.positioning.AnchoredPosition.prototype.reposition = function(
    -    movableElement, movableCorner, opt_margin, opt_preferredSize) {
    -  goog.positioning.positionAtAnchor(this.element,
    -                                    this.corner,
    -                                    movableElement,
    -                                    movableCorner,
    -                                    undefined,
    -                                    opt_margin,
    -                                    this.overflow_);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/positioning/anchoredposition_test.html b/src/database/third_party/closure-library/closure/goog/positioning/anchoredposition_test.html
    deleted file mode 100644
    index e3c813cf138..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/positioning/anchoredposition_test.html
    +++ /dev/null
    @@ -1,28 +0,0 @@
    -<!DOCTYPE HTML>
    -<!--
    -
    --->
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.positioning.AnchoredPosition
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.positioning.AnchoredPositionTest');
    -  </script>
    - </head>
    - <body>
    -  <!-- Use IFRAME to avoid non-deterministic window size problems in Selenium. -->
    -  <iframe id="frame1" style="width:200px; height:200px;" src="anchoredviewportposition_test_iframe.html">
    -  </iframe>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/positioning/anchoredposition_test.js b/src/database/third_party/closure-library/closure/goog/positioning/anchoredposition_test.js
    deleted file mode 100644
    index 4603b7d3d85..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/positioning/anchoredposition_test.js
    +++ /dev/null
    @@ -1,68 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.positioning.AnchoredPositionTest');
    -goog.setTestOnly('goog.positioning.AnchoredPositionTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.positioning.AnchoredPosition');
    -goog.require('goog.positioning.Corner');
    -goog.require('goog.positioning.Overflow');
    -goog.require('goog.style');
    -goog.require('goog.testing.jsunit');
    -
    -var frame, doc, dom, viewportSize, anchor, popup;
    -var corner = goog.positioning.Corner;
    -var popupLength = 20;
    -var anchorLength = 100;
    -
    -function setUp() {
    -  frame = document.getElementById('frame1');
    -  doc = goog.dom.getFrameContentDocument(frame);
    -  dom = goog.dom.getDomHelper(doc);
    -  viewportSize = dom.getViewportSize();
    -  anchor = dom.getElement('anchor');
    -  popup = dom.getElement('popup');
    -  goog.style.setSize(popup, popupLength, popupLength);
    -  goog.style.setPosition(popup, popupLength, popupLength);
    -  goog.style.setSize(anchor, anchorLength, anchorLength);
    -}
    -
    -// No enough space at the bottom and no overflow adjustment.
    -function testRepositionWithDefaultOverflow() {
    -  var avp = new goog.positioning.AnchoredPosition(
    -      anchor, corner.BOTTOM_LEFT);
    -  var newTop = viewportSize.height - anchorLength;
    -  goog.style.setPosition(anchor, 50, newTop);
    -  var anchorRect = goog.style.getBounds(anchor);
    -
    -  avp.reposition(popup, corner.TOP_LEFT);
    -  var popupRect = goog.style.getBounds(popup);
    -  assertEquals(anchorRect.top + anchorRect.height, popupRect.top);
    -}
    -
    -// No enough space at the bottom and ADJUST_Y overflow adjustment.
    -function testRepositionWithOverflow() {
    -  var avp = new goog.positioning.AnchoredPosition(
    -      anchor, corner.BOTTOM_LEFT,
    -      goog.positioning.Overflow.ADJUST_Y);
    -  var newTop = viewportSize.height - anchorLength;
    -  goog.style.setPosition(anchor, 50, newTop);
    -  var anchorRect = goog.style.getBounds(anchor);
    -
    -  avp.reposition(popup, corner.TOP_LEFT);
    -  var popupRect = goog.style.getBounds(popup);
    -  assertEquals(anchorRect.top + anchorRect.height,
    -      popupRect.top + popupRect.height);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/positioning/anchoredviewportposition.js b/src/database/third_party/closure-library/closure/goog/positioning/anchoredviewportposition.js
    deleted file mode 100644
    index dfc7c1ed278..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/positioning/anchoredviewportposition.js
    +++ /dev/null
    @@ -1,189 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Anchored viewport positioning class.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - */
    -
    -goog.provide('goog.positioning.AnchoredViewportPosition');
    -
    -goog.require('goog.positioning');
    -goog.require('goog.positioning.AnchoredPosition');
    -goog.require('goog.positioning.Overflow');
    -goog.require('goog.positioning.OverflowStatus');
    -
    -
    -
    -/**
    - * Encapsulates a popup position where the popup is anchored at a corner of
    - * an element. The corners are swapped if dictated by the viewport. For instance
    - * if a popup is anchored with its top left corner to the bottom left corner of
    - * the anchor the popup is either displayed below the anchor (as specified) or
    - * above it if there's not enough room to display it below.
    - *
    - * When using this positioning object it's recommended that the movable element
    - * be absolutely positioned.
    - *
    - * @param {Element} anchorElement Element the movable element should be
    - *     anchored against.
    - * @param {goog.positioning.Corner} corner Corner of anchored element the
    - *     movable element should be positioned at.
    - * @param {boolean=} opt_adjust Whether the positioning should be adjusted until
    - *     the element fits inside the viewport even if that means that the anchored
    - *     corners are ignored.
    - * @param {goog.math.Box=} opt_overflowConstraint Box object describing the
    - *     dimensions in which the movable element could be shown.
    - * @constructor
    - * @extends {goog.positioning.AnchoredPosition}
    - */
    -goog.positioning.AnchoredViewportPosition = function(anchorElement,
    -                                                     corner,
    -                                                     opt_adjust,
    -                                                     opt_overflowConstraint) {
    -  goog.positioning.AnchoredPosition.call(this, anchorElement, corner);
    -
    -  /**
    -   * The last resort algorithm to use if the algorithm can't fit inside
    -   * the viewport.
    -   *
    -   * IGNORE = do nothing, just display at the preferred position.
    -   *
    -   * ADJUST_X | ADJUST_Y = Adjust until the element fits, even if that means
    -   * that the anchored corners are ignored.
    -   *
    -   * @type {number}
    -   * @private
    -   */
    -  this.lastResortOverflow_ = opt_adjust ?
    -      (goog.positioning.Overflow.ADJUST_X |
    -       goog.positioning.Overflow.ADJUST_Y) :
    -      goog.positioning.Overflow.IGNORE;
    -
    -  /**
    -   * The dimensions in which the movable element could be shown.
    -   * @type {goog.math.Box|undefined}
    -   * @private
    -   */
    -  this.overflowConstraint_ = opt_overflowConstraint || undefined;
    -};
    -goog.inherits(goog.positioning.AnchoredViewportPosition,
    -              goog.positioning.AnchoredPosition);
    -
    -
    -/**
    - * @return {goog.math.Box|undefined} The box object describing the
    - *     dimensions in which the movable element will be shown.
    - */
    -goog.positioning.AnchoredViewportPosition.prototype.getOverflowConstraint =
    -    function() {
    -  return this.overflowConstraint_;
    -};
    -
    -
    -/**
    - * @param {goog.math.Box|undefined} overflowConstraint Box object describing the
    - *     dimensions in which the movable element could be shown.
    - */
    -goog.positioning.AnchoredViewportPosition.prototype.setOverflowConstraint =
    -    function(overflowConstraint) {
    -  this.overflowConstraint_ = overflowConstraint;
    -};
    -
    -
    -/**
    - * @return {number} A bitmask for the "last resort" overflow.
    - */
    -goog.positioning.AnchoredViewportPosition.prototype.getLastResortOverflow =
    -    function() {
    -  return this.lastResortOverflow_;
    -};
    -
    -
    -/**
    - * @param {number} lastResortOverflow A bitmask for the "last resort" overflow,
    - *     if we fail to fit the element on-screen.
    - */
    -goog.positioning.AnchoredViewportPosition.prototype.setLastResortOverflow =
    -    function(lastResortOverflow) {
    -  this.lastResortOverflow_ = lastResortOverflow;
    -};
    -
    -
    -/**
    - * Repositions the movable element.
    - *
    - * @param {Element} movableElement Element to position.
    - * @param {goog.positioning.Corner} movableCorner Corner of the movable element
    - *     that should be positioned adjacent to the anchored element.
    - * @param {goog.math.Box=} opt_margin A margin specified in pixels.
    - * @param {goog.math.Size=} opt_preferredSize The preferred size of the
    - *     movableElement.
    - * @override
    - */
    -goog.positioning.AnchoredViewportPosition.prototype.reposition = function(
    -    movableElement, movableCorner, opt_margin, opt_preferredSize) {
    -  var status = goog.positioning.positionAtAnchor(this.element, this.corner,
    -      movableElement, movableCorner, null, opt_margin,
    -      goog.positioning.Overflow.FAIL_X | goog.positioning.Overflow.FAIL_Y,
    -      opt_preferredSize, this.overflowConstraint_);
    -
    -  // If the desired position is outside the viewport try mirroring the corners
    -  // horizontally or vertically.
    -  if (status & goog.positioning.OverflowStatus.FAILED) {
    -    var cornerFallback = this.adjustCorner(status, this.corner);
    -    var movableCornerFallback = this.adjustCorner(status, movableCorner);
    -
    -    status = goog.positioning.positionAtAnchor(this.element, cornerFallback,
    -        movableElement, movableCornerFallback, null, opt_margin,
    -        goog.positioning.Overflow.FAIL_X | goog.positioning.Overflow.FAIL_Y,
    -        opt_preferredSize, this.overflowConstraint_);
    -
    -    if (status & goog.positioning.OverflowStatus.FAILED) {
    -      // If that also fails, pick the best corner from the two tries,
    -      // and adjust the position until it fits.
    -      cornerFallback = this.adjustCorner(status, cornerFallback);
    -      movableCornerFallback = this.adjustCorner(
    -          status, movableCornerFallback);
    -
    -      goog.positioning.positionAtAnchor(this.element, cornerFallback,
    -          movableElement, movableCornerFallback, null, opt_margin,
    -          this.getLastResortOverflow(), opt_preferredSize,
    -          this.overflowConstraint_);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Adjusts the corner if X or Y positioning failed.
    - * @param {number} status The status of the last positionAtAnchor call.
    - * @param {goog.positioning.Corner} corner The corner to adjust.
    - * @return {goog.positioning.Corner} The adjusted corner.
    - * @protected
    - */
    -goog.positioning.AnchoredViewportPosition.prototype.adjustCorner = function(
    -    status, corner) {
    -  if (status & goog.positioning.OverflowStatus.FAILED_HORIZONTAL) {
    -    corner = goog.positioning.flipCornerHorizontal(corner);
    -  }
    -
    -  if (status & goog.positioning.OverflowStatus.FAILED_VERTICAL) {
    -    corner = goog.positioning.flipCornerVertical(corner);
    -  }
    -
    -  return corner;
    -};
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/positioning/anchoredviewportposition_test.html b/src/database/third_party/closure-library/closure/goog/positioning/anchoredviewportposition_test.html
    deleted file mode 100644
    index 1f8d326847c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/positioning/anchoredviewportposition_test.html
    +++ /dev/null
    @@ -1,28 +0,0 @@
    -<!DOCTYPE HTML>
    -<!--
    -
    --->
    -<html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.positioning.AnchoredViewportPosition
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.positioning.AnchoredViewportPositionTest');
    -  </script>
    - </head>
    - <body>
    -  <!-- Use IFRAME to avoid non-deterministic window size problems in Selenium. -->
    -  <iframe id="frame1" style="width:200px; height:200px;" src="anchoredviewportposition_test_iframe.html">
    -  </iframe>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/positioning/anchoredviewportposition_test.js b/src/database/third_party/closure-library/closure/goog/positioning/anchoredviewportposition_test.js
    deleted file mode 100644
    index 2f336b3a847..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/positioning/anchoredviewportposition_test.js
    +++ /dev/null
    @@ -1,165 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.positioning.AnchoredViewportPositionTest');
    -goog.setTestOnly('goog.positioning.AnchoredViewportPositionTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.math.Box');
    -goog.require('goog.positioning.AnchoredViewportPosition');
    -goog.require('goog.positioning.Corner');
    -goog.require('goog.positioning.OverflowStatus');
    -goog.require('goog.style');
    -goog.require('goog.testing.jsunit');
    -
    -var frame, doc, dom, viewportSize, anchor, popup;
    -var corner = goog.positioning.Corner;
    -
    -function setUp() {
    -  frame = document.getElementById('frame1');
    -  doc = goog.dom.getFrameContentDocument(frame);
    -  dom = goog.dom.getDomHelper(doc);
    -  viewportSize = dom.getViewportSize();
    -  anchor = dom.getElement('anchor');
    -  popup = dom.getElement('popup');
    -  goog.style.setSize(popup, 20, 20);
    -}
    -
    -// The frame has enough space at the bottom of the anchor.
    -function testRepositionBottom() {
    -  var avp = new goog.positioning.AnchoredViewportPosition(
    -      anchor, corner.BOTTOM_LEFT, false);
    -  goog.style.setSize(anchor, 100, 100);
    -  goog.style.setPosition(anchor, 0, 0);
    -  assertTrue(viewportSize.height >= 100 + 20);
    -
    -  avp.reposition(popup, corner.TOP_LEFT);
    -  var anchorRect = goog.style.getBounds(anchor);
    -  assertEquals(anchorRect.top + anchorRect.height,
    -               goog.style.getPageOffset(popup).y);
    -}
    -
    -// No enough space at the bottom, but at the top.
    -function testRepositionTop() {
    -  var avp = new goog.positioning.AnchoredViewportPosition(
    -      anchor, corner.BOTTOM_LEFT, false);
    -  var newTop = viewportSize.height - 100;
    -  goog.style.setSize(anchor, 100, 100);
    -  goog.style.setPosition(anchor, 50, newTop);
    -  assertTrue(newTop >= 20);
    -
    -  avp.reposition(popup, corner.TOP_LEFT);
    -  anchorRect = goog.style.getBounds(anchor);
    -  var popupRect = goog.style.getBounds(popup);
    -  assertEquals(anchorRect.top, popupRect.top + popupRect.height);
    -}
    -
    -// Not enough space either at the bottom or right but there is enough space at
    -// top left.
    -function testRepositionBottomRight() {
    -  var avp = new goog.positioning.AnchoredViewportPosition(
    -      anchor, corner.BOTTOM_RIGHT, false);
    -  goog.style.setSize(anchor, 100, 100);
    -  goog.style.setPosition(anchor, viewportSize.width - 110,
    -      viewportSize.height - 110);
    -
    -  avp.reposition(popup, corner.TOP_LEFT);
    -  anchorRect = goog.style.getBounds(anchor);
    -  var popupRect = goog.style.getBounds(popup);
    -  assertEquals(anchorRect.top, popupRect.top + popupRect.height);
    -  assertEquals(anchorRect.left, popupRect.left + popupRect.width);
    -}
    -
    -// Enough space at neither the bottom nor the top.  Adjustment flag is false.
    -function testRepositionNoSpaceWithoutAdjustment() {
    -  var avp = new goog.positioning.AnchoredViewportPosition(
    -      anchor, corner.BOTTOM_LEFT, false);
    -  goog.style.setPosition(anchor, 50, 10);
    -  goog.style.setSize(anchor, 100, viewportSize.height - 20);
    -
    -  avp.reposition(popup, corner.TOP_LEFT);
    -  anchorRect = goog.style.getBounds(anchor);
    -  popupRect = goog.style.getBounds(popup);
    -  assertEquals(anchorRect.top + anchorRect.height, popupRect.top);
    -  assertTrue(popupRect.top + popupRect.height > viewportSize.height);
    -}
    -
    -// Enough space at neither the bottom nor the top.  Adjustment flag is true.
    -function testRepositionNoSpaceWithAdjustment() {
    -  var avp = new goog.positioning.AnchoredViewportPosition(
    -      anchor, corner.BOTTOM_LEFT, true);
    -  goog.style.setPosition(anchor, 50, 10);
    -  goog.style.setSize(anchor, 100, viewportSize.height - 20);
    -
    -  avp.reposition(popup, corner.TOP_LEFT);
    -  anchorRect = goog.style.getBounds(anchor);
    -  popupRect = goog.style.getBounds(popup);
    -  assertTrue(anchorRect.top + anchorRect.height > popupRect.top);
    -  assertEquals(viewportSize.height, popupRect.top + popupRect.height);
    -}
    -
    -function testAdjustCorner() {
    -  var avp = new goog.positioning.AnchoredViewportPosition(
    -      anchor, corner.BOTTOM_LEFT);
    -  assertEquals(corner.BOTTOM_LEFT, avp.adjustCorner(0, corner.BOTTOM_LEFT));
    -  assertEquals(corner.BOTTOM_RIGHT, avp.adjustCorner(
    -      goog.positioning.OverflowStatus.FAILED_HORIZONTAL, corner.BOTTOM_LEFT));
    -  assertEquals(corner.TOP_LEFT, avp.adjustCorner(
    -      goog.positioning.OverflowStatus.FAILED_VERTICAL, corner.BOTTOM_LEFT));
    -  assertEquals(corner.TOP_RIGHT, avp.adjustCorner(
    -      goog.positioning.OverflowStatus.FAILED_VERTICAL |
    -      goog.positioning.OverflowStatus.FAILED_HORIZONTAL,
    -      corner.BOTTOM_LEFT));
    -}
    -
    -// No space to fit, so uses fallback.
    -function testOverflowConstraint() {
    -  var tinyBox = new goog.math.Box(0, 0, 0, 0);
    -  var avp = new goog.positioning.AnchoredViewportPosition(
    -      anchor, corner.BOTTOM_LEFT, false, tinyBox);
    -  assertEquals(tinyBox, avp.getOverflowConstraint());
    -
    -  goog.style.setSize(anchor, 50, 50);
    -  goog.style.setPosition(anchor, 80, 80);
    -  avp.reposition(popup, corner.TOP_LEFT);
    -
    -  anchorRect = goog.style.getBounds(anchor);
    -  popupRect = goog.style.getBounds(popup);
    -  assertEquals(anchorRect.left, popupRect.left);
    -  assertEquals(anchorRect.top + anchorRect.height, popupRect.top);
    -}
    -
    -// Initially no space to fit above, then changes to have room.
    -function testChangeOverflowConstraint() {
    -  var tinyBox = new goog.math.Box(0, 0, 0, 0);
    -  var avp = new goog.positioning.AnchoredViewportPosition(
    -      anchor, corner.BOTTOM_LEFT, false, tinyBox);
    -  assertEquals(tinyBox, avp.getOverflowConstraint());
    -
    -  goog.style.setSize(anchor, 50, 50);
    -  goog.style.setPosition(anchor, 80, 80);
    -
    -  avp.reposition(popup, corner.TOP_LEFT);
    -  popupRect = goog.style.getBounds(popup);
    -  assertNotEquals(60, popupRect.top);
    -
    -  var movedBox = new goog.math.Box(60, 100, 100, 60);
    -  avp.setOverflowConstraint(movedBox);
    -  assertEquals(movedBox, avp.getOverflowConstraint());
    -
    -  avp.reposition(popup, corner.TOP_LEFT);
    -  popupRect = goog.style.getBounds(popup);
    -  assertEquals(80, popupRect.left);
    -  assertEquals(60, popupRect.top);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/positioning/anchoredviewportposition_test_iframe.html b/src/database/third_party/closure-library/closure/goog/positioning/anchoredviewportposition_test_iframe.html
    deleted file mode 100644
    index a9b7e5eb334..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/positioning/anchoredviewportposition_test_iframe.html
    +++ /dev/null
    @@ -1,35 +0,0 @@
    -<!DOCTYPE HTML>
    -<!--
    -
    --->
    -<html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -  <style>
    -    .bar {
    -      position: absolute;
    -      text-align: center;
    -      overflow: hidden;
    -    }
    -
    -    #anchor {
    -      background: blue;
    -    }
    -
    -    #popup {
    -      background: red;
    -    }
    -  </style>
    -</head>
    -<body>
    -  <div id="anchor" class="bar">anchor</div>
    -  <div id="popup" class="bar">popup</div>
    -</body>
    -</html>
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/positioning/clientposition.js b/src/database/third_party/closure-library/closure/goog/positioning/clientposition.js
    deleted file mode 100644
    index 05e4f01e140..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/positioning/clientposition.js
    +++ /dev/null
    @@ -1,89 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Client positioning class.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - * @author chrishenry@google.com (Chris Henry)
    - */
    -
    -goog.provide('goog.positioning.ClientPosition');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.positioning');
    -goog.require('goog.positioning.AbstractPosition');
    -goog.require('goog.style');
    -
    -
    -
    -/**
    - * Encapsulates a popup position where the popup is positioned relative to the
    - * window (client) coordinates. This calculates the correct position to
    - * use even if the element is relatively positioned to some other element. This
    - * is for trying to position an element at the spot of the mouse cursor in
    - * a MOUSEMOVE event. Just use the event.clientX and event.clientY as the
    - * parameters.
    - *
    - * @param {number|goog.math.Coordinate} arg1 Left position or coordinate.
    - * @param {number=} opt_arg2 Top position.
    - * @constructor
    - * @extends {goog.positioning.AbstractPosition}
    - */
    -goog.positioning.ClientPosition = function(arg1, opt_arg2) {
    -  /**
    -   * Coordinate to position popup at.
    -   * @type {goog.math.Coordinate}
    -   */
    -  this.coordinate = arg1 instanceof goog.math.Coordinate ? arg1 :
    -      new goog.math.Coordinate(/** @type {number} */ (arg1), opt_arg2);
    -};
    -goog.inherits(goog.positioning.ClientPosition,
    -              goog.positioning.AbstractPosition);
    -
    -
    -/**
    - * Repositions the popup according to the current state
    - *
    - * @param {Element} movableElement The DOM element of the popup.
    - * @param {goog.positioning.Corner} movableElementCorner The corner of
    - *     the popup element that that should be positioned adjacent to
    - *     the anchorElement.  One of the goog.positioning.Corner
    - *     constants.
    - * @param {goog.math.Box=} opt_margin A margin specified in pixels.
    - * @param {goog.math.Size=} opt_preferredSize Preferred size of the element.
    - * @override
    - */
    -goog.positioning.ClientPosition.prototype.reposition = function(
    -    movableElement, movableElementCorner, opt_margin, opt_preferredSize) {
    -  goog.asserts.assert(movableElement);
    -
    -  // Translates the coordinate to be relative to the page.
    -  var viewportOffset = goog.style.getViewportPageOffset(
    -      goog.dom.getOwnerDocument(movableElement));
    -  var x = this.coordinate.x + viewportOffset.x;
    -  var y = this.coordinate.y + viewportOffset.y;
    -
    -  // Translates the coordinate to be relative to the offset parent.
    -  var movableParentTopLeft =
    -      goog.positioning.getOffsetParentPageOffset(movableElement);
    -  x -= movableParentTopLeft.x;
    -  y -= movableParentTopLeft.y;
    -
    -  goog.positioning.positionAtCoordinate(
    -      new goog.math.Coordinate(x, y), movableElement, movableElementCorner,
    -      opt_margin, null, null, opt_preferredSize);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/positioning/clientposition_test.html b/src/database/third_party/closure-library/closure/goog/positioning/clientposition_test.html
    deleted file mode 100644
    index b2c26bf9333..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/positioning/clientposition_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -  Author: chrishenry@google.com (Chris Henry)
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.positioning.ClientPosition</title>
    -<script src="../base.js"></script>
    -<script>
    -goog.require('goog.positioning.clientPositionTest');
    -</script>
    -</head>
    -<body>
    -<div id="test-area"></div>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/positioning/clientposition_test.js b/src/database/third_party/closure-library/closure/goog/positioning/clientposition_test.js
    deleted file mode 100644
    index 9e63476b5dc..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/positioning/clientposition_test.js
    +++ /dev/null
    @@ -1,124 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * Tests for {@code goog.positioning.ClientPosition}
    - * @author chrishenry@google.com (Chris Henry)
    - */
    -
    -goog.provide('goog.positioning.clientPositionTest');
    -goog.setTestOnly('goog.positioning.clientPositionTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.positioning.ClientPosition');
    -goog.require('goog.positioning.Corner');
    -goog.require('goog.style');
    -goog.require('goog.testing.jsunit');
    -
    -
    -/**
    - * Prefabricated popup element for convenient. This is created during
    - * setUp and is not attached to the document at the beginning of the
    - * test.
    - * @type {Element}
    - */
    -var popupElement;
    -var testArea;
    -var POPUP_HEIGHT = 100;
    -var POPUP_WIDTH = 150;
    -
    -
    -function setUp() {
    -  testArea = goog.dom.getElement('test-area');
    -
    -  // Enlarges the test area to 5000x5000px so that we can be confident
    -  // that scrolling the document to some small (x,y) value would work.
    -  goog.style.setSize(testArea, 5000, 5000);
    -
    -  window.scrollTo(0, 0);
    -
    -  popupElement = goog.dom.createDom('div');
    -  goog.style.setSize(popupElement, POPUP_WIDTH, POPUP_HEIGHT);
    -  popupElement.style.position = 'absolute';
    -
    -  // For ease of debugging.
    -  popupElement.style.background = 'blue';
    -}
    -
    -
    -function tearDown() {
    -  popupElement = null;
    -  testArea.innerHTML = '';
    -  testArea.setAttribute('style', '');
    -}
    -
    -
    -function testClientPositionWithZeroViewportOffset() {
    -  goog.dom.appendChild(testArea, popupElement);
    -
    -  var x = 300;
    -  var y = 200;
    -  var pos = new goog.positioning.ClientPosition(x, y);
    -
    -  pos.reposition(popupElement, goog.positioning.Corner.TOP_LEFT);
    -  assertPageOffset(x, y, popupElement);
    -
    -  pos.reposition(popupElement, goog.positioning.Corner.TOP_RIGHT);
    -  assertPageOffset(x - POPUP_WIDTH, y, popupElement);
    -
    -  pos.reposition(popupElement, goog.positioning.Corner.BOTTOM_LEFT);
    -  assertPageOffset(x, y - POPUP_HEIGHT, popupElement);
    -
    -  pos.reposition(popupElement, goog.positioning.Corner.BOTTOM_RIGHT);
    -  assertPageOffset(x - POPUP_WIDTH, y - POPUP_HEIGHT, popupElement);
    -}
    -
    -
    -function testClientPositionWithSomeViewportOffset() {
    -  goog.dom.appendChild(testArea, popupElement);
    -
    -  var x = 300;
    -  var y = 200;
    -  var scrollX = 135;
    -  var scrollY = 270;
    -  window.scrollTo(scrollX, scrollY);
    -
    -  var pos = new goog.positioning.ClientPosition(x, y);
    -  pos.reposition(popupElement, goog.positioning.Corner.TOP_LEFT);
    -  assertPageOffset(scrollX + x, scrollY + y, popupElement);
    -}
    -
    -
    -function testClientPositionWithPositionContext() {
    -  var contextAbsoluteX = 90;
    -  var contextAbsoluteY = 110;
    -  var x = 300;
    -  var y = 200;
    -
    -  var contextElement = goog.dom.createDom('div', undefined, popupElement);
    -  goog.style.setPosition(contextElement, contextAbsoluteX, contextAbsoluteY);
    -  contextElement.style.position = 'absolute';
    -  goog.dom.appendChild(testArea, contextElement);
    -
    -  var pos = new goog.positioning.ClientPosition(x, y);
    -  pos.reposition(popupElement, goog.positioning.Corner.TOP_LEFT);
    -  assertPageOffset(x, y, popupElement);
    -}
    -
    -
    -function assertPageOffset(expectedX, expectedY, el) {
    -  var offsetCoordinate = goog.style.getPageOffset(el);
    -  assertEquals('x-coord page offset is wrong.', expectedX, offsetCoordinate.x);
    -  assertEquals('y-coord page offset is wrong.', expectedY, offsetCoordinate.y);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/positioning/menuanchoredposition.js b/src/database/third_party/closure-library/closure/goog/positioning/menuanchoredposition.js
    deleted file mode 100644
    index 652e62c3473..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/positioning/menuanchoredposition.js
    +++ /dev/null
    @@ -1,66 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Anchored viewport positioning class with both adjust and
    - *     resize options for the popup.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - */
    -
    -goog.provide('goog.positioning.MenuAnchoredPosition');
    -
    -goog.require('goog.positioning.AnchoredViewportPosition');
    -goog.require('goog.positioning.Overflow');
    -
    -
    -
    -/**
    - * Encapsulates a popup position where the popup is anchored at a corner of
    - * an element.  The positioning behavior changes based on the values of
    - * opt_adjust and opt_resize.
    - *
    - * When using this positioning object it's recommended that the movable element
    - * be absolutely positioned.
    - *
    - * @param {Element} anchorElement Element the movable element should be
    - *     anchored against.
    - * @param {goog.positioning.Corner} corner Corner of anchored element the
    - *     movable element should be positioned at.
    - * @param {boolean=} opt_adjust Whether the positioning should be adjusted until
    - *     the element fits inside the viewport even if that means that the anchored
    - *     corners are ignored.
    - * @param {boolean=} opt_resize Whether the positioning should be adjusted until
    - *     the element fits inside the viewport on the X axis and its height is
    - *     resized so if fits in the viewport. This take precedence over opt_adjust.
    - * @constructor
    - * @extends {goog.positioning.AnchoredViewportPosition}
    - */
    -goog.positioning.MenuAnchoredPosition = function(anchorElement,
    -                                                 corner,
    -                                                 opt_adjust,
    -                                                 opt_resize) {
    -  goog.positioning.AnchoredViewportPosition.call(this, anchorElement, corner,
    -                                                 opt_adjust || opt_resize);
    -
    -  if (opt_adjust || opt_resize) {
    -    var overflowX = goog.positioning.Overflow.ADJUST_X_EXCEPT_OFFSCREEN;
    -    var overflowY = opt_resize ?
    -        goog.positioning.Overflow.RESIZE_HEIGHT :
    -        goog.positioning.Overflow.ADJUST_Y_EXCEPT_OFFSCREEN;
    -    this.setLastResortOverflow(overflowX | overflowY);
    -  }
    -};
    -goog.inherits(goog.positioning.MenuAnchoredPosition,
    -              goog.positioning.AnchoredViewportPosition);
    diff --git a/src/database/third_party/closure-library/closure/goog/positioning/menuanchoredposition_test.html b/src/database/third_party/closure-library/closure/goog/positioning/menuanchoredposition_test.html
    deleted file mode 100644
    index c90693ec854..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/positioning/menuanchoredposition_test.html
    +++ /dev/null
    @@ -1,39 +0,0 @@
    -<!DOCTYPE HTML>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    -Author: nicksantos@google.com (Nick Santos)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.positioning.MenuAnchoredPosition
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.positioning.MenuAnchoredPositionTest');
    -  </script>
    - </head>
    - <!-- Force offscreen menus to count as FAIL_X -->
    - <body style="overflow: hidden">
    -  <div id="offscreen-anchor" style="position: absolute; left: -1000px; top: -1000px">
    -  </div>
    -  <div id="onscreen-anchor" style="position: absolute; left: 5px; top: 5px">
    -  </div>
    -  <!-- The x and y positon of this anchor will be reset on each setUp -->
    -  <div id="custom-anchor" style="position: absolute;">
    -  </div>
    -  <div id="menu" style="position: absolute; left: 20px; top: 20px">
    -   Menu Item 1
    -   <br />
    -   Menu Item 2
    -   <br />
    -   Menu Item 3
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/positioning/menuanchoredposition_test.js b/src/database/third_party/closure-library/closure/goog/positioning/menuanchoredposition_test.js
    deleted file mode 100644
    index 41015cab679..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/positioning/menuanchoredposition_test.js
    +++ /dev/null
    @@ -1,95 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.positioning.MenuAnchoredPositionTest');
    -goog.setTestOnly('goog.positioning.MenuAnchoredPositionTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.positioning.Corner');
    -goog.require('goog.positioning.MenuAnchoredPosition');
    -goog.require('goog.testing.jsunit');
    -
    -var offscreenAnchor;
    -var onscreenAnchor;
    -var customAnchor;
    -var menu;
    -var corner = goog.positioning.Corner;
    -var savedMenuHtml;
    -
    -function setUp() {
    -  offscreenAnchor = goog.dom.getElement('offscreen-anchor');
    -  onscreenAnchor = goog.dom.getElement('onscreen-anchor');
    -  customAnchor = goog.dom.getElement('custom-anchor');
    -  customAnchor.style.left = '0';
    -  customAnchor.style.top = '0';
    -
    -  menu = goog.dom.getElement('menu');
    -  savedMenuHtml = menu.innerHTML;
    -  menu.style.left = '20px';
    -  menu.style.top = '20px';
    -}
    -
    -function tearDown() {
    -  menu.innerHTML = savedMenuHtml;
    -}
    -
    -function testRepositionWithAdjustAndOnscreenAnchor() {
    -  // Add so many children that it can't possibly fit onscreen.
    -  for (var i = 0; i < 200; i++) {
    -    menu.appendChild(goog.dom.createDom('div', null, 'New Item ' + i));
    -  }
    -
    -  var pos = new goog.positioning.MenuAnchoredPosition(
    -      onscreenAnchor, corner.TOP_LEFT, true);
    -  pos.reposition(menu, corner.TOP_LEFT);
    -
    -  var offset = 0;
    -  assertEquals(offset, menu.offsetTop);
    -  assertEquals(5, menu.offsetLeft);
    -}
    -
    -function testRepositionWithAdjustAndOffscreenAnchor() {
    -  // This does not get adjusted because it's too far offscreen.
    -  var pos = new goog.positioning.MenuAnchoredPosition(
    -      offscreenAnchor, corner.TOP_LEFT, true);
    -  pos.reposition(menu, corner.TOP_LEFT);
    -
    -  assertEquals(-1000, menu.offsetTop);
    -  assertEquals(-1000, menu.offsetLeft);
    -}
    -
    -function testRespositionFailoverEvenWhenResizeHeightIsOn() {
    -  var pos = new goog.positioning.MenuAnchoredPosition(
    -      onscreenAnchor, corner.TOP_LEFT, true, true);
    -  pos.reposition(menu, corner.TOP_RIGHT);
    -
    -  // The menu should not get positioned offscreen.
    -  assertEquals(5, menu.offsetTop);
    -  assertEquals(5, menu.offsetLeft);
    -}
    -
    -function testRepositionToBottomLeftWhenBottomFailsAndRightFailsAndResizeOn() {
    -  var pageSize = goog.dom.getViewportSize();
    -  customAnchor.style.left = (pageSize.width - 10) + 'px';
    -
    -  // Add so many children that it can't possibly fit onscreen.
    -  for (var i = 0; i < 200; i++) {
    -    menu.appendChild(goog.dom.createDom('div', null, 'New Item ' + i));
    -  }
    -
    -  var pos = new goog.positioning.MenuAnchoredPosition(
    -      customAnchor, corner.TOP_LEFT, true, true);
    -  pos.reposition(menu, corner.TOP_LEFT);
    -  assertEquals(menu.offsetLeft + menu.offsetWidth, customAnchor.offsetLeft);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/positioning/positioning.js b/src/database/third_party/closure-library/closure/goog/positioning/positioning.js
    deleted file mode 100644
    index 0097f2f0ce6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/positioning/positioning.js
    +++ /dev/null
    @@ -1,619 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Common positioning code.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - */
    -
    -goog.provide('goog.positioning');
    -goog.provide('goog.positioning.Corner');
    -goog.provide('goog.positioning.CornerBit');
    -goog.provide('goog.positioning.Overflow');
    -goog.provide('goog.positioning.OverflowStatus');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.math.Rect');
    -goog.require('goog.math.Size');
    -goog.require('goog.style');
    -goog.require('goog.style.bidi');
    -
    -
    -/**
    - * Enum for representing an element corner for positioning the popup.
    - *
    - * The START constants map to LEFT if element directionality is left
    - * to right and RIGHT if the directionality is right to left.
    - * Likewise END maps to RIGHT or LEFT depending on the directionality.
    - *
    - * @enum {number}
    - */
    -goog.positioning.Corner = {
    -  TOP_LEFT: 0,
    -  TOP_RIGHT: 2,
    -  BOTTOM_LEFT: 1,
    -  BOTTOM_RIGHT: 3,
    -  TOP_START: 4,
    -  TOP_END: 6,
    -  BOTTOM_START: 5,
    -  BOTTOM_END: 7
    -};
    -
    -
    -/**
    - * Enum for bits in the {@see goog.positioning.Corner) bitmap.
    - *
    - * @enum {number}
    - */
    -goog.positioning.CornerBit = {
    -  BOTTOM: 1,
    -  RIGHT: 2,
    -  FLIP_RTL: 4
    -};
    -
    -
    -/**
    - * Enum for representing position handling in cases where the element would be
    - * positioned outside the viewport.
    - *
    - * @enum {number}
    - */
    -goog.positioning.Overflow = {
    -  /** Ignore overflow */
    -  IGNORE: 0,
    -
    -  /** Try to fit horizontally in the viewport at all costs. */
    -  ADJUST_X: 1,
    -
    -  /** If the element can't fit horizontally, report positioning failure. */
    -  FAIL_X: 2,
    -
    -  /** Try to fit vertically in the viewport at all costs. */
    -  ADJUST_Y: 4,
    -
    -  /** If the element can't fit vertically, report positioning failure. */
    -  FAIL_Y: 8,
    -
    -  /** Resize the element's width to fit in the viewport. */
    -  RESIZE_WIDTH: 16,
    -
    -  /** Resize the element's height to fit in the viewport. */
    -  RESIZE_HEIGHT: 32,
    -
    -  /**
    -   * If the anchor goes off-screen in the x-direction, position the movable
    -   * element off-screen. Otherwise, try to fit horizontally in the viewport.
    -   */
    -  ADJUST_X_EXCEPT_OFFSCREEN: 64 | 1,
    -
    -  /**
    -   * If the anchor goes off-screen in the y-direction, position the movable
    -   * element off-screen. Otherwise, try to fit vertically in the viewport.
    -   */
    -  ADJUST_Y_EXCEPT_OFFSCREEN: 128 | 4
    -};
    -
    -
    -/**
    - * Enum for representing the outcome of a positioning call.
    - *
    - * @enum {number}
    - */
    -goog.positioning.OverflowStatus = {
    -  NONE: 0,
    -  ADJUSTED_X: 1,
    -  ADJUSTED_Y: 2,
    -  WIDTH_ADJUSTED: 4,
    -  HEIGHT_ADJUSTED: 8,
    -  FAILED_LEFT: 16,
    -  FAILED_RIGHT: 32,
    -  FAILED_TOP: 64,
    -  FAILED_BOTTOM: 128,
    -  FAILED_OUTSIDE_VIEWPORT: 256
    -};
    -
    -
    -/**
    - * Shorthand to check if a status code contains any fail code.
    - * @type {number}
    - */
    -goog.positioning.OverflowStatus.FAILED =
    -    goog.positioning.OverflowStatus.FAILED_LEFT |
    -    goog.positioning.OverflowStatus.FAILED_RIGHT |
    -    goog.positioning.OverflowStatus.FAILED_TOP |
    -    goog.positioning.OverflowStatus.FAILED_BOTTOM |
    -    goog.positioning.OverflowStatus.FAILED_OUTSIDE_VIEWPORT;
    -
    -
    -/**
    - * Shorthand to check if horizontal positioning failed.
    - * @type {number}
    - */
    -goog.positioning.OverflowStatus.FAILED_HORIZONTAL =
    -    goog.positioning.OverflowStatus.FAILED_LEFT |
    -    goog.positioning.OverflowStatus.FAILED_RIGHT;
    -
    -
    -/**
    - * Shorthand to check if vertical positioning failed.
    - * @type {number}
    - */
    -goog.positioning.OverflowStatus.FAILED_VERTICAL =
    -    goog.positioning.OverflowStatus.FAILED_TOP |
    -    goog.positioning.OverflowStatus.FAILED_BOTTOM;
    -
    -
    -/**
    - * Positions a movable element relative to an anchor element. The caller
    - * specifies the corners that should touch. This functions then moves the
    - * movable element accordingly.
    - *
    - * @param {Element} anchorElement The element that is the anchor for where
    - *    the movable element should position itself.
    - * @param {goog.positioning.Corner} anchorElementCorner The corner of the
    - *     anchorElement for positioning the movable element.
    - * @param {Element} movableElement The element to move.
    - * @param {goog.positioning.Corner} movableElementCorner The corner of the
    - *     movableElement that that should be positioned adjacent to the anchor
    - *     element.
    - * @param {goog.math.Coordinate=} opt_offset An offset specified in pixels.
    - *    After the normal positioning algorithm is applied, the offset is then
    - *    applied. Positive coordinates move the popup closer to the center of the
    - *    anchor element. Negative coordinates move the popup away from the center
    - *    of the anchor element.
    - * @param {goog.math.Box=} opt_margin A margin specified in pixels.
    - *    After the normal positioning algorithm is applied and any offset, the
    - *    margin is then applied. Positive coordinates move the popup away from the
    - *    spot it was positioned towards its center. Negative coordinates move it
    - *    towards the spot it was positioned away from its center.
    - * @param {?number=} opt_overflow Overflow handling mode. Defaults to IGNORE if
    - *     not specified. Bitmap, {@see goog.positioning.Overflow}.
    - * @param {goog.math.Size=} opt_preferredSize The preferred size of the
    - *     movableElement.
    - * @param {goog.math.Box=} opt_viewport Box object describing the dimensions of
    - *     the viewport. The viewport is specified relative to offsetParent of
    - *     {@code movableElement}. In other words, the viewport can be thought of as
    - *     describing a "position: absolute" element contained in the offsetParent.
    - *     It defaults to visible area of nearest scrollable ancestor of
    - *     {@code movableElement} (see {@code goog.style.getVisibleRectForElement}).
    - * @return {goog.positioning.OverflowStatus} Status bitmap,
    - *     {@see goog.positioning.OverflowStatus}.
    - */
    -goog.positioning.positionAtAnchor = function(anchorElement,
    -                                             anchorElementCorner,
    -                                             movableElement,
    -                                             movableElementCorner,
    -                                             opt_offset,
    -                                             opt_margin,
    -                                             opt_overflow,
    -                                             opt_preferredSize,
    -                                             opt_viewport) {
    -
    -  goog.asserts.assert(movableElement);
    -  var movableParentTopLeft =
    -      goog.positioning.getOffsetParentPageOffset(movableElement);
    -
    -  // Get the visible part of the anchor element.  anchorRect is
    -  // relative to anchorElement's page.
    -  var anchorRect = goog.positioning.getVisiblePart_(anchorElement);
    -
    -  // Translate anchorRect to be relative to movableElement's page.
    -  goog.style.translateRectForAnotherFrame(
    -      anchorRect,
    -      goog.dom.getDomHelper(anchorElement),
    -      goog.dom.getDomHelper(movableElement));
    -
    -  // Offset based on which corner of the element we want to position against.
    -  var corner = goog.positioning.getEffectiveCorner(anchorElement,
    -                                                   anchorElementCorner);
    -  // absolutePos is a candidate position relative to the
    -  // movableElement's window.
    -  var absolutePos = new goog.math.Coordinate(
    -      corner & goog.positioning.CornerBit.RIGHT ?
    -          anchorRect.left + anchorRect.width : anchorRect.left,
    -      corner & goog.positioning.CornerBit.BOTTOM ?
    -          anchorRect.top + anchorRect.height : anchorRect.top);
    -
    -  // Translate absolutePos to be relative to the offsetParent.
    -  absolutePos =
    -      goog.math.Coordinate.difference(absolutePos, movableParentTopLeft);
    -
    -  // Apply offset, if specified
    -  if (opt_offset) {
    -    absolutePos.x += (corner & goog.positioning.CornerBit.RIGHT ? -1 : 1) *
    -        opt_offset.x;
    -    absolutePos.y += (corner & goog.positioning.CornerBit.BOTTOM ? -1 : 1) *
    -        opt_offset.y;
    -  }
    -
    -  // Determine dimension of viewport.
    -  var viewport;
    -  if (opt_overflow) {
    -    if (opt_viewport) {
    -      viewport = opt_viewport;
    -    } else {
    -      viewport = goog.style.getVisibleRectForElement(movableElement);
    -      if (viewport) {
    -        viewport.top -= movableParentTopLeft.y;
    -        viewport.right -= movableParentTopLeft.x;
    -        viewport.bottom -= movableParentTopLeft.y;
    -        viewport.left -= movableParentTopLeft.x;
    -      }
    -    }
    -  }
    -
    -  return goog.positioning.positionAtCoordinate(absolutePos,
    -                                               movableElement,
    -                                               movableElementCorner,
    -                                               opt_margin,
    -                                               viewport,
    -                                               opt_overflow,
    -                                               opt_preferredSize);
    -};
    -
    -
    -/**
    - * Calculates the page offset of the given element's
    - * offsetParent. This value can be used to translate any x- and
    - * y-offset relative to the page to an offset relative to the
    - * offsetParent, which can then be used directly with as position
    - * coordinate for {@code positionWithCoordinate}.
    - * @param {!Element} movableElement The element to calculate.
    - * @return {!goog.math.Coordinate} The page offset, may be (0, 0).
    - */
    -goog.positioning.getOffsetParentPageOffset = function(movableElement) {
    -  // Ignore offset for the BODY element unless its position is non-static.
    -  // For cases where the offset parent is HTML rather than the BODY (such as in
    -  // IE strict mode) there's no need to get the position of the BODY as it
    -  // doesn't affect the page offset.
    -  var movableParentTopLeft;
    -  var parent = movableElement.offsetParent;
    -  if (parent) {
    -    var isBody = parent.tagName == goog.dom.TagName.HTML ||
    -        parent.tagName == goog.dom.TagName.BODY;
    -    if (!isBody ||
    -        goog.style.getComputedPosition(parent) != 'static') {
    -      // Get the top-left corner of the parent, in page coordinates.
    -      movableParentTopLeft = goog.style.getPageOffset(parent);
    -
    -      if (!isBody) {
    -        movableParentTopLeft = goog.math.Coordinate.difference(
    -            movableParentTopLeft,
    -            new goog.math.Coordinate(goog.style.bidi.getScrollLeft(parent),
    -                parent.scrollTop));
    -      }
    -    }
    -  }
    -
    -  return movableParentTopLeft || new goog.math.Coordinate();
    -};
    -
    -
    -/**
    - * Returns intersection of the specified element and
    - * goog.style.getVisibleRectForElement for it.
    - *
    - * @param {Element} el The target element.
    - * @return {!goog.math.Rect} Intersection of getVisibleRectForElement
    - *     and the current bounding rectangle of the element.  If the
    - *     intersection is empty, returns the bounding rectangle.
    - * @private
    - */
    -goog.positioning.getVisiblePart_ = function(el) {
    -  var rect = goog.style.getBounds(el);
    -  var visibleBox = goog.style.getVisibleRectForElement(el);
    -  if (visibleBox) {
    -    rect.intersection(goog.math.Rect.createFromBox(visibleBox));
    -  }
    -  return rect;
    -};
    -
    -
    -/**
    - * Positions the specified corner of the movable element at the
    - * specified coordinate.
    - *
    - * @param {goog.math.Coordinate} absolutePos The coordinate to position the
    - *     element at.
    - * @param {Element} movableElement The element to be positioned.
    - * @param {goog.positioning.Corner} movableElementCorner The corner of the
    - *     movableElement that that should be positioned.
    - * @param {goog.math.Box=} opt_margin A margin specified in pixels.
    - *    After the normal positioning algorithm is applied and any offset, the
    - *    margin is then applied. Positive coordinates move the popup away from the
    - *    spot it was positioned towards its center. Negative coordinates move it
    - *    towards the spot it was positioned away from its center.
    - * @param {goog.math.Box=} opt_viewport Box object describing the dimensions of
    - *     the viewport. Required if opt_overflow is specified.
    - * @param {?number=} opt_overflow Overflow handling mode. Defaults to IGNORE if
    - *     not specified, {@see goog.positioning.Overflow}.
    - * @param {goog.math.Size=} opt_preferredSize The preferred size of the
    - *     movableElement. Defaults to the current size.
    - * @return {goog.positioning.OverflowStatus} Status bitmap.
    - */
    -goog.positioning.positionAtCoordinate = function(absolutePos,
    -                                                 movableElement,
    -                                                 movableElementCorner,
    -                                                 opt_margin,
    -                                                 opt_viewport,
    -                                                 opt_overflow,
    -                                                 opt_preferredSize) {
    -  absolutePos = absolutePos.clone();
    -
    -  // Offset based on attached corner and desired margin.
    -  var corner = goog.positioning.getEffectiveCorner(movableElement,
    -                                                   movableElementCorner);
    -  var elementSize = goog.style.getSize(movableElement);
    -  var size = opt_preferredSize ? opt_preferredSize.clone() :
    -      elementSize.clone();
    -
    -  var positionResult = goog.positioning.getPositionAtCoordinate(absolutePos,
    -      size, corner, opt_margin, opt_viewport, opt_overflow);
    -
    -  if (positionResult.status & goog.positioning.OverflowStatus.FAILED) {
    -    return positionResult.status;
    -  }
    -
    -  goog.style.setPosition(movableElement, positionResult.rect.getTopLeft());
    -  size = positionResult.rect.getSize();
    -  if (!goog.math.Size.equals(elementSize, size)) {
    -    goog.style.setBorderBoxSize(movableElement, size);
    -  }
    -
    -  return positionResult.status;
    -};
    -
    -
    -/**
    - * Computes the position for an element to be placed on-screen at the
    - * specified coordinates. Returns an object containing both the resulting
    - * rectangle, and the overflow status bitmap.
    - *
    - * @param {!goog.math.Coordinate} absolutePos The coordinate to position the
    - *     element at.
    - * @param {!goog.math.Size} elementSize The size of the element to be
    - *     positioned.
    - * @param {goog.positioning.Corner} elementCorner The corner of the
    - *     movableElement that that should be positioned.
    - * @param {goog.math.Box=} opt_margin A margin specified in pixels.
    - *    After the normal positioning algorithm is applied and any offset, the
    - *    margin is then applied. Positive coordinates move the popup away from the
    - *    spot it was positioned towards its center. Negative coordinates move it
    - *    towards the spot it was positioned away from its center.
    - * @param {goog.math.Box=} opt_viewport Box object describing the dimensions of
    - *     the viewport. Required if opt_overflow is specified.
    - * @param {?number=} opt_overflow Overflow handling mode. Defaults to IGNORE
    - *     if not specified, {@see goog.positioning.Overflow}.
    - * @return {{rect:!goog.math.Rect, status:goog.positioning.OverflowStatus}}
    - *     Object containing the computed position and status bitmap.
    - */
    -goog.positioning.getPositionAtCoordinate = function(
    -    absolutePos,
    -    elementSize,
    -    elementCorner,
    -    opt_margin,
    -    opt_viewport,
    -    opt_overflow) {
    -  absolutePos = absolutePos.clone();
    -  elementSize = elementSize.clone();
    -  var status = goog.positioning.OverflowStatus.NONE;
    -
    -  if (opt_margin || elementCorner != goog.positioning.Corner.TOP_LEFT) {
    -    if (elementCorner & goog.positioning.CornerBit.RIGHT) {
    -      absolutePos.x -= elementSize.width + (opt_margin ? opt_margin.right : 0);
    -    } else if (opt_margin) {
    -      absolutePos.x += opt_margin.left;
    -    }
    -    if (elementCorner & goog.positioning.CornerBit.BOTTOM) {
    -      absolutePos.y -= elementSize.height +
    -          (opt_margin ? opt_margin.bottom : 0);
    -    } else if (opt_margin) {
    -      absolutePos.y += opt_margin.top;
    -    }
    -  }
    -
    -  // Adjust position to fit inside viewport.
    -  if (opt_overflow) {
    -    status = opt_viewport ?
    -        goog.positioning.adjustForViewport_(
    -            absolutePos, elementSize, opt_viewport, opt_overflow) :
    -        goog.positioning.OverflowStatus.FAILED_OUTSIDE_VIEWPORT;
    -  }
    -
    -  var rect = new goog.math.Rect(0, 0, 0, 0);
    -  rect.left = absolutePos.x;
    -  rect.top = absolutePos.y;
    -  rect.width = elementSize.width;
    -  rect.height = elementSize.height;
    -  return {rect: rect, status: status};
    -};
    -
    -
    -/**
    - * Adjusts the position and/or size of an element, identified by its position
    - * and size, to fit inside the viewport. If the position or size of the element
    - * is adjusted the pos or size objects, respectively, are modified.
    - *
    - * @param {goog.math.Coordinate} pos Position of element, updated if the
    - *     position is adjusted.
    - * @param {goog.math.Size} size Size of element, updated if the size is
    - *     adjusted.
    - * @param {goog.math.Box} viewport Bounding box describing the viewport.
    - * @param {number} overflow Overflow handling mode,
    - *     {@see goog.positioning.Overflow}.
    - * @return {goog.positioning.OverflowStatus} Status bitmap,
    - *     {@see goog.positioning.OverflowStatus}.
    - * @private
    - */
    -goog.positioning.adjustForViewport_ = function(pos, size, viewport, overflow) {
    -  var status = goog.positioning.OverflowStatus.NONE;
    -
    -  var ADJUST_X_EXCEPT_OFFSCREEN =
    -      goog.positioning.Overflow.ADJUST_X_EXCEPT_OFFSCREEN;
    -  var ADJUST_Y_EXCEPT_OFFSCREEN =
    -      goog.positioning.Overflow.ADJUST_Y_EXCEPT_OFFSCREEN;
    -  if ((overflow & ADJUST_X_EXCEPT_OFFSCREEN) == ADJUST_X_EXCEPT_OFFSCREEN &&
    -      (pos.x < viewport.left || pos.x >= viewport.right)) {
    -    overflow &= ~goog.positioning.Overflow.ADJUST_X;
    -  }
    -  if ((overflow & ADJUST_Y_EXCEPT_OFFSCREEN) == ADJUST_Y_EXCEPT_OFFSCREEN &&
    -      (pos.y < viewport.top || pos.y >= viewport.bottom)) {
    -    overflow &= ~goog.positioning.Overflow.ADJUST_Y;
    -  }
    -
    -  // Left edge outside viewport, try to move it.
    -  if (pos.x < viewport.left && overflow & goog.positioning.Overflow.ADJUST_X) {
    -    pos.x = viewport.left;
    -    status |= goog.positioning.OverflowStatus.ADJUSTED_X;
    -  }
    -
    -  // Ensure object is inside the viewport width if required.
    -  if (overflow & goog.positioning.Overflow.RESIZE_WIDTH) {
    -    // Move left edge inside viewport.
    -    var originalX = pos.x;
    -    if (pos.x < viewport.left) {
    -      pos.x = viewport.left;
    -      status |= goog.positioning.OverflowStatus.WIDTH_ADJUSTED;
    -    }
    -
    -    // Shrink width to inside right of viewport.
    -    if (pos.x + size.width > viewport.right) {
    -      // Set the width to be either the new maximum width within the viewport
    -      // or the width originally within the viewport, whichever is less.
    -      size.width = Math.min(
    -          viewport.right - pos.x, originalX + size.width - viewport.left);
    -      size.width = Math.max(size.width, 0);
    -      status |= goog.positioning.OverflowStatus.WIDTH_ADJUSTED;
    -    }
    -  }
    -
    -  // Right edge outside viewport, try to move it.
    -  if (pos.x + size.width > viewport.right &&
    -      overflow & goog.positioning.Overflow.ADJUST_X) {
    -    pos.x = Math.max(viewport.right - size.width, viewport.left);
    -    status |= goog.positioning.OverflowStatus.ADJUSTED_X;
    -  }
    -
    -  // Left or right edge still outside viewport, fail if the FAIL_X option was
    -  // specified, ignore it otherwise.
    -  if (overflow & goog.positioning.Overflow.FAIL_X) {
    -    status |= (pos.x < viewport.left ?
    -                   goog.positioning.OverflowStatus.FAILED_LEFT : 0) |
    -              (pos.x + size.width > viewport.right ?
    -                   goog.positioning.OverflowStatus.FAILED_RIGHT : 0);
    -  }
    -
    -  // Top edge outside viewport, try to move it.
    -  if (pos.y < viewport.top && overflow & goog.positioning.Overflow.ADJUST_Y) {
    -    pos.y = viewport.top;
    -    status |= goog.positioning.OverflowStatus.ADJUSTED_Y;
    -  }
    -
    -  // Ensure object is inside the viewport height if required.
    -  if (overflow & goog.positioning.Overflow.RESIZE_HEIGHT) {
    -    // Move top edge inside viewport.
    -    var originalY = pos.y;
    -    if (pos.y < viewport.top) {
    -      pos.y = viewport.top;
    -      status |= goog.positioning.OverflowStatus.HEIGHT_ADJUSTED;
    -    }
    -
    -    // Shrink height to inside bottom of viewport.
    -    if (pos.y + size.height > viewport.bottom) {
    -      // Set the height to be either the new maximum height within the viewport
    -      // or the height originally within the viewport, whichever is less.
    -      size.height = Math.min(
    -          viewport.bottom - pos.y, originalY + size.height - viewport.top);
    -      size.height = Math.max(size.height, 0);
    -      status |= goog.positioning.OverflowStatus.HEIGHT_ADJUSTED;
    -    }
    -  }
    -
    -  // Bottom edge outside viewport, try to move it.
    -  if (pos.y + size.height > viewport.bottom &&
    -      overflow & goog.positioning.Overflow.ADJUST_Y) {
    -    pos.y = Math.max(viewport.bottom - size.height, viewport.top);
    -    status |= goog.positioning.OverflowStatus.ADJUSTED_Y;
    -  }
    -
    -  // Top or bottom edge still outside viewport, fail if the FAIL_Y option was
    -  // specified, ignore it otherwise.
    -  if (overflow & goog.positioning.Overflow.FAIL_Y) {
    -    status |= (pos.y < viewport.top ?
    -                   goog.positioning.OverflowStatus.FAILED_TOP : 0) |
    -              (pos.y + size.height > viewport.bottom ?
    -                   goog.positioning.OverflowStatus.FAILED_BOTTOM : 0);
    -  }
    -
    -  return status;
    -};
    -
    -
    -/**
    - * Returns an absolute corner (top/bottom left/right) given an absolute
    - * or relative (top/bottom start/end) corner and the direction of an element.
    - * Absolute corners remain unchanged.
    - * @param {Element} element DOM element to test for RTL direction.
    - * @param {goog.positioning.Corner} corner The popup corner used for
    - *     positioning.
    - * @return {goog.positioning.Corner} Effective corner.
    - */
    -goog.positioning.getEffectiveCorner = function(element, corner) {
    -  return /** @type {goog.positioning.Corner} */ (
    -      (corner & goog.positioning.CornerBit.FLIP_RTL &&
    -          goog.style.isRightToLeft(element) ?
    -          corner ^ goog.positioning.CornerBit.RIGHT :
    -          corner
    -      ) & ~goog.positioning.CornerBit.FLIP_RTL);
    -};
    -
    -
    -/**
    - * Returns the corner opposite the given one horizontally.
    - * @param {goog.positioning.Corner} corner The popup corner used to flip.
    - * @return {goog.positioning.Corner} The opposite corner horizontally.
    - */
    -goog.positioning.flipCornerHorizontal = function(corner) {
    -  return /** @type {goog.positioning.Corner} */ (corner ^
    -      goog.positioning.CornerBit.RIGHT);
    -};
    -
    -
    -/**
    - * Returns the corner opposite the given one vertically.
    - * @param {goog.positioning.Corner} corner The popup corner used to flip.
    - * @return {goog.positioning.Corner} The opposite corner vertically.
    - */
    -goog.positioning.flipCornerVertical = function(corner) {
    -  return /** @type {goog.positioning.Corner} */ (corner ^
    -      goog.positioning.CornerBit.BOTTOM);
    -};
    -
    -
    -/**
    - * Returns the corner opposite the given one horizontally and vertically.
    - * @param {goog.positioning.Corner} corner The popup corner used to flip.
    - * @return {goog.positioning.Corner} The opposite corner horizontally and
    - *     vertically.
    - */
    -goog.positioning.flipCorner = function(corner) {
    -  return /** @type {goog.positioning.Corner} */ (corner ^
    -      goog.positioning.CornerBit.BOTTOM ^
    -      goog.positioning.CornerBit.RIGHT);
    -};
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/positioning/positioning_test.html b/src/database/third_party/closure-library/closure/goog/positioning/positioning_test.html
    deleted file mode 100644
    index 70f53498f0e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/positioning/positioning_test.html
    +++ /dev/null
    @@ -1,199 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    -Author: eae@google.com (Emil A Eklund)
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.positioning</title>
    -<script src="../base.js"></script>
    -
    -
    -<style>
    -  .box1 {
    -    border: 1px solid black;
    -    margin: 10px;
    -    padding: 5px;
    -    height: 150px;
    -  }
    -  .outerbox {
    -    border: 1px solid gray;
    -    padding: 3px;
    -    margin: 5px 5px 5px 100px;
    -  }
    -  .box2 {
    -    position: relative;
    -    padding: 0px; /* If the padding has >0 value, IE6 fails some tests. */
    -    margin: -2px;
    -  }
    -  .box8 {
    -    position: absolute;
    -    padding: 0px; /* If the padding has >0 value, IE6 fails some tests. */
    -    margin: -2px;
    -    width: 500px;
    -    height: 100px;
    -  }
    -  .box9 {
    -    border: 1px solid black;
    -    margin: 10px;
    -    padding: 5px;
    -    height: 150px;
    -    width: 150px;
    -  }
    -  .anchorFrame {
    -    overflow: auto;
    -    width: 100px;
    -    height: 100px;
    -  }
    -  #popup1, #popup2, #popup3, #popup5, #popup6, #popup7 {
    -    position: absolute;
    -    border: 1px solid red;
    -    width: 100px;
    -    height: 100px;
    -  }
    -  #popup9 {
    -    border: 1px solid green;
    -    height: 100px;
    -    left: 0;
    -    position: absolute;
    -    top: 0;
    -    width: 100px;
    -  }
    -  #popup8 {
    -    position: absolute;
    -    border: 1px solid red;
    -    width: 100px;
    -    height: 100px;
    -  }
    -  #anchor1 {
    -    border: 1px solid blue;
    -  }
    -  #anchor4 {
    -    position: absolute;
    -    left: 2px;
    -  }
    -
    -  #test-area {
    -    height: 1000px;
    -    position: relative;
    -    width: 1000px;
    -  }
    -  .overflow-hidden {
    -    overflow: hidden;
    -  }
    -  .overflow-auto {
    -    overflow: auto;
    -  }
    -</style>
    -</head>
    -<body>
    -
    -<div id='offscreen-anchor'
    -   style='position: absolute; left: -1000px; top: -1000px'></div>
    -
    -  <div id="ltr" dir="ltr">
    -    Left to right element.
    -  </div>
    -
    -  <div id="rtl" dir="rtl">
    -    Right to left element.
    -  </div>
    -
    -  <div class="outerbox">
    -    <div id="box1" class="box1">
    -      <span id="anchor1">Anchor LTR.</span>
    -    </div>
    -
    -    <div class="box2">
    -      <div id="popup1">
    -        <div>Popup ltr.</div>
    -      </div>
    -    </div>
    -  </div>
    -
    -  <div class="outerbox" dir="rtl">
    -    <div class="box1">
    -      <span id="anchor2">Anchor RTL.</span>
    -    </div>
    -
    -    <div class="box2">
    -      <div id="popup2">
    -        <div>Popup rtl.</div>
    -      </div>
    -    </div>
    -  </div>
    -
    -  <div id="anchor4">
    -    Anchor 4.
    -  </div>
    -
    -  <div id="popup3">
    -    Popup.
    -  </div>
    -
    -<div dir="rtl" style="border: 1px solid red;">
    -  <div dir="rtl" style="position: relative; overflow: auto; width: 150px; height: 100px; border: 1px solid black;">
    -    <div style="height: 200px;">
    -      <span id="anchor5">Anchor 5.</span>
    -    </div>
    -    <div id="popup5">
    -      Popup.
    -    </div>
    -  </div>
    -</div>
    -
    -<iframe id="iframe-standard" src="positioning_test_standard.html" class="anchorFrame">
    -</iframe>
    -<iframe id="iframe-quirk" src="positioning_test_quirk.html" class="anchorFrame">
    -</iframe>
    -<div id="popup6">Popup6</div>
    -
    -<div style="position:relative;height:100px;width:100px;overflow:auto;">
    -  I hate positioning!
    -  <div>1</div>
    -  <div>2</div>
    -  <div>3</div>
    -  <div>4</div>
    -  <div>5</div>
    -  <div>6</div>
    -  <div>7</div>
    -  <div id="popup7">Popup7</div>
    -</div>
    -
    -<iframe id="nested-outer" src="positioning_test_iframe1.html"
    - style="overflow:auto;width:150px;height:150px;"></iframe>
    -
    -<div class="outerbox" dir="rtl">
    -  <div class="box1">
    -    <span id="anchor8">Anchor8 RTL.</span>
    -  </div>
    -
    -  <div class="box8 overflow-auto">
    -    <div id="popup8">
    -      <div>Popup8 rtl.</div>
    -    </div>
    -    <div style="width:10000px;">&nbsp;</div>
    -  </div>
    -
    -</div>
    -
    -<div id="box9" class="box9">
    -  <div id="popup9">
    -    <div>Popup9</div>
    -  </div>
    -  <span id="anchor9">Anchor9</span>
    -</div>
    -
    -<div id="test-area"></div>
    -
    -<script>
    -goog.require('goog.positioningTest');
    -</script>
    -
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/positioning/positioning_test.js b/src/database/third_party/closure-library/closure/goog/positioning/positioning_test.js
    deleted file mode 100644
    index edf16914162..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/positioning/positioning_test.js
    +++ /dev/null
    @@ -1,1283 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.position.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - */
    -
    -/** @suppress {extraProvide} */
    -goog.provide('goog.positioningTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.DomHelper');
    -goog.require('goog.math.Box');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.math.Size');
    -goog.require('goog.positioning');
    -goog.require('goog.positioning.Corner');
    -goog.require('goog.positioning.Overflow');
    -goog.require('goog.positioning.OverflowStatus');
    -goog.require('goog.style');
    -goog.require('goog.testing.ExpectedFailures');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -goog.require('goog.userAgent.product');
    -
    -goog.setTestOnly('goog.positioningTest');
    -
    -// Allow positions to be off by one in gecko as it reports scrolling
    -// offsets in steps of 2.  Otherwise, allow for subpixel difference
    -// as seen in IE10+
    -var ALLOWED_OFFSET = goog.userAgent.GECKO ? 1 : 0.1;
    -// Error bar for positions since some browsers are not super accurate
    -// in reporting them.
    -var EPSILON = 2;
    -
    -var expectedFailures = new goog.testing.ExpectedFailures();
    -
    -var corner = goog.positioning.Corner;
    -var overflow = goog.positioning.Overflow;
    -var testArea;
    -
    -function setUp() {
    -  window.scrollTo(0, 0);
    -
    -  var viewportSize = goog.dom.getViewportSize();
    -  // Some tests need enough size viewport.
    -  if (viewportSize.width < 600 || viewportSize.height < 600) {
    -    window.moveTo(0, 0);
    -    window.resizeTo(640, 640);
    -  }
    -
    -  testArea = goog.dom.getElement('test-area');
    -}
    -
    -function tearDown() {
    -  expectedFailures.handleTearDown();
    -  testArea.setAttribute('style', '');
    -  testArea.innerHTML = '';
    -}
    -
    -
    -/**
    - * This is used to round pixel values on FF3 Mac.
    - */
    -function assertRoundedEquals(a, b, c) {
    -  function round(x) {
    -    return goog.userAgent.GECKO && (goog.userAgent.MAC || goog.userAgent.X11) &&
    -        goog.userAgent.isVersionOrHigher('1.9') ? Math.round(x) : x;
    -  }
    -  if (arguments.length == 3) {
    -    assertRoughlyEquals(a, round(b), round(c), ALLOWED_OFFSET);
    -  } else {
    -    assertRoughlyEquals(round(a), round(b), ALLOWED_OFFSET);
    -  }
    -}
    -
    -function testPositionAtAnchorLeftToRight() {
    -  var anchor = document.getElementById('anchor1');
    -  var popup = document.getElementById('popup1');
    -
    -  // Anchor top left to top left.
    -  goog.positioning.positionAtAnchor(anchor, corner.TOP_LEFT,
    -                                    popup, corner.TOP_LEFT);
    -  var anchorRect = goog.style.getBounds(anchor);
    -  var popupRect = goog.style.getBounds(popup);
    -  assertRoundedEquals('Left edge of popup should line up with left edge ' +
    -                      'of anchor.',
    -                      anchorRect.left,
    -                      popupRect.left);
    -  assertRoundedEquals('Popup should have the same y position as the anchor.',
    -                      anchorRect.top,
    -                      popupRect.top);
    -
    -  // Anchor top left to bottom left.
    -  goog.positioning.positionAtAnchor(anchor, corner.BOTTOM_LEFT,
    -                                    popup, corner.TOP_LEFT);
    -  anchorRect = goog.style.getBounds(anchor);
    -  popupRect = goog.style.getBounds(popup);
    -  assertRoundedEquals('Left edge of popup should line up with left edge ' +
    -                      'of anchor.',
    -                      anchorRect.left,
    -                      popupRect.left);
    -  assertRoundedEquals('Popup should be positioned just below the anchor.',
    -                      anchorRect.top + anchorRect.height,
    -                      popupRect.top);
    -
    -  // Anchor top left to top right.
    -  goog.positioning.positionAtAnchor(anchor, corner.TOP_RIGHT,
    -                                    popup, corner.TOP_LEFT);
    -  anchorRect = goog.style.getBounds(anchor);
    -  popupRect = goog.style.getBounds(popup);
    -  assertRoundedEquals('Popup should be positioned just right of the anchor.',
    -                      anchorRect.left + anchorRect.width,
    -                      popupRect.left);
    -  assertRoundedEquals('Popup should have the same y position as the anchor.',
    -                      anchorRect.top,
    -                      popupRect.top);
    -
    -  // Anchor top right to bottom right.
    -  goog.positioning.positionAtAnchor(anchor, corner.BOTTOM_RIGHT,
    -                                    popup, corner.TOP_RIGHT);
    -  anchorRect = goog.style.getBounds(anchor);
    -  popupRect = goog.style.getBounds(popup);
    -  assertRoundedEquals('Right edge of popup should line up with right edge ' +
    -                      'of anchor.',
    -                      anchorRect.left + anchorRect.width,
    -                      popupRect.left + popupRect.width);
    -  assertRoundedEquals('Popup should be positioned just below the anchor.',
    -                      anchorRect.top + anchorRect.height,
    -                      popupRect.top);
    -
    -  // Anchor top start to bottom start.
    -  goog.positioning.positionAtAnchor(anchor, corner.BOTTOM_START,
    -                                    popup, corner.TOP_START);
    -  anchorRect = goog.style.getBounds(anchor);
    -  popupRect = goog.style.getBounds(popup);
    -  assertRoundedEquals('Left edge of popup should line up with left edge ' +
    -                      'of anchor.',
    -                      anchorRect.left,
    -                      popupRect.left);
    -  assertRoundedEquals('Popup should be positioned just below the anchor.',
    -                      anchorRect.top + anchorRect.height,
    -                      popupRect.top);
    -}
    -
    -
    -function testPositionAtAnchorWithOffset() {
    -  var anchor = document.getElementById('anchor1');
    -  var popup = document.getElementById('popup1');
    -
    -  // Anchor top left to top left with an offset moving the popup away from the
    -  // anchor.
    -  goog.positioning.positionAtAnchor(anchor, corner.TOP_LEFT,
    -                                    popup, corner.TOP_LEFT,
    -                                    newCoord(-15, -20));
    -  var anchorRect = goog.style.getBounds(anchor);
    -  var popupRect = goog.style.getBounds(popup);
    -  assertRoundedEquals('Left edge of popup should be fifteen pixels from ' +
    -                      'anchor.',
    -                      anchorRect.left,
    -                      popupRect.left + 15);
    -  assertRoundedEquals('Top edge of popup should be twenty pixels from anchor.',
    -                      anchorRect.top,
    -                      popupRect.top + 20);
    -
    -  // Anchor top left to top left with an offset moving the popup towards the
    -  // anchor.
    -  goog.positioning.positionAtAnchor(anchor, corner.TOP_LEFT,
    -                                    popup, corner.TOP_LEFT,
    -                                    newCoord(3, 1));
    -  anchorRect = goog.style.getBounds(anchor);
    -  popupRect = goog.style.getBounds(popup);
    -  assertRoundedEquals('Left edge of popup should be three pixels right of ' +
    -                      'the anchor\'s left edge',
    -                      anchorRect.left,
    -                      popupRect.left - 3);
    -  assertRoundedEquals('Top edge of popup should be one pixel below of the ' +
    -                      'anchor\'s top edge',
    -                      anchorRect.top,
    -                      popupRect.top - 1);
    -}
    -
    -
    -function testPositionAtAnchorOverflowLeftEdgeRightToLeft() {
    -  var anchor = document.getElementById('anchor5');
    -  var popup = document.getElementById('popup5');
    -
    -  var status = goog.positioning.positionAtAnchor(anchor, corner.TOP_LEFT,
    -                                                 popup, corner.TOP_RIGHT,
    -                                                 undefined, undefined,
    -                                                 overflow.FAIL_X);
    -  assertFalse('Positioning operation should have failed.',
    -              (status & goog.positioning.OverflowStatus.FAILED) == 0);
    -
    -  // Change overflow strategy to ADJUST.
    -  status = goog.positioning.positionAtAnchor(anchor, corner.TOP_LEFT,
    -                                             popup, corner.TOP_RIGHT,
    -                                             undefined, undefined,
    -                                             overflow.ADJUST_X);
    -
    -  // Fails in Chrome because of infrastructure issues, temporarily disabled.
    -  // See b/4274723.
    -  expectedFailures.expectFailureFor(goog.userAgent.product.CHROME);
    -  try {
    -    assertTrue('Positioning operation should have been successful.',
    -               (status & goog.positioning.OverflowStatus.FAILED) == 0);
    -    assertTrue('Positioning operation should have been adjusted.',
    -               (status & goog.positioning.OverflowStatus.ADJUSTED_X) != 0);
    -  } catch (e) {
    -    expectedFailures.handleException(e);
    -  }
    -
    -  var anchorRect = goog.style.getBounds(anchor);
    -  var popupRect = goog.style.getBounds(popup);
    -  var parentRect = goog.style.getBounds(anchor.parentNode);
    -  assertTrue('Position should have been adjusted so that the left edge of ' +
    -             'the popup is left of the anchor but still within the bounding ' +
    -             'box of the parent container.',
    -      anchorRect.left <= popupRect.left <= parentRect.left);
    -
    -}
    -
    -
    -function testPositionAtAnchorWithMargin() {
    -  var anchor = document.getElementById('anchor1');
    -  var popup = document.getElementById('popup1');
    -
    -  // Anchor top left to top left.
    -  goog.positioning.positionAtAnchor(anchor, corner.TOP_LEFT,
    -                                    popup, corner.TOP_LEFT, undefined,
    -                                    new goog.math.Box(1, 2, 3, 4));
    -  var anchorRect = goog.style.getBounds(anchor);
    -  var popupRect = goog.style.getBounds(popup);
    -  assertRoundedEquals('Left edge of popup should be four pixels from anchor.',
    -                      anchorRect.left,
    -                      popupRect.left - 4);
    -  assertRoundedEquals('Top edge of popup should be one pixels from anchor.',
    -                      anchorRect.top,
    -                      popupRect.top - 1);
    -
    -  // Anchor top right to bottom right.
    -  goog.positioning.positionAtAnchor(anchor, corner.BOTTOM_RIGHT,
    -                                    popup, corner.TOP_RIGHT, undefined,
    -                                    new goog.math.Box(1, 2, 3, 4));
    -  anchorRect = goog.style.getBounds(anchor);
    -  popupRect = goog.style.getBounds(popup);
    -
    -  var visibleAnchorRect = goog.positioning.getVisiblePart_(anchor);
    -
    -  assertRoundedEquals('Right edge of popup should line up with right edge ' +
    -                      'of anchor.',
    -                      visibleAnchorRect.left + visibleAnchorRect.width,
    -                      popupRect.left + popupRect.width + 2);
    -
    -  assertRoundedEquals('Popup should be positioned just below the anchor.',
    -                      visibleAnchorRect.top + visibleAnchorRect.height,
    -                      popupRect.top - 1);
    -
    -}
    -
    -
    -function testPositionAtAnchorRightToLeft() {
    -  if (goog.userAgent.IE && goog.userAgent.isVersionOrHigher('6')) {
    -    // These tests fails with IE6.
    -    // TODO(user): Investigate the reason.
    -    return;
    -  }
    -
    -  var anchor = document.getElementById('anchor2');
    -  var popup = document.getElementById('popup2');
    -
    -  // Anchor top left to top left.
    -  goog.positioning.positionAtAnchor(anchor, corner.TOP_LEFT,
    -                                    popup, corner.TOP_LEFT);
    -  var anchorRect = goog.style.getBounds(anchor);
    -  var popupRect = goog.style.getBounds(popup);
    -
    -  assertRoundedEquals('Left edge of popup should line up with left edge ' +
    -                      'of anchor.',
    -                      anchorRect.left,
    -                      popupRect.left);
    -  assertRoundedEquals('Popup should have the same y position as the anchor.',
    -                      anchorRect.top,
    -                      popupRect.top);
    -
    -  // Anchor top start to bottom start.
    -  goog.positioning.positionAtAnchor(anchor, corner.BOTTOM_START,
    -                                    popup, corner.TOP_START);
    -  anchorRect = goog.style.getBounds(anchor);
    -  popupRect = goog.style.getBounds(popup);
    -  assertRoundedEquals('Right edge of popup should line up with right edge ' +
    -                      'of anchor.',
    -                      anchorRect.left + anchorRect.width,
    -                      popupRect.left + popupRect.width);
    -  assertRoundedEquals('Popup should be positioned just below the anchor.',
    -                      anchorRect.top + anchorRect.height,
    -                      popupRect.top);
    -}
    -
    -function testPositionAtAnchorRightToLeftWithScroll() {
    -  if (goog.userAgent.IE && goog.userAgent.isVersionOrHigher('6')) {
    -    // These tests fails with IE6.
    -    // TODO(user): Investigate the reason.
    -    return;
    -  }
    -
    -  var anchor = document.getElementById('anchor8');
    -  var popup = document.getElementById('popup8');
    -
    -  // Anchor top left to top left.
    -  goog.positioning.positionAtAnchor(anchor, corner.TOP_LEFT,
    -                                    popup, corner.TOP_LEFT);
    -  var anchorRect = goog.style.getBounds(anchor);
    -  var popupRect = goog.style.getBounds(popup);
    -
    -  assertRoundedEquals('Left edge of popup should line up with left edge ' +
    -                      'of anchor.',
    -                      anchorRect.left,
    -                      popupRect.left);
    -  assertRoundedEquals('Popup should have the same y position as the anchor.',
    -                      anchorRect.top,
    -                      popupRect.top);
    -
    -  // Anchor top start to bottom start.
    -  goog.positioning.positionAtAnchor(anchor, corner.BOTTOM_START,
    -                                    popup, corner.TOP_START);
    -  anchorRect = goog.style.getBounds(anchor);
    -  popupRect = goog.style.getBounds(popup);
    -
    -  var visibleAnchorRect = goog.positioning.getVisiblePart_(anchor);
    -  var visibleAnchorBox = visibleAnchorRect.toBox();
    -
    -  assertRoundedEquals('Right edge of popup should line up with right edge ' +
    -                      'of anchor.',
    -                      anchorRect.left + anchorRect.width,
    -                      popupRect.left + popupRect.width);
    -  assertRoundedEquals('Popup should be positioned just below the anchor.',
    -                      visibleAnchorBox.bottom,
    -                      popupRect.top);
    -}
    -
    -function testPositionAtAnchorBodyViewport() {
    -  var anchor = document.getElementById('anchor1');
    -  var popup = document.getElementById('popup3');
    -
    -  // Anchor top left to top left.
    -  goog.positioning.positionAtAnchor(anchor, corner.TOP_LEFT,
    -                                    popup, corner.TOP_LEFT);
    -  var anchorRect = goog.style.getBounds(anchor);
    -  var popupRect = goog.style.getBounds(popup);
    -  assertEquals('Left edge of popup should line up with left edge of anchor.',
    -               anchorRect.left,
    -               popupRect.left);
    -  assertRoughlyEquals('Popup should have the same y position as the anchor.',
    -                      anchorRect.top,
    -                      popupRect.top,
    -                      1);
    -
    -  // Anchor top start to bottom right.
    -  goog.positioning.positionAtAnchor(anchor, corner.BOTTOM_RIGHT,
    -                                    popup, corner.TOP_RIGHT);
    -  anchorRect = goog.style.getBounds(anchor);
    -  popupRect = goog.style.getBounds(popup);
    -  assertEquals('Right edge of popup should line up with right edge of anchor.',
    -               anchorRect.left + anchorRect.width,
    -               popupRect.left + popupRect.width);
    -  assertRoughlyEquals('Popup should be positioned just below the anchor.',
    -                      anchorRect.top + anchorRect.height,
    -                      popupRect.top,
    -                      1);
    -
    -  // Anchor top right to top left.
    -  goog.positioning.positionAtAnchor(anchor, corner.TOP_LEFT,
    -                                    popup, corner.TOP_RIGHT);
    -  anchorRect = goog.style.getBounds(anchor);
    -  popupRect = goog.style.getBounds(popup);
    -  assertEquals('Right edge of popup should line up with left edge of anchor.',
    -               anchorRect.left,
    -               popupRect.left + popupRect.width);
    -  assertRoughlyEquals('Popup should have the same y position as the anchor.',
    -                      anchorRect.top,
    -                      popupRect.top,
    -                      1);
    -}
    -
    -function testPositionAtAnchorSpecificViewport() {
    -  var anchor = document.getElementById('anchor1');
    -  var popup = document.getElementById('popup3');
    -
    -  // Anchor top right to top left within outerbox.
    -  var status = goog.positioning.positionAtAnchor(anchor, corner.TOP_LEFT,
    -                                                 popup, corner.TOP_RIGHT,
    -                                                 undefined, undefined,
    -                                                 overflow.FAIL_X);
    -  anchorRect = goog.style.getBounds(anchor);
    -  popupRect = goog.style.getBounds(popup);
    -  assertTrue('Positioning operation should have been successful.',
    -             (status & goog.positioning.OverflowStatus.FAILED) == 0);
    -  assertTrue('X position should not have been adjusted.',
    -             (status & goog.positioning.OverflowStatus.ADJUSTED_X) == 0);
    -  assertTrue('Y position should not have been adjusted.',
    -             (status & goog.positioning.OverflowStatus.ADJUSTED_Y) == 0);
    -  assertEquals('Right edge of popup should line up with left edge of anchor.',
    -               anchorRect.left,
    -               popupRect.left + popupRect.width);
    -  assertRoughlyEquals('Popup should have the same y position as the anchor.',
    -                      anchorRect.top,
    -                      popupRect.top,
    -                      1);
    -
    -  // position again within box1.
    -  var box = document.getElementById('box1');
    -  var viewport = goog.style.getBounds(box);
    -  status = goog.positioning.positionAtAnchor(anchor, corner.TOP_LEFT,
    -                                             popup, corner.TOP_RIGHT,
    -                                             undefined, undefined,
    -                                             overflow.FAIL_X, undefined,
    -                                             viewport);
    -  assertFalse('Positioning operation should have failed.',
    -              (status & goog.positioning.OverflowStatus.FAILED) == 0);
    -
    -  // Change overflow strategy to adjust.
    -  status = goog.positioning.positionAtAnchor(anchor, corner.TOP_LEFT,
    -                                             popup, corner.TOP_RIGHT,
    -                                             undefined, undefined,
    -                                             overflow.ADJUST_X, undefined,
    -                                             viewport);
    -  anchorRect = goog.style.getBounds(anchor);
    -  popupRect = goog.style.getBounds(popup);
    -  assertTrue('Positioning operation should have been successful.',
    -             (status & goog.positioning.OverflowStatus.FAILED) == 0);
    -  assertFalse('X position should have been adjusted.',
    -              (status & goog.positioning.OverflowStatus.ADJUSTED_X) == 0);
    -  assertTrue('Y position should not have been adjusted.',
    -             (status & goog.positioning.OverflowStatus.ADJUSTED_Y) == 0);
    -  assertRoughlyEquals(
    -      'Left edge of popup should line up with left edge of viewport.',
    -      viewport.left, popupRect.left, EPSILON);
    -  assertRoughlyEquals('Popup should have the same y position as the anchor.',
    -                      anchorRect.top,
    -                      popupRect.top,
    -                      1);
    -}
    -
    -function testPositionAtAnchorOutsideViewport() {
    -  var anchor = document.getElementById('anchor4');
    -  var popup = document.getElementById('popup1');
    -
    -  var status = goog.positioning.positionAtAnchor(anchor, corner.TOP_LEFT,
    -                                                 popup, corner.TOP_RIGHT);
    -  var anchorRect = goog.style.getBounds(anchor);
    -  var popupRect = goog.style.getBounds(popup);
    -  assertTrue('Positioning operation should have been successful.',
    -             (status & goog.positioning.OverflowStatus.FAILED) == 0);
    -  assertTrue('X position should not have been adjusted.',
    -             (status & goog.positioning.OverflowStatus.ADJUSTED_X) == 0);
    -  assertTrue('Y position should not have been adjusted.',
    -             (status & goog.positioning.OverflowStatus.ADJUSTED_Y) == 0);
    -
    -  assertEquals('Right edge of popup should line up with left edge of anchor.',
    -               anchorRect.left,
    -               popupRect.left + popupRect.width);
    -
    -  // Change overflow strategy to fail.
    -  status = goog.positioning.positionAtAnchor(anchor, corner.BOTTOM_RIGHT,
    -                                             popup, corner.TOP_RIGHT,
    -                                             undefined, undefined,
    -                                             overflow.FAIL_X);
    -  assertFalse('Positioning operation should have failed.',
    -              (status & goog.positioning.OverflowStatus.FAILED) == 0);
    -
    -  // Change overflow strategy to adjust.
    -  status = goog.positioning.positionAtAnchor(anchor, corner.BOTTOM_RIGHT,
    -                                             popup, corner.TOP_RIGHT,
    -                                             undefined, undefined,
    -                                             overflow.ADJUST_X);
    -  anchorRect = goog.style.getBounds(anchor);
    -  popupRect = goog.style.getBounds(popup);
    -  assertTrue('Positioning operation should have been successful.',
    -             (status & goog.positioning.OverflowStatus.FAILED) == 0);
    -  assertFalse('X position should have been adjusted.',
    -              (status & goog.positioning.OverflowStatus.ADJUSTED_X) == 0);
    -  assertTrue('Y position should not have been adjusted.',
    -             (status & goog.positioning.OverflowStatus.ADJUSTED_Y) == 0);
    -  assertRoughlyEquals(
    -      'Left edge of popup should line up with left edge of viewport.',
    -      0, popupRect.left, EPSILON);
    -  assertEquals('Popup should be positioned just below the anchor.',
    -               anchorRect.top + anchorRect.height,
    -               popupRect.top);
    -}
    -
    -
    -function testAdjustForViewportFailIgnore() {
    -  var f = goog.positioning.adjustForViewport_;
    -  var viewport = new goog.math.Box(100, 200, 200, 100);
    -  var overflow = goog.positioning.Overflow.IGNORE;
    -
    -  var pos = newCoord(150, 150);
    -  var size = newSize(50, 50);
    -  assertEquals('Viewport overflow should be ignored.',
    -               goog.positioning.OverflowStatus.NONE,
    -               f(pos, size, viewport, overflow));
    -
    -  pos = newCoord(150, 150);
    -  size = newSize(100, 50);
    -  assertEquals('Viewport overflow should be ignored.',
    -               goog.positioning.OverflowStatus.NONE,
    -               f(pos, size, viewport, overflow));
    -
    -  pos = newCoord(50, 50);
    -  size = newSize(50, 50);
    -  assertEquals('Viewport overflow should be ignored.',
    -               goog.positioning.OverflowStatus.NONE,
    -               f(pos, size, viewport, overflow));
    -}
    -
    -
    -function testAdjustForViewportFailXY() {
    -  var f = goog.positioning.adjustForViewport_;
    -  var viewport = new goog.math.Box(100, 200, 200, 100);
    -  var overflow = goog.positioning.Overflow.FAIL_X |
    -                 goog.positioning.Overflow.FAIL_Y;
    -
    -  var pos = newCoord(150, 150);
    -  var size = newSize(50, 50);
    -  assertEquals('Element should not overflow viewport.',
    -               goog.positioning.OverflowStatus.NONE,
    -               f(pos, size, viewport, overflow));
    -
    -  pos = newCoord(150, 150);
    -  size = newSize(100, 50);
    -  assertEquals('Element should overflow the right edge of viewport.',
    -               goog.positioning.OverflowStatus.FAILED_RIGHT,
    -               f(pos, size, viewport, overflow));
    -
    -  pos = newCoord(150, 150);
    -  size = newSize(50, 100);
    -  assertEquals('Element should overflow the bottom edge of viewport.',
    -               goog.positioning.OverflowStatus.FAILED_BOTTOM,
    -               f(pos, size, viewport, overflow));
    -
    -  pos = newCoord(50, 150);
    -  size = newSize(50, 50);
    -  assertEquals('Element should overflow the left edge of viewport.',
    -               goog.positioning.OverflowStatus.FAILED_LEFT,
    -               f(pos, size, viewport, overflow));
    -
    -  pos = newCoord(150, 50);
    -  size = newSize(50, 50);
    -  assertEquals('Element should overflow the top edge of viewport.',
    -               goog.positioning.OverflowStatus.FAILED_TOP,
    -               f(pos, size, viewport, overflow));
    -
    -  pos = newCoord(50, 50);
    -  size = newSize(50, 50);
    -  assertEquals('Element should overflow the left & top edges of viewport.',
    -               goog.positioning.OverflowStatus.FAILED_LEFT |
    -               goog.positioning.OverflowStatus.FAILED_TOP,
    -               f(pos, size, viewport, overflow));
    -}
    -
    -
    -function testAdjustForViewportAdjustXFailY() {
    -  var f = goog.positioning.adjustForViewport_;
    -  var viewport = new goog.math.Box(100, 200, 200, 100);
    -  var overflow = goog.positioning.Overflow.ADJUST_X |
    -                 goog.positioning.Overflow.FAIL_Y;
    -
    -  var pos = newCoord(150, 150);
    -  var size = newSize(50, 50);
    -  assertEquals('Element should not overflow viewport.',
    -               goog.positioning.OverflowStatus.NONE,
    -               f(pos, size, viewport, overflow));
    -  assertEquals('X Position should not have been changed.', 150, pos.x);
    -  assertEquals('Y Position should not have been changed.', 150, pos.y);
    -
    -  pos = newCoord(150, 150);
    -  size = newSize(100, 50);
    -  assertEquals('Element position should be adjusted not to overflow right ' +
    -               'edge of viewport.',
    -               goog.positioning.OverflowStatus.ADJUSTED_X,
    -               f(pos, size, viewport, overflow));
    -  assertEquals('X Position should be adjusted to 100.', 100, pos.x);
    -  assertEquals('Y Position should not have been changed.', 150, pos.y);
    -
    -  pos = newCoord(50, 150);
    -  size = newSize(100, 50);
    -  assertEquals('Element position should be adjusted not to overflow left ' +
    -               'edge of viewport.',
    -               goog.positioning.OverflowStatus.ADJUSTED_X,
    -               f(pos, size, viewport, overflow));
    -  assertEquals('X Position should be adjusted to 100.', 100, pos.x);
    -  assertEquals('Y Position should not have been changed.', 150, pos.y);
    -
    -
    -  pos = newCoord(50, 50);
    -  size = newSize(100, 50);
    -  assertEquals('Element position should be adjusted not to overflow left ' +
    -               'edge of viewport, should overflow bottom edge.',
    -               goog.positioning.OverflowStatus.ADJUSTED_X |
    -               goog.positioning.OverflowStatus.FAILED_TOP,
    -               f(pos, size, viewport, overflow));
    -  assertEquals('X Position should be adjusted to 100.', 100, pos.x);
    -  assertEquals('Y Position should not have been changed.', 50, pos.y);
    -}
    -
    -
    -function testAdjustForViewportResizeHeight() {
    -  var f = goog.positioning.adjustForViewport_;
    -  var viewport = new goog.math.Box(0, 200, 200, 0);
    -  var overflow = goog.positioning.Overflow.RESIZE_HEIGHT;
    -
    -  var pos = newCoord(150, 150);
    -  var size = newSize(25, 100);
    -  assertEquals('Viewport height should be resized.',
    -               goog.positioning.OverflowStatus.HEIGHT_ADJUSTED,
    -               f(pos, size, viewport, overflow));
    -  assertEquals('Height should be resized to 50.',
    -               50, size.height);
    -  assertTrue('Output box is within viewport',
    -             viewport.contains(new goog.math.Box(pos.y, pos.x + size.width,
    -                                                 pos.y + size.height, pos.x)));
    -
    -  var pos = newCoord(0, 0);
    -  var size = newSize(50, 250);
    -  assertEquals('Viewport height should be resized.',
    -               goog.positioning.OverflowStatus.HEIGHT_ADJUSTED,
    -               f(pos, size, viewport, overflow));
    -  assertEquals('Height should be resized to 200.',
    -               200, size.height);
    -  assertTrue('Output box is within viewport',
    -             viewport.contains(new goog.math.Box(pos.y, pos.x + size.width,
    -                                                 pos.y + size.height, pos.x)));
    -
    -  var pos = newCoord(0, -50);
    -  var size = newSize(50, 240);
    -  assertEquals('Viewport height should be resized.',
    -               goog.positioning.OverflowStatus.HEIGHT_ADJUSTED,
    -               f(pos, size, viewport, overflow));
    -  assertEquals('Height should be resized to 190.',
    -               190, size.height);
    -  assertTrue('Output box is within viewport',
    -             viewport.contains(new goog.math.Box(pos.y, pos.x + size.width,
    -                                                 pos.y + size.height, pos.x)));
    -
    -  var pos = newCoord(0, -50);
    -  var size = newSize(50, 300);
    -  assertEquals('Viewport height should be resized.',
    -               goog.positioning.OverflowStatus.HEIGHT_ADJUSTED,
    -               f(pos, size, viewport, overflow));
    -  assertEquals('Height should be resized to 200.',
    -               200, size.height);
    -  assertTrue('Output box is within viewport',
    -             viewport.contains(new goog.math.Box(pos.y, pos.x + size.width,
    -                                                 pos.y + size.height, pos.x)));
    -
    -  pos = newCoord(150, 150);
    -  size = newSize(50, 50);
    -  assertEquals('No Viewport overflow.',
    -               goog.positioning.OverflowStatus.NONE,
    -               f(pos, size, viewport, overflow));
    -  assertTrue('Output box is within viewport',
    -             viewport.contains(new goog.math.Box(pos.y, pos.x + size.width,
    -                                                 pos.y + size.height, pos.x)));
    -
    -  var offsetViewport = new goog.math.Box(100, 200, 300, 0);
    -  var pos = newCoord(0, 50);
    -  var size = newSize(50, 240);
    -  assertEquals('Viewport height should be resized.',
    -               goog.positioning.OverflowStatus.HEIGHT_ADJUSTED,
    -               f(pos, size, offsetViewport, overflow));
    -  assertEquals('Height should be resized to 190.',
    -               190, size.height);
    -  assertTrue('Output box is within viewport',
    -             offsetViewport.contains(new goog.math.Box(pos.y,
    -                                                       pos.x + size.width,
    -                                                       pos.y + size.height,
    -                                                       pos.x)));
    -}
    -
    -
    -
    -function testAdjustForViewportResizeWidth() {
    -  var f = goog.positioning.adjustForViewport_;
    -  var viewport = new goog.math.Box(0, 200, 200, 0);
    -  var overflow = goog.positioning.Overflow.RESIZE_WIDTH;
    -
    -  var pos = newCoord(150, 150);
    -  var size = newSize(100, 25);
    -  assertEquals('Viewport width should be resized.',
    -               goog.positioning.OverflowStatus.WIDTH_ADJUSTED,
    -               f(pos, size, viewport, overflow));
    -  assertEquals('Width should be resized to 50.',
    -               50, size.width);
    -  assertTrue('Output box is within viewport',
    -             viewport.contains(new goog.math.Box(pos.y, pos.x + size.width,
    -                                                 pos.y + size.height, pos.x)));
    -
    -  var pos = newCoord(0, 0);
    -  var size = newSize(250, 50);
    -  assertEquals('Viewport width should be resized.',
    -               goog.positioning.OverflowStatus.WIDTH_ADJUSTED,
    -               f(pos, size, viewport, overflow));
    -  assertEquals('Width should be resized to 200.',
    -               200, size.width);
    -  assertTrue('Output box is within viewport',
    -             viewport.contains(new goog.math.Box(pos.y, pos.x + size.width,
    -                                                 pos.y + size.height, pos.x)));
    -
    -  var pos = newCoord(-50, 0);
    -  var size = newSize(240, 50);
    -  assertEquals('Viewport width should be resized.',
    -               goog.positioning.OverflowStatus.WIDTH_ADJUSTED,
    -               f(pos, size, viewport, overflow));
    -  assertEquals('Width should be resized to 190.',
    -               190, size.width);
    -  assertTrue('Output box is within viewport',
    -             viewport.contains(new goog.math.Box(pos.y, pos.x + size.width,
    -                                                 pos.y + size.height, pos.x)));
    -
    -  var pos = newCoord(-50, 0);
    -  var size = newSize(300, 50);
    -  assertEquals('Viewport width should be resized.',
    -               goog.positioning.OverflowStatus.WIDTH_ADJUSTED,
    -               f(pos, size, viewport, overflow));
    -  assertEquals('Width should be resized to 200.',
    -               200, size.width);
    -  assertTrue('Output box is within viewport',
    -             viewport.contains(new goog.math.Box(pos.y, pos.x + size.width,
    -                                                 pos.y + size.height, pos.x)));
    -
    -  pos = newCoord(150, 150);
    -  size = newSize(50, 50);
    -  assertEquals('No Viewport overflow.',
    -               goog.positioning.OverflowStatus.NONE,
    -               f(pos, size, viewport, overflow));
    -  assertTrue('Output box is within viewport',
    -             viewport.contains(new goog.math.Box(pos.y, pos.x + size.width,
    -                                                 pos.y + size.height, pos.x)));
    -
    -  var offsetViewport = new goog.math.Box(0, 300, 200, 100);
    -  var pos = newCoord(50, 0);
    -  var size = newSize(240, 50);
    -  assertEquals('Viewport width should be resized.',
    -               goog.positioning.OverflowStatus.WIDTH_ADJUSTED,
    -               f(pos, size, offsetViewport, overflow));
    -  assertEquals('Width should be resized to 190.',
    -               190, size.width);
    -  assertTrue('Output box is within viewport',
    -             offsetViewport.contains(new goog.math.Box(pos.y,
    -                                                       pos.x + size.width,
    -                                                       pos.y + size.height,
    -                                                       pos.x)));
    -}
    -
    -
    -function testPositionAtAnchorWithResizeHeight() {
    -  var anchor = document.getElementById('anchor9');
    -  var popup = document.getElementById('popup9');
    -  var box = document.getElementById('box9');
    -  var viewport = goog.style.getBounds(box);
    -
    -  var status = goog.positioning.positionAtAnchor(
    -      anchor, corner.TOP_START, popup, corner.TOP_START,
    -      new goog.math.Coordinate(0, -20), null,
    -      goog.positioning.Overflow.RESIZE_HEIGHT, null,
    -      viewport.toBox());
    -  assertEquals('Status should be HEIGHT_ADJUSTED.',
    -               goog.positioning.OverflowStatus.HEIGHT_ADJUSTED, status);
    -
    -  var TOLERANCE = 0.1;
    -  // Adjust the viewport to allow some tolerance for subpixel positioning,
    -  // this is required for this test to pass on IE10,11
    -  viewport.top -= TOLERANCE;
    -  viewport.left -= TOLERANCE;
    -
    -  assertTrue('Popup ' + goog.style.getBounds(popup) +
    -             ' not is within viewport' + viewport,
    -             viewport.contains(goog.style.getBounds(popup)));
    -}
    -
    -
    -function testPositionAtCoordinateResizeHeight() {
    -  var f = goog.positioning.positionAtCoordinate;
    -  var viewport = new goog.math.Box(0, 50, 50, 0);
    -  var overflow = goog.positioning.Overflow.RESIZE_HEIGHT |
    -      goog.positioning.Overflow.ADJUST_Y;
    -  var popup = document.getElementById('popup1');
    -  var corner = goog.positioning.Corner.BOTTOM_LEFT;
    -
    -  var pos = newCoord(100, 100);
    -
    -  assertEquals('Viewport height should be resized.',
    -               goog.positioning.OverflowStatus.HEIGHT_ADJUSTED |
    -               goog.positioning.OverflowStatus.ADJUSTED_Y,
    -               f(pos, popup, corner, undefined, viewport, overflow));
    -  var bounds = goog.style.getSize(popup);
    -  assertEquals('Height should be resized to the size of the viewport.',
    -               50, bounds.height);
    -}
    -
    -
    -function testGetPositionAtCoordinateResizeHeight() {
    -  var f = goog.positioning.getPositionAtCoordinate;
    -  var viewport = new goog.math.Box(0, 50, 50, 0);
    -  var overflow = goog.positioning.Overflow.RESIZE_HEIGHT |
    -      goog.positioning.Overflow.ADJUST_Y;
    -  var popup = document.getElementById('popup1');
    -  var corner = goog.positioning.Corner.BOTTOM_LEFT;
    -
    -  var pos = newCoord(100, 100);
    -  var size = goog.style.getSize(popup);
    -
    -  var result = f(pos, size, corner, undefined, viewport, overflow);
    -  assertEquals('Viewport height should be resized.',
    -               goog.positioning.OverflowStatus.HEIGHT_ADJUSTED |
    -               goog.positioning.OverflowStatus.ADJUSTED_Y,
    -               result.status);
    -  assertEquals('Height should be resized to the size of the viewport.',
    -               50, result.rect.height);
    -}
    -
    -
    -function testGetEffectiveCornerLeftToRight() {
    -  var f = goog.positioning.getEffectiveCorner;
    -  var el = document.getElementById('ltr');
    -
    -  assertEquals('TOP_LEFT should be unchanged for ltr.',
    -               corner.TOP_LEFT,
    -               f(el, corner.TOP_LEFT));
    -  assertEquals('TOP_RIGHT should be unchanged for ltr.',
    -               corner.TOP_RIGHT,
    -               f(el, corner.TOP_RIGHT));
    -  assertEquals('BOTTOM_LEFT should be unchanged for ltr.',
    -               corner.BOTTOM_LEFT,
    -               f(el, corner.BOTTOM_LEFT));
    -  assertEquals('BOTTOM_RIGHT should be unchanged for ltr.',
    -               corner.BOTTOM_RIGHT,
    -               f(el, corner.BOTTOM_RIGHT));
    -
    -  assertEquals('TOP_START should be TOP_LEFT for ltr.',
    -               corner.TOP_LEFT,
    -               f(el, corner.TOP_START));
    -  assertEquals('TOP_END should be TOP_RIGHT for ltr.',
    -               corner.TOP_RIGHT,
    -               f(el, corner.TOP_END));
    -  assertEquals('BOTTOM_START should be BOTTOM_LEFT for ltr.',
    -               corner.BOTTOM_LEFT,
    -               f(el, corner.BOTTOM_START));
    -  assertEquals('BOTTOM_END should be BOTTOM_RIGHT for ltr.',
    -               corner.BOTTOM_RIGHT,
    -               f(el, corner.BOTTOM_END));
    -}
    -
    -
    -function testGetEffectiveCornerRightToLeft() {
    -  var f = goog.positioning.getEffectiveCorner;
    -  var el = document.getElementById('rtl');
    -
    -  assertEquals('TOP_LEFT should be unchanged for rtl.',
    -               corner.TOP_LEFT,
    -               f(el, corner.TOP_LEFT));
    -  assertEquals('TOP_RIGHT should be unchanged for rtl.',
    -               corner.TOP_RIGHT,
    -               f(el, corner.TOP_RIGHT));
    -  assertEquals('BOTTOM_LEFT should be unchanged for rtl.',
    -               corner.BOTTOM_LEFT,
    -               f(el, corner.BOTTOM_LEFT));
    -  assertEquals('BOTTOM_RIGHT should be unchanged for rtl.',
    -               corner.BOTTOM_RIGHT,
    -               f(el, corner.BOTTOM_RIGHT));
    -
    -  assertEquals('TOP_START should be TOP_RIGHT for rtl.',
    -               corner.TOP_RIGHT,
    -               f(el, corner.TOP_START));
    -  assertEquals('TOP_END should be TOP_LEFT for rtl.',
    -               corner.TOP_LEFT,
    -               f(el, corner.TOP_END));
    -  assertEquals('BOTTOM_START should be BOTTOM_RIGHT for rtl.',
    -               corner.BOTTOM_RIGHT,
    -               f(el, corner.BOTTOM_START));
    -  assertEquals('BOTTOM_END should be BOTTOM_LEFT for rtl.',
    -               corner.BOTTOM_LEFT,
    -               f(el, corner.BOTTOM_END));
    -}
    -
    -
    -function testFlipCornerHorizontal() {
    -  var f = goog.positioning.flipCornerHorizontal;
    -
    -  assertEquals('TOP_LEFT should be flipped to TOP_RIGHT.',
    -               corner.TOP_RIGHT,
    -               f(corner.TOP_LEFT));
    -  assertEquals('TOP_RIGHT should be flipped to TOP_LEFT.',
    -               corner.TOP_LEFT,
    -               f(corner.TOP_RIGHT));
    -  assertEquals('BOTTOM_LEFT should be flipped to BOTTOM_RIGHT.',
    -               corner.BOTTOM_RIGHT,
    -               f(corner.BOTTOM_LEFT));
    -  assertEquals('BOTTOM_RIGHT should be flipped to BOTTOM_LEFT.',
    -               corner.BOTTOM_LEFT,
    -               f(corner.BOTTOM_RIGHT));
    -
    -  assertEquals('TOP_START should be flipped to TOP_END.',
    -               corner.TOP_END,
    -               f(corner.TOP_START));
    -  assertEquals('TOP_END should be flipped to TOP_START.',
    -               corner.TOP_START,
    -               f(corner.TOP_END));
    -  assertEquals('BOTTOM_START should be flipped to BOTTOM_END.',
    -               corner.BOTTOM_END,
    -               f(corner.BOTTOM_START));
    -  assertEquals('BOTTOM_END should be flipped to BOTTOM_START.',
    -               corner.BOTTOM_START,
    -               f(corner.BOTTOM_END));
    -}
    -
    -
    -function testFlipCornerVertical() {
    -  var f = goog.positioning.flipCornerVertical;
    -
    -  assertEquals('TOP_LEFT should be flipped to BOTTOM_LEFT.',
    -               corner.BOTTOM_LEFT,
    -               f(corner.TOP_LEFT));
    -  assertEquals('TOP_RIGHT should be flipped to BOTTOM_RIGHT.',
    -               corner.BOTTOM_RIGHT,
    -               f(corner.TOP_RIGHT));
    -  assertEquals('BOTTOM_LEFT should be flipped to TOP_LEFT.',
    -               corner.TOP_LEFT,
    -               f(corner.BOTTOM_LEFT));
    -  assertEquals('BOTTOM_RIGHT should be flipped to TOP_RIGHT.',
    -               corner.TOP_RIGHT,
    -               f(corner.BOTTOM_RIGHT));
    -
    -  assertEquals('TOP_START should be flipped to BOTTOM_START.',
    -               corner.BOTTOM_START,
    -               f(corner.TOP_START));
    -  assertEquals('TOP_END should be flipped to BOTTOM_END.',
    -               corner.BOTTOM_END,
    -               f(corner.TOP_END));
    -  assertEquals('BOTTOM_START should be flipped to TOP_START.',
    -               corner.TOP_START,
    -               f(corner.BOTTOM_START));
    -  assertEquals('BOTTOM_END should be flipped to TOP_END.',
    -               corner.TOP_END,
    -               f(corner.BOTTOM_END));
    -}
    -
    -
    -function testFlipCorner() {
    -  var f = goog.positioning.flipCorner;
    -
    -  assertEquals('TOP_LEFT should be flipped to BOTTOM_RIGHT.',
    -               corner.BOTTOM_RIGHT,
    -               f(corner.TOP_LEFT));
    -  assertEquals('TOP_RIGHT should be flipped to BOTTOM_LEFT.',
    -               corner.BOTTOM_LEFT,
    -               f(corner.TOP_RIGHT));
    -  assertEquals('BOTTOM_LEFT should be flipped to TOP_RIGHT.',
    -               corner.TOP_RIGHT,
    -               f(corner.BOTTOM_LEFT));
    -  assertEquals('BOTTOM_RIGHT should be flipped to TOP_LEFT.',
    -               corner.TOP_LEFT,
    -               f(corner.BOTTOM_RIGHT));
    -
    -  assertEquals('TOP_START should be flipped to BOTTOM_END.',
    -               corner.BOTTOM_END,
    -               f(corner.TOP_START));
    -  assertEquals('TOP_END should be flipped to BOTTOM_START.',
    -               corner.BOTTOM_START,
    -               f(corner.TOP_END));
    -  assertEquals('BOTTOM_START should be flipped to TOP_END.',
    -               corner.TOP_END,
    -               f(corner.BOTTOM_START));
    -  assertEquals('BOTTOM_END should be flipped to TOP_START.',
    -               corner.TOP_START,
    -               f(corner.BOTTOM_END));
    -}
    -
    -function testPositionAtAnchorFrameViewportStandard() {
    -  var iframe = document.getElementById('iframe-standard');
    -  var iframeDoc = goog.dom.getFrameContentDocument(iframe);
    -  assertTrue(new goog.dom.DomHelper(iframeDoc).isCss1CompatMode());
    -
    -  new goog.dom.DomHelper(iframeDoc).getDocumentScrollElement().scrollTop = 100;
    -  var anchor = iframeDoc.getElementById('anchor1');
    -  var popup = document.getElementById('popup6');
    -
    -  var status = goog.positioning.positionAtAnchor(
    -      anchor, corner.TOP_RIGHT, popup, corner.BOTTOM_RIGHT);
    -  var iframeRect = goog.style.getBounds(iframe);
    -  var popupRect = goog.style.getBounds(popup);
    -  assertEquals('Status should not have any ADJUSTED and FAILED.',
    -               goog.positioning.OverflowStatus.NONE, status);
    -  assertRoundedEquals('Popup should be positioned just above the iframe, ' +
    -                      'not above the anchor element inside the iframe',
    -                      iframeRect.top,
    -                      popupRect.top + popupRect.height);
    -}
    -
    -function testPositionAtAnchorFrameViewportQuirk() {
    -  var iframe = document.getElementById('iframe-quirk');
    -  var iframeDoc = goog.dom.getFrameContentDocument(iframe);
    -  assertFalse(new goog.dom.DomHelper(iframeDoc).isCss1CompatMode());
    -
    -  window.scrollTo(0, 100);
    -  new goog.dom.DomHelper(iframeDoc).getDocumentScrollElement().scrollTop = 100;
    -  var anchor = iframeDoc.getElementById('anchor1');
    -  var popup = document.getElementById('popup6');
    -
    -  var status = goog.positioning.positionAtAnchor(
    -      anchor, corner.TOP_RIGHT, popup, corner.BOTTOM_RIGHT);
    -  var iframeRect = goog.style.getBounds(iframe);
    -  var popupRect = goog.style.getBounds(popup);
    -  assertEquals('Status should not have any ADJUSTED and FAILED.',
    -               goog.positioning.OverflowStatus.NONE, status);
    -  assertRoundedEquals('Popup should be positioned just above the iframe, ' +
    -                      'not above the anchor element inside the iframe',
    -                      iframeRect.top,
    -                      popupRect.top + popupRect.height);
    -}
    -
    -function testPositionAtAnchorFrameViewportWithPopupInScroller() {
    -  var iframe = document.getElementById('iframe-standard');
    -  var iframeDoc = goog.dom.getFrameContentDocument(iframe);
    -
    -  new goog.dom.DomHelper(iframeDoc).getDocumentScrollElement().scrollTop = 100;
    -  var anchor = iframeDoc.getElementById('anchor1');
    -  var popup = document.getElementById('popup7');
    -  popup.offsetParent.scrollTop = 50;
    -
    -  var status = goog.positioning.positionAtAnchor(
    -      anchor, corner.TOP_RIGHT, popup, corner.BOTTOM_RIGHT);
    -  var iframeRect = goog.style.getBounds(iframe);
    -  var popupRect = goog.style.getBounds(popup);
    -  assertEquals('Status should not have any ADJUSTED and FAILED.',
    -               goog.positioning.OverflowStatus.NONE, status);
    -  assertRoughlyEquals('Popup should be positioned just above the iframe, ' +
    -      'not above the anchor element inside the iframe',
    -      iframeRect.top,
    -      popupRect.top + popupRect.height,
    -      ALLOWED_OFFSET);
    -}
    -
    -function testPositionAtAnchorNestedFrames() {
    -  var outerIframe = document.getElementById('nested-outer');
    -  var outerDoc = goog.dom.getFrameContentDocument(outerIframe);
    -  var popup = outerDoc.getElementById('popup1');
    -  var innerIframe = outerDoc.getElementById('inner-frame');
    -  var innerDoc = goog.dom.getFrameContentDocument(innerIframe);
    -  var anchor = innerDoc.getElementById('anchor1');
    -
    -  var status = goog.positioning.positionAtAnchor(
    -      anchor, corner.TOP_LEFT, popup, corner.BOTTOM_LEFT);
    -  assertEquals('Status should not have any ADJUSTED and FAILED.',
    -               goog.positioning.OverflowStatus.NONE, status);
    -  var innerIframeRect = goog.style.getBounds(innerIframe);
    -  var popupRect = goog.style.getBounds(popup);
    -  assertRoundedEquals('Top of frame should align with bottom of the popup',
    -                      innerIframeRect.top, popupRect.top + popupRect.height);
    -
    -  // The anchor is scrolled up by 10px.
    -  // Popup position should be the same as above.
    -  goog.dom.getWindow(innerDoc).scrollTo(0, 10);
    -  status = goog.positioning.positionAtAnchor(
    -      anchor, corner.TOP_LEFT, popup, corner.BOTTOM_LEFT);
    -  assertEquals('Status should not have any ADJUSTED and FAILED.',
    -               goog.positioning.OverflowStatus.NONE, status);
    -  innerIframeRect = goog.style.getBounds(innerIframe);
    -  popupRect = goog.style.getBounds(popup);
    -  assertRoundedEquals('Top of frame should align with bottom of the popup',
    -                      innerIframeRect.top, popupRect.top + popupRect.height);
    -}
    -
    -function testPositionAtAnchorOffscreen() {
    -  var offset = 0;
    -  var anchor = goog.dom.getElement('offscreen-anchor');
    -  var popup = goog.dom.getElement('popup3');
    -
    -  goog.positioning.positionAtAnchor(
    -      anchor, corner.TOP_LEFT, popup, corner.TOP_LEFT, null, null,
    -      overflow.ADJUST_X | overflow.ADJUST_Y);
    -  assertObjectEquals(
    -      newCoord(offset, offset), goog.style.getPageOffset(popup));
    -
    -  goog.positioning.positionAtAnchor(
    -      anchor, corner.TOP_LEFT, popup, corner.TOP_LEFT, null, null,
    -      overflow.ADJUST_X_EXCEPT_OFFSCREEN | overflow.ADJUST_Y);
    -  assertObjectEquals(
    -      newCoord(-1000, offset), goog.style.getPageOffset(popup));
    -
    -  goog.positioning.positionAtAnchor(
    -      anchor, corner.TOP_LEFT, popup, corner.TOP_LEFT, null, null,
    -      overflow.ADJUST_X | overflow.ADJUST_Y_EXCEPT_OFFSCREEN);
    -  assertObjectEquals(
    -      newCoord(offset, -1000), goog.style.getPageOffset(popup));
    -
    -  goog.positioning.positionAtAnchor(
    -      anchor, corner.TOP_LEFT, popup, corner.TOP_LEFT, null, null,
    -      overflow.ADJUST_X_EXCEPT_OFFSCREEN | overflow.ADJUST_Y_EXCEPT_OFFSCREEN);
    -  assertObjectEquals(
    -      newCoord(-1000, -1000),
    -      goog.style.getPageOffset(popup));
    -}
    -
    -function testPositionAtAnchorWithOverflowScrollOffsetParent() {
    -  var testAreaOffset = goog.style.getPageOffset(testArea);
    -  var scrollbarWidth = goog.style.getScrollbarWidth();
    -  window.scrollTo(testAreaOffset.x, testAreaOffset.y);
    -
    -  var overflowDiv = goog.dom.createElement('div');
    -  overflowDiv.style.overflow = 'scroll';
    -  overflowDiv.style.position = 'relative';
    -  goog.style.setSize(overflowDiv, 200 /* width */, 100 /* height */);
    -
    -  var anchor = goog.dom.createElement('div');
    -  anchor.style.position = 'absolute';
    -  goog.style.setSize(anchor, 50 /* width */, 50 /* height */);
    -  goog.style.setPosition(anchor, 300 /* left */, 300 /* top */);
    -
    -  var popup = createPopupDiv(75 /* width */, 50 /* height */);
    -
    -  goog.dom.append(testArea, overflowDiv, anchor);
    -  goog.dom.append(overflowDiv, popup);
    -
    -  // Popup should always be positioned within the overflowDiv
    -  goog.style.setPosition(overflowDiv, 0 /* left */, 0 /* top */);
    -  goog.positioning.positionAtAnchor(
    -      anchor, corner.TOP_LEFT, popup, corner.TOP_RIGHT, null, null,
    -      overflow.ADJUST_X | overflow.ADJUST_Y);
    -  assertObjectRoughlyEquals(
    -      new goog.math.Coordinate(
    -          testAreaOffset.x + 200 - 75 - scrollbarWidth,
    -          testAreaOffset.y + 100 - 50 - scrollbarWidth),
    -      goog.style.getPageOffset(popup),
    -      1);
    -
    -  goog.style.setPosition(overflowDiv, 400 /* left */, 0 /* top */);
    -  goog.positioning.positionAtAnchor(
    -      anchor, corner.TOP_RIGHT, popup, corner.TOP_LEFT, null, null,
    -      overflow.ADJUST_X | overflow.ADJUST_Y);
    -  assertObjectRoughlyEquals(
    -      new goog.math.Coordinate(
    -          testAreaOffset.x + 400, testAreaOffset.y + 100 - 50 - scrollbarWidth),
    -      goog.style.getPageOffset(popup),
    -      1);
    -
    -  goog.style.setPosition(overflowDiv, 0 /* left */, 400 /* top */);
    -  goog.positioning.positionAtAnchor(
    -      anchor, corner.BOTTOM_LEFT, popup, corner.BOTTOM_RIGHT, null, null,
    -      overflow.ADJUST_X | overflow.ADJUST_Y);
    -  assertObjectRoughlyEquals(
    -      new goog.math.Coordinate(
    -          testAreaOffset.x + 200 - 75 - scrollbarWidth, testAreaOffset.y + 400),
    -      goog.style.getPageOffset(popup),
    -      1);
    -
    -  goog.style.setPosition(overflowDiv, 400 /* left */, 400 /* top */);
    -  goog.positioning.positionAtAnchor(
    -      anchor, corner.BOTTOM_RIGHT, popup, corner.BOTTOM_LEFT, null, null,
    -      overflow.ADJUST_X | overflow.ADJUST_Y);
    -  assertObjectRoughlyEquals(
    -      new goog.math.Coordinate(
    -          testAreaOffset.x + 400, testAreaOffset.y + 400),
    -      goog.style.getPageOffset(popup),
    -      1);
    -
    -  // No overflow.
    -  goog.style.setPosition(overflowDiv, 300 - 50 /* left */, 300 /* top */);
    -  goog.positioning.positionAtAnchor(
    -      anchor, corner.TOP_LEFT, popup, corner.TOP_RIGHT, null, null,
    -      overflow.ADJUST_X | overflow.ADJUST_Y);
    -  assertObjectRoughlyEquals(
    -      new goog.math.Coordinate(
    -          testAreaOffset.x + 300 - 50, testAreaOffset.y + 300),
    -      goog.style.getPageOffset(popup),
    -      1);
    -}
    -
    -function testPositionAtAnchorWithOverflowHiddenParent() {
    -  var testAreaOffset = goog.style.getPageOffset(testArea);
    -  window.scrollTo(testAreaOffset.x, testAreaOffset.y);
    -
    -  var overflowDiv = goog.dom.createElement('div');
    -  overflowDiv.style.overflow = 'hidden';
    -  overflowDiv.style.position = 'relative';
    -  goog.style.setSize(overflowDiv, 200 /* width */, 100 /* height */);
    -
    -  var anchor = goog.dom.createElement('div');
    -  anchor.style.position = 'absolute';
    -  goog.style.setSize(anchor, 50 /* width */, 50 /* height */);
    -  goog.style.setPosition(anchor, 300 /* left */, 300 /* top */);
    -
    -  var popup = createPopupDiv(75 /* width */, 50 /* height */);
    -
    -  goog.dom.append(testArea, overflowDiv, anchor);
    -  goog.dom.append(overflowDiv, popup);
    -
    -  // Popup should always be positioned within the overflowDiv
    -  goog.style.setPosition(overflowDiv, 0 /* left */, 0 /* top */);
    -  goog.positioning.positionAtAnchor(
    -      anchor, corner.TOP_LEFT, popup, corner.TOP_RIGHT, null, null,
    -      overflow.ADJUST_X | overflow.ADJUST_Y);
    -  assertObjectRoughlyEquals(
    -      new goog.math.Coordinate(
    -          testAreaOffset.x + 200 - 75, testAreaOffset.y + 100 - 50),
    -      goog.style.getPageOffset(popup),
    -      1);
    -
    -  goog.style.setPosition(overflowDiv, 400 /* left */, 0 /* top */);
    -  goog.positioning.positionAtAnchor(
    -      anchor, corner.TOP_RIGHT, popup, corner.TOP_LEFT, null, null,
    -      overflow.ADJUST_X | overflow.ADJUST_Y);
    -  assertObjectRoughlyEquals(
    -      new goog.math.Coordinate(
    -          testAreaOffset.x + 400, testAreaOffset.y + 100 - 50),
    -      goog.style.getPageOffset(popup),
    -      1);
    -
    -  goog.style.setPosition(overflowDiv, 0 /* left */, 400 /* top */);
    -  goog.positioning.positionAtAnchor(
    -      anchor, corner.BOTTOM_LEFT, popup, corner.BOTTOM_RIGHT, null, null,
    -      overflow.ADJUST_X | overflow.ADJUST_Y);
    -  assertObjectRoughlyEquals(
    -      new goog.math.Coordinate(
    -          testAreaOffset.x + 200 - 75, testAreaOffset.y + 400),
    -      goog.style.getPageOffset(popup),
    -      1);
    -
    -  goog.style.setPosition(overflowDiv, 400 /* left */, 400 /* top */);
    -  goog.positioning.positionAtAnchor(
    -      anchor, corner.BOTTOM_RIGHT, popup, corner.BOTTOM_LEFT, null, null,
    -      overflow.ADJUST_X | overflow.ADJUST_Y);
    -  assertObjectRoughlyEquals(
    -      new goog.math.Coordinate(
    -          testAreaOffset.x + 400, testAreaOffset.y + 400),
    -      goog.style.getPageOffset(popup),
    -      1);
    -
    -  // No overflow.
    -  goog.style.setPosition(overflowDiv, 300 - 50 /* left */, 300 /* top */);
    -  goog.positioning.positionAtAnchor(
    -      anchor, corner.TOP_LEFT, popup, corner.TOP_RIGHT, null, null,
    -      overflow.ADJUST_X | overflow.ADJUST_Y);
    -  assertObjectRoughlyEquals(
    -      new goog.math.Coordinate(
    -          testAreaOffset.x + 300 - 50, testAreaOffset.y + 300),
    -      goog.style.getPageOffset(popup),
    -      1);
    -}
    -
    -function createPopupDiv(width, height) {
    -  var popupDiv = goog.dom.createElement('div');
    -  popupDiv.style.position = 'absolute';
    -  goog.style.setSize(popupDiv, width, height);
    -  goog.style.setPosition(popupDiv, 0 /* left */, 250 /* top */);
    -  return popupDiv;
    -}
    -
    -function newCoord(x, y) {
    -  return new goog.math.Coordinate(x, y);
    -}
    -
    -function newSize(w, h) {
    -  return new goog.math.Size(w, h);
    -}
    -
    -function newBox(coord, size) {
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/positioning/positioning_test_iframe1.html b/src/database/third_party/closure-library/closure/goog/positioning/positioning_test_iframe1.html
    deleted file mode 100644
    index 6288f7a7b0c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/positioning/positioning_test_iframe1.html
    +++ /dev/null
    @@ -1,16 +0,0 @@
    -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    -            "http://www.w3.org/TR/html4/loose.dtd">
    -<!--
    --->
    -<html><body>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<p>The following IFRAME's Y-position is not 0.</p>
    -<iframe id="inner-frame" src="positioning_test_iframe2.html"
    - style="overflow:auto;width:200px;height:200px;border:0px;"></iframe>
    -<div id="popup1" style="position:absolute;width:16px;height:16px;background-color:#088;"></div>
    -</body></html>
    diff --git a/src/database/third_party/closure-library/closure/goog/positioning/positioning_test_iframe2.html b/src/database/third_party/closure-library/closure/goog/positioning/positioning_test_iframe2.html
    deleted file mode 100644
    index 5c35b29bee0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/positioning/positioning_test_iframe2.html
    +++ /dev/null
    @@ -1,13 +0,0 @@
    -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    -            "http://www.w3.org/TR/html4/loose.dtd">
    -<!--
    --->
    -<html><body style="border:0px;margin:0px;">
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<div id="anchor1" style="width:300px;height:300px;border:0px;background-color:#008;"></div>
    -</body></html>
    diff --git a/src/database/third_party/closure-library/closure/goog/positioning/positioning_test_quirk.html b/src/database/third_party/closure-library/closure/goog/positioning/positioning_test_quirk.html
    deleted file mode 100644
    index 5906053f67d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/positioning/positioning_test_quirk.html
    +++ /dev/null
    @@ -1,9 +0,0 @@
    -<!--
    --->
    -<html><body style="border:0px;"><div id="anchor1" style="width:400px;height:400px;"></body></html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    diff --git a/src/database/third_party/closure-library/closure/goog/positioning/positioning_test_standard.html b/src/database/third_party/closure-library/closure/goog/positioning/positioning_test_standard.html
    deleted file mode 100644
    index 36d7784d224..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/positioning/positioning_test_standard.html
    +++ /dev/null
    @@ -1,13 +0,0 @@
    -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    -            "http://www.w3.org/TR/html4/loose.dtd">
    -<!--
    --->
    -<html><body>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<div id="anchor1" style="width:400px;height:400px;"></div>
    -</body></html>
    diff --git a/src/database/third_party/closure-library/closure/goog/positioning/viewportclientposition.js b/src/database/third_party/closure-library/closure/goog/positioning/viewportclientposition.js
    deleted file mode 100644
    index 0f7e1a01be4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/positioning/viewportclientposition.js
    +++ /dev/null
    @@ -1,124 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Client viewport positioning class.
    - *
    - * @author robbyw@google.com (Robert Walker)
    - * @author eae@google.com (Emil A Eklund)
    - */
    -
    -goog.provide('goog.positioning.ViewportClientPosition');
    -
    -goog.require('goog.dom');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.positioning');
    -goog.require('goog.positioning.ClientPosition');
    -goog.require('goog.positioning.Overflow');
    -goog.require('goog.positioning.OverflowStatus');
    -goog.require('goog.style');
    -
    -
    -
    -/**
    - * Encapsulates a popup position where the popup is positioned relative to the
    - * window (client) coordinates, and made to stay within the viewport.
    - *
    - * @param {number|goog.math.Coordinate} arg1 Left position or coordinate.
    - * @param {number=} opt_arg2 Top position if arg1 is a number representing the
    - *     left position, ignored otherwise.
    - * @constructor
    - * @extends {goog.positioning.ClientPosition}
    - */
    -goog.positioning.ViewportClientPosition = function(arg1, opt_arg2) {
    -  goog.positioning.ClientPosition.call(this, arg1, opt_arg2);
    -};
    -goog.inherits(goog.positioning.ViewportClientPosition,
    -              goog.positioning.ClientPosition);
    -
    -
    -/**
    - * The last-resort overflow strategy, if the popup fails to fit.
    - * @type {number}
    - * @private
    - */
    -goog.positioning.ViewportClientPosition.prototype.lastResortOverflow_ = 0;
    -
    -
    -/**
    - * Set the last-resort overflow strategy, if the popup fails to fit.
    - * @param {number} overflow A bitmask of goog.positioning.Overflow strategies.
    - */
    -goog.positioning.ViewportClientPosition.prototype.setLastResortOverflow =
    -    function(overflow) {
    -  this.lastResortOverflow_ = overflow;
    -};
    -
    -
    -/**
    - * Repositions the popup according to the current state.
    - *
    - * @param {Element} element The DOM element of the popup.
    - * @param {goog.positioning.Corner} popupCorner The corner of the popup
    - *     element that that should be positioned adjacent to the anchorElement.
    - *     One of the goog.positioning.Corner constants.
    - * @param {goog.math.Box=} opt_margin A margin specified in pixels.
    - * @param {goog.math.Size=} opt_preferredSize Preferred size fo the element.
    - * @override
    - */
    -goog.positioning.ViewportClientPosition.prototype.reposition = function(
    -    element, popupCorner, opt_margin, opt_preferredSize) {
    -  var viewportElt = goog.style.getClientViewportElement(element);
    -  var viewport = goog.style.getVisibleRectForElement(viewportElt);
    -  var scrollEl = goog.dom.getDomHelper(element).getDocumentScrollElement();
    -  var clientPos = new goog.math.Coordinate(
    -      this.coordinate.x + scrollEl.scrollLeft,
    -      this.coordinate.y + scrollEl.scrollTop);
    -
    -  var failXY = goog.positioning.Overflow.FAIL_X |
    -               goog.positioning.Overflow.FAIL_Y;
    -  var corner = popupCorner;
    -
    -  // Try the requested position.
    -  var status = goog.positioning.positionAtCoordinate(clientPos, element, corner,
    -      opt_margin, viewport, failXY, opt_preferredSize);
    -  if ((status & goog.positioning.OverflowStatus.FAILED) == 0) {
    -    return;
    -  }
    -
    -  // Outside left or right edge of viewport, try try to flip it horizontally.
    -  if (status & goog.positioning.OverflowStatus.FAILED_LEFT ||
    -      status & goog.positioning.OverflowStatus.FAILED_RIGHT) {
    -    corner = goog.positioning.flipCornerHorizontal(corner);
    -  }
    -
    -  // Outside top or bottom edge of viewport, try try to flip it vertically.
    -  if (status & goog.positioning.OverflowStatus.FAILED_TOP ||
    -      status & goog.positioning.OverflowStatus.FAILED_BOTTOM) {
    -    corner = goog.positioning.flipCornerVertical(corner);
    -  }
    -
    -  // Try flipped position.
    -  status = goog.positioning.positionAtCoordinate(clientPos, element, corner,
    -      opt_margin, viewport, failXY, opt_preferredSize);
    -  if ((status & goog.positioning.OverflowStatus.FAILED) == 0) {
    -    return;
    -  }
    -
    -  // If that failed, the viewport is simply too small to contain the popup.
    -  // Revert to the original position.
    -  goog.positioning.positionAtCoordinate(
    -      clientPos, element, popupCorner, opt_margin, viewport,
    -      this.lastResortOverflow_, opt_preferredSize);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/positioning/viewportclientposition_test.html b/src/database/third_party/closure-library/closure/goog/positioning/viewportclientposition_test.html
    deleted file mode 100644
    index ec8ecc71d8c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/positioning/viewportclientposition_test.html
    +++ /dev/null
    @@ -1,31 +0,0 @@
    -<!DOCTYPE HTML>
    -<!--
    -
    -  Author: eae@google.com (Emil A Eklund)
    --->
    -<html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.positioning.ViewportClientPosition
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.positioning.ViewportClientPositionTest');
    -  </script>
    - </head>
    - <body>
    -  <!--
    -    Uses an iframe to avoid window size problems when running under Selenium.
    -  -->
    -  <iframe id="frame1" style="width: 200px; height: 200px;" src="anchoredviewportposition_test_iframe.html">
    -  </iframe>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/positioning/viewportclientposition_test.js b/src/database/third_party/closure-library/closure/goog/positioning/viewportclientposition_test.js
    deleted file mode 100644
    index 7fac4807052..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/positioning/viewportclientposition_test.js
    +++ /dev/null
    @@ -1,178 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.positioning.ViewportClientPositionTest');
    -goog.setTestOnly('goog.positioning.ViewportClientPositionTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.positioning.Corner');
    -goog.require('goog.positioning.Overflow');
    -goog.require('goog.positioning.ViewportClientPosition');
    -goog.require('goog.style');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -var viewportSize, anchor, popup, dom, frameRect;
    -var corner = goog.positioning.Corner;
    -
    -// Allow positions to be off by one in gecko as it reports scrolling
    -// offsets in steps of 2.
    -var ALLOWED_OFFSET = goog.userAgent.GECKO ? 1 : 0;
    -
    -
    -function setUp() {
    -  var frame = document.getElementById('frame1');
    -  var doc = goog.dom.getFrameContentDocument(frame);
    -
    -  dom = goog.dom.getDomHelper(doc);
    -  viewportSize = dom.getViewportSize();
    -  anchor = dom.getElement('anchor');
    -  popup = dom.getElement('popup');
    -  popup.style.overflowY = 'visible';
    -  goog.style.setSize(popup, 20, 20);
    -  frameRect = goog.style.getVisibleRectForElement(doc.body);
    -}
    -
    -
    -function testPositionAtCoordinateTopLeft() {
    -  var pos = new goog.positioning.ViewportClientPosition(100, 100);
    -  pos.reposition(popup, corner.TOP_LEFT);
    -
    -  var offset = goog.style.getPageOffset(popup);
    -  assertEquals('Left edge of popup should be at specified x coordinate.',
    -               100,
    -               offset.x);
    -  assertEquals('Top edge of popup should be at specified y coordinate.',
    -               100,
    -               offset.y);
    -}
    -
    -
    -function testPositionAtCoordinateBottomRight() {
    -  var pos = new goog.positioning.ViewportClientPosition(100, 100);
    -  pos.reposition(popup, corner.BOTTOM_RIGHT);
    -
    -  var bounds = goog.style.getBounds(popup);
    -  assertEquals('Right edge of popup should be at specified x coordinate.',
    -               100,
    -               bounds.left + bounds.width);
    -  assertEquals('Bottom edge of popup should be at specified x coordinate.',
    -               100,
    -               bounds.top + bounds.height);
    -}
    -
    -
    -function testPositionAtCoordinateTopLeftWithScroll() {
    -  dom.getDocument().body.style.paddingTop = '300px';
    -  dom.getDocument().body.style.height = '3000px';
    -  dom.getDocumentScrollElement().scrollTop = 50;
    -  dom.getDocument().body.scrollTop = 50;
    -
    -  var pos = new goog.positioning.ViewportClientPosition(0, 0);
    -  pos.reposition(popup, corner.TOP_LEFT);
    -
    -  var offset = goog.style.getPageOffset(popup);
    -  assertEquals('Left edge of popup should be at specified x coordinate.',
    -               0,
    -               offset.x);
    -  assertTrue('Top edge of popup should be at specified y coordinate ' +
    -             'adjusted for scroll.',
    -             Math.abs(offset.y - 50) <= ALLOWED_OFFSET);
    -
    -  dom.getDocument().body.style.paddingLeft = '1000px';
    -  dom.getDocumentScrollElement().scrollLeft = 500;
    -
    -  pos.reposition(popup, corner.TOP_LEFT);
    -  offset = goog.style.getPageOffset(popup);
    -  assertTrue('Left edge of popup should be at specified x coordinate ' +
    -             'adjusted for scroll.',
    -             Math.abs(offset.x - 500) <= ALLOWED_OFFSET);
    -
    -  dom.getDocumentScrollElement().scrollLeft = 0;
    -  dom.getDocumentScrollElement().scrollTop = 0;
    -  dom.getDocument().body.style.paddingLeft = '';
    -  dom.getDocument().body.style.paddingTop = '';
    -
    -  pos.reposition(popup, corner.TOP_LEFT);
    -  offset = goog.style.getPageOffset(popup);
    -  assertEquals('Left edge of popup should be at specified x coordinate.',
    -               0,
    -               offset.x);
    -  assertEquals('Top edge of popup should be at specified y coordinate.',
    -               0,
    -               offset.y);
    -}
    -
    -
    -function testOverflowRightFlipHor() {
    -  var pos = new goog.positioning.ViewportClientPosition(frameRect.right,
    -                                                        100);
    -  pos.reposition(popup, corner.TOP_LEFT);
    -
    -  var offset = goog.style.getPageOffset(popup);
    -  assertEquals('Left edge of popup should have been adjusted so that it ' +
    -      'fits inside the viewport.',
    -               frameRect.right - popup.offsetWidth,
    -               offset.x);
    -  assertEquals('Top edge of popup should be at specified y coordinate.',
    -               100,
    -               offset.y);
    -}
    -
    -
    -function testOverflowTopFlipVer() {
    -  var pos = new goog.positioning.ViewportClientPosition(100, 0);
    -  pos.reposition(popup, corner.TOP_RIGHT);
    -
    -  var offset = goog.style.getPageOffset(popup);
    -  assertEquals('Left edge of popup should be at specified x coordinate.',
    -               80,
    -               offset.x);
    -  assertEquals('Top edge of popup should have been adjusted so that it ' +
    -      'fits inside the viewport.',
    -               0,
    -               offset.y);
    -}
    -
    -
    -function testOverflowBottomRightFlipBoth() {
    -  var pos = new goog.positioning.ViewportClientPosition(frameRect.right,
    -                                                        frameRect.bottom);
    -  pos.reposition(popup, corner.TOP_LEFT);
    -
    -  var offset = goog.style.getPageOffset(popup);
    -  assertEquals('Left edge of popup should have been adjusted so that it ' +
    -      'fits inside the viewport.',
    -               frameRect.right - popup.offsetWidth,
    -               offset.x);
    -  assertEquals('Top edge of popup should have been adjusted so that it ' +
    -      'fits inside the viewport.',
    -               frameRect.bottom - popup.offsetHeight,
    -               offset.y);
    -}
    -
    -
    -function testLastRespotOverflow() {
    -  var large = 2000;
    -  goog.style.setSize(popup, 20, large);
    -  popup.style.overflowY = 'auto';
    -
    -  var pos = new goog.positioning.ViewportClientPosition(0, 0);
    -  pos.reposition(popup, corner.TOP_LEFT);
    -
    -  assertEquals(large, popup.offsetHeight);
    -  pos.setLastResortOverflow(goog.positioning.Overflow.RESIZE_HEIGHT);
    -  pos.reposition(popup, corner.TOP_LEFT);
    -  assertNotEquals(large, popup.offsetHeight);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/positioning/viewportposition.js b/src/database/third_party/closure-library/closure/goog/positioning/viewportposition.js
    deleted file mode 100644
    index 3b1dc07e5d7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/positioning/viewportposition.js
    +++ /dev/null
    @@ -1,66 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Client positioning class.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - */
    -
    -goog.provide('goog.positioning.ViewportPosition');
    -
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.positioning');
    -goog.require('goog.positioning.AbstractPosition');
    -goog.require('goog.positioning.Corner');
    -goog.require('goog.style');
    -
    -
    -
    -/**
    - * Encapsulates a popup position where the popup is positioned according to
    - * coordinates relative to the  element's viewport (page). This calculates the
    - * correct position to use even if the element is relatively positioned to some
    - * other element.
    - *
    - * @param {number|goog.math.Coordinate} arg1 Left position or coordinate.
    - * @param {number=} opt_arg2 Top position.
    - * @constructor
    - * @extends {goog.positioning.AbstractPosition}
    - */
    -goog.positioning.ViewportPosition = function(arg1, opt_arg2) {
    -  this.coordinate = arg1 instanceof goog.math.Coordinate ? arg1 :
    -      new goog.math.Coordinate(/** @type {number} */ (arg1), opt_arg2);
    -};
    -goog.inherits(goog.positioning.ViewportPosition,
    -              goog.positioning.AbstractPosition);
    -
    -
    -/**
    - * Repositions the popup according to the current state
    - *
    - * @param {Element} element The DOM element of the popup.
    - * @param {goog.positioning.Corner} popupCorner The corner of the popup
    - *     element that that should be positioned adjacent to the anchorElement.
    - * @param {goog.math.Box=} opt_margin A margin specified in pixels.
    - * @param {goog.math.Size=} opt_preferredSize Preferred size of the element.
    - * @override
    - */
    -goog.positioning.ViewportPosition.prototype.reposition = function(
    -    element, popupCorner, opt_margin, opt_preferredSize) {
    -  goog.positioning.positionAtAnchor(
    -      goog.style.getClientViewportElement(element),
    -      goog.positioning.Corner.TOP_LEFT, element, popupCorner,
    -      this.coordinate, opt_margin, null, opt_preferredSize);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/promise/promise.js b/src/database/third_party/closure-library/closure/goog/promise/promise.js
    deleted file mode 100644
    index 50915755c53..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/promise/promise.js
    +++ /dev/null
    @@ -1,1025 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.Promise');
    -
    -goog.require('goog.Thenable');
    -goog.require('goog.asserts');
    -goog.require('goog.async.run');
    -goog.require('goog.async.throwException');
    -goog.require('goog.debug.Error');
    -goog.require('goog.promise.Resolver');
    -
    -
    -
    -/**
    - * Promises provide a result that may be resolved asynchronously. A Promise may
    - * be resolved by being fulfilled or rejected with a value, which will be known
    - * as the fulfillment value or the rejection reason. Whether fulfilled or
    - * rejected, the Promise result is immutable once it is set.
    - *
    - * Promises may represent results of any type, including undefined. Rejection
    - * reasons are typically Errors, but may also be of any type. Closure Promises
    - * allow for optional type annotations that enforce that fulfillment values are
    - * of the appropriate types at compile time.
    - *
    - * The result of a Promise is accessible by calling {@code then} and registering
    - * {@code onFulfilled} and {@code onRejected} callbacks. Once the Promise
    - * resolves, the relevant callbacks are invoked with the fulfillment value or
    - * rejection reason as argument. Callbacks are always invoked in the order they
    - * were registered, even when additional {@code then} calls are made from inside
    - * another callback. A callback is always run asynchronously sometime after the
    - * scope containing the registering {@code then} invocation has returned.
    - *
    - * If a Promise is resolved with another Promise, the first Promise will block
    - * until the second is resolved, and then assumes the same result as the second
    - * Promise. This allows Promises to depend on the results of other Promises,
    - * linking together multiple asynchronous operations.
    - *
    - * This implementation is compatible with the Promises/A+ specification and
    - * passes that specification's conformance test suite. A Closure Promise may be
    - * resolved with a Promise instance (or sufficiently compatible Promise-like
    - * object) created by other Promise implementations. From the specification,
    - * Promise-like objects are known as "Thenables".
    - *
    - * @see http://promisesaplus.com/
    - *
    - * @param {function(
    - *             this:RESOLVER_CONTEXT,
    - *             function((TYPE|IThenable<TYPE>|Thenable)=),
    - *             function(*)): void} resolver
    - *     Initialization function that is invoked immediately with {@code resolve}
    - *     and {@code reject} functions as arguments. The Promise is resolved or
    - *     rejected with the first argument passed to either function.
    - * @param {RESOLVER_CONTEXT=} opt_context An optional context for executing the
    - *     resolver function. If unspecified, the resolver function will be executed
    - *     in the default scope.
    - * @constructor
    - * @struct
    - * @final
    - * @implements {goog.Thenable<TYPE>}
    - * @template TYPE,RESOLVER_CONTEXT
    - */
    -goog.Promise = function(resolver, opt_context) {
    -  /**
    -   * The internal state of this Promise. Either PENDING, FULFILLED, REJECTED, or
    -   * BLOCKED.
    -   * @private {goog.Promise.State_}
    -   */
    -  this.state_ = goog.Promise.State_.PENDING;
    -
    -  /**
    -   * The resolved result of the Promise. Immutable once set with either a
    -   * fulfillment value or rejection reason.
    -   * @private {*}
    -   */
    -  this.result_ = undefined;
    -
    -  /**
    -   * For Promises created by calling {@code then()}, the originating parent.
    -   * @private {goog.Promise}
    -   */
    -  this.parent_ = null;
    -
    -  /**
    -   * The list of {@code onFulfilled} and {@code onRejected} callbacks added to
    -   * this Promise by calls to {@code then()}.
    -   * @private {Array<goog.Promise.CallbackEntry_>}
    -   */
    -  this.callbackEntries_ = null;
    -
    -  /**
    -   * Whether the Promise is in the queue of Promises to execute.
    -   * @private {boolean}
    -   */
    -  this.executing_ = false;
    -
    -  if (goog.Promise.UNHANDLED_REJECTION_DELAY > 0) {
    -    /**
    -     * A timeout ID used when the {@code UNHANDLED_REJECTION_DELAY} is greater
    -     * than 0 milliseconds. The ID is set when the Promise is rejected, and
    -     * cleared only if an {@code onRejected} callback is invoked for the
    -     * Promise (or one of its descendants) before the delay is exceeded.
    -     *
    -     * If the rejection is not handled before the timeout completes, the
    -     * rejection reason is passed to the unhandled rejection handler.
    -     * @private {number}
    -     */
    -    this.unhandledRejectionId_ = 0;
    -  } else if (goog.Promise.UNHANDLED_REJECTION_DELAY == 0) {
    -    /**
    -     * When the {@code UNHANDLED_REJECTION_DELAY} is set to 0 milliseconds, a
    -     * boolean that is set if the Promise is rejected, and reset to false if an
    -     * {@code onRejected} callback is invoked for the Promise (or one of its
    -     * descendants). If the rejection is not handled before the next timestep,
    -     * the rejection reason is passed to the unhandled rejection handler.
    -     * @private {boolean}
    -     */
    -    this.hadUnhandledRejection_ = false;
    -  }
    -
    -  if (goog.Promise.LONG_STACK_TRACES) {
    -    /**
    -     * A list of stack trace frames pointing to the locations where this Promise
    -     * was created or had callbacks added to it. Saved to add additional context
    -     * to stack traces when an exception is thrown.
    -     * @private {!Array<string>}
    -     */
    -    this.stack_ = [];
    -    this.addStackTrace_(new Error('created'));
    -
    -    /**
    -     * Index of the most recently executed stack frame entry.
    -     * @private {number}
    -     */
    -    this.currentStep_ = 0;
    -  }
    -
    -  if (resolver == goog.Promise.RESOLVE_FAST_PATH_) {
    -    // If the special sentinel resolver value is passed (from
    -    // goog.Promise.resolve) we short cut to immediately resolve the promise
    -    // using the value passed as opt_context. Don't try this at home.
    -    this.resolve_(goog.Promise.State_.FULFILLED, opt_context);
    -  } else {
    -    try {
    -      var self = this;
    -      resolver.call(
    -          opt_context,
    -          function(value) {
    -            self.resolve_(goog.Promise.State_.FULFILLED, value);
    -          },
    -          function(reason) {
    -            if (goog.DEBUG &&
    -                !(reason instanceof goog.Promise.CancellationError)) {
    -              try {
    -                // Promise was rejected. Step up one call frame to see why.
    -                if (reason instanceof Error) {
    -                  throw reason;
    -                } else {
    -                  throw new Error('Promise rejected.');
    -                }
    -              } catch (e) {
    -                // Only thrown so browser dev tools can catch rejections of
    -                // promises when the option to break on caught exceptions is
    -                // activated.
    -              }
    -            }
    -            self.resolve_(goog.Promise.State_.REJECTED, reason);
    -          });
    -    } catch (e) {
    -      this.resolve_(goog.Promise.State_.REJECTED, e);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * @define {boolean} Whether traces of {@code then} calls should be included in
    - * exceptions thrown
    - */
    -goog.define('goog.Promise.LONG_STACK_TRACES', false);
    -
    -
    -/**
    - * @define {number} The delay in milliseconds before a rejected Promise's reason
    - * is passed to the rejection handler. By default, the rejection handler
    - * rethrows the rejection reason so that it appears in the developer console or
    - * {@code window.onerror} handler.
    - *
    - * Rejections are rethrown as quickly as possible by default. A negative value
    - * disables rejection handling entirely.
    - */
    -goog.define('goog.Promise.UNHANDLED_REJECTION_DELAY', 0);
    -
    -
    -/**
    - * The possible internal states for a Promise. These states are not directly
    - * observable to external callers.
    - * @enum {number}
    - * @private
    - */
    -goog.Promise.State_ = {
    -  /** The Promise is waiting for resolution. */
    -  PENDING: 0,
    -
    -  /** The Promise is blocked waiting for the result of another Thenable. */
    -  BLOCKED: 1,
    -
    -  /** The Promise has been resolved with a fulfillment value. */
    -  FULFILLED: 2,
    -
    -  /** The Promise has been resolved with a rejection reason. */
    -  REJECTED: 3
    -};
    -
    -
    -/**
    - * Typedef for entries in the callback chain. Each call to {@code then},
    - * {@code thenCatch}, or {@code thenAlways} creates an entry containing the
    - * functions that may be invoked once the Promise is resolved.
    - *
    - * @typedef {{
    - *   child: goog.Promise,
    - *   onFulfilled: function(*),
    - *   onRejected: function(*)
    - * }}
    - * @private
    - */
    -goog.Promise.CallbackEntry_;
    -
    -
    -/**
    - * If this passed as the first argument to the {@link goog.Promise} constructor
    - * the the opt_context is (against its primary use) used to immediately resolve
    - * the promise. This is used from  {@link goog.Promise.resolve} as an
    - * optimization to avoid allocating 3 closures that are never really needed.
    - * @private @const {!Function}
    - */
    -goog.Promise.RESOLVE_FAST_PATH_ = function() {};
    -
    -
    -/**
    - * @param {(TYPE|goog.Thenable<TYPE>|Thenable)=} opt_value
    - * @return {!goog.Promise<TYPE>} A new Promise that is immediately resolved
    - *     with the given value.
    - * @template TYPE
    - */
    -goog.Promise.resolve = function(opt_value) {
    -  // Passes the value as the context, which is a special fast pass when
    -  // goog.Promise.RESOLVE_FAST_PATH_ is passed as the first argument.
    -  return new goog.Promise(goog.Promise.RESOLVE_FAST_PATH_, opt_value);
    -};
    -
    -
    -/**
    - * @param {*=} opt_reason
    - * @return {!goog.Promise} A new Promise that is immediately rejected with the
    - *     given reason.
    - */
    -goog.Promise.reject = function(opt_reason) {
    -  return new goog.Promise(function(resolve, reject) {
    -    reject(opt_reason);
    -  });
    -};
    -
    -
    -/**
    - * @param {!Array<!(goog.Thenable<TYPE>|Thenable)>} promises
    - * @return {!goog.Promise<TYPE>} A Promise that receives the result of the
    - *     first Promise (or Promise-like) input to complete.
    - * @template TYPE
    - */
    -goog.Promise.race = function(promises) {
    -  return new goog.Promise(function(resolve, reject) {
    -    if (!promises.length) {
    -      resolve(undefined);
    -    }
    -    for (var i = 0, promise; promise = promises[i]; i++) {
    -      promise.then(resolve, reject);
    -    }
    -  });
    -};
    -
    -
    -/**
    - * @param {!Array<!(goog.Thenable<TYPE>|Thenable)>} promises
    - * @return {!goog.Promise<!Array<TYPE>>} A Promise that receives a list of
    - *     every fulfilled value once every input Promise (or Promise-like) is
    - *     successfully fulfilled, or is rejected by the first rejection result.
    - * @template TYPE
    - */
    -goog.Promise.all = function(promises) {
    -  return new goog.Promise(function(resolve, reject) {
    -    var toFulfill = promises.length;
    -    var values = [];
    -
    -    if (!toFulfill) {
    -      resolve(values);
    -      return;
    -    }
    -
    -    var onFulfill = function(index, value) {
    -      toFulfill--;
    -      values[index] = value;
    -      if (toFulfill == 0) {
    -        resolve(values);
    -      }
    -    };
    -
    -    var onReject = function(reason) {
    -      reject(reason);
    -    };
    -
    -    for (var i = 0, promise; promise = promises[i]; i++) {
    -      promise.then(goog.partial(onFulfill, i), onReject);
    -    }
    -  });
    -};
    -
    -
    -/**
    - * @param {!Array<!(goog.Thenable<TYPE>|Thenable)>} promises
    - * @return {!goog.Promise<TYPE>} A Promise that receives the value of the first
    - *     input to be fulfilled, or is rejected with a list of every rejection
    - *     reason if all inputs are rejected.
    - * @template TYPE
    - */
    -goog.Promise.firstFulfilled = function(promises) {
    -  return new goog.Promise(function(resolve, reject) {
    -    var toReject = promises.length;
    -    var reasons = [];
    -
    -    if (!toReject) {
    -      resolve(undefined);
    -      return;
    -    }
    -
    -    var onFulfill = function(value) {
    -      resolve(value);
    -    };
    -
    -    var onReject = function(index, reason) {
    -      toReject--;
    -      reasons[index] = reason;
    -      if (toReject == 0) {
    -        reject(reasons);
    -      }
    -    };
    -
    -    for (var i = 0, promise; promise = promises[i]; i++) {
    -      promise.then(onFulfill, goog.partial(onReject, i));
    -    }
    -  });
    -};
    -
    -
    -/**
    - * @return {!goog.promise.Resolver<TYPE>} Resolver wrapping the promise and its
    - *     resolve / reject functions. Resolving or rejecting the resolver
    - *     resolves or rejects the promise.
    - * @template TYPE
    - */
    -goog.Promise.withResolver = function() {
    -  var resolve, reject;
    -  var promise = new goog.Promise(function(rs, rj) {
    -    resolve = rs;
    -    reject = rj;
    -  });
    -  return new goog.Promise.Resolver_(promise, resolve, reject);
    -};
    -
    -
    -/**
    - * Adds callbacks that will operate on the result of the Promise, returning a
    - * new child Promise.
    - *
    - * If the Promise is fulfilled, the {@code onFulfilled} callback will be invoked
    - * with the fulfillment value as argument, and the child Promise will be
    - * fulfilled with the return value of the callback. If the callback throws an
    - * exception, the child Promise will be rejected with the thrown value instead.
    - *
    - * If the Promise is rejected, the {@code onRejected} callback will be invoked
    - * with the rejection reason as argument, and the child Promise will be resolved
    - * with the return value or rejected with the thrown value of the callback.
    - *
    - * @override
    - */
    -goog.Promise.prototype.then = function(
    -    opt_onFulfilled, opt_onRejected, opt_context) {
    -
    -  if (opt_onFulfilled != null) {
    -    goog.asserts.assertFunction(opt_onFulfilled,
    -        'opt_onFulfilled should be a function.');
    -  }
    -  if (opt_onRejected != null) {
    -    goog.asserts.assertFunction(opt_onRejected,
    -        'opt_onRejected should be a function. Did you pass opt_context ' +
    -        'as the second argument instead of the third?');
    -  }
    -
    -  if (goog.Promise.LONG_STACK_TRACES) {
    -    this.addStackTrace_(new Error('then'));
    -  }
    -
    -  return this.addChildPromise_(
    -      goog.isFunction(opt_onFulfilled) ? opt_onFulfilled : null,
    -      goog.isFunction(opt_onRejected) ? opt_onRejected : null,
    -      opt_context);
    -};
    -goog.Thenable.addImplementation(goog.Promise);
    -
    -
    -/**
    - * Adds a callback that will be invoked whether the Promise is fulfilled or
    - * rejected. The callback receives no argument, and no new child Promise is
    - * created. This is useful for ensuring that cleanup takes place after certain
    - * asynchronous operations. Callbacks added with {@code thenAlways} will be
    - * executed in the same order with other calls to {@code then},
    - * {@code thenAlways}, or {@code thenCatch}.
    - *
    - * Since it does not produce a new child Promise, cancellation propagation is
    - * not prevented by adding callbacks with {@code thenAlways}. A Promise that has
    - * a cleanup handler added with {@code thenAlways} will be canceled if all of
    - * its children created by {@code then} (or {@code thenCatch}) are canceled.
    - * Additionally, since any rejections are not passed to the callback, it does
    - * not stop the unhandled rejection handler from running.
    - *
    - * @param {function(this:THIS): void} onResolved A function that will be invoked
    - *     when the Promise is resolved.
    - * @param {THIS=} opt_context An optional context object that will be the
    - *     execution context for the callbacks. By default, functions are executed
    - *     in the global scope.
    - * @return {!goog.Promise<TYPE>} This Promise, for chaining additional calls.
    - * @template THIS
    - */
    -goog.Promise.prototype.thenAlways = function(onResolved, opt_context) {
    -  if (goog.Promise.LONG_STACK_TRACES) {
    -    this.addStackTrace_(new Error('thenAlways'));
    -  }
    -
    -  var callback = function() {
    -    try {
    -      // Ensure that no arguments are passed to onResolved.
    -      onResolved.call(opt_context);
    -    } catch (err) {
    -      goog.Promise.handleRejection_.call(null, err);
    -    }
    -  };
    -
    -  this.addCallbackEntry_({
    -    child: null,
    -    onRejected: callback,
    -    onFulfilled: callback
    -  });
    -  return this;
    -};
    -
    -
    -/**
    - * Adds a callback that will be invoked only if the Promise is rejected. This
    - * is equivalent to {@code then(null, onRejected)}.
    - *
    - * @param {!function(this:THIS, *): *} onRejected A function that will be
    - *     invoked with the rejection reason if the Promise is rejected.
    - * @param {THIS=} opt_context An optional context object that will be the
    - *     execution context for the callbacks. By default, functions are executed
    - *     in the global scope.
    - * @return {!goog.Promise} A new Promise that will receive the result of the
    - *     callback.
    - * @template THIS
    - */
    -goog.Promise.prototype.thenCatch = function(onRejected, opt_context) {
    -  if (goog.Promise.LONG_STACK_TRACES) {
    -    this.addStackTrace_(new Error('thenCatch'));
    -  }
    -  return this.addChildPromise_(null, onRejected, opt_context);
    -};
    -
    -
    -/**
    - * Cancels the Promise if it is still pending by rejecting it with a cancel
    - * Error. No action is performed if the Promise is already resolved.
    - *
    - * All child Promises of the canceled Promise will be rejected with the same
    - * cancel error, as with normal Promise rejection. If the Promise to be canceled
    - * is the only child of a pending Promise, the parent Promise will also be
    - * canceled. Cancellation may propagate upward through multiple generations.
    - *
    - * @param {string=} opt_message An optional debugging message for describing the
    - *     cancellation reason.
    - */
    -goog.Promise.prototype.cancel = function(opt_message) {
    -  if (this.state_ == goog.Promise.State_.PENDING) {
    -    goog.async.run(function() {
    -      var err = new goog.Promise.CancellationError(opt_message);
    -      this.cancelInternal_(err);
    -    }, this);
    -  }
    -};
    -
    -
    -/**
    - * Cancels this Promise with the given error.
    - *
    - * @param {!Error} err The cancellation error.
    - * @private
    - */
    -goog.Promise.prototype.cancelInternal_ = function(err) {
    -  if (this.state_ == goog.Promise.State_.PENDING) {
    -    if (this.parent_) {
    -      // Cancel the Promise and remove it from the parent's child list.
    -      this.parent_.cancelChild_(this, err);
    -      this.parent_ = null;
    -    } else {
    -      this.resolve_(goog.Promise.State_.REJECTED, err);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Cancels a child Promise from the list of callback entries. If the Promise has
    - * not already been resolved, reject it with a cancel error. If there are no
    - * other children in the list of callback entries, propagate the cancellation
    - * by canceling this Promise as well.
    - *
    - * @param {!goog.Promise} childPromise The Promise to cancel.
    - * @param {!Error} err The cancel error to use for rejecting the Promise.
    - * @private
    - */
    -goog.Promise.prototype.cancelChild_ = function(childPromise, err) {
    -  if (!this.callbackEntries_) {
    -    return;
    -  }
    -  var childCount = 0;
    -  var childIndex = -1;
    -
    -  // Find the callback entry for the childPromise, and count whether there are
    -  // additional child Promises.
    -  for (var i = 0, entry; entry = this.callbackEntries_[i]; i++) {
    -    var child = entry.child;
    -    if (child) {
    -      childCount++;
    -      if (child == childPromise) {
    -        childIndex = i;
    -      }
    -      if (childIndex >= 0 && childCount > 1) {
    -        break;
    -      }
    -    }
    -  }
    -
    -  // If the child Promise was the only child, cancel this Promise as well.
    -  // Otherwise, reject only the child Promise with the cancel error.
    -  if (childIndex >= 0) {
    -    if (this.state_ == goog.Promise.State_.PENDING && childCount == 1) {
    -      this.cancelInternal_(err);
    -    } else {
    -      var callbackEntry = this.callbackEntries_.splice(childIndex, 1)[0];
    -      this.executeCallback_(
    -          callbackEntry, goog.Promise.State_.REJECTED, err);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Adds a callback entry to the current Promise, and schedules callback
    - * execution if the Promise has already been resolved.
    - *
    - * @param {goog.Promise.CallbackEntry_} callbackEntry Record containing
    - *     {@code onFulfilled} and {@code onRejected} callbacks to execute after
    - *     the Promise is resolved.
    - * @private
    - */
    -goog.Promise.prototype.addCallbackEntry_ = function(callbackEntry) {
    -  if ((!this.callbackEntries_ || !this.callbackEntries_.length) &&
    -      (this.state_ == goog.Promise.State_.FULFILLED ||
    -       this.state_ == goog.Promise.State_.REJECTED)) {
    -    this.scheduleCallbacks_();
    -  }
    -  if (!this.callbackEntries_) {
    -    this.callbackEntries_ = [];
    -  }
    -  this.callbackEntries_.push(callbackEntry);
    -};
    -
    -
    -/**
    - * Creates a child Promise and adds it to the callback entry list. The result of
    - * the child Promise is determined by the state of the parent Promise and the
    - * result of the {@code onFulfilled} or {@code onRejected} callbacks as
    - * specified in the Promise resolution procedure.
    - *
    - * @see http://promisesaplus.com/#the__method
    - *
    - * @param {?function(this:THIS, TYPE):
    - *          (RESULT|goog.Promise<RESULT>|Thenable)} onFulfilled A callback that
    - *     will be invoked if the Promise is fullfilled, or null.
    - * @param {?function(this:THIS, *): *} onRejected A callback that will be
    - *     invoked if the Promise is rejected, or null.
    - * @param {THIS=} opt_context An optional execution context for the callbacks.
    - *     in the default calling context.
    - * @return {!goog.Promise} The child Promise.
    - * @template RESULT,THIS
    - * @private
    - */
    -goog.Promise.prototype.addChildPromise_ = function(
    -    onFulfilled, onRejected, opt_context) {
    -
    -  var callbackEntry = {
    -    child: null,
    -    onFulfilled: null,
    -    onRejected: null
    -  };
    -
    -  callbackEntry.child = new goog.Promise(function(resolve, reject) {
    -    // Invoke onFulfilled, or resolve with the parent's value if absent.
    -    callbackEntry.onFulfilled = onFulfilled ? function(value) {
    -      try {
    -        var result = onFulfilled.call(opt_context, value);
    -        resolve(result);
    -      } catch (err) {
    -        reject(err);
    -      }
    -    } : resolve;
    -
    -    // Invoke onRejected, or reject with the parent's reason if absent.
    -    callbackEntry.onRejected = onRejected ? function(reason) {
    -      try {
    -        var result = onRejected.call(opt_context, reason);
    -        if (!goog.isDef(result) &&
    -            reason instanceof goog.Promise.CancellationError) {
    -          // Propagate cancellation to children if no other result is returned.
    -          reject(reason);
    -        } else {
    -          resolve(result);
    -        }
    -      } catch (err) {
    -        reject(err);
    -      }
    -    } : reject;
    -  });
    -
    -  callbackEntry.child.parent_ = this;
    -  this.addCallbackEntry_(
    -      /** @type {goog.Promise.CallbackEntry_} */ (callbackEntry));
    -  return callbackEntry.child;
    -};
    -
    -
    -/**
    - * Unblocks the Promise and fulfills it with the given value.
    - *
    - * @param {TYPE} value
    - * @private
    - */
    -goog.Promise.prototype.unblockAndFulfill_ = function(value) {
    -  goog.asserts.assert(this.state_ == goog.Promise.State_.BLOCKED);
    -  this.state_ = goog.Promise.State_.PENDING;
    -  this.resolve_(goog.Promise.State_.FULFILLED, value);
    -};
    -
    -
    -/**
    - * Unblocks the Promise and rejects it with the given rejection reason.
    - *
    - * @param {*} reason
    - * @private
    - */
    -goog.Promise.prototype.unblockAndReject_ = function(reason) {
    -  goog.asserts.assert(this.state_ == goog.Promise.State_.BLOCKED);
    -  this.state_ = goog.Promise.State_.PENDING;
    -  this.resolve_(goog.Promise.State_.REJECTED, reason);
    -};
    -
    -
    -/**
    - * Attempts to resolve a Promise with a given resolution state and value. This
    - * is a no-op if the given Promise has already been resolved.
    - *
    - * If the given result is a Thenable (such as another Promise), the Promise will
    - * be resolved with the same state and result as the Thenable once it is itself
    - * resolved.
    - *
    - * If the given result is not a Thenable, the Promise will be fulfilled or
    - * rejected with that result based on the given state.
    - *
    - * @see http://promisesaplus.com/#the_promise_resolution_procedure
    - *
    - * @param {goog.Promise.State_} state
    - * @param {*} x The result to apply to the Promise.
    - * @private
    - */
    -goog.Promise.prototype.resolve_ = function(state, x) {
    -  if (this.state_ != goog.Promise.State_.PENDING) {
    -    return;
    -  }
    -
    -  if (this == x) {
    -    state = goog.Promise.State_.REJECTED;
    -    x = new TypeError('Promise cannot resolve to itself');
    -
    -  } else if (goog.Thenable.isImplementedBy(x)) {
    -    x = /** @type {!goog.Thenable} */ (x);
    -    this.state_ = goog.Promise.State_.BLOCKED;
    -    x.then(this.unblockAndFulfill_, this.unblockAndReject_, this);
    -    return;
    -
    -  } else if (goog.isObject(x)) {
    -    try {
    -      var then = x['then'];
    -      if (goog.isFunction(then)) {
    -        this.tryThen_(x, then);
    -        return;
    -      }
    -    } catch (e) {
    -      state = goog.Promise.State_.REJECTED;
    -      x = e;
    -    }
    -  }
    -
    -  this.result_ = x;
    -  this.state_ = state;
    -  // Since we can no longer be cancelled, remove link to parent, so that the
    -  // child promise does not keep the parent promise alive.
    -  this.parent_ = null;
    -  this.scheduleCallbacks_();
    -
    -  if (state == goog.Promise.State_.REJECTED &&
    -      !(x instanceof goog.Promise.CancellationError)) {
    -    goog.Promise.addUnhandledRejection_(this, x);
    -  }
    -};
    -
    -
    -/**
    - * Attempts to call the {@code then} method on an object in the hopes that it is
    - * a Promise-compatible instance. This allows interoperation between different
    - * Promise implementations, however a non-compliant object may cause a Promise
    - * to hang indefinitely. If the {@code then} method throws an exception, the
    - * dependent Promise will be rejected with the thrown value.
    - *
    - * @see http://promisesaplus.com/#point-70
    - *
    - * @param {Thenable} thenable An object with a {@code then} method that may be
    - *     compatible with the Promise/A+ specification.
    - * @param {!Function} then The {@code then} method of the Thenable object.
    - * @private
    - */
    -goog.Promise.prototype.tryThen_ = function(thenable, then) {
    -  this.state_ = goog.Promise.State_.BLOCKED;
    -  var promise = this;
    -  var called = false;
    -
    -  var resolve = function(value) {
    -    if (!called) {
    -      called = true;
    -      promise.unblockAndFulfill_(value);
    -    }
    -  };
    -
    -  var reject = function(reason) {
    -    if (!called) {
    -      called = true;
    -      promise.unblockAndReject_(reason);
    -    }
    -  };
    -
    -  try {
    -    then.call(thenable, resolve, reject);
    -  } catch (e) {
    -    reject(e);
    -  }
    -};
    -
    -
    -/**
    - * Executes the pending callbacks of a resolved Promise after a timeout.
    - *
    - * Section 2.2.4 of the Promises/A+ specification requires that Promise
    - * callbacks must only be invoked from a call stack that only contains Promise
    - * implementation code, which we accomplish by invoking callback execution after
    - * a timeout. If {@code startExecution_} is called multiple times for the same
    - * Promise, the callback chain will be evaluated only once. Additional callbacks
    - * may be added during the evaluation phase, and will be executed in the same
    - * event loop.
    - *
    - * All Promises added to the waiting list during the same browser event loop
    - * will be executed in one batch to avoid using a separate timeout per Promise.
    - *
    - * @private
    - */
    -goog.Promise.prototype.scheduleCallbacks_ = function() {
    -  if (!this.executing_) {
    -    this.executing_ = true;
    -    goog.async.run(this.executeCallbacks_, this);
    -  }
    -};
    -
    -
    -/**
    - * Executes all pending callbacks for this Promise.
    - *
    - * @private
    - */
    -goog.Promise.prototype.executeCallbacks_ = function() {
    -  while (this.callbackEntries_ && this.callbackEntries_.length) {
    -    var entries = this.callbackEntries_;
    -    this.callbackEntries_ = null;
    -
    -    for (var i = 0; i < entries.length; i++) {
    -      if (goog.Promise.LONG_STACK_TRACES) {
    -        this.currentStep_++;
    -      }
    -      this.executeCallback_(entries[i], this.state_, this.result_);
    -    }
    -  }
    -  this.executing_ = false;
    -};
    -
    -
    -/**
    - * Executes a pending callback for this Promise. Invokes an {@code onFulfilled}
    - * or {@code onRejected} callback based on the resolved state of the Promise.
    - *
    - * @param {!goog.Promise.CallbackEntry_} callbackEntry An entry containing the
    - *     onFulfilled and/or onRejected callbacks for this step.
    - * @param {goog.Promise.State_} state The resolution status of the Promise,
    - *     either FULFILLED or REJECTED.
    - * @param {*} result The resolved result of the Promise.
    - * @private
    - */
    -goog.Promise.prototype.executeCallback_ = function(
    -    callbackEntry, state, result) {
    -  if (state == goog.Promise.State_.FULFILLED) {
    -    callbackEntry.onFulfilled(result);
    -  } else {
    -    if (callbackEntry.child) {
    -      this.removeUnhandledRejection_();
    -    }
    -    callbackEntry.onRejected(result);
    -  }
    -};
    -
    -
    -/**
    - * Records a stack trace entry for functions that call {@code then} or the
    - * Promise constructor. May be disabled by unsetting {@code LONG_STACK_TRACES}.
    - *
    - * @param {!Error} err An Error object created by the calling function for
    - *     providing a stack trace.
    - * @private
    - */
    -goog.Promise.prototype.addStackTrace_ = function(err) {
    -  if (goog.Promise.LONG_STACK_TRACES && goog.isString(err.stack)) {
    -    // Extract the third line of the stack trace, which is the entry for the
    -    // user function that called into Promise code.
    -    var trace = err.stack.split('\n', 4)[3];
    -    var message = err.message;
    -
    -    // Pad the message to align the traces.
    -    message += Array(11 - message.length).join(' ');
    -    this.stack_.push(message + trace);
    -  }
    -};
    -
    -
    -/**
    - * Adds extra stack trace information to an exception for the list of
    - * asynchronous {@code then} calls that have been run for this Promise. Stack
    - * trace information is recorded in {@see #addStackTrace_}, and appended to
    - * rethrown errors when {@code LONG_STACK_TRACES} is enabled.
    - *
    - * @param {*} err An unhandled exception captured during callback execution.
    - * @private
    - */
    -goog.Promise.prototype.appendLongStack_ = function(err) {
    -  if (goog.Promise.LONG_STACK_TRACES &&
    -      err && goog.isString(err.stack) && this.stack_.length) {
    -    var longTrace = ['Promise trace:'];
    -
    -    for (var promise = this; promise; promise = promise.parent_) {
    -      for (var i = this.currentStep_; i >= 0; i--) {
    -        longTrace.push(promise.stack_[i]);
    -      }
    -      longTrace.push('Value: ' +
    -          '[' + (promise.state_ == goog.Promise.State_.REJECTED ?
    -              'REJECTED' : 'FULFILLED') + '] ' +
    -          '<' + String(promise.result_) + '>');
    -    }
    -    err.stack += '\n\n' + longTrace.join('\n');
    -  }
    -};
    -
    -
    -/**
    - * Marks this rejected Promise as having being handled. Also marks any parent
    - * Promises in the rejected state as handled. The rejection handler will no
    - * longer be invoked for this Promise (if it has not been called already).
    - *
    - * @private
    - */
    -goog.Promise.prototype.removeUnhandledRejection_ = function() {
    -  if (goog.Promise.UNHANDLED_REJECTION_DELAY > 0) {
    -    for (var p = this; p && p.unhandledRejectionId_; p = p.parent_) {
    -      goog.global.clearTimeout(p.unhandledRejectionId_);
    -      p.unhandledRejectionId_ = 0;
    -    }
    -  } else if (goog.Promise.UNHANDLED_REJECTION_DELAY == 0) {
    -    for (var p = this; p && p.hadUnhandledRejection_; p = p.parent_) {
    -      p.hadUnhandledRejection_ = false;
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Marks this rejected Promise as unhandled. If no {@code onRejected} callback
    - * is called for this Promise before the {@code UNHANDLED_REJECTION_DELAY}
    - * expires, the reason will be passed to the unhandled rejection handler. The
    - * handler typically rethrows the rejection reason so that it becomes visible in
    - * the developer console.
    - *
    - * @param {!goog.Promise} promise The rejected Promise.
    - * @param {*} reason The Promise rejection reason.
    - * @private
    - */
    -goog.Promise.addUnhandledRejection_ = function(promise, reason) {
    -  if (goog.Promise.UNHANDLED_REJECTION_DELAY > 0) {
    -    promise.unhandledRejectionId_ = goog.global.setTimeout(function() {
    -      promise.appendLongStack_(reason);
    -      goog.Promise.handleRejection_.call(null, reason);
    -    }, goog.Promise.UNHANDLED_REJECTION_DELAY);
    -
    -  } else if (goog.Promise.UNHANDLED_REJECTION_DELAY == 0) {
    -    promise.hadUnhandledRejection_ = true;
    -    goog.async.run(function() {
    -      if (promise.hadUnhandledRejection_) {
    -        promise.appendLongStack_(reason);
    -        goog.Promise.handleRejection_.call(null, reason);
    -      }
    -    });
    -  }
    -};
    -
    -
    -/**
    - * A method that is invoked with the rejection reasons for Promises that are
    - * rejected but have no {@code onRejected} callbacks registered yet.
    - * @type {function(*)}
    - * @private
    - */
    -goog.Promise.handleRejection_ = goog.async.throwException;
    -
    -
    -/**
    - * Sets a handler that will be called with reasons from unhandled rejected
    - * Promises. If the rejected Promise (or one of its descendants) has an
    - * {@code onRejected} callback registered, the rejection will be considered
    - * handled, and the rejection handler will not be called.
    - *
    - * By default, unhandled rejections are rethrown so that the error may be
    - * captured by the developer console or a {@code window.onerror} handler.
    - *
    - * @param {function(*)} handler A function that will be called with reasons from
    - *     rejected Promises. Defaults to {@code goog.async.throwException}.
    - */
    -goog.Promise.setUnhandledRejectionHandler = function(handler) {
    -  goog.Promise.handleRejection_ = handler;
    -};
    -
    -
    -
    -/**
    - * Error used as a rejection reason for canceled Promises.
    - *
    - * @param {string=} opt_message
    - * @constructor
    - * @extends {goog.debug.Error}
    - * @final
    - */
    -goog.Promise.CancellationError = function(opt_message) {
    -  goog.Promise.CancellationError.base(this, 'constructor', opt_message);
    -};
    -goog.inherits(goog.Promise.CancellationError, goog.debug.Error);
    -
    -
    -/** @override */
    -goog.Promise.CancellationError.prototype.name = 'cancel';
    -
    -
    -
    -/**
    - * Internal implementation of the resolver interface.
    - *
    - * @param {!goog.Promise<TYPE>} promise
    - * @param {function((TYPE|goog.Promise<TYPE>|Thenable)=)} resolve
    - * @param {function(*): void} reject
    - * @implements {goog.promise.Resolver<TYPE>}
    - * @final @struct
    - * @constructor
    - * @private
    - * @template TYPE
    - */
    -goog.Promise.Resolver_ = function(promise, resolve, reject) {
    -  /** @const */
    -  this.promise = promise;
    -
    -  /** @const */
    -  this.resolve = resolve;
    -
    -  /** @const */
    -  this.reject = reject;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/promise/promise_test.html b/src/database/third_party/closure-library/closure/goog/promise/promise_test.html
    deleted file mode 100644
    index edf95df0196..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/promise/promise_test.html
    +++ /dev/null
    @@ -1,18 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<title>Closure Unit Tests - goog.Promise</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.PromiseTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/promise/promise_test.js b/src/database/third_party/closure-library/closure/goog/promise/promise_test.js
    deleted file mode 100644
    index a835ab64adb..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/promise/promise_test.js
    +++ /dev/null
    @@ -1,1520 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.PromiseTest');
    -
    -goog.require('goog.Promise');
    -goog.require('goog.Thenable');
    -goog.require('goog.functions');
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -
    -goog.setTestOnly('goog.PromiseTest');
    -
    -
    -// TODO(brenneman):
    -// - Add tests for interoperability with native Promises where available.
    -// - Make most tests use the MockClock (though some tests should still verify
    -//   real asynchronous behavior.
    -// - Add tests for long stack traces.
    -
    -
    -var mockClock;
    -var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall(document.title);
    -var stubs = new goog.testing.PropertyReplacer();
    -var unhandledRejections;
    -
    -
    -// Simple shared objects used as test values.
    -var dummy = {toString: goog.functions.constant('[object dummy]')};
    -var sentinel = {toString: goog.functions.constant('[object sentinel]')};
    -
    -
    -function setUpPage() {
    -  asyncTestCase.stepTimeout = 200;
    -  mockClock = new goog.testing.MockClock();
    -}
    -
    -
    -function setUp() {
    -  unhandledRejections = goog.testing.recordFunction();
    -  goog.Promise.setUnhandledRejectionHandler(unhandledRejections);
    -}
    -
    -
    -function tearDown() {
    -  if (mockClock) {
    -    // The system should leave no pending unhandled rejections. Advance the mock
    -    // clock to the end of time to catch any rethrows waiting in the queue.
    -    mockClock.tick(Infinity);
    -    mockClock.uninstall();
    -    mockClock.reset();
    -  }
    -  stubs.reset();
    -}
    -
    -
    -function tearDownPage() {
    -  goog.dispose(mockClock);
    -}
    -
    -
    -function continueTesting() {
    -  asyncTestCase.continueTesting();
    -}
    -
    -
    -/**
    - * Dummy onfulfilled or onrejected function that should not be called.
    - *
    - * @param {*} result The result passed into the callback.
    - */
    -function shouldNotCall(result) {
    -  fail('This should not have been called (result: ' + String(result) + ')');
    -}
    -
    -
    -function fulfillSoon(value, delay) {
    -  return new goog.Promise(function(resolve, reject) {
    -    window.setTimeout(function() {
    -      resolve(value);
    -    }, delay);
    -  });
    -}
    -
    -
    -function rejectSoon(reason, delay) {
    -  return new goog.Promise(function(resolve, reject) {
    -    window.setTimeout(function() {
    -      reject(reason);
    -    }, delay);
    -  });
    -}
    -
    -
    -function testThenIsFulfilled() {
    -  asyncTestCase.waitForAsync();
    -  var timesCalled = 0;
    -
    -  var p = new goog.Promise(function(resolve, reject) {
    -    resolve(sentinel);
    -  });
    -  p.then(function(value) {
    -    timesCalled++;
    -    assertEquals(sentinel, value);
    -    assertEquals('onFulfilled must be called exactly once.', 1, timesCalled);
    -  });
    -  p.thenAlways(continueTesting);
    -
    -  assertEquals('then() must return before callbacks are invoked.',
    -               0, timesCalled);
    -}
    -
    -
    -function testThenIsRejected() {
    -  asyncTestCase.waitForAsync();
    -  var timesCalled = 0;
    -
    -  var p = new goog.Promise(function(resolve, reject) {
    -    reject(sentinel);
    -  });
    -  p.then(shouldNotCall, function(value) {
    -    timesCalled++;
    -    assertEquals(sentinel, value);
    -    assertEquals('onRejected must be called exactly once.', 1, timesCalled);
    -  });
    -  p.thenAlways(continueTesting);
    -
    -  assertEquals('then() must return before callbacks are invoked.',
    -               0, timesCalled);
    -}
    -
    -function testThenAsserts() {
    -  var p = goog.Promise.resolve();
    -
    -  var m = assertThrows(function() {
    -    p.then({});
    -  });
    -  assertContains('opt_onFulfilled should be a function.', m.message);
    -
    -  m = assertThrows(function() {
    -    p.then(function() {}, {});
    -  });
    -  assertContains('opt_onRejected should be a function.', m.message);
    -}
    -
    -
    -function testOptionalOnFulfilled() {
    -  asyncTestCase.waitForAsync();
    -
    -  goog.Promise.resolve(sentinel).
    -      then(null, null).
    -      then(null, shouldNotCall).
    -      then(function(value) {
    -        assertEquals(sentinel, value);
    -      }).
    -      thenAlways(continueTesting);
    -}
    -
    -
    -function testOptionalOnRejected() {
    -  asyncTestCase.waitForAsync();
    -
    -  goog.Promise.reject(sentinel).
    -      then(null, null).
    -      then(shouldNotCall).
    -      then(null, function(reason) {
    -        assertEquals(sentinel, reason);
    -      }).
    -      thenAlways(continueTesting);
    -}
    -
    -
    -function testMultipleResolves() {
    -  asyncTestCase.waitForAsync();
    -  var timesCalled = 0;
    -  var resolvePromise;
    -
    -  var p = new goog.Promise(function(resolve, reject) {
    -    resolvePromise = resolve;
    -    resolve('foo');
    -    resolve('bar');
    -  });
    -
    -  p.then(function(value) {
    -    timesCalled++;
    -    assertEquals('onFulfilled must be called exactly once.', 1, timesCalled);
    -  });
    -
    -  // Add one more test for fulfilling after a delay.
    -  window.setTimeout(function() {
    -    resolvePromise('baz');
    -    assertEquals(1, timesCalled);
    -    continueTesting();
    -  }, 10);
    -}
    -
    -
    -function testMultipleRejects() {
    -  asyncTestCase.waitForAsync();
    -  var timesCalled = 0;
    -  var rejectPromise;
    -
    -  var p = new goog.Promise(function(resolve, reject) {
    -    rejectPromise = reject;
    -    reject('foo');
    -    reject('bar');
    -  });
    -
    -  p.then(shouldNotCall, function(value) {
    -    timesCalled++;
    -    assertEquals('onRejected must be called exactly once.', 1, timesCalled);
    -  });
    -
    -  // Add one more test for rejecting after a delay.
    -  window.setTimeout(function() {
    -    rejectPromise('baz');
    -    assertEquals(1, timesCalled);
    -    continueTesting();
    -  }, 10);
    -}
    -
    -
    -function testAsynchronousThenCalls() {
    -  asyncTestCase.waitForAsync();
    -  var timesCalled = [0, 0, 0, 0];
    -  var p = new goog.Promise(function(resolve, reject) {
    -    window.setTimeout(function() {
    -      resolve();
    -    }, 30);
    -  });
    -
    -  p.then(function() {
    -    timesCalled[0]++;
    -    assertArrayEquals([1, 0, 0, 0], timesCalled);
    -  });
    -
    -  window.setTimeout(function() {
    -    p.then(function() {
    -      timesCalled[1]++;
    -      assertArrayEquals([1, 1, 0, 0], timesCalled);
    -    });
    -  }, 10);
    -
    -  window.setTimeout(function() {
    -    p.then(function() {
    -      timesCalled[2]++;
    -      assertArrayEquals([1, 1, 1, 0], timesCalled);
    -    });
    -  }, 20);
    -
    -  window.setTimeout(function() {
    -    p.then(function() {
    -      timesCalled[3]++;
    -      assertArrayEquals([1, 1, 1, 1], timesCalled);
    -    });
    -    p.thenAlways(continueTesting);
    -  }, 40);
    -}
    -
    -
    -function testResolveWithPromise() {
    -  asyncTestCase.waitForAsync();
    -  var resolveBlocker;
    -  var hasFulfilled = false;
    -  var blocker = new goog.Promise(function(resolve, reject) {
    -    resolveBlocker = resolve;
    -  });
    -
    -  var p = goog.Promise.resolve(blocker);
    -  p.then(function(value) {
    -    hasFulfilled = true;
    -    assertEquals(sentinel, value);
    -  }, shouldNotCall);
    -  p.thenAlways(function() {
    -    assertTrue(hasFulfilled);
    -    continueTesting();
    -  });
    -
    -  assertFalse(hasFulfilled);
    -  resolveBlocker(sentinel);
    -}
    -
    -
    -function testResolveWithRejectedPromise() {
    -  asyncTestCase.waitForAsync();
    -  var rejectBlocker;
    -  var hasRejected = false;
    -  var blocker = new goog.Promise(function(resolve, reject) {
    -    rejectBlocker = reject;
    -  });
    -
    -  var p = goog.Promise.resolve(blocker);
    -  p.then(shouldNotCall, function(reason) {
    -    hasRejected = true;
    -    assertEquals(sentinel, reason);
    -  });
    -  p.thenAlways(function() {
    -    assertTrue(hasRejected);
    -    continueTesting();
    -  });
    -
    -  assertFalse(hasRejected);
    -  rejectBlocker(sentinel);
    -}
    -
    -
    -function testRejectWithPromise() {
    -  asyncTestCase.waitForAsync();
    -  var resolveBlocker;
    -  var hasFulfilled = false;
    -  var blocker = new goog.Promise(function(resolve, reject) {
    -    resolveBlocker = resolve;
    -  });
    -
    -  var p = goog.Promise.reject(blocker);
    -  p.then(function(value) {
    -    hasFulfilled = true;
    -    assertEquals(sentinel, value);
    -  }, shouldNotCall);
    -  p.thenAlways(function() {
    -    assertTrue(hasFulfilled);
    -    continueTesting();
    -  });
    -
    -  assertFalse(hasFulfilled);
    -  resolveBlocker(sentinel);
    -}
    -
    -
    -function testRejectWithRejectedPromise() {
    -  asyncTestCase.waitForAsync();
    -  var rejectBlocker;
    -  var hasRejected = false;
    -  var blocker = new goog.Promise(function(resolve, reject) {
    -    rejectBlocker = reject;
    -  });
    -
    -  var p = goog.Promise.reject(blocker);
    -  p.then(shouldNotCall, function(reason) {
    -    hasRejected = true;
    -    assertEquals(sentinel, reason);
    -  });
    -  p.thenAlways(function() {
    -    assertTrue(hasRejected);
    -    continueTesting();
    -  });
    -
    -  assertFalse(hasRejected);
    -  rejectBlocker(sentinel);
    -}
    -
    -
    -function testResolveAndReject() {
    -  asyncTestCase.waitForAsync();
    -  var onFulfilledCalled = false;
    -  var onRejectedCalled = false;
    -  var p = new goog.Promise(function(resolve, reject) {
    -    resolve();
    -    reject();
    -  });
    -
    -  p.then(function() {
    -    onFulfilledCalled = true;
    -  }, function() {
    -    onRejectedCalled = true;
    -  });
    -
    -  p.thenAlways(function() {
    -    assertTrue(onFulfilledCalled);
    -    assertFalse(onRejectedCalled);
    -    continueTesting();
    -  });
    -}
    -
    -
    -function testRejectAndResolve() {
    -  asyncTestCase.waitForAsync();
    -  var onFulfilledCalled = false;
    -  var onRejectedCalled = false;
    -  var p = new goog.Promise(function(resolve, reject) {
    -    reject();
    -    resolve();
    -  });
    -
    -  p.then(function() {
    -    onFulfilledCalled = true;
    -  }, function() {
    -    onRejectedCalled = true;
    -  });
    -
    -  p.thenAlways(function() {
    -    assertTrue(onRejectedCalled);
    -    assertFalse(onFulfilledCalled);
    -    continueTesting();
    -  });
    -}
    -
    -
    -function testThenReturnsBeforeCallbackWithFulfill() {
    -  asyncTestCase.waitForAsync();
    -  var thenHasReturned = false;
    -  var p = goog.Promise.resolve();
    -
    -  p.then(function() {
    -    assertTrue(
    -        'Callback must be called only after then() has returned.',
    -        thenHasReturned);
    -  });
    -  p.thenAlways(continueTesting);
    -  thenHasReturned = true;
    -}
    -
    -
    -function testThenReturnsBeforeCallbackWithReject() {
    -  asyncTestCase.waitForAsync();
    -  var thenHasReturned = false;
    -  var p = goog.Promise.reject();
    -
    -  p.then(null, function() {
    -    assertTrue(thenHasReturned);
    -  });
    -  p.thenAlways(continueTesting);
    -  thenHasReturned = true;
    -}
    -
    -
    -function testResolutionOrder() {
    -  asyncTestCase.waitForAsync();
    -  var callbacks = [];
    -  var p = goog.Promise.resolve();
    -
    -  p.then(function() { callbacks.push(1); }, shouldNotCall);
    -  p.then(function() { callbacks.push(2); }, shouldNotCall);
    -  p.then(function() { callbacks.push(3); }, shouldNotCall);
    -
    -  p.then(function() {
    -    assertArrayEquals([1, 2, 3], callbacks);
    -  });
    -  p.thenAlways(continueTesting);
    -}
    -
    -
    -function testResolutionOrderWithThrow() {
    -  asyncTestCase.waitForAsync();
    -  var callbacks = [];
    -  var p = goog.Promise.resolve();
    -
    -  p.then(function() { callbacks.push(1); }, shouldNotCall);
    -  var child = p.then(function() {
    -    callbacks.push(2);
    -    throw Error();
    -  }, shouldNotCall);
    -
    -  child.then(shouldNotCall, function() {
    -    // The parent callbacks should be evaluated before the child.
    -    callbacks.push(4);
    -  });
    -
    -  p.then(function() { callbacks.push(3); }, shouldNotCall);
    -
    -  child.then(shouldNotCall, function() {
    -    callbacks.push(5);
    -    assertArrayEquals([1, 2, 3, 4, 5], callbacks);
    -  });
    -
    -  p.thenAlways(continueTesting);
    -}
    -
    -
    -function testResolutionOrderWithNestedThen() {
    -  asyncTestCase.waitForAsync();
    -  var callbacks = [];
    -  var p = goog.Promise.resolve();
    -
    -  p.then(function() {
    -    callbacks.push(1);
    -    p.then(function() {
    -      callbacks.push(3);
    -    });
    -  });
    -  p.then(function() { callbacks.push(2); });
    -
    -  window.setTimeout(function() {
    -    assertArrayEquals([1, 2, 3], callbacks);
    -    continueTesting();
    -  }, 100);
    -}
    -
    -
    -function testRejectionOrder() {
    -  asyncTestCase.waitForAsync();
    -  var callbacks = [];
    -  var p = goog.Promise.reject();
    -
    -  p.then(shouldNotCall, function() { callbacks.push(1); });
    -  p.then(shouldNotCall, function() { callbacks.push(2); });
    -  p.then(shouldNotCall, function() { callbacks.push(3); });
    -
    -  p.then(shouldNotCall, function() {
    -    assertArrayEquals([1, 2, 3], callbacks);
    -  });
    -  p.thenAlways(continueTesting);
    -}
    -
    -
    -function testRejectionOrderWithThrow() {
    -  asyncTestCase.waitForAsync();
    -  var callbacks = [];
    -  var p = goog.Promise.reject();
    -
    -  p.then(shouldNotCall, function() { callbacks.push(1); });
    -  p.then(shouldNotCall, function() {
    -    callbacks.push(2);
    -    throw Error();
    -  });
    -  p.then(shouldNotCall, function() { callbacks.push(3); });
    -
    -  p.then(shouldNotCall, function() {
    -    assertArrayEquals([1, 2, 3], callbacks);
    -  });
    -  p.thenAlways(continueTesting);
    -}
    -
    -
    -function testRejectionOrderWithNestedThen() {
    -  asyncTestCase.waitForAsync();
    -  var callbacks = [];
    -
    -  var p = goog.Promise.reject();
    -
    -  p.then(shouldNotCall, function() {
    -    callbacks.push(1);
    -    p.then(shouldNotCall, function() {
    -      callbacks.push(3);
    -    });
    -  });
    -  p.then(shouldNotCall, function() { callbacks.push(2); });
    -
    -  window.setTimeout(function() {
    -    assertArrayEquals([1, 2, 3], callbacks);
    -    continueTesting();
    -  }, 0);
    -}
    -
    -
    -function testBranching() {
    -  asyncTestCase.waitForSignals(3);
    -  var p = goog.Promise.resolve(2);
    -
    -  p.then(function(value) {
    -    assertEquals('then functions should see the same value', 2, value);
    -    return value / 2;
    -  }).then(function(value) {
    -    assertEquals('branch should receive the returned value', 1, value);
    -    asyncTestCase.signal();
    -  });
    -
    -  p.then(function(value) {
    -    assertEquals('then functions should see the same value', 2, value);
    -    throw value + 1;
    -  }).then(shouldNotCall, function(reason) {
    -    assertEquals('branch should receive the thrown value', 3, reason);
    -    asyncTestCase.signal();
    -  });
    -
    -  p.then(function(value) {
    -    assertEquals('then functions should see the same value', 2, value);
    -    return value * 2;
    -  }).then(function(value) {
    -    assertEquals('branch should receive the returned value', 4, value);
    -    asyncTestCase.signal();
    -  });
    -}
    -
    -
    -function testThenReturnsPromise() {
    -  var parent = goog.Promise.resolve();
    -  var child = parent.then();
    -
    -  assertTrue(child instanceof goog.Promise);
    -  assertNotEquals('The returned Promise must be different from the input.',
    -                  parent, child);
    -}
    -
    -
    -function testBlockingPromise() {
    -  asyncTestCase.waitForAsync();
    -  var p = goog.Promise.resolve();
    -  var wasFulfilled = false;
    -  var wasRejected = false;
    -
    -  var p2 = p.then(function() {
    -    return new goog.Promise(function(resolve, reject) {});
    -  });
    -
    -  p2.then(function() {
    -    wasFulfilled = true;
    -  }, function() {
    -    wasRejected = true;
    -  });
    -
    -  window.setTimeout(function() {
    -    assertFalse('p2 should be blocked on the returned Promise', wasFulfilled);
    -    assertFalse('p2 should be blocked on the returned Promise', wasRejected);
    -    continueTesting();
    -  }, 100);
    -}
    -
    -
    -function testBlockingPromiseFulfilled() {
    -  asyncTestCase.waitForAsync();
    -  var blockingPromise = new goog.Promise(function(resolve, reject) {
    -    window.setTimeout(function() {
    -      resolve(sentinel);
    -    }, 0);
    -  });
    -
    -  var p = goog.Promise.resolve(dummy);
    -  var p2 = p.then(function(value) {
    -    return blockingPromise;
    -  });
    -
    -  p2.then(function(value) {
    -    assertEquals(sentinel, value);
    -  }).thenAlways(continueTesting);
    -}
    -
    -
    -function testBlockingPromiseRejected() {
    -  asyncTestCase.waitForAsync();
    -  var blockingPromise = new goog.Promise(function(resolve, reject) {
    -    window.setTimeout(function() {
    -      reject(sentinel);
    -    }, 0);
    -  });
    -
    -  var p = goog.Promise.resolve(blockingPromise);
    -
    -  p.then(shouldNotCall, function(reason) {
    -    assertEquals(sentinel, reason);
    -  }).thenAlways(continueTesting);
    -}
    -
    -
    -function testBlockingThenableFulfilled() {
    -  asyncTestCase.waitForAsync();
    -  var thenable = {
    -    then: function(onFulfill, onReject) { onFulfill(sentinel); }
    -  };
    -
    -  var p = goog.Promise.resolve(thenable).
    -      then(function(reason) {
    -        assertEquals(sentinel, reason);
    -      }, shouldNotCall).thenAlways(continueTesting);
    -}
    -
    -
    -function testBlockingThenableRejected() {
    -  asyncTestCase.waitForAsync();
    -  var thenable = {
    -    then: function(onFulfill, onReject) { onReject(sentinel); }
    -  };
    -
    -  var p = goog.Promise.resolve(thenable).
    -      then(shouldNotCall, function(reason) {
    -        assertEquals(sentinel, reason);
    -      }).thenAlways(continueTesting);
    -}
    -
    -
    -function testBlockingThenableThrows() {
    -  asyncTestCase.waitForAsync();
    -  var thenable = {
    -    then: function(onFulfill, onReject) { throw sentinel; }
    -  };
    -
    -  var p = goog.Promise.resolve(thenable).
    -      then(shouldNotCall, function(reason) {
    -        assertEquals(sentinel, reason);
    -      }).thenAlways(continueTesting);
    -}
    -
    -
    -function testBlockingThenableMisbehaves() {
    -  asyncTestCase.waitForAsync();
    -  var thenable = {
    -    then: function(onFulfill, onReject) {
    -      onFulfill(sentinel);
    -      onFulfill(dummy);
    -      onReject(dummy);
    -      throw dummy;
    -    }
    -  };
    -
    -  var p = goog.Promise.resolve(thenable).
    -      then(function(value) {
    -        assertEquals(
    -            'Only the first resolution of the Thenable should have a result.',
    -            sentinel, value);
    -      }, shouldNotCall).thenAlways(continueTesting);
    -}
    -
    -
    -function testNestingThenables() {
    -  asyncTestCase.waitForAsync();
    -  var thenableA = {
    -    then: function(onFulfill, onReject) { onFulfill(sentinel); }
    -  };
    -  var thenableB = {
    -    then: function(onFulfill, onReject) { onFulfill(thenableA); }
    -  };
    -  var thenableC = {
    -    then: function(onFulfill, onReject) { onFulfill(thenableB); }
    -  };
    -
    -  var p = goog.Promise.resolve(thenableC).
    -      then(function(value) {
    -        assertEquals(
    -            'Should resolve to the fulfillment value of thenableA',
    -            sentinel, value);
    -      }, shouldNotCall).thenAlways(continueTesting);
    -}
    -
    -
    -function testNestingThenablesRejected() {
    -  asyncTestCase.waitForAsync();
    -  var thenableA = {
    -    then: function(onFulfill, onReject) { onReject(sentinel); }
    -  };
    -  var thenableB = {
    -    then: function(onFulfill, onReject) { onReject(thenableA); }
    -  };
    -  var thenableC = {
    -    then: function(onFulfill, onReject) { onReject(thenableB); }
    -  };
    -
    -  var p = goog.Promise.reject(thenableC).
    -      then(shouldNotCall, function(reason) {
    -        assertEquals(
    -            'Should resolve to rejection reason of thenableA',
    -            sentinel, reason);
    -      }).thenAlways(continueTesting);
    -}
    -
    -
    -function testThenCatch() {
    -  asyncTestCase.waitForAsync();
    -  var catchCalled = false;
    -  var p = goog.Promise.reject();
    -
    -  var p2 = p.thenCatch(function(reason) {
    -    catchCalled = true;
    -    return sentinel;
    -  });
    -
    -  p2.then(function(value) {
    -    assertTrue(catchCalled);
    -    assertEquals(sentinel, value);
    -  }, shouldNotCall);
    -  p2.thenAlways(continueTesting);
    -}
    -
    -
    -function testRaceWithEmptyList() {
    -  asyncTestCase.waitForAsync();
    -  goog.Promise.race([]).then(function(value) {
    -    assertUndefined(value);
    -  }).thenAlways(continueTesting);
    -}
    -
    -
    -function testRaceWithFulfill() {
    -  asyncTestCase.waitForAsync();
    -
    -  var a = fulfillSoon('a', 40);
    -  var b = fulfillSoon('b', 30);
    -  var c = fulfillSoon('c', 10);
    -  var d = fulfillSoon('d', 20);
    -
    -  goog.Promise.race([a, b, c, d]).
    -      then(function(value) {
    -        assertEquals('c', value);
    -        // Return the slowest input promise to wait for it to complete.
    -        return a;
    -      }).
    -      then(function(value) {
    -        assertEquals('The slowest promise should resolve eventually.',
    -                     'a', value);
    -      }).thenAlways(continueTesting);
    -}
    -
    -
    -function testRaceWithReject() {
    -  asyncTestCase.waitForAsync();
    -
    -  var a = rejectSoon('rejected-a', 40);
    -  var b = rejectSoon('rejected-b', 30);
    -  var c = rejectSoon('rejected-c', 10);
    -  var d = rejectSoon('rejected-d', 20);
    -
    -  var p = goog.Promise.race([a, b, c, d]).
    -      then(shouldNotCall, function(value) {
    -        assertEquals('rejected-c', value);
    -        return a;
    -      }).
    -      then(shouldNotCall, function(reason) {
    -        assertEquals('The slowest promise should resolve eventually.',
    -                     'rejected-a', reason);
    -      }).thenAlways(continueTesting);
    -}
    -
    -
    -function testAllWithEmptyList() {
    -  asyncTestCase.waitForAsync();
    -  goog.Promise.all([]).then(function(value) {
    -    assertArrayEquals([], value);
    -  }).thenAlways(continueTesting);
    -}
    -
    -
    -function testAllWithFulfill() {
    -  asyncTestCase.waitForAsync();
    -
    -  var a = fulfillSoon('a', 40);
    -  var b = fulfillSoon('b', 30);
    -  var c = fulfillSoon('c', 10);
    -  var d = fulfillSoon('d', 20);
    -
    -  goog.Promise.all([a, b, c, d]).then(function(value) {
    -    assertArrayEquals(['a', 'b', 'c', 'd'], value);
    -  }).thenAlways(continueTesting);
    -}
    -
    -
    -function testAllWithReject() {
    -  asyncTestCase.waitForAsync();
    -
    -  var a = fulfillSoon('a', 40);
    -  var b = rejectSoon('rejected-b', 30);
    -  var c = fulfillSoon('c', 10);
    -  var d = fulfillSoon('d', 20);
    -
    -  goog.Promise.all([a, b, c, d]).
    -      then(shouldNotCall, function(reason) {
    -        assertEquals('rejected-b', reason);
    -        return a;
    -      }).
    -      then(function(value) {
    -        assertEquals('Promise "a" should be fulfilled even though the all()' +
    -                     'was rejected.', 'a', value);
    -      }).thenAlways(continueTesting);
    -}
    -
    -
    -function testFirstFulfilledWithEmptyList() {
    -  asyncTestCase.waitForAsync();
    -  goog.Promise.firstFulfilled([]).then(function(value) {
    -    assertUndefined(value);
    -  }).thenAlways(continueTesting);
    -}
    -
    -
    -function testFirstFulfilledWithFulfill() {
    -  asyncTestCase.waitForAsync();
    -
    -  var a = fulfillSoon('a', 40);
    -  var b = rejectSoon('rejected-b', 30);
    -  var c = rejectSoon('rejected-c', 10);
    -  var d = fulfillSoon('d', 20);
    -
    -  goog.Promise.firstFulfilled([a, b, c, d]).
    -      then(function(value) {
    -        assertEquals('d', value);
    -        return c;
    -      }).
    -      then(shouldNotCall, function(reason) {
    -        assertEquals(
    -            'Promise "c" should have been rejected before the some() resolved.',
    -            'rejected-c', reason);
    -        return a;
    -      }).
    -      then(function(reason) {
    -        assertEquals(
    -            'Promise "a" should be fulfilled even after some() has resolved.',
    -            'a', value);
    -      }, shouldNotCall).thenAlways(continueTesting);
    -}
    -
    -
    -function testFirstFulfilledWithReject() {
    -  asyncTestCase.waitForAsync();
    -
    -  var a = rejectSoon('rejected-a', 40);
    -  var b = rejectSoon('rejected-b', 30);
    -  var c = rejectSoon('rejected-c', 10);
    -  var d = rejectSoon('rejected-d', 20);
    -
    -  var p = goog.Promise.firstFulfilled([a, b, c, d]).
    -      then(shouldNotCall, function(reason) {
    -        assertArrayEquals(
    -            ['rejected-a', 'rejected-b', 'rejected-c', 'rejected-d'], reason);
    -      }).thenAlways(continueTesting);
    -}
    -
    -
    -function testThenAlwaysWithFulfill() {
    -  asyncTestCase.waitForAsync();
    -  var p = goog.Promise.resolve().
    -      thenAlways(function() {
    -        assertEquals(0, arguments.length);
    -      }).
    -      then(continueTesting, shouldNotCall);
    -}
    -
    -
    -function testThenAlwaysWithReject() {
    -  asyncTestCase.waitForAsync();
    -  var p = goog.Promise.reject().
    -      thenAlways(function() {
    -        assertEquals(0, arguments.length);
    -      }).
    -      then(shouldNotCall, continueTesting);
    -}
    -
    -
    -function testThenAlwaysCalledMultipleTimes() {
    -  asyncTestCase.waitForAsync();
    -  var calls = [];
    -
    -  var p = goog.Promise.resolve(sentinel);
    -  p.then(function(value) {
    -    assertEquals(sentinel, value);
    -    calls.push(1);
    -    return value;
    -  });
    -  p.thenAlways(function() {
    -    assertEquals(0, arguments.length);
    -    calls.push(2);
    -    throw Error('thenAlways throw');
    -  });
    -  p.then(function(value) {
    -    assertEquals(
    -        'Promise result should not mutate after throw from thenAlways.',
    -        sentinel, value);
    -    calls.push(3);
    -  });
    -  p.thenAlways(function() {
    -    assertArrayEquals([1, 2, 3], calls);
    -  });
    -  p.thenAlways(function() {
    -    assertEquals(
    -        'Should be one unhandled exception from the "thenAlways throw".',
    -        1, unhandledRejections.getCallCount());
    -    var rejectionCall = unhandledRejections.popLastCall();
    -    assertEquals(1, rejectionCall.getArguments().length);
    -    var err = rejectionCall.getArguments()[0];
    -    assertEquals('thenAlways throw', err.message);
    -    assertEquals(goog.global, rejectionCall.getThis());
    -  });
    -  p.thenAlways(continueTesting);
    -}
    -
    -
    -function testContextWithInit() {
    -  var initContext;
    -  var p = new goog.Promise(function(resolve, reject) {
    -    initContext = this;
    -  }, sentinel);
    -  assertEquals(sentinel, initContext);
    -}
    -
    -
    -function testContextWithInitDefault() {
    -  var initContext;
    -  var p = new goog.Promise(function(resolve, reject) {
    -    initContext = this;
    -  });
    -  assertEquals(
    -      'initFunc should default to being called in the global scope',
    -      goog.global, initContext);
    -}
    -
    -
    -function testContextWithFulfillment() {
    -  asyncTestCase.waitForAsync();
    -  var context = sentinel;
    -  var p = goog.Promise.resolve();
    -
    -  p.then(function() {
    -    assertEquals(
    -        'Call should be made in the global scope if no context is specified.',
    -        goog.global, this);
    -  });
    -  p.then(function() {
    -    assertEquals(sentinel, this);
    -  }, shouldNotCall, sentinel);
    -  p.thenAlways(function() {
    -    assertEquals(sentinel, this);
    -    continueTesting();
    -  }, sentinel);
    -}
    -
    -
    -function testContextWithRejection() {
    -  asyncTestCase.waitForAsync();
    -  var context = sentinel;
    -  var p = goog.Promise.reject();
    -
    -  p.then(shouldNotCall, function() {
    -    assertEquals(
    -        'Call should be made in the global scope if no context is specified.',
    -        goog.global, this);
    -  });
    -  p.then(shouldNotCall, function() {
    -    assertEquals(sentinel, this);
    -  }, sentinel);
    -  p.thenCatch(function() {
    -    assertEquals(sentinel, this);
    -  }, sentinel);
    -  p.thenAlways(function() {
    -    assertEquals(sentinel, this);
    -    continueTesting();
    -  }, sentinel);
    -}
    -
    -
    -function testCancel() {
    -  asyncTestCase.waitForAsync();
    -  var p = new goog.Promise(goog.nullFunction);
    -  p.then(shouldNotCall, function(reason) {
    -    assertTrue(reason instanceof goog.Promise.CancellationError);
    -    assertEquals('cancellation message', reason.message);
    -    continueTesting();
    -  });
    -  p.cancel('cancellation message');
    -}
    -
    -
    -function testCancelAfterResolve() {
    -  asyncTestCase.waitForAsync();
    -  var p = goog.Promise.resolve();
    -  p.cancel();
    -  p.then(null, shouldNotCall);
    -  p.thenAlways(continueTesting);
    -}
    -
    -
    -function testCancelAfterReject() {
    -  asyncTestCase.waitForAsync();
    -  var p = goog.Promise.reject(sentinel);
    -  p.cancel();
    -  p.then(shouldNotCall, function(reason) {
    -    assertEquals(sentinel, reason);
    -    continueTesting();
    -  });
    -}
    -
    -
    -function testCancelPropagation() {
    -  asyncTestCase.waitForSignals(2);
    -  var cancelError;
    -  var p = new goog.Promise(goog.nullFunction);
    -
    -  var p2 = p.then(shouldNotCall, function(reason) {
    -    cancelError = reason;
    -    assertTrue(reason instanceof goog.Promise.CancellationError);
    -    assertEquals('parent cancel message', reason.message);
    -    return sentinel;
    -  });
    -  p2.then(function(value) {
    -    assertEquals(
    -        'Child promises should receive the returned value of the parent.',
    -        sentinel, value);
    -    asyncTestCase.signal();
    -  }, shouldNotCall);
    -
    -  var p3 = p.then(shouldNotCall, function(reason) {
    -    assertEquals(
    -        'Every onRejected handler should receive the same cancel error.',
    -        cancelError, reason);
    -    assertEquals('parent cancel message', reason.message);
    -    asyncTestCase.signal();
    -  });
    -
    -  p.cancel('parent cancel message');
    -}
    -
    -
    -function testCancelPropagationUpward() {
    -  asyncTestCase.waitForAsync();
    -  var cancelError;
    -  var cancelCalls = [];
    -  var parent = new goog.Promise(goog.nullFunction);
    -
    -  var child = parent.then(shouldNotCall, function(reason) {
    -    assertTrue(reason instanceof goog.Promise.CancellationError);
    -    assertEquals('grandChild cancel message', reason.message);
    -    cancelError = reason;
    -    cancelCalls.push('parent');
    -  });
    -
    -  var grandChild = child.then(shouldNotCall, function(reason) {
    -    assertEquals('Child should receive the same cancel error.',
    -                 cancelError, reason);
    -    cancelCalls.push('child');
    -  });
    -
    -  grandChild.then(shouldNotCall, function(reason) {
    -    assertEquals('GrandChild should receive the same cancel error.',
    -                 cancelError, reason);
    -    cancelCalls.push('grandChild');
    -  });
    -
    -  grandChild.then(shouldNotCall, function(reason) {
    -    assertArrayEquals(
    -        'Each promise in the hierarchy has a single child, so canceling the ' +
    -        'grandChild should cancel each ancestor in order.',
    -        ['parent', 'child', 'grandChild'], cancelCalls);
    -  }).thenAlways(continueTesting);
    -
    -  grandChild.cancel('grandChild cancel message');
    -}
    -
    -
    -function testCancelPropagationUpwardWithMultipleChildren() {
    -  asyncTestCase.waitForAsync();
    -  var cancelError;
    -  var cancelCalls = [];
    -  var parent = fulfillSoon(sentinel, 0);
    -
    -  parent.then(function(value) {
    -    assertEquals(
    -        'Non-canceled callbacks should be called after a sibling is canceled.',
    -        sentinel, value);
    -    continueTesting();
    -  });
    -
    -  var child = parent.then(shouldNotCall, function(reason) {
    -    assertTrue(reason instanceof goog.Promise.CancellationError);
    -    assertEquals('grandChild cancel message', reason.message);
    -    cancelError = reason;
    -    cancelCalls.push('child');
    -  });
    -
    -  var grandChild = child.then(shouldNotCall, function(reason) {
    -    assertEquals(reason, cancelError);
    -    cancelCalls.push('grandChild');
    -  });
    -
    -  grandChild.then(shouldNotCall, function(reason) {
    -    assertEquals(reason, cancelError);
    -    assertArrayEquals(
    -        'The parent promise has multiple children, so only the child and ' +
    -        'grandChild should be canceled.',
    -        ['child', 'grandChild'], cancelCalls);
    -  });
    -
    -  grandChild.cancel('grandChild cancel message');
    -}
    -
    -
    -function testCancelRecovery() {
    -  asyncTestCase.waitForSignals(2);
    -  var cancelError;
    -  var cancelCalls = [];
    -
    -  var parent = fulfillSoon(sentinel, 100);
    -
    -  var sibling1 = parent.then(function(value) {
    -    assertEquals(
    -        'Non-canceled callbacks should be called after a sibling is canceled.',
    -        sentinel, value);
    -  });
    -
    -  var sibling2 = parent.then(shouldNotCall, function(reason) {
    -    assertTrue(reason instanceof goog.Promise.CancellationError);
    -    cancelError = reason;
    -    cancelCalls.push('sibling2');
    -    return sentinel;
    -  });
    -
    -  parent.thenAlways(function() {
    -    asyncTestCase.signal();
    -  });
    -
    -  var grandChild = sibling2.then(function(value) {
    -    cancelCalls.push('child');
    -    assertEquals(
    -        'Returning a non-cancel value should uncancel the grandChild.',
    -        value, sentinel);
    -    assertArrayEquals(['sibling2', 'child'], cancelCalls);
    -  }, shouldNotCall).thenAlways(function() {
    -    asyncTestCase.signal();
    -  });
    -
    -  grandChild.cancel();
    -}
    -
    -
    -function testCancellationError() {
    -  var err = new goog.Promise.CancellationError('cancel message');
    -  assertTrue(err instanceof Error);
    -  assertTrue(err instanceof goog.Promise.CancellationError);
    -  assertEquals('cancel', err.name);
    -  assertEquals('cancel message', err.message);
    -}
    -
    -
    -function testMockClock() {
    -  mockClock.install();
    -
    -  var resolveA;
    -  var resolveB;
    -  var calls = [];
    -
    -  var p = new goog.Promise(function(resolve, reject) {
    -    resolveA = resolve;
    -  });
    -
    -  p.then(function(value) {
    -    assertEquals(sentinel, value);
    -    calls.push('then');
    -  });
    -
    -  var fulfilledChild = p.then(function(value) {
    -    assertEquals(sentinel, value);
    -    return goog.Promise.resolve(1);
    -  }).then(function(value) {
    -    assertEquals(1, value);
    -    calls.push('fulfilledChild');
    -
    -  });
    -
    -  var rejectedChild = p.then(function(value) {
    -    assertEquals(sentinel, value);
    -    return goog.Promise.reject(2);
    -  }).then(shouldNotCall, function(reason) {
    -    assertEquals(2, reason);
    -    calls.push('rejectedChild');
    -  });
    -
    -  var unresolvedChild = p.then(function(value) {
    -    assertEquals(sentinel, value);
    -    return new goog.Promise(function(r) {
    -      resolveB = r;
    -    });
    -  }).then(function(value) {
    -    assertEquals(3, value);
    -    calls.push('unresolvedChild');
    -  });
    -
    -  resolveA(sentinel);
    -  assertArrayEquals(
    -      'Calls must not be resolved until the clock ticks.',
    -      [], calls);
    -
    -  mockClock.tick();
    -  assertArrayEquals(
    -      'All resolved Promises should execute in the same timestep.',
    -      ['then', 'fulfilledChild', 'rejectedChild'], calls);
    -
    -  resolveB(3);
    -  assertArrayEquals(
    -      'New calls must not resolve until the clock ticks.',
    -      ['then', 'fulfilledChild', 'rejectedChild'], calls);
    -
    -  mockClock.tick();
    -  assertArrayEquals(
    -      'All callbacks should have executed.',
    -      ['then', 'fulfilledChild', 'rejectedChild', 'unresolvedChild'], calls);
    -}
    -
    -
    -function testHandledRejection() {
    -  mockClock.install();
    -  goog.Promise.reject(sentinel).then(shouldNotCall, function(reason) {});
    -
    -  mockClock.tick();
    -  assertEquals(0, unhandledRejections.getCallCount());
    -}
    -
    -
    -function testUnhandledRejection() {
    -  mockClock.install();
    -  goog.Promise.reject(sentinel);
    -
    -  mockClock.tick();
    -  assertEquals(1, unhandledRejections.getCallCount());
    -  var rejectionCall = unhandledRejections.popLastCall();
    -  assertArrayEquals([sentinel], rejectionCall.getArguments());
    -  assertEquals(goog.global, rejectionCall.getThis());
    -}
    -
    -
    -function testUnhandledRejection_asyncTestCase() {
    -  goog.Promise.reject(sentinel);
    -
    -  goog.Promise.setUnhandledRejectionHandler(function(error) {
    -    assertEquals(sentinel, error);
    -    asyncTestCase.continueTesting();
    -  });
    -}
    -
    -
    -function testUnhandledThrow_asyncTestCase() {
    -  goog.Promise.resolve().then(function() {
    -    throw sentinel;
    -  });
    -
    -  goog.Promise.setUnhandledRejectionHandler(function(error) {
    -    assertEquals(sentinel, error);
    -    asyncTestCase.continueTesting();
    -  });
    -}
    -
    -
    -function testUnhandledBlockingRejection() {
    -  mockClock.install();
    -  var blocker = goog.Promise.reject(sentinel);
    -  goog.Promise.resolve(blocker);
    -
    -  mockClock.tick();
    -  assertEquals(1, unhandledRejections.getCallCount());
    -  var rejectionCall = unhandledRejections.popLastCall();
    -  assertArrayEquals([sentinel], rejectionCall.getArguments());
    -  assertEquals(goog.global, rejectionCall.getThis());
    -}
    -
    -
    -function testUnhandledRejectionAfterThenAlways() {
    -  mockClock.install();
    -  var resolver = goog.Promise.withResolver();
    -  resolver.promise.thenAlways(function() {});
    -  resolver.reject(sentinel);
    -
    -  mockClock.tick();
    -  assertEquals(1, unhandledRejections.getCallCount());
    -  var rejectionCall = unhandledRejections.popLastCall();
    -  assertArrayEquals([sentinel], rejectionCall.getArguments());
    -  assertEquals(goog.global, rejectionCall.getThis());
    -}
    -
    -
    -function testHandledBlockingRejection() {
    -  mockClock.install();
    -  var blocker = goog.Promise.reject(sentinel);
    -  goog.Promise.resolve(blocker).then(shouldNotCall, function(reason) {});
    -
    -  mockClock.tick();
    -  assertEquals(0, unhandledRejections.getCallCount());
    -}
    -
    -
    -function testUnhandledRejectionWithTimeout() {
    -  mockClock.install();
    -  stubs.replace(goog.Promise, 'UNHANDLED_REJECTION_DELAY', 200);
    -  goog.Promise.reject(sentinel);
    -
    -  mockClock.tick(199);
    -  assertEquals(0, unhandledRejections.getCallCount());
    -
    -  mockClock.tick(1);
    -  assertEquals(1, unhandledRejections.getCallCount());
    -}
    -
    -
    -function testHandledRejectionWithTimeout() {
    -  mockClock.install();
    -  stubs.replace(goog.Promise, 'UNHANDLED_REJECTION_DELAY', 200);
    -  var p = goog.Promise.reject(sentinel);
    -
    -  mockClock.tick(199);
    -  p.then(shouldNotCall, function(reason) {});
    -
    -  mockClock.tick(1);
    -  assertEquals(0, unhandledRejections.getCallCount());
    -}
    -
    -
    -function testUnhandledRejectionDisabled() {
    -  mockClock.install();
    -  stubs.replace(goog.Promise, 'UNHANDLED_REJECTION_DELAY', -1);
    -  goog.Promise.reject(sentinel);
    -
    -  mockClock.tick();
    -  assertEquals(0, unhandledRejections.getCallCount());
    -}
    -
    -
    -function testThenableInterface() {
    -  var promise = new goog.Promise(function(resolve, reject) {});
    -  assertTrue(goog.Thenable.isImplementedBy(promise));
    -
    -  assertFalse(goog.Thenable.isImplementedBy({}));
    -  assertFalse(goog.Thenable.isImplementedBy('string'));
    -  assertFalse(goog.Thenable.isImplementedBy(1));
    -  assertFalse(goog.Thenable.isImplementedBy({then: function() {}}));
    -
    -  function T() {}
    -  T.prototype.then = function(opt_a, opt_b, opt_c) {};
    -  goog.Thenable.addImplementation(T);
    -  assertTrue(goog.Thenable.isImplementedBy(new T));
    -
    -  // Test COMPILED code path.
    -  try {
    -    COMPIlED = true;
    -    function C() {}
    -    C.prototype.then = function(opt_a, opt_b, opt_c) {};
    -    goog.Thenable.addImplementation(C);
    -    assertTrue(goog.Thenable.isImplementedBy(new C));
    -  } finally {
    -    COMPILED = false;
    -  }
    -}
    -
    -
    -function testCreateWithResolver_Resolved() {
    -  mockClock.install();
    -  var timesCalled = 0;
    -
    -  var resolver = goog.Promise.withResolver();
    -
    -  resolver.promise.then(function(value) {
    -    timesCalled++;
    -    assertEquals(sentinel, value);
    -  }, fail);
    -
    -  assertEquals('then() must return before callbacks are invoked.',
    -      0, timesCalled);
    -
    -  mockClock.tick();
    -
    -  assertEquals('promise is not resolved until resolver is invoked.',
    -      0, timesCalled);
    -
    -  resolver.resolve(sentinel);
    -
    -  assertEquals('resolution is delayed until the next tick',
    -      0, timesCalled);
    -
    -  mockClock.tick();
    -
    -  assertEquals('onFulfilled must be called exactly once.', 1, timesCalled);
    -}
    -
    -
    -function testCreateWithResolver_Rejected() {
    -  mockClock.install();
    -  var timesCalled = 0;
    -
    -  var resolver = goog.Promise.withResolver();
    -
    -  resolver.promise.then(fail, function(reason) {
    -    timesCalled++;
    -    assertEquals(sentinel, reason);
    -  });
    -
    -  assertEquals('then() must return before callbacks are invoked.',
    -      0, timesCalled);
    -
    -  mockClock.tick();
    -
    -  assertEquals('promise is not resolved until resolver is invoked.',
    -      0, timesCalled);
    -
    -  resolver.reject(sentinel);
    -
    -  assertEquals('resolution is delayed until the next tick',
    -      0, timesCalled);
    -
    -  mockClock.tick();
    -
    -  assertEquals('onFulfilled must be called exactly once.', 1, timesCalled);
    -}
    -
    -
    -function testLinksBetweenParentsAndChildrenAreCutOnResolve() {
    -  mockClock.install();
    -  var parentResolver = goog.Promise.withResolver();
    -  var parent = parentResolver.promise;
    -  var child = parent.then(function() {});
    -  assertNotNull(child.parent_);
    -  assertEquals(1, parent.callbackEntries_.length);
    -  parentResolver.resolve();
    -  mockClock.tick();
    -  assertNull(child.parent_);
    -  assertEquals(null, parent.callbackEntries_);
    -}
    -
    -
    -function testLinksBetweenParentsAndChildrenAreCutOnCancel() {
    -  mockClock.install();
    -  var parent = new goog.Promise(function() {});
    -  var child = parent.then(function() {});
    -  var grandChild = child.then(function() {});
    -  assertEquals(1, child.callbackEntries_.length);
    -  assertNotNull(child.parent_);
    -  assertEquals(1, parent.callbackEntries_.length);
    -  parent.cancel();
    -  mockClock.tick();
    -  assertNull(child.parent_);
    -  assertNull(grandChild.parent_);
    -  assertEquals(null, parent.callbackEntries_);
    -  assertEquals(null, child.callbackEntries_);
    -}
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/promise/resolver.js b/src/database/third_party/closure-library/closure/goog/promise/resolver.js
    deleted file mode 100644
    index 06ee2e5d1b5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/promise/resolver.js
    +++ /dev/null
    @@ -1,48 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.promise.Resolver');
    -
    -
    -
    -/**
    - * Resolver interface for promises. The resolver is a convenience interface that
    - * bundles the promise and its associated resolve and reject functions together,
    - * for cases where the resolver needs to be persisted internally.
    - *
    - * @interface
    - * @template TYPE
    - */
    -goog.promise.Resolver = function() {};
    -
    -
    -/**
    - * The promise that created this resolver.
    - * @type {!goog.Promise<TYPE>}
    - */
    -goog.promise.Resolver.prototype.promise;
    -
    -
    -/**
    - * Resolves this resolver with the specified value.
    - * @type {function((TYPE|goog.Promise<TYPE>|Thenable)=)}
    - */
    -goog.promise.Resolver.prototype.resolve;
    -
    -
    -/**
    - * Rejects this resolver with the specified reason.
    - * @type {function(*): void}
    - */
    -goog.promise.Resolver.prototype.reject;
    diff --git a/src/database/third_party/closure-library/closure/goog/promise/testsuiteadapter.js b/src/database/third_party/closure-library/closure/goog/promise/testsuiteadapter.js
    deleted file mode 100644
    index 57e2e4ddd20..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/promise/testsuiteadapter.js
    +++ /dev/null
    @@ -1,74 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Test adapter for testing Closure Promises against the
    - * Promises/A+ Compliance Test Suite, which is implemented as a Node.js module.
    - *
    - * This test suite adapter may not be run in Node.js directly, but must first be
    - * compiled with the Closure Compiler to pull in the required dependencies.
    - *
    - * @see https://npmjs.org/package/promises-aplus-tests
    - */
    -
    -goog.provide('goog.promise.testSuiteAdapter');
    -
    -goog.require('goog.Promise');
    -
    -goog.setTestOnly('goog.promise.testSuiteAdapter');
    -
    -
    -var promisesAplusTests = /** @type {function(!Object, function(*))} */ (
    -    require('promises_aplus_tests'));
    -
    -
    -/**
    - * Adapter for specifying Promise-creating functions to the Promises test suite.
    - * @type {!Object}
    - */
    -goog.promise.testSuiteAdapter = {
    -  /** @type {function(*): !goog.Promise} */
    -  'resolved': goog.Promise.resolve,
    -
    -  /** @type {function(*): !goog.Promise} */
    -  'rejected': goog.Promise.reject,
    -
    -  /** @return {!Object} */
    -  'deferred': function() {
    -    var promiseObj = {};
    -    promiseObj['promise'] = new goog.Promise(function(resolve, reject) {
    -      promiseObj['resolve'] = resolve;
    -      promiseObj['reject'] = reject;
    -    });
    -    return promiseObj;
    -  }
    -};
    -
    -
    -// Node.js defines setTimeout globally, but Closure relies on finding it
    -// defined on goog.global.
    -goog.exportSymbol('setTimeout', setTimeout);
    -
    -
    -// Rethrowing an error to the global scope kills Node immediately. Suppress
    -// error rethrowing for running this test suite.
    -goog.Promise.setUnhandledRejectionHandler(goog.nullFunction);
    -
    -
    -// Run the tests, exiting with a failure code if any of the tests fail.
    -promisesAplusTests(goog.promise.testSuiteAdapter, function(err) {
    -  if (err) {
    -    process.exit(1);
    -  }
    -});
    diff --git a/src/database/third_party/closure-library/closure/goog/promise/thenable.js b/src/database/third_party/closure-library/closure/goog/promise/thenable.js
    deleted file mode 100644
    index 96bbf95898b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/promise/thenable.js
    +++ /dev/null
    @@ -1,111 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.Thenable');
    -
    -
    -
    -/**
    - * Provides a more strict interface for Thenables in terms of
    - * http://promisesaplus.com for interop with {@see goog.Promise}.
    - *
    - * @interface
    - * @extends {IThenable<TYPE>}
    - * @template TYPE
    - */
    -goog.Thenable = function() {};
    -
    -
    -/**
    - * Adds callbacks that will operate on the result of the Thenable, returning a
    - * new child Promise.
    - *
    - * If the Thenable is fulfilled, the {@code onFulfilled} callback will be
    - * invoked with the fulfillment value as argument, and the child Promise will
    - * be fulfilled with the return value of the callback. If the callback throws
    - * an exception, the child Promise will be rejected with the thrown value
    - * instead.
    - *
    - * If the Thenable is rejected, the {@code onRejected} callback will be invoked
    - * with the rejection reason as argument, and the child Promise will be rejected
    - * with the return value of the callback or thrown value.
    - *
    - * @param {?(function(this:THIS, TYPE):
    - *             (RESULT|IThenable<RESULT>|Thenable))=} opt_onFulfilled A
    - *     function that will be invoked with the fulfillment value if the Promise
    - *     is fullfilled.
    - * @param {?(function(this:THIS, *): *)=} opt_onRejected A function that will
    - *     be invoked with the rejection reason if the Promise is rejected.
    - * @param {THIS=} opt_context An optional context object that will be the
    - *     execution context for the callbacks. By default, functions are executed
    - *     with the default this.
    - * @return {!goog.Promise<RESULT>} A new Promise that will receive the result
    - *     of the fulfillment or rejection callback.
    - * @template RESULT,THIS
    - */
    -goog.Thenable.prototype.then = function(opt_onFulfilled, opt_onRejected,
    -    opt_context) {};
    -
    -
    -/**
    - * An expando property to indicate that an object implements
    - * {@code goog.Thenable}.
    - *
    - * {@see addImplementation}.
    - *
    - * @const
    - */
    -goog.Thenable.IMPLEMENTED_BY_PROP = '$goog_Thenable';
    -
    -
    -/**
    - * Marks a given class (constructor) as an implementation of Thenable, so
    - * that we can query that fact at runtime. The class must have already
    - * implemented the interface.
    - * Exports a 'then' method on the constructor prototype, so that the objects
    - * also implement the extern {@see goog.Thenable} interface for interop with
    - * other Promise implementations.
    - * @param {function(new:goog.Thenable,...?)} ctor The class constructor. The
    - *     corresponding class must have already implemented the interface.
    - */
    -goog.Thenable.addImplementation = function(ctor) {
    -  goog.exportProperty(ctor.prototype, 'then', ctor.prototype.then);
    -  if (COMPILED) {
    -    ctor.prototype[goog.Thenable.IMPLEMENTED_BY_PROP] = true;
    -  } else {
    -    // Avoids dictionary access in uncompiled mode.
    -    ctor.prototype.$goog_Thenable = true;
    -  }
    -};
    -
    -
    -/**
    - * @param {*} object
    - * @return {boolean} Whether a given instance implements {@code goog.Thenable}.
    - *     The class/superclass of the instance must call {@code addImplementation}.
    - */
    -goog.Thenable.isImplementedBy = function(object) {
    -  if (!object) {
    -    return false;
    -  }
    -  try {
    -    if (COMPILED) {
    -      return !!object[goog.Thenable.IMPLEMENTED_BY_PROP];
    -    }
    -    return !!object.$goog_Thenable;
    -  } catch (e) {
    -    // Property access seems to be forbidden.
    -    return false;
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/proto/proto.js b/src/database/third_party/closure-library/closure/goog/proto/proto.js
    deleted file mode 100644
    index f505760a572..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/proto/proto.js
    +++ /dev/null
    @@ -1,44 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Protocol buffer serializer.
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -goog.provide('goog.proto');
    -
    -
    -goog.require('goog.proto.Serializer');
    -
    -
    -/**
    - * Instance of the serializer object.
    - * @type {goog.proto.Serializer}
    - * @private
    - */
    -goog.proto.serializer_ = null;
    -
    -
    -/**
    - * Serializes an object or a value to a protocol buffer string.
    - * @param {Object} object The object to serialize.
    - * @return {string} The serialized protocol buffer string.
    - */
    -goog.proto.serialize = function(object) {
    -  if (!goog.proto.serializer_) {
    -    goog.proto.serializer_ = new goog.proto.Serializer;
    -  }
    -  return goog.proto.serializer_.serialize(object);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/proto/serializer.js b/src/database/third_party/closure-library/closure/goog/proto/serializer.js
    deleted file mode 100644
    index 6fe3b0de7f9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/proto/serializer.js
    +++ /dev/null
    @@ -1,70 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Protocol buffer serializer.
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -
    -// TODO(arv): Serialize booleans as 0 and 1
    -
    -
    -goog.provide('goog.proto.Serializer');
    -
    -
    -goog.require('goog.json.Serializer');
    -goog.require('goog.string');
    -
    -
    -
    -/**
    - * Object that can serialize objects or values to a protocol buffer string.
    - * @constructor
    - * @extends {goog.json.Serializer}
    - * @final
    - */
    -goog.proto.Serializer = function() {
    -  goog.json.Serializer.call(this);
    -};
    -goog.inherits(goog.proto.Serializer, goog.json.Serializer);
    -
    -
    -/**
    - * Serializes an array to a protocol buffer string. This overrides the JSON
    - * method to output empty slots when the value is null or undefined.
    - * @param {Array<*>} arr The array to serialize.
    - * @param {Array<string>} sb Array used as a string builder.
    - * @override
    - */
    -goog.proto.Serializer.prototype.serializeArray = function(arr, sb) {
    -  var l = arr.length;
    -  sb.push('[');
    -  var emptySlots = 0;
    -  var sep = '';
    -  for (var i = 0; i < l; i++) {
    -    if (arr[i] == null) { // catches undefined as well
    -      emptySlots++;
    -    } else {
    -      if (emptySlots > 0) {
    -        sb.push(goog.string.repeat(',', emptySlots));
    -        emptySlots = 0;
    -      }
    -      sb.push(sep);
    -      this.serializeInternal(arr[i], sb);
    -      sep = ',';
    -    }
    -  }
    -  sb.push(']');
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/proto/serializer_test.html b/src/database/third_party/closure-library/closure/goog/proto/serializer_test.html
    deleted file mode 100644
    index 09841cf1f49..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/proto/serializer_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.proto
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.protoTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/proto/serializer_test.js b/src/database/third_party/closure-library/closure/goog/proto/serializer_test.js
    deleted file mode 100644
    index 6965a9178f5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/proto/serializer_test.js
    +++ /dev/null
    @@ -1,38 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.protoTest');
    -goog.setTestOnly('goog.protoTest');
    -
    -goog.require('goog.proto');
    -goog.require('goog.testing.jsunit');
    -
    -var serialize = goog.proto.serialize;
    -
    -function testArraySerialize() {
    -
    -  assertEquals('Empty array', serialize([]), '[]');
    -
    -  assertEquals('Normal array', serialize([0, 1, 2]), '[0,1,2]');
    -  assertEquals('Empty start', serialize([, 1, 2]), '[,1,2]');
    -  assertEquals('Empty start', serialize([,,, 3, 4]), '[,,,3,4]');
    -  assertEquals('Empty middle', serialize([0,, 2]), '[0,,2]');
    -  assertEquals('Empty middle', serialize([0,,, 3]), '[0,,,3]');
    -  assertEquals('Empty end', serialize([0, 1, 2]), '[0,1,2]');
    -  assertEquals('Empty end', serialize([0, 1, 2,,]), '[0,1,2]');
    -  assertEquals('Empty start and end', serialize([,, 2,, 4]), '[,,2,,4]');
    -  assertEquals('All elements empty', serialize([,,,]), '[]');
    -
    -  assertEquals('Nested', serialize([, 1, [, 1, [, 1]]]), '[,1,[,1,[,1]]]');
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/proto2/descriptor.js b/src/database/third_party/closure-library/closure/goog/proto2/descriptor.js
    deleted file mode 100644
    index 16a9ef93cd6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/proto2/descriptor.js
    +++ /dev/null
    @@ -1,202 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Protocol Buffer (Message) Descriptor class.
    - */
    -
    -goog.provide('goog.proto2.Descriptor');
    -goog.provide('goog.proto2.Metadata');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.object');
    -goog.require('goog.string');
    -
    -
    -/**
    - * @typedef {{name: (string|undefined),
    - *            fullName: (string|undefined),
    - *            containingType: (goog.proto2.Message|undefined)}}
    - */
    -goog.proto2.Metadata;
    -
    -
    -
    -/**
    - * A class which describes a Protocol Buffer 2 Message.
    - *
    - * @param {function(new:goog.proto2.Message)} messageType Constructor for
    - *      the message class that this descriptor describes.
    - * @param {!goog.proto2.Metadata} metadata The metadata about the message that
    - *      will be used to construct this descriptor.
    - * @param {Array<!goog.proto2.FieldDescriptor>} fields The fields of the
    - *      message described by this descriptor.
    - *
    - * @constructor
    - * @final
    - */
    -goog.proto2.Descriptor = function(messageType, metadata, fields) {
    -
    -  /**
    -   * @type {function(new:goog.proto2.Message)}
    -   * @private
    -   */
    -  this.messageType_ = messageType;
    -
    -  /**
    -   * @type {?string}
    -   * @private
    -   */
    -  this.name_ = metadata.name || null;
    -
    -  /**
    -   * @type {?string}
    -   * @private
    -   */
    -  this.fullName_ = metadata.fullName || null;
    -
    -  /**
    -   * @type {goog.proto2.Message|undefined}
    -   * @private
    -   */
    -  this.containingType_ = metadata.containingType;
    -
    -  /**
    -   * The fields of the message described by this descriptor.
    -   * @type {!Object<number, !goog.proto2.FieldDescriptor>}
    -   * @private
    -   */
    -  this.fields_ = {};
    -
    -  for (var i = 0; i < fields.length; i++) {
    -    var field = fields[i];
    -    this.fields_[field.getTag()] = field;
    -  }
    -};
    -
    -
    -/**
    - * Returns the name of the message, if any.
    - *
    - * @return {?string} The name.
    - */
    -goog.proto2.Descriptor.prototype.getName = function() {
    -  return this.name_;
    -};
    -
    -
    -/**
    - * Returns the full name of the message, if any.
    - *
    - * @return {?string} The name.
    - */
    -goog.proto2.Descriptor.prototype.getFullName = function() {
    -  return this.fullName_;
    -};
    -
    -
    -/**
    - * Returns the descriptor of the containing message type or null if none.
    - *
    - * @return {goog.proto2.Descriptor} The descriptor.
    - */
    -goog.proto2.Descriptor.prototype.getContainingType = function() {
    -  if (!this.containingType_) {
    -    return null;
    -  }
    -
    -  return this.containingType_.getDescriptor();
    -};
    -
    -
    -/**
    - * Returns the fields in the message described by this descriptor ordered by
    - * tag.
    - *
    - * @return {!Array<!goog.proto2.FieldDescriptor>} The array of field
    - *     descriptors.
    - */
    -goog.proto2.Descriptor.prototype.getFields = function() {
    -  /**
    -   * @param {!goog.proto2.FieldDescriptor} fieldA First field.
    -   * @param {!goog.proto2.FieldDescriptor} fieldB Second field.
    -   * @return {number} Negative if fieldA's tag number is smaller, positive
    -   *     if greater, zero if the same.
    -   */
    -  function tagComparator(fieldA, fieldB) {
    -    return fieldA.getTag() - fieldB.getTag();
    -  };
    -
    -  var fields = goog.object.getValues(this.fields_);
    -  goog.array.sort(fields, tagComparator);
    -
    -  return fields;
    -};
    -
    -
    -/**
    - * Returns the fields in the message as a key/value map, where the key is
    - * the tag number of the field. DO NOT MODIFY THE RETURNED OBJECT. We return
    - * the actual, internal, fields map for performance reasons, and changing the
    - * map can result in undefined behavior of this library.
    - *
    - * @return {!Object<number, !goog.proto2.FieldDescriptor>} The field map.
    - */
    -goog.proto2.Descriptor.prototype.getFieldsMap = function() {
    -  return this.fields_;
    -};
    -
    -
    -/**
    - * Returns the field matching the given name, if any. Note that
    - * this method searches over the *original* name of the field,
    - * not the camelCase version.
    - *
    - * @param {string} name The field name for which to search.
    - *
    - * @return {goog.proto2.FieldDescriptor} The field found, if any.
    - */
    -goog.proto2.Descriptor.prototype.findFieldByName = function(name) {
    -  var valueFound = goog.object.findValue(this.fields_,
    -      function(field, key, obj) {
    -        return field.getName() == name;
    -      });
    -
    -  return /** @type {goog.proto2.FieldDescriptor} */ (valueFound) || null;
    -};
    -
    -
    -/**
    - * Returns the field matching the given tag number, if any.
    - *
    - * @param {number|string} tag The field tag number for which to search.
    - *
    - * @return {goog.proto2.FieldDescriptor} The field found, if any.
    - */
    -goog.proto2.Descriptor.prototype.findFieldByTag = function(tag) {
    -  goog.asserts.assert(goog.string.isNumeric(tag));
    -  return this.fields_[parseInt(tag, 10)] || null;
    -};
    -
    -
    -/**
    - * Creates an instance of the message type that this descriptor
    - * describes.
    - *
    - * @return {!goog.proto2.Message} The instance of the message.
    - */
    -goog.proto2.Descriptor.prototype.createMessageInstance = function() {
    -  return new this.messageType_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/proto2/descriptor_test.html b/src/database/third_party/closure-library/closure/goog/proto2/descriptor_test.html
    deleted file mode 100644
    index 69047692638..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/proto2/descriptor_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.proto2 - descriptor.js
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.proto2.DescriptorTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/proto2/descriptor_test.js b/src/database/third_party/closure-library/closure/goog/proto2/descriptor_test.js
    deleted file mode 100644
    index 48b11dbc240..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/proto2/descriptor_test.js
    +++ /dev/null
    @@ -1,78 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.proto2.DescriptorTest');
    -goog.setTestOnly('goog.proto2.DescriptorTest');
    -
    -goog.require('goog.proto2.Descriptor');
    -goog.require('goog.proto2.Message');
    -goog.require('goog.testing.jsunit');
    -
    -function testDescriptorConstruction() {
    -  var messageType = function() {};
    -  var descriptor = new goog.proto2.Descriptor(messageType, {
    -    name: 'test',
    -    fullName: 'this.is.a.test'
    -  }, []);
    -
    -  assertEquals('test', descriptor.getName());
    -  assertEquals('this.is.a.test', descriptor.getFullName());
    -  assertEquals(null, descriptor.getContainingType());
    -}
    -
    -function testParentDescriptor() {
    -  var parentType = function() {};
    -  var messageType = function() {};
    -
    -  var parentDescriptor = new goog.proto2.Descriptor(parentType, {
    -    name: 'parent',
    -    fullName: 'this.is.a.parent'
    -  }, []);
    -
    -  parentType.getDescriptor = function() {
    -    return parentDescriptor;
    -  };
    -
    -  var descriptor = new goog.proto2.Descriptor(messageType, {
    -    name: 'test',
    -    fullName: 'this.is.a.test',
    -    containingType: parentType
    -  }, []);
    -
    -  assertEquals(parentDescriptor, descriptor.getContainingType());
    -}
    -
    -function testStaticGetDescriptorCachesResults() {
    -  var messageType = function() {};
    -
    -  // This method would be provided by proto_library() BUILD rule.
    -  messageType.prototype.getDescriptor = function() {
    -    if (!messageType.descriptor_) {
    -      // The descriptor is created lazily when we instantiate a new instance.
    -      var descriptorObj = {
    -        0: {
    -          name: 'test',
    -          fullName: 'this.is.a.test'
    -        }
    -      };
    -      messageType.descriptor_ = goog.proto2.Message.createDescriptor(
    -          messageType, descriptorObj);
    -    }
    -    return messageType.descriptor_;
    -  };
    -  messageType.getDescriptor = messageType.prototype.getDescriptor;
    -
    -  var descriptor = messageType.getDescriptor();
    -  assertEquals(descriptor, messageType.getDescriptor());  // same instance
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/proto2/fielddescriptor.js b/src/database/third_party/closure-library/closure/goog/proto2/fielddescriptor.js
    deleted file mode 100644
    index 5c541a259f5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/proto2/fielddescriptor.js
    +++ /dev/null
    @@ -1,312 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Protocol Buffer Field Descriptor class.
    - */
    -
    -goog.provide('goog.proto2.FieldDescriptor');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.string');
    -
    -
    -
    -/**
    - * A class which describes a field in a Protocol Buffer 2 Message.
    - *
    - * @param {function(new:goog.proto2.Message)} messageType Constructor for the
    - *     message class to which the field described by this class belongs.
    - * @param {number|string} tag The field's tag index.
    - * @param {Object} metadata The metadata about this field that will be used
    - *     to construct this descriptor.
    - *
    - * @constructor
    - * @final
    - */
    -goog.proto2.FieldDescriptor = function(messageType, tag, metadata) {
    -  /**
    -   * The message type that contains the field that this
    -   * descriptor describes.
    -   * @private {function(new:goog.proto2.Message)}
    -   */
    -  this.parent_ = messageType;
    -
    -  // Ensure that the tag is numeric.
    -  goog.asserts.assert(goog.string.isNumeric(tag));
    -
    -  /**
    -   * The field's tag number.
    -   * @private {number}
    -   */
    -  this.tag_ = /** @type {number} */ (tag);
    -
    -  /**
    -   * The field's name.
    -   * @private {string}
    -   */
    -  this.name_ = metadata.name;
    -
    -  /** @type {goog.proto2.FieldDescriptor.FieldType} */
    -  metadata.fieldType;
    -
    -  /** @type {*} */
    -  metadata.repeated;
    -
    -  /** @type {*} */
    -  metadata.required;
    -
    -  /** @type {*} */
    -  metadata.packed;
    -
    -  /**
    -   * If true, this field is a packed field.
    -   * @private {boolean}
    -   */
    -  this.isPacked_ = !!metadata.packed;
    -
    -  /**
    -   * If true, this field is a repeating field.
    -   * @private {boolean}
    -   */
    -  this.isRepeated_ = !!metadata.repeated;
    -
    -  /**
    -   * If true, this field is required.
    -   * @private {boolean}
    -   */
    -  this.isRequired_ = !!metadata.required;
    -
    -  /**
    -   * The field type of this field.
    -   * @private {goog.proto2.FieldDescriptor.FieldType}
    -   */
    -  this.fieldType_ = metadata.fieldType;
    -
    -  /**
    -   * If this field is a primitive: The native (ECMAScript) type of this field.
    -   * If an enumeration: The enumeration object.
    -   * If a message or group field: The Message function.
    -   * @private {Function}
    -   */
    -  this.nativeType_ = metadata.type;
    -
    -  /**
    -   * Is it permissible on deserialization to convert between numbers and
    -   * well-formed strings?  Is true for 64-bit integral field types and float and
    -   * double types, false for all other field types.
    -   * @private {boolean}
    -   */
    -  this.deserializationConversionPermitted_ = false;
    -
    -  switch (this.fieldType_) {
    -    case goog.proto2.FieldDescriptor.FieldType.INT64:
    -    case goog.proto2.FieldDescriptor.FieldType.UINT64:
    -    case goog.proto2.FieldDescriptor.FieldType.FIXED64:
    -    case goog.proto2.FieldDescriptor.FieldType.SFIXED64:
    -    case goog.proto2.FieldDescriptor.FieldType.SINT64:
    -    case goog.proto2.FieldDescriptor.FieldType.FLOAT:
    -    case goog.proto2.FieldDescriptor.FieldType.DOUBLE:
    -      this.deserializationConversionPermitted_ = true;
    -      break;
    -  }
    -
    -  /**
    -   * The default value of this field, if different from the default, default
    -   * value.
    -   * @private {*}
    -   */
    -  this.defaultValue_ = metadata.defaultValue;
    -};
    -
    -
    -/**
    - * An enumeration defining the possible field types.
    - * Should be a mirror of that defined in descriptor.h.
    - *
    - * @enum {number}
    - */
    -goog.proto2.FieldDescriptor.FieldType = {
    -  DOUBLE: 1,
    -  FLOAT: 2,
    -  INT64: 3,
    -  UINT64: 4,
    -  INT32: 5,
    -  FIXED64: 6,
    -  FIXED32: 7,
    -  BOOL: 8,
    -  STRING: 9,
    -  GROUP: 10,
    -  MESSAGE: 11,
    -  BYTES: 12,
    -  UINT32: 13,
    -  ENUM: 14,
    -  SFIXED32: 15,
    -  SFIXED64: 16,
    -  SINT32: 17,
    -  SINT64: 18
    -};
    -
    -
    -/**
    - * Returns the tag of the field that this descriptor represents.
    - *
    - * @return {number} The tag number.
    - */
    -goog.proto2.FieldDescriptor.prototype.getTag = function() {
    -  return this.tag_;
    -};
    -
    -
    -/**
    - * Returns the descriptor describing the message that defined this field.
    - * @return {!goog.proto2.Descriptor} The descriptor.
    - */
    -goog.proto2.FieldDescriptor.prototype.getContainingType = function() {
    -  // Generated JS proto_library messages have getDescriptor() method which can
    -  // be called with or without an instance.
    -  return this.parent_.prototype.getDescriptor();
    -};
    -
    -
    -/**
    - * Returns the name of the field that this descriptor represents.
    - * @return {string} The name.
    - */
    -goog.proto2.FieldDescriptor.prototype.getName = function() {
    -  return this.name_;
    -};
    -
    -
    -/**
    - * Returns the default value of this field.
    - * @return {*} The default value.
    - */
    -goog.proto2.FieldDescriptor.prototype.getDefaultValue = function() {
    -  if (this.defaultValue_ === undefined) {
    -    // Set the default value based on a new instance of the native type.
    -    // This will be (0, false, "") for (number, boolean, string) and will
    -    // be a new instance of a group/message if the field is a message type.
    -    var nativeType = this.nativeType_;
    -    if (nativeType === Boolean) {
    -      this.defaultValue_ = false;
    -    } else if (nativeType === Number) {
    -      this.defaultValue_ = 0;
    -    } else if (nativeType === String) {
    -      if (this.deserializationConversionPermitted_) {
    -        // This field is a 64 bit integer represented as a string.
    -        this.defaultValue_ = '0';
    -      } else {
    -        this.defaultValue_ = '';
    -      }
    -    } else {
    -      return new nativeType;
    -    }
    -  }
    -
    -  return this.defaultValue_;
    -};
    -
    -
    -/**
    - * Returns the field type of the field described by this descriptor.
    - * @return {goog.proto2.FieldDescriptor.FieldType} The field type.
    - */
    -goog.proto2.FieldDescriptor.prototype.getFieldType = function() {
    -  return this.fieldType_;
    -};
    -
    -
    -/**
    - * Returns the native (i.e. ECMAScript) type of the field described by this
    - * descriptor.
    - *
    - * @return {Object} The native type.
    - */
    -goog.proto2.FieldDescriptor.prototype.getNativeType = function() {
    -  return this.nativeType_;
    -};
    -
    -
    -/**
    - * Returns true if simple conversions between numbers and strings are permitted
    - * during deserialization for this field.
    - *
    - * @return {boolean} Whether conversion is permitted.
    - */
    -goog.proto2.FieldDescriptor.prototype.deserializationConversionPermitted =
    -    function() {
    -  return this.deserializationConversionPermitted_;
    -};
    -
    -
    -/**
    - * Returns the descriptor of the message type of this field. Only valid
    - * for fields of type GROUP and MESSAGE.
    - *
    - * @return {!goog.proto2.Descriptor} The message descriptor.
    - */
    -goog.proto2.FieldDescriptor.prototype.getFieldMessageType = function() {
    -  // Generated JS proto_library messages have getDescriptor() method which can
    -  // be called with or without an instance.
    -  var messageClass = /** @type {function(new:goog.proto2.Message)} */(
    -      this.nativeType_);
    -  return messageClass.prototype.getDescriptor();
    -};
    -
    -
    -/**
    - * @return {boolean} True if the field stores composite data or repeated
    - *     composite data (message or group).
    - */
    -goog.proto2.FieldDescriptor.prototype.isCompositeType = function() {
    -  return this.fieldType_ == goog.proto2.FieldDescriptor.FieldType.MESSAGE ||
    -      this.fieldType_ == goog.proto2.FieldDescriptor.FieldType.GROUP;
    -};
    -
    -
    -/**
    - * Returns whether the field described by this descriptor is packed.
    - * @return {boolean} Whether the field is packed.
    - */
    -goog.proto2.FieldDescriptor.prototype.isPacked = function() {
    -  return this.isPacked_;
    -};
    -
    -
    -/**
    - * Returns whether the field described by this descriptor is repeating.
    - * @return {boolean} Whether the field is repeated.
    - */
    -goog.proto2.FieldDescriptor.prototype.isRepeated = function() {
    -  return this.isRepeated_;
    -};
    -
    -
    -/**
    - * Returns whether the field described by this descriptor is required.
    - * @return {boolean} Whether the field is required.
    - */
    -goog.proto2.FieldDescriptor.prototype.isRequired = function() {
    -  return this.isRequired_;
    -};
    -
    -
    -/**
    - * Returns whether the field described by this descriptor is optional.
    - * @return {boolean} Whether the field is optional.
    - */
    -goog.proto2.FieldDescriptor.prototype.isOptional = function() {
    -  return !this.isRepeated_ && !this.isRequired_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/proto2/fielddescriptor_test.html b/src/database/third_party/closure-library/closure/goog/proto2/fielddescriptor_test.html
    deleted file mode 100644
    index 6e67ec7cc8d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/proto2/fielddescriptor_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.proto2 - fielddescriptor.js
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.proto2.FieldDescriptorTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/proto2/fielddescriptor_test.js b/src/database/third_party/closure-library/closure/goog/proto2/fielddescriptor_test.js
    deleted file mode 100644
    index f09aff64655..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/proto2/fielddescriptor_test.js
    +++ /dev/null
    @@ -1,147 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.proto2.FieldDescriptorTest');
    -goog.setTestOnly('goog.proto2.FieldDescriptorTest');
    -
    -goog.require('goog.proto2.FieldDescriptor');
    -goog.require('goog.proto2.Message');
    -goog.require('goog.testing.jsunit');
    -
    -function testFieldDescriptorConstruction() {
    -  var messageType = {};
    -  var fieldDescriptor = new goog.proto2.FieldDescriptor(messageType, 10, {
    -    name: 'test',
    -    repeated: true,
    -    packed: true,
    -    fieldType: goog.proto2.FieldDescriptor.FieldType.INT32,
    -    type: Number
    -  });
    -
    -  assertEquals(10, fieldDescriptor.getTag());
    -  assertEquals('test', fieldDescriptor.getName());
    -
    -  assertEquals(true, fieldDescriptor.isRepeated());
    -
    -  assertEquals(true, fieldDescriptor.isPacked());
    -
    -  assertEquals(goog.proto2.FieldDescriptor.FieldType.INT32,
    -      fieldDescriptor.getFieldType());
    -  assertEquals(Number, fieldDescriptor.getNativeType());
    -  assertEquals(0, fieldDescriptor.getDefaultValue());
    -}
    -
    -function testGetDefaultValueOfString() {
    -  var fieldDescriptor = new goog.proto2.FieldDescriptor({}, 10, {
    -    name: 'test',
    -    fieldType: goog.proto2.FieldDescriptor.FieldType.STRING,
    -    type: String
    -  });
    -
    -  assertEquals('', fieldDescriptor.getDefaultValue());
    -}
    -
    -function testGetDefaultValueOfBool() {
    -  var fieldDescriptor = new goog.proto2.FieldDescriptor({}, 10, {
    -    name: 'test',
    -    fieldType: goog.proto2.FieldDescriptor.FieldType.BOOL,
    -    type: Boolean
    -  });
    -
    -  assertEquals(false, fieldDescriptor.getDefaultValue());
    -}
    -
    -function testGetDefaultValueOfInt64() {
    -  var fieldDescriptor = new goog.proto2.FieldDescriptor({}, 10, {
    -    name: 'test',
    -    fieldType: goog.proto2.FieldDescriptor.FieldType.INT64,
    -    type: String
    -  });
    -
    -  assertEquals('0', fieldDescriptor.getDefaultValue());
    -}
    -
    -function testRepeatedField() {
    -  var messageType = {};
    -  var fieldDescriptor = new goog.proto2.FieldDescriptor(messageType, 10, {
    -    name: 'test',
    -    repeated: true,
    -    fieldType: 7,
    -    type: Number
    -  });
    -
    -  assertEquals(true, fieldDescriptor.isRepeated());
    -  assertEquals(false, fieldDescriptor.isRequired());
    -  assertEquals(false, fieldDescriptor.isOptional());
    -}
    -
    -function testRequiredField() {
    -  var messageType = {};
    -  var fieldDescriptor = new goog.proto2.FieldDescriptor(messageType, 10, {
    -    name: 'test',
    -    required: true,
    -    fieldType: 7,
    -    type: Number
    -  });
    -
    -  assertEquals(false, fieldDescriptor.isRepeated());
    -  assertEquals(true, fieldDescriptor.isRequired());
    -  assertEquals(false, fieldDescriptor.isOptional());
    -}
    -
    -function testOptionalField() {
    -  var messageType = {};
    -  var fieldDescriptor = new goog.proto2.FieldDescriptor(messageType, 10, {
    -    name: 'test',
    -    fieldType: 7,
    -    type: Number
    -  });
    -
    -  assertEquals(false, fieldDescriptor.isRepeated());
    -  assertEquals(false, fieldDescriptor.isRequired());
    -  assertEquals(true, fieldDescriptor.isOptional());
    -}
    -
    -function testContaingType() {
    -  var MessageType = function() {
    -    MessageType.base(this, 'constructor');
    -  };
    -  goog.inherits(MessageType, goog.proto2.Message);
    -
    -  MessageType.getDescriptor = function() {
    -    if (!MessageType.descriptor_) {
    -      // The descriptor is created lazily when we instantiate a new instance.
    -      var descriptorObj = {
    -        0: {
    -          name: 'test_message',
    -          fullName: 'this.is.a.test_message'
    -        },
    -        10: {
    -          name: 'test',
    -          fieldType: 7,
    -          type: Number
    -        }
    -      };
    -      MessageType.descriptor_ = goog.proto2.Message.createDescriptor(
    -          MessageType, descriptorObj);
    -    }
    -    return MessageType.descriptor_;
    -  };
    -  MessageType.prototype.getDescriptor = MessageType.getDescriptor;
    -
    -  var descriptor = MessageType.getDescriptor();
    -  var fieldDescriptor = descriptor.getFields()[0];
    -  assertEquals('10', fieldDescriptor.getTag());
    -  assertEquals(descriptor, fieldDescriptor.getContainingType());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/proto2/lazydeserializer.js b/src/database/third_party/closure-library/closure/goog/proto2/lazydeserializer.js
    deleted file mode 100644
    index 270e6ace02b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/proto2/lazydeserializer.js
    +++ /dev/null
    @@ -1,70 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Base class for all PB2 lazy deserializer. A lazy deserializer
    - *   is a serializer whose deserialization occurs on the fly as data is
    - *   requested. In order to use a lazy deserializer, the serialized form
    - *   of the data must be an object or array that can be indexed by the tag
    - *   number.
    - *
    - */
    -
    -goog.provide('goog.proto2.LazyDeserializer');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.proto2.Message');
    -goog.require('goog.proto2.Serializer');
    -
    -
    -
    -/**
    - * Base class for all lazy deserializers.
    - *
    - * @constructor
    - * @extends {goog.proto2.Serializer}
    - */
    -goog.proto2.LazyDeserializer = function() {};
    -goog.inherits(goog.proto2.LazyDeserializer, goog.proto2.Serializer);
    -
    -
    -/** @override */
    -goog.proto2.LazyDeserializer.prototype.deserialize =
    -    function(descriptor, data) {
    -  var message = descriptor.createMessageInstance();
    -  message.initializeForLazyDeserializer(this, data);
    -  goog.asserts.assert(message instanceof goog.proto2.Message);
    -  return message;
    -};
    -
    -
    -/** @override */
    -goog.proto2.LazyDeserializer.prototype.deserializeTo = function(message, data) {
    -  throw new Error('Unimplemented');
    -};
    -
    -
    -/**
    - * Deserializes a message field from the expected format and places the
    - * data in the given message
    - *
    - * @param {goog.proto2.Message} message The message in which to
    - *     place the information.
    - * @param {goog.proto2.FieldDescriptor} field The field for which to set the
    - *     message value.
    - * @param {*} data The serialized data for the field.
    - *
    - * @return {*} The deserialized data or null for no value found.
    - */
    -goog.proto2.LazyDeserializer.prototype.deserializeField = goog.abstractMethod;
    diff --git a/src/database/third_party/closure-library/closure/goog/proto2/message.js b/src/database/third_party/closure-library/closure/goog/proto2/message.js
    deleted file mode 100644
    index 8d1b4151149..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/proto2/message.js
    +++ /dev/null
    @@ -1,722 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Protocol Buffer Message base class.
    - */
    -
    -goog.provide('goog.proto2.Message');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.proto2.Descriptor');
    -goog.require('goog.proto2.FieldDescriptor');
    -
    -
    -
    -/**
    - * Abstract base class for all Protocol Buffer 2 messages. It will be
    - * subclassed in the code generated by the Protocol Compiler. Any other
    - * subclasses are prohibited.
    - * @constructor
    - */
    -goog.proto2.Message = function() {
    -  /**
    -   * Stores the field values in this message. Keyed by the tag of the fields.
    -   * @type {*}
    -   * @private
    -   */
    -  this.values_ = {};
    -
    -  /**
    -   * Stores the field information (i.e. metadata) about this message.
    -   * @type {Object<number, !goog.proto2.FieldDescriptor>}
    -   * @private
    -   */
    -  this.fields_ = this.getDescriptor().getFieldsMap();
    -
    -  /**
    -   * The lazy deserializer for this message instance, if any.
    -   * @type {goog.proto2.LazyDeserializer}
    -   * @private
    -   */
    -  this.lazyDeserializer_ = null;
    -
    -  /**
    -   * A map of those fields deserialized, from tag number to their deserialized
    -   * value.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.deserializedFields_ = null;
    -};
    -
    -
    -/**
    - * An enumeration defining the possible field types.
    - * Should be a mirror of that defined in descriptor.h.
    - *
    - * TODO(user): Remove this alias.  The code generator generates code that
    - * references this enum, so it needs to exist until the code generator is
    - * changed.  The enum was moved to from Message to FieldDescriptor to avoid a
    - * dependency cycle.
    - *
    - * Use goog.proto2.FieldDescriptor.FieldType instead.
    - *
    - * @enum {number}
    - */
    -goog.proto2.Message.FieldType = {
    -  DOUBLE: 1,
    -  FLOAT: 2,
    -  INT64: 3,
    -  UINT64: 4,
    -  INT32: 5,
    -  FIXED64: 6,
    -  FIXED32: 7,
    -  BOOL: 8,
    -  STRING: 9,
    -  GROUP: 10,
    -  MESSAGE: 11,
    -  BYTES: 12,
    -  UINT32: 13,
    -  ENUM: 14,
    -  SFIXED32: 15,
    -  SFIXED64: 16,
    -  SINT32: 17,
    -  SINT64: 18
    -};
    -
    -
    -/**
    - * All instances of goog.proto2.Message should have a static descriptor_
    - * property. The Descriptor will be deserialized lazily in the getDescriptor()
    - * method.
    - *
    - * This declaration is just here for documentation purposes.
    - * goog.proto2.Message does not have its own descriptor.
    - *
    - * @type {undefined}
    - * @private
    - */
    -goog.proto2.Message.descriptor_;
    -
    -
    -/**
    - * Initializes the message with a lazy deserializer and its associated data.
    - * This method should be called by internal methods ONLY.
    - *
    - * @param {goog.proto2.LazyDeserializer} deserializer The lazy deserializer to
    - *   use to decode the data on the fly.
    - *
    - * @param {*} data The data to decode/deserialize.
    - */
    -goog.proto2.Message.prototype.initializeForLazyDeserializer = function(
    -    deserializer, data) {
    -
    -  this.lazyDeserializer_ = deserializer;
    -  this.values_ = data;
    -  this.deserializedFields_ = {};
    -};
    -
    -
    -/**
    - * Sets the value of an unknown field, by tag.
    - *
    - * @param {number} tag The tag of an unknown field (must be >= 1).
    - * @param {*} value The value for that unknown field.
    - */
    -goog.proto2.Message.prototype.setUnknown = function(tag, value) {
    -  goog.asserts.assert(!this.fields_[tag],
    -      'Field is not unknown in this message');
    -  goog.asserts.assert(tag >= 1, 'Tag is not valid');
    -  goog.asserts.assert(value !== null, 'Value cannot be null');
    -
    -  this.values_[tag] = value;
    -  if (this.deserializedFields_) {
    -    delete this.deserializedFields_[tag];
    -  }
    -};
    -
    -
    -/**
    - * Iterates over all the unknown fields in the message.
    - *
    - * @param {function(number, *)} callback A callback method
    - *     which gets invoked for each unknown field.
    - * @param {Object=} opt_scope The scope under which to execute the callback.
    - *     If not given, the current message will be used.
    - */
    -goog.proto2.Message.prototype.forEachUnknown = function(callback, opt_scope) {
    -  var scope = opt_scope || this;
    -  for (var key in this.values_) {
    -    var keyNum = Number(key);
    -    if (!this.fields_[keyNum]) {
    -      callback.call(scope, keyNum, this.values_[key]);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Returns the descriptor which describes the current message.
    - *
    - * This only works if we assume people never subclass protobufs.
    - *
    - * @return {!goog.proto2.Descriptor} The descriptor.
    - */
    -goog.proto2.Message.prototype.getDescriptor = goog.abstractMethod;
    -
    -
    -/**
    - * Returns whether there is a value stored at the field specified by the
    - * given field descriptor.
    - *
    - * @param {goog.proto2.FieldDescriptor} field The field for which to check
    - *     if there is a value.
    - *
    - * @return {boolean} True if a value was found.
    - */
    -goog.proto2.Message.prototype.has = function(field) {
    -  goog.asserts.assert(
    -      field.getContainingType() == this.getDescriptor(),
    -      'The current message does not contain the given field');
    -
    -  return this.has$Value(field.getTag());
    -};
    -
    -
    -/**
    - * Returns the array of values found for the given repeated field.
    - *
    - * @param {goog.proto2.FieldDescriptor} field The field for which to
    - *     return the values.
    - *
    - * @return {!Array<?>} The values found.
    - */
    -goog.proto2.Message.prototype.arrayOf = function(field) {
    -  goog.asserts.assert(
    -      field.getContainingType() == this.getDescriptor(),
    -      'The current message does not contain the given field');
    -
    -  return this.array$Values(field.getTag());
    -};
    -
    -
    -/**
    - * Returns the number of values stored in the given field.
    - *
    - * @param {goog.proto2.FieldDescriptor} field The field for which to count
    - *     the number of values.
    - *
    - * @return {number} The count of the values in the given field.
    - */
    -goog.proto2.Message.prototype.countOf = function(field) {
    -  goog.asserts.assert(
    -      field.getContainingType() == this.getDescriptor(),
    -      'The current message does not contain the given field');
    -
    -  return this.count$Values(field.getTag());
    -};
    -
    -
    -/**
    - * Returns the value stored at the field specified by the
    - * given field descriptor.
    - *
    - * @param {goog.proto2.FieldDescriptor} field The field for which to get the
    - *     value.
    - * @param {number=} opt_index If the field is repeated, the index to use when
    - *     looking up the value.
    - *
    - * @return {*} The value found or null if none.
    - */
    -goog.proto2.Message.prototype.get = function(field, opt_index) {
    -  goog.asserts.assert(
    -      field.getContainingType() == this.getDescriptor(),
    -      'The current message does not contain the given field');
    -
    -  return this.get$Value(field.getTag(), opt_index);
    -};
    -
    -
    -/**
    - * Returns the value stored at the field specified by the
    - * given field descriptor or the default value if none exists.
    - *
    - * @param {goog.proto2.FieldDescriptor} field The field for which to get the
    - *     value.
    - * @param {number=} opt_index If the field is repeated, the index to use when
    - *     looking up the value.
    - *
    - * @return {*} The value found or the default if none.
    - */
    -goog.proto2.Message.prototype.getOrDefault = function(field, opt_index) {
    -  goog.asserts.assert(
    -      field.getContainingType() == this.getDescriptor(),
    -      'The current message does not contain the given field');
    -
    -  return this.get$ValueOrDefault(field.getTag(), opt_index);
    -};
    -
    -
    -/**
    - * Stores the given value to the field specified by the
    - * given field descriptor. Note that the field must not be repeated.
    - *
    - * @param {goog.proto2.FieldDescriptor} field The field for which to set
    - *     the value.
    - * @param {*} value The new value for the field.
    - */
    -goog.proto2.Message.prototype.set = function(field, value) {
    -  goog.asserts.assert(
    -      field.getContainingType() == this.getDescriptor(),
    -      'The current message does not contain the given field');
    -
    -  this.set$Value(field.getTag(), value);
    -};
    -
    -
    -/**
    - * Adds the given value to the field specified by the
    - * given field descriptor. Note that the field must be repeated.
    - *
    - * @param {goog.proto2.FieldDescriptor} field The field in which to add the
    - *     the value.
    - * @param {*} value The new value to add to the field.
    - */
    -goog.proto2.Message.prototype.add = function(field, value) {
    -  goog.asserts.assert(
    -      field.getContainingType() == this.getDescriptor(),
    -      'The current message does not contain the given field');
    -
    -  this.add$Value(field.getTag(), value);
    -};
    -
    -
    -/**
    - * Clears the field specified.
    - *
    - * @param {goog.proto2.FieldDescriptor} field The field to clear.
    - */
    -goog.proto2.Message.prototype.clear = function(field) {
    -  goog.asserts.assert(
    -      field.getContainingType() == this.getDescriptor(),
    -      'The current message does not contain the given field');
    -
    -  this.clear$Field(field.getTag());
    -};
    -
    -
    -/**
    - * Compares this message with another one ignoring the unknown fields.
    - * @param {*} other The other message.
    - * @return {boolean} Whether they are equal. Returns false if the {@code other}
    - *     argument is a different type of message or not a message.
    - */
    -goog.proto2.Message.prototype.equals = function(other) {
    -  if (!other || this.constructor != other.constructor) {
    -    return false;
    -  }
    -
    -  var fields = this.getDescriptor().getFields();
    -  for (var i = 0; i < fields.length; i++) {
    -    var field = fields[i];
    -    var tag = field.getTag();
    -    if (this.has$Value(tag) != other.has$Value(tag)) {
    -      return false;
    -    }
    -
    -    if (this.has$Value(tag)) {
    -      var isComposite = field.isCompositeType();
    -
    -      var fieldsEqual = function(value1, value2) {
    -        return isComposite ? value1.equals(value2) : value1 == value2;
    -      };
    -
    -      var thisValue = this.getValueForTag_(tag);
    -      var otherValue = other.getValueForTag_(tag);
    -
    -      if (field.isRepeated()) {
    -        // In this case thisValue and otherValue are arrays.
    -        if (thisValue.length != otherValue.length) {
    -          return false;
    -        }
    -        for (var j = 0; j < thisValue.length; j++) {
    -          if (!fieldsEqual(thisValue[j], otherValue[j])) {
    -            return false;
    -          }
    -        }
    -      } else if (!fieldsEqual(thisValue, otherValue)) {
    -        return false;
    -      }
    -    }
    -  }
    -
    -  return true;
    -};
    -
    -
    -/**
    - * Recursively copies the known fields from the given message to this message.
    - * Removes the fields which are not present in the source message.
    - * @param {!goog.proto2.Message} message The source message.
    - */
    -goog.proto2.Message.prototype.copyFrom = function(message) {
    -  goog.asserts.assert(this.constructor == message.constructor,
    -      'The source message must have the same type.');
    -
    -  if (this != message) {
    -    this.values_ = {};
    -    if (this.deserializedFields_) {
    -      this.deserializedFields_ = {};
    -    }
    -    this.mergeFrom(message);
    -  }
    -};
    -
    -
    -/**
    - * Merges the given message into this message.
    - *
    - * Singular fields will be overwritten, except for embedded messages which will
    - * be merged. Repeated fields will be concatenated.
    - * @param {!goog.proto2.Message} message The source message.
    - */
    -goog.proto2.Message.prototype.mergeFrom = function(message) {
    -  goog.asserts.assert(this.constructor == message.constructor,
    -      'The source message must have the same type.');
    -  var fields = this.getDescriptor().getFields();
    -
    -  for (var i = 0; i < fields.length; i++) {
    -    var field = fields[i];
    -    var tag = field.getTag();
    -    if (message.has$Value(tag)) {
    -      if (this.deserializedFields_) {
    -        delete this.deserializedFields_[field.getTag()];
    -      }
    -
    -      var isComposite = field.isCompositeType();
    -      if (field.isRepeated()) {
    -        var values = message.array$Values(tag);
    -        for (var j = 0; j < values.length; j++) {
    -          this.add$Value(tag, isComposite ? values[j].clone() : values[j]);
    -        }
    -      } else {
    -        var value = message.getValueForTag_(tag);
    -        if (isComposite) {
    -          var child = this.getValueForTag_(tag);
    -          if (child) {
    -            child.mergeFrom(value);
    -          } else {
    -            this.set$Value(tag, value.clone());
    -          }
    -        } else {
    -          this.set$Value(tag, value);
    -        }
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * @return {!goog.proto2.Message} Recursive clone of the message only including
    - *     the known fields.
    - */
    -goog.proto2.Message.prototype.clone = function() {
    -  /** @type {!goog.proto2.Message} */
    -  var clone = new this.constructor;
    -  clone.copyFrom(this);
    -  return clone;
    -};
    -
    -
    -/**
    - * Fills in the protocol buffer with default values. Any fields that are
    - * already set will not be overridden.
    - * @param {boolean} simpleFieldsToo If true, all fields will be initialized;
    - *     if false, only the nested messages and groups.
    - */
    -goog.proto2.Message.prototype.initDefaults = function(simpleFieldsToo) {
    -  var fields = this.getDescriptor().getFields();
    -  for (var i = 0; i < fields.length; i++) {
    -    var field = fields[i];
    -    var tag = field.getTag();
    -    var isComposite = field.isCompositeType();
    -
    -    // Initialize missing fields.
    -    if (!this.has$Value(tag) && !field.isRepeated()) {
    -      if (isComposite) {
    -        this.values_[tag] = new /** @type {Function} */ (field.getNativeType());
    -      } else if (simpleFieldsToo) {
    -        this.values_[tag] = field.getDefaultValue();
    -      }
    -    }
    -
    -    // Fill in the existing composite fields recursively.
    -    if (isComposite) {
    -      if (field.isRepeated()) {
    -        var values = this.array$Values(tag);
    -        for (var j = 0; j < values.length; j++) {
    -          values[j].initDefaults(simpleFieldsToo);
    -        }
    -      } else {
    -        this.get$Value(tag).initDefaults(simpleFieldsToo);
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Returns the whether or not the field indicated by the given tag
    - * has a value.
    - *
    - * GENERATED CODE USE ONLY. Basis of the has{Field} methods.
    - *
    - * @param {number} tag The tag.
    - *
    - * @return {boolean} Whether the message has a value for the field.
    - */
    -goog.proto2.Message.prototype.has$Value = function(tag) {
    -  return this.values_[tag] != null;
    -};
    -
    -
    -/**
    - * Returns the value for the given tag number. If a lazy deserializer is
    - * instantiated, lazily deserializes the field if required before returning the
    - * value.
    - *
    - * @param {number} tag The tag number.
    - * @return {*} The corresponding value, if any.
    - * @private
    - */
    -goog.proto2.Message.prototype.getValueForTag_ = function(tag) {
    -  // Retrieve the current value, which may still be serialized.
    -  var value = this.values_[tag];
    -  if (!goog.isDefAndNotNull(value)) {
    -    return null;
    -  }
    -
    -  // If we have a lazy deserializer, then ensure that the field is
    -  // properly deserialized.
    -  if (this.lazyDeserializer_) {
    -    // If the tag is not deserialized, then we must do so now. Deserialize
    -    // the field's value via the deserializer.
    -    if (!(tag in this.deserializedFields_)) {
    -      var deserializedValue = this.lazyDeserializer_.deserializeField(
    -          this, this.fields_[tag], value);
    -      this.deserializedFields_[tag] = deserializedValue;
    -      return deserializedValue;
    -    }
    -
    -    return this.deserializedFields_[tag];
    -  }
    -
    -  // Otherwise, just return the value.
    -  return value;
    -};
    -
    -
    -/**
    - * Gets the value at the field indicated by the given tag.
    - *
    - * GENERATED CODE USE ONLY. Basis of the get{Field} methods.
    - *
    - * @param {number} tag The field's tag index.
    - * @param {number=} opt_index If the field is a repeated field, the index
    - *     at which to get the value.
    - *
    - * @return {*} The value found or null for none.
    - * @protected
    - */
    -goog.proto2.Message.prototype.get$Value = function(tag, opt_index) {
    -  var value = this.getValueForTag_(tag);
    -
    -  if (this.fields_[tag].isRepeated()) {
    -    var index = opt_index || 0;
    -    goog.asserts.assert(
    -        index >= 0 && index < value.length,
    -        'Given index %s is out of bounds.  Repeated field length: %s',
    -        index, value.length);
    -    return value[index];
    -  }
    -
    -  return value;
    -};
    -
    -
    -/**
    - * Gets the value at the field indicated by the given tag or the default value
    - * if none.
    - *
    - * GENERATED CODE USE ONLY. Basis of the get{Field} methods.
    - *
    - * @param {number} tag The field's tag index.
    - * @param {number=} opt_index If the field is a repeated field, the index
    - *     at which to get the value.
    - *
    - * @return {*} The value found or the default value if none set.
    - * @protected
    - */
    -goog.proto2.Message.prototype.get$ValueOrDefault = function(tag, opt_index) {
    -  if (!this.has$Value(tag)) {
    -    // Return the default value.
    -    var field = this.fields_[tag];
    -    return field.getDefaultValue();
    -  }
    -
    -  return this.get$Value(tag, opt_index);
    -};
    -
    -
    -/**
    - * Gets the values at the field indicated by the given tag.
    - *
    - * GENERATED CODE USE ONLY. Basis of the {field}Array methods.
    - *
    - * @param {number} tag The field's tag index.
    - *
    - * @return {!Array<*>} The values found. If none, returns an empty array.
    - * @protected
    - */
    -goog.proto2.Message.prototype.array$Values = function(tag) {
    -  var value = this.getValueForTag_(tag);
    -  return /** @type {Array<*>} */ (value) || [];
    -};
    -
    -
    -/**
    - * Returns the number of values stored in the field by the given tag.
    - *
    - * GENERATED CODE USE ONLY. Basis of the {field}Count methods.
    - *
    - * @param {number} tag The tag.
    - *
    - * @return {number} The number of values.
    - * @protected
    - */
    -goog.proto2.Message.prototype.count$Values = function(tag) {
    -  var field = this.fields_[tag];
    -  if (field.isRepeated()) {
    -    return this.has$Value(tag) ? this.values_[tag].length : 0;
    -  } else {
    -    return this.has$Value(tag) ? 1 : 0;
    -  }
    -};
    -
    -
    -/**
    - * Sets the value of the *non-repeating* field indicated by the given tag.
    - *
    - * GENERATED CODE USE ONLY. Basis of the set{Field} methods.
    - *
    - * @param {number} tag The field's tag index.
    - * @param {*} value The field's value.
    - * @protected
    - */
    -goog.proto2.Message.prototype.set$Value = function(tag, value) {
    -  if (goog.asserts.ENABLE_ASSERTS) {
    -    var field = this.fields_[tag];
    -    this.checkFieldType_(field, value);
    -  }
    -
    -  this.values_[tag] = value;
    -  if (this.deserializedFields_) {
    -    this.deserializedFields_[tag] = value;
    -  }
    -};
    -
    -
    -/**
    - * Adds the value to the *repeating* field indicated by the given tag.
    - *
    - * GENERATED CODE USE ONLY. Basis of the add{Field} methods.
    - *
    - * @param {number} tag The field's tag index.
    - * @param {*} value The value to add.
    - * @protected
    - */
    -goog.proto2.Message.prototype.add$Value = function(tag, value) {
    -  if (goog.asserts.ENABLE_ASSERTS) {
    -    var field = this.fields_[tag];
    -    this.checkFieldType_(field, value);
    -  }
    -
    -  if (!this.values_[tag]) {
    -    this.values_[tag] = [];
    -  }
    -
    -  this.values_[tag].push(value);
    -  if (this.deserializedFields_) {
    -    delete this.deserializedFields_[tag];
    -  }
    -};
    -
    -
    -/**
    - * Ensures that the value being assigned to the given field
    - * is valid.
    - *
    - * @param {!goog.proto2.FieldDescriptor} field The field being assigned.
    - * @param {*} value The value being assigned.
    - * @private
    - */
    -goog.proto2.Message.prototype.checkFieldType_ = function(field, value) {
    -  if (field.getFieldType() == goog.proto2.FieldDescriptor.FieldType.ENUM) {
    -    goog.asserts.assertNumber(value);
    -  } else {
    -    goog.asserts.assert(value.constructor == field.getNativeType());
    -  }
    -};
    -
    -
    -/**
    - * Clears the field specified by tag.
    - *
    - * GENERATED CODE USE ONLY. Basis of the clear{Field} methods.
    - *
    - * @param {number} tag The tag of the field to clear.
    - * @protected
    - */
    -goog.proto2.Message.prototype.clear$Field = function(tag) {
    -  delete this.values_[tag];
    -  if (this.deserializedFields_) {
    -    delete this.deserializedFields_[tag];
    -  }
    -};
    -
    -
    -/**
    - * Creates the metadata descriptor representing the definition of this message.
    - *
    - * @param {function(new:goog.proto2.Message)} messageType Constructor for the
    - *     message type to which this metadata applies.
    - * @param {!Object} metadataObj The object containing the metadata.
    - * @return {!goog.proto2.Descriptor} The new descriptor.
    - */
    -goog.proto2.Message.createDescriptor = function(messageType, metadataObj) {
    -  var fields = [];
    -  var descriptorInfo = metadataObj[0];
    -
    -  for (var key in metadataObj) {
    -    if (key != 0) {
    -      // Create the field descriptor.
    -      fields.push(
    -          new goog.proto2.FieldDescriptor(messageType, key, metadataObj[key]));
    -    }
    -  }
    -
    -  return new goog.proto2.Descriptor(messageType, descriptorInfo, fields);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/proto2/message_test.html b/src/database/third_party/closure-library/closure/goog/proto2/message_test.html
    deleted file mode 100644
    index 1b03ea5f1df..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/proto2/message_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.proto2 - message.js
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.proto2.MessageTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/proto2/message_test.js b/src/database/third_party/closure-library/closure/goog/proto2/message_test.js
    deleted file mode 100644
    index 9a8a56fb24b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/proto2/message_test.js
    +++ /dev/null
    @@ -1,466 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.proto2.MessageTest');
    -goog.setTestOnly('goog.proto2.MessageTest');
    -
    -goog.require('goog.testing.jsunit');
    -goog.require('proto2.TestAllTypes');
    -goog.require('proto2.TestAllTypes.NestedEnum');
    -goog.require('proto2.TestAllTypes.NestedMessage');
    -goog.require('proto2.TestAllTypes.OptionalGroup');
    -goog.require('proto2.TestAllTypes.RepeatedGroup');
    -
    -function testEqualsWithEmptyMessages() {
    -  var message1 = new proto2.TestAllTypes();
    -  assertTrue('same message object', message1.equals(message1));
    -  assertFalse('comparison with null', message1.equals(null));
    -  assertFalse('comparison with undefined', message1.equals(undefined));
    -
    -  var message2 = new proto2.TestAllTypes();
    -  assertTrue('two empty message objects', message1.equals(message2));
    -
    -  var message3 = new proto2.TestAllTypes.NestedMessage();
    -  assertFalse('different message types', message3.equals(message1));
    -}
    -
    -function testEqualsWithSingleInt32Field() {
    -  var message1 = new proto2.TestAllTypes();
    -  var message2 = new proto2.TestAllTypes();
    -
    -  message1.setOptionalInt32(1);
    -  assertFalse('message1 has an extra int32 field', message1.equals(message2));
    -
    -  message2.setOptionalInt32(1);
    -  assertTrue('same int32 field in both messages', message1.equals(message2));
    -
    -  message2.setOptionalInt32(2);
    -  assertFalse('different int32 field', message1.equals(message2));
    -
    -  message1.clearOptionalInt32();
    -  assertFalse('message2 has an extra int32 field', message1.equals(message2));
    -}
    -
    -function testEqualsWithRepeatedInt32Fields() {
    -  var message1 = new proto2.TestAllTypes();
    -  var message2 = new proto2.TestAllTypes();
    -
    -  message1.addRepeatedInt32(0);
    -  message2.addRepeatedInt32(0);
    -  assertTrue('equal repeated int32 field', message1.equals(message2));
    -
    -  message1.addRepeatedInt32(1);
    -  assertFalse('message1 has more items', message1.equals(message2));
    -
    -  message2.addRepeatedInt32(1);
    -  message2.addRepeatedInt32(1);
    -  assertFalse('message2 has more items', message1.equals(message2));
    -
    -  message1.addRepeatedInt32(2);
    -  assertFalse('different int32 items', message1.equals(message2));
    -}
    -
    -function testEqualsWithDefaultValue() {
    -  var message1 = new proto2.TestAllTypes();
    -  var message2 = new proto2.TestAllTypes();
    -  message1.setOptionalInt64('1');
    -
    -  assertEquals('message1.getOptionalInt64OrDefault should return 1',
    -      '1', message1.getOptionalInt64OrDefault());
    -  assertEquals('message2.getOptionalInt64OrDefault should return 1 too',
    -      '1', message2.getOptionalInt64OrDefault());
    -  assertTrue('message1.hasOptionalInt64() should be true',
    -      message1.hasOptionalInt64());
    -  assertFalse('message2.hasOptionalInt64() should be false',
    -      message2.hasOptionalInt64());
    -  assertFalse('as a result they are not equal', message1.equals(message2));
    -}
    -
    -function testEqualsWithOptionalGroup() {
    -  var message1 = new proto2.TestAllTypes();
    -  var message2 = new proto2.TestAllTypes();
    -  var group1 = new proto2.TestAllTypes.OptionalGroup();
    -  var group2 = new proto2.TestAllTypes.OptionalGroup();
    -
    -  message1.setOptionalgroup(group1);
    -  assertFalse('only message1 has OptionalGroup field',
    -      message1.equals(message2));
    -
    -  message2.setOptionalgroup(group2);
    -  assertTrue('both messages have OptionalGroup field',
    -      message1.equals(message2));
    -
    -  group1.setA(0);
    -  group2.setA(1);
    -  assertFalse('different value in the optional group',
    -      message1.equals(message2));
    -
    -  message1.clearOptionalgroup();
    -  assertFalse('only message2 has OptionalGroup field',
    -      message1.equals(message2));
    -}
    -
    -function testEqualsWithRepeatedGroup() {
    -  var message1 = new proto2.TestAllTypes();
    -  var message2 = new proto2.TestAllTypes();
    -  var group1 = new proto2.TestAllTypes.RepeatedGroup();
    -  var group2 = new proto2.TestAllTypes.RepeatedGroup();
    -
    -  message1.addRepeatedgroup(group1);
    -  assertFalse('message1 has more RepeatedGroups',
    -      message1.equals(message2));
    -
    -  message2.addRepeatedgroup(group2);
    -  assertTrue('both messages have one RepeatedGroup',
    -      message1.equals(message2));
    -
    -  group1.addA(1);
    -  assertFalse('message1 has more int32s in RepeatedGroup',
    -      message1.equals(message2));
    -
    -  group2.addA(1);
    -  assertTrue('both messages have one int32 in RepeatedGroup',
    -      message1.equals(message2));
    -
    -  group1.addA(1);
    -  group2.addA(2);
    -  assertFalse('the messages have different int32s in RepeatedGroup',
    -      message1.equals(message2));
    -}
    -
    -function testEqualsWithNestedMessage() {
    -  var message1 = new proto2.TestAllTypes();
    -  var message2 = new proto2.TestAllTypes();
    -  var nested1 = new proto2.TestAllTypes.NestedMessage();
    -  var nested2 = new proto2.TestAllTypes.NestedMessage();
    -
    -  message1.setOptionalNestedMessage(nested1);
    -  assertFalse('only message1 has nested message', message1.equals(message2));
    -
    -  message2.setOptionalNestedMessage(nested2);
    -  assertTrue('both messages have nested message', message1.equals(message2));
    -
    -  nested1.setB(1);
    -  assertFalse('different int32 in the nested messages',
    -      message1.equals(message2));
    -
    -  message1.clearOptionalNestedMessage();
    -  assertFalse('only message2 has nested message', message1.equals(message2));
    -}
    -
    -function testEqualsWithNestedEnum() {
    -  var message1 = new proto2.TestAllTypes();
    -  var message2 = new proto2.TestAllTypes();
    -
    -  message1.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
    -  assertFalse('only message1 has nested enum', message1.equals(message2));
    -
    -  message2.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
    -  assertTrue('both messages have nested enum', message1.equals(message2));
    -
    -  message2.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.BAR);
    -  assertFalse('different enum value', message1.equals(message2));
    -
    -  message1.clearOptionalNestedEnum();
    -  assertFalse('only message2 has nested enum', message1.equals(message2));
    -}
    -
    -function testEqualsWithUnknownFields() {
    -  var message1 = new proto2.TestAllTypes();
    -  var message2 = new proto2.TestAllTypes();
    -  message1.setUnknown(999, 'foo');
    -  message1.setUnknown(999, 'bar');
    -  assertTrue('unknown fields are ignored', message1.equals(message2));
    -}
    -
    -function testCloneEmptyMessage() {
    -  var message = new proto2.TestAllTypes();
    -  var clone = message.clone();
    -  assertObjectEquals('cloned empty message', message, clone);
    -}
    -
    -function testCloneMessageWithSeveralFields() {
    -  var message = new proto2.TestAllTypes();
    -  message.setOptionalInt32(1);
    -  message.addRepeatedInt32(2);
    -  var optionalGroup = new proto2.TestAllTypes.OptionalGroup();
    -  optionalGroup.setA(3);
    -  message.setOptionalgroup(optionalGroup);
    -  var repeatedGroup = new proto2.TestAllTypes.RepeatedGroup();
    -  repeatedGroup.addA(4);
    -  message.addRepeatedgroup(repeatedGroup);
    -  var nestedMessage = new proto2.TestAllTypes.NestedMessage();
    -  nestedMessage.setB(5);
    -  message.setOptionalNestedMessage(nestedMessage);
    -  message.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
    -  message.setUnknown(999, 'foo');
    -
    -  var clone = message.clone();
    -  assertNotEquals('different OptionalGroup instance',
    -      message.getOptionalgroup(), clone.getOptionalgroup());
    -  assertNotEquals('different RepeatedGroup array instance',
    -      message.repeatedgroupArray(), clone.repeatedgroupArray());
    -  assertNotEquals('different RepeatedGroup array item instance',
    -      message.getRepeatedgroup(0), clone.getRepeatedgroup(0));
    -  assertNotEquals('different NestedMessage instance',
    -      message.getOptionalNestedMessage(), clone.getOptionalNestedMessage());
    -}
    -
    -function testCloneWithUnknownFields() {
    -  var message = new proto2.TestAllTypes();
    -  message.setUnknown(999, 'foo');
    -
    -  var clone = message.clone();
    -  assertTrue('clone.equals(message) returns true', clone.equals(message));
    -  clone.forEachUnknown(function(tag, value) {
    -    fail('the unknown fields should not have been cloned');
    -  });
    -
    -  clone.setUnknown(999, 'foo');
    -  assertObjectEquals('the original and the cloned message are equal except ' +
    -      'for the unknown fields', message, clone);
    -}
    -
    -function testCopyFromSameMessage() {
    -  var source = new proto2.TestAllTypes();
    -  source.setOptionalInt32(32);
    -  source.copyFrom(source);
    -  assertEquals(32, source.getOptionalInt32());
    -}
    -
    -function testCopyFromFlatMessage() {
    -  // Recursive copying is implicitly tested in the testClone... methods.
    -
    -  var source = new proto2.TestAllTypes();
    -  source.setOptionalInt32(32);
    -  source.setOptionalInt64('64');
    -  source.addRepeatedInt32(32);
    -
    -  var target = new proto2.TestAllTypes();
    -  target.setOptionalInt32(33);
    -  target.setOptionalUint32(33);
    -  target.addRepeatedInt32(33);
    -
    -  target.copyFrom(source);
    -  assertObjectEquals('source and target are equal after copyFrom', source,
    -      target);
    -
    -  target.copyFrom(source);
    -  assertObjectEquals('second copyFrom call has no effect', source, target);
    -
    -  source.setUnknown(999, 'foo');
    -  target.setUnknown(999, 'bar');
    -  target.copyFrom(source);
    -  assertThrows('unknown fields are not copied',
    -      goog.partial(assertObjectEquals, source, target));
    -}
    -
    -function testMergeFromEmptyMessage() {
    -  var source = new proto2.TestAllTypes();
    -  source.setOptionalInt32(32);
    -  source.setOptionalInt64('64');
    -  var nested = new proto2.TestAllTypes.NestedMessage();
    -  nested.setB(66);
    -  source.setOptionalNestedMessage(nested);
    -
    -  var target = new proto2.TestAllTypes();
    -  target.mergeFrom(source);
    -  assertObjectEquals('source and target are equal after mergeFrom', source,
    -      target);
    -}
    -
    -function testMergeFromFlatMessage() {
    -  var source = new proto2.TestAllTypes();
    -  source.setOptionalInt32(32);
    -  source.setOptionalString('foo');
    -  source.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
    -
    -  var target = new proto2.TestAllTypes();
    -  target.setOptionalInt64('64');
    -  target.setOptionalString('bar');
    -  target.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.BAR);
    -
    -  var expected = new proto2.TestAllTypes();
    -  expected.setOptionalInt32(32);
    -  expected.setOptionalInt64('64');
    -  expected.setOptionalString('foo');
    -  expected.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
    -
    -  target.mergeFrom(source);
    -  assertObjectEquals('expected and target are equal after mergeFrom', expected,
    -      target);
    -}
    -
    -function testMergeFromNestedMessage() {
    -  var source = new proto2.TestAllTypes();
    -  var nested = new proto2.TestAllTypes.NestedMessage();
    -  nested.setB(66);
    -  source.setOptionalNestedMessage(nested);
    -
    -  var target = new proto2.TestAllTypes();
    -  nested = new proto2.TestAllTypes.NestedMessage();
    -  nested.setC(77);
    -  target.setOptionalNestedMessage(nested);
    -
    -  var expected = new proto2.TestAllTypes();
    -  nested = new proto2.TestAllTypes.NestedMessage();
    -  nested.setB(66);
    -  nested.setC(77);
    -  expected.setOptionalNestedMessage(nested);
    -
    -  target.mergeFrom(source);
    -  assertObjectEquals('expected and target are equal after mergeFrom', expected,
    -      target);
    -}
    -
    -function testMergeFromRepeatedMessage() {
    -  var source = new proto2.TestAllTypes();
    -  source.addRepeatedInt32(2);
    -  source.addRepeatedInt32(3);
    -
    -  var target = new proto2.TestAllTypes();
    -  target.addRepeatedInt32(1);
    -
    -  target.mergeFrom(source);
    -  assertArrayEquals('repeated_int32 array has elements from both messages',
    -      [1, 2, 3], target.repeatedInt32Array());
    -}
    -
    -function testInitDefaultsWithEmptyMessage() {
    -  var message = new proto2.TestAllTypes();
    -  message.initDefaults(false);
    -
    -  assertFalse('int32 field is not set', message.hasOptionalInt32());
    -  assertFalse('int64 [default=1] field is not set', message.hasOptionalInt64());
    -  assertTrue('optional group field is set', message.hasOptionalgroup());
    -  assertFalse('int32 inside the group is not set',
    -      message.getOptionalgroup().hasA());
    -  assertObjectEquals('value of the optional group',
    -      new proto2.TestAllTypes.OptionalGroup(), message.getOptionalgroup());
    -  assertTrue('nested message is set', message.hasOptionalNestedMessage());
    -  assertObjectEquals('value of the nested message',
    -      new proto2.TestAllTypes.NestedMessage(),
    -      message.getOptionalNestedMessage());
    -  assertFalse('nested enum is not set', message.hasOptionalNestedEnum());
    -  assertFalse('repeated int32 is not set', message.hasRepeatedInt32());
    -  assertFalse('repeated nested message is not set',
    -      message.hasRepeatedNestedMessage());
    -
    -  message = new proto2.TestAllTypes();
    -  message.initDefaults(true);
    -
    -  assertTrue('int32 field is set', message.hasOptionalInt32());
    -  assertEquals('value of the int32 field', 0, message.getOptionalInt32());
    -  assertTrue('int64 [default=1] field is set', message.hasOptionalInt64());
    -  assertEquals('value of the int64 field', '1', message.getOptionalInt64());
    -  assertTrue('int32 inside nested message is set',
    -      message.getOptionalNestedMessage().hasB());
    -  assertEquals('value of the int32 field inside the nested message', 0,
    -      message.getOptionalNestedMessage().getB());
    -}
    -
    -function testInitDefaultsWithNonEmptyMessage() {
    -  var message = new proto2.TestAllTypes();
    -  message.setOptionalInt32(32);
    -  message.setOptionalInt64('64');
    -  message.setOptionalgroup(new proto2.TestAllTypes.OptionalGroup());
    -  var nested1 = new proto2.TestAllTypes.NestedMessage();
    -  nested1.setB(66);
    -  message.setOptionalNestedMessage(nested1);
    -  var nested2 = new proto2.TestAllTypes.NestedMessage();
    -  message.addRepeatedNestedMessage(nested2);
    -  var nested3 = new proto2.TestAllTypes.NestedMessage();
    -  nested3.setB(66);
    -  message.addRepeatedNestedMessage(nested3);
    -
    -  message.initDefaults(true);
    -  assertEquals('int32 field is unchanged', 32, message.getOptionalInt32());
    -  assertEquals('int64 [default=1] field is unchanged', '64',
    -      message.getOptionalInt64());
    -  assertTrue('bool field is initialized', message.hasOptionalBool());
    -  assertFalse('value of the bool field', message.getOptionalBool());
    -  assertTrue('int32 inside the optional group is initialized',
    -      message.getOptionalgroup().hasA());
    -  assertEquals('value of the int32 inside the optional group', 0,
    -      message.getOptionalgroup().getA());
    -  assertEquals('int32 inside nested message is unchanged', 66,
    -      message.getOptionalNestedMessage().getB());
    -  assertTrue('int32 at index 0 of the repeated nested message is initialized',
    -      message.getRepeatedNestedMessage(0).hasB());
    -  assertEquals('value of int32 at index 0 of the repeated nested message', 0,
    -      message.getRepeatedNestedMessage(0).getB());
    -  assertEquals('int32 at index 1 of the repeated nested message is unchanged',
    -      66, message.getRepeatedNestedMessage(1).getB());
    -}
    -
    -function testInitDefaultsTwice() {
    -  var message = new proto2.TestAllTypes();
    -  message.initDefaults(false);
    -  var clone = message.clone();
    -  clone.initDefaults(false);
    -  assertObjectEquals('second call of initDefaults(false) has no effect',
    -      message, clone);
    -
    -  message = new proto2.TestAllTypes();
    -  message.initDefaults(true);
    -  clone = message.clone();
    -  clone.initDefaults(true);
    -  assertObjectEquals('second call of initDefaults(true) has no effect',
    -      message, clone);
    -}
    -
    -function testInitDefaultsThenClone() {
    -  var message = new proto2.TestAllTypes();
    -  message.initDefaults(true);
    -  assertObjectEquals('message is cloned properly', message, message.clone());
    -}
    -
    -function testClassGetDescriptorEqualToInstanceGetDescriptor() {
    -  var classDescriptor = proto2.TestAllTypes.getDescriptor();
    -  var instanceDescriptor = new proto2.TestAllTypes().getDescriptor();
    -  assertEquals(classDescriptor, instanceDescriptor);
    -}
    -
    -function testGetAfterSetWithLazyDeserializer() {
    -  // Test makes sure that the lazy deserializer for a field is not
    -  // erroneously called when get$Value is called after set$Value.
    -  var message = new proto2.TestAllTypes();
    -
    -  var fakeDeserializer = {}; // stub with no methods defined; fails hard
    -  message.initializeForLazyDeserializer(fakeDeserializer, {} /* data */);
    -  message.setOptionalBool(true);
    -  assertEquals(true, message.getOptionalBool());
    -}
    -
    -function testHasOnLazyDeserializer() {
    -  // Test that null values for fields are treated as absent by the lazy
    -  // deserializer.
    -  var message = new proto2.TestAllTypes();
    -
    -  var fakeDeserializer = {}; // stub with no methods defined; fails hard
    -  message.initializeForLazyDeserializer(fakeDeserializer,
    -      {13: false} /* data */);
    -  assertEquals(true, message.hasOptionalBool());
    -}
    -
    -function testHasOnLazyDeserializerWithNulls() {
    -  // Test that null values for fields are treated as absent by the lazy
    -  // deserializer.
    -  var message = new proto2.TestAllTypes();
    -
    -  var fakeDeserializer = {}; // stub with no methods defined; fails hard
    -  message.initializeForLazyDeserializer(fakeDeserializer,
    -      {13: null} /* data */);
    -  assertEquals(false, message.hasOptionalBool());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/proto2/objectserializer.js b/src/database/third_party/closure-library/closure/goog/proto2/objectserializer.js
    deleted file mode 100644
    index d7b1b241020..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/proto2/objectserializer.js
    +++ /dev/null
    @@ -1,176 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Protocol Buffer 2 Serializer which serializes messages
    - *  into anonymous, simplified JSON objects.
    - *
    - */
    -
    -goog.provide('goog.proto2.ObjectSerializer');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.proto2.FieldDescriptor');
    -goog.require('goog.proto2.Serializer');
    -goog.require('goog.string');
    -
    -
    -
    -/**
    - * ObjectSerializer, a serializer which turns Messages into simplified
    - * ECMAScript objects.
    - *
    - * @param {goog.proto2.ObjectSerializer.KeyOption=} opt_keyOption If specified,
    - *     which key option to use when serializing/deserializing.
    - * @constructor
    - * @extends {goog.proto2.Serializer}
    - */
    -goog.proto2.ObjectSerializer = function(opt_keyOption) {
    -  this.keyOption_ = opt_keyOption;
    -};
    -goog.inherits(goog.proto2.ObjectSerializer, goog.proto2.Serializer);
    -
    -
    -/**
    - * An enumeration of the options for how to emit the keys in
    - * the generated simplified object.
    - *
    - * @enum {number}
    - */
    -goog.proto2.ObjectSerializer.KeyOption = {
    -  /**
    -   * Use the tag of the field as the key (default)
    -   */
    -  TAG: 0,
    -
    -  /**
    -   * Use the name of the field as the key. Unknown fields
    -   * will still use their tags as keys.
    -   */
    -  NAME: 1
    -};
    -
    -
    -/**
    - * Serializes a message to an object.
    - *
    - * @param {goog.proto2.Message} message The message to be serialized.
    - * @return {!Object} The serialized form of the message.
    - * @override
    - */
    -goog.proto2.ObjectSerializer.prototype.serialize = function(message) {
    -  var descriptor = message.getDescriptor();
    -  var fields = descriptor.getFields();
    -
    -  var objectValue = {};
    -
    -  // Add the defined fields, recursively.
    -  for (var i = 0; i < fields.length; i++) {
    -    var field = fields[i];
    -
    -    var key =
    -        this.keyOption_ == goog.proto2.ObjectSerializer.KeyOption.NAME ?
    -        field.getName() : field.getTag();
    -
    -
    -    if (message.has(field)) {
    -      if (field.isRepeated()) {
    -        var array = [];
    -        objectValue[key] = array;
    -
    -        for (var j = 0; j < message.countOf(field); j++) {
    -          array.push(this.getSerializedValue(field, message.get(field, j)));
    -        }
    -
    -      } else {
    -        objectValue[key] = this.getSerializedValue(field, message.get(field));
    -      }
    -    }
    -  }
    -
    -  // Add the unknown fields, if any.
    -  message.forEachUnknown(function(tag, value) {
    -    objectValue[tag] = value;
    -  });
    -
    -  return objectValue;
    -};
    -
    -
    -/** @override */
    -goog.proto2.ObjectSerializer.prototype.getDeserializedValue =
    -    function(field, value) {
    -
    -  // Gracefully handle the case where a boolean is represented by 0/1.
    -  // Some serialization libraries, such as GWT, can use this notation.
    -  if (field.getFieldType() == goog.proto2.FieldDescriptor.FieldType.BOOL &&
    -      goog.isNumber(value)) {
    -    return Boolean(value);
    -  }
    -
    -  return goog.proto2.ObjectSerializer.base(
    -      this, 'getDeserializedValue', field, value);
    -};
    -
    -
    -/**
    - * Deserializes a message from an object and places the
    - * data in the message.
    - *
    - * @param {goog.proto2.Message} message The message in which to
    - *     place the information.
    - * @param {*} data The data of the message.
    - * @override
    - */
    -goog.proto2.ObjectSerializer.prototype.deserializeTo = function(message, data) {
    -  var descriptor = message.getDescriptor();
    -
    -  for (var key in data) {
    -    var field;
    -    var value = data[key];
    -
    -    var isNumeric = goog.string.isNumeric(key);
    -
    -    if (isNumeric) {
    -      field = descriptor.findFieldByTag(key);
    -    } else {
    -      // We must be in Key == NAME mode to lookup by name.
    -      goog.asserts.assert(
    -          this.keyOption_ == goog.proto2.ObjectSerializer.KeyOption.NAME);
    -
    -      field = descriptor.findFieldByName(key);
    -    }
    -
    -    if (field) {
    -      if (field.isRepeated()) {
    -        goog.asserts.assert(goog.isArray(value));
    -
    -        for (var j = 0; j < value.length; j++) {
    -          message.add(field, this.getDeserializedValue(field, value[j]));
    -        }
    -      } else {
    -        goog.asserts.assert(!goog.isArray(value));
    -        message.set(field, this.getDeserializedValue(field, value));
    -      }
    -    } else {
    -      if (isNumeric) {
    -        // We have an unknown field.
    -        message.setUnknown(Number(key), value);
    -      } else {
    -        // Named fields must be present.
    -        goog.asserts.fail('Failed to find field: ' + field);
    -      }
    -    }
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/proto2/objectserializer_test.html b/src/database/third_party/closure-library/closure/goog/proto2/objectserializer_test.html
    deleted file mode 100644
    index 6c5a46a8a21..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/proto2/objectserializer_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.proto2 - objectserializer.js
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.proto2.ObjectSerializerTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/proto2/objectserializer_test.js b/src/database/third_party/closure-library/closure/goog/proto2/objectserializer_test.js
    deleted file mode 100644
    index 026bdac09e4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/proto2/objectserializer_test.js
    +++ /dev/null
    @@ -1,567 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.proto2.ObjectSerializerTest');
    -goog.setTestOnly('goog.proto2.ObjectSerializerTest');
    -
    -goog.require('goog.proto2.ObjectSerializer');
    -goog.require('goog.proto2.Serializer');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('proto2.TestAllTypes');
    -
    -var propertyReplacer = new goog.testing.PropertyReplacer();
    -
    -function tearDown() {
    -  propertyReplacer.reset();
    -}
    -
    -function testSerialization() {
    -  var message = new proto2.TestAllTypes();
    -
    -  // Set the fields.
    -  // Singular.
    -  message.setOptionalInt32(101);
    -  message.setOptionalInt64('102');
    -  message.setOptionalUint32(103);
    -  message.setOptionalUint64('104');
    -  message.setOptionalSint32(105);
    -  message.setOptionalSint64('106');
    -  message.setOptionalFixed32(107);
    -  message.setOptionalFixed64('108');
    -  message.setOptionalSfixed32(109);
    -  message.setOptionalSfixed64('110');
    -  message.setOptionalFloat(111.5);
    -  message.setOptionalDouble(112.5);
    -  message.setOptionalBool(true);
    -  message.setOptionalString('test');
    -  message.setOptionalBytes('abcd');
    -
    -  var group = new proto2.TestAllTypes.OptionalGroup();
    -  group.setA(111);
    -
    -  message.setOptionalgroup(group);
    -
    -  var nestedMessage = new proto2.TestAllTypes.NestedMessage();
    -  nestedMessage.setB(112);
    -
    -  message.setOptionalNestedMessage(nestedMessage);
    -
    -  message.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
    -
    -  // Repeated.
    -  message.addRepeatedInt32(201);
    -  message.addRepeatedInt32(202);
    -
    -  // Serialize to a simplified object.
    -  var simplified = new goog.proto2.ObjectSerializer().serialize(message);
    -
    -  // Assert that everything serialized properly.
    -  assertEquals(101, simplified[1]);
    -  assertEquals('102', simplified[2]);
    -  assertEquals(103, simplified[3]);
    -  assertEquals('104', simplified[4]);
    -  assertEquals(105, simplified[5]);
    -  assertEquals('106', simplified[6]);
    -  assertEquals(107, simplified[7]);
    -  assertEquals('108', simplified[8]);
    -  assertEquals(109, simplified[9]);
    -  assertEquals('110', simplified[10]);
    -  assertEquals(111.5, simplified[11]);
    -  assertEquals(112.5, simplified[12]);
    -  assertEquals(true, simplified[13]);
    -  assertEquals('test', simplified[14]);
    -  assertEquals('abcd', simplified[15]);
    -
    -  assertEquals(111, simplified[16][17]);
    -  assertEquals(112, simplified[18][1]);
    -  assertEquals(proto2.TestAllTypes.NestedEnum.FOO, simplified[21]);
    -
    -  assertEquals(201, simplified[31][0]);
    -  assertEquals(202, simplified[31][1]);
    -
    -  // Serialize to a simplified object (with key as name).
    -  simplified = new goog.proto2.ObjectSerializer(
    -      goog.proto2.ObjectSerializer.KeyOption.NAME).serialize(message);
    -
    -  // Assert that everything serialized properly.
    -  assertEquals(101, simplified['optional_int32']);
    -  assertEquals('102', simplified['optional_int64']);
    -  assertEquals(103, simplified['optional_uint32']);
    -  assertEquals('104', simplified['optional_uint64']);
    -  assertEquals(105, simplified['optional_sint32']);
    -  assertEquals('106', simplified['optional_sint64']);
    -  assertEquals(107, simplified['optional_fixed32']);
    -  assertEquals('108', simplified['optional_fixed64']);
    -  assertEquals(109, simplified['optional_sfixed32']);
    -  assertEquals('110', simplified['optional_sfixed64']);
    -  assertEquals(111.5, simplified['optional_float']);
    -  assertEquals(112.5, simplified['optional_double']);
    -  assertEquals(true, simplified['optional_bool']);
    -  assertEquals('test', simplified['optional_string']);
    -  assertEquals('abcd', simplified['optional_bytes']);
    -
    -  assertEquals(111, simplified['optionalgroup']['a']);
    -  assertEquals(112, simplified['optional_nested_message']['b']);
    -
    -  assertEquals(proto2.TestAllTypes.NestedEnum.FOO,
    -      simplified['optional_nested_enum']);
    -
    -  assertEquals(201, simplified['repeated_int32'][0]);
    -  assertEquals(202, simplified['repeated_int32'][1]);
    -}
    -
    -
    -function testSerializationOfUnknown() {
    -  var message = new proto2.TestAllTypes();
    -
    -  // Set the fields.
    -  // Known.
    -  message.setOptionalInt32(101);
    -  message.setOptionalInt64('102');
    -  message.addRepeatedInt32(201);
    -  message.addRepeatedInt32(202);
    -
    -  // Unknown.
    -  message.setUnknown(1000, 301);
    -  message.setUnknown(1001, 302);
    -
    -  // Serialize.
    -  var simplified = new goog.proto2.ObjectSerializer().serialize(message);
    -
    -  assertEquals(101, simplified['1']);
    -  assertEquals('102', simplified['2']);
    -
    -  assertEquals(201, simplified['31'][0]);
    -  assertEquals(202, simplified['31'][1]);
    -
    -  assertEquals(301, simplified['1000']);
    -  assertEquals(302, simplified['1001']);
    -}
    -
    -function testDeserializationOfUnknown() {
    -  var simplified = {
    -    1: 101,
    -    2: '102',
    -    1000: 103,
    -    1001: 104
    -  };
    -
    -  var serializer = new goog.proto2.ObjectSerializer();
    -
    -  var message = serializer.deserialize(
    -      proto2.TestAllTypes.getDescriptor(), simplified);
    -
    -  assertNotNull(message);
    -  assertTrue(message.hasOptionalInt32());
    -  assertTrue(message.hasOptionalInt64());
    -
    -  assertEquals(101, message.getOptionalInt32());
    -  assertEquals('102', message.getOptionalInt64());
    -
    -  var count = 0;
    -
    -  message.forEachUnknown(function(tag, value) {
    -    if (tag == 1000) {
    -      assertEquals(103, value);
    -    }
    -
    -    if (tag == 1001) {
    -      assertEquals(104, value);
    -    }
    -
    -    ++count;
    -  });
    -
    -  assertEquals(2, count);
    -}
    -
    -function testDeserializationRepeated() {
    -  var simplified = {
    -    31: [101, 102],
    -    41: [201.5, 202.5, 203.5],
    -    42: [],
    -    43: [true, false],
    -    44: ['he', 'llo'],
    -    46: [{ 47: [101] } , { 47: [102] }],
    -    48: [{ 1: 201 }, { 1: 202 }]
    -  };
    -
    -  var serializer = new goog.proto2.ObjectSerializer();
    -
    -  var message = serializer.deserialize(
    -      proto2.TestAllTypes.getDescriptor(), simplified);
    -
    -  assertNotNull(message);
    -
    -  // Ensure the fields are set as expected.
    -  assertTrue(message.hasRepeatedInt32());
    -  assertTrue(message.hasRepeatedFloat());
    -
    -  assertFalse(message.hasRepeatedDouble());
    -
    -  assertTrue(message.hasRepeatedBool());
    -  assertTrue(message.hasRepeatedgroup());
    -  assertTrue(message.hasRepeatedNestedMessage());
    -
    -  // Ensure the counts match.
    -  assertEquals(2, message.repeatedInt32Count());
    -  assertEquals(3, message.repeatedFloatCount());
    -
    -  assertEquals(0, message.repeatedDoubleCount());
    -
    -  assertEquals(2, message.repeatedBoolCount());
    -  assertEquals(2, message.repeatedStringCount());
    -  assertEquals(2, message.repeatedgroupCount());
    -  assertEquals(2, message.repeatedNestedMessageCount());
    -
    -  // Ensure the values match.
    -  assertEquals(101, message.getRepeatedInt32(0));
    -  assertEquals(102, message.getRepeatedInt32(1));
    -
    -  assertEquals(201.5, message.getRepeatedFloat(0));
    -  assertEquals(202.5, message.getRepeatedFloat(1));
    -  assertEquals(203.5, message.getRepeatedFloat(2));
    -
    -  assertEquals(true, message.getRepeatedBool(0));
    -  assertEquals(false, message.getRepeatedBool(1));
    -
    -  assertEquals('he', message.getRepeatedString(0));
    -  assertEquals('llo', message.getRepeatedString(1));
    -
    -  assertEquals(101, message.getRepeatedgroup(0).getA(0));
    -  assertEquals(102, message.getRepeatedgroup(1).getA(0));
    -
    -  assertEquals(201, message.getRepeatedNestedMessage(0).getB());
    -  assertEquals(202, message.getRepeatedNestedMessage(1).getB());
    -}
    -
    -function testDeserialization() {
    -  var simplified = {
    -    1: 101,
    -    2: '102',
    -    3: 103,
    -    4: '104',
    -    5: 105,
    -    6: '106',
    -    7: 107,
    -    8: '108',
    -    9: 109,
    -    10: '110',
    -    11: 111.5,
    -    12: 112.5,
    -    13: true,
    -    14: 'test',
    -    15: 'abcd',
    -    16: { 17 : 113 },
    -    18: { 1 : 114 },
    -    21: proto2.TestAllTypes.NestedEnum.FOO
    -  };
    -
    -  var serializer = new goog.proto2.ObjectSerializer();
    -
    -  var message = serializer.deserialize(
    -      proto2.TestAllTypes.getDescriptor(), simplified);
    -
    -  assertNotNull(message);
    -
    -  assertTrue(message.hasOptionalInt32());
    -  assertTrue(message.hasOptionalInt64());
    -  assertTrue(message.hasOptionalUint32());
    -  assertTrue(message.hasOptionalUint64());
    -  assertTrue(message.hasOptionalSint32());
    -  assertTrue(message.hasOptionalSint64());
    -  assertTrue(message.hasOptionalFixed32());
    -  assertTrue(message.hasOptionalFixed64());
    -  assertTrue(message.hasOptionalSfixed32());
    -  assertTrue(message.hasOptionalSfixed64());
    -  assertTrue(message.hasOptionalFloat());
    -  assertTrue(message.hasOptionalDouble());
    -  assertTrue(message.hasOptionalBool());
    -  assertTrue(message.hasOptionalString());
    -  assertTrue(message.hasOptionalBytes());
    -  assertTrue(message.hasOptionalgroup());
    -  assertTrue(message.hasOptionalNestedMessage());
    -  assertTrue(message.hasOptionalNestedEnum());
    -
    -  assertEquals(1, message.optionalInt32Count());
    -  assertEquals(1, message.optionalInt64Count());
    -  assertEquals(1, message.optionalUint32Count());
    -  assertEquals(1, message.optionalUint64Count());
    -  assertEquals(1, message.optionalSint32Count());
    -  assertEquals(1, message.optionalSint64Count());
    -  assertEquals(1, message.optionalFixed32Count());
    -  assertEquals(1, message.optionalFixed64Count());
    -  assertEquals(1, message.optionalSfixed32Count());
    -  assertEquals(1, message.optionalSfixed64Count());
    -  assertEquals(1, message.optionalFloatCount());
    -  assertEquals(1, message.optionalDoubleCount());
    -  assertEquals(1, message.optionalBoolCount());
    -  assertEquals(1, message.optionalStringCount());
    -  assertEquals(1, message.optionalBytesCount());
    -  assertEquals(1, message.optionalgroupCount());
    -  assertEquals(1, message.optionalNestedMessageCount());
    -  assertEquals(1, message.optionalNestedEnumCount());
    -
    -  assertEquals(101, message.getOptionalInt32());
    -  assertEquals('102', message.getOptionalInt64());
    -  assertEquals(103, message.getOptionalUint32());
    -  assertEquals('104', message.getOptionalUint64());
    -  assertEquals(105, message.getOptionalSint32());
    -  assertEquals('106', message.getOptionalSint64());
    -  assertEquals(107, message.getOptionalFixed32());
    -  assertEquals('108', message.getOptionalFixed64());
    -  assertEquals(109, message.getOptionalSfixed32());
    -  assertEquals('110', message.getOptionalSfixed64());
    -  assertEquals(111.5, message.getOptionalFloat());
    -  assertEquals(112.5, message.getOptionalDouble());
    -  assertEquals(true, message.getOptionalBool());
    -  assertEquals('test', message.getOptionalString());
    -  assertEquals('abcd', message.getOptionalBytes());
    -  assertEquals(113, message.getOptionalgroup().getA());
    -  assertEquals(114, message.getOptionalNestedMessage().getB());
    -
    -  assertEquals(proto2.TestAllTypes.NestedEnum.FOO,
    -      message.getOptionalNestedEnum());
    -}
    -
    -function testDeserializationUnknownEnumValue() {
    -  var simplified = {
    -    21: 1001
    -  };
    -
    -  var serializer = new goog.proto2.ObjectSerializer();
    -
    -  var message = serializer.deserialize(
    -      proto2.TestAllTypes.getDescriptor(), simplified);
    -
    -  assertNotNull(message);
    -
    -  assertEquals(1001, message.getOptionalNestedEnum());
    -}
    -
    -function testDeserializationSymbolicEnumValue() {
    -  var simplified = {
    -    21: 'BAR'
    -  };
    -
    -  propertyReplacer.set(goog.proto2.Serializer, 'DECODE_SYMBOLIC_ENUMS', true);
    -
    -  var serializer = new goog.proto2.ObjectSerializer();
    -
    -  var message = serializer.deserialize(
    -      proto2.TestAllTypes.getDescriptor(), simplified);
    -
    -  assertNotNull(message);
    -
    -  assertEquals(proto2.TestAllTypes.NestedEnum.BAR,
    -      message.getOptionalNestedEnum());
    -}
    -
    -function testDeserializationSymbolicEnumValueTurnedOff() {
    -  var simplified = {
    -    21: 'BAR'
    -  };
    -
    -  var serializer = new goog.proto2.ObjectSerializer();
    -
    -  assertThrows('Should have an assertion failure in deserialization',
    -      function() {
    -        serializer.deserialize(proto2.TestAllTypes.getDescriptor(), simplified);
    -      });
    -}
    -
    -function testDeserializationUnknownSymbolicEnumValue() {
    -  var simplified = {
    -    21: 'BARRED'
    -  };
    -
    -  var serializer = new goog.proto2.ObjectSerializer();
    -
    -  assertThrows('Should have an assertion failure in deserialization',
    -      function() {
    -        serializer.deserialize(proto2.TestAllTypes.getDescriptor(), simplified);
    -      });
    -}
    -
    -function testDeserializationNumbersOrStrings() {
    -  // 64-bit types may have been serialized as numbers or strings.
    -  // Deserialization should be able to handle either.
    -
    -  var simplifiedWithNumbers = {
    -    50: 5000,
    -    51: 5100,
    -    52: [5200, 5201],
    -    53: [5300, 5301]
    -  };
    -
    -  var simplifiedWithStrings = {
    -    50: '5000',
    -    51: '5100',
    -    52: ['5200', '5201'],
    -    53: ['5300', '5301']
    -  };
    -
    -  var serializer = new goog.proto2.ObjectSerializer();
    -
    -  var message = serializer.deserialize(
    -      proto2.TestAllTypes.getDescriptor(), simplifiedWithNumbers);
    -
    -  assertNotNull(message);
    -
    -  assertEquals(5000, message.getOptionalInt64Number());
    -  assertEquals('5100', message.getOptionalInt64String());
    -  assertEquals(5200, message.getRepeatedInt64Number(0));
    -  assertEquals(5201, message.getRepeatedInt64Number(1));
    -  assertEquals('5300', message.getRepeatedInt64String(0));
    -  assertEquals('5301', message.getRepeatedInt64String(1));
    -
    -  assertArrayEquals([5200, 5201], message.repeatedInt64NumberArray());
    -  assertArrayEquals(['5300', '5301'], message.repeatedInt64StringArray());
    -
    -  message = serializer.deserialize(
    -      proto2.TestAllTypes.getDescriptor(), simplifiedWithStrings);
    -
    -  assertNotNull(message);
    -
    -  assertEquals(5000, message.getOptionalInt64Number());
    -  assertEquals('5100', message.getOptionalInt64String());
    -  assertEquals(5200, message.getRepeatedInt64Number(0));
    -  assertEquals(5201, message.getRepeatedInt64Number(1));
    -  assertEquals('5300', message.getRepeatedInt64String(0));
    -  assertEquals('5301', message.getRepeatedInt64String(1));
    -
    -  assertArrayEquals([5200, 5201], message.repeatedInt64NumberArray());
    -  assertArrayEquals(['5300', '5301'], message.repeatedInt64StringArray());
    -}
    -
    -function testSerializationSpecialFloatDoubleValues() {
    -  // NaN, Infinity and -Infinity should get serialized as strings.
    -  var message = new proto2.TestAllTypes();
    -  message.setOptionalFloat(Infinity);
    -  message.setOptionalDouble(-Infinity);
    -  message.addRepeatedFloat(Infinity);
    -  message.addRepeatedFloat(-Infinity);
    -  message.addRepeatedFloat(NaN);
    -  message.addRepeatedDouble(Infinity);
    -  message.addRepeatedDouble(-Infinity);
    -  message.addRepeatedDouble(NaN);
    -  var simplified = new goog.proto2.ObjectSerializer().serialize(message);
    -
    -  // Assert that everything serialized properly.
    -  assertEquals('Infinity', simplified[11]);
    -  assertEquals('-Infinity', simplified[12]);
    -  assertEquals('Infinity', simplified[41][0]);
    -  assertEquals('-Infinity', simplified[41][1]);
    -  assertEquals('NaN', simplified[41][2]);
    -  assertEquals('Infinity', simplified[42][0]);
    -  assertEquals('-Infinity', simplified[42][1]);
    -  assertEquals('NaN', simplified[42][2]);
    -}
    -
    -function testDeserializationSpecialFloatDoubleValues() {
    -  // NaN, Infinity and -Infinity values should be de-serialized from their
    -  // string representation.
    -  var simplified = {
    -    41: ['Infinity', '-Infinity', 'NaN'],
    -    42: ['Infinity', '-Infinity', 'NaN']
    -  };
    -
    -  var serializer = new goog.proto2.ObjectSerializer();
    -
    -  var message = serializer.deserialize(
    -      proto2.TestAllTypes.getDescriptor(), simplified);
    -
    -  assertNotNull(message);
    -
    -  var floatArray = message.repeatedFloatArray();
    -  assertEquals(Infinity, floatArray[0]);
    -  assertEquals(-Infinity, floatArray[1]);
    -  assertTrue(isNaN(floatArray[2]));
    -
    -  var doubleArray = message.repeatedDoubleArray();
    -  assertEquals(Infinity, doubleArray[0]);
    -  assertEquals(-Infinity, doubleArray[1]);
    -  assertTrue(isNaN(doubleArray[2]));
    -}
    -
    -function testDeserializationConversionProhibited() {
    -  // 64-bit types may have been serialized as numbers or strings.
    -  // But 32-bit types must be serialized as numbers.
    -  // Test deserialization fails on 32-bit numbers as strings.
    -
    -  var simplified = {
    -    1: '1000'   // optionalInt32
    -  };
    -  var serializer = new goog.proto2.ObjectSerializer();
    -
    -  assertThrows('Should have an assertion failure in deserialization',
    -      function() {
    -        serializer.deserialize(proto2.TestAllTypes.getDescriptor(), simplified);
    -      });
    -}
    -
    -function testDefaultValueNumbersOrStrings() {
    -  // 64-bit types may have been serialized as numbers or strings.
    -  // The default values should have the correct type.
    -
    -  var serializer = new goog.proto2.ObjectSerializer();
    -  var message = serializer.deserialize(proto2.TestAllTypes.getDescriptor(), {});
    -
    -  assertNotNull(message);
    -
    -  // Default when using Number is a number, and precision is lost.
    -  var value = message.getOptionalInt64NumberOrDefault();
    -  assertTrue('Expecting a number', typeof value === 'number');
    -  assertEquals(1000000000000000000, value);
    -  assertEquals(1000000000000000001, value);
    -  assertEquals(1000000000000000002, value);
    -  assertEquals('1000000000000000000', String(value));  // Value is rounded!
    -
    -  // When using a String, the value is preserved.
    -  assertEquals('1000000000000000001',
    -               message.getOptionalInt64StringOrDefault());
    -}
    -
    -function testBooleanAsNumberFalse() {
    -  // Some libraries, such as GWT, can serialize boolean values as 0/1
    -
    -  var simplified = {
    -    13: 0
    -  };
    -
    -  var serializer = new goog.proto2.ObjectSerializer();
    -
    -  var message = serializer.deserialize(
    -      proto2.TestAllTypes.getDescriptor(), simplified);
    -
    -  assertNotNull(message);
    -
    -  assertFalse(message.getOptionalBool());
    -}
    -
    -function testBooleanAsNumberTrue() {
    -  var simplified = {
    -    13: 1
    -  };
    -
    -  var serializer = new goog.proto2.ObjectSerializer();
    -
    -  var message = serializer.deserialize(
    -      proto2.TestAllTypes.getDescriptor(), simplified);
    -
    -  assertNotNull(message);
    -
    -  assertTrue(message.getOptionalBool());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/proto2/package_test.pb.js b/src/database/third_party/closure-library/closure/goog/proto2/package_test.pb.js
    deleted file mode 100644
    index eb69e38c06b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/proto2/package_test.pb.js
    +++ /dev/null
    @@ -1,184 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -// All other code copyright its respective owners(s).
    -
    -/**
    - * @fileoverview Generated Protocol Buffer code for file
    - * closure/goog/proto2/package_test.proto.
    - */
    -
    -goog.provide('someprotopackage.TestPackageTypes');
    -
    -goog.require('goog.proto2.Message');
    -goog.require('proto2.TestAllTypes');
    -
    -goog.setTestOnly('package_test.pb');
    -
    -
    -
    -/**
    - * Message TestPackageTypes.
    - * @constructor
    - * @extends {goog.proto2.Message}
    - * @final
    - */
    -someprotopackage.TestPackageTypes = function() {
    -  goog.proto2.Message.call(this);
    -};
    -goog.inherits(someprotopackage.TestPackageTypes, goog.proto2.Message);
    -
    -
    -/**
    - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type.
    - * @return {!someprotopackage.TestPackageTypes} The cloned message.
    - * @override
    - */
    -someprotopackage.TestPackageTypes.prototype.clone;
    -
    -
    -/**
    - * Gets the value of the optional_int32 field.
    - * @return {?number} The value.
    - */
    -someprotopackage.TestPackageTypes.prototype.getOptionalInt32 = function() {
    -  return /** @type {?number} */ (this.get$Value(1));
    -};
    -
    -
    -/**
    - * Gets the value of the optional_int32 field or the default value if not set.
    - * @return {number} The value.
    - */
    -someprotopackage.TestPackageTypes.prototype.getOptionalInt32OrDefault =
    -    function() {
    -  return /** @type {number} */ (this.get$ValueOrDefault(1));
    -};
    -
    -
    -/**
    - * Sets the value of the optional_int32 field.
    - * @param {number} value The value.
    - */
    -someprotopackage.TestPackageTypes.prototype.setOptionalInt32 = function(value) {
    -  this.set$Value(1, value);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the optional_int32 field has a value.
    - */
    -someprotopackage.TestPackageTypes.prototype.hasOptionalInt32 = function() {
    -  return this.has$Value(1);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the optional_int32 field.
    - */
    -someprotopackage.TestPackageTypes.prototype.optionalInt32Count = function() {
    -  return this.count$Values(1);
    -};
    -
    -
    -/**
    - * Clears the values in the optional_int32 field.
    - */
    -someprotopackage.TestPackageTypes.prototype.clearOptionalInt32 = function() {
    -  this.clear$Field(1);
    -};
    -
    -
    -/**
    - * Gets the value of the other_all field.
    - * @return {proto2.TestAllTypes} The value.
    - */
    -someprotopackage.TestPackageTypes.prototype.getOtherAll = function() {
    -  return /** @type {proto2.TestAllTypes} */ (this.get$Value(2));
    -};
    -
    -
    -/**
    - * Gets the value of the other_all field or the default value if not set.
    - * @return {!proto2.TestAllTypes} The value.
    - */
    -someprotopackage.TestPackageTypes.prototype.getOtherAllOrDefault = function() {
    -  return /** @type {!proto2.TestAllTypes} */ (this.get$ValueOrDefault(2));
    -};
    -
    -
    -/**
    - * Sets the value of the other_all field.
    - * @param {!proto2.TestAllTypes} value The value.
    - */
    -someprotopackage.TestPackageTypes.prototype.setOtherAll = function(value) {
    -  this.set$Value(2, value);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the other_all field has a value.
    - */
    -someprotopackage.TestPackageTypes.prototype.hasOtherAll = function() {
    -  return this.has$Value(2);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the other_all field.
    - */
    -someprotopackage.TestPackageTypes.prototype.otherAllCount = function() {
    -  return this.count$Values(2);
    -};
    -
    -
    -/**
    - * Clears the values in the other_all field.
    - */
    -someprotopackage.TestPackageTypes.prototype.clearOtherAll = function() {
    -  this.clear$Field(2);
    -};
    -
    -
    -/** @override */
    -someprotopackage.TestPackageTypes.prototype.getDescriptor = function() {
    -  if (!someprotopackage.TestPackageTypes.descriptor_) {
    -    // The descriptor is created lazily when we instantiate a new instance.
    -    var descriptorObj = {
    -      0: {
    -        name: 'TestPackageTypes',
    -        fullName: 'someprotopackage.TestPackageTypes'
    -      },
    -      1: {
    -        name: 'optional_int32',
    -        fieldType: goog.proto2.Message.FieldType.INT32,
    -        type: Number
    -      },
    -      2: {
    -        name: 'other_all',
    -        fieldType: goog.proto2.Message.FieldType.MESSAGE,
    -        type: proto2.TestAllTypes
    -      }
    -    };
    -    someprotopackage.TestPackageTypes.descriptor_ =
    -        goog.proto2.Message.createDescriptor(
    -            someprotopackage.TestPackageTypes, descriptorObj);
    -  }
    -  return someprotopackage.TestPackageTypes.descriptor_;
    -};
    -
    -
    -// Export getDescriptor static function robust to minification.
    -someprotopackage.TestPackageTypes['ctor'] = someprotopackage.TestPackageTypes;
    -someprotopackage.TestPackageTypes['ctor'].getDescriptor =
    -    someprotopackage.TestPackageTypes.prototype.getDescriptor;
    diff --git a/src/database/third_party/closure-library/closure/goog/proto2/pbliteserializer.js b/src/database/third_party/closure-library/closure/goog/proto2/pbliteserializer.js
    deleted file mode 100644
    index 2a9260c9f96..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/proto2/pbliteserializer.js
    +++ /dev/null
    @@ -1,199 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Protocol Buffer 2 Serializer which serializes messages
    - *  into PB-Lite ("JsPbLite") format.
    - *
    - * PB-Lite format is an array where each index corresponds to the associated tag
    - * number. For example, a message like so:
    - *
    - * message Foo {
    - *   optional int bar = 1;
    - *   optional int baz = 2;
    - *   optional int bop = 4;
    - * }
    - *
    - * would be represented as such:
    - *
    - * [, (bar data), (baz data), (nothing), (bop data)]
    - *
    - * Note that since the array index is used to represent the tag number, sparsely
    - * populated messages with tag numbers that are not continuous (and/or are very
    - * large) will have many (empty) spots and thus, are inefficient.
    - *
    - *
    - */
    -
    -goog.provide('goog.proto2.PbLiteSerializer');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.proto2.FieldDescriptor');
    -goog.require('goog.proto2.LazyDeserializer');
    -goog.require('goog.proto2.Serializer');
    -
    -
    -
    -/**
    - * PB-Lite serializer.
    - *
    - * @constructor
    - * @extends {goog.proto2.LazyDeserializer}
    - */
    -goog.proto2.PbLiteSerializer = function() {};
    -goog.inherits(goog.proto2.PbLiteSerializer, goog.proto2.LazyDeserializer);
    -
    -
    -/**
    - * If true, fields will be serialized with 0-indexed tags (i.e., the proto
    - * field with tag id 1 will have index 0 in the array).
    - * @type {boolean}
    - * @private
    - */
    -goog.proto2.PbLiteSerializer.prototype.zeroIndexing_ = false;
    -
    -
    -/**
    - * By default, the proto tag with id 1 will have index 1 in the serialized
    - * array.
    - *
    - * If the serializer is set to use zero-indexing, the tag with id 1 will have
    - * index 0.
    - *
    - * @param {boolean} zeroIndexing Whether this serializer should deal with
    - *     0-indexed protos.
    - */
    -goog.proto2.PbLiteSerializer.prototype.setZeroIndexed = function(zeroIndexing) {
    -  this.zeroIndexing_ = zeroIndexing;
    -};
    -
    -
    -/**
    - * Serializes a message to a PB-Lite object.
    - *
    - * @param {goog.proto2.Message} message The message to be serialized.
    - * @return {!Array<?>} The serialized form of the message.
    - * @override
    - */
    -goog.proto2.PbLiteSerializer.prototype.serialize = function(message) {
    -  var descriptor = message.getDescriptor();
    -  var fields = descriptor.getFields();
    -
    -  var serialized = [];
    -  var zeroIndexing = this.zeroIndexing_;
    -
    -  // Add the known fields.
    -  for (var i = 0; i < fields.length; i++) {
    -    var field = fields[i];
    -
    -    if (!message.has(field)) {
    -      continue;
    -    }
    -
    -    var tag = field.getTag();
    -    var index = zeroIndexing ? tag - 1 : tag;
    -
    -    if (field.isRepeated()) {
    -      serialized[index] = [];
    -
    -      for (var j = 0; j < message.countOf(field); j++) {
    -        serialized[index][j] =
    -            this.getSerializedValue(field, message.get(field, j));
    -      }
    -    } else {
    -      serialized[index] = this.getSerializedValue(field, message.get(field));
    -    }
    -  }
    -
    -  // Add any unknown fields.
    -  message.forEachUnknown(function(tag, value) {
    -    var index = zeroIndexing ? tag - 1 : tag;
    -    serialized[index] = value;
    -  });
    -
    -  return serialized;
    -};
    -
    -
    -/** @override */
    -goog.proto2.PbLiteSerializer.prototype.deserializeField =
    -    function(message, field, value) {
    -
    -  if (value == null) {
    -    // Since value double-equals null, it may be either null or undefined.
    -    // Ensure we return the same one, since they have different meanings.
    -    // TODO(user): If the field is repeated, this method should probably
    -    // return [] instead of null.
    -    return value;
    -  }
    -
    -  if (field.isRepeated()) {
    -    var data = [];
    -
    -    goog.asserts.assert(goog.isArray(value), 'Value must be array: %s', value);
    -
    -    for (var i = 0; i < value.length; i++) {
    -      data[i] = this.getDeserializedValue(field, value[i]);
    -    }
    -
    -    return data;
    -  } else {
    -    return this.getDeserializedValue(field, value);
    -  }
    -};
    -
    -
    -/** @override */
    -goog.proto2.PbLiteSerializer.prototype.getSerializedValue =
    -    function(field, value) {
    -  if (field.getFieldType() == goog.proto2.FieldDescriptor.FieldType.BOOL) {
    -    // Booleans are serialized in numeric form.
    -    return value ? 1 : 0;
    -  }
    -
    -  return goog.proto2.Serializer.prototype.getSerializedValue.apply(this,
    -                                                                   arguments);
    -};
    -
    -
    -/** @override */
    -goog.proto2.PbLiteSerializer.prototype.getDeserializedValue =
    -    function(field, value) {
    -
    -  if (field.getFieldType() == goog.proto2.FieldDescriptor.FieldType.BOOL) {
    -    goog.asserts.assert(goog.isNumber(value) || goog.isBoolean(value),
    -        'Value is expected to be a number or boolean');
    -    return !!value;
    -  }
    -
    -  return goog.proto2.Serializer.prototype.getDeserializedValue.apply(this,
    -                                                                     arguments);
    -};
    -
    -
    -/** @override */
    -goog.proto2.PbLiteSerializer.prototype.deserialize =
    -    function(descriptor, data) {
    -  var toConvert = data;
    -  if (this.zeroIndexing_) {
    -    // Make the data align with tag-IDs (1-indexed) by shifting everything
    -    // up one.
    -    toConvert = [];
    -    for (var key in data) {
    -      toConvert[parseInt(key, 10) + 1] = data[key];
    -    }
    -  }
    -  return goog.proto2.PbLiteSerializer.base(
    -      this, 'deserialize', descriptor, toConvert);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/proto2/pbliteserializer_test.html b/src/database/third_party/closure-library/closure/goog/proto2/pbliteserializer_test.html
    deleted file mode 100644
    index f94cf1cdcb0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/proto2/pbliteserializer_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.proto2 - pbliteserializer.js
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.proto2.PbLiteSerializerTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/proto2/pbliteserializer_test.js b/src/database/third_party/closure-library/closure/goog/proto2/pbliteserializer_test.js
    deleted file mode 100644
    index 889b08bf255..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/proto2/pbliteserializer_test.js
    +++ /dev/null
    @@ -1,499 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.proto2.PbLiteSerializerTest');
    -goog.setTestOnly('goog.proto2.PbLiteSerializerTest');
    -
    -goog.require('goog.proto2.PbLiteSerializer');
    -goog.require('goog.testing.jsunit');
    -goog.require('proto2.TestAllTypes');
    -
    -function testSerializationAndDeserialization() {
    -  var message = createPopulatedMessage();
    -
    -  // Serialize.
    -  var serializer = new goog.proto2.PbLiteSerializer();
    -  var pblite = serializer.serialize(message);
    -
    -  assertTrue(goog.isArray(pblite));
    -
    -  // Assert that everything serialized properly.
    -  assertEquals(101, pblite[1]);
    -  assertEquals('102', pblite[2]);
    -  assertEquals(103, pblite[3]);
    -  assertEquals('104', pblite[4]);
    -  assertEquals(105, pblite[5]);
    -  assertEquals('106', pblite[6]);
    -  assertEquals(107, pblite[7]);
    -  assertEquals('108', pblite[8]);
    -  assertEquals(109, pblite[9]);
    -  assertEquals('110', pblite[10]);
    -  assertEquals(111.5, pblite[11]);
    -  assertEquals(112.5, pblite[12]);
    -  assertEquals(1, pblite[13]); // true is serialized as 1
    -  assertEquals('test', pblite[14]);
    -  assertEquals('abcd', pblite[15]);
    -
    -  assertEquals(111, pblite[16][17]);
    -  assertEquals(112, pblite[18][1]);
    -
    -  assertTrue(pblite[19] === undefined);
    -  assertTrue(pblite[20] === undefined);
    -
    -  assertEquals(proto2.TestAllTypes.NestedEnum.FOO, pblite[21]);
    -
    -  assertEquals(201, pblite[31][0]);
    -  assertEquals(202, pblite[31][1]);
    -  assertEquals('foo', pblite[44][0]);
    -  assertEquals('bar', pblite[44][1]);
    -
    -  var serializer = new goog.proto2.PbLiteSerializer();
    -  // Deserialize.
    -  var messageCopy =
    -      serializer.deserialize(proto2.TestAllTypes.getDescriptor(), pblite);
    -
    -  assertNotEquals(messageCopy, message);
    -
    -  assertDeserializationMatches(messageCopy);
    -}
    -
    -function testZeroBasedSerializationAndDeserialization() {
    -  var message = createPopulatedMessage();
    -
    -  // Serialize.
    -  var serializer = new goog.proto2.PbLiteSerializer();
    -  serializer.setZeroIndexed(true);
    -
    -  var pblite = serializer.serialize(message);
    -
    -  assertTrue(goog.isArray(pblite));
    -
    -  // Assert that everything serialized properly.
    -  assertEquals(101, pblite[0]);
    -  assertEquals('102', pblite[1]);
    -  assertEquals(103, pblite[2]);
    -  assertEquals('104', pblite[3]);
    -  assertEquals(105, pblite[4]);
    -  assertEquals('106', pblite[5]);
    -  assertEquals(107, pblite[6]);
    -  assertEquals('108', pblite[7]);
    -  assertEquals(109, pblite[8]);
    -  assertEquals('110', pblite[9]);
    -  assertEquals(111.5, pblite[10]);
    -  assertEquals(112.5, pblite[11]);
    -  assertEquals(1, pblite[12]); // true is serialized as 1
    -  assertEquals('test', pblite[13]);
    -  assertEquals('abcd', pblite[14]);
    -
    -  assertEquals(111, pblite[15][16]);
    -  assertEquals(112, pblite[17][0]);
    -
    -  assertTrue(pblite[18] === undefined);
    -  assertTrue(pblite[19] === undefined);
    -
    -  assertEquals(proto2.TestAllTypes.NestedEnum.FOO, pblite[20]);
    -
    -  assertEquals(201, pblite[30][0]);
    -  assertEquals(202, pblite[30][1]);
    -  assertEquals('foo', pblite[43][0]);
    -  assertEquals('bar', pblite[43][1]);
    -
    -  // Deserialize.
    -  var messageCopy =
    -      serializer.deserialize(proto2.TestAllTypes.getDescriptor(), pblite);
    -
    -  assertNotEquals(messageCopy, message);
    -
    -  assertEquals(message.getOptionalInt32(), messageCopy.getOptionalInt32());
    -  assertDeserializationMatches(messageCopy);
    -}
    -
    -function createPopulatedMessage() {
    -  var message = new proto2.TestAllTypes();
    -
    -  // Set the fields.
    -  // Singular.
    -  message.setOptionalInt32(101);
    -  message.setOptionalInt64('102');
    -  message.setOptionalUint32(103);
    -  message.setOptionalUint64('104');
    -  message.setOptionalSint32(105);
    -  message.setOptionalSint64('106');
    -  message.setOptionalFixed32(107);
    -  message.setOptionalFixed64('108');
    -  message.setOptionalSfixed32(109);
    -  message.setOptionalSfixed64('110');
    -  message.setOptionalFloat(111.5);
    -  message.setOptionalDouble(112.5);
    -  message.setOptionalBool(true);
    -  message.setOptionalString('test');
    -  message.setOptionalBytes('abcd');
    -
    -  var group = new proto2.TestAllTypes.OptionalGroup();
    -  group.setA(111);
    -
    -  message.setOptionalgroup(group);
    -
    -  var nestedMessage = new proto2.TestAllTypes.NestedMessage();
    -  nestedMessage.setB(112);
    -
    -  message.setOptionalNestedMessage(nestedMessage);
    -
    -  message.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
    -
    -  // Repeated.
    -  message.addRepeatedInt32(201);
    -  message.addRepeatedInt32(202);
    -
    -  // Skip a few repeated fields so we can test how null array values are
    -  // handled.
    -  message.addRepeatedString('foo');
    -  message.addRepeatedString('bar');
    -  return message;
    -}
    -
    -function testDeserializationFromExternalSource() {
    -  // Test deserialization where the JSON array is initialized from something
    -  // outside the Closure proto2 library, such as the JsPbLite library, or
    -  // manually as in this test.
    -  var pblite = [
    -    , // 0
    -    101, // 1
    -    '102', // 2
    -    103, // 3
    -    '104', // 4
    -    105, // 5
    -    '106', // 6
    -    107, // 7
    -    '108', // 8
    -    109, // 9
    -    '110', // 10
    -    111.5, // 11
    -    112.5, // 12
    -    1, // 13
    -    'test', // 14
    -    'abcd', // 15
    -    [,,,,,,,,,,,,,,,,, 111], // 16, note the 17 commas so value is index 17
    -    , // 17
    -    [, 112], // 18
    -    ,, // 19-20
    -    proto2.TestAllTypes.NestedEnum.FOO, // 21
    -    ,,,,,,,,, // 22-30
    -    [201, 202], // 31
    -    ,,,,,,,,,,,, // 32-43
    -    ['foo', 'bar'], // 44
    -    ,,,, // 45-49
    -  ];
    -
    -  // Deserialize.
    -  var serializer = new goog.proto2.PbLiteSerializer();
    -  var messageCopy =
    -      serializer.deserialize(proto2.TestAllTypes.getDescriptor(), pblite);
    -
    -  assertDeserializationMatches(messageCopy);
    -
    -  // http://b/issue?id=2928075
    -  assertFalse(messageCopy.hasRepeatedInt64());
    -  assertEquals(0, messageCopy.repeatedInt64Count());
    -  messageCopy.repeatedInt64Array();
    -  assertFalse(messageCopy.hasRepeatedInt64());
    -  assertEquals(0, messageCopy.repeatedInt64Count());
    -
    -  // Access a nested message to ensure it is deserialized.
    -  assertNotNull(messageCopy.getOptionalNestedMessage());
    -
    -  // Verify that the pblite array itself has not been replaced by the
    -  // deserialization.
    -  assertEquals('array', goog.typeOf(pblite[16]));
    -
    -  // Update some fields and verify that the changes work with the lazy
    -  // deserializer.
    -  messageCopy.setOptionalBool(true);
    -  assertTrue(messageCopy.getOptionalBool());
    -
    -  messageCopy.setOptionalBool(false);
    -  assertFalse(messageCopy.getOptionalBool());
    -
    -  messageCopy.setOptionalInt32(1234);
    -  assertEquals(1234, messageCopy.getOptionalInt32());
    -}
    -
    -function testModifyLazyDeserializedMessage() {
    -  var pblite = [
    -    , // 0
    -    101, // 1
    -    '102', // 2
    -    103, // 3
    -    '104', // 4
    -    105, // 5
    -    '106', // 6
    -    107, // 7
    -    '108', // 8
    -    109, // 9
    -    '110', // 10
    -    111.5, // 11
    -    112.5, // 12
    -    1, // 13
    -    'test', // 14
    -    'abcd', // 15
    -    [,,,,,,,,,,,,,,,,, 111], // 16, note the 17 commas so value is index 17
    -    , // 17
    -    [, 112], // 18
    -    ,, // 19-20
    -    proto2.TestAllTypes.NestedEnum.FOO, // 21
    -    ,,,,,,,,, // 22-30
    -    [201, 202], // 31
    -    ,,,,,,,,,,,, // 32-43
    -    ['foo', 'bar'], // 44
    -    ,,,, // 45-49
    -  ];
    -
    -  // Deserialize.
    -  var serializer = new goog.proto2.PbLiteSerializer();
    -  var message =
    -      serializer.deserialize(proto2.TestAllTypes.getDescriptor(), pblite);
    -
    -  // Conduct some operations, ensuring that they all work as expected, even with
    -  // the lazily deserialized data.
    -  assertEquals(101, message.getOptionalInt32());
    -  message.setOptionalInt32(401);
    -  assertEquals(401, message.getOptionalInt32());
    -
    -  assertEquals(2, message.repeatedInt32Count());
    -  assertEquals(201, message.getRepeatedInt32(0));
    -  assertEquals(202, message.getRepeatedInt32(1));
    -
    -  message.clearRepeatedInt32();
    -  assertEquals(0, message.repeatedInt32Count());
    -
    -  message.addRepeatedInt32(101);
    -  assertEquals(1, message.repeatedInt32Count());
    -  assertEquals(101, message.getRepeatedInt32(0));
    -
    -  message.setUnknown(12345, 601);
    -  message.forEachUnknown(function(tag, value) {
    -    assertEquals(12345, tag);
    -    assertEquals(601, value);
    -  });
    -
    -  // Create a copy of the message.
    -  var messageCopy = new proto2.TestAllTypes();
    -  messageCopy.copyFrom(message);
    -
    -  assertEquals(1, messageCopy.repeatedInt32Count());
    -  assertEquals(101, messageCopy.getRepeatedInt32(0));
    -}
    -
    -function testModifyLazyDeserializedMessageByAddingMessage() {
    -  var pblite = [
    -    , // 0
    -    101, // 1
    -    '102', // 2
    -    103, // 3
    -    '104', // 4
    -    105, // 5
    -    '106', // 6
    -    107, // 7
    -    '108', // 8
    -    109, // 9
    -    '110', // 10
    -    111.5, // 11
    -    112.5, // 12
    -    1, // 13
    -    'test', // 14
    -    'abcd', // 15
    -    [,,,,,,,,,,,,,,,,, 111], // 16, note the 17 commas so value is index 17
    -    , // 17
    -    [, 112], // 18
    -    ,, // 19-20
    -    proto2.TestAllTypes.NestedEnum.FOO, // 21
    -    ,,,,,,,,, // 22-30
    -    [201, 202], // 31
    -    ,,,,,,,,,,,, // 32-43
    -    ['foo', 'bar'], // 44
    -    ,,,, // 45-49
    -  ];
    -
    -  // Deserialize.
    -  var serializer = new goog.proto2.PbLiteSerializer();
    -  var message =
    -      serializer.deserialize(proto2.TestAllTypes.getDescriptor(), pblite);
    -
    -  // Add a new nested message.
    -  var nested1 = new proto2.TestAllTypes.NestedMessage();
    -  nested1.setB(1234);
    -
    -  var nested2 = new proto2.TestAllTypes.NestedMessage();
    -  nested2.setB(4567);
    -
    -  message.addRepeatedNestedMessage(nested1);
    -
    -  // Check the new nested message.
    -  assertEquals(1, message.repeatedNestedMessageArray().length);
    -  assertTrue(message.repeatedNestedMessageArray()[0].equals(nested1));
    -
    -  // Add another nested message.
    -  message.addRepeatedNestedMessage(nested2);
    -
    -  // Check both nested messages.
    -  assertEquals(2, message.repeatedNestedMessageArray().length);
    -  assertTrue(message.repeatedNestedMessageArray()[0].equals(nested1));
    -  assertTrue(message.repeatedNestedMessageArray()[1].equals(nested2));
    -}
    -
    -function assertDeserializationMatches(messageCopy) {
    -  assertNotNull(messageCopy);
    -
    -  assertTrue(messageCopy.hasOptionalInt32());
    -  assertTrue(messageCopy.hasOptionalInt64());
    -  assertTrue(messageCopy.hasOptionalUint32());
    -  assertTrue(messageCopy.hasOptionalUint64());
    -  assertTrue(messageCopy.hasOptionalSint32());
    -  assertTrue(messageCopy.hasOptionalSint64());
    -  assertTrue(messageCopy.hasOptionalFixed32());
    -  assertTrue(messageCopy.hasOptionalFixed64());
    -  assertTrue(messageCopy.hasOptionalSfixed32());
    -  assertTrue(messageCopy.hasOptionalSfixed64());
    -  assertTrue(messageCopy.hasOptionalFloat());
    -  assertTrue(messageCopy.hasOptionalDouble());
    -  assertTrue(messageCopy.hasOptionalBool());
    -  assertTrue(messageCopy.hasOptionalString());
    -  assertTrue(messageCopy.hasOptionalBytes());
    -  assertTrue(messageCopy.hasOptionalgroup());
    -  assertTrue(messageCopy.hasOptionalNestedMessage());
    -  assertTrue(messageCopy.hasOptionalNestedEnum());
    -
    -  assertTrue(messageCopy.hasRepeatedInt32());
    -  assertFalse(messageCopy.hasRepeatedInt64());
    -  assertFalse(messageCopy.hasRepeatedUint32());
    -  assertFalse(messageCopy.hasRepeatedUint64());
    -  assertFalse(messageCopy.hasRepeatedSint32());
    -  assertFalse(messageCopy.hasRepeatedSint64());
    -  assertFalse(messageCopy.hasRepeatedFixed32());
    -  assertFalse(messageCopy.hasRepeatedFixed64());
    -  assertFalse(messageCopy.hasRepeatedSfixed32());
    -  assertFalse(messageCopy.hasRepeatedSfixed64());
    -  assertFalse(messageCopy.hasRepeatedFloat());
    -  assertFalse(messageCopy.hasRepeatedDouble());
    -  assertFalse(messageCopy.hasRepeatedBool());
    -  assertTrue(messageCopy.hasRepeatedString());
    -  assertFalse(messageCopy.hasRepeatedBytes());
    -  assertFalse(messageCopy.hasRepeatedgroup());
    -  assertFalse(messageCopy.hasRepeatedNestedMessage());
    -  assertFalse(messageCopy.hasRepeatedNestedEnum());
    -
    -  assertEquals(1, messageCopy.optionalInt32Count());
    -  assertEquals(1, messageCopy.optionalInt64Count());
    -  assertEquals(1, messageCopy.optionalUint32Count());
    -  assertEquals(1, messageCopy.optionalUint64Count());
    -  assertEquals(1, messageCopy.optionalSint32Count());
    -  assertEquals(1, messageCopy.optionalSint64Count());
    -  assertEquals(1, messageCopy.optionalFixed32Count());
    -  assertEquals(1, messageCopy.optionalFixed64Count());
    -  assertEquals(1, messageCopy.optionalSfixed32Count());
    -  assertEquals(1, messageCopy.optionalSfixed64Count());
    -  assertEquals(1, messageCopy.optionalFloatCount());
    -  assertEquals(1, messageCopy.optionalDoubleCount());
    -  assertEquals(1, messageCopy.optionalBoolCount());
    -  assertEquals(1, messageCopy.optionalStringCount());
    -  assertEquals(1, messageCopy.optionalBytesCount());
    -  assertEquals(1, messageCopy.optionalgroupCount());
    -  assertEquals(1, messageCopy.optionalNestedMessageCount());
    -  assertEquals(1, messageCopy.optionalNestedEnumCount());
    -
    -  assertEquals(2, messageCopy.repeatedInt32Count());
    -  assertEquals(0, messageCopy.repeatedInt64Count());
    -  assertEquals(0, messageCopy.repeatedUint32Count());
    -  assertEquals(0, messageCopy.repeatedUint64Count());
    -  assertEquals(0, messageCopy.repeatedSint32Count());
    -  assertEquals(0, messageCopy.repeatedSint64Count());
    -  assertEquals(0, messageCopy.repeatedFixed32Count());
    -  assertEquals(0, messageCopy.repeatedFixed64Count());
    -  assertEquals(0, messageCopy.repeatedSfixed32Count());
    -  assertEquals(0, messageCopy.repeatedSfixed64Count());
    -  assertEquals(0, messageCopy.repeatedFloatCount());
    -  assertEquals(0, messageCopy.repeatedDoubleCount());
    -  assertEquals(0, messageCopy.repeatedBoolCount());
    -  assertEquals(2, messageCopy.repeatedStringCount());
    -  assertEquals(0, messageCopy.repeatedBytesCount());
    -  assertEquals(0, messageCopy.repeatedgroupCount());
    -  assertEquals(0, messageCopy.repeatedNestedMessageCount());
    -  assertEquals(0, messageCopy.repeatedNestedEnumCount());
    -
    -  assertEquals(101, messageCopy.getOptionalInt32());
    -  assertEquals('102', messageCopy.getOptionalInt64());
    -  assertEquals(103, messageCopy.getOptionalUint32());
    -  assertEquals('104', messageCopy.getOptionalUint64());
    -  assertEquals(105, messageCopy.getOptionalSint32());
    -  assertEquals('106', messageCopy.getOptionalSint64());
    -  assertEquals(107, messageCopy.getOptionalFixed32());
    -  assertEquals('108', messageCopy.getOptionalFixed64());
    -  assertEquals(109, messageCopy.getOptionalSfixed32());
    -  assertEquals('110', messageCopy.getOptionalSfixed64());
    -  assertEquals(111.5, messageCopy.getOptionalFloat());
    -  assertEquals(112.5, messageCopy.getOptionalDouble());
    -  assertEquals(true, messageCopy.getOptionalBool());
    -  assertEquals('test', messageCopy.getOptionalString());
    -  assertEquals('abcd', messageCopy.getOptionalBytes());
    -  assertEquals(111, messageCopy.getOptionalgroup().getA());
    -
    -  assertEquals(112, messageCopy.getOptionalNestedMessage().getB());
    -
    -  assertEquals(proto2.TestAllTypes.NestedEnum.FOO,
    -      messageCopy.getOptionalNestedEnum());
    -
    -  assertEquals(201, messageCopy.getRepeatedInt32(0));
    -  assertEquals(202, messageCopy.getRepeatedInt32(1));
    -}
    -
    -function testMergeFromLazyTarget() {
    -  var serializer = new goog.proto2.PbLiteSerializer();
    -
    -  var source = new proto2.TestAllTypes();
    -  var nested = new proto2.TestAllTypes.NestedMessage();
    -  nested.setB(66);
    -  source.setOptionalNestedMessage(nested);
    -  source.setOptionalInt32(32);
    -  source.setOptionalString('foo');
    -  source.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
    -  source.addRepeatedInt32(2);
    -
    -  var target = new proto2.TestAllTypes();
    -  nested = new proto2.TestAllTypes.NestedMessage();
    -  nested.setC(77);
    -  target.setOptionalNestedMessage(nested);
    -  target.setOptionalInt64('64');
    -  target.setOptionalString('bar');
    -  target.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.BAR);
    -  target.addRepeatedInt32(1);
    -  var pbliteTarget = serializer.serialize(target);
    -  var lazyTarget =
    -      serializer.deserialize(proto2.TestAllTypes.getDescriptor(), pbliteTarget);
    -
    -  var expected = new proto2.TestAllTypes();
    -  nested = new proto2.TestAllTypes.NestedMessage();
    -  nested.setB(66);
    -  nested.setC(77);
    -  expected.setOptionalNestedMessage(nested);
    -  expected.setOptionalInt32(32);
    -  expected.setOptionalInt64('64');
    -  expected.setOptionalString('foo');
    -  expected.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
    -  expected.addRepeatedInt32(1);
    -  expected.addRepeatedInt32(2);
    -
    -  lazyTarget.mergeFrom(source);
    -  assertTrue('expected and lazyTarget are equal after mergeFrom',
    -      lazyTarget.equals(expected));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/proto2/proto_test.html b/src/database/third_party/closure-library/closure/goog/proto2/proto_test.html
    deleted file mode 100644
    index 394e590d95e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/proto2/proto_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.proto2 - Message Tests
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.proto2.messageTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/proto2/proto_test.js b/src/database/third_party/closure-library/closure/goog/proto2/proto_test.js
    deleted file mode 100644
    index 374a072b31d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/proto2/proto_test.js
    +++ /dev/null
    @@ -1,755 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.proto2.messageTest');
    -goog.setTestOnly('goog.proto2.messageTest');
    -
    -goog.require('goog.proto2.FieldDescriptor');
    -goog.require('goog.testing.jsunit');
    -goog.require('proto2.TestAllTypes');
    -goog.require('someprotopackage.TestPackageTypes');
    -
    -function testPackage() {
    -  var message = new someprotopackage.TestPackageTypes();
    -  message.setOptionalInt32(45);
    -  message.setOtherAll(new proto2.TestAllTypes());
    -}
    -
    -function testFields() {
    -  var message = new proto2.TestAllTypes();
    -
    -  // Ensure that the fields are not set.
    -  assertFalse(message.hasOptionalInt32());
    -  assertFalse(message.hasOptionalInt64());
    -  assertFalse(message.hasOptionalUint32());
    -  assertFalse(message.hasOptionalUint64());
    -  assertFalse(message.hasOptionalSint32());
    -  assertFalse(message.hasOptionalSint64());
    -  assertFalse(message.hasOptionalFixed32());
    -  assertFalse(message.hasOptionalFixed64());
    -  assertFalse(message.hasOptionalSfixed32());
    -  assertFalse(message.hasOptionalSfixed64());
    -  assertFalse(message.hasOptionalFloat());
    -  assertFalse(message.hasOptionalDouble());
    -  assertFalse(message.hasOptionalBool());
    -  assertFalse(message.hasOptionalString());
    -  assertFalse(message.hasOptionalBytes());
    -  assertFalse(message.hasOptionalgroup());
    -  assertFalse(message.hasOptionalNestedMessage());
    -  assertFalse(message.hasOptionalNestedEnum());
    -
    -  // Check non-set values.
    -  assertNull(message.getOptionalInt32());
    -  assertNull(message.getOptionalInt64());
    -  assertNull(message.getOptionalFloat());
    -  assertNull(message.getOptionalString());
    -  assertNull(message.getOptionalBytes());
    -  assertNull(message.getOptionalNestedMessage());
    -  assertNull(message.getOptionalNestedEnum());
    -
    -  // Check default values.
    -  assertEquals(0, message.getOptionalInt32OrDefault());
    -  assertEquals('1', message.getOptionalInt64OrDefault());
    -  assertEquals(1.5, message.getOptionalFloatOrDefault());
    -  assertEquals('', message.getOptionalStringOrDefault());
    -  assertEquals('moo', message.getOptionalBytesOrDefault());
    -
    -  // Set the fields.
    -  message.setOptionalInt32(101);
    -  message.setOptionalInt64('102');
    -  message.setOptionalUint32(103);
    -  message.setOptionalUint64('104');
    -  message.setOptionalSint32(105);
    -  message.setOptionalSint64('106');
    -  message.setOptionalFixed32(107);
    -  message.setOptionalFixed64('108');
    -  message.setOptionalSfixed32(109);
    -  message.setOptionalSfixed64('110');
    -  message.setOptionalFloat(111.5);
    -  message.setOptionalDouble(112.5);
    -  message.setOptionalBool(true);
    -  message.setOptionalString('test');
    -  message.setOptionalBytes('abcd');
    -
    -  var group = new proto2.TestAllTypes.OptionalGroup();
    -  group.setA(111);
    -
    -  message.setOptionalgroup(group);
    -
    -  var nestedMessage = new proto2.TestAllTypes.NestedMessage();
    -  nestedMessage.setB(112);
    -
    -  message.setOptionalNestedMessage(nestedMessage);
    -
    -  message.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
    -
    -  // Ensure that the fields are set.
    -  assertTrue(message.hasOptionalInt32());
    -  assertTrue(message.hasOptionalInt64());
    -  assertTrue(message.hasOptionalUint32());
    -  assertTrue(message.hasOptionalUint64());
    -  assertTrue(message.hasOptionalSint32());
    -  assertTrue(message.hasOptionalSint64());
    -  assertTrue(message.hasOptionalFixed32());
    -  assertTrue(message.hasOptionalFixed64());
    -  assertTrue(message.hasOptionalSfixed32());
    -  assertTrue(message.hasOptionalSfixed64());
    -  assertTrue(message.hasOptionalFloat());
    -  assertTrue(message.hasOptionalDouble());
    -  assertTrue(message.hasOptionalBool());
    -  assertTrue(message.hasOptionalString());
    -  assertTrue(message.hasOptionalBytes());
    -  assertTrue(message.hasOptionalgroup());
    -  assertTrue(message.hasOptionalNestedMessage());
    -  assertTrue(message.hasOptionalNestedEnum());
    -
    -  // Ensure that there is a count of 1 for each of the fields.
    -  assertEquals(1, message.optionalInt32Count());
    -  assertEquals(1, message.optionalInt64Count());
    -  assertEquals(1, message.optionalUint32Count());
    -  assertEquals(1, message.optionalUint64Count());
    -  assertEquals(1, message.optionalSint32Count());
    -  assertEquals(1, message.optionalSint64Count());
    -  assertEquals(1, message.optionalFixed32Count());
    -  assertEquals(1, message.optionalFixed64Count());
    -  assertEquals(1, message.optionalSfixed32Count());
    -  assertEquals(1, message.optionalSfixed64Count());
    -  assertEquals(1, message.optionalFloatCount());
    -  assertEquals(1, message.optionalDoubleCount());
    -  assertEquals(1, message.optionalBoolCount());
    -  assertEquals(1, message.optionalStringCount());
    -  assertEquals(1, message.optionalBytesCount());
    -  assertEquals(1, message.optionalgroupCount());
    -  assertEquals(1, message.optionalNestedMessageCount());
    -  assertEquals(1, message.optionalNestedEnumCount());
    -
    -  // Ensure that the fields have the values expected.
    -  assertEquals(101, message.getOptionalInt32());
    -  assertEquals('102', message.getOptionalInt64());
    -  assertEquals(103, message.getOptionalUint32());
    -  assertEquals('104', message.getOptionalUint64());
    -  assertEquals(105, message.getOptionalSint32());
    -  assertEquals('106', message.getOptionalSint64());
    -  assertEquals(107, message.getOptionalFixed32());
    -  assertEquals('108', message.getOptionalFixed64());
    -  assertEquals(109, message.getOptionalSfixed32());
    -  assertEquals('110', message.getOptionalSfixed64());
    -  assertEquals(111.5, message.getOptionalFloat());
    -  assertEquals(112.5, message.getOptionalDouble());
    -  assertEquals(true, message.getOptionalBool());
    -  assertEquals('test', message.getOptionalString());
    -  assertEquals('abcd', message.getOptionalBytes());
    -  assertEquals(group, message.getOptionalgroup());
    -  assertEquals(nestedMessage, message.getOptionalNestedMessage());
    -  assertEquals(proto2.TestAllTypes.NestedEnum.FOO,
    -               message.getOptionalNestedEnum());
    -}
    -
    -function testRepeated() {
    -  var message = new proto2.TestAllTypes();
    -
    -  // Ensure that the fields are not set.
    -  assertFalse(message.hasRepeatedInt32());
    -  assertFalse(message.hasRepeatedInt64());
    -  assertFalse(message.hasRepeatedUint32());
    -  assertFalse(message.hasRepeatedUint64());
    -  assertFalse(message.hasRepeatedSint32());
    -  assertFalse(message.hasRepeatedSint64());
    -  assertFalse(message.hasRepeatedFixed32());
    -  assertFalse(message.hasRepeatedFixed64());
    -  assertFalse(message.hasRepeatedSfixed32());
    -  assertFalse(message.hasRepeatedSfixed64());
    -  assertFalse(message.hasRepeatedFloat());
    -  assertFalse(message.hasRepeatedDouble());
    -  assertFalse(message.hasRepeatedBool());
    -  assertFalse(message.hasRepeatedString());
    -  assertFalse(message.hasRepeatedBytes());
    -  assertFalse(message.hasRepeatedgroup());
    -  assertFalse(message.hasRepeatedNestedMessage());
    -  assertFalse(message.hasRepeatedNestedEnum());
    -
    -  // Expect the arrays to be empty.
    -  assertEquals(0, message.repeatedInt32Array().length);
    -  assertEquals(0, message.repeatedInt64Array().length);
    -  assertEquals(0, message.repeatedUint32Array().length);
    -  assertEquals(0, message.repeatedUint64Array().length);
    -  assertEquals(0, message.repeatedSint32Array().length);
    -  assertEquals(0, message.repeatedSint64Array().length);
    -  assertEquals(0, message.repeatedFixed32Array().length);
    -  assertEquals(0, message.repeatedFixed64Array().length);
    -  assertEquals(0, message.repeatedSfixed32Array().length);
    -  assertEquals(0, message.repeatedSfixed64Array().length);
    -  assertEquals(0, message.repeatedFloatArray().length);
    -  assertEquals(0, message.repeatedDoubleArray().length);
    -  assertEquals(0, message.repeatedBoolArray().length);
    -  assertEquals(0, message.repeatedStringArray().length);
    -  assertEquals(0, message.repeatedBytesArray().length);
    -  assertEquals(0, message.repeatedgroupArray().length);
    -  assertEquals(0, message.repeatedNestedMessageArray().length);
    -  assertEquals(0, message.repeatedNestedEnumArray().length);
    -
    -  // Set the fields.
    -  message.addRepeatedInt32(101);
    -  message.addRepeatedInt64('102');
    -  message.addRepeatedUint32(103);
    -  message.addRepeatedUint64('104');
    -  message.addRepeatedSint32(105);
    -  message.addRepeatedSint64('106');
    -  message.addRepeatedFixed32(107);
    -  message.addRepeatedFixed64('108');
    -  message.addRepeatedSfixed32(109);
    -  message.addRepeatedSfixed64('110');
    -  message.addRepeatedFloat(111.5);
    -  message.addRepeatedDouble(112.5);
    -  message.addRepeatedBool(true);
    -  message.addRepeatedString('test');
    -  message.addRepeatedBytes('abcd');
    -
    -  message.addRepeatedInt32(201);
    -  message.addRepeatedInt64('202');
    -  message.addRepeatedUint32(203);
    -  message.addRepeatedUint64('204');
    -  message.addRepeatedSint32(205);
    -  message.addRepeatedSint64('206');
    -  message.addRepeatedFixed32(207);
    -  message.addRepeatedFixed64('208');
    -  message.addRepeatedSfixed32(209);
    -  message.addRepeatedSfixed64('210');
    -  message.addRepeatedFloat(211.5);
    -  message.addRepeatedDouble(212.5);
    -  message.addRepeatedBool(true);
    -  message.addRepeatedString('test#2');
    -  message.addRepeatedBytes('efgh');
    -
    -
    -  var group1 = new proto2.TestAllTypes.RepeatedGroup();
    -  group1.addA(111);
    -
    -  message.addRepeatedgroup(group1);
    -
    -  var group2 = new proto2.TestAllTypes.RepeatedGroup();
    -  group2.addA(211);
    -
    -  message.addRepeatedgroup(group2);
    -
    -  var nestedMessage1 = new proto2.TestAllTypes.NestedMessage();
    -  nestedMessage1.setB(112);
    -  message.addRepeatedNestedMessage(nestedMessage1);
    -
    -  var nestedMessage2 = new proto2.TestAllTypes.NestedMessage();
    -  nestedMessage2.setB(212);
    -  message.addRepeatedNestedMessage(nestedMessage2);
    -
    -  message.addRepeatedNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
    -  message.addRepeatedNestedEnum(proto2.TestAllTypes.NestedEnum.BAR);
    -
    -  // Ensure that the fields are set.
    -  assertTrue(message.hasRepeatedInt32());
    -  assertTrue(message.hasRepeatedInt64());
    -  assertTrue(message.hasRepeatedUint32());
    -  assertTrue(message.hasRepeatedUint64());
    -  assertTrue(message.hasRepeatedSint32());
    -  assertTrue(message.hasRepeatedSint64());
    -  assertTrue(message.hasRepeatedFixed32());
    -  assertTrue(message.hasRepeatedFixed64());
    -  assertTrue(message.hasRepeatedSfixed32());
    -  assertTrue(message.hasRepeatedSfixed64());
    -  assertTrue(message.hasRepeatedFloat());
    -  assertTrue(message.hasRepeatedDouble());
    -  assertTrue(message.hasRepeatedBool());
    -  assertTrue(message.hasRepeatedString());
    -  assertTrue(message.hasRepeatedBytes());
    -  assertTrue(message.hasRepeatedgroup());
    -  assertTrue(message.hasRepeatedNestedMessage());
    -  assertTrue(message.hasRepeatedNestedEnum());
    -
    -  // Ensure that there is a count of 2 for each of the fields.
    -  assertEquals(2, message.repeatedInt32Count());
    -  assertEquals(2, message.repeatedInt64Count());
    -  assertEquals(2, message.repeatedUint32Count());
    -  assertEquals(2, message.repeatedUint64Count());
    -  assertEquals(2, message.repeatedSint32Count());
    -  assertEquals(2, message.repeatedSint64Count());
    -  assertEquals(2, message.repeatedFixed32Count());
    -  assertEquals(2, message.repeatedFixed64Count());
    -  assertEquals(2, message.repeatedSfixed32Count());
    -  assertEquals(2, message.repeatedSfixed64Count());
    -  assertEquals(2, message.repeatedFloatCount());
    -  assertEquals(2, message.repeatedDoubleCount());
    -  assertEquals(2, message.repeatedBoolCount());
    -  assertEquals(2, message.repeatedStringCount());
    -  assertEquals(2, message.repeatedBytesCount());
    -  assertEquals(2, message.repeatedgroupCount());
    -  assertEquals(2, message.repeatedNestedMessageCount());
    -  assertEquals(2, message.repeatedNestedEnumCount());
    -
    -  // Ensure that the fields have the values expected.
    -  assertEquals(101, message.getRepeatedInt32(0));
    -  assertEquals('102', message.getRepeatedInt64(0));
    -  assertEquals(103, message.getRepeatedUint32(0));
    -  assertEquals('104', message.getRepeatedUint64(0));
    -  assertEquals(105, message.getRepeatedSint32(0));
    -  assertEquals('106', message.getRepeatedSint64(0));
    -  assertEquals(107, message.getRepeatedFixed32(0));
    -  assertEquals('108', message.getRepeatedFixed64(0));
    -  assertEquals(109, message.getRepeatedSfixed32(0));
    -  assertEquals('110', message.getRepeatedSfixed64(0));
    -  assertEquals(111.5, message.getRepeatedFloat(0));
    -  assertEquals(112.5, message.getRepeatedDouble(0));
    -  assertEquals(true, message.getRepeatedBool(0));
    -  assertEquals('test', message.getRepeatedString(0));
    -  assertEquals('abcd', message.getRepeatedBytes(0));
    -  assertEquals(group1, message.getRepeatedgroup(0));
    -  assertEquals(nestedMessage1, message.getRepeatedNestedMessage(0));
    -  assertEquals(proto2.TestAllTypes.NestedEnum.FOO,
    -               message.getRepeatedNestedEnum(0));
    -
    -  assertEquals(201, message.getRepeatedInt32(1));
    -  assertEquals('202', message.getRepeatedInt64(1));
    -  assertEquals(203, message.getRepeatedUint32(1));
    -  assertEquals('204', message.getRepeatedUint64(1));
    -  assertEquals(205, message.getRepeatedSint32(1));
    -  assertEquals('206', message.getRepeatedSint64(1));
    -  assertEquals(207, message.getRepeatedFixed32(1));
    -  assertEquals('208', message.getRepeatedFixed64(1));
    -  assertEquals(209, message.getRepeatedSfixed32(1));
    -  assertEquals('210', message.getRepeatedSfixed64(1));
    -  assertEquals(211.5, message.getRepeatedFloat(1));
    -  assertEquals(212.5, message.getRepeatedDouble(1));
    -  assertEquals(true, message.getRepeatedBool(1));
    -  assertEquals('test#2', message.getRepeatedString(1));
    -  assertEquals('efgh', message.getRepeatedBytes(1));
    -  assertEquals(group2, message.getRepeatedgroup(1));
    -  assertEquals(nestedMessage2, message.getRepeatedNestedMessage(1));
    -  assertEquals(proto2.TestAllTypes.NestedEnum.BAR,
    -               message.getRepeatedNestedEnum(1));
    -
    -  // Check the array lengths.
    -  assertEquals(2, message.repeatedInt32Array().length);
    -  assertEquals(2, message.repeatedInt64Array().length);
    -  assertEquals(2, message.repeatedUint32Array().length);
    -  assertEquals(2, message.repeatedUint64Array().length);
    -  assertEquals(2, message.repeatedSint32Array().length);
    -  assertEquals(2, message.repeatedSint64Array().length);
    -  assertEquals(2, message.repeatedFixed32Array().length);
    -  assertEquals(2, message.repeatedFixed64Array().length);
    -  assertEquals(2, message.repeatedSfixed32Array().length);
    -  assertEquals(2, message.repeatedSfixed64Array().length);
    -  assertEquals(2, message.repeatedFloatArray().length);
    -  assertEquals(2, message.repeatedDoubleArray().length);
    -  assertEquals(2, message.repeatedBoolArray().length);
    -  assertEquals(2, message.repeatedStringArray().length);
    -  assertEquals(2, message.repeatedBytesArray().length);
    -  assertEquals(2, message.repeatedgroupArray().length);
    -  assertEquals(2, message.repeatedNestedMessageArray().length);
    -  assertEquals(2, message.repeatedNestedEnumArray().length);
    -
    -  // Check the array values.
    -  assertEquals(message.getRepeatedInt32(0), message.repeatedInt32Array()[0]);
    -  assertEquals(message.getRepeatedInt64(0), message.repeatedInt64Array()[0]);
    -  assertEquals(message.getRepeatedUint32(0), message.repeatedUint32Array()[0]);
    -  assertEquals(message.getRepeatedUint64(0), message.repeatedUint64Array()[0]);
    -  assertEquals(message.getRepeatedSint32(0), message.repeatedSint32Array()[0]);
    -  assertEquals(message.getRepeatedSint64(0), message.repeatedSint64Array()[0]);
    -  assertEquals(message.getRepeatedFixed32(0),
    -               message.repeatedFixed32Array()[0]);
    -  assertEquals(message.getRepeatedFixed64(0),
    -               message.repeatedFixed64Array()[0]);
    -  assertEquals(message.getRepeatedSfixed32(0),
    -               message.repeatedSfixed32Array()[0]);
    -  assertEquals(message.getRepeatedSfixed64(0),
    -               message.repeatedSfixed64Array()[0]);
    -  assertEquals(message.getRepeatedFloat(0), message.repeatedFloatArray()[0]);
    -  assertEquals(message.getRepeatedDouble(0), message.repeatedDoubleArray()[0]);
    -  assertEquals(message.getRepeatedBool(0), message.repeatedBoolArray()[0]);
    -  assertEquals(message.getRepeatedString(0), message.repeatedStringArray()[0]);
    -  assertEquals(message.getRepeatedBytes(0), message.repeatedBytesArray()[0]);
    -  assertEquals(message.getRepeatedgroup(0), message.repeatedgroupArray()[0]);
    -  assertEquals(message.getRepeatedNestedMessage(0),
    -               message.repeatedNestedMessageArray()[0]);
    -  assertEquals(message.getRepeatedNestedEnum(0),
    -               message.repeatedNestedEnumArray()[0]);
    -
    -  assertEquals(message.getRepeatedInt32(1), message.repeatedInt32Array()[1]);
    -  assertEquals(message.getRepeatedInt64(1), message.repeatedInt64Array()[1]);
    -  assertEquals(message.getRepeatedUint32(1), message.repeatedUint32Array()[1]);
    -  assertEquals(message.getRepeatedUint64(1), message.repeatedUint64Array()[1]);
    -  assertEquals(message.getRepeatedSint32(1), message.repeatedSint32Array()[1]);
    -  assertEquals(message.getRepeatedSint64(1), message.repeatedSint64Array()[1]);
    -  assertEquals(message.getRepeatedFixed32(1),
    -               message.repeatedFixed32Array()[1]);
    -  assertEquals(message.getRepeatedFixed64(1),
    -               message.repeatedFixed64Array()[1]);
    -  assertEquals(message.getRepeatedSfixed32(1),
    -               message.repeatedSfixed32Array()[1]);
    -  assertEquals(message.getRepeatedSfixed64(1),
    -               message.repeatedSfixed64Array()[1]);
    -  assertEquals(message.getRepeatedFloat(1), message.repeatedFloatArray()[1]);
    -  assertEquals(message.getRepeatedDouble(1), message.repeatedDoubleArray()[1]);
    -  assertEquals(message.getRepeatedBool(1), message.repeatedBoolArray()[1]);
    -  assertEquals(message.getRepeatedString(1), message.repeatedStringArray()[1]);
    -  assertEquals(message.getRepeatedBytes(1), message.repeatedBytesArray()[1]);
    -  assertEquals(message.getRepeatedgroup(1), message.repeatedgroupArray()[1]);
    -  assertEquals(message.getRepeatedNestedMessage(1),
    -               message.repeatedNestedMessageArray()[1]);
    -  assertEquals(message.getRepeatedNestedEnum(1),
    -               message.repeatedNestedEnumArray()[1]);
    -}
    -
    -function testDescriptor() {
    -  var message = new proto2.TestAllTypes();
    -  var descriptor = message.getDescriptor();
    -
    -  assertEquals('TestAllTypes', descriptor.getName());
    -  assertEquals('TestAllTypes', descriptor.getFullName());
    -  assertEquals(null, descriptor.getContainingType());
    -
    -  var nestedMessage = new proto2.TestAllTypes.NestedMessage();
    -  var nestedDescriptor = nestedMessage.getDescriptor();
    -
    -  assertEquals('NestedMessage', nestedDescriptor.getName());
    -  assertEquals('TestAllTypes.NestedMessage',
    -               nestedDescriptor.getFullName());
    -  assertEquals(descriptor, nestedDescriptor.getContainingType());
    -}
    -
    -function testFieldDescriptor() {
    -  var message = new proto2.TestAllTypes();
    -  var descriptor = message.getDescriptor();
    -  var fields = descriptor.getFields();
    -
    -  assertEquals(53, fields.length);
    -
    -  // Check the containing types.
    -  for (var i = 0; i < fields.length; ++i) {
    -    assertEquals(descriptor, fields[i].getContainingType());
    -  }
    -
    -  // Check the field names.
    -  assertEquals('optional_int32', fields[0].getName());
    -  assertEquals('optional_int64', fields[1].getName());
    -  assertEquals('optional_uint32', fields[2].getName());
    -  assertEquals('optional_uint64', fields[3].getName());
    -  assertEquals('optional_sint32', fields[4].getName());
    -  assertEquals('optional_sint64', fields[5].getName());
    -  assertEquals('optional_fixed32', fields[6].getName());
    -  assertEquals('optional_fixed64', fields[7].getName());
    -  assertEquals('optional_sfixed32', fields[8].getName());
    -  assertEquals('optional_sfixed64', fields[9].getName());
    -  assertEquals('optional_float', fields[10].getName());
    -  assertEquals('optional_double', fields[11].getName());
    -  assertEquals('optional_bool', fields[12].getName());
    -  assertEquals('optional_string', fields[13].getName());
    -  assertEquals('optional_bytes', fields[14].getName());
    -  assertEquals('optionalgroup', fields[15].getName());
    -  assertEquals('optional_nested_message', fields[16].getName());
    -  assertEquals('optional_nested_enum', fields[17].getName());
    -
    -  assertEquals('repeated_int32', fields[18].getName());
    -  assertEquals('repeated_int64', fields[19].getName());
    -  assertEquals('repeated_uint32', fields[20].getName());
    -  assertEquals('repeated_uint64', fields[21].getName());
    -  assertEquals('repeated_sint32', fields[22].getName());
    -  assertEquals('repeated_sint64', fields[23].getName());
    -  assertEquals('repeated_fixed32', fields[24].getName());
    -  assertEquals('repeated_fixed64', fields[25].getName());
    -  assertEquals('repeated_sfixed32', fields[26].getName());
    -  assertEquals('repeated_sfixed64', fields[27].getName());
    -  assertEquals('repeated_float', fields[28].getName());
    -  assertEquals('repeated_double', fields[29].getName());
    -  assertEquals('repeated_bool', fields[30].getName());
    -  assertEquals('repeated_string', fields[31].getName());
    -  assertEquals('repeated_bytes', fields[32].getName());
    -  assertEquals('repeatedgroup', fields[33].getName());
    -  assertEquals('repeated_nested_message', fields[34].getName());
    -  assertEquals('repeated_nested_enum', fields[35].getName());
    -
    -  assertEquals('optional_int64_number', fields[36].getName());
    -  assertEquals('optional_int64_string', fields[37].getName());
    -  assertEquals('repeated_int64_number', fields[38].getName());
    -  assertEquals('repeated_int64_string', fields[39].getName());
    -
    -  assertEquals('packed_int32', fields[40].getName());
    -  assertEquals('packed_int64', fields[41].getName());
    -  assertEquals('packed_uint32', fields[42].getName());
    -  assertEquals('packed_uint64', fields[43].getName());
    -  assertEquals('packed_sint32', fields[44].getName());
    -  assertEquals('packed_sint64', fields[45].getName());
    -  assertEquals('packed_fixed32', fields[46].getName());
    -  assertEquals('packed_fixed64', fields[47].getName());
    -  assertEquals('packed_sfixed32', fields[48].getName());
    -  assertEquals('packed_sfixed64', fields[49].getName());
    -  assertEquals('packed_float', fields[50].getName());
    -  assertEquals('packed_double', fields[51].getName());
    -  assertEquals('packed_bool', fields[52].getName());
    -
    -  // Check the field types.
    -  var FieldType = goog.proto2.FieldDescriptor.FieldType;
    -  assertEquals(FieldType.INT32, fields[0].getFieldType());
    -  assertEquals(FieldType.INT64, fields[1].getFieldType());
    -  assertEquals(FieldType.UINT32, fields[2].getFieldType());
    -  assertEquals(FieldType.UINT64, fields[3].getFieldType());
    -  assertEquals(FieldType.SINT32, fields[4].getFieldType());
    -  assertEquals(FieldType.SINT64, fields[5].getFieldType());
    -  assertEquals(FieldType.FIXED32, fields[6].getFieldType());
    -  assertEquals(FieldType.FIXED64, fields[7].getFieldType());
    -  assertEquals(FieldType.SFIXED32, fields[8].getFieldType());
    -  assertEquals(FieldType.SFIXED64, fields[9].getFieldType());
    -  assertEquals(FieldType.FLOAT, fields[10].getFieldType());
    -  assertEquals(FieldType.DOUBLE, fields[11].getFieldType());
    -  assertEquals(FieldType.BOOL, fields[12].getFieldType());
    -  assertEquals(FieldType.STRING, fields[13].getFieldType());
    -  assertEquals(FieldType.BYTES, fields[14].getFieldType());
    -  assertEquals(FieldType.GROUP, fields[15].getFieldType());
    -  assertEquals(FieldType.MESSAGE, fields[16].getFieldType());
    -  assertEquals(FieldType.ENUM, fields[17].getFieldType());
    -
    -  assertEquals(FieldType.INT32, fields[18].getFieldType());
    -  assertEquals(FieldType.INT64, fields[19].getFieldType());
    -  assertEquals(FieldType.UINT32, fields[20].getFieldType());
    -  assertEquals(FieldType.UINT64, fields[21].getFieldType());
    -  assertEquals(FieldType.SINT32, fields[22].getFieldType());
    -  assertEquals(FieldType.SINT64, fields[23].getFieldType());
    -  assertEquals(FieldType.FIXED32, fields[24].getFieldType());
    -  assertEquals(FieldType.FIXED64, fields[25].getFieldType());
    -  assertEquals(FieldType.SFIXED32, fields[26].getFieldType());
    -  assertEquals(FieldType.SFIXED64, fields[27].getFieldType());
    -  assertEquals(FieldType.FLOAT, fields[28].getFieldType());
    -  assertEquals(FieldType.DOUBLE, fields[29].getFieldType());
    -  assertEquals(FieldType.BOOL, fields[30].getFieldType());
    -  assertEquals(FieldType.STRING, fields[31].getFieldType());
    -  assertEquals(FieldType.BYTES, fields[32].getFieldType());
    -  assertEquals(FieldType.GROUP, fields[33].getFieldType());
    -  assertEquals(FieldType.MESSAGE, fields[34].getFieldType());
    -  assertEquals(FieldType.ENUM, fields[35].getFieldType());
    -
    -  assertEquals(FieldType.INT64, fields[36].getFieldType());
    -  assertEquals(FieldType.INT64, fields[37].getFieldType());
    -  assertEquals(FieldType.INT64, fields[38].getFieldType());
    -  assertEquals(FieldType.INT64, fields[39].getFieldType());
    -
    -  assertEquals(FieldType.INT32, fields[40].getFieldType());
    -  assertEquals(FieldType.INT64, fields[41].getFieldType());
    -  assertEquals(FieldType.UINT32, fields[42].getFieldType());
    -  assertEquals(FieldType.UINT64, fields[43].getFieldType());
    -  assertEquals(FieldType.SINT32, fields[44].getFieldType());
    -  assertEquals(FieldType.SINT64, fields[45].getFieldType());
    -  assertEquals(FieldType.FIXED32, fields[46].getFieldType());
    -  assertEquals(FieldType.FIXED64, fields[47].getFieldType());
    -  assertEquals(FieldType.SFIXED32, fields[48].getFieldType());
    -  assertEquals(FieldType.SFIXED64, fields[49].getFieldType());
    -  assertEquals(FieldType.FLOAT, fields[50].getFieldType());
    -  assertEquals(FieldType.DOUBLE, fields[51].getFieldType());
    -  assertEquals(FieldType.BOOL, fields[52].getFieldType());
    -
    -  // Check the field native types.
    -  // Singular.
    -  assertEquals(Number, fields[0].getNativeType());
    -  assertEquals(String, fields[1].getNativeType()); // 64 bit values are strings.
    -  assertEquals(Number, fields[2].getNativeType());
    -  assertEquals(String, fields[3].getNativeType());
    -  assertEquals(Number, fields[4].getNativeType());
    -  assertEquals(String, fields[5].getNativeType());
    -  assertEquals(Number, fields[6].getNativeType());
    -  assertEquals(String, fields[7].getNativeType());
    -  assertEquals(Number, fields[8].getNativeType());
    -  assertEquals(String, fields[9].getNativeType());
    -  assertEquals(Number, fields[10].getNativeType());
    -  assertEquals(Number, fields[11].getNativeType());
    -
    -  assertEquals(Boolean, fields[12].getNativeType());
    -
    -  assertEquals(String, fields[13].getNativeType());
    -  assertEquals(String, fields[14].getNativeType());
    -
    -  assertEquals(proto2.TestAllTypes.OptionalGroup, fields[15].getNativeType());
    -  assertEquals(proto2.TestAllTypes.NestedMessage, fields[16].getNativeType());
    -  assertEquals(proto2.TestAllTypes.NestedEnum, fields[17].getNativeType());
    -
    -  assertEquals(Number, fields[36].getNativeType());  // [jstype="number"]
    -  assertEquals(String, fields[37].getNativeType());
    -
    -  // Repeated.
    -  assertEquals(Number, fields[18].getNativeType());
    -  assertEquals(String, fields[19].getNativeType());
    -  assertEquals(Number, fields[20].getNativeType());
    -  assertEquals(String, fields[21].getNativeType());
    -  assertEquals(Number, fields[22].getNativeType());
    -  assertEquals(String, fields[23].getNativeType());
    -  assertEquals(Number, fields[24].getNativeType());
    -  assertEquals(String, fields[25].getNativeType());
    -  assertEquals(Number, fields[26].getNativeType());
    -  assertEquals(String, fields[27].getNativeType());
    -  assertEquals(Number, fields[28].getNativeType());
    -  assertEquals(Number, fields[29].getNativeType());
    -
    -  assertEquals(Boolean, fields[30].getNativeType());
    -
    -  assertEquals(String, fields[31].getNativeType());
    -  assertEquals(String, fields[32].getNativeType());
    -
    -  assertEquals(proto2.TestAllTypes.RepeatedGroup, fields[33].getNativeType());
    -  assertEquals(proto2.TestAllTypes.NestedMessage, fields[34].getNativeType());
    -  assertEquals(proto2.TestAllTypes.NestedEnum, fields[35].getNativeType());
    -
    -  assertEquals(Number, fields[38].getNativeType());  // [jstype="number"]
    -  assertEquals(String, fields[39].getNativeType());
    -
    -  // Packed (only numeric types can be packed).
    -  assertEquals(Number, fields[40].getNativeType());
    -  assertEquals(Number, fields[41].getNativeType());
    -  assertEquals(Number, fields[42].getNativeType());
    -  assertEquals(Number, fields[43].getNativeType());
    -  assertEquals(Number, fields[44].getNativeType());
    -  assertEquals(Number, fields[45].getNativeType());
    -  assertEquals(Number, fields[46].getNativeType());
    -  assertEquals(Number, fields[47].getNativeType());
    -  assertEquals(Number, fields[48].getNativeType());
    -  assertEquals(Number, fields[49].getNativeType());
    -  assertEquals(Number, fields[50].getNativeType());
    -  assertEquals(Number, fields[51].getNativeType());
    -  assertEquals(Boolean, fields[52].getNativeType());
    -}
    -
    -function testUnknown() {
    -  var message = new proto2.TestAllTypes();
    -
    -  // Set some unknown fields.
    -  message.setUnknown(1000, 101);
    -  message.setUnknown(1001, -102);
    -  message.setUnknown(1002, true);
    -  message.setUnknown(1003, 'abcd');
    -  message.setUnknown(1004, ['he', 'llo']);
    -
    -  // Ensure we find them all.
    -  var count = 0;
    -
    -  message.forEachUnknown(function(tag, value) {
    -    if (tag == 1000) {
    -      assertEquals(101, value);
    -    }
    -
    -    if (tag == 1001) {
    -      assertEquals(-102, value);
    -    }
    -
    -    if (tag == 1002) {
    -      assertEquals(true, value);
    -    }
    -
    -    if (tag == 1003) {
    -      assertEquals('abcd', value);
    -    }
    -
    -    if (tag == 1004) {
    -      assertEquals('he', value[0]);
    -      assertEquals('llo', value[1]);
    -    }
    -
    -    count++;
    -  });
    -
    -  assertEquals(5, count);
    -}
    -
    -function testReflection() {
    -  var message = new proto2.TestAllTypes();
    -  var descriptor = message.getDescriptor();
    -  var optionalInt = descriptor.findFieldByName('optional_int32');
    -  var optionalString = descriptor.findFieldByName('optional_string');
    -  var repeatedInt64 = descriptor.findFieldByName('repeated_int64');
    -  var optionalWrong = descriptor.findFieldByName('foo_bar');
    -
    -  assertFalse(optionalInt == null);
    -  assertFalse(optionalString == null);
    -  assertFalse(repeatedInt64 == null);
    -  assertTrue(optionalWrong == null);
    -
    -  // Check to ensure the fields are empty.
    -  assertFalse(message.has(optionalInt));
    -  assertFalse(message.has(optionalString));
    -  assertFalse(message.has(repeatedInt64));
    -
    -  assertEquals(0, message.arrayOf(repeatedInt64).length);
    -
    -  // Check default values.
    -  assertEquals(0, message.getOrDefault(optionalInt));
    -  assertEquals('', message.getOrDefault(optionalString));
    -
    -  // Set some of the fields.
    -  message.set(optionalString, 'hello!');
    -
    -  message.add(repeatedInt64, '101');
    -  message.add(repeatedInt64, '102');
    -
    -  // Check the fields.
    -  assertFalse(message.has(optionalInt));
    -
    -  assertTrue(message.has(optionalString));
    -  assertTrue(message.hasOptionalString());
    -
    -  assertTrue(message.has(repeatedInt64));
    -  assertTrue(message.hasRepeatedInt64());
    -
    -  // Check the values.
    -  assertEquals('hello!', message.get(optionalString));
    -  assertEquals('hello!', message.getOptionalString());
    -
    -  assertEquals('101', message.get(repeatedInt64, 0));
    -  assertEquals('102', message.get(repeatedInt64, 1));
    -
    -  assertEquals('101', message.getRepeatedInt64(0));
    -  assertEquals('102', message.getRepeatedInt64(1));
    -
    -  // Check the count.
    -  assertEquals(0, message.countOf(optionalInt));
    -
    -  assertEquals(1, message.countOf(optionalString));
    -  assertEquals(1, message.optionalStringCount());
    -
    -  assertEquals(2, message.countOf(repeatedInt64));
    -  assertEquals(2, message.repeatedInt64Count());
    -
    -  // Check the array.
    -  assertEquals(2, message.arrayOf(repeatedInt64).length);
    -
    -  assertEquals(message.get(repeatedInt64, 0),
    -      message.arrayOf(repeatedInt64)[0]);
    -
    -  assertEquals(message.get(repeatedInt64, 1),
    -      message.arrayOf(repeatedInt64)[1]);
    -}
    -
    -function testDefaultValuesForMessages() {
    -  var message = new proto2.TestDefaultParent();
    -  // Ideally this object would be immutable, but the current API does not
    -  // enforce that behavior, so get**OrDefault returns a new instance every time.
    -  var child = message.getChildOrDefault();
    -  child.setFoo(false);
    -  // Changing the value returned by get**OrDefault does not actually change
    -  // the value stored in the parent message.
    -  assertFalse(message.hasChild());
    -  assertNull(message.getChild());
    -
    -  var message2 = new proto2.TestDefaultParent();
    -  var child2 = message2.getChildOrDefault();
    -  assertNull(message2.getChild());
    -
    -  // The parent message returns a different object for the default.
    -  assertNotEquals(child, child2);
    -
    -  // You've only changed the value of child, so child2 should be unaffected.
    -  assertFalse(child2.hasFoo());
    -  assertTrue(child2.getFooOrDefault());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/proto2/serializer.js b/src/database/third_party/closure-library/closure/goog/proto2/serializer.js
    deleted file mode 100644
    index 37828134fd6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/proto2/serializer.js
    +++ /dev/null
    @@ -1,182 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Base class for all Protocol Buffer 2 serializers.
    - */
    -
    -goog.provide('goog.proto2.Serializer');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.proto2.FieldDescriptor');
    -goog.require('goog.proto2.Message');
    -
    -
    -
    -/**
    - * Abstract base class for PB2 serializers. A serializer is a class which
    - * implements the serialization and deserialization of a Protocol Buffer Message
    - * to/from a specific format.
    - *
    - * @constructor
    - */
    -goog.proto2.Serializer = function() {};
    -
    -
    -/**
    - * @define {boolean} Whether to decode and convert symbolic enum values to
    - * actual enum values or leave them as strings.
    - */
    -goog.define('goog.proto2.Serializer.DECODE_SYMBOLIC_ENUMS', false);
    -
    -
    -/**
    - * Serializes a message to the expected format.
    - *
    - * @param {goog.proto2.Message} message The message to be serialized.
    - *
    - * @return {*} The serialized form of the message.
    - */
    -goog.proto2.Serializer.prototype.serialize = goog.abstractMethod;
    -
    -
    -/**
    - * Returns the serialized form of the given value for the given field if the
    - * field is a Message or Group and returns the value unchanged otherwise, except
    - * for Infinity, -Infinity and NaN numerical values which are converted to
    - * string representation.
    - *
    - * @param {goog.proto2.FieldDescriptor} field The field from which this
    - *     value came.
    - *
    - * @param {*} value The value of the field.
    - *
    - * @return {*} The value.
    - * @protected
    - */
    -goog.proto2.Serializer.prototype.getSerializedValue = function(field, value) {
    -  if (field.isCompositeType()) {
    -    return this.serialize(/** @type {goog.proto2.Message} */ (value));
    -  } else if (goog.isNumber(value) && !isFinite(value)) {
    -    return value.toString();
    -  } else {
    -    return value;
    -  }
    -};
    -
    -
    -/**
    - * Deserializes a message from the expected format.
    - *
    - * @param {goog.proto2.Descriptor} descriptor The descriptor of the message
    - *     to be created.
    - * @param {*} data The data of the message.
    - *
    - * @return {!goog.proto2.Message} The message created.
    - */
    -goog.proto2.Serializer.prototype.deserialize = function(descriptor, data) {
    -  var message = descriptor.createMessageInstance();
    -  this.deserializeTo(message, data);
    -  goog.asserts.assert(message instanceof goog.proto2.Message);
    -  return message;
    -};
    -
    -
    -/**
    - * Deserializes a message from the expected format and places the
    - * data in the message.
    - *
    - * @param {goog.proto2.Message} message The message in which to
    - *     place the information.
    - * @param {*} data The data of the message.
    - */
    -goog.proto2.Serializer.prototype.deserializeTo = goog.abstractMethod;
    -
    -
    -/**
    - * Returns the deserialized form of the given value for the given field if the
    - * field is a Message or Group and returns the value, converted or unchanged,
    - * for primitive field types otherwise.
    - *
    - * @param {goog.proto2.FieldDescriptor} field The field from which this
    - *     value came.
    - *
    - * @param {*} value The value of the field.
    - *
    - * @return {*} The value.
    - * @protected
    - */
    -goog.proto2.Serializer.prototype.getDeserializedValue = function(field, value) {
    -  // Composite types are deserialized recursively.
    -  if (field.isCompositeType()) {
    -    if (value instanceof goog.proto2.Message) {
    -      return value;
    -    }
    -
    -    return this.deserialize(field.getFieldMessageType(), value);
    -  }
    -
    -  // Decode enum values.
    -  if (field.getFieldType() == goog.proto2.FieldDescriptor.FieldType.ENUM) {
    -    // If it's a string, get enum value by name.
    -    // NB: In order this feature to work, property renaming should be turned off
    -    // for the respective enums.
    -    if (goog.proto2.Serializer.DECODE_SYMBOLIC_ENUMS && goog.isString(value)) {
    -      // enumType is a regular Javascript enum as defined in field's metadata.
    -      var enumType = field.getNativeType();
    -      if (enumType.hasOwnProperty(value)) {
    -        return enumType[value];
    -      }
    -    }
    -    // Return unknown values as is for backward compatibility.
    -    return value;
    -  }
    -
    -  // Return the raw value if the field does not allow the JSON input to be
    -  // converted.
    -  if (!field.deserializationConversionPermitted()) {
    -    return value;
    -  }
    -
    -  // Convert to native type of field.  Return the converted value or fall
    -  // through to return the raw value.  The JSON encoding of int64 value 123
    -  // might be either the number 123 or the string "123".  The field native type
    -  // could be either Number or String (depending on field options in the .proto
    -  // file).  All four combinations should work correctly.
    -  var nativeType = field.getNativeType();
    -  if (nativeType === String) {
    -    // JSON numbers can be converted to strings.
    -    if (goog.isNumber(value)) {
    -      return String(value);
    -    }
    -  } else if (nativeType === Number) {
    -    // JSON strings are sometimes used for large integer numeric values, as well
    -    // as Infinity, -Infinity and NaN.
    -    if (goog.isString(value)) {
    -      // Handle +/- Infinity and NaN values.
    -      if (value === 'Infinity' || value === '-Infinity' || value === 'NaN') {
    -        return Number(value);
    -      }
    -
    -      // Validate the string.  If the string is not an integral number, we would
    -      // rather have an assertion or error in the caller than a mysterious NaN
    -      // value.
    -      if (/^-?[0-9]+$/.test(value)) {
    -        return Number(value);
    -      }
    -    }
    -  }
    -
    -  return value;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/proto2/test.pb.js b/src/database/third_party/closure-library/closure/goog/proto2/test.pb.js
    deleted file mode 100644
    index 5832edaed61..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/proto2/test.pb.js
    +++ /dev/null
    @@ -1,4028 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -// All other code copyright its respective owners(s).
    -
    -/**
    - * @fileoverview Generated Protocol Buffer code for file
    - * closure/goog/proto2/test.proto.
    - */
    -
    -goog.provide('proto2.TestAllTypes');
    -goog.provide('proto2.TestAllTypes.NestedMessage');
    -goog.provide('proto2.TestAllTypes.OptionalGroup');
    -goog.provide('proto2.TestAllTypes.RepeatedGroup');
    -goog.provide('proto2.TestAllTypes.NestedEnum');
    -goog.provide('proto2.TestDefaultParent');
    -goog.provide('proto2.TestDefaultChild');
    -
    -goog.require('goog.proto2.Message');
    -
    -
    -
    -/**
    - * Message TestAllTypes.
    - * @constructor
    - * @extends {goog.proto2.Message}
    - */
    -proto2.TestAllTypes = function() {
    -  goog.proto2.Message.call(this);
    -};
    -goog.inherits(proto2.TestAllTypes, goog.proto2.Message);
    -
    -
    -/**
    - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type.
    - * @return {!proto2.TestAllTypes} The cloned message.
    - * @override
    - */
    -proto2.TestAllTypes.prototype.clone;
    -
    -
    -/**
    - * Gets the value of the optional_int32 field.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalInt32 = function() {
    -  return /** @type {?number} */ (this.get$Value(1));
    -};
    -
    -
    -/**
    - * Gets the value of the optional_int32 field or the default value if not set.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalInt32OrDefault = function() {
    -  return /** @type {number} */ (this.get$ValueOrDefault(1));
    -};
    -
    -
    -/**
    - * Sets the value of the optional_int32 field.
    - * @param {number} value The value.
    - */
    -proto2.TestAllTypes.prototype.setOptionalInt32 = function(value) {
    -  this.set$Value(1, value);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the optional_int32 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasOptionalInt32 = function() {
    -  return this.has$Value(1);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the optional_int32 field.
    - */
    -proto2.TestAllTypes.prototype.optionalInt32Count = function() {
    -  return this.count$Values(1);
    -};
    -
    -
    -/**
    - * Clears the values in the optional_int32 field.
    - */
    -proto2.TestAllTypes.prototype.clearOptionalInt32 = function() {
    -  this.clear$Field(1);
    -};
    -
    -
    -/**
    - * Gets the value of the optional_int64 field.
    - * @return {?string} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalInt64 = function() {
    -  return /** @type {?string} */ (this.get$Value(2));
    -};
    -
    -
    -/**
    - * Gets the value of the optional_int64 field or the default value if not set.
    - * @return {string} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalInt64OrDefault = function() {
    -  return /** @type {string} */ (this.get$ValueOrDefault(2));
    -};
    -
    -
    -/**
    - * Sets the value of the optional_int64 field.
    - * @param {string} value The value.
    - */
    -proto2.TestAllTypes.prototype.setOptionalInt64 = function(value) {
    -  this.set$Value(2, value);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the optional_int64 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasOptionalInt64 = function() {
    -  return this.has$Value(2);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the optional_int64 field.
    - */
    -proto2.TestAllTypes.prototype.optionalInt64Count = function() {
    -  return this.count$Values(2);
    -};
    -
    -
    -/**
    - * Clears the values in the optional_int64 field.
    - */
    -proto2.TestAllTypes.prototype.clearOptionalInt64 = function() {
    -  this.clear$Field(2);
    -};
    -
    -
    -/**
    - * Gets the value of the optional_uint32 field.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalUint32 = function() {
    -  return /** @type {?number} */ (this.get$Value(3));
    -};
    -
    -
    -/**
    - * Gets the value of the optional_uint32 field or the default value if not set.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalUint32OrDefault = function() {
    -  return /** @type {number} */ (this.get$ValueOrDefault(3));
    -};
    -
    -
    -/**
    - * Sets the value of the optional_uint32 field.
    - * @param {number} value The value.
    - */
    -proto2.TestAllTypes.prototype.setOptionalUint32 = function(value) {
    -  this.set$Value(3, value);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the optional_uint32 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasOptionalUint32 = function() {
    -  return this.has$Value(3);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the optional_uint32 field.
    - */
    -proto2.TestAllTypes.prototype.optionalUint32Count = function() {
    -  return this.count$Values(3);
    -};
    -
    -
    -/**
    - * Clears the values in the optional_uint32 field.
    - */
    -proto2.TestAllTypes.prototype.clearOptionalUint32 = function() {
    -  this.clear$Field(3);
    -};
    -
    -
    -/**
    - * Gets the value of the optional_uint64 field.
    - * @return {?string} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalUint64 = function() {
    -  return /** @type {?string} */ (this.get$Value(4));
    -};
    -
    -
    -/**
    - * Gets the value of the optional_uint64 field or the default value if not set.
    - * @return {string} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalUint64OrDefault = function() {
    -  return /** @type {string} */ (this.get$ValueOrDefault(4));
    -};
    -
    -
    -/**
    - * Sets the value of the optional_uint64 field.
    - * @param {string} value The value.
    - */
    -proto2.TestAllTypes.prototype.setOptionalUint64 = function(value) {
    -  this.set$Value(4, value);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the optional_uint64 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasOptionalUint64 = function() {
    -  return this.has$Value(4);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the optional_uint64 field.
    - */
    -proto2.TestAllTypes.prototype.optionalUint64Count = function() {
    -  return this.count$Values(4);
    -};
    -
    -
    -/**
    - * Clears the values in the optional_uint64 field.
    - */
    -proto2.TestAllTypes.prototype.clearOptionalUint64 = function() {
    -  this.clear$Field(4);
    -};
    -
    -
    -/**
    - * Gets the value of the optional_sint32 field.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalSint32 = function() {
    -  return /** @type {?number} */ (this.get$Value(5));
    -};
    -
    -
    -/**
    - * Gets the value of the optional_sint32 field or the default value if not set.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalSint32OrDefault = function() {
    -  return /** @type {number} */ (this.get$ValueOrDefault(5));
    -};
    -
    -
    -/**
    - * Sets the value of the optional_sint32 field.
    - * @param {number} value The value.
    - */
    -proto2.TestAllTypes.prototype.setOptionalSint32 = function(value) {
    -  this.set$Value(5, value);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the optional_sint32 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasOptionalSint32 = function() {
    -  return this.has$Value(5);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the optional_sint32 field.
    - */
    -proto2.TestAllTypes.prototype.optionalSint32Count = function() {
    -  return this.count$Values(5);
    -};
    -
    -
    -/**
    - * Clears the values in the optional_sint32 field.
    - */
    -proto2.TestAllTypes.prototype.clearOptionalSint32 = function() {
    -  this.clear$Field(5);
    -};
    -
    -
    -/**
    - * Gets the value of the optional_sint64 field.
    - * @return {?string} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalSint64 = function() {
    -  return /** @type {?string} */ (this.get$Value(6));
    -};
    -
    -
    -/**
    - * Gets the value of the optional_sint64 field or the default value if not set.
    - * @return {string} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalSint64OrDefault = function() {
    -  return /** @type {string} */ (this.get$ValueOrDefault(6));
    -};
    -
    -
    -/**
    - * Sets the value of the optional_sint64 field.
    - * @param {string} value The value.
    - */
    -proto2.TestAllTypes.prototype.setOptionalSint64 = function(value) {
    -  this.set$Value(6, value);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the optional_sint64 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasOptionalSint64 = function() {
    -  return this.has$Value(6);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the optional_sint64 field.
    - */
    -proto2.TestAllTypes.prototype.optionalSint64Count = function() {
    -  return this.count$Values(6);
    -};
    -
    -
    -/**
    - * Clears the values in the optional_sint64 field.
    - */
    -proto2.TestAllTypes.prototype.clearOptionalSint64 = function() {
    -  this.clear$Field(6);
    -};
    -
    -
    -/**
    - * Gets the value of the optional_fixed32 field.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalFixed32 = function() {
    -  return /** @type {?number} */ (this.get$Value(7));
    -};
    -
    -
    -/**
    - * Gets the value of the optional_fixed32 field or the default value if not set.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalFixed32OrDefault = function() {
    -  return /** @type {number} */ (this.get$ValueOrDefault(7));
    -};
    -
    -
    -/**
    - * Sets the value of the optional_fixed32 field.
    - * @param {number} value The value.
    - */
    -proto2.TestAllTypes.prototype.setOptionalFixed32 = function(value) {
    -  this.set$Value(7, value);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the optional_fixed32 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasOptionalFixed32 = function() {
    -  return this.has$Value(7);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the optional_fixed32 field.
    - */
    -proto2.TestAllTypes.prototype.optionalFixed32Count = function() {
    -  return this.count$Values(7);
    -};
    -
    -
    -/**
    - * Clears the values in the optional_fixed32 field.
    - */
    -proto2.TestAllTypes.prototype.clearOptionalFixed32 = function() {
    -  this.clear$Field(7);
    -};
    -
    -
    -/**
    - * Gets the value of the optional_fixed64 field.
    - * @return {?string} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalFixed64 = function() {
    -  return /** @type {?string} */ (this.get$Value(8));
    -};
    -
    -
    -/**
    - * Gets the value of the optional_fixed64 field or the default value if not set.
    - * @return {string} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalFixed64OrDefault = function() {
    -  return /** @type {string} */ (this.get$ValueOrDefault(8));
    -};
    -
    -
    -/**
    - * Sets the value of the optional_fixed64 field.
    - * @param {string} value The value.
    - */
    -proto2.TestAllTypes.prototype.setOptionalFixed64 = function(value) {
    -  this.set$Value(8, value);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the optional_fixed64 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasOptionalFixed64 = function() {
    -  return this.has$Value(8);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the optional_fixed64 field.
    - */
    -proto2.TestAllTypes.prototype.optionalFixed64Count = function() {
    -  return this.count$Values(8);
    -};
    -
    -
    -/**
    - * Clears the values in the optional_fixed64 field.
    - */
    -proto2.TestAllTypes.prototype.clearOptionalFixed64 = function() {
    -  this.clear$Field(8);
    -};
    -
    -
    -/**
    - * Gets the value of the optional_sfixed32 field.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalSfixed32 = function() {
    -  return /** @type {?number} */ (this.get$Value(9));
    -};
    -
    -
    -/**
    - * Gets the value of the optional_sfixed32 field or the default value if not set.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalSfixed32OrDefault = function() {
    -  return /** @type {number} */ (this.get$ValueOrDefault(9));
    -};
    -
    -
    -/**
    - * Sets the value of the optional_sfixed32 field.
    - * @param {number} value The value.
    - */
    -proto2.TestAllTypes.prototype.setOptionalSfixed32 = function(value) {
    -  this.set$Value(9, value);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the optional_sfixed32 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasOptionalSfixed32 = function() {
    -  return this.has$Value(9);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the optional_sfixed32 field.
    - */
    -proto2.TestAllTypes.prototype.optionalSfixed32Count = function() {
    -  return this.count$Values(9);
    -};
    -
    -
    -/**
    - * Clears the values in the optional_sfixed32 field.
    - */
    -proto2.TestAllTypes.prototype.clearOptionalSfixed32 = function() {
    -  this.clear$Field(9);
    -};
    -
    -
    -/**
    - * Gets the value of the optional_sfixed64 field.
    - * @return {?string} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalSfixed64 = function() {
    -  return /** @type {?string} */ (this.get$Value(10));
    -};
    -
    -
    -/**
    - * Gets the value of the optional_sfixed64 field or the default value if not set.
    - * @return {string} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalSfixed64OrDefault = function() {
    -  return /** @type {string} */ (this.get$ValueOrDefault(10));
    -};
    -
    -
    -/**
    - * Sets the value of the optional_sfixed64 field.
    - * @param {string} value The value.
    - */
    -proto2.TestAllTypes.prototype.setOptionalSfixed64 = function(value) {
    -  this.set$Value(10, value);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the optional_sfixed64 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasOptionalSfixed64 = function() {
    -  return this.has$Value(10);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the optional_sfixed64 field.
    - */
    -proto2.TestAllTypes.prototype.optionalSfixed64Count = function() {
    -  return this.count$Values(10);
    -};
    -
    -
    -/**
    - * Clears the values in the optional_sfixed64 field.
    - */
    -proto2.TestAllTypes.prototype.clearOptionalSfixed64 = function() {
    -  this.clear$Field(10);
    -};
    -
    -
    -/**
    - * Gets the value of the optional_float field.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalFloat = function() {
    -  return /** @type {?number} */ (this.get$Value(11));
    -};
    -
    -
    -/**
    - * Gets the value of the optional_float field or the default value if not set.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalFloatOrDefault = function() {
    -  return /** @type {number} */ (this.get$ValueOrDefault(11));
    -};
    -
    -
    -/**
    - * Sets the value of the optional_float field.
    - * @param {number} value The value.
    - */
    -proto2.TestAllTypes.prototype.setOptionalFloat = function(value) {
    -  this.set$Value(11, value);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the optional_float field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasOptionalFloat = function() {
    -  return this.has$Value(11);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the optional_float field.
    - */
    -proto2.TestAllTypes.prototype.optionalFloatCount = function() {
    -  return this.count$Values(11);
    -};
    -
    -
    -/**
    - * Clears the values in the optional_float field.
    - */
    -proto2.TestAllTypes.prototype.clearOptionalFloat = function() {
    -  this.clear$Field(11);
    -};
    -
    -
    -/**
    - * Gets the value of the optional_double field.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalDouble = function() {
    -  return /** @type {?number} */ (this.get$Value(12));
    -};
    -
    -
    -/**
    - * Gets the value of the optional_double field or the default value if not set.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalDoubleOrDefault = function() {
    -  return /** @type {number} */ (this.get$ValueOrDefault(12));
    -};
    -
    -
    -/**
    - * Sets the value of the optional_double field.
    - * @param {number} value The value.
    - */
    -proto2.TestAllTypes.prototype.setOptionalDouble = function(value) {
    -  this.set$Value(12, value);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the optional_double field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasOptionalDouble = function() {
    -  return this.has$Value(12);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the optional_double field.
    - */
    -proto2.TestAllTypes.prototype.optionalDoubleCount = function() {
    -  return this.count$Values(12);
    -};
    -
    -
    -/**
    - * Clears the values in the optional_double field.
    - */
    -proto2.TestAllTypes.prototype.clearOptionalDouble = function() {
    -  this.clear$Field(12);
    -};
    -
    -
    -/**
    - * Gets the value of the optional_bool field.
    - * @return {?boolean} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalBool = function() {
    -  return /** @type {?boolean} */ (this.get$Value(13));
    -};
    -
    -
    -/**
    - * Gets the value of the optional_bool field or the default value if not set.
    - * @return {boolean} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalBoolOrDefault = function() {
    -  return /** @type {boolean} */ (this.get$ValueOrDefault(13));
    -};
    -
    -
    -/**
    - * Sets the value of the optional_bool field.
    - * @param {boolean} value The value.
    - */
    -proto2.TestAllTypes.prototype.setOptionalBool = function(value) {
    -  this.set$Value(13, value);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the optional_bool field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasOptionalBool = function() {
    -  return this.has$Value(13);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the optional_bool field.
    - */
    -proto2.TestAllTypes.prototype.optionalBoolCount = function() {
    -  return this.count$Values(13);
    -};
    -
    -
    -/**
    - * Clears the values in the optional_bool field.
    - */
    -proto2.TestAllTypes.prototype.clearOptionalBool = function() {
    -  this.clear$Field(13);
    -};
    -
    -
    -/**
    - * Gets the value of the optional_string field.
    - * @return {?string} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalString = function() {
    -  return /** @type {?string} */ (this.get$Value(14));
    -};
    -
    -
    -/**
    - * Gets the value of the optional_string field or the default value if not set.
    - * @return {string} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalStringOrDefault = function() {
    -  return /** @type {string} */ (this.get$ValueOrDefault(14));
    -};
    -
    -
    -/**
    - * Sets the value of the optional_string field.
    - * @param {string} value The value.
    - */
    -proto2.TestAllTypes.prototype.setOptionalString = function(value) {
    -  this.set$Value(14, value);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the optional_string field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasOptionalString = function() {
    -  return this.has$Value(14);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the optional_string field.
    - */
    -proto2.TestAllTypes.prototype.optionalStringCount = function() {
    -  return this.count$Values(14);
    -};
    -
    -
    -/**
    - * Clears the values in the optional_string field.
    - */
    -proto2.TestAllTypes.prototype.clearOptionalString = function() {
    -  this.clear$Field(14);
    -};
    -
    -
    -/**
    - * Gets the value of the optional_bytes field.
    - * @return {?string} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalBytes = function() {
    -  return /** @type {?string} */ (this.get$Value(15));
    -};
    -
    -
    -/**
    - * Gets the value of the optional_bytes field or the default value if not set.
    - * @return {string} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalBytesOrDefault = function() {
    -  return /** @type {string} */ (this.get$ValueOrDefault(15));
    -};
    -
    -
    -/**
    - * Sets the value of the optional_bytes field.
    - * @param {string} value The value.
    - */
    -proto2.TestAllTypes.prototype.setOptionalBytes = function(value) {
    -  this.set$Value(15, value);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the optional_bytes field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasOptionalBytes = function() {
    -  return this.has$Value(15);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the optional_bytes field.
    - */
    -proto2.TestAllTypes.prototype.optionalBytesCount = function() {
    -  return this.count$Values(15);
    -};
    -
    -
    -/**
    - * Clears the values in the optional_bytes field.
    - */
    -proto2.TestAllTypes.prototype.clearOptionalBytes = function() {
    -  this.clear$Field(15);
    -};
    -
    -
    -/**
    - * Gets the value of the optionalgroup field.
    - * @return {proto2.TestAllTypes.OptionalGroup} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalgroup = function() {
    -  return /** @type {proto2.TestAllTypes.OptionalGroup} */ (this.get$Value(16));
    -};
    -
    -
    -/**
    - * Gets the value of the optionalgroup field or the default value if not set.
    - * @return {!proto2.TestAllTypes.OptionalGroup} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalgroupOrDefault = function() {
    -  return /** @type {!proto2.TestAllTypes.OptionalGroup} */ (this.get$ValueOrDefault(16));
    -};
    -
    -
    -/**
    - * Sets the value of the optionalgroup field.
    - * @param {!proto2.TestAllTypes.OptionalGroup} value The value.
    - */
    -proto2.TestAllTypes.prototype.setOptionalgroup = function(value) {
    -  this.set$Value(16, value);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the optionalgroup field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasOptionalgroup = function() {
    -  return this.has$Value(16);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the optionalgroup field.
    - */
    -proto2.TestAllTypes.prototype.optionalgroupCount = function() {
    -  return this.count$Values(16);
    -};
    -
    -
    -/**
    - * Clears the values in the optionalgroup field.
    - */
    -proto2.TestAllTypes.prototype.clearOptionalgroup = function() {
    -  this.clear$Field(16);
    -};
    -
    -
    -/**
    - * Gets the value of the optional_nested_message field.
    - * @return {proto2.TestAllTypes.NestedMessage} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalNestedMessage = function() {
    -  return /** @type {proto2.TestAllTypes.NestedMessage} */ (this.get$Value(18));
    -};
    -
    -
    -/**
    - * Gets the value of the optional_nested_message field or the default value if not set.
    - * @return {!proto2.TestAllTypes.NestedMessage} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalNestedMessageOrDefault = function() {
    -  return /** @type {!proto2.TestAllTypes.NestedMessage} */ (this.get$ValueOrDefault(18));
    -};
    -
    -
    -/**
    - * Sets the value of the optional_nested_message field.
    - * @param {!proto2.TestAllTypes.NestedMessage} value The value.
    - */
    -proto2.TestAllTypes.prototype.setOptionalNestedMessage = function(value) {
    -  this.set$Value(18, value);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the optional_nested_message field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasOptionalNestedMessage = function() {
    -  return this.has$Value(18);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the optional_nested_message field.
    - */
    -proto2.TestAllTypes.prototype.optionalNestedMessageCount = function() {
    -  return this.count$Values(18);
    -};
    -
    -
    -/**
    - * Clears the values in the optional_nested_message field.
    - */
    -proto2.TestAllTypes.prototype.clearOptionalNestedMessage = function() {
    -  this.clear$Field(18);
    -};
    -
    -
    -/**
    - * Gets the value of the optional_nested_enum field.
    - * @return {?proto2.TestAllTypes.NestedEnum} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalNestedEnum = function() {
    -  return /** @type {?proto2.TestAllTypes.NestedEnum} */ (this.get$Value(21));
    -};
    -
    -
    -/**
    - * Gets the value of the optional_nested_enum field or the default value if not set.
    - * @return {proto2.TestAllTypes.NestedEnum} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalNestedEnumOrDefault = function() {
    -  return /** @type {proto2.TestAllTypes.NestedEnum} */ (this.get$ValueOrDefault(21));
    -};
    -
    -
    -/**
    - * Sets the value of the optional_nested_enum field.
    - * @param {proto2.TestAllTypes.NestedEnum} value The value.
    - */
    -proto2.TestAllTypes.prototype.setOptionalNestedEnum = function(value) {
    -  this.set$Value(21, value);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the optional_nested_enum field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasOptionalNestedEnum = function() {
    -  return this.has$Value(21);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the optional_nested_enum field.
    - */
    -proto2.TestAllTypes.prototype.optionalNestedEnumCount = function() {
    -  return this.count$Values(21);
    -};
    -
    -
    -/**
    - * Clears the values in the optional_nested_enum field.
    - */
    -proto2.TestAllTypes.prototype.clearOptionalNestedEnum = function() {
    -  this.clear$Field(21);
    -};
    -
    -
    -/**
    - * Gets the value of the optional_int64_number field.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalInt64Number = function() {
    -  return /** @type {?number} */ (this.get$Value(50));
    -};
    -
    -
    -/**
    - * Gets the value of the optional_int64_number field or the default value if not set.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalInt64NumberOrDefault = function() {
    -  return /** @type {number} */ (this.get$ValueOrDefault(50));
    -};
    -
    -
    -/**
    - * Sets the value of the optional_int64_number field.
    - * @param {number} value The value.
    - */
    -proto2.TestAllTypes.prototype.setOptionalInt64Number = function(value) {
    -  this.set$Value(50, value);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the optional_int64_number field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasOptionalInt64Number = function() {
    -  return this.has$Value(50);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the optional_int64_number field.
    - */
    -proto2.TestAllTypes.prototype.optionalInt64NumberCount = function() {
    -  return this.count$Values(50);
    -};
    -
    -
    -/**
    - * Clears the values in the optional_int64_number field.
    - */
    -proto2.TestAllTypes.prototype.clearOptionalInt64Number = function() {
    -  this.clear$Field(50);
    -};
    -
    -
    -/**
    - * Gets the value of the optional_int64_string field.
    - * @return {?string} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalInt64String = function() {
    -  return /** @type {?string} */ (this.get$Value(51));
    -};
    -
    -
    -/**
    - * Gets the value of the optional_int64_string field or the default value if not set.
    - * @return {string} The value.
    - */
    -proto2.TestAllTypes.prototype.getOptionalInt64StringOrDefault = function() {
    -  return /** @type {string} */ (this.get$ValueOrDefault(51));
    -};
    -
    -
    -/**
    - * Sets the value of the optional_int64_string field.
    - * @param {string} value The value.
    - */
    -proto2.TestAllTypes.prototype.setOptionalInt64String = function(value) {
    -  this.set$Value(51, value);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the optional_int64_string field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasOptionalInt64String = function() {
    -  return this.has$Value(51);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the optional_int64_string field.
    - */
    -proto2.TestAllTypes.prototype.optionalInt64StringCount = function() {
    -  return this.count$Values(51);
    -};
    -
    -
    -/**
    - * Clears the values in the optional_int64_string field.
    - */
    -proto2.TestAllTypes.prototype.clearOptionalInt64String = function() {
    -  this.clear$Field(51);
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_int32 field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedInt32 = function(index) {
    -  return /** @type {?number} */ (this.get$Value(31, index));
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_int32 field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedInt32OrDefault = function(index) {
    -  return /** @type {number} */ (this.get$ValueOrDefault(31, index));
    -};
    -
    -
    -/**
    - * Adds a value to the repeated_int32 field.
    - * @param {number} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addRepeatedInt32 = function(value) {
    -  this.add$Value(31, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the repeated_int32 field.
    - * @return {!Array.<number>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.repeatedInt32Array = function() {
    -  return /** @type {!Array.<number>} */ (this.array$Values(31));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the repeated_int32 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasRepeatedInt32 = function() {
    -  return this.has$Value(31);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the repeated_int32 field.
    - */
    -proto2.TestAllTypes.prototype.repeatedInt32Count = function() {
    -  return this.count$Values(31);
    -};
    -
    -
    -/**
    - * Clears the values in the repeated_int32 field.
    - */
    -proto2.TestAllTypes.prototype.clearRepeatedInt32 = function() {
    -  this.clear$Field(31);
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_int64 field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?string} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedInt64 = function(index) {
    -  return /** @type {?string} */ (this.get$Value(32, index));
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_int64 field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {string} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedInt64OrDefault = function(index) {
    -  return /** @type {string} */ (this.get$ValueOrDefault(32, index));
    -};
    -
    -
    -/**
    - * Adds a value to the repeated_int64 field.
    - * @param {string} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addRepeatedInt64 = function(value) {
    -  this.add$Value(32, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the repeated_int64 field.
    - * @return {!Array.<string>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.repeatedInt64Array = function() {
    -  return /** @type {!Array.<string>} */ (this.array$Values(32));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the repeated_int64 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasRepeatedInt64 = function() {
    -  return this.has$Value(32);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the repeated_int64 field.
    - */
    -proto2.TestAllTypes.prototype.repeatedInt64Count = function() {
    -  return this.count$Values(32);
    -};
    -
    -
    -/**
    - * Clears the values in the repeated_int64 field.
    - */
    -proto2.TestAllTypes.prototype.clearRepeatedInt64 = function() {
    -  this.clear$Field(32);
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_uint32 field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedUint32 = function(index) {
    -  return /** @type {?number} */ (this.get$Value(33, index));
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_uint32 field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedUint32OrDefault = function(index) {
    -  return /** @type {number} */ (this.get$ValueOrDefault(33, index));
    -};
    -
    -
    -/**
    - * Adds a value to the repeated_uint32 field.
    - * @param {number} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addRepeatedUint32 = function(value) {
    -  this.add$Value(33, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the repeated_uint32 field.
    - * @return {!Array.<number>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.repeatedUint32Array = function() {
    -  return /** @type {!Array.<number>} */ (this.array$Values(33));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the repeated_uint32 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasRepeatedUint32 = function() {
    -  return this.has$Value(33);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the repeated_uint32 field.
    - */
    -proto2.TestAllTypes.prototype.repeatedUint32Count = function() {
    -  return this.count$Values(33);
    -};
    -
    -
    -/**
    - * Clears the values in the repeated_uint32 field.
    - */
    -proto2.TestAllTypes.prototype.clearRepeatedUint32 = function() {
    -  this.clear$Field(33);
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_uint64 field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?string} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedUint64 = function(index) {
    -  return /** @type {?string} */ (this.get$Value(34, index));
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_uint64 field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {string} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedUint64OrDefault = function(index) {
    -  return /** @type {string} */ (this.get$ValueOrDefault(34, index));
    -};
    -
    -
    -/**
    - * Adds a value to the repeated_uint64 field.
    - * @param {string} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addRepeatedUint64 = function(value) {
    -  this.add$Value(34, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the repeated_uint64 field.
    - * @return {!Array.<string>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.repeatedUint64Array = function() {
    -  return /** @type {!Array.<string>} */ (this.array$Values(34));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the repeated_uint64 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasRepeatedUint64 = function() {
    -  return this.has$Value(34);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the repeated_uint64 field.
    - */
    -proto2.TestAllTypes.prototype.repeatedUint64Count = function() {
    -  return this.count$Values(34);
    -};
    -
    -
    -/**
    - * Clears the values in the repeated_uint64 field.
    - */
    -proto2.TestAllTypes.prototype.clearRepeatedUint64 = function() {
    -  this.clear$Field(34);
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_sint32 field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedSint32 = function(index) {
    -  return /** @type {?number} */ (this.get$Value(35, index));
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_sint32 field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedSint32OrDefault = function(index) {
    -  return /** @type {number} */ (this.get$ValueOrDefault(35, index));
    -};
    -
    -
    -/**
    - * Adds a value to the repeated_sint32 field.
    - * @param {number} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addRepeatedSint32 = function(value) {
    -  this.add$Value(35, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the repeated_sint32 field.
    - * @return {!Array.<number>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.repeatedSint32Array = function() {
    -  return /** @type {!Array.<number>} */ (this.array$Values(35));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the repeated_sint32 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasRepeatedSint32 = function() {
    -  return this.has$Value(35);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the repeated_sint32 field.
    - */
    -proto2.TestAllTypes.prototype.repeatedSint32Count = function() {
    -  return this.count$Values(35);
    -};
    -
    -
    -/**
    - * Clears the values in the repeated_sint32 field.
    - */
    -proto2.TestAllTypes.prototype.clearRepeatedSint32 = function() {
    -  this.clear$Field(35);
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_sint64 field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?string} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedSint64 = function(index) {
    -  return /** @type {?string} */ (this.get$Value(36, index));
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_sint64 field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {string} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedSint64OrDefault = function(index) {
    -  return /** @type {string} */ (this.get$ValueOrDefault(36, index));
    -};
    -
    -
    -/**
    - * Adds a value to the repeated_sint64 field.
    - * @param {string} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addRepeatedSint64 = function(value) {
    -  this.add$Value(36, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the repeated_sint64 field.
    - * @return {!Array.<string>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.repeatedSint64Array = function() {
    -  return /** @type {!Array.<string>} */ (this.array$Values(36));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the repeated_sint64 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasRepeatedSint64 = function() {
    -  return this.has$Value(36);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the repeated_sint64 field.
    - */
    -proto2.TestAllTypes.prototype.repeatedSint64Count = function() {
    -  return this.count$Values(36);
    -};
    -
    -
    -/**
    - * Clears the values in the repeated_sint64 field.
    - */
    -proto2.TestAllTypes.prototype.clearRepeatedSint64 = function() {
    -  this.clear$Field(36);
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_fixed32 field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedFixed32 = function(index) {
    -  return /** @type {?number} */ (this.get$Value(37, index));
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_fixed32 field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedFixed32OrDefault = function(index) {
    -  return /** @type {number} */ (this.get$ValueOrDefault(37, index));
    -};
    -
    -
    -/**
    - * Adds a value to the repeated_fixed32 field.
    - * @param {number} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addRepeatedFixed32 = function(value) {
    -  this.add$Value(37, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the repeated_fixed32 field.
    - * @return {!Array.<number>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.repeatedFixed32Array = function() {
    -  return /** @type {!Array.<number>} */ (this.array$Values(37));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the repeated_fixed32 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasRepeatedFixed32 = function() {
    -  return this.has$Value(37);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the repeated_fixed32 field.
    - */
    -proto2.TestAllTypes.prototype.repeatedFixed32Count = function() {
    -  return this.count$Values(37);
    -};
    -
    -
    -/**
    - * Clears the values in the repeated_fixed32 field.
    - */
    -proto2.TestAllTypes.prototype.clearRepeatedFixed32 = function() {
    -  this.clear$Field(37);
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_fixed64 field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?string} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedFixed64 = function(index) {
    -  return /** @type {?string} */ (this.get$Value(38, index));
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_fixed64 field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {string} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedFixed64OrDefault = function(index) {
    -  return /** @type {string} */ (this.get$ValueOrDefault(38, index));
    -};
    -
    -
    -/**
    - * Adds a value to the repeated_fixed64 field.
    - * @param {string} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addRepeatedFixed64 = function(value) {
    -  this.add$Value(38, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the repeated_fixed64 field.
    - * @return {!Array.<string>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.repeatedFixed64Array = function() {
    -  return /** @type {!Array.<string>} */ (this.array$Values(38));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the repeated_fixed64 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasRepeatedFixed64 = function() {
    -  return this.has$Value(38);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the repeated_fixed64 field.
    - */
    -proto2.TestAllTypes.prototype.repeatedFixed64Count = function() {
    -  return this.count$Values(38);
    -};
    -
    -
    -/**
    - * Clears the values in the repeated_fixed64 field.
    - */
    -proto2.TestAllTypes.prototype.clearRepeatedFixed64 = function() {
    -  this.clear$Field(38);
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_sfixed32 field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedSfixed32 = function(index) {
    -  return /** @type {?number} */ (this.get$Value(39, index));
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_sfixed32 field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedSfixed32OrDefault = function(index) {
    -  return /** @type {number} */ (this.get$ValueOrDefault(39, index));
    -};
    -
    -
    -/**
    - * Adds a value to the repeated_sfixed32 field.
    - * @param {number} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addRepeatedSfixed32 = function(value) {
    -  this.add$Value(39, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the repeated_sfixed32 field.
    - * @return {!Array.<number>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.repeatedSfixed32Array = function() {
    -  return /** @type {!Array.<number>} */ (this.array$Values(39));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the repeated_sfixed32 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasRepeatedSfixed32 = function() {
    -  return this.has$Value(39);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the repeated_sfixed32 field.
    - */
    -proto2.TestAllTypes.prototype.repeatedSfixed32Count = function() {
    -  return this.count$Values(39);
    -};
    -
    -
    -/**
    - * Clears the values in the repeated_sfixed32 field.
    - */
    -proto2.TestAllTypes.prototype.clearRepeatedSfixed32 = function() {
    -  this.clear$Field(39);
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_sfixed64 field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?string} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedSfixed64 = function(index) {
    -  return /** @type {?string} */ (this.get$Value(40, index));
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_sfixed64 field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {string} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedSfixed64OrDefault = function(index) {
    -  return /** @type {string} */ (this.get$ValueOrDefault(40, index));
    -};
    -
    -
    -/**
    - * Adds a value to the repeated_sfixed64 field.
    - * @param {string} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addRepeatedSfixed64 = function(value) {
    -  this.add$Value(40, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the repeated_sfixed64 field.
    - * @return {!Array.<string>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.repeatedSfixed64Array = function() {
    -  return /** @type {!Array.<string>} */ (this.array$Values(40));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the repeated_sfixed64 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasRepeatedSfixed64 = function() {
    -  return this.has$Value(40);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the repeated_sfixed64 field.
    - */
    -proto2.TestAllTypes.prototype.repeatedSfixed64Count = function() {
    -  return this.count$Values(40);
    -};
    -
    -
    -/**
    - * Clears the values in the repeated_sfixed64 field.
    - */
    -proto2.TestAllTypes.prototype.clearRepeatedSfixed64 = function() {
    -  this.clear$Field(40);
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_float field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedFloat = function(index) {
    -  return /** @type {?number} */ (this.get$Value(41, index));
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_float field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedFloatOrDefault = function(index) {
    -  return /** @type {number} */ (this.get$ValueOrDefault(41, index));
    -};
    -
    -
    -/**
    - * Adds a value to the repeated_float field.
    - * @param {number} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addRepeatedFloat = function(value) {
    -  this.add$Value(41, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the repeated_float field.
    - * @return {!Array.<number>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.repeatedFloatArray = function() {
    -  return /** @type {!Array.<number>} */ (this.array$Values(41));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the repeated_float field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasRepeatedFloat = function() {
    -  return this.has$Value(41);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the repeated_float field.
    - */
    -proto2.TestAllTypes.prototype.repeatedFloatCount = function() {
    -  return this.count$Values(41);
    -};
    -
    -
    -/**
    - * Clears the values in the repeated_float field.
    - */
    -proto2.TestAllTypes.prototype.clearRepeatedFloat = function() {
    -  this.clear$Field(41);
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_double field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedDouble = function(index) {
    -  return /** @type {?number} */ (this.get$Value(42, index));
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_double field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedDoubleOrDefault = function(index) {
    -  return /** @type {number} */ (this.get$ValueOrDefault(42, index));
    -};
    -
    -
    -/**
    - * Adds a value to the repeated_double field.
    - * @param {number} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addRepeatedDouble = function(value) {
    -  this.add$Value(42, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the repeated_double field.
    - * @return {!Array.<number>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.repeatedDoubleArray = function() {
    -  return /** @type {!Array.<number>} */ (this.array$Values(42));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the repeated_double field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasRepeatedDouble = function() {
    -  return this.has$Value(42);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the repeated_double field.
    - */
    -proto2.TestAllTypes.prototype.repeatedDoubleCount = function() {
    -  return this.count$Values(42);
    -};
    -
    -
    -/**
    - * Clears the values in the repeated_double field.
    - */
    -proto2.TestAllTypes.prototype.clearRepeatedDouble = function() {
    -  this.clear$Field(42);
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_bool field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?boolean} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedBool = function(index) {
    -  return /** @type {?boolean} */ (this.get$Value(43, index));
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_bool field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {boolean} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedBoolOrDefault = function(index) {
    -  return /** @type {boolean} */ (this.get$ValueOrDefault(43, index));
    -};
    -
    -
    -/**
    - * Adds a value to the repeated_bool field.
    - * @param {boolean} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addRepeatedBool = function(value) {
    -  this.add$Value(43, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the repeated_bool field.
    - * @return {!Array.<boolean>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.repeatedBoolArray = function() {
    -  return /** @type {!Array.<boolean>} */ (this.array$Values(43));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the repeated_bool field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasRepeatedBool = function() {
    -  return this.has$Value(43);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the repeated_bool field.
    - */
    -proto2.TestAllTypes.prototype.repeatedBoolCount = function() {
    -  return this.count$Values(43);
    -};
    -
    -
    -/**
    - * Clears the values in the repeated_bool field.
    - */
    -proto2.TestAllTypes.prototype.clearRepeatedBool = function() {
    -  this.clear$Field(43);
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_string field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?string} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedString = function(index) {
    -  return /** @type {?string} */ (this.get$Value(44, index));
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_string field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {string} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedStringOrDefault = function(index) {
    -  return /** @type {string} */ (this.get$ValueOrDefault(44, index));
    -};
    -
    -
    -/**
    - * Adds a value to the repeated_string field.
    - * @param {string} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addRepeatedString = function(value) {
    -  this.add$Value(44, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the repeated_string field.
    - * @return {!Array.<string>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.repeatedStringArray = function() {
    -  return /** @type {!Array.<string>} */ (this.array$Values(44));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the repeated_string field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasRepeatedString = function() {
    -  return this.has$Value(44);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the repeated_string field.
    - */
    -proto2.TestAllTypes.prototype.repeatedStringCount = function() {
    -  return this.count$Values(44);
    -};
    -
    -
    -/**
    - * Clears the values in the repeated_string field.
    - */
    -proto2.TestAllTypes.prototype.clearRepeatedString = function() {
    -  this.clear$Field(44);
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_bytes field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?string} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedBytes = function(index) {
    -  return /** @type {?string} */ (this.get$Value(45, index));
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_bytes field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {string} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedBytesOrDefault = function(index) {
    -  return /** @type {string} */ (this.get$ValueOrDefault(45, index));
    -};
    -
    -
    -/**
    - * Adds a value to the repeated_bytes field.
    - * @param {string} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addRepeatedBytes = function(value) {
    -  this.add$Value(45, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the repeated_bytes field.
    - * @return {!Array.<string>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.repeatedBytesArray = function() {
    -  return /** @type {!Array.<string>} */ (this.array$Values(45));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the repeated_bytes field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasRepeatedBytes = function() {
    -  return this.has$Value(45);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the repeated_bytes field.
    - */
    -proto2.TestAllTypes.prototype.repeatedBytesCount = function() {
    -  return this.count$Values(45);
    -};
    -
    -
    -/**
    - * Clears the values in the repeated_bytes field.
    - */
    -proto2.TestAllTypes.prototype.clearRepeatedBytes = function() {
    -  this.clear$Field(45);
    -};
    -
    -
    -/**
    - * Gets the value of the repeatedgroup field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {proto2.TestAllTypes.RepeatedGroup} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedgroup = function(index) {
    -  return /** @type {proto2.TestAllTypes.RepeatedGroup} */ (this.get$Value(46, index));
    -};
    -
    -
    -/**
    - * Gets the value of the repeatedgroup field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {!proto2.TestAllTypes.RepeatedGroup} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedgroupOrDefault = function(index) {
    -  return /** @type {!proto2.TestAllTypes.RepeatedGroup} */ (this.get$ValueOrDefault(46, index));
    -};
    -
    -
    -/**
    - * Adds a value to the repeatedgroup field.
    - * @param {!proto2.TestAllTypes.RepeatedGroup} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addRepeatedgroup = function(value) {
    -  this.add$Value(46, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the repeatedgroup field.
    - * @return {!Array.<!proto2.TestAllTypes.RepeatedGroup>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.repeatedgroupArray = function() {
    -  return /** @type {!Array.<!proto2.TestAllTypes.RepeatedGroup>} */ (this.array$Values(46));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the repeatedgroup field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasRepeatedgroup = function() {
    -  return this.has$Value(46);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the repeatedgroup field.
    - */
    -proto2.TestAllTypes.prototype.repeatedgroupCount = function() {
    -  return this.count$Values(46);
    -};
    -
    -
    -/**
    - * Clears the values in the repeatedgroup field.
    - */
    -proto2.TestAllTypes.prototype.clearRepeatedgroup = function() {
    -  this.clear$Field(46);
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_nested_message field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {proto2.TestAllTypes.NestedMessage} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedNestedMessage = function(index) {
    -  return /** @type {proto2.TestAllTypes.NestedMessage} */ (this.get$Value(48, index));
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_nested_message field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {!proto2.TestAllTypes.NestedMessage} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedNestedMessageOrDefault = function(index) {
    -  return /** @type {!proto2.TestAllTypes.NestedMessage} */ (this.get$ValueOrDefault(48, index));
    -};
    -
    -
    -/**
    - * Adds a value to the repeated_nested_message field.
    - * @param {!proto2.TestAllTypes.NestedMessage} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addRepeatedNestedMessage = function(value) {
    -  this.add$Value(48, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the repeated_nested_message field.
    - * @return {!Array.<!proto2.TestAllTypes.NestedMessage>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.repeatedNestedMessageArray = function() {
    -  return /** @type {!Array.<!proto2.TestAllTypes.NestedMessage>} */ (this.array$Values(48));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the repeated_nested_message field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasRepeatedNestedMessage = function() {
    -  return this.has$Value(48);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the repeated_nested_message field.
    - */
    -proto2.TestAllTypes.prototype.repeatedNestedMessageCount = function() {
    -  return this.count$Values(48);
    -};
    -
    -
    -/**
    - * Clears the values in the repeated_nested_message field.
    - */
    -proto2.TestAllTypes.prototype.clearRepeatedNestedMessage = function() {
    -  this.clear$Field(48);
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_nested_enum field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?proto2.TestAllTypes.NestedEnum} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedNestedEnum = function(index) {
    -  return /** @type {?proto2.TestAllTypes.NestedEnum} */ (this.get$Value(49, index));
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_nested_enum field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {proto2.TestAllTypes.NestedEnum} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedNestedEnumOrDefault = function(index) {
    -  return /** @type {proto2.TestAllTypes.NestedEnum} */ (this.get$ValueOrDefault(49, index));
    -};
    -
    -
    -/**
    - * Adds a value to the repeated_nested_enum field.
    - * @param {proto2.TestAllTypes.NestedEnum} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addRepeatedNestedEnum = function(value) {
    -  this.add$Value(49, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the repeated_nested_enum field.
    - * @return {!Array.<proto2.TestAllTypes.NestedEnum>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.repeatedNestedEnumArray = function() {
    -  return /** @type {!Array.<proto2.TestAllTypes.NestedEnum>} */ (this.array$Values(49));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the repeated_nested_enum field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasRepeatedNestedEnum = function() {
    -  return this.has$Value(49);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the repeated_nested_enum field.
    - */
    -proto2.TestAllTypes.prototype.repeatedNestedEnumCount = function() {
    -  return this.count$Values(49);
    -};
    -
    -
    -/**
    - * Clears the values in the repeated_nested_enum field.
    - */
    -proto2.TestAllTypes.prototype.clearRepeatedNestedEnum = function() {
    -  this.clear$Field(49);
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_int64_number field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedInt64Number = function(index) {
    -  return /** @type {?number} */ (this.get$Value(52, index));
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_int64_number field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedInt64NumberOrDefault = function(index) {
    -  return /** @type {number} */ (this.get$ValueOrDefault(52, index));
    -};
    -
    -
    -/**
    - * Adds a value to the repeated_int64_number field.
    - * @param {number} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addRepeatedInt64Number = function(value) {
    -  this.add$Value(52, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the repeated_int64_number field.
    - * @return {!Array.<number>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.repeatedInt64NumberArray = function() {
    -  return /** @type {!Array.<number>} */ (this.array$Values(52));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the repeated_int64_number field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasRepeatedInt64Number = function() {
    -  return this.has$Value(52);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the repeated_int64_number field.
    - */
    -proto2.TestAllTypes.prototype.repeatedInt64NumberCount = function() {
    -  return this.count$Values(52);
    -};
    -
    -
    -/**
    - * Clears the values in the repeated_int64_number field.
    - */
    -proto2.TestAllTypes.prototype.clearRepeatedInt64Number = function() {
    -  this.clear$Field(52);
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_int64_string field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?string} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedInt64String = function(index) {
    -  return /** @type {?string} */ (this.get$Value(53, index));
    -};
    -
    -
    -/**
    - * Gets the value of the repeated_int64_string field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {string} The value.
    - */
    -proto2.TestAllTypes.prototype.getRepeatedInt64StringOrDefault = function(index) {
    -  return /** @type {string} */ (this.get$ValueOrDefault(53, index));
    -};
    -
    -
    -/**
    - * Adds a value to the repeated_int64_string field.
    - * @param {string} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addRepeatedInt64String = function(value) {
    -  this.add$Value(53, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the repeated_int64_string field.
    - * @return {!Array.<string>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.repeatedInt64StringArray = function() {
    -  return /** @type {!Array.<string>} */ (this.array$Values(53));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the repeated_int64_string field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasRepeatedInt64String = function() {
    -  return this.has$Value(53);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the repeated_int64_string field.
    - */
    -proto2.TestAllTypes.prototype.repeatedInt64StringCount = function() {
    -  return this.count$Values(53);
    -};
    -
    -
    -/**
    - * Clears the values in the repeated_int64_string field.
    - */
    -proto2.TestAllTypes.prototype.clearRepeatedInt64String = function() {
    -  this.clear$Field(53);
    -};
    -
    -
    -/**
    - * Gets the value of the packed_int32 field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.prototype.getPackedInt32 = function(index) {
    -  return /** @type {?number} */ (this.get$Value(54, index));
    -};
    -
    -
    -/**
    - * Gets the value of the packed_int32 field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.prototype.getPackedInt32OrDefault = function(index) {
    -  return /** @type {number} */ (this.get$ValueOrDefault(54, index));
    -};
    -
    -
    -/**
    - * Adds a value to the packed_int32 field.
    - * @param {number} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addPackedInt32 = function(value) {
    -  this.add$Value(54, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the packed_int32 field.
    - * @return {!Array.<number>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.packedInt32Array = function() {
    -  return /** @type {!Array.<number>} */ (this.array$Values(54));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the packed_int32 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasPackedInt32 = function() {
    -  return this.has$Value(54);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the packed_int32 field.
    - */
    -proto2.TestAllTypes.prototype.packedInt32Count = function() {
    -  return this.count$Values(54);
    -};
    -
    -
    -/**
    - * Clears the values in the packed_int32 field.
    - */
    -proto2.TestAllTypes.prototype.clearPackedInt32 = function() {
    -  this.clear$Field(54);
    -};
    -
    -
    -/**
    - * Gets the value of the packed_int64 field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.prototype.getPackedInt64 = function(index) {
    -  return /** @type {?number} */ (this.get$Value(55, index));
    -};
    -
    -
    -/**
    - * Gets the value of the packed_int64 field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.prototype.getPackedInt64OrDefault = function(index) {
    -  return /** @type {number} */ (this.get$ValueOrDefault(55, index));
    -};
    -
    -
    -/**
    - * Adds a value to the packed_int64 field.
    - * @param {number} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addPackedInt64 = function(value) {
    -  this.add$Value(55, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the packed_int64 field.
    - * @return {!Array.<number>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.packedInt64Array = function() {
    -  return /** @type {!Array.<number>} */ (this.array$Values(55));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the packed_int64 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasPackedInt64 = function() {
    -  return this.has$Value(55);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the packed_int64 field.
    - */
    -proto2.TestAllTypes.prototype.packedInt64Count = function() {
    -  return this.count$Values(55);
    -};
    -
    -
    -/**
    - * Clears the values in the packed_int64 field.
    - */
    -proto2.TestAllTypes.prototype.clearPackedInt64 = function() {
    -  this.clear$Field(55);
    -};
    -
    -
    -/**
    - * Gets the value of the packed_uint32 field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.prototype.getPackedUint32 = function(index) {
    -  return /** @type {?number} */ (this.get$Value(56, index));
    -};
    -
    -
    -/**
    - * Gets the value of the packed_uint32 field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.prototype.getPackedUint32OrDefault = function(index) {
    -  return /** @type {number} */ (this.get$ValueOrDefault(56, index));
    -};
    -
    -
    -/**
    - * Adds a value to the packed_uint32 field.
    - * @param {number} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addPackedUint32 = function(value) {
    -  this.add$Value(56, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the packed_uint32 field.
    - * @return {!Array.<number>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.packedUint32Array = function() {
    -  return /** @type {!Array.<number>} */ (this.array$Values(56));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the packed_uint32 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasPackedUint32 = function() {
    -  return this.has$Value(56);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the packed_uint32 field.
    - */
    -proto2.TestAllTypes.prototype.packedUint32Count = function() {
    -  return this.count$Values(56);
    -};
    -
    -
    -/**
    - * Clears the values in the packed_uint32 field.
    - */
    -proto2.TestAllTypes.prototype.clearPackedUint32 = function() {
    -  this.clear$Field(56);
    -};
    -
    -
    -/**
    - * Gets the value of the packed_uint64 field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.prototype.getPackedUint64 = function(index) {
    -  return /** @type {?number} */ (this.get$Value(57, index));
    -};
    -
    -
    -/**
    - * Gets the value of the packed_uint64 field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.prototype.getPackedUint64OrDefault = function(index) {
    -  return /** @type {number} */ (this.get$ValueOrDefault(57, index));
    -};
    -
    -
    -/**
    - * Adds a value to the packed_uint64 field.
    - * @param {number} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addPackedUint64 = function(value) {
    -  this.add$Value(57, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the packed_uint64 field.
    - * @return {!Array.<number>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.packedUint64Array = function() {
    -  return /** @type {!Array.<number>} */ (this.array$Values(57));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the packed_uint64 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasPackedUint64 = function() {
    -  return this.has$Value(57);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the packed_uint64 field.
    - */
    -proto2.TestAllTypes.prototype.packedUint64Count = function() {
    -  return this.count$Values(57);
    -};
    -
    -
    -/**
    - * Clears the values in the packed_uint64 field.
    - */
    -proto2.TestAllTypes.prototype.clearPackedUint64 = function() {
    -  this.clear$Field(57);
    -};
    -
    -
    -/**
    - * Gets the value of the packed_sint32 field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.prototype.getPackedSint32 = function(index) {
    -  return /** @type {?number} */ (this.get$Value(58, index));
    -};
    -
    -
    -/**
    - * Gets the value of the packed_sint32 field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.prototype.getPackedSint32OrDefault = function(index) {
    -  return /** @type {number} */ (this.get$ValueOrDefault(58, index));
    -};
    -
    -
    -/**
    - * Adds a value to the packed_sint32 field.
    - * @param {number} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addPackedSint32 = function(value) {
    -  this.add$Value(58, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the packed_sint32 field.
    - * @return {!Array.<number>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.packedSint32Array = function() {
    -  return /** @type {!Array.<number>} */ (this.array$Values(58));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the packed_sint32 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasPackedSint32 = function() {
    -  return this.has$Value(58);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the packed_sint32 field.
    - */
    -proto2.TestAllTypes.prototype.packedSint32Count = function() {
    -  return this.count$Values(58);
    -};
    -
    -
    -/**
    - * Clears the values in the packed_sint32 field.
    - */
    -proto2.TestAllTypes.prototype.clearPackedSint32 = function() {
    -  this.clear$Field(58);
    -};
    -
    -
    -/**
    - * Gets the value of the packed_sint64 field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.prototype.getPackedSint64 = function(index) {
    -  return /** @type {?number} */ (this.get$Value(59, index));
    -};
    -
    -
    -/**
    - * Gets the value of the packed_sint64 field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.prototype.getPackedSint64OrDefault = function(index) {
    -  return /** @type {number} */ (this.get$ValueOrDefault(59, index));
    -};
    -
    -
    -/**
    - * Adds a value to the packed_sint64 field.
    - * @param {number} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addPackedSint64 = function(value) {
    -  this.add$Value(59, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the packed_sint64 field.
    - * @return {!Array.<number>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.packedSint64Array = function() {
    -  return /** @type {!Array.<number>} */ (this.array$Values(59));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the packed_sint64 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasPackedSint64 = function() {
    -  return this.has$Value(59);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the packed_sint64 field.
    - */
    -proto2.TestAllTypes.prototype.packedSint64Count = function() {
    -  return this.count$Values(59);
    -};
    -
    -
    -/**
    - * Clears the values in the packed_sint64 field.
    - */
    -proto2.TestAllTypes.prototype.clearPackedSint64 = function() {
    -  this.clear$Field(59);
    -};
    -
    -
    -/**
    - * Gets the value of the packed_fixed32 field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.prototype.getPackedFixed32 = function(index) {
    -  return /** @type {?number} */ (this.get$Value(60, index));
    -};
    -
    -
    -/**
    - * Gets the value of the packed_fixed32 field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.prototype.getPackedFixed32OrDefault = function(index) {
    -  return /** @type {number} */ (this.get$ValueOrDefault(60, index));
    -};
    -
    -
    -/**
    - * Adds a value to the packed_fixed32 field.
    - * @param {number} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addPackedFixed32 = function(value) {
    -  this.add$Value(60, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the packed_fixed32 field.
    - * @return {!Array.<number>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.packedFixed32Array = function() {
    -  return /** @type {!Array.<number>} */ (this.array$Values(60));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the packed_fixed32 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasPackedFixed32 = function() {
    -  return this.has$Value(60);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the packed_fixed32 field.
    - */
    -proto2.TestAllTypes.prototype.packedFixed32Count = function() {
    -  return this.count$Values(60);
    -};
    -
    -
    -/**
    - * Clears the values in the packed_fixed32 field.
    - */
    -proto2.TestAllTypes.prototype.clearPackedFixed32 = function() {
    -  this.clear$Field(60);
    -};
    -
    -
    -/**
    - * Gets the value of the packed_fixed64 field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.prototype.getPackedFixed64 = function(index) {
    -  return /** @type {?number} */ (this.get$Value(61, index));
    -};
    -
    -
    -/**
    - * Gets the value of the packed_fixed64 field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.prototype.getPackedFixed64OrDefault = function(index) {
    -  return /** @type {number} */ (this.get$ValueOrDefault(61, index));
    -};
    -
    -
    -/**
    - * Adds a value to the packed_fixed64 field.
    - * @param {number} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addPackedFixed64 = function(value) {
    -  this.add$Value(61, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the packed_fixed64 field.
    - * @return {!Array.<number>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.packedFixed64Array = function() {
    -  return /** @type {!Array.<number>} */ (this.array$Values(61));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the packed_fixed64 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasPackedFixed64 = function() {
    -  return this.has$Value(61);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the packed_fixed64 field.
    - */
    -proto2.TestAllTypes.prototype.packedFixed64Count = function() {
    -  return this.count$Values(61);
    -};
    -
    -
    -/**
    - * Clears the values in the packed_fixed64 field.
    - */
    -proto2.TestAllTypes.prototype.clearPackedFixed64 = function() {
    -  this.clear$Field(61);
    -};
    -
    -
    -/**
    - * Gets the value of the packed_sfixed32 field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.prototype.getPackedSfixed32 = function(index) {
    -  return /** @type {?number} */ (this.get$Value(62, index));
    -};
    -
    -
    -/**
    - * Gets the value of the packed_sfixed32 field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.prototype.getPackedSfixed32OrDefault = function(index) {
    -  return /** @type {number} */ (this.get$ValueOrDefault(62, index));
    -};
    -
    -
    -/**
    - * Adds a value to the packed_sfixed32 field.
    - * @param {number} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addPackedSfixed32 = function(value) {
    -  this.add$Value(62, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the packed_sfixed32 field.
    - * @return {!Array.<number>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.packedSfixed32Array = function() {
    -  return /** @type {!Array.<number>} */ (this.array$Values(62));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the packed_sfixed32 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasPackedSfixed32 = function() {
    -  return this.has$Value(62);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the packed_sfixed32 field.
    - */
    -proto2.TestAllTypes.prototype.packedSfixed32Count = function() {
    -  return this.count$Values(62);
    -};
    -
    -
    -/**
    - * Clears the values in the packed_sfixed32 field.
    - */
    -proto2.TestAllTypes.prototype.clearPackedSfixed32 = function() {
    -  this.clear$Field(62);
    -};
    -
    -
    -/**
    - * Gets the value of the packed_sfixed64 field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.prototype.getPackedSfixed64 = function(index) {
    -  return /** @type {?number} */ (this.get$Value(63, index));
    -};
    -
    -
    -/**
    - * Gets the value of the packed_sfixed64 field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.prototype.getPackedSfixed64OrDefault = function(index) {
    -  return /** @type {number} */ (this.get$ValueOrDefault(63, index));
    -};
    -
    -
    -/**
    - * Adds a value to the packed_sfixed64 field.
    - * @param {number} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addPackedSfixed64 = function(value) {
    -  this.add$Value(63, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the packed_sfixed64 field.
    - * @return {!Array.<number>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.packedSfixed64Array = function() {
    -  return /** @type {!Array.<number>} */ (this.array$Values(63));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the packed_sfixed64 field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasPackedSfixed64 = function() {
    -  return this.has$Value(63);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the packed_sfixed64 field.
    - */
    -proto2.TestAllTypes.prototype.packedSfixed64Count = function() {
    -  return this.count$Values(63);
    -};
    -
    -
    -/**
    - * Clears the values in the packed_sfixed64 field.
    - */
    -proto2.TestAllTypes.prototype.clearPackedSfixed64 = function() {
    -  this.clear$Field(63);
    -};
    -
    -
    -/**
    - * Gets the value of the packed_float field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.prototype.getPackedFloat = function(index) {
    -  return /** @type {?number} */ (this.get$Value(64, index));
    -};
    -
    -
    -/**
    - * Gets the value of the packed_float field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.prototype.getPackedFloatOrDefault = function(index) {
    -  return /** @type {number} */ (this.get$ValueOrDefault(64, index));
    -};
    -
    -
    -/**
    - * Adds a value to the packed_float field.
    - * @param {number} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addPackedFloat = function(value) {
    -  this.add$Value(64, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the packed_float field.
    - * @return {!Array.<number>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.packedFloatArray = function() {
    -  return /** @type {!Array.<number>} */ (this.array$Values(64));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the packed_float field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasPackedFloat = function() {
    -  return this.has$Value(64);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the packed_float field.
    - */
    -proto2.TestAllTypes.prototype.packedFloatCount = function() {
    -  return this.count$Values(64);
    -};
    -
    -
    -/**
    - * Clears the values in the packed_float field.
    - */
    -proto2.TestAllTypes.prototype.clearPackedFloat = function() {
    -  this.clear$Field(64);
    -};
    -
    -
    -/**
    - * Gets the value of the packed_double field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.prototype.getPackedDouble = function(index) {
    -  return /** @type {?number} */ (this.get$Value(65, index));
    -};
    -
    -
    -/**
    - * Gets the value of the packed_double field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.prototype.getPackedDoubleOrDefault = function(index) {
    -  return /** @type {number} */ (this.get$ValueOrDefault(65, index));
    -};
    -
    -
    -/**
    - * Adds a value to the packed_double field.
    - * @param {number} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addPackedDouble = function(value) {
    -  this.add$Value(65, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the packed_double field.
    - * @return {!Array.<number>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.packedDoubleArray = function() {
    -  return /** @type {!Array.<number>} */ (this.array$Values(65));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the packed_double field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasPackedDouble = function() {
    -  return this.has$Value(65);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the packed_double field.
    - */
    -proto2.TestAllTypes.prototype.packedDoubleCount = function() {
    -  return this.count$Values(65);
    -};
    -
    -
    -/**
    - * Clears the values in the packed_double field.
    - */
    -proto2.TestAllTypes.prototype.clearPackedDouble = function() {
    -  this.clear$Field(65);
    -};
    -
    -
    -/**
    - * Gets the value of the packed_bool field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?boolean} The value.
    - */
    -proto2.TestAllTypes.prototype.getPackedBool = function(index) {
    -  return /** @type {?boolean} */ (this.get$Value(66, index));
    -};
    -
    -
    -/**
    - * Gets the value of the packed_bool field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {boolean} The value.
    - */
    -proto2.TestAllTypes.prototype.getPackedBoolOrDefault = function(index) {
    -  return /** @type {boolean} */ (this.get$ValueOrDefault(66, index));
    -};
    -
    -
    -/**
    - * Adds a value to the packed_bool field.
    - * @param {boolean} value The value to add.
    - */
    -proto2.TestAllTypes.prototype.addPackedBool = function(value) {
    -  this.add$Value(66, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the packed_bool field.
    - * @return {!Array.<boolean>} The values in the field.
    - */
    -proto2.TestAllTypes.prototype.packedBoolArray = function() {
    -  return /** @type {!Array.<boolean>} */ (this.array$Values(66));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the packed_bool field has a value.
    - */
    -proto2.TestAllTypes.prototype.hasPackedBool = function() {
    -  return this.has$Value(66);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the packed_bool field.
    - */
    -proto2.TestAllTypes.prototype.packedBoolCount = function() {
    -  return this.count$Values(66);
    -};
    -
    -
    -/**
    - * Clears the values in the packed_bool field.
    - */
    -proto2.TestAllTypes.prototype.clearPackedBool = function() {
    -  this.clear$Field(66);
    -};
    -
    -
    -/**
    - * Enumeration NestedEnum.
    - * @enum {number}
    - */
    -proto2.TestAllTypes.NestedEnum = {
    -  FOO: 0,
    -  BAR: 2,
    -  BAZ: 3
    -};
    -
    -
    -
    -/**
    - * Message NestedMessage.
    - * @constructor
    - * @extends {goog.proto2.Message}
    - */
    -proto2.TestAllTypes.NestedMessage = function() {
    -  goog.proto2.Message.call(this);
    -};
    -goog.inherits(proto2.TestAllTypes.NestedMessage, goog.proto2.Message);
    -
    -
    -/**
    - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type.
    - * @return {!proto2.TestAllTypes.NestedMessage} The cloned message.
    - * @override
    - */
    -proto2.TestAllTypes.NestedMessage.prototype.clone;
    -
    -
    -/**
    - * Gets the value of the b field.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.NestedMessage.prototype.getB = function() {
    -  return /** @type {?number} */ (this.get$Value(1));
    -};
    -
    -
    -/**
    - * Gets the value of the b field or the default value if not set.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.NestedMessage.prototype.getBOrDefault = function() {
    -  return /** @type {number} */ (this.get$ValueOrDefault(1));
    -};
    -
    -
    -/**
    - * Sets the value of the b field.
    - * @param {number} value The value.
    - */
    -proto2.TestAllTypes.NestedMessage.prototype.setB = function(value) {
    -  this.set$Value(1, value);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the b field has a value.
    - */
    -proto2.TestAllTypes.NestedMessage.prototype.hasB = function() {
    -  return this.has$Value(1);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the b field.
    - */
    -proto2.TestAllTypes.NestedMessage.prototype.bCount = function() {
    -  return this.count$Values(1);
    -};
    -
    -
    -/**
    - * Clears the values in the b field.
    - */
    -proto2.TestAllTypes.NestedMessage.prototype.clearB = function() {
    -  this.clear$Field(1);
    -};
    -
    -
    -/**
    - * Gets the value of the c field.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.NestedMessage.prototype.getC = function() {
    -  return /** @type {?number} */ (this.get$Value(2));
    -};
    -
    -
    -/**
    - * Gets the value of the c field or the default value if not set.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.NestedMessage.prototype.getCOrDefault = function() {
    -  return /** @type {number} */ (this.get$ValueOrDefault(2));
    -};
    -
    -
    -/**
    - * Sets the value of the c field.
    - * @param {number} value The value.
    - */
    -proto2.TestAllTypes.NestedMessage.prototype.setC = function(value) {
    -  this.set$Value(2, value);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the c field has a value.
    - */
    -proto2.TestAllTypes.NestedMessage.prototype.hasC = function() {
    -  return this.has$Value(2);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the c field.
    - */
    -proto2.TestAllTypes.NestedMessage.prototype.cCount = function() {
    -  return this.count$Values(2);
    -};
    -
    -
    -/**
    - * Clears the values in the c field.
    - */
    -proto2.TestAllTypes.NestedMessage.prototype.clearC = function() {
    -  this.clear$Field(2);
    -};
    -
    -
    -
    -/**
    - * Message OptionalGroup.
    - * @constructor
    - * @extends {goog.proto2.Message}
    - */
    -proto2.TestAllTypes.OptionalGroup = function() {
    -  goog.proto2.Message.call(this);
    -};
    -goog.inherits(proto2.TestAllTypes.OptionalGroup, goog.proto2.Message);
    -
    -
    -/**
    - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type.
    - * @return {!proto2.TestAllTypes.OptionalGroup} The cloned message.
    - * @override
    - */
    -proto2.TestAllTypes.OptionalGroup.prototype.clone;
    -
    -
    -/**
    - * Gets the value of the a field.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.OptionalGroup.prototype.getA = function() {
    -  return /** @type {?number} */ (this.get$Value(17));
    -};
    -
    -
    -/**
    - * Gets the value of the a field or the default value if not set.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.OptionalGroup.prototype.getAOrDefault = function() {
    -  return /** @type {number} */ (this.get$ValueOrDefault(17));
    -};
    -
    -
    -/**
    - * Sets the value of the a field.
    - * @param {number} value The value.
    - */
    -proto2.TestAllTypes.OptionalGroup.prototype.setA = function(value) {
    -  this.set$Value(17, value);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the a field has a value.
    - */
    -proto2.TestAllTypes.OptionalGroup.prototype.hasA = function() {
    -  return this.has$Value(17);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the a field.
    - */
    -proto2.TestAllTypes.OptionalGroup.prototype.aCount = function() {
    -  return this.count$Values(17);
    -};
    -
    -
    -/**
    - * Clears the values in the a field.
    - */
    -proto2.TestAllTypes.OptionalGroup.prototype.clearA = function() {
    -  this.clear$Field(17);
    -};
    -
    -
    -
    -/**
    - * Message RepeatedGroup.
    - * @constructor
    - * @extends {goog.proto2.Message}
    - */
    -proto2.TestAllTypes.RepeatedGroup = function() {
    -  goog.proto2.Message.call(this);
    -};
    -goog.inherits(proto2.TestAllTypes.RepeatedGroup, goog.proto2.Message);
    -
    -
    -/**
    - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type.
    - * @return {!proto2.TestAllTypes.RepeatedGroup} The cloned message.
    - * @override
    - */
    -proto2.TestAllTypes.RepeatedGroup.prototype.clone;
    -
    -
    -/**
    - * Gets the value of the a field at the index given.
    - * @param {number} index The index to lookup.
    - * @return {?number} The value.
    - */
    -proto2.TestAllTypes.RepeatedGroup.prototype.getA = function(index) {
    -  return /** @type {?number} */ (this.get$Value(47, index));
    -};
    -
    -
    -/**
    - * Gets the value of the a field at the index given or the default value if not set.
    - * @param {number} index The index to lookup.
    - * @return {number} The value.
    - */
    -proto2.TestAllTypes.RepeatedGroup.prototype.getAOrDefault = function(index) {
    -  return /** @type {number} */ (this.get$ValueOrDefault(47, index));
    -};
    -
    -
    -/**
    - * Adds a value to the a field.
    - * @param {number} value The value to add.
    - */
    -proto2.TestAllTypes.RepeatedGroup.prototype.addA = function(value) {
    -  this.add$Value(47, value);
    -};
    -
    -
    -/**
    - * Returns the array of values in the a field.
    - * @return {!Array.<number>} The values in the field.
    - */
    -proto2.TestAllTypes.RepeatedGroup.prototype.aArray = function() {
    -  return /** @type {!Array.<number>} */ (this.array$Values(47));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the a field has a value.
    - */
    -proto2.TestAllTypes.RepeatedGroup.prototype.hasA = function() {
    -  return this.has$Value(47);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the a field.
    - */
    -proto2.TestAllTypes.RepeatedGroup.prototype.aCount = function() {
    -  return this.count$Values(47);
    -};
    -
    -
    -/**
    - * Clears the values in the a field.
    - */
    -proto2.TestAllTypes.RepeatedGroup.prototype.clearA = function() {
    -  this.clear$Field(47);
    -};
    -
    -
    -
    -/**
    - * Message TestDefaultParent.
    - * @constructor
    - * @extends {goog.proto2.Message}
    - */
    -proto2.TestDefaultParent = function() {
    -  goog.proto2.Message.call(this);
    -};
    -goog.inherits(proto2.TestDefaultParent, goog.proto2.Message);
    -
    -
    -/**
    - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type.
    - * @return {!proto2.TestDefaultParent} The cloned message.
    - * @override
    - */
    -proto2.TestDefaultParent.prototype.clone;
    -
    -
    -/**
    - * Gets the value of the child field.
    - * @return {proto2.TestDefaultChild} The value.
    - */
    -proto2.TestDefaultParent.prototype.getChild = function() {
    -  return /** @type {proto2.TestDefaultChild} */ (this.get$Value(1));
    -};
    -
    -
    -/**
    - * Gets the value of the child field or the default value if not set.
    - * @return {!proto2.TestDefaultChild} The value.
    - */
    -proto2.TestDefaultParent.prototype.getChildOrDefault = function() {
    -  return /** @type {!proto2.TestDefaultChild} */ (this.get$ValueOrDefault(1));
    -};
    -
    -
    -/**
    - * Sets the value of the child field.
    - * @param {!proto2.TestDefaultChild} value The value.
    - */
    -proto2.TestDefaultParent.prototype.setChild = function(value) {
    -  this.set$Value(1, value);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the child field has a value.
    - */
    -proto2.TestDefaultParent.prototype.hasChild = function() {
    -  return this.has$Value(1);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the child field.
    - */
    -proto2.TestDefaultParent.prototype.childCount = function() {
    -  return this.count$Values(1);
    -};
    -
    -
    -/**
    - * Clears the values in the child field.
    - */
    -proto2.TestDefaultParent.prototype.clearChild = function() {
    -  this.clear$Field(1);
    -};
    -
    -
    -
    -/**
    - * Message TestDefaultChild.
    - * @constructor
    - * @extends {goog.proto2.Message}
    - */
    -proto2.TestDefaultChild = function() {
    -  goog.proto2.Message.call(this);
    -};
    -goog.inherits(proto2.TestDefaultChild, goog.proto2.Message);
    -
    -
    -/**
    - * Overrides {@link goog.proto2.Message#clone} to specify its exact return type.
    - * @return {!proto2.TestDefaultChild} The cloned message.
    - * @override
    - */
    -proto2.TestDefaultChild.prototype.clone;
    -
    -
    -/**
    - * Gets the value of the foo field.
    - * @return {?boolean} The value.
    - */
    -proto2.TestDefaultChild.prototype.getFoo = function() {
    -  return /** @type {?boolean} */ (this.get$Value(1));
    -};
    -
    -
    -/**
    - * Gets the value of the foo field or the default value if not set.
    - * @return {boolean} The value.
    - */
    -proto2.TestDefaultChild.prototype.getFooOrDefault = function() {
    -  return /** @type {boolean} */ (this.get$ValueOrDefault(1));
    -};
    -
    -
    -/**
    - * Sets the value of the foo field.
    - * @param {boolean} value The value.
    - */
    -proto2.TestDefaultChild.prototype.setFoo = function(value) {
    -  this.set$Value(1, value);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the foo field has a value.
    - */
    -proto2.TestDefaultChild.prototype.hasFoo = function() {
    -  return this.has$Value(1);
    -};
    -
    -
    -/**
    - * @return {number} The number of values in the foo field.
    - */
    -proto2.TestDefaultChild.prototype.fooCount = function() {
    -  return this.count$Values(1);
    -};
    -
    -
    -/**
    - * Clears the values in the foo field.
    - */
    -proto2.TestDefaultChild.prototype.clearFoo = function() {
    -  this.clear$Field(1);
    -};
    -
    -
    -/** @override */
    -proto2.TestAllTypes.prototype.getDescriptor = function() {
    -  if (!proto2.TestAllTypes.descriptor_) {
    -    // The descriptor is created lazily when we instantiate a new instance.
    -    var descriptorObj = {
    -      0: {
    -        name: 'TestAllTypes',
    -        fullName: 'TestAllTypes'
    -      },
    -      1: {
    -        name: 'optional_int32',
    -        fieldType: goog.proto2.Message.FieldType.INT32,
    -        type: Number
    -      },
    -      2: {
    -        name: 'optional_int64',
    -        fieldType: goog.proto2.Message.FieldType.INT64,
    -        defaultValue: '1',
    -        type: String
    -      },
    -      3: {
    -        name: 'optional_uint32',
    -        fieldType: goog.proto2.Message.FieldType.UINT32,
    -        type: Number
    -      },
    -      4: {
    -        name: 'optional_uint64',
    -        fieldType: goog.proto2.Message.FieldType.UINT64,
    -        type: String
    -      },
    -      5: {
    -        name: 'optional_sint32',
    -        fieldType: goog.proto2.Message.FieldType.SINT32,
    -        type: Number
    -      },
    -      6: {
    -        name: 'optional_sint64',
    -        fieldType: goog.proto2.Message.FieldType.SINT64,
    -        type: String
    -      },
    -      7: {
    -        name: 'optional_fixed32',
    -        fieldType: goog.proto2.Message.FieldType.FIXED32,
    -        type: Number
    -      },
    -      8: {
    -        name: 'optional_fixed64',
    -        fieldType: goog.proto2.Message.FieldType.FIXED64,
    -        type: String
    -      },
    -      9: {
    -        name: 'optional_sfixed32',
    -        fieldType: goog.proto2.Message.FieldType.SFIXED32,
    -        type: Number
    -      },
    -      10: {
    -        name: 'optional_sfixed64',
    -        fieldType: goog.proto2.Message.FieldType.SFIXED64,
    -        type: String
    -      },
    -      11: {
    -        name: 'optional_float',
    -        fieldType: goog.proto2.Message.FieldType.FLOAT,
    -        defaultValue: 1.5,
    -        type: Number
    -      },
    -      12: {
    -        name: 'optional_double',
    -        fieldType: goog.proto2.Message.FieldType.DOUBLE,
    -        type: Number
    -      },
    -      13: {
    -        name: 'optional_bool',
    -        fieldType: goog.proto2.Message.FieldType.BOOL,
    -        type: Boolean
    -      },
    -      14: {
    -        name: 'optional_string',
    -        fieldType: goog.proto2.Message.FieldType.STRING,
    -        type: String
    -      },
    -      15: {
    -        name: 'optional_bytes',
    -        fieldType: goog.proto2.Message.FieldType.BYTES,
    -        defaultValue: 'moo',
    -        type: String
    -      },
    -      16: {
    -        name: 'optionalgroup',
    -        fieldType: goog.proto2.Message.FieldType.GROUP,
    -        type: proto2.TestAllTypes.OptionalGroup
    -      },
    -      18: {
    -        name: 'optional_nested_message',
    -        fieldType: goog.proto2.Message.FieldType.MESSAGE,
    -        type: proto2.TestAllTypes.NestedMessage
    -      },
    -      21: {
    -        name: 'optional_nested_enum',
    -        fieldType: goog.proto2.Message.FieldType.ENUM,
    -        defaultValue: proto2.TestAllTypes.NestedEnum.FOO,
    -        type: proto2.TestAllTypes.NestedEnum
    -      },
    -      50: {
    -        name: 'optional_int64_number',
    -        fieldType: goog.proto2.Message.FieldType.INT64,
    -        defaultValue: 1000000000000000001,
    -        type: Number
    -      },
    -      51: {
    -        name: 'optional_int64_string',
    -        fieldType: goog.proto2.Message.FieldType.INT64,
    -        defaultValue: '1000000000000000001',
    -        type: String
    -      },
    -      31: {
    -        name: 'repeated_int32',
    -        repeated: true,
    -        fieldType: goog.proto2.Message.FieldType.INT32,
    -        type: Number
    -      },
    -      32: {
    -        name: 'repeated_int64',
    -        repeated: true,
    -        fieldType: goog.proto2.Message.FieldType.INT64,
    -        type: String
    -      },
    -      33: {
    -        name: 'repeated_uint32',
    -        repeated: true,
    -        fieldType: goog.proto2.Message.FieldType.UINT32,
    -        type: Number
    -      },
    -      34: {
    -        name: 'repeated_uint64',
    -        repeated: true,
    -        fieldType: goog.proto2.Message.FieldType.UINT64,
    -        type: String
    -      },
    -      35: {
    -        name: 'repeated_sint32',
    -        repeated: true,
    -        fieldType: goog.proto2.Message.FieldType.SINT32,
    -        type: Number
    -      },
    -      36: {
    -        name: 'repeated_sint64',
    -        repeated: true,
    -        fieldType: goog.proto2.Message.FieldType.SINT64,
    -        type: String
    -      },
    -      37: {
    -        name: 'repeated_fixed32',
    -        repeated: true,
    -        fieldType: goog.proto2.Message.FieldType.FIXED32,
    -        type: Number
    -      },
    -      38: {
    -        name: 'repeated_fixed64',
    -        repeated: true,
    -        fieldType: goog.proto2.Message.FieldType.FIXED64,
    -        type: String
    -      },
    -      39: {
    -        name: 'repeated_sfixed32',
    -        repeated: true,
    -        fieldType: goog.proto2.Message.FieldType.SFIXED32,
    -        type: Number
    -      },
    -      40: {
    -        name: 'repeated_sfixed64',
    -        repeated: true,
    -        fieldType: goog.proto2.Message.FieldType.SFIXED64,
    -        type: String
    -      },
    -      41: {
    -        name: 'repeated_float',
    -        repeated: true,
    -        fieldType: goog.proto2.Message.FieldType.FLOAT,
    -        type: Number
    -      },
    -      42: {
    -        name: 'repeated_double',
    -        repeated: true,
    -        fieldType: goog.proto2.Message.FieldType.DOUBLE,
    -        type: Number
    -      },
    -      43: {
    -        name: 'repeated_bool',
    -        repeated: true,
    -        fieldType: goog.proto2.Message.FieldType.BOOL,
    -        type: Boolean
    -      },
    -      44: {
    -        name: 'repeated_string',
    -        repeated: true,
    -        fieldType: goog.proto2.Message.FieldType.STRING,
    -        type: String
    -      },
    -      45: {
    -        name: 'repeated_bytes',
    -        repeated: true,
    -        fieldType: goog.proto2.Message.FieldType.BYTES,
    -        type: String
    -      },
    -      46: {
    -        name: 'repeatedgroup',
    -        repeated: true,
    -        fieldType: goog.proto2.Message.FieldType.GROUP,
    -        type: proto2.TestAllTypes.RepeatedGroup
    -      },
    -      48: {
    -        name: 'repeated_nested_message',
    -        repeated: true,
    -        fieldType: goog.proto2.Message.FieldType.MESSAGE,
    -        type: proto2.TestAllTypes.NestedMessage
    -      },
    -      49: {
    -        name: 'repeated_nested_enum',
    -        repeated: true,
    -        fieldType: goog.proto2.Message.FieldType.ENUM,
    -        defaultValue: proto2.TestAllTypes.NestedEnum.FOO,
    -        type: proto2.TestAllTypes.NestedEnum
    -      },
    -      52: {
    -        name: 'repeated_int64_number',
    -        repeated: true,
    -        fieldType: goog.proto2.Message.FieldType.INT64,
    -        type: Number
    -      },
    -      53: {
    -        name: 'repeated_int64_string',
    -        repeated: true,
    -        fieldType: goog.proto2.Message.FieldType.INT64,
    -        type: String
    -      },
    -      54: {
    -        name: 'packed_int32',
    -        repeated: true,
    -        packed: true,
    -        fieldType: goog.proto2.Message.FieldType.INT32,
    -        type: Number
    -      },
    -      55: {
    -        name: 'packed_int64',
    -        repeated: true,
    -        packed: true,
    -        fieldType: goog.proto2.Message.FieldType.INT64,
    -        type: Number
    -      },
    -      56: {
    -        name: 'packed_uint32',
    -        repeated: true,
    -        packed: true,
    -        fieldType: goog.proto2.Message.FieldType.UINT32,
    -        type: Number
    -      },
    -      57: {
    -        name: 'packed_uint64',
    -        repeated: true,
    -        packed: true,
    -        fieldType: goog.proto2.Message.FieldType.UINT64,
    -        type: Number
    -      },
    -      58: {
    -        name: 'packed_sint32',
    -        repeated: true,
    -        packed: true,
    -        fieldType: goog.proto2.Message.FieldType.SINT32,
    -        type: Number
    -      },
    -      59: {
    -        name: 'packed_sint64',
    -        repeated: true,
    -        packed: true,
    -        fieldType: goog.proto2.Message.FieldType.SINT64,
    -        type: Number
    -      },
    -      60: {
    -        name: 'packed_fixed32',
    -        repeated: true,
    -        packed: true,
    -        fieldType: goog.proto2.Message.FieldType.FIXED32,
    -        type: Number
    -      },
    -      61: {
    -        name: 'packed_fixed64',
    -        repeated: true,
    -        packed: true,
    -        fieldType: goog.proto2.Message.FieldType.FIXED64,
    -        type: Number
    -      },
    -      62: {
    -        name: 'packed_sfixed32',
    -        repeated: true,
    -        packed: true,
    -        fieldType: goog.proto2.Message.FieldType.SFIXED32,
    -        type: Number
    -      },
    -      63: {
    -        name: 'packed_sfixed64',
    -        repeated: true,
    -        packed: true,
    -        fieldType: goog.proto2.Message.FieldType.SFIXED64,
    -        type: Number
    -      },
    -      64: {
    -        name: 'packed_float',
    -        repeated: true,
    -        packed: true,
    -        fieldType: goog.proto2.Message.FieldType.FLOAT,
    -        type: Number
    -      },
    -      65: {
    -        name: 'packed_double',
    -        repeated: true,
    -        packed: true,
    -        fieldType: goog.proto2.Message.FieldType.DOUBLE,
    -        type: Number
    -      },
    -      66: {
    -        name: 'packed_bool',
    -        repeated: true,
    -        packed: true,
    -        fieldType: goog.proto2.Message.FieldType.BOOL,
    -        type: Boolean
    -      }
    -    };
    -    proto2.TestAllTypes.descriptor_ =
    -        goog.proto2.Message.createDescriptor(
    -             proto2.TestAllTypes, descriptorObj);
    -  }
    -  return proto2.TestAllTypes.descriptor_;
    -};
    -
    -
    -proto2.TestAllTypes['ctor'] = proto2.TestAllTypes;proto2.TestAllTypes['ctor'].getDescriptor =
    -    proto2.TestAllTypes.prototype.getDescriptor;
    -
    -
    -/** @override */
    -proto2.TestAllTypes.NestedMessage.prototype.getDescriptor = function() {
    -  if (!proto2.TestAllTypes.NestedMessage.descriptor_) {
    -    // The descriptor is created lazily when we instantiate a new instance.
    -    var descriptorObj = {
    -      0: {
    -        name: 'NestedMessage',
    -        containingType: proto2.TestAllTypes,
    -        fullName: 'TestAllTypes.NestedMessage'
    -      },
    -      1: {
    -        name: 'b',
    -        fieldType: goog.proto2.Message.FieldType.INT32,
    -        type: Number
    -      },
    -      2: {
    -        name: 'c',
    -        fieldType: goog.proto2.Message.FieldType.INT32,
    -        type: Number
    -      }
    -    };
    -    proto2.TestAllTypes.NestedMessage.descriptor_ =
    -        goog.proto2.Message.createDescriptor(
    -             proto2.TestAllTypes.NestedMessage, descriptorObj);
    -  }
    -  return proto2.TestAllTypes.NestedMessage.descriptor_;
    -};
    -
    -
    -proto2.TestAllTypes.NestedMessage['ctor'] = proto2.TestAllTypes.NestedMessage;proto2.TestAllTypes.NestedMessage['ctor'].getDescriptor =
    -    proto2.TestAllTypes.NestedMessage.prototype.getDescriptor;
    -
    -
    -/** @override */
    -proto2.TestAllTypes.OptionalGroup.prototype.getDescriptor = function() {
    -  if (!proto2.TestAllTypes.OptionalGroup.descriptor_) {
    -    // The descriptor is created lazily when we instantiate a new instance.
    -    var descriptorObj = {
    -      0: {
    -        name: 'OptionalGroup',
    -        containingType: proto2.TestAllTypes,
    -        fullName: 'TestAllTypes.OptionalGroup'
    -      },
    -      17: {
    -        name: 'a',
    -        fieldType: goog.proto2.Message.FieldType.INT32,
    -        type: Number
    -      }
    -    };
    -    proto2.TestAllTypes.OptionalGroup.descriptor_ =
    -        goog.proto2.Message.createDescriptor(
    -             proto2.TestAllTypes.OptionalGroup, descriptorObj);
    -  }
    -  return proto2.TestAllTypes.OptionalGroup.descriptor_;
    -};
    -
    -
    -proto2.TestAllTypes.OptionalGroup['ctor'] = proto2.TestAllTypes.OptionalGroup;proto2.TestAllTypes.OptionalGroup['ctor'].getDescriptor =
    -    proto2.TestAllTypes.OptionalGroup.prototype.getDescriptor;
    -
    -
    -/** @override */
    -proto2.TestAllTypes.RepeatedGroup.prototype.getDescriptor = function() {
    -  if (!proto2.TestAllTypes.RepeatedGroup.descriptor_) {
    -    // The descriptor is created lazily when we instantiate a new instance.
    -    var descriptorObj = {
    -      0: {
    -        name: 'RepeatedGroup',
    -        containingType: proto2.TestAllTypes,
    -        fullName: 'TestAllTypes.RepeatedGroup'
    -      },
    -      47: {
    -        name: 'a',
    -        repeated: true,
    -        fieldType: goog.proto2.Message.FieldType.INT32,
    -        type: Number
    -      }
    -    };
    -    proto2.TestAllTypes.RepeatedGroup.descriptor_ =
    -        goog.proto2.Message.createDescriptor(
    -             proto2.TestAllTypes.RepeatedGroup, descriptorObj);
    -  }
    -  return proto2.TestAllTypes.RepeatedGroup.descriptor_;
    -};
    -
    -
    -proto2.TestAllTypes.RepeatedGroup['ctor'] = proto2.TestAllTypes.RepeatedGroup;proto2.TestAllTypes.RepeatedGroup['ctor'].getDescriptor =
    -    proto2.TestAllTypes.RepeatedGroup.prototype.getDescriptor;
    -
    -
    -/** @override */
    -proto2.TestDefaultParent.prototype.getDescriptor = function() {
    -  if (!proto2.TestDefaultParent.descriptor_) {
    -    // The descriptor is created lazily when we instantiate a new instance.
    -    var descriptorObj = {
    -      0: {
    -        name: 'TestDefaultParent',
    -        fullName: 'TestDefaultParent'
    -      },
    -      1: {
    -        name: 'child',
    -        fieldType: goog.proto2.Message.FieldType.MESSAGE,
    -        type: proto2.TestDefaultChild
    -      }
    -    };
    -    proto2.TestDefaultParent.descriptor_ =
    -        goog.proto2.Message.createDescriptor(
    -             proto2.TestDefaultParent, descriptorObj);
    -  }
    -  return proto2.TestDefaultParent.descriptor_;
    -};
    -
    -
    -proto2.TestDefaultParent['ctor'] = proto2.TestDefaultParent;proto2.TestDefaultParent['ctor'].getDescriptor =
    -    proto2.TestDefaultParent.prototype.getDescriptor;
    -
    -
    -/** @override */
    -proto2.TestDefaultChild.prototype.getDescriptor = function() {
    -  if (!proto2.TestDefaultChild.descriptor_) {
    -    // The descriptor is created lazily when we instantiate a new instance.
    -    var descriptorObj = {
    -      0: {
    -        name: 'TestDefaultChild',
    -        fullName: 'TestDefaultChild'
    -      },
    -      1: {
    -        name: 'foo',
    -        fieldType: goog.proto2.Message.FieldType.BOOL,
    -        defaultValue: true,
    -        type: Boolean
    -      }
    -    };
    -    proto2.TestDefaultChild.descriptor_ =
    -        goog.proto2.Message.createDescriptor(
    -             proto2.TestDefaultChild, descriptorObj);
    -  }
    -  return proto2.TestDefaultChild.descriptor_;
    -};
    -
    -
    -proto2.TestDefaultChild['ctor'] = proto2.TestDefaultChild;proto2.TestDefaultChild['ctor'].getDescriptor =
    -    proto2.TestDefaultChild.prototype.getDescriptor;
    diff --git a/src/database/third_party/closure-library/closure/goog/proto2/textformatserializer.js b/src/database/third_party/closure-library/closure/goog/proto2/textformatserializer.js
    deleted file mode 100644
    index a1161f344d8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/proto2/textformatserializer.js
    +++ /dev/null
    @@ -1,1070 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Protocol Buffer 2 Serializer which serializes messages
    - *  into a user-friendly text format. Note that this code can run a bit
    - *  slowly (especially for parsing) and should therefore not be used for
    - *  time or space-critical applications.
    - *
    - * @see http://goo.gl/QDmDr
    - */
    -
    -goog.provide('goog.proto2.TextFormatSerializer');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.json');
    -goog.require('goog.math');
    -goog.require('goog.object');
    -goog.require('goog.proto2.FieldDescriptor');
    -goog.require('goog.proto2.Message');
    -goog.require('goog.proto2.Serializer');
    -goog.require('goog.string');
    -
    -
    -
    -/**
    - * TextFormatSerializer, a serializer which turns Messages into the human
    - * readable text format.
    - * @param {boolean=} opt_ignoreMissingFields If true, then fields that cannot be
    - *     found on the proto when parsing the text format will be ignored.
    - * @param {boolean=} opt_useEnumValues If true, serialization code for enums
    - *     will use enum integer values instead of human-readable symbolic names.
    - * @constructor
    - * @extends {goog.proto2.Serializer}
    - * @final
    - */
    -goog.proto2.TextFormatSerializer = function(
    -    opt_ignoreMissingFields, opt_useEnumValues) {
    -  /**
    -   * Whether to ignore fields not defined on the proto when parsing the text
    -   * format.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.ignoreMissingFields_ = !!opt_ignoreMissingFields;
    -
    -  /**
    -   * Whether to use integer enum values during enum serialization.
    -   * If false, symbolic names will be used.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.useEnumValues_ = !!opt_useEnumValues;
    -};
    -goog.inherits(goog.proto2.TextFormatSerializer, goog.proto2.Serializer);
    -
    -
    -/**
    - * Deserializes a message from text format and places the data in the message.
    - * @param {goog.proto2.Message} message The message in which to
    - *     place the information.
    - * @param {*} data The text format data.
    - * @return {?string} The parse error or null on success.
    - * @override
    - */
    -goog.proto2.TextFormatSerializer.prototype.deserializeTo =
    -    function(message, data) {
    -  var descriptor = message.getDescriptor();
    -  var textData = data.toString();
    -  var parser = new goog.proto2.TextFormatSerializer.Parser();
    -  if (!parser.parse(message, textData, this.ignoreMissingFields_)) {
    -    return parser.getError();
    -  }
    -
    -  return null;
    -};
    -
    -
    -/**
    - * Serializes a message to a string.
    - * @param {goog.proto2.Message} message The message to be serialized.
    - * @return {string} The serialized form of the message.
    - * @override
    - */
    -goog.proto2.TextFormatSerializer.prototype.serialize = function(message) {
    -  var printer = new goog.proto2.TextFormatSerializer.Printer_();
    -  this.serializeMessage_(message, printer);
    -  return printer.toString();
    -};
    -
    -
    -/**
    - * Serializes the message and prints the text form into the given printer.
    - * @param {goog.proto2.Message} message The message to serialize.
    - * @param {goog.proto2.TextFormatSerializer.Printer_} printer The printer to
    - *    which the text format will be printed.
    - * @private
    - */
    -goog.proto2.TextFormatSerializer.prototype.serializeMessage_ =
    -    function(message, printer) {
    -  var descriptor = message.getDescriptor();
    -  var fields = descriptor.getFields();
    -
    -  // Add the defined fields, recursively.
    -  goog.array.forEach(fields, function(field) {
    -    this.printField_(message, field, printer);
    -  }, this);
    -
    -  // Add the unknown fields, if any.
    -  message.forEachUnknown(function(tag, value) {
    -    this.serializeUnknown_(tag, value, printer);
    -  }, this);
    -};
    -
    -
    -/**
    - * Serializes an unknown field. When parsed from the JsPb object format, this
    - * manifests as either a primitive type, an array, or a raw object with integer
    - * keys. There is no descriptor available to interpret the types of nested
    - * messages.
    - * @param {number} tag The tag for the field. Since it's unknown, this is a
    - *     number rather than a string.
    - * @param {*} value The value of the field.
    - * @param {!goog.proto2.TextFormatSerializer.Printer_} printer The printer to
    - *     which the text format will be serialized.
    - * @private
    - */
    -goog.proto2.TextFormatSerializer.prototype.serializeUnknown_ =
    -    function(tag, value, printer) {
    -  if (!goog.isDefAndNotNull(value)) {
    -    return;
    -  }
    -
    -  if (goog.isArray(value)) {
    -    goog.array.forEach(value, function(val) {
    -      this.serializeUnknown_(tag, val, printer);
    -    }, this);
    -    return;
    -  }
    -
    -  if (goog.isObject(value)) {
    -    printer.append(tag);
    -    printer.append(' {');
    -    printer.appendLine();
    -    printer.indent();
    -    if (value instanceof goog.proto2.Message) {
    -      // Note(user): This conditional is here to make the
    -      // testSerializationOfUnknown unit test pass, but in practice we should
    -      // never have a Message for an "unknown" field.
    -      this.serializeMessage_(value, printer);
    -    } else {
    -      // For an unknown message, fields are keyed by positive integers. We
    -      // don't have a 'length' property to use for enumeration, so go through
    -      // all properties and ignore the ones that aren't legal keys.
    -      for (var key in value) {
    -        var keyAsNumber = goog.string.parseInt(key);
    -        goog.asserts.assert(goog.math.isInt(keyAsNumber));
    -        this.serializeUnknown_(keyAsNumber, value[key], printer);
    -      }
    -    }
    -    printer.dedent();
    -    printer.append('}');
    -    printer.appendLine();
    -    return;
    -  }
    -
    -  if (goog.isString(value)) {
    -    value = goog.string.quote(value);
    -  }
    -  printer.append(tag);
    -  printer.append(': ');
    -  printer.append(value.toString());
    -  printer.appendLine();
    -};
    -
    -
    -/**
    - * Prints the serialized value for the given field to the printer.
    - * @param {*} value The field's value.
    - * @param {goog.proto2.FieldDescriptor} field The field whose value is being
    - *    printed.
    - * @param {goog.proto2.TextFormatSerializer.Printer_} printer The printer to
    - *    which the value will be printed.
    - * @private
    - */
    -goog.proto2.TextFormatSerializer.prototype.printFieldValue_ =
    -    function(value, field, printer) {
    -  switch (field.getFieldType()) {
    -    case goog.proto2.FieldDescriptor.FieldType.DOUBLE:
    -    case goog.proto2.FieldDescriptor.FieldType.FLOAT:
    -    case goog.proto2.FieldDescriptor.FieldType.INT64:
    -    case goog.proto2.FieldDescriptor.FieldType.UINT64:
    -    case goog.proto2.FieldDescriptor.FieldType.INT32:
    -    case goog.proto2.FieldDescriptor.FieldType.UINT32:
    -    case goog.proto2.FieldDescriptor.FieldType.FIXED64:
    -    case goog.proto2.FieldDescriptor.FieldType.FIXED32:
    -    case goog.proto2.FieldDescriptor.FieldType.BOOL:
    -    case goog.proto2.FieldDescriptor.FieldType.SFIXED32:
    -    case goog.proto2.FieldDescriptor.FieldType.SFIXED64:
    -    case goog.proto2.FieldDescriptor.FieldType.SINT32:
    -    case goog.proto2.FieldDescriptor.FieldType.SINT64:
    -      printer.append(value);
    -      break;
    -
    -    case goog.proto2.FieldDescriptor.FieldType.BYTES:
    -    case goog.proto2.FieldDescriptor.FieldType.STRING:
    -      value = goog.string.quote(value.toString());
    -      printer.append(value);
    -      break;
    -
    -    case goog.proto2.FieldDescriptor.FieldType.ENUM:
    -      if (!this.useEnumValues_) {
    -        // Search the enum type for a matching key.
    -        var found = false;
    -        goog.object.forEach(field.getNativeType(), function(eValue, key) {
    -          if (eValue == value) {
    -            printer.append(key);
    -            found = true;
    -          }
    -        });
    -      }
    -
    -      if (!found || this.useEnumValues_) {
    -        // Otherwise, just print the numeric value.
    -        printer.append(value.toString());
    -      }
    -      break;
    -
    -    case goog.proto2.FieldDescriptor.FieldType.GROUP:
    -    case goog.proto2.FieldDescriptor.FieldType.MESSAGE:
    -      this.serializeMessage_(
    -          /** @type {goog.proto2.Message} */ (value), printer);
    -      break;
    -  }
    -};
    -
    -
    -/**
    - * Prints the serialized field to the printer.
    - * @param {goog.proto2.Message} message The parent message.
    - * @param {goog.proto2.FieldDescriptor} field The field to print.
    - * @param {goog.proto2.TextFormatSerializer.Printer_} printer The printer to
    - *    which the field will be printed.
    - * @private
    - */
    -goog.proto2.TextFormatSerializer.prototype.printField_ =
    -    function(message, field, printer) {
    -  // Skip fields not present.
    -  if (!message.has(field)) {
    -    return;
    -  }
    -
    -  var count = message.countOf(field);
    -  for (var i = 0; i < count; ++i) {
    -    // Field name.
    -    printer.append(field.getName());
    -
    -    // Field delimiter.
    -    if (field.getFieldType() == goog.proto2.FieldDescriptor.FieldType.MESSAGE ||
    -        field.getFieldType() == goog.proto2.FieldDescriptor.FieldType.GROUP) {
    -      printer.append(' {');
    -      printer.appendLine();
    -      printer.indent();
    -    } else {
    -      printer.append(': ');
    -    }
    -
    -    // Write the field value.
    -    this.printFieldValue_(message.get(field, i), field, printer);
    -
    -    // Close the field.
    -    if (field.getFieldType() == goog.proto2.FieldDescriptor.FieldType.MESSAGE ||
    -        field.getFieldType() == goog.proto2.FieldDescriptor.FieldType.GROUP) {
    -      printer.dedent();
    -      printer.append('}');
    -      printer.appendLine();
    -    } else {
    -      printer.appendLine();
    -    }
    -  }
    -};
    -
    -
    -////////////////////////////////////////////////////////////////////////////////
    -
    -
    -
    -/**
    - * Helper class used by the text format serializer for pretty-printing text.
    - * @constructor
    - * @private
    - */
    -goog.proto2.TextFormatSerializer.Printer_ = function() {
    -  /**
    -   * The current indentation count.
    -   * @type {number}
    -   * @private
    -   */
    -  this.indentation_ = 0;
    -
    -  /**
    -   * The buffer of string pieces.
    -   * @type {Array<string>}
    -   * @private
    -   */
    -  this.buffer_ = [];
    -
    -  /**
    -   * Whether indentation is required before the next append of characters.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.requiresIndentation_ = true;
    -};
    -
    -
    -/**
    - * @return {string} The contents of the printer.
    - * @override
    - */
    -goog.proto2.TextFormatSerializer.Printer_.prototype.toString = function() {
    -  return this.buffer_.join('');
    -};
    -
    -
    -/**
    - * Increases the indentation in the printer.
    - */
    -goog.proto2.TextFormatSerializer.Printer_.prototype.indent = function() {
    -  this.indentation_ += 2;
    -};
    -
    -
    -/**
    - * Decreases the indentation in the printer.
    - */
    -goog.proto2.TextFormatSerializer.Printer_.prototype.dedent = function() {
    -  this.indentation_ -= 2;
    -  goog.asserts.assert(this.indentation_ >= 0);
    -};
    -
    -
    -/**
    - * Appends the given value to the printer.
    - * @param {*} value The value to append.
    - */
    -goog.proto2.TextFormatSerializer.Printer_.prototype.append = function(value) {
    -  if (this.requiresIndentation_) {
    -    for (var i = 0; i < this.indentation_; ++i) {
    -      this.buffer_.push(' ');
    -    }
    -    this.requiresIndentation_ = false;
    -  }
    -
    -  this.buffer_.push(value.toString());
    -};
    -
    -
    -/**
    - * Appends a newline to the printer.
    - */
    -goog.proto2.TextFormatSerializer.Printer_.prototype.appendLine = function() {
    -  this.buffer_.push('\n');
    -  this.requiresIndentation_ = true;
    -};
    -
    -
    -////////////////////////////////////////////////////////////////////////////////
    -
    -
    -
    -/**
    - * Helper class for tokenizing the text format.
    - * @param {string} data The string data to tokenize.
    - * @param {boolean=} opt_ignoreWhitespace If true, whitespace tokens will not
    - *    be reported by the tokenizer.
    - * @param {boolean=} opt_ignoreComments If true, comment tokens will not be
    - *    reported by the tokenizer.
    - * @constructor
    - * @private
    - */
    -goog.proto2.TextFormatSerializer.Tokenizer_ =
    -    function(data, opt_ignoreWhitespace, opt_ignoreComments) {
    -
    -  /**
    -   * Whether to skip whitespace tokens on output.
    -   * @private {boolean}
    -   */
    -  this.ignoreWhitespace_ = !!opt_ignoreWhitespace;
    -
    -  /**
    -   * Whether to skip comment tokens on output.
    -   * @private {boolean}
    -   */
    -  this.ignoreComments_ = !!opt_ignoreComments;
    -
    -  /**
    -   * The data being tokenized.
    -   * @private {string}
    -   */
    -  this.data_ = data;
    -
    -  /**
    -   * The current index in the data.
    -   * @private {number}
    -   */
    -  this.index_ = 0;
    -
    -  /**
    -   * The data string starting at the current index.
    -   * @private {string}
    -   */
    -  this.currentData_ = data;
    -
    -  /**
    -   * The current token type.
    -   * @private {goog.proto2.TextFormatSerializer.Tokenizer_.Token}
    -   */
    -  this.current_ = {
    -    type: goog.proto2.TextFormatSerializer.Tokenizer_.TokenTypes.END,
    -    value: null
    -  };
    -};
    -
    -
    -/**
    - * @typedef {{type: goog.proto2.TextFormatSerializer.Tokenizer_.TokenTypes,
    - *            value: ?string}}
    - */
    -goog.proto2.TextFormatSerializer.Tokenizer_.Token;
    -
    -
    -/**
    - * @return {goog.proto2.TextFormatSerializer.Tokenizer_.Token} The current
    - *     token.
    - */
    -goog.proto2.TextFormatSerializer.Tokenizer_.prototype.getCurrent = function() {
    -  return this.current_;
    -};
    -
    -
    -/**
    - * An enumeration of all the token types.
    - * @enum {!RegExp}
    - */
    -goog.proto2.TextFormatSerializer.Tokenizer_.TokenTypes = {
    -  END: /---end---/,
    -  // Leading "-" to identify "-infinity"."
    -  IDENTIFIER: /^-?[a-zA-Z][a-zA-Z0-9_]*/,
    -  NUMBER: /^(0x[0-9a-f]+)|(([-])?[0-9][0-9]*(\.?[0-9]+)?(e[+-]?[0-9]+|[f])?)/,
    -  COMMENT: /^#.*/,
    -  OPEN_BRACE: /^{/,
    -  CLOSE_BRACE: /^}/,
    -  OPEN_TAG: /^</,
    -  CLOSE_TAG: /^>/,
    -  OPEN_LIST: /^\[/,
    -  CLOSE_LIST: /^\]/,
    -  STRING: new RegExp('^"([^"\\\\]|\\\\.)*"'),
    -  COLON: /^:/,
    -  COMMA: /^,/,
    -  SEMI: /^;/,
    -  WHITESPACE: /^\s/
    -};
    -
    -
    -/**
    - * Advances to the next token.
    - * @return {boolean} True if a valid token was found, false if the end was
    - *    reached or no valid token was found.
    - */
    -goog.proto2.TextFormatSerializer.Tokenizer_.prototype.next = function() {
    -  var types = goog.proto2.TextFormatSerializer.Tokenizer_.TokenTypes;
    -
    -  // Skip any whitespace if requested.
    -  while (this.nextInternal_()) {
    -    var type = this.getCurrent().type;
    -    if ((type != types.WHITESPACE && type != types.COMMENT) ||
    -        (type == types.WHITESPACE && !this.ignoreWhitespace_) ||
    -        (type == types.COMMENT && !this.ignoreComments_)) {
    -      return true;
    -    }
    -  }
    -
    -  // If we reach this point, set the current token to END.
    -  this.current_ = {
    -    type: goog.proto2.TextFormatSerializer.Tokenizer_.TokenTypes.END,
    -    value: null
    -  };
    -
    -  return false;
    -};
    -
    -
    -/**
    - * Internal method for determining the next token.
    - * @return {boolean} True if a next token was found, false otherwise.
    - * @private
    - */
    -goog.proto2.TextFormatSerializer.Tokenizer_.prototype.nextInternal_ =
    -    function() {
    -  if (this.index_ >= this.data_.length) {
    -    return false;
    -  }
    -
    -  var data = this.currentData_;
    -  var types = goog.proto2.TextFormatSerializer.Tokenizer_.TokenTypes;
    -  var next = null;
    -
    -  // Loop through each token type and try to match the beginning of the string
    -  // with the token's regular expression.
    -  goog.object.some(types, function(type, id) {
    -    if (next || type == types.END) {
    -      return false;
    -    }
    -
    -    // Note: This regular expression check is at, minimum, O(n).
    -    var info = type.exec(data);
    -    if (info && info.index == 0) {
    -      next = {
    -        type: type,
    -        value: info[0]
    -      };
    -    }
    -
    -    return !!next;
    -  });
    -
    -  // Advance the index by the length of the token.
    -  if (next) {
    -    this.current_ =
    -        /** @type {goog.proto2.TextFormatSerializer.Tokenizer_.Token} */ (next);
    -    this.index_ += next.value.length;
    -    this.currentData_ = this.currentData_.substring(next.value.length);
    -  }
    -
    -  return !!next;
    -};
    -
    -
    -////////////////////////////////////////////////////////////////////////////////
    -
    -
    -
    -/**
    - * Helper class for parsing the text format.
    - * @constructor
    - * @final
    - */
    -goog.proto2.TextFormatSerializer.Parser = function() {
    -  /**
    -   * The error during parsing, if any.
    -   * @type {?string}
    -   * @private
    -   */
    -  this.error_ = null;
    -
    -  /**
    -   * The current tokenizer.
    -   * @type {goog.proto2.TextFormatSerializer.Tokenizer_}
    -   * @private
    -   */
    -  this.tokenizer_ = null;
    -
    -  /**
    -   * Whether to ignore missing fields in the proto when parsing.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.ignoreMissingFields_ = false;
    -};
    -
    -
    -/**
    - * Parses the given data, filling the message as it goes.
    - * @param {goog.proto2.Message} message The message to fill.
    - * @param {string} data The text format data.
    - * @param {boolean=} opt_ignoreMissingFields If true, fields missing in the
    - *     proto will be ignored.
    - * @return {boolean} True on success, false on failure. On failure, the
    - *     getError method can be called to get the reason for failure.
    - */
    -goog.proto2.TextFormatSerializer.Parser.prototype.parse =
    -    function(message, data, opt_ignoreMissingFields) {
    -  this.error_ = null;
    -  this.ignoreMissingFields_ = !!opt_ignoreMissingFields;
    -  this.tokenizer_ =
    -      new goog.proto2.TextFormatSerializer.Tokenizer_(data, true, true);
    -  this.tokenizer_.next();
    -  return this.consumeMessage_(message, '');
    -};
    -
    -
    -/**
    - * @return {?string} The parse error, if any.
    - */
    -goog.proto2.TextFormatSerializer.Parser.prototype.getError = function() {
    -  return this.error_;
    -};
    -
    -
    -/**
    - * Reports a parse error.
    - * @param {string} msg The error message.
    - * @private
    - */
    -goog.proto2.TextFormatSerializer.Parser.prototype.reportError_ =
    -    function(msg) {
    -  this.error_ = msg;
    -};
    -
    -
    -/**
    - * Attempts to consume the given message.
    - * @param {goog.proto2.Message} message The message to consume and fill. If
    - *    null, then the message contents will be consumed without ever being set
    - *    to anything.
    - * @param {string} delimiter The delimiter expected at the end of the message.
    - * @return {boolean} True on success, false otherwise.
    - * @private
    - */
    -goog.proto2.TextFormatSerializer.Parser.prototype.consumeMessage_ =
    -    function(message, delimiter) {
    -  var types = goog.proto2.TextFormatSerializer.Tokenizer_.TokenTypes;
    -  while (!this.lookingAt_('>') && !this.lookingAt_('}') &&
    -         !this.lookingAtType_(types.END)) {
    -    if (!this.consumeField_(message)) { return false; }
    -  }
    -
    -  if (delimiter) {
    -    if (!this.consume_(delimiter)) { return false; }
    -  } else {
    -    if (!this.lookingAtType_(types.END)) {
    -      this.reportError_('Expected END token');
    -    }
    -  }
    -
    -  return true;
    -};
    -
    -
    -/**
    - * Attempts to consume the value of the given field.
    - * @param {goog.proto2.Message} message The parent message.
    - * @param {goog.proto2.FieldDescriptor} field The field.
    - * @return {boolean} True on success, false otherwise.
    - * @private
    - */
    -goog.proto2.TextFormatSerializer.Parser.prototype.consumeFieldValue_ =
    -    function(message, field) {
    -  var value = this.getFieldValue_(field);
    -  if (goog.isNull(value)) { return false; }
    -
    -  if (field.isRepeated()) {
    -    message.add(field, value);
    -  } else {
    -    message.set(field, value);
    -  }
    -
    -  return true;
    -};
    -
    -
    -/**
    - * Attempts to convert a string to a number.
    - * @param {string} num in hexadecimal or float format.
    - * @return {!number} The converted number or null on error.
    - * @private
    - */
    -goog.proto2.TextFormatSerializer.Parser.getNumberFromString_ =
    -    function(num) {
    -
    -  var returnValue = goog.string.contains(num, '.') ?
    -      parseFloat(num) : // num is a float.
    -      goog.string.parseInt(num); // num is an int.
    -
    -  goog.asserts.assert(!isNaN(returnValue));
    -  goog.asserts.assert(isFinite(returnValue));
    -
    -  return returnValue;
    -};
    -
    -
    -/**
    - * Parse NaN, positive infinity, or negative infinity from a string.
    - * @param {string} identifier An identifier string to check.
    - * @return {?number} Infinity, negative infinity, NaN, or null if none
    - *     of the constants could be parsed.
    - * @private
    - */
    -goog.proto2.TextFormatSerializer.Parser.parseNumericalConstant_ =
    -    function(identifier) {
    -  if (/^-?inf(?:inity)?f?$/i.test(identifier)) {
    -    return Infinity * (goog.string.startsWith(identifier, '-') ? -1 : 1);
    -  }
    -
    -  if (/^nanf?$/i.test(identifier)) {
    -    return NaN;
    -  }
    -
    -  return null;
    -};
    -
    -
    -/**
    - * Attempts to parse the given field's value from the stream.
    - * @param {goog.proto2.FieldDescriptor} field The field.
    - * @return {*} The field's value or null if none.
    - * @private
    - */
    -goog.proto2.TextFormatSerializer.Parser.prototype.getFieldValue_ =
    -    function(field) {
    -  var types = goog.proto2.TextFormatSerializer.Tokenizer_.TokenTypes;
    -  switch (field.getFieldType()) {
    -    case goog.proto2.FieldDescriptor.FieldType.DOUBLE:
    -    case goog.proto2.FieldDescriptor.FieldType.FLOAT:
    -
    -      var identifier = this.consumeIdentifier_();
    -      if (identifier) {
    -        var numericalIdentifier =
    -            goog.proto2.TextFormatSerializer.Parser.parseNumericalConstant_(
    -                identifier);
    -        // Use isDefAndNotNull since !!NaN is false.
    -        if (goog.isDefAndNotNull(numericalIdentifier)) {
    -          return numericalIdentifier;
    -        }
    -      }
    -
    -    case goog.proto2.FieldDescriptor.FieldType.INT32:
    -    case goog.proto2.FieldDescriptor.FieldType.UINT32:
    -    case goog.proto2.FieldDescriptor.FieldType.FIXED32:
    -    case goog.proto2.FieldDescriptor.FieldType.SFIXED32:
    -    case goog.proto2.FieldDescriptor.FieldType.SINT32:
    -      var num = this.consumeNumber_();
    -      if (!num) {
    -        return null;
    -      }
    -
    -      return goog.proto2.TextFormatSerializer.Parser.getNumberFromString_(num);
    -
    -    case goog.proto2.FieldDescriptor.FieldType.INT64:
    -    case goog.proto2.FieldDescriptor.FieldType.UINT64:
    -    case goog.proto2.FieldDescriptor.FieldType.FIXED64:
    -    case goog.proto2.FieldDescriptor.FieldType.SFIXED64:
    -    case goog.proto2.FieldDescriptor.FieldType.SINT64:
    -      var num = this.consumeNumber_();
    -      if (!num) {
    -        return null;
    -      }
    -
    -      if (field.getNativeType() == Number) {
    -        // 64-bit number stored as a number.
    -        return goog.proto2.TextFormatSerializer.Parser.getNumberFromString_(
    -            num);
    -      }
    -
    -      return num; // 64-bit numbers are by default stored as strings.
    -
    -    case goog.proto2.FieldDescriptor.FieldType.BOOL:
    -      var ident = this.consumeIdentifier_();
    -      if (!ident) {
    -        return null;
    -      }
    -
    -      switch (ident) {
    -        case 'true': return true;
    -        case 'false': return false;
    -        default:
    -          this.reportError_('Unknown type for bool: ' + ident);
    -          return null;
    -      }
    -
    -    case goog.proto2.FieldDescriptor.FieldType.ENUM:
    -      if (this.lookingAtType_(types.NUMBER)) {
    -        var num = this.consumeNumber_();
    -        if (!num) {
    -          return null;
    -        }
    -
    -        return goog.proto2.TextFormatSerializer.Parser.getNumberFromString_(
    -            num);
    -      } else {
    -        // Search the enum type for a matching key.
    -        var name = this.consumeIdentifier_();
    -        if (!name) {
    -          return null;
    -        }
    -
    -        var enumValue = field.getNativeType()[name];
    -        if (enumValue == null) {
    -          this.reportError_('Unknown enum value: ' + name);
    -          return null;
    -        }
    -
    -        return enumValue;
    -      }
    -
    -    case goog.proto2.FieldDescriptor.FieldType.BYTES:
    -    case goog.proto2.FieldDescriptor.FieldType.STRING:
    -      return this.consumeString_();
    -  }
    -};
    -
    -
    -/**
    - * Attempts to consume a nested message.
    - * @param {goog.proto2.Message} message The parent message.
    - * @param {goog.proto2.FieldDescriptor} field The field.
    - * @return {boolean} True on success, false otherwise.
    - * @private
    - */
    -goog.proto2.TextFormatSerializer.Parser.prototype.consumeNestedMessage_ =
    -    function(message, field) {
    -  var delimiter = '';
    -
    -  // Messages support both < > and { } as delimiters for legacy reasons.
    -  if (this.tryConsume_('<')) {
    -    delimiter = '>';
    -  } else {
    -    if (!this.consume_('{')) { return false; }
    -    delimiter = '}';
    -  }
    -
    -  var msg = field.getFieldMessageType().createMessageInstance();
    -  var result = this.consumeMessage_(msg, delimiter);
    -  if (!result) { return false; }
    -
    -  // Add the message to the parent message.
    -  if (field.isRepeated()) {
    -    message.add(field, msg);
    -  } else {
    -    message.set(field, msg);
    -  }
    -
    -  return true;
    -};
    -
    -
    -/**
    - * Attempts to consume the value of an unknown field. This method uses
    - * heuristics to try to consume just the right tokens.
    - * @return {boolean} True on success, false otherwise.
    - * @private
    - */
    -goog.proto2.TextFormatSerializer.Parser.prototype.consumeUnknownFieldValue_ =
    -    function() {
    -  // : is optional.
    -  this.tryConsume_(':');
    -
    -  // Handle form: [.. , ... , ..]
    -  if (this.tryConsume_('[')) {
    -    while (true) {
    -      this.tokenizer_.next();
    -      if (this.tryConsume_(']')) {
    -        break;
    -      }
    -      if (!this.consume_(',')) { return false; }
    -    }
    -
    -    return true;
    -  }
    -
    -  // Handle nested messages/groups.
    -  if (this.tryConsume_('<')) {
    -    return this.consumeMessage_(null /* unknown */, '>');
    -  } else if (this.tryConsume_('{')) {
    -    return this.consumeMessage_(null /* unknown */, '}');
    -  } else {
    -    // Otherwise, consume a single token for the field value.
    -    this.tokenizer_.next();
    -  }
    -
    -  return true;
    -};
    -
    -
    -/**
    - * Attempts to consume a field under a message.
    - * @param {goog.proto2.Message} message The parent message. If null, then the
    - *     field value will be consumed without being assigned to anything.
    - * @return {boolean} True on success, false otherwise.
    - * @private
    - */
    -goog.proto2.TextFormatSerializer.Parser.prototype.consumeField_ =
    -    function(message) {
    -  var fieldName = this.consumeIdentifier_();
    -  if (!fieldName) {
    -    this.reportError_('Missing field name');
    -    return false;
    -  }
    -
    -  var field = null;
    -  if (message) {
    -    field = message.getDescriptor().findFieldByName(fieldName.toString());
    -  }
    -
    -  if (field == null) {
    -    if (this.ignoreMissingFields_) {
    -      return this.consumeUnknownFieldValue_();
    -    } else {
    -      this.reportError_('Unknown field: ' + fieldName);
    -      return false;
    -    }
    -  }
    -
    -  if (field.getFieldType() == goog.proto2.FieldDescriptor.FieldType.MESSAGE ||
    -      field.getFieldType() == goog.proto2.FieldDescriptor.FieldType.GROUP) {
    -    // : is optional here.
    -    this.tryConsume_(':');
    -    if (!this.consumeNestedMessage_(message, field)) { return false; }
    -  } else {
    -    // Long Format: "someField: 123"
    -    // Short Format: "someField: [123, 456, 789]"
    -    if (!this.consume_(':')) { return false; }
    -
    -    if (field.isRepeated() && this.tryConsume_('[')) {
    -      // Short repeated format, e.g.  "foo: [1, 2, 3]"
    -      while (true) {
    -        if (!this.consumeFieldValue_(message, field)) { return false; }
    -        if (this.tryConsume_(']')) {
    -          break;
    -        }
    -        if (!this.consume_(',')) { return false; }
    -      }
    -    } else {
    -      // Normal field format.
    -      if (!this.consumeFieldValue_(message, field)) { return false; }
    -    }
    -  }
    -
    -  // For historical reasons, fields may optionally be separated by commas or
    -  // semicolons.
    -  this.tryConsume_(',') || this.tryConsume_(';');
    -  return true;
    -};
    -
    -
    -/**
    - * Attempts to consume a token with the given string value.
    - * @param {string} value The string value for the token.
    - * @return {boolean} True if the token matches and was consumed, false
    - *    otherwise.
    - * @private
    - */
    -goog.proto2.TextFormatSerializer.Parser.prototype.tryConsume_ =
    -    function(value) {
    -  if (this.lookingAt_(value)) {
    -    this.tokenizer_.next();
    -    return true;
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Consumes a token of the given type.
    - * @param {goog.proto2.TextFormatSerializer.Tokenizer_.TokenTypes} type The type
    - *     of the token to consume.
    - * @return {?string} The string value of the token or null on error.
    - * @private
    - */
    -goog.proto2.TextFormatSerializer.Parser.prototype.consumeToken_ =
    -    function(type) {
    -  if (!this.lookingAtType_(type)) {
    -    this.reportError_('Expected token type: ' + type);
    -    return null;
    -  }
    -
    -  var value = this.tokenizer_.getCurrent().value;
    -  this.tokenizer_.next();
    -  return value;
    -};
    -
    -
    -/**
    - * Consumes an IDENTIFIER token.
    - * @return {?string} The string value or null on error.
    - * @private
    - */
    -goog.proto2.TextFormatSerializer.Parser.prototype.consumeIdentifier_ =
    -    function() {
    -  var types = goog.proto2.TextFormatSerializer.Tokenizer_.TokenTypes;
    -  return this.consumeToken_(types.IDENTIFIER);
    -};
    -
    -
    -/**
    - * Consumes a NUMBER token.
    - * @return {?string} The string value or null on error.
    - * @private
    - */
    -goog.proto2.TextFormatSerializer.Parser.prototype.consumeNumber_ =
    -    function() {
    -  var types = goog.proto2.TextFormatSerializer.Tokenizer_.TokenTypes;
    -  return this.consumeToken_(types.NUMBER);
    -};
    -
    -
    -/**
    - * Consumes a STRING token. Strings may come in multiple adjacent tokens which
    - * are automatically concatenated, like in C or Python.
    - * @return {?string} The *deescaped* string value or null on error.
    - * @private
    - */
    -goog.proto2.TextFormatSerializer.Parser.prototype.consumeString_ =
    -    function() {
    -  var types = goog.proto2.TextFormatSerializer.Tokenizer_.TokenTypes;
    -  var value = this.consumeToken_(types.STRING);
    -  if (!value) {
    -    return null;
    -  }
    -
    -  var stringValue = goog.json.parse(value).toString();
    -  while (this.lookingAtType_(types.STRING)) {
    -    value = this.consumeToken_(types.STRING);
    -    stringValue += goog.json.parse(value).toString();
    -  }
    -
    -  return stringValue;
    -};
    -
    -
    -/**
    - * Consumes a token with the given value. If not found, reports an error.
    - * @param {string} value The string value expected for the token.
    - * @return {boolean} True on success, false otherwise.
    - * @private
    - */
    -goog.proto2.TextFormatSerializer.Parser.prototype.consume_ = function(value) {
    -  if (!this.tryConsume_(value)) {
    -    this.reportError_('Expected token "' + value + '"');
    -    return false;
    -  }
    -
    -  return true;
    -};
    -
    -
    -/**
    - * @param {string} value The value to check against.
    - * @return {boolean} True if the current token has the given string value.
    - * @private
    - */
    -goog.proto2.TextFormatSerializer.Parser.prototype.lookingAt_ =
    -    function(value) {
    -  return this.tokenizer_.getCurrent().value == value;
    -};
    -
    -
    -/**
    - * @param {goog.proto2.TextFormatSerializer.Tokenizer_.TokenTypes} type The
    - *     token type.
    - * @return {boolean} True if the current token has the given type.
    - * @private
    - */
    -goog.proto2.TextFormatSerializer.Parser.prototype.lookingAtType_ =
    -    function(type) {
    -  return this.tokenizer_.getCurrent().type == type;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/proto2/textformatserializer_test.html b/src/database/third_party/closure-library/closure/goog/proto2/textformatserializer_test.html
    deleted file mode 100644
    index bd8e43d276e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/proto2/textformatserializer_test.html
    +++ /dev/null
    @@ -1,21 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.proto2 - textformatserializer.js</title>
    -<script src="../base.js"></script>
    -</head>
    -<body>
    -<script>
    -goog.require('goog.proto2.TextFormatSerializerTest');
    -</script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/proto2/textformatserializer_test.js b/src/database/third_party/closure-library/closure/goog/proto2/textformatserializer_test.js
    deleted file mode 100644
    index 62e994d4962..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/proto2/textformatserializer_test.js
    +++ /dev/null
    @@ -1,807 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.proto2.TextFormatSerializer.
    - *
    - */
    -
    -/** @suppress {extraProvide} */
    -goog.provide('goog.proto2.TextFormatSerializerTest');
    -
    -goog.require('goog.proto2.ObjectSerializer');
    -goog.require('goog.proto2.TextFormatSerializer');
    -goog.require('goog.testing.jsunit');
    -goog.require('proto2.TestAllTypes');
    -
    -goog.setTestOnly('goog.proto2.TextFormatSerializerTest');
    -
    -function testSerialization() {
    -  var message = new proto2.TestAllTypes();
    -
    -  // Set the fields.
    -  // Singular.
    -  message.setOptionalInt32(101);
    -  message.setOptionalUint32(103);
    -  message.setOptionalSint32(105);
    -  message.setOptionalFixed32(107);
    -  message.setOptionalSfixed32(109);
    -  message.setOptionalInt64('102');
    -  message.setOptionalFloat(111.5);
    -  message.setOptionalDouble(112.5);
    -  message.setOptionalBool(true);
    -  message.setOptionalString('test');
    -  message.setOptionalBytes('abcd');
    -
    -  var group = new proto2.TestAllTypes.OptionalGroup();
    -  group.setA(111);
    -
    -  message.setOptionalgroup(group);
    -
    -  var nestedMessage = new proto2.TestAllTypes.NestedMessage();
    -  nestedMessage.setB(112);
    -
    -  message.setOptionalNestedMessage(nestedMessage);
    -
    -  message.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
    -
    -  // Repeated.
    -  message.addRepeatedInt32(201);
    -  message.addRepeatedInt32(202);
    -
    -  // Serialize to a simplified text format.
    -  var simplified = new goog.proto2.TextFormatSerializer().serialize(message);
    -  var expected = 'optional_int32: 101\n' +
    -      'optional_int64: 102\n' +
    -      'optional_uint32: 103\n' +
    -      'optional_sint32: 105\n' +
    -      'optional_fixed32: 107\n' +
    -      'optional_sfixed32: 109\n' +
    -      'optional_float: 111.5\n' +
    -      'optional_double: 112.5\n' +
    -      'optional_bool: true\n' +
    -      'optional_string: "test"\n' +
    -      'optional_bytes: "abcd"\n' +
    -      'optionalgroup {\n' +
    -      '  a: 111\n' +
    -      '}\n' +
    -      'optional_nested_message {\n' +
    -      '  b: 112\n' +
    -      '}\n' +
    -      'optional_nested_enum: FOO\n' +
    -      'repeated_int32: 201\n' +
    -      'repeated_int32: 202\n';
    -
    -  assertEquals(expected, simplified);
    -}
    -
    -function testSerializationOfUnknown() {
    -  var nestedUnknown = new proto2.TestAllTypes();
    -  var message = new proto2.TestAllTypes();
    -
    -  // Set the fields.
    -  // Known.
    -  message.setOptionalInt32(101);
    -  message.addRepeatedInt32(201);
    -  message.addRepeatedInt32(202);
    -
    -  nestedUnknown.addRepeatedInt32(301);
    -  nestedUnknown.addRepeatedInt32(302);
    -
    -  // Unknown.
    -  message.setUnknown(1000, 301);
    -  message.setUnknown(1001, 302);
    -  message.setUnknown(1002, 'hello world');
    -  message.setUnknown(1002, nestedUnknown);
    -
    -  nestedUnknown.setUnknown(2000, 401);
    -
    -  // Serialize.
    -  var simplified = new goog.proto2.TextFormatSerializer().serialize(message);
    -  var expected = 'optional_int32: 101\n' +
    -      'repeated_int32: 201\n' +
    -      'repeated_int32: 202\n' +
    -      '1000: 301\n' +
    -      '1001: 302\n' +
    -      '1002 {\n' +
    -      '  repeated_int32: 301\n' +
    -      '  repeated_int32: 302\n' +
    -      '  2000: 401\n' +
    -      '}\n';
    -
    -  assertEquals(expected, simplified);
    -}
    -
    -function testSerializationOfUnknownParsedFromObject() {
    -  // Construct the object-serialized representation of the message constructed
    -  // programmatically in the test above.
    -  var serialized = {
    -    1: 101,
    -    31: [201, 202],
    -    1000: 301,
    -    1001: 302,
    -    1002: {
    -      31: [301, 302],
    -      2000: 401
    -    }
    -  };
    -
    -  // Deserialize that representation into a TestAllTypes message.
    -  var objectSerializer = new goog.proto2.ObjectSerializer();
    -  var message = new proto2.TestAllTypes();
    -  objectSerializer.deserializeTo(message, serialized);
    -
    -  // Check that the text format matches what we expect.
    -  var simplified = new goog.proto2.TextFormatSerializer().serialize(message);
    -  var expected = (
    -      'optional_int32: 101\n' +
    -      'repeated_int32: 201\n' +
    -      'repeated_int32: 202\n' +
    -      '1000: 301\n' +
    -      '1001: 302\n' +
    -      '1002 {\n' +
    -      '  31: 301\n' +
    -      '  31: 302\n' +
    -      '  2000: 401\n' +
    -      '}\n'
    -      );
    -  assertEquals(expected, simplified);
    -}
    -
    -
    -/**
    - * Asserts that the given string value parses into the given set of tokens.
    - * @param {string} value The string value to parse.
    - * @param {Array<Object> | Object} tokens The tokens to check against. If not
    - *     an array, a single token is expected.
    - * @param {boolean=} opt_ignoreWhitespace Whether whitespace tokens should be
    - *     skipped by the tokenizer.
    - */
    -function assertTokens(value, tokens, opt_ignoreWhitespace) {
    -  var tokenizer = new goog.proto2.TextFormatSerializer.Tokenizer_(
    -      value, opt_ignoreWhitespace);
    -  var tokensFound = [];
    -
    -  while (tokenizer.next()) {
    -    tokensFound.push(tokenizer.getCurrent());
    -  }
    -
    -  if (goog.typeOf(tokens) != 'array') {
    -    tokens = [tokens];
    -  }
    -
    -  assertEquals(tokens.length, tokensFound.length);
    -  for (var i = 0; i < tokens.length; ++i) {
    -    assertToken(tokens[i], tokensFound[i]);
    -  }
    -}
    -
    -function assertToken(expected, found) {
    -  assertEquals(expected.type, found.type);
    -  if (expected.value) {
    -    assertEquals(expected.value, found.value);
    -  }
    -}
    -
    -function testTokenizer() {
    -  var types = goog.proto2.TextFormatSerializer.Tokenizer_.TokenTypes;
    -  assertTokens('{ 123 }', [
    -    { type: types.OPEN_BRACE },
    -    { type: types.WHITESPACE, value: ' ' },
    -    { type: types.NUMBER, value: '123' },
    -    { type: types.WHITESPACE, value: ' '},
    -    { type: types.CLOSE_BRACE }
    -  ]);
    -  // The c++ proto serializer might represent a float in exponential
    -  // notation:
    -  assertTokens('{ 1.2345e+3 }', [
    -    { type: types.OPEN_BRACE },
    -    { type: types.WHITESPACE, value: ' ' },
    -    { type: types.NUMBER, value: '1.2345e+3' },
    -    { type: types.WHITESPACE, value: ' '},
    -    { type: types.CLOSE_BRACE }
    -  ]);
    -}
    -
    -function testTokenizerExponentialFloatProblem() {
    -  var input = 'merchant: {              # blah blah\n' +
    -      '    total_price: 3.2186e+06      # 3_218_600; 3.07Mi\n' +
    -      '    taxes      : 2.17199e+06\n' +
    -      '}';
    -  var types = goog.proto2.TextFormatSerializer.Tokenizer_.TokenTypes;
    -  assertTokens(input, [
    -    { type: types.IDENTIFIER, value: 'merchant' },
    -    { type: types.COLON, value: ':' },
    -    { type: types.OPEN_BRACE, value: '{' },
    -    { type: types.COMMENT, value: '# blah blah' },
    -    { type: types.IDENTIFIER, value: 'total_price' },
    -    { type: types.COLON, value: ':' },
    -    { type: types.NUMBER, value: '3.2186e+06' },
    -    { type: types.COMMENT, value: '# 3_218_600; 3.07Mi' },
    -    { type: types.IDENTIFIER, value: 'taxes' },
    -    { type: types.COLON, value: ':' },
    -    { type: types.NUMBER, value: '2.17199e+06' },
    -    { type: types.CLOSE_BRACE, value: '}' }
    -  ],
    -  true);
    -}
    -
    -function testTokenizerNoWhitespace() {
    -  var types = goog.proto2.TextFormatSerializer.Tokenizer_.TokenTypes;
    -  assertTokens('{ "hello world" }', [
    -    { type: types.OPEN_BRACE },
    -    { type: types.STRING, value: '"hello world"' },
    -    { type: types.CLOSE_BRACE }
    -  ], true);
    -}
    -
    -
    -function assertIdentifier(identifier) {
    -  var types = goog.proto2.TextFormatSerializer.Tokenizer_.TokenTypes;
    -  assertTokens(identifier, { type: types.IDENTIFIER, value: identifier });
    -}
    -
    -function assertComment(comment) {
    -  var types = goog.proto2.TextFormatSerializer.Tokenizer_.TokenTypes;
    -  assertTokens(comment, { type: types.COMMENT, value: comment });
    -}
    -
    -function assertString(str) {
    -  var types = goog.proto2.TextFormatSerializer.Tokenizer_.TokenTypes;
    -  assertTokens(str, { type: types.STRING, value: str });
    -}
    -
    -function assertNumber(num) {
    -  num = num.toString();
    -  var types = goog.proto2.TextFormatSerializer.Tokenizer_.TokenTypes;
    -  assertTokens(num, { type: types.NUMBER, value: num });
    -}
    -
    -function testTokenizerSingleTokens() {
    -  var types = goog.proto2.TextFormatSerializer.Tokenizer_.TokenTypes;
    -  assertTokens('{', { type: types.OPEN_BRACE });
    -  assertTokens('}', { type: types.CLOSE_BRACE });
    -  assertTokens('<', { type: types.OPEN_TAG });
    -  assertTokens('>', { type: types.CLOSE_TAG });
    -  assertTokens(':', { type: types.COLON });
    -  assertTokens(',', { type: types.COMMA });
    -  assertTokens(';', { type: types.SEMI });
    -
    -  assertIdentifier('abcd');
    -  assertIdentifier('Abcd');
    -  assertIdentifier('ABcd');
    -  assertIdentifier('ABcD');
    -  assertIdentifier('a123nc');
    -  assertIdentifier('a45_bC');
    -  assertIdentifier('A45_bC');
    -
    -  assertIdentifier('inf');
    -  assertIdentifier('infinity');
    -  assertIdentifier('nan');
    -
    -  assertNumber(0);
    -  assertNumber(10);
    -  assertNumber(123);
    -  assertNumber(1234);
    -  assertNumber(123.56);
    -  assertNumber(-124);
    -  assertNumber(-1234);
    -  assertNumber(-123.56);
    -  assertNumber('123f');
    -  assertNumber('123.6f');
    -  assertNumber('-123f');
    -  assertNumber('-123.8f');
    -  assertNumber('0x1234');
    -  assertNumber('0x12ac34');
    -  assertNumber('0x49e281db686fb');
    -  // Floating point numbers might be serialized in exponential
    -  // notation:
    -  assertNumber('1.2345e+3');
    -  assertNumber('1.2345e3');
    -  assertNumber('1.2345e-2');
    -
    -  assertString('""');
    -  assertString('"hello world"');
    -  assertString('"hello # world"');
    -  assertString('"hello #\\" world"');
    -  assertString('"|"');
    -  assertString('"\\"\\""');
    -  assertString('"\\"foo\\""');
    -  assertString('"\\"foo\\" and \\"bar\\""');
    -  assertString('"foo \\"and\\" bar"');
    -
    -  assertComment('# foo bar baz');
    -  assertComment('# foo ## bar baz');
    -  assertComment('# foo "bar" baz');
    -}
    -
    -function testSerializationOfStringWithQuotes() {
    -  var nestedUnknown = new proto2.TestAllTypes();
    -  var message = new proto2.TestAllTypes();
    -  message.setOptionalString('hello "world"');
    -
    -  // Serialize.
    -  var simplified = new goog.proto2.TextFormatSerializer().serialize(message);
    -  var expected = 'optional_string: "hello \\"world\\""\n';
    -  assertEquals(expected, simplified);
    -}
    -
    -function testDeserialization() {
    -  var message = new proto2.TestAllTypes();
    -  var value = 'optional_int32: 101\n' +
    -      'repeated_int32: 201\n' +
    -      'repeated_int32: 202\n' +
    -      'optional_float: 123.4';
    -
    -  new goog.proto2.TextFormatSerializer().deserializeTo(message, value);
    -
    -  assertEquals(101, message.getOptionalInt32());
    -  assertEquals(201, message.getRepeatedInt32(0));
    -  assertEquals(202, message.getRepeatedInt32(1));
    -  assertEquals(123.4, message.getOptionalFloat());
    -}
    -
    -function testDeserializationOfList() {
    -  var message = new proto2.TestAllTypes();
    -  var value = 'optional_int32: 101\n' +
    -      'repeated_int32: [201, 202]\n' +
    -      'optional_float: 123.4';
    -
    -  new goog.proto2.TextFormatSerializer().deserializeTo(message, value);
    -
    -  assertEquals(101, message.getOptionalInt32());
    -  assertEquals(201, message.getRepeatedInt32(0));
    -  assertEquals(123.4, message.getOptionalFloat());
    -}
    -
    -function testDeserializationOfIntegerAsHexadecimalString() {
    -  var message = new proto2.TestAllTypes();
    -  var value = 'optional_int32: 0x1\n' +
    -      'optional_sint32: 0xf\n' +
    -      'optional_uint32: 0xffffffff\n' +
    -      'repeated_int32: [0x0, 0xff]\n';
    -
    -  new goog.proto2.TextFormatSerializer().deserializeTo(message, value);
    -
    -  assertEquals(1, message.getOptionalInt32());
    -  assertEquals(15, message.getOptionalSint32());
    -  assertEquals(4294967295, message.getOptionalUint32());
    -  assertEquals(0, message.getRepeatedInt32(0));
    -  assertEquals(255, message.getRepeatedInt32(1));
    -}
    -
    -function testDeserializationOfInt64AsHexadecimalString() {
    -  var message = new proto2.TestAllTypes();
    -  var value = 'optional_int64: 0xf';
    -
    -  new goog.proto2.TextFormatSerializer().deserializeTo(message, value);
    -
    -  assertEquals('0xf', message.getOptionalInt64());
    -}
    -
    -function testDeserializationOfZeroFalseAndEmptyString() {
    -  var message = new proto2.TestAllTypes();
    -  var value = 'optional_int32: 0\n' +
    -      'optional_bool: false\n' +
    -      'optional_string: ""';
    -
    -  new goog.proto2.TextFormatSerializer().deserializeTo(message, value);
    -
    -  assertEquals(0, message.getOptionalInt32());
    -  assertEquals(false, message.getOptionalBool());
    -  assertEquals('', message.getOptionalString());
    -}
    -
    -function testDeserializationOfConcatenatedString() {
    -  var message = new proto2.TestAllTypes();
    -  var value = 'optional_int32: 123\n' +
    -      'optional_string:\n' +
    -      '    "FirstLine"\n' +
    -      '    "SecondLine"\n' +
    -      'optional_float: 456.7';
    -
    -  new goog.proto2.TextFormatSerializer().deserializeTo(message, value);
    -
    -  assertEquals(123, message.getOptionalInt32());
    -  assertEquals('FirstLineSecondLine', message.getOptionalString());
    -  assertEquals(456.7, message.getOptionalFloat());
    -}
    -
    -function testDeserializationSkipComment() {
    -  var message = new proto2.TestAllTypes();
    -  var value = 'optional_int32: 101\n' +
    -      'repeated_int32: 201\n' +
    -      '# Some comment.\n' +
    -      'repeated_int32: 202\n' +
    -      'optional_float: 123.4';
    -
    -  var parser = new goog.proto2.TextFormatSerializer.Parser();
    -  assertTrue(parser.parse(message, value));
    -
    -  assertEquals(101, message.getOptionalInt32());
    -  assertEquals(201, message.getRepeatedInt32(0));
    -  assertEquals(202, message.getRepeatedInt32(1));
    -  assertEquals(123.4, message.getOptionalFloat());
    -}
    -
    -function testDeserializationSkipTrailingComment() {
    -  var message = new proto2.TestAllTypes();
    -  var value = 'optional_int32: 101\n' +
    -      'repeated_int32: 201\n' +
    -      'repeated_int32: 202  # Some trailing comment.\n' +
    -      'optional_float: 123.4';
    -
    -  var parser = new goog.proto2.TextFormatSerializer.Parser();
    -  assertTrue(parser.parse(message, value));
    -
    -  assertEquals(101, message.getOptionalInt32());
    -  assertEquals(201, message.getRepeatedInt32(0));
    -  assertEquals(202, message.getRepeatedInt32(1));
    -  assertEquals(123.4, message.getOptionalFloat());
    -}
    -
    -function testDeserializationSkipUnknown() {
    -  var message = new proto2.TestAllTypes();
    -  var value = 'optional_int32: 101\n' +
    -      'repeated_int32: 201\n' +
    -      'some_unknown: true\n' +
    -      'repeated_int32: 202\n' +
    -      'optional_float: 123.4';
    -
    -  var parser = new goog.proto2.TextFormatSerializer.Parser();
    -  assertTrue(parser.parse(message, value, true));
    -
    -  assertEquals(101, message.getOptionalInt32());
    -  assertEquals(201, message.getRepeatedInt32(0));
    -  assertEquals(202, message.getRepeatedInt32(1));
    -  assertEquals(123.4, message.getOptionalFloat());
    -}
    -
    -function testDeserializationSkipUnknownList() {
    -  var message = new proto2.TestAllTypes();
    -  var value = 'optional_int32: 101\n' +
    -      'repeated_int32: 201\n' +
    -      'some_unknown: [true, 1, 201, "hello"]\n' +
    -      'repeated_int32: 202\n' +
    -      'optional_float: 123.4';
    -
    -  var parser = new goog.proto2.TextFormatSerializer.Parser();
    -  assertTrue(parser.parse(message, value, true));
    -
    -  assertEquals(101, message.getOptionalInt32());
    -  assertEquals(201, message.getRepeatedInt32(0));
    -  assertEquals(202, message.getRepeatedInt32(1));
    -  assertEquals(123.4, message.getOptionalFloat());
    -}
    -
    -function testDeserializationSkipUnknownNested() {
    -  var message = new proto2.TestAllTypes();
    -  var value = 'optional_int32: 101\n' +
    -      'repeated_int32: 201\n' +
    -      'some_unknown: <\n' +
    -      '  a: 1\n' +
    -      '  b: 2\n' +
    -      '>\n' +
    -      'repeated_int32: 202\n' +
    -      'optional_float: 123.4';
    -
    -  var parser = new goog.proto2.TextFormatSerializer.Parser();
    -  assertTrue(parser.parse(message, value, true));
    -
    -  assertEquals(101, message.getOptionalInt32());
    -  assertEquals(201, message.getRepeatedInt32(0));
    -  assertEquals(202, message.getRepeatedInt32(1));
    -  assertEquals(123.4, message.getOptionalFloat());
    -}
    -
    -function testDeserializationSkipUnknownNestedInvalid() {
    -  var message = new proto2.TestAllTypes();
    -  var value = 'optional_int32: 101\n' +
    -      'repeated_int32: 201\n' +
    -      'some_unknown: <\n' +
    -      '  a: \n' + // Missing value.
    -      '  b: 2\n' +
    -      '>\n' +
    -      'repeated_int32: 202\n' +
    -      'optional_float: 123.4';
    -
    -  var parser = new goog.proto2.TextFormatSerializer.Parser();
    -  assertFalse(parser.parse(message, value, true));
    -}
    -
    -function testDeserializationSkipUnknownNestedInvalid2() {
    -  var message = new proto2.TestAllTypes();
    -  var value = 'optional_int32: 101\n' +
    -      'repeated_int32: 201\n' +
    -      'some_unknown: <\n' +
    -      '  a: 2\n' +
    -      '  b: 2\n' +
    -      '}\n' + // Delimiter mismatch
    -      'repeated_int32: 202\n' +
    -      'optional_float: 123.4';
    -
    -  var parser = new goog.proto2.TextFormatSerializer.Parser();
    -  assertFalse(parser.parse(message, value, true));
    -}
    -
    -
    -function testDeserializationLegacyFormat() {
    -  var message = new proto2.TestAllTypes();
    -  var value = 'optional_int32: 101,\n' +
    -      'repeated_int32: 201,\n' +
    -      'repeated_int32: 202;\n' +
    -      'optional_float: 123.4';
    -
    -  new goog.proto2.TextFormatSerializer().deserializeTo(message, value);
    -
    -  assertEquals(101, message.getOptionalInt32());
    -  assertEquals(201, message.getRepeatedInt32(0));
    -  assertEquals(202, message.getRepeatedInt32(1));
    -  assertEquals(123.4, message.getOptionalFloat());
    -}
    -
    -function testDeserializationVariedNumbers() {
    -  var message = new proto2.TestAllTypes();
    -  var value = (
    -      'repeated_int32: 23\n' +
    -      'repeated_int32: -3\n' +
    -      'repeated_int32: 0xdeadbeef\n' +
    -      'repeated_float: 123.0\n' +
    -      'repeated_float: -3.27\n' +
    -      'repeated_float: -35.5f\n'
    -      );
    -
    -  new goog.proto2.TextFormatSerializer().deserializeTo(message, value);
    -
    -  assertEquals(23, message.getRepeatedInt32(0));
    -  assertEquals(-3, message.getRepeatedInt32(1));
    -  assertEquals(3735928559, message.getRepeatedInt32(2));
    -  assertEquals(123.0, message.getRepeatedFloat(0));
    -  assertEquals(-3.27, message.getRepeatedFloat(1));
    -  assertEquals(-35.5, message.getRepeatedFloat(2));
    -}
    -
    -function testDeserializationScientificNotation() {
    -  var message = new proto2.TestAllTypes();
    -  var value = 'repeated_float: 1.1e5\n' +
    -      'repeated_float: 1.1e-5\n' +
    -      'repeated_double: 1.1e5\n' +
    -      'repeated_double: 1.1e-5\n';
    -  new goog.proto2.TextFormatSerializer().deserializeTo(message, value);
    -  assertEquals(1.1e5, message.getRepeatedFloat(0));
    -  assertEquals(1.1e-5, message.getRepeatedFloat(1));
    -  assertEquals(1.1e5, message.getRepeatedDouble(0));
    -  assertEquals(1.1e-5, message.getRepeatedDouble(1));
    -}
    -
    -function testParseNumericalConstant() {
    -  var parseNumericalConstant =
    -      goog.proto2.TextFormatSerializer.Parser.parseNumericalConstant_;
    -
    -  assertEquals(Infinity, parseNumericalConstant('inf'));
    -  assertEquals(Infinity, parseNumericalConstant('inff'));
    -  assertEquals(Infinity, parseNumericalConstant('infinity'));
    -  assertEquals(Infinity, parseNumericalConstant('infinityf'));
    -  assertEquals(Infinity, parseNumericalConstant('Infinityf'));
    -
    -  assertEquals(-Infinity, parseNumericalConstant('-inf'));
    -  assertEquals(-Infinity, parseNumericalConstant('-inff'));
    -  assertEquals(-Infinity, parseNumericalConstant('-infinity'));
    -  assertEquals(-Infinity, parseNumericalConstant('-infinityf'));
    -  assertEquals(-Infinity, parseNumericalConstant('-Infinity'));
    -
    -  assertNull(parseNumericalConstant('-infin'));
    -  assertNull(parseNumericalConstant('infin'));
    -  assertNull(parseNumericalConstant('-infinite'));
    -
    -  assertNull(parseNumericalConstant('-infin'));
    -  assertNull(parseNumericalConstant('infin'));
    -  assertNull(parseNumericalConstant('-infinite'));
    -
    -  assertTrue(isNaN(parseNumericalConstant('Nan')));
    -  assertTrue(isNaN(parseNumericalConstant('NaN')));
    -  assertTrue(isNaN(parseNumericalConstant('NAN')));
    -  assertTrue(isNaN(parseNumericalConstant('nan')));
    -  assertTrue(isNaN(parseNumericalConstant('nanf')));
    -  assertTrue(isNaN(parseNumericalConstant('NaNf')));
    -
    -  assertEquals(Number.POSITIVE_INFINITY, parseNumericalConstant('infinity'));
    -  assertEquals(Number.NEGATIVE_INFINITY, parseNumericalConstant('-inf'));
    -  assertEquals(Number.NEGATIVE_INFINITY, parseNumericalConstant('-infinity'));
    -
    -  assertNull(parseNumericalConstant('na'));
    -  assertNull(parseNumericalConstant('-nan'));
    -  assertNull(parseNumericalConstant('none'));
    -}
    -
    -function testDeserializationOfNumericalConstants() {
    -
    -  var message = new proto2.TestAllTypes();
    -  var value = (
    -      'repeated_float: inf\n' +
    -      'repeated_float: -inf\n' +
    -      'repeated_float: nan\n' +
    -      'repeated_float: 300.2\n'
    -      );
    -
    -  new goog.proto2.TextFormatSerializer().deserializeTo(message, value);
    -
    -  assertEquals(Infinity, message.getRepeatedFloat(0));
    -  assertEquals(-Infinity, message.getRepeatedFloat(1));
    -  assertTrue(isNaN(message.getRepeatedFloat(2)));
    -  assertEquals(300.2, message.getRepeatedFloat(3));
    -}
    -
    -var floatFormatCases = [{given: '1.69e+06', expect: 1.69e+06},
    -                        {given: '1.69e6', expect: 1.69e+06},
    -                        {given: '2.468e-2', expect: 0.02468}
    -                       ];
    -
    -function testGetNumberFromStringExponentialNotation() {
    -  for (var i = 0; i < floatFormatCases.length; ++i) {
    -    var thistest = floatFormatCases[i];
    -    var result = goog.proto2.TextFormatSerializer.Parser.
    -        getNumberFromString_(thistest.given);
    -    assertEquals(thistest.expect, result);
    -  }
    -}
    -
    -function testDeserializationExponentialFloat() {
    -  var parser = new goog.proto2.TextFormatSerializer.Parser();
    -  for (var i = 0; i < floatFormatCases.length; ++i) {
    -    var thistest = floatFormatCases[i];
    -    var message = new proto2.TestAllTypes();
    -    var value = 'optional_float: ' + thistest.given;
    -    assertTrue(parser.parse(message, value, true));
    -    assertEquals(thistest.expect, message.getOptionalFloat());
    -  }
    -}
    -
    -function testGetNumberFromString() {
    -  var getNumberFromString =
    -      goog.proto2.TextFormatSerializer.Parser.getNumberFromString_;
    -
    -  assertEquals(3735928559, getNumberFromString('0xdeadbeef'));
    -  assertEquals(4276215469, getNumberFromString('0xFEE1DEAD'));
    -  assertEquals(123.1, getNumberFromString('123.1'));
    -  assertEquals(123.0, getNumberFromString('123.0'));
    -  assertEquals(-29.3, getNumberFromString('-29.3f'));
    -  assertEquals(23, getNumberFromString('23'));
    -  assertEquals(-3, getNumberFromString('-3'));
    -  assertEquals(-3.27, getNumberFromString('-3.27'));
    -
    -  assertThrows(goog.partial(getNumberFromString, 'cat'));
    -  assertThrows(goog.partial(getNumberFromString, 'NaN'));
    -  assertThrows(goog.partial(getNumberFromString, 'inf'));
    -}
    -
    -function testDeserializationError() {
    -  var message = new proto2.TestAllTypes();
    -  var value = 'optional_int33: 101\n';
    -  var result =
    -      new goog.proto2.TextFormatSerializer().deserializeTo(message, value);
    -  assertEquals(result, 'Unknown field: optional_int33');
    -}
    -
    -function testNestedDeserialization() {
    -  var message = new proto2.TestAllTypes();
    -  var value = 'optional_int32: 101\n' +
    -      'optional_nested_message: {\n' +
    -      '  b: 301\n' +
    -      '}';
    -
    -  new goog.proto2.TextFormatSerializer().deserializeTo(message, value);
    -
    -  assertEquals(101, message.getOptionalInt32());
    -  assertEquals(301, message.getOptionalNestedMessage().getB());
    -}
    -
    -function testNestedDeserializationLegacyFormat() {
    -  var message = new proto2.TestAllTypes();
    -  var value = 'optional_int32: 101\n' +
    -      'optional_nested_message: <\n' +
    -      '  b: 301\n' +
    -      '>';
    -
    -  new goog.proto2.TextFormatSerializer().deserializeTo(message, value);
    -
    -  assertEquals(101, message.getOptionalInt32());
    -  assertEquals(301, message.getOptionalNestedMessage().getB());
    -}
    -
    -function testBidirectional() {
    -  var message = new proto2.TestAllTypes();
    -
    -  // Set the fields.
    -  // Singular.
    -  message.setOptionalInt32(101);
    -  message.setOptionalInt64('102');
    -  message.setOptionalUint32(103);
    -  message.setOptionalUint64('104');
    -  message.setOptionalSint32(105);
    -  message.setOptionalSint64('106');
    -  message.setOptionalFixed32(107);
    -  message.setOptionalFixed64('108');
    -  message.setOptionalSfixed32(109);
    -  message.setOptionalSfixed64('110');
    -  message.setOptionalFloat(111.5);
    -  message.setOptionalDouble(112.5);
    -  message.setOptionalBool(true);
    -  message.setOptionalString('test');
    -  message.setOptionalBytes('abcd');
    -
    -  var group = new proto2.TestAllTypes.OptionalGroup();
    -  group.setA(111);
    -
    -  message.setOptionalgroup(group);
    -
    -  var nestedMessage = new proto2.TestAllTypes.NestedMessage();
    -  nestedMessage.setB(112);
    -
    -  message.setOptionalNestedMessage(nestedMessage);
    -
    -  message.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
    -
    -  // Repeated.
    -  message.addRepeatedInt32(201);
    -  message.addRepeatedInt32(202);
    -  message.addRepeatedString('hello "world"');
    -
    -  // Serialize the message to text form.
    -  var serializer = new goog.proto2.TextFormatSerializer();
    -  var textform = serializer.serialize(message);
    -
    -  // Create a copy and deserialize into the copy.
    -  var copy = new proto2.TestAllTypes();
    -  serializer.deserializeTo(copy, textform);
    -
    -  // Assert that the messages are structurally equivalent.
    -  assertTrue(copy.equals(message));
    -}
    -
    -function testBidirectional64BitNumber() {
    -  var message = new proto2.TestAllTypes();
    -  message.setOptionalInt64Number(10000000);
    -  message.setOptionalInt64String('200000000000000000');
    -
    -  // Serialize the message to text form.
    -  var serializer = new goog.proto2.TextFormatSerializer();
    -  var textform = serializer.serialize(message);
    -
    -  // Create a copy and deserialize into the copy.
    -  var copy = new proto2.TestAllTypes();
    -  serializer.deserializeTo(copy, textform);
    -
    -  // Assert that the messages are structurally equivalent.
    -  assertTrue(copy.equals(message));
    -}
    -
    -function testUseEnumValues() {
    -  var message = new proto2.TestAllTypes();
    -  message.setOptionalNestedEnum(proto2.TestAllTypes.NestedEnum.FOO);
    -
    -  var serializer = new goog.proto2.TextFormatSerializer(false, true);
    -  var textform = serializer.serialize(message);
    -
    -  var expected = 'optional_nested_enum: 0\n';
    -
    -  assertEquals(expected, textform);
    -
    -  var deserializedMessage = new proto2.TestAllTypes();
    -  serializer.deserializeTo(deserializedMessage, textform);
    -
    -  assertEquals(
    -      proto2.TestAllTypes.NestedEnum.FOO,
    -      deserializedMessage.getOptionalNestedEnum());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/proto2/util.js b/src/database/third_party/closure-library/closure/goog/proto2/util.js
    deleted file mode 100644
    index 62c1e44dc2e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/proto2/util.js
    +++ /dev/null
    @@ -1,54 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Utility methods for Protocol Buffer 2 implementation.
    - */
    -
    -goog.provide('goog.proto2.Util');
    -
    -goog.require('goog.asserts');
    -
    -
    -/**
    - * @define {boolean} Defines a PBCHECK constant that can be turned off by
    - * clients of PB2. This for is clients that do not want assertion/checking
    - * running even in non-COMPILED builds.
    - */
    -goog.define('goog.proto2.Util.PBCHECK', !COMPILED);
    -
    -
    -/**
    - * Asserts that the given condition is true, if and only if the PBCHECK
    - * flag is on.
    - *
    - * @param {*} condition The condition to check.
    - * @param {string=} opt_message Error message in case of failure.
    - * @throws {Error} Assertion failed, the condition evaluates to false.
    - */
    -goog.proto2.Util.assert = function(condition, opt_message) {
    -  if (goog.proto2.Util.PBCHECK) {
    -    goog.asserts.assert(condition, opt_message);
    -  }
    -};
    -
    -
    -/**
    - * Returns true if debug assertions (checks) are on.
    - *
    - * @return {boolean} The value of the PBCHECK constant.
    - */
    -goog.proto2.Util.conductChecks = function() {
    -  return goog.proto2.Util.PBCHECK;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/pubsub/pubsub.js b/src/database/third_party/closure-library/closure/goog/pubsub/pubsub.js
    deleted file mode 100644
    index e7a2698ace6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/pubsub/pubsub.js
    +++ /dev/null
    @@ -1,335 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview  Topic-based publish/subscribe channel implementation.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.pubsub.PubSub');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.array');
    -
    -
    -
    -/**
    - * Topic-based publish/subscribe channel.  Maintains a map of topics to
    - * subscriptions.  When a message is published to a topic, all functions
    - * subscribed to that topic are invoked in the order they were added.
    - * Uncaught errors abort publishing.
    - *
    - * Topics may be identified by any nonempty string, <strong>except</strong>
    - * strings corresponding to native Object properties, e.g. "constructor",
    - * "toString", "hasOwnProperty", etc.
    - *
    - * @constructor
    - * @extends {goog.Disposable}
    - */
    -goog.pubsub.PubSub = function() {
    -  goog.Disposable.call(this);
    -  this.subscriptions_ = [];
    -  this.topics_ = {};
    -};
    -goog.inherits(goog.pubsub.PubSub, goog.Disposable);
    -
    -
    -/**
    - * Sparse array of subscriptions.  Each subscription is represented by a tuple
    - * comprising a topic identifier, a function, and an optional context object.
    - * Each tuple occupies three consecutive positions in the array, with the topic
    - * identifier at index n, the function at index (n + 1), the context object at
    - * index (n + 2), the next topic at index (n + 3), etc.  (This representation
    - * minimizes the number of object allocations and has been shown to be faster
    - * than an array of objects with three key-value pairs or three parallel arrays,
    - * especially on IE.)  Once a subscription is removed via {@link #unsubscribe}
    - * or {@link #unsubscribeByKey}, the three corresponding array elements are
    - * deleted, and never reused.  This means the total number of subscriptions
    - * during the lifetime of the pubsub channel is limited by the maximum length
    - * of a JavaScript array to (2^32 - 1) / 3 = 1,431,655,765 subscriptions, which
    - * should suffice for most applications.
    - *
    - * @type {!Array<?>}
    - * @private
    - */
    -goog.pubsub.PubSub.prototype.subscriptions_;
    -
    -
    -/**
    - * The next available subscription key.  Internally, this is an index into the
    - * sparse array of subscriptions.
    - *
    - * @type {number}
    - * @private
    - */
    -goog.pubsub.PubSub.prototype.key_ = 1;
    -
    -
    -/**
    - * Map of topics to arrays of subscription keys.
    - *
    - * @type {!Object<!Array<number>>}
    - * @private
    - */
    -goog.pubsub.PubSub.prototype.topics_;
    -
    -
    -/**
    - * Array of subscription keys pending removal once publishing is done.
    - *
    - * @type {Array<number>}
    - * @private
    - */
    -goog.pubsub.PubSub.prototype.pendingKeys_;
    -
    -
    -/**
    - * Lock to prevent the removal of subscriptions during publishing.  Incremented
    - * at the beginning of {@link #publish}, and decremented at the end.
    - *
    - * @type {number}
    - * @private
    - */
    -goog.pubsub.PubSub.prototype.publishDepth_ = 0;
    -
    -
    -/**
    - * Subscribes a function to a topic.  The function is invoked as a method on
    - * the given {@code opt_context} object, or in the global scope if no context
    - * is specified.  Subscribing the same function to the same topic multiple
    - * times will result in multiple function invocations while publishing.
    - * Returns a subscription key that can be used to unsubscribe the function from
    - * the topic via {@link #unsubscribeByKey}.
    - *
    - * @param {string} topic Topic to subscribe to.
    - * @param {Function} fn Function to be invoked when a message is published to
    - *     the given topic.
    - * @param {Object=} opt_context Object in whose context the function is to be
    - *     called (the global scope if none).
    - * @return {number} Subscription key.
    - */
    -goog.pubsub.PubSub.prototype.subscribe = function(topic, fn, opt_context) {
    -  var keys = this.topics_[topic];
    -  if (!keys) {
    -    // First subscription to this topic; initialize subscription key array.
    -    keys = this.topics_[topic] = [];
    -  }
    -
    -  // Push the tuple representing the subscription onto the subscription array.
    -  var key = this.key_;
    -  this.subscriptions_[key] = topic;
    -  this.subscriptions_[key + 1] = fn;
    -  this.subscriptions_[key + 2] = opt_context;
    -  this.key_ = key + 3;
    -
    -  // Push the subscription key onto the list of subscriptions for the topic.
    -  keys.push(key);
    -
    -  // Return the subscription key.
    -  return key;
    -};
    -
    -
    -/**
    - * Subscribes a single-use function to a topic.  The function is invoked as a
    - * method on the given {@code opt_context} object, or in the global scope if
    - * no context is specified, and is then unsubscribed.  Returns a subscription
    - * key that can be used to unsubscribe the function from the topic via
    - * {@link #unsubscribeByKey}.
    - *
    - * @param {string} topic Topic to subscribe to.
    - * @param {Function} fn Function to be invoked once and then unsubscribed when
    - *     a message is published to the given topic.
    - * @param {Object=} opt_context Object in whose context the function is to be
    - *     called (the global scope if none).
    - * @return {number} Subscription key.
    - */
    -goog.pubsub.PubSub.prototype.subscribeOnce = function(topic, fn, opt_context) {
    -  // Behold the power of lexical closures!
    -  var key = this.subscribe(topic, function(var_args) {
    -    fn.apply(opt_context, arguments);
    -    this.unsubscribeByKey(key);
    -  }, this);
    -  return key;
    -};
    -
    -
    -/**
    - * Unsubscribes a function from a topic.  Only deletes the first match found.
    - * Returns a Boolean indicating whether a subscription was removed.
    - *
    - * @param {string} topic Topic to unsubscribe from.
    - * @param {Function} fn Function to unsubscribe.
    - * @param {Object=} opt_context Object in whose context the function was to be
    - *     called (the global scope if none).
    - * @return {boolean} Whether a matching subscription was removed.
    - */
    -goog.pubsub.PubSub.prototype.unsubscribe = function(topic, fn, opt_context) {
    -  var keys = this.topics_[topic];
    -  if (keys) {
    -    // Find the subscription key for the given combination of topic, function,
    -    // and context object.
    -    var subscriptions = this.subscriptions_;
    -    var key = goog.array.find(keys, function(k) {
    -      return subscriptions[k + 1] == fn && subscriptions[k + 2] == opt_context;
    -    });
    -    // Zero is not a valid key.
    -    if (key) {
    -      return this.unsubscribeByKey(/** @type {number} */ (key));
    -    }
    -  }
    -
    -  return false;
    -};
    -
    -
    -/**
    - * Removes a subscription based on the key returned by {@link #subscribe}.
    - * No-op if no matching subscription is found.  Returns a Boolean indicating
    - * whether a subscription was removed.
    - *
    - * @param {number} key Subscription key.
    - * @return {boolean} Whether a matching subscription was removed.
    - */
    -goog.pubsub.PubSub.prototype.unsubscribeByKey = function(key) {
    -  if (this.publishDepth_ != 0) {
    -    // Defer removal until after publishing is complete.
    -    if (!this.pendingKeys_) {
    -      this.pendingKeys_ = [];
    -    }
    -    this.pendingKeys_.push(key);
    -    return false;
    -  }
    -
    -  var topic = this.subscriptions_[key];
    -  if (topic) {
    -    // Subscription tuple found.
    -    var keys = this.topics_[topic];
    -    if (keys) {
    -      goog.array.remove(keys, key);
    -    }
    -    delete this.subscriptions_[key];
    -    delete this.subscriptions_[key + 1];
    -    delete this.subscriptions_[key + 2];
    -  }
    -
    -  return !!topic;
    -};
    -
    -
    -/**
    - * Publishes a message to a topic.  Calls functions subscribed to the topic in
    - * the order in which they were added, passing all arguments along.  If any of
    - * the functions throws an uncaught error, publishing is aborted.
    - *
    - * @param {string} topic Topic to publish to.
    - * @param {...*} var_args Arguments that are applied to each subscription
    - *     function.
    - * @return {boolean} Whether any subscriptions were called.
    - */
    -goog.pubsub.PubSub.prototype.publish = function(topic, var_args) {
    -  var keys = this.topics_[topic];
    -  if (keys) {
    -    // We must lock subscriptions and remove them at the end, so we don't
    -    // adversely affect the performance of the common case by cloning the key
    -    // array.
    -    this.publishDepth_++;
    -
    -    // Copy var_args to a new array so they can be passed to subscribers.
    -    // Note that we can't use Array.slice or goog.array.toArray for this for
    -    // performance reasons. Using those with the arguments object will cause
    -    // deoptimization.
    -    var args = new Array(arguments.length - 1);
    -    for (var i = 1, len = arguments.length; i < len; i++) {
    -      args[i - 1] = arguments[i];
    -    }
    -
    -    // For each key in the list of subscription keys for the topic, apply the
    -    // function to the arguments in the appropriate context.  The length of the
    -    // array mush be fixed during the iteration, since subscribers may add new
    -    // subscribers during publishing.
    -    for (var i = 0, len = keys.length; i < len; i++) {
    -      var key = keys[i];
    -      this.subscriptions_[key + 1].apply(this.subscriptions_[key + 2], args);
    -    }
    -
    -    // Unlock subscriptions.
    -    this.publishDepth_--;
    -
    -    if (this.pendingKeys_ && this.publishDepth_ == 0) {
    -      var pendingKey;
    -      while ((pendingKey = this.pendingKeys_.pop())) {
    -        this.unsubscribeByKey(pendingKey);
    -      }
    -    }
    -
    -    // At least one subscriber was called.
    -    return i != 0;
    -  }
    -
    -  // No subscribers were found.
    -  return false;
    -};
    -
    -
    -/**
    - * Clears the subscription list for a topic, or all topics if unspecified.
    - * @param {string=} opt_topic Topic to clear (all topics if unspecified).
    - */
    -goog.pubsub.PubSub.prototype.clear = function(opt_topic) {
    -  if (opt_topic) {
    -    var keys = this.topics_[opt_topic];
    -    if (keys) {
    -      goog.array.forEach(keys, this.unsubscribeByKey, this);
    -      delete this.topics_[opt_topic];
    -    }
    -  } else {
    -    this.subscriptions_.length = 0;
    -    this.topics_ = {};
    -    // We don't reset key_ on purpose, because we want subscription keys to be
    -    // unique throughout the lifetime of the application.  Reusing subscription
    -    // keys could lead to subtle errors in client code.
    -  }
    -};
    -
    -
    -/**
    - * Returns the number of subscriptions to the given topic (or all topics if
    - * unspecified).
    - * @param {string=} opt_topic The topic (all topics if unspecified).
    - * @return {number} Number of subscriptions to the topic.
    - */
    -goog.pubsub.PubSub.prototype.getCount = function(opt_topic) {
    -  if (opt_topic) {
    -    var keys = this.topics_[opt_topic];
    -    return keys ? keys.length : 0;
    -  }
    -
    -  var count = 0;
    -  for (var topic in this.topics_) {
    -    count += this.getCount(topic);
    -  }
    -
    -  return count;
    -};
    -
    -
    -/** @override */
    -goog.pubsub.PubSub.prototype.disposeInternal = function() {
    -  goog.pubsub.PubSub.superClass_.disposeInternal.call(this);
    -  delete this.subscriptions_;
    -  delete this.topics_;
    -  delete this.pendingKeys_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/pubsub/pubsub_perf.html b/src/database/third_party/closure-library/closure/goog/pubsub/pubsub_perf.html
    deleted file mode 100644
    index 17f31bd8fa7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/pubsub/pubsub_perf.html
    +++ /dev/null
    @@ -1,290 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -Author:  attila@google.com (Attila Bodis)
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -  <title>Closure Performance Tests - goog.pubsub.PubSub</title>
    -  <link rel="stylesheet" href="../testing/performancetable.css" />
    -  <script src="../base.js"></script>
    -  <script>
    -    goog.require('goog.events');
    -    goog.require('goog.events.EventTarget');
    -    goog.require('goog.pubsub.PubSub');
    -    goog.require('goog.testing.PerformanceTable');
    -    goog.require('goog.testing.PerformanceTimer');
    -    goog.require('goog.testing.jsunit');
    -  </script>
    -</head>
    -<body>
    -  <h1>goog.pubsub.PubSub Performance Tests</h1>
    -  <p>
    -    <b>User-agent:</b> <script>document.write(navigator.userAgent);</script>
    -  </p>
    -  <p>
    -    Compares the performance of the event system (<code>goog.events.*</code>)
    -    with the <code>goog.pubsub.PubSub</code> class.
    -  </p>
    -  <p>
    -    The baseline test creates 1000 event targets and 1000 objects that handle
    -    events dispatched by the event targets, and has each event target dispatch
    -    2 events 5 times each.
    -  </p>
    -  <p>
    -    The single-<code>PubSub</code> test creates 1000 publishers, 1000
    -    subscribers, and a single pubsub channel.  Each subscriber subscribes to
    -    topics on the same pubsub channel.  Each publisher publishes 5 messages to
    -    2 topics each via the pubsub channel.
    -  </p>
    -  <p>
    -    The multi-<code>PubSub</code> test creates 1000 publishers that are
    -    subclasses of <code>goog.pubsub.PubSub</code> and 1000 subscribers.  Each
    -    subscriber subscribes to its own publisher.  Each publisher publishes 5
    -    messages to 2 topics each via its own pubsub channel.
    -  </p>
    -  <div id="perfTable"></div>
    -  <hr>
    -  <script>
    -    var targets, publishers, pubsubs, handlers;
    -
    -    // Number of objects to test per run.
    -    var SAMPLES_PER_RUN = 1000;
    -
    -    // The performance table & performance timer.
    -    var table, timer;
    -
    -    // Event/topic identifiers.
    -    var ACTION = 'action';
    -    var CHANGE = 'change';
    -
    -    // Number of times handlers have been called.
    -    var actionCount = 0;
    -    var changeCount = 0;
    -
    -    // Generic event handler class.
    -    function Handler() {
    -    }
    -    Handler.prototype.handleAction = function() {
    -      actionCount++;
    -    };
    -    Handler.prototype.handleChange = function() {
    -      changeCount++;
    -    };
    -
    -    // Generic publisher class that uses a global pubsub channel.
    -    function Publisher(pubsub, id) {
    -      this.pubsub = pubsub;
    -      this.id = id;
    -    }
    -    Publisher.prototype.publish = function(topic) {
    -      this.pubsub.publish(this.id + '.' + topic);
    -    };
    -
    -    // PubSub subclass; allows clients to subscribe and uses itself to publish.
    -    function PubSub() {
    -      goog.pubsub.PubSub.call(this);
    -    }
    -    goog.inherits(PubSub, goog.pubsub.PubSub);
    -
    -    // EventTarget subclass; uses goog.events.* to dispatch events.
    -    function Target() {
    -      goog.events.EventTarget.call(this);
    -    }
    -    goog.inherits(Target, goog.events.EventTarget);
    -    Target.prototype.fireEvent = function(type) {
    -      this.dispatchEvent(type);
    -    };
    -
    -    function initHandlers(count) {
    -      for (var i = 0; i < count; i++) {
    -        handlers[i] = new Handler();
    -      }
    -    }
    -
    -    function initPublishers(pubsub, count) {
    -      for (var i = 0; i < count; i++) {
    -        publishers[i] = new Publisher(pubsub, i);
    -      }
    -    }
    -
    -    function initPubSubs(count) {
    -      for (var i = 0; i < count; i++) {
    -        pubsubs[i] = new PubSub();
    -      }
    -    }
    -
    -    function initTargets(count) {
    -      for (var i = 0; i < count; i++) {
    -        targets[i] = new Target();
    -      }
    -    }
    -
    -    function createEventListeners(count) {
    -      initHandlers(count);
    -      initTargets(count);
    -      for (var i = 0; i < count; i++) {
    -        goog.events.listen(targets[i], ACTION, Handler.prototype.handleAction,
    -            false, handlers[i]);
    -        goog.events.listen(targets[i], CHANGE, Handler.prototype.handleChange,
    -            false, handlers[i]);
    -      }
    -    }
    -
    -    function createGlobalSubscriptions(pubsub, count) {
    -      initHandlers(count);
    -      initPublishers(pubsub, count);
    -      for (var i = 0; i < count; i++) {
    -        pubsub.subscribe(i + '.' + ACTION, Handler.prototype.handleAction,
    -            handlers[i]);
    -        pubsub.subscribe(i + '.' + CHANGE, Handler.prototype.handleChange,
    -            handlers[i]);
    -      }
    -    }
    -
    -    function createSubscriptions(count) {
    -      initHandlers(count);
    -      initPubSubs(count);
    -      for (var i = 0; i < count; i++) {
    -        pubsubs[i].subscribe(ACTION, Handler.prototype.handleAction,
    -            handlers[i]);
    -        pubsubs[i].subscribe(CHANGE, Handler.prototype.handleChange,
    -            handlers[i]);
    -      }
    -    }
    -
    -    function dispatchEvents(count) {
    -      for (var i = 0; i < count; i++) {
    -        for (var j = 0; j < 5; j++) {
    -          targets[i].fireEvent(ACTION);
    -          targets[i].fireEvent(CHANGE);
    -        }
    -      }
    -    }
    -
    -    function publishGlobalMessages(count) {
    -      for (var i = 0; i < count; i++) {
    -        for (var j = 0; j < 5; j++) {
    -          publishers[i].publish(ACTION);
    -          publishers[i].publish(CHANGE);
    -        }
    -      }
    -    }
    -
    -    function publishMessages(count) {
    -      for (var i = 0; i < count; i++) {
    -        for (var j = 0; j < 5; j++) {
    -          pubsubs[i].publish(ACTION);
    -          pubsubs[i].publish(CHANGE);
    -        }
    -      }
    -    }
    -
    -    function setUpPage() {
    -      timer = new goog.testing.PerformanceTimer();
    -      timer.setNumSamples(10);
    -      timer.setTimeoutInterval(9000);
    -      timer.setDiscardOutliers(true);
    -      table = new goog.testing.PerformanceTable(
    -          goog.dom.getElement('perfTable'), timer);
    -    }
    -
    -    function setUp() {
    -      actionCount = 0;
    -      changeCount = 0;
    -      handlers = [];
    -      publishers = [];
    -      pubsubs = [];
    -      targets = [];
    -    }
    -
    -    function testCreateEventListeners() {
    -      table.run(goog.partial(createEventListeners, SAMPLES_PER_RUN),
    -          '1A: Create event listeners');
    -      assertEquals(0, actionCount);
    -      assertEquals(0, changeCount);
    -    }
    -
    -    function testCreateGlobalSubscriptions() {
    -      var pubsub = new goog.pubsub.PubSub();
    -      table.run(
    -          goog.partial(createGlobalSubscriptions, pubsub, SAMPLES_PER_RUN),
    -          '1B: Create global subscriptions');
    -      assertEquals(SAMPLES_PER_RUN * timer.getNumSamples() * 2,
    -          pubsub.getCount());
    -      assertEquals(0, actionCount);
    -      assertEquals(0, changeCount);
    -      pubsub.dispose();
    -    }
    -
    -    function testCreateSubscripions() {
    -      table.run(goog.partial(createSubscriptions, SAMPLES_PER_RUN),
    -          '1C: Create subscriptions');
    -      assertEquals(0, actionCount);
    -      assertEquals(0, changeCount);
    -    }
    -
    -    function testDispatchEvents() {
    -      createEventListeners(SAMPLES_PER_RUN);
    -      table.run(goog.partial(dispatchEvents, SAMPLES_PER_RUN),
    -          '2A: Dispatch events');
    -      assertEquals(SAMPLES_PER_RUN * timer.getNumSamples() * 5, actionCount);
    -      assertEquals(SAMPLES_PER_RUN * timer.getNumSamples() * 5, changeCount);
    -    }
    -
    -    function testPublishGlobalMessages() {
    -      var pubsub = new goog.pubsub.PubSub();
    -      createGlobalSubscriptions(pubsub, SAMPLES_PER_RUN);
    -      table.run(
    -          goog.partial(publishGlobalMessages, SAMPLES_PER_RUN),
    -          '2B: Publish global messages');
    -      assertEquals(SAMPLES_PER_RUN * timer.getNumSamples() * 5, actionCount);
    -      assertEquals(SAMPLES_PER_RUN * timer.getNumSamples() * 5, changeCount);
    -      pubsub.dispose();
    -    }
    -
    -    function testPublishMessages() {
    -      createSubscriptions(SAMPLES_PER_RUN);
    -      table.run(goog.partial(publishMessages, SAMPLES_PER_RUN),
    -          '2C: Publish messages');
    -      assertEquals(SAMPLES_PER_RUN * timer.getNumSamples() * 5, actionCount);
    -      assertEquals(SAMPLES_PER_RUN * timer.getNumSamples() * 5, changeCount);
    -    }
    -
    -    function testEvents() {
    -      table.run(function() {
    -        createEventListeners(SAMPLES_PER_RUN);
    -        dispatchEvents(SAMPLES_PER_RUN);
    -      }, '3A: Events');
    -      assertEquals(SAMPLES_PER_RUN * timer.getNumSamples() * 5, actionCount);
    -      assertEquals(SAMPLES_PER_RUN * timer.getNumSamples() * 5, changeCount);
    -    }
    -
    -    function testSinglePubSub() {
    -      table.run(function() {
    -        var pubsub = new goog.pubsub.PubSub();
    -        createGlobalSubscriptions(pubsub, SAMPLES_PER_RUN);
    -        publishGlobalMessages(SAMPLES_PER_RUN);
    -        pubsub.dispose();
    -      }, '3B: Single PubSub');
    -      assertEquals(SAMPLES_PER_RUN * timer.getNumSamples() * 5, actionCount);
    -      assertEquals(SAMPLES_PER_RUN * timer.getNumSamples() * 5, changeCount);
    -    }
    -
    -    function testMultiPubSub() {
    -      table.run(function() {
    -        createSubscriptions(SAMPLES_PER_RUN);
    -        publishMessages(SAMPLES_PER_RUN);
    -      }, '3C: Multi PubSub');
    -      assertEquals(SAMPLES_PER_RUN * timer.getNumSamples() * 5, actionCount);
    -      assertEquals(SAMPLES_PER_RUN * timer.getNumSamples() * 5, changeCount);
    -    }
    -  </script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/pubsub/pubsub_test.html b/src/database/third_party/closure-library/closure/goog/pubsub/pubsub_test.html
    deleted file mode 100644
    index 95add1cf29f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/pubsub/pubsub_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -  Author: attila@google.com (Attila Bodis)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.pubsub.PubSub
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.pubsub.PubSubTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/pubsub/pubsub_test.js b/src/database/third_party/closure-library/closure/goog/pubsub/pubsub_test.js
    deleted file mode 100644
    index 191720785be..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/pubsub/pubsub_test.js
    +++ /dev/null
    @@ -1,631 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.pubsub.PubSubTest');
    -goog.setTestOnly('goog.pubsub.PubSubTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.pubsub.PubSub');
    -goog.require('goog.testing.jsunit');
    -
    -var pubsub;
    -
    -function setUp() {
    -  pubsub = new goog.pubsub.PubSub();
    -}
    -
    -function tearDown() {
    -  pubsub.dispose();
    -}
    -
    -function testConstructor() {
    -  assertNotNull('PubSub instance must not be null', pubsub);
    -  assertTrue('PubSub instance must have the expected type',
    -      pubsub instanceof goog.pubsub.PubSub);
    -}
    -
    -function testDispose() {
    -  assertFalse('PubSub instance must not have been disposed of',
    -      pubsub.isDisposed());
    -  pubsub.dispose();
    -  assertTrue('PubSub instance must have been disposed of',
    -      pubsub.isDisposed());
    -}
    -
    -function testSubscribeUnsubscribe() {
    -  function foo1() {
    -  }
    -  function bar1() {
    -  }
    -  function foo2() {
    -  }
    -  function bar2() {
    -  }
    -
    -  assertEquals('Topic "foo" must not have any subscribers', 0,
    -      pubsub.getCount('foo'));
    -  assertEquals('Topic "bar" must not have any subscribers', 0,
    -      pubsub.getCount('bar'));
    -
    -  pubsub.subscribe('foo', foo1);
    -  assertEquals('Topic "foo" must have 1 subscriber', 1,
    -      pubsub.getCount('foo'));
    -  assertEquals('Topic "bar" must not have any subscribers', 0,
    -      pubsub.getCount('bar'));
    -
    -  pubsub.subscribe('bar', bar1);
    -  assertEquals('Topic "foo" must have 1 subscriber', 1,
    -      pubsub.getCount('foo'));
    -  assertEquals('Topic "bar" must have 1 subscriber', 1,
    -      pubsub.getCount('bar'));
    -
    -  pubsub.subscribe('foo', foo2);
    -  assertEquals('Topic "foo" must have 2 subscribers', 2,
    -      pubsub.getCount('foo'));
    -  assertEquals('Topic "bar" must have 1 subscriber', 1,
    -      pubsub.getCount('bar'));
    -
    -  pubsub.subscribe('bar', bar2);
    -  assertEquals('Topic "foo" must have 2 subscribers', 2,
    -      pubsub.getCount('foo'));
    -  assertEquals('Topic "bar" must have 2 subscribers', 2,
    -      pubsub.getCount('bar'));
    -
    -  assertTrue(pubsub.unsubscribe('foo', foo1));
    -  assertEquals('Topic "foo" must have 1 subscriber', 1,
    -      pubsub.getCount('foo'));
    -  assertEquals('Topic "bar" must have 2 subscribers', 2,
    -      pubsub.getCount('bar'));
    -
    -  assertTrue(pubsub.unsubscribe('foo', foo2));
    -  assertEquals('Topic "foo" must have no subscribers', 0,
    -      pubsub.getCount('foo'));
    -  assertEquals('Topic "bar" must have 2 subscribers', 2,
    -      pubsub.getCount('bar'));
    -
    -  assertTrue(pubsub.unsubscribe('bar', bar1));
    -  assertEquals('Topic "foo" must have no subscribers', 0,
    -      pubsub.getCount('foo'));
    -  assertEquals('Topic "bar" must have 1 subscriber', 1,
    -      pubsub.getCount('bar'));
    -
    -  assertTrue(pubsub.unsubscribe('bar', bar2));
    -  assertEquals('Topic "foo" must have no subscribers', 0,
    -      pubsub.getCount('foo'));
    -  assertEquals('Topic "bar" must have no subscribers', 0,
    -      pubsub.getCount('bar'));
    -
    -  assertFalse('Unsubscribing a nonexistent topic must return false',
    -      pubsub.unsubscribe('baz', foo1));
    -
    -  assertFalse('Unsubscribing a nonexistent function must return false',
    -      pubsub.unsubscribe('foo', function() {}));
    -}
    -
    -function testSubscribeUnsubscribeWithContext() {
    -  function foo() {
    -  }
    -  function bar() {
    -  }
    -
    -  var contextA = {};
    -  var contextB = {};
    -
    -  assertEquals('Topic "X" must not have any subscribers', 0,
    -      pubsub.getCount('X'));
    -
    -  pubsub.subscribe('X', foo, contextA);
    -  assertEquals('Topic "X" must have 1 subscriber', 1,
    -      pubsub.getCount('X'));
    -
    -  pubsub.subscribe('X', bar);
    -  assertEquals('Topic "X" must have 2 subscribers', 2,
    -      pubsub.getCount('X'));
    -
    -  pubsub.subscribe('X', bar, contextB);
    -  assertEquals('Topic "X" must have 3 subscribers', 3,
    -      pubsub.getCount('X'));
    -
    -  assertFalse('Unknown function/context combination return false',
    -      pubsub.unsubscribe('X', foo, contextB));
    -
    -  assertTrue(pubsub.unsubscribe('X', foo, contextA));
    -  assertEquals('Topic "X" must have 2 subscribers', 2,
    -      pubsub.getCount('X'));
    -
    -  assertTrue(pubsub.unsubscribe('X', bar));
    -  assertEquals('Topic "X" must have 1 subscriber', 1,
    -      pubsub.getCount('X'));
    -
    -  assertTrue(pubsub.unsubscribe('X', bar, contextB));
    -  assertEquals('Topic "X" must have no subscribers', 0,
    -      pubsub.getCount('X'));
    -}
    -
    -function testSubscribeOnce() {
    -  var called, context;
    -
    -  called = false;
    -  pubsub.subscribeOnce('someTopic', function() {
    -    called = true;
    -  });
    -  assertEquals('Topic must have one subscriber', 1,
    -      pubsub.getCount('someTopic'));
    -  assertFalse('Subscriber must not have been called yet', called);
    -
    -  pubsub.publish('someTopic');
    -  assertEquals('Topic must have no subscribers', 0,
    -      pubsub.getCount('someTopic'));
    -  assertTrue('Subscriber must have been called', called);
    -
    -  context = {called: false};
    -  pubsub.subscribeOnce('someTopic', function() {
    -    this.called = true;
    -  }, context);
    -  assertEquals('Topic must have one subscriber', 1,
    -      pubsub.getCount('someTopic'));
    -  assertFalse('Subscriber must not have been called yet', context.called);
    -
    -  pubsub.publish('someTopic');
    -  assertEquals('Topic must have no subscribers', 0,
    -      pubsub.getCount('someTopic'));
    -  assertTrue('Subscriber must have been called', context.called);
    -
    -  context = {called: false, value: 0};
    -  pubsub.subscribeOnce('someTopic', function(value) {
    -    this.called = true;
    -    this.value = value;
    -  }, context);
    -  assertEquals('Topic must have one subscriber', 1,
    -      pubsub.getCount('someTopic'));
    -  assertFalse('Subscriber must not have been called yet', context.called);
    -  assertEquals('Value must have expected value', 0, context.value);
    -
    -  pubsub.publish('someTopic', 17);
    -  assertEquals('Topic must have no subscribers', 0,
    -      pubsub.getCount('someTopic'));
    -  assertTrue('Subscriber must have been called', context.called);
    -  assertEquals('Value must have been updated', 17, context.value);
    -}
    -
    -function testSubscribeOnce_boundFn() {
    -  var context = {called: false, value: 0};
    -
    -  function subscriber(value) {
    -    this.called = true;
    -    this.value = value;
    -  }
    -
    -  pubsub.subscribeOnce('someTopic', goog.bind(subscriber, context));
    -  assertEquals('Topic must have one subscriber', 1,
    -      pubsub.getCount('someTopic'));
    -  assertFalse('Subscriber must not have been called yet', context.called);
    -  assertEquals('Value must have expected value', 0, context.value);
    -
    -  pubsub.publish('someTopic', 17);
    -  assertEquals('Topic must have no subscribers', 0,
    -      pubsub.getCount('someTopic'));
    -  assertTrue('Subscriber must have been called', context.called);
    -  assertEquals('Value must have been updated', 17, context.value);
    -}
    -
    -function testSubscribeOnce_partialFn() {
    -  var called = false;
    -  var value = 0;
    -
    -  function subscriber(hasBeenCalled, newValue) {
    -    called = hasBeenCalled;
    -    value = newValue;
    -  }
    -
    -  pubsub.subscribeOnce('someTopic', goog.partial(subscriber, true));
    -  assertEquals('Topic must have one subscriber', 1,
    -      pubsub.getCount('someTopic'));
    -  assertFalse('Subscriber must not have been called yet', called);
    -  assertEquals('Value must have expected value', 0, value);
    -
    -  pubsub.publish('someTopic', 17);
    -  assertEquals('Topic must have no subscribers', 0,
    -      pubsub.getCount('someTopic'));
    -  assertTrue('Subscriber must have been called', called);
    -  assertEquals('Value must have been updated', 17, value);
    -}
    -
    -function testSelfResubscribe() {
    -  var value = null;
    -
    -  function resubscribe(iteration, newValue) {
    -    pubsub.subscribeOnce('someTopic',
    -        goog.partial(resubscribe, iteration + 1));
    -    value = newValue + ':' + iteration;
    -  }
    -
    -  pubsub.subscribeOnce('someTopic', goog.partial(resubscribe, 0));
    -  assertEquals('Topic must have 1 subscriber', 1,
    -      pubsub.getCount('someTopic'));
    -  assertNull('Value must be null', value);
    -
    -  pubsub.publish('someTopic', 'foo');
    -  assertEquals('Topic must have 1 subscriber', 1,
    -      pubsub.getCount('someTopic'));
    -  assertEquals('Pubsub must not have any pending unsubscribe keys', 0,
    -      pubsub.pendingKeys_.length);
    -  assertEquals('Value be as expected', 'foo:0', value);
    -
    -  pubsub.publish('someTopic', 'bar');
    -  assertEquals('Topic must have 1 subscriber', 1,
    -      pubsub.getCount('someTopic'));
    -  assertEquals('Pubsub must not have any pending unsubscribe keys', 0,
    -      pubsub.pendingKeys_.length);
    -  assertEquals('Value be as expected', 'bar:1', value);
    -
    -  pubsub.publish('someTopic', 'baz');
    -  assertEquals('Topic must have 1 subscriber', 1,
    -      pubsub.getCount('someTopic'));
    -  assertEquals('Pubsub must not have any pending unsubscribe keys', 0,
    -      pubsub.pendingKeys_.length);
    -  assertEquals('Value be as expected', 'baz:2', value);
    -}
    -
    -function testUnsubscribeByKey() {
    -  var key1, key2, key3;
    -
    -  key1 = pubsub.subscribe('X', function() {});
    -  key2 = pubsub.subscribe('Y', function() {});
    -
    -  assertEquals('Topic "X" must have 1 subscriber', 1,
    -      pubsub.getCount('X'));
    -  assertEquals('Topic "Y" must have 1 subscriber', 1,
    -      pubsub.getCount('Y'));
    -  assertNotEquals('Subscription keys must be distinct', key1, key2);
    -
    -  pubsub.unsubscribeByKey(key1);
    -  assertEquals('Topic "X" must have no subscribers', 0,
    -      pubsub.getCount('X'));
    -  assertEquals('Topic "Y" must have 1 subscriber', 1,
    -      pubsub.getCount('Y'));
    -
    -  key3 = pubsub.subscribe('X', function() {});
    -  assertEquals('Topic "X" must have 1 subscriber', 1,
    -      pubsub.getCount('X'));
    -  assertEquals('Topic "Y" must have 1 subscriber', 1,
    -      pubsub.getCount('Y'));
    -  assertNotEquals('Subscription keys must be distinct', key1, key3);
    -  assertNotEquals('Subscription keys must be distinct', key2, key3);
    -
    -  pubsub.unsubscribeByKey(key1); // Obsolete key; should be no-op.
    -  assertEquals('Topic "X" must have 1 subscriber', 1,
    -      pubsub.getCount('X'));
    -  assertEquals('Topic "Y" must have 1 subscriber', 1,
    -      pubsub.getCount('Y'));
    -
    -  pubsub.unsubscribeByKey(key2);
    -  assertEquals('Topic "X" must have 1 subscriber', 1,
    -      pubsub.getCount('X'));
    -  assertEquals('Topic "Y" must have no subscribers', 0,
    -      pubsub.getCount('Y'));
    -
    -  pubsub.unsubscribeByKey(key3);
    -  assertEquals('Topic "X" must have no subscribers', 0,
    -      pubsub.getCount('X'));
    -  assertEquals('Topic "Y" must have no subscribers', 0,
    -      pubsub.getCount('Y'));
    -}
    -
    -function testSubscribeUnsubscribeMultiple() {
    -  function foo() {
    -  }
    -  function bar() {
    -  }
    -
    -  var context = {};
    -
    -  assertEquals('Pubsub channel must not have any subscribers', 0,
    -      pubsub.getCount());
    -
    -  assertEquals('Topic "X" must not have any subscribers', 0,
    -      pubsub.getCount('X'));
    -  assertEquals('Topic "Y" must not have any subscribers', 0,
    -      pubsub.getCount('Y'));
    -  assertEquals('Topic "Z" must not have any subscribers', 0,
    -      pubsub.getCount('Z'));
    -
    -  goog.array.forEach(['X', 'Y', 'Z'], function(topic) {
    -    pubsub.subscribe(topic, foo);
    -  });
    -  assertEquals('Topic "X" must have 1 subscriber', 1,
    -      pubsub.getCount('X'));
    -  assertEquals('Topic "Y" must have 1 subscriber', 1,
    -      pubsub.getCount('Y'));
    -  assertEquals('Topic "Z" must have 1 subscriber', 1,
    -      pubsub.getCount('Z'));
    -
    -  goog.array.forEach(['X', 'Y', 'Z'], function(topic) {
    -    pubsub.subscribe(topic, bar, context);
    -  });
    -  assertEquals('Topic "X" must have 2 subscribers', 2,
    -      pubsub.getCount('X'));
    -  assertEquals('Topic "Y" must have 2 subscribers', 2,
    -      pubsub.getCount('Y'));
    -  assertEquals('Topic "Z" must have 2 subscribers', 2,
    -      pubsub.getCount('Z'));
    -
    -  assertEquals('Pubsub channel must have a total of 6 subscribers', 6,
    -      pubsub.getCount());
    -
    -  goog.array.forEach(['X', 'Y', 'Z'], function(topic) {
    -    pubsub.unsubscribe(topic, foo);
    -  });
    -  assertEquals('Topic "X" must have 1 subscriber', 1,
    -      pubsub.getCount('X'));
    -  assertEquals('Topic "Y" must have 1 subscriber', 1,
    -      pubsub.getCount('Y'));
    -  assertEquals('Topic "Z" must have 1 subscriber', 1,
    -      pubsub.getCount('Z'));
    -
    -  goog.array.forEach(['X', 'Y', 'Z'], function(topic) {
    -    pubsub.unsubscribe(topic, bar, context);
    -  });
    -  assertEquals('Topic "X" must not have any subscribers', 0,
    -      pubsub.getCount('X'));
    -  assertEquals('Topic "Y" must not have any subscribers', 0,
    -      pubsub.getCount('Y'));
    -  assertEquals('Topic "Z" must not have any subscribers', 0,
    -      pubsub.getCount('Z'));
    -
    -  assertEquals('Pubsub channel must not have any subscribers', 0,
    -      pubsub.getCount());
    -}
    -
    -function testPublish() {
    -  var context = {};
    -  var fooCalled = false;
    -  var barCalled = false;
    -
    -  function foo(x, y) {
    -    fooCalled = true;
    -    assertEquals('x must have expected value', 'x', x);
    -    assertEquals('y must have expected value', 'y', y);
    -  }
    -
    -  function bar(x, y) {
    -    barCalled = true;
    -    assertEquals('Context must have expected value', context, this);
    -    assertEquals('x must have expected value', 'x', x);
    -    assertEquals('y must have expected value', 'y', y);
    -  }
    -
    -  pubsub.subscribe('someTopic', foo);
    -  pubsub.subscribe('someTopic', bar, context);
    -
    -  assertTrue(pubsub.publish('someTopic', 'x', 'y'));
    -  assertTrue('foo() must have been called', fooCalled);
    -  assertTrue('bar() must have been called', barCalled);
    -
    -  fooCalled = false;
    -  barCalled = false;
    -  assertTrue(pubsub.unsubscribe('someTopic', foo));
    -
    -  assertTrue(pubsub.publish('someTopic', 'x', 'y'));
    -  assertFalse('foo() must not have been called', fooCalled);
    -  assertTrue('bar() must have been called', barCalled);
    -
    -  fooCalled = false;
    -  barCalled = false;
    -  pubsub.subscribe('differentTopic', foo);
    -
    -  assertTrue(pubsub.publish('someTopic', 'x', 'y'));
    -  assertFalse('foo() must not have been called', fooCalled);
    -  assertTrue('bar() must have been called', barCalled);
    -}
    -
    -function testPublishEmptyTopic() {
    -  var fooCalled = false;
    -  function foo() {
    -    fooCalled = true;
    -  }
    -
    -  assertFalse('Publishing to nonexistent topic must return false',
    -      pubsub.publish('someTopic'));
    -
    -  pubsub.subscribe('someTopic', foo);
    -  assertTrue('Publishing to topic with subscriber must return true',
    -      pubsub.publish('someTopic'));
    -  assertTrue('Foo must have been called', fooCalled);
    -
    -  pubsub.unsubscribe('someTopic', foo);
    -  fooCalled = false;
    -  assertFalse('Publishing to topic without subscribers must return false',
    -      pubsub.publish('someTopic'));
    -  assertFalse('Foo must nothave been called', fooCalled);
    -}
    -
    -function testSubscribeWhilePublishing() {
    -  // It's OK for a subscriber to add a new subscriber to its own topic,
    -  // but the newly added subscriber shouldn't be called until the next
    -  // publish cycle.
    -
    -  var firstCalled = false;
    -  var secondCalled = false;
    -
    -  pubsub.subscribe('someTopic', function() {
    -    pubsub.subscribe('someTopic', function() {
    -      secondCalled = true;
    -    });
    -    firstCalled = true;
    -  });
    -  assertEquals('Topic must have one subscriber', 1,
    -      pubsub.getCount('someTopic'));
    -  assertFalse('No subscriber must have been called yet',
    -      firstCalled || secondCalled);
    -
    -  pubsub.publish('someTopic');
    -  assertEquals('Topic must have two subscribers', 2,
    -      pubsub.getCount('someTopic'));
    -  assertTrue('The first subscriber must have been called',
    -      firstCalled);
    -  assertFalse('The second subscriber must not have been called yet',
    -      secondCalled);
    -
    -  pubsub.publish('someTopic');
    -  assertEquals('Topic must have three subscribers', 3,
    -      pubsub.getCount('someTopic'));
    -  assertTrue('The first subscriber must have been called',
    -      firstCalled);
    -  assertTrue('The second subscriber must also have been called',
    -      secondCalled);
    -}
    -
    -function testUnsubscribeWhilePublishing() {
    -  // It's OK for a subscriber to unsubscribe another subscriber from its
    -  // own topic, but the subscriber in question won't actually be removed
    -  // until after publishing is complete.
    -
    -  var firstCalled = false;
    -  var secondCalled = false;
    -  var thirdCalled = false;
    -
    -  function first() {
    -    assertFalse('unsubscribe() must return false during publishing',
    -        pubsub.unsubscribe('X', second));
    -    assertEquals('Topic "X" must still have 3 subscribers', 3,
    -        pubsub.getCount('X'));
    -    firstCalled = true;
    -  }
    -  pubsub.subscribe('X', first);
    -
    -  function second() {
    -    assertEquals('Topic "X" must still have 3 subscribers', 3,
    -        pubsub.getCount('X'));
    -    secondCalled = true;
    -  }
    -  pubsub.subscribe('X', second);
    -
    -  function third() {
    -    assertFalse('unsubscribe() must return false during publishing',
    -        pubsub.unsubscribe('X', first));
    -    assertEquals('Topic "X" must still have 3 subscribers', 3,
    -        pubsub.getCount('X'));
    -    thirdCalled = true;
    -  }
    -  pubsub.subscribe('X', third);
    -
    -  assertEquals('Topic "X" must have 3 subscribers', 3,
    -      pubsub.getCount('X'));
    -  assertFalse('No subscribers must have been called yet',
    -      firstCalled || secondCalled || thirdCalled);
    -
    -  assertTrue(pubsub.publish('X'));
    -  assertTrue('First function must have been called', firstCalled);
    -  assertTrue('Second function must have been called', secondCalled);
    -  assertTrue('Third function must have been called', thirdCalled);
    -  assertEquals('Topic "X" must have 1 subscriber after publishing', 1,
    -      pubsub.getCount('X'));
    -  assertEquals('PubSub must not have any subscriptions pending removal', 0,
    -      pubsub.pendingKeys_.length);
    -}
    -
    -function testUnsubscribeSelfWhilePublishing() {
    -  // It's OK for a subscriber to unsubscribe itself, but it won't actually
    -  // be removed until after publishing is complete.
    -
    -  var selfDestructCalled = false;
    -
    -  function selfDestruct() {
    -    assertFalse('unsubscribe() must return false during publishing',
    -        pubsub.unsubscribe('someTopic', arguments.callee));
    -    assertEquals('Topic must still have 1 subscriber', 1,
    -        pubsub.getCount('someTopic'));
    -    selfDestructCalled = true;
    -  }
    -
    -  pubsub.subscribe('someTopic', selfDestruct);
    -  assertEquals('Topic must have 1 subscriber', 1,
    -      pubsub.getCount('someTopic'));
    -  assertFalse('selfDestruct() must not have been called yet',
    -      selfDestructCalled);
    -
    -  pubsub.publish('someTopic');
    -  assertTrue('selfDestruct() must have been called', selfDestructCalled);
    -  assertEquals('Topic must have no subscribers after publishing', 0,
    -      pubsub.getCount('someTopic'));
    -  assertEquals('PubSub must not have any subscriptions pending removal', 0,
    -      pubsub.pendingKeys_.length);
    -}
    -
    -function testPublishReturnValue() {
    -  pubsub.subscribe('X', function() {
    -    pubsub.unsubscribe('X', arguments.callee);
    -  });
    -  assertTrue('publish() must return true even if the only subscriber ' +
    -      'removes itself during publishing', pubsub.publish('X'));
    -}
    -
    -function testNestedPublish() {
    -  var x1 = false;
    -  var x2 = false;
    -  var y1 = false;
    -  var y2 = false;
    -
    -  pubsub.subscribe('X', function() {
    -    pubsub.publish('Y');
    -    pubsub.unsubscribe('X', arguments.callee);
    -    x1 = true;
    -  });
    -
    -  pubsub.subscribe('X', function() {
    -    x2 = true;
    -  });
    -
    -  pubsub.subscribe('Y', function() {
    -    pubsub.unsubscribe('Y', arguments.callee);
    -    y1 = true;
    -  });
    -
    -  pubsub.subscribe('Y', function() {
    -    y2 = true;
    -  });
    -
    -  pubsub.publish('X');
    -
    -  assertTrue('x1 must be true', x1);
    -  assertTrue('x2 must be true', x2);
    -  assertTrue('y1 must be true', y1);
    -  assertTrue('y2 must be true', y2);
    -}
    -
    -function testClear() {
    -  function fn() {
    -  }
    -
    -  goog.array.forEach(['W', 'X', 'Y', 'Z'], function(topic) {
    -    pubsub.subscribe(topic, fn);
    -  });
    -  assertEquals('Pubsub channel must have 4 subscribers', 4,
    -      pubsub.getCount());
    -
    -  pubsub.clear('W');
    -  assertEquals('Pubsub channel must have 3 subscribers', 3,
    -      pubsub.getCount());
    -
    -  goog.array.forEach(['X', 'Y'], function(topic) {
    -    pubsub.clear(topic);
    -  });
    -  assertEquals('Pubsub channel must have 1 subscriber', 1,
    -      pubsub.getCount());
    -
    -  pubsub.clear();
    -  assertEquals('Pubsub channel must have no subscribers', 0,
    -      pubsub.getCount());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/pubsub/topicid.js b/src/database/third_party/closure-library/closure/goog/pubsub/topicid.js
    deleted file mode 100644
    index 36dcbf8e8cc..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/pubsub/topicid.js
    +++ /dev/null
    @@ -1,61 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.pubsub.TopicId');
    -
    -
    -
    -/**
    - * A templated class that is used to register {@code goog.pubsub.PubSub}
    - * subscribers.
    - *
    - * Typical usage for a publisher:
    - * <code>
    - *   /** @type {!goog.pubsub.TopicId<!zorg.State>}
    - *   zorg.TopicId.STATE_CHANGE = new goog.pubsub.TopicId(
    - *       goog.events.getUniqueId('state-change'));
    - *
    - *   // Compiler enforces that these types are correct.
    - *   pubSub.publish(zorg.TopicId.STATE_CHANGE, zorg.State.STARTED);
    - * </code>
    - *
    - * Typical usage for a subscriber:
    - * <code>
    - *   // Compiler enforces the callback parameter type.
    - *   pubSub.subscribe(zorg.TopicId.STATE_CHANGE, function(state) {
    - *     if (state == zorg.State.STARTED) {
    - *       // Handle STARTED state.
    - *     }
    - *   });
    - * </code>
    - *
    - * @param {string} topicId
    - * @template PAYLOAD
    - * @constructor
    - * @final
    - * @struct
    - */
    -goog.pubsub.TopicId = function(topicId) {
    -  /**
    -   * @const
    -   * @private
    -   */
    -  this.topicId_ = topicId;
    -};
    -
    -
    -/** @override */
    -goog.pubsub.TopicId.prototype.toString = function() {
    -  return this.topicId_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/pubsub/typedpubsub.js b/src/database/third_party/closure-library/closure/goog/pubsub/typedpubsub.js
    deleted file mode 100644
    index 957db59dea7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/pubsub/typedpubsub.js
    +++ /dev/null
    @@ -1,126 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.pubsub.TypedPubSub');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.pubsub.PubSub');
    -
    -
    -
    -/**
    - * This object is a temporary shim that provides goog.pubsub.TopicId support
    - * for goog.pubsub.PubSub.  See b/12477087 for more info.
    - * @constructor
    - * @extends {goog.Disposable}
    - */
    -goog.pubsub.TypedPubSub = function() {
    -  goog.pubsub.TypedPubSub.base(this, 'constructor');
    -
    -  this.pubSub_ = new goog.pubsub.PubSub();
    -  this.registerDisposable(this.pubSub_);
    -};
    -goog.inherits(goog.pubsub.TypedPubSub, goog.Disposable);
    -
    -
    -/**
    - * See {@code goog.pubsub.PubSub.subscribe}.
    - * @param {!goog.pubsub.TopicId<PAYLOAD>} topic Topic to subscribe to.
    - * @param {function(this:CONTEXT, PAYLOAD)} fn Function to be invoked when a
    - *     message is published to the given topic.
    - * @param {CONTEXT=} opt_context Object in whose context the function is to be
    - *     called (the global scope if none).
    - * @return {number} Subscription key.
    - * @template PAYLOAD, CONTEXT
    - */
    -goog.pubsub.TypedPubSub.prototype.subscribe = function(topic, fn, opt_context) {
    -  return this.pubSub_.subscribe(topic.toString(), fn, opt_context);
    -};
    -
    -
    -/**
    - * See {@code goog.pubsub.PubSub.subscribeOnce}.
    - * @param {!goog.pubsub.TopicId<PAYLOAD>} topic Topic to subscribe to.
    - * @param {function(this:CONTEXT, PAYLOAD)} fn Function to be invoked once and
    - *     then unsubscribed when a message is published to the given topic.
    - * @param {CONTEXT=} opt_context Object in whose context the function is to be
    - *     called (the global scope if none).
    - * @return {number} Subscription key.
    - * @template PAYLOAD, CONTEXT
    - */
    -goog.pubsub.TypedPubSub.prototype.subscribeOnce = function(
    -    topic, fn, opt_context) {
    -  return this.pubSub_.subscribeOnce(topic.toString(), fn, opt_context);
    -};
    -
    -
    -/**
    - * See {@code goog.pubsub.PubSub.unsubscribe}.
    - * @param {!goog.pubsub.TopicId<PAYLOAD>} topic Topic to unsubscribe from.
    - * @param {function(this:CONTEXT, PAYLOAD)} fn Function to unsubscribe.
    - * @param {CONTEXT=} opt_context Object in whose context the function was to be
    - *     called (the global scope if none).
    - * @return {boolean} Whether a matching subscription was removed.
    - * @template PAYLOAD, CONTEXT
    - */
    -goog.pubsub.TypedPubSub.prototype.unsubscribe = function(
    -    topic, fn, opt_context) {
    -  return this.pubSub_.unsubscribe(topic.toString(), fn, opt_context);
    -};
    -
    -
    -/**
    - * See {@code goog.pubsub.PubSub.unsubscribeByKey}.
    - * @param {number} key Subscription key.
    - * @return {boolean} Whether a matching subscription was removed.
    - */
    -goog.pubsub.TypedPubSub.prototype.unsubscribeByKey = function(key) {
    -  return this.pubSub_.unsubscribeByKey(key);
    -};
    -
    -
    -/**
    - * See {@code goog.pubsub.PubSub.publish}.
    - * @param {!goog.pubsub.TopicId<PAYLOAD>} topic Topic to publish to.
    - * @param {PAYLOAD} payload Payload passed to each subscription function.
    - * @return {boolean} Whether any subscriptions were called.
    - * @template PAYLOAD
    - */
    -goog.pubsub.TypedPubSub.prototype.publish = function(topic, payload) {
    -  return this.pubSub_.publish(topic.toString(), payload);
    -};
    -
    -
    -/**
    - * See {@code goog.pubsub.PubSub.clear}.
    - * @param {!goog.pubsub.TopicId<PAYLOAD>=} opt_topic Topic to clear (all topics
    - *     if unspecified).
    - * @template PAYLOAD
    - */
    -goog.pubsub.TypedPubSub.prototype.clear = function(opt_topic) {
    -  this.pubSub_.clear(goog.isDef(opt_topic) ? opt_topic.toString() : undefined);
    -};
    -
    -
    -/**
    - * See {@code goog.pubsub.PubSub.getCount}.
    - * @param {!goog.pubsub.TopicId<PAYLOAD>=} opt_topic The topic (all topics if
    - *     unspecified).
    - * @return {number} Number of subscriptions to the topic.
    - * @template PAYLOAD
    - */
    -goog.pubsub.TypedPubSub.prototype.getCount = function(opt_topic) {
    -  return this.pubSub_.getCount(
    -      goog.isDef(opt_topic) ? opt_topic.toString() : undefined);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/pubsub/typedpubsub_test.html b/src/database/third_party/closure-library/closure/goog/pubsub/typedpubsub_test.html
    deleted file mode 100644
    index 0f517ffd0a7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/pubsub/typedpubsub_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.pubsub.TypedPubSub
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.pubsub.TypedPubSubTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/pubsub/typedpubsub_test.js b/src/database/third_party/closure-library/closure/goog/pubsub/typedpubsub_test.js
    deleted file mode 100644
    index ca693257623..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/pubsub/typedpubsub_test.js
    +++ /dev/null
    @@ -1,663 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.pubsub.TypedPubSubTest');
    -goog.setTestOnly('goog.pubsub.TypedPubSubTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.pubsub.TopicId');
    -goog.require('goog.pubsub.TypedPubSub');
    -goog.require('goog.testing.jsunit');
    -
    -var pubsub;
    -
    -function setUp() {
    -  pubsub = new goog.pubsub.TypedPubSub();
    -}
    -
    -function tearDown() {
    -  pubsub.dispose();
    -}
    -
    -function testConstructor() {
    -  assertNotNull('PubSub instance must not be null', pubsub);
    -  assertTrue('PubSub instance must have the expected type',
    -      pubsub instanceof goog.pubsub.TypedPubSub);
    -}
    -
    -function testDispose() {
    -  assertFalse('PubSub instance must not have been disposed of',
    -      pubsub.isDisposed());
    -  pubsub.dispose();
    -  assertTrue('PubSub instance must have been disposed of',
    -      pubsub.isDisposed());
    -}
    -
    -function testSubscribeUnsubscribe() {
    -  function foo1() {
    -  }
    -  function bar1() {
    -  }
    -  function foo2() {
    -  }
    -  function bar2() {
    -  }
    -
    -  /** const */ var FOO = new goog.pubsub.TopicId('foo');
    -  /** const */ var BAR = new goog.pubsub.TopicId('bar');
    -  /** const */ var BAZ = new goog.pubsub.TopicId('baz');
    -
    -  assertEquals('Topic "foo" must not have any subscribers', 0,
    -      pubsub.getCount(FOO));
    -  assertEquals('Topic "bar" must not have any subscribers', 0,
    -      pubsub.getCount(BAR));
    -
    -  pubsub.subscribe(FOO, foo1);
    -  assertEquals('Topic "foo" must have 1 subscriber', 1,
    -      pubsub.getCount(FOO));
    -  assertEquals('Topic "bar" must not have any subscribers', 0,
    -      pubsub.getCount(BAR));
    -
    -  pubsub.subscribe(BAR, bar1);
    -  assertEquals('Topic "foo" must have 1 subscriber', 1,
    -      pubsub.getCount(FOO));
    -  assertEquals('Topic "bar" must have 1 subscriber', 1,
    -      pubsub.getCount(BAR));
    -
    -  pubsub.subscribe(FOO, foo2);
    -  assertEquals('Topic "foo" must have 2 subscribers', 2,
    -      pubsub.getCount(FOO));
    -  assertEquals('Topic "bar" must have 1 subscriber', 1,
    -      pubsub.getCount(BAR));
    -
    -  pubsub.subscribe(BAR, bar2);
    -  assertEquals('Topic "foo" must have 2 subscribers', 2,
    -      pubsub.getCount(FOO));
    -  assertEquals('Topic "bar" must have 2 subscribers', 2,
    -      pubsub.getCount(BAR));
    -
    -  assertTrue(pubsub.unsubscribe(FOO, foo1));
    -  assertEquals('Topic "foo" must have 1 subscriber', 1,
    -      pubsub.getCount(FOO));
    -  assertEquals('Topic "bar" must have 2 subscribers', 2,
    -      pubsub.getCount(BAR));
    -
    -  assertTrue(pubsub.unsubscribe(FOO, foo2));
    -  assertEquals('Topic "foo" must have no subscribers', 0,
    -      pubsub.getCount(FOO));
    -  assertEquals('Topic "bar" must have 2 subscribers', 2,
    -      pubsub.getCount(BAR));
    -
    -  assertTrue(pubsub.unsubscribe(BAR, bar1));
    -  assertEquals('Topic "foo" must have no subscribers', 0,
    -      pubsub.getCount(FOO));
    -  assertEquals('Topic "bar" must have 1 subscriber', 1,
    -      pubsub.getCount(BAR));
    -
    -  assertTrue(pubsub.unsubscribe(BAR, bar2));
    -  assertEquals('Topic "foo" must have no subscribers', 0,
    -      pubsub.getCount(FOO));
    -  assertEquals('Topic "bar" must have no subscribers', 0,
    -      pubsub.getCount(BAR));
    -
    -  assertFalse('Unsubscribing a nonexistent topic must return false',
    -      pubsub.unsubscribe(BAZ, foo1));
    -
    -  assertFalse('Unsubscribing a nonexistent function must return false',
    -      pubsub.unsubscribe(FOO, function() {}));
    -}
    -
    -function testSubscribeUnsubscribeWithContext() {
    -  function foo() {
    -  }
    -  function bar() {
    -  }
    -
    -  var contextA = {};
    -  var contextB = {};
    -
    -  /** const */ var TOPIC_X = new goog.pubsub.TopicId('X');
    -
    -  assertEquals('Topic "X" must not have any subscribers', 0,
    -      pubsub.getCount(TOPIC_X));
    -
    -  pubsub.subscribe(TOPIC_X, foo, contextA);
    -  assertEquals('Topic "X" must have 1 subscriber', 1,
    -      pubsub.getCount(TOPIC_X));
    -
    -  pubsub.subscribe(TOPIC_X, bar);
    -  assertEquals('Topic "X" must have 2 subscribers', 2,
    -      pubsub.getCount(TOPIC_X));
    -
    -  pubsub.subscribe(TOPIC_X, bar, contextB);
    -  assertEquals('Topic "X" must have 3 subscribers', 3,
    -      pubsub.getCount(TOPIC_X));
    -
    -  assertFalse('Unknown function/context combination return false',
    -      pubsub.unsubscribe(TOPIC_X, foo, contextB));
    -
    -  assertTrue(pubsub.unsubscribe(TOPIC_X, foo, contextA));
    -  assertEquals('Topic "X" must have 2 subscribers', 2,
    -      pubsub.getCount(TOPIC_X));
    -
    -  assertTrue(pubsub.unsubscribe(TOPIC_X, bar));
    -  assertEquals('Topic "X" must have 1 subscriber', 1,
    -      pubsub.getCount(TOPIC_X));
    -
    -  assertTrue(pubsub.unsubscribe(TOPIC_X, bar, contextB));
    -  assertEquals('Topic "X" must have no subscribers', 0,
    -      pubsub.getCount(TOPIC_X));
    -}
    -
    -function testSubscribeOnce() {
    -  var called, context;
    -
    -  /** @const */ SOME_TOPIC = new goog.pubsub.TopicId('someTopic');
    -
    -  called = false;
    -  pubsub.subscribeOnce(SOME_TOPIC, function() {
    -    called = true;
    -  });
    -  assertEquals('Topic must have one subscriber', 1,
    -      pubsub.getCount(SOME_TOPIC));
    -  assertFalse('Subscriber must not have been called yet', called);
    -
    -  pubsub.publish(SOME_TOPIC);
    -  assertEquals('Topic must have no subscribers', 0,
    -      pubsub.getCount(SOME_TOPIC));
    -  assertTrue('Subscriber must have been called', called);
    -
    -  context = {called: false};
    -  pubsub.subscribeOnce(SOME_TOPIC, function() {
    -    this.called = true;
    -  }, context);
    -  assertEquals('Topic must have one subscriber', 1,
    -      pubsub.getCount(SOME_TOPIC));
    -  assertFalse('Subscriber must not have been called yet', context.called);
    -
    -  pubsub.publish(SOME_TOPIC);
    -  assertEquals('Topic must have no subscribers', 0,
    -      pubsub.getCount(SOME_TOPIC));
    -  assertTrue('Subscriber must have been called', context.called);
    -
    -  context = {called: false, value: 0};
    -  pubsub.subscribeOnce(SOME_TOPIC, function(value) {
    -    this.called = true;
    -    this.value = value;
    -  }, context);
    -  assertEquals('Topic must have one subscriber', 1,
    -      pubsub.getCount(SOME_TOPIC));
    -  assertFalse('Subscriber must not have been called yet', context.called);
    -  assertEquals('Value must have expected value', 0, context.value);
    -
    -  pubsub.publish(SOME_TOPIC, 17);
    -  assertEquals('Topic must have no subscribers', 0,
    -      pubsub.getCount(SOME_TOPIC));
    -  assertTrue('Subscriber must have been called', context.called);
    -  assertEquals('Value must have been updated', 17, context.value);
    -}
    -
    -function testSubscribeOnce_boundFn() {
    -  var context = {called: false, value: 0};
    -
    -  /** @const */ SOME_TOPIC = new goog.pubsub.TopicId('someTopic');
    -
    -  function subscriber(value) {
    -    this.called = true;
    -    this.value = value;
    -  }
    -
    -  pubsub.subscribeOnce(SOME_TOPIC, goog.bind(subscriber, context));
    -  assertEquals('Topic must have one subscriber', 1,
    -      pubsub.getCount(SOME_TOPIC));
    -  assertFalse('Subscriber must not have been called yet', context.called);
    -  assertEquals('Value must have expected value', 0, context.value);
    -
    -  pubsub.publish(SOME_TOPIC, 17);
    -  assertEquals('Topic must have no subscribers', 0,
    -      pubsub.getCount(SOME_TOPIC));
    -  assertTrue('Subscriber must have been called', context.called);
    -  assertEquals('Value must have been updated', 17, context.value);
    -}
    -
    -function testSubscribeOnce_partialFn() {
    -  var called = false;
    -  var value = 0;
    -
    -  /** @const */ SOME_TOPIC = new goog.pubsub.TopicId('someTopic');
    -
    -  function subscriber(hasBeenCalled, newValue) {
    -    called = hasBeenCalled;
    -    value = newValue;
    -  }
    -
    -  pubsub.subscribeOnce(SOME_TOPIC, goog.partial(subscriber, true));
    -  assertEquals('Topic must have one subscriber', 1,
    -      pubsub.getCount(SOME_TOPIC));
    -  assertFalse('Subscriber must not have been called yet', called);
    -  assertEquals('Value must have expected value', 0, value);
    -
    -  pubsub.publish(SOME_TOPIC, 17);
    -  assertEquals('Topic must have no subscribers', 0,
    -      pubsub.getCount(SOME_TOPIC));
    -  assertTrue('Subscriber must have been called', called);
    -  assertEquals('Value must have been updated', 17, value);
    -}
    -
    -function testSelfResubscribe() {
    -  var value = null;
    -
    -  /** @const */ SOME_TOPIC = new goog.pubsub.TopicId('someTopic');
    -
    -  function resubscribe(iteration, newValue) {
    -    pubsub.subscribeOnce(SOME_TOPIC,
    -        goog.partial(resubscribe, iteration + 1));
    -    value = newValue + ':' + iteration;
    -  }
    -
    -  pubsub.subscribeOnce(SOME_TOPIC, goog.partial(resubscribe, 0));
    -  assertEquals('Topic must have 1 subscriber', 1,
    -      pubsub.getCount(SOME_TOPIC));
    -  assertNull('Value must be null', value);
    -
    -  pubsub.publish(SOME_TOPIC, 'foo');
    -  assertEquals('Topic must have 1 subscriber', 1,
    -      pubsub.getCount(SOME_TOPIC));
    -  assertEquals('Value be as expected', 'foo:0', value);
    -
    -  pubsub.publish(SOME_TOPIC, 'bar');
    -  assertEquals('Topic must have 1 subscriber', 1,
    -      pubsub.getCount(SOME_TOPIC));
    -  assertEquals('Value be as expected', 'bar:1', value);
    -
    -  pubsub.publish(SOME_TOPIC, 'baz');
    -  assertEquals('Topic must have 1 subscriber', 1,
    -      pubsub.getCount(SOME_TOPIC));
    -  assertEquals('Value be as expected', 'baz:2', value);
    -}
    -
    -function testUnsubscribeByKey() {
    -  var key1, key2, key3;
    -
    -  /** const */ var TOPIC_X = new goog.pubsub.TopicId('X');
    -  /** const */ var TOPIC_Y = new goog.pubsub.TopicId('Y');
    -
    -  key1 = pubsub.subscribe(TOPIC_X, function() {});
    -  key2 = pubsub.subscribe(TOPIC_Y, function() {});
    -
    -  assertEquals('Topic "X" must have 1 subscriber', 1,
    -      pubsub.getCount(TOPIC_X));
    -  assertEquals('Topic "Y" must have 1 subscriber', 1,
    -      pubsub.getCount(TOPIC_Y));
    -  assertNotEquals('Subscription keys must be distinct', key1, key2);
    -
    -  pubsub.unsubscribeByKey(key1);
    -  assertEquals('Topic "X" must have no subscribers', 0,
    -      pubsub.getCount(TOPIC_X));
    -  assertEquals('Topic "Y" must have 1 subscriber', 1,
    -      pubsub.getCount(TOPIC_Y));
    -
    -  key3 = pubsub.subscribe(TOPIC_X, function() {});
    -  assertEquals('Topic "X" must have 1 subscriber', 1,
    -      pubsub.getCount(TOPIC_X));
    -  assertEquals('Topic "Y" must have 1 subscriber', 1,
    -      pubsub.getCount(TOPIC_Y));
    -  assertNotEquals('Subscription keys must be distinct', key1, key3);
    -  assertNotEquals('Subscription keys must be distinct', key2, key3);
    -
    -  pubsub.unsubscribeByKey(key1); // Obsolete key; should be no-op.
    -  assertEquals('Topic "X" must have 1 subscriber', 1,
    -      pubsub.getCount(TOPIC_X));
    -  assertEquals('Topic "Y" must have 1 subscriber', 1,
    -      pubsub.getCount(TOPIC_Y));
    -
    -  pubsub.unsubscribeByKey(key2);
    -  assertEquals('Topic "X" must have 1 subscriber', 1,
    -      pubsub.getCount(TOPIC_X));
    -  assertEquals('Topic "Y" must have no subscribers', 0,
    -      pubsub.getCount(TOPIC_Y));
    -
    -  pubsub.unsubscribeByKey(key3);
    -  assertEquals('Topic "X" must have no subscribers', 0,
    -      pubsub.getCount(TOPIC_X));
    -  assertEquals('Topic "Y" must have no subscribers', 0,
    -      pubsub.getCount(TOPIC_Y));
    -}
    -
    -function testSubscribeUnsubscribeMultiple() {
    -  function foo() {
    -  }
    -  function bar() {
    -  }
    -
    -  var context = {};
    -
    -  /** const */ var TOPIC_X = new goog.pubsub.TopicId('X');
    -  /** const */ var TOPIC_Y = new goog.pubsub.TopicId('Y');
    -  /** const */ var TOPIC_Z = new goog.pubsub.TopicId('Z');
    -
    -  assertEquals('Pubsub channel must not have any subscribers', 0,
    -      pubsub.getCount());
    -
    -  assertEquals('Topic "X" must not have any subscribers', 0,
    -      pubsub.getCount(TOPIC_X));
    -  assertEquals('Topic "Y" must not have any subscribers', 0,
    -      pubsub.getCount(TOPIC_Y));
    -  assertEquals('Topic "Z" must not have any subscribers', 0,
    -      pubsub.getCount(TOPIC_Z));
    -
    -  goog.array.forEach([TOPIC_X, TOPIC_Y, TOPIC_Z], function(topic) {
    -    pubsub.subscribe(topic, foo);
    -  });
    -  assertEquals('Topic "X" must have 1 subscriber', 1,
    -      pubsub.getCount(TOPIC_X));
    -  assertEquals('Topic "Y" must have 1 subscriber', 1,
    -      pubsub.getCount(TOPIC_Y));
    -  assertEquals('Topic "Z" must have 1 subscriber', 1,
    -      pubsub.getCount(TOPIC_Z));
    -
    -  goog.array.forEach([TOPIC_X, TOPIC_Y, TOPIC_Z], function(topic) {
    -    pubsub.subscribe(topic, bar, context);
    -  });
    -  assertEquals('Topic "X" must have 2 subscribers', 2,
    -      pubsub.getCount(TOPIC_X));
    -  assertEquals('Topic "Y" must have 2 subscribers', 2,
    -      pubsub.getCount(TOPIC_Y));
    -  assertEquals('Topic "Z" must have 2 subscribers', 2,
    -      pubsub.getCount(TOPIC_Z));
    -
    -  assertEquals('Pubsub channel must have a total of 6 subscribers', 6,
    -      pubsub.getCount());
    -
    -  goog.array.forEach([TOPIC_X, TOPIC_Y, TOPIC_Z], function(topic) {
    -    pubsub.unsubscribe(topic, foo);
    -  });
    -  assertEquals('Topic "X" must have 1 subscriber', 1,
    -      pubsub.getCount(TOPIC_X));
    -  assertEquals('Topic "Y" must have 1 subscriber', 1,
    -      pubsub.getCount(TOPIC_Y));
    -  assertEquals('Topic "Z" must have 1 subscriber', 1,
    -      pubsub.getCount(TOPIC_Z));
    -
    -  goog.array.forEach([TOPIC_X, TOPIC_Y, TOPIC_Z], function(topic) {
    -    pubsub.unsubscribe(topic, bar, context);
    -  });
    -  assertEquals('Topic "X" must not have any subscribers', 0,
    -      pubsub.getCount(TOPIC_X));
    -  assertEquals('Topic "Y" must not have any subscribers', 0,
    -      pubsub.getCount(TOPIC_Y));
    -  assertEquals('Topic "Z" must not have any subscribers', 0,
    -      pubsub.getCount(TOPIC_Z));
    -
    -  assertEquals('Pubsub channel must not have any subscribers', 0,
    -      pubsub.getCount());
    -}
    -
    -function testPublish() {
    -  var context = {};
    -  var fooCalled = false;
    -  var barCalled = false;
    -
    -  /** @const */ SOME_TOPIC = new goog.pubsub.TopicId('someTopic');
    -
    -  function foo(record) {
    -    fooCalled = true;
    -    assertEquals('x must have expected value', 'x', record.x);
    -    assertEquals('y must have expected value', 'y', record.y);
    -  }
    -
    -  function bar(record) {
    -    barCalled = true;
    -    assertEquals('Context must have expected value', context, this);
    -    assertEquals('x must have expected value', 'x', record.x);
    -    assertEquals('y must have expected value', 'y', record.y);
    -  }
    -
    -  pubsub.subscribe(SOME_TOPIC, foo);
    -  pubsub.subscribe(SOME_TOPIC, bar, context);
    -
    -  assertTrue(pubsub.publish(SOME_TOPIC, {x: 'x', y: 'y'}));
    -  assertTrue('foo() must have been called', fooCalled);
    -  assertTrue('bar() must have been called', barCalled);
    -
    -  fooCalled = false;
    -  barCalled = false;
    -  assertTrue(pubsub.unsubscribe(SOME_TOPIC, foo));
    -
    -  assertTrue(pubsub.publish(SOME_TOPIC, {x: 'x', y: 'y'}));
    -  assertFalse('foo() must not have been called', fooCalled);
    -  assertTrue('bar() must have been called', barCalled);
    -
    -  fooCalled = false;
    -  barCalled = false;
    -  pubsub.subscribe('differentTopic', foo);
    -
    -  assertTrue(pubsub.publish(SOME_TOPIC, {x: 'x', y: 'y'}));
    -  assertFalse('foo() must not have been called', fooCalled);
    -  assertTrue('bar() must have been called', barCalled);
    -}
    -
    -function testPublishEmptyTopic() {
    -  var fooCalled = false;
    -  function foo() {
    -    fooCalled = true;
    -  }
    -
    -  /** @const */ SOME_TOPIC = new goog.pubsub.TopicId('someTopic');
    -
    -  assertFalse('Publishing to nonexistent topic must return false',
    -      pubsub.publish(SOME_TOPIC));
    -
    -  pubsub.subscribe(SOME_TOPIC, foo);
    -  assertTrue('Publishing to topic with subscriber must return true',
    -      pubsub.publish(SOME_TOPIC));
    -  assertTrue('Foo must have been called', fooCalled);
    -
    -  pubsub.unsubscribe(SOME_TOPIC, foo);
    -  fooCalled = false;
    -  assertFalse('Publishing to topic without subscribers must return false',
    -      pubsub.publish(SOME_TOPIC));
    -  assertFalse('Foo must nothave been called', fooCalled);
    -}
    -
    -function testSubscribeWhilePublishing() {
    -  // It's OK for a subscriber to add a new subscriber to its own topic,
    -  // but the newly added subscriber shouldn't be called until the next
    -  // publish cycle.
    -
    -  var firstCalled = false;
    -  var secondCalled = false;
    -
    -  /** @const */ SOME_TOPIC = new goog.pubsub.TopicId('someTopic');
    -
    -  pubsub.subscribe(SOME_TOPIC, function() {
    -    pubsub.subscribe(SOME_TOPIC, function() {
    -      secondCalled = true;
    -    });
    -    firstCalled = true;
    -  });
    -  assertEquals('Topic must have one subscriber', 1,
    -      pubsub.getCount(SOME_TOPIC));
    -  assertFalse('No subscriber must have been called yet',
    -      firstCalled || secondCalled);
    -
    -  pubsub.publish(SOME_TOPIC);
    -  assertEquals('Topic must have two subscribers', 2,
    -      pubsub.getCount(SOME_TOPIC));
    -  assertTrue('The first subscriber must have been called',
    -      firstCalled);
    -  assertFalse('The second subscriber must not have been called yet',
    -      secondCalled);
    -
    -  pubsub.publish(SOME_TOPIC);
    -  assertEquals('Topic must have three subscribers', 3,
    -      pubsub.getCount(SOME_TOPIC));
    -  assertTrue('The first subscriber must have been called',
    -      firstCalled);
    -  assertTrue('The second subscriber must also have been called',
    -      secondCalled);
    -}
    -
    -function testUnsubscribeWhilePublishing() {
    -  // It's OK for a subscriber to unsubscribe another subscriber from its
    -  // own topic, but the subscriber in question won't actually be removed
    -  // until after publishing is complete.
    -
    -  var firstCalled = false;
    -  var secondCalled = false;
    -  var thirdCalled = false;
    -
    -  /** const */ var TOPIC_X = new goog.pubsub.TopicId('X');
    -
    -  function first() {
    -    assertFalse('unsubscribe() must return false during publishing',
    -        pubsub.unsubscribe(TOPIC_X, second));
    -    assertEquals('Topic "X" must still have 3 subscribers', 3,
    -        pubsub.getCount(TOPIC_X));
    -    firstCalled = true;
    -  }
    -  pubsub.subscribe(TOPIC_X, first);
    -
    -  function second() {
    -    assertEquals('Topic "X" must still have 3 subscribers', 3,
    -        pubsub.getCount(TOPIC_X));
    -    secondCalled = true;
    -  }
    -  pubsub.subscribe(TOPIC_X, second);
    -
    -  function third() {
    -    assertFalse('unsubscribe() must return false during publishing',
    -        pubsub.unsubscribe(TOPIC_X, first));
    -    assertEquals('Topic "X" must still have 3 subscribers', 3,
    -        pubsub.getCount(TOPIC_X));
    -    thirdCalled = true;
    -  }
    -  pubsub.subscribe(TOPIC_X, third);
    -
    -  assertEquals('Topic "X" must have 3 subscribers', 3,
    -      pubsub.getCount(TOPIC_X));
    -  assertFalse('No subscribers must have been called yet',
    -      firstCalled || secondCalled || thirdCalled);
    -
    -  assertTrue(pubsub.publish(TOPIC_X));
    -  assertTrue('First function must have been called', firstCalled);
    -  assertTrue('Second function must have been called', secondCalled);
    -  assertTrue('Third function must have been called', thirdCalled);
    -  assertEquals('Topic "X" must have 1 subscriber after publishing', 1,
    -      pubsub.getCount(TOPIC_X));
    -}
    -
    -function testUnsubscribeSelfWhilePublishing() {
    -  // It's OK for a subscriber to unsubscribe itself, but it won't actually
    -  // be removed until after publishing is complete.
    -
    -  var selfDestructCalled = false;
    -
    -  /** @const */ SOME_TOPIC = new goog.pubsub.TopicId('someTopic');
    -
    -  function selfDestruct() {
    -    assertFalse('unsubscribe() must return false during publishing',
    -        pubsub.unsubscribe(SOME_TOPIC, arguments.callee));
    -    assertEquals('Topic must still have 1 subscriber', 1,
    -        pubsub.getCount(SOME_TOPIC));
    -    selfDestructCalled = true;
    -  }
    -
    -  pubsub.subscribe(SOME_TOPIC, selfDestruct);
    -  assertEquals('Topic must have 1 subscriber', 1,
    -      pubsub.getCount(SOME_TOPIC));
    -  assertFalse('selfDestruct() must not have been called yet',
    -      selfDestructCalled);
    -
    -  pubsub.publish(SOME_TOPIC);
    -  assertTrue('selfDestruct() must have been called', selfDestructCalled);
    -  assertEquals('Topic must have no subscribers after publishing', 0,
    -      pubsub.getCount(SOME_TOPIC));
    -}
    -
    -function testPublishReturnValue() {
    -  /** @const */ SOME_TOPIC = new goog.pubsub.TopicId('someTopic');
    -  pubsub.subscribe(SOME_TOPIC, function() {
    -    pubsub.unsubscribe(SOME_TOPIC, arguments.callee);
    -  });
    -  assertTrue('publish() must return true even if the only subscriber ' +
    -      'removes itself during publishing', pubsub.publish(SOME_TOPIC));
    -}
    -
    -function testNestedPublish() {
    -  var x1 = false;
    -  var x2 = false;
    -  var y1 = false;
    -  var y2 = false;
    -
    -  /** @const */ TOPIC_X = new goog.pubsub.TopicId('X');
    -  /** @const */ TOPIC_Y = new goog.pubsub.TopicId('Y');
    -
    -  pubsub.subscribe(TOPIC_X, function() {
    -    pubsub.publish(TOPIC_Y);
    -    pubsub.unsubscribe(TOPIC_X, arguments.callee);
    -    x1 = true;
    -  });
    -
    -  pubsub.subscribe(TOPIC_X, function() {
    -    x2 = true;
    -  });
    -
    -  pubsub.subscribe(TOPIC_Y, function() {
    -    pubsub.unsubscribe(TOPIC_Y, arguments.callee);
    -    y1 = true;
    -  });
    -
    -  pubsub.subscribe(TOPIC_Y, function() {
    -    y2 = true;
    -  });
    -
    -  pubsub.publish(TOPIC_X);
    -
    -  assertTrue('x1 must be true', x1);
    -  assertTrue('x2 must be true', x2);
    -  assertTrue('y1 must be true', y1);
    -  assertTrue('y2 must be true', y2);
    -}
    -
    -function testClear() {
    -  function fn() {
    -  }
    -
    -  var topics = [
    -    new goog.pubsub.TopicId('W'),
    -    new goog.pubsub.TopicId('X'),
    -    new goog.pubsub.TopicId('Y'),
    -    new goog.pubsub.TopicId('Z')
    -  ];
    -
    -  goog.array.forEach(topics, function(topic) {
    -    pubsub.subscribe(topic, fn);
    -  });
    -  assertEquals('Pubsub channel must have 4 subscribers', 4,
    -      pubsub.getCount());
    -
    -  pubsub.clear(topics[0]);
    -  assertEquals('Pubsub channel must have 3 subscribers', 3,
    -      pubsub.getCount());
    -
    -  pubsub.clear(topics[1]);
    -  pubsub.clear(topics[2]);
    -  assertEquals('Pubsub channel must have 1 subscriber', 1,
    -      pubsub.getCount());
    -
    -  pubsub.clear();
    -  assertEquals('Pubsub channel must have no subscribers', 0,
    -      pubsub.getCount());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/reflect/reflect.js b/src/database/third_party/closure-library/closure/goog/reflect/reflect.js
    deleted file mode 100644
    index c49050f58ad..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/reflect/reflect.js
    +++ /dev/null
    @@ -1,78 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Useful compiler idioms.
    - *
    - * @author johnlenz@google.com (John Lenz)
    - */
    -
    -goog.provide('goog.reflect');
    -
    -
    -/**
    - * Syntax for object literal casts.
    - * @see http://go/jscompiler-renaming
    - * @see http://code.google.com/p/closure-compiler/wiki/
    - *      ExperimentalTypeBasedPropertyRenaming
    - *
    - * Use this if you have an object literal whose keys need to have the same names
    - * as the properties of some class even after they are renamed by the compiler.
    - *
    - * @param {!Function} type Type to cast to.
    - * @param {Object} object Object literal to cast.
    - * @return {Object} The object literal.
    - */
    -goog.reflect.object = function(type, object) {
    -  return object;
    -};
    -
    -
    -/**
    - * To assert to the compiler that an operation is needed when it would
    - * otherwise be stripped. For example:
    - * <code>
    - *     // Force a layout
    - *     goog.reflect.sinkValue(dialog.offsetHeight);
    - * </code>
    - * @type {!Function}
    - */
    -goog.reflect.sinkValue = function(x) {
    -  goog.reflect.sinkValue[' '](x);
    -  return x;
    -};
    -
    -
    -/**
    - * The compiler should optimize this function away iff no one ever uses
    - * goog.reflect.sinkValue.
    - */
    -goog.reflect.sinkValue[' '] = goog.nullFunction;
    -
    -
    -/**
    - * Check if a property can be accessed without throwing an exception.
    - * @param {Object} obj The owner of the property.
    - * @param {string} prop The property name.
    - * @return {boolean} Whether the property is accessible. Will also return true
    - *     if obj is null.
    - */
    -goog.reflect.canAccessProperty = function(obj, prop) {
    -  /** @preserveTry */
    -  try {
    -    goog.reflect.sinkValue(obj[prop]);
    -    return true;
    -  } catch (e) {}
    -  return false;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/result/chain_test.html b/src/database/third_party/closure-library/closure/goog/result/chain_test.html
    deleted file mode 100644
    index c56c93d24a4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/result/chain_test.html
    +++ /dev/null
    @@ -1,236 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<title>Closure Unit Tests - goog.result.chain</title>
    -<script src="../base.js"></script>
    -<script>
    -
    -goog.require('goog.Timer');
    -goog.require('goog.result');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -var givenResult, dependentResult, counter, actionCallback;
    -var mockClock;
    -
    -function setUpPage() {
    -  mockClock = new goog.testing.MockClock();
    -  mockClock.install();
    -}
    -
    -function setUp() {
    -  mockClock.reset();
    -  givenResult = new goog.result.SimpleResult();
    -  dependentResult = new goog.result.SimpleResult();
    -  counter = new goog.testing.recordFunction();
    -  actionCallback = goog.testing.recordFunction(function(result) {
    -    return dependentResult;
    -  });
    -}
    -
    -function tearDown() {
    -  givenResult = dependentResult = counter = null;
    -}
    -
    -function tearDownPage() {
    -  mockClock.uninstall();
    -}
    -
    -// SYNCHRONOUS TESTS:
    -
    -function testChainWhenBothResultsSuccess() {
    -  var finalResult = goog.result.chain(givenResult, actionCallback);
    -  goog.result.wait(finalResult, counter);
    -
    -  givenResult.setValue(1);
    -  dependentResult.setValue(2);
    -
    -  assertSuccess(actionCallback, givenResult, 1);
    -  assertSuccess(counter, finalResult, 2);
    -}
    -
    -function testChainWhenFirstResultError() {
    -  var finalResult = goog.result.chain(givenResult, actionCallback);
    -  goog.result.wait(finalResult, counter);
    -
    -  givenResult.setError(4);
    -
    -  assertNoCall(actionCallback);
    -  assertError(counter, finalResult, 4);
    -}
    -
    -function testChainWhenSecondResultError() {
    -  var finalResult = goog.result.chain(givenResult, actionCallback);
    -  goog.result.wait(finalResult, counter);
    -
    -  givenResult.setValue(1);
    -  dependentResult.setError(5);
    -
    -  assertSuccess(actionCallback, givenResult, 1);
    -  assertError(counter, finalResult, 5);
    -}
    -
    -function testChainCancelFirstResult() {
    -  var finalResult = goog.result.chain(givenResult, actionCallback);
    -  goog.result.wait(finalResult, counter);
    -
    -  goog.result.cancelParentResults(finalResult);
    -
    -  assertNoCall(actionCallback);
    -  assertTrue(givenResult.isCanceled());
    -  assertTrue(finalResult.isCanceled());
    -}
    -
    -function testChainCancelSecondResult() {
    -  var finalResult = goog.result.chain(givenResult, actionCallback);
    -  goog.result.wait(finalResult, counter);
    -
    -  givenResult.setValue(1);
    -  goog.result.cancelParentResults(finalResult);
    -
    -  assertSuccess(actionCallback, givenResult, 1);
    -  assertTrue(dependentResult.isCanceled());
    -  assertTrue(finalResult.isCanceled());
    -}
    -
    -function testDoubleChainCancel() {
    -  var intermediateResult = goog.result.chain(givenResult, actionCallback);
    -  var finalResult = goog.result.chain(intermediateResult, actionCallback);
    -
    -  assertTrue(goog.result.cancelParentResults(finalResult));
    -  assertTrue(finalResult.isCanceled());
    -  assertTrue(intermediateResult.isCanceled());
    -  assertFalse(givenResult.isCanceled());
    -  assertFalse(goog.result.cancelParentResults(finalResult));
    -}
    -
    -function testCustomScope() {
    -  var scope = {};
    -  var finalResult = goog.result.chain(givenResult, actionCallback, scope);
    -  goog.result.wait(finalResult, counter);
    -
    -  givenResult.setValue(1);
    -  dependentResult.setValue(2);
    -
    -  assertEquals(scope, actionCallback.popLastCall().getThis());
    -}
    -
    -
    -// ASYNCHRONOUS TESTS:
    -
    -function testChainAsyncWhenBothResultsSuccess() {
    -  var finalResult = goog.result.chain(givenResult, actionCallback);
    -  goog.result.wait(finalResult, counter);
    -
    -  goog.Timer.callOnce(function() { givenResult.setValue(1); });
    -  mockClock.tick();
    -
    -  assertSuccess(actionCallback, givenResult, 1);
    -
    -  goog.Timer.callOnce(function() { dependentResult.setValue(2); });
    -  mockClock.tick();
    -
    -  assertSuccess(counter, finalResult, 2);
    -}
    -
    -function testChainAsyncWhenFirstResultError() {
    -  var finalResult = goog.result.chain(givenResult, actionCallback);
    -  goog.result.wait(finalResult, counter);
    -
    -  goog.Timer.callOnce(function() { givenResult.setError(6); });
    -  mockClock.tick();
    -
    -  assertNoCall(actionCallback);
    -  assertError(counter, finalResult, 6);
    -}
    -
    -function testChainAsyncWhenSecondResultError() {
    -  var finalResult = goog.result.chain(givenResult, actionCallback);
    -  goog.result.wait(finalResult, counter);
    -
    -  goog.Timer.callOnce(function() { givenResult.setValue(1); });
    -  mockClock.tick();
    -
    -  assertSuccess(actionCallback, givenResult, 1);
    -
    -  goog.Timer.callOnce(function() { dependentResult.setError(7); });
    -  mockClock.tick();
    -
    -  assertError(counter, finalResult, 7);
    -}
    -
    -function testChainAsyncCancelFirstResult() {
    -  var finalResult = goog.result.chain(givenResult, actionCallback);
    -  goog.result.wait(finalResult, counter);
    -
    -  goog.Timer.callOnce(function() {
    -    goog.result.cancelParentResults(finalResult);
    -  });
    -  mockClock.tick();
    -
    -  assertNoCall(actionCallback);
    -  assertTrue(givenResult.isCanceled());
    -  assertTrue(finalResult.isCanceled());
    -}
    -
    -function testChainAsyncCancelSecondResult() {
    -  var finalResult = goog.result.chain(givenResult, actionCallback);
    -  goog.result.wait(finalResult, counter);
    -
    -  goog.Timer.callOnce(function() { givenResult.setValue(1); });
    -  mockClock.tick();
    -
    -  assertSuccess(actionCallback, givenResult, 1);
    -
    -  goog.Timer.callOnce(function() {
    -    goog.result.cancelParentResults(finalResult);
    -  });
    -  mockClock.tick();
    -
    -  assertTrue(dependentResult.isCanceled());
    -  assertTrue(finalResult.isCanceled());
    -}
    -
    -// HELPER FUNCTIONS:
    -
    -// Assert that the recordFunction was called once with an argument of
    -// 'result' (the second argument) which has a state of SUCCESS and
    -// a value of 'value' (the third argument).
    -function assertSuccess(recordFunction, result, value) {
    -  assertEquals(1, recordFunction.getCallCount());
    -  var res = recordFunction.popLastCall().getArgument(0);
    -  assertEquals(result, res);
    -  assertEquals(goog.result.Result.State.SUCCESS, res.getState());
    -  assertEquals(value, res.getValue());
    -}
    -
    -// Assert that the recordFunction was called once with an argument of
    -// 'result' (the second argument) which has a state of ERROR.
    -function assertError(recordFunction, result, value) {
    -  assertEquals(1, recordFunction.getCallCount());
    -  var res = recordFunction.popLastCall().getArgument(0);
    -  assertEquals(result, res);
    -  assertEquals(goog.result.Result.State.ERROR, res.getState());
    -  assertEquals(value, res.getError());
    -}
    -
    -// Assert that the recordFunction wasn't called
    -function assertNoCall(recordFunction) {
    -  assertEquals(0, recordFunction.getCallCount());
    -}
    -
    -</script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/result/combine_test.html b/src/database/third_party/closure-library/closure/goog/result/combine_test.html
    deleted file mode 100644
    index c8a31bba960..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/result/combine_test.html
    +++ /dev/null
    @@ -1,229 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<title>Closure Unit Tests - goog.result.combine</title>
    -<script src="../base.js"></script>
    -<script>
    -
    -goog.require('goog.Timer');
    -goog.require('goog.array');
    -goog.require('goog.result');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -var result1, result2, result3, result4, resultCallback;
    -var combinedResult, successCombinedResult, mockClock;
    -
    -function setUpPage() {
    -  mockClock = new goog.testing.MockClock();
    -  mockClock.install();
    -}
    -
    -function tearDownPage() {
    -  goog.dispose(mockClock);
    -}
    -
    -function setUp() {
    -  mockClock.reset();
    -  result1 = new goog.result.SimpleResult();
    -  result2 = new goog.result.SimpleResult();
    -  result3 = new goog.result.SimpleResult();
    -  result4 = new goog.result.SimpleResult();
    -
    -  combinedResult = goog.result.combine(result1, result2, result3, result4);
    -
    -  successCombinedResult =
    -      goog.result.combineOnSuccess(result1, result2, result3, result4);
    -
    -  resultCallback = goog.testing.recordFunction();
    -}
    -
    -function tearDown() {
    -  result1 = result2 = result3 = result4 = resultCallback = null;
    -  combinedResult = successCombinedResult = null;
    -}
    -
    -function testSynchronousCombine() {
    -  resolveAllGivenResultsToSuccess();
    -
    -  newCombinedResult = goog.result.combine(result1, result2, result3, result4);
    -
    -  goog.result.wait(newCombinedResult, resultCallback);
    -
    -  assertSuccessCall(newCombinedResult, resultCallback);
    -}
    -
    -function testCombineWhenAllResultsSuccess() {
    -  goog.result.wait(combinedResult, resultCallback);
    -
    -  resolveAllGivenResultsToSuccess();
    -
    -  assertSuccessCall(combinedResult, resultCallback);
    -}
    -
    -function testAsyncCombineWhenAllResultsSuccess() {
    -  goog.result.wait(combinedResult, resultCallback);
    -
    -  goog.Timer.callOnce(function() { resolveAllGivenResultsToSuccess(); });
    -  mockClock.tick();
    -
    -  assertSuccessCall(combinedResult, resultCallback);
    -}
    -
    -function testCombineWhenAllResultsFail() {
    -  goog.result.wait(combinedResult, resultCallback);
    -
    -  resolveAllGivenResultsToError();
    -
    -  assertSuccessCall(combinedResult, resultCallback);
    -}
    -
    -function testAsyncCombineWhenAllResultsFail() {
    -  goog.result.wait(combinedResult, resultCallback);
    -
    -  goog.Timer.callOnce(function() { resolveAllGivenResultsToError(); });
    -  mockClock.tick();
    -
    -  assertSuccessCall(combinedResult, resultCallback);
    -}
    -
    -function testCombineWhenSomeResultsSuccess() {
    -  goog.result.wait(combinedResult, resultCallback);
    -
    -  resolveSomeGivenResultsToSuccess();
    -
    -  assertSuccessCall(combinedResult, resultCallback);
    -}
    -
    -function testAsyncCombineWhenSomeResultsSuccess() {
    -  goog.result.wait(combinedResult, resultCallback);
    -
    -  goog.Timer.callOnce(function() { resolveSomeGivenResultsToSuccess(); });
    -  mockClock.tick();
    -
    -  assertSuccessCall(combinedResult, resultCallback);
    -}
    -
    -function testCombineOnSuccessWhenAllResultsSuccess() {
    -  goog.result.wait(successCombinedResult, resultCallback);
    -
    -  resolveAllGivenResultsToSuccess();
    -
    -  assertSuccessCall(successCombinedResult, resultCallback);
    -}
    -
    -function testAsyncCombineOnSuccessWhenAllResultsSuccess() {
    -  goog.result.wait(successCombinedResult, resultCallback);
    -
    -  goog.Timer.callOnce(function() { resolveAllGivenResultsToSuccess(); });
    -  mockClock.tick();
    -
    -  assertSuccessCall(successCombinedResult, resultCallback);
    -}
    -
    -function testCombineOnSuccessWhenAllResultsFail() {
    -  goog.result.wait(successCombinedResult, resultCallback);
    -
    -  resolveAllGivenResultsToError();
    -
    -  assertErrorCall(successCombinedResult, resultCallback);
    -}
    -
    -function testAsyncCombineOnSuccessWhenAllResultsFail() {
    -  goog.result.wait(successCombinedResult, resultCallback);
    -
    -  goog.Timer.callOnce(function() { resolveAllGivenResultsToError(); });
    -  mockClock.tick();
    -
    -  assertErrorCall(successCombinedResult, resultCallback);
    -}
    -
    -function testCombineOnSuccessWhenSomeResultsSuccess() {
    -  goog.result.wait(successCombinedResult, resultCallback);
    -
    -  resolveSomeGivenResultsToSuccess();
    -
    -  assertErrorCall(successCombinedResult, resultCallback);
    -}
    -
    -function testAsyncCombineOnSuccessWhenSomeResultsSuccess() {
    -  goog.result.wait(successCombinedResult, resultCallback);
    -
    -  goog.Timer.callOnce(function() { resolveSomeGivenResultsToSuccess(); });
    -  mockClock.tick();
    -
    -  assertErrorCall(successCombinedResult, resultCallback);
    -}
    -
    -function testCancelParentResults() {
    -  goog.result.wait(combinedResult, resultCallback);
    -
    -  goog.result.cancelParentResults(combinedResult);
    -
    -  assertArgumentContainsGivenResults(combinedResult.getValue())
    -  goog.array.forEach([result1, result2, result3, result4],
    -      function(result) {
    -        assertTrue(result.isCanceled());
    -      });
    -}
    -
    -function assertSuccessCall(combinedResult, resultCallback) {
    -  assertEquals(goog.result.Result.State.SUCCESS, combinedResult.getState());
    -  assertEquals(1, resultCallback.getCallCount());
    -
    -  var result = resultCallback.popLastCall().getArgument(0);
    -  assertEquals(combinedResult, result);
    -  assertArgumentContainsGivenResults(result.getValue());
    -}
    -
    -function assertErrorCall(combinedResult, resultCallback) {
    -  assertEquals(goog.result.Result.State.ERROR,
    -                 combinedResult.getState());
    -  assertEquals(1, resultCallback.getCallCount());
    -
    -  var result = resultCallback.popLastCall().getArgument(0);
    -  assertEquals(combinedResult, result);
    -  assertArgumentContainsGivenResults(combinedResult.getError());
    -}
    -
    -function assertArgumentContainsGivenResults(resultsArray) {
    -  assertEquals(4, resultsArray.length);
    -
    -  goog.array.forEach([result1, result2, result3, result4], function(res) {
    -      assertTrue(goog.array.contains(resultsArray, res));
    -  });
    -}
    -
    -function resolveAllGivenResultsToSuccess() {
    -  goog.array.forEach([result1, result2, result3, result4], function(res) {
    -      res.setValue(1);
    -  });
    -}
    -
    -function resolveAllGivenResultsToError() {
    -  goog.array.forEach([result1, result2, result3, result4], function(res) {
    -      res.setError();
    -  });
    -}
    -
    -function resolveSomeGivenResultsToSuccess() {
    -  goog.array.forEach([result2, result3, result4], function(res) {
    -      res.setValue(1);
    -  });
    -  result1.setError();
    -}
    -</script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/result/deferredadaptor.js b/src/database/third_party/closure-library/closure/goog/result/deferredadaptor.js
    deleted file mode 100644
    index d55a3f65c09..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/result/deferredadaptor.js
    +++ /dev/null
    @@ -1,59 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview An adaptor from a Result to a Deferred.
    - *
    - * TODO (vbhasin): cancel() support.
    - * TODO (vbhasin): See if we can make this a static.
    - * TODO (gboyer, vbhasin): Rename to "Adapter" once this graduates; this is the
    - * proper programmer spelling.
    - */
    -
    -
    -goog.provide('goog.result.DeferredAdaptor');
    -
    -goog.require('goog.async.Deferred');
    -goog.require('goog.result');
    -goog.require('goog.result.Result');
    -
    -
    -
    -/**
    - * An adaptor from Result to a Deferred, for use with existing Deferred chains.
    - *
    - * @param {!goog.result.Result} result A result.
    - * @constructor
    - * @extends {goog.async.Deferred}
    - * @final
    - * @deprecated Use {@link goog.Promise} instead - http://go/promisemigration
    - */
    -goog.result.DeferredAdaptor = function(result) {
    -  goog.result.DeferredAdaptor.base(this, 'constructor');
    -  goog.result.wait(result, function(result) {
    -    if (this.hasFired()) {
    -      return;
    -    }
    -    if (result.getState() == goog.result.Result.State.SUCCESS) {
    -      this.callback(result.getValue());
    -    } else if (result.getState() == goog.result.Result.State.ERROR) {
    -      if (result.getError() instanceof goog.result.Result.CancelError) {
    -        this.cancel();
    -      } else {
    -        this.errback(result.getError());
    -      }
    -    }
    -  }, this);
    -};
    -goog.inherits(goog.result.DeferredAdaptor, goog.async.Deferred);
    diff --git a/src/database/third_party/closure-library/closure/goog/result/deferredadaptor_test.html b/src/database/third_party/closure-library/closure/goog/result/deferredadaptor_test.html
    deleted file mode 100644
    index 02df7b7b8ce..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/result/deferredadaptor_test.html
    +++ /dev/null
    @@ -1,86 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<title>Closure Unit Tests - goog.result.DeferredAdaptor</title>
    -<script src="../base.js"></script>
    -<script>
    -
    -goog.require('goog.result');
    -goog.require('goog.result.DeferredAdaptor');
    -goog.require('goog.result.SimpleResult');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -var result, deferred, record;
    -
    -function setUp() {
    -  result = new goog.result.SimpleResult();
    -  deferred = new goog.result.DeferredAdaptor(result);
    -  record = new goog.testing.recordFunction();
    -}
    -
    -function tearDown() {
    -  result = deferred = record = null;
    -}
    -
    -function testResultSuccesfulResolution() {
    -  deferred.addCallback(record);
    -  result.setValue(1);
    -  assertEquals(1, record.getCallCount());
    -  var call = record.popLastCall();
    -  assertEquals(1, call.getArgument(0));
    -}
    -
    -function testResultErrorResolution() {
    -  deferred.addErrback(record);
    -  result.setError(2);
    -  assertEquals(1, record.getCallCount());
    -  var call = record.popLastCall();
    -  assertEquals(2, call.getArgument(0));
    -}
    -
    -function testResultCancelResolution() {
    -  deferred.addCallback(record);
    -  var cancelCallback = new goog.testing.recordFunction();
    -  deferred.addErrback(cancelCallback);
    -  result.cancel();
    -  assertEquals(0, record.getCallCount());
    -  assertEquals(1, cancelCallback.getCallCount());
    -  var call = cancelCallback.popLastCall();
    -  assertTrue(call.getArgument(0) instanceof
    -             goog.async.Deferred.CanceledError);
    -}
    -
    -function testAddCallbackOnResolvedResult() {
    -  result.setValue(1);
    -  assertEquals(1, result.getValue());
    -  deferred.addCallback(record);
    -
    -  // callback should be called immediately when result is already resolved.
    -  assertEquals(1, record.getCallCount());
    -  assertEquals(1, record.popLastCall().getArgument(0));
    -}
    -
    -function testAddErrbackOnErroredResult() {
    -  result.setError(1);
    -  assertEquals(1, result.getError());
    -
    -  // errback should be called immediately when result already errored.
    -  deferred.addErrback(record);
    -  assertEquals(1, record.getCallCount());
    -  assertEquals(1, record.popLastCall().getArgument(0));
    -}
    -</script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/result/dependentresult.js b/src/database/third_party/closure-library/closure/goog/result/dependentresult.js
    deleted file mode 100644
    index 11898c8cedc..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/result/dependentresult.js
    +++ /dev/null
    @@ -1,45 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview An interface for Results whose eventual value depends on the
    - *     value of one or more other Results.
    - */
    -
    -goog.provide('goog.result.DependentResult');
    -
    -goog.require('goog.result.Result');
    -
    -
    -
    -/**
    - * A DependentResult represents a Result whose eventual value depends on the
    - * value of one or more other Results. For example, the Result returned by
    - * @see goog.result.chain or @see goog.result.combine is dependent on the
    - * Results given as arguments.
    - * @interface
    - * @extends {goog.result.Result}
    - * @deprecated Use {@link goog.Promise} instead - http://go/promisemigration
    - */
    -goog.result.DependentResult = function() {};
    -
    -
    -/**
    - *
    - * @return {!Array<!goog.result.Result>} A list of Results which will affect
    - *     the eventual value of this Result. The returned Results may themselves
    - *     have parent results, which would be grandparents of this Result;
    - *     grandparents (and any other ancestors) are not included in this list.
    - */
    -goog.result.DependentResult.prototype.getParentResults = function() {};
    diff --git a/src/database/third_party/closure-library/closure/goog/result/result_interface.js b/src/database/third_party/closure-library/closure/goog/result/result_interface.js
    deleted file mode 100644
    index 68c3c8d334f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/result/result_interface.js
    +++ /dev/null
    @@ -1,119 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Defines an interface that represents a Result.
    - *
    - * NOTE: goog.result is soft deprecated - we expect to replace this and
    - * {@link goog.async.Deferred} with {@link goog.Promise}.
    - */
    -
    -goog.provide('goog.result.Result');
    -
    -goog.require('goog.Thenable');
    -
    -
    -
    -/**
    - * A Result object represents a value returned by an asynchronous
    - * operation at some point in the future (e.g. a network fetch). This is akin
    - * to a 'Promise' or a 'Future' in other languages and frameworks.
    - *
    - * @interface
    - * @extends {goog.Thenable}
    - * @deprecated Use {@link goog.Promise} instead - http://go/promisemigration
    - */
    -goog.result.Result = function() {};
    -
    -
    -/**
    - * Attaches handlers to be called when the value of this Result is available.
    - * Handlers are called in the order they were added by wait.
    - *
    - * @param {!function(this:T, !goog.result.Result)} handler The function called
    - *     when the value is available. The function is passed the Result object as
    - *     the only argument.
    - * @param {T=} opt_scope Optional scope for the handler.
    - * @template T
    - */
    -goog.result.Result.prototype.wait = function(handler, opt_scope) {};
    -
    -
    -/**
    - * The States this object can be in.
    - *
    - * @enum {string}
    - * @deprecated Use {@link goog.Promise} instead - http://go/promisemigration
    - */
    -goog.result.Result.State = {
    -  /** The operation was a success and the value is available. */
    -  SUCCESS: 'success',
    -
    -  /** The operation resulted in an error. */
    -  ERROR: 'error',
    -
    -  /** The operation is incomplete and the value is not yet available. */
    -  PENDING: 'pending'
    -};
    -
    -
    -/**
    - * @return {!goog.result.Result.State} The state of this Result.
    - */
    -goog.result.Result.prototype.getState = function() {};
    -
    -
    -/**
    - * @return {*} The value of this Result. Will return undefined if the Result is
    - *     pending or was an error.
    - */
    -goog.result.Result.prototype.getValue = function() {};
    -
    -
    -/**
    - * @return {*} The error slug for this Result. Will return undefined if the
    - *     Result was a success, the error slug was not set, or if the Result is
    - *     pending.
    - */
    -goog.result.Result.prototype.getError = function() {};
    -
    -
    -/**
    - * Cancels the current Result, invoking the canceler function, if set.
    - *
    - * @return {boolean} Whether the Result was canceled.
    - */
    -goog.result.Result.prototype.cancel = function() {};
    -
    -
    -/**
    - * @return {boolean} Whether this Result was canceled.
    - */
    -goog.result.Result.prototype.isCanceled = function() {};
    -
    -
    -
    -/**
    - * The value to be passed to the error handlers invoked upon cancellation.
    - * @constructor
    - * @extends {Error}
    - * @final
    - * @deprecated Use {@link goog.Promise} instead - http://go/promisemigration
    - */
    -goog.result.Result.CancelError = function() {
    -  // Note that this does not derive from goog.debug.Error in order to prevent
    -  // stack trace capture and reduce the amount of garbage generated during a
    -  // cancel() operation.
    -};
    -goog.inherits(goog.result.Result.CancelError, Error);
    diff --git a/src/database/third_party/closure-library/closure/goog/result/resultutil.js b/src/database/third_party/closure-library/closure/goog/result/resultutil.js
    deleted file mode 100644
    index 91ffef404fc..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/result/resultutil.js
    +++ /dev/null
    @@ -1,556 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview This file provides primitives and tools (wait, transform,
    - *     chain, combine) that make it easier to work with Results. This section
    - *     gives an overview of their functionality along with some examples and the
    - *     actual definitions have detailed descriptions next to them.
    - *
    - *
    - * NOTE: goog.result is soft deprecated - we expect to replace this and
    - * goog.async.Deferred with a wrapper around W3C Promises:
    - * http://dom.spec.whatwg.org/#promises.
    - */
    -
    -goog.provide('goog.result');
    -
    -goog.require('goog.array');
    -goog.require('goog.result.DependentResult');
    -goog.require('goog.result.Result');
    -goog.require('goog.result.SimpleResult');
    -
    -
    -/**
    - * Returns a successful result containing the provided value.
    - *
    - * Example:
    - * <pre>
    - *
    - * var value = 'some-value';
    - * var result = goog.result.immediateResult(value);
    - * assertEquals(goog.result.Result.State.SUCCESS, result.getState());
    - * assertEquals(value, result.getValue());
    - *
    - * </pre>
    - *
    - * @param {*} value The value of the result.
    - * @return {!goog.result.Result} A Result object that has already been resolved
    - *     to the supplied value.
    - */
    -goog.result.successfulResult = function(value) {
    -  var result = new goog.result.SimpleResult();
    -  result.setValue(value);
    -  return result;
    -};
    -
    -
    -/**
    - * Returns a failed result with the optional error slug set.
    - *
    - * Example:
    - * <pre>
    - *
    - * var error = new Error('something-failed');
    - * var result = goog.result.failedResult(error);
    - * assertEquals(goog.result.Result.State.ERROR, result.getState());
    - * assertEquals(error, result.getError());
    - *
    - * </pre>
    - *
    - * @param {*=} opt_error The error to which the result should resolve.
    - * @return {!goog.result.Result} A Result object that has already been resolved
    - *     to the supplied Error.
    - */
    -goog.result.failedResult = function(opt_error) {
    -  var result = new goog.result.SimpleResult();
    -  result.setError(opt_error);
    -  return result;
    -};
    -
    -
    -/**
    - * Returns a canceled result.
    - * The result will be resolved to an error of type CancelError.
    - *
    - * Example:
    - * <pre>
    - *
    - * var result = goog.result.canceledResult();
    - * assertEquals(goog.result.Result.State.ERROR, result.getState());
    - * var error = result.getError();
    - * assertTrue(error instanceof goog.result.Result.CancelError);
    - *
    - * </pre>
    - *
    - * @return {!goog.result.Result} A canceled Result.
    - */
    -goog.result.canceledResult = function() {
    -  var result = new goog.result.SimpleResult();
    -  result.cancel();
    -  return result;
    -};
    -
    -
    -/**
    - * Calls the handler on resolution of the result (success or failure).
    - * The handler is passed the result object as the only parameter. The call will
    - * be immediate if the result is no longer pending.
    - *
    - * Example:
    - * <pre>
    - *
    - * var result = xhr.get('testdata/xhr_test_text.data');
    - *
    - * // Wait for the result to be resolved and alert it's state.
    - * goog.result.wait(result, function(result) {
    - *   alert('State: ' + result.getState());
    - * });
    - * </pre>
    - *
    - * @param {!goog.result.Result} result The result to install the handlers.
    - * @param {function(this:T, !goog.result.Result)} handler The handler to be
    - *     called. The handler is passed the result object as the only parameter.
    - * @param {T=} opt_scope Optional scope for the handler.
    - * @template T
    - */
    -goog.result.wait = function(result, handler, opt_scope) {
    -  result.wait(handler, opt_scope);
    -};
    -
    -
    -/**
    - * Calls the handler if the result succeeds. The result object is the only
    - * parameter passed to the handler. The call will be immediate if the result
    - * has already succeeded.
    - *
    - * Example:
    - * <pre>
    - *
    - * var result = xhr.get('testdata/xhr_test_text.data');
    - *
    - * // attach a success handler.
    - * goog.result.waitOnSuccess(result, function(resultValue, result) {
    - *   var datavalue = result.getvalue();
    - *   alert('value: ' + datavalue + ' == ' + resultValue);
    - * });
    - * </pre>
    - *
    - * @param {!goog.result.Result} result The result to install the handlers.
    - * @param {function(this:T, ?, !goog.result.Result)} handler The handler to be
    - *     called. The handler is passed the result value and the result as
    - *     parameters.
    - * @param {T=} opt_scope Optional scope for the handler.
    - * @template T
    - */
    -goog.result.waitOnSuccess = function(result, handler, opt_scope) {
    -  goog.result.wait(result, function(res) {
    -    if (res.getState() == goog.result.Result.State.SUCCESS) {
    -      // 'this' refers to opt_scope
    -      handler.call(this, res.getValue(), res);
    -    }
    -  }, opt_scope);
    -};
    -
    -
    -/**
    - * Calls the handler if the result action errors. The result object is passed as
    - * the only parameter to the handler. The call will be immediate if the result
    - * object has already resolved to an error.
    - *
    - * Example:
    - *
    - * <pre>
    - *
    - * var result = xhr.get('testdata/xhr_test_text.data');
    - *
    - * // Attach a failure handler.
    - * goog.result.waitOnError(result, function(error) {
    - *  // Failed asynchronous call!
    - * });
    - * </pre>
    - *
    - * @param {!goog.result.Result} result The result to install the handlers.
    - * @param {function(this:T, ?, !goog.result.Result)} handler The handler to be
    - *     called. The handler is passed the error and the result object as
    - *     parameters.
    - * @param {T=} opt_scope Optional scope for the handler.
    - * @template T
    - */
    -goog.result.waitOnError = function(result, handler, opt_scope) {
    -  goog.result.wait(result, function(res) {
    -    if (res.getState() == goog.result.Result.State.ERROR) {
    -      // 'this' refers to opt_scope
    -      handler.call(this, res.getError(), res);
    -    }
    -  }, opt_scope);
    -};
    -
    -
    -/**
    - * Given a result and a transform function, returns a new result whose value,
    - * on success, will be the value of the given result after having been passed
    - * through the transform function.
    - *
    - * If the given result is an error, the returned result is also an error and the
    - * transform will not be called.
    - *
    - * Example:
    - * <pre>
    - *
    - * var result = xhr.getJson('testdata/xhr_test_json.data');
    - *
    - * // Transform contents of returned data using 'processJson' and create a
    - * // transformed result to use returned JSON.
    - * var transformedResult = goog.result.transform(result, processJson);
    - *
    - * // Attach success and failure handlers to the tranformed result.
    - * goog.result.waitOnSuccess(transformedResult, function(resultValue, result) {
    - *   var jsonData = resultValue;
    - *   assertEquals('ok', jsonData['stat']);
    - * });
    - *
    - * goog.result.waitOnError(transformedResult, function(error) {
    - *   // Failed getJson call
    - * });
    - * </pre>
    - *
    - * @param {!goog.result.Result} result The result whose value will be
    - *     transformed.
    - * @param {function(?):?} transformer The transformer
    - *     function. The return value of this function will become the value of the
    - *     returned result.
    - *
    - * @return {!goog.result.DependentResult} A new Result whose eventual value will
    - *     be the returned value of the transformer function.
    - */
    -goog.result.transform = function(result, transformer) {
    -  var returnedResult = new goog.result.DependentResultImpl_([result]);
    -
    -  goog.result.wait(result, function(res) {
    -    if (res.getState() == goog.result.Result.State.SUCCESS) {
    -      returnedResult.setValue(transformer(res.getValue()));
    -    } else {
    -      returnedResult.setError(res.getError());
    -    }
    -  });
    -
    -  return returnedResult;
    -};
    -
    -
    -/**
    - * The chain function aids in chaining of asynchronous Results. This provides a
    - * convenience for use cases where asynchronous operations must happen serially
    - * i.e. subsequent asynchronous operations are dependent on data returned by
    - * prior asynchronous operations.
    - *
    - * It accepts a result and an action callback as arguments and returns a
    - * result. The action callback is called when the first result succeeds and is
    - * supposed to return a second result. The returned result is resolved when one
    - * of both of the results resolve (depending on their success or failure.) The
    - * state and value of the returned result in the various cases is documented
    - * below:
    - * <pre>
    - *
    - * First Result State:    Second Result State:    Returned Result State:
    - * SUCCESS                SUCCESS                 SUCCESS
    - * SUCCESS                ERROR                   ERROR
    - * ERROR                  Not created             ERROR
    - * </pre>
    - *
    - * The value of the returned result, in the case both results succeed, is the
    - * value of the second result (the result returned by the action callback.)
    - *
    - * Example:
    - * <pre>
    - *
    - * var testDataResult = xhr.get('testdata/xhr_test_text.data');
    - *
    - * // Chain this result to perform another asynchronous operation when this
    - * // Result is resolved.
    - * var chainedResult = goog.result.chain(testDataResult,
    - *     function(testDataResult) {
    - *
    - *       // The result value of testDataResult is the URL for JSON data.
    - *       var jsonDataUrl = testDataResult.getValue();
    - *
    - *       // Create a new Result object when the original result is resolved.
    - *       var jsonResult = xhr.getJson(jsonDataUrl);
    - *
    - *       // Return the newly created Result.
    - *       return jsonResult;
    - *     });
    - *
    - * // The chained result resolves to success when both results resolve to
    - * // success.
    - * goog.result.waitOnSuccess(chainedResult, function(resultValue, result) {
    - *
    - *   // At this point, both results have succeeded and we can use the JSON
    - *   // data returned by the second asynchronous call.
    - *   var jsonData = resultValue;
    - *   assertEquals('ok', jsonData['stat']);
    - * });
    - *
    - * // Attach the error handler to be called when either Result fails.
    - * goog.result.waitOnError(chainedResult, function(result) {
    - *   alert('chained result failed!');
    - * });
    - * </pre>
    - *
    - * @param {!goog.result.Result} result The result to chain.
    - * @param {function(this:T, !goog.result.Result):!goog.result.Result}
    - *     actionCallback The callback called when the result is resolved. This
    - *     callback must return a Result.
    - * @param {T=} opt_scope Optional scope for the action callback.
    - * @return {!goog.result.DependentResult} A result that is resolved when both
    - *     the given Result and the Result returned by the actionCallback have
    - *     resolved.
    - * @template T
    - */
    -goog.result.chain = function(result, actionCallback, opt_scope) {
    -  var dependentResult = new goog.result.DependentResultImpl_([result]);
    -
    -  // Wait for the first action.
    -  goog.result.wait(result, function(result) {
    -    if (result.getState() == goog.result.Result.State.SUCCESS) {
    -
    -      // The first action succeeded. Chain the contingent action.
    -      var contingentResult = actionCallback.call(opt_scope, result);
    -      dependentResult.addParentResult(contingentResult);
    -      goog.result.wait(contingentResult, function(contingentResult) {
    -
    -        // The contingent action completed. Set the dependent result based on
    -        // the contingent action's outcome.
    -        if (contingentResult.getState() ==
    -            goog.result.Result.State.SUCCESS) {
    -          dependentResult.setValue(contingentResult.getValue());
    -        } else {
    -          dependentResult.setError(contingentResult.getError());
    -        }
    -      });
    -    } else {
    -      // First action failed, the dependent result should also fail.
    -      dependentResult.setError(result.getError());
    -    }
    -  });
    -
    -  return dependentResult;
    -};
    -
    -
    -/**
    - * Returns a result that waits on all given results to resolve. Once all have
    - * resolved, the returned result will succeed (and never error).
    - *
    - * Example:
    - * <pre>
    - *
    - * var result1 = xhr.get('testdata/xhr_test_text.data');
    - *
    - * // Get a second independent Result.
    - * var result2 = xhr.getJson('testdata/xhr_test_json.data');
    - *
    - * // Create a Result that resolves when both prior results resolve.
    - * var combinedResult = goog.result.combine(result1, result2);
    - *
    - * // Process data after resolution of both results.
    - * goog.result.waitOnSuccess(combinedResult, function(results) {
    - *   goog.array.forEach(results, function(result) {
    - *       alert(result.getState());
    - *   });
    - * });
    - * </pre>
    - *
    - * @param {...!goog.result.Result} var_args The results to wait on.
    - *
    - * @return {!goog.result.DependentResult} A new Result whose eventual value will
    - *     be the resolved given Result objects.
    - */
    -goog.result.combine = function(var_args) {
    -  /** @type {!Array<!goog.result.Result>} */
    -  var results = goog.array.clone(arguments);
    -  var combinedResult = new goog.result.DependentResultImpl_(results);
    -
    -  var isResolved = function(res) {
    -    return res.getState() != goog.result.Result.State.PENDING;
    -  };
    -
    -  var checkResults = function() {
    -    if (combinedResult.getState() == goog.result.Result.State.PENDING &&
    -        goog.array.every(results, isResolved)) {
    -      combinedResult.setValue(results);
    -    }
    -  };
    -
    -  goog.array.forEach(results, function(result) {
    -    goog.result.wait(result, checkResults);
    -  });
    -
    -  return combinedResult;
    -};
    -
    -
    -/**
    - * Returns a result that waits on all given results to resolve. Once all have
    - * resolved, the returned result will succeed if and only if all given results
    - * succeeded. Otherwise it will error.
    - *
    - * Example:
    - * <pre>
    - *
    - * var result1 = xhr.get('testdata/xhr_test_text.data');
    - *
    - * // Get a second independent Result.
    - * var result2 = xhr.getJson('testdata/xhr_test_json.data');
    - *
    - * // Create a Result that resolves when both prior results resolve.
    - * var combinedResult = goog.result.combineOnSuccess(result1, result2);
    - *
    - * // Process data after successful resolution of both results.
    - * goog.result.waitOnSuccess(combinedResult, function(results) {
    - *   var textData = results[0].getValue();
    - *   var jsonData = results[1].getValue();
    - *   assertEquals('Just some data.', textData);
    - *   assertEquals('ok', jsonData['stat']);
    - * });
    - *
    - * // Handle errors when either or both results failed.
    - * goog.result.waitOnError(combinedResult, function(combined) {
    - *   var results = combined.getError();
    - *
    - *   if (results[0].getState() == goog.result.Result.State.ERROR) {
    - *     alert('result1 failed');
    - *   }
    - *
    - *   if (results[1].getState() == goog.result.Result.State.ERROR) {
    - *     alert('result2 failed');
    - *   }
    - * });
    - * </pre>
    - *
    - * @param {...!goog.result.Result} var_args The results to wait on.
    - *
    - * @return {!goog.result.DependentResult} A new Result whose eventual value will
    - *     be an array of values of the given Result objects.
    - */
    -goog.result.combineOnSuccess = function(var_args) {
    -  var results = goog.array.clone(arguments);
    -  var combinedResult = new goog.result.DependentResultImpl_(results);
    -
    -  var resolvedSuccessfully = function(res) {
    -    return res.getState() == goog.result.Result.State.SUCCESS;
    -  };
    -
    -  goog.result.wait(
    -      goog.result.combine.apply(goog.result.combine, results),
    -      // The combined result never ERRORs
    -      function(res) {
    -        var results = /** @type {Array<!goog.result.Result>} */ (
    -            res.getValue());
    -        if (goog.array.every(results, resolvedSuccessfully)) {
    -          combinedResult.setValue(results);
    -        } else {
    -          combinedResult.setError(results);
    -        }
    -      });
    -
    -  return combinedResult;
    -};
    -
    -
    -/**
    - * Given a DependentResult, cancels the Results it depends on (that is, the
    - * results returned by getParentResults). This function does not recurse,
    - * so e.g. parents of parents are not canceled; only the immediate parents of
    - * the given Result are canceled.
    - *
    - * Example using @see goog.result.combine:
    - * <pre>
    - * var result1 = xhr.get('testdata/xhr_test_text.data');
    - *
    - * // Get a second independent Result.
    - * var result2 = xhr.getJson('testdata/xhr_test_json.data');
    - *
    - * // Create a Result that resolves when both prior results resolve.
    - * var combinedResult = goog.result.combineOnSuccess(result1, result2);
    - *
    - * combinedResult.wait(function() {
    - *   if (combinedResult.isCanceled()) {
    - *     goog.result.cancelParentResults(combinedResult);
    - *   }
    - * });
    - *
    - * // Now, canceling combinedResult will cancel both result1 and result2.
    - * combinedResult.cancel();
    - * </pre>
    - * @param {!goog.result.DependentResult} dependentResult A Result that is
    - *     dependent on the values of other Results (for example the Result of a
    - *     goog.result.combine, goog.result.chain, or goog.result.transform call).
    - * @return {boolean} True if any results were successfully canceled; otherwise
    - *     false.
    - * TODO(user): Implement a recursive version of this that cancels all
    - * ancestor results.
    - */
    -goog.result.cancelParentResults = function(dependentResult) {
    -  var anyCanceled = false;
    -  var results = dependentResult.getParentResults();
    -  for (var n = 0; n < results.length; n++) {
    -    anyCanceled |= results[n].cancel();
    -  }
    -  return !!anyCanceled;
    -};
    -
    -
    -
    -/**
    - * A DependentResult represents a Result whose eventual value depends on the
    - * value of one or more other Results. For example, the Result returned by
    - * @see goog.result.chain or @see goog.result.combine is dependent on the
    - * Results given as arguments.
    - *
    - * @param {!Array<!goog.result.Result>} parentResults A list of Results that
    - *     will affect the eventual value of this Result.
    - * @constructor
    - * @implements {goog.result.DependentResult}
    - * @extends {goog.result.SimpleResult}
    - * @private
    - */
    -goog.result.DependentResultImpl_ = function(parentResults) {
    -  goog.result.DependentResultImpl_.base(this, 'constructor');
    -  /**
    -   * A list of Results that will affect the eventual value of this Result.
    -   * @type {!Array<!goog.result.Result>}
    -   * @private
    -   */
    -  this.parentResults_ = parentResults;
    -};
    -goog.inherits(goog.result.DependentResultImpl_, goog.result.SimpleResult);
    -
    -
    -/**
    - * Adds a Result to the list of Results that affect this one.
    - * @param {!goog.result.Result} parentResult A result whose value affects the
    - *     value of this Result.
    - */
    -goog.result.DependentResultImpl_.prototype.addParentResult = function(
    -    parentResult) {
    -  this.parentResults_.push(parentResult);
    -};
    -
    -
    -/** @override */
    -goog.result.DependentResultImpl_.prototype.getParentResults = function() {
    -  return this.parentResults_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/result/resultutil_test.html b/src/database/third_party/closure-library/closure/goog/result/resultutil_test.html
    deleted file mode 100644
    index d26898ccfa4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/result/resultutil_test.html
    +++ /dev/null
    @@ -1,46 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<title>Closure Unit Tests - goog.result.*</title>
    -<script src="../base.js"></script>
    -<script>
    -goog.require('goog.result');
    -goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -function testSuccessfulResult() {
    -  var value = 'some-value';
    -  var result = goog.result.successfulResult(value);
    -  assertEquals(goog.result.Result.State.SUCCESS, result.getState());
    -  assertEquals(value, result.getValue());
    -}
    -
    -
    -function testFailedResult() {
    -  var error = new Error('something-failed');
    -  var result = goog.result.failedResult(error);
    -  assertEquals(goog.result.Result.State.ERROR, result.getState());
    -  assertEquals(error, result.getError());
    -}
    -
    -
    -function testCanceledResult() {
    -  var result = goog.result.canceledResult();
    -  assertEquals(goog.result.Result.State.ERROR, result.getState());
    -
    -  var error = result.getError();
    -  assertTrue(error instanceof goog.result.Result.CancelError);
    -}
    -
    -</script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/result/simpleresult.js b/src/database/third_party/closure-library/closure/goog/result/simpleresult.js
    deleted file mode 100644
    index 9e1af70a553..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/result/simpleresult.js
    +++ /dev/null
    @@ -1,260 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A SimpleResult object that implements goog.result.Result.
    - * See below for a more detailed description.
    - */
    -
    -goog.provide('goog.result.SimpleResult');
    -goog.provide('goog.result.SimpleResult.StateError');
    -
    -goog.require('goog.Promise');
    -goog.require('goog.Thenable');
    -goog.require('goog.debug.Error');
    -goog.require('goog.result.Result');
    -
    -
    -
    -/**
    - * A SimpleResult object is a basic implementation of the
    - * goog.result.Result interface. This could be subclassed(e.g. XHRResult)
    - * or instantiated and returned by another class as a form of result. The caller
    - * receiving the result could then attach handlers to be called when the result
    - * is resolved(success or error).
    - *
    - * @constructor
    - * @implements {goog.result.Result}
    - * @deprecated Use {@link goog.Promise} instead - http://go/promisemigration
    - */
    -goog.result.SimpleResult = function() {
    -  /**
    -   * The current state of this Result.
    -   * @type {goog.result.Result.State}
    -   * @private
    -   */
    -  this.state_ = goog.result.Result.State.PENDING;
    -
    -  /**
    -   * The list of handlers to call when this Result is resolved.
    -   * @type {!Array<!goog.result.SimpleResult.HandlerEntry_>}
    -   * @private
    -   */
    -  this.handlers_ = [];
    -
    -  // The value_ and error_ properties are initialized in the constructor to
    -  // ensure that all SimpleResult instances share the same hidden class in
    -  // modern JavaScript engines.
    -
    -  /**
    -   * The 'value' of this Result.
    -   * @type {*}
    -   * @private
    -   */
    -  this.value_ = undefined;
    -
    -  /**
    -   * The error slug for this Result.
    -   * @type {*}
    -   * @private
    -   */
    -  this.error_ = undefined;
    -};
    -goog.Thenable.addImplementation(goog.result.SimpleResult);
    -
    -
    -/**
    - * A waiting handler entry.
    - * @typedef {{
    - *   callback: !function(goog.result.SimpleResult),
    - *   scope: Object
    - * }}
    - * @private
    - */
    -goog.result.SimpleResult.HandlerEntry_;
    -
    -
    -
    -/**
    - * Error thrown if there is an attempt to set the value or error for this result
    - * more than once.
    - *
    - * @constructor
    - * @extends {goog.debug.Error}
    - * @final
    - * @deprecated Use {@link goog.Promise} instead - http://go/promisemigration
    - */
    -goog.result.SimpleResult.StateError = function() {
    -  goog.result.SimpleResult.StateError.base(this, 'constructor',
    -      'Multiple attempts to set the state of this Result');
    -};
    -goog.inherits(goog.result.SimpleResult.StateError, goog.debug.Error);
    -
    -
    -/** @override */
    -goog.result.SimpleResult.prototype.getState = function() {
    -  return this.state_;
    -};
    -
    -
    -/** @override */
    -goog.result.SimpleResult.prototype.getValue = function() {
    -  return this.value_;
    -};
    -
    -
    -/** @override */
    -goog.result.SimpleResult.prototype.getError = function() {
    -  return this.error_;
    -};
    -
    -
    -/**
    - * Attaches handlers to be called when the value of this Result is available.
    - *
    - * @param {!function(this:T, !goog.result.SimpleResult)} handler The function
    - *     called when the value is available. The function is passed the Result
    - *     object as the only argument.
    - * @param {T=} opt_scope Optional scope for the handler.
    - * @template T
    - * @override
    - */
    -goog.result.SimpleResult.prototype.wait = function(handler, opt_scope) {
    -  if (this.isPending_()) {
    -    this.handlers_.push({
    -      callback: handler,
    -      scope: opt_scope || null
    -    });
    -  } else {
    -    handler.call(opt_scope, this);
    -  }
    -};
    -
    -
    -/**
    - * Sets the value of this Result, changing the state.
    - *
    - * @param {*} value The value to set for this Result.
    - */
    -goog.result.SimpleResult.prototype.setValue = function(value) {
    -  if (this.isPending_()) {
    -    this.value_ = value;
    -    this.state_ = goog.result.Result.State.SUCCESS;
    -    this.callHandlers_();
    -  } else if (!this.isCanceled()) {
    -    // setValue is a no-op if this Result has been canceled.
    -    throw new goog.result.SimpleResult.StateError();
    -  }
    -};
    -
    -
    -/**
    - * Sets the Result to be an error Result.
    - *
    - * @param {*=} opt_error Optional error slug to set for this Result.
    - */
    -goog.result.SimpleResult.prototype.setError = function(opt_error) {
    -  if (this.isPending_()) {
    -    this.error_ = opt_error;
    -    this.state_ = goog.result.Result.State.ERROR;
    -    this.callHandlers_();
    -  } else if (!this.isCanceled()) {
    -    // setError is a no-op if this Result has been canceled.
    -    throw new goog.result.SimpleResult.StateError();
    -  }
    -};
    -
    -
    -/**
    - * Calls the handlers registered for this Result.
    - *
    - * @private
    - */
    -goog.result.SimpleResult.prototype.callHandlers_ = function() {
    -  var handlers = this.handlers_;
    -  this.handlers_ = [];
    -  for (var n = 0; n < handlers.length; n++) {
    -    var handlerEntry = handlers[n];
    -    handlerEntry.callback.call(handlerEntry.scope, this);
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the Result is pending.
    - * @private
    - */
    -goog.result.SimpleResult.prototype.isPending_ = function() {
    -  return this.state_ == goog.result.Result.State.PENDING;
    -};
    -
    -
    -/**
    - * Cancels the Result.
    - *
    - * @return {boolean} Whether the result was canceled. It will not be canceled if
    - *    the result was already canceled or has already resolved.
    - * @override
    - */
    -goog.result.SimpleResult.prototype.cancel = function() {
    -  // cancel is a no-op if the result has been resolved.
    -  if (this.isPending_()) {
    -    this.setError(new goog.result.Result.CancelError());
    -    return true;
    -  }
    -  return false;
    -};
    -
    -
    -/** @override */
    -goog.result.SimpleResult.prototype.isCanceled = function() {
    -  return this.state_ == goog.result.Result.State.ERROR &&
    -         this.error_ instanceof goog.result.Result.CancelError;
    -};
    -
    -
    -/** @override */
    -goog.result.SimpleResult.prototype.then = function(
    -    opt_onFulfilled, opt_onRejected, opt_context) {
    -  var resolve, reject;
    -  // Copy the resolvers to outer scope, so that they are available
    -  // when the callback to wait() fires (which may be synchronous).
    -  var promise = new goog.Promise(function(res, rej) {
    -    resolve = res;
    -    reject = rej;
    -  });
    -  this.wait(function(result) {
    -    if (result.isCanceled()) {
    -      promise.cancel();
    -    } else if (result.getState() == goog.result.Result.State.SUCCESS) {
    -      resolve(result.getValue());
    -    } else if (result.getState() == goog.result.Result.State.ERROR) {
    -      reject(result.getError());
    -    }
    -  });
    -  return promise.then(opt_onFulfilled, opt_onRejected, opt_context);
    -};
    -
    -
    -/**
    - * Creates a SimpleResult that fires when the given promise resolves.
    - * Use only during migration to Promises.
    - * @param {!goog.Promise<?>} promise
    - * @return {!goog.result.Result}
    - */
    -goog.result.SimpleResult.fromPromise = function(promise) {
    -  var result = new goog.result.SimpleResult();
    -  promise.then(result.setValue, result.setError, result);
    -  return result;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/result/simpleresult_test.html b/src/database/third_party/closure-library/closure/goog/result/simpleresult_test.html
    deleted file mode 100644
    index 4c0e9faa5d6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/result/simpleresult_test.html
    +++ /dev/null
    @@ -1,375 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<title>Closure Unit Tests - goog.result.SimpleResult</title>
    -<script src="../base.js"></script>
    -<script>
    -
    -goog.require('goog.Timer');
    -goog.require('goog.Promise');
    -goog.require('goog.Thenable');
    -goog.require('goog.result');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.recordFunction');
    -goog.require('goog.testing.jsunit');
    -
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -var result, mockClock, resultCallback;
    -
    -function setUpPage() {
    -  mockClock = new goog.testing.MockClock();
    -  mockClock.install();
    -}
    -
    -function setUp() {
    -  mockClock.reset();
    -  resultCallback = new goog.testing.recordFunction();
    -  resultCallback1 = new goog.testing.recordFunction();
    -  resultCallback2 = new goog.testing.recordFunction();
    -  result = new goog.result.SimpleResult();
    -}
    -
    -function tearDown() {
    -  resultCallback = resultCallback1 = resultCallback2 = result = null;
    -}
    -
    -function tearDownPage() {
    -  mockClock.uninstall();
    -  goog.dispose(mockClock);
    -}
    -
    -function testHandlersCalledOnSuccess() {
    -  result.wait(resultCallback1);
    -  result.wait(resultCallback2);
    -
    -  assertEquals(goog.result.Result.State.PENDING, result.getState());
    -  assertEquals(0, resultCallback1.getCallCount());
    -  assertEquals(0, resultCallback2.getCallCount());
    -
    -  result.setValue(2);
    -
    -  assertEquals(goog.result.Result.State.SUCCESS, result.getState());
    -  assertEquals(2, result.getValue());
    -  assertEquals(1, resultCallback1.getCallCount());
    -  assertEquals(1, resultCallback2.getCallCount());
    -
    -  var res1 = resultCallback1.popLastCall().getArgument(0);
    -  assertObjectEquals(result, res1);
    -
    -  var res2 = resultCallback2.popLastCall().getArgument(0);
    -  assertObjectEquals(result, res2);
    -}
    -
    -function testCustomHandlerScope() {
    -  result.wait(resultCallback1);
    -  var scope = {};
    -  result.wait(resultCallback2, scope);
    -
    -  result.setValue(2);
    -
    -  assertEquals(1, resultCallback1.getCallCount());
    -  assertEquals(1, resultCallback2.getCallCount());
    -
    -  var this1 = resultCallback1.popLastCall().getThis();
    -  assertObjectEquals(goog.global, this1);
    -
    -  var this2 = resultCallback2.popLastCall().getThis();
    -  assertObjectEquals(scope, this2);
    -}
    -
    -function testHandlersCalledOnError() {
    -  result.wait(resultCallback1);
    -  result.wait(resultCallback2);
    -  assertEquals(goog.result.Result.State.PENDING, result.getState());
    -
    -  var error = "Network Error";
    -  result.setError(error);
    -
    -  assertEquals(goog.result.Result.State.ERROR, result.getState());
    -  assertEquals(error, result.getError());
    -  assertEquals(1, resultCallback1.getCallCount());
    -  assertEquals(1, resultCallback2.getCallCount());
    -
    -  var res1 = resultCallback1.popLastCall().getArgument(0);
    -  assertObjectEquals(result, res1);
    -  var res2 = resultCallback2.popLastCall().getArgument(0);
    -  assertObjectEquals(result, res2);
    -}
    -
    -function testAttachingHandlerOnSuccessfulResult() {
    -  result.setValue(2);
    -  assertEquals(goog.result.Result.State.SUCCESS, result.getState());
    -  assertEquals(2, result.getValue());
    -  // resultCallback should be called immediately on a resolved Result
    -  assertEquals(0, resultCallback.getCallCount());
    -
    -  result.wait(resultCallback);
    -
    -  assertEquals(1, resultCallback.getCallCount());
    -  var res = resultCallback.popLastCall().getArgument(0);
    -  assertEquals(result, res);
    -}
    -
    -function testAttachingHandlerOnErrorResult() {
    -  var error = { code: -1, errorString: "Invalid JSON" };
    -  result.setError(error);
    -  assertEquals(goog.result.Result.State.ERROR, result.getState());
    -  assertEquals(error, result.getError());
    -  // resultCallback should be called immediately on a resolved Result
    -  assertEquals(0, resultCallback.getCallCount());
    -
    -  result.wait(resultCallback);
    -
    -  assertEquals(1, resultCallback.getCallCount());
    -  var res = resultCallback.popLastCall().getArgument(0);
    -  assertEquals(result, res);
    -}
    -
    -function testExceptionThrownOnMultipleSuccessfulResolutionAttempts() {
    -  result.setValue(1);
    -  assertEquals(goog.result.Result.State.SUCCESS, result.getState());
    -  assertEquals(1, result.getValue());
    -
    -  // Try to set the value again
    -  var e = assertThrows(goog.bind(result.setValue, result, 3));
    -  assertTrue(e instanceof goog.result.SimpleResult.StateError);
    -}
    -
    -function testExceptionThrownOnMultipleErrorResolutionAttempts() {
    -  assertEquals(goog.result.Result.State.PENDING, result.getState());
    -
    -  result.setError(5);
    -
    -  assertEquals(goog.result.Result.State.ERROR, result.getState());
    -  assertEquals(5, result.getError());
    -  // Try to set error again
    -  var e = assertThrows(goog.bind(result.setError, result, 4));
    -  assertTrue(e instanceof goog.result.SimpleResult.StateError);
    -}
    -
    -function testExceptionThrownOnSuccessThenErrorResolutionAttempt() {
    -  assertEquals(goog.result.Result.State.PENDING, result.getState());
    -
    -  result.setValue(1);
    -
    -  assertEquals(goog.result.Result.State.SUCCESS, result.getState());
    -  assertEquals(1, result.getValue());
    -
    -  // Try to set error after setting value
    -  var e = assertThrows(goog.bind(result.setError, result, 3));
    -  assertTrue(e instanceof goog.result.SimpleResult.StateError);
    -}
    -
    -function testExceptionThrownOnErrorThenSuccessResolutionAttempt() {
    -  assertEquals(goog.result.Result.State.PENDING, result.getState());
    -
    -  var error = "fail";
    -  result.setError(error);
    -
    -  assertEquals(goog.result.Result.State.ERROR, result.getState());
    -  assertEquals(error, result.getError());
    -  // Try to set value after setting error
    -  var e = assertThrows(goog.bind(result.setValue, result, 1));
    -  assertTrue(e instanceof goog.result.SimpleResult.StateError);
    -}
    -
    -function testSuccessfulAsyncResolution() {
    -  result.wait(resultCallback);
    -  assertEquals(goog.result.Result.State.PENDING, result.getState());
    -
    -  goog.Timer.callOnce(function() {
    -    result.setValue(1);
    -  });
    -  mockClock.tick();
    -
    -  assertEquals(1, resultCallback.getCallCount());
    -
    -  var res = resultCallback.popLastCall().getArgument(0);
    -  assertEquals(goog.result.Result.State.SUCCESS, res.getState());
    -  assertEquals(1, res.getValue());
    -}
    -
    -function testErrorAsyncResolution() {
    -  result.wait(resultCallback);
    -  assertEquals(goog.result.Result.State.PENDING, result.getState());
    -
    -  var error = 'Network failure';
    -  goog.Timer.callOnce(function() {
    -    result.setError(error);
    -  });
    -  mockClock.tick();
    -
    -  assertEquals(1, resultCallback.getCallCount());
    -  var res = resultCallback.popLastCall().getArgument(0);
    -  assertEquals(goog.result.Result.State.ERROR, res.getState());
    -  assertEquals(error, res.getError());
    -}
    -
    -function testCancelStateAndReturn() {
    -  assertFalse(result.isCanceled());
    -  var canceled = result.cancel();
    -  assertTrue(result.isCanceled());
    -  assertEquals(goog.result.Result.State.ERROR, result.getState());
    -  assertTrue(result.getError() instanceof goog.result.Result.CancelError);
    -  assertTrue(canceled);
    -}
    -
    -function testErrorHandlersFireOnCancel() {
    -  result.wait(resultCallback);
    -  result.cancel();
    -
    -  assertEquals(1, resultCallback.getCallCount());
    -  var lastCall = resultCallback.popLastCall();
    -  var res = lastCall.getArgument(0);
    -  assertEquals(goog.result.Result.State.ERROR, res.getState());
    -  assertTrue(res.getError() instanceof goog.result.Result.CancelError);
    -}
    -
    -function testCancelAfterSetValue() {
    -  // cancel after setValue/setError => no-op
    -  result.wait(resultCallback);
    -  result.setValue(1);
    -
    -  assertEquals(goog.result.Result.State.SUCCESS, result.getState());
    -  assertEquals(1, result.getValue());
    -  assertEquals(1, resultCallback.getCallCount());
    -
    -  result.cancel();
    -
    -  assertEquals(goog.result.Result.State.SUCCESS, result.getState());
    -  assertEquals(1, result.getValue());
    -  assertEquals(1, resultCallback.getCallCount());
    -}
    -
    -function testSetValueAfterCancel() {
    -  // setValue/setError after cancel => no-op
    -  result.wait(resultCallback);
    -
    -  result.cancel();
    -  assertTrue(result.isCanceled());
    -  assertTrue(result.getError() instanceof goog.result.Result.CancelError);
    -
    -  result.setValue(1);
    -  assertTrue(result.isCanceled());
    -  assertTrue(result.getError() instanceof goog.result.Result.CancelError);
    -
    -  result.setError(3);
    -  assertTrue(result.isCanceled());
    -  assertTrue(result.getError() instanceof goog.result.Result.CancelError);
    -}
    -
    -function testFromResolvedPromise() {
    -  var promise = goog.Promise.resolve('resolved');
    -  result = goog.result.SimpleResult.fromPromise(promise);
    -  assertEquals(goog.result.Result.State.PENDING, result.getState());
    -  mockClock.tick();
    -  assertEquals(goog.result.Result.State.SUCCESS, result.getState());
    -  assertEquals('resolved', result.getValue());
    -  assertEquals(undefined, result.getError());
    -}
    -
    -function testFromRejectedPromise() {
    -  var promise = goog.Promise.reject('rejected');
    -  result = goog.result.SimpleResult.fromPromise(promise);
    -  assertEquals(goog.result.Result.State.PENDING, result.getState());
    -  mockClock.tick();
    -  assertEquals(goog.result.Result.State.ERROR, result.getState());
    -  assertEquals(undefined, result.getValue());
    -  assertEquals('rejected', result.getError());
    -}
    -
    -function testThen() {
    -  var value1, value2;
    -  result.then(function(val1) {
    -    return value1 = val1;
    -  }).then(function(val2) {
    -    value2 = val2;
    -  });
    -  result.setValue('done');
    -  assertUndefined(value1);
    -  assertUndefined(value2);
    -  mockClock.tick();
    -  assertEquals('done', value1);
    -  assertEquals('done', value2);
    -}
    -
    -function testThen_reject() {
    -  var value, reason;
    -  result.then(
    -    function(v) { value = v; },
    -    function(r) { reason = r; });
    -  result.setError(new Error('oops'));
    -  assertUndefined(value);
    -  mockClock.tick();
    -  assertUndefined(value);
    -  assertEquals('oops', reason.message);
    -}
    -
    -function testPromiseAll() {
    -  var promise = goog.Promise.resolve('promise');
    -  goog.Promise.all([result, promise]).then(function(values) {
    -    assertEquals(2, values.length);
    -    assertEquals('result', values[0]);
    -    assertEquals('promise', values[1]);
    -  });
    -  result.setValue('result');
    -  mockClock.tick();
    -}
    -
    -function testResolvingPromiseBlocksResult() {
    -  var value;
    -  goog.Promise.resolve('promise').then(function(value) {
    -    result.setValue(value);
    -  });
    -  result.wait(function(r) {
    -    value = r.getValue();
    -  });
    -  assertUndefined(value);
    -  mockClock.tick();
    -  assertEquals('promise', value);
    -}
    -
    -function testRejectingPromiseBlocksResult() {
    -  var err;
    -  goog.Promise.reject(new Error('oops')).then(
    -    undefined /* opt_onResolved */,
    -    function(reason) {
    -      result.setError(reason);
    -    });
    -  result.wait(function(r) {
    -    err = r.getError();
    -  });
    -  assertUndefined(err);
    -  mockClock.tick();
    -  assertEquals('oops', err.message);
    -}
    -
    -function testPromiseFromCanceledResult() {
    -  var reason;
    -  result.cancel();
    -  result.then(
    -    undefined /* opt_onResolved */,
    -    function(r) {
    -      reason = r;
    -    });
    -  mockClock.tick();
    -  assertTrue(reason instanceof goog.Promise.CancellationError);
    -}
    -
    -function testThenableInterface() {
    -  assertTrue(goog.Thenable.isImplementedBy(result));
    -}
    -
    -</script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/result/transform_test.html b/src/database/third_party/closure-library/closure/goog/result/transform_test.html
    deleted file mode 100644
    index f21281e0330..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/result/transform_test.html
    +++ /dev/null
    @@ -1,153 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<title>Closure Unit Tests - goog.result.transform</title>
    -<script src="../base.js"></script>
    -<script>
    -
    -goog.require('goog.Timer');
    -goog.require('goog.result.SimpleResult');
    -goog.require('goog.result');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -var result, resultCallback, multiplyResult, mockClock;
    -
    -function setUpPage() {
    -  mockClock = new goog.testing.MockClock();
    -  mockClock.install();
    -}
    -
    -function setUp() {
    -  mockClock.reset();
    -  result = new goog.result.SimpleResult();
    -  resultCallback = new goog.testing.recordFunction();
    -  multiplyResult = goog.testing.recordFunction(function(value) {
    -      return value * 2;
    -    });
    -}
    -
    -function tearDown() {
    -  result = multiplyResult = null;
    -}
    -
    -function tearDownPage() {
    -  mockClock.uninstall();
    -  goog.dispose(mockClock);
    -}
    -
    -function testTransformWhenResultSuccess() {
    -  var transformedResult = goog.result.transform(result, multiplyResult);
    -  goog.result.wait(transformedResult, resultCallback);
    -
    -  assertEquals(goog.result.Result.State.PENDING, result.getState());
    -  result.setValue(1);
    -  assertTransformerCall(multiplyResult, 1);
    -  assertSuccessCall(resultCallback, transformedResult, 2);
    -}
    -
    -function testTransformWhenResultSuccessAsync() {
    -  var transformedResult = goog.result.transform(result, multiplyResult);
    -  goog.result.wait(transformedResult, resultCallback);
    -
    -  goog.Timer.callOnce(function() {
    -    result.setValue(1);
    -  });
    -
    -  assertEquals(goog.result.Result.State.PENDING, result.getState());
    -  mockClock.tick();
    -  assertTransformerCall(multiplyResult, 1);
    -  assertSuccessCall(resultCallback, transformedResult, 2);
    -}
    -
    -function testTransformWhenResultError() {
    -  var transformedResult = goog.result.transform(result, multiplyResult);
    -  goog.result.wait(transformedResult, resultCallback);
    -
    -  assertEquals(goog.result.Result.State.PENDING, result.getState());
    -  result.setError(4);
    -  assertNoCall(multiplyResult);
    -  assertErrorCall(resultCallback, transformedResult, 4);
    -}
    -
    -function testTransformWhenResultErrorAsync() {
    -  var transformedResult = goog.result.transform(result, multiplyResult);
    -
    -  goog.result.wait(transformedResult, resultCallback);
    -
    -  goog.Timer.callOnce(function() {
    -    result.setError(5);
    -  });
    -
    -  assertEquals(goog.result.Result.State.PENDING, result.getState());
    -  mockClock.tick();
    -  assertNoCall(multiplyResult);
    -  assertErrorCall(resultCallback, transformedResult, 5);
    -}
    -
    -function testCancelParentResults() {
    -  var transformedResult = goog.result.transform(result, multiplyResult);
    -  goog.result.wait(transformedResult, resultCallback);
    -
    -  goog.result.cancelParentResults(transformedResult);
    -
    -  assertTrue(result.isCanceled());
    -  result.setValue(1);
    -  assertNoCall(multiplyResult);
    -}
    -
    -function testDoubleTransformCancel() {
    -  var step1Result = goog.result.transform(result, multiplyResult);
    -  var step2Result = goog.result.transform(step1Result, multiplyResult);
    -
    -  goog.result.cancelParentResults(step2Result);
    -
    -  assertFalse(result.isCanceled());
    -  assertTrue(step1Result.isCanceled());
    -  assertTrue(step2Result.isCanceled());
    -}
    -
    -function assertSuccessCall(recordFunction, result, value) {
    -  assertEquals(1, recordFunction.getCallCount());
    -
    -  var res = recordFunction.popLastCall().getArgument(0);
    -  assertEquals(result, res);
    -  assertEquals(goog.result.Result.State.SUCCESS, res.getState());
    -  assertEquals(value, res.getValue());
    -}
    -
    -function assertErrorCall(recordFunction, result, value) {
    -  assertEquals(1, recordFunction.getCallCount());
    -
    -  var res = recordFunction.popLastCall().getArgument(0);
    -  assertEquals(result, res);
    -  assertEquals(goog.result.Result.State.ERROR, res.getState());
    -  assertEquals(value, res.getError());
    -}
    -
    -function assertNoCall(recordFunction) {
    -  assertEquals(0, recordFunction.getCallCount());
    -}
    -
    -function assertTransformerCall(recordFunction, value) {
    -  assertEquals(1, recordFunction.getCallCount());
    -
    -  var argValue = recordFunction.popLastCall().getArgument(0);
    -  assertEquals(value, argValue);
    -}
    -
    -</script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/result/wait_test.html b/src/database/third_party/closure-library/closure/goog/result/wait_test.html
    deleted file mode 100644
    index fdba6dcae6f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/result/wait_test.html
    +++ /dev/null
    @@ -1,211 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<title>Closure Unit Tests - goog.result.wait</title>
    -<script src="../base.js"></script>
    -<script>
    -
    -goog.require('goog.Timer');
    -goog.require('goog.result.SimpleResult');
    -goog.require('goog.result');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -var result, waitCallback, waitOnSuccessCallback, waitOnErrorCallback;
    -
    -var mockClock, propertyReplacer;
    -
    -function setUpPage() {
    -  mockClock = new goog.testing.MockClock();
    -  mockClock.install();
    -}
    -
    -function setUp() {
    -  mockClock.reset();
    -  result = new goog.result.SimpleResult();
    -  propertyReplacer = new goog.testing.PropertyReplacer();
    -  waitCallback = new goog.testing.recordFunction();
    -  waitOnSuccessCallback = new goog.testing.recordFunction();
    -  waitOnErrorCallback = new goog.testing.recordFunction();
    -}
    -
    -function tearDown() {
    -  result = waitCallback = waitOnSuccessCallback = waitOnErrorCallback = null;
    -  propertyReplacer.reset();
    -}
    -
    -function tearDownPage() {
    -  mockClock.uninstall();
    -}
    -
    -function testSynchronousSuccess() {
    -  assertEquals(goog.result.Result.State.PENDING, result.getState());
    -  assertUndefined(result.getValue());
    -
    -  goog.result.wait(result, waitCallback);
    -  goog.result.waitOnSuccess(result, waitOnSuccessCallback);
    -  goog.result.waitOnError(result, waitOnErrorCallback);
    -
    -  result.setValue(1);
    -
    -  assertEquals(goog.result.Result.State.SUCCESS, result.getState());
    -  assertEquals(1, result.getValue());
    -
    -  assertWaitCall(waitCallback, result);
    -  assertCall(waitOnSuccessCallback, 1, result);
    -  assertNoCall(waitOnErrorCallback);
    -}
    -
    -function testAsynchronousSuccess() {
    -  goog.result.wait(result, waitCallback);
    -  goog.result.waitOnSuccess(result, waitOnSuccessCallback);
    -  goog.result.waitOnError(result, waitOnErrorCallback);
    -
    -  goog.Timer.callOnce(function() {
    -    result.setValue(1);
    -  });
    -
    -  assertUndefined(result.getValue());
    -  assertEquals(goog.result.Result.State.PENDING, result.getState());
    -
    -  assertNoCall(waitCallback);
    -  assertNoCall(waitOnSuccessCallback);
    -  assertNoCall(waitOnErrorCallback);
    -
    -  mockClock.tick();
    -
    -  assertEquals(goog.result.Result.State.SUCCESS, result.getState());
    -  assertEquals(1, result.getValue());
    -
    -  assertWaitCall(waitCallback, result);
    -  assertCall(waitOnSuccessCallback, 1, result);
    -  assertNoCall(waitOnErrorCallback);
    -}
    -
    -function testSynchronousError() {
    -  assertEquals(goog.result.Result.State.PENDING, result.getState());
    -  assertUndefined(result.getValue());
    -
    -  goog.result.wait(result, waitCallback);
    -  goog.result.waitOnSuccess(result, waitOnSuccessCallback);
    -  goog.result.waitOnError(result, waitOnErrorCallback);
    -
    -  result.setError();
    -
    -  assertEquals(goog.result.Result.State.ERROR, result.getState());
    -  assertUndefined(result.getValue());
    -
    -  assertWaitCall(waitCallback, result);
    -  assertNoCall(waitOnSuccessCallback);
    -  assertCall(waitOnErrorCallback, undefined, result);
    -}
    -
    -function testAsynchronousError() {
    -  goog.result.wait(result, waitCallback);
    -  goog.result.waitOnSuccess(result, waitOnSuccessCallback);
    -  goog.result.waitOnError(result, waitOnErrorCallback);
    -
    -  goog.Timer.callOnce(function() {
    -    result.setError();
    -  });
    -
    -  assertEquals(goog.result.Result.State.PENDING, result.getState());
    -  assertUndefined(result.getValue());
    -
    -  assertNoCall(waitCallback);
    -  assertNoCall(waitOnSuccessCallback);
    -  assertNoCall(waitOnErrorCallback);
    -
    -  mockClock.tick();
    -
    -  assertEquals(goog.result.Result.State.ERROR, result.getState());
    -  assertUndefined(result.getValue());
    -
    -  assertWaitCall(waitCallback, result);
    -  assertNoCall(waitOnSuccessCallback);
    -  assertCall(waitOnErrorCallback, undefined, result);
    -}
    -
    -function testCustomScope() {
    -  var scope = {};
    -  goog.result.wait(result, waitCallback, scope);
    -  result.setValue(1);
    -  assertEquals(scope, waitCallback.popLastCall().getThis());
    -}
    -
    -function testDefaultScope() {
    -  goog.result.wait(result, waitCallback);
    -  result.setValue(1);
    -  assertEquals(goog.global, waitCallback.popLastCall().getThis());
    -}
    -
    -function testOnSuccessScope() {
    -  var scope = {};
    -  goog.result.waitOnSuccess(result, waitOnSuccessCallback, scope);
    -  result.setValue(1);
    -  assertCall(waitOnSuccessCallback, 1, result, scope);
    -}
    -
    -function testOnErrorScope() {
    -  var scope = {};
    -  goog.result.waitOnError(result, waitOnErrorCallback, scope);
    -  result.setError();
    -  assertCall(waitOnErrorCallback, undefined, result, scope);
    -}
    -
    -/**
    - * Assert that a callback function stubbed out with goog.recordFunction was
    - * called with the expected arguments by goog.result.waitOnSuccess/Error.
    - * @param {Function} recordedFunction The callback function.
    - * @param {?} value The value stored in the result.
    - * @param {!goog.result.Result} result The result that was resolved to SUCCESS
    - *     or ERROR.
    - * @param {Object=} opt_scope Optional scope that the test function should be
    - *     called in. By default, it is goog.global.
    - */
    -function assertCall(recordedFunction, value, result, opt_scope) {
    -  var scope = opt_scope || goog.global;
    -  assertEquals(1, recordedFunction.getCallCount());
    -  var call = recordedFunction.popLastCall();
    -  assertEquals(2, call.getArguments().length);
    -  assertEquals(value, call.getArgument(0));
    -  assertEquals(result, call.getArgument(1));
    -  assertEquals(scope, call.getThis());
    -}
    -
    -/**
    - * Assert that a callback function stubbed out with goog.recordFunction was
    - * called with the expected arguments by goog.result.wait.
    - * @param {Function} recordedFunction The callback function.
    - * @param {!goog.result.Result} result The result that was resolved to SUCCESS
    - *     or ERROR.
    - * @param {Object=} opt_scope Optional scope that the test function should be
    - *     called in. By default, it is goog.global.
    - */
    -function assertWaitCall(recordedFunction, result, opt_scope) {
    -  var scope = opt_scope || goog.global;
    -  assertEquals(1, recordedFunction.getCallCount());
    -  var call = recordedFunction.popLastCall();
    -  assertEquals(1, call.getArguments().length);
    -  assertEquals(result, call.getArgument(0));
    -  assertEquals(scope, call.getThis());
    -}
    -
    -function assertNoCall(recordedFunction) {
    -  assertEquals(0, recordedFunction.getCallCount());
    -}
    -</script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/soy/data.js b/src/database/third_party/closure-library/closure/goog/soy/data.js
    deleted file mode 100644
    index f2b00d2a417..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/soy/data.js
    +++ /dev/null
    @@ -1,160 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Soy data primitives.
    - *
    - * The goal is to encompass data types used by Soy, especially to mark content
    - * as known to be "safe".
    - *
    - * @author gboyer@google.com (Garrett Boyer)
    - */
    -
    -goog.provide('goog.soy.data.SanitizedContent');
    -goog.provide('goog.soy.data.SanitizedContentKind');
    -
    -goog.require('goog.html.SafeHtml');
    -goog.require('goog.html.uncheckedconversions');
    -goog.require('goog.string.Const');
    -
    -
    -/**
    - * A type of textual content.
    - *
    - * This is an enum of type Object so that these values are unforgeable.
    - *
    - * @enum {!Object}
    - */
    -goog.soy.data.SanitizedContentKind = {
    -
    -  /**
    -   * A snippet of HTML that does not start or end inside a tag, comment, entity,
    -   * or DOCTYPE; and that does not contain any executable code
    -   * (JS, {@code <object>}s, etc.) from a different trust domain.
    -   */
    -  HTML: goog.DEBUG ? {sanitizedContentKindHtml: true} : {},
    -
    -  /**
    -   * Executable Javascript code or expression, safe for insertion in a
    -   * script-tag or event handler context, known to be free of any
    -   * attacker-controlled scripts. This can either be side-effect-free
    -   * Javascript (such as JSON) or Javascript that's entirely under Google's
    -   * control.
    -   */
    -  JS: goog.DEBUG ? {sanitizedContentJsChars: true} : {},
    -
    -  /** A properly encoded portion of a URI. */
    -  URI: goog.DEBUG ? {sanitizedContentUri: true} : {},
    -
    -  /**
    -   * Repeated attribute names and values. For example,
    -   * {@code dir="ltr" foo="bar" onclick="trustedFunction()" checked}.
    -   */
    -  ATTRIBUTES: goog.DEBUG ? {sanitizedContentHtmlAttribute: true} : {},
    -
    -  // TODO: Consider separating rules, declarations, and values into
    -  // separate types, but for simplicity, we'll treat explicitly blessed
    -  // SanitizedContent as allowed in all of these contexts.
    -  /**
    -   * A CSS3 declaration, property, value or group of semicolon separated
    -   * declarations.
    -   */
    -  CSS: goog.DEBUG ? {sanitizedContentCss: true} : {},
    -
    -  /**
    -   * Unsanitized plain-text content.
    -   *
    -   * This is effectively the "null" entry of this enum, and is sometimes used
    -   * to explicitly mark content that should never be used unescaped. Since any
    -   * string is safe to use as text, being of ContentKind.TEXT makes no
    -   * guarantees about its safety in any other context such as HTML.
    -   */
    -  TEXT: goog.DEBUG ? {sanitizedContentKindText: true} : {}
    -};
    -
    -
    -
    -/**
    - * A string-like object that carries a content-type and a content direction.
    - *
    - * IMPORTANT! Do not create these directly, nor instantiate the subclasses.
    - * Instead, use a trusted, centrally reviewed library as endorsed by your team
    - * to generate these objects. Otherwise, you risk accidentally creating
    - * SanitizedContent that is attacker-controlled and gets evaluated unescaped in
    - * templates.
    - *
    - * @constructor
    - */
    -goog.soy.data.SanitizedContent = function() {
    -  throw Error('Do not instantiate directly');
    -};
    -
    -
    -/**
    - * The context in which this content is safe from XSS attacks.
    - * @type {goog.soy.data.SanitizedContentKind}
    - */
    -goog.soy.data.SanitizedContent.prototype.contentKind;
    -
    -
    -/**
    - * The content's direction; null if unknown and thus to be estimated when
    - * necessary.
    - * @type {?goog.i18n.bidi.Dir}
    - */
    -goog.soy.data.SanitizedContent.prototype.contentDir = null;
    -
    -
    -/**
    - * The already-safe content.
    - * @protected {string}
    - */
    -goog.soy.data.SanitizedContent.prototype.content;
    -
    -
    -/**
    - * Gets the already-safe content.
    - * @return {string}
    - */
    -goog.soy.data.SanitizedContent.prototype.getContent = function() {
    -  return this.content;
    -};
    -
    -
    -/** @override */
    -goog.soy.data.SanitizedContent.prototype.toString = function() {
    -  return this.content;
    -};
    -
    -
    -/**
    - * Converts sanitized content of kind TEXT or HTML into SafeHtml. HTML content
    - * is converted without modification, while text content is HTML-escaped.
    - * @return {!goog.html.SafeHtml}
    - * @throws {Error} when the content kind is not TEXT or HTML.
    - */
    -goog.soy.data.SanitizedContent.prototype.toSafeHtml = function() {
    -  if (this.contentKind === goog.soy.data.SanitizedContentKind.TEXT) {
    -    return goog.html.SafeHtml.htmlEscape(this.toString());
    -  }
    -  if (this.contentKind !== goog.soy.data.SanitizedContentKind.HTML) {
    -    throw Error('Sanitized content was not of kind TEXT or HTML.');
    -  }
    -  return goog.html.uncheckedconversions.
    -      safeHtmlFromStringKnownToSatisfyTypeContract(
    -          goog.string.Const.from(
    -              'Soy SanitizedContent of kind HTML produces ' +
    -                  'SafeHtml-contract-compliant value.'),
    -          this.toString(), this.contentDir);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/soy/data_test.html b/src/database/third_party/closure-library/closure/goog/soy/data_test.html
    deleted file mode 100644
    index 0f1ac733185..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/soy/data_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.soy.data
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.soy.dataTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/soy/data_test.js b/src/database/third_party/closure-library/closure/goog/soy/data_test.js
    deleted file mode 100644
    index af14ae6e311..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/soy/data_test.js
    +++ /dev/null
    @@ -1,33 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.soy.dataTest');
    -goog.setTestOnly('goog.soy.dataTest');
    -
    -goog.require('goog.html.SafeHtml');
    -/** @suppress {extraRequire} */
    -goog.require('goog.soy.testHelper');
    -goog.require('goog.testing.jsunit');
    -
    -
    -function testToSafeHtml() {
    -  var html;
    -
    -  html = example.unsanitizedTextTemplate().toSafeHtml();
    -  assertEquals('I &lt;3 Puppies &amp; Kittens',
    -      goog.html.SafeHtml.unwrap(html));
    -
    -  html = example.sanitizedHtmlTemplate().toSafeHtml();
    -  assertEquals('Hello <b>World</b>', goog.html.SafeHtml.unwrap(html));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/soy/renderer.js b/src/database/third_party/closure-library/closure/goog/soy/renderer.js
    deleted file mode 100644
    index 359be20c022..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/soy/renderer.js
    +++ /dev/null
    @@ -1,314 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides a soy renderer that allows registration of
    - * injected data ("globals") that will be passed into the rendered
    - * templates.
    - *
    - * There is also an interface {@link goog.soy.InjectedDataSupplier} that
    - * user should implement to provide the injected data for a specific
    - * application. The injected data format is a JavaScript object:
    - * <pre>
    - * {'dataKey': 'value', 'otherDataKey': 'otherValue'}
    - * </pre>
    - *
    - * To use injected data, you need to enable the soy-to-js compiler
    - * option {@code --isUsingIjData}. The injected data can then be
    - * referred to in any soy templates as part of a magic "ij"
    - * parameter. For example, {@code $ij.dataKey} will evaluate to
    - * 'value' with the above injected data.
    - *
    - * @author henrywong@google.com (Henry Wong)
    - * @author chrishenry@google.com (Chris Henry)
    - */
    -
    -goog.provide('goog.soy.InjectedDataSupplier');
    -goog.provide('goog.soy.Renderer');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.soy');
    -goog.require('goog.soy.data.SanitizedContent');
    -goog.require('goog.soy.data.SanitizedContentKind');
    -
    -
    -
    -/**
    - * Creates a new soy renderer. Note that the renderer will only be
    - * guaranteed to work correctly within the document scope provided in
    - * the DOM helper.
    - *
    - * @param {goog.soy.InjectedDataSupplier=} opt_injectedDataSupplier A supplier
    - *     that provides an injected data.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper;
    - *     defaults to that provided by {@code goog.dom.getDomHelper()}.
    - * @constructor
    - */
    -goog.soy.Renderer = function(opt_injectedDataSupplier, opt_domHelper) {
    -  /**
    -   * @type {goog.dom.DomHelper}
    -   * @private
    -   */
    -  this.dom_ = opt_domHelper || goog.dom.getDomHelper();
    -
    -  /**
    -   * @type {goog.soy.InjectedDataSupplier}
    -   * @private
    -   */
    -  this.supplier_ = opt_injectedDataSupplier || null;
    -
    -  /**
    -   * Map from template name to the data used to render that template.
    -   * @type {!goog.soy.Renderer.SavedTemplateRender}
    -   * @private
    -   */
    -  this.savedTemplateRenders_ = [];
    -};
    -
    -
    -/**
    - * @typedef {Array<{template: string, data: Object, ijData: Object}>}
    - */
    -goog.soy.Renderer.SavedTemplateRender;
    -
    -
    -/**
    - * Renders a Soy template into a single node or a document fragment.
    - * Delegates to {@code goog.soy.renderAsFragment}.
    - *
    - * @param {null|function(ARG_TYPES, null=, Object<string, *>=):*} template
    - *     The Soy template defining the element's content.
    - * @param {ARG_TYPES=} opt_templateData The data for the template.
    - * @return {!Node} The resulting node or document fragment.
    - * @template ARG_TYPES
    - */
    -goog.soy.Renderer.prototype.renderAsFragment = function(template,
    -                                                        opt_templateData) {
    -  this.saveTemplateRender_(template, opt_templateData);
    -  var node = goog.soy.renderAsFragment(template, opt_templateData,
    -                                       this.getInjectedData_(), this.dom_);
    -  this.handleRender(node);
    -  return node;
    -};
    -
    -
    -/**
    - * Renders a Soy template into a single node. If the rendered HTML
    - * string represents a single node, then that node is returned.
    - * Otherwise, a DIV element is returned containing the rendered nodes.
    - * Delegates to {@code goog.soy.renderAsElement}.
    - *
    - * @param {null|function(ARG_TYPES, null=, Object<string, *>=):*} template
    - *     The Soy template defining the element's content.
    - * @param {ARG_TYPES=} opt_templateData The data for the template.
    - * @return {!Element} Rendered template contents, wrapped in a parent DIV
    - *     element if necessary.
    - * @template ARG_TYPES
    - */
    -goog.soy.Renderer.prototype.renderAsElement = function(template,
    -                                                       opt_templateData) {
    -  this.saveTemplateRender_(template, opt_templateData);
    -  var element = goog.soy.renderAsElement(template, opt_templateData,
    -                                         this.getInjectedData_(), this.dom_);
    -  this.handleRender(element);
    -  return element;
    -};
    -
    -
    -/**
    - * Renders a Soy template and then set the output string as the
    - * innerHTML of the given element. Delegates to {@code goog.soy.renderElement}.
    - *
    - * @param {Element} element The element whose content we are rendering.
    - * @param {null|function(ARG_TYPES, null=, Object<string, *>=):*} template
    - *     The Soy template defining the element's content.
    - * @param {ARG_TYPES=} opt_templateData The data for the template.
    - * @template ARG_TYPES
    - */
    -goog.soy.Renderer.prototype.renderElement = function(element, template,
    -                                                     opt_templateData) {
    -  this.saveTemplateRender_(template, opt_templateData);
    -  goog.soy.renderElement(
    -      element, template, opt_templateData, this.getInjectedData_());
    -  this.handleRender(element);
    -};
    -
    -
    -/**
    - * Renders a Soy template and returns the output string.
    - * If the template is strict, it must be of kind HTML. To render strict
    - * templates of other kinds, use {@code renderText} (for {@code kind="text"}) or
    - * {@code renderStrict}.
    - *
    - * @param {null|function(ARG_TYPES, null=, Object<string, *>=):*} template
    - *     The Soy template to render.
    - * @param {ARG_TYPES=} opt_templateData The data for the template.
    - * @return {string} The return value of rendering the template directly.
    - * @template ARG_TYPES
    - */
    -goog.soy.Renderer.prototype.render = function(template, opt_templateData) {
    -  var result = template(
    -      opt_templateData || {}, undefined, this.getInjectedData_());
    -  goog.asserts.assert(!(result instanceof goog.soy.data.SanitizedContent) ||
    -      result.contentKind === goog.soy.data.SanitizedContentKind.HTML,
    -      'render was called with a strict template of kind other than "html"' +
    -          ' (consider using renderText or renderStrict)');
    -  this.saveTemplateRender_(template, opt_templateData);
    -  this.handleRender();
    -  return String(result);
    -};
    -
    -
    -/**
    - * Renders a strict Soy template of kind="text" and returns the output string.
    - * It is an error to use renderText on non-strict templates, or strict templates
    - * of kinds other than "text".
    - *
    - * @param {null|function(ARG_TYPES, null=, Object<string, *>=):
    - *     goog.soy.data.SanitizedContent} template The Soy template to render.
    - * @param {ARG_TYPES=} opt_templateData The data for the template.
    - * @return {string} The return value of rendering the template directly.
    - * @template ARG_TYPES
    - */
    -goog.soy.Renderer.prototype.renderText = function(template, opt_templateData) {
    -  var result = template(
    -      opt_templateData || {}, undefined, this.getInjectedData_());
    -  goog.asserts.assertInstanceof(result, goog.soy.data.SanitizedContent,
    -      'renderText cannot be called on a non-strict soy template');
    -  goog.asserts.assert(
    -      result.contentKind === goog.soy.data.SanitizedContentKind.TEXT,
    -      'renderText was called with a template of kind other than "text"');
    -  this.saveTemplateRender_(template, opt_templateData);
    -  this.handleRender();
    -  return String(result);
    -};
    -
    -
    -/**
    - * Renders a strict Soy template and returns the output SanitizedContent object.
    - *
    - * @param {null|function(ARG_TYPES, null=, Object<string, *>=):RETURN_TYPE}
    - *     template The Soy template to render.
    - * @param {ARG_TYPES=} opt_templateData The data for the template.
    - * @param {goog.soy.data.SanitizedContentKind=} opt_kind The output kind to
    - *     assert. If null, the template must be of kind="html" (i.e., opt_kind
    - *     defaults to goog.soy.data.SanitizedContentKind.HTML).
    - * @return {RETURN_TYPE} The SanitizedContent object. This return type is
    - *     generic based on the return type of the template, such as
    - *     soy.SanitizedHtml.
    - * @template ARG_TYPES, RETURN_TYPE
    - */
    -goog.soy.Renderer.prototype.renderStrict = function(
    -    template, opt_templateData, opt_kind) {
    -  var result = template(
    -      opt_templateData || {}, undefined, this.getInjectedData_());
    -  goog.asserts.assertInstanceof(result, goog.soy.data.SanitizedContent,
    -      'renderStrict cannot be called on a non-strict soy template');
    -  goog.asserts.assert(
    -      result.contentKind ===
    -          (opt_kind || goog.soy.data.SanitizedContentKind.HTML),
    -      'renderStrict was called with the wrong kind of template');
    -  this.saveTemplateRender_(template, opt_templateData);
    -  this.handleRender();
    -  return result;
    -};
    -
    -
    -/**
    - * Renders a strict Soy template of kind="html" and returns the result as
    - * a goog.html.SafeHtml object.
    - *
    - * Rendering a template that is not a strict template of kind="html" results in
    - * a runtime error.
    - *
    - * @param {null|function(ARG_TYPES, null=, Object<string, *>=):
    - *     goog.soy.data.SanitizedContent} template The Soy template to render.
    - * @param {ARG_TYPES=} opt_templateData The data for the template.
    - * @return {!goog.html.SafeHtml}
    - * @template ARG_TYPES
    - */
    -goog.soy.Renderer.prototype.renderSafeHtml = function(
    -    template, opt_templateData) {
    -  var result = this.renderStrict(template, opt_templateData);
    -  return result.toSafeHtml();
    -};
    -
    -
    -/**
    - * @return {!goog.soy.Renderer.SavedTemplateRender} Saved template data for
    - *     the renders that have happened so far.
    - */
    -goog.soy.Renderer.prototype.getSavedTemplateRenders = function() {
    -  return this.savedTemplateRenders_;
    -};
    -
    -
    -/**
    - * Observes rendering of templates by this renderer.
    - * @param {Node=} opt_node Relevant node, if available. The node may or may
    - *     not be in the document, depending on whether Soy is creating an element
    - *     or writing into an existing one.
    - * @protected
    - */
    -goog.soy.Renderer.prototype.handleRender = goog.nullFunction;
    -
    -
    -/**
    - * Saves information about the current template render for debug purposes.
    - * @param {Function} template The Soy template defining the element's content.
    - * @param {Object=} opt_templateData The data for the template.
    - * @private
    - * @suppress {missingProperties} SoyJs compiler adds soyTemplateName to the
    - *     template.
    - */
    -goog.soy.Renderer.prototype.saveTemplateRender_ = function(
    -    template, opt_templateData) {
    -  if (goog.DEBUG) {
    -    this.savedTemplateRenders_.push({
    -      template: template.soyTemplateName,
    -      data: opt_templateData,
    -      ijData: this.getInjectedData_()
    -    });
    -  }
    -};
    -
    -
    -/**
    - * Creates the injectedParams map if necessary and calls the configuration
    - * service to prepopulate it.
    - * @return {Object} The injected params.
    - * @private
    - */
    -goog.soy.Renderer.prototype.getInjectedData_ = function() {
    -  return this.supplier_ ? this.supplier_.getData() : {};
    -};
    -
    -
    -
    -/**
    - * An interface for a supplier that provides Soy injected data.
    - * @interface
    - */
    -goog.soy.InjectedDataSupplier = function() {};
    -
    -
    -/**
    - * Gets the injected data. Implementation may assume that
    - * {@code goog.soy.Renderer} will treat the returned data as
    - * immutable.  The renderer will call this every time one of its
    - * {@code render*} methods is called.
    - * @return {Object} A key-value pair representing the injected data.
    - */
    -goog.soy.InjectedDataSupplier.prototype.getData = function() {};
    diff --git a/src/database/third_party/closure-library/closure/goog/soy/renderer_test.html b/src/database/third_party/closure-library/closure/goog/soy/renderer_test.html
    deleted file mode 100644
    index 7475a8dcb06..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/soy/renderer_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -  Author: chrishenry@google.com (Chris Henry)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.soy.Renderer
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.soy.RendererTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/soy/renderer_test.js b/src/database/third_party/closure-library/closure/goog/soy/renderer_test.js
    deleted file mode 100644
    index 1ef8d6acc69..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/soy/renderer_test.js
    +++ /dev/null
    @@ -1,209 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.soy.RendererTest');
    -goog.setTestOnly('goog.soy.RendererTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.NodeType');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.html.SafeHtml');
    -goog.require('goog.i18n.bidi.Dir');
    -goog.require('goog.soy.Renderer');
    -goog.require('goog.soy.data.SanitizedContentKind');
    -/** @suppress {extraRequire} */
    -goog.require('goog.soy.testHelper');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -
    -var handleRender;
    -
    -
    -function setUp() {
    -  // Replace the empty default implementation.
    -  handleRender = goog.soy.Renderer.prototype.handleRender =
    -      goog.testing.recordFunction(goog.soy.Renderer.prototype.handleRender);
    -}
    -
    -
    -var dataSupplier = {
    -  getData: function() {
    -    return {name: 'IjValue'};
    -  }
    -};
    -
    -
    -function testRenderElement() {
    -  var testDiv = goog.dom.createElement(goog.dom.TagName.DIV);
    -
    -  var renderer = new goog.soy.Renderer(dataSupplier);
    -  renderer.renderElement(
    -      testDiv, example.injectedDataTemplate, {name: 'Value'});
    -  assertEquals('ValueIjValue', elementToInnerHtml(testDiv));
    -  assertEquals(testDiv, handleRender.getLastCall().getArguments()[0]);
    -  handleRender.assertCallCount(1);
    -}
    -
    -
    -function testRenderElementWithNoTemplateData() {
    -  var testDiv = goog.dom.createElement(goog.dom.TagName.DIV);
    -
    -  var renderer = new goog.soy.Renderer(dataSupplier);
    -  renderer.renderElement(testDiv, example.noDataTemplate);
    -  assertEquals('<div>Hello</div>', elementToInnerHtml(testDiv));
    -  assertEquals(testDiv, handleRender.getLastCall().getArguments()[0]);
    -  handleRender.assertCallCount(1);
    -}
    -
    -
    -function testRenderAsFragment() {
    -  var renderer = new goog.soy.Renderer(dataSupplier);
    -  var fragment = renderer.renderAsFragment(
    -      example.injectedDataTemplate, {name: 'Value'});
    -  assertEquals('ValueIjValue', fragmentToHtml(fragment));
    -  assertEquals(fragment, handleRender.getLastCall().getArguments()[0]);
    -  handleRender.assertCallCount(1);
    -}
    -
    -
    -function testRenderAsFragmentWithNoTemplateData() {
    -  var renderer = new goog.soy.Renderer(dataSupplier);
    -  var fragment = renderer.renderAsFragment(example.noDataTemplate);
    -  assertEquals(goog.dom.NodeType.ELEMENT, fragment.nodeType);
    -  assertEquals('<div>Hello</div>', fragmentToHtml(fragment));
    -  assertEquals(fragment, handleRender.getLastCall().getArguments()[0]);
    -  handleRender.assertCallCount(1);
    -}
    -
    -
    -function testRenderAsElement() {
    -  var renderer = new goog.soy.Renderer(dataSupplier);
    -  var element = renderer.renderAsElement(
    -      example.injectedDataTemplate, {name: 'Value'});
    -  assertEquals('ValueIjValue', elementToInnerHtml(element));
    -  assertEquals(element, handleRender.getLastCall().getArguments()[0]);
    -  handleRender.assertCallCount(1);
    -}
    -
    -
    -function testRenderAsElementWithNoTemplateData() {
    -  var renderer = new goog.soy.Renderer(dataSupplier);
    -  var elem = renderer.renderAsElement(example.noDataTemplate);
    -  assertEquals('Hello', elementToInnerHtml(elem));
    -  assertEquals(elem, handleRender.getLastCall().getArguments()[0]);
    -}
    -
    -
    -function testRenderConvertsToString() {
    -  var renderer = new goog.soy.Renderer(dataSupplier);
    -  assertEquals('Output should be a string',
    -      'Hello <b>World</b>', renderer.render(example.sanitizedHtmlTemplate));
    -  assertUndefined(handleRender.getLastCall().getArguments()[0]);
    -  handleRender.assertCallCount(1);
    -}
    -
    -
    -function testRenderRejectsNonHtmlStrictTemplates() {
    -  var renderer = new goog.soy.Renderer(dataSupplier);
    -  assertEquals(
    -      'Assertion failed: ' +
    -      'render was called with a strict template of kind other than "html"' +
    -      ' (consider using renderText or renderStrict)',
    -      assertThrows(function() {
    -        renderer.render(example.unsanitizedTextTemplate, {});
    -      }).message);
    -  handleRender.assertCallCount(0);
    -}
    -
    -
    -function testRenderStrictDoesNotConvertToString() {
    -  var renderer = new goog.soy.Renderer(dataSupplier);
    -  var result = renderer.renderStrict(example.sanitizedHtmlTemplate);
    -  assertEquals('Hello <b>World</b>', result.content);
    -  assertEquals(goog.soy.data.SanitizedContentKind.HTML, result.contentKind);
    -  assertUndefined(handleRender.getLastCall().getArguments()[0]);
    -  handleRender.assertCallCount(1);
    -}
    -
    -
    -function testRenderStrictValidatesOutput() {
    -  var renderer = new goog.soy.Renderer(dataSupplier);
    -  // Passes.
    -  renderer.renderStrict(example.sanitizedHtmlTemplate, {});
    -  // No SanitizedContent at all.
    -  assertEquals(
    -      'Assertion failed: ' +
    -      'renderStrict cannot be called on a non-strict soy template',
    -      assertThrows(function() {
    -        renderer.renderStrict(example.noDataTemplate, {});
    -      }).message);
    -  assertUndefined(handleRender.getLastCall().getArguments()[0]);
    -  // Passes.
    -  renderer.renderStrict(example.sanitizedHtmlTemplate, {},
    -      goog.soy.data.SanitizedContentKind.HTML);
    -  // Wrong content kind.
    -  assertEquals(
    -      'Assertion failed: ' +
    -      'renderStrict was called with the wrong kind of template',
    -      assertThrows(function() {
    -        renderer.renderStrict(example.sanitizedHtmlTemplate, {},
    -            goog.soy.data.SanitizedContentKind.JS);
    -      }).message);
    -  assertUndefined(handleRender.getLastCall().getArguments()[0]);
    -
    -  // renderStrict's opt_kind parameter defaults to SanitizedContentKind.HTML:
    -  // Passes.
    -  renderer.renderStrict(example.sanitizedHtmlTemplate, {});
    -  // Rendering non-HTML template fails:
    -  assertEquals(
    -      'Assertion failed: ' +
    -      'renderStrict was called with the wrong kind of template',
    -      assertThrows(function() {
    -        renderer.renderStrict(example.unsanitizedTextTemplate, {});
    -      }).message);
    -  assertUndefined(handleRender.getLastCall().getArguments()[0]);
    -  handleRender.assertCallCount(3);
    -}
    -
    -
    -function testRenderText() {
    -  var renderer = new goog.soy.Renderer(dataSupplier);
    -  // RenderText converts to string.
    -  assertEquals('Output of renderText should be a string',
    -      'I <3 Puppies & Kittens',
    -      renderer.renderText(example.unsanitizedTextTemplate));
    -  assertUndefined(handleRender.getLastCall().getArguments()[0]);
    -  // RenderText on non-strict template fails.
    -  assertEquals(
    -      'Assertion failed: ' +
    -      'renderText cannot be called on a non-strict soy template',
    -      assertThrows(function() {
    -        renderer.renderText(example.noDataTemplate, {});
    -      }).message);
    -  // RenderText on non-text template fails.
    -  assertEquals(
    -      'Assertion failed: ' +
    -      'renderText was called with a template of kind other than "text"',
    -      assertThrows(function() {
    -        renderer.renderText(example.sanitizedHtmlTemplate, {});
    -      }).message);
    -  handleRender.assertCallCount(1);
    -}
    -
    -function testRenderSafeHtml() {
    -  var renderer = new goog.soy.Renderer(dataSupplier);
    -  var result = renderer.renderSafeHtml(example.sanitizedHtmlTemplate);
    -  assertEquals('Hello <b>World</b>', goog.html.SafeHtml.unwrap(result));
    -  assertEquals(goog.i18n.bidi.Dir.LTR, result.getDirection());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/soy/soy.js b/src/database/third_party/closure-library/closure/goog/soy/soy.js
    deleted file mode 100644
    index 65b9aadaee4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/soy/soy.js
    +++ /dev/null
    @@ -1,218 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides utility methods to render soy template.
    - * @author chrishenry@google.com (Chris Henry)
    - */
    -
    -goog.provide('goog.soy');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.NodeType');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.soy.data.SanitizedContent');
    -goog.require('goog.soy.data.SanitizedContentKind');
    -goog.require('goog.string');
    -
    -
    -/**
    - * @define {boolean} Whether to require all Soy templates to be "strict html".
    - * Soy templates that use strict autoescaping forbid noAutoescape along with
    - * many dangerous directives, and return a runtime type SanitizedContent that
    - * marks them as safe.
    - *
    - * If this flag is enabled, Soy templates will fail to render if a template
    - * returns plain text -- indicating it is a non-strict template.
    - */
    -goog.define('goog.soy.REQUIRE_STRICT_AUTOESCAPE', false);
    -
    -
    -/**
    - * Renders a Soy template and then set the output string as
    - * the innerHTML of an element. It is recommended to use this helper function
    - * instead of directly setting innerHTML in your hand-written code, so that it
    - * will be easier to audit the code for cross-site scripting vulnerabilities.
    - *
    - * @param {Element} element The element whose content we are rendering into.
    - * @param {null|function(ARG_TYPES, null=, Object<string, *>=):*} template
    - *     The Soy template defining the element's content.
    - * @param {ARG_TYPES=} opt_templateData The data for the template.
    - * @param {Object=} opt_injectedData The injected data for the template.
    - * @template ARG_TYPES
    - */
    -goog.soy.renderElement = function(element, template, opt_templateData,
    -                                  opt_injectedData) {
    -  // Soy template parameter is only nullable for historical reasons.
    -  goog.asserts.assert(template, 'Soy template may not be null.');
    -  element.innerHTML = goog.soy.ensureTemplateOutputHtml_(template(
    -      opt_templateData || goog.soy.defaultTemplateData_, undefined,
    -      opt_injectedData));
    -};
    -
    -
    -/**
    - * Renders a Soy template into a single node or a document
    - * fragment. If the rendered HTML string represents a single node, then that
    - * node is returned (note that this is *not* a fragment, despite them name of
    - * the method). Otherwise a document fragment is returned containing the
    - * rendered nodes.
    - *
    - * @param {null|function(ARG_TYPES, null=, Object<string, *>=):*} template
    - *     The Soy template defining the element's content.
    - * @param {ARG_TYPES=} opt_templateData The data for the template.
    - * @param {Object=} opt_injectedData The injected data for the template.
    - * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper used to
    - *     create DOM nodes; defaults to {@code goog.dom.getDomHelper}.
    - * @return {!Node} The resulting node or document fragment.
    - * @template ARG_TYPES
    - */
    -goog.soy.renderAsFragment = function(template, opt_templateData,
    -                                     opt_injectedData, opt_domHelper) {
    -  // Soy template parameter is only nullable for historical reasons.
    -  goog.asserts.assert(template, 'Soy template may not be null.');
    -  var dom = opt_domHelper || goog.dom.getDomHelper();
    -  var html = goog.soy.ensureTemplateOutputHtml_(
    -      template(opt_templateData || goog.soy.defaultTemplateData_,
    -               undefined, opt_injectedData));
    -  goog.soy.assertFirstTagValid_(html);
    -  return dom.htmlToDocumentFragment(html);
    -};
    -
    -
    -/**
    - * Renders a Soy template into a single node. If the rendered
    - * HTML string represents a single node, then that node is returned. Otherwise,
    - * a DIV element is returned containing the rendered nodes.
    - *
    - * @param {null|function(ARG_TYPES, null=, Object<string, *>=):*} template
    - *     The Soy template defining the element's content.
    - * @param {ARG_TYPES=} opt_templateData The data for the template.
    - * @param {Object=} opt_injectedData The injected data for the template.
    - * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper used to
    - *     create DOM nodes; defaults to {@code goog.dom.getDomHelper}.
    - * @return {!Element} Rendered template contents, wrapped in a parent DIV
    - *     element if necessary.
    - * @template ARG_TYPES
    - */
    -goog.soy.renderAsElement = function(template, opt_templateData,
    -                                    opt_injectedData, opt_domHelper) {
    -  // Soy template parameter is only nullable for historical reasons.
    -  goog.asserts.assert(template, 'Soy template may not be null.');
    -  var dom = opt_domHelper || goog.dom.getDomHelper();
    -  var wrapper = dom.createElement(goog.dom.TagName.DIV);
    -  var html = goog.soy.ensureTemplateOutputHtml_(template(
    -      opt_templateData || goog.soy.defaultTemplateData_,
    -      undefined, opt_injectedData));
    -  goog.soy.assertFirstTagValid_(html);
    -  wrapper.innerHTML = html;
    -
    -  // If the template renders as a single element, return it.
    -  if (wrapper.childNodes.length == 1) {
    -    var firstChild = wrapper.firstChild;
    -    if (firstChild.nodeType == goog.dom.NodeType.ELEMENT) {
    -      return /** @type {!Element} */ (firstChild);
    -    }
    -  }
    -
    -  // Otherwise, return the wrapper DIV.
    -  return wrapper;
    -};
    -
    -
    -/**
    - * Ensures the result is "safe" to insert as HTML.
    - *
    - * Note if the template has non-strict autoescape, the guarantees here are very
    - * weak. It is recommended applications switch to requiring strict
    - * autoescaping over time by tweaking goog.soy.REQUIRE_STRICT_AUTOESCAPE.
    - *
    - * In the case the argument is a SanitizedContent object, it either must
    - * already be of kind HTML, or if it is kind="text", the output will be HTML
    - * escaped.
    - *
    - * @param {*} templateResult The template result.
    - * @return {string} The assumed-safe HTML output string.
    - * @private
    - */
    -goog.soy.ensureTemplateOutputHtml_ = function(templateResult) {
    -  // Allow strings as long as strict autoescaping is not mandated. Note we
    -  // allow everything that isn't an object, because some non-escaping templates
    -  // end up returning non-strings if their only print statement is a
    -  // non-escaped argument, plus some unit tests spoof templates.
    -  // TODO(gboyer): Track down and fix these cases.
    -  if (!goog.soy.REQUIRE_STRICT_AUTOESCAPE && !goog.isObject(templateResult)) {
    -    return String(templateResult);
    -  }
    -
    -  // Allow SanitizedContent of kind HTML.
    -  if (templateResult instanceof goog.soy.data.SanitizedContent) {
    -    templateResult = /** @type {!goog.soy.data.SanitizedContent} */ (
    -        templateResult);
    -    var ContentKind = goog.soy.data.SanitizedContentKind;
    -    if (templateResult.contentKind === ContentKind.HTML) {
    -      return goog.asserts.assertString(templateResult.getContent());
    -    }
    -    if (templateResult.contentKind === ContentKind.TEXT) {
    -      // Allow text to be rendered, as long as we escape it. Other content
    -      // kinds will fail, since we don't know what to do with them.
    -      // TODO(gboyer): Perhaps also include URI in this case.
    -      return goog.string.htmlEscape(templateResult.getContent());
    -    }
    -  }
    -
    -  goog.asserts.fail('Soy template output is unsafe for use as HTML: ' +
    -      templateResult);
    -
    -  // In production, return a safe string, rather than failing hard.
    -  return 'zSoyz';
    -};
    -
    -
    -/**
    - * Checks that the rendered HTML does not start with an invalid tag that would
    - * likely cause unexpected output from renderAsElement or renderAsFragment.
    - * See {@link http://www.w3.org/TR/html5/semantics.html#semantics} for reference
    - * as to which HTML elements can be parents of each other.
    - * @param {string} html The output of a template.
    - * @private
    - */
    -goog.soy.assertFirstTagValid_ = function(html) {
    -  if (goog.asserts.ENABLE_ASSERTS) {
    -    var matches = html.match(goog.soy.INVALID_TAG_TO_RENDER_);
    -    goog.asserts.assert(!matches, 'This template starts with a %s, which ' +
    -        'cannot be a child of a <div>, as required by soy internals. ' +
    -        'Consider using goog.soy.renderElement instead.\nTemplate output: %s',
    -        matches && matches[0], html);
    -  }
    -};
    -
    -
    -/**
    - * A pattern to find templates that cannot be rendered by renderAsElement or
    - * renderAsFragment, as these elements cannot exist as the child of a <div>.
    - * @type {!RegExp}
    - * @private
    - */
    -goog.soy.INVALID_TAG_TO_RENDER_ =
    -    /^<(body|caption|col|colgroup|head|html|tr|td|tbody|thead|tfoot)>/i;
    -
    -
    -/**
    - * Immutable object that is passed into templates that are rendered
    - * without any data.
    - * @private @const
    - */
    -goog.soy.defaultTemplateData_ = {};
    diff --git a/src/database/third_party/closure-library/closure/goog/soy/soy_test.html b/src/database/third_party/closure-library/closure/goog/soy/soy_test.html
    deleted file mode 100644
    index 67faae1d447..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/soy/soy_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -  Author: chrishenry@google.com (Chris Henry)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.soy
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.soyTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/soy/soy_test.js b/src/database/third_party/closure-library/closure/goog/soy/soy_test.js
    deleted file mode 100644
    index 934e45531b6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/soy/soy_test.js
    +++ /dev/null
    @@ -1,225 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.soyTest');
    -goog.setTestOnly('goog.soyTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.NodeType');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.functions');
    -goog.require('goog.soy');
    -/** @suppress {extraRequire} */
    -goog.require('goog.soy.testHelper');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -
    -var stubs;
    -
    -function setUp() {
    -  stubs = new goog.testing.PropertyReplacer();
    -}
    -
    -function tearDown() {
    -  stubs.reset();
    -}
    -
    -function testRenderElement() {
    -  var testDiv = goog.dom.createElement(goog.dom.TagName.DIV);
    -  goog.soy.renderElement(testDiv, example.multiRootTemplate, {name: 'Boo'});
    -  assertEquals('<div>Hello</div><div>Boo</div>', elementToInnerHtml(testDiv));
    -}
    -
    -
    -function testRenderElementWithNoTemplateData() {
    -  var testDiv = goog.dom.createElement(goog.dom.TagName.DIV);
    -  goog.soy.renderElement(testDiv, example.noDataTemplate);
    -  assertEquals('<div>Hello</div>', elementToInnerHtml(testDiv));
    -}
    -
    -
    -function testRenderAsFragmentTextNode() {
    -  var fragment = goog.soy.renderAsFragment(
    -      example.textNodeTemplate, {name: 'Boo'});
    -  assertEquals(goog.dom.NodeType.TEXT, fragment.nodeType);
    -  assertEquals('Boo', fragmentToHtml(fragment));
    -}
    -
    -
    -function testRenderAsFragmentInjectedData() {
    -  var fragment = goog.soy.renderAsFragment(example.injectedDataTemplate,
    -      {name: 'Boo'}, {name: 'ijBoo'});
    -  assertEquals(goog.dom.NodeType.TEXT, fragment.nodeType);
    -  assertEquals('BooijBoo', fragmentToHtml(fragment));
    -}
    -
    -
    -function testRenderAsFragmentSingleRoot() {
    -  var fragment = goog.soy.renderAsFragment(
    -      example.singleRootTemplate, {name: 'Boo'});
    -  assertEquals(goog.dom.NodeType.ELEMENT, fragment.nodeType);
    -  assertEquals(goog.dom.TagName.SPAN, fragment.tagName);
    -  assertEquals('Boo', fragment.innerHTML);
    -}
    -
    -
    -function testRenderAsFragmentMultiRoot() {
    -  var fragment = goog.soy.renderAsFragment(
    -      example.multiRootTemplate, {name: 'Boo'});
    -  assertEquals(goog.dom.NodeType.DOCUMENT_FRAGMENT, fragment.nodeType);
    -  assertEquals('<div>Hello</div><div>Boo</div>', fragmentToHtml(fragment));
    -}
    -
    -
    -function testRenderAsFragmentNoData() {
    -  var fragment = goog.soy.renderAsFragment(example.noDataTemplate);
    -  assertEquals(goog.dom.NodeType.ELEMENT, fragment.nodeType);
    -  assertEquals('<div>Hello</div>', fragmentToHtml(fragment));
    -}
    -
    -
    -function testRenderAsElementTextNode() {
    -  var elem = goog.soy.renderAsElement(example.textNodeTemplate, {name: 'Boo'});
    -  assertEquals(goog.dom.NodeType.ELEMENT, elem.nodeType);
    -  assertEquals(goog.dom.TagName.DIV, elem.tagName);
    -  assertEquals('Boo', elementToInnerHtml(elem));
    -}
    -
    -function testRenderAsElementInjectedData() {
    -  var elem = goog.soy.renderAsElement(example.injectedDataTemplate,
    -      {name: 'Boo'}, {name: 'ijBoo'});
    -  assertEquals(goog.dom.NodeType.ELEMENT, elem.nodeType);
    -  assertEquals(goog.dom.TagName.DIV, elem.tagName);
    -  assertEquals('BooijBoo', elementToInnerHtml(elem));
    -}
    -
    -
    -function testRenderAsElementSingleRoot() {
    -  var elem = goog.soy.renderAsElement(
    -      example.singleRootTemplate, {name: 'Boo'});
    -  assertEquals(goog.dom.NodeType.ELEMENT, elem.nodeType);
    -  assertEquals(goog.dom.TagName.SPAN, elem.tagName);
    -  assertEquals('Boo', elementToInnerHtml(elem));
    -}
    -
    -
    -function testRenderAsElementMultiRoot() {
    -  var elem = goog.soy.renderAsElement(example.multiRootTemplate, {name: 'Boo'});
    -  assertEquals(goog.dom.NodeType.ELEMENT, elem.nodeType);
    -  assertEquals(goog.dom.TagName.DIV, elem.tagName);
    -  assertEquals('<div>Hello</div><div>Boo</div>', elementToInnerHtml(elem));
    -}
    -
    -function testRenderAsElementWithNoData() {
    -  var elem = goog.soy.renderAsElement(example.noDataTemplate);
    -  assertEquals('Hello', elementToInnerHtml(elem));
    -}
    -
    -
    -/**
    - * Asserts that the function throws an error for unsafe templates.
    - * @param {Function} function Callback to test.
    - */
    -function assertUnsafeTemplateOutputErrorThrown(func) {
    -  stubs.set(goog.asserts, 'ENABLE_ASSERTS', true);
    -  assertContains('Soy template output is unsafe for use as HTML',
    -      assertThrows(func).message);
    -  stubs.set(goog.asserts, 'ENABLE_ASSERTS', false);
    -  assertEquals('zSoyz', func());
    -}
    -
    -function testAllowButEscapeUnsanitizedText() {
    -  var div = goog.dom.createElement(goog.dom.TagName.DIV);
    -  goog.soy.renderElement(div, example.unsanitizedTextTemplate);
    -  assertEquals('I &lt;3 Puppies &amp; Kittens', div.innerHTML);
    -  var fragment = goog.soy.renderAsFragment(example.unsanitizedTextTemplate);
    -  assertEquals('I <3 Puppies & Kittens', fragment.nodeValue);
    -  assertEquals('I &lt;3 Puppies &amp; Kittens',
    -      goog.soy.renderAsElement(example.unsanitizedTextTemplate).innerHTML);
    -}
    -
    -function testRejectSanitizedCss() {
    -  assertUnsafeTemplateOutputErrorThrown(function() {
    -    goog.soy.renderAsElement(example.sanitizedCssTemplate);
    -  });
    -}
    -
    -function testRejectSanitizedCss() {
    -  assertUnsafeTemplateOutputErrorThrown(function() {
    -    return goog.soy.renderAsElement(
    -        example.templateSpoofingSanitizedContentString).innerHTML;
    -  });
    -}
    -
    -function testRejectStringTemplatesWhenModeIsSet() {
    -  stubs.set(goog.soy, 'REQUIRE_STRICT_AUTOESCAPE', true);
    -  assertUnsafeTemplateOutputErrorThrown(function() {
    -    return goog.soy.renderAsElement(example.noDataTemplate).innerHTML;
    -  });
    -}
    -
    -function testAcceptSanitizedHtml() {
    -  assertEquals('Hello World', goog.dom.getTextContent(
    -      goog.soy.renderAsElement(example.sanitizedHtmlTemplate)));
    -}
    -
    -function testRejectSanitizedHtmlAttributes() {
    -  // Attributes context has nothing to do with html.
    -  assertUnsafeTemplateOutputErrorThrown(function() {
    -    return goog.dom.getTextContent(
    -        goog.soy.renderAsElement(example.sanitizedHtmlAttributesTemplate));
    -  });
    -}
    -
    -function testAcceptNonObject() {
    -  // Some templates, or things that spoof templates in unit tests, might return
    -  // non-strings in unusual cases.
    -  assertEquals('null', goog.dom.getTextContent(
    -      goog.soy.renderAsElement(goog.functions.constant(null))));
    -}
    -
    -function testDebugAssertionWithBadFirstTag() {
    -  try {
    -    goog.soy.renderAsElement(example.tableRowTemplate);
    -    // Expect no exception in production code.
    -    assert(!goog.DEBUG);
    -  } catch (e) {
    -    // Expect exception in debug code.
    -    assert(goog.DEBUG);
    -    // Make sure to let the developer know which tag caused the problem.
    -    assertContains('<tr>', e.message);
    -  }
    -
    -  try {
    -    goog.soy.renderAsFragment(example.tableRowTemplate);
    -    // Expect no exception in production code.
    -    assert(!goog.DEBUG);
    -  } catch (e) {
    -    // Expect exception in debug code.
    -    assert(goog.DEBUG);
    -    // Make sure to let the developer know which tag caused the problem.
    -    assertContains('<tr>', e.message);
    -  }
    -
    -  try {
    -    goog.soy.renderAsElement(example.colGroupTemplateCaps);
    -    // Expect no exception in production code.
    -    assert(!goog.DEBUG);
    -  } catch (e) {
    -    // Expect exception in debug code.
    -    assert(goog.DEBUG);
    -    // Make sure to let the developer know which tag caused the problem.
    -    assertContains('<COLGROUP>', e.message);
    -  }
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/soy/soy_testhelper.js b/src/database/third_party/closure-library/closure/goog/soy/soy_testhelper.js
    deleted file mode 100644
    index 657c6e77911..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/soy/soy_testhelper.js
    +++ /dev/null
    @@ -1,181 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides test helpers for Soy tests.
    - * @author chrishenry@google.com (Chris Henry)
    - */
    -
    -/** @suppress {extraProvide} */
    -goog.provide('goog.soy.testHelper');
    -goog.setTestOnly('goog.soy.testHelper');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.i18n.bidi.Dir');
    -goog.require('goog.soy.data.SanitizedContent');
    -goog.require('goog.soy.data.SanitizedContentKind');
    -goog.require('goog.string');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Instantiable subclass of SanitizedContent.
    - *
    - * This is a spoof for sanitized content that isn't robust enough to get
    - * through Soy's escaping functions but is good enough for the checks here.
    - *
    - * @constructor
    - * @param {string} content The text.
    - * @param {goog.soy.data.SanitizedContentKind} kind The kind of safe content.
    - * @extends {goog.soy.data.SanitizedContent}
    - */
    -function SanitizedContentSubclass(content, kind) {
    -  // IMPORTANT! No superclass chaining to avoid exception being thrown.
    -  this.content = content;
    -  this.contentKind = kind;
    -}
    -goog.inherits(SanitizedContentSubclass, goog.soy.data.SanitizedContent);
    -
    -
    -function makeSanitizedContent(content, kind) {
    -  return new SanitizedContentSubclass(content, kind);
    -}
    -
    -
    -
    -//
    -// Fake Soy-generated template functions.
    -//
    -
    -var example = {};
    -
    -
    -example.textNodeTemplate = function(opt_data, opt_sb, opt_injectedData) {
    -  assertNotNull(opt_data);
    -  assertNotUndefined(opt_data);
    -  return goog.string.htmlEscape(opt_data.name);
    -};
    -
    -
    -example.singleRootTemplate = function(opt_data, opt_sb, opt_injectedData) {
    -  assertNotNull(opt_data);
    -  assertNotUndefined(opt_data);
    -  return '<span>' + goog.string.htmlEscape(opt_data.name) + '</span>';
    -};
    -
    -
    -example.multiRootTemplate = function(opt_data, opt_sb, opt_injectedData) {
    -  assertNotNull(opt_data);
    -  assertNotUndefined(opt_data);
    -  return '<div>Hello</div><div>' + goog.string.htmlEscape(opt_data.name) +
    -      '</div>';
    -};
    -
    -
    -example.injectedDataTemplate = function(opt_data, opt_sb, opt_injectedData) {
    -  assertNotNull(opt_data);
    -  assertNotUndefined(opt_data);
    -  return goog.string.htmlEscape(opt_data.name) +
    -      goog.string.htmlEscape(opt_injectedData.name);
    -};
    -
    -
    -example.noDataTemplate = function(opt_data, opt_sb, opt_injectedData) {
    -  assertNotNull(opt_data);
    -  assertNotUndefined(opt_data);
    -  return '<div>Hello</div>';
    -};
    -
    -
    -example.sanitizedHtmlTemplate = function(opt_data, opt_sb, opt_injectedData) {
    -  // Test the SanitizedContent constructor.
    -  var sanitized = makeSanitizedContent('Hello <b>World</b>',
    -      goog.soy.data.SanitizedContentKind.HTML);
    -  sanitized.contentDir = goog.i18n.bidi.Dir.LTR;
    -  return sanitized;
    -};
    -
    -
    -example.sanitizedHtmlAttributesTemplate =
    -    function(opt_data, opt_sb, opt_injectedData) {
    -  return makeSanitizedContent('foo="bar"',
    -      goog.soy.data.SanitizedContentKind.ATTRIBUTES);
    -};
    -
    -
    -example.sanitizedCssTemplate =
    -    function(opt_data, opt_sb, opt_injectedData) {
    -  return makeSanitizedContent('display:none',
    -      goog.soy.data.SanitizedContentKind.CSS);
    -};
    -
    -
    -example.unsanitizedTextTemplate =
    -    function(opt_data, opt_sb, opt_injectedData) {
    -  return makeSanitizedContent('I <3 Puppies & Kittens',
    -      goog.soy.data.SanitizedContentKind.TEXT);
    -};
    -
    -
    -example.templateSpoofingSanitizedContentString =
    -    function(opt_data, opt_sb, opt_injectedData) {
    -  return makeSanitizedContent('Hello World',
    -      // This is to ensure we're using triple-equals against a unique Javascript
    -      // object.  For example, in Javascript, consider ({}) == '[Object object]'
    -      // is true.
    -      goog.soy.data.SanitizedContentKind.HTML.toString());
    -};
    -
    -
    -example.tableRowTemplate = function(opt_data, opt_sb, opt_injectedData) {
    -  return '<tr><td></td></tr>';
    -};
    -
    -
    -example.colGroupTemplateCaps = function(opt_data, opt_sb, opt_injectedData) {
    -  return '<COLGROUP></COLGROUP>';
    -};
    -
    -
    -//
    -// Test helper functions.
    -//
    -
    -
    -/**
    - * Retrieves the content of document fragment as HTML.
    - * @param {Node} fragment The document fragment.
    - * @return {string} Content of the document fragment as HTML.
    - */
    -function fragmentToHtml(fragment) {
    -  var testDiv = goog.dom.createElement(goog.dom.TagName.DIV);
    -  testDiv.appendChild(fragment);
    -  return elementToInnerHtml(testDiv);
    -}
    -
    -
    -/**
    - * Retrieves the content of an element as HTML.
    - * @param {Element} elem The element.
    - * @return {string} Content of the element as HTML.
    - */
    -function elementToInnerHtml(elem) {
    -  var innerHtml = elem.innerHTML;
    -  if (goog.userAgent.IE) {
    -    innerHtml = innerHtml.replace(/DIV/g, 'div').replace(/\s/g, '');
    -  }
    -  return innerHtml;
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/spell/spellcheck.js b/src/database/third_party/closure-library/closure/goog/spell/spellcheck.js
    deleted file mode 100644
    index 3462d3961c8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/spell/spellcheck.js
    +++ /dev/null
    @@ -1,478 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Support class for spell checker components.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - */
    -
    -goog.provide('goog.spell.SpellCheck');
    -goog.provide('goog.spell.SpellCheck.WordChangedEvent');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.structs.Set');
    -
    -
    -
    -/**
    - * Support class for spell checker components. Provides basic functionality
    - * such as word lookup and caching.
    - *
    - * @param {Function=} opt_lookupFunction Function to use for word lookup. Must
    - *     accept an array of words, an object reference and a callback function as
    - *     parameters. It must also call the callback function (as a method on the
    - *     object), once ready, with an array containing the original words, their
    - *     spelling status and optionally an array of suggestions.
    - * @param {string=} opt_language Content language.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - * @final
    - */
    -goog.spell.SpellCheck = function(opt_lookupFunction, opt_language) {
    -  goog.events.EventTarget.call(this);
    -
    -  /**
    -   * Function used to lookup spelling of words.
    -   * @type {Function}
    -   * @private
    -   */
    -  this.lookupFunction_ = opt_lookupFunction || null;
    -
    -  /**
    -   * Cache for words not yet checked with lookup function.
    -   * @type {goog.structs.Set}
    -   * @private
    -   */
    -  this.unknownWords_ = new goog.structs.Set();
    -
    -  this.setLanguage(opt_language);
    -};
    -goog.inherits(goog.spell.SpellCheck, goog.events.EventTarget);
    -
    -
    -/**
    - * Delay, in ms, to wait for additional words to be entered before a lookup
    - * operation is triggered.
    - *
    - * @type {number}
    - * @private
    - */
    -goog.spell.SpellCheck.LOOKUP_DELAY_ = 100;
    -
    -
    -/**
    - * Constants for event names
    - *
    - * @enum {string}
    - */
    -goog.spell.SpellCheck.EventType = {
    -  /**
    -   * Fired when all pending words have been processed.
    -   */
    -  READY: 'ready',
    -
    -  /**
    -   * Fired when all lookup function failed.
    -   */
    -  ERROR: 'error',
    -
    -  /**
    -   * Fired when a word's status is changed.
    -   */
    -  WORD_CHANGED: 'wordchanged'
    -};
    -
    -
    -/**
    - * Cache. Shared across all spell checker instances. Map with langauge as the
    - * key and a cache for that language as the value.
    - *
    - * @type {Object}
    - * @private
    - */
    -goog.spell.SpellCheck.cache_ = {};
    -
    -
    -/**
    - * Content Language.
    - * @type {string}
    - * @private
    - */
    -goog.spell.SpellCheck.prototype.language_ = '';
    -
    -
    -/**
    - * Cache for set language. Reference to the element corresponding to the set
    - * language in the static goog.spell.SpellCheck.cache_.
    - *
    - * @type {Object|undefined}
    - * @private
    - */
    -goog.spell.SpellCheck.prototype.cache_;
    -
    -
    -/**
    - * Id for timer processing the pending queue.
    - *
    - * @type {number}
    - * @private
    - */
    -goog.spell.SpellCheck.prototype.queueTimer_ = 0;
    -
    -
    -/**
    - * Whether a lookup operation is in progress.
    - *
    - * @type {boolean}
    - * @private
    - */
    -goog.spell.SpellCheck.prototype.lookupInProgress_ = false;
    -
    -
    -/**
    - * Codes representing the status of an individual word.
    - *
    - * @enum {number}
    - */
    -goog.spell.SpellCheck.WordStatus = {
    -  UNKNOWN: 0,
    -  VALID: 1,
    -  INVALID: 2,
    -  IGNORED: 3,
    -  CORRECTED: 4 // Temporary status, not stored in cache
    -};
    -
    -
    -/**
    - * Fields for word array in cache.
    - *
    - * @enum {number}
    - */
    -goog.spell.SpellCheck.CacheIndex = {
    -  STATUS: 0,
    -  SUGGESTIONS: 1
    -};
    -
    -
    -/**
    - * Regular expression for identifying word boundaries.
    - *
    - * @type {string}
    - */
    -goog.spell.SpellCheck.WORD_BOUNDARY_CHARS =
    -    '\t\r\n\u00A0 !\"#$%&()*+,\-.\/:;<=>?@\[\\\]^_`{|}~';
    -
    -
    -/**
    - * Regular expression for identifying word boundaries.
    - *
    - * @type {RegExp}
    - */
    -goog.spell.SpellCheck.WORD_BOUNDARY_REGEX = new RegExp(
    -    '[' + goog.spell.SpellCheck.WORD_BOUNDARY_CHARS + ']');
    -
    -
    -/**
    - * Regular expression for splitting a string into individual words and blocks of
    - * separators. Matches zero or one word followed by zero or more separators.
    - *
    - * @type {RegExp}
    - */
    -goog.spell.SpellCheck.SPLIT_REGEX = new RegExp(
    -    '([^' + goog.spell.SpellCheck.WORD_BOUNDARY_CHARS + ']*)' +
    -    '([' + goog.spell.SpellCheck.WORD_BOUNDARY_CHARS + ']*)');
    -
    -
    -/**
    - * Sets the lookup function.
    - *
    - * @param {Function} f Function to use for word lookup. Must accept an array of
    - *     words, an object reference and a callback function as parameters.
    - *     It must also call the callback function (as a method on the object),
    - *     once ready, with an array containing the original words, their
    - *     spelling status and optionally an array of suggestions.
    - */
    -goog.spell.SpellCheck.prototype.setLookupFunction = function(f) {
    -  this.lookupFunction_ = f;
    -};
    -
    -
    -/**
    - * Sets language.
    - *
    - * @param {string=} opt_language Content language.
    - */
    -goog.spell.SpellCheck.prototype.setLanguage = function(opt_language) {
    -  this.language_ = opt_language || '';
    -
    -  if (!goog.spell.SpellCheck.cache_[this.language_]) {
    -    goog.spell.SpellCheck.cache_[this.language_] = {};
    -  }
    -  this.cache_ = goog.spell.SpellCheck.cache_[this.language_];
    -};
    -
    -
    -/**
    - * Returns language.
    - *
    - * @return {string} Content language.
    - */
    -goog.spell.SpellCheck.prototype.getLanguage = function() {
    -  return this.language_;
    -};
    -
    -
    -/**
    - * Checks spelling for a block of text.
    - *
    - * @param {string} text Block of text to spell check.
    - */
    -goog.spell.SpellCheck.prototype.checkBlock = function(text) {
    -  var words = text.split(goog.spell.SpellCheck.WORD_BOUNDARY_REGEX);
    -
    -  var len = words.length;
    -  for (var word, i = 0; i < len; i++) {
    -    word = words[i];
    -    this.checkWord_(word);
    -  }
    -
    -  if (!this.queueTimer_ && !this.lookupInProgress_ &&
    -      this.unknownWords_.getCount()) {
    -    this.processPending_();
    -  }
    -  else if (this.unknownWords_.getCount() == 0) {
    -    this.dispatchEvent(goog.spell.SpellCheck.EventType.READY);
    -  }
    -};
    -
    -
    -/**
    - * Checks spelling for a single word. Returns the status of the supplied word,
    - * or UNKNOWN if it's not cached. If it's not cached the word is added to a
    - * queue and checked with the verification implementation with a short delay.
    - *
    - * @param {string} word Word to check spelling of.
    - * @return {goog.spell.SpellCheck.WordStatus} The status of the supplied word,
    - *     or UNKNOWN if it's not cached.
    - */
    -goog.spell.SpellCheck.prototype.checkWord = function(word) {
    -  var status = this.checkWord_(word);
    -
    -  if (status == goog.spell.SpellCheck.WordStatus.UNKNOWN &&
    -      !this.queueTimer_ && !this.lookupInProgress_) {
    -    this.queueTimer_ = goog.Timer.callOnce(this.processPending_,
    -        goog.spell.SpellCheck.LOOKUP_DELAY_, this);
    -  }
    -
    -  return status;
    -};
    -
    -
    -/**
    - * Checks spelling for a single word. Returns the status of the supplied word,
    - * or UNKNOWN if it's not cached.
    - *
    - * @param {string} word Word to check spelling of.
    - * @return {goog.spell.SpellCheck.WordStatus} The status of the supplied word,
    - *     or UNKNOWN if it's not cached.
    - * @private
    - */
    -goog.spell.SpellCheck.prototype.checkWord_ = function(word) {
    -  if (!word) {
    -    return goog.spell.SpellCheck.WordStatus.INVALID;
    -  }
    -
    -  var cacheEntry = this.cache_[word];
    -  if (!cacheEntry) {
    -    this.unknownWords_.add(word);
    -    return goog.spell.SpellCheck.WordStatus.UNKNOWN;
    -  }
    -
    -  return cacheEntry[goog.spell.SpellCheck.CacheIndex.STATUS];
    -};
    -
    -
    -/**
    - * Processes pending words unless a lookup operation has already been queued or
    - * is in progress.
    - *
    - * @throws {Error}
    - */
    -goog.spell.SpellCheck.prototype.processPending = function() {
    -  if (this.unknownWords_.getCount()) {
    -    if (!this.queueTimer_ && !this.lookupInProgress_) {
    -      this.processPending_();
    -    }
    -  } else {
    -    this.dispatchEvent(goog.spell.SpellCheck.EventType.READY);
    -  }
    -};
    -
    -
    -/**
    - * Processes pending words using the verification callback.
    - *
    - * @throws {Error}
    - * @private
    - */
    -goog.spell.SpellCheck.prototype.processPending_ = function() {
    -  if (!this.lookupFunction_) {
    -    throw Error('No lookup function provided for spell checker.');
    -  }
    -
    -  if (this.unknownWords_.getCount()) {
    -    this.lookupInProgress_ = true;
    -    var func = this.lookupFunction_;
    -    func(this.unknownWords_.getValues(), this, this.lookupCallback_);
    -  } else {
    -    this.dispatchEvent(goog.spell.SpellCheck.EventType.READY);
    -  }
    -
    -  this.queueTimer_ = 0;
    -};
    -
    -
    -/**
    - * Callback for lookup function.
    - *
    - * @param {Array<Array<?>>} data Data array. Each word is represented by an
    - *     array containing the word, the status and optionally an array of
    - *     suggestions. Passing null indicates that the operation failed.
    - * @private
    - *
    - * Example:
    - * obj.lookupCallback_([
    - *   ['word', VALID],
    - *   ['wrod', INVALID, ['word', 'wood', 'rod']]
    - * ]);
    - */
    -goog.spell.SpellCheck.prototype.lookupCallback_ = function(data) {
    -
    -  // Lookup function failed; abort then dispatch error event.
    -  if (data == null) {
    -    if (this.queueTimer_) {
    -      goog.Timer.clear(this.queueTimer_);
    -      this.queueTimer_ = 0;
    -    }
    -    this.lookupInProgress_ = false;
    -
    -    this.dispatchEvent(goog.spell.SpellCheck.EventType.ERROR);
    -    return;
    -  }
    -
    -  for (var a, i = 0; a = data[i]; i++) {
    -    this.setWordStatus_(a[0], a[1], a[2]);
    -  }
    -  this.lookupInProgress_ = false;
    -
    -  // Fire ready event if all pending words have been processed.
    -  if (this.unknownWords_.getCount() == 0) {
    -    this.dispatchEvent(goog.spell.SpellCheck.EventType.READY);
    -
    -  // Process pending
    -  } else if (!this.queueTimer_) {
    -    this.queueTimer_ = goog.Timer.callOnce(this.processPending_,
    -        goog.spell.SpellCheck.LOOKUP_DELAY_, this);
    -  }
    -};
    -
    -
    -/**
    - * Sets a words spelling status.
    - *
    - * @param {string} word Word to set status for.
    - * @param {goog.spell.SpellCheck.WordStatus} status Status of word.
    - * @param {Array<string>=} opt_suggestions Suggestions.
    - *
    - * Example:
    - * obj.setWordStatus('word', VALID);
    - * obj.setWordStatus('wrod', INVALID, ['word', 'wood', 'rod']);.
    - */
    -goog.spell.SpellCheck.prototype.setWordStatus =
    -    function(word, status, opt_suggestions) {
    -  this.setWordStatus_(word, status, opt_suggestions);
    -};
    -
    -
    -/**
    - * Sets a words spelling status.
    - *
    - * @param {string} word Word to set status for.
    - * @param {goog.spell.SpellCheck.WordStatus} status Status of word.
    - * @param {Array<string>=} opt_suggestions Suggestions.
    - * @private
    - */
    -goog.spell.SpellCheck.prototype.setWordStatus_ =
    -    function(word, status, opt_suggestions) {
    -  var suggestions = opt_suggestions || [];
    -  this.cache_[word] = [status, suggestions];
    -  this.unknownWords_.remove(word);
    -
    -  this.dispatchEvent(
    -      new goog.spell.SpellCheck.WordChangedEvent(this, word, status));
    -};
    -
    -
    -/**
    - * Returns suggestions for the given word.
    - *
    - * @param {string} word Word to get suggestions for.
    - * @return {Array<string>} An array of suggestions for the given word.
    - */
    -goog.spell.SpellCheck.prototype.getSuggestions = function(word) {
    -  var cacheEntry = this.cache_[word];
    -
    -  if (!cacheEntry) {
    -    this.checkWord(word);
    -    return [];
    -  }
    -
    -  return cacheEntry[goog.spell.SpellCheck.CacheIndex.STATUS] ==
    -      goog.spell.SpellCheck.WordStatus.INVALID ?
    -      cacheEntry[goog.spell.SpellCheck.CacheIndex.SUGGESTIONS] : [];
    -};
    -
    -
    -
    -/**
    - * Object representing a word changed event. Fired when the status of a word
    - * changes.
    - *
    - * @param {goog.spell.SpellCheck} target Spellcheck object initiating event.
    - * @param {string} word Word to set status for.
    - * @param {goog.spell.SpellCheck.WordStatus} status Status of word.
    - * @extends {goog.events.Event}
    - * @constructor
    - * @final
    - */
    -goog.spell.SpellCheck.WordChangedEvent = function(target, word, status) {
    -  goog.events.Event.call(this, goog.spell.SpellCheck.EventType.WORD_CHANGED,
    -      target);
    -
    -  /**
    -   * Word the status has changed for.
    -   * @type {string}
    -   */
    -  this.word = word;
    -
    -  /**
    -   * New status
    -   * @type {goog.spell.SpellCheck.WordStatus}
    -   */
    -  this.status = status;
    -};
    -goog.inherits(goog.spell.SpellCheck.WordChangedEvent, goog.events.Event);
    diff --git a/src/database/third_party/closure-library/closure/goog/spell/spellcheck_test.html b/src/database/third_party/closure-library/closure/goog/spell/spellcheck_test.html
    deleted file mode 100644
    index 69b342164e8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/spell/spellcheck_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.spell.SpellCheck
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.spell.SpellCheckTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/spell/spellcheck_test.js b/src/database/third_party/closure-library/closure/goog/spell/spellcheck_test.js
    deleted file mode 100644
    index b72b0db8e75..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/spell/spellcheck_test.js
    +++ /dev/null
    @@ -1,110 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.spell.SpellCheckTest');
    -goog.setTestOnly('goog.spell.SpellCheckTest');
    -
    -goog.require('goog.spell.SpellCheck');
    -goog.require('goog.testing.jsunit');
    -
    -var TEST_DATA = {
    -  'Test': [goog.spell.SpellCheck.WordStatus.VALID, []],
    -  'strnig': [goog.spell.SpellCheck.WordStatus.INVALID, []],
    -  'wtih': [goog.spell.SpellCheck.WordStatus.INVALID, []],
    -  'a': [goog.spell.SpellCheck.WordStatus.VALID, []],
    -  'few': [goog.spell.SpellCheck.WordStatus.VALID, []],
    -  'misspeled': [goog.spell.SpellCheck.WordStatus.INVALID,
    -    ['misspelled', 'misapplied', 'misspell']],
    -  'words': [goog.spell.SpellCheck.WordStatus.VALID, []],
    -  'Testing': [goog.spell.SpellCheck.WordStatus.VALID, []],
    -  'set': [goog.spell.SpellCheck.WordStatus.VALID, []],
    -  'status': [goog.spell.SpellCheck.WordStatus.VALID, []],
    -  'vaild': [goog.spell.SpellCheck.WordStatus.INVALID, []],
    -  'invalid': [goog.spell.SpellCheck.WordStatus.VALID, []],
    -  'ignoerd': [goog.spell.SpellCheck.WordStatus.INVALID, []]
    -};
    -
    -function mockSpellCheckingFunction(words, spellChecker, callback) {
    -  var len = words.length;
    -  var data = [];
    -  for (var i = 0; i < len; i++) {
    -    var word = words[i];
    -    var status = TEST_DATA[word][0];
    -    var suggestions = TEST_DATA[word][1];
    -    data.push([word, status, suggestions]);
    -  }
    -  callback.call(spellChecker, data);
    -}
    -
    -
    -function testWordMatching() {
    -  var spell = new goog.spell.SpellCheck(mockSpellCheckingFunction);
    -
    -  var valid = goog.spell.SpellCheck.WordStatus.VALID;
    -  var invalid = goog.spell.SpellCheck.WordStatus.INVALID;
    -
    -  spell.checkBlock('Test strnig wtih a few misspeled words.');
    -  assertEquals(valid, spell.checkWord('Test'));
    -  assertEquals(invalid, spell.checkWord('strnig'));
    -  assertEquals(invalid, spell.checkWord('wtih'));
    -  assertEquals(valid, spell.checkWord('a'));
    -  assertEquals(valid, spell.checkWord('few'));
    -  assertEquals(invalid, spell.checkWord('misspeled'));
    -  assertEquals(valid, spell.checkWord('words'));
    -}
    -
    -
    -function testSetWordStatusValid() {
    -  var spell = new goog.spell.SpellCheck(mockSpellCheckingFunction);
    -
    -  var valid = goog.spell.SpellCheck.WordStatus.VALID;
    -
    -  spell.checkBlock('Testing set status vaild.');
    -  spell.setWordStatus('vaild', valid);
    -
    -  assertEquals(valid, spell.checkWord('vaild'));
    -}
    -
    -function testSetWordStatusInvalid() {
    -  var spell = new goog.spell.SpellCheck(mockSpellCheckingFunction);
    -
    -  var valid = goog.spell.SpellCheck.WordStatus.VALID;
    -  var invalid = goog.spell.SpellCheck.WordStatus.INVALID;
    -
    -  spell.checkBlock('Testing set status invalid.');
    -  spell.setWordStatus('invalid', invalid);
    -
    -  assertEquals(invalid, spell.checkWord('invalid'));
    -}
    -
    -
    -function testSetWordStatusIgnored() {
    -  var spell = new goog.spell.SpellCheck(mockSpellCheckingFunction);
    -
    -  var ignored = goog.spell.SpellCheck.WordStatus.IGNORED;
    -
    -  spell.checkBlock('Testing set status ignoerd.');
    -  spell.setWordStatus('ignoerd', ignored);
    -
    -  assertEquals(ignored, spell.checkWord('ignoerd'));
    -}
    -
    -
    -function testGetSuggestions() {
    -  var spell = new goog.spell.SpellCheck(mockSpellCheckingFunction);
    -
    -  spell.checkBlock('Test strnig wtih a few misspeled words.');
    -  var suggestions = spell.getSuggestions('misspeled');
    -  assertEquals(3, suggestions.length);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/stats/basicstat.js b/src/database/third_party/closure-library/closure/goog/stats/basicstat.js
    deleted file mode 100644
    index 7439294f53c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/stats/basicstat.js
    +++ /dev/null
    @@ -1,270 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A basic statistics tracker.
    - *
    - */
    -
    -goog.provide('goog.stats.BasicStat');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.log');
    -goog.require('goog.string.format');
    -goog.require('goog.structs.CircularBuffer');
    -
    -
    -
    -/**
    - * Tracks basic statistics over a specified time interval.
    - *
    - * Statistics are kept in a fixed number of slots, each representing
    - * an equal portion of the time interval.
    - *
    - * Most methods optionally allow passing in the current time, so that
    - * higher level stats can synchronize operations on multiple child
    - * objects.  Under normal usage, the default of goog.now() should be
    - * sufficient.
    - *
    - * @param {number} interval The stat interval, in milliseconds.
    - * @constructor
    - * @final
    - */
    -goog.stats.BasicStat = function(interval) {
    -  goog.asserts.assert(interval > 50);
    -
    -  /**
    -   * The time interval that this statistic aggregates over.
    -   * @type {number}
    -   * @private
    -   */
    -  this.interval_ = interval;
    -
    -  /**
    -   * The number of milliseconds in each slot.
    -   * @type {number}
    -   * @private
    -   */
    -  this.slotInterval_ = Math.floor(interval / goog.stats.BasicStat.NUM_SLOTS_);
    -
    -  /**
    -   * The array of slots.
    -   * @type {goog.structs.CircularBuffer}
    -   * @private
    -   */
    -  this.slots_ =
    -      new goog.structs.CircularBuffer(goog.stats.BasicStat.NUM_SLOTS_);
    -};
    -
    -
    -/**
    - * The number of slots. This value limits the accuracy of the get()
    - * method to (this.interval_ / NUM_SLOTS).  A 1-minute statistic would
    - * be accurate to within 2 seconds.
    - * @type {number}
    - * @private
    - */
    -goog.stats.BasicStat.NUM_SLOTS_ = 50;
    -
    -
    -/**
    - * @type {goog.log.Logger}
    - * @private
    - */
    -goog.stats.BasicStat.prototype.logger_ =
    -    goog.log.getLogger('goog.stats.BasicStat');
    -
    -
    -/**
    - * @return {number} The interval which over statistics are being
    - *     accumulated, in milliseconds.
    - */
    -goog.stats.BasicStat.prototype.getInterval = function() {
    -  return this.interval_;
    -};
    -
    -
    -/**
    - * Increments the count of this statistic by the specified amount.
    - *
    - * @param {number} amt The amount to increase the count by.
    - * @param {number=} opt_now The time, in milliseconds, to be treated
    - *     as the "current" time.  The current time must always be greater
    - *     than or equal to the last time recorded by this stat tracker.
    - */
    -goog.stats.BasicStat.prototype.incBy = function(amt, opt_now) {
    -  var now = opt_now ? opt_now : goog.now();
    -  this.checkForTimeTravel_(now);
    -  var slot = /** @type {goog.stats.BasicStat.Slot_} */ (this.slots_.getLast());
    -  if (!slot || now >= slot.end) {
    -    slot = new goog.stats.BasicStat.Slot_(this.getSlotBoundary_(now));
    -    this.slots_.add(slot);
    -  }
    -  slot.count += amt;
    -  slot.min = Math.min(amt, slot.min);
    -  slot.max = Math.max(amt, slot.max);
    -};
    -
    -
    -/**
    - * Returns the count of the statistic over its configured time
    - * interval.
    - * @param {number=} opt_now The time, in milliseconds, to be treated
    - *     as the "current" time.  The current time must always be greater
    - *     than or equal to the last time recorded by this stat tracker.
    - * @return {number} The total count over the tracked interval.
    - */
    -goog.stats.BasicStat.prototype.get = function(opt_now) {
    -  return this.reduceSlots_(opt_now,
    -      function(sum, slot) { return sum + slot.count; },
    -      0);
    -};
    -
    -
    -/**
    - * Returns the magnitute of the largest atomic increment that occurred
    - * during the watched time interval.
    - * @param {number=} opt_now The time, in milliseconds, to be treated
    - *     as the "current" time.  The current time must always be greater
    - *     than or equal to the last time recorded by this stat tracker.
    - * @return {number} The maximum count of this statistic.
    - */
    -goog.stats.BasicStat.prototype.getMax = function(opt_now) {
    -  return this.reduceSlots_(opt_now,
    -      function(max, slot) { return Math.max(max, slot.max); },
    -      Number.MIN_VALUE);
    -};
    -
    -
    -/**
    - * Returns the magnitute of the smallest atomic increment that
    - * occurred during the watched time interval.
    - * @param {number=} opt_now The time, in milliseconds, to be treated
    - *     as the "current" time.  The current time must always be greater
    - *     than or equal to the last time recorded by this stat tracker.
    - * @return {number} The minimum count of this statistic.
    - */
    -goog.stats.BasicStat.prototype.getMin = function(opt_now) {
    -  return this.reduceSlots_(opt_now,
    -      function(min, slot) { return Math.min(min, slot.min); },
    -      Number.MAX_VALUE);
    -};
    -
    -
    -/**
    - * Passes each active slot into a function and accumulates the result.
    - *
    - * @param {number|undefined} now The current time, in milliseconds.
    - * @param {function(number, goog.stats.BasicStat.Slot_): number} func
    - *     The function to call for every active slot.  This function
    - *     takes two arguments: the previous result and the new slot to
    - *     include in the reduction.
    - * @param {number} val The initial value for the reduction.
    - * @return {number} The result of the reduction.
    - * @private
    - */
    -goog.stats.BasicStat.prototype.reduceSlots_ = function(now, func, val) {
    -  now = now || goog.now();
    -  this.checkForTimeTravel_(now);
    -  var rval = val;
    -  var start = this.getSlotBoundary_(now) - this.interval_;
    -  for (var i = this.slots_.getCount() - 1; i >= 0; --i) {
    -    var slot = /** @type {goog.stats.BasicStat.Slot_} */ (this.slots_.get(i));
    -    if (slot.end <= start) {
    -      break;
    -    }
    -    rval = func(rval, slot);
    -  }
    -  return rval;
    -};
    -
    -
    -/**
    - * Computes the end time for the slot that should contain the count
    - * around the given time.  This method ensures that every bucket is
    - * aligned on a "this.slotInterval_" millisecond boundary.
    - * @param {number} time The time to compute a boundary for.
    - * @return {number} The computed boundary.
    - * @private
    - */
    -goog.stats.BasicStat.prototype.getSlotBoundary_ = function(time) {
    -  return this.slotInterval_ * (Math.floor(time / this.slotInterval_) + 1);
    -};
    -
    -
    -/**
    - * Checks that time never goes backwards.  If it does (for example,
    - * the user changes their system clock), the object state is cleared.
    - * @param {number} now The current time, in milliseconds.
    - * @private
    - */
    -goog.stats.BasicStat.prototype.checkForTimeTravel_ = function(now) {
    -  var slot = /** @type {goog.stats.BasicStat.Slot_} */ (this.slots_.getLast());
    -  if (slot) {
    -    var slotStart = slot.end - this.slotInterval_;
    -    if (now < slotStart) {
    -      goog.log.warning(this.logger_, goog.string.format(
    -          'Went backwards in time: now=%d, slotStart=%d.  Resetting state.',
    -          now, slotStart));
    -      this.reset_();
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Clears any statistics tracked by this object, as though it were
    - * freshly created.
    - * @private
    - */
    -goog.stats.BasicStat.prototype.reset_ = function() {
    -  this.slots_.clear();
    -};
    -
    -
    -
    -/**
    - * A struct containing information for each sub-interval.
    - * @param {number} end The end time for this slot, in milliseconds.
    - * @constructor
    - * @private
    - */
    -goog.stats.BasicStat.Slot_ = function(end) {
    -  /**
    -   * End time of this slot, exclusive.
    -   * @type {number}
    -   */
    -  this.end = end;
    -};
    -
    -
    -/**
    - * Aggregated count within this slot.
    - * @type {number}
    - */
    -goog.stats.BasicStat.Slot_.prototype.count = 0;
    -
    -
    -/**
    - * The smallest atomic increment of the count within this slot.
    - * @type {number}
    - */
    -goog.stats.BasicStat.Slot_.prototype.min = Number.MAX_VALUE;
    -
    -
    -/**
    - * The largest atomic increment of the count within this slot.
    - * @type {number}
    - */
    -goog.stats.BasicStat.Slot_.prototype.max = Number.MIN_VALUE;
    diff --git a/src/database/third_party/closure-library/closure/goog/stats/basicstat_test.html b/src/database/third_party/closure-library/closure/goog/stats/basicstat_test.html
    deleted file mode 100644
    index 78ba14bf584..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/stats/basicstat_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.stats.BasicStat
    -  </title>
    -  <script src="../base.js" type="text/javascript">
    -  </script>
    -  <script type="text/javascript">
    -    goog.require('goog.stats.BasicStatTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/stats/basicstat_test.js b/src/database/third_party/closure-library/closure/goog/stats/basicstat_test.js
    deleted file mode 100644
    index 912ed237055..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/stats/basicstat_test.js
    +++ /dev/null
    @@ -1,165 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.stats.BasicStatTest');
    -goog.setTestOnly('goog.stats.BasicStatTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.stats.BasicStat');
    -goog.require('goog.string.format');
    -goog.require('goog.testing.PseudoRandom');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -function testGetSlotBoundary() {
    -  var stat = new goog.stats.BasicStat(1654);
    -  assertEquals('Checking interval', 33, stat.slotInterval_);
    -
    -  assertEquals(132, stat.getSlotBoundary_(125));
    -  assertEquals(165, stat.getSlotBoundary_(132));
    -  assertEquals(132, stat.getSlotBoundary_(99));
    -  assertEquals(99, stat.getSlotBoundary_(98));
    -}
    -
    -function testCheckForTimeTravel() {
    -  var stat = new goog.stats.BasicStat(1000);
    -
    -  // no slots yet, should always be OK
    -  stat.checkForTimeTravel_(100);
    -  stat.checkForTimeTravel_(-1);
    -
    -  stat.incBy(1, 125); // creates a first bucket, ending at t=140
    -
    -  // Even though these go backwards in time, our basic fuzzy check passes
    -  // because we just check that the time is within the latest interval bucket.
    -  stat.checkForTimeTravel_(141);
    -  stat.checkForTimeTravel_(140);
    -  stat.checkForTimeTravel_(139);
    -  stat.checkForTimeTravel_(125);
    -  stat.checkForTimeTravel_(124);
    -  stat.checkForTimeTravel_(120);
    -
    -  // State should still be the same, all of the above times are valid.
    -  assertEquals('State unchanged when called with good times', 1, stat.get(125));
    -
    -  stat.checkForTimeTravel_(119);
    -  assertEquals('Reset after called with a bad time', 0, stat.get(125));
    -}
    -
    -function testConstantIncrementPerSlot() {
    -  var stat = new goog.stats.BasicStat(1000);
    -
    -  var now = 1000;
    -  for (var i = 0; i < 50; ++i) {
    -    var newMax = 1000 + i;
    -    var newMin = 1000 - i;
    -    stat.incBy(newMin, now);
    -    stat.incBy(newMax, now);
    -
    -    var msg = goog.string.format(
    -        'now=%d i=%d newMin=%d newMax=%d', now, i, newMin, newMax);
    -    assertEquals(msg, 2000 * (i + 1), stat.get(now));
    -    assertEquals(msg, newMax, stat.getMax(now));
    -    assertEquals(msg, newMin, stat.getMin(now));
    -
    -    now += 20; // push into the next slots
    -  }
    -
    -  // The next increment should cause old data to fall off.
    -  stat.incBy(1, now);
    -  assertEquals(2000 * 49 + 1, stat.get(now));
    -  assertEquals(1, stat.getMin(now));
    -  assertEquals(1049, stat.getMax(now));
    -
    -  now += 20; // drop off another bucket
    -  stat.incBy(1, now);
    -  assertEquals(2000 * 48 + 2, stat.get(now));
    -  assertEquals(1, stat.getMin(now));
    -  assertEquals(1049, stat.getMax(now));
    -}
    -
    -function testSparseBuckets() {
    -  var stat = new goog.stats.BasicStat(1000);
    -  var now = 1000;
    -
    -  stat.incBy(10, now);
    -  assertEquals(10, stat.get(now));
    -
    -  now += 5000; // the old slot is now still in memory, but should be ignored
    -  stat.incBy(1, now);
    -  assertEquals(1, stat.get(now));
    -}
    -
    -function testFuzzy() {
    -  var stat = new goog.stats.BasicStat(1000);
    -  var test = new PerfectlySlowStat(1000);
    -  var rand = new goog.testing.PseudoRandom(58849020);
    -  var eventCount = 0;
    -
    -  // test over 5 simulated seconds (2 for IE, due to timeouts)
    -  var simulationDuration = goog.userAgent.IE ? 2000 : 5000;
    -  for (var now = 1000; now < simulationDuration; ) {
    -    var count = Math.floor(rand.random() * 2147483648);
    -    var delay = Math.floor(rand.random() * 25);
    -    for (var i = 0; i <= delay; ++i) {
    -      var time = now + i;
    -      var msg = goog.string.format('now=%d eventCount=%d', time, eventCount);
    -      var expected = test.getStats(now + i);
    -      assertEquals(expected.count, stat.get(time));
    -      assertEquals(expected.min, stat.getMin(time));
    -      assertEquals(expected.max, stat.getMax(time));
    -    }
    -
    -    now += delay;
    -    stat.incBy(count, now);
    -    test.incBy(count, now);
    -    eventCount++;
    -  }
    -}
    -
    -
    -
    -/**
    - * A horribly inefficient implementation of BasicStat that stores
    - * every event in an array and dynamically filters to perform
    - * aggregations.
    - * @constructor
    - */
    -var PerfectlySlowStat = function(interval) {
    -  this.interval_ = interval;
    -  this.slotSize_ = Math.floor(interval / goog.stats.BasicStat.NUM_SLOTS_);
    -  this.events_ = [];
    -};
    -
    -PerfectlySlowStat.prototype.incBy = function(amt, now) {
    -  this.events_.push({'time': now, 'count': amt});
    -};
    -
    -PerfectlySlowStat.prototype.getStats = function(now) {
    -  var end = Math.floor(now / this.slotSize_) * this.slotSize_ + this.slotSize_;
    -  var start = end - this.interval_;
    -  var events = goog.array.filter(this.events_,
    -      function(e) { return e.time >= start });
    -  return {
    -    'count': goog.array.reduce(events,
    -        function(sum, e) { return sum + e.count },
    -        0),
    -    'min': goog.array.reduce(events,
    -        function(min, e) { return Math.min(min, e.count); },
    -        Number.MAX_VALUE),
    -    'max': goog.array.reduce(events,
    -        function(max, e) { return Math.max(max, e.count); },
    -        Number.MIN_VALUE)
    -  };
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/collectablestorage.js b/src/database/third_party/closure-library/closure/goog/storage/collectablestorage.js
    deleted file mode 100644
    index 96244069705..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/collectablestorage.js
    +++ /dev/null
    @@ -1,131 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides a convenient API for data persistence with data
    - * expiration and user-initiated expired key collection.
    - *
    - */
    -
    -goog.provide('goog.storage.CollectableStorage');
    -
    -goog.require('goog.array');
    -goog.require('goog.iter');
    -goog.require('goog.storage.ErrorCode');
    -goog.require('goog.storage.ExpiringStorage');
    -goog.require('goog.storage.RichStorage');
    -
    -
    -
    -/**
    - * Provides a storage with expirning keys and a collection method.
    - *
    - * @param {!goog.storage.mechanism.IterableMechanism} mechanism The underlying
    - *     storage mechanism.
    - * @constructor
    - * @extends {goog.storage.ExpiringStorage}
    - */
    -goog.storage.CollectableStorage = function(mechanism) {
    -  goog.storage.CollectableStorage.base(this, 'constructor', mechanism);
    -};
    -goog.inherits(goog.storage.CollectableStorage, goog.storage.ExpiringStorage);
    -
    -
    -/**
    - * Iterate over keys and returns those that expired.
    - *
    - * @param {goog.iter.Iterable} keys keys to iterate over.
    - * @param {boolean=} opt_strict Also return invalid keys.
    - * @return {!Array<string>} Keys of values that expired.
    - * @private
    - */
    -goog.storage.CollectableStorage.prototype.getExpiredKeys_ =
    -    function(keys, opt_strict) {
    -  var keysToRemove = [];
    -  goog.iter.forEach(keys, function(key) {
    -    // Get the wrapper.
    -    var wrapper;
    -    /** @preserveTry */
    -    try {
    -      wrapper = goog.storage.CollectableStorage.prototype.getWrapper.call(
    -          this, key, true);
    -    } catch (ex) {
    -      if (ex == goog.storage.ErrorCode.INVALID_VALUE) {
    -        // Bad wrappers are removed in strict mode.
    -        if (opt_strict) {
    -          keysToRemove.push(key);
    -        }
    -        // Skip over bad wrappers and continue.
    -        return;
    -      }
    -      // Unknown error, escalate.
    -      throw ex;
    -    }
    -    if (!goog.isDef(wrapper)) {
    -      // A value for a given key is no longer available. Clean it up.
    -      keysToRemove.push(key);
    -      return;
    -    }
    -    // Remove expired objects.
    -    if (goog.storage.ExpiringStorage.isExpired(wrapper)) {
    -      keysToRemove.push(key);
    -      // Continue with the next key.
    -      return;
    -    }
    -    // Objects which can't be decoded are removed in strict mode.
    -    if (opt_strict) {
    -      /** @preserveTry */
    -      try {
    -        goog.storage.RichStorage.Wrapper.unwrap(wrapper);
    -      } catch (ex) {
    -        if (ex == goog.storage.ErrorCode.INVALID_VALUE) {
    -          keysToRemove.push(key);
    -          // Skip over bad wrappers and continue.
    -          return;
    -        }
    -        // Unknown error, escalate.
    -        throw ex;
    -      }
    -    }
    -  }, this);
    -  return keysToRemove;
    -};
    -
    -
    -/**
    - * Cleans up the storage by removing expired keys.
    - *
    - * @param {Array<string>} keys List of all keys.
    - * @param {boolean=} opt_strict Also remove invalid keys.
    - * @return {!Array<string>} a list of expired keys.
    - * @protected
    - */
    -goog.storage.CollectableStorage.prototype.collectInternal = function(
    -    keys, opt_strict) {
    -  var keysToRemove = this.getExpiredKeys_(keys, opt_strict);
    -  goog.array.forEach(keysToRemove, function(key) {
    -    goog.storage.CollectableStorage.prototype.remove.call(this, key);
    -  }, this);
    -  return keysToRemove;
    -};
    -
    -
    -/**
    - * Cleans up the storage by removing expired keys.
    - *
    - * @param {boolean=} opt_strict Also remove invalid keys.
    - */
    -goog.storage.CollectableStorage.prototype.collect = function(opt_strict) {
    -  this.collectInternal(this.mechanism.__iterator__(true), opt_strict);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/collectablestorage_test.html b/src/database/third_party/closure-library/closure/goog/storage/collectablestorage_test.html
    deleted file mode 100644
    index 9b9d9c4c5ec..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/collectablestorage_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.storage.CollectableStorage
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.storage.CollectableStorageTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/collectablestorage_test.js b/src/database/third_party/closure-library/closure/goog/storage/collectablestorage_test.js
    deleted file mode 100644
    index f1b78f12ebc..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/collectablestorage_test.js
    +++ /dev/null
    @@ -1,38 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.storage.CollectableStorageTest');
    -goog.setTestOnly('goog.storage.CollectableStorageTest');
    -
    -goog.require('goog.storage.CollectableStorage');
    -goog.require('goog.storage.collectableStorageTester');
    -goog.require('goog.storage.storage_test');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.storage.FakeMechanism');
    -
    -function testBasicOperations() {
    -  var mechanism = new goog.testing.storage.FakeMechanism();
    -  var storage = new goog.storage.CollectableStorage(mechanism);
    -  goog.storage.storage_test.runBasicTests(storage);
    -}
    -
    -function testExpiredKeyCollection() {
    -  var mechanism = new goog.testing.storage.FakeMechanism();
    -  var clock = new goog.testing.MockClock(true);
    -  var storage = new goog.storage.CollectableStorage(mechanism);
    -
    -  goog.storage.collectableStorageTester.runBasicTests(mechanism, clock,
    -      storage);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/collectablestoragetester.js b/src/database/third_party/closure-library/closure/goog/storage/collectablestoragetester.js
    deleted file mode 100644
    index 439c42d6a83..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/collectablestoragetester.js
    +++ /dev/null
    @@ -1,71 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for the collectable storage interface.
    - *
    - */
    -
    -goog.provide('goog.storage.collectableStorageTester');
    -
    -goog.require('goog.testing.asserts');
    -goog.setTestOnly('collectablestorage_test');
    -
    -
    -/**
    - * Tests basic operation: expiration and collection of collectable storage.
    - *
    - * @param {goog.storage.mechanism.IterableMechanism} mechanism
    - * @param {goog.testing.MockClock} clock
    - * @param {goog.storage.CollectableStorage} storage
    -  */
    -goog.storage.collectableStorageTester.runBasicTests =
    -    function(mechanism, clock, storage) {
    -  // No expiration.
    -  storage.set('first', 'three seconds', 3000);
    -  storage.set('second', 'one second', 1000);
    -  storage.set('third', 'permanent');
    -  storage.set('fourth', 'two seconds', 2000);
    -  clock.tick(100);
    -  storage.collect();
    -  assertEquals('three seconds', storage.get('first'));
    -  assertEquals('one second', storage.get('second'));
    -  assertEquals('permanent', storage.get('third'));
    -  assertEquals('two seconds', storage.get('fourth'));
    -
    -  // A key has expired.
    -  clock.tick(1000);
    -  storage.collect();
    -  assertNull(mechanism.get('second'));
    -  assertEquals('three seconds', storage.get('first'));
    -  assertUndefined(storage.get('second'));
    -  assertEquals('permanent', storage.get('third'));
    -  assertEquals('two seconds', storage.get('fourth'));
    -
    -  // Another two keys have expired.
    -  clock.tick(2000);
    -  storage.collect();
    -  assertNull(mechanism.get('first'));
    -  assertNull(mechanism.get('fourth'));
    -  assertUndefined(storage.get('first'));
    -  assertEquals('permanent', storage.get('third'));
    -  assertUndefined(storage.get('fourth'));
    -
    -  // Clean up.
    -  storage.remove('third');
    -  assertNull(mechanism.get('third'));
    -  assertUndefined(storage.get('third'));
    -  storage.collect();
    -  clock.uninstall();
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/encryptedstorage.js b/src/database/third_party/closure-library/closure/goog/storage/encryptedstorage.js
    deleted file mode 100644
    index 5bd9ede6c26..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/encryptedstorage.js
    +++ /dev/null
    @@ -1,202 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides a convenient API for data persistence with key and
    - * object encryption. Without a valid secret, the existence of a particular
    - * key can't be verified and values can't be decrypted. The value encryption
    - * is salted, so subsequent writes of the same cleartext result in different
    - * ciphertext. The ciphertext is *not* authenticated, so there is no protection
    - * against data manipulation.
    - *
    - * The metadata is *not* encrypted, so expired keys can be cleaned up without
    - * decrypting them. If sensitive metadata is added in subclasses, it is up
    - * to the subclass to protect this information, perhaps by embedding it in
    - * the object.
    - *
    - */
    -
    -goog.provide('goog.storage.EncryptedStorage');
    -
    -goog.require('goog.crypt');
    -goog.require('goog.crypt.Arc4');
    -goog.require('goog.crypt.Sha1');
    -goog.require('goog.crypt.base64');
    -goog.require('goog.json');
    -goog.require('goog.json.Serializer');
    -goog.require('goog.storage.CollectableStorage');
    -goog.require('goog.storage.ErrorCode');
    -goog.require('goog.storage.RichStorage');
    -
    -
    -
    -/**
    - * Provides an encrypted storage. The keys are hashed with a secret, so
    - * their existence cannot be verified without the knowledge of the secret.
    - * The values are encrypted using the key, a salt, and the secret, so
    - * stream cipher initialization varies for each stored value.
    - *
    - * @param {!goog.storage.mechanism.IterableMechanism} mechanism The underlying
    - *     storage mechanism.
    - * @param {string} secret The secret key used to encrypt the storage.
    - * @constructor
    - * @extends {goog.storage.CollectableStorage}
    - * @final
    - */
    -goog.storage.EncryptedStorage = function(mechanism, secret) {
    -  goog.storage.EncryptedStorage.base(this, 'constructor', mechanism);
    -  this.secret_ = goog.crypt.stringToByteArray(secret);
    -  this.cleartextSerializer_ = new goog.json.Serializer();
    -};
    -goog.inherits(goog.storage.EncryptedStorage, goog.storage.CollectableStorage);
    -
    -
    -/**
    - * Metadata key under which the salt is stored.
    - *
    - * @type {string}
    - * @protected
    - */
    -goog.storage.EncryptedStorage.SALT_KEY = 'salt';
    -
    -
    -/**
    - * The secret used to encrypt the storage.
    - *
    - * @type {Array<number>}
    - * @private
    - */
    -goog.storage.EncryptedStorage.prototype.secret_ = null;
    -
    -
    -/**
    - * The JSON serializer used to serialize values before encryption. This can
    - * be potentially different from serializing for the storage mechanism (see
    - * goog.storage.Storage), so a separate serializer is kept here.
    - *
    - * @type {goog.json.Serializer}
    - * @private
    - */
    -goog.storage.EncryptedStorage.prototype.cleartextSerializer_ = null;
    -
    -
    -/**
    - * Hashes a key using the secret.
    - *
    - * @param {string} key The key.
    - * @return {string} The hash.
    - * @private
    - */
    -goog.storage.EncryptedStorage.prototype.hashKeyWithSecret_ = function(key) {
    -  var sha1 = new goog.crypt.Sha1();
    -  sha1.update(goog.crypt.stringToByteArray(key));
    -  sha1.update(this.secret_);
    -  return goog.crypt.base64.encodeByteArray(sha1.digest(), true);
    -};
    -
    -
    -/**
    - * Encrypts a value using a key, a salt, and the secret.
    - *
    - * @param {!Array<number>} salt The salt.
    - * @param {string} key The key.
    - * @param {string} value The cleartext value.
    - * @return {string} The encrypted value.
    - * @private
    - */
    -goog.storage.EncryptedStorage.prototype.encryptValue_ = function(
    -    salt, key, value) {
    -  if (!(salt.length > 0)) {
    -    throw Error('Non-empty salt must be provided');
    -  }
    -  var sha1 = new goog.crypt.Sha1();
    -  sha1.update(goog.crypt.stringToByteArray(key));
    -  sha1.update(salt);
    -  sha1.update(this.secret_);
    -  var arc4 = new goog.crypt.Arc4();
    -  arc4.setKey(sha1.digest());
    -  // Warm up the streamcypher state, see goog.crypt.Arc4 for details.
    -  arc4.discard(1536);
    -  var bytes = goog.crypt.stringToByteArray(value);
    -  arc4.crypt(bytes);
    -  return goog.crypt.byteArrayToString(bytes);
    -};
    -
    -
    -/**
    - * Decrypts a value using a key, a salt, and the secret.
    - *
    - * @param {!Array<number>} salt The salt.
    - * @param {string} key The key.
    - * @param {string} value The encrypted value.
    - * @return {string} The decrypted value.
    - * @private
    - */
    -goog.storage.EncryptedStorage.prototype.decryptValue_ = function(
    -    salt, key, value) {
    -  // ARC4 is symmetric.
    -  return this.encryptValue_(salt, key, value);
    -};
    -
    -
    -/** @override */
    -goog.storage.EncryptedStorage.prototype.set = function(
    -    key, value, opt_expiration) {
    -  if (!goog.isDef(value)) {
    -    goog.storage.EncryptedStorage.prototype.remove.call(this, key);
    -    return;
    -  }
    -  var salt = [];
    -  // 64-bit random salt.
    -  for (var i = 0; i < 8; ++i) {
    -    salt[i] = Math.floor(Math.random() * 0x100);
    -  }
    -  var wrapper = new goog.storage.RichStorage.Wrapper(
    -      this.encryptValue_(salt, key,
    -                         this.cleartextSerializer_.serialize(value)));
    -  wrapper[goog.storage.EncryptedStorage.SALT_KEY] = salt;
    -  goog.storage.EncryptedStorage.base(this, 'set',
    -      this.hashKeyWithSecret_(key), wrapper, opt_expiration);
    -};
    -
    -
    -/** @override */
    -goog.storage.EncryptedStorage.prototype.getWrapper = function(
    -    key, opt_expired) {
    -  var wrapper = goog.storage.EncryptedStorage.base(this, 'getWrapper',
    -      this.hashKeyWithSecret_(key), opt_expired);
    -  if (!wrapper) {
    -    return undefined;
    -  }
    -  var value = goog.storage.RichStorage.Wrapper.unwrap(wrapper);
    -  var salt = wrapper[goog.storage.EncryptedStorage.SALT_KEY];
    -  if (!goog.isString(value) || !goog.isArray(salt) || !salt.length) {
    -    throw goog.storage.ErrorCode.INVALID_VALUE;
    -  }
    -  var json = this.decryptValue_(salt, key, value);
    -  /** @preserveTry */
    -  try {
    -    wrapper[goog.storage.RichStorage.DATA_KEY] = goog.json.parse(json);
    -  } catch (e) {
    -    throw goog.storage.ErrorCode.DECRYPTION_ERROR;
    -  }
    -  return wrapper;
    -};
    -
    -
    -/** @override */
    -goog.storage.EncryptedStorage.prototype.remove = function(key) {
    -  goog.storage.EncryptedStorage.base(
    -      this, 'remove', this.hashKeyWithSecret_(key));
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/encryptedstorage_test.html b/src/database/third_party/closure-library/closure/goog/storage/encryptedstorage_test.html
    deleted file mode 100644
    index 15c34d6fa9c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/encryptedstorage_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.storage.EncryptedStorage
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.storage.EncryptedStorageTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/encryptedstorage_test.js b/src/database/third_party/closure-library/closure/goog/storage/encryptedstorage_test.js
    deleted file mode 100644
    index bd41907dd93..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/encryptedstorage_test.js
    +++ /dev/null
    @@ -1,167 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.storage.EncryptedStorageTest');
    -goog.setTestOnly('goog.storage.EncryptedStorageTest');
    -
    -goog.require('goog.json');
    -goog.require('goog.storage.EncryptedStorage');
    -goog.require('goog.storage.ErrorCode');
    -goog.require('goog.storage.RichStorage');
    -goog.require('goog.storage.collectableStorageTester');
    -goog.require('goog.storage.storage_test');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.PseudoRandom');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.storage.FakeMechanism');
    -
    -function getEncryptedWrapper(storage, key) {
    -  return goog.json.parse(
    -      storage.mechanism.get(storage.hashKeyWithSecret_(key)));
    -}
    -
    -function getEncryptedData(storage, key) {
    -  return getEncryptedWrapper(storage, key)[goog.storage.RichStorage.DATA_KEY];
    -}
    -
    -function decryptWrapper(storage, key, wrapper) {
    -  return goog.json.parse(
    -      storage.decryptValue_(wrapper[goog.storage.EncryptedStorage.SALT_KEY],
    -          key, wrapper[goog.storage.RichStorage.DATA_KEY]));
    -}
    -
    -function hammingDistance(a, b) {
    -  if (a.length != b.length) {
    -    throw Error('Lengths must be the same for Hamming distance');
    -  }
    -  var distance = 0;
    -  for (var i = 0; i < a.length; ++i) {
    -    if (a.charAt(i) != b.charAt(i)) {
    -      ++distance;
    -    }
    -  }
    -  return distance;
    -}
    -
    -
    -function testBasicOperations() {
    -  var mechanism = new goog.testing.storage.FakeMechanism();
    -  var storage = new goog.storage.EncryptedStorage(mechanism, 'secret');
    -  goog.storage.storage_test.runBasicTests(storage);
    -}
    -
    -
    -function testExpiredKeyCollection() {
    -  var mechanism = new goog.testing.storage.FakeMechanism();
    -  var clock = new goog.testing.MockClock(true);
    -  var storage = new goog.storage.EncryptedStorage(mechanism, 'secret');
    -
    -  goog.storage.collectableStorageTester.runBasicTests(mechanism, clock,
    -      storage);
    -}
    -
    -
    -function testEncryption() {
    -  var mechanism = new goog.testing.storage.FakeMechanism();
    -  var clock = new goog.testing.MockClock(true);
    -  var storage = new goog.storage.EncryptedStorage(mechanism, 'secret');
    -  var mallory = new goog.storage.EncryptedStorage(mechanism, 'guess');
    -
    -  // Simple Objects.
    -  storage.set('first', 'Hello world!');
    -  storage.set('second', ['one', 'two', 'three'], 1000);
    -  storage.set('third', {'a': 97, 'b': 98});
    -
    -  // Wrong secret can't find keys.
    -  assertNull(mechanism.get('first'));
    -  assertNull(mechanism.get('second'));
    -  assertNull(mechanism.get('third'));
    -  assertUndefined(mallory.get('first'));
    -  assertUndefined(mallory.get('second'));
    -  assertUndefined(mallory.get('third'));
    -
    -  // Wrong secret can't overwrite keys.
    -  mallory.set('first', 'Ho ho ho!');
    -  assertObjectEquals('Ho ho ho!', mallory.get('first'));
    -  assertObjectEquals('Hello world!', storage.get('first'));
    -  mallory.remove('first');
    -
    -  // Correct key decrypts properly.
    -  assertObjectEquals('Hello world!', storage.get('first'));
    -  assertObjectEquals(['one', 'two', 'three'], storage.get('second'));
    -  assertObjectEquals({'a': 97, 'b': 98}, storage.get('third'));
    -
    -  // Wrong secret can't decode values even if the key is revealed.
    -  var encryptedWrapper = getEncryptedWrapper(storage, 'first');
    -  assertObjectEquals('Hello world!',
    -      decryptWrapper(storage, 'first', encryptedWrapper));
    -  assertThrows(function() {
    -    decryptWrapper(mallory, 'first', encryptedWrapper);
    -  });
    -
    -  // If the value is overwritten, it can't be decrypted.
    -  encryptedWrapper[goog.storage.RichStorage.DATA_KEY] = 'kaboom';
    -  mechanism.set(storage.hashKeyWithSecret_('first'),
    -                goog.json.serialize(encryptedWrapper));
    -  assertEquals(goog.storage.ErrorCode.DECRYPTION_ERROR,
    -               assertThrows(function() {storage.get('first')}));
    -
    -  // Test garbage collection.
    -  storage.collect();
    -  assertNotNull(getEncryptedWrapper(storage, 'first'));
    -  assertObjectEquals(['one', 'two', 'three'], storage.get('second'));
    -  assertObjectEquals({'a': 97, 'b': 98}, storage.get('third'));
    -  clock.tick(2000);
    -  storage.collect();
    -  assertNotNull(getEncryptedWrapper(storage, 'first'));
    -  assertUndefined(storage.get('second'));
    -  assertObjectEquals({'a': 97, 'b': 98}, storage.get('third'));
    -  mechanism.set(storage.hashKeyWithSecret_('first'), '"kaboom"');
    -  storage.collect();
    -  assertNotNull(getEncryptedWrapper(storage, 'first'));
    -  assertObjectEquals({'a': 97, 'b': 98}, storage.get('third'));
    -  storage.collect(true);
    -  assertUndefined(storage.get('first'));
    -  assertObjectEquals({'a': 97, 'b': 98}, storage.get('third'));
    -
    -  // Clean up.
    -  storage.remove('third');
    -  assertUndefined(storage.get('third'));
    -  clock.uninstall();
    -}
    -
    -function testSalting() {
    -  var mechanism = new goog.testing.storage.FakeMechanism();
    -  var randomMock = new goog.testing.PseudoRandom(0, true);
    -  var storage = new goog.storage.EncryptedStorage(mechanism, 'secret');
    -
    -  // Same value under two different keys should appear very different,
    -  // even with the same salt.
    -  storage.set('one', 'Hello world!');
    -  randomMock.seed(0); // Reset the generator so we get the same salt.
    -  storage.set('two', 'Hello world!');
    -  var golden = getEncryptedData(storage, 'one');
    -  assertRoughlyEquals('Ciphertext did not change with keys', golden.length,
    -      hammingDistance(golden, getEncryptedData(storage, 'two')), 2);
    -
    -  // Same key-value pair written second time should appear very different.
    -  storage.set('one', 'Hello world!');
    -  assertRoughlyEquals('Salting seems to have failed', golden.length,
    -      hammingDistance(golden, getEncryptedData(storage, 'one')), 2);
    -
    -  // Clean up.
    -  storage.remove('1');
    -  storage.remove('2');
    -  randomMock.uninstall();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/errorcode.js b/src/database/third_party/closure-library/closure/goog/storage/errorcode.js
    deleted file mode 100644
    index 8fd19ecf94e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/errorcode.js
    +++ /dev/null
    @@ -1,30 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Defines errors to be thrown by the storage.
    - *
    - */
    -
    -goog.provide('goog.storage.ErrorCode');
    -
    -
    -/**
    - * Errors thrown by the storage.
    - * @enum {string}
    - */
    -goog.storage.ErrorCode = {
    -  INVALID_VALUE: 'Storage: Invalid value was encountered',
    -  DECRYPTION_ERROR: 'Storage: The value could not be decrypted'
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/expiringstorage.js b/src/database/third_party/closure-library/closure/goog/storage/expiringstorage.js
    deleted file mode 100644
    index 3a432e8166d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/expiringstorage.js
    +++ /dev/null
    @@ -1,140 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides a convenient API for data persistence with expiration.
    - *
    - */
    -
    -goog.provide('goog.storage.ExpiringStorage');
    -
    -goog.require('goog.storage.RichStorage');
    -
    -
    -
    -/**
    - * Provides a storage with expirning keys.
    - *
    - * @param {!goog.storage.mechanism.Mechanism} mechanism The underlying
    - *     storage mechanism.
    - * @constructor
    - * @extends {goog.storage.RichStorage}
    - */
    -goog.storage.ExpiringStorage = function(mechanism) {
    -  goog.storage.ExpiringStorage.base(this, 'constructor', mechanism);
    -};
    -goog.inherits(goog.storage.ExpiringStorage, goog.storage.RichStorage);
    -
    -
    -/**
    - * Metadata key under which the expiration time is stored.
    - *
    - * @type {string}
    - * @protected
    - */
    -goog.storage.ExpiringStorage.EXPIRATION_TIME_KEY = 'expiration';
    -
    -
    -/**
    - * Metadata key under which the creation time is stored.
    - *
    - * @type {string}
    - * @protected
    - */
    -goog.storage.ExpiringStorage.CREATION_TIME_KEY = 'creation';
    -
    -
    -/**
    - * Returns the wrapper creation time.
    - *
    - * @param {!Object} wrapper The wrapper.
    - * @return {number|undefined} Wrapper creation time.
    - */
    -goog.storage.ExpiringStorage.getCreationTime = function(wrapper) {
    -  return wrapper[goog.storage.ExpiringStorage.CREATION_TIME_KEY];
    -};
    -
    -
    -/**
    - * Returns the wrapper expiration time.
    - *
    - * @param {!Object} wrapper The wrapper.
    - * @return {number|undefined} Wrapper expiration time.
    - */
    -goog.storage.ExpiringStorage.getExpirationTime = function(wrapper) {
    -  return wrapper[goog.storage.ExpiringStorage.EXPIRATION_TIME_KEY];
    -};
    -
    -
    -/**
    - * Checks if the data item has expired.
    - *
    - * @param {!Object} wrapper The wrapper.
    - * @return {boolean} True if the item has expired.
    - */
    -goog.storage.ExpiringStorage.isExpired = function(wrapper) {
    -  var creation = goog.storage.ExpiringStorage.getCreationTime(wrapper);
    -  var expiration = goog.storage.ExpiringStorage.getExpirationTime(wrapper);
    -  return !!expiration && expiration < goog.now() ||
    -         !!creation && creation > goog.now();
    -};
    -
    -
    -/**
    - * Set an item in the storage.
    - *
    - * @param {string} key The key to set.
    - * @param {*} value The value to serialize to a string and save.
    - * @param {number=} opt_expiration The number of miliseconds since epoch
    - *     (as in goog.now()) when the value is to expire. If the expiration
    - *     time is not provided, the value will persist as long as possible.
    - * @override
    - */
    -goog.storage.ExpiringStorage.prototype.set = function(
    -    key, value, opt_expiration) {
    -  var wrapper = goog.storage.RichStorage.Wrapper.wrapIfNecessary(value);
    -  if (wrapper) {
    -    if (opt_expiration) {
    -      if (opt_expiration < goog.now()) {
    -        goog.storage.ExpiringStorage.prototype.remove.call(this, key);
    -        return;
    -      }
    -      wrapper[goog.storage.ExpiringStorage.EXPIRATION_TIME_KEY] =
    -          opt_expiration;
    -    }
    -    wrapper[goog.storage.ExpiringStorage.CREATION_TIME_KEY] = goog.now();
    -  }
    -  goog.storage.ExpiringStorage.base(this, 'set', key, wrapper);
    -};
    -
    -
    -/**
    - * Get an item wrapper (the item and its metadata) from the storage.
    - *
    - * @param {string} key The key to get.
    - * @param {boolean=} opt_expired If true, return expired wrappers as well.
    - * @return {(!Object|undefined)} The wrapper, or undefined if not found.
    - * @override
    - */
    -goog.storage.ExpiringStorage.prototype.getWrapper = function(key, opt_expired) {
    -  var wrapper = goog.storage.ExpiringStorage.base(this, 'getWrapper', key);
    -  if (!wrapper) {
    -    return undefined;
    -  }
    -  if (!opt_expired && goog.storage.ExpiringStorage.isExpired(wrapper)) {
    -    goog.storage.ExpiringStorage.prototype.remove.call(this, key);
    -    return undefined;
    -  }
    -  return wrapper;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/expiringstorage_test.html b/src/database/third_party/closure-library/closure/goog/storage/expiringstorage_test.html
    deleted file mode 100644
    index ae27966df95..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/expiringstorage_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.storage.ExpiringStorage
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.storage.ExpiringStorageTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/expiringstorage_test.js b/src/database/third_party/closure-library/closure/goog/storage/expiringstorage_test.js
    deleted file mode 100644
    index fa40243d97f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/expiringstorage_test.js
    +++ /dev/null
    @@ -1,85 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.storage.ExpiringStorageTest');
    -goog.setTestOnly('goog.storage.ExpiringStorageTest');
    -
    -goog.require('goog.storage.ExpiringStorage');
    -goog.require('goog.storage.storage_test');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.storage.FakeMechanism');
    -
    -function testBasicOperations() {
    -  var mechanism = new goog.testing.storage.FakeMechanism();
    -  var storage = new goog.storage.ExpiringStorage(mechanism);
    -  goog.storage.storage_test.runBasicTests(storage);
    -}
    -
    -function testExpiration() {
    -  var mechanism = new goog.testing.storage.FakeMechanism();
    -  var clock = new goog.testing.MockClock(true);
    -  var storage = new goog.storage.ExpiringStorage(mechanism);
    -
    -  // No expiration.
    -  storage.set('first', 'one second', 1000);
    -  storage.set('second', 'permanent');
    -  storage.set('third', 'two seconds', 2000);
    -  storage.set('fourth', 'permanent');
    -  clock.tick(100);
    -  assertEquals('one second', storage.get('first'));
    -  assertEquals('permanent', storage.get('second'));
    -  assertEquals('two seconds', storage.get('third'));
    -  assertEquals('permanent', storage.get('fourth'));
    -
    -  // A key has expired.
    -  clock.tick(1000);
    -  assertUndefined(storage.get('first'));
    -  assertEquals('permanent', storage.get('second'));
    -  assertEquals('two seconds', storage.get('third'));
    -  assertEquals('permanent', storage.get('fourth'));
    -  assertNull(mechanism.get('first'));
    -
    -  // Add an already expired key.
    -  storage.set('fourth', 'one second again', 1000);
    -  assertNull(mechanism.get('fourth'));
    -  assertUndefined(storage.get('fourth'));
    -
    -  // Another key has expired.
    -  clock.tick(1000);
    -  assertEquals('permanent', storage.get('second'));
    -  assertUndefined(storage.get('third'));
    -  assertNull(mechanism.get('third'));
    -
    -  // Clean up.
    -  storage.remove('second');
    -  assertNull(mechanism.get('second'));
    -  assertUndefined(storage.get('second'));
    -  clock.uninstall();
    -}
    -
    -function testClockSkew() {
    -  var mechanism = new goog.testing.storage.FakeMechanism();
    -  var storage = new goog.storage.ExpiringStorage(mechanism);
    -  var clock = new goog.testing.MockClock(true);
    -
    -  // Simulate clock skew.
    -  clock.tick(100);
    -  storage.set('first', 'one second', 1000);
    -  clock.reset();
    -  assertUndefined(storage.get('first'));
    -  assertNull(mechanism.get('first'));
    -
    -  clock.uninstall();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/mechanism/errorcode.js b/src/database/third_party/closure-library/closure/goog/storage/mechanism/errorcode.js
    deleted file mode 100644
    index 3d643503ffe..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/mechanism/errorcode.js
    +++ /dev/null
    @@ -1,31 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Defines error codes to be thrown by storage mechanisms.
    - *
    - */
    -
    -goog.provide('goog.storage.mechanism.ErrorCode');
    -
    -
    -/**
    - * Errors thrown by storage mechanisms.
    - * @enum {string}
    - */
    -goog.storage.mechanism.ErrorCode = {
    -  INVALID_VALUE: 'Storage mechanism: Invalid value was encountered',
    -  QUOTA_EXCEEDED: 'Storage mechanism: Quota exceeded',
    -  STORAGE_DISABLED: 'Storage mechanism: Storage disabled'
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/mechanism/errorhandlingmechanism.js b/src/database/third_party/closure-library/closure/goog/storage/mechanism/errorhandlingmechanism.js
    deleted file mode 100644
    index 1daab57d69e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/mechanism/errorhandlingmechanism.js
    +++ /dev/null
    @@ -1,130 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Wraps a storage mechanism with a custom error handler.
    - *
    - * @author ruilopes@google.com (Rui do Nascimento Dias Lopes)
    - */
    -
    -goog.provide('goog.storage.mechanism.ErrorHandlingMechanism');
    -
    -goog.require('goog.storage.mechanism.Mechanism');
    -
    -
    -
    -/**
    - * Wraps a storage mechanism with a custom error handler.
    - *
    - * @param {!goog.storage.mechanism.Mechanism} mechanism Underlying storage
    - *     mechanism.
    - * @param {goog.storage.mechanism.ErrorHandlingMechanism.ErrorHandler}
    - *     errorHandler An error handler.
    - * @constructor
    - * @extends {goog.storage.mechanism.Mechanism}
    - * @final
    - */
    -goog.storage.mechanism.ErrorHandlingMechanism = function(mechanism,
    -                                                         errorHandler) {
    -  goog.storage.mechanism.ErrorHandlingMechanism.base(this, 'constructor');
    -
    -  /**
    -   * The mechanism to be wrapped.
    -   * @type {!goog.storage.mechanism.Mechanism}
    -   * @private
    -   */
    -  this.mechanism_ = mechanism;
    -
    -  /**
    -   * The error handler.
    -   * @type {goog.storage.mechanism.ErrorHandlingMechanism.ErrorHandler}
    -   * @private
    -   */
    -  this.errorHandler_ = errorHandler;
    -};
    -goog.inherits(goog.storage.mechanism.ErrorHandlingMechanism,
    -              goog.storage.mechanism.Mechanism);
    -
    -
    -/**
    - * Valid storage mechanism operations.
    - * @enum {string}
    - */
    -goog.storage.mechanism.ErrorHandlingMechanism.Operation = {
    -  SET: 'set',
    -  GET: 'get',
    -  REMOVE: 'remove'
    -};
    -
    -
    -/**
    - * A function that handles errors raised in goog.storage.  Since some places in
    - * the goog.storage codebase throw strings instead of Error objects, we accept
    - * these as a valid parameter type.  It supports the following arguments:
    - *
    - * 1) The raised error (either in Error or string form);
    - * 2) The operation name which triggered the error, as defined per the
    - *    ErrorHandlingMechanism.Operation enum;
    - * 3) The key that is passed to a storage method;
    - * 4) An optional value that is passed to a storage method (only used in set
    - *    operations).
    - *
    - * @typedef {function(
    - *   (!Error|string),
    - *   goog.storage.mechanism.ErrorHandlingMechanism.Operation,
    - *   string,
    - *   *=)}
    - */
    -goog.storage.mechanism.ErrorHandlingMechanism.ErrorHandler;
    -
    -
    -/** @override */
    -goog.storage.mechanism.ErrorHandlingMechanism.prototype.set = function(key,
    -                                                                       value) {
    -  try {
    -    this.mechanism_.set(key, value);
    -  } catch (e) {
    -    this.errorHandler_(
    -        e,
    -        goog.storage.mechanism.ErrorHandlingMechanism.Operation.SET,
    -        key,
    -        value);
    -  }
    -};
    -
    -
    -/** @override */
    -goog.storage.mechanism.ErrorHandlingMechanism.prototype.get = function(key) {
    -  try {
    -    return this.mechanism_.get(key);
    -  } catch (e) {
    -    this.errorHandler_(
    -        e,
    -        goog.storage.mechanism.ErrorHandlingMechanism.Operation.GET,
    -        key);
    -  }
    -};
    -
    -
    -/** @override */
    -goog.storage.mechanism.ErrorHandlingMechanism.prototype.remove = function(key) {
    -  try {
    -    this.mechanism_.remove(key);
    -  } catch (e) {
    -    this.errorHandler_(
    -        e,
    -        goog.storage.mechanism.ErrorHandlingMechanism.Operation.REMOVE,
    -        key);
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/mechanism/errorhandlingmechanism_test.html b/src/database/third_party/closure-library/closure/goog/storage/mechanism/errorhandlingmechanism_test.html
    deleted file mode 100644
    index dbf13b2498b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/mechanism/errorhandlingmechanism_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    -Author:  ruilopes@google.com (Rui do Nascimento Dias Lopes)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.storage.mechanism.ErrorHandlingMechanism
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.storage.mechanism.ErrorHandlingMechanismTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/mechanism/errorhandlingmechanism_test.js b/src/database/third_party/closure-library/closure/goog/storage/mechanism/errorhandlingmechanism_test.js
    deleted file mode 100644
    index 3de6aeb885f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/mechanism/errorhandlingmechanism_test.js
    +++ /dev/null
    @@ -1,77 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.storage.mechanism.ErrorHandlingMechanismTest');
    -goog.setTestOnly('goog.storage.mechanism.ErrorHandlingMechanismTest');
    -
    -goog.require('goog.storage.mechanism.ErrorHandlingMechanism');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -
    -var error = new Error();
    -
    -var submechanism = {
    -  get: function() { throw error; },
    -  set: function() { throw error; },
    -  remove: function() { throw error; }
    -};
    -
    -var handler = goog.testing.recordFunction(goog.nullFunction);
    -var mechanism;
    -
    -function setUp() {
    -  mechanism = new goog.storage.mechanism.ErrorHandlingMechanism(
    -      submechanism, handler);
    -}
    -
    -function tearDown() {
    -  handler.reset();
    -}
    -
    -function testSet() {
    -  mechanism.set('foo', 'bar');
    -  assertEquals(1, handler.getCallCount());
    -  assertArrayEquals(
    -      [
    -        error,
    -        goog.storage.mechanism.ErrorHandlingMechanism.Operation.SET,
    -        'foo',
    -        'bar'
    -      ],
    -      handler.getLastCall().getArguments());
    -}
    -
    -function testGet() {
    -  mechanism.get('foo');
    -  assertEquals(1, handler.getCallCount());
    -  assertArrayEquals(
    -      [
    -        error,
    -        goog.storage.mechanism.ErrorHandlingMechanism.Operation.GET,
    -        'foo'
    -      ],
    -      handler.getLastCall().getArguments());
    -}
    -
    -function testRemove() {
    -  mechanism.remove('foo');
    -  assertEquals(1, handler.getCallCount());
    -  assertArrayEquals(
    -      [
    -        error,
    -        goog.storage.mechanism.ErrorHandlingMechanism.Operation.REMOVE,
    -        'foo'
    -      ],
    -      handler.getLastCall().getArguments());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/mechanism/html5localstorage.js b/src/database/third_party/closure-library/closure/goog/storage/mechanism/html5localstorage.js
    deleted file mode 100644
    index e35ad5c97c4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/mechanism/html5localstorage.js
    +++ /dev/null
    @@ -1,45 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides data persistence using HTML5 local storage
    - * mechanism. Local storage must be available under window.localStorage,
    - * see: http://www.w3.org/TR/webstorage/#the-localstorage-attribute.
    - *
    - */
    -
    -goog.provide('goog.storage.mechanism.HTML5LocalStorage');
    -
    -goog.require('goog.storage.mechanism.HTML5WebStorage');
    -
    -
    -
    -/**
    - * Provides a storage mechanism that uses HTML5 local storage.
    - *
    - * @constructor
    - * @extends {goog.storage.mechanism.HTML5WebStorage}
    - */
    -goog.storage.mechanism.HTML5LocalStorage = function() {
    -  var storage = null;
    -  /** @preserveTry */
    -  try {
    -    // May throw an exception in cases where the local storage object
    -    // is visible but access to it is disabled.
    -    storage = window.localStorage || null;
    -  } catch (e) {}
    -  goog.storage.mechanism.HTML5LocalStorage.base(this, 'constructor', storage);
    -};
    -goog.inherits(goog.storage.mechanism.HTML5LocalStorage,
    -              goog.storage.mechanism.HTML5WebStorage);
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/mechanism/html5localstorage_test.html b/src/database/third_party/closure-library/closure/goog/storage/mechanism/html5localstorage_test.html
    deleted file mode 100644
    index e1df6bd4215..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/mechanism/html5localstorage_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.storage.mechanism.HTML5LocalStorage
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.storage.mechanism.HTML5LocalStorageTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/mechanism/html5localstorage_test.js b/src/database/third_party/closure-library/closure/goog/storage/mechanism/html5localstorage_test.js
    deleted file mode 100644
    index 36ea04e43bf..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/mechanism/html5localstorage_test.js
    +++ /dev/null
    @@ -1,58 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.storage.mechanism.HTML5LocalStorageTest');
    -goog.setTestOnly('goog.storage.mechanism.HTML5LocalStorageTest');
    -
    -goog.require('goog.storage.mechanism.HTML5LocalStorage');
    -/** @suppress {extraRequire} */
    -goog.require('goog.storage.mechanism.mechanismSeparationTester');
    -/** @suppress {extraRequire} */
    -goog.require('goog.storage.mechanism.mechanismSharingTester');
    -/** @suppress {extraRequire} */
    -goog.require('goog.storage.mechanism.mechanismTestDefinition');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -function setUp() {
    -  var localStorage = new goog.storage.mechanism.HTML5LocalStorage();
    -  if (localStorage.isAvailable()) {
    -    mechanism = localStorage;
    -    // There should be at least 2 MiB.
    -    minimumQuota = 2 * 1024 * 1024;
    -    mechanism_shared = new goog.storage.mechanism.HTML5LocalStorage();
    -  }
    -}
    -
    -function tearDown() {
    -  if (!!mechanism) {
    -    mechanism.clear();
    -    mechanism = null;
    -  }
    -  if (!!mechanism_shared) {
    -    mechanism_shared.clear();
    -    mechanism_shared = null;
    -  }
    -}
    -
    -function testAvailability() {
    -  if (goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher('532.5') ||
    -      goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.9.1') ||
    -      goog.userAgent.IE && goog.userAgent.isVersionOrHigher('8')) {
    -    assertNotNull(mechanism);
    -    assertTrue(mechanism.isAvailable());
    -    assertNotNull(mechanism_shared);
    -    assertTrue(mechanism_shared.isAvailable());
    -  }
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/mechanism/html5sessionstorage.js b/src/database/third_party/closure-library/closure/goog/storage/mechanism/html5sessionstorage.js
    deleted file mode 100644
    index 688079a6d88..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/mechanism/html5sessionstorage.js
    +++ /dev/null
    @@ -1,46 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides data persistence using HTML5 session storage
    - * mechanism. Session storage must be available under window.sessionStorage,
    - * see: http://www.w3.org/TR/webstorage/#the-sessionstorage-attribute.
    - *
    - */
    -
    -goog.provide('goog.storage.mechanism.HTML5SessionStorage');
    -
    -goog.require('goog.storage.mechanism.HTML5WebStorage');
    -
    -
    -
    -/**
    - * Provides a storage mechanism that uses HTML5 session storage.
    - *
    - * @constructor
    - * @extends {goog.storage.mechanism.HTML5WebStorage}
    - */
    -goog.storage.mechanism.HTML5SessionStorage = function() {
    -  var storage = null;
    -  /** @preserveTry */
    -  try {
    -    // May throw an exception in cases where the session storage object is
    -    // visible but access to it is disabled. For example, accessing the file
    -    // in local mode in Firefox throws 'Operation is not supported' exception.
    -    storage = window.sessionStorage || null;
    -  } catch (e) {}
    -  goog.storage.mechanism.HTML5SessionStorage.base(this, 'constructor', storage);
    -};
    -goog.inherits(goog.storage.mechanism.HTML5SessionStorage,
    -              goog.storage.mechanism.HTML5WebStorage);
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/mechanism/html5sessionstorage_test.html b/src/database/third_party/closure-library/closure/goog/storage/mechanism/html5sessionstorage_test.html
    deleted file mode 100644
    index bae9a135836..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/mechanism/html5sessionstorage_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.storage.mechanism.HTML5SessionStorage
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.storage.mechanism.HTML5SessionStorageTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/mechanism/html5sessionstorage_test.js b/src/database/third_party/closure-library/closure/goog/storage/mechanism/html5sessionstorage_test.js
    deleted file mode 100644
    index b1fed0b6792..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/mechanism/html5sessionstorage_test.js
    +++ /dev/null
    @@ -1,59 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.storage.mechanism.HTML5SessionStorageTest');
    -goog.setTestOnly('goog.storage.mechanism.HTML5SessionStorageTest');
    -
    -goog.require('goog.storage.mechanism.HTML5SessionStorage');
    -/** @suppress {extraRequire} */
    -goog.require('goog.storage.mechanism.mechanismSeparationTester');
    -/** @suppress {extraRequire} */
    -goog.require('goog.storage.mechanism.mechanismSharingTester');
    -/** @suppress {extraRequire} */
    -goog.require('goog.storage.mechanism.mechanismTestDefinition');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -function setUp() {
    -  var sessionStorage = new goog.storage.mechanism.HTML5SessionStorage();
    -  if (sessionStorage.isAvailable()) {
    -    mechanism = sessionStorage;
    -    // There should be at least 2 MiB.
    -    minimumQuota = 2 * 1024 * 1024;
    -    mechanism_shared = new goog.storage.mechanism.HTML5SessionStorage();
    -  }
    -}
    -
    -function tearDown() {
    -  if (!!mechanism) {
    -    mechanism.clear();
    -    mechanism = null;
    -  }
    -  if (!!mechanism_shared) {
    -    mechanism_shared.clear();
    -    mechanism_shared = null;
    -  }
    -}
    -
    -function testAvailability() {
    -  if (goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher('532.5') ||
    -      goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.9.1') &&
    -      window.location.protocol != 'file:' ||
    -      goog.userAgent.IE && goog.userAgent.isVersionOrHigher('8')) {
    -    assertNotNull(mechanism);
    -    assertTrue(mechanism.isAvailable());
    -    assertNotNull(mechanism_shared);
    -    assertTrue(mechanism_shared.isAvailable());
    -  }
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/mechanism/html5webstorage.js b/src/database/third_party/closure-library/closure/goog/storage/mechanism/html5webstorage.js
    deleted file mode 100644
    index 348ba986b42..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/mechanism/html5webstorage.js
    +++ /dev/null
    @@ -1,171 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Base class that implements functionality common
    - * across both session and local web storage mechanisms.
    - *
    - */
    -
    -goog.provide('goog.storage.mechanism.HTML5WebStorage');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.iter.Iterator');
    -goog.require('goog.iter.StopIteration');
    -goog.require('goog.storage.mechanism.ErrorCode');
    -goog.require('goog.storage.mechanism.IterableMechanism');
    -
    -
    -
    -/**
    - * Provides a storage mechanism that uses HTML5 Web storage.
    - *
    - * @param {Storage} storage The Web storage object.
    - * @constructor
    - * @extends {goog.storage.mechanism.IterableMechanism}
    - */
    -goog.storage.mechanism.HTML5WebStorage = function(storage) {
    -  goog.storage.mechanism.HTML5WebStorage.base(this, 'constructor');
    -
    -  /**
    -   * The web storage object (window.localStorage or window.sessionStorage).
    -   * @private {Storage}
    -   */
    -  this.storage_ = storage;
    -};
    -goog.inherits(goog.storage.mechanism.HTML5WebStorage,
    -              goog.storage.mechanism.IterableMechanism);
    -
    -
    -/**
    - * The key used to check if the storage instance is available.
    - * @private {string}
    - * @const
    - */
    -goog.storage.mechanism.HTML5WebStorage.STORAGE_AVAILABLE_KEY_ = '__sak';
    -
    -
    -/**
    - * Determines whether or not the mechanism is available.
    - * It works only if the provided web storage object exists and is enabled.
    - *
    - * @return {boolean} True if the mechanism is available.
    - */
    -goog.storage.mechanism.HTML5WebStorage.prototype.isAvailable = function() {
    -  if (!this.storage_) {
    -    return false;
    -  }
    -  /** @preserveTry */
    -  try {
    -    // setItem will throw an exception if we cannot access WebStorage (e.g.,
    -    // Safari in private mode).
    -    this.storage_.setItem(
    -        goog.storage.mechanism.HTML5WebStorage.STORAGE_AVAILABLE_KEY_, '1');
    -    this.storage_.removeItem(
    -        goog.storage.mechanism.HTML5WebStorage.STORAGE_AVAILABLE_KEY_);
    -    return true;
    -  } catch (e) {
    -    return false;
    -  }
    -};
    -
    -
    -/** @override */
    -goog.storage.mechanism.HTML5WebStorage.prototype.set = function(key, value) {
    -  /** @preserveTry */
    -  try {
    -    // May throw an exception if storage quota is exceeded.
    -    this.storage_.setItem(key, value);
    -  } catch (e) {
    -    // In Safari Private mode, conforming to the W3C spec, invoking
    -    // Storage.prototype.setItem will allways throw a QUOTA_EXCEEDED_ERR
    -    // exception.  Since it's impossible to verify if we're in private browsing
    -    // mode, we throw a different exception if the storage is empty.
    -    if (this.storage_.length == 0) {
    -      throw goog.storage.mechanism.ErrorCode.STORAGE_DISABLED;
    -    } else {
    -      throw goog.storage.mechanism.ErrorCode.QUOTA_EXCEEDED;
    -    }
    -  }
    -};
    -
    -
    -/** @override */
    -goog.storage.mechanism.HTML5WebStorage.prototype.get = function(key) {
    -  // According to W3C specs, values can be of any type. Since we only save
    -  // strings, any other type is a storage error. If we returned nulls for
    -  // such keys, i.e., treated them as non-existent, this would lead to a
    -  // paradox where a key exists, but it does not when it is retrieved.
    -  // http://www.w3.org/TR/2009/WD-webstorage-20091029/#the-storage-interface
    -  var value = this.storage_.getItem(key);
    -  if (!goog.isString(value) && !goog.isNull(value)) {
    -    throw goog.storage.mechanism.ErrorCode.INVALID_VALUE;
    -  }
    -  return value;
    -};
    -
    -
    -/** @override */
    -goog.storage.mechanism.HTML5WebStorage.prototype.remove = function(key) {
    -  this.storage_.removeItem(key);
    -};
    -
    -
    -/** @override */
    -goog.storage.mechanism.HTML5WebStorage.prototype.getCount = function() {
    -  return this.storage_.length;
    -};
    -
    -
    -/** @override */
    -goog.storage.mechanism.HTML5WebStorage.prototype.__iterator__ = function(
    -    opt_keys) {
    -  var i = 0;
    -  var storage = this.storage_;
    -  var newIter = new goog.iter.Iterator();
    -  newIter.next = function() {
    -    if (i >= storage.length) {
    -      throw goog.iter.StopIteration;
    -    }
    -    var key = goog.asserts.assertString(storage.key(i++));
    -    if (opt_keys) {
    -      return key;
    -    }
    -    var value = storage.getItem(key);
    -    // The value must exist and be a string, otherwise it is a storage error.
    -    if (!goog.isString(value)) {
    -      throw goog.storage.mechanism.ErrorCode.INVALID_VALUE;
    -    }
    -    return value;
    -  };
    -  return newIter;
    -};
    -
    -
    -/** @override */
    -goog.storage.mechanism.HTML5WebStorage.prototype.clear = function() {
    -  this.storage_.clear();
    -};
    -
    -
    -/**
    - * Gets the key for a given key index. If an index outside of
    - * [0..this.getCount()) is specified, this function returns null.
    - * @param {number} index A key index.
    - * @return {?string} A storage key, or null if the specified index is out of
    - *     range.
    - */
    -goog.storage.mechanism.HTML5WebStorage.prototype.key = function(index) {
    -  return this.storage_.key(index);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/mechanism/html5webstorage_test.html b/src/database/third_party/closure-library/closure/goog/storage/mechanism/html5webstorage_test.html
    deleted file mode 100644
    index 3de28e1ea71..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/mechanism/html5webstorage_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    -Author:  ruilopes@google.com (Rui do Nascimento Dias Lopes)
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.storage.mechanism.HTML5WebStorage
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.storage.mechanism.HTML5WebStorageTest');
    -  </script>
    -  <body>
    -  </body>
    - </head>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/mechanism/html5webstorage_test.js b/src/database/third_party/closure-library/closure/goog/storage/mechanism/html5webstorage_test.js
    deleted file mode 100644
    index 239478facb6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/mechanism/html5webstorage_test.js
    +++ /dev/null
    @@ -1,120 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.setTestOnly('goog.storage.mechanism.HTML5WebStorageTest');
    -goog.provide('goog.storage.mechanism.HTML5MockStorage');
    -goog.provide('goog.storage.mechanism.HTML5WebStorageTest');
    -goog.provide('goog.storage.mechanism.MockThrowableStorage');
    -
    -goog.require('goog.storage.mechanism.ErrorCode');
    -goog.require('goog.storage.mechanism.HTML5WebStorage');
    -goog.require('goog.testing.jsunit');
    -
    -
    -
    -/**
    - * A minimal WebStorage implementation that throws exceptions for disabled
    - * storage. Since we cannot have unit tests running in Safari private mode to
    - * test this, we need to mock an exception throwing when trying to set a value.
    - *
    - * @param {boolean=} opt_isStorageDisabled If true, throws exceptions emulating
    - *     Private browsing mode.  If false, storage quota will be marked as
    - *     exceeded.
    - * @constructor
    - */
    -goog.storage.mechanism.MockThrowableStorage = function(opt_isStorageDisabled) {
    -  this.isStorageDisabled_ = !!opt_isStorageDisabled;
    -  this.length = opt_isStorageDisabled ? 0 : 1;
    -};
    -
    -
    -/** @override */
    -goog.storage.mechanism.MockThrowableStorage.prototype.setItem =
    -    function(key, value) {
    -  if (this.isStorageDisabled_) {
    -    throw goog.storage.mechanism.ErrorCode.STORAGE_DISABLED;
    -  } else {
    -    throw goog.storage.mechanism.ErrorCode.QUOTA_EXCEEDED;
    -  }
    -};
    -
    -
    -/** @override */
    -goog.storage.mechanism.MockThrowableStorage.prototype.removeItem =
    -    function(key) {};
    -
    -
    -/**
    - * A very simple, dummy implementation of key(), merely to verify that calls to
    - * HTML5WebStorage#key are proxied through.
    - * @param {number} index A key index.
    - * @return {string} The key associated with that index.
    - */
    -goog.storage.mechanism.MockThrowableStorage.prototype.key = function(index) {
    -  return 'dummyKey';
    -};
    -
    -
    -
    -/**
    - * Provides an HTML5WebStorage wrapper for MockThrowableStorage.
    - *
    - * @constructor
    - * @extends {goog.storage.mechanism.HTML5WebStorage}
    - */
    -goog.storage.mechanism.HTML5MockStorage = function(opt_isStorageDisabled) {
    -  goog.base(
    -      this,
    -      new goog.storage.mechanism.MockThrowableStorage(opt_isStorageDisabled));
    -};
    -goog.inherits(goog.storage.mechanism.HTML5MockStorage,
    -              goog.storage.mechanism.HTML5WebStorage);
    -
    -
    -function testIsNotAvailableWhenQuotaExceeded() {
    -  var storage = new goog.storage.mechanism.HTML5MockStorage(false);
    -  assertFalse(storage.isAvailable());
    -}
    -
    -function testIsNotAvailableWhenStorageDisabled() {
    -  var storage = new goog.storage.mechanism.HTML5MockStorage(true);
    -  assertFalse(storage.isAvailable());
    -}
    -
    -function testSetThrowsExceptionWhenQuotaExceeded() {
    -  var storage = new goog.storage.mechanism.HTML5MockStorage(false);
    -  var isQuotaExceeded = false;
    -  try {
    -    storage.set('foobar', '1');
    -  } catch (e) {
    -    isQuotaExceeded = e == goog.storage.mechanism.ErrorCode.QUOTA_EXCEEDED;
    -  }
    -  assertTrue(isQuotaExceeded);
    -}
    -
    -function testSetThrowsExceptionWhenStorageDisabled() {
    -  var storage = new goog.storage.mechanism.HTML5MockStorage(true);
    -  var isStorageDisabled = false;
    -  try {
    -    storage.set('foobar', '1');
    -  } catch (e) {
    -    isStorageDisabled = e == goog.storage.mechanism.ErrorCode.STORAGE_DISABLED;
    -  }
    -  assertTrue(isStorageDisabled);
    -}
    -
    -function testKeyIterationWithKeyMethod() {
    -  var storage = new goog.storage.mechanism.HTML5MockStorage(true);
    -  assertEquals('dummyKey', storage.key(1));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/mechanism/ieuserdata.js b/src/database/third_party/closure-library/closure/goog/storage/mechanism/ieuserdata.js
    deleted file mode 100644
    index 3b9875a6ef4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/mechanism/ieuserdata.js
    +++ /dev/null
    @@ -1,284 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides data persistence using IE userData mechanism.
    - * UserData uses proprietary Element.addBehavior(), Element.load(),
    - * Element.save(), and Element.XMLDocument() methods, see:
    - * http://msdn.microsoft.com/en-us/library/ms531424(v=vs.85).aspx.
    - *
    - */
    -
    -goog.provide('goog.storage.mechanism.IEUserData');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.iter.Iterator');
    -goog.require('goog.iter.StopIteration');
    -goog.require('goog.storage.mechanism.ErrorCode');
    -goog.require('goog.storage.mechanism.IterableMechanism');
    -goog.require('goog.structs.Map');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Provides a storage mechanism using IE userData.
    - *
    - * @param {string} storageKey The key (store name) to store the data under.
    - * @param {string=} opt_storageNodeId The ID of the associated HTML element,
    - *     one will be created if not provided.
    - * @constructor
    - * @extends {goog.storage.mechanism.IterableMechanism}
    - * @final
    - */
    -goog.storage.mechanism.IEUserData = function(storageKey, opt_storageNodeId) {
    -  goog.storage.mechanism.IEUserData.base(this, 'constructor');
    -
    -  // Tested on IE6, IE7 and IE8. It seems that IE9 introduces some security
    -  // features which make persistent (loaded) node attributes invisible from
    -  // JavaScript.
    -  if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9)) {
    -    if (!goog.storage.mechanism.IEUserData.storageMap_) {
    -      goog.storage.mechanism.IEUserData.storageMap_ = new goog.structs.Map();
    -    }
    -    this.storageNode_ = /** @type {Element} */ (
    -        goog.storage.mechanism.IEUserData.storageMap_.get(storageKey));
    -    if (!this.storageNode_) {
    -      if (opt_storageNodeId) {
    -        this.storageNode_ = document.getElementById(opt_storageNodeId);
    -      } else {
    -        this.storageNode_ = document.createElement('userdata');
    -        // This is a special IE-only method letting us persist data.
    -        this.storageNode_['addBehavior']('#default#userData');
    -        document.body.appendChild(this.storageNode_);
    -      }
    -      goog.storage.mechanism.IEUserData.storageMap_.set(
    -          storageKey, this.storageNode_);
    -    }
    -    this.storageKey_ = storageKey;
    -
    -    /** @preserveTry */
    -    try {
    -      // Availability check.
    -      this.loadNode_();
    -    } catch (e) {
    -      this.storageNode_ = null;
    -    }
    -  }
    -};
    -goog.inherits(goog.storage.mechanism.IEUserData,
    -              goog.storage.mechanism.IterableMechanism);
    -
    -
    -/**
    - * Encoding map for characters which are not encoded by encodeURIComponent().
    - * See encodeKey_ documentation for encoding details.
    - *
    - * @type {!Object}
    - * @const
    - */
    -goog.storage.mechanism.IEUserData.ENCODE_MAP = {
    -  '.': '.2E',
    -  '!': '.21',
    -  '~': '.7E',
    -  '*': '.2A',
    -  '\'': '.27',
    -  '(': '.28',
    -  ')': '.29',
    -  '%': '.'
    -};
    -
    -
    -/**
    - * Global storageKey to storageNode map, so we save on reloading the storage.
    - *
    - * @type {goog.structs.Map}
    - * @private
    - */
    -goog.storage.mechanism.IEUserData.storageMap_ = null;
    -
    -
    -/**
    - * The document element used for storing data.
    - *
    - * @type {Element}
    - * @private
    - */
    -goog.storage.mechanism.IEUserData.prototype.storageNode_ = null;
    -
    -
    -/**
    - * The key to store the data under.
    - *
    - * @type {?string}
    - * @private
    - */
    -goog.storage.mechanism.IEUserData.prototype.storageKey_ = null;
    -
    -
    -/**
    - * Encodes anything other than [-a-zA-Z0-9_] using a dot followed by hex,
    - * and prefixes with underscore to form a valid and safe HTML attribute name.
    - *
    - * We use URI encoding to do the initial heavy lifting, then escape the
    - * remaining characters that we can't use. Since a valid attribute name can't
    - * contain the percent sign (%), we use a dot (.) as an escape character.
    - *
    - * @param {string} key The key to be encoded.
    - * @return {string} The encoded key.
    - * @private
    - */
    -goog.storage.mechanism.IEUserData.encodeKey_ = function(key) {
    -  // encodeURIComponent leaves - _ . ! ~ * ' ( ) unencoded.
    -  return '_' + encodeURIComponent(key).replace(/[.!~*'()%]/g, function(c) {
    -    return goog.storage.mechanism.IEUserData.ENCODE_MAP[c];
    -  });
    -};
    -
    -
    -/**
    - * Decodes a dot-encoded and character-prefixed key.
    - * See encodeKey_ documentation for encoding details.
    - *
    - * @param {string} key The key to be decoded.
    - * @return {string} The decoded key.
    - * @private
    - */
    -goog.storage.mechanism.IEUserData.decodeKey_ = function(key) {
    -  return decodeURIComponent(key.replace(/\./g, '%')).substr(1);
    -};
    -
    -
    -/**
    - * Determines whether or not the mechanism is available.
    - *
    - * @return {boolean} True if the mechanism is available.
    - */
    -goog.storage.mechanism.IEUserData.prototype.isAvailable = function() {
    -  return !!this.storageNode_;
    -};
    -
    -
    -/** @override */
    -goog.storage.mechanism.IEUserData.prototype.set = function(key, value) {
    -  this.storageNode_.setAttribute(
    -      goog.storage.mechanism.IEUserData.encodeKey_(key), value);
    -  this.saveNode_();
    -};
    -
    -
    -/** @override */
    -goog.storage.mechanism.IEUserData.prototype.get = function(key) {
    -  // According to Microsoft, values can be strings, numbers or booleans. Since
    -  // we only save strings, any other type is a storage error. If we returned
    -  // nulls for such keys, i.e., treated them as non-existent, this would lead
    -  // to a paradox where a key exists, but it does not when it is retrieved.
    -  // http://msdn.microsoft.com/en-us/library/ms531348(v=vs.85).aspx
    -  var value = this.storageNode_.getAttribute(
    -      goog.storage.mechanism.IEUserData.encodeKey_(key));
    -  if (!goog.isString(value) && !goog.isNull(value)) {
    -    throw goog.storage.mechanism.ErrorCode.INVALID_VALUE;
    -  }
    -  return value;
    -};
    -
    -
    -/** @override */
    -goog.storage.mechanism.IEUserData.prototype.remove = function(key) {
    -  this.storageNode_.removeAttribute(
    -      goog.storage.mechanism.IEUserData.encodeKey_(key));
    -  this.saveNode_();
    -};
    -
    -
    -/** @override */
    -goog.storage.mechanism.IEUserData.prototype.getCount = function() {
    -  return this.getNode_().attributes.length;
    -};
    -
    -
    -/** @override */
    -goog.storage.mechanism.IEUserData.prototype.__iterator__ = function(opt_keys) {
    -  var i = 0;
    -  var attributes = this.getNode_().attributes;
    -  var newIter = new goog.iter.Iterator();
    -  newIter.next = function() {
    -    if (i >= attributes.length) {
    -      throw goog.iter.StopIteration;
    -    }
    -    var item = goog.asserts.assert(attributes[i++]);
    -    if (opt_keys) {
    -      return goog.storage.mechanism.IEUserData.decodeKey_(item.nodeName);
    -    }
    -    var value = item.nodeValue;
    -    // The value must exist and be a string, otherwise it is a storage error.
    -    if (!goog.isString(value)) {
    -      throw goog.storage.mechanism.ErrorCode.INVALID_VALUE;
    -    }
    -    return value;
    -  };
    -  return newIter;
    -};
    -
    -
    -/** @override */
    -goog.storage.mechanism.IEUserData.prototype.clear = function() {
    -  var node = this.getNode_();
    -  for (var left = node.attributes.length; left > 0; left--) {
    -    node.removeAttribute(node.attributes[left - 1].nodeName);
    -  }
    -  this.saveNode_();
    -};
    -
    -
    -/**
    - * Loads the underlying storage node to the state we saved it to before.
    - *
    - * @private
    - */
    -goog.storage.mechanism.IEUserData.prototype.loadNode_ = function() {
    -  // This is a special IE-only method on Elements letting us persist data.
    -  this.storageNode_['load'](this.storageKey_);
    -};
    -
    -
    -/**
    - * Saves the underlying storage node.
    - *
    - * @private
    - */
    -goog.storage.mechanism.IEUserData.prototype.saveNode_ = function() {
    -  /** @preserveTry */
    -  try {
    -    // This is a special IE-only method on Elements letting us persist data.
    -    // Do not try to assign this.storageNode_['save'] to a variable, it does
    -    // not work. May throw an exception when the quota is exceeded.
    -    this.storageNode_['save'](this.storageKey_);
    -  } catch (e) {
    -    throw goog.storage.mechanism.ErrorCode.QUOTA_EXCEEDED;
    -  }
    -};
    -
    -
    -/**
    - * Returns the storage node.
    - *
    - * @return {!Element} Storage DOM Element.
    - * @private
    - */
    -goog.storage.mechanism.IEUserData.prototype.getNode_ = function() {
    -  // This is a special IE-only property letting us browse persistent data.
    -  var doc = /** @type {Document} */ (this.storageNode_['XMLDocument']);
    -  return doc.documentElement;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/mechanism/ieuserdata_test.html b/src/database/third_party/closure-library/closure/goog/storage/mechanism/ieuserdata_test.html
    deleted file mode 100644
    index 85e24695583..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/mechanism/ieuserdata_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.storage.mechanism.IEUserData
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.storage.mechanism.IEUserDataTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/mechanism/ieuserdata_test.js b/src/database/third_party/closure-library/closure/goog/storage/mechanism/ieuserdata_test.js
    deleted file mode 100644
    index 3393a306039..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/mechanism/ieuserdata_test.js
    +++ /dev/null
    @@ -1,75 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.storage.mechanism.IEUserDataTest');
    -goog.setTestOnly('goog.storage.mechanism.IEUserDataTest');
    -
    -goog.require('goog.storage.mechanism.IEUserData');
    -/** @suppress {extraRequire} */
    -goog.require('goog.storage.mechanism.mechanismSeparationTester');
    -/** @suppress {extraRequire} */
    -goog.require('goog.storage.mechanism.mechanismSharingTester');
    -/** @suppress {extraRequire} */
    -goog.require('goog.storage.mechanism.mechanismTestDefinition');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -function setUp() {
    -  var ieUserData = new goog.storage.mechanism.IEUserData('test');
    -  if (ieUserData.isAvailable()) {
    -    mechanism = ieUserData;
    -    // There should be at least 32 KiB.
    -    minimumQuota = 32 * 1024;
    -    mechanism_shared = new goog.storage.mechanism.IEUserData('test');
    -    mechanism_separate = new goog.storage.mechanism.IEUserData('test2');
    -  }
    -}
    -
    -function tearDown() {
    -  if (!!mechanism) {
    -    mechanism.clear();
    -    mechanism = null;
    -  }
    -  if (!!mechanism_shared) {
    -    mechanism_shared.clear();
    -    mechanism_shared = null;
    -  }
    -  if (!!mechanism_separate) {
    -    mechanism_separate.clear();
    -    mechanism_separate = null;
    -  }
    -}
    -
    -function testAvailability() {
    -  if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9)) {
    -    assertNotNull(mechanism);
    -    assertTrue(mechanism.isAvailable());
    -    assertNotNull(mechanism_shared);
    -    assertTrue(mechanism_shared.isAvailable());
    -    assertNotNull(mechanism_separate);
    -    assertTrue(mechanism_separate.isAvailable());
    -  }
    -}
    -
    -function testEncoding() {
    -  function assertEncodingPair(cleartext, encoded) {
    -    assertEquals(encoded,
    -                 goog.storage.mechanism.IEUserData.encodeKey_(cleartext));
    -    assertEquals(cleartext,
    -                 goog.storage.mechanism.IEUserData.decodeKey_(encoded));
    -  }
    -  assertEncodingPair('simple', '_simple');
    -  assertEncodingPair('aa.bb%cc!\0$\u4e00.',
    -                     '_aa.2Ebb.25cc.21.00.24.E4.B8.80.2E');
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/mechanism/iterablemechanism.js b/src/database/third_party/closure-library/closure/goog/storage/mechanism/iterablemechanism.js
    deleted file mode 100644
    index b5c6ced8ead..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/mechanism/iterablemechanism.js
    +++ /dev/null
    @@ -1,85 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Interface for storing, retieving and scanning data using some
    - * persistence mechanism.
    - *
    - */
    -
    -goog.provide('goog.storage.mechanism.IterableMechanism');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.iter');
    -goog.require('goog.storage.mechanism.Mechanism');
    -
    -
    -
    -/**
    - * Interface for all iterable storage mechanisms.
    - *
    - * @constructor
    - * @extends {goog.storage.mechanism.Mechanism}
    - */
    -goog.storage.mechanism.IterableMechanism = function() {
    -  goog.storage.mechanism.IterableMechanism.base(this, 'constructor');
    -};
    -goog.inherits(goog.storage.mechanism.IterableMechanism,
    -              goog.storage.mechanism.Mechanism);
    -
    -
    -/**
    - * Get the number of stored key-value pairs.
    - *
    - * Could be overridden in a subclass, as the default implementation is not very
    - * efficient - it iterates over all keys.
    - *
    - * @return {number} Number of stored elements.
    - */
    -goog.storage.mechanism.IterableMechanism.prototype.getCount = function() {
    -  var count = 0;
    -  goog.iter.forEach(this.__iterator__(true), function(key) {
    -    goog.asserts.assertString(key);
    -    count++;
    -  });
    -  return count;
    -};
    -
    -
    -/**
    - * Returns an iterator that iterates over the elements in the storage. Will
    - * throw goog.iter.StopIteration after the last element.
    - *
    - * @param {boolean=} opt_keys True to iterate over the keys. False to iterate
    - *     over the values.  The default value is false.
    - * @return {!goog.iter.Iterator} The iterator.
    - */
    -goog.storage.mechanism.IterableMechanism.prototype.__iterator__ =
    -    goog.abstractMethod;
    -
    -
    -/**
    - * Remove all key-value pairs.
    - *
    - * Could be overridden in a subclass, as the default implementation is not very
    - * efficient - it iterates over all keys.
    - */
    -goog.storage.mechanism.IterableMechanism.prototype.clear = function() {
    -  var keys = goog.iter.toArray(this.__iterator__(true));
    -  var selfObj = this;
    -  goog.array.forEach(keys, function(key) {
    -    selfObj.remove(key);
    -  });
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/mechanism/iterablemechanismtester.js b/src/database/third_party/closure-library/closure/goog/storage/mechanism/iterablemechanismtester.js
    deleted file mode 100644
    index 7e65b43a4aa..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/mechanism/iterablemechanismtester.js
    +++ /dev/null
    @@ -1,117 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for the iterable storage mechanism interface.
    - *
    - * These tests should be included in tests of any class extending
    - * goog.storage.mechanism.IterableMechanism.
    - *
    - */
    -
    -goog.provide('goog.storage.mechanism.iterableMechanismTester');
    -
    -goog.require('goog.iter.Iterator');
    -goog.require('goog.storage.mechanism.IterableMechanism');
    -goog.require('goog.testing.asserts');
    -goog.setTestOnly('iterableMechanismTester');
    -
    -
    -var mechanism = null;
    -
    -
    -function testCount() {
    -  if (!mechanism) {
    -    return;
    -  }
    -  assertEquals(0, mechanism.getCount());
    -  mechanism.set('first', 'one');
    -  assertEquals(1, mechanism.getCount());
    -  mechanism.set('second', 'two');
    -  assertEquals(2, mechanism.getCount());
    -  mechanism.set('first', 'three');
    -  assertEquals(2, mechanism.getCount());
    -}
    -
    -
    -function testIteratorBasics() {
    -  if (!mechanism) {
    -    return;
    -  }
    -  mechanism.set('first', 'one');
    -  assertEquals('first', mechanism.__iterator__(true).next());
    -  assertEquals('one', mechanism.__iterator__(false).next());
    -  var iterator = mechanism.__iterator__();
    -  assertEquals('one', iterator.next());
    -  assertEquals(goog.iter.StopIteration,
    -               assertThrows(iterator.next));
    -}
    -
    -
    -function testIteratorWithTwoValues() {
    -  if (!mechanism) {
    -    return;
    -  }
    -  mechanism.set('first', 'one');
    -  mechanism.set('second', 'two');
    -  assertSameElements(['one', 'two'], goog.iter.toArray(mechanism));
    -  assertSameElements(['first', 'second'],
    -                     goog.iter.toArray(mechanism.__iterator__(true)));
    -}
    -
    -
    -function testClear() {
    -  if (!mechanism) {
    -    return;
    -  }
    -  mechanism.set('first', 'one');
    -  mechanism.set('second', 'two');
    -  mechanism.clear();
    -  assertNull(mechanism.get('first'));
    -  assertNull(mechanism.get('second'));
    -  assertEquals(0, mechanism.getCount());
    -  assertEquals(goog.iter.StopIteration,
    -               assertThrows(mechanism.__iterator__(true).next));
    -  assertEquals(goog.iter.StopIteration,
    -               assertThrows(mechanism.__iterator__(false).next));
    -}
    -
    -
    -function testClearClear() {
    -  if (!mechanism) {
    -    return;
    -  }
    -  mechanism.clear();
    -  mechanism.clear();
    -  assertEquals(0, mechanism.getCount());
    -}
    -
    -
    -function testIteratorWithWeirdKeys() {
    -  if (!mechanism) {
    -    return;
    -  }
    -  mechanism.set(' ', 'space');
    -  mechanism.set('=+!@#$%^&*()-_\\|;:\'",./<>?[]{}~`', 'control');
    -  mechanism.set(
    -      '\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341', 'ten');
    -  assertEquals(3, mechanism.getCount());
    -  assertSameElements([
    -    ' ',
    -    '=+!@#$%^&*()-_\\|;:\'",./<>?[]{}~`',
    -    '\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341'
    -  ], goog.iter.toArray(mechanism.__iterator__(true)));
    -  mechanism.clear();
    -  assertEquals(0, mechanism.getCount());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/mechanism/mechanism.js b/src/database/third_party/closure-library/closure/goog/storage/mechanism/mechanism.js
    deleted file mode 100644
    index 4a41cd9ab72..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/mechanism/mechanism.js
    +++ /dev/null
    @@ -1,56 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Abstract interface for storing and retrieving data using
    - * some persistence mechanism.
    - *
    - */
    -
    -goog.provide('goog.storage.mechanism.Mechanism');
    -
    -
    -
    -/**
    - * Basic interface for all storage mechanisms.
    - *
    - * @constructor
    - */
    -goog.storage.mechanism.Mechanism = function() {};
    -
    -
    -/**
    - * Set a value for a key.
    - *
    - * @param {string} key The key to set.
    - * @param {string} value The string to save.
    - */
    -goog.storage.mechanism.Mechanism.prototype.set = goog.abstractMethod;
    -
    -
    -/**
    - * Get the value stored under a key.
    - *
    - * @param {string} key The key to get.
    - * @return {?string} The corresponding value, null if not found.
    - */
    -goog.storage.mechanism.Mechanism.prototype.get = goog.abstractMethod;
    -
    -
    -/**
    - * Remove a key and its value.
    - *
    - * @param {string} key The key to remove.
    - */
    -goog.storage.mechanism.Mechanism.prototype.remove = goog.abstractMethod;
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/mechanism/mechanismfactory.js b/src/database/third_party/closure-library/closure/goog/storage/mechanism/mechanismfactory.js
    deleted file mode 100644
    index ac1da6796e1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/mechanism/mechanismfactory.js
    +++ /dev/null
    @@ -1,112 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides factory methods for selecting the best storage
    - * mechanism, depending on availability and needs.
    - *
    - */
    -
    -goog.provide('goog.storage.mechanism.mechanismfactory');
    -
    -goog.require('goog.storage.mechanism.HTML5LocalStorage');
    -goog.require('goog.storage.mechanism.HTML5SessionStorage');
    -goog.require('goog.storage.mechanism.IEUserData');
    -goog.require('goog.storage.mechanism.PrefixedMechanism');
    -
    -
    -/**
    - * The key to shared userData storage.
    - * @type {string}
    - */
    -goog.storage.mechanism.mechanismfactory.USER_DATA_SHARED_KEY =
    -    'UserDataSharedStore';
    -
    -
    -/**
    - * Returns the best local storage mechanism, or null if unavailable.
    - * Local storage means that the database is placed on user's computer.
    - * The key-value database is normally shared between all the code paths
    - * that request it, so using an optional namespace is recommended. This
    - * provides separation and makes key collisions unlikely.
    - *
    - * @param {string=} opt_namespace Restricts the visibility to given namespace.
    - * @return {goog.storage.mechanism.IterableMechanism} Created mechanism or null.
    - */
    -goog.storage.mechanism.mechanismfactory.create = function(opt_namespace) {
    -  return goog.storage.mechanism.mechanismfactory.createHTML5LocalStorage(
    -      opt_namespace) ||
    -      goog.storage.mechanism.mechanismfactory.createIEUserData(opt_namespace);
    -};
    -
    -
    -/**
    - * Returns an HTML5 local storage mechanism, or null if unavailable.
    - * Since the HTML5 local storage does not support namespaces natively,
    - * and the key-value database is shared between all the code paths
    - * that request it, it is recommended that an optional namespace is
    - * used to provide key separation employing a prefix.
    - *
    - * @param {string=} opt_namespace Restricts the visibility to given namespace.
    - * @return {goog.storage.mechanism.IterableMechanism} Created mechanism or null.
    - */
    -goog.storage.mechanism.mechanismfactory.createHTML5LocalStorage = function(
    -    opt_namespace) {
    -  var storage = new goog.storage.mechanism.HTML5LocalStorage();
    -  if (storage.isAvailable()) {
    -    return opt_namespace ? new goog.storage.mechanism.PrefixedMechanism(
    -        storage, opt_namespace) : storage;
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * Returns an HTML5 session storage mechanism, or null if unavailable.
    - * Since the HTML5 session storage does not support namespaces natively,
    - * and the key-value database is shared between all the code paths
    - * that request it, it is recommended that an optional namespace is
    - * used to provide key separation employing a prefix.
    - *
    - * @param {string=} opt_namespace Restricts the visibility to given namespace.
    - * @return {goog.storage.mechanism.IterableMechanism} Created mechanism or null.
    - */
    -goog.storage.mechanism.mechanismfactory.createHTML5SessionStorage = function(
    -    opt_namespace) {
    -  var storage = new goog.storage.mechanism.HTML5SessionStorage();
    -  if (storage.isAvailable()) {
    -    return opt_namespace ? new goog.storage.mechanism.PrefixedMechanism(
    -        storage, opt_namespace) : storage;
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * Returns an IE userData local storage mechanism, or null if unavailable.
    - * Using an optional namespace is recommended to provide separation and
    - * avoid key collisions.
    - *
    - * @param {string=} opt_namespace Restricts the visibility to given namespace.
    - * @return {goog.storage.mechanism.IterableMechanism} Created mechanism or null.
    - */
    -goog.storage.mechanism.mechanismfactory.createIEUserData = function(
    -    opt_namespace) {
    -  var storage = new goog.storage.mechanism.IEUserData(opt_namespace ||
    -      goog.storage.mechanism.mechanismfactory.USER_DATA_SHARED_KEY);
    -  if (storage.isAvailable()) {
    -    return storage;
    -  }
    -  return null;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/mechanism/mechanismfactory_test.html b/src/database/third_party/closure-library/closure/goog/storage/mechanism/mechanismfactory_test.html
    deleted file mode 100644
    index 59a8e36968d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/mechanism/mechanismfactory_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.storage.mechanism.mechanismfactory
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.storage.mechanism.mechanismfactoryTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/mechanism/mechanismfactory_test.js b/src/database/third_party/closure-library/closure/goog/storage/mechanism/mechanismfactory_test.js
    deleted file mode 100644
    index a07e289cb46..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/mechanism/mechanismfactory_test.js
    +++ /dev/null
    @@ -1,49 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.storage.mechanism.mechanismfactoryTest');
    -goog.setTestOnly('goog.storage.mechanism.mechanismfactoryTest');
    -
    -goog.require('goog.storage.mechanism.mechanismfactory');
    -goog.require('goog.testing.jsunit');
    -
    -function setUp() {
    -  mechanism = goog.storage.mechanism.mechanismfactory.create('test');
    -  mechanism_shared = goog.storage.mechanism.mechanismfactory.create('test');
    -  mechanism_separate = goog.storage.mechanism.mechanismfactory.create('test2');
    -}
    -
    -function tearDown() {
    -  if (!!mechanism) {
    -    mechanism.clear();
    -    mechanism = null;
    -  }
    -  if (!!mechanism_shared) {
    -    mechanism_shared.clear();
    -    mechanism_shared = null;
    -  }
    -  if (!!mechanism_separate) {
    -    mechanism_separate.clear();
    -    mechanism_separate = null;
    -  }
    -}
    -
    -function testAvailability() {
    -  var probe = goog.storage.mechanism.mechanismfactory.create();
    -  if (!!probe) {
    -    assertNotNull(mechanism);
    -    assertNotNull(mechanism_shared);
    -    assertNotNull(mechanism_separate);
    -  }
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/mechanism/mechanismseparationtester.js b/src/database/third_party/closure-library/closure/goog/storage/mechanism/mechanismseparationtester.js
    deleted file mode 100644
    index a2b3264b850..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/mechanism/mechanismseparationtester.js
    +++ /dev/null
    @@ -1,89 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for storage mechanism separation.
    - *
    - * These tests should be included by tests of any mechanism which natively
    - * implements namespaces. There is no need to include those tests for mechanisms
    - * extending goog.storage.mechanism.PrefixedMechanism. Make sure a different
    - * namespace is used for each object.
    - *
    - */
    -
    -goog.provide('goog.storage.mechanism.mechanismSeparationTester');
    -
    -goog.require('goog.iter.StopIteration');
    -/** @suppress {extraRequire} */
    -goog.require('goog.storage.mechanism.mechanismTestDefinition');
    -goog.require('goog.testing.asserts');
    -
    -goog.setTestOnly('goog.storage.mechanism.mechanismSeparationTester');
    -
    -
    -function testSeparateSet() {
    -  if (!mechanism || !mechanism_separate) {
    -    return;
    -  }
    -  mechanism.set('first', 'one');
    -  assertNull(mechanism_separate.get('first'));
    -  assertEquals(0, mechanism_separate.getCount());
    -  assertEquals(goog.iter.StopIteration,
    -               assertThrows(mechanism_separate.__iterator__().next));
    -}
    -
    -
    -function testSeparateSetInverse() {
    -  if (!mechanism || !mechanism_separate) {
    -    return;
    -  }
    -  mechanism.set('first', 'one');
    -  mechanism_separate.set('first', 'two');
    -  assertEquals('one', mechanism.get('first'));
    -  assertEquals(1, mechanism.getCount());
    -  var iterator = mechanism.__iterator__();
    -  assertEquals('one', iterator.next());
    -  assertEquals(goog.iter.StopIteration,
    -               assertThrows(iterator.next));
    -}
    -
    -
    -function testSeparateRemove() {
    -  if (!mechanism || !mechanism_separate) {
    -    return;
    -  }
    -  mechanism.set('first', 'one');
    -  mechanism_separate.remove('first');
    -  assertEquals('one', mechanism.get('first'));
    -  assertEquals(1, mechanism.getCount());
    -  var iterator = mechanism.__iterator__();
    -  assertEquals('one', iterator.next());
    -  assertEquals(goog.iter.StopIteration,
    -               assertThrows(iterator.next));
    -}
    -
    -
    -function testSeparateClean() {
    -  if (!mechanism || !mechanism_separate) {
    -    return;
    -  }
    -  mechanism_separate.set('first', 'two');
    -  mechanism.clear();
    -  assertEquals('two', mechanism_separate.get('first'));
    -  assertEquals(1, mechanism_separate.getCount());
    -  var iterator = mechanism_separate.__iterator__();
    -  assertEquals('two', iterator.next());
    -  assertEquals(goog.iter.StopIteration,
    -               assertThrows(iterator.next));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/mechanism/mechanismsharingtester.js b/src/database/third_party/closure-library/closure/goog/storage/mechanism/mechanismsharingtester.js
    deleted file mode 100644
    index c40972e52e3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/mechanism/mechanismsharingtester.js
    +++ /dev/null
    @@ -1,85 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for storage mechanism sharing.
    - *
    - * These tests should be included in tests of any storage mechanism in which
    - * separate mechanism instances share the same underlying storage. Most (if
    - * not all) storage mechanisms should have this property. If the mechanism
    - * employs namespaces, make sure the same namespace is used for both objects.
    - *
    - */
    -
    -goog.provide('goog.storage.mechanism.mechanismSharingTester');
    -
    -goog.require('goog.iter.StopIteration');
    -/** @suppress {extraRequire} */
    -goog.require('goog.storage.mechanism.mechanismTestDefinition');
    -goog.require('goog.testing.asserts');
    -
    -
    -goog.setTestOnly('goog.storage.mechanism.mechanismSharingTester');
    -
    -function testSharedSet() {
    -  if (!mechanism || !mechanism_shared) {
    -    return;
    -  }
    -  mechanism.set('first', 'one');
    -  assertEquals('one', mechanism_shared.get('first'));
    -  assertEquals(1, mechanism_shared.getCount());
    -  var iterator = mechanism_shared.__iterator__();
    -  assertEquals('one', iterator.next());
    -  assertEquals(goog.iter.StopIteration,
    -               assertThrows(iterator.next));
    -}
    -
    -
    -function testSharedSetInverse() {
    -  if (!mechanism || !mechanism_shared) {
    -    return;
    -  }
    -  mechanism_shared.set('first', 'two');
    -  assertEquals('two', mechanism.get('first'));
    -  assertEquals(1, mechanism.getCount());
    -  var iterator = mechanism.__iterator__();
    -  assertEquals('two', iterator.next());
    -  assertEquals(goog.iter.StopIteration,
    -               assertThrows(iterator.next));
    -}
    -
    -
    -function testSharedRemove() {
    -  if (!mechanism || !mechanism_shared) {
    -    return;
    -  }
    -  mechanism_shared.set('first', 'three');
    -  mechanism.remove('first');
    -  assertNull(mechanism_shared.get('first'));
    -  assertEquals(0, mechanism_shared.getCount());
    -  assertEquals(goog.iter.StopIteration,
    -               assertThrows(mechanism_shared.__iterator__().next));
    -}
    -
    -
    -function testSharedClean() {
    -  if (!mechanism || !mechanism_shared) {
    -    return;
    -  }
    -  mechanism.set('first', 'four');
    -  mechanism_shared.clear();
    -  assertEquals(0, mechanism.getCount());
    -  assertEquals(goog.iter.StopIteration,
    -               assertThrows(mechanism.__iterator__().next));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/mechanism/mechanismtestdefinition.js b/src/database/third_party/closure-library/closure/goog/storage/mechanism/mechanismtestdefinition.js
    deleted file mode 100644
    index 0e91e716429..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/mechanism/mechanismtestdefinition.js
    +++ /dev/null
    @@ -1,29 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview This shim namespace defines the shared
    - * mechanism variables used in mechanismSeparationTester
    - * and mechanismSelectionTester. This exists to allow test compilation
    - * to work correctly for these legacy tests.
    - * @visibility {//visibility:private}
    - */
    -
    -goog.provide('goog.storage.mechanism.mechanismTestDefinition');
    -goog.setTestOnly('goog.storage.mechanism.mechanismTestDefinition');
    -
    -var mechanism;
    -var mechanism_shared;
    -var mechanism_separate;
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/mechanism/mechanismtester.js b/src/database/third_party/closure-library/closure/goog/storage/mechanism/mechanismtester.js
    deleted file mode 100644
    index 0c37eb9c6b0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/mechanism/mechanismtester.js
    +++ /dev/null
    @@ -1,199 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for the abstract storage mechanism interface.
    - *
    - * These tests should be included in tests of any class extending
    - * goog.storage.mechanism.Mechanism.
    - *
    - */
    -
    -goog.provide('goog.storage.mechanism.mechanismTester');
    -
    -goog.require('goog.storage.mechanism.ErrorCode');
    -goog.require('goog.testing.asserts');
    -goog.require('goog.userAgent');
    -goog.require('goog.userAgent.product');
    -goog.require('goog.userAgent.product.isVersion');
    -goog.setTestOnly('goog.storage.mechanism.mechanismTester');
    -
    -
    -var mechanism = null;
    -var minimumQuota = 0;
    -
    -
    -function testSetGet() {
    -  if (!mechanism) {
    -    return;
    -  }
    -  mechanism.set('first', 'one');
    -  assertEquals('one', mechanism.get('first'));
    -}
    -
    -
    -function testChange() {
    -  if (!mechanism) {
    -    return;
    -  }
    -  mechanism.set('first', 'one');
    -  mechanism.set('first', 'two');
    -  assertEquals('two', mechanism.get('first'));
    -}
    -
    -
    -function testRemove() {
    -  if (!mechanism) {
    -    return;
    -  }
    -  mechanism.set('first', 'one');
    -  mechanism.remove('first');
    -  assertNull(mechanism.get('first'));
    -}
    -
    -
    -function testSetRemoveSet() {
    -  if (!mechanism) {
    -    return;
    -  }
    -  mechanism.set('first', 'one');
    -  mechanism.remove('first');
    -  mechanism.set('first', 'one');
    -  assertEquals('one', mechanism.get('first'));
    -}
    -
    -
    -function testRemoveRemove() {
    -  if (!mechanism) {
    -    return;
    -  }
    -  mechanism.remove('first');
    -  mechanism.remove('first');
    -  assertNull(mechanism.get('first'));
    -}
    -
    -
    -function testSetTwo() {
    -  if (!mechanism) {
    -    return;
    -  }
    -  mechanism.set('first', 'one');
    -  mechanism.set('second', 'two');
    -  assertEquals('one', mechanism.get('first'));
    -  assertEquals('two', mechanism.get('second'));
    -}
    -
    -
    -function testChangeTwo() {
    -  if (!mechanism) {
    -    return;
    -  }
    -  mechanism.set('first', 'one');
    -  mechanism.set('second', 'two');
    -  mechanism.set('second', 'three');
    -  mechanism.set('first', 'four');
    -  assertEquals('four', mechanism.get('first'));
    -  assertEquals('three', mechanism.get('second'));
    -}
    -
    -
    -function testSetRemoveThree() {
    -  if (!mechanism) {
    -    return;
    -  }
    -  mechanism.set('first', 'one');
    -  mechanism.set('second', 'two');
    -  mechanism.set('third', 'three');
    -  mechanism.remove('second');
    -  assertNull(mechanism.get('second'));
    -  assertEquals('one', mechanism.get('first'));
    -  assertEquals('three', mechanism.get('third'));
    -  mechanism.remove('first');
    -  assertNull(mechanism.get('first'));
    -  assertEquals('three', mechanism.get('third'));
    -  mechanism.remove('third');
    -  assertNull(mechanism.get('third'));
    -}
    -
    -
    -function testEmptyValue() {
    -  if (!mechanism) {
    -    return;
    -  }
    -  mechanism.set('third', '');
    -  assertEquals('', mechanism.get('third'));
    -}
    -
    -
    -function testWeirdKeys() {
    -  if (!mechanism) {
    -    return;
    -  }
    -  // Some weird keys. We leave out some tests for some browsers where they
    -  // trigger browser bugs, and where the keys are too obscure to prepare a
    -  // workaround.
    -  mechanism.set(' ', 'space');
    -  mechanism.set('=+!@#$%^&*()-_\\|;:\'",./<>?[]{}~`', 'control');
    -  mechanism.set(
    -      '\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341', 'ten');
    -  mechanism.set('\0', 'null');
    -  mechanism.set('\0\0', 'double null');
    -  mechanism.set('\0A', 'null A');
    -  mechanism.set('', 'zero');
    -  assertEquals('space', mechanism.get(' '));
    -  assertEquals('control', mechanism.get('=+!@#$%^&*()-_\\|;:\'",./<>?[]{}~`'));
    -  assertEquals('ten', mechanism.get(
    -      '\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341'));
    -  if (!goog.userAgent.IE) {
    -    // IE does not properly handle nulls in HTML5 localStorage keys (IE8, IE9).
    -    // https://connect.microsoft.com/IE/feedback/details/667799/
    -    assertEquals('null', mechanism.get('\0'));
    -    assertEquals('double null', mechanism.get('\0\0'));
    -    assertEquals('null A', mechanism.get('\0A'));
    -  }
    -  if (!goog.userAgent.GECKO) {
    -    // Firefox does not properly handle the empty key (FF 3.5, 3.6, 4.0).
    -    // https://bugzilla.mozilla.org/show_bug.cgi?id=510849
    -    assertEquals('zero', mechanism.get(''));
    -  }
    -}
    -
    -
    -function testQuota() {
    -  if (!mechanism) {
    -    return;
    -  }
    -  // This test might crash Safari 4, so it is disabled for this version.
    -  // It works fine on Safari 3 and Safari 5.
    -  if (goog.userAgent.product.SAFARI &&
    -      goog.userAgent.product.isVersion(4) &&
    -      !goog.userAgent.product.isVersion(5)) {
    -    return;
    -  }
    -  var buffer = '\u03ff'; // 2 bytes
    -  var savedBytes = 0;
    -  try {
    -    while (buffer.length < minimumQuota) {
    -      buffer = buffer + buffer;
    -      mechanism.set('foo', buffer);
    -      savedBytes = buffer.length;
    -    }
    -  } catch (ex) {
    -    if (ex != goog.storage.mechanism.ErrorCode.QUOTA_EXCEEDED) {
    -      throw ex;
    -    }
    -  }
    -  mechanism.remove('foo');
    -  assertTrue(savedBytes >= minimumQuota);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/mechanism/prefixedmechanism.js b/src/database/third_party/closure-library/closure/goog/storage/mechanism/prefixedmechanism.js
    deleted file mode 100644
    index 61414c6136c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/mechanism/prefixedmechanism.js
    +++ /dev/null
    @@ -1,98 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Wraps an iterable storage mechanism and creates artificial
    - * namespaces using a prefix in the global namespace.
    - *
    - */
    -
    -goog.provide('goog.storage.mechanism.PrefixedMechanism');
    -
    -goog.require('goog.iter.Iterator');
    -goog.require('goog.storage.mechanism.IterableMechanism');
    -
    -
    -
    -/**
    - * Wraps an iterable storage mechanism and creates artificial namespaces.
    - *
    - * @param {!goog.storage.mechanism.IterableMechanism} mechanism Underlying
    - *     iterable storage mechanism.
    - * @param {string} prefix Prefix for creating an artificial namespace.
    - * @constructor
    - * @extends {goog.storage.mechanism.IterableMechanism}
    - * @final
    - */
    -goog.storage.mechanism.PrefixedMechanism = function(mechanism, prefix) {
    -  goog.storage.mechanism.PrefixedMechanism.base(this, 'constructor');
    -  this.mechanism_ = mechanism;
    -  this.prefix_ = prefix + '::';
    -};
    -goog.inherits(goog.storage.mechanism.PrefixedMechanism,
    -              goog.storage.mechanism.IterableMechanism);
    -
    -
    -/**
    - * The mechanism to be prefixed.
    - *
    - * @type {goog.storage.mechanism.IterableMechanism}
    - * @private
    - */
    -goog.storage.mechanism.PrefixedMechanism.prototype.mechanism_ = null;
    -
    -
    -/**
    - * The prefix for creating artificial namespaces.
    - *
    - * @type {string}
    - * @private
    - */
    -goog.storage.mechanism.PrefixedMechanism.prototype.prefix_ = '';
    -
    -
    -/** @override */
    -goog.storage.mechanism.PrefixedMechanism.prototype.set = function(key, value) {
    -  this.mechanism_.set(this.prefix_ + key, value);
    -};
    -
    -
    -/** @override */
    -goog.storage.mechanism.PrefixedMechanism.prototype.get = function(key) {
    -  return this.mechanism_.get(this.prefix_ + key);
    -};
    -
    -
    -/** @override */
    -goog.storage.mechanism.PrefixedMechanism.prototype.remove = function(key) {
    -  this.mechanism_.remove(this.prefix_ + key);
    -};
    -
    -
    -/** @override */
    -goog.storage.mechanism.PrefixedMechanism.prototype.__iterator__ = function(
    -    opt_keys) {
    -  var subIter = this.mechanism_.__iterator__(true);
    -  var selfObj = this;
    -  var newIter = new goog.iter.Iterator();
    -  newIter.next = function() {
    -    var key = /** @type {string} */ (subIter.next());
    -    while (key.substr(0, selfObj.prefix_.length) != selfObj.prefix_) {
    -      key = /** @type {string} */ (subIter.next());
    -    }
    -    return opt_keys ? key.substr(selfObj.prefix_.length) :
    -                      selfObj.mechanism_.get(key);
    -  };
    -  return newIter;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/mechanism/prefixedmechanism_test.html b/src/database/third_party/closure-library/closure/goog/storage/mechanism/prefixedmechanism_test.html
    deleted file mode 100644
    index 71cf66e1e25..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/mechanism/prefixedmechanism_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.storage.mechanism.PrefixedMechanism
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.storage.mechanism.PrefixedMechanismTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/mechanism/prefixedmechanism_test.js b/src/database/third_party/closure-library/closure/goog/storage/mechanism/prefixedmechanism_test.js
    deleted file mode 100644
    index 963fec4df98..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/mechanism/prefixedmechanism_test.js
    +++ /dev/null
    @@ -1,61 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.storage.mechanism.PrefixedMechanismTest');
    -goog.setTestOnly('goog.storage.mechanism.PrefixedMechanismTest');
    -
    -goog.require('goog.storage.mechanism.HTML5LocalStorage');
    -goog.require('goog.storage.mechanism.PrefixedMechanism');
    -/** @suppress {extraRequire} */
    -goog.require('goog.storage.mechanism.mechanismSeparationTester');
    -/** @suppress {extraRequire} */
    -goog.require('goog.storage.mechanism.mechanismSharingTester');
    -goog.require('goog.testing.jsunit');
    -
    -var submechanism = null;
    -
    -function setUp() {
    -  submechanism = new goog.storage.mechanism.HTML5LocalStorage();
    -  if (submechanism.isAvailable()) {
    -    mechanism = new goog.storage.mechanism.PrefixedMechanism(
    -        submechanism, 'test');
    -    mechanism_shared = new goog.storage.mechanism.PrefixedMechanism(
    -        submechanism, 'test');
    -    mechanism_separate = new goog.storage.mechanism.PrefixedMechanism(
    -        submechanism, 'test2');
    -  }
    -}
    -
    -function tearDown() {
    -  if (!!mechanism) {
    -    mechanism.clear();
    -    mechanism = null;
    -  }
    -  if (!!mechanism_shared) {
    -    mechanism_shared.clear();
    -    mechanism_shared = null;
    -  }
    -  if (!!mechanism_separate) {
    -    mechanism_separate.clear();
    -    mechanism_separate = null;
    -  }
    -}
    -
    -function testAvailability() {
    -  if (submechanism.isAvailable()) {
    -    assertNotNull(mechanism);
    -    assertNotNull(mechanism_shared);
    -    assertNotNull(mechanism_separate);
    -  }
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/richstorage.js b/src/database/third_party/closure-library/closure/goog/storage/richstorage.js
    deleted file mode 100644
    index 7a0e5d07683..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/richstorage.js
    +++ /dev/null
    @@ -1,149 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides a convenient API for data with attached metadata
    - * persistence. You probably don't want to use this class directly as it
    - * does not save any metadata by itself. It only provides the necessary
    - * infrastructure for subclasses that need to save metadata along with
    - * values stored.
    - *
    - */
    -
    -goog.provide('goog.storage.RichStorage');
    -goog.provide('goog.storage.RichStorage.Wrapper');
    -
    -goog.require('goog.storage.ErrorCode');
    -goog.require('goog.storage.Storage');
    -
    -
    -
    -/**
    - * Provides a storage for data with attached metadata.
    - *
    - * @param {!goog.storage.mechanism.Mechanism} mechanism The underlying
    - *     storage mechanism.
    - * @constructor
    - * @extends {goog.storage.Storage}
    - */
    -goog.storage.RichStorage = function(mechanism) {
    -  goog.storage.RichStorage.base(this, 'constructor', mechanism);
    -};
    -goog.inherits(goog.storage.RichStorage, goog.storage.Storage);
    -
    -
    -/**
    - * Metadata key under which the actual data is stored.
    - *
    - * @type {string}
    - * @protected
    - */
    -goog.storage.RichStorage.DATA_KEY = 'data';
    -
    -
    -
    -/**
    - * Wraps a value so metadata can be associated with it. You probably want
    - * to use goog.storage.RichStorage.Wrapper.wrapIfNecessary to avoid multiple
    - * embeddings.
    - *
    - * @param {*} value The value to wrap.
    - * @constructor
    - * @final
    - */
    -goog.storage.RichStorage.Wrapper = function(value) {
    -  this[goog.storage.RichStorage.DATA_KEY] = value;
    -};
    -
    -
    -/**
    - * Convenience method for wrapping a value so metadata can be associated with
    - * it. No-op if the value is already wrapped or is undefined.
    - *
    - * @param {*} value The value to wrap.
    - * @return {(!goog.storage.RichStorage.Wrapper|undefined)} The wrapper.
    - */
    -goog.storage.RichStorage.Wrapper.wrapIfNecessary = function(value) {
    -  if (!goog.isDef(value) || value instanceof goog.storage.RichStorage.Wrapper) {
    -    return /** @type {(!goog.storage.RichStorage.Wrapper|undefined)} */ (value);
    -  }
    -  return new goog.storage.RichStorage.Wrapper(value);
    -};
    -
    -
    -/**
    - * Unwraps a value, any metadata is discarded (not returned). You might want to
    - * use goog.storage.RichStorage.Wrapper.unwrapIfPossible to handle cases where
    - * the wrapper is missing.
    - *
    - * @param {!Object} wrapper The wrapper.
    - * @return {*} The wrapped value.
    - */
    -goog.storage.RichStorage.Wrapper.unwrap = function(wrapper) {
    -  var value = wrapper[goog.storage.RichStorage.DATA_KEY];
    -  if (!goog.isDef(value)) {
    -    throw goog.storage.ErrorCode.INVALID_VALUE;
    -  }
    -  return value;
    -};
    -
    -
    -/**
    - * Convenience method for unwrapping a value. Returns undefined if the
    - * wrapper is missing.
    - *
    - * @param {(!Object|undefined)} wrapper The wrapper.
    - * @return {*} The wrapped value or undefined.
    - */
    -goog.storage.RichStorage.Wrapper.unwrapIfPossible = function(wrapper) {
    -  if (!wrapper) {
    -    return undefined;
    -  }
    -  return goog.storage.RichStorage.Wrapper.unwrap(wrapper);
    -};
    -
    -
    -/** @override */
    -goog.storage.RichStorage.prototype.set = function(key, value) {
    -  goog.storage.RichStorage.base(this, 'set', key,
    -      goog.storage.RichStorage.Wrapper.wrapIfNecessary(value));
    -};
    -
    -
    -/**
    - * Get an item wrapper (the item and its metadata) from the storage.
    - *
    - * WARNING: This returns an Object, which once used to be
    - * goog.storage.RichStorage.Wrapper. This is due to the fact
    - * that deserialized objects lose type information and it
    - * is hard to do proper typecasting in JavaScript. Be sure
    - * you know what you are doing when using the returned value.
    - *
    - * @param {string} key The key to get.
    - * @return {(!Object|undefined)} The wrapper, or undefined if not found.
    - */
    -goog.storage.RichStorage.prototype.getWrapper = function(key) {
    -  var wrapper = goog.storage.RichStorage.superClass_.get.call(this, key);
    -  if (!goog.isDef(wrapper) || wrapper instanceof Object) {
    -    return /** @type {(!Object|undefined)} */ (wrapper);
    -  }
    -  throw goog.storage.ErrorCode.INVALID_VALUE;
    -};
    -
    -
    -/** @override */
    -goog.storage.RichStorage.prototype.get = function(key) {
    -  return goog.storage.RichStorage.Wrapper.unwrapIfPossible(
    -      this.getWrapper(key));
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/richstorage_test.html b/src/database/third_party/closure-library/closure/goog/storage/richstorage_test.html
    deleted file mode 100644
    index bc8a66cc293..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/richstorage_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.storage.RichStorage
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.storage.RichStorageTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/richstorage_test.js b/src/database/third_party/closure-library/closure/goog/storage/richstorage_test.js
    deleted file mode 100644
    index 7d3edb26939..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/richstorage_test.js
    +++ /dev/null
    @@ -1,82 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.storage.RichStorageTest');
    -goog.setTestOnly('goog.storage.RichStorageTest');
    -
    -goog.require('goog.storage.ErrorCode');
    -goog.require('goog.storage.RichStorage');
    -goog.require('goog.storage.storage_test');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.storage.FakeMechanism');
    -
    -function testBasicOperations() {
    -  var mechanism = new goog.testing.storage.FakeMechanism();
    -  var storage = new goog.storage.RichStorage(mechanism);
    -  goog.storage.storage_test.runBasicTests(storage);
    -}
    -
    -function testWrapping() {
    -  var mechanism = new goog.testing.storage.FakeMechanism();
    -  var storage = new goog.storage.RichStorage(mechanism);
    -
    -  // Some metadata.
    -  var object = {'a': 97, 'b': 98};
    -  var wrapper = new goog.storage.RichStorage.Wrapper(object);
    -  wrapper['meta'] = 'info';
    -  storage.set('first', wrapper);
    -  assertObjectEquals(object, storage.get('first'));
    -  assertObjectEquals(wrapper, storage.getWrapper('first'));
    -  assertEquals('info', storage.getWrapper('first')['meta']);
    -
    -  // Multiple wrappings.
    -  var wrapper1 = goog.storage.RichStorage.Wrapper.wrapIfNecessary(object);
    -  wrapper1['some'] = 'meta';
    -  var wrapper2 = goog.storage.RichStorage.Wrapper.wrapIfNecessary(wrapper1);
    -  wrapper2['more'] = 'stuff';
    -  storage.set('second', wrapper2);
    -  assertObjectEquals(object, storage.get('second'));
    -  assertObjectEquals(wrapper2, storage.getWrapper('second'));
    -  assertEquals('meta', storage.getWrapper('second')['some']);
    -  assertEquals('stuff', storage.getWrapper('second')['more']);
    -
    -  // Invalid wrappings.
    -  mechanism.set('third', 'null');
    -  assertEquals(goog.storage.ErrorCode.INVALID_VALUE,
    -               assertThrows(function() {storage.get('third')}));
    -  mechanism.set('third', '{"meta": "data"}');
    -  assertEquals(goog.storage.ErrorCode.INVALID_VALUE,
    -               assertThrows(function() {storage.get('third')}));
    -
    -  // Weird values.
    -  var wrapperA = new goog.storage.RichStorage.Wrapper.wrapIfNecessary(null);
    -  wrapperA['one'] = 1;
    -  storage.set('first', wrapperA);
    -  assertObjectEquals(wrapperA, storage.getWrapper('first'));
    -  var wrapperB = new goog.storage.RichStorage.Wrapper.wrapIfNecessary('');
    -  wrapperA['two'] = [];
    -  storage.set('second', wrapperB);
    -  assertObjectEquals(wrapperB, storage.getWrapper('second'));
    -
    -  // Clean up.
    -  storage.remove('first');
    -  storage.remove('second');
    -  storage.remove('third');
    -  assertUndefined(storage.get('first'));
    -  assertUndefined(storage.get('second'));
    -  assertUndefined(storage.get('third'));
    -  assertNull(mechanism.get('first'));
    -  assertNull(mechanism.get('second'));
    -  assertNull(mechanism.get('third'));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/storage.js b/src/database/third_party/closure-library/closure/goog/storage/storage.js
    deleted file mode 100644
    index e35c722ca9b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/storage.js
    +++ /dev/null
    @@ -1,96 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides a convenient API for data persistence using a selected
    - * data storage mechanism.
    - *
    - */
    -
    -goog.provide('goog.storage.Storage');
    -
    -goog.require('goog.json');
    -goog.require('goog.storage.ErrorCode');
    -
    -
    -
    -/**
    - * The base implementation for all storage APIs.
    - *
    - * @param {!goog.storage.mechanism.Mechanism} mechanism The underlying
    - *     storage mechanism.
    - * @constructor
    - */
    -goog.storage.Storage = function(mechanism) {
    -  /**
    -   * The mechanism used to persist key-value pairs.
    -   *
    -   * @protected {goog.storage.mechanism.Mechanism}
    -   */
    -  this.mechanism = mechanism;
    -};
    -
    -
    -/**
    - * Sets an item in the data storage.
    - *
    - * @param {string} key The key to set.
    - * @param {*} value The value to serialize to a string and save.
    - */
    -goog.storage.Storage.prototype.set = function(key, value) {
    -  if (!goog.isDef(value)) {
    -    this.mechanism.remove(key);
    -    return;
    -  }
    -  this.mechanism.set(key, goog.json.serialize(value));
    -};
    -
    -
    -/**
    - * Gets an item from the data storage.
    - *
    - * @param {string} key The key to get.
    - * @return {*} Deserialized value or undefined if not found.
    - */
    -goog.storage.Storage.prototype.get = function(key) {
    -  var json;
    -  try {
    -    json = this.mechanism.get(key);
    -  } catch (e) {
    -    // If, for any reason, the value returned by a mechanism's get method is not
    -    // a string, an exception is thrown.  In this case, we must fail gracefully
    -    // instead of propagating the exception to clients.  See b/8095488 for
    -    // details.
    -    return undefined;
    -  }
    -  if (goog.isNull(json)) {
    -    return undefined;
    -  }
    -  /** @preserveTry */
    -  try {
    -    return goog.json.parse(json);
    -  } catch (e) {
    -    throw goog.storage.ErrorCode.INVALID_VALUE;
    -  }
    -};
    -
    -
    -/**
    - * Removes an item from the data storage.
    - *
    - * @param {string} key The key to remove.
    - */
    -goog.storage.Storage.prototype.remove = function(key) {
    -  this.mechanism.remove(key);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/storage_test.html b/src/database/third_party/closure-library/closure/goog/storage/storage_test.html
    deleted file mode 100644
    index 46802ff66d7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/storage_test.html
    +++ /dev/null
    @@ -1,64 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.storage.Storage</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.functions');
    -  goog.require('goog.storage.ErrorCode');
    -  goog.require('goog.storage.Storage');
    -  goog.require('goog.storage.mechanism.mechanismfactory');
    -  goog.require('goog.storage.storage_test');
    -  goog.require('goog.testing.jsunit');
    -  goog.require('goog.testing.storage.FakeMechanism');
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -function testBasicOperations() {
    -  var mechanism = new goog.testing.storage.FakeMechanism();
    -  var storage = new goog.storage.Storage(mechanism);
    -  goog.storage.storage_test.runBasicTests(storage);
    -}
    -
    -function testMechanismCommunication() {
    -  var mechanism = new goog.testing.storage.FakeMechanism();
    -  var storage = new goog.storage.Storage(mechanism);
    -
    -  // Invalid JSON.
    -  mechanism.set('first', '');
    -  assertEquals(goog.storage.ErrorCode.INVALID_VALUE,
    -               assertThrows(function() {storage.get('first')}));
    -  mechanism.set('second', '(');
    -  assertEquals(goog.storage.ErrorCode.INVALID_VALUE,
    -               assertThrows(function() {storage.get('second')}));
    -
    -  // Cleaning up.
    -  storage.remove('first');
    -  storage.remove('second');
    -  assertUndefined(storage.get('first'));
    -  assertUndefined(storage.get('second'));
    -  assertNull(mechanism.get('first'));
    -  assertNull(mechanism.get('second'));
    -}
    -
    -function testMechanismFailsGracefullyOnInvalidValue() {
    -  var mechanism = {
    -    get: goog.functions.error('Invalid value')
    -  };
    -  var storage = new goog.storage.Storage(mechanism);
    -  assertUndefined(storage.get('foobar'));
    -}
    -
    -</script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/storage/storage_test.js b/src/database/third_party/closure-library/closure/goog/storage/storage_test.js
    deleted file mode 100644
    index b8f4a51ec5a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/storage/storage_test.js
    +++ /dev/null
    @@ -1,59 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for the storage interface.
    - *
    - */
    -
    -goog.provide('goog.storage.storage_test');
    -
    -goog.require('goog.structs.Map');
    -goog.require('goog.testing.asserts');
    -goog.setTestOnly('storage_test');
    -
    -
    -goog.storage.storage_test.runBasicTests = function(storage) {
    -  // Simple Objects.
    -  storage.set('first', 'Hello world!');
    -  storage.set('second', ['one', 'two', 'three']);
    -  storage.set('third', {'a': 97, 'b': 98});
    -  assertEquals('Hello world!', storage.get('first'));
    -  assertObjectEquals(['one', 'two', 'three'], storage.get('second'));
    -  assertObjectEquals({'a': 97, 'b': 98}, storage.get('third'));
    -
    -  // Some more complex fun with a Map.
    -  var map = new goog.structs.Map();
    -  map.set('Alice', 'Hello world!');
    -  map.set('Bob', ['one', 'two', 'three']);
    -  map.set('Cecile', {'a': 97, 'b': 98});
    -  storage.set('first', map.toObject());
    -  assertObjectEquals(map.toObject(), storage.get('first'));
    -
    -  // Setting weird values.
    -  storage.set('second', null);
    -  assertEquals(null, storage.get('second'));
    -  storage.set('second', undefined);
    -  assertEquals(undefined, storage.get('second'));
    -  storage.set('second', '');
    -  assertEquals('', storage.get('second'));
    -
    -  // Clean up.
    -  storage.remove('first');
    -  storage.remove('second');
    -  storage.remove('third');
    -  assertUndefined(storage.get('first'));
    -  assertUndefined(storage.get('second'));
    -  assertUndefined(storage.get('third'));
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/string/const.js b/src/database/third_party/closure-library/closure/goog/string/const.js
    deleted file mode 100644
    index 76cac4fd4f6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/string/const.js
    +++ /dev/null
    @@ -1,182 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.string.Const');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.string.TypedString');
    -
    -
    -
    -/**
    - * Wrapper for compile-time-constant strings.
    - *
    - * Const is a wrapper for strings that can only be created from program
    - * constants (i.e., string literals).  This property relies on a custom Closure
    - * compiler check that {@code goog.string.Const.from} is only invoked on
    - * compile-time-constant expressions.
    - *
    - * Const is useful in APIs whose correct and secure use requires that certain
    - * arguments are not attacker controlled: Compile-time constants are inherently
    - * under the control of the application and not under control of external
    - * attackers, and hence are safe to use in such contexts.
    - *
    - * Instances of this type must be created via its factory method
    - * {@code goog.string.Const.from} and not by invoking its constructor.  The
    - * constructor intentionally takes no parameters and the type is immutable;
    - * hence only a default instance corresponding to the empty string can be
    - * obtained via constructor invocation.
    - *
    - * @see goog.string.Const#from
    - * @constructor
    - * @final
    - * @struct
    - * @implements {goog.string.TypedString}
    - */
    -goog.string.Const = function() {
    -  /**
    -   * The wrapped value of this Const object.  The field has a purposely ugly
    -   * name to make (non-compiled) code that attempts to directly access this
    -   * field stand out.
    -   * @private {string}
    -   */
    -  this.stringConstValueWithSecurityContract__googStringSecurityPrivate_ = '';
    -
    -  /**
    -   * A type marker used to implement additional run-time type checking.
    -   * @see goog.string.Const#unwrap
    -   * @const
    -   * @private
    -   */
    -  this.STRING_CONST_TYPE_MARKER__GOOG_STRING_SECURITY_PRIVATE_ =
    -      goog.string.Const.TYPE_MARKER_;
    -};
    -
    -
    -/**
    - * @override
    - * @const
    - */
    -goog.string.Const.prototype.implementsGoogStringTypedString = true;
    -
    -
    -/**
    - * Returns this Const's value a string.
    - *
    - * IMPORTANT: In code where it is security-relevant that an object's type is
    - * indeed {@code goog.string.Const}, use {@code goog.string.Const.unwrap}
    - * instead of this method.
    - *
    - * @see goog.string.Const#unwrap
    - * @override
    - */
    -goog.string.Const.prototype.getTypedStringValue = function() {
    -  return this.stringConstValueWithSecurityContract__googStringSecurityPrivate_;
    -};
    -
    -
    -/**
    - * Returns a debug-string representation of this value.
    - *
    - * To obtain the actual string value wrapped inside an object of this type,
    - * use {@code goog.string.Const.unwrap}.
    - *
    - * @see goog.string.Const#unwrap
    - * @override
    - */
    -goog.string.Const.prototype.toString = function() {
    -  return 'Const{' +
    -         this.stringConstValueWithSecurityContract__googStringSecurityPrivate_ +
    -         '}';
    -};
    -
    -
    -/**
    - * Performs a runtime check that the provided object is indeed an instance
    - * of {@code goog.string.Const}, and returns its value.
    - * @param {!goog.string.Const} stringConst The object to extract from.
    - * @return {string} The Const object's contained string, unless the run-time
    - *     type check fails. In that case, {@code unwrap} returns an innocuous
    - *     string, or, if assertions are enabled, throws
    - *     {@code goog.asserts.AssertionError}.
    - */
    -goog.string.Const.unwrap = function(stringConst) {
    -  // Perform additional run-time type-checking to ensure that stringConst is
    -  // indeed an instance of the expected type.  This provides some additional
    -  // protection against security bugs due to application code that disables type
    -  // checks.
    -  if (stringConst instanceof goog.string.Const &&
    -      stringConst.constructor === goog.string.Const &&
    -      stringConst.STRING_CONST_TYPE_MARKER__GOOG_STRING_SECURITY_PRIVATE_ ===
    -          goog.string.Const.TYPE_MARKER_) {
    -    return stringConst.
    -        stringConstValueWithSecurityContract__googStringSecurityPrivate_;
    -  } else {
    -    goog.asserts.fail('expected object of type Const, got \'' +
    -                      stringConst + '\'');
    -    return 'type_error:Const';
    -  }
    -};
    -
    -
    -/**
    - * Creates a Const object from a compile-time constant string.
    - *
    - * It is illegal to invoke this function on an expression whose
    - * compile-time-contant value cannot be determined by the Closure compiler.
    - *
    - * Correct invocations include,
    - * <pre>
    - *   var s = goog.string.Const.from('hello');
    - *   var t = goog.string.Const.from('hello' + 'world');
    - * </pre>
    - *
    - * In contrast, the following are illegal:
    - * <pre>
    - *   var s = goog.string.Const.from(getHello());
    - *   var t = goog.string.Const.from('hello' + world);
    - * </pre>
    - *
    - * TODO(user): Compile-time checks that this function is only called
    - * with compile-time constant expressions.
    - *
    - * @param {string} s A constant string from which to create a Const.
    - * @return {!goog.string.Const} A Const object initialized to stringConst.
    - */
    -goog.string.Const.from = function(s) {
    -  return goog.string.Const.create__googStringSecurityPrivate_(s);
    -};
    -
    -
    -/**
    - * Type marker for the Const type, used to implement additional run-time
    - * type checking.
    - * @const
    - * @private
    - */
    -goog.string.Const.TYPE_MARKER_ = {};
    -
    -
    -/**
    - * Utility method to create Const instances.
    - * @param {string} s The string to initialize the Const object with.
    - * @return {!goog.string.Const} The initialized Const object.
    - * @private
    - */
    -goog.string.Const.create__googStringSecurityPrivate_ = function(s) {
    -  var stringConst = new goog.string.Const();
    -  stringConst.stringConstValueWithSecurityContract__googStringSecurityPrivate_ =
    -      s;
    -  return stringConst;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/string/const_test.html b/src/database/third_party/closure-library/closure/goog/string/const_test.html
    deleted file mode 100644
    index 98a33fa7b47..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/string/const_test.html
    +++ /dev/null
    @@ -1,19 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.string</title>
    -<script src="../base.js"></script>
    -<script>
    -goog.require('goog.string.constTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/string/const_test.js b/src/database/third_party/closure-library/closure/goog/string/const_test.js
    deleted file mode 100644
    index 3da24c8e4f4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/string/const_test.js
    +++ /dev/null
    @@ -1,51 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.string.Const.
    - */
    -
    -goog.provide('goog.string.constTest');
    -
    -goog.require('goog.string.Const');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.string.constTest');
    -
    -
    -
    -function testConst() {
    -  var constString = goog.string.Const.from('blah');
    -  var extracted = goog.string.Const.unwrap(constString);
    -  assertEquals('blah', extracted);
    -  assertEquals('blah', constString.getTypedStringValue());
    -  assertEquals('Const{blah}', String(constString));
    -
    -  // Interface marker is present.
    -  assertTrue(constString.implementsGoogStringTypedString);
    -}
    -
    -
    -/** @suppress {checkTypes} */
    -function testUnwrap() {
    -  var evil = {};
    -  evil.constStringValueWithSecurityContract__googStringSecurityPrivate_ =
    -      'evil';
    -  evil.CONST_STRING_TYPE_MARKER__GOOG_STRING_SECURITY_PRIVATE_ = {};
    -
    -  var exception = assertThrows(function() {
    -    goog.string.Const.unwrap(evil);
    -  });
    -  assertTrue(exception.message.indexOf('expected object of type Const') > 0);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/string/linkify.js b/src/database/third_party/closure-library/closure/goog/string/linkify.js
    deleted file mode 100644
    index 6f7a7112cbc..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/string/linkify.js
    +++ /dev/null
    @@ -1,252 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Utility function for linkifying text.
    - * @author bolinfest@google.com (Michael Bolin)
    - */
    -
    -goog.provide('goog.string.linkify');
    -
    -goog.require('goog.string');
    -
    -
    -/**
    - * Takes a string of plain text and linkifies URLs and email addresses. For a
    - * URL (unless opt_attributes is specified), the target of the link will be
    - * _blank and it will have a rel=nofollow attribute applied to it so that links
    - * created by linkify will not be of interest to search engines.
    - * @param {string} text Plain text.
    - * @param {Object<string, string>=} opt_attributes Attributes to add to all
    - *      links created. Default are rel=nofollow and target=_blank. To clear
    - *      those default attributes set rel='' and target=''.
    - * @return {string} HTML Linkified HTML text. Any text that is not part of a
    - *      link will be HTML-escaped.
    - */
    -goog.string.linkify.linkifyPlainText = function(text, opt_attributes) {
    -  // This shortcut makes linkifyPlainText ~10x faster if text doesn't contain
    -  // URLs or email addresses and adds insignificant performance penalty if it
    -  // does.
    -  if (text.indexOf('@') == -1 &&
    -      text.indexOf('://') == -1 &&
    -      text.indexOf('www.') == -1 &&
    -      text.indexOf('Www.') == -1 &&
    -      text.indexOf('WWW.') == -1) {
    -    return goog.string.htmlEscape(text);
    -  }
    -
    -  var attributesMap = opt_attributes || {};
    -  // Set default options.
    -  if (!('rel' in attributesMap)) {
    -    attributesMap['rel'] = 'nofollow';
    -  }
    -  if (!('target' in attributesMap)) {
    -    attributesMap['target'] = '_blank';
    -  }
    -  // Creates attributes string from options.
    -  var attributesArray = [];
    -  for (var key in attributesMap) {
    -    if (attributesMap.hasOwnProperty(key) && attributesMap[key]) {
    -      attributesArray.push(
    -          goog.string.htmlEscape(key), '="',
    -          goog.string.htmlEscape(attributesMap[key]), '" ');
    -    }
    -  }
    -  var attributes = attributesArray.join('');
    -
    -  return text.replace(
    -      goog.string.linkify.FIND_LINKS_RE_,
    -      function(part, before, original, email, protocol) {
    -        var output = [goog.string.htmlEscape(before)];
    -        if (!original) {
    -          return output[0];
    -        }
    -        output.push('<a ', attributes, 'href="');
    -        /** @type {string} */
    -        var linkText;
    -        /** @type {string} */
    -        var afterLink;
    -        if (email) {
    -          output.push('mailto:');
    -          linkText = email;
    -          afterLink = '';
    -        } else {
    -          // This is a full url link.
    -          if (!protocol) {
    -            output.push('http://');
    -          }
    -          var splitEndingPunctuation =
    -              original.match(goog.string.linkify.ENDS_WITH_PUNCTUATION_RE_);
    -          // An open paren in the link will often be matched with a close paren
    -          // at the end, so skip cutting off ending punctuation if there's an
    -          // open paren. For example:
    -          // http://en.wikipedia.org/wiki/Titanic_(1997_film)
    -          if (splitEndingPunctuation && !goog.string.contains(original, '(')) {
    -            linkText = splitEndingPunctuation[1];
    -            afterLink = splitEndingPunctuation[2];
    -          } else {
    -            linkText = original;
    -            afterLink = '';
    -          }
    -        }
    -        linkText = goog.string.htmlEscape(linkText);
    -        afterLink = goog.string.htmlEscape(afterLink);
    -        output.push(linkText, '">', linkText, '</a>', afterLink);
    -        return output.join('');
    -      });
    -};
    -
    -
    -/**
    - * Gets the first URI in text.
    - * @param {string} text Plain text.
    - * @return {string} The first URL, or an empty string if not found.
    - */
    -goog.string.linkify.findFirstUrl = function(text) {
    -  var link = text.match(goog.string.linkify.URL_);
    -  return link != null ? link[0] : '';
    -};
    -
    -
    -/**
    - * Gets the first email address in text.
    - * @param {string} text Plain text.
    - * @return {string} The first email address, or an empty string if not found.
    - */
    -goog.string.linkify.findFirstEmail = function(text) {
    -  var email = text.match(goog.string.linkify.EMAIL_);
    -  return email != null ? email[0] : '';
    -};
    -
    -
    -/**
    - * If a series of these characters is at the end of a url, it will be considered
    - * punctuation and not part of the url.
    - * @type {string}
    - * @const
    - * @private
    - */
    -goog.string.linkify.ENDING_PUNCTUATION_CHARS_ = ':;,\\.?>\\]\\)!';
    -
    -
    -/**
    - * @type {!RegExp}
    - * @const
    - * @private
    - */
    -goog.string.linkify.ENDS_WITH_PUNCTUATION_RE_ = new RegExp(
    -    '^(.*?)([' + goog.string.linkify.ENDING_PUNCTUATION_CHARS_ + ']+)$');
    -
    -
    -/**
    - * Set of characters to be put into a regex character set ("[...]"), used to
    - * match against a url hostname and everything after it. It includes
    - * "#-@", which represents the characters "#$%&'()*+,-./0123456789:;<=>?@".
    - * @type {string}
    - * @const
    - * @private
    - */
    -goog.string.linkify.ACCEPTABLE_URL_CHARS_ = '\\w~#-@!\\[\\]';
    -
    -
    -/**
    - * List of all protocols patterns recognized in urls (mailto is handled in email
    - * matching).
    - * @type {!Array<string>}
    - * @const
    - * @private
    - */
    -goog.string.linkify.RECOGNIZED_PROTOCOLS_ = ['https?', 'ftp'];
    -
    -
    -/**
    - * Regular expression pattern that matches the beginning of an url.
    - * Contains a catching group to capture the scheme.
    - * @type {string}
    - * @const
    - * @private
    - */
    -goog.string.linkify.PROTOCOL_START_ =
    -    '(' + goog.string.linkify.RECOGNIZED_PROTOCOLS_.join('|') + ')://';
    -
    -
    -/**
    - * Regular expression pattern that matches the beginning of a typical
    - * http url without the http:// scheme.
    - * @type {string}
    - * @const
    - * @private
    - */
    -goog.string.linkify.WWW_START_ = 'www\\.';
    -
    -
    -/**
    - * Regular expression pattern that matches an url.
    - * @type {string}
    - * @const
    - * @private
    - */
    -goog.string.linkify.URL_ =
    -    '(?:' + goog.string.linkify.PROTOCOL_START_ + '|' +
    -    goog.string.linkify.WWW_START_ + ')\\w[' +
    -    goog.string.linkify.ACCEPTABLE_URL_CHARS_ + ']*';
    -
    -
    -/**
    - * Regular expression pattern that matches a top level domain.
    - * @type {string}
    - * @const
    - * @private
    - */
    -goog.string.linkify.TOP_LEVEL_DOMAIN_ =
    -    '(?:com|org|net|edu|gov' +
    -    // from http://www.iana.org/gtld/gtld.htm
    -    '|aero|biz|cat|coop|info|int|jobs|mobi|museum|name|pro|travel' +
    -    '|arpa|asia|xxx' +
    -    // a two letter country code
    -    '|[a-z][a-z])\\b';
    -
    -
    -/**
    - * Regular expression pattern that matches an email.
    - * Contains a catching group to capture the email without the optional "mailto:"
    - * prefix.
    - * @type {string}
    - * @const
    - * @private
    - */
    -goog.string.linkify.EMAIL_ =
    -    '(?:mailto:)?([\\w.+-]+@[A-Za-z0-9.-]+\\.' +
    -    goog.string.linkify.TOP_LEVEL_DOMAIN_ + ')';
    -
    -
    -/**
    - * Regular expression to match all the links (url or email) in a string.
    - * First match is text before first link, might be empty string.
    - * Second match is the original text that should be replaced by a link.
    - * Third match is the email address in the case of an email.
    - * Fourth match is the scheme of the url if specified.
    - * @type {!RegExp}
    - * @const
    - * @private
    - */
    -goog.string.linkify.FIND_LINKS_RE_ = new RegExp(
    -    // Match everything including newlines.
    -    '([\\S\\s]*?)(' +
    -    // Match email after a word break.
    -    '\\b' + goog.string.linkify.EMAIL_ + '|' +
    -    // Match url after a workd break.
    -    '\\b' + goog.string.linkify.URL_ + '|$)',
    -    'gi');
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/string/linkify_test.html b/src/database/third_party/closure-library/closure/goog/string/linkify_test.html
    deleted file mode 100644
    index d7785575bbe..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/string/linkify_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.string.linkify
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.string.linkifyTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/string/linkify_test.js b/src/database/third_party/closure-library/closure/goog/string/linkify_test.js
    deleted file mode 100644
    index b788b172f52..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/string/linkify_test.js
    +++ /dev/null
    @@ -1,455 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.string.linkifyTest');
    -goog.setTestOnly('goog.string.linkifyTest');
    -
    -goog.require('goog.string');
    -goog.require('goog.string.linkify');
    -goog.require('goog.testing.dom');
    -goog.require('goog.testing.jsunit');
    -
    -var div = document.createElement('div');
    -
    -function assertLinkify(comment, input, expected) {
    -  assertEquals(
    -      comment, expected,
    -      goog.string.linkify.linkifyPlainText(input, {rel: '', target: ''}));
    -}
    -
    -function testContainsNoLink() {
    -  assertLinkify(
    -      'Text does not contain any links',
    -      'Text with no links in it.',
    -      'Text with no links in it.');
    -}
    -
    -function testContainsALink() {
    -  assertLinkify(
    -      'Text only contains a link',
    -      'http://www.google.com/',
    -      '<a href="http://www.google.com/">http://www.google.com/<\/a>');
    -}
    -
    -function testStartsWithALink() {
    -  assertLinkify(
    -      'Text starts with a link',
    -      'http://www.google.com/ is a well known search engine',
    -      '<a href="http://www.google.com/">http://www.google.com/<\/a>' +
    -          ' is a well known search engine');
    -}
    -
    -function testEndsWithALink() {
    -  assertLinkify(
    -      'Text ends with a link',
    -      'Look at this search engine: http://www.google.com/',
    -      'Look at this search engine: ' +
    -          '<a href="http://www.google.com/">http://www.google.com/<\/a>');
    -}
    -
    -function testContainsOnlyEmail() {
    -  assertLinkify(
    -      'Text only contains an email address',
    -      'bolinfest@google.com',
    -      '<a href="mailto:bolinfest@google.com">bolinfest@google.com<\/a>');
    -}
    -
    -function testStartsWithAnEmail() {
    -  assertLinkify(
    -      'Text starts with an email address',
    -      'bolinfest@google.com wrote this test.',
    -      '<a href="mailto:bolinfest@google.com">bolinfest@google.com<\/a>' +
    -          ' wrote this test.');
    -}
    -
    -function testEndsWithAnEmail() {
    -  assertLinkify(
    -      'Text ends with an email address',
    -      'This test was written by bolinfest@google.com.',
    -      'This test was written by ' +
    -          '<a href="mailto:bolinfest@google.com">bolinfest@google.com<\/a>.');
    -}
    -
    -function testUrlWithPortNumber() {
    -  assertLinkify(
    -      'URL with a port number',
    -      'http://www.google.com:80/',
    -      '<a href="http://www.google.com:80/">http://www.google.com:80/<\/a>');
    -}
    -
    -function testUrlWithUserPasswordAndPortNumber() {
    -  assertLinkify(
    -      'URL with a user, a password and a port number',
    -      'http://lascap:p4ssw0rd@google.com:80/s?q=a&hl=en',
    -      '<a href="http://lascap:p4ssw0rd@google.com:80/s?q=a&amp;hl=en">' +
    -          'http://lascap:p4ssw0rd@google.com:80/s?q=a&amp;hl=en<\/a>');
    -}
    -
    -function testUrlWithUnderscore() {
    -  assertLinkify(
    -      'URL with an underscore',
    -      'http://www_foo.google.com/',
    -      '<a href="http://www_foo.google.com/">http://www_foo.google.com/<\/a>');
    -}
    -
    -function testInternalUrlWithoutDomain() {
    -  assertLinkify(
    -      'Internal URL without a proper domain',
    -      'http://tracker/1068594',
    -      '<a href="http://tracker/1068594">http://tracker/1068594<\/a>');
    -}
    -
    -function testInternalUrlOneChar() {
    -  assertLinkify(
    -      'Internal URL with a one char domain',
    -      'http://b',
    -      '<a href="http://b">http://b<\/a>');
    -}
    -
    -function testSecureInternalUrlWithoutDomain() {
    -  assertLinkify(
    -      'Secure Internal URL without a proper domain',
    -      'https://review/6594805',
    -      '<a href="https://review/6594805">https://review/6594805<\/a>');
    -}
    -
    -function testTwoUrls() {
    -  assertLinkify(
    -      'Text with two URLs in it',
    -      'I use both http://www.google.com and http://yahoo.com, don\'t you?',
    -      'I use both <a href="http://www.google.com">http://www.google.com<\/a> ' +
    -          'and <a href="http://yahoo.com">http://yahoo.com<\/a>, ' +
    -          goog.string.htmlEscape('don\'t you?'));
    -}
    -
    -function testGetParams() {
    -  assertLinkify(
    -      'URL with GET params',
    -      'http://google.com/?a=b&c=d&e=f',
    -      '<a href="http://google.com/?a=b&amp;c=d&amp;e=f">' +
    -          'http://google.com/?a=b&amp;c=d&amp;e=f<\/a>');
    -}
    -
    -function testGoogleCache() {
    -  assertLinkify(
    -      'Google search result from cache',
    -      'http://66.102.7.104/search?q=cache:I4LoMT6euUUJ:' +
    -          'www.google.com/intl/en/help/features.html+google+cache&hl=en',
    -      '<a href="http://66.102.7.104/search?q=cache:I4LoMT6euUUJ:' +
    -          'www.google.com/intl/en/help/features.html+google+cache&amp;hl=en">' +
    -          'http://66.102.7.104/search?q=cache:I4LoMT6euUUJ:' +
    -          'www.google.com/intl/en/help/features.html+google+cache&amp;hl=en' +
    -          '<\/a>');
    -}
    -
    -function testUrlWithoutHttp() {
    -  assertLinkify(
    -      'URL without http protocol',
    -      'It\'s faster to type www.google.com without the http:// in front.',
    -      goog.string.htmlEscape('It\'s faster to type ') +
    -          '<a href="http://www.google.com">www.google.com' +
    -          '<\/a> without the http:// in front.');
    -}
    -
    -function testUrlWithCapitalsWithoutHttp() {
    -  assertLinkify(
    -      'URL with capital letters without http protocol',
    -      'It\'s faster to type Www.google.com without the http:// in front.',
    -      goog.string.htmlEscape('It\'s faster to type ') +
    -          '<a href="http://Www.google.com">Www.google.com' +
    -          '<\/a> without the http:// in front.');
    -}
    -
    -function testUrlHashBang() {
    -  assertLinkify(
    -      'URL with #!',
    -      'Another test URL: ' +
    -      'https://www.google.com/testurls/#!/page',
    -      'Another test URL: ' +
    -      '<a href="https://www.google.com/testurls/#!/page">' +
    -      'https://www.google.com/testurls/#!/page<\/a>');
    -}
    -
    -function testTextLooksLikeUrlWithoutHttp() {
    -  assertLinkify(
    -      'Text looks like an url but is not',
    -      'This showww.is just great: www.is',
    -      'This showww.is just great: <a href="http://www.is">www.is<\/a>');
    -}
    -
    -function testEmailWithSubdomain() {
    -  assertLinkify(
    -      'Email with a subdomain',
    -      'Send mail to bolinfest@groups.google.com.',
    -      'Send mail to <a href="mailto:bolinfest@groups.google.com">' +
    -          'bolinfest@groups.google.com<\/a>.');
    -}
    -
    -function testEmailWithHyphen() {
    -  assertLinkify(
    -      'Email with a hyphen in the domain name',
    -      'Send mail to bolinfest@google-groups.com.',
    -      'Send mail to <a href="mailto:bolinfest@google-groups.com">' +
    -          'bolinfest@google-groups.com<\/a>.');
    -}
    -
    -function testEmailUsernameWithSpecialChars() {
    -  assertLinkify(
    -      'Email with a hyphen, period, and + in the user name',
    -      'Send mail to bolin-fest+for.um@google.com',
    -      'Send mail to <a href="mailto:bolin-fest+for.um@google.com">' +
    -          'bolin-fest+for.um@google.com<\/a>');
    -}
    -
    -function testEmailWithUnderscoreInvalid() {
    -  assertLinkify(
    -      'Email with an underscore in the domain name, which is invalid',
    -      'Do not email bolinfest@google_groups.com.',
    -      'Do not email bolinfest@google_groups.com.');
    -}
    -
    -function testUrlNotHttp() {
    -  assertLinkify(
    -      'Url using unusual scheme',
    -      'Looking for some goodies: ftp://ftp.google.com/goodstuff/',
    -      'Looking for some goodies: ' +
    -      '<a href="ftp://ftp.google.com/goodstuff/">' +
    -          'ftp://ftp.google.com/goodstuff/<\/a>');
    -}
    -
    -function testJsInjection() {
    -  assertLinkify(
    -      'Text includes some javascript',
    -      'Welcome in hell <script>alert(\'this is hell\')<\/script>',
    -      goog.string.htmlEscape(
    -          'Welcome in hell <script>alert(\'this is hell\')<\/script>'));
    -}
    -
    -function testJsInjectionDotIsBlind() {
    -  assertLinkify(
    -      'Javascript injection using regex . blindness to newline chars',
    -      '<script>malicious_code()<\/script>\nVery nice url: www.google.com',
    -      '&lt;script&gt;malicious_code()&lt;/script&gt;\nVery nice url: ' +
    -          '<a href="http://www.google.com">www.google.com<\/a>');
    -}
    -
    -function testJsInjectionWithUnicodeLineReturn() {
    -  assertLinkify(
    -      'Javascript injection using regex . blindness to newline chars with a ' +
    -          'unicode newline character.',
    -      '<script>malicious_code()<\/script>\u2029Vanilla text',
    -      '&lt;script&gt;malicious_code()&lt;/script&gt;\u2029Vanilla text');
    -}
    -
    -function testJsInjectionWithIgnorableNonTagChar() {
    -  assertLinkify(
    -      'Angle brackets are normalized even when followed by an ignorable ' +
    -          'non-tag character.',
    -      '<\u0000img onerror=alert(1337) src=\n>',
    -      '&lt;&#0;img onerror=alert(1337) src=\n&gt;');
    -}
    -
    -function testJsInjectionWithTextarea() {
    -  assertLinkify(
    -      'Putting the result in a textarea can\'t cause other textarea text to ' +
    -          'be treated as tag content.',
    -      '</textarea',
    -      '&lt;/textarea');
    -}
    -
    -function testJsInjectionWithNewlineConversion() {
    -  assertLinkify(
    -      'Any newline conversion and whitespace normalization won\'t cause tag ' +
    -          'parts to be recombined.',
    -      '<<br>script<br>>alert(1337)<<br>/<br>script<br>>',
    -      '&lt;&lt;br&gt;script&lt;br&gt;&gt;alert(1337)&lt;&lt;br&gt;/&lt;' +
    -          'br&gt;script&lt;br&gt;&gt;');
    -}
    -
    -function testNoProtocolBlacklisting() {
    -  assertLinkify(
    -      'No protocol blacklisting.',
    -      'Click: jscript:alert%281337%29\nClick: JSscript:alert%281337%29\n' +
    -          'Click: VBscript:alert%281337%29\nClick: Script:alert%281337%29\n' +
    -          'Click: flavascript:alert%281337%29',
    -      'Click: jscript:alert%281337%29\nClick: JSscript:alert%281337%29\n' +
    -          'Click: VBscript:alert%281337%29\nClick: Script:alert%281337%29\n' +
    -          'Click: flavascript:alert%281337%29');
    -}
    -
    -function testProtocolWhitelistingEffective() {
    -  assertLinkify(
    -      'Protocol whitelisting is effective.',
    -      'Click httpscript:alert%281337%29\nClick mailtoscript:alert%281337%29\n' +
    -          'Click j\u00A0avascript:alert%281337%29\n' +
    -          'Click \u00A0javascript:alert%281337%29',
    -      'Click httpscript:alert%281337%29\nClick mailtoscript:alert%281337%29\n' +
    -          'Click j\u00A0avascript:alert%281337%29\n' +
    -          'Click \u00A0javascript:alert%281337%29');
    -}
    -
    -function testLinkifyNoOptions() {
    -  div.innerHTML = goog.string.linkify.linkifyPlainText('http://www.google.com');
    -  goog.testing.dom.assertHtmlContentsMatch(
    -      '<a href="http://www.google.com" target="_blank" rel="nofollow">' +
    -      'http://www.google.com<\/a>',
    -      div, true /* opt_strictAttributes */);
    -}
    -
    -function testLinkifyOptionsNoAttributes() {
    -  div.innerHTML = goog.string.linkify.linkifyPlainText(
    -      'The link for www.google.com is located somewhere in ' +
    -      'https://www.google.fr/?hl=en, you should find it easily.',
    -      {rel: '', target: ''});
    -  goog.testing.dom.assertHtmlContentsMatch(
    -      'The link for <a href="http://www.google.com">www.google.com<\/a> is ' +
    -      'located somewhere in ' +
    -      '<a href="https://www.google.fr/?hl=en">https://www.google.fr/?hl=en' +
    -      '<\/a>, you should find it easily.',
    -      div, true /* opt_strictAttributes */);
    -}
    -
    -function testLinkifyOptionsClassName() {
    -  div.innerHTML = goog.string.linkify.linkifyPlainText(
    -      'Attribute with <class> name www.w3c.org.',
    -      {'class': 'link-added'});
    -  goog.testing.dom.assertHtmlContentsMatch(
    -      'Attribute with &lt;class&gt; name <a href="http://www.w3c.org" ' +
    -      'target="_blank" rel="nofollow" class="link-added">www.w3c.org<\/a>.',
    -      div, true /* opt_strictAttributes */);
    -}
    -
    -function testFindFirstUrlNoScheme() {
    -  assertEquals('www.google.com', goog.string.linkify.findFirstUrl(
    -      'www.google.com'));
    -}
    -
    -function testFindFirstUrlNoSchemeWithText() {
    -  assertEquals('www.google.com', goog.string.linkify.findFirstUrl(
    -      'prefix www.google.com something'));
    -}
    -
    -function testFindFirstUrlScheme() {
    -  assertEquals('http://www.google.com', goog.string.linkify.findFirstUrl(
    -      'http://www.google.com'));
    -}
    -
    -function testFindFirstUrlSchemeWithText() {
    -  assertEquals('http://www.google.com', goog.string.linkify.findFirstUrl(
    -      'prefix http://www.google.com something'));
    -}
    -
    -function testFindFirstUrlNoUrl() {
    -  assertEquals('', goog.string.linkify.findFirstUrl(
    -      'ygvtfr676 5v68fk uygbt85F^&%^&I%FVvc .'));
    -}
    -
    -function testFindFirstEmailNoScheme() {
    -  assertEquals('fake@google.com', goog.string.linkify.findFirstEmail(
    -      'fake@google.com'));
    -}
    -
    -function testFindFirstEmailNoSchemeWithText() {
    -  assertEquals('fake@google.com', goog.string.linkify.findFirstEmail(
    -      'prefix fake@google.com something'));
    -}
    -
    -function testFindFirstEmailScheme() {
    -  assertEquals('mailto:fake@google.com', goog.string.linkify.findFirstEmail(
    -      'mailto:fake@google.com'));
    -}
    -
    -function testFindFirstEmailSchemeWithText() {
    -  assertEquals('mailto:fake@google.com', goog.string.linkify.findFirstEmail(
    -      'prefix mailto:fake@google.com something'));
    -}
    -
    -function testFindFirstEmailNoUrl() {
    -  assertEquals('', goog.string.linkify.findFirstEmail(
    -      'ygvtfr676 5v68fk uygbt85F^&%^&I%FVvc .'));
    -}
    -
    -function testContainsPunctuation_parens() {
    -  assertLinkify(
    -      'Link contains parens, but does not end with them',
    -      'www.google.com/abc(v1).html',
    -      '<a href="http://www.google.com/abc(v1).html">' +
    -          'www.google.com/abc(v1).html<\/a>');
    -}
    -
    -function testEndsWithPunctuation() {
    -  assertLinkify(
    -      'Link ends with punctuation',
    -      'Have you seen www.google.com? It\'s awesome.',
    -      'Have you seen <a href="http://www.google.com">www.google.com<\/a>?' +
    -      goog.string.htmlEscape(' It\'s awesome.'));
    -}
    -
    -function testEndsWithPunctuation_closeParen() {
    -  assertLinkify(
    -      'Link inside parentheses',
    -      '(For more info see www.googl.com)',
    -      '(For more info see <a href="http://www.googl.com">www.googl.com<\/a>)');
    -  assertLinkify(
    -      'Parentheses inside link',
    -      'http://en.wikipedia.org/wiki/Titanic_(1997_film)',
    -      '<a href="http://en.wikipedia.org/wiki/Titanic_(1997_film)">' +
    -          'http://en.wikipedia.org/wiki/Titanic_(1997_film)<\/a>');
    -}
    -
    -function testEndsWithPunctuation_openParen() {
    -  assertLinkify(
    -      'Link followed by open parenthesis',
    -      'www.google.com(',
    -      '<a href="http://www.google.com(">www.google.com(<\/a>');
    -}
    -
    -function testEndsWithPunctuation_angles() {
    -  assertLinkify(
    -      'Link inside angled brackets',
    -      'Here is a bibliography entry <http://www.google.com/>',
    -      'Here is a bibliography entry &lt;<a href="http://www.google.com/">' +
    -          'http://www.google.com/<\/a>&gt;');
    -}
    -
    -function testEndsWithPunctuation_closingPairThenSingle() {
    -  assertLinkify(
    -      'Link followed by closing punctuation pair then singular punctuation',
    -      'Here is a bibliography entry <http://www.google.com/>, PTAL.',
    -      'Here is a bibliography entry &lt;<a href="http://www.google.com/">' +
    -          'http://www.google.com/<\/a>&gt;, PTAL.');
    -}
    -
    -function testEndsWithPunctuation_ellipses() {
    -  assertLinkify(
    -      'Link followed by three dots',
    -      'just look it up on www.google.com...',
    -      'just look it up on <a href="http://www.google.com">www.google.com' +
    -          '<\/a>...');
    -}
    -
    -function testBracketsInUrl() {
    -  assertLinkify(
    -      'Link containing brackets',
    -      'before http://google.com/details?answer[0]=42 after',
    -      'before <a href="http://google.com/details?answer[0]=42">' +
    -          'http://google.com/details?answer[0]=42<\/a> after');
    -}
    -
    -function testUrlWithExclamation() {
    -  assertLinkify(
    -      'URL with exclamation points',
    -      'This is awesome www.google.com!',
    -      'This is awesome <a href="http://www.google.com">www.google.com<\/a>!');
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/string/newlines.js b/src/database/third_party/closure-library/closure/goog/string/newlines.js
    deleted file mode 100644
    index 14b6f03e261..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/string/newlines.js
    +++ /dev/null
    @@ -1,154 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Utilities for string newlines.
    - * @author nnaze@google.com (Nathan Naze)
    - */
    -
    -
    -/**
    - * Namespace for string utilities
    - */
    -goog.provide('goog.string.newlines');
    -goog.provide('goog.string.newlines.Line');
    -
    -goog.require('goog.array');
    -
    -
    -/**
    - * Splits a string into lines, properly handling universal newlines.
    - * @param {string} str String to split.
    - * @param {boolean=} opt_keepNewlines Whether to keep the newlines in the
    - *     resulting strings. Defaults to false.
    - * @return {!Array<string>} String split into lines.
    - */
    -goog.string.newlines.splitLines = function(str, opt_keepNewlines) {
    -  var lines = goog.string.newlines.getLines(str);
    -  return goog.array.map(lines, function(line) {
    -    return opt_keepNewlines ? line.getFullLine() : line.getContent();
    -  });
    -};
    -
    -
    -
    -/**
    - * Line metadata class that records the start/end indicies of lines
    - * in a string.  Can be used to implement common newline use cases such as
    - * splitLines() or determining line/column of an index in a string.
    - * Also implements methods to get line contents.
    - *
    - * Indexes are expressed as string indicies into string.substring(), inclusive
    - * at the start, exclusive at the end.
    - *
    - * Create an array of these with goog.string.newlines.getLines().
    - * @param {string} string The original string.
    - * @param {number} startLineIndex The index of the start of the line.
    - * @param {number} endContentIndex The index of the end of the line, excluding
    - *     newlines.
    - * @param {number} endLineIndex The index of the end of the line, index
    - *     newlines.
    - * @constructor
    - * @struct
    - * @final
    - */
    -goog.string.newlines.Line = function(string, startLineIndex,
    -                                     endContentIndex, endLineIndex) {
    -  /**
    -   * The original string.
    -   * @type {string}
    -   */
    -  this.string = string;
    -
    -  /**
    -   * Index of the start of the line.
    -   * @type {number}
    -   */
    -  this.startLineIndex = startLineIndex;
    -
    -  /**
    -   * Index of the end of the line, excluding any newline characters.
    -   * Index is the first character after the line, suitable for
    -   * String.substring().
    -   * @type {number}
    -   */
    -  this.endContentIndex = endContentIndex;
    -
    -  /**
    -   * Index of the end of the line, excluding any newline characters.
    -   * Index is the first character after the line, suitable for
    -   * String.substring().
    -   * @type {number}
    -   */
    -
    -  this.endLineIndex = endLineIndex;
    -};
    -
    -
    -/**
    - * @return {string} The content of the line, excluding any newline characters.
    - */
    -goog.string.newlines.Line.prototype.getContent = function() {
    -  return this.string.substring(this.startLineIndex, this.endContentIndex);
    -};
    -
    -
    -/**
    - * @return {string} The full line, including any newline characters.
    - */
    -goog.string.newlines.Line.prototype.getFullLine = function() {
    -  return this.string.substring(this.startLineIndex, this.endLineIndex);
    -};
    -
    -
    -/**
    - * @return {string} The newline characters, if any ('\n', \r', '\r\n', '', etc).
    - */
    -goog.string.newlines.Line.prototype.getNewline = function() {
    -  return this.string.substring(this.endContentIndex, this.endLineIndex);
    -};
    -
    -
    -/**
    - * Splits a string into an array of line metadata.
    - * @param {string} str String to split.
    - * @return {!Array<!goog.string.newlines.Line>} Array of line metadata.
    - */
    -goog.string.newlines.getLines = function(str) {
    -  // We use the constructor because literals are evaluated only once in
    -  // < ES 3.1.
    -  // See http://www.mail-archive.com/es-discuss@mozilla.org/msg01796.html
    -  var re = RegExp('\r\n|\r|\n', 'g');
    -  var sliceIndex = 0;
    -  var result;
    -  var lines = [];
    -
    -  while (result = re.exec(str)) {
    -    var line = new goog.string.newlines.Line(
    -        str, sliceIndex, result.index, result.index + result[0].length);
    -    lines.push(line);
    -
    -    // remember where to start the slice from
    -    sliceIndex = re.lastIndex;
    -  }
    -
    -  // If the string does not end with a newline, add the last line.
    -  if (sliceIndex < str.length) {
    -    var line = new goog.string.newlines.Line(
    -        str, sliceIndex, str.length, str.length);
    -    lines.push(line);
    -  }
    -
    -  return lines;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/string/newlines_test.html b/src/database/third_party/closure-library/closure/goog/string/newlines_test.html
    deleted file mode 100644
    index dc9854bd463..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/string/newlines_test.html
    +++ /dev/null
    @@ -1,19 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.string</title>
    -<script src="../base.js"></script>
    -<script>
    -goog.require('goog.string.newlinesTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/string/newlines_test.js b/src/database/third_party/closure-library/closure/goog/string/newlines_test.js
    deleted file mode 100644
    index 6464a18c9ed..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/string/newlines_test.js
    +++ /dev/null
    @@ -1,87 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.string.
    - */
    -
    -goog.provide('goog.string.newlinesTest');
    -
    -goog.require('goog.string.newlines');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.string.newlinesTest');
    -
    -// test for goog.string.splitLines
    -function testSplitLines() {
    -
    -  /**
    -   * @param {!Array<string>} expected
    -   * @param {string} string
    -   * @param {boolean=} opt_keepNewlines
    -   */
    -  function assertSplitLines(expected, string, opt_keepNewlines) {
    -    var keepNewlines = opt_keepNewlines || false;
    -    var lines = goog.string.newlines.splitLines(string, keepNewlines);
    -    assertElementsEquals(expected, lines);
    -  }
    -
    -  // Test values borrowed from Python's splitlines. http://goo.gl/iwawx
    -  assertSplitLines(['abc', 'def', '', 'ghi'], 'abc\ndef\n\rghi');
    -  assertSplitLines(['abc', 'def', '', 'ghi'], 'abc\ndef\n\r\nghi');
    -  assertSplitLines(['abc', 'def', 'ghi'], 'abc\ndef\r\nghi');
    -  assertSplitLines(['abc', 'def', 'ghi'], 'abc\ndef\r\nghi\n');
    -  assertSplitLines(['abc', 'def', 'ghi', ''], 'abc\ndef\r\nghi\n\r');
    -  assertSplitLines(['', 'abc', 'def', 'ghi', ''], '\nabc\ndef\r\nghi\n\r');
    -  assertSplitLines(['', 'abc', 'def', 'ghi', ''], '\nabc\ndef\r\nghi\n\r');
    -  assertSplitLines(['\n', 'abc\n', 'def\r\n', 'ghi\n', '\r'],
    -                   '\nabc\ndef\r\nghi\n\r', true);
    -  assertSplitLines(['', 'abc', 'def', 'ghi', ''], '\nabc\ndef\r\nghi\n\r');
    -  assertSplitLines(['\n', 'abc\n', 'def\r\n', 'ghi\n', '\r'],
    -                   '\nabc\ndef\r\nghi\n\r', true);
    -}
    -
    -function testGetLines() {
    -  var lines = goog.string.newlines.getLines('abc\ndef\n\rghi');
    -
    -  assertEquals(4, lines.length);
    -
    -  assertEquals(0, lines[0].startLineIndex);
    -  assertEquals(3, lines[0].endContentIndex);
    -  assertEquals(4, lines[0].endLineIndex);
    -  assertEquals('abc', lines[0].getContent());
    -  assertEquals('abc\n', lines[0].getFullLine());
    -  assertEquals('\n', lines[0].getNewline());
    -
    -  assertEquals(4, lines[1].startLineIndex);
    -  assertEquals(7, lines[1].endContentIndex);
    -  assertEquals(8, lines[1].endLineIndex);
    -  assertEquals('def', lines[1].getContent());
    -  assertEquals('def\n', lines[1].getFullLine());
    -  assertEquals('\n', lines[1].getNewline());
    -
    -  assertEquals(8, lines[2].startLineIndex);
    -  assertEquals(8, lines[2].endContentIndex);
    -  assertEquals(9, lines[2].endLineIndex);
    -  assertEquals('', lines[2].getContent());
    -  assertEquals('\r', lines[2].getFullLine());
    -  assertEquals('\r', lines[2].getNewline());
    -
    -  assertEquals(9, lines[3].startLineIndex);
    -  assertEquals(12, lines[3].endContentIndex);
    -  assertEquals(12, lines[3].endLineIndex);
    -  assertEquals('ghi', lines[3].getContent());
    -  assertEquals('ghi', lines[3].getFullLine());
    -  assertEquals('', lines[3].getNewline());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/string/parser.js b/src/database/third_party/closure-library/closure/goog/string/parser.js
    deleted file mode 100644
    index 05c6eb8dfb8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/string/parser.js
    +++ /dev/null
    @@ -1,38 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Defines an interface for parsing strings into objects.
    - */
    -
    -goog.provide('goog.string.Parser');
    -
    -
    -
    -/**
    - * An interface for parsing strings into objects.
    - * @interface
    - */
    -goog.string.Parser = function() {};
    -
    -
    -/**
    - * Parses a string into an object and returns the result.
    - * Agnostic to the format of string and object.
    - *
    - * @param {string} s The string to parse.
    - * @return {*} The object generated from the string.
    - */
    -goog.string.Parser.prototype.parse;
    diff --git a/src/database/third_party/closure-library/closure/goog/string/path.js b/src/database/third_party/closure-library/closure/goog/string/path.js
    deleted file mode 100644
    index 7a9dfff8b5f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/string/path.js
    +++ /dev/null
    @@ -1,169 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Utilities for dealing with POSIX path strings. Based on
    - * Python's os.path and posixpath.
    - * @author nnaze@google.com (Nathan Naze)
    - */
    -
    -goog.provide('goog.string.path');
    -
    -goog.require('goog.array');
    -goog.require('goog.string');
    -
    -
    -/**
    - * Returns the final component of a pathname.
    - * See http://docs.python.org/library/os.path.html#os.path.basename
    - * @param {string} path A pathname.
    - * @return {string} path The final component of a pathname, i.e. everything
    - *     after the final slash.
    - */
    -goog.string.path.baseName = function(path) {
    -  var i = path.lastIndexOf('/') + 1;
    -  return path.slice(i);
    -};
    -
    -
    -/**
    - * Alias to goog.string.path.baseName.
    - * @param {string} path A pathname.
    - * @return {string} path The final component of a pathname.
    - * @deprecated Use goog.string.path.baseName.
    - */
    -goog.string.path.basename = goog.string.path.baseName;
    -
    -
    -/**
    - * Returns the directory component of a pathname.
    - * See http://docs.python.org/library/os.path.html#os.path.dirname
    - * @param {string} path A pathname.
    - * @return {string} The directory component of a pathname, i.e. everything
    - *     leading up to the final slash.
    - */
    -goog.string.path.dirname = function(path) {
    -  var i = path.lastIndexOf('/') + 1;
    -  var head = path.slice(0, i);
    -  // If the path isn't all forward slashes, trim the trailing slashes.
    -  if (!/^\/+$/.test(head)) {
    -    head = head.replace(/\/+$/, '');
    -  }
    -  return head;
    -};
    -
    -
    -/**
    - * Extracts the extension part of a pathname.
    - * @param {string} path The path name to process.
    - * @return {string} The extension if any, otherwise the empty string.
    - */
    -goog.string.path.extension = function(path) {
    -  var separator = '.';
    -  // Combining all adjacent periods in the basename to a single period.
    -  var baseName = goog.string.path.baseName(path).replace(/\.+/g, separator);
    -  var separatorIndex = baseName.lastIndexOf(separator);
    -  return separatorIndex <= 0 ? '' : baseName.substr(separatorIndex + 1);
    -};
    -
    -
    -/**
    - * Joins one or more path components (e.g. 'foo/' and 'bar' make 'foo/bar').
    - * An absolute component will discard all previous component.
    - * See http://docs.python.org/library/os.path.html#os.path.join
    - * @param {...string} var_args One of more path components.
    - * @return {string} The path components joined.
    - */
    -goog.string.path.join = function(var_args) {
    -  var path = arguments[0];
    -
    -  for (var i = 1; i < arguments.length; i++) {
    -    var arg = arguments[i];
    -    if (goog.string.startsWith(arg, '/')) {
    -      path = arg;
    -    } else if (path == '' || goog.string.endsWith(path, '/')) {
    -      path += arg;
    -    } else {
    -      path += '/' + arg;
    -    }
    -  }
    -
    -  return path;
    -};
    -
    -
    -/**
    - * Normalizes a pathname by collapsing duplicate separators, parent directory
    - * references ('..'), and current directory references ('.').
    - * See http://docs.python.org/library/os.path.html#os.path.normpath
    - * @param {string} path One or more path components.
    - * @return {string} The path after normalization.
    - */
    -goog.string.path.normalizePath = function(path) {
    -  if (path == '') {
    -    return '.';
    -  }
    -
    -  var initialSlashes = '';
    -  // POSIX will keep two slashes, but three or more will be collapsed to one.
    -  if (goog.string.startsWith(path, '/')) {
    -    initialSlashes = '/';
    -    if (goog.string.startsWith(path, '//') &&
    -        !goog.string.startsWith(path, '///')) {
    -      initialSlashes = '//';
    -    }
    -  }
    -
    -  var parts = path.split('/');
    -  var newParts = [];
    -
    -  for (var i = 0; i < parts.length; i++) {
    -    var part = parts[i];
    -
    -    // '' and '.' don't change the directory, ignore.
    -    if (part == '' || part == '.') {
    -      continue;
    -    }
    -
    -    // A '..' should pop a directory unless this is not an absolute path and
    -    // we're at the root, or we've travelled upwards relatively in the last
    -    // iteration.
    -    if (part != '..' ||
    -        (!initialSlashes && !newParts.length) ||
    -        goog.array.peek(newParts) == '..') {
    -      newParts.push(part);
    -    } else {
    -      newParts.pop();
    -    }
    -  }
    -
    -  var returnPath = initialSlashes + newParts.join('/');
    -  return returnPath || '.';
    -};
    -
    -
    -/**
    - * Splits a pathname into "dirname" and "baseName" components, where "baseName"
    - * is everything after the final slash. Either part may return an empty string.
    - * See http://docs.python.org/library/os.path.html#os.path.split
    - * @param {string} path A pathname.
    - * @return {!Array<string>} An array of [dirname, basename].
    - */
    -goog.string.path.split = function(path) {
    -  var head = goog.string.path.dirname(path);
    -  var tail = goog.string.path.baseName(path);
    -  return [head, tail];
    -};
    -
    -// TODO(nnaze): Implement other useful functions from os.path
    diff --git a/src/database/third_party/closure-library/closure/goog/string/path_test.html b/src/database/third_party/closure-library/closure/goog/string/path_test.html
    deleted file mode 100644
    index 7caad288f98..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/string/path_test.html
    +++ /dev/null
    @@ -1,21 +0,0 @@
    -<!doctype html>
    -<html>
    -<!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.string.path
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.string.pathTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/string/path_test.js b/src/database/third_party/closure-library/closure/goog/string/path_test.js
    deleted file mode 100644
    index 79f00817053..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/string/path_test.js
    +++ /dev/null
    @@ -1,108 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.string.pathTest');
    -goog.setTestOnly('goog.string.pathTest');
    -
    -goog.require('goog.string.path');
    -goog.require('goog.testing.jsunit');
    -
    -// Some test data comes from Python's posixpath tests.
    -// See http://svn.python.org/view/python/trunk/Lib/test/test_posixpath.py
    -
    -function testBasename() {
    -  assertEquals('bar', goog.string.path.baseName('/foo/bar'));
    -  assertEquals('', goog.string.path.baseName('/'));
    -  assertEquals('foo', goog.string.path.baseName('foo'));
    -  assertEquals('foo', goog.string.path.baseName('////foo'));
    -  assertEquals('bar', goog.string.path.baseName('//foo//bar'));
    -}
    -
    -function testDirname() {
    -  assertEquals('/foo', goog.string.path.dirname('/foo/bar'));
    -  assertEquals('/', goog.string.path.dirname('/'));
    -  assertEquals('', goog.string.path.dirname('foo'));
    -  assertEquals('////', goog.string.path.dirname('////foo'));
    -  assertEquals('//foo', goog.string.path.dirname('//foo//bar'));
    -}
    -
    -function testJoin() {
    -  assertEquals('/bar/baz',
    -      goog.string.path.join('/foo', 'bar', '/bar', 'baz'));
    -  assertEquals('/foo/bar/baz',
    -      goog.string.path.join('/foo', 'bar', 'baz'));
    -  assertEquals('/foo/bar/baz',
    -      goog.string.path.join('/foo/', 'bar', 'baz'));
    -  assertEquals('/foo/bar/baz/',
    -      goog.string.path.join('/foo/', 'bar/', 'baz/'));
    -}
    -
    -function testNormalizePath() {
    -  assertEquals('.', goog.string.path.normalizePath(''));
    -  assertEquals('.', goog.string.path.normalizePath('./'));
    -  assertEquals('/', goog.string.path.normalizePath('/'));
    -  assertEquals('//', goog.string.path.normalizePath('//'));
    -  assertEquals('/', goog.string.path.normalizePath('///'));
    -  assertEquals('/foo/bar',
    -               goog.string.path.normalizePath('///foo/.//bar//'));
    -  assertEquals('/foo/baz',
    -               goog.string.path.normalizePath('///foo/.//bar//.//..//.//baz'));
    -  assertEquals('/foo/bar',
    -               goog.string.path.normalizePath('///..//./foo/.//bar'));
    -  assertEquals('../../cat/dog',
    -               goog.string.path.normalizePath('../../cat/dog/'));
    -  assertEquals('../dog',
    -               goog.string.path.normalizePath('../cat/../dog/'));
    -  assertEquals('/cat/dog',
    -               goog.string.path.normalizePath('/../cat/dog/'));
    -  assertEquals('/dog',
    -               goog.string.path.normalizePath('/../cat/../dog'));
    -  assertEquals('/dog',
    -               goog.string.path.normalizePath('/../../../dog'));
    -}
    -
    -function testSplit() {
    -  assertArrayEquals(['/foo', 'bar'], goog.string.path.split('/foo/bar'));
    -  assertArrayEquals(['/', ''], goog.string.path.split('/'));
    -  assertArrayEquals(['', 'foo'], goog.string.path.split('foo'));
    -  assertArrayEquals(['////', 'foo'], goog.string.path.split('////foo'));
    -  assertArrayEquals(['//foo', 'bar'], goog.string.path.split('//foo//bar'));
    -}
    -
    -function testExtension() {
    -  assertEquals('jpg', goog.string.path.extension('././foo/bar/baz.jpg'));
    -  assertEquals('jpg', goog.string.path.extension('././foo bar/baz.jpg'));
    -  assertEquals('jpg', goog.string.path.extension(
    -      'foo/bar/baz/blah blah.jpg'));
    -  assertEquals('', goog.string.path.extension('../../foo/bar/baz baz'));
    -  assertEquals('', goog.string.path.extension('../../foo bar/baz baz'));
    -  assertEquals('', goog.string.path.extension('foo/bar/.'));
    -  assertEquals('', goog.string.path.extension('  '));
    -  assertEquals('', goog.string.path.extension(''));
    -  assertEquals('', goog.string.path.extension('/home/username/.bashrc'));
    -
    -  // Tests cases taken from python os.path.splitext().
    -  assertEquals('bar', goog.string.path.extension('foo.bar'));
    -  assertEquals('bar', goog.string.path.extension('foo.boo.bar'));
    -  assertEquals('bar', goog.string.path.extension('foo.boo.biff.bar'));
    -  assertEquals('rc', goog.string.path.extension('.csh.rc'));
    -  assertEquals('', goog.string.path.extension('nodots'));
    -  assertEquals('', goog.string.path.extension('.cshrc'));
    -  assertEquals('', goog.string.path.extension('...manydots'));
    -  assertEquals('ext', goog.string.path.extension('...manydots.ext'));
    -  assertEquals('', goog.string.path.extension('.'));
    -  assertEquals('', goog.string.path.extension('..'));
    -  assertEquals('', goog.string.path.extension('........'));
    -  assertEquals('', goog.string.path.extension(''));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/string/string.js b/src/database/third_party/closure-library/closure/goog/string/string.js
    deleted file mode 100644
    index 065a1a8409b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/string/string.js
    +++ /dev/null
    @@ -1,1565 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Utilities for string manipulation.
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -
    -/**
    - * Namespace for string utilities
    - */
    -goog.provide('goog.string');
    -goog.provide('goog.string.Unicode');
    -
    -
    -/**
    - * @define {boolean} Enables HTML escaping of lowercase letter "e" which helps
    - * with detection of double-escaping as this letter is frequently used.
    - */
    -goog.define('goog.string.DETECT_DOUBLE_ESCAPING', false);
    -
    -
    -/**
    - * @define {boolean} Whether to force non-dom html unescaping.
    - */
    -goog.define('goog.string.FORCE_NON_DOM_HTML_UNESCAPING', false);
    -
    -
    -/**
    - * Common Unicode string characters.
    - * @enum {string}
    - */
    -goog.string.Unicode = {
    -  NBSP: '\xa0'
    -};
    -
    -
    -/**
    - * Fast prefix-checker.
    - * @param {string} str The string to check.
    - * @param {string} prefix A string to look for at the start of {@code str}.
    - * @return {boolean} True if {@code str} begins with {@code prefix}.
    - */
    -goog.string.startsWith = function(str, prefix) {
    -  return str.lastIndexOf(prefix, 0) == 0;
    -};
    -
    -
    -/**
    - * Fast suffix-checker.
    - * @param {string} str The string to check.
    - * @param {string} suffix A string to look for at the end of {@code str}.
    - * @return {boolean} True if {@code str} ends with {@code suffix}.
    - */
    -goog.string.endsWith = function(str, suffix) {
    -  var l = str.length - suffix.length;
    -  return l >= 0 && str.indexOf(suffix, l) == l;
    -};
    -
    -
    -/**
    - * Case-insensitive prefix-checker.
    - * @param {string} str The string to check.
    - * @param {string} prefix  A string to look for at the end of {@code str}.
    - * @return {boolean} True if {@code str} begins with {@code prefix} (ignoring
    - *     case).
    - */
    -goog.string.caseInsensitiveStartsWith = function(str, prefix) {
    -  return goog.string.caseInsensitiveCompare(
    -      prefix, str.substr(0, prefix.length)) == 0;
    -};
    -
    -
    -/**
    - * Case-insensitive suffix-checker.
    - * @param {string} str The string to check.
    - * @param {string} suffix A string to look for at the end of {@code str}.
    - * @return {boolean} True if {@code str} ends with {@code suffix} (ignoring
    - *     case).
    - */
    -goog.string.caseInsensitiveEndsWith = function(str, suffix) {
    -  return goog.string.caseInsensitiveCompare(
    -      suffix, str.substr(str.length - suffix.length, suffix.length)) == 0;
    -};
    -
    -
    -/**
    - * Case-insensitive equality checker.
    - * @param {string} str1 First string to check.
    - * @param {string} str2 Second string to check.
    - * @return {boolean} True if {@code str1} and {@code str2} are the same string,
    - *     ignoring case.
    - */
    -goog.string.caseInsensitiveEquals = function(str1, str2) {
    -  return str1.toLowerCase() == str2.toLowerCase();
    -};
    -
    -
    -/**
    - * Does simple python-style string substitution.
    - * subs("foo%s hot%s", "bar", "dog") becomes "foobar hotdog".
    - * @param {string} str The string containing the pattern.
    - * @param {...*} var_args The items to substitute into the pattern.
    - * @return {string} A copy of {@code str} in which each occurrence of
    - *     {@code %s} has been replaced an argument from {@code var_args}.
    - */
    -goog.string.subs = function(str, var_args) {
    -  var splitParts = str.split('%s');
    -  var returnString = '';
    -
    -  var subsArguments = Array.prototype.slice.call(arguments, 1);
    -  while (subsArguments.length &&
    -         // Replace up to the last split part. We are inserting in the
    -         // positions between split parts.
    -         splitParts.length > 1) {
    -    returnString += splitParts.shift() + subsArguments.shift();
    -  }
    -
    -  return returnString + splitParts.join('%s'); // Join unused '%s'
    -};
    -
    -
    -/**
    - * Converts multiple whitespace chars (spaces, non-breaking-spaces, new lines
    - * and tabs) to a single space, and strips leading and trailing whitespace.
    - * @param {string} str Input string.
    - * @return {string} A copy of {@code str} with collapsed whitespace.
    - */
    -goog.string.collapseWhitespace = function(str) {
    -  // Since IE doesn't include non-breaking-space (0xa0) in their \s character
    -  // class (as required by section 7.2 of the ECMAScript spec), we explicitly
    -  // include it in the regexp to enforce consistent cross-browser behavior.
    -  return str.replace(/[\s\xa0]+/g, ' ').replace(/^\s+|\s+$/g, '');
    -};
    -
    -
    -/**
    - * Checks if a string is empty or contains only whitespaces.
    - * @param {string} str The string to check.
    - * @return {boolean} Whether {@code str} is empty or whitespace only.
    - */
    -goog.string.isEmptyOrWhitespace = function(str) {
    -  // testing length == 0 first is actually slower in all browsers (about the
    -  // same in Opera).
    -  // Since IE doesn't include non-breaking-space (0xa0) in their \s character
    -  // class (as required by section 7.2 of the ECMAScript spec), we explicitly
    -  // include it in the regexp to enforce consistent cross-browser behavior.
    -  return /^[\s\xa0]*$/.test(str);
    -};
    -
    -
    -/**
    - * Checks if a string is empty.
    - * @param {string} str The string to check.
    - * @return {boolean} Whether {@code str} is empty.
    - */
    -goog.string.isEmptyString = function(str) {
    -  return str.length == 0;
    -};
    -
    -
    -/**
    - * Checks if a string is empty or contains only whitespaces.
    - *
    - * TODO(user): Deprecate this when clients have been switched over to
    - * goog.string.isEmptyOrWhitespace.
    - *
    - * @param {string} str The string to check.
    - * @return {boolean} Whether {@code str} is empty or whitespace only.
    - */
    -goog.string.isEmpty = goog.string.isEmptyOrWhitespace;
    -
    -
    -/**
    - * Checks if a string is null, undefined, empty or contains only whitespaces.
    - * @param {*} str The string to check.
    - * @return {boolean} Whether {@code str} is null, undefined, empty, or
    - *     whitespace only.
    - * @deprecated Use goog.string.isEmptyOrWhitespace(goog.string.makeSafe(str))
    - *     instead.
    - */
    -goog.string.isEmptyOrWhitespaceSafe = function(str) {
    -  return goog.string.isEmptyOrWhitespace(goog.string.makeSafe(str));
    -};
    -
    -
    -/**
    - * Checks if a string is null, undefined, empty or contains only whitespaces.
    - *
    - * TODO(user): Deprecate this when clients have been switched over to
    - * goog.string.isEmptyOrWhitespaceSafe.
    - *
    - * @param {*} str The string to check.
    - * @return {boolean} Whether {@code str} is null, undefined, empty, or
    - *     whitespace only.
    - */
    -goog.string.isEmptySafe = goog.string.isEmptyOrWhitespaceSafe;
    -
    -
    -/**
    - * Checks if a string is all breaking whitespace.
    - * @param {string} str The string to check.
    - * @return {boolean} Whether the string is all breaking whitespace.
    - */
    -goog.string.isBreakingWhitespace = function(str) {
    -  return !/[^\t\n\r ]/.test(str);
    -};
    -
    -
    -/**
    - * Checks if a string contains all letters.
    - * @param {string} str string to check.
    - * @return {boolean} True if {@code str} consists entirely of letters.
    - */
    -goog.string.isAlpha = function(str) {
    -  return !/[^a-zA-Z]/.test(str);
    -};
    -
    -
    -/**
    - * Checks if a string contains only numbers.
    - * @param {*} str string to check. If not a string, it will be
    - *     casted to one.
    - * @return {boolean} True if {@code str} is numeric.
    - */
    -goog.string.isNumeric = function(str) {
    -  return !/[^0-9]/.test(str);
    -};
    -
    -
    -/**
    - * Checks if a string contains only numbers or letters.
    - * @param {string} str string to check.
    - * @return {boolean} True if {@code str} is alphanumeric.
    - */
    -goog.string.isAlphaNumeric = function(str) {
    -  return !/[^a-zA-Z0-9]/.test(str);
    -};
    -
    -
    -/**
    - * Checks if a character is a space character.
    - * @param {string} ch Character to check.
    - * @return {boolean} True if {@code ch} is a space.
    - */
    -goog.string.isSpace = function(ch) {
    -  return ch == ' ';
    -};
    -
    -
    -/**
    - * Checks if a character is a valid unicode character.
    - * @param {string} ch Character to check.
    - * @return {boolean} True if {@code ch} is a valid unicode character.
    - */
    -goog.string.isUnicodeChar = function(ch) {
    -  return ch.length == 1 && ch >= ' ' && ch <= '~' ||
    -         ch >= '\u0080' && ch <= '\uFFFD';
    -};
    -
    -
    -/**
    - * Takes a string and replaces newlines with a space. Multiple lines are
    - * replaced with a single space.
    - * @param {string} str The string from which to strip newlines.
    - * @return {string} A copy of {@code str} stripped of newlines.
    - */
    -goog.string.stripNewlines = function(str) {
    -  return str.replace(/(\r\n|\r|\n)+/g, ' ');
    -};
    -
    -
    -/**
    - * Replaces Windows and Mac new lines with unix style: \r or \r\n with \n.
    - * @param {string} str The string to in which to canonicalize newlines.
    - * @return {string} {@code str} A copy of {@code} with canonicalized newlines.
    - */
    -goog.string.canonicalizeNewlines = function(str) {
    -  return str.replace(/(\r\n|\r|\n)/g, '\n');
    -};
    -
    -
    -/**
    - * Normalizes whitespace in a string, replacing all whitespace chars with
    - * a space.
    - * @param {string} str The string in which to normalize whitespace.
    - * @return {string} A copy of {@code str} with all whitespace normalized.
    - */
    -goog.string.normalizeWhitespace = function(str) {
    -  return str.replace(/\xa0|\s/g, ' ');
    -};
    -
    -
    -/**
    - * Normalizes spaces in a string, replacing all consecutive spaces and tabs
    - * with a single space. Replaces non-breaking space with a space.
    - * @param {string} str The string in which to normalize spaces.
    - * @return {string} A copy of {@code str} with all consecutive spaces and tabs
    - *    replaced with a single space.
    - */
    -goog.string.normalizeSpaces = function(str) {
    -  return str.replace(/\xa0|[ \t]+/g, ' ');
    -};
    -
    -
    -/**
    - * Removes the breaking spaces from the left and right of the string and
    - * collapses the sequences of breaking spaces in the middle into single spaces.
    - * The original and the result strings render the same way in HTML.
    - * @param {string} str A string in which to collapse spaces.
    - * @return {string} Copy of the string with normalized breaking spaces.
    - */
    -goog.string.collapseBreakingSpaces = function(str) {
    -  return str.replace(/[\t\r\n ]+/g, ' ').replace(
    -      /^[\t\r\n ]+|[\t\r\n ]+$/g, '');
    -};
    -
    -
    -/**
    - * Trims white spaces to the left and right of a string.
    - * @param {string} str The string to trim.
    - * @return {string} A trimmed copy of {@code str}.
    - */
    -goog.string.trim = (goog.TRUSTED_SITE && String.prototype.trim) ?
    -    function(str) {
    -      return str.trim();
    -    } :
    -    function(str) {
    -      // Since IE doesn't include non-breaking-space (0xa0) in their \s
    -      // character class (as required by section 7.2 of the ECMAScript spec),
    -      // we explicitly include it in the regexp to enforce consistent
    -      // cross-browser behavior.
    -      return str.replace(/^[\s\xa0]+|[\s\xa0]+$/g, '');
    -    };
    -
    -
    -/**
    - * Trims whitespaces at the left end of a string.
    - * @param {string} str The string to left trim.
    - * @return {string} A trimmed copy of {@code str}.
    - */
    -goog.string.trimLeft = function(str) {
    -  // Since IE doesn't include non-breaking-space (0xa0) in their \s character
    -  // class (as required by section 7.2 of the ECMAScript spec), we explicitly
    -  // include it in the regexp to enforce consistent cross-browser behavior.
    -  return str.replace(/^[\s\xa0]+/, '');
    -};
    -
    -
    -/**
    - * Trims whitespaces at the right end of a string.
    - * @param {string} str The string to right trim.
    - * @return {string} A trimmed copy of {@code str}.
    - */
    -goog.string.trimRight = function(str) {
    -  // Since IE doesn't include non-breaking-space (0xa0) in their \s character
    -  // class (as required by section 7.2 of the ECMAScript spec), we explicitly
    -  // include it in the regexp to enforce consistent cross-browser behavior.
    -  return str.replace(/[\s\xa0]+$/, '');
    -};
    -
    -
    -/**
    - * A string comparator that ignores case.
    - * -1 = str1 less than str2
    - *  0 = str1 equals str2
    - *  1 = str1 greater than str2
    - *
    - * @param {string} str1 The string to compare.
    - * @param {string} str2 The string to compare {@code str1} to.
    - * @return {number} The comparator result, as described above.
    - */
    -goog.string.caseInsensitiveCompare = function(str1, str2) {
    -  var test1 = String(str1).toLowerCase();
    -  var test2 = String(str2).toLowerCase();
    -
    -  if (test1 < test2) {
    -    return -1;
    -  } else if (test1 == test2) {
    -    return 0;
    -  } else {
    -    return 1;
    -  }
    -};
    -
    -
    -/**
    - * Regular expression used for splitting a string into substrings of fractional
    - * numbers, integers, and non-numeric characters.
    - * @type {RegExp}
    - * @private
    - */
    -goog.string.numerateCompareRegExp_ = /(\.\d+)|(\d+)|(\D+)/g;
    -
    -
    -/**
    - * String comparison function that handles numbers in a way humans might expect.
    - * Using this function, the string "File 2.jpg" sorts before "File 10.jpg". The
    - * comparison is mostly case-insensitive, though strings that are identical
    - * except for case are sorted with the upper-case strings before lower-case.
    - *
    - * This comparison function is significantly slower (about 500x) than either
    - * the default or the case-insensitive compare. It should not be used in
    - * time-critical code, but should be fast enough to sort several hundred short
    - * strings (like filenames) with a reasonable delay.
    - *
    - * @param {string} str1 The string to compare in a numerically sensitive way.
    - * @param {string} str2 The string to compare {@code str1} to.
    - * @return {number} less than 0 if str1 < str2, 0 if str1 == str2, greater than
    - *     0 if str1 > str2.
    - */
    -goog.string.numerateCompare = function(str1, str2) {
    -  if (str1 == str2) {
    -    return 0;
    -  }
    -  if (!str1) {
    -    return -1;
    -  }
    -  if (!str2) {
    -    return 1;
    -  }
    -
    -  // Using match to split the entire string ahead of time turns out to be faster
    -  // for most inputs than using RegExp.exec or iterating over each character.
    -  var tokens1 = str1.toLowerCase().match(goog.string.numerateCompareRegExp_);
    -  var tokens2 = str2.toLowerCase().match(goog.string.numerateCompareRegExp_);
    -
    -  var count = Math.min(tokens1.length, tokens2.length);
    -
    -  for (var i = 0; i < count; i++) {
    -    var a = tokens1[i];
    -    var b = tokens2[i];
    -
    -    // Compare pairs of tokens, returning if one token sorts before the other.
    -    if (a != b) {
    -
    -      // Only if both tokens are integers is a special comparison required.
    -      // Decimal numbers are sorted as strings (e.g., '.09' < '.1').
    -      var num1 = parseInt(a, 10);
    -      if (!isNaN(num1)) {
    -        var num2 = parseInt(b, 10);
    -        if (!isNaN(num2) && num1 - num2) {
    -          return num1 - num2;
    -        }
    -      }
    -      return a < b ? -1 : 1;
    -    }
    -  }
    -
    -  // If one string is a substring of the other, the shorter string sorts first.
    -  if (tokens1.length != tokens2.length) {
    -    return tokens1.length - tokens2.length;
    -  }
    -
    -  // The two strings must be equivalent except for case (perfect equality is
    -  // tested at the head of the function.) Revert to default ASCII-betical string
    -  // comparison to stablize the sort.
    -  return str1 < str2 ? -1 : 1;
    -};
    -
    -
    -/**
    - * URL-encodes a string
    - * @param {*} str The string to url-encode.
    - * @return {string} An encoded copy of {@code str} that is safe for urls.
    - *     Note that '#', ':', and other characters used to delimit portions
    - *     of URLs *will* be encoded.
    - */
    -goog.string.urlEncode = function(str) {
    -  return encodeURIComponent(String(str));
    -};
    -
    -
    -/**
    - * URL-decodes the string. We need to specially handle '+'s because
    - * the javascript library doesn't convert them to spaces.
    - * @param {string} str The string to url decode.
    - * @return {string} The decoded {@code str}.
    - */
    -goog.string.urlDecode = function(str) {
    -  return decodeURIComponent(str.replace(/\+/g, ' '));
    -};
    -
    -
    -/**
    - * Converts \n to <br>s or <br />s.
    - * @param {string} str The string in which to convert newlines.
    - * @param {boolean=} opt_xml Whether to use XML compatible tags.
    - * @return {string} A copy of {@code str} with converted newlines.
    - */
    -goog.string.newLineToBr = function(str, opt_xml) {
    -  return str.replace(/(\r\n|\r|\n)/g, opt_xml ? '<br />' : '<br>');
    -};
    -
    -
    -/**
    - * Escapes double quote '"' and single quote '\'' characters in addition to
    - * '&', '<', and '>' so that a string can be included in an HTML tag attribute
    - * value within double or single quotes.
    - *
    - * It should be noted that > doesn't need to be escaped for the HTML or XML to
    - * be valid, but it has been decided to escape it for consistency with other
    - * implementations.
    - *
    - * With goog.string.DETECT_DOUBLE_ESCAPING, this function escapes also the
    - * lowercase letter "e".
    - *
    - * NOTE(user):
    - * HtmlEscape is often called during the generation of large blocks of HTML.
    - * Using statics for the regular expressions and strings is an optimization
    - * that can more than half the amount of time IE spends in this function for
    - * large apps, since strings and regexes both contribute to GC allocations.
    - *
    - * Testing for the presence of a character before escaping increases the number
    - * of function calls, but actually provides a speed increase for the average
    - * case -- since the average case often doesn't require the escaping of all 4
    - * characters and indexOf() is much cheaper than replace().
    - * The worst case does suffer slightly from the additional calls, therefore the
    - * opt_isLikelyToContainHtmlChars option has been included for situations
    - * where all 4 HTML entities are very likely to be present and need escaping.
    - *
    - * Some benchmarks (times tended to fluctuate +-0.05ms):
    - *                                     FireFox                     IE6
    - * (no chars / average (mix of cases) / all 4 chars)
    - * no checks                     0.13 / 0.22 / 0.22         0.23 / 0.53 / 0.80
    - * indexOf                       0.08 / 0.17 / 0.26         0.22 / 0.54 / 0.84
    - * indexOf + re test             0.07 / 0.17 / 0.28         0.19 / 0.50 / 0.85
    - *
    - * An additional advantage of checking if replace actually needs to be called
    - * is a reduction in the number of object allocations, so as the size of the
    - * application grows the difference between the various methods would increase.
    - *
    - * @param {string} str string to be escaped.
    - * @param {boolean=} opt_isLikelyToContainHtmlChars Don't perform a check to see
    - *     if the character needs replacing - use this option if you expect each of
    - *     the characters to appear often. Leave false if you expect few html
    - *     characters to occur in your strings, such as if you are escaping HTML.
    - * @return {string} An escaped copy of {@code str}.
    - */
    -goog.string.htmlEscape = function(str, opt_isLikelyToContainHtmlChars) {
    -
    -  if (opt_isLikelyToContainHtmlChars) {
    -    str = str.replace(goog.string.AMP_RE_, '&amp;')
    -          .replace(goog.string.LT_RE_, '&lt;')
    -          .replace(goog.string.GT_RE_, '&gt;')
    -          .replace(goog.string.QUOT_RE_, '&quot;')
    -          .replace(goog.string.SINGLE_QUOTE_RE_, '&#39;')
    -          .replace(goog.string.NULL_RE_, '&#0;');
    -    if (goog.string.DETECT_DOUBLE_ESCAPING) {
    -      str = str.replace(goog.string.E_RE_, '&#101;');
    -    }
    -    return str;
    -
    -  } else {
    -    // quick test helps in the case when there are no chars to replace, in
    -    // worst case this makes barely a difference to the time taken
    -    if (!goog.string.ALL_RE_.test(str)) return str;
    -
    -    // str.indexOf is faster than regex.test in this case
    -    if (str.indexOf('&') != -1) {
    -      str = str.replace(goog.string.AMP_RE_, '&amp;');
    -    }
    -    if (str.indexOf('<') != -1) {
    -      str = str.replace(goog.string.LT_RE_, '&lt;');
    -    }
    -    if (str.indexOf('>') != -1) {
    -      str = str.replace(goog.string.GT_RE_, '&gt;');
    -    }
    -    if (str.indexOf('"') != -1) {
    -      str = str.replace(goog.string.QUOT_RE_, '&quot;');
    -    }
    -    if (str.indexOf('\'') != -1) {
    -      str = str.replace(goog.string.SINGLE_QUOTE_RE_, '&#39;');
    -    }
    -    if (str.indexOf('\x00') != -1) {
    -      str = str.replace(goog.string.NULL_RE_, '&#0;');
    -    }
    -    if (goog.string.DETECT_DOUBLE_ESCAPING && str.indexOf('e') != -1) {
    -      str = str.replace(goog.string.E_RE_, '&#101;');
    -    }
    -    return str;
    -  }
    -};
    -
    -
    -/**
    - * Regular expression that matches an ampersand, for use in escaping.
    - * @const {!RegExp}
    - * @private
    - */
    -goog.string.AMP_RE_ = /&/g;
    -
    -
    -/**
    - * Regular expression that matches a less than sign, for use in escaping.
    - * @const {!RegExp}
    - * @private
    - */
    -goog.string.LT_RE_ = /</g;
    -
    -
    -/**
    - * Regular expression that matches a greater than sign, for use in escaping.
    - * @const {!RegExp}
    - * @private
    - */
    -goog.string.GT_RE_ = />/g;
    -
    -
    -/**
    - * Regular expression that matches a double quote, for use in escaping.
    - * @const {!RegExp}
    - * @private
    - */
    -goog.string.QUOT_RE_ = /"/g;
    -
    -
    -/**
    - * Regular expression that matches a single quote, for use in escaping.
    - * @const {!RegExp}
    - * @private
    - */
    -goog.string.SINGLE_QUOTE_RE_ = /'/g;
    -
    -
    -/**
    - * Regular expression that matches null character, for use in escaping.
    - * @const {!RegExp}
    - * @private
    - */
    -goog.string.NULL_RE_ = /\x00/g;
    -
    -
    -/**
    - * Regular expression that matches a lowercase letter "e", for use in escaping.
    - * @const {!RegExp}
    - * @private
    - */
    -goog.string.E_RE_ = /e/g;
    -
    -
    -/**
    - * Regular expression that matches any character that needs to be escaped.
    - * @const {!RegExp}
    - * @private
    - */
    -goog.string.ALL_RE_ = (goog.string.DETECT_DOUBLE_ESCAPING ?
    -    /[\x00&<>"'e]/ :
    -    /[\x00&<>"']/);
    -
    -
    -/**
    - * Unescapes an HTML string.
    - *
    - * @param {string} str The string to unescape.
    - * @return {string} An unescaped copy of {@code str}.
    - */
    -goog.string.unescapeEntities = function(str) {
    -  if (goog.string.contains(str, '&')) {
    -    // We are careful not to use a DOM if we do not have one or we explicitly
    -    // requested non-DOM html unescaping.
    -    if (!goog.string.FORCE_NON_DOM_HTML_UNESCAPING &&
    -        'document' in goog.global) {
    -      return goog.string.unescapeEntitiesUsingDom_(str);
    -    } else {
    -      // Fall back on pure XML entities
    -      return goog.string.unescapePureXmlEntities_(str);
    -    }
    -  }
    -  return str;
    -};
    -
    -
    -/**
    - * Unescapes a HTML string using the provided document.
    - *
    - * @param {string} str The string to unescape.
    - * @param {!Document} document A document to use in escaping the string.
    - * @return {string} An unescaped copy of {@code str}.
    - */
    -goog.string.unescapeEntitiesWithDocument = function(str, document) {
    -  if (goog.string.contains(str, '&')) {
    -    return goog.string.unescapeEntitiesUsingDom_(str, document);
    -  }
    -  return str;
    -};
    -
    -
    -/**
    - * Unescapes an HTML string using a DOM to resolve non-XML, non-numeric
    - * entities. This function is XSS-safe and whitespace-preserving.
    - * @private
    - * @param {string} str The string to unescape.
    - * @param {Document=} opt_document An optional document to use for creating
    - *     elements. If this is not specified then the default window.document
    - *     will be used.
    - * @return {string} The unescaped {@code str} string.
    - */
    -goog.string.unescapeEntitiesUsingDom_ = function(str, opt_document) {
    -  /** @type {!Object<string, string>} */
    -  var seen = {'&amp;': '&', '&lt;': '<', '&gt;': '>', '&quot;': '"'};
    -  var div;
    -  if (opt_document) {
    -    div = opt_document.createElement('div');
    -  } else {
    -    div = goog.global.document.createElement('div');
    -  }
    -  // Match as many valid entity characters as possible. If the actual entity
    -  // happens to be shorter, it will still work as innerHTML will return the
    -  // trailing characters unchanged. Since the entity characters do not include
    -  // open angle bracket, there is no chance of XSS from the innerHTML use.
    -  // Since no whitespace is passed to innerHTML, whitespace is preserved.
    -  return str.replace(goog.string.HTML_ENTITY_PATTERN_, function(s, entity) {
    -    // Check for cached entity.
    -    var value = seen[s];
    -    if (value) {
    -      return value;
    -    }
    -    // Check for numeric entity.
    -    if (entity.charAt(0) == '#') {
    -      // Prefix with 0 so that hex entities (e.g. &#x10) parse as hex numbers.
    -      var n = Number('0' + entity.substr(1));
    -      if (!isNaN(n)) {
    -        value = String.fromCharCode(n);
    -      }
    -    }
    -    // Fall back to innerHTML otherwise.
    -    if (!value) {
    -      // Append a non-entity character to avoid a bug in Webkit that parses
    -      // an invalid entity at the end of innerHTML text as the empty string.
    -      div.innerHTML = s + ' ';
    -      // Then remove the trailing character from the result.
    -      value = div.firstChild.nodeValue.slice(0, -1);
    -    }
    -    // Cache and return.
    -    return seen[s] = value;
    -  });
    -};
    -
    -
    -/**
    - * Unescapes XML entities.
    - * @private
    - * @param {string} str The string to unescape.
    - * @return {string} An unescaped copy of {@code str}.
    - */
    -goog.string.unescapePureXmlEntities_ = function(str) {
    -  return str.replace(/&([^;]+);/g, function(s, entity) {
    -    switch (entity) {
    -      case 'amp':
    -        return '&';
    -      case 'lt':
    -        return '<';
    -      case 'gt':
    -        return '>';
    -      case 'quot':
    -        return '"';
    -      default:
    -        if (entity.charAt(0) == '#') {
    -          // Prefix with 0 so that hex entities (e.g. &#x10) parse as hex.
    -          var n = Number('0' + entity.substr(1));
    -          if (!isNaN(n)) {
    -            return String.fromCharCode(n);
    -          }
    -        }
    -        // For invalid entities we just return the entity
    -        return s;
    -    }
    -  });
    -};
    -
    -
    -/**
    - * Regular expression that matches an HTML entity.
    - * See also HTML5: Tokenization / Tokenizing character references.
    - * @private
    - * @type {!RegExp}
    - */
    -goog.string.HTML_ENTITY_PATTERN_ = /&([^;\s<&]+);?/g;
    -
    -
    -/**
    - * Do escaping of whitespace to preserve spatial formatting. We use character
    - * entity #160 to make it safer for xml.
    - * @param {string} str The string in which to escape whitespace.
    - * @param {boolean=} opt_xml Whether to use XML compatible tags.
    - * @return {string} An escaped copy of {@code str}.
    - */
    -goog.string.whitespaceEscape = function(str, opt_xml) {
    -  // This doesn't use goog.string.preserveSpaces for backwards compatibility.
    -  return goog.string.newLineToBr(str.replace(/  /g, ' &#160;'), opt_xml);
    -};
    -
    -
    -/**
    - * Preserve spaces that would be otherwise collapsed in HTML by replacing them
    - * with non-breaking space Unicode characters.
    - * @param {string} str The string in which to preserve whitespace.
    - * @return {string} A copy of {@code str} with preserved whitespace.
    - */
    -goog.string.preserveSpaces = function(str) {
    -  return str.replace(/(^|[\n ]) /g, '$1' + goog.string.Unicode.NBSP);
    -};
    -
    -
    -/**
    - * Strip quote characters around a string.  The second argument is a string of
    - * characters to treat as quotes.  This can be a single character or a string of
    - * multiple character and in that case each of those are treated as possible
    - * quote characters. For example:
    - *
    - * <pre>
    - * goog.string.stripQuotes('"abc"', '"`') --> 'abc'
    - * goog.string.stripQuotes('`abc`', '"`') --> 'abc'
    - * </pre>
    - *
    - * @param {string} str The string to strip.
    - * @param {string} quoteChars The quote characters to strip.
    - * @return {string} A copy of {@code str} without the quotes.
    - */
    -goog.string.stripQuotes = function(str, quoteChars) {
    -  var length = quoteChars.length;
    -  for (var i = 0; i < length; i++) {
    -    var quoteChar = length == 1 ? quoteChars : quoteChars.charAt(i);
    -    if (str.charAt(0) == quoteChar && str.charAt(str.length - 1) == quoteChar) {
    -      return str.substring(1, str.length - 1);
    -    }
    -  }
    -  return str;
    -};
    -
    -
    -/**
    - * Truncates a string to a certain length and adds '...' if necessary.  The
    - * length also accounts for the ellipsis, so a maximum length of 10 and a string
    - * 'Hello World!' produces 'Hello W...'.
    - * @param {string} str The string to truncate.
    - * @param {number} chars Max number of characters.
    - * @param {boolean=} opt_protectEscapedCharacters Whether to protect escaped
    - *     characters from being cut off in the middle.
    - * @return {string} The truncated {@code str} string.
    - */
    -goog.string.truncate = function(str, chars, opt_protectEscapedCharacters) {
    -  if (opt_protectEscapedCharacters) {
    -    str = goog.string.unescapeEntities(str);
    -  }
    -
    -  if (str.length > chars) {
    -    str = str.substring(0, chars - 3) + '...';
    -  }
    -
    -  if (opt_protectEscapedCharacters) {
    -    str = goog.string.htmlEscape(str);
    -  }
    -
    -  return str;
    -};
    -
    -
    -/**
    - * Truncate a string in the middle, adding "..." if necessary,
    - * and favoring the beginning of the string.
    - * @param {string} str The string to truncate the middle of.
    - * @param {number} chars Max number of characters.
    - * @param {boolean=} opt_protectEscapedCharacters Whether to protect escaped
    - *     characters from being cutoff in the middle.
    - * @param {number=} opt_trailingChars Optional number of trailing characters to
    - *     leave at the end of the string, instead of truncating as close to the
    - *     middle as possible.
    - * @return {string} A truncated copy of {@code str}.
    - */
    -goog.string.truncateMiddle = function(str, chars,
    -    opt_protectEscapedCharacters, opt_trailingChars) {
    -  if (opt_protectEscapedCharacters) {
    -    str = goog.string.unescapeEntities(str);
    -  }
    -
    -  if (opt_trailingChars && str.length > chars) {
    -    if (opt_trailingChars > chars) {
    -      opt_trailingChars = chars;
    -    }
    -    var endPoint = str.length - opt_trailingChars;
    -    var startPoint = chars - opt_trailingChars;
    -    str = str.substring(0, startPoint) + '...' + str.substring(endPoint);
    -  } else if (str.length > chars) {
    -    // Favor the beginning of the string:
    -    var half = Math.floor(chars / 2);
    -    var endPos = str.length - half;
    -    half += chars % 2;
    -    str = str.substring(0, half) + '...' + str.substring(endPos);
    -  }
    -
    -  if (opt_protectEscapedCharacters) {
    -    str = goog.string.htmlEscape(str);
    -  }
    -
    -  return str;
    -};
    -
    -
    -/**
    - * Special chars that need to be escaped for goog.string.quote.
    - * @private {!Object<string, string>}
    - */
    -goog.string.specialEscapeChars_ = {
    -  '\0': '\\0',
    -  '\b': '\\b',
    -  '\f': '\\f',
    -  '\n': '\\n',
    -  '\r': '\\r',
    -  '\t': '\\t',
    -  '\x0B': '\\x0B', // '\v' is not supported in JScript
    -  '"': '\\"',
    -  '\\': '\\\\'
    -};
    -
    -
    -/**
    - * Character mappings used internally for goog.string.escapeChar.
    - * @private {!Object<string, string>}
    - */
    -goog.string.jsEscapeCache_ = {
    -  '\'': '\\\''
    -};
    -
    -
    -/**
    - * Encloses a string in double quotes and escapes characters so that the
    - * string is a valid JS string.
    - * @param {string} s The string to quote.
    - * @return {string} A copy of {@code s} surrounded by double quotes.
    - */
    -goog.string.quote = function(s) {
    -  s = String(s);
    -  if (s.quote) {
    -    return s.quote();
    -  } else {
    -    var sb = ['"'];
    -    for (var i = 0; i < s.length; i++) {
    -      var ch = s.charAt(i);
    -      var cc = ch.charCodeAt(0);
    -      sb[i + 1] = goog.string.specialEscapeChars_[ch] ||
    -          ((cc > 31 && cc < 127) ? ch : goog.string.escapeChar(ch));
    -    }
    -    sb.push('"');
    -    return sb.join('');
    -  }
    -};
    -
    -
    -/**
    - * Takes a string and returns the escaped string for that character.
    - * @param {string} str The string to escape.
    - * @return {string} An escaped string representing {@code str}.
    - */
    -goog.string.escapeString = function(str) {
    -  var sb = [];
    -  for (var i = 0; i < str.length; i++) {
    -    sb[i] = goog.string.escapeChar(str.charAt(i));
    -  }
    -  return sb.join('');
    -};
    -
    -
    -/**
    - * Takes a character and returns the escaped string for that character. For
    - * example escapeChar(String.fromCharCode(15)) -> "\\x0E".
    - * @param {string} c The character to escape.
    - * @return {string} An escaped string representing {@code c}.
    - */
    -goog.string.escapeChar = function(c) {
    -  if (c in goog.string.jsEscapeCache_) {
    -    return goog.string.jsEscapeCache_[c];
    -  }
    -
    -  if (c in goog.string.specialEscapeChars_) {
    -    return goog.string.jsEscapeCache_[c] = goog.string.specialEscapeChars_[c];
    -  }
    -
    -  var rv = c;
    -  var cc = c.charCodeAt(0);
    -  if (cc > 31 && cc < 127) {
    -    rv = c;
    -  } else {
    -    // tab is 9 but handled above
    -    if (cc < 256) {
    -      rv = '\\x';
    -      if (cc < 16 || cc > 256) {
    -        rv += '0';
    -      }
    -    } else {
    -      rv = '\\u';
    -      if (cc < 4096) { // \u1000
    -        rv += '0';
    -      }
    -    }
    -    rv += cc.toString(16).toUpperCase();
    -  }
    -
    -  return goog.string.jsEscapeCache_[c] = rv;
    -};
    -
    -
    -/**
    - * Determines whether a string contains a substring.
    - * @param {string} str The string to search.
    - * @param {string} subString The substring to search for.
    - * @return {boolean} Whether {@code str} contains {@code subString}.
    - */
    -goog.string.contains = function(str, subString) {
    -  return str.indexOf(subString) != -1;
    -};
    -
    -
    -/**
    - * Determines whether a string contains a substring, ignoring case.
    - * @param {string} str The string to search.
    - * @param {string} subString The substring to search for.
    - * @return {boolean} Whether {@code str} contains {@code subString}.
    - */
    -goog.string.caseInsensitiveContains = function(str, subString) {
    -  return goog.string.contains(str.toLowerCase(), subString.toLowerCase());
    -};
    -
    -
    -/**
    - * Returns the non-overlapping occurrences of ss in s.
    - * If either s or ss evalutes to false, then returns zero.
    - * @param {string} s The string to look in.
    - * @param {string} ss The string to look for.
    - * @return {number} Number of occurrences of ss in s.
    - */
    -goog.string.countOf = function(s, ss) {
    -  return s && ss ? s.split(ss).length - 1 : 0;
    -};
    -
    -
    -/**
    - * Removes a substring of a specified length at a specific
    - * index in a string.
    - * @param {string} s The base string from which to remove.
    - * @param {number} index The index at which to remove the substring.
    - * @param {number} stringLength The length of the substring to remove.
    - * @return {string} A copy of {@code s} with the substring removed or the full
    - *     string if nothing is removed or the input is invalid.
    - */
    -goog.string.removeAt = function(s, index, stringLength) {
    -  var resultStr = s;
    -  // If the index is greater or equal to 0 then remove substring
    -  if (index >= 0 && index < s.length && stringLength > 0) {
    -    resultStr = s.substr(0, index) +
    -        s.substr(index + stringLength, s.length - index - stringLength);
    -  }
    -  return resultStr;
    -};
    -
    -
    -/**
    - *  Removes the first occurrence of a substring from a string.
    - *  @param {string} s The base string from which to remove.
    - *  @param {string} ss The string to remove.
    - *  @return {string} A copy of {@code s} with {@code ss} removed or the full
    - *      string if nothing is removed.
    - */
    -goog.string.remove = function(s, ss) {
    -  var re = new RegExp(goog.string.regExpEscape(ss), '');
    -  return s.replace(re, '');
    -};
    -
    -
    -/**
    - *  Removes all occurrences of a substring from a string.
    - *  @param {string} s The base string from which to remove.
    - *  @param {string} ss The string to remove.
    - *  @return {string} A copy of {@code s} with {@code ss} removed or the full
    - *      string if nothing is removed.
    - */
    -goog.string.removeAll = function(s, ss) {
    -  var re = new RegExp(goog.string.regExpEscape(ss), 'g');
    -  return s.replace(re, '');
    -};
    -
    -
    -/**
    - * Escapes characters in the string that are not safe to use in a RegExp.
    - * @param {*} s The string to escape. If not a string, it will be casted
    - *     to one.
    - * @return {string} A RegExp safe, escaped copy of {@code s}.
    - */
    -goog.string.regExpEscape = function(s) {
    -  return String(s).replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, '\\$1').
    -      replace(/\x08/g, '\\x08');
    -};
    -
    -
    -/**
    - * Repeats a string n times.
    - * @param {string} string The string to repeat.
    - * @param {number} length The number of times to repeat.
    - * @return {string} A string containing {@code length} repetitions of
    - *     {@code string}.
    - */
    -goog.string.repeat = function(string, length) {
    -  return new Array(length + 1).join(string);
    -};
    -
    -
    -/**
    - * Pads number to given length and optionally rounds it to a given precision.
    - * For example:
    - * <pre>padNumber(1.25, 2, 3) -> '01.250'
    - * padNumber(1.25, 2) -> '01.25'
    - * padNumber(1.25, 2, 1) -> '01.3'
    - * padNumber(1.25, 0) -> '1.25'</pre>
    - *
    - * @param {number} num The number to pad.
    - * @param {number} length The desired length.
    - * @param {number=} opt_precision The desired precision.
    - * @return {string} {@code num} as a string with the given options.
    - */
    -goog.string.padNumber = function(num, length, opt_precision) {
    -  var s = goog.isDef(opt_precision) ? num.toFixed(opt_precision) : String(num);
    -  var index = s.indexOf('.');
    -  if (index == -1) {
    -    index = s.length;
    -  }
    -  return goog.string.repeat('0', Math.max(0, length - index)) + s;
    -};
    -
    -
    -/**
    - * Returns a string representation of the given object, with
    - * null and undefined being returned as the empty string.
    - *
    - * @param {*} obj The object to convert.
    - * @return {string} A string representation of the {@code obj}.
    - */
    -goog.string.makeSafe = function(obj) {
    -  return obj == null ? '' : String(obj);
    -};
    -
    -
    -/**
    - * Concatenates string expressions. This is useful
    - * since some browsers are very inefficient when it comes to using plus to
    - * concat strings. Be careful when using null and undefined here since
    - * these will not be included in the result. If you need to represent these
    - * be sure to cast the argument to a String first.
    - * For example:
    - * <pre>buildString('a', 'b', 'c', 'd') -> 'abcd'
    - * buildString(null, undefined) -> ''
    - * </pre>
    - * @param {...*} var_args A list of strings to concatenate. If not a string,
    - *     it will be casted to one.
    - * @return {string} The concatenation of {@code var_args}.
    - */
    -goog.string.buildString = function(var_args) {
    -  return Array.prototype.join.call(arguments, '');
    -};
    -
    -
    -/**
    - * Returns a string with at least 64-bits of randomness.
    - *
    - * Doesn't trust Javascript's random function entirely. Uses a combination of
    - * random and current timestamp, and then encodes the string in base-36 to
    - * make it shorter.
    - *
    - * @return {string} A random string, e.g. sn1s7vb4gcic.
    - */
    -goog.string.getRandomString = function() {
    -  var x = 2147483648;
    -  return Math.floor(Math.random() * x).toString(36) +
    -         Math.abs(Math.floor(Math.random() * x) ^ goog.now()).toString(36);
    -};
    -
    -
    -/**
    - * Compares two version numbers.
    - *
    - * @param {string|number} version1 Version of first item.
    - * @param {string|number} version2 Version of second item.
    - *
    - * @return {number}  1 if {@code version1} is higher.
    - *                   0 if arguments are equal.
    - *                  -1 if {@code version2} is higher.
    - */
    -goog.string.compareVersions = function(version1, version2) {
    -  var order = 0;
    -  // Trim leading and trailing whitespace and split the versions into
    -  // subversions.
    -  var v1Subs = goog.string.trim(String(version1)).split('.');
    -  var v2Subs = goog.string.trim(String(version2)).split('.');
    -  var subCount = Math.max(v1Subs.length, v2Subs.length);
    -
    -  // Iterate over the subversions, as long as they appear to be equivalent.
    -  for (var subIdx = 0; order == 0 && subIdx < subCount; subIdx++) {
    -    var v1Sub = v1Subs[subIdx] || '';
    -    var v2Sub = v2Subs[subIdx] || '';
    -
    -    // Split the subversions into pairs of numbers and qualifiers (like 'b').
    -    // Two different RegExp objects are needed because they are both using
    -    // the 'g' flag.
    -    var v1CompParser = new RegExp('(\\d*)(\\D*)', 'g');
    -    var v2CompParser = new RegExp('(\\d*)(\\D*)', 'g');
    -    do {
    -      var v1Comp = v1CompParser.exec(v1Sub) || ['', '', ''];
    -      var v2Comp = v2CompParser.exec(v2Sub) || ['', '', ''];
    -      // Break if there are no more matches.
    -      if (v1Comp[0].length == 0 && v2Comp[0].length == 0) {
    -        break;
    -      }
    -
    -      // Parse the numeric part of the subversion. A missing number is
    -      // equivalent to 0.
    -      var v1CompNum = v1Comp[1].length == 0 ? 0 : parseInt(v1Comp[1], 10);
    -      var v2CompNum = v2Comp[1].length == 0 ? 0 : parseInt(v2Comp[1], 10);
    -
    -      // Compare the subversion components. The number has the highest
    -      // precedence. Next, if the numbers are equal, a subversion without any
    -      // qualifier is always higher than a subversion with any qualifier. Next,
    -      // the qualifiers are compared as strings.
    -      order = goog.string.compareElements_(v1CompNum, v2CompNum) ||
    -          goog.string.compareElements_(v1Comp[2].length == 0,
    -              v2Comp[2].length == 0) ||
    -          goog.string.compareElements_(v1Comp[2], v2Comp[2]);
    -      // Stop as soon as an inequality is discovered.
    -    } while (order == 0);
    -  }
    -
    -  return order;
    -};
    -
    -
    -/**
    - * Compares elements of a version number.
    - *
    - * @param {string|number|boolean} left An element from a version number.
    - * @param {string|number|boolean} right An element from a version number.
    - *
    - * @return {number}  1 if {@code left} is higher.
    - *                   0 if arguments are equal.
    - *                  -1 if {@code right} is higher.
    - * @private
    - */
    -goog.string.compareElements_ = function(left, right) {
    -  if (left < right) {
    -    return -1;
    -  } else if (left > right) {
    -    return 1;
    -  }
    -  return 0;
    -};
    -
    -
    -/**
    - * Maximum value of #goog.string.hashCode, exclusive. 2^32.
    - * @type {number}
    - * @private
    - */
    -goog.string.HASHCODE_MAX_ = 0x100000000;
    -
    -
    -/**
    - * String hash function similar to java.lang.String.hashCode().
    - * The hash code for a string is computed as
    - * s[0] * 31 ^ (n - 1) + s[1] * 31 ^ (n - 2) + ... + s[n - 1],
    - * where s[i] is the ith character of the string and n is the length of
    - * the string. We mod the result to make it between 0 (inclusive) and 2^32
    - * (exclusive).
    - * @param {string} str A string.
    - * @return {number} Hash value for {@code str}, between 0 (inclusive) and 2^32
    - *  (exclusive). The empty string returns 0.
    - */
    -goog.string.hashCode = function(str) {
    -  var result = 0;
    -  for (var i = 0; i < str.length; ++i) {
    -    result = 31 * result + str.charCodeAt(i);
    -    // Normalize to 4 byte range, 0 ... 2^32.
    -    result %= goog.string.HASHCODE_MAX_;
    -  }
    -  return result;
    -};
    -
    -
    -/**
    - * The most recent unique ID. |0 is equivalent to Math.floor in this case.
    - * @type {number}
    - * @private
    - */
    -goog.string.uniqueStringCounter_ = Math.random() * 0x80000000 | 0;
    -
    -
    -/**
    - * Generates and returns a string which is unique in the current document.
    - * This is useful, for example, to create unique IDs for DOM elements.
    - * @return {string} A unique id.
    - */
    -goog.string.createUniqueString = function() {
    -  return 'goog_' + goog.string.uniqueStringCounter_++;
    -};
    -
    -
    -/**
    - * Converts the supplied string to a number, which may be Infinity or NaN.
    - * This function strips whitespace: (toNumber(' 123') === 123)
    - * This function accepts scientific notation: (toNumber('1e1') === 10)
    - *
    - * This is better than Javascript's built-in conversions because, sadly:
    - *     (Number(' ') === 0) and (parseFloat('123a') === 123)
    - *
    - * @param {string} str The string to convert.
    - * @return {number} The number the supplied string represents, or NaN.
    - */
    -goog.string.toNumber = function(str) {
    -  var num = Number(str);
    -  if (num == 0 && goog.string.isEmptyOrWhitespace(str)) {
    -    return NaN;
    -  }
    -  return num;
    -};
    -
    -
    -/**
    - * Returns whether the given string is lower camel case (e.g. "isFooBar").
    - *
    - * Note that this assumes the string is entirely letters.
    - * @see http://en.wikipedia.org/wiki/CamelCase#Variations_and_synonyms
    - *
    - * @param {string} str String to test.
    - * @return {boolean} Whether the string is lower camel case.
    - */
    -goog.string.isLowerCamelCase = function(str) {
    -  return /^[a-z]+([A-Z][a-z]*)*$/.test(str);
    -};
    -
    -
    -/**
    - * Returns whether the given string is upper camel case (e.g. "FooBarBaz").
    - *
    - * Note that this assumes the string is entirely letters.
    - * @see http://en.wikipedia.org/wiki/CamelCase#Variations_and_synonyms
    - *
    - * @param {string} str String to test.
    - * @return {boolean} Whether the string is upper camel case.
    - */
    -goog.string.isUpperCamelCase = function(str) {
    -  return /^([A-Z][a-z]*)+$/.test(str);
    -};
    -
    -
    -/**
    - * Converts a string from selector-case to camelCase (e.g. from
    - * "multi-part-string" to "multiPartString"), useful for converting
    - * CSS selectors and HTML dataset keys to their equivalent JS properties.
    - * @param {string} str The string in selector-case form.
    - * @return {string} The string in camelCase form.
    - */
    -goog.string.toCamelCase = function(str) {
    -  return String(str).replace(/\-([a-z])/g, function(all, match) {
    -    return match.toUpperCase();
    -  });
    -};
    -
    -
    -/**
    - * Converts a string from camelCase to selector-case (e.g. from
    - * "multiPartString" to "multi-part-string"), useful for converting JS
    - * style and dataset properties to equivalent CSS selectors and HTML keys.
    - * @param {string} str The string in camelCase form.
    - * @return {string} The string in selector-case form.
    - */
    -goog.string.toSelectorCase = function(str) {
    -  return String(str).replace(/([A-Z])/g, '-$1').toLowerCase();
    -};
    -
    -
    -/**
    - * Converts a string into TitleCase. First character of the string is always
    - * capitalized in addition to the first letter of every subsequent word.
    - * Words are delimited by one or more whitespaces by default. Custom delimiters
    - * can optionally be specified to replace the default, which doesn't preserve
    - * whitespace delimiters and instead must be explicitly included if needed.
    - *
    - * Default delimiter => " ":
    - *    goog.string.toTitleCase('oneTwoThree')    => 'OneTwoThree'
    - *    goog.string.toTitleCase('one two three')  => 'One Two Three'
    - *    goog.string.toTitleCase('  one   two   ') => '  One   Two   '
    - *    goog.string.toTitleCase('one_two_three')  => 'One_two_three'
    - *    goog.string.toTitleCase('one-two-three')  => 'One-two-three'
    - *
    - * Custom delimiter => "_-.":
    - *    goog.string.toTitleCase('oneTwoThree', '_-.')       => 'OneTwoThree'
    - *    goog.string.toTitleCase('one two three', '_-.')     => 'One two three'
    - *    goog.string.toTitleCase('  one   two   ', '_-.')    => '  one   two   '
    - *    goog.string.toTitleCase('one_two_three', '_-.')     => 'One_Two_Three'
    - *    goog.string.toTitleCase('one-two-three', '_-.')     => 'One-Two-Three'
    - *    goog.string.toTitleCase('one...two...three', '_-.') => 'One...Two...Three'
    - *    goog.string.toTitleCase('one. two. three', '_-.')   => 'One. two. three'
    - *    goog.string.toTitleCase('one-two.three', '_-.')     => 'One-Two.Three'
    - *
    - * @param {string} str String value in camelCase form.
    - * @param {string=} opt_delimiters Custom delimiter character set used to
    - *      distinguish words in the string value. Each character represents a
    - *      single delimiter. When provided, default whitespace delimiter is
    - *      overridden and must be explicitly included if needed.
    - * @return {string} String value in TitleCase form.
    - */
    -goog.string.toTitleCase = function(str, opt_delimiters) {
    -  var delimiters = goog.isString(opt_delimiters) ?
    -      goog.string.regExpEscape(opt_delimiters) : '\\s';
    -
    -  // For IE8, we need to prevent using an empty character set. Otherwise,
    -  // incorrect matching will occur.
    -  delimiters = delimiters ? '|[' + delimiters + ']+' : '';
    -
    -  var regexp = new RegExp('(^' + delimiters + ')([a-z])', 'g');
    -  return str.replace(regexp, function(all, p1, p2) {
    -    return p1 + p2.toUpperCase();
    -  });
    -};
    -
    -
    -/**
    - * Capitalizes a string, i.e. converts the first letter to uppercase
    - * and all other letters to lowercase, e.g.:
    - *
    - * goog.string.capitalize('one')     => 'One'
    - * goog.string.capitalize('ONE')     => 'One'
    - * goog.string.capitalize('one two') => 'One two'
    - *
    - * Note that this function does not trim initial whitespace.
    - *
    - * @param {string} str String value to capitalize.
    - * @return {string} String value with first letter in uppercase.
    - */
    -goog.string.capitalize = function(str) {
    -  return String(str.charAt(0)).toUpperCase() +
    -      String(str.substr(1)).toLowerCase();
    -};
    -
    -
    -/**
    - * Parse a string in decimal or hexidecimal ('0xFFFF') form.
    - *
    - * To parse a particular radix, please use parseInt(string, radix) directly. See
    - * https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/parseInt
    - *
    - * This is a wrapper for the built-in parseInt function that will only parse
    - * numbers as base 10 or base 16.  Some JS implementations assume strings
    - * starting with "0" are intended to be octal. ES3 allowed but discouraged
    - * this behavior. ES5 forbids it.  This function emulates the ES5 behavior.
    - *
    - * For more information, see Mozilla JS Reference: http://goo.gl/8RiFj
    - *
    - * @param {string|number|null|undefined} value The value to be parsed.
    - * @return {number} The number, parsed. If the string failed to parse, this
    - *     will be NaN.
    - */
    -goog.string.parseInt = function(value) {
    -  // Force finite numbers to strings.
    -  if (isFinite(value)) {
    -    value = String(value);
    -  }
    -
    -  if (goog.isString(value)) {
    -    // If the string starts with '0x' or '-0x', parse as hex.
    -    return /^\s*-?0x/i.test(value) ?
    -        parseInt(value, 16) : parseInt(value, 10);
    -  }
    -
    -  return NaN;
    -};
    -
    -
    -/**
    - * Splits a string on a separator a limited number of times.
    - *
    - * This implementation is more similar to Python or Java, where the limit
    - * parameter specifies the maximum number of splits rather than truncating
    - * the number of results.
    - *
    - * See http://docs.python.org/2/library/stdtypes.html#str.split
    - * See JavaDoc: http://goo.gl/F2AsY
    - * See Mozilla reference: http://goo.gl/dZdZs
    - *
    - * @param {string} str String to split.
    - * @param {string} separator The separator.
    - * @param {number} limit The limit to the number of splits. The resulting array
    - *     will have a maximum length of limit+1.  Negative numbers are the same
    - *     as zero.
    - * @return {!Array<string>} The string, split.
    - */
    -
    -goog.string.splitLimit = function(str, separator, limit) {
    -  var parts = str.split(separator);
    -  var returnVal = [];
    -
    -  // Only continue doing this while we haven't hit the limit and we have
    -  // parts left.
    -  while (limit > 0 && parts.length) {
    -    returnVal.push(parts.shift());
    -    limit--;
    -  }
    -
    -  // If there are remaining parts, append them to the end.
    -  if (parts.length) {
    -    returnVal.push(parts.join(separator));
    -  }
    -
    -  return returnVal;
    -};
    -
    -
    -/**
    - * Computes the Levenshtein edit distance between two strings.
    - * @param {string} a
    - * @param {string} b
    - * @return {number} The edit distance between the two strings.
    - */
    -goog.string.editDistance = function(a, b) {
    -  var v0 = [];
    -  var v1 = [];
    -
    -  if (a == b) {
    -    return 0;
    -  }
    -
    -  if (!a.length || !b.length) {
    -    return Math.max(a.length, b.length);
    -  }
    -
    -  for (var i = 0; i < b.length + 1; i++) {
    -    v0[i] = i;
    -  }
    -
    -  for (var i = 0; i < a.length; i++) {
    -    v1[0] = i + 1;
    -
    -    for (var j = 0; j < b.length; j++) {
    -      var cost = a[i] != b[j];
    -      // Cost for the substring is the minimum of adding one character, removing
    -      // one character, or a swap.
    -      v1[j + 1] = Math.min(v1[j] + 1, v0[j + 1] + 1, v0[j] + cost);
    -    }
    -
    -    for (var j = 0; j < v0.length; j++) {
    -      v0[j] = v1[j];
    -    }
    -  }
    -
    -  return v1[b.length];
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/string/string_test.html b/src/database/third_party/closure-library/closure/goog/string/string_test.html
    deleted file mode 100644
    index 11821a5bc72..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/string/string_test.html
    +++ /dev/null
    @@ -1,19 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.string</title>
    -<script src="../base.js"></script>
    -<script>
    -goog.require('goog.stringTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/string/string_test.js b/src/database/third_party/closure-library/closure/goog/string/string_test.js
    deleted file mode 100644
    index 5ac3dc0a479..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/string/string_test.js
    +++ /dev/null
    @@ -1,1327 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.string.
    - */
    -
    -/** @suppress {extraProvide} */
    -goog.provide('goog.stringTest');
    -
    -goog.require('goog.functions');
    -goog.require('goog.object');
    -goog.require('goog.string');
    -goog.require('goog.string.Unicode');
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.stringTest');
    -
    -var stubs;
    -var mockControl;
    -
    -function setUp() {
    -  stubs = new goog.testing.PropertyReplacer();
    -  mockControl = new goog.testing.MockControl();
    -}
    -
    -function tearDown() {
    -  stubs.reset();
    -  mockControl.$tearDown();
    -}
    -
    -
    -//=== tests for goog.string.collapseWhitespace ===
    -
    -function testCollapseWhiteSpace() {
    -  var f = goog.string.collapseWhitespace;
    -
    -  assertEquals('Leading spaces not stripped', f('  abc'), 'abc');
    -  assertEquals('Trailing spaces not stripped', f('abc  '), 'abc');
    -  assertEquals('Wrapping spaces not stripped', f('  abc  '), 'abc');
    -
    -  assertEquals('All white space chars not stripped',
    -               f('\xa0\n\t abc\xa0\n\t '), 'abc');
    -
    -  assertEquals('Spaces not collapsed', f('a   b    c'), 'a b c');
    -
    -  assertEquals('Tabs not collapsed', f('a\t\t\tb\tc'), 'a b c');
    -
    -  assertEquals('All check failed', f(' \ta \t \t\tb\t\n\xa0  c  \t\n'),
    -               'a b c');
    -}
    -
    -
    -function testIsEmpty() {
    -  assertTrue(goog.string.isEmpty(''));
    -  assertTrue(goog.string.isEmpty(' '));
    -  assertTrue(goog.string.isEmpty('    '));
    -  assertTrue(goog.string.isEmpty(' \t\t\n\xa0   '));
    -
    -  assertFalse(goog.string.isEmpty(' abc \t\xa0'));
    -  assertFalse(goog.string.isEmpty(' a b c \t'));
    -  assertFalse(goog.string.isEmpty(';'));
    -
    -  assertFalse(goog.string.isEmpty(undefined));
    -  assertFalse(goog.string.isEmpty(null));
    -  assertFalse(goog.string.isEmpty({a: 1, b: 2}));
    -}
    -
    -
    -function testIsEmptyOrWhitespace() {
    -  assertTrue(goog.string.isEmptyOrWhitespace(''));
    -  assertTrue(goog.string.isEmptyOrWhitespace(' '));
    -  assertTrue(goog.string.isEmptyOrWhitespace('    '));
    -  assertTrue(goog.string.isEmptyOrWhitespace(' \t\t\n\xa0   '));
    -
    -  assertFalse(goog.string.isEmptyOrWhitespace(' abc \t\xa0'));
    -  assertFalse(goog.string.isEmptyOrWhitespace(' a b c \t'));
    -  assertFalse(goog.string.isEmptyOrWhitespace(';'));
    -
    -  assertFalse(goog.string.isEmptyOrWhitespace(undefined));
    -  assertFalse(goog.string.isEmptyOrWhitespace(null));
    -  assertFalse(goog.string.isEmptyOrWhitespace({a: 1, b: 2}));
    -}
    -
    -
    -function testIsEmptyString() {
    -  assertTrue(goog.string.isEmptyString(''));
    -
    -  assertFalse(goog.string.isEmptyString(' '));
    -  assertFalse(goog.string.isEmptyString('    '));
    -  assertFalse(goog.string.isEmptyString(' \t\t\n\xa0   '));
    -  assertFalse(goog.string.isEmptyString(' abc \t\xa0'));
    -  assertFalse(goog.string.isEmptyString(' a b c \t'));
    -  assertFalse(goog.string.isEmptyString(';'));
    -
    -  assertFalse(goog.string.isEmptyString({a: 1, b: 2}));
    -}
    -
    -
    -function testIsEmptySafe() {
    -  assertTrue(goog.string.isEmptySafe(''));
    -  assertTrue(goog.string.isEmptySafe(' '));
    -  assertTrue(goog.string.isEmptySafe('    '));
    -  assertTrue(goog.string.isEmptySafe(' \t\t\n\xa0   '));
    -
    -  assertFalse(goog.string.isEmptySafe(' abc \t\xa0'));
    -  assertFalse(goog.string.isEmptySafe(' a b c \t'));
    -  assertFalse(goog.string.isEmptySafe(';'));
    -
    -  assertTrue(goog.string.isEmptySafe(undefined));
    -  assertTrue(goog.string.isEmptySafe(null));
    -  assertFalse(goog.string.isEmptySafe({a: 1, b: 2}));
    -}
    -
    -
    -function testIsEmptyOrWhitespaceSafe() {
    -  assertTrue(goog.string.isEmptyOrWhitespaceSafe(''));
    -  assertTrue(goog.string.isEmptyOrWhitespaceSafe(' '));
    -  assertTrue(goog.string.isEmptyOrWhitespaceSafe('    '));
    -  assertTrue(goog.string.isEmptyOrWhitespaceSafe(' \t\t\n\xa0   '));
    -
    -  assertFalse(goog.string.isEmptyOrWhitespaceSafe(' abc \t\xa0'));
    -  assertFalse(goog.string.isEmptyOrWhitespaceSafe(' a b c \t'));
    -  assertFalse(goog.string.isEmptyOrWhitespaceSafe(';'));
    -
    -  assertTrue(goog.string.isEmptyOrWhitespaceSafe(undefined));
    -  assertTrue(goog.string.isEmptyOrWhitespaceSafe(null));
    -  assertFalse(goog.string.isEmptyOrWhitespaceSafe({a: 1, b: 2}));
    -}
    -
    -
    -//=== tests for goog.string.isAlpha ===
    -function testIsAlpha() {
    -  assertTrue('"a" should be alpha', goog.string.isAlpha('a'));
    -  assertTrue('"n" should be alpha', goog.string.isAlpha('n'));
    -  assertTrue('"z" should be alpha', goog.string.isAlpha('z'));
    -  assertTrue('"A" should be alpha', goog.string.isAlpha('A'));
    -  assertTrue('"N" should be alpha', goog.string.isAlpha('N'));
    -  assertTrue('"Z" should be alpha', goog.string.isAlpha('Z'));
    -  assertTrue('"aa" should be alpha', goog.string.isAlpha('aa'));
    -  assertTrue('null is alpha', goog.string.isAlpha(null));
    -  assertTrue('undefined is alpha', goog.string.isAlpha(undefined));
    -
    -  assertFalse('"aa!" is not alpha', goog.string.isAlpha('aa!s'));
    -  assertFalse('"!" is not alpha', goog.string.isAlpha('!'));
    -  assertFalse('"0" is not alpha', goog.string.isAlpha('0'));
    -  assertFalse('"5" is not alpha', goog.string.isAlpha('5'));
    -}
    -
    -
    -
    -//=== tests for goog.string.isNumeric ===
    -function testIsNumeric() {
    -  assertTrue('"8" is a numeric string', goog.string.isNumeric('8'));
    -  assertTrue('"5" is a numeric string', goog.string.isNumeric('5'));
    -  assertTrue('"34" is a numeric string', goog.string.isNumeric('34'));
    -  assertTrue('34 is a number', goog.string.isNumeric(34));
    -
    -  assertFalse('"3.14" has a period', goog.string.isNumeric('3.14'));
    -  assertFalse('"A" is a letter', goog.string.isNumeric('A'));
    -  assertFalse('"!" is punctuation', goog.string.isNumeric('!'));
    -  assertFalse('null is not numeric', goog.string.isNumeric(null));
    -  assertFalse('undefined is not numeric', goog.string.isNumeric(undefined));
    -}
    -
    -
    -//=== tests for tests for goog.string.isAlphaNumeric ===
    -function testIsAlphaNumeric() {
    -  assertTrue('"ABCabc" should be alphanumeric',
    -             goog.string.isAlphaNumeric('ABCabc'));
    -  assertTrue('"123" should be alphanumeric', goog.string.isAlphaNumeric('123'));
    -  assertTrue('"ABCabc123" should be alphanumeric',
    -             goog.string.isAlphaNumeric('ABCabc123'));
    -  assertTrue('null is alphanumeric', goog.string.isAlphaNumeric(null));
    -  assertTrue('undefined is alphanumeric',
    -             goog.string.isAlphaNumeric(undefined));
    -
    -  assertFalse('"123!" should not be alphanumeric',
    -              goog.string.isAlphaNumeric('123!'));
    -  assertFalse('"  " should not be alphanumeric',
    -              goog.string.isAlphaNumeric('  '));
    -}
    -
    -
    -//== tests for goog.string.isBreakingWhitespace ===
    -
    -function testIsBreakingWhitespace() {
    -  assertTrue('" " is breaking', goog.string.isBreakingWhitespace(' '));
    -  assertTrue('"\\n" is breaking', goog.string.isBreakingWhitespace('\n'));
    -  assertTrue('"\\t" is breaking', goog.string.isBreakingWhitespace('\t'));
    -  assertTrue('"\\r" is breaking', goog.string.isBreakingWhitespace('\r'));
    -  assertTrue('"\\r\\n\\t " is breaking',
    -      goog.string.isBreakingWhitespace('\r\n\t '));
    -
    -  assertFalse('nbsp is non-breaking', goog.string.isBreakingWhitespace('\xa0'));
    -  assertFalse('"a" is non-breaking', goog.string.isBreakingWhitespace('a'));
    -  assertFalse('"a\\r" is non-breaking',
    -      goog.string.isBreakingWhitespace('a\r'));
    -}
    -
    -
    -//=== tests for goog.string.isSpace ===
    -function testIsSpace() {
    -  assertTrue('" " is a space', goog.string.isSpace(' '));
    -
    -  assertFalse('"\\n" is not a space', goog.string.isSpace('\n'));
    -  assertFalse('"\\t" is not a space', goog.string.isSpace('\t'));
    -  assertFalse('"  " is not a space, it\'s two spaces',
    -              goog.string.isSpace('  '));
    -  assertFalse('"a" is not a space', goog.string.isSpace('a'));
    -  assertFalse('"3" is not a space', goog.string.isSpace('3'));
    -  assertFalse('"#" is not a space', goog.string.isSpace('#'));
    -  assertFalse('null is not a space', goog.string.isSpace(null));
    -  assertFalse('nbsp is not a space', goog.string.isSpace('\xa0'));
    -}
    -
    -
    -// === tests for goog.string.stripNewlines ===
    -function testStripNewLines() {
    -  assertEquals('Should replace new lines with spaces',
    -               goog.string.stripNewlines('some\nlines\rthat\r\nare\n\nsplit'),
    -               'some lines that are split');
    -}
    -
    -
    -// === tests for goog.string.canonicalizeNewlines ===
    -function testCanonicalizeNewlines() {
    -  assertEquals('Should replace all types of new line with \\n',
    -               goog.string.canonicalizeNewlines(
    -      'some\nlines\rthat\r\nare\n\nsplit'),
    -               'some\nlines\nthat\nare\n\nsplit');
    -}
    -
    -
    -// === tests for goog.string.normalizeWhitespace ===
    -function testNormalizeWhitespace() {
    -  assertEquals('All whitespace chars should be replaced with a normal space',
    -               goog.string.normalizeWhitespace('\xa0 \n\t \xa0 \n\t'),
    -               '         ');
    -}
    -
    -
    -// === tests for goog.string.normalizeSpaces ===
    -function testNormalizeSpaces() {
    -  assertEquals('All whitespace chars should be replaced with a normal space',
    -               goog.string.normalizeSpaces('\xa0 \t \xa0 \t'),
    -               '    ');
    -}
    -
    -function testCollapseBreakingSpaces() {
    -  assertEquals('breaking spaces are collapsed', 'a b',
    -      goog.string.collapseBreakingSpaces(' \t\r\n a \t\r\n b \t\r\n '));
    -  assertEquals('non-breaking spaces are kept', 'a \u00a0\u2000 b',
    -      goog.string.collapseBreakingSpaces('a \u00a0\u2000 b'));
    -}
    -
    -/// === tests for goog.string.trim ===
    -function testTrim() {
    -  assertEquals('Should be the same', goog.string.trim('nothing 2 trim'),
    -               'nothing 2 trim');
    -  assertEquals('Remove spaces', goog.string.trim('   hello  goodbye   '),
    -               'hello  goodbye');
    -  assertEquals('Trim other stuff', goog.string.trim('\n\r\xa0 hi \r\n\xa0'),
    -               'hi');
    -}
    -
    -
    -/// === tests for goog.string.trimLeft ===
    -function testTrimLeft() {
    -  var f = goog.string.trimLeft;
    -  assertEquals('Should be the same', f('nothing to trim'), 'nothing to trim');
    -  assertEquals('Remove spaces', f('   hello  goodbye   '), 'hello  goodbye   ');
    -  assertEquals('Trim other stuff', f('\xa0\n\r hi \r\n\xa0'), 'hi \r\n\xa0');
    -}
    -
    -
    -/// === tests for goog.string.trimRight ===
    -function testTrimRight() {
    -  var f = goog.string.trimRight;
    -  assertEquals('Should be the same', f('nothing to trim'), 'nothing to trim');
    -  assertEquals('Remove spaces', f('   hello  goodbye   '), '   hello  goodbye');
    -  assertEquals('Trim other stuff', f('\n\r\xa0 hi \r\n\xa0'), '\n\r\xa0 hi');
    -}
    -
    -
    -// === tests for goog.string.startsWith ===
    -function testStartsWith() {
    -  assertTrue('Should start with \'\'', goog.string.startsWith('abcd', ''));
    -  assertTrue('Should start with \'ab\'', goog.string.startsWith('abcd', 'ab'));
    -  assertTrue('Should start with \'abcd\'',
    -             goog.string.startsWith('abcd', 'abcd'));
    -  assertFalse('Should not start with \'bcd\'',
    -              goog.string.startsWith('abcd', 'bcd'));
    -}
    -
    -function testEndsWith() {
    -  assertTrue('Should end with \'\'', goog.string.endsWith('abcd', ''));
    -  assertTrue('Should end with \'ab\'', goog.string.endsWith('abcd', 'cd'));
    -  assertTrue('Should end with \'abcd\'', goog.string.endsWith('abcd', 'abcd'));
    -  assertFalse('Should not end \'abc\'', goog.string.endsWith('abcd', 'abc'));
    -  assertFalse('Should not end \'abcde\'',
    -              goog.string.endsWith('abcd', 'abcde'));
    -}
    -
    -
    -// === tests for goog.string.caseInsensitiveStartsWith ===
    -function testCaseInsensitiveStartsWith() {
    -  assertTrue('Should start with \'\'',
    -             goog.string.caseInsensitiveStartsWith('abcd', ''));
    -  assertTrue('Should start with \'ab\'',
    -             goog.string.caseInsensitiveStartsWith('abcd', 'Ab'));
    -  assertTrue('Should start with \'abcd\'',
    -             goog.string.caseInsensitiveStartsWith('AbCd', 'abCd'));
    -  assertFalse('Should not start with \'bcd\'',
    -              goog.string.caseInsensitiveStartsWith('ABCD', 'bcd'));
    -}
    -
    -// === tests for goog.string.caseInsensitiveEndsWith ===
    -function testCaseInsensitiveEndsWith() {
    -  assertTrue('Should end with \'\'',
    -             goog.string.caseInsensitiveEndsWith('abcd', ''));
    -  assertTrue('Should end with \'cd\'',
    -             goog.string.caseInsensitiveEndsWith('abCD', 'cd'));
    -  assertTrue('Should end with \'abcd\'',
    -             goog.string.caseInsensitiveEndsWith('abcd', 'abCd'));
    -  assertFalse('Should not end \'abc\'',
    -              goog.string.caseInsensitiveEndsWith('aBCd', 'ABc'));
    -  assertFalse('Should not end \'abcde\'',
    -              goog.string.caseInsensitiveEndsWith('ABCD', 'abcde'));
    -}
    -
    -// === tests for goog.string.caseInsensitiveEquals ===
    -function testCaseInsensitiveEquals() {
    -
    -  function assertCaseInsensitiveEquals(str1, str2) {
    -    assertTrue(goog.string.caseInsensitiveEquals(str1, str2));
    -  }
    -
    -  function assertCaseInsensitiveNotEquals(str1, str2) {
    -    assertFalse(goog.string.caseInsensitiveEquals(str1, str2));
    -  }
    -
    -  assertCaseInsensitiveEquals('abc', 'abc');
    -  assertCaseInsensitiveEquals('abc', 'abC');
    -  assertCaseInsensitiveEquals('d,e,F,G', 'd,e,F,G');
    -  assertCaseInsensitiveEquals('ABCD EFGH 1234', 'abcd efgh 1234');
    -  assertCaseInsensitiveEquals('FooBarBaz', 'fOObARbAZ');
    -
    -  assertCaseInsensitiveNotEquals('ABCD EFGH', 'abcd efg');
    -  assertCaseInsensitiveNotEquals('ABC DEFGH', 'ABCD EFGH');
    -  assertCaseInsensitiveNotEquals('FooBarBaz', 'fOObARbAZ ');
    -}
    -
    -
    -// === tests for goog.string.subs ===
    -function testSubs() {
    -  assertEquals('Should be the same',
    -               'nothing to subs',
    -               goog.string.subs('nothing to subs'));
    -  assertEquals('Should be the same',
    -               '1',
    -               goog.string.subs('%s', '1'));
    -  assertEquals('Should be the same',
    -               '12true',
    -               goog.string.subs('%s%s%s', '1', 2, true));
    -  function f() {
    -    fail('This should not be called');
    -  }
    -  f.toString = function() { return 'f'; };
    -  assertEquals('Should not call function', 'f', goog.string.subs('%s', f));
    -
    -  // If the string that is to be substituted in contains $& then it will be
    -  // usually be replaced with %s, we need to check goog.string.subs, handles
    -  // this case.
    -  assertEquals('$& should not be substituted with %s', 'Foo Bar $&',
    -      goog.string.subs('Foo %s', 'Bar $&'));
    -
    -  assertEquals('$$ should not be substituted', '_$$_',
    -               goog.string.subs('%s', '_$$_'));
    -  assertEquals('$` should not be substituted', '_$`_',
    -               goog.string.subs('%s', '_$`_'));
    -  assertEquals('$\' should not be substituted', '_$\'_',
    -               goog.string.subs('%s', '_$\'_'));
    -  for (var i = 0; i < 99; i += 9) {
    -    assertEquals('$' + i + ' should not be substituted',
    -        '_$' + i + '_', goog.string.subs('%s', '_$' + i + '_'));
    -  }
    -
    -  assertEquals(
    -      'Only the first three "%s" strings should be replaced.',
    -      'test foo test bar test baz test %s test %s test',
    -      goog.string.subs(
    -          'test %s test %s test %s test %s test %s test',
    -          'foo', 'bar', 'baz'));
    -}
    -
    -
    -/**
    - * Verifies that if too many arguments are given, they are ignored.
    - * Logic test for bug documented here: http://go/eusxz
    - */
    -function testSubsTooManyArguments() {
    -  assertEquals('one', goog.string.subs('one', 'two', 'three'));
    -  assertEquals('onetwo', goog.string.subs('one%s', 'two', 'three'));
    -}
    -
    -
    -// === tests for goog.string.caseInsensitiveCompare ===
    -function testCaseInsensitiveCompare() {
    -  var f = goog.string.caseInsensitiveCompare;
    -
    -  assert('"ABC" should be less than "def"', f('ABC', 'def') == -1);
    -  assert('"abc" should be less than "DEF"', f('abc', 'DEF') == -1);
    -
    -  assert('"XYZ" should equal "xyz"', f('XYZ', 'xyz') == 0);
    -
    -  assert('"XYZ" should be greater than "UVW"', f('xyz', 'UVW') == 1);
    -  assert('"XYZ" should be greater than "uvw"', f('XYZ', 'uvw') == 1);
    -}
    -
    -
    -// === tests for goog.string.numerateCompare ===
    -function testNumerateCompare() {
    -  var f = goog.string.numerateCompare;
    -
    -  // Each comparison in this list is tested to assure that t[0] < t[1],
    -  // t[1] > t[0], and identity tests t[0] == t[0] and t[1] == t[1].
    -  var comparisons = [
    -    ['', '0'],
    -    ['2', '10'],
    -    ['05', '9'],
    -    ['3.14', '3.2'],
    -    ['sub', 'substring'],
    -    ['Photo 7', 'photo 8'], // Case insensitive for most sorts.
    -    ['Mango', 'mango'], // Case sensitive if strings are otherwise identical.
    -    ['album 2 photo 20', 'album 10 photo 20'],
    -    ['album 7 photo 20', 'album 7 photo 100']];
    -
    -  for (var i = 0; i < comparisons.length; i++) {
    -    var t = comparisons[i];
    -    assert(t[0] + ' should be less than ' + t[1],
    -           f(t[0], t[1]) < 0);
    -    assert(t[1] + ' should be greater than ' + t[0],
    -           f(t[1], t[0]) > 0);
    -    assert(t[0] + ' should be equal to ' + t[0],
    -           f(t[0], t[0]) == 0);
    -    assert(t[1] + ' should be equal to ' + t[1],
    -           f(t[1], t[1]) == 0);
    -  }
    -}
    -
    -// === tests for goog.string.urlEncode && .urlDecode ===
    -// NOTE: When test was written it was simply an alias for the built in
    -// 'encodeURICompoent', therefore this test is simply used to make sure that in
    -// the future it doesn't get broken.
    -function testUrlEncodeAndDecode() {
    -  var input = '<p>"hello there," she said, "what is going on here?</p>';
    -  var output = '%3Cp%3E%22hello%20there%2C%22%20she%20said%2C%20%22what%20is' +
    -               '%20going%20on%20here%3F%3C%2Fp%3E';
    -
    -  assertEquals('urlEncode vs encodeURIComponent',
    -               encodeURIComponent(input),
    -               goog.string.urlEncode(input));
    -
    -  assertEquals('urlEncode vs model', goog.string.urlEncode(input), output);
    -
    -  assertEquals('urlDecode vs model', goog.string.urlDecode(output), input);
    -
    -  assertEquals('urlDecode vs urlEncode',
    -               goog.string.urlDecode(goog.string.urlEncode(input)), input);
    -
    -  assertEquals('urlDecode with +s instead of %20s',
    -               goog.string.urlDecode(output.replace(/%20/g, '+')),
    -               input);
    -}
    -
    -
    -// === tests for goog.string.newLineToBr ===
    -function testNewLineToBr() {
    -  var str = 'some\nlines\rthat\r\nare\n\nsplit';
    -  var html = 'some<br>lines<br>that<br>are<br><br>split';
    -  var xhtml = 'some<br />lines<br />that<br />are<br /><br />split';
    -
    -  assertEquals('Should be html', goog.string.newLineToBr(str), html);
    -  assertEquals('Should be html', goog.string.newLineToBr(str, false), html);
    -  assertEquals('Should be xhtml', goog.string.newLineToBr(str, true), xhtml);
    -
    -}
    -
    -
    -// === tests for goog.string.htmlEscape and .unescapeEntities ===
    -function testHtmlEscapeAndUnescapeEntities() {
    -  var text = '\'"x1 < x2 && y2 > y1"\'';
    -  var html = '&#39;&quot;x1 &lt; x2 &amp;&amp; y2 &gt; y1&quot;&#39;';
    -
    -  assertEquals('Testing htmlEscape', html, goog.string.htmlEscape(text));
    -  assertEquals('Testing htmlEscape', html, goog.string.htmlEscape(text, false));
    -  assertEquals('Testing htmlEscape', html, goog.string.htmlEscape(text, true));
    -  assertEquals('Testing unescapeEntities', text,
    -               goog.string.unescapeEntities(html));
    -
    -  assertEquals('escape -> unescape', text,
    -               goog.string.unescapeEntities(goog.string.htmlEscape(text)));
    -  assertEquals('unescape -> escape', html,
    -               goog.string.htmlEscape(goog.string.unescapeEntities(html)));
    -}
    -
    -function testHtmlUnescapeEntitiesWithDocument() {
    -  var documentMock = {
    -    createElement: mockControl.createFunctionMock('createElement')
    -  };
    -  var divMock = document.createElement('div');
    -  documentMock.createElement('div').$returns(divMock);
    -  mockControl.$replayAll();
    -
    -  var html = '&lt;a&b&gt;';
    -  var text = '<a&b>';
    -
    -  assertEquals('wrong unescaped value',
    -      text, goog.string.unescapeEntitiesWithDocument(html, documentMock));
    -  assertNotEquals('divMock.innerHTML should have been used', '',
    -      divMock.innerHTML);
    -  mockControl.$verifyAll();
    -}
    -
    -function testHtmlEscapeAndUnescapeEntitiesUsingDom() {
    -  var text = '"x1 < x2 && y2 > y1"';
    -  var html = '&quot;x1 &lt; x2 &amp;&amp; y2 &gt; y1&quot;';
    -
    -  assertEquals('Testing unescapeEntities',
    -               goog.string.unescapeEntitiesUsingDom_(html), text);
    -  assertEquals('escape -> unescape',
    -               goog.string.unescapeEntitiesUsingDom_(
    -                   goog.string.htmlEscape(text)), text);
    -  assertEquals('unescape -> escape',
    -               goog.string.htmlEscape(
    -                   goog.string.unescapeEntitiesUsingDom_(html)), html);
    -}
    -
    -function testHtmlUnescapeEntitiesUsingDom_withAmpersands() {
    -  var html = '&lt;a&b&gt;';
    -  var text = '<a&b>';
    -
    -  assertEquals('wrong unescaped value',
    -      text, goog.string.unescapeEntitiesUsingDom_(html));
    -}
    -
    -function testHtmlEscapeAndUnescapePureXmlEntities_() {
    -  var text = '"x1 < x2 && y2 > y1"';
    -  var html = '&quot;x1 &lt; x2 &amp;&amp; y2 &gt; y1&quot;';
    -
    -  assertEquals('Testing unescapePureXmlEntities_',
    -               goog.string.unescapePureXmlEntities_(html), text);
    -  assertEquals('escape -> unescape',
    -               goog.string.unescapePureXmlEntities_(
    -                   goog.string.htmlEscape(text)), text);
    -  assertEquals('unescape -> escape',
    -               goog.string.htmlEscape(
    -                   goog.string.unescapePureXmlEntities_(html)), html);
    -}
    -
    -
    -function testForceNonDomHtmlUnescaping() {
    -  stubs.set(goog.string, 'FORCE_NON_DOM_HTML_UNESCAPING', true);
    -  // Set document.createElement to empty object so that the call to
    -  // unescapeEntities will blow up if html unescaping is carried out with DOM.
    -  // Notice that we can't directly set document to empty object since IE8 won't
    -  // let us do so.
    -  stubs.set(goog.global.document, 'createElement', {});
    -  goog.string.unescapeEntities('&quot;x1 &lt; x2 &amp;&amp; y2 &gt; y1&quot;');
    -}
    -
    -
    -function testHtmlEscapeDetectDoubleEscaping() {
    -  stubs.set(goog.string, 'DETECT_DOUBLE_ESCAPING', true);
    -  assertEquals('&#101; &lt; pi', goog.string.htmlEscape('e < pi'));
    -  assertEquals('&#101; &lt; pi', goog.string.htmlEscape('e < pi', true));
    -}
    -
    -function testHtmlEscapeNullByte() {
    -  assertEquals('&#0;', goog.string.htmlEscape('\x00'));
    -  assertEquals('&#0;', goog.string.htmlEscape('\x00', true));
    -  assertEquals('\\x00', goog.string.htmlEscape('\\x00'));
    -  assertEquals('\\x00', goog.string.htmlEscape('\\x00', true));
    -}
    -
    -var globalXssVar = 0;
    -
    -function testXssUnescapeEntities() {
    -  // This tests that we don't have any XSS exploits in unescapeEntities
    -  var test = '&amp;<script defer>globalXssVar=1;</' + 'script>';
    -  var expected = '&<script defer>globalXssVar=1;</' + 'script>';
    -
    -  assertEquals('Testing unescapeEntities', expected,
    -               goog.string.unescapeEntities(test));
    -  assertEquals('unescapeEntities is vulnarable to XSS', 0, globalXssVar);
    -
    -  test = '&amp;<script>globalXssVar=1;</' + 'script>';
    -  expected = '&<script>globalXssVar=1;</' + 'script>';
    -
    -  assertEquals('Testing unescapeEntities', expected,
    -               goog.string.unescapeEntities(test));
    -  assertEquals('unescapeEntities is vulnarable to XSS', 0, globalXssVar);
    -}
    -
    -
    -function testXssUnescapeEntitiesUsingDom() {
    -  // This tests that we don't have any XSS exploits in unescapeEntitiesUsingDom
    -  var test = '&amp;<script defer>globalXssVar=1;</' + 'script>';
    -  var expected = '&<script defer>globalXssVar=1;</' + 'script>';
    -
    -  assertEquals('Testing unescapeEntitiesUsingDom_', expected,
    -               goog.string.unescapeEntitiesUsingDom_(test));
    -  assertEquals('unescapeEntitiesUsingDom_ is vulnerable to XSS', 0,
    -               globalXssVar);
    -
    -  test = '&amp;<script>globalXssVar=1;</' + 'script>';
    -  expected = '&<script>globalXssVar=1;</' + 'script>';
    -
    -  assertEquals('Testing unescapeEntitiesUsingDom_', expected,
    -               goog.string.unescapeEntitiesUsingDom_(test));
    -  assertEquals('unescapeEntitiesUsingDom_ is vulnerable to XSS', 0,
    -               globalXssVar);
    -}
    -
    -
    -function testXssUnescapePureXmlEntities() {
    -  // This tests that we don't have any XSS exploits in unescapePureXmlEntities
    -  var test = '&amp;<script defer>globalXssVar=1;</' + 'script>';
    -  var expected = '&<script defer>globalXssVar=1;</' + 'script>';
    -
    -  assertEquals('Testing unescapePureXmlEntities_', expected,
    -               goog.string.unescapePureXmlEntities_(test));
    -  assertEquals('unescapePureXmlEntities_ is vulnarable to XSS', 0,
    -               globalXssVar);
    -
    -  test = '&amp;<script>globalXssVar=1;</' + 'script>';
    -  expected = '&<script>globalXssVar=1;</' + 'script>';
    -
    -  assertEquals('Testing unescapePureXmlEntities_', expected,
    -               goog.string.unescapePureXmlEntities_(test));
    -  assertEquals('unescapePureXmlEntities_ is vulnarable to XSS', 0,
    -               globalXssVar);
    -}
    -
    -
    -function testUnescapeEntitiesPreservesWhitespace() {
    -  // This tests that whitespace is preserved (primarily for IE)
    -  // Also make sure leading and trailing whitespace are preserved.
    -  var test = '\nTesting\n\twhitespace\n    preservation\n';
    -  var expected = test;
    -
    -  assertEquals('Testing unescapeEntities', expected,
    -               goog.string.unescapeEntities(test));
    -
    -  // Now with entities
    -  test += ' &amp;&nbsp;\n';
    -  expected += ' &\u00A0\n';
    -  assertEquals('Testing unescapeEntities', expected,
    -               goog.string.unescapeEntities(test));
    -}
    -
    -
    -// === tests for goog.string.whitespaceEscape ===
    -function testWhitespaceEscape() {
    -  assertEquals('Should be the same',
    -      goog.string.whitespaceEscape('one two  three   four    five     '),
    -      'one two &#160;three &#160; four &#160; &#160;five &#160; &#160; ');
    -}
    -
    -
    -// === tests for goog.string.preserveSpaces ===
    -function testPreserveSpaces() {
    -  var nbsp = goog.string.Unicode.NBSP;
    -  assertEquals('', goog.string.preserveSpaces(''));
    -  assertEquals(nbsp + 'a', goog.string.preserveSpaces(' a'));
    -  assertEquals(nbsp + ' a', goog.string.preserveSpaces('  a'));
    -  assertEquals(nbsp + ' ' + nbsp + 'a', goog.string.preserveSpaces('   a'));
    -  assertEquals('a ' + nbsp + 'b', goog.string.preserveSpaces('a  b'));
    -  assertEquals('a\n' + nbsp + 'b', goog.string.preserveSpaces('a\n b'));
    -
    -  // We don't care about trailing spaces.
    -  assertEquals('a ', goog.string.preserveSpaces('a '));
    -  assertEquals('a \n' + nbsp + 'b', goog.string.preserveSpaces('a \n b'));
    -}
    -
    -
    -// === tests for goog.string.stripQuotes ===
    -function testStripQuotes() {
    -  assertEquals('Quotes should be stripped',
    -               goog.string.stripQuotes('"hello"', '"'),
    -               'hello');
    -
    -  assertEquals('Quotes should be stripped',
    -               goog.string.stripQuotes('\'hello\'', '\''),
    -               'hello');
    -
    -  assertEquals('Quotes should not be stripped',
    -               goog.string.stripQuotes('-"hello"', '"'),
    -               '-"hello"');
    -}
    -
    -function testStripQuotesMultiple() {
    -  assertEquals('Quotes should be stripped',
    -               goog.string.stripQuotes('"hello"', '"\''),
    -               'hello');
    -  assertEquals('Quotes should be stripped',
    -               goog.string.stripQuotes('\'hello\'', '"\''),
    -               'hello');
    -
    -  assertEquals('Quotes should be stripped',
    -               goog.string.stripQuotes('\'hello\'', ''),
    -               '\'hello\'');
    -}
    -
    -function testStripQuotesMultiple2() {
    -  // Makes sure we do not strip twice
    -  assertEquals('Quotes should be stripped',
    -               goog.string.stripQuotes('"\'hello\'"', '"\''),
    -               '\'hello\'');
    -  assertEquals('Quotes should be stripped',
    -               goog.string.stripQuotes('"\'hello\'"', '\'"'),
    -               '\'hello\'');
    -
    -}
    -
    -// === tests for goog.string.truncate ===
    -function testTruncate() {
    -  var str = 'abcdefghijklmnopqrstuvwxyz';
    -  assertEquals('Should be equal', goog.string.truncate(str, 8), 'abcde...');
    -  assertEquals('Should be equal', goog.string.truncate(str, 11), 'abcdefgh...');
    -
    -  var html = 'true &amp;&amp; false == false';
    -  assertEquals('Should clip html char', goog.string.truncate(html, 11),
    -               'true &am...');
    -  assertEquals('Should not clip html char',
    -               goog.string.truncate(html, 12, true),
    -               'true &amp;&amp; f...');
    -}
    -
    -
    -// === tests for goog.string.truncateMiddle ===
    -function testTruncateMiddle() {
    -  var str = 'abcdefghijklmnopqrstuvwxyz';
    -  assertEquals('abc...xyz', goog.string.truncateMiddle(str, 6));
    -  assertEquals('abc...yz', goog.string.truncateMiddle(str, 5));
    -  assertEquals(str, goog.string.truncateMiddle(str, str.length));
    -
    -  var html = 'true &amp;&amp; false == false';
    -  assertEquals('Should clip html char', 'true &a...= false',
    -      goog.string.truncateMiddle(html, 14));
    -  assertEquals('Should not clip html char',
    -      'true &amp;&amp;...= false',
    -      goog.string.truncateMiddle(html, 14, true));
    -
    -  assertEquals('ab...xyz', goog.string.truncateMiddle(str, 5, null, 3));
    -  assertEquals('abcdefg...xyz', goog.string.truncateMiddle(str, 10, null, 3));
    -  assertEquals('abcdef...wxyz', goog.string.truncateMiddle(str, 10, null, 4));
    -  assertEquals('...yz', goog.string.truncateMiddle(str, 2, null, 3));
    -  assertEquals(str, goog.string.truncateMiddle(str, 50, null, 3));
    -
    -  assertEquals('Should clip html char', 'true &amp;&...lse',
    -      goog.string.truncateMiddle(html, 14, null, 3));
    -  assertEquals('Should not clip html char',
    -      'true &amp;&amp; fal...lse',
    -      goog.string.truncateMiddle(html, 14, true, 3));
    -}
    -
    -
    -// === goog.string.quote ===
    -function testQuote() {
    -  var str = allChars();
    -  assertEquals(str, eval(goog.string.quote(str)));
    -
    -  // empty string
    -  assertEquals('', eval(goog.string.quote('')));
    -
    -  // unicode
    -  str = allChars(0, 10000);
    -  assertEquals(str, eval(goog.string.quote(str)));
    -}
    -
    -function testQuoteSpecialChars() {
    -  assertEquals('"\\""', goog.string.quote('"'));
    -  assertEquals('"\'"', goog.string.quote("'"));
    -  assertEquals('"\\\\"', goog.string.quote('\\'));
    -
    -  var zeroQuoted = goog.string.quote('\0');
    -  assertTrue(
    -      'goog.string.quote mangles the 0 char: ',
    -      '"\\0"' == zeroQuoted || '"\\x00"' == zeroQuoted);
    -}
    -
    -function testCrossBrowserQuote() {
    -  // The vertical space char has weird semantics on jscript, so we don't test
    -  // that one.
    -  var vertChar = '\x0B'.charCodeAt(0);
    -
    -  // The zero char has two alternate encodings (\0 and \x00) both are ok,
    -  // and tested above.
    -  var zeroChar = 0;
    -
    -  var str = allChars(zeroChar + 1, vertChar) + allChars(vertChar + 1, 10000);
    -  var nativeQuote = goog.string.quote(str);
    -
    -  stubs.set(String.prototype, 'quote', null);
    -  assertNull(''.quote);
    -
    -  assertEquals(nativeQuote, goog.string.quote(str));
    -}
    -
    -function allChars(opt_start, opt_end) {
    -  opt_start = opt_start || 0;
    -  opt_end = opt_end || 256;
    -  var rv = '';
    -  for (var i = opt_start; i < opt_end; i++) {
    -    rv += String.fromCharCode(i);
    -  }
    -  return rv;
    -}
    -
    -function testEscapeString() {
    -  var expected = allChars(0, 10000);
    -  try {
    -    var actual =
    -        eval('"' + goog.string.escapeString(expected) + '"');
    -  } catch (e) {
    -    fail('Quote failed: err ' + e.message);
    -  }
    -  assertEquals(expected, actual);
    -}
    -
    -function testCountOf() {
    -  assertEquals(goog.string.countOf('REDSOXROX', undefined), 0);
    -  assertEquals(goog.string.countOf('REDSOXROX', null), 0);
    -  assertEquals(goog.string.countOf('REDSOXROX', ''), 0);
    -  assertEquals(goog.string.countOf('', undefined), 0);
    -  assertEquals(goog.string.countOf('', null), 0);
    -  assertEquals(goog.string.countOf('', ''), 0);
    -  assertEquals(goog.string.countOf('', 'REDSOXROX'), 0);
    -  assertEquals(goog.string.countOf(undefined, 'R'), 0);
    -  assertEquals(goog.string.countOf(null, 'R'), 0);
    -  assertEquals(goog.string.countOf(undefined, undefined), 0);
    -  assertEquals(goog.string.countOf(null, null), 0);
    -
    -  assertEquals(goog.string.countOf('REDSOXROX', 'R'), 2);
    -  assertEquals(goog.string.countOf('REDSOXROX', 'E'), 1);
    -  assertEquals(goog.string.countOf('REDSOXROX', 'X'), 2);
    -  assertEquals(goog.string.countOf('REDSOXROX', 'RED'), 1);
    -  assertEquals(goog.string.countOf('REDSOXROX', 'ROX'), 1);
    -  assertEquals(goog.string.countOf('REDSOXROX', 'OX'), 2);
    -  assertEquals(goog.string.countOf('REDSOXROX', 'Z'), 0);
    -  assertEquals(goog.string.countOf('REDSOXROX', 'REDSOXROX'), 1);
    -  assertEquals(goog.string.countOf('REDSOXROX', 'YANKEES'), 0);
    -  assertEquals(goog.string.countOf('REDSOXROX', 'EVIL_EMPIRE'), 0);
    -
    -  assertEquals(goog.string.countOf('RRRRRRRRR', 'R'), 9);
    -  assertEquals(goog.string.countOf('RRRRRRRRR', 'RR'), 4);
    -  assertEquals(goog.string.countOf('RRRRRRRRR', 'RRR'), 3);
    -  assertEquals(goog.string.countOf('RRRRRRRRR', 'RRRR'), 2);
    -  assertEquals(goog.string.countOf('RRRRRRRRR', 'RRRRR'), 1);
    -  assertEquals(goog.string.countOf('RRRRRRRRR', 'RRRRRR'), 1);
    -}
    -
    -function testRemoveAt() {
    -  var str = 'barfoobarbazbar';
    -  str = goog.string.removeAt(str, 0, 3);
    -  assertEquals('Remove first bar', 'foobarbazbar', str);
    -  str = goog.string.removeAt(str, 3, 3);
    -  assertEquals('Remove middle bar', 'foobazbar', str);
    -  str = goog.string.removeAt(str, 6, 3);
    -  assertEquals('Remove last bar', 'foobaz', str);
    -  assertEquals('Invalid negative index', 'foobaz',
    -      goog.string.removeAt(str, -1, 0));
    -  assertEquals('Invalid overflow index', 'foobaz',
    -      goog.string.removeAt(str, 9, 0));
    -  assertEquals('Invalid negative stringLength', 'foobaz',
    -      goog.string.removeAt(str, 0, -1));
    -  assertEquals('Invalid overflow stringLength', '',
    -      goog.string.removeAt(str, 0, 9));
    -  assertEquals('Invalid overflow index and stringLength', 'foobaz',
    -      goog.string.removeAt(str, 9, 9));
    -  assertEquals('Invalid zero stringLength', 'foobaz',
    -      goog.string.removeAt(str, 0, 0));
    -}
    -
    -function testRemove() {
    -  var str = 'barfoobarbazbar';
    -  str = goog.string.remove(str, 'bar');
    -  assertEquals('Remove first bar', 'foobarbazbar', str);
    -  str = goog.string.remove(str, 'bar');
    -  assertEquals('Remove middle bar', 'foobazbar', str);
    -  str = goog.string.remove(str, 'bar');
    -  assertEquals('Remove last bar', 'foobaz', str);
    -  str = goog.string.remove(str, 'bar');
    -  assertEquals('Original string', 'foobaz', str);
    -}
    -
    -function testRemoveAll() {
    -  var str = 'foobarbazbarfoobazfoo';
    -  str = goog.string.removeAll(str, 'foo');
    -  assertEquals('Remove all occurrences of foo', 'barbazbarbaz', str);
    -  str = goog.string.removeAll(str, 'foo');
    -  assertEquals('Original string', 'barbazbarbaz', str);
    -}
    -
    -function testRegExpEscape() {
    -  var spec = '()[]{}+-?*.$^|,:#<!\\';
    -  var escapedSpec = '\\' + spec.split('').join('\\');
    -  assertEquals('special chars', escapedSpec, goog.string.regExpEscape(spec));
    -  assertEquals('backslash b', '\\x08', goog.string.regExpEscape('\b'));
    -
    -  var s = allChars();
    -  var re = new RegExp('^' + goog.string.regExpEscape(s) + '$');
    -  assertTrue('All ASCII', re.test(s));
    -  s = '';
    -  var re = new RegExp('^' + goog.string.regExpEscape(s) + '$');
    -  assertTrue('empty string', re.test(s));
    -  s = allChars(0, 10000);
    -  var re = new RegExp('^' + goog.string.regExpEscape(s) + '$');
    -  assertTrue('Unicode', re.test(s));
    -}
    -
    -function testPadNumber() {
    -  assertEquals('01.250', goog.string.padNumber(1.25, 2, 3));
    -  assertEquals('01.25', goog.string.padNumber(1.25, 2));
    -  assertEquals('01.3', goog.string.padNumber(1.25, 2, 1));
    -  assertEquals('1.25', goog.string.padNumber(1.25, 0));
    -  assertEquals('10', goog.string.padNumber(9.9, 2, 0));
    -  assertEquals('7', goog.string.padNumber(7, 0));
    -  assertEquals('7', goog.string.padNumber(7, 1));
    -  assertEquals('07', goog.string.padNumber(7, 2));
    -}
    -
    -function testAsString() {
    -  assertEquals('', goog.string.makeSafe(null));
    -  assertEquals('', goog.string.makeSafe(undefined));
    -  assertEquals('', goog.string.makeSafe(''));
    -
    -  assertEquals('abc', goog.string.makeSafe('abc'));
    -  assertEquals('123', goog.string.makeSafe(123));
    -  assertEquals('0', goog.string.makeSafe(0));
    -
    -  assertEquals('true', goog.string.makeSafe(true));
    -  assertEquals('false', goog.string.makeSafe(false));
    -
    -  var funky = function() {};
    -  funky.toString = function() { return 'funky-thing' };
    -  assertEquals('funky-thing', goog.string.makeSafe(funky));
    -}
    -
    -function testStringRepeat() {
    -  assertEquals('', goog.string.repeat('*', 0));
    -  assertEquals('*', goog.string.repeat('*', 1));
    -  assertEquals('     ', goog.string.repeat(' ', 5));
    -  assertEquals('__________', goog.string.repeat('_', 10));
    -  assertEquals('aaa', goog.string.repeat('a', 3));
    -  assertEquals('foofoofoofoofoofoo', goog.string.repeat('foo', 6));
    -}
    -
    -function testBuildString() {
    -  assertEquals('', goog.string.buildString());
    -  assertEquals('a', goog.string.buildString('a'));
    -  assertEquals('ab', goog.string.buildString('ab'));
    -  assertEquals('ab', goog.string.buildString('a', 'b'));
    -  assertEquals('abcd', goog.string.buildString('a', 'b', 'c', 'd'));
    -  assertEquals('0', goog.string.buildString(0));
    -  assertEquals('0123', goog.string.buildString(0, 1, 2, 3));
    -  assertEquals('ab01', goog.string.buildString('a', 'b', 0, 1));
    -  assertEquals('', goog.string.buildString(null, undefined));
    -}
    -
    -function testCompareVersions() {
    -  var f = goog.string.compareVersions;
    -  assertTrue('numeric equality broken', f(1, 1) == 0);
    -  assertTrue('numeric less than broken', f(1.0, 1.1) < 0);
    -  assertTrue('numeric greater than broken', f(2.0, 1.1) > 0);
    -
    -  assertTrue('exact equality broken', f('1.0', '1.0') == 0);
    -  assertTrue('mutlidot equality broken', f('1.0.0.0', '1.0') == 0);
    -  assertTrue('mutlidigit equality broken', f('1.000', '1.0') == 0);
    -  assertTrue('less than broken', f('1.0.2.1', '1.1') < 0);
    -  assertTrue('greater than broken', f('1.1', '1.0.2.1') > 0);
    -
    -  assertTrue('substring less than broken', f('1', '1.1') < 0);
    -  assertTrue('substring greater than broken', f('2.2', '2') > 0);
    -
    -  assertTrue('b greater than broken', f('1.1', '1.1b') > 0);
    -  assertTrue('b less than broken', f('1.1b', '1.1') < 0);
    -  assertTrue('b equality broken', f('1.1b', '1.1b') == 0);
    -
    -  assertTrue('b > a broken', f('1.1b', '1.1a') > 0);
    -  assertTrue('a < b broken', f('1.1a', '1.1b') < 0);
    -
    -  assertTrue('9.5 < 9.10 broken', f('9.5', '9.10') < 0);
    -  assertTrue('9.5 < 9.11 broken', f('9.5', '9.11') < 0);
    -  assertTrue('9.11 > 9.10 broken', f('9.11', '9.10') > 0);
    -  assertTrue('9.1 < 9.10 broken', f('9.1', '9.10') < 0);
    -  assertTrue('9.1.1 < 9.10 broken', f('9.1.1', '9.10') < 0);
    -  assertTrue('9.1.1 < 9.11 broken', f('9.1.1', '9.11') < 0);
    -
    -  assertTrue('10a > 9b broken', f('1.10a', '1.9b') > 0);
    -  assertTrue('b < b2 broken', f('1.1b', '1.1b2') < 0);
    -  assertTrue('b10 > b9 broken', f('1.1b10', '1.1b9') > 0);
    -
    -  assertTrue('7 > 6 broken with leading whitespace', f(' 7', '6') > 0);
    -  assertTrue('7 > 6 broken with trailing whitespace', f('7 ', '6') > 0);
    -}
    -
    -function testIsUnicodeChar() {
    -  assertFalse('empty string broken', goog.string.isUnicodeChar(''));
    -  assertFalse('non-single char string broken',
    -              goog.string.isUnicodeChar('abc'));
    -  assertTrue('space broken', goog.string.isUnicodeChar(' '));
    -  assertTrue('single char broken', goog.string.isUnicodeChar('a'));
    -  assertTrue('upper case broken', goog.string.isUnicodeChar('A'));
    -  assertTrue('unicode char broken', goog.string.isUnicodeChar('\u0C07'));
    -}
    -
    -function assertHashcodeEquals(expectedHashCode, str) {
    -  assertEquals('wrong hashCode for ' + str.substring(0, 32),
    -      expectedHashCode, goog.string.hashCode(str));
    -}
    -
    -
    -/**
    - * Verify we get random-ish looking values for hash of Strings.
    - */
    -function testHashCode() {
    -  try {
    -    goog.string.hashCode(null);
    -    fail('should throw exception for null');
    -  } catch (ex) {
    -    // success
    -  }
    -  assertHashcodeEquals(0, '');
    -  assertHashcodeEquals(101574, 'foo');
    -  assertHashcodeEquals(1301670364, '\uAAAAfoo');
    -  assertHashcodeEquals(92567585, goog.string.repeat('a', 5));
    -  assertHashcodeEquals(2869595232, goog.string.repeat('a', 6));
    -  assertHashcodeEquals(3058106369, goog.string.repeat('a', 7));
    -  assertHashcodeEquals(312017024, goog.string.repeat('a', 8));
    -  assertHashcodeEquals(2929737728, goog.string.repeat('a', 1024));
    -}
    -
    -function testUniqueString() {
    -  var TEST_COUNT = 20;
    -
    -  var obj = {};
    -  for (var i = 0; i < TEST_COUNT; i++) {
    -    obj[goog.string.createUniqueString()] = true;
    -  }
    -
    -  assertEquals('All strings should be unique.', TEST_COUNT,
    -      goog.object.getCount(obj));
    -}
    -
    -function testToNumber() {
    -  // First, test the cases goog.string.toNumber() was primarily written for,
    -  // because JS built-ins are dumb.
    -  assertNaN(goog.string.toNumber('123a'));
    -  assertNaN(goog.string.toNumber('123.456.78'));
    -  assertNaN(goog.string.toNumber(''));
    -  assertNaN(goog.string.toNumber(' '));
    -
    -  // Now, sanity-check.
    -  assertEquals(123, goog.string.toNumber(' 123 '));
    -  assertEquals(321.123, goog.string.toNumber('321.123'));
    -  assertEquals(1.00001, goog.string.toNumber('1.00001'));
    -  assertEquals(1, goog.string.toNumber('1.00000'));
    -  assertEquals(0.2, goog.string.toNumber('0.20'));
    -  assertEquals(0, goog.string.toNumber('0'));
    -  assertEquals(0, goog.string.toNumber('0.0'));
    -  assertEquals(-1, goog.string.toNumber('-1'));
    -  assertEquals(-0.3, goog.string.toNumber('-.3'));
    -  assertEquals(-12.345, goog.string.toNumber('-12.345'));
    -  assertEquals(100, goog.string.toNumber('1e2'));
    -  assertEquals(0.123, goog.string.toNumber('12.3e-2'));
    -  assertNaN(goog.string.toNumber('abc'));
    -}
    -
    -function testGetRandomString() {
    -  stubs.set(goog, 'now', goog.functions.constant(1295726605874));
    -  stubs.set(Math, 'random', goog.functions.constant(0.6679361383522245));
    -  assertTrue('String must be alphanumeric',
    -             goog.string.isAlphaNumeric(goog.string.getRandomString()));
    -}
    -
    -function testToCamelCase() {
    -  assertEquals('OneTwoThree', goog.string.toCamelCase('-one-two-three'));
    -  assertEquals('oneTwoThree', goog.string.toCamelCase('one-two-three'));
    -  assertEquals('oneTwo', goog.string.toCamelCase('one-two'));
    -  assertEquals('one', goog.string.toCamelCase('one'));
    -  assertEquals('oneTwo', goog.string.toCamelCase('oneTwo'));
    -  assertEquals('String value matching a native function name.',
    -      'toString', goog.string.toCamelCase('toString'));
    -}
    -
    -function testToSelectorCase() {
    -  assertEquals('-one-two-three', goog.string.toSelectorCase('OneTwoThree'));
    -  assertEquals('one-two-three', goog.string.toSelectorCase('oneTwoThree'));
    -  assertEquals('one-two', goog.string.toSelectorCase('oneTwo'));
    -  assertEquals('one', goog.string.toSelectorCase('one'));
    -  assertEquals('one-two', goog.string.toSelectorCase('one-two'));
    -  assertEquals('String value matching a native function name.',
    -      'to-string', goog.string.toSelectorCase('toString'));
    -}
    -
    -function testToTitleCase() {
    -  assertEquals('One', goog.string.toTitleCase('one'));
    -  assertEquals('CamelCase', goog.string.toTitleCase('camelCase'));
    -  assertEquals('Onelongword', goog.string.toTitleCase('onelongword'));
    -  assertEquals('One Two Three', goog.string.toTitleCase('one two three'));
    -  assertEquals('One        Two    Three',
    -      goog.string.toTitleCase('one        two    three'));
    -  assertEquals('   Longword  ', goog.string.toTitleCase('   longword  '));
    -  assertEquals('One-two-three', goog.string.toTitleCase('one-two-three'));
    -  assertEquals('One_two_three', goog.string.toTitleCase('one_two_three'));
    -  assertEquals('String value matching a native function name.',
    -      'ToString', goog.string.toTitleCase('toString'));
    -
    -  // Verify results with no delimiter.
    -  assertEquals('One two three', goog.string.toTitleCase('one two three', ''));
    -  assertEquals('One-two-three', goog.string.toTitleCase('one-two-three', ''));
    -  assertEquals(' onetwothree', goog.string.toTitleCase(' onetwothree', ''));
    -
    -  // Verify results with one delimiter.
    -  assertEquals('One two', goog.string.toTitleCase('one two', '.'));
    -  assertEquals(' one two', goog.string.toTitleCase(' one two', '.'));
    -  assertEquals(' one.Two', goog.string.toTitleCase(' one.two', '.'));
    -  assertEquals('One.Two', goog.string.toTitleCase('one.two', '.'));
    -  assertEquals('One...Two...', goog.string.toTitleCase('one...two...', '.'));
    -
    -  // Verify results with multiple delimiters.
    -  var delimiters = '_-.';
    -  assertEquals('One two three',
    -      goog.string.toTitleCase('one two three', delimiters));
    -  assertEquals('  one two three',
    -      goog.string.toTitleCase('  one two three', delimiters));
    -  assertEquals('One-Two-Three',
    -      goog.string.toTitleCase('one-two-three', delimiters));
    -  assertEquals('One_Two_Three',
    -      goog.string.toTitleCase('one_two_three', delimiters));
    -  assertEquals('One...Two...Three',
    -      goog.string.toTitleCase('one...two...three', delimiters));
    -  assertEquals('One.  two.  three',
    -      goog.string.toTitleCase('one.  two.  three', delimiters));
    -}
    -
    -function testCapitalize() {
    -  assertEquals('Reptar', goog.string.capitalize('reptar'));
    -  assertEquals('Reptar reptar', goog.string.capitalize('reptar reptar'));
    -  assertEquals('Reptar', goog.string.capitalize('REPTAR'));
    -  assertEquals('Reptar', goog.string.capitalize('Reptar'));
    -  assertEquals('1234', goog.string.capitalize('1234'));
    -  assertEquals('$#@!', goog.string.capitalize('$#@!'));
    -  assertEquals('', goog.string.capitalize(''));
    -  assertEquals('R', goog.string.capitalize('r'));
    -  assertEquals('R', goog.string.capitalize('R'));
    -}
    -
    -function testParseInt() {
    -  // Many example values borrowed from
    -  // http://trac.webkit.org/browser/trunk/LayoutTests/fast/js/kde/
    -  // GlobalObject-expected.txt
    -
    -  // Check non-numbers and strings
    -  assertTrue(isNaN(goog.string.parseInt(undefined)));
    -  assertTrue(isNaN(goog.string.parseInt(null)));
    -  assertTrue(isNaN(goog.string.parseInt({})));
    -
    -  assertTrue(isNaN(goog.string.parseInt('')));
    -  assertTrue(isNaN(goog.string.parseInt(' ')));
    -  assertTrue(isNaN(goog.string.parseInt('a')));
    -  assertTrue(isNaN(goog.string.parseInt('FFAA')));
    -  assertEquals(1, goog.string.parseInt(1));
    -  assertEquals(1234567890123456, goog.string.parseInt(1234567890123456));
    -  assertEquals(2, goog.string.parseInt(' 2.3'));
    -  assertEquals(16, goog.string.parseInt('0x10'));
    -  assertEquals(11, goog.string.parseInt('11'));
    -  assertEquals(15, goog.string.parseInt('0xF'));
    -  assertEquals(15, goog.string.parseInt('0XF'));
    -  assertEquals(3735928559, goog.string.parseInt('0XDEADBEEF'));
    -  assertEquals(3, goog.string.parseInt('3x'));
    -  assertEquals(3, goog.string.parseInt('3 x'));
    -  assertFalse(isFinite(goog.string.parseInt('Infinity')));
    -  assertEquals(15, goog.string.parseInt('15'));
    -  assertEquals(15, goog.string.parseInt('015'));
    -  assertEquals(15, goog.string.parseInt('0xf'));
    -  assertEquals(15, goog.string.parseInt('15'));
    -  assertEquals(15, goog.string.parseInt('0xF'));
    -  assertEquals(15, goog.string.parseInt('15.99'));
    -  assertTrue(isNaN(goog.string.parseInt('FXX123')));
    -  assertEquals(15, goog.string.parseInt('15*3'));
    -  assertEquals(7, goog.string.parseInt('0x7'));
    -  assertEquals(1, goog.string.parseInt('1x7'));
    -
    -  // Strings have no special meaning
    -  assertTrue(isNaN(goog.string.parseInt('Infinity')));
    -  assertTrue(isNaN(goog.string.parseInt('NaN')));
    -
    -  // Test numbers and values
    -  assertEquals(3, goog.string.parseInt(3.3));
    -  assertEquals(-3, goog.string.parseInt(-3.3));
    -  assertEquals(0, goog.string.parseInt(-0));
    -  assertTrue(isNaN(goog.string.parseInt(Infinity)));
    -  assertTrue(isNaN(goog.string.parseInt(NaN)));
    -  assertTrue(isNaN(goog.string.parseInt(Number.POSITIVE_INFINITY)));
    -  assertTrue(isNaN(goog.string.parseInt(Number.NEGATIVE_INFINITY)));
    -
    -  // In Chrome (at least), parseInt(Number.MIN_VALUE) is 5 (5e-324) and
    -  // parseInt(Number.MAX_VALUE) is 1 (1.79...e+308) as they are converted
    -  // to strings.  We do not attempt to correct this behavior.
    -
    -  // Additional values for negatives.
    -  assertEquals(-3, goog.string.parseInt('-3'));
    -  assertEquals(-32, goog.string.parseInt('-32    '));
    -  assertEquals(-32, goog.string.parseInt(' -32 '));
    -  assertEquals(-3, goog.string.parseInt('-0x3'));
    -  assertEquals(-50, goog.string.parseInt('-0x32    '));
    -  assertEquals(-243, goog.string.parseInt('   -0xF3    '));
    -  assertTrue(isNaN(goog.string.parseInt(' - 0x32 ')));
    -}
    -
    -function testIsLowerCamelCase() {
    -  assertTrue(goog.string.isLowerCamelCase('foo'));
    -  assertTrue(goog.string.isLowerCamelCase('fooBar'));
    -  assertTrue(goog.string.isLowerCamelCase('fooBarBaz'));
    -  assertTrue(goog.string.isLowerCamelCase('innerHTML'));
    -
    -  assertFalse(goog.string.isLowerCamelCase(''));
    -  assertFalse(goog.string.isLowerCamelCase('a3a'));
    -  assertFalse(goog.string.isLowerCamelCase('goog.dom'));
    -  assertFalse(goog.string.isLowerCamelCase('Foo'));
    -  assertFalse(goog.string.isLowerCamelCase('FooBar'));
    -  assertFalse(goog.string.isLowerCamelCase('ABCBBD'));
    -}
    -
    -function testIsUpperCamelCase() {
    -  assertFalse(goog.string.isUpperCamelCase(''));
    -  assertFalse(goog.string.isUpperCamelCase('foo'));
    -  assertFalse(goog.string.isUpperCamelCase('fooBar'));
    -  assertFalse(goog.string.isUpperCamelCase('fooBarBaz'));
    -  assertFalse(goog.string.isUpperCamelCase('innerHTML'));
    -  assertFalse(goog.string.isUpperCamelCase('a3a'));
    -  assertFalse(goog.string.isUpperCamelCase('goog.dom'));
    -  assertFalse(goog.string.isUpperCamelCase('Boyz2Men'));
    -
    -  assertTrue(goog.string.isUpperCamelCase('ABCBBD'));
    -  assertTrue(goog.string.isUpperCamelCase('Foo'));
    -  assertTrue(goog.string.isUpperCamelCase('FooBar'));
    -  assertTrue(goog.string.isUpperCamelCase('FooBarBaz'));
    -}
    -
    -function testSplitLimit() {
    -  assertArrayEquals(['a*a*a*a'], goog.string.splitLimit('a*a*a*a', '*', -1));
    -  assertArrayEquals(['a*a*a*a'], goog.string.splitLimit('a*a*a*a', '*', 0));
    -  assertArrayEquals(['a', 'a*a*a'], goog.string.splitLimit('a*a*a*a', '*', 1));
    -  assertArrayEquals(['a', 'a', 'a*a'],
    -                    goog.string.splitLimit('a*a*a*a', '*', 2));
    -  assertArrayEquals(['a', 'a', 'a', 'a'],
    -                    goog.string.splitLimit('a*a*a*a', '*', 3));
    -  assertArrayEquals(['a', 'a', 'a', 'a'],
    -                    goog.string.splitLimit('a*a*a*a', '*', 4));
    -
    -  assertArrayEquals(['bbbbbbbbbbbb'],
    -                    goog.string.splitLimit('bbbbbbbbbbbb', 'a', 10));
    -  assertArrayEquals(['babab', 'bab', 'abb'],
    -                    goog.string.splitLimit('bababaababaaabb', 'aa', 10));
    -  assertArrayEquals(['babab', 'babaaabb'],
    -                    goog.string.splitLimit('bababaababaaabb', 'aa', 1));
    -  assertArrayEquals(
    -      ['b', 'a', 'b', 'a', 'b', 'a', 'a', 'b', 'a', 'b', 'aaabb'],
    -      goog.string.splitLimit('bababaababaaabb', '', 10));
    -}
    -
    -function testContains() {
    -  assertTrue(goog.string.contains('moot', 'moo'));
    -  assertFalse(goog.string.contains('moo', 'moot'));
    -  assertFalse(goog.string.contains('Moot', 'moo'));
    -  assertTrue(goog.string.contains('moo', 'moo'));
    -}
    -
    -function testCaseInsensitiveContains() {
    -  assertTrue(goog.string.caseInsensitiveContains('moot', 'moo'));
    -  assertFalse(goog.string.caseInsensitiveContains('moo', 'moot'));
    -  assertTrue(goog.string.caseInsensitiveContains('Moot', 'moo'));
    -  assertTrue(goog.string.caseInsensitiveContains('moo', 'moo'));
    -}
    -
    -function testEditDistance() {
    -  assertEquals('Empty string should match to length of other string', 4,
    -      goog.string.editDistance('goat', ''));
    -  assertEquals('Empty string should match to length of other string', 4,
    -      goog.string.editDistance('', 'moat'));
    -
    -  assertEquals('Equal strings should have zero edit distance', 0,
    -      goog.string.editDistance('abcd', 'abcd'));
    -  assertEquals('Equal strings should have zero edit distance', 0,
    -      goog.string.editDistance('', ''));
    -
    -  assertEquals('Edit distance for adding characters incorrect', 4,
    -      goog.string.editDistance('bdf', 'abcdefg'));
    -  assertEquals('Edit distance for removing characters incorrect', 4,
    -      goog.string.editDistance('abcdefg', 'bdf'));
    -
    -  assertEquals('Edit distance for substituting characters incorrect', 4,
    -      goog.string.editDistance('adef', 'ghij'));
    -  assertEquals('Edit distance for substituting characters incorrect', 1,
    -      goog.string.editDistance('goat', 'boat'));
    -
    -  assertEquals('Substitution should be preferred over insert/delete', 4,
    -      goog.string.editDistance('abcd', 'defg'));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/string/stringbuffer.js b/src/database/third_party/closure-library/closure/goog/string/stringbuffer.js
    deleted file mode 100644
    index f4b3a871e24..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/string/stringbuffer.js
    +++ /dev/null
    @@ -1,103 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Utility for fast string concatenation.
    - */
    -
    -goog.provide('goog.string.StringBuffer');
    -
    -
    -
    -/**
    - * Utility class to facilitate string concatenation.
    - *
    - * @param {*=} opt_a1 Optional first initial item to append.
    - * @param {...*} var_args Other initial items to
    - *     append, e.g., new goog.string.StringBuffer('foo', 'bar').
    - * @constructor
    - */
    -goog.string.StringBuffer = function(opt_a1, var_args) {
    -  if (opt_a1 != null) {
    -    this.append.apply(this, arguments);
    -  }
    -};
    -
    -
    -/**
    - * Internal buffer for the string to be concatenated.
    - * @type {string}
    - * @private
    - */
    -goog.string.StringBuffer.prototype.buffer_ = '';
    -
    -
    -/**
    - * Sets the contents of the string buffer object, replacing what's currently
    - * there.
    - *
    - * @param {*} s String to set.
    - */
    -goog.string.StringBuffer.prototype.set = function(s) {
    -  this.buffer_ = '' + s;
    -};
    -
    -
    -/**
    - * Appends one or more items to the buffer.
    - *
    - * Calling this with null, undefined, or empty arguments is an error.
    - *
    - * @param {*} a1 Required first string.
    - * @param {*=} opt_a2 Optional second string.
    - * @param {...*} var_args Other items to append,
    - *     e.g., sb.append('foo', 'bar', 'baz').
    - * @return {!goog.string.StringBuffer} This same StringBuffer object.
    - * @suppress {duplicate}
    - */
    -goog.string.StringBuffer.prototype.append = function(a1, opt_a2, var_args) {
    -  // Use a1 directly to avoid arguments instantiation for single-arg case.
    -  this.buffer_ += a1;
    -  if (opt_a2 != null) { // second argument is undefined (null == undefined)
    -    for (var i = 1; i < arguments.length; i++) {
    -      this.buffer_ += arguments[i];
    -    }
    -  }
    -  return this;
    -};
    -
    -
    -/**
    - * Clears the internal buffer.
    - */
    -goog.string.StringBuffer.prototype.clear = function() {
    -  this.buffer_ = '';
    -};
    -
    -
    -/**
    - * @return {number} the length of the current contents of the buffer.
    - */
    -goog.string.StringBuffer.prototype.getLength = function() {
    -  return this.buffer_.length;
    -};
    -
    -
    -/**
    - * @return {string} The concatenated string.
    - * @override
    - */
    -goog.string.StringBuffer.prototype.toString = function() {
    -  return this.buffer_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/string/stringbuffer_test.html b/src/database/third_party/closure-library/closure/goog/string/stringbuffer_test.html
    deleted file mode 100644
    index 01ff24a75bb..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/string/stringbuffer_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.string.StringBuffer
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.string.StringBufferTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/string/stringbuffer_test.js b/src/database/third_party/closure-library/closure/goog/string/stringbuffer_test.js
    deleted file mode 100644
    index 73cb440a98e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/string/stringbuffer_test.js
    +++ /dev/null
    @@ -1,97 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.string.StringBufferTest');
    -goog.setTestOnly('goog.string.StringBufferTest');
    -
    -goog.require('goog.string.StringBuffer');
    -goog.require('goog.testing.jsunit');
    -
    -function testStringBuffer() {
    -  var sb = new goog.string.StringBuffer();
    -  sb.append('Four score');
    -  sb.append(' ');
    -  sb.append('and seven years ago.');
    -  assertEquals('Test 1', 'Four score and seven years ago.', sb.toString());
    -
    -  sb.clear();
    -  assertEquals('Test 2', '', sb.toString());
    -
    -  sb = new goog.string.StringBuffer('Four score ');
    -  sb.append('and seven years ago.');
    -  assertEquals('Test 3', 'Four score and seven years ago.', sb.toString());
    -
    -  // can pass in non-Strings?
    -  sb = new goog.string.StringBuffer(1);
    -  sb.append(2);
    -  assertEquals('Test 4', '12', sb.toString());
    -}
    -
    -
    -function testStringBufferSet() {
    -  var sb = new goog.string.StringBuffer('foo');
    -  sb.set('bar');
    -  assertEquals('Test 1', 'bar', sb.toString());
    -}
    -
    -
    -function testStringBufferMultiAppend() {
    -  var sb = new goog.string.StringBuffer('hey', 'foo');
    -  sb.append('bar', 'baz');
    -  assertEquals('Test 1', 'heyfoobarbaz', sb.toString());
    -
    -  sb = new goog.string.StringBuffer();
    -  sb.append(1, 2);
    -  // should not add up to '3'
    -  assertEquals('Test 2', '12', sb.toString());
    -}
    -
    -
    -function testStringBufferToString() {
    -  var sb = new goog.string.StringBuffer('foo', 'bar');
    -  assertEquals('Test 1', 'foobar', sb.toString());
    -}
    -
    -
    -function testStringBufferWithFalseFirstArgument() {
    -  var sb = new goog.string.StringBuffer(0, 'more');
    -  assertEquals('Test 1', '0more', sb.toString());
    -
    -  sb = new goog.string.StringBuffer(false, 'more');
    -  assertEquals('Test 2', 'falsemore', sb.toString());
    -
    -  sb = new goog.string.StringBuffer('', 'more');
    -  assertEquals('Test 3', 'more', sb.toString());
    -
    -  sb = new goog.string.StringBuffer(null, 'more');
    -  assertEquals('Test 4', '', sb.toString());
    -
    -  sb = new goog.string.StringBuffer(undefined, 'more');
    -  assertEquals('Test 5', '', sb.toString());
    -}
    -
    -
    -function testStringBufferGetLength() {
    -  var sb = new goog.string.StringBuffer();
    -  assertEquals(0, sb.getLength());
    -
    -  sb.append('foo');
    -  assertEquals(3, sb.getLength());
    -
    -  sb.append('baroo');
    -  assertEquals(8, sb.getLength());
    -
    -  sb.clear();
    -  assertEquals(0, sb.getLength());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/string/stringformat.js b/src/database/third_party/closure-library/closure/goog/string/stringformat.js
    deleted file mode 100644
    index 99d66fc3898..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/string/stringformat.js
    +++ /dev/null
    @@ -1,250 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Implementation of sprintf-like, python-%-operator-like,
    - * .NET-String.Format-like functionality. Uses JS string's replace method to
    - * extract format specifiers and sends those specifiers to a handler function,
    - * which then, based on conversion type part of the specifier, calls the
    - * appropriate function to handle the specific conversion.
    - * For specific functionality implemented, look at formatRe below, or look
    - * at the tests.
    - */
    -
    -goog.provide('goog.string.format');
    -
    -goog.require('goog.string');
    -
    -
    -/**
    - * Performs sprintf-like conversion, ie. puts the values in a template.
    - * DO NOT use it instead of built-in conversions in simple cases such as
    - * 'Cost: %.2f' as it would introduce unneccessary latency oposed to
    - * 'Cost: ' + cost.toFixed(2).
    - * @param {string} formatString Template string containing % specifiers.
    - * @param {...string|number} var_args Values formatString is to be filled with.
    - * @return {string} Formatted string.
    - */
    -goog.string.format = function(formatString, var_args) {
    -
    -  // Convert the arguments to an array (MDC recommended way).
    -  var args = Array.prototype.slice.call(arguments);
    -
    -  // Try to get the template.
    -  var template = args.shift();
    -  if (typeof template == 'undefined') {
    -    throw Error('[goog.string.format] Template required');
    -  }
    -
    -  // This re is used for matching, it also defines what is supported.
    -  var formatRe = /%([0\-\ \+]*)(\d+)?(\.(\d+))?([%sfdiu])/g;
    -
    -  /**
    -   * Chooses which conversion function to call based on type conversion
    -   * specifier.
    -   * @param {string} match Contains the re matched string.
    -   * @param {string} flags Formatting flags.
    -   * @param {string} width Replacement string minimum width.
    -   * @param {string} dotp Matched precision including a dot.
    -   * @param {string} precision Specifies floating point precision.
    -   * @param {string} type Type conversion specifier.
    -   * @param {string} offset Matching location in the original string.
    -   * @param {string} wholeString Has the actualString being searched.
    -   * @return {string} Formatted parameter.
    -   */
    -  function replacerDemuxer(match,
    -                           flags,
    -                           width,
    -                           dotp,
    -                           precision,
    -                           type,
    -                           offset,
    -                           wholeString) {
    -
    -    // The % is too simple and doesn't take an argument.
    -    if (type == '%') {
    -      return '%';
    -    }
    -
    -    // Try to get the actual value from parent function.
    -    var value = args.shift();
    -
    -    // If we didn't get any arguments, fail.
    -    if (typeof value == 'undefined') {
    -      throw Error('[goog.string.format] Not enough arguments');
    -    }
    -
    -    // Patch the value argument to the beginning of our type specific call.
    -    arguments[0] = value;
    -
    -    return goog.string.format.demuxes_[type].apply(null, arguments);
    -
    -  }
    -
    -  return template.replace(formatRe, replacerDemuxer);
    -};
    -
    -
    -/**
    - * Contains various conversion functions (to be filled in later on).
    - * @type {Object}
    - * @private
    - */
    -goog.string.format.demuxes_ = {};
    -
    -
    -/**
    - * Processes %s conversion specifier.
    - * @param {string} value Contains the formatRe matched string.
    - * @param {string} flags Formatting flags.
    - * @param {string} width Replacement string minimum width.
    - * @param {string} dotp Matched precision including a dot.
    - * @param {string} precision Specifies floating point precision.
    - * @param {string} type Type conversion specifier.
    - * @param {string} offset Matching location in the original string.
    - * @param {string} wholeString Has the actualString being searched.
    - * @return {string} Replacement string.
    - */
    -goog.string.format.demuxes_['s'] = function(value,
    -                                            flags,
    -                                            width,
    -                                            dotp,
    -                                            precision,
    -                                            type,
    -                                            offset,
    -                                            wholeString) {
    -  var replacement = value;
    -  // If no padding is necessary we're done.
    -  // The check for '' is necessary because Firefox incorrectly provides the
    -  // empty string instead of undefined for non-participating capture groups,
    -  // and isNaN('') == false.
    -  if (isNaN(width) || width == '' || replacement.length >= width) {
    -    return replacement;
    -  }
    -
    -  // Otherwise we should find out where to put spaces.
    -  if (flags.indexOf('-', 0) > -1) {
    -    replacement =
    -        replacement + goog.string.repeat(' ', width - replacement.length);
    -  } else {
    -    replacement =
    -        goog.string.repeat(' ', width - replacement.length) + replacement;
    -  }
    -  return replacement;
    -};
    -
    -
    -/**
    - * Processes %f conversion specifier.
    - * @param {string} value Contains the formatRe matched string.
    - * @param {string} flags Formatting flags.
    - * @param {string} width Replacement string minimum width.
    - * @param {string} dotp Matched precision including a dot.
    - * @param {string} precision Specifies floating point precision.
    - * @param {string} type Type conversion specifier.
    - * @param {string} offset Matching location in the original string.
    - * @param {string} wholeString Has the actualString being searched.
    - * @return {string} Replacement string.
    - */
    -goog.string.format.demuxes_['f'] = function(value,
    -                                            flags,
    -                                            width,
    -                                            dotp,
    -                                            precision,
    -                                            type,
    -                                            offset,
    -                                            wholeString) {
    -
    -  var replacement = value.toString();
    -
    -  // The check for '' is necessary because Firefox incorrectly provides the
    -  // empty string instead of undefined for non-participating capture groups,
    -  // and isNaN('') == false.
    -  if (!(isNaN(precision) || precision == '')) {
    -    replacement = parseFloat(value).toFixed(precision);
    -  }
    -
    -  // Generates sign string that will be attached to the replacement.
    -  var sign;
    -  if (value < 0) {
    -    sign = '-';
    -  } else if (flags.indexOf('+') >= 0) {
    -    sign = '+';
    -  } else if (flags.indexOf(' ') >= 0) {
    -    sign = ' ';
    -  } else {
    -    sign = '';
    -  }
    -
    -  if (value >= 0) {
    -    replacement = sign + replacement;
    -  }
    -
    -  // If no padding is neccessary we're done.
    -  if (isNaN(width) || replacement.length >= width) {
    -    return replacement;
    -  }
    -
    -  // We need a clean signless replacement to start with
    -  replacement = isNaN(precision) ?
    -      Math.abs(value).toString() :
    -      Math.abs(value).toFixed(precision);
    -
    -  var padCount = width - replacement.length - sign.length;
    -
    -  // Find out which side to pad, and if it's left side, then which character to
    -  // pad, and set the sign on the left and padding in the middle.
    -  if (flags.indexOf('-', 0) >= 0) {
    -    replacement = sign + replacement + goog.string.repeat(' ', padCount);
    -  } else {
    -    // Decides which character to pad.
    -    var paddingChar = (flags.indexOf('0', 0) >= 0) ? '0' : ' ';
    -    replacement =
    -        sign + goog.string.repeat(paddingChar, padCount) + replacement;
    -  }
    -
    -  return replacement;
    -};
    -
    -
    -/**
    - * Processes %d conversion specifier.
    - * @param {string} value Contains the formatRe matched string.
    - * @param {string} flags Formatting flags.
    - * @param {string} width Replacement string minimum width.
    - * @param {string} dotp Matched precision including a dot.
    - * @param {string} precision Specifies floating point precision.
    - * @param {string} type Type conversion specifier.
    - * @param {string} offset Matching location in the original string.
    - * @param {string} wholeString Has the actualString being searched.
    - * @return {string} Replacement string.
    - */
    -goog.string.format.demuxes_['d'] = function(value,
    -                                            flags,
    -                                            width,
    -                                            dotp,
    -                                            precision,
    -                                            type,
    -                                            offset,
    -                                            wholeString) {
    -  return goog.string.format.demuxes_['f'](
    -      parseInt(value, 10) /* value */,
    -      flags, width, dotp, 0 /* precision */,
    -      type, offset, wholeString);
    -};
    -
    -
    -// These are additional aliases, for integer conversion.
    -goog.string.format.demuxes_['i'] = goog.string.format.demuxes_['d'];
    -goog.string.format.demuxes_['u'] = goog.string.format.demuxes_['d'];
    diff --git a/src/database/third_party/closure-library/closure/goog/string/stringformat_test.html b/src/database/third_party/closure-library/closure/goog/string/stringformat_test.html
    deleted file mode 100644
    index 50ff9a62bcf..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/string/stringformat_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.string.format
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.string.formatTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/string/stringformat_test.js b/src/database/third_party/closure-library/closure/goog/string/stringformat_test.js
    deleted file mode 100644
    index b60cf4b4707..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/string/stringformat_test.js
    +++ /dev/null
    @@ -1,224 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.string.formatTest');
    -goog.setTestOnly('goog.string.formatTest');
    -
    -goog.require('goog.string.format');
    -goog.require('goog.testing.jsunit');
    -
    -// The discussion on naming this functionality is going on.
    -var f = goog.string.format;
    -
    -function testImmediateFormatSpecifier() {
    -  assertEquals('Empty String', '', f(''));
    -  assertEquals('Immediate Value', 'Immediate Value', f('Immediate Value'));
    -}
    -
    -function testPercentSign() {
    -  assertEquals('%', '%', f('%'));
    -  assertEquals('%%', '%', f('%%'));
    -  assertEquals('%%%', '%%', f('%%%'));
    -  assertEquals('%%%%', '%%', f('%%%%'));
    -
    -  assertEquals('width of the percent sign ???', '%%', f('%345%%-67.987%'));
    -}
    -
    -function testStringConversionSpecifier() {
    -  assertEquals('%s', 'abc', f('%s', 'abc'));
    -  assertEquals('%2s', 'abc', f('%2s', 'abc'));
    -  assertEquals('%6s', '   abc', f('%6s', 'abc'));
    -  assertEquals('%-6s', 'abc   ', f('%-6s', 'abc'));
    -}
    -
    -function testFloatConversionSpecifier() {
    -  assertEquals('%f', '123', f('%f', 123));
    -  assertEquals('%f', '0.1', f('%f', 0.1));
    -  assertEquals('%f', '123.456', f('%f', 123.456));
    -
    -  // Precisions, paddings and other flags are handled on a flag to flag basis.
    -
    -}
    -
    -function testAliasedConversionSpecifiers() {
    -  assertEquals('%i vs. %d', f('%i', 123), f('%d', 123));
    -  assertEquals('%u vs. %d', f('%u', 123), f('%d', 123));
    -}
    -
    -function testIntegerConversion() {
    -  assertEquals('%d', '0', f('%d', 0));
    -
    -  assertEquals('%d', '123', f('%d', 123));
    -  assertEquals('%d', '0', f('%d', 0.1));
    -  assertEquals('%d', '0', f('%d', 0.9));
    -  assertEquals('%d', '123', f('%d', 123.456));
    -
    -  assertEquals('%d', '-1', f('%d', -1));
    -  assertEquals('%d', '0', f('%d', -0.1));
    -  assertEquals('%d', '0', f('%d', -0.9));
    -  assertEquals('%d', '-123', f('%d', -123.456));
    -
    -  // Precisions, paddings and other flags are handled on a flag to flag basis.
    -
    -}
    -
    -function testSpaceFlag() {
    -  assertEquals('zero %+d ', ' 0', f('% d', 0));
    -
    -  assertEquals('positive % d ', ' 123', f('% d', 123));
    -  assertEquals('negative % d ', '-123', f('% d', -123));
    -
    -  assertEquals('positive % 3d', ' 123', f('% 3d', 123));
    -  assertEquals('negative % 3d', '-123', f('% 3d', -123));
    -
    -  assertEquals('positive % 4d', ' 123', f('% 4d', 123));
    -  assertEquals('negative % 4d', '-123', f('% 4d', -123));
    -
    -  assertEquals('positive % 6d', '   123', f('% 6d', 123));
    -  assertEquals('negative % 6d', '-  123', f('% 6d', -123));
    -
    -  assertEquals('positive % f ', ' 123.456', f('% f', 123.456));
    -  assertEquals('negative % f ', '-123.456', f('% f', -123.456));
    -
    -  assertEquals('positive % .2f ', ' 123.46', f('% .2f', 123.456));
    -  assertEquals('negative % .2f ', '-123.46', f('% .2f', -123.456));
    -
    -  assertEquals('positive % 6.2f', ' 123.46', f('% 6.2f', 123.456));
    -  assertEquals('negative % 6.2f', '-123.46', f('% 6.2f', -123.456));
    -
    -  assertEquals('positive % 7.2f', ' 123.46', f('% 7.2f', 123.456));
    -  assertEquals('negative % 7.2f', '-123.46', f('% 7.2f', -123.456));
    -
    -  assertEquals('positive % 10.2f', '    123.46', f('% 10.2f', 123.456));
    -  assertEquals('negative % 10.2f', '-   123.46', f('% 10.2f', -123.456));
    -
    -  assertEquals('string % s ', 'abc', f('% s', 'abc'));
    -  assertEquals('string % 3s', 'abc', f('% 3s', 'abc'));
    -  assertEquals('string % 4s', ' abc', f('% 4s', 'abc'));
    -  assertEquals('string % 6s', '   abc', f('% 6s', 'abc'));
    -}
    -
    -function testPlusFlag() {
    -  assertEquals('zero %+d ', '+0', f('%+d', 0));
    -
    -  assertEquals('positive %+d ', '+123', f('%+d', 123));
    -  assertEquals('negative %+d ', '-123', f('%+d', -123));
    -
    -  assertEquals('positive %+3d', '+123', f('%+3d', 123));
    -  assertEquals('negative %+3d', '-123', f('%+3d', -123));
    -
    -  assertEquals('positive %+4d', '+123', f('%+4d', 123));
    -  assertEquals('negative %+4d', '-123', f('%+4d', -123));
    -
    -  assertEquals('positive %+6d', '+  123', f('%+6d', 123));
    -  assertEquals('negative %+6d', '-  123', f('%+6d', -123));
    -
    -  assertEquals('positive %+f ', '+123.456', f('%+f', 123.456));
    -  assertEquals('negative %+f ', '-123.456', f('%+f', -123.456));
    -
    -  assertEquals('positive %+.2f ', '+123.46', f('%+.2f', 123.456));
    -  assertEquals('negative %+.2f ', '-123.46', f('%+.2f', -123.456));
    -
    -  assertEquals('positive %+6.2f', '+123.46', f('%+6.2f', 123.456));
    -  assertEquals('negative %+6.2f', '-123.46', f('%+6.2f', -123.456));
    -
    -  assertEquals('positive %+7.2f', '+123.46', f('%+7.2f', 123.456));
    -  assertEquals('negative %+7.2f', '-123.46', f('%+7.2f', -123.456));
    -
    -  assertEquals('positive %+10.2f', '+   123.46', f('%+10.2f', 123.456));
    -  assertEquals('negative %+10.2f', '-   123.46', f('%+10.2f', -123.456));
    -
    -  assertEquals('string %+s ', 'abc', f('%+s', 'abc'));
    -  assertEquals('string %+3s', 'abc', f('%+3s', 'abc'));
    -  assertEquals('string %+4s', ' abc', f('%+4s', 'abc'));
    -  assertEquals('string %+6s', '   abc', f('%+6s', 'abc'));
    -}
    -
    -function testPrecision() {
    -  assertEquals('%.5d', '0', f('%.5d', 0));
    -
    -  assertEquals('%d', '123', f('%d', 123.456));
    -  assertEquals('%.2d', '123', f('%.2d', 123.456));
    -
    -  assertEquals('%f', '123.456', f('%f', 123.456));
    -  assertEquals('%.2f', '123.46', f('%.2f', 123.456));
    -
    -  assertEquals('%.3f', '123.456', f('%.3f', 123.456));
    -  assertEquals('%.6f', '123.456000', f('%.6f', 123.456));
    -  assertEquals('%1.2f', '123.46', f('%1.2f', 123.456));
    -  assertEquals('%7.2f', ' 123.46', f('%7.2f', 123.456));
    -
    -  assertEquals('%5.6f', '123.456000', f('%5.6f', 123.456));
    -  assertEquals('%11.6f', ' 123.456000', f('%11.6f', 123.456));
    -
    -  assertEquals('%07.2f', '0123.46', f('%07.2f', 123.456));
    -  assertEquals('%+7.2f', '+123.46', f('%+7.2f', 123.456));
    -}
    -
    -function testZeroFlag() {
    -  assertEquals('%0s', 'abc', f('%0s', 'abc'));
    -  assertEquals('%02s', 'abc', f('%02s', 'abc'));
    -  assertEquals('%06s', '   abc', f('%06s', 'abc'));
    -
    -  assertEquals('%0d', '123', f('%0d', 123));
    -  assertEquals('%0d', '-123', f('%0d', -123));
    -  assertEquals('%06d', '000123', f('%06d', 123));
    -  assertEquals('%06d', '-00123', f('%06d', -123));
    -  assertEquals('%010d', '0000000123', f('%010d', 123));
    -  assertEquals('%010d', '-000000123', f('%010d', -123));
    -}
    -
    -function testFlagMinus() {
    -  assertEquals('%-s', 'abc', f('%-s', 'abc'));
    -  assertEquals('%-2s', 'abc', f('%-2s', 'abc'));
    -  assertEquals('%-6s', 'abc   ', f('%-6s', 'abc'));
    -
    -  assertEquals('%-d', '123', f('%-d', 123));
    -  assertEquals('%-d', '-123', f('%-d', -123));
    -  assertEquals('%-2d', '123', f('%-2d', 123));
    -  assertEquals('%-2d', '-123', f('%-2d', -123));
    -  assertEquals('%-4d', '123 ', f('%-4d', 123));
    -  assertEquals('%-4d', '-123', f('%-4d', -123));
    -
    -  assertEquals('%-d', '123', f('%-0d', 123));
    -  assertEquals('%-d', '-123', f('%-0d', -123));
    -  assertEquals('%-4d', '123 ', f('%-04d', 123));
    -  assertEquals('%-4d', '-123', f('%-04d', -123));
    -}
    -
    -function testExceptions() {
    -  var e = assertThrows(goog.partial(f, '%f%f', 123.456));
    -  assertEquals('[goog.string.format] Not enough arguments', e.message);
    -
    -  e = assertThrows(f);
    -  assertEquals('[goog.string.format] Template required', e.message);
    -}
    -
    -function testNonParticipatingGroupHandling() {
    -  // Firefox supplies empty string instead of undefined for non-participating
    -  // capture groups. This can trigger bad behavior if a demuxer only checks
    -  // isNaN(val) and not also val == ''. Check for regressions.
    -  var format = '%s %d %i %u';
    -  var expected = '1 2 3 4';
    -  // Good types
    -  assertEquals(expected, goog.string.format(format, 1, '2', '3', '4'));
    -  // Bad types
    -  assertEquals(expected, goog.string.format(format, '1', 2, 3, 4));
    -}
    -
    -function testMinusString() {
    -  var format = '%0.1f%%';
    -  var expected = '-0.7%';
    -  assertEquals(expected, goog.string.format(format, '-0.723'));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/string/stringifier.js b/src/database/third_party/closure-library/closure/goog/string/stringifier.js
    deleted file mode 100644
    index 8e66e924663..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/string/stringifier.js
    +++ /dev/null
    @@ -1,38 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Defines an interface for serializing objects into strings.
    - */
    -
    -goog.provide('goog.string.Stringifier');
    -
    -
    -
    -/**
    - * An interface for serializing objects into strings.
    - * @interface
    - */
    -goog.string.Stringifier = function() {};
    -
    -
    -/**
    - * Serializes an object or a value to a string.
    - * Agnostic to the particular format of object and string.
    - *
    - * @param {*} object The object to stringify.
    - * @return {string} A string representation of the input.
    - */
    -goog.string.Stringifier.prototype.stringify;
    diff --git a/src/database/third_party/closure-library/closure/goog/string/typedstring.js b/src/database/third_party/closure-library/closure/goog/string/typedstring.js
    deleted file mode 100644
    index 075115f1c84..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/string/typedstring.js
    +++ /dev/null
    @@ -1,48 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.string.TypedString');
    -
    -
    -
    -/**
    - * Wrapper for strings that conform to a data type or language.
    - *
    - * Implementations of this interface are wrappers for strings, and typically
    - * associate a type contract with the wrapped string.  Concrete implementations
    - * of this interface may choose to implement additional run-time type checking,
    - * see for example {@code goog.html.SafeHtml}. If available, client code that
    - * needs to ensure type membership of an object should use the type's function
    - * to assert type membership, such as {@code goog.html.SafeHtml.unwrap}.
    - * @interface
    - */
    -goog.string.TypedString = function() {};
    -
    -
    -/**
    - * Interface marker of the TypedString interface.
    - *
    - * This property can be used to determine at runtime whether or not an object
    - * implements this interface.  All implementations of this interface set this
    - * property to {@code true}.
    - * @type {boolean}
    - */
    -goog.string.TypedString.prototype.implementsGoogStringTypedString;
    -
    -
    -/**
    - * Retrieves this wrapped string's value.
    - * @return {!string} The wrapped string's value.
    - */
    -goog.string.TypedString.prototype.getTypedStringValue;
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/avltree.js b/src/database/third_party/closure-library/closure/goog/structs/avltree.js
    deleted file mode 100644
    index d45db1e9c22..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/avltree.js
    +++ /dev/null
    @@ -1,899 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Datastructure: AvlTree.
    - *
    - *
    - * This file provides the implementation of an AVL-Tree datastructure. The tree
    - * maintains a set of unique values in a sorted order. The values can be
    - * accessed efficiently in their sorted order since the tree enforces an O(logn)
    - * maximum height. See http://en.wikipedia.org/wiki/Avl_tree for more detail.
    - *
    - * The big-O notation for all operations are below:
    - * <pre>
    - *   Method                 big-O
    - * ----------------------------------------------------------------------------
    - * - add                    O(logn)
    - * - remove                 O(logn)
    - * - clear                  O(1)
    - * - contains               O(logn)
    - * - indexOf                O(logn)
    - * - getCount               O(1)
    - * - getMinimum             O(1), or O(logn) when optional root is specified
    - * - getMaximum             O(1), or O(logn) when optional root is specified
    - * - getHeight              O(1)
    - * - getValues              O(n)
    - * - inOrderTraverse        O(logn + k), where k is number of traversed nodes
    - * - reverseOrderTraverse   O(logn + k), where k is number of traversed nodes
    - * </pre>
    - */
    -
    -
    -goog.provide('goog.structs.AvlTree');
    -goog.provide('goog.structs.AvlTree.Node');
    -
    -goog.require('goog.structs.Collection');
    -
    -
    -
    -/**
    - * Constructs an AVL-Tree, which uses the specified comparator to order its
    - * values. The values can be accessed efficiently in their sorted order since
    - * the tree enforces a O(logn) maximum height.
    - *
    - * @param {Function=} opt_comparator Function used to order the tree's nodes.
    - * @constructor
    - * @implements {goog.structs.Collection<T>}
    - * @final
    - * @template T
    - */
    -goog.structs.AvlTree = function(opt_comparator) {
    -  this.comparator_ = opt_comparator ||
    -                     goog.structs.AvlTree.DEFAULT_COMPARATOR_;
    -};
    -
    -
    -/**
    - * String comparison function used to compare values in the tree. This function
    - * is used by default if no comparator is specified in the tree's constructor.
    - *
    - * @param {T} a The first value.
    - * @param {T} b The second value.
    - * @return {number} -1 if a < b, 1 if a > b, 0 if a = b.
    - * @template T
    - * @private
    - */
    -goog.structs.AvlTree.DEFAULT_COMPARATOR_ = function(a, b) {
    -  if (String(a) < String(b)) {
    -    return -1;
    -  } else if (String(a) > String(b)) {
    -    return 1;
    -  }
    -  return 0;
    -};
    -
    -
    -/**
    - * Pointer to the root node of the tree.
    - *
    - * @private {goog.structs.AvlTree.Node<T>}
    - */
    -goog.structs.AvlTree.prototype.root_ = null;
    -
    -
    -/**
    - * Comparison function used to compare values in the tree. This function should
    - * take two values, a and b, and return x where:
    - * <pre>
    - *  x < 0 if a < b,
    - *  x > 0 if a > b,
    - *  x = 0 otherwise
    - * </pre>
    - *
    - * @type {Function}
    - * @private
    - */
    -goog.structs.AvlTree.prototype.comparator_ = null;
    -
    -
    -/**
    - * Pointer to the node with the smallest value in the tree.
    - *
    - * @type {goog.structs.AvlTree.Node<T>}
    - * @private
    - */
    -goog.structs.AvlTree.prototype.minNode_ = null;
    -
    -
    -/**
    - * Pointer to the node with the largest value in the tree.
    - *
    - * @type {goog.structs.AvlTree.Node<T>}
    - * @private
    - */
    -goog.structs.AvlTree.prototype.maxNode_ = null;
    -
    -
    -/**
    - * Inserts a node into the tree with the specified value if the tree does
    - * not already contain a node with the specified value. If the value is
    - * inserted, the tree is balanced to enforce the AVL-Tree height property.
    - *
    - * @param {T} value Value to insert into the tree.
    - * @return {boolean} Whether value was inserted into the tree.
    - * @override
    - */
    -goog.structs.AvlTree.prototype.add = function(value) {
    -  // If the tree is empty, create a root node with the specified value
    -  if (this.root_ == null) {
    -    this.root_ = new goog.structs.AvlTree.Node(value);
    -    this.minNode_ = this.root_;
    -    this.maxNode_ = this.root_;
    -    return true;
    -  }
    -
    -  // This will be set to the new node if a new node is added.
    -  var newNode = null;
    -
    -  // Depth traverse the tree and insert the value if we reach a null node
    -  this.traverse_(function(node) {
    -    var retNode = null;
    -    var comparison = this.comparator_(node.value, value);
    -    if (comparison > 0) {
    -      retNode = node.left;
    -      if (node.left == null) {
    -        newNode = new goog.structs.AvlTree.Node(value, node);
    -        node.left = newNode;
    -        if (node == this.minNode_) {
    -          this.minNode_ = newNode;
    -        }
    -      }
    -    } else if (comparison < 0) {
    -      retNode = node.right;
    -      if (node.right == null) {
    -        newNode = new goog.structs.AvlTree.Node(value, node);
    -        node.right = newNode;
    -        if (node == this.maxNode_) {
    -          this.maxNode_ = newNode;
    -        }
    -      }
    -    }
    -    return retNode; // If null, we'll stop traversing the tree
    -  });
    -
    -  // If a node was added, increment counts and balance tree.
    -  if (newNode) {
    -    this.traverse_(
    -        function(node) {
    -          node.count++;
    -          return node.parent;
    -        },
    -        newNode.parent);
    -    this.balance_(newNode.parent); // Maintain the AVL-tree balance
    -  }
    -
    -  // Return true if a node was added, false otherwise
    -  return !!newNode;
    -};
    -
    -
    -/**
    - * Removes a node from the tree with the specified value if the tree contains a
    - * node with this value. If a node is removed the tree is balanced to enforce
    - * the AVL-Tree height property. The value of the removed node is returned.
    - *
    - * @param {T} value Value to find and remove from the tree.
    - * @return {T} The value of the removed node or null if the value was not in
    - *     the tree.
    - * @override
    - */
    -goog.structs.AvlTree.prototype.remove = function(value) {
    -  // Assume the value is not removed and set the value when it is removed
    -  var retValue = null;
    -
    -  // Depth traverse the tree and remove the value if we find it
    -  this.traverse_(function(node) {
    -    var retNode = null;
    -    var comparison = this.comparator_(node.value, value);
    -    if (comparison > 0) {
    -      retNode = node.left;
    -    } else if (comparison < 0) {
    -      retNode = node.right;
    -    } else {
    -      retValue = node.value;
    -      this.removeNode_(node);
    -    }
    -    return retNode; // If null, we'll stop traversing the tree
    -  });
    -
    -  // Return the value that was removed, null if the value was not in the tree
    -  return retValue;
    -};
    -
    -
    -/**
    - * Removes all nodes from the tree.
    - */
    -goog.structs.AvlTree.prototype.clear = function() {
    -  this.root_ = null;
    -  this.minNode_ = null;
    -  this.maxNode_ = null;
    -};
    -
    -
    -/**
    - * Returns true if the tree contains a node with the specified value, false
    - * otherwise.
    - *
    - * @param {T} value Value to find in the tree.
    - * @return {boolean} Whether the tree contains a node with the specified value.
    - * @override
    - */
    -goog.structs.AvlTree.prototype.contains = function(value) {
    -  // Assume the value is not in the tree and set this value if it is found
    -  var isContained = false;
    -
    -  // Depth traverse the tree and set isContained if we find the node
    -  this.traverse_(function(node) {
    -    var retNode = null;
    -    var comparison = this.comparator_(node.value, value);
    -    if (comparison > 0) {
    -      retNode = node.left;
    -    } else if (comparison < 0) {
    -      retNode = node.right;
    -    } else {
    -      isContained = true;
    -    }
    -    return retNode; // If null, we'll stop traversing the tree
    -  });
    -
    -  // Return true if the value is contained in the tree, false otherwise
    -  return isContained;
    -};
    -
    -
    -/**
    - * Returns the index (in an in-order traversal) of the node in the tree with
    - * the specified value. For example, the minimum value in the tree will
    - * return an index of 0 and the maximum will return an index of n - 1 (where
    - * n is the number of nodes in the tree).  If the value is not found then -1
    - * is returned.
    - *
    - * @param {T} value Value in the tree whose in-order index is returned.
    - * @return {!number} The in-order index of the given value in the
    - *     tree or -1 if the value is not found.
    - */
    -goog.structs.AvlTree.prototype.indexOf = function(value) {
    -  // Assume the value is not in the tree and set this value if it is found
    -  var retIndex = -1;
    -  var currIndex = 0;
    -
    -  // Depth traverse the tree and set retIndex if we find the node
    -  this.traverse_(function(node) {
    -    var comparison = this.comparator_(node.value, value);
    -    if (comparison > 0) {
    -      // The value is less than this node, so recurse into the left subtree.
    -      return node.left;
    -    }
    -
    -    if (node.left) {
    -      // The value is greater than all of the nodes in the left subtree.
    -      currIndex += node.left.count;
    -    }
    -
    -    if (comparison < 0) {
    -      // The value is also greater than this node.
    -      currIndex++;
    -      // Recurse into the right subtree.
    -      return node.right;
    -    }
    -    // We found the node, so stop traversing the tree.
    -    retIndex = currIndex;
    -    return null;
    -  });
    -
    -  // Return index if the value is contained in the tree, -1 otherwise
    -  return retIndex;
    -};
    -
    -
    -/**
    - * Returns the number of values stored in the tree.
    - *
    - * @return {number} The number of values stored in the tree.
    - * @override
    - */
    -goog.structs.AvlTree.prototype.getCount = function() {
    -  return this.root_ ? this.root_.count : 0;
    -};
    -
    -
    -/**
    - * Returns a k-th smallest value, based on the comparator, where 0 <= k <
    - * this.getCount().
    - * @param {number} k The number k.
    - * @return {T} The k-th smallest value.
    - */
    -goog.structs.AvlTree.prototype.getKthValue = function(k) {
    -  if (k < 0 || k >= this.getCount()) {
    -    return null;
    -  }
    -  return this.getKthNode_(k).value;
    -};
    -
    -
    -/**
    - * Returns the value u, such that u is contained in the tree and u < v, for all
    - * values v in the tree where v != u.
    - *
    - * @return {T} The minimum value contained in the tree.
    - */
    -goog.structs.AvlTree.prototype.getMinimum = function() {
    -  return this.getMinNode_().value;
    -};
    -
    -
    -/**
    - * Returns the value u, such that u is contained in the tree and u > v, for all
    - * values v in the tree where v != u.
    - *
    - * @return {T} The maximum value contained in the tree.
    - */
    -goog.structs.AvlTree.prototype.getMaximum = function() {
    -  return this.getMaxNode_().value;
    -};
    -
    -
    -/**
    - * Returns the height of the tree (the maximum depth). This height should
    - * always be <= 1.4405*(Math.log(n+2)/Math.log(2))-1.3277, where n is the
    - * number of nodes in the tree.
    - *
    - * @return {number} The height of the tree.
    - */
    -goog.structs.AvlTree.prototype.getHeight = function() {
    -  return this.root_ ? this.root_.height : 0;
    -};
    -
    -
    -/**
    - * Inserts the values stored in the tree into a new Array and returns the Array.
    - *
    - * @return {!Array<T>} An array containing all of the trees values in sorted
    - *     order.
    - */
    -goog.structs.AvlTree.prototype.getValues = function() {
    -  var ret = [];
    -  this.inOrderTraverse(function(value) {
    -    ret.push(value);
    -  });
    -  return ret;
    -};
    -
    -
    -/**
    - * Performs an in-order traversal of the tree and calls {@code func} with each
    - * traversed node, optionally starting from the smallest node with a value >= to
    - * the specified start value. The traversal ends after traversing the tree's
    - * maximum node or when {@code func} returns a value that evaluates to true.
    - *
    - * @param {Function} func Function to call on each traversed node.
    - * @param {Object=} opt_startValue If specified, traversal will begin on the
    - *    node with the smallest value >= opt_startValue.
    - */
    -goog.structs.AvlTree.prototype.inOrderTraverse =
    -    function(func, opt_startValue) {
    -  // If our tree is empty, return immediately
    -  if (!this.root_) {
    -    return;
    -  }
    -
    -  // Depth traverse the tree to find node to begin in-order traversal from
    -  var startNode;
    -  if (opt_startValue) {
    -    this.traverse_(function(node) {
    -      var retNode = null;
    -      var comparison = this.comparator_(node.value, opt_startValue);
    -      if (comparison > 0) {
    -        retNode = node.left;
    -        startNode = node;
    -      } else if (comparison < 0) {
    -        retNode = node.right;
    -      } else {
    -        startNode = node;
    -      }
    -      return retNode; // If null, we'll stop traversing the tree
    -    });
    -    if (!startNode) {
    -      return;
    -    }
    -  } else {
    -    startNode = this.getMinNode_();
    -  }
    -
    -  // Traverse the tree and call func on each traversed node's value
    -  var node = startNode, prev = startNode.left ? startNode.left : startNode;
    -  while (node != null) {
    -    if (node.left != null && node.left != prev && node.right != prev) {
    -      node = node.left;
    -    } else {
    -      if (node.right != prev) {
    -        if (func(node.value)) {
    -          return;
    -        }
    -      }
    -      var temp = node;
    -      node = node.right != null && node.right != prev ?
    -             node.right :
    -             node.parent;
    -      prev = temp;
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Performs a reverse-order traversal of the tree and calls {@code func} with
    - * each traversed node, optionally starting from the largest node with a value
    - * <= to the specified start value. The traversal ends after traversing the
    - * tree's minimum node or when func returns a value that evaluates to true.
    - *
    - * @param {function(T):?} func Function to call on each traversed node.
    - * @param {Object=} opt_startValue If specified, traversal will begin on the
    - *    node with the largest value <= opt_startValue.
    - */
    -goog.structs.AvlTree.prototype.reverseOrderTraverse =
    -    function(func, opt_startValue) {
    -  // If our tree is empty, return immediately
    -  if (!this.root_) {
    -    return;
    -  }
    -
    -  // Depth traverse the tree to find node to begin reverse-order traversal from
    -  var startNode;
    -  if (opt_startValue) {
    -    this.traverse_(goog.bind(function(node) {
    -      var retNode = null;
    -      var comparison = this.comparator_(node.value, opt_startValue);
    -      if (comparison > 0) {
    -        retNode = node.left;
    -      } else if (comparison < 0) {
    -        retNode = node.right;
    -        startNode = node;
    -      } else {
    -        startNode = node;
    -      }
    -      return retNode; // If null, we'll stop traversing the tree
    -    }, this));
    -    if (!startNode) {
    -      return;
    -    }
    -  } else {
    -    startNode = this.getMaxNode_();
    -  }
    -
    -  // Traverse the tree and call func on each traversed node's value
    -  var node = startNode, prev = startNode.right ? startNode.right : startNode;
    -  while (node != null) {
    -    if (node.right != null && node.right != prev && node.left != prev) {
    -      node = node.right;
    -    } else {
    -      if (node.left != prev) {
    -        if (func(node.value)) {
    -          return;
    -        }
    -      }
    -      var temp = node;
    -      node = node.left != null && node.left != prev ?
    -             node.left :
    -             node.parent;
    -      prev = temp;
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Performs a traversal defined by the supplied {@code traversalFunc}. The first
    - * call to {@code traversalFunc} is passed the root or the optionally specified
    - * startNode. After that, calls {@code traversalFunc} with the node returned
    - * by the previous call to {@code traversalFunc} until {@code traversalFunc}
    - * returns null or the optionally specified endNode. The first call to
    - * traversalFunc is passed the root or the optionally specified startNode.
    - *
    - * @param {function(
    - *     this:goog.structs.AvlTree<T>,
    - *     !goog.structs.AvlTree.Node):?goog.structs.AvlTree.Node} traversalFunc
    - * Function used to traverse the tree.
    - * @param {goog.structs.AvlTree.Node<T>=} opt_startNode The node at which the
    - *     traversal begins.
    - * @param {goog.structs.AvlTree.Node<T>=} opt_endNode The node at which the
    - *     traversal ends.
    - * @private
    - */
    -goog.structs.AvlTree.prototype.traverse_ =
    -    function(traversalFunc, opt_startNode, opt_endNode) {
    -  var node = opt_startNode ? opt_startNode : this.root_;
    -  var endNode = opt_endNode ? opt_endNode : null;
    -  while (node && node != endNode) {
    -    node = traversalFunc.call(this, node);
    -  }
    -};
    -
    -
    -/**
    - * Ensures that the specified node and all its ancestors are balanced. If they
    - * are not, performs left and right tree rotations to achieve a balanced
    - * tree. This method assumes that at most 2 rotations are necessary to balance
    - * the tree (which is true for AVL-trees that are balanced after each node is
    - * added or removed).
    - *
    - * @param {goog.structs.AvlTree.Node<T>} node Node to begin balance from.
    - * @private
    - */
    -goog.structs.AvlTree.prototype.balance_ = function(node) {
    -
    -  this.traverse_(function(node) {
    -    // Calculate the left and right node's heights
    -    var lh = node.left ? node.left.height : 0;
    -    var rh = node.right ? node.right.height : 0;
    -
    -    // Rotate tree rooted at this node if it is not AVL-tree balanced
    -    if (lh - rh > 1) {
    -      if (node.left.right && (!node.left.left ||
    -          node.left.left.height < node.left.right.height)) {
    -        this.leftRotate_(node.left);
    -      }
    -      this.rightRotate_(node);
    -    } else if (rh - lh > 1) {
    -      if (node.right.left && (!node.right.right ||
    -          node.right.right.height < node.right.left.height)) {
    -        this.rightRotate_(node.right);
    -      }
    -      this.leftRotate_(node);
    -    }
    -
    -    // Recalculate the left and right node's heights
    -    lh = node.left ? node.left.height : 0;
    -    rh = node.right ? node.right.height : 0;
    -
    -    // Set this node's height
    -    node.height = Math.max(lh, rh) + 1;
    -
    -    // Traverse up tree and balance parent
    -    return node.parent;
    -  }, node);
    -
    -};
    -
    -
    -/**
    - * Performs a left tree rotation on the specified node.
    - *
    - * @param {goog.structs.AvlTree.Node<T>} node Pivot node to rotate from.
    - * @private
    - */
    -goog.structs.AvlTree.prototype.leftRotate_ = function(node) {
    -  // Re-assign parent-child references for the parent of the node being removed
    -  if (node.isLeftChild()) {
    -    node.parent.left = node.right;
    -    node.right.parent = node.parent;
    -  } else if (node.isRightChild()) {
    -    node.parent.right = node.right;
    -    node.right.parent = node.parent;
    -  } else {
    -    this.root_ = node.right;
    -    this.root_.parent = null;
    -  }
    -
    -  // Re-assign parent-child references for the child of the node being removed
    -  var temp = node.right;
    -  node.right = node.right.left;
    -  if (node.right != null) node.right.parent = node;
    -  temp.left = node;
    -  node.parent = temp;
    -
    -  // Update counts.
    -  temp.count = node.count;
    -  node.count -= (temp.right ? temp.right.count : 0) + 1;
    -};
    -
    -
    -/**
    - * Performs a right tree rotation on the specified node.
    - *
    - * @param {goog.structs.AvlTree.Node<T>} node Pivot node to rotate from.
    - * @private
    - */
    -goog.structs.AvlTree.prototype.rightRotate_ = function(node) {
    -  // Re-assign parent-child references for the parent of the node being removed
    -  if (node.isLeftChild()) {
    -    node.parent.left = node.left;
    -    node.left.parent = node.parent;
    -  } else if (node.isRightChild()) {
    -    node.parent.right = node.left;
    -    node.left.parent = node.parent;
    -  } else {
    -    this.root_ = node.left;
    -    this.root_.parent = null;
    -  }
    -
    -  // Re-assign parent-child references for the child of the node being removed
    -  var temp = node.left;
    -  node.left = node.left.right;
    -  if (node.left != null) node.left.parent = node;
    -  temp.right = node;
    -  node.parent = temp;
    -
    -  // Update counts.
    -  temp.count = node.count;
    -  node.count -= (temp.left ? temp.left.count : 0) + 1;
    -};
    -
    -
    -/**
    - * Removes the specified node from the tree and ensures the tree still
    - * maintains the AVL-tree balance.
    - *
    - * @param {goog.structs.AvlTree.Node<T>} node The node to be removed.
    - * @private
    - */
    -goog.structs.AvlTree.prototype.removeNode_ = function(node) {
    -  // Perform normal binary tree node removal, but balance the tree, starting
    -  // from where we removed the node
    -  if (node.left != null || node.right != null) {
    -    var b = null; // Node to begin balance from
    -    var r;        // Node to replace the node being removed
    -    if (node.left != null) {
    -      r = this.getMaxNode_(node.left);
    -
    -      // Update counts.
    -      this.traverse_(function(node) {
    -        node.count--;
    -        return node.parent;
    -      }, r);
    -
    -      if (r != node.left) {
    -        r.parent.right = r.left;
    -        if (r.left) r.left.parent = r.parent;
    -        r.left = node.left;
    -        r.left.parent = r;
    -        b = r.parent;
    -      }
    -      r.parent = node.parent;
    -      r.right = node.right;
    -      if (r.right) r.right.parent = r;
    -      if (node == this.maxNode_) this.maxNode_ = r;
    -      r.count = node.count;
    -    } else {
    -      r = this.getMinNode_(node.right);
    -
    -      // Update counts.
    -      this.traverse_(function(node) {
    -        node.count--;
    -        return node.parent;
    -      }, r);
    -
    -      if (r != node.right) {
    -        r.parent.left = r.right;
    -        if (r.right) r.right.parent = r.parent;
    -        r.right = node.right;
    -        r.right.parent = r;
    -        b = r.parent;
    -      }
    -      r.parent = node.parent;
    -      r.left = node.left;
    -      if (r.left) r.left.parent = r;
    -      if (node == this.minNode_) this.minNode_ = r;
    -      r.count = node.count;
    -    }
    -
    -    // Update the parent of the node being removed to point to its replace
    -    if (node.isLeftChild()) {
    -      node.parent.left = r;
    -    } else if (node.isRightChild()) {
    -      node.parent.right = r;
    -    } else {
    -      this.root_ = r;
    -    }
    -
    -    // Balance the tree
    -    this.balance_(b ? b : r);
    -  } else {
    -    // Update counts.
    -    this.traverse_(function(node) {
    -      node.count--;
    -      return node.parent;
    -    }, node.parent);
    -
    -    // If the node is a leaf, remove it and balance starting from its parent
    -    if (node.isLeftChild()) {
    -      this.special = 1;
    -      node.parent.left = null;
    -      if (node == this.minNode_) this.minNode_ = node.parent;
    -      this.balance_(node.parent);
    -    } else if (node.isRightChild()) {
    -      node.parent.right = null;
    -      if (node == this.maxNode_) this.maxNode_ = node.parent;
    -      this.balance_(node.parent);
    -    } else {
    -      this.clear();
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Returns the node in the tree that has k nodes before it in an in-order
    - * traversal, optionally rooted at {@code opt_rootNode}.
    - *
    - * @param {number} k The number of nodes before the node to be returned in an
    - *     in-order traversal, where 0 <= k < root.count.
    - * @param {goog.structs.AvlTree.Node<T>=} opt_rootNode Optional root node.
    - * @return {goog.structs.AvlTree.Node<T>} The node at the specified index.
    - * @private
    - */
    -goog.structs.AvlTree.prototype.getKthNode_ = function(k, opt_rootNode) {
    -  var root = opt_rootNode || this.root_;
    -  var numNodesInLeftSubtree = root.left ? root.left.count : 0;
    -
    -  if (k < numNodesInLeftSubtree) {
    -    return this.getKthNode_(k, root.left);
    -  } else if (k == numNodesInLeftSubtree) {
    -    return root;
    -  } else {
    -    return this.getKthNode_(k - numNodesInLeftSubtree - 1, root.right);
    -  }
    -};
    -
    -
    -/**
    - * Returns the node with the smallest value in tree, optionally rooted at
    - * {@code opt_rootNode}.
    - *
    - * @param {goog.structs.AvlTree.Node<T>=} opt_rootNode Optional root node.
    - * @return {goog.structs.AvlTree.Node<T>} The node with the smallest value in
    - *     the tree.
    - * @private
    - */
    -goog.structs.AvlTree.prototype.getMinNode_ = function(opt_rootNode) {
    -  if (!opt_rootNode) {
    -    return this.minNode_;
    -  }
    -
    -  var minNode = opt_rootNode;
    -  this.traverse_(function(node) {
    -    var retNode = null;
    -    if (node.left) {
    -      minNode = node.left;
    -      retNode = node.left;
    -    }
    -    return retNode; // If null, we'll stop traversing the tree
    -  }, opt_rootNode);
    -
    -  return minNode;
    -};
    -
    -
    -/**
    - * Returns the node with the largest value in tree, optionally rooted at
    - * opt_rootNode.
    - *
    - * @param {goog.structs.AvlTree.Node<T>=} opt_rootNode Optional root node.
    - * @return {goog.structs.AvlTree.Node<T>} The node with the largest value in
    - *     the tree.
    - * @private
    - */
    -goog.structs.AvlTree.prototype.getMaxNode_ = function(opt_rootNode) {
    -  if (!opt_rootNode) {
    -    return this.maxNode_;
    -  }
    -
    -  var maxNode = opt_rootNode;
    -  this.traverse_(function(node) {
    -    var retNode = null;
    -    if (node.right) {
    -      maxNode = node.right;
    -      retNode = node.right;
    -    }
    -    return retNode; // If null, we'll stop traversing the tree
    -  }, opt_rootNode);
    -
    -  return maxNode;
    -};
    -
    -
    -
    -/**
    - * Constructs an AVL-Tree node with the specified value. If no parent is
    - * specified, the node's parent is assumed to be null. The node's height
    - * defaults to 1 and its children default to null.
    - *
    - * @param {T} value Value to store in the node.
    - * @param {goog.structs.AvlTree.Node<T>=} opt_parent Optional parent node.
    - * @constructor
    - * @final
    - * @template T
    - */
    -goog.structs.AvlTree.Node = function(value, opt_parent) {
    -  /**
    -   * The value stored by the node.
    -   *
    -   * @type {T}
    -   */
    -  this.value = value;
    -
    -  /**
    -   * The node's parent. Null if the node is the root.
    -   *
    -   * @type {goog.structs.AvlTree.Node<T>}
    -   */
    -  this.parent = opt_parent ? opt_parent : null;
    -
    -  /**
    -   * The number of nodes in the subtree rooted at this node.
    -   *
    -   * @type {number}
    -   */
    -  this.count = 1;
    -};
    -
    -
    -/**
    - * The node's left child. Null if the node does not have a left child.
    - *
    - * @type {?goog.structs.AvlTree.Node<T>}
    - */
    -goog.structs.AvlTree.Node.prototype.left = null;
    -
    -
    -/**
    - * The node's right child. Null if the node does not have a right child.
    - *
    - * @type {?goog.structs.AvlTree.Node<T>}
    - */
    -goog.structs.AvlTree.Node.prototype.right = null;
    -
    -
    -/**
    - * The height of the tree rooted at this node.
    - *
    - * @type {number}
    - */
    -goog.structs.AvlTree.Node.prototype.height = 1;
    -
    -
    -/**
    - * Returns true iff the specified node has a parent and is the right child of
    - * its parent.
    - *
    - * @return {boolean} Whether the specified node has a parent and is the right
    - *    child of its parent.
    - */
    -goog.structs.AvlTree.Node.prototype.isRightChild = function() {
    -  return !!this.parent && this.parent.right == this;
    -};
    -
    -
    -/**
    - * Returns true iff the specified node has a parent and is the left child of
    - * its parent.
    - *
    - * @return {boolean} Whether the specified node has a parent and is the left
    - *    child of its parent.
    - */
    -goog.structs.AvlTree.Node.prototype.isLeftChild = function() {
    -  return !!this.parent && this.parent.left == this;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/avltree_test.html b/src/database/third_party/closure-library/closure/goog/structs/avltree_test.html
    deleted file mode 100644
    index aff7dd2f6c4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/avltree_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.structs.AvlTree
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -  goog.require('goog.structs.AvlTreeTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/avltree_test.js b/src/database/third_party/closure-library/closure/goog/structs/avltree_test.js
    deleted file mode 100644
    index a24972e094f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/avltree_test.js
    +++ /dev/null
    @@ -1,363 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.structs.AvlTreeTest');
    -goog.setTestOnly('goog.structs.AvlTreeTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.structs.AvlTree');
    -goog.require('goog.testing.jsunit');
    -
    -
    -/**
    - * This test verifies that we can insert strings into the AvlTree and have
    - * them be stored and sorted correctly by the default comparator.
    - */
    -function testInsertsWithDefaultComparator() {
    -  var tree = new goog.structs.AvlTree();
    -  var values = ['bill', 'blake', 'elliot', 'jacob', 'john', 'myles', 'ted'];
    -
    -  // Insert strings into tree out of order
    -  tree.add(values[4]);
    -  tree.add(values[3]);
    -  tree.add(values[0]);
    -  tree.add(values[6]);
    -  tree.add(values[5]);
    -  tree.add(values[1]);
    -  tree.add(values[2]);
    -
    -  // Verify strings are stored in sorted order
    -  var i = 0;
    -  tree.inOrderTraverse(function(value) {
    -    assertEquals(values[i], value);
    -    i += 1;
    -  });
    -  assertEquals(i, values.length);
    -
    -  // Verify that no nodes are visited if the start value is larger than all
    -  // values
    -  tree.inOrderTraverse(function(value) {
    -    fail();
    -  }, 'zed');
    -
    -  // Verify strings are stored in sorted order
    -  i = values.length;
    -  tree.reverseOrderTraverse(function(value) {
    -    i--;
    -    assertEquals(values[i], value);
    -  });
    -  assertEquals(i, 0);
    -
    -  // Verify that no nodes are visited if the start value is smaller than all
    -  // values
    -  tree.reverseOrderTraverse(function(value) {
    -    fail();
    -  }, 'aardvark');
    -}
    -
    -
    -/**
    - * This test verifies that we can insert strings into and remove strings from
    - * the AvlTree and have the only the non-removed values be stored and sorted
    - * correctly by the default comparator.
    - */
    -function testRemovesWithDefaultComparator() {
    -  var tree = new goog.structs.AvlTree();
    -  var values = ['bill', 'blake', 'elliot', 'jacob', 'john', 'myles', 'ted'];
    -
    -  // Insert strings into tree out of order
    -  tree.add('frodo');
    -  tree.add(values[4]);
    -  tree.add(values[3]);
    -  tree.add(values[0]);
    -  tree.add(values[6]);
    -  tree.add('samwise');
    -  tree.add(values[5]);
    -  tree.add(values[1]);
    -  tree.add(values[2]);
    -  tree.add('pippin');
    -
    -  // Remove strings from tree
    -  assertEquals(tree.remove('samwise'), 'samwise');
    -  assertEquals(tree.remove('pippin'), 'pippin');
    -  assertEquals(tree.remove('frodo'), 'frodo');
    -  assertEquals(tree.remove('merry'), null);
    -
    -
    -  // Verify strings are stored in sorted order
    -  var i = 0;
    -  tree.inOrderTraverse(function(value) {
    -    assertEquals(values[i], value);
    -    i += 1;
    -  });
    -  assertEquals(i, values.length);
    -}
    -
    -
    -/**
    - * This test verifies that we can insert values into and remove values from
    - * the AvlTree and have them be stored and sorted correctly by a custom
    - * comparator.
    - */
    -function testInsertsAndRemovesWithCustomComparator() {
    -  var tree = new goog.structs.AvlTree(function(a, b) {
    -    return a - b;
    -  });
    -
    -  var NUM_TO_INSERT = 37;
    -  var valuesToRemove = [1, 0, 6, 7, 36];
    -
    -  // Insert ints into tree out of order
    -  var values = [];
    -  for (var i = 0; i < NUM_TO_INSERT; i += 1) {
    -    tree.add(i);
    -    values.push(i);
    -  }
    -
    -  for (var i = 0; i < valuesToRemove.length; i += 1) {
    -    assertEquals(tree.remove(valuesToRemove[i]), valuesToRemove[i]);
    -    goog.array.remove(values, valuesToRemove[i]);
    -  }
    -  assertEquals(tree.remove(-1), null);
    -  assertEquals(tree.remove(37), null);
    -
    -  // Verify strings are stored in sorted order
    -  var i = 0;
    -  tree.inOrderTraverse(function(value) {
    -    assertEquals(values[i], value);
    -    i += 1;
    -  });
    -  assertEquals(i, values.length);
    -}
    -
    -
    -/**
    - * This test verifies that we can insert values into and remove values from
    - * the AvlTree and have it maintain the AVL-Tree upperbound on its height.
    - */
    -function testAvlTreeHeight() {
    -  var tree = new goog.structs.AvlTree(function(a, b) {
    -    return a - b;
    -  });
    -
    -  var NUM_TO_INSERT = 2000;
    -  var NUM_TO_REMOVE = 500;
    -
    -  // Insert ints into tree out of order
    -  for (var i = 0; i < NUM_TO_INSERT; i += 1) {
    -    tree.add(i);
    -  }
    -
    -  // Remove valuse
    -  for (var i = 0; i < NUM_TO_REMOVE; i += 1) {
    -    tree.remove(i);
    -  }
    -
    -  assertTrue(tree.getHeight() <= 1.4405 *
    -      (Math.log(NUM_TO_INSERT - NUM_TO_REMOVE + 2) / Math.log(2)) - 1.3277);
    -}
    -
    -
    -/**
    - * This test verifies that we can insert values into and remove values from
    - * the AvlTree and have its contains method correctly determine the values it
    - * is contains.
    - */
    -function testAvlTreeContains() {
    -  var tree = new goog.structs.AvlTree();
    -  var values = ['bill', 'blake', 'elliot', 'jacob', 'john', 'myles', 'ted'];
    -
    -  // Insert strings into tree out of order
    -  tree.add('frodo');
    -  tree.add(values[4]);
    -  tree.add(values[3]);
    -  tree.add(values[0]);
    -  tree.add(values[6]);
    -  tree.add('samwise');
    -  tree.add(values[5]);
    -  tree.add(values[1]);
    -  tree.add(values[2]);
    -  tree.add('pippin');
    -
    -  // Remove strings from tree
    -  assertEquals(tree.remove('samwise'), 'samwise');
    -  assertEquals(tree.remove('pippin'), 'pippin');
    -  assertEquals(tree.remove('frodo'), 'frodo');
    -
    -  for (var i = 0; i < values.length; i += 1) {
    -    assertTrue(tree.contains(values[i]));
    -  }
    -  assertFalse(tree.contains('samwise'));
    -  assertFalse(tree.contains('pippin'));
    -  assertFalse(tree.contains('frodo'));
    -}
    -
    -
    -/**
    - * This test verifies that we can insert values into and remove values from
    - * the AvlTree and have its indexOf method correctly determine the in-order
    - * index of the values it contains.
    - */
    -function testAvlTreeIndexOf() {
    -  var tree = new goog.structs.AvlTree();
    -  var values = ['bill', 'blake', 'elliot', 'jacob', 'john', 'myles', 'ted'];
    -
    -  // Insert strings into tree out of order
    -  tree.add('frodo');
    -  tree.add(values[4]);
    -  tree.add(values[3]);
    -  tree.add(values[0]);
    -  tree.add(values[6]);
    -  tree.add('samwise');
    -  tree.add(values[5]);
    -  tree.add(values[1]);
    -  tree.add(values[2]);
    -  tree.add('pippin');
    -
    -  // Remove strings from tree
    -  assertEquals('samwise', tree.remove('samwise'));
    -  assertEquals('pippin', tree.remove('pippin'));
    -  assertEquals('frodo', tree.remove('frodo'));
    -
    -  for (var i = 0; i < values.length; i += 1) {
    -    assertEquals(i, tree.indexOf(values[i]));
    -  }
    -  assertEquals(-1, tree.indexOf('samwise'));
    -  assertEquals(-1, tree.indexOf('pippin'));
    -  assertEquals(-1, tree.indexOf('frodo'));
    -}
    -
    -
    -/**
    - * This test verifies that we can insert values into and remove values from
    - * the AvlTree and have its minValue and maxValue routines return the correct
    - * min and max values contained by the tree.
    - */
    -function testMinAndMaxValues() {
    -  var tree = new goog.structs.AvlTree(function(a, b) {
    -    return a - b;
    -  });
    -
    -  var NUM_TO_INSERT = 2000;
    -  var NUM_TO_REMOVE = 500;
    -
    -  // Insert ints into tree out of order
    -  for (var i = 0; i < NUM_TO_INSERT; i += 1) {
    -    tree.add(i);
    -  }
    -
    -  // Remove valuse
    -  for (var i = 0; i < NUM_TO_REMOVE; i += 1) {
    -    tree.remove(i);
    -  }
    -
    -  assertEquals(tree.getMinimum(), NUM_TO_REMOVE);
    -  assertEquals(tree.getMaximum(), NUM_TO_INSERT - 1);
    -}
    -
    -
    -/**
    - * This test verifies that we can insert values into and remove values from
    - * the AvlTree and traverse the tree in reverse order using the
    - * reverseOrderTraverse routine.
    - */
    -function testReverseOrderTraverse() {
    -  var tree = new goog.structs.AvlTree(function(a, b) {
    -    return a - b;
    -  });
    -
    -  var NUM_TO_INSERT = 2000;
    -  var NUM_TO_REMOVE = 500;
    -
    -  // Insert ints into tree out of order
    -  for (var i = 0; i < NUM_TO_INSERT; i += 1) {
    -    tree.add(i);
    -  }
    -
    -  // Remove valuse
    -  for (var i = 0; i < NUM_TO_REMOVE; i += 1) {
    -    tree.remove(i);
    -  }
    -
    -  var i = NUM_TO_INSERT - 1;
    -  tree.reverseOrderTraverse(function(value) {
    -    assertEquals(value, i);
    -    i -= 1;
    -  });
    -  assertEquals(i, NUM_TO_REMOVE - 1);
    -}
    -
    -
    -/**
    - * Verifies correct behavior of getCount(). See http://b/4347755
    - */
    -function testGetCountBehavior() {
    -  var tree = new goog.structs.AvlTree();
    -  tree.add(1);
    -  tree.remove(1);
    -  assertEquals(0, tree.getCount());
    -
    -  var values = ['bill', 'blake', 'elliot', 'jacob', 'john', 'myles', 'ted'];
    -
    -  // Insert strings into tree out of order
    -  tree.add('frodo');
    -  tree.add(values[4]);
    -  tree.add(values[3]);
    -  tree.add(values[0]);
    -  tree.add(values[6]);
    -  tree.add('samwise');
    -  tree.add(values[5]);
    -  tree.add(values[1]);
    -  tree.add(values[2]);
    -  tree.add('pippin');
    -  assertEquals(10, tree.getCount());
    -  assertEquals(
    -      tree.root_.left.count + tree.root_.right.count + 1, tree.getCount());
    -
    -  // Remove strings from tree
    -  assertEquals('samwise', tree.remove('samwise'));
    -  assertEquals('pippin', tree.remove('pippin'));
    -  assertEquals('frodo', tree.remove('frodo'));
    -  assertEquals(null, tree.remove('merry'));
    -  assertEquals(7, tree.getCount());
    -
    -  assertEquals(
    -      tree.root_.left.count + tree.root_.right.count + 1, tree.getCount());
    -}
    -
    -
    -/**
    - * This test verifies that getKthOrder gets the correct value.
    - */
    -function testGetKthOrder() {
    -  var tree = new goog.structs.AvlTree(function(a, b) {
    -    return a - b;
    -  });
    -
    -  var NUM_TO_INSERT = 2000;
    -  var NUM_TO_REMOVE = 500;
    -
    -  // Insert ints into tree out of order
    -  for (var i = 0; i < NUM_TO_INSERT; i += 1) {
    -    tree.add(i);
    -  }
    -
    -  // Remove values.
    -  for (var i = 0; i < NUM_TO_REMOVE; i += 1) {
    -    tree.remove(i);
    -  }
    -  for (var k = 0; k < tree.getCount(); ++k) {
    -    assertEquals(NUM_TO_REMOVE + k, tree.getKthValue(k));
    -  }
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/circularbuffer.js b/src/database/third_party/closure-library/closure/goog/structs/circularbuffer.js
    deleted file mode 100644
    index e50971c4919..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/circularbuffer.js
    +++ /dev/null
    @@ -1,216 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Datastructure: Circular Buffer.
    - *
    - * Implements a buffer with a maximum size. New entries override the oldest
    - * entries when the maximum size has been reached.
    - *
    - */
    -
    -
    -goog.provide('goog.structs.CircularBuffer');
    -
    -
    -
    -/**
    - * Class for CircularBuffer.
    - * @param {number=} opt_maxSize The maximum size of the buffer.
    - * @constructor
    - * @template T
    - */
    -goog.structs.CircularBuffer = function(opt_maxSize) {
    -  /**
    -   * Index of the next element in the circular array structure.
    -   * @private {number}
    -   */
    -  this.nextPtr_ = 0;
    -
    -  /**
    -   * Maximum size of the the circular array structure.
    -   * @private {number}
    -   */
    -  this.maxSize_ = opt_maxSize || 100;
    -
    -  /**
    -   * Underlying array for the CircularBuffer.
    -   * @private {!Array<T>}
    -   */
    -  this.buff_ = [];
    -};
    -
    -
    -/**
    - * Adds an item to the buffer. May remove the oldest item if the buffer is at
    - * max size.
    - * @param {T} item The item to add.
    - * @return {T|undefined} The removed old item, if the buffer is at max size.
    - *     Return undefined, otherwise.
    - */
    -goog.structs.CircularBuffer.prototype.add = function(item) {
    -  var previousItem = this.buff_[this.nextPtr_];
    -  this.buff_[this.nextPtr_] = item;
    -  this.nextPtr_ = (this.nextPtr_ + 1) % this.maxSize_;
    -  return previousItem;
    -};
    -
    -
    -/**
    - * Returns the item at the specified index.
    - * @param {number} index The index of the item. The index of an item can change
    - *     after calls to {@code add()} if the buffer is at maximum size.
    - * @return {T} The item at the specified index.
    - */
    -goog.structs.CircularBuffer.prototype.get = function(index) {
    -  index = this.normalizeIndex_(index);
    -  return this.buff_[index];
    -};
    -
    -
    -/**
    - * Sets the item at the specified index.
    - * @param {number} index The index of the item. The index of an item can change
    - *     after calls to {@code add()} if the buffer is at maximum size.
    - * @param {T} item The item to add.
    - */
    -goog.structs.CircularBuffer.prototype.set = function(index, item) {
    -  index = this.normalizeIndex_(index);
    -  this.buff_[index] = item;
    -};
    -
    -
    -/**
    - * Returns the current number of items in the buffer.
    - * @return {number} The current number of items in the buffer.
    - */
    -goog.structs.CircularBuffer.prototype.getCount = function() {
    -  return this.buff_.length;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the buffer is empty.
    - */
    -goog.structs.CircularBuffer.prototype.isEmpty = function() {
    -  return this.buff_.length == 0;
    -};
    -
    -
    -/**
    - * Empties the current buffer.
    - */
    -goog.structs.CircularBuffer.prototype.clear = function() {
    -  this.buff_.length = 0;
    -  this.nextPtr_ = 0;
    -};
    -
    -
    -/** @return {!Array<T>} The values in the buffer. */
    -goog.structs.CircularBuffer.prototype.getValues = function() {
    -  // getNewestValues returns all the values if the maxCount parameter is the
    -  // count
    -  return this.getNewestValues(this.getCount());
    -};
    -
    -
    -/**
    - * Returns the newest values in the buffer up to {@code count}.
    - * @param {number} maxCount The maximum number of values to get. Should be a
    - *     positive number.
    - * @return {!Array<T>} The newest values in the buffer up to {@code count}.
    - */
    -goog.structs.CircularBuffer.prototype.getNewestValues = function(maxCount) {
    -  var l = this.getCount();
    -  var start = this.getCount() - maxCount;
    -  var rv = [];
    -  for (var i = start; i < l; i++) {
    -    rv.push(this.get(i));
    -  }
    -  return rv;
    -};
    -
    -
    -/** @return {!Array<number>} The indexes in the buffer. */
    -goog.structs.CircularBuffer.prototype.getKeys = function() {
    -  var rv = [];
    -  var l = this.getCount();
    -  for (var i = 0; i < l; i++) {
    -    rv[i] = i;
    -  }
    -  return rv;
    -};
    -
    -
    -/**
    - * Whether the buffer contains the key/index.
    - * @param {number} key The key/index to check for.
    - * @return {boolean} Whether the buffer contains the key/index.
    - */
    -goog.structs.CircularBuffer.prototype.containsKey = function(key) {
    -  return key < this.getCount();
    -};
    -
    -
    -/**
    - * Whether the buffer contains the given value.
    - * @param {T} value The value to check for.
    - * @return {boolean} Whether the buffer contains the given value.
    - */
    -goog.structs.CircularBuffer.prototype.containsValue = function(value) {
    -  var l = this.getCount();
    -  for (var i = 0; i < l; i++) {
    -    if (this.get(i) == value) {
    -      return true;
    -    }
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Returns the last item inserted into the buffer.
    - * @return {T|null} The last item inserted into the buffer,
    - *     or null if the buffer is empty.
    - */
    -goog.structs.CircularBuffer.prototype.getLast = function() {
    -  if (this.getCount() == 0) {
    -    return null;
    -  }
    -  return this.get(this.getCount() - 1);
    -};
    -
    -
    -/**
    - * Helper function to convert an index in the number space of oldest to
    - * newest items in the array to the position that the element will be at in the
    - * underlying array.
    - * @param {number} index The index of the item in a list ordered from oldest to
    - *     newest.
    - * @return {number} The index of the item in the CircularBuffer's underlying
    - *     array.
    - * @private
    - */
    -goog.structs.CircularBuffer.prototype.normalizeIndex_ = function(index) {
    -  if (index >= this.buff_.length) {
    -    throw Error('Out of bounds exception');
    -  }
    -
    -  if (this.buff_.length < this.maxSize_) {
    -    return index;
    -  }
    -
    -  return (this.nextPtr_ + Number(index)) % this.maxSize_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/circularbuffer_test.html b/src/database/third_party/closure-library/closure/goog/structs/circularbuffer_test.html
    deleted file mode 100644
    index e0225307631..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/circularbuffer_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.structs
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.structs.CircularBufferTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/circularbuffer_test.js b/src/database/third_party/closure-library/closure/goog/structs/circularbuffer_test.js
    deleted file mode 100644
    index d3e81f217ca..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/circularbuffer_test.js
    +++ /dev/null
    @@ -1,101 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.structs.CircularBufferTest');
    -goog.setTestOnly('goog.structs.CircularBufferTest');
    -
    -goog.require('goog.structs.CircularBuffer');
    -goog.require('goog.testing.jsunit');
    -
    -function testCircularBuffer() {
    -  var buff = new goog.structs.CircularBuffer(2);
    -  assertUndefined(buff.add('first'));
    -  assertEquals(1, buff.getCount());
    -  assertEquals('first', buff.get(0));
    -  assertEquals('first', buff.getLast());
    -  assertUndefined(buff.add('second'));
    -  assertEquals(2, buff.getCount());
    -  assertEquals('first', buff.get(0));
    -  assertEquals('second', buff.get(1));
    -  assertEquals('second', buff.getLast());
    -  assertEquals('first', buff.add('third'));
    -  assertEquals(2, buff.getCount());
    -  assertEquals('second', buff.get(0));
    -  assertEquals('third', buff.get(1));
    -  assertEquals('third', buff.getLast());
    -}
    -
    -function testIsEmpty() {
    -  var buff = new goog.structs.CircularBuffer(2);
    -  assertTrue('initially empty', buff.isEmpty());
    -  assertUndefined(buff.add('first'));
    -  assertFalse('not empty after add empty', buff.isEmpty());
    -}
    -
    -function testClear() {
    -  var buff = new goog.structs.CircularBuffer(2);
    -  assertUndefined(buff.add('first'));
    -  buff.clear();
    -  assertTrue('should be empty after clear', buff.isEmpty());
    -
    -}
    -
    -function testGetValues() {
    -  var buff = new goog.structs.CircularBuffer(2);
    -  assertUndefined(buff.add('first'));
    -  assertUndefined(buff.add('second'));
    -  assertArrayEquals(['first', 'second'], buff.getValues());
    -}
    -
    -function testGetNewestValues() {
    -  var buff = new goog.structs.CircularBuffer(5);
    -  assertUndefined(buff.add('first'));
    -  assertUndefined(buff.add('second'));
    -  assertUndefined(buff.add('third'));
    -  assertUndefined(buff.add('fourth'));
    -  assertUndefined(buff.add('fifth'));
    -  assertArrayEquals(['fourth', 'fifth'], buff.getNewestValues(2));
    -}
    -
    -
    -function testGetKeys() {
    -  var buff = new goog.structs.CircularBuffer(2);
    -  assertUndefined(buff.add('first'));
    -  assertUndefined(buff.add('second'));
    -  assertArrayEquals([0, 1], buff.getKeys());
    -}
    -
    -function testContainsValue() {
    -  var buff = new goog.structs.CircularBuffer(2);
    -  assertUndefined(buff.add('first'));
    -  assertUndefined(buff.add('second'));
    -  assertTrue(buff.containsValue('first'));
    -  assertTrue(buff.containsValue('second'));
    -  assertFalse(buff.containsValue('third'));
    -}
    -
    -function testContainsKey() {
    -  var buff = new goog.structs.CircularBuffer(3);
    -  assertUndefined(buff.add('first'));
    -  assertUndefined(buff.add('second'));
    -  assertUndefined(buff.add('third'));
    -  assertTrue(buff.containsKey(0));
    -  assertTrue(buff.containsKey('0'));
    -  assertTrue(buff.containsKey(1));
    -  assertTrue(buff.containsKey('1'));
    -  assertTrue(buff.containsKey(2));
    -  assertTrue(buff.containsKey('2'));
    -  assertFalse(buff.containsKey(3));
    -  assertFalse(buff.containsKey('3'));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/collection.js b/src/database/third_party/closure-library/closure/goog/structs/collection.js
    deleted file mode 100644
    index 86d008db5ce..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/collection.js
    +++ /dev/null
    @@ -1,56 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Defines the collection interface.
    - *
    - * @author nnaze@google.com (Nathan Naze)
    - */
    -
    -goog.provide('goog.structs.Collection');
    -
    -
    -
    -/**
    - * An interface for a collection of values.
    - * @interface
    - * @template T
    - */
    -goog.structs.Collection = function() {};
    -
    -
    -/**
    - * @param {T} value Value to add to the collection.
    - */
    -goog.structs.Collection.prototype.add;
    -
    -
    -/**
    - * @param {T} value Value to remove from the collection.
    - */
    -goog.structs.Collection.prototype.remove;
    -
    -
    -/**
    - * @param {T} value Value to find in the collection.
    - * @return {boolean} Whether the collection contains the specified value.
    - */
    -goog.structs.Collection.prototype.contains;
    -
    -
    -/**
    - * @return {number} The number of values stored in the collection.
    - */
    -goog.structs.Collection.prototype.getCount;
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/collection_test.html b/src/database/third_party/closure-library/closure/goog/structs/collection_test.html
    deleted file mode 100644
    index 240db38cdc4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/collection_test.html
    +++ /dev/null
    @@ -1,21 +0,0 @@
    -<!doctype html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.structs.Collection
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.structs.CollectionTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/collection_test.js b/src/database/third_party/closure-library/closure/goog/structs/collection_test.js
    deleted file mode 100644
    index 3545b82a16f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/collection_test.js
    +++ /dev/null
    @@ -1,53 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.structs.CollectionTest');
    -goog.setTestOnly('goog.structs.CollectionTest');
    -
    -goog.require('goog.structs.AvlTree');
    -goog.require('goog.structs.Set');
    -goog.require('goog.testing.jsunit');
    -
    -function testSet() {
    -  var set = new goog.structs.Set();
    -  exerciseCollection(set);
    -}
    -
    -function testAvlTree() {
    -  var tree = new goog.structs.AvlTree();
    -  exerciseCollection(tree);
    -}
    -
    -// Simple exercise of a collection object.
    -function exerciseCollection(collection) {
    -  assertEquals(0, collection.getCount());
    -
    -  for (var i = 1; i <= 10; i++) {
    -    assertFalse(collection.contains(i));
    -    collection.add(i);
    -    assertTrue(collection.contains(i));
    -    assertEquals(i, collection.getCount());
    -  }
    -
    -  assertEquals(10, collection.getCount());
    -
    -  for (var i = 10; i > 0; i--) {
    -    assertTrue(collection.contains(i));
    -    collection.remove(i);
    -    assertFalse(collection.contains(i));
    -    assertEquals(i - 1, collection.getCount());
    -  }
    -
    -  assertEquals(0, collection.getCount());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/heap.js b/src/database/third_party/closure-library/closure/goog/structs/heap.js
    deleted file mode 100644
    index c2b09b4d899..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/heap.js
    +++ /dev/null
    @@ -1,334 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Datastructure: Heap.
    - *
    - *
    - * This file provides the implementation of a Heap datastructure. Smaller keys
    - * rise to the top.
    - *
    - * The big-O notation for all operations are below:
    - * <pre>
    - *  Method          big-O
    - * ----------------------------------------------------------------------------
    - * - insert         O(logn)
    - * - remove         O(logn)
    - * - peek           O(1)
    - * - contains       O(n)
    - * </pre>
    - */
    -// TODO(user): Should this rely on natural ordering via some Comparable
    -//     interface?
    -
    -
    -goog.provide('goog.structs.Heap');
    -
    -goog.require('goog.array');
    -goog.require('goog.object');
    -goog.require('goog.structs.Node');
    -
    -
    -
    -/**
    - * Class for a Heap datastructure.
    - *
    - * @param {goog.structs.Heap|Object=} opt_heap Optional goog.structs.Heap or
    - *     Object to initialize heap with.
    - * @constructor
    - * @template K, V
    - */
    -goog.structs.Heap = function(opt_heap) {
    -  /**
    -   * The nodes of the heap.
    -   * @private
    -   * @type {Array<goog.structs.Node>}
    -   */
    -  this.nodes_ = [];
    -
    -  if (opt_heap) {
    -    this.insertAll(opt_heap);
    -  }
    -};
    -
    -
    -/**
    - * Insert the given value into the heap with the given key.
    - * @param {K} key The key.
    - * @param {V} value The value.
    - */
    -goog.structs.Heap.prototype.insert = function(key, value) {
    -  var node = new goog.structs.Node(key, value);
    -  var nodes = this.nodes_;
    -  nodes.push(node);
    -  this.moveUp_(nodes.length - 1);
    -};
    -
    -
    -/**
    - * Adds multiple key-value pairs from another goog.structs.Heap or Object
    - * @param {goog.structs.Heap|Object} heap Object containing the data to add.
    - */
    -goog.structs.Heap.prototype.insertAll = function(heap) {
    -  var keys, values;
    -  if (heap instanceof goog.structs.Heap) {
    -    keys = heap.getKeys();
    -    values = heap.getValues();
    -
    -    // If it is a heap and the current heap is empty, I can rely on the fact
    -    // that the keys/values are in the correct order to put in the underlying
    -    // structure.
    -    if (heap.getCount() <= 0) {
    -      var nodes = this.nodes_;
    -      for (var i = 0; i < keys.length; i++) {
    -        nodes.push(new goog.structs.Node(keys[i], values[i]));
    -      }
    -      return;
    -    }
    -  } else {
    -    keys = goog.object.getKeys(heap);
    -    values = goog.object.getValues(heap);
    -  }
    -
    -  for (var i = 0; i < keys.length; i++) {
    -    this.insert(keys[i], values[i]);
    -  }
    -};
    -
    -
    -/**
    - * Retrieves and removes the root value of this heap.
    - * @return {V} The value removed from the root of the heap.  Returns
    - *     undefined if the heap is empty.
    - */
    -goog.structs.Heap.prototype.remove = function() {
    -  var nodes = this.nodes_;
    -  var count = nodes.length;
    -  var rootNode = nodes[0];
    -  if (count <= 0) {
    -    return undefined;
    -  } else if (count == 1) {
    -    goog.array.clear(nodes);
    -  } else {
    -    nodes[0] = nodes.pop();
    -    this.moveDown_(0);
    -  }
    -  return rootNode.getValue();
    -};
    -
    -
    -/**
    - * Retrieves but does not remove the root value of this heap.
    - * @return {V} The value at the root of the heap. Returns
    - *     undefined if the heap is empty.
    - */
    -goog.structs.Heap.prototype.peek = function() {
    -  var nodes = this.nodes_;
    -  if (nodes.length == 0) {
    -    return undefined;
    -  }
    -  return nodes[0].getValue();
    -};
    -
    -
    -/**
    - * Retrieves but does not remove the key of the root node of this heap.
    - * @return {K} The key at the root of the heap. Returns undefined if the
    - *     heap is empty.
    - */
    -goog.structs.Heap.prototype.peekKey = function() {
    -  return this.nodes_[0] && this.nodes_[0].getKey();
    -};
    -
    -
    -/**
    - * Moves the node at the given index down to its proper place in the heap.
    - * @param {number} index The index of the node to move down.
    - * @private
    - */
    -goog.structs.Heap.prototype.moveDown_ = function(index) {
    -  var nodes = this.nodes_;
    -  var count = nodes.length;
    -
    -  // Save the node being moved down.
    -  var node = nodes[index];
    -  // While the current node has a child.
    -  while (index < (count >> 1)) {
    -    var leftChildIndex = this.getLeftChildIndex_(index);
    -    var rightChildIndex = this.getRightChildIndex_(index);
    -
    -    // Determine the index of the smaller child.
    -    var smallerChildIndex = rightChildIndex < count &&
    -        nodes[rightChildIndex].getKey() < nodes[leftChildIndex].getKey() ?
    -        rightChildIndex : leftChildIndex;
    -
    -    // If the node being moved down is smaller than its children, the node
    -    // has found the correct index it should be at.
    -    if (nodes[smallerChildIndex].getKey() > node.getKey()) {
    -      break;
    -    }
    -
    -    // If not, then take the smaller child as the current node.
    -    nodes[index] = nodes[smallerChildIndex];
    -    index = smallerChildIndex;
    -  }
    -  nodes[index] = node;
    -};
    -
    -
    -/**
    - * Moves the node at the given index up to its proper place in the heap.
    - * @param {number} index The index of the node to move up.
    - * @private
    - */
    -goog.structs.Heap.prototype.moveUp_ = function(index) {
    -  var nodes = this.nodes_;
    -  var node = nodes[index];
    -
    -  // While the node being moved up is not at the root.
    -  while (index > 0) {
    -    // If the parent is less than the node being moved up, move the parent down.
    -    var parentIndex = this.getParentIndex_(index);
    -    if (nodes[parentIndex].getKey() > node.getKey()) {
    -      nodes[index] = nodes[parentIndex];
    -      index = parentIndex;
    -    } else {
    -      break;
    -    }
    -  }
    -  nodes[index] = node;
    -};
    -
    -
    -/**
    - * Gets the index of the left child of the node at the given index.
    - * @param {number} index The index of the node to get the left child for.
    - * @return {number} The index of the left child.
    - * @private
    - */
    -goog.structs.Heap.prototype.getLeftChildIndex_ = function(index) {
    -  return index * 2 + 1;
    -};
    -
    -
    -/**
    - * Gets the index of the right child of the node at the given index.
    - * @param {number} index The index of the node to get the right child for.
    - * @return {number} The index of the right child.
    - * @private
    - */
    -goog.structs.Heap.prototype.getRightChildIndex_ = function(index) {
    -  return index * 2 + 2;
    -};
    -
    -
    -/**
    - * Gets the index of the parent of the node at the given index.
    - * @param {number} index The index of the node to get the parent for.
    - * @return {number} The index of the parent.
    - * @private
    - */
    -goog.structs.Heap.prototype.getParentIndex_ = function(index) {
    -  return (index - 1) >> 1;
    -};
    -
    -
    -/**
    - * Gets the values of the heap.
    - * @return {!Array<V>} The values in the heap.
    - */
    -goog.structs.Heap.prototype.getValues = function() {
    -  var nodes = this.nodes_;
    -  var rv = [];
    -  var l = nodes.length;
    -  for (var i = 0; i < l; i++) {
    -    rv.push(nodes[i].getValue());
    -  }
    -  return rv;
    -};
    -
    -
    -/**
    - * Gets the keys of the heap.
    - * @return {!Array<K>} The keys in the heap.
    - */
    -goog.structs.Heap.prototype.getKeys = function() {
    -  var nodes = this.nodes_;
    -  var rv = [];
    -  var l = nodes.length;
    -  for (var i = 0; i < l; i++) {
    -    rv.push(nodes[i].getKey());
    -  }
    -  return rv;
    -};
    -
    -
    -/**
    - * Whether the heap contains the given value.
    - * @param {V} val The value to check for.
    - * @return {boolean} Whether the heap contains the value.
    - */
    -goog.structs.Heap.prototype.containsValue = function(val) {
    -  return goog.array.some(this.nodes_, function(node) {
    -    return node.getValue() == val;
    -  });
    -};
    -
    -
    -/**
    - * Whether the heap contains the given key.
    - * @param {K} key The key to check for.
    - * @return {boolean} Whether the heap contains the key.
    - */
    -goog.structs.Heap.prototype.containsKey = function(key) {
    -  return goog.array.some(this.nodes_, function(node) {
    -    return node.getKey() == key;
    -  });
    -};
    -
    -
    -/**
    - * Clones a heap and returns a new heap
    - * @return {!goog.structs.Heap} A new goog.structs.Heap with the same key-value
    - *     pairs.
    - */
    -goog.structs.Heap.prototype.clone = function() {
    -  return new goog.structs.Heap(this);
    -};
    -
    -
    -/**
    - * The number of key-value pairs in the map
    - * @return {number} The number of pairs.
    - */
    -goog.structs.Heap.prototype.getCount = function() {
    -  return this.nodes_.length;
    -};
    -
    -
    -/**
    - * Returns true if this heap contains no elements.
    - * @return {boolean} Whether this heap contains no elements.
    - */
    -goog.structs.Heap.prototype.isEmpty = function() {
    -  return goog.array.isEmpty(this.nodes_);
    -};
    -
    -
    -/**
    - * Removes all elements from the heap.
    - */
    -goog.structs.Heap.prototype.clear = function() {
    -  goog.array.clear(this.nodes_);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/heap_test.html b/src/database/third_party/closure-library/closure/goog/structs/heap_test.html
    deleted file mode 100644
    index a771036f498..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/heap_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.structs.Heap
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.structs.HeapTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/heap_test.js b/src/database/third_party/closure-library/closure/goog/structs/heap_test.js
    deleted file mode 100644
    index d40a80e1667..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/heap_test.js
    +++ /dev/null
    @@ -1,215 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.structs.HeapTest');
    -goog.setTestOnly('goog.structs.HeapTest');
    -
    -goog.require('goog.structs');
    -goog.require('goog.structs.Heap');
    -goog.require('goog.testing.jsunit');
    -
    -function getHeap() {
    -  var h = new goog.structs.Heap();
    -  h.insert(0, 'a');
    -  h.insert(1, 'b');
    -  h.insert(2, 'c');
    -  h.insert(3, 'd');
    -  return h;
    -}
    -
    -
    -function getHeap2() {
    -  var h = new goog.structs.Heap();
    -  h.insert(1, 'b');
    -  h.insert(3, 'd');
    -  h.insert(0, 'a');
    -  h.insert(2, 'c');
    -  return h;
    -}
    -
    -
    -function testGetCount1() {
    -  var h = getHeap();
    -  assertEquals('count, should be 4', h.getCount(), 4);
    -  h.remove();
    -  assertEquals('count, should be 3', h.getCount(), 3);
    -}
    -
    -function testGetCount2() {
    -  var h = getHeap();
    -  h.remove();
    -  h.remove();
    -  h.remove();
    -  h.remove();
    -  assertEquals('count, should be 0', h.getCount(), 0);
    -}
    -
    -
    -function testKeys() {
    -  var h = getHeap();
    -  var keys = h.getKeys();
    -  for (var i = 0; i < 4; i++) {
    -    assertTrue('getKeys, key ' + i + ' found', goog.structs.contains(keys, i));
    -  }
    -  assertEquals('getKeys, Should be 4 keys', goog.structs.getCount(keys), 4);
    -}
    -
    -
    -function testValues() {
    -  var h = getHeap();
    -  var values = h.getValues();
    -
    -  assertTrue('getKeys, value "a" found', goog.structs.contains(values, 'a'));
    -  assertTrue('getKeys, value "b" found', goog.structs.contains(values, 'b'));
    -  assertTrue('getKeys, value "c" found', goog.structs.contains(values, 'c'));
    -  assertTrue('getKeys, value "d" found', goog.structs.contains(values, 'd'));
    -  assertEquals('getKeys, Should be 4 keys', goog.structs.getCount(values), 4);
    -}
    -
    -
    -function testContainsKey() {
    -  var h = getHeap();
    -
    -  for (var i = 0; i < 4; i++) {
    -    assertTrue('containsKey, key ' + i + ' found', h.containsKey(i));
    -  }
    -  assertFalse('containsKey, value 4 not found', h.containsKey(4));
    -}
    -
    -
    -function testContainsValue() {
    -  var h = getHeap();
    -
    -  assertTrue('containsValue, value "a" found', h.containsValue('a'));
    -  assertTrue('containsValue, value "b" found', h.containsValue('b'));
    -  assertTrue('containsValue, value "c" found', h.containsValue('c'));
    -  assertTrue('containsValue, value "d" found', h.containsValue('d'));
    -  assertFalse('containsValue, value "e" not found', h.containsValue('e'));
    -}
    -
    -
    -function testClone() {
    -  var h = getHeap();
    -  var h2 = h.clone();
    -  assertTrue('clone so it should not be empty', !h2.isEmpty());
    -  assertTrue('clone so it should contain key 0', h2.containsKey(0));
    -  assertTrue('clone so it should contain value "a"', h2.containsValue('a'));
    -}
    -
    -
    -function testClear() {
    -  var h = getHeap();
    -  h.clear();
    -  assertTrue('cleared so it should be empty', h.isEmpty());
    -}
    -
    -
    -function testIsEmpty() {
    -  var h = getHeap();
    -  assertFalse('4 values so should not be empty', h.isEmpty());
    -
    -  h.remove();
    -  h.remove();
    -  h.remove();
    -  assertFalse('1 values so should not be empty', h.isEmpty());
    -
    -  h.remove();
    -  assertTrue('0 values so should be empty', h.isEmpty());
    -}
    -
    -
    -function testPeek1() {
    -  var h = getHeap();
    -  assertEquals('peek, Should be "a"', h.peek(), 'a');
    -}
    -
    -
    -function testPeek2() {
    -  var h = getHeap2();
    -  assertEquals('peek, Should be "a"', h.peek(), 'a');
    -}
    -
    -
    -function testPeek3() {
    -  var h = getHeap();
    -  h.clear();
    -  assertEquals('peek, Should be "undefined"', h.peek(), undefined);
    -}
    -
    -
    -function testPeekKey1() {
    -  var h = getHeap();
    -  assertEquals('peekKey, Should be "0"', h.peekKey(), 0);
    -}
    -
    -
    -function testPeekKey2() {
    -  var h = getHeap2();
    -  assertEquals('peekKey, Should be "0"', h.peekKey(), 0);
    -}
    -
    -
    -function testPeekKey3() {
    -  var h = getHeap();
    -  h.clear();
    -  assertEquals('peekKey, Should be "undefined"', h.peekKey(), undefined);
    -}
    -
    -
    -function testRemove1() {
    -  var h = getHeap();
    -
    -  assertEquals('remove, Should be "a"', h.remove(), 'a');
    -  assertEquals('remove, Should be "b"', h.remove(), 'b');
    -  assertEquals('remove, Should be "c"', h.remove(), 'c');
    -  assertEquals('remove, Should be "d"', h.remove(), 'd');
    -}
    -
    -
    -function testRemove2() {
    -  var h = getHeap2();
    -
    -  assertEquals('remove, Should be "a"', h.remove(), 'a');
    -  assertEquals('remove, Should be "b"', h.remove(), 'b');
    -  assertEquals('remove, Should be "c"', h.remove(), 'c');
    -  assertEquals('remove, Should be "d"', h.remove(), 'd');
    -}
    -
    -
    -function testInsertPeek1() {
    -  var h = new goog.structs.Heap();
    -
    -  h.insert(3, 'd');
    -  assertEquals('peek, Should be "d"', h.peek(), 'd');
    -  h.insert(2, 'c');
    -  assertEquals('peek, Should be "c"', h.peek(), 'c');
    -  h.insert(1, 'b');
    -  assertEquals('peek, Should be "b"', h.peek(), 'b');
    -  h.insert(0, 'a');
    -  assertEquals('peek, Should be "a"', h.peek(), 'a');
    -}
    -
    -
    -function testInsertPeek2() {
    -  var h = new goog.structs.Heap();
    -
    -  h.insert(1, 'b');
    -  assertEquals('peak, Should be "b"', h.peek(), 'b');
    -  h.insert(3, 'd');
    -  assertEquals('peak, Should be "b"', h.peek(), 'b');
    -  h.insert(0, 'a');
    -  assertEquals('peak, Should be "a"', h.peek(), 'a');
    -  h.insert(2, 'c');
    -  assertEquals('peak, Should be "a"', h.peek(), 'a');
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/inversionmap.js b/src/database/third_party/closure-library/closure/goog/structs/inversionmap.js
    deleted file mode 100644
    index cbc69e57d43..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/inversionmap.js
    +++ /dev/null
    @@ -1,155 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides inversion and inversion map functionality for storing
    - * integer ranges and corresponding values.
    - *
    - */
    -
    -goog.provide('goog.structs.InversionMap');
    -
    -goog.require('goog.array');
    -
    -
    -
    -/**
    - * Maps ranges to values.
    - * @param {Array<number>} rangeArray An array of monotonically
    - *     increasing integer values, with at least one instance.
    - * @param {Array<T>} valueArray An array of corresponding values.
    - *     Length must be the same as rangeArray.
    - * @param {boolean=} opt_delta If true, saves only delta from previous value.
    - * @constructor
    - * @template T
    - */
    -goog.structs.InversionMap = function(rangeArray, valueArray, opt_delta) {
    -  /**
    -   * @protected {Array<number>}
    -   */
    -  this.rangeArray = null;
    -
    -  if (rangeArray.length != valueArray.length) {
    -    // rangeArray and valueArray has to match in number of entries.
    -    return null;
    -  }
    -  this.storeInversion_(rangeArray, opt_delta);
    -
    -  /** @protected {Array<T>} */
    -  this.values = valueArray;
    -};
    -
    -
    -/**
    - * Stores the integers as ranges (half-open).
    - * If delta is true, the integers are delta from the previous value and
    - * will be restored to the absolute value.
    - * When used as a set, even indices are IN, and odd are OUT.
    - * @param {Array<number?>} rangeArray An array of monotonically
    - *     increasing integer values, with at least one instance.
    - * @param {boolean=} opt_delta If true, saves only delta from previous value.
    - * @private
    - */
    -goog.structs.InversionMap.prototype.storeInversion_ = function(rangeArray,
    -    opt_delta) {
    -  this.rangeArray = rangeArray;
    -
    -  for (var i = 1; i < rangeArray.length; i++) {
    -    if (rangeArray[i] == null) {
    -      rangeArray[i] = rangeArray[i - 1] + 1;
    -    } else if (opt_delta) {
    -      rangeArray[i] += rangeArray[i - 1];
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Splices a range -> value map into this inversion map.
    - * @param {Array<number>} rangeArray An array of monotonically
    - *     increasing integer values, with at least one instance.
    - * @param {Array<T>} valueArray An array of corresponding values.
    - *     Length must be the same as rangeArray.
    - * @param {boolean=} opt_delta If true, saves only delta from previous value.
    - */
    -goog.structs.InversionMap.prototype.spliceInversion = function(
    -    rangeArray, valueArray, opt_delta) {
    -  // By building another inversion map, we build the arrays that we need
    -  // to splice in.
    -  var otherMap = new goog.structs.InversionMap(
    -      rangeArray, valueArray, opt_delta);
    -
    -  // Figure out where to splice those arrays.
    -  var startRange = otherMap.rangeArray[0];
    -  var endRange =
    -      /** @type {number} */ (goog.array.peek(otherMap.rangeArray));
    -  var startSplice = this.getLeast(startRange);
    -  var endSplice = this.getLeast(endRange);
    -
    -  // The inversion map works by storing the start points of ranges...
    -  if (startRange != this.rangeArray[startSplice]) {
    -    // ...if we're splicing in a start point that isn't already here,
    -    // then we need to insert it after the insertion point.
    -    startSplice++;
    -  } // otherwise we overwrite the insertion point.
    -
    -  var spliceLength = endSplice - startSplice + 1;
    -  goog.partial(goog.array.splice, this.rangeArray, startSplice,
    -      spliceLength).apply(null, otherMap.rangeArray);
    -  goog.partial(goog.array.splice, this.values, startSplice,
    -      spliceLength).apply(null, otherMap.values);
    -};
    -
    -
    -/**
    - * Gets the value corresponding to a number from the inversion map.
    - * @param {number} intKey The number for which value needs to be retrieved
    - *     from inversion map.
    - * @return {T|null} Value retrieved from inversion map; null if not found.
    - */
    -goog.structs.InversionMap.prototype.at = function(intKey) {
    -  var index = this.getLeast(intKey);
    -  if (index < 0) {
    -    return null;
    -  }
    -  return this.values[index];
    -};
    -
    -
    -/**
    - * Gets the largest index such that rangeArray[index] <= intKey from the
    - * inversion map.
    - * @param {number} intKey The probe for which rangeArray is searched.
    - * @return {number} Largest index such that rangeArray[index] <= intKey.
    - * @protected
    - */
    -goog.structs.InversionMap.prototype.getLeast = function(intKey) {
    -  var arr = this.rangeArray;
    -  var low = 0;
    -  var high = arr.length;
    -  while (high - low > 8) {
    -    var mid = (high + low) >> 1;
    -    if (arr[mid] <= intKey) {
    -      low = mid;
    -    } else {
    -      high = mid;
    -    }
    -  }
    -  for (; low < high; ++low) {
    -    if (intKey < arr[low]) {
    -      break;
    -    }
    -  }
    -  return low - 1;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/inversionmap_test.html b/src/database/third_party/closure-library/closure/goog/structs/inversionmap_test.html
    deleted file mode 100644
    index 9ee0fe0c332..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/inversionmap_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.structs.InversionMap
    -  </title>
    -  <script type="text/javascript" src="../base.js">
    -  </script>
    -  <script type="text/javascript">
    -    goog.require('goog.structs.InversionMapTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/inversionmap_test.js b/src/database/third_party/closure-library/closure/goog/structs/inversionmap_test.js
    deleted file mode 100644
    index 32560f5b56a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/inversionmap_test.js
    +++ /dev/null
    @@ -1,154 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.structs.InversionMapTest');
    -goog.setTestOnly('goog.structs.InversionMapTest');
    -
    -goog.require('goog.structs.InversionMap');
    -goog.require('goog.testing.jsunit');
    -
    -function testInversionWithDelta() {
    -  var alphabetNames = new goog.structs.InversionMap(
    -      [0, 97, 1, 1, 1, 20, 1, 1, 1],
    -      [null,
    -        'LATIN SMALL LETTER A',
    -        'LATIN SMALL LETTER B',
    -        'LATIN SMALL LETTER C',
    -        null,
    -        'LATIN SMALL LETTER X',
    -        'LATIN SMALL LETTER Y',
    -        'LATIN SMALL LETTER Z',
    -        null],
    -      true);
    -
    -  assertEquals('LATIN SMALL LETTER A', alphabetNames.at(97));
    -  assertEquals('LATIN SMALL LETTER Y', alphabetNames.at(121));
    -  assertEquals(null, alphabetNames.at(140));
    -  assertEquals(null, alphabetNames.at(0));
    -}
    -
    -function testInversionWithoutDelta() {
    -  var alphabetNames = new goog.structs.InversionMap(
    -      [0, 97, 98, 99, 100, 120, 121, 122, 123],
    -      [null,
    -        'LATIN SMALL LETTER A',
    -        'LATIN SMALL LETTER B',
    -        'LATIN SMALL LETTER C',
    -        null,
    -        'LATIN SMALL LETTER X',
    -        'LATIN SMALL LETTER Y',
    -        'LATIN SMALL LETTER Z',
    -        null],
    -      false);
    -
    -  assertEquals('LATIN SMALL LETTER A', alphabetNames.at(97));
    -  assertEquals('LATIN SMALL LETTER Y', alphabetNames.at(121));
    -  assertEquals(null, alphabetNames.at(140));
    -  assertEquals(null, alphabetNames.at(0));
    -}
    -
    -function testInversionWithoutDeltaNoOpt() {
    -  var alphabetNames = new goog.structs.InversionMap(
    -      [0, 97, 98, 99, 100, 120, 121, 122, 123],
    -      [null,
    -        'LATIN SMALL LETTER A',
    -        'LATIN SMALL LETTER B',
    -        'LATIN SMALL LETTER C',
    -        null,
    -        'LATIN SMALL LETTER X',
    -        'LATIN SMALL LETTER Y',
    -        'LATIN SMALL LETTER Z',
    -        null]);
    -
    -  assertEquals('LATIN SMALL LETTER A', alphabetNames.at(97));
    -  assertEquals('LATIN SMALL LETTER Y', alphabetNames.at(121));
    -  assertEquals(null, alphabetNames.at(140));
    -  assertEquals(null, alphabetNames.at(0));
    -}
    -
    -function testInversionMapSplice1() {
    -  var alphabetNames = newAsciiMap();
    -  alphabetNames.spliceInversion(
    -      [99, 105, 114], ['XXX', 'YYY', 'ZZZ']);
    -  assertEquals('LATIN SMALL LETTER B', alphabetNames.at(98));
    -  assertEquals('XXX', alphabetNames.at(100));
    -  assertEquals('ZZZ', alphabetNames.at(114));
    -  assertEquals('ZZZ', alphabetNames.at(119));
    -  assertEquals('LATIN SMALL LETTER X', alphabetNames.at(120));
    -}
    -
    -function testInversionMapSplice2() {
    -  var alphabetNames = newAsciiMap();
    -  alphabetNames.spliceInversion(
    -      [105, 114, 121], ['XXX', 'YYY', 'ZZZ']);
    -  assertEquals(null, alphabetNames.at(104));
    -  assertEquals('XXX', alphabetNames.at(105));
    -  assertEquals('YYY', alphabetNames.at(120));
    -  assertEquals('ZZZ', alphabetNames.at(121));
    -  assertEquals('LATIN SMALL LETTER Z', alphabetNames.at(122));
    -}
    -
    -function testInversionMapSplice3() {
    -  var alphabetNames = newAsciiMap();
    -  alphabetNames.spliceInversion(
    -      [98, 99], ['CHANGED LETTER B', 'CHANGED LETTER C']);
    -  assertEquals('LATIN SMALL LETTER A', alphabetNames.at(97));
    -  assertEquals('CHANGED LETTER B', alphabetNames.at(98));
    -  assertEquals('CHANGED LETTER C', alphabetNames.at(99));
    -  assertEquals('LATIN SMALL LETTER D', alphabetNames.at(100));
    -  assertEquals(null, alphabetNames.at(101));
    -}
    -
    -function testInversionMapSplice4() {
    -  var alphabetNames = newAsciiMap();
    -  alphabetNames.spliceInversion(
    -      [98, 1], ['CHANGED LETTER B', 'CHANGED LETTER C'],
    -      true /* delta mode */);
    -  assertEquals('LATIN SMALL LETTER A', alphabetNames.at(97));
    -  assertEquals('CHANGED LETTER B', alphabetNames.at(98));
    -  assertEquals('CHANGED LETTER C', alphabetNames.at(99));
    -  assertEquals('LATIN SMALL LETTER D', alphabetNames.at(100));
    -  assertEquals(null, alphabetNames.at(101));
    -}
    -
    -function testInversionMapSplice5() {
    -  var map = new goog.structs.InversionMap(
    -      [0, 97, 98, 99],
    -      [null,
    -       'LATIN SMALL LETTER A',
    -       'LATIN SMALL LETTER B',
    -       'LATIN SMALL LETTER C']);
    -  map.spliceInversion(
    -      [98], ['CHANGED LETTER B']);
    -  assertEquals('LATIN SMALL LETTER A', map.at(97));
    -  assertEquals('CHANGED LETTER B', map.at(98));
    -  assertEquals('LATIN SMALL LETTER C', map.at(99));
    -
    -  assertArrayEquals([0, 97, 98, 99], map.rangeArray);
    -}
    -
    -function newAsciiMap() {
    -  return new goog.structs.InversionMap(
    -      [0, 97, 98, 99, 100, 101, 120, 121, 122, 123],
    -      [null,
    -        'LATIN SMALL LETTER A',
    -        'LATIN SMALL LETTER B',
    -        'LATIN SMALL LETTER C',
    -        'LATIN SMALL LETTER D',
    -        null,
    -        'LATIN SMALL LETTER X',
    -        'LATIN SMALL LETTER Y',
    -        'LATIN SMALL LETTER Z',
    -        null]);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/linkedmap.js b/src/database/third_party/closure-library/closure/goog/structs/linkedmap.js
    deleted file mode 100644
    index b064586ace1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/linkedmap.js
    +++ /dev/null
    @@ -1,488 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A LinkedMap data structure that is accessed using key/value
    - * pairs like an ordinary Map, but which guarantees a consistent iteration
    - * order over its entries. The iteration order is either insertion order (the
    - * default) or ordered from most recent to least recent use. By setting a fixed
    - * size, the LRU version of the LinkedMap makes an effective object cache. This
    - * data structure is similar to Java's LinkedHashMap.
    - *
    - * @author brenneman@google.com (Shawn Brenneman)
    - */
    -
    -
    -goog.provide('goog.structs.LinkedMap');
    -
    -goog.require('goog.structs.Map');
    -
    -
    -
    -/**
    - * Class for a LinkedMap datastructure, which combines O(1) map access for
    - * key/value pairs with a linked list for a consistent iteration order. Sample
    - * usage:
    - *
    - * <pre>
    - * var m = new LinkedMap();
    - * m.set('param1', 'A');
    - * m.set('param2', 'B');
    - * m.set('param3', 'C');
    - * alert(m.getKeys()); // param1, param2, param3
    - *
    - * var c = new LinkedMap(5, true);
    - * for (var i = 0; i < 10; i++) {
    - *   c.set('entry' + i, false);
    - * }
    - * alert(c.getKeys()); // entry9, entry8, entry7, entry6, entry5
    - *
    - * c.set('entry5', true);
    - * c.set('entry1', false);
    - * alert(c.getKeys()); // entry1, entry5, entry9, entry8, entry7
    - * </pre>
    - *
    - * @param {number=} opt_maxCount The maximum number of objects to store in the
    - *     LinkedMap. If unspecified or 0, there is no maximum.
    - * @param {boolean=} opt_cache When set, the LinkedMap stores items in order
    - *     from most recently used to least recently used, instead of insertion
    - *     order.
    - * @constructor
    - * @template KEY, VALUE
    - */
    -goog.structs.LinkedMap = function(opt_maxCount, opt_cache) {
    -  /**
    -   * The maximum number of entries to allow, or null if there is no limit.
    -   * @type {?number}
    -   * @private
    -   */
    -  this.maxCount_ = opt_maxCount || null;
    -
    -  /**
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.cache_ = !!opt_cache;
    -
    -  /**
    -   * @private {!goog.structs.Map<string,
    -   *     goog.structs.LinkedMap.Node_.<string, VALUE>>}
    -   */
    -  this.map_ = new goog.structs.Map();
    -
    -  this.head_ = new goog.structs.LinkedMap.Node_('', undefined);
    -  this.head_.next = this.head_.prev = this.head_;
    -};
    -
    -
    -/**
    - * Finds a node and updates it to be the most recently used.
    - * @param {string} key The key of the node.
    - * @return {goog.structs.LinkedMap.Node_} The node or null if not found.
    - * @private
    - */
    -goog.structs.LinkedMap.prototype.findAndMoveToTop_ = function(key) {
    -  var node = this.map_.get(key);
    -  if (node) {
    -    if (this.cache_) {
    -      node.remove();
    -      this.insert_(node);
    -    }
    -  }
    -  return node;
    -};
    -
    -
    -/**
    - * Retrieves the value for a given key. If this is a caching LinkedMap, the
    - * entry will become the most recently used.
    - * @param {string} key The key to retrieve the value for.
    - * @param {VALUE=} opt_val A default value that will be returned if the key is
    - *     not found, defaults to undefined.
    - * @return {VALUE} The retrieved value.
    - */
    -goog.structs.LinkedMap.prototype.get = function(key, opt_val) {
    -  var node = this.findAndMoveToTop_(key);
    -  return node ? node.value : opt_val;
    -};
    -
    -
    -/**
    - * Retrieves the value for a given key without updating the entry to be the
    - * most recently used.
    - * @param {string} key The key to retrieve the value for.
    - * @param {VALUE=} opt_val A default value that will be returned if the key is
    - *     not found.
    - * @return {VALUE} The retrieved value.
    - */
    -goog.structs.LinkedMap.prototype.peekValue = function(key, opt_val) {
    -  var node = this.map_.get(key);
    -  return node ? node.value : opt_val;
    -};
    -
    -
    -/**
    - * Sets a value for a given key. If this is a caching LinkedMap, this entry
    - * will become the most recently used.
    - * @param {string} key Key with which the specified value is to be associated.
    - * @param {VALUE} value Value to be associated with the specified key.
    - */
    -goog.structs.LinkedMap.prototype.set = function(key, value) {
    -  var node = this.findAndMoveToTop_(key);
    -  if (node) {
    -    node.value = value;
    -  } else {
    -    node = new goog.structs.LinkedMap.Node_(key, value);
    -    this.map_.set(key, node);
    -    this.insert_(node);
    -  }
    -};
    -
    -
    -/**
    - * Returns the value of the first node without making any modifications.
    - * @return {VALUE} The value of the first node or undefined if the map is empty.
    - */
    -goog.structs.LinkedMap.prototype.peek = function() {
    -  return this.head_.next.value;
    -};
    -
    -
    -/**
    - * Returns the value of the last node without making any modifications.
    - * @return {VALUE} The value of the last node or undefined if the map is empty.
    - */
    -goog.structs.LinkedMap.prototype.peekLast = function() {
    -  return this.head_.prev.value;
    -};
    -
    -
    -/**
    - * Removes the first node from the list and returns its value.
    - * @return {VALUE} The value of the popped node, or undefined if the map was
    - *     empty.
    - */
    -goog.structs.LinkedMap.prototype.shift = function() {
    -  return this.popNode_(this.head_.next);
    -};
    -
    -
    -/**
    - * Removes the last node from the list and returns its value.
    - * @return {VALUE} The value of the popped node, or undefined if the map was
    - *     empty.
    - */
    -goog.structs.LinkedMap.prototype.pop = function() {
    -  return this.popNode_(this.head_.prev);
    -};
    -
    -
    -/**
    - * Removes a value from the LinkedMap based on its key.
    - * @param {string} key The key to remove.
    - * @return {boolean} True if the entry was removed, false if the key was not
    - *     found.
    - */
    -goog.structs.LinkedMap.prototype.remove = function(key) {
    -  var node = this.map_.get(key);
    -  if (node) {
    -    this.removeNode(node);
    -    return true;
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Removes a node from the {@code LinkedMap}. It can be overridden to do
    - * further cleanup such as disposing of the node value.
    - * @param {!goog.structs.LinkedMap.Node_} node The node to remove.
    - * @protected
    - */
    -goog.structs.LinkedMap.prototype.removeNode = function(node) {
    -  node.remove();
    -  this.map_.remove(node.key);
    -};
    -
    -
    -/**
    - * @return {number} The number of items currently in the LinkedMap.
    - */
    -goog.structs.LinkedMap.prototype.getCount = function() {
    -  return this.map_.getCount();
    -};
    -
    -
    -/**
    - * @return {boolean} True if the cache is empty, false if it contains any items.
    - */
    -goog.structs.LinkedMap.prototype.isEmpty = function() {
    -  return this.map_.isEmpty();
    -};
    -
    -
    -/**
    - * Sets the maximum number of entries allowed in this object, truncating any
    - * excess objects if necessary.
    - * @param {number} maxCount The new maximum number of entries to allow.
    - */
    -goog.structs.LinkedMap.prototype.setMaxCount = function(maxCount) {
    -  this.maxCount_ = maxCount || null;
    -  if (this.maxCount_ != null) {
    -    this.truncate_(this.maxCount_);
    -  }
    -};
    -
    -
    -/**
    - * @return {!Array<string>} The list of the keys in the appropriate order for
    - *     this LinkedMap.
    - */
    -goog.structs.LinkedMap.prototype.getKeys = function() {
    -  return this.map(function(val, key) {
    -    return key;
    -  });
    -};
    -
    -
    -/**
    - * @return {!Array<VALUE>} The list of the values in the appropriate order for
    - *     this LinkedMap.
    - */
    -goog.structs.LinkedMap.prototype.getValues = function() {
    -  return this.map(function(val, key) {
    -    return val;
    -  });
    -};
    -
    -
    -/**
    - * Tests whether a provided value is currently in the LinkedMap. This does not
    - * affect item ordering in cache-style LinkedMaps.
    - * @param {VALUE} value The value to check for.
    - * @return {boolean} Whether the value is in the LinkedMap.
    - */
    -goog.structs.LinkedMap.prototype.contains = function(value) {
    -  return this.some(function(el) {
    -    return el == value;
    -  });
    -};
    -
    -
    -/**
    - * Tests whether a provided key is currently in the LinkedMap. This does not
    - * affect item ordering in cache-style LinkedMaps.
    - * @param {string} key The key to check for.
    - * @return {boolean} Whether the key is in the LinkedMap.
    - */
    -goog.structs.LinkedMap.prototype.containsKey = function(key) {
    -  return this.map_.containsKey(key);
    -};
    -
    -
    -/**
    - * Removes all entries in this object.
    - */
    -goog.structs.LinkedMap.prototype.clear = function() {
    -  this.truncate_(0);
    -};
    -
    -
    -/**
    - * Calls a function on each item in the LinkedMap.
    - *
    - * @see goog.structs.forEach
    - * @param {function(this:T, VALUE, KEY, goog.structs.LinkedMap<KEY,VALUE>)} f
    - * @param {T=} opt_obj The value of "this" inside f.
    - * @template T
    - */
    -goog.structs.LinkedMap.prototype.forEach = function(f, opt_obj) {
    -  for (var n = this.head_.next; n != this.head_; n = n.next) {
    -    f.call(opt_obj, n.value, n.key, this);
    -  }
    -};
    -
    -
    -/**
    - * Calls a function on each item in the LinkedMap and returns the results of
    - * those calls in an array.
    - *
    - * @see goog.structs.map
    - * @param {function(this:T, VALUE, KEY,
    - *         goog.structs.LinkedMap<KEY,VALUE>): RESULT} f
    - *     The function to call for each item. The function takes
    - *     three arguments: the value, the key, and the LinkedMap.
    - * @param {T=} opt_obj The object context to use as "this" for the
    - *     function.
    - * @return {!Array<RESULT>} The results of the function calls for each item in
    - *     the LinkedMap.
    - * @template T,RESULT
    - */
    -goog.structs.LinkedMap.prototype.map = function(f, opt_obj) {
    -  var rv = [];
    -  for (var n = this.head_.next; n != this.head_; n = n.next) {
    -    rv.push(f.call(opt_obj, n.value, n.key, this));
    -  }
    -  return rv;
    -};
    -
    -
    -/**
    - * Calls a function on each item in the LinkedMap and returns true if any of
    - * those function calls returns a true-like value.
    - *
    - * @see goog.structs.some
    - * @param {function(this:T, VALUE, KEY,
    - *         goog.structs.LinkedMap<KEY,VALUE>):boolean} f
    - *     The function to call for each item. The function takes
    - *     three arguments: the value, the key, and the LinkedMap, and returns a
    - *     boolean.
    - * @param {T=} opt_obj The object context to use as "this" for the
    - *     function.
    - * @return {boolean} Whether f evaluates to true for at least one item in the
    - *     LinkedMap.
    - * @template T
    - */
    -goog.structs.LinkedMap.prototype.some = function(f, opt_obj) {
    -  for (var n = this.head_.next; n != this.head_; n = n.next) {
    -    if (f.call(opt_obj, n.value, n.key, this)) {
    -      return true;
    -    }
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Calls a function on each item in the LinkedMap and returns true only if every
    - * function call returns a true-like value.
    - *
    - * @see goog.structs.some
    - * @param {function(this:T, VALUE, KEY,
    - *         goog.structs.LinkedMap<KEY,VALUE>):boolean} f
    - *     The function to call for each item. The function takes
    - *     three arguments: the value, the key, and the Cache, and returns a
    - *     boolean.
    - * @param {T=} opt_obj The object context to use as "this" for the
    - *     function.
    - * @return {boolean} Whether f evaluates to true for every item in the Cache.
    - * @template T
    - */
    -goog.structs.LinkedMap.prototype.every = function(f, opt_obj) {
    -  for (var n = this.head_.next; n != this.head_; n = n.next) {
    -    if (!f.call(opt_obj, n.value, n.key, this)) {
    -      return false;
    -    }
    -  }
    -  return true;
    -};
    -
    -
    -/**
    - * Appends a node to the list. LinkedMap in cache mode adds new nodes to
    - * the head of the list, otherwise they are appended to the tail. If there is a
    - * maximum size, the list will be truncated if necessary.
    - *
    - * @param {goog.structs.LinkedMap.Node_} node The item to insert.
    - * @private
    - */
    -goog.structs.LinkedMap.prototype.insert_ = function(node) {
    -  if (this.cache_) {
    -    node.next = this.head_.next;
    -    node.prev = this.head_;
    -
    -    this.head_.next = node;
    -    node.next.prev = node;
    -  } else {
    -    node.prev = this.head_.prev;
    -    node.next = this.head_;
    -
    -    this.head_.prev = node;
    -    node.prev.next = node;
    -  }
    -
    -  if (this.maxCount_ != null) {
    -    this.truncate_(this.maxCount_);
    -  }
    -};
    -
    -
    -/**
    - * Removes elements from the LinkedMap if the given count has been exceeded.
    - * In cache mode removes nodes from the tail of the list. Otherwise removes
    - * nodes from the head.
    - * @param {number} count Number of elements to keep.
    - * @private
    - */
    -goog.structs.LinkedMap.prototype.truncate_ = function(count) {
    -  for (var i = this.map_.getCount(); i > count; i--) {
    -    this.removeNode(this.cache_ ? this.head_.prev : this.head_.next);
    -  }
    -};
    -
    -
    -/**
    - * Removes the node from the LinkedMap if it is not the head, and returns
    - * the node's value.
    - * @param {!goog.structs.LinkedMap.Node_} node The item to remove.
    - * @return {VALUE} The value of the popped node.
    - * @private
    - */
    -goog.structs.LinkedMap.prototype.popNode_ = function(node) {
    -  if (this.head_ != node) {
    -    this.removeNode(node);
    -  }
    -  return node.value;
    -};
    -
    -
    -
    -/**
    - * Internal class for a doubly-linked list node containing a key/value pair.
    - * @param {KEY} key The key.
    - * @param {VALUE} value The value.
    - * @constructor
    - * @template KEY, VALUE
    - * @private
    - */
    -goog.structs.LinkedMap.Node_ = function(key, value) {
    -  this.key = key;
    -  this.value = value;
    -};
    -
    -
    -/**
    - * The next node in the list.
    - * @type {!goog.structs.LinkedMap.Node_}
    - */
    -goog.structs.LinkedMap.Node_.prototype.next;
    -
    -
    -/**
    - * The previous node in the list.
    - * @type {!goog.structs.LinkedMap.Node_}
    - */
    -goog.structs.LinkedMap.Node_.prototype.prev;
    -
    -
    -/**
    - * Causes this node to remove itself from the list.
    - */
    -goog.structs.LinkedMap.Node_.prototype.remove = function() {
    -  this.prev.next = this.next;
    -  this.next.prev = this.prev;
    -
    -  delete this.prev;
    -  delete this.next;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/linkedmap_test.html b/src/database/third_party/closure-library/closure/goog/structs/linkedmap_test.html
    deleted file mode 100644
    index 32332581dd9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/linkedmap_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.structs.LinkedMap
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.structs.LinkedMapTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/linkedmap_test.js b/src/database/third_party/closure-library/closure/goog/structs/linkedmap_test.js
    deleted file mode 100644
    index 29c7ce964ea..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/linkedmap_test.js
    +++ /dev/null
    @@ -1,296 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.structs.LinkedMapTest');
    -goog.setTestOnly('goog.structs.LinkedMapTest');
    -
    -goog.require('goog.structs.LinkedMap');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -
    -function fillLinkedMap(m) {
    -  m.set('a', 0);
    -  m.set('b', 1);
    -  m.set('c', 2);
    -  m.set('d', 3);
    -}
    -
    -var someObj = {};
    -
    -function testLinkedMap() {
    -  var m = new goog.structs.LinkedMap();
    -  fillLinkedMap(m);
    -
    -  assertArrayEquals(['a', 'b', 'c', 'd'], m.getKeys());
    -  assertArrayEquals([0, 1, 2, 3], m.getValues());
    -}
    -
    -function testMaxSizeLinkedMap() {
    -  var m = new goog.structs.LinkedMap(3);
    -  fillLinkedMap(m);
    -
    -  assertArrayEquals(['b', 'c', 'd'], m.getKeys());
    -  assertArrayEquals([1, 2, 3], m.getValues());
    -}
    -
    -function testLruLinkedMap() {
    -  var m = new goog.structs.LinkedMap(undefined, true);
    -  fillLinkedMap(m);
    -
    -  assertArrayEquals(['d', 'c', 'b', 'a'], m.getKeys());
    -  assertArrayEquals([3, 2, 1, 0], m.getValues());
    -
    -  m.get('a');
    -  assertArrayEquals(['a', 'd', 'c', 'b'], m.getKeys());
    -  assertArrayEquals([0, 3, 2, 1], m.getValues());
    -
    -  m.set('b', 4);
    -  assertArrayEquals(['b', 'a', 'd', 'c'], m.getKeys());
    -  assertArrayEquals([4, 0, 3, 2], m.getValues());
    -}
    -
    -function testMaxSizeLruLinkedMap() {
    -  var m = new goog.structs.LinkedMap(3, true);
    -  fillLinkedMap(m);
    -
    -  assertArrayEquals(['d', 'c', 'b'], m.getKeys());
    -  assertArrayEquals([3, 2, 1], m.getValues());
    -
    -  m.get('c');
    -  assertArrayEquals(['c', 'd', 'b'], m.getKeys());
    -  assertArrayEquals([2, 3, 1], m.getValues());
    -
    -  m.set('d', 4);
    -  assertArrayEquals(['d', 'c', 'b'], m.getKeys());
    -  assertArrayEquals([4, 2, 1], m.getValues());
    -}
    -
    -function testGetCount() {
    -  var m = new goog.structs.LinkedMap();
    -  assertEquals(0, m.getCount());
    -  m.set('a', 0);
    -  assertEquals(1, m.getCount());
    -  m.set('a', 1);
    -  assertEquals(1, m.getCount());
    -  m.set('b', 2);
    -  assertEquals(2, m.getCount());
    -  m.remove('a');
    -  assertEquals(1, m.getCount());
    -}
    -
    -function testIsEmpty() {
    -  var m = new goog.structs.LinkedMap();
    -  assertTrue(m.isEmpty());
    -  m.set('a', 0);
    -  assertFalse(m.isEmpty());
    -  m.remove('a');
    -  assertTrue(m.isEmpty());
    -}
    -
    -function testSetMaxCount() {
    -  var m = new goog.structs.LinkedMap(3);
    -  fillLinkedMap(m);
    -  assertEquals(3, m.getCount());
    -
    -  m.setMaxCount(5);
    -  m.set('e', 5);
    -  m.set('f', 6);
    -  m.set('g', 7);
    -  assertEquals(5, m.getCount());
    -
    -  m.setMaxCount(4);
    -  assertEquals(4, m.getCount());
    -
    -  m.setMaxCount(0);
    -  m.set('h', 8);
    -  m.set('i', 9);
    -  m.set('j', 10);
    -  assertEquals(7, m.getCount());
    -}
    -
    -function testClear() {
    -  var m = new goog.structs.LinkedMap();
    -  fillLinkedMap(m);
    -  m.clear();
    -  assertTrue(m.isEmpty());
    -}
    -
    -function testForEach() {
    -  var m = new goog.structs.LinkedMap();
    -  fillLinkedMap(m);
    -
    -  m.forEach(function(val, key, linkedMap) {
    -    linkedMap.set(key, val * 2);
    -    assertEquals('forEach should run in provided context.', someObj, this);
    -  }, someObj);
    -
    -  assertArrayEquals(['a', 'b', 'c', 'd'], m.getKeys());
    -  assertArrayEquals([0, 2, 4, 6], m.getValues());
    -}
    -
    -function testMap() {
    -  var m = new goog.structs.LinkedMap();
    -  fillLinkedMap(m);
    -
    -  var result = m.map(function(val, key, linkedMap) {
    -    assertEquals('The LinkedMap object should get passed in', m, linkedMap);
    -    assertEquals('map should run in provided context', someObj, this);
    -    return key + val;
    -  }, someObj);
    -
    -  assertArrayEquals(['a0', 'b1', 'c2', 'd3'], result);
    -}
    -
    -function testSome() {
    -  var m = new goog.structs.LinkedMap();
    -  fillLinkedMap(m);
    -
    -  var result = m.some(function(val, key, linkedMap) {
    -    assertEquals('The LinkedMap object should get passed in', m, linkedMap);
    -    assertEquals('map should run in provided context', someObj, this);
    -    return val > 2;
    -  }, someObj);
    -
    -  assertTrue(result);
    -  assertFalse(m.some(function(val) {return val > 3}));
    -
    -  assertTrue(m.some(function(val, key) {return key == 'c';}));
    -  assertFalse(m.some(function(val, key) {return key == 'e';}));
    -}
    -
    -function testEvery() {
    -  var m = new goog.structs.LinkedMap();
    -  fillLinkedMap(m);
    -
    -  var result = m.every(function(val, key, linkedMap) {
    -    assertEquals('The LinkedMap object should get passed in', m, linkedMap);
    -    assertEquals('map should run in provided context', someObj, this);
    -    return val < 5;
    -  }, someObj);
    -
    -  assertTrue(result);
    -  assertFalse(m.every(function(val) {return val < 2}));
    -
    -  assertTrue(m.every(function(val, key) {return key.length == 1;}));
    -  assertFalse(m.every(function(val, key) {return key == 'b';}));
    -}
    -
    -function testPeek() {
    -  var m = new goog.structs.LinkedMap();
    -  assertEquals(undefined, m.peek());
    -  assertEquals(undefined, m.peekLast());
    -
    -  fillLinkedMap(m);
    -  assertEquals(0, m.peek());
    -
    -  m.remove('a');
    -  assertEquals(1, m.peek());
    -
    -  assertEquals(3, m.peekLast());
    -
    -  assertEquals(3, m.peekValue('d'));
    -  assertEquals(1, m.peek());
    -
    -  m.remove('d');
    -  assertEquals(2, m.peekLast());
    -}
    -
    -function testPop() {
    -  var m = new goog.structs.LinkedMap();
    -  assertEquals(undefined, m.shift());
    -  assertEquals(undefined, m.pop());
    -
    -  fillLinkedMap(m);
    -  assertEquals(4, m.getCount());
    -
    -  assertEquals(0, m.shift());
    -  assertEquals(1, m.peek());
    -
    -  assertEquals(3, m.pop());
    -  assertEquals(2, m.peekLast());
    -
    -  assertEquals(2, m.getCount());
    -}
    -
    -function testContains() {
    -  var m = new goog.structs.LinkedMap();
    -  fillLinkedMap(m);
    -
    -  assertTrue(m.contains(2));
    -  assertFalse(m.contains(4));
    -}
    -
    -function testContainsKey() {
    -  var m = new goog.structs.LinkedMap();
    -  fillLinkedMap(m);
    -
    -  assertTrue(m.containsKey('b'));
    -  assertFalse(m.containsKey('elephant'));
    -  assertFalse(m.containsKey('undefined'));
    -}
    -
    -function testRemoveNodeCalls() {
    -  var m = new goog.structs.LinkedMap(1);
    -  m.removeNode = goog.testing.recordFunction(m.removeNode);
    -
    -  m.set('1', 1);
    -  assertEquals('removeNode not called after adding an element', 0,
    -      m.removeNode.getCallCount());
    -  m.set('1', 2);
    -  assertEquals('removeNode not called after updating an element', 0,
    -      m.removeNode.getCallCount());
    -  m.set('2', 2);
    -  assertEquals('removeNode called after adding an overflowing element', 1,
    -      m.removeNode.getCallCount());
    -
    -  m.remove('3');
    -  assertEquals('removeNode not called after removing a non-existing element', 1,
    -      m.removeNode.getCallCount());
    -  m.remove('2');
    -  assertEquals('removeNode called after removing an existing element', 2,
    -      m.removeNode.getCallCount());
    -
    -  m.set('1', 1);
    -  m.clear();
    -  assertEquals('removeNode called after clearing the map', 3,
    -      m.removeNode.getCallCount());
    -  m.clear();
    -  assertEquals('removeNode not called after clearing an empty map', 3,
    -      m.removeNode.getCallCount());
    -
    -  m.set('1', 1);
    -  m.pop();
    -  assertEquals('removeNode called after calling pop', 4,
    -      m.removeNode.getCallCount());
    -  m.pop();
    -  assertEquals('removeNode not called after calling pop on an empty map', 4,
    -      m.removeNode.getCallCount());
    -
    -  m.set('1', 1);
    -  m.shift();
    -  assertEquals('removeNode called after calling shift', 5,
    -      m.removeNode.getCallCount());
    -  m.shift();
    -  assertEquals('removeNode not called after calling shift on an empty map', 5,
    -      m.removeNode.getCallCount());
    -
    -  m.setMaxCount(2);
    -  m.set('1', 1);
    -  m.set('2', 2);
    -  assertEquals('removeNode not called after increasing the maximum map size', 5,
    -      m.removeNode.getCallCount());
    -  m.setMaxCount(1);
    -  assertEquals('removeNode called after decreasing the maximum map size', 6,
    -      m.removeNode.getCallCount());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/map.js b/src/database/third_party/closure-library/closure/goog/structs/map.js
    deleted file mode 100644
    index 330bb7d130a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/map.js
    +++ /dev/null
    @@ -1,460 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Datastructure: Hash Map.
    - *
    - * @author arv@google.com (Erik Arvidsson)
    - *
    - * This file contains an implementation of a Map structure. It implements a lot
    - * of the methods used in goog.structs so those functions work on hashes. This
    - * is best suited for complex key types. For simple keys such as numbers and
    - * strings, and where special names like __proto__ are not a concern, consider
    - * using the lighter-weight utilities in goog.object.
    - */
    -
    -
    -goog.provide('goog.structs.Map');
    -
    -goog.require('goog.iter.Iterator');
    -goog.require('goog.iter.StopIteration');
    -goog.require('goog.object');
    -
    -
    -
    -/**
    - * Class for Hash Map datastructure.
    - * @param {*=} opt_map Map or Object to initialize the map with.
    - * @param {...*} var_args If 2 or more arguments are present then they
    - *     will be used as key-value pairs.
    - * @constructor
    - * @template K, V
    - */
    -goog.structs.Map = function(opt_map, var_args) {
    -
    -  /**
    -   * Underlying JS object used to implement the map.
    -   * @private {!Object}
    -   */
    -  this.map_ = {};
    -
    -  /**
    -   * An array of keys. This is necessary for two reasons:
    -   *   1. Iterating the keys using for (var key in this.map_) allocates an
    -   *      object for every key in IE which is really bad for IE6 GC perf.
    -   *   2. Without a side data structure, we would need to escape all the keys
    -   *      as that would be the only way we could tell during iteration if the
    -   *      key was an internal key or a property of the object.
    -   *
    -   * This array can contain deleted keys so it's necessary to check the map
    -   * as well to see if the key is still in the map (this doesn't require a
    -   * memory allocation in IE).
    -   * @private {!Array<string>}
    -   */
    -  this.keys_ = [];
    -
    -  /**
    -   * The number of key value pairs in the map.
    -   * @private {number}
    -   */
    -  this.count_ = 0;
    -
    -  /**
    -   * Version used to detect changes while iterating.
    -   * @private {number}
    -   */
    -  this.version_ = 0;
    -
    -  var argLength = arguments.length;
    -
    -  if (argLength > 1) {
    -    if (argLength % 2) {
    -      throw Error('Uneven number of arguments');
    -    }
    -    for (var i = 0; i < argLength; i += 2) {
    -      this.set(arguments[i], arguments[i + 1]);
    -    }
    -  } else if (opt_map) {
    -    this.addAll(/** @type {Object} */ (opt_map));
    -  }
    -};
    -
    -
    -/**
    - * @return {number} The number of key-value pairs in the map.
    - */
    -goog.structs.Map.prototype.getCount = function() {
    -  return this.count_;
    -};
    -
    -
    -/**
    - * Returns the values of the map.
    - * @return {!Array<V>} The values in the map.
    - */
    -goog.structs.Map.prototype.getValues = function() {
    -  this.cleanupKeysArray_();
    -
    -  var rv = [];
    -  for (var i = 0; i < this.keys_.length; i++) {
    -    var key = this.keys_[i];
    -    rv.push(this.map_[key]);
    -  }
    -  return rv;
    -};
    -
    -
    -/**
    - * Returns the keys of the map.
    - * @return {!Array<string>} Array of string values.
    - */
    -goog.structs.Map.prototype.getKeys = function() {
    -  this.cleanupKeysArray_();
    -  return /** @type {!Array<string>} */ (this.keys_.concat());
    -};
    -
    -
    -/**
    - * Whether the map contains the given key.
    - * @param {*} key The key to check for.
    - * @return {boolean} Whether the map contains the key.
    - */
    -goog.structs.Map.prototype.containsKey = function(key) {
    -  return goog.structs.Map.hasKey_(this.map_, key);
    -};
    -
    -
    -/**
    - * Whether the map contains the given value. This is O(n).
    - * @param {V} val The value to check for.
    - * @return {boolean} Whether the map contains the value.
    - */
    -goog.structs.Map.prototype.containsValue = function(val) {
    -  for (var i = 0; i < this.keys_.length; i++) {
    -    var key = this.keys_[i];
    -    if (goog.structs.Map.hasKey_(this.map_, key) && this.map_[key] == val) {
    -      return true;
    -    }
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Whether this map is equal to the argument map.
    - * @param {goog.structs.Map} otherMap The map against which to test equality.
    - * @param {function(V, V): boolean=} opt_equalityFn Optional equality function
    - *     to test equality of values. If not specified, this will test whether
    - *     the values contained in each map are identical objects.
    - * @return {boolean} Whether the maps are equal.
    - */
    -goog.structs.Map.prototype.equals = function(otherMap, opt_equalityFn) {
    -  if (this === otherMap) {
    -    return true;
    -  }
    -
    -  if (this.count_ != otherMap.getCount()) {
    -    return false;
    -  }
    -
    -  var equalityFn = opt_equalityFn || goog.structs.Map.defaultEquals;
    -
    -  this.cleanupKeysArray_();
    -  for (var key, i = 0; key = this.keys_[i]; i++) {
    -    if (!equalityFn(this.get(key), otherMap.get(key))) {
    -      return false;
    -    }
    -  }
    -
    -  return true;
    -};
    -
    -
    -/**
    - * Default equality test for values.
    - * @param {*} a The first value.
    - * @param {*} b The second value.
    - * @return {boolean} Whether a and b reference the same object.
    - */
    -goog.structs.Map.defaultEquals = function(a, b) {
    -  return a === b;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the map is empty.
    - */
    -goog.structs.Map.prototype.isEmpty = function() {
    -  return this.count_ == 0;
    -};
    -
    -
    -/**
    - * Removes all key-value pairs from the map.
    - */
    -goog.structs.Map.prototype.clear = function() {
    -  this.map_ = {};
    -  this.keys_.length = 0;
    -  this.count_ = 0;
    -  this.version_ = 0;
    -};
    -
    -
    -/**
    - * Removes a key-value pair based on the key. This is O(logN) amortized due to
    - * updating the keys array whenever the count becomes half the size of the keys
    - * in the keys array.
    - * @param {*} key  The key to remove.
    - * @return {boolean} Whether object was removed.
    - */
    -goog.structs.Map.prototype.remove = function(key) {
    -  if (goog.structs.Map.hasKey_(this.map_, key)) {
    -    delete this.map_[key];
    -    this.count_--;
    -    this.version_++;
    -
    -    // clean up the keys array if the threshhold is hit
    -    if (this.keys_.length > 2 * this.count_) {
    -      this.cleanupKeysArray_();
    -    }
    -
    -    return true;
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Cleans up the temp keys array by removing entries that are no longer in the
    - * map.
    - * @private
    - */
    -goog.structs.Map.prototype.cleanupKeysArray_ = function() {
    -  if (this.count_ != this.keys_.length) {
    -    // First remove keys that are no longer in the map.
    -    var srcIndex = 0;
    -    var destIndex = 0;
    -    while (srcIndex < this.keys_.length) {
    -      var key = this.keys_[srcIndex];
    -      if (goog.structs.Map.hasKey_(this.map_, key)) {
    -        this.keys_[destIndex++] = key;
    -      }
    -      srcIndex++;
    -    }
    -    this.keys_.length = destIndex;
    -  }
    -
    -  if (this.count_ != this.keys_.length) {
    -    // If the count still isn't correct, that means we have duplicates. This can
    -    // happen when the same key is added and removed multiple times. Now we have
    -    // to allocate one extra Object to remove the duplicates. This could have
    -    // been done in the first pass, but in the common case, we can avoid
    -    // allocating an extra object by only doing this when necessary.
    -    var seen = {};
    -    var srcIndex = 0;
    -    var destIndex = 0;
    -    while (srcIndex < this.keys_.length) {
    -      var key = this.keys_[srcIndex];
    -      if (!(goog.structs.Map.hasKey_(seen, key))) {
    -        this.keys_[destIndex++] = key;
    -        seen[key] = 1;
    -      }
    -      srcIndex++;
    -    }
    -    this.keys_.length = destIndex;
    -  }
    -};
    -
    -
    -/**
    - * Returns the value for the given key.  If the key is not found and the default
    - * value is not given this will return {@code undefined}.
    - * @param {*} key The key to get the value for.
    - * @param {DEFAULT=} opt_val The value to return if no item is found for the
    - *     given key, defaults to undefined.
    - * @return {V|DEFAULT} The value for the given key.
    - * @template DEFAULT
    - */
    -goog.structs.Map.prototype.get = function(key, opt_val) {
    -  if (goog.structs.Map.hasKey_(this.map_, key)) {
    -    return this.map_[key];
    -  }
    -  return opt_val;
    -};
    -
    -
    -/**
    - * Adds a key-value pair to the map.
    - * @param {*} key The key.
    - * @param {V} value The value to add.
    - * @return {*} Some subclasses return a value.
    - */
    -goog.structs.Map.prototype.set = function(key, value) {
    -  if (!(goog.structs.Map.hasKey_(this.map_, key))) {
    -    this.count_++;
    -    this.keys_.push(key);
    -    // Only change the version if we add a new key.
    -    this.version_++;
    -  }
    -  this.map_[key] = value;
    -};
    -
    -
    -/**
    - * Adds multiple key-value pairs from another goog.structs.Map or Object.
    - * @param {Object} map  Object containing the data to add.
    - */
    -goog.structs.Map.prototype.addAll = function(map) {
    -  var keys, values;
    -  if (map instanceof goog.structs.Map) {
    -    keys = map.getKeys();
    -    values = map.getValues();
    -  } else {
    -    keys = goog.object.getKeys(map);
    -    values = goog.object.getValues(map);
    -  }
    -  // we could use goog.array.forEach here but I don't want to introduce that
    -  // dependency just for this.
    -  for (var i = 0; i < keys.length; i++) {
    -    this.set(keys[i], values[i]);
    -  }
    -};
    -
    -
    -/**
    - * Calls the given function on each entry in the map.
    - * @param {function(this:T, V, K, goog.structs.Map<K,V>)} f
    - * @param {T=} opt_obj The value of "this" inside f.
    - * @template T
    - */
    -goog.structs.Map.prototype.forEach = function(f, opt_obj) {
    -  var keys = this.getKeys();
    -  for (var i = 0; i < keys.length; i++) {
    -    var key = keys[i];
    -    var value = this.get(key);
    -    f.call(opt_obj, value, key, this);
    -  }
    -};
    -
    -
    -/**
    - * Clones a map and returns a new map.
    - * @return {!goog.structs.Map} A new map with the same key-value pairs.
    - */
    -goog.structs.Map.prototype.clone = function() {
    -  return new goog.structs.Map(this);
    -};
    -
    -
    -/**
    - * Returns a new map in which all the keys and values are interchanged
    - * (keys become values and values become keys). If multiple keys map to the
    - * same value, the chosen transposed value is implementation-dependent.
    - *
    - * It acts very similarly to {goog.object.transpose(Object)}.
    - *
    - * @return {!goog.structs.Map} The transposed map.
    - */
    -goog.structs.Map.prototype.transpose = function() {
    -  var transposed = new goog.structs.Map();
    -  for (var i = 0; i < this.keys_.length; i++) {
    -    var key = this.keys_[i];
    -    var value = this.map_[key];
    -    transposed.set(value, key);
    -  }
    -
    -  return transposed;
    -};
    -
    -
    -/**
    - * @return {!Object} Object representation of the map.
    - */
    -goog.structs.Map.prototype.toObject = function() {
    -  this.cleanupKeysArray_();
    -  var obj = {};
    -  for (var i = 0; i < this.keys_.length; i++) {
    -    var key = this.keys_[i];
    -    obj[key] = this.map_[key];
    -  }
    -  return obj;
    -};
    -
    -
    -/**
    - * Returns an iterator that iterates over the keys in the map.  Removal of keys
    - * while iterating might have undesired side effects.
    - * @return {!goog.iter.Iterator} An iterator over the keys in the map.
    - */
    -goog.structs.Map.prototype.getKeyIterator = function() {
    -  return this.__iterator__(true);
    -};
    -
    -
    -/**
    - * Returns an iterator that iterates over the values in the map.  Removal of
    - * keys while iterating might have undesired side effects.
    - * @return {!goog.iter.Iterator} An iterator over the values in the map.
    - */
    -goog.structs.Map.prototype.getValueIterator = function() {
    -  return this.__iterator__(false);
    -};
    -
    -
    -/**
    - * Returns an iterator that iterates over the values or the keys in the map.
    - * This throws an exception if the map was mutated since the iterator was
    - * created.
    - * @param {boolean=} opt_keys True to iterate over the keys. False to iterate
    - *     over the values.  The default value is false.
    - * @return {!goog.iter.Iterator} An iterator over the values or keys in the map.
    - */
    -goog.structs.Map.prototype.__iterator__ = function(opt_keys) {
    -  // Clean up keys to minimize the risk of iterating over dead keys.
    -  this.cleanupKeysArray_();
    -
    -  var i = 0;
    -  var keys = this.keys_;
    -  var map = this.map_;
    -  var version = this.version_;
    -  var selfObj = this;
    -
    -  var newIter = new goog.iter.Iterator;
    -  newIter.next = function() {
    -    while (true) {
    -      if (version != selfObj.version_) {
    -        throw Error('The map has changed since the iterator was created');
    -      }
    -      if (i >= keys.length) {
    -        throw goog.iter.StopIteration;
    -      }
    -      var key = keys[i++];
    -      return opt_keys ? key : map[key];
    -    }
    -  };
    -  return newIter;
    -};
    -
    -
    -/**
    - * Safe way to test for hasOwnProperty.  It even allows testing for
    - * 'hasOwnProperty'.
    - * @param {Object} obj The object to test for presence of the given key.
    - * @param {*} key The key to check for.
    - * @return {boolean} Whether the object has the key.
    - * @private
    - */
    -goog.structs.Map.hasKey_ = function(obj, key) {
    -  return Object.prototype.hasOwnProperty.call(obj, key);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/map_test.html b/src/database/third_party/closure-library/closure/goog/structs/map_test.html
    deleted file mode 100644
    index c60db95b46e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/map_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.structs.Map
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.structs.MapTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/map_test.js b/src/database/third_party/closure-library/closure/goog/structs/map_test.js
    deleted file mode 100644
    index daa8850cd75..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/map_test.js
    +++ /dev/null
    @@ -1,426 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.structs.MapTest');
    -goog.setTestOnly('goog.structs.MapTest');
    -
    -goog.require('goog.iter');
    -goog.require('goog.structs');
    -goog.require('goog.structs.Map');
    -goog.require('goog.testing.jsunit');
    -
    -function stringifyMap(m) {
    -  var keys = goog.structs.getKeys(m);
    -  var s = '';
    -  for (var i = 0; i < keys.length; i++) {
    -    s += keys[i] + m[keys[i]];
    -  }
    -  return s;
    -}
    -
    -function getMap() {
    -  var m = new goog.structs.Map;
    -  m.set('a', 0);
    -  m.set('b', 1);
    -  m.set('c', 2);
    -  m.set('d', 3);
    -  return m;
    -}
    -
    -function testGetCount() {
    -  var m = getMap();
    -  assertEquals('count, should be 4', m.getCount(), 4);
    -  m.remove('d');
    -  assertEquals('count, should be 3', m.getCount(), 3);
    -}
    -
    -function testKeys() {
    -  var m = getMap();
    -  assertEquals('getKeys, The keys should be a,b,c', m.getKeys().join(','),
    -      'a,b,c,d');
    -}
    -
    -function testValues() {
    -  var m = getMap();
    -  assertEquals('getValues, The values should be 0,1,2',
    -      m.getValues().join(','), '0,1,2,3');
    -}
    -
    -function testContainsKey() {
    -  var m = getMap();
    -  assertTrue("containsKey, Should contain the 'a' key", m.containsKey('a'));
    -  assertFalse("containsKey, Should not contain the 'e' key",
    -      m.containsKey('e'));
    -}
    -
    -function testClear() {
    -  var m = getMap();
    -  m.clear();
    -  assertTrue('cleared so it should be empty', m.isEmpty());
    -  assertTrue("cleared so it should not contain 'a' key", !m.containsKey('a'));
    -}
    -
    -function testAddAll() {
    -  var m = new goog.structs.Map;
    -  m.addAll({a: 0, b: 1, c: 2, d: 3});
    -  assertTrue('addAll so it should not be empty', !m.isEmpty());
    -  assertTrue("addAll so it should contain 'c' key", m.containsKey('c'));
    -
    -  var m2 = new goog.structs.Map;
    -  m2.addAll(m);
    -  assertTrue('addAll so it should not be empty', !m2.isEmpty());
    -  assertTrue("addAll so it should contain 'c' key", m2.containsKey('c'));
    -}
    -
    -function testConstructor() {
    -  var m = getMap();
    -  var m2 = new goog.structs.Map(m);
    -  assertTrue('constr with Map so it should not be empty', !m2.isEmpty());
    -  assertTrue("constr with Map so it should contain 'c' key",
    -      m2.containsKey('c'));
    -}
    -
    -
    -function testConstructorWithVarArgs() {
    -  var m = new goog.structs.Map('a', 1);
    -  assertTrue('constr with var_args so it should not be empty', !m.isEmpty());
    -  assertEquals('constr with var_args', 1, m.get('a'));
    -
    -  m = new goog.structs.Map('a', 1, 'b', 2);
    -  assertTrue('constr with var_args so it should not be empty', !m.isEmpty());
    -  assertEquals('constr with var_args', 1, m.get('a'));
    -  assertEquals('constr with var_args', 2, m.get('b'));
    -
    -  assertThrows('Odd number of arguments is not allowed', function() {
    -    var m = new goog.structs.Map('a', 1, 'b');
    -  });
    -}
    -
    -function testClone() {
    -  var m = getMap();
    -  var m2 = m.clone();
    -  assertTrue('clone so it should not be empty', !m2.isEmpty());
    -  assertTrue("clone so it should contain 'c' key", m2.containsKey('c'));
    -}
    -
    -
    -function testRemove() {
    -  var m = new goog.structs.Map();
    -  for (var i = 0; i < 1000; i++) {
    -    m.set(i, 'foo');
    -  }
    -
    -  for (var i = 0; i < 1000; i++) {
    -    assertTrue(m.keys_.length <= 2 * m.getCount());
    -    m.remove(i);
    -  }
    -  assertTrue(m.isEmpty());
    -  assertEquals('', m.getKeys().join(''));
    -}
    -
    -
    -function testForEach() {
    -  var m = getMap();
    -  var s = '';
    -  goog.structs.forEach(m, function(val, key, m2) {
    -    assertNotUndefined(key);
    -    assertEquals(m, m2);
    -    s += key + val;
    -  });
    -  assertEquals(s, 'a0b1c2d3');
    -}
    -
    -function testFilter() {
    -  var m = getMap();
    -
    -  var m2 = goog.structs.filter(m, function(val, key, m3) {
    -    assertNotUndefined(key);
    -    assertEquals(m, m3);
    -    return val > 1;
    -  });
    -  assertEquals(stringifyMap(m2), 'c2d3');
    -}
    -
    -
    -function testMap() {
    -  var m = getMap();
    -  var m2 = goog.structs.map(m, function(val, key, m3) {
    -    assertNotUndefined(key);
    -    assertEquals(m, m3);
    -    return val * val;
    -  });
    -  assertEquals(stringifyMap(m2), 'a0b1c4d9');
    -}
    -
    -function testSome() {
    -  var m = getMap();
    -  var b = goog.structs.some(m, function(val, key, m2) {
    -    assertNotUndefined(key);
    -    assertEquals(m, m2);
    -    return val > 1;
    -  });
    -  assertTrue(b);
    -  var b = goog.structs.some(m, function(val, key, m2) {
    -    assertNotUndefined(key);
    -    assertEquals(m, m2);
    -    return val > 100;
    -  });
    -  assertFalse(b);
    -}
    -
    -function testEvery() {
    -  var m = getMap();
    -  var b = goog.structs.every(m, function(val, key, m2) {
    -    assertNotUndefined(key);
    -    assertEquals(m, m2);
    -    return val >= 0;
    -  });
    -  assertTrue(b);
    -  b = goog.structs.every(m, function(val, key, m2) {
    -    assertNotUndefined(key);
    -    assertEquals(m, m2);
    -    return val > 1;
    -  });
    -  assertFalse(b);
    -}
    -
    -function testContainsValue() {
    -  var m = getMap();
    -  assertTrue(m.containsValue(3));
    -  assertFalse(m.containsValue(4));
    -}
    -
    -function testObjectProperties() {
    -  var m = new goog.structs.Map;
    -
    -  assertEquals(m.get('toString'), undefined);
    -  assertEquals(m.get('valueOf'), undefined);
    -  assertEquals(m.get('eval'), undefined);
    -  assertEquals(m.get('toSource'), undefined);
    -  assertEquals(m.get('prototype'), undefined);
    -  assertEquals(m.get(':foo'), undefined);
    -
    -  m.set('toString', 'once');
    -  m.set('valueOf', 'upon');
    -  m.set('eval', 'a');
    -  m.set('toSource', 'midnight');
    -  m.set('prototype', 'dreary');
    -  m.set('hasOwnProperty', 'dark');
    -  m.set(':foo', 'happy');
    -
    -  assertEquals(m.get('toString'), 'once');
    -  assertEquals(m.get('valueOf'), 'upon');
    -  assertEquals(m.get('eval'), 'a');
    -  assertEquals(m.get('toSource'), 'midnight');
    -  assertEquals(m.get('prototype'), 'dreary');
    -  assertEquals(m.get('hasOwnProperty'), 'dark');
    -  assertEquals(m.get(':foo'), 'happy');
    -
    -  var keys = m.getKeys().join(',');
    -  assertEquals(keys,
    -      'toString,valueOf,eval,toSource,prototype,hasOwnProperty,:foo');
    -
    -  var values = m.getValues().join(',');
    -  assertEquals(values, 'once,upon,a,midnight,dreary,dark,happy');
    -}
    -
    -function testDuplicateKeys() {
    -  var m = new goog.structs.Map;
    -
    -  m.set('a', 1);
    -  m.set('b', 2);
    -  m.set('c', 3);
    -  m.set('d', 4);
    -  m.set('e', 5);
    -  m.set('f', 6);
    -  assertEquals(6, m.getKeys().length);
    -  m.set('foo', 1);
    -  assertEquals(7, m.getKeys().length);
    -  m.remove('foo');
    -  assertEquals(6, m.getKeys().length);
    -  m.set('foo', 2);
    -  assertEquals(7, m.getKeys().length);
    -  m.remove('foo');
    -  m.set('foo', 3);
    -  m.remove('foo');
    -  m.set('foo', 4);
    -  assertEquals(7, m.getKeys().length);
    -}
    -
    -function testGetKeyIterator() {
    -  var m = new goog.structs.Map;
    -  m.set('a', 1);
    -  m.set('b', 2);
    -  m.set('c', 3);
    -  m.set('d', 4);
    -  m.set('e', 5);
    -
    -  var iter = m.getKeyIterator();
    -  assertEquals('Should contain the keys', 'abcde', goog.iter.join(iter, ''));
    -
    -  m.remove('b');
    -  m.remove('d');
    -  iter = m.getKeyIterator();
    -  assertEquals('Should not contain the removed keys',
    -               'ace', goog.iter.join(iter, ''));
    -}
    -
    -function testGetValueIterator() {
    -  var m = new goog.structs.Map;
    -  m.set('a', 1);
    -  m.set('b', 2);
    -  m.set('c', 3);
    -  m.set('d', 4);
    -  m.set('e', 5);
    -
    -  var iter = m.getValueIterator();
    -  assertEquals('Should contain the values', '12345', goog.iter.join(iter, ''));
    -
    -  m.remove('b');
    -  m.remove('d');
    -  iter = m.getValueIterator();
    -  assertEquals('Should not contain the removed keys',
    -               '135', goog.iter.join(iter, ''));
    -}
    -
    -function testDefaultIterator() {
    -  // The default iterator should behave like the value iterator
    -
    -  var m = new goog.structs.Map;
    -  m.set('a', 1);
    -  m.set('b', 2);
    -  m.set('c', 3);
    -  m.set('d', 4);
    -  m.set('e', 5);
    -
    -  assertEquals('Should contain the values', '12345', goog.iter.join(m, ''));
    -
    -  m.remove('b');
    -  m.remove('d');
    -  assertEquals('Should not contain the removed keys',
    -               '135', goog.iter.join(m, ''));
    -}
    -
    -function testMutatedIterator() {
    -  var message = 'The map has changed since the iterator was created';
    -
    -  var m = new goog.structs.Map;
    -  m.set('a', 1);
    -  m.set('b', 2);
    -  m.set('c', 3);
    -  m.set('d', 4);
    -
    -  var iter = m.getValueIterator();
    -  m.set('e', 5);
    -  var ex = assertThrows('Expected an exception since the map has changed',
    -      function() {
    -        iter.next();
    -      });
    -  assertEquals(message, ex.message);
    -
    -  m = new goog.structs.Map;
    -  m.set('a', 1);
    -  m.set('b', 2);
    -  m.set('c', 3);
    -  m.set('d', 4);
    -
    -  iter = m.getValueIterator();
    -  m.remove('d');
    -  var ex = assertThrows('Expected an exception since the map has changed',
    -      function() {
    -        iter.next();
    -      });
    -  assertEquals(message, ex.message);
    -
    -  m = new goog.structs.Map;
    -  m.set('a', 1);
    -  m.set('b', 2);
    -  m.set('c', 3);
    -  m.set('d', 4);
    -
    -  iter = m.getValueIterator();
    -  m.set('d', 5);
    -  iter.next();
    -  // Changing an existing value is OK.
    -  iter.next();
    -}
    -
    -function testTranspose() {
    -  var m = new goog.structs.Map;
    -  m.set('a', 1);
    -  m.set('b', 2);
    -  m.set('c', 3);
    -  m.set('d', 4);
    -  m.set('e', 5);
    -
    -  var transposed = m.transpose();
    -  assertEquals('Should contain the keys', 'abcde',
    -      goog.iter.join(transposed, ''));
    -}
    -
    -function testToObject() {
    -  Object.prototype.b = 0;
    -  try {
    -    var map = new goog.structs.Map();
    -    map.set('a', 0);
    -    var obj = map.toObject();
    -    assertTrue('object representation has key "a"', obj.hasOwnProperty('a'));
    -    assertFalse('object representation does not have key "b"',
    -        obj.hasOwnProperty('b'));
    -    assertEquals('value for key "a"', 0, obj['a']);
    -  } finally {
    -    delete Object.prototype.b;
    -  }
    -}
    -
    -function testEqualsWithSameObject() {
    -  var map1 = getMap();
    -  assertTrue('maps are the same object', map1.equals(map1));
    -}
    -
    -function testEqualsWithDifferentSizeMaps() {
    -  var map1 = getMap();
    -  var map2 = new goog.structs.Map();
    -
    -  assertFalse('maps are different sizes', map1.equals(map2));
    -}
    -
    -function testEqualsWithDefaultEqualityFn() {
    -  var map1 = new goog.structs.Map();
    -  var map2 = new goog.structs.Map();
    -
    -  assertTrue('maps are both empty', map1.equals(map2));
    -
    -  map1 = getMap();
    -  map2 = getMap();
    -  assertTrue('maps are the same', map1.equals(map2));
    -
    -  map2.set('d', '3');
    -  assertFalse('maps have 3 and \'3\'', map1.equals(map2));
    -}
    -
    -function testEqualsWithCustomEqualityFn() {
    -  var map1 = new goog.structs.Map();
    -  var map2 = new goog.structs.Map();
    -
    -  map1.set('a', 0);
    -  map1.set('b', 1);
    -
    -  map2.set('a', '0');
    -  map2.set('b', '1');
    -
    -  var equalsFn = function(a, b) { return a == b };
    -
    -  assertTrue('maps are equal with ==', map1.equals(map2, equalsFn));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/node.js b/src/database/third_party/closure-library/closure/goog/structs/node.js
    deleted file mode 100644
    index 3e1d1acfc89..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/node.js
    +++ /dev/null
    @@ -1,73 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Generic immutable node object to be used in collections.
    - *
    - */
    -
    -
    -goog.provide('goog.structs.Node');
    -
    -
    -
    -/**
    - * A generic immutable node. This can be used in various collections that
    - * require a node object for its item (such as a heap).
    - * @param {K} key Key.
    - * @param {V} value Value.
    - * @constructor
    - * @template K, V
    - */
    -goog.structs.Node = function(key, value) {
    -  /**
    -   * The key.
    -   * @private {K}
    -   */
    -  this.key_ = key;
    -
    -  /**
    -   * The value.
    -   * @private {V}
    -   */
    -  this.value_ = value;
    -};
    -
    -
    -/**
    - * Gets the key.
    - * @return {K} The key.
    - */
    -goog.structs.Node.prototype.getKey = function() {
    -  return this.key_;
    -};
    -
    -
    -/**
    - * Gets the value.
    - * @return {V} The value.
    - */
    -goog.structs.Node.prototype.getValue = function() {
    -  return this.value_;
    -};
    -
    -
    -/**
    - * Clones a node and returns a new node.
    - * @return {!goog.structs.Node<K, V>} A new goog.structs.Node with the same
    - *     key value pair.
    - */
    -goog.structs.Node.prototype.clone = function() {
    -  return new goog.structs.Node(this.key_, this.value_);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/pool.js b/src/database/third_party/closure-library/closure/goog/structs/pool.js
    deleted file mode 100644
    index 5b6e4ccdc27..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/pool.js
    +++ /dev/null
    @@ -1,376 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Datastructure: Pool.
    - *
    - *
    - * A generic class for handling pools of objects.
    - * When an object is released, it is attempted to be reused.
    - */
    -
    -
    -goog.provide('goog.structs.Pool');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.structs.Queue');
    -goog.require('goog.structs.Set');
    -
    -
    -
    -/**
    - * A generic pool class. If min is greater than max, an error is thrown.
    - * @param {number=} opt_minCount Min. number of objects (Default: 1).
    - * @param {number=} opt_maxCount Max. number of objects (Default: 10).
    - * @constructor
    - * @extends {goog.Disposable}
    - * @template T
    - */
    -goog.structs.Pool = function(opt_minCount, opt_maxCount) {
    -  goog.Disposable.call(this);
    -
    -  /**
    -   * Minimum number of objects allowed
    -   * @private {number}
    -   */
    -  this.minCount_ = opt_minCount || 0;
    -
    -  /**
    -   * Maximum number of objects allowed
    -   * @private {number}
    -   */
    -  this.maxCount_ = opt_maxCount || 10;
    -
    -  // Make sure that the max and min constraints are valid.
    -  if (this.minCount_ > this.maxCount_) {
    -    throw Error(goog.structs.Pool.ERROR_MIN_MAX_);
    -  }
    -
    -  /**
    -   * Set used to store objects that are currently in the pool and available
    -   * to be used.
    -   * @private {goog.structs.Queue<T>}
    -   */
    -  this.freeQueue_ = new goog.structs.Queue();
    -
    -  /**
    -   * Set used to store objects that are currently in the pool and in use.
    -   * @private {goog.structs.Set<T>}
    -   */
    -  this.inUseSet_ = new goog.structs.Set();
    -
    -  /**
    -   * The minimum delay between objects being made available, in milliseconds. If
    -   * this is 0, no minimum delay is enforced.
    -   * @protected {number}
    -   */
    -  this.delay = 0;
    -
    -  /**
    -   * The time of the last object being made available, in milliseconds since the
    -   * epoch (i.e., the result of Date#toTime). If this is null, no access has
    -   * occurred yet.
    -   * @protected {number?}
    -   */
    -  this.lastAccess = null;
    -
    -  // Make sure that the minCount constraint is satisfied.
    -  this.adjustForMinMax();
    -
    -
    -  // TODO(user): Remove once JSCompiler's undefined properties warnings
    -  // don't error for guarded properties.
    -  var magicProps = {canBeReused: 0};
    -};
    -goog.inherits(goog.structs.Pool, goog.Disposable);
    -
    -
    -/**
    - * Error to throw when the max/min constraint is attempted to be invalidated.
    - * I.e., when it is attempted for maxCount to be less than minCount.
    - * @type {string}
    - * @private
    - */
    -goog.structs.Pool.ERROR_MIN_MAX_ =
    -    '[goog.structs.Pool] Min can not be greater than max';
    -
    -
    -/**
    - * Error to throw when the Pool is attempted to be disposed and it is asked to
    - * make sure that there are no objects that are in use (i.e., haven't been
    - * released).
    - * @type {string}
    - * @private
    - */
    -goog.structs.Pool.ERROR_DISPOSE_UNRELEASED_OBJS_ =
    -    '[goog.structs.Pool] Objects not released';
    -
    -
    -/**
    - * Sets the minimum count of the pool.
    - * If min is greater than the max count of the pool, an error is thrown.
    - * @param {number} min The minimum count of the pool.
    - */
    -goog.structs.Pool.prototype.setMinimumCount = function(min) {
    -  // Check count constraints.
    -  if (min > this.maxCount_) {
    -    throw Error(goog.structs.Pool.ERROR_MIN_MAX_);
    -  }
    -  this.minCount_ = min;
    -
    -  // Adjust the objects in the pool as needed.
    -  this.adjustForMinMax();
    -};
    -
    -
    -/**
    - * Sets the maximum count of the pool.
    - * If max is less than the max count of the pool, an error is thrown.
    - * @param {number} max The maximum count of the pool.
    - */
    -goog.structs.Pool.prototype.setMaximumCount = function(max) {
    -  // Check count constraints.
    -  if (max < this.minCount_) {
    -    throw Error(goog.structs.Pool.ERROR_MIN_MAX_);
    -  }
    -  this.maxCount_ = max;
    -
    -  // Adjust the objects in the pool as needed.
    -  this.adjustForMinMax();
    -};
    -
    -
    -/**
    - * Sets the minimum delay between objects being returned by getObject, in
    - * milliseconds. This defaults to zero, meaning that no minimum delay is
    - * enforced and objects may be used as soon as they're available.
    - * @param {number} delay The minimum delay, in milliseconds.
    - */
    -goog.structs.Pool.prototype.setDelay = function(delay) {
    -  this.delay = delay;
    -};
    -
    -
    -/**
    - * @return {T|undefined} A new object from the pool if there is one available,
    - *     otherwise undefined.
    - */
    -goog.structs.Pool.prototype.getObject = function() {
    -  var time = goog.now();
    -  if (goog.isDefAndNotNull(this.lastAccess) &&
    -      time - this.lastAccess < this.delay) {
    -    return undefined;
    -  }
    -
    -  var obj = this.removeFreeObject_();
    -  if (obj) {
    -    this.lastAccess = time;
    -    this.inUseSet_.add(obj);
    -  }
    -
    -  return obj;
    -};
    -
    -
    -/**
    - * Returns an object to the pool of available objects so that it can be reused.
    - * @param {T} obj The object to return to the pool of free objects.
    - * @return {boolean} Whether the object was found in the Pool's set of in-use
    - *     objects (in other words, whether any action was taken).
    - */
    -goog.structs.Pool.prototype.releaseObject = function(obj) {
    -  if (this.inUseSet_.remove(obj)) {
    -    this.addFreeObject(obj);
    -    return true;
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Removes a free object from the collection of objects that are free so that it
    - * can be used.
    - *
    - * NOTE: This method does not mark the returned object as in use.
    - *
    - * @return {T|undefined} The object removed from the free collection, if there
    - *     is one available. Otherwise, undefined.
    - * @private
    - */
    -goog.structs.Pool.prototype.removeFreeObject_ = function() {
    -  var obj;
    -  while (this.getFreeCount() > 0) {
    -    obj = this.freeQueue_.dequeue();
    -
    -    if (!this.objectCanBeReused(obj)) {
    -      this.adjustForMinMax();
    -    } else {
    -      break;
    -    }
    -  }
    -
    -  if (!obj && this.getCount() < this.maxCount_) {
    -    obj = this.createObject();
    -  }
    -
    -  return obj;
    -};
    -
    -
    -/**
    - * Adds an object to the collection of objects that are free. If the object can
    - * not be added, then it is disposed.
    - *
    - * @param {T} obj The object to add to collection of free objects.
    - */
    -goog.structs.Pool.prototype.addFreeObject = function(obj) {
    -  this.inUseSet_.remove(obj);
    -  if (this.objectCanBeReused(obj) && this.getCount() < this.maxCount_) {
    -    this.freeQueue_.enqueue(obj);
    -  } else {
    -    this.disposeObject(obj);
    -  }
    -};
    -
    -
    -/**
    - * Adjusts the objects held in the pool to be within the min/max constraints.
    - *
    - * NOTE: It is possible that the number of objects in the pool will still be
    - * greater than the maximum count of objects allowed. This will be the case
    - * if no more free objects can be disposed of to get below the minimum count
    - * (i.e., all objects are in use).
    - */
    -goog.structs.Pool.prototype.adjustForMinMax = function() {
    -  var freeQueue = this.freeQueue_;
    -
    -  // Make sure the at least the minimum number of objects are created.
    -  while (this.getCount() < this.minCount_) {
    -    freeQueue.enqueue(this.createObject());
    -  }
    -
    -  // Make sure no more than the maximum number of objects are created.
    -  while (this.getCount() > this.maxCount_ && this.getFreeCount() > 0) {
    -    this.disposeObject(freeQueue.dequeue());
    -  }
    -};
    -
    -
    -/**
    - * Should be overridden by sub-classes to return an instance of the object type
    - * that is expected in the pool.
    - * @return {T} The created object.
    - */
    -goog.structs.Pool.prototype.createObject = function() {
    -  return {};
    -};
    -
    -
    -/**
    - * Should be overridden to dispose of an object. Default implementation is to
    - * remove all its members, which should render it useless. Calls the object's
    - * {@code dispose()} method, if available.
    - * @param {T} obj The object to dispose.
    - */
    -goog.structs.Pool.prototype.disposeObject = function(obj) {
    -  if (typeof obj.dispose == 'function') {
    -    obj.dispose();
    -  } else {
    -    for (var i in obj) {
    -      obj[i] = null;
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Should be overridden to determine whether an object has become unusable and
    - * should not be returned by getObject(). Calls the object's
    - * {@code canBeReused()}  method, if available.
    - * @param {T} obj The object to test.
    - * @return {boolean} Whether the object can be reused.
    - */
    -goog.structs.Pool.prototype.objectCanBeReused = function(obj) {
    -  if (typeof obj.canBeReused == 'function') {
    -    return obj.canBeReused();
    -  }
    -  return true;
    -};
    -
    -
    -/**
    - * Returns true if the given object is in the pool.
    - * @param {T} obj The object to check the pool for.
    - * @return {boolean} Whether the pool contains the object.
    - */
    -goog.structs.Pool.prototype.contains = function(obj) {
    -  return this.freeQueue_.contains(obj) || this.inUseSet_.contains(obj);
    -};
    -
    -
    -/**
    - * Returns the number of objects currently in the pool.
    - * @return {number} Number of objects currently in the pool.
    - */
    -goog.structs.Pool.prototype.getCount = function() {
    -  return this.freeQueue_.getCount() + this.inUseSet_.getCount();
    -};
    -
    -
    -/**
    - * Returns the number of objects currently in use in the pool.
    - * @return {number} Number of objects currently in use in the pool.
    - */
    -goog.structs.Pool.prototype.getInUseCount = function() {
    -  return this.inUseSet_.getCount();
    -};
    -
    -
    -/**
    - * Returns the number of objects currently free in the pool.
    - * @return {number} Number of objects currently free in the pool.
    - */
    -goog.structs.Pool.prototype.getFreeCount = function() {
    -  return this.freeQueue_.getCount();
    -};
    -
    -
    -/**
    - * Determines if the pool contains no objects.
    - * @return {boolean} Whether the pool contains no objects.
    - */
    -goog.structs.Pool.prototype.isEmpty = function() {
    -  return this.freeQueue_.isEmpty() && this.inUseSet_.isEmpty();
    -};
    -
    -
    -/**
    - * Disposes of the pool and all objects currently held in the pool.
    - * @override
    - * @protected
    - */
    -goog.structs.Pool.prototype.disposeInternal = function() {
    -  goog.structs.Pool.superClass_.disposeInternal.call(this);
    -  if (this.getInUseCount() > 0) {
    -    throw Error(goog.structs.Pool.ERROR_DISPOSE_UNRELEASED_OBJS_);
    -  }
    -  delete this.inUseSet_;
    -
    -  // Call disposeObject on each object held by the pool.
    -  var freeQueue = this.freeQueue_;
    -  while (!freeQueue.isEmpty()) {
    -    this.disposeObject(freeQueue.dequeue());
    -  }
    -  delete this.freeQueue_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/pool_test.html b/src/database/third_party/closure-library/closure/goog/structs/pool_test.html
    deleted file mode 100644
    index 439845870b4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/pool_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.structs.Pool
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.structs.PoolTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/pool_test.js b/src/database/third_party/closure-library/closure/goog/structs/pool_test.js
    deleted file mode 100644
    index c1b055800a7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/pool_test.js
    +++ /dev/null
    @@ -1,285 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.structs.PoolTest');
    -goog.setTestOnly('goog.structs.PoolTest');
    -
    -goog.require('goog.structs.Pool');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.jsunit');
    -
    -// Implementation of the Pool class with isObjectDead() always returning TRUE,
    -// so that the the Pool will not reuse any objects.
    -function NoObjectReusePool(opt_min, opt_max) {
    -  goog.structs.Pool.call(this, opt_min, opt_max);
    -}
    -goog.inherits(NoObjectReusePool, goog.structs.Pool);
    -
    -NoObjectReusePool.prototype.objectCanBeReused = function(obj) {
    -  return false;
    -};
    -
    -
    -function testExceedMax1() {
    -  var p = new goog.structs.Pool(0, 3);
    -  var obj1 = p.getObject();
    -  var obj2 = p.getObject();
    -  var obj3 = p.getObject();
    -  var obj4 = p.getObject();
    -  var obj5 = p.getObject();
    -
    -  assertNotUndefined(obj1);
    -  assertNotUndefined(obj2);
    -  assertNotUndefined(obj3);
    -  assertUndefined(obj4);
    -  assertUndefined(obj5);
    -}
    -
    -
    -function testExceedMax2() {
    -  var p = new goog.structs.Pool(0, 1);
    -  var obj1 = p.getObject();
    -  var obj2 = p.getObject();
    -  var obj3 = p.getObject();
    -  var obj4 = p.getObject();
    -  var obj5 = p.getObject();
    -
    -  assertNotUndefined(obj1);
    -  assertUndefined(obj2);
    -  assertUndefined(obj3);
    -  assertUndefined(obj4);
    -  assertUndefined(obj5);
    -}
    -
    -
    -function testExceedMax3() {
    -  var p = new goog.structs.Pool(); // default: 10
    -  var objs = [];
    -
    -  for (var i = 0; i < 12; i++) {
    -    objs[i] = p.getObject();
    -  }
    -
    -  for (var i = 0; i < 10; i++) {
    -    assertNotNull('First 10 should be not null', objs[i]);
    -  }
    -
    -  assertUndefined(objs[10]);
    -  assertUndefined(objs[11]);
    -}
    -
    -
    -function testReleaseAndGet1() {
    -  var p = new goog.structs.Pool(0, 10);
    -  var o = p.getObject();
    -  assertEquals(1, p.getCount());
    -  assertEquals(1, p.getInUseCount());
    -  assertEquals(0, p.getFreeCount());
    -  assertTrue('Result should be true', p.releaseObject(o));
    -  assertEquals(1, p.getCount());
    -  assertEquals(0, p.getInUseCount());
    -  assertEquals(1, p.getFreeCount());
    -}
    -
    -
    -function testReleaseAndGet2() {
    -  var p = new NoObjectReusePool(0, 10);
    -  var o = p.getObject();
    -  assertEquals(1, p.getCount());
    -  assertEquals(1, p.getInUseCount());
    -  assertEquals(0, p.getFreeCount());
    -  assertTrue('Result should be true', p.releaseObject(o));
    -  assertEquals(0, p.getCount());
    -  assertEquals(0, p.getInUseCount());
    -  assertEquals(0, p.getFreeCount());
    -}
    -
    -
    -function testReleaseAndGet3() {
    -  var p = new goog.structs.Pool(0, 10);
    -  var o1 = p.getObject();
    -  var o2 = p.getObject();
    -  var o3 = p.getObject();
    -  var o4 = {};
    -  assertEquals(3, p.getCount());
    -  assertEquals(3, p.getInUseCount());
    -  assertEquals(0, p.getFreeCount());
    -  assertTrue('Result should be true', p.releaseObject(o1));
    -  assertTrue('Result should be true', p.releaseObject(o2));
    -  assertFalse('Result should be false', p.releaseObject(o4));
    -  assertEquals(3, p.getCount());
    -  assertEquals(1, p.getInUseCount());
    -  assertEquals(2, p.getFreeCount());
    -}
    -
    -
    -function testReleaseAndGet4() {
    -  var p = new NoObjectReusePool(0, 10);
    -  var o1 = p.getObject();
    -  var o2 = p.getObject();
    -  var o3 = p.getObject();
    -  var o4 = {};
    -  assertEquals(3, p.getCount());
    -  assertEquals(3, p.getInUseCount());
    -  assertEquals(0, p.getFreeCount());
    -  assertTrue('Result should be true', p.releaseObject(o1));
    -  assertTrue('Result should be true', p.releaseObject(o2));
    -  assertFalse('Result should be false', p.releaseObject(o4));
    -  assertEquals(1, p.getCount());
    -  assertEquals(1, p.getInUseCount());
    -  assertEquals(0, p.getFreeCount());
    -}
    -
    -
    -function testIsInPool1() {
    -  var p = new goog.structs.Pool();
    -  var o1 = p.getObject();
    -  var o2 = p.getObject();
    -  var o3 = p.getObject();
    -  var o4 = {};
    -  var o5 = {};
    -  var o6 = o1;
    -
    -  assertTrue(p.contains(o1));
    -  assertTrue(p.contains(o2));
    -  assertTrue(p.contains(o3));
    -  assertFalse(p.contains(o4));
    -  assertFalse(p.contains(o5));
    -  assertTrue(p.contains(o6));
    -}
    -
    -
    -function testSetMin1() {
    -  var p = new goog.structs.Pool(0, 10);
    -
    -  assertEquals(0, p.getCount());
    -  assertEquals(0, p.getInUseCount());
    -  assertEquals(0, p.getFreeCount());
    -
    -  p.setMinimumCount(10);
    -
    -  assertEquals(10, p.getCount());
    -  assertEquals(0, p.getInUseCount());
    -  assertEquals(10, p.getFreeCount());
    -}
    -
    -
    -function testSetMin2() {
    -  var p = new goog.structs.Pool(0, 10);
    -
    -  assertEquals(0, p.getCount());
    -  assertEquals(0, p.getInUseCount());
    -  assertEquals(0, p.getFreeCount());
    -
    -  var o1 = p.getObject();
    -
    -  assertEquals(1, p.getCount());
    -  assertEquals(1, p.getInUseCount());
    -  assertEquals(0, p.getFreeCount());
    -
    -  p.setMinimumCount(10);
    -
    -  assertEquals(10, p.getCount());
    -  assertEquals(1, p.getInUseCount());
    -  assertEquals(9, p.getFreeCount());
    -}
    -
    -
    -function testSetMax1() {
    -  var p = new goog.structs.Pool(0, 10);
    -
    -  assertEquals(0, p.getCount());
    -  assertEquals(0, p.getInUseCount());
    -  assertEquals(0, p.getFreeCount());
    -
    -  var o1 = p.getObject();
    -  var o2 = p.getObject();
    -  var o3 = p.getObject();
    -  var o4 = p.getObject();
    -  var o5 = p.getObject();
    -
    -  assertEquals(5, p.getCount());
    -  assertEquals(5, p.getInUseCount());
    -  assertEquals(0, p.getFreeCount());
    -
    -  assertTrue('Result should be true', p.releaseObject(o5));
    -
    -  assertEquals(5, p.getCount());
    -  assertEquals(4, p.getInUseCount());
    -  assertEquals(1, p.getFreeCount());
    -
    -  p.setMaximumCount(4);
    -
    -  assertEquals(4, p.getCount());
    -  assertEquals(4, p.getInUseCount());
    -  assertEquals(0, p.getFreeCount());
    -}
    -
    -
    -function testInvalidMinMax1() {
    -  var p = new goog.structs.Pool(0, 10);
    -
    -  assertEquals(0, p.getCount());
    -  assertEquals(0, p.getInUseCount());
    -  assertEquals(0, p.getFreeCount());
    -
    -  assertThrows(function() {
    -    p.setMinimumCount(11);
    -  });
    -}
    -
    -
    -function testInvalidMinMax2() {
    -  var p = new goog.structs.Pool(5, 10);
    -
    -  assertEquals(5, p.getCount());
    -  assertEquals(0, p.getInUseCount());
    -  assertEquals(5, p.getFreeCount());
    -
    -  assertThrows(function() {
    -    p.setMaximumCount(4);
    -  });
    -}
    -
    -
    -function testInvalidMinMax3() {
    -  assertThrows(function() {
    -    new goog.structs.Pool(10, 1);
    -  });
    -}
    -
    -
    -function testRateLimiting() {
    -  var clock = new goog.testing.MockClock();
    -  clock.install();
    -
    -  var p = new goog.structs.Pool(0, 3);
    -  p.setDelay(100);
    -
    -  assertNotUndefined(p.getObject());
    -  assertUndefined(p.getObject());
    -
    -  clock.tick(100);
    -  assertNotUndefined(p.getObject());
    -  assertUndefined(p.getObject());
    -
    -  clock.tick(100);
    -  assertNotUndefined(p.getObject());
    -  assertUndefined(p.getObject());
    -
    -  clock.tick(100);
    -  assertUndefined(p.getObject());
    -
    -  goog.dispose(clock);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/prioritypool.js b/src/database/third_party/closure-library/closure/goog/structs/prioritypool.js
    deleted file mode 100644
    index 7f4ade297c4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/prioritypool.js
    +++ /dev/null
    @@ -1,182 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Datastructure: Priority Pool.
    - *
    - *
    - * An extending of Pool that handles queueing and prioritization.
    - */
    -
    -
    -goog.provide('goog.structs.PriorityPool');
    -
    -goog.require('goog.structs.Pool');
    -goog.require('goog.structs.PriorityQueue');
    -
    -
    -
    -/**
    - * A generic pool class. If max is greater than min, an error is thrown.
    - * @param {number=} opt_minCount Min. number of objects (Default: 1).
    - * @param {number=} opt_maxCount Max. number of objects (Default: 10).
    - * @constructor
    - * @extends {goog.structs.Pool<VALUE>}
    - * @template VALUE
    - */
    -goog.structs.PriorityPool = function(opt_minCount, opt_maxCount) {
    -  /**
    -   * The key for the most recent timeout created.
    -   * @private {number|undefined}
    -   */
    -  this.delayTimeout_ = undefined;
    -
    -  /**
    -   * Queue of requests for pool objects.
    -   * @private {goog.structs.PriorityQueue<VALUE>}
    -   */
    -  this.requestQueue_ = new goog.structs.PriorityQueue();
    -
    -  // Must break convention of putting the super-class's constructor first. This
    -  // is because the super-class constructor calls adjustForMinMax, which this
    -  // class overrides. In this class's implementation, it assumes that there
    -  // is a requestQueue_, and will error if not present.
    -  goog.structs.Pool.call(this, opt_minCount, opt_maxCount);
    -};
    -goog.inherits(goog.structs.PriorityPool, goog.structs.Pool);
    -
    -
    -/**
    - * Default priority for pool objects requests.
    - * @type {number}
    - * @private
    - */
    -goog.structs.PriorityPool.DEFAULT_PRIORITY_ = 100;
    -
    -
    -/** @override */
    -goog.structs.PriorityPool.prototype.setDelay = function(delay) {
    -  goog.structs.PriorityPool.base(this, 'setDelay', delay);
    -
    -  // If the pool hasn't been accessed yet, no need to do anything.
    -  if (!goog.isDefAndNotNull(this.lastAccess)) {
    -    return;
    -  }
    -
    -  goog.global.clearTimeout(this.delayTimeout_);
    -  this.delayTimeout_ = goog.global.setTimeout(
    -      goog.bind(this.handleQueueRequests_, this),
    -      this.delay + this.lastAccess - goog.now());
    -
    -  // Handle all requests.
    -  this.handleQueueRequests_();
    -};
    -
    -
    -/**
    - * Get a new object from the the pool, if there is one available, otherwise
    - * return undefined.
    - * @param {Function=} opt_callback The function to callback when an object is
    - *     available. This could be immediately. If this is not present, then an
    - *     object is immediately returned if available, or undefined if not.
    - * @param {number=} opt_priority The priority of the request. A smaller value
    - *     means a higher priority.
    - * @return {VALUE|undefined} The new object from the pool if there is one
    - *     available and a callback is not given. Otherwise, undefined.
    - * @override
    - */
    -goog.structs.PriorityPool.prototype.getObject = function(opt_callback,
    -                                                         opt_priority) {
    -  if (!opt_callback) {
    -    var result = goog.structs.PriorityPool.base(this, 'getObject');
    -    if (result && this.delay) {
    -      this.delayTimeout_ = goog.global.setTimeout(
    -          goog.bind(this.handleQueueRequests_, this),
    -          this.delay);
    -    }
    -    return result;
    -  }
    -
    -  var priority = goog.isDef(opt_priority) ? opt_priority :
    -      goog.structs.PriorityPool.DEFAULT_PRIORITY_;
    -  this.requestQueue_.enqueue(priority, opt_callback);
    -
    -  // Handle all requests.
    -  this.handleQueueRequests_();
    -
    -  return undefined;
    -};
    -
    -
    -/**
    - * Handles the request queue. Tries to fires off as many queued requests as
    - * possible.
    - * @private
    - */
    -goog.structs.PriorityPool.prototype.handleQueueRequests_ = function() {
    -  var requestQueue = this.requestQueue_;
    -  while (requestQueue.getCount() > 0) {
    -    var obj = this.getObject();
    -
    -    if (!obj) {
    -      return;
    -    } else {
    -      var requestCallback = requestQueue.dequeue();
    -      requestCallback.apply(this, [obj]);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Adds an object to the collection of objects that are free. If the object can
    - * not be added, then it is disposed.
    - *
    - * NOTE: This method does not remove the object from the in use collection.
    - *
    - * @param {VALUE} obj The object to add to the collection of free objects.
    - * @override
    - */
    -goog.structs.PriorityPool.prototype.addFreeObject = function(obj) {
    -  goog.structs.PriorityPool.superClass_.addFreeObject.call(this, obj);
    -
    -  // Handle all requests.
    -  this.handleQueueRequests_();
    -};
    -
    -
    -/**
    - * Adjusts the objects held in the pool to be within the min/max constraints.
    - *
    - * NOTE: It is possible that the number of objects in the pool will still be
    - * greater than the maximum count of objects allowed. This will be the case
    - * if no more free objects can be disposed of to get below the minimum count
    - * (i.e., all objects are in use).
    - * @override
    - */
    -goog.structs.PriorityPool.prototype.adjustForMinMax = function() {
    -  goog.structs.PriorityPool.superClass_.adjustForMinMax.call(this);
    -
    -  // Handle all requests.
    -  this.handleQueueRequests_();
    -};
    -
    -
    -/** @override */
    -goog.structs.PriorityPool.prototype.disposeInternal = function() {
    -  goog.structs.PriorityPool.superClass_.disposeInternal.call(this);
    -  goog.global.clearTimeout(this.delayTimeout_);
    -  this.requestQueue_.clear();
    -  this.requestQueue_ = null;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/prioritypool_test.html b/src/database/third_party/closure-library/closure/goog/structs/prioritypool_test.html
    deleted file mode 100644
    index 8a41fd90077..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/prioritypool_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.structs.PriorityPool
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.structs.PriorityPoolTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/prioritypool_test.js b/src/database/third_party/closure-library/closure/goog/structs/prioritypool_test.js
    deleted file mode 100644
    index e4a2e9ce31c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/prioritypool_test.js
    +++ /dev/null
    @@ -1,582 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.structs.PriorityPoolTest');
    -goog.setTestOnly('goog.structs.PriorityPoolTest');
    -
    -goog.require('goog.structs.PriorityPool');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.jsunit');
    -
    -// Implementation of the Pool class with isObjectDead() always returning TRUE,
    -// so that the the Pool will not reuse any objects.
    -function NoObjectReusePriorityPool(opt_min, opt_max) {
    -  goog.structs.PriorityPool.call(this, opt_min, opt_max);
    -}
    -goog.inherits(NoObjectReusePriorityPool, goog.structs.PriorityPool);
    -
    -NoObjectReusePriorityPool.prototype.objectCanBeReused = function(obj) {
    -  return false;
    -};
    -
    -
    -function testExceedMax1() {
    -  var p = new goog.structs.PriorityPool(0, 3);
    -
    -  var getCount1 = 0;
    -  var callback1 = function(obj) {
    -    assertNotNull(obj);
    -    getCount1++;
    -  };
    -
    -  var getCount2 = 0;
    -  var callback2 = function(obj) {
    -    getCount2++;
    -  };
    -
    -  p.getObject(callback1);
    -  p.getObject(callback1);
    -  p.getObject(callback1);
    -  p.getObject(callback2);
    -  p.getObject(callback2);
    -  p.getObject(callback2);
    -
    -  assertEquals('getCount for allocated, Should be 3', getCount1, 3);
    -  assertEquals('getCount for unallocated, Should be 0', getCount2, 0);
    -}
    -
    -
    -function testExceedMax2() {
    -  var p = new goog.structs.PriorityPool(0, 1);
    -
    -  var getCount1 = 0;
    -  var callback1 = function(obj) {
    -    assertNotNull(obj);
    -    getCount1++;
    -  };
    -
    -  var getCount2 = 0;
    -  var callback2 = function(obj) {
    -    getCount2++;
    -  };
    -
    -  p.getObject(callback1);
    -  p.getObject(callback2);
    -  p.getObject(callback2);
    -  p.getObject(callback2);
    -  p.getObject(callback2);
    -  p.getObject(callback2);
    -
    -  assertEquals('getCount for allocated, Should be 1', getCount1, 1);
    -  assertEquals('getCount for unallocated, Should be 0', getCount2, 0);
    -}
    -
    -function testExceedMax3() {
    -  var p = new goog.structs.PriorityPool(0, 2);
    -
    -  var obj1 = null;
    -  var callback1 = function(obj) {
    -    obj1 = obj;
    -  };
    -
    -  var obj2 = null;
    -  var callback2 = function(obj) {
    -    obj2 = obj;
    -  };
    -
    -  var obj3 = null;
    -  var callback3 = function(obj) {
    -    obj3 = obj;
    -  };
    -
    -  p.getObject(callback1);
    -  p.getObject(callback2);
    -  p.getObject(callback3);
    -
    -  assertNotNull(obj1);
    -  assertNotNull(obj2);
    -  assertNull(obj3);
    -}
    -
    -function testExceedMax4() {
    -  var p = new goog.structs.PriorityPool(); // default: 10
    -  var objs = [];
    -
    -  var getCount1 = 0;
    -  var callback1 = function(obj) {
    -    assertNotNull(obj);
    -    getCount1++;
    -  };
    -
    -  var getCount2 = 0;
    -  var callback2 = function(obj) {
    -    getCount2++;
    -  };
    -
    -  for (var i = 0; i < 12; i++) {
    -    p.getObject(i < 10 ? callback1 : callback2);
    -  }
    -
    -  assertEquals('getCount for allocated, Should be 10', getCount1, 10);
    -  assertEquals('getCount for unallocated, Should be 0', getCount2, 0);
    -}
    -
    -
    -function testReleaseAndGet1() {
    -  var p = new goog.structs.PriorityPool(0, 10);
    -
    -  var o = null;
    -  var callback = function(obj) {
    -    o = obj;
    -  };
    -
    -  p.getObject(callback);
    -  assertEquals(1, p.getCount());
    -  assertEquals(1, p.getInUseCount());
    -  assertEquals(0, p.getFreeCount());
    -  assertTrue('Result should be true', p.releaseObject(o));
    -  assertEquals(1, p.getCount());
    -  assertEquals(0, p.getInUseCount());
    -  assertEquals(1, p.getFreeCount());
    -}
    -
    -
    -function testReleaseAndGet2() {
    -  var p = new NoObjectReusePriorityPool(0, 10);
    -
    -  var o = null;
    -  var callback = function(obj) {
    -    o = obj;
    -  };
    -
    -  p.getObject(callback);
    -  assertEquals(1, p.getCount());
    -  assertEquals(1, p.getInUseCount());
    -  assertEquals(0, p.getFreeCount());
    -  assertTrue('Result should be true', p.releaseObject(o));
    -  assertEquals(0, p.getCount());
    -  assertEquals(0, p.getInUseCount());
    -  assertEquals(0, p.getFreeCount());
    -}
    -
    -
    -function testReleaseAndGet3() {
    -  var p = new goog.structs.PriorityPool(0, 10);
    -  var o1 = null;
    -  var callback1 = function(obj) {
    -    o1 = obj;
    -  };
    -
    -  var o2 = null;
    -  var callback2 = function(obj) {
    -    o2 = obj;
    -  };
    -
    -  var o3 = null;
    -  var callback3 = function(obj) {
    -    o3 = obj;
    -  };
    -
    -  var o4 = {};
    -
    -  p.getObject(callback1);
    -  p.getObject(callback2);
    -  p.getObject(callback3);
    -
    -  assertEquals(3, p.getCount());
    -  assertEquals(3, p.getInUseCount());
    -  assertEquals(0, p.getFreeCount());
    -  assertTrue('Result should be true', p.releaseObject(o1));
    -  assertTrue('Result should be true', p.releaseObject(o2));
    -  assertFalse('Result should be false', p.releaseObject(o4));
    -  assertEquals(3, p.getCount());
    -  assertEquals(1, p.getInUseCount());
    -  assertEquals(2, p.getFreeCount());
    -}
    -
    -
    -function testReleaseAndGet4() {
    -  var p = new NoObjectReusePriorityPool(0, 10);
    -
    -  var o1 = null;
    -  var callback1 = function(obj) {
    -    o1 = obj;
    -  };
    -
    -  var o2 = null;
    -  var callback2 = function(obj) {
    -    o2 = obj;
    -  };
    -
    -  var o3 = null;
    -  var callback3 = function(obj) {
    -    o3 = obj;
    -  };
    -
    -  var o4 = {};
    -
    -  p.getObject(callback1);
    -  p.getObject(callback2);
    -  p.getObject(callback3);
    -  assertEquals(3, p.getCount());
    -  assertEquals(3, p.getInUseCount());
    -  assertEquals(0, p.getFreeCount());
    -  assertTrue('Result should be true', p.releaseObject(o1));
    -  assertTrue('Result should be true', p.releaseObject(o2));
    -  assertFalse('Result should be false', p.releaseObject(o4));
    -  assertEquals(1, p.getCount());
    -  assertEquals(1, p.getInUseCount());
    -  assertEquals(0, p.getFreeCount());
    -}
    -
    -
    -function testIsInPool1() {
    -  var p = new goog.structs.PriorityPool();
    -  var o1 = null;
    -  var callback1 = function(obj) {
    -    o1 = obj;
    -  };
    -
    -  var o2 = null;
    -  var callback2 = function(obj) {
    -    o2 = obj;
    -  };
    -
    -  var o3 = null;
    -  var callback3 = function(obj) {
    -    o3 = obj;
    -  };
    -
    -  var o4 = {};
    -  var o5 = {};
    -
    -  p.getObject(callback1);
    -  p.getObject(callback2);
    -  p.getObject(callback3);
    -  var o6 = o1;
    -
    -  assertTrue(p.contains(o1));
    -  assertTrue(p.contains(o2));
    -  assertTrue(p.contains(o3));
    -  assertFalse(p.contains(o4));
    -  assertFalse(p.contains(o5));
    -  assertTrue(p.contains(o6));
    -}
    -
    -
    -function testSetMin1() {
    -  var p = new goog.structs.PriorityPool(0, 10);
    -
    -  assertEquals(0, p.getCount());
    -  assertEquals(0, p.getInUseCount());
    -  assertEquals(0, p.getFreeCount());
    -
    -  p.setMinimumCount(10);
    -
    -  assertEquals(10, p.getCount());
    -  assertEquals(0, p.getInUseCount());
    -  assertEquals(10, p.getFreeCount());
    -}
    -
    -
    -function testSetMin2() {
    -  var p = new goog.structs.PriorityPool(0, 10);
    -
    -  assertEquals(0, p.getCount());
    -  assertEquals(0, p.getInUseCount());
    -  assertEquals(0, p.getFreeCount());
    -
    -  var o1 = null;
    -  var callback1 = function(obj) {
    -    o1 = obj;
    -  };
    -  p.getObject(callback1);
    -
    -  assertEquals(1, p.getCount());
    -  assertEquals(1, p.getInUseCount());
    -  assertEquals(0, p.getFreeCount());
    -
    -  p.setMinimumCount(10);
    -
    -  assertEquals(10, p.getCount());
    -  assertEquals(1, p.getInUseCount());
    -  assertEquals(9, p.getFreeCount());
    -}
    -
    -
    -function testSetMax1() {
    -  var p = new goog.structs.PriorityPool(0, 10);
    -
    -  assertEquals(0, p.getCount());
    -  assertEquals(0, p.getInUseCount());
    -  assertEquals(0, p.getFreeCount());
    -
    -  var o1 = null;
    -  var callback1 = function(obj) {
    -    o1 = obj;
    -  };
    -
    -  var o2 = null;
    -  var callback2 = function(obj) {
    -    o2 = obj;
    -  };
    -
    -  var o3 = null;
    -  var callback3 = function(obj) {
    -    o3 = obj;
    -  };
    -
    -  var o4 = null;
    -  var callback4 = function(obj) {
    -    o4 = obj;
    -  };
    -
    -  var o5 = null;
    -  var callback5 = function(obj) {
    -    o5 = obj;
    -  };
    -
    -  p.getObject(callback1);
    -  p.getObject(callback2);
    -  p.getObject(callback3);
    -  p.getObject(callback4);
    -  p.getObject(callback5);
    -
    -  assertEquals(5, p.getCount());
    -  assertEquals(5, p.getInUseCount());
    -  assertEquals(0, p.getFreeCount());
    -
    -  assertTrue('Result should be true', p.releaseObject(o5));
    -
    -  assertEquals(5, p.getCount());
    -  assertEquals(4, p.getInUseCount());
    -  assertEquals(1, p.getFreeCount());
    -
    -  p.setMaximumCount(4);
    -
    -  assertEquals(4, p.getCount());
    -  assertEquals(4, p.getInUseCount());
    -  assertEquals(0, p.getFreeCount());
    -}
    -
    -
    -function testInvalidMinMax1() {
    -  var p = new goog.structs.PriorityPool(0, 10);
    -
    -  assertEquals(0, p.getCount());
    -  assertEquals(0, p.getInUseCount());
    -  assertEquals(0, p.getFreeCount());
    -
    -  assertThrows(function() {
    -    p.setMinimumCount(11);
    -  });
    -}
    -
    -
    -function testInvalidMinMax2() {
    -  var p = new goog.structs.PriorityPool(5, 10);
    -
    -  assertEquals(5, p.getCount());
    -  assertEquals(0, p.getInUseCount());
    -  assertEquals(5, p.getFreeCount());
    -
    -  assertThrows(function() {
    -    p.setMaximumCount(4);
    -  });
    -}
    -
    -
    -function testInvalidMinMax3() {
    -  assertThrows(function() {
    -    new goog.structs.PriorityPool(10, 1);
    -  });
    -}
    -
    -function testQueue1() {
    -  var p = new goog.structs.PriorityPool(0, 2);
    -
    -  var o1 = null;
    -  var callback1 = function(obj) {
    -    o1 = obj;
    -  };
    -
    -  var o2 = null;
    -  var callback2 = function(obj) {
    -    o2 = obj;
    -  };
    -
    -  var o3 = null;
    -  var callback3 = function(obj) {
    -    o3 = obj;
    -  };
    -
    -  p.getObject(callback1);
    -  p.getObject(callback2);
    -  p.getObject(callback3);
    -
    -  assertNotNull(o1);
    -  assertNotNull(o2);
    -  assertNull(o3);
    -
    -  p.releaseObject(o1);
    -  assertNotNull(o3);
    -}
    -
    -
    -function testPriority1() {
    -  var p = new goog.structs.PriorityPool(0, 2);
    -
    -  var o1 = null;
    -  var callback1 = function(obj) {
    -    o1 = obj;
    -  };
    -
    -  var o2 = null;
    -  var callback2 = function(obj) {
    -    o2 = obj;
    -  };
    -
    -  var o3 = null;
    -  var callback3 = function(obj) {
    -    o3 = obj;
    -  };
    -
    -  var o4 = null;
    -  var callback4 = function(obj) {
    -    o4 = obj;
    -  };
    -
    -  var o5 = null;
    -  var callback5 = function(obj) {
    -    o5 = obj;
    -  };
    -
    -  var o6 = null;
    -  var callback6 = function(obj) {
    -    o6 = obj;
    -  };
    -
    -  p.getObject(callback1);       // Initially seeded requests.
    -  p.getObject(callback2);
    -
    -  p.getObject(callback3, 101);  // Lowest priority.
    -  p.getObject(callback4);       // Second lowest priority (default is 100).
    -  p.getObject(callback5, 99);   // Second highest priority.
    -  p.getObject(callback6, 0);    // Highest priority.
    -
    -  assertNotNull(o1);
    -  assertNotNull(o2);
    -  assertNull(o3);
    -  assertNull(o4);
    -  assertNull(o5);
    -  assertNull(o6);
    -
    -  p.releaseObject(o1);  // Release the first initially seeded request (o1).
    -  assertNotNull(o6);    // Make sure the highest priority request (o6) started.
    -  assertNull(o3);
    -  assertNull(o4);
    -  assertNull(o5);
    -
    -  p.releaseObject(o2);  // Release the second, initially seeded request (o2).
    -  assertNotNull(o5);    // The second highest priority request starts (o5).
    -  assertNull(o3);
    -  assertNull(o4);
    -
    -  p.releaseObject(o6);
    -  assertNotNull(o4);
    -  assertNull(o3);
    -}
    -
    -
    -function testRateLimiting() {
    -  var clock = new goog.testing.MockClock();
    -  clock.install();
    -
    -  var p = new goog.structs.PriorityPool(0, 4);
    -  p.setDelay(100);
    -
    -  var getCount = 0;
    -  var callback = function(obj) {
    -    assertNotNull(obj);
    -    getCount++;
    -  };
    -
    -  p.getObject(callback);
    -  assertEquals(1, getCount);
    -
    -  p.getObject(callback);
    -  assertEquals(1, getCount);
    -
    -  clock.tick(100);
    -  assertEquals(2, getCount);
    -
    -  p.getObject(callback);
    -  p.getObject(callback);
    -  assertEquals(2, getCount);
    -
    -  clock.tick(100);
    -  assertEquals(3, getCount);
    -
    -  clock.tick(100);
    -  assertEquals(4, getCount);
    -
    -  p.getObject(callback);
    -  assertEquals(4, getCount);
    -
    -  clock.tick(100);
    -  assertEquals(4, getCount);
    -
    -  goog.dispose(clock);
    -}
    -
    -
    -function testRateLimitingWithChangingDelay() {
    -  var clock = new goog.testing.MockClock();
    -  clock.install();
    -
    -  var p = new goog.structs.PriorityPool(0, 3);
    -  p.setDelay(100);
    -
    -  var getCount = 0;
    -  var callback = function(obj) {
    -    assertNotNull(obj);
    -    getCount++;
    -  };
    -
    -  p.getObject(callback);
    -  assertEquals(1, getCount);
    -
    -  p.getObject(callback);
    -  assertEquals(1, getCount);
    -
    -  clock.tick(50);
    -  assertEquals(1, getCount);
    -
    -  p.setDelay(50);
    -  assertEquals(2, getCount);
    -
    -  p.getObject(callback);
    -  assertEquals(2, getCount);
    -
    -  clock.tick(20);
    -  assertEquals(2, getCount);
    -
    -  p.setDelay(40);
    -  assertEquals(2, getCount);
    -
    -  clock.tick(20);
    -  assertEquals(3, getCount);
    -
    -  goog.dispose(clock);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/priorityqueue.js b/src/database/third_party/closure-library/closure/goog/structs/priorityqueue.js
    deleted file mode 100644
    index c89f912b278..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/priorityqueue.js
    +++ /dev/null
    @@ -1,66 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Datastructure: Priority Queue.
    - *
    - *
    - * This file provides the implementation of a Priority Queue. Smaller priorities
    - * move to the front of the queue. If two values have the same priority,
    - * it is arbitrary which value will come to the front of the queue first.
    - */
    -
    -// TODO(user): Should this rely on natural ordering via some Comparable
    -//     interface?
    -
    -
    -goog.provide('goog.structs.PriorityQueue');
    -
    -goog.require('goog.structs.Heap');
    -
    -
    -
    -/**
    - * Class for Priority Queue datastructure.
    - *
    - * @constructor
    - * @extends {goog.structs.Heap<number, VALUE>}
    - * @template VALUE
    - * @final
    - */
    -goog.structs.PriorityQueue = function() {
    -  goog.structs.Heap.call(this);
    -};
    -goog.inherits(goog.structs.PriorityQueue, goog.structs.Heap);
    -
    -
    -/**
    - * Puts the specified value in the queue.
    - * @param {number} priority The priority of the value. A smaller value here
    - *     means a higher priority.
    - * @param {VALUE} value The value.
    - */
    -goog.structs.PriorityQueue.prototype.enqueue = function(priority, value) {
    -  this.insert(priority, value);
    -};
    -
    -
    -/**
    - * Retrieves and removes the head of this queue.
    - * @return {VALUE} The element at the head of this queue. Returns undefined if
    - *     the queue is empty.
    - */
    -goog.structs.PriorityQueue.prototype.dequeue = function() {
    -  return this.remove();
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/priorityqueue_test.html b/src/database/third_party/closure-library/closure/goog/structs/priorityqueue_test.html
    deleted file mode 100644
    index 0538f20d590..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/priorityqueue_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.structs.PriorityQueue
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.structs.PriorityQueueTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/priorityqueue_test.js b/src/database/third_party/closure-library/closure/goog/structs/priorityqueue_test.js
    deleted file mode 100644
    index f0ccdbde442..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/priorityqueue_test.js
    +++ /dev/null
    @@ -1,175 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.structs.PriorityQueueTest');
    -goog.setTestOnly('goog.structs.PriorityQueueTest');
    -
    -goog.require('goog.structs');
    -goog.require('goog.structs.PriorityQueue');
    -goog.require('goog.testing.jsunit');
    -
    -function getPriorityQueue() {
    -  var p = new goog.structs.PriorityQueue();
    -  p.enqueue(0, 'a');
    -  p.enqueue(1, 'b');
    -  p.enqueue(2, 'c');
    -  p.enqueue(3, 'd');
    -  return p;
    -}
    -
    -
    -function getPriorityQueue2() {
    -  var p = new goog.structs.PriorityQueue();
    -  p.insert(1, 'b');
    -  p.insert(3, 'd');
    -  p.insert(0, 'a');
    -  p.insert(2, 'c');
    -  return p;
    -}
    -
    -
    -function testGetCount1() {
    -  var p = getPriorityQueue();
    -  assertEquals('count, should be 4', p.getCount(), 4);
    -  p.dequeue();
    -  assertEquals('count, should be 3', p.getCount(), 3);
    -}
    -
    -
    -function testGetCount2() {
    -  var p = getPriorityQueue();
    -  assertEquals('count, should be 4', p.getCount(), 4);
    -  p.dequeue();
    -  assertEquals('count, should be 3', p.getCount(), 3);
    -}
    -
    -
    -function testGetCount3() {
    -  var p = getPriorityQueue();
    -  p.dequeue();
    -  p.dequeue();
    -  p.dequeue();
    -  p.dequeue();
    -  assertEquals('count, should be 0', p.getCount(), 0);
    -}
    -
    -
    -function testKeys() {
    -  var p = getPriorityQueue();
    -  var keys = p.getKeys();
    -  for (var i = 0; i < 4; i++) {
    -    assertTrue('getKeys, key ' + i + ' found', goog.structs.contains(keys, i));
    -  }
    -  assertEquals('getKeys, Should be 4 keys', goog.structs.getCount(keys), 4);
    -}
    -
    -
    -function testValues() {
    -  var p = getPriorityQueue();
    -  var values = p.getValues();
    -
    -  assertTrue('getKeys, value "a" found', goog.structs.contains(values, 'a'));
    -  assertTrue('getKeys, value "b" found', goog.structs.contains(values, 'b'));
    -  assertTrue('getKeys, value "c" found', goog.structs.contains(values, 'c'));
    -  assertTrue('getKeys, value "d" found', goog.structs.contains(values, 'd'));
    -  assertEquals('getKeys, Should be 4 keys', goog.structs.getCount(values), 4);
    -}
    -
    -
    -function testClear() {
    -  var p = getPriorityQueue();
    -  p.clear();
    -  assertTrue('cleared so it should be empty', p.isEmpty());
    -}
    -
    -
    -function testIsEmpty() {
    -  var p = getPriorityQueue();
    -  assertFalse('4 values so should not be empty', p.isEmpty());
    -
    -  p.dequeue();
    -  p.dequeue();
    -  p.dequeue();
    -  assertFalse('1 values so should not be empty', p.isEmpty());
    -
    -  p.dequeue();
    -  assertTrue('0 values so should be empty', p.isEmpty());
    -}
    -
    -
    -function testPeek1() {
    -  var p = getPriorityQueue();
    -  assertEquals('peek, Should be "a"', p.peek(), 'a');
    -}
    -
    -
    -function testPeek2() {
    -  var p = getPriorityQueue2();
    -  assertEquals('peek, Should be "a"', p.peek(), 'a');
    -}
    -
    -
    -function testPeek3() {
    -  var p = getPriorityQueue();
    -  p.clear();
    -  assertEquals('peek, Should be "a"', p.peek(), undefined);
    -}
    -
    -
    -function testDequeue1() {
    -  var p = getPriorityQueue();
    -
    -  assertEquals('dequeue, Should be "a"', p.dequeue(), 'a');
    -  assertEquals('dequeue, Should be "b"', p.dequeue(), 'b');
    -  assertEquals('dequeue, Should be "c"', p.dequeue(), 'c');
    -  assertEquals('dequeue, Should be "d"', p.dequeue(), 'd');
    -}
    -
    -
    -function testDequeue2() {
    -  var p = getPriorityQueue2();
    -
    -  assertEquals('dequeue, Should be "a"', p.dequeue(), 'a');
    -  assertEquals('dequeue, Should be "b"', p.dequeue(), 'b');
    -  assertEquals('dequeue, Should be "c"', p.dequeue(), 'c');
    -  assertEquals('dequeue, Should be "d"', p.dequeue(), 'd');
    -}
    -
    -
    -function testEnqueuePeek1() {
    -  var p = new goog.structs.PriorityQueue();
    -
    -  p.enqueue(3, 'd');
    -  assertEquals('peak, Should be "d"', p.peek(), 'd');
    -  p.enqueue(2, 'c');
    -  assertEquals('peak, Should be "c"', p.peek(), 'c');
    -  p.enqueue(1, 'b');
    -  assertEquals('peak, Should be "b"', p.peek(), 'b');
    -  p.enqueue(0, 'a');
    -  assertEquals('peak, Should be "a"', p.peek(), 'a');
    -}
    -
    -
    -function testEnqueuePeek2() {
    -  var p = new goog.structs.PriorityQueue();
    -
    -  p.enqueue(1, 'b');
    -  assertEquals('peak, Should be "b"', p.peek(), 'b');
    -  p.enqueue(3, 'd');
    -  assertEquals('peak, Should be "b"', p.peek(), 'b');
    -  p.enqueue(0, 'a');
    -  assertEquals('peak, Should be "a"', p.peek(), 'a');
    -  p.enqueue(2, 'c');
    -  assertEquals('peak, Should be "a"', p.peek(), 'a');
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/quadtree.js b/src/database/third_party/closure-library/closure/goog/structs/quadtree.js
    deleted file mode 100644
    index cd645dd525d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/quadtree.js
    +++ /dev/null
    @@ -1,570 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Datastructure: A point Quad Tree for representing 2D data. Each
    - * region has the same ratio as the bounds for the tree.
    - *
    - * The implementation currently requires pre-determined bounds for data as it
    - * can not rebalance itself to that degree.
    - *
    - * @see ../demos/quadtree.html
    - */
    -
    -
    -goog.provide('goog.structs.QuadTree');
    -goog.provide('goog.structs.QuadTree.Node');
    -goog.provide('goog.structs.QuadTree.Point');
    -
    -goog.require('goog.math.Coordinate');
    -
    -
    -
    -/**
    - * Constructs a new quad tree.
    - * @param {number} minX Minimum x-value that can be held in tree.
    - * @param {number} minY Minimum y-value that can be held in tree.
    - * @param {number} maxX Maximum x-value that can be held in tree.
    - * @param {number} maxY Maximum y-value that can be held in tree.
    - * @constructor
    - * @final
    - */
    -goog.structs.QuadTree = function(minX, minY, maxX, maxY) {
    -  /**
    -   * Count of the number of items in the tree.
    -   * @private {number}
    -   */
    -  this.count_ = 0;
    -
    -  /**
    -   * The root node for the quad tree.
    -   * @private {goog.structs.QuadTree.Node}
    -   */
    -  this.root_ = new goog.structs.QuadTree.Node(
    -      minX, minY, maxX - minX, maxY - minY);
    -};
    -
    -
    -/**
    - * Returns a reference to the tree's root node.  Callers shouldn't modify nodes,
    - * directly.  This is a convenience for visualization and debugging purposes.
    - * @return {goog.structs.QuadTree.Node} The root node.
    - */
    -goog.structs.QuadTree.prototype.getRootNode = function() {
    -  return this.root_;
    -};
    -
    -
    -/**
    - * Sets the value of an (x, y) point within the quad-tree.
    - * @param {number} x The x-coordinate.
    - * @param {number} y The y-coordinate.
    - * @param {*} value The value associated with the point.
    - */
    -goog.structs.QuadTree.prototype.set = function(x, y, value) {
    -  var root = this.root_;
    -  if (x < root.x || y < root.y || x > root.x + root.w || y > root.y + root.h) {
    -    throw Error('Out of bounds : (' + x + ', ' + y + ')');
    -  }
    -  if (this.insert_(root, new goog.structs.QuadTree.Point(x, y, value))) {
    -    this.count_++;
    -  }
    -};
    -
    -
    -/**
    - * Gets the value of the point at (x, y) or null if the point is empty.
    - * @param {number} x The x-coordinate.
    - * @param {number} y The y-coordinate.
    - * @param {*=} opt_default The default value to return if the node doesn't
    - *     exist.
    - * @return {*} The value of the node, the default value if the node
    - *     doesn't exist, or undefined if the node doesn't exist and no default
    - *     has been provided.
    - */
    -goog.structs.QuadTree.prototype.get = function(x, y, opt_default) {
    -  var node = this.find_(this.root_, x, y);
    -  return node ? node.point.value : opt_default;
    -};
    -
    -
    -/**
    - * Removes a point from (x, y) if it exists.
    - * @param {number} x The x-coordinate.
    - * @param {number} y The y-coordinate.
    - * @return {*} The value of the node that was removed, or null if the
    - *     node doesn't exist.
    - */
    -goog.structs.QuadTree.prototype.remove = function(x, y) {
    -  var node = this.find_(this.root_, x, y);
    -  if (node) {
    -    var value = node.point.value;
    -    node.point = null;
    -    node.nodeType = goog.structs.QuadTree.NodeType.EMPTY;
    -    this.balance_(node);
    -    this.count_--;
    -    return value;
    -  } else {
    -    return null;
    -  }
    -};
    -
    -
    -/**
    - * Returns true if the point at (x, y) exists in the tree.
    - * @param {number} x The x-coordinate.
    - * @param {number} y The y-coordinate.
    - * @return {boolean} Whether the tree contains a point at (x, y).
    - */
    -goog.structs.QuadTree.prototype.contains = function(x, y) {
    -  return this.get(x, y) != null;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the tree is empty.
    - */
    -goog.structs.QuadTree.prototype.isEmpty = function() {
    -  return this.root_.nodeType == goog.structs.QuadTree.NodeType.EMPTY;
    -};
    -
    -
    -/**
    - * @return {number} The number of items in the tree.
    - */
    -goog.structs.QuadTree.prototype.getCount = function() {
    -  return this.count_;
    -};
    -
    -
    -/**
    - * Removes all items from the tree.
    - */
    -goog.structs.QuadTree.prototype.clear = function() {
    -  this.root_.nw = this.root_.ne = this.root_.sw = this.root_.se = null;
    -  this.root_.nodeType = goog.structs.QuadTree.NodeType.EMPTY;
    -  this.root_.point = null;
    -  this.count_ = 0;
    -};
    -
    -
    -/**
    - * Returns an array containing the coordinates of each point stored in the tree.
    - * @return {!Array<goog.math.Coordinate?>} Array of coordinates.
    - */
    -goog.structs.QuadTree.prototype.getKeys = function() {
    -  var arr = [];
    -  this.traverse_(this.root_, function(node) {
    -    arr.push(new goog.math.Coordinate(node.point.x, node.point.y));
    -  });
    -  return arr;
    -};
    -
    -
    -/**
    - * Returns an array containing all values stored within the tree.
    - * @return {!Array<Object>} The values stored within the tree.
    - */
    -goog.structs.QuadTree.prototype.getValues = function() {
    -  var arr = [];
    -  this.traverse_(this.root_, function(node) {
    -    // Must have a point because it's a leaf.
    -    arr.push(node.point.value);
    -  });
    -  return arr;
    -};
    -
    -
    -/**
    - * Clones the quad-tree and returns the new instance.
    - * @return {!goog.structs.QuadTree} A clone of the tree.
    - */
    -goog.structs.QuadTree.prototype.clone = function() {
    -  var x1 = this.root_.x;
    -  var y1 = this.root_.y;
    -  var x2 = x1 + this.root_.w;
    -  var y2 = y1 + this.root_.h;
    -  var clone = new goog.structs.QuadTree(x1, y1, x2, y2);
    -  // This is inefficient as the clone needs to recalculate the structure of the
    -  // tree, even though we know it already.  But this is easier and can be
    -  // optimized when/if needed.
    -  this.traverse_(this.root_, function(node) {
    -    clone.set(node.point.x, node.point.y, node.point.value);
    -  });
    -  return clone;
    -};
    -
    -
    -/**
    - * Traverses the tree and calls a function on each node.
    - * @param {function(?, goog.math.Coordinate, goog.structs.QuadTree)} fn
    - *     The function to call for every value. This function takes 3 arguments
    - *     (the value, the coordinate, and the tree itself) and the return value is
    - *     irrelevant.
    - * @param {Object=} opt_obj The object to be used as the value of 'this'
    - *     within {@ code fn}.
    - */
    -goog.structs.QuadTree.prototype.forEach = function(fn, opt_obj) {
    -  this.traverse_(this.root_, function(node) {
    -    var coord = new goog.math.Coordinate(node.point.x, node.point.y);
    -    fn.call(opt_obj, node.point.value, coord, this);
    -  });
    -};
    -
    -
    -/**
    - * Traverses the tree depth-first, with quadrants being traversed in clockwise
    - * order (NE, SE, SW, NW).  The provided function will be called for each
    - * leaf node that is encountered.
    - * @param {goog.structs.QuadTree.Node} node The current node.
    - * @param {function(goog.structs.QuadTree.Node)} fn The function to call
    - *     for each leaf node. This function takes the node as an argument, and its
    - *     return value is irrelevant.
    - * @private
    - */
    -goog.structs.QuadTree.prototype.traverse_ = function(node, fn) {
    -  switch (node.nodeType) {
    -    case goog.structs.QuadTree.NodeType.LEAF:
    -      fn.call(this, node);
    -      break;
    -
    -    case goog.structs.QuadTree.NodeType.POINTER:
    -      this.traverse_(node.ne, fn);
    -      this.traverse_(node.se, fn);
    -      this.traverse_(node.sw, fn);
    -      this.traverse_(node.nw, fn);
    -      break;
    -  }
    -};
    -
    -
    -/**
    - * Finds a leaf node with the same (x, y) coordinates as the target point, or
    - * null if no point exists.
    - * @param {goog.structs.QuadTree.Node} node The node to search in.
    - * @param {number} x The x-coordinate of the point to search for.
    - * @param {number} y The y-coordinate of the point to search for.
    - * @return {goog.structs.QuadTree.Node} The leaf node that matches the target,
    - *     or null if it doesn't exist.
    - * @private
    - */
    -goog.structs.QuadTree.prototype.find_ = function(node, x, y) {
    -  switch (node.nodeType) {
    -    case goog.structs.QuadTree.NodeType.EMPTY:
    -      return null;
    -
    -    case goog.structs.QuadTree.NodeType.LEAF:
    -      return node.point.x == x && node.point.y == y ? node : null;
    -
    -    case goog.structs.QuadTree.NodeType.POINTER:
    -      return this.find_(this.getQuadrantForPoint_(node, x, y), x, y);
    -
    -    default:
    -      throw Error('Invalid nodeType');
    -  }
    -};
    -
    -
    -/**
    - * Inserts a point into the tree, updating the tree's structure if necessary.
    - * @param {goog.structs.QuadTree.Node} parent The parent to insert the point
    - *     into.
    - * @param {goog.structs.QuadTree.Point} point The point to insert.
    - * @return {boolean} True if a new node was added to the tree; False if a node
    - *     already existed with the correpsonding coordinates and had its value
    - *     reset.
    - * @private
    - */
    -goog.structs.QuadTree.prototype.insert_ = function(parent, point) {
    -  switch (parent.nodeType) {
    -    case goog.structs.QuadTree.NodeType.EMPTY:
    -      this.setPointForNode_(parent, point);
    -      return true;
    -
    -    case goog.structs.QuadTree.NodeType.LEAF:
    -      if (parent.point.x == point.x && parent.point.y == point.y) {
    -        this.setPointForNode_(parent, point);
    -        return false;
    -      } else {
    -        this.split_(parent);
    -        return this.insert_(parent, point);
    -      }
    -
    -    case goog.structs.QuadTree.NodeType.POINTER:
    -      return this.insert_(
    -          this.getQuadrantForPoint_(parent, point.x, point.y), point);
    -
    -    default:
    -      throw Error('Invalid nodeType in parent');
    -  }
    -};
    -
    -
    -/**
    - * Converts a leaf node to a pointer node and reinserts the node's point into
    - * the correct child.
    - * @param {goog.structs.QuadTree.Node} node The node to split.
    - * @private
    - */
    -goog.structs.QuadTree.prototype.split_ = function(node) {
    -  var oldPoint = node.point;
    -  node.point = null;
    -
    -  node.nodeType = goog.structs.QuadTree.NodeType.POINTER;
    -
    -  var x = node.x;
    -  var y = node.y;
    -  var hw = node.w / 2;
    -  var hh = node.h / 2;
    -
    -  node.nw = new goog.structs.QuadTree.Node(x, y, hw, hh, node);
    -  node.ne = new goog.structs.QuadTree.Node(x + hw, y, hw, hh, node);
    -  node.sw = new goog.structs.QuadTree.Node(x, y + hh, hw, hh, node);
    -  node.se = new goog.structs.QuadTree.Node(x + hw, y + hh, hw, hh, node);
    -
    -  this.insert_(node, oldPoint);
    -};
    -
    -
    -/**
    - * Attempts to balance a node. A node will need balancing if all its children
    - * are empty or it contains just one leaf.
    - * @param {goog.structs.QuadTree.Node} node The node to balance.
    - * @private
    - */
    -goog.structs.QuadTree.prototype.balance_ = function(node) {
    -  switch (node.nodeType) {
    -    case goog.structs.QuadTree.NodeType.EMPTY:
    -    case goog.structs.QuadTree.NodeType.LEAF:
    -      if (node.parent) {
    -        this.balance_(node.parent);
    -      }
    -      break;
    -
    -    case goog.structs.QuadTree.NodeType.POINTER:
    -      var nw = node.nw, ne = node.ne, sw = node.sw, se = node.se;
    -      var firstLeaf = null;
    -
    -      // Look for the first non-empty child, if there is more than one then we
    -      // break as this node can't be balanced.
    -      if (nw.nodeType != goog.structs.QuadTree.NodeType.EMPTY) {
    -        firstLeaf = nw;
    -      }
    -      if (ne.nodeType != goog.structs.QuadTree.NodeType.EMPTY) {
    -        if (firstLeaf) {
    -          break;
    -        }
    -        firstLeaf = ne;
    -      }
    -      if (sw.nodeType != goog.structs.QuadTree.NodeType.EMPTY) {
    -        if (firstLeaf) {
    -          break;
    -        }
    -        firstLeaf = sw;
    -      }
    -      if (se.nodeType != goog.structs.QuadTree.NodeType.EMPTY) {
    -        if (firstLeaf) {
    -          break;
    -        }
    -        firstLeaf = se;
    -      }
    -
    -      if (!firstLeaf) {
    -        // All child nodes are empty: so make this node empty.
    -        node.nodeType = goog.structs.QuadTree.NodeType.EMPTY;
    -        node.nw = node.ne = node.sw = node.se = null;
    -
    -      } else if (firstLeaf.nodeType == goog.structs.QuadTree.NodeType.POINTER) {
    -        // Only child was a pointer, therefore we can't rebalance.
    -        break;
    -
    -      } else {
    -        // Only child was a leaf: so update node's point and make it a leaf.
    -        node.nodeType = goog.structs.QuadTree.NodeType.LEAF;
    -        node.nw = node.ne = node.sw = node.se = null;
    -        node.point = firstLeaf.point;
    -      }
    -
    -      // Try and balance the parent as well.
    -      if (node.parent) {
    -        this.balance_(node.parent);
    -      }
    -
    -      break;
    -  }
    -};
    -
    -
    -/**
    - * Returns the child quadrant within a node that contains the given (x, y)
    - * coordinate.
    - * @param {goog.structs.QuadTree.Node} parent The node.
    - * @param {number} x The x-coordinate to look for.
    - * @param {number} y The y-coordinate to look for.
    - * @return {goog.structs.QuadTree.Node} The child quadrant that contains the
    - *     point.
    - * @private
    - */
    -goog.structs.QuadTree.prototype.getQuadrantForPoint_ = function(parent, x, y) {
    -  var mx = parent.x + parent.w / 2;
    -  var my = parent.y + parent.h / 2;
    -  if (x < mx) {
    -    return y < my ? parent.nw : parent.sw;
    -  } else {
    -    return y < my ? parent.ne : parent.se;
    -  }
    -};
    -
    -
    -/**
    - * Sets the point for a node, as long as the node is a leaf or empty.
    - * @param {goog.structs.QuadTree.Node} node The node to set the point for.
    - * @param {goog.structs.QuadTree.Point} point The point to set.
    - * @private
    - */
    -goog.structs.QuadTree.prototype.setPointForNode_ = function(node, point) {
    -  if (node.nodeType == goog.structs.QuadTree.NodeType.POINTER) {
    -    throw Error('Can not set point for node of type POINTER');
    -  }
    -  node.nodeType = goog.structs.QuadTree.NodeType.LEAF;
    -  node.point = point;
    -};
    -
    -
    -/**
    - * Enumeration of node types.
    - * @enum {number}
    - */
    -goog.structs.QuadTree.NodeType = {
    -  EMPTY: 0,
    -  LEAF: 1,
    -  POINTER: 2
    -};
    -
    -
    -
    -/**
    - * Constructs a new quad tree node.
    - * @param {number} x X-coordiate of node.
    - * @param {number} y Y-coordinate of node.
    - * @param {number} w Width of node.
    - * @param {number} h Height of node.
    - * @param {goog.structs.QuadTree.Node=} opt_parent Optional parent node.
    - * @constructor
    - * @final
    - */
    -goog.structs.QuadTree.Node = function(x, y, w, h, opt_parent) {
    -  /**
    -   * The x-coordinate of the node.
    -   * @type {number}
    -   */
    -  this.x = x;
    -
    -  /**
    -   * The y-coordinate of the node.
    -   * @type {number}
    -   */
    -  this.y = y;
    -
    -  /**
    -   * The width of the node.
    -   * @type {number}
    -   */
    -  this.w = w;
    -
    -  /**
    -   * The height of the node.
    -   * @type {number}
    -   */
    -  this.h = h;
    -
    -  /**
    -   * The parent node.
    -   * @type {goog.structs.QuadTree.Node?}
    -   */
    -  this.parent = opt_parent || null;
    -};
    -
    -
    -/**
    - * The node's type.
    - * @type {goog.structs.QuadTree.NodeType}
    - */
    -goog.structs.QuadTree.Node.prototype.nodeType =
    -    goog.structs.QuadTree.NodeType.EMPTY;
    -
    -
    -/**
    - * The child node in the North-West quadrant.
    - * @type {goog.structs.QuadTree.Node?}
    - */
    -goog.structs.QuadTree.Node.prototype.nw = null;
    -
    -
    -/**
    - * The child node in the North-East quadrant.
    - * @type {goog.structs.QuadTree.Node?}
    - */
    -goog.structs.QuadTree.Node.prototype.ne = null;
    -
    -
    -/**
    - * The child node in the South-West quadrant.
    - * @type {goog.structs.QuadTree.Node?}
    - */
    -goog.structs.QuadTree.Node.prototype.sw = null;
    -
    -
    -/**
    - * The child node in the South-East quadrant.
    - * @type {goog.structs.QuadTree.Node?}
    - */
    -goog.structs.QuadTree.Node.prototype.se = null;
    -
    -
    -/**
    - * The point for the node, if it is a leaf node.
    - * @type {goog.structs.QuadTree.Point?}
    - */
    -goog.structs.QuadTree.Node.prototype.point = null;
    -
    -
    -
    -/**
    - * Creates a new point object.
    - * @param {number} x The x-coordinate of the point.
    - * @param {number} y The y-coordinate of the point.
    - * @param {*=} opt_value Optional value associated with the point.
    - * @constructor
    - * @final
    - */
    -goog.structs.QuadTree.Point = function(x, y, opt_value) {
    -  /**
    -   * The x-coordinate for the point.
    -   * @type {number}
    -   */
    -  this.x = x;
    -
    -  /**
    -   * The y-coordinate for the point.
    -   * @type {number}
    -   */
    -  this.y = y;
    -
    -  /**
    -   * Optional value associated with the point.
    -   * @type {*}
    -   */
    -  this.value = goog.isDef(opt_value) ? opt_value : null;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/quadtree_test.html b/src/database/third_party/closure-library/closure/goog/structs/quadtree_test.html
    deleted file mode 100644
    index 18456f088d5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/quadtree_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.structs.QuadTree
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.structs.QuadTreeTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/quadtree_test.js b/src/database/third_party/closure-library/closure/goog/structs/quadtree_test.js
    deleted file mode 100644
    index 2b300403433..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/quadtree_test.js
    +++ /dev/null
    @@ -1,174 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.structs.QuadTreeTest');
    -goog.setTestOnly('goog.structs.QuadTreeTest');
    -
    -goog.require('goog.structs');
    -goog.require('goog.structs.QuadTree');
    -goog.require('goog.testing.jsunit');
    -
    -function getTree() {
    -  var qt = new goog.structs.QuadTree(0, 0, 100, 100);
    -  qt.set(5, 20, 'Foo');
    -  qt.set(50, 32, 'Bar');
    -  qt.set(47, 96, 'Baz');
    -  qt.set(50, 50, 'Bing');
    -  qt.set(12, 0, 'Bong');
    -  return qt;
    -}
    -
    -function testGetCount() {
    -  var qt = getTree();
    -  assertEquals('Count should be 5', 5, qt.getCount());
    -  qt.remove(50, 32);
    -  assertEquals('Count should be 4', 4, qt.getCount());
    -}
    -
    -function testGetKeys() {
    -  var keys = getTree().getKeys();
    -  var keyString = keys.sort().join(' ');
    -  var expected = '(12, 0) (47, 96) (5, 20) (50, 32) (50, 50)';
    -  assertEquals('Sorted keys should be ' + expected, expected, keyString);
    -}
    -
    -function testGetValues() {
    -  var values = getTree().getValues();
    -  var valueString = values.sort().join(',');
    -  assertEquals('Sorted values should be Bar,Baz,Bing,Bong,Foo',
    -      'Bar,Baz,Bing,Bong,Foo', valueString);
    -}
    -
    -function testContains() {
    -  var qt = getTree();
    -  assertTrue('Should contain (5, 20)', qt.contains(5, 20));
    -  assertFalse('Should not contain (13, 13)', qt.contains(13, 13));
    -}
    -
    -function testClear() {
    -  var qt = getTree();
    -  qt.clear();
    -  assertTrue('Tree should be empty', qt.isEmpty());
    -  assertFalse('Tree should not contain (5, 20)', qt.contains(5, 20));
    -}
    -
    -function testConstructor() {
    -  var qt = new goog.structs.QuadTree(-10, -5, 6, 12);
    -  var root = qt.getRootNode();
    -  assertEquals('X of root should be -10', -10, root.x);
    -  assertEquals('Y of root should be -5', -5, root.y);
    -  assertEquals('Width of root should be 16', 16, root.w);
    -  assertEquals('Height of root should be 17', 17, root.h);
    -  assertTrue('Tree should be empty', qt.isEmpty());
    -}
    -
    -function testClone() {
    -  var qt = getTree().clone();
    -  assertFalse('Clone should not be empty', qt.isEmpty());
    -  assertTrue('Should contain (47, 96)', qt.contains(47, 96));
    -}
    -
    -function testRemove() {
    -  var qt = getTree();
    -  assertEquals('(5, 20) should be removed', 'Foo', qt.remove(5, 20));
    -  assertEquals('(5, 20) should be removed', 'Bar', qt.remove(50, 32));
    -  assertEquals('(5, 20) should be removed', 'Baz', qt.remove(47, 96));
    -  assertEquals('(5, 20) should be removed', 'Bing', qt.remove(50, 50));
    -  assertEquals('(5, 20) should be removed', 'Bong', qt.remove(12, 0));
    -  assertNull('(6, 6) wasn\'t there to remove', qt.remove(6, 6));
    -  assertTrue('Tree should be empty', qt.isEmpty());
    -  assertTreesChildrenAreNull(qt);
    -}
    -
    -function testIsEmpty() {
    -  var qt = getTree();
    -  qt.clear();
    -  assertTrue(qt.isEmpty());
    -  assertEquals('Root should  be empty node',
    -      goog.structs.QuadTree.NodeType.EMPTY, qt.getRootNode().nodeType);
    -  assertTreesChildrenAreNull(qt);
    -}
    -
    -function testForEach() {
    -  var qt = getTree();
    -  var s = '';
    -  goog.structs.forEach(qt, function(val, key, qt2) {
    -    assertNotUndefined(key);
    -    assertEquals(qt, qt2);
    -    s += key.x + ',' + key.y + '=' + val + ' ';
    -  });
    -  assertEquals('50,32=Bar 50,50=Bing 47,96=Baz 5,20=Foo 12,0=Bong ', s);
    -}
    -
    -function testBalancing() {
    -  var qt = new goog.structs.QuadTree(0, 0, 100, 100);
    -  var root = qt.getRootNode();
    -
    -  // Add a point to the NW quadrant.
    -  qt.set(25, 25, 'first');
    -
    -  assertEquals('Root should be a leaf node.',
    -      goog.structs.QuadTree.NodeType.LEAF, root.nodeType);
    -  assertTreesChildrenAreNull(qt);
    -
    -  assertEquals('first', root.point.value);
    -
    -  // Add another point in the NW quadrant
    -  qt.set(25, 30, 'second');
    -
    -  assertEquals('Root should now be a pointer.',
    -      goog.structs.QuadTree.NodeType.POINTER, root.nodeType);
    -  assertNotNull('NE should be not be null', root.ne);
    -  assertNotNull('NW should be not be null', root.nw);
    -  assertNotNull('SE should be not be null', root.se);
    -  assertNotNull('SW should be not be null', root.sw);
    -  assertNull(root.point);
    -
    -  // Delete the second point.
    -  qt.remove(25, 30);
    -
    -  assertEquals('Root should have been rebalanced and be a leaf node.',
    -      goog.structs.QuadTree.NodeType.LEAF, root.nodeType);
    -  assertTreesChildrenAreNull(qt);
    -  assertEquals('first', root.point.value);
    -}
    -
    -function testTreeBounds() {
    -  var qt = getTree();
    -  assertFails(qt, qt.set, [-10, -10, 1]);
    -  assertFails(qt, qt.set, [-10, 10, 2]);
    -  assertFails(qt, qt.set, [10, -10, 3]);
    -  assertFails(qt, qt.set, [-10, 110, 4]);
    -  assertFails(qt, qt.set, [10, 130, 5]);
    -  assertFails(qt, qt.set, [110, -10, 6]);
    -  assertFails(qt, qt.set, [150, 14, 7]);
    -}
    -
    -// Helper functions
    -
    -function assertFails(context, fn, args) {
    -  assertThrows('Exception expected from ' + fn.toString() +
    -      ' with arguments ' + args,
    -      function() {
    -        fn.apply(context, args);
    -      });
    -}
    -
    -function assertTreesChildrenAreNull(qt) {
    -  var root = qt.getRootNode();
    -  assertNull('NE should be null', root.ne);
    -  assertNull('NW should be null', root.nw);
    -  assertNull('SE should be null', root.se);
    -  assertNull('SW should be null', root.sw);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/queue.js b/src/database/third_party/closure-library/closure/goog/structs/queue.js
    deleted file mode 100644
    index 8637945f2af..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/queue.js
    +++ /dev/null
    @@ -1,187 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Datastructure: Queue.
    - *
    - *
    - * This file provides the implementation of a FIFO Queue structure.
    - * API is similar to that of com.google.common.collect.IntQueue
    - *
    - * The implementation is a classic 2-stack queue.
    - * There's a "front" stack and a "back" stack.
    - * Items are pushed onto "back" and popped from "front".
    - * When "front" is empty, we replace "front" with reverse(back).
    - *
    - * Example:
    - * front                         back            op
    - * []                            []              enqueue 1
    - * []                            [1]             enqueue 2
    - * []                            [1,2]           enqueue 3
    - * []                            [1,2,3]         dequeue -> ...
    - * [3,2,1]                       []              ... -> 1
    - * [3,2]                         []              enqueue 4
    - * [3,2]                         [4]             dequeue -> 2
    - * [3]                           [4]
    - *
    - * Front and back are simple javascript arrays. We rely on
    - * Array.push and Array.pop being O(1) amortized.
    - *
    - * Note: In V8, queues, up to a certain size, can be implemented
    - * just fine using Array.push and Array.shift, but other JavaScript
    - * engines do not have the optimization of Array.shift.
    - *
    - */
    -
    -goog.provide('goog.structs.Queue');
    -
    -goog.require('goog.array');
    -
    -
    -
    -/**
    - * Class for FIFO Queue data structure.
    - *
    - * @constructor
    - * @template T
    - */
    -goog.structs.Queue = function() {
    -  /**
    -   * @private {!Array<T>} Front stack. Items are pop()'ed from here.
    -   */
    -  this.front_ = [];
    -  /**
    -   * @private {!Array<T>} Back stack. Items are push()'ed here.
    -   */
    -  this.back_ = [];
    -};
    -
    -
    -/**
    - * Flips the back stack onto the front stack if front is empty,
    - * to prepare for peek() or dequeue().
    - *
    - * @private
    - */
    -goog.structs.Queue.prototype.maybeFlip_ = function() {
    -  if (goog.array.isEmpty(this.front_)) {
    -    this.front_ = this.back_;
    -    this.front_.reverse();
    -    this.back_ = [];
    -  }
    -};
    -
    -
    -/**
    - * Puts the specified element on this queue.
    - * @param {T} element The element to be added to the queue.
    - */
    -goog.structs.Queue.prototype.enqueue = function(element) {
    -  this.back_.push(element);
    -};
    -
    -
    -/**
    - * Retrieves and removes the head of this queue.
    - * @return {T} The element at the head of this queue. Returns undefined if the
    - *     queue is empty.
    - */
    -goog.structs.Queue.prototype.dequeue = function() {
    -  this.maybeFlip_();
    -  return this.front_.pop();
    -};
    -
    -
    -/**
    - * Retrieves but does not remove the head of this queue.
    - * @return {T} The element at the head of this queue. Returns undefined if the
    - *     queue is empty.
    - */
    -goog.structs.Queue.prototype.peek = function() {
    -  this.maybeFlip_();
    -  return goog.array.peek(this.front_);
    -};
    -
    -
    -/**
    - * Returns the number of elements in this queue.
    - * @return {number} The number of elements in this queue.
    - */
    -goog.structs.Queue.prototype.getCount = function() {
    -  return this.front_.length + this.back_.length;
    -};
    -
    -
    -/**
    - * Returns true if this queue contains no elements.
    - * @return {boolean} true if this queue contains no elements.
    - */
    -goog.structs.Queue.prototype.isEmpty = function() {
    -  return goog.array.isEmpty(this.front_) &&
    -         goog.array.isEmpty(this.back_);
    -};
    -
    -
    -/**
    - * Removes all elements from the queue.
    - */
    -goog.structs.Queue.prototype.clear = function() {
    -  this.front_ = [];
    -  this.back_ = [];
    -};
    -
    -
    -/**
    - * Returns true if the given value is in the queue.
    - * @param {T} obj The value to look for.
    - * @return {boolean} Whether the object is in the queue.
    - */
    -goog.structs.Queue.prototype.contains = function(obj) {
    -  return goog.array.contains(this.front_, obj) ||
    -         goog.array.contains(this.back_, obj);
    -};
    -
    -
    -/**
    - * Removes the first occurrence of a particular value from the queue.
    - * @param {T} obj Object to remove.
    - * @return {boolean} True if an element was removed.
    - */
    -goog.structs.Queue.prototype.remove = function(obj) {
    -  // TODO(user): Implement goog.array.removeLast() and use it here.
    -  var index = goog.array.lastIndexOf(this.front_, obj);
    -  if (index < 0) {
    -    return goog.array.remove(this.back_, obj);
    -  }
    -  goog.array.removeAt(this.front_, index);
    -  return true;
    -};
    -
    -
    -/**
    - * Returns all the values in the queue.
    - * @return {!Array<T>} An array of the values in the queue.
    - */
    -goog.structs.Queue.prototype.getValues = function() {
    -  var res = [];
    -  // Add the front array in reverse, then the back array.
    -  for (var i = this.front_.length - 1; i >= 0; --i) {
    -    res.push(this.front_[i]);
    -  }
    -  var len = this.back_.length;
    -  for (var i = 0; i < len; ++i) {
    -    res.push(this.back_[i]);
    -  }
    -  return res;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/queue_perf.html b/src/database/third_party/closure-library/closure/goog/structs/queue_perf.html
    deleted file mode 100644
    index de83db3eb50..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/queue_perf.html
    +++ /dev/null
    @@ -1,126 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -  <title>Closure Performance Tests - goog.structs.Queue</title>
    -  <link rel="stylesheet" type="text/css" href="../testing/performancetable.css"/>
    -  <script src="../base.js"></script>
    -  <script>
    -    goog.require('goog.functions');
    -    goog.require('goog.structs.Queue');
    -    goog.require('goog.testing.PerformanceTable');
    -    goog.require('goog.testing.jsunit');
    -  </script>
    -</head>
    -<body>
    -  <h1>goog.structs.Queue Performance Tests</h1>
    -  <p>
    -    <strong>User-agent:</strong>
    -    <script>document.write(navigator.userAgent);</script>
    -  </p>
    -  <div id="perfTable"></div>
    -  <hr>
    -
    -  <script>
    -    var table = new goog.testing.PerformanceTable(
    -        goog.dom.getElement('perfTable'));
    -
    -    // Number of operations to measure in each table line.
    -    var OPS_COUNT = 10000;
    -
    -    var smallSizes = [1, 2, 5, 10, 20, 50, 100, 1000, 10000];
    -    var largeSizes = [100000];
    -
    -    function populateQueue(size) {
    -      var q = new goog.structs.Queue();
    -      for (var i = 0; i < size; ++i) {
    -        q.enqueue(i);
    -      }
    -      return q;
    -    }
    -
    -    function enqueueDequeueTest(size) {
    -      var q = populateQueue(size);
    -      table.run(function() {
    -        for (var i = 0; i < OPS_COUNT; ++i) {
    -          q.dequeue();
    -          q.enqueue(i);
    -        }
    -      }, 'Enqueue and dequeue, size ' + size);
    -    }
    -
    -    function containsTest(size) {
    -      var q = populateQueue(size);
    -      table.run(function() {
    -        for (var i = 0; i < OPS_COUNT; ++i) {
    -          q.contains(i);
    -        }
    -      }, 'Contains every element, size ' + size);
    -    }
    -
    -    function removeTest(size) {
    -      var q = populateQueue(size);
    -      if (size == 1) {
    -        return;
    -      }
    -      table.run(function() {
    -        var offset = Math.round(size / 2);
    -        for (var i = 0; i < OPS_COUNT; ++i) {
    -          q.remove(i + offset);
    -          q.enqueue(i + size);
    -        }
    -      }, 'Remove element from the middle, size ' + size);
    -    }
    -
    -    function getValuesTest(size) {
    -      var q = populateQueue(size);
    -      table.run(function() {
    -        for (var i = 0; i < OPS_COUNT; ++i) {
    -          q.getValues()[size - 1];
    -        }
    -      }, 'Get values, size ' + size);
    -    }
    -
    -    function testEnqueueDequeueSmall() {
    -      goog.array.forEach(smallSizes, enqueueDequeueTest);
    -    }
    -
    -    function testEnqueueDequeueLarge() {
    -      goog.array.forEach(largeSizes, enqueueDequeueTest);
    -    }
    -
    -    function testContainsSmall() {
    -      goog.array.forEach(smallSizes, containsTest);
    -    }
    -
    -    function testContainsLarge() {
    -      goog.array.forEach(largeSizes, containsTest);
    -    }
    -
    -    function testRemoveSmall() {
    -      goog.array.forEach(smallSizes, removeTest);
    -    }
    -
    -    function testRemoveLarge() {
    -      goog.array.forEach(largeSizes, removeTest);
    -    }
    -
    -    function testGetValuesSmall() {
    -      goog.array.forEach(smallSizes, getValuesTest);
    -    }
    -
    -    function testGetValuesLarge() {
    -      goog.array.forEach(largeSizes, getValuesTest);
    -    }
    -
    -  </script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/queue_test.html b/src/database/third_party/closure-library/closure/goog/structs/queue_test.html
    deleted file mode 100644
    index 84adad03228..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/queue_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.structs.Queue
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.structs.QueueTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/queue_test.js b/src/database/third_party/closure-library/closure/goog/structs/queue_test.js
    deleted file mode 100644
    index ea02c70a4cd..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/queue_test.js
    +++ /dev/null
    @@ -1,161 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.structs.QueueTest');
    -goog.setTestOnly('goog.structs.QueueTest');
    -
    -goog.require('goog.structs.Queue');
    -goog.require('goog.testing.jsunit');
    -
    -function stringifyQueue(q) {
    -  var values = q.getValues();
    -  var s = '';
    -  for (var i = 0; i < values.length; i++) {
    -    s += values[i];
    -  }
    -  return s;
    -}
    -
    -function createQueue() {
    -  var q = new goog.structs.Queue();
    -  q.enqueue('a');
    -  q.enqueue('b');
    -  q.enqueue('c');
    -  q.enqueue('a');
    -  q.dequeue();
    -  q.enqueue('b');
    -  q.enqueue('c');
    -  // q is now: bcabc
    -  return q;
    -}
    -
    -function testConstructor() {
    -  var q = new goog.structs.Queue();
    -  assertTrue('testConstructor(), queue should be empty initially', q.isEmpty());
    -  assertEquals('testConstructor(), count should be 0', q.getCount(), 0);
    -  assertEquals('testConstructor(), head element should be undefined', q.peek(),
    -      undefined);
    -}
    -
    -function testCount() {
    -  var q = createQueue();
    -  assertEquals('testCount(), count should be 5', q.getCount(), 5);
    -  q.enqueue('d');
    -  assertEquals('testCount(), count should be 6', q.getCount(), 6);
    -  q.dequeue();
    -  assertEquals('testCount(), count should be 5', q.getCount(), 5);
    -  q.clear();
    -  assertEquals('testCount(), count should be 0', q.getCount(), 0);
    -}
    -
    -function testEnqueue() {
    -  var q = new goog.structs.Queue();
    -  q.enqueue('a');
    -  assertEquals('testEnqueue(), count should be 1', q.getCount(), 1);
    -  q.enqueue('b');
    -  assertEquals('testEnqueue(), count should be 2', q.getCount(), 2);
    -  assertEquals('testEnqueue(), head element should be a', q.peek(), 'a');
    -  q.dequeue();
    -  assertEquals('testEnqueue(), count should be 1', q.getCount(), 1);
    -  assertEquals('testEnqueue(), head element should be b', q.peek(), 'b');
    -}
    -
    -function testDequeue() {
    -  var q = createQueue();
    -  assertEquals('testDequeue(), should return b', q.dequeue(), 'b');
    -  assertEquals('testDequeue(), should return b', q.dequeue(), 'c');
    -  assertEquals('testDequeue(), should return b', q.dequeue(), 'a');
    -  assertEquals('testDequeue(), should return b', q.dequeue(), 'b');
    -  assertEquals('testDequeue(), should return b', q.dequeue(), 'c');
    -  assertTrue('testDequeue(), queue should be empty', q.isEmpty());
    -  assertEquals('testDequeue(), should return undefined for empty queue',
    -      q.dequeue(), undefined);
    -}
    -
    -function testPeek() {
    -  var q = createQueue();
    -  assertEquals('testPeek(), should return b', q.peek(), 'b');
    -  assertEquals('testPeek(), dequeue should return peek() result',
    -      q.dequeue(), 'b');
    -  assertEquals('testPeek(), should return b', q.peek(), 'c');
    -  q.clear();
    -  assertEquals('testPeek(), should return undefined for empty queue',
    -      q.peek(), undefined);
    -}
    -
    -function testClear() {
    -  var q = createQueue();
    -  q.clear();
    -  assertTrue('testClear(), queue should be empty', q.isEmpty());
    -}
    -
    -function testQueue() {
    -  var q = createQueue();
    -  assertEquals('testQueue(), contents must be bcabc',
    -      stringifyQueue(q), 'bcabc');
    -}
    -
    -function testRemove() {
    -  var q = createQueue();
    -  assertEquals('testRemove(), contents must be bcabc',
    -      stringifyQueue(q), 'bcabc');
    -
    -  q.dequeue();
    -  assertEquals('testRemove(), contents must be cabc',
    -      stringifyQueue(q), 'cabc');
    -
    -  q.enqueue('a');
    -  assertEquals('testRemove(), contents must be cabca',
    -      stringifyQueue(q), 'cabca');
    -
    -  assertTrue('testRemove(), remove should have returned true', q.remove('c'));
    -  assertEquals('testRemove(), contents must be abca',
    -      stringifyQueue(q), 'abca');
    -
    -  assertTrue('testRemove(), remove should have returned true', q.remove('b'));
    -  assertEquals('testRemove(), contents must be aca', stringifyQueue(q), 'aca');
    -
    -  assertFalse('testRemove(), remove should have returned false', q.remove('b'));
    -  assertEquals('testRemove(), contents must be aca', stringifyQueue(q), 'aca');
    -
    -  assertTrue('testRemove(), remove should have returned true', q.remove('a'));
    -  assertEquals('testRemove(), contents must be ca', stringifyQueue(q), 'ca');
    -
    -  assertTrue('testRemove(), remove should have returned true', q.remove('a'));
    -  assertEquals('testRemove(), contents must be c', stringifyQueue(q), 'c');
    -
    -  assertTrue('testRemove(), remove should have returned true', q.remove('c'));
    -  assertEquals('testRemove(), contents must be empty', stringifyQueue(q), '');
    -
    -  q.enqueue('a');
    -  q.enqueue('b');
    -  q.enqueue('c');
    -  q.enqueue('a');
    -  q.dequeue();
    -  q.enqueue('b');
    -  q.enqueue('c');
    -  assertEquals('testRemove(), contents must be bcabc',
    -      stringifyQueue(q), 'bcabc');
    -  assertTrue('testRemove(), remove should have returned true', q.remove('c'));
    -  assertEquals('testRemove(), contents must be babc',
    -      stringifyQueue(q), 'babc');
    -}
    -
    -function testContains() {
    -  var q = createQueue();
    -  assertTrue('testContains(), contains should have returned true',
    -      q.contains('a'));
    -  assertFalse('testContains(), contains should have returned false',
    -      q.contains('foobar'));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/set.js b/src/database/third_party/closure-library/closure/goog/structs/set.js
    deleted file mode 100644
    index 334ecae7a82..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/set.js
    +++ /dev/null
    @@ -1,279 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Datastructure: Set.
    - *
    - * @author arv@google.com (Erik Arvidsson)
    - *
    - * This class implements a set data structure. Adding and removing is O(1). It
    - * supports both object and primitive values. Be careful because you can add
    - * both 1 and new Number(1), because these are not the same. You can even add
    - * multiple new Number(1) because these are not equal.
    - */
    -
    -
    -goog.provide('goog.structs.Set');
    -
    -goog.require('goog.structs');
    -goog.require('goog.structs.Collection');
    -goog.require('goog.structs.Map');
    -
    -
    -
    -/**
    - * A set that can contain both primitives and objects.  Adding and removing
    - * elements is O(1).  Primitives are treated as identical if they have the same
    - * type and convert to the same string.  Objects are treated as identical only
    - * if they are references to the same object.  WARNING: A goog.structs.Set can
    - * contain both 1 and (new Number(1)), because they are not the same.  WARNING:
    - * Adding (new Number(1)) twice will yield two distinct elements, because they
    - * are two different objects.  WARNING: Any object that is added to a
    - * goog.structs.Set will be modified!  Because goog.getUid() is used to
    - * identify objects, every object in the set will be mutated.
    - * @param {Array<T>|Object<?,T>=} opt_values Initial values to start with.
    - * @constructor
    - * @implements {goog.structs.Collection<T>}
    - * @final
    - * @template T
    - */
    -goog.structs.Set = function(opt_values) {
    -  this.map_ = new goog.structs.Map;
    -  if (opt_values) {
    -    this.addAll(opt_values);
    -  }
    -};
    -
    -
    -/**
    - * Obtains a unique key for an element of the set.  Primitives will yield the
    - * same key if they have the same type and convert to the same string.  Object
    - * references will yield the same key only if they refer to the same object.
    - * @param {*} val Object or primitive value to get a key for.
    - * @return {string} A unique key for this value/object.
    - * @private
    - */
    -goog.structs.Set.getKey_ = function(val) {
    -  var type = typeof val;
    -  if (type == 'object' && val || type == 'function') {
    -    return 'o' + goog.getUid(/** @type {Object} */ (val));
    -  } else {
    -    return type.substr(0, 1) + val;
    -  }
    -};
    -
    -
    -/**
    - * @return {number} The number of elements in the set.
    - * @override
    - */
    -goog.structs.Set.prototype.getCount = function() {
    -  return this.map_.getCount();
    -};
    -
    -
    -/**
    - * Add a primitive or an object to the set.
    - * @param {T} element The primitive or object to add.
    - * @override
    - */
    -goog.structs.Set.prototype.add = function(element) {
    -  this.map_.set(goog.structs.Set.getKey_(element), element);
    -};
    -
    -
    -/**
    - * Adds all the values in the given collection to this set.
    - * @param {Array<T>|goog.structs.Collection<T>|Object<?,T>} col A collection
    - *     containing the elements to add.
    - */
    -goog.structs.Set.prototype.addAll = function(col) {
    -  var values = goog.structs.getValues(col);
    -  var l = values.length;
    -  for (var i = 0; i < l; i++) {
    -    this.add(values[i]);
    -  }
    -};
    -
    -
    -/**
    - * Removes all values in the given collection from this set.
    - * @param {Array<T>|goog.structs.Collection<T>|Object<?,T>} col A collection
    - *     containing the elements to remove.
    - */
    -goog.structs.Set.prototype.removeAll = function(col) {
    -  var values = goog.structs.getValues(col);
    -  var l = values.length;
    -  for (var i = 0; i < l; i++) {
    -    this.remove(values[i]);
    -  }
    -};
    -
    -
    -/**
    - * Removes the given element from this set.
    - * @param {T} element The primitive or object to remove.
    - * @return {boolean} Whether the element was found and removed.
    - * @override
    - */
    -goog.structs.Set.prototype.remove = function(element) {
    -  return this.map_.remove(goog.structs.Set.getKey_(element));
    -};
    -
    -
    -/**
    - * Removes all elements from this set.
    - */
    -goog.structs.Set.prototype.clear = function() {
    -  this.map_.clear();
    -};
    -
    -
    -/**
    - * Tests whether this set is empty.
    - * @return {boolean} True if there are no elements in this set.
    - */
    -goog.structs.Set.prototype.isEmpty = function() {
    -  return this.map_.isEmpty();
    -};
    -
    -
    -/**
    - * Tests whether this set contains the given element.
    - * @param {T} element The primitive or object to test for.
    - * @return {boolean} True if this set contains the given element.
    - * @override
    - */
    -goog.structs.Set.prototype.contains = function(element) {
    -  return this.map_.containsKey(goog.structs.Set.getKey_(element));
    -};
    -
    -
    -/**
    - * Tests whether this set contains all the values in a given collection.
    - * Repeated elements in the collection are ignored, e.g.  (new
    - * goog.structs.Set([1, 2])).containsAll([1, 1]) is True.
    - * @param {goog.structs.Collection<T>|Object} col A collection-like object.
    - * @return {boolean} True if the set contains all elements.
    - */
    -goog.structs.Set.prototype.containsAll = function(col) {
    -  return goog.structs.every(col, this.contains, this);
    -};
    -
    -
    -/**
    - * Finds all values that are present in both this set and the given collection.
    - * @param {Array<S>|Object<?,S>} col A collection.
    - * @return {!goog.structs.Set<T|S>} A new set containing all the values
    - *     (primitives or objects) present in both this set and the given
    - *     collection.
    - * @template S
    - */
    -goog.structs.Set.prototype.intersection = function(col) {
    -  var result = new goog.structs.Set();
    -
    -  var values = goog.structs.getValues(col);
    -  for (var i = 0; i < values.length; i++) {
    -    var value = values[i];
    -    if (this.contains(value)) {
    -      result.add(value);
    -    }
    -  }
    -
    -  return result;
    -};
    -
    -
    -/**
    - * Finds all values that are present in this set and not in the given
    - * collection.
    - * @param {Array<T>|goog.structs.Collection<T>|Object<?,T>} col A collection.
    - * @return {!goog.structs.Set} A new set containing all the values
    - *     (primitives or objects) present in this set but not in the given
    - *     collection.
    - */
    -goog.structs.Set.prototype.difference = function(col) {
    -  var result = this.clone();
    -  result.removeAll(col);
    -  return result;
    -};
    -
    -
    -/**
    - * Returns an array containing all the elements in this set.
    - * @return {!Array<T>} An array containing all the elements in this set.
    - */
    -goog.structs.Set.prototype.getValues = function() {
    -  return this.map_.getValues();
    -};
    -
    -
    -/**
    - * Creates a shallow clone of this set.
    - * @return {!goog.structs.Set<T>} A new set containing all the same elements as
    - *     this set.
    - */
    -goog.structs.Set.prototype.clone = function() {
    -  return new goog.structs.Set(this);
    -};
    -
    -
    -/**
    - * Tests whether the given collection consists of the same elements as this set,
    - * regardless of order, without repetition.  Primitives are treated as equal if
    - * they have the same type and convert to the same string; objects are treated
    - * as equal if they are references to the same object.  This operation is O(n).
    - * @param {goog.structs.Collection<T>|Object} col A collection.
    - * @return {boolean} True if the given collection consists of the same elements
    - *     as this set, regardless of order, without repetition.
    - */
    -goog.structs.Set.prototype.equals = function(col) {
    -  return this.getCount() == goog.structs.getCount(col) && this.isSubsetOf(col);
    -};
    -
    -
    -/**
    - * Tests whether the given collection contains all the elements in this set.
    - * Primitives are treated as equal if they have the same type and convert to the
    - * same string; objects are treated as equal if they are references to the same
    - * object.  This operation is O(n).
    - * @param {goog.structs.Collection<T>|Object} col A collection.
    - * @return {boolean} True if this set is a subset of the given collection.
    - */
    -goog.structs.Set.prototype.isSubsetOf = function(col) {
    -  var colCount = goog.structs.getCount(col);
    -  if (this.getCount() > colCount) {
    -    return false;
    -  }
    -  // TODO(user) Find the minimal collection size where the conversion makes
    -  // the contains() method faster.
    -  if (!(col instanceof goog.structs.Set) && colCount > 5) {
    -    // Convert to a goog.structs.Set so that goog.structs.contains runs in
    -    // O(1) time instead of O(n) time.
    -    col = new goog.structs.Set(col);
    -  }
    -  return goog.structs.every(this, function(value) {
    -    return goog.structs.contains(col, value);
    -  });
    -};
    -
    -
    -/**
    - * Returns an iterator that iterates over the elements in this set.
    - * @param {boolean=} opt_keys This argument is ignored.
    - * @return {!goog.iter.Iterator} An iterator over the elements in this set.
    - */
    -goog.structs.Set.prototype.__iterator__ = function(opt_keys) {
    -  return this.map_.__iterator__(false);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/set_perf.html b/src/database/third_party/closure-library/closure/goog/structs/set_perf.html
    deleted file mode 100644
    index 76d3d874706..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/set_perf.html
    +++ /dev/null
    @@ -1,267 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -  <title>Closure Performance Tests - goog.ui.Set vs goog.ui.StringSet</title>
    -  <link rel="stylesheet" type="text/css" href="../testing/performancetable.css"/>
    -  <script src="../base.js"></script>
    -  <script>
    -    goog.require('goog.functions');
    -    goog.require('goog.string');
    -    goog.require('goog.structs.Set');
    -    goog.require('goog.structs.StringSet');
    -    goog.require('goog.testing.PerformanceTable');
    -    goog.require('goog.testing.PropertyReplacer');
    -    goog.require('goog.testing.jsunit');
    -  </script>
    -</head>
    -<body>
    -  <h1>goog.ui.Set and goog.ui.StringSet Performance Tests</h1>
    -  <p>
    -    <strong>User-agent:</strong>
    -    <script>document.write(navigator.userAgent);</script>
    -  </p>
    -  <div id="perfTable"></div>
    -  <hr>
    -
    -  <script>
    -    var table = new goog.testing.PerformanceTable(
    -        goog.dom.getElement('perfTable'));
    -
    -    // Number of operations to measure in each table line.
    -    var OPS_COUNT = 100000;
    -
    -    var stubs = new goog.testing.PropertyReplacer();
    -
    -    function tearDown() {
    -      stubs.reset();
    -    }
    -
    -    function testCreateSetFromArrayWithoutRepetition() {
    -      var values = []
    -      for (var i = 0; i < OPS_COUNT; i++) {
    -        values.push(i);
    -      }
    -
    -      table.run(function() {
    -        var s = new goog.structs.StringSet(values);
    -      }, 'Create string set from number array without repetition');
    -
    -      values = []
    -      for (var i = 0; i < OPS_COUNT; i++) {
    -        values.push(String(i));
    -      }
    -
    -      table.run(function() {
    -        var s = new goog.structs.StringSet(values);
    -      }, 'Create string set from string array without repetition');
    -    }
    -
    -    function testCreateSetWithoutRepetition() {
    -      table.run(function() {
    -        var s = new goog.structs.Set();
    -        for (var i = 0; i < OPS_COUNT; i++) {
    -          s.add(i);
    -        }
    -      }, 'Add elements to set without repetition');
    -
    -      table.run(function() {
    -        var s = new goog.structs.StringSet();
    -        for (var i = 0; i < OPS_COUNT; i++) {
    -          s.add(i);
    -        }
    -      }, 'Add elements to string set without repetition');
    -
    -      stubs.replace(goog.structs.StringSet, 'encode_', goog.functions.identity);
    -      stubs.replace(goog.structs.StringSet, 'decode_', goog.functions.identity);
    -
    -      table.run(function() {
    -        var s = new goog.structs.StringSet();
    -        for (var i = 0; i < OPS_COUNT; i++) {
    -          s.add(i);
    -        }
    -      }, 'Add elements to string set without repetition and escaping');
    -    }
    -
    -    function testCreateSetWithRepetition() {
    -      table.run(function() {
    -        var s = new goog.structs.Set();
    -        for (var n = 0; n < 10 ; n++) {
    -          for (var i = 0; i < OPS_COUNT / 10; i++) {
    -            s.add(i);
    -          }
    -        }
    -      }, 'Add elements to set with repetition');
    -
    -      table.run(function() {
    -        var s = new goog.structs.StringSet();
    -        for (var n = 0; n < 10; n++) {
    -          for (var i = 0; i < OPS_COUNT / 10; i++) {
    -            s.add(i);
    -          }
    -        }
    -      }, 'Add elements to string set with repetition');
    -    }
    -
    -    function testGetCount() {
    -      var bigSet = new goog.structs.Set;
    -      var bigStringSet = new goog.structs.StringSet;
    -      for (var i = 0; i < OPS_COUNT; i++) {
    -        bigSet.add(i);
    -        bigStringSet.add(i);
    -      }
    -
    -      table.run(function() {
    -        bigSet.getCount();
    -      }, 'Count the number of elements in a set');
    -
    -      table.run(function() {
    -        bigStringSet.getCount();
    -      }, 'Count the number of elements in a string set');
    -    }
    -
    -    function testGetValues() {
    -      var bigSet = new goog.structs.Set;
    -      var bigStringSet = new goog.structs.StringSet;
    -      for (var i = 0; i < OPS_COUNT; i++) {
    -        bigSet.add(i);
    -        bigStringSet.add(i);
    -      }
    -
    -      table.run(function() {
    -        bigSet.getValues();
    -      }, 'Convert a set to array');
    -
    -      table.run(function() {
    -        bigStringSet.getValues();
    -      }, 'Convert a string set to array');
    -    }
    -
    -    function testForEach() {
    -      var bigSet = new goog.structs.Set;
    -      var bigStringSet = new goog.structs.StringSet;
    -      for (var i = 0; i < OPS_COUNT; i++) {
    -        bigSet.add(i);
    -        bigStringSet.add(i);
    -      }
    -
    -      table.run(function() {
    -        goog.structs.forEach(bigSet, goog.nullFunction);
    -      }, 'Iterate over set with forEach');
    -
    -      table.run(function() {
    -        goog.structs.forEach(bigStringSet, goog.nullFunction);
    -      }, 'Iterate over string set with forEach');
    -    }
    -
    -    function testForEachWithLargeKeys() {
    -      var bigSet = new goog.structs.Set;
    -      var bigStringSet = new goog.structs.StringSet;
    -      for (var i = 0; i < OPS_COUNT / 100; i++) {
    -        bigSet.add(goog.string.repeat(String(i), 1000));
    -        bigStringSet.add(goog.string.repeat(String(i), 1000));
    -      }
    -
    -      table.run(function() {
    -        for (var i = 0; i < 100; i++) {
    -          goog.structs.forEach(bigSet, goog.nullFunction);
    -        }
    -      }, 'Iterate over set of large strings with forEach');
    -
    -      table.run(function() {
    -        for (var i = 0; i < 100; i++) {
    -          goog.structs.forEach(bigStringSet, goog.nullFunction);
    -        }
    -      }, 'Iterate over string set of large strings with forEach');
    -    }
    -
    -    function testAddRemove() {
    -      table.run(function() {
    -        var s = new goog.structs.Set();
    -        for (var i = 0; i < OPS_COUNT / 2; i++) {
    -          s.add(i);
    -        }
    -        for (var i = 0; i < OPS_COUNT / 2; i++) {
    -          s.remove(i);
    -        }
    -      }, 'Add then remove elements from set');
    -
    -      table.run(function() {
    -        var s = new goog.structs.StringSet();
    -        for (var i = 0; i < OPS_COUNT / 2; i++) {
    -          s.add(i);
    -        }
    -        for (var i = 0; i < OPS_COUNT / 2; i++) {
    -          s.remove(i);
    -        }
    -      }, 'Add then remove elements from string set');
    -    }
    -
    -    function testContains() {
    -      var bigSet = new goog.structs.Set;
    -      var bigStringSet = new goog.structs.StringSet;
    -      var arr = [];
    -      for (var i = 0; i < OPS_COUNT; i++) {
    -        bigSet.add(i);
    -        bigStringSet.add(i);
    -        arr.push(i);
    -      }
    -
    -      table.run(function() {
    -        for (var i = 0; i < OPS_COUNT; i++) {
    -          bigSet.contains(i);
    -        }
    -      }, 'Membership check for each element of set');
    -
    -      table.run(function() {
    -        for (var i = 0; i < OPS_COUNT; i++) {
    -          bigStringSet.contains(i);
    -        }
    -      }, 'Membership check for each element of string set with contains');
    -
    -      table.run(function() {
    -        bigStringSet.containsArray(arr);
    -      }, 'Membership check for each element of string set with containsArray');
    -
    -      stubs.replace(goog.structs.StringSet, 'encode_', goog.functions.identity);
    -      stubs.replace(goog.structs.StringSet, 'decode_', goog.functions.identity);
    -
    -      table.run(function() {
    -        for (var i = 0; i < OPS_COUNT; i++) {
    -          bigStringSet.contains(i);
    -        }
    -      }, 'Membership check for each element of string set without escaping');
    -    }
    -
    -    function testEquals() {
    -      table.run(function() {
    -        var s1 = new goog.structs.Set();
    -        var s2 = new goog.structs.Set();
    -        for (var i = 0; i < OPS_COUNT / 4; i++) {
    -          s1.add(i);
    -          s2.add(i);
    -        }
    -        s1.equals(s2);
    -      }, 'Create then compare two sets');
    -
    -      table.run(function() {
    -        var s1 = new goog.structs.StringSet();
    -        var s2 = new goog.structs.StringSet();
    -        for (var i = 0; i < OPS_COUNT / 4; i++) {
    -          s1.add(i);
    -          s2.add(i);
    -        }
    -        s1.equals(s2);
    -      }, 'Create then compare two string sets');
    -    }
    -  </script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/set_test.html b/src/database/third_party/closure-library/closure/goog/structs/set_test.html
    deleted file mode 100644
    index cf5fe850c4c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/set_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.structs.Set
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.structs.SetTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/set_test.js b/src/database/third_party/closure-library/closure/goog/structs/set_test.js
    deleted file mode 100644
    index e21e89dba20..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/set_test.js
    +++ /dev/null
    @@ -1,579 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.structs.SetTest');
    -goog.setTestOnly('goog.structs.SetTest');
    -
    -goog.require('goog.iter');
    -goog.require('goog.structs');
    -goog.require('goog.structs.Set');
    -goog.require('goog.testing.jsunit');
    -
    -var Set = goog.structs.Set;
    -
    -function stringifySet(s) {
    -  return goog.structs.getValues(s).join('');
    -}
    -
    -function testGetCount() {
    -  var s = new Set;
    -  var a = new String('a'); s.add(a);
    -  var b = new String('b'); s.add(b);
    -  var c = new String('c'); s.add(c);
    -  assertEquals('count, should be 3', s.getCount(), 3);
    -  var d = new String('d'); s.add(d);
    -  assertEquals('count, should be 4', s.getCount(), 4);
    -  s.remove(d);
    -  assertEquals('count, should be 3', s.getCount(), 3);
    -
    -  s = new Set;
    -  s.add('a');
    -  s.add('b');
    -  s.add('c');
    -  assertEquals('count, should be 3', s.getCount(), 3);
    -  s.add('d');
    -  assertEquals('count, should be 4', s.getCount(), 4);
    -  s.remove('d');
    -  assertEquals('count, should be 3', s.getCount(), 3);
    -}
    -
    -function testGetValues() {
    -  var s = new Set;
    -  var a = new String('a'); s.add(a);
    -  var b = new String('b'); s.add(b);
    -  var c = new String('c'); s.add(c);
    -  var d = new String('d'); s.add(d);
    -  assertEquals(s.getValues().join(''), 'abcd');
    -
    -  var s = new Set;
    -  s.add('a');
    -  s.add('b');
    -  s.add('c');
    -  s.add('d');
    -  assertEquals(s.getValues().join(''), 'abcd');
    -}
    -
    -function testContains() {
    -  var s = new Set;
    -  var a = new String('a'); s.add(a);
    -  var b = new String('b'); s.add(b);
    -  var c = new String('c'); s.add(c);
    -  var d = new String('d'); s.add(d);
    -  var e = new String('e');
    -
    -  assertTrue("contains, Should contain 'a'", s.contains(a));
    -  assertFalse("contains, Should not contain 'e'", s.contains(e));
    -
    -  s = new Set;
    -  s.add('a');
    -  s.add('b');
    -  s.add('c');
    -  s.add('d');
    -
    -  assertTrue("contains, Should contain 'a'", s.contains('a'));
    -  assertFalse("contains, Should not contain 'e'", s.contains('e'));
    -}
    -
    -function testContainsFunctionValue() {
    -  var s = new Set;
    -
    -  var fn1 = function() {};
    -
    -  assertFalse(s.contains(fn1));
    -  s.add(fn1);
    -  assertTrue(s.contains(fn1));
    -
    -  var fn2 = function() {};
    -
    -  assertFalse(s.contains(fn2));
    -  s.add(fn2);
    -  assertTrue(s.contains(fn2));
    -
    -  assertEquals(s.getCount(), 2);
    -}
    -
    -function testContainsAll() {
    -  var set = new Set([1, 2, 3]);
    -
    -  assertTrue('{1, 2, 3} contains []', set.containsAll([]));
    -  assertTrue('{1, 2, 3} contains [1]', set.containsAll([1]));
    -  assertTrue('{1, 2, 3} contains [1, 1]', set.containsAll([1, 1]));
    -  assertTrue('{1, 2, 3} contains [3, 2, 1]', set.containsAll([3, 2, 1]));
    -  assertFalse("{1, 2, 3} doesn't contain [4]", set.containsAll([4]));
    -  assertFalse("{1, 2, 3} doesn't contain [1, 4]", set.containsAll([1, 4]));
    -
    -  assertTrue('{1, 2, 3} contains {a: 1}', set.containsAll({a: 1}));
    -  assertFalse("{1, 2, 3} doesn't contain {a: 4}", set.containsAll({a: 4}));
    -
    -  assertTrue('{1, 2, 3} contains {1}', set.containsAll(new Set([1])));
    -  assertFalse("{1, 2, 3} doesn't contain {4}", set.containsAll(new Set([4])));
    -}
    -
    -function testIntersection() {
    -  var emptySet = new Set;
    -
    -  assertTrue('intersection of empty set and [] should be empty',
    -      emptySet.intersection([]).isEmpty());
    -  assertIntersection('intersection of 2 empty sets should be empty',
    -      emptySet, new Set(), new Set());
    -
    -  var abcdSet = new Set();
    -  abcdSet.add('a');
    -  abcdSet.add('b');
    -  abcdSet.add('c');
    -  abcdSet.add('d');
    -
    -  assertTrue('intersection of populated set and [] should be empty',
    -      abcdSet.intersection([]).isEmpty());
    -  assertIntersection(
    -      'intersection of populated set and empty set should be empty',
    -      abcdSet, new Set(), new Set());
    -
    -  var bcSet = new Set(['b', 'c']);
    -  assertIntersection('intersection of [a,b,c,d] and [b,c]',
    -      abcdSet, bcSet, bcSet);
    -
    -  var bceSet = new Set(['b', 'c', 'e']);
    -  assertIntersection('intersection of [a,b,c,d] and [b,c,e]',
    -      abcdSet, bceSet, bcSet);
    -}
    -
    -function testDifference() {
    -  var emptySet = new Set;
    -
    -  assertTrue('difference of empty set and [] should be empty',
    -      emptySet.difference([]).isEmpty());
    -  assertTrue('difference of 2 empty sets should be empty',
    -      emptySet.difference(new Set()).isEmpty());
    -
    -  var abcdSet = new Set(['a', 'b', 'c', 'd']);
    -
    -  assertTrue('difference of populated set and [] should be the populated set',
    -      abcdSet.difference([]).equals(abcdSet));
    -  assertTrue(
    -      'difference of populated set and empty set should be the populated set',
    -      abcdSet.difference(new Set()).equals(abcdSet));
    -  assertTrue('difference of two identical sets should be the empty set',
    -      abcdSet.difference(abcdSet).equals(new Set()));
    -
    -  var bcSet = new Set(['b', 'c']);
    -  assertTrue('difference of [a,b,c,d] and [b,c] shoule be [a,d]',
    -      abcdSet.difference(bcSet).equals(new Set(['a', 'd'])));
    -  assertTrue('difference of [b,c] and [a,b,c,d] should be the empty set',
    -      bcSet.difference(abcdSet).equals(new Set()));
    -
    -  var xyzSet = new Set(['x', 'y', 'z']);
    -  assertTrue('difference of [a,b,c,d] and [x,y,z] should be the [a,b,c,d]',
    -      abcdSet.difference(xyzSet).equals(abcdSet));
    -}
    -
    -
    -/**
    - * Helper function to assert intersection is commutative.
    - */
    -function assertIntersection(msg, set1, set2, expectedIntersection) {
    -  assertTrue(msg + ': set1->set2',
    -      set1.intersection(set2).equals(expectedIntersection));
    -  assertTrue(msg + ': set2->set1',
    -      set2.intersection(set1).equals(expectedIntersection));
    -}
    -
    -function testRemoveAll() {
    -  assertRemoveAll('removeAll of empty set from empty set', [], [], []);
    -  assertRemoveAll('removeAll of empty set from populated set',
    -      ['a', 'b', 'c', 'd'], [], ['a', 'b', 'c', 'd']);
    -  assertRemoveAll('removeAll of [a,d] from [a,b,c,d]',
    -      ['a', 'b', 'c', 'd'], ['a', 'd'], ['b', 'c']);
    -  assertRemoveAll('removeAll of [b,c] from [a,b,c,d]',
    -      ['a', 'b', 'c', 'd'], ['b', 'c'], ['a', 'd']);
    -  assertRemoveAll('removeAll of [b,c,e] from [a,b,c,d]',
    -      ['a', 'b', 'c', 'd'], ['b', 'c', 'e'], ['a', 'd']);
    -  assertRemoveAll('removeAll of [a,b,c,d] from [a,d]',
    -      ['a', 'd'], ['a', 'b', 'c', 'd'], []);
    -  assertRemoveAll('removeAll of [a,b,c,d] from [b,c]',
    -      ['b', 'c'], ['a', 'b', 'c', 'd'], []);
    -  assertRemoveAll('removeAll of [a,b,c,d] from [b,c,e]',
    -      ['b', 'c', 'e'], ['a', 'b', 'c', 'd'], ['e']);
    -}
    -
    -
    -/**
    - * Helper function to test removeAll.
    - */
    -function assertRemoveAll(msg, elements1, elements2, expectedResult) {
    -  var set1 = new Set(elements1);
    -  var set2 = new Set(elements2);
    -  set1.removeAll(set2);
    -
    -  assertTrue(msg + ': set1 count increased after removeAll',
    -      elements1.length >= set1.getCount());
    -  assertEquals(msg + ': set2 count changed after removeAll',
    -      elements2.length, set2.getCount());
    -  assertTrue(msg + ': wrong set1 after removeAll', set1.equals(expectedResult));
    -  assertIntersection(msg + ': non-empty intersection after removeAll',
    -      set1, set2, []);
    -}
    -
    -function testAdd() {
    -  var s = new Set;
    -  var a = new String('a');
    -  var b = new String('b');
    -  s.add(a);
    -  assertTrue(s.contains(a));
    -  s.add(b);
    -  assertTrue(s.contains(b));
    -
    -  s = new Set;
    -  s.add('a');
    -  assertTrue(s.contains('a'));
    -  s.add('b');
    -  assertTrue(s.contains('b'));
    -  s.add(null);
    -  assertTrue('contains null', s.contains(null));
    -  assertFalse('does not contain "null"', s.contains('null'));
    -}
    -
    -
    -function testClear() {
    -  var s = new Set;
    -  var a = new String('a'); s.add(a);
    -  var b = new String('b'); s.add(b);
    -  var c = new String('c'); s.add(c);
    -  var d = new String('d'); s.add(d);
    -  s.clear();
    -  assertTrue('cleared so it should be empty', s.isEmpty());
    -  assertTrue("cleared so it should not contain 'a' key", !s.contains(a));
    -
    -  s = new Set;
    -  s.add('a');
    -  s.add('b');
    -  s.add('c');
    -  s.add('d');
    -  s.clear();
    -  assertTrue('cleared so it should be empty', s.isEmpty());
    -  assertTrue("cleared so it should not contain 'a' key", !s.contains('a'));
    -}
    -
    -
    -function testAddAll() {
    -  var s = new Set;
    -  var a = new String('a');
    -  var b = new String('b');
    -  var c = new String('c');
    -  var d = new String('d');
    -  s.addAll([a, b, c, d]);
    -  assertTrue('addAll so it should not be empty', !s.isEmpty());
    -  assertTrue("addAll so it should contain 'c' key", s.contains(c));
    -
    -  var s2 = new Set;
    -  s2.addAll(s);
    -  assertTrue('addAll so it should not be empty', !s2.isEmpty());
    -  assertTrue("addAll so it should contain 'c' key", s2.contains(c));
    -
    -
    -  s = new Set;
    -  s.addAll(['a', 'b', 'c', 'd']);
    -  assertTrue('addAll so it should not be empty', !s.isEmpty());
    -  assertTrue("addAll so it should contain 'c' key", s.contains('c'));
    -
    -  s2 = new Set;
    -  s2.addAll(s);
    -  assertTrue('addAll so it should not be empty', !s2.isEmpty());
    -  assertTrue("addAll so it should contain 'c' key", s2.contains('c'));
    -}
    -
    -
    -function testConstructor() {
    -  var s = new Set;
    -  var a = new String('a'); s.add(a);
    -  var b = new String('b'); s.add(b);
    -  var c = new String('c'); s.add(c);
    -  var d = new String('d'); s.add(d);
    -  var s2 = new Set(s);
    -  assertFalse('constr with Set so it should not be empty', s2.isEmpty());
    -  assertTrue('constr with Set so it should contain c', s2.contains(c));
    -
    -  s = new Set;
    -  s.add('a');
    -  s.add('b');
    -  s.add('c');
    -  s.add('d');
    -  s2 = new Set(s);
    -  assertFalse('constr with Set so it should not be empty', s2.isEmpty());
    -  assertTrue('constr with Set so it should contain c', s2.contains('c'));
    -}
    -
    -
    -function testClone() {
    -  var s = new Set;
    -  var a = new String('a'); s.add(a);
    -  var b = new String('b'); s.add(b);
    -  var c = new String('c'); s.add(c);
    -  var d = new String('d'); s.add(d);
    -
    -  var s2 = s.clone();
    -  assertFalse('clone so it should not be empty', s2.isEmpty());
    -  assertTrue("clone so it should contain 'c' key", s2.contains(c));
    -
    -  var s = new Set;
    -  s.add('a');
    -  s.add('b');
    -  s.add('c');
    -  s.add('d');
    -
    -  s2 = s.clone();
    -  assertFalse('clone so it should not be empty', s2.isEmpty());
    -  assertTrue("clone so it should contain 'c' key", s2.contains('c'));
    -}
    -
    -
    -/**
    - * Helper method for testEquals().
    - * @param {Object} a First element to use in the tests.
    - * @param {Object} b Second element to use in the tests.
    - * @param {Object} c Third element to use in the tests.
    - * @param {Object} d Fourth element to use in the tests.
    - */
    -function helperForTestEquals(a, b, c, d) {
    -  var s = new Set([a, b, c]);
    -
    -  assertTrue('set == itself', s.equals(s));
    -  assertTrue('set == same set', s.equals(new Set([a, b, c])));
    -  assertTrue('set == its clone', s.equals(s.clone()));
    -  assertTrue('set == array of same elements', s.equals([a, b, c]));
    -  assertTrue('set == array of same elements in different order',
    -             s.equals([c, b, a]));
    -
    -  assertFalse('set != empty set', s.equals(new Set));
    -  assertFalse('set != its subset', s.equals(new Set([a, c])));
    -  assertFalse('set != its superset',
    -              s.equals(new Set([a, b, c, d])));
    -  assertFalse('set != different set',
    -              s.equals(new Set([b, c, d])));
    -  assertFalse('set != its subset as array', s.equals([a, c]));
    -  assertFalse('set != its superset as array', s.equals([a, b, c, d]));
    -  assertFalse('set != different set as array', s.equals([b, c, d]));
    -  assertFalse('set != [a, b, c, c]', s.equals([a, b, c, c]));
    -  assertFalse('set != [a, b, b]', s.equals([a, b, b]));
    -  assertFalse('set != [a, a]', s.equals([a, a]));
    -}
    -
    -
    -function testEquals() {
    -  helperForTestEquals(1, 2, 3, 4);
    -  helperForTestEquals('a', 'b', 'c', 'd');
    -  helperForTestEquals(new String('a'), new String('b'),
    -                      new String('c'), new String('d'));
    -}
    -
    -
    -/**
    - * Helper method for testIsSubsetOf().
    - * @param {Object} a First element to use in the tests.
    - * @param {Object} b Second element to use in the tests.
    - * @param {Object} c Third element to use in the tests.
    - * @param {Object} d Fourth element to use in the tests.
    - */
    -function helperForTestIsSubsetOf(a, b, c, d) {
    -  var s = new Set([a, b, c]);
    -
    -  assertTrue('set <= itself', s.isSubsetOf(s));
    -  assertTrue('set <= same set',
    -             s.isSubsetOf(new Set([a, b, c])));
    -  assertTrue('set <= its clone', s.isSubsetOf(s.clone()));
    -  assertTrue('set <= array of same elements', s.isSubsetOf([a, b, c]));
    -  assertTrue('set <= array of same elements in different order',
    -             s.equals([c, b, a]));
    -
    -  assertTrue('set <= Set([a, b, c, d])',
    -             s.isSubsetOf(new Set([a, b, c, d])));
    -  assertTrue('set <= [a, b, c, d]', s.isSubsetOf([a, b, c, d]));
    -  assertTrue('set <= [a, b, c, c]', s.isSubsetOf([a, b, c, c]));
    -
    -  assertFalse('set !<= Set([a, b])',
    -              s.isSubsetOf(new Set([a, b])));
    -  assertFalse('set !<= [a, b]', s.isSubsetOf([a, b]));
    -  assertFalse('set !<= Set([c, d])',
    -              s.isSubsetOf(new Set([c, d])));
    -  assertFalse('set !<= [c, d]', s.isSubsetOf([c, d]));
    -  assertFalse('set !<= Set([a, c, d])',
    -              s.isSubsetOf(new Set([a, c, d])));
    -  assertFalse('set !<= [a, c, d]', s.isSubsetOf([a, c, d]));
    -  assertFalse('set !<= [a, a, b]', s.isSubsetOf([a, a, b]));
    -  assertFalse('set !<= [a, a, b, b]', s.isSubsetOf([a, a, b, b]));
    -}
    -
    -
    -function testIsSubsetOf() {
    -  helperForTestIsSubsetOf(1, 2, 3, 4);
    -  helperForTestIsSubsetOf('a', 'b', 'c', 'd');
    -  helperForTestIsSubsetOf(new String('a'), new String('b'),
    -                          new String('c'), new String('d'));
    -}
    -
    -
    -function testForEach() {
    -  var s = new Set;
    -  var a = new String('a'); s.add(a);
    -  var b = new String('b'); s.add(b);
    -  var c = new String('c'); s.add(c);
    -  var d = new String('d'); s.add(d);
    -  var str = '';
    -  goog.structs.forEach(s, function(val, key, set) {
    -    assertUndefined(key);
    -    assertEquals(s, set);
    -    str += val;
    -  });
    -  assertEquals(str, 'abcd');
    -
    -  s = new Set;
    -  s.add('a');
    -  s.add('b');
    -  s.add('c');
    -  s.add('d');
    -  str = '';
    -  goog.structs.forEach(s, function(val, key, set) {
    -    assertUndefined(key);
    -    assertEquals(s, set);
    -    str += val;
    -  });
    -  assertEquals(str, 'abcd');
    -}
    -
    -
    -function testFilter() {
    -  var s = new Set;
    -  var a = new Number(0); s.add(a);
    -  var b = new Number(1); s.add(b);
    -  var c = new Number(2); s.add(c);
    -  var d = new Number(3); s.add(d);
    -
    -  var s2 = goog.structs.filter(s, function(val, key, set) {
    -    assertUndefined(key);
    -    assertEquals(s, set);
    -    return val > 1;
    -  });
    -  assertEquals(stringifySet(s2), '23');
    -
    -  s = new Set;
    -  s.add(0);
    -  s.add(1);
    -  s.add(2);
    -  s.add(3);
    -
    -  s2 = goog.structs.filter(s, function(val, key, set) {
    -    assertUndefined(key);
    -    assertEquals(s, set);
    -    return val > 1;
    -  });
    -  assertEquals(stringifySet(s2), '23');
    -}
    -
    -
    -function testSome() {
    -  var s = new Set;
    -  var a = new Number(0); s.add(a);
    -  var b = new Number(1); s.add(b);
    -  var c = new Number(2); s.add(c);
    -  var d = new Number(3); s.add(d);
    -
    -  var b = goog.structs.some(s, function(val, key, s2) {
    -    assertUndefined(key);
    -    assertEquals(s, s2);
    -    return val > 1;
    -  });
    -  assertTrue(b);
    -  var b = goog.structs.some(s, function(val, key, s2) {
    -    assertUndefined(key);
    -    assertEquals(s, s2);
    -    return val > 100;
    -  });
    -  assertFalse(b);
    -
    -  s = new Set;
    -  s.add(0);
    -  s.add(1);
    -  s.add(2);
    -  s.add(3);
    -
    -  b = goog.structs.some(s, function(val, key, s2) {
    -    assertUndefined(key);
    -    assertEquals(s, s2);
    -    return val > 1;
    -  });
    -  assertTrue(b);
    -  b = goog.structs.some(s, function(val, key, s2) {
    -    assertUndefined(key);
    -    assertEquals(s, s2);
    -    return val > 100;
    -  });
    -  assertFalse(b);
    -}
    -
    -
    -function testEvery() {
    -  var s = new Set;
    -  var a = new Number(0); s.add(a);
    -  var b = new Number(1); s.add(b);
    -  var c = new Number(2); s.add(c);
    -  var d = new Number(3); s.add(d);
    -
    -  var b = goog.structs.every(s, function(val, key, s2) {
    -    assertUndefined(key);
    -    assertEquals(s, s2);
    -    return val >= 0;
    -  });
    -  assertTrue(b);
    -  b = goog.structs.every(s, function(val, key, s2) {
    -    assertUndefined(key);
    -    assertEquals(s, s2);
    -    return val > 1;
    -  });
    -  assertFalse(b);
    -
    -  s = new Set;
    -  s.add(0);
    -  s.add(1);
    -  s.add(2);
    -  s.add(3);
    -
    -  b = goog.structs.every(s, function(val, key, s2) {
    -    assertUndefined(key);
    -    assertEquals(s, s2);
    -    return val >= 0;
    -  });
    -  assertTrue(b);
    -  b = goog.structs.every(s, function(val, key, s2) {
    -    assertUndefined(key);
    -    assertEquals(s, s2);
    -    return val > 1;
    -  });
    -  assertFalse(b);
    -}
    -
    -function testIterator() {
    -  var s = new Set;
    -  s.add(0);
    -  s.add(1);
    -  s.add(2);
    -  s.add(3);
    -  s.add(4);
    -
    -  assertEquals('01234', goog.iter.join(s, ''));
    -
    -  s.remove(1);
    -  s.remove(3);
    -
    -  assertEquals('024', goog.iter.join(s, ''));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/simplepool.js b/src/database/third_party/closure-library/closure/goog/structs/simplepool.js
    deleted file mode 100644
    index ff400fccbc3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/simplepool.js
    +++ /dev/null
    @@ -1,200 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Datastructure: Pool.
    - *
    - *
    - * A generic class for handling pools of objects that is more efficient than
    - * goog.structs.Pool because it doesn't maintain a list of objects that are in
    - * use. See constructor comment.
    - */
    -
    -
    -goog.provide('goog.structs.SimplePool');
    -
    -goog.require('goog.Disposable');
    -
    -
    -
    -/**
    - * A generic pool class. Simpler and more efficient than goog.structs.Pool
    - * because it doesn't maintain a list of objects that are in use. This class
    - * has constant overhead and doesn't create any additional objects as part of
    - * the pool management after construction time.
    - *
    - * IMPORTANT: If the objects being pooled are arrays or maps that can have
    - * unlimited number of properties, they need to be cleaned before being
    - * returned to the pool.
    - *
    - * Also note that {@see goog.object.clean} actually allocates an array to clean
    - * the object passed to it, so simply using this function would defy the
    - * purpose of using the pool.
    - *
    - * @param {number} initialCount Initial number of objects to populate the free
    - *     pool at construction time.
    - * @param {number} maxCount Maximum number of objects to keep in the free pool.
    - * @constructor
    - * @extends {goog.Disposable}
    - * @template T
    - */
    -goog.structs.SimplePool = function(initialCount, maxCount) {
    -  goog.Disposable.call(this);
    -
    -  /**
    -   * Function for overriding createObject. The avoids a common case requiring
    -   * subclassing this class.
    -   * @private {Function}
    -   */
    -  this.createObjectFn_ = null;
    -
    -  /**
    -   * Function for overriding disposeObject. The avoids a common case requiring
    -   * subclassing this class.
    -   * @private {Function}
    -   */
    -  this.disposeObjectFn_ = null;
    -
    -  /**
    -   * Maximum number of objects allowed
    -   * @private {number}
    -   */
    -  this.maxCount_ = maxCount;
    -
    -  /**
    -   * Queue used to store objects that are currently in the pool and available
    -   * to be used.
    -   * @private {Array<T>}
    -   */
    -  this.freeQueue_ = [];
    -
    -  this.createInitial_(initialCount);
    -};
    -goog.inherits(goog.structs.SimplePool, goog.Disposable);
    -
    -
    -/**
    - * Sets the {@code createObject} function which is used for creating a new
    - * object in the pool.
    - * @param {Function} createObjectFn Create object function which returns the
    - *     newly created object.
    - */
    -goog.structs.SimplePool.prototype.setCreateObjectFn = function(createObjectFn) {
    -  this.createObjectFn_ = createObjectFn;
    -};
    -
    -
    -/**
    - * Sets the {@code disposeObject} function which is used for disposing of an
    - * object in the pool.
    - * @param {Function} disposeObjectFn Dispose object function which takes the
    - *     object to dispose as a parameter.
    - */
    -goog.structs.SimplePool.prototype.setDisposeObjectFn = function(
    -    disposeObjectFn) {
    -  this.disposeObjectFn_ = disposeObjectFn;
    -};
    -
    -
    -/**
    - * Gets an unused object from the the pool, if there is one available,
    - * otherwise creates a new one.
    - * @return {T} An object from the pool or a new one if necessary.
    - */
    -goog.structs.SimplePool.prototype.getObject = function() {
    -  if (this.freeQueue_.length) {
    -    return this.freeQueue_.pop();
    -  }
    -  return this.createObject();
    -};
    -
    -
    -/**
    - * Returns an object to the pool so that it can be reused. If the pool is
    - * already full, the object is disposed instead.
    - * @param {T} obj The object to release.
    - */
    -goog.structs.SimplePool.prototype.releaseObject = function(obj) {
    -  if (this.freeQueue_.length < this.maxCount_) {
    -    this.freeQueue_.push(obj);
    -  } else {
    -    this.disposeObject(obj);
    -  }
    -};
    -
    -
    -/**
    - * Populates the pool with initialCount objects.
    - * @param {number} initialCount The number of objects to add to the pool.
    - * @private
    - */
    -goog.structs.SimplePool.prototype.createInitial_ = function(initialCount) {
    -  if (initialCount > this.maxCount_) {
    -    throw Error('[goog.structs.SimplePool] Initial cannot be greater than max');
    -  }
    -  for (var i = 0; i < initialCount; i++) {
    -    this.freeQueue_.push(this.createObject());
    -  }
    -};
    -
    -
    -/**
    - * Should be overridden by sub-classes to return an instance of the object type
    - * that is expected in the pool.
    - * @return {T} The created object.
    - */
    -goog.structs.SimplePool.prototype.createObject = function() {
    -  if (this.createObjectFn_) {
    -    return this.createObjectFn_();
    -  } else {
    -    return {};
    -  }
    -};
    -
    -
    -/**
    - * Should be overrideen to dispose of an object. Default implementation is to
    - * remove all of the object's members, which should render it useless. Calls the
    - *  object's dispose method, if available.
    - * @param {T} obj The object to dispose.
    - */
    -goog.structs.SimplePool.prototype.disposeObject = function(obj) {
    -  if (this.disposeObjectFn_) {
    -    this.disposeObjectFn_(obj);
    -  } else if (goog.isObject(obj)) {
    -    if (goog.isFunction(obj.dispose)) {
    -      obj.dispose();
    -    } else {
    -      for (var i in obj) {
    -        delete obj[i];
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Disposes of the pool and all objects currently held in the pool.
    - * @override
    - * @protected
    - */
    -goog.structs.SimplePool.prototype.disposeInternal = function() {
    -  goog.structs.SimplePool.superClass_.disposeInternal.call(this);
    -  // Call disposeObject on each object held by the pool.
    -  var freeQueue = this.freeQueue_;
    -  while (freeQueue.length) {
    -    this.disposeObject(freeQueue.pop());
    -  }
    -  delete this.freeQueue_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/stringset.js b/src/database/third_party/closure-library/closure/goog/structs/stringset.js
    deleted file mode 100644
    index 6c6cf3bc623..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/stringset.js
    +++ /dev/null
    @@ -1,405 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Data structure for set of strings.
    - *
    - *
    - * This class implements a set data structure for strings. Adding and removing
    - * is O(1). It doesn't contain any bloat from {@link goog.structs.Set}, i.e.
    - * it isn't optimized for IE6 garbage collector (see the description of
    - * {@link goog.structs.Map#keys_} for details), and it distinguishes its
    - * elements by their string value not by hash code.
    - * The implementation assumes that no new keys are added to Object.prototype.
    - */
    -
    -goog.provide('goog.structs.StringSet');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.iter');
    -
    -
    -
    -/**
    - * Creates a set of strings.
    - * @param {!Array<?>=} opt_elements Elements to add to the set. The non-string
    - *     items will be converted to strings, so 15 and '15' will mean the same.
    - * @constructor
    - * @final
    - */
    -goog.structs.StringSet = function(opt_elements) {
    -  /**
    -   * An object storing the escaped elements of the set in its keys.
    -   * @type {!Object}
    -   * @private
    -   */
    -  this.elements_ = {};
    -
    -  if (opt_elements) {
    -    for (var i = 0; i < opt_elements.length; i++) {
    -      this.elements_[goog.structs.StringSet.encode_(opt_elements[i])] = null;
    -    }
    -  }
    -
    -  goog.asserts.assertObjectPrototypeIsIntact();
    -};
    -
    -
    -/**
    - * Empty object. Referring to it is faster than creating a new empty object in
    - * {@code goog.structs.StringSet.encode_}.
    - * @const {!Object}
    - * @private
    - */
    -goog.structs.StringSet.EMPTY_OBJECT_ = {};
    -
    -
    -/**
    - * The '__proto__' and the '__count__' keys aren't enumerable in Firefox, and
    - * 'toString', 'valueOf', 'constructor', etc. aren't enumerable in IE so they
    - * have to be escaped before they are added to the internal object.
    - * NOTE: When a new set is created, 50-80% of the CPU time is spent in encode.
    - * @param {*} element The element to escape.
    - * @return {*} The escaped element or the element itself if it doesn't have to
    - *     be escaped.
    - * @private
    - */
    -goog.structs.StringSet.encode_ = function(element) {
    -  return element in goog.structs.StringSet.EMPTY_OBJECT_ ||
    -      String(element).charCodeAt(0) == 32 ? ' ' + element : element;
    -};
    -
    -
    -/**
    - * Inverse function of {@code goog.structs.StringSet.encode_}.
    - * NOTE: forEach would be 30% faster in FF if the compiler inlined decode.
    - * @param {string} key The escaped element used as the key of the internal
    - *     object.
    - * @return {string} The unescaped element.
    - * @private
    - */
    -goog.structs.StringSet.decode_ = function(key) {
    -  return key.charCodeAt(0) == 32 ? key.substr(1) : key;
    -};
    -
    -
    -/**
    - * Adds a single element to the set.
    - * @param {*} element The element to add. It will be converted to string.
    - */
    -goog.structs.StringSet.prototype.add = function(element) {
    -  this.elements_[goog.structs.StringSet.encode_(element)] = null;
    -};
    -
    -
    -/**
    - * Adds a the elements of an array to this set.
    - * @param {!Array<?>} arr The array to add the elements of.
    - */
    -goog.structs.StringSet.prototype.addArray = function(arr) {
    -  for (var i = 0; i < arr.length; i++) {
    -    this.elements_[goog.structs.StringSet.encode_(arr[i])] = null;
    -  }
    -};
    -
    -
    -/**
    - * Adds the elements which are in {@code set1} but not in {@code set2} to this
    - * set.
    - * @param {!goog.structs.StringSet} set1 First set.
    - * @param {!goog.structs.StringSet} set2 Second set.
    - * @private
    - */
    -goog.structs.StringSet.prototype.addDifference_ = function(set1, set2) {
    -  for (var key in set1.elements_) {
    -    if (!(key in set2.elements_)) {
    -      this.elements_[key] = null;
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Adds a the elements of a set to this set.
    - * @param {!goog.structs.StringSet} stringSet The set to add the elements of.
    - */
    -goog.structs.StringSet.prototype.addSet = function(stringSet) {
    -  for (var key in stringSet.elements_) {
    -    this.elements_[key] = null;
    -  }
    -};
    -
    -
    -/**
    - * Removes all elements of the set.
    - */
    -goog.structs.StringSet.prototype.clear = function() {
    -  this.elements_ = {};
    -};
    -
    -
    -/**
    - * @return {!goog.structs.StringSet} Clone of the set.
    - */
    -goog.structs.StringSet.prototype.clone = function() {
    -  var ret = new goog.structs.StringSet;
    -  ret.addSet(this);
    -  return ret;
    -};
    -
    -
    -/**
    - * Tells if the set contains the given element.
    - * @param {*} element The element to check.
    - * @return {boolean} Whether it is in the set.
    - */
    -goog.structs.StringSet.prototype.contains = function(element) {
    -  return goog.structs.StringSet.encode_(element) in this.elements_;
    -};
    -
    -
    -/**
    - * Tells if the set contains all elements of the array.
    - * @param {!Array<?>} arr The elements to check.
    - * @return {boolean} Whether they are in the set.
    - */
    -goog.structs.StringSet.prototype.containsArray = function(arr) {
    -  for (var i = 0; i < arr.length; i++) {
    -    if (!(goog.structs.StringSet.encode_(arr[i]) in this.elements_)) {
    -      return false;
    -    }
    -  }
    -  return true;
    -};
    -
    -
    -/**
    - * Tells if this set has the same elements as the given set.
    - * @param {!goog.structs.StringSet} stringSet The other set.
    - * @return {boolean} Whether they have the same elements.
    - */
    -goog.structs.StringSet.prototype.equals = function(stringSet) {
    -  return this.isSubsetOf(stringSet) && stringSet.isSubsetOf(this);
    -};
    -
    -
    -/**
    - * Calls a function for each element in the set.
    - * @param {function(string, undefined, !goog.structs.StringSet)} f The function
    - *     to call for every element. It takes the element, undefined (because sets
    - *     have no notion of keys), and the set.
    - * @param {Object=} opt_obj The object to be used as the value of 'this'
    - *     within {@code f}.
    - */
    -goog.structs.StringSet.prototype.forEach = function(f, opt_obj) {
    -  for (var key in this.elements_) {
    -    f.call(opt_obj, goog.structs.StringSet.decode_(key), undefined, this);
    -  }
    -};
    -
    -
    -/**
    - * Counts the number of elements in the set in linear time.
    - * NOTE: getCount is always called at most once per set instance in google3.
    - * If this usage pattern won't change, the linear getCount implementation is
    - * better, because
    - * <li>populating a set and getting the number of elements in it takes the same
    - * amount of time as keeping a count_ member up to date and getting its value;
    - * <li>if getCount is not called, adding and removing elements have no overhead.
    - * @return {number} The number of elements in the set.
    - */
    -goog.structs.StringSet.prototype.getCount = Object.keys ?
    -    function() {
    -      return Object.keys(this.elements_).length;
    -    } :
    -    function() {
    -      var count = 0;
    -      for (var key in this.elements_) {
    -        count++;
    -      }
    -      return count;
    -    };
    -
    -
    -/**
    - * Calculates the difference of two sets.
    - * @param {!goog.structs.StringSet} stringSet The set to subtract from this set.
    - * @return {!goog.structs.StringSet} {@code this} minus {@code stringSet}.
    - */
    -goog.structs.StringSet.prototype.getDifference = function(stringSet) {
    -  var ret = new goog.structs.StringSet;
    -  ret.addDifference_(this, stringSet);
    -  return ret;
    -};
    -
    -
    -/**
    - * Calculates the intersection of this set with another set.
    - * @param {!goog.structs.StringSet} stringSet The set to take the intersection
    - *     with.
    - * @return {!goog.structs.StringSet} A new set with the common elements.
    - */
    -goog.structs.StringSet.prototype.getIntersection = function(stringSet) {
    -  var ret = new goog.structs.StringSet;
    -  for (var key in this.elements_) {
    -    if (key in stringSet.elements_) {
    -      ret.elements_[key] = null;
    -    }
    -  }
    -  return ret;
    -};
    -
    -
    -/**
    - * Calculates the symmetric difference of two sets.
    - * @param {!goog.structs.StringSet} stringSet The other set.
    - * @return {!goog.structs.StringSet} A new set with the elements in exactly one
    - *     of {@code this} and {@code stringSet}.
    - */
    -goog.structs.StringSet.prototype.getSymmetricDifference = function(stringSet) {
    -  var ret = new goog.structs.StringSet;
    -  ret.addDifference_(this, stringSet);
    -  ret.addDifference_(stringSet, this);
    -  return ret;
    -};
    -
    -
    -/**
    - * Calculates the union of this set and another set.
    - * @param {!goog.structs.StringSet} stringSet The set to take the union with.
    - * @return {!goog.structs.StringSet} A new set with the union of elements.
    - */
    -goog.structs.StringSet.prototype.getUnion = function(stringSet) {
    -  var ret = this.clone();
    -  ret.addSet(stringSet);
    -  return ret;
    -};
    -
    -
    -/**
    - * @return {!Array<string>} The elements of the set.
    - */
    -goog.structs.StringSet.prototype.getValues = Object.keys ?
    -    function() {
    -      // Object.keys was introduced in JavaScript 1.8.5, Array#map in 1.6.
    -      return Object.keys(this.elements_).map(
    -          goog.structs.StringSet.decode_, this);
    -    } :
    -    function() {
    -      var ret = [];
    -      for (var key in this.elements_) {
    -        ret.push(goog.structs.StringSet.decode_(key));
    -      }
    -      return ret;
    -    };
    -
    -
    -/**
    - * Tells if this set and the given set are disjoint.
    - * @param {!goog.structs.StringSet} stringSet The other set.
    - * @return {boolean} True iff they don't have common elements.
    - */
    -goog.structs.StringSet.prototype.isDisjoint = function(stringSet) {
    -  for (var key in this.elements_) {
    -    if (key in stringSet.elements_) {
    -      return false;
    -    }
    -  }
    -  return true;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the set is empty.
    - */
    -goog.structs.StringSet.prototype.isEmpty = function() {
    -  for (var key in this.elements_) {
    -    return false;
    -  }
    -  return true;
    -};
    -
    -
    -/**
    - * Tells if this set is the subset of the given set.
    - * @param {!goog.structs.StringSet} stringSet The other set.
    - * @return {boolean} Whether this set if the subset of that.
    - */
    -goog.structs.StringSet.prototype.isSubsetOf = function(stringSet) {
    -  for (var key in this.elements_) {
    -    if (!(key in stringSet.elements_)) {
    -      return false;
    -    }
    -  }
    -  return true;
    -};
    -
    -
    -/**
    - * Tells if this set is the superset of the given set.
    - * @param {!goog.structs.StringSet} stringSet The other set.
    - * @return {boolean} Whether this set if the superset of that.
    - */
    -goog.structs.StringSet.prototype.isSupersetOf = function(stringSet) {
    -  return stringSet.isSubsetOf(this);
    -};
    -
    -
    -/**
    - * Removes a single element from the set.
    - * @param {*} element The element to remove.
    - * @return {boolean} Whether the element was in the set.
    - */
    -goog.structs.StringSet.prototype.remove = function(element) {
    -  var key = goog.structs.StringSet.encode_(element);
    -  if (key in this.elements_) {
    -    delete this.elements_[key];
    -    return true;
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Removes all elements of the given array from this set.
    - * @param {!Array<?>} arr The elements to remove.
    - */
    -goog.structs.StringSet.prototype.removeArray = function(arr) {
    -  for (var i = 0; i < arr.length; i++) {
    -    delete this.elements_[goog.structs.StringSet.encode_(arr[i])];
    -  }
    -};
    -
    -
    -/**
    - * Removes all elements of the given set from this set.
    - * @param {!goog.structs.StringSet} stringSet The set of elements to remove.
    - */
    -goog.structs.StringSet.prototype.removeSet = function(stringSet) {
    -  for (var key in stringSet.elements_) {
    -    delete this.elements_[key];
    -  }
    -};
    -
    -
    -/**
    - * Returns an iterator that iterates over the elements in the set.
    - * NOTE: creating the iterator copies the whole set so use {@link #forEach} when
    - * possible.
    - * @param {boolean=} opt_keys Ignored for sets.
    - * @return {!goog.iter.Iterator} An iterator over the elements in the set.
    - */
    -goog.structs.StringSet.prototype.__iterator__ = function(opt_keys) {
    -  return goog.iter.toIterator(this.getValues());
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/stringset_test.html b/src/database/third_party/closure-library/closure/goog/structs/stringset_test.html
    deleted file mode 100644
    index 131202c7619..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/stringset_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.structs.StringSet
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.structs.StringSetTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/stringset_test.js b/src/database/third_party/closure-library/closure/goog/structs/stringset_test.js
    deleted file mode 100644
    index d7499e02dd2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/stringset_test.js
    +++ /dev/null
    @@ -1,259 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.structs.StringSetTest');
    -goog.setTestOnly('goog.structs.StringSetTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.iter');
    -goog.require('goog.structs.StringSet');
    -goog.require('goog.testing.asserts');
    -goog.require('goog.testing.jsunit');
    -
    -var TEST_VALUES = [
    -  '', ' ', '  ', 'true', 'null', 'undefined', '0', 'new', 'constructor',
    -  'prototype', '__proto__', 'set', 'hasOwnProperty', 'toString', 'valueOf'
    -];
    -
    -var TEST_VALUES_WITH_DUPLICATES = [
    -  '', '', ' ', '  ', 'true', true, 'null', null, 'undefined', undefined, '0', 0,
    -  'new', 'constructor', 'prototype', '__proto__', 'set', 'hasOwnProperty',
    -  'toString', 'valueOf'
    -];
    -
    -function testConstructor() {
    -  var empty = new goog.structs.StringSet;
    -  assertSameElements('elements in empty set', [], empty.getValues());
    -
    -  var s = new goog.structs.StringSet(TEST_VALUES_WITH_DUPLICATES);
    -  assertSameElements('duplicates are filtered out by their string value',
    -      TEST_VALUES, s.getValues());
    -}
    -
    -function testConstructorAssertsThatObjectPrototypeHasNoEnumerableKeys() {
    -  assertNotThrows(goog.structs.StringSet);
    -  Object.prototype.foo = 0;
    -  try {
    -    assertThrows(goog.structs.StringSet);
    -  } finally {
    -    delete Object.prototype.foo;
    -  }
    -  assertNotThrows(goog.structs.StringSet);
    -}
    -
    -function testOverridingObjectPrototypeToStringIsSafe() {
    -  var originalToString = Object.prototype.toString;
    -  Object.prototype.toString = function() {
    -    return 'object';
    -  };
    -  try {
    -    assertEquals(0, new goog.structs.StringSet().getCount());
    -    assertFalse(new goog.structs.StringSet().contains('toString'));
    -  } finally {
    -    Object.prototype.toString = originalToString;
    -  }
    -}
    -
    -function testAdd() {
    -  var s = new goog.structs.StringSet;
    -  goog.array.forEach(TEST_VALUES_WITH_DUPLICATES, s.add, s);
    -  assertSameElements(TEST_VALUES, s.getValues());
    -}
    -
    -function testAddArray() {
    -  var s = new goog.structs.StringSet;
    -  s.addArray(TEST_VALUES_WITH_DUPLICATES);
    -  assertSameElements('added elements from array', TEST_VALUES, s.getValues());
    -}
    -
    -function testAddSet() {
    -  var s = new goog.structs.StringSet;
    -  s.addSet(new goog.structs.StringSet([1, 2]));
    -  assertSameElements('empty set + {1, 2}', ['1', '2'], s.getValues());
    -  s.addSet(new goog.structs.StringSet([2, 3]));
    -  assertSameElements('{1, 2} + {2, 3}', ['1', '2', '3'], s.getValues());
    -}
    -
    -function testClear() {
    -  var s = new goog.structs.StringSet([1, 2]);
    -  s.clear();
    -  assertSameElements('cleared set', [], s.getValues());
    -}
    -
    -function testClone() {
    -  var s = new goog.structs.StringSet([1, 2]);
    -  var c = s.clone();
    -  assertSameElements('elements in clone', ['1', '2'], c.getValues());
    -  s.add(3);
    -  assertSameElements('changing the original set does not affect the clone',
    -      ['1', '2'], c.getValues());
    -}
    -
    -function testContains() {
    -  var e = new goog.structs.StringSet;
    -  goog.array.forEach(TEST_VALUES, function(element) {
    -    assertFalse('empty set does not contain ' + element, e.contains(element));
    -  });
    -
    -  var s = new goog.structs.StringSet(TEST_VALUES);
    -  goog.array.forEach(TEST_VALUES_WITH_DUPLICATES, function(element) {
    -    assertTrue('s contains ' + element, s.contains(element));
    -  });
    -  assertFalse('s does not contain 42', s.contains(42));
    -}
    -
    -function testContainsArray() {
    -  var s = new goog.structs.StringSet(TEST_VALUES);
    -  assertTrue('set contains empty array', s.containsArray([]));
    -  assertTrue('set contains all elements of itself with some duplication',
    -      s.containsArray(TEST_VALUES_WITH_DUPLICATES));
    -  assertFalse('set does not contain 42', s.containsArray([42]));
    -}
    -
    -function testEquals() {
    -  var s = new goog.structs.StringSet([1, 2]);
    -  assertTrue('set equals to itself', s.equals(s));
    -  assertTrue('set equals to its clone', s.equals(s.clone()));
    -  assertFalse('set does not equal to its subset',
    -      s.equals(new goog.structs.StringSet([1])));
    -  assertFalse('set does not equal to its superset',
    -      s.equals(new goog.structs.StringSet([1, 2, 3])));
    -}
    -
    -function testForEach() {
    -  var s = new goog.structs.StringSet(TEST_VALUES);
    -  var values = [];
    -  var context = {};
    -  s.forEach(function(value, key, stringSet) {
    -    assertEquals('context of forEach callback', context, this);
    -    values.push(value);
    -    assertUndefined('key argument of forEach callback', key);
    -    assertEquals('set argument of forEach callback', s, stringSet);
    -  }, context);
    -  assertSameElements('values passed to forEach callback', TEST_VALUES, values);
    -}
    -
    -function testGetCount() {
    -  var empty = new goog.structs.StringSet;
    -  assertEquals('count(empty set)', 0, empty.getCount());
    -
    -  var s = new goog.structs.StringSet(TEST_VALUES);
    -  assertEquals('count(non-empty set)', TEST_VALUES.length, s.getCount());
    -}
    -
    -function testGetDifference() {
    -  var s1 = new goog.structs.StringSet([1, 2]);
    -  var s2 = new goog.structs.StringSet([2, 3]);
    -  assertSameElements('{1, 2} - {2, 3}', ['1'],
    -      s1.getDifference(s2).getValues());
    -}
    -
    -function testGetIntersection() {
    -  var s1 = new goog.structs.StringSet([1, 2]);
    -  var s2 = new goog.structs.StringSet([2, 3]);
    -  assertSameElements('{1, 2} * {2, 3}', ['2'],
    -      s1.getIntersection(s2).getValues());
    -}
    -
    -function testGetSymmetricDifference() {
    -  var s1 = new goog.structs.StringSet([1, 2]);
    -  var s2 = new goog.structs.StringSet([2, 3]);
    -  assertSameElements('{1, 2} sym.diff. {2, 3}', ['1', '3'],
    -      s1.getSymmetricDifference(s2).getValues());
    -}
    -
    -function testGetUnion() {
    -  var s1 = new goog.structs.StringSet([1, 2]);
    -  var s2 = new goog.structs.StringSet([2, 3]);
    -  assertSameElements('{1, 2} + {2, 3}', ['1', '2', '3'],
    -      s1.getUnion(s2).getValues());
    -}
    -
    -function testIsDisjoint() {
    -  var s = new goog.structs.StringSet;
    -  var s12 = new goog.structs.StringSet([1, 2]);
    -  var s23 = new goog.structs.StringSet([2, 3]);
    -  var s34 = new goog.structs.StringSet([3, 4]);
    -
    -  assertTrue('{} and {1, 2} are disjoint', s.isDisjoint(s12));
    -  assertTrue('{1, 2} and {3, 4} are disjoint', s12.isDisjoint(s34));
    -  assertFalse('{1, 2} and {2, 3} are not disjoint', s12.isDisjoint(s23));
    -}
    -
    -function testIsEmpty() {
    -  assertTrue('empty set', new goog.structs.StringSet().isEmpty());
    -  assertFalse('non-empty set', new goog.structs.StringSet(['']).isEmpty());
    -}
    -
    -function testIsSubsetOf() {
    -  var s1 = new goog.structs.StringSet([1]);
    -  var s12 = new goog.structs.StringSet([1, 2]);
    -  var s123 = new goog.structs.StringSet([1, 2, 3]);
    -  var s23 = new goog.structs.StringSet([2, 3]);
    -
    -  assertTrue('{1, 2} is subset of {1, 2}', s12.isSubsetOf(s12));
    -  assertTrue('{1, 2} is subset of {1, 2, 3}', s12.isSubsetOf(s123));
    -  assertFalse('{1, 2} is not subset of {1}', s12.isSubsetOf(s1));
    -  assertFalse('{1, 2} is not subset of {2, 3}', s12.isSubsetOf(s23));
    -}
    -
    -function testIsSupersetOf() {
    -  var s1 = new goog.structs.StringSet([1]);
    -  var s12 = new goog.structs.StringSet([1, 2]);
    -  var s123 = new goog.structs.StringSet([1, 2, 3]);
    -  var s23 = new goog.structs.StringSet([2, 3]);
    -
    -  assertTrue('{1, 2} is superset of {1}', s12.isSupersetOf(s1));
    -  assertTrue('{1, 2} is superset of {1, 2}', s12.isSupersetOf(s12));
    -  assertFalse('{1, 2} is not superset of {1, 2, 3}', s12.isSupersetOf(s123));
    -  assertFalse('{1, 2} is not superset of {2, 3}', s12.isSupersetOf(s23));
    -}
    -
    -function testRemove() {
    -  var n = new goog.structs.StringSet([1, 2]);
    -  assertFalse('3 not removed from {1, 2}', n.remove(3));
    -  assertSameElements('set == {1, 2}', ['1', '2'], n.getValues());
    -  assertTrue('2 removed from {1, 2}', n.remove(2));
    -  assertSameElements('set == {1}', ['1'], n.getValues());
    -  assertTrue('"1" removed from {1}', n.remove('1'));
    -  assertSameElements('set == {}', [], n.getValues());
    -
    -  var s = new goog.structs.StringSet(TEST_VALUES);
    -  goog.array.forEach(TEST_VALUES, s.remove, s);
    -  assertSameElements('all special values have been removed', [], s.getValues());
    -}
    -
    -function testRemoveArray() {
    -  var s = new goog.structs.StringSet(TEST_VALUES);
    -  s.removeArray(TEST_VALUES.slice(0, TEST_VALUES.length - 2));
    -  assertSameElements('removed elements from array',
    -      TEST_VALUES.slice(TEST_VALUES.length - 2), s.getValues());
    -}
    -
    -function testRemoveSet() {
    -  var s1 = new goog.structs.StringSet([1, 2]);
    -  var s2 = new goog.structs.StringSet([2, 3]);
    -  s1.removeSet(s2);
    -  assertSameElements('{1, 2} - {2, 3}', ['1'], s1.getValues());
    -}
    -
    -function testIterator() {
    -  var s = new goog.structs.StringSet(TEST_VALUES_WITH_DUPLICATES);
    -  var values = [];
    -  goog.iter.forEach(s, function(value) {
    -    values.push(value);
    -  });
    -  assertSameElements('__iterator__ takes all elements once',
    -      TEST_VALUES, values);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/structs.js b/src/database/third_party/closure-library/closure/goog/structs/structs.js
    deleted file mode 100644
    index 2744f6f5e2e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/structs.js
    +++ /dev/null
    @@ -1,354 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Generics method for collection-like classes and objects.
    - *
    - * @author arv@google.com (Erik Arvidsson)
    - *
    - * This file contains functions to work with collections. It supports using
    - * Map, Set, Array and Object and other classes that implement collection-like
    - * methods.
    - */
    -
    -
    -goog.provide('goog.structs');
    -
    -goog.require('goog.array');
    -goog.require('goog.object');
    -
    -
    -// We treat an object as a dictionary if it has getKeys or it is an object that
    -// isn't arrayLike.
    -
    -
    -/**
    - * Returns the number of values in the collection-like object.
    - * @param {Object} col The collection-like object.
    - * @return {number} The number of values in the collection-like object.
    - */
    -goog.structs.getCount = function(col) {
    -  if (typeof col.getCount == 'function') {
    -    return col.getCount();
    -  }
    -  if (goog.isArrayLike(col) || goog.isString(col)) {
    -    return col.length;
    -  }
    -  return goog.object.getCount(col);
    -};
    -
    -
    -/**
    - * Returns the values of the collection-like object.
    - * @param {Object} col The collection-like object.
    - * @return {!Array<?>} The values in the collection-like object.
    - */
    -goog.structs.getValues = function(col) {
    -  if (typeof col.getValues == 'function') {
    -    return col.getValues();
    -  }
    -  if (goog.isString(col)) {
    -    return col.split('');
    -  }
    -  if (goog.isArrayLike(col)) {
    -    var rv = [];
    -    var l = col.length;
    -    for (var i = 0; i < l; i++) {
    -      rv.push(col[i]);
    -    }
    -    return rv;
    -  }
    -  return goog.object.getValues(col);
    -};
    -
    -
    -/**
    - * Returns the keys of the collection. Some collections have no notion of
    - * keys/indexes and this function will return undefined in those cases.
    - * @param {Object} col The collection-like object.
    - * @return {!Array|undefined} The keys in the collection.
    - */
    -goog.structs.getKeys = function(col) {
    -  if (typeof col.getKeys == 'function') {
    -    return col.getKeys();
    -  }
    -  // if we have getValues but no getKeys we know this is a key-less collection
    -  if (typeof col.getValues == 'function') {
    -    return undefined;
    -  }
    -  if (goog.isArrayLike(col) || goog.isString(col)) {
    -    var rv = [];
    -    var l = col.length;
    -    for (var i = 0; i < l; i++) {
    -      rv.push(i);
    -    }
    -    return rv;
    -  }
    -
    -  return goog.object.getKeys(col);
    -};
    -
    -
    -/**
    - * Whether the collection contains the given value. This is O(n) and uses
    - * equals (==) to test the existence.
    - * @param {Object} col The collection-like object.
    - * @param {*} val The value to check for.
    - * @return {boolean} True if the map contains the value.
    - */
    -goog.structs.contains = function(col, val) {
    -  if (typeof col.contains == 'function') {
    -    return col.contains(val);
    -  }
    -  if (typeof col.containsValue == 'function') {
    -    return col.containsValue(val);
    -  }
    -  if (goog.isArrayLike(col) || goog.isString(col)) {
    -    return goog.array.contains(/** @type {!Array<?>} */ (col), val);
    -  }
    -  return goog.object.containsValue(col, val);
    -};
    -
    -
    -/**
    - * Whether the collection is empty.
    - * @param {Object} col The collection-like object.
    - * @return {boolean} True if empty.
    - */
    -goog.structs.isEmpty = function(col) {
    -  if (typeof col.isEmpty == 'function') {
    -    return col.isEmpty();
    -  }
    -
    -  // We do not use goog.string.isEmptyOrWhitespace because here we treat the string as
    -  // collection and as such even whitespace matters
    -
    -  if (goog.isArrayLike(col) || goog.isString(col)) {
    -    return goog.array.isEmpty(/** @type {!Array<?>} */ (col));
    -  }
    -  return goog.object.isEmpty(col);
    -};
    -
    -
    -/**
    - * Removes all the elements from the collection.
    - * @param {Object} col The collection-like object.
    - */
    -goog.structs.clear = function(col) {
    -  // NOTE(arv): This should not contain strings because strings are immutable
    -  if (typeof col.clear == 'function') {
    -    col.clear();
    -  } else if (goog.isArrayLike(col)) {
    -    goog.array.clear(/** @type {goog.array.ArrayLike} */ (col));
    -  } else {
    -    goog.object.clear(col);
    -  }
    -};
    -
    -
    -/**
    - * Calls a function for each value in a collection. The function takes
    - * three arguments; the value, the key and the collection.
    - *
    - * NOTE: This will be deprecated soon! Please use a more specific method if
    - * possible, e.g. goog.array.forEach, goog.object.forEach, etc.
    - *
    - * @param {S} col The collection-like object.
    - * @param {function(this:T,?,?,S):?} f The function to call for every value.
    - *     This function takes
    - *     3 arguments (the value, the key or undefined if the collection has no
    - *     notion of keys, and the collection) and the return value is irrelevant.
    - * @param {T=} opt_obj The object to be used as the value of 'this'
    - *     within {@code f}.
    - * @template T,S
    - */
    -goog.structs.forEach = function(col, f, opt_obj) {
    -  if (typeof col.forEach == 'function') {
    -    col.forEach(f, opt_obj);
    -  } else if (goog.isArrayLike(col) || goog.isString(col)) {
    -    goog.array.forEach(/** @type {!Array<?>} */ (col), f, opt_obj);
    -  } else {
    -    var keys = goog.structs.getKeys(col);
    -    var values = goog.structs.getValues(col);
    -    var l = values.length;
    -    for (var i = 0; i < l; i++) {
    -      f.call(opt_obj, values[i], keys && keys[i], col);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Calls a function for every value in the collection. When a call returns true,
    - * adds the value to a new collection (Array is returned by default).
    - *
    - * @param {S} col The collection-like object.
    - * @param {function(this:T,?,?,S):boolean} f The function to call for every
    - *     value. This function takes
    - *     3 arguments (the value, the key or undefined if the collection has no
    - *     notion of keys, and the collection) and should return a Boolean. If the
    - *     return value is true the value is added to the result collection. If it
    - *     is false the value is not included.
    - * @param {T=} opt_obj The object to be used as the value of 'this'
    - *     within {@code f}.
    - * @return {!Object|!Array<?>} A new collection where the passed values are
    - *     present. If col is a key-less collection an array is returned.  If col
    - *     has keys and values a plain old JS object is returned.
    - * @template T,S
    - */
    -goog.structs.filter = function(col, f, opt_obj) {
    -  if (typeof col.filter == 'function') {
    -    return col.filter(f, opt_obj);
    -  }
    -  if (goog.isArrayLike(col) || goog.isString(col)) {
    -    return goog.array.filter(/** @type {!Array<?>} */ (col), f, opt_obj);
    -  }
    -
    -  var rv;
    -  var keys = goog.structs.getKeys(col);
    -  var values = goog.structs.getValues(col);
    -  var l = values.length;
    -  if (keys) {
    -    rv = {};
    -    for (var i = 0; i < l; i++) {
    -      if (f.call(opt_obj, values[i], keys[i], col)) {
    -        rv[keys[i]] = values[i];
    -      }
    -    }
    -  } else {
    -    // We should not use goog.array.filter here since we want to make sure that
    -    // the index is undefined as well as make sure that col is passed to the
    -    // function.
    -    rv = [];
    -    for (var i = 0; i < l; i++) {
    -      if (f.call(opt_obj, values[i], undefined, col)) {
    -        rv.push(values[i]);
    -      }
    -    }
    -  }
    -  return rv;
    -};
    -
    -
    -/**
    - * Calls a function for every value in the collection and adds the result into a
    - * new collection (defaults to creating a new Array).
    - *
    - * @param {S} col The collection-like object.
    - * @param {function(this:T,?,?,S):V} f The function to call for every value.
    - *     This function takes 3 arguments (the value, the key or undefined if the
    - *     collection has no notion of keys, and the collection) and should return
    - *     something. The result will be used as the value in the new collection.
    - * @param {T=} opt_obj  The object to be used as the value of 'this'
    - *     within {@code f}.
    - * @return {!Object<V>|!Array<V>} A new collection with the new values.  If
    - *     col is a key-less collection an array is returned.  If col has keys and
    - *     values a plain old JS object is returned.
    - * @template T,S,V
    - */
    -goog.structs.map = function(col, f, opt_obj) {
    -  if (typeof col.map == 'function') {
    -    return col.map(f, opt_obj);
    -  }
    -  if (goog.isArrayLike(col) || goog.isString(col)) {
    -    return goog.array.map(/** @type {!Array<?>} */ (col), f, opt_obj);
    -  }
    -
    -  var rv;
    -  var keys = goog.structs.getKeys(col);
    -  var values = goog.structs.getValues(col);
    -  var l = values.length;
    -  if (keys) {
    -    rv = {};
    -    for (var i = 0; i < l; i++) {
    -      rv[keys[i]] = f.call(opt_obj, values[i], keys[i], col);
    -    }
    -  } else {
    -    // We should not use goog.array.map here since we want to make sure that
    -    // the index is undefined as well as make sure that col is passed to the
    -    // function.
    -    rv = [];
    -    for (var i = 0; i < l; i++) {
    -      rv[i] = f.call(opt_obj, values[i], undefined, col);
    -    }
    -  }
    -  return rv;
    -};
    -
    -
    -/**
    - * Calls f for each value in a collection. If any call returns true this returns
    - * true (without checking the rest). If all returns false this returns false.
    - *
    - * @param {S} col The collection-like object.
    - * @param {function(this:T,?,?,S):boolean} f The function to call for every
    - *     value. This function takes 3 arguments (the value, the key or undefined
    - *     if the collection has no notion of keys, and the collection) and should
    - *     return a boolean.
    - * @param {T=} opt_obj  The object to be used as the value of 'this'
    - *     within {@code f}.
    - * @return {boolean} True if any value passes the test.
    - * @template T,S
    - */
    -goog.structs.some = function(col, f, opt_obj) {
    -  if (typeof col.some == 'function') {
    -    return col.some(f, opt_obj);
    -  }
    -  if (goog.isArrayLike(col) || goog.isString(col)) {
    -    return goog.array.some(/** @type {!Array<?>} */ (col), f, opt_obj);
    -  }
    -  var keys = goog.structs.getKeys(col);
    -  var values = goog.structs.getValues(col);
    -  var l = values.length;
    -  for (var i = 0; i < l; i++) {
    -    if (f.call(opt_obj, values[i], keys && keys[i], col)) {
    -      return true;
    -    }
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Calls f for each value in a collection. If all calls return true this return
    - * true this returns true. If any returns false this returns false at this point
    - *  and does not continue to check the remaining values.
    - *
    - * @param {S} col The collection-like object.
    - * @param {function(this:T,?,?,S):boolean} f The function to call for every
    - *     value. This function takes 3 arguments (the value, the key or
    - *     undefined if the collection has no notion of keys, and the collection)
    - *     and should return a boolean.
    - * @param {T=} opt_obj  The object to be used as the value of 'this'
    - *     within {@code f}.
    - * @return {boolean} True if all key-value pairs pass the test.
    - * @template T,S
    - */
    -goog.structs.every = function(col, f, opt_obj) {
    -  if (typeof col.every == 'function') {
    -    return col.every(f, opt_obj);
    -  }
    -  if (goog.isArrayLike(col) || goog.isString(col)) {
    -    return goog.array.every(/** @type {!Array<?>} */ (col), f, opt_obj);
    -  }
    -  var keys = goog.structs.getKeys(col);
    -  var values = goog.structs.getValues(col);
    -  var l = values.length;
    -  for (var i = 0; i < l; i++) {
    -    if (!f.call(opt_obj, values[i], keys && keys[i], col)) {
    -      return false;
    -    }
    -  }
    -  return true;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/structs_test.html b/src/database/third_party/closure-library/closure/goog/structs/structs_test.html
    deleted file mode 100644
    index 6084aafe51b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/structs_test.html
    +++ /dev/null
    @@ -1,53 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.structs
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.structsTest');
    -  </script>
    - </head>
    - <body>
    -  <!-- test container with 10 elements inside, 1 hr and 1 h1 with id h1 -->
    -  <div id="test">
    -   <hr />
    -   <p>
    -    Paragraph 0
    -   </p>
    -   <p>
    -    Paragraph 1
    -   </p>
    -   <p>
    -    Paragraph 2
    -   </p>
    -   <p>
    -    Paragraph 3
    -   </p>
    -   <p>
    -    Paragraph 4
    -   </p>
    -   <p>
    -    Paragraph 5
    -   </p>
    -   <p>
    -    Paragraph 6
    -   </p>
    -   <p>
    -    Paragraph 7
    -   </p>
    -   <h1 id="h1">
    -    Header
    -   </h1>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/structs_test.js b/src/database/third_party/closure-library/closure/goog/structs/structs_test.js
    deleted file mode 100644
    index 96b2dab3f9b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/structs_test.js
    +++ /dev/null
    @@ -1,1040 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.structsTest');
    -goog.setTestOnly('goog.structsTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.structs');
    -goog.require('goog.structs.Map');
    -goog.require('goog.structs.Set');  // needed for filter
    -goog.require('goog.testing.jsunit');
    -
    -/*
    -
    - This one does not test Map or Set
    - It tests Array, Object, String and a NodeList
    -
    -*/
    -
    -
    -
    -function stringifyObject(obj) {
    -  var sb = [];
    -  for (var key in obj) {
    -    sb.push(key + obj[key]);
    -  }
    -  return sb.join('');
    -}
    -
    -
    -function getTestElement() {
    -  return document.getElementById('test');
    -}
    -
    -
    -function getAll() {
    -  return getTestElement().getElementsByTagName('*');
    -}
    -
    -
    -var node;
    -
    -
    -function addNode() {
    -  node = document.createElement('span');
    -  getTestElement().appendChild(node);
    -}
    -
    -
    -function removeNode() {
    -  getTestElement().removeChild(node);
    -}
    -
    -
    -function nodeNames(nl) {
    -  var sb = [];
    -  for (var i = 0, n; n = nl[i]; i++) {
    -    sb.push(n.nodeName.toLowerCase());
    -  }
    -  return sb.join(',');
    -}
    -
    -
    -var allTagNames1 = 'hr,p,p,p,p,p,p,p,p,h1';
    -var allTagNames2 = allTagNames1 + ',span';
    -
    -
    -function testGetCount() {
    -  var arr = ['a', 'b', 'c'];
    -  assertEquals('count, should be 3', 3, goog.structs.getCount(arr));
    -  arr.push('d');
    -  assertEquals('count, should be 4', 4, goog.structs.getCount(arr));
    -  goog.array.remove(arr, 'd');
    -  assertEquals('count, should be 3', 3, goog.structs.getCount(arr));
    -
    -  var obj = {a: 0, b: 1, c: 2};
    -  assertEquals('count, should be 3', 3, goog.structs.getCount(obj));
    -  obj.d = 3;
    -  assertEquals('count, should be 4', 4, goog.structs.getCount(obj));
    -  delete obj.d;
    -  assertEquals('count, should be 3', 3, goog.structs.getCount(obj));
    -
    -  var s = 'abc';
    -  assertEquals('count, should be 3', 3, goog.structs.getCount(s));
    -  s += 'd';
    -  assertEquals('count, should be 4', 4, goog.structs.getCount(s));
    -
    -  var all = getAll();
    -  assertEquals('count, should be 10', 10, goog.structs.getCount(all));
    -  addNode();
    -  assertEquals('count, should be 11', 11, goog.structs.getCount(all));
    -  removeNode();
    -  assertEquals('count, should be 10', 10, goog.structs.getCount(all));
    -
    -  var aMap = new goog.structs.Map({a: 0, b: 1, c: 2});
    -  assertEquals('count, should be 3', 3, goog.structs.getCount(aMap));
    -  aMap.set('d', 3);
    -  assertEquals('count, should be 4', 4, goog.structs.getCount(aMap));
    -  aMap.remove('a');
    -  assertEquals('count, should be 3', 3, goog.structs.getCount(aMap));
    -
    -  var aSet = new goog.structs.Set('abc');
    -  assertEquals('count, should be 3', 3, goog.structs.getCount(aSet));
    -  aSet.add('d');
    -  assertEquals('count, should be 4', 4, goog.structs.getCount(aSet));
    -  aSet.remove('a');
    -  assertEquals('count, should be 3', 3, goog.structs.getCount(aSet));
    -}
    -
    -
    -function testGetValues() {
    -  var arr = ['a', 'b', 'c', 'd'];
    -  assertEquals('abcd', goog.structs.getValues(arr).join(''));
    -
    -  var obj = {a: 0, b: 1, c: 2, d: 3};
    -  assertEquals('0123', goog.structs.getValues(obj).join(''));
    -
    -  var s = 'abc';
    -  assertEquals('abc', goog.structs.getValues(s).join(''));
    -  s += 'd';
    -  assertEquals('abcd', goog.structs.getValues(s).join(''));
    -
    -  var all = getAll();
    -  assertEquals(allTagNames1, nodeNames(goog.structs.getValues(all)));
    -  addNode();
    -  assertEquals(allTagNames2, nodeNames(goog.structs.getValues(all)));
    -  removeNode();
    -  assertEquals(allTagNames1, nodeNames(goog.structs.getValues(all)));
    -
    -  var aMap = new goog.structs.Map({a: 1, b: 2, c: 3});
    -  assertEquals('123', goog.structs.getValues(aMap).join(''));
    -
    -  var aSet = new goog.structs.Set([1, 2, 3]);
    -  assertEquals('123', goog.structs.getValues(aMap).join(''));
    -}
    -
    -
    -function testGetKeys() {
    -  var arr = ['a', 'b', 'c', 'd'];
    -  assertEquals('0123', goog.structs.getKeys(arr).join(''));
    -
    -  var obj = {a: 0, b: 1, c: 2, d: 3};
    -  assertEquals('abcd', goog.structs.getKeys(obj).join(''));
    -
    -  var s = 'abc';
    -  assertEquals('012', goog.structs.getKeys(s).join(''));
    -  s += 'd';
    -  assertEquals('0123', goog.structs.getKeys(s).join(''));
    -
    -  var all = getAll();
    -  assertEquals('0123456789', goog.structs.getKeys(all).join(''));
    -  addNode();
    -  assertEquals('012345678910', goog.structs.getKeys(all).join(''));
    -  removeNode();
    -  assertEquals('0123456789', goog.structs.getKeys(all).join(''));
    -
    -  var aMap = new goog.structs.Map({a: 1, b: 2, c: 3});
    -  assertEquals('abc', goog.structs.getKeys(aMap).join(''));
    -
    -  var aSet = new goog.structs.Set([1, 2, 3]);
    -  assertUndefined(goog.structs.getKeys(aSet));
    -}
    -
    -function testContains() {
    -  var arr = ['a', 'b', 'c', 'd'];
    -  assertTrue("contains, Should contain 'a'", goog.structs.contains(arr, 'a'));
    -  assertFalse(
    -      "contains, Should not contain 'e'", goog.structs.contains(arr, 'e'));
    -
    -  var obj = {a: 0, b: 1, c: 2, d: 3};
    -  assertTrue("contains, Should contain '0'", goog.structs.contains(obj, 0));
    -  assertFalse(
    -      "contains, Should not contain '4'", goog.structs.contains(obj, 4));
    -
    -  var s = 'abc';
    -  assertTrue("contains, Should contain 'a'", goog.structs.contains(s, 'a'));
    -  assertFalse(
    -      "contains, Should not contain 'd'", goog.structs.contains(s, 'd'));
    -
    -  var all = getAll();
    -  assertTrue("contains, Should contain 'h1'",
    -             goog.structs.contains(all, document.getElementById('h1')));
    -  assertFalse("contains, Should not contain 'document.body'",
    -              goog.structs.contains(all, document.body));
    -
    -  var aMap = new goog.structs.Map({a: 1, b: 2, c: 3});
    -  assertTrue("contains, Should contain '1'", goog.structs.contains(aMap, 1));
    -  assertFalse(
    -      "contains, Should not contain '4'", goog.structs.contains(aMap, 4));
    -
    -  var aSet = new goog.structs.Set([1, 2, 3]);
    -  assertTrue("contains, Should contain '1'", goog.structs.contains(aSet, 1));
    -  assertFalse(
    -      "contains, Should not contain '4'", goog.structs.contains(aSet, 4));
    -}
    -
    -
    -function testClear() {
    -  var arr = ['a', 'b', 'c', 'd'];
    -  goog.structs.clear(arr);
    -  assertTrue('cleared so it should be empty', goog.structs.isEmpty(arr));
    -  assertFalse(
    -      "cleared so it should not contain 'a'", goog.structs.contains(arr, 'a'));
    -
    -  var obj = {a: 0, b: 1, c: 2, d: 3};
    -  goog.structs.clear(obj);
    -  assertTrue('cleared so it should be empty', goog.structs.isEmpty(obj));
    -  assertFalse(
    -      "cleared so it should not contain 'a' key",
    -      goog.structs.contains(obj, 0));
    -
    -  var aMap = new goog.structs.Map({a: 1, b: 2, c: 3});
    -  goog.structs.clear(aMap);
    -  assertTrue('cleared map so it should be empty', goog.structs.isEmpty(aMap));
    -  assertFalse("cleared map so it should not contain '1' value",
    -      goog.structs.contains(aMap, 1));
    -
    -  var aSet = new goog.structs.Set([1, 2, 3]);
    -  goog.structs.clear(aSet);
    -  assertTrue('cleared set so it should be empty', goog.structs.isEmpty(aSet));
    -  assertFalse(
    -      "cleared set so it should not contain '1'",
    -      goog.structs.contains(aSet, 1));
    -
    -  // cannot clear a string or a NodeList
    -}
    -
    -
    -
    -// Map
    -
    -function testMap() {
    -  var RV = {};
    -  var obj = {
    -    map: function(g) {
    -      assertEquals(f, g);
    -      assertEquals(this, obj);
    -      return RV;
    -    }
    -  };
    -  function f() {}
    -  assertEquals(RV, goog.structs.map(obj, f));
    -}
    -
    -function testMap2() {
    -  var THIS_OBJ = {};
    -  var RV = {};
    -  var obj = {
    -    map: function(g, obj2) {
    -      assertEquals(f, g);
    -      assertEquals(this, obj);
    -      assertEquals(THIS_OBJ, obj2);
    -      return RV;
    -    }
    -  };
    -  function f() {}
    -  assertEquals(RV, goog.structs.map(obj, f, THIS_OBJ));
    -}
    -
    -function testMapArrayLike() {
    -  var col = [0, 1, 2];
    -  function f(v, i, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('number', typeof i);
    -    return v * v;
    -  }
    -  assertArrayEquals([0, 1, 4], goog.structs.map(col, f));
    -}
    -
    -function testMapArrayLike2() {
    -  var THIS_OBJ = {};
    -  var col = [0, 1, 2];
    -  function f(v, i, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('number', typeof i);
    -    assertEquals(THIS_OBJ, this);
    -    return v * v;
    -  }
    -  assertArrayEquals([0, 1, 4], goog.structs.map(col, f, THIS_OBJ));
    -}
    -
    -function testMapString() {
    -  var col = '012';
    -  function f(v, i, col2) {
    -    // Teh SpiderMonkey Array.map for strings turns the string into a String
    -    // so we cannot use assertEquals because it uses ===.
    -    assertTrue(col == col2);
    -    assertEquals('number', typeof i);
    -    return Number(v) * Number(v);
    -  }
    -  assertArrayEquals([0, 1, 4], goog.structs.map(col, f));
    -}
    -
    -function testMapString2() {
    -  var THIS_OBJ = {};
    -  var col = '012';
    -  function f(v, i, col2) {
    -    // for some reason the strings are equal but identical???
    -    assertEquals(String(col), String(col2));
    -    assertEquals('number', typeof i);
    -    assertEquals(THIS_OBJ, this);
    -    return Number(v) * Number(v);
    -  }
    -  assertArrayEquals([0, 1, 4], goog.structs.map(col, f, THIS_OBJ));
    -}
    -
    -function testMapMap() {
    -  var col = new goog.structs.Map({a: 0, b: 1, c: 2});
    -  function f(v, key, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('string', typeof key);
    -    return v * v;
    -  }
    -  assertObjectEquals({a: 0, b: 1, c: 4}, goog.structs.map(col, f));
    -}
    -
    -function testMapMap2() {
    -  var THIS_OBJ = {};
    -  var col = new goog.structs.Map({a: 0, b: 1, c: 2});
    -  function f(v, key, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('string', typeof key);
    -    assertEquals(THIS_OBJ, this);
    -    return v * v;
    -  }
    -  assertObjectEquals({a: 0, b: 1, c: 4}, goog.structs.map(col, f, THIS_OBJ));
    -}
    -
    -function testMapSet() {
    -  var col = new goog.structs.Set([0, 1, 2]);
    -  function f(v, key, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('undefined', typeof key);
    -    return v * v;
    -  }
    -  assertArrayEquals([0, 1, 4], goog.structs.map(col, f));
    -}
    -
    -function testMapSet2() {
    -  var THIS_OBJ = {};
    -  var col = new goog.structs.Set([0, 1, 2]);
    -  function f(v, key, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('undefined', typeof key);
    -    assertEquals(THIS_OBJ, this);
    -    return v * v;
    -  }
    -  assertArrayEquals([0, 1, 4], goog.structs.map(col, f, THIS_OBJ));
    -}
    -
    -function testMapNodeList() {
    -  var col = getAll();
    -  function f(v, i, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('number', typeof i);
    -    return v.tagName;
    -  }
    -  assertEquals('HRPPPPPPPPH1', goog.structs.map(col, f).join(''));
    -}
    -
    -function testMapNodeList2() {
    -  var THIS_OBJ = {};
    -  var col = getAll();
    -  function f(v, i, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('number', typeof i);
    -    assertEquals(THIS_OBJ, this);
    -    return v.tagName;
    -  }
    -  assertEquals('HRPPPPPPPPH1', goog.structs.map(col, f, THIS_OBJ).join(''));
    -}
    -
    -// Filter
    -
    -function testFilter() {
    -  var RV = {};
    -  var obj = {
    -    filter: function(g) {
    -      assertEquals(f, g);
    -      assertEquals(this, obj);
    -      return RV;
    -    }
    -  };
    -  function f() {}
    -  assertEquals(RV, goog.structs.filter(obj, f));
    -}
    -
    -function testFilter2() {
    -  var THIS_OBJ = {};
    -  var RV = {};
    -  var obj = {
    -    filter: function(g, obj2) {
    -      assertEquals(f, g);
    -      assertEquals(this, obj);
    -      assertEquals(THIS_OBJ, obj2);
    -      return RV;
    -    }
    -  };
    -  function f() {}
    -  assertEquals(RV, goog.structs.filter(obj, f, THIS_OBJ));
    -}
    -
    -function testFilterArrayLike() {
    -  var col = [0, 1, 2];
    -  function f(v, i, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('number', typeof i);
    -    return v > 0;
    -  }
    -  assertArrayEquals([1, 2], goog.structs.filter(col, f));
    -}
    -
    -function testFilterArrayLike2() {
    -  var THIS_OBJ = {};
    -  var col = [0, 1, 2];
    -  function f(v, i, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('number', typeof i);
    -    assertEquals(THIS_OBJ, this);
    -    return v > 0;
    -  }
    -  assertArrayEquals([1, 2], goog.structs.filter(col, f, THIS_OBJ));
    -}
    -
    -function testFilterString() {
    -  var col = '012';
    -  function f(v, i, col2) {
    -    // for some reason the strings are equal but identical???
    -    assertEquals(String(col), String(col2));
    -    assertEquals('number', typeof i);
    -    return Number(v) > 0;
    -  }
    -  assertArrayEquals(['1', '2'], goog.structs.filter(col, f));
    -}
    -
    -function testFilterString2() {
    -  var THIS_OBJ = {};
    -  var col = '012';
    -  function f(v, i, col2) {
    -    // for some reason the strings are equal but identical???
    -    assertEquals(String(col), String(col2));
    -    assertEquals('number', typeof i);
    -    assertEquals(THIS_OBJ, this);
    -    return Number(v) > 0;
    -  }
    -  assertArrayEquals(['1', '2'], goog.structs.filter(col, f, THIS_OBJ));
    -}
    -
    -function testFilterMap() {
    -  var col = new goog.structs.Map({a: 0, b: 1, c: 2});
    -  function f(v, key, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('string', typeof key);
    -    return v > 0;
    -  }
    -  assertObjectEquals({b: 1, c: 2}, goog.structs.filter(col, f));
    -}
    -
    -function testFilterMap2() {
    -  var THIS_OBJ = {};
    -  var col = new goog.structs.Map({a: 0, b: 1, c: 2});
    -  function f(v, key, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('string', typeof key);
    -    assertEquals(THIS_OBJ, this);
    -    return v > 0;
    -  }
    -  assertObjectEquals({b: 1, c: 2}, goog.structs.filter(col, f, THIS_OBJ));
    -}
    -
    -function testFilterSet() {
    -  var col = new goog.structs.Set([0, 1, 2]);
    -  function f(v, key, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('undefined', typeof key);
    -    return v > 0;
    -  }
    -  assertArrayEquals([1, 2], goog.structs.filter(col, f));
    -}
    -
    -function testFilterSet2() {
    -  var THIS_OBJ = {};
    -  var col = new goog.structs.Set([0, 1, 2]);
    -  function f(v, key, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('undefined', typeof key);
    -    assertEquals(THIS_OBJ, this);
    -    return v > 0;
    -  }
    -  assertArrayEquals([1, 2], goog.structs.filter(col, f, THIS_OBJ));
    -}
    -
    -function testFilterNodeList() {
    -  var col = getAll();
    -  function f(v, i, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('number', typeof i);
    -    return v.tagName == 'P';
    -  }
    -  assertEquals('p,p,p,p,p,p,p,p',
    -               nodeNames(goog.structs.filter(col, f)));
    -}
    -
    -function testFilterNodeList2() {
    -  var THIS_OBJ = {};
    -  var col = getAll();
    -  function f(v, i, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('number', typeof i);
    -    assertEquals(THIS_OBJ, this);
    -    return v.tagName == 'P';
    -  }
    -  assertEquals('p,p,p,p,p,p,p,p',
    -               nodeNames(goog.structs.filter(col, f, THIS_OBJ)));
    -}
    -
    -// Some
    -
    -function testSome() {
    -  var RV = {};
    -  var obj = {
    -    some: function(g) {
    -      assertEquals(f, g);
    -      assertEquals(this, obj);
    -      return RV;
    -    }
    -  };
    -  function f() {}
    -  assertEquals(RV, goog.structs.some(obj, f));
    -}
    -
    -function testSome2() {
    -  var THIS_OBJ = {};
    -  var RV = {};
    -  var obj = {
    -    some: function(g, obj2) {
    -      assertEquals(f, g);
    -      assertEquals(this, obj);
    -      assertEquals(THIS_OBJ, obj2);
    -      return RV;
    -    }
    -  };
    -  function f() {}
    -  assertEquals(RV, goog.structs.some(obj, f, THIS_OBJ));
    -}
    -
    -function testSomeArrayLike() {
    -  var limit = 0;
    -  var col = [0, 1, 2];
    -  function f(v, i, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('number', typeof i);
    -    return v > limit;
    -  }
    -  assertTrue(goog.structs.some(col, f));
    -  limit = 2;
    -  assertFalse(goog.structs.some(col, f));
    -}
    -
    -function testSomeArrayLike2() {
    -  var THIS_OBJ = {};
    -  var limit = 0;
    -  var col = [0, 1, 2];
    -  function f(v, i, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('number', typeof i);
    -    assertEquals(THIS_OBJ, this);
    -    return v > limit;
    -  }
    -  assertTrue(goog.structs.some(col, f, THIS_OBJ));
    -  limit = 2;
    -  assertFalse(goog.structs.some(col, f, THIS_OBJ));
    -}
    -
    -function testSomeString() {
    -  var limit = 0;
    -  var col = '012';
    -  function f(v, i, col2) {
    -    // for some reason the strings are equal but identical???
    -    assertEquals(String(col), String(col2));
    -    assertEquals('number', typeof i);
    -    return Number(v) > limit;
    -  }
    -  assertTrue(goog.structs.some(col, f));
    -  limit = 2;
    -  assertFalse(goog.structs.some(col, f));
    -}
    -
    -function testSomeString2() {
    -  var THIS_OBJ = {};
    -  var limit = 0;
    -  var col = '012';
    -  function f(v, i, col2) {
    -    // for some reason the strings are equal but identical???
    -    assertEquals(String(col), String(col2));
    -    assertEquals('number', typeof i);
    -    assertEquals(THIS_OBJ, this);
    -    return Number(v) > limit;
    -  }
    -  assertTrue(goog.structs.some(col, f, THIS_OBJ));
    -  limit = 2;
    -  assertFalse(goog.structs.some(col, f, THIS_OBJ));
    -}
    -
    -function testSomeMap() {
    -  var limit = 0;
    -  var col = new goog.structs.Map({a: 0, b: 1, c: 2});
    -  function f(v, key, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('string', typeof key);
    -    return v > limit;
    -  }
    -  assertObjectEquals(true, goog.structs.some(col, f));
    -  limit = 2;
    -  assertFalse(goog.structs.some(col, f));
    -}
    -
    -function testSomeMap2() {
    -  var THIS_OBJ = {};
    -  var limit = 0;
    -  var col = new goog.structs.Map({a: 0, b: 1, c: 2});
    -  function f(v, key, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('string', typeof key);
    -    assertEquals(THIS_OBJ, this);
    -    return v > limit;
    -  }
    -  assertObjectEquals(true, goog.structs.some(col, f, THIS_OBJ));
    -  limit = 2;
    -  assertFalse(goog.structs.some(col, f, THIS_OBJ));
    -}
    -
    -function testSomeSet() {
    -  var limit = 0;
    -  var col = new goog.structs.Set([0, 1, 2]);
    -  function f(v, key, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('undefined', typeof key);
    -    return v > limit;
    -  }
    -  assertTrue(goog.structs.some(col, f));
    -  limit = 2;
    -  assertFalse(goog.structs.some(col, f));
    -}
    -
    -function testSomeSet2() {
    -  var THIS_OBJ = {};
    -  var limit = 0;
    -  var col = new goog.structs.Set([0, 1, 2]);
    -  function f(v, key, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('undefined', typeof key);
    -    assertEquals(THIS_OBJ, this);
    -    return v > limit;
    -  }
    -  assertTrue(goog.structs.some(col, f, THIS_OBJ));
    -  limit = 2;
    -  assertFalse(goog.structs.some(col, f, THIS_OBJ));
    -}
    -
    -function testSomeNodeList() {
    -  var tagName = 'P';
    -  var col = getAll();
    -  function f(v, i, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('number', typeof i);
    -    return v.tagName == tagName;
    -  }
    -  assertTrue(goog.structs.some(col, f));
    -  tagName = 'MARQUEE';
    -  assertFalse(goog.structs.some(col, f));
    -}
    -
    -function testSomeNodeList2() {
    -  var THIS_OBJ = {};
    -  var tagName = 'P';
    -  var col = getAll();
    -  function f(v, i, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('number', typeof i);
    -    assertEquals(THIS_OBJ, this);
    -    return v.tagName == tagName;
    -  }
    -  assertTrue(goog.structs.some(col, f, THIS_OBJ));
    -  tagName = 'MARQUEE';
    -  assertFalse(goog.structs.some(col, f, THIS_OBJ));
    -}
    -
    -// Every
    -
    -function testEvery() {
    -  var RV = {};
    -  var obj = {
    -    every: function(g) {
    -      assertEquals(f, g);
    -      assertEquals(this, obj);
    -      return RV;
    -    }
    -  };
    -  function f() {}
    -  assertEquals(RV, goog.structs.every(obj, f));
    -}
    -
    -function testEvery2() {
    -  var THIS_OBJ = {};
    -  var RV = {};
    -  var obj = {
    -    every: function(g, obj2) {
    -      assertEquals(f, g);
    -      assertEquals(this, obj);
    -      assertEquals(THIS_OBJ, obj2);
    -      return RV;
    -    }
    -  };
    -  function f() {}
    -  assertEquals(RV, goog.structs.every(obj, f, THIS_OBJ));
    -}
    -
    -function testEveryArrayLike() {
    -  var limit = -1;
    -  var col = [0, 1, 2];
    -  function f(v, i, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('number', typeof i);
    -    return v > limit;
    -  }
    -  assertTrue(goog.structs.every(col, f));
    -  limit = 1;
    -  assertFalse(goog.structs.every(col, f));
    -}
    -
    -function testEveryArrayLike2() {
    -  var THIS_OBJ = {};
    -  var limit = -1;
    -  var col = [0, 1, 2];
    -  function f(v, i, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('number', typeof i);
    -    assertEquals(THIS_OBJ, this);
    -    return v > limit;
    -  }
    -  assertTrue(goog.structs.every(col, f, THIS_OBJ));
    -  limit = 1;
    -  assertFalse(goog.structs.every(col, f, THIS_OBJ));
    -}
    -
    -function testEveryString() {
    -  var limit = -1;
    -  var col = '012';
    -  function f(v, i, col2) {
    -    // for some reason the strings are equal but identical???
    -    assertEquals(String(col), String(col2));
    -    assertEquals('number', typeof i);
    -    return Number(v) > limit;
    -  }
    -  assertTrue(goog.structs.every(col, f));
    -  limit = 1;
    -  assertFalse(goog.structs.every(col, f));
    -}
    -
    -function testEveryString2() {
    -  var THIS_OBJ = {};
    -  var limit = -1;
    -  var col = '012';
    -  function f(v, i, col2) {
    -    // for some reason the strings are equal but identical???
    -    assertEquals(String(col), String(col2));
    -    assertEquals('number', typeof i);
    -    assertEquals(THIS_OBJ, this);
    -    return Number(v) > limit;
    -  }
    -  assertTrue(goog.structs.every(col, f, THIS_OBJ));
    -  limit = 1;
    -  assertFalse(goog.structs.every(col, f, THIS_OBJ));
    -}
    -
    -function testEveryMap() {
    -  var limit = -1;
    -  var col = new goog.structs.Map({a: 0, b: 1, c: 2});
    -  function f(v, key, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('string', typeof key);
    -    return v > limit;
    -  }
    -  assertObjectEquals(true, goog.structs.every(col, f));
    -  limit = 1;
    -  assertFalse(goog.structs.every(col, f));
    -}
    -
    -function testEveryMap2() {
    -  var THIS_OBJ = {};
    -  var limit = -1;
    -  var col = new goog.structs.Map({a: 0, b: 1, c: 2});
    -  function f(v, key, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('string', typeof key);
    -    assertEquals(THIS_OBJ, this);
    -    return v > limit;
    -  }
    -  assertObjectEquals(true, goog.structs.every(col, f, THIS_OBJ));
    -  limit = 1;
    -  assertFalse(goog.structs.every(col, f, THIS_OBJ));
    -}
    -
    -function testEverySet() {
    -  var limit = -1;
    -  var col = new goog.structs.Set([0, 1, 2]);
    -  function f(v, key, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('undefined', typeof key);
    -    return v > limit;
    -  }
    -  assertTrue(goog.structs.every(col, f));
    -  limit = 1;
    -  assertFalse(goog.structs.every(col, f));
    -}
    -
    -function testEverySet2() {
    -  var THIS_OBJ = {};
    -  var limit = -1;
    -  var col = new goog.structs.Set([0, 1, 2]);
    -  function f(v, key, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('undefined', typeof key);
    -    assertEquals(THIS_OBJ, this);
    -    return v > limit;
    -  }
    -  assertTrue(goog.structs.every(col, f, THIS_OBJ));
    -  limit = 1;
    -  assertFalse(goog.structs.every(col, f, THIS_OBJ));
    -}
    -
    -function testEveryNodeList() {
    -  var nodeType = 1; // ELEMENT
    -  var col = getAll();
    -  function f(v, i, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('number', typeof i);
    -    return v.nodeType == nodeType;
    -  }
    -  assertTrue(goog.structs.every(col, f));
    -  nodeType = 3; // TEXT
    -  assertFalse(goog.structs.every(col, f));
    -}
    -
    -function testEveryNodeList2() {
    -  var THIS_OBJ = {};
    -  var nodeType = 1; // ELEMENT
    -  var col = getAll();
    -  function f(v, i, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('number', typeof i);
    -    assertEquals(THIS_OBJ, this);
    -    return v.nodeType == nodeType;
    -  }
    -  assertTrue(goog.structs.every(col, f, THIS_OBJ));
    -  nodeType = 3; // TEXT
    -  assertFalse(goog.structs.every(col, f, THIS_OBJ));
    -}
    -
    -// For each
    -
    -function testForEach() {
    -  var called = false;
    -  var obj = {
    -    forEach: function(g) {
    -      assertEquals(f, g);
    -      assertEquals(this, obj);
    -      called = true;
    -    }
    -  };
    -  function f() {}
    -  goog.structs.forEach(obj, f);
    -  assertTrue(called);
    -}
    -
    -function testForEach2() {
    -  var called = false;
    -  var THIS_OBJ = {};
    -  var obj = {
    -    forEach: function(g, obj2) {
    -      assertEquals(f, g);
    -      assertEquals(this, obj);
    -      assertEquals(THIS_OBJ, obj2);
    -      called = true;
    -    }
    -  };
    -  function f() {}
    -  goog.structs.forEach(obj, f, THIS_OBJ);
    -  assertTrue(called);
    -}
    -
    -function testForEachArrayLike() {
    -  var col = [0, 1, 2];
    -  var values = [];
    -  function f(v, i, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('number', typeof i);
    -    values.push(v * v);
    -  }
    -  goog.structs.forEach(col, f);
    -  assertArrayEquals([0, 1, 4], values);
    -}
    -
    -function testForEachArrayLike2() {
    -  var THIS_OBJ = {};
    -  var col = [0, 1, 2];
    -  var values = [];
    -  function f(v, i, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('number', typeof i);
    -    assertEquals(THIS_OBJ, this);
    -    values.push(v * v);
    -  }
    -  goog.structs.forEach(col, f, THIS_OBJ);
    -  assertArrayEquals([0, 1, 4], values);
    -}
    -
    -function testForEachString() {
    -  var col = '012';
    -  var values = [];
    -  function f(v, i, col2) {
    -    // for some reason the strings are equal but identical???
    -    assertEquals(String(col), String(col2));
    -    assertEquals('number', typeof i);
    -    values.push(Number(v) * Number(v));
    -  }
    -  goog.structs.forEach(col, f);
    -  assertArrayEquals([0, 1, 4], values);
    -}
    -
    -function testForEachString2() {
    -  var THIS_OBJ = {};
    -  var col = '012';
    -  var values = [];
    -  function f(v, i, col2) {
    -    // for some reason the strings are equal but identical???
    -    assertEquals(String(col), String(col2));
    -    assertEquals('number', typeof i);
    -    assertEquals(THIS_OBJ, this);
    -    values.push(Number(v) * Number(v));
    -  }
    -  goog.structs.forEach(col, f, THIS_OBJ);
    -  assertArrayEquals([0, 1, 4], values);
    -}
    -
    -function testForEachMap() {
    -  var col = new goog.structs.Map({a: 0, b: 1, c: 2});
    -  var values = [];
    -  var keys = [];
    -  function f(v, key, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('string', typeof key);
    -    values.push(v * v);
    -    keys.push(key);
    -  }
    -  goog.structs.forEach(col, f);
    -  assertArrayEquals([0, 1, 4], values);
    -  assertArrayEquals(['a', 'b', 'c'], keys);
    -}
    -
    -function testForEachMap2() {
    -  var THIS_OBJ = {};
    -  var col = new goog.structs.Map({a: 0, b: 1, c: 2});
    -  var values = [];
    -  var keys = [];
    -  function f(v, key, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('string', typeof key);
    -    assertEquals(THIS_OBJ, this);
    -    values.push(v * v);
    -    keys.push(key);
    -  }
    -  goog.structs.forEach(col, f, THIS_OBJ);
    -  assertArrayEquals([0, 1, 4], values);
    -  assertArrayEquals(['a', 'b', 'c'], keys);
    -}
    -
    -function testForEachSet() {
    -  var col = new goog.structs.Set([0, 1, 2]);
    -  var values = [];
    -  function f(v, key, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('undefined', typeof key);
    -    values.push(v * v);
    -  }
    -  goog.structs.forEach(col, f);
    -  assertArrayEquals([0, 1, 4], values);
    -}
    -
    -function testForEachSet2() {
    -  var THIS_OBJ = {};
    -  var col = new goog.structs.Set([0, 1, 2]);
    -  var values = [];
    -  function f(v, key, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('undefined', typeof key);
    -    assertEquals(THIS_OBJ, this);
    -    values.push(v * v);
    -  }
    -  goog.structs.forEach(col, f, THIS_OBJ);
    -  assertArrayEquals([0, 1, 4], values);
    -}
    -
    -function testForEachNodeList() {
    -  var values = [];
    -  var col = getAll();
    -  function f(v, i, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('number', typeof i);
    -    values.push(v.tagName);
    -  }
    -  goog.structs.forEach(col, f);
    -  assertEquals('HRPPPPPPPPH1', values.join(''));
    -}
    -
    -function testForEachNodeList2() {
    -  var THIS_OBJ = {};
    -  var values = [];
    -  var col = getAll();
    -  function f(v, i, col2) {
    -    assertEquals(col, col2);
    -    assertEquals('number', typeof i);
    -    assertEquals(THIS_OBJ, this);
    -    values.push(v.tagName);
    -  }
    -  goog.structs.forEach(col, f, THIS_OBJ);
    -  assertEquals('HRPPPPPPPPH1', values.join(''));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/treenode.js b/src/database/third_party/closure-library/closure/goog/structs/treenode.js
    deleted file mode 100644
    index 9df77a32870..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/treenode.js
    +++ /dev/null
    @@ -1,456 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Generic tree node data structure with arbitrary number of child
    - * nodes.
    - *
    - */
    -
    -goog.provide('goog.structs.TreeNode');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.structs.Node');
    -
    -
    -
    -/**
    - * Generic tree node data structure with arbitrary number of child nodes.
    - * It is possible to create a dynamic tree structure by overriding
    - * {@link #getParent} and {@link #getChildren} in a subclass. All other getters
    - * will automatically work.
    - *
    - * @param {KEY} key Key.
    - * @param {VALUE} value Value.
    - * @constructor
    - * @extends {goog.structs.Node<KEY, VALUE>}
    - * @template KEY, VALUE
    - */
    -goog.structs.TreeNode = function(key, value) {
    -  goog.structs.Node.call(this, key, value);
    -
    -  /**
    -   * Reference to the parent node or null if it has no parent.
    -   * @private {goog.structs.TreeNode<KEY, VALUE>}
    -   */
    -  this.parent_ = null;
    -
    -  /**
    -   * Child nodes or null in case of leaf node.
    -   * @private {Array<!goog.structs.TreeNode<KEY, VALUE>>}
    -   */
    -  this.children_ = null;
    -};
    -goog.inherits(goog.structs.TreeNode, goog.structs.Node);
    -
    -
    -/**
    - * Constant for empty array to avoid unnecessary allocations.
    - * @private
    - */
    -goog.structs.TreeNode.EMPTY_ARRAY_ = [];
    -
    -
    -/**
    - * @return {!goog.structs.TreeNode} Clone of the tree node without its parent
    - *     and child nodes. The key and the value are copied by reference.
    - * @override
    - */
    -goog.structs.TreeNode.prototype.clone = function() {
    -  return new goog.structs.TreeNode(this.getKey(), this.getValue());
    -};
    -
    -
    -/**
    - * @return {!goog.structs.TreeNode} Clone of the subtree with this node as root.
    - */
    -goog.structs.TreeNode.prototype.deepClone = function() {
    -  var clone = this.clone();
    -  this.forEachChild(function(child) {
    -    clone.addChild(child.deepClone());
    -  });
    -  return clone;
    -};
    -
    -
    -/**
    - * @return {goog.structs.TreeNode<KEY, VALUE>} Parent node or null if it has no
    - *     parent.
    - */
    -goog.structs.TreeNode.prototype.getParent = function() {
    -  return this.parent_;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the node is a leaf node.
    - */
    -goog.structs.TreeNode.prototype.isLeaf = function() {
    -  return !this.getChildCount();
    -};
    -
    -
    -/**
    - * Tells if the node is the last child of its parent. This method helps how to
    - * connect the tree nodes with lines: L shapes should be used before the last
    - * children and |- shapes before the rest. Schematic tree visualization:
    - *
    - * <pre>
    - * Node1
    - * |-Node2
    - * | L-Node3
    - * |   |-Node4
    - * |   L-Node5
    - * L-Node6
    - * </pre>
    - *
    - * @return {boolean} Whether the node has parent and is the last child of it.
    - */
    -goog.structs.TreeNode.prototype.isLastChild = function() {
    -  var parent = this.getParent();
    -  return Boolean(parent && this == goog.array.peek(parent.getChildren()));
    -};
    -
    -
    -/**
    - * @return {!Array<!goog.structs.TreeNode<KEY, VALUE>>} Immutable child nodes.
    - */
    -goog.structs.TreeNode.prototype.getChildren = function() {
    -  return this.children_ || goog.structs.TreeNode.EMPTY_ARRAY_;
    -};
    -
    -
    -/**
    - * Gets the child node of this node at the given index.
    - * @param {number} index Child index.
    - * @return {goog.structs.TreeNode<KEY, VALUE>} The node at the given index or
    - *     null if not found.
    - */
    -goog.structs.TreeNode.prototype.getChildAt = function(index) {
    -  return this.getChildren()[index] || null;
    -};
    -
    -
    -/**
    - * @return {number} The number of children.
    - */
    -goog.structs.TreeNode.prototype.getChildCount = function() {
    -  return this.getChildren().length;
    -};
    -
    -
    -/**
    - * @return {number} The number of ancestors of the node.
    - */
    -goog.structs.TreeNode.prototype.getDepth = function() {
    -  var depth = 0;
    -  var node = this;
    -  while (node.getParent()) {
    -    depth++;
    -    node = node.getParent();
    -  }
    -  return depth;
    -};
    -
    -
    -/**
    - * @return {!Array<!goog.structs.TreeNode<KEY, VALUE>>} All ancestor nodes in
    - *     bottom-up order.
    - */
    -goog.structs.TreeNode.prototype.getAncestors = function() {
    -  var ancestors = [];
    -  var node = this.getParent();
    -  while (node) {
    -    ancestors.push(node);
    -    node = node.getParent();
    -  }
    -  return ancestors;
    -};
    -
    -
    -/**
    - * @return {!goog.structs.TreeNode<KEY, VALUE>} The root of the tree structure,
    - *     i.e. the farthest ancestor of the node or the node itself if it has no
    - *     parents.
    - */
    -goog.structs.TreeNode.prototype.getRoot = function() {
    -  var root = this;
    -  while (root.getParent()) {
    -    root = root.getParent();
    -  }
    -  return root;
    -};
    -
    -
    -/**
    - * Builds a nested array structure from the node keys in this node's subtree to
    - * facilitate testing tree operations that change the hierarchy.
    - * @return {!Array<KEY>} The structure of this node's descendants as nested
    - *     array of node keys. The number of unclosed opening brackets up to a
    - *     particular node is proportional to the indentation of that node in the
    - *     graphical representation of the tree. Example:
    - *     <pre>
    - *       this
    - *       |- child1
    - *       |  L- grandchild
    - *       L- child2
    - *     </pre>
    - *     is represented as ['child1', ['grandchild'], 'child2'].
    - */
    -goog.structs.TreeNode.prototype.getSubtreeKeys = function() {
    -  var ret = [];
    -  this.forEachChild(function(child) {
    -    ret.push(child.getKey());
    -    if (!child.isLeaf()) {
    -      ret.push(child.getSubtreeKeys());
    -    }
    -  });
    -  return ret;
    -};
    -
    -
    -/**
    - * Tells whether this node is the ancestor of the given node.
    - * @param {!goog.structs.TreeNode<KEY, VALUE>} node A node.
    - * @return {boolean} Whether this node is the ancestor of {@code node}.
    - */
    -goog.structs.TreeNode.prototype.contains = function(node) {
    -  var current = node;
    -  do {
    -    current = current.getParent();
    -  } while (current && current != this);
    -  return Boolean(current);
    -};
    -
    -
    -/**
    - * Finds the deepest common ancestor of the given nodes. The concept of
    - * ancestor is not strict in this case, it includes the node itself.
    - * @param {...!goog.structs.TreeNode<KEY, VALUE>} var_args The nodes.
    - * @return {goog.structs.TreeNode<KEY, VALUE>} The common ancestor of the nodes
    - *     or null if they are from different trees.
    - * @template KEY, VALUE
    - */
    -goog.structs.TreeNode.findCommonAncestor = function(var_args) {
    -  /** @type {goog.structs.TreeNode} */
    -  var ret = arguments[0];
    -  if (!ret) {
    -    return null;
    -  }
    -
    -  var retDepth = ret.getDepth();
    -  for (var i = 1; i < arguments.length; i++) {
    -    /** @type {goog.structs.TreeNode} */
    -    var node = arguments[i];
    -    var depth = node.getDepth();
    -    while (node != ret) {
    -      if (depth <= retDepth) {
    -        ret = ret.getParent();
    -        retDepth--;
    -      }
    -      if (depth > retDepth) {
    -        node = node.getParent();
    -        depth--;
    -      }
    -    }
    -  }
    -
    -  return ret;
    -};
    -
    -
    -/**
    - * Returns a node whose key matches the given one in the hierarchy rooted at
    - * this node. The hierarchy is searched using an in-order traversal.
    - * @param {KEY} key The key to search for.
    - * @return {goog.structs.TreeNode<KEY, VALUE>} The node with the given key, or
    - *     null if no node with the given key exists in the hierarchy.
    - */
    -goog.structs.TreeNode.prototype.getNodeByKey = function(key) {
    -  if (this.getKey() == key) {
    -    return this;
    -  }
    -  var children = this.getChildren();
    -  for (var i = 0; i < children.length; i++) {
    -    var descendant = children[i].getNodeByKey(key);
    -    if (descendant) {
    -      return descendant;
    -    }
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * Traverses all child nodes.
    - * @param {function(this:THIS, !goog.structs.TreeNode<KEY, VALUE>, number,
    - *     !Array<!goog.structs.TreeNode<KEY, VALUE>>)} f Callback function. It
    - *     takes the node, its index and the array of all child nodes as arguments.
    - * @param {THIS=} opt_this The object to be used as the value of {@code this}
    - *     within {@code f}.
    - * @template THIS
    - */
    -goog.structs.TreeNode.prototype.forEachChild = function(f, opt_this) {
    -  goog.array.forEach(this.getChildren(), f, opt_this);
    -};
    -
    -
    -/**
    - * Traverses all child nodes recursively in preorder.
    - * @param {function(this:THIS, !goog.structs.TreeNode<KEY, VALUE>)} f Callback
    - *     function.  It takes the node as argument.
    - * @param {THIS=} opt_this The object to be used as the value of {@code this}
    - *     within {@code f}.
    - * @template THIS
    - */
    -goog.structs.TreeNode.prototype.forEachDescendant = function(f, opt_this) {
    -  goog.array.forEach(this.getChildren(), function(child) {
    -    f.call(opt_this, child);
    -    child.forEachDescendant(f, opt_this);
    -  });
    -};
    -
    -
    -/**
    - * Traverses the subtree with the possibility to skip branches. Starts with
    - * this node, and visits the descendant nodes depth-first, in preorder.
    - * @param {function(this:THIS, !goog.structs.TreeNode<KEY, VALUE>):
    - *     (boolean|undefined)} f Callback function. It takes the node as argument.
    - *     The children of this node will be visited if the callback returns true or
    - *     undefined, and will be skipped if the callback returns false.
    - * @param {THIS=} opt_this The object to be used as the value of {@code this}
    - *     within {@code f}.
    - * @template THIS
    - */
    -goog.structs.TreeNode.prototype.traverse = function(f, opt_this) {
    -  if (f.call(opt_this, this) !== false) {
    -    goog.array.forEach(this.getChildren(), function(child) {
    -      child.traverse(f, opt_this);
    -    });
    -  }
    -};
    -
    -
    -/**
    - * Sets the parent node of this node. The callers must ensure that the parent
    - * node and only that has this node among its children.
    - * @param {goog.structs.TreeNode<KEY, VALUE>} parent The parent to set. If
    - *     null, the node will be detached from the tree.
    - * @protected
    - */
    -goog.structs.TreeNode.prototype.setParent = function(parent) {
    -  this.parent_ = parent;
    -};
    -
    -
    -/**
    - * Appends a child node to this node.
    - * @param {!goog.structs.TreeNode<KEY, VALUE>} child Orphan child node.
    - */
    -goog.structs.TreeNode.prototype.addChild = function(child) {
    -  this.addChildAt(child, this.children_ ? this.children_.length : 0);
    -};
    -
    -
    -/**
    - * Inserts a child node at the given index.
    - * @param {!goog.structs.TreeNode<KEY, VALUE>} child Orphan child node.
    - * @param {number} index The position to insert at.
    - */
    -goog.structs.TreeNode.prototype.addChildAt = function(child, index) {
    -  goog.asserts.assert(!child.getParent());
    -  child.setParent(this);
    -  this.children_ = this.children_ || [];
    -  goog.asserts.assert(index >= 0 && index <= this.children_.length);
    -  goog.array.insertAt(this.children_, child, index);
    -};
    -
    -
    -/**
    - * Replaces a child node at the given index.
    - * @param {!goog.structs.TreeNode<KEY, VALUE>} newChild Child node to set. It
    - *     must not have parent node.
    - * @param {number} index Valid index of the old child to replace.
    - * @return {!goog.structs.TreeNode<KEY, VALUE>} The original child node,
    - *     detached from its parent.
    - */
    -goog.structs.TreeNode.prototype.replaceChildAt = function(newChild, index) {
    -  goog.asserts.assert(!newChild.getParent(),
    -      'newChild must not have parent node');
    -  var children = this.getChildren();
    -  var oldChild = children[index];
    -  goog.asserts.assert(oldChild, 'Invalid child or child index is given.');
    -  oldChild.setParent(null);
    -  children[index] = newChild;
    -  newChild.setParent(this);
    -  return oldChild;
    -};
    -
    -
    -/**
    - * Replaces the given child node.
    - * @param {!goog.structs.TreeNode<KEY, VALUE>} newChild New node to replace
    - *     {@code oldChild}. It must not have parent node.
    - * @param {!goog.structs.TreeNode<KEY, VALUE>} oldChild Existing child node to
    - *     be replaced.
    - * @return {!goog.structs.TreeNode<KEY, VALUE>} The replaced child node
    - *     detached from its parent.
    - */
    -goog.structs.TreeNode.prototype.replaceChild = function(newChild, oldChild) {
    -  return this.replaceChildAt(newChild,
    -      goog.array.indexOf(this.getChildren(), oldChild));
    -};
    -
    -
    -/**
    - * Removes the child node at the given index.
    - * @param {number} index The position to remove from.
    - * @return {goog.structs.TreeNode<KEY, VALUE>} The removed node if any.
    - */
    -goog.structs.TreeNode.prototype.removeChildAt = function(index) {
    -  var child = this.children_ && this.children_[index];
    -  if (child) {
    -    child.setParent(null);
    -    goog.array.removeAt(this.children_, index);
    -    if (this.children_.length == 0) {
    -      delete this.children_;
    -    }
    -    return child;
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * Removes the given child node of this node.
    - * @param {goog.structs.TreeNode<KEY, VALUE>} child The node to remove.
    - * @return {goog.structs.TreeNode<KEY, VALUE>} The removed node if any.
    - */
    -goog.structs.TreeNode.prototype.removeChild = function(child) {
    -  return this.removeChildAt(goog.array.indexOf(this.getChildren(), child));
    -};
    -
    -
    -/**
    - * Removes all child nodes of this node.
    - */
    -goog.structs.TreeNode.prototype.removeChildren = function() {
    -  if (this.children_) {
    -    goog.array.forEach(this.children_, function(child) {
    -      child.setParent(null);
    -    });
    -  }
    -  delete this.children_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/treenode_test.html b/src/database/third_party/closure-library/closure/goog/structs/treenode_test.html
    deleted file mode 100644
    index 73312f49939..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/treenode_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.structs.TreeNode
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.structs.TreeNodeTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/treenode_test.js b/src/database/third_party/closure-library/closure/goog/structs/treenode_test.js
    deleted file mode 100644
    index 86a1f0550e3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/treenode_test.js
    +++ /dev/null
    @@ -1,384 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.structs.TreeNodeTest');
    -goog.setTestOnly('goog.structs.TreeNodeTest');
    -
    -goog.require('goog.structs.TreeNode');
    -goog.require('goog.testing.jsunit');
    -
    -function testConstructor() {
    -  var node = new goog.structs.TreeNode('key', 'value');
    -  assertEquals('key', 'key', node.getKey());
    -  assertEquals('value', 'value', node.getValue());
    -  assertNull('parent', node.getParent());
    -  assertArrayEquals('children', [], node.getChildren());
    -  assertTrue('leaf', node.isLeaf());
    -}
    -
    -function testClone() {
    -  var node1 = new goog.structs.TreeNode(1, '1');
    -  var node2 = new goog.structs.TreeNode(2, '2');
    -  var node3 = new goog.structs.TreeNode(3, '3');
    -  node1.addChild(node2);
    -  node2.addChild(node3);
    -
    -  var clone = node2.clone();
    -  assertEquals('key', 2, clone.getKey());
    -  assertEquals('value', '2', clone.getValue());
    -  assertNull('parent', clone.getParent());
    -  assertArrayEquals('children', [], clone.getChildren());
    -}
    -
    -function testDeepClone() {
    -  var node1 = new goog.structs.TreeNode(1, '1');
    -  var node2 = new goog.structs.TreeNode(2, '2');
    -  var node3 = new goog.structs.TreeNode(3, '3');
    -  node1.addChild(node2);
    -  node2.addChild(node3);
    -
    -  var clone = node2.deepClone();
    -  assertEquals('key', 2, clone.getKey());
    -  assertEquals('value', '2', clone.getValue());
    -  assertNull('parent', clone.getParent());
    -  assertEquals('number of children', 1, clone.getChildren().length);
    -  assertEquals('first child key', 3, clone.getChildAt(0).getKey());
    -  assertNotEquals('first child has been cloned', node3, clone.getChildAt(0));
    -}
    -
    -function testGetParent() {
    -  var node1 = new goog.structs.TreeNode(1, null);
    -  var node2 = new goog.structs.TreeNode(2, null);
    -  node1.addChild(node2);
    -  assertEquals('parent', node1, node2.getParent());
    -  assertNull('orphan', node1.getParent());
    -}
    -
    -function testIsLeaf() {
    -  var node1 = new goog.structs.TreeNode(1, null);
    -  var node2 = new goog.structs.TreeNode(2, null);
    -  node1.addChild(node2);
    -  assertFalse('not leaf', node1.isLeaf());
    -  assertTrue('leaf', node2.isLeaf());
    -}
    -
    -function testIsLastChild() {
    -  var node1 = new goog.structs.TreeNode(1, '1');
    -  var node2 = new goog.structs.TreeNode(2, '2');
    -  var node3 = new goog.structs.TreeNode(3, '3');
    -  node1.addChild(node2);
    -  node1.addChild(node3);
    -  assertFalse('root', node1.isLastChild());
    -  assertFalse('first child out of the two', node2.isLastChild());
    -  assertTrue('second child out of the two', node3.isLastChild());
    -}
    -
    -function testGetChildren() {
    -  var node1 = new goog.structs.TreeNode(1, null);
    -  var node2 = new goog.structs.TreeNode(2, null);
    -  node1.addChild(node2);
    -  assertArrayEquals('1 child', [node2], node1.getChildren());
    -  assertArrayEquals('no children', [], node2.getChildren());
    -}
    -
    -function testGetChildAt() {
    -  var node1 = new goog.structs.TreeNode(1, null);
    -  var node2 = new goog.structs.TreeNode(2, null);
    -  node1.addChild(node2);
    -  assertNull('index too low', node1.getChildAt(-1));
    -  assertEquals('first child', node2, node1.getChildAt(0));
    -  assertNull('index too high', node1.getChildAt(1));
    -  assertNull('no children', node2.getChildAt(0));
    -}
    -
    -function testGetChildCount() {
    -  var node1 = new goog.structs.TreeNode(1, null);
    -  var node2 = new goog.structs.TreeNode(2, null);
    -  node1.addChild(node2);
    -  assertEquals('child count of root node', 1, node1.getChildCount());
    -  assertEquals('child count of leaf node', 0, node2.getChildCount());
    -}
    -
    -function testGetDepth() {
    -  var node1 = new goog.structs.TreeNode(1, null);
    -  var node2 = new goog.structs.TreeNode(2, null);
    -  var node3 = new goog.structs.TreeNode(3, null);
    -  node1.addChild(node2);
    -  node2.addChild(node3);
    -  assertEquals('no parent', 0, node1.getDepth());
    -  assertEquals('1 ancestor', 1, node2.getDepth());
    -  assertEquals('2 ancestors', 2, node3.getDepth());
    -}
    -
    -function testGetAncestors() {
    -  var node1 = new goog.structs.TreeNode(1, null);
    -  var node2 = new goog.structs.TreeNode(2, null);
    -  var node3 = new goog.structs.TreeNode(3, null);
    -  node1.addChild(node2);
    -  node2.addChild(node3);
    -  assertArrayEquals('no ancestors', [], node1.getAncestors());
    -  assertArrayEquals('2 ancestors', [node2, node1], node3.getAncestors());
    -}
    -
    -function testGetRoot() {
    -  var node1 = new goog.structs.TreeNode(1, null);
    -  var node2 = new goog.structs.TreeNode(2, null);
    -  node1.addChild(node2);
    -  assertEquals('no ancestors', node1, node1.getRoot());
    -  assertEquals('has ancestors', node1, node2.getRoot());
    -}
    -
    -function testGetSubtreeKeys() {
    -  var root = new goog.structs.TreeNode('root', null);
    -  var child1 = new goog.structs.TreeNode('child1', null);
    -  var child2 = new goog.structs.TreeNode('child2', null);
    -  var grandchild = new goog.structs.TreeNode('grandchild', null);
    -  root.addChild(child1);
    -  root.addChild(child2);
    -  child1.addChild(grandchild);
    -  assertArrayEquals('node hierarchy', ['child1', ['grandchild'], 'child2'],
    -      root.getSubtreeKeys());
    -}
    -
    -function testContains() {
    -  var node1 = new goog.structs.TreeNode(1, null);
    -  var node2 = new goog.structs.TreeNode(2, null);
    -  var node3 = new goog.structs.TreeNode(3, null);
    -  var node4 = new goog.structs.TreeNode(4, null);
    -  node1.addChild(node2);
    -  node2.addChild(node3);
    -  node2.addChild(node4);
    -
    -  assertTrue('parent', node1.contains(node2));
    -  assertTrue('grandparent', node1.contains(node3));
    -  assertFalse('child', node2.contains(node1));
    -  assertFalse('grandchild', node3.contains(node1));
    -  assertFalse('sibling', node3.contains(node4));
    -}
    -
    -function testFindCommonAncestor() {
    -  var findCommonAncestor = goog.structs.TreeNode.findCommonAncestor;
    -  var node1 = new goog.structs.TreeNode(1, null);
    -  var node2 = new goog.structs.TreeNode(2, null);
    -  var node3 = new goog.structs.TreeNode(3, null);
    -  var node4 = new goog.structs.TreeNode(4, null);
    -  var node5 = new goog.structs.TreeNode(5, null);
    -  node1.addChild(node2);
    -  node2.addChild(node3);
    -  node1.addChild(node4);
    -
    -  assertNull('0 nodes', findCommonAncestor());
    -  assertEquals('1 node', node2, findCommonAncestor(node2));
    -  assertEquals('same nodes', node3, findCommonAncestor(node3, node3));
    -  assertEquals('node and child node', node2, findCommonAncestor(node2, node3));
    -  assertEquals('node and parent node', node1, findCommonAncestor(node2, node1));
    -  assertEquals('siblings', node1, findCommonAncestor(node2, node4));
    -  assertEquals('all nodes', node1,
    -      findCommonAncestor(node2, node3, node4, node1));
    -  assertNull('disconnected nodes', findCommonAncestor(node3, node5));
    -}
    -
    -function testGetNodeByKey() {
    -  var node1 = new goog.structs.TreeNode(1, null);
    -  var node2 = new goog.structs.TreeNode(2, null);
    -  var node3 = new goog.structs.TreeNode(3, null);
    -  var node4 = new goog.structs.TreeNode(4, null);
    -  var node5 = new goog.structs.TreeNode(2, null);
    -  var node6 = new goog.structs.TreeNode(3, null);
    -  node1.addChild(node2);
    -  node2.addChild(node3);
    -  node1.addChild(node4);
    -  node4.addChild(node5);
    -  node1.addChild(node6);
    -
    -  assertEquals('root', node1, node1.getNodeByKey(1));
    -  assertEquals('child with unique key', node5, node4.getNodeByKey(2));
    -  assertEquals('child with duplicate keys', node2, node1.getNodeByKey(2));
    -  assertEquals('grandchild with duplicate keys', node3, node1.getNodeByKey(3));
    -  assertNull('disconnected', node2.getNodeByKey(4));
    -  assertNull('missing', node1.getNodeByKey(5));
    -}
    -
    -function testForEachChild() {
    -  var node1 = new goog.structs.TreeNode(1, null);
    -  var node2 = new goog.structs.TreeNode(2, null);
    -  var node3 = new goog.structs.TreeNode(3, null);
    -  node1.addChild(node2);
    -  node1.addChild(node3);
    -
    -  var thisContext = {};
    -  var visitedNodes = [];
    -  var indices = [];
    -  node1.forEachChild(function(node, index, children) {
    -    assertEquals('value of this', thisContext, this);
    -    visitedNodes.push(node);
    -    indices.push(index);
    -    assertArrayEquals('children argument', [node2, node3], children);
    -  }, thisContext);
    -  assertArrayEquals('visited nodes', [node2, node3], visitedNodes);
    -  assertArrayEquals('index of visited nodes', [0, 1], indices);
    -}
    -
    -function testForEachDescendant() {
    -  var node1 = new goog.structs.TreeNode(1, null);
    -  var node2 = new goog.structs.TreeNode(2, null);
    -  var node3 = new goog.structs.TreeNode(3, null);
    -  var node4 = new goog.structs.TreeNode(4, null);
    -  node1.addChild(node2);
    -  node2.addChild(node3);
    -  node2.addChild(node4);
    -
    -  var thisContext = {};
    -  var visitedNodes = [];
    -  node1.forEachDescendant(function(node) {
    -    assertEquals('value of this', thisContext, this);
    -    visitedNodes.push(node);
    -  }, thisContext);
    -  assertArrayEquals('visited nodes', [node2, node3, node4], visitedNodes);
    -}
    -
    -function testTraverse() {
    -  var node1 = new goog.structs.TreeNode(1, null);
    -  var node2 = new goog.structs.TreeNode(2, null);
    -  var node3 = new goog.structs.TreeNode(3, null);
    -  var node4 = new goog.structs.TreeNode(4, null);
    -  node1.addChild(node2);
    -  node2.addChild(node3);
    -  node2.addChild(node4);
    -
    -  var thisContext = {};
    -  var visitedNodes = [];
    -  node1.traverse(function(node) {
    -    assertEquals('value of this', thisContext, this);
    -    visitedNodes.push(node);
    -  }, thisContext);
    -  assertArrayEquals('callback returns nothing => all nodes are visited',
    -      [node1, node2, node3, node4], visitedNodes);
    -
    -  visitedNodes = [];
    -  node1.traverse(function(node) {
    -    visitedNodes.push(node);
    -    return node != node2;  // Cut off at node2.
    -  });
    -  assertArrayEquals('children of node2 are skipped',
    -      [node1, node2], visitedNodes);
    -}
    -
    -function testAddChild() {
    -  var node1 = new goog.structs.TreeNode(1, null);
    -  var node2 = new goog.structs.TreeNode(2, null);
    -  var node3 = new goog.structs.TreeNode(3, null);
    -  assertArrayEquals('0 children', [], node1.getChildren());
    -  node1.addChild(node2);
    -  assertArrayEquals('1 child', [node2], node1.getChildren());
    -  assertEquals('parent is set', node1, node2.getParent());
    -  node1.addChild(node3);
    -  assertArrayEquals('2 children', [node2, node3], node1.getChildren());
    -}
    -
    -function testAddChildAt() {
    -  var node1 = new goog.structs.TreeNode(1, null);
    -  var node2 = new goog.structs.TreeNode(2, null);
    -  var node3 = new goog.structs.TreeNode(3, null);
    -  var node4 = new goog.structs.TreeNode(4, null);
    -  var node5 = new goog.structs.TreeNode(5, null);
    -  node1.addChildAt(node2, 0);
    -  assertArrayEquals('add first child', [node2], node1.getChildren());
    -  assertEquals('parent is set', node1, node2.getParent());
    -  node1.addChildAt(node3, 0);
    -  assertArrayEquals('add to the front', [node3, node2],
    -      node1.getChildren());
    -  node1.addChildAt(node4, 1);
    -  assertArrayEquals('add to the middle', [node3, node4, node2],
    -      node1.getChildren());
    -  node1.addChildAt(node5, 3);
    -  assertArrayEquals('add to the end', [node3, node4, node2, node5],
    -      node1.getChildren());
    -}
    -
    -function testReplaceChildAt() {
    -  var root = new goog.structs.TreeNode(0, null);
    -  var node1 = new goog.structs.TreeNode(1, null);
    -  root.addChild(node1);
    -
    -  var node2 = new goog.structs.TreeNode(2, null);
    -  assertEquals('original node', node1, root.replaceChildAt(node2, 0));
    -  assertEquals('parent is set', root, node2.getParent());
    -  assertArrayEquals('children are updated', [node2], root.getChildren());
    -  assertNull('old child node is detached', node1.getParent());
    -}
    -
    -function testReplaceChild() {
    -  var root = new goog.structs.TreeNode(0, null);
    -  var node1 = new goog.structs.TreeNode(1, null);
    -  root.addChild(node1);
    -
    -  var node2 = new goog.structs.TreeNode(2, null);
    -  assertEquals('original node', node1, root.replaceChild(node2, node1));
    -  assertEquals('parent is set', root, node2.getParent());
    -  assertArrayEquals('children are updated', [node2], root.getChildren());
    -  assertNull('old child node is detached', node1.getParent());
    -}
    -
    -function testRemoveChildAt() {
    -  var node1 = new goog.structs.TreeNode(1, null);
    -  var node2 = new goog.structs.TreeNode(2, null);
    -  var node3 = new goog.structs.TreeNode(3, null);
    -  node1.addChild(node2);
    -  node1.addChild(node3);
    -
    -  assertNull('index too low', node1.removeChildAt(-1));
    -  assertNull('index too high', node1.removeChildAt(2));
    -  assertArrayEquals('node1 is intact', [node2, node3], node1.getChildren());
    -
    -  assertEquals('remove first child', node2, node1.removeChildAt(0));
    -  assertArrayEquals('remove from the front', [node3], node1.getChildren());
    -  assertNull('parent is unset', node2.getParent());
    -
    -  assertEquals('remove last child', node3, node1.removeChildAt(0));
    -  assertArrayEquals('remove last child', [], node1.getChildren());
    -  assertTrue('node1 became leaf', node1.isLeaf());
    -}
    -
    -function testRemoveChild() {
    -  var node1 = new goog.structs.TreeNode(1, null);
    -  var node2 = new goog.structs.TreeNode(2, null);
    -  var node3 = new goog.structs.TreeNode(3, null);
    -  node1.addChild(node2);
    -  node1.addChild(node3);
    -
    -  assertNull('remove null', node1.removeChild(null));
    -  assertNull('remove non-child', node1.removeChild(node1));
    -  assertArrayEquals('node1 is intact', [node2, node3], node1.getChildren());
    -
    -  assertEquals('remove node3, return value', node3, node1.removeChild(node3));
    -  assertArrayEquals('node is removed', [node2], node1.getChildren());
    -}
    -
    -function testRemoveChildren() {
    -  var node1 = new goog.structs.TreeNode(1, null);
    -  var node2 = new goog.structs.TreeNode(2, null);
    -  var node3 = new goog.structs.TreeNode(3, null);
    -  node1.addChild(node2);
    -  node1.addChild(node3);
    -
    -  node2.removeChildren();
    -  assertArrayEquals('removing a leaf node\'s children has no effect', [],
    -      node2.getChildren());
    -  assertEquals('node still has parent', node1, node2.getParent());
    -
    -  node1.removeChildren();
    -  assertArrayEquals('children have been removed', [], node1.getChildren());
    -  assertNull('children\'s parents have been unset', node2.getParent());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/trie.js b/src/database/third_party/closure-library/closure/goog/structs/trie.js
    deleted file mode 100644
    index e583290865f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/trie.js
    +++ /dev/null
    @@ -1,395 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Datastructure: Trie.
    - *
    - *
    - * This file provides the implementation of a trie data structure.  A trie is a
    - * data structure that stores key/value pairs in a prefix tree.  See:
    - *     http://en.wikipedia.org/wiki/Trie
    - */
    -
    -
    -goog.provide('goog.structs.Trie');
    -
    -goog.require('goog.object');
    -goog.require('goog.structs');
    -
    -
    -
    -/**
    - * Class for a Trie datastructure.  Trie data structures are made out of trees
    - * of Trie classes.
    - *
    - * @param {goog.structs.Trie<VALUE>|Object<string, VALUE>=} opt_trie Optional
    - *     goog.structs.Trie or Object to initialize trie with.
    - * @constructor
    - * @template VALUE
    - */
    -goog.structs.Trie = function(opt_trie) {
    -  /**
    -   * This trie's value.  For the base trie, this will be the value of the
    -   * empty key, if defined.
    -   * @private {VALUE}
    -   */
    -  this.value_ = undefined;
    -
    -  /**
    -   * This trie's child nodes.
    -   * @private {!Object<!goog.structs.Trie<VALUE>>}
    -   */
    -  this.childNodes_ = {};
    -
    -  if (opt_trie) {
    -    this.setAll(opt_trie);
    -  }
    -};
    -
    -
    -/**
    - * Sets the given key/value pair in the trie.  O(L), where L is the length
    - * of the key.
    - * @param {string} key The key.
    - * @param {VALUE} value The value.
    - */
    -goog.structs.Trie.prototype.set = function(key, value) {
    -  this.setOrAdd_(key, value, false);
    -};
    -
    -
    -/**
    - * Adds the given key/value pair in the trie.  Throw an exception if the key
    - * already exists in the trie.  O(L), where L is the length of the key.
    - * @param {string} key The key.
    - * @param {VALUE} value The value.
    - */
    -goog.structs.Trie.prototype.add = function(key, value) {
    -  this.setOrAdd_(key, value, true);
    -};
    -
    -
    -/**
    - * Helper function for set and add.  Adds the given key/value pair to
    - * the trie, or, if the key already exists, sets the value of the key. If
    - * opt_add is true, then throws an exception if the key already has a value in
    - * the trie.  O(L), where L is the length of the key.
    - * @param {string} key The key.
    - * @param {VALUE} value The value.
    - * @param {boolean=} opt_add Throw exception if key is already in the trie.
    - * @private
    - */
    -goog.structs.Trie.prototype.setOrAdd_ = function(key, value, opt_add) {
    -  var node = this;
    -  for (var characterPosition = 0; characterPosition < key.length;
    -       characterPosition++) {
    -    var currentCharacter = key.charAt(characterPosition);
    -    if (!node.childNodes_[currentCharacter]) {
    -      node.childNodes_[currentCharacter] = new goog.structs.Trie();
    -    }
    -    node = node.childNodes_[currentCharacter];
    -  }
    -  if (opt_add && node.value_ !== undefined) {
    -    throw Error('The collection already contains the key "' + key + '"');
    -  } else {
    -    node.value_ = value;
    -  }
    -};
    -
    -
    -/**
    - * Adds multiple key/value pairs from another goog.structs.Trie or Object.
    - * O(N) where N is the number of nodes in the trie.
    - * @param {!Object<string, VALUE>|!goog.structs.Trie<VALUE>} trie Object
    - *     containing the data to add.
    - */
    -goog.structs.Trie.prototype.setAll = function(trie) {
    -  var keys = goog.structs.getKeys(trie);
    -  var values = goog.structs.getValues(trie);
    -
    -  for (var i = 0; i < keys.length; i++) {
    -    this.set(keys[i], values[i]);
    -  }
    -};
    -
    -
    -/**
    - * Traverse along the given path, returns the child node at ending.
    - * Returns undefined if node for the path doesn't exist.
    - * @param {string} path The path to traverse.
    - * @return {!goog.structs.Trie<VALUE>|undefined}
    - * @private
    - */
    -goog.structs.Trie.prototype.getChildNode_ = function(path) {
    -  var node = this;
    -  for (var characterPosition = 0; characterPosition < path.length;
    -      characterPosition++) {
    -    var currentCharacter = path.charAt(characterPosition);
    -    node = node.childNodes_[currentCharacter];
    -    if (!node) {
    -      return undefined;
    -    }
    -  }
    -  return node;
    -};
    -
    -
    -/**
    - * Retrieves a value from the trie given a key.  O(L), where L is the length of
    - * the key.
    - * @param {string} key The key to retrieve from the trie.
    - * @return {VALUE|undefined} The value of the key in the trie, or undefined if
    - *     the trie does not contain this key.
    - */
    -goog.structs.Trie.prototype.get = function(key) {
    -  var node = this.getChildNode_(key);
    -  return node ? node.value_ : undefined;
    -};
    -
    -
    -/**
    - * Retrieves all values from the trie that correspond to prefixes of the given
    - * input key. O(L), where L is the length of the key.
    - *
    - * @param {string} key The key to use for lookup. The given key as well as all
    - *     prefixes of the key are retrieved.
    - * @param {?number=} opt_keyStartIndex Optional position in key to start lookup
    - *     from. Defaults to 0 if not specified.
    - * @return {!Object<string, VALUE>} Map of end index of matching prefixes and
    - *     corresponding values. Empty if no match found.
    - */
    -goog.structs.Trie.prototype.getKeyAndPrefixes = function(key,
    -                                                         opt_keyStartIndex) {
    -  var node = this;
    -  var matches = {};
    -  var characterPosition = opt_keyStartIndex || 0;
    -
    -  if (node.value_ !== undefined) {
    -    matches[characterPosition] = node.value_;
    -  }
    -
    -  for (; characterPosition < key.length; characterPosition++) {
    -    var currentCharacter = key.charAt(characterPosition);
    -    if (!(currentCharacter in node.childNodes_)) {
    -      break;
    -    }
    -    node = node.childNodes_[currentCharacter];
    -    if (node.value_ !== undefined) {
    -      matches[characterPosition] = node.value_;
    -    }
    -  }
    -
    -  return matches;
    -};
    -
    -
    -/**
    - * Gets the values of the trie.  Not returned in any reliable order.  O(N) where
    - * N is the number of nodes in the trie.  Calls getValuesInternal_.
    - * @return {!Array<VALUE>} The values in the trie.
    - */
    -goog.structs.Trie.prototype.getValues = function() {
    -  var allValues = [];
    -  this.getValuesInternal_(allValues);
    -  return allValues;
    -};
    -
    -
    -/**
    - * Gets the values of the trie.  Not returned in any reliable order.  O(N) where
    - * N is the number of nodes in the trie.  Builds the values as it goes.
    - * @param {!Array<VALUE>} allValues Array to place values into.
    - * @private
    - */
    -goog.structs.Trie.prototype.getValuesInternal_ = function(allValues) {
    -  if (this.value_ !== undefined) {
    -    allValues.push(this.value_);
    -  }
    -  for (var childNode in this.childNodes_) {
    -    this.childNodes_[childNode].getValuesInternal_(allValues);
    -  }
    -};
    -
    -
    -/**
    - * Gets the keys of the trie.  Not returned in any reliable order.  O(N) where
    - * N is the number of nodes in the trie (or prefix subtree).
    - * @param {string=} opt_prefix Find only keys with this optional prefix.
    - * @return {!Array<string>} The keys in the trie.
    - */
    -goog.structs.Trie.prototype.getKeys = function(opt_prefix) {
    -  var allKeys = [];
    -  if (opt_prefix) {
    -    // Traverse to the given prefix, then call getKeysInternal_ to dump the
    -    // keys below that point.
    -    var node = this;
    -    for (var characterPosition = 0; characterPosition < opt_prefix.length;
    -        characterPosition++) {
    -      var currentCharacter = opt_prefix.charAt(characterPosition);
    -      if (!node.childNodes_[currentCharacter]) {
    -        return [];
    -      }
    -      node = node.childNodes_[currentCharacter];
    -    }
    -    node.getKeysInternal_(opt_prefix, allKeys);
    -  } else {
    -    this.getKeysInternal_('', allKeys);
    -  }
    -  return allKeys;
    -};
    -
    -
    -/**
    - * Private method to get keys from the trie.  Builds the keys as it goes.
    - * @param {string} keySoFar The partial key (prefix) traversed so far.
    - * @param {!Array<string>} allKeys The partially built array of keys seen so
    - *     far.
    - * @private
    - */
    -goog.structs.Trie.prototype.getKeysInternal_ = function(keySoFar, allKeys) {
    -  if (this.value_ !== undefined) {
    -    allKeys.push(keySoFar);
    -  }
    -  for (var childNode in this.childNodes_) {
    -    this.childNodes_[childNode].getKeysInternal_(keySoFar + childNode, allKeys);
    -  }
    -};
    -
    -
    -/**
    - * Checks to see if a certain key is in the trie.  O(L), where L is the length
    - * of the key.
    - * @param {string} key A key that may be in the trie.
    - * @return {boolean} Whether the trie contains key.
    - */
    -goog.structs.Trie.prototype.containsKey = function(key) {
    -  return this.get(key) !== undefined;
    -};
    -
    -
    -/**
    - * Checks to see if a certain prefix is in the trie. O(L), where L is the length
    - * of the prefix.
    - * @param {string} prefix A prefix that may be in the trie.
    - * @return {boolean} Whether any key of the trie has the prefix.
    - */
    -goog.structs.Trie.prototype.containsPrefix = function(prefix) {
    -  // Empty string is any key's prefix.
    -  if (prefix.length == 0) {
    -    return !this.isEmpty();
    -  }
    -  return !!this.getChildNode_(prefix);
    -};
    -
    -
    -/**
    - * Checks to see if a certain value is in the trie.  Worst case is O(N) where
    - * N is the number of nodes in the trie.
    - * @param {VALUE} value A value that may be in the trie.
    - * @return {boolean} Whether the trie contains the value.
    - */
    -goog.structs.Trie.prototype.containsValue = function(value) {
    -  if (this.value_ === value) {
    -    return true;
    -  }
    -  for (var childNode in this.childNodes_) {
    -    if (this.childNodes_[childNode].containsValue(value)) {
    -      return true;
    -    }
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Completely empties a trie of all keys and values.  ~O(1)
    - */
    -goog.structs.Trie.prototype.clear = function() {
    -  this.childNodes_ = {};
    -  this.value_ = undefined;
    -};
    -
    -
    -/**
    - * Removes a key from the trie or throws an exception if the key is not in the
    - * trie.  O(L), where L is the length of the key.
    - * @param {string} key A key that should be removed from the trie.
    - * @return {VALUE} The value whose key was removed.
    - */
    -goog.structs.Trie.prototype.remove = function(key) {
    -  var node = this;
    -  var parents = [];
    -  for (var characterPosition = 0; characterPosition < key.length;
    -       characterPosition++) {
    -    var currentCharacter = key.charAt(characterPosition);
    -    if (!node.childNodes_[currentCharacter]) {
    -      throw Error('The collection does not have the key "' + key + '"');
    -    }
    -
    -    // Archive the current parent and child name (key in childNodes_) so that
    -    // we may remove the following node and its parents if they are empty.
    -    parents.push([node, currentCharacter]);
    -
    -    node = node.childNodes_[currentCharacter];
    -  }
    -  var oldValue = node.value_;
    -  delete node.value_;
    -
    -  while (parents.length > 0) {
    -    var currentParentAndCharacter = parents.pop();
    -    var currentParent = currentParentAndCharacter[0];
    -    var currentCharacter = currentParentAndCharacter[1];
    -    if (currentParent.childNodes_[currentCharacter].isEmpty()) {
    -      // If the child is empty, then remove it.
    -      delete currentParent.childNodes_[currentCharacter];
    -    } else {
    -      // No point of traversing back any further, since we can't remove this
    -      // path.
    -      break;
    -    }
    -  }
    -  return oldValue;
    -};
    -
    -
    -/**
    - * Clones a trie and returns a new trie.  O(N), where N is the number of nodes
    - * in the trie.
    - * @return {!goog.structs.Trie<VALUE>} A new goog.structs.Trie with the same
    - *     key value pairs.
    - */
    -goog.structs.Trie.prototype.clone = function() {
    -  return new goog.structs.Trie(this);
    -};
    -
    -
    -/**
    - * Returns the number of key value pairs in the trie.  O(N), where N is the
    - * number of nodes in the trie.
    - * TODO: This could be optimized by storing a weight (count below) in every
    - * node.
    - * @return {number} The number of pairs.
    - */
    -goog.structs.Trie.prototype.getCount = function() {
    -  return goog.structs.getCount(this.getValues());
    -};
    -
    -
    -/**
    - * Returns true if this trie contains no elements.  ~O(1).
    - * @return {boolean} True iff this trie contains no elements.
    - */
    -goog.structs.Trie.prototype.isEmpty = function() {
    -  return this.value_ === undefined && goog.object.isEmpty(this.childNodes_);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/trie_test.html b/src/database/third_party/closure-library/closure/goog/structs/trie_test.html
    deleted file mode 100644
    index 19219559036..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/trie_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.structs.Trie
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.structs.TrieTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/trie_test.js b/src/database/third_party/closure-library/closure/goog/structs/trie_test.js
    deleted file mode 100644
    index 57935cf35eb..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/trie_test.js
    +++ /dev/null
    @@ -1,454 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.structs.TrieTest');
    -goog.setTestOnly('goog.structs.TrieTest');
    -
    -goog.require('goog.object');
    -goog.require('goog.structs');
    -goog.require('goog.structs.Trie');
    -goog.require('goog.testing.jsunit');
    -
    -function makeTrie() {
    -  var trie = new goog.structs.Trie();
    -  trie.add('hello', 1);
    -  trie.add('hi', 'howdy');
    -  trie.add('', 'an empty string key');
    -  trie.add('empty value', '');
    -  trie.add('zero', 0);
    -  trie.add('object', {});
    -  trie.add('null', null);
    -  trie.add('hello, world', 2);
    -  trie.add('world', {});
    -  return trie;
    -}
    -
    -function checkTrie(trie) {
    -  assertEquals('get, should be 1', trie.get('hello'), 1);
    -  assertEquals('get, should be "howdy"', trie.get('hi'), 'howdy');
    -  assertEquals('get, should be "an empty string key"', trie.get(''),
    -      'an empty string key');
    -  assertEquals('get, should be ""', trie.get('empty value'), '');
    -  assertEquals('get, should be ""', typeof trie.get('empty value'), 'string');
    -  assertEquals('get, should be an object', typeof trie.get('object'), 'object');
    -  assertEquals('get, should be 0', trie.get('zero'), 0);
    -  assertEquals('get "null", should be null', trie.get('null'), null);
    -  assertEquals('get, should be 2', trie.get('hello, world'), 2);
    -  assertEquals('get, should be an object', typeof trie.get('world'), 'object');
    -}
    -
    -function testTrieFormation() {
    -  var t = makeTrie();
    -  checkTrie(t);
    -}
    -
    -function testFailureOfMultipleAdds() {
    -  var t = new goog.structs.Trie();
    -  t.add('hello', 'testing');
    -  assertThrows('Error should be thrown when same key added twice.', function() {
    -    t.add('hello', 'test');
    -  });
    -
    -  t = new goog.structs.Trie();
    -  t.add('null', null);
    -  assertThrows('Error should be thrown when same key added twice.', function() {
    -    t.add('null', 'hi!');
    -  });
    -
    -  t = new goog.structs.Trie();
    -  t.add('null', 'blah');
    -  assertThrows('Error should be thrown when same key added twice.', function() {
    -    t.add('null', null);
    -  });
    -}
    -
    -function testTrieClone() {
    -  var trieOne = makeTrie();
    -  var trieTwo = new goog.structs.Trie(trieOne);
    -  checkTrie(trieTwo);
    -}
    -
    -function testTrieFromObject() {
    -  var someObject = {'hello' : 1,
    -    'hi' : 'howdy',
    -    '' : 'an empty string key',
    -    'empty value' : '',
    -    'object' : {},
    -    'zero' : 0,
    -    'null' : null,
    -    'hello, world' : 2,
    -    'world' : {}};
    -  var trie = new goog.structs.Trie(someObject);
    -  checkTrie(trie);
    -}
    -
    -function testTrieGetValues() {
    -  var trie = makeTrie();
    -  var values = trie.getValues();
    -  assertTrue('getValues, should contain "howdy"',
    -      goog.object.contains(values, 'howdy'));
    -  assertTrue('getValues, should contain 1', goog.object.contains(values, 1));
    -  assertTrue('getValues, should contain 0', goog.object.contains(values, 0));
    -  assertTrue('getValues, should contain ""', goog.object.contains(values, ''));
    -  assertTrue('getValues, should contain null',
    -      goog.object.contains(values, null));
    -  assertEquals('goog.structs.getCount(getValues()) should be 9',
    -      goog.structs.getCount(values), 9);
    -}
    -
    -function testTrieGetKeys() {
    -  var trie = makeTrie();
    -  var keys = trie.getKeys();
    -  assertTrue('getKeys, should contain "hello"',
    -      goog.object.contains(keys, 'hello'));
    -  assertTrue('getKeys, should contain "empty value"',
    -      goog.object.contains(keys, 'empty value'));
    -  assertTrue('getKeys, should contain ""', goog.object.contains(keys, ''));
    -  assertTrue('getKeys, should contain "zero"',
    -      goog.object.contains(keys, 'zero'));
    -  assertEquals('goog.structs.getCount(getKeys()) should be 9',
    -      goog.structs.getCount(keys), 9);
    -}
    -
    -
    -function testTrieCount() {
    -  var trieOne = makeTrie();
    -  var trieTwo = new goog.structs.Trie();
    -  assertEquals('count, should be 9', trieOne.getCount(), 9);
    -  assertEquals('count, should be 0', trieTwo.getCount(), 0);
    -}
    -
    -function testRemoveKeyFromTrie() {
    -  var trie = new goog.structs.Trie();
    -  trie.add('key1', 'value1');
    -  trie.add('key2', 'value2');
    -  trie.add('ke', 'value3');
    -  trie.add('zero', 0);
    -  trie.remove('key2');
    -  assertEquals('get "key1", should be "value1"', trie.get('key1'), 'value1');
    -  assertUndefined('get "key2", should be undefined', trie.get('key2'));
    -  trie.remove('zero');
    -  assertUndefined('get "zero", should be undefined', trie.get('zero'));
    -  trie.remove('ke');
    -  assertUndefined('get "ke", should be undefined', trie.get('ke'));
    -  assertEquals('get "key1", should be "value1"', trie.get('key1'), 'value1');
    -  trie.add('a', 'value4');
    -  assertTrue('testing internal structure, a should be a child',
    -      'a' in trie.childNodes_);
    -  trie.remove('a');
    -  assertFalse('testing internal structure, a should no longer be a child',
    -      'a' in trie.childNodes_);
    -
    -  trie.add('xyza', 'value');
    -  trie.remove('xyza', 'value');
    -  assertFalse('Should not have "x"', 'x' in trie.childNodes_);
    -
    -  trie.add('xyza', null);
    -  assertTrue('Should have "x"', 'x' in trie.childNodes_);
    -  trie.remove('xyza');
    -  assertFalse('Should not have "x"', 'x' in trie.childNodes_);
    -
    -  trie.add('xyza', 'value');
    -  trie.add('xb', 'value');
    -  trie.remove('xyza');
    -  assertTrue('get "x" should be defined', 'x' in trie.childNodes_);
    -  assertFalse('get "y" should be undefined',
    -      'y' in trie.childNodes_['x'].childNodes_);
    -
    -  trie.add('akey', 'value1');
    -  trie.add('akey1', 'value2');
    -  trie.remove('akey1');
    -  assertEquals('get "akey", should be "value1"', 'value1', trie.get('akey'));
    -  assertUndefined('get "akey1", should be undefined', trie.get('akey1'));
    -}
    -
    -function testRemoveKeyFromTrieWithNulls() {
    -  var trie = new goog.structs.Trie();
    -  trie.add('key1', null);
    -  trie.add('key2', 'value2');
    -  trie.add('ke', 'value3');
    -  trie.add('zero', 0);
    -  trie.remove('key2');
    -  assertEquals('get "key1", should be null', trie.get('key1'), null);
    -  assertUndefined('get "key2", should be undefined', trie.get('key2'));
    -  trie.remove('zero');
    -  assertUndefined('get "zero", should be undefined', trie.get('zero'));
    -  trie.remove('ke');
    -  assertUndefined('get "ke", should be undefined', trie.get('ke'));
    -  assertEquals('get "key1", should be null', trie.get('key1'), null);
    -  trie.add('a', 'value4');
    -  assertTrue('testing internal structure, a should be a child',
    -      'a' in trie.childNodes_);
    -  trie.remove('a');
    -  assertFalse('testing internal structure, a should no longer be a child',
    -      'a' in trie.childNodes_);
    -
    -  trie.add('xyza', null);
    -  trie.add('xb', 'value');
    -  trie.remove('xyza');
    -  assertTrue('Should have "x"', 'x' in trie.childNodes_);
    -  assertFalse('Should not have "y"',
    -      'y' in trie.childNodes_['x'].childNodes_);
    -}
    -
    -function testRemoveKeyException() {
    -  var trie = new goog.structs.Trie();
    -  trie.add('abcdefg', 'value');
    -  trie.add('abcz', 'value');
    -  trie.add('abc', 'value');
    -
    -  assertThrows('Remove should throw an error on removal of non-existent key',
    -      function() {
    -        trie.remove('abcdefge');
    -      });
    -}
    -
    -function testTrieIsEmpty() {
    -  var trieOne = new goog.structs.Trie();
    -  var trieTwo = makeTrie();
    -  assertTrue('isEmpty, should be empty', trieOne.isEmpty());
    -  assertFalse('isEmpty, should not be empty', trieTwo.isEmpty());
    -  trieOne.add('', 1);
    -  assertFalse('isEmpty, should not be empty', trieTwo.isEmpty());
    -  trieOne.remove('');
    -  assertTrue('isEmpty, should be empty', trieOne.isEmpty());
    -  trieOne.add('', 1);
    -  trieOne.add('a', 1);
    -  trieOne.remove('a');
    -  assertFalse('isEmpty, should not be empty', trieOne.isEmpty());
    -  trieOne.remove('');
    -  assertTrue('isEmpty, should be empty', trieOne.isEmpty());
    -  trieOne.add('', 1);
    -  trieOne.add('a', 1);
    -  trieOne.remove('');
    -  assertFalse('isEmpty, should not be empty', trieOne.isEmpty());
    -  trieOne.remove('a');
    -  assertTrue('isEmpty, should be empty', trieOne.isEmpty());
    -}
    -
    -function testTrieClear() {
    -  var trie = new goog.structs.Trie();
    -  trie.add('key1', 'value1');
    -  trie.add('key2', 'value2');
    -  trie.add('key3', null);
    -  trie.clear();
    -  assertUndefined('get key1, should be undefined', trie.get('key1'));
    -  assertUndefined('get key2, should be undefined', trie.get('key2'));
    -  assertUndefined('get key3, should be undefined', trie.get('key3'));
    -}
    -
    -function testTrieContainsKey() {
    -  var trie = makeTrie();
    -  assertTrue('containsKey, should contain "hello"', trie.containsKey('hello'));
    -  assertTrue('containsKey, should contain "hi"', trie.containsKey('hi'));
    -  assertTrue('containsKey, should contain ""', trie.containsKey(''));
    -  assertTrue('containsKey, should contain "empty value"',
    -      trie.containsKey('empty value'));
    -  assertTrue('containsKey, should contain "object"',
    -      trie.containsKey('object'));
    -  assertTrue('containsKey, should contain "zero"', trie.containsKey('zero'));
    -  assertTrue('containsKey, should contain "null"', trie.containsKey('null'));
    -  assertFalse('containsKey, should not contain "blah"',
    -      trie.containsKey('blah'));
    -  trie.remove('');
    -  trie.remove('hi');
    -  trie.remove('zero');
    -  trie.remove('null');
    -  assertFalse('containsKey, should not contain "zero"',
    -      trie.containsKey('zero'));
    -  assertFalse('containsKey, should not contain ""', trie.containsKey(''));
    -  assertFalse('containsKey, should not contain "hi"', trie.containsKey('hi'));
    -  assertFalse('containsKey, should not contain "null"',
    -      trie.containsKey('null'));
    -}
    -
    -function testTrieContainsPrefix() {
    -
    -  // Empty trie.
    -  var trie = new goog.structs.Trie();
    -  assertFalse('containsPrefix, should not contain ""', trie.containsPrefix(''));
    -  assertFalse('containsPrefix, should not contain "any"',
    -      trie.containsPrefix('any'));
    -  trie.add('key', 'value');
    -  assertTrue('containsPrefix, should contain ""', trie.containsPrefix(''));
    -
    -  // Non-empty trie.
    -  trie = makeTrie();
    -  assertTrue('containsPrefix, should contain ""', trie.containsPrefix(''));
    -  assertFalse('containsPrefix, should not contain "blah"',
    -      trie.containsPrefix('blah'));
    -  assertTrue('containsPrefix, should contain "h"', trie.containsPrefix('h'));
    -  assertTrue('containsPrefix, should contain "hello"',
    -      trie.containsPrefix('hello'));
    -  assertTrue('containsPrefix, should contain "hello, world"',
    -      trie.containsPrefix('hello, world'));
    -  assertFalse('containsPrefix, should not contain "hello, world!"',
    -      trie.containsPrefix('hello, world!'));
    -  assertTrue('containsPrefix, should contain "nu"',
    -      trie.containsPrefix('nu'));
    -  assertTrue('containsPrefix, should contain "null"',
    -      trie.containsPrefix('null'));
    -  assertTrue('containsPrefix, should contain "empty value"',
    -      trie.containsPrefix('empty value'));
    -
    -  // Remove nodes.
    -  trie.remove('');
    -  assertTrue('containsPrefix, should contain ""', trie.containsPrefix(''));
    -  trie.remove('hi');
    -  assertTrue('containsPrefix, should contain "h"', trie.containsPrefix('h'));
    -  assertFalse('containsPrefix, should not contain "hi"',
    -      trie.containsPrefix('hi'));
    -  trie.remove('hello');
    -  trie.remove('hello, world');
    -  assertFalse('containsPrefix, should not contain "h"',
    -      trie.containsPrefix('h'));
    -  assertFalse('containsPrefix, should not contain "hello"',
    -      trie.containsPrefix('hello'));
    -
    -  // Remove all nodes.
    -  trie.remove('empty value');
    -  trie.remove('zero');
    -  trie.remove('object');
    -  trie.remove('null');
    -  trie.remove('world');
    -  assertFalse('containsPrefix, should not contain ""',
    -      trie.containsPrefix(''));
    -  assertFalse('containsPrefix, should not contain "h"',
    -      trie.containsPrefix('h'));
    -  assertFalse('containsPrefix, should not contain "hi"',
    -      trie.containsPrefix('hi'));
    -
    -  // Add some new nodes.
    -  trie.add('hi', 'value');
    -  trie.add('null', 'value');
    -  assertTrue('containsPrefix, should contain ""', trie.containsPrefix(''));
    -  assertTrue('containsPrefix, should contain "h"', trie.containsPrefix('h'));
    -  assertTrue('containsPrefix, should contain "hi"', trie.containsPrefix('hi'));
    -  assertFalse('containsPrefix, should not contain "hello"',
    -      trie.containsPrefix('hello'));
    -  assertFalse('containsPrefix, should not contain "zero"',
    -      trie.containsPrefix('zero'));
    -
    -  // Clear the trie.
    -  trie.clear();
    -  assertFalse('containsPrefix, should not contain ""',
    -      trie.containsPrefix(''));
    -  assertFalse('containsPrefix, should not contain "h"',
    -      trie.containsPrefix('h'));
    -  assertFalse('containsPrefix, should not contain "hi"',
    -      trie.containsPrefix('hi'));
    -}
    -
    -function testTrieContainsValue() {
    -  var trie = makeTrie();
    -  assertTrue('containsValue, should be true, should contain 1',
    -      trie.containsValue(1));
    -  assertTrue('containsValue, should be true, should contain "howdy"',
    -      trie.containsValue('howdy'));
    -  assertTrue('containsValue, should be true, should contain ""',
    -      trie.containsValue(''));
    -  assertTrue('containsValue, should be true, should contain 0',
    -      trie.containsValue(0));
    -  assertTrue('containsValue, should be true, should contain null',
    -      trie.containsValue(null));
    -  assertTrue('containsValue, should be true, should ' +
    -      'contain "an empty string key"',
    -      trie.containsValue('an empty string key'));
    -  assertFalse('containsValue, should be false, should not contain "blah"',
    -      trie.containsValue('blah'));
    -  trie.remove('empty value');
    -  trie.remove('zero');
    -  assertFalse('containsValue, should be false, should not contain 0',
    -      trie.containsValue(0));
    -  assertFalse('containsValue, should be false, should not contain ""',
    -      trie.containsValue(''));
    -}
    -
    -function testTrieHandlingOfEmptyStrings() {
    -  var trie = new goog.structs.Trie();
    -  assertEquals('get, should be undefined', trie.get(''), undefined);
    -  assertFalse('containsValue, should be false', trie.containsValue(''));
    -  assertFalse('containsKey, should be false', trie.containsKey(''));
    -  trie.add('', 'test');
    -  trie.add('test2', '');
    -  assertTrue('containsValue, should be true', trie.containsValue(''));
    -  assertTrue('containsKey, should be true', trie.containsKey(''));
    -  assertEquals('get, should be "test"', trie.get(''), 'test');
    -  assertEquals('get, should be ""', trie.get('test2'), '');
    -  trie.remove('');
    -  trie.remove('test2');
    -  assertEquals('get, should be undefined', trie.get(''), undefined);
    -  assertFalse('containsValue, should be false', trie.containsValue(''));
    -  assertFalse('containsKey, should be false', trie.containsKey(''));
    -}
    -
    -function testPrefixOptionOnGetKeys() {
    -  var trie = new goog.structs.Trie();
    -  trie.add('abcdefg', 'one');
    -  trie.add('abcdefghijk', 'two');
    -  trie.add('abcde', 'three');
    -  trie.add('abcq', null);
    -  trie.add('abc', 'four');
    -  trie.add('xyz', 'five');
    -  assertEquals('getKeys, should be 1', trie.getKeys('xy').length, 1);
    -  assertEquals('getKeys, should be 1', trie.getKeys('xyz').length, 1);
    -  assertEquals('getKeys, should be 1', trie.getKeys('x').length, 1);
    -  assertEquals('getKeys, should be 4', trie.getKeys('abc').length, 5);
    -  assertEquals('getKeys, should be 2', trie.getKeys('abcdef').length, 2);
    -  assertEquals('getKeys, should be 0', trie.getKeys('abcdefgi').length, 0);
    -}
    -
    -function testGetKeyAndPrefixes() {
    -  var trie = makeTrie();
    -  // Note: trie has one of its keys as ''
    -  assertEquals('getKeyAndPrefixes, should be 2',
    -               2,
    -               goog.object.getCount(trie.getKeyAndPrefixes('world')));
    -  assertEquals('getKeyAndPrefixes, should be 2',
    -               2,
    -               goog.object.getCount(trie.getKeyAndPrefixes('hello')));
    -  assertEquals('getKeyAndPrefixes, should be 2',
    -               2,
    -               goog.object.getCount(trie.getKeyAndPrefixes('hello,')));
    -  assertEquals('getKeyAndPrefixes, should be 3',
    -               3,
    -               goog.object.getCount(trie.getKeyAndPrefixes('hello, world')));
    -  assertEquals('getKeyAndPrefixes, should be 1',
    -               1,
    -               goog.object.getCount(trie.getKeyAndPrefixes('hell')));
    -}
    -
    -function testGetKeyAndPrefixesStartIndex() {
    -  var trie = new goog.structs.Trie();
    -  trie.add('abcdefg', 'one');
    -  trie.add('bcdefg', 'two');
    -  trie.add('abcdefghijk', 'three');
    -  trie.add('abcde', 'four');
    -  trie.add('abcq', null);
    -  trie.add('q', null);
    -  trie.add('abc', 'five');
    -  trie.add('xyz', 'six');
    -  assertEquals('getKeyAndPrefixes, should be 3',
    -               3,
    -               goog.object.getCount(trie.getKeyAndPrefixes('abcdefg', 0)));
    -  assertEquals('getKeyAndPrefixes, should be 1',
    -               1,
    -               goog.object.getCount(trie.getKeyAndPrefixes('abcdefg', 1)));
    -  assertEquals('getKeyAndPrefixes, should be 1',
    -               1,
    -               goog.object.getCount(trie.getKeyAndPrefixes('abcq', 3)));
    -  assertEquals('getKeyAndPrefixes, should be 0',
    -               0,
    -               goog.object.getCount(trie.getKeyAndPrefixes('abcd', 3)));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/weak/weak.js b/src/database/third_party/closure-library/closure/goog/structs/weak/weak.js
    deleted file mode 100644
    index bfc3292fceb..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/weak/weak.js
    +++ /dev/null
    @@ -1,159 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Common code for weak collections.
    - *
    - * The helpers in this file are used for the shim implementations of
    - * {@code goog.structs.weak.Map} and {@code goog.structs.weak.Set}, for browsers
    - * that do not support ECMAScript 6 native WeakMap and WeakSet.
    - *
    - * IMPORTANT CAVEAT: On browsers that do not provide native WeakMap and WeakSet
    - * implementations, these data structure are only partially weak, and CAN LEAK
    - * MEMORY. Specifically, if a key is no longer held, the key-value pair (in the
    - * case of Map) and some internal metadata (in the case of Set), can be garbage
    - * collected; however, if a key is still held when a Map or Set is no longer
    - * held, the value and metadata will not be collected.
    - *
    - * RECOMMENDATIONS: If the lifetime of the weak collection is expected to be
    - * shorter than that of its keys, the keys should be explicitly removed from the
    - * collection when they are disposed. If this is not possible, this library may
    - * be inappopriate for the application.
    - *
    - * BROWSER COMPATIBILITY: This library is compatible with browsers with a
    - * correct implementation of Object.defineProperty (IE9+, FF4+, SF5.1+, CH5+,
    - * OP12+, etc).
    - * @see goog.structs.weak.SUPPORTED_BROWSER
    - * @see http://kangax.github.io/compat-table/es5/#Object.defineProperty
    - *
    - * @package
    - */
    -
    -
    -goog.provide('goog.structs.weak');
    -
    -goog.require('goog.userAgent');
    -
    -
    -/**
    - * Whether this browser supports weak collections, using either the native or
    - * shim implementation.
    - * @const
    - */
    -// Only test for shim, since ES6 native WeakMap/Set imply ES5 shim dependencies
    -goog.structs.weak.SUPPORTED_BROWSER = Object.defineProperty &&
    -    // IE<9 and Safari<5.1 cannot defineProperty on some objects
    -    !(goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9')) &&
    -    !(goog.userAgent.SAFARI && !goog.userAgent.isVersionOrHigher('534.48.3'));
    -
    -
    -/**
    - * Whether to use the browser's native WeakMap.
    - * @const
    - */
    -goog.structs.weak.USE_NATIVE_WEAKMAP = 'WeakMap' in goog.global &&
    -    // Firefox<24 WeakMap disallows some objects as keys
    -    // See https://github.com/Polymer/WeakMap/issues/3
    -    !(goog.userAgent.GECKO && !goog.userAgent.isVersionOrHigher('24'));
    -
    -
    -/**
    - * Whether to use the browser's native WeakSet.
    - * @const
    - */
    -goog.structs.weak.USE_NATIVE_WEAKSET = 'WeakSet' in goog.global;
    -
    -
    -/** @const */
    -goog.structs.weak.WEAKREFS_PROPERTY_NAME = '__shimWeakrefs__';
    -
    -
    -/**
    - * Counter used to generate unique ID for shim.
    - * @private
    - */
    -goog.structs.weak.counter_ = 0;
    -
    -
    -/**
    - * Generate a unique ID for shim.
    - * @return {string}
    - */
    -goog.structs.weak.generateId = function() {
    -  return (Math.random() * 1e9 >>> 0) + '' +
    -      (goog.structs.weak.counter_++ % 1e9);
    -};
    -
    -
    -/**
    - * Checks that the key is an extensible object, otherwise throws an Error.
    - * @param {*} key The key.
    - */
    -goog.structs.weak.checkKeyType = function(key) {
    -  if (!goog.isObject(key)) {
    -    throw TypeError('Invalid value used in weak collection');
    -  }
    -  if (Object.isExtensible && !Object.isExtensible(key)) {
    -    throw TypeError('Unsupported non-extensible object used as weak map key');
    -  }
    -};
    -
    -
    -/**
    - * Adds a key-value pair to the collection with the given ID. Helper for shim
    - * implementations of Map#set and Set#add.
    - * @param {string} id The unique ID of the shim weak collection.
    - * @param {*} key The key.
    - * @param {*} value value to add.
    - */
    -goog.structs.weak.set = function(id, key, value) {
    -  goog.structs.weak.checkKeyType(key);
    -  if (!key.hasOwnProperty(goog.structs.weak.WEAKREFS_PROPERTY_NAME)) {
    -    // Use defineProperty to make property non-enumerable
    -    Object.defineProperty(/** @type {!Object} */(key),
    -        goog.structs.weak.WEAKREFS_PROPERTY_NAME, {value: {}});
    -  }
    -  key[goog.structs.weak.WEAKREFS_PROPERTY_NAME][id] = value;
    -};
    -
    -
    -/**
    - * Returns whether the collection with the given ID contains the given
    - * key. Helper for shim implementations of Map#containsKey and Set#contains.
    - * @param {string} id The unique ID of the shim weak collection.
    - * @param {*} key The key to check for.
    - * @return {boolean}
    - */
    -goog.structs.weak.has = function(id, key) {
    -  goog.structs.weak.checkKeyType(key);
    -  return key.hasOwnProperty(goog.structs.weak.WEAKREFS_PROPERTY_NAME) ?
    -      id in key[goog.structs.weak.WEAKREFS_PROPERTY_NAME] :
    -      false;
    -};
    -
    -
    -/**
    - * Removes a key-value pair based on the key. Helper for shim implementations of
    - * Map#remove and Set#remove.
    - * @param {string} id The unique ID of the shim weak collection.
    - * @param {*} key The key to remove.
    - * @return {boolean} Whether object was removed.
    - */
    -goog.structs.weak.remove = function(id, key) {
    -  if (goog.structs.weak.has(id, key)) {
    -    delete key[goog.structs.weak.WEAKREFS_PROPERTY_NAME][id];
    -    return true;
    -  }
    -  return false;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/structs/weak/weak_test.js b/src/database/third_party/closure-library/closure/goog/structs/weak/weak_test.js
    deleted file mode 100644
    index e799e94b168..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/structs/weak/weak_test.js
    +++ /dev/null
    @@ -1,75 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Tests for {@code goog.structs.weak}. set, has, and remove are
    - * exercised in {@code goog.structs.weak.MapTest} and
    - * {@code goog.structs.weak.SetTest}.
    - *
    - */
    -
    -
    -goog.provide('goog.structs.weakTest');
    -goog.setTestOnly('goog.structs.weakTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.structs.weak');
    -goog.require('goog.testing.jsunit');
    -
    -
    -function shouldRunTests() {
    -  return goog.structs.weak.SUPPORTED_BROWSER;
    -}
    -
    -
    -function testGenerateId() {
    -  assertNotEquals(goog.structs.weak.generateId(),
    -                  goog.structs.weak.generateId());
    -}
    -
    -
    -function testCheckKeyTypeValidObject() {
    -  var validKeys = [{}, [], document.body, /RegExp/, goog.nullFunction];
    -  goog.array.forEach(validKeys, function(key) {
    -    // no error
    -    goog.structs.weak.checkKeyType(key);
    -  });
    -}
    -
    -
    -function testCheckKeyTypePrimitive() {
    -  var primitiveKeys = ['test', 1, true, null, undefined];
    -  goog.array.forEach(primitiveKeys, function(key) {
    -    assertThrows(function() {
    -      goog.structs.weak.checkKeyType(key);
    -    });
    -  });
    -}
    -
    -
    -function testCheckKeyTypeNonExtensibleObject() {
    -  var sealedObj = {}, frozenObj = {}, preventExtensionsObj = {};
    -  Object.seal(sealedObj);
    -  Object.freeze(frozenObj);
    -  Object.preventExtensions(preventExtensionsObj);
    -  assertThrows(function() {
    -    goog.structs.weak.checkKeyType(sealedObj);
    -  });
    -  assertThrows(function() {
    -    goog.structs.weak.checkKeyType(frozenObj);
    -  });
    -  assertThrows(function() {
    -    goog.structs.weak.checkKeyType(preventExtensionsObj);
    -  });
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/style/bidi.js b/src/database/third_party/closure-library/closure/goog/style/bidi.js
    deleted file mode 100644
    index 2d5c7c586d1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/style/bidi.js
    +++ /dev/null
    @@ -1,184 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Bidi utility functions.
    - *
    - */
    -
    -goog.provide('goog.style.bidi');
    -
    -goog.require('goog.dom');
    -goog.require('goog.style');
    -goog.require('goog.userAgent');
    -
    -
    -/**
    - * Returns the normalized scrollLeft position for a scrolled element.
    - * @param {Element} element The scrolled element.
    - * @return {number} The number of pixels the element is scrolled. 0 indicates
    - *     that the element is not scrolled at all (which, in general, is the
    - *     left-most position in ltr and the right-most position in rtl).
    - */
    -goog.style.bidi.getScrollLeft = function(element) {
    -  var isRtl = goog.style.isRightToLeft(element);
    -  if (isRtl && goog.userAgent.GECKO) {
    -    // ScrollLeft starts at 0 and then goes negative as the element is scrolled
    -    // towards the left.
    -    return -element.scrollLeft;
    -  } else if (isRtl &&
    -             !(goog.userAgent.IE && goog.userAgent.isVersionOrHigher('8'))) {
    -    // ScrollLeft starts at the maximum positive value and decreases towards
    -    // 0 as the element is scrolled towards the left. However, for overflow
    -    // visible, there is no scrollLeft and the value always stays correctly at 0
    -    var overflowX = goog.style.getComputedOverflowX(element);
    -    if (overflowX == 'visible') {
    -      return element.scrollLeft;
    -    } else {
    -      return element.scrollWidth - element.clientWidth - element.scrollLeft;
    -    }
    -  }
    -  // ScrollLeft behavior is identical in rtl and ltr, it starts at 0 and
    -  // increases as the element is scrolled away from the start.
    -  return element.scrollLeft;
    -};
    -
    -
    -/**
    - * Returns the "offsetStart" of an element, analagous to offsetLeft but
    - * normalized for right-to-left environments and various browser
    - * inconsistencies. This value returned can always be passed to setScrollOffset
    - * to scroll to an element's left edge in a left-to-right offsetParent or
    - * right edge in a right-to-left offsetParent.
    - *
    - * For example, here offsetStart is 10px in an LTR environment and 5px in RTL:
    - *
    - * <pre>
    - * |          xxxxxxxxxx     |
    - *  ^^^^^^^^^^   ^^^^   ^^^^^
    - *     10px      elem    5px
    - * </pre>
    - *
    - * If an element is positioned before the start of its offsetParent, the
    - * startOffset may be negative.  This can be used with setScrollOffset to
    - * reliably scroll to an element:
    - *
    - * <pre>
    - * var scrollOffset = goog.style.bidi.getOffsetStart(element);
    - * goog.style.bidi.setScrollOffset(element.offsetParent, scrollOffset);
    - * </pre>
    - *
    - * @see setScrollOffset
    - *
    - * @param {Element} element The element for which we need to determine the
    - *     offsetStart position.
    - * @return {number} The offsetStart for that element.
    - */
    -goog.style.bidi.getOffsetStart = function(element) {
    -  var offsetLeftForReal = element.offsetLeft;
    -
    -  // The element might not have an offsetParent.
    -  // For example, the node might not be attached to the DOM tree,
    -  // and position:fixed children do not have an offset parent.
    -  // Just try to do the best we can with what we have.
    -  var bestParent = element.offsetParent;
    -
    -  if (!bestParent && goog.style.getComputedPosition(element) == 'fixed') {
    -    bestParent = goog.dom.getOwnerDocument(element).documentElement;
    -  }
    -
    -  // Just give up in this case.
    -  if (!bestParent) {
    -    return offsetLeftForReal;
    -  }
    -
    -  if (goog.userAgent.GECKO) {
    -    // When calculating an element's offsetLeft, Firefox erroneously subtracts
    -    // the border width from the actual distance.  So we need to add it back.
    -    var borderWidths = goog.style.getBorderBox(bestParent);
    -    offsetLeftForReal += borderWidths.left;
    -  } else if (goog.userAgent.isDocumentModeOrHigher(8) &&
    -             !goog.userAgent.isDocumentModeOrHigher(9)) {
    -    // When calculating an element's offsetLeft, IE8/9-Standards Mode
    -    // erroneously adds the border width to the actual distance.  So we need to
    -    // subtract it.
    -    var borderWidths = goog.style.getBorderBox(bestParent);
    -    offsetLeftForReal -= borderWidths.left;
    -  }
    -
    -  if (goog.style.isRightToLeft(bestParent)) {
    -    // Right edge of the element relative to the left edge of its parent.
    -    var elementRightOffset = offsetLeftForReal + element.offsetWidth;
    -
    -    // Distance from the parent's right edge to the element's right edge.
    -    return bestParent.clientWidth - elementRightOffset;
    -  }
    -
    -  return offsetLeftForReal;
    -};
    -
    -
    -/**
    - * Sets the element's scrollLeft attribute so it is correctly scrolled by
    - * offsetStart pixels.  This takes into account whether the element is RTL and
    - * the nuances of different browsers.  To scroll to the "beginning" of an
    - * element use getOffsetStart to obtain the element's offsetStart value and then
    - * pass the value to setScrollOffset.
    - * @see getOffsetStart
    - * @param {Element} element The element to set scrollLeft on.
    - * @param {number} offsetStart The number of pixels to scroll the element.
    - *     If this value is < 0, 0 is used.
    - */
    -goog.style.bidi.setScrollOffset = function(element, offsetStart) {
    -  offsetStart = Math.max(offsetStart, 0);
    -  // In LTR and in "mirrored" browser RTL (such as IE), we set scrollLeft to
    -  // the number of pixels to scroll.
    -  // Otherwise, in RTL, we need to account for different browser behavior.
    -  if (!goog.style.isRightToLeft(element)) {
    -    element.scrollLeft = offsetStart;
    -  } else if (goog.userAgent.GECKO) {
    -    // Negative scroll-left positions in RTL.
    -    element.scrollLeft = -offsetStart;
    -  } else if (!(goog.userAgent.IE && goog.userAgent.isVersionOrHigher('8'))) {
    -    // Take the current scrollLeft value and move to the right by the
    -    // offsetStart to get to the left edge of the element, and then by
    -    // the clientWidth of the element to get to the right edge.
    -    element.scrollLeft =
    -        element.scrollWidth - offsetStart - element.clientWidth;
    -  } else {
    -    element.scrollLeft = offsetStart;
    -  }
    -};
    -
    -
    -/**
    - * Sets the element's left style attribute in LTR or right style attribute in
    - * RTL.  Also clears the left attribute in RTL and the right attribute in LTR.
    - * @param {Element} elem The element to position.
    - * @param {number} left The left position in LTR; will be set as right in RTL.
    - * @param {?number} top The top position.  If null only the left/right is set.
    - * @param {boolean} isRtl Whether we are in RTL mode.
    - */
    -goog.style.bidi.setPosition = function(elem, left, top, isRtl) {
    -  if (!goog.isNull(top)) {
    -    elem.style.top = top + 'px';
    -  }
    -  if (isRtl) {
    -    elem.style.right = left + 'px';
    -    elem.style.left = '';
    -  } else {
    -    elem.style.left = left + 'px';
    -    elem.style.right = '';
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/style/bidi_test.html b/src/database/third_party/closure-library/closure/goog/style/bidi_test.html
    deleted file mode 100644
    index 05c0e26b641..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/style/bidi_test.html
    +++ /dev/null
    @@ -1,139 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.style.bidi
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.style.bidiTest');
    -  </script>
    -  <style>
    -   /* Using borders, padding, and margins of various prime values. */
    -    .scrollDiv {
    -      left:50px; width:250px; height: 100px;
    -      position:absolute; overflow:auto; border-left: 3px solid green;
    -      border-right: 17px solid green; margin: 7px; padding: 13px;
    -    }
    -  </style>
    - </head>
    - <body>
    -  <span id="bodyChild" style="position:fixed;left:60px">
    -   bodyChild
    -  </span>
    -  <div>
    -   <span>
    -    LTR
    -   </span>
    -   <div dir="ltr" onscroll="updateInfo()" id="scrollDivLtr" class="scrollDiv">
    -    <div style="width: 1000px; height: 2000px;background-color: blue">
    -    </div>
    -    <div id="scrolledElementLtr" style="background:yellow; top: 25px; left:85px;
    -             width: 100px; position:absolute">
    -     elm
    -    </div>
    -   </div>
    -   <div style="left:400px; position:absolute;">
    -    <div>
    -     elm.offsetParent.scrollLeft:
    -     <span id="elementScrollLeftLtr">
    -     </span>
    -    </div>
    -    <div>
    -     bidi.getScrollLeft(...):
    -     <span id="bidiScrollLeftLtr">
    -     </span>
    -    </div>
    -    <div>
    -     bidi.getOffsetStart(...):
    -     <span id="bidiOffsetStartLtr">
    -     </span>
    -    </div>
    -    <form name="formLtr" action="bidi_test.html#">
    -     goog.style.bidi.setScrollOffset:
    -     <input name="pixelsLtr" type="text" />
    -     <a href="bidi_test.html#" onclick="goog.style.bidi.setScrollOffset(
    -          document.getElementById('scrollDivLtr'),
    -          parseInt(formLtr.elements['pixelsLtr'].value));">
    -      set
    -     </a>
    -    </form>
    -   </div>
    -   <br />
    -   <br />
    -   <br />
    -   <br />
    -   <br />
    -   <br />
    -   <br />
    -   <br />
    -  </div>
    -  <hr />
    -  <div>
    -   <span>
    -    RTL
    -   </span>
    -   <div dir="rtl" onscroll="updateInfo();" id="scrollDivRtl" class="scrollDiv">
    -    <div style="width:1000px; height:70px;background-color:blue">
    -    </div>
    -    <div id="scrolledElementRtl" style="background:yellow; top: 25px; right:85px;
    -             width: 100px; position:absolute">
    -     elm
    -    </div>
    -   </div>
    -   <div style="left:400px; position:absolute;">
    -    <div>
    -     elm.offsetParent.scrollLeft:
    -     <span id="elementScrollLeftRtl">
    -     </span>
    -    </div>
    -    <div>
    -     bidi.getScrollLeft(...):
    -     <span id="bidiScrollLeftRtl">
    -     </span>
    -    </div>
    -    <div>
    -     bidi.getOffsetStart(...):
    -     <span id="bidiOffsetStartRtl">
    -     </span>
    -    </div>
    -    <form name="formRtl" action="bidi_test.html#">
    -     goog.style.setScrollOffset:
    -     <input name="pixelsRtl" type="text" />
    -     <a href="bidi_test.html#" onclick="goog.style.bidi.setScrollOffset(
    -          document.getElementById('scrollDivRtl'),
    -          parseInt(formRtl.elements['pixelsRtl'].value));">
    -      set
    -     </a>
    -    </form>
    -   </div>
    -   <br />
    -   <br />
    -   <br />
    -   <br />
    -   <br />
    -   <br />
    -   <br />
    -   <br />
    -  </div>
    -  <div dir="rtl" id="scrollLeftRtl" style="position: relative; width: 100px; height: 100px;
    -      background-color: blue">
    -   <div style="position:absolute; width: 200px; height: 20px; background-color:
    -    green">
    -    INNER
    -   </div>
    -  </div>
    -  <hr />
    -  <br />
    -  <br />
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/style/bidi_test.js b/src/database/third_party/closure-library/closure/goog/style/bidi_test.js
    deleted file mode 100644
    index dd75fe8013f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/style/bidi_test.js
    +++ /dev/null
    @@ -1,135 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.style.bidiTest');
    -goog.setTestOnly('goog.style.bidiTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.style');
    -goog.require('goog.style.bidi');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -// Updates the calculated metrics.
    -function updateInfo() {
    -  var element = document.getElementById('scrolledElementRtl');
    -  document.getElementById('elementScrollLeftRtl').innerHTML =
    -      element.offsetParent.scrollLeft;
    -  document.getElementById('bidiOffsetStartRtl').innerHTML =
    -      goog.style.bidi.getOffsetStart(element);
    -  document.getElementById('bidiScrollLeftRtl').innerHTML =
    -      goog.style.bidi.getScrollLeft(element.offsetParent);
    -
    -  element = document.getElementById('scrolledElementLtr');
    -  document.getElementById('elementScrollLeftLtr').innerHTML =
    -      element.offsetParent.scrollLeft;
    -  document.getElementById('bidiOffsetStartLtr').innerHTML =
    -      goog.style.bidi.getOffsetStart(element);
    -  document.getElementById('bidiScrollLeftLtr').innerHTML =
    -      goog.style.bidi.getScrollLeft(element.offsetParent);
    -}
    -
    -function setUpPage() {
    -  updateInfo();
    -}
    -
    -function tearDown() {
    -  document.documentElement.dir = 'ltr';
    -  document.body.dir = 'ltr';
    -}
    -
    -function testGetOffsetStart() {
    -  var elm = document.getElementById('scrolledElementRtl');
    -  assertEquals(elm.style['right'], goog.style.bidi.getOffsetStart(elm) + 'px');
    -  elm = document.getElementById('scrolledElementLtr');
    -  assertEquals(elm.style['left'], goog.style.bidi.getOffsetStart(elm) + 'px');
    -}
    -
    -function testSetScrollOffsetRtl() {
    -  var scrollElm = document.getElementById('scrollDivRtl');
    -  var scrolledElm = document.getElementById('scrolledElementRtl');
    -  var originalDistance =
    -      goog.style.getRelativePosition(scrolledElm, document.body).x;
    -  var scrollAndAssert = function(pixels) {
    -    goog.style.bidi.setScrollOffset(scrollElm, pixels);
    -    assertEquals(originalDistance + pixels,
    -        goog.style.getRelativePosition(scrolledElm, document.body).x);
    -  };
    -  scrollAndAssert(0);
    -  scrollAndAssert(50);
    -  scrollAndAssert(100);
    -  scrollAndAssert(150);
    -  scrollAndAssert(155);
    -  scrollAndAssert(0);
    -}
    -
    -function testSetScrollOffsetLtr() {
    -  var scrollElm = document.getElementById('scrollDivLtr');
    -  var scrolledElm = document.getElementById('scrolledElementLtr');
    -  var originalDistance =
    -      goog.style.getRelativePosition(scrolledElm, document.body).x;
    -  var scrollAndAssert = function(pixels) {
    -    goog.style.bidi.setScrollOffset(scrollElm, pixels);
    -    assertEquals(originalDistance - pixels,
    -        goog.style.getRelativePosition(scrolledElm, document.body).x);
    -  };
    -  scrollAndAssert(0);
    -  scrollAndAssert(50);
    -  scrollAndAssert(100);
    -  scrollAndAssert(150);
    -  scrollAndAssert(155);
    -  scrollAndAssert(0);
    -}
    -
    -function testFixedBodyChildLtr() {
    -  var bodyChild = document.getElementById('bodyChild');
    -  assertEquals(goog.userAgent.GECKO ? document.body : null,
    -      bodyChild.offsetParent);
    -  assertEquals(60, goog.style.bidi.getOffsetStart(bodyChild));
    -}
    -
    -function testFixedBodyChildRtl() {
    -  document.documentElement.dir = 'rtl';
    -  document.body.dir = 'rtl';
    -
    -  var bodyChild = document.getElementById('bodyChild');
    -  assertEquals(goog.userAgent.GECKO ? document.body : null,
    -      bodyChild.offsetParent);
    -
    -  var expectedOffsetStart =
    -      goog.dom.getViewportSize().width - 60 - bodyChild.offsetWidth;
    -
    -  // Gecko seems to also add in the marginbox for the body.
    -  // It's not really clear to me if this is true in the general case,
    -  // or just under certain conditions.
    -  if (goog.userAgent.GECKO) {
    -    var marginBox = goog.style.getMarginBox(document.body);
    -    expectedOffsetStart -= (marginBox.left + marginBox.right);
    -  }
    -
    -  assertEquals(expectedOffsetStart,
    -      goog.style.bidi.getOffsetStart(bodyChild));
    -}
    -
    -function testGetScrollLeftRTL() {
    -  var scrollLeftDiv = document.getElementById('scrollLeftRtl');
    -  scrollLeftDiv.style.overflow = 'visible';
    -  assertEquals(0, goog.style.bidi.getScrollLeft(scrollLeftDiv));
    -  scrollLeftDiv.style.overflow = 'hidden';
    -  assertEquals(0, goog.style.bidi.getScrollLeft(scrollLeftDiv));
    -  scrollLeftDiv.style.overflow = 'scroll';
    -  assertEquals(0, goog.style.bidi.getScrollLeft(scrollLeftDiv));
    -  scrollLeftDiv.style.overflow = 'auto';
    -  assertEquals(0, goog.style.bidi.getScrollLeft(scrollLeftDiv));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/style/cursor.js b/src/database/third_party/closure-library/closure/goog/style/cursor.js
    deleted file mode 100644
    index 7c54ef2d443..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/style/cursor.js
    +++ /dev/null
    @@ -1,116 +0,0 @@
    -// Copyright 2005 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Functions to create special cursor styles, like "draggable"
    - * (open hand) or "dragging" (closed hand).
    - *
    - * @author dgajda@google.com (Damian Gajda) Ported to closure.
    - */
    -
    -goog.provide('goog.style.cursor');
    -
    -goog.require('goog.userAgent');
    -
    -
    -/**
    - * The file name for the open-hand (draggable) cursor.
    - * @type {string}
    - */
    -goog.style.cursor.OPENHAND_FILE = 'openhand.cur';
    -
    -
    -/**
    - * The file name for the close-hand (dragging) cursor.
    - * @type {string}
    - */
    -goog.style.cursor.CLOSEDHAND_FILE = 'closedhand.cur';
    -
    -
    -/**
    - * Create the style for the draggable cursor based on browser and OS.
    - * The value can be extended to be '!important' if needed.
    - *
    - * @param {string} absoluteDotCurFilePath The absolute base path of
    - *     'openhand.cur' file to be used if the browser supports it.
    - * @param {boolean=} opt_obsolete Just for compiler backward compatibility.
    - * @return {string} The "draggable" mouse cursor style value.
    - */
    -goog.style.cursor.getDraggableCursorStyle = function(
    -    absoluteDotCurFilePath, opt_obsolete) {
    -  return goog.style.cursor.getCursorStyle_(
    -      '-moz-grab',
    -      absoluteDotCurFilePath + goog.style.cursor.OPENHAND_FILE,
    -      'default');
    -};
    -
    -
    -/**
    - * Create the style for the dragging cursor based on browser and OS.
    - * The value can be extended to be '!important' if needed.
    - *
    - * @param {string} absoluteDotCurFilePath The absolute base path of
    - *     'closedhand.cur' file to be used if the browser supports it.
    - * @param {boolean=} opt_obsolete Just for compiler backward compatibility.
    - * @return {string} The "dragging" mouse cursor style value.
    - */
    -goog.style.cursor.getDraggingCursorStyle = function(
    -    absoluteDotCurFilePath, opt_obsolete) {
    -  return goog.style.cursor.getCursorStyle_(
    -      '-moz-grabbing',
    -      absoluteDotCurFilePath + goog.style.cursor.CLOSEDHAND_FILE,
    -      'move');
    -};
    -
    -
    -/**
    - * Create the style for the cursor based on browser and OS.
    - *
    - * @param {string} geckoNonWinBuiltInStyleValue The Gecko on non-Windows OS,
    - *     built in cursor style.
    - * @param {string} absoluteDotCurFilePath The .cur file absolute file to be
    - *     used if the browser supports it.
    - * @param {string} defaultStyle The default fallback cursor style.
    - * @return {string} The computed mouse cursor style value.
    - * @private
    - */
    -goog.style.cursor.getCursorStyle_ = function(geckoNonWinBuiltInStyleValue,
    -    absoluteDotCurFilePath, defaultStyle) {
    -  // Use built in cursors for Gecko on non Windows OS.
    -  // We prefer our custom cursor, but Firefox Mac and Firefox Linux
    -  // cannot do custom cursors. They do have a built-in hand, so use it:
    -  if (goog.userAgent.GECKO && !goog.userAgent.WINDOWS) {
    -    return geckoNonWinBuiltInStyleValue;
    -  }
    -
    -  // Use the custom cursor file.
    -  var cursorStyleValue = 'url("' + absoluteDotCurFilePath + '")';
    -  // Change hot-spot for Safari.
    -  if (goog.userAgent.WEBKIT) {
    -    // Safari seems to ignore the hotspot specified in the .cur file (it uses
    -    // 0,0 instead).  This causes the cursor to jump as it transitions between
    -    // openhand and pointer which is especially annoying when trying to hover
    -    // over the route for draggable routes.  We specify the hotspot here as 7,5
    -    // in the css - unfortunately ie6 can't understand this and falls back to
    -    // the builtin cursors so we just do this for safari (but ie DOES correctly
    -    // use the hotspot specified in the file so this is ok).  The appropriate
    -    // coordinates were determined by looking at a hex dump and the format
    -    // description from wikipedia.
    -    cursorStyleValue += ' 7 5';
    -  }
    -  // Add default cursor fallback.
    -  cursorStyleValue += ', ' + defaultStyle;
    -  return cursorStyleValue;
    -};
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/style/cursor_test.html b/src/database/third_party/closure-library/closure/goog/style/cursor_test.html
    deleted file mode 100644
    index 6c65a8518a5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/style/cursor_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -  Author: dgajda@google.com (Damian Gajda)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.style.cursor
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.style.cursorTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/style/cursor_test.js b/src/database/third_party/closure-library/closure/goog/style/cursor_test.js
    deleted file mode 100644
    index dc0a7e476e5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/style/cursor_test.js
    +++ /dev/null
    @@ -1,125 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.style.cursorTest');
    -goog.setTestOnly('goog.style.cursorTest');
    -
    -goog.require('goog.style.cursor');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -var baseCursorUrl = '/images/2/';
    -var origWindowsUserAgentValue;
    -var origGeckoUserAgentValue;
    -var origWebkitUserAgentValue;
    -
    -
    -function setUp() {
    -  origWindowsUserAgentValue = goog.userAgent.WINDOWS;
    -  origGeckoUserAgentValue = goog.userAgent.GECKO;
    -  origWebkitUserAgentValue = goog.userAgent.WEBKIT;
    -}
    -
    -
    -function tearDown() {
    -  goog.userAgent.WINDOWS = origWindowsUserAgentValue;
    -  goog.userAgent.GECKO = origGeckoUserAgentValue;
    -  goog.userAgent.WEBKIT = origWebkitUserAgentValue;
    -}
    -
    -
    -function testGetCursorStylesWebkit() {
    -  goog.userAgent.GECKO = false;
    -  goog.userAgent.WEBKIT = true;
    -
    -  assertEquals('Webkit should get a cursor style with moved hot-spot.',
    -      'url("/images/2/openhand.cur") 7 5, default',
    -      goog.style.cursor.getDraggableCursorStyle(baseCursorUrl));
    -  assertEquals('Webkit should get a cursor style with moved hot-spot.',
    -      'url("/images/2/openhand.cur") 7 5, default',
    -      goog.style.cursor.getDraggableCursorStyle(baseCursorUrl, true));
    -
    -  assertEquals('Webkit should get a cursor style with moved hot-spot.',
    -      'url("/images/2/closedhand.cur") 7 5, move',
    -      goog.style.cursor.getDraggingCursorStyle(baseCursorUrl));
    -  assertEquals('Webkit should get a cursor style with moved hot-spot.',
    -      'url("/images/2/closedhand.cur") 7 5, move',
    -      goog.style.cursor.getDraggingCursorStyle(baseCursorUrl, true));
    -}
    -
    -
    -function testGetCursorStylesFireFoxNonWin() {
    -  goog.userAgent.GECKO = true;
    -  goog.userAgent.WEBKIT = false;
    -  goog.userAgent.WINDOWS = false;
    -
    -  assertEquals('FireFox on non Windows should get a custom cursor style.',
    -      '-moz-grab',
    -      goog.style.cursor.getDraggableCursorStyle(baseCursorUrl));
    -  assertEquals('FireFox on non Windows should get a custom cursor style and ' +
    -      'no !important modifier.',
    -      '-moz-grab',
    -      goog.style.cursor.getDraggableCursorStyle(baseCursorUrl, true));
    -
    -  assertEquals('FireFox on non Windows should get a custom cursor style.',
    -      '-moz-grabbing',
    -      goog.style.cursor.getDraggingCursorStyle(baseCursorUrl));
    -  assertEquals('FireFox on non Windows should get a custom cursor style and ' +
    -          'no !important modifier.',
    -      '-moz-grabbing',
    -      goog.style.cursor.getDraggingCursorStyle(baseCursorUrl, true));
    -}
    -
    -
    -function testGetCursorStylesFireFoxWin() {
    -  goog.userAgent.GECKO = true;
    -  goog.userAgent.WEBKIT = false;
    -  goog.userAgent.WINDOWS = true;
    -
    -  assertEquals('FireFox should get a cursor style with URL.',
    -      'url("/images/2/openhand.cur"), default',
    -      goog.style.cursor.getDraggableCursorStyle(baseCursorUrl));
    -  assertEquals('FireFox should get a cursor style with URL and no !important' +
    -          ' modifier.',
    -      'url("/images/2/openhand.cur"), default',
    -      goog.style.cursor.getDraggableCursorStyle(baseCursorUrl, true));
    -
    -  assertEquals('FireFox should get a cursor style with URL.',
    -      'url("/images/2/closedhand.cur"), move',
    -      goog.style.cursor.getDraggingCursorStyle(baseCursorUrl));
    -  assertEquals('FireFox should get a cursor style with URL and no !important' +
    -          ' modifier.',
    -      'url("/images/2/closedhand.cur"), move',
    -      goog.style.cursor.getDraggingCursorStyle(baseCursorUrl, true));
    -}
    -
    -
    -function testGetCursorStylesOther() {
    -  goog.userAgent.GECKO = false;
    -  goog.userAgent.WEBKIT = false;
    -
    -  assertEquals('Other browsers (IE) should get a cursor style with URL.',
    -      'url("/images/2/openhand.cur"), default',
    -      goog.style.cursor.getDraggableCursorStyle(baseCursorUrl));
    -  assertEquals('Other browsers (IE) should get a cursor style with URL.',
    -      'url("/images/2/openhand.cur"), default',
    -      goog.style.cursor.getDraggableCursorStyle(baseCursorUrl, true));
    -
    -  assertEquals('Other browsers (IE) should get a cursor style with URL.',
    -      'url("/images/2/closedhand.cur"), move',
    -      goog.style.cursor.getDraggingCursorStyle(baseCursorUrl));
    -  assertEquals('Other browsers (IE) should get a cursor style with URL.',
    -      'url("/images/2/closedhand.cur"), move',
    -      goog.style.cursor.getDraggingCursorStyle(baseCursorUrl, true));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/style/style.js b/src/database/third_party/closure-library/closure/goog/style/style.js
    deleted file mode 100644
    index 1058345be48..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/style/style.js
    +++ /dev/null
    @@ -1,2031 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Utilities for element styles.
    - *
    - * @author arv@google.com (Erik Arvidsson)
    - * @author eae@google.com (Emil A Eklund)
    - * @see ../demos/inline_block_quirks.html
    - * @see ../demos/inline_block_standards.html
    - * @see ../demos/style_viewport.html
    - */
    -
    -goog.provide('goog.style');
    -
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.NodeType');
    -goog.require('goog.dom.vendor');
    -goog.require('goog.math.Box');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.math.Rect');
    -goog.require('goog.math.Size');
    -goog.require('goog.object');
    -goog.require('goog.string');
    -goog.require('goog.userAgent');
    -
    -
    -/**
    - * Sets a style value on an element.
    - *
    - * This function is not indended to patch issues in the browser's style
    - * handling, but to allow easy programmatic access to setting dash-separated
    - * style properties.  An example is setting a batch of properties from a data
    - * object without overwriting old styles.  When possible, use native APIs:
    - * elem.style.propertyKey = 'value' or (if obliterating old styles is fine)
    - * elem.style.cssText = 'property1: value1; property2: value2'.
    - *
    - * @param {Element} element The element to change.
    - * @param {string|Object} style If a string, a style name. If an object, a hash
    - *     of style names to style values.
    - * @param {string|number|boolean=} opt_value If style was a string, then this
    - *     should be the value.
    - */
    -goog.style.setStyle = function(element, style, opt_value) {
    -  if (goog.isString(style)) {
    -    goog.style.setStyle_(element, opt_value, style);
    -  } else {
    -    for (var key in style) {
    -      goog.style.setStyle_(element, style[key], key);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Sets a style value on an element, with parameters swapped to work with
    - * {@code goog.object.forEach()}. Prepends a vendor-specific prefix when
    - * necessary.
    - * @param {Element} element The element to change.
    - * @param {string|number|boolean|undefined} value Style value.
    - * @param {string} style Style name.
    - * @private
    - */
    -goog.style.setStyle_ = function(element, value, style) {
    -  var propertyName = goog.style.getVendorJsStyleName_(element, style);
    -
    -  if (propertyName) {
    -    element.style[propertyName] = value;
    -  }
    -};
    -
    -
    -/**
    - * Style name cache that stores previous property name lookups.
    - *
    - * This is used by setStyle to speed up property lookups, entries look like:
    - *   { StyleName: ActualPropertyName }
    - *
    - * @private {!Object<string, string>}
    - */
    -goog.style.styleNameCache_ = {};
    -
    -
    -/**
    - * Returns the style property name in camel-case. If it does not exist and a
    - * vendor-specific version of the property does exist, then return the vendor-
    - * specific property name instead.
    - * @param {Element} element The element to change.
    - * @param {string} style Style name.
    - * @return {string} Vendor-specific style.
    - * @private
    - */
    -goog.style.getVendorJsStyleName_ = function(element, style) {
    -  var propertyName = goog.style.styleNameCache_[style];
    -  if (!propertyName) {
    -    var camelStyle = goog.string.toCamelCase(style);
    -    propertyName = camelStyle;
    -
    -    if (element.style[camelStyle] === undefined) {
    -      var prefixedStyle = goog.dom.vendor.getVendorJsPrefix() +
    -          goog.string.toTitleCase(camelStyle);
    -
    -      if (element.style[prefixedStyle] !== undefined) {
    -        propertyName = prefixedStyle;
    -      }
    -    }
    -    goog.style.styleNameCache_[style] = propertyName;
    -  }
    -
    -  return propertyName;
    -};
    -
    -
    -/**
    - * Returns the style property name in CSS notation. If it does not exist and a
    - * vendor-specific version of the property does exist, then return the vendor-
    - * specific property name instead.
    - * @param {Element} element The element to change.
    - * @param {string} style Style name.
    - * @return {string} Vendor-specific style.
    - * @private
    - */
    -goog.style.getVendorStyleName_ = function(element, style) {
    -  var camelStyle = goog.string.toCamelCase(style);
    -
    -  if (element.style[camelStyle] === undefined) {
    -    var prefixedStyle = goog.dom.vendor.getVendorJsPrefix() +
    -        goog.string.toTitleCase(camelStyle);
    -
    -    if (element.style[prefixedStyle] !== undefined) {
    -      return goog.dom.vendor.getVendorPrefix() + '-' + style;
    -    }
    -  }
    -
    -  return style;
    -};
    -
    -
    -/**
    - * Retrieves an explicitly-set style value of a node. This returns '' if there
    - * isn't a style attribute on the element or if this style property has not been
    - * explicitly set in script.
    - *
    - * @param {Element} element Element to get style of.
    - * @param {string} property Property to get, css-style (if you have a camel-case
    - * property, use element.style[style]).
    - * @return {string} Style value.
    - */
    -goog.style.getStyle = function(element, property) {
    -  // element.style is '' for well-known properties which are unset.
    -  // For for browser specific styles as 'filter' is undefined
    -  // so we need to return '' explicitly to make it consistent across
    -  // browsers.
    -  var styleValue = element.style[goog.string.toCamelCase(property)];
    -
    -  // Using typeof here because of a bug in Safari 5.1, where this value
    -  // was undefined, but === undefined returned false.
    -  if (typeof(styleValue) !== 'undefined') {
    -    return styleValue;
    -  }
    -
    -  return element.style[goog.style.getVendorJsStyleName_(element, property)] ||
    -      '';
    -};
    -
    -
    -/**
    - * Retrieves a computed style value of a node. It returns empty string if the
    - * value cannot be computed (which will be the case in Internet Explorer) or
    - * "none" if the property requested is an SVG one and it has not been
    - * explicitly set (firefox and webkit).
    - *
    - * @param {Element} element Element to get style of.
    - * @param {string} property Property to get (camel-case).
    - * @return {string} Style value.
    - */
    -goog.style.getComputedStyle = function(element, property) {
    -  var doc = goog.dom.getOwnerDocument(element);
    -  if (doc.defaultView && doc.defaultView.getComputedStyle) {
    -    var styles = doc.defaultView.getComputedStyle(element, null);
    -    if (styles) {
    -      // element.style[..] is undefined for browser specific styles
    -      // as 'filter'.
    -      return styles[property] || styles.getPropertyValue(property) || '';
    -    }
    -  }
    -
    -  return '';
    -};
    -
    -
    -/**
    - * Gets the cascaded style value of a node, or null if the value cannot be
    - * computed (only Internet Explorer can do this).
    - *
    - * @param {Element} element Element to get style of.
    - * @param {string} style Property to get (camel-case).
    - * @return {string} Style value.
    - */
    -goog.style.getCascadedStyle = function(element, style) {
    -  // TODO(nicksantos): This should be documented to return null. #fixTypes
    -  return element.currentStyle ? element.currentStyle[style] : null;
    -};
    -
    -
    -/**
    - * Cross-browser pseudo get computed style. It returns the computed style where
    - * available. If not available it tries the cascaded style value (IE
    - * currentStyle) and in worst case the inline style value.  It shouldn't be
    - * called directly, see http://wiki/Main/ComputedStyleVsCascadedStyle for
    - * discussion.
    - *
    - * @param {Element} element Element to get style of.
    - * @param {string} style Property to get (must be camelCase, not css-style.).
    - * @return {string} Style value.
    - * @private
    - */
    -goog.style.getStyle_ = function(element, style) {
    -  return goog.style.getComputedStyle(element, style) ||
    -         goog.style.getCascadedStyle(element, style) ||
    -         (element.style && element.style[style]);
    -};
    -
    -
    -/**
    - * Retrieves the computed value of the box-sizing CSS attribute.
    - * Browser support: http://caniuse.com/css3-boxsizing.
    - * @param {!Element} element The element whose box-sizing to get.
    - * @return {?string} 'content-box', 'border-box' or 'padding-box'. null if
    - *     box-sizing is not supported (IE7 and below).
    - */
    -goog.style.getComputedBoxSizing = function(element) {
    -  return goog.style.getStyle_(element, 'boxSizing') ||
    -      goog.style.getStyle_(element, 'MozBoxSizing') ||
    -      goog.style.getStyle_(element, 'WebkitBoxSizing') || null;
    -};
    -
    -
    -/**
    - * Retrieves the computed value of the position CSS attribute.
    - * @param {Element} element The element to get the position of.
    - * @return {string} Position value.
    - */
    -goog.style.getComputedPosition = function(element) {
    -  return goog.style.getStyle_(element, 'position');
    -};
    -
    -
    -/**
    - * Retrieves the computed background color string for a given element. The
    - * string returned is suitable for assigning to another element's
    - * background-color, but is not guaranteed to be in any particular string
    - * format. Accessing the color in a numeric form may not be possible in all
    - * browsers or with all input.
    - *
    - * If the background color for the element is defined as a hexadecimal value,
    - * the resulting string can be parsed by goog.color.parse in all supported
    - * browsers.
    - *
    - * Whether named colors like "red" or "lightblue" get translated into a
    - * format which can be parsed is browser dependent. Calling this function on
    - * transparent elements will return "transparent" in most browsers or
    - * "rgba(0, 0, 0, 0)" in WebKit.
    - * @param {Element} element The element to get the background color of.
    - * @return {string} The computed string value of the background color.
    - */
    -goog.style.getBackgroundColor = function(element) {
    -  return goog.style.getStyle_(element, 'backgroundColor');
    -};
    -
    -
    -/**
    - * Retrieves the computed value of the overflow-x CSS attribute.
    - * @param {Element} element The element to get the overflow-x of.
    - * @return {string} The computed string value of the overflow-x attribute.
    - */
    -goog.style.getComputedOverflowX = function(element) {
    -  return goog.style.getStyle_(element, 'overflowX');
    -};
    -
    -
    -/**
    - * Retrieves the computed value of the overflow-y CSS attribute.
    - * @param {Element} element The element to get the overflow-y of.
    - * @return {string} The computed string value of the overflow-y attribute.
    - */
    -goog.style.getComputedOverflowY = function(element) {
    -  return goog.style.getStyle_(element, 'overflowY');
    -};
    -
    -
    -/**
    - * Retrieves the computed value of the z-index CSS attribute.
    - * @param {Element} element The element to get the z-index of.
    - * @return {string|number} The computed value of the z-index attribute.
    - */
    -goog.style.getComputedZIndex = function(element) {
    -  return goog.style.getStyle_(element, 'zIndex');
    -};
    -
    -
    -/**
    - * Retrieves the computed value of the text-align CSS attribute.
    - * @param {Element} element The element to get the text-align of.
    - * @return {string} The computed string value of the text-align attribute.
    - */
    -goog.style.getComputedTextAlign = function(element) {
    -  return goog.style.getStyle_(element, 'textAlign');
    -};
    -
    -
    -/**
    - * Retrieves the computed value of the cursor CSS attribute.
    - * @param {Element} element The element to get the cursor of.
    - * @return {string} The computed string value of the cursor attribute.
    - */
    -goog.style.getComputedCursor = function(element) {
    -  return goog.style.getStyle_(element, 'cursor');
    -};
    -
    -
    -/**
    - * Retrieves the computed value of the CSS transform attribute.
    - * @param {Element} element The element to get the transform of.
    - * @return {string} The computed string representation of the transform matrix.
    - */
    -goog.style.getComputedTransform = function(element) {
    -  var property = goog.style.getVendorStyleName_(element, 'transform');
    -  return goog.style.getStyle_(element, property) ||
    -      goog.style.getStyle_(element, 'transform');
    -};
    -
    -
    -/**
    - * Sets the top/left values of an element.  If no unit is specified in the
    - * argument then it will add px. The second argument is required if the first
    - * argument is a string or number and is ignored if the first argument
    - * is a coordinate.
    - * @param {Element} el Element to move.
    - * @param {string|number|goog.math.Coordinate} arg1 Left position or coordinate.
    - * @param {string|number=} opt_arg2 Top position.
    - */
    -goog.style.setPosition = function(el, arg1, opt_arg2) {
    -  var x, y;
    -
    -  if (arg1 instanceof goog.math.Coordinate) {
    -    x = arg1.x;
    -    y = arg1.y;
    -  } else {
    -    x = arg1;
    -    y = opt_arg2;
    -  }
    -
    -  el.style.left = goog.style.getPixelStyleValue_(
    -      /** @type {number|string} */ (x), false);
    -  el.style.top = goog.style.getPixelStyleValue_(
    -      /** @type {number|string} */ (y), false);
    -};
    -
    -
    -/**
    - * Gets the offsetLeft and offsetTop properties of an element and returns them
    - * in a Coordinate object
    - * @param {Element} element Element.
    - * @return {!goog.math.Coordinate} The position.
    - */
    -goog.style.getPosition = function(element) {
    -  return new goog.math.Coordinate(element.offsetLeft, element.offsetTop);
    -};
    -
    -
    -/**
    - * Returns the viewport element for a particular document
    - * @param {Node=} opt_node DOM node (Document is OK) to get the viewport element
    - *     of.
    - * @return {Element} document.documentElement or document.body.
    - */
    -goog.style.getClientViewportElement = function(opt_node) {
    -  var doc;
    -  if (opt_node) {
    -    doc = goog.dom.getOwnerDocument(opt_node);
    -  } else {
    -    doc = goog.dom.getDocument();
    -  }
    -
    -  // In old IE versions the document.body represented the viewport
    -  if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9) &&
    -      !goog.dom.getDomHelper(doc).isCss1CompatMode()) {
    -    return doc.body;
    -  }
    -  return doc.documentElement;
    -};
    -
    -
    -/**
    - * Calculates the viewport coordinates relative to the page/document
    - * containing the node. The viewport may be the browser viewport for
    - * non-iframe document, or the iframe container for iframe'd document.
    - * @param {!Document} doc The document to use as the reference point.
    - * @return {!goog.math.Coordinate} The page offset of the viewport.
    - */
    -goog.style.getViewportPageOffset = function(doc) {
    -  var body = doc.body;
    -  var documentElement = doc.documentElement;
    -  var scrollLeft = body.scrollLeft || documentElement.scrollLeft;
    -  var scrollTop = body.scrollTop || documentElement.scrollTop;
    -  return new goog.math.Coordinate(scrollLeft, scrollTop);
    -};
    -
    -
    -/**
    - * Gets the client rectangle of the DOM element.
    - *
    - * getBoundingClientRect is part of a new CSS object model draft (with a
    - * long-time presence in IE), replacing the error-prone parent offset
    - * computation and the now-deprecated Gecko getBoxObjectFor.
    - *
    - * This utility patches common browser bugs in getBoundingClientRect. It
    - * will fail if getBoundingClientRect is unsupported.
    - *
    - * If the element is not in the DOM, the result is undefined, and an error may
    - * be thrown depending on user agent.
    - *
    - * @param {!Element} el The element whose bounding rectangle is being queried.
    - * @return {Object} A native bounding rectangle with numerical left, top,
    - *     right, and bottom.  Reported by Firefox to be of object type ClientRect.
    - * @private
    - */
    -goog.style.getBoundingClientRect_ = function(el) {
    -  var rect;
    -  try {
    -    rect = el.getBoundingClientRect();
    -  } catch (e) {
    -    // In IE < 9, calling getBoundingClientRect on an orphan element raises an
    -    // "Unspecified Error". All other browsers return zeros.
    -    return {'left': 0, 'top': 0, 'right': 0, 'bottom': 0};
    -  }
    -
    -  // Patch the result in IE only, so that this function can be inlined if
    -  // compiled for non-IE.
    -  if (goog.userAgent.IE && el.ownerDocument.body) {
    -
    -    // In IE, most of the time, 2 extra pixels are added to the top and left
    -    // due to the implicit 2-pixel inset border.  In IE6/7 quirks mode and
    -    // IE6 standards mode, this border can be overridden by setting the
    -    // document element's border to zero -- thus, we cannot rely on the
    -    // offset always being 2 pixels.
    -
    -    // In quirks mode, the offset can be determined by querying the body's
    -    // clientLeft/clientTop, but in standards mode, it is found by querying
    -    // the document element's clientLeft/clientTop.  Since we already called
    -    // getBoundingClientRect we have already forced a reflow, so it is not
    -    // too expensive just to query them all.
    -
    -    // See: http://msdn.microsoft.com/en-us/library/ms536433(VS.85).aspx
    -    var doc = el.ownerDocument;
    -    rect.left -= doc.documentElement.clientLeft + doc.body.clientLeft;
    -    rect.top -= doc.documentElement.clientTop + doc.body.clientTop;
    -  }
    -  return /** @type {Object} */ (rect);
    -};
    -
    -
    -/**
    - * Returns the first parent that could affect the position of a given element.
    - * @param {Element} element The element to get the offset parent for.
    - * @return {Element} The first offset parent or null if one cannot be found.
    - */
    -goog.style.getOffsetParent = function(element) {
    -  // element.offsetParent does the right thing in IE7 and below.  In other
    -  // browsers it only includes elements with position absolute, relative or
    -  // fixed, not elements with overflow set to auto or scroll.
    -  if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(8)) {
    -    return element.offsetParent;
    -  }
    -
    -  var doc = goog.dom.getOwnerDocument(element);
    -  var positionStyle = goog.style.getStyle_(element, 'position');
    -  var skipStatic = positionStyle == 'fixed' || positionStyle == 'absolute';
    -  for (var parent = element.parentNode; parent && parent != doc;
    -       parent = parent.parentNode) {
    -    // Skip shadowDOM roots.
    -    if (parent.nodeType == goog.dom.NodeType.DOCUMENT_FRAGMENT &&
    -        parent.host) {
    -      parent = parent.host;
    -    }
    -    positionStyle =
    -        goog.style.getStyle_(/** @type {!Element} */ (parent), 'position');
    -    skipStatic = skipStatic && positionStyle == 'static' &&
    -                 parent != doc.documentElement && parent != doc.body;
    -    if (!skipStatic && (parent.scrollWidth > parent.clientWidth ||
    -                        parent.scrollHeight > parent.clientHeight ||
    -                        positionStyle == 'fixed' ||
    -                        positionStyle == 'absolute' ||
    -                        positionStyle == 'relative')) {
    -      return /** @type {!Element} */ (parent);
    -    }
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * Calculates and returns the visible rectangle for a given element. Returns a
    - * box describing the visible portion of the nearest scrollable offset ancestor.
    - * Coordinates are given relative to the document.
    - *
    - * @param {Element} element Element to get the visible rect for.
    - * @return {goog.math.Box} Bounding elementBox describing the visible rect or
    - *     null if scrollable ancestor isn't inside the visible viewport.
    - */
    -goog.style.getVisibleRectForElement = function(element) {
    -  var visibleRect = new goog.math.Box(0, Infinity, Infinity, 0);
    -  var dom = goog.dom.getDomHelper(element);
    -  var body = dom.getDocument().body;
    -  var documentElement = dom.getDocument().documentElement;
    -  var scrollEl = dom.getDocumentScrollElement();
    -
    -  // Determine the size of the visible rect by climbing the dom accounting for
    -  // all scrollable containers.
    -  for (var el = element; el = goog.style.getOffsetParent(el); ) {
    -    // clientWidth is zero for inline block elements in IE.
    -    // on WEBKIT, body element can have clientHeight = 0 and scrollHeight > 0
    -    if ((!goog.userAgent.IE || el.clientWidth != 0) &&
    -        (!goog.userAgent.WEBKIT || el.clientHeight != 0 || el != body) &&
    -        // body may have overflow set on it, yet we still get the entire
    -        // viewport. In some browsers, el.offsetParent may be
    -        // document.documentElement, so check for that too.
    -        (el != body && el != documentElement &&
    -            goog.style.getStyle_(el, 'overflow') != 'visible')) {
    -      var pos = goog.style.getPageOffset(el);
    -      var client = goog.style.getClientLeftTop(el);
    -      pos.x += client.x;
    -      pos.y += client.y;
    -
    -      visibleRect.top = Math.max(visibleRect.top, pos.y);
    -      visibleRect.right = Math.min(visibleRect.right,
    -                                   pos.x + el.clientWidth);
    -      visibleRect.bottom = Math.min(visibleRect.bottom,
    -                                    pos.y + el.clientHeight);
    -      visibleRect.left = Math.max(visibleRect.left, pos.x);
    -    }
    -  }
    -
    -  // Clip by window's viewport.
    -  var scrollX = scrollEl.scrollLeft, scrollY = scrollEl.scrollTop;
    -  visibleRect.left = Math.max(visibleRect.left, scrollX);
    -  visibleRect.top = Math.max(visibleRect.top, scrollY);
    -  var winSize = dom.getViewportSize();
    -  visibleRect.right = Math.min(visibleRect.right, scrollX + winSize.width);
    -  visibleRect.bottom = Math.min(visibleRect.bottom, scrollY + winSize.height);
    -  return visibleRect.top >= 0 && visibleRect.left >= 0 &&
    -         visibleRect.bottom > visibleRect.top &&
    -         visibleRect.right > visibleRect.left ?
    -         visibleRect : null;
    -};
    -
    -
    -/**
    - * Calculate the scroll position of {@code container} with the minimum amount so
    - * that the content and the borders of the given {@code element} become visible.
    - * If the element is bigger than the container, its top left corner will be
    - * aligned as close to the container's top left corner as possible.
    - *
    - * @param {Element} element The element to make visible.
    - * @param {Element} container The container to scroll.
    - * @param {boolean=} opt_center Whether to center the element in the container.
    - *     Defaults to false.
    - * @return {!goog.math.Coordinate} The new scroll position of the container,
    - *     in form of goog.math.Coordinate(scrollLeft, scrollTop).
    - */
    -goog.style.getContainerOffsetToScrollInto =
    -    function(element, container, opt_center) {
    -  // Absolute position of the element's border's top left corner.
    -  var elementPos = goog.style.getPageOffset(element);
    -  // Absolute position of the container's border's top left corner.
    -  var containerPos = goog.style.getPageOffset(container);
    -  var containerBorder = goog.style.getBorderBox(container);
    -  // Relative pos. of the element's border box to the container's content box.
    -  var relX = elementPos.x - containerPos.x - containerBorder.left;
    -  var relY = elementPos.y - containerPos.y - containerBorder.top;
    -  // How much the element can move in the container, i.e. the difference between
    -  // the element's bottom-right-most and top-left-most position where it's
    -  // fully visible.
    -  var spaceX = container.clientWidth - element.offsetWidth;
    -  var spaceY = container.clientHeight - element.offsetHeight;
    -
    -  var scrollLeft = container.scrollLeft;
    -  var scrollTop = container.scrollTop;
    -  if (container == goog.dom.getDocument().body ||
    -      container == goog.dom.getDocument().documentElement) {
    -    // If the container is the document scroll element (usually <body>),
    -    // getPageOffset(element) is already relative to it and there is no need to
    -    // consider the current scroll.
    -    scrollLeft = containerPos.x + containerBorder.left;
    -    scrollTop = containerPos.y + containerBorder.top;
    -
    -    if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(10)) {
    -      // In older versions of IE getPageOffset(element) does not include the
    -      // continaer border so it has to be added to accomodate.
    -      scrollLeft += containerBorder.left;
    -      scrollTop += containerBorder.top;
    -    }
    -  }
    -  if (opt_center) {
    -    // All browsers round non-integer scroll positions down.
    -    scrollLeft += relX - spaceX / 2;
    -    scrollTop += relY - spaceY / 2;
    -  } else {
    -    // This formula was designed to give the correct scroll values in the
    -    // following cases:
    -    // - element is higher than container (spaceY < 0) => scroll down by relY
    -    // - element is not higher that container (spaceY >= 0):
    -    //   - it is above container (relY < 0) => scroll up by abs(relY)
    -    //   - it is below container (relY > spaceY) => scroll down by relY - spaceY
    -    //   - it is in the container => don't scroll
    -    scrollLeft += Math.min(relX, Math.max(relX - spaceX, 0));
    -    scrollTop += Math.min(relY, Math.max(relY - spaceY, 0));
    -  }
    -  return new goog.math.Coordinate(scrollLeft, scrollTop);
    -};
    -
    -
    -/**
    - * Changes the scroll position of {@code container} with the minimum amount so
    - * that the content and the borders of the given {@code element} become visible.
    - * If the element is bigger than the container, its top left corner will be
    - * aligned as close to the container's top left corner as possible.
    - *
    - * @param {Element} element The element to make visible.
    - * @param {Element} container The container to scroll.
    - * @param {boolean=} opt_center Whether to center the element in the container.
    - *     Defaults to false.
    - */
    -goog.style.scrollIntoContainerView = function(element, container, opt_center) {
    -  var offset =
    -      goog.style.getContainerOffsetToScrollInto(element, container, opt_center);
    -  container.scrollLeft = offset.x;
    -  container.scrollTop = offset.y;
    -};
    -
    -
    -/**
    - * Returns clientLeft (width of the left border and, if the directionality is
    - * right to left, the vertical scrollbar) and clientTop as a coordinate object.
    - *
    - * @param {Element} el Element to get clientLeft for.
    - * @return {!goog.math.Coordinate} Client left and top.
    - */
    -goog.style.getClientLeftTop = function(el) {
    -  return new goog.math.Coordinate(el.clientLeft, el.clientTop);
    -};
    -
    -
    -/**
    - * Returns a Coordinate object relative to the top-left of the HTML document.
    - * Implemented as a single function to save having to do two recursive loops in
    - * opera and safari just to get both coordinates.  If you just want one value do
    - * use goog.style.getPageOffsetLeft() and goog.style.getPageOffsetTop(), but
    - * note if you call both those methods the tree will be analysed twice.
    - *
    - * @param {Element} el Element to get the page offset for.
    - * @return {!goog.math.Coordinate} The page offset.
    - */
    -goog.style.getPageOffset = function(el) {
    -  var doc = goog.dom.getOwnerDocument(el);
    -  // TODO(gboyer): Update the jsdoc in a way that doesn't break the universe.
    -  goog.asserts.assertObject(el, 'Parameter is required');
    -
    -  // NOTE(arv): If element is hidden (display none or disconnected or any the
    -  // ancestors are hidden) we get (0,0) by default but we still do the
    -  // accumulation of scroll position.
    -
    -  // TODO(arv): Should we check if the node is disconnected and in that case
    -  //            return (0,0)?
    -
    -  var pos = new goog.math.Coordinate(0, 0);
    -  var viewportElement = goog.style.getClientViewportElement(doc);
    -  if (el == viewportElement) {
    -    // viewport is always at 0,0 as that defined the coordinate system for this
    -    // function - this avoids special case checks in the code below
    -    return pos;
    -  }
    -
    -  var box = goog.style.getBoundingClientRect_(el);
    -  // Must add the scroll coordinates in to get the absolute page offset
    -  // of element since getBoundingClientRect returns relative coordinates to
    -  // the viewport.
    -  var scrollCoord = goog.dom.getDomHelper(doc).getDocumentScroll();
    -  pos.x = box.left + scrollCoord.x;
    -  pos.y = box.top + scrollCoord.y;
    -
    -  return pos;
    -};
    -
    -
    -/**
    - * Returns the left coordinate of an element relative to the HTML document
    - * @param {Element} el Elements.
    - * @return {number} The left coordinate.
    - */
    -goog.style.getPageOffsetLeft = function(el) {
    -  return goog.style.getPageOffset(el).x;
    -};
    -
    -
    -/**
    - * Returns the top coordinate of an element relative to the HTML document
    - * @param {Element} el Elements.
    - * @return {number} The top coordinate.
    - */
    -goog.style.getPageOffsetTop = function(el) {
    -  return goog.style.getPageOffset(el).y;
    -};
    -
    -
    -/**
    - * Returns a Coordinate object relative to the top-left of an HTML document
    - * in an ancestor frame of this element. Used for measuring the position of
    - * an element inside a frame relative to a containing frame.
    - *
    - * @param {Element} el Element to get the page offset for.
    - * @param {Window} relativeWin The window to measure relative to. If relativeWin
    - *     is not in the ancestor frame chain of the element, we measure relative to
    - *     the top-most window.
    - * @return {!goog.math.Coordinate} The page offset.
    - */
    -goog.style.getFramedPageOffset = function(el, relativeWin) {
    -  var position = new goog.math.Coordinate(0, 0);
    -
    -  // Iterate up the ancestor frame chain, keeping track of the current window
    -  // and the current element in that window.
    -  var currentWin = goog.dom.getWindow(goog.dom.getOwnerDocument(el));
    -  var currentEl = el;
    -  do {
    -    // if we're at the top window, we want to get the page offset.
    -    // if we're at an inner frame, we only want to get the window position
    -    // so that we can determine the actual page offset in the context of
    -    // the outer window.
    -    var offset = currentWin == relativeWin ?
    -        goog.style.getPageOffset(currentEl) :
    -        goog.style.getClientPositionForElement_(
    -            goog.asserts.assert(currentEl));
    -
    -    position.x += offset.x;
    -    position.y += offset.y;
    -  } while (currentWin && currentWin != relativeWin &&
    -      currentWin != currentWin.parent &&
    -      (currentEl = currentWin.frameElement) &&
    -      (currentWin = currentWin.parent));
    -
    -  return position;
    -};
    -
    -
    -/**
    - * Translates the specified rect relative to origBase page, for newBase page.
    - * If origBase and newBase are the same, this function does nothing.
    - *
    - * @param {goog.math.Rect} rect The source rectangle relative to origBase page,
    - *     and it will have the translated result.
    - * @param {goog.dom.DomHelper} origBase The DomHelper for the input rectangle.
    - * @param {goog.dom.DomHelper} newBase The DomHelper for the resultant
    - *     coordinate.  This must be a DOM for an ancestor frame of origBase
    - *     or the same as origBase.
    - */
    -goog.style.translateRectForAnotherFrame = function(rect, origBase, newBase) {
    -  if (origBase.getDocument() != newBase.getDocument()) {
    -    var body = origBase.getDocument().body;
    -    var pos = goog.style.getFramedPageOffset(body, newBase.getWindow());
    -
    -    // Adjust Body's margin.
    -    pos = goog.math.Coordinate.difference(pos, goog.style.getPageOffset(body));
    -
    -    if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9) &&
    -        !origBase.isCss1CompatMode()) {
    -      pos = goog.math.Coordinate.difference(pos, origBase.getDocumentScroll());
    -    }
    -
    -    rect.left += pos.x;
    -    rect.top += pos.y;
    -  }
    -};
    -
    -
    -/**
    - * Returns the position of an element relative to another element in the
    - * document.  A relative to B
    - * @param {Element|Event|goog.events.Event} a Element or mouse event whose
    - *     position we're calculating.
    - * @param {Element|Event|goog.events.Event} b Element or mouse event position
    - *     is relative to.
    - * @return {!goog.math.Coordinate} The relative position.
    - */
    -goog.style.getRelativePosition = function(a, b) {
    -  var ap = goog.style.getClientPosition(a);
    -  var bp = goog.style.getClientPosition(b);
    -  return new goog.math.Coordinate(ap.x - bp.x, ap.y - bp.y);
    -};
    -
    -
    -/**
    - * Returns the position of the event or the element's border box relative to
    - * the client viewport.
    - * @param {!Element} el Element whose position to get.
    - * @return {!goog.math.Coordinate} The position.
    - * @private
    - */
    -goog.style.getClientPositionForElement_ = function(el) {
    -  var box = goog.style.getBoundingClientRect_(el);
    -  return new goog.math.Coordinate(box.left, box.top);
    -};
    -
    -
    -/**
    - * Returns the position of the event or the element's border box relative to
    - * the client viewport.
    - * @param {Element|Event|goog.events.Event} el Element or a mouse / touch event.
    - * @return {!goog.math.Coordinate} The position.
    - */
    -goog.style.getClientPosition = function(el) {
    -  goog.asserts.assert(el);
    -  if (el.nodeType == goog.dom.NodeType.ELEMENT) {
    -    return goog.style.getClientPositionForElement_(
    -        /** @type {!Element} */ (el));
    -  } else {
    -    var isAbstractedEvent = goog.isFunction(el.getBrowserEvent);
    -    var be = /** @type {!goog.events.BrowserEvent} */ (el);
    -    var targetEvent = el;
    -
    -    if (el.targetTouches && el.targetTouches.length) {
    -      targetEvent = el.targetTouches[0];
    -    } else if (isAbstractedEvent && be.getBrowserEvent().targetTouches &&
    -        be.getBrowserEvent().targetTouches.length) {
    -      targetEvent = be.getBrowserEvent().targetTouches[0];
    -    }
    -
    -    return new goog.math.Coordinate(
    -        targetEvent.clientX,
    -        targetEvent.clientY);
    -  }
    -};
    -
    -
    -/**
    - * Moves an element to the given coordinates relative to the client viewport.
    - * @param {Element} el Absolutely positioned element to set page offset for.
    - *     It must be in the document.
    - * @param {number|goog.math.Coordinate} x Left position of the element's margin
    - *     box or a coordinate object.
    - * @param {number=} opt_y Top position of the element's margin box.
    - */
    -goog.style.setPageOffset = function(el, x, opt_y) {
    -  // Get current pageoffset
    -  var cur = goog.style.getPageOffset(el);
    -
    -  if (x instanceof goog.math.Coordinate) {
    -    opt_y = x.y;
    -    x = x.x;
    -  }
    -
    -  // NOTE(arv): We cannot allow strings for x and y. We could but that would
    -  // require us to manually transform between different units
    -
    -  // Work out deltas
    -  var dx = x - cur.x;
    -  var dy = opt_y - cur.y;
    -
    -  // Set position to current left/top + delta
    -  goog.style.setPosition(el, el.offsetLeft + dx, el.offsetTop + dy);
    -};
    -
    -
    -/**
    - * Sets the width/height values of an element.  If an argument is numeric,
    - * or a goog.math.Size is passed, it is assumed to be pixels and will add
    - * 'px' after converting it to an integer in string form. (This just sets the
    - * CSS width and height properties so it might set content-box or border-box
    - * size depending on the box model the browser is using.)
    - *
    - * @param {Element} element Element to set the size of.
    - * @param {string|number|goog.math.Size} w Width of the element, or a
    - *     size object.
    - * @param {string|number=} opt_h Height of the element. Required if w is not a
    - *     size object.
    - */
    -goog.style.setSize = function(element, w, opt_h) {
    -  var h;
    -  if (w instanceof goog.math.Size) {
    -    h = w.height;
    -    w = w.width;
    -  } else {
    -    if (opt_h == undefined) {
    -      throw Error('missing height argument');
    -    }
    -    h = opt_h;
    -  }
    -
    -  goog.style.setWidth(element, /** @type {string|number} */ (w));
    -  goog.style.setHeight(element, /** @type {string|number} */ (h));
    -};
    -
    -
    -/**
    - * Helper function to create a string to be set into a pixel-value style
    - * property of an element. Can round to the nearest integer value.
    - *
    - * @param {string|number} value The style value to be used. If a number,
    - *     'px' will be appended, otherwise the value will be applied directly.
    - * @param {boolean} round Whether to round the nearest integer (if property
    - *     is a number).
    - * @return {string} The string value for the property.
    - * @private
    - */
    -goog.style.getPixelStyleValue_ = function(value, round) {
    -  if (typeof value == 'number') {
    -    value = (round ? Math.round(value) : value) + 'px';
    -  }
    -
    -  return value;
    -};
    -
    -
    -/**
    - * Set the height of an element.  Sets the element's style property.
    - * @param {Element} element Element to set the height of.
    - * @param {string|number} height The height value to set.  If a number, 'px'
    - *     will be appended, otherwise the value will be applied directly.
    - */
    -goog.style.setHeight = function(element, height) {
    -  element.style.height = goog.style.getPixelStyleValue_(height, true);
    -};
    -
    -
    -/**
    - * Set the width of an element.  Sets the element's style property.
    - * @param {Element} element Element to set the width of.
    - * @param {string|number} width The width value to set.  If a number, 'px'
    - *     will be appended, otherwise the value will be applied directly.
    - */
    -goog.style.setWidth = function(element, width) {
    -  element.style.width = goog.style.getPixelStyleValue_(width, true);
    -};
    -
    -
    -/**
    - * Gets the height and width of an element, even if its display is none.
    - *
    - * Specifically, this returns the height and width of the border box,
    - * irrespective of the box model in effect.
    - *
    - * Note that this function does not take CSS transforms into account. Please see
    - * {@code goog.style.getTransformedSize}.
    - * @param {Element} element Element to get size of.
    - * @return {!goog.math.Size} Object with width/height properties.
    - */
    -goog.style.getSize = function(element) {
    -  return goog.style.evaluateWithTemporaryDisplay_(
    -      goog.style.getSizeWithDisplay_, /** @type {!Element} */ (element));
    -};
    -
    -
    -/**
    - * Call {@code fn} on {@code element} such that {@code element}'s dimensions are
    - * accurate when it's passed to {@code fn}.
    - * @param {function(!Element): T} fn Function to call with {@code element} as
    - *     an argument after temporarily changing {@code element}'s display such
    - *     that its dimensions are accurate.
    - * @param {!Element} element Element (which may have display none) to use as
    - *     argument to {@code fn}.
    - * @return {T} Value returned by calling {@code fn} with {@code element}.
    - * @template T
    - * @private
    - */
    -goog.style.evaluateWithTemporaryDisplay_ = function(fn, element) {
    -  if (goog.style.getStyle_(element, 'display') != 'none') {
    -    return fn(element);
    -  }
    -
    -  var style = element.style;
    -  var originalDisplay = style.display;
    -  var originalVisibility = style.visibility;
    -  var originalPosition = style.position;
    -
    -  style.visibility = 'hidden';
    -  style.position = 'absolute';
    -  style.display = 'inline';
    -
    -  var retVal = fn(element);
    -
    -  style.display = originalDisplay;
    -  style.position = originalPosition;
    -  style.visibility = originalVisibility;
    -
    -  return retVal;
    -};
    -
    -
    -/**
    - * Gets the height and width of an element when the display is not none.
    - * @param {Element} element Element to get size of.
    - * @return {!goog.math.Size} Object with width/height properties.
    - * @private
    - */
    -goog.style.getSizeWithDisplay_ = function(element) {
    -  var offsetWidth = element.offsetWidth;
    -  var offsetHeight = element.offsetHeight;
    -  var webkitOffsetsZero =
    -      goog.userAgent.WEBKIT && !offsetWidth && !offsetHeight;
    -  if ((!goog.isDef(offsetWidth) || webkitOffsetsZero) &&
    -      element.getBoundingClientRect) {
    -    // Fall back to calling getBoundingClientRect when offsetWidth or
    -    // offsetHeight are not defined, or when they are zero in WebKit browsers.
    -    // This makes sure that we return for the correct size for SVG elements, but
    -    // will still return 0 on Webkit prior to 534.8, see
    -    // http://trac.webkit.org/changeset/67252.
    -    var clientRect = goog.style.getBoundingClientRect_(element);
    -    return new goog.math.Size(clientRect.right - clientRect.left,
    -        clientRect.bottom - clientRect.top);
    -  }
    -  return new goog.math.Size(offsetWidth, offsetHeight);
    -};
    -
    -
    -/**
    - * Gets the height and width of an element, post transform, even if its display
    - * is none.
    - *
    - * This is like {@code goog.style.getSize}, except:
    - * <ol>
    - * <li>Takes webkitTransforms such as rotate and scale into account.
    - * <li>Will return null if {@code element} doesn't respond to
    - *     {@code getBoundingClientRect}.
    - * <li>Currently doesn't make sense on non-WebKit browsers which don't support
    - *    webkitTransforms.
    - * </ol>
    - * @param {!Element} element Element to get size of.
    - * @return {goog.math.Size} Object with width/height properties.
    - */
    -goog.style.getTransformedSize = function(element) {
    -  if (!element.getBoundingClientRect) {
    -    return null;
    -  }
    -
    -  var clientRect = goog.style.evaluateWithTemporaryDisplay_(
    -      goog.style.getBoundingClientRect_, element);
    -  return new goog.math.Size(clientRect.right - clientRect.left,
    -      clientRect.bottom - clientRect.top);
    -};
    -
    -
    -/**
    - * Returns a bounding rectangle for a given element in page space.
    - * @param {Element} element Element to get bounds of. Must not be display none.
    - * @return {!goog.math.Rect} Bounding rectangle for the element.
    - */
    -goog.style.getBounds = function(element) {
    -  var o = goog.style.getPageOffset(element);
    -  var s = goog.style.getSize(element);
    -  return new goog.math.Rect(o.x, o.y, s.width, s.height);
    -};
    -
    -
    -/**
    - * Converts a CSS selector in the form style-property to styleProperty.
    - * @param {*} selector CSS Selector.
    - * @return {string} Camel case selector.
    - * @deprecated Use goog.string.toCamelCase instead.
    - */
    -goog.style.toCamelCase = function(selector) {
    -  return goog.string.toCamelCase(String(selector));
    -};
    -
    -
    -/**
    - * Converts a CSS selector in the form styleProperty to style-property.
    - * @param {string} selector Camel case selector.
    - * @return {string} Selector cased.
    - * @deprecated Use goog.string.toSelectorCase instead.
    - */
    -goog.style.toSelectorCase = function(selector) {
    -  return goog.string.toSelectorCase(selector);
    -};
    -
    -
    -/**
    - * Gets the opacity of a node (x-browser). This gets the inline style opacity
    - * of the node, and does not take into account the cascaded or the computed
    - * style for this node.
    - * @param {Element} el Element whose opacity has to be found.
    - * @return {number|string} Opacity between 0 and 1 or an empty string {@code ''}
    - *     if the opacity is not set.
    - */
    -goog.style.getOpacity = function(el) {
    -  var style = el.style;
    -  var result = '';
    -  if ('opacity' in style) {
    -    result = style.opacity;
    -  } else if ('MozOpacity' in style) {
    -    result = style.MozOpacity;
    -  } else if ('filter' in style) {
    -    var match = style.filter.match(/alpha\(opacity=([\d.]+)\)/);
    -    if (match) {
    -      result = String(match[1] / 100);
    -    }
    -  }
    -  return result == '' ? result : Number(result);
    -};
    -
    -
    -/**
    - * Sets the opacity of a node (x-browser).
    - * @param {Element} el Elements whose opacity has to be set.
    - * @param {number|string} alpha Opacity between 0 and 1 or an empty string
    - *     {@code ''} to clear the opacity.
    - */
    -goog.style.setOpacity = function(el, alpha) {
    -  var style = el.style;
    -  if ('opacity' in style) {
    -    style.opacity = alpha;
    -  } else if ('MozOpacity' in style) {
    -    style.MozOpacity = alpha;
    -  } else if ('filter' in style) {
    -    // TODO(arv): Overwriting the filter might have undesired side effects.
    -    if (alpha === '') {
    -      style.filter = '';
    -    } else {
    -      style.filter = 'alpha(opacity=' + alpha * 100 + ')';
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Sets the background of an element to a transparent image in a browser-
    - * independent manner.
    - *
    - * This function does not support repeating backgrounds or alternate background
    - * positions to match the behavior of Internet Explorer. It also does not
    - * support sizingMethods other than crop since they cannot be replicated in
    - * browsers other than Internet Explorer.
    - *
    - * @param {Element} el The element to set background on.
    - * @param {string} src The image source URL.
    - */
    -goog.style.setTransparentBackgroundImage = function(el, src) {
    -  var style = el.style;
    -  // It is safe to use the style.filter in IE only. In Safari 'filter' is in
    -  // style object but access to style.filter causes it to throw an exception.
    -  // Note: IE8 supports images with an alpha channel.
    -  if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('8')) {
    -    // See TODO in setOpacity.
    -    style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(' +
    -        'src="' + src + '", sizingMethod="crop")';
    -  } else {
    -    // Set style properties individually instead of using background shorthand
    -    // to prevent overwriting a pre-existing background color.
    -    style.backgroundImage = 'url(' + src + ')';
    -    style.backgroundPosition = 'top left';
    -    style.backgroundRepeat = 'no-repeat';
    -  }
    -};
    -
    -
    -/**
    - * Clears the background image of an element in a browser independent manner.
    - * @param {Element} el The element to clear background image for.
    - */
    -goog.style.clearTransparentBackgroundImage = function(el) {
    -  var style = el.style;
    -  if ('filter' in style) {
    -    // See TODO in setOpacity.
    -    style.filter = '';
    -  } else {
    -    // Set style properties individually instead of using background shorthand
    -    // to prevent overwriting a pre-existing background color.
    -    style.backgroundImage = 'none';
    -  }
    -};
    -
    -
    -/**
    - * Shows or hides an element from the page. Hiding the element is done by
    - * setting the display property to "none", removing the element from the
    - * rendering hierarchy so it takes up no space. To show the element, the default
    - * inherited display property is restored (defined either in stylesheets or by
    - * the browser's default style rules.)
    - *
    - * Caveat 1: if the inherited display property for the element is set to "none"
    - * by the stylesheets, that is the property that will be restored by a call to
    - * showElement(), effectively toggling the display between "none" and "none".
    - *
    - * Caveat 2: if the element display style is set inline (by setting either
    - * element.style.display or a style attribute in the HTML), a call to
    - * showElement will clear that setting and defer to the inherited style in the
    - * stylesheet.
    - * @param {Element} el Element to show or hide.
    - * @param {*} display True to render the element in its default style,
    - *     false to disable rendering the element.
    - * @deprecated Use goog.style.setElementShown instead.
    - */
    -goog.style.showElement = function(el, display) {
    -  goog.style.setElementShown(el, display);
    -};
    -
    -
    -/**
    - * Shows or hides an element from the page. Hiding the element is done by
    - * setting the display property to "none", removing the element from the
    - * rendering hierarchy so it takes up no space. To show the element, the default
    - * inherited display property is restored (defined either in stylesheets or by
    - * the browser's default style rules).
    - *
    - * Caveat 1: if the inherited display property for the element is set to "none"
    - * by the stylesheets, that is the property that will be restored by a call to
    - * setElementShown(), effectively toggling the display between "none" and
    - * "none".
    - *
    - * Caveat 2: if the element display style is set inline (by setting either
    - * element.style.display or a style attribute in the HTML), a call to
    - * setElementShown will clear that setting and defer to the inherited style in
    - * the stylesheet.
    - * @param {Element} el Element to show or hide.
    - * @param {*} isShown True to render the element in its default style,
    - *     false to disable rendering the element.
    - */
    -goog.style.setElementShown = function(el, isShown) {
    -  el.style.display = isShown ? '' : 'none';
    -};
    -
    -
    -/**
    - * Test whether the given element has been shown or hidden via a call to
    - * {@link #setElementShown}.
    - *
    - * Note this is strictly a companion method for a call
    - * to {@link #setElementShown} and the same caveats apply; in particular, this
    - * method does not guarantee that the return value will be consistent with
    - * whether or not the element is actually visible.
    - *
    - * @param {Element} el The element to test.
    - * @return {boolean} Whether the element has been shown.
    - * @see #setElementShown
    - */
    -goog.style.isElementShown = function(el) {
    -  return el.style.display != 'none';
    -};
    -
    -
    -/**
    - * Installs the styles string into the window that contains opt_element.  If
    - * opt_element is null, the main window is used.
    - * @param {string} stylesString The style string to install.
    - * @param {Node=} opt_node Node whose parent document should have the
    - *     styles installed.
    - * @return {Element|StyleSheet} The style element created.
    - */
    -goog.style.installStyles = function(stylesString, opt_node) {
    -  var dh = goog.dom.getDomHelper(opt_node);
    -  var styleSheet = null;
    -
    -  // IE < 11 requires createStyleSheet. Note that doc.createStyleSheet will be
    -  // undefined as of IE 11.
    -  var doc = dh.getDocument();
    -  if (goog.userAgent.IE && doc.createStyleSheet) {
    -    styleSheet = doc.createStyleSheet();
    -    goog.style.setStyles(styleSheet, stylesString);
    -  } else {
    -    var head = dh.getElementsByTagNameAndClass('head')[0];
    -
    -    // In opera documents are not guaranteed to have a head element, thus we
    -    // have to make sure one exists before using it.
    -    if (!head) {
    -      var body = dh.getElementsByTagNameAndClass('body')[0];
    -      head = dh.createDom('head');
    -      body.parentNode.insertBefore(head, body);
    -    }
    -    styleSheet = dh.createDom('style');
    -    // NOTE(user): Setting styles after the style element has been appended
    -    // to the head results in a nasty Webkit bug in certain scenarios. Please
    -    // refer to https://bugs.webkit.org/show_bug.cgi?id=26307 for additional
    -    // details.
    -    goog.style.setStyles(styleSheet, stylesString);
    -    dh.appendChild(head, styleSheet);
    -  }
    -  return styleSheet;
    -};
    -
    -
    -/**
    - * Removes the styles added by {@link #installStyles}.
    - * @param {Element|StyleSheet} styleSheet The value returned by
    - *     {@link #installStyles}.
    - */
    -goog.style.uninstallStyles = function(styleSheet) {
    -  var node = styleSheet.ownerNode || styleSheet.owningElement ||
    -      /** @type {Element} */ (styleSheet);
    -  goog.dom.removeNode(node);
    -};
    -
    -
    -/**
    - * Sets the content of a style element.  The style element can be any valid
    - * style element.  This element will have its content completely replaced by
    - * the new stylesString.
    - * @param {Element|StyleSheet} element A stylesheet element as returned by
    - *     installStyles.
    - * @param {string} stylesString The new content of the stylesheet.
    - */
    -goog.style.setStyles = function(element, stylesString) {
    -  if (goog.userAgent.IE && goog.isDef(element.cssText)) {
    -    // Adding the selectors individually caused the browser to hang if the
    -    // selector was invalid or there were CSS comments.  Setting the cssText of
    -    // the style node works fine and ignores CSS that IE doesn't understand.
    -    // However IE >= 11 doesn't support cssText any more, so we make sure that
    -    // cssText is a defined property and otherwise fall back to innerHTML.
    -    element.cssText = stylesString;
    -  } else {
    -    element.innerHTML = stylesString;
    -  }
    -};
    -
    -
    -/**
    - * Sets 'white-space: pre-wrap' for a node (x-browser).
    - *
    - * There are as many ways of specifying pre-wrap as there are browsers.
    - *
    - * CSS3/IE8: white-space: pre-wrap;
    - * Mozilla:  white-space: -moz-pre-wrap;
    - * Opera:    white-space: -o-pre-wrap;
    - * IE6/7:    white-space: pre; word-wrap: break-word;
    - *
    - * @param {Element} el Element to enable pre-wrap for.
    - */
    -goog.style.setPreWrap = function(el) {
    -  var style = el.style;
    -  if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('8')) {
    -    style.whiteSpace = 'pre';
    -    style.wordWrap = 'break-word';
    -  } else if (goog.userAgent.GECKO) {
    -    style.whiteSpace = '-moz-pre-wrap';
    -  } else {
    -    style.whiteSpace = 'pre-wrap';
    -  }
    -};
    -
    -
    -/**
    - * Sets 'display: inline-block' for an element (cross-browser).
    - * @param {Element} el Element to which the inline-block display style is to be
    - *    applied.
    - * @see ../demos/inline_block_quirks.html
    - * @see ../demos/inline_block_standards.html
    - */
    -goog.style.setInlineBlock = function(el) {
    -  var style = el.style;
    -  // Without position:relative, weirdness ensues.  Just accept it and move on.
    -  style.position = 'relative';
    -
    -  if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('8')) {
    -    // IE8 supports inline-block so fall through to the else
    -    // Zoom:1 forces hasLayout, display:inline gives inline behavior.
    -    style.zoom = '1';
    -    style.display = 'inline';
    -  } else {
    -    // Opera, Webkit, and Safari seem to do OK with the standard inline-block
    -    // style.
    -    style.display = 'inline-block';
    -  }
    -};
    -
    -
    -/**
    - * Returns true if the element is using right to left (rtl) direction.
    - * @param {Element} el  The element to test.
    - * @return {boolean} True for right to left, false for left to right.
    - */
    -goog.style.isRightToLeft = function(el) {
    -  return 'rtl' == goog.style.getStyle_(el, 'direction');
    -};
    -
    -
    -/**
    - * The CSS style property corresponding to an element being
    - * unselectable on the current browser platform (null if none).
    - * Opera and IE instead use a DOM attribute 'unselectable'.
    - * @type {?string}
    - * @private
    - */
    -goog.style.unselectableStyle_ =
    -    goog.userAgent.GECKO ? 'MozUserSelect' :
    -    goog.userAgent.WEBKIT ? 'WebkitUserSelect' :
    -    null;
    -
    -
    -/**
    - * Returns true if the element is set to be unselectable, false otherwise.
    - * Note that on some platforms (e.g. Mozilla), even if an element isn't set
    - * to be unselectable, it will behave as such if any of its ancestors is
    - * unselectable.
    - * @param {Element} el  Element to check.
    - * @return {boolean}  Whether the element is set to be unselectable.
    - */
    -goog.style.isUnselectable = function(el) {
    -  if (goog.style.unselectableStyle_) {
    -    return el.style[goog.style.unselectableStyle_].toLowerCase() == 'none';
    -  } else if (goog.userAgent.IE || goog.userAgent.OPERA) {
    -    return el.getAttribute('unselectable') == 'on';
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Makes the element and its descendants selectable or unselectable.  Note
    - * that on some platforms (e.g. Mozilla), even if an element isn't set to
    - * be unselectable, it will behave as such if any of its ancestors is
    - * unselectable.
    - * @param {Element} el  The element to alter.
    - * @param {boolean} unselectable  Whether the element and its descendants
    - *     should be made unselectable.
    - * @param {boolean=} opt_noRecurse  Whether to only alter the element's own
    - *     selectable state, and leave its descendants alone; defaults to false.
    - */
    -goog.style.setUnselectable = function(el, unselectable, opt_noRecurse) {
    -  // TODO(attila): Do we need all of TR_DomUtil.makeUnselectable() in Closure?
    -  var descendants = !opt_noRecurse ? el.getElementsByTagName('*') : null;
    -  var name = goog.style.unselectableStyle_;
    -  if (name) {
    -    // Add/remove the appropriate CSS style to/from the element and its
    -    // descendants.
    -    var value = unselectable ? 'none' : '';
    -    el.style[name] = value;
    -    if (descendants) {
    -      for (var i = 0, descendant; descendant = descendants[i]; i++) {
    -        descendant.style[name] = value;
    -      }
    -    }
    -  } else if (goog.userAgent.IE || goog.userAgent.OPERA) {
    -    // Toggle the 'unselectable' attribute on the element and its descendants.
    -    var value = unselectable ? 'on' : '';
    -    el.setAttribute('unselectable', value);
    -    if (descendants) {
    -      for (var i = 0, descendant; descendant = descendants[i]; i++) {
    -        descendant.setAttribute('unselectable', value);
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Gets the border box size for an element.
    - * @param {Element} element  The element to get the size for.
    - * @return {!goog.math.Size} The border box size.
    - */
    -goog.style.getBorderBoxSize = function(element) {
    -  return new goog.math.Size(element.offsetWidth, element.offsetHeight);
    -};
    -
    -
    -/**
    - * Sets the border box size of an element. This is potentially expensive in IE
    - * if the document is CSS1Compat mode
    - * @param {Element} element  The element to set the size on.
    - * @param {goog.math.Size} size  The new size.
    - */
    -goog.style.setBorderBoxSize = function(element, size) {
    -  var doc = goog.dom.getOwnerDocument(element);
    -  var isCss1CompatMode = goog.dom.getDomHelper(doc).isCss1CompatMode();
    -
    -  if (goog.userAgent.IE &&
    -      !goog.userAgent.isVersionOrHigher('10') &&
    -      (!isCss1CompatMode || !goog.userAgent.isVersionOrHigher('8'))) {
    -    var style = element.style;
    -    if (isCss1CompatMode) {
    -      var paddingBox = goog.style.getPaddingBox(element);
    -      var borderBox = goog.style.getBorderBox(element);
    -      style.pixelWidth = size.width - borderBox.left - paddingBox.left -
    -                         paddingBox.right - borderBox.right;
    -      style.pixelHeight = size.height - borderBox.top - paddingBox.top -
    -                          paddingBox.bottom - borderBox.bottom;
    -    } else {
    -      style.pixelWidth = size.width;
    -      style.pixelHeight = size.height;
    -    }
    -  } else {
    -    goog.style.setBoxSizingSize_(element, size, 'border-box');
    -  }
    -};
    -
    -
    -/**
    - * Gets the content box size for an element.  This is potentially expensive in
    - * all browsers.
    - * @param {Element} element  The element to get the size for.
    - * @return {!goog.math.Size} The content box size.
    - */
    -goog.style.getContentBoxSize = function(element) {
    -  var doc = goog.dom.getOwnerDocument(element);
    -  var ieCurrentStyle = goog.userAgent.IE && element.currentStyle;
    -  if (ieCurrentStyle &&
    -      goog.dom.getDomHelper(doc).isCss1CompatMode() &&
    -      ieCurrentStyle.width != 'auto' && ieCurrentStyle.height != 'auto' &&
    -      !ieCurrentStyle.boxSizing) {
    -    // If IE in CSS1Compat mode than just use the width and height.
    -    // If we have a boxSizing then fall back on measuring the borders etc.
    -    var width = goog.style.getIePixelValue_(element, ieCurrentStyle.width,
    -                                            'width', 'pixelWidth');
    -    var height = goog.style.getIePixelValue_(element, ieCurrentStyle.height,
    -                                             'height', 'pixelHeight');
    -    return new goog.math.Size(width, height);
    -  } else {
    -    var borderBoxSize = goog.style.getBorderBoxSize(element);
    -    var paddingBox = goog.style.getPaddingBox(element);
    -    var borderBox = goog.style.getBorderBox(element);
    -    return new goog.math.Size(borderBoxSize.width -
    -                              borderBox.left - paddingBox.left -
    -                              paddingBox.right - borderBox.right,
    -                              borderBoxSize.height -
    -                              borderBox.top - paddingBox.top -
    -                              paddingBox.bottom - borderBox.bottom);
    -  }
    -};
    -
    -
    -/**
    - * Sets the content box size of an element. This is potentially expensive in IE
    - * if the document is BackCompat mode.
    - * @param {Element} element  The element to set the size on.
    - * @param {goog.math.Size} size  The new size.
    - */
    -goog.style.setContentBoxSize = function(element, size) {
    -  var doc = goog.dom.getOwnerDocument(element);
    -  var isCss1CompatMode = goog.dom.getDomHelper(doc).isCss1CompatMode();
    -  if (goog.userAgent.IE &&
    -      !goog.userAgent.isVersionOrHigher('10') &&
    -      (!isCss1CompatMode || !goog.userAgent.isVersionOrHigher('8'))) {
    -    var style = element.style;
    -    if (isCss1CompatMode) {
    -      style.pixelWidth = size.width;
    -      style.pixelHeight = size.height;
    -    } else {
    -      var paddingBox = goog.style.getPaddingBox(element);
    -      var borderBox = goog.style.getBorderBox(element);
    -      style.pixelWidth = size.width + borderBox.left + paddingBox.left +
    -                         paddingBox.right + borderBox.right;
    -      style.pixelHeight = size.height + borderBox.top + paddingBox.top +
    -                          paddingBox.bottom + borderBox.bottom;
    -    }
    -  } else {
    -    goog.style.setBoxSizingSize_(element, size, 'content-box');
    -  }
    -};
    -
    -
    -/**
    - * Helper function that sets the box sizing as well as the width and height
    - * @param {Element} element  The element to set the size on.
    - * @param {goog.math.Size} size  The new size to set.
    - * @param {string} boxSizing  The box-sizing value.
    - * @private
    - */
    -goog.style.setBoxSizingSize_ = function(element, size, boxSizing) {
    -  var style = element.style;
    -  if (goog.userAgent.GECKO) {
    -    style.MozBoxSizing = boxSizing;
    -  } else if (goog.userAgent.WEBKIT) {
    -    style.WebkitBoxSizing = boxSizing;
    -  } else {
    -    // Includes IE8 and Opera 9.50+
    -    style.boxSizing = boxSizing;
    -  }
    -
    -  // Setting this to a negative value will throw an exception on IE
    -  // (and doesn't do anything different than setting it to 0).
    -  style.width = Math.max(size.width, 0) + 'px';
    -  style.height = Math.max(size.height, 0) + 'px';
    -};
    -
    -
    -/**
    - * IE specific function that converts a non pixel unit to pixels.
    - * @param {Element} element  The element to convert the value for.
    - * @param {string} value  The current value as a string. The value must not be
    - *     ''.
    - * @param {string} name  The CSS property name to use for the converstion. This
    - *     should be 'left', 'top', 'width' or 'height'.
    - * @param {string} pixelName  The CSS pixel property name to use to get the
    - *     value in pixels.
    - * @return {number} The value in pixels.
    - * @private
    - */
    -goog.style.getIePixelValue_ = function(element, value, name, pixelName) {
    -  // Try if we already have a pixel value. IE does not do half pixels so we
    -  // only check if it matches a number followed by 'px'.
    -  if (/^\d+px?$/.test(value)) {
    -    return parseInt(value, 10);
    -  } else {
    -    var oldStyleValue = element.style[name];
    -    var oldRuntimeValue = element.runtimeStyle[name];
    -    // set runtime style to prevent changes
    -    element.runtimeStyle[name] = element.currentStyle[name];
    -    element.style[name] = value;
    -    var pixelValue = element.style[pixelName];
    -    // restore
    -    element.style[name] = oldStyleValue;
    -    element.runtimeStyle[name] = oldRuntimeValue;
    -    return pixelValue;
    -  }
    -};
    -
    -
    -/**
    - * Helper function for getting the pixel padding or margin for IE.
    - * @param {Element} element  The element to get the padding for.
    - * @param {string} propName  The property name.
    - * @return {number} The pixel padding.
    - * @private
    - */
    -goog.style.getIePixelDistance_ = function(element, propName) {
    -  var value = goog.style.getCascadedStyle(element, propName);
    -  return value ?
    -      goog.style.getIePixelValue_(element, value, 'left', 'pixelLeft') : 0;
    -};
    -
    -
    -/**
    - * Gets the computed paddings or margins (on all sides) in pixels.
    - * @param {Element} element  The element to get the padding for.
    - * @param {string} stylePrefix  Pass 'padding' to retrieve the padding box,
    - *     or 'margin' to retrieve the margin box.
    - * @return {!goog.math.Box} The computed paddings or margins.
    - * @private
    - */
    -goog.style.getBox_ = function(element, stylePrefix) {
    -  if (goog.userAgent.IE) {
    -    var left = goog.style.getIePixelDistance_(element, stylePrefix + 'Left');
    -    var right = goog.style.getIePixelDistance_(element, stylePrefix + 'Right');
    -    var top = goog.style.getIePixelDistance_(element, stylePrefix + 'Top');
    -    var bottom = goog.style.getIePixelDistance_(
    -        element, stylePrefix + 'Bottom');
    -    return new goog.math.Box(top, right, bottom, left);
    -  } else {
    -    // On non-IE browsers, getComputedStyle is always non-null.
    -    var left = /** @type {string} */ (
    -        goog.style.getComputedStyle(element, stylePrefix + 'Left'));
    -    var right = /** @type {string} */ (
    -        goog.style.getComputedStyle(element, stylePrefix + 'Right'));
    -    var top = /** @type {string} */ (
    -        goog.style.getComputedStyle(element, stylePrefix + 'Top'));
    -    var bottom = /** @type {string} */ (
    -        goog.style.getComputedStyle(element, stylePrefix + 'Bottom'));
    -
    -    // NOTE(arv): Gecko can return floating point numbers for the computed
    -    // style values.
    -    return new goog.math.Box(parseFloat(top),
    -                             parseFloat(right),
    -                             parseFloat(bottom),
    -                             parseFloat(left));
    -  }
    -};
    -
    -
    -/**
    - * Gets the computed paddings (on all sides) in pixels.
    - * @param {Element} element  The element to get the padding for.
    - * @return {!goog.math.Box} The computed paddings.
    - */
    -goog.style.getPaddingBox = function(element) {
    -  return goog.style.getBox_(element, 'padding');
    -};
    -
    -
    -/**
    - * Gets the computed margins (on all sides) in pixels.
    - * @param {Element} element  The element to get the margins for.
    - * @return {!goog.math.Box} The computed margins.
    - */
    -goog.style.getMarginBox = function(element) {
    -  return goog.style.getBox_(element, 'margin');
    -};
    -
    -
    -/**
    - * A map used to map the border width keywords to a pixel width.
    - * @type {Object}
    - * @private
    - */
    -goog.style.ieBorderWidthKeywords_ = {
    -  'thin': 2,
    -  'medium': 4,
    -  'thick': 6
    -};
    -
    -
    -/**
    - * Helper function for IE to get the pixel border.
    - * @param {Element} element  The element to get the pixel border for.
    - * @param {string} prop  The part of the property name.
    - * @return {number} The value in pixels.
    - * @private
    - */
    -goog.style.getIePixelBorder_ = function(element, prop) {
    -  if (goog.style.getCascadedStyle(element, prop + 'Style') == 'none') {
    -    return 0;
    -  }
    -  var width = goog.style.getCascadedStyle(element, prop + 'Width');
    -  if (width in goog.style.ieBorderWidthKeywords_) {
    -    return goog.style.ieBorderWidthKeywords_[width];
    -  }
    -  return goog.style.getIePixelValue_(element, width, 'left', 'pixelLeft');
    -};
    -
    -
    -/**
    - * Gets the computed border widths (on all sides) in pixels
    - * @param {Element} element  The element to get the border widths for.
    - * @return {!goog.math.Box} The computed border widths.
    - */
    -goog.style.getBorderBox = function(element) {
    -  if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9)) {
    -    var left = goog.style.getIePixelBorder_(element, 'borderLeft');
    -    var right = goog.style.getIePixelBorder_(element, 'borderRight');
    -    var top = goog.style.getIePixelBorder_(element, 'borderTop');
    -    var bottom = goog.style.getIePixelBorder_(element, 'borderBottom');
    -    return new goog.math.Box(top, right, bottom, left);
    -  } else {
    -    // On non-IE browsers, getComputedStyle is always non-null.
    -    var left = /** @type {string} */ (
    -        goog.style.getComputedStyle(element, 'borderLeftWidth'));
    -    var right = /** @type {string} */ (
    -        goog.style.getComputedStyle(element, 'borderRightWidth'));
    -    var top = /** @type {string} */ (
    -        goog.style.getComputedStyle(element, 'borderTopWidth'));
    -    var bottom = /** @type {string} */ (
    -        goog.style.getComputedStyle(element, 'borderBottomWidth'));
    -
    -    return new goog.math.Box(parseFloat(top),
    -                             parseFloat(right),
    -                             parseFloat(bottom),
    -                             parseFloat(left));
    -  }
    -};
    -
    -
    -/**
    - * Returns the font face applied to a given node. Opera and IE should return
    - * the font actually displayed. Firefox returns the author's most-preferred
    - * font (whether the browser is capable of displaying it or not.)
    - * @param {Element} el  The element whose font family is returned.
    - * @return {string} The font family applied to el.
    - */
    -goog.style.getFontFamily = function(el) {
    -  var doc = goog.dom.getOwnerDocument(el);
    -  var font = '';
    -  // The moveToElementText method from the TextRange only works if the element
    -  // is attached to the owner document.
    -  if (doc.body.createTextRange && goog.dom.contains(doc, el)) {
    -    var range = doc.body.createTextRange();
    -    range.moveToElementText(el);
    -    /** @preserveTry */
    -    try {
    -      font = range.queryCommandValue('FontName');
    -    } catch (e) {
    -      // This is a workaround for a awkward exception.
    -      // On some IE, there is an exception coming from it.
    -      // The error description from this exception is:
    -      // This window has already been registered as a drop target
    -      // This is bogus description, likely due to a bug in ie.
    -      font = '';
    -    }
    -  }
    -  if (!font) {
    -    // Note if for some reason IE can't derive FontName with a TextRange, we
    -    // fallback to using currentStyle
    -    font = goog.style.getStyle_(el, 'fontFamily');
    -  }
    -
    -  // Firefox returns the applied font-family string (author's list of
    -  // preferred fonts.) We want to return the most-preferred font, in lieu of
    -  // the *actually* applied font.
    -  var fontsArray = font.split(',');
    -  if (fontsArray.length > 1) font = fontsArray[0];
    -
    -  // Sanitize for x-browser consistency:
    -  // Strip quotes because browsers aren't consistent with how they're
    -  // applied; Opera always encloses, Firefox sometimes, and IE never.
    -  return goog.string.stripQuotes(font, '"\'');
    -};
    -
    -
    -/**
    - * Regular expression used for getLengthUnits.
    - * @type {RegExp}
    - * @private
    - */
    -goog.style.lengthUnitRegex_ = /[^\d]+$/;
    -
    -
    -/**
    - * Returns the units used for a CSS length measurement.
    - * @param {string} value  A CSS length quantity.
    - * @return {?string} The units of measurement.
    - */
    -goog.style.getLengthUnits = function(value) {
    -  var units = value.match(goog.style.lengthUnitRegex_);
    -  return units && units[0] || null;
    -};
    -
    -
    -/**
    - * Map of absolute CSS length units
    - * @type {Object}
    - * @private
    - */
    -goog.style.ABSOLUTE_CSS_LENGTH_UNITS_ = {
    -  'cm' : 1,
    -  'in' : 1,
    -  'mm' : 1,
    -  'pc' : 1,
    -  'pt' : 1
    -};
    -
    -
    -/**
    - * Map of relative CSS length units that can be accurately converted to px
    - * font-size values using getIePixelValue_. Only units that are defined in
    - * relation to a font size are convertible (%, small, etc. are not).
    - * @type {Object}
    - * @private
    - */
    -goog.style.CONVERTIBLE_RELATIVE_CSS_UNITS_ = {
    -  'em' : 1,
    -  'ex' : 1
    -};
    -
    -
    -/**
    - * Returns the font size, in pixels, of text in an element.
    - * @param {Element} el  The element whose font size is returned.
    - * @return {number} The font size (in pixels).
    - */
    -goog.style.getFontSize = function(el) {
    -  var fontSize = goog.style.getStyle_(el, 'fontSize');
    -  var sizeUnits = goog.style.getLengthUnits(fontSize);
    -  if (fontSize && 'px' == sizeUnits) {
    -    // NOTE(user): This could be parseFloat instead, but IE doesn't return
    -    // decimal fractions in getStyle_ and Firefox reports the fractions, but
    -    // ignores them when rendering. Interestingly enough, when we force the
    -    // issue and size something to e.g., 50% of 25px, the browsers round in
    -    // opposite directions with Firefox reporting 12px and IE 13px. I punt.
    -    return parseInt(fontSize, 10);
    -  }
    -
    -  // In IE, we can convert absolute length units to a px value using
    -  // goog.style.getIePixelValue_. Units defined in relation to a font size
    -  // (em, ex) are applied relative to the element's parentNode and can also
    -  // be converted.
    -  if (goog.userAgent.IE) {
    -    if (sizeUnits in goog.style.ABSOLUTE_CSS_LENGTH_UNITS_) {
    -      return goog.style.getIePixelValue_(el,
    -                                         fontSize,
    -                                         'left',
    -                                         'pixelLeft');
    -    } else if (el.parentNode &&
    -               el.parentNode.nodeType == goog.dom.NodeType.ELEMENT &&
    -               sizeUnits in goog.style.CONVERTIBLE_RELATIVE_CSS_UNITS_) {
    -      // Check the parent size - if it is the same it means the relative size
    -      // value is inherited and we therefore don't want to count it twice.  If
    -      // it is different, this element either has explicit style or has a CSS
    -      // rule applying to it.
    -      var parentElement = /** @type {!Element} */ (el.parentNode);
    -      var parentSize = goog.style.getStyle_(parentElement, 'fontSize');
    -      return goog.style.getIePixelValue_(parentElement,
    -                                         fontSize == parentSize ?
    -                                             '1em' : fontSize,
    -                                         'left',
    -                                         'pixelLeft');
    -    }
    -  }
    -
    -  // Sometimes we can't cleanly find the font size (some units relative to a
    -  // node's parent's font size are difficult: %, smaller et al), so we create
    -  // an invisible, absolutely-positioned span sized to be the height of an 'M'
    -  // rendered in its parent's (i.e., our target element's) font size. This is
    -  // the definition of CSS's font size attribute.
    -  var sizeElement = goog.dom.createDom(
    -      'span',
    -      {'style': 'visibility:hidden;position:absolute;' +
    -            'line-height:0;padding:0;margin:0;border:0;height:1em;'});
    -  goog.dom.appendChild(el, sizeElement);
    -  fontSize = sizeElement.offsetHeight;
    -  goog.dom.removeNode(sizeElement);
    -
    -  return fontSize;
    -};
    -
    -
    -/**
    - * Parses a style attribute value.  Converts CSS property names to camel case.
    - * @param {string} value The style attribute value.
    - * @return {!Object} Map of CSS properties to string values.
    - */
    -goog.style.parseStyleAttribute = function(value) {
    -  var result = {};
    -  goog.array.forEach(value.split(/\s*;\s*/), function(pair) {
    -    var keyValue = pair.split(/\s*:\s*/);
    -    if (keyValue.length == 2) {
    -      result[goog.string.toCamelCase(keyValue[0].toLowerCase())] = keyValue[1];
    -    }
    -  });
    -  return result;
    -};
    -
    -
    -/**
    - * Reverse of parseStyleAttribute; that is, takes a style object and returns the
    - * corresponding attribute value.  Converts camel case property names to proper
    - * CSS selector names.
    - * @param {Object} obj Map of CSS properties to values.
    - * @return {string} The style attribute value.
    - */
    -goog.style.toStyleAttribute = function(obj) {
    -  var buffer = [];
    -  goog.object.forEach(obj, function(value, key) {
    -    buffer.push(goog.string.toSelectorCase(key), ':', value, ';');
    -  });
    -  return buffer.join('');
    -};
    -
    -
    -/**
    - * Sets CSS float property on an element.
    - * @param {Element} el The element to set float property on.
    - * @param {string} value The value of float CSS property to set on this element.
    - */
    -goog.style.setFloat = function(el, value) {
    -  el.style[goog.userAgent.IE ? 'styleFloat' : 'cssFloat'] = value;
    -};
    -
    -
    -/**
    - * Gets value of explicitly-set float CSS property on an element.
    - * @param {Element} el The element to get float property of.
    - * @return {string} The value of explicitly-set float CSS property on this
    - *     element.
    - */
    -goog.style.getFloat = function(el) {
    -  return el.style[goog.userAgent.IE ? 'styleFloat' : 'cssFloat'] || '';
    -};
    -
    -
    -/**
    - * Returns the scroll bar width (represents the width of both horizontal
    - * and vertical scroll).
    - *
    - * @param {string=} opt_className An optional class name (or names) to apply
    - *     to the invisible div created to measure the scrollbar. This is necessary
    - *     if some scrollbars are styled differently than others.
    - * @return {number} The scroll bar width in px.
    - */
    -goog.style.getScrollbarWidth = function(opt_className) {
    -  // Add two hidden divs.  The child div is larger than the parent and
    -  // forces scrollbars to appear on it.
    -  // Using overflow:scroll does not work consistently with scrollbars that
    -  // are styled with ::-webkit-scrollbar.
    -  var outerDiv = goog.dom.createElement('div');
    -  if (opt_className) {
    -    outerDiv.className = opt_className;
    -  }
    -  outerDiv.style.cssText = 'overflow:auto;' +
    -      'position:absolute;top:0;width:100px;height:100px';
    -  var innerDiv = goog.dom.createElement('div');
    -  goog.style.setSize(innerDiv, '200px', '200px');
    -  outerDiv.appendChild(innerDiv);
    -  goog.dom.appendChild(goog.dom.getDocument().body, outerDiv);
    -  var width = outerDiv.offsetWidth - outerDiv.clientWidth;
    -  goog.dom.removeNode(outerDiv);
    -  return width;
    -};
    -
    -
    -/**
    - * Regular expression to extract x and y translation components from a CSS
    - * transform Matrix representation.
    - *
    - * @type {!RegExp}
    - * @const
    - * @private
    - */
    -goog.style.MATRIX_TRANSLATION_REGEX_ =
    -    new RegExp('matrix\\([0-9\\.\\-]+, [0-9\\.\\-]+, ' +
    -               '[0-9\\.\\-]+, [0-9\\.\\-]+, ' +
    -               '([0-9\\.\\-]+)p?x?, ([0-9\\.\\-]+)p?x?\\)');
    -
    -
    -/**
    - * Returns the x,y translation component of any CSS transforms applied to the
    - * element, in pixels.
    - *
    - * @param {!Element} element The element to get the translation of.
    - * @return {!goog.math.Coordinate} The CSS translation of the element in px.
    - */
    -goog.style.getCssTranslation = function(element) {
    -  var transform = goog.style.getComputedTransform(element);
    -  if (!transform) {
    -    return new goog.math.Coordinate(0, 0);
    -  }
    -  var matches = transform.match(goog.style.MATRIX_TRANSLATION_REGEX_);
    -  if (!matches) {
    -    return new goog.math.Coordinate(0, 0);
    -  }
    -  return new goog.math.Coordinate(parseFloat(matches[1]),
    -                                  parseFloat(matches[2]));
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/style/style_document_scroll_test.html b/src/database/third_party/closure-library/closure/goog/style/style_document_scroll_test.html
    deleted file mode 100644
    index 9bd1a44344f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/style/style_document_scroll_test.html
    +++ /dev/null
    @@ -1,45 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<title>Closure Unit Tests - goog.style</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.style.style_document_scroll_test');
    -</script>
    -<style>
    -  body, html {
    -    height: 100%;
    -    margin: 0;
    -    padding: 0;
    -    position: absolute;
    -    white-space: nowrap;
    -    width: 800px;
    -  }
    -
    -  #testEl1 {
    -    background: lightblue;
    -    height: 110%;
    -    margin-top: 200px;
    -  }
    -
    -  #testEl2 {
    -    background: lightblue;
    -    display: inline-block;
    -    margin-left: 300px;
    -    width: 5000px;
    -  }
    -</style>
    -</head>
    -<body>
    -  <div id="testEl1">
    -    Test Element2
    -  </div>
    -  <div id="testEl2">Test Element4</div>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/style/style_document_scroll_test.js b/src/database/third_party/closure-library/closure/goog/style/style_document_scroll_test.js
    deleted file mode 100644
    index abd29fe63ad..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/style/style_document_scroll_test.js
    +++ /dev/null
    @@ -1,188 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.style.style_document_scroll_test');
    -goog.setTestOnly('goog.style.style_document_scroll_test');
    -
    -goog.require('goog.dom');
    -goog.require('goog.style');
    -goog.require('goog.testing.jsunit');
    -
    -
    -var EPSILON = 2;
    -var body;
    -var html;
    -
    -function setUp() {
    -  body = document.body;
    -  setUpElement(body);
    -  html = document.documentElement;
    -  setUpElement(html);
    -}
    -
    -
    -function setUpElement(element) {
    -  element.scrollTop = 100;
    -  element.scrollLeft = 100;
    -}
    -
    -
    -function tearDown() {
    -  tearDownElement(body);
    -  tearDownElement(html);
    -}
    -
    -
    -function tearDownElement(element) {
    -  element.style.border = '';
    -  element.style.padding = '';
    -  element.style.margin = '';
    -  element.scrollTop = 0;
    -  element.scrollLeft = 0;
    -}
    -
    -
    -
    -function testDocumentScrollWithZeroedBodyProperties() {
    -  assertRoughlyEquals(200,
    -      goog.style.getContainerOffsetToScrollInto(
    -          goog.dom.getElement('testEl1'), body).y,
    -      EPSILON);
    -  assertRoughlyEquals(300,
    -      goog.style.getContainerOffsetToScrollInto(
    -          goog.dom.getElement('testEl2'), body).x,
    -      EPSILON);
    -}
    -
    -
    -function testHtmlScrollWithZeroedBodyProperties() {
    -  assertRoughlyEquals(200,
    -      goog.style.getContainerOffsetToScrollInto(
    -          goog.dom.getElement('testEl1'), html).y,
    -      EPSILON);
    -  assertRoughlyEquals(300,
    -      goog.style.getContainerOffsetToScrollInto(
    -          goog.dom.getElement('testEl2'), html).x,
    -      EPSILON);
    -}
    -
    -
    -function testDocumentScrollWithMargin() {
    -  body.style.margin = '20px 0 0 30px';
    -  assertRoughlyEquals(220,
    -      goog.style.getContainerOffsetToScrollInto(
    -          goog.dom.getElement('testEl1'), body).y,
    -      EPSILON);
    -  assertRoughlyEquals(330,
    -      goog.style.getContainerOffsetToScrollInto(
    -          goog.dom.getElement('testEl2'), body).x,
    -      EPSILON);
    -}
    -
    -
    -function testHtmlScrollWithMargin() {
    -  html.style.margin = '20px 0 0 30px';
    -  assertRoughlyEquals(220,
    -      goog.style.getContainerOffsetToScrollInto(
    -          goog.dom.getElement('testEl1'), html).y,
    -      EPSILON);
    -  assertRoughlyEquals(330,
    -      goog.style.getContainerOffsetToScrollInto(
    -          goog.dom.getElement('testEl2'), html).x,
    -      EPSILON);
    -}
    -
    -
    -
    -function testDocumentScrollWithPadding() {
    -  body.style.padding = '20px 0 0 30px';
    -  assertRoughlyEquals(220,
    -      goog.style.getContainerOffsetToScrollInto(
    -          goog.dom.getElement('testEl1'), body).y,
    -      EPSILON);
    -  assertRoughlyEquals(330,
    -      goog.style.getContainerOffsetToScrollInto(
    -          goog.dom.getElement('testEl2'), body).x,
    -      EPSILON);
    -}
    -
    -
    -function testHtmlScrollWithPadding() {
    -  html.style.padding = '20px 0 0 30px';
    -  assertRoughlyEquals(220,
    -      goog.style.getContainerOffsetToScrollInto(
    -          goog.dom.getElement('testEl1'), html).y,
    -      EPSILON);
    -  assertRoughlyEquals(330,
    -      goog.style.getContainerOffsetToScrollInto(
    -          goog.dom.getElement('testEl2'), html).x,
    -      EPSILON);
    -}
    -
    -
    -function testDocumentScrollWithBorder() {
    -  body.style.border = '20px solid green';
    -  assertRoughlyEquals(220,
    -      goog.style.getContainerOffsetToScrollInto(
    -          goog.dom.getElement('testEl1'), body).y,
    -      EPSILON);
    -  assertRoughlyEquals(320,
    -      goog.style.getContainerOffsetToScrollInto(
    -          goog.dom.getElement('testEl2'), body).x,
    -      EPSILON);
    -}
    -
    -
    -function testHtmlScrollWithBorder() {
    -  html.style.border = '20px solid green';
    -  assertRoughlyEquals(220,
    -      goog.style.getContainerOffsetToScrollInto(
    -          goog.dom.getElement('testEl1'), html).y,
    -      EPSILON);
    -  assertRoughlyEquals(320,
    -      goog.style.getContainerOffsetToScrollInto(
    -          goog.dom.getElement('testEl2'), html).x,
    -      EPSILON);
    -}
    -
    -
    -function testDocumentScrollWithAllProperties() {
    -  body.style.margin = '20px 0 0 30px';
    -  body.style.padding = '40px 0 0 50px';
    -  body.style.border = '10px solid green';
    -  assertRoughlyEquals(270,
    -      goog.style.getContainerOffsetToScrollInto(
    -          goog.dom.getElement('testEl1'), body).y,
    -      EPSILON);
    -  assertRoughlyEquals(390,
    -      goog.style.getContainerOffsetToScrollInto(
    -          goog.dom.getElement('testEl2'), body).x,
    -      EPSILON);
    -}
    -
    -
    -function testHtmlScrollWithAllProperties() {
    -  html.style.margin = '20px 0 0 30px';
    -  html.style.padding = '40px 0 0 50px';
    -  html.style.border = '10px solid green';
    -  assertRoughlyEquals(270,
    -      goog.style.getContainerOffsetToScrollInto(
    -          goog.dom.getElement('testEl1'), html).y,
    -      EPSILON);
    -  assertRoughlyEquals(390,
    -      goog.style.getContainerOffsetToScrollInto(
    -          goog.dom.getElement('testEl2'), html).x,
    -      EPSILON);
    -}
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/style/style_quirks_test.html b/src/database/third_party/closure-library/closure/goog/style/style_quirks_test.html
    deleted file mode 100644
    index e23ebccb4c8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/style/style_quirks_test.html
    +++ /dev/null
    @@ -1,538 +0,0 @@
    -<!-- BackCompat -->
    -<!--
    -
    -  This is a copy of style_test.html but without a doctype. Make sure these two
    -  are in sync.
    -
    --->
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta name="viewport" content="width=device-width, initial-scale=1.0,
    -    maximum-scale=1.0, minimum-scale=1.0, user-scalable=0">
    -<title>Closure Unit Tests - goog.dom.style</title>
    -<script src="../base.js"></script>
    -<script>goog.require('goog.userAgent');</script>
    -<style>
    -
    -* {
    -  box-sizing: border-box;
    -  -moz-box-sizing: border-box;
    -  -webkit-box-sizing: border-box;
    -}
    -
    -</style>
    -<style>
    -
    -i {
    -  font-family: Times, sans-serif;
    -  font-size: 5em;
    -}
    -
    -#testEl5 {
    -  display: none;
    -}
    -
    -#styleTest1 {
    -  width: 120px;
    -  text-decoration: underline;
    -}
    -
    -#bgcolorTest0 {
    -  background-color: #f00;
    -}
    -
    -#bgcolorTest1 {
    -  background-color: #ff0000;
    -}
    -
    -#bgcolorTest2 {
    -  background-color: rgb(255, 0, 0);
    -}
    -
    -#bgcolorTest3 {
    -  background-color: rgb(100%, 0%, 0%);
    -}
    -
    -#bgcolorTest5 {
    -  background-color: lightblue;
    -}
    -
    -#bgcolorTest6 {
    -  background-color: inherit;
    -}
    -
    -#bgcolorTest7 {
    -  background-color: transparent;
    -}
    -
    -.rtl {
    -  direction: rtl;
    -}
    -
    -.ltr {
    -  direction: ltr;
    -}
    -
    -#pos-scroll-abs {
    -  position: absolute;
    -  top: 200px;
    -  left: 100px;
    -}
    -
    -#pos-scroll-abs-1 {
    -  overflow: scroll;
    -  width: 100px;
    -  height: 100px;
    -}
    -
    -#pos-scroll-abs-2 {
    -  position: absolute;
    -  top: 100px;
    -  left: 100px;
    -  width: 500px;
    -  background-color: pink;
    -}
    -
    -#abs-upper-left {
    -  position: absolute;
    -  top: 0px;
    -  left: 0px;
    -}
    -
    -#no-text-font-styles {
    -  font-family: "Helvetica", Times, serif;
    -  font-size: 30px;
    -}
    -
    -.century {
    -  font-family: "Comic Sans MS", "Century Schoolbook L", serif;
    -}
    -
    -#size-a,
    -#size-e {
    -  width: 100px;
    -  height: 100px;
    -  background: red;
    -  padding: 0;
    -  border-style: solid;
    -  border-color: black;
    -  border-width: 0;
    -}
    -
    -#size-b {
    -  width: 100px;
    -  height: 100px;
    -  background: red;
    -  border: 10px solid black;
    -}
    -
    -#size-c {
    -  width: 100px;
    -  height: 100px;
    -  background: red;
    -  border: 10px solid black;
    -  padding: 10px;
    -  overflow: auto;
    -}
    -
    -#size-d {
    -  width: 10em;
    -  height: 2cm;
    -  background: red;
    -  border: thick solid black;
    -  padding: 2mm;
    -}
    -
    -#size-f {
    -  border-width: 0;
    -  margin: 0;
    -  padding: 0;
    -}
    -
    -#css-position-absolute {
    -  position: absolute;
    -}
    -
    -#css-overflow-hidden {
    -  overflow: hidden;
    -}
    -
    -#css-z-index-200 {
    -  position:relative;
    -  z-index: 200;
    -}
    -
    -#css-text-align-center {
    -  text-align: center;
    -}
    -
    -#css-cursor-pointer {
    -  cursor: pointer;
    -}
    -
    -#test-opacity {
    -  opacity: 0.5;
    -  -moz-opacity: 0.5;
    -  filter: alpha(opacity=50);
    -}
    -
    -#test-frame-offset {
    -  display: block;
    -  position: absolute;
    -  top: 50px;
    -  left: 50px;
    -  width: 50px;
    -  height: 50px;
    -}
    -
    -#test-visible {
    -  background: yellow;
    -  position: absolute;
    -  overflow: hidden;
    -}
    -
    -#test-visible2 {
    -  background: #ebebeb;
    -  position: absolute;
    -  overflow: hidden;
    -}
    -
    -.scrollable-container {
    -  border: 8px solid blue;
    -  padding: 16px;
    -  margin: 32px;
    -  width: 100px;
    -  height: 100px;
    -  overflow: auto;
    -  position: absolute;
    -  left: 400px;
    -  top: 0;
    -}
    -
    -.scrollable-container-item {
    -  margin: 1px;
    -  border: 2px solid gray;
    -  padding: 4px;
    -  width: auto;
    -  /* The overflow is different from style_test so that we have consistent
    -     scroll positions in all browsers. */
    -  overflow: hidden;
    -  height: 20px;
    -}
    -
    -#translation {
    -  position: absolute;
    -  z-index: 10;
    -  left: 10px;
    -  top: 10px;
    -  width: 10px;
    -  height: 10px;
    -  background-color: blue;
    -  -webkit-transform: translate(20px, 30px);
    -  -ms-transform: translate(20px, 30px);
    -  -o-transform: translate(20px, 30px);
    -  -moz-transform: translate(20px, 30px);
    -  transform: translate(20px, 30px);
    -}
    -
    -</style>
    -</head>
    -<body>
    -  <div id="testEl">
    -    <span>Test Element</span>
    -  </div>
    -
    -  <div id="testEl5">
    -    <span>Test Element 5</span>
    -  </div>
    -
    -  <table id="table1">
    -    <tr>
    -      <td id="td1">td1</td>
    -    </tr>
    -  </table>
    -
    -  <span id="span0">span0</span>
    -
    -  <ul>
    -    <li id="li1">li1</li>
    -  </ul>
    -
    -  <span id="span1" class="test1"></span>
    -  <span id="span2" class="test1"></span>
    -  <span id="span3" class="test2"></span>
    -  <span id="span4" class="test3"></span>
    -  <span id="span5" class="test1"></span>
    -  <span id="span6" class="test1"></span>
    -
    -  <p id="p1"></p>
    -
    -  <div id="styleTest1"></div>
    -  <div id="styleTest2" style="width:100px;text-decoration:underline"></div>
    -  <div id="styleTest3"></div>
    -
    -  <!-- Paragraph to test element child and sibling -->
    -  <p id="p2">
    -    <!-- Comment -->
    -    a
    -    <b id="b1">c</b>
    -    d
    -    <!-- Comment -->
    -    e
    -    <b id="b2">f</b>
    -    g
    -    <!-- Comment -->
    -  </p>
    -
    -  <p style="background-color: #eee">
    -    <span id="bgcolorTest0">1</span>
    -    <span id="bgcolorTest1">1</span>
    -    <span id="bgcolorTest2">2</span>
    -    <span id="bgcolorTest3">3</span>
    -    <span id="bgcolorTest4" style="background-color:#ff0000">4</span>
    -    <span id="bgcolorTest5">5</span>
    -    <span id="bgcolorTest6">6</span>
    -    <span id="bgcolorTest7">7</span>
    -    <span id="bgcolorDest">Dest</span>
    -    <span id="installTest0">Styled 0</span>
    -    <span id="installTest1">Styled 1</span>
    -  </p>
    -
    -  <div class='rtl-test' dir='ltr' id='rtl1'>
    -    <div dir='rtl' id='rtl2'>right to left</div>
    -    <div dir='ltr' id='rtl3'>left to right</div>
    -    <div id='rtl4'>left to right (inherited)</div>
    -    <div id='rtl5' style="direction: rtl">right to left (style)</div>
    -    <div id='rtl6' style="direction: ltr">left to right (style)</div>
    -    <div id='rtl7' class=rtl>right to left (css)</div>
    -    <div id='rtl8' class=ltr>left to right (css)</div>
    -    <div class=rtl>
    -      <div id='rtl9'>right to left (css)</div>
    -    </div>
    -    <div class=ltr>
    -      <div id='rtl10'>left to right (css)</div>
    -    </div>
    -  </div>
    -
    -  <div id="pos-scroll-abs">
    -
    -    <p>Some text some text some text some text some text some text some text
    -    some text some text some text. Some text some text some text some text some
    -    text some text some text some text some text some text. Some text some text
    -    some text some text some text some text some text some text some text some
    -    text. Some text some text some text some text some text some text some text
    -    some text some text some text.
    -
    -    <p>Some text some text some text some text some text some text some text
    -    some text some text some text. Some text some text some text some text some
    -    text some text some text some text some text some text. Some text some text
    -    some text some text some text some text some text some text some text some
    -    text. Some text some text some text some text some text some text some text
    -    some text some text some text.
    -
    -    <div id="pos-scroll-abs-1">
    -      <p>Some text some text some text some text some text some text some text
    -      some text some text some text. Some text some text some text some text
    -      some text some text some text some text some text some text. Some text
    -      some text some text some text some text some text some text some text some
    -      text some text. Some text some text some text some text some text some
    -      text some text some text some text some text.
    -
    -      <p>Some text some text some text some text some text some text some text
    -      some text some text some text. Some text some text some text some text
    -      some text some text some text some text some text some text. Some text
    -      some text some text some text some text some text some text some text some
    -      text some text. Some text some text some text some text some text some
    -      text some text some text some text some text.
    -
    -      <div id="pos-scroll-abs-2">
    -
    -        <p>Some text some text some text some text some text some text some text
    -        some text some text some text. Some text some text some text some text
    -        some text some text some text some text some text some text. Some text
    -        some text some text some text some text some text some text some text
    -        some text some text. Some text some text some text some text some text
    -        some text some text some text some text some text.
    -
    -      </div>
    -
    -    </div>
    -
    -  </div>
    -
    -  <div id="abs-upper-left">
    -  foo
    -  </div>
    -
    -  <div id="no-text-font-styles">
    -    <font size="+1" face="Times,serif" id="font-tag">Times</font>
    -    <pre id="pre-font">pre text</pre>
    -    <span style="font:inherit" id="inherit-font">inherited</span>
    -    <span style="font-family:Times,sans-serif; font-size:3in"
    -          id="times-font-family">Times</span>
    -    <b id="bold-font">Bolded</b>
    -    <i id="css-html-tag-redefinition">Times</i>
    -    <span id="small-text" class="century" style="font-size:small">eensy</span>
    -    <span id="x-small-text" style="font-size:x-small">weensy</span>
    -    <span style="font:50% badFont" id="font-style-badfont">
    -      badFont
    -      <span style="font:inherit" id="inherit-50pct-font">
    -        same size as badFont
    -      </span>
    -    </span>
    -    <span id="icon-font" style="font:icon">Icon Font</span>
    -  </div>
    -  <span id="no-font-style">plain</span>
    -  <span style="font-family:Arial" id="nested-font">Arial<span style="font-family:Times">Times nested inside Arial</span></span>
    -  <img id="img-font-test" src=""/>
    -
    -  <span style="font-size:25px">
    -    <span style="font-size:12.5px" id="font-size-12-point-5-px">12.5PX</span>
    -    <span style="font-size:0.5em" id="font-size-50-pct-of-25-px">12.5PX</span>
    -  </span>
    -
    -<div id="size-a"></div>
    -
    -<div id="size-b"></div>
    -
    -<div id="size-c">xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxxxxxxxxxx
    -xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
    -xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
    -xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
    -xxxxxxxxxxxxxxxx</div>
    -
    -<div id="size-d">xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxxxxxxxxxx
    -xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
    -xxxxxxxx x</div>
    -
    -<div id="size-e"></div>
    -
    -<div id="size-f">hello</div>
    -
    -<div style="font-size: 1px">
    -  <div style="font-size: 2em"><span id="em-font-size"></span></div>
    -</div>
    -
    -<div id="no-float"></div>
    -
    -<div id="float-none" style="float:none"></div>
    -
    -<div id="float-left" style="float:left"></div>
    -
    -<div id="float-test"></div>
    -
    -<div id="position-unset"></div>
    -<div id="style-position-relative" style="position:relative"></div>
    -<div id="style-position-fixed" style="position:fixed"></div>
    -<div id="css-position-absolute"></div>
    -
    -<div id="box-sizing-unset"></div>
    -<div id="box-sizing-border-box" style="box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box;"></div>
    -
    -<div id="style-overflow-scroll" style="overflow:scroll"></div>
    -<div id="css-overflow-hidden"></div>
    -
    -<!-- Getting the computed z-index of an unpositioned element is unspecified. -->
    -<div id="style-z-index-200" style="position:relative;z-index:200"></div>
    -<div id="css-z-index-200"></div>
    -
    -<div id="style-text-align-right" style="text-align:right">
    -  <div id="style-text-align-right-inner">foo</div>
    -</div>
    -<div id="css-text-align-center"></div>
    -
    -<div id="style-cursor-move" style="cursor:move">
    -  <span id="style-cursor-move-inner">foo</span>
    -</div>
    -<div id="css-cursor-pointer"></div>
    -
    -<div id="height-test" style="display:inline-block;position:relative">
    -  <div id="height-test-inner" style="display:inline-block">
    -    foo
    -  </div>
    -</div>
    -
    -<div id="test-opacity"></div>
    -
    -<iframe id="test-frame-offset"></iframe>
    -
    -<iframe id="test-translate-frame-standard" src="style_test_standard.html"
    - style="overflow:auto;position:absolute;left:100px;top:150px;width:200px;height:200px;border:0px;">
    -</iframe>
    -<iframe id="test-translate-frame-quirk" src="style_test_quirk.html"
    - style="overflow:auto;position:absolute;left:100px;top:350px;width:200px;height:200px;border:0px;margin:0px;">
    -</iframe>
    -
    -<iframe
    -    id="test-visible-frame"
    -    src="style_test_iframe_standard.html"
    -    style="width: 200px; height: 200px; border: 0px;">
    -</iframe>
    -
    -<div id="test-scrollbarwidth" style="background-color: orange; width: 100px; height: 100px; overflow: auto;">
    -  <div style='width: 200px; height: 200px; background-color: red'>Test Scroll bar width with scroll</div>
    -</div>
    -
    -<div id="scrollable-container" class="scrollable-container">
    -  <!--
    -    Workaround for overlapping top padding of the container and top margin of
    -    the first item in Internet Explorer 6 and 7.
    -    See http://www.quirksmode.org/bugreports/archives/2005/01/IE_nested_boxes_padding_topmargin_top.html#c11285
    -  -->
    -  <div style="height: 0"><!--  --></div>
    -  <div id="item1" class="scrollable-container-item">1</div>
    -  <div id="item2" class="scrollable-container-item">2</div>
    -  <div id="item3" class="scrollable-container-item">3</div>
    -  <div id="item4" class="scrollable-container-item">4</div>
    -  <div id="item5" class="scrollable-container-item">5</div>
    -  <div id="item6" class="scrollable-container-item">6</div>
    -  <div id="item7" class="scrollable-container-item">7</div>
    -  <div id="item8" class="scrollable-container-item">8</div>
    -</div>
    -
    -<div id="test-visible">
    -Test-visible
    -<div id="test-visible-el" style="height:200px;">Test-visible</div>
    -Test-visible
    -</div>
    -
    -<div id="test-visible2"></div>
    -
    -<div id="msFilter" style="-ms-filter:'alpha(opacity=0)'">
    -  A div</div>
    -<div id="filter" style="filter:alpha(opacity=0)">
    -  Another div</div>
    -
    -<div id="offset-parent" style="position:relative">
    -  <div id="offset-child">child</div>
    -</div>
    -
    -<div id="offset-parent-overflow"
    -     style="overflow: scroll; width: 50px; height: 50px;">
    -  <a id="offset-child-overflow">
    -    scrollscrollscrollscrollscrollscrollscrollscroll
    -  </a>
    -</div>
    -
    -<div id="test-viewport"></div>
    -<div id="translation"></div>
    -
    -<div id="rotated"></div>
    -<div id="scaled"></div>
    -
    -<script>
    -if (!goog.userAgent.IE || goog.userAgent.isDocumentModeOrHigher(9)) {
    -  document.write(
    -      '<iframe id="svg-frame" src="style_test_rect.svg"></' + 'iframe>');
    -}
    -goog.require('goog.style_test');
    -</script>
    -
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/style/style_test.html b/src/database/third_party/closure-library/closure/goog/style/style_test.html
    deleted file mode 100644
    index c44322810ec..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/style/style_test.html
    +++ /dev/null
    @@ -1,526 +0,0 @@
    -<!DOCTYPE html>
    -<!--
    -
    -  When changing this, make sure that style_quirks_test.html is kept in sync.
    -
    --->
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<meta name="viewport" content="width=device-width, initial-scale=1.0,
    -    maximum-scale=1.0, minimum-scale=1.0, user-scalable=0">
    -<title>Closure Unit Tests - goog.dom.style</title>
    -<script src="../base.js"></script>
    -<script>goog.require('goog.userAgent');</script>
    -<style>
    -
    -i {
    -  font-family: Times, sans-serif;
    -  font-size: 5em;
    -}
    -
    -#testEl5 {
    -  display: none;
    -}
    -
    -#styleTest1 {
    -  width: 120px;
    -  text-decoration: underline;
    -}
    -
    -#bgcolorTest0 {
    -  background-color: #f00;
    -}
    -
    -#bgcolorTest1 {
    -  background-color: #ff0000;
    -}
    -
    -#bgcolorTest2 {
    -  background-color: rgb(255, 0, 0);
    -}
    -
    -#bgcolorTest3 {
    -  background-color: rgb(100%, 0%, 0%);
    -}
    -
    -#bgcolorTest5 {
    -  background-color: lightblue;
    -}
    -
    -#bgcolorTest6 {
    -  background-color: inherit;
    -}
    -
    -#bgcolorTest7 {
    -  background-color: transparent;
    -}
    -
    -.rtl {
    -  direction: rtl;
    -}
    -
    -.ltr {
    -  direction: ltr;
    -}
    -
    -#pos-scroll-abs {
    -  position: absolute;
    -  top: 200px;
    -  left: 100px;
    -}
    -
    -#pos-scroll-abs-1 {
    -  overflow: scroll;
    -  width: 100px;
    -  height: 100px;
    -}
    -
    -#pos-scroll-abs-2 {
    -  position: absolute;
    -  top: 100px;
    -  left: 100px;
    -  width: 500px;
    -  background-color: pink;
    -}
    -
    -#abs-upper-left {
    -  position: absolute;
    -  top: 0px;
    -  left: 0px;
    -}
    -
    -#no-text-font-styles {
    -  font-family: "Helvetica", Times, serif;
    -  font-size: 30px;
    -}
    -
    -.century {
    -  font-family: "Comic Sans MS", "Century Schoolbook L", serif;
    -}
    -
    -#size-a,
    -#size-e {
    -  width: 100px;
    -  height: 100px;
    -  background: red;
    -  padding: 0;
    -  border-style: solid;
    -  border-color: black;
    -  border-width: 0;
    -}
    -
    -#size-b {
    -  width: 100px;
    -  height: 100px;
    -  background: red;
    -  border: 10px solid black;
    -}
    -
    -#size-c {
    -  width: 100px;
    -  height: 100px;
    -  background: red;
    -  border: 10px solid black;
    -  padding: 10px;
    -  overflow: auto;
    -}
    -
    -#size-d {
    -  width: 10em;
    -  height: 2cm;
    -  background: red;
    -  border: thick solid black;
    -  padding: 2mm;
    -}
    -
    -#size-f {
    -  border-width: 0;
    -  margin: 0;
    -  padding: 0;
    -}
    -
    -#css-position-absolute {
    -  position: absolute;
    -}
    -
    -#css-overflow-hidden {
    -  overflow: hidden;
    -}
    -
    -#css-z-index-200 {
    -  position:relative;
    -  z-index: 200;
    -}
    -
    -#css-text-align-center {
    -  text-align: center;
    -}
    -
    -#css-cursor-pointer {
    -  cursor: pointer;
    -}
    -
    -#test-opacity {
    -  opacity: 0.5;
    -  -moz-opacity: 0.5;
    -  filter: alpha(opacity=50);
    -}
    -
    -#test-frame-offset {
    -  display: block;
    -  position: absolute;
    -  top: 50px;
    -  left: 50px;
    -  width: 50px;
    -  height: 50px;
    -}
    -
    -#test-visible {
    -  background: yellow;
    -  position: absolute;
    -  overflow: hidden;
    -}
    -
    -#test-visible2 {
    -  background: #ebebeb;
    -  position: absolute;
    -  overflow: hidden;
    -}
    -
    -.scrollable-container {
    -  border: 8px solid blue;
    -  padding: 16px;
    -  margin: 32px;
    -  width: 100px;
    -  height: 100px;
    -  overflow: auto;
    -  position: absolute;
    -  left: 400px;
    -  top: 0;
    -}
    -
    -.scrollable-container-item {
    -  margin: 1px;
    -  border: 2px solid gray;
    -  padding: 4px;
    -  width: auto;
    -  height: 20px;
    -}
    -
    -#translation {
    -  position: absolute;
    -  z-index: 10;
    -  left: 10px;
    -  top: 10px;
    -  width: 10px;
    -  height: 10px;
    -  background-color: blue;
    -  -webkit-transform: translate(20px, 30px);
    -  -ms-transform: translate(20px, 30px);
    -  -o-transform: translate(20px, 30px);
    -  -moz-transform: translate(20px, 30px);
    -  transform: translate(20px, 30px);
    -}
    -
    -</style>
    -</head>
    -<body>
    -  <div id="testEl">
    -    <span>Test Element</span>
    -  </div>
    -
    -  <div id="testEl5">
    -    <span>Test Element 5</span>
    -  </div>
    -
    -  <table id="table1">
    -    <tr>
    -      <td id="td1">td1</td>
    -    </tr>
    -  </table>
    -
    -  <span id="span0">span0</span>
    -
    -  <ul>
    -    <li id="li1">li1</li>
    -  </ul>
    -
    -  <span id="span1" class="test1"></span>
    -  <span id="span2" class="test1"></span>
    -  <span id="span3" class="test2"></span>
    -  <span id="span4" class="test3"></span>
    -  <span id="span5" class="test1"></span>
    -  <span id="span6" class="test1"></span>
    -
    -  <p id="p1"></p>
    -
    -  <div id="styleTest1"></div>
    -  <div id="styleTest2" style="width:100px;text-decoration:underline"></div>
    -  <div id="styleTest3"></div>
    -
    -  <!-- Paragraph to test element child and sibling -->
    -  <p id="p2">
    -    <!-- Comment -->
    -    a
    -    <b id="b1">c</b>
    -    d
    -    <!-- Comment -->
    -    e
    -    <b id="b2">f</b>
    -    g
    -    <!-- Comment -->
    -  </p>
    -
    -  <p style="background-color: #eee">
    -    <span id="bgcolorTest0">1</span>
    -    <span id="bgcolorTest1">1</span>
    -    <span id="bgcolorTest2">2</span>
    -    <span id="bgcolorTest3">3</span>
    -    <span id="bgcolorTest4" style="background-color:#ff0000">4</span>
    -    <span id="bgcolorTest5">5</span>
    -    <span id="bgcolorTest6">6</span>
    -    <span id="bgcolorTest7">7</span>
    -    <span id="bgcolorDest">Dest</span>
    -    <span id="installTest0">Styled 0</span>
    -    <span id="installTest1">Styled 1</span>
    -  </p>
    -
    -  <div class='rtl-test' dir='ltr' id='rtl1'>
    -    <div dir='rtl' id='rtl2'>right to left</div>
    -    <div dir='ltr' id='rtl3'>left to right</div>
    -    <div id='rtl4'>left to right (inherited)</div>
    -    <div id='rtl5' style="direction: rtl">right to left (style)</div>
    -    <div id='rtl6' style="direction: ltr">left to right (style)</div>
    -    <div id='rtl7' class=rtl>right to left (css)</div>
    -    <div id='rtl8' class=ltr>left to right (css)</div>
    -    <div class=rtl>
    -      <div id='rtl9'>right to left (css)</div>
    -    </div>
    -    <div class=ltr>
    -      <div id='rtl10'>left to right (css)</div>
    -    </div>
    -  </div>
    -
    -  <div id="pos-scroll-abs">
    -
    -    <p>Some text some text some text some text some text some text some text
    -    some text some text some text. Some text some text some text some text some
    -    text some text some text some text some text some text. Some text some text
    -    some text some text some text some text some text some text some text some
    -    text. Some text some text some text some text some text some text some text
    -    some text some text some text.
    -
    -    <p>Some text some text some text some text some text some text some text
    -    some text some text some text. Some text some text some text some text some
    -    text some text some text some text some text some text. Some text some text
    -    some text some text some text some text some text some text some text some
    -    text. Some text some text some text some text some text some text some text
    -    some text some text some text.
    -
    -    <div id="pos-scroll-abs-1">
    -      <p>Some text some text some text some text some text some text some text
    -      some text some text some text. Some text some text some text some text
    -      some text some text some text some text some text some text. Some text
    -      some text some text some text some text some text some text some text some
    -      text some text. Some text some text some text some text some text some
    -      text some text some text some text some text.
    -
    -      <p>Some text some text some text some text some text some text some text
    -      some text some text some text. Some text some text some text some text
    -      some text some text some text some text some text some text. Some text
    -      some text some text some text some text some text some text some text some
    -      text some text. Some text some text some text some text some text some
    -      text some text some text some text some text.
    -
    -      <div id="pos-scroll-abs-2">
    -
    -        <p>Some text some text some text some text some text some text some text
    -        some text some text some text. Some text some text some text some text
    -        some text some text some text some text some text some text. Some text
    -        some text some text some text some text some text some text some text
    -        some text some text. Some text some text some text some text some text
    -        some text some text some text some text some text.
    -
    -      </div>
    -
    -    </div>
    -
    -  </div>
    -
    -  <div id="abs-upper-left">
    -  foo
    -  </div>
    -
    -  <div id="no-text-font-styles">
    -    <font size="+1" face="Times,serif" id="font-tag">Times</font>
    -    <pre id="pre-font">pre text</pre>
    -    <span style="font:inherit" id="inherit-font">inherited</span>
    -    <span style="font-family:Times,sans-serif; font-size:3in"
    -          id="times-font-family">Times</span>
    -    <b id="bold-font">Bolded</b>
    -    <i id="css-html-tag-redefinition">Times</i>
    -    <span id="small-text" class="century" style="font-size:small">eensy</span>
    -    <span id="x-small-text" style="font-size:x-small">weensy</span>
    -    <span style="font:50% badFont" id="font-style-badfont">
    -      badFont
    -      <span style="font:inherit" id="inherit-50pct-font">
    -        same size as badFont
    -      </span>
    -    </span>
    -    <span id="icon-font" style="font:icon">Icon Font</span>
    -  </div>
    -  <span id="no-font-style">plain</span>
    -  <span style="font-family:Arial" id="nested-font">Arial<span style="font-family:Times">Times nested inside Arial</span></span>
    -  <img id="img-font-test" src=""/>
    -
    -  <span style="font-size:25px">
    -    <span style="font-size:12.5px" id="font-size-12-point-5-px">12.5PX</span>
    -    <span style="font-size:0.5em" id="font-size-50-pct-of-25-px">12.5PX</span>
    -  </span>
    -
    -<div id="size-a"></div>
    -
    -<div id="size-b"></div>
    -
    -<div id="size-c">xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxxxxxxxxxx
    -xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
    -xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
    -xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
    -xxxxxxxxxxxxxxxx</div>
    -
    -<div id="size-d">xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxxxxxxxxxx
    -xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
    -xxxxxxxx x</div>
    -
    -<div id="size-e"></div>
    -
    -<div id="size-f">hello</div>
    -
    -<div style="font-size: 1px">
    -  <div style="font-size: 2em"><span id="em-font-size"></span></div>
    -</div>
    -
    -<div id="no-float"></div>
    -
    -<div id="float-none" style="float:none"></div>
    -
    -<div id="float-left" style="float:left"></div>
    -
    -<div id="float-test"></div>
    -
    -<div id="position-unset"></div>
    -<div id="style-position-relative" style="position:relative"></div>
    -<div id="style-position-fixed" style="position:fixed"></div>
    -<div id="css-position-absolute"></div>
    -
    -<div id="box-sizing-unset"></div>
    -<div id="box-sizing-border-box" style="box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box;"></div>
    -
    -<div id="style-overflow-scroll" style="overflow:scroll"></div>
    -<div id="css-overflow-hidden"></div>
    -
    -<!-- Getting the computed z-index of an unpositioned element is unspecified. -->
    -<div id="style-z-index-200" style="position:relative;z-index:200"></div>
    -<div id="css-z-index-200"></div>
    -
    -<div id="style-text-align-right" style="text-align:right">
    -  <div id="style-text-align-right-inner">foo</div>
    -</div>
    -<div id="css-text-align-center"></div>
    -
    -<div id="style-cursor-move" style="cursor:move">
    -  <span id="style-cursor-move-inner">foo</span>
    -</div>
    -<div id="css-cursor-pointer"></div>
    -
    -<div id="height-test" style="display:inline-block;position:relative">
    -  <div id="height-test-inner" style="display:inline-block">
    -    foo
    -  </div>
    -</div>
    -
    -<div id="test-opacity"></div>
    -
    -<iframe id="test-frame-offset"></iframe>
    -
    -<iframe id="test-translate-frame-standard" src="style_test_standard.html"
    - style="overflow:auto;position:absolute;left:100px;top:150px;width:200px;height:200px;border:0px;">
    -</iframe>
    -<iframe id="test-translate-frame-quirk" src="style_test_quirk.html"
    - style="overflow:auto;position:absolute;left:100px;top:350px;width:200px;height:200px;border:0px;margin:0px;">
    -</iframe>
    -
    -<iframe
    -    id="test-visible-frame"
    -    src="style_test_iframe_standard.html"
    -    style="width: 200px; height: 200px; border: 0px;">
    -</iframe>
    -
    -<div id="test-scrollbarwidth" style="background-color: orange; width: 100px; height: 100px; overflow: auto;">
    -  <div style='width: 200px; height: 200px; background-color: red'>Test Scroll bar width with scroll</div>
    -</div>
    -
    -<div id="scrollable-container" class="scrollable-container">
    -  <!--
    -    Workaround for overlapping top padding of the container and top margin of
    -    the first item in Internet Explorer 6 and 7.
    -    See http://www.quirksmode.org/bugreports/archives/2005/01/IE_nested_boxes_padding_topmargin_top.html#c11285
    -  -->
    -  <div style="height: 0"><!--  --></div>
    -  <div id="item1" class="scrollable-container-item">1</div>
    -  <div id="item2" class="scrollable-container-item">2</div>
    -  <div id="item3" class="scrollable-container-item">3</div>
    -  <div id="item4" class="scrollable-container-item">4</div>
    -  <div id="item5" class="scrollable-container-item">5</div>
    -  <div id="item6" class="scrollable-container-item">6</div>
    -  <div id="item7" class="scrollable-container-item">7</div>
    -  <div id="item8" class="scrollable-container-item">8</div>
    -</div>
    -
    -<div id="test-visible">
    -Test-visible
    -<div id="test-visible-el" style="height:200px;">Test-visible</div>
    -Test-visible
    -</div>
    -
    -<div id="test-visible2"></div>
    -
    -<div id="msFilter" style="-ms-filter:'alpha(opacity=0)'">
    -  A div</div>
    -<div id="filter" style="filter:alpha(opacity=0)">
    -  Another div</div>
    -
    -<div id="offset-parent" style="position:relative">
    -  <div id="offset-child">child</div>
    -</div>
    -
    -<div id="offset-parent-overflow"
    -     style="overflow: scroll; width: 50px; height: 50px;">
    -  <a id="offset-child-overflow">
    -    scrollscrollscrollscrollscrollscrollscrollscroll
    -  </a>
    -</div>
    -
    -<div id="test-viewport"></div>
    -<div id="translation"></div>
    -
    -<div id="rotated"></div>
    -<div id="scaled"></div>
    -
    -<script>
    -if (!goog.userAgent.IE || goog.userAgent.isDocumentModeOrHigher(9)) {
    -  document.write(
    -      '<iframe id="svg-frame" src="style_test_rect.svg"></' + 'iframe>');
    -}
    -goog.require('goog.style_test');
    -</script>
    -
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/style/style_test.js b/src/database/third_party/closure-library/closure/goog/style/style_test.js
    deleted file mode 100644
    index 51efdcd29a2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/style/style_test.js
    +++ /dev/null
    @@ -1,2657 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the Licensegg at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Shared unit tests for styles.
    - */
    -
    -/** @suppress {extraProvide} */
    -goog.provide('goog.style_test');
    -
    -goog.require('goog.array');
    -goog.require('goog.color');
    -goog.require('goog.dom');
    -goog.require('goog.events.BrowserEvent');
    -goog.require('goog.labs.userAgent.util');
    -goog.require('goog.math.Box');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.math.Rect');
    -goog.require('goog.math.Size');
    -goog.require('goog.object');
    -goog.require('goog.string');
    -goog.require('goog.style');
    -goog.require('goog.testing.ExpectedFailures');
    -goog.require('goog.testing.MockUserAgent');
    -goog.require('goog.testing.asserts');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -goog.require('goog.userAgent.product');
    -goog.require('goog.userAgentTestUtil');
    -goog.require('goog.userAgentTestUtil.UserAgents');
    -
    -goog.setTestOnly('goog.style_test');
    -
    -// IE before version 6 will always be border box in compat mode.
    -var isBorderBox = goog.dom.isCss1CompatMode() ?
    -    (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('6')) :
    -    true;
    -var EPSILON = 2;
    -var expectedFailures = new goog.testing.ExpectedFailures();
    -var $ = goog.dom.getElement;
    -var mockUserAgent;
    -
    -function setUpPage() {
    -  var viewportSize = goog.dom.getViewportSize();
    -  // When the window is too short or not wide enough, some tests, especially
    -  // those for off-screen elements, fail.  Oddly, the most reliable
    -  // indicator is a width of zero (which is of course erroneous), since
    -  // height sometimes includes a scroll bar.  We can make no assumptions on
    -  // window size on the Selenium farm.
    -  if (goog.userAgent.IE && viewportSize.width < 300) {
    -    // Move to origin, since IE won't resize outside the screen.
    -    window.moveTo(0, 0);
    -    window.resizeTo(640, 480);
    -  }
    -}
    -
    -function setUp() {
    -  window.scrollTo(0, 0);
    -  goog.userAgentTestUtil.reinitializeUserAgent();
    -  mockUserAgent = new goog.testing.MockUserAgent();
    -  mockUserAgent.install();
    -}
    -
    -function tearDown() {
    -  expectedFailures.handleTearDown();
    -  var testVisibleDiv2 = goog.dom.getElement('test-visible2');
    -  testVisibleDiv2.setAttribute('style', '');
    -  testVisibleDiv2.innerHTML = '';
    -  var testViewport = goog.dom.getElement('test-viewport');
    -  testViewport.setAttribute('style', '');
    -  testViewport.innerHTML = '';
    -  goog.dispose(mockUserAgent);
    -
    -  // Prevent multiple vendor prefixed mock elements from poisoning the cache.
    -  goog.style.styleNameCache_ = {};
    -}
    -
    -function testSetStyle() {
    -  var el = $('span1');
    -  goog.style.setStyle(el, 'textDecoration', 'underline');
    -  assertEquals('Should be underline', 'underline', el.style.textDecoration);
    -}
    -
    -function testSetStyleMap() {
    -  var el = $('span6');
    -
    -  var styles = {
    -    'background-color': 'blue',
    -    'font-size': '100px',
    -    textAlign: 'center'
    -  };
    -
    -  goog.style.setStyle(el, styles);
    -
    -  var answers = {
    -    backgroundColor: 'blue',
    -    fontSize: '100px',
    -    textAlign: 'center'
    -  };
    -
    -  goog.object.forEach(answers, function(value, style) {
    -    assertEquals('Should be ' + value, value, el.style[style]);
    -  });
    -}
    -
    -function testSetStyleWithNonCamelizedString() {
    -  var el = $('span5');
    -  goog.style.setStyle(el, 'text-decoration', 'underline');
    -  assertEquals('Should be underline', 'underline', el.style.textDecoration);
    -}
    -
    -function testGetStyle() {
    -  var el = goog.dom.getElement('styleTest3');
    -  goog.style.setStyle(el, 'width', '80px');
    -  goog.style.setStyle(el, 'textDecoration', 'underline');
    -
    -  assertEquals('80px', goog.style.getStyle(el, 'width'));
    -  assertEquals('underline', goog.style.getStyle(el, 'textDecoration'));
    -  assertEquals('underline', goog.style.getStyle(el, 'text-decoration'));
    -  // Non set properties are always empty strings.
    -  assertEquals('', goog.style.getStyle(el, 'border'));
    -}
    -
    -function testGetStyleMsFilter() {
    -  // Element with -ms-filter style set.
    -  var e = goog.dom.getElement('msFilter');
    -
    -  if (goog.userAgent.IE && goog.userAgent.isDocumentModeOrHigher(8) &&
    -      !goog.userAgent.isDocumentModeOrHigher(10)) {
    -    // Only IE8/9 supports -ms-filter and returns it as value for the "filter"
    -    // property. When in compatibility mode, -ms-filter is not supported
    -    // and IE8 behaves as IE7 so the other case will apply.
    -    assertEquals('alpha(opacity=0)', goog.style.getStyle(e, 'filter'));
    -  } else {
    -    // Any other browser does not support ms-filter so it returns empty string.
    -    assertEquals('', goog.style.getStyle(e, 'filter'));
    -  }
    -}
    -
    -function testGetStyleFilter() {
    -  // Element with filter style set.
    -  var e = goog.dom.getElement('filter');
    -
    -  if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(10)) {
    -    // Filter supported.
    -    assertEquals('alpha(opacity=0)', goog.style.getStyle(e, 'filter'));
    -  } else {
    -    assertEquals('', goog.style.getStyle(e, 'filter'));
    -  }
    -}
    -
    -function testGetComputedStyleMsFilter() {
    -  // Element with -ms-filter style set.
    -  var e = goog.dom.getElement('msFilter');
    -
    -  if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(10)) {
    -    if (goog.userAgent.isDocumentModeOrHigher(9)) {
    -      // IE 9 returns the value.
    -      assertEquals('alpha(opacity=0)',
    -          goog.style.getComputedStyle(e, 'filter'));
    -    } else {
    -      // Older IE always returns empty string for computed styles.
    -      assertEquals('', goog.style.getComputedStyle(e, 'filter'));
    -    }
    -  } else {
    -    // Non IE returns 'none' for filter as it is an SVG property
    -    assertEquals('none', goog.style.getComputedStyle(e, 'filter'));
    -  }
    -}
    -
    -function testGetComputedStyleFilter() {
    -  // Element with filter style set.
    -  var e = goog.dom.getElement('filter');
    -
    -  if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(10)) {
    -    if (goog.userAgent.isDocumentModeOrHigher(9)) {
    -      // IE 9 returns the value.
    -      assertEquals('alpha(opacity=0)',
    -          goog.style.getComputedStyle(e, 'filter'));
    -    } else {
    -      // Older IE always returns empty string for computed styles.
    -      assertEquals('', goog.style.getComputedStyle(e, 'filter'));
    -    }
    -  } else {
    -    // Non IE returns 'none' for filter as it is an SVG property
    -    assertEquals('none', goog.style.getComputedStyle(e, 'filter'));
    -  }
    -}
    -
    -function testGetComputedBoxSizing() {
    -  if (!goog.userAgent.IE || goog.userAgent.isVersionOrHigher(8)) {
    -    var defaultBoxSizing = goog.dom.isCss1CompatMode() ?
    -        'content-box' : 'border-box';
    -    var el = goog.dom.getElement('box-sizing-unset');
    -    assertEquals(defaultBoxSizing, goog.style.getComputedBoxSizing(el));
    -
    -    el = goog.dom.getElement('box-sizing-border-box');
    -    assertEquals('border-box', goog.style.getComputedBoxSizing(el));
    -  } else {
    -    // IE7 and below don't support box-sizing.
    -    assertNull(goog.style.getComputedBoxSizing(
    -        goog.dom.getElement('box-sizing-border-box')));
    -  }
    -}
    -
    -function testGetComputedPosition() {
    -  assertEquals('position not set', 'static',
    -               goog.style.getComputedPosition($('position-unset')));
    -  assertEquals('position:relative in style attribute', 'relative',
    -               goog.style.getComputedPosition($('style-position-relative')));
    -  if (goog.userAgent.IE && !goog.dom.isCss1CompatMode() &&
    -      !goog.userAgent.isVersionOrHigher(10)) {
    -    assertEquals('position:fixed in style attribute', 'static',
    -        goog.style.getComputedPosition($('style-position-fixed')));
    -  } else {
    -    assertEquals('position:fixed in style attribute', 'fixed',
    -        goog.style.getComputedPosition($('style-position-fixed')));
    -  }
    -  assertEquals('position:absolute in css', 'absolute',
    -               goog.style.getComputedPosition($('css-position-absolute')));
    -}
    -
    -function testGetComputedOverflowXAndY() {
    -  assertEquals('overflow-x:scroll in style attribute', 'scroll',
    -               goog.style.getComputedOverflowX($('style-overflow-scroll')));
    -  assertEquals('overflow-y:scroll in style attribute', 'scroll',
    -               goog.style.getComputedOverflowY($('style-overflow-scroll')));
    -  assertEquals('overflow-x:hidden in css', 'hidden',
    -               goog.style.getComputedOverflowX($('css-overflow-hidden')));
    -  assertEquals('overflow-y:hidden in css', 'hidden',
    -               goog.style.getComputedOverflowY($('css-overflow-hidden')));
    -}
    -
    -function testGetComputedZIndex() {
    -  assertEquals('z-index:200 in style attribute', '200',
    -               '' + goog.style.getComputedZIndex($('style-z-index-200')));
    -  assertEquals('z-index:200 in css', '200',
    -               '' + goog.style.getComputedZIndex($('css-z-index-200')));
    -}
    -
    -function testGetComputedTextAlign() {
    -  assertEquals('text-align:right in style attribute', 'right',
    -               goog.style.getComputedTextAlign($('style-text-align-right')));
    -  assertEquals(
    -      'text-align:right inherited from parent', 'right',
    -      goog.style.getComputedTextAlign($('style-text-align-right-inner')));
    -  assertEquals('text-align:center in css', 'center',
    -               goog.style.getComputedTextAlign($('css-text-align-center')));
    -}
    -
    -function testGetComputedCursor() {
    -  assertEquals('cursor:move in style attribute', 'move',
    -               goog.style.getComputedCursor($('style-cursor-move')));
    -  assertEquals('cursor:move inherited from parent', 'move',
    -               goog.style.getComputedCursor($('style-cursor-move-inner')));
    -  assertEquals('cursor:poiner in css', 'pointer',
    -               goog.style.getComputedCursor($('css-cursor-pointer')));
    -}
    -
    -function testGetBackgroundColor() {
    -  var dest = $('bgcolorDest');
    -
    -  for (var i = 0; $('bgcolorTest' + i); i++) {
    -    var src = $('bgcolorTest' + i);
    -    var bgColor = goog.style.getBackgroundColor(src);
    -
    -    dest.style.backgroundColor = bgColor;
    -    assertEquals('Background colors should be equal',
    -                 goog.style.getBackgroundColor(src),
    -                 goog.style.getBackgroundColor(dest));
    -
    -    try {
    -      // goog.color.parse throws a generic exception if handed input it
    -      // doesn't understand.
    -      var c = goog.color.parse(bgColor);
    -      assertEquals('rgb(255,0,0)', goog.color.hexToRgbStyle(c.hex));
    -    } catch (e) {
    -      // Internet Explorer is unable to parse colors correctly after test 4.
    -      // Other browsers may vary, but all should be able to handle straight
    -      // hex input.
    -      assertFalse('Should be able to parse color "' + bgColor + '"', i < 5);
    -    }
    -  }
    -}
    -
    -function testSetPosition() {
    -  var el = $('testEl');
    -
    -  goog.style.setPosition(el, 100, 100);
    -  assertEquals('100px', el.style.left);
    -  assertEquals('100px', el.style.top);
    -
    -  goog.style.setPosition(el, '50px', '25px');
    -  assertEquals('50px', el.style.left);
    -  assertEquals('25px', el.style.top);
    -
    -  goog.style.setPosition(el, '10ex', '25px');
    -  assertEquals('10ex', el.style.left);
    -  assertEquals('25px', el.style.top);
    -
    -  goog.style.setPosition(el, '10%', '25%');
    -  assertEquals('10%', el.style.left);
    -  assertEquals('25%', el.style.top);
    -
    -  // ignores stupid units
    -  goog.style.setPosition(el, 0, 0);
    -  // TODO(user): IE errors if you set these values.  Should we make setStyle
    -  // catch these?  Or leave it up to the app.  Fixing the tests for now.
    -  //goog.style.setPosition(el, '10rainbows', '25rainbows');
    -  assertEquals('0px', el.style.left);
    -  assertEquals('0px', el.style.top);
    -
    -
    -  goog.style.setPosition(el, new goog.math.Coordinate(20, 40));
    -  assertEquals('20px', el.style.left);
    -  assertEquals('40px', el.style.top);
    -}
    -
    -function testGetClientPositionAbsPositionElement() {
    -  var div = goog.dom.createDom('DIV');
    -  div.style.position = 'absolute';
    -  div.style.left = '100px';
    -  div.style.top = '200px';
    -  document.body.appendChild(div);
    -  var pos = goog.style.getClientPosition(div);
    -  assertEquals(100, pos.x);
    -  assertEquals(200, pos.y);
    -}
    -
    -function testGetClientPositionNestedElements() {
    -  var innerDiv = goog.dom.createDom('DIV');
    -  innerDiv.style.position = 'relative';
    -  innerDiv.style.left = '-10px';
    -  innerDiv.style.top = '-10px';
    -  var div = goog.dom.createDom('DIV');
    -  div.style.position = 'absolute';
    -  div.style.left = '150px';
    -  div.style.top = '250px';
    -  div.appendChild(innerDiv);
    -  document.body.appendChild(div);
    -  var pos = goog.style.getClientPosition(innerDiv);
    -  assertEquals(140, pos.x);
    -  assertEquals(240, pos.y);
    -}
    -
    -function testGetClientPositionOfOffscreenElement() {
    -  var div = goog.dom.createDom('DIV');
    -  div.style.position = 'absolute';
    -  div.style.left = '2000px';
    -  div.style.top = '2000px';
    -  div.style.width = '10px';
    -  div.style.height = '10px';
    -  document.body.appendChild(div);
    -
    -  try {
    -    window.scroll(0, 0);
    -    var pos = goog.style.getClientPosition(div);
    -    assertEquals(2000, pos.x);
    -    assertEquals(2000, pos.y);
    -
    -    // The following tests do not work in Gecko 1.8 and below, due to an
    -    // obscure off-by-one bug in goog.style.getPageOffset.  Same for IE.
    -    if (!goog.userAgent.IE &&
    -        !(goog.userAgent.GECKO && !goog.userAgent.isVersionOrHigher('1.9'))) {
    -      window.scroll(1, 1);
    -      var pos = goog.style.getClientPosition(div);
    -      assertEquals(1999, pos.x);
    -      assertRoughlyEquals(1999, pos.y, 0.5);
    -
    -      window.scroll(2, 2);
    -      pos = goog.style.getClientPosition(div);
    -      assertEquals(1998, pos.x);
    -      assertRoughlyEquals(1998, pos.y, 0.5);
    -
    -      window.scroll(100, 100);
    -      pos = goog.style.getClientPosition(div);
    -      assertEquals(1900, pos.x);
    -      assertRoughlyEquals(1900, pos.y, 0.5);
    -    }
    -  }
    -  finally {
    -    window.scroll(0, 0);
    -    document.body.removeChild(div);
    -  }
    -}
    -
    -function testGetClientPositionOfOrphanElement() {
    -  var orphanElem = document.createElement('DIV');
    -  var pos = goog.style.getClientPosition(orphanElem);
    -  assertEquals(0, pos.x);
    -  assertEquals(0, pos.y);
    -}
    -
    -function testGetClientPositionEvent() {
    -  var mockEvent = {};
    -  mockEvent.clientX = 100;
    -  mockEvent.clientY = 200;
    -  var pos = goog.style.getClientPosition(mockEvent);
    -  assertEquals(100, pos.x);
    -  assertEquals(200, pos.y);
    -}
    -
    -function testGetClientPositionTouchEvent() {
    -  var mockTouchEvent = {};
    -
    -  mockTouchEvent.targetTouches = [{}];
    -  mockTouchEvent.targetTouches[0].clientX = 100;
    -  mockTouchEvent.targetTouches[0].clientY = 200;
    -
    -  mockTouchEvent.touches = [{}];
    -  mockTouchEvent.touches[0].clientX = 100;
    -  mockTouchEvent.touches[0].clientY = 200;
    -
    -  var pos = goog.style.getClientPosition(mockTouchEvent);
    -  assertEquals(100, pos.x);
    -  assertEquals(200, pos.y);
    -}
    -
    -function testGetClientPositionEmptyTouchList() {
    -  var mockTouchEvent = {};
    -
    -  mockTouchEvent.clientX = 100;
    -  mockTouchEvent.clientY = 200;
    -
    -  mockTouchEvent.targetTouches = [];
    -  mockTouchEvent.touches = [];
    -
    -  var pos = goog.style.getClientPosition(mockTouchEvent);
    -  assertEquals(100, pos.x);
    -  assertEquals(200, pos.y);
    -}
    -
    -function testGetClientPositionAbstractedTouchEvent() {
    -  var e = new goog.events.BrowserEvent();
    -  e.event_ = {};
    -  e.event_.touches = [{}];
    -  e.event_.touches[0].clientX = 100;
    -  e.event_.touches[0].clientY = 200;
    -  e.event_.targetTouches = [{}];
    -  e.event_.targetTouches[0].clientX = 100;
    -  e.event_.targetTouches[0].clientY = 200;
    -  var pos = goog.style.getClientPosition(e);
    -  assertEquals(100, pos.x);
    -  assertEquals(200, pos.y);
    -}
    -
    -function testGetPageOffsetAbsPositionedElement() {
    -  var div = goog.dom.createDom('DIV');
    -  div.style.position = 'absolute';
    -  div.style.left = '100px';
    -  div.style.top = '200px';
    -  document.body.appendChild(div);
    -  var pos = goog.style.getPageOffset(div);
    -  assertEquals(100, pos.x);
    -  assertEquals(200, pos.y);
    -}
    -
    -function testGetPageOffsetNestedElements() {
    -  var innerDiv = goog.dom.createDom('DIV');
    -  innerDiv.style.position = 'relative';
    -  innerDiv.style.left = '-10px';
    -  innerDiv.style.top = '-10px';
    -  var div = goog.dom.createDom('DIV');
    -  div.style.position = 'absolute';
    -  div.style.left = '150px';
    -  div.style.top = '250px';
    -  div.appendChild(innerDiv);
    -  document.body.appendChild(div);
    -  var pos = goog.style.getPageOffset(innerDiv);
    -  assertRoughlyEquals(140, pos.x, 0.1);
    -  assertRoughlyEquals(240, pos.y, 0.1);
    -}
    -
    -function testGetPageOffsetWithBodyPadding() {
    -  document.body.style.margin = '40px';
    -  document.body.style.padding = '60px';
    -  document.body.style.borderWidth = '70px';
    -  try {
    -    var div = goog.dom.createDom('DIV');
    -    div.style.position = 'absolute';
    -    div.style.left = '100px';
    -    div.style.top = '200px';
    -    // Margin will affect position, but padding and borders should not.
    -    div.style.margin = '1px';
    -    div.style.padding = '2px';
    -    div.style.borderWidth = '3px';
    -    document.body.appendChild(div);
    -    var pos = goog.style.getPageOffset(div);
    -    assertRoughlyEquals(101, pos.x, 0.1);
    -    assertRoughlyEquals(201, pos.y, 0.1);
    -  }
    -  finally {
    -    document.body.removeChild(div);
    -    document.body.style.margin = '';
    -    document.body.style.padding = '';
    -    document.body.style.borderWidth = '';
    -  }
    -}
    -
    -function testGetPageOffsetWithDocumentElementPadding() {
    -  document.documentElement.style.margin = '40px';
    -  document.documentElement.style.padding = '60px';
    -  document.documentElement.style.borderWidth = '70px';
    -  try {
    -    var div = goog.dom.createDom('DIV');
    -    div.style.position = 'absolute';
    -    div.style.left = '100px';
    -    div.style.top = '200px';
    -    // Margin will affect position, but padding and borders should not.
    -    div.style.margin = '1px';
    -    div.style.padding = '2px';
    -    div.style.borderWidth = '3px';
    -    document.body.appendChild(div);
    -    var pos = goog.style.getPageOffset(div);
    -    // FF3 (but not beyond) gets confused by document margins.
    -    if (goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.9') &&
    -        !goog.userAgent.isVersionOrHigher('1.9.1')) {
    -      assertEquals(141, pos.x);
    -      assertEquals(241, pos.y);
    -    } else {
    -      assertRoughlyEquals(101, pos.x, 0.1);
    -      assertRoughlyEquals(201, pos.y, 0.1);
    -    }
    -  }
    -  finally {
    -    document.body.removeChild(div);
    -    document.documentElement.style.margin = '';
    -    document.documentElement.style.padding = '';
    -    document.documentElement.style.borderWidth = '';
    -  }
    -}
    -
    -function testGetPageOffsetElementOffscreen() {
    -  var div = goog.dom.createDom('DIV');
    -  div.style.position = 'absolute';
    -  div.style.left = '10000px';
    -  div.style.top = '20000px';
    -  document.body.appendChild(div);
    -  window.scroll(0, 0);
    -  try {
    -    var pos = goog.style.getPageOffset(div);
    -    assertEquals(10000, pos.x);
    -    assertEquals(20000, pos.y);
    -
    -    // The following tests do not work in Gecko 1.8 and below, due to an
    -    // obscure off-by-one bug in goog.style.getPageOffset.  Same for IE.
    -    if (!(goog.userAgent.IE) &&
    -        !(goog.userAgent.GECKO && !goog.userAgent.isVersionOrHigher('1.9'))) {
    -      window.scroll(1, 1);
    -      pos = goog.style.getPageOffset(div);
    -      assertEquals(10000, pos.x);
    -      assertRoughlyEquals(20000, pos.y, 0.5);
    -
    -      window.scroll(1000, 2000);
    -      pos = goog.style.getPageOffset(div);
    -      assertEquals(10000, pos.x);
    -      assertRoughlyEquals(20000, pos.y, 1);
    -
    -      window.scroll(10000, 20000);
    -      pos = goog.style.getPageOffset(div);
    -      assertEquals(10000, pos.x);
    -      assertRoughlyEquals(20000, pos.y, 1);
    -    }
    -  }
    -  // Undo changes.
    -  finally {
    -    document.body.removeChild(div);
    -    window.scroll(0, 0);
    -  }
    -}
    -
    -function testGetPageOffsetFixedPositionElements() {
    -  // Skip these tests in certain browsers.
    -  // position:fixed is not supported in IE before version 7
    -  if (!goog.userAgent.IE || !goog.userAgent.isVersionOrHigher('6')) {
    -    // Test with a position fixed element
    -    var div = goog.dom.createDom('DIV');
    -    div.style.position = 'fixed';
    -    div.style.top = '10px';
    -    div.style.left = '10px';
    -    document.body.appendChild(div);
    -    var pos = goog.style.getPageOffset(div);
    -    assertEquals(10, pos.x);
    -    assertEquals(10, pos.y);
    -
    -    // Test with a position fixed element as parent
    -    var innerDiv = goog.dom.createDom('DIV');
    -    div = goog.dom.createDom('DIV');
    -    div.style.position = 'fixed';
    -    div.style.top = '10px';
    -    div.style.left = '10px';
    -    div.style.padding = '5px';
    -    div.appendChild(innerDiv);
    -    document.body.appendChild(div);
    -    pos = goog.style.getPageOffset(innerDiv);
    -    assertEquals(15, pos.x);
    -    assertEquals(15, pos.y);
    -  }
    -}
    -
    -function testGetPositionTolerantToNoDocumentElementBorder() {
    -  // In IE, removing the border on the document element undoes the normal
    -  // 2-pixel offset.  Ensure that we're correctly compensating for both cases.
    -  try {
    -    document.documentElement.style.borderWidth = '0';
    -    var div = goog.dom.createDom('DIV');
    -    div.style.position = 'absolute';
    -    div.style.left = '100px';
    -    div.style.top = '200px';
    -    document.body.appendChild(div);
    -
    -    // Test all major positioning methods.
    -    // Disabled for IE8 and below - IE8 returns dimensions multiplied by 100.
    -    expectedFailures.expectFailureFor(
    -        goog.userAgent.IE && !goog.userAgent.isVersionOrHigher(9));
    -    try {
    -      // Test all major positioning methods.
    -      var pos = goog.style.getClientPosition(div);
    -      assertEquals(100, pos.x);
    -      assertRoughlyEquals(200, pos.y, .1);
    -      var offset = goog.style.getPageOffset(div);
    -      assertEquals(100, offset.x);
    -      assertRoughlyEquals(200, offset.y, .1);
    -    } catch (e) {
    -      expectedFailures.handleException(e);
    -    }
    -  } finally {
    -    document.documentElement.style.borderWidth = '';
    -  }
    -}
    -
    -function testSetSize() {
    -  var el = $('testEl');
    -
    -  goog.style.setSize(el, 100, 100);
    -  assertEquals('100px', el.style.width);
    -  assertEquals('100px', el.style.height);
    -
    -  goog.style.setSize(el, '50px', '25px');
    -  assertEquals('should be "50px"', '50px', el.style.width);
    -  assertEquals('should be "25px"', '25px', el.style.height);
    -
    -  goog.style.setSize(el, '10ex', '25px');
    -  assertEquals('10ex', el.style.width);
    -  assertEquals('25px', el.style.height);
    -
    -  goog.style.setSize(el, '10%', '25%');
    -  assertEquals('10%', el.style.width);
    -  assertEquals('25%', el.style.height);
    -
    -  // ignores stupid units
    -  goog.style.setSize(el, 0, 0);
    -  // TODO(user): IE errors if you set these values.  Should we make setStyle
    -  // catch these?  Or leave it up to the app.  Fixing the tests for now.
    -  //goog.style.setSize(el, '10rainbows', '25rainbows');
    -  assertEquals('0px', el.style.width);
    -  assertEquals('0px', el.style.height);
    -
    -  goog.style.setSize(el, new goog.math.Size(20, 40));
    -  assertEquals('20px', el.style.width);
    -  assertEquals('40px', el.style.height);
    -}
    -
    -function testSetWidthAndHeight() {
    -  var el = $('testEl');
    -
    -  // Replicate all of the setSize tests above.
    -
    -  goog.style.setWidth(el, 100);
    -  goog.style.setHeight(el, 100);
    -  assertEquals('100px', el.style.width);
    -  assertEquals('100px', el.style.height);
    -
    -  goog.style.setWidth(el, '50px');
    -  goog.style.setHeight(el, '25px');
    -  assertEquals('should be "50px"', '50px', el.style.width);
    -  assertEquals('should be "25px"', '25px', el.style.height);
    -
    -  goog.style.setWidth(el, '10ex');
    -  goog.style.setHeight(el, '25px');
    -  assertEquals('10ex', el.style.width);
    -  assertEquals('25px', el.style.height);
    -
    -  goog.style.setWidth(el, '10%');
    -  goog.style.setHeight(el, '25%');
    -  assertEquals('10%', el.style.width);
    -  assertEquals('25%', el.style.height);
    -
    -  goog.style.setWidth(el, 0);
    -  goog.style.setHeight(el, 0);
    -  assertEquals('0px', el.style.width);
    -  assertEquals('0px', el.style.height);
    -
    -  goog.style.setWidth(el, 20);
    -  goog.style.setHeight(el, 40);
    -  assertEquals('20px', el.style.width);
    -  assertEquals('40px', el.style.height);
    -
    -  // Additional tests testing each separately.
    -  goog.style.setWidth(el, '');
    -  goog.style.setHeight(el, '');
    -  assertEquals('', el.style.width);
    -  assertEquals('', el.style.height);
    -
    -  goog.style.setHeight(el, 20);
    -  assertEquals('', el.style.width);
    -  assertEquals('20px', el.style.height);
    -
    -  goog.style.setWidth(el, 40);
    -  assertEquals('40px', el.style.width);
    -  assertEquals('20px', el.style.height);
    -}
    -
    -function testGetSize() {
    -  var el = $('testEl');
    -  goog.style.setSize(el, 100, 100);
    -
    -  var dims = goog.style.getSize(el);
    -  assertEquals(100, dims.width);
    -  assertEquals(100, dims.height);
    -
    -  goog.style.setStyle(el, 'display', 'none');
    -  dims = goog.style.getSize(el);
    -  assertEquals(100, dims.width);
    -  assertEquals(100, dims.height);
    -
    -  el = $('testEl5');
    -  goog.style.setSize(el, 100, 100);
    -  dims = goog.style.getSize(el);
    -  assertEquals(100, dims.width);
    -  assertEquals(100, dims.height);
    -
    -  el = $('span0');
    -  dims = goog.style.getSize(el);
    -  assertNotEquals(0, dims.width);
    -  assertNotEquals(0, dims.height);
    -
    -  el = $('table1');
    -  dims = goog.style.getSize(el);
    -  assertNotEquals(0, dims.width);
    -  assertNotEquals(0, dims.height);
    -
    -  el = $('td1');
    -  dims = goog.style.getSize(el);
    -  assertNotEquals(0, dims.width);
    -  assertNotEquals(0, dims.height);
    -
    -  el = $('li1');
    -  dims = goog.style.getSize(el);
    -  assertNotEquals(0, dims.width);
    -  assertNotEquals(0, dims.height);
    -
    -  el = goog.dom.getElementsByTagNameAndClass('html')[0];
    -  dims = goog.style.getSize(el);
    -  assertNotEquals(0, dims.width);
    -  assertNotEquals(0, dims.height);
    -
    -  el = goog.dom.getElementsByTagNameAndClass('body')[0];
    -  dims = goog.style.getSize(el);
    -  assertNotEquals(0, dims.width);
    -  assertNotEquals(0, dims.height);
    -}
    -
    -function testGetSizeSvgElements() {
    -  var svgEl = document.createElementNS &&
    -      document.createElementNS('http://www.w3.org/2000/svg', 'svg');
    -  if (!svgEl || svgEl.getAttribute('transform') == '' ||
    -      (goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher(534.8))) {
    -    // SVG not supported, or getBoundingClientRect not supported on SVG
    -    // elements.
    -    return;
    -  }
    -
    -  document.body.appendChild(svgEl);
    -  var el = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
    -  el.setAttribute('x', 10);
    -  el.setAttribute('y', 10);
    -  el.setAttribute('width', 32);
    -  el.setAttribute('height', 21);
    -  el.setAttribute('fill', '#000');
    -
    -  svgEl.appendChild(el);
    -
    -  // The bounding size in 1 larger than the SVG element in IE.
    -  var expectedWidth = (goog.userAgent.IE) ? 33 : 32;
    -  var expectedHeight = (goog.userAgent.IE) ? 22 : 21;
    -
    -  var dims = goog.style.getSize(el);
    -  assertEquals(expectedWidth, dims.width);
    -  assertRoughlyEquals(expectedHeight, dims.height, 0.01);
    -
    -  dims = goog.style.getSize(svgEl);
    -  // The size of the <svg> will be the viewport size on all browsers. This used
    -  // to not be true for Firefox, but they fixed the glitch in Firefox 33.
    -  // https://bugzilla.mozilla.org/show_bug.cgi?id=530985
    -  assertTrue(dims.width >= expectedWidth);
    -  assertTrue(dims.height >= expectedHeight);
    -
    -  el.style.visibility = 'none';
    -
    -  dims = goog.style.getSize(el);
    -  assertEquals(expectedWidth, dims.width);
    -  assertRoughlyEquals(expectedHeight, dims.height, 0.01);
    -
    -  dims = goog.style.getSize(svgEl);
    -  assertTrue(dims.width >= expectedWidth);
    -  assertTrue(dims.height >= expectedHeight);
    -}
    -
    -function testGetSizeSvgDocument() {
    -  var svgEl = document.createElementNS &&
    -      document.createElementNS('http://www.w3.org/2000/svg', 'svg');
    -  if (!svgEl || svgEl.getAttribute('transform') == '' ||
    -      (goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher(534.8))) {
    -    // SVG not supported, or getBoundingClientRect not supported on SVG
    -    // elements.
    -    return;
    -  }
    -
    -  var frame = goog.dom.getElement('svg-frame');
    -  var doc = goog.dom.getFrameContentDocument(frame);
    -  var rect = doc.getElementById('rect');
    -  var dims = goog.style.getSize(rect);
    -  if (!goog.userAgent.IE) {
    -    assertEquals(50, dims.width);
    -    assertEquals(50, dims.height);
    -  } else {
    -    assertEquals(51, dims.width);
    -    assertEquals(51, dims.height);
    -  }
    -}
    -
    -function testGetSizeInlineBlock() {
    -  var el = $('height-test-inner');
    -  var dims = goog.style.getSize(el);
    -  assertNotEquals(0, dims.height);
    -}
    -
    -function testGetSizeTransformedRotated() {
    -  if (!hasWebkitTransform()) return;
    -
    -  var el = $('rotated');
    -  goog.style.setSize(el, 300, 200);
    -
    -  var noRotateDims = goog.style.getTransformedSize(el);
    -  assertEquals(300, noRotateDims.width);
    -  assertEquals(200, noRotateDims.height);
    -
    -  el.style.webkitTransform = 'rotate(180deg)';
    -  var rotate180Dims = goog.style.getTransformedSize(el);
    -  assertEquals(300, rotate180Dims.width);
    -  assertEquals(200, rotate180Dims.height);
    -
    -  el.style.webkitTransform = 'rotate(90deg)';
    -  var rotate90ClockwiseDims = goog.style.getTransformedSize(el);
    -  assertEquals(200, rotate90ClockwiseDims.width);
    -  assertEquals(300, rotate90ClockwiseDims.height);
    -
    -  el.style.webkitTransform = 'rotate(-90deg)';
    -  var rotate90CounterClockwiseDims = goog.style.getTransformedSize(el);
    -  assertEquals(200, rotate90CounterClockwiseDims.width);
    -  assertEquals(300, rotate90CounterClockwiseDims.height);
    -}
    -
    -function testGetSizeTransformedScaled() {
    -  if (!hasWebkitTransform()) return;
    -
    -  var el = $('scaled');
    -  goog.style.setSize(el, 300, 200);
    -
    -  var noScaleDims = goog.style.getTransformedSize(el);
    -  assertEquals(300, noScaleDims.width);
    -  assertEquals(200, noScaleDims.height);
    -
    -  el.style.webkitTransform = 'scale(2, 0.5)';
    -  var scaledDims = goog.style.getTransformedSize(el);
    -  assertEquals(600, scaledDims.width);
    -  assertEquals(100, scaledDims.height);
    -}
    -
    -function hasWebkitTransform() {
    -  return 'webkitTransform' in document.body.style;
    -}
    -
    -function testGetSizeOfOrphanElement() {
    -  var orphanElem = document.createElement('DIV');
    -  var size = goog.style.getSize(orphanElem);
    -  assertEquals(0, size.width);
    -  assertEquals(0, size.height);
    -}
    -
    -function testGetBounds() {
    -  var el = $('testEl');
    -
    -  var dims = goog.style.getSize(el);
    -  var pos = goog.style.getPageOffset(el);
    -
    -  var rect = goog.style.getBounds(el);
    -
    -  // Relies on getSize and getPageOffset being correct.
    -  assertEquals(dims.width, rect.width);
    -  assertEquals(dims.height, rect.height);
    -  assertEquals(pos.x, rect.left);
    -  assertEquals(pos.y, rect.top);
    -}
    -
    -function testInstallStyles() {
    -  var el = $('installTest0');
    -  var originalBackground = goog.style.getBackgroundColor(el);
    -
    -  // Uses background-color because it's easy to get the computed value
    -  var result = goog.style.installStyles(
    -      '#installTest0 { background-color: rgb(255, 192, 203); }');
    -
    -  // For some odd reason, the change in computed style does not register on
    -  // Chrome 19 unless the style property is touched.  The behavior goes
    -  // away again in Chrome 20.
    -  // TODO(nnaze): Remove special caseing once we switch the testing image
    -  // to Chrome 20 or higher.
    -  if (isChrome19()) {
    -    el.style.display = '';
    -  }
    -
    -  assertColorRgbEquals('rgb(255,192,203)', goog.style.getBackgroundColor(el));
    -
    -  goog.style.uninstallStyles(result);
    -  assertEquals(originalBackground, goog.style.getBackgroundColor(el));
    -}
    -
    -function testSetStyles() {
    -  var el = $('installTest1');
    -
    -  // Change to pink
    -  var ss = goog.style.installStyles(
    -      '#installTest1 { background-color: rgb(255, 192, 203); }');
    -
    -  // For some odd reason, the change in computed style does not register on
    -  // Chrome 19 unless the style property is touched.  The behavior goes
    -  // away again in Chrome 20.
    -  // TODO(nnaze): Remove special caseing once we switch the testing image
    -  // to Chrome 20 or higher.
    -  if (isChrome19()) {
    -    el.style.display = '';
    -  }
    -
    -  assertColorRgbEquals('rgb(255,192,203)', goog.style.getBackgroundColor(el));
    -
    -  // Now change to orange
    -  goog.style.setStyles(ss,
    -      '#installTest1 { background-color: rgb(255, 255, 0); }');
    -  assertColorRgbEquals('rgb(255,255,0)', goog.style.getBackgroundColor(el));
    -}
    -
    -function assertColorRgbEquals(expected, actual) {
    -  assertEquals(expected,
    -      goog.color.hexToRgbStyle(goog.color.parse(actual).hex));
    -}
    -
    -function isChrome19() {
    -  return goog.userAgent.product.CHROME &&
    -         goog.string.startsWith(goog.userAgent.product.VERSION, '19.');
    -}
    -
    -function testIsRightToLeft() {
    -  assertFalse(goog.style.isRightToLeft($('rtl1')));
    -  assertTrue(goog.style.isRightToLeft($('rtl2')));
    -  assertFalse(goog.style.isRightToLeft($('rtl3')));
    -  assertFalse(goog.style.isRightToLeft($('rtl4')));
    -  assertTrue(goog.style.isRightToLeft($('rtl5')));
    -  assertFalse(goog.style.isRightToLeft($('rtl6')));
    -  assertTrue(goog.style.isRightToLeft($('rtl7')));
    -  assertFalse(goog.style.isRightToLeft($('rtl8')));
    -  assertTrue(goog.style.isRightToLeft($('rtl9')));
    -  assertFalse(goog.style.isRightToLeft($('rtl10')));
    -}
    -
    -function testPosWithAbsoluteAndScroll() {
    -  var el = $('pos-scroll-abs');
    -  var el1 = $('pos-scroll-abs-1');
    -  var el2 = $('pos-scroll-abs-2');
    -
    -  el1.scrollTop = 200;
    -  var pos = goog.style.getPageOffset(el2);
    -
    -  assertEquals(200, pos.x);
    -  // Don't bother with IE in quirks mode
    -  if (!goog.userAgent.IE || document.compatMode == 'CSS1Compat') {
    -    assertRoughlyEquals(300, pos.y, .1);
    -  }
    -}
    -
    -function testPosWithAbsoluteAndWindowScroll() {
    -  window.scrollBy(0, 200);
    -  var el = $('abs-upper-left');
    -  var pos = goog.style.getPageOffset(el);
    -  assertRoughlyEquals('Top should be about 0', 0, pos.y, 0.1);
    -}
    -
    -function testGetBorderBoxSize() {
    -  // Strict mode
    -  var getBorderBoxSize = goog.style.getBorderBoxSize;
    -
    -  var el = $('size-a');
    -  var rect = getBorderBoxSize(el);
    -  assertEquals('width:100px', 100, rect.width);
    -  assertEquals('height:100px', 100, rect.height);
    -
    -  // with border: 10px
    -  el = $('size-b');
    -  rect = getBorderBoxSize(el);
    -  assertEquals('width:100px;border:10px', isBorderBox ? 100 : 120, rect.width);
    -  assertEquals('height:100px;border:10px', isBorderBox ? 100 : 120,
    -               rect.height);
    -
    -  // with border: 10px; padding: 10px
    -  el = $('size-c');
    -  rect = getBorderBoxSize(el);
    -  assertEquals('width:100px;border:10px;padding:10px',
    -               isBorderBox ? 100 : 140, rect.width);
    -  assertEquals('height:100px;border:10px;padding:10px',
    -               isBorderBox ? 100 : 140, rect.height);
    -
    -  // size, padding and borders are all in non pixel units
    -  // all we test here is that we get a number out
    -  el = $('size-d');
    -  rect = getBorderBoxSize(el);
    -  assertEquals('number', typeof rect.width);
    -  assertEquals('number', typeof rect.height);
    -  assertFalse(isNaN(rect.width));
    -  assertFalse(isNaN(rect.height));
    -}
    -
    -function testGetContentBoxSize() {
    -  // Strict mode
    -  var getContentBoxSize = goog.style.getContentBoxSize;
    -
    -  var el = $('size-a');
    -  var rect = getContentBoxSize(el);
    -  assertEquals('width:100px', 100, rect.width);
    -  assertEquals('height:100px', 100, rect.height);
    -
    -  // with border: 10px
    -  el = $('size-b');
    -  rect = getContentBoxSize(el);
    -  assertEquals('width:100px;border:10px',
    -               isBorderBox ? 80 : 100, rect.width);
    -  assertEquals('height:100px;border:10px',
    -               isBorderBox ? 80 : 100, rect.height);
    -
    -  // with border: 10px; padding: 10px
    -  el = $('size-c');
    -  rect = getContentBoxSize(el);
    -  assertEquals('width:100px;border:10px;padding:10px',
    -               isBorderBox ? 60 : 100, rect.width);
    -  assertEquals('height:100px;border:10px;padding:10px',
    -               isBorderBox ? 60 : 100, rect.height);
    -
    -  // size, padding and borders are all in non pixel units
    -  // all we test here is that we get a number out
    -  el = $('size-d');
    -  rect = getContentBoxSize(el);
    -  assertEquals('number', typeof rect.width);
    -  assertEquals('number', typeof rect.height);
    -  assertFalse(isNaN(rect.width));
    -  assertFalse(isNaN(rect.height));
    -
    -  // test whether getContentBoxSize works when width and height
    -  // aren't explicitly set, but the default of 'auto'.
    -  // 'size-f' has no margin, border, or padding, so offsetWidth/Height
    -  // should match the content box size
    -  el = $('size-f');
    -  rect = getContentBoxSize(el);
    -  assertEquals(el.offsetWidth, rect.width);
    -  assertEquals(el.offsetHeight, rect.height);
    -}
    -
    -function testSetBorderBoxSize() {
    -  // Strict mode
    -  var el = $('size-e');
    -  var Size = goog.math.Size;
    -  var setBorderBoxSize = goog.style.setBorderBoxSize;
    -
    -  // Clean up
    -  // style element has 100x100, no border and no padding
    -  el.style.padding = '';
    -  el.style.margin = '';
    -  el.style.borderWidth = '';
    -  el.style.width = '';
    -  el.style.height = '';
    -
    -  setBorderBoxSize(el, new Size(100, 100));
    -
    -  assertEquals(100, el.offsetWidth);
    -  assertEquals(100, el.offsetHeight);
    -
    -  el.style.borderWidth = '10px';
    -  setBorderBoxSize(el, new Size(100, 100));
    -
    -  assertEquals('width:100px;border:10px', 100, el.offsetWidth);
    -  assertEquals('height:100px;border:10px', 100, el.offsetHeight);
    -
    -  el.style.padding = '10px';
    -  setBorderBoxSize(el, new Size(100, 100));
    -  assertEquals(100, el.offsetWidth);
    -  assertEquals(100, el.offsetHeight);
    -
    -  el.style.borderWidth = '0';
    -  setBorderBoxSize(el, new Size(100, 100));
    -  assertEquals(100, el.offsetWidth);
    -  assertEquals(100, el.offsetHeight);
    -
    -  if (goog.userAgent.GECKO) {
    -    assertEquals('border-box', el.style.MozBoxSizing);
    -  } else if (goog.userAgent.WEBKIT) {
    -    assertEquals('border-box', el.style.WebkitBoxSizing);
    -  } else if (goog.userAgent.OPERA ||
    -      goog.userAgent.IE && goog.userAgent.isDocumentModeOrHigher(8)) {
    -    assertEquals('border-box', el.style.boxSizing);
    -  }
    -
    -  // Try a negative width/height.
    -  setBorderBoxSize(el, new Size(-10, -10));
    -
    -  // Setting the border box smaller than the borders will just give you
    -  // a content box of size 0.
    -  // NOTE(nicksantos): I'm not really sure why IE7 is special here.
    -  var isIeLt8Quirks = goog.userAgent.IE &&
    -      !goog.userAgent.isDocumentModeOrHigher(8) &&
    -      !goog.dom.isCss1CompatMode();
    -  assertEquals(20, el.offsetWidth);
    -  assertEquals(isIeLt8Quirks ? 39 : 20, el.offsetHeight);
    -}
    -
    -function testSetContentBoxSize() {
    -  // Strict mode
    -  var el = $('size-e');
    -  var Size = goog.math.Size;
    -  var setContentBoxSize = goog.style.setContentBoxSize;
    -
    -  // Clean up
    -  // style element has 100x100, no border and no padding
    -  el.style.padding = '';
    -  el.style.margin = '';
    -  el.style.borderWidth = '';
    -  el.style.width = '';
    -  el.style.height = '';
    -
    -  setContentBoxSize(el, new Size(100, 100));
    -
    -  assertEquals(100, el.offsetWidth);
    -  assertEquals(100, el.offsetHeight);
    -
    -  el.style.borderWidth = '10px';
    -  setContentBoxSize(el, new Size(100, 100));
    -  assertEquals('width:100px;border-width:10px', 120, el.offsetWidth);
    -  assertEquals('height:100px;border-width:10px', 120, el.offsetHeight);
    -
    -  el.style.padding = '10px';
    -  setContentBoxSize(el, new Size(100, 100));
    -  assertEquals('width:100px;border-width:10px;padding:10px',
    -               140, el.offsetWidth);
    -  assertEquals('height:100px;border-width:10px;padding:10px',
    -               140, el.offsetHeight);
    -
    -  el.style.borderWidth = '0';
    -  setContentBoxSize(el, new Size(100, 100));
    -  assertEquals('width:100px;padding:10px', 120, el.offsetWidth);
    -  assertEquals('height:100px;padding:10px', 120, el.offsetHeight);
    -
    -  if (goog.userAgent.GECKO) {
    -    assertEquals('content-box', el.style.MozBoxSizing);
    -  } else if (goog.userAgent.WEBKIT) {
    -    assertEquals('content-box', el.style.WebkitBoxSizing);
    -  } else if (goog.userAgent.OPERA ||
    -      goog.userAgent.IE && goog.userAgent.isDocumentModeOrHigher(8)) {
    -    assertEquals('content-box', el.style.boxSizing);
    -  }
    -
    -  // Try a negative width/height.
    -  setContentBoxSize(el, new Size(-10, -10));
    -
    -  // NOTE(nicksantos): I'm not really sure why IE7 is special here.
    -  var isIeLt8Quirks = goog.userAgent.IE &&
    -      !goog.userAgent.isDocumentModeOrHigher('8') &&
    -      !goog.dom.isCss1CompatMode();
    -  assertEquals(20, el.offsetWidth);
    -  assertEquals(isIeLt8Quirks ? 39 : 20, el.offsetHeight);
    -}
    -
    -function testGetPaddingBox() {
    -  // Strict mode
    -  var el = $('size-e');
    -  var Size = goog.math.Size;
    -  var getPaddingBox = goog.style.getPaddingBox;
    -
    -  // Clean up
    -  // style element has 100x100, no border and no padding
    -  el.style.padding = '';
    -  el.style.margin = '';
    -  el.style.borderWidth = '';
    -  el.style.width = '';
    -  el.style.height = '';
    -
    -  el.style.padding = '10px';
    -  var rect = getPaddingBox(el);
    -  assertEquals(10, rect.left);
    -  assertEquals(10, rect.right);
    -  assertEquals(10, rect.top);
    -  assertEquals(10, rect.bottom);
    -
    -  el.style.padding = '0';
    -  rect = getPaddingBox(el);
    -  assertEquals(0, rect.left);
    -  assertEquals(0, rect.right);
    -  assertEquals(0, rect.top);
    -  assertEquals(0, rect.bottom);
    -
    -  el.style.padding = '1px 2px 3px 4px';
    -  rect = getPaddingBox(el);
    -  assertEquals(1, rect.top);
    -  assertEquals(2, rect.right);
    -  assertEquals(3, rect.bottom);
    -  assertEquals(4, rect.left);
    -
    -  el.style.padding = '1mm 2em 3ex 4%';
    -  rect = getPaddingBox(el);
    -  assertFalse(isNaN(rect.top));
    -  assertFalse(isNaN(rect.right));
    -  assertFalse(isNaN(rect.bottom));
    -  assertFalse(isNaN(rect.left));
    -  assertTrue(rect.top >= 0);
    -  assertTrue(rect.right >= 0);
    -  assertTrue(rect.bottom >= 0);
    -  assertTrue(rect.left >= 0);
    -}
    -
    -function testGetPaddingBoxUnattached() {
    -  var el = document.createElement('div');
    -  var box = goog.style.getPaddingBox(el);
    -  if (goog.userAgent.WEBKIT) {
    -    assertTrue(isNaN(box.top));
    -    assertTrue(isNaN(box.right));
    -    assertTrue(isNaN(box.bottom));
    -    assertTrue(isNaN(box.left));
    -  } else {
    -    assertObjectEquals(new goog.math.Box(0, 0, 0, 0), box);
    -  }
    -}
    -
    -function testGetMarginBox() {
    -  // Strict mode
    -  var el = $('size-e');
    -  var Size = goog.math.Size;
    -  var getMarginBox = goog.style.getMarginBox;
    -
    -  // Clean up
    -  // style element has 100x100, no border and no padding
    -  el.style.padding = '';
    -  el.style.margin = '';
    -  el.style.borderWidth = '';
    -  el.style.width = '';
    -  el.style.height = '';
    -
    -  el.style.margin = '10px';
    -  var rect = getMarginBox(el);
    -  assertEquals(10, rect.left);
    -  // In webkit the right margin is the calculated distance from right edge and
    -  // not the computed right margin so it is not reliable.
    -  // See https://bugs.webkit.org/show_bug.cgi?id=19828
    -  if (!goog.userAgent.WEBKIT) {
    -    assertEquals(10, rect.right);
    -  }
    -  assertEquals(10, rect.top);
    -  assertEquals(10, rect.bottom);
    -
    -  el.style.margin = '0';
    -  rect = getMarginBox(el);
    -  assertEquals(0, rect.left);
    -  // In webkit the right margin is the calculated distance from right edge and
    -  // not the computed right margin so it is not reliable.
    -  // See https://bugs.webkit.org/show_bug.cgi?id=19828
    -  if (!goog.userAgent.WEBKIT) {
    -    assertEquals(0, rect.right);
    -  }
    -  assertEquals(0, rect.top);
    -  assertEquals(0, rect.bottom);
    -
    -  el.style.margin = '1px 2px 3px 4px';
    -  rect = getMarginBox(el);
    -  assertEquals(1, rect.top);
    -  // In webkit the right margin is the calculated distance from right edge and
    -  // not the computed right margin so it is not reliable.
    -  // See https://bugs.webkit.org/show_bug.cgi?id=19828
    -  if (!goog.userAgent.WEBKIT) {
    -    assertEquals(2, rect.right);
    -  }
    -  assertEquals(3, rect.bottom);
    -  assertEquals(4, rect.left);
    -
    -  el.style.margin = '1mm 2em 3ex 4%';
    -  rect = getMarginBox(el);
    -  assertFalse(isNaN(rect.top));
    -  assertFalse(isNaN(rect.right));
    -  assertFalse(isNaN(rect.bottom));
    -  assertFalse(isNaN(rect.left));
    -  assertTrue(rect.top >= 0);
    -  // In webkit the right margin is the calculated distance from right edge and
    -  // not the computed right margin so it is not reliable.
    -  // See https://bugs.webkit.org/show_bug.cgi?id=19828
    -  if (!goog.userAgent.WEBKIT) {
    -    assertTrue(rect.right >= 0);
    -  }
    -  assertTrue(rect.bottom >= 0);
    -  assertTrue(rect.left >= 0);
    -}
    -
    -function testGetBorderBox() {
    -  // Strict mode
    -  var el = $('size-e');
    -  var Size = goog.math.Size;
    -  var getBorderBox = goog.style.getBorderBox;
    -
    -  // Clean up
    -  // style element has 100x100, no border and no padding
    -  el.style.padding = '';
    -  el.style.margin = '';
    -  el.style.borderWidth = '';
    -  el.style.width = '';
    -  el.style.height = '';
    -
    -  el.style.borderWidth = '10px';
    -  var rect = getBorderBox(el);
    -  assertEquals(10, rect.left);
    -  assertEquals(10, rect.right);
    -  assertEquals(10, rect.top);
    -  assertEquals(10, rect.bottom);
    -
    -  el.style.borderWidth = '0';
    -  rect = getBorderBox(el);
    -  assertEquals(0, rect.left);
    -  assertEquals(0, rect.right);
    -  assertEquals(0, rect.top);
    -  assertEquals(0, rect.bottom);
    -
    -  el.style.borderWidth = '1px 2px 3px 4px';
    -  rect = getBorderBox(el);
    -  assertEquals(1, rect.top);
    -  assertEquals(2, rect.right);
    -  assertEquals(3, rect.bottom);
    -  assertEquals(4, rect.left);
    -
    -  // % does not work for border widths in IE
    -  el.style.borderWidth = '1mm 2em 3ex 4pt';
    -  rect = getBorderBox(el);
    -  assertFalse(isNaN(rect.top));
    -  assertFalse(isNaN(rect.right));
    -  assertFalse(isNaN(rect.bottom));
    -  assertFalse(isNaN(rect.left));
    -  assertTrue(rect.top >= 0);
    -  assertTrue(rect.right >= 0);
    -  assertTrue(rect.bottom >= 0);
    -  assertTrue(rect.left >= 0);
    -
    -  el.style.borderWidth = 'thin medium thick 1px';
    -  rect = getBorderBox(el);
    -  assertFalse(isNaN(rect.top));
    -  assertFalse(isNaN(rect.right));
    -  assertFalse(isNaN(rect.bottom));
    -  assertFalse(isNaN(rect.left));
    -  assertTrue(rect.top >= 0);
    -  assertTrue(rect.right >= 0);
    -  assertTrue(rect.bottom >= 0);
    -  assertTrue(rect.left >= 0);
    -}
    -
    -function testGetFontFamily() {
    -  // I tried to use common fonts for these tests. It's possible the test fails
    -  // because the testing platform doesn't have one of these fonts installed:
    -  //   Comic Sans MS or Century Schoolbook L
    -  //   Times
    -  //   Helvetica
    -
    -  var tmpFont = goog.style.getFontFamily($('font-tag'));
    -  assertTrue('FontFamily should be detectable when set via <font face>',
    -             'Times' == tmpFont || 'Times New Roman' == tmpFont);
    -  tmpFont = goog.style.getFontFamily($('small-text'));
    -  assertTrue('Multiword fonts should be reported with quotes stripped.',
    -             'Comic Sans MS' == tmpFont ||
    -                 'Century Schoolbook L' == tmpFont);
    -  // Firefox fails this test & retuns a generic 'monospace' instead of the
    -  // actually displayed font (e.g., "Times New").
    -  //tmpFont = goog.style.getFontFamily($('pre-font'));
    -  //assertEquals('<pre> tags should use a fixed-width font',
    -  //             'Times New',
    -  //             tmpFont);
    -  tmpFont = goog.style.getFontFamily($('inherit-font'));
    -  assertEquals('Explicitly inherited fonts should be detectable',
    -               'Helvetica',
    -               tmpFont);
    -  tmpFont = goog.style.getFontFamily($('times-font-family'));
    -  assertEquals('Font-family set via style attribute should be detected',
    -               'Times',
    -               tmpFont);
    -  tmpFont = goog.style.getFontFamily($('bold-font'));
    -  assertEquals('Implicitly inherited font should be detected',
    -               'Helvetica',
    -               tmpFont);
    -  tmpFont = goog.style.getFontFamily($('css-html-tag-redefinition'));
    -  assertEquals('HTML tag CSS rewrites should be detected',
    -               'Times',
    -               tmpFont);
    -  tmpFont = goog.style.getFontFamily($('no-text-font-styles'));
    -  assertEquals('Font family should exist even with no text',
    -               'Helvetica',
    -               tmpFont);
    -  tmpFont = goog.style.getFontFamily($('icon-font'));
    -  assertNotEquals('icon is a special font-family value',
    -                  'icon',
    -                  tmpFont.toLowerCase());
    -  tmpFont = goog.style.getFontFamily($('font-style-badfont'));
    -  // Firefox fails this test and reports the specified "badFont", which is
    -  // obviously not displayed.
    -  //assertEquals('Invalid fonts should not be returned',
    -  //             'Helvetica',
    -  //             tmpFont);
    -  tmpFont = goog.style.getFontFamily($('img-font-test'));
    -  assertTrue('Even img tags should inherit the document body\'s font',
    -             tmpFont != '');
    -  tmpFont = goog.style.getFontFamily($('nested-font'));
    -  assertEquals('An element with nested content should be unaffected.',
    -               'Arial',
    -               tmpFont);
    -  // IE raises an 'Invalid Argument' error when using the moveToElementText
    -  // method from the TextRange object with an element that is not attached to
    -  // a document.
    -  var element = goog.dom.createDom('span',
    -      {style: 'font-family:Times,sans-serif;'}, 'some text');
    -  tmpFont = goog.style.getFontFamily(element);
    -  assertEquals('Font should be correctly retrieved for element not attached' +
    -               ' to a document',
    -               'Times',
    -               tmpFont);
    -}
    -
    -function testGetFontSize() {
    -  assertEquals('Font size should be determined even without any text',
    -               30,
    -               goog.style.getFontSize($('no-text-font-styles')));
    -  assertEquals('A 5em font should be 5x larger than its parent.',
    -               150,
    -               goog.style.getFontSize($('css-html-tag-redefinition')));
    -  assertTrue('Setting font size=-1 should result in a positive font size.',
    -             goog.style.getFontSize($('font-tag')) > 0);
    -  assertEquals('Inheriting a 50% font-size should have no additional effect',
    -               goog.style.getFontSize($('font-style-badfont')),
    -               goog.style.getFontSize($('inherit-50pct-font')));
    -  assertTrue('In pretty much any display, 3in should be > 8px',
    -             goog.style.getFontSize($('times-font-family')) >
    -                 goog.style.getFontSize($('no-text-font-styles')));
    -  assertTrue('With no applied styles, font-size should still be defined.',
    -             goog.style.getFontSize($('no-font-style')) > 0);
    -  assertEquals('50% of 30px is 15',
    -               15,
    -               goog.style.getFontSize($('font-style-badfont')));
    -  assertTrue('x-small text should be smaller than small text',
    -             goog.style.getFontSize($('x-small-text')) <
    -                 goog.style.getFontSize($('small-text')));
    -  // IE fails this test, the decimal portion of px lengths isn't reported
    -  // by getCascadedStyle. Firefox passes, but only because it ignores the
    -  // decimals altogether.
    -  //assertEquals('12.5px should be the same as 0.5em nested in a 25px node.',
    -  //             goog.style.getFontSize($('font-size-12-point-5-px')),
    -  //             goog.style.getFontSize($('font-size-50-pct-of-25-px')));
    -
    -  assertEquals('Font size should not doubly count em values',
    -      2, goog.style.getFontSize($('em-font-size')));
    -}
    -
    -function testGetLengthUnits() {
    -  assertEquals('px', goog.style.getLengthUnits('15px'));
    -  assertEquals('%', goog.style.getLengthUnits('99%'));
    -  assertNull(goog.style.getLengthUnits(''));
    -}
    -
    -function testParseStyleAttribute() {
    -  var css = 'left: 0px; text-align: center';
    -  var expected = {'left': '0px', 'textAlign': 'center'};
    -
    -  assertObjectEquals(expected, goog.style.parseStyleAttribute(css));
    -}
    -
    -function testToStyleAttribute() {
    -  var object = {'left': '0px', 'textAlign': 'center'};
    -  var expected = 'left:0px;text-align:center;';
    -
    -  assertEquals(expected, goog.style.toStyleAttribute(object));
    -}
    -
    -function testStyleAttributePassthrough() {
    -  var object = {'left': '0px', 'textAlign': 'center'};
    -
    -  assertObjectEquals(object,
    -      goog.style.parseStyleAttribute(goog.style.toStyleAttribute(object)));
    -}
    -
    -function testGetFloat() {
    -  assertEquals('', goog.style.getFloat($('no-float')));
    -  assertEquals('none', goog.style.getFloat($('float-none')));
    -  assertEquals('left', goog.style.getFloat($('float-left')));
    -}
    -
    -function testSetFloat() {
    -  var el = $('float-test');
    -
    -  goog.style.setFloat(el, 'left');
    -  assertEquals('left', goog.style.getFloat(el));
    -
    -  goog.style.setFloat(el, 'right');
    -  assertEquals('right', goog.style.getFloat(el));
    -
    -  goog.style.setFloat(el, 'none');
    -  assertEquals('none', goog.style.getFloat(el));
    -
    -  goog.style.setFloat(el, '');
    -  assertEquals('', goog.style.getFloat(el));
    -}
    -
    -function testIsElementShown() {
    -  var el = $('testEl');
    -
    -  goog.style.setElementShown(el, false);
    -  assertFalse(goog.style.isElementShown(el));
    -
    -  goog.style.setElementShown(el, true);
    -  assertTrue(goog.style.isElementShown(el));
    -}
    -
    -function testGetOpacity() {
    -  var el1 = {
    -    style: {
    -      opacity: '0.3'
    -    }
    -  };
    -
    -  var el2 = {
    -    style: {
    -      MozOpacity: '0.1'
    -    }
    -  };
    -
    -  var el3 = {
    -    style: {
    -      filter: 'some:other,filter;alpha(opacity=25.5);alpha(more=100);'
    -    }
    -  };
    -
    -  assertEquals(0.3, goog.style.getOpacity(el1));
    -  assertEquals(0.1, goog.style.getOpacity(el2));
    -  assertEquals(0.255, goog.style.getOpacity(el3));
    -
    -  el1.style.opacity = '0';
    -  el2.style.MozOpacity = '0';
    -  el3.style.filter = 'some:other,filter;alpha(opacity=0);alpha(more=100);';
    -
    -  assertEquals(0, goog.style.getOpacity(el1));
    -  assertEquals(0, goog.style.getOpacity(el2));
    -  assertEquals(0, goog.style.getOpacity(el3));
    -
    -  el1.style.opacity = '';
    -  el2.style.MozOpacity = '';
    -  el3.style.filter = '';
    -
    -  assertEquals('', goog.style.getOpacity(el1));
    -  assertEquals('', goog.style.getOpacity(el2));
    -  assertEquals('', goog.style.getOpacity(el3));
    -
    -  var el4 = {
    -    style: {}
    -  };
    -
    -  assertEquals('', goog.style.getOpacity(el4));
    -  assertEquals('', goog.style.getOpacity($('test-opacity')));
    -}
    -
    -function testSetOpacity() {
    -  var el1 = {
    -    style: {
    -      opacity: '0.3'
    -    }
    -  };
    -  goog.style.setOpacity(el1, 0.8);
    -
    -  var el2 = {
    -    style: {
    -      MozOpacity: '0.1'
    -    }
    -  };
    -  goog.style.setOpacity(el2, 0.5);
    -
    -  var el3 = {
    -    style: {
    -      filter: 'alpha(opacity=25)'
    -    }
    -  };
    -  goog.style.setOpacity(el3, 0.1);
    -
    -  assertEquals(0.8, Number(el1.style.opacity));
    -  assertEquals(0.5, Number(el2.style.MozOpacity));
    -  assertEquals('alpha(opacity=10)', el3.style.filter);
    -
    -  goog.style.setOpacity(el1, 0);
    -  goog.style.setOpacity(el2, 0);
    -  goog.style.setOpacity(el3, 0);
    -
    -  assertEquals(0, Number(el1.style.opacity));
    -  assertEquals(0, Number(el2.style.MozOpacity));
    -  assertEquals('alpha(opacity=0)', el3.style.filter);
    -
    -  goog.style.setOpacity(el1, '');
    -  goog.style.setOpacity(el2, '');
    -  goog.style.setOpacity(el3, '');
    -
    -  assertEquals('', el1.style.opacity);
    -  assertEquals('', el2.style.MozOpacity);
    -  assertEquals('', el3.style.filter);
    -}
    -
    -function testFramedPageOffset() {
    -  // Set up a complicated iframe ancestor chain.
    -  var iframe = goog.dom.getElement('test-frame-offset');
    -  var iframeDoc = goog.dom.getFrameContentDocument(iframe);
    -  var iframeWindow = goog.dom.getWindow(iframeDoc);
    -
    -  var iframePos = 'style="display:block;position:absolute;' +
    -      'top:50px;left:50px;width:50px;height:50px;"';
    -  iframeDoc.write('<iframe id="test-frame-offset-2" ' +
    -      iframePos + '></iframe>' +
    -      '<div id="test-element-2" ' +
    -      ' style="position:absolute;left:300px;top:300px">hi mom!</div>');
    -  iframeDoc.close();
    -  var iframe2 = iframeDoc.getElementById('test-frame-offset-2');
    -  var testElement2 = iframeDoc.getElementById('test-element-2');
    -  var iframeDoc2 = goog.dom.getFrameContentDocument(iframe2);
    -  var iframeWindow2 = goog.dom.getWindow(iframeDoc2);
    -
    -  iframeDoc2.write(
    -      '<div id="test-element-3" ' +
    -      ' style="position:absolute;left:500px;top:500px">hi mom!</div>');
    -  iframeDoc2.close();
    -  var testElement3 = iframeDoc2.getElementById('test-element-3');
    -
    -  assertCoordinateApprox(300, 300, 0,
    -      goog.style.getPageOffset(testElement2));
    -  assertCoordinateApprox(500, 500, 0,
    -      goog.style.getPageOffset(testElement3));
    -
    -  assertCoordinateApprox(350, 350, 0,
    -      goog.style.getFramedPageOffset(testElement2, window));
    -  assertCoordinateApprox(300, 300, 0,
    -      goog.style.getFramedPageOffset(testElement2, iframeWindow));
    -
    -  assertCoordinateApprox(600, 600, 0,
    -      goog.style.getFramedPageOffset(testElement3, window));
    -  assertCoordinateApprox(550, 550, 0,
    -      goog.style.getFramedPageOffset(testElement3, iframeWindow));
    -  assertCoordinateApprox(500, 500, 0,
    -      goog.style.getFramedPageOffset(testElement3, iframeWindow2));
    -
    -  // Scroll the iframes a bit.
    -  window.scrollBy(0, 5);
    -  iframeWindow.scrollBy(0, 11);
    -  iframeWindow2.scrollBy(0, 18);
    -
    -  // On Firefox 2, scrolling inner iframes causes off by one errors
    -  // in the page position, because we're using screen coords to compute them.
    -  assertCoordinateApprox(300, 300, 2,
    -      goog.style.getPageOffset(testElement2));
    -  assertCoordinateApprox(500, 500, 2,
    -      goog.style.getPageOffset(testElement3));
    -
    -  assertCoordinateApprox(350, 350 - 11, 2,
    -      goog.style.getFramedPageOffset(testElement2, window));
    -  assertCoordinateApprox(300, 300, 2,
    -      goog.style.getFramedPageOffset(testElement2, iframeWindow));
    -
    -  assertCoordinateApprox(600, 600 - 18 - 11, 2,
    -      goog.style.getFramedPageOffset(testElement3, window));
    -  assertCoordinateApprox(550, 550 - 18, 2,
    -      goog.style.getFramedPageOffset(testElement3, iframeWindow));
    -  assertCoordinateApprox(500, 500, 2,
    -      goog.style.getFramedPageOffset(testElement3, iframeWindow2));
    -
    -  // In IE, if the element is in a frame that's been removed from the DOM and
    -  // relativeWin is not that frame's contentWindow, the contentWindow's parent
    -  // reference points to itself. We want to guarantee that we don't fall into
    -  // an infinite loop.
    -  var iframeParent = iframe.parentElement;
    -  iframeParent.removeChild(iframe);
    -  // We don't check the value returned as it differs by browser. 0,0 for Chrome
    -  // and FF. IE returns 30000 or 30198 for x in IE8-9 and 300 in IE10-11
    -  goog.style.getFramedPageOffset(testElement2, window);
    -}
    -
    -
    -/**
    - * Asserts that the coordinate is approximately equal to the given
    - * x and y coordinates, give or take delta.
    - */
    -function assertCoordinateApprox(x, y, delta, coord) {
    -  assertTrue('Expected x: ' + x + ', actual x: ' + coord.x,
    -      coord.x >= x - delta && coord.x <= x + delta);
    -  assertTrue('Expected y: ' + y + ', actual y: ' + coord.y,
    -      coord.y >= y - delta && coord.y <= y + delta);
    -}
    -
    -function testTranslateRectForAnotherFrame() {
    -  var rect = new goog.math.Rect(1, 2, 3, 4);
    -  var thisDom = goog.dom.getDomHelper();
    -  goog.style.translateRectForAnotherFrame(rect, thisDom, thisDom);
    -  assertEquals(1, rect.left);
    -  assertEquals(2, rect.top);
    -  assertEquals(3, rect.width);
    -  assertEquals(4, rect.height);
    -
    -  var iframe = $('test-translate-frame-standard');
    -  var iframeDoc = goog.dom.getFrameContentDocument(iframe);
    -  var iframeDom = goog.dom.getDomHelper(iframeDoc);
    -  // Cannot rely on iframe starting at origin.
    -  iframeDom.getWindow().scrollTo(0, 0);
    -  // iframe is at (100, 150) and its body is not scrolled.
    -  rect = new goog.math.Rect(1, 2, 3, 4);
    -  goog.style.translateRectForAnotherFrame(rect, iframeDom, thisDom);
    -  assertEquals(1 + 100, rect.left);
    -  assertRoughlyEquals(2 + 150, rect.top, .1);
    -  assertEquals(3, rect.width);
    -  assertEquals(4, rect.height);
    -
    -  iframeDom.getWindow().scrollTo(11, 13);
    -  rect = new goog.math.Rect(1, 2, 3, 4);
    -  goog.style.translateRectForAnotherFrame(rect, iframeDom, thisDom);
    -  assertEquals(1 + 100 - 11, rect.left);
    -  assertRoughlyEquals(2 + 150 - 13, rect.top, .1);
    -  assertEquals(3, rect.width);
    -  assertEquals(4, rect.height);
    -
    -  iframe = $('test-translate-frame-quirk');
    -  iframeDoc = goog.dom.getFrameContentDocument(iframe);
    -  iframeDom = goog.dom.getDomHelper(iframeDoc);
    -  // Cannot rely on iframe starting at origin.
    -  iframeDom.getWindow().scrollTo(0, 0);
    -  // iframe is at (100, 350) and its body is not scrolled.
    -  rect = new goog.math.Rect(1, 2, 3, 4);
    -  goog.style.translateRectForAnotherFrame(rect, iframeDom, thisDom);
    -  assertEquals(1 + 100, rect.left);
    -  assertRoughlyEquals(2 + 350, rect.top, .1);
    -  assertEquals(3, rect.width);
    -  assertEquals(4, rect.height);
    -
    -  iframeDom.getWindow().scrollTo(11, 13);
    -  rect = new goog.math.Rect(1, 2, 3, 4);
    -  goog.style.translateRectForAnotherFrame(rect, iframeDom, thisDom);
    -  assertEquals(1 + 100 - 11, rect.left);
    -  assertRoughlyEquals(2 + 350 - 13, rect.top, .1);
    -  assertEquals(3, rect.width);
    -  assertEquals(4, rect.height);
    -}
    -
    -function testGetVisibleRectForElement() {
    -  var container = goog.dom.getElement('test-visible');
    -  var el = goog.dom.getElement('test-visible-el');
    -  var dom = goog.dom.getDomHelper(el);
    -  var winScroll = dom.getDocumentScroll();
    -  var winSize = dom.getViewportSize();
    -
    -  // Skip this test if the window size is small.  Firefox3/Linux in Selenium
    -  // sometimes fails without this check.
    -  if (winSize.width < 20 || winSize.height < 20) {
    -    return;
    -  }
    -
    -  // Move the container element to the window's viewport.
    -  var h = winSize.height < 100 ? winSize.height / 2 : 100;
    -  goog.style.setSize(container, winSize.width / 2, h);
    -  goog.style.setPosition(container, 8, winScroll.y + winSize.height - h);
    -  var visible = goog.style.getVisibleRectForElement(el);
    -  var bounds = goog.style.getBounds(container);
    -  // VisibleRect == Bounds rect of the offsetParent
    -  assertNotNull(visible);
    -  assertEquals(bounds.left, visible.left);
    -  assertEquals(bounds.top, visible.top);
    -  assertEquals(bounds.left + bounds.width, visible.right);
    -  assertEquals(bounds.top + bounds.height, visible.bottom);
    -
    -  // Move a part of the container element to outside of the viewpoert.
    -  goog.style.setPosition(container, 8, winScroll.y + winSize.height - h / 2);
    -  visible = goog.style.getVisibleRectForElement(el);
    -  bounds = goog.style.getBounds(container);
    -  // Confirm VisibleRect == Intersection of the bounds rect of the
    -  // offsetParent and the viewport.
    -  assertNotNull(visible);
    -  assertEquals(bounds.left, visible.left);
    -  assertEquals(bounds.top, visible.top);
    -  assertEquals(bounds.left + bounds.width, visible.right);
    -  assertEquals(winScroll.y + winSize.height, visible.bottom);
    -
    -  // Move the container element to outside of the viewpoert.
    -  goog.style.setPosition(container, 8, winScroll.y + winSize.height * 2);
    -  visible = goog.style.getVisibleRectForElement(el);
    -  assertNull(visible);
    -
    -  // Test the case with body element of height 0
    -  var iframe = goog.dom.getElement('test-visible-frame');
    -  var iframeDoc = goog.dom.getFrameContentDocument(iframe);
    -  el = iframeDoc.getElementById('test-visible');
    -  visible = goog.style.getVisibleRectForElement(el);
    -
    -  var iframeViewportSize = goog.dom.getDomHelper(el).getViewportSize();
    -  // NOTE(chrishenry): For iframe, the clipping viewport is always the iframe
    -  // viewport, and not the actual browser viewport.
    -  assertNotNull(visible);
    -  assertEquals(0, visible.top);
    -  assertEquals(iframeViewportSize.height, visible.bottom);
    -  assertEquals(0, visible.left);
    -  assertEquals(iframeViewportSize.width, visible.right);
    -}
    -
    -function testGetVisibleRectForElementWithBodyScrolled() {
    -  var container = goog.dom.getElement('test-visible2');
    -  var dom = goog.dom.getDomHelper(container);
    -  var el = dom.createDom('div', undefined, 'Test');
    -  el.style.position = 'absolute';
    -  dom.append(container, el);
    -
    -  container.style.position = 'absolute';
    -  goog.style.setPosition(container, 20, 500);
    -  goog.style.setSize(container, 100, 150);
    -
    -  // Scroll body container such that container is exactly at top.
    -  window.scrollTo(0, 500);
    -  var visibleRect = goog.style.getVisibleRectForElement(el);
    -  assertNotNull(visibleRect);
    -  assertRoughlyEquals(500, visibleRect.top, EPSILON);
    -  assertRoughlyEquals(20, visibleRect.left, EPSILON);
    -  assertRoughlyEquals(650, visibleRect.bottom, EPSILON);
    -  assertRoughlyEquals(120, visibleRect.right, EPSILON);
    -
    -  // Top 100px is clipped by window viewport.
    -  window.scrollTo(0, 600);
    -  var visibleRect = goog.style.getVisibleRectForElement(el);
    -  assertNotNull(visibleRect);
    -  assertRoughlyEquals(600, visibleRect.top, EPSILON);
    -  assertRoughlyEquals(20, visibleRect.left, EPSILON);
    -  assertRoughlyEquals(650, visibleRect.bottom, EPSILON);
    -  assertRoughlyEquals(120, visibleRect.right, EPSILON);
    -
    -  var winSize = dom.getViewportSize();
    -
    -  // Left 50px is clipped by window viewport.
    -  // Right part is clipped by window viewport.
    -  goog.style.setSize(container, 10000, 150);
    -  window.scrollTo(70, 500);
    -  var visibleRect = goog.style.getVisibleRectForElement(el);
    -  assertNotNull(visibleRect);
    -  assertRoughlyEquals(500, visibleRect.top, EPSILON);
    -  assertRoughlyEquals(70, visibleRect.left, EPSILON);
    -  assertRoughlyEquals(650, visibleRect.bottom, EPSILON);
    -  assertRoughlyEquals(70 + winSize.width, visibleRect.right, EPSILON);
    -
    -  // Bottom part is clipped by window viewport.
    -  goog.style.setSize(container, 100, 2000);
    -  window.scrollTo(0, 500);
    -  var visibleRect = goog.style.getVisibleRectForElement(el);
    -  assertNotNull(visibleRect);
    -  assertRoughlyEquals(500, visibleRect.top, EPSILON);
    -  assertRoughlyEquals(20, visibleRect.left, EPSILON);
    -  assertRoughlyEquals(120, visibleRect.right, EPSILON);
    -  assertRoughlyEquals(500 + winSize.height, visibleRect.bottom, EPSILON);
    -
    -  goog.style.setPosition(container, 10000, 10000);
    -  assertNull(goog.style.getVisibleRectForElement(el));
    -}
    -
    -function testGetVisibleRectForElementWithNestedAreaAndNonOffsetAncestor() {
    -  // IE7 quirks mode somehow consider container2 below as offset parent
    -  // of the element, which is incorrect.
    -  if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(8) &&
    -      !goog.dom.isCss1CompatMode()) {
    -    return;
    -  }
    -
    -  var container = goog.dom.getElement('test-visible2');
    -  var dom = goog.dom.getDomHelper(container);
    -  var container2 = dom.createDom('div');
    -  var el = dom.createDom('div', undefined, 'Test');
    -  el.style.position = 'absolute';
    -  dom.append(container, container2);
    -  dom.append(container2, el);
    -
    -  container.style.position = 'absolute';
    -  goog.style.setPosition(container, 20, 500);
    -  goog.style.setSize(container, 100, 150);
    -
    -  // container2 is a scrollable container but is not an offsetParent of
    -  // the element. It is ignored in the computation.
    -  container2.style.overflow = 'hidden';
    -  container2.style.marginTop = '50px';
    -  container2.style.marginLeft = '100px';
    -  goog.style.setSize(container2, 150, 100);
    -
    -  // Scroll body container such that container is exactly at top.
    -  window.scrollTo(0, 500);
    -  var visibleRect = goog.style.getVisibleRectForElement(el);
    -  assertNotNull(visibleRect);
    -  assertRoughlyEquals(500, visibleRect.top, EPSILON);
    -  assertRoughlyEquals(20, visibleRect.left, EPSILON);
    -  assertRoughlyEquals(650, visibleRect.bottom, EPSILON);
    -  assertRoughlyEquals(120, visibleRect.right, EPSILON);
    -
    -  // Top 100px is clipped by window viewport.
    -  window.scrollTo(0, 600);
    -  var visibleRect = goog.style.getVisibleRectForElement(el);
    -  assertNotNull(visibleRect);
    -  assertRoughlyEquals(600, visibleRect.top, EPSILON);
    -  assertRoughlyEquals(20, visibleRect.left, EPSILON);
    -  assertRoughlyEquals(650, visibleRect.bottom, EPSILON);
    -  assertRoughlyEquals(120, visibleRect.right, EPSILON);
    -
    -  var winSize = dom.getViewportSize();
    -
    -  // Left 50px is clipped by window viewport.
    -  // Right part is clipped by window viewport.
    -  goog.style.setSize(container, 10000, 150);
    -  window.scrollTo(70, 500);
    -  var visibleRect = goog.style.getVisibleRectForElement(el);
    -  assertNotNull(visibleRect);
    -  assertRoughlyEquals(500, visibleRect.top, EPSILON);
    -  assertRoughlyEquals(70, visibleRect.left, EPSILON);
    -  assertRoughlyEquals(650, visibleRect.bottom, EPSILON);
    -  assertRoughlyEquals(70 + winSize.width, visibleRect.right, EPSILON);
    -
    -  // Bottom part is clipped by window viewport.
    -  goog.style.setSize(container, 100, 2000);
    -  window.scrollTo(0, 500);
    -  var visibleRect = goog.style.getVisibleRectForElement(el);
    -  assertNotNull(visibleRect);
    -  assertRoughlyEquals(500, visibleRect.top, EPSILON);
    -  assertRoughlyEquals(20, visibleRect.left, EPSILON);
    -  assertRoughlyEquals(120, visibleRect.right, EPSILON);
    -  assertRoughlyEquals(500 + winSize.height, visibleRect.bottom, EPSILON);
    -
    -  goog.style.setPosition(container, 10000, 10000);
    -  assertNull(goog.style.getVisibleRectForElement(el));
    -}
    -
    -function testGetVisibleRectForElementInsideNestedScrollableArea() {
    -  var container = goog.dom.getElement('test-visible2');
    -  var dom = goog.dom.getDomHelper(container);
    -  var container2 = dom.createDom('div');
    -  var el = dom.createDom('div', undefined, 'Test');
    -  el.style.position = 'absolute';
    -  dom.append(container, container2);
    -  dom.append(container2, el);
    -
    -  container.style.position = 'absolute';
    -  goog.style.setPosition(container, 100 /* left */, 500 /* top */);
    -  goog.style.setSize(container, 300 /* width */, 300 /* height */);
    -
    -  container2.style.overflow = 'hidden';
    -  container2.style.position = 'relative';
    -  goog.style.setPosition(container2, 100, 50);
    -  goog.style.setSize(container2, 150, 100);
    -
    -  // Scroll body container such that container is exactly at top.
    -  window.scrollTo(0, 500);
    -  var visibleRect = goog.style.getVisibleRectForElement(el);
    -  assertNotNull(visibleRect);
    -  assertRoughlyEquals(550, visibleRect.top, EPSILON);
    -  assertRoughlyEquals(200, visibleRect.left, EPSILON);
    -  assertRoughlyEquals(650, visibleRect.bottom, EPSILON);
    -  assertRoughlyEquals(350, visibleRect.right, EPSILON);
    -
    -  // Left 50px is clipped by container.
    -  goog.style.setPosition(container2, -50, 50);
    -  var visibleRect = goog.style.getVisibleRectForElement(el);
    -  assertNotNull(visibleRect);
    -  assertRoughlyEquals(550, visibleRect.top, EPSILON);
    -  assertRoughlyEquals(100, visibleRect.left, EPSILON);
    -  assertRoughlyEquals(650, visibleRect.bottom, EPSILON);
    -  assertRoughlyEquals(200, visibleRect.right, EPSILON);
    -
    -  // Right part is clipped by container.
    -  goog.style.setPosition(container2, 100, 50);
    -  goog.style.setWidth(container2, 1000, 100);
    -  var visibleRect = goog.style.getVisibleRectForElement(el);
    -  assertNotNull(visibleRect);
    -  assertRoughlyEquals(550, visibleRect.top, EPSILON);
    -  assertRoughlyEquals(200, visibleRect.left, EPSILON);
    -  assertRoughlyEquals(650, visibleRect.bottom, EPSILON);
    -  assertRoughlyEquals(400, visibleRect.right, EPSILON);
    -
    -  // Top 50px is clipped by container.
    -  goog.style.setStyle(container2, 'width', '150px');
    -  goog.style.setStyle(container2, 'top', '-50px');
    -  var visibleRect = goog.style.getVisibleRectForElement(el);
    -  assertNotNull(visibleRect);
    -  assertRoughlyEquals(500, visibleRect.top, EPSILON);
    -  assertRoughlyEquals(200, visibleRect.left, EPSILON);
    -  assertRoughlyEquals(550, visibleRect.bottom, EPSILON);
    -  assertRoughlyEquals(350, visibleRect.right, EPSILON);
    -
    -  // Bottom part is clipped by container.
    -  goog.style.setStyle(container2, 'top', '50px');
    -  goog.style.setStyle(container2, 'height', '1000px');
    -  var visibleRect = goog.style.getVisibleRectForElement(el);
    -  assertNotNull(visibleRect);
    -  assertRoughlyEquals(550, visibleRect.top, EPSILON);
    -  assertRoughlyEquals(200, visibleRect.left, EPSILON);
    -  assertRoughlyEquals(800, visibleRect.bottom, EPSILON);
    -  assertRoughlyEquals(350, visibleRect.right, EPSILON);
    -
    -  // Outside viewport.
    -  goog.style.setStyle(container2, 'top', '10000px');
    -  goog.style.setStyle(container2, 'left', '10000px');
    -  assertNull(goog.style.getVisibleRectForElement(el));
    -}
    -
    -function testScrollIntoContainerViewQuirks() {
    -  if (goog.dom.isCss1CompatMode()) return;
    -
    -  var container = goog.dom.getElement('scrollable-container');
    -
    -  // Scroll the minimum amount to make the elements visible.
    -  goog.style.scrollIntoContainerView(goog.dom.getElement('item7'), container);
    -  assertEquals('scroll to item7', 79, container.scrollTop);
    -  goog.style.scrollIntoContainerView(goog.dom.getElement('item8'), container);
    -  assertEquals('scroll to item8', 100, container.scrollTop);
    -  goog.style.scrollIntoContainerView(goog.dom.getElement('item7'), container);
    -  assertEquals('item7 still visible', 100, container.scrollTop);
    -  goog.style.scrollIntoContainerView(goog.dom.getElement('item1'), container);
    -  assertEquals('scroll to item1', 17, container.scrollTop);
    -
    -  // Center the element in the first argument.
    -  goog.style.scrollIntoContainerView(goog.dom.getElement('item1'), container,
    -                                     true);
    -  assertEquals('center item1', 0, container.scrollTop);
    -  goog.style.scrollIntoContainerView(goog.dom.getElement('item4'), container,
    -                                     true);
    -  assertEquals('center item4', 48, container.scrollTop);
    -
    -  // The element is higher than the container.
    -  goog.dom.getElement('item3').style.height = '140px';
    -  goog.style.scrollIntoContainerView(goog.dom.getElement('item3'), container);
    -  assertEquals('show item3 with increased height', 59, container.scrollTop);
    -  goog.style.scrollIntoContainerView(goog.dom.getElement('item3'), container,
    -      true);
    -  assertEquals('center item3 with increased height', 87, container.scrollTop);
    -  goog.dom.getElement('item3').style.height = '';
    -
    -  // Scroll to non-integer position.
    -  goog.dom.getElement('item4').style.height = '21px';
    -  goog.style.scrollIntoContainerView(goog.dom.getElement('item4'), container,
    -                                     true);
    -  assertEquals('scroll position is rounded down', 48, container.scrollTop);
    -  goog.dom.getElement('item4').style.height = '';
    -}
    -
    -function testScrollIntoContainerViewStandard() {
    -  if (!goog.dom.isCss1CompatMode()) return;
    -
    -  var container = goog.dom.getElement('scrollable-container');
    -
    -  // Scroll the minimum amount to make the elements visible.
    -  goog.style.scrollIntoContainerView(goog.dom.getElement('item7'), container);
    -  assertEquals('scroll to item7', 115, container.scrollTop);
    -  goog.style.scrollIntoContainerView(goog.dom.getElement('item8'), container);
    -  assertEquals('scroll to item8', 148, container.scrollTop);
    -  goog.style.scrollIntoContainerView(goog.dom.getElement('item7'), container);
    -  assertEquals('item7 still visible', 148, container.scrollTop);
    -  goog.style.scrollIntoContainerView(goog.dom.getElement('item1'), container);
    -  assertEquals('scroll to item1', 17, container.scrollTop);
    -
    -  // Center the element in the first argument.
    -  goog.style.scrollIntoContainerView(
    -      goog.dom.getElement('item1'), container, true);
    -  assertEquals('center item1', 0, container.scrollTop);
    -  goog.style.scrollIntoContainerView(
    -      goog.dom.getElement('item4'), container, true);
    -  assertEquals('center item4', 66, container.scrollTop);
    -
    -  // The element is higher than the container.
    -  goog.dom.getElement('item3').style.height = '140px';
    -  goog.style.scrollIntoContainerView(goog.dom.getElement('item3'), container);
    -  assertEquals('show item3 with increased height', 83, container.scrollTop);
    -  goog.style.scrollIntoContainerView(
    -      goog.dom.getElement('item3'), container, true);
    -  assertEquals('center item3 with increased height', 93, container.scrollTop);
    -  goog.dom.getElement('item3').style.height = '';
    -
    -  // Scroll to non-integer position.
    -  goog.dom.getElement('item4').style.height = '21px';
    -  goog.style.scrollIntoContainerView(
    -      goog.dom.getElement('item4'), container, true);
    -  assertEquals('scroll position is rounded down', 66, container.scrollTop);
    -  goog.dom.getElement('item4').style.height = '';
    -}
    -
    -function testOffsetParent() {
    -  var parent = goog.dom.getElement('offset-parent');
    -  var child = goog.dom.getElement('offset-child');
    -  assertEquals(parent, goog.style.getOffsetParent(child));
    -}
    -
    -function testOverflowOffsetParent() {
    -  var parent = goog.dom.getElement('offset-parent-overflow');
    -  var child = goog.dom.getElement('offset-child-overflow');
    -  assertEquals(parent, goog.style.getOffsetParent(child));
    -}
    -
    -function testShadowDomOffsetParent() {
    -  // Ignore browsers that don't support shadowDOM.
    -  if (!document.createShadowRoot) {
    -    return;
    -  }
    -
    -  var parent = goog.dom.createDom('DIV');
    -  parent.style.position = 'relative';
    -  var host = goog.dom.createDom('DIV');
    -  goog.dom.appendChild(parent, host);
    -  var root = host.createShadowRoot();
    -  var child = goog.dom.createDom('DIV');
    -  goog.dom.appendChild(root, child);
    -
    -  assertEquals(parent, goog.style.getOffsetParent(child));
    -}
    -
    -function testGetViewportPageOffset() {
    -  expectedFailures.expectFailureFor(
    -      goog.userAgent.IE && !goog.userAgent.isVersionOrHigher(9),
    -      'Test has been flaky for ie8-winxp image. Disabling.');
    -
    -  var testViewport = goog.dom.getElement('test-viewport');
    -  testViewport.style.height = '5000px';
    -  testViewport.style.width = '5000px';
    -  var offset = goog.style.getViewportPageOffset(document);
    -  assertEquals(0, offset.x);
    -  assertEquals(0, offset.y);
    -
    -  window.scrollTo(0, 100);
    -  offset = goog.style.getViewportPageOffset(document);
    -  assertEquals(0, offset.x);
    -  assertEquals(100, offset.y);
    -
    -  window.scrollTo(100, 0);
    -  offset = goog.style.getViewportPageOffset(document);
    -  assertEquals(100, offset.x);
    -  assertEquals(0, offset.y);
    -}
    -
    -function testGetsTranslation() {
    -  var element = document.getElementById('translation');
    -
    -  if (goog.userAgent.IE) {
    -    if (!goog.userAgent.isDocumentModeOrHigher(9) ||
    -        (!goog.dom.isCss1CompatMode() &&
    -            !goog.userAgent.isDocumentModeOrHigher(10))) {
    -      // 'CSS transforms were introduced in IE9, but only in standards mode
    -      // later browsers support the translations in quirks mode.
    -      return;
    -    }
    -  }
    -
    -  // First check the element is actually translated, and we haven't missed
    -  // one of the vendor-specific transform properties
    -  var position = goog.style.getClientPosition(element);
    -  var translation = goog.style.getCssTranslation(element);
    -  var expectedTranslation = new goog.math.Coordinate(20, 30);
    -
    -  assertEquals(30, position.x);
    -  assertRoughlyEquals(40, position.y, .1);
    -  assertObjectEquals(expectedTranslation, translation);
    -}
    -
    -
    -/**
    - * Test browser detection for a user agent configuration.
    - * @param {Array<number>} expectedAgents Array of expected userAgents.
    - * @param {string} uaString User agent string.
    - * @param {string=} opt_product Navigator product string.
    - * @param {string=} opt_vendor Navigator vendor string.
    - */
    -function assertUserAgent(expectedAgents, uaString, opt_product, opt_vendor) {
    -
    -  var mockNavigator = {
    -    'userAgent': uaString,
    -    'product': opt_product,
    -    'vendor': opt_vendor
    -  };
    -
    -  mockUserAgent.setNavigator(mockNavigator);
    -  mockUserAgent.setUserAgentString(uaString);
    -
    -  // Force User-Agent lib to reread the global userAgent.
    -  goog.labs.userAgent.util.setUserAgent(null);
    -
    -  goog.userAgentTestUtil.reinitializeUserAgent();
    -  for (var ua in goog.userAgentTestUtil.UserAgents) {
    -    var isExpected = goog.array.contains(
    -        expectedAgents,
    -        goog.userAgentTestUtil.UserAgents[ua]);
    -    assertEquals(isExpected,
    -                 goog.userAgentTestUtil.getUserAgentDetected(
    -                     goog.userAgentTestUtil.UserAgents[ua]));
    -  }
    -}
    -
    -
    -/**
    - * Test for the proper vendor style name for a CSS property
    - * with a vendor prefix for Webkit.
    - */
    -function testGetVendorStyleNameWebkit() {
    -  var mockElement = {
    -    'style': {
    -      'WebkitTransformOrigin': ''
    -    }
    -  };
    -
    -  assertUserAgent([goog.userAgentTestUtil.UserAgents.WEBKIT], 'WebKit');
    -  assertEquals('-webkit-transform-origin',
    -      goog.style.getVendorStyleName_(mockElement, 'transform-origin'));
    -}
    -
    -
    -/**
    - * Test for the proper vendor style name for a CSS property
    - * when it exists without a vendor prefix for Webkit.
    - */
    -function testGetVendorStyleNameWebkitNoPrefix() {
    -  var mockElement = {
    -    'style': {
    -      'WebkitTransformOrigin': '',
    -      'transformOrigin': ''
    -    }
    -  };
    -
    -  assertUserAgent([goog.userAgentTestUtil.UserAgents.WEBKIT], 'WebKit');
    -  assertEquals(
    -      'transform-origin',
    -      goog.style.getVendorStyleName_(mockElement, 'transform-origin'));
    -}
    -
    -
    -/**
    - * Test for the proper vendor style name for a CSS property
    - * with a vendor prefix for Gecko.
    - */
    -function testGetVendorStyleNameGecko() {
    -  var mockElement = {
    -    'style': {
    -      'MozTransformOrigin': ''
    -    }
    -  };
    -
    -  assertUserAgent([goog.userAgentTestUtil.UserAgents.GECKO], 'Gecko', 'Gecko');
    -  assertEquals('-moz-transform-origin',
    -      goog.style.getVendorStyleName_(mockElement, 'transform-origin'));
    -}
    -
    -
    -/**
    - * Test for the proper vendor style name for a CSS property
    - * when it exists without a vendor prefix for Gecko.
    - */
    -function testGetVendorStyleNameGeckoNoPrefix() {
    -  var mockElement = {
    -    'style': {
    -      'MozTransformOrigin': '',
    -      'transformOrigin': ''
    -    }
    -  };
    -
    -  assertUserAgent([goog.userAgentTestUtil.UserAgents.GECKO], 'Gecko', 'Gecko');
    -  assertEquals(
    -      'transform-origin',
    -      goog.style.getVendorStyleName_(mockElement, 'transform-origin'));
    -}
    -
    -
    -/**
    - * Test for the proper vendor style name for a CSS property
    - * with a vendor prefix for IE.
    - */
    -function testGetVendorStyleNameIE() {
    -  var mockElement = {
    -    'style': {
    -      'msTransformOrigin': ''
    -    }
    -  };
    -
    -  assertUserAgent([goog.userAgentTestUtil.UserAgents.IE], 'MSIE');
    -  assertEquals('-ms-transform-origin',
    -      goog.style.getVendorStyleName_(mockElement, 'transform-origin'));
    -}
    -
    -
    -/**
    - * Test for the proper vendor style name for a CSS property
    - * when it exists without a vendor prefix for IE.
    - */
    -function testGetVendorStyleNameIENoPrefix() {
    -  var mockElement = {
    -    'style': {
    -      'msTransformOrigin': '',
    -      'transformOrigin': ''
    -    }
    -  };
    -
    -  assertUserAgent([goog.userAgentTestUtil.UserAgents.IE], 'MSIE');
    -  assertEquals(
    -      'transform-origin',
    -      goog.style.getVendorStyleName_(mockElement, 'transform-origin'));
    -}
    -
    -
    -/**
    - * Test for the proper vendor style name for a CSS property
    - * with a vendor prefix for Opera.
    - */
    -function testGetVendorStyleNameOpera() {
    -  var mockElement = {
    -    'style': {
    -      'OTransformOrigin': ''
    -    }
    -  };
    -
    -  assertUserAgent([goog.userAgentTestUtil.UserAgents.OPERA], 'Opera');
    -  assertEquals('-o-transform-origin',
    -      goog.style.getVendorStyleName_(mockElement, 'transform-origin'));
    -}
    -
    -
    -/**
    - * Test for the proper vendor style name for a CSS property
    - * when it exists without a vendor prefix for Opera.
    - */
    -function testGetVendorStyleNameOperaNoPrefix() {
    -  var mockElement = {
    -    'style': {
    -      'OTransformOrigin': '',
    -      'transformOrigin': ''
    -    }
    -  };
    -
    -  assertUserAgent([goog.userAgentTestUtil.UserAgents.OPERA], 'Opera');
    -  assertEquals(
    -      'transform-origin',
    -      goog.style.getVendorStyleName_(mockElement, 'transform-origin'));
    -}
    -
    -
    -/**
    - * Test for the proper vendor style name for a CSS property
    - * with a vendor prefix for Webkit.
    - */
    -function testGetVendorJsStyleNameWebkit() {
    -  var mockElement = {
    -    'style': {
    -      'WebkitTransformOrigin': ''
    -    }
    -  };
    -
    -  assertUserAgent([goog.userAgentTestUtil.UserAgents.WEBKIT], 'WebKit');
    -  assertEquals('WebkitTransformOrigin',
    -      goog.style.getVendorJsStyleName_(mockElement, 'transform-origin'));
    -}
    -
    -
    -/**
    - * Test for the proper vendor style name for a CSS property
    - * when it exists without a vendor prefix for Webkit.
    - */
    -function testGetVendorJsStyleNameWebkitNoPrefix() {
    -  var mockElement = {
    -    'style': {
    -      'WebkitTransformOrigin': '',
    -      'transformOrigin': ''
    -    }
    -  };
    -
    -  assertUserAgent([goog.userAgentTestUtil.UserAgents.WEBKIT], 'WebKit');
    -  assertEquals(
    -      'transformOrigin',
    -      goog.style.getVendorJsStyleName_(mockElement, 'transform-origin'));
    -}
    -
    -
    -/**
    - * Test for the proper vendor style name for a CSS property
    - * with a vendor prefix for Gecko.
    - */
    -function testGetVendorJsStyleNameGecko() {
    -  var mockElement = {
    -    'style': {
    -      'MozTransformOrigin': ''
    -    }
    -  };
    -
    -  assertUserAgent([goog.userAgentTestUtil.UserAgents.GECKO], 'Gecko', 'Gecko');
    -  assertEquals('MozTransformOrigin',
    -      goog.style.getVendorJsStyleName_(mockElement, 'transform-origin'));
    -}
    -
    -
    -/**
    - * Test for the proper vendor style name for a CSS property
    - * when it exists without a vendor prefix for Gecko.
    - */
    -function testGetVendorJsStyleNameGeckoNoPrefix() {
    -  var mockElement = {
    -    'style': {
    -      'MozTransformOrigin': '',
    -      'transformOrigin': ''
    -    }
    -  };
    -
    -  assertUserAgent([goog.userAgentTestUtil.UserAgents.GECKO], 'Gecko', 'Gecko');
    -  assertEquals(
    -      'transformOrigin',
    -      goog.style.getVendorJsStyleName_(mockElement, 'transform-origin'));
    -}
    -
    -
    -/**
    - * Test for the proper vendor style name for a CSS property
    - * with a vendor prefix for IE.
    - */
    -function testGetVendorJsStyleNameIE() {
    -  var mockElement = {
    -    'style': {
    -      'msTransformOrigin': ''
    -    }
    -  };
    -
    -  assertUserAgent([goog.userAgentTestUtil.UserAgents.IE], 'MSIE');
    -  assertEquals('msTransformOrigin',
    -      goog.style.getVendorJsStyleName_(mockElement, 'transform-origin'));
    -}
    -
    -
    -/**
    - * Test for the proper vendor style name for a CSS property
    - * when it exists without a vendor prefix for IE.
    - */
    -function testGetVendorJsStyleNameIENoPrefix() {
    -  var mockElement = {
    -    'style': {
    -      'msTransformOrigin': '',
    -      'transformOrigin': ''
    -    }
    -  };
    -
    -  assertUserAgent([goog.userAgentTestUtil.UserAgents.IE], 'MSIE');
    -  assertEquals(
    -      'transformOrigin',
    -      goog.style.getVendorJsStyleName_(mockElement, 'transform-origin'));
    -}
    -
    -
    -/**
    - * Test for the proper vendor style name for a CSS property
    - * with a vendor prefix for Opera.
    - */
    -function testGetVendorJsStyleNameOpera() {
    -  var mockElement = {
    -    'style': {
    -      'OTransformOrigin': ''
    -    }
    -  };
    -
    -  assertUserAgent([goog.userAgentTestUtil.UserAgents.OPERA], 'Opera');
    -  assertEquals('OTransformOrigin',
    -      goog.style.getVendorJsStyleName_(mockElement, 'transform-origin'));
    -}
    -
    -
    -/**
    - * Test for the proper vendor style name for a CSS property
    - * when it exists without a vendor prefix for Opera.
    - */
    -function testGetVendorJsStyleNameOperaNoPrefix() {
    -  var mockElement = {
    -    'style': {
    -      'OTransformOrigin': '',
    -      'transformOrigin': ''
    -    }
    -  };
    -
    -  assertUserAgent([goog.userAgentTestUtil.UserAgents.OPERA], 'Opera');
    -  assertEquals(
    -      'transformOrigin',
    -      goog.style.getVendorJsStyleName_(mockElement, 'transform-origin'));
    -}
    -
    -
    -/**
    - * Test for the setting a style name for a CSS property
    - * with a vendor prefix for Webkit.
    - */
    -function testSetVendorStyleWebkit() {
    -  var mockElement = {
    -    'style': {
    -      'WebkitTransform': ''
    -    }
    -  };
    -  var styleValue = 'translate3d(0,0,0)';
    -
    -  assertUserAgent([goog.userAgentTestUtil.UserAgents.WEBKIT], 'WebKit');
    -  goog.style.setStyle(mockElement, 'transform', styleValue);
    -  assertEquals(styleValue, mockElement.style.WebkitTransform);
    -}
    -
    -
    -/**
    - * Test for the setting a style name for a CSS property
    - * with a vendor prefix for Mozilla.
    - */
    -function testSetVendorStyleGecko() {
    -  var mockElement = {
    -    'style': {
    -      'MozTransform': ''
    -    }
    -  };
    -  var styleValue = 'translate3d(0,0,0)';
    -
    -  assertUserAgent([goog.userAgentTestUtil.UserAgents.GECKO], 'Gecko', 'Gecko');
    -  goog.style.setStyle(mockElement, 'transform', styleValue);
    -  assertEquals(styleValue, mockElement.style.MozTransform);
    -}
    -
    -
    -/**
    - * Test for the setting a style name for a CSS property
    - * with a vendor prefix for IE.
    - */
    -function testSetVendorStyleIE() {
    -  var mockElement = {
    -    'style': {
    -      'msTransform': ''
    -    }
    -  };
    -  var styleValue = 'translate3d(0,0,0)';
    -
    -  assertUserAgent([goog.userAgentTestUtil.UserAgents.IE], 'MSIE');
    -  goog.style.setStyle(mockElement, 'transform', styleValue);
    -  assertEquals(styleValue, mockElement.style.msTransform);
    -}
    -
    -
    -/**
    - * Test for the setting a style name for a CSS property
    - * with a vendor prefix for Opera.
    - */
    -function testSetVendorStyleOpera() {
    -  var mockElement = {
    -    'style': {
    -      'OTransform': ''
    -    }
    -  };
    -  var styleValue = 'translate3d(0,0,0)';
    -
    -  assertUserAgent([goog.userAgentTestUtil.UserAgents.OPERA], 'Opera');
    -  goog.style.setStyle(mockElement, 'transform', styleValue);
    -  assertEquals(styleValue, mockElement.style.OTransform);
    -}
    -
    -
    -/**
    - * Test for the getting a style name for a CSS property
    - * with a vendor prefix for Webkit.
    - */
    -function testGetVendorStyleWebkit() {
    -  var mockElement = {
    -    'style': {
    -      'WebkitTransform': ''
    -    }
    -  };
    -  var styleValue = 'translate3d(0,0,0)';
    -
    -  assertUserAgent([goog.userAgentTestUtil.UserAgents.WEBKIT], 'WebKit');
    -  goog.style.setStyle(mockElement, 'transform', styleValue);
    -  assertEquals(styleValue, goog.style.getStyle(mockElement, 'transform'));
    -}
    -
    -
    -/**
    - * Test for the getting a style name for a CSS property
    - * with a vendor prefix for Mozilla.
    - */
    -function testGetVendorStyleGecko() {
    -  var mockElement = {
    -    'style': {
    -      'MozTransform': ''
    -    }
    -  };
    -  var styleValue = 'translate3d(0,0,0)';
    -
    -  assertUserAgent([goog.userAgentTestUtil.UserAgents.GECKO], 'Gecko', 'Gecko');
    -  goog.style.setStyle(mockElement, 'transform', styleValue);
    -  assertEquals(styleValue, goog.style.getStyle(mockElement, 'transform'));
    -}
    -
    -
    -/**
    - * Test for the getting a style name for a CSS property
    - * with a vendor prefix for IE.
    - */
    -function testGetVendorStyleIE() {
    -  var mockElement = {
    -    'style': {
    -      'msTransform': ''
    -    }
    -  };
    -  var styleValue = 'translate3d(0,0,0)';
    -
    -  assertUserAgent([goog.userAgentTestUtil.UserAgents.IE], 'MSIE');
    -  goog.style.setStyle(mockElement, 'transform', styleValue);
    -  assertEquals(styleValue, goog.style.getStyle(mockElement, 'transform'));
    -}
    -
    -
    -/**
    - * Test for the getting a style name for a CSS property
    - * with a vendor prefix for Opera.
    - */
    -function testGetVendorStyleOpera() {
    -  var mockElement = {
    -    'style': {
    -      'OTransform': ''
    -    }
    -  };
    -  var styleValue = 'translate3d(0,0,0)';
    -
    -  assertUserAgent([goog.userAgentTestUtil.UserAgents.OPERA], 'Opera');
    -  goog.style.setStyle(mockElement, 'transform', styleValue);
    -  assertEquals(styleValue, goog.style.getStyle(mockElement, 'transform'));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/style/style_test_iframe_quirk.html b/src/database/third_party/closure-library/closure/goog/style/style_test_iframe_quirk.html
    deleted file mode 100644
    index 2c195581a58..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/style/style_test_iframe_quirk.html
    +++ /dev/null
    @@ -1,27 +0,0 @@
    -<!--
    -
    --->
    -<html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -  <style>
    -    #test-visible {
    -      position: absolute;
    -      background: blue;
    -    }
    -
    -    body {
    -      overflow: hidden;
    -      margin: 0px;
    -    }
    -  </style>
    -</head>
    -<body>
    -  <div id="test-visible">Test</div>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/style/style_test_iframe_standard.html b/src/database/third_party/closure-library/closure/goog/style/style_test_iframe_standard.html
    deleted file mode 100644
    index cf6fe4bcf4e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/style/style_test_iframe_standard.html
    +++ /dev/null
    @@ -1,30 +0,0 @@
    -<!DOCTYPE html>
    -<!--
    -
    --->
    -<html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -  <style>
    -    #test-visible {
    -      position: absolute;
    -      background: blue;
    -    }
    -
    -    body {
    -      overflow: hidden;
    -      margin: 0px;
    -    }
    -  </style>
    -</head>
    -<body>
    -  <div id="test-visible">Test</div>
    -</body>
    -</html>
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/style/style_test_quirk.html b/src/database/third_party/closure-library/closure/goog/style/style_test_quirk.html
    deleted file mode 100644
    index ba3c46f76df..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/style/style_test_quirk.html
    +++ /dev/null
    @@ -1,9 +0,0 @@
    -<!--
    --->
    -<html><body style="border:0px;margin:0px;"><div style="width:400px;height:400px;background-color:yellow;"></div></body></html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    diff --git a/src/database/third_party/closure-library/closure/goog/style/style_test_rect.svg b/src/database/third_party/closure-library/closure/goog/style/style_test_rect.svg
    deleted file mode 100644
    index 2d0f26c692d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/style/style_test_rect.svg
    +++ /dev/null
    @@ -1,11 +0,0 @@
    -<?xml version="1.0" encoding="utf-8"?>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<svg xmlns="http://www.w3.org/2000/svg" version="1.1" baseProfile="full"
    -    width="100px" height="100px" viewBox="0 0 100 100">
    -  <rect id="rect" width="50" height="50" fill="blue"/>
    -</svg>
    diff --git a/src/database/third_party/closure-library/closure/goog/style/style_test_standard.html b/src/database/third_party/closure-library/closure/goog/style/style_test_standard.html
    deleted file mode 100644
    index 46c94dac2cc..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/style/style_test_standard.html
    +++ /dev/null
    @@ -1,11 +0,0 @@
    -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    -            "http://www.w3.org/TR/html4/loose.dtd">
    -<!--
    --->
    -<html><body style="border:0px;width:400px;height:400px;background-color:blue;"></body></html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    diff --git a/src/database/third_party/closure-library/closure/goog/style/style_webkit_scrollbars_test.html b/src/database/third_party/closure-library/closure/goog/style/style_webkit_scrollbars_test.html
    deleted file mode 100644
    index 1ea42cd5c07..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/style/style_webkit_scrollbars_test.html
    +++ /dev/null
    @@ -1,42 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.dom.style
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.style.webkitScrollbarsTest');
    -  </script>
    -  <style>
    -   /*
    - * Note that we have to apply these styles when the page is loaded or the
    - * scrollbars might not pick them up.
    - */
    -::-webkit-scrollbar {
    -  width: 16px;
    -  height: 16px;
    -}
    -
    -.otherScrollBar::-webkit-scrollbar {
    -  width: 10px;
    -  height: 10px;
    -}
    -  </style>
    - </head>
    - <body>
    -  <div id="test-scrollbarwidth" style="background-color: orange; width: 100px; height: 100px; overflow: auto;">
    -   <div style="width: 200px; height: 200px; background-color: red">
    -    Test Scroll bar width with scroll
    -   </div>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/style/style_webkit_scrollbars_test.js b/src/database/third_party/closure-library/closure/goog/style/style_webkit_scrollbars_test.js
    deleted file mode 100644
    index 7ce686e6a2c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/style/style_webkit_scrollbars_test.js
    +++ /dev/null
    @@ -1,59 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.style.webkitScrollbarsTest');
    -goog.setTestOnly('goog.style.webkitScrollbarsTest');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.style');
    -/** @suppress {extraRequire} */
    -goog.require('goog.styleScrollbarTester');
    -goog.require('goog.testing.ExpectedFailures');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -var expectedFailures;
    -
    -function setUpPage() {
    -  expectedFailures = new goog.testing.ExpectedFailures();
    -}
    -
    -function tearDown() {
    -  expectedFailures.handleTearDown();
    -
    -  // Assert that the test loaded.
    -  goog.asserts.assert(testScrollbarWidth);
    -}
    -
    -function testScrollBarWidth_webkitScrollbar() {
    -  expectedFailures.expectFailureFor(!goog.userAgent.WEBKIT);
    -
    -  try {
    -    var width = goog.style.getScrollbarWidth();
    -    assertEquals('Scrollbar width should be 16', 16, width);
    -  } catch (e) {
    -    expectedFailures.handleException(e);
    -  }
    -}
    -
    -function testScrollBarWidth_webkitScrollbarWithCustomClass() {
    -  expectedFailures.expectFailureFor(!goog.userAgent.WEBKIT);
    -
    -  try {
    -    var customWidth = goog.style.getScrollbarWidth('otherScrollBar');
    -    assertEquals('Custom width should be 10', 10, customWidth);
    -  } catch (e) {
    -    expectedFailures.handleException(e);
    -  }
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/style/stylescrollbartester.js b/src/database/third_party/closure-library/closure/goog/style/stylescrollbartester.js
    deleted file mode 100644
    index cb9ec204e24..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/style/stylescrollbartester.js
    +++ /dev/null
    @@ -1,78 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Shared unit tests for scrollbar measurement.
    - *
    - * @author flan@google.com (Ian Flanigan)
    - */
    -
    -goog.provide('goog.styleScrollbarTester');
    -
    -goog.require('goog.dom');
    -goog.require('goog.style');
    -goog.require('goog.testing.asserts');
    -goog.setTestOnly('goog.styleScrollbarTester');
    -
    -
    -/**
    - * Tests the scrollbar width calculation. Assumes that there is an element with
    - * id 'test-scrollbarwidth' in the page.
    - */
    -function testScrollbarWidth() {
    -  var width = goog.style.getScrollbarWidth();
    -  assertTrue(width > 0);
    -
    -  var outer = goog.dom.getElement('test-scrollbarwidth');
    -  var inner = goog.dom.getElementsByTagNameAndClass('div', null, outer)[0];
    -  assertTrue('should have a scroll bar',
    -      hasVerticalScroll(outer));
    -  assertTrue('should have a scroll bar',
    -      hasHorizontalScroll(outer));
    -
    -  // Get the inner div absolute width
    -  goog.style.setStyle(outer, 'width', '100%');
    -  assertTrue('should have a scroll bar',
    -      hasVerticalScroll(outer));
    -  assertFalse('should not have a scroll bar',
    -      hasHorizontalScroll(outer));
    -  var innerAbsoluteWidth = inner.offsetWidth;
    -
    -  // Leave the vertical scroll and remove the horizontal by using the scroll
    -  // bar width calculation.
    -  goog.style.setStyle(outer, 'width',
    -      (innerAbsoluteWidth + width) + 'px');
    -  assertTrue('should have a scroll bar',
    -      hasVerticalScroll(outer));
    -  assertFalse('should not have a scroll bar',
    -      hasHorizontalScroll(outer));
    -
    -  // verify by adding 1 more pixel (brings back the vertical scroll bar).
    -  goog.style.setStyle(outer, 'width',
    -      (innerAbsoluteWidth + width - 1) + 'px');
    -  assertTrue('should have a scroll bar',
    -      hasVerticalScroll(outer));
    -  assertTrue('should have a scroll bar',
    -      hasHorizontalScroll(outer));
    -}
    -
    -
    -function hasVerticalScroll(el) {
    -  return el.clientWidth != 0 && el.offsetWidth - el.clientWidth > 0;
    -}
    -
    -
    -function hasHorizontalScroll(el) {
    -  return el.clientHeight != 0 && el.offsetHeight - el.clientHeight > 0;
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/style/transform.js b/src/database/third_party/closure-library/closure/goog/style/transform.js
    deleted file mode 100644
    index 4ceb7411c1a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/style/transform.js
    +++ /dev/null
    @@ -1,169 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Utility methods to deal with CSS3 transforms programmatically.
    - */
    -
    -goog.provide('goog.style.transform');
    -
    -goog.require('goog.functions');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.math.Coordinate3');
    -goog.require('goog.style');
    -goog.require('goog.userAgent');
    -goog.require('goog.userAgent.product.isVersion');
    -
    -
    -/**
    - * Whether CSS3 transform translate() is supported. IE 9 supports 2D transforms
    - * and IE 10 supports 3D transforms. IE 8 supports neither.
    - * @return {boolean} Whether the current environment supports CSS3 transforms.
    - */
    -goog.style.transform.isSupported = goog.functions.cacheReturnValue(function() {
    -  return !goog.userAgent.IE || goog.userAgent.product.isVersion(9);
    -});
    -
    -
    -/**
    - * Whether CSS3 transform translate3d() is supported. If the current browser
    - * supports this transform strategy.
    - * @return {boolean} Whether the current environment supports CSS3 transforms.
    - */
    -goog.style.transform.is3dSupported =
    -    goog.functions.cacheReturnValue(function() {
    -  return goog.userAgent.WEBKIT ||
    -      (goog.userAgent.GECKO && goog.userAgent.product.isVersion(10)) ||
    -      (goog.userAgent.IE && goog.userAgent.product.isVersion(10));
    -});
    -
    -
    -/**
    - * Returns the x,y translation component of any CSS transforms applied to the
    - * element, in pixels.
    - *
    - * @param {!Element} element The element to get the translation of.
    - * @return {!goog.math.Coordinate} The CSS translation of the element in px.
    - */
    -goog.style.transform.getTranslation = function(element) {
    -  var transform = goog.style.getComputedTransform(element);
    -  var matrixConstructor = goog.style.transform.matrixConstructor_();
    -  if (transform && matrixConstructor) {
    -    var matrix = new matrixConstructor(transform);
    -    if (matrix) {
    -      return new goog.math.Coordinate(matrix.m41, matrix.m42);
    -    }
    -  }
    -  return new goog.math.Coordinate(0, 0);
    -};
    -
    -
    -/**
    - * Translates an element's position using the CSS3 transform property.
    - * NOTE: This replaces all other transforms already defined on the element.
    - * @param {Element} element The element to translate.
    - * @param {number} x The horizontal translation.
    - * @param {number} y The vertical translation.
    - * @return {boolean} Whether the CSS translation was set.
    - */
    -goog.style.transform.setTranslation = function(element, x, y) {
    -  if (!goog.style.transform.isSupported()) {
    -    return false;
    -  }
    -  // TODO(user): After http://crbug.com/324107 is fixed, it will be faster to
    -  // use something like: translation = new CSSMatrix().translate(x, y, 0);
    -  var translation = goog.style.transform.is3dSupported() ?
    -      'translate3d(' + x + 'px,' + y + 'px,' + '0px)' :
    -      'translate(' + x + 'px,' + y + 'px)';
    -  goog.style.setStyle(element,
    -      goog.style.transform.getTransformProperty_(), translation);
    -  return true;
    -};
    -
    -
    -/**
    - * Returns the scale of the x, y and z dimensions of CSS transforms applied to
    - * the element.
    - *
    - * @param {!Element} element The element to get the scale of.
    - * @return {!goog.math.Coordinate3} The scale of the element.
    - */
    -goog.style.transform.getScale = function(element) {
    -  var transform = goog.style.getComputedTransform(element);
    -  var matrixConstructor = goog.style.transform.matrixConstructor_();
    -  if (transform && matrixConstructor) {
    -    var matrix = new matrixConstructor(transform);
    -    if (matrix) {
    -      return new goog.math.Coordinate3(matrix.m11, matrix.m22, matrix.m33);
    -    }
    -  }
    -  return new goog.math.Coordinate3(0, 0, 0);
    -};
    -
    -
    -/**
    - * Scales an element using the CSS3 transform property.
    - * NOTE: This replaces all other transforms already defined on the element.
    - * @param {!Element} element The element to scale.
    - * @param {number} x The horizontal scale.
    - * @param {number} y The vertical scale.
    - * @param {number} z The depth scale.
    - * @return {boolean} Whether the CSS scale was set.
    - */
    -goog.style.transform.setScale = function(element, x, y, z) {
    -  if (!goog.style.transform.isSupported()) {
    -    return false;
    -  }
    -  var scale = goog.style.transform.is3dSupported() ?
    -      'scale3d(' + x + ',' + y + ',' + z + ')' :
    -      'scale(' + x + ',' + y + ')';
    -  goog.style.setStyle(element,
    -      goog.style.transform.getTransformProperty_(), scale);
    -  return true;
    -};
    -
    -
    -/**
    - * A cached value of the transform property depending on whether the useragent
    - * is IE9.
    - * @return {string} The transform property depending on whether the useragent
    - *     is IE9.
    - * @private
    - */
    -goog.style.transform.getTransformProperty_ =
    -    goog.functions.cacheReturnValue(function() {
    -  return goog.userAgent.IE && goog.userAgent.DOCUMENT_MODE == 9 ?
    -      '-ms-transform' : 'transform';
    -});
    -
    -
    -/**
    - * Gets the constructor for a CSSMatrix object.
    - * @return {function(new:CSSMatrix, string)?} A constructor for a CSSMatrix
    - *     object (or null).
    - * @private
    - */
    -goog.style.transform.matrixConstructor_ =
    -    goog.functions.cacheReturnValue(function() {
    -  if (goog.isDef(goog.global['WebKitCSSMatrix'])) {
    -    return goog.global['WebKitCSSMatrix'];
    -  }
    -  if (goog.isDef(goog.global['MSCSSMatrix'])) {
    -    return goog.global['MSCSSMatrix'];
    -  }
    -  if (goog.isDef(goog.global['CSSMatrix'])) {
    -    return goog.global['CSSMatrix'];
    -  }
    -  return null;
    -});
    diff --git a/src/database/third_party/closure-library/closure/goog/style/transform_test.js b/src/database/third_party/closure-library/closure/goog/style/transform_test.js
    deleted file mode 100644
    index b5d1339dd7e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/style/transform_test.js
    +++ /dev/null
    @@ -1,136 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.style.transformTest');
    -goog.setTestOnly('goog.style.transformTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.style.transform');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -goog.require('goog.userAgent.product.isVersion');
    -
    -
    -/**
    - * Element being transformed.
    - * @type {Element}
    - */
    -var element;
    -
    -
    -/**
    - * Sets a transform translation and asserts the translation was applied.
    - * @param {number} x The horizontal translation
    - * @param {number} y The vertical translation
    - */
    -var setAndAssertTranslation = function(x, y) {
    -  if (goog.userAgent.GECKO ||
    -      goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(10)) {
    -    // Mozilla and <IE10 do not support CSSMatrix.
    -    return;
    -  }
    -  var success = goog.style.transform.setTranslation(element, x, y);
    -  if (!goog.style.transform.isSupported()) {
    -    assertFalse(success);
    -  } else {
    -    assertTrue(success);
    -    var translation = goog.style.transform.getTranslation(element);
    -    assertEquals(x, translation.x);
    -    assertEquals(y, translation.y);
    -  }
    -};
    -
    -
    -/**
    - * Sets a transform translation and asserts the translation was applied.
    - * @param {number} x The horizontal scale
    - * @param {number} y The vertical scale
    - * @param {number} z The depth scale
    - */
    -var setAndAssertScale = function(x, y, z) {
    -  if (goog.userAgent.GECKO ||
    -      goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(10)) {
    -    // Mozilla and <IE10 do not support CSSMatrix.
    -    return;
    -  }
    -  var success = goog.style.transform.setScale(element, x, y, z);
    -  if (!goog.style.transform.isSupported()) {
    -    assertFalse(success);
    -  } else {
    -    assertTrue(success);
    -    var scale = goog.style.transform.getScale(element);
    -    assertEquals(x, scale.x);
    -    assertEquals(y, scale.y);
    -    if (goog.style.transform.is3dSupported()) {
    -      assertEquals(z, scale.z);
    -    }
    -  }
    -};
    -
    -
    -function setUp() {
    -  element = goog.dom.createElement('div');
    -  goog.dom.appendChild(goog.dom.getDocument().body, element);
    -}
    -
    -function tearDown() {
    -  goog.dom.removeNode(element);
    -}
    -
    -
    -function testIsSupported() {
    -  if (goog.userAgent.IE && !goog.userAgent.product.isVersion(9)) {
    -    assertFalse(goog.style.transform.isSupported());
    -  } else {
    -    assertTrue(goog.style.transform.isSupported());
    -  }
    -}
    -
    -
    -function testIs3dSupported() {
    -  if (goog.userAgent.GECKO && !goog.userAgent.product.isVersion(10) ||
    -      (goog.userAgent.IE && !goog.userAgent.product.isVersion(10))) {
    -    assertFalse(goog.style.transform.is3dSupported());
    -  } else {
    -    assertTrue(goog.style.transform.is3dSupported());
    -  }
    -}
    -
    -function testTranslateX() {
    -  setAndAssertTranslation(10, 0);
    -}
    -
    -function testTranslateY() {
    -  setAndAssertTranslation(0, 10);
    -}
    -
    -function testTranslateXY() {
    -  setAndAssertTranslation(10, 20);
    -}
    -
    -function testScaleX() {
    -  setAndAssertScale(5, 1, 1);
    -}
    -
    -function testScaleY() {
    -  setAndAssertScale(1, 3, 1);
    -}
    -
    -function testScaleZ() {
    -  setAndAssertScale(1, 1, 8);
    -}
    -
    -function testScale() {
    -  setAndAssertScale(2, 2, 2);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/style/transition.js b/src/database/third_party/closure-library/closure/goog/style/transition.js
    deleted file mode 100644
    index 60d8d487903..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/style/transition.js
    +++ /dev/null
    @@ -1,132 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Utility methods to deal with CSS3 transitions
    - * programmatically.
    - * @author chrishenry@google.com (Chris Henry)
    - */
    -
    -goog.provide('goog.style.transition');
    -goog.provide('goog.style.transition.Css3Property');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.dom.safe');
    -goog.require('goog.dom.vendor');
    -goog.require('goog.functions');
    -goog.require('goog.html.SafeHtml');
    -goog.require('goog.style');
    -goog.require('goog.userAgent');
    -
    -
    -/**
    - * A typedef to represent a CSS3 transition property. Duration and delay
    - * are both in seconds. Timing is CSS3 timing function string, such as
    - * 'easein', 'linear'.
    - *
    - * Alternatively, specifying string in the form of '[property] [duration]
    - * [timing] [delay]' as specified in CSS3 transition is fine too.
    - *
    - * @typedef { {
    - *   property: string,
    - *   duration: number,
    - *   timing: string,
    - *   delay: number
    - * } | string }
    - */
    -goog.style.transition.Css3Property;
    -
    -
    -/**
    - * Sets the element CSS3 transition to properties.
    - * @param {Element} element The element to set transition on.
    - * @param {goog.style.transition.Css3Property|
    - *     Array<goog.style.transition.Css3Property>} properties A single CSS3
    - *     transition property or array of properties.
    - */
    -goog.style.transition.set = function(element, properties) {
    -  if (!goog.isArray(properties)) {
    -    properties = [properties];
    -  }
    -  goog.asserts.assert(
    -      properties.length > 0, 'At least one Css3Property should be specified.');
    -
    -  var values = goog.array.map(
    -      properties, function(p) {
    -        if (goog.isString(p)) {
    -          return p;
    -        } else {
    -          goog.asserts.assertObject(p,
    -              'Expected css3 property to be an object.');
    -          var propString = p.property + ' ' + p.duration + 's ' + p.timing +
    -              ' ' + p.delay + 's';
    -          goog.asserts.assert(p.property && goog.isNumber(p.duration) &&
    -              p.timing && goog.isNumber(p.delay),
    -              'Unexpected css3 property value: %s', propString);
    -          return propString;
    -        }
    -      });
    -  goog.style.transition.setPropertyValue_(element, values.join(','));
    -};
    -
    -
    -/**
    - * Removes any programmatically-added CSS3 transition in the given element.
    - * @param {Element} element The element to remove transition from.
    - */
    -goog.style.transition.removeAll = function(element) {
    -  goog.style.transition.setPropertyValue_(element, '');
    -};
    -
    -
    -/**
    - * @return {boolean} Whether CSS3 transition is supported.
    - */
    -goog.style.transition.isSupported = goog.functions.cacheReturnValue(function() {
    -  // Since IE would allow any attribute, we need to explicitly check the
    -  // browser version here instead.
    -  if (goog.userAgent.IE) {
    -    return goog.userAgent.isVersionOrHigher('10.0');
    -  }
    -
    -  // We create a test element with style=-vendor-transition
    -  // We then detect whether those style properties are recognized and
    -  // available from js.
    -  var el = document.createElement('div');
    -  var transition = 'opacity 1s linear';
    -  var vendorPrefix = goog.dom.vendor.getVendorPrefix();
    -  var style = {'transition': transition};
    -  if (vendorPrefix) {
    -    style[vendorPrefix + '-transition'] = transition;
    -  }
    -  goog.dom.safe.setInnerHtml(el,
    -      goog.html.SafeHtml.create('div', {'style': style}));
    -
    -  var testElement = /** @type {Element} */ (el.firstChild);
    -  goog.asserts.assert(testElement.nodeType == Node.ELEMENT_NODE);
    -
    -  return goog.style.getStyle(testElement, 'transition') != '';
    -});
    -
    -
    -/**
    - * Sets CSS3 transition property value to the given value.
    - * @param {Element} element The element to set transition on.
    - * @param {string} transitionValue The CSS3 transition property value.
    - * @private
    - */
    -goog.style.transition.setPropertyValue_ = function(element, transitionValue) {
    -  goog.style.setStyle(element, 'transition', transitionValue);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/style/transition_test.html b/src/database/third_party/closure-library/closure/goog/style/transition_test.html
    deleted file mode 100644
    index c27b9bae6ef..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/style/transition_test.html
    +++ /dev/null
    @@ -1,27 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -  Author: chrishenry@google.com (Chris Henry)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.style.transition
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.style.transitionTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="test">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/style/transition_test.js b/src/database/third_party/closure-library/closure/goog/style/transition_test.js
    deleted file mode 100644
    index 04dccfaa738..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/style/transition_test.js
    +++ /dev/null
    @@ -1,119 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.style.transitionTest');
    -goog.setTestOnly('goog.style.transitionTest');
    -
    -goog.require('goog.style');
    -goog.require('goog.style.transition');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -
    -/** Fake element. */
    -var element;
    -
    -
    -function setUp() {
    -  element = {'style': {}};
    -}
    -
    -function getTransitionStyle(element) {
    -  return element.style['transition'] ||
    -      goog.style.getStyle(element, 'transition');
    -}
    -
    -
    -function testSetWithNoProperty() {
    -  try {
    -    goog.style.transition.set(element, []);
    -  } catch (e) {
    -    return;
    -  }
    -  fail('Should fail when no property is given.');
    -}
    -
    -
    -function testSetWithString() {
    -  goog.style.transition.set(element, 'opacity 1s ease-in 0.125s');
    -  assertEquals('opacity 1s ease-in 0.125s', getTransitionStyle(element));
    -}
    -
    -
    -function testSetWithSingleProperty() {
    -  goog.style.transition.set(element,
    -      {property: 'opacity', duration: 1, timing: 'ease-in', delay: 0.125});
    -  assertEquals('opacity 1s ease-in 0.125s', getTransitionStyle(element));
    -}
    -
    -
    -function testSetWithMultipleStrings() {
    -  goog.style.transition.set(element, [
    -    'width 1s ease-in',
    -    'height 0.5s linear 1s'
    -  ]);
    -  assertEquals('width 1s ease-in,height 0.5s linear 1s',
    -               getTransitionStyle(element));
    -}
    -
    -
    -function testSetWithMultipleProperty() {
    -  goog.style.transition.set(element, [
    -    {property: 'width', duration: 1, timing: 'ease-in', delay: 0},
    -    {property: 'height', duration: 0.5, timing: 'linear', delay: 1}
    -  ]);
    -  assertEquals('width 1s ease-in 0s,height 0.5s linear 1s',
    -      getTransitionStyle(element));
    -}
    -
    -
    -function testRemoveAll() {
    -  goog.style.setStyle(element, 'transition', 'opacity 1s ease-in');
    -  goog.style.transition.removeAll(element);
    -  assertEquals('', getTransitionStyle(element));
    -}
    -
    -
    -function testAddAndRemoveOnRealElement() {
    -  if (!goog.style.transition.isSupported()) {
    -    return;
    -  }
    -
    -  var div = document.getElementById('test');
    -  goog.style.transition.set(div, 'opacity 1s ease-in 125ms');
    -  assertEquals('opacity 1s ease-in 125ms', getTransitionStyle(div));
    -  goog.style.transition.removeAll(div);
    -  assertEquals('', getTransitionStyle(div));
    -}
    -
    -
    -function testSanityDetectionOfCss3Transition() {
    -  var support = goog.style.transition.isSupported();
    -
    -  // IE support starts at IE10.
    -  if (goog.userAgent.IE) {
    -    assertEquals(goog.userAgent.isVersionOrHigher('10.0'), support);
    -  }
    -
    -  // FF support start at FF4 (Gecko 2.0)
    -  if (goog.userAgent.GECKO) {
    -    assertEquals(goog.userAgent.isVersionOrHigher('2.0'), support);
    -  }
    -
    -  // Webkit support has existed for a long time, we assume support on
    -  // most webkit version in used today.
    -  if (goog.userAgent.WEBKIT) {
    -    assertTrue(support);
    -  }
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/test_module.js b/src/database/third_party/closure-library/closure/goog/test_module.js
    deleted file mode 100644
    index b265fcefc56..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/test_module.js
    +++ /dev/null
    @@ -1,27 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A test file for testing goog.module.
    - */
    -
    -goog.module('goog.test_module');
    -goog.setTestOnly('goog.test_module');
    -goog.module.declareLegacyNamespace();
    -
    -var dep = goog.require('goog.test_module_dep');
    -
    -/** @constructor */
    -exports = function() {};
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/test_module_dep.js b/src/database/third_party/closure-library/closure/goog/test_module_dep.js
    deleted file mode 100644
    index b65af6f3f76..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/test_module_dep.js
    +++ /dev/null
    @@ -1,26 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A test file for testing goog.module.
    - */
    -
    -goog.module('goog.test_module_dep');
    -goog.setTestOnly('goog.test_module');
    -
    -/** @type {number} */
    -exports.someValue = 1;
    -
    -/** @type {function()} */
    -exports.someFunction = function() {};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/asserts.js b/src/database/third_party/closure-library/closure/goog/testing/asserts.js
    deleted file mode 100644
    index 047897f7403..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/asserts.js
    +++ /dev/null
    @@ -1,1263 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -goog.provide('goog.testing.JsUnitException');
    -goog.provide('goog.testing.asserts');
    -goog.provide('goog.testing.asserts.ArrayLike');
    -
    -goog.require('goog.testing.stacktrace');
    -
    -// TODO(user): Copied from JsUnit with some small modifications, we should
    -// reimplement the asserters.
    -
    -
    -/**
    - * @typedef {Array|NodeList|Arguments|{length: number}}
    - */
    -goog.testing.asserts.ArrayLike;
    -
    -var DOUBLE_EQUALITY_PREDICATE = function(var1, var2) {
    -  return var1 == var2;
    -};
    -var JSUNIT_UNDEFINED_VALUE;
    -var TO_STRING_EQUALITY_PREDICATE = function(var1, var2) {
    -  return var1.toString() === var2.toString();
    -};
    -
    -var PRIMITIVE_EQUALITY_PREDICATES = {
    -  'String': DOUBLE_EQUALITY_PREDICATE,
    -  'Number': DOUBLE_EQUALITY_PREDICATE,
    -  'Boolean': DOUBLE_EQUALITY_PREDICATE,
    -  'Date': function(date1, date2) {
    -    return date1.getTime() == date2.getTime();
    -  },
    -  'RegExp': TO_STRING_EQUALITY_PREDICATE,
    -  'Function': TO_STRING_EQUALITY_PREDICATE
    -};
    -
    -
    -/**
    - * Compares equality of two numbers, allowing them to differ up to a given
    - * tolerance.
    - * @param {number} var1 A number.
    - * @param {number} var2 A number.
    - * @param {number} tolerance the maximum allowed difference.
    - * @return {boolean} Whether the two variables are sufficiently close.
    - * @private
    - */
    -goog.testing.asserts.numberRoughEqualityPredicate_ = function(
    -    var1, var2, tolerance) {
    -  return Math.abs(var1 - var2) <= tolerance;
    -};
    -
    -
    -/**
    - * @type {Object<string, function(*, *, number): boolean>}
    - * @private
    - */
    -goog.testing.asserts.primitiveRoughEqualityPredicates_ = {
    -  'Number': goog.testing.asserts.numberRoughEqualityPredicate_
    -};
    -
    -
    -var _trueTypeOf = function(something) {
    -  var result = typeof something;
    -  try {
    -    switch (result) {
    -      case 'string':
    -        break;
    -      case 'boolean':
    -        break;
    -      case 'number':
    -        break;
    -      case 'object':
    -        if (something == null) {
    -          result = 'null';
    -          break;
    -        }
    -      case 'function':
    -        switch (something.constructor) {
    -          case new String('').constructor:
    -            result = 'String';
    -            break;
    -          case new Boolean(true).constructor:
    -            result = 'Boolean';
    -            break;
    -          case new Number(0).constructor:
    -            result = 'Number';
    -            break;
    -          case new Array().constructor:
    -            result = 'Array';
    -            break;
    -          case new RegExp().constructor:
    -            result = 'RegExp';
    -            break;
    -          case new Date().constructor:
    -            result = 'Date';
    -            break;
    -          case Function:
    -            result = 'Function';
    -            break;
    -          default:
    -            var m = something.constructor.toString().match(
    -                /function\s*([^( ]+)\(/);
    -            if (m) {
    -              result = m[1];
    -            } else {
    -              break;
    -            }
    -        }
    -        break;
    -    }
    -  } catch (e) {
    -
    -  } finally {
    -    result = result.substr(0, 1).toUpperCase() + result.substr(1);
    -  }
    -  return result;
    -};
    -
    -var _displayStringForValue = function(aVar) {
    -  var result;
    -  try {
    -    result = '<' + String(aVar) + '>';
    -  } catch (ex) {
    -    result = '<toString failed: ' + ex.message + '>';
    -    // toString does not work on this object :-(
    -  }
    -  if (!(aVar === null || aVar === JSUNIT_UNDEFINED_VALUE)) {
    -    result += ' (' + _trueTypeOf(aVar) + ')';
    -  }
    -  return result;
    -};
    -
    -var fail = function(failureMessage) {
    -  goog.testing.asserts.raiseException('Call to fail()', failureMessage);
    -};
    -
    -var argumentsIncludeComments = function(expectedNumberOfNonCommentArgs, args) {
    -  return args.length == expectedNumberOfNonCommentArgs + 1;
    -};
    -
    -var commentArg = function(expectedNumberOfNonCommentArgs, args) {
    -  if (argumentsIncludeComments(expectedNumberOfNonCommentArgs, args)) {
    -    return args[0];
    -  }
    -
    -  return null;
    -};
    -
    -var nonCommentArg = function(desiredNonCommentArgIndex,
    -    expectedNumberOfNonCommentArgs, args) {
    -  return argumentsIncludeComments(expectedNumberOfNonCommentArgs, args) ?
    -      args[desiredNonCommentArgIndex] :
    -      args[desiredNonCommentArgIndex - 1];
    -};
    -
    -var _validateArguments = function(expectedNumberOfNonCommentArgs, args) {
    -  var valid = args.length == expectedNumberOfNonCommentArgs ||
    -      args.length == expectedNumberOfNonCommentArgs + 1 &&
    -      goog.isString(args[0]);
    -  _assert(null, valid, 'Incorrect arguments passed to assert function');
    -};
    -
    -var _assert = function(comment, booleanValue, failureMessage) {
    -  if (!booleanValue) {
    -    goog.testing.asserts.raiseException(comment, failureMessage);
    -  }
    -};
    -
    -
    -/**
    - * @param {*} expected The expected value.
    - * @param {*} actual The actual value.
    - * @return {string} A failure message of the values don't match.
    - * @private
    - */
    -goog.testing.asserts.getDefaultErrorMsg_ = function(expected, actual) {
    -  var msg = 'Expected ' + _displayStringForValue(expected) + ' but was ' +
    -      _displayStringForValue(actual);
    -  if ((typeof expected == 'string') && (typeof actual == 'string')) {
    -    // Try to find a human-readable difference.
    -    var limit = Math.min(expected.length, actual.length);
    -    var commonPrefix = 0;
    -    while (commonPrefix < limit &&
    -        expected.charAt(commonPrefix) == actual.charAt(commonPrefix)) {
    -      commonPrefix++;
    -    }
    -
    -    var commonSuffix = 0;
    -    while (commonSuffix < limit &&
    -        expected.charAt(expected.length - commonSuffix - 1) ==
    -            actual.charAt(actual.length - commonSuffix - 1)) {
    -      commonSuffix++;
    -    }
    -
    -    if (commonPrefix + commonSuffix > limit) {
    -      commonSuffix = 0;
    -    }
    -
    -    if (commonPrefix > 2 || commonSuffix > 2) {
    -      var printString = function(str) {
    -        var startIndex = Math.max(0, commonPrefix - 2);
    -        var endIndex = Math.min(str.length, str.length - (commonSuffix - 2));
    -        return (startIndex > 0 ? '...' : '') +
    -            str.substring(startIndex, endIndex) +
    -            (endIndex < str.length ? '...' : '');
    -      };
    -
    -      msg += '\nDifference was at position ' + commonPrefix +
    -          '. Expected [' + printString(expected) +
    -          '] vs. actual [' + printString(actual) + ']';
    -    }
    -  }
    -  return msg;
    -};
    -
    -
    -/**
    - * @param {*} a The value to assert (1 arg) or debug message (2 args).
    - * @param {*=} opt_b The value to assert (2 args only).
    - */
    -var assert = function(a, opt_b) {
    -  _validateArguments(1, arguments);
    -  var comment = commentArg(1, arguments);
    -  var booleanValue = nonCommentArg(1, 1, arguments);
    -
    -  _assert(comment, goog.isBoolean(booleanValue),
    -      'Bad argument to assert(boolean)');
    -  _assert(comment, booleanValue, 'Call to assert(boolean) with false');
    -};
    -
    -
    -/**
    - * Asserts that the function throws an error.
    - *
    - * @param {!(string|Function)} a The assertion comment or the function to call.
    - * @param {!Function=} opt_b The function to call (if the first argument of
    - *     {@code assertThrows} was the comment).
    - * @return {*} The error thrown by the function.
    - * @throws {goog.testing.JsUnitException} If the assertion failed.
    - */
    -var assertThrows = function(a, opt_b) {
    -  _validateArguments(1, arguments);
    -  var func = nonCommentArg(1, 1, arguments);
    -  var comment = commentArg(1, arguments);
    -  _assert(comment, typeof func == 'function',
    -      'Argument passed to assertThrows is not a function');
    -
    -  try {
    -    func();
    -  } catch (e) {
    -    if (e && goog.isString(e['stacktrace']) && goog.isString(e['message'])) {
    -      // Remove the stack trace appended to the error message by Opera 10.0
    -      var startIndex = e['message'].length - e['stacktrace'].length;
    -      if (e['message'].indexOf(e['stacktrace'], startIndex) == startIndex) {
    -        e['message'] = e['message'].substr(0, startIndex - 14);
    -      }
    -    }
    -    return e;
    -  }
    -  goog.testing.asserts.raiseException(comment,
    -      'No exception thrown from function passed to assertThrows');
    -};
    -
    -
    -/**
    - * Asserts that the function does not throw an error.
    - *
    - * @param {!(string|Function)} a The assertion comment or the function to call.
    - * @param {!Function=} opt_b The function to call (if the first argument of
    - *     {@code assertNotThrows} was the comment).
    - * @return {*} The return value of the function.
    - * @throws {goog.testing.JsUnitException} If the assertion failed.
    - */
    -var assertNotThrows = function(a, opt_b) {
    -  _validateArguments(1, arguments);
    -  var comment = commentArg(1, arguments);
    -  var func = nonCommentArg(1, 1, arguments);
    -  _assert(comment, typeof func == 'function',
    -      'Argument passed to assertNotThrows is not a function');
    -
    -  try {
    -    return func();
    -  } catch (e) {
    -    comment = comment ? (comment + '\n') : '';
    -    comment += 'A non expected exception was thrown from function passed to ' +
    -               'assertNotThrows';
    -    // Some browsers don't have a stack trace so at least have the error
    -    // description.
    -    var stackTrace = e['stack'] || e['stacktrace'] || e.toString();
    -    goog.testing.asserts.raiseException(comment, stackTrace);
    -  }
    -};
    -
    -
    -/**
    - * Asserts that the given callback function results in a JsUnitException when
    - * called, and that the resulting failure message matches the given expected
    - * message.
    - * @param {function() : void} callback Function to be run expected to result
    - *     in a JsUnitException (usually contains a call to an assert).
    - * @param {string=} opt_expectedMessage Failure message expected to be given
    - *     with the exception.
    - */
    -var assertThrowsJsUnitException = function(callback, opt_expectedMessage) {
    -  var failed = false;
    -  try {
    -    goog.testing.asserts.callWithoutLogging(callback);
    -  } catch (ex) {
    -    if (!ex.isJsUnitException) {
    -      fail('Expected a JsUnitException');
    -    }
    -    if (typeof opt_expectedMessage != 'undefined' &&
    -        ex.message != opt_expectedMessage) {
    -      fail('Expected message [' + opt_expectedMessage + '] but got [' +
    -          ex.message + ']');
    -    }
    -    failed = true;
    -  }
    -  if (!failed) {
    -    fail('Expected a failure: ' + opt_expectedMessage);
    -  }
    -};
    -
    -
    -/**
    - * @param {*} a The value to assert (1 arg) or debug message (2 args).
    - * @param {*=} opt_b The value to assert (2 args only).
    - */
    -var assertTrue = function(a, opt_b) {
    -  _validateArguments(1, arguments);
    -  var comment = commentArg(1, arguments);
    -  var booleanValue = nonCommentArg(1, 1, arguments);
    -
    -  _assert(comment, goog.isBoolean(booleanValue),
    -      'Bad argument to assertTrue(boolean)');
    -  _assert(comment, booleanValue, 'Call to assertTrue(boolean) with false');
    -};
    -
    -
    -/**
    - * @param {*} a The value to assert (1 arg) or debug message (2 args).
    - * @param {*=} opt_b The value to assert (2 args only).
    - */
    -var assertFalse = function(a, opt_b) {
    -  _validateArguments(1, arguments);
    -  var comment = commentArg(1, arguments);
    -  var booleanValue = nonCommentArg(1, 1, arguments);
    -
    -  _assert(comment, goog.isBoolean(booleanValue),
    -      'Bad argument to assertFalse(boolean)');
    -  _assert(comment, !booleanValue, 'Call to assertFalse(boolean) with true');
    -};
    -
    -
    -/**
    - * @param {*} a The expected value (2 args) or the debug message (3 args).
    - * @param {*} b The actual value (2 args) or the expected value (3 args).
    - * @param {*=} opt_c The actual value (3 args only).
    - */
    -var assertEquals = function(a, b, opt_c) {
    -  _validateArguments(2, arguments);
    -  var var1 = nonCommentArg(1, 2, arguments);
    -  var var2 = nonCommentArg(2, 2, arguments);
    -  _assert(commentArg(2, arguments), var1 === var2,
    -          goog.testing.asserts.getDefaultErrorMsg_(var1, var2));
    -};
    -
    -
    -/**
    - * @param {*} a The expected value (2 args) or the debug message (3 args).
    - * @param {*} b The actual value (2 args) or the expected value (3 args).
    - * @param {*=} opt_c The actual value (3 args only).
    - */
    -var assertNotEquals = function(a, b, opt_c) {
    -  _validateArguments(2, arguments);
    -  var var1 = nonCommentArg(1, 2, arguments);
    -  var var2 = nonCommentArg(2, 2, arguments);
    -  _assert(commentArg(2, arguments), var1 !== var2,
    -      'Expected not to be ' + _displayStringForValue(var2));
    -};
    -
    -
    -/**
    - * @param {*} a The value to assert (1 arg) or debug message (2 args).
    - * @param {*=} opt_b The value to assert (2 args only).
    - */
    -var assertNull = function(a, opt_b) {
    -  _validateArguments(1, arguments);
    -  var aVar = nonCommentArg(1, 1, arguments);
    -  _assert(commentArg(1, arguments), aVar === null,
    -      goog.testing.asserts.getDefaultErrorMsg_(null, aVar));
    -};
    -
    -
    -/**
    - * @param {*} a The value to assert (1 arg) or debug message (2 args).
    - * @param {*=} opt_b The value to assert (2 args only).
    - */
    -var assertNotNull = function(a, opt_b) {
    -  _validateArguments(1, arguments);
    -  var aVar = nonCommentArg(1, 1, arguments);
    -  _assert(commentArg(1, arguments), aVar !== null,
    -      'Expected not to be ' + _displayStringForValue(null));
    -};
    -
    -
    -/**
    - * @param {*} a The value to assert (1 arg) or debug message (2 args).
    - * @param {*=} opt_b The value to assert (2 args only).
    - */
    -var assertUndefined = function(a, opt_b) {
    -  _validateArguments(1, arguments);
    -  var aVar = nonCommentArg(1, 1, arguments);
    -  _assert(commentArg(1, arguments), aVar === JSUNIT_UNDEFINED_VALUE,
    -      goog.testing.asserts.getDefaultErrorMsg_(JSUNIT_UNDEFINED_VALUE, aVar));
    -};
    -
    -
    -/**
    - * @param {*} a The value to assert (1 arg) or debug message (2 args).
    - * @param {*=} opt_b The value to assert (2 args only).
    - */
    -var assertNotUndefined = function(a, opt_b) {
    -  _validateArguments(1, arguments);
    -  var aVar = nonCommentArg(1, 1, arguments);
    -  _assert(commentArg(1, arguments), aVar !== JSUNIT_UNDEFINED_VALUE,
    -      'Expected not to be ' + _displayStringForValue(JSUNIT_UNDEFINED_VALUE));
    -};
    -
    -
    -/**
    - * @param {*} a The value to assert (1 arg) or debug message (2 args).
    - * @param {*=} opt_b The value to assert (2 args only).
    - */
    -var assertNotNullNorUndefined = function(a, opt_b) {
    -  _validateArguments(1, arguments);
    -  assertNotNull.apply(null, arguments);
    -  assertNotUndefined.apply(null, arguments);
    -};
    -
    -
    -/**
    - * @param {*} a The value to assert (1 arg) or debug message (2 args).
    - * @param {*=} opt_b The value to assert (2 args only).
    - */
    -var assertNonEmptyString = function(a, opt_b) {
    -  _validateArguments(1, arguments);
    -  var aVar = nonCommentArg(1, 1, arguments);
    -  _assert(commentArg(1, arguments),
    -      aVar !== JSUNIT_UNDEFINED_VALUE && aVar !== null &&
    -      typeof aVar == 'string' && aVar !== '',
    -      'Expected non-empty string but was ' + _displayStringForValue(aVar));
    -};
    -
    -
    -/**
    - * @param {*} a The value to assert (1 arg) or debug message (2 args).
    - * @param {*=} opt_b The value to assert (2 args only).
    - */
    -var assertNaN = function(a, opt_b) {
    -  _validateArguments(1, arguments);
    -  var aVar = nonCommentArg(1, 1, arguments);
    -  _assert(commentArg(1, arguments), isNaN(aVar), 'Expected NaN');
    -};
    -
    -
    -/**
    - * @param {*} a The value to assert (1 arg) or debug message (2 args).
    - * @param {*=} opt_b The value to assert (2 args only).
    - */
    -var assertNotNaN = function(a, opt_b) {
    -  _validateArguments(1, arguments);
    -  var aVar = nonCommentArg(1, 1, arguments);
    -  _assert(commentArg(1, arguments), !isNaN(aVar), 'Expected not NaN');
    -};
    -
    -
    -/**
    - * Runs a function in an environment where test failures are not logged. This is
    - * useful for testing test code, where failures can be a normal part of a test.
    - * @param {function() : void} fn Function to run without logging failures.
    - */
    -goog.testing.asserts.callWithoutLogging = function(fn) {
    -  var testRunner = goog.global['G_testRunner'];
    -  var oldLogTestFailure = testRunner['logTestFailure'];
    -  try {
    -    // Any failures in the callback shouldn't be recorded.
    -    testRunner['logTestFailure'] = undefined;
    -    fn();
    -  } finally {
    -    testRunner['logTestFailure'] = oldLogTestFailure;
    -  }
    -};
    -
    -
    -/**
    - * The return value of the equality predicate passed to findDifferences below,
    - * in cases where the predicate can't test the input variables for equality.
    - * @type {?string}
    - */
    -goog.testing.asserts.EQUALITY_PREDICATE_CANT_PROCESS = null;
    -
    -
    -/**
    - * The return value of the equality predicate passed to findDifferences below,
    - * in cases where the input vriables are equal.
    - * @type {?string}
    - */
    -goog.testing.asserts.EQUALITY_PREDICATE_VARS_ARE_EQUAL = '';
    -
    -
    -/**
    - * Determines if two items of any type match, and formulates an error message
    - * if not.
    - * @param {*} expected Expected argument to match.
    - * @param {*} actual Argument as a result of performing the test.
    - * @param {(function(string, *, *): ?string)=} opt_equalityPredicate An optional
    - *     function that can be used to check equality of variables. It accepts 3
    - *     arguments: type-of-variables, var1, var2 (in that order) and returns an
    - *     error message if the variables are not equal,
    - *     goog.testing.asserts.EQUALITY_PREDICATE_VARS_ARE_EQUAL if the variables
    - *     are equal, or
    - *     goog.testing.asserts.EQUALITY_PREDICATE_CANT_PROCESS if the predicate
    - *     couldn't check the input variables. The function will be called only if
    - *     the types of var1 and var2 are identical.
    - * @return {?string} Null on success, error message on failure.
    - */
    -goog.testing.asserts.findDifferences = function(expected, actual,
    -    opt_equalityPredicate) {
    -  var failures = [];
    -  var seen1 = [];
    -  var seen2 = [];
    -
    -  // To avoid infinite recursion when the two parameters are self-referential
    -  // along the same path of properties, keep track of the object pairs already
    -  // seen in this call subtree, and abort when a cycle is detected.
    -  function innerAssertWithCycleCheck(var1, var2, path) {
    -    // This is used for testing, so we can afford to be slow (but more
    -    // accurate). So we just check whether var1 is in seen1. If we
    -    // found var1 in index i, we simply need to check whether var2 is
    -    // in seen2[i]. If it is, we do not recurse to check var1/var2. If
    -    // it isn't, we know that the structures of the two objects must be
    -    // different.
    -    //
    -    // This is based on the fact that values at index i in seen1 and
    -    // seen2 will be checked for equality eventually (when
    -    // innerAssertImplementation(seen1[i], seen2[i], path) finishes).
    -    for (var i = 0; i < seen1.length; ++i) {
    -      var match1 = seen1[i] === var1;
    -      var match2 = seen2[i] === var2;
    -      if (match1 || match2) {
    -        if (!match1 || !match2) {
    -          // Asymmetric cycles, so the objects have different structure.
    -          failures.push('Asymmetric cycle detected at ' + path);
    -        }
    -        return;
    -      }
    -    }
    -
    -    seen1.push(var1);
    -    seen2.push(var2);
    -    innerAssertImplementation(var1, var2, path);
    -    seen1.pop();
    -    seen2.pop();
    -  }
    -
    -  var equalityPredicate = opt_equalityPredicate || function(type, var1, var2) {
    -    var typedPredicate = PRIMITIVE_EQUALITY_PREDICATES[type];
    -    if (!typedPredicate) {
    -      return goog.testing.asserts.EQUALITY_PREDICATE_CANT_PROCESS;
    -    }
    -    var equal = typedPredicate(var1, var2);
    -    return equal ? goog.testing.asserts.EQUALITY_PREDICATE_VARS_ARE_EQUAL :
    -        goog.testing.asserts.getDefaultErrorMsg_(var1, var2);
    -  };
    -
    -  /**
    -   * @param {*} var1 An item in the expected object.
    -   * @param {*} var2 The corresponding item in the actual object.
    -   * @param {string} path Their path in the objects.
    -   * @suppress {missingProperties} The map_ property is unknown to the compiler
    -   *     unless goog.structs.Map is loaded.
    -   */
    -  function innerAssertImplementation(var1, var2, path) {
    -    if (var1 === var2) {
    -      return;
    -    }
    -
    -    var typeOfVar1 = _trueTypeOf(var1);
    -    var typeOfVar2 = _trueTypeOf(var2);
    -
    -    if (typeOfVar1 == typeOfVar2) {
    -      var isArray = typeOfVar1 == 'Array';
    -      var errorMessage = equalityPredicate(typeOfVar1, var1, var2);
    -      if (errorMessage !=
    -          goog.testing.asserts.EQUALITY_PREDICATE_CANT_PROCESS) {
    -        if (errorMessage !=
    -            goog.testing.asserts.EQUALITY_PREDICATE_VARS_ARE_EQUAL) {
    -          failures.push(path + ': ' + errorMessage);
    -        }
    -      } else if (isArray && var1.length != var2.length) {
    -        failures.push(path + ': Expected ' + var1.length + '-element array ' +
    -                      'but got a ' + var2.length + '-element array');
    -      } else {
    -        var childPath = path + (isArray ? '[%s]' : (path ? '.%s' : '%s'));
    -
    -        // if an object has an __iterator__ property, we have no way of
    -        // actually inspecting its raw properties, and JS 1.7 doesn't
    -        // overload [] to make it possible for someone to generically
    -        // use what the iterator returns to compare the object-managed
    -        // properties. This gets us into deep poo with things like
    -        // goog.structs.Map, at least on systems that support iteration.
    -        if (!var1['__iterator__']) {
    -          for (var prop in var1) {
    -            if (isArray && goog.testing.asserts.isArrayIndexProp_(prop)) {
    -              // Skip array indices for now. We'll handle them later.
    -              continue;
    -            }
    -
    -            if (prop in var2) {
    -              innerAssertWithCycleCheck(var1[prop], var2[prop],
    -                  childPath.replace('%s', prop));
    -            } else {
    -              failures.push('property ' + prop +
    -                            ' not present in actual ' + (path || typeOfVar2));
    -            }
    -          }
    -          // make sure there aren't properties in var2 that are missing
    -          // from var1. if there are, then by definition they don't
    -          // match.
    -          for (var prop in var2) {
    -            if (isArray && goog.testing.asserts.isArrayIndexProp_(prop)) {
    -              // Skip array indices for now. We'll handle them later.
    -              continue;
    -            }
    -
    -            if (!(prop in var1)) {
    -              failures.push('property ' + prop +
    -                            ' not present in expected ' +
    -                            (path || typeOfVar1));
    -            }
    -          }
    -
    -          // Handle array indices by iterating from 0 to arr.length.
    -          //
    -          // Although all browsers allow holes in arrays, browsers
    -          // are inconsistent in what they consider a hole. For example,
    -          // "[0,undefined,2]" has a hole on IE but not on Firefox.
    -          //
    -          // Because our style guide bans for...in iteration over arrays,
    -          // we assume that most users don't care about holes in arrays,
    -          // and that it is ok to say that a hole is equivalent to a slot
    -          // populated with 'undefined'.
    -          if (isArray) {
    -            for (prop = 0; prop < var1.length; prop++) {
    -              innerAssertWithCycleCheck(var1[prop], var2[prop],
    -                  childPath.replace('%s', String(prop)));
    -            }
    -          }
    -        } else {
    -          // special-case for closure objects that have iterators
    -          if (goog.isFunction(var1.equals)) {
    -            // use the object's own equals function, assuming it accepts an
    -            // object and returns a boolean
    -            if (!var1.equals(var2)) {
    -              failures.push('equals() returned false for ' +
    -                            (path || typeOfVar1));
    -            }
    -          } else if (var1.map_) {
    -            // assume goog.structs.Map or goog.structs.Set, where comparing
    -            // their private map_ field is sufficient
    -            innerAssertWithCycleCheck(var1.map_, var2.map_,
    -                childPath.replace('%s', 'map_'));
    -          } else {
    -            // else die, so user knows we can't do anything
    -            failures.push('unable to check ' + (path || typeOfVar1) +
    -                          ' for equality: it has an iterator we do not ' +
    -                          'know how to handle. please add an equals method');
    -          }
    -        }
    -      }
    -    } else {
    -      failures.push(path + ' ' +
    -          goog.testing.asserts.getDefaultErrorMsg_(var1, var2));
    -    }
    -  }
    -
    -  innerAssertWithCycleCheck(expected, actual, '');
    -  return failures.length == 0 ? null :
    -      goog.testing.asserts.getDefaultErrorMsg_(expected, actual) +
    -          '\n   ' + failures.join('\n   ');
    -};
    -
    -
    -/**
    - * Notes:
    - * Object equality has some nasty browser quirks, and this implementation is
    - * not 100% correct. For example,
    - *
    - * <code>
    - * var a = [0, 1, 2];
    - * var b = [0, 1, 2];
    - * delete a[1];
    - * b[1] = undefined;
    - * assertObjectEquals(a, b); // should fail, but currently passes
    - * </code>
    - *
    - * See asserts_test.html for more interesting edge cases.
    - *
    - * The first comparison object provided is the expected value, the second is
    - * the actual.
    - *
    - * @param {*} a Assertion message or comparison object.
    - * @param {*} b Comparison object.
    - * @param {*=} opt_c Comparison object, if an assertion message was provided.
    - */
    -var assertObjectEquals = function(a, b, opt_c) {
    -  _validateArguments(2, arguments);
    -  var v1 = nonCommentArg(1, 2, arguments);
    -  var v2 = nonCommentArg(2, 2, arguments);
    -  var failureMessage = commentArg(2, arguments) ? commentArg(2, arguments) : '';
    -  var differences = goog.testing.asserts.findDifferences(v1, v2);
    -
    -  _assert(failureMessage, !differences, differences);
    -};
    -
    -
    -/**
    - * Similar to assertObjectEquals above, but accepts a tolerance margin.
    - *
    - * @param {*} a Assertion message or comparison object.
    - * @param {*} b Comparison object.
    - * @param {*} c Comparison object or tolerance.
    - * @param {*=} opt_d Tolerance, if an assertion message was provided.
    - */
    -var assertObjectRoughlyEquals = function(a, b, c, opt_d) {
    -  _validateArguments(3, arguments);
    -  var v1 = nonCommentArg(1, 3, arguments);
    -  var v2 = nonCommentArg(2, 3, arguments);
    -  var tolerance = nonCommentArg(3, 3, arguments);
    -  var failureMessage = commentArg(3, arguments) ? commentArg(3, arguments) : '';
    -  var equalityPredicate = function(type, var1, var2) {
    -    var typedPredicate =
    -        goog.testing.asserts.primitiveRoughEqualityPredicates_[type];
    -    if (!typedPredicate) {
    -      return goog.testing.asserts.EQUALITY_PREDICATE_CANT_PROCESS;
    -    }
    -    var equal = typedPredicate(var1, var2, tolerance);
    -    return equal ? goog.testing.asserts.EQUALITY_PREDICATE_VARS_ARE_EQUAL :
    -        goog.testing.asserts.getDefaultErrorMsg_(var1, var2) +
    -        ' which was more than ' + tolerance + ' away';
    -  };
    -  var differences = goog.testing.asserts.findDifferences(
    -      v1, v2, equalityPredicate);
    -
    -  _assert(failureMessage, !differences, differences);
    -};
    -
    -
    -/**
    - * Compares two arbitrary objects for non-equalness.
    - *
    - * All the same caveats as for assertObjectEquals apply here:
    - * Undefined values may be confused for missing values, or vice versa.
    - *
    - * @param {*} a Assertion message or comparison object.
    - * @param {*} b Comparison object.
    - * @param {*=} opt_c Comparison object, if an assertion message was provided.
    - */
    -var assertObjectNotEquals = function(a, b, opt_c) {
    -  _validateArguments(2, arguments);
    -  var v1 = nonCommentArg(1, 2, arguments);
    -  var v2 = nonCommentArg(2, 2, arguments);
    -  var failureMessage = commentArg(2, arguments) ? commentArg(2, arguments) : '';
    -  var differences = goog.testing.asserts.findDifferences(v1, v2);
    -
    -  _assert(failureMessage, differences, 'Objects should not be equal');
    -};
    -
    -
    -/**
    - * Compares two arrays ignoring negative indexes and extra properties on the
    - * array objects. Use case: Internet Explorer adds the index, lastIndex and
    - * input enumerable fields to the result of string.match(/regexp/g), which makes
    - * assertObjectEquals fail.
    - * @param {*} a The expected array (2 args) or the debug message (3 args).
    - * @param {*} b The actual array (2 args) or the expected array (3 args).
    - * @param {*=} opt_c The actual array (3 args only).
    - */
    -var assertArrayEquals = function(a, b, opt_c) {
    -  _validateArguments(2, arguments);
    -  var v1 = nonCommentArg(1, 2, arguments);
    -  var v2 = nonCommentArg(2, 2, arguments);
    -  var failureMessage = commentArg(2, arguments) ? commentArg(2, arguments) : '';
    -
    -  var typeOfVar1 = _trueTypeOf(v1);
    -  _assert(failureMessage,
    -          typeOfVar1 == 'Array',
    -          'Expected an array for assertArrayEquals but found a ' + typeOfVar1);
    -
    -  var typeOfVar2 = _trueTypeOf(v2);
    -  _assert(failureMessage,
    -          typeOfVar2 == 'Array',
    -          'Expected an array for assertArrayEquals but found a ' + typeOfVar2);
    -
    -  assertObjectEquals(failureMessage,
    -      Array.prototype.concat.call(v1), Array.prototype.concat.call(v2));
    -};
    -
    -
    -/**
    - * Compares two objects that can be accessed like an array and assert that
    - * each element is equal.
    - * @param {string|Object} a Failure message (3 arguments)
    - *     or object #1 (2 arguments).
    - * @param {Object} b Object #1 (2 arguments) or object #2 (3 arguments).
    - * @param {Object=} opt_c Object #2 (3 arguments).
    - */
    -var assertElementsEquals = function(a, b, opt_c) {
    -  _validateArguments(2, arguments);
    -
    -  var v1 = nonCommentArg(1, 2, arguments);
    -  var v2 = nonCommentArg(2, 2, arguments);
    -  var failureMessage = commentArg(2, arguments) ? commentArg(2, arguments) : '';
    -
    -  if (!v1) {
    -    assert(failureMessage, !v2);
    -  } else {
    -    assertEquals('length mismatch: ' + failureMessage, v1.length, v2.length);
    -    for (var i = 0; i < v1.length; ++i) {
    -      assertEquals(
    -          'mismatch at index ' + i + ': ' + failureMessage, v1[i], v2[i]);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compares two objects that can be accessed like an array and assert that
    - * each element is roughly equal.
    - * @param {string|Object} a Failure message (4 arguments)
    - *     or object #1 (3 arguments).
    - * @param {Object} b Object #1 (4 arguments) or object #2 (3 arguments).
    - * @param {Object|number} c Object #2 (4 arguments) or tolerance (3 arguments).
    - * @param {number=} opt_d tolerance (4 arguments).
    - */
    -var assertElementsRoughlyEqual = function(a, b, c, opt_d) {
    -  _validateArguments(3, arguments);
    -
    -  var v1 = nonCommentArg(1, 3, arguments);
    -  var v2 = nonCommentArg(2, 3, arguments);
    -  var tolerance = nonCommentArg(3, 3, arguments);
    -  var failureMessage = commentArg(3, arguments) ? commentArg(3, arguments) : '';
    -
    -  if (!v1) {
    -    assert(failureMessage, !v2);
    -  } else {
    -    assertEquals('length mismatch: ' + failureMessage, v1.length, v2.length);
    -    for (var i = 0; i < v1.length; ++i) {
    -      assertRoughlyEquals(failureMessage, v1[i], v2[i], tolerance);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Compares two array-like objects without taking their order into account.
    - * @param {string|goog.testing.asserts.ArrayLike} a Assertion message or the
    - *     expected elements.
    - * @param {goog.testing.asserts.ArrayLike} b Expected elements or the actual
    - *     elements.
    - * @param {goog.testing.asserts.ArrayLike=} opt_c Actual elements.
    - */
    -var assertSameElements = function(a, b, opt_c) {
    -  _validateArguments(2, arguments);
    -  var expected = nonCommentArg(1, 2, arguments);
    -  var actual = nonCommentArg(2, 2, arguments);
    -  var message = commentArg(2, arguments);
    -
    -  assertTrue('Bad arguments to assertSameElements(opt_message, expected: ' +
    -      'ArrayLike, actual: ArrayLike)',
    -      goog.isArrayLike(expected) && goog.isArrayLike(actual));
    -
    -  // Clones expected and actual and converts them to real arrays.
    -  expected = goog.testing.asserts.toArray_(expected);
    -  actual = goog.testing.asserts.toArray_(actual);
    -  // TODO(user): It would be great to show only the difference
    -  // between the expected and actual elements.
    -  _assert(message, expected.length == actual.length,
    -      'Expected ' + expected.length + ' elements: [' + expected + '], ' +
    -      'got ' + actual.length + ' elements: [' + actual + ']');
    -
    -  var toFind = goog.testing.asserts.toArray_(expected);
    -  for (var i = 0; i < actual.length; i++) {
    -    var index = goog.testing.asserts.indexOf_(toFind, actual[i]);
    -    _assert(message, index != -1, 'Expected [' + expected + '], got [' +
    -        actual + ']');
    -    toFind.splice(index, 1);
    -  }
    -};
    -
    -
    -/**
    - * @param {*} a The value to assert (1 arg) or debug message (2 args).
    - * @param {*=} opt_b The value to assert (2 args only).
    - */
    -var assertEvaluatesToTrue = function(a, opt_b) {
    -  _validateArguments(1, arguments);
    -  var value = nonCommentArg(1, 1, arguments);
    -  if (!value) {
    -    _assert(commentArg(1, arguments), false, 'Expected to evaluate to true');
    -  }
    -};
    -
    -
    -/**
    - * @param {*} a The value to assert (1 arg) or debug message (2 args).
    - * @param {*=} opt_b The value to assert (2 args only).
    - */
    -var assertEvaluatesToFalse = function(a, opt_b) {
    -  _validateArguments(1, arguments);
    -  var value = nonCommentArg(1, 1, arguments);
    -  if (value) {
    -    _assert(commentArg(1, arguments), false, 'Expected to evaluate to false');
    -  }
    -};
    -
    -
    -/**
    - * Compares two HTML snippets.
    - *
    - * Take extra care if attributes are involved. {@code assertHTMLEquals}'s
    - * implementation isn't prepared for complex cases. For example, the following
    - * comparisons erroneously fail:
    - * <pre>
    - * assertHTMLEquals('<a href="x" target="y">', '<a target="y" href="x">');
    - * assertHTMLEquals('<div classname="a b">', '<div classname="b a">');
    - * assertHTMLEquals('<input disabled>', '<input disabled="disabled">');
    - * </pre>
    - *
    - * When in doubt, use {@code goog.testing.dom.assertHtmlMatches}.
    - *
    - * @param {*} a The expected value (2 args) or the debug message (3 args).
    - * @param {*} b The actual value (2 args) or the expected value (3 args).
    - * @param {*=} opt_c The actual value (3 args only).
    - */
    -var assertHTMLEquals = function(a, b, opt_c) {
    -  _validateArguments(2, arguments);
    -  var var1 = nonCommentArg(1, 2, arguments);
    -  var var2 = nonCommentArg(2, 2, arguments);
    -  var var1Standardized = standardizeHTML(var1);
    -  var var2Standardized = standardizeHTML(var2);
    -
    -  _assert(commentArg(2, arguments), var1Standardized === var2Standardized,
    -          goog.testing.asserts.getDefaultErrorMsg_(
    -              var1Standardized, var2Standardized));
    -};
    -
    -
    -/**
    - * Compares two CSS property values to make sure that they represent the same
    - * things. This will normalize values in the browser. For example, in Firefox,
    - * this assertion will consider "rgb(0, 0, 255)" and "#0000ff" to be identical
    - * values for the "color" property. This function won't normalize everything --
    - * for example, in most browsers, "blue" will not match "#0000ff". It is
    - * intended only to compensate for unexpected normalizations performed by
    - * the browser that should also affect your expected value.
    - * @param {string} a Assertion message, or the CSS property name.
    - * @param {string} b CSS property name, or the expected value.
    - * @param {string} c The expected value, or the actual value.
    - * @param {string=} opt_d The actual value.
    - */
    -var assertCSSValueEquals = function(a, b, c, opt_d) {
    -  _validateArguments(3, arguments);
    -  var propertyName = nonCommentArg(1, 3, arguments);
    -  var expectedValue = nonCommentArg(2, 3, arguments);
    -  var actualValue = nonCommentArg(3, 3, arguments);
    -  var expectedValueStandardized =
    -      standardizeCSSValue(propertyName, expectedValue);
    -  var actualValueStandardized =
    -      standardizeCSSValue(propertyName, actualValue);
    -
    -  _assert(commentArg(3, arguments),
    -          expectedValueStandardized == actualValueStandardized,
    -          goog.testing.asserts.getDefaultErrorMsg_(
    -              expectedValueStandardized, actualValueStandardized));
    -};
    -
    -
    -/**
    - * @param {*} a The expected value (2 args) or the debug message (3 args).
    - * @param {*} b The actual value (2 args) or the expected value (3 args).
    - * @param {*=} opt_c The actual value (3 args only).
    - */
    -var assertHashEquals = function(a, b, opt_c) {
    -  _validateArguments(2, arguments);
    -  var var1 = nonCommentArg(1, 2, arguments);
    -  var var2 = nonCommentArg(2, 2, arguments);
    -  var message = commentArg(2, arguments);
    -  for (var key in var1) {
    -    _assert(message,
    -        key in var2, 'Expected hash had key ' + key + ' that was not found');
    -    _assert(message, var1[key] == var2[key], 'Value for key ' + key +
    -        ' mismatch - expected = ' + var1[key] + ', actual = ' + var2[key]);
    -  }
    -
    -  for (var key in var2) {
    -    _assert(message, key in var1, 'Actual hash had key ' + key +
    -        ' that was not expected');
    -  }
    -};
    -
    -
    -/**
    - * @param {*} a The expected value (3 args) or the debug message (4 args).
    - * @param {*} b The actual value (3 args) or the expected value (4 args).
    - * @param {*} c The tolerance (3 args) or the actual value (4 args).
    - * @param {*=} opt_d The tolerance (4 args only).
    - */
    -var assertRoughlyEquals = function(a, b, c, opt_d) {
    -  _validateArguments(3, arguments);
    -  var expected = nonCommentArg(1, 3, arguments);
    -  var actual = nonCommentArg(2, 3, arguments);
    -  var tolerance = nonCommentArg(3, 3, arguments);
    -  _assert(commentArg(3, arguments),
    -      goog.testing.asserts.numberRoughEqualityPredicate_(
    -          expected, actual, tolerance),
    -      'Expected ' + expected + ', but got ' + actual +
    -      ' which was more than ' + tolerance + ' away');
    -};
    -
    -
    -/**
    - * Checks if the given element is the member of the given container.
    - * @param {*} a Failure message (3 arguments) or the contained element
    - *     (2 arguments).
    - * @param {*} b The contained element (3 arguments) or the container
    - *     (2 arguments).
    - * @param {*=} opt_c The container.
    - */
    -var assertContains = function(a, b, opt_c) {
    -  _validateArguments(2, arguments);
    -  var contained = nonCommentArg(1, 2, arguments);
    -  var container = nonCommentArg(2, 2, arguments);
    -  _assert(commentArg(2, arguments),
    -      goog.testing.asserts.contains_(container, contained),
    -      'Expected \'' + container + '\' to contain \'' + contained + '\'');
    -};
    -
    -
    -/**
    - * Checks if the given element is not the member of the given container.
    - * @param {*} a Failure message (3 arguments) or the contained element
    - *     (2 arguments).
    - * @param {*} b The contained element (3 arguments) or the container
    - *     (2 arguments).
    - * @param {*=} opt_c The container.
    - */
    -var assertNotContains = function(a, b, opt_c) {
    -  _validateArguments(2, arguments);
    -  var contained = nonCommentArg(1, 2, arguments);
    -  var container = nonCommentArg(2, 2, arguments);
    -  _assert(commentArg(2, arguments),
    -      !goog.testing.asserts.contains_(container, contained),
    -      'Expected \'' + container + '\' not to contain \'' + contained + '\'');
    -};
    -
    -
    -/**
    - * Checks if the given string matches the given regular expression.
    - * @param {*} a Failure message (3 arguments) or the expected regular
    - *     expression as a string or RegExp (2 arguments).
    - * @param {*} b The regular expression (3 arguments) or the string to test
    - *     (2 arguments).
    - * @param {*=} opt_c The string to test.
    - */
    -var assertRegExp = function(a, b, opt_c) {
    -  _validateArguments(2, arguments);
    -  var regexp = nonCommentArg(1, 2, arguments);
    -  var string = nonCommentArg(2, 2, arguments);
    -  if (typeof(regexp) == 'string') {
    -    regexp = new RegExp(regexp);
    -  }
    -  _assert(commentArg(2, arguments),
    -      regexp.test(string),
    -      'Expected \'' + string + '\' to match RegExp ' + regexp.toString());
    -};
    -
    -
    -/**
    - * Converts an array like object to array or clones it if it's already array.
    - * @param {goog.testing.asserts.ArrayLike} arrayLike The collection.
    - * @return {!Array<?>} Copy of the collection as array.
    - * @private
    - */
    -goog.testing.asserts.toArray_ = function(arrayLike) {
    -  var ret = [];
    -  for (var i = 0; i < arrayLike.length; i++) {
    -    ret[i] = arrayLike[i];
    -  }
    -  return ret;
    -};
    -
    -
    -/**
    - * Finds the position of the first occurrence of an element in a container.
    - * @param {goog.testing.asserts.ArrayLike} container
    - *     The array to find the element in.
    - * @param {*} contained Element to find.
    - * @return {number} Index of the first occurrence or -1 if not found.
    - * @private
    - */
    -goog.testing.asserts.indexOf_ = function(container, contained) {
    -  if (container.indexOf) {
    -    return container.indexOf(contained);
    -  } else {
    -    // IE6/7 do not have indexOf so do a search.
    -    for (var i = 0; i < container.length; i++) {
    -      if (container[i] === contained) {
    -        return i;
    -      }
    -    }
    -    return -1;
    -  }
    -};
    -
    -
    -/**
    - * Tells whether the array contains the given element.
    - * @param {goog.testing.asserts.ArrayLike} container The array to
    - *     find the element in.
    - * @param {*} contained Element to find.
    - * @return {boolean} Whether the element is in the array.
    - * @private
    - */
    -goog.testing.asserts.contains_ = function(container, contained) {
    -  // TODO(user): Can we check for container.contains as well?
    -  // That would give us support for most goog.structs (though weird results
    -  // with anything else with a contains method, like goog.math.Range). Falling
    -  // back with container.some would catch all iterables, too.
    -  return goog.testing.asserts.indexOf_(container, contained) != -1;
    -};
    -
    -var standardizeHTML = function(html) {
    -  var translator = document.createElement('DIV');
    -  translator.innerHTML = html;
    -
    -  // Trim whitespace from result (without relying on goog.string)
    -  return translator.innerHTML.replace(/^\s+|\s+$/g, '');
    -};
    -
    -
    -/**
    - * Standardizes a CSS value for a given property by applying it to an element
    - * and then reading it back.
    - * @param {string} propertyName CSS property name.
    - * @param {string} value CSS value.
    - * @return {string} Normalized CSS value.
    - */
    -var standardizeCSSValue = function(propertyName, value) {
    -  var styleDeclaration = document.createElement('DIV').style;
    -  styleDeclaration[propertyName] = value;
    -  return styleDeclaration[propertyName];
    -};
    -
    -
    -/**
    - * Raises a JsUnit exception with the given comment.
    - * @param {string} comment A summary for the exception.
    - * @param {string=} opt_message A description of the exception.
    - */
    -goog.testing.asserts.raiseException = function(comment, opt_message) {
    -  throw new goog.testing.JsUnitException(comment, opt_message);
    -};
    -
    -
    -/**
    - * Helper function for assertObjectEquals.
    - * @param {string} prop A property name.
    - * @return {boolean} If the property name is an array index.
    - * @private
    - */
    -goog.testing.asserts.isArrayIndexProp_ = function(prop) {
    -  return (prop | 0) == prop;
    -};
    -
    -
    -
    -/**
    - * @param {string} comment A summary for the exception.
    - * @param {?string=} opt_message A description of the exception.
    - * @constructor
    - * @extends {Error}
    - * @final
    - */
    -goog.testing.JsUnitException = function(comment, opt_message) {
    -  this.isJsUnitException = true;
    -  this.message = (comment ? comment : '') +
    -                 (comment && opt_message ? '\n' : '') +
    -                 (opt_message ? opt_message : '');
    -  this.stackTrace = goog.testing.stacktrace.get();
    -  // These fields are for compatibility with jsUnitTestManager.
    -  this.comment = comment || null;
    -  this.jsUnitMessage = opt_message || '';
    -
    -  // Ensure there is a stack trace.
    -  if (Error.captureStackTrace) {
    -    Error.captureStackTrace(this, goog.testing.JsUnitException);
    -  } else {
    -    this.stack = new Error().stack || '';
    -  }
    -};
    -goog.inherits(goog.testing.JsUnitException, Error);
    -
    -
    -/** @override */
    -goog.testing.JsUnitException.prototype.toString = function() {
    -  return this.message;
    -};
    -
    -
    -goog.exportSymbol('fail', fail);
    -goog.exportSymbol('assert', assert);
    -goog.exportSymbol('assertThrows', assertThrows);
    -goog.exportSymbol('assertNotThrows', assertNotThrows);
    -goog.exportSymbol('assertTrue', assertTrue);
    -goog.exportSymbol('assertFalse', assertFalse);
    -goog.exportSymbol('assertEquals', assertEquals);
    -goog.exportSymbol('assertNotEquals', assertNotEquals);
    -goog.exportSymbol('assertNull', assertNull);
    -goog.exportSymbol('assertNotNull', assertNotNull);
    -goog.exportSymbol('assertUndefined', assertUndefined);
    -goog.exportSymbol('assertNotUndefined', assertNotUndefined);
    -goog.exportSymbol('assertNotNullNorUndefined', assertNotNullNorUndefined);
    -goog.exportSymbol('assertNonEmptyString', assertNonEmptyString);
    -goog.exportSymbol('assertNaN', assertNaN);
    -goog.exportSymbol('assertNotNaN', assertNotNaN);
    -goog.exportSymbol('assertObjectEquals', assertObjectEquals);
    -goog.exportSymbol('assertObjectRoughlyEquals', assertObjectRoughlyEquals);
    -goog.exportSymbol('assertObjectNotEquals', assertObjectNotEquals);
    -goog.exportSymbol('assertArrayEquals', assertArrayEquals);
    -goog.exportSymbol('assertElementsEquals', assertElementsEquals);
    -goog.exportSymbol('assertElementsRoughlyEqual', assertElementsRoughlyEqual);
    -goog.exportSymbol('assertSameElements', assertSameElements);
    -goog.exportSymbol('assertEvaluatesToTrue', assertEvaluatesToTrue);
    -goog.exportSymbol('assertEvaluatesToFalse', assertEvaluatesToFalse);
    -goog.exportSymbol('assertHTMLEquals', assertHTMLEquals);
    -goog.exportSymbol('assertHashEquals', assertHashEquals);
    -goog.exportSymbol('assertRoughlyEquals', assertRoughlyEquals);
    -goog.exportSymbol('assertContains', assertContains);
    -goog.exportSymbol('assertNotContains', assertNotContains);
    -goog.exportSymbol('assertRegExp', assertRegExp);
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/asserts_test.html b/src/database/third_party/closure-library/closure/goog/testing/asserts_test.html
    deleted file mode 100644
    index adb266db6a4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/asserts_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.testing.asserts
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.assertsTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/asserts_test.js b/src/database/third_party/closure-library/closure/goog/testing/asserts_test.js
    deleted file mode 100644
    index bcf29a19c39..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/asserts_test.js
    +++ /dev/null
    @@ -1,1181 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.assertsTest');
    -goog.setTestOnly('goog.testing.assertsTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.iter.Iterator');
    -goog.require('goog.iter.StopIteration');
    -goog.require('goog.labs.userAgent.browser');
    -goog.require('goog.string');
    -goog.require('goog.structs.Map');
    -goog.require('goog.structs.Set');
    -goog.require('goog.testing.asserts');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -function testAssertTrue() {
    -  assertTrue(true);
    -  assertTrue('Good assertion', true);
    -  assertThrowsJsUnitException(
    -      function() { assertTrue(false); },
    -      'Call to assertTrue(boolean) with false');
    -  assertThrowsJsUnitException(
    -      function() { assertTrue('Should be true', false); },
    -      'Should be true\nCall to assertTrue(boolean) with false');
    -  assertThrowsJsUnitException(
    -      function() { assertTrue(null); },
    -      'Bad argument to assertTrue(boolean)');
    -  assertThrowsJsUnitException(
    -      function() { assertTrue(undefined); },
    -      'Bad argument to assertTrue(boolean)');
    -}
    -
    -function testAssertFalse() {
    -  assertFalse(false);
    -  assertFalse('Good assertion', false);
    -  assertThrowsJsUnitException(
    -      function() { assertFalse(true); },
    -      'Call to assertFalse(boolean) with true');
    -  assertThrowsJsUnitException(
    -      function() { assertFalse('Should be false', true); },
    -      'Should be false\nCall to assertFalse(boolean) with true');
    -  assertThrowsJsUnitException(
    -      function() { assertFalse(null); },
    -      'Bad argument to assertFalse(boolean)');
    -  assertThrowsJsUnitException(
    -      function() { assertFalse(undefined); },
    -      'Bad argument to assertFalse(boolean)');
    -}
    -
    -function testAssertEqualsWithString() {
    -  assertEquals('a', 'a');
    -  assertEquals('Good assertion', 'a', 'a');
    -  assertThrowsJsUnitException(
    -      function() { assertEquals('a', 'b'); },
    -      'Expected <a> (String) but was <b> (String)');
    -  assertThrowsJsUnitException(
    -      function() { assertEquals('Bad assertion', 'a', 'b'); },
    -      'Bad assertion\nExpected <a> (String) but was <b> (String)');
    -}
    -
    -function testAssertEqualsWithInteger() {
    -  assertEquals(1, 1);
    -  assertEquals('Good assertion', 1, 1);
    -  assertThrowsJsUnitException(
    -      function() { assertEquals(1, 2); },
    -      'Expected <1> (Number) but was <2> (Number)');
    -  assertThrowsJsUnitException(
    -      function() { assertEquals('Bad assertion', 1, 2); },
    -      'Bad assertion\nExpected <1> (Number) but was <2> (Number)');
    -}
    -
    -function testAssertNotEquals() {
    -  assertNotEquals('a', 'b');
    -  assertNotEquals('a', 'a', 'b');
    -  assertThrowsJsUnitException(
    -      function() { assertNotEquals('a', 'a'); },
    -      'Expected not to be <a> (String)');
    -  assertThrowsJsUnitException(
    -      function() { assertNotEquals('a', 'a', 'a'); },
    -      'a\nExpected not to be <a> (String)');
    -}
    -
    -function testAssertNull() {
    -  assertNull(null);
    -  assertNull('Good assertion', null);
    -  assertThrowsJsUnitException(
    -      function() { assertNull(true); },
    -      'Expected <null> but was <true> (Boolean)');
    -  assertThrowsJsUnitException(
    -      function() { assertNull('Should be null', false); },
    -      'Should be null\nExpected <null> but was <false> (Boolean)');
    -  assertThrowsJsUnitException(
    -      function() { assertNull(undefined); },
    -      'Expected <null> but was <undefined>');
    -  assertThrowsJsUnitException(
    -      function() { assertNull(1); },
    -      'Expected <null> but was <1> (Number)');
    -}
    -
    -function testAssertNotNull() {
    -  assertNotNull(true);
    -  assertNotNull('Good assertion', true);
    -  assertNotNull(false);
    -  assertNotNull(undefined);
    -  assertNotNull(1);
    -  assertNotNull('a');
    -  assertThrowsJsUnitException(
    -      function() { assertNotNull(null); },
    -      'Expected not to be <null>');
    -  assertThrowsJsUnitException(
    -      function() { assertNotNull('Should not be null', null); },
    -      'Should not be null\nExpected not to be <null>');
    -}
    -
    -function testAssertUndefined() {
    -  assertUndefined(undefined);
    -  assertUndefined('Good assertion', undefined);
    -  assertThrowsJsUnitException(
    -      function() { assertUndefined(true); },
    -      'Expected <undefined> but was <true> (Boolean)');
    -  assertThrowsJsUnitException(
    -      function() { assertUndefined('Should be undefined', false); },
    -      'Should be undefined\nExpected <undefined> but was <false> (Boolean)');
    -  assertThrowsJsUnitException(
    -      function() { assertUndefined(null); },
    -      'Expected <undefined> but was <null>');
    -  assertThrowsJsUnitException(
    -      function() { assertUndefined(1); },
    -      'Expected <undefined> but was <1> (Number)');
    -}
    -
    -function testAssertNotUndefined() {
    -  assertNotUndefined(true);
    -  assertNotUndefined('Good assertion', true);
    -  assertNotUndefined(false);
    -  assertNotUndefined(null);
    -  assertNotUndefined(1);
    -  assertNotUndefined('a');
    -  assertThrowsJsUnitException(
    -      function() { assertNotUndefined(undefined); },
    -      'Expected not to be <undefined>');
    -  assertThrowsJsUnitException(
    -      function() { assertNotUndefined('Should not be undefined', undefined); },
    -      'Should not be undefined\nExpected not to be <undefined>');
    -}
    -
    -function testAssertNotNullNorUndefined() {
    -  assertNotNullNorUndefined(true);
    -  assertNotNullNorUndefined('Good assertion', true);
    -  assertNotNullNorUndefined(false);
    -  assertNotNullNorUndefined(1);
    -  assertNotNullNorUndefined(0);
    -  assertNotNullNorUndefined('a');
    -  assertThrowsJsUnitException(function() {
    -    assertNotNullNorUndefined(undefined);
    -  }, 'Expected not to be <undefined>');
    -  assertThrowsJsUnitException(function() {
    -    assertNotNullNorUndefined('Should not be undefined', undefined);
    -  }, 'Should not be undefined\nExpected not to be <undefined>');
    -  assertThrowsJsUnitException(function() {
    -    assertNotNullNorUndefined(null);
    -  }, 'Expected not to be <null>');
    -  assertThrowsJsUnitException(function() {
    -    assertNotNullNorUndefined('Should not be null', null);
    -  }, 'Should not be null\nExpected not to be <null>');
    -}
    -
    -function testAssertNonEmptyString() {
    -  assertNonEmptyString('hello');
    -  assertNonEmptyString('Good assertion', 'hello');
    -  assertNonEmptyString('true');
    -  assertNonEmptyString('false');
    -  assertNonEmptyString('1');
    -  assertNonEmptyString('null');
    -  assertNonEmptyString('undefined');
    -  assertNonEmptyString('\n');
    -  assertNonEmptyString(' ');
    -  assertThrowsJsUnitException(
    -      function() { assertNonEmptyString(''); },
    -      'Expected non-empty string but was <> (String)');
    -  assertThrowsJsUnitException(
    -      function() { assertNonEmptyString('Should be non-empty string', ''); },
    -      'Should be non-empty string\n' +
    -      'Expected non-empty string but was <> (String)');
    -  assertThrowsJsUnitException(
    -      function() { assertNonEmptyString(true); },
    -      'Expected non-empty string but was <true> (Boolean)');
    -  assertThrowsJsUnitException(
    -      function() { assertNonEmptyString(false); },
    -      'Expected non-empty string but was <false> (Boolean)');
    -  assertThrowsJsUnitException(
    -      function() { assertNonEmptyString(1); },
    -      'Expected non-empty string but was <1> (Number)');
    -  assertThrowsJsUnitException(
    -      function() { assertNonEmptyString(null); },
    -      'Expected non-empty string but was <null>');
    -  assertThrowsJsUnitException(
    -      function() { assertNonEmptyString(undefined); },
    -      'Expected non-empty string but was <undefined>');
    -  assertThrowsJsUnitException(
    -      function() { assertNonEmptyString(['hello']); },
    -      'Expected non-empty string but was <hello> (Array)');
    -  // Different browsers return different values/types in the failure message
    -  // so don't bother checking if the message is exactly as expected.
    -  assertThrowsJsUnitException(
    -      function() { assertNonEmptyString(goog.dom.createTextNode('hello')); });
    -}
    -
    -function testAssertNaN() {
    -  assertNaN(NaN);
    -  assertNaN('Good assertion', NaN);
    -  assertThrowsJsUnitException(
    -      function() { assertNaN(1); }, 'Expected NaN');
    -  assertThrowsJsUnitException(
    -      function() { assertNaN('Should be NaN', 1); },
    -      'Should be NaN\nExpected NaN');
    -  assertThrowsJsUnitException(
    -      function() { assertNaN(true); }, 'Expected NaN');
    -  assertThrowsJsUnitException(
    -      function() { assertNaN(false); }, 'Expected NaN');
    -  assertThrowsJsUnitException(
    -      function() { assertNaN(null); }, 'Expected NaN');
    -  assertThrowsJsUnitException(
    -      function() { assertNaN(''); }, 'Expected NaN');
    -
    -  // TODO(user): These assertions fail. We should decide on the
    -  // semantics of assertNaN
    -  //assertThrowsJsUnitException(function() { assertNaN(undefined); },
    -  //    'Expected NaN');
    -  //assertThrowsJsUnitException(function() { assertNaN('a'); },
    -  //    'Expected NaN');
    -}
    -
    -function testAssertNotNaN() {
    -  assertNotNaN(1);
    -  assertNotNaN('Good assertion', 1);
    -  assertNotNaN(true);
    -  assertNotNaN(false);
    -  assertNotNaN('');
    -  assertNotNaN(null);
    -
    -  // TODO(user): These assertions fail. We should decide on the
    -  // semantics of assertNotNaN
    -  //assertNotNaN(undefined);
    -  //assertNotNaN('a');
    -
    -  assertThrowsJsUnitException(
    -      function() { assertNotNaN(Number.NaN); },
    -      'Expected not NaN');
    -  assertThrowsJsUnitException(
    -      function() { assertNotNaN('Should not be NaN', Number.NaN); },
    -      'Should not be NaN\nExpected not NaN');
    -}
    -
    -function testAssertObjectEquals() {
    -  var obj1 = [{'a': 'hello', 'b': 'world'}];
    -  var obj2 = [{'a': 'hello', 'c': 'dear', 'b' : 'world'}];
    -
    -  // Check with obj1 and obj2 as first and second arguments respectively.
    -  assertThrows('Objects should not be equal', function() {
    -    assertObjectEquals(obj1, obj2);
    -  });
    -
    -  // Check with obj1 and obj2 as second and first arguments respectively.
    -  assertThrows('Objects should not be equal', function() {
    -    assertObjectEquals(obj2, obj1);
    -  });
    -
    -  // Test if equal objects are considered equal.
    -  var obj3 = [{'b': 'world', 'a': 'hello'}];
    -  assertObjectEquals(obj1, obj3);
    -  assertObjectEquals(obj3, obj1);
    -
    -  // Test with a case where one of the members has an undefined value.
    -  var obj4 = [{'a': 'hello', 'b': undefined}];
    -  var obj5 = [{'a': 'hello'}];
    -
    -  // Check with obj4 and obj5 as first and second arguments respectively.
    -  assertThrows('Objects should not be equal', function() {
    -    assertObjectEquals(obj4, obj5);
    -  });
    -
    -  // Check with obj5 and obj4 as first and second arguments respectively.
    -  assertThrows('Objects should not be equal', function() {
    -    assertObjectEquals(obj5, obj4);
    -  });
    -}
    -
    -function testAssertObjectNotEquals() {
    -  var obj1 = [{'a': 'hello', 'b': 'world'}];
    -  var obj2 = [{'a': 'hello', 'c': 'dear', 'b' : 'world'}];
    -
    -  // Check with obj1 and obj2 as first and second arguments respectively.
    -  assertObjectNotEquals(obj1, obj2);
    -
    -  // Check with obj1 and obj2 as second and first arguments respectively.
    -  assertObjectNotEquals(obj2, obj1);
    -
    -  // Test if equal objects are considered equal.
    -  var obj3 = [{'b': 'world', 'a': 'hello'}];
    -  var error = assertThrows('Objects should be equal', function() {
    -    assertObjectNotEquals(obj1, obj3);
    -  });
    -  assertContains('Objects should not be equal', error.message);
    -  error = assertThrows('Objects should be equal', function() {
    -    assertObjectNotEquals(obj3, obj1);
    -  });
    -  assertContains('Objects should not be equal', error.message);
    -
    -  // Test with a case where one of the members has an undefined value.
    -  var obj4 = [{'a': 'hello', 'b': undefined}];
    -  var obj5 = [{'a': 'hello'}];
    -
    -  // Check with obj4 and obj5 as first and second arguments respectively.
    -  assertObjectNotEquals(obj4, obj5);
    -
    -  // Check with obj5 and obj4 as first and second arguments respectively.
    -  assertObjectNotEquals(obj5, obj4);
    -}
    -
    -function testAssertObjectEquals2() {
    -  // NOTE: (0 in [undefined]) is true on FF but false on IE.
    -  // (0 in {'0': undefined}) is true on both.
    -  // grrr.
    -  assertObjectEquals('arrays should be equal', [undefined], [undefined]);
    -  assertThrows('arrays should not be equal', function() {
    -    assertObjectEquals([undefined, undefined], [undefined]);
    -  });
    -  assertThrows('arrays should not be equal', function() {
    -    assertObjectEquals([undefined], [undefined, undefined]);
    -  });
    -}
    -
    -function testAssertObjectEquals3() {
    -  // Check that objects that contain identical Map objects compare
    -  // as equals. We can't do a negative test because on browsers that
    -  // implement __iterator__ we can't check the values of the iterated
    -  // properties.
    -  var obj1 = [{'a': 'hi',
    -               'b': new goog.structs.Map('hola', 'amigo',
    -                                         'como', 'estas?')},
    -              14,
    -              'yes',
    -              true];
    -  var obj2 = [{'a': 'hi',
    -               'b': new goog.structs.Map('hola', 'amigo',
    -                                         'como', 'estas?')},
    -              14,
    -              'yes',
    -              true];
    -  assertObjectEquals('Objects should be equal', obj1, obj2);
    -
    -  var obj3 = {'a': [1, 2]};
    -  var obj4 = {'a': [1, 2, 3]};
    -  assertThrows('inner arrays should not be equal', function() {
    -    assertObjectEquals(obj3, obj4);
    -  });
    -  assertThrows('inner arrays should not be equal', function() {
    -    assertObjectEquals(obj4, obj3);
    -  });
    -}
    -
    -function testAssertObjectEqualsSet() {
    -  // verify that Sets compare equal, when run in an environment that
    -  // supports iterators
    -  var set1 = new goog.structs.Set();
    -  var set2 = new goog.structs.Set();
    -
    -  set1.add('a');
    -  set1.add('b');
    -  set1.add(13);
    -
    -  set2.add('a');
    -  set2.add('b');
    -  set2.add(13);
    -
    -  assertObjectEquals('sets should be equal', set1, set2);
    -
    -  set2.add('hey');
    -  assertThrows('sets should not be equal', function() {
    -    assertObjectEquals(set1, set2);
    -  });
    -}
    -
    -function testAssertObjectEqualsIterNoEquals() {
    -  // an object with an iterator but no equals() and no map_ cannot
    -  // be compared
    -  function Thing() {
    -    this.what = [];
    -  }
    -  Thing.prototype.add = function(n, v) {
    -    this.what.push(n + '@' + v);
    -  };
    -  Thing.prototype.get = function(n) {
    -    var m = new RegExp('^' + n + '@(.*)$', '');
    -    for (var i = 0; i < this.what.length; ++i) {
    -      var match = this.what[i].match(m);
    -      if (match) {
    -        return match[1];
    -      }
    -    }
    -    return null;
    -  };
    -  Thing.prototype.__iterator__ = function() {
    -    var iter = new goog.iter.Iterator;
    -    iter.index = 0;
    -    iter.thing = this;
    -    iter.next = function() {
    -      if (this.index < this.thing.what.length) {
    -        return this.thing.what[this.index++].split('@')[0];
    -      } else {
    -        throw goog.iter.StopIteration;
    -      }
    -    };
    -    return iter;
    -  };
    -
    -  var thing1 = new Thing(); thing1.name = 'thing1';
    -  var thing2 = new Thing(); thing2.name = 'thing2';
    -  thing1.add('red', 'fish');
    -  thing1.add('blue', 'fish');
    -
    -  thing2.add('red', 'fish');
    -  thing2.add('blue', 'fish');
    -
    -  assertThrows('things should not be equal', function() {
    -    assertObjectEquals(thing1, thing2);
    -  });
    -}
    -
    -function testAssertObjectEqualsWithDates() {
    -  var date = new Date(2010, 0, 1);
    -  var dateWithMilliseconds = new Date(2010, 0, 1, 0, 0, 0, 1);
    -  assertObjectEquals(new Date(2010, 0, 1), date);
    -  assertThrows(goog.partial(assertObjectEquals, date, dateWithMilliseconds));
    -}
    -
    -function testAssertObjectEqualsSparseArrays() {
    -  var arr1 = [, 2,, 4];
    -  var arr2 = [1, 2, 3, 4, 5];
    -
    -  assertThrows('Sparse arrays should not be equal', function() {
    -    assertObjectEquals(arr1, arr2);
    -  });
    -
    -  assertThrows('Sparse arrays should not be equal', function() {
    -    assertObjectEquals(arr2, arr1);
    -  });
    -}
    -
    -function testAssertObjectEqualsSparseArrays2() {
    -  // On IE6-8, the expression "1 in [4,undefined]" evaluates to false,
    -  // but true on other browsers. FML. This test verifies a regression
    -  // where IE reported that arr4 was not equal to arr1 or arr2.
    -  var arr1 = [1,, 3];
    -  var arr2 = [1, undefined, 3];
    -  var arr3 = goog.array.clone(arr1);
    -  var arr4 = [];
    -  arr4.push(1, undefined, 3);
    -
    -  // Assert that all those arrays are equivalent pairwise.
    -  var arrays = [arr1, arr2, arr3, arr4];
    -  for (var i = 0; i < arrays.length; i++) {
    -    for (var j = 0; j < arrays.length; j++) {
    -      assertArrayEquals(arrays[i], arrays[j]);
    -    }
    -  }
    -}
    -
    -function testAssertObjectEqualsArraysWithExtraProps() {
    -  var arr1 = [1];
    -  var arr2 = [1];
    -  arr2.foo = 3;
    -
    -  assertThrows('Aarrays should not be equal', function() {
    -    assertObjectEquals(arr1, arr2);
    -  });
    -
    -  assertThrows('Arrays should not be equal', function() {
    -    assertObjectEquals(arr2, arr1);
    -  });
    -}
    -
    -function testAssertSameElementsOnArray() {
    -  assertSameElements([1, 2], [2, 1]);
    -  assertSameElements('Good assertion', [1, 2], [2, 1]);
    -  assertSameElements('Good assertion with duplicates', [1, 1, 2], [2, 1, 1]);
    -  assertThrowsJsUnitException(
    -      function() {
    -        assertSameElements([1, 2], [1]);
    -      },
    -      'Expected 2 elements: [1,2], got 1 elements: [1]');
    -  assertThrowsJsUnitException(
    -      function() {
    -        assertSameElements('Should match', [1, 2], [1]);
    -      },
    -      'Should match\nExpected 2 elements: [1,2], got 1 elements: [1]');
    -  assertThrowsJsUnitException(
    -      function() {
    -        assertSameElements([1, 2], [1, 3]);
    -      },
    -      'Expected [1,2], got [1,3]');
    -  assertThrowsJsUnitException(
    -      function() {
    -        assertSameElements('Should match', [1, 2], [1, 3]);
    -      },
    -      'Should match\nExpected [1,2], got [1,3]');
    -  assertThrowsJsUnitException(
    -      function() {
    -        assertSameElements([1, 1, 2], [2, 2, 1]);
    -      },
    -      'Expected [1,1,2], got [2,2,1]');
    -}
    -
    -function testAssertSameElementsOnArrayLike() {
    -  assertSameElements({0: 0, 1: 1, length: 2}, {length: 2, 1: 1, 0: 0});
    -  assertThrowsJsUnitException(
    -      function() {
    -        assertSameElements({0: 0, 1: 1, length: 2}, {0: 0, length: 1});
    -      },
    -      'Expected 2 elements: [0,1], got 1 elements: [0]');
    -}
    -
    -function testAssertSameElementsWithBadArguments() {
    -  assertThrowsJsUnitException(
    -      function() {
    -        assertSameElements([], new goog.structs.Set());
    -      },
    -      'Bad arguments to assertSameElements(opt_message, expected: ' +
    -      'ArrayLike, actual: ArrayLike)\n' +
    -      'Call to assertTrue(boolean) with false');
    -}
    -
    -var implicitlyTrue = [
    -  true,
    -  1,
    -  -1,
    -  ' ',
    -  'string',
    -  Infinity,
    -  new Object()
    -];
    -
    -var implicitlyFalse = [
    -  false,
    -  0,
    -  '',
    -  null,
    -  undefined,
    -  NaN
    -];
    -
    -function testAssertEvaluatesToTrue() {
    -  assertEvaluatesToTrue(true);
    -  assertEvaluatesToTrue('', true);
    -  assertEvaluatesToTrue('Good assertion', true);
    -  assertThrowsJsUnitException(
    -      function() { assertEvaluatesToTrue(false); },
    -      'Expected to evaluate to true');
    -  assertThrowsJsUnitException(
    -      function() {assertEvaluatesToTrue('Should be true', false); },
    -      'Should be true\nExpected to evaluate to true');
    -  for (var i = 0; i < implicitlyTrue.length; i++) {
    -    assertEvaluatesToTrue(String('Test ' + implicitlyTrue[i] +
    -        ' [' + i + ']'), implicitlyTrue[i]);
    -  }
    -  for (var i = 0; i < implicitlyFalse.length; i++) {
    -    assertThrowsJsUnitException(
    -        function() { assertEvaluatesToTrue(implicitlyFalse[i]); },
    -        'Expected to evaluate to true');
    -  }
    -}
    -
    -function testAssertEvaluatesToFalse() {
    -  assertEvaluatesToFalse(false);
    -  assertEvaluatesToFalse('Good assertion', false);
    -  assertThrowsJsUnitException(
    -      function() { assertEvaluatesToFalse(true); },
    -      'Expected to evaluate to false');
    -  assertThrowsJsUnitException(
    -      function() { assertEvaluatesToFalse('Should be false', true); },
    -      'Should be false\nExpected to evaluate to false');
    -  for (var i = 0; i < implicitlyFalse.length; i++) {
    -    assertEvaluatesToFalse(String('Test ' + implicitlyFalse[i] +
    -        ' [' + i + ']'), implicitlyFalse[i]);
    -  }
    -  for (var i = 0; i < implicitlyTrue.length; i++) {
    -    assertThrowsJsUnitException(
    -        function() { assertEvaluatesToFalse(implicitlyTrue[i]); },
    -        'Expected to evaluate to false');
    -  }
    -}
    -
    -function testAssertHTMLEquals() {
    -  // TODO
    -}
    -
    -function testAssertHashEquals() {
    -  assertHashEquals({a: 1, b: 2}, {b: 2, a: 1});
    -  assertHashEquals('Good assertion', {a: 1, b: 2}, {b: 2, a: 1});
    -  assertHashEquals({a: undefined}, {a: undefined});
    -  // Missing key.
    -  assertThrowsJsUnitException(
    -      function() { assertHashEquals({a: 1, b: 2}, {a: 1}); },
    -      'Expected hash had key b that was not found');
    -  assertThrowsJsUnitException(
    -      function() { assertHashEquals('Should match', {a: 1, b: 2}, {a: 1}); },
    -      'Should match\nExpected hash had key b that was not found');
    -  assertThrowsJsUnitException(
    -      function() { assertHashEquals({a: undefined}, {}); },
    -      'Expected hash had key a that was not found');
    -  // Not equal key.
    -  assertThrowsJsUnitException(
    -      function() { assertHashEquals({a: 1}, {a: 5}); },
    -      'Value for key a mismatch - expected = 1, actual = 5');
    -  assertThrowsJsUnitException(
    -      function() { assertHashEquals('Should match', {a: 1}, {a: 5}); },
    -      'Should match\nValue for key a mismatch - expected = 1, actual = 5');
    -  assertThrowsJsUnitException(
    -      function() { assertHashEquals({a: undefined}, {a: 1})},
    -      'Value for key a mismatch - expected = undefined, actual = 1');
    -  // Extra key.
    -  assertThrowsJsUnitException(
    -      function() { assertHashEquals({a: 1}, {a: 1, b: 1}); },
    -      'Actual hash had key b that was not expected');
    -  assertThrowsJsUnitException(
    -      function() { assertHashEquals('Should match', {a: 1}, {a: 1, b: 1}); },
    -      'Should match\nActual hash had key b that was not expected');
    -}
    -
    -function testAssertRoughlyEquals() {
    -  assertRoughlyEquals(1, 1, 0);
    -  assertRoughlyEquals('Good assertion', 1, 1, 0);
    -  assertRoughlyEquals(1, 1.1, 0.11);
    -  assertRoughlyEquals(1.1, 1, 0.11);
    -  assertThrowsJsUnitException(
    -      function() { assertRoughlyEquals(1, 1.1, 0.05); },
    -      'Expected 1, but got 1.1 which was more than 0.05 away');
    -  assertThrowsJsUnitException(
    -      function() { assertRoughlyEquals('Close enough', 1, 1.1, 0.05); },
    -      'Close enough\nExpected 1, but got 1.1 which was more than 0.05 away');
    -}
    -
    -function testAssertContains() {
    -  var a = [1, 2, 3];
    -  assertContains(1, [1, 2, 3]);
    -  assertContains('Should contain', 1, [1, 2, 3]);
    -  assertThrowsJsUnitException(
    -      function() { assertContains(4, [1, 2, 3]); },
    -      'Expected \'1,2,3\' to contain \'4\'');
    -  assertThrowsJsUnitException(
    -      function() { assertContains('Should contain', 4, [1, 2, 3]); },
    -      'Should contain\nExpected \'1,2,3\' to contain \'4\'');
    -  // assertContains uses ===.
    -  var o = new Object();
    -  assertContains(o, [o, 2, 3]);
    -  assertThrowsJsUnitException(
    -      function() { assertContains(o, [1, 2, 3]); },
    -      'Expected \'1,2,3\' to contain \'[object Object]\'');
    -}
    -
    -function testAssertNotContains() {
    -  var a = [1, 2, 3];
    -  assertNotContains(4, [1, 2, 3]);
    -  assertNotContains('Should not contain', 4, [1, 2, 3]);
    -  assertThrowsJsUnitException(
    -      function() { assertNotContains(1, [1, 2, 3]); },
    -      'Expected \'1,2,3\' not to contain \'1\'');
    -  assertThrowsJsUnitException(
    -      function() { assertNotContains('Should not contain', 1, [1, 2, 3]); },
    -      "Should not contain\nExpected '1,2,3' not to contain '1'");
    -  // assertNotContains uses ===.
    -  var o = new Object();
    -  assertNotContains({}, [o, 2, 3]);
    -  assertThrowsJsUnitException(
    -      function() { assertNotContains(o, [o, 2, 3]); },
    -      'Expected \'[object Object],2,3\' not to contain \'[object Object]\'');
    -}
    -
    -function testAssertRegExp() {
    -  var a = 'I like turtles';
    -  assertRegExp(/turtles$/, a);
    -  assertRegExp('turtles$', a);
    -  assertRegExp('Expected subject to be about turtles', /turtles$/, a);
    -  assertRegExp('Expected subject to be about turtles', 'turtles$', a);
    -
    -  var b = 'Hello';
    -  assertThrowsJsUnitException(
    -      function() { assertRegExp(/turtles$/, b); },
    -      'Expected \'Hello\' to match RegExp /turtles$/');
    -  assertThrowsJsUnitException(
    -      function() { assertRegExp('turtles$', b); },
    -      'Expected \'Hello\' to match RegExp /turtles$/');
    -}
    -
    -function testAssertThrows() {
    -  var failed = false;
    -  try {
    -    assertThrows('assertThrows should not pass with null param', null);
    -    failed = true;
    -  } catch (e) {
    -  }
    -  assertFalse('Fail should not get set to true', failed);
    -
    -  try {
    -    assertThrows(
    -        'assertThrows should not pass with undefined param',
    -        undefined);
    -    failed = true;
    -  } catch (e) {
    -  }
    -  assertFalse('Fail should not get set to true', failed);
    -
    -  try {
    -    assertThrows('assertThrows should not pass with number param', 1);
    -    failed = true;
    -  } catch (e) {
    -  }
    -  assertFalse('Fail should not get set to true', failed);
    -
    -  try {
    -    assertThrows('assertThrows should not pass with string param', 'string');
    -    failed = true;
    -  } catch (e) {
    -  }
    -  assertFalse('Fail should not get set to true', failed);
    -
    -  try {
    -    assertThrows('assertThrows should not pass with object param', {});
    -    failed = true;
    -  } catch (e) {
    -  }
    -  assertFalse('Fail should not get set to true', failed);
    -
    -  try {
    -    var error = assertThrows('valid function throws Error', function() {
    -      throw new Error('test');
    -    });
    -  } catch (e) {
    -    fail('assertThrows incorrectly doesn\'t detect a thrown exception');
    -  }
    -  assertEquals('error message', 'test', error.message);
    -
    -  try {
    -    var stringError = assertThrows('valid function throws string error',
    -        function() {
    -          throw 'string error test';
    -        });
    -  } catch (e) {
    -    fail('assertThrows doesn\'t detect a thrown string exception');
    -  }
    -  assertEquals('string error', 'string error test', stringError);
    -}
    -
    -function testAssertNotThrows() {
    -  var failed = false;
    -  try {
    -    assertNotThrows('assertNotThrows should not pass with null param', null);
    -    failed = true;
    -  } catch (e) {
    -  }
    -  assertFalse('Fail should not get set to true', failed);
    -
    -  try {
    -    assertNotThrows(
    -        'assertNotThrows should not pass with undefined param', undefined);
    -    failed = true;
    -  } catch (e) {
    -  }
    -  assertFalse('Fail should not get set to true', failed);
    -
    -  try {
    -    assertNotThrows('assertNotThrows should not pass with number param', 1);
    -    failed = true;
    -  } catch (e) {
    -  }
    -  assertFalse('Fail should not get set to true', failed);
    -
    -  try {
    -    assertNotThrows('assertNotThrows should not pass with string param',
    -        'string');
    -    failed = true;
    -  } catch (e) {
    -  }
    -  assertFalse('Fail should not get set to true', failed);
    -
    -
    -  try {
    -    assertNotThrows('assertNotThrows should not pass with object param', {});
    -    failed = true;
    -  } catch (e) {
    -  }
    -  assertFalse('Fail should not get set to true', failed);
    -
    -
    -  var result;
    -  try {
    -    result = assertNotThrows('valid function',
    -        function() {
    -          return 'some value';
    -        });
    -  } catch (e) {
    -    // Shouldn't be here: throw exception.
    -    fail('assertNotThrows returned failure on a valid function');
    -  }
    -  assertEquals('assertNotThrows should return the result of the function.',
    -      'some value', result);
    -
    -  var errorDescription = 'a test error exception';
    -  try {
    -    assertNotThrows('non valid error throwing function',
    -        function() {
    -          throw new Error(errorDescription);
    -        });
    -    failed = true;
    -  } catch (e) {
    -    // Some browsers don't have a stack trace so expect to at least have the
    -    // error description. For Gecko and IE7 not even that is included.
    -    if (!goog.userAgent.GECKO &&
    -        (!goog.userAgent.IE || goog.userAgent.isVersionOrHigher('8'))) {
    -      assertContains(errorDescription, e.message);
    -    }
    -  }
    -  assertFalse('assertNotThrows did not fail on a thrown exception', failed);
    -}
    -
    -function testAssertArrayEquals() {
    -  var a1 = [0, 1, 2];
    -  var a2 = [0, 1, 2];
    -  assertArrayEquals('Arrays should be equal', a1, a2);
    -
    -  assertThrows('Should have thrown because args are not arrays', function() {
    -    assertArrayEquals(true, true);
    -  });
    -
    -  a1 = [0, undefined, 2];
    -  a2 = [0, , 2];
    -  // The following test fails unexpectedly. The bug is tracked at
    -  // http://code.google.com/p/closure-library/issues/detail?id=419
    -  // assertThrows(
    -  //     'assertArrayEquals distinguishes undefined items from sparse arrays',
    -  //     function() {
    -  //       assertArrayEquals(a1, a2);
    -  //     });
    -
    -  // For the record. This behavior will probably change in the future.
    -  assertArrayEquals(
    -      'Bug: sparse arrays and undefined items are not distinguished',
    -      [0, undefined, 2], [0, , 2]);
    -
    -  assertThrows('The array elements should be compared with ===', function() {
    -    assertArrayEquals([0], ['0']);
    -  });
    -
    -  assertThrows('Arrays with different length should be different',
    -      function() {
    -        assertArrayEquals([0, undefined], [0]);
    -      });
    -
    -  a1 = [0];
    -  a2 = [0];
    -  a2[-1] = -1;
    -  assertArrayEquals('Negative indexes are ignored', a1, a2);
    -
    -  a1 = [0];
    -  a2 = [0];
    -  a2['extra'] = 1;
    -  assertArrayEquals(
    -      'Extra properties are ignored. Use assertObjectEquals to compare them.',
    -      a1, a2);
    -
    -  assertArrayEquals('An example where assertObjectEquals would fail in IE.',
    -      ['x'], 'x'.match(/x/g));
    -}
    -
    -function testAssertObjectsEqualsDifferentArrays() {
    -  assertThrows('Should have thrown because args are different', function() {
    -    var a1 = ['className1'];
    -    var a2 = ['className2'];
    -    assertObjectEquals(a1, a2);
    -  });
    -}
    -
    -function testAssertObjectsEqualsNegativeArrayIndexes() {
    -  var a1 = [0];
    -  var a2 = [0];
    -  a2[-1] = -1;
    -  // The following test fails unexpectedly. The bug is tracked at
    -  // http://code.google.com/p/closure-library/issues/detail?id=418
    -  // assertThrows('assertObjectEquals compares negative indexes', function() {
    -  //   assertObjectEquals(a1, a2);
    -  // });
    -}
    -
    -function testAssertObjectsEqualsDifferentTypeSameToString() {
    -  assertThrows('Should have thrown because args are different', function() {
    -    var a1 = 'className1';
    -    var a2 = ['className1'];
    -    assertObjectEquals(a1, a2);
    -  });
    -
    -  assertThrows('Should have thrown because args are different', function() {
    -    var a1 = ['className1'];
    -    var a2 = {'0': 'className1'};
    -    assertObjectEquals(a1, a2);
    -  });
    -
    -  assertThrows('Should have thrown because args are different', function() {
    -    var a1 = ['className1'];
    -    var a2 = [['className1']];
    -    assertObjectEquals(a1, a2);
    -  });
    -}
    -
    -function testAssertObjectsRoughlyEquals() {
    -  assertObjectRoughlyEquals({'a': 1}, {'a': 1.2}, 0.3);
    -  assertThrowsJsUnitException(
    -      function() { assertObjectRoughlyEquals({'a': 1}, {'a': 1.2}, 0.1); },
    -      'Expected <[object Object]> (Object) but was <[object Object]> ' +
    -      '(Object)\n   a: Expected <1> (Number) but was <1.2> (Number) which ' +
    -      'was more than 0.1 away');
    -}
    -
    -function testFindDifferences_equal() {
    -  assertNull(goog.testing.asserts.findDifferences(true, true));
    -  assertNull(goog.testing.asserts.findDifferences(null, null));
    -  assertNull(goog.testing.asserts.findDifferences(undefined, undefined));
    -  assertNull(goog.testing.asserts.findDifferences(1, 1));
    -  assertNull(goog.testing.asserts.findDifferences([1, 'a'], [1, 'a']));
    -  assertNull(goog.testing.asserts.findDifferences(
    -      [[1, 2], [3, 4]], [[1, 2], [3, 4]]));
    -  assertNull(goog.testing.asserts.findDifferences(
    -      [{a: 1, b: 2}], [{b: 2, a: 1}]));
    -  assertNull(goog.testing.asserts.findDifferences(null, null));
    -  assertNull(goog.testing.asserts.findDifferences(undefined, undefined));
    -}
    -
    -function testFindDifferences_unequal() {
    -  assertNotNull(goog.testing.asserts.findDifferences(true, false));
    -  assertNotNull(goog.testing.asserts.findDifferences(
    -      [{a: 1, b: 2}], [{a: 2, b: 1}]));
    -  assertNotNull(goog.testing.asserts.findDifferences(
    -      [{a: 1}], [{a: 1, b: [2]}]));
    -  assertNotNull(goog.testing.asserts.findDifferences(
    -      [{a: 1, b: [2]}], [{a: 1}]));
    -}
    -
    -function testFindDifferences_objectsAndNull() {
    -  assertNotNull(goog.testing.asserts.findDifferences({a: 1}, null));
    -  assertNotNull(goog.testing.asserts.findDifferences(null, {a: 1}));
    -  assertNotNull(goog.testing.asserts.findDifferences(null, []));
    -  assertNotNull(goog.testing.asserts.findDifferences([], null));
    -  assertNotNull(goog.testing.asserts.findDifferences([], undefined));
    -}
    -
    -function testFindDifferences_basicCycle() {
    -  var a = {};
    -  var b = {};
    -  a.self = a;
    -  b.self = b;
    -  assertNull(goog.testing.asserts.findDifferences(a, b));
    -
    -  a.unique = 1;
    -  assertNotNull(goog.testing.asserts.findDifferences(a, b));
    -}
    -
    -function testFindDifferences_crossedCycle() {
    -  var a = {};
    -  var b = {};
    -  a.self = b;
    -  b.self = a;
    -  assertNull(goog.testing.asserts.findDifferences(a, b));
    -
    -  a.unique = 1;
    -  assertNotNull(goog.testing.asserts.findDifferences(a, b));
    -}
    -
    -function testFindDifferences_asymmetricCycle() {
    -  var a = {};
    -  var b = {};
    -  var c = {};
    -  var d = {};
    -  var e = {};
    -  a.self = b;
    -  b.self = a;
    -  c.self = d;
    -  d.self = e;
    -  e.self = c;
    -  assertNotNull(goog.testing.asserts.findDifferences(a, c));
    -}
    -
    -function testFindDifferences_basicCycleArray() {
    -  var a = [];
    -  var b = [];
    -  a[0] = a;
    -  b[0] = b;
    -  assertNull(goog.testing.asserts.findDifferences(a, b));
    -
    -  a[1] = 1;
    -  assertNotNull(goog.testing.asserts.findDifferences(a, b));
    -}
    -
    -function testFindDifferences_crossedCycleArray() {
    -  var a = [];
    -  var b = [];
    -  a[0] = b;
    -  b[0] = a;
    -  assertNull(goog.testing.asserts.findDifferences(a, b));
    -
    -  a[1] = 1;
    -  assertNotNull(goog.testing.asserts.findDifferences(a, b));
    -}
    -
    -function testFindDifferences_asymmetricCycleArray() {
    -  var a = [];
    -  var b = [];
    -  var c = [];
    -  var d = [];
    -  var e = [];
    -  a[0] = b;
    -  b[0] = a;
    -  c[0] = d;
    -  d[0] = e;
    -  e[0] = c;
    -  assertNotNull(goog.testing.asserts.findDifferences(a, c));
    -}
    -
    -function testFindDifferences_multiCycles() {
    -  var a = {};
    -  a.cycle1 = a;
    -  a.test = {
    -    cycle2: a
    -  };
    -
    -  var b = {};
    -  b.cycle1 = b;
    -  b.test = {
    -    cycle2: b
    -  };
    -  assertNull(goog.testing.asserts.findDifferences(a, b));
    -}
    -
    -function testFindDifferences_binaryTree() {
    -  function createBinTree(depth, root) {
    -    if (depth == 0) {
    -      return {root: root};
    -    } else {
    -      var node = {};
    -      node.left = createBinTree(depth - 1, root || node);
    -      node.right = createBinTree(depth - 1, root || node);
    -      return node;
    -    }
    -  }
    -
    -  // TODO(gboyer,user): This test does not terminate with the current
    -  // algorithm. Can be enabled when (if) the algorithm is improved.
    -  //assertNull(goog.testing.asserts.findDifferences(
    -  //    createBinTree(5, null), createBinTree(5, null)));
    -  assertNotNull(goog.testing.asserts.findDifferences(
    -      createBinTree(4, null), createBinTree(5, null)));
    -}
    -
    -function testStringForWindowIE() {
    -  if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('8')) {
    -    // NOTE(user): This test sees of we are being affected by a JScript bug
    -    // in try/finally handling. This bug only affects the lowest try/finally
    -    // block in the stack. Calling this function via VBScript allows
    -    // us to run the test synchronously in an empty JS stack.
    -    window.execScript('stringForWindowIEHelper()', 'vbscript');
    -    assertEquals('<[object]> (Object)', window.stringForWindowIEResult);
    -  }
    -}
    -
    -function testStringSamePrefix() {
    -  assertThrowsJsUnitException(
    -      function() { assertEquals('abcdefghi', 'abcdefghx'); },
    -      'Expected <abcdefghi> (String) but was <abcdefghx> (String)\n' +
    -      'Difference was at position 8. Expected [...ghi] vs. actual [...ghx]');
    -}
    -
    -function testStringSameSuffix() {
    -  assertThrowsJsUnitException(
    -      function() { assertEquals('xbcdefghi', 'abcdefghi'); },
    -      'Expected <xbcdefghi> (String) but was <abcdefghi> (String)\n' +
    -      'Difference was at position 0. Expected [xbc...] vs. actual [abc...]');
    -}
    -
    -function testStringDissimilarShort() {
    -  assertThrowsJsUnitException(
    -      function() { assertEquals('x', 'y'); },
    -      'Expected <x> (String) but was <y> (String)');
    -}
    -
    -function testStringDissimilarLong() {
    -  assertThrowsJsUnitException(
    -      function() { assertEquals('xxxxxxxxxx', 'yyyyyyyyyy'); },
    -      'Expected <xxxxxxxxxx> (String) but was <yyyyyyyyyy> (String)');
    -}
    -
    -function testAssertElementsEquals() {
    -  assertElementsEquals([1, 2], [1, 2]);
    -  assertElementsEquals([1, 2], {0: 1, 1: 2, length: 2});
    -  assertElementsEquals('Good assertion', [1, 2], [1, 2]);
    -  assertThrowsJsUnitException(
    -      function() {
    -        assertElementsEquals('Message', [1, 2], [1]);
    -      },
    -      'length mismatch: Message\n' +
    -      'Expected <2> (Number) but was <1> (Number)');
    -}
    -
    -function testStackTrace() {
    -  try {
    -    assertTrue(false);
    -  } catch (e) {
    -    if (Error.captureStackTrace) {
    -      assertNotUndefined(e.stack);
    -    }
    -    if (e.stack) {
    -      var stack = e.stack;
    -      var stackTraceContainsTestName = goog.string.contains(
    -          stack, 'testStackTrace');
    -      if (!stackTraceContainsTestName &&
    -          goog.labs.userAgent.browser.isChrome()) {
    -        // Occasionally Chrome does not give us a full stack trace, making for
    -        // a flaky test. If we don't have the full stack trace, at least
    -        // check that we got the error string.
    -        // Filed a bug on Chromium here:
    -        // https://code.google.com/p/chromium/issues/detail?id=403029
    -        var expected = 'Call to assertTrue(boolean) with false';
    -        assertContains(expected, stack);
    -        return;
    -      }
    -
    -      assertTrue('Expected the stack trace to contain string "testStackTrace"',
    -                 stackTraceContainsTestName);
    -    }
    -  }
    -}
    -
    -function stringForWindowIEHelper() {
    -  window.stringForWindowIEResult = _displayStringForValue(window);
    -}
    -
    -function testDisplayStringForValue() {
    -  assertEquals('<hello> (String)', _displayStringForValue('hello'));
    -  assertEquals('<1> (Number)', _displayStringForValue(1));
    -  assertEquals('<null>', _displayStringForValue(null));
    -  assertEquals('<undefined>', _displayStringForValue(undefined));
    -  assertEquals('<hello,,,,1> (Array)', _displayStringForValue(
    -      ['hello', /* array hole */, undefined, null, 1]));
    -}
    -
    -function testDisplayStringForValue_exception() {
    -  assertEquals('<toString failed: foo message> (Object)',
    -      _displayStringForValue({toString: function() {
    -        throw Error('foo message');
    -      }}));
    -}
    -
    -function testDisplayStringForValue_cycle() {
    -  var cycle = ['cycle'];
    -  cycle.push(cycle);
    -  assertTrue(
    -      'Computing string should terminate and result in a reasonable length',
    -      _displayStringForValue(cycle).length < 1000);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/async/mockcontrol.js b/src/database/third_party/closure-library/closure/goog/testing/async/mockcontrol.js
    deleted file mode 100644
    index d85cfac08b5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/async/mockcontrol.js
    +++ /dev/null
    @@ -1,175 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A wrapper for MockControl that provides mocks and assertions
    - * for testing asynchronous code. All assertions will only be verified when
    - * $verifyAll is called on the wrapped MockControl.
    - *
    - * This class is meant primarily for testing code that exposes asynchronous APIs
    - * without being truly asynchronous (using asynchronous primitives like browser
    - * events or timeouts). This is often the case when true asynchronous
    - * depedencies have been mocked out. This means that it doesn't rely on
    - * AsyncTestCase or DeferredTestCase, although it can be used with those as
    - * well.
    - *
    - * Example usage:
    - *
    - * <pre>
    - * var mockControl = new goog.testing.MockControl();
    - * var asyncMockControl = new goog.testing.async.MockControl(mockControl);
    - *
    - * myAsyncObject.onSuccess(asyncMockControl.asyncAssertEquals(
    - *     'callback should run and pass the correct value',
    - *     'http://someurl.com');
    - * asyncMockControl.assertDeferredEquals(
    - *     'deferred object should be resolved with the correct value',
    - *     'http://someurl.com',
    - *     myAsyncObject.getDeferredUrl());
    - * asyncMockControl.run();
    - * mockControl.$verifyAll();
    - * </pre>
    - *
    - */
    -
    -
    -goog.provide('goog.testing.async.MockControl');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.async.Deferred');
    -goog.require('goog.debug');
    -goog.require('goog.testing.asserts');
    -goog.require('goog.testing.mockmatchers.IgnoreArgument');
    -
    -
    -
    -/**
    - * Provides asynchronous mocks and assertions controlled by a parent
    - * MockControl.
    - *
    - * @param {goog.testing.MockControl} mockControl The parent MockControl.
    - * @constructor
    - * @final
    - */
    -goog.testing.async.MockControl = function(mockControl) {
    -  /**
    -   * The parent MockControl.
    -   * @type {goog.testing.MockControl}
    -   * @private
    -   */
    -  this.mockControl_ = mockControl;
    -};
    -
    -
    -/**
    - * Returns a function that will assert that it will be called, and run the given
    - * callback when it is.
    - *
    - * @param {string} name The name of the callback mock.
    - * @param {function(...*) : *} callback The wrapped callback. This will be
    - *     called when the returned function is called.
    - * @param {Object=} opt_selfObj The object which this should point to when the
    - *     callback is run.
    - * @return {!Function} The mock callback.
    - * @suppress {missingProperties} Mocks do not fit in the type system well.
    - */
    -goog.testing.async.MockControl.prototype.createCallbackMock = function(
    -    name, callback, opt_selfObj) {
    -  goog.asserts.assert(
    -      goog.isString(name),
    -      'name parameter ' + goog.debug.deepExpose(name) + ' should be a string');
    -
    -  var ignored = new goog.testing.mockmatchers.IgnoreArgument();
    -
    -  // Use everyone's favorite "double-cast" trick to subvert the type system.
    -  var obj = /** @type {Object} */ (this.mockControl_.createFunctionMock(name));
    -  var fn = /** @type {Function} */ (obj);
    -
    -  fn(ignored).$does(function(args) {
    -    if (opt_selfObj) {
    -      callback = goog.bind(callback, opt_selfObj);
    -    }
    -    return callback.apply(this, args);
    -  });
    -  fn.$replay();
    -  return function() { return fn(arguments); };
    -};
    -
    -
    -/**
    - * Returns a function that will assert that its arguments are equal to the
    - * arguments given to asyncAssertEquals. In addition, the function also asserts
    - * that it will be called.
    - *
    - * @param {string} message A message to print if the arguments are wrong.
    - * @param {...*} var_args The arguments to assert.
    - * @return {function(...*) : void} The mock callback.
    - */
    -goog.testing.async.MockControl.prototype.asyncAssertEquals = function(
    -    message, var_args) {
    -  var expectedArgs = Array.prototype.slice.call(arguments, 1);
    -  return this.createCallbackMock('asyncAssertEquals', function() {
    -    assertObjectEquals(
    -        message, expectedArgs, Array.prototype.slice.call(arguments));
    -  });
    -};
    -
    -
    -/**
    - * Asserts that a deferred object will have an error and call its errback
    - * function.
    - * @param {goog.async.Deferred} deferred The deferred object.
    - * @param {function() : void} fn A function wrapping the code in which the error
    - *     will occur.
    - */
    -goog.testing.async.MockControl.prototype.assertDeferredError = function(
    -    deferred, fn) {
    -  deferred.addErrback(this.createCallbackMock(
    -      'assertDeferredError', function() {}));
    -  goog.testing.asserts.callWithoutLogging(fn);
    -};
    -
    -
    -/**
    - * Asserts that a deferred object will call its callback with the given value.
    - *
    - * @param {string} message A message to print if the arguments are wrong.
    - * @param {goog.async.Deferred|*} expected The expected value. If this is a
    - *     deferred object, then the expected value is the deferred value.
    - * @param {goog.async.Deferred|*} actual The actual value. If this is a deferred
    - *     object, then the actual value is the deferred value. Either this or
    - *     'expected' must be deferred.
    - */
    -goog.testing.async.MockControl.prototype.assertDeferredEquals = function(
    -    message, expected, actual) {
    -  if (expected instanceof goog.async.Deferred &&
    -      actual instanceof goog.async.Deferred) {
    -    // Assert that the first deferred is resolved.
    -    expected.addCallback(this.createCallbackMock(
    -        'assertDeferredEquals', function(exp) {
    -          // Assert that the second deferred is resolved, and that the value is
    -          // as expected.
    -          actual.addCallback(this.asyncAssertEquals(message, exp));
    -        }, this));
    -  } else if (expected instanceof goog.async.Deferred) {
    -    expected.addCallback(this.createCallbackMock(
    -        'assertDeferredEquals', function(exp) {
    -          assertObjectEquals(message, exp, actual);
    -        }));
    -  } else if (actual instanceof goog.async.Deferred) {
    -    actual.addCallback(this.asyncAssertEquals(message, expected));
    -  } else {
    -    throw Error('Either expected or actual must be deferred');
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/async/mockcontrol_test.html b/src/database/third_party/closure-library/closure/goog/testing/async/mockcontrol_test.html
    deleted file mode 100644
    index 6467dc063c0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/async/mockcontrol_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.testing.async.MockControl;
    -  </title>
    -  <script type="text/javascript" src="../../base.js">
    -  </script>
    -  <script type="text/javascript">
    -    goog.require('goog.testing.async.MockControlTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/async/mockcontrol_test.js b/src/database/third_party/closure-library/closure/goog/testing/async/mockcontrol_test.js
    deleted file mode 100644
    index bb496005e4b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/async/mockcontrol_test.js
    +++ /dev/null
    @@ -1,217 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.async.MockControlTest');
    -goog.setTestOnly('goog.testing.async.MockControlTest');
    -
    -goog.require('goog.async.Deferred');
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.asserts');
    -goog.require('goog.testing.async.MockControl');
    -goog.require('goog.testing.jsunit');
    -
    -var mockControl;
    -var asyncMockControl;
    -
    -var mockControl2;
    -var asyncMockControl2;
    -
    -function setUp() {
    -  mockControl = new goog.testing.MockControl();
    -  asyncMockControl = new goog.testing.async.MockControl(mockControl);
    -
    -  // We need two of these for the tests where we need to verify our meta-test
    -  // assertions without verifying our tested assertions.
    -  mockControl2 = new goog.testing.MockControl();
    -  asyncMockControl2 = new goog.testing.async.MockControl(mockControl2);
    -}
    -
    -function assertVerifyFails() {
    -  assertThrowsJsUnitException(function() { mockControl.$verifyAll(); });
    -}
    -
    -function testCreateCallbackMockFailure() {
    -  asyncMockControl.createCallbackMock('failingCallbackMock', function() {});
    -  assertVerifyFails();
    -}
    -
    -function testCreateCallbackMockSuccess() {
    -  var callback = asyncMockControl.createCallbackMock(
    -      'succeedingCallbackMock', function() {});
    -  callback();
    -  mockControl.$verifyAll();
    -}
    -
    -function testCreateCallbackMockSuccessWithArg() {
    -  var callback = asyncMockControl.createCallbackMock(
    -      'succeedingCallbackMockWithArg',
    -      asyncMockControl.createCallbackMock(
    -          'metaCallbackMock',
    -          function(val) { assertEquals(10, val); }));
    -  callback(10);
    -  mockControl.$verifyAll();
    -}
    -
    -function testCreateCallbackMockSuccessWithArgs() {
    -  var callback = asyncMockControl.createCallbackMock(
    -      'succeedingCallbackMockWithArgs',
    -      asyncMockControl.createCallbackMock(
    -          'metaCallbackMock', function(val1, val2, val3) {
    -            assertEquals(10, val1);
    -            assertEquals('foo', val2);
    -            assertObjectEquals({foo: 'bar'}, val3);
    -          }));
    -  callback(10, 'foo', {foo: 'bar'});
    -  mockControl.$verifyAll();
    -}
    -
    -function testAsyncAssertEqualsFailureNeverCalled() {
    -  asyncMockControl.asyncAssertEquals('never called', 12);
    -  assertVerifyFails();
    -}
    -
    -function testAsyncAssertEqualsFailureNumberOfArgs() {
    -  assertThrowsJsUnitException(function() {
    -    asyncMockControl.asyncAssertEquals('wrong number of args', 12)();
    -  });
    -}
    -
    -function testAsyncAssertEqualsFailureOneArg() {
    -  assertThrowsJsUnitException(function() {
    -    asyncMockControl.asyncAssertEquals('wrong arg value', 12)(13);
    -  });
    -}
    -
    -function testAsyncAssertEqualsFailureThreeArgs() {
    -  assertThrowsJsUnitException(function() {
    -    asyncMockControl.asyncAssertEquals('wrong arg values', 1, 2, 15)(2, 2, 15);
    -  });
    -}
    -
    -function testAsyncAssertEqualsSuccessNoArgs() {
    -  asyncMockControl.asyncAssertEquals('should be called')();
    -  mockControl.$verifyAll();
    -}
    -
    -function testAsyncAssertEqualsSuccessThreeArgs() {
    -  asyncMockControl.asyncAssertEquals('should have args', 1, 2, 3)(1, 2, 3);
    -  mockControl.$verifyAll();
    -}
    -
    -function testAssertDeferredErrorFailureNoError() {
    -  var deferred = new goog.async.Deferred();
    -  asyncMockControl.assertDeferredError(deferred, function() {});
    -  assertVerifyFails();
    -}
    -
    -function testAssertDeferredErrorSuccess() {
    -  var deferred = new goog.async.Deferred();
    -  asyncMockControl.assertDeferredError(deferred, function() {
    -    deferred.errback(new Error('FAIL'));
    -  });
    -  mockControl.$verifyAll();
    -}
    -
    -function testAssertDeferredEqualsFailureActualDeferredNeverResolves() {
    -  var actual = new goog.async.Deferred();
    -  asyncMockControl.assertDeferredEquals('doesn\'t resolve', 12, actual);
    -  assertVerifyFails();
    -}
    -
    -function testAssertDeferredEqualsFailureActualDeferredNeverResolvesBoth() {
    -  var actualDeferred = new goog.async.Deferred();
    -  var expectedDeferred = new goog.async.Deferred();
    -  expectedDeferred.callback(12);
    -  asyncMockControl.assertDeferredEquals(
    -      'doesn\'t resolve', expectedDeferred, actualDeferred);
    -  assertVerifyFails();
    -}
    -
    -function testAssertDeferredEqualsFailureExpectedDeferredNeverResolves() {
    -  var expected = new goog.async.Deferred();
    -  asyncMockControl.assertDeferredEquals('doesn\'t resolve', expected, 12);
    -  assertVerifyFails();
    -}
    -
    -function testAssertDeferredEqualsFailureExpectedDeferredNeverResolvesBoth() {
    -  var actualDeferred = new goog.async.Deferred();
    -  var expectedDeferred = new goog.async.Deferred();
    -  actualDeferred.callback(12);
    -  asyncMockControl.assertDeferredEquals(
    -      'doesn\'t resolve', expectedDeferred, actualDeferred);
    -  assertVerifyFails();
    -}
    -
    -function testAssertDeferredEqualsFailureWrongValueActualDeferred() {
    -  var actual = new goog.async.Deferred();
    -  asyncMockControl.assertDeferredEquals('doesn\'t resolve', 12, actual);
    -  asyncMockControl2.assertDeferredError(actual, function() {
    -    actual.callback(13);
    -  });
    -  mockControl2.$verifyAll();
    -}
    -
    -function testAssertDeferredEqualsFailureWrongValueExpectedDeferred() {
    -  var expected = new goog.async.Deferred();
    -  asyncMockControl.assertDeferredEquals('doesn\'t resolve', expected, 12);
    -  asyncMockControl2.assertDeferredError(expected, function() {
    -    expected.callback(13);
    -  });
    -  mockControl2.$verifyAll();
    -}
    -
    -function testAssertDeferredEqualsFailureWongValueBothDeferred() {
    -  var actualDeferred = new goog.async.Deferred();
    -  var expectedDeferred = new goog.async.Deferred();
    -  asyncMockControl.assertDeferredEquals(
    -      'different values', expectedDeferred, actualDeferred);
    -  expectedDeferred.callback(12);
    -  asyncMockControl2.assertDeferredError(actualDeferred, function() {
    -    actualDeferred.callback(13);
    -  });
    -  assertVerifyFails();
    -  mockControl2.$verifyAll();
    -}
    -
    -function testAssertDeferredEqualsFailureNeitherDeferredEverResolves() {
    -  var actualDeferred = new goog.async.Deferred();
    -  var expectedDeferred = new goog.async.Deferred();
    -  asyncMockControl.assertDeferredEquals(
    -      'doesn\'t resolve', expectedDeferred, actualDeferred);
    -  assertVerifyFails();
    -}
    -
    -function testAssertDeferredEqualsSuccessActualDeferred() {
    -  var actual = new goog.async.Deferred();
    -  asyncMockControl.assertDeferredEquals('should succeed', 12, actual);
    -  actual.callback(12);
    -  mockControl.$verifyAll();
    -}
    -
    -function testAssertDeferredEqualsSuccessExpectedDeferred() {
    -  var expected = new goog.async.Deferred();
    -  asyncMockControl.assertDeferredEquals('should succeed', expected, 12);
    -  expected.callback(12);
    -  mockControl.$verifyAll();
    -}
    -
    -function testAssertDeferredEqualsSuccessBothDeferred() {
    -  var actualDeferred = new goog.async.Deferred();
    -  var expectedDeferred = new goog.async.Deferred();
    -  asyncMockControl.assertDeferredEquals(
    -      'should succeed', expectedDeferred, actualDeferred);
    -  expectedDeferred.callback(12);
    -  actualDeferred.callback(12);
    -  mockControl.$verifyAll();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/asynctestcase.js b/src/database/third_party/closure-library/closure/goog/testing/asynctestcase.js
    deleted file mode 100644
    index b915eddd592..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/asynctestcase.js
    +++ /dev/null
    @@ -1,900 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -// All Rights Reserved.
    -
    -/**
    - * @fileoverview A class representing a set of test functions that use
    - * asynchronous functions that cannot be meaningfully mocked.
    - *
    - * To create a Google-compatable JsUnit test using this test case, put the
    - * following snippet in your test:
    - *
    - *   var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall();
    - *
    - * To make the test runner wait for your asynchronous behaviour, use:
    - *
    - *   asyncTestCase.waitForAsync('Waiting for xhr to respond');
    - *
    - * The next test will not start until the following call is made, or a
    - * timeout occurs:
    - *
    - *   asyncTestCase.continueTesting();
    - *
    - * There does NOT need to be a 1:1 mapping of waitForAsync calls and
    - * continueTesting calls. The next test will be run after a single call to
    - * continueTesting is made, as long as there is no subsequent call to
    - * waitForAsync in the same thread.
    - *
    - * Example:
    - *   // Returning here would cause the next test to be run.
    - *   asyncTestCase.waitForAsync('description 1');
    - *   // Returning here would *not* cause the next test to be run.
    - *   // Only effect of additional waitForAsync() calls is an updated
    - *   // description in the case of a timeout.
    - *   asyncTestCase.waitForAsync('updated description');
    - *   asyncTestCase.continueTesting();
    - *   // Returning here would cause the next test to be run.
    - *   asyncTestCase.waitForAsync('just kidding, still running.');
    - *   // Returning here would *not* cause the next test to be run.
    - *
    - * The test runner can also be made to wait for more than one asynchronous
    - * event with:
    - *
    - *   asyncTestCase.waitForSignals(n);
    - *
    - * The next test will not start until asyncTestCase.signal() is called n times,
    - * or the test step timeout is exceeded.
    - *
    - * This class supports asynchronous behaviour in all test functions except for
    - * tearDownPage. If such support is needed, it can be added.
    - *
    - * Example Usage:
    - *
    - *   var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall();
    - *   // Optionally, set a longer-than-normal step timeout.
    - *   asyncTestCase.stepTimeout = 30 * 1000;
    - *
    - *   function testSetTimeout() {
    - *     var step = 0;
    - *     function stepCallback() {
    - *       step++;
    - *       switch (step) {
    - *         case 1:
    - *           var startTime = goog.now();
    - *           asyncTestCase.waitForAsync('step 1');
    - *           window.setTimeout(stepCallback, 100);
    - *           break;
    - *         case 2:
    - *           assertTrue('Timeout fired too soon',
    - *               goog.now() - startTime >= 100);
    - *           asyncTestCase.waitForAsync('step 2');
    - *           window.setTimeout(stepCallback, 100);
    - *           break;
    - *         case 3:
    - *           assertTrue('Timeout fired too soon',
    - *               goog.now() - startTime >= 200);
    - *           asyncTestCase.continueTesting();
    - *           break;
    - *         default:
    - *           fail('Unexpected call to stepCallback');
    - *       }
    - *     }
    - *     stepCallback();
    - *   }
    - *
    - * Known Issues:
    - *   IE7 Exceptions:
    - *     As the failingtest.html will show, it appears as though ie7 does not
    - *     propagate an exception past a function called using the func.call()
    - *     syntax. This causes case 3 of the failing tests (exceptions) to show up
    - *     as timeouts in IE.
    - *   window.onerror:
    - *     This seems to catch errors only in ff2/ff3. It does not work in Safari or
    - *     IE7. The consequence of this is that exceptions that would have been
    - *     caught by window.onerror show up as timeouts.
    - *
    - * @author agrieve@google.com (Andrew Grieve)
    - */
    -
    -goog.provide('goog.testing.AsyncTestCase');
    -goog.provide('goog.testing.AsyncTestCase.ControlBreakingException');
    -
    -goog.require('goog.testing.TestCase');
    -goog.require('goog.testing.asserts');
    -
    -
    -
    -/**
    - * A test case that is capable of running tests the contain asynchronous logic.
    - * @param {string=} opt_name A descriptive name for the test case.
    - * @extends {goog.testing.TestCase}
    - * @constructor
    - */
    -goog.testing.AsyncTestCase = function(opt_name) {
    -  goog.testing.TestCase.call(this, opt_name);
    -};
    -goog.inherits(goog.testing.AsyncTestCase, goog.testing.TestCase);
    -
    -
    -/**
    - * Represents result of top stack function call.
    - * @typedef {{controlBreakingExceptionThrown: boolean, message: string}}
    - * @private
    - */
    -goog.testing.AsyncTestCase.TopStackFuncResult_;
    -
    -
    -
    -/**
    - * An exception class used solely for control flow.
    - * @param {string=} opt_message Error message.
    - * @constructor
    - * @extends {Error}
    - * @final
    - */
    -goog.testing.AsyncTestCase.ControlBreakingException = function(opt_message) {
    -  goog.testing.AsyncTestCase.ControlBreakingException.base(
    -      this, 'constructor', opt_message);
    -
    -  /**
    -   * The exception message.
    -   * @type {string}
    -   */
    -  this.message = opt_message || '';
    -};
    -goog.inherits(goog.testing.AsyncTestCase.ControlBreakingException, Error);
    -
    -
    -/**
    - * Return value for .toString().
    - * @type {string}
    - */
    -goog.testing.AsyncTestCase.ControlBreakingException.TO_STRING =
    -    '[AsyncTestCase.ControlBreakingException]';
    -
    -
    -/**
    - * Marks this object as a ControlBreakingException
    - * @type {boolean}
    - */
    -goog.testing.AsyncTestCase.ControlBreakingException.prototype.
    -    isControlBreakingException = true;
    -
    -
    -/** @override */
    -goog.testing.AsyncTestCase.ControlBreakingException.prototype.toString =
    -    function() {
    -  // This shows up in the console when the exception is not caught.
    -  return goog.testing.AsyncTestCase.ControlBreakingException.TO_STRING;
    -};
    -
    -
    -/**
    - * How long to wait for a single step of a test to complete in milliseconds.
    - * A step starts when a call to waitForAsync() is made.
    - * @type {number}
    - */
    -goog.testing.AsyncTestCase.prototype.stepTimeout = 1000;
    -
    -
    -/**
    - * How long to wait after a failed test before moving onto the next one.
    - * The purpose of this is to allow any pending async callbacks from the failing
    - * test to finish up and not cause the next test to fail.
    - * @type {number}
    - */
    -goog.testing.AsyncTestCase.prototype.timeToSleepAfterFailure = 500;
    -
    -
    -/**
    - * Turn on extra logging to help debug failing async. tests.
    - * @type {boolean}
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.enableDebugLogs_ = false;
    -
    -
    -/**
    - * A reference to the original asserts.js assert_() function.
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.origAssert_;
    -
    -
    -/**
    - * A reference to the original asserts.js fail() function.
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.origFail_;
    -
    -
    -/**
    - * A reference to the original window.onerror function.
    - * @type {Function|undefined}
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.origOnError_;
    -
    -
    -/**
    - * The stage of the test we are currently on.
    - * @type {Function|undefined}}
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.curStepFunc_;
    -
    -
    -/**
    - * The name of the stage of the test we are currently on.
    - * @type {string}
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.curStepName_ = '';
    -
    -
    -/**
    - * The stage of the test we should run next.
    - * @type {Function|undefined}
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.nextStepFunc;
    -
    -
    -/**
    - * The name of the stage of the test we should run next.
    - * @type {string}
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.nextStepName_ = '';
    -
    -
    -/**
    - * The handle to the current setTimeout timer.
    - * @type {number}
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.timeoutHandle_ = 0;
    -
    -
    -/**
    - * Marks if the cleanUp() function has been called for the currently running
    - * test.
    - * @type {boolean}
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.cleanedUp_ = false;
    -
    -
    -/**
    - * The currently active test.
    - * @type {goog.testing.TestCase.Test|undefined}
    - * @protected
    - */
    -goog.testing.AsyncTestCase.prototype.activeTest;
    -
    -
    -/**
    - * A flag to prevent recursive exception handling.
    - * @type {boolean}
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.inException_ = false;
    -
    -
    -/**
    - * Flag used to determine if we can move to the next step in the testing loop.
    - * @type {boolean}
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.isReady_ = true;
    -
    -
    -/**
    - * Number of signals to wait for before continuing testing when waitForSignals
    - * is used.
    - * @type {number}
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.expectedSignalCount_ = 0;
    -
    -
    -/**
    - * Number of signals received.
    - * @type {number}
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.receivedSignalCount_ = 0;
    -
    -
    -/**
    - * Flag that tells us if there is a function in the call stack that will make
    - * a call to pump_().
    - * @type {boolean}
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.returnWillPump_ = false;
    -
    -
    -/**
    - * The number of times we have thrown a ControlBreakingException so that we
    - * know not to complain in our window.onerror handler. In Webkit, window.onerror
    - * is not supported, and so this counter will keep going up but we won't care
    - * about it.
    - * @type {number}
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.numControlExceptionsExpected_ = 0;
    -
    -
    -/**
    - * The current step name.
    - * @return {!string} Step name.
    - * @protected
    - */
    -goog.testing.AsyncTestCase.prototype.getCurrentStepName = function() {
    -  return this.curStepName_;
    -};
    -
    -
    -/**
    - * Preferred way of creating an AsyncTestCase. Creates one and initializes it
    - * with the G_testRunner.
    - * @param {string=} opt_name A descriptive name for the test case.
    - * @return {!goog.testing.AsyncTestCase} The created AsyncTestCase.
    - */
    -goog.testing.AsyncTestCase.createAndInstall = function(opt_name) {
    -  var asyncTestCase = new goog.testing.AsyncTestCase(opt_name);
    -  goog.testing.TestCase.initializeTestRunner(asyncTestCase);
    -  return asyncTestCase;
    -};
    -
    -
    -/**
    - * Informs the testcase not to continue to the next step in the test cycle
    - * until continueTesting is called.
    - * @param {string=} opt_name A description of what we are waiting for.
    - */
    -goog.testing.AsyncTestCase.prototype.waitForAsync = function(opt_name) {
    -  this.isReady_ = false;
    -  this.curStepName_ = opt_name || this.curStepName_;
    -
    -  // Reset the timer that tracks if the async test takes too long.
    -  this.stopTimeoutTimer_();
    -  this.startTimeoutTimer_();
    -};
    -
    -
    -/**
    - * Continue with the next step in the test cycle.
    - */
    -goog.testing.AsyncTestCase.prototype.continueTesting = function() {
    -  if (this.receivedSignalCount_ < this.expectedSignalCount_) {
    -    var remaining = this.expectedSignalCount_ - this.receivedSignalCount_;
    -    throw Error('Still waiting for ' + remaining + ' signals.');
    -  }
    -  this.endCurrentStep_();
    -};
    -
    -
    -/**
    - * Ends the current test step and queues the next test step to run.
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.endCurrentStep_ = function() {
    -  if (!this.isReady_) {
    -    // We are a potential entry point, so we pump.
    -    this.isReady_ = true;
    -    this.stopTimeoutTimer_();
    -    // Run this in a setTimeout so that the caller has a chance to call
    -    // waitForAsync() again before we continue.
    -    this.timeout(goog.bind(this.pump_, this, null), 0);
    -  }
    -};
    -
    -
    -/**
    - * Informs the testcase not to continue to the next step in the test cycle
    - * until signal is called the specified number of times. Within a test, this
    - * function behaves additively if called multiple times; the number of signals
    - * to wait for will be the sum of all expected number of signals this function
    - * was called with.
    - * @param {number} times The number of signals to receive before
    - *    continuing testing.
    - * @param {string=} opt_name A description of what we are waiting for.
    - */
    -goog.testing.AsyncTestCase.prototype.waitForSignals =
    -    function(times, opt_name) {
    -  this.expectedSignalCount_ += times;
    -  if (this.receivedSignalCount_ < this.expectedSignalCount_) {
    -    this.waitForAsync(opt_name);
    -  }
    -};
    -
    -
    -/**
    - * Signals once to continue with the test. If this is the last signal that the
    - * test was waiting on, call continueTesting.
    - */
    -goog.testing.AsyncTestCase.prototype.signal = function() {
    -  if (++this.receivedSignalCount_ === this.expectedSignalCount_ &&
    -      this.expectedSignalCount_ > 0) {
    -    this.endCurrentStep_();
    -  }
    -};
    -
    -
    -/**
    - * Handles an exception thrown by a test.
    - * @param {*=} opt_e The exception object associated with the failure
    - *     or a string.
    - * @throws Always throws a ControlBreakingException.
    - */
    -goog.testing.AsyncTestCase.prototype.doAsyncError = function(opt_e) {
    -  // If we've caught an exception that we threw, then just pass it along. This
    -  // can happen if doAsyncError() was called from a call to assert and then
    -  // again by pump_().
    -  if (opt_e && opt_e.isControlBreakingException) {
    -    throw opt_e;
    -  }
    -
    -  // Prevent another timeout error from triggering for this test step.
    -  this.stopTimeoutTimer_();
    -
    -  // doError() uses test.name. Here, we create a dummy test and give it a more
    -  // helpful name based on the step we're currently on.
    -  var fakeTestObj = new goog.testing.TestCase.Test(this.curStepName_,
    -                                                   goog.nullFunction);
    -  if (this.activeTest) {
    -    fakeTestObj.name = this.activeTest.name + ' [' + fakeTestObj.name + ']';
    -  }
    -
    -  if (this.activeTest) {
    -    // Note: if the test has an error, and then tearDown has an error, they will
    -    // both be reported.
    -    this.doError(fakeTestObj, opt_e);
    -  } else {
    -    this.exceptionBeforeTest = opt_e;
    -  }
    -
    -  // This is a potential entry point, so we pump. We also add in a bit of a
    -  // delay to try and prevent any async behavior from the failed test from
    -  // causing the next test to fail.
    -  this.timeout(goog.bind(this.pump_, this, this.doAsyncErrorTearDown_),
    -      this.timeToSleepAfterFailure);
    -
    -  // We just caught an exception, so we do not want the code above us on the
    -  // stack to continue executing. If pump_ is in our call-stack, then it will
    -  // batch together multiple errors, so we only increment the count if pump_ is
    -  // not in the stack and let pump_ increment the count when it batches them.
    -  if (!this.returnWillPump_) {
    -    this.numControlExceptionsExpected_ += 1;
    -    this.dbgLog_('doAsynError: numControlExceptionsExpected_ = ' +
    -        this.numControlExceptionsExpected_ + ' and throwing exception.');
    -  }
    -
    -  // Copy the error message to ControlBreakingException.
    -  var message = '';
    -  if (typeof opt_e == 'string') {
    -    message = opt_e;
    -  } else if (opt_e && opt_e.message) {
    -    message = opt_e.message;
    -  }
    -  throw new goog.testing.AsyncTestCase.ControlBreakingException(message);
    -};
    -
    -
    -/**
    - * Sets up the test page and then waits until the test case has been marked
    - * as ready before executing the tests.
    - * @override
    - */
    -goog.testing.AsyncTestCase.prototype.runTests = function() {
    -  this.hookAssert_();
    -  this.hookOnError_();
    -
    -  this.setNextStep_(this.doSetUpPage_, 'setUpPage');
    -  // We are an entry point, so we pump.
    -  this.pump_();
    -};
    -
    -
    -/**
    - * Starts the tests.
    - * @override
    - */
    -goog.testing.AsyncTestCase.prototype.cycleTests = function() {
    -  // We are an entry point, so we pump.
    -  this.saveMessage('Start');
    -  this.setNextStep_(this.doIteration_, 'doIteration');
    -  this.pump_();
    -};
    -
    -
    -/**
    - * Finalizes the test case, called when the tests have finished executing.
    - * @override
    - */
    -goog.testing.AsyncTestCase.prototype.finalize = function() {
    -  this.unhookAll_();
    -  this.setNextStep_(null, 'finalized');
    -  goog.testing.AsyncTestCase.superClass_.finalize.call(this);
    -};
    -
    -
    -/**
    - * Enables verbose logging of what is happening inside of the AsyncTestCase.
    - */
    -goog.testing.AsyncTestCase.prototype.enableDebugLogging = function() {
    -  this.enableDebugLogs_ = true;
    -};
    -
    -
    -/**
    - * Logs the given debug message to the console (when enabled).
    - * @param {string} message The message to log.
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.dbgLog_ = function(message) {
    -  if (this.enableDebugLogs_) {
    -    this.log('AsyncTestCase - ' + message);
    -  }
    -};
    -
    -
    -/**
    - * Wraps doAsyncError() for when we are sure that the test runner has no user
    - * code above it in the stack.
    - * @param {string|Error=} opt_e The exception object associated with the
    - *     failure or a string.
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.doTopOfStackAsyncError_ =
    -    function(opt_e) {
    -  /** @preserveTry */
    -  try {
    -    this.doAsyncError(opt_e);
    -  } catch (e) {
    -    // We know that we are on the top of the stack, so there is no need to
    -    // throw this exception in this case.
    -    if (e.isControlBreakingException) {
    -      this.numControlExceptionsExpected_ -= 1;
    -      this.dbgLog_('doTopOfStackAsyncError_: numControlExceptionsExpected_ = ' +
    -          this.numControlExceptionsExpected_ + ' and catching exception.');
    -    } else {
    -      throw e;
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Calls the tearDown function, catching any errors, and then moves on to
    - * the next step in the testing cycle.
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.doAsyncErrorTearDown_ = function() {
    -  if (this.inException_) {
    -    // We get here if tearDown is throwing the error.
    -    // Upon calling continueTesting, the inline function 'doAsyncError' (set
    -    // below) is run.
    -    this.endCurrentStep_();
    -  } else {
    -    this.inException_ = true;
    -    this.isReady_ = true;
    -
    -    // The continue point is different depending on if the error happened in
    -    // setUpPage() or in setUp()/test*()/tearDown().
    -    var stepFuncAfterError = this.nextStepFunc_;
    -    var stepNameAfterError = 'TestCase.execute (after error)';
    -    if (this.activeTest) {
    -      stepFuncAfterError = this.doIteration_;
    -      stepNameAfterError = 'doIteration (after error)';
    -    }
    -
    -    // We must set the next step before calling tearDown.
    -    this.setNextStep_(function() {
    -      this.inException_ = false;
    -      // This is null when an error happens in setUpPage.
    -      this.setNextStep_(stepFuncAfterError, stepNameAfterError);
    -    }, 'doAsyncError');
    -
    -    // Call the test's tearDown().
    -    if (!this.cleanedUp_) {
    -      this.cleanedUp_ = true;
    -      this.tearDown();
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Replaces the asserts.js assert_() and fail() functions with a wrappers to
    - * catch the exceptions.
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.hookAssert_ = function() {
    -  if (!this.origAssert_) {
    -    this.origAssert_ = _assert;
    -    this.origFail_ = fail;
    -    var self = this;
    -    _assert = function() {
    -      /** @preserveTry */
    -      try {
    -        self.origAssert_.apply(this, arguments);
    -      } catch (e) {
    -        self.dbgLog_('Wrapping failed assert()');
    -        self.doAsyncError(e);
    -      }
    -    };
    -    fail = function() {
    -      /** @preserveTry */
    -      try {
    -        self.origFail_.apply(this, arguments);
    -      } catch (e) {
    -        self.dbgLog_('Wrapping fail()');
    -        self.doAsyncError(e);
    -      }
    -    };
    -  }
    -};
    -
    -
    -/**
    - * Sets a window.onerror handler for catching exceptions that happen in async
    - * callbacks. Note that as of Safari 3.1, Safari does not support this.
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.hookOnError_ = function() {
    -  if (!this.origOnError_) {
    -    this.origOnError_ = window.onerror;
    -    var self = this;
    -    window.onerror = function(error, url, line) {
    -      // Ignore exceptions that we threw on purpose.
    -      var cbe =
    -          goog.testing.AsyncTestCase.ControlBreakingException.TO_STRING;
    -      if (String(error).indexOf(cbe) != -1 &&
    -          self.numControlExceptionsExpected_) {
    -        self.numControlExceptionsExpected_ -= 1;
    -        self.dbgLog_('window.onerror: numControlExceptionsExpected_ = ' +
    -            self.numControlExceptionsExpected_ + ' and ignoring exception. ' +
    -            error);
    -        // Tell the browser not to compain about the error.
    -        return true;
    -      } else {
    -        self.dbgLog_('window.onerror caught exception.');
    -        var message = error + '\nURL: ' + url + '\nLine: ' + line;
    -        self.doTopOfStackAsyncError_(message);
    -        // Tell the browser to complain about the error.
    -        return false;
    -      }
    -    };
    -  }
    -};
    -
    -
    -/**
    - * Unhooks window.onerror and _assert.
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.unhookAll_ = function() {
    -  if (this.origOnError_) {
    -    window.onerror = this.origOnError_;
    -    this.origOnError_ = null;
    -    _assert = this.origAssert_;
    -    this.origAssert_ = null;
    -    fail = this.origFail_;
    -    this.origFail_ = null;
    -  }
    -};
    -
    -
    -/**
    - * Enables the timeout timer. This timer fires unless continueTesting is
    - * called.
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.startTimeoutTimer_ = function() {
    -  if (!this.timeoutHandle_ && this.stepTimeout > 0) {
    -    this.timeoutHandle_ = this.timeout(goog.bind(function() {
    -      this.dbgLog_('Timeout timer fired with id ' + this.timeoutHandle_);
    -      this.timeoutHandle_ = 0;
    -
    -      this.doTopOfStackAsyncError_('Timed out while waiting for ' +
    -          'continueTesting() to be called.');
    -    }, this, null), this.stepTimeout);
    -    this.dbgLog_('Started timeout timer with id ' + this.timeoutHandle_);
    -  }
    -};
    -
    -
    -/**
    - * Disables the timeout timer.
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.stopTimeoutTimer_ = function() {
    -  if (this.timeoutHandle_) {
    -    this.dbgLog_('Clearing timeout timer with id ' + this.timeoutHandle_);
    -    this.clearTimeout(this.timeoutHandle_);
    -    this.timeoutHandle_ = 0;
    -  }
    -};
    -
    -
    -/**
    - * Sets the next function to call in our sequence of async callbacks.
    - * @param {Function} func The function that executes the next step.
    - * @param {string} name A description of the next step.
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.setNextStep_ = function(func, name) {
    -  this.nextStepFunc_ = func && goog.bind(func, this);
    -  this.nextStepName_ = name;
    -};
    -
    -
    -/**
    - * Calls the given function, redirecting any exceptions to doAsyncError.
    - * @param {Function} func The function to call.
    - * @return {!goog.testing.AsyncTestCase.TopStackFuncResult_} Returns a
    - * TopStackFuncResult_.
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.callTopOfStackFunc_ = function(func) {
    -  /** @preserveTry */
    -  try {
    -    func.call(this);
    -    return {controlBreakingExceptionThrown: false, message: ''};
    -  } catch (e) {
    -    this.dbgLog_('Caught exception in callTopOfStackFunc_');
    -    /** @preserveTry */
    -    try {
    -      this.doAsyncError(e);
    -      return {controlBreakingExceptionThrown: false, message: ''};
    -    } catch (e2) {
    -      if (!e2.isControlBreakingException) {
    -        throw e2;
    -      }
    -      return {controlBreakingExceptionThrown: true, message: e2.message};
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Calls the next callback when the isReady_ flag is true.
    - * @param {Function=} opt_doFirst A function to call before pumping.
    - * @private
    - * @throws Throws a ControlBreakingException if there were any failing steps.
    - */
    -goog.testing.AsyncTestCase.prototype.pump_ = function(opt_doFirst) {
    -  // If this function is already above us in the call-stack, then we should
    -  // return rather than pumping in order to minimize call-stack depth.
    -  if (!this.returnWillPump_) {
    -    this.setBatchTime(this.now());
    -    this.returnWillPump_ = true;
    -    var topFuncResult = {};
    -
    -    if (opt_doFirst) {
    -      topFuncResult = this.callTopOfStackFunc_(opt_doFirst);
    -    }
    -    // Note: we don't check for this.running here because it is not set to true
    -    // while executing setUpPage and tearDownPage.
    -    // Also, if isReady_ is false, then one of two things will happen:
    -    // 1. Our timeout callback will be called.
    -    // 2. The tests will call continueTesting(), which will call pump_() again.
    -    while (this.isReady_ && this.nextStepFunc_ &&
    -        !topFuncResult.controlBreakingExceptionThrown) {
    -      this.curStepFunc_ = this.nextStepFunc_;
    -      this.curStepName_ = this.nextStepName_;
    -      this.nextStepFunc_ = null;
    -      this.nextStepName_ = '';
    -
    -      this.dbgLog_('Performing step: ' + this.curStepName_);
    -      topFuncResult =
    -          this.callTopOfStackFunc_(/** @type {Function} */(this.curStepFunc_));
    -
    -      // If the max run time is exceeded call this function again async so as
    -      // not to block the browser.
    -      var delta = this.now() - this.getBatchTime();
    -      if (delta > goog.testing.TestCase.maxRunTime &&
    -          !topFuncResult.controlBreakingExceptionThrown) {
    -        this.saveMessage('Breaking async');
    -        var self = this;
    -        this.timeout(function() { self.pump_(); }, 100);
    -        break;
    -      }
    -    }
    -    this.returnWillPump_ = false;
    -  } else if (opt_doFirst) {
    -    opt_doFirst.call(this);
    -  }
    -};
    -
    -
    -/**
    - * Sets up the test page and then waits untill the test case has been marked
    - * as ready before executing the tests.
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.doSetUpPage_ = function() {
    -  this.setNextStep_(this.execute, 'TestCase.execute');
    -  this.setUpPage();
    -};
    -
    -
    -/**
    - * Step 1: Move to the next test.
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.doIteration_ = function() {
    -  this.expectedSignalCount_ = 0;
    -  this.receivedSignalCount_ = 0;
    -  this.activeTest = this.next();
    -  if (this.activeTest && this.running) {
    -    this.result_.runCount++;
    -    // If this test should be marked as having failed, doIteration will go
    -    // straight to the next test.
    -    if (this.maybeFailTestEarly(this.activeTest)) {
    -      this.setNextStep_(this.doIteration_, 'doIteration');
    -    } else {
    -      this.setNextStep_(this.doSetUp_, 'setUp');
    -    }
    -  } else {
    -    // All tests done.
    -    this.finalize();
    -  }
    -};
    -
    -
    -/**
    - * Step 2: Call setUp().
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.doSetUp_ = function() {
    -  this.log('Running test: ' + this.activeTest.name);
    -  this.cleanedUp_ = false;
    -  this.setNextStep_(this.doExecute_, this.activeTest.name);
    -  this.setUp();
    -};
    -
    -
    -/**
    - * Step 3: Call test.execute().
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.doExecute_ = function() {
    -  this.setNextStep_(this.doTearDown_, 'tearDown');
    -  this.activeTest.execute();
    -};
    -
    -
    -/**
    - * Step 4: Call tearDown().
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.doTearDown_ = function() {
    -  this.cleanedUp_ = true;
    -  this.setNextStep_(this.doNext_, 'doNext');
    -  this.tearDown();
    -};
    -
    -
    -/**
    - * Step 5: Call doSuccess()
    - * @private
    - */
    -goog.testing.AsyncTestCase.prototype.doNext_ = function() {
    -  this.setNextStep_(this.doIteration_, 'doIteration');
    -  this.doSuccess(/** @type {goog.testing.TestCase.Test} */(this.activeTest));
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/asynctestcase_async_test.html b/src/database/third_party/closure-library/closure/goog/testing/asynctestcase_async_test.html
    deleted file mode 100644
    index 8bfe23f006b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/asynctestcase_async_test.html
    +++ /dev/null
    @@ -1,31 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -Author: agrieve@google.com (Andrew Grieve)
    -
    -This tests that the AsyncTestCase can handle asynchronous behaviour in:
    -  setUpPage(),
    -  setUp(),
    -  test*(),
    -  tearDown()
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.testing.AsyncTestCase Asyncronous Tests
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script type="text/javascript">
    -    goog.require('goog.testing.AsyncTestCaseAsyncTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/asynctestcase_async_test.js b/src/database/third_party/closure-library/closure/goog/testing/asynctestcase_async_test.js
    deleted file mode 100644
    index af62836bec0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/asynctestcase_async_test.js
    +++ /dev/null
    @@ -1,136 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.AsyncTestCaseAsyncTest');
    -goog.setTestOnly('goog.testing.AsyncTestCaseAsyncTest');
    -
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.jsunit');
    -
    -// Has the setUp() function been called.
    -var setUpCalled = false;
    -// Has the current test function completed. This helps us to ensure that
    -// the next test is not started before the previous completed.
    -var curTestIsDone = true;
    -// Use an asynchronous test runner for our tests.
    -var asyncTestCase =
    -    goog.testing.AsyncTestCase.createAndInstall(document.title);
    -
    -
    -/**
    - * Uses window.setTimeout() to perform asynchronous behaviour and uses
    - * asyncTestCase.waitForAsync() and asyncTestCase.continueTesting() to mark
    - * the beginning and end of it.
    - * @param {number} numAsyncCalls The number of asynchronous calls to make.
    - * @param {string} name The name of the current step.
    - */
    -function doAsyncStuff(numAsyncCalls, name) {
    -  if (numAsyncCalls > 0) {
    -    curTestIsDone = false;
    -    asyncTestCase.waitForAsync(
    -        'doAsyncStuff-' + name + '(' + numAsyncCalls + ')');
    -    window.setTimeout(function() {
    -      doAsyncStuff(numAsyncCalls - 1, name);
    -    }, 0);
    -  } else {
    -    curTestIsDone = true;
    -    asyncTestCase.continueTesting();
    -  }
    -}
    -
    -function setUpPage() {
    -  debug('setUpPage was called.');
    -  doAsyncStuff(3, 'setUpPage');
    -}
    -function setUp() {
    -  assertTrue(curTestIsDone);
    -  doAsyncStuff(3, 'setUp');
    -}
    -function tearDown() {
    -  assertTrue(curTestIsDone);
    -}
    -function test1() {
    -  assertTrue(curTestIsDone);
    -  doAsyncStuff(1, 'test1');
    -}
    -function test2_asyncContinueThenWait() {
    -  var activeTest = asyncTestCase.activeTest_;
    -  function async1() {
    -    asyncTestCase.continueTesting();
    -    asyncTestCase.waitForAsync('2');
    -    window.setTimeout(async2, 0);
    -  }
    -  function async2() {
    -    asyncTestCase.continueTesting();
    -    assertEquals('Did not wait for inner waitForAsync',
    -                 activeTest,
    -                 asyncTestCase.activeTest_);
    -  }
    -  asyncTestCase.waitForAsync('1');
    -  window.setTimeout(async1, 0);
    -}
    -function test3() {
    -  assertTrue(curTestIsDone);
    -  doAsyncStuff(2, 'test3');
    -}
    -
    -function tearDownPage() {
    -  debug('tearDownPage was called.');
    -  assertTrue(curTestIsDone);
    -}
    -
    -
    -var callback = function() {
    -  curTestIsDone = true;
    -  asyncTestCase.signal();
    -};
    -var doAsyncSignals = function() {
    -  curTestIsDone = false;
    -  window.setTimeout(callback, 0);
    -};
    -
    -function testSignalsReturn() {
    -  doAsyncSignals();
    -  doAsyncSignals();
    -  doAsyncSignals();
    -  asyncTestCase.waitForSignals(3);
    -}
    -
    -function testSignalsMixedSyncAndAsync() {
    -  asyncTestCase.signal();
    -  doAsyncSignals();
    -  doAsyncSignals();
    -  asyncTestCase.waitForSignals(3);
    -}
    -
    -function testSignalsMixedSyncAndAsyncMultipleWaits() {
    -  asyncTestCase.signal();
    -  doAsyncSignals();
    -  asyncTestCase.waitForSignals(1);
    -  doAsyncSignals();
    -  asyncTestCase.waitForSignals(2);
    -}
    -
    -function testSignalsCallContinueTestingBeforeFinishing() {
    -  doAsyncSignals();
    -  asyncTestCase.waitForSignals(2);
    -
    -  window.setTimeout(function() {
    -    var thrown = assertThrows(function() {
    -      asyncTestCase.continueTesting();
    -    });
    -    assertEquals('Still waiting for 1 signals.', thrown.message);
    -  }, 0);
    -  doAsyncSignals(); // To not timeout.
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/asynctestcase_noasync_test.html b/src/database/third_party/closure-library/closure/goog/testing/asynctestcase_noasync_test.html
    deleted file mode 100644
    index 856b2f3f889..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/asynctestcase_noasync_test.html
    +++ /dev/null
    @@ -1,33 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -Author: agrieve@google.com (Andrew Grieve)
    -
    -This tests that the AsyncTestCase can handle synchronous behaviour in:
    -  setUpPage(),
    -  setUp(),
    -  test*(),
    -  tearDown()
    -It is the same test as asynctestcase_async_test.html, except that it uses a mock
    -version of window.setTimeout() to eliminate all asynchronous calls.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.testing.AsyncTestCase Synchronous Tests
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script type="text/javascript">
    -   goog.require('goog.testing.AsyncTestCaseSyncTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/asynctestcase_noasync_test.js b/src/database/third_party/closure-library/closure/goog/testing/asynctestcase_noasync_test.js
    deleted file mode 100644
    index e2b30222577..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/asynctestcase_noasync_test.js
    +++ /dev/null
    @@ -1,111 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.AsyncTestCaseSyncTest');
    -goog.setTestOnly('goog.testing.AsyncTestCaseSyncTest');
    -
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.jsunit');
    -
    -// Has the setUp() function been called.
    -var setUpCalled = false;
    -// Has the current test function completed. This helps us to ensure that the
    -// next test is not started before the previous completed.
    -var curTestIsDone = true;
    -// For restoring it later.
    -var oldTimeout = window.setTimeout;
    -// Use an asynchronous test runner for our tests.
    -var asyncTestCase =
    -    goog.testing.AsyncTestCase.createAndInstall(document.title);
    -
    -
    -/**
    - * Uses window.setTimeout() to perform asynchronous behaviour and uses
    - * asyncTestCase.waitForAsync() and asyncTestCase.continueTesting() to mark
    - * the beginning and end of it.
    - * @param {number} numAsyncCalls The number of asynchronous calls to make.
    - * @param {string} name The name of the current step.
    - */
    -function doAsyncStuff(numAsyncCalls, name) {
    -  if (numAsyncCalls > 0) {
    -    curTestIsDone = false;
    -    asyncTestCase.waitForAsync(
    -        'doAsyncStuff-' + name + '(' + numAsyncCalls + ')');
    -    window.setTimeout(function() {
    -      doAsyncStuff(numAsyncCalls - 1, name);
    -    }, 0);
    -  } else {
    -    curTestIsDone = true;
    -    asyncTestCase.continueTesting();
    -  }
    -}
    -
    -function setUpPage() {
    -  debug('setUpPage was called.');
    -  // Don't do anything asynchronously.
    -  window.setTimeout = function(callback, time) {
    -    callback();
    -  };
    -  doAsyncStuff(3, 'setUpPage');
    -}
    -function setUp() {
    -  assertTrue(curTestIsDone);
    -  doAsyncStuff(3, 'setUp');
    -}
    -function tearDown() {
    -  assertTrue(curTestIsDone);
    -}
    -function test1() {
    -  assertTrue(curTestIsDone);
    -  doAsyncStuff(1, 'test1');
    -}
    -function test2() {
    -  assertTrue(curTestIsDone);
    -  doAsyncStuff(2, 'test2');
    -}
    -function test3() {
    -  assertTrue(curTestIsDone);
    -  doAsyncStuff(5, 'test3');
    -}
    -var callback = function() {
    -  curTestIsDone = true;
    -  asyncTestCase.signal();
    -};
    -var doAsyncSignals = function() {
    -  curTestIsDone = false;
    -  window.setTimeout(callback, 0);
    -};
    -function testSignalsReturn() {
    -  doAsyncSignals();
    -  doAsyncSignals();
    -  doAsyncSignals();
    -  asyncTestCase.waitForSignals(3);
    -}
    -function testSignalsCallContinueTestingBeforeFinishing() {
    -  doAsyncSignals();
    -  asyncTestCase.waitForSignals(2);
    -
    -  window.setTimeout(function() {
    -    var thrown = assertThrows(function() {
    -      asyncTestCase.continueTesting();
    -    });
    -    assertEquals('Still waiting for 1 signals.', thrown.message);
    -  }, 0);
    -  doAsyncSignals(); // To not timeout.
    -}
    -function tearDownPage() {
    -  debug('tearDownPage was called.');
    -  assertTrue(curTestIsDone);
    -  window.setTimeout = oldTimeout;
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/asynctestcase_test.html b/src/database/third_party/closure-library/closure/goog/testing/asynctestcase_test.html
    deleted file mode 100644
    index 38efeed929c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/asynctestcase_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.testing.asynctestcase
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.AsyncTestCaseTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/asynctestcase_test.js b/src/database/third_party/closure-library/closure/goog/testing/asynctestcase_test.js
    deleted file mode 100644
    index 7d3b52c266d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/asynctestcase_test.js
    +++ /dev/null
    @@ -1,52 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.AsyncTestCaseTest');
    -goog.setTestOnly('goog.testing.AsyncTestCaseTest');
    -
    -goog.require('goog.debug.Error');
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.asserts');
    -goog.require('goog.testing.jsunit');
    -
    -function testControlBreakingExceptionThrown() {
    -  var asyncTestCase = new goog.testing.AsyncTestCase();
    -
    -  // doAsyncError with no message.
    -  try {
    -    asyncTestCase.doAsyncError();
    -  } catch (e) {
    -    assertTrue(e.isControlBreakingException);
    -    assertEquals('', e.message);
    -  }
    -
    -  // doAsyncError with string.
    -  var errorMessage1 = 'Error message 1';
    -  try {
    -    asyncTestCase.doAsyncError(errorMessage1);
    -  } catch (e) {
    -    assertTrue(e.isControlBreakingException);
    -    assertEquals(errorMessage1, e.message);
    -  }
    -
    -  // doAsyncError with error.
    -  var errorMessage2 = 'Error message 2';
    -  try {
    -    var error = new goog.debug.Error(errorMessage2);
    -    asyncTestCase.doAsyncError(error);
    -  } catch (e) {
    -    assertTrue(e.isControlBreakingException);
    -    assertEquals(errorMessage2, e.message);
    -  }
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/benchmark.js b/src/database/third_party/closure-library/closure/goog/testing/benchmark.js
    deleted file mode 100644
    index 41673e0c884..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/benchmark.js
    +++ /dev/null
    @@ -1,96 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.benchmark');
    -goog.setTestOnly('goog.testing.benchmark');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.testing.PerformanceTable');
    -goog.require('goog.testing.PerformanceTimer');
    -goog.require('goog.testing.TestCase');
    -
    -
    -/**
    - * Run the benchmarks.
    - * @private
    - */
    -goog.testing.benchmark.run_ = function() {
    -  // Parse the 'times' query parameter if it's set.
    -  var times = 200;
    -  var search = window.location.search;
    -  var timesMatch = search.match(/(?:\?|&)times=([^?&]+)/i);
    -  if (timesMatch) {
    -    times = Number(timesMatch[1]);
    -  }
    -
    -  var prefix = 'benchmark';
    -
    -  // First, get the functions.
    -  var testSources = goog.testing.TestCase.getGlobals();
    -
    -  var benchmarks = {};
    -  var names = [];
    -
    -  for (var i = 0; i < testSources.length; i++) {
    -    var testSource = testSources[i];
    -    for (var name in testSource) {
    -      if ((new RegExp('^' + prefix)).test(name)) {
    -        var ref;
    -        try {
    -          ref = testSource[name];
    -        } catch (ex) {
    -          // NOTE(brenneman): When running tests from a file:// URL on Firefox
    -          // 3.5 for Windows, any reference to window.sessionStorage raises
    -          // an "Operation is not supported" exception. Ignore any exceptions
    -          // raised by simply accessing global properties.
    -          ref = undefined;
    -        }
    -
    -        if (goog.isFunction(ref)) {
    -          benchmarks[name] = ref;
    -          names.push(name);
    -        }
    -      }
    -    }
    -  }
    -
    -  document.body.appendChild(
    -      goog.dom.createTextNode(
    -          'Running ' + names.length + ' benchmarks ' + times + ' times each.'));
    -  document.body.appendChild(goog.dom.createElement(goog.dom.TagName.BR));
    -
    -  names.sort();
    -
    -  // Build a table and timer.
    -  var performanceTimer = new goog.testing.PerformanceTimer(times);
    -  performanceTimer.setDiscardOutliers(true);
    -
    -  var performanceTable = new goog.testing.PerformanceTable(document.body,
    -      performanceTimer, 2);
    -
    -  // Next, run the benchmarks.
    -  for (var i = 0; i < names.length; i++) {
    -    performanceTable.run(benchmarks[names[i]], names[i]);
    -  }
    -};
    -
    -
    -/**
    - * Onload handler that runs the benchmarks.
    - * @param {Event} e The event object.
    - */
    -window.onload = function(e) {
    -  goog.testing.benchmark.run_();
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/continuationtestcase.js b/src/database/third_party/closure-library/closure/goog/testing/continuationtestcase.js
    deleted file mode 100644
    index 952b034b205..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/continuationtestcase.js
    +++ /dev/null
    @@ -1,691 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Defines test classes for tests that can wait for conditions.
    - *
    - * Normal unit tests must complete their test logic within a single function
    - * execution. This is ideal for most tests, but makes it difficult to test
    - * routines that require real time to complete. The tests and TestCase in this
    - * file allow for tests that can wait until a condition is true before
    - * continuing execution.
    - *
    - * Each test has the typical three phases of execution: setUp, the test itself,
    - * and tearDown. During each phase, the test function may add wait conditions,
    - * which result in new test steps being added for that phase. All steps in a
    - * given phase must complete before moving on to the next phase. An error in
    - * any phase will stop that test and report the error to the test runner.
    - *
    - * This class should not be used where adequate mocks exist. Time-based routines
    - * should use the MockClock, which runs much faster and provides equivalent
    - * results. Continuation tests should be used for testing code that depends on
    - * browser behaviors that are difficult to mock. For example, testing code that
    - * relies on Iframe load events, event or layout code that requires a setTimeout
    - * to become valid, and other browser-dependent native object interactions for
    - * which mocks are insufficient.
    - *
    - * Sample usage:
    - *
    - * <pre>
    - * var testCase = new goog.testing.ContinuationTestCase();
    - * testCase.autoDiscoverTests();
    - *
    - * if (typeof G_testRunner != 'undefined') {
    - *   G_testRunner.initialize(testCase);
    - * }
    - *
    - * function testWaiting() {
    - *   var someVar = true;
    - *   waitForTimeout(function() {
    - *     assertTrue(someVar)
    - *   }, 500);
    - * }
    - *
    - * function testWaitForEvent() {
    - *   var et = goog.events.EventTarget();
    - *   waitForEvent(et, 'test', function() {
    - *     // Test step runs after the event fires.
    - *   })
    - *   et.dispatchEvent(et, 'test');
    - * }
    - *
    - * function testWaitForCondition() {
    - *   var counter = 0;
    - *
    - *   waitForCondition(function() {
    - *     // This function is evaluated periodically until it returns true, or it
    - *     // times out.
    - *     return ++counter >= 3;
    - *   }, function() {
    - *     // This test step is run once the condition becomes true.
    - *     assertEquals(3, counter);
    - *   });
    - * }
    - * </pre>
    - *
    - * @author brenneman@google.com (Shawn Brenneman)
    - */
    -
    -
    -goog.provide('goog.testing.ContinuationTestCase');
    -goog.provide('goog.testing.ContinuationTestCase.Step');
    -goog.provide('goog.testing.ContinuationTestCase.Test');
    -
    -goog.require('goog.array');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.testing.TestCase');
    -goog.require('goog.testing.asserts');
    -
    -
    -
    -/**
    - * Constructs a test case that supports tests with continuations. Test functions
    - * may issue "wait" commands that suspend the test temporarily and continue once
    - * the wait condition is met.
    - *
    - * @param {string=} opt_name Optional name for the test case.
    - * @constructor
    - * @extends {goog.testing.TestCase}
    - * @final
    - */
    -goog.testing.ContinuationTestCase = function(opt_name) {
    -  goog.testing.TestCase.call(this, opt_name);
    -
    -  /**
    -   * An event handler for waiting on Closure or browser events during tests.
    -   * @type {goog.events.EventHandler<!goog.testing.ContinuationTestCase>}
    -   * @private
    -   */
    -  this.handler_ = new goog.events.EventHandler(this);
    -};
    -goog.inherits(goog.testing.ContinuationTestCase, goog.testing.TestCase);
    -
    -
    -/**
    - * The default maximum time to wait for a single test step in milliseconds.
    - * @type {number}
    - */
    -goog.testing.ContinuationTestCase.MAX_TIMEOUT = 1000;
    -
    -
    -/**
    - * Lock used to prevent multiple test steps from running recursively.
    - * @type {boolean}
    - * @private
    - */
    -goog.testing.ContinuationTestCase.locked_ = false;
    -
    -
    -/**
    - * The current test being run.
    - * @type {goog.testing.ContinuationTestCase.Test}
    - * @private
    - */
    -goog.testing.ContinuationTestCase.prototype.currentTest_ = null;
    -
    -
    -/**
    - * Enables or disables the wait functions in the global scope.
    - * @param {boolean} enable Whether the wait functions should be exported.
    - * @private
    - */
    -goog.testing.ContinuationTestCase.prototype.enableWaitFunctions_ =
    -    function(enable) {
    -  if (enable) {
    -    goog.exportSymbol('waitForCondition',
    -                      goog.bind(this.waitForCondition, this));
    -    goog.exportSymbol('waitForEvent', goog.bind(this.waitForEvent, this));
    -    goog.exportSymbol('waitForTimeout', goog.bind(this.waitForTimeout, this));
    -  } else {
    -    // Internet Explorer doesn't allow deletion of properties on the window.
    -    goog.global['waitForCondition'] = undefined;
    -    goog.global['waitForEvent'] = undefined;
    -    goog.global['waitForTimeout'] = undefined;
    -  }
    -};
    -
    -
    -/** @override */
    -goog.testing.ContinuationTestCase.prototype.runTests = function() {
    -  this.enableWaitFunctions_(true);
    -  goog.testing.ContinuationTestCase.superClass_.runTests.call(this);
    -};
    -
    -
    -/** @override */
    -goog.testing.ContinuationTestCase.prototype.finalize = function() {
    -  this.enableWaitFunctions_(false);
    -  goog.testing.ContinuationTestCase.superClass_.finalize.call(this);
    -};
    -
    -
    -/** @override */
    -goog.testing.ContinuationTestCase.prototype.cycleTests = function() {
    -  // Get the next test in the queue.
    -  if (!this.currentTest_) {
    -    this.currentTest_ = this.createNextTest_();
    -  }
    -
    -  // Run the next step of the current test, or exit if all tests are complete.
    -  if (this.currentTest_) {
    -    this.runNextStep_();
    -  } else {
    -    this.finalize();
    -  }
    -};
    -
    -
    -/**
    - * Creates the next test in the queue.
    - * @return {goog.testing.ContinuationTestCase.Test} The next test to execute, or
    - *     null if no pending tests remain.
    - * @private
    - */
    -goog.testing.ContinuationTestCase.prototype.createNextTest_ = function() {
    -  var test = this.next();
    -  if (!test) {
    -    return null;
    -  }
    -
    -
    -  var name = test.name;
    -  goog.testing.TestCase.currentTestName = name;
    -  this.result_.runCount++;
    -  this.log('Running test: ' + name);
    -
    -  return new goog.testing.ContinuationTestCase.Test(
    -      new goog.testing.TestCase.Test(name, this.setUp, this),
    -      test,
    -      new goog.testing.TestCase.Test(name, this.tearDown, this));
    -};
    -
    -
    -/**
    - * Cleans up a finished test and cycles to the next test.
    - * @private
    - */
    -goog.testing.ContinuationTestCase.prototype.finishTest_ = function() {
    -  var err = this.currentTest_.getError();
    -  if (err) {
    -    this.doError(this.currentTest_, err);
    -  } else {
    -    this.doSuccess(this.currentTest_);
    -  }
    -
    -  goog.testing.TestCase.currentTestName = null;
    -  this.currentTest_ = null;
    -  this.locked_ = false;
    -  this.handler_.removeAll();
    -
    -  this.timeout(goog.bind(this.cycleTests, this), 0);
    -};
    -
    -
    -/**
    - * Executes the next step in the current phase, advancing through each phase as
    - * all steps are completed.
    - * @private
    - */
    -goog.testing.ContinuationTestCase.prototype.runNextStep_ = function() {
    -  if (this.locked_) {
    -    // Attempting to run a step before the previous step has finished. Try again
    -    // after that step has released the lock.
    -    return;
    -  }
    -
    -  var phase = this.currentTest_.getCurrentPhase();
    -
    -  if (!phase || !phase.length) {
    -    // No more steps for this test.
    -    this.finishTest_();
    -    return;
    -  }
    -
    -  // Find the next step that is not in a wait state.
    -  var stepIndex = goog.array.findIndex(phase, function(step) {
    -    return !step.waiting;
    -  });
    -
    -  if (stepIndex < 0) {
    -    // All active steps are currently waiting. Return until one wakes up.
    -    return;
    -  }
    -
    -  this.locked_ = true;
    -  var step = phase[stepIndex];
    -
    -  try {
    -    step.execute();
    -    // Remove the successfully completed step. If an error is thrown, all steps
    -    // will be removed for this phase.
    -    goog.array.removeAt(phase, stepIndex);
    -
    -  } catch (e) {
    -    this.currentTest_.setError(e);
    -
    -    // An assertion has failed, or an exception was raised. Clear the current
    -    // phase, whether it is setUp, test, or tearDown.
    -    this.currentTest_.cancelCurrentPhase();
    -
    -    // Cancel the setUp and test phase no matter where the error occurred. The
    -    // tearDown phase will still run if it has pending steps.
    -    this.currentTest_.cancelTestPhase();
    -  }
    -
    -  this.locked_ = false;
    -  this.runNextStep_();
    -};
    -
    -
    -/**
    - * Creates a new test step that will run after a user-specified
    - * timeout.  No guarantee is made on the execution order of the
    - * continuation, except for those provided by each browser's
    - * window.setTimeout. In particular, if two continuations are
    - * registered at the same time with very small delta for their
    - * durations, this class can not guarantee that the continuation with
    - * the smaller duration will be executed first.
    - * @param {Function} continuation The test function to invoke after the timeout.
    - * @param {number=} opt_duration The length of the timeout in milliseconds.
    - */
    -goog.testing.ContinuationTestCase.prototype.waitForTimeout =
    -    function(continuation, opt_duration) {
    -  var step = this.addStep_(continuation);
    -  step.setTimeout(goog.bind(this.handleComplete_, this, step),
    -                  opt_duration || 0);
    -};
    -
    -
    -/**
    - * Creates a new test step that will run after an event has fired. If the event
    - * does not fire within a reasonable timeout, the test will fail.
    - * @param {goog.events.EventTarget|EventTarget} eventTarget The target that will
    - *     fire the event.
    - * @param {string} eventType The type of event to listen for.
    - * @param {Function} continuation The test function to invoke after the event
    - *     fires.
    - */
    -goog.testing.ContinuationTestCase.prototype.waitForEvent = function(
    -    eventTarget,
    -    eventType,
    -    continuation) {
    -
    -  var step = this.addStep_(continuation);
    -
    -  var duration = goog.testing.ContinuationTestCase.MAX_TIMEOUT;
    -  step.setTimeout(goog.bind(this.handleTimeout_, this, step, duration),
    -                  duration);
    -
    -  this.handler_.listenOnce(eventTarget,
    -                           eventType,
    -                           goog.bind(this.handleComplete_, this, step));
    -};
    -
    -
    -/**
    - * Creates a new test step which will run once a condition becomes true. The
    - * condition will be polled at a user-specified interval until it becomes true,
    - * or until a maximum timeout is reached.
    - * @param {Function} condition The condition to poll.
    - * @param {Function} continuation The test code to evaluate once the condition
    - *     becomes true.
    - * @param {number=} opt_interval The polling interval in milliseconds.
    - * @param {number=} opt_maxTimeout The maximum amount of time to wait for the
    - *     condition in milliseconds (defaults to 1000).
    - */
    -goog.testing.ContinuationTestCase.prototype.waitForCondition = function(
    -    condition,
    -    continuation,
    -    opt_interval,
    -    opt_maxTimeout) {
    -
    -  var interval = opt_interval || 100;
    -  var timeout = opt_maxTimeout || goog.testing.ContinuationTestCase.MAX_TIMEOUT;
    -
    -  var step = this.addStep_(continuation);
    -  this.testCondition_(step, condition, goog.now(), interval, timeout);
    -};
    -
    -
    -/**
    - * Creates a new asynchronous test step which will be added to the current test
    - * phase.
    - * @param {Function} func The test function that will be executed for this step.
    - * @return {!goog.testing.ContinuationTestCase.Step} A new test step.
    - * @private
    - */
    -goog.testing.ContinuationTestCase.prototype.addStep_ = function(func) {
    -  if (!this.currentTest_) {
    -    throw Error('Cannot add test steps outside of a running test.');
    -  }
    -
    -  var step = new goog.testing.ContinuationTestCase.Step(
    -      this.currentTest_.name,
    -      func,
    -      this.currentTest_.scope);
    -  this.currentTest_.addStep(step);
    -  return step;
    -};
    -
    -
    -/**
    - * Handles completion of a step's wait condition. Advances the test, allowing
    - * the step's test method to run.
    - * @param {goog.testing.ContinuationTestCase.Step} step The step that has
    - *     finished waiting.
    - * @private
    - */
    -goog.testing.ContinuationTestCase.prototype.handleComplete_ = function(step) {
    -  step.clearTimeout();
    -  step.waiting = false;
    -  this.runNextStep_();
    -};
    -
    -
    -/**
    - * Handles the timeout event for a step that has exceeded the maximum time. This
    - * causes the current test to fail.
    - * @param {goog.testing.ContinuationTestCase.Step} step The timed-out step.
    - * @param {number} duration The length of the timeout in milliseconds.
    - * @private
    - */
    -goog.testing.ContinuationTestCase.prototype.handleTimeout_ =
    -    function(step, duration) {
    -  step.ref = function() {
    -    fail('Continuation timed out after ' + duration + 'ms.');
    -  };
    -
    -  // Since the test is failing, cancel any other pending event listeners.
    -  this.handler_.removeAll();
    -  this.handleComplete_(step);
    -};
    -
    -
    -/**
    - * Tests a wait condition and executes the associated test step once the
    - * condition is true.
    - *
    - * If the condition does not become true before the maximum duration, the
    - * interval will stop and the test step will fail in the kill timer.
    - *
    - * @param {goog.testing.ContinuationTestCase.Step} step The waiting test step.
    - * @param {Function} condition The test condition.
    - * @param {number} startTime Time when the test step began waiting.
    - * @param {number} interval The duration in milliseconds to wait between tests.
    - * @param {number} timeout The maximum amount of time to wait for the condition
    - *     to become true. Measured from the startTime in milliseconds.
    - * @private
    - */
    -goog.testing.ContinuationTestCase.prototype.testCondition_ = function(
    -    step,
    -    condition,
    -    startTime,
    -    interval,
    -    timeout) {
    -
    -  var duration = goog.now() - startTime;
    -
    -  if (condition()) {
    -    this.handleComplete_(step);
    -  } else if (duration < timeout) {
    -    step.setTimeout(goog.bind(this.testCondition_,
    -                              this,
    -                              step,
    -                              condition,
    -                              startTime,
    -                              interval,
    -                              timeout),
    -                    interval);
    -  } else {
    -    this.handleTimeout_(step, duration);
    -  }
    -};
    -
    -
    -
    -/**
    - * Creates a continuation test case, which consists of multiple test steps that
    - * occur in several phases.
    - *
    - * The steps are distributed between setUp, test, and tearDown phases. During
    - * the execution of each step, 0 or more steps may be added to the current
    - * phase. Once all steps in a phase have completed, the next phase will be
    - * executed.
    - *
    - * If any errors occur (such as an assertion failure), the setUp and Test phases
    - * will be cancelled immediately. The tearDown phase will always start, but may
    - * be cancelled as well if it raises an error.
    - *
    - * @param {goog.testing.TestCase.Test} setUp A setUp test method to run before
    - *     the main test phase.
    - * @param {goog.testing.TestCase.Test} test A test method to run.
    - * @param {goog.testing.TestCase.Test} tearDown A tearDown test method to run
    - *     after the test method completes or fails.
    - * @constructor
    - * @extends {goog.testing.TestCase.Test}
    - * @final
    - */
    -goog.testing.ContinuationTestCase.Test = function(setUp, test, tearDown) {
    -  // This test container has a name, but no evaluation function or scope.
    -  goog.testing.TestCase.Test.call(this, test.name, null, null);
    -
    -  /**
    -   * The list of test steps to run during setUp.
    -   * @type {Array<goog.testing.TestCase.Test>}
    -   * @private
    -   */
    -  this.setUp_ = [setUp];
    -
    -  /**
    -   * The list of test steps to run for the actual test.
    -   * @type {Array<goog.testing.TestCase.Test>}
    -   * @private
    -   */
    -  this.test_ = [test];
    -
    -  /**
    -   * The list of test steps to run during the tearDown phase.
    -   * @type {Array<goog.testing.TestCase.Test>}
    -   * @private
    -   */
    -  this.tearDown_ = [tearDown];
    -};
    -goog.inherits(goog.testing.ContinuationTestCase.Test,
    -              goog.testing.TestCase.Test);
    -
    -
    -/**
    - * The first error encountered during the test run, if any.
    - * @type {Error}
    - * @private
    - */
    -goog.testing.ContinuationTestCase.Test.prototype.error_ = null;
    -
    -
    -/**
    - * @return {Error} The first error to be raised during the test run or null if
    - *     no errors occurred.
    - */
    -goog.testing.ContinuationTestCase.Test.prototype.getError = function() {
    -  return this.error_;
    -};
    -
    -
    -/**
    - * Sets an error for the test so it can be reported. Only the first error set
    - * during a test will be reported. Additional errors that occur in later test
    - * phases will be discarded.
    - * @param {Error} e An error.
    - */
    -goog.testing.ContinuationTestCase.Test.prototype.setError = function(e) {
    -  this.error_ = this.error_ || e;
    -};
    -
    -
    -/**
    - * @return {Array<goog.testing.TestCase.Test>} The current phase of steps
    - *    being processed. Returns null if all steps have been completed.
    - */
    -goog.testing.ContinuationTestCase.Test.prototype.getCurrentPhase = function() {
    -  if (this.setUp_.length) {
    -    return this.setUp_;
    -  }
    -
    -  if (this.test_.length) {
    -    return this.test_;
    -  }
    -
    -  if (this.tearDown_.length) {
    -    return this.tearDown_;
    -  }
    -
    -  return null;
    -};
    -
    -
    -/**
    - * Adds a new test step to the end of the current phase. The new step will wait
    - * for a condition to be met before running, or will fail after a timeout.
    - * @param {goog.testing.ContinuationTestCase.Step} step The test step to add.
    - */
    -goog.testing.ContinuationTestCase.Test.prototype.addStep = function(step) {
    -  var phase = this.getCurrentPhase();
    -  if (phase) {
    -    phase.push(step);
    -  } else {
    -    throw Error('Attempted to add a step to a completed test.');
    -  }
    -};
    -
    -
    -/**
    - * Cancels all remaining steps in the current phase. Called after an error in
    - * any phase occurs.
    - */
    -goog.testing.ContinuationTestCase.Test.prototype.cancelCurrentPhase =
    -    function() {
    -  this.cancelPhase_(this.getCurrentPhase());
    -};
    -
    -
    -/**
    - * Skips the rest of the setUp and test phases, but leaves the tearDown phase to
    - * clean up.
    - */
    -goog.testing.ContinuationTestCase.Test.prototype.cancelTestPhase = function() {
    -  this.cancelPhase_(this.setUp_);
    -  this.cancelPhase_(this.test_);
    -};
    -
    -
    -/**
    - * Clears a test phase and cancels any pending steps found.
    - * @param {Array<goog.testing.TestCase.Test>} phase A list of test steps.
    - * @private
    - */
    -goog.testing.ContinuationTestCase.Test.prototype.cancelPhase_ =
    -    function(phase) {
    -  while (phase && phase.length) {
    -    var step = phase.pop();
    -    if (step instanceof goog.testing.ContinuationTestCase.Step) {
    -      step.clearTimeout();
    -    }
    -  }
    -};
    -
    -
    -
    -/**
    - * Constructs a single step in a larger continuation test. Each step is similar
    - * to a typical TestCase test, except it may wait for an event or timeout to
    - * occur before running the test function.
    - *
    - * @param {string} name The test name.
    - * @param {Function} ref The test function to run.
    - * @param {Object=} opt_scope The object context to run the test in.
    - * @constructor
    - * @extends {goog.testing.TestCase.Test}
    - * @final
    - */
    -goog.testing.ContinuationTestCase.Step = function(name, ref, opt_scope) {
    -  goog.testing.TestCase.Test.call(this, name, ref, opt_scope);
    -};
    -goog.inherits(goog.testing.ContinuationTestCase.Step,
    -              goog.testing.TestCase.Test);
    -
    -
    -/**
    - * Whether the step is currently waiting for a condition to continue. All new
    - * steps begin in wait state.
    - * @type {boolean}
    - */
    -goog.testing.ContinuationTestCase.Step.prototype.waiting = true;
    -
    -
    -/**
    - * A saved reference to window.clearTimeout so that MockClock or other overrides
    - * don't affect continuation timeouts.
    - * @type {Function}
    - * @private
    - */
    -goog.testing.ContinuationTestCase.Step.protectedClearTimeout_ =
    -    window.clearTimeout;
    -
    -
    -/**
    - * A saved reference to window.setTimeout so that MockClock or other overrides
    - * don't affect continuation timeouts.
    - * @type {Function}
    - * @private
    - */
    -goog.testing.ContinuationTestCase.Step.protectedSetTimeout_ = window.setTimeout;
    -
    -
    -/**
    - * Key to this step's timeout. If the step is waiting for an event, the timeout
    - * will be used as a kill timer. If the step is waiting
    - * @type {number}
    - * @private
    - */
    -goog.testing.ContinuationTestCase.Step.prototype.timeout_;
    -
    -
    -/**
    - * Starts a timeout for this step. Each step may have only one timeout active at
    - * a time.
    - * @param {Function} func The function to call after the timeout.
    - * @param {number} duration The number of milliseconds to wait before invoking
    - *     the function.
    - */
    -goog.testing.ContinuationTestCase.Step.prototype.setTimeout =
    -    function(func, duration) {
    -
    -  this.clearTimeout();
    -
    -  var setTimeout = goog.testing.ContinuationTestCase.Step.protectedSetTimeout_;
    -  this.timeout_ = setTimeout(func, duration);
    -};
    -
    -
    -/**
    - * Clears the current timeout if it is active.
    - */
    -goog.testing.ContinuationTestCase.Step.prototype.clearTimeout = function() {
    -  if (this.timeout_) {
    -    var clear = goog.testing.ContinuationTestCase.Step.protectedClearTimeout_;
    -
    -    clear(this.timeout_);
    -    delete this.timeout_;
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/continuationtestcase_test.html b/src/database/third_party/closure-library/closure/goog/testing/continuationtestcase_test.html
    deleted file mode 100644
    index ae11bfbe3ad..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/continuationtestcase_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -Author: brenneman@google.com (Shawn Brenneman)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.testing.ContinuationTestCase
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.ContinuationTestCaseTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/continuationtestcase_test.js b/src/database/third_party/closure-library/closure/goog/testing/continuationtestcase_test.js
    deleted file mode 100644
    index e97a3e269b5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/continuationtestcase_test.js
    +++ /dev/null
    @@ -1,346 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.ContinuationTestCaseTest');
    -goog.setTestOnly('goog.testing.ContinuationTestCaseTest');
    -
    -goog.require('goog.events');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.testing.ContinuationTestCase');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.TestCase');
    -goog.require('goog.testing.jsunit');
    -
    -/**
    - * @fileoverview This test file uses the ContinuationTestCase to test itself,
    - * which is a little confusing. It's also difficult to write a truly effective
    - * test, since testing a failure causes an actual failure in the test runner.
    - * All tests have been manually verified using a sophisticated combination of
    - * alerts and false assertions.
    - */
    -
    -var testCase = new goog.testing.ContinuationTestCase('Continuation Test Case');
    -testCase.autoDiscoverTests();
    -
    -// Standalone Closure Test Runner.
    -if (typeof G_testRunner != 'undefined') {
    -  G_testRunner.initialize(testCase);
    -}
    -
    -
    -var clock = new goog.testing.MockClock();
    -var count = 0;
    -var stubs = new goog.testing.PropertyReplacer();
    -
    -
    -function setUpPage() {
    -  count = testCase.getCount();
    -}
    -
    -
    -/**
    - * Resets the mock clock. Includes a wait step to verify that setUp routines
    - * can contain continuations.
    - */
    -function setUp() {
    -  waitForTimeout(function() {
    -    // Pointless assertion to verify that setUp methods can contain waits.
    -    assertEquals(count, testCase.getCount());
    -  }, 0);
    -
    -  clock.reset();
    -}
    -
    -
    -/**
    - * Uninstalls the mock clock if it was installed, and restores the Step timeout
    - * functions to the default window implementations.
    - */
    -function tearDown() {
    -  clock.uninstall();
    -  stubs.reset();
    -
    -  waitForTimeout(function() {
    -    // Pointless assertion to verify that tearDown methods can contain waits.
    -    assertTrue(testCase.now() >= testCase.startTime_);
    -  }, 0);
    -}
    -
    -
    -/**
    - * Installs the Mock Clock and replaces the Step timeouts with the mock
    - * implementations.
    - */
    -function installMockClock() {
    -  clock.install();
    -
    -  // Overwrite the "protected" setTimeout and clearTimeout with the versions
    -  // replaced by MockClock. Normal tests should never do this, but we need to
    -  // test the ContinuationTest itself.
    -  stubs.set(goog.testing.ContinuationTestCase.Step, 'protectedClearTimeout_',
    -            window.clearTimeout);
    -  stubs.set(goog.testing.ContinuationTestCase.Step, 'protectedSetTimeout_',
    -            window.setTimeout);
    -}
    -
    -
    -/**
    - * @return {goog.testing.ContinuationTestCase.Step} A generic step in a
    - *     continuation test.
    - */
    -function getSampleStep() {
    -  return new goog.testing.ContinuationTestCase.Step('test', function() {});
    -}
    -
    -
    -/**
    - * @return {goog.testing.ContinuationTestCase.Test} A simple continuation test
    - *     with generic setUp, test, and tearDown functions.
    - */
    -function getSampleTest() {
    -  var setupStep = new goog.testing.TestCase.Test('setup', function() {});
    -  var testStep = new goog.testing.TestCase.Test('test', function() {});
    -  var teardownStep = new goog.testing.TestCase.Test('teardown', function() {});
    -
    -  return new goog.testing.ContinuationTestCase.Test(setupStep,
    -                                                    testStep,
    -                                                    teardownStep);
    -}
    -
    -
    -function testStepWaiting() {
    -  var step = getSampleStep();
    -  assertTrue(step.waiting);
    -}
    -
    -
    -function testStepSetTimeout() {
    -  installMockClock();
    -  var step = getSampleStep();
    -
    -  var timeoutReached = false;
    -  step.setTimeout(function() {timeoutReached = true}, 100);
    -
    -  clock.tick(50);
    -  assertFalse(timeoutReached);
    -  clock.tick(50);
    -  assertTrue(timeoutReached);
    -}
    -
    -
    -function testStepClearTimeout() {
    -  var step = new goog.testing.ContinuationTestCase.Step('test', function() {});
    -
    -  var timeoutReached = false;
    -  step.setTimeout(function() {timeoutReached = true}, 100);
    -
    -  clock.tick(50);
    -  assertFalse(timeoutReached);
    -  step.clearTimeout();
    -  clock.tick(50);
    -  assertFalse(timeoutReached);
    -}
    -
    -
    -function testTestPhases() {
    -  var test = getSampleTest();
    -
    -  assertEquals('setup', test.getCurrentPhase()[0].name);
    -  test.cancelCurrentPhase();
    -
    -  assertEquals('test', test.getCurrentPhase()[0].name);
    -  test.cancelCurrentPhase();
    -
    -  assertEquals('teardown', test.getCurrentPhase()[0].name);
    -  test.cancelCurrentPhase();
    -
    -  assertNull(test.getCurrentPhase());
    -}
    -
    -
    -function testTestSetError() {
    -  var test = getSampleTest();
    -
    -  var error1 = new Error('Oh noes!');
    -  var error2 = new Error('B0rken.');
    -
    -  assertNull(test.getError());
    -  test.setError(error1);
    -  assertEquals(error1, test.getError());
    -  test.setError(error2);
    -  assertEquals('Once an error has been set, it should not be overwritten.',
    -               error1, test.getError());
    -}
    -
    -
    -function testAddStep() {
    -  var test = getSampleTest();
    -  var step = getSampleStep();
    -
    -  // Try adding a step to each phase and then cancelling the phase.
    -  for (var i = 0; i < 3; i++) {
    -    assertEquals(1, test.getCurrentPhase().length);
    -    test.addStep(step);
    -
    -    assertEquals(2, test.getCurrentPhase().length);
    -    assertEquals(step, test.getCurrentPhase()[1]);
    -    test.cancelCurrentPhase();
    -  }
    -
    -  assertNull(test.getCurrentPhase());
    -}
    -
    -
    -function testCancelTestPhase() {
    -  var test = getSampleTest();
    -
    -  test.cancelTestPhase();
    -  assertEquals('teardown', test.getCurrentPhase()[0].name);
    -
    -  test = getSampleTest();
    -  test.cancelCurrentPhase();
    -  test.cancelTestPhase();
    -  assertEquals('teardown', test.getCurrentPhase()[0].name);
    -
    -  test = getSampleTest();
    -  test.cancelTestPhase();
    -  test.cancelTestPhase();
    -  assertEquals('teardown', test.getCurrentPhase()[0].name);
    -}
    -
    -
    -function testWaitForTimeout() {
    -  var reachedA = false;
    -  var reachedB = false;
    -  var reachedC = false;
    -
    -  waitForTimeout(function a() {
    -    reachedA = true;
    -
    -    assertTrue('A must be true at callback a.', reachedA);
    -    assertFalse('B must be false at callback a.', reachedB);
    -    assertFalse('C must be false at callback a.', reachedC);
    -  }, 10);
    -
    -  waitForTimeout(function b() {
    -    reachedB = true;
    -
    -    assertTrue('A must be true at callback b.', reachedA);
    -    assertTrue('B must be true at callback b.', reachedB);
    -    assertFalse('C must be false at callback b.', reachedC);
    -  }, 20);
    -
    -  waitForTimeout(function c() {
    -    reachedC = true;
    -
    -    assertTrue('A must be true at callback c.', reachedA);
    -    assertTrue('B must be true at callback c.', reachedB);
    -    assertTrue('C must be true at callback c.', reachedC);
    -  }, 20);
    -
    -  assertFalse('a', reachedA);
    -  assertFalse('b', reachedB);
    -  assertFalse('c', reachedC);
    -}
    -
    -
    -function testWaitForEvent() {
    -  var et = new goog.events.EventTarget();
    -
    -  var eventFired = false;
    -  goog.events.listen(et, 'testPrefire', function() {
    -    eventFired = true;
    -    et.dispatchEvent('test');
    -  });
    -
    -  waitForEvent(et, 'test', function() {
    -    assertTrue(eventFired);
    -  });
    -
    -  et.dispatchEvent('testPrefire');
    -}
    -
    -
    -function testWaitForCondition() {
    -  var counter = 0;
    -
    -  waitForCondition(function() {
    -    return ++counter >= 2;
    -  }, function() {
    -    assertEquals(2, counter);
    -  }, 10, 200);
    -}
    -
    -
    -function testOutOfOrderWaits() {
    -  var counter = 0;
    -
    -  // Note that if the delta between the timeout is too small, two
    -  // continuation may be invoked at the same timer tick, using the
    -  // registration order.
    -  waitForTimeout(function() {assertEquals(3, ++counter);}, 200);
    -  waitForTimeout(function() {assertEquals(1, ++counter);}, 0);
    -  waitForTimeout(function() {assertEquals(2, ++counter);}, 100);
    -}
    -
    -
    -/*
    - * Any of the test functions below (except the condition check passed into
    - * waitForCondition) can raise an assertion successfully. Any level of nested
    - * test steps should be possible, in any configuration.
    - */
    -
    -var testObj;
    -
    -
    -function testCrazyNestedWaitFunction() {
    -  testObj = {
    -    lock: true,
    -    et: new goog.events.EventTarget(),
    -    steps: 0
    -  };
    -
    -  waitForTimeout(handleTimeout, 10);
    -  waitForEvent(testObj.et, 'test', handleEvent);
    -  waitForCondition(condition, handleCondition, 1);
    -}
    -
    -function handleTimeout() {
    -  testObj.steps++;
    -  assertEquals('handleTimeout should be called first.', 1, testObj.steps);
    -  waitForTimeout(fireEvent, 10);
    -}
    -
    -function fireEvent() {
    -  testObj.steps++;
    -  assertEquals('fireEvent should be called second.', 2, testObj.steps);
    -  testObj.et.dispatchEvent('test');
    -}
    -
    -function handleEvent() {
    -  testObj.steps++;
    -  assertEquals('handleEvent should be called third.', 3, testObj.steps);
    -  testObj.lock = false;
    -}
    -
    -function condition() {
    -  return !testObj.lock;
    -}
    -
    -function handleCondition() {
    -  assertFalse(testObj.lock);
    -  testObj.steps++;
    -  assertEquals('handleCondition should be called last.', 4, testObj.steps);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/deferredtestcase.js b/src/database/third_party/closure-library/closure/goog/testing/deferredtestcase.js
    deleted file mode 100644
    index e903efdc184..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/deferredtestcase.js
    +++ /dev/null
    @@ -1,154 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Defines DeferredTestCase class. By calling waitForDeferred(),
    - * tests in DeferredTestCase can wait for a Deferred object to complete its
    - * callbacks before continuing to the next test.
    - *
    - * Example Usage:
    - *
    - *   var deferredTestCase = goog.testing.DeferredTestCase.createAndInstall();
    - *   // Optionally, set a longer-than-usual step timeout.
    - *   deferredTestCase.stepTimeout = 15 * 1000; // 15 seconds
    - *
    - *   function testDeferredCallbacks() {
    - *     var callbackTime = goog.now();
    - *     var callbacks = new goog.async.Deferred();
    - *     deferredTestCase.addWaitForAsync('Waiting for 1st callback', callbacks);
    - *     callbacks.addCallback(
    - *         function() {
    - *           assertTrue(
    - *               'We\'re going back in time!', goog.now() >= callbackTime);
    - *           callbackTime = goog.now();
    - *         });
    - *     deferredTestCase.addWaitForAsync('Waiting for 2nd callback', callbacks);
    - *     callbacks.addCallback(
    - *         function() {
    - *           assertTrue(
    - *               'We\'re going back in time!', goog.now() >= callbackTime);
    - *           callbackTime = goog.now();
    - *         });
    - *     deferredTestCase.addWaitForAsync('Waiting for last callback', callbacks);
    - *     callbacks.addCallback(
    - *         function() {
    - *           assertTrue(
    - *               'We\'re going back in time!', goog.now() >= callbackTime);
    - *           callbackTime = goog.now();
    - *         });
    - *
    - *     deferredTestCase.waitForDeferred(callbacks);
    - *   }
    - *
    - * Note that DeferredTestCase still preserves the functionality of
    - * AsyncTestCase.
    - *
    - * @see.goog.async.Deferred
    - * @see goog.testing.AsyncTestCase
    - */
    -
    -goog.provide('goog.testing.DeferredTestCase');
    -
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.TestCase');
    -
    -
    -
    -/**
    - * A test case that can asynchronously wait on a Deferred object.
    - * @param {string=} opt_name A descriptive name for the test case.
    - * @constructor
    - * @extends {goog.testing.AsyncTestCase}
    - */
    -goog.testing.DeferredTestCase = function(opt_name) {
    -  goog.testing.AsyncTestCase.call(this, opt_name);
    -};
    -goog.inherits(goog.testing.DeferredTestCase, goog.testing.AsyncTestCase);
    -
    -
    -/**
    - * Preferred way of creating a DeferredTestCase. Creates one and initializes it
    - * with the G_testRunner.
    - * @param {string=} opt_name A descriptive name for the test case.
    - * @return {!goog.testing.DeferredTestCase} The created DeferredTestCase.
    - */
    -goog.testing.DeferredTestCase.createAndInstall = function(opt_name) {
    -  var deferredTestCase = new goog.testing.DeferredTestCase(opt_name);
    -  goog.testing.TestCase.initializeTestRunner(deferredTestCase);
    -  return deferredTestCase;
    -};
    -
    -
    -/**
    - * Handler for when the test produces an error.
    - * @param {Error|string} err The error object.
    - * @protected
    - * @throws Always throws a ControlBreakingException.
    - */
    -goog.testing.DeferredTestCase.prototype.onError = function(err) {
    -  this.doAsyncError(err);
    -};
    -
    -
    -/**
    - * Handler for when the test succeeds.
    - * @protected
    - */
    -goog.testing.DeferredTestCase.prototype.onSuccess = function() {
    -  this.continueTesting();
    -};
    -
    -
    -/**
    - * Adds a callback to update the wait message of this async test case. Using
    - * this method generously also helps to document the test flow.
    - * @param {string} msg The update wait status message.
    - * @param {goog.async.Deferred} d The deferred object to add the waitForAsync
    - *     callback to.
    - * @see goog.testing.AsyncTestCase#waitForAsync
    - */
    -goog.testing.DeferredTestCase.prototype.addWaitForAsync = function(msg, d) {
    -  d.addCallback(goog.bind(this.waitForAsync, this, msg));
    -};
    -
    -
    -/**
    - * Wires up given Deferred object to the test case, then starts the
    - * goog.async.Deferred object's callback.
    - * @param {!string|goog.async.Deferred} a The wait status message or the
    - *     deferred object to wait for.
    - * @param {goog.async.Deferred=} opt_b The deferred object to wait for.
    - */
    -goog.testing.DeferredTestCase.prototype.waitForDeferred = function(a, opt_b) {
    -  var waitMsg;
    -  var deferred;
    -  switch (arguments.length) {
    -    case 1:
    -      deferred = a;
    -      waitMsg = null;
    -      break;
    -    case 2:
    -      deferred = opt_b;
    -      waitMsg = a;
    -      break;
    -    default: // Shouldn't be here in compiled mode
    -      throw Error('Invalid number of arguments');
    -  }
    -  deferred.addCallbacks(this.onSuccess, this.onError, this);
    -  if (!waitMsg) {
    -    waitMsg = 'Waiting for deferred in ' + this.getCurrentStepName();
    -  }
    -  this.waitForAsync( /** @type {!string} */ (waitMsg));
    -  deferred.callback(true);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/deferredtestcase_test.html b/src/database/third_party/closure-library/closure/goog/testing/deferredtestcase_test.html
    deleted file mode 100644
    index d5fbd690626..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/deferredtestcase_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.testing.DeferredTestCase Asyncronous Tests
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.DeferredTestCaseTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/deferredtestcase_test.js b/src/database/third_party/closure-library/closure/goog/testing/deferredtestcase_test.js
    deleted file mode 100644
    index d0fd47200e7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/deferredtestcase_test.js
    +++ /dev/null
    @@ -1,137 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.DeferredTestCaseTest');
    -goog.setTestOnly('goog.testing.DeferredTestCaseTest');
    -
    -goog.require('goog.async.Deferred');
    -goog.require('goog.testing.DeferredTestCase');
    -goog.require('goog.testing.TestCase');
    -goog.require('goog.testing.TestRunner');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -
    -var deferredTestCase =
    -    goog.testing.DeferredTestCase.createAndInstall(document.title);
    -var testTestCase;
    -var runner;
    -
    -// Optionally, set a longer-than-usual step timeout.
    -deferredTestCase.stepTimeout = 15 * 1000; // 15 seconds
    -
    -// This is the sample code in deferredtestcase.js
    -function testDeferredCallbacks() {
    -  var callbackTime = goog.now();
    -  var callbacks = new goog.async.Deferred();
    -  deferredTestCase.addWaitForAsync('Waiting for 1st callback', callbacks);
    -  callbacks.addCallback(
    -      function() {
    -        assertTrue(
    -            'We\'re going back in time!', goog.now() >= callbackTime);
    -        callbackTime = goog.now();
    -      });
    -  deferredTestCase.addWaitForAsync('Waiting for 2nd callback', callbacks);
    -  callbacks.addCallback(
    -      function() {
    -        assertTrue(
    -            'We\'re going back in time!', goog.now() >= callbackTime);
    -        callbackTime = goog.now();
    -      });
    -  deferredTestCase.addWaitForAsync('Waiting for last callback', callbacks);
    -  callbacks.addCallback(
    -      function() {
    -        assertTrue(
    -            'We\'re going back in time!', goog.now() >= callbackTime);
    -        callbackTime = goog.now();
    -      });
    -
    -  deferredTestCase.waitForDeferred(callbacks);
    -}
    -
    -function createDeferredTestCase(d) {
    -  testTestCase = new goog.testing.DeferredTestCase('Foobar TestCase');
    -  testTestCase.add(new goog.testing.TestCase.Test(
    -      'Foobar Test',
    -      function() {
    -        this.waitForDeferred(d);
    -      },
    -      testTestCase));
    -
    -  var testCompleteCallback = new goog.async.Deferred();
    -  testTestCase.setCompletedCallback(
    -      function() {
    -        testCompleteCallback.callback(true);
    -      });
    -
    -  // We're not going to use the runner to run the test, but we attach one
    -  // here anyway because without a runner TestCase throws an exception in
    -  // finalize().
    -  var runner = new goog.testing.TestRunner();
    -  runner.initialize(testTestCase);
    -
    -  return testCompleteCallback;
    -}
    -
    -function testDeferredWait() {
    -  var d = new goog.async.Deferred();
    -  deferredTestCase.addWaitForAsync('Foobar', d);
    -  d.addCallback(function() {
    -    return goog.async.Deferred.succeed(true);
    -  });
    -  deferredTestCase.waitForDeferred(d);
    -}
    -
    -function testNonAsync() {
    -  assertTrue(true);
    -}
    -
    -function testPassWithTestRunner() {
    -  var d = new goog.async.Deferred();
    -  d.addCallback(function() {
    -    return goog.async.Deferred.succeed(true);
    -  });
    -
    -  var testCompleteDeferred = createDeferredTestCase(d);
    -  testTestCase.execute();
    -
    -  var deferredCallbackOnPass = new goog.async.Deferred();
    -  deferredCallbackOnPass.addCallback(function() {
    -    return testCompleteDeferred;
    -  });
    -  deferredCallbackOnPass.addCallback(function() {
    -    assertTrue('Test case should have succeded.', testTestCase.isSuccess());
    -  });
    -
    -  deferredTestCase.waitForDeferred(deferredCallbackOnPass);
    -}
    -
    -function testFailWithTestRunner() {
    -  var d = new goog.async.Deferred();
    -  d.addCallback(function() {
    -    return goog.async.Deferred.fail(true);
    -  });
    -
    -  var testCompleteDeferred = createDeferredTestCase(d);
    -
    -  // Mock doAsyncError to instead let the test completes successfully,
    -  // but record the failure. The test works as is because the failing
    -  // deferred is not actually asynchronous.
    -  var mockDoAsyncError = goog.testing.recordFunction(function() {
    -    testTestCase.continueTesting();
    -  });
    -  testTestCase.doAsyncError = mockDoAsyncError;
    -
    -  testTestCase.execute();
    -  assertEquals(1, mockDoAsyncError.getCallCount());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/dom.js b/src/database/third_party/closure-library/closure/goog/testing/dom.js
    deleted file mode 100644
    index 8b00106d7e0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/dom.js
    +++ /dev/null
    @@ -1,624 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Testing utilities for DOM related tests.
    - *
    - * @author robbyw@google.com (Robby Walker)
    - */
    -
    -goog.provide('goog.testing.dom');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.NodeIterator');
    -goog.require('goog.dom.NodeType');
    -goog.require('goog.dom.TagIterator');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.iter');
    -goog.require('goog.object');
    -goog.require('goog.string');
    -goog.require('goog.style');
    -goog.require('goog.testing.asserts');
    -goog.require('goog.userAgent');
    -
    -
    -/**
    - * @return {!Node} A DIV node with a unique ID identifying the
    - *     {@code END_TAG_MARKER_}.
    - * @private
    - */
    -goog.testing.dom.createEndTagMarker_ = function() {
    -  var marker = goog.dom.createElement(goog.dom.TagName.DIV);
    -  marker.id = goog.getUid(marker);
    -  return marker;
    -};
    -
    -
    -/**
    - * A unique object to use as an end tag marker.
    - * @private {!Node}
    - * @const
    - */
    -goog.testing.dom.END_TAG_MARKER_ = goog.testing.dom.createEndTagMarker_();
    -
    -
    -/**
    - * Tests if the given iterator over nodes matches the given Array of node
    - * descriptors.  Throws an error if any match fails.
    - * @param {goog.iter.Iterator} it  An iterator over nodes.
    - * @param {Array<Node|number|string>} array Array of node descriptors to match
    - *     against.  Node descriptors can be any of the following:
    - *         Node: Test if the two nodes are equal.
    - *         number: Test node.nodeType == number.
    - *         string starting with '#': Match the node's id with the text
    - *             after "#".
    - *         other string: Match the text node's contents.
    - */
    -goog.testing.dom.assertNodesMatch = function(it, array) {
    -  var i = 0;
    -  goog.iter.forEach(it, function(node) {
    -    if (array.length <= i) {
    -      fail('Got more nodes than expected: ' + goog.testing.dom.describeNode_(
    -          node));
    -    }
    -    var expected = array[i];
    -
    -    if (goog.dom.isNodeLike(expected)) {
    -      assertEquals('Nodes should match at position ' + i, expected, node);
    -    } else if (goog.isNumber(expected)) {
    -      assertEquals('Node types should match at position ' + i, expected,
    -          node.nodeType);
    -    } else if (expected.charAt(0) == '#') {
    -      assertEquals('Expected element at position ' + i,
    -          goog.dom.NodeType.ELEMENT, node.nodeType);
    -      var expectedId = expected.substr(1);
    -      assertEquals('IDs should match at position ' + i,
    -          expectedId, node.id);
    -
    -    } else {
    -      assertEquals('Expected text node at position ' + i,
    -          goog.dom.NodeType.TEXT, node.nodeType);
    -      assertEquals('Node contents should match at position ' + i,
    -          expected, node.nodeValue);
    -    }
    -
    -    i++;
    -  });
    -
    -  assertEquals('Used entire match array', array.length, i);
    -};
    -
    -
    -/**
    - * Exposes a node as a string.
    - * @param {Node} node A node.
    - * @return {string} A string representation of the node.
    - */
    -goog.testing.dom.exposeNode = function(node) {
    -  return (node.tagName || node.nodeValue) + (node.id ? '#' + node.id : '') +
    -      ':"' + (node.innerHTML || '') + '"';
    -};
    -
    -
    -/**
    - * Exposes the nodes of a range wrapper as a string.
    - * @param {goog.dom.AbstractRange} range A range.
    - * @return {string} A string representation of the range.
    - */
    -goog.testing.dom.exposeRange = function(range) {
    -  // This is deliberately not implemented as
    -  // goog.dom.AbstractRange.prototype.toString, because it is non-authoritative.
    -  // Two equivalent ranges may have very different exposeRange values, and
    -  // two different ranges may have equal exposeRange values.
    -  // (The mapping of ranges to DOM nodes/offsets is a many-to-many mapping).
    -  if (!range) {
    -    return 'null';
    -  }
    -  return goog.testing.dom.exposeNode(range.getStartNode()) + ':' +
    -         range.getStartOffset() + ' to ' +
    -         goog.testing.dom.exposeNode(range.getEndNode()) + ':' +
    -         range.getEndOffset();
    -};
    -
    -
    -/**
    - * Determines if the current user agent matches the specified string.  Returns
    - * false if the string does specify at least one user agent but does not match
    - * the running agent.
    - * @param {string} userAgents Space delimited string of user agents.
    - * @return {boolean} Whether the user agent was matched.  Also true if no user
    - *     agent was listed in the expectation string.
    - * @private
    - */
    -goog.testing.dom.checkUserAgents_ = function(userAgents) {
    -  if (goog.string.startsWith(userAgents, '!')) {
    -    if (goog.string.contains(userAgents, ' ')) {
    -      throw new Error('Only a single negative user agent may be specified');
    -    }
    -    return !goog.userAgent[userAgents.substr(1)];
    -  }
    -
    -  var agents = userAgents.split(' ');
    -  var hasUserAgent = false;
    -  for (var i = 0, len = agents.length; i < len; i++) {
    -    var cls = agents[i];
    -    if (cls in goog.userAgent) {
    -      hasUserAgent = true;
    -      if (goog.userAgent[cls]) {
    -        return true;
    -      }
    -    }
    -  }
    -  // If we got here, there was a user agent listed but we didn't match it.
    -  return !hasUserAgent;
    -};
    -
    -
    -/**
    - * Map function that converts end tags to a specific object.
    - * @param {Node} node The node to map.
    - * @param {undefined} ignore Always undefined.
    - * @param {!goog.iter.Iterator<Node>} iterator The iterator.
    - * @return {Node} The resulting iteration item.
    - * @private
    - */
    -goog.testing.dom.endTagMap_ = function(node, ignore, iterator) {
    -  return iterator.isEndTag() ? goog.testing.dom.END_TAG_MARKER_ : node;
    -};
    -
    -
    -/**
    - * Check if the given node is important.  A node is important if it is a
    - * non-empty text node, a non-annotated element, or an element annotated to
    - * match on this user agent.
    - * @param {Node} node The node to test.
    - * @return {boolean} Whether this node should be included for iteration.
    - * @private
    - */
    -goog.testing.dom.nodeFilter_ = function(node) {
    -  if (node.nodeType == goog.dom.NodeType.TEXT) {
    -    // If a node is part of a string of text nodes and it has spaces in it,
    -    // we allow it since it's going to affect the merging of nodes done below.
    -    if (goog.string.isBreakingWhitespace(node.nodeValue) &&
    -        (!node.previousSibling ||
    -             node.previousSibling.nodeType != goog.dom.NodeType.TEXT) &&
    -        (!node.nextSibling ||
    -             node.nextSibling.nodeType != goog.dom.NodeType.TEXT)) {
    -      return false;
    -    }
    -    // Allow optional text to be specified as [[BROWSER1 BROWSER2]]Text
    -    var match = node.nodeValue.match(/^\[\[(.+)\]\]/);
    -    if (match) {
    -      return goog.testing.dom.checkUserAgents_(match[1]);
    -    }
    -  } else if (node.className && goog.isString(node.className)) {
    -    return goog.testing.dom.checkUserAgents_(node.className);
    -  }
    -  return true;
    -};
    -
    -
    -/**
    - * Determines the text to match from the given node, removing browser
    - * specification strings.
    - * @param {Node} node The node expected to match.
    - * @return {string} The text, stripped of browser specification strings.
    - * @private
    - */
    -goog.testing.dom.getExpectedText_ = function(node) {
    -  // Strip off the browser specifications.
    -  return node.nodeValue.match(/^(\[\[.+\]\])?(.*)/)[2];
    -};
    -
    -
    -/**
    - * Describes the given node.
    - * @param {Node} node The node to describe.
    - * @return {string} A description of the node.
    - * @private
    - */
    -goog.testing.dom.describeNode_ = function(node) {
    -  if (node.nodeType == goog.dom.NodeType.TEXT) {
    -    return '[Text: ' + node.nodeValue + ']';
    -  } else {
    -    return '<' + node.tagName + (node.id ? ' #' + node.id : '') + ' .../>';
    -  }
    -};
    -
    -
    -/**
    - * Assert that the html in {@code actual} is substantially similar to
    - * htmlPattern.  This method tests for the same set of styles, for the same
    - * order of nodes, and the presence of attributes.  Breaking whitespace nodes
    - * are ignored.  Elements can be
    - * annotated with classnames corresponding to keys in goog.userAgent and will be
    - * expected to show up in that user agent and expected not to show up in
    - * others.
    - * @param {string} htmlPattern The pattern to match.
    - * @param {!Node} actual The element to check: its contents are matched
    - *     against the HTML pattern.
    - * @param {boolean=} opt_strictAttributes If false, attributes that appear in
    - *     htmlPattern must be in actual, but actual can have attributes not
    - *     present in htmlPattern.  If true, htmlPattern and actual must have the
    - *     same set of attributes.  Default is false.
    - */
    -goog.testing.dom.assertHtmlContentsMatch = function(htmlPattern, actual,
    -    opt_strictAttributes) {
    -  var div = goog.dom.createDom(goog.dom.TagName.DIV);
    -  div.innerHTML = htmlPattern;
    -
    -  var errorSuffix = '\nExpected\n' + htmlPattern + '\nActual\n' +
    -      actual.innerHTML;
    -
    -  var actualIt = goog.iter.filter(
    -      goog.iter.map(new goog.dom.TagIterator(actual),
    -          goog.testing.dom.endTagMap_),
    -      goog.testing.dom.nodeFilter_);
    -
    -  var expectedIt = goog.iter.filter(new goog.dom.NodeIterator(div),
    -      goog.testing.dom.nodeFilter_);
    -
    -  var actualNode;
    -  var preIterated = false;
    -  var advanceActualNode = function() {
    -    // If the iterator has already been advanced, don't advance it again.
    -    if (!preIterated) {
    -      actualNode = /** @type {Node} */ (goog.iter.nextOrValue(actualIt, null));
    -    }
    -    preIterated = false;
    -
    -    // Advance the iterator so long as it is return end tags.
    -    while (actualNode == goog.testing.dom.END_TAG_MARKER_) {
    -      actualNode = /** @type {Node} */ (goog.iter.nextOrValue(actualIt, null));
    -    }
    -  };
    -
    -  // HACK(brenneman): IE has unique ideas about whitespace handling when setting
    -  // innerHTML. This results in elision of leading whitespace in the expected
    -  // nodes where doing so doesn't affect visible rendering. As a workaround, we
    -  // remove the leading whitespace in the actual nodes where necessary.
    -  //
    -  // The collapsible variable tracks whether we should collapse the whitespace
    -  // in the next Text node we encounter.
    -  var IE_TEXT_COLLAPSE =
    -      goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9');
    -
    -  var collapsible = true;
    -
    -  var number = 0;
    -  goog.iter.forEach(expectedIt, function(expectedNode) {
    -    expectedNode = /** @type {Node} */ (expectedNode);
    -
    -    advanceActualNode();
    -    assertNotNull('Finished actual HTML before finishing expected HTML at ' +
    -                  'node number ' + number + ': ' +
    -                  goog.testing.dom.describeNode_(expectedNode) + errorSuffix,
    -                  actualNode);
    -
    -    // Do no processing for expectedNode == div.
    -    if (expectedNode == div) {
    -      return;
    -    }
    -
    -    assertEquals('Should have the same node type, got ' +
    -        goog.testing.dom.describeNode_(actualNode) + ' but expected ' +
    -        goog.testing.dom.describeNode_(expectedNode) + '.' + errorSuffix,
    -        expectedNode.nodeType, actualNode.nodeType);
    -
    -    if (expectedNode.nodeType == goog.dom.NodeType.ELEMENT) {
    -      var expectedElem = goog.asserts.assertElement(expectedNode);
    -      var actualElem = goog.asserts.assertElement(actualNode);
    -
    -      assertEquals('Tag names should match' + errorSuffix,
    -          expectedElem.tagName, actualElem.tagName);
    -      assertObjectEquals('Should have same styles' + errorSuffix,
    -          goog.style.parseStyleAttribute(expectedElem.style.cssText),
    -          goog.style.parseStyleAttribute(actualElem.style.cssText));
    -      goog.testing.dom.assertAttributesEqual_(errorSuffix, expectedElem,
    -          actualElem, !!opt_strictAttributes);
    -
    -      if (IE_TEXT_COLLAPSE &&
    -          goog.style.getCascadedStyle(actualElem, 'display') != 'inline') {
    -        // Text may be collapsed after any non-inline element.
    -        collapsible = true;
    -      }
    -    } else {
    -      // Concatenate text nodes until we reach a non text node.
    -      var actualText = actualNode.nodeValue;
    -      preIterated = true;
    -      while ((actualNode = /** @type {Node} */
    -              (goog.iter.nextOrValue(actualIt, null))) &&
    -          actualNode.nodeType == goog.dom.NodeType.TEXT) {
    -        actualText += actualNode.nodeValue;
    -      }
    -
    -      if (IE_TEXT_COLLAPSE) {
    -        // Collapse the leading whitespace, unless the string consists entirely
    -        // of whitespace.
    -        if (collapsible && !goog.string.isEmptyOrWhitespace(actualText)) {
    -          actualText = goog.string.trimLeft(actualText);
    -        }
    -        // Prepare to collapse whitespace in the next Text node if this one does
    -        // not end in a whitespace character.
    -        collapsible = /\s$/.test(actualText);
    -      }
    -
    -      var expectedText = goog.testing.dom.getExpectedText_(expectedNode);
    -      if ((actualText && !goog.string.isBreakingWhitespace(actualText)) ||
    -          (expectedText && !goog.string.isBreakingWhitespace(expectedText))) {
    -        var normalizedActual = actualText.replace(/\s+/g, ' ');
    -        var normalizedExpected = expectedText.replace(/\s+/g, ' ');
    -
    -        assertEquals('Text should match' + errorSuffix, normalizedExpected,
    -            normalizedActual);
    -      }
    -    }
    -
    -    number++;
    -  });
    -
    -  advanceActualNode();
    -  assertNull('Finished expected HTML before finishing actual HTML' +
    -      errorSuffix, goog.iter.nextOrValue(actualIt, null));
    -};
    -
    -
    -/**
    - * Assert that the html in {@code actual} is substantially similar to
    - * htmlPattern.  This method tests for the same set of styles, and for the same
    - * order of nodes.  Breaking whitespace nodes are ignored.  Elements can be
    - * annotated with classnames corresponding to keys in goog.userAgent and will be
    - * expected to show up in that user agent and expected not to show up in
    - * others.
    - * @param {string} htmlPattern The pattern to match.
    - * @param {string} actual The html to check.
    - */
    -goog.testing.dom.assertHtmlMatches = function(htmlPattern, actual) {
    -  var div = goog.dom.createDom(goog.dom.TagName.DIV);
    -  div.innerHTML = actual;
    -
    -  goog.testing.dom.assertHtmlContentsMatch(htmlPattern, div);
    -};
    -
    -
    -/**
    - * Finds the first text node descendant of root with the given content.  Note
    - * that this operates on a text node level, so if text nodes get split this
    - * may not match the user visible text.  Using normalize() may help here.
    - * @param {string|RegExp} textOrRegexp The text to find, or a regular
    - *     expression to find a match of.
    - * @param {Element} root The element to search in.
    - * @return {Node} The first text node that matches, or null if none is found.
    - */
    -goog.testing.dom.findTextNode = function(textOrRegexp, root) {
    -  var it = new goog.dom.NodeIterator(root);
    -  var ret = goog.iter.nextOrValue(goog.iter.filter(it, function(node) {
    -    if (node.nodeType == goog.dom.NodeType.TEXT) {
    -      if (goog.isString(textOrRegexp)) {
    -        return node.nodeValue == textOrRegexp;
    -      } else {
    -        return !!node.nodeValue.match(textOrRegexp);
    -      }
    -    } else {
    -      return false;
    -    }
    -  }), null);
    -  return /** @type {Node} */ (ret);
    -};
    -
    -
    -/**
    - * Assert the end points of a range.
    - *
    - * Notice that "Are two ranges visually identical?" and "Do two ranges have
    - * the same endpoint?" are independent questions. Two visually identical ranges
    - * may have different endpoints. And two ranges with the same endpoints may
    - * be visually different.
    - *
    - * @param {Node} start The expected start node.
    - * @param {number} startOffset The expected start offset.
    - * @param {Node} end The expected end node.
    - * @param {number} endOffset The expected end offset.
    - * @param {goog.dom.AbstractRange} range The actual range.
    - */
    -goog.testing.dom.assertRangeEquals = function(start, startOffset, end,
    -    endOffset, range) {
    -  assertEquals('Unexpected start node', start, range.getStartNode());
    -  assertEquals('Unexpected end node', end, range.getEndNode());
    -  assertEquals('Unexpected start offset', startOffset, range.getStartOffset());
    -  assertEquals('Unexpected end offset', endOffset, range.getEndOffset());
    -};
    -
    -
    -/**
    - * Gets the value of a DOM attribute in deterministic way.
    - * @param {!Node} node A node.
    - * @param {string} name Attribute name.
    - * @return {*} Attribute value.
    - * @private
    - */
    -goog.testing.dom.getAttributeValue_ = function(node, name) {
    -  // These hacks avoid nondetermistic results in the following cases:
    -  // IE7: document.createElement('input').height returns a random number.
    -  // FF3: getAttribute('disabled') returns different value for <div disabled="">
    -  //      and <div disabled="disabled">
    -  // WebKit: Two radio buttons with the same name can't be checked at the same
    -  //      time, even if only one of them is in the document.
    -  if (goog.userAgent.WEBKIT && node.tagName == 'INPUT' &&
    -      node['type'] == 'radio' && name == 'checked') {
    -    return false;
    -  }
    -  return goog.isDef(node[name]) &&
    -      typeof node.getAttribute(name) != typeof node[name] ?
    -      node[name] : node.getAttribute(name);
    -};
    -
    -
    -/**
    - * Assert that the attributes of two Nodes are the same (ignoring any
    - * instances of the style attribute).
    - * @param {string} errorSuffix String to add to end of error messages.
    - * @param {!Element} expectedElem The element whose attributes we are expecting.
    - * @param {!Element} actualElem The element with the actual attributes.
    - * @param {boolean} strictAttributes If false, attributes that appear in
    - *     expectedNode must also be in actualNode, but actualNode can have
    - *     attributes not present in expectedNode.  If true, expectedNode and
    - *     actualNode must have the same set of attributes.
    - * @private
    - */
    -goog.testing.dom.assertAttributesEqual_ = function(errorSuffix,
    -    expectedElem, actualElem, strictAttributes) {
    -  if (strictAttributes) {
    -    goog.testing.dom.compareClassAttribute_(expectedElem, actualElem);
    -  }
    -
    -  var expectedAttributes = expectedElem.attributes;
    -  var actualAttributes = actualElem.attributes;
    -
    -  for (var i = 0, len = expectedAttributes.length; i < len; i++) {
    -    var expectedName = expectedAttributes[i].name;
    -    var expectedValue = goog.testing.dom.getAttributeValue_(expectedElem,
    -        expectedName);
    -
    -    var actualAttribute = actualAttributes[expectedName];
    -    var actualValue = goog.testing.dom.getAttributeValue_(actualElem,
    -        expectedName);
    -
    -    // IE enumerates attribute names in the expected node that are not present,
    -    // causing an undefined actualAttribute.
    -    if (!expectedValue && !actualValue) {
    -      continue;
    -    }
    -
    -    if (expectedName == 'id' && goog.userAgent.IE) {
    -      goog.testing.dom.compareIdAttributeForIe_(
    -          /** @type {string} */ (expectedValue), actualAttribute,
    -          strictAttributes, errorSuffix);
    -      continue;
    -    }
    -
    -    if (goog.testing.dom.ignoreAttribute_(expectedName)) {
    -      continue;
    -    }
    -
    -    assertNotUndefined('Expected to find attribute with name ' +
    -        expectedName + ', in element ' +
    -        goog.testing.dom.describeNode_(actualElem) + errorSuffix,
    -        actualAttribute);
    -    assertEquals('Expected attribute ' + expectedName +
    -        ' has a different value ' + errorSuffix,
    -        expectedValue,
    -        goog.testing.dom.getAttributeValue_(actualElem, actualAttribute.name));
    -  }
    -
    -  if (strictAttributes) {
    -    for (i = 0; i < actualAttributes.length; i++) {
    -      var actualName = actualAttributes[i].name;
    -      var actualAttribute = actualAttributes.getNamedItem(actualName);
    -
    -      if (!actualAttribute || goog.testing.dom.ignoreAttribute_(actualName)) {
    -        continue;
    -      }
    -
    -      assertNotUndefined('Unexpected attribute with name ' +
    -          actualName + ' in element ' +
    -          goog.testing.dom.describeNode_(actualElem) + errorSuffix,
    -          expectedAttributes[actualName]);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Assert the class attribute of actualElem is the same as the one in
    - * expectedElem, ignoring classes that are useragents.
    - * @param {!Element} expectedElem The DOM element whose class we expect.
    - * @param {!Element} actualElem The DOM element with the actual class.
    - * @private
    - */
    -goog.testing.dom.compareClassAttribute_ = function(expectedElem,
    -    actualElem) {
    -  var classes = goog.dom.classlist.get(expectedElem);
    -
    -  var expectedClasses = [];
    -  for (var i = 0, len = classes.length; i < len; i++) {
    -    if (!(classes[i] in goog.userAgent)) {
    -      expectedClasses.push(classes[i]);
    -    }
    -  }
    -  expectedClasses.sort();
    -
    -  var actualClasses = goog.array.toArray(goog.dom.classlist.get(actualElem));
    -  actualClasses.sort();
    -
    -  assertArrayEquals(
    -      'Expected class was: ' + expectedClasses.join(' ') +
    -      ', but actual class was: ' + actualElem.className,
    -      expectedClasses, actualClasses);
    -};
    -
    -
    -/**
    - * Set of attributes IE adds to elements randomly.
    - * @type {Object}
    - * @private
    - */
    -goog.testing.dom.BAD_IE_ATTRIBUTES_ = goog.object.createSet(
    -    'methods', 'CHECKED', 'dataFld', 'dataFormatAs', 'dataSrc');
    -
    -
    -/**
    - * Whether to ignore the attribute.
    - * @param {string} name Name of the attribute.
    - * @return {boolean} True if the attribute should be ignored.
    - * @private
    - */
    -goog.testing.dom.ignoreAttribute_ = function(name) {
    -  if (name == 'style' || name == 'class') {
    -    return true;
    -  }
    -  return goog.userAgent.IE && goog.testing.dom.BAD_IE_ATTRIBUTES_[name];
    -};
    -
    -
    -/**
    - * Compare id attributes for IE.  In IE, if an element lacks an id attribute
    - * in the original HTML, the element object will still have such an attribute,
    - * but its value will be the empty string.
    - * @param {string} expectedValue The expected value of the id attribute.
    - * @param {Attr} actualAttribute The actual id attribute.
    - * @param {boolean} strictAttributes Whether strict attribute checking should be
    - *     done.
    - * @param {string} errorSuffix String to append to error messages.
    - * @private
    - */
    -goog.testing.dom.compareIdAttributeForIe_ = function(expectedValue,
    -    actualAttribute, strictAttributes, errorSuffix) {
    -  if (expectedValue === '') {
    -    if (strictAttributes) {
    -      assertTrue('Unexpected attribute with name id in element ' +
    -          errorSuffix, actualAttribute.value == '');
    -    }
    -  } else {
    -    assertNotUndefined('Expected to find attribute with name id, in element ' +
    -        errorSuffix, actualAttribute);
    -    assertNotEquals('Expected to find attribute with name id, in element ' +
    -        errorSuffix, '', actualAttribute.value);
    -    assertEquals('Expected attribute has a different value ' + errorSuffix,
    -        expectedValue, actualAttribute.value);
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/dom_test.html b/src/database/third_party/closure-library/closure/goog/testing/dom_test.html
    deleted file mode 100644
    index 92bed453c12..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/dom_test.html
    +++ /dev/null
    @@ -1,28 +0,0 @@
    -<!DOCTYPE html>
    -<html lang="en" dir="ltr">
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <!--
    -This test has not yet been updated to run on IE8. See http://b/hotlist?id=36311
    --->
    -  <!--meta http-equiv="X-UA-Compatible" content="IE=edge"-->
    -  <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
    -  <title>
    -   Closure Unit Tests - goog.testing.dom
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.domTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="root">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/dom_test.js b/src/database/third_party/closure-library/closure/goog/testing/dom_test.js
    deleted file mode 100644
    index 5d075a88016..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/dom_test.js
    +++ /dev/null
    @@ -1,434 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.domTest');
    -goog.setTestOnly('goog.testing.domTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.testing.dom');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -var root;
    -function setUpPage() {
    -  root = goog.dom.getElement('root');
    -}
    -
    -function setUp() {
    -  root.innerHTML = '';
    -}
    -
    -function testFindNode() {
    -  // Test the easiest case.
    -  root.innerHTML = 'a<br>b';
    -  assertEquals(goog.testing.dom.findTextNode('a', root), root.firstChild);
    -  assertEquals(goog.testing.dom.findTextNode('b', root), root.lastChild);
    -  assertNull(goog.testing.dom.findTextNode('c', root));
    -}
    -
    -function testFindNodeDuplicate() {
    -  // Test duplicate.
    -  root.innerHTML = 'c<br>c';
    -  assertEquals('Should return first duplicate',
    -      goog.testing.dom.findTextNode('c', root), root.firstChild);
    -}
    -
    -function findNodeWithHierarchy() {
    -  // Test a more complicated hierarchy.
    -  root.innerHTML = '<div>a<p>b<span>c</span>d</p>e</div>';
    -  assertEquals(goog.dom.TagName.DIV,
    -      goog.testing.dom.findTextNode('a', root).parentNode.tagName);
    -  assertEquals(goog.dom.TagName.P,
    -      goog.testing.dom.findTextNode('b', root).parentNode.tagName);
    -  assertEquals(goog.dom.TagName.SPAN,
    -      goog.testing.dom.findTextNode('c', root).parentNode.tagName);
    -  assertEquals(goog.dom.TagName.P,
    -      goog.testing.dom.findTextNode('d', root).parentNode.tagName);
    -  assertEquals(goog.dom.TagName.DIV,
    -      goog.testing.dom.findTextNode('e', root).parentNode.tagName);
    -}
    -
    -function setUpAssertHtmlMatches() {
    -  var tag1, tag2;
    -  if (goog.userAgent.IE) {
    -    tag1 = goog.dom.TagName.DIV;
    -  } else if (goog.userAgent.WEBKIT) {
    -    tag1 = goog.dom.TagName.P;
    -    tag2 = goog.dom.TagName.BR;
    -  } else if (goog.userAgent.GECKO) {
    -    tag1 = goog.dom.TagName.SPAN;
    -    tag2 = goog.dom.TagName.BR;
    -  }
    -
    -  var parent = goog.dom.createDom(goog.dom.TagName.DIV);
    -  root.appendChild(parent);
    -  parent.style.fontSize = '2em';
    -  parent.style.display = 'none';
    -  if (!goog.userAgent.WEBKIT) {
    -    parent.appendChild(goog.dom.createTextNode('NonWebKitText'));
    -  }
    -
    -  if (tag1) {
    -    var e1 = goog.dom.createDom(tag1);
    -    parent.appendChild(e1);
    -    parent = e1;
    -  }
    -  if (tag2) {
    -    parent.appendChild(goog.dom.createDom(tag2));
    -  }
    -  parent.appendChild(goog.dom.createTextNode('Text'));
    -  if (goog.userAgent.WEBKIT) {
    -    root.firstChild.appendChild(goog.dom.createTextNode('WebKitText'));
    -  }
    -}
    -
    -function testAssertHtmlContentsMatch() {
    -  setUpAssertHtmlMatches();
    -
    -  goog.testing.dom.assertHtmlContentsMatch(
    -      '<div style="display: none; font-size: 2em">' +
    -      '[[!WEBKIT]]NonWebKitText<div class="IE"><p class="WEBKIT">' +
    -      '<span class="GECKO"><br class="GECKO WEBKIT">Text</span></p></div>' +
    -      '</div>[[WEBKIT]]WebKitText',
    -      root);
    -}
    -
    -function testAssertHtmlMismatchText() {
    -  setUpAssertHtmlMatches();
    -
    -  var e = assertThrows('Should fail due to mismatched text', function() {
    -    goog.testing.dom.assertHtmlContentsMatch(
    -        '<div style="display: none; font-size: 2em">' +
    -        '[[IE GECKO]]NonWebKitText<div class="IE"><p class="WEBKIT">' +
    -        '<span class="GECKO"><br class="GECKO WEBKIT">Bad</span></p></div>' +
    -        '</div>[[WEBKIT]]Extra',
    -        root);
    -  });
    -  assertContains('Text should match', e.message);
    -}
    -
    -function testAssertHtmlMismatchTag() {
    -  setUpAssertHtmlMatches();
    -
    -  var e = assertThrows('Should fail due to mismatched tag', function() {
    -    goog.testing.dom.assertHtmlContentsMatch(
    -        '<span style="display: none; font-size: 2em">' +
    -        '[[IE GECKO]]NonWebKitText<div class="IE"><p class="WEBKIT">' +
    -        '<span class="GECKO"><br class="GECKO WEBKIT">Text</span></p></div>' +
    -        '</span>[[WEBKIT]]Extra',
    -        root);
    -  });
    -  assertContains('Tag names should match', e.message);
    -}
    -
    -function testAssertHtmlMismatchStyle() {
    -  setUpAssertHtmlMatches();
    -
    -  var e = assertThrows('Should fail due to mismatched style', function() {
    -    goog.testing.dom.assertHtmlContentsMatch(
    -        '<div style="display: none; font-size: 3em">' +
    -        '[[IE GECKO]]NonWebKitText<div class="IE"><p class="WEBKIT">' +
    -        '<span class="GECKO"><br class="GECKO WEBKIT">Text</span></p></div>' +
    -        '</div>[[WEBKIT]]Extra',
    -        root);
    -  });
    -  assertContains('Should have same styles', e.message);
    -}
    -
    -function testAssertHtmlMismatchOptionalText() {
    -  setUpAssertHtmlMatches();
    -
    -  var e = assertThrows('Should fail due to mismatched text', function() {
    -    goog.testing.dom.assertHtmlContentsMatch(
    -        '<div style="display: none; font-size: 2em">' +
    -        '[[IE GECKO]]Bad<div class="IE"><p class="WEBKIT">' +
    -        '<span class="GECKO"><br class="GECKO WEBKIT">Text</span></p></div>' +
    -        '</div>[[WEBKIT]]Bad',
    -        root);
    -  });
    -  assertContains('Text should match', e.message);
    -}
    -
    -function testAssertHtmlMismatchExtraActualAfterText() {
    -  root.innerHTML = '<div>abc</div>def';
    -
    -  var e = assertThrows('Should fail due to extra actual nodes', function() {
    -    goog.testing.dom.assertHtmlContentsMatch('<div>abc</div>', root);
    -  });
    -  assertContains('Finished expected HTML before', e.message);
    -}
    -
    -function testAssertHtmlMismatchExtraActualAfterElement() {
    -  root.innerHTML = '<br>def';
    -
    -  var e = assertThrows('Should fail due to extra actual nodes', function() {
    -    goog.testing.dom.assertHtmlContentsMatch('<br>', root);
    -  });
    -  assertContains('Finished expected HTML before', e.message);
    -}
    -
    -function testAssertHtmlMatchesWithSplitTextNodes() {
    -  root.appendChild(goog.dom.createTextNode('1'));
    -  root.appendChild(goog.dom.createTextNode('2'));
    -  root.appendChild(goog.dom.createTextNode('3'));
    -  goog.testing.dom.assertHtmlContentsMatch('123', root);
    -}
    -
    -function testAssertHtmlMatchesWithDifferentlyOrderedAttributes() {
    -  root.innerHTML = '<div foo="a" bar="b" class="className"></div>';
    -
    -  goog.testing.dom.assertHtmlContentsMatch(
    -      '<div bar="b" class="className" foo="a"></div>', root, true);
    -}
    -
    -function testAssertHtmlMismatchWithDifferentNumberOfAttributes() {
    -  root.innerHTML = '<div foo="a" bar="b"></div>';
    -
    -  var e = assertThrows(function() {
    -    goog.testing.dom.assertHtmlContentsMatch(
    -        '<div foo="a"></div>', root, true);
    -  });
    -  assertContains('Unexpected attribute with name bar in element', e.message);
    -}
    -
    -function testAssertHtmlMismatchWithDifferentAttributeNames() {
    -  root.innerHTML = '<div foo="a" bar="b"></div>';
    -
    -  var e = assertThrows(function() {
    -    goog.testing.dom.assertHtmlContentsMatch(
    -        '<div foo="a" baz="b"></div>', root, true);
    -  });
    -  assertContains('Expected to find attribute with name baz', e.message);
    -}
    -
    -function testAssertHtmlMismatchWithDifferentClassNames() {
    -  root.innerHTML = '<div class="className1"></div>';
    -
    -  var e = assertThrows(function() {
    -    goog.testing.dom.assertHtmlContentsMatch(
    -        '<div class="className2"></div>', root, true);
    -  });
    -  assertContains(
    -      'Expected class was: className2, but actual class was: className1',
    -      e.message);
    -}
    -
    -function testAssertHtmlMatchesWithClassNameAndUserAgentSpecified() {
    -  root.innerHTML =
    -      '<div>' + (goog.userAgent.GECKO ? '<div class="foo"></div>' : '') +
    -      '</div>';
    -
    -  goog.testing.dom.assertHtmlContentsMatch(
    -      '<div><div class="foo GECKO"></div></div>',
    -      root, true);
    -}
    -
    -function testAssertHtmlMatchesWithClassesInDifferentOrder() {
    -  root.innerHTML = '<div class="class1 class2"></div>';
    -
    -  goog.testing.dom.assertHtmlContentsMatch(
    -      '<div class="class2 class1"></div>', root, true);
    -}
    -
    -function testAssertHtmlMismatchWithDifferentAttributeValues() {
    -  root.innerHTML = '<div foo="b" bar="a"></div>';
    -
    -  var e = assertThrows(function() {
    -    goog.testing.dom.assertHtmlContentsMatch(
    -        '<div foo="a" bar="a"></div>', root, true);
    -  });
    -  assertContains('Expected attribute foo has a different value', e.message);
    -}
    -
    -function testAssertHtmlMatchesWhenStrictAttributesIsFalse() {
    -  root.innerHTML = '<div foo="a" bar="b"></div>';
    -
    -  goog.testing.dom.assertHtmlContentsMatch('<div foo="a"></div>', root);
    -}
    -
    -function testAssertHtmlMatchesForMethodsAttribute() {
    -  root.innerHTML = '<a methods="get"></a>';
    -
    -  goog.testing.dom.assertHtmlContentsMatch('<a></a>', root);
    -  goog.testing.dom.assertHtmlContentsMatch('<a methods="get"></a>', root);
    -  goog.testing.dom.assertHtmlContentsMatch('<a methods="get"></a>', root,
    -      true);
    -}
    -
    -function testAssertHtmlMatchesForMethodsAttribute() {
    -  root.innerHTML = '<input></input>';
    -
    -  goog.testing.dom.assertHtmlContentsMatch('<input></input>', root);
    -  goog.testing.dom.assertHtmlContentsMatch('<input></input>', root, true);
    -}
    -
    -function testAssertHtmlMatchesForIdAttribute() {
    -  root.innerHTML = '<div id="foo"></div>';
    -
    -  goog.testing.dom.assertHtmlContentsMatch('<div></div>', root);
    -  goog.testing.dom.assertHtmlContentsMatch('<div id="foo"></div>', root);
    -  goog.testing.dom.assertHtmlContentsMatch('<div id="foo"></div>', root,
    -      true);
    -}
    -
    -function testAssertHtmlMatchesWhenIdIsNotSpecified() {
    -  root.innerHTML = '<div id="someId"></div>';
    -
    -  goog.testing.dom.assertHtmlContentsMatch('<div></div>', root);
    -}
    -
    -function testAssertHtmlMismatchWhenIdIsNotSpecified() {
    -  root.innerHTML = '<div id="someId"></div>';
    -
    -  var e = assertThrows(function() {
    -    goog.testing.dom.assertHtmlContentsMatch('<div></div>', root, true);
    -  });
    -  assertContains('Unexpected attribute with name id in element', e.message);
    -}
    -
    -function testAssertHtmlMismatchWhenIdIsSpecified() {
    -  root.innerHTML = '<div></div>';
    -
    -  var e = assertThrows(function() {
    -    goog.testing.dom.assertHtmlContentsMatch('<div id="someId"></div>', root);
    -  });
    -  assertContains('Expected to find attribute with name id, in element',
    -      e.message);
    -
    -  e = assertThrows(function() {
    -    goog.testing.dom.assertHtmlContentsMatch('<div id="someId"></div>', root,
    -        true);
    -  });
    -  assertContains('Expected to find attribute with name id, in element',
    -      e.message);
    -}
    -
    -function testAssertHtmlMatchesWhenIdIsEmpty() {
    -  root.innerHTML = '<div></div>';
    -
    -  goog.testing.dom.assertHtmlContentsMatch('<div></div>', root);
    -  goog.testing.dom.assertHtmlContentsMatch('<div></div>', root, true);
    -}
    -
    -function testAssertHtmlMatchesWithDisabledAttribute() {
    -  var disabledShortest = '<input disabled="disabled">';
    -  var disabledShort = '<input disabled="">';
    -  var disabledLong = '<input disabled="disabled">';
    -  var enabled = '<input>';
    -
    -  root.innerHTML = disabledLong;
    -  goog.testing.dom.assertHtmlContentsMatch(disabledShortest, root, true);
    -  goog.testing.dom.assertHtmlContentsMatch(disabledShort, root, true);
    -  goog.testing.dom.assertHtmlContentsMatch(disabledLong, root, true);
    -
    -
    -  var e = assertThrows('Should fail due to mismatched text', function() {
    -    goog.testing.dom.assertHtmlContentsMatch(enabled, root, true);
    -  });
    -  // Attribute value mismatch in IE.
    -  // Unexpected attribute error in other browsers.
    -  assertContains('disabled', e.message);
    -}
    -
    -function testAssertHtmlMatchesWithCheckedAttribute() {
    -  var checkedShortest = '<input type="radio" name="x" checked="checked">';
    -  var checkedShort = '<input type="radio" name="x" checked="">';
    -  var checkedLong = '<input type="radio" name="x" checked="checked">';
    -  var unchecked = '<input type="radio" name="x">';
    -
    -  root.innerHTML = checkedLong;
    -  goog.testing.dom.assertHtmlContentsMatch(checkedShortest, root, true);
    -  goog.testing.dom.assertHtmlContentsMatch(checkedShort, root, true);
    -  goog.testing.dom.assertHtmlContentsMatch(checkedLong, root, true);
    -  if (!goog.userAgent.IE) {
    -    // CHECKED attribute is ignored because it's among BAD_IE_ATTRIBUTES_.
    -    var e = assertThrows('Should fail due to mismatched text', function() {
    -      goog.testing.dom.assertHtmlContentsMatch(unchecked, root, true);
    -    });
    -    assertContains('Unexpected attribute with name checked', e.message);
    -  }
    -}
    -
    -function testAssertHtmlMatchesWithWhitespace() {
    -  root.innerHTML = '';
    -  root.appendChild(goog.dom.createTextNode('  A  '));
    -  goog.testing.dom.assertHtmlContentsMatch('  A  ', root);
    -
    -  root.innerHTML = '';
    -  root.appendChild(goog.dom.createTextNode('  A  '));
    -  root.appendChild(goog.dom.createDom('span', null, '  B  '));
    -  root.appendChild(goog.dom.createTextNode('  C  '));
    -  goog.testing.dom.assertHtmlContentsMatch(
    -      '  A  <span>  B  </span>  C  ', root);
    -
    -  root.innerHTML = '';
    -  root.appendChild(goog.dom.createTextNode('  A'));
    -  root.appendChild(goog.dom.createDom('span', null, '  B'));
    -  root.appendChild(goog.dom.createTextNode('  C'));
    -  goog.testing.dom.assertHtmlContentsMatch(
    -      '  A<span>  B</span>  C', root);
    -}
    -
    -function testAssertHtmlMatchesWithWhitespaceAndNesting() {
    -  root.innerHTML = '';
    -  root.appendChild(goog.dom.createDom('div', null,
    -      goog.dom.createDom('b', null, '  A  '),
    -      goog.dom.createDom('b', null, '  B  ')));
    -  root.appendChild(goog.dom.createDom('div', null,
    -      goog.dom.createDom('b', null, '  C  '),
    -      goog.dom.createDom('b', null, '  D  ')));
    -
    -  goog.testing.dom.assertHtmlContentsMatch(
    -      '<div><b>  A  </b><b>  B  </b></div>' +
    -      '<div><b>  C  </b><b>  D  </b></div>', root);
    -
    -  root.innerHTML = '';
    -  root.appendChild(goog.dom.createDom('b', null,
    -      goog.dom.createDom('b', null,
    -          goog.dom.createDom('b', null, '  A  '))));
    -  root.appendChild(goog.dom.createDom('b', null, '  B  '));
    -
    -  goog.testing.dom.assertHtmlContentsMatch(
    -      '<b><b><b>  A  </b></b></b><b>  B  </b>', root);
    -
    -  root.innerHTML = '';
    -  root.appendChild(goog.dom.createDom('div', null,
    -      goog.dom.createDom('b', null,
    -          goog.dom.createDom('b', null, '  A  '))));
    -  root.appendChild(goog.dom.createDom('b', null, '  B  '));
    -
    -  goog.testing.dom.assertHtmlContentsMatch(
    -      '<div><b><b>  A  </b></b></div><b>  B  </b>', root);
    -
    -  root.innerHTML = '&nbsp;';
    -  goog.testing.dom.assertHtmlContentsMatch(
    -      '&nbsp;', root);
    -}
    -
    -function testAssertHtmlMatches() {
    -  // Since assertHtmlMatches is based on assertHtmlContentsMatch, we leave the
    -  // majority of edge case testing to the above.  Here we just do a sanity
    -  // check.
    -  goog.testing.dom.assertHtmlMatches('<div>abc</div>', '<div>abc</div>');
    -  goog.testing.dom.assertHtmlMatches('<div>abc</div>', '<div>abc</div> ');
    -  goog.testing.dom.assertHtmlMatches(
    -      '<div style="font-size: 1px; color: red">abc</div>',
    -      '<div style="color: red;  font-size: 1px;;">abc</div>');
    -
    -  var e = assertThrows('Should fail due to mismatched text', function() {
    -    goog.testing.dom.assertHtmlMatches('<div>abc</div>', '<div>abd</div>');
    -  });
    -  assertContains('Text should match', e.message);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/editor/dom.js b/src/database/third_party/closure-library/closure/goog/testing/editor/dom.js
    deleted file mode 100644
    index d30b711c632..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/editor/dom.js
    +++ /dev/null
    @@ -1,293 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Testing utilities for editor specific DOM related tests.
    - *
    - */
    -
    -goog.provide('goog.testing.editor.dom');
    -
    -goog.require('goog.dom.NodeType');
    -goog.require('goog.dom.TagIterator');
    -goog.require('goog.dom.TagWalkType');
    -goog.require('goog.iter');
    -goog.require('goog.string');
    -goog.require('goog.testing.asserts');
    -
    -
    -/**
    - * Returns the previous (in document order) node from the given node that is a
    - * non-empty text node, or null if none is found or opt_stopAt is not an
    - * ancestor of node. Note that if the given node has children, the search will
    - * start from the end tag of the node, meaning all its descendants will be
    - * included in the search, unless opt_skipDescendants is true.
    - * @param {Node} node Node to start searching from.
    - * @param {Node=} opt_stopAt Node to stop searching at (search will be
    - *     restricted to this node's subtree), defaults to the body of the document
    - *     containing node.
    - * @param {boolean=} opt_skipDescendants Whether to skip searching the given
    - *     node's descentants.
    - * @return {Text} The previous (in document order) node from the given node
    - *     that is a non-empty text node, or null if none is found.
    - */
    -goog.testing.editor.dom.getPreviousNonEmptyTextNode = function(
    -    node, opt_stopAt, opt_skipDescendants) {
    -  return goog.testing.editor.dom.getPreviousNextNonEmptyTextNodeHelper_(
    -      node, opt_stopAt, opt_skipDescendants, true);
    -};
    -
    -
    -/**
    - * Returns the next (in document order) node from the given node that is a
    - * non-empty text node, or null if none is found or opt_stopAt is not an
    - * ancestor of node. Note that if the given node has children, the search will
    - * start from the start tag of the node, meaning all its descendants will be
    - * included in the search, unless opt_skipDescendants is true.
    - * @param {Node} node Node to start searching from.
    - * @param {Node=} opt_stopAt Node to stop searching at (search will be
    - *     restricted to this node's subtree), defaults to the body of the document
    - *     containing node.
    - * @param {boolean=} opt_skipDescendants Whether to skip searching the given
    - *     node's descentants.
    - * @return {Text} The next (in document order) node from the given node that
    - *     is a non-empty text node, or null if none is found or opt_stopAt is not
    - *     an ancestor of node.
    - */
    -goog.testing.editor.dom.getNextNonEmptyTextNode = function(
    -    node, opt_stopAt, opt_skipDescendants) {
    -  return goog.testing.editor.dom.getPreviousNextNonEmptyTextNodeHelper_(
    -      node, opt_stopAt, opt_skipDescendants, false);
    -};
    -
    -
    -/**
    - * Helper that returns the previous or next (in document order) node from the
    - * given node that is a non-empty text node, or null if none is found or
    - * opt_stopAt is not an ancestor of node. Note that if the given node has
    - * children, the search will start from the end or start tag of the node
    - * (depending on whether it's searching for the previous or next node), meaning
    - * all its descendants will be included in the search, unless
    - * opt_skipDescendants is true.
    - * @param {Node} node Node to start searching from.
    - * @param {Node=} opt_stopAt Node to stop searching at (search will be
    - *     restricted to this node's subtree), defaults to the body of the document
    - *     containing node.
    - * @param {boolean=} opt_skipDescendants Whether to skip searching the given
    - *   node's descentants.
    - * @param {boolean=} opt_isPrevious Whether to search for the previous non-empty
    - *     text node instead of the next one.
    - * @return {Text} The next (in document order) node from the given node that
    - *     is a non-empty text node, or null if none is found or opt_stopAt is not
    - *     an ancestor of node.
    - * @private
    - */
    -goog.testing.editor.dom.getPreviousNextNonEmptyTextNodeHelper_ = function(
    -    node, opt_stopAt, opt_skipDescendants, opt_isPrevious) {
    -  opt_stopAt = opt_stopAt || node.ownerDocument.body;
    -  // Initializing the iterator to iterate over the children of opt_stopAt
    -  // makes it stop only when it finishes iterating through all of that
    -  // node's children, even though we will start at a different node and exit
    -  // that starting node's subtree in the process.
    -  var iter = new goog.dom.TagIterator(opt_stopAt, opt_isPrevious);
    -
    -  // TODO(user): Move this logic to a new method in TagIterator such as
    -  // skipToNode().
    -  // Then we set the iterator to start at the given start node, not opt_stopAt.
    -  var walkType; // Let TagIterator set the initial walk type by default.
    -  var depth = goog.testing.editor.dom.getRelativeDepth_(node, opt_stopAt);
    -  if (depth == -1) {
    -    return null; // Fail because opt_stopAt is not an ancestor of node.
    -  }
    -  if (node.nodeType == goog.dom.NodeType.ELEMENT) {
    -    if (opt_skipDescendants) {
    -      // Specifically set the initial walk type so that we skip the descendant
    -      // subtree by starting at the start if going backwards or at the end if
    -      // going forwards.
    -      walkType = opt_isPrevious ? goog.dom.TagWalkType.START_TAG :
    -                                  goog.dom.TagWalkType.END_TAG;
    -    } else {
    -      // We're starting "inside" an element node so the depth needs to be one
    -      // deeper than the node's actual depth. That's how TagIterator works!
    -      depth++;
    -    }
    -  }
    -  iter.setPosition(node, walkType, depth);
    -
    -  // Advance the iterator so it skips the start node.
    -  try {
    -    iter.next();
    -  } catch (e) {
    -    return null; // It could have been a leaf node.
    -  }
    -  // Now just get the first non-empty text node the iterator finds.
    -  var filter = goog.iter.filter(iter,
    -                                goog.testing.editor.dom.isNonEmptyTextNode_);
    -  try {
    -    return /** @type {Text} */ (filter.next());
    -  } catch (e) { // No next item is available so return null.
    -    return null;
    -  }
    -};
    -
    -
    -/**
    - * Returns whether the given node is a non-empty text node.
    - * @param {Node} node Node to be checked.
    - * @return {boolean} Whether the given node is a non-empty text node.
    - * @private
    - */
    -goog.testing.editor.dom.isNonEmptyTextNode_ = function(node) {
    -  return !!node && node.nodeType == goog.dom.NodeType.TEXT && node.length > 0;
    -};
    -
    -
    -/**
    - * Returns the depth of the given node relative to the given parent node, or -1
    - * if the given node is not a descendant of the given parent node. E.g. if
    - * node == parentNode returns 0, if node.parentNode == parentNode returns 1,
    - * etc.
    - * @param {Node} node Node whose depth to get.
    - * @param {Node} parentNode Node relative to which the depth should be
    - *     calculated.
    - * @return {number} The depth of the given node relative to the given parent
    - *     node, or -1 if the given node is not a descendant of the given parent
    - *     node.
    - * @private
    - */
    -goog.testing.editor.dom.getRelativeDepth_ = function(node, parentNode) {
    -  var depth = 0;
    -  while (node) {
    -    if (node == parentNode) {
    -      return depth;
    -    }
    -    node = node.parentNode;
    -    depth++;
    -  }
    -  return -1;
    -};
    -
    -
    -/**
    - * Assert that the range is surrounded by the given strings. This is useful
    - * because different browsers can place the range endpoints inside different
    - * nodes even when visually the range looks the same. Also, there may be empty
    - * text nodes in the way (again depending on the browser) making it difficult to
    - * use assertRangeEquals.
    - * @param {string} before String that should occur immediately before the start
    - *     point of the range. If this is the empty string, assert will only succeed
    - *     if there is no text before the start point of the range.
    - * @param {string} after String that should occur immediately after the end
    - *     point of the range. If this is the empty string, assert will only succeed
    - *     if there is no text after the end point of the range.
    - * @param {goog.dom.AbstractRange} range The range to be tested.
    - * @param {Node=} opt_stopAt Node to stop searching at (search will be
    - *     restricted to this node's subtree).
    - */
    -goog.testing.editor.dom.assertRangeBetweenText = function(before,
    -                                                          after,
    -                                                          range,
    -                                                          opt_stopAt) {
    -  var previousText =
    -      goog.testing.editor.dom.getTextFollowingRange_(range, true, opt_stopAt);
    -  if (before == '') {
    -    assertNull('Expected nothing before range but found <' + previousText + '>',
    -               previousText);
    -  } else {
    -    assertNotNull('Expected <' + before + '> before range but found nothing',
    -                  previousText);
    -    assertTrue('Expected <' + before + '> before range but found <' +
    -               previousText + '>',
    -               goog.string.endsWith(
    -                   /** @type {string} */ (previousText), before));
    -  }
    -  var nextText =
    -      goog.testing.editor.dom.getTextFollowingRange_(range, false, opt_stopAt);
    -  if (after == '') {
    -    assertNull('Expected nothing after range but found <' + nextText + '>',
    -               nextText);
    -  } else {
    -    assertNotNull('Expected <' + after + '> after range but found nothing',
    -                  nextText);
    -    assertTrue('Expected <' + after + '> after range but found <' +
    -               nextText + '>',
    -               goog.string.startsWith(
    -                   /** @type {string} */ (nextText), after));
    -  }
    -};
    -
    -
    -/**
    - * Returns the text that follows the given range, where the term "follows" means
    - * "comes immediately before the start of the range" if isBefore is true, and
    - * "comes immediately after the end of the range" if isBefore is false, or null
    - * if no non-empty text node is found.
    - * @param {goog.dom.AbstractRange} range The range to search from.
    - * @param {boolean} isBefore Whether to search before the range instead of
    - *     after it.
    - * @param {Node=} opt_stopAt Node to stop searching at (search will be
    - *     restricted to this node's subtree).
    - * @return {?string} The text that follows the given range, or null if no
    - *     non-empty text node is found.
    - * @private
    - */
    -goog.testing.editor.dom.getTextFollowingRange_ = function(range,
    -                                                          isBefore,
    -                                                          opt_stopAt) {
    -  var followingTextNode;
    -  var endpointNode = isBefore ? range.getStartNode() : range.getEndNode();
    -  var endpointOffset = isBefore ? range.getStartOffset() : range.getEndOffset();
    -  var getFollowingTextNode =
    -      isBefore ? goog.testing.editor.dom.getPreviousNonEmptyTextNode :
    -                 goog.testing.editor.dom.getNextNonEmptyTextNode;
    -
    -  if (endpointNode.nodeType == goog.dom.NodeType.TEXT) {
    -    // Range endpoint is in a text node.
    -    var endText = endpointNode.nodeValue;
    -    if (isBefore ? endpointOffset > 0 : endpointOffset < endText.length) {
    -      // There is text in this node following the endpoint so return the portion
    -      // that follows the endpoint.
    -      return isBefore ? endText.substr(0, endpointOffset) :
    -                        endText.substr(endpointOffset);
    -    } else {
    -      // There is no text following the endpoint so look for the follwing text
    -      // node.
    -      followingTextNode = getFollowingTextNode(endpointNode, opt_stopAt);
    -      return followingTextNode && followingTextNode.nodeValue;
    -    }
    -  } else {
    -    // Range endpoint is in an element node.
    -    var numChildren = endpointNode.childNodes.length;
    -    if (isBefore ? endpointOffset > 0 : endpointOffset < numChildren) {
    -      // There is at least one child following the endpoint.
    -      var followingChild =
    -          endpointNode.childNodes[isBefore ? endpointOffset - 1 :
    -                                             endpointOffset];
    -      if (goog.testing.editor.dom.isNonEmptyTextNode_(followingChild)) {
    -        // The following child has text so return that.
    -        return followingChild.nodeValue;
    -      } else {
    -        // The following child has no text so look for the following text node.
    -        followingTextNode = getFollowingTextNode(followingChild, opt_stopAt);
    -        return followingTextNode && followingTextNode.nodeValue;
    -      }
    -    } else {
    -      // There is no child following the endpoint, so search from the endpoint
    -      // node, but don't search its children because they are not following the
    -      // endpoint!
    -      followingTextNode = getFollowingTextNode(endpointNode, opt_stopAt, true);
    -      return followingTextNode && followingTextNode.nodeValue;
    -    }
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/editor/dom_test.html b/src/database/third_party/closure-library/closure/goog/testing/editor/dom_test.html
    deleted file mode 100644
    index 0a13be34409..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/editor/dom_test.html
    +++ /dev/null
    @@ -1,28 +0,0 @@
    -<!DOCTYPE html>
    -<html lang="en" dir="ltr">
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <!--
    -
    -   @author marcosalmeida@google.com (Marcos Almeida)
    -  -->
    -  <title>
    -   Closure Unit Tests - goog.testing.editor.dom
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.editor.domTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="root">
    -  </div>
    - </body>
    -</html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/editor/dom_test.js b/src/database/third_party/closure-library/closure/goog/testing/editor/dom_test.js
    deleted file mode 100644
    index 74e8b8b504c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/editor/dom_test.js
    +++ /dev/null
    @@ -1,290 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.editor.domTest');
    -goog.setTestOnly('goog.testing.editor.domTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.functions');
    -goog.require('goog.testing.editor.dom');
    -goog.require('goog.testing.jsunit');
    -
    -var root;
    -var parentNode, childNode1, childNode2, childNode3;
    -var first, middle, last;
    -
    -function setUpPage() {
    -  root = goog.dom.getElement('root');
    -}
    -
    -function tearDown() {
    -  root.innerHTML = '';
    -}
    -
    -function setUpNonEmptyTests() {
    -  childNode1 = goog.dom.createElement(goog.dom.TagName.DIV);
    -  childNode2 = goog.dom.createElement(goog.dom.TagName.DIV);
    -  childNode3 = goog.dom.createElement(goog.dom.TagName.DIV);
    -  parentNode = goog.dom.createDom(goog.dom.TagName.DIV,
    -      null,
    -      childNode1,
    -      childNode2,
    -      childNode3);
    -  goog.dom.appendChild(root, parentNode);
    -
    -  childNode1.appendChild(goog.dom.createTextNode('One'));
    -  childNode1.appendChild(goog.dom.createTextNode(''));
    -
    -  childNode2.appendChild(goog.dom.createElement(goog.dom.TagName.BR));
    -  childNode2.appendChild(goog.dom.createTextNode('TwoA'));
    -  childNode2.appendChild(goog.dom.createTextNode('TwoB'));
    -  childNode2.appendChild(goog.dom.createElement(goog.dom.TagName.BR));
    -
    -  childNode3.appendChild(goog.dom.createTextNode(''));
    -  childNode3.appendChild(goog.dom.createTextNode('Three'));
    -}
    -
    -function testGetNextNonEmptyTextNode() {
    -  setUpNonEmptyTests();
    -
    -  var nodeOne =
    -      goog.testing.editor.dom.getNextNonEmptyTextNode(parentNode);
    -  assertEquals('Should have found the next non-empty text node',
    -               'One',
    -               nodeOne.nodeValue);
    -  var nodeTwoA =
    -      goog.testing.editor.dom.getNextNonEmptyTextNode(nodeOne);
    -  assertEquals('Should have found the next non-empty text node',
    -               'TwoA',
    -               nodeTwoA.nodeValue);
    -  var nodeTwoB =
    -      goog.testing.editor.dom.getNextNonEmptyTextNode(nodeTwoA);
    -  assertEquals('Should have found the next non-empty text node',
    -               'TwoB',
    -               nodeTwoB.nodeValue);
    -  var nodeThree =
    -      goog.testing.editor.dom.getNextNonEmptyTextNode(nodeTwoB);
    -  assertEquals('Should have found the next non-empty text node',
    -               'Three',
    -               nodeThree.nodeValue);
    -  var nodeNull =
    -      goog.testing.editor.dom.getNextNonEmptyTextNode(nodeThree, parentNode);
    -  assertNull('Should not have found any non-empty text node', nodeNull);
    -
    -  var nodeStop =
    -      goog.testing.editor.dom.getNextNonEmptyTextNode(nodeOne, childNode1);
    -  assertNull('Should have stopped before finding a node', nodeStop);
    -
    -  var nodeBeforeStop =
    -      goog.testing.editor.dom.getNextNonEmptyTextNode(nodeTwoA, childNode2);
    -  assertEquals('Should have found the next non-empty text node',
    -               'TwoB',
    -               nodeBeforeStop.nodeValue);
    -}
    -
    -function testGetPreviousNonEmptyTextNode() {
    -  setUpNonEmptyTests();
    -
    -  var nodeThree =
    -      goog.testing.editor.dom.getPreviousNonEmptyTextNode(parentNode);
    -  assertEquals('Should have found the previous non-empty text node',
    -               'Three',
    -               nodeThree.nodeValue);
    -  var nodeTwoB =
    -      goog.testing.editor.dom.getPreviousNonEmptyTextNode(nodeThree);
    -  assertEquals('Should have found the previous non-empty text node',
    -               'TwoB',
    -               nodeTwoB.nodeValue);
    -  var nodeTwoA =
    -      goog.testing.editor.dom.getPreviousNonEmptyTextNode(nodeTwoB);
    -  assertEquals('Should have found the previous non-empty text node',
    -               'TwoA',
    -               nodeTwoA.nodeValue);
    -  var nodeOne =
    -      goog.testing.editor.dom.getPreviousNonEmptyTextNode(nodeTwoA);
    -  assertEquals('Should have found the previous non-empty text node',
    -               'One',
    -               nodeOne.nodeValue);
    -  var nodeNull =
    -      goog.testing.editor.dom.getPreviousNonEmptyTextNode(nodeOne,
    -                                                          parentNode);
    -  assertNull('Should not have found any non-empty text node', nodeNull);
    -
    -  var nodeStop =
    -      goog.testing.editor.dom.getPreviousNonEmptyTextNode(nodeThree,
    -                                                          childNode3);
    -  assertNull('Should have stopped before finding a node', nodeStop);
    -
    -  var nodeBeforeStop =
    -      goog.testing.editor.dom.getPreviousNonEmptyTextNode(nodeTwoB,
    -                                                          childNode2);
    -  assertEquals('Should have found the previous non-empty text node',
    -               'TwoA',
    -               nodeBeforeStop.nodeValue);
    -}
    -
    -
    -function setUpAssertRangeBetweenText() {
    -  // Create the following structure: <[01]><[]><[23]>
    -  // Where <> delimits spans, [] delimits text nodes, 01 and 23 are text.
    -  // We will test all 10 positions in between 0 and 2. All should pass.
    -  first = goog.dom.createDom(goog.dom.TagName.SPAN, null, '01');
    -  middle = goog.dom.createElement(goog.dom.TagName.SPAN);
    -  var emptyTextNode = goog.dom.createTextNode('');
    -  goog.dom.appendChild(middle, emptyTextNode);
    -  last = goog.dom.createDom(goog.dom.TagName.SPAN, null, '23');
    -  goog.dom.appendChild(root, first);
    -  goog.dom.appendChild(root, middle);
    -  goog.dom.appendChild(root, last);
    -}
    -
    -function createFakeRange(startNode, startOffset, opt_endNode, opt_endOffset) {
    -  opt_endNode = opt_endNode || startNode;
    -  opt_endOffset = opt_endOffset || startOffset;
    -  return {
    -    getStartNode: goog.functions.constant(startNode),
    -    getStartOffset: goog.functions.constant(startOffset),
    -    getEndNode: goog.functions.constant(opt_endNode),
    -    getEndOffset: goog.functions.constant(opt_endOffset)
    -  };
    -}
    -
    -function testAssertRangeBetweenText0() {
    -  setUpAssertRangeBetweenText();
    -  goog.testing.editor.dom.assertRangeBetweenText('0', '1',
    -      createFakeRange(first.firstChild, 1));
    -}
    -
    -function testAssertRangeBetweenText1() {
    -  setUpAssertRangeBetweenText();
    -  goog.testing.editor.dom.assertRangeBetweenText('1', '2',
    -      createFakeRange(first.firstChild, 2));
    -}
    -
    -function testAssertRangeBetweenText2() {
    -  setUpAssertRangeBetweenText();
    -  goog.testing.editor.dom.assertRangeBetweenText('1', '2',
    -      createFakeRange(first, 1));
    -}
    -
    -function testAssertRangeBetweenText3() {
    -  setUpAssertRangeBetweenText();
    -  goog.testing.editor.dom.assertRangeBetweenText('1', '2',
    -      createFakeRange(root, 1));
    -}
    -
    -function testAssertRangeBetweenText4() {
    -  setUpAssertRangeBetweenText();
    -  goog.testing.editor.dom.assertRangeBetweenText('1', '2',
    -      createFakeRange(middle, 0));
    -}
    -
    -function testAssertRangeBetweenText5() {
    -  setUpAssertRangeBetweenText();
    -  goog.testing.editor.dom.assertRangeBetweenText('1', '2',
    -      createFakeRange(middle.firstChild, 0));
    -}
    -
    -function testAssertRangeBetweenText6() {
    -  setUpAssertRangeBetweenText();
    -  goog.testing.editor.dom.assertRangeBetweenText('1', '2',
    -      createFakeRange(middle, 1));
    -}
    -
    -function testAssertRangeBetweenText7() {
    -  setUpAssertRangeBetweenText();
    -  goog.testing.editor.dom.assertRangeBetweenText('1', '2',
    -      createFakeRange(root, 2));
    -}
    -
    -function testAssertRangeBetweenText8() {
    -  setUpAssertRangeBetweenText();
    -  goog.testing.editor.dom.assertRangeBetweenText('1', '2',
    -      createFakeRange(last, 0));
    -}
    -
    -function testAssertRangeBetweenText9() {
    -  setUpAssertRangeBetweenText();
    -  goog.testing.editor.dom.assertRangeBetweenText('1', '2',
    -      createFakeRange(last.firstChild, 0));
    -}
    -
    -
    -function testAssertRangeBetweenTextBefore() {
    -  setUpAssertRangeBetweenText();
    -  // Test that it works when the cursor is at the beginning of all text.
    -  goog.testing.editor.dom.assertRangeBetweenText('', '0',
    -      createFakeRange(first.firstChild, 0),
    -      root); // Restrict to root div so it won't find /n's and script.
    -}
    -
    -function testAssertRangeBetweenTextAfter() {
    -  setUpAssertRangeBetweenText();
    -  // Test that it works when the cursor is at the end of all text.
    -  goog.testing.editor.dom.assertRangeBetweenText('3', '',
    -      createFakeRange(last.firstChild, 2),
    -      root); // Restrict to root div so it won't find /n's and script.
    -}
    -
    -
    -function testAssertRangeBetweenTextFail1() {
    -  setUpAssertRangeBetweenText();
    -  var e = assertThrows('assertRangeBetweenText should have failed',
    -      function() {
    -        goog.testing.editor.dom.assertRangeBetweenText('1', '3',
    -            createFakeRange(first.firstChild, 2));
    -      });
    -  assertContains('Assert reason incorrect',
    -      'Expected <3> after range but found <23>', e.message);
    -}
    -
    -function testAssertRangeBetweenTextFail2() {
    -  setUpAssertRangeBetweenText();
    -  var e = assertThrows('assertRangeBetweenText should have failed',
    -      function() {
    -        goog.testing.editor.dom.assertRangeBetweenText('1', '2',
    -            createFakeRange(first.firstChild, 2, last.firstChild, 1));
    -      });
    -  assertContains('Assert reason incorrect',
    -      'Expected <2> after range but found <3>', e.message);
    -}
    -
    -function testAssertRangeBetweenTextBeforeFail() {
    -  setUpAssertRangeBetweenText();
    -  // Test that it gives the right message when the cursor is at the beginning
    -  // of all text but you're expecting something before it.
    -  var e = assertThrows('assertRangeBetweenText should have failed',
    -      function() {
    -        goog.testing.editor.dom.assertRangeBetweenText('-1', '0',
    -            createFakeRange(first.firstChild, 0),
    -            root); // Restrict to root div so it won't find /n's and script.
    -      });
    -  assertContains('Assert reason incorrect',
    -      'Expected <-1> before range but found nothing', e.message);
    -}
    -
    -function testAssertRangeBetweenTextAfterFail() {
    -  setUpAssertRangeBetweenText();
    -  // Test that it gives the right message when the cursor is at the end
    -  // of all text but you're expecting something after it.
    -  var e = assertThrows('assertRangeBetweenText should have failed',
    -      function() {
    -        goog.testing.editor.dom.assertRangeBetweenText('3', '4',
    -            createFakeRange(last.firstChild, 2),
    -            root); // Restrict to root div so it won't find /n's and script.
    -      });
    -  assertContains('Assert reason incorrect',
    -      'Expected <4> after range but found nothing', e.message);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/editor/fieldmock.js b/src/database/third_party/closure-library/closure/goog/testing/editor/fieldmock.js
    deleted file mode 100644
    index 3628c97bfd6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/editor/fieldmock.js
    +++ /dev/null
    @@ -1,116 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Mock of goog.editor.field.
    - *
    - * @author robbyw@google.com (Robby Walker)
    - */
    -
    -goog.provide('goog.testing.editor.FieldMock');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.Range');
    -goog.require('goog.editor.Field');
    -goog.require('goog.testing.LooseMock');
    -goog.require('goog.testing.mockmatchers');
    -
    -
    -
    -/**
    - * Mock of goog.editor.Field.
    - * @param {Window=} opt_window Window the field would edit.  Defaults to
    - *     {@code window}.
    - * @param {Window=} opt_appWindow "AppWindow" of the field, which can be
    - *     different from {@code opt_window} when mocking a field that uses an
    - *     iframe. Defaults to {@code opt_window}.
    - * @param {goog.dom.AbstractRange=} opt_range An object (mock or real) to be
    - *     returned by getRange(). If ommitted, a new goog.dom.Range is created
    - *     from the window every time getRange() is called.
    - * @constructor
    - * @extends {goog.testing.LooseMock}
    - * @suppress {missingProperties} Mocks do not fit in the type system well.
    - * @final
    - */
    -goog.testing.editor.FieldMock =
    -    function(opt_window, opt_appWindow, opt_range) {
    -  goog.testing.LooseMock.call(this, goog.editor.Field);
    -  opt_window = opt_window || window;
    -  opt_appWindow = opt_appWindow || opt_window;
    -
    -  this.getAppWindow();
    -  this.$anyTimes();
    -  this.$returns(opt_appWindow);
    -
    -  this.getRange();
    -  this.$anyTimes();
    -  this.$does(function() {
    -    return opt_range || goog.dom.Range.createFromWindow(opt_window);
    -  });
    -
    -  this.getEditableDomHelper();
    -  this.$anyTimes();
    -  this.$returns(goog.dom.getDomHelper(opt_window.document));
    -
    -  this.usesIframe();
    -  this.$anyTimes();
    -
    -  this.getBaseZindex();
    -  this.$anyTimes();
    -  this.$returns(0);
    -
    -  this.restoreSavedRange(goog.testing.mockmatchers.ignoreArgument);
    -  this.$anyTimes();
    -  this.$does(function(range) {
    -    if (range) {
    -      range.restore();
    -    }
    -    this.focus();
    -  });
    -
    -  // These methods cannot be set on the prototype, because the prototype
    -  // gets stepped on by the mock framework.
    -  var inModalMode = false;
    -
    -  /**
    -   * @return {boolean} Whether we're in modal interaction mode.
    -   */
    -  this.inModalMode = function() {
    -    return inModalMode;
    -  };
    -
    -  /**
    -   * @param {boolean} mode Sets whether we're in modal interaction mode.
    -   */
    -  this.setModalMode = function(mode) {
    -    inModalMode = mode;
    -  };
    -
    -  var uneditable = false;
    -
    -  /**
    -   * @return {boolean} Whether the field is uneditable.
    -   */
    -  this.isUneditable = function() {
    -    return uneditable;
    -  };
    -
    -  /**
    -   * @param {boolean} isUneditable Whether the field is uneditable.
    -   */
    -  this.setUneditable = function(isUneditable) {
    -    uneditable = isUneditable;
    -  };
    -};
    -goog.inherits(goog.testing.editor.FieldMock, goog.testing.LooseMock);
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/editor/testhelper.js b/src/database/third_party/closure-library/closure/goog/testing/editor/testhelper.js
    deleted file mode 100644
    index 763e3da5327..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/editor/testhelper.js
    +++ /dev/null
    @@ -1,180 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Class that allows for simple text editing tests.
    - *
    - * @author robbyw@google.com (Robby Walker)
    - */
    -
    -goog.provide('goog.testing.editor.TestHelper');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.dom');
    -goog.require('goog.dom.Range');
    -goog.require('goog.editor.BrowserFeature');
    -goog.require('goog.editor.node');
    -goog.require('goog.editor.plugins.AbstractBubblePlugin');
    -goog.require('goog.testing.dom');
    -
    -
    -
    -/**
    - * Create a new test controller.
    - * @param {Element} root The root editable element.
    - * @constructor
    - * @extends {goog.Disposable}
    - * @final
    - */
    -goog.testing.editor.TestHelper = function(root) {
    -  if (!root) {
    -    throw Error('Null root');
    -  }
    -  goog.Disposable.call(this);
    -
    -  /**
    -   * Convenience variable for root DOM element.
    -   * @type {!Element}
    -   * @private
    -   */
    -  this.root_ = root;
    -
    -  /**
    -   * The starting HTML of the editable element.
    -   * @type {string}
    -   * @private
    -   */
    -  this.savedHtml_ = '';
    -};
    -goog.inherits(goog.testing.editor.TestHelper, goog.Disposable);
    -
    -
    -/**
    - * Selects a new root element.
    - * @param {Element} root The root editable element.
    - */
    -goog.testing.editor.TestHelper.prototype.setRoot = function(root) {
    -  if (!root) {
    -    throw Error('Null root');
    -  }
    -  this.root_ = root;
    -};
    -
    -
    -/**
    - * Make the root element editable.  Alse saves its HTML to be restored
    - * in tearDown.
    - */
    -goog.testing.editor.TestHelper.prototype.setUpEditableElement = function() {
    -  this.savedHtml_ = this.root_.innerHTML;
    -  if (goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE) {
    -    this.root_.contentEditable = true;
    -  } else {
    -    this.root_.ownerDocument.designMode = 'on';
    -  }
    -  this.root_.setAttribute('g_editable', 'true');
    -};
    -
    -
    -/**
    - * Reset the element previously initialized, restoring its HTML and making it
    - * non editable.
    - * @suppress {accessControls} Private state of
    - *     {@link goog.editor.plugins.AbstractBubblePlugin} is accessed for test
    - *     purposes.
    - */
    -goog.testing.editor.TestHelper.prototype.tearDownEditableElement = function() {
    -  if (goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE) {
    -    this.root_.contentEditable = false;
    -  } else {
    -    this.root_.ownerDocument.designMode = 'off';
    -  }
    -  goog.dom.removeChildren(this.root_);
    -  this.root_.innerHTML = this.savedHtml_;
    -  this.root_.removeAttribute('g_editable');
    -
    -  if (goog.editor.plugins && goog.editor.plugins.AbstractBubblePlugin) {
    -    // Remove old bubbles.
    -    for (var key in goog.editor.plugins.AbstractBubblePlugin.bubbleMap_) {
    -      goog.editor.plugins.AbstractBubblePlugin.bubbleMap_[key].dispose();
    -    }
    -    // Ensure we get a new bubble for each test.
    -    goog.editor.plugins.AbstractBubblePlugin.bubbleMap_ = {};
    -  }
    -};
    -
    -
    -/**
    - * Assert that the html in 'root' is substantially similar to htmlPattern.
    - * This method tests for the same set of styles, and for the same order of
    - * nodes.  Breaking whitespace nodes are ignored.  Elements can be annotated
    - * with classnames corresponding to keys in goog.userAgent and will be
    - * expected to show up in that user agent and expected not to show up in
    - * others.
    - * @param {string} htmlPattern The pattern to match.
    - */
    -goog.testing.editor.TestHelper.prototype.assertHtmlMatches = function(
    -    htmlPattern) {
    -  goog.testing.dom.assertHtmlContentsMatch(htmlPattern, this.root_);
    -};
    -
    -
    -/**
    - * Finds the first text node descendant of root with the given content.
    - * @param {string|RegExp} textOrRegexp The text to find, or a regular
    - *     expression to find a match of.
    - * @return {Node} The first text node that matches, or null if none is found.
    - */
    -goog.testing.editor.TestHelper.prototype.findTextNode = function(textOrRegexp) {
    -  return goog.testing.dom.findTextNode(textOrRegexp, this.root_);
    -};
    -
    -
    -/**
    - * Select from the given from offset in the given from node to the given
    - * to offset in the optionally given to node. If nodes are passed in, uses them,
    - * otherwise uses findTextNode to find the nodes to select. Selects a caret
    - * if opt_to and opt_toOffset are not given.
    - * @param {Node|string} from Node or text of the node to start the selection at.
    - * @param {number} fromOffset Offset within the above node to start the
    - *     selection at.
    - * @param {Node|string=} opt_to Node or text of the node to end the selection
    - *     at.
    - * @param {number=} opt_toOffset Offset within the above node to end the
    - *     selection at.
    - */
    -goog.testing.editor.TestHelper.prototype.select = function(from, fromOffset,
    -    opt_to, opt_toOffset) {
    -  var end;
    -  var start = end = goog.isString(from) ? this.findTextNode(from) : from;
    -  var endOffset;
    -  var startOffset = endOffset = fromOffset;
    -
    -  if (opt_to && goog.isNumber(opt_toOffset)) {
    -    end = goog.isString(opt_to) ? this.findTextNode(opt_to) : opt_to;
    -    endOffset = opt_toOffset;
    -  }
    -
    -  goog.dom.Range.createFromNodes(start, startOffset, end, endOffset).select();
    -};
    -
    -
    -/** @override */
    -goog.testing.editor.TestHelper.prototype.disposeInternal = function() {
    -  if (goog.editor.node.isEditableContainer(this.root_)) {
    -    this.tearDownEditableElement();
    -  }
    -  delete this.root_;
    -  goog.testing.editor.TestHelper.base(this, 'disposeInternal');
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/editor/testhelper_test.html b/src/database/third_party/closure-library/closure/goog/testing/editor/testhelper_test.html
    deleted file mode 100644
    index 8f540e2f04b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/editor/testhelper_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html lang="en" dir="ltr">
    - <head>
    -  <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.testing.editor.TestHelper
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.editor.TestHelperTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="root">
    -  </div>
    -  <div id="root2">Root 2</div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/editor/testhelper_test.js b/src/database/third_party/closure-library/closure/goog/testing/editor/testhelper_test.js
    deleted file mode 100644
    index 195645979f7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/editor/testhelper_test.js
    +++ /dev/null
    @@ -1,175 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.editor.TestHelperTest');
    -goog.setTestOnly('goog.testing.editor.TestHelperTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.editor.node');
    -goog.require('goog.testing.editor.TestHelper');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -var root;
    -var helper;
    -
    -function setUp() {
    -  root = goog.dom.getElement('root');
    -  goog.dom.removeChildren(root);
    -  helper = new goog.testing.editor.TestHelper(root);
    -}
    -
    -function tearDown() {
    -  helper.dispose();
    -}
    -
    -function testSetRoot() {
    -  helper.setRoot(goog.dom.getElement('root2'));
    -  helper.assertHtmlMatches('Root 2');
    -}
    -
    -function testSetupEditableElement() {
    -  helper.setUpEditableElement();
    -  assertTrue(goog.editor.node.isEditableContainer(root));
    -}
    -
    -function testTearDownEditableElement() {
    -  helper.setUpEditableElement();
    -  assertTrue(goog.editor.node.isEditableContainer(root));
    -
    -  helper.tearDownEditableElement();
    -  assertFalse(goog.editor.node.isEditableContainer(root));
    -}
    -
    -function testFindNode() {
    -  // Test the easiest case.
    -  root.innerHTML = 'a<br>b';
    -  assertEquals(helper.findTextNode('a'), root.firstChild);
    -  assertEquals(helper.findTextNode('b'), root.lastChild);
    -  assertNull(helper.findTextNode('c'));
    -}
    -
    -function testFindNodeDuplicate() {
    -  // Test duplicate.
    -  root.innerHTML = 'c<br>c';
    -  assertEquals('Should return first duplicate', helper.findTextNode('c'),
    -      root.firstChild);
    -}
    -
    -function findNodeWithHierarchy() {
    -  // Test a more complicated hierarchy.
    -  root.innerHTML = '<div>a<p>b<span>c</span>d</p>e</div>';
    -  assertEquals(goog.dom.TagName.DIV,
    -      helper.findTextNode('a').parentNode.tagName);
    -  assertEquals(goog.dom.TagName.P,
    -      helper.findTextNode('b').parentNode.tagName);
    -  assertEquals(goog.dom.TagName.SPAN,
    -      helper.findTextNode('c').parentNode.tagName);
    -  assertEquals(goog.dom.TagName.P,
    -      helper.findTextNode('d').parentNode.tagName);
    -  assertEquals(goog.dom.TagName.DIV,
    -      helper.findTextNode('e').parentNode.tagName);
    -}
    -
    -function setUpAssertHtmlMatches() {
    -  var tag1, tag2;
    -  if (goog.userAgent.IE) {
    -    tag1 = goog.dom.TagName.DIV;
    -  } else if (goog.userAgent.WEBKIT) {
    -    tag1 = goog.dom.TagName.P;
    -    tag2 = goog.dom.TagName.BR;
    -  } else if (goog.userAgent.GECKO) {
    -    tag1 = goog.dom.TagName.SPAN;
    -    tag2 = goog.dom.TagName.BR;
    -  }
    -
    -  var parent = goog.dom.createDom(goog.dom.TagName.DIV);
    -  root.appendChild(parent);
    -  parent.style.fontSize = '2em';
    -  parent.style.display = 'none';
    -  if (goog.userAgent.IE || goog.userAgent.GECKO) {
    -    parent.appendChild(goog.dom.createTextNode('NonWebKitText'));
    -  }
    -
    -  if (tag1) {
    -    var e1 = goog.dom.createDom(tag1);
    -    parent.appendChild(e1);
    -    parent = e1;
    -  }
    -  if (tag2) {
    -    parent.appendChild(goog.dom.createDom(tag2));
    -  }
    -  parent.appendChild(goog.dom.createTextNode('Text'));
    -  if (goog.userAgent.WEBKIT) {
    -    root.firstChild.appendChild(goog.dom.createTextNode('WebKitText'));
    -  }
    -}
    -
    -function testAssertHtmlMatches() {
    -  setUpAssertHtmlMatches();
    -
    -  helper.assertHtmlMatches('<div style="display: none; font-size: 2em">' +
    -      '[[IE GECKO]]NonWebKitText<div class="IE"><p class="WEBKIT">' +
    -      '<span class="GECKO"><br class="GECKO WEBKIT">Text</span></p></div>' +
    -      '</div>[[WEBKIT]]WebKitText');
    -}
    -
    -function testAssertHtmlMismatchText() {
    -  setUpAssertHtmlMatches();
    -
    -  var e = assertThrows('Should fail due to mismatched text', function() {
    -    helper.assertHtmlMatches('<div style="display: none; font-size: 2em">' +
    -        '[[IE GECKO]]NonWebKitText<div class="IE"><p class="WEBKIT">' +
    -        '<span class="GECKO"><br class="GECKO WEBKIT">Bad</span></p></div>' +
    -        '</div>[[WEBKIT]]Extra');
    -  });
    -  assertContains('Text should match', e.message);
    -}
    -
    -function testAssertHtmlMismatchTag() {
    -  setUpAssertHtmlMatches();
    -
    -  var e = assertThrows('Should fail due to mismatched tag', function() {
    -    helper.assertHtmlMatches('<span style="display: none; font-size: 2em">' +
    -        '[[IE GECKO]]NonWebKitText<div class="IE"><p class="WEBKIT">' +
    -        '<span class="GECKO"><br class="GECKO WEBKIT">Text</span></p></div>' +
    -        '</span>[[WEBKIT]]Extra');
    -  });
    -  assertContains('Tag names should match', e.message);
    -}
    -
    -function testAssertHtmlMismatchStyle() {
    -  setUpAssertHtmlMatches();
    -
    -  var e = assertThrows('Should fail due to mismatched style', function() {
    -    helper.assertHtmlMatches('<div style="display: none; font-size: 3em">' +
    -        '[[IE GECKO]]NonWebKitText<div class="IE"><p class="WEBKIT">' +
    -        '<span class="GECKO"><br class="GECKO WEBKIT">Text</span></p></div>' +
    -        '</div>[[WEBKIT]]Extra');
    -  });
    -  assertContains('Should have same styles', e.message);
    -}
    -
    -function testAssertHtmlMismatchOptionalText() {
    -  setUpAssertHtmlMatches();
    -
    -  var e = assertThrows('Should fail due to mismatched style', function() {
    -    helper.assertHtmlMatches('<div style="display: none; font-size: 2em">' +
    -        '[[IE GECKO]]Bad<div class="IE"><p class="WEBKIT">' +
    -        '<span class="GECKO"><br class="GECKO WEBKIT">Text</span></p></div>' +
    -        '</div>[[WEBKIT]]Bad');
    -  });
    -  assertContains('Text should match', e.message);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/events/eventobserver.js b/src/database/third_party/closure-library/closure/goog/testing/events/eventobserver.js
    deleted file mode 100644
    index 77ae69d3b2d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/events/eventobserver.js
    +++ /dev/null
    @@ -1,87 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Event observer.
    - *
    - * Provides an event observer that holds onto events that it handles.  This
    - * can be used in unit testing to verify an event target's events --
    - * that the order count, types, etc. are correct.
    - *
    - * Example usage:
    - * <pre>
    - * var observer = new goog.testing.events.EventObserver();
    - * var widget = new foo.Widget();
    - * goog.events.listen(widget, ['select', 'submit'], observer);
    - * // Simulate user action of 3 select events and 2 submit events.
    - * assertEquals(3, observer.getEvents('select').length);
    - * assertEquals(2, observer.getEvents('submit').length);
    - * </pre>
    - *
    - * @author nnaze@google.com (Nathan Naze)
    - */
    -
    -goog.provide('goog.testing.events.EventObserver');
    -
    -goog.require('goog.array');
    -
    -
    -
    -/**
    - * Event observer.  Implements a handleEvent interface so it may be used as
    - * a listener in listening functions and methods.
    - * @see goog.events.listen
    - * @see goog.events.EventHandler
    - * @constructor
    - * @final
    - */
    -goog.testing.events.EventObserver = function() {
    -
    -  /**
    -   * A list of events handled by the observer in order of handling, oldest to
    -   * newest.
    -   * @type {!Array<!goog.events.Event>}
    -   * @private
    -   */
    -  this.events_ = [];
    -};
    -
    -
    -/**
    - * Handles an event and remembers it.  Event listening functions and methods
    - * will call this method when this observer is used as a listener.
    - * @see goog.events.listen
    - * @see goog.events.EventHandler
    - * @param {!goog.events.Event} e Event to handle.
    - */
    -goog.testing.events.EventObserver.prototype.handleEvent = function(e) {
    -  this.events_.push(e);
    -};
    -
    -
    -/**
    - * @param {string=} opt_type If given, only return events of this type.
    - * @return {!Array<!goog.events.Event>} The events handled, oldest to newest.
    - */
    -goog.testing.events.EventObserver.prototype.getEvents = function(opt_type) {
    -  var events = goog.array.clone(this.events_);
    -
    -  if (opt_type) {
    -    events = goog.array.filter(events, function(event) {
    -      return event.type == opt_type;
    -    });
    -  }
    -
    -  return events;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/events/eventobserver_test.html b/src/database/third_party/closure-library/closure/goog/testing/events/eventobserver_test.html
    deleted file mode 100644
    index 772ed8061b1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/events/eventobserver_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.testing.events.EventObserver
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.events.EventObserverTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/events/eventobserver_test.js b/src/database/third_party/closure-library/closure/goog/testing/events/eventobserver_test.js
    deleted file mode 100644
    index efe9702decc..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/events/eventobserver_test.js
    +++ /dev/null
    @@ -1,67 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.events.EventObserverTest');
    -goog.setTestOnly('goog.testing.events.EventObserverTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.events');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.testing.events.EventObserver');
    -goog.require('goog.testing.jsunit');
    -
    -// Return an event's type
    -function getEventType(e) {
    -  return e.type;
    -}
    -
    -function testGetEvents() {
    -  var observer = new goog.testing.events.EventObserver();
    -  var target = new goog.events.EventTarget();
    -  goog.events.listen(target, ['foo', 'bar', 'baz'], observer);
    -
    -  var eventTypes = [
    -    'bar', 'baz', 'foo', 'qux', 'quux', 'corge', 'foo', 'baz'];
    -  goog.array.forEach(eventTypes, goog.bind(target.dispatchEvent, target));
    -
    -  var replayEvents = observer.getEvents();
    -
    -  assertArrayEquals('Only the listened-for event types should be remembered',
    -      ['bar', 'baz', 'foo', 'foo', 'baz'],
    -      goog.array.map(observer.getEvents(), getEventType));
    -
    -  assertArrayEquals(['bar'],
    -      goog.array.map(observer.getEvents('bar'), getEventType));
    -  assertArrayEquals(['baz', 'baz'],
    -      goog.array.map(observer.getEvents('baz'), getEventType));
    -  assertArrayEquals(['foo', 'foo'],
    -      goog.array.map(observer.getEvents('foo'), getEventType));
    -}
    -
    -function testHandleEvent() {
    -  var events = [
    -    new goog.events.Event('foo'),
    -    new goog.events.Event('bar'),
    -    new goog.events.Event('baz')
    -  ];
    -
    -  var observer = new goog.testing.events.EventObserver();
    -  goog.array.forEach(events, goog.bind(observer.handleEvent, observer));
    -
    -  assertArrayEquals(events, observer.getEvents());
    -  assertArrayEquals([events[0]], observer.getEvents('foo'));
    -  assertArrayEquals([events[1]], observer.getEvents('bar'));
    -  assertArrayEquals([events[2]], observer.getEvents('baz'));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/events/events.js b/src/database/third_party/closure-library/closure/goog/testing/events/events.js
    deleted file mode 100644
    index e2070ab6d02..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/events/events.js
    +++ /dev/null
    @@ -1,727 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Event Simulation.
    - *
    - * Utility functions for simulating events at the Closure level. All functions
    - * in this package generate events by calling goog.events.fireListeners,
    - * rather than interfacing with the browser directly. This is intended for
    - * testing purposes, and should not be used in production code.
    - *
    - * The decision to use Closure events and dispatchers instead of the browser's
    - * native events and dispatchers was conscious and deliberate. Native event
    - * dispatchers have their own set of quirks and edge cases. Pure JS dispatchers
    - * are more robust and transparent.
    - *
    - * If you think you need a testing mechanism that uses native Event objects,
    - * please, please email closure-tech first to explain your use case before you
    - * sink time into this.
    - *
    - * @author nicksantos@google.com (Nick Santos)
    - */
    -
    -goog.provide('goog.testing.events');
    -goog.provide('goog.testing.events.Event');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.asserts');
    -goog.require('goog.dom.NodeType');
    -goog.require('goog.events');
    -goog.require('goog.events.BrowserEvent');
    -goog.require('goog.events.BrowserFeature');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.object');
    -goog.require('goog.style');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * goog.events.BrowserEvent expects an Event so we provide one for JSCompiler.
    - *
    - * This clones a lot of the functionality of goog.events.Event. This used to
    - * use a mixin, but the mixin results in confusing the two types when compiled.
    - *
    - * @param {string} type Event Type.
    - * @param {Object=} opt_target Reference to the object that is the target of
    - *     this event.
    - * @constructor
    - * @extends {Event}
    - */
    -goog.testing.events.Event = function(type, opt_target) {
    -  this.type = type;
    -
    -  this.target = /** @type {EventTarget} */ (opt_target || null);
    -
    -  this.currentTarget = this.target;
    -};
    -
    -
    -/**
    - * Whether to cancel the event in internal capture/bubble processing for IE.
    - * @type {boolean}
    - * @public
    - * @suppress {underscore|visibility} Technically public, but referencing this
    - *     outside this package is strongly discouraged.
    - */
    -goog.testing.events.Event.prototype.propagationStopped_ = false;
    -
    -
    -/** @override */
    -goog.testing.events.Event.prototype.defaultPrevented = false;
    -
    -
    -/**
    - * Return value for in internal capture/bubble processing for IE.
    - * @type {boolean}
    - * @public
    - * @suppress {underscore|visibility} Technically public, but referencing this
    - *     outside this package is strongly discouraged.
    - */
    -goog.testing.events.Event.prototype.returnValue_ = true;
    -
    -
    -/** @override */
    -goog.testing.events.Event.prototype.stopPropagation = function() {
    -  this.propagationStopped_ = true;
    -};
    -
    -
    -/** @override */
    -goog.testing.events.Event.prototype.preventDefault = function() {
    -  this.defaultPrevented = true;
    -  this.returnValue_ = false;
    -};
    -
    -
    -/**
    - * Asserts an event target exists.  This will fail if target is not defined.
    - *
    - * TODO(nnaze): Gradually add this to the methods in this file, and eventually
    - *     update the method signatures to not take nullables.  See http://b/8961907
    - *
    - * @param {EventTarget} target A target to assert.
    - * @return {!EventTarget} The target, guaranteed to exist.
    - * @private
    - */
    -goog.testing.events.assertEventTarget_ = function(target) {
    -  return goog.asserts.assert(target, 'EventTarget should be defined.');
    -};
    -
    -
    -/**
    - * A static helper function that sets the mouse position to the event.
    - * @param {Event} event A simulated native event.
    - * @param {goog.math.Coordinate=} opt_coords Mouse position. Defaults to event's
    - * target's position (if available), otherwise (0, 0).
    - * @private
    - */
    -goog.testing.events.setEventClientXY_ = function(event, opt_coords) {
    -  if (!opt_coords && event.target &&
    -      event.target.nodeType == goog.dom.NodeType.ELEMENT) {
    -    try {
    -      opt_coords =
    -          goog.style.getClientPosition(/** @type {!Element} **/ (event.target));
    -    } catch (ex) {
    -      // IE sometimes throws if it can't get the position.
    -    }
    -  }
    -  event.clientX = opt_coords ? opt_coords.x : 0;
    -  event.clientY = opt_coords ? opt_coords.y : 0;
    -
    -  // Pretend the browser window is at (0, 0).
    -  event.screenX = event.clientX;
    -  event.screenY = event.clientY;
    -};
    -
    -
    -/**
    - * Simulates a mousedown, mouseup, and then click on the given event target,
    - * with the left mouse button.
    - * @param {EventTarget} target The target for the event.
    - * @param {goog.events.BrowserEvent.MouseButton=} opt_button Mouse button;
    - *     defaults to {@code goog.events.BrowserEvent.MouseButton.LEFT}.
    - * @param {goog.math.Coordinate=} opt_coords Mouse position. Defaults to event's
    - * target's position (if available), otherwise (0, 0).
    - * @param {Object=} opt_eventProperties Event properties to be mixed into the
    - *     BrowserEvent.
    - * @return {boolean} The returnValue of the sequence: false if preventDefault()
    - *     was called on any of the events, true otherwise.
    - */
    -goog.testing.events.fireClickSequence =
    -    function(target, opt_button, opt_coords, opt_eventProperties) {
    -  // Fire mousedown, mouseup, and click. Then return the bitwise AND of the 3.
    -  return !!(goog.testing.events.fireMouseDownEvent(
    -      target, opt_button, opt_coords, opt_eventProperties) &
    -            goog.testing.events.fireMouseUpEvent(
    -                target, opt_button, opt_coords, opt_eventProperties) &
    -            goog.testing.events.fireClickEvent(
    -                target, opt_button, opt_coords, opt_eventProperties));
    -};
    -
    -
    -/**
    - * Simulates the sequence of events fired by the browser when the user double-
    - * clicks the given target.
    - * @param {EventTarget} target The target for the event.
    - * @param {goog.math.Coordinate=} opt_coords Mouse position. Defaults to event's
    - * target's position (if available), otherwise (0, 0).
    - * @param {Object=} opt_eventProperties Event properties to be mixed into the
    - *     BrowserEvent.
    - * @return {boolean} The returnValue of the sequence: false if preventDefault()
    - *     was called on any of the events, true otherwise.
    - */
    -goog.testing.events.fireDoubleClickSequence = function(
    -    target, opt_coords, opt_eventProperties) {
    -  // Fire mousedown, mouseup, click, mousedown, mouseup, click, dblclick.
    -  // Then return the bitwise AND of the 7.
    -  var btn = goog.events.BrowserEvent.MouseButton.LEFT;
    -  return !!(goog.testing.events.fireMouseDownEvent(
    -      target, btn, opt_coords, opt_eventProperties) &
    -            goog.testing.events.fireMouseUpEvent(
    -                target, btn, opt_coords, opt_eventProperties) &
    -            goog.testing.events.fireClickEvent(
    -                target, btn, opt_coords, opt_eventProperties) &
    -            // IE fires a selectstart instead of the second mousedown in a
    -            // dblclick, but we don't care about selectstart.
    -            (goog.userAgent.IE ||
    -            goog.testing.events.fireMouseDownEvent(
    -                target, btn, opt_coords, opt_eventProperties)) &
    -            goog.testing.events.fireMouseUpEvent(
    -                target, btn, opt_coords, opt_eventProperties) &
    -            // IE doesn't fire the second click in a dblclick.
    -            (goog.userAgent.IE ||
    -            goog.testing.events.fireClickEvent(
    -                target, btn, opt_coords, opt_eventProperties)) &
    -            goog.testing.events.fireDoubleClickEvent(
    -                target, opt_coords, opt_eventProperties));
    -};
    -
    -
    -/**
    - * Simulates a complete keystroke (keydown, keypress, and keyup). Note that
    - * if preventDefault is called on the keydown, the keypress will not fire.
    - *
    - * @param {EventTarget} target The target for the event.
    - * @param {number} keyCode The keycode of the key pressed.
    - * @param {Object=} opt_eventProperties Event properties to be mixed into the
    - *     BrowserEvent.
    - * @return {boolean} The returnValue of the sequence: false if preventDefault()
    - *     was called on any of the events, true otherwise.
    - */
    -goog.testing.events.fireKeySequence = function(
    -    target, keyCode, opt_eventProperties) {
    -  return goog.testing.events.fireNonAsciiKeySequence(target, keyCode, keyCode,
    -                                                     opt_eventProperties);
    -};
    -
    -
    -/**
    - * Simulates a complete keystroke (keydown, keypress, and keyup) when typing
    - * a non-ASCII character. Same as fireKeySequence, the keypress will not fire
    - * if preventDefault is called on the keydown.
    - *
    - * @param {EventTarget} target The target for the event.
    - * @param {number} keyCode The keycode of the keydown and keyup events.
    - * @param {number} keyPressKeyCode The keycode of the keypress event.
    - * @param {Object=} opt_eventProperties Event properties to be mixed into the
    - *     BrowserEvent.
    - * @return {boolean} The returnValue of the sequence: false if preventDefault()
    - *     was called on any of the events, true otherwise.
    - */
    -goog.testing.events.fireNonAsciiKeySequence = function(
    -    target, keyCode, keyPressKeyCode, opt_eventProperties) {
    -  var keydown =
    -      new goog.testing.events.Event(goog.events.EventType.KEYDOWN, target);
    -  var keyup =
    -      new goog.testing.events.Event(goog.events.EventType.KEYUP, target);
    -  var keypress =
    -      new goog.testing.events.Event(goog.events.EventType.KEYPRESS, target);
    -  keydown.keyCode = keyup.keyCode = keyCode;
    -  keypress.keyCode = keyPressKeyCode;
    -
    -  if (opt_eventProperties) {
    -    goog.object.extend(keydown, opt_eventProperties);
    -    goog.object.extend(keyup, opt_eventProperties);
    -    goog.object.extend(keypress, opt_eventProperties);
    -  }
    -
    -  // Fire keydown, keypress, and keyup. Note that if the keydown is
    -  // prevent-defaulted, then the keypress will not fire.
    -  var result = true;
    -  if (!goog.testing.events.isBrokenGeckoMacActionKey_(keydown)) {
    -    result = goog.testing.events.fireBrowserEvent(keydown);
    -  }
    -  if (goog.events.KeyCodes.firesKeyPressEvent(
    -      keyCode, undefined, keydown.shiftKey, keydown.ctrlKey,
    -      keydown.altKey) && result) {
    -    result &= goog.testing.events.fireBrowserEvent(keypress);
    -  }
    -  return !!(result & goog.testing.events.fireBrowserEvent(keyup));
    -};
    -
    -
    -/**
    - * @param {goog.testing.events.Event} e The event.
    - * @return {boolean} Whether this is the Gecko/Mac's Meta-C/V/X, which
    - *     is broken and requires special handling.
    - * @private
    - */
    -goog.testing.events.isBrokenGeckoMacActionKey_ = function(e) {
    -  return goog.userAgent.MAC && goog.userAgent.GECKO &&
    -      (e.keyCode == goog.events.KeyCodes.C ||
    -       e.keyCode == goog.events.KeyCodes.X ||
    -       e.keyCode == goog.events.KeyCodes.V) && e.metaKey;
    -};
    -
    -
    -/**
    - * Simulates a mouseover event on the given target.
    - * @param {EventTarget} target The target for the event.
    - * @param {EventTarget} relatedTarget The related target for the event (e.g.,
    - *     the node that the mouse is being moved out of).
    - * @param {goog.math.Coordinate=} opt_coords Mouse position. Defaults to event's
    - * target's position (if available), otherwise (0, 0).
    - * @return {boolean} The returnValue of the event: false if preventDefault() was
    - *     called on it, true otherwise.
    - */
    -goog.testing.events.fireMouseOverEvent = function(target, relatedTarget,
    -    opt_coords) {
    -  var mouseover =
    -      new goog.testing.events.Event(goog.events.EventType.MOUSEOVER, target);
    -  mouseover.relatedTarget = relatedTarget;
    -  goog.testing.events.setEventClientXY_(mouseover, opt_coords);
    -  return goog.testing.events.fireBrowserEvent(mouseover);
    -};
    -
    -
    -/**
    - * Simulates a mousemove event on the given target.
    - * @param {EventTarget} target The target for the event.
    - * @param {goog.math.Coordinate=} opt_coords Mouse position. Defaults to event's
    - * target's position (if available), otherwise (0, 0).
    - * @return {boolean} The returnValue of the event: false if preventDefault() was
    - *     called on it, true otherwise.
    - */
    -goog.testing.events.fireMouseMoveEvent = function(target, opt_coords) {
    -  var mousemove =
    -      new goog.testing.events.Event(goog.events.EventType.MOUSEMOVE, target);
    -
    -  goog.testing.events.setEventClientXY_(mousemove, opt_coords);
    -  return goog.testing.events.fireBrowserEvent(mousemove);
    -};
    -
    -
    -/**
    - * Simulates a mouseout event on the given target.
    - * @param {EventTarget} target The target for the event.
    - * @param {EventTarget} relatedTarget The related target for the event (e.g.,
    - *     the node that the mouse is being moved into).
    - * @param {goog.math.Coordinate=} opt_coords Mouse position. Defaults to event's
    - * target's position (if available), otherwise (0, 0).
    - * @return {boolean} The returnValue of the event: false if preventDefault() was
    - *     called on it, true otherwise.
    - */
    -goog.testing.events.fireMouseOutEvent = function(target, relatedTarget,
    -    opt_coords) {
    -  var mouseout =
    -      new goog.testing.events.Event(goog.events.EventType.MOUSEOUT, target);
    -  mouseout.relatedTarget = relatedTarget;
    -  goog.testing.events.setEventClientXY_(mouseout, opt_coords);
    -  return goog.testing.events.fireBrowserEvent(mouseout);
    -};
    -
    -
    -/**
    - * Simulates a mousedown event on the given target.
    - * @param {EventTarget} target The target for the event.
    - * @param {goog.events.BrowserEvent.MouseButton=} opt_button Mouse button;
    - *     defaults to {@code goog.events.BrowserEvent.MouseButton.LEFT}.
    - * @param {goog.math.Coordinate=} opt_coords Mouse position. Defaults to event's
    - * target's position (if available), otherwise (0, 0).
    - * @param {Object=} opt_eventProperties Event properties to be mixed into the
    - *     BrowserEvent.
    - * @return {boolean} The returnValue of the event: false if preventDefault() was
    - *     called on it, true otherwise.
    - */
    -goog.testing.events.fireMouseDownEvent =
    -    function(target, opt_button, opt_coords, opt_eventProperties) {
    -
    -  var button = opt_button || goog.events.BrowserEvent.MouseButton.LEFT;
    -  button = !goog.events.BrowserFeature.HAS_W3C_BUTTON ?
    -      goog.events.BrowserEvent.IEButtonMap[button] : button;
    -  return goog.testing.events.fireMouseButtonEvent_(
    -      goog.events.EventType.MOUSEDOWN, target, button, opt_coords,
    -      opt_eventProperties);
    -};
    -
    -
    -/**
    - * Simulates a mouseup event on the given target.
    - * @param {EventTarget} target The target for the event.
    - * @param {goog.events.BrowserEvent.MouseButton=} opt_button Mouse button;
    - *     defaults to {@code goog.events.BrowserEvent.MouseButton.LEFT}.
    - * @param {goog.math.Coordinate=} opt_coords Mouse position. Defaults to event's
    - * target's position (if available), otherwise (0, 0).
    - * @param {Object=} opt_eventProperties Event properties to be mixed into the
    - *     BrowserEvent.
    - * @return {boolean} The returnValue of the event: false if preventDefault() was
    - *     called on it, true otherwise.
    - */
    -goog.testing.events.fireMouseUpEvent =
    -    function(target, opt_button, opt_coords, opt_eventProperties) {
    -  var button = opt_button || goog.events.BrowserEvent.MouseButton.LEFT;
    -  button = !goog.events.BrowserFeature.HAS_W3C_BUTTON ?
    -      goog.events.BrowserEvent.IEButtonMap[button] : button;
    -  return goog.testing.events.fireMouseButtonEvent_(
    -      goog.events.EventType.MOUSEUP, target, button, opt_coords,
    -      opt_eventProperties);
    -};
    -
    -
    -/**
    - * Simulates a click event on the given target. IE only supports click with
    - * the left mouse button.
    - * @param {EventTarget} target The target for the event.
    - * @param {goog.events.BrowserEvent.MouseButton=} opt_button Mouse button;
    - *     defaults to {@code goog.events.BrowserEvent.MouseButton.LEFT}.
    - * @param {goog.math.Coordinate=} opt_coords Mouse position. Defaults to event's
    - * target's position (if available), otherwise (0, 0).
    - * @param {Object=} opt_eventProperties Event properties to be mixed into the
    - *     BrowserEvent.
    - * @return {boolean} The returnValue of the event: false if preventDefault() was
    - *     called on it, true otherwise.
    - */
    -goog.testing.events.fireClickEvent =
    -    function(target, opt_button, opt_coords, opt_eventProperties) {
    -  return goog.testing.events.fireMouseButtonEvent_(goog.events.EventType.CLICK,
    -      target, opt_button, opt_coords, opt_eventProperties);
    -};
    -
    -
    -/**
    - * Simulates a double-click event on the given target. Always double-clicks
    - * with the left mouse button since no browser supports double-clicking with
    - * any other buttons.
    - * @param {EventTarget} target The target for the event.
    - * @param {goog.math.Coordinate=} opt_coords Mouse position. Defaults to event's
    - * target's position (if available), otherwise (0, 0).
    - * @param {Object=} opt_eventProperties Event properties to be mixed into the
    - *     BrowserEvent.
    - * @return {boolean} The returnValue of the event: false if preventDefault() was
    - *     called on it, true otherwise.
    - */
    -goog.testing.events.fireDoubleClickEvent =
    -    function(target, opt_coords, opt_eventProperties) {
    -  return goog.testing.events.fireMouseButtonEvent_(
    -      goog.events.EventType.DBLCLICK, target,
    -      goog.events.BrowserEvent.MouseButton.LEFT, opt_coords,
    -      opt_eventProperties);
    -};
    -
    -
    -/**
    - * Helper function to fire a mouse event.
    - * with the left mouse button since no browser supports double-clicking with
    - * any other buttons.
    - * @param {string} type The event type.
    - * @param {EventTarget} target The target for the event.
    - * @param {number=} opt_button Mouse button; defaults to
    - *     {@code goog.events.BrowserEvent.MouseButton.LEFT}.
    - * @param {goog.math.Coordinate=} opt_coords Mouse position. Defaults to event's
    - * target's position (if available), otherwise (0, 0).
    - * @param {Object=} opt_eventProperties Event properties to be mixed into the
    - *     BrowserEvent.
    - * @return {boolean} The returnValue of the event: false if preventDefault() was
    - *     called on it, true otherwise.
    - * @private
    - */
    -goog.testing.events.fireMouseButtonEvent_ =
    -    function(type, target, opt_button, opt_coords, opt_eventProperties) {
    -  var e =
    -      new goog.testing.events.Event(type, target);
    -  e.button = opt_button || goog.events.BrowserEvent.MouseButton.LEFT;
    -  goog.testing.events.setEventClientXY_(e, opt_coords);
    -  if (opt_eventProperties) {
    -    goog.object.extend(e, opt_eventProperties);
    -  }
    -  return goog.testing.events.fireBrowserEvent(e);
    -};
    -
    -
    -/**
    - * Simulates a contextmenu event on the given target.
    - * @param {EventTarget} target The target for the event.
    - * @param {goog.math.Coordinate=} opt_coords Mouse position. Defaults to event's
    - * target's position (if available), otherwise (0, 0).
    - * @return {boolean} The returnValue of the event: false if preventDefault() was
    - *     called on it, true otherwise.
    - */
    -goog.testing.events.fireContextMenuEvent = function(target, opt_coords) {
    -  var button = (goog.userAgent.MAC && goog.userAgent.WEBKIT) ?
    -      goog.events.BrowserEvent.MouseButton.LEFT :
    -      goog.events.BrowserEvent.MouseButton.RIGHT;
    -  var contextmenu =
    -      new goog.testing.events.Event(goog.events.EventType.CONTEXTMENU, target);
    -  contextmenu.button = !goog.events.BrowserFeature.HAS_W3C_BUTTON ?
    -      goog.events.BrowserEvent.IEButtonMap[button] : button;
    -  contextmenu.ctrlKey = goog.userAgent.MAC;
    -  goog.testing.events.setEventClientXY_(contextmenu, opt_coords);
    -  return goog.testing.events.fireBrowserEvent(contextmenu);
    -};
    -
    -
    -/**
    - * Simulates a mousedown, contextmenu, and the mouseup on the given event
    - * target, with the right mouse button.
    - * @param {EventTarget} target The target for the event.
    - * @param {goog.math.Coordinate=} opt_coords Mouse position. Defaults to event's
    - * target's position (if available), otherwise (0, 0).
    - * @return {boolean} The returnValue of the sequence: false if preventDefault()
    - *     was called on any of the events, true otherwise.
    - */
    -goog.testing.events.fireContextMenuSequence = function(target, opt_coords) {
    -  var props = goog.userAgent.MAC ? {ctrlKey: true} : {};
    -  var button = (goog.userAgent.MAC && goog.userAgent.WEBKIT) ?
    -      goog.events.BrowserEvent.MouseButton.LEFT :
    -      goog.events.BrowserEvent.MouseButton.RIGHT;
    -
    -  var result = goog.testing.events.fireMouseDownEvent(target,
    -      button, opt_coords, props);
    -  if (goog.userAgent.WINDOWS) {
    -    // All browsers are consistent on Windows.
    -    result &= goog.testing.events.fireMouseUpEvent(target,
    -        button, opt_coords) &
    -              goog.testing.events.fireContextMenuEvent(target, opt_coords);
    -  } else {
    -    result &= goog.testing.events.fireContextMenuEvent(target, opt_coords);
    -
    -    // GECKO on Mac and Linux always fires the mouseup after the contextmenu.
    -
    -    // WEBKIT is really weird.
    -    //
    -    // On Linux, it sometimes fires mouseup, but most of the time doesn't.
    -    // It's really hard to reproduce consistently. I think there's some
    -    // internal race condition. If contextmenu is preventDefaulted, then
    -    // mouseup always fires.
    -    //
    -    // On Mac, it always fires mouseup and then fires a click.
    -    result &= goog.testing.events.fireMouseUpEvent(target,
    -        button, opt_coords, props);
    -
    -    if (goog.userAgent.WEBKIT && goog.userAgent.MAC) {
    -      result &= goog.testing.events.fireClickEvent(
    -          target, button, opt_coords, props);
    -    }
    -  }
    -  return !!result;
    -};
    -
    -
    -/**
    - * Simulates a popstate event on the given target.
    - * @param {EventTarget} target The target for the event.
    - * @param {Object} state History state object.
    - * @return {boolean} The returnValue of the event: false if preventDefault() was
    - *     called on it, true otherwise.
    - */
    -goog.testing.events.firePopStateEvent = function(target, state) {
    -  var e = new goog.testing.events.Event(goog.events.EventType.POPSTATE, target);
    -  e.state = state;
    -  return goog.testing.events.fireBrowserEvent(e);
    -};
    -
    -
    -/**
    - * Simulate a blur event on the given target.
    - * @param {EventTarget} target The target for the event.
    - * @return {boolean} The value returned by firing the blur browser event,
    - *      which returns false iff 'preventDefault' was invoked.
    - */
    -goog.testing.events.fireBlurEvent = function(target) {
    -  var e = new goog.testing.events.Event(
    -      goog.events.EventType.BLUR, target);
    -  return goog.testing.events.fireBrowserEvent(e);
    -};
    -
    -
    -/**
    - * Simulate a focus event on the given target.
    - * @param {EventTarget} target The target for the event.
    - * @return {boolean} The value returned by firing the focus browser event,
    - *     which returns false iff 'preventDefault' was invoked.
    - */
    -goog.testing.events.fireFocusEvent = function(target) {
    -  var e = new goog.testing.events.Event(
    -      goog.events.EventType.FOCUS, target);
    -  return goog.testing.events.fireBrowserEvent(e);
    -};
    -
    -
    -/**
    - * Simulates an event's capturing and bubbling phases.
    - * @param {Event} event A simulated native event. It will be wrapped in a
    - *     normalized BrowserEvent and dispatched to Closure listeners on all
    - *     ancestors of its target (inclusive).
    - * @return {boolean} The returnValue of the event: false if preventDefault() was
    - *     called on it, true otherwise.
    - */
    -goog.testing.events.fireBrowserEvent = function(event) {
    -  event.returnValue_ = true;
    -
    -  // generate a list of ancestors
    -  var ancestors = [];
    -  for (var current = event.target; current; current = current.parentNode) {
    -    ancestors.push(current);
    -  }
    -
    -  // dispatch capturing listeners
    -  for (var j = ancestors.length - 1;
    -       j >= 0 && !event.propagationStopped_;
    -       j--) {
    -    goog.events.fireListeners(ancestors[j], event.type, true,
    -        new goog.events.BrowserEvent(event, ancestors[j]));
    -  }
    -
    -  // dispatch bubbling listeners
    -  for (var j = 0;
    -       j < ancestors.length && !event.propagationStopped_;
    -       j++) {
    -    goog.events.fireListeners(ancestors[j], event.type, false,
    -        new goog.events.BrowserEvent(event, ancestors[j]));
    -  }
    -
    -  return event.returnValue_;
    -};
    -
    -
    -/**
    - * Simulates a touchstart event on the given target.
    - * @param {EventTarget} target The target for the event.
    - * @param {goog.math.Coordinate=} opt_coords Touch position. Defaults to event's
    - *     target's position (if available), otherwise (0, 0).
    - * @param {Object=} opt_eventProperties Event properties to be mixed into the
    - *     BrowserEvent.
    - * @return {boolean} The returnValue of the event: false if preventDefault() was
    - *     called on it, true otherwise.
    - */
    -goog.testing.events.fireTouchStartEvent = function(
    -    target, opt_coords, opt_eventProperties) {
    -  // TODO: Support multi-touch events with array of coordinates.
    -  var touchstart =
    -      new goog.testing.events.Event(goog.events.EventType.TOUCHSTART, target);
    -  goog.testing.events.setEventClientXY_(touchstart, opt_coords);
    -  if (opt_eventProperties) {
    -    goog.object.extend(touchstart, opt_eventProperties);
    -  }
    -  return goog.testing.events.fireBrowserEvent(touchstart);
    -};
    -
    -
    -/**
    - * Simulates a touchmove event on the given target.
    - * @param {EventTarget} target The target for the event.
    - * @param {goog.math.Coordinate=} opt_coords Touch position. Defaults to event's
    - *     target's position (if available), otherwise (0, 0).
    - * @param {Object=} opt_eventProperties Event properties to be mixed into the
    - *     BrowserEvent.
    - * @return {boolean} The returnValue of the event: false if preventDefault() was
    - *     called on it, true otherwise.
    - */
    -goog.testing.events.fireTouchMoveEvent = function(
    -    target, opt_coords, opt_eventProperties) {
    -  // TODO: Support multi-touch events with array of coordinates.
    -  var touchmove =
    -      new goog.testing.events.Event(goog.events.EventType.TOUCHMOVE, target);
    -  goog.testing.events.setEventClientXY_(touchmove, opt_coords);
    -  if (opt_eventProperties) {
    -    goog.object.extend(touchmove, opt_eventProperties);
    -  }
    -  return goog.testing.events.fireBrowserEvent(touchmove);
    -};
    -
    -
    -/**
    - * Simulates a touchend event on the given target.
    - * @param {EventTarget} target The target for the event.
    - * @param {goog.math.Coordinate=} opt_coords Touch position. Defaults to event's
    - *     target's position (if available), otherwise (0, 0).
    - * @param {Object=} opt_eventProperties Event properties to be mixed into the
    - *     BrowserEvent.
    - * @return {boolean} The returnValue of the event: false if preventDefault() was
    - *     called on it, true otherwise.
    - */
    -goog.testing.events.fireTouchEndEvent = function(
    -    target, opt_coords, opt_eventProperties) {
    -  // TODO: Support multi-touch events with array of coordinates.
    -  var touchend =
    -      new goog.testing.events.Event(goog.events.EventType.TOUCHEND, target);
    -  goog.testing.events.setEventClientXY_(touchend, opt_coords);
    -  if (opt_eventProperties) {
    -    goog.object.extend(touchend, opt_eventProperties);
    -  }
    -  return goog.testing.events.fireBrowserEvent(touchend);
    -};
    -
    -
    -/**
    - * Simulates a simple touch sequence on the given target.
    - * @param {EventTarget} target The target for the event.
    - * @param {goog.math.Coordinate=} opt_coords Touch position. Defaults to event
    - *     target's position (if available), otherwise (0, 0).
    - * @param {Object=} opt_eventProperties Event properties to be mixed into the
    - *     BrowserEvent.
    - * @return {boolean} The returnValue of the sequence: false if preventDefault()
    - *     was called on any of the events, true otherwise.
    - */
    -goog.testing.events.fireTouchSequence = function(
    -    target, opt_coords, opt_eventProperties) {
    -  // TODO: Support multi-touch events with array of coordinates.
    -  // Fire touchstart, touchmove, touchend then return the bitwise AND of the 3.
    -  return !!(goog.testing.events.fireTouchStartEvent(
    -      target, opt_coords, opt_eventProperties) &
    -            goog.testing.events.fireTouchEndEvent(
    -                target, opt_coords, opt_eventProperties));
    -};
    -
    -
    -/**
    - * Mixins a listenable into the given object. This turns the object
    - * into a goog.events.Listenable. This is useful, for example, when
    - * you need to mock a implementation of listenable and still want it
    - * to work with goog.events.
    - * @param {!Object} obj The object to mixin into.
    - */
    -goog.testing.events.mixinListenable = function(obj) {
    -  var listenable = new goog.events.EventTarget();
    -
    -  listenable.setTargetForTesting(obj);
    -
    -  var listenablePrototype = goog.events.EventTarget.prototype;
    -  var disposablePrototype = goog.Disposable.prototype;
    -  for (var key in listenablePrototype) {
    -    if (listenablePrototype.hasOwnProperty(key) ||
    -        disposablePrototype.hasOwnProperty(key)) {
    -      var member = listenablePrototype[key];
    -      if (goog.isFunction(member)) {
    -        obj[key] = goog.bind(member, listenable);
    -      } else {
    -        obj[key] = member;
    -      }
    -    }
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/events/events_test.html b/src/database/third_party/closure-library/closure/goog/testing/events/events_test.html
    deleted file mode 100644
    index 910b0f2a01a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/events/events_test.html
    +++ /dev/null
    @@ -1,41 +0,0 @@
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!DOCTYPE html>
    -<html lang="en" dir="ltr">
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <!--
    -
    -  Author: nicksantos@google.com (Nick Santos)
    -  -->
    -  <title>
    -   Closure Unit Tests - goog.testing.events
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.eventsTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="root">
    -  </div>
    -  <input id="testButton" type="input" value="Click Me" />
    -  <div id="input">
    -   Prevent Default these events:
    -   <br />
    -  </div>
    -  <div id="log" style="position:absolute;right:0;top:0">
    -   Logged events:
    -  </div>
    -  <div id="parentEl">
    -   <div id="childEl">
    -    hello!
    -   </div>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/events/events_test.js b/src/database/third_party/closure-library/closure/goog/testing/events/events_test.js
    deleted file mode 100644
    index 8c642ec5176..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/events/events_test.js
    +++ /dev/null
    @@ -1,624 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.eventsTest');
    -goog.setTestOnly('goog.testing.eventsTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.string');
    -goog.require('goog.style');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -goog.require('goog.userAgent');
    -
    -var firedEventTypes;
    -var firedEventCoordinates;
    -var firedScreenCoordinates;
    -var firedShiftKeys;
    -var firedKeyCodes;
    -var root;
    -var log;
    -var input;
    -var testButton;
    -var parentEl;
    -var childEl;
    -var coordinate = new goog.math.Coordinate(123, 456);
    -var stubs = new goog.testing.PropertyReplacer();
    -var eventCount;
    -
    -function setUpPage() {
    -  root = goog.dom.getElement('root');
    -  log = goog.dom.getElement('log');
    -  input = goog.dom.getElement('input');
    -  testButton = goog.dom.getElement('testButton');
    -  parentEl = goog.dom.getElement('parentEl');
    -  childEl = goog.dom.getElement('childEl');
    -}
    -
    -function setUp() {
    -  stubs.reset();
    -  goog.events.removeAll(root);
    -  goog.events.removeAll(log);
    -  goog.events.removeAll(input);
    -  goog.events.removeAll(testButton);
    -  goog.events.removeAll(parentEl);
    -  goog.events.removeAll(childEl);
    -
    -  root.innerHTML = '';
    -  firedEventTypes = [];
    -  firedEventCoordinates = [];
    -  firedScreenCoordinates = [];
    -  firedShiftKeys = [];
    -  firedKeyCodes = [];
    -
    -  for (var key in goog.events.EventType) {
    -    goog.events.listen(root, goog.events.EventType[key], function(e) {
    -      firedEventTypes.push(e.type);
    -      var coord = new goog.math.Coordinate(e.clientX, e.clientY);
    -      firedEventCoordinates.push(coord);
    -
    -      firedScreenCoordinates.push(
    -          new goog.math.Coordinate(e.screenX, e.screenY));
    -
    -      firedShiftKeys.push(!!e.shiftKey);
    -      firedKeyCodes.push(e.keyCode);
    -    });
    -  }
    -
    -  eventCount = {
    -    parentBubble: 0,
    -    parentCapture: 0,
    -    childCapture: 0,
    -    childBubble: 0
    -  };
    -  // Event listeners for the capture/bubble test.
    -  goog.events.listen(parentEl, goog.events.EventType.CLICK,
    -      function(e) {
    -        eventCount.parentCapture++;
    -        assertEquals(parentEl, e.currentTarget);
    -        assertEquals(childEl, e.target);
    -      }, true);
    -  goog.events.listen(childEl, goog.events.EventType.CLICK,
    -      function(e) {
    -        eventCount.childCapture++;
    -        assertEquals(childEl, e.currentTarget);
    -        assertEquals(childEl, e.target);
    -      }, true);
    -  goog.events.listen(childEl, goog.events.EventType.CLICK,
    -      function(e) {
    -        eventCount.childBubble++;
    -        assertEquals(childEl, e.currentTarget);
    -        assertEquals(childEl, e.target);
    -      });
    -  goog.events.listen(parentEl, goog.events.EventType.CLICK,
    -      function(e) {
    -        eventCount.parentBubble++;
    -        assertEquals(parentEl, e.currentTarget);
    -        assertEquals(childEl, e.target);
    -      });
    -}
    -
    -function tearDownPage() {
    -  for (var key in goog.events.EventType) {
    -    var type = goog.events.EventType[key];
    -    if (type == 'mousemove' || type == 'mouseout' || type == 'mouseover') {
    -      continue;
    -    }
    -    goog.dom.appendChild(input,
    -        goog.dom.createDom('label', null,
    -            goog.dom.createDom('input',
    -                {'id': type, 'type': 'checkbox'}),
    -            type,
    -            goog.dom.createDom('br')));
    -    goog.events.listen(testButton, type, function(e) {
    -      if (goog.dom.getElement(e.type).checked) {
    -        e.preventDefault();
    -      }
    -
    -      log.innerHTML += goog.string.subs('<br />%s (%s, %s)',
    -          e.type, e.clientX, e.clientY);
    -    });
    -  }
    -}
    -
    -function testMouseOver() {
    -  goog.testing.events.fireMouseOverEvent(root, null);
    -  goog.testing.events.fireMouseOverEvent(root, null, coordinate);
    -  assertEventTypes(['mouseover', 'mouseover']);
    -  assertCoordinates([goog.style.getClientPosition(root), coordinate]);
    -}
    -
    -function testMouseOut() {
    -  goog.testing.events.fireMouseOutEvent(root, null);
    -  goog.testing.events.fireMouseOutEvent(root, null, coordinate);
    -  assertEventTypes(['mouseout', 'mouseout']);
    -  assertCoordinates([goog.style.getClientPosition(root), coordinate]);
    -}
    -
    -function testFocus() {
    -  goog.testing.events.fireFocusEvent(root);
    -  assertEventTypes(['focus']);
    -}
    -
    -function testBlur() {
    -  goog.testing.events.fireBlurEvent(root);
    -  assertEventTypes(['blur']);
    -}
    -
    -function testClickSequence() {
    -  assertTrue(goog.testing.events.fireClickSequence(root));
    -  assertEventTypes(['mousedown', 'mouseup', 'click']);
    -  var rootPosition = goog.style.getClientPosition(root);
    -  assertCoordinates([rootPosition, rootPosition, rootPosition]);
    -}
    -
    -function testClickSequenceWithCoordinate() {
    -  assertTrue(goog.testing.events.fireClickSequence(root, null, coordinate));
    -  assertCoordinates([coordinate, coordinate, coordinate]);
    -  assertArrayEquals([false, false, false], firedShiftKeys);
    -}
    -
    -function testTouchStart() {
    -  goog.testing.events.fireTouchStartEvent(root);
    -  goog.testing.events.fireTouchStartEvent(root, coordinate);
    -  assertEventTypes(['touchstart', 'touchstart']);
    -  assertCoordinates([goog.style.getClientPosition(root), coordinate]);
    -}
    -
    -function testTouchMove() {
    -  goog.testing.events.fireTouchMoveEvent(root);
    -  goog.testing.events.fireTouchMoveEvent(root, coordinate, {touches: []});
    -  assertEventTypes(['touchmove', 'touchmove']);
    -  assertCoordinates([goog.style.getClientPosition(root), coordinate]);
    -}
    -
    -function testTouchEnd() {
    -  goog.testing.events.fireTouchEndEvent(root);
    -  goog.testing.events.fireTouchEndEvent(root, coordinate);
    -  assertEventTypes(['touchend', 'touchend']);
    -  assertCoordinates([goog.style.getClientPosition(root), coordinate]);
    -}
    -
    -function testTouchSequence() {
    -  assertTrue(goog.testing.events.fireTouchSequence(root));
    -  assertEventTypes(['touchstart', 'touchend']);
    -  var rootPosition = goog.style.getClientPosition(root);
    -  assertCoordinates([rootPosition, rootPosition]);
    -}
    -
    -function testTouchSequenceWithCoordinate() {
    -  assertTrue(goog.testing.events.fireTouchSequence(root, coordinate));
    -  assertCoordinates([coordinate, coordinate]);
    -}
    -
    -function testClickSequenceWithEventProperty() {
    -  assertTrue(goog.testing.events.fireClickSequence(
    -      root, null, undefined, { shiftKey: true }));
    -  assertArrayEquals([true, true, true], firedShiftKeys);
    -}
    -
    -function testClickSequenceCancellingMousedown() {
    -  preventDefaultEventType('mousedown');
    -  assertFalse(goog.testing.events.fireClickSequence(root));
    -  assertEventTypes(['mousedown', 'mouseup', 'click']);
    -}
    -
    -function testClickSequenceCancellingMousedownWithCoordinate() {
    -  preventDefaultEventType('mousedown');
    -  assertFalse(goog.testing.events.fireClickSequence(root, null, coordinate));
    -  assertCoordinates([coordinate, coordinate, coordinate]);
    -}
    -
    -function testClickSequenceCancellingMouseup() {
    -  preventDefaultEventType('mouseup');
    -  assertFalse(goog.testing.events.fireClickSequence(root));
    -  assertEventTypes(['mousedown', 'mouseup', 'click']);
    -}
    -
    -function testClickSequenceCancellingMouseupWithCoordinate() {
    -  preventDefaultEventType('mouseup');
    -  assertFalse(goog.testing.events.fireClickSequence(root, null, coordinate));
    -  assertCoordinates([coordinate, coordinate, coordinate]);
    -}
    -
    -function testClickSequenceCancellingClick() {
    -  preventDefaultEventType('click');
    -  assertFalse(goog.testing.events.fireClickSequence(root));
    -  assertEventTypes(['mousedown', 'mouseup', 'click']);
    -}
    -
    -function testClickSequenceCancellingClickWithCoordinate() {
    -  preventDefaultEventType('click');
    -  assertFalse(goog.testing.events.fireClickSequence(root, null, coordinate));
    -  assertCoordinates([coordinate, coordinate, coordinate]);
    -}
    -
    -// For a double click, IE fires selectstart instead of the second mousedown,
    -// but we don't simulate selectstart. Also, IE doesn't fire the second click.
    -var DBLCLICK_SEQ = (goog.userAgent.IE ?
    -                    ['mousedown',
    -                     'mouseup',
    -                     'click',
    -                     'mouseup',
    -                     'dblclick'] :
    -                    ['mousedown',
    -                     'mouseup',
    -                     'click',
    -                     'mousedown',
    -                     'mouseup',
    -                     'click',
    -                     'dblclick']);
    -
    -
    -var DBLCLICK_SEQ_COORDS = goog.array.repeat(coordinate, DBLCLICK_SEQ.length);
    -
    -function testDoubleClickSequence() {
    -  assertTrue(goog.testing.events.fireDoubleClickSequence(root));
    -  assertEventTypes(DBLCLICK_SEQ);
    -}
    -
    -function testDoubleClickSequenceWithCoordinate() {
    -  assertTrue(goog.testing.events.fireDoubleClickSequence(root, coordinate));
    -  assertCoordinates(DBLCLICK_SEQ_COORDS);
    -}
    -
    -function testDoubleClickSequenceCancellingMousedown() {
    -  preventDefaultEventType('mousedown');
    -  assertFalse(goog.testing.events.fireDoubleClickSequence(root));
    -  assertEventTypes(DBLCLICK_SEQ);
    -}
    -
    -function testDoubleClickSequenceCancellingMousedownWithCoordinate() {
    -  preventDefaultEventType('mousedown');
    -  assertFalse(goog.testing.events.fireDoubleClickSequence(root, coordinate));
    -  assertCoordinates(DBLCLICK_SEQ_COORDS);
    -}
    -
    -function testDoubleClickSequenceCancellingMouseup() {
    -  preventDefaultEventType('mouseup');
    -  assertFalse(goog.testing.events.fireDoubleClickSequence(root));
    -  assertEventTypes(DBLCLICK_SEQ);
    -}
    -
    -function testDoubleClickSequenceCancellingMouseupWithCoordinate() {
    -  preventDefaultEventType('mouseup');
    -  assertFalse(goog.testing.events.fireDoubleClickSequence(root, coordinate));
    -  assertCoordinates(DBLCLICK_SEQ_COORDS);
    -}
    -
    -function testDoubleClickSequenceCancellingClick() {
    -  preventDefaultEventType('click');
    -  assertFalse(goog.testing.events.fireDoubleClickSequence(root));
    -  assertEventTypes(DBLCLICK_SEQ);
    -}
    -
    -function testDoubleClickSequenceCancellingClickWithCoordinate() {
    -  preventDefaultEventType('click');
    -  assertFalse(goog.testing.events.fireDoubleClickSequence(root, coordinate));
    -  assertCoordinates(DBLCLICK_SEQ_COORDS);
    -}
    -
    -function testDoubleClickSequenceCancellingDoubleClick() {
    -  preventDefaultEventType('dblclick');
    -  assertFalse(goog.testing.events.fireDoubleClickSequence(root));
    -  assertEventTypes(DBLCLICK_SEQ);
    -}
    -
    -function testDoubleClickSequenceCancellingDoubleClickWithCoordinate() {
    -  preventDefaultEventType('dblclick');
    -  assertFalse(goog.testing.events.fireDoubleClickSequence(root, coordinate));
    -  assertCoordinates(DBLCLICK_SEQ_COORDS);
    -}
    -
    -function testKeySequence() {
    -  assertTrue(goog.testing.events.fireKeySequence(
    -      root, goog.events.KeyCodes.ZERO));
    -  assertEventTypes(['keydown', 'keypress', 'keyup']);
    -}
    -
    -function testKeySequenceCancellingKeydown() {
    -  preventDefaultEventType('keydown');
    -  assertFalse(goog.testing.events.fireKeySequence(
    -      root, goog.events.KeyCodes.ZERO));
    -  assertEventTypes(['keydown', 'keyup']);
    -}
    -
    -function testKeySequenceCancellingKeypress() {
    -  preventDefaultEventType('keypress');
    -  assertFalse(goog.testing.events.fireKeySequence(
    -      root, goog.events.KeyCodes.ZERO));
    -  assertEventTypes(['keydown', 'keypress', 'keyup']);
    -}
    -
    -function testKeySequenceCancellingKeyup() {
    -  preventDefaultEventType('keyup');
    -  assertFalse(goog.testing.events.fireKeySequence(
    -      root, goog.events.KeyCodes.ZERO));
    -  assertEventTypes(['keydown', 'keypress', 'keyup']);
    -}
    -
    -function testKeySequenceWithEscapeKey() {
    -  assertTrue(goog.testing.events.fireKeySequence(
    -      root, goog.events.KeyCodes.ESC));
    -  if (goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher('525')) {
    -    assertEventTypes(['keydown', 'keyup']);
    -  } else {
    -    assertEventTypes(['keydown', 'keypress', 'keyup']);
    -  }
    -}
    -
    -function testKeySequenceForMacActionKeysNegative() {
    -  stubs.set(goog.userAgent, 'GECKO', false);
    -  goog.testing.events.fireKeySequence(
    -      root, goog.events.KeyCodes.C, {'metaKey': true});
    -  assertEventTypes(['keydown', 'keypress', 'keyup']);
    -}
    -
    -function testKeySequenceForMacActionKeysPositive() {
    -  stubs.set(goog.userAgent, 'GECKO', true);
    -  stubs.set(goog.userAgent, 'MAC', true);
    -  goog.testing.events.fireKeySequence(
    -      root, goog.events.KeyCodes.C, {'metaKey': true});
    -  assertEventTypes(['keypress', 'keyup']);
    -}
    -
    -function testKeySequenceForOptionKeysOnMac() {
    -  // Mac uses an option (or alt) key to type non-ASCII characters. This test
    -  // verifies we can emulate key events sent when typing such non-ASCII
    -  // characters.
    -  stubs.set(goog.userAgent, 'WEBKIT', true);
    -  stubs.set(goog.userAgent, 'MAC', true);
    -
    -  var optionKeyCodes = [
    -    [0xc0, 0x00e6],  // option+'
    -    [0xbc, 0x2264],  // option+,
    -    [0xbd, 0x2013],  // option+-
    -    [0xbe, 0x2265],  // option+.
    -    [0xbf, 0x00f7],  // option+/
    -    [0x30, 0x00ba],  // option+0
    -    [0x31, 0x00a1],  // option+1
    -    [0x32, 0x2122],  // option+2
    -    [0x33, 0x00a3],  // option+3
    -    [0x34, 0x00a2],  // option+4
    -    [0x35, 0x221e],  // option+5
    -    [0x36, 0x00a7],  // option+6
    -    [0x37, 0x00b6],  // option+7
    -    [0x38, 0x2022],  // option+8
    -    [0x39, 0x00aa],  // option+9
    -    [0xba, 0x2026],  // option+;
    -    [0xbb, 0x2260],  // option+=
    -    [0xdb, 0x201c],  // option+[
    -    [0xdc, 0x00ab],  // option+\
    -    [0xdd, 0x2018],  // option+]
    -    [0x41, 0x00e5],  // option+a
    -    [0x42, 0x222b],  // option+b
    -    [0x43, 0x00e7],  // option+c
    -    [0x44, 0x2202],  // option+d
    -    [0x45, 0x00b4],  // option+e
    -    [0x46, 0x0192],  // option+f
    -    [0x47, 0x00a9],  // option+g
    -    [0x48, 0x02d9],  // option+h
    -    [0x49, 0x02c6],  // option+i
    -    [0x4a, 0x2206],  // option+j
    -    [0x4b, 0x02da],  // option+k
    -    [0x4c, 0x00ac],  // option+l
    -    [0x4d, 0x00b5],  // option+m
    -    [0x4e, 0x02dc],  // option+n
    -    [0x4f, 0x00f8],  // option+o
    -    [0x50, 0x03c0],  // option+p
    -    [0x51, 0x0153],  // option+q
    -    [0x52, 0x00ae],  // option+r
    -    [0x53, 0x00df],  // option+s
    -    [0x54, 0x2020],  // option+t
    -    [0x56, 0x221a],  // option+v
    -    [0x57, 0x2211],  // option+w
    -    [0x58, 0x2248],  // option+x
    -    [0x59, 0x00a5],  // option+y
    -    [0x5a, 0x03a9]   // option+z
    -  ];
    -
    -  for (var i = 0; i < optionKeyCodes.length; ++i) {
    -    firedEventTypes = [];
    -    firedKeyCodes = [];
    -    var keyCode = optionKeyCodes[i][0];
    -    var keyPressKeyCode = optionKeyCodes[i][1];
    -    goog.testing.events.fireNonAsciiKeySequence(
    -        root, keyCode, keyPressKeyCode, {'altKey': true});
    -    assertEventTypes(['keydown', 'keypress', 'keyup']);
    -    assertArrayEquals([keyCode, keyPressKeyCode, keyCode], firedKeyCodes);
    -  }
    -}
    -
    -var CONTEXTMENU_SEQ =
    -    goog.userAgent.WINDOWS ? ['mousedown', 'mouseup', 'contextmenu'] :
    -    goog.userAgent.GECKO ? ['mousedown', 'contextmenu', 'mouseup'] :
    -    goog.userAgent.WEBKIT && goog.userAgent.MAC ?
    -        ['mousedown', 'contextmenu', 'mouseup', 'click'] :
    -    ['mousedown', 'contextmenu', 'mouseup'];
    -
    -function testContextMenuSequence() {
    -  assertTrue(goog.testing.events.fireContextMenuSequence(root));
    -  assertEventTypes(CONTEXTMENU_SEQ);
    -}
    -
    -function testContextMenuSequenceWithCoordinate() {
    -  assertTrue(goog.testing.events.fireContextMenuSequence(root, coordinate));
    -  assertEventTypes(CONTEXTMENU_SEQ);
    -  assertCoordinates(goog.array.repeat(coordinate, CONTEXTMENU_SEQ.length));
    -}
    -
    -function testContextMenuSequenceCancellingMousedown() {
    -  preventDefaultEventType('mousedown');
    -  assertFalse(goog.testing.events.fireContextMenuSequence(root));
    -  assertEventTypes(CONTEXTMENU_SEQ);
    -}
    -
    -function testContextMenuSequenceCancellingMouseup() {
    -  preventDefaultEventType('mouseup');
    -  assertFalse(goog.testing.events.fireContextMenuSequence(root));
    -  assertEventTypes(CONTEXTMENU_SEQ);
    -}
    -
    -function testContextMenuSequenceCancellingContextMenu() {
    -  preventDefaultEventType('contextmenu');
    -  assertFalse(goog.testing.events.fireContextMenuSequence(root));
    -  assertEventTypes(CONTEXTMENU_SEQ);
    -}
    -
    -function testContextMenuSequenceFakeMacWebkit() {
    -  stubs.set(goog.userAgent, 'WINDOWS', false);
    -  stubs.set(goog.userAgent, 'MAC', true);
    -  stubs.set(goog.userAgent, 'WEBKIT', true);
    -  assertTrue(goog.testing.events.fireContextMenuSequence(root));
    -  assertEventTypes(['mousedown', 'contextmenu', 'mouseup', 'click']);
    -}
    -
    -function testCaptureBubble_simple() {
    -  assertTrue(goog.testing.events.fireClickEvent(childEl));
    -  assertObjectEquals({
    -    parentCapture: 1,
    -    childCapture: 1,
    -    childBubble: 1,
    -    parentBubble: 1
    -  }, eventCount);
    -}
    -
    -function testCaptureBubble_preventDefault() {
    -  goog.events.listen(childEl, goog.events.EventType.CLICK,
    -      function(e) {
    -        e.preventDefault();
    -      });
    -  assertFalse(goog.testing.events.fireClickEvent(childEl));
    -  assertObjectEquals({
    -    parentCapture: 1,
    -    childCapture: 1,
    -    childBubble: 1,
    -    parentBubble: 1
    -  }, eventCount);
    -}
    -
    -function testCaptureBubble_stopPropagationParentCapture() {
    -  goog.events.listen(parentEl, goog.events.EventType.CLICK,
    -      function(e) {
    -        e.stopPropagation();
    -      }, true /* capture */);
    -  assertTrue(goog.testing.events.fireClickEvent(childEl));
    -  assertObjectEquals({
    -    parentCapture: 1,
    -    childCapture: 0,
    -    childBubble: 0,
    -    parentBubble: 0
    -  }, eventCount);
    -}
    -
    -function testCaptureBubble_stopPropagationChildCapture() {
    -  goog.events.listen(childEl, goog.events.EventType.CLICK,
    -      function(e) {
    -        e.stopPropagation();
    -      }, true /* capture */);
    -  assertTrue(goog.testing.events.fireClickEvent(childEl));
    -  assertObjectEquals({
    -    parentCapture: 1,
    -    childCapture: 1,
    -    childBubble: 0,
    -    parentBubble: 0
    -  }, eventCount);
    -}
    -
    -function testCaptureBubble_stopPropagationChildBubble() {
    -  goog.events.listen(childEl, goog.events.EventType.CLICK,
    -      function(e) {
    -        e.stopPropagation();
    -      });
    -  assertTrue(goog.testing.events.fireClickEvent(childEl));
    -  assertObjectEquals({
    -    parentCapture: 1,
    -    childCapture: 1,
    -    childBubble: 1,
    -    parentBubble: 0
    -  }, eventCount);
    -}
    -
    -function testCaptureBubble_stopPropagationParentBubble() {
    -  goog.events.listen(parentEl, goog.events.EventType.CLICK,
    -      function(e) {
    -        e.stopPropagation();
    -      });
    -  assertTrue(goog.testing.events.fireClickEvent(childEl));
    -  assertObjectEquals({
    -    parentCapture: 1,
    -    childCapture: 1,
    -    childBubble: 1,
    -    parentBubble: 1
    -  }, eventCount);
    -}
    -
    -function testMixinListenable() {
    -  var obj = {};
    -  obj.doFoo = goog.testing.recordFunction();
    -
    -  goog.testing.events.mixinListenable(obj);
    -
    -  obj.doFoo();
    -  assertEquals(1, obj.doFoo.getCallCount());
    -
    -  var handler = goog.testing.recordFunction();
    -  goog.events.listen(obj, 'test', handler);
    -  obj.dispatchEvent('test');
    -  assertEquals(1, handler.getCallCount());
    -  assertEquals(obj, handler.getLastCall().getArgument(0).target);
    -
    -  goog.events.unlisten(obj, 'test', handler);
    -  obj.dispatchEvent('test');
    -  assertEquals(1, handler.getCallCount());
    -
    -  goog.events.listen(obj, 'test', handler);
    -  obj.dispose();
    -  obj.dispatchEvent('test');
    -  assertEquals(1, handler.getCallCount());
    -}
    -
    -
    -/**
    - * Assert that the list of events given was fired, in that order.
    - */
    -function assertEventTypes(list) {
    -  assertArrayEquals(list, firedEventTypes);
    -}
    -
    -
    -/**
    - * Assert that the list of event coordinates given was caught, in that order.
    - */
    -function assertCoordinates(list) {
    -  assertArrayEquals(list, firedEventCoordinates);
    -  assertArrayEquals(list, firedScreenCoordinates);
    -}
    -
    -
    -/** Prevent default the event of the given type on the root element. */
    -function preventDefaultEventType(type) {
    -  goog.events.listen(root, type, preventDefault);
    -}
    -
    -function preventDefault(e) {
    -  e.preventDefault();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/events/matchers.js b/src/database/third_party/closure-library/closure/goog/testing/events/matchers.js
    deleted file mode 100644
    index 7223b084556..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/events/matchers.js
    +++ /dev/null
    @@ -1,42 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Mock matchers for event related arguments.
    - */
    -
    -goog.provide('goog.testing.events.EventMatcher');
    -
    -goog.require('goog.events.Event');
    -goog.require('goog.testing.mockmatchers.ArgumentMatcher');
    -
    -
    -
    -/**
    - * A matcher that verifies that an argument is a {@code goog.events.Event} of a
    - * particular type.
    - * @param {string} type The single type the event argument must be of.
    - * @constructor
    - * @extends {goog.testing.mockmatchers.ArgumentMatcher}
    - * @final
    - */
    -goog.testing.events.EventMatcher = function(type) {
    -  goog.testing.mockmatchers.ArgumentMatcher.call(this,
    -      function(obj) {
    -        return obj instanceof goog.events.Event &&
    -            obj.type == type;
    -      }, 'isEventOfType(' + type + ')');
    -};
    -goog.inherits(goog.testing.events.EventMatcher,
    -    goog.testing.mockmatchers.ArgumentMatcher);
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/events/matchers_test.html b/src/database/third_party/closure-library/closure/goog/testing/events/matchers_test.html
    deleted file mode 100644
    index 1d49ee2e14b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/events/matchers_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <!--
    -
    -  -->
    -  <title>
    -   Closure Unit Tests - goog.testing.events.EventMatcher
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.testing.events.EventMatcherTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/events/matchers_test.js b/src/database/third_party/closure-library/closure/goog/testing/events/matchers_test.js
    deleted file mode 100644
    index 12826b039a2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/events/matchers_test.js
    +++ /dev/null
    @@ -1,35 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.events.EventMatcherTest');
    -goog.setTestOnly('goog.testing.events.EventMatcherTest');
    -
    -goog.require('goog.events.Event');
    -goog.require('goog.testing.events.EventMatcher');
    -goog.require('goog.testing.jsunit');
    -
    -function testEventMatcher() {
    -  var matcher = new goog.testing.events.EventMatcher('foo');
    -  assertFalse(matcher.matches(undefined));
    -  assertFalse(matcher.matches(null));
    -  assertFalse(matcher.matches({type: 'foo'}));
    -  assertFalse(matcher.matches(new goog.events.Event('bar')));
    -
    -  assertTrue(matcher.matches(new goog.events.Event('foo')));
    -  var FooEvent = function() {
    -    goog.events.Event.call(this, 'foo');
    -  };
    -  goog.inherits(FooEvent, goog.events.Event);
    -  assertTrue(matcher.matches(new FooEvent()));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/events/onlinehandler.js b/src/database/third_party/closure-library/closure/goog/testing/events/onlinehandler.js
    deleted file mode 100644
    index 31529bff12a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/events/onlinehandler.js
    +++ /dev/null
    @@ -1,65 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview NetworkStatusMonitor test double.
    - * @author dbk@google.com (David Barrett-Kahn)
    - */
    -
    -goog.provide('goog.testing.events.OnlineHandler');
    -
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.net.NetworkStatusMonitor');
    -
    -
    -
    -/**
    - * NetworkStatusMonitor test double.
    - * @param {boolean} initialState The initial online state of the mock.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - * @implements {goog.net.NetworkStatusMonitor}
    - * @final
    - */
    -goog.testing.events.OnlineHandler = function(initialState) {
    -  goog.testing.events.OnlineHandler.base(this, 'constructor');
    -
    -  /**
    -   * Whether the mock is online.
    -   * @private {boolean}
    -   */
    -  this.online_ = initialState;
    -};
    -goog.inherits(goog.testing.events.OnlineHandler, goog.events.EventTarget);
    -
    -
    -/** @override */
    -goog.testing.events.OnlineHandler.prototype.isOnline = function() {
    -  return this.online_;
    -};
    -
    -
    -/**
    - * Sets the online state.
    - * @param {boolean} newOnlineState The new online state.
    - */
    -goog.testing.events.OnlineHandler.prototype.setOnline =
    -    function(newOnlineState) {
    -  if (newOnlineState != this.online_) {
    -    this.online_ = newOnlineState;
    -    this.dispatchEvent(newOnlineState ?
    -        goog.net.NetworkStatusMonitor.EventType.ONLINE :
    -        goog.net.NetworkStatusMonitor.EventType.OFFLINE);
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/events/onlinehandler_test.html b/src/database/third_party/closure-library/closure/goog/testing/events/onlinehandler_test.html
    deleted file mode 100644
    index 59034b204ef..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/events/onlinehandler_test.html
    +++ /dev/null
    @@ -1,26 +0,0 @@
    -<!DOCTYPE html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<html>
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <!--
    -
    -  Author: dbk@google.com (David Barrett-Kahn)
    -  -->
    -  <title>
    -   Closure Unit Tests - goog.testing.events
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.events.OnlineHandlerTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/events/onlinehandler_test.js b/src/database/third_party/closure-library/closure/goog/testing/events/onlinehandler_test.js
    deleted file mode 100644
    index 00bb3c3803d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/events/onlinehandler_test.js
    +++ /dev/null
    @@ -1,84 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.events.OnlineHandlerTest');
    -goog.setTestOnly('goog.testing.events.OnlineHandlerTest');
    -
    -goog.require('goog.events');
    -goog.require('goog.net.NetworkStatusMonitor');
    -goog.require('goog.testing.events.EventObserver');
    -goog.require('goog.testing.events.OnlineHandler');
    -goog.require('goog.testing.jsunit');
    -
    -var handler;
    -
    -var observer;
    -
    -function tearDown() {
    -  handler = null;
    -  observer = null;
    -}
    -
    -function testInitialValue() {
    -  createHandler(true);
    -  assertEquals(true, handler.isOnline());
    -  createHandler(false);
    -  assertEquals(false, handler.isOnline());
    -}
    -
    -function testStateChange() {
    -  createHandler(true);
    -  assertEventCounts(0 /* expectedOnlineEvents */,
    -      0 /* expectedOfflineEvents */);
    -
    -  // Expect no events.
    -  handler.setOnline(true);
    -  assertEquals(true, handler.isOnline());
    -  assertEventCounts(0 /* expectedOnlineEvents */,
    -      0 /* expectedOfflineEvents */);
    -
    -  // Expect one offline event.
    -  handler.setOnline(false);
    -  assertEquals(false, handler.isOnline());
    -  assertEventCounts(0 /* expectedOnlineEvents */,
    -      1 /* expectedOfflineEvents */);
    -
    -  // Expect no events.
    -  handler.setOnline(false);
    -  assertEquals(false, handler.isOnline());
    -  assertEventCounts(0 /* expectedOnlineEvents */,
    -      1 /* expectedOfflineEvents */);
    -
    -  // Expect one online event.
    -  handler.setOnline(true);
    -  assertEquals(true, handler.isOnline());
    -  assertEventCounts(1 /* expectedOnlineEvents */,
    -      1 /* expectedOfflineEvents */);
    -}
    -
    -function createHandler(initialValue) {
    -  handler = new goog.testing.events.OnlineHandler(initialValue);
    -  observer = new goog.testing.events.EventObserver();
    -  goog.events.listen(handler,
    -      [goog.net.NetworkStatusMonitor.EventType.ONLINE,
    -       goog.net.NetworkStatusMonitor.EventType.OFFLINE],
    -      observer);
    -}
    -
    -function assertEventCounts(expectedOnlineEvents, expectedOfflineEvents) {
    -  assertEquals(expectedOnlineEvents, observer.getEvents(
    -      goog.net.NetworkStatusMonitor.EventType.ONLINE).length);
    -  assertEquals(expectedOfflineEvents, observer.getEvents(
    -      goog.net.NetworkStatusMonitor.EventType.OFFLINE).length);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/expectedfailures.js b/src/database/third_party/closure-library/closure/goog/testing/expectedfailures.js
    deleted file mode 100644
    index 1df3a1c1d79..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/expectedfailures.js
    +++ /dev/null
    @@ -1,237 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Helper class to allow for expected unit test failures.
    - *
    - * @author robbyw@google.com (Robby Walker)
    - */
    -
    -goog.provide('goog.testing.ExpectedFailures');
    -
    -goog.require('goog.debug.DivConsole');
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.events');
    -goog.require('goog.events.EventType');
    -goog.require('goog.log');
    -goog.require('goog.style');
    -goog.require('goog.testing.JsUnitException');
    -goog.require('goog.testing.TestCase');
    -goog.require('goog.testing.asserts');
    -
    -
    -
    -/**
    - * Helper class for allowing some unit tests to fail, particularly designed to
    - * mark tests that should be fixed on a given browser.
    - *
    - * <pre>
    - * var expectedFailures = new goog.testing.ExpectedFailures();
    - *
    - * function tearDown() {
    - *   expectedFailures.handleTearDown();
    - * }
    - *
    - * function testSomethingThatBreaksInWebKit() {
    - *   expectedFailures.expectFailureFor(goog.userAgent.WEBKIT);
    - *
    - *   try {
    - *     ...
    - *     assert(somethingThatFailsInWebKit);
    - *     ...
    - *   } catch (e) {
    - *     expectedFailures.handleException(e);
    - *   }
    - * }
    - * </pre>
    - *
    - * @constructor
    - * @final
    - */
    -goog.testing.ExpectedFailures = function() {
    -  goog.testing.ExpectedFailures.setUpConsole_();
    -  this.reset_();
    -};
    -
    -
    -/**
    - * The lazily created debugging console.
    - * @type {goog.debug.DivConsole?}
    - * @private
    - */
    -goog.testing.ExpectedFailures.console_ = null;
    -
    -
    -/**
    - * Logger for the expected failures.
    - * @type {goog.log.Logger}
    - * @private
    - */
    -goog.testing.ExpectedFailures.prototype.logger_ =
    -    goog.log.getLogger('goog.testing.ExpectedFailures');
    -
    -
    -/**
    - * Whether or not we are expecting failure.
    - * @type {boolean}
    - * @private
    - */
    -goog.testing.ExpectedFailures.prototype.expectingFailure_;
    -
    -
    -/**
    - * The string to emit upon an expected failure.
    - * @type {string}
    - * @private
    - */
    -goog.testing.ExpectedFailures.prototype.failureMessage_;
    -
    -
    -/**
    - * An array of suppressed failures.
    - * @type {Array<!Error>}
    - * @private
    - */
    -goog.testing.ExpectedFailures.prototype.suppressedFailures_;
    -
    -
    -/**
    - * Sets up the debug console, if it isn't already set up.
    - * @private
    - */
    -goog.testing.ExpectedFailures.setUpConsole_ = function() {
    -  if (!goog.testing.ExpectedFailures.console_) {
    -    var xButton = goog.dom.createDom(goog.dom.TagName.DIV, {
    -      'style': 'position: absolute; border-left:1px solid #333;' +
    -          'border-bottom:1px solid #333; right: 0; top: 0; width: 1em;' +
    -          'height: 1em; cursor: pointer; background-color: #cde;' +
    -          'text-align: center; color: black'
    -    }, 'X');
    -    var div = goog.dom.createDom(goog.dom.TagName.DIV, {
    -      'style': 'position: absolute; border: 1px solid #333; right: 10px;' +
    -          'top : 10px; width: 400px; display: none'
    -    }, xButton);
    -    document.body.appendChild(div);
    -    goog.events.listen(xButton, goog.events.EventType.CLICK, function() {
    -      goog.style.setElementShown(div, false);
    -    });
    -
    -    goog.testing.ExpectedFailures.console_ = new goog.debug.DivConsole(div);
    -    goog.log.addHandler(goog.testing.ExpectedFailures.prototype.logger_,
    -        goog.bind(goog.style.setElementShown, null, div, true));
    -    goog.log.addHandler(goog.testing.ExpectedFailures.prototype.logger_,
    -        goog.bind(goog.testing.ExpectedFailures.console_.addLogRecord,
    -            goog.testing.ExpectedFailures.console_));
    -  }
    -};
    -
    -
    -/**
    - * Register to expect failure for the given condition.  Multiple calls to this
    - * function act as a boolean OR.  The first applicable message will be used.
    - * @param {boolean} condition Whether to expect failure.
    - * @param {string=} opt_message Descriptive message of this expected failure.
    - */
    -goog.testing.ExpectedFailures.prototype.expectFailureFor = function(
    -    condition, opt_message) {
    -  this.expectingFailure_ = this.expectingFailure_ || condition;
    -  if (condition) {
    -    this.failureMessage_ = this.failureMessage_ || opt_message || '';
    -  }
    -};
    -
    -
    -/**
    - * Determines if the given exception was expected.
    - * @param {Object} ex The exception to check.
    - * @return {boolean} Whether the exception was expected.
    - */
    -goog.testing.ExpectedFailures.prototype.isExceptionExpected = function(ex) {
    -  return this.expectingFailure_ && ex instanceof goog.testing.JsUnitException;
    -};
    -
    -
    -/**
    - * Handle an exception, suppressing it if it is a unit test failure that we
    - * expected.
    - * @param {Error} ex The exception to handle.
    - */
    -goog.testing.ExpectedFailures.prototype.handleException = function(ex) {
    -  if (this.isExceptionExpected(ex)) {
    -    goog.log.info(this.logger_, 'Suppressing test failure in ' +
    -        goog.testing.TestCase.currentTestName + ':' +
    -        (this.failureMessage_ ? '\n(' + this.failureMessage_ + ')' : ''),
    -        ex);
    -    this.suppressedFailures_.push(ex);
    -    return;
    -  }
    -
    -  // Rethrow the exception if we weren't expecting it or if it is a normal
    -  // exception.
    -  throw ex;
    -};
    -
    -
    -/**
    - * Run the given function, catching any expected failures.
    - * @param {Function} func The function to run.
    - * @param {boolean=} opt_lenient Whether to ignore if the expected failures
    - *     didn't occur.  In this case a warning will be logged in handleTearDown.
    - */
    -goog.testing.ExpectedFailures.prototype.run = function(func, opt_lenient) {
    -  try {
    -    func();
    -  } catch (ex) {
    -    this.handleException(ex);
    -  }
    -
    -  if (!opt_lenient && this.expectingFailure_ &&
    -      !this.suppressedFailures_.length) {
    -    fail(this.getExpectationMessage_());
    -  }
    -};
    -
    -
    -/**
    - * @return {string} A warning describing an expected failure that didn't occur.
    - * @private
    - */
    -goog.testing.ExpectedFailures.prototype.getExpectationMessage_ = function() {
    -  return 'Expected a test failure in \'' +
    -         goog.testing.TestCase.currentTestName + '\' but the test passed.';
    -};
    -
    -
    -/**
    - * Handle the tearDown phase of a test, alerting the user if an expected test
    - * was not suppressed.
    - */
    -goog.testing.ExpectedFailures.prototype.handleTearDown = function() {
    -  if (this.expectingFailure_ && !this.suppressedFailures_.length) {
    -    goog.log.warning(this.logger_, this.getExpectationMessage_());
    -  }
    -  this.reset_();
    -};
    -
    -
    -/**
    - * Reset internal state.
    - * @private
    - */
    -goog.testing.ExpectedFailures.prototype.reset_ = function() {
    -  this.expectingFailure_ = false;
    -  this.failureMessage_ = '';
    -  this.suppressedFailures_ = [];
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/expectedfailures_test.html b/src/database/third_party/closure-library/closure/goog/testing/expectedfailures_test.html
    deleted file mode 100644
    index 1ae17be86a1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/expectedfailures_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.testing.ExpectedFailures
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.ExpectedFailuresTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/expectedfailures_test.js b/src/database/third_party/closure-library/closure/goog/testing/expectedfailures_test.js
    deleted file mode 100644
    index 8a287b06640..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/expectedfailures_test.js
    +++ /dev/null
    @@ -1,121 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.ExpectedFailuresTest');
    -goog.setTestOnly('goog.testing.ExpectedFailuresTest');
    -
    -goog.require('goog.debug.Logger');
    -goog.require('goog.testing.ExpectedFailures');
    -goog.require('goog.testing.JsUnitException');
    -goog.require('goog.testing.jsunit');
    -
    -var count, expectedFailures, lastLevel, lastMessage;
    -
    -// Stub out the logger.
    -goog.testing.ExpectedFailures.prototype.logger_.log = function(level,
    -    message) {
    -  lastLevel = level;
    -  lastMessage = message;
    -  count++;
    -};
    -
    -function setUp() {
    -  expectedFailures = new goog.testing.ExpectedFailures();
    -  count = 0;
    -  lastLevel = lastMessage = '';
    -}
    -
    -// Individual test methods.
    -
    -function testNoExpectedFailure() {
    -  expectedFailures.handleTearDown();
    -}
    -
    -function testPreventExpectedFailure() {
    -  expectedFailures.expectFailureFor(true);
    -
    -  expectedFailures.handleException(new goog.testing.JsUnitException('', ''));
    -  assertEquals('Should have logged a message', 1, count);
    -  assertEquals('Should have logged an info message',
    -      goog.debug.Logger.Level.INFO, lastLevel);
    -  assertContains('Should log a suppression message',
    -      'Suppressing test failure', lastMessage);
    -
    -  expectedFailures.handleTearDown();
    -  assertEquals('Should not have logged another message', 1, count);
    -}
    -
    -function testDoNotPreventException() {
    -  var ex = 'exception';
    -  expectedFailures.expectFailureFor(false);
    -  var e = assertThrows('Should have rethrown exception', function() {
    -    expectedFailures.handleException(ex);
    -  });
    -  assertEquals('Should rethrow same exception', ex, e);
    -}
    -
    -function testExpectedFailureDidNotOccur() {
    -  expectedFailures.expectFailureFor(true);
    -
    -  expectedFailures.handleTearDown();
    -  assertEquals('Should have logged a message', 1, count);
    -  assertEquals('Should have logged a warning',
    -      goog.debug.Logger.Level.WARNING, lastLevel);
    -  assertContains('Should log a suppression message',
    -      'Expected a test failure', lastMessage);
    -}
    -
    -function testRun() {
    -  expectedFailures.expectFailureFor(true);
    -
    -  expectedFailures.run(function() {
    -    fail('Expected failure');
    -  });
    -
    -  assertEquals('Should have logged a message', 1, count);
    -  assertEquals('Should have logged an info message',
    -      goog.debug.Logger.Level.INFO, lastLevel);
    -  assertContains('Should log a suppression message',
    -      'Suppressing test failure', lastMessage);
    -
    -  expectedFailures.handleTearDown();
    -  assertEquals('Should not have logged another message', 1, count);
    -}
    -
    -function testRunStrict() {
    -  expectedFailures.expectFailureFor(true);
    -
    -  var ex = assertThrows(function() {
    -    expectedFailures.run(function() {
    -      // Doesn't fail!
    -    });
    -  });
    -  assertContains(
    -      "Expected a test failure in 'testRunStrict' but the test passed.",
    -      ex.message);
    -}
    -
    -function testRunLenient() {
    -  expectedFailures.expectFailureFor(true);
    -
    -  expectedFailures.run(function() {
    -    // Doesn't fail!
    -  }, true);
    -  expectedFailures.handleTearDown();
    -  assertEquals('Should have logged a message', 1, count);
    -  assertEquals('Should have logged a warning',
    -      goog.debug.Logger.Level.WARNING, lastLevel);
    -  assertContains('Should log a suppression message',
    -      'Expected a test failure', lastMessage);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/fs/blob.js b/src/database/third_party/closure-library/closure/goog/testing/fs/blob.js
    deleted file mode 100644
    index d1da648eaf2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/fs/blob.js
    +++ /dev/null
    @@ -1,135 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Mock blob object.
    - *
    - */
    -
    -goog.provide('goog.testing.fs.Blob');
    -
    -goog.require('goog.crypt.base64');
    -
    -
    -
    -/**
    - * A mock Blob object. The data is stored as a string.
    - *
    - * @param {string=} opt_data The string data encapsulated by the blob.
    - * @param {string=} opt_type The mime type of the blob.
    - * @constructor
    - */
    -goog.testing.fs.Blob = function(opt_data, opt_type) {
    -  /**
    -   * @see http://www.w3.org/TR/FileAPI/#dfn-type
    -   * @type {string}
    -   */
    -  this.type = opt_type || '';
    -
    -  this.setDataInternal(opt_data || '');
    -};
    -
    -
    -/**
    - * The string data encapsulated by the blob.
    - * @type {string}
    - * @private
    - */
    -goog.testing.fs.Blob.prototype.data_;
    -
    -
    -/**
    - * @see http://www.w3.org/TR/FileAPI/#dfn-size
    - * @type {number}
    - */
    -goog.testing.fs.Blob.prototype.size;
    -
    -
    -/**
    - * Creates a blob with bytes of a blob ranging from the optional start
    - * parameter up to but not including the optional end parameter, and with a type
    - * attribute that is the value of the optional contentType parameter.
    - * @see http://www.w3.org/TR/FileAPI/#dfn-slice
    - * @param {number=} opt_start The start byte offset.
    - * @param {number=} opt_end The end point of a slice.
    - * @param {string=} opt_contentType The type of the resulting Blob.
    - * @return {!goog.testing.fs.Blob} The result blob of the slice operation.
    - */
    -goog.testing.fs.Blob.prototype.slice = function(
    -    opt_start, opt_end, opt_contentType) {
    -  var relativeStart;
    -  if (goog.isNumber(opt_start)) {
    -    relativeStart = (opt_start < 0) ?
    -        Math.max(this.data_.length + opt_start, 0) :
    -        Math.min(opt_start, this.data_.length);
    -  } else {
    -    relativeStart = 0;
    -  }
    -  var relativeEnd;
    -  if (goog.isNumber(opt_end)) {
    -    relativeEnd = (opt_end < 0) ?
    -        Math.max(this.data_.length + opt_end, 0) :
    -        Math.min(opt_end, this.data_.length);
    -  } else {
    -    relativeEnd = this.data_.length;
    -  }
    -  var span = Math.max(relativeEnd - relativeStart, 0);
    -  return new goog.testing.fs.Blob(
    -      this.data_.substr(relativeStart, span),
    -      opt_contentType);
    -};
    -
    -
    -/**
    - * @return {string} The string data encapsulated by the blob.
    - * @override
    - */
    -goog.testing.fs.Blob.prototype.toString = function() {
    -  return this.data_;
    -};
    -
    -
    -/**
    - * @return {!ArrayBuffer} The string data encapsulated by the blob as an
    - *     ArrayBuffer.
    - */
    -goog.testing.fs.Blob.prototype.toArrayBuffer = function() {
    -  var buf = new ArrayBuffer(this.data_.length * 2);
    -  var arr = new Uint16Array(buf);
    -  for (var i = 0; i < this.data_.length; i++) {
    -    arr[i] = this.data_.charCodeAt(i);
    -  }
    -  return buf;
    -};
    -
    -
    -/**
    - * @return {string} The string data encapsulated by the blob as a data: URI.
    - */
    -goog.testing.fs.Blob.prototype.toDataUrl = function() {
    -  return 'data:' + this.type + ';base64,' +
    -      goog.crypt.base64.encodeString(this.data_);
    -};
    -
    -
    -/**
    - * Sets the internal contents of the blob. This should only be called by other
    - * functions inside the {@code goog.testing.fs} namespace.
    - *
    - * @param {string} data The data for this Blob.
    - */
    -goog.testing.fs.Blob.prototype.setDataInternal = function(data) {
    -  this.data_ = data;
    -  this.size = data.length;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/fs/blob_test.html b/src/database/third_party/closure-library/closure/goog/testing/fs/blob_test.html
    deleted file mode 100644
    index 50a46ff9bb9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/fs/blob_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.testing.fs.Blob
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.fs.BlobTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/fs/blob_test.js b/src/database/third_party/closure-library/closure/goog/testing/fs/blob_test.js
    deleted file mode 100644
    index 8b57ee968ff..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/fs/blob_test.js
    +++ /dev/null
    @@ -1,65 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.fs.BlobTest');
    -goog.setTestOnly('goog.testing.fs.BlobTest');
    -
    -goog.require('goog.testing.fs.Blob');
    -goog.require('goog.testing.jsunit');
    -
    -function testAttributes() {
    -  var blob = new goog.testing.fs.Blob();
    -  assertEquals(0, blob.size);
    -  assertEquals('', blob.type);
    -
    -  blob = new goog.testing.fs.Blob('foo bar baz');
    -  assertEquals(11, blob.size);
    -  assertEquals('', blob.type);
    -
    -  blob = new goog.testing.fs.Blob('foo bar baz', 'text/plain');
    -  assertEquals(11, blob.size);
    -  assertEquals('text/plain', blob.type);
    -}
    -
    -function testToString() {
    -  assertEquals('', new goog.testing.fs.Blob().toString());
    -  assertEquals('foo bar', new goog.testing.fs.Blob('foo bar').toString());
    -}
    -
    -function testSlice() {
    -  var blob = new goog.testing.fs.Blob('abcdef');
    -  assertEquals('bc', blob.slice(1, 3).toString());
    -  assertEquals('def', blob.slice(3, 10).toString());
    -  assertEquals('abcd', blob.slice(0, -2).toString());
    -  assertEquals('', blob.slice(10, 1).toString());
    -  assertEquals('b', blob.slice(-5, 2).toString());
    -
    -  assertEquals('abcdef', blob.slice().toString());
    -  assertEquals('abc', blob.slice(/* opt_start */ undefined, 3).toString());
    -  assertEquals('def', blob.slice(3).toString());
    -
    -  assertEquals('text/plain', blob.slice(1, 2, 'text/plain').type);
    -}
    -
    -function testSetDataInternal() {
    -  var blob = new goog.testing.fs.Blob();
    -
    -  blob.setDataInternal('asdf');
    -  assertEquals('asdf', blob.toString());
    -  assertEquals(4, blob.size);
    -
    -  blob.setDataInternal('');
    -  assertEquals('', blob.toString());
    -  assertEquals(0, blob.size);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/fs/directoryentry_test.html b/src/database/third_party/closure-library/closure/goog/testing/fs/directoryentry_test.html
    deleted file mode 100644
    index 732b6f31b9e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/fs/directoryentry_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.testing.fs.DirectoryEntry
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.fs.DirectoryEntryTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/fs/directoryentry_test.js b/src/database/third_party/closure-library/closure/goog/testing/fs/directoryentry_test.js
    deleted file mode 100644
    index 976190f4586..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/fs/directoryentry_test.js
    +++ /dev/null
    @@ -1,319 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.fs.DirectoryEntryTest');
    -goog.setTestOnly('goog.testing.fs.DirectoryEntryTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.fs.DirectoryEntry');
    -goog.require('goog.fs.Error');
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.fs.FileSystem');
    -goog.require('goog.testing.jsunit');
    -
    -var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall();
    -var fs, dir, mockClock;
    -
    -function setUp() {
    -  mockClock = new goog.testing.MockClock(true);
    -
    -  fs = new goog.testing.fs.FileSystem();
    -  dir = fs.getRoot().createDirectorySync('foo');
    -  dir.createDirectorySync('subdir').createFileSync('subfile');
    -  dir.createFileSync('file');
    -}
    -
    -function tearDown() {
    -  mockClock.uninstall();
    -}
    -
    -function testIsFile() {
    -  assertFalse(dir.isFile());
    -}
    -
    -function testIsDirectory() {
    -  assertTrue(dir.isDirectory());
    -}
    -
    -function testRemoveWithChildren() {
    -  dir.getFileSync('bar', goog.fs.DirectoryEntry.Behavior.CREATE);
    -  expectError(dir.remove(), goog.fs.Error.ErrorCode.INVALID_MODIFICATION);
    -}
    -
    -function testRemoveWithoutChildren() {
    -  var emptyDir = dir.getDirectorySync(
    -      'empty', goog.fs.DirectoryEntry.Behavior.CREATE);
    -  emptyDir.remove().
    -      addCallback(function() {
    -        assertTrue(emptyDir.deleted);
    -        assertFalse(fs.getRoot().hasChild('empty'));
    -      }).
    -      addBoth(continueTesting);
    -  waitForAsync('waiting for file removal');
    -}
    -
    -function testRemoveRootRecursively() {
    -  var root = fs.getRoot();
    -  root.removeRecursively().addCallback(function() {
    -    assertTrue(dir.deleted);
    -    assertFalse(fs.getRoot().deleted);
    -  })
    -  .addBoth(continueTesting);
    -  waitForAsync('waiting for testRemoveRoot');
    -}
    -
    -function testGetFile() {
    -  // Advance the clock by an arbitrary but known amount.
    -  mockClock.tick(41);
    -  dir.getFile('file').
    -      addCallback(function(file) {
    -        assertEquals(dir.getFileSync('file'), file);
    -        assertEquals('file', file.getName());
    -        assertEquals('/foo/file', file.getFullPath());
    -        assertTrue(file.isFile());
    -
    -        return dir.getLastModified();
    -      }).
    -      addCallback(function(date) {
    -        assertEquals('Reading a file should not update the modification date.',
    -            0, date.getTime());
    -        return dir.getMetadata();
    -      }).
    -      addCallback(function(metadata) {
    -        assertEquals('Reading a file should not update the metadata.',
    -            0, metadata.modificationTime.getTime());
    -      }).
    -      addBoth(continueTesting);
    -  waitForAsync('waiting for file');
    -}
    -
    -function testGetFileFromSubdir() {
    -  dir.getFile('subdir/subfile').addCallback(function(file) {
    -    assertEquals(dir.getDirectorySync('subdir').getFileSync('subfile'), file);
    -    assertEquals('subfile', file.getName());
    -    assertEquals('/foo/subdir/subfile', file.getFullPath());
    -    assertTrue(file.isFile());
    -  }).
    -      addBoth(continueTesting);
    -  waitForAsync('waiting for file');
    -}
    -
    -function testGetAbsolutePaths() {
    -  fs.getRoot().getFile('/foo/subdir/subfile').
    -      addCallback(function(subfile) {
    -        assertEquals('/foo/subdir/subfile', subfile.getFullPath());
    -        return fs.getRoot().getDirectory('//foo////');
    -      }).
    -      addCallback(function(foo) {
    -        assertEquals('/foo', foo.getFullPath());
    -        return foo.getDirectory('/');
    -      }).
    -      addCallback(function(root) {
    -        assertEquals('/', root.getFullPath());
    -        return root.getDirectory('/////');
    -      }).
    -      addCallback(function(root) {
    -        assertEquals('/', root.getFullPath());
    -      }).
    -      addBoth(continueTesting);
    -  waitForAsync('testGetAbsolutePaths');
    -}
    -
    -function testCreateFile() {
    -  mockClock.tick(43);
    -  dir.getLastModified().
    -      addCallback(function(date) { assertEquals(0, date.getTime()); }).
    -      addCallback(function() {
    -        return dir.getFile('bar', goog.fs.DirectoryEntry.Behavior.CREATE);
    -      }).
    -      addCallback(function(file) {
    -        mockClock.tick();
    -        assertEquals('bar', file.getName());
    -        assertEquals('/foo/bar', file.getFullPath());
    -        assertEquals(dir, file.parent);
    -        assertTrue(file.isFile());
    -
    -        return dir.getLastModified();
    -      }).
    -      addCallback(function(date) {
    -        assertEquals(43, date.getTime());
    -        return dir.getMetadata();
    -      }).
    -      addCallback(function(metadata) {
    -        assertEquals(43, metadata.modificationTime.getTime());
    -      }).
    -      addBoth(continueTesting);
    -  waitForAsync('waiting for file creation');
    -}
    -
    -function testCreateFileThatAlreadyExists() {
    -  mockClock.tick(47);
    -  var existingFile = dir.getFileSync('file');
    -  dir.getFile('file', goog.fs.DirectoryEntry.Behavior.CREATE).
    -      addCallback(function(file) {
    -        mockClock.tick();
    -        assertEquals('file', file.getName());
    -        assertEquals('/foo/file', file.getFullPath());
    -        assertEquals(dir, file.parent);
    -        assertEquals(existingFile, file);
    -        assertTrue(file.isFile());
    -
    -        return dir.getLastModified();
    -      }).
    -      addCallback(function(date) {
    -        assertEquals(47, date.getTime());
    -        return dir.getMetadata();
    -      }).
    -      addCallback(function(metadata) {
    -        assertEquals(47, metadata.modificationTime.getTime());
    -      }).
    -      addBoth(continueTesting);
    -  waitForAsync('waiting for file creation');
    -}
    -
    -function testCreateFileInSubdir() {
    -  dir.getFile('subdir/bar', goog.fs.DirectoryEntry.Behavior.CREATE).
    -      addCallback(function(file) {
    -        assertEquals('bar', file.getName());
    -        assertEquals('/foo/subdir/bar', file.getFullPath());
    -        assertEquals(dir.getDirectorySync('subdir'), file.parent);
    -        assertTrue(file.isFile());
    -      }).
    -      addBoth(continueTesting);
    -  waitForAsync('waiting for file creation');
    -}
    -
    -function testCreateFileExclusive() {
    -  dir.getFile('bar', goog.fs.DirectoryEntry.Behavior.CREATE_EXCLUSIVE).
    -      addCallback(function(file) {
    -        assertEquals('bar', file.getName());
    -        assertEquals('/foo/bar', file.getFullPath());
    -        assertEquals(dir, file.parent);
    -        assertTrue(file.isFile());
    -      }).
    -      addBoth(continueTesting);
    -  waitForAsync('waiting for file creation');
    -}
    -
    -function testGetNonExistentFile() {
    -  expectError(dir.getFile('bar'), goog.fs.Error.ErrorCode.NOT_FOUND);
    -}
    -
    -function testGetNonExistentFileInSubdir() {
    -  expectError(dir.getFile('subdir/bar'), goog.fs.Error.ErrorCode.NOT_FOUND);
    -}
    -
    -function testGetFileInNonExistentSubdir() {
    -  expectError(dir.getFile('bar/subfile'), goog.fs.Error.ErrorCode.NOT_FOUND);
    -}
    -
    -function testGetFileThatsActuallyADirectory() {
    -  expectError(dir.getFile('subdir'), goog.fs.Error.ErrorCode.TYPE_MISMATCH);
    -}
    -
    -function testCreateFileInNonExistentSubdir() {
    -  expectError(
    -      dir.getFile('bar/newfile', goog.fs.DirectoryEntry.Behavior.CREATE),
    -      goog.fs.Error.ErrorCode.NOT_FOUND);
    -}
    -
    -function testCreateFileThatsActuallyADirectory() {
    -  expectError(
    -      dir.getFile('subdir', goog.fs.DirectoryEntry.Behavior.CREATE),
    -      goog.fs.Error.ErrorCode.TYPE_MISMATCH);
    -}
    -
    -function testCreateExclusiveExistingFile() {
    -  expectError(
    -      dir.getFile('file', goog.fs.DirectoryEntry.Behavior.CREATE_EXCLUSIVE),
    -      goog.fs.Error.ErrorCode.INVALID_MODIFICATION);
    -}
    -
    -function testListEmptyDirectory() {
    -  var emptyDir = fs.getRoot().
    -      getDirectorySync('empty', goog.fs.DirectoryEntry.Behavior.CREATE);
    -
    -  emptyDir.listDirectory().
    -      addCallback(function(entryList) {
    -        assertSameElements([], entryList);
    -      }).
    -      addBoth(continueTesting);
    -  waitForAsync('testListEmptyDirectory');
    -}
    -
    -function testListDirectory() {
    -  var root = fs.getRoot();
    -  root.getDirectorySync('dir1', goog.fs.DirectoryEntry.Behavior.CREATE);
    -  root.getDirectorySync('dir2', goog.fs.DirectoryEntry.Behavior.CREATE);
    -  root.getFileSync('file1', goog.fs.DirectoryEntry.Behavior.CREATE);
    -  root.getFileSync('file2', goog.fs.DirectoryEntry.Behavior.CREATE);
    -
    -  fs.getRoot().listDirectory().
    -      addCallback(function(entryList) {
    -        assertSameElements([
    -          'dir1',
    -          'dir2',
    -          'file1',
    -          'file2',
    -          'foo'
    -        ],
    -        goog.array.map(entryList, function(entry) {
    -          return entry.getName();
    -        }));
    -      }).
    -      addBoth(continueTesting);
    -  waitForAsync('testListDirectory');
    -}
    -
    -function testCreatePath() {
    -  dir.createPath('baz/bat').
    -      addCallback(function(batDir) {
    -        assertEquals('/foo/baz/bat', batDir.getFullPath());
    -        return batDir.createPath('../zazzle');
    -      }).
    -      addCallback(function(zazzleDir) {
    -        assertEquals('/foo/baz/zazzle', zazzleDir.getFullPath());
    -        return zazzleDir.createPath('/elements/actinides/neptunium/');
    -      }).
    -      addCallback(function(elDir) {
    -        assertEquals('/elements/actinides/neptunium', elDir.getFullPath());
    -      }).
    -      addBoth(continueTesting);
    -  waitForAsync('testCreatePath');
    -}
    -
    -
    -function continueTesting(result) {
    -  asyncTestCase.continueTesting();
    -  if (result instanceof Error) {
    -    throw result;
    -  }
    -  mockClock.tick();
    -}
    -
    -function expectError(deferred, code) {
    -  deferred.
    -      addCallback(function() { fail('Expected an error'); }).
    -      addErrback(function(err) {
    -        assertEquals(code, err.code);
    -        asyncTestCase.continueTesting();
    -      });
    -  waitForAsync('waiting for error');
    -}
    -
    -function waitForAsync(msg) {
    -  asyncTestCase.waitForAsync(msg);
    -  mockClock.tick();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/fs/entry.js b/src/database/third_party/closure-library/closure/goog/testing/fs/entry.js
    deleted file mode 100644
    index c8aba755354..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/fs/entry.js
    +++ /dev/null
    @@ -1,637 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Mock filesystem objects. These are all in the same file to
    - * avoid circular dependency issues.
    - *
    - */
    -
    -goog.provide('goog.testing.fs.DirectoryEntry');
    -goog.provide('goog.testing.fs.Entry');
    -goog.provide('goog.testing.fs.FileEntry');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.async.Deferred');
    -goog.require('goog.fs.DirectoryEntry');
    -goog.require('goog.fs.DirectoryEntryImpl');
    -goog.require('goog.fs.Entry');
    -goog.require('goog.fs.Error');
    -goog.require('goog.fs.FileEntry');
    -goog.require('goog.functions');
    -goog.require('goog.object');
    -goog.require('goog.string');
    -goog.require('goog.testing.fs.File');
    -goog.require('goog.testing.fs.FileWriter');
    -
    -
    -
    -/**
    - * A mock filesystem entry object.
    - *
    - * @param {!goog.testing.fs.FileSystem} fs The filesystem containing this entry.
    - * @param {!goog.testing.fs.DirectoryEntry} parent The directory entry directly
    - *     containing this entry.
    - * @param {string} name The name of this entry.
    - * @constructor
    - * @implements {goog.fs.Entry}
    - */
    -goog.testing.fs.Entry = function(fs, parent, name) {
    -  /**
    -   * This entry's filesystem.
    -   * @type {!goog.testing.fs.FileSystem}
    -   * @private
    -   */
    -  this.fs_ = fs;
    -
    -  /**
    -   * The name of this entry.
    -   * @type {string}
    -   * @private
    -   */
    -  this.name_ = name;
    -
    -  /**
    -   * The parent of this entry.
    -   * @type {!goog.testing.fs.DirectoryEntry}
    -   */
    -  this.parent = parent;
    -};
    -
    -
    -/**
    - * Whether or not this entry has been deleted.
    - * @type {boolean}
    - */
    -goog.testing.fs.Entry.prototype.deleted = false;
    -
    -
    -/** @override */
    -goog.testing.fs.Entry.prototype.isFile = goog.abstractMethod;
    -
    -
    -/** @override */
    -goog.testing.fs.Entry.prototype.isDirectory = goog.abstractMethod;
    -
    -
    -/** @override */
    -goog.testing.fs.Entry.prototype.getName = function() {
    -  return this.name_;
    -};
    -
    -
    -/** @override */
    -goog.testing.fs.Entry.prototype.getFullPath = function() {
    -  if (this.getName() == '' || this.parent.getName() == '') {
    -    // The root directory has an empty name
    -    return '/' + this.name_;
    -  } else {
    -    return this.parent.getFullPath() + '/' + this.name_;
    -  }
    -};
    -
    -
    -/**
    - * @return {!goog.testing.fs.FileSystem}
    - * @override
    - */
    -goog.testing.fs.Entry.prototype.getFileSystem = function() {
    -  return this.fs_;
    -};
    -
    -
    -/** @override */
    -goog.testing.fs.Entry.prototype.getLastModified = goog.abstractMethod;
    -
    -
    -/** @override */
    -goog.testing.fs.Entry.prototype.getMetadata = goog.abstractMethod;
    -
    -
    -/** @override */
    -goog.testing.fs.Entry.prototype.moveTo = function(parent, opt_newName) {
    -  var msg = 'moving ' + this.getFullPath() + ' into ' + parent.getFullPath() +
    -      (opt_newName ? ', renaming to ' + opt_newName : '');
    -  var newFile;
    -  return this.checkNotDeleted(msg).
    -      addCallback(function() { return this.copyTo(parent, opt_newName); }).
    -      addCallback(function(file) {
    -        newFile = file;
    -        return this.remove();
    -      }).addCallback(function() { return newFile; });
    -};
    -
    -
    -/** @override */
    -goog.testing.fs.Entry.prototype.copyTo = function(parent, opt_newName) {
    -  goog.asserts.assert(parent instanceof goog.testing.fs.DirectoryEntry);
    -  var msg = 'copying ' + this.getFullPath() + ' into ' + parent.getFullPath() +
    -      (opt_newName ? ', renaming to ' + opt_newName : '');
    -  var self = this;
    -  return this.checkNotDeleted(msg).addCallback(function() {
    -    var name = opt_newName || self.getName();
    -    var entry = self.clone();
    -    parent.children[name] = entry;
    -    parent.lastModifiedTimestamp_ = goog.now();
    -    entry.name_ = name;
    -    entry.parent = /** @type {!goog.testing.fs.DirectoryEntry} */ (parent);
    -    return entry;
    -  });
    -};
    -
    -
    -/**
    - * @return {!goog.testing.fs.Entry} A shallow copy of this entry object.
    - */
    -goog.testing.fs.Entry.prototype.clone = goog.abstractMethod;
    -
    -
    -/** @override */
    -goog.testing.fs.Entry.prototype.toUrl = function(opt_mimetype) {
    -  return 'fakefilesystem:' + this.getFullPath();
    -};
    -
    -
    -/** @override */
    -goog.testing.fs.Entry.prototype.toUri = goog.testing.fs.Entry.prototype.toUrl;
    -
    -
    -/** @override */
    -goog.testing.fs.Entry.prototype.wrapEntry = goog.abstractMethod;
    -
    -
    -/** @override */
    -goog.testing.fs.Entry.prototype.remove = function() {
    -  var msg = 'removing ' + this.getFullPath();
    -  var self = this;
    -  return this.checkNotDeleted(msg).addCallback(function() {
    -    delete this.parent.children[self.getName()];
    -    self.parent.lastModifiedTimestamp_ = goog.now();
    -    self.deleted = true;
    -    return;
    -  });
    -};
    -
    -
    -/** @override */
    -goog.testing.fs.Entry.prototype.getParent = function() {
    -  var msg = 'getting parent of ' + this.getFullPath();
    -  return this.checkNotDeleted(msg).
    -      addCallback(function() { return this.parent; });
    -};
    -
    -
    -/**
    - * Return a deferred that will call its errback if this entry has been deleted.
    - * In addition, the deferred will only run after a timeout of 0, and all its
    - * callbacks will run with the entry as "this".
    - *
    - * @param {string} action The name of the action being performed. For error
    - *     reporting.
    - * @return {!goog.async.Deferred} The deferred that will be called after a
    - *     timeout of 0.
    - * @protected
    - */
    -goog.testing.fs.Entry.prototype.checkNotDeleted = function(action) {
    -  var d = new goog.async.Deferred(undefined, this);
    -  goog.Timer.callOnce(function() {
    -    if (this.deleted) {
    -      var err = new goog.fs.Error(
    -          /** @type {!FileError} */ ({'name': 'NotFoundError'}),
    -          action);
    -      d.errback(err);
    -    } else {
    -      d.callback();
    -    }
    -  }, 0, this);
    -  return d;
    -};
    -
    -
    -
    -/**
    - * A mock directory entry object.
    - *
    - * @param {!goog.testing.fs.FileSystem} fs The filesystem containing this entry.
    - * @param {goog.testing.fs.DirectoryEntry} parent The directory entry directly
    - *     containing this entry. If this is null, that means this is the root
    - *     directory and so is its own parent.
    - * @param {string} name The name of this entry.
    - * @param {!Object<!goog.testing.fs.Entry>} children The map of child names to
    - *     entry objects.
    - * @constructor
    - * @extends {goog.testing.fs.Entry}
    - * @implements {goog.fs.DirectoryEntry}
    - * @final
    - */
    -goog.testing.fs.DirectoryEntry = function(fs, parent, name, children) {
    -  goog.testing.fs.DirectoryEntry.base(
    -      this, 'constructor', fs, parent || this, name);
    -
    -  /**
    -   * The map of child names to entry objects.
    -   * @type {!Object<!goog.testing.fs.Entry>}
    -   */
    -  this.children = children;
    -
    -  /**
    -   * The modification time of the directory. Measured using goog.now, which may
    -   * be overridden with mock time providers.
    -   * @type {number}
    -   * @private
    -   */
    -  this.lastModifiedTimestamp_ = goog.now();
    -};
    -goog.inherits(goog.testing.fs.DirectoryEntry, goog.testing.fs.Entry);
    -
    -
    -/**
    - * Constructs and returns the metadata object for this entry.
    - * @return {{modificationTime: Date}} The metadata object.
    - * @private
    - */
    -goog.testing.fs.DirectoryEntry.prototype.getMetadata_ = function() {
    -  return {
    -    'modificationTime': new Date(this.lastModifiedTimestamp_)
    -  };
    -};
    -
    -
    -/** @override */
    -goog.testing.fs.DirectoryEntry.prototype.isFile = function() {
    -  return false;
    -};
    -
    -
    -/** @override */
    -goog.testing.fs.DirectoryEntry.prototype.isDirectory = function() {
    -  return true;
    -};
    -
    -
    -/** @override */
    -goog.testing.fs.DirectoryEntry.prototype.getLastModified = function() {
    -  var msg = 'reading last modified date for ' + this.getFullPath();
    -  return this.checkNotDeleted(msg).
    -      addCallback(function() {return new Date(this.lastModifiedTimestamp_)});
    -};
    -
    -
    -/** @override */
    -goog.testing.fs.DirectoryEntry.prototype.getMetadata = function() {
    -  var msg = 'reading metadata for ' + this.getFullPath();
    -  return this.checkNotDeleted(msg).
    -      addCallback(function() {return this.getMetadata_()});
    -};
    -
    -
    -/** @override */
    -goog.testing.fs.DirectoryEntry.prototype.clone = function() {
    -  return new goog.testing.fs.DirectoryEntry(
    -      this.getFileSystem(), this.parent, this.getName(), this.children);
    -};
    -
    -
    -/** @override */
    -goog.testing.fs.DirectoryEntry.prototype.remove = function() {
    -  if (!goog.object.isEmpty(this.children)) {
    -    var d = new goog.async.Deferred();
    -    goog.Timer.callOnce(function() {
    -      d.errback(new goog.fs.Error(
    -          /** @type {!FileError} */ ({'name': 'InvalidModificationError'}),
    -          'removing ' + this.getFullPath()));
    -    }, 0, this);
    -    return d;
    -  } else if (this != this.getFileSystem().getRoot()) {
    -    return goog.testing.fs.DirectoryEntry.base(this, 'remove');
    -  } else {
    -    // Root directory, do nothing.
    -    return goog.async.Deferred.succeed();
    -  }
    -};
    -
    -
    -/** @override */
    -goog.testing.fs.DirectoryEntry.prototype.getFile = function(
    -    path, opt_behavior) {
    -  var msg = 'loading file ' + path + ' from ' + this.getFullPath();
    -  opt_behavior = opt_behavior || goog.fs.DirectoryEntry.Behavior.DEFAULT;
    -  return this.checkNotDeleted(msg).addCallback(function() {
    -    try {
    -      return goog.async.Deferred.succeed(this.getFileSync(path, opt_behavior));
    -    } catch (e) {
    -      return goog.async.Deferred.fail(e);
    -    }
    -  });
    -};
    -
    -
    -/** @override */
    -goog.testing.fs.DirectoryEntry.prototype.getDirectory = function(
    -    path, opt_behavior) {
    -  var msg = 'loading directory ' + path + ' from ' + this.getFullPath();
    -  opt_behavior = opt_behavior || goog.fs.DirectoryEntry.Behavior.DEFAULT;
    -  return this.checkNotDeleted(msg).addCallback(function() {
    -    try {
    -      return goog.async.Deferred.succeed(
    -          this.getDirectorySync(path, opt_behavior));
    -    } catch (e) {
    -      return goog.async.Deferred.fail(e);
    -    }
    -  });
    -};
    -
    -
    -/**
    - * Get a file entry synchronously, without waiting for a Deferred to resolve.
    - *
    - * @param {string} path The path to the file, relative to this directory.
    - * @param {goog.fs.DirectoryEntry.Behavior=} opt_behavior The behavior for
    - *     loading the file.
    - * @param {string=} opt_data The string data encapsulated by the blob.
    - * @param {string=} opt_type The mime type of the blob.
    - * @return {!goog.testing.fs.FileEntry} The loaded file.
    - */
    -goog.testing.fs.DirectoryEntry.prototype.getFileSync = function(
    -    path, opt_behavior, opt_data, opt_type) {
    -  opt_behavior = opt_behavior || goog.fs.DirectoryEntry.Behavior.DEFAULT;
    -  return (/** @type {!goog.testing.fs.FileEntry} */ (this.getEntry_(
    -      path, opt_behavior, true /* isFile */,
    -      goog.bind(function(parent, name) {
    -        return new goog.testing.fs.FileEntry(
    -            this.getFileSystem(), parent, name,
    -            goog.isDef(opt_data) ? opt_data : '', opt_type);
    -      }, this))));
    -};
    -
    -
    -/**
    - * Creates a file synchronously. This is a shorthand for getFileSync, useful for
    - * setting up tests.
    - *
    - * @param {string} path The path to the file, relative to this directory.
    - * @return {!goog.testing.fs.FileEntry} The created file.
    - */
    -goog.testing.fs.DirectoryEntry.prototype.createFileSync = function(path) {
    -  return this.getFileSync(path, goog.fs.DirectoryEntry.Behavior.CREATE);
    -};
    -
    -
    -/**
    - * Get a directory synchronously, without waiting for a Deferred to resolve.
    - *
    - * @param {string} path The path to the directory, relative to this one.
    - * @param {goog.fs.DirectoryEntry.Behavior=} opt_behavior The behavior for
    - *     loading the directory.
    - * @return {!goog.testing.fs.DirectoryEntry} The loaded directory.
    - */
    -goog.testing.fs.DirectoryEntry.prototype.getDirectorySync = function(
    -    path, opt_behavior) {
    -  opt_behavior = opt_behavior || goog.fs.DirectoryEntry.Behavior.DEFAULT;
    -  return (/** @type {!goog.testing.fs.DirectoryEntry} */ (this.getEntry_(
    -      path, opt_behavior, false /* isFile */,
    -      goog.bind(function(parent, name) {
    -        return new goog.testing.fs.DirectoryEntry(
    -            this.getFileSystem(), parent, name, {});
    -      }, this))));
    -};
    -
    -
    -/**
    - * Creates a directory synchronously. This is a shorthand for getFileSync,
    - * useful for setting up tests.
    - *
    - * @param {string} path The path to the directory, relative to this directory.
    - * @return {!goog.testing.fs.DirectoryEntry} The created directory.
    - */
    -goog.testing.fs.DirectoryEntry.prototype.createDirectorySync = function(path) {
    -  return this.getDirectorySync(path, goog.fs.DirectoryEntry.Behavior.CREATE);
    -};
    -
    -
    -/**
    - * Get a file or directory entry from a path. This handles parsing the path for
    - * subdirectories and throwing appropriate errors should something go wrong.
    - *
    - * @param {string} path The path to the entry, relative to this directory.
    - * @param {goog.fs.DirectoryEntry.Behavior} behavior The behavior for loading
    - *     the entry.
    - * @param {boolean} isFile Whether a file or directory is being loaded.
    - * @param {function(!goog.testing.fs.DirectoryEntry, string) :
    - *             !goog.testing.fs.Entry} createFn
    - *     The function for creating the entry if it doesn't yet exist. This is
    - *     passed the parent entry and the name of the new entry.
    - * @return {!goog.testing.fs.Entry} The loaded entry.
    - * @private
    - */
    -goog.testing.fs.DirectoryEntry.prototype.getEntry_ = function(
    -    path, behavior, isFile, createFn) {
    -  // Filter out leading, trailing, and duplicate slashes.
    -  var components = goog.array.filter(path.split('/'), goog.functions.identity);
    -
    -  var basename = /** @type {string} */ (goog.array.peek(components)) || '';
    -  var dir = goog.string.startsWith(path, '/') ?
    -      this.getFileSystem().getRoot() : this;
    -
    -  goog.array.forEach(components.slice(0, -1), function(p) {
    -    var subdir = dir.children[p];
    -    if (!subdir) {
    -      throw new goog.fs.Error(
    -          /** @type {!FileError} */ ({'name': 'NotFoundError'}),
    -          'loading ' + path + ' from ' + this.getFullPath() + ' (directory ' +
    -          dir.getFullPath() + '/' + p + ')');
    -    }
    -    dir = subdir;
    -  }, this);
    -
    -  // If there is no basename, the path must resolve to the root directory.
    -  var entry = basename ? dir.children[basename] : dir;
    -
    -  if (!entry) {
    -    if (behavior == goog.fs.DirectoryEntry.Behavior.DEFAULT) {
    -      throw new goog.fs.Error(
    -          /** @type {!FileError} */ ({'name': 'NotFoundError'}),
    -          'loading ' + path + ' from ' + this.getFullPath());
    -    } else {
    -      goog.asserts.assert(
    -          behavior == goog.fs.DirectoryEntry.Behavior.CREATE ||
    -          behavior == goog.fs.DirectoryEntry.Behavior.CREATE_EXCLUSIVE);
    -      entry = createFn(dir, basename);
    -      dir.children[basename] = entry;
    -      this.lastModifiedTimestamp_ = goog.now();
    -      return entry;
    -    }
    -  } else if (behavior == goog.fs.DirectoryEntry.Behavior.CREATE_EXCLUSIVE) {
    -    throw new goog.fs.Error(
    -        /** @type {!FileError} */ ({'name': 'InvalidModificationError'}),
    -        'loading ' + path + ' from ' + this.getFullPath());
    -  } else if (entry.isFile() != isFile) {
    -    throw new goog.fs.Error(
    -        /** @type {!FileError} */ ({'name': 'TypeMismatchError'}),
    -        'loading ' + path + ' from ' + this.getFullPath());
    -  } else {
    -    if (behavior == goog.fs.DirectoryEntry.Behavior.CREATE) {
    -      this.lastModifiedTimestamp_ = goog.now();
    -    }
    -    return entry;
    -  }
    -};
    -
    -
    -/**
    - * Returns whether this directory has a child with the given name.
    - *
    - * @param {string} name The name of the entry to check for.
    - * @return {boolean} Whether or not this has a child with the given name.
    - */
    -goog.testing.fs.DirectoryEntry.prototype.hasChild = function(name) {
    -  return name in this.children;
    -};
    -
    -
    -/** @override */
    -goog.testing.fs.DirectoryEntry.prototype.removeRecursively = function() {
    -  var msg = 'removing ' + this.getFullPath() + ' recursively';
    -  return this.checkNotDeleted(msg).addCallback(function() {
    -    var d = goog.async.Deferred.succeed(null);
    -    goog.object.forEach(this.children, function(child) {
    -      d.awaitDeferred(
    -          child.isDirectory() ? child.removeRecursively() : child.remove());
    -    });
    -    d.addCallback(function() { return this.remove(); }, this);
    -    return d;
    -  });
    -};
    -
    -
    -/** @override */
    -goog.testing.fs.DirectoryEntry.prototype.listDirectory = function() {
    -  var msg = 'listing ' + this.getFullPath();
    -  return this.checkNotDeleted(msg).addCallback(function() {
    -    return goog.object.getValues(this.children);
    -  });
    -};
    -
    -
    -/** @override */
    -goog.testing.fs.DirectoryEntry.prototype.createPath =
    -    // This isn't really type-safe.
    -    /** @type {!Function} */ (goog.fs.DirectoryEntryImpl.prototype.createPath);
    -
    -
    -
    -/**
    - * A mock file entry object.
    - *
    - * @param {!goog.testing.fs.FileSystem} fs The filesystem containing this entry.
    - * @param {!goog.testing.fs.DirectoryEntry} parent The directory entry directly
    - *     containing this entry.
    - * @param {string} name The name of this entry.
    - * @param {string} data The data initially contained in the file.
    - * @param {string=} opt_type The mime type of the blob.
    - * @constructor
    - * @extends {goog.testing.fs.Entry}
    - * @implements {goog.fs.FileEntry}
    - * @final
    - */
    -goog.testing.fs.FileEntry = function(fs, parent, name, data, opt_type) {
    -  goog.testing.fs.FileEntry.base(this, 'constructor', fs, parent, name);
    -
    -  /**
    -   * The internal file blob referenced by this file entry.
    -   * @type {!goog.testing.fs.File}
    -   * @private
    -   */
    -  this.file_ =
    -      new goog.testing.fs.File(name, new Date(goog.now()), data, opt_type);
    -
    -  /**
    -   * The metadata for file.
    -   * @type {{modificationTime: Date}}
    -   * @private
    -   */
    -  this.metadata_ = {
    -    'modificationTime': this.file_.lastModifiedDate
    -  };
    -};
    -goog.inherits(goog.testing.fs.FileEntry, goog.testing.fs.Entry);
    -
    -
    -/** @override */
    -goog.testing.fs.FileEntry.prototype.isFile = function() {
    -  return true;
    -};
    -
    -
    -/** @override */
    -goog.testing.fs.FileEntry.prototype.isDirectory = function() {
    -  return false;
    -};
    -
    -
    -/** @override */
    -goog.testing.fs.FileEntry.prototype.clone = function() {
    -  return new goog.testing.fs.FileEntry(
    -      this.getFileSystem(), this.parent,
    -      this.getName(), this.fileSync().toString());
    -};
    -
    -
    -/** @override */
    -goog.testing.fs.FileEntry.prototype.getLastModified = function() {
    -  return this.file().addCallback(function(file) {
    -    return file.lastModifiedDate;
    -  });
    -};
    -
    -
    -/** @override */
    -goog.testing.fs.FileEntry.prototype.getMetadata = function() {
    -  var msg = 'getting metadata for ' + this.getFullPath();
    -  return this.checkNotDeleted(msg).addCallback(function() {
    -    return this.metadata_;
    -  });
    -};
    -
    -
    -/** @override */
    -goog.testing.fs.FileEntry.prototype.createWriter = function() {
    -  var d = new goog.async.Deferred();
    -  goog.Timer.callOnce(
    -      goog.bind(d.callback, d, new goog.testing.fs.FileWriter(this)));
    -  return d;
    -};
    -
    -
    -/** @override */
    -goog.testing.fs.FileEntry.prototype.file = function() {
    -  var msg = 'getting file for ' + this.getFullPath();
    -  return this.checkNotDeleted(msg).addCallback(function() {
    -    return this.fileSync();
    -  });
    -};
    -
    -
    -/**
    - * Get the internal file representation synchronously, without waiting for a
    - * Deferred to resolve.
    - *
    - * @return {!goog.testing.fs.File} The internal file blob referenced by this
    - *     FileEntry.
    - */
    -goog.testing.fs.FileEntry.prototype.fileSync = function() {
    -  return this.file_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/fs/entry_test.html b/src/database/third_party/closure-library/closure/goog/testing/fs/entry_test.html
    deleted file mode 100644
    index 734cf1f4e83..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/fs/entry_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.testing.fs.Entry
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.fs.EntryTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/fs/entry_test.js b/src/database/third_party/closure-library/closure/goog/testing/fs/entry_test.js
    deleted file mode 100644
    index 3f3d3eff93b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/fs/entry_test.js
    +++ /dev/null
    @@ -1,222 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.fs.EntryTest');
    -goog.setTestOnly('goog.testing.fs.EntryTest');
    -
    -goog.require('goog.fs.DirectoryEntry');
    -goog.require('goog.fs.Error');
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.fs.FileSystem');
    -goog.require('goog.testing.jsunit');
    -
    -var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall();
    -var fs, file, mockClock;
    -
    -function setUp() {
    -  mockClock = new goog.testing.MockClock(true);
    -
    -  fs = new goog.testing.fs.FileSystem();
    -  file = fs.getRoot().
    -      getDirectorySync('foo', goog.fs.DirectoryEntry.Behavior.CREATE).
    -      getFileSync('bar', goog.fs.DirectoryEntry.Behavior.CREATE);
    -}
    -
    -function tearDown() {
    -  mockClock.uninstall();
    -}
    -
    -function testGetName() {
    -  assertEquals('bar', file.getName());
    -}
    -
    -function testGetFullPath() {
    -  assertEquals('/foo/bar', file.getFullPath());
    -  assertEquals('/', fs.getRoot().getFullPath());
    -}
    -
    -function testGetFileSystem() {
    -  assertEquals(fs, file.getFileSystem());
    -}
    -
    -function testMoveTo() {
    -  file.moveTo(fs.getRoot()).addCallback(function(newFile) {
    -    assertTrue(file.deleted);
    -    assertFalse(newFile.deleted);
    -    assertEquals('/bar', newFile.getFullPath());
    -    assertEquals(fs.getRoot(), newFile.parent);
    -    assertEquals(newFile, fs.getRoot().getFileSync('bar'));
    -    assertFalse(fs.getRoot().getDirectorySync('foo').hasChild('bar'));
    -
    -    asyncTestCase.continueTesting();
    -  });
    -  waitForAsync('waiting for file move');
    -}
    -
    -function testMoveToNewName() {
    -  // Advance the clock to an arbitrary, known time.
    -  mockClock.tick(71);
    -  file.moveTo(fs.getRoot(), 'baz').
    -      addCallback(function(newFile) {
    -        mockClock.tick();
    -        assertTrue(file.deleted);
    -        assertFalse(newFile.deleted);
    -        assertEquals('/baz', newFile.getFullPath());
    -        assertEquals(fs.getRoot(), newFile.parent);
    -        assertEquals(newFile, fs.getRoot().getFileSync('baz'));
    -
    -        var oldParentDir = fs.getRoot().getDirectorySync('foo');
    -        assertFalse(oldParentDir.hasChild('bar'));
    -        assertFalse(oldParentDir.hasChild('baz'));
    -
    -        return oldParentDir.getLastModified();
    -      }).
    -      addCallback(function(lastModifiedDate) {
    -        assertEquals(71, lastModifiedDate.getTime());
    -        var oldParentDir = fs.getRoot().getDirectorySync('foo');
    -        return oldParentDir.getMetadata();
    -      }).
    -      addCallback(function(metadata) {
    -        assertEquals(71, metadata.modificationTime.getTime());
    -        return fs.getRoot().getLastModified();
    -      }).
    -      addCallback(function(rootLastModifiedDate) {
    -        assertEquals(71, rootLastModifiedDate.getTime());
    -        return fs.getRoot().getMetadata();
    -      }).
    -      addCallback(function(rootMetadata) {
    -        assertEquals(71, rootMetadata.modificationTime.getTime());
    -        asyncTestCase.continueTesting();
    -      });
    -  waitForAsync('waiting for file move');
    -}
    -
    -function testMoveDeletedFile() {
    -  assertFailsWhenDeleted(function() { return file.moveTo(fs.getRoot()); });
    -}
    -
    -function testCopyTo() {
    -  mockClock.tick(61);
    -  file.copyTo(fs.getRoot()).
    -      addCallback(function(newFile) {
    -        assertFalse(file.deleted);
    -        assertFalse(newFile.deleted);
    -        assertEquals('/bar', newFile.getFullPath());
    -        assertEquals(fs.getRoot(), newFile.parent);
    -        assertEquals(newFile, fs.getRoot().getFileSync('bar'));
    -
    -        var oldParentDir = fs.getRoot().getDirectorySync('foo');
    -        assertEquals(file, oldParentDir.getFileSync('bar'));
    -        return oldParentDir.getLastModified();
    -      }).
    -      addCallback(function(lastModifiedDate) {
    -        assertEquals('The original parent directory was not modified.',
    -                     0, lastModifiedDate.getTime());
    -        var oldParentDir = fs.getRoot().getDirectorySync('foo');
    -        return oldParentDir.getMetadata();
    -      }).
    -      addCallback(function(metadata) {
    -        assertEquals('The original parent directory was not modified.',
    -                     0, metadata.modificationTime.getTime());
    -        return fs.getRoot().getLastModified();
    -      }).
    -      addCallback(function(rootLastModifiedDate) {
    -        assertEquals(61, rootLastModifiedDate.getTime());
    -        return fs.getRoot().getMetadata();
    -      }).
    -      addCallback(function(rootMetadata) {
    -        assertEquals(61, rootMetadata.modificationTime.getTime());
    -        asyncTestCase.continueTesting();
    -      });
    -  waitForAsync('waiting for file copy');
    -}
    -
    -function testCopyToNewName() {
    -  file.copyTo(fs.getRoot(), 'baz').addCallback(function(newFile) {
    -    assertFalse(file.deleted);
    -    assertFalse(newFile.deleted);
    -    assertEquals('/baz', newFile.getFullPath());
    -    assertEquals(fs.getRoot(), newFile.parent);
    -    assertEquals(newFile, fs.getRoot().getFileSync('baz'));
    -    assertEquals(file, fs.getRoot().getDirectorySync('foo').getFileSync('bar'));
    -    assertFalse(fs.getRoot().getDirectorySync('foo').hasChild('baz'));
    -
    -    asyncTestCase.continueTesting();
    -  });
    -  waitForAsync('waiting for file copy');
    -}
    -
    -function testCopyDeletedFile() {
    -  assertFailsWhenDeleted(function() { return file.copyTo(fs.getRoot()); });
    -}
    -
    -function testRemove() {
    -  mockClock.tick(57);
    -  file.remove().
    -      addCallback(function() {
    -        mockClock.tick();
    -        var parentDir = fs.getRoot().getDirectorySync('foo');
    -
    -        assertTrue(file.deleted);
    -        assertFalse(parentDir.hasChild('bar'));
    -
    -        return parentDir.getLastModified();
    -      }).
    -      addCallback(function(date) {
    -        assertEquals(57, date.getTime());
    -        var parentDir = fs.getRoot().getDirectorySync('foo');
    -        return parentDir.getMetadata();
    -      }).
    -      addCallback(function(metadata) {
    -        assertEquals(57, metadata.modificationTime.getTime());
    -        asyncTestCase.continueTesting();
    -      });
    -  waitForAsync('waiting for file removal');
    -}
    -
    -function testRemoveDeletedFile() {
    -  assertFailsWhenDeleted(function() { return file.remove(); });
    -}
    -
    -function testGetParent() {
    -  file.getParent().addCallback(function(p) {
    -    assertEquals(file.parent, p);
    -    assertEquals(fs.getRoot().getDirectorySync('foo'), p);
    -    assertEquals('/foo', p.getFullPath());
    -
    -    asyncTestCase.continueTesting();
    -  });
    -  waitForAsync('waiting for file parent');
    -}
    -
    -function testGetDeletedFileParent() {
    -  assertFailsWhenDeleted(function() { return file.getParent(); });
    -}
    -
    -
    -function assertFailsWhenDeleted(fn) {
    -  file.remove().addCallback(fn).
    -      addCallback(function() { fail('Expected an error'); }).
    -      addErrback(function(err) {
    -        assertEquals(goog.fs.Error.ErrorCode.NOT_FOUND, err.code);
    -        asyncTestCase.continueTesting();
    -      });
    -  waitForAsync('waiting for file operation');
    -}
    -
    -function waitForAsync(msg) {
    -  asyncTestCase.waitForAsync(msg);
    -  mockClock.tick();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/fs/file.js b/src/database/third_party/closure-library/closure/goog/testing/fs/file.js
    deleted file mode 100644
    index aa72e66caa0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/fs/file.js
    +++ /dev/null
    @@ -1,53 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Mock file object.
    - *
    - */
    -
    -goog.provide('goog.testing.fs.File');
    -
    -goog.require('goog.testing.fs.Blob');
    -
    -
    -
    -/**
    - * A mock file object.
    - *
    - * @param {string} name The name of the file.
    - * @param {Date=} opt_lastModified The last modified date for this file. May be
    - *     null if file modification dates are not supported.
    - * @param {string=} opt_data The string data encapsulated by the blob.
    - * @param {string=} opt_type The mime type of the blob.
    - * @constructor
    - * @extends {goog.testing.fs.Blob}
    - * @final
    - */
    -goog.testing.fs.File = function(name, opt_lastModified, opt_data, opt_type) {
    -  goog.testing.fs.File.base(this, 'constructor', opt_data, opt_type);
    -
    -  /**
    -   * @see http://www.w3.org/TR/FileAPI/#dfn-name
    -   * @type {string}
    -   */
    -  this.name = name;
    -
    -  /**
    -   * @see http://www.w3.org/TR/FileAPI/#dfn-lastModifiedDate
    -   * @type {Date}
    -   */
    -  this.lastModifiedDate = opt_lastModified || null;
    -};
    -goog.inherits(goog.testing.fs.File, goog.testing.fs.Blob);
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/fs/fileentry_test.html b/src/database/third_party/closure-library/closure/goog/testing/fs/fileentry_test.html
    deleted file mode 100644
    index 574ef466a35..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/fs/fileentry_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.testing.fs.FileEntry
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.fs.FileEntryTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/fs/fileentry_test.js b/src/database/third_party/closure-library/closure/goog/testing/fs/fileentry_test.js
    deleted file mode 100644
    index 9e450f1e12e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/fs/fileentry_test.js
    +++ /dev/null
    @@ -1,88 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.fs.FileEntryTest');
    -goog.setTestOnly('goog.testing.fs.FileEntryTest');
    -
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.fs.FileEntry');
    -goog.require('goog.testing.fs.FileSystem');
    -goog.require('goog.testing.jsunit');
    -
    -var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall();
    -var fs, file, fileEntry, mockClock, currentTime;
    -
    -function setUp() {
    -  mockClock = new goog.testing.MockClock(true);
    -
    -  fs = new goog.testing.fs.FileSystem();
    -  fileEntry = fs.getRoot().createDirectorySync('foo').createFileSync('bar');
    -}
    -
    -function tearDown() {
    -  mockClock.uninstall();
    -}
    -
    -function testIsFile() {
    -  assertTrue(fileEntry.isFile());
    -}
    -
    -function testIsDirectory() {
    -  assertFalse(fileEntry.isDirectory());
    -}
    -
    -function testFile() {
    -  var testFile = new goog.testing.fs.FileEntry(fs, fs.getRoot(),
    -                                               'test', 'hello world');
    -  testFile.file().addCallback(function(f) {
    -    assertEquals('test', f.name);
    -    assertEquals('hello world', f.toString());
    -
    -    asyncTestCase.continueTesting();
    -  });
    -  waitForAsync('testFile');
    -}
    -
    -function testGetLastModified() {
    -  // Advance the clock to a known time.
    -  mockClock.tick(53);
    -  var testFile = new goog.testing.fs.FileEntry(fs, fs.getRoot(),
    -                                               'timeTest', 'hello world');
    -  mockClock.tick();
    -  testFile.getLastModified().addCallback(function(date) {
    -    assertEquals(53, date.getTime());
    -    asyncTestCase.continueTesting();
    -  });
    -  waitForAsync('testGetLastModified');
    -}
    -
    -function testGetMetadata() {
    -  // Advance the clock to a known time.
    -  mockClock.tick(54);
    -  var testFile = new goog.testing.fs.FileEntry(fs, fs.getRoot(),
    -                                               'timeTest', 'hello world');
    -  mockClock.tick();
    -  testFile.getMetadata().addCallback(function(metadata) {
    -    assertEquals(54, metadata.modificationTime.getTime());
    -    asyncTestCase.continueTesting();
    -  });
    -  waitForAsync('testGetMetadata');
    -}
    -
    -
    -function waitForAsync(msg) {
    -  asyncTestCase.waitForAsync(msg);
    -  mockClock.tick();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/fs/filereader.js b/src/database/third_party/closure-library/closure/goog/testing/fs/filereader.js
    deleted file mode 100644
    index 4fb965d4f58..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/fs/filereader.js
    +++ /dev/null
    @@ -1,275 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Mock FileReader object.
    - *
    - */
    -
    -goog.provide('goog.testing.fs.FileReader');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.fs.Error');
    -goog.require('goog.fs.FileReader');
    -goog.require('goog.testing.fs.ProgressEvent');
    -
    -
    -
    -/**
    - * A mock FileReader object. This emits the same events as
    - * {@link goog.fs.FileReader}.
    - *
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - */
    -goog.testing.fs.FileReader = function() {
    -  goog.testing.fs.FileReader.base(this, 'constructor');
    -
    -  /**
    -   * The current state of the reader.
    -   * @type {goog.fs.FileReader.ReadyState}
    -   * @private
    -   */
    -  this.readyState_ = goog.fs.FileReader.ReadyState.INIT;
    -};
    -goog.inherits(goog.testing.fs.FileReader, goog.events.EventTarget);
    -
    -
    -/**
    - * The most recent error experienced by this reader.
    - * @type {goog.fs.Error}
    - * @private
    - */
    -goog.testing.fs.FileReader.prototype.error_;
    -
    -
    -/**
    - * Whether the current operation has been aborted.
    - * @type {boolean}
    - * @private
    - */
    -goog.testing.fs.FileReader.prototype.aborted_ = false;
    -
    -
    -/**
    - * The blob this reader is reading from.
    - * @type {goog.testing.fs.Blob}
    - * @private
    - */
    -goog.testing.fs.FileReader.prototype.blob_;
    -
    -
    -/**
    - * The possible return types.
    - * @enum {number}
    - */
    -goog.testing.fs.FileReader.ReturnType = {
    -  /**
    -   * Used when reading as text.
    -   */
    -  TEXT: 1,
    -
    -  /**
    -   * Used when reading as binary string.
    -   */
    -  BINARY_STRING: 2,
    -
    -  /**
    -   * Used when reading as array buffer.
    -   */
    -  ARRAY_BUFFER: 3,
    -
    -  /**
    -   * Used when reading as data URL.
    -   */
    -  DATA_URL: 4
    -};
    -
    -
    -/**
    - * The return type we're reading.
    - * @type {goog.testing.fs.FileReader.ReturnType}
    - * @private
    - */
    -goog.testing.fs.FileReader.returnType_;
    -
    -
    -/**
    - * @see {goog.fs.FileReader#getReadyState}
    - * @return {goog.fs.FileReader.ReadyState} The current ready state.
    - */
    -goog.testing.fs.FileReader.prototype.getReadyState = function() {
    -  return this.readyState_;
    -};
    -
    -
    -/**
    - * @see {goog.fs.FileReader#getError}
    - * @return {goog.fs.Error} The current error.
    - */
    -goog.testing.fs.FileReader.prototype.getError = function() {
    -  return this.error_;
    -};
    -
    -
    -/**
    - * @see {goog.fs.FileReader#abort}
    - */
    -goog.testing.fs.FileReader.prototype.abort = function() {
    -  if (this.readyState_ != goog.fs.FileReader.ReadyState.LOADING) {
    -    var msg = 'aborting read';
    -    throw new goog.fs.Error(
    -        /** @type {!FileError} */ ({'name': 'InvalidStateError'}),
    -        msg);
    -  }
    -
    -  this.aborted_ = true;
    -};
    -
    -
    -/**
    - * @see {goog.fs.FileReader#getResult}
    - * @return {*} The result of the file read.
    - */
    -goog.testing.fs.FileReader.prototype.getResult = function() {
    -  if (this.readyState_ != goog.fs.FileReader.ReadyState.DONE) {
    -    return undefined;
    -  }
    -  if (this.error_) {
    -    return undefined;
    -  }
    -  if (this.returnType_ == goog.testing.fs.FileReader.ReturnType.TEXT) {
    -    return this.blob_.toString();
    -  } else if (this.returnType_ ==
    -      goog.testing.fs.FileReader.ReturnType.ARRAY_BUFFER) {
    -    return this.blob_.toArrayBuffer();
    -  } else if (this.returnType_ ==
    -      goog.testing.fs.FileReader.ReturnType.BINARY_STRING) {
    -    return this.blob_.toString();
    -  } else if (this.returnType_ ==
    -      goog.testing.fs.FileReader.ReturnType.DATA_URL) {
    -    return this.blob_.toDataUrl();
    -  } else {
    -    return undefined;
    -  }
    -};
    -
    -
    -/**
    - * Fires the read events.
    - * @param {!goog.testing.fs.Blob} blob The blob to read from.
    - * @private
    - */
    -goog.testing.fs.FileReader.prototype.read_ = function(blob) {
    -  this.blob_ = blob;
    -  if (this.readyState_ == goog.fs.FileReader.ReadyState.LOADING) {
    -    var msg = 'reading file';
    -    throw new goog.fs.Error(
    -        /** @type {!FileError} */ ({'name': 'InvalidStateError'}),
    -        msg);
    -  }
    -
    -  this.readyState_ = goog.fs.FileReader.ReadyState.LOADING;
    -  goog.Timer.callOnce(function() {
    -    if (this.aborted_) {
    -      this.abort_(blob.size);
    -      return;
    -    }
    -
    -    this.progressEvent_(goog.fs.FileReader.EventType.LOAD_START, 0, blob.size);
    -    this.progressEvent_(goog.fs.FileReader.EventType.LOAD, blob.size / 2,
    -        blob.size);
    -    this.progressEvent_(goog.fs.FileReader.EventType.LOAD, blob.size,
    -        blob.size);
    -    this.readyState_ = goog.fs.FileReader.ReadyState.DONE;
    -    this.progressEvent_(goog.fs.FileReader.EventType.LOAD, blob.size,
    -        blob.size);
    -    this.progressEvent_(goog.fs.FileReader.EventType.LOAD_END, blob.size,
    -        blob.size);
    -  }, 0, this);
    -};
    -
    -
    -/**
    - * @see {goog.fs.FileReader#readAsBinaryString}
    - * @param {!goog.testing.fs.Blob} blob The blob to read.
    - */
    -goog.testing.fs.FileReader.prototype.readAsBinaryString = function(blob) {
    -  this.returnType_ = goog.testing.fs.FileReader.ReturnType.BINARY_STRING;
    -  this.read_(blob);
    -};
    -
    -
    -/**
    - * @see {goog.fs.FileReader#readAsArrayBuffer}
    - * @param {!goog.testing.fs.Blob} blob The blob to read.
    - */
    -goog.testing.fs.FileReader.prototype.readAsArrayBuffer = function(blob) {
    -  this.returnType_ = goog.testing.fs.FileReader.ReturnType.ARRAY_BUFFER;
    -  this.read_(blob);
    -};
    -
    -
    -/**
    - * @see {goog.fs.FileReader#readAsText}
    - * @param {!goog.testing.fs.Blob} blob The blob to read.
    - * @param {string=} opt_encoding The name of the encoding to use.
    - */
    -goog.testing.fs.FileReader.prototype.readAsText = function(blob, opt_encoding) {
    -  this.returnType_ = goog.testing.fs.FileReader.ReturnType.TEXT;
    -  this.read_(blob);
    -};
    -
    -
    -/**
    - * @see {goog.fs.FileReader#readAsDataUrl}
    - * @param {!goog.testing.fs.Blob} blob The blob to read.
    - */
    -goog.testing.fs.FileReader.prototype.readAsDataUrl = function(blob) {
    -  this.returnType_ = goog.testing.fs.FileReader.ReturnType.DATA_URL;
    -  this.read_(blob);
    -};
    -
    -
    -/**
    - * Abort the current action and emit appropriate events.
    - *
    - * @param {number} total The total data that was to be processed, in bytes.
    - * @private
    - */
    -goog.testing.fs.FileReader.prototype.abort_ = function(total) {
    -  this.error_ = new goog.fs.Error(
    -      /** @type {!FileError} */ ({'name': 'AbortError'}),
    -      'reading file');
    -  this.progressEvent_(goog.fs.FileReader.EventType.ERROR, 0, total);
    -  this.progressEvent_(goog.fs.FileReader.EventType.ABORT, 0, total);
    -  this.readyState_ = goog.fs.FileReader.ReadyState.DONE;
    -  this.progressEvent_(goog.fs.FileReader.EventType.LOAD_END, 0, total);
    -  this.aborted_ = false;
    -};
    -
    -
    -/**
    - * Dispatch a progress event.
    - *
    - * @param {goog.fs.FileReader.EventType} type The event type.
    - * @param {number} loaded The number of bytes processed.
    - * @param {number} total The total data that was to be processed, in bytes.
    - * @private
    - */
    -goog.testing.fs.FileReader.prototype.progressEvent_ = function(type, loaded,
    -    total) {
    -  this.dispatchEvent(new goog.testing.fs.ProgressEvent(type, loaded, total));
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/fs/filereader_test.html b/src/database/third_party/closure-library/closure/goog/testing/fs/filereader_test.html
    deleted file mode 100644
    index 18dfb21d994..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/fs/filereader_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.testing.fs.FileReader
    -  </title>
    -  <script type="text/javascript" src="../../base.js">
    -  </script>
    -  <script type="text/javascript">
    -    goog.require('goog.testing.fs.FileReaderTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/fs/filereader_test.js b/src/database/third_party/closure-library/closure/goog/testing/fs/filereader_test.js
    deleted file mode 100644
    index b2e056b971e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/fs/filereader_test.js
    +++ /dev/null
    @@ -1,234 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.fs.FileReaderTest');
    -goog.setTestOnly('goog.testing.fs.FileReaderTest');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.async.Deferred');
    -goog.require('goog.events');
    -goog.require('goog.fs.Error');
    -goog.require('goog.fs.FileReader');
    -goog.require('goog.fs.FileSaver');
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.fs.FileReader');
    -goog.require('goog.testing.fs.FileSystem');
    -goog.require('goog.testing.jsunit');
    -
    -var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall();
    -var file, deferredReader;
    -var hasArrayBuffer = goog.isDef(goog.global.ArrayBuffer);
    -
    -function setUp() {
    -  var fs = new goog.testing.fs.FileSystem();
    -  var fileEntry = fs.getRoot().createDirectorySync('foo').createFileSync('bar');
    -  file = fileEntry.fileSync();
    -  file.setDataInternal('test content');
    -
    -  deferredReader = new goog.async.Deferred();
    -  goog.Timer.callOnce(
    -      goog.bind(deferredReader.callback, deferredReader,
    -          new goog.testing.fs.FileReader()));
    -}
    -
    -function testRead() {
    -  deferredReader.
    -      addCallback(goog.partial(checkReadyState,
    -                               goog.fs.FileReader.ReadyState.INIT)).
    -      addCallback(goog.partial(checkResult, undefined)).
    -      addCallback(goog.partial(readAsText)).
    -      addCallback(goog.partial(checkReadyState,
    -                               goog.fs.FileReader.ReadyState.LOADING)).
    -      addCallback(goog.partial(checkResult, undefined)).
    -      addCallback(goog.partial(waitForEvent,
    -                               goog.fs.FileReader.EventType.LOAD_START)).
    -      addCallback(goog.partial(checkResult, undefined)).
    -      addCallback(goog.partial(waitForEvent,
    -                               goog.fs.FileReader.EventType.LOAD)).
    -      addCallback(goog.partial(checkResult, undefined)).
    -      addCallback(goog.partial(waitForEvent,
    -                               goog.fs.FileReader.EventType.LOAD_END)).
    -      addCallback(goog.partial(checkResult, file.toString())).
    -      addCallback(goog.partial(checkReadyState,
    -                               goog.fs.FileReader.ReadyState.DONE)).
    -      addBoth(continueTesting);
    -  waitForAsync('testRead');
    -}
    -
    -function testReadAsArrayBuffer() {
    -  if (!hasArrayBuffer) {
    -    // Skip if array buffer is not supported
    -    return;
    -  }
    -  deferredReader.
    -      addCallback(goog.partial(checkReadyState,
    -                               goog.fs.FileReader.ReadyState.INIT)).
    -      addCallback(goog.partial(checkResult, undefined)).
    -      addCallback(goog.partial(readAsArrayBuffer)).
    -      addCallback(goog.partial(checkReadyState,
    -                               goog.fs.FileReader.ReadyState.LOADING)).
    -      addCallback(goog.partial(checkResult, undefined)).
    -      addCallback(goog.partial(waitForEvent,
    -                               goog.fs.FileReader.EventType.LOAD_START)).
    -      addCallback(goog.partial(checkResult, undefined)).
    -      addCallback(goog.partial(waitForEvent,
    -                               goog.fs.FileReader.EventType.LOAD)).
    -      addCallback(goog.partial(checkResult, undefined)).
    -      addCallback(goog.partial(waitForEvent,
    -                               goog.fs.FileReader.EventType.LOAD_END)).
    -      addCallback(goog.partial(checkResult, file.toArrayBuffer())).
    -      addCallback(goog.partial(checkReadyState,
    -                               goog.fs.FileReader.ReadyState.DONE)).
    -      addBoth(continueTesting);
    -  waitForAsync('testReadAsArrayBuffer');
    -}
    -
    -function testReadAsDataUrl() {
    -  deferredReader.
    -      addCallback(goog.partial(checkReadyState,
    -                               goog.fs.FileReader.ReadyState.INIT)).
    -      addCallback(goog.partial(checkResult, undefined)).
    -      addCallback(goog.partial(readAsDataUrl)).
    -      addCallback(goog.partial(checkReadyState,
    -                               goog.fs.FileReader.ReadyState.LOADING)).
    -      addCallback(goog.partial(checkResult, undefined)).
    -      addCallback(goog.partial(waitForEvent,
    -                               goog.fs.FileReader.EventType.LOAD_START)).
    -      addCallback(goog.partial(checkResult, undefined)).
    -      addCallback(goog.partial(waitForEvent,
    -                               goog.fs.FileReader.EventType.LOAD)).
    -      addCallback(goog.partial(checkResult, undefined)).
    -      addCallback(goog.partial(waitForEvent,
    -                               goog.fs.FileReader.EventType.LOAD_END)).
    -      addCallback(goog.partial(checkResult, file.toDataUrl())).
    -      addCallback(goog.partial(checkReadyState,
    -                               goog.fs.FileReader.ReadyState.DONE)).
    -      addBoth(continueTesting);
    -  waitForAsync('testReadAsDataUrl');
    -}
    -
    -function testAbort() {
    -  deferredReader.
    -      addCallback(goog.partial(readAsText)).
    -      addCallback(function(reader) { reader.abort(); }).
    -      addCallback(goog.partial(checkReadyState,
    -                               goog.fs.FileReader.ReadyState.LOADING)).
    -      addCallback(goog.partial(waitForError, goog.fs.Error.ErrorCode.ABORT)).
    -      addCallback(goog.partial(checkReadyState,
    -                               goog.fs.FileReader.ReadyState.LOADING)).
    -      addCallback(goog.partial(waitForEvent,
    -                               goog.fs.FileReader.EventType.ABORT)).
    -      addCallback(goog.partial(checkReadyState,
    -                               goog.fs.FileReader.ReadyState.LOADING)).
    -      addCallback(goog.partial(waitForEvent,
    -                               goog.fs.FileReader.EventType.LOAD_END)).
    -      addCallback(goog.partial(checkReadyState,
    -                               goog.fs.FileReader.ReadyState.DONE)).
    -      addCallback(goog.partial(checkResult, undefined)).
    -      addBoth(continueTesting);
    -  waitForAsync('testAbort');
    -}
    -
    -function testAbortBeforeRead() {
    -  deferredReader.
    -      addCallback(function(reader) { reader.abort(); }).
    -      addErrback(function(err) {
    -        assertEquals(goog.fs.Error.ErrorCode.INVALID_STATE, err.code);
    -        return true;
    -      }).
    -      addCallback(function(calledErrback) {
    -        assertTrue(calledErrback);
    -      }).
    -      addBoth(continueTesting);
    -  waitForAsync('testAbortBeforeRead');
    -}
    -
    -function testReadDuringRead() {
    -  deferredReader.
    -      addCallback(goog.partial(readAsText)).
    -      addCallback(goog.partial(readAsText)).
    -      addErrback(function(err) {
    -        assertEquals(goog.fs.Error.ErrorCode.INVALID_STATE, err.code);
    -        return true;
    -      }).
    -      addCallback(assertTrue).
    -      addBoth(continueTesting);
    -  waitForAsync('testReadDuringRead');
    -}
    -
    -function continueTesting(result) {
    -  asyncTestCase.continueTesting();
    -  if (result instanceof Error) {
    -    throw result;
    -  }
    -}
    -
    -function waitForAsync(msg) {
    -  asyncTestCase.waitForAsync(msg);
    -}
    -
    -function waitForEvent(type, target) {
    -  var d = new goog.async.Deferred();
    -  goog.events.listenOnce(target, type, goog.bind(d.callback, d, target));
    -  return d;
    -}
    -
    -function waitForError(type, target) {
    -  var d = new goog.async.Deferred();
    -  goog.events.listenOnce(
    -      target, goog.fs.FileReader.EventType.ERROR, function(e) {
    -        assertEquals(type, target.getError().code);
    -        d.callback(target);
    -      });
    -  return d;
    -}
    -
    -function readAsText(reader) {
    -  reader.readAsText(file);
    -}
    -
    -function readAsArrayBuffer(reader) {
    -  reader.readAsArrayBuffer(file);
    -}
    -
    -function readAsDataUrl(reader) {
    -  reader.readAsDataUrl(file);
    -}
    -
    -function readAndWait(reader) {
    -  readAsText(reader);
    -  return waitForEvent(goog.fs.FileSaver.EventType.LOAD_END, reader);
    -}
    -
    -function checkResult(expectedResult, reader) {
    -  checkEquals(expectedResult, reader.getResult());
    -}
    -
    -function checkEquals(a, b) {
    -  if (hasArrayBuffer &&
    -      a instanceof ArrayBuffer && b instanceof ArrayBuffer) {
    -    assertEquals(a.byteLength, b.byteLength);
    -    var viewA = new Uint8Array(a);
    -    var viewB = new Uint8Array(b);
    -    for (var i = 0; i < a.byteLength; i++) {
    -      assertEquals(viewA[i], viewB[i]);
    -    }
    -  } else {
    -    assertEquals(a, b);
    -  }
    -}
    -
    -function checkReadyState(expectedState, reader) {
    -  assertEquals(expectedState, reader.getReadyState());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/fs/filesystem.js b/src/database/third_party/closure-library/closure/goog/testing/fs/filesystem.js
    deleted file mode 100644
    index f094cc13067..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/fs/filesystem.js
    +++ /dev/null
    @@ -1,64 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Mock filesystem object.
    - *
    - */
    -
    -goog.provide('goog.testing.fs.FileSystem');
    -
    -goog.require('goog.fs.FileSystem');
    -goog.require('goog.testing.fs.DirectoryEntry');
    -
    -
    -
    -/**
    - * A mock filesystem object.
    - *
    - * @param {string=} opt_name The name of the filesystem.
    - * @constructor
    - * @implements {goog.fs.FileSystem}
    - * @final
    - */
    -goog.testing.fs.FileSystem = function(opt_name) {
    -  /**
    -   * The name of the filesystem.
    -   * @type {string}
    -   * @private
    -   */
    -  this.name_ = opt_name || 'goog.testing.fs.FileSystem';
    -
    -  /**
    -   * The root entry of the filesystem.
    -   * @type {!goog.testing.fs.DirectoryEntry}
    -   * @private
    -   */
    -  this.root_ = new goog.testing.fs.DirectoryEntry(this, null, '', {});
    -};
    -
    -
    -/** @override */
    -goog.testing.fs.FileSystem.prototype.getName = function() {
    -  return this.name_;
    -};
    -
    -
    -/**
    - * @override
    - * @return {!goog.testing.fs.DirectoryEntry}
    - */
    -goog.testing.fs.FileSystem.prototype.getRoot = function() {
    -  return this.root_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/fs/filewriter.js b/src/database/third_party/closure-library/closure/goog/testing/fs/filewriter.js
    deleted file mode 100644
    index aad8a62e890..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/fs/filewriter.js
    +++ /dev/null
    @@ -1,268 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Mock FileWriter object.
    - *
    - */
    -
    -goog.provide('goog.testing.fs.FileWriter');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.fs.Error');
    -goog.require('goog.fs.FileSaver');
    -goog.require('goog.string');
    -goog.require('goog.testing.fs.ProgressEvent');
    -
    -
    -
    -/**
    - * A mock FileWriter object. This emits the same events as
    - * {@link goog.fs.FileSaver} and {@link goog.fs.FileWriter}.
    - *
    - * @param {!goog.testing.fs.FileEntry} fileEntry The file entry to write to.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - * @final
    - */
    -goog.testing.fs.FileWriter = function(fileEntry) {
    -  goog.testing.fs.FileWriter.base(this, 'constructor');
    -
    -  /**
    -   * The file entry to which to write.
    -   * @type {!goog.testing.fs.FileEntry}
    -   * @private
    -   */
    -  this.fileEntry_ = fileEntry;
    -
    -  /**
    -   * The file blob to write to.
    -   * @type {!goog.testing.fs.File}
    -   * @private
    -   */
    -  this.file_ = fileEntry.fileSync();
    -
    -  /**
    -   * The current state of the writer.
    -   * @type {goog.fs.FileSaver.ReadyState}
    -   * @private
    -   */
    -  this.readyState_ = goog.fs.FileSaver.ReadyState.INIT;
    -};
    -goog.inherits(goog.testing.fs.FileWriter, goog.events.EventTarget);
    -
    -
    -/**
    - * The most recent error experienced by this writer.
    - * @type {goog.fs.Error}
    - * @private
    - */
    -goog.testing.fs.FileWriter.prototype.error_;
    -
    -
    -/**
    - * Whether the current operation has been aborted.
    - * @type {boolean}
    - * @private
    - */
    -goog.testing.fs.FileWriter.prototype.aborted_ = false;
    -
    -
    -/**
    - * The current position in the file.
    - * @type {number}
    - * @private
    - */
    -goog.testing.fs.FileWriter.prototype.position_ = 0;
    -
    -
    -/**
    - * @see {goog.fs.FileSaver#getReadyState}
    - * @return {goog.fs.FileSaver.ReadyState} The ready state.
    - */
    -goog.testing.fs.FileWriter.prototype.getReadyState = function() {
    -  return this.readyState_;
    -};
    -
    -
    -/**
    - * @see {goog.fs.FileSaver#getError}
    - * @return {goog.fs.Error} The error.
    - */
    -goog.testing.fs.FileWriter.prototype.getError = function() {
    -  return this.error_;
    -};
    -
    -
    -/**
    - * @see {goog.fs.FileWriter#getPosition}
    - * @return {number} The position.
    - */
    -goog.testing.fs.FileWriter.prototype.getPosition = function() {
    -  return this.position_;
    -};
    -
    -
    -/**
    - * @see {goog.fs.FileWriter#getLength}
    - * @return {number} The length.
    - */
    -goog.testing.fs.FileWriter.prototype.getLength = function() {
    -  return this.file_.size;
    -};
    -
    -
    -/**
    - * @see {goog.fs.FileSaver#abort}
    - */
    -goog.testing.fs.FileWriter.prototype.abort = function() {
    -  if (this.readyState_ != goog.fs.FileSaver.ReadyState.WRITING) {
    -    var msg = 'aborting save of ' + this.fileEntry_.getFullPath();
    -    throw new goog.fs.Error(
    -        /** @type {!FileError} */ ({'name': 'InvalidStateError'}),
    -        msg);
    -  }
    -
    -  this.aborted_ = true;
    -};
    -
    -
    -/**
    - * @see {goog.fs.FileWriter#write}
    - * @param {!goog.testing.fs.Blob} blob The blob to write.
    - */
    -goog.testing.fs.FileWriter.prototype.write = function(blob) {
    -  if (this.readyState_ == goog.fs.FileSaver.ReadyState.WRITING) {
    -    var msg = 'writing to ' + this.fileEntry_.getFullPath();
    -    throw new goog.fs.Error(
    -        /** @type {!FileError} */ ({'name': 'InvalidStateError'}),
    -        msg);
    -  }
    -
    -  this.readyState_ = goog.fs.FileSaver.ReadyState.WRITING;
    -  goog.Timer.callOnce(function() {
    -    if (this.aborted_) {
    -      this.abort_(blob.size);
    -      return;
    -    }
    -
    -    this.progressEvent_(goog.fs.FileSaver.EventType.WRITE_START, 0, blob.size);
    -    var fileString = this.file_.toString();
    -    this.file_.setDataInternal(
    -        fileString.substring(0, this.position_) + blob.toString() +
    -        fileString.substring(this.position_ + blob.size, fileString.length));
    -    this.position_ += blob.size;
    -
    -    this.progressEvent_(
    -        goog.fs.FileSaver.EventType.WRITE, blob.size, blob.size);
    -    this.readyState_ = goog.fs.FileSaver.ReadyState.DONE;
    -    this.progressEvent_(
    -        goog.fs.FileSaver.EventType.WRITE_END, blob.size, blob.size);
    -  }, 0, this);
    -};
    -
    -
    -/**
    - * @see {goog.fs.FileWriter#truncate}
    - * @param {number} size The size to truncate to.
    - */
    -goog.testing.fs.FileWriter.prototype.truncate = function(size) {
    -  if (this.readyState_ == goog.fs.FileSaver.ReadyState.WRITING) {
    -    var msg = 'truncating ' + this.fileEntry_.getFullPath();
    -    throw new goog.fs.Error(
    -        /** @type {!FileError} */ ({'name': 'InvalidStateError'}),
    -        msg);
    -  }
    -
    -  this.readyState_ = goog.fs.FileSaver.ReadyState.WRITING;
    -  goog.Timer.callOnce(function() {
    -    if (this.aborted_) {
    -      this.abort_(size);
    -      return;
    -    }
    -
    -    this.progressEvent_(goog.fs.FileSaver.EventType.WRITE_START, 0, size);
    -
    -    var fileString = this.file_.toString();
    -    if (size > fileString.length) {
    -      this.file_.setDataInternal(
    -          fileString + goog.string.repeat('\0', size - fileString.length));
    -    } else {
    -      this.file_.setDataInternal(fileString.substring(0, size));
    -    }
    -    this.position_ = Math.min(this.position_, size);
    -
    -    this.progressEvent_(goog.fs.FileSaver.EventType.WRITE, size, size);
    -    this.readyState_ = goog.fs.FileSaver.ReadyState.DONE;
    -    this.progressEvent_(goog.fs.FileSaver.EventType.WRITE_END, size, size);
    -  }, 0, this);
    -};
    -
    -
    -/**
    - * @see {goog.fs.FileWriter#seek}
    - * @param {number} offset The offset to seek to.
    - */
    -goog.testing.fs.FileWriter.prototype.seek = function(offset) {
    -  if (this.readyState_ == goog.fs.FileSaver.ReadyState.WRITING) {
    -    var msg = 'truncating ' + this.fileEntry_.getFullPath();
    -    throw new goog.fs.Error(
    -        /** @type {!FileError} */ ({name: 'InvalidStateError'}),
    -        msg);
    -  }
    -
    -  if (offset < 0) {
    -    this.position_ = Math.max(0, this.file_.size + offset);
    -  } else {
    -    this.position_ = Math.min(offset, this.file_.size);
    -  }
    -};
    -
    -
    -/**
    - * Abort the current action and emit appropriate events.
    - *
    - * @param {number} total The total data that was to be processed, in bytes.
    - * @private
    - */
    -goog.testing.fs.FileWriter.prototype.abort_ = function(total) {
    -  this.error_ = new goog.fs.Error(
    -      /** @type {!FileError} */ ({'name': 'AbortError'}),
    -      'saving ' + this.fileEntry_.getFullPath());
    -  this.progressEvent_(goog.fs.FileSaver.EventType.ERROR, 0, total);
    -  this.progressEvent_(goog.fs.FileSaver.EventType.ABORT, 0, total);
    -  this.readyState_ = goog.fs.FileSaver.ReadyState.DONE;
    -  this.progressEvent_(goog.fs.FileSaver.EventType.WRITE_END, 0, total);
    -  this.aborted_ = false;
    -};
    -
    -
    -/**
    - * Dispatch a progress event.
    - *
    - * @param {goog.fs.FileSaver.EventType} type The type of the event.
    - * @param {number} loaded The number of bytes processed.
    - * @param {number} total The total data that was to be processed, in bytes.
    - * @private
    - */
    -goog.testing.fs.FileWriter.prototype.progressEvent_ = function(
    -    type, loaded, total) {
    -  // On write, update the last modified date to the current (real or mock) time.
    -  if (type == goog.fs.FileSaver.EventType.WRITE) {
    -    this.file_.lastModifiedDate = new Date(goog.now());
    -  }
    -
    -  this.dispatchEvent(new goog.testing.fs.ProgressEvent(type, loaded, total));
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/fs/filewriter_test.html b/src/database/third_party/closure-library/closure/goog/testing/fs/filewriter_test.html
    deleted file mode 100644
    index 6aaf582a8ca..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/fs/filewriter_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.testing.fs.FileWriter
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.fs.FileWriterTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/fs/filewriter_test.js b/src/database/third_party/closure-library/closure/goog/testing/fs/filewriter_test.js
    deleted file mode 100644
    index 143fac94fc9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/fs/filewriter_test.js
    +++ /dev/null
    @@ -1,322 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.fs.FileWriterTest');
    -goog.setTestOnly('goog.testing.fs.FileWriterTest');
    -
    -goog.require('goog.async.Deferred');
    -goog.require('goog.events');
    -goog.require('goog.fs.Error');
    -goog.require('goog.fs.FileSaver');
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.fs.Blob');
    -goog.require('goog.testing.fs.FileSystem');
    -goog.require('goog.testing.jsunit');
    -
    -var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall();
    -var file, deferredWriter, mockClock;
    -
    -function setUp() {
    -  mockClock = new goog.testing.MockClock(true);
    -
    -  var fs = new goog.testing.fs.FileSystem();
    -  var fileEntry = fs.getRoot().createDirectorySync('foo').createFileSync('bar');
    -
    -  deferredWriter = fileEntry.createWriter();
    -  file = fileEntry.fileSync();
    -  file.setDataInternal('');
    -}
    -
    -function tearDown() {
    -  mockClock.uninstall();
    -}
    -
    -function testWrite() {
    -  deferredWriter.
    -      addCallback(goog.partial(checkReadyState,
    -                               goog.fs.FileSaver.ReadyState.INIT)).
    -      addCallback(goog.partial(checkPositionAndLength, 0, 0)).
    -      addCallback(goog.partial(checkLastModified, 0)).
    -      addCallback(goog.partial(tick, 3)).
    -      addCallback(goog.partial(writeString, 'hello')).
    -      addCallback(goog.partial(checkPositionAndLength, 0, 0)).
    -      addCallback(goog.partial(checkReadyState,
    -                               goog.fs.FileSaver.ReadyState.WRITING)).
    -      addCallback(goog.partial(checkLastModified, 0)).
    -      addCallback(goog.partial(waitForEvent,
    -                               goog.fs.FileSaver.EventType.WRITE_START)).
    -      addCallback(goog.partial(checkLastModified, 0)).
    -      addCallback(goog.partial(checkPositionAndLength, 0, 0)).
    -      addCallback(goog.partial(waitForEvent,
    -                               goog.fs.FileSaver.EventType.WRITE)).
    -      addCallback(function() { assertEquals('hello', file.toString()); }).
    -      addCallback(goog.partial(checkPositionAndLength, 5, 5)).
    -      addCallback(goog.partial(checkLastModified, 3)).
    -      addCallback(tick).
    -      addCallback(goog.partial(checkReadyState,
    -                               goog.fs.FileSaver.ReadyState.WRITING)).
    -      addCallback(goog.partial(checkLastModified, 3)).
    -      addCallback(goog.partial(waitForEvent,
    -                               goog.fs.FileSaver.EventType.WRITE_END)).
    -      addCallback(goog.partial(checkLastModified, 3)).
    -      addCallback(goog.partial(checkReadyState,
    -                               goog.fs.FileSaver.ReadyState.DONE)).
    -      addCallback(goog.partial(checkLastModified, 3)).
    -      addCallback(goog.partial(writeString, ' world')).
    -      addCallback(goog.partial(checkPositionAndLength, 5, 5)).
    -      addCallback(goog.partial(waitForEvent,
    -                               goog.fs.FileSaver.EventType.WRITE)).
    -      addCallback(function() { assertEquals('hello world', file.toString()); }).
    -      addCallback(goog.partial(checkPositionAndLength, 11, 11)).
    -      addCallback(goog.partial(checkLastModified, 4)).
    -      addBoth(continueTesting);
    -  waitForAsync('testWrite');
    -}
    -
    -function testSeek() {
    -  deferredWriter.
    -      addCallback(goog.partial(tick, 17)).
    -      addCallback(goog.partial(writeAndWait, 'hello world')).
    -      addCallback(tick).
    -      addCallback(goog.partial(checkPositionAndLength, 11, 11)).
    -
    -      addCallback(function(writer) { writer.seek(6); }).
    -      addCallback(goog.partial(checkPositionAndLength, 6, 11)).
    -      addCallback(goog.partial(checkLastModified, 17)).
    -      addCallback(goog.partial(writeAndWait, 'universe')).
    -      addCallback(tick).
    -      addCallback(function() {
    -        assertEquals('hello universe', file.toString());
    -      }).
    -      addCallback(goog.partial(checkPositionAndLength, 14, 14)).
    -
    -      addCallback(function(writer) { writer.seek(500); }).
    -      addCallback(goog.partial(checkPositionAndLength, 14, 14)).
    -      addCallback(goog.partial(writeAndWait, '!')).
    -      addCallback(tick).
    -      addCallback(function() {
    -        assertEquals('hello universe!', file.toString());
    -      }).
    -      addCallback(goog.partial(checkPositionAndLength, 15, 15)).
    -
    -      addCallback(function(writer) { writer.seek(-9); }).
    -      addCallback(goog.partial(checkPositionAndLength, 6, 15)).
    -      addCallback(goog.partial(writeAndWait, 'foo')).
    -      addCallback(tick).
    -      addCallback(function() {
    -        assertEquals('hello fooverse!', file.toString());
    -      }).
    -      addCallback(goog.partial(checkPositionAndLength, 9, 15)).
    -
    -      addCallback(function(writer) { writer.seek(-500); }).
    -      addCallback(goog.partial(checkPositionAndLength, 0, 15)).
    -      addCallback(goog.partial(writeAndWait, 'bye-o')).
    -      addCallback(tick).
    -      addCallback(function() {
    -        assertEquals('bye-o fooverse!', file.toString());
    -      }).
    -      addCallback(goog.partial(checkPositionAndLength, 5, 15)).
    -      addCallback(goog.partial(checkLastModified, 21)).
    -      addBoth(continueTesting);
    -  waitForAsync('testSeek');
    -}
    -
    -function testAbort() {
    -  deferredWriter.
    -      addCallback(goog.partial(tick, 13)).
    -      addCallback(goog.partial(writeString, 'hello world')).
    -      addCallback(function(writer) { writer.abort(); }).
    -      addCallback(goog.partial(checkReadyState,
    -                               goog.fs.FileSaver.ReadyState.WRITING)).
    -      addCallback(goog.partial(waitForError, goog.fs.Error.ErrorCode.ABORT)).
    -      addCallback(goog.partial(checkReadyState,
    -                               goog.fs.FileSaver.ReadyState.WRITING)).
    -      addCallback(goog.partial(waitForEvent,
    -                               goog.fs.FileSaver.EventType.ABORT)).
    -      addCallback(goog.partial(checkReadyState,
    -                               goog.fs.FileSaver.ReadyState.WRITING)).
    -      addCallback(goog.partial(waitForEvent,
    -                               goog.fs.FileSaver.EventType.WRITE_END)).
    -      addCallback(goog.partial(checkReadyState,
    -                               goog.fs.FileSaver.ReadyState.DONE)).
    -      addCallback(goog.partial(checkPositionAndLength, 0, 0)).
    -      addCallback(goog.partial(checkLastModified, 0)).
    -      addCallback(function() { assertEquals('', file.toString()); }).
    -      addBoth(continueTesting);
    -  waitForAsync('testAbort');
    -}
    -
    -function testTruncate() {
    -  deferredWriter.
    -      addCallback(goog.partial(writeAndWait, 'hello world')).
    -      addCallback(goog.partial(checkPositionAndLength, 11, 11)).
    -      addCallback(function(writer) { writer.truncate(5); }).
    -      addCallback(goog.partial(checkPositionAndLength, 11, 11)).
    -      addCallback(goog.partial(checkReadyState,
    -                               goog.fs.FileSaver.ReadyState.WRITING)).
    -      addCallback(goog.partial(waitForEvent,
    -                               goog.fs.FileSaver.EventType.WRITE_START)).
    -      addCallback(goog.partial(tick, 7)).
    -      addCallback(goog.partial(checkPositionAndLength, 11, 11)).
    -      addCallback(goog.partial(checkLastModified, 0)).
    -      addCallback(goog.partial(waitForEvent,
    -                               goog.fs.FileSaver.EventType.WRITE)).
    -      addCallback(goog.partial(checkLastModified, 7)).
    -      addCallback(tick).
    -      addCallback(goog.partial(checkReadyState,
    -                               goog.fs.FileSaver.ReadyState.WRITING)).
    -      addCallback(goog.partial(checkPositionAndLength, 5, 5)).
    -      addCallback(function() { assertEquals('hello', file.toString()); }).
    -      addCallback(goog.partial(waitForEvent,
    -                               goog.fs.FileSaver.EventType.WRITE_END)).
    -      addCallback(goog.partial(checkReadyState,
    -                               goog.fs.FileSaver.ReadyState.DONE)).
    -
    -      addCallback(function(writer) { writer.truncate(10); }).
    -      addCallback(goog.partial(waitForEvent,
    -                               goog.fs.FileSaver.EventType.WRITE_END)).
    -      addCallback(goog.partial(checkPositionAndLength, 5, 10)).
    -      addCallback(goog.partial(checkLastModified, 8)).
    -      addCallback(function() {
    -        assertEquals('hello\0\0\0\0\0', file.toString());
    -      }).
    -      addBoth(continueTesting);
    -  waitForAsync('testTruncate');
    -}
    -
    -function testAbortBeforeWrite() {
    -  deferredWriter.
    -      addCallback(function(writer) { writer.abort(); }).
    -      addErrback(function(err) {
    -        assertEquals(goog.fs.Error.ErrorCode.INVALID_STATE, err.code);
    -        return true;
    -      }).
    -      addCallback(function(calledErrback) {
    -        assertTrue(calledErrback);
    -      }).
    -      addBoth(continueTesting);
    -  waitForAsync('testAbortBeforeWrite');
    -}
    -
    -function testAbortAfterWrite() {
    -  deferredWriter.
    -      addCallback(goog.partial(writeAndWait, 'hello world')).
    -      addCallback(function(writer) { writer.abort(); }).
    -      addErrback(function(err) {
    -        assertEquals(goog.fs.Error.ErrorCode.INVALID_STATE, err.code);
    -        return true;
    -      }).
    -      addCallback(assertTrue).
    -      addBoth(continueTesting);
    -  waitForAsync('testAbortAfterWrite');
    -}
    -
    -function testWriteDuringWrite() {
    -  deferredWriter.
    -      addCallback(goog.partial(writeString, 'hello world')).
    -      addCallback(goog.partial(writeString, 'hello world')).
    -      addErrback(function(err) {
    -        assertEquals(goog.fs.Error.ErrorCode.INVALID_STATE, err.code);
    -        return true;
    -      }).
    -      addCallback(assertTrue).
    -      addBoth(continueTesting);
    -  waitForAsync('testWriteDuringWrite');
    -}
    -
    -function testSeekDuringWrite() {
    -  deferredWriter.
    -      addCallback(goog.partial(writeString, 'hello world')).
    -      addCallback(function(writer) { writer.seek(5); }).
    -      addErrback(function(err) {
    -        assertEquals(goog.fs.Error.ErrorCode.INVALID_STATE, err.code);
    -        return true;
    -      }).
    -      addCallback(assertTrue).
    -      addBoth(continueTesting);
    -  waitForAsync('testSeekDuringWrite');
    -}
    -
    -function testTruncateDuringWrite() {
    -  deferredWriter.
    -      addCallback(goog.partial(writeString, 'hello world')).
    -      addCallback(function(writer) { writer.truncate(5); }).
    -      addErrback(function(err) {
    -        assertEquals(goog.fs.Error.ErrorCode.INVALID_STATE, err.code);
    -        return true;
    -      }).
    -      addCallback(assertTrue).
    -      addBoth(continueTesting);
    -  waitForAsync('testTruncateDuringWrite');
    -}
    -
    -
    -function tick(opt_tickCount) {
    -  mockClock.tick(opt_tickCount);
    -}
    -
    -function continueTesting(result) {
    -  asyncTestCase.continueTesting();
    -  if (result instanceof Error) {
    -    throw result;
    -  }
    -  mockClock.tick();
    -}
    -
    -function waitForAsync(msg) {
    -  asyncTestCase.waitForAsync(msg);
    -
    -  // The mock clock must be advanced far enough that all timeouts added during
    -  // callbacks will be triggered. 1000ms is much more than enough.
    -  mockClock.tick(1000);
    -}
    -
    -function waitForEvent(type, target) {
    -  var d = new goog.async.Deferred();
    -  goog.events.listenOnce(target, type, goog.bind(d.callback, d, target));
    -  return d;
    -}
    -
    -function waitForError(type, target) {
    -  var d = new goog.async.Deferred();
    -  goog.events.listenOnce(
    -      target, goog.fs.FileSaver.EventType.ERROR, function(e) {
    -        assertEquals(type, target.getError().code);
    -        d.callback(target);
    -      });
    -  return d;
    -}
    -
    -function checkReadyState(expectedState, writer) {
    -  assertEquals(expectedState, writer.getReadyState());
    -}
    -
    -function checkPositionAndLength(expectedPosition, expectedLength, writer) {
    -  assertEquals(expectedPosition, writer.getPosition());
    -  assertEquals(expectedLength, writer.getLength());
    -}
    -
    -function checkLastModified(expectedTime) {
    -  assertEquals(expectedTime, file.lastModifiedDate.getTime());
    -}
    -
    -function writeString(str, writer) {
    -  writer.write(new goog.testing.fs.Blob(str));
    -}
    -
    -function writeAndWait(str, writer) {
    -  writeString(str, writer);
    -  return waitForEvent(goog.fs.FileSaver.EventType.WRITE_END, writer);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/fs/fs.js b/src/database/third_party/closure-library/closure/goog/testing/fs/fs.js
    deleted file mode 100644
    index 73121afe3aa..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/fs/fs.js
    +++ /dev/null
    @@ -1,169 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Mock implementations of the Closure HTML5 FileSystem wrapper
    - * classes. These implementations are designed to be usable in any browser, so
    - * they use none of the native FileSystem-related objects.
    - *
    - */
    -
    -goog.provide('goog.testing.fs');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.array');
    -goog.require('goog.async.Deferred');
    -/** @suppress {extraRequire} */
    -goog.require('goog.fs');
    -goog.require('goog.testing.fs.Blob');
    -goog.require('goog.testing.fs.FileSystem');
    -
    -
    -/**
    - * Get a filesystem object. Since these are mocks, there's no difference between
    - * temporary and persistent filesystems.
    - *
    - * @param {number} size Ignored.
    - * @return {!goog.async.Deferred} The deferred
    - *     {@link goog.testing.fs.FileSystem}.
    - */
    -goog.testing.fs.getTemporary = function(size) {
    -  var d = new goog.async.Deferred();
    -  goog.Timer.callOnce(
    -      goog.bind(d.callback, d, new goog.testing.fs.FileSystem()));
    -  return d;
    -};
    -
    -
    -/**
    - * Get a filesystem object. Since these are mocks, there's no difference between
    - * temporary and persistent filesystems.
    - *
    - * @param {number} size Ignored.
    - * @return {!goog.async.Deferred} The deferred
    - *     {@link goog.testing.fs.FileSystem}.
    - */
    -goog.testing.fs.getPersistent = function(size) {
    -  return goog.testing.fs.getTemporary(size);
    -};
    -
    -
    -/**
    - * Which object URLs have been granted for fake blobs.
    - * @type {!Object<boolean>}
    - * @private
    - */
    -goog.testing.fs.objectUrls_ = {};
    -
    -
    -/**
    - * Create a fake object URL for a given fake blob. This can be used as a real
    - * URL, and it can be created and revoked normally.
    - *
    - * @param {!goog.testing.fs.Blob} blob The blob for which to create the URL.
    - * @return {string} The URL.
    - */
    -goog.testing.fs.createObjectUrl = function(blob) {
    -  var url = blob.toDataUrl();
    -  goog.testing.fs.objectUrls_[url] = true;
    -  return url;
    -};
    -
    -
    -/**
    - * Remove a URL that was created for a fake blob.
    - *
    - * @param {string} url The URL to revoke.
    - */
    -goog.testing.fs.revokeObjectUrl = function(url) {
    -  delete goog.testing.fs.objectUrls_[url];
    -};
    -
    -
    -/**
    - * Return whether or not a URL has been granted for the given blob.
    - *
    - * @param {!goog.testing.fs.Blob} blob The blob to check.
    - * @return {boolean} Whether a URL has been granted.
    - */
    -goog.testing.fs.isObjectUrlGranted = function(blob) {
    -  return (blob.toDataUrl()) in goog.testing.fs.objectUrls_;
    -};
    -
    -
    -/**
    - * Concatenates one or more values together and converts them to a fake blob.
    - *
    - * @param {...(string|!goog.testing.fs.Blob)} var_args The values that will make
    - *     up the resulting blob.
    - * @return {!goog.testing.fs.Blob} The blob.
    - */
    -goog.testing.fs.getBlob = function(var_args) {
    -  return new goog.testing.fs.Blob(goog.array.map(arguments, String).join(''));
    -};
    -
    -
    -/**
    - * Creates a blob with the given properties.
    - * See https://developer.mozilla.org/en-US/docs/Web/API/Blob for more details.
    - *
    - * @param {Array<string|!goog.testing.fs.Blob>} parts
    - *     The values that will make up the resulting blob.
    - * @param {string=} opt_type The MIME type of the Blob.
    - * @param {string=} opt_endings Specifies how strings containing newlines are to
    - *     be written out.
    - * @return {!goog.testing.fs.Blob} The blob.
    - */
    -goog.testing.fs.getBlobWithProperties = function(parts, opt_type, opt_endings) {
    -  return new goog.testing.fs.Blob(goog.array.map(parts, String).join(''),
    -      opt_type);
    -};
    -
    -
    -/**
    - * Returns the string value of a fake blob.
    - *
    - * @param {!goog.testing.fs.Blob} blob The blob to convert to a string.
    - * @param {string=} opt_encoding Ignored.
    - * @return {!goog.async.Deferred} The deferred string value of the blob.
    - */
    -goog.testing.fs.blobToString = function(blob, opt_encoding) {
    -  var d = new goog.async.Deferred();
    -  goog.Timer.callOnce(goog.bind(d.callback, d, blob.toString()));
    -  return d;
    -};
    -
    -
    -/**
    - * Installs goog.testing.fs in place of the standard goog.fs. After calling
    - * this, code that uses goog.fs should work without issue using goog.testing.fs.
    - *
    - * @param {!goog.testing.PropertyReplacer} stubs The property replacer for
    - *     stubbing out the original goog.fs functions.
    - */
    -goog.testing.fs.install = function(stubs) {
    -  // Prevent warnings that goog.fs may get optimized away. It's true this is
    -  // unsafe in compiled code, but it's only meant for tests.
    -  var fs = goog.getObjectByName('goog.fs');
    -  stubs.replace(fs, 'getTemporary', goog.testing.fs.getTemporary);
    -  stubs.replace(fs, 'getPersistent', goog.testing.fs.getPersistent);
    -  stubs.replace(fs, 'createObjectUrl', goog.testing.fs.createObjectUrl);
    -  stubs.replace(fs, 'revokeObjectUrl', goog.testing.fs.revokeObjectUrl);
    -  stubs.replace(fs, 'getBlob', goog.testing.fs.getBlob);
    -  stubs.replace(fs, 'getBlobWithProperties',
    -      goog.testing.fs.getBlobWithProperties);
    -  stubs.replace(fs, 'blobToString', goog.testing.fs.blobToString);
    -  stubs.replace(fs, 'browserSupportsObjectUrls',
    -      function() { return true; });
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/fs/fs_test.html b/src/database/third_party/closure-library/closure/goog/testing/fs/fs_test.html
    deleted file mode 100644
    index 8143c2e33b2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/fs/fs_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.testing.fs
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.fsTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/fs/fs_test.js b/src/database/third_party/closure-library/closure/goog/testing/fs/fs_test.js
    deleted file mode 100644
    index ef496f01a3f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/fs/fs_test.js
    +++ /dev/null
    @@ -1,55 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.fsTest');
    -goog.setTestOnly('goog.testing.fsTest');
    -
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.fs');
    -goog.require('goog.testing.fs.Blob');
    -goog.require('goog.testing.jsunit');
    -
    -var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall();
    -
    -function testObjectUrls() {
    -  var blob = goog.testing.fs.getBlob('foo');
    -  var url = goog.testing.fs.createObjectUrl(blob);
    -  assertTrue(goog.testing.fs.isObjectUrlGranted(blob));
    -  goog.testing.fs.revokeObjectUrl(url);
    -  assertFalse(goog.testing.fs.isObjectUrlGranted(blob));
    -}
    -
    -function testGetBlob() {
    -  assertEquals(
    -      new goog.testing.fs.Blob('foobarbaz').toString(),
    -      goog.testing.fs.getBlob('foo', 'bar', 'baz').toString());
    -  assertEquals(
    -      new goog.testing.fs.Blob('foobarbaz').toString(),
    -      goog.testing.fs.getBlob('foo', new goog.testing.fs.Blob('bar'), 'baz').
    -      toString());
    -}
    -
    -function testBlobToString() {
    -  goog.testing.fs.blobToString(new goog.testing.fs.Blob('foobarbaz')).
    -      addCallback(goog.partial(assertEquals, 'foobarbaz')).
    -      addCallback(goog.bind(asyncTestCase.continueTesting, asyncTestCase));
    -  asyncTestCase.waitForAsync('testBlobToString');
    -}
    -
    -function testGetBlobWithProperties() {
    -  assertEquals(
    -      'data:spam/eggs;base64,Zm9vYmFy',
    -      new goog.testing.fs.getBlobWithProperties(
    -          ['foo', new goog.testing.fs.Blob('bar')], 'spam/eggs').toDataUrl());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/fs/integration_test.html b/src/database/third_party/closure-library/closure/goog/testing/fs/integration_test.html
    deleted file mode 100644
    index 81cb8b1e246..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/fs/integration_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <title>
    -   Closure Integration Tests - goog.testing.fs
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.fs.integrationTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="closureTestRunnerLog">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/fs/integration_test.js b/src/database/third_party/closure-library/closure/goog/testing/fs/integration_test.js
    deleted file mode 100644
    index a64566f8044..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/fs/integration_test.js
    +++ /dev/null
    @@ -1,221 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.fs.integrationTest');
    -goog.setTestOnly('goog.testing.fs.integrationTest');
    -
    -goog.require('goog.async.Deferred');
    -goog.require('goog.async.DeferredList');
    -goog.require('goog.events');
    -goog.require('goog.fs');
    -goog.require('goog.fs.DirectoryEntry');
    -goog.require('goog.fs.Error');
    -goog.require('goog.fs.FileSaver');
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.fs');
    -goog.require('goog.testing.jsunit');
    -
    -var TEST_DIR = 'goog-fs-test-dir';
    -
    -var deferredFs = goog.testing.fs.getTemporary();
    -var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall();
    -
    -function setUpPage() {
    -  goog.testing.fs.install(new goog.testing.PropertyReplacer());
    -}
    -
    -function tearDown() {
    -  loadTestDir().
    -      addCallback(function(dir) { return dir.removeRecursively(); }).
    -      addBoth(continueTesting);
    -  asyncTestCase.waitForAsync('removing filesystem');
    -}
    -
    -function testWriteFile() {
    -  loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE).
    -      addCallback(goog.partial(writeToFile, 'test content')).
    -      addCallback(goog.partial(checkFileContent, 'test content')).
    -      addBoth(continueTesting);
    -  asyncTestCase.waitForAsync('testWriteFile');
    -}
    -
    -function testRemoveFile() {
    -  loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE).
    -      addCallback(goog.partial(writeToFile, 'test content')).
    -      addCallback(function(fileEntry) { return fileEntry.remove(); }).
    -      addCallback(goog.partial(checkFileRemoved, 'test')).
    -      addBoth(continueTesting);
    -  asyncTestCase.waitForAsync('testRemoveFile');
    -}
    -
    -function testMoveFile() {
    -  var deferredSubdir = loadDirectory(
    -      'subdir', goog.fs.DirectoryEntry.Behavior.CREATE);
    -  var deferredWrittenFile =
    -      loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE).
    -      addCallback(goog.partial(writeToFile, 'test content'));
    -  goog.async.DeferredList.gatherResults([deferredSubdir, deferredWrittenFile]).
    -      addCallback(splitArgs(function(dir, fileEntry) {
    -        return fileEntry.moveTo(dir);
    -      })).
    -      addCallback(goog.partial(checkFileContent, 'test content')).
    -      addCallback(goog.partial(checkFileRemoved, 'test')).
    -      addBoth(continueTesting);
    -  asyncTestCase.waitForAsync('testMoveFile');
    -}
    -
    -function testCopyFile() {
    -  var deferredFile = loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE);
    -  var deferredSubdir = loadDirectory(
    -      'subdir', goog.fs.DirectoryEntry.Behavior.CREATE);
    -  var deferredWrittenFile = deferredFile.branch().
    -      addCallback(goog.partial(writeToFile, 'test content'));
    -  goog.async.DeferredList.gatherResults([deferredSubdir, deferredWrittenFile]).
    -      addCallback(splitArgs(function(dir, fileEntry) {
    -        return fileEntry.copyTo(dir);
    -      })).
    -      addCallback(goog.partial(checkFileContent, 'test content')).
    -      awaitDeferred(deferredFile).
    -      addCallback(goog.partial(checkFileContent, 'test content')).
    -      addBoth(continueTesting);
    -  asyncTestCase.waitForAsync('testCopyFile');
    -}
    -
    -function testAbortWrite() {
    -  var deferredFile = loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE);
    -  deferredFile.branch().
    -      addCallback(goog.partial(startWrite, 'test content')).
    -      addCallback(function(writer) { writer.abort(); }).
    -      addCallback(
    -          goog.partial(waitForEvent, goog.fs.FileSaver.EventType.ABORT)).
    -      awaitDeferred(deferredFile).
    -      addCallback(goog.partial(checkFileContent, '')).
    -      addBoth(continueTesting);
    -  asyncTestCase.waitForAsync('testAbortWrite');
    -}
    -
    -function testSeek() {
    -  var deferredFile = loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE);
    -  deferredFile.branch().
    -      addCallback(goog.partial(writeToFile, 'test content')).
    -      addCallback(function(fileEntry) { return fileEntry.createWriter(); }).
    -      addCallback(
    -          goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.INIT)).
    -      addCallback(function(writer) {
    -        writer.seek(5);
    -        writer.write(goog.fs.getBlob('stuff and things'));
    -      }).
    -      addCallback(
    -          goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.WRITING)).
    -      addCallback(
    -          goog.partial(waitForEvent, goog.fs.FileSaver.EventType.WRITE)).
    -      awaitDeferred(deferredFile).
    -      addCallback(goog.partial(checkFileContent, 'test stuff and things')).
    -      addBoth(continueTesting);
    -  asyncTestCase.waitForAsync('testSeek');
    -}
    -
    -function testTruncate() {
    -  var deferredFile = loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE);
    -  deferredFile.branch().
    -      addCallback(goog.partial(writeToFile, 'test content')).
    -      addCallback(function(fileEntry) { return fileEntry.createWriter(); }).
    -      addCallback(
    -          goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.INIT)).
    -      addCallback(function(writer) { writer.truncate(4); }).
    -      addCallback(
    -          goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.WRITING)).
    -      addCallback(
    -          goog.partial(waitForEvent, goog.fs.FileSaver.EventType.WRITE)).
    -      awaitDeferred(deferredFile).
    -      addCallback(goog.partial(checkFileContent, 'test')).
    -      addBoth(continueTesting);
    -  asyncTestCase.waitForAsync('testTruncate');
    -}
    -
    -
    -function continueTesting(result) {
    -  asyncTestCase.continueTesting();
    -  if (result instanceof Error) {
    -    throw result;
    -  }
    -}
    -
    -function loadTestDir() {
    -  return deferredFs.branch().addCallback(function(fs) {
    -    return fs.getRoot().getDirectory(
    -        TEST_DIR, goog.fs.DirectoryEntry.Behavior.CREATE);
    -  });
    -}
    -
    -function loadFile(filename, behavior) {
    -  return loadTestDir().addCallback(function(dir) {
    -    return dir.getFile(filename, behavior);
    -  });
    -}
    -
    -function loadDirectory(filename, behavior) {
    -  return loadTestDir().addCallback(function(dir) {
    -    return dir.getDirectory(filename, behavior);
    -  });
    -}
    -
    -function startWrite(content, fileEntry) {
    -  return fileEntry.createWriter().
    -      addCallback(
    -          goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.INIT)).
    -      addCallback(function(writer) {
    -        writer.write(goog.fs.getBlob(content));
    -        return writer;
    -      }).
    -      addCallback(
    -          goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.WRITING));
    -}
    -
    -function waitForEvent(type, target) {
    -  var d = new goog.async.Deferred();
    -  goog.events.listenOnce(target, type, d.callback, false, d);
    -  return d;
    -}
    -
    -function writeToFile(content, fileEntry) {
    -  return startWrite(content, fileEntry).
    -      addCallback(
    -          goog.partial(waitForEvent, goog.fs.FileSaver.EventType.WRITE)).
    -      addCallback(function() { return fileEntry; });
    -}
    -
    -function checkFileContent(content, fileEntry) {
    -  return fileEntry.file().
    -      addCallback(function(blob) { return goog.fs.blobToString(blob); }).
    -      addCallback(goog.partial(assertEquals, content));
    -}
    -
    -function checkFileRemoved(filename) {
    -  return loadFile(filename).
    -      addCallback(goog.partial(fail, 'expected file to be removed')).
    -      addErrback(function(err) {
    -        assertEquals(err.code, goog.fs.Error.ErrorCode.NOT_FOUND);
    -        return true; // Go back to callback path
    -      });
    -}
    -
    -function checkReadyState(expectedState, writer) {
    -  assertEquals(expectedState, writer.getReadyState());
    -}
    -
    -function splitArgs(fn) {
    -  return function(args) { return fn(args[0], args[1]); };
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/fs/progressevent.js b/src/database/third_party/closure-library/closure/goog/testing/fs/progressevent.js
    deleted file mode 100644
    index 6ffe16e0187..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/fs/progressevent.js
    +++ /dev/null
    @@ -1,82 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Mock ProgressEvent object.
    - *
    - */
    -
    -goog.provide('goog.testing.fs.ProgressEvent');
    -
    -goog.require('goog.events.Event');
    -
    -
    -
    -/**
    - * A mock progress event.
    - *
    - * @param {!goog.fs.FileSaver.EventType|!goog.fs.FileReader.EventType} type
    - *     Event type.
    - * @param {number} loaded The number of bytes processed.
    - * @param {number} total The total data that was to be processed, in bytes.
    - * @constructor
    - * @extends {goog.events.Event}
    - * @final
    - */
    -goog.testing.fs.ProgressEvent = function(type, loaded, total) {
    -  goog.testing.fs.ProgressEvent.base(this, 'constructor', type);
    -
    -  /**
    -   * The number of bytes processed.
    -   * @type {number}
    -   * @private
    -   */
    -  this.loaded_ = loaded;
    -
    -
    -  /**
    -   * The total data that was to be procesed, in bytes.
    -   * @type {number}
    -   * @private
    -   */
    -  this.total_ = total;
    -};
    -goog.inherits(goog.testing.fs.ProgressEvent, goog.events.Event);
    -
    -
    -/**
    - * @see {goog.fs.ProgressEvent#isLengthComputable}
    - * @return {boolean} True if the length is known.
    - */
    -goog.testing.fs.ProgressEvent.prototype.isLengthComputable = function() {
    -  return true;
    -};
    -
    -
    -/**
    - * @see {goog.fs.ProgressEvent#getLoaded}
    - * @return {number} The number of bytes loaded or written.
    - */
    -goog.testing.fs.ProgressEvent.prototype.getLoaded = function() {
    -  return this.loaded_;
    -};
    -
    -
    -/**
    - * @see {goog.fs.ProgressEvent#getTotal}
    - * @return {number} The total bytes to load or write.
    - */
    -goog.testing.fs.ProgressEvent.prototype.getTotal = function() {
    -  return this.total_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/functionmock.js b/src/database/third_party/closure-library/closure/goog/testing/functionmock.js
    deleted file mode 100644
    index 4de9f2021ad..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/functionmock.js
    +++ /dev/null
    @@ -1,176 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Enable mocking of functions not attached to objects
    - * whether they be global / top-level or anonymous methods / closures.
    - *
    - * See the unit tests for usage.
    - *
    - */
    -
    -goog.provide('goog.testing');
    -goog.provide('goog.testing.FunctionMock');
    -goog.provide('goog.testing.GlobalFunctionMock');
    -goog.provide('goog.testing.MethodMock');
    -
    -goog.require('goog.object');
    -goog.require('goog.testing.LooseMock');
    -goog.require('goog.testing.Mock');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.StrictMock');
    -
    -
    -/**
    - * Class used to mock a function. Useful for mocking closures and anonymous
    - * callbacks etc. Creates a function object that extends goog.testing.Mock.
    - * @param {string=} opt_functionName The optional name of the function to mock.
    - *     Set to '[anonymous mocked function]' if not passed in.
    - * @param {number=} opt_strictness One of goog.testing.Mock.LOOSE or
    - *     goog.testing.Mock.STRICT. The default is STRICT.
    - * @return {!goog.testing.MockInterface} The mocked function.
    - * @suppress {missingProperties} Mocks do not fit in the type system well.
    - */
    -goog.testing.FunctionMock = function(opt_functionName, opt_strictness) {
    -  var fn = function() {
    -    var args = Array.prototype.slice.call(arguments);
    -    args.splice(0, 0, opt_functionName || '[anonymous mocked function]');
    -    return fn.$mockMethod.apply(fn, args);
    -  };
    -  var base = opt_strictness === goog.testing.Mock.LOOSE ?
    -      goog.testing.LooseMock : goog.testing.StrictMock;
    -  goog.object.extend(fn, new base({}));
    -
    -  return /** @type {!goog.testing.MockInterface} */ (fn);
    -};
    -
    -
    -/**
    - * Mocks an existing function. Creates a goog.testing.FunctionMock
    - * and registers it in the given scope with the name specified by functionName.
    - * @param {Object} scope The scope of the method to be mocked out.
    - * @param {string} functionName The name of the function we're going to mock.
    - * @param {number=} opt_strictness One of goog.testing.Mock.LOOSE or
    - *     goog.testing.Mock.STRICT. The default is STRICT.
    - * @return {!goog.testing.MockInterface} The mocked method.
    - */
    -goog.testing.MethodMock = function(scope, functionName, opt_strictness) {
    -  if (!(functionName in scope)) {
    -    throw Error(functionName + ' is not a property of the given scope.');
    -  }
    -
    -  var fn = goog.testing.FunctionMock(functionName, opt_strictness);
    -
    -  fn.$propertyReplacer_ = new goog.testing.PropertyReplacer();
    -  fn.$propertyReplacer_.set(scope, functionName, fn);
    -  fn.$tearDown = goog.testing.MethodMock.$tearDown;
    -
    -  return fn;
    -};
    -
    -
    -/**
    - * Resets the global function that we mocked back to its original state.
    - * @this {goog.testing.MockInterface}
    - */
    -goog.testing.MethodMock.$tearDown = function() {
    -  this.$propertyReplacer_.reset();
    -};
    -
    -
    -/**
    - * Mocks a global / top-level function. Creates a goog.testing.MethodMock
    - * in the global scope with the name specified by functionName.
    - * @param {string} functionName The name of the function we're going to mock.
    - * @param {number=} opt_strictness One of goog.testing.Mock.LOOSE or
    - *     goog.testing.Mock.STRICT. The default is STRICT.
    - * @return {!goog.testing.MockInterface} The mocked global function.
    - */
    -goog.testing.GlobalFunctionMock = function(functionName, opt_strictness) {
    -  return goog.testing.MethodMock(goog.global, functionName, opt_strictness);
    -};
    -
    -
    -/**
    - * Convenience method for creating a mock for a function.
    - * @param {string=} opt_functionName The optional name of the function to mock
    - *     set to '[anonymous mocked function]' if not passed in.
    - * @param {number=} opt_strictness One of goog.testing.Mock.LOOSE or
    - *     goog.testing.Mock.STRICT. The default is STRICT.
    - * @return {goog.testing.MockInterface} The mocked function.
    - */
    -goog.testing.createFunctionMock = function(opt_functionName, opt_strictness) {
    -  return goog.testing.FunctionMock(opt_functionName, opt_strictness);
    -};
    -
    -
    -/**
    - * Convenience method for creating a mock for a method.
    - * @param {Object} scope The scope of the method to be mocked out.
    - * @param {string} functionName The name of the function we're going to mock.
    - * @param {number=} opt_strictness One of goog.testing.Mock.LOOSE or
    - *     goog.testing.Mock.STRICT. The default is STRICT.
    - * @return {!goog.testing.MockInterface} The mocked global function.
    - */
    -goog.testing.createMethodMock = function(scope, functionName, opt_strictness) {
    -  return goog.testing.MethodMock(scope, functionName, opt_strictness);
    -};
    -
    -
    -/**
    - * Convenience method for creating a mock for a constructor. Copies class
    - * members to the mock.
    - *
    - * <p>When mocking a constructor to return a mocked instance, remember to create
    - * the instance mock before mocking the constructor. If you mock the constructor
    - * first, then the mock framework will be unable to examine the prototype chain
    - * when creating the mock instance.
    - * @param {Object} scope The scope of the constructor to be mocked out.
    - * @param {string} constructorName The name of the constructor we're going to
    - *     mock.
    - * @param {number=} opt_strictness One of goog.testing.Mock.LOOSE or
    - *     goog.testing.Mock.STRICT. The default is STRICT.
    - * @return {!goog.testing.MockInterface} The mocked constructor.
    - */
    -goog.testing.createConstructorMock = function(scope, constructorName,
    -                                              opt_strictness) {
    -  var realConstructor = scope[constructorName];
    -  var constructorMock = goog.testing.MethodMock(scope, constructorName,
    -                                                opt_strictness);
    -
    -  // Copy class members from the real constructor to the mock. Do not copy
    -  // the closure superClass_ property (see goog.inherits), the built-in
    -  // prototype property, or properties added to Function.prototype
    -  // (see goog.MODIFY_FUNCTION_PROTOTYPES in closure/base.js).
    -  for (var property in realConstructor) {
    -    if (property != 'superClass_' &&
    -        property != 'prototype' &&
    -        realConstructor.hasOwnProperty(property)) {
    -      constructorMock[property] = realConstructor[property];
    -    }
    -  }
    -  return constructorMock;
    -};
    -
    -
    -/**
    - * Convenience method for creating a mocks for a global / top-level function.
    - * @param {string} functionName The name of the function we're going to mock.
    - * @param {number=} opt_strictness One of goog.testing.Mock.LOOSE or
    - *     goog.testing.Mock.STRICT. The default is STRICT.
    - * @return {!goog.testing.MockInterface} The mocked global function.
    - */
    -goog.testing.createGlobalFunctionMock = function(functionName, opt_strictness) {
    -  return goog.testing.GlobalFunctionMock(functionName, opt_strictness);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/functionmock_test.html b/src/database/third_party/closure-library/closure/goog/testing/functionmock_test.html
    deleted file mode 100644
    index 20fcb1a71fa..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/functionmock_test.html
    +++ /dev/null
    @@ -1,27 +0,0 @@
    -<!DOCTYPE html>
    -<!--
    -
    -  Test mocking global / top-level functions
    -
    --->
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Global Mock Unit Test
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.FunctionMockTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/functionmock_test.js b/src/database/third_party/closure-library/closure/goog/testing/functionmock_test.js
    deleted file mode 100644
    index 9d495c2f09b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/functionmock_test.js
    +++ /dev/null
    @@ -1,503 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.FunctionMockTest');
    -goog.setTestOnly('goog.testing.FunctionMockTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.string');
    -goog.require('goog.testing');
    -goog.require('goog.testing.FunctionMock');
    -goog.require('goog.testing.Mock');
    -goog.require('goog.testing.StrictMock');
    -goog.require('goog.testing.asserts');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.mockmatchers');
    -
    -// Global scope so we can tear it down safely
    -var mockGlobal;
    -
    -function tearDown() {
    -  if (mockGlobal) {
    -    mockGlobal.$tearDown();
    -  }
    -}
    -
    -
    -//----- Tests for goog.testing.FunctionMock
    -
    -function testMockFunctionCallOrdering() {
    -  var doOneTest = function(mockFunction, success, expected_args, actual_args) {
    -    goog.array.forEach(expected_args, function(arg) { mockFunction(arg); });
    -    mockFunction.$replay();
    -    var callFunction = function() {
    -      goog.array.forEach(actual_args, function(arg) { mockFunction(arg); });
    -      mockFunction.$verify();
    -    };
    -    if (success) {
    -      callFunction();
    -    } else {
    -      assertThrows(callFunction);
    -    }
    -  };
    -
    -  var doTest = function(strict_ok, loose_ok, expected_args, actual_args) {
    -    doOneTest(goog.testing.createFunctionMock(), strict_ok,
    -              expected_args, actual_args);
    -    doOneTest(goog.testing.createFunctionMock('name'), strict_ok,
    -              expected_args, actual_args);
    -    doOneTest(goog.testing.createFunctionMock('name', goog.testing.Mock.STRICT),
    -              strict_ok, expected_args, actual_args);
    -    doOneTest(goog.testing.createFunctionMock('name', goog.testing.Mock.LOOSE),
    -              loose_ok, expected_args, actual_args);
    -  };
    -
    -  doTest(true, true, [1, 2], [1, 2]);
    -  doTest(false, true, [1, 2], [2, 1]);
    -  doTest(false, false, [1, 2], [2, 2]);
    -  doTest(false, false, [1, 2], [1]);
    -  doTest(false, false, [1, 2], [1, 1]);
    -  doTest(false, false, [1, 2], [1]);
    -}
    -
    -function testMocksFunctionWithNoArgs() {
    -  var mockFoo = goog.testing.createFunctionMock();
    -  mockFoo();
    -  mockFoo.$replay();
    -  mockFoo();
    -  mockFoo.$verify();
    -}
    -
    -function testMocksFunctionWithOneArg() {
    -  var mockFoo = goog.testing.createFunctionMock();
    -  mockFoo('x');
    -  mockFoo.$replay();
    -  mockFoo('x');
    -  mockFoo.$verify();
    -}
    -
    -function testMocksFunctionWithMultipleArgs() {
    -  var mockFoo = goog.testing.createFunctionMock();
    -  mockFoo('x', 'y');
    -  mockFoo.$replay();
    -  mockFoo('x', 'y');
    -  mockFoo.$verify();
    -}
    -
    -function testFailsIfCalledWithIncorrectArgs() {
    -  var mockFoo = goog.testing.createFunctionMock();
    -
    -  mockFoo();
    -  mockFoo.$replay();
    -  assertThrows(function() {mockFoo('x');});
    -  mockFoo.$reset();
    -
    -  mockFoo('x');
    -  mockFoo.$replay();
    -  assertThrows(function() {mockFoo();});
    -  mockFoo.$reset();
    -
    -  mockFoo('x');
    -  mockFoo.$replay();
    -  assertThrows(function() {mockFoo('x', 'y');});
    -  mockFoo.$reset();
    -
    -  mockFoo('x', 'y');
    -  mockFoo.$replay();
    -  assertThrows(function() {mockFoo('x');});
    -  mockFoo.$reset();
    -
    -  mockFoo('correct');
    -  mockFoo.$replay();
    -  assertThrows(function() {mockFoo('wrong');});
    -  mockFoo.$reset();
    -
    -  mockFoo('correct', 'args');
    -  mockFoo.$replay();
    -  assertThrows(function() {mockFoo('wrong', 'args');});
    -  mockFoo.$reset();
    -}
    -
    -function testMocksFunctionWithReturnValue() {
    -  var mockFoo = goog.testing.createFunctionMock();
    -  mockFoo().$returns('bar');
    -  mockFoo.$replay();
    -  assertEquals('bar', mockFoo());
    -  mockFoo.$verify();
    -}
    -
    -function testFunctionMockWorksWhenPassedAsACallback() {
    -  var invoker = {
    -    register: function(callback) {
    -      this.callback = callback;
    -    },
    -
    -    invoke: function(args) {
    -      return this.callback(args);
    -    }
    -  };
    -
    -  var mockFunction = goog.testing.createFunctionMock();
    -  mockFunction('bar').$returns('baz');
    -
    -  mockFunction.$replay();
    -  invoker.register(mockFunction);
    -  assertEquals('baz', invoker.invoke('bar'));
    -  mockFunction.$verify();
    -}
    -
    -function testFunctionMockQuacksLikeAStrictMock() {
    -  var mockFunction = goog.testing.createFunctionMock();
    -  assertQuacksLike(mockFunction, goog.testing.StrictMock);
    -}
    -
    -
    -//----- Global functions for goog.testing.GlobalFunctionMock to mock
    -
    -function globalFoo() {
    -  return 'I am Spartacus!';
    -}
    -
    -function globalBar(who, what) {
    -  return [who, 'is', what].join(' ');
    -}
    -
    -
    -//----- Tests for goog.testing.createGlobalFunctionMock
    -
    -function testMocksGlobalFunctionWithNoArgs() {
    -  mockGlobal = goog.testing.createGlobalFunctionMock('globalFoo');
    -  mockGlobal().$returns('No, I am Spartacus!');
    -
    -  mockGlobal.$replay();
    -  assertEquals('No, I am Spartacus!', globalFoo());
    -  mockGlobal.$verify();
    -}
    -
    -function testMocksGlobalFunctionUsingGlobalName() {
    -  goog.testing.createGlobalFunctionMock('globalFoo');
    -  globalFoo().$returns('No, I am Spartacus!');
    -
    -  globalFoo.$replay();
    -  assertEquals('No, I am Spartacus!', globalFoo());
    -  globalFoo.$verify();
    -  globalFoo.$tearDown();
    -}
    -
    -function testMocksGlobalFunctionWithArgs() {
    -  var mockReturnValue = 'Noam is Chomsky!';
    -  mockGlobal = goog.testing.createGlobalFunctionMock('globalBar');
    -  mockGlobal('Noam', 'Spartacus').$returns(mockReturnValue);
    -
    -  mockGlobal.$replay();
    -  assertEquals(mockReturnValue, globalBar('Noam', 'Spartacus'));
    -  mockGlobal.$verify();
    -}
    -
    -function testGlobalFunctionMockFailsWithIncorrectArgs() {
    -  mockGlobal = goog.testing.createGlobalFunctionMock('globalBar');
    -  mockGlobal('a', 'b');
    -
    -  mockGlobal.$replay();
    -
    -  assertThrows('Mock should have failed because of incorrect arguments',
    -      function() {globalBar('b', 'a')});
    -}
    -
    -function testGlobalFunctionMockQuacksLikeAFunctionMock() {
    -  mockGlobal = goog.testing.createGlobalFunctionMock('globalFoo');
    -  assertQuacksLike(mockGlobal, goog.testing.FunctionMock);
    -}
    -
    -function testMockedFunctionsAvailableInGlobalAndGoogGlobalAndWindowScope() {
    -  mockGlobal = goog.testing.createGlobalFunctionMock('globalFoo');
    -
    -  // we expect this call 3 times through global, goog.global and window scope
    -  mockGlobal().$times(3);
    -
    -  mockGlobal.$replay();
    -  goog.global.globalFoo();
    -  window.globalFoo();
    -  globalFoo();
    -  mockGlobal.$verify();
    -}
    -
    -function testTearDownRestoresOriginalGlobalFunction() {
    -  mockGlobal = goog.testing.createGlobalFunctionMock('globalFoo');
    -  mockGlobal().$returns('No, I am Spartacus!');
    -
    -  mockGlobal.$replay();
    -  assertEquals('No, I am Spartacus!', globalFoo());
    -  mockGlobal.$tearDown();
    -  assertEquals('I am Spartacus!', globalFoo());
    -  mockGlobal.$verify();
    -}
    -
    -function testTearDownHandlesMultipleMocking() {
    -  var mock1 = goog.testing.createGlobalFunctionMock('globalFoo');
    -  var mock2 = goog.testing.createGlobalFunctionMock('globalFoo');
    -  var mock3 = goog.testing.createGlobalFunctionMock('globalFoo');
    -  mock1().$returns('No, I am Spartacus 1!');
    -  mock2().$returns('No, I am Spartacus 2!');
    -  mock3().$returns('No, I am Spartacus 3!');
    -
    -  mock1.$replay();
    -  mock2.$replay();
    -  mock3.$replay();
    -  assertEquals('No, I am Spartacus 3!', globalFoo());
    -  mock3.$tearDown();
    -  assertEquals('No, I am Spartacus 2!', globalFoo());
    -  mock2.$tearDown();
    -  assertEquals('No, I am Spartacus 1!', globalFoo());
    -  mock1.$tearDown();
    -  assertEquals('I am Spartacus!', globalFoo());
    -}
    -
    -function testGlobalFunctionMockCallOrdering() {
    -  var mock = goog.testing.createGlobalFunctionMock('globalFoo');
    -  mock(1);
    -  mock(2);
    -  mock.$replay();
    -  assertThrows(function() {globalFoo(2);});
    -  mock.$tearDown();
    -
    -  mock = goog.testing.createGlobalFunctionMock('globalFoo',
    -                                               goog.testing.Mock.STRICT);
    -  mock(1);
    -  mock(2);
    -  mock.$replay();
    -  globalFoo(1);
    -  globalFoo(2);
    -  mock.$verify();
    -  mock.$tearDown();
    -
    -  mock = goog.testing.createGlobalFunctionMock('globalFoo',
    -                                               goog.testing.Mock.STRICT);
    -  mock(1);
    -  mock(2);
    -  mock.$replay();
    -  assertThrows(function() {globalFoo(2);});
    -  mock.$tearDown();
    -
    -  mock = goog.testing.createGlobalFunctionMock('globalFoo',
    -                                               goog.testing.Mock.LOOSE);
    -  mock(1);
    -  mock(2);
    -  mock.$replay();
    -  globalFoo(2);
    -  globalFoo(1);
    -  mock.$verify();
    -  mock.$tearDown();
    -}
    -
    -//----- Functions for goog.testing.MethodMock to mock
    -
    -var mynamespace = {};
    -
    -mynamespace.myMethod = function() {
    -  return 'I should be mocked.';
    -};
    -
    -function testMocksMethod() {
    -  mockMethod = goog.testing.createMethodMock(mynamespace, 'myMethod');
    -  mockMethod().$returns('I have been mocked!');
    -
    -  mockMethod.$replay();
    -  assertEquals('I have been mocked!', mockMethod());
    -  mockMethod.$verify();
    -}
    -
    -function testMocksMethodInNamespace() {
    -  goog.testing.createMethodMock(mynamespace, 'myMethod');
    -  mynamespace.myMethod().$returns('I have been mocked!');
    -
    -  mynamespace.myMethod.$replay();
    -  assertEquals('I have been mocked!', mynamespace.myMethod());
    -  mynamespace.myMethod.$verify();
    -  mynamespace.myMethod.$tearDown();
    -}
    -
    -function testMethodMockCanOnlyMockExistingMethods() {
    -  assertThrows(function() {
    -    goog.testing.createMethodMock(mynamespace, 'doesNotExist');
    -  });
    -}
    -
    -function testMethodMockCallOrdering() {
    -  goog.testing.createMethodMock(mynamespace, 'myMethod');
    -  mynamespace.myMethod(1);
    -  mynamespace.myMethod(2);
    -  mynamespace.myMethod.$replay();
    -  assertThrows(function() {mynamespace.myMethod(2);});
    -  mynamespace.myMethod.$tearDown();
    -
    -  goog.testing.createMethodMock(mynamespace, 'myMethod',
    -                                goog.testing.Mock.STRICT);
    -  mynamespace.myMethod(1);
    -  mynamespace.myMethod(2);
    -  mynamespace.myMethod.$replay();
    -  mynamespace.myMethod(1);
    -  mynamespace.myMethod(2);
    -  mynamespace.myMethod.$verify();
    -  mynamespace.myMethod.$tearDown();
    -
    -  goog.testing.createMethodMock(mynamespace, 'myMethod',
    -                                goog.testing.Mock.STRICT);
    -  mynamespace.myMethod(1);
    -  mynamespace.myMethod(2);
    -  mynamespace.myMethod.$replay();
    -  assertThrows(function() {mynamespace.myMethod(2);});
    -  mynamespace.myMethod.$tearDown();
    -
    -  goog.testing.createMethodMock(mynamespace, 'myMethod',
    -                                goog.testing.Mock.LOOSE);
    -  mynamespace.myMethod(1);
    -  mynamespace.myMethod(2);
    -  mynamespace.myMethod.$replay();
    -  mynamespace.myMethod(2);
    -  mynamespace.myMethod(1);
    -  mynamespace.myMethod.$verify();
    -  mynamespace.myMethod.$tearDown();
    -}
    -
    -//----- Functions for goog.testing.createConstructorMock to mock
    -
    -var constructornamespace = {};
    -
    -constructornamespace.MyConstructor = function() {
    -};
    -
    -constructornamespace.MyConstructor.prototype.myMethod = function() {
    -  return 'I should be mocked.';
    -};
    -
    -constructornamespace.MyConstructorWithArgument = function(argument) {
    -  this.argument_ = argument;
    -};
    -
    -constructornamespace.MyConstructorWithArgument.prototype.myMethod = function() {
    -  return this.argument_;
    -};
    -
    -constructornamespace.MyConstructorWithClassMembers = function() {
    -};
    -
    -constructornamespace.MyConstructorWithClassMembers.CONSTANT = 42;
    -
    -constructornamespace.MyConstructorWithClassMembers.classMethod = function() {
    -  return 'class method return value';
    -};
    -
    -function testConstructorMock() {
    -  var mockObject =
    -      new goog.testing.StrictMock(constructornamespace.MyConstructor);
    -  var mockConstructor = goog.testing.createConstructorMock(
    -      constructornamespace, 'MyConstructor');
    -  mockConstructor().$returns(mockObject);
    -  mockObject.myMethod().$returns('I have been mocked!');
    -
    -  mockConstructor.$replay();
    -  mockObject.$replay();
    -  assertEquals('I have been mocked!',
    -      new constructornamespace.MyConstructor().myMethod());
    -  mockConstructor.$verify();
    -  mockObject.$verify();
    -  mockConstructor.$tearDown();
    -}
    -
    -function testConstructorMockWithArgument() {
    -  var mockObject = new goog.testing.StrictMock(
    -      constructornamespace.MyConstructorWithArgument);
    -  var mockConstructor = goog.testing.createConstructorMock(
    -      constructornamespace, 'MyConstructorWithArgument');
    -  mockConstructor(goog.testing.mockmatchers.isString).$returns(mockObject);
    -  mockObject.myMethod().$returns('I have been mocked!');
    -
    -  mockConstructor.$replay();
    -  mockObject.$replay();
    -  assertEquals('I have been mocked!',
    -      new constructornamespace.MyConstructorWithArgument('I should be mocked.')
    -          .myMethod());
    -  mockConstructor.$verify();
    -  mockObject.$verify();
    -  mockConstructor.$tearDown();
    -}
    -
    -
    -/**
    - * Test that class members are copied to the mock constructor.
    - */
    -function testConstructorMockWithClassMembers() {
    -  var mockConstructor = goog.testing.createConstructorMock(
    -      constructornamespace, 'MyConstructorWithClassMembers');
    -  assertEquals(42, constructornamespace.MyConstructorWithClassMembers.CONSTANT);
    -  assertEquals('class method return value',
    -      constructornamespace.MyConstructorWithClassMembers.classMethod());
    -  mockConstructor.$tearDown();
    -}
    -
    -function testConstructorMockCallOrdering() {
    -  var instance = {};
    -
    -  goog.testing.createConstructorMock(constructornamespace,
    -                                     'MyConstructorWithArgument');
    -  constructornamespace.MyConstructorWithArgument(1).$returns(instance);
    -  constructornamespace.MyConstructorWithArgument(2).$returns(instance);
    -  constructornamespace.MyConstructorWithArgument.$replay();
    -  assertThrows(
    -      function() {new constructornamespace.MyConstructorWithArgument(2);});
    -  constructornamespace.MyConstructorWithArgument.$tearDown();
    -
    -  goog.testing.createConstructorMock(constructornamespace,
    -                                     'MyConstructorWithArgument',
    -                                     goog.testing.Mock.STRICT);
    -  constructornamespace.MyConstructorWithArgument(1).$returns(instance);
    -  constructornamespace.MyConstructorWithArgument(2).$returns(instance);
    -  constructornamespace.MyConstructorWithArgument.$replay();
    -  new constructornamespace.MyConstructorWithArgument(1);
    -  new constructornamespace.MyConstructorWithArgument(2);
    -  constructornamespace.MyConstructorWithArgument.$verify();
    -  constructornamespace.MyConstructorWithArgument.$tearDown();
    -
    -  goog.testing.createConstructorMock(constructornamespace,
    -                                     'MyConstructorWithArgument',
    -                                     goog.testing.Mock.STRICT);
    -  constructornamespace.MyConstructorWithArgument(1).$returns(instance);
    -  constructornamespace.MyConstructorWithArgument(2).$returns(instance);
    -  constructornamespace.MyConstructorWithArgument.$replay();
    -  assertThrows(
    -      function() {new constructornamespace.MyConstructorWithArgument(2);});
    -  constructornamespace.MyConstructorWithArgument.$tearDown();
    -
    -  goog.testing.createConstructorMock(constructornamespace,
    -                                     'MyConstructorWithArgument',
    -                                     goog.testing.Mock.LOOSE);
    -  constructornamespace.MyConstructorWithArgument(1).$returns(instance);
    -  constructornamespace.MyConstructorWithArgument(2).$returns(instance);
    -  constructornamespace.MyConstructorWithArgument.$replay();
    -  new constructornamespace.MyConstructorWithArgument(2);
    -  new constructornamespace.MyConstructorWithArgument(1);
    -  constructornamespace.MyConstructorWithArgument.$verify();
    -  constructornamespace.MyConstructorWithArgument.$tearDown();
    -}
    -
    -//----- Helper assertions
    -
    -function assertQuacksLike(obj, target) {
    -  for (meth in target.prototype) {
    -    if (!goog.string.endsWith(meth, '_')) {
    -      assertNotUndefined('Should have implemented ' + meth + '()', obj[meth]);
    -    }
    -  }
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/graphics.js b/src/database/third_party/closure-library/closure/goog/testing/graphics.js
    deleted file mode 100644
    index be342e457c7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/graphics.js
    +++ /dev/null
    @@ -1,64 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Testing utilities for DOM related tests.
    - *
    - * @author robbyw@google.com (Robby Walker)
    - */
    -
    -goog.provide('goog.testing.graphics');
    -
    -goog.require('goog.graphics.Path');
    -goog.require('goog.testing.asserts');
    -
    -
    -/**
    - * Array mapping numeric segment constant to a descriptive character.
    - * @type {Array<string>}
    - * @private
    - */
    -goog.testing.graphics.SEGMENT_NAMES_ = function() {
    -  var arr = [];
    -  arr[goog.graphics.Path.Segment.MOVETO] = 'M';
    -  arr[goog.graphics.Path.Segment.LINETO] = 'L';
    -  arr[goog.graphics.Path.Segment.CURVETO] = 'C';
    -  arr[goog.graphics.Path.Segment.ARCTO] = 'A';
    -  arr[goog.graphics.Path.Segment.CLOSE] = 'X';
    -  return arr;
    -}();
    -
    -
    -/**
    - * Test if the given path matches the expected array of commands and parameters.
    - * @param {Array<string|number>} expected The expected array of commands and
    - *     parameters.
    - * @param {goog.graphics.Path} path The path to test against.
    - */
    -goog.testing.graphics.assertPathEquals = function(expected, path) {
    -  var actual = [];
    -  path.forEachSegment(function(seg, args) {
    -    actual.push(goog.testing.graphics.SEGMENT_NAMES_[seg]);
    -    Array.prototype.push.apply(actual, args);
    -  });
    -  assertEquals(expected.length, actual.length);
    -  for (var i = 0; i < expected.length; i++) {
    -    if (goog.isNumber(expected[i])) {
    -      assertTrue(goog.isNumber(actual[i]));
    -      assertRoughlyEquals(expected[i], actual[i], 0.01);
    -    } else {
    -      assertEquals(expected[i], actual[i]);
    -    }
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/i18n/asserts.js b/src/database/third_party/closure-library/closure/goog/testing/i18n/asserts.js
    deleted file mode 100644
    index ab3033606fc..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/i18n/asserts.js
    +++ /dev/null
    @@ -1,77 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Assert functions that account for locale data changes.
    - *
    - * The locale data gets updated from CLDR (http://cldr.unicode.org/),
    - * and CLDR gets an update about twice per year.
    - * So the locale data are expected to change.
    - * This can make unit tests quite fragile:
    - *   assertEquals("Dec 31, 2013, 1:23pm", format);
    - * Now imagine that the decision is made to add a dot after abbreviations,
    - * and a comma between date and time.
    - * The previous assert will fail, because the string is now
    - *   "Dec. 31 2013, 1:23pm"
    - *
    - * One option is to not unit test the results of the formatters client side,
    - * and just trust that CLDR and closure/i18n takes care of that.
    - * The other option is to be a more flexible when testing.
    - * This is the role of assertI18nEquals, to centralize all the small
    - * differences between hard-coded values in unit tests and the current result.
    - * It allows some decupling, so that the closure/i18n can be updated without
    - * breaking all the clients using it.
    - * For the example above, this will succeed:
    - *   assertI18nEquals("Dec 31, 2013, 1:23pm", "Dec. 31, 2013 1:23pm");
    - * It does this by white-listing, no "guessing" involved.
    - *
    - * But I would say that the best practice is the first option: trust the
    - * library, stop unit-testing it.
    - */
    -
    -goog.provide('goog.testing.i18n.asserts');
    -goog.setTestOnly('goog.testing.i18n.asserts');
    -
    -goog.require('goog.testing.jsunit');
    -
    -
    -/**
    - * A map of known tests where locale data changed, but the old values are
    - * still tested for by various clients.
    - * @const {!Object<string, string>}
    - * @private
    - */
    -goog.testing.i18n.asserts.EXPECTED_VALUE_MAP_ = {
    -  // Data to test the assert itself, old string as key, new string as value
    -};
    -
    -
    -/**
    - * Asserts that the two values are "almost equal" from i18n perspective
    - * (based on a manually maintained and validated whitelist).
    - * @param {string} expected The expected value.
    - * @param {string} actual The actual value.
    - */
    -goog.testing.i18n.asserts.assertI18nEquals = function(expected, actual) {
    -  if (expected == actual) {
    -    return;
    -  }
    -
    -  var newExpected = goog.testing.i18n.asserts.EXPECTED_VALUE_MAP_[expected];
    -  if (newExpected == actual) {
    -    return;
    -  }
    -
    -  assertEquals(expected, actual);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/i18n/asserts_test.html b/src/database/third_party/closure-library/closure/goog/testing/i18n/asserts_test.html
    deleted file mode 100644
    index 77afbf9804b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/i18n/asserts_test.html
    +++ /dev/null
    @@ -1,19 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.testing.i18n.asserts</title>
    -<script src="../../base.js"></script>
    -</head>
    -<body>
    -<script>
    -  goog.require('goog.testing.i18n.assertsTest');
    -</script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/i18n/asserts_test.js b/src/database/third_party/closure-library/closure/goog/testing/i18n/asserts_test.js
    deleted file mode 100644
    index 163ca04c59d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/i18n/asserts_test.js
    +++ /dev/null
    @@ -1,67 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.testing.i18n.asserts.
    - */
    -
    -goog.provide('goog.testing.i18n.assertsTest');
    -goog.setTestOnly('goog.testing.i18n.assertsTest');
    -
    -goog.require('goog.testing.ExpectedFailures');
    -goog.require('goog.testing.i18n.asserts');
    -
    -
    -// Add this mapping for testing only
    -goog.testing.i18n.asserts.EXPECTED_VALUE_MAP_['mappedValue'] = 'newValue';
    -
    -var expectedFailures = new goog.testing.ExpectedFailures();
    -
    -function tearDown() {
    -  expectedFailures.handleTearDown();
    -}
    -
    -function testEdgeCases() {
    -  // Pass
    -  goog.testing.i18n.asserts.assertI18nEquals(null, null);
    -  goog.testing.i18n.asserts.assertI18nEquals('', '');
    -
    -  // Fail
    -  expectedFailures.expectFailureFor(true);
    -  try {
    -    goog.testing.i18n.asserts.assertI18nEquals(null, '');
    -    goog.testing.i18n.asserts.assertI18nEquals(null, 'test');
    -    goog.testing.i18n.asserts.assertI18nEquals('', null);
    -    goog.testing.i18n.asserts.assertI18nEquals('', 'test');
    -    goog.testing.i18n.asserts.assertI18nEquals('test', null);
    -    goog.testing.i18n.asserts.assertI18nEquals('test', '');
    -  } catch (e) {
    -    expectedFailures.handleException(e);
    -  }
    -}
    -
    -function testMappingWorks() {
    -  // Real equality
    -  goog.testing.i18n.asserts.assertI18nEquals('test', 'test');
    -  // i18n mapped equality
    -  goog.testing.i18n.asserts.assertI18nEquals('mappedValue', 'newValue');
    -
    -  // Negative testing
    -  expectedFailures.expectFailureFor(true);
    -  try {
    -    goog.testing.i18n.asserts.assertI18nEquals('unmappedValue', 'newValue');
    -  } catch (e) {
    -    expectedFailures.handleException(e);
    -  }
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/jsunit.js b/src/database/third_party/closure-library/closure/goog/testing/jsunit.js
    deleted file mode 100644
    index c2c9c1e2108..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/jsunit.js
    +++ /dev/null
    @@ -1,157 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Utilities for working with JsUnit.  Writes out the JsUnit file
    - * that needs to be included in every unit test.
    - *
    - * Testing code should not have dependencies outside of goog.testing so as to
    - * reduce the chance of masking missing dependencies.
    - *
    - */
    -
    -goog.provide('goog.testing.jsunit');
    -
    -goog.require('goog.testing.TestCase');
    -goog.require('goog.testing.TestRunner');
    -
    -
    -/**
    - * Base path for JsUnit app files, relative to Closure's base path.
    - * @type {string}
    - */
    -goog.testing.jsunit.BASE_PATH =
    -    '../../third_party/java/jsunit/core/app/';
    -
    -
    -/**
    - * Filename for the core JS Unit script.
    - * @type {string}
    - */
    -goog.testing.jsunit.CORE_SCRIPT =
    -    goog.testing.jsunit.BASE_PATH + 'jsUnitCore.js';
    -
    -
    -/**
    - * @define {boolean} If this code is being parsed by JsTestC, we let it disable
    - * the onload handler to avoid running the test in JsTestC.
    - */
    -goog.define('goog.testing.jsunit.AUTO_RUN_ONLOAD', true);
    -
    -
    -/**
    - * @define {number} Sets a delay in milliseconds after the window onload event
    - * and running the tests. Used to prevent interference with Selenium and give
    - * tests with asynchronous operations time to finish loading.
    - */
    -goog.define('goog.testing.jsunit.AUTO_RUN_DELAY_IN_MS', 500);
    -
    -
    -(function() {
    -  // Increases the maximum number of stack frames in Google Chrome from the
    -  // default 10 to 50 to get more useful stack traces.
    -  Error.stackTraceLimit = 50;
    -
    -  // Store a reference to the window's timeout so that it can't be overridden
    -  // by tests.
    -  /** @type {!Function} */
    -  var realTimeout = window.setTimeout;
    -
    -  // Check for JsUnit's test runner (need to check for >2.2 and <=2.2)
    -  if (top['JsUnitTestManager'] || top['jsUnitTestManager']) {
    -    // Running inside JsUnit so add support code.
    -    var path = goog.basePath + goog.testing.jsunit.CORE_SCRIPT;
    -    document.write('<script type="text/javascript" src="' +
    -                   path + '"></' + 'script>');
    -
    -  } else {
    -
    -    // Create a test runner.
    -    var tr = new goog.testing.TestRunner();
    -
    -    // Export it so that it can be queried by Selenium and tests that use a
    -    // compiled test runner.
    -    goog.exportSymbol('G_testRunner', tr);
    -    goog.exportSymbol('G_testRunner.initialize', tr.initialize);
    -    goog.exportSymbol('G_testRunner.isInitialized', tr.isInitialized);
    -    goog.exportSymbol('G_testRunner.isFinished', tr.isFinished);
    -    goog.exportSymbol('G_testRunner.isSuccess', tr.isSuccess);
    -    goog.exportSymbol('G_testRunner.getReport', tr.getReport);
    -    goog.exportSymbol('G_testRunner.getRunTime', tr.getRunTime);
    -    goog.exportSymbol('G_testRunner.getNumFilesLoaded', tr.getNumFilesLoaded);
    -    goog.exportSymbol('G_testRunner.setStrict', tr.setStrict);
    -    goog.exportSymbol('G_testRunner.logTestFailure', tr.logTestFailure);
    -    goog.exportSymbol('G_testRunner.getTestResults', tr.getTestResults);
    -
    -    // Export debug as a global function for JSUnit compatibility.  This just
    -    // calls log on the current test case.
    -    if (!goog.global['debug']) {
    -      goog.exportSymbol('debug', goog.bind(tr.log, tr));
    -    }
    -
    -    // If the application has defined a global error filter, set it now.  This
    -    // allows users who use a base test include to set the error filter before
    -    // the testing code is loaded.
    -    if (goog.global['G_errorFilter']) {
    -      tr.setErrorFilter(goog.global['G_errorFilter']);
    -    }
    -
    -    // Add an error handler to report errors that may occur during
    -    // initialization of the page.
    -    var onerror = window.onerror;
    -    window.onerror = function(error, url, line) {
    -      // Call any existing onerror handlers.
    -      if (onerror) {
    -        onerror(error, url, line);
    -      }
    -      if (typeof error == 'object') {
    -        // Webkit started passing an event object as the only argument to
    -        // window.onerror.  It doesn't contain an error message, url or line
    -        // number.  We therefore log as much info as we can.
    -        if (error.target && error.target.tagName == 'SCRIPT') {
    -          tr.logError('UNKNOWN ERROR: Script ' + error.target.src);
    -        } else {
    -          tr.logError('UNKNOWN ERROR: No error information available.');
    -        }
    -      } else {
    -        tr.logError('JS ERROR: ' + error + '\nURL: ' + url + '\nLine: ' + line);
    -      }
    -    };
    -
    -    // Create an onload handler, if the test runner hasn't been initialized then
    -    // no test has been registered with the test runner by the test file.  We
    -    // then create a new test case and auto discover any tests in the global
    -    // scope. If this code is being parsed by JsTestC, we let it disable the
    -    // onload handler to avoid running the test in JsTestC.
    -    if (goog.testing.jsunit.AUTO_RUN_ONLOAD) {
    -      var onload = window.onload;
    -      window.onload = function(e) {
    -        // Call any existing onload handlers.
    -        if (onload) {
    -          onload(e);
    -        }
    -        // Wait so that we don't interfere with WebDriver.
    -        realTimeout(function() {
    -          if (!tr.initialized) {
    -            var test = new goog.testing.TestCase(document.title);
    -            test.autoDiscoverTests();
    -            tr.initialize(test);
    -          }
    -          tr.execute();
    -        }, goog.testing.jsunit.AUTO_RUN_DELAY_IN_MS);
    -        window.onload = null;
    -      };
    -    }
    -  }
    -})();
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/loosemock.js b/src/database/third_party/closure-library/closure/goog/testing/loosemock.js
    deleted file mode 100644
    index cef72d77a6d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/loosemock.js
    +++ /dev/null
    @@ -1,242 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview This file defines a loose mock implementation.
    - */
    -
    -goog.provide('goog.testing.LooseExpectationCollection');
    -goog.provide('goog.testing.LooseMock');
    -
    -goog.require('goog.array');
    -goog.require('goog.structs.Map');
    -goog.require('goog.testing.Mock');
    -
    -
    -
    -/**
    - * This class is an ordered collection of expectations for one method. Since
    - * the loose mock does most of its verification at the time of $verify, this
    - * class is necessary to manage the return/throw behavior when the mock is
    - * being called.
    - * @constructor
    - * @final
    - */
    -goog.testing.LooseExpectationCollection = function() {
    -  /**
    -   * The list of expectations. All of these should have the same name.
    -   * @type {Array<goog.testing.MockExpectation>}
    -   * @private
    -   */
    -  this.expectations_ = [];
    -};
    -
    -
    -/**
    - * Adds an expectation to this collection.
    - * @param {goog.testing.MockExpectation} expectation The expectation to add.
    - */
    -goog.testing.LooseExpectationCollection.prototype.addExpectation =
    -    function(expectation) {
    -  this.expectations_.push(expectation);
    -};
    -
    -
    -/**
    - * Gets the list of expectations in this collection.
    - * @return {Array<goog.testing.MockExpectation>} The array of expectations.
    - */
    -goog.testing.LooseExpectationCollection.prototype.getExpectations = function() {
    -  return this.expectations_;
    -};
    -
    -
    -
    -/**
    - * This is a mock that does not care about the order of method calls. As a
    - * result, it won't throw exceptions until verify() is called. The only
    - * exception is that if a method is called that has no expectations, then an
    - * exception will be thrown.
    - * @param {Object|Function} objectToMock The object that should be mocked, or
    - *    the constructor of an object to mock.
    - * @param {boolean=} opt_ignoreUnexpectedCalls Whether to ignore unexpected
    - *     calls.
    - * @param {boolean=} opt_mockStaticMethods An optional argument denoting that
    - *     a mock should be constructed from the static functions of a class.
    - * @param {boolean=} opt_createProxy An optional argument denoting that
    - *     a proxy for the target mock should be created.
    - * @constructor
    - * @extends {goog.testing.Mock}
    - */
    -goog.testing.LooseMock = function(objectToMock, opt_ignoreUnexpectedCalls,
    -    opt_mockStaticMethods, opt_createProxy) {
    -  goog.testing.Mock.call(this, objectToMock, opt_mockStaticMethods,
    -      opt_createProxy);
    -
    -  /**
    -   * A map of method names to a LooseExpectationCollection for that method.
    -   * @type {goog.structs.Map}
    -   * @private
    -   */
    -  this.$expectations_ = new goog.structs.Map();
    -
    -  /**
    -   * The calls that have been made; we cache them to verify at the end. Each
    -   * element is an array where the first element is the name, and the second
    -   * element is the arguments.
    -   * @type {Array<Array<*>>}
    -   * @private
    -   */
    -  this.$calls_ = [];
    -
    -  /**
    -   * Whether to ignore unexpected calls.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.$ignoreUnexpectedCalls_ = !!opt_ignoreUnexpectedCalls;
    -};
    -goog.inherits(goog.testing.LooseMock, goog.testing.Mock);
    -
    -
    -/**
    - * A setter for the ignoreUnexpectedCalls field.
    - * @param {boolean} ignoreUnexpectedCalls Whether to ignore unexpected calls.
    - * @return {!goog.testing.LooseMock} This mock object.
    - */
    -goog.testing.LooseMock.prototype.$setIgnoreUnexpectedCalls = function(
    -    ignoreUnexpectedCalls) {
    -  this.$ignoreUnexpectedCalls_ = ignoreUnexpectedCalls;
    -  return this;
    -};
    -
    -
    -/** @override */
    -goog.testing.LooseMock.prototype.$recordExpectation = function() {
    -  if (!this.$expectations_.containsKey(this.$pendingExpectation.name)) {
    -    this.$expectations_.set(this.$pendingExpectation.name,
    -        new goog.testing.LooseExpectationCollection());
    -  }
    -
    -  var collection = this.$expectations_.get(this.$pendingExpectation.name);
    -  collection.addExpectation(this.$pendingExpectation);
    -};
    -
    -
    -/** @override */
    -goog.testing.LooseMock.prototype.$recordCall = function(name, args) {
    -  if (!this.$expectations_.containsKey(name)) {
    -    if (this.$ignoreUnexpectedCalls_) {
    -      return;
    -    }
    -    this.$throwCallException(name, args);
    -  }
    -
    -  // Start from the beginning of the expectations for this name,
    -  // and iterate over them until we find an expectation that matches
    -  // and also has calls remaining.
    -  var collection = this.$expectations_.get(name);
    -  var matchingExpectation = null;
    -  var expectations = collection.getExpectations();
    -  for (var i = 0; i < expectations.length; i++) {
    -    var expectation = expectations[i];
    -    if (this.$verifyCall(expectation, name, args)) {
    -      matchingExpectation = expectation;
    -      if (expectation.actualCalls < expectation.maxCalls) {
    -        break;
    -      } // else continue and see if we can find something that does match
    -    }
    -  }
    -  if (matchingExpectation == null) {
    -    this.$throwCallException(name, args, expectation);
    -  }
    -
    -  matchingExpectation.actualCalls++;
    -  if (matchingExpectation.actualCalls > matchingExpectation.maxCalls) {
    -    this.$throwException('Too many calls to ' + matchingExpectation.name +
    -            '\nExpected: ' + matchingExpectation.maxCalls + ' but was: ' +
    -            matchingExpectation.actualCalls);
    -  }
    -
    -  this.$calls_.push([name, args]);
    -  return this.$do(matchingExpectation, args);
    -};
    -
    -
    -/** @override */
    -goog.testing.LooseMock.prototype.$reset = function() {
    -  goog.testing.LooseMock.superClass_.$reset.call(this);
    -
    -  this.$expectations_ = new goog.structs.Map();
    -  this.$calls_ = [];
    -};
    -
    -
    -/** @override */
    -goog.testing.LooseMock.prototype.$replay = function() {
    -  goog.testing.LooseMock.superClass_.$replay.call(this);
    -
    -  // Verify that there are no expectations that can never be reached.
    -  // This can't catch every situation, but it is a decent sanity check
    -  // and it's similar to the behavior of EasyMock in java.
    -  var collections = this.$expectations_.getValues();
    -  for (var i = 0; i < collections.length; i++) {
    -    var expectations = collections[i].getExpectations();
    -    for (var j = 0; j < expectations.length; j++) {
    -      var expectation = expectations[j];
    -      // If this expectation can be called infinite times, then
    -      // check if any subsequent expectation has the exact same
    -      // argument list.
    -      if (!isFinite(expectation.maxCalls)) {
    -        for (var k = j + 1; k < expectations.length; k++) {
    -          var laterExpectation = expectations[k];
    -          if (laterExpectation.minCalls > 0 &&
    -              goog.array.equals(expectation.argumentList,
    -                  laterExpectation.argumentList)) {
    -            var name = expectation.name;
    -            var argsString = this.$argumentsAsString(expectation.argumentList);
    -            this.$throwException([
    -              'Expected call to ', name, ' with arguments ', argsString,
    -              ' has an infinite max number of calls; can\'t expect an',
    -              ' identical call later with a positive min number of calls'
    -            ].join(''));
    -          }
    -        }
    -      }
    -    }
    -  }
    -};
    -
    -
    -/** @override */
    -goog.testing.LooseMock.prototype.$verify = function() {
    -  goog.testing.LooseMock.superClass_.$verify.call(this);
    -  var collections = this.$expectations_.getValues();
    -
    -  for (var i = 0; i < collections.length; i++) {
    -    var expectations = collections[i].getExpectations();
    -    for (var j = 0; j < expectations.length; j++) {
    -      var expectation = expectations[j];
    -      if (expectation.actualCalls > expectation.maxCalls) {
    -        this.$throwException('Too many calls to ' + expectation.name +
    -            '\nExpected: ' + expectation.maxCalls + ' but was: ' +
    -            expectation.actualCalls);
    -      } else if (expectation.actualCalls < expectation.minCalls) {
    -        this.$throwException('Not enough calls to ' + expectation.name +
    -            '\nExpected: ' + expectation.minCalls + ' but was: ' +
    -            expectation.actualCalls);
    -      }
    -    }
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/loosemock_test.html b/src/database/third_party/closure-library/closure/goog/testing/loosemock_test.html
    deleted file mode 100644
    index 3950b5bcbac..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/loosemock_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.testing.LooseMock
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.LooseMockTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/loosemock_test.js b/src/database/third_party/closure-library/closure/goog/testing/loosemock_test.js
    deleted file mode 100644
    index a3d4483cda4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/loosemock_test.js
    +++ /dev/null
    @@ -1,342 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.LooseMockTest');
    -goog.setTestOnly('goog.testing.LooseMockTest');
    -
    -goog.require('goog.testing.LooseMock');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.mockmatchers');
    -
    -// The object that we will be mocking
    -var RealObject = function() {
    -};
    -
    -RealObject.prototype.a = function() {
    -  fail('real object should never be called');
    -};
    -
    -RealObject.prototype.b = function() {
    -  fail('real object should never be called');
    -};
    -
    -var mock;
    -
    -var stubs;
    -
    -function setUp() {
    -  var obj = new RealObject();
    -  mock = new goog.testing.LooseMock(obj);
    -  stubs = new goog.testing.PropertyReplacer();
    -}
    -
    -function tearDown() {
    -  stubs.reset();
    -}
    -
    -/*
    - * Calling this method evades the logTestFailure in
    - * goog.testing.Mock.prototype.$recordAndThrow, so it doesn't look like the
    - * test failed.
    - */
    -function silenceFailureLogging() {
    -  if (goog.global['G_testRunner']) {
    -    stubs.set(goog.global['G_testRunner'],
    -        'logTestFailure', goog.nullFunction);
    -  }
    -}
    -
    -function unsilenceFailureLogging() {
    -  stubs.reset();
    -}
    -
    -
    -/**
    - * Version of assertThrows that doesn't log the exception generated by the
    - * mocks under test.
    - * TODO: would be nice to check that a particular substring is in the thrown
    - * message so we know it's not something dumb like a syntax error
    - */
    -function assertThrowsQuiet(var_args) {
    -  silenceFailureLogging();
    -  assertThrows.apply(null, arguments);
    -  unsilenceFailureLogging();
    -}
    -
    -// Most of the basic functionality is tested in strictmock_test; these tests
    -// cover the cases where loose mocks are different from strict mocks
    -function testSimpleExpectations() {
    -  mock.a(5);
    -  mock.b();
    -  mock.$replay();
    -  mock.a(5);
    -  mock.b();
    -  mock.$verify();
    -
    -  mock.$reset();
    -
    -  mock.a();
    -  mock.b();
    -  mock.$replay();
    -  mock.b();
    -  mock.a();
    -  mock.$verify();
    -
    -  mock.$reset();
    -
    -  mock.a(5).$times(2);
    -  mock.a(5);
    -  mock.a(2);
    -  mock.$replay();
    -  mock.a(5);
    -  mock.a(5);
    -  mock.a(5);
    -  mock.a(2);
    -  mock.$verify();
    -}
    -
    -
    -function testMultipleExpectations() {
    -  mock.a().$returns(1);
    -  mock.a().$returns(2);
    -  mock.$replay();
    -  assertEquals(1, mock.a());
    -  assertEquals(2, mock.a());
    -  mock.$verify();
    -}
    -
    -
    -function testMultipleExpectationArgs() {
    -  mock.a('asdf').$anyTimes();
    -  mock.a('qwer').$anyTimes();
    -  mock.b().$times(3);
    -  mock.$replay();
    -  mock.a('asdf');
    -  mock.b();
    -  mock.a('asdf');
    -  mock.a('qwer');
    -  mock.b();
    -  mock.a('qwer');
    -  mock.b();
    -  mock.$verify();
    -
    -  mock.$reset();
    -
    -  mock.a('asdf').$anyTimes();
    -  mock.a('qwer').$anyTimes();
    -  mock.$replay();
    -  mock.a('asdf');
    -  mock.a('qwer');
    -  goog.bind(mock.a, mock, 'asdf');
    -  goog.bind(mock.$verify, mock);
    -}
    -
    -function testSameMethodOutOfOrder() {
    -  mock.a('foo').$returns(1);
    -  mock.a('bar').$returns(2);
    -  mock.$replay();
    -  assertEquals(2, mock.a('bar'));
    -  assertEquals(1, mock.a('foo'));
    -}
    -
    -function testSameMethodDifferentReturnValues() {
    -  mock.a('foo').$returns(1).$times(2);
    -  mock.a('foo').$returns(3);
    -  mock.a('bar').$returns(2);
    -  mock.$replay();
    -  assertEquals(1, mock.a('foo'));
    -  assertEquals(2, mock.a('bar'));
    -  assertEquals(1, mock.a('foo'));
    -  assertEquals(3, mock.a('foo'));
    -  assertThrowsQuiet(function() {
    -    mock.a('foo');
    -    mock.$verify();
    -  });
    -}
    -
    -function testSameMethodBrokenExpectations() {
    -  // This is a weird corner case.
    -  // No way to ever make this verify no matter what you call after replaying,
    -  // because the second expectation of mock.a('foo') will be masked by
    -  // the first expectation that can be called any number of times, and so we
    -  // can never satisfy that second expectation.
    -  mock.a('foo').$returns(1).$anyTimes();
    -  mock.a('bar').$returns(2);
    -  mock.a('foo').$returns(3);
    -
    -  // LooseMock can detect this case and fail on $replay.
    -  assertThrowsQuiet(goog.bind(mock.$replay, mock));
    -  mock.$reset();
    -
    -  // This is a variant of the corner case above, but it's harder to determine
    -  // that the expectation to mock.a('bar') can never be satisfied. So we don't
    -  // fail on $replay, but we do fail on $verify.
    -  mock.a(goog.testing.mockmatchers.isString).$returns(1).$anyTimes();
    -  mock.a('bar').$returns(2);
    -  mock.$replay();
    -
    -  assertEquals(1, mock.a('foo'));
    -  assertEquals(1, mock.a('bar'));
    -  assertThrowsQuiet(goog.bind(mock.$verify, mock));
    -}
    -
    -function testSameMethodMultipleAnyTimes() {
    -  mock.a('foo').$returns(1).$anyTimes();
    -  mock.a('foo').$returns(2).$anyTimes();
    -  mock.$replay();
    -  assertEquals(1, mock.a('foo'));
    -  assertEquals(1, mock.a('foo'));
    -  assertEquals(1, mock.a('foo'));
    -  // Note we'll never return 2 but that's ok.
    -  mock.$verify();
    -}
    -
    -function testFailingFast() {
    -  mock.a().$anyTimes();
    -  mock.$replay();
    -  mock.a();
    -  mock.a();
    -  assertThrowsQuiet(goog.bind(mock.b, mock));
    -  mock.$reset();
    -
    -  // too many
    -  mock.a();
    -  mock.b();
    -  mock.$replay();
    -  mock.a();
    -  mock.b();
    -
    -  var message;
    -  silenceFailureLogging();
    -  try {
    -    mock.a();
    -  } catch (e) {
    -    message = e.message;
    -  }
    -  unsilenceFailureLogging();
    -
    -  assertTrue('No exception thrown on unexpected call', goog.isDef(message));
    -  assertContains('Too many calls to a', message);
    -}
    -
    -function testTimes() {
    -  mock.a().$times(3);
    -  mock.b().$times(2);
    -  mock.$replay();
    -  mock.a();
    -  mock.b();
    -  mock.b();
    -  mock.a();
    -  mock.a();
    -  mock.$verify();
    -}
    -
    -
    -function testFailingSlow() {
    -  // not enough
    -  mock.a().$times(3);
    -  mock.$replay();
    -  mock.a();
    -  mock.a();
    -  assertThrowsQuiet(goog.bind(mock.$verify, mock));
    -
    -  mock.$reset();
    -
    -  // not enough, interleaved order
    -  mock.a().$times(3);
    -  mock.b().$times(3);
    -  mock.$replay();
    -  mock.a();
    -  mock.b();
    -  mock.a();
    -  mock.b();
    -  assertThrowsQuiet(goog.bind(mock.$verify, mock));
    -
    -  mock.$reset();
    -  // bad args
    -  mock.a('asdf').$anyTimes();
    -  mock.$replay();
    -  mock.a('asdf');
    -  assertThrowsQuiet(goog.bind(mock.a, mock, 'qwert'));
    -  assertThrowsQuiet(goog.bind(mock.$verify, mock));
    -}
    -
    -
    -function testArgsAndReturns() {
    -  mock.a('asdf').$atLeastOnce().$returns(5);
    -  mock.b('qwer').$times(2).$returns(3);
    -  mock.$replay();
    -  assertEquals(5, mock.a('asdf'));
    -  assertEquals(3, mock.b('qwer'));
    -  assertEquals(5, mock.a('asdf'));
    -  assertEquals(5, mock.a('asdf'));
    -  assertEquals(3, mock.b('qwer'));
    -  mock.$verify();
    -}
    -
    -
    -function testThrows() {
    -  mock.a().$throws('exception!');
    -  mock.$replay();
    -  assertThrowsQuiet(goog.bind(mock.a, mock));
    -  mock.$verify();
    -}
    -
    -
    -function testDoes() {
    -  mock.a(1, 2).$does(function(a, b) {return a + b;});
    -  mock.$replay();
    -  assertEquals('Mock should call the function', 3, mock.a(1, 2));
    -  mock.$verify();
    -}
    -
    -function testIgnoresExtraCalls() {
    -  mock = new goog.testing.LooseMock(RealObject, true);
    -  mock.a();
    -  mock.$replay();
    -  mock.a();
    -  mock.b(); // doesn't throw
    -  mock.$verify();
    -}
    -
    -function testSkipAnyTimes() {
    -  mock = new goog.testing.LooseMock(RealObject);
    -  mock.a(1).$anyTimes();
    -  mock.a(2).$anyTimes();
    -  mock.a(3).$anyTimes();
    -  mock.$replay();
    -  mock.a(1);
    -  mock.a(3);
    -  mock.$verify();
    -}
    -
    -function testErrorMessageForBadArgs() {
    -  mock.a();
    -  mock.$anyTimes();
    -
    -  mock.$replay();
    -
    -  var message;
    -  silenceFailureLogging();
    -  try {
    -    mock.a('a');
    -  } catch (e) {
    -    message = e.message;
    -  }
    -  unsilenceFailureLogging();
    -
    -  assertTrue('No exception thrown on verify', goog.isDef(message));
    -  assertContains('Bad arguments to a()', message);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/messaging/mockmessagechannel.js b/src/database/third_party/closure-library/closure/goog/testing/messaging/mockmessagechannel.js
    deleted file mode 100644
    index 085587a7945..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/messaging/mockmessagechannel.js
    +++ /dev/null
    @@ -1,80 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Mock MessageChannel implementation that can receive fake
    - * messages and test that the right messages are sent.
    - *
    - */
    -
    -
    -goog.provide('goog.testing.messaging.MockMessageChannel');
    -
    -goog.require('goog.messaging.AbstractChannel');
    -goog.require('goog.testing.asserts');
    -
    -
    -
    -/**
    - * Class for unit-testing code that communicates over a MessageChannel.
    - * @param {goog.testing.MockControl} mockControl The mock control used to create
    - *   the method mock for #send.
    - * @extends {goog.messaging.AbstractChannel}
    - * @constructor
    - * @final
    - */
    -goog.testing.messaging.MockMessageChannel = function(mockControl) {
    -  goog.testing.messaging.MockMessageChannel.base(this, 'constructor');
    -
    -  /**
    -   * Whether the channel has been disposed.
    -   * @type {boolean}
    -   */
    -  this.disposed = false;
    -
    -  mockControl.createMethodMock(this, 'send');
    -};
    -goog.inherits(goog.testing.messaging.MockMessageChannel,
    -              goog.messaging.AbstractChannel);
    -
    -
    -/**
    - * A mock send function. Actually an instance of
    - * {@link goog.testing.FunctionMock}.
    - * @param {string} serviceName The name of the remote service to run.
    - * @param {string|!Object} payload The payload to send to the remote page.
    - * @override
    - */
    -goog.testing.messaging.MockMessageChannel.prototype.send = function(
    -    serviceName, payload) {};
    -
    -
    -/**
    - * Sets a flag indicating that this is disposed.
    - * @override
    - */
    -goog.testing.messaging.MockMessageChannel.prototype.dispose = function() {
    -  this.disposed = true;
    -};
    -
    -
    -/**
    - * Mocks the receipt of a message. Passes the payload the appropriate service.
    - * @param {string} serviceName The service to run.
    - * @param {string|!Object} payload The argument to pass to the service.
    - */
    -goog.testing.messaging.MockMessageChannel.prototype.receive = function(
    -    serviceName, payload) {
    -  this.deliver(serviceName, payload);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/messaging/mockmessageevent.js b/src/database/third_party/closure-library/closure/goog/testing/messaging/mockmessageevent.js
    deleted file mode 100644
    index 474bcd1f66c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/messaging/mockmessageevent.js
    +++ /dev/null
    @@ -1,102 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A simple mock class for imitating HTML5 MessageEvents.
    - *
    - */
    -
    -goog.provide('goog.testing.messaging.MockMessageEvent');
    -
    -goog.require('goog.events.BrowserEvent');
    -goog.require('goog.events.EventType');
    -goog.require('goog.testing.events.Event');
    -
    -
    -
    -/**
    - * Creates a new fake MessageEvent.
    - *
    - * @param {*} data The data of the message.
    - * @param {string=} opt_origin The origin of the message, for server-sent and
    - *     cross-document events.
    - * @param {string=} opt_lastEventId The last event ID, for server-sent events.
    - * @param {Window=} opt_source The proxy for the source window, for
    - *     cross-document events.
    - * @param {Array<MessagePort>=} opt_ports The Array of ports sent with the
    - *     message, for cross-document and channel events.
    - * @extends {goog.testing.events.Event}
    - * @constructor
    - * @final
    - */
    -goog.testing.messaging.MockMessageEvent = function(
    -    data, opt_origin, opt_lastEventId, opt_source, opt_ports) {
    -  goog.testing.messaging.MockMessageEvent.base(
    -      this, 'constructor', goog.events.EventType.MESSAGE);
    -
    -  /**
    -   * The data of the message.
    -   * @type {*}
    -   */
    -  this.data = data;
    -
    -  /**
    -   * The origin of the message, for server-sent and cross-document events.
    -   * @type {?string}
    -   */
    -  this.origin = opt_origin || null;
    -
    -  /**
    -   * The last event ID, for server-sent events.
    -   * @type {?string}
    -   */
    -  this.lastEventId = opt_lastEventId || null;
    -
    -  /**
    -   * The proxy for the source window, for cross-document events.
    -   * @type {Window}
    -   */
    -  this.source = opt_source || null;
    -
    -  /**
    -   * The Array of ports sent with the message, for cross-document and channel
    -   * events.
    -   * @type {Array<!MessagePort>}
    -   */
    -  this.ports = opt_ports || null;
    -};
    -goog.inherits(
    -    goog.testing.messaging.MockMessageEvent, goog.testing.events.Event);
    -
    -
    -/**
    - * Wraps a new fake MessageEvent in a BrowserEvent, like how a real MessageEvent
    - * would be wrapped.
    - *
    - * @param {*} data The data of the message.
    - * @param {string=} opt_origin The origin of the message, for server-sent and
    - *     cross-document events.
    - * @param {string=} opt_lastEventId The last event ID, for server-sent events.
    - * @param {Window=} opt_source The proxy for the source window, for
    - *     cross-document events.
    - * @param {Array<MessagePort>=} opt_ports The Array of ports sent with the
    - *     message, for cross-document and channel events.
    - * @return {!goog.events.BrowserEvent} The wrapping event.
    - */
    -goog.testing.messaging.MockMessageEvent.wrap = function(
    -    data, opt_origin, opt_lastEventId, opt_source, opt_ports) {
    -  return new goog.events.BrowserEvent(
    -      new goog.testing.messaging.MockMessageEvent(
    -          data, opt_origin, opt_lastEventId, opt_source, opt_ports));
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/messaging/mockmessageport.js b/src/database/third_party/closure-library/closure/goog/testing/messaging/mockmessageport.js
    deleted file mode 100644
    index b99ea0da484..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/messaging/mockmessageport.js
    +++ /dev/null
    @@ -1,86 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A simple dummy class for representing message ports in tests.
    - *
    - */
    -
    -goog.provide('goog.testing.messaging.MockMessagePort');
    -
    -goog.require('goog.events.EventTarget');
    -
    -
    -
    -/**
    - * Class for unit-testing code that uses MessagePorts.
    - * @param {*} id An opaque identifier, used because message ports otherwise have
    - *     no distinguishing characteristics.
    - * @param {goog.testing.MockControl} mockControl The mock control used to create
    - *     the method mock for #postMessage.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - * @final
    - */
    -goog.testing.messaging.MockMessagePort = function(id, mockControl) {
    -  goog.testing.messaging.MockMessagePort.base(this, 'constructor');
    -
    -  /**
    -   * An opaque identifier, used because message ports otherwise have no
    -   * distinguishing characteristics.
    -   * @type {*}
    -   */
    -  this.id = id;
    -
    -  /**
    -   * Whether or not the port has been started.
    -   * @type {boolean}
    -   */
    -  this.started = false;
    -
    -  /**
    -   * Whether or not the port has been closed.
    -   * @type {boolean}
    -   */
    -  this.closed = false;
    -
    -  mockControl.createMethodMock(this, 'postMessage');
    -};
    -goog.inherits(goog.testing.messaging.MockMessagePort, goog.events.EventTarget);
    -
    -
    -/**
    - * A mock postMessage funciton. Actually an instance of
    - * {@link goog.testing.FunctionMock}.
    - * @param {*} message The message to send.
    - * @param {Array<MessagePort>=} opt_ports Ports to send with the message.
    - */
    -goog.testing.messaging.MockMessagePort.prototype.postMessage = function(
    -    message, opt_ports) {};
    -
    -
    -/**
    - * Starts the port.
    - */
    -goog.testing.messaging.MockMessagePort.prototype.start = function() {
    -  this.started = true;
    -};
    -
    -
    -/**
    - * Closes the port.
    - */
    -goog.testing.messaging.MockMessagePort.prototype.close = function() {
    -  this.closed = true;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/messaging/mockportnetwork.js b/src/database/third_party/closure-library/closure/goog/testing/messaging/mockportnetwork.js
    deleted file mode 100644
    index 3ef9062cda3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/messaging/mockportnetwork.js
    +++ /dev/null
    @@ -1,66 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A fake PortNetwork implementation that simply produces
    - * MockMessageChannels for all ports.
    - *
    - */
    -
    -goog.provide('goog.testing.messaging.MockPortNetwork');
    -
    -goog.require('goog.messaging.PortNetwork'); // interface
    -goog.require('goog.testing.messaging.MockMessageChannel');
    -
    -
    -
    -/**
    - * The fake PortNetwork.
    - *
    - * @param {!goog.testing.MockControl} mockControl The mock control for creating
    - *     the mock message channels.
    - * @constructor
    - * @implements {goog.messaging.PortNetwork}
    - * @final
    - */
    -goog.testing.messaging.MockPortNetwork = function(mockControl) {
    -  /**
    -   * The mock control for creating mock message channels.
    -   * @type {!goog.testing.MockControl}
    -   * @private
    -   */
    -  this.mockControl_ = mockControl;
    -
    -  /**
    -   * The mock ports that have been created.
    -   * @type {!Object<!goog.testing.messaging.MockMessageChannel>}
    -   * @private
    -   */
    -  this.ports_ = {};
    -};
    -
    -
    -/**
    - * Get the mock port with the given name.
    - * @param {string} name The name of the port to get.
    - * @return {!goog.testing.messaging.MockMessageChannel} The mock port.
    - * @override
    - */
    -goog.testing.messaging.MockPortNetwork.prototype.dial = function(name) {
    -  if (!(name in this.ports_)) {
    -    this.ports_[name] =
    -        new goog.testing.messaging.MockMessageChannel(this.mockControl_);
    -  }
    -  return this.ports_[name];
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/mock.js b/src/database/third_party/closure-library/closure/goog/testing/mock.js
    deleted file mode 100644
    index c832ac66497..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/mock.js
    +++ /dev/null
    @@ -1,645 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview This file defines base classes used for creating mocks in
    - * JavaScript. The API was inspired by EasyMock.
    - *
    - * The basic API is:
    - * <ul>
    - *   <li>Create an object to be mocked
    - *   <li>Create a mock object, passing in the above object to the constructor
    - *   <li>Set expectations by calling methods on the mock object
    - *   <li>Call $replay() on the mock object
    - *   <li>Pass the mock to code that will make real calls on it
    - *   <li>Call $verify() to make sure that expectations were met
    - * </ul>
    - *
    - * For examples, please see the unit tests for LooseMock and StrictMock.
    - *
    - * Still TODO
    - *   implement better (and pluggable) argument matching
    - *   Have the exceptions for LooseMock show the number of expected/actual calls
    - *   loose and strict mocks share a lot of code - move it to the base class
    - *
    - */
    -
    -goog.provide('goog.testing.Mock');
    -goog.provide('goog.testing.MockExpectation');
    -
    -goog.require('goog.array');
    -goog.require('goog.object');
    -goog.require('goog.testing.JsUnitException');
    -goog.require('goog.testing.MockInterface');
    -goog.require('goog.testing.mockmatchers');
    -
    -
    -
    -/**
    - * This is a class that represents an expectation.
    - * @param {string} name The name of the method for this expectation.
    - * @constructor
    - * @final
    - */
    -goog.testing.MockExpectation = function(name) {
    -  /**
    -   * The name of the method that is expected to be called.
    -   * @type {string}
    -   */
    -  this.name = name;
    -
    -  /**
    -   * An array of error messages for expectations not met.
    -   * @type {Array<string>}
    -   */
    -  this.errorMessages = [];
    -};
    -
    -
    -/**
    - * The minimum number of times this method should be called.
    - * @type {number}
    - */
    -goog.testing.MockExpectation.prototype.minCalls = 1;
    -
    -
    -/**
    -  * The maximum number of times this method should be called.
    -  * @type {number}
    -  */
    -goog.testing.MockExpectation.prototype.maxCalls = 1;
    -
    -
    -/**
    - * The value that this method should return.
    - * @type {*}
    - */
    -goog.testing.MockExpectation.prototype.returnValue;
    -
    -
    -/**
    - * The value that will be thrown when the method is called
    - * @type {*}
    - */
    -goog.testing.MockExpectation.prototype.exceptionToThrow;
    -
    -
    -/**
    - * The arguments that are expected to be passed to this function
    - * @type {Array<*>}
    - */
    -goog.testing.MockExpectation.prototype.argumentList;
    -
    -
    -/**
    - * The number of times this method is called by real code.
    - * @type {number}
    - */
    -goog.testing.MockExpectation.prototype.actualCalls = 0;
    -
    -
    -/**
    - * The number of times this method is called during the verification phase.
    - * @type {number}
    - */
    -goog.testing.MockExpectation.prototype.verificationCalls = 0;
    -
    -
    -/**
    - * The function which will be executed when this method is called.
    - * Method arguments will be passed to this function, and return value
    - * of this function will be returned by the method.
    - * @type {Function}
    - */
    -goog.testing.MockExpectation.prototype.toDo;
    -
    -
    -/**
    - * Allow expectation failures to include messages.
    - * @param {string} message The failure message.
    - */
    -goog.testing.MockExpectation.prototype.addErrorMessage = function(message) {
    -  this.errorMessages.push(message);
    -};
    -
    -
    -/**
    - * Get the error messages seen so far.
    - * @return {string} Error messages separated by \n.
    - */
    -goog.testing.MockExpectation.prototype.getErrorMessage = function() {
    -  return this.errorMessages.join('\n');
    -};
    -
    -
    -/**
    - * Get how many error messages have been seen so far.
    - * @return {number} Count of error messages.
    - */
    -goog.testing.MockExpectation.prototype.getErrorMessageCount = function() {
    -  return this.errorMessages.length;
    -};
    -
    -
    -
    -/**
    - * The base class for a mock object.
    - * @param {Object|Function} objectToMock The object that should be mocked, or
    - *    the constructor of an object to mock.
    - * @param {boolean=} opt_mockStaticMethods An optional argument denoting that
    - *     a mock should be constructed from the static functions of a class.
    - * @param {boolean=} opt_createProxy An optional argument denoting that
    - *     a proxy for the target mock should be created.
    - * @constructor
    - * @implements {goog.testing.MockInterface}
    - */
    -goog.testing.Mock = function(objectToMock, opt_mockStaticMethods,
    -    opt_createProxy) {
    -  if (!goog.isObject(objectToMock) && !goog.isFunction(objectToMock)) {
    -    throw new Error('objectToMock must be an object or constructor.');
    -  }
    -  if (opt_createProxy && !opt_mockStaticMethods &&
    -      goog.isFunction(objectToMock)) {
    -    /**
    - * @constructor
    - * @final
    - */
    -    var tempCtor = function() {};
    -    goog.inherits(tempCtor, objectToMock);
    -    this.$proxy = new tempCtor();
    -  } else if (opt_createProxy && opt_mockStaticMethods &&
    -      goog.isFunction(objectToMock)) {
    -    throw Error('Cannot create a proxy when opt_mockStaticMethods is true');
    -  } else if (opt_createProxy && !goog.isFunction(objectToMock)) {
    -    throw Error('Must have a constructor to create a proxy');
    -  }
    -
    -  if (goog.isFunction(objectToMock) && !opt_mockStaticMethods) {
    -    this.$initializeFunctions_(objectToMock.prototype);
    -  } else {
    -    this.$initializeFunctions_(objectToMock);
    -  }
    -  this.$argumentListVerifiers_ = {};
    -};
    -
    -
    -/**
    - * Option that may be passed when constructing function, method, and
    - * constructor mocks. Indicates that the expected calls should be accepted in
    - * any order.
    - * @const
    - * @type {number}
    - */
    -goog.testing.Mock.LOOSE = 1;
    -
    -
    -/**
    - * Option that may be passed when constructing function, method, and
    - * constructor mocks. Indicates that the expected calls should be accepted in
    - * the recorded order only.
    - * @const
    - * @type {number}
    - */
    -goog.testing.Mock.STRICT = 0;
    -
    -
    -/**
    - * This array contains the name of the functions that are part of the base
    - * Object prototype.
    - * Basically a copy of goog.object.PROTOTYPE_FIELDS_.
    - * @const
    - * @type {!Array<string>}
    - * @private
    - */
    -goog.testing.Mock.PROTOTYPE_FIELDS_ = [
    -  'constructor',
    -  'hasOwnProperty',
    -  'isPrototypeOf',
    -  'propertyIsEnumerable',
    -  'toLocaleString',
    -  'toString',
    -  'valueOf'
    -];
    -
    -
    -/**
    - * A proxy for the mock.  This can be used for dependency injection in lieu of
    - * the mock if the test requires a strict instanceof check.
    - * @type {Object}
    - */
    -goog.testing.Mock.prototype.$proxy = null;
    -
    -
    -/**
    - * Map of argument name to optional argument list verifier function.
    - * @type {Object}
    - */
    -goog.testing.Mock.prototype.$argumentListVerifiers_;
    -
    -
    -/**
    - * Whether or not we are in recording mode.
    - * @type {boolean}
    - * @private
    - */
    -goog.testing.Mock.prototype.$recording_ = true;
    -
    -
    -/**
    - * The expectation currently being created. All methods that modify the
    - * current expectation return the Mock object for easy chaining, so this is
    - * where we keep track of the expectation that's currently being modified.
    - * @type {goog.testing.MockExpectation}
    - * @protected
    - */
    -goog.testing.Mock.prototype.$pendingExpectation;
    -
    -
    -/**
    - * First exception thrown by this mock; used in $verify.
    - * @type {Object}
    - * @private
    - */
    -goog.testing.Mock.prototype.$threwException_ = null;
    -
    -
    -/**
    - * Initializes the functions on the mock object.
    - * @param {Object} objectToMock The object being mocked.
    - * @private
    - */
    -goog.testing.Mock.prototype.$initializeFunctions_ = function(objectToMock) {
    -  // Gets the object properties.
    -  var enumerableProperties = goog.object.getKeys(objectToMock);
    -
    -  // The non enumerable properties are added if they override the ones in the
    -  // Object prototype. This is due to the fact that IE8 does not enumerate any
    -  // of the prototype Object functions even when overriden and mocking these is
    -  // sometimes needed.
    -  for (var i = 0; i < goog.testing.Mock.PROTOTYPE_FIELDS_.length; i++) {
    -    var prop = goog.testing.Mock.PROTOTYPE_FIELDS_[i];
    -    // Look at b/6758711 if you're considering adding ALL properties to ALL
    -    // mocks.
    -    if (objectToMock[prop] !== Object.prototype[prop]) {
    -      enumerableProperties.push(prop);
    -    }
    -  }
    -
    -  // Adds the properties to the mock.
    -  for (var i = 0; i < enumerableProperties.length; i++) {
    -    var prop = enumerableProperties[i];
    -    if (typeof objectToMock[prop] == 'function') {
    -      this[prop] = goog.bind(this.$mockMethod, this, prop);
    -      if (this.$proxy) {
    -        this.$proxy[prop] = goog.bind(this.$mockMethod, this, prop);
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Registers a verfifier function to use when verifying method argument lists.
    - * @param {string} methodName The name of the method for which the verifierFn
    - *     should be used.
    - * @param {Function} fn Argument list verifier function.  Should take 2 argument
    - *     arrays as arguments, and return true if they are considered equivalent.
    - * @return {!goog.testing.Mock} This mock object.
    - */
    -goog.testing.Mock.prototype.$registerArgumentListVerifier = function(methodName,
    -                                                                     fn) {
    -  this.$argumentListVerifiers_[methodName] = fn;
    -  return this;
    -};
    -
    -
    -/**
    - * The function that replaces all methods on the mock object.
    - * @param {string} name The name of the method being mocked.
    - * @return {*} In record mode, returns the mock object. In replay mode, returns
    - *    whatever the creator of the mock set as the return value.
    - */
    -goog.testing.Mock.prototype.$mockMethod = function(name) {
    -  try {
    -    // Shift off the name argument so that args contains the arguments to
    -    // the mocked method.
    -    var args = goog.array.slice(arguments, 1);
    -    if (this.$recording_) {
    -      this.$pendingExpectation = new goog.testing.MockExpectation(name);
    -      this.$pendingExpectation.argumentList = args;
    -      this.$recordExpectation();
    -      return this;
    -    } else {
    -      return this.$recordCall(name, args);
    -    }
    -  } catch (ex) {
    -    this.$recordAndThrow(ex);
    -  }
    -};
    -
    -
    -/**
    - * Records the currently pending expectation, intended to be overridden by a
    - * subclass.
    - * @protected
    - */
    -goog.testing.Mock.prototype.$recordExpectation = function() {};
    -
    -
    -/**
    - * Records an actual method call, intended to be overridden by a
    - * subclass. The subclass must find the pending expectation and return the
    - * correct value.
    - * @param {string} name The name of the method being called.
    - * @param {Array<?>} args The arguments to the method.
    - * @return {*} The return expected by the mock.
    - * @protected
    - */
    -goog.testing.Mock.prototype.$recordCall = function(name, args) {
    -  return undefined;
    -};
    -
    -
    -/**
    - * If the expectation expects to throw, this method will throw.
    - * @param {goog.testing.MockExpectation} expectation The expectation.
    - */
    -goog.testing.Mock.prototype.$maybeThrow = function(expectation) {
    -  if (typeof expectation.exceptionToThrow != 'undefined') {
    -    throw expectation.exceptionToThrow;
    -  }
    -};
    -
    -
    -/**
    - * If this expectation defines a function to be called,
    - * it will be called and its result will be returned.
    - * Otherwise, if the expectation expects to throw, it will throw.
    - * Otherwise, this method will return defined value.
    - * @param {goog.testing.MockExpectation} expectation The expectation.
    - * @param {Array<?>} args The arguments to the method.
    - * @return {*} The return value expected by the mock.
    - */
    -goog.testing.Mock.prototype.$do = function(expectation, args) {
    -  if (typeof expectation.toDo == 'undefined') {
    -    this.$maybeThrow(expectation);
    -    return expectation.returnValue;
    -  } else {
    -    return expectation.toDo.apply(this, args);
    -  }
    -};
    -
    -
    -/**
    - * Specifies a return value for the currently pending expectation.
    - * @param {*} val The return value.
    - * @return {!goog.testing.Mock} This mock object.
    - */
    -goog.testing.Mock.prototype.$returns = function(val) {
    -  this.$pendingExpectation.returnValue = val;
    -  return this;
    -};
    -
    -
    -/**
    - * Specifies a value for the currently pending expectation to throw.
    - * @param {*} val The value to throw.
    - * @return {!goog.testing.Mock} This mock object.
    - */
    -goog.testing.Mock.prototype.$throws = function(val) {
    -  this.$pendingExpectation.exceptionToThrow = val;
    -  return this;
    -};
    -
    -
    -/**
    - * Specifies a function to call for currently pending expectation.
    - * Note, that using this method overrides declarations made
    - * using $returns() and $throws() methods.
    - * @param {Function} func The function to call.
    - * @return {!goog.testing.Mock} This mock object.
    - */
    -goog.testing.Mock.prototype.$does = function(func) {
    -  this.$pendingExpectation.toDo = func;
    -  return this;
    -};
    -
    -
    -/**
    - * Allows the expectation to be called 0 or 1 times.
    - * @return {!goog.testing.Mock} This mock object.
    - */
    -goog.testing.Mock.prototype.$atMostOnce = function() {
    -  this.$pendingExpectation.minCalls = 0;
    -  this.$pendingExpectation.maxCalls = 1;
    -  return this;
    -};
    -
    -
    -/**
    - * Allows the expectation to be called any number of times, as long as it's
    - * called once.
    - * @return {!goog.testing.Mock} This mock object.
    - */
    -goog.testing.Mock.prototype.$atLeastOnce = function() {
    -  this.$pendingExpectation.maxCalls = Infinity;
    -  return this;
    -};
    -
    -
    -/**
    - * Allows the expectation to be called exactly once.
    - * @return {!goog.testing.Mock} This mock object.
    - */
    -goog.testing.Mock.prototype.$once = function() {
    -  this.$pendingExpectation.minCalls = 1;
    -  this.$pendingExpectation.maxCalls = 1;
    -  return this;
    -};
    -
    -
    -/**
    - * Disallows the expectation from being called.
    - * @return {!goog.testing.Mock} This mock object.
    - */
    -goog.testing.Mock.prototype.$never = function() {
    -  this.$pendingExpectation.minCalls = 0;
    -  this.$pendingExpectation.maxCalls = 0;
    -  return this;
    -};
    -
    -
    -/**
    - * Allows the expectation to be called any number of times.
    - * @return {!goog.testing.Mock} This mock object.
    - */
    -goog.testing.Mock.prototype.$anyTimes = function() {
    -  this.$pendingExpectation.minCalls = 0;
    -  this.$pendingExpectation.maxCalls = Infinity;
    -  return this;
    -};
    -
    -
    -/**
    - * Specifies the number of times the expectation should be called.
    - * @param {number} times The number of times this method will be called.
    - * @return {!goog.testing.Mock} This mock object.
    - */
    -goog.testing.Mock.prototype.$times = function(times) {
    -  this.$pendingExpectation.minCalls = times;
    -  this.$pendingExpectation.maxCalls = times;
    -  return this;
    -};
    -
    -
    -/**
    - * Switches from recording to replay mode.
    - * @override
    - */
    -goog.testing.Mock.prototype.$replay = function() {
    -  this.$recording_ = false;
    -};
    -
    -
    -/**
    - * Resets the state of this mock object. This clears all pending expectations
    - * without verifying, and puts the mock in recording mode.
    - * @override
    - */
    -goog.testing.Mock.prototype.$reset = function() {
    -  this.$recording_ = true;
    -  this.$threwException_ = null;
    -  delete this.$pendingExpectation;
    -};
    -
    -
    -/**
    - * Throws an exception and records that an exception was thrown.
    - * @param {string} comment A short comment about the exception.
    - * @param {?string=} opt_message A longer message about the exception.
    - * @throws {Object} JsUnitException object.
    - * @protected
    - */
    -goog.testing.Mock.prototype.$throwException = function(comment, opt_message) {
    -  this.$recordAndThrow(new goog.testing.JsUnitException(comment, opt_message));
    -};
    -
    -
    -/**
    - * Throws an exception and records that an exception was thrown.
    - * @param {Object} ex Exception.
    - * @throws {Object} #ex.
    - * @protected
    - */
    -goog.testing.Mock.prototype.$recordAndThrow = function(ex) {
    -  // If it's an assert exception, record it.
    -  if (ex['isJsUnitException']) {
    -    var testRunner = goog.global['G_testRunner'];
    -    if (testRunner) {
    -      var logTestFailureFunction = testRunner['logTestFailure'];
    -      if (logTestFailureFunction) {
    -        logTestFailureFunction.call(testRunner, ex);
    -      }
    -    }
    -
    -    if (!this.$threwException_) {
    -      // Only remember first exception thrown.
    -      this.$threwException_ = ex;
    -    }
    -  }
    -  throw ex;
    -};
    -
    -
    -/**
    - * Verify that all of the expectations were met. Should be overridden by
    - * subclasses.
    - * @override
    - */
    -goog.testing.Mock.prototype.$verify = function() {
    -  if (this.$threwException_) {
    -    throw this.$threwException_;
    -  }
    -};
    -
    -
    -/**
    - * Verifies that a method call matches an expectation.
    - * @param {goog.testing.MockExpectation} expectation The expectation to check.
    - * @param {string} name The name of the called method.
    - * @param {Array<*>?} args The arguments passed to the mock.
    - * @return {boolean} Whether the call matches the expectation.
    - */
    -goog.testing.Mock.prototype.$verifyCall = function(expectation, name, args) {
    -  if (expectation.name != name) {
    -    return false;
    -  }
    -  var verifierFn =
    -      this.$argumentListVerifiers_.hasOwnProperty(expectation.name) ?
    -      this.$argumentListVerifiers_[expectation.name] :
    -      goog.testing.mockmatchers.flexibleArrayMatcher;
    -
    -  return verifierFn(expectation.argumentList, args, expectation);
    -};
    -
    -
    -/**
    - * Render the provided argument array to a string to help
    - * clients with debugging tests.
    - * @param {Array<*>?} args The arguments passed to the mock.
    - * @return {string} Human-readable string.
    - */
    -goog.testing.Mock.prototype.$argumentsAsString = function(args) {
    -  var retVal = [];
    -  for (var i = 0; i < args.length; i++) {
    -    try {
    -      retVal.push(goog.typeOf(args[i]));
    -    } catch (e) {
    -      retVal.push('[unknown]');
    -    }
    -  }
    -  return '(' + retVal.join(', ') + ')';
    -};
    -
    -
    -/**
    - * Throw an exception based on an incorrect method call.
    - * @param {string} name Name of method called.
    - * @param {Array<*>?} args Arguments passed to the mock.
    - * @param {goog.testing.MockExpectation=} opt_expectation Expected next call,
    - *     if any.
    - */
    -goog.testing.Mock.prototype.$throwCallException = function(name, args,
    -                                                           opt_expectation) {
    -  var errorStringBuffer = [];
    -  var actualArgsString = this.$argumentsAsString(args);
    -  var expectedArgsString = opt_expectation ?
    -      this.$argumentsAsString(opt_expectation.argumentList) : '';
    -
    -  if (opt_expectation && opt_expectation.name == name) {
    -    errorStringBuffer.push('Bad arguments to ', name, '().\n',
    -                           'Actual: ', actualArgsString, '\n',
    -                           'Expected: ', expectedArgsString, '\n',
    -                           opt_expectation.getErrorMessage());
    -  } else {
    -    errorStringBuffer.push('Unexpected call to ', name,
    -                           actualArgsString, '.');
    -    if (opt_expectation) {
    -      errorStringBuffer.push('\nNext expected call was to ',
    -                             opt_expectation.name,
    -                             expectedArgsString);
    -    }
    -  }
    -  this.$throwException(errorStringBuffer.join(''));
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/mock_test.html b/src/database/third_party/closure-library/closure/goog/testing/mock_test.html
    deleted file mode 100644
    index fd2f0a41db0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/mock_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.testing.Mock
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.MockTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/mock_test.js b/src/database/third_party/closure-library/closure/goog/testing/mock_test.js
    deleted file mode 100644
    index 3b8d23aba8e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/mock_test.js
    +++ /dev/null
    @@ -1,260 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.MockTest');
    -goog.setTestOnly('goog.testing.MockTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.testing');
    -goog.require('goog.testing.Mock');
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.MockExpectation');
    -goog.require('goog.testing.jsunit');
    -
    -// The object that we will be mocking
    -var RealObject = function() {
    -};
    -
    -RealObject.prototype.a = function() {
    -  fail('real object should never be called');
    -};
    -
    -RealObject.prototype.b = function() {
    -  fail('real object should never be called');
    -};
    -
    -var matchers = goog.testing.mockmatchers;
    -var mock;
    -
    -function setUp() {
    -  var obj = new RealObject();
    -  mock = new goog.testing.Mock(obj);
    -}
    -
    -function testMockErrorMessage() {
    -  var expectation = new goog.testing.MockExpectation('a');
    -  assertEquals(0, expectation.getErrorMessageCount());
    -  assertEquals('', expectation.getErrorMessage());
    -
    -  expectation.addErrorMessage('foo failed');
    -  assertEquals(1, expectation.getErrorMessageCount());
    -  assertEquals('foo failed', expectation.getErrorMessage());
    -
    -  expectation.addErrorMessage('bar failed');
    -  assertEquals(2, expectation.getErrorMessageCount());
    -  assertEquals('foo failed\nbar failed', expectation.getErrorMessage());
    -}
    -
    -function testVerifyArgumentList() {
    -  var expectation = new goog.testing.MockExpectation('a');
    -  assertEquals('', expectation.getErrorMessage());
    -
    -  // test single string arg
    -  expectation.argumentList = ['foo'];
    -  assertTrue(mock.$verifyCall(expectation, 'a', ['foo']));
    -
    -  // single numeric arg
    -  expectation.argumentList = [2];
    -  assertTrue(mock.$verifyCall(expectation, 'a', [2]));
    -
    -  // single object arg (using standard === comparison)
    -  var obj = {prop1: 'prop1', prop2: 2};
    -  expectation.argumentList = [obj];
    -  assertTrue(mock.$verifyCall(expectation, 'a', [obj]));
    -
    -  // make sure comparison succeeds if args are similar, but not ===
    -  var obj2 = {prop1: 'prop1', prop2: 2};
    -  expectation.argumentList = [obj];
    -  assertTrue(mock.$verifyCall(expectation, 'a', [obj2]));
    -  assertEquals('', expectation.getErrorMessage());
    -
    -  // multiple args
    -  expectation.argumentList = ['foo', 2, obj, obj2];
    -  assertTrue(mock.$verifyCall(expectation, 'a', ['foo', 2, obj, obj2]));
    -
    -  // test flexible arg matching.
    -  expectation.argumentList = ['foo', matchers.isNumber];
    -  assertTrue(mock.$verifyCall(expectation, 'a', ['foo', 1]));
    -
    -  expectation.argumentList = [new matchers.InstanceOf(RealObject)];
    -  assertTrue(mock.$verifyCall(expectation, 'a', [new RealObject()]));
    -}
    -
    -function testVerifyArgumentListForObjectMethods() {
    -  var expectation = new goog.testing.MockExpectation('toString');
    -  expectation.argumentList = [];
    -  assertTrue(mock.$verifyCall(expectation, 'toString', []));
    -}
    -
    -function testRegisterArgumentListVerifier() {
    -  var expectationA = new goog.testing.MockExpectation('a');
    -  var expectationB = new goog.testing.MockExpectation('b');
    -
    -  // Simple matcher that return true if all args are === equivalent.
    -  mock.$registerArgumentListVerifier('a', function(expectedArgs, args) {
    -    return goog.array.equals(expectedArgs, args, function(a, b) {
    -      return (a === b);
    -    });
    -  });
    -
    -  // test single string arg
    -  expectationA.argumentList = ['foo'];
    -  assertTrue(mock.$verifyCall(expectationA, 'a', ['foo']));
    -
    -  // single numeric arg
    -  expectationA.argumentList = [2];
    -  assertTrue(mock.$verifyCall(expectationA, 'a', [2]));
    -
    -  // single object arg (using standard === comparison)
    -  var obj = {prop1: 'prop1', prop2: 2};
    -  expectationA.argumentList = [obj];
    -  expectationB.argumentList = [obj];
    -  assertTrue(mock.$verifyCall(expectationA, 'a', [obj]));
    -  assertTrue(mock.$verifyCall(expectationB, 'b', [obj]));
    -
    -  // if args are similar, but not ===, then comparison should succeed
    -  // for method with registered object matcher, and fail for method without
    -  var obj2 = {prop1: 'prop1', prop2: 2};
    -  expectationA.argumentList = [obj];
    -  expectationB.argumentList = [obj];
    -  assertFalse(mock.$verifyCall(expectationA, 'a', [obj2]));
    -  assertTrue(mock.$verifyCall(expectationB, 'b', [obj2]));
    -
    -
    -  // multiple args, should fail for method with registered arg matcher,
    -  // and succeed for method without.
    -  expectationA.argumentList = ['foo', 2, obj, obj2];
    -  expectationB.argumentList = ['foo', 2, obj, obj2];
    -  assertFalse(mock.$verifyCall(expectationA, 'a', ['foo', 2, obj2, obj]));
    -  assertTrue(mock.$verifyCall(expectationB, 'b', ['foo', 2, obj2, obj]));
    -}
    -
    -
    -function testCreateProxy() {
    -  mock = new goog.testing.Mock(RealObject, false, true);
    -  assertTrue(mock.$proxy instanceof RealObject);
    -  assertThrows(function() {
    -    new goog.testing.Mock(RealObject, true, true);
    -  });
    -  assertThrows(function() {
    -    new goog.testing.Mock(1, false, true);
    -  });
    -}
    -
    -
    -function testValidConstructorArgument() {
    -  var someNamespace = { };
    -  assertThrows(function() {
    -    new goog.testing.Mock(someNamespace.RealObjectWithTypo);
    -  });
    -}
    -
    -
    -function testArgumentsAsString() {
    -  assertEquals('()', mock.$argumentsAsString([]));
    -  assertEquals('(string, number, object, null)',
    -               mock.$argumentsAsString(['red', 1, {}, null]));
    -}
    -
    -
    -function testThrowCallExceptionBadArgs() {
    -  var msg;
    -  mock.$throwException = function(m) {
    -    msg = m;
    -  };
    -
    -  mock.$throwCallException(
    -      'fn1', ['b'],
    -      { name: 'fn1',
    -        argumentList: ['c'],
    -        getErrorMessage: function() { return ''; } });
    -  assertContains(
    -      'Bad arguments to fn1().\nActual: (string)\nExpected: (string)', msg);
    -}
    -
    -function testThrowCallExceptionUnexpected() {
    -  var msg;
    -  mock.$throwException = function(m) {
    -    msg = m;
    -  };
    -
    -  mock.$throwCallException('fn1', ['b']);
    -  assertEquals('Unexpected call to fn1(string).', msg);
    -}
    -
    -function testThrowCallExceptionUnexpectedWithNext() {
    -  var msg;
    -  mock.$throwException = function(m) {
    -    msg = m;
    -  };
    -
    -  mock.$throwCallException(
    -      'fn1', ['b'],
    -      { name: 'fn2',
    -        argumentList: [3],
    -        getErrorMessage: function() { return ''; } });
    -  assertEquals(
    -      'Unexpected call to fn1(string).\n' +
    -      'Next expected call was to fn2(number)', msg);
    -}
    -
    -// This tests that base Object functions which are not enumerable in IE can
    -// be mocked correctly.
    -function testBindNonEnumerableFunctions() {
    -  // Create Foo and override non enumerable functions.
    -  var Foo = function() {};
    -  Foo.prototype.constructor = function() {
    -    fail('real object should never be called');
    -  };
    -  Foo.prototype.hasOwnProperty = function() {
    -    fail('real object should never be called');
    -  };
    -  Foo.prototype.isPrototypeOf = function() {
    -    fail('real object should never be called');
    -  };
    -  Foo.prototype.propertyIsEnumerable = function() {
    -    fail('real object should never be called');
    -  };
    -  Foo.prototype.toLocaleString = function() {
    -    fail('real object should never be called');
    -  };
    -  Foo.prototype.toString = function() {
    -    fail('real object should never be called');
    -  };
    -  Foo.prototype.valueOf = function() {
    -    fail('real object should never be called');
    -  };
    -
    -  // Create Mock and set $returns for toString.
    -  var mockControl = new goog.testing.MockControl();
    -  var mock = mockControl.createLooseMock(Foo);
    -  mock.constructor().$returns('constructor');
    -  mock.hasOwnProperty().$returns('hasOwnProperty');
    -  mock.isPrototypeOf().$returns('isPrototypeOf');
    -  mock.propertyIsEnumerable().$returns('propertyIsEnumerable');
    -  mock.toLocaleString().$returns('toLocaleString');
    -  mock.toString().$returns('toString');
    -  mock.valueOf().$returns('valueOf');
    -
    -  // Execute and assert that the Mock is working correctly.
    -  mockControl.$replayAll();
    -  assertEquals('constructor', mock.constructor());
    -  assertEquals('hasOwnProperty', mock.hasOwnProperty());
    -  assertEquals('isPrototypeOf', mock.isPrototypeOf());
    -  assertEquals('propertyIsEnumerable', mock.propertyIsEnumerable());
    -  assertEquals('toLocaleString', mock.toLocaleString());
    -  assertEquals('toString', mock.toString());
    -  assertEquals('valueOf', mock.valueOf());
    -  mockControl.$verifyAll();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/mockclassfactory.js b/src/database/third_party/closure-library/closure/goog/testing/mockclassfactory.js
    deleted file mode 100644
    index e4adc103839..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/mockclassfactory.js
    +++ /dev/null
    @@ -1,585 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview This file defines a factory that can be used to mock and
    - * replace an entire class.  This allows for mocks to be used effectively with
    - * "new" instead of having to inject all instances.  Essentially, a given class
    - * is replaced with a proxy to either a loose or strict mock.  Proxies locate
    - * the appropriate mock based on constructor arguments.
    - *
    - * The usage is:
    - * <ul>
    - *   <li>Create a mock with one of the provided methods with a specifc set of
    - *       constructor arguments
    - *   <li>Set expectations by calling methods on the mock object
    - *   <li>Call $replay() on the mock object
    - *   <li>Instantiate the object as normal
    - *   <li>Call $verify() to make sure that expectations were met
    - *   <li>Call reset on the factory to revert all classes back to their original
    - *       state
    - * </ul>
    - *
    - * For examples, please see the unit test.
    - *
    - */
    -
    -
    -goog.provide('goog.testing.MockClassFactory');
    -goog.provide('goog.testing.MockClassRecord');
    -
    -goog.require('goog.array');
    -goog.require('goog.object');
    -goog.require('goog.testing.LooseMock');
    -goog.require('goog.testing.StrictMock');
    -goog.require('goog.testing.TestCase');
    -goog.require('goog.testing.mockmatchers');
    -
    -
    -
    -/**
    - * A record that represents all the data associated with a mock replacement of
    - * a given class.
    - * @param {Object} namespace The namespace in which the mocked class resides.
    - * @param {string} className The name of the class within the namespace.
    - * @param {Function} originalClass The original class implementation before it
    - *     was replaced by a proxy.
    - * @param {Function} proxy The proxy that replaced the original class.
    - * @constructor
    - * @final
    - */
    -goog.testing.MockClassRecord = function(namespace, className, originalClass,
    -    proxy) {
    -  /**
    -   * A standard closure namespace (e.g. goog.foo.bar) that contains the mock
    -   * class referenced by this MockClassRecord.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.namespace_ = namespace;
    -
    -  /**
    -   * The name of the class within the provided namespace.
    -   * @type {string}
    -   * @private
    -   */
    -  this.className_ = className;
    -
    -  /**
    -   * The original class implementation.
    -   * @type {Function}
    -   * @private
    -   */
    -  this.originalClass_ = originalClass;
    -
    -  /**
    -   * The proxy being used as a replacement for the original class.
    -   * @type {Function}
    -   * @private
    -   */
    -  this.proxy_ = proxy;
    -
    -  /**
    -   * A mocks that will be constructed by their argument list.  The entries are
    -   * objects with the format {'args': args, 'mock': mock}.
    -   * @type {Array<Object>}
    -   * @private
    -   */
    -  this.instancesByArgs_ = [];
    -};
    -
    -
    -/**
    - * A mock associated with the static functions for a given class.
    - * @type {goog.testing.StrictMock|goog.testing.LooseMock|null}
    - * @private
    - */
    -goog.testing.MockClassRecord.prototype.staticMock_ = null;
    -
    -
    -/**
    - * A getter for this record's namespace.
    - * @return {Object} The namespace.
    - */
    -goog.testing.MockClassRecord.prototype.getNamespace = function() {
    -  return this.namespace_;
    -};
    -
    -
    -/**
    - * A getter for this record's class name.
    - * @return {string} The name of the class referenced by this record.
    - */
    -goog.testing.MockClassRecord.prototype.getClassName = function() {
    -  return this.className_;
    -};
    -
    -
    -/**
    - * A getter for the original class.
    - * @return {Function} The original class implementation before mocking.
    - */
    -goog.testing.MockClassRecord.prototype.getOriginalClass = function() {
    -  return this.originalClass_;
    -};
    -
    -
    -/**
    - * A getter for the proxy being used as a replacement for the original class.
    - * @return {Function} The proxy.
    - */
    -goog.testing.MockClassRecord.prototype.getProxy = function() {
    -  return this.proxy_;
    -};
    -
    -
    -/**
    - * A getter for the static mock.
    - * @return {goog.testing.StrictMock|goog.testing.LooseMock|null} The static
    - *     mock associated with this record.
    - */
    -goog.testing.MockClassRecord.prototype.getStaticMock = function() {
    -  return this.staticMock_;
    -};
    -
    -
    -/**
    - * A setter for the static mock.
    - * @param {goog.testing.StrictMock|goog.testing.LooseMock} staticMock A mock to
    - *     associate with the static functions for the referenced class.
    - */
    -goog.testing.MockClassRecord.prototype.setStaticMock = function(staticMock) {
    -  this.staticMock_ = staticMock;
    -};
    -
    -
    -/**
    - * Adds a new mock instance mapping.  The mapping connects a set of function
    - * arguments to a specific mock instance.
    - * @param {Array<?>} args An array of function arguments.
    - * @param {goog.testing.StrictMock|goog.testing.LooseMock} mock A mock
    - *     associated with the supplied arguments.
    - */
    -goog.testing.MockClassRecord.prototype.addMockInstance = function(args, mock) {
    -  this.instancesByArgs_.push({args: args, mock: mock});
    -};
    -
    -
    -/**
    - * Finds the mock corresponding to a given argument set.  Throws an error if
    - * there is no appropriate match found.
    - * @param {Array<?>} args An array of function arguments.
    - * @return {goog.testing.StrictMock|goog.testing.LooseMock|null} The mock
    - *     corresponding to a given argument set.
    - */
    -goog.testing.MockClassRecord.prototype.findMockInstance = function(args) {
    -  for (var i = 0; i < this.instancesByArgs_.length; i++) {
    -    var instanceArgs = this.instancesByArgs_[i].args;
    -    if (goog.testing.mockmatchers.flexibleArrayMatcher(instanceArgs, args)) {
    -      return this.instancesByArgs_[i].mock;
    -    }
    -  }
    -
    -  return null;
    -};
    -
    -
    -/**
    - * Resets this record by reverting all the mocked classes back to the original
    - * implementation and clearing out the mock instance list.
    - */
    -goog.testing.MockClassRecord.prototype.reset = function() {
    -  this.namespace_[this.className_] = this.originalClass_;
    -  this.instancesByArgs_ = [];
    -};
    -
    -
    -
    -/**
    - * A factory used to create new mock class instances.  It is able to generate
    - * both static and loose mocks.  The MockClassFactory is a singleton since it
    - * tracks the classes that have been mocked internally.
    - * @constructor
    - * @final
    - */
    -goog.testing.MockClassFactory = function() {
    -  if (goog.testing.MockClassFactory.instance_) {
    -    return goog.testing.MockClassFactory.instance_;
    -  }
    -
    -  /**
    -   * A map from class name -> goog.testing.MockClassRecord.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.mockClassRecords_ = {};
    -
    -  goog.testing.MockClassFactory.instance_ = this;
    -};
    -
    -
    -/**
    - * A singleton instance of the MockClassFactory.
    - * @type {goog.testing.MockClassFactory?}
    - * @private
    - */
    -goog.testing.MockClassFactory.instance_ = null;
    -
    -
    -/**
    - * The names of the fields that are defined on Object.prototype.
    - * @type {Array<string>}
    - * @private
    - */
    -goog.testing.MockClassFactory.PROTOTYPE_FIELDS_ = [
    -  'constructor',
    -  'hasOwnProperty',
    -  'isPrototypeOf',
    -  'propertyIsEnumerable',
    -  'toLocaleString',
    -  'toString',
    -  'valueOf'
    -];
    -
    -
    -/**
    - * Iterates through a namespace to find the name of a given class.  This is done
    - * solely to support compilation since string identifiers would break down.
    - * Tests usually aren't compiled, but the functionality is supported.
    - * @param {Object} namespace A javascript namespace (e.g. goog.testing).
    - * @param {Function} classToMock The class whose name should be returned.
    - * @return {string} The name of the class.
    - * @private
    - */
    -goog.testing.MockClassFactory.prototype.getClassName_ = function(namespace,
    -    classToMock) {
    -  var namespaces;
    -  if (namespace === goog.global) {
    -    namespaces = goog.testing.TestCase.getGlobals();
    -  } else {
    -    namespaces = [namespace];
    -  }
    -  for (var i = 0; i < namespaces.length; i++) {
    -    for (var prop in namespaces[i]) {
    -      if (namespaces[i][prop] === classToMock) {
    -        return prop;
    -      }
    -    }
    -  }
    -
    -  throw Error('Class is not a part of the given namespace');
    -};
    -
    -
    -/**
    - * Returns whether or not a given class has been mocked.
    - * @param {string} className The name of the class.
    - * @return {boolean} Whether or not the given class name has a MockClassRecord.
    - * @private
    - */
    -goog.testing.MockClassFactory.prototype.classHasMock_ = function(className) {
    -  return !!this.mockClassRecords_[className];
    -};
    -
    -
    -/**
    - * Returns a proxy constructor closure.  Since this is a constructor, "this"
    - * refers to the local scope of the constructed object thus bind cannot be
    - * used.
    - * @param {string} className The name of the class.
    - * @param {Function} mockFinder A bound function that returns the mock
    - *     associated with a class given the constructor's argument list.
    - * @return {!Function} A proxy constructor.
    - * @private
    - */
    -goog.testing.MockClassFactory.prototype.getProxyCtor_ = function(className,
    -    mockFinder) {
    -  return function() {
    -    this.$mock_ = mockFinder(className, arguments);
    -    if (!this.$mock_) {
    -      // The "arguments" variable is not a proper Array so it must be converted.
    -      var args = Array.prototype.slice.call(arguments, 0);
    -      throw Error('No mock found for ' + className + ' with arguments ' +
    -          args.join(', '));
    -    }
    -  };
    -};
    -
    -
    -/**
    - * Returns a proxy function for a mock class instance.  This function cannot
    - * be used with bind since "this" must refer to the scope of the proxy
    - * constructor.
    - * @param {string} fnName The name of the function that should be proxied.
    - * @return {!Function} A proxy function.
    - * @private
    - */
    -goog.testing.MockClassFactory.prototype.getProxyFunction_ = function(fnName) {
    -  return function() {
    -    return this.$mock_[fnName].apply(this.$mock_, arguments);
    -  };
    -};
    -
    -
    -/**
    - * Find a mock instance for a given class name and argument list.
    - * @param {string} className The name of the class.
    - * @param {Array<?>} args The argument list to match.
    - * @return {goog.testing.StrictMock|goog.testing.LooseMock} The mock found for
    - *     the given argument list.
    - * @private
    - */
    -goog.testing.MockClassFactory.prototype.findMockInstance_ = function(className,
    -    args) {
    -  return this.mockClassRecords_[className].findMockInstance(args);
    -};
    -
    -
    -/**
    - * Create a proxy class.  A proxy will pass functions to the mock for a class.
    - * The proxy class only covers prototype methods.  A static mock is not build
    - * simultaneously since it might be strict or loose.  The proxy class inherits
    - * from the target class in order to preserve instanceof checks.
    - * @param {Object} namespace A javascript namespace (e.g. goog.testing).
    - * @param {Function} classToMock The class that will be proxied.
    - * @param {string} className The name of the class.
    - * @return {!Function} The proxy for provided class.
    - * @private
    - */
    -goog.testing.MockClassFactory.prototype.createProxy_ = function(namespace,
    -    classToMock, className) {
    -  var proxy = this.getProxyCtor_(className,
    -      goog.bind(this.findMockInstance_, this));
    -  var protoToProxy = classToMock.prototype;
    -  goog.inherits(proxy, classToMock);
    -
    -  for (var prop in protoToProxy) {
    -    if (goog.isFunction(protoToProxy[prop])) {
    -      proxy.prototype[prop] = this.getProxyFunction_(prop);
    -    }
    -  }
    -
    -  // For IE the for-in-loop does not contain any properties that are not
    -  // enumerable on the prototype object (for example isPrototypeOf from
    -  // Object.prototype) and it will also not include 'replace' on objects that
    -  // extend String and change 'replace' (not that it is common for anyone to
    -  // extend anything except Object).
    -  // TODO (arv): Implement goog.object.getIterator and replace this loop.
    -
    -  goog.array.forEach(goog.testing.MockClassFactory.PROTOTYPE_FIELDS_,
    -      function(field) {
    -        if (Object.prototype.hasOwnProperty.call(protoToProxy, field)) {
    -          proxy.prototype[field] = this.getProxyFunction_(field);
    -        }
    -      }, this);
    -
    -  this.mockClassRecords_[className] = new goog.testing.MockClassRecord(
    -      namespace, className, classToMock, proxy);
    -  namespace[className] = proxy;
    -  return proxy;
    -};
    -
    -
    -/**
    - * Gets either a loose or strict mock for a given class based on a set of
    - * arguments.
    - * @param {Object} namespace A javascript namespace (e.g. goog.testing).
    - * @param {Function} classToMock The class that will be mocked.
    - * @param {boolean} isStrict Whether or not the mock should be strict.
    - * @param {goog.array.ArrayLike} ctorArgs The arguments associated with this
    - *     instance's constructor.
    - * @return {!goog.testing.StrictMock|!goog.testing.LooseMock} The mock created
    - *     for the provided class.
    - * @private
    - */
    -goog.testing.MockClassFactory.prototype.getMockClass_ =
    -    function(namespace, classToMock, isStrict, ctorArgs) {
    -  var className = this.getClassName_(namespace, classToMock);
    -
    -  // The namespace and classToMock variables should be removed from the
    -  // passed in argument stack.
    -  ctorArgs = goog.array.slice(ctorArgs, 2);
    -
    -  if (goog.isFunction(classToMock)) {
    -    var mock = isStrict ? new goog.testing.StrictMock(classToMock) :
    -        new goog.testing.LooseMock(classToMock);
    -
    -    if (!this.classHasMock_(className)) {
    -      this.createProxy_(namespace, classToMock, className);
    -    } else {
    -      var instance = this.findMockInstance_(className, ctorArgs);
    -      if (instance) {
    -        throw Error('Mock instance already created for ' + className +
    -            ' with arguments ' + ctorArgs.join(', '));
    -      }
    -    }
    -    this.mockClassRecords_[className].addMockInstance(ctorArgs, mock);
    -
    -    return mock;
    -  } else {
    -    throw Error('Cannot create a mock class for ' + className +
    -        ' of type ' + typeof classToMock);
    -  }
    -};
    -
    -
    -/**
    - * Gets a strict mock for a given class.
    - * @param {Object} namespace A javascript namespace (e.g. goog.testing).
    - * @param {Function} classToMock The class that will be mocked.
    - * @param {...*} var_args The arguments associated with this instance's
    - *     constructor.
    - * @return {!goog.testing.StrictMock} The mock created for the provided class.
    - */
    -goog.testing.MockClassFactory.prototype.getStrictMockClass =
    -    function(namespace, classToMock, var_args) {
    -  return /** @type {!goog.testing.StrictMock} */ (this.getMockClass_(namespace,
    -      classToMock, true, arguments));
    -};
    -
    -
    -/**
    - * Gets a loose mock for a given class.
    - * @param {Object} namespace A javascript namespace (e.g. goog.testing).
    - * @param {Function} classToMock The class that will be mocked.
    - * @param {...*} var_args The arguments associated with this instance's
    - *     constructor.
    - * @return {goog.testing.LooseMock} The mock created for the provided class.
    - */
    -goog.testing.MockClassFactory.prototype.getLooseMockClass =
    -    function(namespace, classToMock, var_args) {
    -  return /** @type {goog.testing.LooseMock} */ (this.getMockClass_(namespace,
    -      classToMock, false, arguments));
    -};
    -
    -
    -/**
    - * Creates either a loose or strict mock for the static functions of a given
    - * class.
    - * @param {Function} classToMock The class whose static functions will be
    - *     mocked.  This should be the original class and not the proxy.
    - * @param {string} className The name of the class.
    - * @param {Function} proxy The proxy that will replace the original class.
    - * @param {boolean} isStrict Whether or not the mock should be strict.
    - * @return {!goog.testing.StrictMock|!goog.testing.LooseMock} The mock created
    - *     for the static functions of the provided class.
    - * @private
    - */
    -goog.testing.MockClassFactory.prototype.createStaticMock_ =
    -    function(classToMock, className, proxy, isStrict) {
    -  var mock = isStrict ? new goog.testing.StrictMock(classToMock, true) :
    -      new goog.testing.LooseMock(classToMock, false, true);
    -
    -  for (var prop in classToMock) {
    -    if (goog.isFunction(classToMock[prop])) {
    -      proxy[prop] = goog.bind(mock.$mockMethod, mock, prop);
    -    } else if (classToMock[prop] !== classToMock.prototype) {
    -      proxy[prop] = classToMock[prop];
    -    }
    -  }
    -
    -  this.mockClassRecords_[className].setStaticMock(mock);
    -  return mock;
    -};
    -
    -
    -/**
    - * Gets either a loose or strict mock for the static functions of a given class.
    - * @param {Object} namespace A javascript namespace (e.g. goog.testing).
    - * @param {Function} classToMock The class whose static functions will be
    - *     mocked.  This should be the original class and not the proxy.
    - * @param {boolean} isStrict Whether or not the mock should be strict.
    - * @return {goog.testing.StrictMock|goog.testing.LooseMock} The mock created
    - *     for the static functions of the provided class.
    - * @private
    - */
    -goog.testing.MockClassFactory.prototype.getStaticMock_ = function(namespace,
    -    classToMock, isStrict) {
    -  var className = this.getClassName_(namespace, classToMock);
    -
    -  if (goog.isFunction(classToMock)) {
    -    if (!this.classHasMock_(className)) {
    -      var proxy = this.createProxy_(namespace, classToMock, className);
    -      var mock = this.createStaticMock_(classToMock, className, proxy,
    -          isStrict);
    -      return mock;
    -    }
    -
    -    if (!this.mockClassRecords_[className].getStaticMock()) {
    -      var proxy = this.mockClassRecords_[className].getProxy();
    -      var originalClass = this.mockClassRecords_[className].getOriginalClass();
    -      var mock = this.createStaticMock_(originalClass, className, proxy,
    -          isStrict);
    -      return mock;
    -    } else {
    -      var mock = this.mockClassRecords_[className].getStaticMock();
    -      var mockIsStrict = mock instanceof goog.testing.StrictMock;
    -
    -      if (mockIsStrict != isStrict) {
    -        var mockType = mock instanceof goog.testing.StrictMock ? 'strict' :
    -            'loose';
    -        var requestedType = isStrict ? 'strict' : 'loose';
    -        throw Error('Requested a ' + requestedType + ' static mock, but a ' +
    -            mockType + ' mock already exists.');
    -      }
    -
    -      return mock;
    -    }
    -  } else {
    -    throw Error('Cannot create a mock for the static functions of ' +
    -        className + ' of type ' + typeof classToMock);
    -  }
    -};
    -
    -
    -/**
    - * Gets a strict mock for the static functions of a given class.
    - * @param {Object} namespace A javascript namespace (e.g. goog.testing).
    - * @param {Function} classToMock The class whose static functions will be
    - *     mocked.  This should be the original class and not the proxy.
    - * @return {goog.testing.StrictMock} The mock created for the static functions
    - *     of the provided class.
    - */
    -goog.testing.MockClassFactory.prototype.getStrictStaticMock =
    -    function(namespace, classToMock) {
    -  return /** @type {goog.testing.StrictMock} */ (this.getStaticMock_(namespace,
    -      classToMock, true));
    -};
    -
    -
    -/**
    - * Gets a loose mock for the static functions of a given class.
    - * @param {Object} namespace A javascript namespace (e.g. goog.testing).
    - * @param {Function} classToMock The class whose static functions will be
    - *     mocked.  This should be the original class and not the proxy.
    - * @return {goog.testing.LooseMock} The mock created for the static functions
    - *     of the provided class.
    - */
    -goog.testing.MockClassFactory.prototype.getLooseStaticMock =
    -    function(namespace, classToMock) {
    -  return /** @type {goog.testing.LooseMock} */ (this.getStaticMock_(namespace,
    -      classToMock, false));
    -};
    -
    -
    -/**
    - * Resests the factory by reverting all mocked classes to their original
    - * implementations and removing all MockClassRecords.
    - */
    -goog.testing.MockClassFactory.prototype.reset = function() {
    -  goog.object.forEach(this.mockClassRecords_, function(record) {
    -    record.reset();
    -  });
    -  this.mockClassRecords_ = {};
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/mockclassfactory_test.html b/src/database/third_party/closure-library/closure/goog/testing/mockclassfactory_test.html
    deleted file mode 100644
    index 49e96da47a0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/mockclassfactory_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.testing.MockClassFactory
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.MockClassFactoryTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/mockclassfactory_test.js b/src/database/third_party/closure-library/closure/goog/testing/mockclassfactory_test.js
    deleted file mode 100644
    index 5ecec302248..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/mockclassfactory_test.js
    +++ /dev/null
    @@ -1,238 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.setTestOnly('goog.testing.MockClassFactoryTest');
    -goog.require('goog.testing');
    -goog.require('goog.testing.MockClassFactory');
    -goog.require('goog.testing.jsunit');
    -goog.provide('fake.BaseClass');
    -goog.provide('fake.ChildClass');
    -goog.provide('goog.testing.MockClassFactoryTest');
    -
    -// Classes that will be mocked.  A base class and child class are used to
    -// test inheritance.
    -fake.BaseClass = function(a) {
    -  fail('real object should never be called');
    -};
    -
    -fake.BaseClass.prototype.foo = function() {
    -  fail('real object should never be called');
    -};
    -
    -fake.BaseClass.prototype.toString = function() {return 'foo';};
    -
    -fake.BaseClass.prototype.toLocaleString = function() {return 'bar';};
    -
    -fake.ChildClass = function(a) {
    -  fail('real object should never be called');
    -};
    -goog.inherits(fake.ChildClass, fake.BaseClass);
    -
    -fake.ChildClass.staticFoo = function() {
    -  fail('real object should never be called');
    -};
    -
    -fake.ChildClass.prototype.bar = function() {
    -  fail('real object should never be called');
    -};
    -
    -fake.ChildClass.staticProperty = 'staticPropertyOnClass';
    -
    -function TopLevelBaseClass() {
    -}
    -
    -var mockClassFactory = new goog.testing.MockClassFactory();
    -var matchers = goog.testing.mockmatchers;
    -
    -function tearDown() {
    -  mockClassFactory.reset();
    -}
    -
    -function testGetStrictMockClass() {
    -  var mock1 = mockClassFactory.getStrictMockClass(fake, fake.BaseClass, 1);
    -  mock1.foo();
    -  mock1.$replay();
    -
    -  var mock2 = mockClassFactory.getStrictMockClass(fake, fake.BaseClass, 2);
    -  mock2.foo();
    -  mock2.$replay();
    -
    -  var mock3 = mockClassFactory.getStrictMockClass(fake, fake.ChildClass, 3);
    -  mock3.foo();
    -  mock3.bar();
    -  mock3.$replay();
    -
    -  var instance1 = new fake.BaseClass(1);
    -  instance1.foo();
    -  mock1.$verify();
    -
    -  var instance2 = new fake.BaseClass(2);
    -  instance2.foo();
    -  mock2.$verify();
    -
    -  var instance3 = new fake.ChildClass(3);
    -  instance3.foo();
    -  instance3.bar();
    -  mock3.$verify();
    -
    -  assertThrows(function() {new fake.BaseClass(-1)});
    -  assertTrue(instance1 instanceof fake.BaseClass);
    -  assertTrue(instance2 instanceof fake.BaseClass);
    -  assertTrue(instance3 instanceof fake.ChildClass);
    -}
    -
    -function testGetStrictMockClassCreatesAllProxies() {
    -  var mock1 = mockClassFactory.getStrictMockClass(fake, fake.BaseClass, 1);
    -  // toString(), toLocaleString() and others are treaded specially in
    -  // createProxy_().
    -  mock1.toString();
    -  mock1.toLocaleString();
    -  mock1.$replay();
    -
    -  var instance1 = new fake.BaseClass(1);
    -  instance1.toString();
    -  instance1.toLocaleString();
    -  mock1.$verify();
    -}
    -
    -function testGetLooseMockClass() {
    -  var mock1 = mockClassFactory.getLooseMockClass(fake, fake.BaseClass, 1);
    -  mock1.foo().$anyTimes().$returns(3);
    -  mock1.$replay();
    -
    -  var mock2 = mockClassFactory.getLooseMockClass(fake, fake.BaseClass, 2);
    -  mock2.foo().$times(3);
    -  mock2.$replay();
    -
    -  var mock3 = mockClassFactory.getLooseMockClass(fake, fake.ChildClass, 3);
    -  mock3.foo().$atLeastOnce().$returns(5);
    -  mock3.bar().$atLeastOnce();
    -  mock3.$replay();
    -
    -  var instance1 = new fake.BaseClass(1);
    -  assertEquals(3, instance1.foo());
    -  assertEquals(3, instance1.foo());
    -  assertEquals(3, instance1.foo());
    -  assertEquals(3, instance1.foo());
    -  assertEquals(3, instance1.foo());
    -  mock1.$verify();
    -
    -  var instance2 = new fake.BaseClass(2);
    -  instance2.foo();
    -  instance2.foo();
    -  instance2.foo();
    -  mock2.$verify();
    -
    -  var instance3 = new fake.ChildClass(3);
    -  assertEquals(5, instance3.foo());
    -  assertEquals(5, instance3.foo());
    -  instance3.bar();
    -  mock3.$verify();
    -
    -  assertThrows(function() {new fake.BaseClass(-1)});
    -  assertTrue(instance1 instanceof fake.BaseClass);
    -  assertTrue(instance2 instanceof fake.BaseClass);
    -  assertTrue(instance3 instanceof fake.ChildClass);
    -}
    -
    -function testGetStrictStaticMock() {
    -  var staticMock = mockClassFactory.getStrictStaticMock(fake,
    -      fake.ChildClass);
    -  var mock = mockClassFactory.getStrictMockClass(fake, fake.ChildClass, 1);
    -
    -  mock.foo();
    -  mock.bar();
    -  staticMock.staticFoo();
    -  mock.$replay();
    -  staticMock.$replay();
    -
    -  var instance = new fake.ChildClass(1);
    -  instance.foo();
    -  instance.bar();
    -  fake.ChildClass.staticFoo();
    -  mock.$verify();
    -  staticMock.$verify();
    -
    -  assertTrue(instance instanceof fake.BaseClass);
    -  assertTrue(instance instanceof fake.ChildClass);
    -  assertThrows(function() {
    -    mockClassFactory.getLooseStaticMock(fake, fake.ChildClass);
    -  });
    -}
    -
    -function testGetStrictStaticMockKeepsStaticProperties() {
    -  var OriginalChildClass = fake.ChildClass;
    -  var staticMock = mockClassFactory.getStrictStaticMock(fake,
    -      fake.ChildClass);
    -  assertEquals(OriginalChildClass.staticProperty,
    -      fake.ChildClass.staticProperty);
    -}
    -
    -function testGetLooseStaticMockKeepsStaticProperties() {
    -  var OriginalChildClass = fake.ChildClass;
    -  var staticMock = mockClassFactory.getLooseStaticMock(fake,
    -      fake.ChildClass);
    -  assertEquals(OriginalChildClass.staticProperty,
    -      fake.ChildClass.staticProperty);
    -}
    -
    -function testGetLooseStaticMock() {
    -  var staticMock = mockClassFactory.getLooseStaticMock(fake,
    -      fake.ChildClass);
    -  var mock = mockClassFactory.getStrictMockClass(fake, fake.ChildClass, 1);
    -
    -  mock.foo();
    -  mock.bar();
    -  staticMock.staticFoo().$atLeastOnce();
    -  mock.$replay();
    -  staticMock.$replay();
    -
    -  var instance = new fake.ChildClass(1);
    -  instance.foo();
    -  instance.bar();
    -  fake.ChildClass.staticFoo();
    -  fake.ChildClass.staticFoo();
    -  mock.$verify();
    -  staticMock.$verify();
    -
    -  assertTrue(instance instanceof fake.BaseClass);
    -  assertTrue(instance instanceof fake.ChildClass);
    -  assertThrows(function() {
    -    mockClassFactory.getStrictStaticMock(fake, fake.ChildClass);
    -  });
    -}
    -
    -function testFlexibleClassMockInstantiation() {
    -  // This mock should be returned for all instances created with a number
    -  // as the first argument.
    -  var mock = mockClassFactory.getStrictMockClass(fake, fake.ChildClass,
    -      matchers.isNumber);
    -  mock.foo(); // Will be called by the first mock instance.
    -  mock.foo(); // Will be called by the second mock instance.
    -  mock.$replay();
    -
    -  var instance1 = new fake.ChildClass(1);
    -  var instance2 = new fake.ChildClass(2);
    -  instance1.foo();
    -  instance2.foo();
    -  assertThrows(function() {
    -    new fake.ChildClass('foo');
    -  });
    -  mock.$verify();
    -}
    -
    -function testMockTopLevelClass() {
    -  var mock = mockClassFactory.getStrictMockClass(goog.global,
    -      goog.global.TopLevelBaseClass);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/mockclock.js b/src/database/third_party/closure-library/closure/goog/testing/mockclock.js
    deleted file mode 100644
    index b1d6b6f59ac..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/mockclock.js
    +++ /dev/null
    @@ -1,591 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Mock Clock implementation for working with setTimeout,
    - * setInterval, clearTimeout and clearInterval within unit tests.
    - *
    - * Derived from jsUnitMockTimeout.js, contributed to JsUnit by
    - * Pivotal Computer Systems, www.pivotalsf.com
    - *
    - */
    -
    -goog.provide('goog.testing.MockClock');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.async.run');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.events.Event');
    -goog.require('goog.testing.watchers');
    -
    -
    -
    -/**
    - * Class for unit testing code that uses setTimeout and clearTimeout.
    - *
    - * NOTE: If you are using MockClock to test code that makes use of
    - *       goog.fx.Animation, then you must either:
    - *
    - * 1. Install and dispose of the MockClock in setUpPage() and tearDownPage()
    - *    respectively (rather than setUp()/tearDown()).
    - *
    - * or
    - *
    - * 2. Ensure that every test clears the animation queue by calling
    - *    mockClock.tick(x) at the end of each test function (where `x` is large
    - *    enough to complete all animations).
    - *
    - * Otherwise, if any animation is left pending at the time that
    - * MockClock.dispose() is called, that will permanently prevent any future
    - * animations from playing on the page.
    - *
    - * @param {boolean=} opt_autoInstall Install the MockClock at construction time.
    - * @constructor
    - * @extends {goog.Disposable}
    - * @final
    - */
    -goog.testing.MockClock = function(opt_autoInstall) {
    -  goog.Disposable.call(this);
    -
    -  /**
    -   * Reverse-order queue of timers to fire.
    -   *
    -   * The last item of the queue is popped off.  Insertion happens from the
    -   * right.  For example, the expiration times for each element of the queue
    -   * might be in the order 300, 200, 200.
    -   *
    -   * @type {Array<Object>}
    -   * @private
    -   */
    -  this.queue_ = [];
    -
    -  /**
    -   * Set of timeouts that should be treated as cancelled.
    -   *
    -   * Rather than removing cancelled timers directly from the queue, this set
    -   * simply marks them as deleted so that they can be ignored when their
    -   * turn comes up.  The keys are the timeout keys that are cancelled, each
    -   * mapping to true.
    -   *
    -   * @type {Object}
    -   * @private
    -   */
    -  this.deletedKeys_ = {};
    -
    -  if (opt_autoInstall) {
    -    this.install();
    -  }
    -};
    -goog.inherits(goog.testing.MockClock, goog.Disposable);
    -
    -
    -/**
    - * Default wait timeout for mocking requestAnimationFrame (in milliseconds).
    - *
    - * @type {number}
    - * @const
    - */
    -goog.testing.MockClock.REQUEST_ANIMATION_FRAME_TIMEOUT = 20;
    -
    -
    -/**
    - * Count of the number of timeouts made.
    - * @type {number}
    - * @private
    - */
    -goog.testing.MockClock.prototype.timeoutsMade_ = 0;
    -
    -
    -/**
    - * PropertyReplacer instance which overwrites and resets setTimeout,
    - * setInterval, etc. or null if the MockClock is not installed.
    - * @type {goog.testing.PropertyReplacer}
    - * @private
    - */
    -goog.testing.MockClock.prototype.replacer_ = null;
    -
    -
    -/**
    - * Map of deleted keys.  These keys represents keys that were deleted in a
    - * clearInterval, timeoutid -> object.
    - * @type {Object}
    - * @private
    - */
    -goog.testing.MockClock.prototype.deletedKeys_ = null;
    -
    -
    -/**
    - * The current simulated time in milliseconds.
    - * @type {number}
    - * @private
    - */
    -goog.testing.MockClock.prototype.nowMillis_ = 0;
    -
    -
    -/**
    - * Additional delay between the time a timeout was set to fire, and the time
    - * it actually fires.  Useful for testing workarounds for this Firefox 2 bug:
    - * https://bugzilla.mozilla.org/show_bug.cgi?id=291386
    - * May be negative.
    - * @type {number}
    - * @private
    - */
    -goog.testing.MockClock.prototype.timeoutDelay_ = 0;
    -
    -
    -/**
    - * Installs the MockClock by overriding the global object's implementation of
    - * setTimeout, setInterval, clearTimeout and clearInterval.
    - */
    -goog.testing.MockClock.prototype.install = function() {
    -  if (!this.replacer_) {
    -    var r = this.replacer_ = new goog.testing.PropertyReplacer();
    -    r.set(goog.global, 'setTimeout', goog.bind(this.setTimeout_, this));
    -    r.set(goog.global, 'setInterval', goog.bind(this.setInterval_, this));
    -    r.set(goog.global, 'setImmediate', goog.bind(this.setImmediate_, this));
    -    r.set(goog.global, 'clearTimeout', goog.bind(this.clearTimeout_, this));
    -    r.set(goog.global, 'clearInterval', goog.bind(this.clearInterval_, this));
    -    // goog.Promise uses goog.async.run. In order to be able to test
    -    // Promise-based code, we need to make sure that goog.async.run uses
    -    // nextTick instead of native browser Promises. This means that it will
    -    // default to setImmediate, which is replaced above. Note that we test for
    -    // the presence of goog.async.run.forceNextTick to be resilient to the case
    -    // where tests replace goog.async.run directly.
    -    goog.async.run.forceNextTick && goog.async.run.forceNextTick();
    -
    -    // Replace the requestAnimationFrame functions.
    -    this.replaceRequestAnimationFrame_();
    -
    -    // PropertyReplacer#set can't be called with renameable functions.
    -    this.oldGoogNow_ = goog.now;
    -    goog.now = goog.bind(this.getCurrentTime, this);
    -  }
    -};
    -
    -
    -/**
    - * Installs the mocks for requestAnimationFrame and cancelRequestAnimationFrame.
    - * @private
    - */
    -goog.testing.MockClock.prototype.replaceRequestAnimationFrame_ = function() {
    -  var r = this.replacer_;
    -  var requestFuncs = ['requestAnimationFrame',
    -                      'webkitRequestAnimationFrame',
    -                      'mozRequestAnimationFrame',
    -                      'oRequestAnimationFrame',
    -                      'msRequestAnimationFrame'];
    -
    -  var cancelFuncs = ['cancelAnimationFrame',
    -                     'cancelRequestAnimationFrame',
    -                     'webkitCancelRequestAnimationFrame',
    -                     'mozCancelRequestAnimationFrame',
    -                     'oCancelRequestAnimationFrame',
    -                     'msCancelRequestAnimationFrame'];
    -
    -  for (var i = 0; i < requestFuncs.length; ++i) {
    -    if (goog.global && goog.global[requestFuncs[i]]) {
    -      r.set(goog.global, requestFuncs[i],
    -          goog.bind(this.requestAnimationFrame_, this));
    -    }
    -  }
    -
    -  for (var i = 0; i < cancelFuncs.length; ++i) {
    -    if (goog.global && goog.global[cancelFuncs[i]]) {
    -      r.set(goog.global, cancelFuncs[i],
    -          goog.bind(this.cancelRequestAnimationFrame_, this));
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Removes the MockClock's hooks into the global object's functions and revert
    - * to their original values.
    - */
    -goog.testing.MockClock.prototype.uninstall = function() {
    -  if (this.replacer_) {
    -    this.replacer_.reset();
    -    this.replacer_ = null;
    -    goog.now = this.oldGoogNow_;
    -  }
    -
    -  this.fireResetEvent();
    -};
    -
    -
    -/** @override */
    -goog.testing.MockClock.prototype.disposeInternal = function() {
    -  this.uninstall();
    -  this.queue_ = null;
    -  this.deletedKeys_ = null;
    -  goog.testing.MockClock.superClass_.disposeInternal.call(this);
    -};
    -
    -
    -/**
    - * Resets the MockClock, removing all timeouts that are scheduled and resets
    - * the fake timer count.
    - */
    -goog.testing.MockClock.prototype.reset = function() {
    -  this.queue_ = [];
    -  this.deletedKeys_ = {};
    -  this.nowMillis_ = 0;
    -  this.timeoutsMade_ = 0;
    -  this.timeoutDelay_ = 0;
    -
    -  this.fireResetEvent();
    -};
    -
    -
    -/**
    - * Signals that the mock clock has been reset, allowing objects that
    - * maintain their own internal state to reset.
    - */
    -goog.testing.MockClock.prototype.fireResetEvent = function() {
    -  goog.testing.watchers.signalClockReset();
    -};
    -
    -
    -/**
    - * Sets the amount of time between when a timeout is scheduled to fire and when
    - * it actually fires.
    - * @param {number} delay The delay in milliseconds.  May be negative.
    - */
    -goog.testing.MockClock.prototype.setTimeoutDelay = function(delay) {
    -  this.timeoutDelay_ = delay;
    -};
    -
    -
    -/**
    - * @return {number} delay The amount of time between when a timeout is
    - *     scheduled to fire and when it actually fires, in milliseconds.  May
    - *     be negative.
    - */
    -goog.testing.MockClock.prototype.getTimeoutDelay = function() {
    -  return this.timeoutDelay_;
    -};
    -
    -
    -/**
    - * Increments the MockClock's time by a given number of milliseconds, running
    - * any functions that are now overdue.
    - * @param {number=} opt_millis Number of milliseconds to increment the counter.
    - *     If not specified, clock ticks 1 millisecond.
    - * @return {number} Current mock time in milliseconds.
    - */
    -goog.testing.MockClock.prototype.tick = function(opt_millis) {
    -  if (typeof opt_millis != 'number') {
    -    opt_millis = 1;
    -  }
    -  var endTime = this.nowMillis_ + opt_millis;
    -  this.runFunctionsWithinRange_(endTime);
    -  this.nowMillis_ = endTime;
    -  return endTime;
    -};
    -
    -
    -/**
    - * Takes a promise and then ticks the mock clock. If the promise successfully
    - * resolves, returns the value produced by the promise. If the promise is
    - * rejected, it throws the rejection as an exception. If the promise is not
    - * resolved at all, throws an exception.
    - * Also ticks the general clock by the specified amount.
    - *
    - * @param {!goog.Thenable<T>} promise A promise that should be resolved after
    - *     the mockClock is ticked for the given opt_millis.
    - * @param {number=} opt_millis Number of milliseconds to increment the counter.
    - *     If not specified, clock ticks 1 millisecond.
    - * @return {T}
    - * @template T
    - */
    -goog.testing.MockClock.prototype.tickPromise = function(promise, opt_millis) {
    -  var value;
    -  var error;
    -  var resolved = false;
    -  promise.then(function(v) {
    -    value = v;
    -    resolved = true;
    -  }, function(e) {
    -    error = e;
    -    resolved = true;
    -  });
    -  this.tick(opt_millis);
    -  if (!resolved) {
    -    throw new Error(
    -        'Promise was expected to be resolved after mock clock tick.');
    -  }
    -  if (error) {
    -    throw error;
    -  }
    -  return value;
    -};
    -
    -
    -/**
    - * @return {number} The number of timeouts that have been scheduled.
    - */
    -goog.testing.MockClock.prototype.getTimeoutsMade = function() {
    -  return this.timeoutsMade_;
    -};
    -
    -
    -/**
    - * @return {number} The MockClock's current time in milliseconds.
    - */
    -goog.testing.MockClock.prototype.getCurrentTime = function() {
    -  return this.nowMillis_;
    -};
    -
    -
    -/**
    - * @param {number} timeoutKey The timeout key.
    - * @return {boolean} Whether the timer has been set and not cleared,
    - *     independent of the timeout's expiration.  In other words, the timeout
    - *     could have passed or could be scheduled for the future.  Either way,
    - *     this function returns true or false depending only on whether the
    - *     provided timeoutKey represents a timeout that has been set and not
    - *     cleared.
    - */
    -goog.testing.MockClock.prototype.isTimeoutSet = function(timeoutKey) {
    -  return timeoutKey <= this.timeoutsMade_ && !this.deletedKeys_[timeoutKey];
    -};
    -
    -
    -/**
    - * Runs any function that is scheduled before a certain time.  Timeouts can
    - * be made to fire early or late if timeoutDelay_ is non-0.
    - * @param {number} endTime The latest time in the range, in milliseconds.
    - * @private
    - */
    -goog.testing.MockClock.prototype.runFunctionsWithinRange_ = function(
    -    endTime) {
    -  var adjustedEndTime = endTime - this.timeoutDelay_;
    -
    -  // Repeatedly pop off the last item since the queue is always sorted.
    -  while (this.queue_ && this.queue_.length &&
    -      this.queue_[this.queue_.length - 1].runAtMillis <= adjustedEndTime) {
    -    var timeout = this.queue_.pop();
    -
    -    if (!(timeout.timeoutKey in this.deletedKeys_)) {
    -      // Only move time forwards.
    -      this.nowMillis_ = Math.max(this.nowMillis_,
    -          timeout.runAtMillis + this.timeoutDelay_);
    -      // Call timeout in global scope and pass the timeout key as the argument.
    -      timeout.funcToCall.call(goog.global, timeout.timeoutKey);
    -      // In case the interval was cleared in the funcToCall
    -      if (timeout.recurring) {
    -        this.scheduleFunction_(
    -            timeout.timeoutKey, timeout.funcToCall, timeout.millis, true);
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Schedules a function to be run at a certain time.
    - * @param {number} timeoutKey The timeout key.
    - * @param {Function} funcToCall The function to call.
    - * @param {number} millis The number of milliseconds to call it in.
    - * @param {boolean} recurring Whether to function call should recur.
    - * @private
    - */
    -goog.testing.MockClock.prototype.scheduleFunction_ = function(
    -    timeoutKey, funcToCall, millis, recurring) {
    -  if (!goog.isFunction(funcToCall)) {
    -    // Early error for debuggability rather than dying in the next .tick()
    -    throw new TypeError('The provided callback must be a function, not a ' +
    -        typeof funcToCall);
    -  }
    -
    -  var timeout = {
    -    runAtMillis: this.nowMillis_ + millis,
    -    funcToCall: funcToCall,
    -    recurring: recurring,
    -    timeoutKey: timeoutKey,
    -    millis: millis
    -  };
    -
    -  goog.testing.MockClock.insert_(timeout, this.queue_);
    -};
    -
    -
    -/**
    - * Inserts a timer descriptor into a descending-order queue.
    - *
    - * Later-inserted duplicates appear at lower indices.  For example, the
    - * asterisk in (5,4,*,3,2,1) would be the insertion point for 3.
    - *
    - * @param {Object} timeout The timeout to insert, with numerical runAtMillis
    - *     property.
    - * @param {Array<Object>} queue The queue to insert into, with each element
    - *     having a numerical runAtMillis property.
    - * @private
    - */
    -goog.testing.MockClock.insert_ = function(timeout, queue) {
    -  // Although insertion of N items is quadratic, requiring goog.structs.Heap
    -  // from a unit test will make tests more prone to breakage.  Since unit
    -  // tests are normally small, scalability is not a primary issue.
    -
    -  // Find an insertion point.  Since the queue is in reverse order (so we
    -  // can pop rather than unshift), and later timers with the same time stamp
    -  // should be executed later, we look for the element strictly greater than
    -  // the one we are inserting.
    -
    -  for (var i = queue.length; i != 0; i--) {
    -    if (queue[i - 1].runAtMillis > timeout.runAtMillis) {
    -      break;
    -    }
    -    queue[i] = queue[i - 1];
    -  }
    -
    -  queue[i] = timeout;
    -};
    -
    -
    -/**
    - * Maximum 32-bit signed integer.
    - *
    - * Timeouts over this time return immediately in many browsers, due to integer
    - * overflow.  Such known browsers include Firefox, Chrome, and Safari, but not
    - * IE.
    - *
    - * @type {number}
    - * @private
    - */
    -goog.testing.MockClock.MAX_INT_ = 2147483647;
    -
    -
    -/**
    - * Schedules a function to be called after {@code millis} milliseconds.
    - * Mock implementation for setTimeout.
    - * @param {Function} funcToCall The function to call.
    - * @param {number=} opt_millis The number of milliseconds to call it after.
    - * @return {number} The number of timeouts created.
    - * @private
    - */
    -goog.testing.MockClock.prototype.setTimeout_ = function(
    -    funcToCall, opt_millis) {
    -  var millis = opt_millis || 0;
    -  if (millis > goog.testing.MockClock.MAX_INT_) {
    -    throw Error(
    -        'Bad timeout value: ' + millis + '.  Timeouts over MAX_INT ' +
    -        '(24.8 days) cause timeouts to be fired ' +
    -        'immediately in most browsers, except for IE.');
    -  }
    -  this.timeoutsMade_ = this.timeoutsMade_ + 1;
    -  this.scheduleFunction_(this.timeoutsMade_, funcToCall, millis, false);
    -  return this.timeoutsMade_;
    -};
    -
    -
    -/**
    - * Schedules a function to be called every {@code millis} milliseconds.
    - * Mock implementation for setInterval.
    - * @param {Function} funcToCall The function to call.
    - * @param {number=} opt_millis The number of milliseconds between calls.
    - * @return {number} The number of timeouts created.
    - * @private
    - */
    -goog.testing.MockClock.prototype.setInterval_ =
    -    function(funcToCall, opt_millis) {
    -  var millis = opt_millis || 0;
    -  this.timeoutsMade_ = this.timeoutsMade_ + 1;
    -  this.scheduleFunction_(this.timeoutsMade_, funcToCall, millis, true);
    -  return this.timeoutsMade_;
    -};
    -
    -
    -/**
    - * Schedules a function to be called when an animation frame is triggered.
    - * Mock implementation for requestAnimationFrame.
    - * @param {Function} funcToCall The function to call.
    - * @return {number} The number of timeouts created.
    - * @private
    - */
    -goog.testing.MockClock.prototype.requestAnimationFrame_ = function(funcToCall) {
    -  return this.setTimeout_(goog.bind(function() {
    -    if (funcToCall) {
    -      funcToCall(this.getCurrentTime());
    -    } else if (goog.global.mozRequestAnimationFrame) {
    -      var event = new goog.testing.events.Event('MozBeforePaint', goog.global);
    -      event['timeStamp'] = this.getCurrentTime();
    -      goog.testing.events.fireBrowserEvent(event);
    -    }
    -  }, this), goog.testing.MockClock.REQUEST_ANIMATION_FRAME_TIMEOUT);
    -};
    -
    -
    -/**
    - * Schedules a function to be called immediately after the current JS
    - * execution.
    - * Mock implementation for setImmediate.
    - * @param {Function} funcToCall The function to call.
    - * @return {number} The number of timeouts created.
    - * @private
    - */
    -goog.testing.MockClock.prototype.setImmediate_ = function(funcToCall) {
    -  return this.setTimeout_(funcToCall, 0);
    -};
    -
    -
    -/**
    - * Clears a timeout.
    - * Mock implementation for clearTimeout.
    - * @param {number} timeoutKey The timeout key to clear.
    - * @private
    - */
    -goog.testing.MockClock.prototype.clearTimeout_ = function(timeoutKey) {
    -  // Some common libraries register static state with timers.
    -  // This is bad. It leads to all sorts of crazy test problems where
    -  // 1) Test A sets up a new mock clock and a static timer.
    -  // 2) Test B sets up a new mock clock, but re-uses the static timer
    -  //    from Test A.
    -  // 3) A timeout key from test A gets cleared, breaking a timeout in
    -  //    Test B.
    -  //
    -  // For now, we just hackily fail silently if someone tries to clear a timeout
    -  // key before we've allocated it.
    -  // Ideally, we should throw an exception if we see this happening.
    -  //
    -  // TODO(chrishenry): We might also try allocating timeout ids from a global
    -  // pool rather than a local pool.
    -  if (this.isTimeoutSet(timeoutKey)) {
    -    this.deletedKeys_[timeoutKey] = true;
    -  }
    -};
    -
    -
    -/**
    - * Clears an interval.
    - * Mock implementation for clearInterval.
    - * @param {number} timeoutKey The interval key to clear.
    - * @private
    - */
    -goog.testing.MockClock.prototype.clearInterval_ = function(timeoutKey) {
    -  this.clearTimeout_(timeoutKey);
    -};
    -
    -
    -/**
    - * Clears a requestAnimationFrame.
    - * Mock implementation for cancelRequestAnimationFrame.
    - * @param {number} timeoutKey The requestAnimationFrame key to clear.
    - * @private
    - */
    -goog.testing.MockClock.prototype.cancelRequestAnimationFrame_ =
    -    function(timeoutKey) {
    -  this.clearTimeout_(timeoutKey);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/mockclock_test.html b/src/database/third_party/closure-library/closure/goog/testing/mockclock_test.html
    deleted file mode 100644
    index a729a15912b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/mockclock_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.testing.MockClock
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.MockClockTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/mockclock_test.js b/src/database/third_party/closure-library/closure/goog/testing/mockclock_test.js
    deleted file mode 100644
    index 8a71ca12695..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/mockclock_test.js
    +++ /dev/null
    @@ -1,610 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.MockClockTest');
    -goog.setTestOnly('goog.testing.MockClockTest');
    -
    -goog.require('goog.Promise');
    -goog.require('goog.Timer');
    -goog.require('goog.events');
    -goog.require('goog.functions');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -
    -var stubs = new goog.testing.PropertyReplacer();
    -
    -function tearDown() {
    -  stubs.reset();
    -}
    -
    -function testMockClockWasInstalled() {
    -  var clock = new goog.testing.MockClock();
    -  var originalTimeout = window.setTimeout;
    -  clock.install();
    -  assertNotEquals(window.setTimeout, originalTimeout);
    -  setTimeout(function() {}, 100);
    -  assertEquals(1, clock.getTimeoutsMade());
    -  setInterval(function() {}, 200);
    -  assertEquals(2, clock.getTimeoutsMade());
    -  clock.uninstall();
    -  assertEquals(window.setTimeout, originalTimeout);
    -  assertNull(clock.replacer_);
    -}
    -
    -
    -function testSetTimeoutAndTick() {
    -  var clock = new goog.testing.MockClock(true);
    -  var m5 = false, m10 = false, m15 = false, m20 = false;
    -  setTimeout(function() { m5 = true; }, 5);
    -  setTimeout(function() { m10 = true; }, 10);
    -  setTimeout(function() { m15 = true; }, 15);
    -  setTimeout(function() { m20 = true; }, 20);
    -  assertEquals(4, clock.getTimeoutsMade());
    -
    -  assertEquals(4, clock.tick(4));
    -  assertEquals(4, clock.getCurrentTime());
    -
    -  assertFalse(m5);
    -  assertFalse(m10);
    -  assertFalse(m15);
    -  assertFalse(m20);
    -
    -  assertEquals(5, clock.tick(1));
    -  assertEquals(5, clock.getCurrentTime());
    -
    -  assertTrue('m5 should now be true', m5);
    -  assertFalse(m10);
    -  assertFalse(m15);
    -  assertFalse(m20);
    -
    -  assertEquals(10, clock.tick(5));
    -  assertEquals(10, clock.getCurrentTime());
    -
    -  assertTrue('m5 should be true', m5);
    -  assertTrue('m10 should now be true', m10);
    -  assertFalse(m15);
    -  assertFalse(m20);
    -
    -  assertEquals(15, clock.tick(5));
    -  assertEquals(15, clock.getCurrentTime());
    -
    -  assertTrue('m5 should be true', m5);
    -  assertTrue('m10 should be true', m10);
    -  assertTrue('m15 should now be true', m15);
    -  assertFalse(m20);
    -
    -  assertEquals(20, clock.tick(5));
    -  assertEquals(20, clock.getCurrentTime());
    -
    -  assertTrue('m5 should be true', m5);
    -  assertTrue('m10 should be true', m10);
    -  assertTrue('m15 should be true', m15);
    -  assertTrue('m20 should now be true', m20);
    -
    -  clock.uninstall();
    -}
    -
    -
    -function testSetImmediateAndTick() {
    -  var clock = new goog.testing.MockClock(true);
    -  var tick0 = false;
    -  var tick1 = false;
    -  setImmediate(function() { tick0 = true; });
    -  setImmediate(function() { tick1 = true; });
    -  assertEquals(2, clock.getTimeoutsMade());
    -
    -  clock.tick(0);
    -  assertTrue(tick0);
    -  assertTrue(tick1);
    -
    -  clock.uninstall();
    -}
    -
    -
    -function testSetInterval() {
    -  var clock = new goog.testing.MockClock(true);
    -  var times = 0;
    -  setInterval(function() { times++; }, 100);
    -
    -  clock.tick(500);
    -  assertEquals(5, times);
    -  clock.tick(100);
    -  assertEquals(6, times);
    -  clock.tick(100);
    -  assertEquals(7, times);
    -  clock.tick(50);
    -  assertEquals(7, times);
    -  clock.tick(50);
    -  assertEquals(8, times);
    -
    -  clock.uninstall();
    -}
    -
    -
    -function testRequestAnimationFrame() {
    -  goog.global.requestAnimationFrame = function() {
    -  };
    -  var clock = new goog.testing.MockClock(true);
    -  var times = [];
    -  var recFunc = goog.testing.recordFunction(function(now) {
    -    times.push(now);
    -  });
    -  goog.global.requestAnimationFrame(recFunc);
    -  clock.tick(50);
    -  assertEquals(1, recFunc.getCallCount());
    -  assertEquals(20, times[0]);
    -
    -  goog.global.requestAnimationFrame(recFunc);
    -  clock.tick(100);
    -  assertEquals(2, recFunc.getCallCount());
    -  assertEquals(70, times[1]);
    -
    -  clock.uninstall();
    -}
    -
    -
    -function testClearTimeout() {
    -  var clock = new goog.testing.MockClock(true);
    -  var ran = false;
    -  var c = setTimeout(function() { ran = true; }, 100);
    -  clock.tick(50);
    -  assertFalse(ran);
    -  clearTimeout(c);
    -  clock.tick(100);
    -  assertFalse(ran);
    -  clock.uninstall();
    -}
    -
    -
    -function testClearInterval() {
    -  var clock = new goog.testing.MockClock(true);
    -  var times = 0;
    -  var c = setInterval(function() { times++; }, 100);
    -
    -  clock.tick(500);
    -  assertEquals(5, times);
    -  clock.tick(100);
    -  assertEquals(6, times);
    -  clock.tick(100);
    -  clearInterval(c);
    -  assertEquals(7, times);
    -  clock.tick(50);
    -  assertEquals(7, times);
    -  clock.tick(50);
    -  assertEquals(7, times);
    -
    -  clock.uninstall();
    -}
    -
    -
    -function testClearInterval2() {
    -  // Tests that we can clear the interval from inside the function
    -  var clock = new goog.testing.MockClock(true);
    -  var times = 0;
    -  var c = setInterval(function() {
    -    times++;
    -    if (times == 6) {
    -      clearInterval(c);
    -    }
    -  }, 100);
    -
    -  clock.tick(500);
    -  assertEquals(5, times);
    -  clock.tick(100);
    -  assertEquals(6, times);
    -  clock.tick(100);
    -  assertEquals(6, times);
    -  clock.tick(50);
    -  assertEquals(6, times);
    -  clock.tick(50);
    -  assertEquals(6, times);
    -
    -  clock.uninstall();
    -}
    -
    -
    -function testCancelRequestAnimationFrame() {
    -  goog.global.requestAnimationFrame = function() {
    -  };
    -  goog.global.cancelRequestAnimationFrame = function() {
    -  };
    -  var clock = new goog.testing.MockClock(true);
    -  var ran = false;
    -  var c = goog.global.requestAnimationFrame(function() { ran = true; });
    -  clock.tick(10);
    -  assertFalse(ran);
    -  goog.global.cancelRequestAnimationFrame(c);
    -  clock.tick(20);
    -  assertFalse(ran);
    -  clock.uninstall();
    -}
    -
    -
    -function testMockGoogNow() {
    -  assertNotEquals(0, goog.now());
    -  var clock = new goog.testing.MockClock(true);
    -  assertEquals(0, goog.now());
    -  clock.tick(50);
    -  assertEquals(50, goog.now());
    -  clock.uninstall();
    -  assertNotEquals(50, goog.now());
    -}
    -
    -
    -function testTimeoutDelay() {
    -  var clock = new goog.testing.MockClock(true);
    -  var m5 = false, m10 = false, m20 = false;
    -  setTimeout(function() { m5 = true; }, 5);
    -  setTimeout(function() { m10 = true; }, 10);
    -  setTimeout(function() { m20 = true; }, 20);
    -
    -  // Fire 3ms early, so m5 fires at t=2
    -  clock.setTimeoutDelay(-3);
    -  clock.tick(1);
    -  assertFalse(m5);
    -  assertFalse(m10);
    -  clock.tick(1);
    -  assertTrue(m5);
    -  assertFalse(m10);
    -
    -  // Fire 3ms late, so m10 fires at t=13
    -  clock.setTimeoutDelay(3);
    -  assertEquals(12, clock.tick(10));
    -  assertEquals(12, clock.getCurrentTime());
    -  assertFalse(m10);
    -  clock.tick(1);
    -  assertTrue(m10);
    -  assertFalse(m20);
    -
    -  // Fire 10ms early, so m20 fires now, since it's after t=10
    -  clock.setTimeoutDelay(-10);
    -  assertFalse(m20);
    -  assertEquals(14, clock.tick(1));
    -  assertEquals(14, clock.getCurrentTime());
    -  assertTrue(m20);
    -
    -  clock.uninstall();
    -}
    -
    -
    -function testTimerCallbackCanCreateIntermediateTimer() {
    -  var clock = new goog.testing.MockClock(true);
    -  var sequence = [];
    -
    -  // Create 3 timers: 1, 2, and 3.  Timer 1 should fire at T=1, timer 2 at
    -  // T=2, and timer 3 at T=3.  The catch: Timer 2 is created by the
    -  // callback within timer 0.
    -
    -  // Testing method: Create a simple string sequencing each timer and at
    -  // what time it fired.
    -
    -  setTimeout(function() {
    -    sequence.push('timer1 at T=' + goog.now());
    -    setTimeout(function() {
    -      sequence.push('timer2 at T=' + goog.now());
    -    }, 1);
    -  }, 1);
    -
    -  setTimeout(function() {
    -    sequence.push('timer3 at T=' + goog.now());
    -  }, 3);
    -
    -  clock.tick(4);
    -
    -  assertEquals(
    -      'Each timer should fire in sequence at the correct time.',
    -      'timer1 at T=1, timer2 at T=2, timer3 at T=3',
    -      sequence.join(', '));
    -
    -  clock.uninstall();
    -}
    -
    -
    -function testCorrectArgumentsPassedToCallback() {
    -  var clock = new goog.testing.MockClock(true);
    -  var timeoutId;
    -  var timeoutExecuted = false;
    -
    -  timeoutId = setTimeout(function(arg) {
    -    assertEquals('"this" must be goog.global',
    -        goog.global, this);
    -    assertEquals('The timeout ID must be the first parameter',
    -        timeoutId, arg);
    -    assertEquals('Exactly one argument must be passed',
    -        1, arguments.length);
    -    timeoutExecuted = true;
    -  }, 1);
    -
    -  clock.tick(4);
    -
    -  assertTrue('The timeout was not executed', timeoutExecuted);
    -
    -  clock.uninstall();
    -}
    -
    -
    -function testTickZero() {
    -  var clock = new goog.testing.MockClock(true);
    -  var calls = 0;
    -
    -  setTimeout(function() {
    -    assertEquals('I need to be first', 0, calls);
    -    calls++;
    -  }, 0);
    -
    -  setTimeout(function() {
    -    assertEquals('I need to be second', 1, calls);
    -    calls++;
    -  }, 0);
    -
    -  clock.tick(0);
    -  assertEquals(2, calls);
    -
    -  setTimeout(function() {
    -    assertEquals('I need to be third', 2, calls);
    -    calls++;
    -  }, 0);
    -
    -  clock.tick(0);
    -  assertEquals(3, calls);
    -
    -  assertEquals('Time should still be zero', 0, goog.now());
    -
    -  clock.uninstall();
    -}
    -
    -
    -function testReset() {
    -  var clock = new goog.testing.MockClock(true);
    -
    -  setTimeout(function() {
    -    fail('Timeouts should be cleared after a reset');
    -  }, 0);
    -
    -  clock.reset();
    -  clock.tick(999999);
    -  clock.uninstall();
    -}
    -
    -
    -function testQueueInsertionHelper() {
    -  var queue = [];
    -
    -  function queueToString() {
    -    var buffer = [];
    -    for (var i = 0; i < queue.length; i++) {
    -      buffer.push(queue[i].runAtMillis);
    -    }
    -    return buffer.join(',');
    -  }
    -
    -  goog.testing.MockClock.insert_({runAtMillis: 2}, queue);
    -  assertEquals('Only item',
    -      '2', queueToString());
    -
    -  goog.testing.MockClock.insert_({runAtMillis: 4}, queue);
    -  assertEquals('Biggest item',
    -      '4,2', queueToString());
    -
    -  goog.testing.MockClock.insert_({runAtMillis: 5}, queue);
    -  assertEquals('An even bigger item',
    -      '5,4,2', queueToString());
    -
    -  goog.testing.MockClock.insert_({runAtMillis: 1}, queue);
    -  assertEquals('Smallest item',
    -      '5,4,2,1', queueToString());
    -
    -  goog.testing.MockClock.insert_({runAtMillis: 1, dup: true}, queue);
    -  assertEquals('Duplicate smallest item',
    -      '5,4,2,1,1', queueToString());
    -  assertTrue('Duplicate item comes at a smaller index', queue[3].dup);
    -
    -  goog.testing.MockClock.insert_({runAtMillis: 3}, queue);
    -  goog.testing.MockClock.insert_({runAtMillis: 3, dup: true}, queue);
    -  assertEquals('Duplicate a middle item',
    -      '5,4,3,3,2,1,1', queueToString());
    -  assertTrue('Duplicate item comes at a smaller index', queue[2].dup);
    -}
    -
    -
    -function testIsTimeoutSet() {
    -  var clock = new goog.testing.MockClock(true);
    -  var timeoutKey = setTimeout(function() {}, 1);
    -  assertTrue('Timeout ' + timeoutKey + ' should be set',
    -      clock.isTimeoutSet(timeoutKey));
    -  var nextTimeoutKey = timeoutKey + 1;
    -  assertFalse('Timeout ' + nextTimeoutKey + ' should not be set',
    -      clock.isTimeoutSet(nextTimeoutKey));
    -  clearTimeout(timeoutKey);
    -  assertFalse('Timeout ' + timeoutKey + ' should no longer be set',
    -      clock.isTimeoutSet(timeoutKey));
    -  var newTimeoutKey = setTimeout(function() {}, 1);
    -  clock.tick(5);
    -  assertFalse('Timeout ' + timeoutKey + ' should not be set',
    -      clock.isTimeoutSet(timeoutKey));
    -  assertTrue('Timeout ' + newTimeoutKey + ' should be set',
    -      clock.isTimeoutSet(newTimeoutKey));
    -  clock.uninstall();
    -}
    -
    -
    -function testBalksOnTimeoutsGreaterThanMaxInt() {
    -  // Browsers have trouble with timeout greater than max int, so we
    -  // want Mock Clock to fail if this happens.
    -  var clock = new goog.testing.MockClock(true);
    -  // Functions on window don't seem to be able to throw exceptions in
    -  // IE6.  Explicitly reading the property makes it work.
    -  var setTimeout = window.setTimeout;
    -  assertThrows('Timeouts > MAX_INT should fail',
    -      function() {
    -        setTimeout(goog.nullFunction, 2147483648);
    -      });
    -  assertThrows('Timeouts much greater than MAX_INT should fail',
    -      function() {
    -        setTimeout(goog.nullFunction, 2147483648 * 10);
    -      });
    -  clock.uninstall();
    -}
    -
    -
    -function testCorrectSetTimeoutIsRestored() {
    -  var safe = goog.functions.error('should not have been called');
    -  stubs.set(window, 'setTimeout', safe);
    -
    -  var clock = new goog.testing.MockClock(true);
    -  assertNotEquals('setTimeout is replaced', safe, window.setTimeout);
    -  clock.uninstall();
    -  // NOTE: If this assertion proves to be flaky in IE, the string value of
    -  // the two functions have to be compared as described in
    -  // goog.testing.TestCase#finalize.
    -  assertEquals('setTimeout is restored', safe, window.setTimeout);
    -}
    -
    -
    -function testMozRequestAnimationFrame() {
    -  // Setting this function will indirectly tell the mock clock to mock it out.
    -  stubs.set(window, 'mozRequestAnimationFrame', goog.nullFunction);
    -
    -  var clock = new goog.testing.MockClock(true);
    -
    -  var mozBeforePaint = goog.testing.recordFunction();
    -  goog.events.listen(window, 'MozBeforePaint', mozBeforePaint);
    -
    -  window.mozRequestAnimationFrame(null);
    -  assertEquals(0, mozBeforePaint.getCallCount());
    -
    -  clock.tick(goog.testing.MockClock.REQUEST_ANIMATION_FRAME_TIMEOUT);
    -  assertEquals(1, mozBeforePaint.getCallCount());
    -  clock.dispose();
    -}
    -
    -
    -function testClearBeforeSet() {
    -  var clock = new goog.testing.MockClock(true);
    -  var expectedId = 1;
    -  window.clearTimeout(expectedId);
    -
    -  var fn = goog.testing.recordFunction();
    -  var actualId = window.setTimeout(fn, 0);
    -  assertEquals(
    -      'In order for this test to work, we have to guess the ids in advance',
    -      expectedId, actualId);
    -  clock.tick(1);
    -  assertEquals(1, fn.getCallCount());
    -  clock.dispose();
    -}
    -
    -
    -function testNonFunctionArguments() {
    -  var clock = new goog.testing.MockClock(true);
    -
    -  // Unlike normal setTimeout and friends, we only accept functions (not
    -  // strings, not undefined, etc). Make sure that if we get a non-function, we
    -  // fail early rather than on the next .tick() operation.
    -
    -  assertThrows('setTimeout with a non-function value should fail',
    -      function() {
    -        window.setTimeout(undefined, 0);
    -      });
    -  clock.tick(1);
    -
    -  assertThrows('setTimeout with a string should fail',
    -      function() {
    -        window.setTimeout('throw new Error("setTimeout string eval!");', 0);
    -      });
    -  clock.tick(1);
    -
    -  clock.dispose();
    -}
    -
    -
    -function testUnspecifiedTimeout() {
    -  var clock = new goog.testing.MockClock(true);
    -  var m0a = false, m0b = false, m10 = false;
    -  setTimeout(function() { m0a = true; });
    -  setTimeout(function() { m10 = true; }, 10);
    -  assertEquals(2, clock.getTimeoutsMade());
    -
    -  assertFalse(m0a);
    -  assertFalse(m0b);
    -  assertFalse(m10);
    -
    -  assertEquals(0, clock.tick(0));
    -  assertEquals(0, clock.getCurrentTime());
    -
    -  assertTrue(m0a);
    -  assertFalse(m0b);
    -  assertFalse(m10);
    -
    -  setTimeout(function() { m0b = true; });
    -  assertEquals(3, clock.getTimeoutsMade());
    -
    -  assertEquals(0, clock.tick(0));
    -  assertEquals(0, clock.getCurrentTime());
    -
    -  assertTrue(m0a);
    -  assertTrue(m0b);
    -  assertFalse(m10);
    -
    -  assertEquals(10, clock.tick(10));
    -  assertEquals(10, clock.getCurrentTime());
    -
    -  assertTrue(m0a);
    -  assertTrue(m0b);
    -  assertTrue(m10);
    -
    -  clock.uninstall();
    -}
    -
    -
    -function testUnspecifiedInterval() {
    -  var clock = new goog.testing.MockClock(true);
    -  var times = 0;
    -  var handle = setInterval(function() {
    -    if (++times >= 5) {
    -      clearInterval(handle);
    -    }
    -  });
    -
    -  clock.tick(0);
    -  assertEquals(5, times);
    -
    -  clock.uninstall();
    -}
    -
    -
    -function testTickPromise() {
    -  var clock = new goog.testing.MockClock(true);
    -
    -  var p = goog.Promise.resolve('foo');
    -  assertEquals('foo', clock.tickPromise(p));
    -
    -  var rejected = goog.Promise.reject(new Error('failed'));
    -  var e = assertThrows(function() {
    -    clock.tickPromise(rejected);
    -  });
    -  assertEquals('failed', e.message);
    -
    -  var delayed = goog.Timer.promise(500, 'delayed');
    -  e = assertThrows(function() {
    -    clock.tickPromise(delayed);
    -  });
    -  assertEquals('Promise was expected to be resolved after mock clock tick.',
    -      e.message);
    -  assertEquals('delayed', clock.tickPromise(delayed, 500));
    -
    -  clock.dispose();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/mockcontrol.js b/src/database/third_party/closure-library/closure/goog/testing/mockcontrol.js
    deleted file mode 100644
    index 0e2e3bc73a1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/mockcontrol.js
    +++ /dev/null
    @@ -1,220 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A MockControl holds a set of mocks for a particular test.
    - * It consolidates calls to $replay, $verify, and $tearDown, which simplifies
    - * the test and helps avoid omissions.
    - *
    - * You can create and control a mock:
    - *   var mockFoo = mockControl.addMock(new MyMock(Foo));
    - *
    - * MockControl also exposes some convenience functions that create
    - * controlled mocks for common mocks: StrictMock, LooseMock,
    - * FunctionMock, MethodMock, and GlobalFunctionMock.
    - *
    - */
    -
    -
    -goog.provide('goog.testing.MockControl');
    -
    -goog.require('goog.array');
    -goog.require('goog.testing');
    -goog.require('goog.testing.LooseMock');
    -goog.require('goog.testing.StrictMock');
    -
    -
    -
    -/**
    - * Controls a set of mocks.  Controlled mocks are replayed, verified, and
    - * cleaned-up at the same time.
    - * @constructor
    - */
    -goog.testing.MockControl = function() {
    -  /**
    -   * The list of mocks being controlled.
    -   * @type {Array<goog.testing.MockInterface>}
    -   * @private
    -   */
    -  this.mocks_ = [];
    -};
    -
    -
    -/**
    - * Takes control of this mock.
    - * @param {goog.testing.MockInterface} mock Mock to be controlled.
    - * @return {goog.testing.MockInterface} The same mock passed in,
    - *     for convenience.
    - */
    -goog.testing.MockControl.prototype.addMock = function(mock) {
    -  this.mocks_.push(mock);
    -  return mock;
    -};
    -
    -
    -/**
    - * Calls replay on each controlled mock.
    - */
    -goog.testing.MockControl.prototype.$replayAll = function() {
    -  goog.array.forEach(this.mocks_, function(m) {
    -    m.$replay();
    -  });
    -};
    -
    -
    -/**
    - * Calls reset on each controlled mock.
    - */
    -goog.testing.MockControl.prototype.$resetAll = function() {
    -  goog.array.forEach(this.mocks_, function(m) {
    -    m.$reset();
    -  });
    -};
    -
    -
    -/**
    - * Calls verify on each controlled mock.
    - */
    -goog.testing.MockControl.prototype.$verifyAll = function() {
    -  goog.array.forEach(this.mocks_, function(m) {
    -    m.$verify();
    -  });
    -};
    -
    -
    -/**
    - * Calls tearDown on each controlled mock, if necesssary.
    - */
    -goog.testing.MockControl.prototype.$tearDown = function() {
    -  goog.array.forEach(this.mocks_, function(m) {
    -    // $tearDown if defined.
    -    if (m.$tearDown) {
    -      m.$tearDown();
    -    }
    -    // TODO(user): Somehow determine if verifyAll should have been called
    -    // but was not.
    -  });
    -};
    -
    -
    -/**
    - * Creates a controlled StrictMock.  Passes its arguments through to the
    - * StrictMock constructor.
    - * @param {Object|Function} objectToMock The object that should be mocked, or
    - *    the constructor of an object to mock.
    - * @param {boolean=} opt_mockStaticMethods An optional argument denoting that
    - *     a mock should be constructed from the static functions of a class.
    - * @param {boolean=} opt_createProxy An optional argument denoting that
    - *     a proxy for the target mock should be created.
    - * @return {!goog.testing.StrictMock} The mock object.
    - */
    -goog.testing.MockControl.prototype.createStrictMock = function(
    -    objectToMock, opt_mockStaticMethods, opt_createProxy) {
    -  var m = new goog.testing.StrictMock(objectToMock, opt_mockStaticMethods,
    -                                      opt_createProxy);
    -  this.addMock(m);
    -  return m;
    -};
    -
    -
    -/**
    - * Creates a controlled LooseMock.  Passes its arguments through to the
    - * LooseMock constructor.
    - * @param {Object|Function} objectToMock The object that should be mocked, or
    - *    the constructor of an object to mock.
    - * @param {boolean=} opt_ignoreUnexpectedCalls Whether to ignore unexpected
    - *     calls.
    - * @param {boolean=} opt_mockStaticMethods An optional argument denoting that
    - *     a mock should be constructed from the static functions of a class.
    - * @param {boolean=} opt_createProxy An optional argument denoting that
    - *     a proxy for the target mock should be created.
    - * @return {!goog.testing.LooseMock} The mock object.
    - */
    -goog.testing.MockControl.prototype.createLooseMock = function(
    -    objectToMock, opt_ignoreUnexpectedCalls,
    -    opt_mockStaticMethods, opt_createProxy) {
    -  var m = new goog.testing.LooseMock(objectToMock, opt_ignoreUnexpectedCalls,
    -                                     opt_mockStaticMethods, opt_createProxy);
    -  this.addMock(m);
    -  return m;
    -};
    -
    -
    -/**
    - * Creates a controlled FunctionMock.  Passes its arguments through to the
    - * FunctionMock constructor.
    - * @param {string=} opt_functionName The optional name of the function to mock
    - *     set to '[anonymous mocked function]' if not passed in.
    - * @param {number=} opt_strictness One of goog.testing.Mock.LOOSE or
    - *     goog.testing.Mock.STRICT. The default is STRICT.
    - * @return {goog.testing.MockInterface} The mocked function.
    - */
    -goog.testing.MockControl.prototype.createFunctionMock = function(
    -    opt_functionName, opt_strictness) {
    -  var m = goog.testing.createFunctionMock(opt_functionName, opt_strictness);
    -  this.addMock(m);
    -  return m;
    -};
    -
    -
    -/**
    - * Creates a controlled MethodMock.  Passes its arguments through to the
    - * MethodMock constructor.
    - * @param {Object} scope The scope of the method to be mocked out.
    - * @param {string} functionName The name of the function we're going to mock.
    - * @param {number=} opt_strictness One of goog.testing.Mock.LOOSE or
    - *     goog.testing.Mock.STRICT. The default is STRICT.
    - * @return {!goog.testing.MockInterface} The mocked method.
    - */
    -goog.testing.MockControl.prototype.createMethodMock = function(
    -    scope, functionName, opt_strictness) {
    -  var m = goog.testing.createMethodMock(scope, functionName, opt_strictness);
    -  this.addMock(m);
    -  return m;
    -};
    -
    -
    -/**
    - * Creates a controlled MethodMock for a constructor.  Passes its arguments
    - * through to the MethodMock constructor. See
    - * {@link goog.testing.createConstructorMock} for details.
    - * @param {Object} scope The scope of the constructor to be mocked out.
    - * @param {string} constructorName The name of the function we're going to mock.
    - * @param {number=} opt_strictness One of goog.testing.Mock.LOOSE or
    - *     goog.testing.Mock.STRICT. The default is STRICT.
    - * @return {!goog.testing.MockInterface} The mocked method.
    - */
    -goog.testing.MockControl.prototype.createConstructorMock = function(
    -    scope, constructorName, opt_strictness) {
    -  var m = goog.testing.createConstructorMock(scope, constructorName,
    -                                             opt_strictness);
    -  this.addMock(m);
    -  return m;
    -};
    -
    -
    -/**
    - * Creates a controlled GlobalFunctionMock.  Passes its arguments through to the
    - * GlobalFunctionMock constructor.
    - * @param {string} functionName The name of the function we're going to mock.
    - * @param {number=} opt_strictness One of goog.testing.Mock.LOOSE or
    - *     goog.testing.Mock.STRICT. The default is STRICT.
    - * @return {goog.testing.MockInterface} The mocked function.
    - */
    -goog.testing.MockControl.prototype.createGlobalFunctionMock = function(
    -    functionName, opt_strictness) {
    -  var m = goog.testing.createGlobalFunctionMock(functionName, opt_strictness);
    -  this.addMock(m);
    -  return m;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/mockcontrol_test.html b/src/database/third_party/closure-library/closure/goog/testing/mockcontrol_test.html
    deleted file mode 100644
    index 193f6283b97..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/mockcontrol_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.testing.MockControl
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.MockControlTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/mockcontrol_test.js b/src/database/third_party/closure-library/closure/goog/testing/mockcontrol_test.js
    deleted file mode 100644
    index a73e538b4a8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/mockcontrol_test.js
    +++ /dev/null
    @@ -1,121 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.MockControlTest');
    -goog.setTestOnly('goog.testing.MockControlTest');
    -
    -goog.require('goog.testing.Mock');
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.jsunit');
    -
    -// Emulate the behavior of a mock.
    -function MockMock() {
    -  this.replayCalled = false;
    -  this.resetCalled = false;
    -  this.verifyCalled = false;
    -  this.tearDownCalled = false;
    -}
    -
    -MockMock.prototype.$replay = function() {
    -  this.replayCalled = true;
    -};
    -
    -MockMock.prototype.$reset = function() {
    -  this.resetCalled = true;
    -};
    -
    -MockMock.prototype.$verify = function() {
    -  this.verifyCalled = true;
    -};
    -
    -function setUp() {
    -  var mock = new goog.testing.Mock(MockMock);
    -}
    -
    -function testAdd() {
    -  var mockMock = new MockMock();
    -
    -  var control = new goog.testing.MockControl();
    -  assertEquals(mockMock, control.addMock(mockMock));
    -}
    -
    -function testReplayAll() {
    -  var mockMock1 = new MockMock();
    -  var mockMock2 = new MockMock();
    -  var mockMockExcluded = new MockMock();
    -
    -  var control = new goog.testing.MockControl();
    -  control.addMock(mockMock1);
    -  control.addMock(mockMock2);
    -
    -  control.$replayAll();
    -  assertTrue(mockMock1.replayCalled);
    -  assertTrue(mockMock2.replayCalled);
    -  assertFalse(mockMockExcluded.replayCalled);
    -}
    -
    -function testResetAll() {
    -  var mockMock1 = new MockMock();
    -  var mockMock2 = new MockMock();
    -  var mockMockExcluded = new MockMock();
    -
    -  var control = new goog.testing.MockControl();
    -  control.addMock(mockMock1);
    -  control.addMock(mockMock2);
    -
    -  control.$resetAll();
    -  assertTrue(mockMock1.resetCalled);
    -  assertTrue(mockMock2.resetCalled);
    -  assertFalse(mockMockExcluded.resetCalled);
    -}
    -
    -function testVerifyAll() {
    -  var mockMock1 = new MockMock();
    -  var mockMock2 = new MockMock();
    -  var mockMockExcluded = new MockMock();
    -
    -  var control = new goog.testing.MockControl();
    -  control.addMock(mockMock1);
    -  control.addMock(mockMock2);
    -
    -  control.$verifyAll();
    -  assertTrue(mockMock1.verifyCalled);
    -  assertTrue(mockMock2.verifyCalled);
    -  assertFalse(mockMockExcluded.verifyCalled);
    -}
    -
    -function testTearDownAll() {
    -  var mockMock1 = new MockMock();
    -  var mockMock2 = new MockMock();
    -  var mockMockExcluded = new MockMock();
    -
    -  // $tearDown is optional.
    -  mockMock2.$tearDown = function() {
    -    this.tearDownCalled = true;
    -  };
    -  mockMockExcluded.$tearDown = function() {
    -    this.tearDownCalled = true;
    -  };
    -
    -  var control = new goog.testing.MockControl();
    -  control.addMock(mockMock1);
    -  control.addMock(mockMock2);
    -
    -  control.$tearDown();
    -
    -  // mockMock2 has a tearDown method and is in the control.
    -  assertTrue(mockMock2.tearDownCalled);
    -  assertFalse(mockMock1.tearDownCalled);
    -  assertFalse(mockMockExcluded.tearDownCalled);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/mockinterface.js b/src/database/third_party/closure-library/closure/goog/testing/mockinterface.js
    deleted file mode 100644
    index 1a534702677..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/mockinterface.js
    +++ /dev/null
    @@ -1,45 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview An interface that all mocks should share.
    - * @author nicksantos@google.com (Nick Santos)
    - */
    -
    -goog.provide('goog.testing.MockInterface');
    -
    -
    -
    -/** @interface */
    -goog.testing.MockInterface = function() {};
    -
    -
    -/**
    - * Write down all the expected functions that have been called on the
    - * mock so far. From here on out, future function calls will be
    - * compared against this list.
    - */
    -goog.testing.MockInterface.prototype.$replay = function() {};
    -
    -
    -/**
    - * Reset the mock.
    - */
    -goog.testing.MockInterface.prototype.$reset = function() {};
    -
    -
    -/**
    - * Assert that the expected function calls match the actual calls.
    - */
    -goog.testing.MockInterface.prototype.$verify = function() {};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/mockmatchers.js b/src/database/third_party/closure-library/closure/goog/testing/mockmatchers.js
    deleted file mode 100644
    index a0545f73ab9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/mockmatchers.js
    +++ /dev/null
    @@ -1,400 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Matchers to be used with the mock utilities.  They allow for
    - * flexible matching by type.  Custom matchers can be created by passing a
    - * matcher function into an ArgumentMatcher instance.
    - *
    - * For examples, please see the unit test.
    - *
    - */
    -
    -
    -goog.provide('goog.testing.mockmatchers');
    -goog.provide('goog.testing.mockmatchers.ArgumentMatcher');
    -goog.provide('goog.testing.mockmatchers.IgnoreArgument');
    -goog.provide('goog.testing.mockmatchers.InstanceOf');
    -goog.provide('goog.testing.mockmatchers.ObjectEquals');
    -goog.provide('goog.testing.mockmatchers.RegexpMatch');
    -goog.provide('goog.testing.mockmatchers.SaveArgument');
    -goog.provide('goog.testing.mockmatchers.TypeOf');
    -
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.testing.asserts');
    -
    -
    -
    -/**
    - * A simple interface for executing argument matching.  A match in this case is
    - * testing to see if a supplied object fits a given criteria.  True is returned
    - * if the given criteria is met.
    - * @param {Function=} opt_matchFn A function that evaluates a given argument
    - *     and returns true if it meets a given criteria.
    - * @param {?string=} opt_matchName The name expressing intent as part of
    - *      an error message for when a match fails.
    - * @constructor
    - */
    -goog.testing.mockmatchers.ArgumentMatcher =
    -    function(opt_matchFn, opt_matchName) {
    -  /**
    -   * A function that evaluates a given argument and returns true if it meets a
    -   * given criteria.
    -   * @type {Function}
    -   * @private
    -   */
    -  this.matchFn_ = opt_matchFn || null;
    -
    -  /**
    -   * A string indicating the match intent (e.g. isBoolean or isString).
    -   * @type {?string}
    -   * @private
    -   */
    -  this.matchName_ = opt_matchName || null;
    -};
    -
    -
    -/**
    - * A function that takes a match argument and an optional MockExpectation
    - * which (if provided) will get error information and returns whether or
    - * not it matches.
    - * @param {*} toVerify The argument that should be verified.
    - * @param {goog.testing.MockExpectation?=} opt_expectation The expectation
    - *     for this match.
    - * @return {boolean} Whether or not a given argument passes verification.
    - */
    -goog.testing.mockmatchers.ArgumentMatcher.prototype.matches =
    -    function(toVerify, opt_expectation) {
    -  if (this.matchFn_) {
    -    var isamatch = this.matchFn_(toVerify);
    -    if (!isamatch && opt_expectation) {
    -      if (this.matchName_) {
    -        opt_expectation.addErrorMessage('Expected: ' +
    -            this.matchName_ + ' but was: ' + _displayStringForValue(toVerify));
    -      } else {
    -        opt_expectation.addErrorMessage('Expected: missing mockmatcher' +
    -            ' description but was: ' +
    -            _displayStringForValue(toVerify));
    -      }
    -    }
    -    return isamatch;
    -  } else {
    -    throw Error('No match function defined for this mock matcher');
    -  }
    -};
    -
    -
    -
    -/**
    - * A matcher that verifies that an argument is an instance of a given class.
    - * @param {Function} ctor The class that will be used for verification.
    - * @constructor
    - * @extends {goog.testing.mockmatchers.ArgumentMatcher}
    - * @final
    - */
    -goog.testing.mockmatchers.InstanceOf = function(ctor) {
    -  goog.testing.mockmatchers.ArgumentMatcher.call(this,
    -      function(obj) {
    -        return obj instanceof ctor;
    -        // NOTE: Browser differences on ctor.toString() output
    -        // make using that here problematic. So for now, just let
    -        // people know the instanceOf() failed without providing
    -        // browser specific details...
    -      }, 'instanceOf()');
    -};
    -goog.inherits(goog.testing.mockmatchers.InstanceOf,
    -    goog.testing.mockmatchers.ArgumentMatcher);
    -
    -
    -
    -/**
    - * A matcher that verifies that an argument is of a given type (e.g. "object").
    - * @param {string} type The type that a given argument must have.
    - * @constructor
    - * @extends {goog.testing.mockmatchers.ArgumentMatcher}
    - * @final
    - */
    -goog.testing.mockmatchers.TypeOf = function(type) {
    -  goog.testing.mockmatchers.ArgumentMatcher.call(this,
    -      function(obj) {
    -        return goog.typeOf(obj) == type;
    -      }, 'typeOf(' + type + ')');
    -};
    -goog.inherits(goog.testing.mockmatchers.TypeOf,
    -    goog.testing.mockmatchers.ArgumentMatcher);
    -
    -
    -
    -/**
    - * A matcher that verifies that an argument matches a given RegExp.
    - * @param {RegExp} regexp The regular expression that the argument must match.
    - * @constructor
    - * @extends {goog.testing.mockmatchers.ArgumentMatcher}
    - * @final
    - */
    -goog.testing.mockmatchers.RegexpMatch = function(regexp) {
    -  goog.testing.mockmatchers.ArgumentMatcher.call(this,
    -      function(str) {
    -        return regexp.test(str);
    -      }, 'match(' + regexp + ')');
    -};
    -goog.inherits(goog.testing.mockmatchers.RegexpMatch,
    -    goog.testing.mockmatchers.ArgumentMatcher);
    -
    -
    -
    -/**
    - * A matcher that always returns true. It is useful when the user does not care
    - * for some arguments.
    - * For example: mockFunction('username', 'password', IgnoreArgument);
    - * @constructor
    - * @extends {goog.testing.mockmatchers.ArgumentMatcher}
    - * @final
    - */
    -goog.testing.mockmatchers.IgnoreArgument = function() {
    -  goog.testing.mockmatchers.ArgumentMatcher.call(this,
    -      function() {
    -        return true;
    -      }, 'true');
    -};
    -goog.inherits(goog.testing.mockmatchers.IgnoreArgument,
    -    goog.testing.mockmatchers.ArgumentMatcher);
    -
    -
    -
    -/**
    - * A matcher that verifies that the argument is an object that equals the given
    - * expected object, using a deep comparison.
    - * @param {Object} expectedObject An object to match against when
    - *     verifying the argument.
    - * @constructor
    - * @extends {goog.testing.mockmatchers.ArgumentMatcher}
    - */
    -goog.testing.mockmatchers.ObjectEquals = function(expectedObject) {
    -  goog.testing.mockmatchers.ArgumentMatcher.call(this,
    -      function(matchObject) {
    -        assertObjectEquals('Expected equal objects', expectedObject,
    -            matchObject);
    -        return true;
    -      }, 'objectEquals(' + expectedObject + ')');
    -};
    -goog.inherits(goog.testing.mockmatchers.ObjectEquals,
    -    goog.testing.mockmatchers.ArgumentMatcher);
    -
    -
    -/** @override */
    -goog.testing.mockmatchers.ObjectEquals.prototype.matches =
    -    function(toVerify, opt_expectation) {
    -  // Override the default matches implementation to capture the exception thrown
    -  // by assertObjectEquals (if any) and add that message to the expectation.
    -  try {
    -    return goog.testing.mockmatchers.ObjectEquals.superClass_.matches.call(
    -        this, toVerify, opt_expectation);
    -  } catch (e) {
    -    if (opt_expectation) {
    -      opt_expectation.addErrorMessage(e.message);
    -    }
    -    return false;
    -  }
    -};
    -
    -
    -
    -/**
    - * A matcher that saves the argument that it is verifying so that your unit test
    - * can perform extra tests with this argument later.  For example, if the
    - * argument is a callback method, the unit test can then later call this
    - * callback to test the asynchronous portion of the call.
    - * @param {goog.testing.mockmatchers.ArgumentMatcher|Function=} opt_matcher
    - *     Argument matcher or matching function that will be used to validate the
    - *     argument.  By default, argument will always be valid.
    - * @param {?string=} opt_matchName The name expressing intent as part of
    - *      an error message for when a match fails.
    - * @constructor
    - * @extends {goog.testing.mockmatchers.ArgumentMatcher}
    - * @final
    - */
    -goog.testing.mockmatchers.SaveArgument = function(opt_matcher, opt_matchName) {
    -  goog.testing.mockmatchers.ArgumentMatcher.call(
    -      this, /** @type {Function} */ (opt_matcher), opt_matchName);
    -
    -  if (opt_matcher instanceof goog.testing.mockmatchers.ArgumentMatcher) {
    -    /**
    -     * Delegate match requests to this matcher.
    -     * @type {goog.testing.mockmatchers.ArgumentMatcher}
    -     * @private
    -     */
    -    this.delegateMatcher_ = opt_matcher;
    -  } else if (!opt_matcher) {
    -    this.delegateMatcher_ = goog.testing.mockmatchers.ignoreArgument;
    -  }
    -};
    -goog.inherits(goog.testing.mockmatchers.SaveArgument,
    -    goog.testing.mockmatchers.ArgumentMatcher);
    -
    -
    -/** @override */
    -goog.testing.mockmatchers.SaveArgument.prototype.matches = function(
    -    toVerify, opt_expectation) {
    -  this.arg = toVerify;
    -  if (this.delegateMatcher_) {
    -    return this.delegateMatcher_.matches(toVerify, opt_expectation);
    -  }
    -  return goog.testing.mockmatchers.SaveArgument.superClass_.matches.call(
    -      this, toVerify, opt_expectation);
    -};
    -
    -
    -/**
    - * Saved argument that was verified.
    - * @type {*}
    - */
    -goog.testing.mockmatchers.SaveArgument.prototype.arg;
    -
    -
    -/**
    - * An instance of the IgnoreArgument matcher. Returns true for all matches.
    - * @type {goog.testing.mockmatchers.IgnoreArgument}
    - */
    -goog.testing.mockmatchers.ignoreArgument =
    -    new goog.testing.mockmatchers.IgnoreArgument();
    -
    -
    -/**
    - * A matcher that verifies that an argument is an array.
    - * @type {goog.testing.mockmatchers.ArgumentMatcher}
    - */
    -goog.testing.mockmatchers.isArray =
    -    new goog.testing.mockmatchers.ArgumentMatcher(goog.isArray,
    -        'isArray');
    -
    -
    -/**
    - * A matcher that verifies that an argument is a array-like.  A NodeList is an
    - * example of a collection that is very close to an array.
    - * @type {goog.testing.mockmatchers.ArgumentMatcher}
    - */
    -goog.testing.mockmatchers.isArrayLike =
    -    new goog.testing.mockmatchers.ArgumentMatcher(goog.isArrayLike,
    -        'isArrayLike');
    -
    -
    -/**
    - * A matcher that verifies that an argument is a date-like.
    - * @type {goog.testing.mockmatchers.ArgumentMatcher}
    - */
    -goog.testing.mockmatchers.isDateLike =
    -    new goog.testing.mockmatchers.ArgumentMatcher(goog.isDateLike,
    -        'isDateLike');
    -
    -
    -/**
    - * A matcher that verifies that an argument is a string.
    - * @type {goog.testing.mockmatchers.ArgumentMatcher}
    - */
    -goog.testing.mockmatchers.isString =
    -    new goog.testing.mockmatchers.ArgumentMatcher(goog.isString,
    -        'isString');
    -
    -
    -/**
    - * A matcher that verifies that an argument is a boolean.
    - * @type {goog.testing.mockmatchers.ArgumentMatcher}
    - */
    -goog.testing.mockmatchers.isBoolean =
    -    new goog.testing.mockmatchers.ArgumentMatcher(goog.isBoolean,
    -        'isBoolean');
    -
    -
    -/**
    - * A matcher that verifies that an argument is a number.
    - * @type {goog.testing.mockmatchers.ArgumentMatcher}
    - */
    -goog.testing.mockmatchers.isNumber =
    -    new goog.testing.mockmatchers.ArgumentMatcher(goog.isNumber,
    -        'isNumber');
    -
    -
    -/**
    - * A matcher that verifies that an argument is a function.
    - * @type {goog.testing.mockmatchers.ArgumentMatcher}
    - */
    -goog.testing.mockmatchers.isFunction =
    -    new goog.testing.mockmatchers.ArgumentMatcher(goog.isFunction,
    -        'isFunction');
    -
    -
    -/**
    - * A matcher that verifies that an argument is an object.
    - * @type {goog.testing.mockmatchers.ArgumentMatcher}
    - */
    -goog.testing.mockmatchers.isObject =
    -    new goog.testing.mockmatchers.ArgumentMatcher(goog.isObject,
    -        'isObject');
    -
    -
    -/**
    - * A matcher that verifies that an argument is like a DOM node.
    - * @type {goog.testing.mockmatchers.ArgumentMatcher}
    - */
    -goog.testing.mockmatchers.isNodeLike =
    -    new goog.testing.mockmatchers.ArgumentMatcher(goog.dom.isNodeLike,
    -        'isNodeLike');
    -
    -
    -/**
    - * A function that checks to see if an array matches a given set of
    - * expectations.  The expectations array can be a mix of ArgumentMatcher
    - * implementations and values.  True will be returned if values are identical or
    - * if a matcher returns a positive result.
    - * @param {Array<?>} expectedArr An array of expectations which can be either
    - *     values to check for equality or ArgumentMatchers.
    - * @param {Array<?>} arr The array to match.
    - * @param {goog.testing.MockExpectation?=} opt_expectation The expectation
    - *     for this match.
    - * @return {boolean} Whether or not the given array matches the expectations.
    - */
    -goog.testing.mockmatchers.flexibleArrayMatcher =
    -    function(expectedArr, arr, opt_expectation) {
    -  return goog.array.equals(expectedArr, arr, function(a, b) {
    -    var errCount = 0;
    -    if (opt_expectation) {
    -      errCount = opt_expectation.getErrorMessageCount();
    -    }
    -    var isamatch = a === b ||
    -        a instanceof goog.testing.mockmatchers.ArgumentMatcher &&
    -        a.matches(b, opt_expectation);
    -    var failureMessage = null;
    -    if (!isamatch) {
    -      failureMessage = goog.testing.asserts.findDifferences(a, b);
    -      isamatch = !failureMessage;
    -    }
    -    if (!isamatch && opt_expectation) {
    -      // If the error count changed, the match sent out an error
    -      // message. If the error count has not changed, then
    -      // we need to send out an error message...
    -      if (errCount == opt_expectation.getErrorMessageCount()) {
    -        // Use the _displayStringForValue() from assert.js
    -        // for consistency...
    -        if (!failureMessage) {
    -          failureMessage = 'Expected: ' + _displayStringForValue(a) +
    -              ' but was: ' + _displayStringForValue(b);
    -        }
    -        opt_expectation.addErrorMessage(failureMessage);
    -      }
    -    }
    -    return isamatch;
    -  });
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/mockmatchers_test.html b/src/database/third_party/closure-library/closure/goog/testing/mockmatchers_test.html
    deleted file mode 100644
    index f56b54f47be..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/mockmatchers_test.html
    +++ /dev/null
    @@ -1,28 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -
    -  @author earmbrust@google.com (Erick Armbrust)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.testing.mockmatchers
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.mockmatchersTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="someDiv">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/mockmatchers_test.js b/src/database/third_party/closure-library/closure/goog/testing/mockmatchers_test.js
    deleted file mode 100644
    index 68d8e252450..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/mockmatchers_test.js
    +++ /dev/null
    @@ -1,378 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.mockmatchersTest');
    -goog.setTestOnly('goog.testing.mockmatchersTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.mockmatchers');
    -goog.require('goog.testing.mockmatchers.ArgumentMatcher');
    -
    -// A local reference to the mockmatchers namespace.
    -var matchers = goog.testing.mockmatchers;
    -
    -// Simple classes to test the InstanceOf matcher.
    -var foo = function() {};
    -var bar = function() {};
    -
    -// Simple class to test adding error messages to
    -// MockExpectation objects
    -function MockMock() {
    -  this.errorMessages = [];
    -}
    -
    -var mockExpect = null;
    -
    -MockMock.prototype.addErrorMessage = function(msg) {
    -  this.errorMessages.push(msg);
    -};
    -
    -
    -MockMock.prototype.getErrorMessageCount = function() {
    -  return this.errorMessages.length;
    -};
    -
    -
    -function setUp() {
    -  mockExpect = new MockMock();
    -}
    -
    -
    -function testNoMatchName() {
    -  // A matcher that does not fill in the match name
    -  var matcher = new goog.testing.mockmatchers.ArgumentMatcher(goog.isString);
    -
    -  // Make sure the lack of match name doesn't affect the ability
    -  // to return True/False
    -  assertTrue(matcher.matches('hello'));
    -  assertFalse(matcher.matches(123));
    -
    -  // Make sure we handle the lack of a match name
    -  assertFalse(matcher.matches(456, mockExpect));
    -  assertEquals(1, mockExpect.errorMessages.length);
    -  assertEquals('Expected: missing mockmatcher description ' +
    -      'but was: <456> (Number)', mockExpect.errorMessages[0]);
    -}
    -
    -
    -function testInstanceOf() {
    -  var matcher = new matchers.InstanceOf(foo);
    -  assertTrue(matcher.matches(new foo()));
    -  assertFalse(matcher.matches(new bar()));
    -
    -  assertFalse(matcher.matches(new bar(), mockExpect));
    -  assertEquals(1, mockExpect.errorMessages.length);
    -  assertEquals('Expected: instanceOf() ' +
    -      'but was: <[object Object]> (Object)',
    -      mockExpect.errorMessages[0]);
    -}
    -
    -
    -function testTypeOf() {
    -  var matcher = new matchers.TypeOf('number');
    -  assertTrue(matcher.matches(1));
    -  assertTrue(matcher.matches(2));
    -  assertFalse(matcher.matches('test'));
    -
    -  assertFalse(matcher.matches(true, mockExpect));
    -  assertEquals(1, mockExpect.errorMessages.length);
    -  assertEquals('Expected: typeOf(number) but was: <true> (Boolean)',
    -      mockExpect.errorMessages[0]);
    -}
    -
    -
    -function testRegexpMatch() {
    -  var matcher = new matchers.RegexpMatch(/^cho[dtp]/);
    -  assertTrue(matcher.matches('chodhop'));
    -  assertTrue(matcher.matches('chopper'));
    -  assertFalse(matcher.matches('chocolate'));
    -  assertFalse(matcher.matches(null));
    -
    -  assertFalse(matcher.matches('an anger', mockExpect));
    -  assertEquals(1, mockExpect.errorMessages.length);
    -  assertEquals('Expected: match(/^cho[dtp]/) but was: <an anger> (String)',
    -      mockExpect.errorMessages[0]);
    -}
    -
    -
    -function testObjectEquals() {
    -  // Test a simple match.
    -  var simpleMatcher = new matchers.ObjectEquals({name: 'Bob', age: 42});
    -  assertTrue(simpleMatcher.matches({name: 'Bob', age: 42}, mockExpect));
    -  assertEquals(0, mockExpect.getErrorMessageCount());
    -  expectObjectEqualsFailure(simpleMatcher, {name: 'Bill', age: 42},
    -      'name: Expected <Bob> (String) but was <Bill> (String)');
    -  expectObjectEqualsFailure(simpleMatcher, {name: 'Bob', age: 21},
    -      'age: Expected <42> (Number) but was <21> (Number)');
    -  expectObjectEqualsFailure(simpleMatcher, {name: 'Bob'},
    -      'property age not present in actual Object');
    -  expectObjectEqualsFailure(simpleMatcher,
    -      {name: 'Bob', age: 42, country: 'USA'},
    -      'property country not present in expected Object');
    -
    -  // Multiple mismatches should include multiple messages.
    -  expectObjectEqualsFailure(simpleMatcher, {name: 'Jim', age: 36},
    -      'name: Expected <Bob> (String) but was <Jim> (String)\n' +
    -      '   age: Expected <42> (Number) but was <36> (Number)');
    -}
    -
    -function testComplexObjectEquals() {
    -  var complexMatcher = new matchers.ObjectEquals(
    -      {a: 'foo', b: 2, c: ['bar', 3], d: {sub1: 'baz', sub2: -1}});
    -  assertTrue(complexMatcher.matches(
    -      {a: 'foo', b: 2, c: ['bar', 3], d: {sub1: 'baz', sub2: -1}}));
    -  expectObjectEqualsFailure(complexMatcher,
    -      {a: 'foo', b: 2, c: ['bar', 3], d: {sub1: 'zap', sub2: -1}},
    -      'sub1: Expected <baz> (String) but was <zap> (String)');
    -  expectObjectEqualsFailure(complexMatcher,
    -      {a: 'foo', b: 2, c: ['bar', 6], d: {sub1: 'baz', sub2: -1}},
    -      'c[1]: Expected <3> (Number) but was <6> (Number)');
    -}
    -
    -
    -function testSaveArgument() {
    -  var saveMatcher = new matchers.SaveArgument();
    -  assertTrue(saveMatcher.matches(42));
    -  assertEquals(42, saveMatcher.arg);
    -
    -  saveMatcher = new matchers.SaveArgument(goog.isString);
    -  assertTrue(saveMatcher.matches('test'));
    -  assertEquals('test', saveMatcher.arg);
    -  assertFalse(saveMatcher.matches(17));
    -  assertEquals(17, saveMatcher.arg);
    -
    -  saveMatcher = new matchers.SaveArgument(new matchers.ObjectEquals({
    -    value: 'value'
    -  }));
    -  assertTrue(saveMatcher.matches({ value: 'value' }));
    -  assertEquals('value', saveMatcher.arg.value);
    -  assertFalse(saveMatcher.matches('test'));
    -  assertEquals('test', saveMatcher.arg);
    -}
    -
    -
    -function testIsArray() {
    -  assertTrue(matchers.isArray.matches([]));
    -  assertTrue(matchers.isArray.matches(new Array()));
    -  assertFalse(matchers.isArray.matches('test'));
    -
    -  assertFalse(matchers.isArray.matches({}, mockExpect));
    -  assertEquals(1, mockExpect.errorMessages.length);
    -  assertEquals('Expected: isArray but was: <[object Object]> (Object)',
    -      mockExpect.errorMessages[0]);
    -}
    -
    -
    -function testIsArrayLike() {
    -  var nodeList = (function() {
    -    var div = document.createElement('div');
    -    div.appendChild(document.createElement('p'));
    -    div.appendChild(document.createElement('p'));
    -    return div.getElementsByTagName('div');
    -  })();
    -
    -  assertTrue(matchers.isArrayLike.matches([]));
    -  assertTrue(matchers.isArrayLike.matches(new Array()));
    -  assertTrue(matchers.isArrayLike.matches(nodeList));
    -  assertFalse(matchers.isArrayLike.matches('test'));
    -
    -  assertFalse(matchers.isArrayLike.matches(3, mockExpect));
    -  assertEquals(1, mockExpect.errorMessages.length);
    -  assertEquals('Expected: isArrayLike but was: <3> (Number)',
    -      mockExpect.errorMessages[0]);
    -}
    -
    -
    -function testIsDateLike() {
    -  assertTrue(matchers.isDateLike.matches(new Date()));
    -  assertFalse(matchers.isDateLike.matches('test'));
    -
    -  assertFalse(matchers.isDateLike.matches('test', mockExpect));
    -  assertEquals(1, mockExpect.errorMessages.length);
    -  assertEquals('Expected: isDateLike but was: <test> (String)',
    -      mockExpect.errorMessages[0]);
    -}
    -
    -
    -function testIsString() {
    -  assertTrue(matchers.isString.matches('a'));
    -  assertTrue(matchers.isString.matches('b'));
    -  assertFalse(matchers.isString.matches(null));
    -
    -  assertFalse(matchers.isString.matches(null, mockExpect));
    -  assertEquals(1, mockExpect.errorMessages.length);
    -  assertEquals('Expected: isString but was: <null>',
    -      mockExpect.errorMessages[0]);
    -}
    -
    -
    -function testIsBoolean() {
    -  assertTrue(matchers.isBoolean.matches(true));
    -  assertTrue(matchers.isBoolean.matches(false));
    -  assertFalse(matchers.isBoolean.matches(null));
    -
    -  assertFalse(matchers.isBoolean.matches([], mockExpect));
    -  assertEquals(1, mockExpect.errorMessages.length);
    -  assertEquals('Expected: isBoolean but was: <> (Array)',
    -      mockExpect.errorMessages[0]);
    -}
    -
    -
    -function testIsNumber() {
    -  assertTrue(matchers.isNumber.matches(-1));
    -  assertTrue(matchers.isNumber.matches(1));
    -  assertTrue(matchers.isNumber.matches(1.25));
    -  assertFalse(matchers.isNumber.matches(null));
    -
    -  assertFalse(matchers.isNumber.matches('hello', mockExpect));
    -  assertEquals(1, mockExpect.errorMessages.length);
    -  assertEquals('Expected: isNumber but was: <hello> (String)',
    -      mockExpect.errorMessages[0]);
    -}
    -
    -
    -function testIsFunction() {
    -  assertTrue(matchers.isFunction.matches(function() {}));
    -  assertFalse(matchers.isFunction.matches('test'));
    -
    -  assertFalse(matchers.isFunction.matches({}, mockExpect));
    -  assertEquals(1, mockExpect.errorMessages.length);
    -  assertEquals('Expected: isFunction but was: <[object Object]> (Object)',
    -      mockExpect.errorMessages[0]);
    -}
    -
    -
    -function testIsObject() {
    -  assertTrue(matchers.isObject.matches({}));
    -  assertTrue(matchers.isObject.matches(new Object()));
    -  assertTrue(matchers.isObject.matches(new function() {}));
    -  assertTrue(matchers.isObject.matches([]));
    -  assertTrue(matchers.isObject.matches(new Array()));
    -  assertTrue(matchers.isObject.matches(function() {}));
    -  assertFalse(matchers.isObject.matches(null));
    -
    -  assertFalse(matchers.isObject.matches(1234, mockExpect));
    -  assertEquals(1, mockExpect.errorMessages.length);
    -  assertEquals('Expected: isObject but was: <1234> (Number)',
    -      mockExpect.errorMessages[0]);
    -}
    -
    -
    -function testIsNodeLike() {
    -  assertFalse(matchers.isNodeLike.matches({}));
    -  assertFalse(matchers.isNodeLike.matches(1));
    -  assertFalse(matchers.isNodeLike.matches(function() {}));
    -  assertFalse(matchers.isNodeLike.matches(false));
    -  assertTrue(matchers.isNodeLike.matches(document.body));
    -  assertTrue(matchers.isNodeLike.matches(goog.dom.getElement('someDiv')));
    -
    -  assertFalse(matchers.isNodeLike.matches('test', mockExpect));
    -  assertEquals(1, mockExpect.errorMessages.length);
    -  assertEquals('Expected: isNodeLike but was: <test> (String)',
    -      mockExpect.errorMessages[0]);
    -}
    -
    -
    -function testIgnoreArgumentsMatcher() {
    -  // ignoreArgument always returns true:
    -  assertTrue(matchers.ignoreArgument.matches());
    -  assertTrue(matchers.ignoreArgument.matches(356));
    -  assertTrue(matchers.ignoreArgument.matches('str'));
    -  assertTrue(matchers.ignoreArgument.matches(['array', 123, false]));
    -  assertTrue(matchers.ignoreArgument.matches({'map': 1, key2: 'value2'}));
    -}
    -
    -
    -function testFlexibleArrayMatcher() {
    -  // Test that basic lists are verified properly.
    -  var a1 = [1, 'test'];
    -  var a2 = [1, 'test'];
    -  var a3 = [1, 'test', 'extra'];
    -  assertTrue(matchers.flexibleArrayMatcher(a1, a2));
    -  assertFalse(matchers.flexibleArrayMatcher(a1, a3));
    -
    -  // Test that basic lists with basic class instances are verified properly.
    -  var instance = new foo();
    -  a1 = [1, 'test', instance];
    -  a2 = [1, 'test', instance];
    -  a3 = [1, 'test', new foo()];
    -  assertTrue(matchers.flexibleArrayMatcher(a1, a2));
    -  assertTrue(matchers.flexibleArrayMatcher(a1, a3));
    -
    -  // Create an argument verifier that returns a consistent value.
    -  var verifyValue = true;
    -  var argVerifier = function() {};
    -  goog.inherits(argVerifier, matchers.ArgumentMatcher);
    -  argVerifier.prototype.matches = function(arg) {
    -    return verifyValue;
    -  };
    -
    -  // Test that the arguments are always verified when the verifier returns
    -  // true.
    -  a1 = [1, 'test', new argVerifier()];
    -  a2 = [1, 'test', 'anything'];
    -  a3 = [1, 'test', 12345];
    -  assertTrue(matchers.flexibleArrayMatcher(a1, a2));
    -  assertTrue(matchers.flexibleArrayMatcher(a1, a3));
    -
    -  // Now test the case when then verifier returns false.
    -  verifyValue = false;
    -  assertFalse(matchers.flexibleArrayMatcher(a1, a2));
    -  assertFalse(matchers.flexibleArrayMatcher(a1, a3));
    -
    -  // And test we report errors back up via the opt_expectation
    -  assertFalse(matchers.flexibleArrayMatcher(a2, a3, mockExpect));
    -  assertEquals(1, mockExpect.errorMessages.length);
    -  assertEquals(
    -      'Expected <anything> (String) but was <12345> (Number)\n' +
    -      '    Expected <anything> (String) but was <12345> (Number)',
    -      mockExpect.errorMessages[0]);
    -
    -  // And test we report errors found via the matcher
    -  a1 = [1, goog.testing.mockmatchers.isString];
    -  a2 = [1, 'test string'];
    -  a3 = [1, null];
    -  assertTrue(matchers.flexibleArrayMatcher(a1, a2, mockExpect));
    -  assertFalse(matchers.flexibleArrayMatcher(a1, a3, mockExpect));
    -  // Old error is still there
    -  assertEquals(2, mockExpect.errorMessages.length);
    -  assertEquals(
    -      'Expected <anything> (String) but was <12345> (Number)\n' +
    -      '    Expected <anything> (String) but was <12345> (Number)',
    -      mockExpect.errorMessages[0]);
    -  // plus the new error...
    -  assertEquals('Expected: isString but was: <null>',
    -      mockExpect.errorMessages[1]);
    -}
    -
    -
    -/**
    - * Utility method for checking for an ObjectEquals match failure.  Checks that
    - * the expected error message was included in the error messages appended to
    - * the expectation object.
    - * @param {goog.testing.mockmatchers.ArgumentMatcher.ObjectEquals} matcher
    - *     The matcher to test against.
    - * @param {Object} matchObject The object to compare.
    - * @param {string=} opt_errorMsg The deep object comparison failure message
    - *     to check for.
    - */
    -function expectObjectEqualsFailure(matcher, matchObject, opt_errorMsg) {
    -  mockExpect.errorMessages = [];
    -  assertFalse(matcher.matches(matchObject, mockExpect));
    -  assertNotEquals(0, mockExpect.getErrorMessageCount());
    -  if (opt_errorMsg) {
    -    assertContains(opt_errorMsg, mockExpect.errorMessages[0]);
    -  }
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/mockrandom.js b/src/database/third_party/closure-library/closure/goog/testing/mockrandom.js
    deleted file mode 100644
    index 5c6d77c5161..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/mockrandom.js
    +++ /dev/null
    @@ -1,153 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview MockRandom provides a mechanism for specifying a stream of
    - * numbers to expect from calls to Math.random().
    - *
    - */
    -
    -goog.provide('goog.testing.MockRandom');
    -
    -goog.require('goog.Disposable');
    -
    -
    -
    -/**
    - * Class for unit testing code that uses Math.random.
    - *
    - * @param {Array<number>} sequence The sequence of numbers to return.
    - * @param {boolean=} opt_install Whether to install the MockRandom at
    - *     construction time.
    - * @extends {goog.Disposable}
    - * @constructor
    - * @final
    - */
    -goog.testing.MockRandom = function(sequence, opt_install) {
    -  goog.Disposable.call(this);
    -
    -  /**
    -   * The sequence of numbers to be returned by calls to random()
    -   * @type {Array<number>}
    -   * @private
    -   */
    -  this.sequence_ = sequence || [];
    -
    -  /**
    -   * The original Math.random function.
    -   * @type {function(): number}
    -   * @private
    -   */
    -  this.mathRandom_ = Math.random;
    -
    -  /**
    -   * Whether to throw an exception when Math.random() is called when there is
    -   * nothing left in the sequence.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.strictlyFromSequence_ = false;
    -
    -  if (opt_install) {
    -    this.install();
    -  }
    -};
    -goog.inherits(goog.testing.MockRandom, goog.Disposable);
    -
    -
    -/**
    - * Whether this MockRandom has been installed.
    - * @type {boolean}
    - * @private
    - */
    -goog.testing.MockRandom.prototype.installed_;
    -
    -
    -/**
    - * Installs this MockRandom as the system number generator.
    - */
    -goog.testing.MockRandom.prototype.install = function() {
    -  if (!this.installed_) {
    -    Math.random = goog.bind(this.random, this);
    -    this.installed_ = true;
    -  }
    -};
    -
    -
    -/**
    - * @return {number} The next number in the sequence. If there are no more values
    - *     left, this will return a random number, unless
    - *     {@code this.strictlyFromSequence_} is true, in which case an error will
    - *     be thrown.
    - */
    -goog.testing.MockRandom.prototype.random = function() {
    -  if (this.hasMoreValues()) {
    -    return this.sequence_.shift();
    -  }
    -  if (this.strictlyFromSequence_) {
    -    throw new Error('No numbers left in sequence.');
    -  }
    -  return this.mathRandom_();
    -};
    -
    -
    -/**
    - * @return {boolean} Whether there are more numbers left in the sequence.
    - */
    -goog.testing.MockRandom.prototype.hasMoreValues = function() {
    -  return this.sequence_.length > 0;
    -};
    -
    -
    -/**
    - * Injects new numbers into the beginning of the sequence.
    - * @param {Array<number>|number} values Number or array of numbers to inject.
    - */
    -goog.testing.MockRandom.prototype.inject = function(values) {
    -  if (goog.isArray(values)) {
    -    this.sequence_ = values.concat(this.sequence_);
    -  } else {
    -    this.sequence_.splice(0, 0, values);
    -  }
    -};
    -
    -
    -/**
    - * Uninstalls the MockRandom.
    - */
    -goog.testing.MockRandom.prototype.uninstall = function() {
    -  if (this.installed_) {
    -    Math.random = this.mathRandom_;
    -    this.installed_ = false;
    -  }
    -};
    -
    -
    -/** @override */
    -goog.testing.MockRandom.prototype.disposeInternal = function() {
    -  this.uninstall();
    -  delete this.sequence_;
    -  delete this.mathRandom_;
    -  goog.testing.MockRandom.superClass_.disposeInternal.call(this);
    -};
    -
    -
    -/**
    - * @param {boolean} strictlyFromSequence Whether to throw an exception when
    - *     Math.random() is called when there is nothing left in the sequence.
    - */
    -goog.testing.MockRandom.prototype.setStrictlyFromSequence =
    -    function(strictlyFromSequence) {
    -  this.strictlyFromSequence_ = strictlyFromSequence;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/mockrandom_test.html b/src/database/third_party/closure-library/closure/goog/testing/mockrandom_test.html
    deleted file mode 100644
    index 5094264a07d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/mockrandom_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.testing.MockRandom
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.MockRandomTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/mockrandom_test.js b/src/database/third_party/closure-library/closure/goog/testing/mockrandom_test.js
    deleted file mode 100644
    index 73f48967784..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/mockrandom_test.js
    +++ /dev/null
    @@ -1,73 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.MockRandomTest');
    -goog.setTestOnly('goog.testing.MockRandomTest');
    -
    -goog.require('goog.testing.MockRandom');
    -goog.require('goog.testing.jsunit');
    -
    -function testMockRandomInstall() {
    -  var random = new goog.testing.MockRandom([]);
    -  var originalRandom = Math.random;
    -
    -  assertFalse(!!random.installed_);
    -
    -  random.install();
    -  assertTrue(random.installed_);
    -  assertNotEquals(Math.random, originalRandom);
    -
    -  random.uninstall();
    -  assertFalse(random.installed_);
    -  assertEquals(originalRandom, Math.random);
    -}
    -
    -function testMockRandomRandom() {
    -  var random = new goog.testing.MockRandom([], true);
    -
    -  assertFalse(random.hasMoreValues());
    -
    -  random.inject(2);
    -  assertTrue(random.hasMoreValues());
    -  assertEquals(2, Math.random());
    -
    -  random.inject([1, 2, 3]);
    -  assertTrue(random.hasMoreValues());
    -  assertEquals(1, Math.random());
    -  assertEquals(2, Math.random());
    -  assertEquals(3, Math.random());
    -  assertFalse(random.hasMoreValues());
    -  assertNotUndefined(Math.random());
    -}
    -
    -function testRandomStrictlyFromSequence() {
    -  var random = new goog.testing.MockRandom([], /* install */ true);
    -  random.setStrictlyFromSequence(true);
    -  assertFalse(random.hasMoreValues());
    -  assertThrows(function() {
    -    Math.random();
    -  });
    -
    -  random.inject(3);
    -  assertTrue(random.hasMoreValues());
    -  assertNotThrows(function() {
    -    Math.random();
    -  });
    -
    -  random.setStrictlyFromSequence(false);
    -  assertFalse(random.hasMoreValues());
    -  assertNotThrows(function() {
    -    Math.random();
    -  });
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/mockrange.js b/src/database/third_party/closure-library/closure/goog/testing/mockrange.js
    deleted file mode 100644
    index 0e41892b185..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/mockrange.js
    +++ /dev/null
    @@ -1,67 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview LooseMock of goog.dom.AbstractRange.
    - *
    - */
    -
    -goog.provide('goog.testing.MockRange');
    -
    -goog.require('goog.dom.AbstractRange');
    -goog.require('goog.testing.LooseMock');
    -
    -
    -
    -/**
    - * LooseMock of goog.dom.AbstractRange. Useful because the mock framework cannot
    - * simply create a mock out of an abstract class, and cannot create a mock out
    - * of classes that implements __iterator__ because it relies on the default
    - * behavior of iterating through all of an object's properties.
    - * @constructor
    - * @extends {goog.testing.LooseMock}
    - * @final
    - */
    -goog.testing.MockRange = function() {
    -  goog.testing.LooseMock.call(this, goog.testing.MockRange.ConcreteRange_);
    -};
    -goog.inherits(goog.testing.MockRange, goog.testing.LooseMock);
    -
    -
    -// *** Private helper class ************************************************* //
    -
    -
    -
    -/**
    - * Concrete subclass of goog.dom.AbstractRange that simply sets the abstract
    - * method __iterator__ to undefined so that javascript defaults to iterating
    - * through all of the object's properties.
    - * @constructor
    - * @extends {goog.dom.AbstractRange}
    - * @private
    - */
    -goog.testing.MockRange.ConcreteRange_ = function() {
    -  goog.dom.AbstractRange.call(this);
    -};
    -goog.inherits(goog.testing.MockRange.ConcreteRange_, goog.dom.AbstractRange);
    -
    -
    -/**
    - * Undefine the iterator so the mock framework can loop through this class'
    - * properties.
    - * @override
    - */
    -goog.testing.MockRange.ConcreteRange_.prototype.__iterator__ =
    -    // This isn't really type-safe.
    -    /** @type {?} */ (undefined);
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/mockrange_test.html b/src/database/third_party/closure-library/closure/goog/testing/mockrange_test.html
    deleted file mode 100644
    index 172b378a40e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/mockrange_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.testing.MockRange
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.MockRangeTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/mockrange_test.js b/src/database/third_party/closure-library/closure/goog/testing/mockrange_test.js
    deleted file mode 100644
    index c6c9db530f4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/mockrange_test.js
    +++ /dev/null
    @@ -1,35 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.MockRangeTest');
    -goog.setTestOnly('goog.testing.MockRangeTest');
    -
    -goog.require('goog.testing.MockRange');
    -goog.require('goog.testing.jsunit');
    -
    -
    -/**
    - * Tests that a MockRange can be created successfully, a call to a mock
    - * method can be recorded, and the correct behavior replayed and verified.
    - */
    -function testMockMethod() {
    -  var mockRange = new goog.testing.MockRange();
    -  mockRange.getStartOffset().$returns(42);
    -  mockRange.$replay();
    -
    -  assertEquals('Mock method should return recorded value',
    -               42,
    -               mockRange.getStartOffset());
    -  mockRange.$verify();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/mockstorage.js b/src/database/third_party/closure-library/closure/goog/testing/mockstorage.js
    deleted file mode 100644
    index f4e267162a3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/mockstorage.js
    +++ /dev/null
    @@ -1,108 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides a JS storage class implementing the HTML5 Storage
    - * interface.
    - */
    -
    -
    -goog.require('goog.structs.Map');
    -
    -
    -goog.provide('goog.testing.MockStorage');
    -
    -
    -
    -/**
    - * A JS storage instance, implementing the HTML5 Storage interface.
    - * See http://www.w3.org/TR/webstorage/ for details.
    - *
    - * @constructor
    - * @implements {Storage}
    - * @final
    - */
    -goog.testing.MockStorage = function() {
    -  /**
    -   * The underlying storage object.
    -   * @type {goog.structs.Map}
    -   * @private
    -   */
    -  this.store_ = new goog.structs.Map();
    -
    -  /**
    -   * The number of elements in the storage.
    -   * @type {number}
    -   */
    -  this.length = 0;
    -};
    -
    -
    -/**
    - * Sets an item to the storage.
    - * @param {string} key Storage key.
    - * @param {*} value Storage value. Must be convertible to string.
    - * @override
    - */
    -goog.testing.MockStorage.prototype.setItem = function(key, value) {
    -  this.store_.set(key, String(value));
    -  this.length = this.store_.getCount();
    -};
    -
    -
    -/**
    - * Gets an item from the storage.  The item returned is the "structured clone"
    - * of the value from setItem.  In practice this means it's the value cast to a
    - * string.
    - * @param {string} key Storage key.
    - * @return {?string} Storage value for key; null if does not exist.
    - * @override
    - */
    -goog.testing.MockStorage.prototype.getItem = function(key) {
    -  var val = this.store_.get(key);
    -  // Enforce that getItem returns string values.
    -  return (val != null) ? /** @type {string} */ (val) : null;
    -};
    -
    -
    -/**
    - * Removes and item from the storage.
    - * @param {string} key Storage key.
    - * @override
    - */
    -goog.testing.MockStorage.prototype.removeItem = function(key) {
    -  this.store_.remove(key);
    -  this.length = this.store_.getCount();
    -};
    -
    -
    -/**
    - * Clears the storage.
    - * @override
    - */
    -goog.testing.MockStorage.prototype.clear = function() {
    -  this.store_.clear();
    -  this.length = 0;
    -};
    -
    -
    -/**
    - * Returns the key at the given index.
    - * @param {number} index The index for the key.
    - * @return {?string} Key at the given index, null if not found.
    - * @override
    - */
    -goog.testing.MockStorage.prototype.key = function(index) {
    -  return this.store_.getKeys()[index] || null;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/mockstorage_test.html b/src/database/third_party/closure-library/closure/goog/testing/mockstorage_test.html
    deleted file mode 100644
    index ccc87fef757..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/mockstorage_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.testing.MockStorage
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.MockStorageTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/mockstorage_test.js b/src/database/third_party/closure-library/closure/goog/testing/mockstorage_test.js
    deleted file mode 100644
    index a4f686e17b6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/mockstorage_test.js
    +++ /dev/null
    @@ -1,73 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.MockStorageTest');
    -goog.setTestOnly('goog.testing.MockStorageTest');
    -
    -goog.require('goog.testing.MockStorage');
    -goog.require('goog.testing.jsunit');
    -
    -var instance;
    -
    -function setUp() {
    -  instance = new goog.testing.MockStorage();
    -}
    -
    -
    -/**
    - * Tests the MockStorage interface.
    - */
    -function testMockStorage() {
    -  assertEquals(0, instance.length);
    -
    -  instance.setItem('foo', 'bar');
    -  assertEquals(1, instance.length);
    -  assertEquals('bar', instance.getItem('foo'));
    -  assertEquals('foo', instance.key(0));
    -
    -  instance.setItem('foo', 'baz');
    -  assertEquals('baz', instance.getItem('foo'));
    -
    -  instance.setItem('goo', 'gl');
    -  assertEquals(2, instance.length);
    -  assertEquals('gl', instance.getItem('goo'));
    -  assertEquals('goo', instance.key(1));
    -
    -  assertNull(instance.getItem('poogle'));
    -
    -  instance.removeItem('foo');
    -  assertEquals(1, instance.length);
    -  assertEquals('goo', instance.key(0));
    -
    -  instance.setItem('a', 12);
    -  assertEquals('12', instance.getItem('a'));
    -  instance.setItem('b', false);
    -  assertEquals('false', instance.getItem('b'));
    -  instance.setItem('c', {a: 1, b: 12});
    -  assertEquals('[object Object]', instance.getItem('c'));
    -
    -  instance.clear();
    -  assertEquals(0, instance.length);
    -
    -  // Test some special cases.
    -  instance.setItem('emptyString', '');
    -  assertEquals('', instance.getItem('emptyString'));
    -  instance.setItem('isNull', null);
    -  assertEquals('null', instance.getItem('isNull'));
    -  instance.setItem('isUndefined', undefined);
    -  assertEquals('undefined', instance.getItem('isUndefined'));
    -  instance.setItem('', 'empty key');
    -  assertEquals('empty key', instance.getItem(''));
    -  assertEquals(4, instance.length);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/mockuseragent.js b/src/database/third_party/closure-library/closure/goog/testing/mockuseragent.js
    deleted file mode 100644
    index 49db5e61acc..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/mockuseragent.js
    +++ /dev/null
    @@ -1,143 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview MockUserAgent overrides goog.userAgent.getUserAgentString()
    - *     depending on a specified configuration.
    - *
    - */
    -
    -goog.provide('goog.testing.MockUserAgent');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.labs.userAgent.util');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Class for unit testing code that uses goog.userAgent.
    - *
    - * @extends {goog.Disposable}
    - * @constructor
    - * @final
    - */
    -goog.testing.MockUserAgent = function() {
    -  goog.Disposable.call(this);
    -
    -  /**
    -   * Property replacer used to mock out User-Agent functions.
    -   * @type {!goog.testing.PropertyReplacer}
    -   * @private
    -   */
    -  this.propertyReplacer_ = new goog.testing.PropertyReplacer();
    -
    -  /**
    -   * The userAgent string used by goog.userAgent.
    -   * @type {?string}
    -   * @private
    -   */
    -  this.userAgent_ = goog.userAgent.getUserAgentString();
    -
    -  /**
    -   * The navigator object used by goog.userAgent
    -   * @type {Object}
    -   * @private
    -   */
    -  this.navigator_ = goog.userAgent.getNavigator();
    -};
    -goog.inherits(goog.testing.MockUserAgent, goog.Disposable);
    -
    -
    -/**
    - * Whether this MockUserAgent has been installed.
    - * @type {boolean}
    - * @private
    - */
    -goog.testing.MockUserAgent.prototype.installed_;
    -
    -
    -/**
    - * Installs this MockUserAgent.
    - */
    -goog.testing.MockUserAgent.prototype.install = function() {
    -  if (!this.installed_) {
    -    // Stub out user agent functions.
    -    this.propertyReplacer_.set(goog.userAgent, 'getUserAgentString',
    -                               goog.bind(this.getUserAgentString, this));
    -
    -    this.propertyReplacer_.set(goog.labs.userAgent.util, 'getUserAgent',
    -                               goog.bind(this.getUserAgentString, this));
    -
    -    // Stub out navigator functions.
    -    this.propertyReplacer_.set(goog.userAgent, 'getNavigator',
    -                               goog.bind(this.getNavigator, this));
    -
    -    this.installed_ = true;
    -  }
    -};
    -
    -
    -/**
    - * @return {?string} The userAgent set in this class.
    - */
    -goog.testing.MockUserAgent.prototype.getUserAgentString = function() {
    -  return this.userAgent_;
    -};
    -
    -
    -/**
    - * @param {string} userAgent The desired userAgent string to use.
    - */
    -goog.testing.MockUserAgent.prototype.setUserAgentString = function(userAgent) {
    -  this.userAgent_ = userAgent;
    -};
    -
    -
    -/**
    - * @return {Object} The Navigator set in this class.
    - */
    -goog.testing.MockUserAgent.prototype.getNavigator = function() {
    -  return this.navigator_;
    -};
    -
    -
    -/**
    - * @param {Object} navigator The desired Navigator object to use.
    - */
    -goog.testing.MockUserAgent.prototype.setNavigator = function(navigator) {
    -  this.navigator_ = navigator;
    -};
    -
    -
    -/**
    - * Uninstalls the MockUserAgent.
    - */
    -goog.testing.MockUserAgent.prototype.uninstall = function() {
    -  if (this.installed_) {
    -    this.propertyReplacer_.reset();
    -    this.installed_ = false;
    -  }
    -
    -};
    -
    -
    -/** @override */
    -goog.testing.MockUserAgent.prototype.disposeInternal = function() {
    -  this.uninstall();
    -  delete this.propertyReplacer_;
    -  delete this.navigator_;
    -  goog.testing.MockUserAgent.base(this, 'disposeInternal');
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/mockuseragent_test.html b/src/database/third_party/closure-library/closure/goog/testing/mockuseragent_test.html
    deleted file mode 100644
    index 331994c04b5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/mockuseragent_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -
    -  @author andybons@google.com (Andrew Bonventre)
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.testing.MockUserAgent</title>
    -<script src="../base.js"></script>
    -<body>
    -<script>
    -goog.require('goog.testing.MockUserAgentTest');
    -</script>
    -</script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/mockuseragent_test.js b/src/database/third_party/closure-library/closure/goog/testing/mockuseragent_test.js
    deleted file mode 100644
    index 913b3c25ed0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/mockuseragent_test.js
    +++ /dev/null
    @@ -1,73 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.MockUserAgentTest');
    -
    -goog.require('goog.dispose');
    -goog.require('goog.testing.MockUserAgent');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -goog.setTestOnly('goog.testing.MockUserAgentTest');
    -
    -var mockUserAgent;
    -
    -function setUp() {
    -  mockUserAgent = new goog.testing.MockUserAgent();
    -}
    -
    -function tearDown() {
    -  goog.dispose(mockUserAgent);
    -  assertFalse(mockUserAgent.installed_);
    -}
    -
    -function testMockUserAgentInstall() {
    -  var originalUserAgentFunction = goog.userAgent.getUserAgentString;
    -
    -  assertFalse(!!mockUserAgent.installed_);
    -
    -  mockUserAgent.install();
    -  assertTrue(mockUserAgent.installed_);
    -  assertNotEquals(goog.userAgent.getUserAgentString,
    -      originalUserAgentFunction);
    -
    -  mockUserAgent.uninstall();
    -  assertFalse(mockUserAgent.installed_);
    -  assertEquals(originalUserAgentFunction, goog.userAgent.getUserAgentString);
    -}
    -
    -function testMockUserAgentGetAgent() {
    -  var uaString = 'Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) ' +
    -      'AppleWebKit/525.13 (KHTML, like Gecko) ' +
    -      'Chrome/0.2.149.27 Safari/525.13';
    -
    -  mockUserAgent = new goog.testing.MockUserAgent();
    -  mockUserAgent.setUserAgentString(uaString);
    -  mockUserAgent.install();
    -
    -  assertTrue(mockUserAgent.installed_);
    -  assertEquals(uaString, goog.userAgent.getUserAgentString());
    -}
    -
    -function testMockUserAgentNavigator() {
    -  var fakeNavigator = {};
    -
    -  mockUserAgent = new goog.testing.MockUserAgent();
    -  mockUserAgent.setNavigator(fakeNavigator);
    -  mockUserAgent.install();
    -
    -  assertTrue(mockUserAgent.installed_);
    -  assertEquals(fakeNavigator, goog.userAgent.getNavigator());
    -}
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/multitestrunner.js b/src/database/third_party/closure-library/closure/goog/testing/multitestrunner.js
    deleted file mode 100644
    index c7c7246f35f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/multitestrunner.js
    +++ /dev/null
    @@ -1,1450 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Utility for running multiple test files that utilize the same
    - * interface as goog.testing.TestRunner.  Each test is run in series and their
    - * results aggregated.  The main usecase for the MultiTestRunner is to allow
    - * the testing of all tests in a project locally.
    - *
    - */
    -
    -goog.provide('goog.testing.MultiTestRunner');
    -goog.provide('goog.testing.MultiTestRunner.TestFrame');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.functions');
    -goog.require('goog.string');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.ServerChart');
    -goog.require('goog.ui.TableSorter');
    -
    -
    -
    -/**
    - * A component for running multiple tests within the browser.
    - * @param {goog.dom.DomHelper=} opt_domHelper A DOM helper.
    - * @extends {goog.ui.Component}
    - * @constructor
    - * @final
    - */
    -goog.testing.MultiTestRunner = function(opt_domHelper) {
    -  goog.ui.Component.call(this, opt_domHelper);
    -
    -  /**
    -   * Array of tests to execute, when combined with the base path this should be
    -   * a relative path to the test from the page containing the multi testrunner.
    -   * @type {Array<string>}
    -   * @private
    -   */
    -  this.allTests_ = [];
    -
    -  /**
    -   * Tests that match the filter function.
    -   * @type {Array<string>}
    -   * @private
    -   */
    -  this.activeTests_ = [];
    -
    -  /**
    -   * An event handler for handling events.
    -   * @type {goog.events.EventHandler<!goog.testing.MultiTestRunner>}
    -   * @private
    -   */
    -  this.eh_ = new goog.events.EventHandler(this);
    -
    -  /**
    -   * A table sorter for the stats.
    -   * @type {goog.ui.TableSorter}
    -   * @private
    -   */
    -  this.tableSorter_ = new goog.ui.TableSorter(this.dom_);
    -};
    -goog.inherits(goog.testing.MultiTestRunner, goog.ui.Component);
    -
    -
    -/**
    - * Default maximimum amount of time to spend at each stage of the test.
    - * @type {number}
    - */
    -goog.testing.MultiTestRunner.DEFAULT_TIMEOUT_MS = 45 * 1000;
    -
    -
    -/**
    - * Messages corresponding to the numeric states.
    - * @type {Array<string>}
    - */
    -goog.testing.MultiTestRunner.STATES = [
    -  'waiting for test runner',
    -  'initializing tests',
    -  'waiting for tests to finish'
    -];
    -
    -
    -/**
    - * The test suite's name.
    - * @type {string} name
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.name_ = '';
    -
    -
    -/**
    - * The base path used to resolve files within the allTests_ array.
    - * @type {string}
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.basePath_ = '';
    -
    -
    -/**
    - * A set of tests that have finished.  All extant keys map to true.
    - * @type {Object<boolean>}
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.finished_ = null;
    -
    -
    -/**
    - * Whether the report should contain verbose information about the passes.
    - * @type {boolean}
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.verbosePasses_ = false;
    -
    -
    -/**
    - * Whether to hide passing tests completely in the report, makes verbosePasses_
    - * obsolete.
    - * @type {boolean}
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.hidePasses_ = false;
    -
    -
    -/**
    - * Flag used to tell the test runner to stop after the current test.
    - * @type {boolean}
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.stopped_ = false;
    -
    -
    -/**
    - * Flag indicating whether the test runner is active.
    - * @type {boolean}
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.active_ = false;
    -
    -
    -/**
    - * Index of the next test to run.
    - * @type {number}
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.startedCount_ = 0;
    -
    -
    -/**
    - * Count of the results received so far.
    - * @type {number}
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.resultCount_ = 0;
    -
    -
    -/**
    - * Number of passes so far.
    - * @type {number}
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.passes_ = 0;
    -
    -
    -/**
    - * Timestamp for the current start time.
    - * @type {number}
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.startTime_ = 0;
    -
    -
    -/**
    - * Only tests whose paths patch this filter function will be
    - * executed.
    - * @type {function(string): boolean}
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.filterFn_ = goog.functions.TRUE;
    -
    -
    -/**
    - * Number of milliseconds to wait for loading and initialization steps.
    - * @type {number}
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.timeoutMs_ =
    -    goog.testing.MultiTestRunner.DEFAULT_TIMEOUT_MS;
    -
    -
    -/**
    - * An array of objects containing stats about the tests.
    - * @type {Array<Object>?}
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.stats_ = null;
    -
    -
    -/**
    - * Reference to the start button element.
    - * @type {Element}
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.startButtonEl_ = null;
    -
    -
    -/**
    - * Reference to the stop button element.
    - * @type {Element}
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.stopButtonEl_ = null;
    -
    -
    -/**
    - * Reference to the log element.
    - * @type {Element}
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.logEl_ = null;
    -
    -
    -/**
    - * Reference to the report element.
    - * @type {Element}
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.reportEl_ = null;
    -
    -
    -/**
    - * Reference to the stats element.
    - * @type {Element}
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.statsEl_ = null;
    -
    -
    -/**
    - * Reference to the progress bar's element.
    - * @type {Element}
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.progressEl_ = null;
    -
    -
    -/**
    - * Reference to the progress bar's inner row element.
    - * @type {Element}
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.progressRow_ = null;
    -
    -
    -/**
    - * Reference to the log tab.
    - * @type {Element}
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.logTabEl_ = null;
    -
    -
    -/**
    - * Reference to the report tab.
    - * @type {Element}
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.reportTabEl_ = null;
    -
    -
    -/**
    - * Reference to the stats tab.
    - * @type {Element}
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.statsTabEl_ = null;
    -
    -
    -/**
    - * The number of tests to run at a time.
    - * @type {number}
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.poolSize_ = 1;
    -
    -
    -/**
    - * The size of the stats bucket for the number of files loaded histogram.
    - * @type {number}
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.numFilesStatsBucketSize_ = 20;
    -
    -
    -/**
    - * The size of the stats bucket in ms for the run time histogram.
    - * @type {number}
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.runTimeStatsBucketSize_ = 500;
    -
    -
    -/**
    - * Sets the name for the test suite.
    - * @param {string} name The suite's name.
    - * @return {!goog.testing.MultiTestRunner} Instance for chaining.
    - */
    -goog.testing.MultiTestRunner.prototype.setName = function(name) {
    -  this.name_ = name;
    -  return this;
    -};
    -
    -
    -/**
    - * Returns the name for the test suite.
    - * @return {string} The name for the test suite.
    - */
    -goog.testing.MultiTestRunner.prototype.getName = function() {
    -  return this.name_;
    -};
    -
    -
    -/**
    - * Sets the basepath that tests added using addTests are resolved with.
    - * @param {string} path The relative basepath.
    - * @return {!goog.testing.MultiTestRunner} Instance for chaining.
    - */
    -goog.testing.MultiTestRunner.prototype.setBasePath = function(path) {
    -  this.basePath_ = path;
    -  return this;
    -};
    -
    -
    -/**
    - * Returns the basepath that tests added using addTests are resolved with.
    - * @return {string} The basepath that tests added using addTests are resolved
    - *     with.
    - */
    -goog.testing.MultiTestRunner.prototype.getBasePath = function() {
    -  return this.basePath_;
    -};
    -
    -
    -/**
    - * Sets whether the report should contain verbose information for tests that
    - * pass.
    - * @param {boolean} verbose Whether report should be verbose.
    - * @return {!goog.testing.MultiTestRunner} Instance for chaining.
    - */
    -goog.testing.MultiTestRunner.prototype.setVerbosePasses = function(verbose) {
    -  this.verbosePasses_ = verbose;
    -  return this;
    -};
    -
    -
    -/**
    - * Returns whether the report should contain verbose information for tests that
    - * pass.
    - * @return {boolean} Whether the report should contain verbose information for
    - *     tests that pass.
    - */
    -goog.testing.MultiTestRunner.prototype.getVerbosePasses = function() {
    -  return this.verbosePasses_;
    -};
    -
    -
    -/**
    - * Sets whether the report should contain passing tests at all, makes
    - * setVerbosePasses obsolete.
    - * @param {boolean} hide Whether report should not contain passing tests.
    - * @return {!goog.testing.MultiTestRunner} Instance for chaining.
    - */
    -goog.testing.MultiTestRunner.prototype.setHidePasses = function(hide) {
    -  this.hidePasses_ = hide;
    -  return this;
    -};
    -
    -
    -/**
    - * Returns whether the report should contain passing tests at all, makes
    - * setVerbosePasses obsolete.
    - * @return {boolean} Whether the report should contain passing tests at all,
    - *     makes setVerbosePasses obsolete.
    - */
    -goog.testing.MultiTestRunner.prototype.getHidePasses = function() {
    -  return this.hidePasses_;
    -};
    -
    -
    -/**
    - * Sets the bucket sizes for the histograms.
    - * @param {number} f Bucket size for num files loaded histogram.
    - * @param {number} t Bucket size for run time histogram.
    - * @return {!goog.testing.MultiTestRunner} Instance for chaining.
    - */
    -goog.testing.MultiTestRunner.prototype.setStatsBucketSizes = function(f, t) {
    -  this.numFilesStatsBucketSize_ = f;
    -  this.runTimeStatsBucketSize_ = t;
    -  return this;
    -};
    -
    -
    -/**
    - * Sets the number of milliseconds to wait for the page to load, initialize and
    - * run the tests.
    - * @param {number} timeout Time in milliseconds.
    - * @return {!goog.testing.MultiTestRunner} Instance for chaining.
    - */
    -goog.testing.MultiTestRunner.prototype.setTimeout = function(timeout) {
    -  this.timeoutMs_ = timeout;
    -  return this;
    -};
    -
    -
    -/**
    - * Returns the number of milliseconds to wait for the page to load, initialize
    - * and run the tests.
    - * @return {number} The number of milliseconds to wait for the page to load,
    - *     initialize and run the tests.
    - */
    -goog.testing.MultiTestRunner.prototype.getTimeout = function() {
    -  return this.timeoutMs_;
    -};
    -
    -
    -/**
    - * Sets the number of tests that can be run at the same time. This only improves
    - * performance due to the amount of time spent loading the tests.
    - * @param {number} size The number of tests to run at a time.
    - * @return {!goog.testing.MultiTestRunner} Instance for chaining.
    - */
    -goog.testing.MultiTestRunner.prototype.setPoolSize = function(size) {
    -  this.poolSize_ = size;
    -  return this;
    -};
    -
    -
    -/**
    - * Returns the number of tests that can be run at the same time. This only
    - * improves performance due to the amount of time spent loading the tests.
    - * @return {number} The number of tests that can be run at the same time. This
    - *     only improves performance due to the amount of time spent loading the
    - *     tests.
    - */
    -goog.testing.MultiTestRunner.prototype.getPoolSize = function() {
    -  return this.poolSize_;
    -};
    -
    -
    -/**
    - * Sets a filter function. Only test paths that match the filter function
    - * will be executed.
    - * @param {function(string): boolean} filterFn Filters test paths.
    - * @return {!goog.testing.MultiTestRunner} Instance for chaining.
    - */
    -goog.testing.MultiTestRunner.prototype.setFilterFunction = function(filterFn) {
    -  this.filterFn_ = filterFn;
    -  return this;
    -};
    -
    -
    -/**
    - * Returns a filter function. Only test paths that match the filter function
    - * will be executed.
    - * @return {function(string): boolean} A filter function. Only test paths that
    - *     match the filter function will be executed.
    -
    - */
    -goog.testing.MultiTestRunner.prototype.getFilterFunction = function() {
    -  return this.filterFn_;
    -};
    -
    -
    -/**
    - * Adds an array of tests to the tests that the test runner should execute.
    - * @param {Array<string>} tests Adds tests to the test runner.
    - * @return {!goog.testing.MultiTestRunner} Instance for chaining.
    - */
    -goog.testing.MultiTestRunner.prototype.addTests = function(tests) {
    -  goog.array.extend(this.allTests_, tests);
    -  return this;
    -};
    -
    -
    -/**
    - * Returns the list of all tests added to the runner.
    - * @return {Array<string>} The list of all tests added to the runner.
    - */
    -goog.testing.MultiTestRunner.prototype.getAllTests = function() {
    -  return this.allTests_;
    -};
    -
    -
    -/**
    - * Returns the list of tests that will be run when start() is called.
    - * @return {!Array<string>} The list of tests that will be run when start() is
    - *     called.
    - */
    -goog.testing.MultiTestRunner.prototype.getTestsToRun = function() {
    -  return goog.array.filter(this.allTests_, this.filterFn_);
    -};
    -
    -
    -/**
    - * Returns a list of tests from runner that have been marked as failed.
    - * @return {!Array<string>} A list of tests from runner that have been marked
    - *     as failed.
    - */
    -goog.testing.MultiTestRunner.prototype.getTestsThatFailed = function() {
    -  var stats = this.stats_;
    -  var failedTests = [];
    -  if (stats) {
    -    for (var i = 0, stat; stat = stats[i]; i++) {
    -      if (!stat.success) {
    -        failedTests.push(stat.testFile);
    -      }
    -    }
    -  }
    -  return failedTests;
    -};
    -
    -
    -/**
    - * Deletes and re-creates the progress table inside the progess element.
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.resetProgressDom_ = function() {
    -  goog.dom.removeChildren(this.progressEl_);
    -  var progressTable = this.dom_.createDom('table');
    -  var progressTBody = this.dom_.createDom('tbody');
    -  this.progressRow_ = this.dom_.createDom('tr');
    -  for (var i = 0; i < this.activeTests_.length; i++) {
    -    var progressCell = this.dom_.createDom('td');
    -    this.progressRow_.appendChild(progressCell);
    -  }
    -  progressTBody.appendChild(this.progressRow_);
    -  progressTable.appendChild(progressTBody);
    -  this.progressEl_.appendChild(progressTable);
    -};
    -
    -
    -/** @override */
    -goog.testing.MultiTestRunner.prototype.createDom = function() {
    -  goog.testing.MultiTestRunner.superClass_.createDom.call(this);
    -  var el = this.getElement();
    -  el.className = goog.getCssName('goog-testrunner');
    -
    -  this.progressEl_ = this.dom_.createDom('div');
    -  this.progressEl_.className = goog.getCssName('goog-testrunner-progress');
    -  el.appendChild(this.progressEl_);
    -
    -  var buttons = this.dom_.createDom('div');
    -  buttons.className = goog.getCssName('goog-testrunner-buttons');
    -  this.startButtonEl_ = this.dom_.createDom('button', null, 'Start');
    -  this.stopButtonEl_ =
    -      this.dom_.createDom('button', {'disabled': true}, 'Stop');
    -  buttons.appendChild(this.startButtonEl_);
    -  buttons.appendChild(this.stopButtonEl_);
    -  el.appendChild(buttons);
    -
    -  this.eh_.listen(this.startButtonEl_, 'click',
    -      this.onStartClicked_);
    -  this.eh_.listen(this.stopButtonEl_, 'click',
    -      this.onStopClicked_);
    -
    -  this.logEl_ = this.dom_.createElement('div');
    -  this.logEl_.className = goog.getCssName('goog-testrunner-log');
    -  el.appendChild(this.logEl_);
    -
    -  this.reportEl_ = this.dom_.createElement('div');
    -  this.reportEl_.className = goog.getCssName('goog-testrunner-report');
    -  this.reportEl_.style.display = 'none';
    -  el.appendChild(this.reportEl_);
    -
    -  this.statsEl_ = this.dom_.createElement('div');
    -  this.statsEl_.className = goog.getCssName('goog-testrunner-stats');
    -  this.statsEl_.style.display = 'none';
    -  el.appendChild(this.statsEl_);
    -
    -  this.logTabEl_ = this.dom_.createDom('div', null, 'Log');
    -  this.logTabEl_.className = goog.getCssName('goog-testrunner-logtab') + ' ' +
    -      goog.getCssName('goog-testrunner-activetab');
    -  el.appendChild(this.logTabEl_);
    -
    -  this.reportTabEl_ = this.dom_.createDom('div', null, 'Report');
    -  this.reportTabEl_.className = goog.getCssName('goog-testrunner-reporttab');
    -  el.appendChild(this.reportTabEl_);
    -
    -  this.statsTabEl_ = this.dom_.createDom('div', null, 'Stats');
    -  this.statsTabEl_.className = goog.getCssName('goog-testrunner-statstab');
    -  el.appendChild(this.statsTabEl_);
    -
    -  this.eh_.listen(this.logTabEl_, 'click', this.onLogTabClicked_);
    -  this.eh_.listen(this.reportTabEl_, 'click', this.onReportTabClicked_);
    -  this.eh_.listen(this.statsTabEl_, 'click', this.onStatsTabClicked_);
    -
    -};
    -
    -
    -/** @override */
    -goog.testing.MultiTestRunner.prototype.disposeInternal = function() {
    -  goog.testing.MultiTestRunner.superClass_.disposeInternal.call(this);
    -  this.tableSorter_.dispose();
    -  this.eh_.dispose();
    -  this.startButtonEl_ = null;
    -  this.stopButtonEl_ = null;
    -  this.logEl_ = null;
    -  this.reportEl_ = null;
    -  this.progressEl_ = null;
    -  this.logTabEl_ = null;
    -  this.reportTabEl_ = null;
    -  this.statsTabEl_ = null;
    -  this.statsEl_ = null;
    -};
    -
    -
    -/**
    - * Starts executing the tests.
    - */
    -goog.testing.MultiTestRunner.prototype.start = function() {
    -  this.startButtonEl_.disabled = true;
    -  this.stopButtonEl_.disabled = false;
    -  this.stopped_ = false;
    -  this.active_ = true;
    -  this.finished_ = {};
    -  this.activeTests_ = this.getTestsToRun();
    -  this.startedCount_ = 0;
    -  this.resultCount_ = 0;
    -  this.passes_ = 0;
    -  this.stats_ = [];
    -  this.startTime_ = goog.now();
    -
    -  this.resetProgressDom_();
    -  goog.dom.removeChildren(this.logEl_);
    -
    -  this.resetReport_();
    -  this.clearStats_();
    -  this.showTab_(0);
    -
    -  // Ensure the pool isn't too big.
    -  while (this.getChildCount() > this.poolSize_) {
    -    this.removeChildAt(0, true).dispose();
    -  }
    -
    -  // Start a test in each runner.
    -  for (var i = 0; i < this.poolSize_; i++) {
    -    if (i >= this.getChildCount()) {
    -      var testFrame = new goog.testing.MultiTestRunner.TestFrame(
    -          this.basePath_, this.timeoutMs_, this.verbosePasses_, this.dom_);
    -      this.addChild(testFrame, true);
    -    }
    -    this.runNextTest_(
    -        /** @type {goog.testing.MultiTestRunner.TestFrame} */
    -        (this.getChildAt(i)));
    -  }
    -};
    -
    -
    -/**
    - * Logs a message to the log window.
    - * @param {string} msg A message to log.
    - */
    -goog.testing.MultiTestRunner.prototype.log = function(msg) {
    -  if (msg != '.') {
    -    msg = this.getTimeStamp_() + ' : ' + msg;
    -  }
    -
    -  this.logEl_.appendChild(this.dom_.createDom('div', null, msg));
    -
    -  // Autoscroll if we're near the bottom.
    -  var top = this.logEl_.scrollTop;
    -  var height = this.logEl_.scrollHeight - this.logEl_.offsetHeight;
    -  if (top == 0 || top > height - 50) {
    -    this.logEl_.scrollTop = height;
    -  }
    -};
    -
    -
    -/**
    - * Processes a result returned from a TestFrame.  If there are tests remaining
    - * it will trigger the next one to be run, otherwise if there are no tests and
    - * all results have been recieved then it will call finish.
    - * @param {goog.testing.MultiTestRunner.TestFrame} frame The frame that just
    - *     finished.
    - */
    -goog.testing.MultiTestRunner.prototype.processResult = function(frame) {
    -  var success = frame.isSuccess();
    -  var report = frame.getReport();
    -  var test = frame.getTestFile();
    -
    -  this.stats_.push(frame.getStats());
    -  this.finished_[test] = true;
    -
    -  var prefix = success ? '' : '*** FAILURE *** ';
    -  this.log(prefix +
    -      this.trimFileName_(test) + ' : ' + (success ? 'Passed' : 'Failed'));
    -
    -  this.resultCount_++;
    -
    -  if (success) {
    -    this.passes_++;
    -  }
    -
    -  this.drawProgressSegment_(test, success);
    -  this.writeCurrentSummary_();
    -  if (!(success && this.hidePasses_)) {
    -    this.drawTestResult_(test, success, report);
    -  }
    -
    -  if (!this.stopped_ && this.startedCount_ < this.activeTests_.length) {
    -    this.runNextTest_(frame);
    -  } else if (this.resultCount_ == this.activeTests_.length) {
    -    this.finish_();
    -  }
    -};
    -
    -
    -/**
    - * Runs the next available test, if there are any left.
    - * @param {goog.testing.MultiTestRunner.TestFrame} frame Where to run the test.
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.runNextTest_ = function(frame) {
    -  if (this.startedCount_ < this.activeTests_.length) {
    -    var nextTest = this.activeTests_[this.startedCount_++];
    -    this.log(this.trimFileName_(nextTest) + ' : Loading');
    -    frame.runTest(nextTest);
    -  }
    -};
    -
    -
    -/**
    - * Handles the test finishing, processing the results and rendering the report.
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.finish_ = function() {
    -  if (this.stopped_) {
    -    this.log('Stopped');
    -  } else {
    -    this.log('Finished');
    -  }
    -
    -  this.startButtonEl_.disabled = false;
    -  this.stopButtonEl_.disabled = true;
    -  this.active_ = false;
    -
    -  this.showTab_(1);
    -  this.drawStats_();
    -
    -  // Remove all the test frames
    -  while (this.getChildCount() > 0) {
    -    this.removeChildAt(0, true).dispose();
    -  }
    -
    -  // Compute tests that did not finish before the stop button was hit.
    -  var unfinished = [];
    -  for (var i = 0; i < this.activeTests_.length; i++) {
    -    var test = this.activeTests_[i];
    -    if (!this.finished_[test]) {
    -      unfinished.push(test);
    -    }
    -  }
    -
    -  if (unfinished.length) {
    -    this.reportEl_.appendChild(goog.dom.createDom('pre', undefined,
    -        'Theses tests did not finish:\n' + unfinished.join('\n')));
    -  }
    -};
    -
    -
    -/**
    - * Resets the report, clearing out all children and drawing the initial summary.
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.resetReport_ = function() {
    -  goog.dom.removeChildren(this.reportEl_);
    -  var summary = this.dom_.createDom('div');
    -  summary.className = goog.getCssName('goog-testrunner-progress-summary');
    -  this.reportEl_.appendChild(summary);
    -  this.writeCurrentSummary_();
    -};
    -
    -
    -/**
    - * Draws the stats for the test run.
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.drawStats_ = function() {
    -  this.drawFilesHistogram_();
    -
    -  // Only show time stats if pool size is 1, otherwise times are wrong.
    -  if (this.poolSize_ == 1) {
    -    this.drawRunTimePie_();
    -    this.drawTimeHistogram_();
    -  }
    -
    -  this.drawWorstTestsTable_();
    -};
    -
    -
    -/**
    - * Draws the histogram showing number of files loaded.
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.drawFilesHistogram_ = function() {
    -  this.drawStatsHistogram_(
    -      'numFilesLoaded',
    -      this.numFilesStatsBucketSize_,
    -      goog.functions.identity,
    -      500,
    -      'Histogram showing distribution of\nnumber of files loaded per test');
    -};
    -
    -
    -/**
    - * Draws the histogram showing how long each test took to complete.
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.drawTimeHistogram_ = function() {
    -  this.drawStatsHistogram_(
    -      'totalTime',
    -      this.runTimeStatsBucketSize_,
    -      function(x) { return x / 1000; },
    -      500,
    -      'Histogram showing distribution of\ntime spent running tests in s');
    -};
    -
    -
    -/**
    - * Draws a stats histogram.
    - * @param {string} statsField Field of the stats object to graph.
    - * @param {number} bucketSize The size for the histogram's buckets.
    - * @param {function(number, ...*): *} valueTransformFn Function for
    - *     transforming the x-labels value for display.
    - * @param {number} width The width in pixels of the graph.
    - * @param {string} title The graph's title.
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.drawStatsHistogram_ = function(
    -    statsField, bucketSize, valueTransformFn, width, title) {
    -
    -  var hist = {}, data = [], xlabels = [], ylabels = [];
    -  var max = 0;
    -  for (var i = 0; i < this.stats_.length; i++) {
    -    var num = this.stats_[i][statsField];
    -    var bucket = Math.floor(num / bucketSize) * bucketSize;
    -    if (bucket > max) {
    -      max = bucket;
    -    }
    -    if (!hist[bucket]) {
    -      hist[bucket] = 1;
    -    } else {
    -      hist[bucket]++;
    -    }
    -  }
    -  var maxBucketSize = 0;
    -  for (var i = 0; i <= max; i += bucketSize) {
    -    xlabels.push(valueTransformFn(i));
    -    var count = hist[i] || 0;
    -    if (count > maxBucketSize) {
    -      maxBucketSize = count;
    -    }
    -    data.push(count);
    -  }
    -  var diff = Math.max(1, Math.ceil(maxBucketSize / 10));
    -  for (var i = 0; i <= maxBucketSize; i += diff) {
    -    ylabels.push(i);
    -  }
    -  var chart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.VERTICAL_STACKED_BAR, width, 250, null,
    -      goog.ui.ServerChart.CHART_SERVER_HTTPS_URI);
    -  chart.setTitle(title);
    -  chart.addDataSet(data, 'ff9900');
    -  chart.setLeftLabels(ylabels);
    -  chart.setGridY(ylabels.length - 1);
    -  chart.setXLabels(xlabels);
    -  chart.render(this.statsEl_);
    -};
    -
    -
    -/**
    - * Draws a pie chart showing the percentage of time spent running the tests
    - * compared to loading them etc.
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.drawRunTimePie_ = function() {
    -  var totalTime = 0, runTime = 0;
    -  for (var i = 0; i < this.stats_.length; i++) {
    -    var stat = this.stats_[i];
    -    totalTime += stat.totalTime;
    -    runTime += stat.runTime;
    -  }
    -  var loadTime = totalTime - runTime;
    -  var pie = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.PIE, 500, 250, null,
    -      goog.ui.ServerChart.CHART_SERVER_HTTPS_URI);
    -  pie.setMinValue(0);
    -  pie.setMaxValue(totalTime);
    -  pie.addDataSet([runTime, loadTime], 'ff9900');
    -  pie.setXLabels([
    -    'Test execution (' + runTime + 'ms)',
    -    'Loading (' + loadTime + 'ms)']);
    -  pie.render(this.statsEl_);
    -};
    -
    -
    -/**
    - * Draws a pie chart showing the percentage of time spent running the tests
    - * compared to loading them etc.
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.drawWorstTestsTable_ = function() {
    -  this.stats_.sort(function(a, b) {
    -    return b['numFilesLoaded'] - a['numFilesLoaded'];
    -  });
    -
    -  var tbody = goog.bind(this.dom_.createDom, this.dom_, 'tbody');
    -  var thead = goog.bind(this.dom_.createDom, this.dom_, 'thead');
    -  var tr = goog.bind(this.dom_.createDom, this.dom_, 'tr');
    -  var th = goog.bind(this.dom_.createDom, this.dom_, 'th');
    -  var td = goog.bind(this.dom_.createDom, this.dom_, 'td');
    -  var a = goog.bind(this.dom_.createDom, this.dom_, 'a');
    -
    -  var head = thead({'style': 'cursor: pointer'},
    -      tr(null,
    -          th(null, ' '),
    -          th(null, 'Test file'),
    -          th('center', 'Num files loaded'),
    -          th('center', 'Run time (ms)'),
    -          th('center', 'Total time (ms)')));
    -  var body = tbody();
    -  var table = this.dom_.createDom('table', null, head, body);
    -
    -  for (var i = 0; i < this.stats_.length; i++) {
    -    var stat = this.stats_[i];
    -    body.appendChild(tr(null,
    -        td('center', String(i + 1)),
    -        td(null, a(
    -            {'href': this.basePath_ + stat['testFile'], 'target': '_blank'},
    -            stat['testFile'])),
    -        td('center', String(stat['numFilesLoaded'])),
    -        td('center', String(stat['runTime'])),
    -        td('center', String(stat['totalTime']))));
    -  }
    -
    -  this.statsEl_.appendChild(table);
    -
    -  this.tableSorter_.setDefaultSortFunction(goog.ui.TableSorter.numericSort);
    -  this.tableSorter_.setSortFunction(
    -      1 /* test file name */, goog.ui.TableSorter.alphaSort);
    -  this.tableSorter_.decorate(table);
    -};
    -
    -
    -/**
    - * Clears the stats page.
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.clearStats_ = function() {
    -  goog.dom.removeChildren(this.statsEl_);
    -  this.tableSorter_.exitDocument();
    -};
    -
    -
    -/**
    - * Updates the report's summary.
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.writeCurrentSummary_ = function() {
    -  var total = this.activeTests_.length;
    -  var executed = this.resultCount_;
    -  var passes = this.passes_;
    -  var duration = Math.round((goog.now() - this.startTime_) / 1000);
    -  var text = executed + ' of ' + total + ' tests executed.<br>' +
    -      passes + ' passed, ' + (executed - passes) + ' failed.<br>' +
    -      'Duration: ' + duration + 's.';
    -  this.reportEl_.firstChild.innerHTML = text;
    -};
    -
    -
    -/**
    - * Adds a segment to the progress bar.
    - * @param {string} title Title for the segment.
    - * @param {*} success Whether the segment should indicate a success.
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.drawProgressSegment_ =
    -    function(title, success) {
    -  var part = this.progressRow_.cells[this.resultCount_ - 1];
    -  part.title = title + ' : ' + (success ? 'SUCCESS' : 'FAILURE');
    -  part.style.backgroundColor = success ? '#090' : '#900';
    -};
    -
    -
    -/**
    - * Draws a test result in the report pane.
    - * @param {string} test Test name.
    - * @param {*} success Whether the test succeeded.
    - * @param {string} report The report.
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.drawTestResult_ = function(
    -    test, success, report) {
    -  var text = goog.string.isEmptyOrWhitespace(report) ?
    -      'No report for ' + test + '\n' : report;
    -  var el = this.dom_.createDom('div');
    -  text = goog.string.htmlEscape(text).replace(/\n/g, '<br>');
    -  if (success) {
    -    el.className = goog.getCssName('goog-testrunner-report-success');
    -  } else {
    -    text += '<a href="' + this.basePath_ + test +
    -        '">Run individually &raquo;</a><br>&nbsp;';
    -    el.className = goog.getCssName('goog-testrunner-report-failure');
    -  }
    -  el.innerHTML = text;
    -  this.reportEl_.appendChild(el);
    -};
    -
    -
    -/**
    - * Returns the current timestamp.
    - * @return {string} HH:MM:SS.
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.getTimeStamp_ = function() {
    -  var d = new Date;
    -  return goog.string.padNumber(d.getHours(), 2) + ':' +
    -      goog.string.padNumber(d.getMinutes(), 2) + ':' +
    -      goog.string.padNumber(d.getSeconds(), 2);
    -};
    -
    -
    -/**
    - * Trims a filename to be less than 35-characters, ensuring that we do not break
    - * a path part.
    - * @param {string} name The file name.
    - * @return {string} The shortened name.
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.trimFileName_ = function(name) {
    -  if (name.length < 35) {
    -    return name;
    -  }
    -  var parts = name.split('/');
    -  var result = '';
    -  while (result.length < 35 && parts.length > 0) {
    -    result = '/' + parts.pop() + result;
    -  }
    -  return '...' + result;
    -};
    -
    -
    -/**
    - * Shows the report and hides the log if the argument is true.
    - * @param {number} tab Which tab to show.
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.showTab_ = function(tab) {
    -  var activeTabCssClass = goog.getCssName('goog-testrunner-activetab');
    -
    -  var logTabElement = goog.asserts.assert(this.logTabEl_);
    -  var reportTabElement = goog.asserts.assert(this.reportTabEl_);
    -  var statsTabElement = goog.asserts.assert(this.statsTabEl_);
    -
    -  if (tab == 0) {
    -    this.logEl_.style.display = '';
    -    goog.dom.classlist.add(logTabElement, activeTabCssClass);
    -  } else {
    -    this.logEl_.style.display = 'none';
    -    goog.dom.classlist.remove(logTabElement, activeTabCssClass);
    -  }
    -
    -  if (tab == 1) {
    -    this.reportEl_.style.display = '';
    -    goog.dom.classlist.add(reportTabElement, activeTabCssClass);
    -  } else {
    -    this.reportEl_.style.display = 'none';
    -    goog.dom.classlist.remove(reportTabElement, activeTabCssClass);
    -  }
    -
    -  if (tab == 2) {
    -    this.statsEl_.style.display = '';
    -    goog.dom.classlist.add(statsTabElement, activeTabCssClass);
    -  } else {
    -    this.statsEl_.style.display = 'none';
    -    goog.dom.classlist.remove(statsTabElement, activeTabCssClass);
    -  }
    -};
    -
    -
    -/**
    - * Handles the start button being clicked.
    - * @param {goog.events.BrowserEvent} e The click event.
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.onStartClicked_ = function(e) {
    -  this.start();
    -};
    -
    -
    -/**
    - * Handles the stop button being clicked.
    - * @param {goog.events.BrowserEvent} e The click event.
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.onStopClicked_ = function(e) {
    -  this.stopped_ = true;
    -  this.finish_();
    -};
    -
    -
    -/**
    - * Handles the log tab being clicked.
    - * @param {goog.events.BrowserEvent} e The click event.
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.onLogTabClicked_ = function(e) {
    -  this.showTab_(0);
    -};
    -
    -
    -/**
    - * Handles the log tab being clicked.
    - * @param {goog.events.BrowserEvent} e The click event.
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.onReportTabClicked_ = function(e) {
    -  this.showTab_(1);
    -};
    -
    -
    -/**
    - * Handles the stats tab being clicked.
    - * @param {goog.events.BrowserEvent} e The click event.
    - * @private
    - */
    -goog.testing.MultiTestRunner.prototype.onStatsTabClicked_ = function(e) {
    -  this.showTab_(2);
    -};
    -
    -
    -
    -/**
    - * Class used to manage the interaction with a single iframe.
    - * @param {string} basePath The base path for tests.
    - * @param {number} timeoutMs The time to wait for the test to load and run.
    - * @param {boolean} verbosePasses Whether to show results for passes.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional dom helper.
    - * @constructor
    - * @extends {goog.ui.Component}
    - * @final
    - */
    -goog.testing.MultiTestRunner.TestFrame = function(
    -    basePath, timeoutMs, verbosePasses, opt_domHelper) {
    -  goog.ui.Component.call(this, opt_domHelper);
    -
    -  /**
    -   * Base path where tests should be resolved from.
    -   * @type {string}
    -   * @private
    -   */
    -  this.basePath_ = basePath;
    -
    -  /**
    -   * The timeout for the test.
    -   * @type {number}
    -   * @private
    -   */
    -  this.timeoutMs_ = timeoutMs;
    -
    -  /**
    -   * Whether to show a summary for passing tests.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.verbosePasses_ = verbosePasses;
    -
    -  /**
    -   * An event handler for handling events.
    -   * @type {goog.events.EventHandler<!goog.testing.MultiTestRunner.TestFrame>}
    -   * @private
    -   */
    -  this.eh_ = new goog.events.EventHandler(this);
    -
    -};
    -goog.inherits(goog.testing.MultiTestRunner.TestFrame, goog.ui.Component);
    -
    -
    -/**
    - * Reference to the iframe.
    - * @type {HTMLIFrameElement}
    - * @private
    - */
    -goog.testing.MultiTestRunner.TestFrame.prototype.iframeEl_ = null;
    -
    -
    -/**
    - * Whether the iframe for the current test has loaded.
    - * @type {boolean}
    - * @private
    - */
    -goog.testing.MultiTestRunner.TestFrame.prototype.iframeLoaded_ = false;
    -
    -
    -/**
    - * The test file being run.
    - * @type {string}
    - * @private
    - */
    -goog.testing.MultiTestRunner.TestFrame.prototype.testFile_ = '';
    -
    -
    -/**
    - * The report returned from the test.
    - * @type {string}
    - * @private
    - */
    -goog.testing.MultiTestRunner.TestFrame.prototype.report_ = '';
    -
    -
    -/**
    - * The total time loading and running the test in milliseconds.
    - * @type {number}
    - * @private
    - */
    -goog.testing.MultiTestRunner.TestFrame.prototype.totalTime_ = 0;
    -
    -
    -/**
    - * The actual runtime of the test in milliseconds.
    - * @type {number}
    - * @private
    - */
    -goog.testing.MultiTestRunner.TestFrame.prototype.runTime_ = 0;
    -
    -
    -/**
    - * The number of files loaded by the test.
    - * @type {number}
    - * @private
    - */
    -goog.testing.MultiTestRunner.TestFrame.prototype.numFilesLoaded_ = 0;
    -
    -
    -/**
    - * Whether the test was successful, null if no result has been returned yet.
    - * @type {?boolean}
    - * @private
    - */
    -goog.testing.MultiTestRunner.TestFrame.prototype.isSuccess_ = null;
    -
    -
    -/**
    - * Timestamp for the when the test was started.
    - * @type {number}
    - * @private
    - */
    -goog.testing.MultiTestRunner.TestFrame.prototype.startTime_ = 0;
    -
    -
    -/**
    - * Timestamp for the last state, used to determine timeouts.
    - * @type {number}
    - * @private
    - */
    -goog.testing.MultiTestRunner.TestFrame.prototype.lastStateTime_ = 0;
    -
    -
    -/**
    - * The state of the active test.
    - * @type {number}
    - * @private
    - */
    -goog.testing.MultiTestRunner.TestFrame.prototype.currentState_ = 0;
    -
    -
    -/** @override */
    -goog.testing.MultiTestRunner.TestFrame.prototype.disposeInternal = function() {
    -  goog.testing.MultiTestRunner.TestFrame.superClass_.disposeInternal.call(this);
    -  this.dom_.removeNode(this.iframeEl_);
    -  this.eh_.dispose();
    -  this.iframeEl_ = null;
    -};
    -
    -
    -/**
    - * Runs a test file in this test frame.
    - * @param {string} testFile The test to run.
    - */
    -goog.testing.MultiTestRunner.TestFrame.prototype.runTest = function(testFile) {
    -  this.lastStateTime_ = this.startTime_ = goog.now();
    -
    -  if (!this.iframeEl_) {
    -    this.createIframe_();
    -  }
    -
    -  this.iframeLoaded_ = false;
    -  this.currentState_ = 0;
    -  this.isSuccess_ = null;
    -  this.report_ = '';
    -  this.testFile_ = testFile;
    -
    -  try {
    -    this.iframeEl_.src = this.basePath_ + testFile;
    -  } catch (e) {
    -    // Failures will trigger a JS exception on the local file system.
    -    this.report_ = this.testFile_ + ' failed to load : ' + e.message;
    -    this.isSuccess_ = false;
    -    this.finish_();
    -    return;
    -  }
    -
    -  this.checkForCompletion_();
    -};
    -
    -
    -/**
    - * @return {string} The test file the TestFrame is running.
    - */
    -goog.testing.MultiTestRunner.TestFrame.prototype.getTestFile = function() {
    -  return this.testFile_;
    -};
    -
    -
    -/**
    - * @return {!Object} Stats about the test run.
    - */
    -goog.testing.MultiTestRunner.TestFrame.prototype.getStats = function() {
    -  return {
    -    'testFile': this.testFile_,
    -    'success': this.isSuccess_,
    -    'runTime': this.runTime_,
    -    'totalTime': this.totalTime_,
    -    'numFilesLoaded': this.numFilesLoaded_
    -  };
    -};
    -
    -
    -/**
    - * @return {string} The report for the test run.
    - */
    -goog.testing.MultiTestRunner.TestFrame.prototype.getReport = function() {
    -  return this.report_;
    -};
    -
    -
    -/**
    - * @return {?boolean} Whether the test frame had a success.
    - */
    -goog.testing.MultiTestRunner.TestFrame.prototype.isSuccess = function() {
    -  return this.isSuccess_;
    -};
    -
    -
    -/**
    - * Handles the TestFrame finishing a single test.
    - * @private
    - */
    -goog.testing.MultiTestRunner.TestFrame.prototype.finish_ = function() {
    -  this.totalTime_ = goog.now() - this.startTime_;
    -  // TODO(user): Fire an event instead?
    -  if (this.getParent() && this.getParent().processResult) {
    -    this.getParent().processResult(this);
    -  }
    -};
    -
    -
    -/**
    - * Creates an iframe to run the tests in.  For overriding in unit tests.
    - * @private
    - */
    -goog.testing.MultiTestRunner.TestFrame.prototype.createIframe_ = function() {
    -  this.iframeEl_ =
    -      /** @type {!HTMLIFrameElement} */ (this.dom_.createDom('iframe'));
    -  this.getElement().appendChild(this.iframeEl_);
    -  this.eh_.listen(this.iframeEl_, 'load', this.onIframeLoaded_);
    -};
    -
    -
    -/**
    - * Handles the iframe loading.
    - * @param {goog.events.BrowserEvent} e The load event.
    - * @private
    - */
    -goog.testing.MultiTestRunner.TestFrame.prototype.onIframeLoaded_ = function(e) {
    -  this.iframeLoaded_ = true;
    -};
    -
    -
    -/**
    - * Checks the active test for completion, keeping track of the tests' various
    - * execution stages.
    - * @private
    - */
    -goog.testing.MultiTestRunner.TestFrame.prototype.checkForCompletion_ =
    -    function() {
    -  var js = goog.dom.getFrameContentWindow(this.iframeEl_);
    -  switch (this.currentState_) {
    -    case 0:
    -      if (this.iframeLoaded_ && js['G_testRunner']) {
    -        this.lastStateTime_ = goog.now();
    -        this.currentState_++;
    -      }
    -      break;
    -    case 1:
    -      if (js['G_testRunner']['isInitialized']()) {
    -        this.lastStateTime_ = goog.now();
    -        this.currentState_++;
    -      }
    -      break;
    -    case 2:
    -      if (js['G_testRunner']['isFinished']()) {
    -        var tr = js['G_testRunner'];
    -        this.isSuccess_ = tr['isSuccess']();
    -        this.report_ = tr['getReport'](this.verbosePasses_);
    -        this.runTime_ = tr['getRunTime']();
    -        this.numFilesLoaded_ = tr['getNumFilesLoaded']();
    -        this.finish_();
    -        return;
    -      }
    -  }
    -
    -  // Check to see if the test has timed out.
    -  if (goog.now() - this.lastStateTime_ > this.timeoutMs_) {
    -    this.report_ = this.testFile_ + ' timed out  ' +
    -        goog.testing.MultiTestRunner.STATES[this.currentState_];
    -    this.isSuccess_ = false;
    -    this.finish_();
    -    return;
    -  }
    -
    -  // Check again in 100ms.
    -  goog.Timer.callOnce(this.checkForCompletion_, 100, this);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/net/xhrio.js b/src/database/third_party/closure-library/closure/goog/testing/net/xhrio.js
    deleted file mode 100644
    index b86ae753241..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/net/xhrio.js
    +++ /dev/null
    @@ -1,743 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Mock of XhrIo for unit testing.
    - */
    -
    -goog.provide('goog.testing.net.XhrIo');
    -
    -goog.require('goog.array');
    -goog.require('goog.dom.xml');
    -goog.require('goog.events');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.json');
    -goog.require('goog.net.ErrorCode');
    -goog.require('goog.net.EventType');
    -goog.require('goog.net.HttpStatus');
    -goog.require('goog.net.XhrIo');
    -goog.require('goog.net.XmlHttp');
    -goog.require('goog.object');
    -goog.require('goog.structs.Map');
    -
    -
    -
    -/**
    - * Mock implementation of goog.net.XhrIo. This doesn't provide a mock
    - * implementation for all cases, but it's not too hard to add them as needed.
    - * @param {goog.testing.TestQueue=} opt_testQueue Test queue for inserting test
    - *     events.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - */
    -goog.testing.net.XhrIo = function(opt_testQueue) {
    -  goog.events.EventTarget.call(this);
    -
    -  /**
    -   * Map of default headers to add to every request, use:
    -   * XhrIo.headers.set(name, value)
    -   * @type {goog.structs.Map}
    -   */
    -  this.headers = new goog.structs.Map();
    -
    -  /**
    -   * Queue of events write to.
    -   * @type {goog.testing.TestQueue?}
    -   * @private
    -   */
    -  this.testQueue_ = opt_testQueue || null;
    -};
    -goog.inherits(goog.testing.net.XhrIo, goog.events.EventTarget);
    -
    -
    -/**
    - * Alias this enum here to make mocking of goog.net.XhrIo easier.
    - * @enum {string}
    - */
    -goog.testing.net.XhrIo.ResponseType = goog.net.XhrIo.ResponseType;
    -
    -
    -/**
    - * All non-disposed instances of goog.testing.net.XhrIo created
    - * by {@link goog.testing.net.XhrIo.send} are in this Array.
    - * @see goog.testing.net.XhrIo.cleanup
    - * @type {!Array<!goog.testing.net.XhrIo>}
    - * @private
    - */
    -goog.testing.net.XhrIo.sendInstances_ = [];
    -
    -
    -/**
    - * Returns an Array containing all non-disposed instances of
    - * goog.testing.net.XhrIo created by {@link goog.testing.net.XhrIo.send}.
    - * @return {!Array<!goog.testing.net.XhrIo>} Array of goog.testing.net.XhrIo
    - *     instances.
    - */
    -goog.testing.net.XhrIo.getSendInstances = function() {
    -  return goog.testing.net.XhrIo.sendInstances_;
    -};
    -
    -
    -/**
    - * Disposes all non-disposed instances of goog.testing.net.XhrIo created by
    - * {@link goog.testing.net.XhrIo.send}.
    - * @see goog.net.XhrIo.cleanup
    - */
    -goog.testing.net.XhrIo.cleanup = function() {
    -  var instances = goog.testing.net.XhrIo.sendInstances_;
    -  while (instances.length) {
    -    instances.pop().dispose();
    -  }
    -};
    -
    -
    -/**
    - * Simulates the static XhrIo send method.
    - * @param {string} url Uri to make request to.
    - * @param {Function=} opt_callback Callback function for when request is
    - *     complete.
    - * @param {string=} opt_method Send method, default: GET.
    - * @param {string=} opt_content Post data.
    - * @param {Object|goog.structs.Map=} opt_headers Map of headers to add to the
    - *     request.
    - * @param {number=} opt_timeoutInterval Number of milliseconds after which an
    - *     incomplete request will be aborted; 0 means no timeout is set.
    - * @param {boolean=} opt_withCredentials Whether to send credentials with the
    - *     request. Default to false. See {@link goog.net.XhrIo#setWithCredentials}.
    - * @return {!goog.testing.net.XhrIo} The mocked sent XhrIo.
    - */
    -goog.testing.net.XhrIo.send = function(url, opt_callback, opt_method,
    -                                       opt_content, opt_headers,
    -                                       opt_timeoutInterval,
    -                                       opt_withCredentials) {
    -  var x = new goog.testing.net.XhrIo();
    -  goog.testing.net.XhrIo.sendInstances_.push(x);
    -  if (opt_callback) {
    -    goog.events.listen(x, goog.net.EventType.COMPLETE, opt_callback);
    -  }
    -  goog.events.listen(x,
    -                     goog.net.EventType.READY,
    -                     goog.partial(goog.testing.net.XhrIo.cleanupSend_, x));
    -  if (opt_timeoutInterval) {
    -    x.setTimeoutInterval(opt_timeoutInterval);
    -  }
    -  x.setWithCredentials(Boolean(opt_withCredentials));
    -  x.send(url, opt_method, opt_content, opt_headers);
    -
    -  return x;
    -};
    -
    -
    -/**
    - * Disposes of the specified goog.testing.net.XhrIo created by
    - * {@link goog.testing.net.XhrIo.send} and removes it from
    - * {@link goog.testing.net.XhrIo.pendingStaticSendInstances_}.
    - * @param {!goog.testing.net.XhrIo} XhrIo An XhrIo created by
    - *     {@link goog.testing.net.XhrIo.send}.
    - * @private
    - */
    -goog.testing.net.XhrIo.cleanupSend_ = function(XhrIo) {
    -  XhrIo.dispose();
    -  goog.array.remove(goog.testing.net.XhrIo.sendInstances_, XhrIo);
    -};
    -
    -
    -/**
    - * Stores the simulated response headers for the requests which are sent through
    - * this XhrIo.
    - * @type {Object}
    - * @private
    - */
    -goog.testing.net.XhrIo.prototype.responseHeaders_;
    -
    -
    -/**
    - * Whether MockXhrIo is active.
    - * @type {boolean}
    - * @private
    - */
    -goog.testing.net.XhrIo.prototype.active_ = false;
    -
    -
    -/**
    - * Last URI that was requested.
    - * @type {string}
    - * @private
    - */
    -goog.testing.net.XhrIo.prototype.lastUri_ = '';
    -
    -
    -/**
    - * Last HTTP method that was requested.
    - * @type {string|undefined}
    - * @private
    - */
    -goog.testing.net.XhrIo.prototype.lastMethod_;
    -
    -
    -/**
    - * Last POST content that was requested.
    - * @type {string|undefined}
    - * @private
    - */
    -goog.testing.net.XhrIo.prototype.lastContent_;
    -
    -
    -/**
    - * Additional headers that were requested in the last query.
    - * @type {Object|goog.structs.Map|undefined}
    - * @private
    - */
    -goog.testing.net.XhrIo.prototype.lastHeaders_;
    -
    -
    -/**
    - * Last error code.
    - * @type {goog.net.ErrorCode}
    - * @private
    - */
    -goog.testing.net.XhrIo.prototype.lastErrorCode_ =
    -    goog.net.ErrorCode.NO_ERROR;
    -
    -
    -/**
    - * Last error message.
    - * @type {string}
    - * @private
    - */
    -goog.testing.net.XhrIo.prototype.lastError_ = '';
    -
    -
    -/**
    - * The response object.
    - * @type {string|Document|ArrayBuffer}
    - * @private
    - */
    -goog.testing.net.XhrIo.prototype.response_ = '';
    -
    -
    -/**
    - * Mock ready state.
    - * @type {number}
    - * @private
    - */
    -goog.testing.net.XhrIo.prototype.readyState_ =
    -    goog.net.XmlHttp.ReadyState.UNINITIALIZED;
    -
    -
    -/**
    - * Number of milliseconds after which an incomplete request will be aborted and
    - * a {@link goog.net.EventType.TIMEOUT} event raised; 0 means no timeout is set.
    - * @type {number}
    - * @private
    - */
    -goog.testing.net.XhrIo.prototype.timeoutInterval_ = 0;
    -
    -
    -
    -/**
    - * The requested type for the response. The empty string means use the default
    - * XHR behavior.
    - * @type {goog.net.XhrIo.ResponseType}
    - * @private
    - */
    -goog.testing.net.XhrIo.prototype.responseType_ =
    -    goog.net.XhrIo.ResponseType.DEFAULT;
    -
    -
    -/**
    - * Whether a "credentialed" request is to be sent (one that is aware of cookies
    - * and authentication) . This is applicable only for cross-domain requests and
    - * more recent browsers that support this part of the HTTP Access Control
    - * standard.
    - *
    - * @see http://dev.w3.org/2006/webapi/XMLHttpRequest-2/#withcredentials
    - *
    - * @type {boolean}
    - * @private
    - */
    -goog.testing.net.XhrIo.prototype.withCredentials_ = false;
    -
    -
    -/**
    - * Whether there's currently an underlying XHR object.
    - * @type {boolean}
    - * @private
    - */
    -goog.testing.net.XhrIo.prototype.xhr_ = false;
    -
    -
    -/**
    - * Returns the number of milliseconds after which an incomplete request will be
    - * aborted, or 0 if no timeout is set.
    - * @return {number} Timeout interval in milliseconds.
    - */
    -goog.testing.net.XhrIo.prototype.getTimeoutInterval = function() {
    -  return this.timeoutInterval_;
    -};
    -
    -
    -/**
    - * Sets the number of milliseconds after which an incomplete request will be
    - * aborted and a {@link goog.net.EventType.TIMEOUT} event raised; 0 means no
    - * timeout is set.
    - * @param {number} ms Timeout interval in milliseconds; 0 means none.
    - */
    -goog.testing.net.XhrIo.prototype.setTimeoutInterval = function(ms) {
    -  this.timeoutInterval_ = Math.max(0, ms);
    -};
    -
    -
    -/**
    - * Causes timeout events to be fired.
    - */
    -goog.testing.net.XhrIo.prototype.simulateTimeout = function() {
    -  this.lastErrorCode_ = goog.net.ErrorCode.TIMEOUT;
    -  this.dispatchEvent(goog.net.EventType.TIMEOUT);
    -  this.abort(goog.net.ErrorCode.TIMEOUT);
    -};
    -
    -
    -/**
    - * Sets the desired type for the response. At time of writing, this is only
    - * supported in very recent versions of WebKit (10.0.612.1 dev and later).
    - *
    - * If this is used, the response may only be accessed via {@link #getResponse}.
    - *
    - * @param {goog.net.XhrIo.ResponseType} type The desired type for the response.
    - */
    -goog.testing.net.XhrIo.prototype.setResponseType = function(type) {
    -  this.responseType_ = type;
    -};
    -
    -
    -/**
    - * Gets the desired type for the response.
    - * @return {goog.net.XhrIo.ResponseType} The desired type for the response.
    - */
    -goog.testing.net.XhrIo.prototype.getResponseType = function() {
    -  return this.responseType_;
    -};
    -
    -
    -/**
    - * Sets whether a "credentialed" request that is aware of cookie and
    - * authentication information should be made. This option is only supported by
    - * browsers that support HTTP Access Control. As of this writing, this option
    - * is not supported in IE.
    - *
    - * @param {boolean} withCredentials Whether this should be a "credentialed"
    - *     request.
    - */
    -goog.testing.net.XhrIo.prototype.setWithCredentials =
    -    function(withCredentials) {
    -  this.withCredentials_ = withCredentials;
    -};
    -
    -
    -/**
    - * Gets whether a "credentialed" request is to be sent.
    - * @return {boolean} The desired type for the response.
    - */
    -goog.testing.net.XhrIo.prototype.getWithCredentials = function() {
    -  return this.withCredentials_;
    -};
    -
    -
    -/**
    - * Abort the current XMLHttpRequest
    - * @param {goog.net.ErrorCode=} opt_failureCode Optional error code to use -
    - *     defaults to ABORT.
    - */
    -goog.testing.net.XhrIo.prototype.abort = function(opt_failureCode) {
    -  if (this.active_) {
    -    try {
    -      this.active_ = false;
    -      this.lastErrorCode_ = opt_failureCode || goog.net.ErrorCode.ABORT;
    -      this.dispatchEvent(goog.net.EventType.COMPLETE);
    -      this.dispatchEvent(goog.net.EventType.ABORT);
    -    } finally {
    -      this.simulateReady();
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Simulates the XhrIo send.
    - * @param {string} url Uri to make request too.
    - * @param {string=} opt_method Send method, default: GET.
    - * @param {string=} opt_content Post data.
    - * @param {Object|goog.structs.Map=} opt_headers Map of headers to add to the
    - *     request.
    - */
    -goog.testing.net.XhrIo.prototype.send = function(url, opt_method, opt_content,
    -                                                 opt_headers) {
    -  if (this.xhr_) {
    -    throw Error('[goog.net.XhrIo] Object is active with another request');
    -  }
    -
    -  this.lastUri_ = url;
    -  this.lastMethod_ = opt_method || 'GET';
    -  this.lastContent_ = opt_content;
    -  this.lastHeaders_ = opt_headers;
    -
    -  if (this.testQueue_) {
    -    this.testQueue_.enqueue(['s', url, opt_method, opt_content, opt_headers]);
    -  }
    -  this.xhr_ = true;
    -  this.active_ = true;
    -  this.readyState_ = goog.net.XmlHttp.ReadyState.UNINITIALIZED;
    -  this.simulateReadyStateChange(goog.net.XmlHttp.ReadyState.LOADING);
    -};
    -
    -
    -/**
    - * Creates a new XHR object.
    - * @return {goog.net.XhrLike.OrNative} The newly created XHR
    - *     object.
    - * @protected
    - */
    -goog.testing.net.XhrIo.prototype.createXhr = function() {
    -  return goog.net.XmlHttp();
    -};
    -
    -
    -/**
    - * Simulates changing to the new ready state.
    - * @param {number} readyState Ready state to change to.
    - */
    -goog.testing.net.XhrIo.prototype.simulateReadyStateChange =
    -    function(readyState) {
    -  if (readyState < this.readyState_) {
    -    throw Error('Readystate cannot go backwards');
    -  }
    -
    -  // INTERACTIVE can be dispatched repeatedly as more data is reported.
    -  if (readyState == goog.net.XmlHttp.ReadyState.INTERACTIVE &&
    -      readyState == this.readyState_) {
    -    this.dispatchEvent(goog.net.EventType.READY_STATE_CHANGE);
    -    return;
    -  }
    -
    -  while (this.readyState_ < readyState) {
    -    this.readyState_++;
    -    this.dispatchEvent(goog.net.EventType.READY_STATE_CHANGE);
    -
    -    if (this.readyState_ == goog.net.XmlHttp.ReadyState.COMPLETE) {
    -      this.active_ = false;
    -      this.dispatchEvent(goog.net.EventType.COMPLETE);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Simulate receiving some bytes but the request not fully completing, and
    - * the XHR entering the 'INTERACTIVE' state.
    - * @param {string} partialResponse A string to append to the response text.
    - * @param {Object=} opt_headers Simulated response headers.
    - */
    -goog.testing.net.XhrIo.prototype.simulatePartialResponse =
    -    function(partialResponse, opt_headers) {
    -  this.response_ += partialResponse;
    -  this.responseHeaders_ = opt_headers || {};
    -  this.statusCode_ = 200;
    -  this.simulateReadyStateChange(goog.net.XmlHttp.ReadyState.INTERACTIVE);
    -};
    -
    -
    -/**
    - * Simulates receiving a response.
    - * @param {number} statusCode Simulated status code.
    - * @param {string|Document|ArrayBuffer|null} response Simulated response.
    - * @param {Object=} opt_headers Simulated response headers.
    - */
    -goog.testing.net.XhrIo.prototype.simulateResponse = function(statusCode,
    -    response, opt_headers) {
    -  this.statusCode_ = statusCode;
    -  this.response_ = response || '';
    -  this.responseHeaders_ = opt_headers || {};
    -
    -  try {
    -    if (this.isSuccess()) {
    -      this.simulateReadyStateChange(goog.net.XmlHttp.ReadyState.COMPLETE);
    -      this.dispatchEvent(goog.net.EventType.SUCCESS);
    -    } else {
    -      this.lastErrorCode_ = goog.net.ErrorCode.HTTP_ERROR;
    -      this.lastError_ = this.getStatusText() + ' [' + this.getStatus() + ']';
    -      this.simulateReadyStateChange(goog.net.XmlHttp.ReadyState.COMPLETE);
    -      this.dispatchEvent(goog.net.EventType.ERROR);
    -    }
    -  } finally {
    -    this.simulateReady();
    -  }
    -};
    -
    -
    -/**
    - * Simulates the Xhr is ready for the next request.
    - */
    -goog.testing.net.XhrIo.prototype.simulateReady = function() {
    -  this.active_ = false;
    -  this.xhr_ = false;
    -  this.dispatchEvent(goog.net.EventType.READY);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether there is an active request.
    - */
    -goog.testing.net.XhrIo.prototype.isActive = function() {
    -  return !!this.xhr_;
    -};
    -
    -
    -/**
    - * Has the request completed.
    - * @return {boolean} Whether the request has completed.
    - */
    -goog.testing.net.XhrIo.prototype.isComplete = function() {
    -  return this.readyState_ == goog.net.XmlHttp.ReadyState.COMPLETE;
    -};
    -
    -
    -/**
    - * Has the request compeleted with a success.
    - * @return {boolean} Whether the request compeleted successfully.
    - */
    -goog.testing.net.XhrIo.prototype.isSuccess = function() {
    -  switch (this.getStatus()) {
    -    case goog.net.HttpStatus.OK:
    -    case goog.net.HttpStatus.NO_CONTENT:
    -    case goog.net.HttpStatus.NOT_MODIFIED:
    -      return true;
    -
    -    default:
    -      return false;
    -  }
    -};
    -
    -
    -/**
    - * Returns the readystate.
    - * @return {number} goog.net.XmlHttp.ReadyState.*.
    - */
    -goog.testing.net.XhrIo.prototype.getReadyState = function() {
    -  return this.readyState_;
    -};
    -
    -
    -/**
    - * Get the status from the Xhr object.  Will only return correct result when
    - * called from the context of a callback.
    - * @return {number} Http status.
    - */
    -goog.testing.net.XhrIo.prototype.getStatus = function() {
    -  return this.statusCode_;
    -};
    -
    -
    -/**
    - * Get the status text from the Xhr object.  Will only return correct result
    - * when called from the context of a callback.
    - * @return {string} Status text.
    - */
    -goog.testing.net.XhrIo.prototype.getStatusText = function() {
    -  return '';
    -};
    -
    -
    -/**
    - * Gets the last error message.
    - * @return {goog.net.ErrorCode} Last error code.
    - */
    -goog.testing.net.XhrIo.prototype.getLastErrorCode = function() {
    -  return this.lastErrorCode_;
    -};
    -
    -
    -/**
    - * Gets the last error message.
    - * @return {string} Last error message.
    - */
    -goog.testing.net.XhrIo.prototype.getLastError = function() {
    -  return this.lastError_;
    -};
    -
    -
    -/**
    - * Gets the last URI that was requested.
    - * @return {string} Last URI.
    - */
    -goog.testing.net.XhrIo.prototype.getLastUri = function() {
    -  return this.lastUri_;
    -};
    -
    -
    -/**
    - * Gets the last HTTP method that was requested.
    - * @return {string|undefined} Last HTTP method used by send.
    - */
    -goog.testing.net.XhrIo.prototype.getLastMethod = function() {
    -  return this.lastMethod_;
    -};
    -
    -
    -/**
    - * Gets the last POST content that was requested.
    - * @return {string|undefined} Last POST content or undefined if last request was
    - *      a GET.
    - */
    -goog.testing.net.XhrIo.prototype.getLastContent = function() {
    -  return this.lastContent_;
    -};
    -
    -
    -/**
    - * Gets the headers of the last request.
    - * @return {Object|goog.structs.Map|undefined} Last headers manually set in send
    - *      call or undefined if no additional headers were specified.
    - */
    -goog.testing.net.XhrIo.prototype.getLastRequestHeaders = function() {
    -  return this.lastHeaders_;
    -};
    -
    -
    -/**
    - * Gets the response text from the Xhr object.  Will only return correct result
    - * when called from the context of a callback.
    - * @return {string} Result from the server.
    - */
    -goog.testing.net.XhrIo.prototype.getResponseText = function() {
    -  if (goog.isString(this.response_)) {
    -    return this.response_;
    -  } else if (goog.global['ArrayBuffer'] &&
    -      this.response_ instanceof ArrayBuffer) {
    -    return '';
    -  } else {
    -    return goog.dom.xml.serialize(/** @type {Document} */ (this.response_));
    -  }
    -};
    -
    -
    -/**
    - * Gets the response body from the Xhr object. Will only return correct result
    - * when called from the context of a callback.
    - * @return {Object} Binary result from the server or null.
    - */
    -goog.testing.net.XhrIo.prototype.getResponseBody = function() {
    -  return null;
    -};
    -
    -
    -/**
    - * Gets the response and evaluates it as JSON from the Xhr object.  Will only
    - * return correct result when called from the context of a callback.
    - * @param {string=} opt_xssiPrefix Optional XSSI prefix string to use for
    - *     stripping of the response before parsing. This needs to be set only if
    - *     your backend server prepends the same prefix string to the JSON response.
    - * @return {Object} JavaScript object.
    - */
    -goog.testing.net.XhrIo.prototype.getResponseJson = function(opt_xssiPrefix) {
    -  var responseText = this.getResponseText();
    -  if (opt_xssiPrefix && responseText.indexOf(opt_xssiPrefix) == 0) {
    -    responseText = responseText.substring(opt_xssiPrefix.length);
    -  }
    -
    -  return goog.json.parse(responseText);
    -};
    -
    -
    -/**
    - * Gets the response XML from the Xhr object.  Will only return correct result
    - * when called from the context of a callback.
    - * @return {Document} Result from the server if it was XML.
    - */
    -goog.testing.net.XhrIo.prototype.getResponseXml = function() {
    -  // NOTE(user): I haven't found out how to check in Internet Explorer
    -  // whether the response is XML document, so I do it the other way around.
    -  return goog.isString(this.response_) ||
    -      (goog.global['ArrayBuffer'] && this.response_ instanceof ArrayBuffer) ?
    -      null : /** @type {Document} */ (this.response_);
    -};
    -
    -
    -/**
    - * Get the response as the type specificed by {@link #setResponseType}. At time
    - * of writing, this is only supported in very recent versions of WebKit
    - * (10.0.612.1 dev and later).
    - *
    - * @return {*} The response.
    - */
    -goog.testing.net.XhrIo.prototype.getResponse = function() {
    -  return this.response_;
    -};
    -
    -
    -/**
    - * Get the value of the response-header with the given name from the Xhr object
    - * Will only return correct result when called from the context of a callback
    - * and the request has completed
    - * @param {string} key The name of the response-header to retrieve.
    - * @return {string|undefined} The value of the response-header named key.
    - */
    -goog.testing.net.XhrIo.prototype.getResponseHeader = function(key) {
    -  return this.isComplete() ? this.responseHeaders_[key] : undefined;
    -};
    -
    -
    -/**
    - * Gets the text of all the headers in the response.
    - * Will only return correct result when called from the context of a callback
    - * and the request has completed
    - * @return {string} The string containing all the response headers.
    - */
    -goog.testing.net.XhrIo.prototype.getAllResponseHeaders = function() {
    -  if (!this.isComplete()) {
    -    return '';
    -  }
    -
    -  var headers = [];
    -  goog.object.forEach(this.responseHeaders_, function(value, name) {
    -    headers.push(name + ': ' + value);
    -  });
    -
    -  return headers.join('\r\n');
    -};
    -
    -
    -/**
    - * Returns all response headers as a key-value map.
    - * Multiple values for the same header key can be combined into one,
    - * separated by a comma and a space.
    - * Note that the native getResponseHeader method for retrieving a single header
    - * does a case insensitive match on the header name. This method does not
    - * include any case normalization logic, it will just return a key-value
    - * representation of the headers.
    - * See: http://www.w3.org/TR/XMLHttpRequest/#the-getresponseheader()-method
    - * @return {!Object<string, string>} An object with the header keys as keys
    - *     and header values as values.
    - */
    -goog.testing.net.XhrIo.prototype.getResponseHeaders = function() {
    -  var headersObject = {};
    -  goog.object.forEach(this.responseHeaders_, function(value, key) {
    -    if (headersObject[key]) {
    -      headersObject[key] += ', ' + value;
    -    } else {
    -      headersObject[key] = value;
    -    }
    -  });
    -  return headersObject;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/net/xhrio_test.html b/src/database/third_party/closure-library/closure/goog/testing/net/xhrio_test.html
    deleted file mode 100644
    index 4dfe7fc0de8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/net/xhrio_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.testing.net.XhrIo
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.net.XhrIoTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/net/xhrio_test.js b/src/database/third_party/closure-library/closure/goog/testing/net/xhrio_test.js
    deleted file mode 100644
    index c72005c710b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/net/xhrio_test.js
    +++ /dev/null
    @@ -1,423 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.net.XhrIoTest');
    -goog.setTestOnly('goog.testing.net.XhrIoTest');
    -
    -goog.require('goog.dom.xml');
    -goog.require('goog.events');
    -goog.require('goog.events.Event');
    -goog.require('goog.net.ErrorCode');
    -goog.require('goog.net.EventType');
    -goog.require('goog.net.XmlHttp');
    -goog.require('goog.object');
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.asserts');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.mockmatchers.InstanceOf');
    -goog.require('goog.testing.net.XhrIo');
    -
    -var mockControl;
    -
    -function setUp() {
    -  mockControl = new goog.testing.MockControl();
    -}
    -
    -function testStaticSend() {
    -  sendInstances = goog.testing.net.XhrIo.getSendInstances();
    -  var returnedXhr = goog.testing.net.XhrIo.send('url');
    -  assertEquals('sendInstances_ after send',
    -               1, sendInstances.length);
    -  xhr = sendInstances[sendInstances.length - 1];
    -  assertTrue('isActive after request', xhr.isActive());
    -  assertEquals(returnedXhr, xhr);
    -  assertEquals('readyState after request',
    -               goog.net.XmlHttp.ReadyState.LOADING,
    -               xhr.getReadyState());
    -
    -  xhr.simulateResponse(200, '');
    -  assertFalse('isActive after response', xhr.isActive());
    -  assertEquals('readyState after response',
    -               goog.net.XmlHttp.ReadyState.COMPLETE,
    -               xhr.getReadyState());
    -
    -  xhr.simulateReady();
    -  assertEquals('sendInstances_ after READY',
    -               0, sendInstances.length);
    -}
    -
    -function testStaticSendWithException() {
    -  goog.testing.net.XhrIo.send('url', function() {
    -    if (!this.isSuccess()) {
    -      throw Error('The xhr did not complete successfully!');
    -    }
    -  });
    -  var sendInstances = goog.testing.net.XhrIo.getSendInstances();
    -  var xhr = sendInstances[sendInstances.length - 1];
    -  try {
    -    xhr.simulateResponse(400, '');
    -  } catch (e) {
    -    // Do nothing with the exception; we just want to make sure
    -    // the class cleans itself up properly when an exception is
    -    // thrown.
    -  }
    -  assertEquals('Send instance array not cleaned up properly!',
    -               0, sendInstances.length);
    -}
    -
    -function testMultipleSend() {
    -  var xhr = new goog.testing.net.XhrIo();
    -  assertFalse('isActive before first request', xhr.isActive());
    -  assertEquals('readyState before first request',
    -               goog.net.XmlHttp.ReadyState.UNINITIALIZED,
    -               xhr.getReadyState());
    -
    -  xhr.send('url');
    -  assertTrue('isActive after first request', xhr.isActive());
    -  assertEquals('readyState after first request',
    -               goog.net.XmlHttp.ReadyState.LOADING,
    -               xhr.getReadyState());
    -
    -  xhr.simulateResponse(200, '');
    -  assertFalse('isActive after first response', xhr.isActive());
    -  assertEquals('readyState after first response',
    -               goog.net.XmlHttp.ReadyState.COMPLETE,
    -               xhr.getReadyState());
    -
    -  xhr.send('url');
    -  assertTrue('isActive after second request', xhr.isActive());
    -  assertEquals('readyState after second request',
    -               goog.net.XmlHttp.ReadyState.LOADING,
    -               xhr.getReadyState());
    -}
    -
    -function testGetLastUri() {
    -  var xhr = new goog.testing.net.XhrIo();
    -  assertEquals('nothing sent yet, empty URI', '', xhr.getLastUri());
    -
    -  var requestUrl = 'http://www.example.com/';
    -  xhr.send(requestUrl);
    -  assertEquals('message sent, URI saved', requestUrl, xhr.getLastUri());
    -}
    -
    -function testGetLastMethod() {
    -  var xhr = new goog.testing.net.XhrIo();
    -  assertUndefined('nothing sent yet, empty method', xhr.getLastMethod());
    -
    -  var method = 'POKE';
    -  xhr.send('http://www.example.com/', method);
    -  assertEquals('message sent, method saved', method, xhr.getLastMethod());
    -  xhr.simulateResponse(200, '');
    -
    -  xhr.send('http://www.example.com/');
    -  assertEquals('message sent, method saved', 'GET', xhr.getLastMethod());
    -}
    -
    -function testGetLastContent() {
    -  var xhr = new goog.testing.net.XhrIo();
    -  assertUndefined('nothing sent yet, empty content', xhr.getLastContent());
    -
    -  var postContent = 'var=value&var2=value2';
    -  xhr.send('http://www.example.com/', undefined, postContent);
    -  assertEquals('POST message sent, content saved',
    -               postContent, xhr.getLastContent());
    -  xhr.simulateResponse(200, '');
    -
    -  xhr.send('http://www.example.com/');
    -  assertUndefined('GET message sent, content cleaned', xhr.getLastContent());
    -}
    -
    -function testGetLastRequestHeaders() {
    -  var xhr = new goog.testing.net.XhrIo();
    -  assertUndefined('nothing sent yet, empty headers',
    -                  xhr.getLastRequestHeaders());
    -
    -  xhr.send('http://www.example.com/', undefined, undefined,
    -      {'From': 'page@google.com'});
    -  assertObjectEquals('Request sent with extra headers, headers saved',
    -      {'From': 'page@google.com'},
    -      xhr.getLastRequestHeaders());
    -  xhr.simulateResponse(200, '');
    -
    -  xhr.send('http://www.example.com');
    -  assertUndefined('New request sent without extra headers',
    -      xhr.getLastRequestHeaders());
    -}
    -
    -function testGetResponseText() {
    -  // Text response came.
    -  var called = false;
    -  var xhr = new goog.testing.net.XhrIo();
    -  goog.events.listen(xhr, goog.net.EventType.SUCCESS, function(e) {
    -    called = true;
    -    assertEquals('text', e.target.getResponseText());
    -  });
    -  xhr.simulateResponse(200, 'text');
    -  assertTrue(called);
    -
    -  // XML response came.
    -  var called = false;
    -  var xhr = new goog.testing.net.XhrIo();
    -  var xml = goog.dom.xml.createDocument();
    -  xml.appendChild(xml.createElement('root'));
    -  goog.events.listen(xhr, goog.net.EventType.SUCCESS, function(e) {
    -    called = true;
    -    var text = e.target.getResponseText();
    -    assertTrue(/<root ?\/>/.test(text));
    -  });
    -  xhr.simulateResponse(200, xml);
    -  assertTrue(called);
    -}
    -
    -function testGetResponseJson() {
    -  // Valid JSON response came.
    -  var called = false;
    -  var xhr = new goog.testing.net.XhrIo();
    -  goog.events.listen(xhr, goog.net.EventType.SUCCESS, function(e) {
    -    called = true;
    -    assertArrayEquals([0, 1], e.target.getResponseJson());
    -  });
    -  xhr.simulateResponse(200, '[0, 1]');
    -  assertTrue(called);
    -
    -  // Valid JSON response with XSSI prefix encoded came.
    -  var called = false;
    -  var xhr = new goog.testing.net.XhrIo();
    -  goog.events.listen(xhr, goog.net.EventType.SUCCESS, function(e) {
    -    called = true;
    -    assertArrayEquals([0, 1], e.target.getResponseJson(')]}\', \n'));
    -  });
    -  xhr.simulateResponse(200, ')]}\', \n[0, 1]');
    -  assertTrue(called);
    -
    -  // Invalid JSON response came.
    -  var called = false;
    -  var xhr = new goog.testing.net.XhrIo();
    -  goog.events.listen(xhr, goog.net.EventType.SUCCESS, function(e) {
    -    called = true;
    -    assertThrows(e.target.getResponseJson);
    -  });
    -  xhr.simulateResponse(200, '[0, 1');
    -  assertTrue(called);
    -
    -  // XML response came.
    -  var called = false;
    -  var xhr = new goog.testing.net.XhrIo();
    -  var xml = goog.dom.xml.createDocument();
    -  xml.appendChild(xml.createElement('root'));
    -  goog.events.listen(xhr, goog.net.EventType.SUCCESS, function(e) {
    -    called = true;
    -    assertThrows(e.target.getResponseJson);
    -  });
    -  xhr.simulateResponse(200, xml);
    -  assertTrue(called);
    -}
    -
    -function testGetResponseXml() {
    -  // Text response came.
    -  var called = false;
    -  var xhr = new goog.testing.net.XhrIo();
    -  goog.events.listen(xhr, goog.net.EventType.SUCCESS, function(e) {
    -    called = true;
    -    assertNull(e.target.getResponseXml());
    -  });
    -  xhr.simulateResponse(200, 'text');
    -  assertTrue(called);
    -
    -  // XML response came.
    -  var called = false;
    -  var xhr = new goog.testing.net.XhrIo();
    -  var xml = goog.dom.xml.createDocument();
    -  xml.appendChild(xml.createElement('root'));
    -  goog.events.listen(xhr, goog.net.EventType.SUCCESS, function(e) {
    -    called = true;
    -    assertEquals(xml, e.target.getResponseXml());
    -  });
    -  xhr.simulateResponse(200, xml);
    -  assertTrue(called);
    -}
    -
    -function testGetResponseHeaders_noHeadersPresent() {
    -  var xhr = new goog.testing.net.XhrIo();
    -  var mockListener = mockControl.createFunctionMock();
    -  mockListener(new goog.testing.mockmatchers.InstanceOf(goog.events.Event))
    -      .$does(function(e) {
    -        assertTrue(e.type == goog.net.EventType.SUCCESS);
    -        assertUndefined(e.target.getResponseHeader('XHR'));
    -      });
    -  mockControl.$replayAll();
    -  goog.events.listen(xhr, goog.net.EventType.SUCCESS, mockListener);
    -  xhr.simulateResponse(200, '');
    -
    -  mockControl.$verifyAll();
    -  mockControl.$resetAll();
    -}
    -
    -function testGetResponseHeaders_headersPresent() {
    -  var xhr = new goog.testing.net.XhrIo();
    -  var mockListener = mockControl.createFunctionMock();
    -  mockListener(new goog.testing.mockmatchers.InstanceOf(goog.events.Event))
    -      .$does(function(e) {
    -        assertTrue(e.type == goog.net.EventType.SUCCESS);
    -        assertUndefined(e.target.getResponseHeader('XHR'));
    -        assertEquals(e.target.getResponseHeader('Pragma'), 'no-cache');
    -      });
    -  mockControl.$replayAll();
    -  goog.events.listen(xhr, goog.net.EventType.SUCCESS, mockListener);
    -  xhr.simulateResponse(200, '', {'Pragma': 'no-cache'});
    -
    -  mockControl.$verifyAll();
    -  mockControl.$resetAll();
    -}
    -
    -function testAbort_WhenNoPendingSentRequests() {
    -  var xhr = new goog.testing.net.XhrIo();
    -  var eventListener = mockControl.createFunctionMock();
    -  mockControl.$replayAll();
    -
    -  goog.events.listen(xhr, goog.net.EventType.COMPLETE, eventListener);
    -  goog.events.listen(xhr, goog.net.EventType.SUCCESS, eventListener);
    -  goog.events.listen(xhr, goog.net.EventType.ABORT, eventListener);
    -  goog.events.listen(xhr, goog.net.EventType.ERROR, eventListener);
    -  goog.events.listen(xhr, goog.net.EventType.READY, eventListener);
    -
    -  xhr.abort();
    -
    -  mockControl.$verifyAll();
    -  mockControl.$resetAll();
    -}
    -
    -function testAbort_PendingSentRequest() {
    -  var xhr = new goog.testing.net.XhrIo();
    -  var mockListener = mockControl.createFunctionMock();
    -
    -  mockListener(new goog.testing.mockmatchers.InstanceOf(goog.events.Event))
    -  .$does(function(e) {
    -        assertTrue(e.type == goog.net.EventType.COMPLETE);
    -        assertObjectEquals(e.target, xhr);
    -        assertEquals(e.target.getLastErrorCode(), goog.net.ErrorCode.ABORT);
    -        assertTrue(e.target.isActive());
    -      });
    -  mockListener(new goog.testing.mockmatchers.InstanceOf(goog.events.Event))
    -  .$does(function(e) {
    -        assertTrue(e.type == goog.net.EventType.ABORT);
    -        assertObjectEquals(e.target, xhr);
    -        assertTrue(e.target.isActive());
    -      });
    -  mockListener(new goog.testing.mockmatchers.InstanceOf(goog.events.Event))
    -  .$does(function(e) {
    -        assertTrue(e.type == goog.net.EventType.READY);
    -        assertObjectEquals(e.target, xhr);
    -        assertFalse(e.target.isActive());
    -      });
    -  mockControl.$replayAll();
    -
    -  goog.events.listen(xhr, goog.net.EventType.COMPLETE, mockListener);
    -  goog.events.listen(xhr, goog.net.EventType.SUCCESS, mockListener);
    -  goog.events.listen(xhr, goog.net.EventType.ABORT, mockListener);
    -  goog.events.listen(xhr, goog.net.EventType.ERROR, mockListener);
    -  goog.events.listen(xhr, goog.net.EventType.READY, mockListener);
    -  xhr.send('dummyurl');
    -  xhr.abort();
    -
    -  mockControl.$verifyAll();
    -  mockControl.$resetAll();
    -}
    -
    -function testEvents_Success() {
    -  var xhr = new goog.testing.net.XhrIo();
    -  var mockListener = mockControl.createFunctionMock();
    -
    -  var readyState = goog.net.XmlHttp.ReadyState.UNINITIALIZED;
    -  function readyStateListener(e) {
    -    assertEquals(e.type, goog.net.EventType.READY_STATE_CHANGE);
    -    assertObjectEquals(e.target, xhr);
    -    readyState++;
    -    assertEquals(e.target.getReadyState(), readyState);
    -    assertTrue(e.target.isActive());
    -  }
    -
    -  mockListener(new goog.testing.mockmatchers.InstanceOf(goog.events.Event))
    -  .$does(function(e) {
    -        assertEquals(e.type, goog.net.EventType.COMPLETE);
    -        assertObjectEquals(e.target, xhr);
    -        assertEquals(e.target.getLastErrorCode(), goog.net.ErrorCode.NO_ERROR);
    -        assertTrue(e.target.isActive());
    -      });
    -  mockListener(new goog.testing.mockmatchers.InstanceOf(goog.events.Event))
    -  .$does(function(e) {
    -        assertEquals(e.type, goog.net.EventType.SUCCESS);
    -        assertObjectEquals(e.target, xhr);
    -        assertTrue(e.target.isActive());
    -      });
    -  mockListener(new goog.testing.mockmatchers.InstanceOf(goog.events.Event))
    -  .$does(function(e) {
    -        assertEquals(e.type, goog.net.EventType.READY);
    -        assertObjectEquals(e.target, xhr);
    -        assertFalse(e.target.isActive());
    -      });
    -  mockControl.$replayAll();
    -
    -  goog.events.listen(xhr, goog.net.EventType.READY_STATE_CHANGE,
    -      readyStateListener);
    -  goog.events.listen(xhr, goog.net.EventType.COMPLETE, mockListener);
    -  goog.events.listen(xhr, goog.net.EventType.SUCCESS, mockListener);
    -  goog.events.listen(xhr, goog.net.EventType.ABORT, mockListener);
    -  goog.events.listen(xhr, goog.net.EventType.ERROR, mockListener);
    -  goog.events.listen(xhr, goog.net.EventType.READY, mockListener);
    -  xhr.send('dummyurl');
    -  xhr.simulateResponse(200, null);
    -
    -  mockControl.$verifyAll();
    -  mockControl.$resetAll();
    -}
    -
    -function testGetResponseHeaders() {
    -  var xhr = new goog.testing.net.XhrIo();
    -  var mockListener = mockControl.createFunctionMock();
    -  mockListener(new goog.testing.mockmatchers.InstanceOf(goog.events.Event))
    -      .$does(function(e) {
    -        var headers = e.target.getResponseHeaders();
    -        assertEquals(2, goog.object.getCount(headers));
    -        assertEquals('foo', headers['test1']);
    -        assertEquals('bar', headers['test2']);
    -      });
    -  mockControl.$replayAll();
    -  goog.events.listen(xhr, goog.net.EventType.SUCCESS, mockListener);
    -
    -  // Simulate an XHR with 2 headers.
    -  xhr.simulateResponse(200, '', {'test1': 'foo', 'test2': 'bar'});
    -
    -  mockControl.$verifyAll();
    -  mockControl.$resetAll();
    -}
    -
    -function testGetResponseHeadersWithColonInValue() {
    -  var xhr = new goog.testing.net.XhrIo();
    -  var mockListener = mockControl.createFunctionMock();
    -  mockListener(new goog.testing.mockmatchers.InstanceOf(goog.events.Event))
    -      .$does(function(e) {
    -        var headers = e.target.getResponseHeaders();
    -        assertEquals(1, goog.object.getCount(headers));
    -        assertEquals('f:o:o', headers['test1']);
    -      });
    -  mockControl.$replayAll();
    -  goog.events.listen(xhr, goog.net.EventType.SUCCESS, mockListener);
    -
    -  // Simulate an XHR with a colon in the http header value.
    -  xhr.simulateResponse(200, '', {'test1': 'f:o:o'});
    -
    -  mockControl.$verifyAll();
    -  mockControl.$resetAll();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/net/xhriopool.js b/src/database/third_party/closure-library/closure/goog/testing/net/xhriopool.js
    deleted file mode 100644
    index a2baa011994..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/net/xhriopool.js
    +++ /dev/null
    @@ -1,65 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview An XhrIo pool that uses a single mock XHR object for testing.
    - *
    - */
    -
    -goog.provide('goog.testing.net.XhrIoPool');
    -
    -goog.require('goog.net.XhrIoPool');
    -goog.require('goog.testing.net.XhrIo');
    -
    -
    -
    -/**
    - * A pool containing a single mock XhrIo object.
    - *
    - * @param {goog.testing.net.XhrIo=} opt_xhr The mock XhrIo object.
    - * @constructor
    - * @extends {goog.net.XhrIoPool}
    - * @final
    - */
    -goog.testing.net.XhrIoPool = function(opt_xhr) {
    -  /**
    -   * The mock XhrIo object.
    -   * @type {!goog.testing.net.XhrIo}
    -   * @private
    -   */
    -  this.xhr_ = opt_xhr || new goog.testing.net.XhrIo();
    -
    -  // Run this after setting xhr_ because xhr_ is used to initialize the pool.
    -  goog.testing.net.XhrIoPool.base(this, 'constructor', undefined, 1, 1);
    -};
    -goog.inherits(goog.testing.net.XhrIoPool, goog.net.XhrIoPool);
    -
    -
    -/**
    - * @override
    - * @suppress {invalidCasts}
    - */
    -goog.testing.net.XhrIoPool.prototype.createObject = function() {
    -  return (/** @type {!goog.net.XhrIo} */ (this.xhr_));
    -};
    -
    -
    -/**
    - * Get the mock XhrIo used by this pool.
    - *
    - * @return {!goog.testing.net.XhrIo} The mock XhrIo.
    - */
    -goog.testing.net.XhrIoPool.prototype.getXhr = function() {
    -  return this.xhr_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/objectpropertystring.js b/src/database/third_party/closure-library/closure/goog/testing/objectpropertystring.js
    deleted file mode 100644
    index 18c93d96aa2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/objectpropertystring.js
    +++ /dev/null
    @@ -1,68 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Helper for passing property names as string literals in
    - * compiled test code.
    - *
    - */
    -
    -goog.provide('goog.testing.ObjectPropertyString');
    -
    -
    -
    -/**
    - * Object to pass a property name as a string literal and its containing object
    - * when the JSCompiler is rewriting these names. This should only be used in
    - * test code.
    - *
    - * @param {Object} object The containing object.
    - * @param {Object|string} propertyString Property name as a string literal.
    - * @constructor
    - * @final
    - */
    -goog.testing.ObjectPropertyString = function(object, propertyString) {
    -  this.object_ = object;
    -  this.propertyString_ = /** @type {string} */ (propertyString);
    -};
    -
    -
    -/**
    - * @type {Object}
    - * @private
    - */
    -goog.testing.ObjectPropertyString.prototype.object_;
    -
    -
    -/**
    - * @type {string}
    - * @private
    - */
    -goog.testing.ObjectPropertyString.prototype.propertyString_;
    -
    -
    -/**
    - * @return {Object} The object.
    - */
    -goog.testing.ObjectPropertyString.prototype.getObject = function() {
    -  return this.object_;
    -};
    -
    -
    -/**
    - * @return {string} The property string.
    - */
    -goog.testing.ObjectPropertyString.prototype.getPropertyString = function() {
    -  return this.propertyString_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/performancetable.css b/src/database/third_party/closure-library/closure/goog/testing/performancetable.css
    deleted file mode 100644
    index 28056d02641..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/performancetable.css
    +++ /dev/null
    @@ -1,46 +0,0 @@
    -/*
    - * Copyright 2009 The Closure Library Authors. All Rights Reserved.
    - *
    - * Use of this source code is governed by the Apache License, Version 2.0.
    - * See the COPYING file for details.
    - */
    -
    -/* Author: attila@google.com (Attila Bodis) */
    -/* Author: nicksantos@google.com (Nick Santos) */
    -
    -table.test-results {
    -  font: 12px "Courier New", Courier, monospace;
    -}
    -
    -table.test-results thead th {
    -  padding: 2px;
    -  color: #fff;
    -  background-color: #369;
    -  text-align: center;
    -}
    -
    -table.test-results tbody td {
    -  padding: 2px;
    -  color: #333;
    -  background-color: #ffc;
    -  text-align: right;
    -}
    -
    -table.test-results tbody td.test-description {
    -  text-align: left;
    -}
    -
    -table.test-results tbody td.test-average {
    -  color: #000;
    -  font-weight: bold;
    -}
    -
    -table.test-results tbody tr.test-suspicious td.test-standard-deviation {
    -  color: #800;
    -}
    -
    -table.test-results tbody td.test-error {
    -  color: #800;
    -  font-weight: bold;
    -  text-align: center;
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/performancetable.js b/src/database/third_party/closure-library/closure/goog/testing/performancetable.js
    deleted file mode 100644
    index c89c2b68bbb..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/performancetable.js
    +++ /dev/null
    @@ -1,191 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A table for showing the results of performance testing.
    - *
    - * {@see goog.testing.benchmark} for an easy way to use this functionality.
    - *
    - * @author attila@google.com (Attila Bodis)
    - * @author nicksantos@google.com (Nick Santos)
    - */
    -
    -goog.provide('goog.testing.PerformanceTable');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.testing.PerformanceTimer');
    -
    -
    -
    -/**
    - * A UI widget that runs performance tests and displays the results.
    - * @param {Element} root The element where the table should be attached.
    - * @param {goog.testing.PerformanceTimer=} opt_timer A timer to use for
    - *     executing functions and profiling them.
    - * @param {number=} opt_precision Number of digits of precision to include in
    - *     results.  Defaults to 0.
    - * @param {number=} opt_numSamples The number of samples to take. Defaults to 5.
    - * @constructor
    - * @final
    - */
    -goog.testing.PerformanceTable = function(
    -    root, opt_timer, opt_precision, opt_numSamples) {
    -  /**
    -   * Where the table should be attached.
    -   * @private {Element}
    -   */
    -  this.root_ = root;
    -
    -  /**
    -   * Number of digits of precision to include in results.
    -   * Defaults to 0.
    -   * @private {number}
    -   */
    -  this.precision_ = opt_precision || 0;
    -
    -  var timer = opt_timer;
    -  if (!timer) {
    -    timer = new goog.testing.PerformanceTimer();
    -    timer.setNumSamples(opt_numSamples || 5);
    -    timer.setDiscardOutliers(true);
    -  }
    -
    -  /**
    -   * A timer for running the tests.
    -   * @private {goog.testing.PerformanceTimer}
    -   */
    -  this.timer_ = timer;
    -
    -  this.initRoot_();
    -};
    -
    -
    -/**
    - * @return {goog.testing.PerformanceTimer} The timer being used.
    - */
    -goog.testing.PerformanceTable.prototype.getTimer = function() {
    -  return this.timer_;
    -};
    -
    -
    -/**
    - * Render the initial table.
    - * @private
    - */
    -goog.testing.PerformanceTable.prototype.initRoot_ = function() {
    -  this.root_.innerHTML =
    -      '<table class="test-results" cellspacing="1">' +
    -      '  <thead>' +
    -      '    <tr>' +
    -      '      <th rowspan="2">Test Description</th>' +
    -      '      <th rowspan="2">Runs</th>' +
    -      '      <th colspan="4">Results (ms)</th>' +
    -      '    </tr>' +
    -      '    <tr>' +
    -      '      <th>Average</th>' +
    -      '      <th>Std Dev</th>' +
    -      '      <th>Minimum</th>' +
    -      '      <th>Maximum</th>' +
    -      '    </tr>' +
    -      '  </thead>' +
    -      '  <tbody>' +
    -      '  </tbody>' +
    -      '</table>';
    -};
    -
    -
    -/**
    - * @return {Element} The body of the table.
    - * @private
    - */
    -goog.testing.PerformanceTable.prototype.getTableBody_ = function() {
    -  return this.root_.getElementsByTagName(goog.dom.TagName.TBODY)[0];
    -};
    -
    -
    -/**
    - * Round to the specified precision.
    - * @param {number} num The number to round.
    - * @return {string} The rounded number, as a string.
    - * @private
    - */
    -goog.testing.PerformanceTable.prototype.round_ = function(num) {
    -  var factor = Math.pow(10, this.precision_);
    -  return String(Math.round(num * factor) / factor);
    -};
    -
    -
    -/**
    - * Run the given function with the performance timer, and show the results.
    - * @param {Function} fn The function to run.
    - * @param {string=} opt_desc A description to associate with this run.
    - */
    -goog.testing.PerformanceTable.prototype.run = function(fn, opt_desc) {
    -  this.runTask(
    -      new goog.testing.PerformanceTimer.Task(/** @type {function()} */ (fn)),
    -      opt_desc);
    -};
    -
    -
    -/**
    - * Run the given task with the performance timer, and show the results.
    - * @param {goog.testing.PerformanceTimer.Task} task The performance timer task
    - *     to run.
    - * @param {string=} opt_desc A description to associate with this run.
    - */
    -goog.testing.PerformanceTable.prototype.runTask = function(task, opt_desc) {
    -  var results = this.timer_.runTask(task);
    -  this.recordResults(results, opt_desc);
    -};
    -
    -
    -/**
    - * Record a performance timer results object to the performance table. See
    - * {@code goog.testing.PerformanceTimer} for details of the format of this
    - * object.
    - * @param {Object} results The performance timer results object.
    - * @param {string=} opt_desc A description to associate with these results.
    - */
    -goog.testing.PerformanceTable.prototype.recordResults = function(
    -    results, opt_desc) {
    -  var average = results['average'];
    -  var standardDeviation = results['standardDeviation'];
    -  var isSuspicious = average < 0 || standardDeviation > average * .5;
    -  var resultsRow = goog.dom.createDom('tr', null,
    -      goog.dom.createDom('td', 'test-description',
    -          opt_desc || 'No description'),
    -      goog.dom.createDom('td', 'test-count', String(results['count'])),
    -      goog.dom.createDom('td', 'test-average', this.round_(average)),
    -      goog.dom.createDom('td', 'test-standard-deviation',
    -          this.round_(standardDeviation)),
    -      goog.dom.createDom('td', 'test-minimum', String(results['minimum'])),
    -      goog.dom.createDom('td', 'test-maximum', String(results['maximum'])));
    -  if (isSuspicious) {
    -    resultsRow.className = 'test-suspicious';
    -  }
    -  this.getTableBody_().appendChild(resultsRow);
    -};
    -
    -
    -/**
    - * Report an error in the table.
    - * @param {*} reason The reason for the error.
    - */
    -goog.testing.PerformanceTable.prototype.reportError = function(reason) {
    -  this.getTableBody_().appendChild(
    -      goog.dom.createDom('tr', null,
    -          goog.dom.createDom('td', {'class': 'test-error', 'colSpan': 5},
    -              String(reason))));
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/performancetimer.js b/src/database/third_party/closure-library/closure/goog/testing/performancetimer.js
    deleted file mode 100644
    index f477105b90c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/performancetimer.js
    +++ /dev/null
    @@ -1,418 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Performance timer.
    - *
    - * {@see goog.testing.benchmark} for an easy way to use this functionality.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.testing.PerformanceTimer');
    -goog.provide('goog.testing.PerformanceTimer.Task');
    -
    -goog.require('goog.array');
    -goog.require('goog.async.Deferred');
    -goog.require('goog.math');
    -
    -
    -
    -/**
    - * Creates a performance timer that runs test functions a number of times to
    - * generate timing samples, and provides performance statistics (minimum,
    - * maximum, average, and standard deviation).
    - * @param {number=} opt_numSamples Number of times to run the test function;
    - *     defaults to 10.
    - * @param {number=} opt_timeoutInterval Number of milliseconds after which the
    - *     test is to be aborted; defaults to 5 seconds (5,000ms).
    - * @constructor
    - */
    -goog.testing.PerformanceTimer = function(opt_numSamples, opt_timeoutInterval) {
    -  /**
    -   * Number of times the test function is to be run; defaults to 10.
    -   * @private {number}
    -   */
    -  this.numSamples_ = opt_numSamples || 10;
    -
    -  /**
    -   * Number of milliseconds after which the test is to be aborted; defaults to
    -   * 5,000ms.
    -   * @private {number}
    -   */
    -  this.timeoutInterval_ = opt_timeoutInterval || 5000;
    -
    -  /**
    -   * Whether to discard outliers (i.e. the smallest and the largest values)
    -   * from the sample set before computing statistics.  Defaults to false.
    -   * @private {boolean}
    -   */
    -  this.discardOutliers_ = false;
    -};
    -
    -
    -/**
    - * A function whose subsequent calls differ in milliseconds. Used to calculate
    - * the start and stop checkpoint times for runs. Note that high performance
    - * timers do not necessarily return the current time in milliseconds.
    - * @return {number}
    - * @private
    - */
    -goog.testing.PerformanceTimer.now_ = function() {
    -  // goog.now is used in DEBUG mode to make the class easier to test.
    -  return !goog.DEBUG && window.performance && window.performance.now ?
    -      window.performance.now() :
    -      goog.now();
    -};
    -
    -
    -/**
    - * @return {number} The number of times the test function will be run.
    - */
    -goog.testing.PerformanceTimer.prototype.getNumSamples = function() {
    -  return this.numSamples_;
    -};
    -
    -
    -/**
    - * Sets the number of times the test function will be run.
    - * @param {number} numSamples Number of times to run the test function.
    - */
    -goog.testing.PerformanceTimer.prototype.setNumSamples = function(numSamples) {
    -  this.numSamples_ = numSamples;
    -};
    -
    -
    -/**
    - * @return {number} The number of milliseconds after which the test times out.
    - */
    -goog.testing.PerformanceTimer.prototype.getTimeoutInterval = function() {
    -  return this.timeoutInterval_;
    -};
    -
    -
    -/**
    - * Sets the number of milliseconds after which the test times out.
    - * @param {number} timeoutInterval Timeout interval in ms.
    - */
    -goog.testing.PerformanceTimer.prototype.setTimeoutInterval = function(
    -    timeoutInterval) {
    -  this.timeoutInterval_ = timeoutInterval;
    -};
    -
    -
    -/**
    - * Sets whether to ignore the smallest and the largest values when computing
    - * stats.
    - * @param {boolean} discard Whether to discard outlier values.
    - */
    -goog.testing.PerformanceTimer.prototype.setDiscardOutliers = function(discard) {
    -  this.discardOutliers_ = discard;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether outlier values are discarded prior to computing
    - *     stats.
    - */
    -goog.testing.PerformanceTimer.prototype.isDiscardOutliers = function() {
    -  return this.discardOutliers_;
    -};
    -
    -
    -/**
    - * Executes the test function the required number of times (or until the
    - * test run exceeds the timeout interval, whichever comes first).  Returns
    - * an object containing the following:
    - * <pre>
    - *   {
    - *     'average': average execution time (ms)
    - *     'count': number of executions (may be fewer than expected due to timeout)
    - *     'maximum': longest execution time (ms)
    - *     'minimum': shortest execution time (ms)
    - *     'standardDeviation': sample standard deviation (ms)
    - *     'total': total execution time (ms)
    - *   }
    - * </pre>
    - *
    - * @param {Function} testFn Test function whose performance is to
    - *     be measured.
    - * @return {!Object} Object containing performance stats.
    - */
    -goog.testing.PerformanceTimer.prototype.run = function(testFn) {
    -  return this.runTask(new goog.testing.PerformanceTimer.Task(
    -      /** @type {goog.testing.PerformanceTimer.TestFunction} */ (testFn)));
    -};
    -
    -
    -/**
    - * Executes the test function of the specified task as described in
    - * {@code run}. In addition, if specified, the set up and tear down functions of
    - * the task are invoked before and after each invocation of the test function.
    - * @see goog.testing.PerformanceTimer#run
    - * @param {goog.testing.PerformanceTimer.Task} task A task describing the test
    - *     function to invoke.
    - * @return {!Object} Object containing performance stats.
    - */
    -goog.testing.PerformanceTimer.prototype.runTask = function(task) {
    -  var samples = [];
    -  var testStart = goog.testing.PerformanceTimer.now_();
    -  var totalRunTime = 0;
    -
    -  var testFn = task.getTest();
    -  var setUpFn = task.getSetUp();
    -  var tearDownFn = task.getTearDown();
    -
    -  for (var i = 0; i < this.numSamples_ && totalRunTime <= this.timeoutInterval_;
    -       i++) {
    -    setUpFn();
    -    var sampleStart = goog.testing.PerformanceTimer.now_();
    -    testFn();
    -    var sampleEnd = goog.testing.PerformanceTimer.now_();
    -    tearDownFn();
    -    samples[i] = sampleEnd - sampleStart;
    -    totalRunTime = sampleEnd - testStart;
    -  }
    -
    -  return this.finishTask_(samples);
    -};
    -
    -
    -/**
    - * Finishes the run of a task by creating a result object from samples, in the
    - * format described in {@code run}.
    - * @see goog.testing.PerformanceTimer#run
    - * @return {!Object} Object containing performance stats.
    - * @private
    - */
    -goog.testing.PerformanceTimer.prototype.finishTask_ = function(samples) {
    -  if (this.discardOutliers_ && samples.length > 2) {
    -    goog.array.remove(samples, Math.min.apply(null, samples));
    -    goog.array.remove(samples, Math.max.apply(null, samples));
    -  }
    -
    -  return goog.testing.PerformanceTimer.createResults(samples);
    -};
    -
    -
    -/**
    - * Executes the test function of the specified task asynchronously. The test
    - * function is expected to take a callback as input and has to call it to signal
    - * that it's done. In addition, if specified, the setUp and tearDown functions
    - * of the task are invoked before and after each invocation of the test
    - * function. Note that setUp/tearDown functions take a callback as input and
    - * must call this callback when they are done.
    - * @see goog.testing.PerformanceTimer#run
    - * @param {goog.testing.PerformanceTimer.Task} task A task describing the test
    - *     function to invoke.
    - * @return {!goog.async.Deferred} The deferred result, eventually an object
    - *     containing performance stats.
    - */
    -goog.testing.PerformanceTimer.prototype.runAsyncTask = function(task) {
    -  var samples = [];
    -  var testStart = goog.testing.PerformanceTimer.now_();
    -
    -  var testFn = task.getTest();
    -  var setUpFn = task.getSetUp();
    -  var tearDownFn = task.getTearDown();
    -
    -  // Note that this uses a separate code path from runTask() because
    -  // implementing runTask() in terms of runAsyncTask() could easily cause
    -  // a stack overflow if there are many iterations.
    -  var result = new goog.async.Deferred();
    -  this.runAsyncTaskSample_(testFn, setUpFn, tearDownFn, result, samples,
    -      testStart);
    -  return result;
    -};
    -
    -
    -/**
    - * Runs a task once, waits for the test function to complete asynchronously
    - * and starts another run if not enough samples have been collected. Otherwise
    - * finishes this task.
    - * @param {goog.testing.PerformanceTimer.TestFunction} testFn The test function.
    - * @param {goog.testing.PerformanceTimer.TestFunction} setUpFn The set up
    - *     function that will be called once before the test function is run.
    - * @param {goog.testing.PerformanceTimer.TestFunction} tearDownFn The set up
    - *     function that will be called once after the test function completed.
    - * @param {!goog.async.Deferred} result The deferred result, eventually an
    - *     object containing performance stats.
    - * @param {!Array<number>} samples The time samples from all runs of the test
    - *     function so far.
    - * @param {number} testStart The timestamp when the first sample was started.
    - * @private
    - */
    -goog.testing.PerformanceTimer.prototype.runAsyncTaskSample_ = function(testFn,
    -    setUpFn, tearDownFn, result, samples, testStart) {
    -  var timer = this;
    -  timer.handleOptionalDeferred_(setUpFn, function() {
    -    var sampleStart = goog.testing.PerformanceTimer.now_();
    -    timer.handleOptionalDeferred_(testFn, function() {
    -      var sampleEnd = goog.testing.PerformanceTimer.now_();
    -      timer.handleOptionalDeferred_(tearDownFn, function() {
    -        samples.push(sampleEnd - sampleStart);
    -        var totalRunTime = sampleEnd - testStart;
    -        if (samples.length < timer.numSamples_ &&
    -            totalRunTime <= timer.timeoutInterval_) {
    -          timer.runAsyncTaskSample_(testFn, setUpFn, tearDownFn, result,
    -              samples, testStart);
    -        } else {
    -          result.callback(timer.finishTask_(samples));
    -        }
    -      });
    -    });
    -  });
    -};
    -
    -
    -/**
    - * Execute a function that optionally returns a deferred object and continue
    - * with the given continuation function only once the deferred object has a
    - * result.
    - * @param {goog.testing.PerformanceTimer.TestFunction} deferredFactory The
    - *     function that optionally returns a deferred object.
    - * @param {function()} continuationFunction The function that should be called
    - *     after the optional deferred has a result.
    - * @private
    - */
    -goog.testing.PerformanceTimer.prototype.handleOptionalDeferred_ = function(
    -    deferredFactory, continuationFunction) {
    -  var deferred = deferredFactory();
    -  if (deferred) {
    -    deferred.addCallback(continuationFunction);
    -  } else {
    -    continuationFunction();
    -  }
    -};
    -
    -
    -/**
    - * Creates a performance timer results object by analyzing a given array of
    - * sample timings.
    - * @param {Array<number>} samples The samples to analyze.
    - * @return {!Object} Object containing performance stats.
    - */
    -goog.testing.PerformanceTimer.createResults = function(samples) {
    -  return {
    -    'average': goog.math.average.apply(null, samples),
    -    'count': samples.length,
    -    'maximum': Math.max.apply(null, samples),
    -    'minimum': Math.min.apply(null, samples),
    -    'standardDeviation': goog.math.standardDeviation.apply(null, samples),
    -    'total': goog.math.sum.apply(null, samples)
    -  };
    -};
    -
    -
    -/**
    - * A test function whose performance should be measured or a setUp/tearDown
    - * function. It may optionally return a deferred object. If it does so, the
    - * test harness will assume the function is asynchronous and it must signal
    - * that it's done by setting an (empty) result on the deferred object. If the
    - * function doesn't return anything, the test harness will assume it's
    - * synchronous.
    - * @typedef {function():(goog.async.Deferred|undefined)}
    - */
    -goog.testing.PerformanceTimer.TestFunction;
    -
    -
    -
    -/**
    - * A task for the performance timer to measure. Callers can specify optional
    - * setUp and tearDown methods to control state before and after each run of the
    - * test function.
    - * @param {goog.testing.PerformanceTimer.TestFunction} test Test function whose
    - *     performance is to be measured.
    - * @constructor
    - * @final
    - */
    -goog.testing.PerformanceTimer.Task = function(test) {
    -  /**
    -   * The test function to time.
    -   * @type {goog.testing.PerformanceTimer.TestFunction}
    -   * @private
    -   */
    -  this.test_ = test;
    -};
    -
    -
    -/**
    - * An optional set up function to run before each invocation of the test
    - * function.
    - * @type {goog.testing.PerformanceTimer.TestFunction}
    - * @private
    - */
    -goog.testing.PerformanceTimer.Task.prototype.setUp_ = goog.nullFunction;
    -
    -
    -/**
    - * An optional tear down function to run after each invocation of the test
    - * function.
    - * @type {goog.testing.PerformanceTimer.TestFunction}
    - * @private
    - */
    -goog.testing.PerformanceTimer.Task.prototype.tearDown_ = goog.nullFunction;
    -
    -
    -/**
    - * @return {goog.testing.PerformanceTimer.TestFunction} The test function to
    - *     time.
    - */
    -goog.testing.PerformanceTimer.Task.prototype.getTest = function() {
    -  return this.test_;
    -};
    -
    -
    -/**
    - * Specifies a set up function to be invoked before each invocation of the test
    - * function.
    - * @param {goog.testing.PerformanceTimer.TestFunction} setUp The set up
    - *     function.
    - * @return {!goog.testing.PerformanceTimer.Task} This task.
    - */
    -goog.testing.PerformanceTimer.Task.prototype.withSetUp = function(setUp) {
    -  this.setUp_ = setUp;
    -  return this;
    -};
    -
    -
    -/**
    - * @return {goog.testing.PerformanceTimer.TestFunction} The set up function or
    - *     the default no-op function if none was specified.
    - */
    -goog.testing.PerformanceTimer.Task.prototype.getSetUp = function() {
    -  return this.setUp_;
    -};
    -
    -
    -/**
    - * Specifies a tear down function to be invoked after each invocation of the
    - * test function.
    - * @param {goog.testing.PerformanceTimer.TestFunction} tearDown The tear down
    - *     function.
    - * @return {!goog.testing.PerformanceTimer.Task} This task.
    - */
    -goog.testing.PerformanceTimer.Task.prototype.withTearDown = function(tearDown) {
    -  this.tearDown_ = tearDown;
    -  return this;
    -};
    -
    -
    -/**
    - * @return {goog.testing.PerformanceTimer.TestFunction} The tear down function
    - *     or the default no-op function if none was specified.
    - */
    -goog.testing.PerformanceTimer.Task.prototype.getTearDown = function() {
    -  return this.tearDown_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/performancetimer_test.html b/src/database/third_party/closure-library/closure/goog/testing/performancetimer_test.html
    deleted file mode 100644
    index 232aa736dae..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/performancetimer_test.html
    +++ /dev/null
    @@ -1,27 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -Author:  attila@google.com (Attila Bodis)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.testing.PerformanceTimer
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.PerformanceTimerTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="sandbox">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/performancetimer_test.js b/src/database/third_party/closure-library/closure/goog/testing/performancetimer_test.js
    deleted file mode 100644
    index fe23bf5f5a3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/performancetimer_test.js
    +++ /dev/null
    @@ -1,198 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.PerformanceTimerTest');
    -goog.setTestOnly('goog.testing.PerformanceTimerTest');
    -
    -goog.require('goog.async.Deferred');
    -goog.require('goog.dom');
    -goog.require('goog.math');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.PerformanceTimer');
    -goog.require('goog.testing.jsunit');
    -
    -var mockClock;
    -var sandbox;
    -var timer;
    -function setUpPage() {
    -  sandbox = document.getElementById('sandbox');
    -}
    -
    -function setUp() {
    -  mockClock = new goog.testing.MockClock(true);
    -  timer = new goog.testing.PerformanceTimer();
    -}
    -
    -function tearDown() {
    -  mockClock.dispose();
    -  timer = null;
    -  goog.dom.removeChildren(sandbox);
    -}
    -
    -function testConstructor() {
    -  assertTrue('Timer must be an instance of goog.testing.PerformanceTimer',
    -      timer instanceof goog.testing.PerformanceTimer);
    -  assertEquals('Timer must collect the default number of samples', 10,
    -      timer.getNumSamples());
    -  assertEquals('Timer must have the default timeout interval', 5000,
    -      timer.getTimeoutInterval());
    -}
    -
    -function testRun_noSetUpOrTearDown() {
    -  runAndAssert(false, false, false);
    -}
    -
    -function testRun_withSetup() {
    -  runAndAssert(true, false, false);
    -}
    -
    -function testRun_withTearDown() {
    -  runAndAssert(false, true, false);
    -}
    -
    -function testRun_withSetUpAndTearDown() {
    -  runAndAssert(true, true, false);
    -}
    -
    -function testRunAsync_noSetUpOrTearDown() {
    -  runAndAssert(false, false, true);
    -}
    -
    -function testRunAsync_withSetup() {
    -  runAndAssert(true, false, true);
    -}
    -
    -function testRunAsync_withTearDown() {
    -  runAndAssert(false, true, true);
    -}
    -
    -function testRunAsync_withSetUpAndTearDown() {
    -  runAndAssert(true, true, true);
    -}
    -
    -function runAndAssert(useSetUp, useTearDown, runAsync) {
    -  var fakeExecutionTime = [100, 95, 98, 104, 130, 101, 96, 98, 90, 103];
    -  var count = 0;
    -  var testFunction = function() {
    -    mockClock.tick(fakeExecutionTime[count++]);
    -    if (runAsync) {
    -      var deferred = new goog.async.Deferred();
    -      deferred.callback();
    -      return deferred;
    -    }
    -  };
    -
    -  var setUpCount = 0;
    -  var setUpFunction = function() {
    -    // Should have no effect on total time.
    -    mockClock.tick(7);
    -    setUpCount++;
    -    if (runAsync) {
    -      var deferred = new goog.async.Deferred();
    -      deferred.callback();
    -      return deferred;
    -    }
    -  };
    -
    -  var tearDownCount = 0;
    -  var tearDownFunction = function() {
    -    // Should have no effect on total time.
    -    mockClock.tick(11);
    -    tearDownCount++;
    -    if (runAsync) {
    -      var deferred = new goog.async.Deferred();
    -      deferred.callback();
    -      return deferred;
    -    }
    -  };
    -
    -  // Fast test function should complete successfully in under 5 seconds...
    -  var task = new goog.testing.PerformanceTimer.Task(testFunction);
    -  if (useSetUp) {
    -    task.withSetUp(setUpFunction);
    -  }
    -  if (useTearDown) {
    -    task.withTearDown(tearDownFunction);
    -  }
    -  if (runAsync) {
    -    var assertsRan = false;
    -    var deferred = timer.runAsyncTask(task);
    -    deferred.addCallback(
    -        function(results) {
    -          assertsRan = assertResults(results, useSetUp, useTearDown,
    -              setUpCount, tearDownCount, fakeExecutionTime);
    -        });
    -    assertTrue(assertsRan);
    -  } else {
    -    var results = timer.runTask(task);
    -    assertResults(results, useSetUp, useTearDown, setUpCount, tearDownCount,
    -        fakeExecutionTime);
    -  }
    -}
    -
    -function assertResults(results, useSetUp, useTearDown, setUpCount,
    -    tearDownCount, fakeExecutionTime) {
    -  assertNotNull('Results must be available.', results);
    -
    -  assertEquals('Average is wrong.',
    -      goog.math.average.apply(null, fakeExecutionTime), results['average']);
    -  assertEquals('Standard deviation is wrong.',
    -      goog.math.standardDeviation.apply(null, fakeExecutionTime),
    -      results['standardDeviation']);
    -
    -  assertEquals('Count must be as expected.', 10, results['count']);
    -  assertEquals('Maximum is wrong.', 130, results['maximum']);
    -  assertEquals('Mimimum is wrong.', 90, results['minimum']);
    -  assertEquals('Total must be a nonnegative number.',
    -      goog.math.sum.apply(null, fakeExecutionTime), results['total']);
    -
    -  assertEquals('Set up count must be as expected.',
    -      useSetUp ? 10 : 0, setUpCount);
    -  assertEquals('Tear down count must be as expected.',
    -      useTearDown ? 10 : 0, tearDownCount);
    -
    -  return true;
    -}
    -
    -function testTimeout() {
    -  var count = 0;
    -  var testFunction = function() {
    -    mockClock.tick(100);
    -    ++count;
    -  };
    -
    -  timer.setNumSamples(200);
    -  timer.setTimeoutInterval(2500);
    -  var results = timer.run(testFunction);
    -
    -  assertNotNull('Results must be available', results);
    -  assertEquals('Count is wrong', count, results['count']);
    -  assertTrue('Count must less than expected',
    -      results['count'] < timer.getNumSamples());
    -}
    -
    -function testCreateResults() {
    -  var samples = [53, 0, 103];
    -  var expectedResults = {
    -    'average': 52,
    -    'count': 3,
    -    'maximum': 103,
    -    'minimum': 0,
    -    'standardDeviation': goog.math.standardDeviation.apply(null, samples),
    -    'total': 156
    -  };
    -  assertObjectEquals(
    -      expectedResults,
    -      goog.testing.PerformanceTimer.createResults(samples));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/propertyreplacer.js b/src/database/third_party/closure-library/closure/goog/testing/propertyreplacer.js
    deleted file mode 100644
    index 3a8b882d8eb..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/propertyreplacer.js
    +++ /dev/null
    @@ -1,245 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Helper class for creating stubs for testing.
    - *
    - */
    -
    -goog.provide('goog.testing.PropertyReplacer');
    -
    -/** @suppress {extraRequire} Needed for some tests to compile. */
    -goog.require('goog.testing.ObjectPropertyString');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Helper class for stubbing out variables and object properties for unit tests.
    - * This class can change the value of some variables before running the test
    - * cases, and to reset them in the tearDown phase.
    - * See googletest.StubOutForTesting as an analogy in Python:
    - * http://protobuf.googlecode.com/svn/trunk/python/stubout.py
    - *
    - * Example usage:
    - * <pre>var stubs = new goog.testing.PropertyReplacer();
    - *
    - * function setUp() {
    - *   // Mock functions used in all test cases.
    - *   stubs.set(Math, 'random', function() {
    - *     return 4;  // Chosen by fair dice roll. Guaranteed to be random.
    - *   });
    - * }
    - *
    - * function tearDown() {
    - *   stubs.reset();
    - * }
    - *
    - * function testThreeDice() {
    - *   // Mock a constant used only in this test case.
    - *   stubs.set(goog.global, 'DICE_COUNT', 3);
    - *   assertEquals(12, rollAllDice());
    - * }</pre>
    - *
    - * Constraints on altered objects:
    - * <ul>
    - *   <li>DOM subclasses aren't supported.
    - *   <li>The value of the objects' constructor property must either be equal to
    - *       the real constructor or kept untouched.
    - * </ul>
    - *
    - * @constructor
    - * @final
    - */
    -goog.testing.PropertyReplacer = function() {
    -  /**
    -   * Stores the values changed by the set() method in chronological order.
    -   * Its items are objects with 3 fields: 'object', 'key', 'value'. The
    -   * original value for the given key in the given object is stored under the
    -   * 'value' key.
    -   * @type {Array<Object>}
    -   * @private
    -   */
    -  this.original_ = [];
    -};
    -
    -
    -/**
    - * Indicates that a key didn't exist before having been set by the set() method.
    - * @private @const
    - */
    -goog.testing.PropertyReplacer.NO_SUCH_KEY_ = {};
    -
    -
    -/**
    - * Tells if the given key exists in the object. Ignores inherited fields.
    - * @param {Object|Function} obj The JavaScript or native object or function
    - *     whose key is to be checked.
    - * @param {string} key The key to check.
    - * @return {boolean} Whether the object has the key as own key.
    - * @private
    - */
    -goog.testing.PropertyReplacer.hasKey_ = function(obj, key) {
    -  if (!(key in obj)) {
    -    return false;
    -  }
    -  // hasOwnProperty is only reliable with JavaScript objects. It returns false
    -  // for built-in DOM attributes.
    -  if (Object.prototype.hasOwnProperty.call(obj, key)) {
    -    return true;
    -  }
    -  // In all browsers except Opera obj.constructor never equals to Object if
    -  // obj is an instance of a native class. In Opera we have to fall back on
    -  // examining obj.toString().
    -  if (obj.constructor == Object &&
    -      (!goog.userAgent.OPERA ||
    -          Object.prototype.toString.call(obj) == '[object Object]')) {
    -    return false;
    -  }
    -  try {
    -    // Firefox hack to consider "className" part of the HTML elements or
    -    // "body" part of document. Although they are defined in the prototype of
    -    // HTMLElement or Document, accessing them this way throws an exception.
    -    // <pre>
    -    //   var dummy = document.body.constructor.prototype.className
    -    //   [Exception... "Cannot modify properties of a WrappedNative"]
    -    // </pre>
    -    var dummy = obj.constructor.prototype[key];
    -  } catch (e) {
    -    return true;
    -  }
    -  return !(key in obj.constructor.prototype);
    -};
    -
    -
    -/**
    - * Deletes a key from an object. Sets it to undefined or empty string if the
    - * delete failed.
    - * @param {Object|Function} obj The object or function to delete a key from.
    - * @param {string} key The key to delete.
    - * @private
    - */
    -goog.testing.PropertyReplacer.deleteKey_ = function(obj, key) {
    -  try {
    -    delete obj[key];
    -    // Delete has no effect for built-in properties of DOM nodes in FF.
    -    if (!goog.testing.PropertyReplacer.hasKey_(obj, key)) {
    -      return;
    -    }
    -  } catch (e) {
    -    // IE throws TypeError when trying to delete properties of native objects
    -    // (e.g. DOM nodes or window), even if they have been added by JavaScript.
    -  }
    -
    -  obj[key] = undefined;
    -  if (obj[key] == 'undefined') {
    -    // Some properties such as className in IE are always evaluated as string
    -    // so undefined will become 'undefined'.
    -    obj[key] = '';
    -  }
    -};
    -
    -
    -/**
    - * Adds or changes a value in an object while saving its original state.
    - * @param {Object|Function} obj The JavaScript or native object or function to
    - *     alter. See the constraints in the class description.
    - * @param {string} key The key to change the value for.
    - * @param {*} value The new value to set.
    - */
    -goog.testing.PropertyReplacer.prototype.set = function(obj, key, value) {
    -  var origValue = goog.testing.PropertyReplacer.hasKey_(obj, key) ? obj[key] :
    -                  goog.testing.PropertyReplacer.NO_SUCH_KEY_;
    -  this.original_.push({object: obj, key: key, value: origValue});
    -  obj[key] = value;
    -};
    -
    -
    -/**
    - * Changes an existing value in an object to another one of the same type while
    - * saving its original state. The advantage of {@code replace} over {@link #set}
    - * is that {@code replace} protects against typos and erroneously passing tests
    - * after some members have been renamed during a refactoring.
    - * @param {Object|Function} obj The JavaScript or native object or function to
    - *     alter. See the constraints in the class description.
    - * @param {string} key The key to change the value for. It has to be present
    - *     either in {@code obj} or in its prototype chain.
    - * @param {*} value The new value to set. It has to have the same type as the
    - *     original value. The types are compared with {@link goog.typeOf}.
    - * @throws {Error} In case of missing key or type mismatch.
    - */
    -goog.testing.PropertyReplacer.prototype.replace = function(obj, key, value) {
    -  if (!(key in obj)) {
    -    throw Error('Cannot replace missing property "' + key + '" in ' + obj);
    -  }
    -  if (goog.typeOf(obj[key]) != goog.typeOf(value)) {
    -    throw Error('Cannot replace property "' + key + '" in ' + obj +
    -        ' with a value of different type');
    -  }
    -  this.set(obj, key, value);
    -};
    -
    -
    -/**
    - * Builds an object structure for the provided namespace path.  Doesn't
    - * overwrite those prefixes of the path that are already objects or functions.
    - * @param {string} path The path to create or alter, e.g. 'goog.ui.Menu'.
    - * @param {*} value The value to set.
    - */
    -goog.testing.PropertyReplacer.prototype.setPath = function(path, value) {
    -  var parts = path.split('.');
    -  var obj = goog.global;
    -  for (var i = 0; i < parts.length - 1; i++) {
    -    var part = parts[i];
    -    if (part == 'prototype' && !obj[part]) {
    -      throw Error('Cannot set the prototype of ' + parts.slice(0, i).join('.'));
    -    }
    -    if (!goog.isObject(obj[part]) && !goog.isFunction(obj[part])) {
    -      this.set(obj, part, {});
    -    }
    -    obj = obj[part];
    -  }
    -  this.set(obj, parts[parts.length - 1], value);
    -};
    -
    -
    -/**
    - * Deletes the key from the object while saving its original value.
    - * @param {Object|Function} obj The JavaScript or native object or function to
    - *     alter. See the constraints in the class description.
    - * @param {string} key The key to delete.
    - */
    -goog.testing.PropertyReplacer.prototype.remove = function(obj, key) {
    -  if (goog.testing.PropertyReplacer.hasKey_(obj, key)) {
    -    this.original_.push({object: obj, key: key, value: obj[key]});
    -    goog.testing.PropertyReplacer.deleteKey_(obj, key);
    -  }
    -};
    -
    -
    -/**
    - * Resets all changes made by goog.testing.PropertyReplacer.prototype.set.
    - */
    -goog.testing.PropertyReplacer.prototype.reset = function() {
    -  for (var i = this.original_.length - 1; i >= 0; i--) {
    -    var original = this.original_[i];
    -    if (original.value == goog.testing.PropertyReplacer.NO_SUCH_KEY_) {
    -      goog.testing.PropertyReplacer.deleteKey_(original.object, original.key);
    -    } else {
    -      original.object[original.key] = original.value;
    -    }
    -    delete this.original_[i];
    -  }
    -  this.original_.length = 0;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/propertyreplacer_test.html b/src/database/third_party/closure-library/closure/goog/testing/propertyreplacer_test.html
    deleted file mode 100644
    index 6455c379045..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/propertyreplacer_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.testing.PropertyReplacer
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.PropertyReplacerTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/propertyreplacer_test.js b/src/database/third_party/closure-library/closure/goog/testing/propertyreplacer_test.js
    deleted file mode 100644
    index e5712d099f5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/propertyreplacer_test.js
    +++ /dev/null
    @@ -1,364 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.PropertyReplacerTest');
    -goog.setTestOnly('goog.testing.PropertyReplacerTest');
    -
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.asserts');
    -goog.require('goog.testing.jsunit');
    -
    -// Test PropertyReplacer with JavaScript objects.
    -function testSetJsProperties() {
    -  var stubs = new goog.testing.PropertyReplacer();
    -  var x = {a: 1, b: undefined};
    -
    -  // Setting simple values.
    -  stubs.set(x, 'num', 1);
    -  assertEquals('x.num = 1', 1, x.num);
    -  stubs.set(x, 'undef', undefined);
    -  assertTrue('x.undef = undefined', 'undef' in x && x.undef === undefined);
    -  stubs.set(x, 'null', null);
    -  assertTrue('x["null"] = null', x['null'] === null);
    -
    -  // Setting a simple value that existed originally.
    -  stubs.set(x, 'b', null);
    -  assertTrue('x.b = null', x.b === null);
    -
    -  // Setting a complex value.
    -  stubs.set(x, 'obj', {});
    -  assertEquals('x.obj = {}', 'object', typeof x.obj);
    -  stubs.set(x.obj, 'num', 2);
    -  assertEquals('x.obj.num = 2', 2, x.obj.num);
    -
    -  // Overwriting a leaf.
    -  stubs.set(x.obj, 'num', 3);
    -  assertEquals('x.obj.num = 3', 3, x.obj.num);
    -
    -  // Overwriting a non-leaf.
    -  stubs.set(x, 'obj', {});
    -  assertFalse('x.obj = {} again', 'num' in x.obj);
    -
    -  // Setting a function.
    -  stubs.set(x, 'func', function(n) { return n + 1; });
    -  assertEquals('x.func = lambda n: n+1', 11, x.func(10));
    -
    -  // Setting a constructor and a prototype method.
    -  stubs.set(x, 'Class', function(num) { this.num = num; });
    -  stubs.set(x.Class.prototype, 'triple', function() { return this.num * 3; });
    -  assertEquals('prototype method', 12, (new x.Class(4)).triple());
    -
    -  // Cleaning up with UnsetAll() twice. The second run should have no effect.
    -  for (var i = 0; i < 2; i++) {
    -    stubs.reset();
    -    assertEquals('x.a preserved', 1, x.a);
    -    assertTrue('x.b reset', 'b' in x && x.b === undefined);
    -    assertFalse('x.num removed', 'num' in x);
    -    assertFalse('x.undef removed', 'undef' in x);
    -    assertFalse('x["null"] removed', 'null' in x);
    -    assertFalse('x.obj removed', 'obj' in x);
    -    assertFalse('x.func removed', 'func' in x);
    -    assertFalse('x.Class removed', 'Class' in x);
    -  }
    -}
    -
    -// Test removing JavaScript object properties.
    -function testRemoveJsProperties() {
    -  var stubs = new goog.testing.PropertyReplacer();
    -  var orig = {'a': 1, 'b': undefined};
    -  var x = {'a': 1, 'b': undefined};
    -
    -  stubs.remove(x, 'a');
    -  assertFalse('x.a removed', 'a' in x);
    -  assertTrue('x.b not removed', 'b' in x);
    -  stubs.reset();
    -  assertObjectEquals('x.a reset', x, orig);
    -
    -  stubs.remove(x, 'b');
    -  assertFalse('x.b removed', 'b' in x);
    -  stubs.reset();
    -  assertObjectEquals('x.b reset', x, orig);
    -
    -  stubs.set(x, 'c', 2);
    -  stubs.remove(x, 'c');
    -  assertObjectEquals('x.c added then removed', x, orig);
    -  stubs.reset();
    -  assertObjectEquals('x.c reset', x, orig);
    -
    -  stubs.remove(x, 'b');
    -  stubs.set(x, 'b', undefined);
    -  assertObjectEquals('x.b removed then added', x, orig);
    -  stubs.reset();
    -  assertObjectEquals('x.b reset', x, orig);
    -
    -  stubs.remove(x, 'd');
    -  assertObjectEquals('removing non-existing key', x, orig);
    -  stubs.reset();
    -  assertObjectEquals('reset removing non-existing key', x, orig);
    -}
    -
    -// Test PropertyReplacer with prototype chain.
    -function testPrototype() {
    -  var stubs = new goog.testing.PropertyReplacer();
    -
    -  // Simple inheritance.
    -  var a = {a: 0};
    -  function B() {};
    -  B.prototype = a;
    -  var b = new B();
    -
    -  stubs.set(a, 0, 1);
    -  stubs.set(b, 0, 2);
    -  stubs.reset();
    -  assertEquals('a.a == 0', 0, a['a']);
    -  assertEquals('b.a == 0', 0, b['a']);
    -
    -  // Inheritance with goog.inherits.
    -  var c = {a: 0};
    -  function C() {};
    -  C.prototype = c;
    -  function D() {};
    -  goog.inherits(D, C);
    -  var d = new D();
    -
    -  var stubs = new goog.testing.PropertyReplacer();
    -  stubs.set(c, 'a', 1);
    -  stubs.set(d, 'a', 2);
    -  stubs.reset();
    -  assertEquals('c.a == 0', 0, c['a']);
    -  assertEquals('d.a == 0', 0, d['a']);
    -
    -  // Setting prototype fields.
    -  stubs.set(B.prototype, 'c', 'z');
    -  assertEquals('b.c=="z"', 'z', b.c);
    -  stubs.reset();
    -  assertFalse('b.c deleted', 'c' in b);
    -
    -  // Setting Object.prototype's fields.
    -  stubs.set(Object.prototype, 'one', 1);
    -  assertEquals('b.one==1', 1, b.one);
    -  stubs.reset();
    -  assertFalse('b.one deleted', 'one' in b);
    -
    -  stubs.set(Object.prototype, 'two', 2);
    -  stubs.remove(b, 'two');
    -  assertEquals('b.two==2', 2, b.two);
    -  stubs.remove(Object.prototype, 'two');
    -  assertFalse('b.two deleted', 'two' in b);
    -  stubs.reset();
    -  assertFalse('Object prototype reset', 'two' in b);
    -}
    -
    -// Test replacing function properties.
    -function testFunctionProperties() {
    -  var stubs = new goog.testing.PropertyReplacer();
    -  stubs.set(Array, 'x', 1);
    -  assertEquals('Array.x==1', 1, Array.x);
    -  stubs.reset();
    -  assertFalse('Array.x deleted', 'x' in Array);
    -
    -  stubs.set(Math.random, 'x', 1);
    -  assertEquals('Math.random.x==1', 1, Math.random.x);
    -  stubs.reset();
    -  assertFalse('Math.random.x deleted', 'x' in Math.random);
    -}
    -
    -// Test the hasKey_ private method.
    -function testHasKey() {
    -  f = goog.testing.PropertyReplacer.hasKey_;
    -
    -  assertFalse('{}.a', f({}, 'a'));
    -  assertTrue('{a:0}.a', f({a: 0}, 'a'));
    -
    -  function C() {};
    -  C.prototype.a = 0;
    -  assertFalse('C.prototype.a set, is C.a own?', f(C, 'a'));
    -  assertTrue('C.prototype.a', f(C.prototype, 'a'));
    -  assertFalse('C.a not set', f(C, 'a'));
    -  C.a = 0;
    -  assertTrue('C.a set', f(C, 'a'));
    -
    -  var c = new C();
    -  assertFalse('C().a, inherited', f(c, 'a'));
    -  c.a = 0;
    -  assertTrue('C().a, own', f(c, 'a'));
    -
    -  assertFalse('window, invalid key', f(window, 'no such key'));
    -  assertTrue('window, global variable', f(window, 'goog'));
    -  assertTrue('window, build-in key', f(window, 'location'));
    -
    -  assertFalse('document, invalid key', f(document, 'no such key'));
    -  assertTrue('document.body', f(document, 'body'));
    -
    -  var div = document.createElement('div');
    -  assertFalse('div, invalid key', f(div, 'no such key'));
    -  assertTrue('div.className', f(div, 'className'));
    -  div['a'] = 0;
    -  assertTrue('div, key added by JS', f(div, 'a'));
    -
    -  assertFalse('Date().getTime', f(new Date(), 'getTime'));
    -  assertTrue('Date.prototype.getTime', f(Date.prototype, 'getTime'));
    -
    -  assertFalse('Math, invalid key', f(Math, 'no such key'));
    -  assertTrue('Math.random', f(Math, 'random'));
    -
    -  function Parent() {};
    -  Parent.prototype.a = 0;
    -  function Child() {};
    -  goog.inherits(Child, Parent);
    -  assertFalse('goog.inherits, parent prototype', f(new Child, 'a'));
    -  Child.prototype.a = 1;
    -  assertFalse('goog.inherits, child prototype', f(new Child, 'a'));
    -
    -  function OverwrittenProto() {};
    -  OverwrittenProto.prototype = {a: 0};
    -  assertFalse(f(new OverwrittenProto, 'a'));
    -}
    -
    -// Test PropertyReplacer with DOM objects' built in attributes.
    -function testDomBuiltInAttributes() {
    -  var div = document.createElement('div');
    -  div.id = 'old-id';
    -
    -  var stubs = new goog.testing.PropertyReplacer();
    -  stubs.set(div, 'id', 'new-id');
    -  stubs.set(div, 'className', 'test-class');
    -  assertEquals('div.id == "new-id"', 'new-id', div.id);
    -  assertEquals('div.className == "test-class"', 'test-class', div.className);
    -
    -  stubs.remove(div, 'className');
    -  // '' in Firefox, undefined in Chrome.
    -  assertEvaluatesToFalse('div.className is empty', div.className);
    -
    -  stubs.reset();
    -  assertEquals('div.id == "old-id"', 'old-id', div.id);
    -  assertEquals('div.name == ""', '', div.className);
    -}
    -
    -// Test PropertyReplacer with DOM objects' custom attributes.
    -function testDomCustomAttributes() {
    -  var div = document.createElement('div');
    -  div.attr1 = 'old';
    -
    -  var stubs = new goog.testing.PropertyReplacer();
    -  stubs.set(div, 'attr1', 'new');
    -  stubs.set(div, 'attr2', 'new');
    -  assertEquals('div.attr1 == "new"', 'new', div.attr1);
    -  assertEquals('div.attr2 == "new"', 'new', div.attr2);
    -
    -  stubs.set(div, 'attr3', 'new');
    -  stubs.remove(div, 'attr3');
    -  assertEquals('div.attr3 == undefined', undefined, div.attr3);
    -
    -  stubs.reset();
    -  assertEquals('div.attr1 == "old"', 'old', div.attr1);
    -  assertEquals('div.attr2 == undefined', undefined, div.attr2);
    -}
    -
    -// Test PropertyReplacer overriding Math.random.
    -function testMathRandom() {
    -  var stubs = new goog.testing.PropertyReplacer();
    -  stubs.set(Math, 'random', function() { return -1; });
    -  assertEquals('mocked Math.random', -1, Math.random());
    -
    -  stubs.reset();
    -  assertNotEquals('original Math.random', -1, Math.random());
    -}
    -
    -// Tests the replace method of PropertyReplacer.
    -function testReplace() {
    -  var stubs = new goog.testing.PropertyReplacer();
    -  function C() {
    -    this.a = 1;
    -  };
    -  C.prototype.b = 1;
    -  C.prototype.toString = function() {
    -    return 'obj';
    -  };
    -  var obj = new C();
    -
    -  stubs.replace(obj, 'a', 2);
    -  assertEquals('successfully replaced the own property of an object', 2, obj.a);
    -
    -  stubs.replace(obj, 'b', 2);
    -  assertEquals('successfully replaced the property in the prototype', 2, obj.b);
    -
    -  var error = assertThrows('cannot replace missing key',
    -      goog.bind(stubs.replace, stubs, obj, 'unknown', 1));
    -  // Using assertContains instead of assertEquals because Opera 10.0 adds
    -  // the stack trace to the error message.
    -  assertEquals('error message for missing key',
    -      'Cannot replace missing property "unknown" in obj', error.message);
    -  assertFalse('object not touched', 'unknown' in obj);
    -
    -  var error = assertThrows('cannot change value type',
    -      goog.bind(stubs.replace, stubs, obj, 'a', '3'));
    -  assertContains('error message for type mismatch',
    -      'Cannot replace property "a" in obj with a value of different type',
    -      error.message);
    -}
    -
    -// Tests altering complete namespace paths.
    -function testSetPath() {
    -  goog.global.a = {b: {}};
    -  var stubs = new goog.testing.PropertyReplacer();
    -
    -  stubs.setPath('a.b.c.d', 1);
    -  assertObjectEquals('a.b.c.d=1', {b: {c: {d: 1}}}, goog.global.a);
    -  stubs.setPath('a.b.e', 2);
    -  assertObjectEquals('a.b.e=2', {b: {c: {d: 1}, e: 2}}, goog.global.a);
    -  stubs.setPath('a.f', 3);
    -  assertObjectEquals('a.f=3', {b: {c: {d: 1}, e: 2}, f: 3}, goog.global.a);
    -  stubs.setPath('a.f.g', 4);
    -  assertObjectEquals('a.f.g=4', {b: {c: {d: 1}, e: 2}, f: {g: 4}},
    -                     goog.global.a);
    -  stubs.setPath('a', 5);
    -  assertEquals('a=5', 5, goog.global.a);
    -
    -  stubs.setPath('x.y.z', 5);
    -  assertObjectEquals('x.y.z=5', {y: {z: 5}}, goog.global.x);
    -
    -  stubs.reset();
    -  assertObjectEquals('a.* reset', {b: {}}, goog.global.a);
    -  // NOTE: it's impossible to delete global variables in Internet Explorer,
    -  // so ('x' in goog.global) would be true.
    -  assertUndefined('x.* reset', goog.global.x);
    -}
    -
    -// Tests altering paths with functions in them.
    -function testSetPathWithFunction() {
    -  var f = function() {};
    -  goog.global.a = {b: f};
    -  var stubs = new goog.testing.PropertyReplacer();
    -
    -  stubs.setPath('a.b.c', 1);
    -  assertEquals('a.b.c=1, f kept', f, goog.global.a.b);
    -  assertEquals('a.b.c=1, c set', 1, goog.global.a.b.c);
    -
    -  stubs.setPath('a.b.prototype.d', 2);
    -  assertEquals('a.b.prototype.d=2, b kept', f, goog.global.a.b);
    -  assertEquals('a.b.prototype.d=2, c kept', 1, goog.global.a.b.c);
    -  assertFalse('a.b.prototype.d=2, a.b.d not set', 'd' in goog.global.a.b);
    -  assertTrue('a.b.prototype.d=2, proto set', 'd' in goog.global.a.b.prototype);
    -  assertEquals('a.b.prototype.d=2, d set', 2, new goog.global.a.b().d);
    -
    -  var invalidSetPath = function() {
    -    stubs.setPath('a.prototype.e', 3);
    -  };
    -  assertThrows('setting the prototype of a non-function', invalidSetPath);
    -
    -  stubs.reset();
    -  assertObjectEquals('a.b.c reset', {b: f}, goog.global.a);
    -  assertObjectEquals('a.b.prototype reset', {}, goog.global.a.b.prototype);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/proto2/proto2.js b/src/database/third_party/closure-library/closure/goog/testing/proto2/proto2.js
    deleted file mode 100644
    index fbf232c9941..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/proto2/proto2.js
    +++ /dev/null
    @@ -1,145 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Test helpers to compare goog.proto2.Messages.
    - *
    - */
    -
    -goog.provide('goog.testing.proto2');
    -
    -goog.require('goog.proto2.Message');
    -goog.require('goog.proto2.ObjectSerializer');
    -goog.require('goog.testing.asserts');
    -
    -
    -/**
    - * Compares two goog.proto2.Message instances of the same type.
    - * @param {!goog.proto2.Message} expected First message.
    - * @param {!goog.proto2.Message} actual Second message.
    - * @param {string} path Path to the messages.
    - * @return {string} A string describing where they differ. Empty string if they
    - *     are equal.
    - * @private
    - */
    -goog.testing.proto2.findDifferences_ = function(expected, actual, path) {
    -  var fields = expected.getDescriptor().getFields();
    -  for (var i = 0; i < fields.length; i++) {
    -    var field = fields[i];
    -    var newPath = (path ? path + '/' : '') + field.getName();
    -
    -    if (expected.has(field) && !actual.has(field)) {
    -      return newPath + ' should be present';
    -    }
    -    if (!expected.has(field) && actual.has(field)) {
    -      return newPath + ' should not be present';
    -    }
    -
    -    if (expected.has(field)) {
    -      var isComposite = field.isCompositeType();
    -
    -      if (field.isRepeated()) {
    -        var expectedCount = expected.countOf(field);
    -        var actualCount = actual.countOf(field);
    -        if (expectedCount != actualCount) {
    -          return newPath + ' should have ' + expectedCount + ' items, ' +
    -              'but has ' + actualCount;
    -        }
    -
    -        for (var j = 0; j < expectedCount; j++) {
    -          var expectedItem = expected.get(field, j);
    -          var actualItem = actual.get(field, j);
    -          if (isComposite) {
    -            var itemDiff = goog.testing.proto2.findDifferences_(
    -                /** @type {!goog.proto2.Message} */ (expectedItem),
    -                /** @type {!goog.proto2.Message} */ (actualItem),
    -                newPath + '[' + j + ']');
    -            if (itemDiff) {
    -              return itemDiff;
    -            }
    -          } else {
    -            if (expectedItem != actualItem) {
    -              return newPath + '[' + j + '] should be ' + expectedItem +
    -                  ', but was ' + actualItem;
    -            }
    -          }
    -        }
    -      } else {
    -        var expectedValue = expected.get(field);
    -        var actualValue = actual.get(field);
    -        if (isComposite) {
    -          var diff = goog.testing.proto2.findDifferences_(
    -              /** @type {!goog.proto2.Message} */ (expectedValue),
    -              /** @type {!goog.proto2.Message} */ (actualValue),
    -              newPath);
    -          if (diff) {
    -            return diff;
    -          }
    -        } else {
    -          if (expectedValue != actualValue) {
    -            return newPath + ' should be ' + expectedValue + ', but was ' +
    -                actualValue;
    -          }
    -        }
    -      }
    -    }
    -  }
    -
    -  return '';
    -};
    -
    -
    -/**
    - * Compares two goog.proto2.Message objects. Gives more readable output than
    - * assertObjectEquals on mismatch.
    - * @param {!goog.proto2.Message} expected Expected proto2 message.
    - * @param {!goog.proto2.Message} actual Actual proto2 message.
    - * @param {string=} opt_failureMessage Failure message when the values don't
    - *     match.
    - */
    -goog.testing.proto2.assertEquals = function(expected, actual,
    -    opt_failureMessage) {
    -  var failureSummary = opt_failureMessage || '';
    -  if (!(expected instanceof goog.proto2.Message) ||
    -      !(actual instanceof goog.proto2.Message)) {
    -    goog.testing.asserts.raiseException(failureSummary,
    -        'Bad arguments were passed to goog.testing.proto2.assertEquals');
    -  }
    -  if (expected.constructor != actual.constructor) {
    -    goog.testing.asserts.raiseException(failureSummary,
    -        'Message type mismatch: ' + expected.getDescriptor().getFullName() +
    -        ' != ' + actual.getDescriptor().getFullName());
    -  }
    -  var diff = goog.testing.proto2.findDifferences_(expected, actual, '');
    -  if (diff) {
    -    goog.testing.asserts.raiseException(failureSummary, diff);
    -  }
    -};
    -
    -
    -/**
    - * Helper function to quickly build protocol buffer messages from JSON objects.
    - * @param {function(new:MessageType)} messageCtor A constructor that
    - *     creates a {@code goog.proto2.Message} subclass instance.
    - * @param {!Object} json JSON object which uses field names as keys.
    - * @return {MessageType} The deserialized protocol buffer.
    - * @template MessageType
    - */
    -goog.testing.proto2.fromObject = function(messageCtor, json) {
    -  var serializer = new goog.proto2.ObjectSerializer(
    -      goog.proto2.ObjectSerializer.KeyOption.NAME);
    -  var message = new messageCtor;
    -  serializer.deserializeTo(message, json);
    -  return message;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/proto2/proto2_test.html b/src/database/third_party/closure-library/closure/goog/testing/proto2/proto2_test.html
    deleted file mode 100644
    index 33444189e6a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/proto2/proto2_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.testing.proto2
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.proto2Test');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/proto2/proto2_test.js b/src/database/third_party/closure-library/closure/goog/testing/proto2/proto2_test.js
    deleted file mode 100644
    index 2b1678d5d9f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/proto2/proto2_test.js
    +++ /dev/null
    @@ -1,137 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.proto2Test');
    -goog.setTestOnly('goog.testing.proto2Test');
    -
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.proto2');
    -goog.require('proto2.TestAllTypes');
    -
    -function testAssertEquals() {
    -  var assertProto2Equals = goog.testing.proto2.assertEquals;
    -  assertProto2Equals(new proto2.TestAllTypes, new proto2.TestAllTypes);
    -  assertProto2Equals(new proto2.TestAllTypes, new proto2.TestAllTypes, 'oops');
    -
    -  var ex = assertThrows(goog.partial(assertProto2Equals,
    -      new proto2.TestAllTypes, new proto2.TestAllTypes.NestedMessage));
    -  assertEquals(
    -      'Message type mismatch: TestAllTypes != TestAllTypes.NestedMessage',
    -      ex.message);
    -
    -  var message = new proto2.TestAllTypes;
    -  message.setOptionalInt32(1);
    -  ex = assertThrows(goog.partial(assertProto2Equals,
    -      new proto2.TestAllTypes, message));
    -  assertEquals('optional_int32 should not be present', ex.message);
    -
    -  ex = assertThrows(goog.partial(assertProto2Equals,
    -      new proto2.TestAllTypes, message, 'oops'));
    -  assertEquals('oops\noptional_int32 should not be present', ex.message);
    -}
    -
    -function testFindDifferences_EmptyMessages() {
    -  assertEquals('', goog.testing.proto2.findDifferences_(
    -      new proto2.TestAllTypes, new proto2.TestAllTypes, ''));
    -}
    -
    -function testFindDifferences_FieldNotPresent() {
    -  var message = new proto2.TestAllTypes;
    -  message.setOptionalInt32(0);
    -  var empty = new proto2.TestAllTypes;
    -  assertEquals('optional_int32 should not be present',
    -      goog.testing.proto2.findDifferences_(empty, message, ''));
    -  assertEquals('optional_int32 should be present',
    -      goog.testing.proto2.findDifferences_(message, empty, ''));
    -  assertEquals('path/optional_int32 should be present',
    -      goog.testing.proto2.findDifferences_(message, empty, 'path'));
    -}
    -
    -function testFindDifferences_IntFieldDiffers() {
    -  var message1 = new proto2.TestAllTypes;
    -  message1.setOptionalInt32(1);
    -  var message2 = new proto2.TestAllTypes;
    -  message2.setOptionalInt32(2);
    -  assertEquals('optional_int32 should be 1, but was 2',
    -      goog.testing.proto2.findDifferences_(message1, message2, ''));
    -}
    -
    -function testFindDifferences_NestedIntFieldDiffers() {
    -  var message1 = new proto2.TestAllTypes;
    -  var nested1 = new proto2.TestAllTypes.NestedMessage();
    -  nested1.setB(1);
    -  message1.setOptionalNestedMessage(nested1);
    -  var message2 = new proto2.TestAllTypes;
    -  var nested2 = new proto2.TestAllTypes.NestedMessage();
    -  nested2.setB(2);
    -  message2.setOptionalNestedMessage(nested2);
    -  assertEquals('optional_nested_message/b should be 1, but was 2',
    -      goog.testing.proto2.findDifferences_(message1, message2, ''));
    -}
    -
    -function testFindDifferences_RepeatedFieldLengthDiffers() {
    -  var message1 = new proto2.TestAllTypes;
    -  message1.addRepeatedInt32(1);
    -  var message2 = new proto2.TestAllTypes;
    -  message2.addRepeatedInt32(1);
    -  message2.addRepeatedInt32(2);
    -  assertEquals('repeated_int32 should have 1 items, but has 2',
    -      goog.testing.proto2.findDifferences_(message1, message2, ''));
    -}
    -
    -function testFindDifferences_RepeatedFieldItemDiffers() {
    -  var message1 = new proto2.TestAllTypes;
    -  message1.addRepeatedInt32(1);
    -  var message2 = new proto2.TestAllTypes;
    -  message2.addRepeatedInt32(2);
    -  assertEquals('repeated_int32[0] should be 1, but was 2',
    -      goog.testing.proto2.findDifferences_(message1, message2, ''));
    -}
    -
    -function testFindDifferences_RepeatedNestedMessageDiffers() {
    -  var message1 = new proto2.TestAllTypes;
    -  var nested1 = new proto2.TestAllTypes.NestedMessage();
    -  nested1.setB(1);
    -  message1.addRepeatedNestedMessage(nested1);
    -  var message2 = new proto2.TestAllTypes;
    -  var nested2 = new proto2.TestAllTypes.NestedMessage();
    -  nested2.setB(2);
    -  message2.addRepeatedNestedMessage(nested2);
    -  assertEquals('repeated_nested_message[0]/b should be 1, but was 2',
    -      goog.testing.proto2.findDifferences_(message1, message2, ''));
    -}
    -
    -function testFromObject() {
    -  var nested = new proto2.TestAllTypes.NestedMessage();
    -  nested.setB(1);
    -  var message = new proto2.TestAllTypes;
    -  message.addRepeatedNestedMessage(nested);
    -  message.setOptionalInt32(2);
    -  // Successfully deserializes simple as well as message fields.
    -  assertObjectEquals(
    -      message,
    -      goog.testing.proto2.fromObject(proto2.TestAllTypes, {
    -        'optional_int32': 2,
    -        'repeated_nested_message': [{'b': 1}]
    -      }));
    -  // Fails if the field name is not recognized.
    -  assertThrows(function() {
    -    goog.testing.proto2.fromObject(proto2.TestAllTypes, {'unknown': 1});
    -  });
    -  // Fails if the value type is wrong in the JSON object.
    -  assertThrows(function() {
    -    goog.testing.proto2.fromObject(proto2.TestAllTypes,
    -        {'optional_int32': '1'});
    -  });
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/pseudorandom.js b/src/database/third_party/closure-library/closure/goog/testing/pseudorandom.js
    deleted file mode 100644
    index fb57a3ac2fb..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/pseudorandom.js
    +++ /dev/null
    @@ -1,180 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview PseudoRandom provides a mechanism for generating deterministic
    - * psuedo random numbers based on a seed. Based on the Park-Miller algorithm.
    - * See http://dx.doi.org/10.1145%2F63039.63042 for details.
    - *
    - */
    -
    -goog.provide('goog.testing.PseudoRandom');
    -
    -goog.require('goog.Disposable');
    -
    -
    -
    -/**
    - * Class for unit testing code that uses Math.random. Generates deterministic
    - * random numbers.
    - *
    - * @param {number=} opt_seed The seed to use.
    - * @param {boolean=} opt_install Whether to install the PseudoRandom at
    - *     construction time.
    - * @extends {goog.Disposable}
    - * @constructor
    - * @final
    - */
    -goog.testing.PseudoRandom = function(opt_seed, opt_install) {
    -  goog.Disposable.call(this);
    -
    -  if (!goog.isDef(opt_seed)) {
    -    opt_seed = goog.testing.PseudoRandom.seedUniquifier_++ + goog.now();
    -  }
    -  this.seed(opt_seed);
    -
    -  if (opt_install) {
    -    this.install();
    -  }
    -};
    -goog.inherits(goog.testing.PseudoRandom, goog.Disposable);
    -
    -
    -/**
    - * Helps create a unique seed.
    - * @type {number}
    - * @private
    - */
    -goog.testing.PseudoRandom.seedUniquifier_ = 0;
    -
    -
    -/**
    - * Constant used as part of the algorithm.
    - * @type {number}
    - */
    -goog.testing.PseudoRandom.A = 48271;
    -
    -
    -/**
    - * Constant used as part of the algorithm. 2^31 - 1.
    - * @type {number}
    - */
    -goog.testing.PseudoRandom.M = 2147483647;
    -
    -
    -/**
    - * Constant used as part of the algorithm. It is equal to M / A.
    - * @type {number}
    - */
    -goog.testing.PseudoRandom.Q = 44488;
    -
    -
    -/**
    - * Constant used as part of the algorithm. It is equal to M % A.
    - * @type {number}
    - */
    -goog.testing.PseudoRandom.R = 3399;
    -
    -
    -/**
    - * Constant used as part of the algorithm to get values from range [0, 1).
    - * @type {number}
    - */
    -goog.testing.PseudoRandom.ONE_OVER_M_MINUS_ONE =
    -    1.0 / (goog.testing.PseudoRandom.M - 1);
    -
    -
    -/**
    - * The seed of the random sequence and also the next returned value (before
    - * normalization). Must be between 1 and M - 1 (inclusive).
    - * @type {number}
    - * @private
    - */
    -goog.testing.PseudoRandom.prototype.seed_ = 1;
    -
    -
    -/**
    - * Whether this PseudoRandom has been installed.
    - * @type {boolean}
    - * @private
    - */
    -goog.testing.PseudoRandom.prototype.installed_;
    -
    -
    -/**
    - * The original Math.random function.
    - * @type {function(): number}
    - * @private
    - */
    -goog.testing.PseudoRandom.prototype.mathRandom_;
    -
    -
    -/**
    - * Installs this PseudoRandom as the system number generator.
    - */
    -goog.testing.PseudoRandom.prototype.install = function() {
    -  if (!this.installed_) {
    -    this.mathRandom_ = Math.random;
    -    Math.random = goog.bind(this.random, this);
    -    this.installed_ = true;
    -  }
    -};
    -
    -
    -/** @override */
    -goog.testing.PseudoRandom.prototype.disposeInternal = function() {
    -  goog.testing.PseudoRandom.superClass_.disposeInternal.call(this);
    -  this.uninstall();
    -};
    -
    -
    -/**
    - * Uninstalls the PseudoRandom.
    - */
    -goog.testing.PseudoRandom.prototype.uninstall = function() {
    -  if (this.installed_) {
    -    Math.random = this.mathRandom_;
    -    this.installed_ = false;
    -  }
    -};
    -
    -
    -/**
    - * Seed the generator.
    - *
    - * @param {number=} seed The seed to use.
    - */
    -goog.testing.PseudoRandom.prototype.seed = function(seed) {
    -  this.seed_ = seed % (goog.testing.PseudoRandom.M - 1);
    -  if (this.seed_ <= 0) {
    -    this.seed_ += goog.testing.PseudoRandom.M - 1;
    -  }
    -};
    -
    -
    -/**
    - * @return {number} The next number in the sequence.
    - */
    -goog.testing.PseudoRandom.prototype.random = function() {
    -  var hi = Math.floor(this.seed_ / goog.testing.PseudoRandom.Q);
    -  var lo = this.seed_ % goog.testing.PseudoRandom.Q;
    -  var test = goog.testing.PseudoRandom.A * lo -
    -             goog.testing.PseudoRandom.R * hi;
    -  if (test > 0) {
    -    this.seed_ = test;
    -  } else {
    -    this.seed_ = test + goog.testing.PseudoRandom.M;
    -  }
    -  return (this.seed_ - 1) * goog.testing.PseudoRandom.ONE_OVER_M_MINUS_ONE;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/pseudorandom_test.html b/src/database/third_party/closure-library/closure/goog/testing/pseudorandom_test.html
    deleted file mode 100644
    index 8fff6ca6db2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/pseudorandom_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.testing.PseudoRandom
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.PseudoRandomTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/pseudorandom_test.js b/src/database/third_party/closure-library/closure/goog/testing/pseudorandom_test.js
    deleted file mode 100644
    index 1d918f1fdf2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/pseudorandom_test.js
    +++ /dev/null
    @@ -1,94 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.PseudoRandomTest');
    -goog.setTestOnly('goog.testing.PseudoRandomTest');
    -
    -goog.require('goog.testing.PseudoRandom');
    -goog.require('goog.testing.jsunit');
    -
    -function runFairnessTest(sides, rolls, chiSquareLimit) {
    -  // Initialize the count table for dice rolls.
    -  var counts = [];
    -  for (var i = 0; i < sides; ++i) {
    -    counts[i] = 0;
    -  }
    -  // Roll the dice many times and count the results.
    -  for (var i = 0; i < rolls; ++i) {
    -    ++counts[Math.floor(Math.random() * sides)];
    -  }
    -  // If the dice is fair, we expect a uniform distribution.
    -  var expected = rolls / sides;
    -  // Pearson's chi-square test for a distribution fit.
    -  var chiSquare = 0;
    -  for (var i = 0; i < sides; ++i) {
    -    chiSquare += (counts[i] - expected) * (counts[i] - expected) / expected;
    -  }
    -  assert('Chi-square test for a distribution fit failed',
    -      chiSquare < chiSquareLimit);
    -}
    -
    -function testInstall() {
    -  var random = new goog.testing.PseudoRandom();
    -  var originalRandom = Math.random;
    -
    -  assertFalse(!!random.installed_);
    -
    -  random.install();
    -  assertTrue(random.installed_);
    -  assertNotEquals(Math.random, originalRandom);
    -
    -  random.uninstall();
    -  assertFalse(random.installed_);
    -  assertEquals(originalRandom, Math.random);
    -}
    -
    -function testBounds() {
    -  var random = new goog.testing.PseudoRandom();
    -  random.install();
    -
    -  for (var i = 0; i < 100000; ++i) {
    -    var value = Math.random();
    -    assert('Random value out of bounds', value >= 0 && value < 1);
    -  }
    -
    -  random.uninstall();
    -}
    -
    -function testFairness() {
    -  var random = new goog.testing.PseudoRandom(0, true);
    -
    -  // Chi-square statistics: p-value = 0.05, df = 5, limit = 11.07.
    -  runFairnessTest(6, 100000, 11.07);
    -  // Chi-square statistics: p-value = 0.05, df = 100, limit = 124.34.
    -  runFairnessTest(101, 100000, 124.34);
    -
    -  random.uninstall();
    -}
    -
    -function testReseed() {
    -  var random = new goog.testing.PseudoRandom(100, true);
    -
    -  var sequence = [];
    -  for (var i = 0; i < 64000; ++i) {
    -    sequence.push(Math.random());
    -  }
    -
    -  random.seed(100);
    -  for (var i = 0; i < sequence.length; ++i) {
    -    assertEquals(sequence[i], Math.random());
    -  }
    -
    -  random.uninstall();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/recordfunction.js b/src/database/third_party/closure-library/closure/goog/testing/recordfunction.js
    deleted file mode 100644
    index fc81c1d8db8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/recordfunction.js
    +++ /dev/null
    @@ -1,215 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Helper class for recording the calls of a function.
    - *
    - * Example:
    - * <pre>
    - * var stubs = new goog.testing.PropertyReplacer();
    - *
    - * function tearDown() {
    - *   stubs.reset();
    - * }
    - *
    - * function testShuffle() {
    - *   stubs.set(Math, 'random', goog.testing.recordFunction(Math.random));
    - *   var arr = shuffle([1, 2, 3, 4, 5]);
    - *   assertSameElements([1, 2, 3, 4, 5], arr);
    - *   assertEquals(4, Math.random.getCallCount());
    - * }
    - *
    - * function testOpenDialog() {
    - *   stubs.set(goog.ui, 'Dialog',
    - *       goog.testing.recordConstructor(goog.ui.Dialog));
    - *   openConfirmDialog();
    - *   var lastDialogInstance = goog.ui.Dialog.getLastCall().getThis();
    - *   assertEquals('confirm', lastDialogInstance.getTitle());
    - * }
    - * </pre>
    - *
    - */
    -
    -goog.provide('goog.testing.FunctionCall');
    -goog.provide('goog.testing.recordConstructor');
    -goog.provide('goog.testing.recordFunction');
    -
    -goog.require('goog.testing.asserts');
    -
    -
    -/**
    - * Wraps the function into another one which calls the inner function and
    - * records its calls. The recorded function will have 3 static methods:
    - * {@code getCallCount}, {@code getCalls} and {@code getLastCall} but won't
    - * inherit the original function's prototype and static fields.
    - *
    - * @param {!Function=} opt_f The function to wrap and record. Defaults to
    - *     {@link goog.nullFunction}.
    - * @return {!Function} The wrapped function.
    - */
    -goog.testing.recordFunction = function(opt_f) {
    -  var f = opt_f || goog.nullFunction;
    -  var calls = [];
    -
    -  function recordedFunction() {
    -    try {
    -      var ret = f.apply(this, arguments);
    -      calls.push(new goog.testing.FunctionCall(f, this, arguments, ret, null));
    -      return ret;
    -    } catch (err) {
    -      calls.push(new goog.testing.FunctionCall(f, this, arguments, undefined,
    -          err));
    -      throw err;
    -    }
    -  }
    -
    -  /**
    -   * @return {number} Total number of calls.
    -   */
    -  recordedFunction.getCallCount = function() {
    -    return calls.length;
    -  };
    -
    -  /**
    -   * Asserts that the function was called {@code expected} times.
    -   * @param {number} expected The expected number of calls.
    -   */
    -  recordedFunction.assertCallCount = function(expected) {
    -    var actual = calls.length;
    -    assertEquals(
    -        'Expected ' + expected + ' call(s), but was ' + actual + '.',
    -        expected, actual);
    -  };
    -
    -  /**
    -   * @return {!Array<!goog.testing.FunctionCall>} All calls of the recorded
    -   *     function.
    -   */
    -  recordedFunction.getCalls = function() {
    -    return calls;
    -  };
    -
    -
    -  /**
    -   * @return {goog.testing.FunctionCall} Last call of the recorded function or
    -   *     null if it hasn't been called.
    -   */
    -  recordedFunction.getLastCall = function() {
    -    return calls[calls.length - 1] || null;
    -  };
    -
    -  /**
    -   * Returns and removes the last call of the recorded function.
    -   * @return {goog.testing.FunctionCall} Last call of the recorded function or
    -   *     null if it hasn't been called.
    -   */
    -  recordedFunction.popLastCall = function() {
    -    return calls.pop() || null;
    -  };
    -
    -  /**
    -   * Resets the recorded function and removes all calls.
    -   */
    -  recordedFunction.reset = function() {
    -    calls.length = 0;
    -  };
    -
    -  return recordedFunction;
    -};
    -
    -
    -/**
    - * Same as {@link goog.testing.recordFunction} but the recorded function will
    - * have the same prototype and static fields as the original one. It can be
    - * used with constructors.
    - *
    - * @param {!Function} ctor The function to wrap and record.
    - * @return {!Function} The wrapped function.
    - */
    -goog.testing.recordConstructor = function(ctor) {
    -  var recordedConstructor = goog.testing.recordFunction(ctor);
    -  recordedConstructor.prototype = ctor.prototype;
    -  goog.mixin(recordedConstructor, ctor);
    -  return recordedConstructor;
    -};
    -
    -
    -
    -/**
    - * Struct for a single function call.
    - * @param {!Function} func The called function.
    - * @param {!Object} thisContext {@code this} context of called function.
    - * @param {!Arguments} args Arguments of the called function.
    - * @param {*} ret Return value of the function or undefined in case of error.
    - * @param {*} error The error thrown by the function or null if none.
    - * @constructor
    - */
    -goog.testing.FunctionCall = function(func, thisContext, args, ret, error) {
    -  this.function_ = func;
    -  this.thisContext_ = thisContext;
    -  this.arguments_ = Array.prototype.slice.call(args);
    -  this.returnValue_ = ret;
    -  this.error_ = error;
    -};
    -
    -
    -/**
    - * @return {!Function} The called function.
    - */
    -goog.testing.FunctionCall.prototype.getFunction = function() {
    -  return this.function_;
    -};
    -
    -
    -/**
    - * @return {!Object} {@code this} context of called function. It is the same as
    - *     the created object if the function is a constructor.
    - */
    -goog.testing.FunctionCall.prototype.getThis = function() {
    -  return this.thisContext_;
    -};
    -
    -
    -/**
    - * @return {!Array<?>} Arguments of the called function.
    - */
    -goog.testing.FunctionCall.prototype.getArguments = function() {
    -  return this.arguments_;
    -};
    -
    -
    -/**
    - * Returns the nth argument of the called function.
    - * @param {number} index 0-based index of the argument.
    - * @return {*} The argument value or undefined if there is no such argument.
    - */
    -goog.testing.FunctionCall.prototype.getArgument = function(index) {
    -  return this.arguments_[index];
    -};
    -
    -
    -/**
    - * @return {*} Return value of the function or undefined in case of error.
    - */
    -goog.testing.FunctionCall.prototype.getReturnValue = function() {
    -  return this.returnValue_;
    -};
    -
    -
    -/**
    - * @return {*} The error thrown by the function or null if none.
    - */
    -goog.testing.FunctionCall.prototype.getError = function() {
    -  return this.error_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/recordfunction_test.html b/src/database/third_party/closure-library/closure/goog/testing/recordfunction_test.html
    deleted file mode 100644
    index 83aaee8c2b4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/recordfunction_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.testing.recordFunction
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.recordFunctionTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/recordfunction_test.js b/src/database/third_party/closure-library/closure/goog/testing/recordfunction_test.js
    deleted file mode 100644
    index 59ed731810b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/recordfunction_test.js
    +++ /dev/null
    @@ -1,175 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.recordFunctionTest');
    -goog.setTestOnly('goog.testing.recordFunctionTest');
    -
    -goog.require('goog.functions');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordConstructor');
    -goog.require('goog.testing.recordFunction');
    -
    -var stubs = new goog.testing.PropertyReplacer();
    -
    -function tearDown() {
    -  stubs.reset();
    -}
    -
    -function testNoCalls() {
    -  var f = goog.testing.recordFunction(goog.functions.identity);
    -  assertEquals('call count', 0, f.getCallCount());
    -  assertNull('last call', f.getLastCall());
    -  assertArrayEquals('all calls', [], f.getCalls());
    -}
    -
    -function testWithoutArguments() {
    -  var f = goog.testing.recordFunction();
    -  assertUndefined('f(1)', f(1));
    -  assertEquals('call count', 1, f.getCallCount());
    -  var lastCall = f.getLastCall();
    -  assertEquals('original function', goog.nullFunction, lastCall.getFunction());
    -  assertEquals('this context', window, lastCall.getThis());
    -  assertArrayEquals('arguments', [1], lastCall.getArguments());
    -  assertEquals('arguments[0]', 1, lastCall.getArgument(0));
    -  assertUndefined('arguments[1]', lastCall.getArgument(1));
    -  assertUndefined('return value', lastCall.getReturnValue());
    -}
    -
    -function testWithIdentityFunction() {
    -  var f = goog.testing.recordFunction(goog.functions.identity);
    -  var dummyThis = {};
    -  assertEquals('f(1)', 1, f(1));
    -  assertEquals('f.call(dummyThis, 2)', 2, f.call(dummyThis, 2));
    -
    -  var calls = f.getCalls();
    -  var firstCall = calls[0];
    -  var lastCall = f.getLastCall();
    -  assertEquals('call count', 2, f.getCallCount());
    -  assertEquals('last call', calls[1], lastCall);
    -  assertEquals('original function', goog.functions.identity,
    -      lastCall.getFunction());
    -  assertEquals('this context of first call', window, firstCall.getThis());
    -  assertEquals('this context of last call', dummyThis, lastCall.getThis());
    -  assertArrayEquals('arguments of the first call', [1],
    -      firstCall.getArguments());
    -  assertArrayEquals('arguments of the last call', [2], lastCall.getArguments());
    -  assertEquals('return value of the first call', 1, firstCall.getReturnValue());
    -  assertEquals('return value of the last call', 2, lastCall.getReturnValue());
    -  assertNull('error thrown by the first call', firstCall.getError());
    -  assertNull('error thrown by the last call', lastCall.getError());
    -}
    -
    -function testWithErrorFunction() {
    -  var f = goog.testing.recordFunction(goog.functions.error('error'));
    -
    -  var error = assertThrows('f(1) should throw an error', function() {
    -    f(1);
    -  });
    -  assertEquals('error message', 'error', error.message);
    -  assertEquals('call count', 1, f.getCallCount());
    -  var lastCall = f.getLastCall();
    -  assertEquals('this context', window, lastCall.getThis());
    -  assertArrayEquals('arguments', [1], lastCall.getArguments());
    -  assertUndefined('return value', lastCall.getReturnValue());
    -  assertEquals('recorded error message', 'error', lastCall.getError().message);
    -}
    -
    -function testWithClass() {
    -  var ns = {};
    -  /** @constructor */
    -  ns.TestClass = function(num) {
    -    this.setX(ns.TestClass.identity(1) + num);
    -  };
    -  ns.TestClass.prototype.setX = function(x) {
    -    this.x = x;
    -  };
    -  ns.TestClass.identity = function(x) {
    -    return x;
    -  };
    -  var originalNsTestClass = ns.TestClass;
    -
    -  stubs.set(ns, 'TestClass', goog.testing.recordConstructor(ns.TestClass));
    -  stubs.set(ns.TestClass.prototype, 'setX',
    -      goog.testing.recordFunction(ns.TestClass.prototype.setX));
    -  stubs.set(ns.TestClass, 'identity',
    -      goog.testing.recordFunction(ns.TestClass.identity));
    -
    -  var obj = new ns.TestClass(2);
    -  assertEquals('constructor is called once', 1, ns.TestClass.getCallCount());
    -  var lastConstructorCall = ns.TestClass.getLastCall();
    -  assertArrayEquals('... with argument 2', [2],
    -      lastConstructorCall.getArguments());
    -  assertEquals('the created object', obj, lastConstructorCall.getThis());
    -  assertEquals('type of the created object', originalNsTestClass,
    -      obj.constructor);
    -
    -  assertEquals('setX is called once', 1, obj.setX.getCallCount());
    -  assertArrayEquals('... with argument 3', [3],
    -      obj.setX.getLastCall().getArguments());
    -  assertEquals('The x field is properly set', 3, obj.x);
    -
    -  assertEquals('identity is called once', 1,
    -      ns.TestClass.identity.getCallCount());
    -  assertArrayEquals('... with argument 1', [1],
    -      ns.TestClass.identity.getLastCall().getArguments());
    -}
    -
    -function testPopLastCall() {
    -  var f = goog.testing.recordFunction();
    -  f(0);
    -  f(1);
    -
    -  var firstCall = f.getCalls()[0];
    -  var lastCall = f.getCalls()[1];
    -  assertEquals('return value of popLastCall', lastCall, f.popLastCall());
    -  assertArrayEquals('1 call remains', [firstCall], f.getCalls());
    -  assertEquals('next return value of popLastCall', firstCall, f.popLastCall());
    -  assertArrayEquals('0 calls remain', [], f.getCalls());
    -  assertNull('no more calls to pop', f.popLastCall());
    -}
    -
    -function testReset() {
    -  var f = goog.testing.recordFunction();
    -  f(0);
    -  f(1);
    -
    -  assertEquals('Should be two calls.', 2, f.getCallCount());
    -
    -  f.reset();
    -
    -  assertEquals('Call count should reset.', 0, f.getCallCount());
    -}
    -
    -function testAssertCallCount() {
    -  var f = goog.testing.recordFunction(goog.functions.identity);
    -
    -  f.assertCallCount(0);
    -
    -  f('Poodles');
    -  f.assertCallCount(1);
    -
    -  f('Hopscotch');
    -  f.assertCallCount(2);
    -
    -  f.reset();
    -  f.assertCallCount(0);
    -
    -  f('Bedazzler');
    -  f.assertCallCount(1);
    -
    -  assertThrows(function() {
    -    f.assertCallCount(11);
    -  });
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/shardingtestcase.js b/src/database/third_party/closure-library/closure/goog/testing/shardingtestcase.js
    deleted file mode 100644
    index e486d430a81..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/shardingtestcase.js
    +++ /dev/null
    @@ -1,125 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Utility for sharding tests.
    - *
    - * Usage instructions:
    - * <ol>
    - *   <li>Instead of writing your large test in foo_test.html, write it in
    - * foo_test_template.html</li>
    - *   <li>Add a call to {@code goog.testing.ShardingTestCase.shardByFileName()}
    - * near the top of your test, before any test cases or setup methods.</li>
    - *   <li>Symlink foo_test_template.html into different sharded test files
    - * named foo_1of4_test.html, foo_2of4_test.html, etc, using `ln -s`.</li>
    - *   <li>Add the symlinks as foo_1of4_test.html.
    - *       In perforce, run the command `g4 add foo_1of4_test.html` followed
    - * by `g4 reopen -t symlink foo_1of4_test.html` so that perforce treats the file
    - * as a symlink
    - *   </li>
    - * </ol>
    - *
    - * @author nicksantos@google.com (Nick Santos)
    - */
    -
    -goog.provide('goog.testing.ShardingTestCase');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.testing.TestCase');
    -
    -
    -
    -/**
    - * A test case that runs tests in per-file shards.
    - * @param {number} shardIndex Shard index for this page,
    - *     <strong>1-indexed</strong>.
    - * @param {number} numShards Number of shards to split up test cases into.
    - * @param {string=} opt_name The name of the test case.
    - * @extends {goog.testing.TestCase}
    - * @constructor
    - * @final
    - */
    -goog.testing.ShardingTestCase = function(shardIndex, numShards, opt_name) {
    -  goog.testing.ShardingTestCase.base(this, 'constructor', opt_name);
    -
    -  goog.asserts.assert(shardIndex > 0, 'Shard index should be positive');
    -  goog.asserts.assert(numShards > 0, 'Number of shards should be positive');
    -  goog.asserts.assert(shardIndex <= numShards,
    -      'Shard index out of bounds');
    -
    -  /**
    -   * @type {number}
    -   * @private
    -   */
    -  this.shardIndex_ = shardIndex;
    -
    -  /**
    -   * @type {number}
    -   * @private
    -   */
    -  this.numShards_ = numShards;
    -};
    -goog.inherits(goog.testing.ShardingTestCase, goog.testing.TestCase);
    -
    -
    -/**
    - * Whether we've actually partitioned the tests yet. We may execute twice
    - * ('Run again without reloading') without failing.
    - * @type {boolean}
    - * @private
    - */
    -goog.testing.ShardingTestCase.prototype.sharded_ = false;
    -
    -
    -/**
    - * Installs a runTests global function that goog.testing.JsUnit will use to
    - * run tests, which will run a single shard of the tests present on the page.
    - * @override
    - */
    -goog.testing.ShardingTestCase.prototype.runTests = function() {
    -  if (!this.sharded_) {
    -    var numTests = this.getCount();
    -    goog.asserts.assert(numTests >= this.numShards_,
    -        'Must have at least as many tests as shards!');
    -    var shardSize = Math.ceil(numTests / this.numShards_);
    -    var startIndex = (this.shardIndex_ - 1) * shardSize;
    -    var endIndex = startIndex + shardSize;
    -    goog.asserts.assert(this.order == goog.testing.TestCase.Order.SORTED,
    -        'Only SORTED order is allowed for sharded tests');
    -    this.setTests(this.getTests().slice(startIndex, endIndex));
    -    this.sharded_ = true;
    -  }
    -
    -  // Call original runTests method to execute the tests.
    -  goog.testing.ShardingTestCase.base(this, 'runTests');
    -};
    -
    -
    -/**
    - * Shards tests based on the test filename. Assumes that the filename is
    - * formatted like 'foo_1of5_test.html'.
    - * @param {string=} opt_name A descriptive name for the test case.
    - */
    -goog.testing.ShardingTestCase.shardByFileName = function(opt_name) {
    -  var path = window.location.pathname;
    -  var shardMatch = path.match(/_(\d+)of(\d+)_test\.(js|html)/);
    -  goog.asserts.assert(shardMatch,
    -      'Filename must be of the form "foo_1of5_test.{js,html}"');
    -  var shardIndex = parseInt(shardMatch[1], 10);
    -  var numShards = parseInt(shardMatch[2], 10);
    -
    -  var testCase = new goog.testing.ShardingTestCase(
    -      shardIndex, numShards, opt_name);
    -  goog.testing.TestCase.initializeTestRunner(testCase);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/shardingtestcase_test.html b/src/database/third_party/closure-library/closure/goog/testing/shardingtestcase_test.html
    deleted file mode 100644
    index 63e60e08e0d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/shardingtestcase_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.testing.asserts
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.ShardingTestCaseTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/shardingtestcase_test.js b/src/database/third_party/closure-library/closure/goog/testing/shardingtestcase_test.js
    deleted file mode 100644
    index cbe3c70856e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/shardingtestcase_test.js
    +++ /dev/null
    @@ -1,31 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.ShardingTestCaseTest');
    -goog.setTestOnly('goog.testing.ShardingTestCaseTest');
    -
    -goog.require('goog.testing.ShardingTestCase');
    -goog.require('goog.testing.TestCase');
    -goog.require('goog.testing.asserts');
    -goog.require('goog.testing.jsunit');
    -
    -goog.testing.TestCase.initializeTestRunner(
    -    new goog.testing.ShardingTestCase(1, 2));
    -
    -function testA() {
    -}
    -
    -function testB() {
    -  fail('testB should not be in this shard');
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/singleton.js b/src/database/third_party/closure-library/closure/goog/testing/singleton.js
    deleted file mode 100644
    index 03f104355d5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/singleton.js
    +++ /dev/null
    @@ -1,46 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview This module simplifies testing code which uses stateful
    - * singletons. {@code goog.testing.singleton.reset} resets all instances, so
    - * next time when {@code getInstance} is called, a new instance is created.
    - * It's recommended to reset the singletons in {@code tearDown} to prevent
    - * interference between subsequent tests.
    - *
    - * The {@code goog.testing.singleton} functions expect that the goog.DEBUG flag
    - * is enabled, and the tests are either uncompiled or compiled without renaming.
    - *
    - */
    -
    -goog.provide('goog.testing.singleton');
    -
    -
    -/**
    - * Deletes all singleton instances, so {@code getInstance} will return a new
    - * instance on next call.
    - */
    -goog.testing.singleton.reset = function() {
    -  var singletons = goog.getObjectByName('goog.instantiatedSingletons_');
    -  var ctor;
    -  while (ctor = singletons.pop()) {
    -    delete ctor.instance_;
    -  }
    -};
    -
    -
    -/**
    - * @deprecated Please use {@code goog.addSingletonGetter}.
    - */
    -goog.testing.singleton.addSingletonGetter = goog.addSingletonGetter;
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/singleton_test.html b/src/database/third_party/closure-library/closure/goog/testing/singleton_test.html
    deleted file mode 100644
    index ca9422670a9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/singleton_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.testing.singleton
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.singletonTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/singleton_test.js b/src/database/third_party/closure-library/closure/goog/testing/singleton_test.js
    deleted file mode 100644
    index 5ec19b21439..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/singleton_test.js
    +++ /dev/null
    @@ -1,33 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.singletonTest');
    -goog.setTestOnly('goog.testing.singletonTest');
    -
    -goog.require('goog.testing.asserts');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.singleton');
    -
    -function testGetInstance() {
    -  function SingletonClass() {}
    -  goog.addSingletonGetter(SingletonClass);
    -
    -  var s1 = SingletonClass.getInstance();
    -  var s2 = SingletonClass.getInstance();
    -  assertEquals('second getInstance call returns the same instance', s1, s2);
    -
    -  goog.testing.singleton.reset();
    -  var s3 = SingletonClass.getInstance();
    -  assertNotEquals('getInstance returns a new instance after reset', s1, s3);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/stacktrace.js b/src/database/third_party/closure-library/closure/goog/testing/stacktrace.js
    deleted file mode 100644
    index 9ece019c0da..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/stacktrace.js
    +++ /dev/null
    @@ -1,594 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Tools for parsing and pretty printing error stack traces.
    - *
    - */
    -
    -goog.provide('goog.testing.stacktrace');
    -goog.provide('goog.testing.stacktrace.Frame');
    -
    -
    -
    -/**
    - * Class representing one stack frame.
    - * @param {string} context Context object, empty in case of global functions or
    - *     if the browser doesn't provide this information.
    - * @param {string} name Function name, empty in case of anonymous functions.
    - * @param {string} alias Alias of the function if available. For example the
    - *     function name will be 'c' and the alias will be 'b' if the function is
    - *     defined as <code>a.b = function c() {};</code>.
    - * @param {string} args Arguments of the function in parentheses if available.
    - * @param {string} path File path or URL including line number and optionally
    - *     column number separated by colons.
    - * @constructor
    - * @final
    - */
    -goog.testing.stacktrace.Frame = function(context, name, alias, args, path) {
    -  this.context_ = context;
    -  this.name_ = name;
    -  this.alias_ = alias;
    -  this.args_ = args;
    -  this.path_ = path;
    -};
    -
    -
    -/**
    - * @return {string} The function name or empty string if the function is
    - *     anonymous and the object field which it's assigned to is unknown.
    - */
    -goog.testing.stacktrace.Frame.prototype.getName = function() {
    -  return this.name_;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the stack frame contains an anonymous function.
    - */
    -goog.testing.stacktrace.Frame.prototype.isAnonymous = function() {
    -  return !this.name_ || this.context_ == '[object Object]';
    -};
    -
    -
    -/**
    - * Brings one frame of the stack trace into a common format across browsers.
    - * @return {string} Pretty printed stack frame.
    - */
    -goog.testing.stacktrace.Frame.prototype.toCanonicalString = function() {
    -  var htmlEscape = goog.testing.stacktrace.htmlEscape_;
    -  var deobfuscate = goog.testing.stacktrace.maybeDeobfuscateFunctionName_;
    -
    -  var canonical = [
    -    this.context_ ? htmlEscape(this.context_) + '.' : '',
    -    this.name_ ? htmlEscape(deobfuscate(this.name_)) : 'anonymous',
    -    htmlEscape(this.args_),
    -    this.alias_ ? ' [as ' + htmlEscape(deobfuscate(this.alias_)) + ']' : ''
    -  ];
    -
    -  if (this.path_) {
    -    canonical.push(' at ');
    -    canonical.push(htmlEscape(this.path_));
    -  }
    -  return canonical.join('');
    -};
    -
    -
    -/**
    - * Maximum number of steps while the call chain is followed.
    - * @private {number}
    - * @const
    - */
    -goog.testing.stacktrace.MAX_DEPTH_ = 20;
    -
    -
    -/**
    - * Maximum length of a string that can be matched with a RegExp on
    - * Firefox 3x. Exceeding this approximate length will cause string.match
    - * to exceed Firefox's stack quota. This situation can be encountered
    - * when goog.globalEval is invoked with a long argument; such as
    - * when loading a module.
    - * @private {number}
    - * @const
    - */
    -goog.testing.stacktrace.MAX_FIREFOX_FRAMESTRING_LENGTH_ = 500000;
    -
    -
    -/**
    - * RegExp pattern for JavaScript identifiers. We don't support Unicode
    - * identifiers defined in ECMAScript v3.
    - * @private {string}
    - * @const
    - */
    -goog.testing.stacktrace.IDENTIFIER_PATTERN_ = '[a-zA-Z_$][\\w$]*';
    -
    -
    -/**
    - * RegExp pattern for function name alias in the V8 stack trace.
    - * @private {string}
    - * @const
    - */
    -goog.testing.stacktrace.V8_ALIAS_PATTERN_ =
    -    '(?: \\[as (' + goog.testing.stacktrace.IDENTIFIER_PATTERN_ + ')\\])?';
    -
    -
    -/**
    - * RegExp pattern for the context of a function call in a V8 stack trace.
    - * Creates an optional submatch for the namespace identifier including the
    - * "new" keyword for constructor calls (e.g. "new foo.Bar").
    - * @private {string}
    - * @const
    - */
    -goog.testing.stacktrace.V8_CONTEXT_PATTERN_ =
    -    '(?:((?:new )?(?:\\[object Object\\]|' +
    -    goog.testing.stacktrace.IDENTIFIER_PATTERN_ +
    -    '(?:\\.' + goog.testing.stacktrace.IDENTIFIER_PATTERN_ + ')*))\\.)?';
    -
    -
    -/**
    - * RegExp pattern for function names and constructor calls in the V8 stack
    - * trace.
    - * @private {string}
    - * @const
    - */
    -goog.testing.stacktrace.V8_FUNCTION_NAME_PATTERN_ =
    -    '(?:new )?(?:' + goog.testing.stacktrace.IDENTIFIER_PATTERN_ +
    -    '|<anonymous>)';
    -
    -
    -/**
    - * RegExp pattern for function call in the V8 stack trace. Creates 3 submatches
    - * with context object (optional), function name and function alias (optional).
    - * @private {string}
    - * @const
    - */
    -goog.testing.stacktrace.V8_FUNCTION_CALL_PATTERN_ =
    -    ' ' + goog.testing.stacktrace.V8_CONTEXT_PATTERN_ +
    -    '(' + goog.testing.stacktrace.V8_FUNCTION_NAME_PATTERN_ + ')' +
    -    goog.testing.stacktrace.V8_ALIAS_PATTERN_;
    -
    -
    -/**
    - * RegExp pattern for an URL + position inside the file.
    - * @private {string}
    - * @const
    - */
    -goog.testing.stacktrace.URL_PATTERN_ =
    -    '((?:http|https|file)://[^\\s)]+|javascript:.*)';
    -
    -
    -/**
    - * RegExp pattern for an URL + line number + column number in V8.
    - * The URL is either in submatch 1 or submatch 2.
    - * @private {string}
    - * @const
    - */
    -goog.testing.stacktrace.CHROME_URL_PATTERN_ = ' (?:' +
    -    '\\(unknown source\\)' + '|' +
    -    '\\(native\\)' + '|' +
    -    '\\((.+)\\)|(.+))';
    -
    -
    -/**
    - * Regular expression for parsing one stack frame in V8. For more information
    - * on V8 stack frame formats, see
    - * https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi.
    - * @private {!RegExp}
    - * @const
    - */
    -goog.testing.stacktrace.V8_STACK_FRAME_REGEXP_ = new RegExp('^    at' +
    -    '(?:' + goog.testing.stacktrace.V8_FUNCTION_CALL_PATTERN_ + ')?' +
    -    goog.testing.stacktrace.CHROME_URL_PATTERN_ + '$');
    -
    -
    -/**
    - * RegExp pattern for function call in the Firefox stack trace.
    - * Creates 2 submatches with function name (optional) and arguments.
    - * @private {string}
    - * @const
    - */
    -goog.testing.stacktrace.FIREFOX_FUNCTION_CALL_PATTERN_ =
    -    '(' + goog.testing.stacktrace.IDENTIFIER_PATTERN_ + ')?' +
    -    '(\\(.*\\))?@';
    -
    -
    -/**
    - * Regular expression for parsing one stack frame in Firefox.
    - * @private {!RegExp}
    - * @const
    - */
    -goog.testing.stacktrace.FIREFOX_STACK_FRAME_REGEXP_ = new RegExp('^' +
    -    goog.testing.stacktrace.FIREFOX_FUNCTION_CALL_PATTERN_ +
    -    '(?::0|' + goog.testing.stacktrace.URL_PATTERN_ + ')$');
    -
    -
    -/**
    - * RegExp pattern for an anonymous function call in an Opera stack frame.
    - * Creates 2 (optional) submatches: the context object and function name.
    - * @private {string}
    - * @const
    - */
    -goog.testing.stacktrace.OPERA_ANONYMOUS_FUNCTION_NAME_PATTERN_ =
    -    '<anonymous function(?:\\: ' +
    -    '(?:(' + goog.testing.stacktrace.IDENTIFIER_PATTERN_ +
    -    '(?:\\.' + goog.testing.stacktrace.IDENTIFIER_PATTERN_ + ')*)\\.)?' +
    -    '(' + goog.testing.stacktrace.IDENTIFIER_PATTERN_ + '))?>';
    -
    -
    -/**
    - * RegExp pattern for a function call in an Opera stack frame.
    - * Creates 4 (optional) submatches: the function name (if not anonymous),
    - * the aliased context object and function name (if anonymous), and the
    - * function call arguments.
    - * @private {string}
    - * @const
    - */
    -goog.testing.stacktrace.OPERA_FUNCTION_CALL_PATTERN_ =
    -    '(?:(?:(' + goog.testing.stacktrace.IDENTIFIER_PATTERN_ + ')|' +
    -    goog.testing.stacktrace.OPERA_ANONYMOUS_FUNCTION_NAME_PATTERN_ +
    -    ')(\\(.*\\)))?@';
    -
    -
    -/**
    - * Regular expression for parsing on stack frame in Opera 11.68 - 12.17.
    - * Newer versions of Opera use V8 and stack frames should match against
    - * goog.testing.stacktrace.V8_STACK_FRAME_REGEXP_.
    - * @private {!RegExp}
    - * @const
    - */
    -goog.testing.stacktrace.OPERA_STACK_FRAME_REGEXP_ = new RegExp('^' +
    -    goog.testing.stacktrace.OPERA_FUNCTION_CALL_PATTERN_ +
    -    goog.testing.stacktrace.URL_PATTERN_ + '?$');
    -
    -
    -/**
    - * Regular expression for finding the function name in its source.
    - * @private {!RegExp}
    - * @const
    - */
    -goog.testing.stacktrace.FUNCTION_SOURCE_REGEXP_ = new RegExp(
    -    '^function (' + goog.testing.stacktrace.IDENTIFIER_PATTERN_ + ')');
    -
    -
    -/**
    - * RegExp pattern for function call in a IE stack trace. This expression allows
    - * for identifiers like 'Anonymous function', 'eval code', and 'Global code'.
    - * @private {string}
    - * @const
    - */
    -goog.testing.stacktrace.IE_FUNCTION_CALL_PATTERN_ = '(' +
    -    goog.testing.stacktrace.IDENTIFIER_PATTERN_ + '(?:\\s+\\w+)*)';
    -
    -
    -/**
    - * Regular expression for parsing a stack frame in IE.
    - * @private {!RegExp}
    - * @const
    - */
    -goog.testing.stacktrace.IE_STACK_FRAME_REGEXP_ = new RegExp('^   at ' +
    -    goog.testing.stacktrace.IE_FUNCTION_CALL_PATTERN_ +
    -    '\\s*\\((eval code:[^)]*|' + goog.testing.stacktrace.URL_PATTERN_ +
    -    ')\\)?$');
    -
    -
    -/**
    - * Creates a stack trace by following the call chain. Based on
    - * {@link goog.debug.getStacktrace}.
    - * @return {!Array<!goog.testing.stacktrace.Frame>} Stack frames.
    - * @private
    - * @suppress {es5Strict}
    - */
    -goog.testing.stacktrace.followCallChain_ = function() {
    -  var frames = [];
    -  var fn = arguments.callee.caller;
    -  var depth = 0;
    -
    -  while (fn && depth < goog.testing.stacktrace.MAX_DEPTH_) {
    -    var fnString = Function.prototype.toString.call(fn);
    -    var match = fnString.match(goog.testing.stacktrace.FUNCTION_SOURCE_REGEXP_);
    -    var functionName = match ? match[1] : '';
    -
    -    var argsBuilder = ['('];
    -    if (fn.arguments) {
    -      for (var i = 0; i < fn.arguments.length; i++) {
    -        var arg = fn.arguments[i];
    -        if (i > 0) {
    -          argsBuilder.push(', ');
    -        }
    -        if (goog.isString(arg)) {
    -          argsBuilder.push('"', arg, '"');
    -        } else {
    -          // Some args are mocks, and we don't want to fail from them not having
    -          // expected a call to toString, so instead insert a static string.
    -          if (arg && arg['$replay']) {
    -            argsBuilder.push('goog.testing.Mock');
    -          } else {
    -            argsBuilder.push(String(arg));
    -          }
    -        }
    -      }
    -    } else {
    -      // Opera 10 doesn't know the arguments of native functions.
    -      argsBuilder.push('unknown');
    -    }
    -    argsBuilder.push(')');
    -    var args = argsBuilder.join('');
    -
    -    frames.push(new goog.testing.stacktrace.Frame('', functionName, '', args,
    -        ''));
    -
    -    /** @preserveTry */
    -    try {
    -      fn = fn.caller;
    -    } catch (e) {
    -      break;
    -    }
    -    depth++;
    -  }
    -
    -  return frames;
    -};
    -
    -
    -/**
    - * Parses one stack frame.
    - * @param {string} frameStr The stack frame as string.
    - * @return {goog.testing.stacktrace.Frame} Stack frame object or null if the
    - *     parsing failed.
    - * @private
    - */
    -goog.testing.stacktrace.parseStackFrame_ = function(frameStr) {
    -  // This match includes newer versions of Opera (15+).
    -  var m = frameStr.match(goog.testing.stacktrace.V8_STACK_FRAME_REGEXP_);
    -  if (m) {
    -    return new goog.testing.stacktrace.Frame(m[1] || '', m[2] || '', m[3] || '',
    -        '', m[4] || m[5] || m[6] || '');
    -  }
    -
    -  if (frameStr.length >
    -      goog.testing.stacktrace.MAX_FIREFOX_FRAMESTRING_LENGTH_) {
    -    return goog.testing.stacktrace.parseLongFirefoxFrame_(frameStr);
    -  }
    -
    -  m = frameStr.match(goog.testing.stacktrace.FIREFOX_STACK_FRAME_REGEXP_);
    -  if (m) {
    -    return new goog.testing.stacktrace.Frame('', m[1] || '', '', m[2] || '',
    -        m[3] || '');
    -  }
    -
    -  // Match against Presto Opera 11.68 - 12.17.
    -  m = frameStr.match(goog.testing.stacktrace.OPERA_STACK_FRAME_REGEXP_);
    -  if (m) {
    -    return new goog.testing.stacktrace.Frame(m[2] || '', m[1] || m[3] || '',
    -        '', m[4] || '', m[5] || '');
    -  }
    -
    -  m = frameStr.match(goog.testing.stacktrace.IE_STACK_FRAME_REGEXP_);
    -  if (m) {
    -    return new goog.testing.stacktrace.Frame('', m[1] || '', '', '',
    -        m[2] || '');
    -  }
    -
    -  return null;
    -};
    -
    -
    -/**
    - * Parses a long firefox stack frame.
    - * @param {string} frameStr The stack frame as string.
    - * @return {!goog.testing.stacktrace.Frame} Stack frame object.
    - * @private
    - */
    -goog.testing.stacktrace.parseLongFirefoxFrame_ = function(frameStr) {
    -  var firstParen = frameStr.indexOf('(');
    -  var lastAmpersand = frameStr.lastIndexOf('@');
    -  var lastColon = frameStr.lastIndexOf(':');
    -  var functionName = '';
    -  if ((firstParen >= 0) && (firstParen < lastAmpersand)) {
    -    functionName = frameStr.substring(0, firstParen);
    -  }
    -  var loc = '';
    -  if ((lastAmpersand >= 0) && (lastAmpersand + 1 < lastColon)) {
    -    loc = frameStr.substring(lastAmpersand + 1);
    -  }
    -  var args = '';
    -  if ((firstParen >= 0 && lastAmpersand > 0) &&
    -      (firstParen < lastAmpersand)) {
    -    args = frameStr.substring(firstParen, lastAmpersand);
    -  }
    -  return new goog.testing.stacktrace.Frame('', functionName, '', args, loc);
    -};
    -
    -
    -/**
    - * Function to deobfuscate function names.
    - * @type {function(string): string}
    - * @private
    - */
    -goog.testing.stacktrace.deobfuscateFunctionName_;
    -
    -
    -/**
    - * Sets function to deobfuscate function names.
    - * @param {function(string): string} fn function to deobfuscate function names.
    - */
    -goog.testing.stacktrace.setDeobfuscateFunctionName = function(fn) {
    -  goog.testing.stacktrace.deobfuscateFunctionName_ = fn;
    -};
    -
    -
    -/**
    - * Deobfuscates a compiled function name with the function passed to
    - * {@link #setDeobfuscateFunctionName}. Returns the original function name if
    - * the deobfuscator hasn't been set.
    - * @param {string} name The function name to deobfuscate.
    - * @return {string} The deobfuscated function name.
    - * @private
    - */
    -goog.testing.stacktrace.maybeDeobfuscateFunctionName_ = function(name) {
    -  return goog.testing.stacktrace.deobfuscateFunctionName_ ?
    -      goog.testing.stacktrace.deobfuscateFunctionName_(name) : name;
    -};
    -
    -
    -/**
    - * Escapes the special character in HTML.
    - * @param {string} text Plain text.
    - * @return {string} Escaped text.
    - * @private
    - */
    -goog.testing.stacktrace.htmlEscape_ = function(text) {
    -  return text.replace(/&/g, '&amp;').
    -             replace(/</g, '&lt;').
    -             replace(/>/g, '&gt;').
    -             replace(/"/g, '&quot;');
    -};
    -
    -
    -/**
    - * Converts the stack frames into canonical format. Chops the beginning and the
    - * end of it which come from the testing environment, not from the test itself.
    - * @param {!Array<goog.testing.stacktrace.Frame>} frames The frames.
    - * @return {string} Canonical, pretty printed stack trace.
    - * @private
    - */
    -goog.testing.stacktrace.framesToString_ = function(frames) {
    -  // Removes the anonymous calls from the end of the stack trace (they come
    -  // from testrunner.js, testcase.js and asserts.js), so the stack trace will
    -  // end with the test... method.
    -  var lastIndex = frames.length - 1;
    -  while (frames[lastIndex] && frames[lastIndex].isAnonymous()) {
    -    lastIndex--;
    -  }
    -
    -  // Removes the beginning of the stack trace until the call of the private
    -  // _assert function (inclusive), so the stack trace will begin with a public
    -  // asserter. Does nothing if _assert is not present in the stack trace.
    -  var privateAssertIndex = -1;
    -  for (var i = 0; i < frames.length; i++) {
    -    if (frames[i] && frames[i].getName() == '_assert') {
    -      privateAssertIndex = i;
    -      break;
    -    }
    -  }
    -
    -  var canonical = [];
    -  for (var i = privateAssertIndex + 1; i <= lastIndex; i++) {
    -    canonical.push('> ');
    -    if (frames[i]) {
    -      canonical.push(frames[i].toCanonicalString());
    -    } else {
    -      canonical.push('(unknown)');
    -    }
    -    canonical.push('\n');
    -  }
    -  return canonical.join('');
    -};
    -
    -
    -/**
    - * Parses the browser's native stack trace.
    - * @param {string} stack Stack trace.
    - * @return {!Array<goog.testing.stacktrace.Frame>} Stack frames. The
    - *     unrecognized frames will be nulled out.
    - * @private
    - */
    -goog.testing.stacktrace.parse_ = function(stack) {
    -  var lines = stack.replace(/\s*$/, '').split('\n');
    -  var frames = [];
    -  for (var i = 0; i < lines.length; i++) {
    -    frames.push(goog.testing.stacktrace.parseStackFrame_(lines[i]));
    -  }
    -  return frames;
    -};
    -
    -
    -/**
    - * Brings the stack trace into a common format across browsers.
    - * @param {string} stack Browser-specific stack trace.
    - * @return {string} Same stack trace in common format.
    - */
    -goog.testing.stacktrace.canonicalize = function(stack) {
    -  var frames = goog.testing.stacktrace.parse_(stack);
    -  return goog.testing.stacktrace.framesToString_(frames);
    -};
    -
    -
    -/**
    - * Returns the native stack trace.
    - * @return {string|!Array<!CallSite>}
    - * @private
    - */
    -goog.testing.stacktrace.getNativeStack_ = function() {
    -  var tmpError = new Error();
    -  if (tmpError.stack) {
    -    return tmpError.stack;
    -  }
    -
    -  // IE10 will only create a stack trace when the Error is thrown.
    -  // We use null.x() to throw an exception because the closure compiler may
    -  // replace "throw" with a function call in an attempt to minimize the binary
    -  // size, which in turn has the side effect of adding an unwanted stack frame.
    -  try {
    -    null.x();
    -  } catch (e) {
    -    return e.stack;
    -  }
    -  return '';
    -};
    -
    -
    -/**
    - * Gets the native stack trace if available otherwise follows the call chain.
    - * @return {string} The stack trace in canonical format.
    - */
    -goog.testing.stacktrace.get = function() {
    -  var stack = goog.testing.stacktrace.getNativeStack_();
    -  var frames;
    -  if (!stack) {
    -    frames = goog.testing.stacktrace.followCallChain_();
    -  } else if (goog.isArray(stack)) {
    -    frames = goog.testing.stacktrace.callSitesToFrames_(stack);
    -  } else {
    -    frames = goog.testing.stacktrace.parse_(stack);
    -  }
    -  return goog.testing.stacktrace.framesToString_(frames);
    -};
    -
    -
    -/**
    - * Converts an array of CallSite (elements of a stack trace in V8) to an array
    - * of Frames.
    - * @param {!Array<!CallSite>} stack The stack as an array of CallSites.
    - * @return {!Array<!goog.testing.stacktrace.Frame>} The stack as an array of
    - *     Frames.
    - * @private
    - */
    -goog.testing.stacktrace.callSitesToFrames_ = function(stack) {
    -  var frames = [];
    -  for (var i = 0; i < stack.length; i++) {
    -    var callSite = stack[i];
    -    var functionName = callSite.getFunctionName() || 'unknown';
    -    var fileName = callSite.getFileName();
    -    var path = fileName ? fileName + ':' + callSite.getLineNumber() + ':' +
    -        callSite.getColumnNumber() : 'unknown';
    -    frames.push(
    -        new goog.testing.stacktrace.Frame('', functionName, '', '', path));
    -  }
    -  return frames;
    -};
    -
    -
    -goog.exportSymbol('setDeobfuscateFunctionName',
    -    goog.testing.stacktrace.setDeobfuscateFunctionName);
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/stacktrace_test.html b/src/database/third_party/closure-library/closure/goog/testing/stacktrace_test.html
    deleted file mode 100644
    index e50c94b6abb..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/stacktrace_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.testing.stacktrace
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.stacktraceTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/stacktrace_test.js b/src/database/third_party/closure-library/closure/goog/testing/stacktrace_test.js
    deleted file mode 100644
    index 1bb945c7a13..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/stacktrace_test.js
    +++ /dev/null
    @@ -1,375 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.stacktraceTest');
    -goog.setTestOnly('goog.testing.stacktraceTest');
    -
    -goog.require('goog.functions');
    -goog.require('goog.string');
    -goog.require('goog.testing.ExpectedFailures');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.StrictMock');
    -goog.require('goog.testing.asserts');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.stacktrace');
    -goog.require('goog.testing.stacktrace.Frame');
    -goog.require('goog.userAgent');
    -
    -var stubs = new goog.testing.PropertyReplacer();
    -var expectedFailures;
    -function setUpPage() {
    -  expectedFailures = new goog.testing.ExpectedFailures();
    -}
    -
    -function setUp() {
    -  stubs.set(goog.testing.stacktrace, 'isClosureInspectorActive_', function() {
    -    return false;
    -  });
    -}
    -
    -function tearDown() {
    -  stubs.reset();
    -  expectedFailures.handleTearDown();
    -}
    -
    -function testParseStackFrameInV8() {
    -  var frameString = '    at Error (unknown source)';
    -  var frame = goog.testing.stacktrace.parseStackFrame_(frameString);
    -  var expected = new goog.testing.stacktrace.Frame('', 'Error', '', '', '');
    -  assertObjectEquals('exception name only', expected, frame);
    -
    -  frameString = '    at Object.assert (file:///.../asserts.js:29:10)';
    -  frame = goog.testing.stacktrace.parseStackFrame_(frameString);
    -  expected = new goog.testing.stacktrace.Frame('Object', 'assert', '', '',
    -      'file:///.../asserts.js:29:10');
    -  assertObjectEquals('context object + function name + url', expected, frame);
    -
    -  frameString = '    at Object.x.y.z (/Users/bob/file.js:564:9)';
    -  frame = goog.testing.stacktrace.parseStackFrame_(frameString);
    -  expected = new goog.testing.stacktrace.Frame('Object.x.y', 'z', '', '',
    -      '/Users/bob/file.js:564:9');
    -  assertObjectEquals('nested context object + function name + url',
    -      expected, frame);
    -
    -  frameString = '    at http://www.example.com/jsunit.js:117:13';
    -  frame = goog.testing.stacktrace.parseStackFrame_(frameString);
    -  expected = new goog.testing.stacktrace.Frame('', '', '', '',
    -      'http://www.example.com/jsunit.js:117:13');
    -  assertObjectEquals('url only', expected, frame);
    -
    -  frameString = '    at [object Object].exec [as execute] (file:///foo)';
    -  frame = goog.testing.stacktrace.parseStackFrame_(frameString);
    -  expected = new goog.testing.stacktrace.Frame('[object Object]', 'exec',
    -      'execute', '', 'file:///foo');
    -  assertObjectEquals('function alias', expected, frame);
    -
    -  frameString = '    at new Class (file:///foo)';
    -  frame = goog.testing.stacktrace.parseStackFrame_(frameString);
    -  expected = new goog.testing.stacktrace.Frame('', 'new Class', '', '',
    -      'file:///foo');
    -  assertObjectEquals('constructor call', expected, frame);
    -
    -  frameString = '    at new <anonymous> (file:///foo)';
    -  frame = goog.testing.stacktrace.parseStackFrame_(frameString);
    -  expected = new goog.testing.stacktrace.Frame('', 'new <anonymous>', '', '',
    -      'file:///foo');
    -  assertObjectEquals('anonymous constructor call', expected, frame);
    -
    -  frameString = '    at Array.forEach (native)';
    -  frame = goog.testing.stacktrace.parseStackFrame_(frameString);
    -  expected = new goog.testing.stacktrace.Frame('Array', 'forEach', '', '', '');
    -  assertObjectEquals('native function call', expected, frame);
    -
    -  frameString = '    at foo (eval at file://bar)';
    -  frame = goog.testing.stacktrace.parseStackFrame_(frameString);
    -  expected = new goog.testing.stacktrace.Frame('', 'foo', '', '',
    -      'eval at file://bar');
    -  assertObjectEquals('eval', expected, frame);
    -
    -  frameString = '    at foo.bar (closure/goog/foo.js:11:99)';
    -  frame = goog.testing.stacktrace.parseStackFrame_(frameString);
    -  expected = new goog.testing.stacktrace.Frame('foo', 'bar', '', '',
    -      'closure/goog/foo.js:11:99');
    -  assertObjectEquals('Path without schema', expected, frame);
    -
    -  // In the Chrome console, execute: console.log(eval('Error().stack')).
    -  frameString =
    -      '    at eval (eval at <anonymous> (unknown source), <anonymous>:1:1)';
    -  frame = goog.testing.stacktrace.parseStackFrame_(frameString);
    -  expected = new goog.testing.stacktrace.Frame('', 'eval', '', '',
    -      'eval at <anonymous> (unknown source), <anonymous>:1:1');
    -  assertObjectEquals('nested eval', expected, frame);
    -}
    -
    -function testParseStackFrameInOpera() {
    -  var frameString = '@';
    -  var frame = goog.testing.stacktrace.parseStackFrame_(frameString);
    -  var expected = new goog.testing.stacktrace.Frame('', '', '', '', '');
    -  assertObjectEquals('empty frame', expected, frame);
    -
    -  frameString = '@javascript:console.log(Error().stack):1';
    -  frame = goog.testing.stacktrace.parseStackFrame_(frameString);
    -  expected = new goog.testing.stacktrace.Frame('', '', '', '',
    -      'javascript:console.log(Error().stack):1');
    -  assertObjectEquals('javascript path only', expected, frame);
    -
    -  frameString = '@file:///foo:42';
    -  frame = goog.testing.stacktrace.parseStackFrame_(frameString);
    -  expected = new goog.testing.stacktrace.Frame('', '', '', '',
    -      'file:///foo:42');
    -  assertObjectEquals('path only', expected, frame);
    -
    -  // (function go() { throw Error() })()
    -  // var c = go; c()
    -  frameString = 'go([arguments not available])@';
    -  frame = goog.testing.stacktrace.parseStackFrame_(frameString);
    -  expected = new goog.testing.stacktrace.Frame('', 'go', '',
    -      '([arguments not available])', '');
    -  assertObjectEquals('name and empty path', expected, frame);
    -
    -  frameString = 'go([arguments not available])@file:///foo:42';
    -  frame = goog.testing.stacktrace.parseStackFrame_(frameString);
    -  expected = new goog.testing.stacktrace.Frame('', 'go', '',
    -      '([arguments not available])', 'file:///foo:42');
    -  assertObjectEquals('name and path', expected, frame);
    -
    -  // (function() { throw Error() })()
    -  frameString =
    -      '<anonymous function>([arguments not available])@file:///foo:42';
    -  frame = goog.testing.stacktrace.parseStackFrame_(frameString);
    -  expected = new goog.testing.stacktrace.Frame('', '', '',
    -      '([arguments not available])', 'file:///foo:42');
    -  assertObjectEquals('anonymous function', expected, frame);
    -
    -  // var b = {foo: function() { throw Error() }}
    -  frameString = '<anonymous function: foo>()@file:///foo:42';
    -  frame = goog.testing.stacktrace.parseStackFrame_(frameString);
    -  expected = new goog.testing.stacktrace.Frame(
    -      '', 'foo', '', '()', 'file:///foo:42');
    -  assertObjectEquals('object literal function', expected, frame);
    -
    -  // var c = {}; c.foo = function() { throw Error() }
    -  frameString = '<anonymous function: c.foo>()@file:///foo:42';
    -  frame = goog.testing.stacktrace.parseStackFrame_(frameString);
    -  expected = new goog.testing.stacktrace.Frame(
    -      'c', 'foo', '', '()', 'file:///foo:42');
    -  assertObjectEquals('named object literal function', expected, frame);
    -
    -  frameString = '<anonymous function: Foo.prototype.bar>()@';
    -  frame = goog.testing.stacktrace.parseStackFrame_(frameString);
    -  expected = new goog.testing.stacktrace.Frame(
    -      'Foo.prototype', 'bar', '', '()', '');
    -  assertObjectEquals('prototype function', expected, frame);
    -
    -  frameString = '<anonymous function: goog.Foo.prototype.bar>()@';
    -  frame = goog.testing.stacktrace.parseStackFrame_(frameString);
    -  expected = new goog.testing.stacktrace.Frame(
    -      'goog.Foo.prototype', 'bar', '', '()', '');
    -  assertObjectEquals('namespaced prototype function', expected, frame);
    -}
    -
    -// All test strings are parsed with the conventional and long
    -// frame algorithms.
    -function testParseStackFrameInFirefox() {
    -  var frameString = 'Error("Assertion failed")@:0';
    -  var frame = goog.testing.stacktrace.parseStackFrame_(frameString);
    -  var expected = new goog.testing.stacktrace.Frame('', 'Error', '',
    -      '("Assertion failed")', '');
    -  assertObjectEquals('function name + arguments', expected, frame);
    -
    -  frame = goog.testing.stacktrace.parseLongFirefoxFrame_(frameString);
    -  assertObjectEquals('function name + arguments', expected, frame);
    -
    -  frameString = '()@file:///foo:42';
    -  frame = goog.testing.stacktrace.parseStackFrame_(frameString);
    -  expected = new goog.testing.stacktrace.Frame('', '', '', '()',
    -      'file:///foo:42');
    -  assertObjectEquals('anonymous function', expected, frame);
    -
    -  frame = goog.testing.stacktrace.parseLongFirefoxFrame_(frameString);
    -  assertObjectEquals('anonymous function', expected, frame);
    -
    -  frameString = '@javascript:alert(0)';
    -  frame = goog.testing.stacktrace.parseStackFrame_(frameString);
    -  expected = new goog.testing.stacktrace.Frame('', '', '', '',
    -      'javascript:alert(0)');
    -  assertObjectEquals('anonymous function', expected, frame);
    -
    -  frame = goog.testing.stacktrace.parseLongFirefoxFrame_(frameString);
    -  assertObjectEquals('anonymous function', expected, frame);
    -}
    -
    -function testCanonicalizeFrame() {
    -  var frame = new goog.testing.stacktrace.Frame('<window>', 'foo', 'bar',
    -      '("<a>\'&amp;")', 'http://x?a=1&b=2:1');
    -  assertEquals('canonical stack frame, everything is escaped',
    -      '&lt;window&gt;.foo(&quot;&lt;a&gt;\'&amp;amp;&quot;) ' +
    -      '[as bar] at http://x?a=1&amp;b=2:1', frame.toCanonicalString());
    -}
    -
    -function testDeobfuscateFunctionName() {
    -  goog.testing.stacktrace.setDeobfuscateFunctionName(function(name) {
    -    return name.replace(/\$/g, '.');
    -  });
    -
    -  var frame = new goog.testing.stacktrace.Frame('', 'a$b$c', 'd$e', '', '');
    -  assertEquals('deobfuscated function name', 'a.b.c [as d.e]',
    -      frame.toCanonicalString());
    -}
    -
    -function testFramesToString() {
    -  var normalFrame = new goog.testing.stacktrace.Frame('', 'foo', '', '', '');
    -  var anonFrame = new goog.testing.stacktrace.Frame('', '', '', '', '');
    -  var frames = [normalFrame, anonFrame, null, anonFrame];
    -  var stack = goog.testing.stacktrace.framesToString_(frames);
    -  assertEquals('framesToString', '> foo\n> anonymous\n> (unknown)\n', stack);
    -}
    -
    -function testFollowCallChain() {
    -  var func = function(var_args) {
    -    return goog.testing.stacktrace.followCallChain_();
    -  };
    -
    -  // Created a fake type with a toString method.
    -  function LocalType() {};
    -  LocalType.prototype.toString = function() {
    -    return 'sg';
    -  };
    -
    -  // Create a mock with no expectations.
    -  var mock = new goog.testing.StrictMock(LocalType);
    -
    -  mock.$replay();
    -
    -  var frames = func(undefined, null, false, 0, '', {}, goog.nullFunction,
    -      mock, new LocalType);
    -
    -  // Opera before version 10 doesn't support the caller attribute. In that
    -  // browser followCallChain_() returns empty stack trace.
    -  expectedFailures.expectFailureFor(goog.userAgent.OPERA &&
    -      !goog.userAgent.isVersionOrHigher('10'));
    -  try {
    -    assertTrue('The stack trace consists of >=2 frames', frames.length >= 2);
    -  } catch (e) {
    -    expectedFailures.handleException(e);
    -  }
    -
    -  if (frames.length >= 2) {
    -    assertEquals('innermost function is anonymous', '', frames[0].getName());
    -    // There are white space differences how browsers convert functions to
    -    // strings.
    -    var expected = '(undefined,null,false,0,"",[objectObject],function(){},' +
    -        'goog.testing.Mock,sg)';
    -    assertEquals('arguments of the innermost function (ignoring whitespaces)',
    -        expected, frames[0].args_.replace(/\s/g, ''));
    -    assertEquals('test function name', 'testFollowCallChain',
    -        frames[1].getName());
    -  }
    -
    -  mock.$verify();
    -}
    -
    -// Create a stack trace string with one modest record and one long record,
    -// Verify that all frames are parsed. The length of the long arg is set
    -// to blow Firefox 3x's stack if put through a RegExp.
    -function testParsingLongStackTrace() {
    -  var longArg = goog.string.buildString(
    -      '(', goog.string.repeat('x', 1000000), ')');
    -  var stackTrace = goog.string.buildString(
    -      'shortFrame()@:0\n',
    -      'longFrame',
    -      longArg,
    -      '@http://google.com/somescript:0\n');
    -  var frames = goog.testing.stacktrace.parse_(stackTrace);
    -  assertEquals('number of returned frames', 2, frames.length);
    -  var expected = new goog.testing.stacktrace.Frame(
    -      '', 'shortFrame', '', '()', '');
    -  assertObjectEquals('short frame', expected, frames[0]);
    -
    -  expected = new goog.testing.stacktrace.Frame(
    -      '', 'longFrame', '', longArg, 'http://google.com/somescript:0');
    -  assertObjectEquals('exception name only', expected, frames[1]);
    -}
    -
    -function testParseStackFrameInIE10() {
    -  var frameString = '   at foo (http://bar:4000/bar.js:150:3)';
    -  var frame = goog.testing.stacktrace.parseStackFrame_(frameString);
    -  var expected = new goog.testing.stacktrace.Frame('', 'foo', '', '',
    -      'http://bar:4000/bar.js:150:3');
    -  assertObjectEquals('name and path', expected, frame);
    -
    -  frameString = '   at Anonymous function (http://bar:4000/bar.js:150:3)';
    -  frame = goog.testing.stacktrace.parseStackFrame_(frameString);
    -  expected = new goog.testing.stacktrace.Frame('', 'Anonymous function', '', '',
    -      'http://bar:4000/bar.js:150:3');
    -  assertObjectEquals('Anonymous function', expected, frame);
    -
    -  frameString = '   at Global code (http://bar:4000/bar.js:150:3)';
    -  frame = goog.testing.stacktrace.parseStackFrame_(frameString);
    -  expected = new goog.testing.stacktrace.Frame('', 'Global code', '', '',
    -      'http://bar:4000/bar.js:150:3');
    -  assertObjectEquals('Global code', expected, frame);
    -
    -  frameString = '   at foo (eval code:150:3)';
    -  frame = goog.testing.stacktrace.parseStackFrame_(frameString);
    -  expected = new goog.testing.stacktrace.Frame('', 'foo', '', '',
    -      'eval code:150:3');
    -  assertObjectEquals('eval code', expected, frame);
    -
    -  frameString = '   at eval code (eval code:150:3)';
    -  frame = goog.testing.stacktrace.parseStackFrame_(frameString);
    -  expected = new goog.testing.stacktrace.Frame('', 'eval code', '', '',
    -      'eval code:150:3');
    -  assertObjectEquals('nested eval', expected, frame);
    -}
    -
    -// Verifies that retrieving the stack trace works when the 'stack' field of an
    -// exception contains an array of CallSites instead of a string. This is the
    -// case when running in a lightweight V8 runtime (for instance, in gjstests),
    -// as opposed to a browser environment.
    -function testGetStackFrameWithV8CallSites() {
    -  // A function to create V8 CallSites. Note that CallSite is an extern and thus
    -  // cannot be mocked with closure mocks.
    -  function createCallSite(functionName, fileName, lineNumber, colNumber) {
    -    return {
    -      getFunctionName: goog.functions.constant(functionName),
    -      getFileName: goog.functions.constant(fileName),
    -      getLineNumber: goog.functions.constant(lineNumber),
    -      getColumnNumber: goog.functions.constant(colNumber)
    -    };
    -  }
    -
    -  // Mock the goog.testing.stacktrace.getStack_ function, which normally
    -  // triggers an exception for the purpose of reading and returning its stack
    -  // trace. Here, pretend that V8 provided an array of CallSites instead of the
    -  // string that browsers provide.
    -  stubs.set(goog.testing.stacktrace, 'getNativeStack_', function() {
    -    return [
    -      createCallSite('fn1', 'file1', 1, 2),
    -      createCallSite('fn2', 'file2', 3, 4),
    -      createCallSite('fn3', 'file3', 5, 6)
    -    ];
    -  });
    -
    -  // Retrieve the stacktrace. This should translate the array of CallSites into
    -  // a single multi-line string.
    -  var stackTrace = goog.testing.stacktrace.get();
    -
    -  // Make sure the stack trace was translated correctly.
    -  var frames = stackTrace.split('\n');
    -  assertEquals(frames[0], '> fn1 at file1:1:2');
    -  assertEquals(frames[1], '> fn2 at file2:3:4');
    -  assertEquals(frames[2], '> fn3 at file3:5:6');
    -}
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/storage/fakemechanism.js b/src/database/third_party/closure-library/closure/goog/testing/storage/fakemechanism.js
    deleted file mode 100644
    index 10947571670..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/storage/fakemechanism.js
    +++ /dev/null
    @@ -1,68 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides a fake storage mechanism for testing.
    - * @author chrishenry@google.com (Chris Henry)
    - */
    -
    -goog.provide('goog.testing.storage.FakeMechanism');
    -goog.setTestOnly('goog.testing.storage.FakeMechanism');
    -
    -goog.require('goog.storage.mechanism.IterableMechanism');
    -goog.require('goog.structs.Map');
    -
    -
    -
    -/**
    - * Creates a fake iterable mechanism.
    - *
    - * @constructor
    - * @extends {goog.storage.mechanism.IterableMechanism}
    - * @final
    - */
    -goog.testing.storage.FakeMechanism = function() {
    -  /**
    -   * @type {goog.structs.Map}
    -   * @private
    -   */
    -  this.storage_ = new goog.structs.Map();
    -};
    -goog.inherits(goog.testing.storage.FakeMechanism,
    -    goog.storage.mechanism.IterableMechanism);
    -
    -
    -/** @override */
    -goog.testing.storage.FakeMechanism.prototype.set = function(key, value) {
    -  this.storage_.set(key, value);
    -};
    -
    -
    -/** @override */
    -goog.testing.storage.FakeMechanism.prototype.get = function(key) {
    -  return /** @type {?string} */ (
    -      this.storage_.get(key, null /* default value */));
    -};
    -
    -
    -/** @override */
    -goog.testing.storage.FakeMechanism.prototype.remove = function(key) {
    -  this.storage_.remove(key);
    -};
    -
    -
    -/** @override */
    -goog.testing.storage.FakeMechanism.prototype.__iterator__ = function(opt_keys) {
    -  return this.storage_.__iterator__(opt_keys);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/strictmock.js b/src/database/third_party/closure-library/closure/goog/testing/strictmock.js
    deleted file mode 100644
    index c3303d69550..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/strictmock.js
    +++ /dev/null
    @@ -1,130 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview This file defines a strict mock implementation.
    - */
    -
    -goog.provide('goog.testing.StrictMock');
    -
    -goog.require('goog.array');
    -goog.require('goog.testing.Mock');
    -
    -
    -
    -/**
    - * This is a mock that verifies that methods are called in the order that they
    - * are specified during the recording phase. Since it verifies order, it
    - * follows 'fail fast' semantics. If it detects a deviation from the
    - * expectations, it will throw an exception and not wait for verify to be
    - * called.
    - * @param {Object|Function} objectToMock The object that should be mocked, or
    - *    the constructor of an object to mock.
    - * @param {boolean=} opt_mockStaticMethods An optional argument denoting that
    - *     a mock should be constructed from the static functions of a class.
    - * @param {boolean=} opt_createProxy An optional argument denoting that
    - *     a proxy for the target mock should be created.
    - * @constructor
    - * @extends {goog.testing.Mock}
    - * @final
    - */
    -goog.testing.StrictMock = function(objectToMock, opt_mockStaticMethods,
    -    opt_createProxy) {
    -  goog.testing.Mock.call(this, objectToMock, opt_mockStaticMethods,
    -      opt_createProxy);
    -
    -  /**
    -   * An array of MockExpectations.
    -   * @type {Array<goog.testing.MockExpectation>}
    -   * @private
    -   */
    -  this.$expectations_ = [];
    -};
    -goog.inherits(goog.testing.StrictMock, goog.testing.Mock);
    -
    -
    -/** @override */
    -goog.testing.StrictMock.prototype.$recordExpectation = function() {
    -  this.$expectations_.push(this.$pendingExpectation);
    -};
    -
    -
    -/** @override */
    -goog.testing.StrictMock.prototype.$recordCall = function(name, args) {
    -  if (this.$expectations_.length == 0) {
    -    this.$throwCallException(name, args);
    -  }
    -
    -  // If the current expectation has a different name, make sure it was called
    -  // enough and then discard it. We're through with it.
    -  var currentExpectation = this.$expectations_[0];
    -  while (!this.$verifyCall(currentExpectation, name, args)) {
    -
    -    // This might be an item which has passed its min, and we can now
    -    // look past it, or it might be below its min and generate an error.
    -    if (currentExpectation.actualCalls < currentExpectation.minCalls) {
    -      this.$throwCallException(name, args, currentExpectation);
    -    }
    -
    -    this.$expectations_.shift();
    -    if (this.$expectations_.length < 1) {
    -      // Nothing left, but this may be a failed attempt to call the previous
    -      // item on the list, which may have been between its min and max.
    -      this.$throwCallException(name, args, currentExpectation);
    -    }
    -    currentExpectation = this.$expectations_[0];
    -  }
    -
    -  if (currentExpectation.maxCalls == 0) {
    -    this.$throwCallException(name, args);
    -  }
    -
    -  currentExpectation.actualCalls++;
    -  // If we hit the max number of calls for this expectation, we're finished
    -  // with it.
    -  if (currentExpectation.actualCalls == currentExpectation.maxCalls) {
    -    this.$expectations_.shift();
    -  }
    -
    -  return this.$do(currentExpectation, args);
    -};
    -
    -
    -/** @override */
    -goog.testing.StrictMock.prototype.$reset = function() {
    -  goog.testing.StrictMock.superClass_.$reset.call(this);
    -
    -  goog.array.clear(this.$expectations_);
    -};
    -
    -
    -/** @override */
    -goog.testing.StrictMock.prototype.$verify = function() {
    -  goog.testing.StrictMock.superClass_.$verify.call(this);
    -
    -  while (this.$expectations_.length > 0) {
    -    var expectation = this.$expectations_[0];
    -    if (expectation.actualCalls < expectation.minCalls) {
    -      this.$throwException('Missing a call to ' + expectation.name +
    -          '\nExpected: ' + expectation.minCalls + ' but was: ' +
    -          expectation.actualCalls);
    -
    -    } else {
    -      // Don't need to check max, that's handled when the call is made
    -      this.$expectations_.shift();
    -    }
    -  }
    -};
    -
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/strictmock_test.html b/src/database/third_party/closure-library/closure/goog/testing/strictmock_test.html
    deleted file mode 100644
    index 161f80c1e8c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/strictmock_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.testing.StrictMock
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.StrictMockTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/strictmock_test.js b/src/database/third_party/closure-library/closure/goog/testing/strictmock_test.js
    deleted file mode 100644
    index 26efd8cf0f2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/strictmock_test.js
    +++ /dev/null
    @@ -1,423 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.StrictMockTest');
    -goog.setTestOnly('goog.testing.StrictMockTest');
    -
    -goog.require('goog.testing.StrictMock');
    -goog.require('goog.testing.jsunit');
    -
    -// The object that we will be mocking
    -var RealObject = function() {
    -};
    -
    -RealObject.prototype.a = function() {
    -  fail('real object should never be called');
    -};
    -
    -RealObject.prototype.b = function() {
    -  fail('real object should never be called');
    -};
    -
    -RealObject.prototype.c = function() {
    -  fail('real object should never be called');
    -};
    -
    -var mock;
    -
    -function setUp() {
    -  var obj = new RealObject();
    -  mock = new goog.testing.StrictMock(obj);
    -}
    -
    -
    -function testMockFunction() {
    -  var mock = new goog.testing.StrictMock(RealObject);
    -  mock.a();
    -  mock.b();
    -  mock.c();
    -  mock.$replay();
    -  mock.a();
    -  mock.b();
    -  mock.c();
    -  mock.$verify();
    -
    -  mock.$reset();
    -
    -  assertThrows(function() {mock.x()});
    -}
    -
    -
    -function testSimpleExpectations() {
    -  mock.a();
    -  mock.$replay();
    -  mock.a();
    -  mock.$verify();
    -
    -  mock.$reset();
    -
    -  mock.a();
    -  mock.b();
    -  mock.a();
    -  mock.a();
    -  mock.$replay();
    -  mock.a();
    -  mock.b();
    -  mock.a();
    -  mock.a();
    -  mock.$verify();
    -}
    -
    -
    -function testFailToSetExpectation() {
    -  mock.$replay();
    -  assertThrows(goog.bind(mock.a, mock));
    -
    -  mock.$reset();
    -
    -  mock.$replay();
    -  assertThrows(goog.bind(mock.b, mock));
    -}
    -
    -
    -function testUnexpectedCall() {
    -  mock.a();
    -  mock.$replay();
    -  mock.a();
    -  assertThrows(goog.bind(mock.a, mock));
    -
    -  mock.$reset();
    -
    -  mock.a();
    -  mock.$replay();
    -  assertThrows(goog.bind(mock.b, mock));
    -}
    -
    -
    -function testNotEnoughCalls() {
    -  mock.a();
    -  mock.$replay();
    -  assertThrows(goog.bind(mock.$verify, mock));
    -
    -  mock.$reset();
    -
    -  mock.a();
    -  mock.b();
    -  mock.$replay();
    -  mock.a();
    -  assertThrows(goog.bind(mock.$verify, mock));
    -}
    -
    -
    -function testOutOfOrderCalls() {
    -  mock.a();
    -  mock.b();
    -  mock.$replay();
    -  assertThrows(goog.bind(mock.b, mock));
    -}
    -
    -
    -function testVerify() {
    -  mock.a();
    -  mock.$replay();
    -  mock.a();
    -  mock.$verify();
    -
    -  mock.$reset();
    -
    -  mock.a();
    -  mock.$replay();
    -  assertThrows(goog.bind(mock.$verify, mock));
    -}
    -
    -
    -function testArgumentMatching() {
    -  mock.a('foo');
    -  mock.b('bar');
    -  mock.$replay();
    -  mock.a('foo');
    -  assertThrows(function() {mock.b('foo')});
    -
    -  mock.$reset();
    -  mock.a('foo');
    -  mock.a('bar');
    -  mock.$replay();
    -  mock.a('foo');
    -  mock.a('bar');
    -  mock.$verify();
    -
    -  mock.$reset();
    -  mock.a('foo');
    -  mock.a('bar');
    -  mock.$replay();
    -  assertThrows(function() {mock.a('bar')});
    -}
    -
    -
    -function testReturnValue() {
    -  mock.a().$returns(5);
    -  mock.$replay();
    -
    -  assertEquals('Mock should return the right value', 5, mock.a());
    -
    -  mock.$verify();
    -}
    -
    -function testMultipleReturnValues() {
    -  mock.a().$returns(3);
    -  mock.a().$returns(2);
    -  mock.a().$returns(1);
    -
    -  mock.$replay();
    -
    -  assertArrayEquals('Mock should return the right value sequence',
    -      [3, 2, 1],
    -      [mock.a(), mock.a(), mock.a()]);
    -
    -  mock.$verify();
    -}
    -
    -
    -function testAtMostOnce() {
    -  // Zero times SUCCESS.
    -  mock.a().$atMostOnce();
    -  mock.$replay();
    -  mock.$verify();
    -
    -  mock.$reset();
    -
    -  // One time SUCCESS.
    -  mock.a().$atMostOnce();
    -  mock.$replay();
    -  mock.a();
    -  mock.$verify();
    -
    -  mock.$reset();
    -
    -  // Many times FAIL.
    -  mock.a().$atMostOnce();
    -  mock.$replay();
    -  mock.a();
    -  assertThrows(goog.bind(mock.a, mock));
    -
    -  mock.$reset();
    -
    -  // atMostOnce only lasts until a new method is called.
    -  mock.a().$atMostOnce();
    -  mock.b();
    -  mock.a();
    -  mock.$replay();
    -  mock.b();
    -  assertThrows(goog.bind(mock.$verify, mock));
    -}
    -
    -
    -function testAtLeastOnce() {
    -  // atLeastOnce does not mean zero times
    -  mock.a().$atLeastOnce();
    -  mock.$replay();
    -  assertThrows(goog.bind(mock.$verify, mock));
    -
    -  mock.$reset();
    -
    -  // atLeastOnce does mean three times
    -  mock.a().$atLeastOnce();
    -  mock.$replay();
    -  mock.a();
    -  mock.a();
    -  mock.a();
    -  mock.$verify();
    -
    -  mock.$reset();
    -
    -  // atLeastOnce only lasts until a new method is called
    -  mock.a().$atLeastOnce();
    -  mock.b();
    -  mock.a();
    -  mock.$replay();
    -  mock.a();
    -  mock.a();
    -  mock.b();
    -  mock.a();
    -  assertThrows(goog.bind(mock.a, mock));
    -}
    -
    -
    -function testAtLeastOnceWithArgs() {
    -  mock.a('asdf').$atLeastOnce();
    -  mock.a('qwert');
    -  mock.$replay();
    -  mock.a('asdf');
    -  mock.a('asdf');
    -  mock.a('qwert');
    -  mock.$verify();
    -
    -  mock.$reset();
    -
    -  mock.a('asdf').$atLeastOnce();
    -  mock.a('qwert');
    -  mock.$replay();
    -  mock.a('asdf');
    -  mock.a('asdf');
    -  assertThrows(function() {mock.a('zxcv')});
    -  assertThrows(goog.bind(mock.$verify, mock));
    -}
    -
    -
    -function testAnyTimes() {
    -  mock.a().$anyTimes();
    -  mock.$replay();
    -  mock.$verify();
    -
    -  mock.$reset();
    -
    -  mock.a().$anyTimes();
    -  mock.$replay();
    -  mock.a();
    -  mock.a();
    -  mock.a();
    -  mock.a();
    -  mock.a();
    -  mock.$verify();
    -}
    -
    -
    -function testAnyTimesWithArguments() {
    -  mock.a('foo').$anyTimes();
    -  mock.$replay();
    -  mock.$verify();
    -
    -  mock.$reset();
    -
    -  mock.a('foo').$anyTimes();
    -  mock.a('bar').$anyTimes();
    -  mock.$replay();
    -  mock.a('foo');
    -  mock.a('foo');
    -  mock.a('foo');
    -  mock.a('bar');
    -  mock.a('bar');
    -  mock.$verify();
    -}
    -
    -
    -function testZeroTimes() {
    -  mock.a().$times(0);
    -  mock.$replay();
    -  mock.$verify();
    -
    -  mock.$reset();
    -
    -  mock.a().$times(0);
    -  mock.$replay();
    -  assertThrows(function() {mock.a()});
    -}
    -
    -
    -function testZeroTimesWithArguments() {
    -  mock.a('foo').$times(0);
    -  mock.$replay();
    -  mock.$verify();
    -
    -  mock.$reset();
    -
    -  mock.a('foo').$times(0);
    -  mock.$replay();
    -  assertThrows(function() {mock.a('foo')});
    -}
    -
    -
    -function testTooManyCalls() {
    -  mock.a().$times(2);
    -  mock.$replay();
    -  mock.a();
    -  mock.a();
    -  assertThrows(function() {mock.a()});
    -}
    -
    -
    -function testTooManyCallsWithArguments() {
    -  mock.a('foo').$times(2);
    -  mock.$replay();
    -  mock.a('foo');
    -  mock.a('foo');
    -  assertThrows(function() {mock.a('foo')});
    -}
    -
    -
    -function testMultipleSkippedAnyTimes() {
    -  mock.a().$anyTimes();
    -  mock.b().$anyTimes();
    -  mock.c().$anyTimes();
    -  mock.$replay();
    -  mock.c();
    -  mock.$verify();
    -}
    -
    -
    -function testMultipleSkippedAnyTimesWithArguments() {
    -  mock.a('foo').$anyTimes();
    -  mock.a('bar').$anyTimes();
    -  mock.a('baz').$anyTimes();
    -  mock.$replay();
    -  mock.a('baz');
    -  mock.$verify();
    -}
    -
    -
    -function testVerifyThrows() {
    -  mock.a(1);
    -  mock.$replay();
    -  mock.a(1);
    -  try {
    -    mock.a(2);
    -    fail('bad mock, should fail');
    -  } catch (ex) {
    -    // this could be an event handler, for example
    -  }
    -  assertThrows(goog.bind(mock.$verify, mock));
    -}
    -
    -
    -function testThrows() {
    -  mock.a().$throws('exception!');
    -  mock.$replay();
    -  assertThrows(goog.bind(mock.a, mock));
    -  mock.$verify();
    -}
    -
    -
    -function testDoes() {
    -  mock.a(1, 2).$does(function(a, b) {return a + b;});
    -  mock.$replay();
    -  assertEquals('Mock should call the function', 3, mock.a(1, 2));
    -  mock.$verify();
    -}
    -
    -function testErrorMessageForBadArgs() {
    -  mock.a();
    -  mock.$anyTimes();
    -
    -  mock.$replay();
    -
    -  var message;
    -  try {
    -    mock.a('a');
    -  } catch (e) {
    -    message = e.message;
    -  }
    -
    -  assertTrue('No exception thrown on verify', goog.isDef(message));
    -  assertContains('Bad arguments to a()', message);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/style/layoutasserts.js b/src/database/third_party/closure-library/closure/goog/testing/style/layoutasserts.js
    deleted file mode 100644
    index 2f9cb34dd07..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/style/layoutasserts.js
    +++ /dev/null
    @@ -1,310 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A utility class for making layout assertions. This is a port
    - * of http://go/layoutbot.java
    - * See {@link http://go/layouttesting}.
    - */
    -
    -goog.provide('goog.testing.style.layoutasserts');
    -
    -goog.require('goog.style');
    -goog.require('goog.testing.asserts');
    -goog.require('goog.testing.style');
    -
    -
    -/**
    - * Asserts that an element has:
    - *   1 - a CSS rendering the makes the element visible.
    - *   2 - a non-zero width and height.
    - * @param {Element|string} a The element or optionally the comment string.
    - * @param {Element=} opt_b The element when a comment string is present.
    - */
    -var assertIsVisible = function(a, opt_b) {
    -  _validateArguments(1, arguments);
    -  var element = nonCommentArg(1, 1, arguments);
    -
    -  _assert(commentArg(1, arguments),
    -      goog.testing.style.isVisible(element) &&
    -      goog.testing.style.hasVisibleDimensions(element),
    -      'Specified element should be visible.');
    -};
    -
    -
    -/**
    - * The counter assertion of assertIsVisible().
    - * @param {Element|string} a The element or optionally the comment string.
    - * @param {Element=} opt_b The element when a comment string is present.
    - */
    -var assertNotVisible = function(a, opt_b) {
    -  _validateArguments(1, arguments);
    -  var element = nonCommentArg(1, 1, arguments);
    -  if (!element) {
    -    return;
    -  }
    -
    -  _assert(commentArg(1, arguments),
    -      !goog.testing.style.isVisible(element) ||
    -      !goog.testing.style.hasVisibleDimensions(element),
    -      'Specified element should not be visible.');
    -};
    -
    -
    -/**
    - * Asserts that the two specified elements intersect.
    - * @param {Element|string} a The first element or optionally the comment string.
    - * @param {Element} b The second element or the first element if comment string
    - *     is present.
    - * @param {Element=} opt_c The second element if comment string is present.
    - */
    -var assertIntersect = function(a, b, opt_c) {
    -  _validateArguments(2, arguments);
    -  var element = nonCommentArg(1, 2, arguments);
    -  var otherElement = nonCommentArg(2, 2, arguments);
    -
    -  _assert(commentArg(1, arguments),
    -      goog.testing.style.intersects(element, otherElement),
    -      'Elements should intersect.');
    -};
    -
    -
    -/**
    - * Asserts that the two specified elements do not intersect.
    - * @param {Element|string} a The first element or optionally the comment string.
    - * @param {Element} b The second element or the first element if comment string
    - *     is present.
    - * @param {Element=} opt_c The second element if comment string is present.
    - */
    -var assertNoIntersect = function(a, b, opt_c) {
    -  _validateArguments(2, arguments);
    -  var element = nonCommentArg(1, 2, arguments);
    -  var otherElement = nonCommentArg(2, 2, arguments);
    -
    -  _assert(commentArg(1, arguments),
    -      !goog.testing.style.intersects(element, otherElement),
    -      'Elements should not intersect.');
    -};
    -
    -
    -/**
    - * Asserts that the element must have the specified width.
    - * @param {Element|string} a The first element or optionally the comment string.
    - * @param {Element} b The second element or the first element if comment string
    - *     is present.
    - * @param {Element=} opt_c The second element if comment string is present.
    - */
    -var assertWidth = function(a, b, opt_c) {
    -  _validateArguments(2, arguments);
    -  var element = nonCommentArg(1, 2, arguments);
    -  var width = nonCommentArg(2, 2, arguments);
    -  var size = goog.style.getSize(element);
    -  var elementWidth = size.width;
    -
    -  _assert(commentArg(1, arguments),
    -      goog.testing.style.layoutasserts.isWithinThreshold_(
    -          width, elementWidth, 0 /* tolerance */),
    -      'Element should have width ' + width + ' but was ' + elementWidth + '.');
    -};
    -
    -
    -/**
    - * Asserts that the element must have the specified width within the specified
    - * tolerance.
    - * @param {Element|string} a The element or optionally the comment string.
    - * @param {number|Element} b The height or the element if comment string is
    - *     present.
    - * @param {number} c The tolerance or the height if comment string is
    - *     present.
    - * @param {number=} opt_d The tolerance if comment string is present.
    - */
    -var assertWidthWithinTolerance = function(a, b, c, opt_d) {
    -  _validateArguments(3, arguments);
    -  var element = nonCommentArg(1, 3, arguments);
    -  var width = nonCommentArg(2, 3, arguments);
    -  var tolerance = nonCommentArg(3, 3, arguments);
    -  var size = goog.style.getSize(element);
    -  var elementWidth = size.width;
    -
    -  _assert(commentArg(1, arguments),
    -      goog.testing.style.layoutasserts.isWithinThreshold_(
    -          width, elementWidth, tolerance),
    -      'Element width(' + elementWidth + ') should be within given width(' +
    -      width + ') with tolerance value of ' + tolerance + '.');
    -};
    -
    -
    -/**
    - * Asserts that the element must have the specified height.
    - * @param {Element|string} a The first element or optionally the comment string.
    - * @param {Element} b The second element or the first element if comment string
    - *     is present.
    - * @param {Element=} opt_c The second element if comment string is present.
    - */
    -var assertHeight = function(a, b, opt_c) {
    -  _validateArguments(2, arguments);
    -  var element = nonCommentArg(1, 2, arguments);
    -  var height = nonCommentArg(2, 2, arguments);
    -  var size = goog.style.getSize(element);
    -  var elementHeight = size.height;
    -
    -  _assert(commentArg(1, arguments),
    -      goog.testing.style.layoutasserts.isWithinThreshold_(
    -          height, elementHeight, 0 /* tolerance */),
    -      'Element should have height ' + height + '.');
    -};
    -
    -
    -/**
    - * Asserts that the element must have the specified height within the specified
    - * tolerance.
    - * @param {Element|string} a The element or optionally the comment string.
    - * @param {number|Element} b The height or the element if comment string is
    - *     present.
    - * @param {number} c The tolerance or the height if comment string is
    - *     present.
    - * @param {number=} opt_d The tolerance if comment string is present.
    - */
    -var assertHeightWithinTolerance = function(a, b, c, opt_d) {
    -  _validateArguments(3, arguments);
    -  var element = nonCommentArg(1, 3, arguments);
    -  var height = nonCommentArg(2, 3, arguments);
    -  var tolerance = nonCommentArg(3, 3, arguments);
    -  var size = goog.style.getSize(element);
    -  var elementHeight = size.height;
    -
    -  _assert(commentArg(1, arguments),
    -      goog.testing.style.layoutasserts.isWithinThreshold_(
    -          height, elementHeight, tolerance),
    -      'Element width(' + elementHeight + ') should be within given width(' +
    -      height + ') with tolerance value of ' + tolerance + '.');
    -};
    -
    -
    -/**
    - * Asserts that the first element is to the left of the second element.
    - * @param {Element|string} a The first element or optionally the comment string.
    - * @param {Element} b The second element or the first element if comment string
    - *     is present.
    - * @param {Element=} opt_c The second element if comment string is present.
    - */
    -var assertIsLeftOf = function(a, b, opt_c) {
    -  _validateArguments(2, arguments);
    -  var element = nonCommentArg(1, 2, arguments);
    -  var otherElement = nonCommentArg(2, 2, arguments);
    -  var elementRect = goog.style.getBounds(element);
    -  var otherElementRect = goog.style.getBounds(otherElement);
    -
    -  _assert(commentArg(1, arguments),
    -      elementRect.left < otherElementRect.left,
    -      'Elements should be left to right.');
    -};
    -
    -
    -/**
    - * Asserts that the first element is strictly left of the second element.
    - * @param {Element|string} a The first element or optionally the comment string.
    - * @param {Element} b The second element or the first element if comment string
    - *     is present.
    - * @param {Element=} opt_c The second element if comment string is present.
    - */
    -var assertIsStrictlyLeftOf = function(a, b, opt_c) {
    -  _validateArguments(2, arguments);
    -  var element = nonCommentArg(1, 2, arguments);
    -  var otherElement = nonCommentArg(2, 2, arguments);
    -  var elementRect = goog.style.getBounds(element);
    -  var otherElementRect = goog.style.getBounds(otherElement);
    -
    -  _assert(commentArg(1, arguments),
    -      elementRect.left + elementRect.width < otherElementRect.left,
    -      'Elements should be strictly left to right.');
    -};
    -
    -
    -/**
    - * Asserts that the first element is higher than the second element.
    - * @param {Element|string} a The first element or optionally the comment string.
    - * @param {Element} b The second element or the first element if comment string
    - *     is present.
    - * @param {Element=} opt_c The second element if comment string is present.
    - */
    -var assertIsAbove = function(a, b, opt_c) {
    -  _validateArguments(2, arguments);
    -  var element = nonCommentArg(1, 2, arguments);
    -  var otherElement = nonCommentArg(2, 2, arguments);
    -  var elementRect = goog.style.getBounds(element);
    -  var otherElementRect = goog.style.getBounds(otherElement);
    -
    -  _assert(commentArg(1, arguments),
    -      elementRect.top < otherElementRect.top,
    -      'Elements should be top to bottom.');
    -};
    -
    -
    -/**
    - * Asserts that the first element is strictly higher than the second element.
    - * @param {Element|string} a The first element or optionally the comment string.
    - * @param {Element} b The second element or the first element if comment string
    - *     is present.
    - * @param {Element=} opt_c The second element if comment string is present.
    - */
    -var assertIsStrictlyAbove = function(a, b, opt_c) {
    -  _validateArguments(2, arguments);
    -  var element = nonCommentArg(1, 2, arguments);
    -  var otherElement = nonCommentArg(2, 2, arguments);
    -  var elementRect = goog.style.getBounds(element);
    -  var otherElementRect = goog.style.getBounds(otherElement);
    -
    -  _assert(commentArg(1, arguments),
    -      elementRect.top + elementRect.height < otherElementRect.top,
    -      'Elements should be strictly top to bottom.');
    -};
    -
    -
    -/**
    - * Asserts that the first element's bounds contain the bounds of the second
    - * element.
    - * @param {Element|string} a The first element or optionally the comment string.
    - * @param {Element} b The second element or the first element if comment string
    - *     is present.
    - * @param {Element=} opt_c The second element if comment string is present.
    - */
    -var assertContained = function(a, b, opt_c) {
    -  _validateArguments(2, arguments);
    -  var element = nonCommentArg(1, 2, arguments);
    -  var otherElement = nonCommentArg(2, 2, arguments);
    -  var elementRect = goog.style.getBounds(element);
    -  var otherElementRect = goog.style.getBounds(otherElement);
    -
    -  _assert(commentArg(1, arguments),
    -      elementRect.contains(otherElementRect),
    -      'Element should be contained within the other element.');
    -};
    -
    -
    -/**
    - * Returns true if the difference between val1 and val2 is less than or equal to
    - * the threashold.
    - * @param {number} val1 The first value.
    - * @param {number} val2 The second value.
    - * @param {number} threshold The threshold value.
    - * @return {boolean} Whether or not the the values are within the threshold.
    - * @private
    - */
    -goog.testing.style.layoutasserts.isWithinThreshold_ = function(
    -    val1, val2, threshold) {
    -  return Math.abs(val1 - val2) <= threshold;
    -};
    -
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/style/layoutasserts_test.html b/src/database/third_party/closure-library/closure/goog/testing/style/layoutasserts_test.html
    deleted file mode 100644
    index ff5a8341e33..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/style/layoutasserts_test.html
    +++ /dev/null
    @@ -1,29 +0,0 @@
    -<!DOCTYPE html>
    -<!--
    -  All Rights Reserved.
    --->
    -<html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   goog.testing.style.layoutasserts Tests
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.style.layoutassertsTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="element1">
    -  </div>
    -  <div id="element2">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/style/layoutasserts_test.js b/src/database/third_party/closure-library/closure/goog/testing/style/layoutasserts_test.js
    deleted file mode 100644
    index 90529b4279c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/style/layoutasserts_test.js
    +++ /dev/null
    @@ -1,257 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.style.layoutassertsTest');
    -goog.setTestOnly('goog.testing.style.layoutassertsTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.style');
    -goog.require('goog.testing.jsunit');
    -/** @suppress {extraRequire} */
    -goog.require('goog.testing.style.layoutasserts');
    -
    -var div1;
    -var div2;
    -var DEFAULT_WIDTH = 200;
    -var DEFAULT_HEIGHT = 100;
    -
    -function setUp() {
    -  div1 = goog.dom.createDom(
    -      'div',
    -      {
    -        id: 'test',
    -        className: 'test',
    -        style: 'position:absolute;top:0;left:0;' +
    -            'width:' + DEFAULT_WIDTH + 'px;' +
    -            'height:' + DEFAULT_HEIGHT + 'px;' +
    -                'background-color:#EEE',
    -        innerHTML: 'abc'
    -      });
    -  div2 = goog.dom.createDom('div',
    -      {
    -        id: 'test2',
    -        className: 'test2',
    -        style: 'position:absolute;' +
    -            'top:0;left:0;' +
    -            'width:' + DEFAULT_WIDTH + 'px;' +
    -            'height:' + DEFAULT_HEIGHT + 'px;' +
    -            'background-color:#F00',
    -        innerHTML: 'abc'
    -      });
    -
    -}
    -
    -
    -function tearDown() {
    -  div1 = null;
    -  div2 = null;
    -}
    -
    -
    -/**
    - * Tests assertIsVisible.
    - */
    -function testAssertIsVisible() {
    -  assertThrows('Exception should be thrown when asserting visibility.',
    -      goog.bind(assertIsVisible, null, null)); // assertIsVisible(null)
    -
    -  // Attach it to BODY tag and assert that it is visible.
    -  document.body.appendChild(div1);
    -  assertIsVisible('Div should be visible.', div1);
    -
    -  // Tests with hidden element
    -  failed = false;
    -  goog.style.setElementShown(div1, false /* display */);
    -  assertThrows('Exception should be thrown when asserting visibility.',
    -      goog.bind(assertIsVisible, null, div1));
    -
    -  // Clean up.
    -  document.body.removeChild(div1);
    -}
    -
    -
    -/**
    - * Tests assertNotVisible.
    - */
    -function testAssertNotVisible() {
    -  // Tests null as a parameter.
    -  var element = null;
    -  assertNotVisible(element);
    -
    -  // Attach the element to BODY element, assert should fail.
    -  document.body.appendChild(div1);
    -  assertThrows('Exception should be thrown when asserting non-visibility.',
    -      goog.bind(assertNotVisible, null, div1));
    -
    -  // Clean up.
    -  document.body.removeChild(div1);
    -}
    -
    -
    -/**
    - * Tests assertIsIntersect.
    - */
    -function testAssertIntersect() {
    -  document.body.appendChild(div1);
    -  document.body.appendChild(div2);
    -
    -  // No intersection
    -  goog.style.setPosition(div1, 0, 0);
    -  goog.style.setPosition(div2, 500, 500);
    -  assertThrows('Exception should be thrown when asserting intersection.',
    -      goog.bind(assertIntersect, null, div1, div2));
    -  assertNoIntersect(div1, div2);
    -
    -  // Some intersection
    -  goog.style.setPosition(div1, 0, 0);
    -  goog.style.setPosition(div2, 50, 50);
    -  assertThrows('Exception should be thrown when asserting no intersection.',
    -      goog.bind(assertNoIntersect, null, div1, div2));
    -  assertIntersect(div1, div2);
    -
    -  // Completely superimposed.
    -  goog.style.setPosition(div1, 0, 0);
    -  goog.style.setPosition(div2, 0, 0);
    -  assertThrows('Exception should be thrown when asserting no intersection.',
    -      goog.bind(assertNoIntersect, null, div1, div2));
    -  assertIntersect(div1, div2);
    -}
    -
    -
    -/**
    - * Tests assertWidth.
    - */
    -function testAssertWidth() {
    -  document.body.appendChild(div1);
    -
    -  // Test correct width
    -  assertWidth(div1, DEFAULT_WIDTH);
    -
    -  // Test wrong width
    -  assertThrows('Exception should be thrown when elements has wrong width',
    -      goog.bind(assertWidth, null, div1, 400));
    -
    -  // Test a valid tolerance value
    -  assertWidthWithinTolerance(div1, 180, 20);
    -
    -  // Test exceeding tolerance value
    -  assertThrows(
    -      'Exception should be thrown when element\'s width exceeds tolerance',
    -      goog.bind(assertWidthWithinTolerance, null, div1, 100, 0.1));
    -}
    -
    -
    -/**
    - * Tests assertHeight.
    - */
    -function testAssertHeight() {
    -  document.body.appendChild(div1);
    -
    -  // Test correct height
    -  assertHeight(div1, DEFAULT_HEIGHT);
    -
    -  // Test wrong height
    -  assertThrows('Exception should be thrown when element has wrong height.',
    -      goog.bind(assertHeightWithinTolerance, null, div1, 300));
    -
    -  // Test a valid tolerance value
    -  assertHeightWithinTolerance(div1, 90, 10);
    -
    -  // Test exceeding tolerance value
    -  assertThrows(
    -      'Exception should be thrown when element\'s height exceeds tolerance',
    -      goog.bind(assertHeight, null, div1, 50, 0.2));
    -}
    -
    -
    -/**
    - * Tests assertIsLeftOf.
    - */
    -function testAssertIsLeftOf() {
    -  document.body.appendChild(div1);
    -  document.body.appendChild(div2);
    -
    -  // Test elements of same size & location
    -  assertThrows('Exception should be thrown when elements intersect.',
    -      goog.bind(assertIsLeftOf, null, div1, div2));
    -  assertThrows('Exception should be thrown when elements intersect.',
    -      goog.bind(
    -          assertIsStrictlyLeftOf, null, div1, div2));
    -
    -  // Test elements that are not left to right
    -  goog.style.setPosition(div1, 100, 0);
    -  goog.style.setPosition(div2, 0, 0);
    -  assertThrows(
    -      'Exception should be thrown when elements are not left to right.',
    -      goog.bind(assertIsLeftOf, null, div1, div2));
    -  assertThrows(
    -      'Exception should be thrown when elements are not left to right.',
    -      goog.bind(
    -          assertIsStrictlyLeftOf, null, div1, div2));
    -
    -  // Test elements that intersect, but is left to right
    -  goog.style.setPosition(div1, 0, 0);
    -  goog.style.setPosition(div2, 100, 0);
    -  assertIsLeftOf(div1, div2);
    -  assertThrows('Exception should be thrown when elements intersect.',
    -      goog.bind(
    -          assertIsStrictlyLeftOf, null, div1, div2));
    -
    -  // Test elements that are strictly left to right
    -  goog.style.setPosition(div1, 0, 0);
    -  goog.style.setPosition(div2, 999, 0);
    -  assertIsLeftOf(div1, div2);
    -  assertIsStrictlyLeftOf(div1, div2);
    -}
    -
    -
    -/**
    - * Tests assertIsAbove.
    - */
    -function testAssertIsAbove() {
    -  document.body.appendChild(div1);
    -  document.body.appendChild(div2);
    -
    -  // Test elements of same size & location
    -  assertThrows('Exception should be thrown when elements intersect.',
    -      goog.bind(assertIsAbove, null, div1, div2));
    -  assertThrows('Exception should be thrown when elements intersect.',
    -      goog.bind(
    -      assertIsStrictlyAbove, null, div1, div2));
    -
    -  // Test elements that are not top to bottom
    -  goog.style.setPosition(div1, 0, 999);
    -  goog.style.setPosition(div2, 0, 0);
    -  assertThrows(
    -      'Exception should be thrown when elements are not top to bottom.',
    -      goog.bind(assertIsAbove, null, div1, div2));
    -  assertThrows(
    -      'Exception should be thrown when elements are not top to bottom.',
    -      goog.bind(
    -      assertIsStrictlyAbove, null, div1, div2));
    -
    -  // Test elements that intersect, but is top to bottom
    -  goog.style.setPosition(div1, 0, 0);
    -  goog.style.setPosition(div2, 0, 50);
    -  assertIsAbove(div1, div2);
    -  assertThrows('Exception should be thrown when elements intersect.',
    -      goog.bind(
    -      assertIsStrictlyAbove, null, div1, div2));
    -
    -  // Test elements that are top to bottom
    -  goog.style.setPosition(div1, 0, 0);
    -  goog.style.setPosition(div2, 0, 999);
    -  assertIsAbove(div1, div2);
    -  assertIsStrictlyAbove(div1, div2);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/style/style.js b/src/database/third_party/closure-library/closure/goog/testing/style/style.js
    deleted file mode 100644
    index e180cf4af99..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/style/style.js
    +++ /dev/null
    @@ -1,101 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Utilities for inspecting page layout. This is a port of
    - *     http://go/layoutbot.java
    - *     See {@link http://go/layouttesting}.
    - */
    -
    -goog.provide('goog.testing.style');
    -
    -goog.require('goog.dom');
    -goog.require('goog.math.Rect');
    -goog.require('goog.style');
    -
    -
    -/**
    - * Determines whether the bounding rectangles of the given elements intersect.
    - * @param {Element} element The first element.
    - * @param {Element} otherElement The second element.
    - * @return {boolean} Whether the bounding rectangles of the given elements
    - *     intersect.
    - */
    -goog.testing.style.intersects = function(element, otherElement) {
    -  var elementRect = goog.style.getBounds(element);
    -  var otherElementRect = goog.style.getBounds(otherElement);
    -  return goog.math.Rect.intersects(elementRect, otherElementRect);
    -};
    -
    -
    -/**
    - * Determines whether the element has visible dimensions, i.e. x > 0 && y > 0.
    - * @param {Element} element The element to check.
    - * @return {boolean} Whether the element has visible dimensions.
    - */
    -goog.testing.style.hasVisibleDimensions = function(element) {
    -  var elSize = goog.style.getSize(element);
    -  var shortest = elSize.getShortest();
    -  if (shortest <= 0) {
    -    return false;
    -  }
    -
    -  return true;
    -};
    -
    -
    -/**
    - * Determines whether the CSS style of the element renders it visible.
    - * @param {!Element} element The element to check.
    - * @return {boolean} Whether the CSS style of the element renders it visible.
    - */
    -goog.testing.style.isVisible = function(element) {
    -  var visibilityStyle =
    -      goog.testing.style.getAvailableStyle_(element, 'visibility');
    -  var displayStyle =
    -      goog.testing.style.getAvailableStyle_(element, 'display');
    -
    -  return (visibilityStyle != 'hidden' && displayStyle != 'none');
    -};
    -
    -
    -/**
    - * Test whether the given element is on screen.
    - * @param {!Element} el The element to test.
    - * @return {boolean} Whether the element is on the screen.
    - */
    -goog.testing.style.isOnScreen = function(el) {
    -  var doc = goog.dom.getDomHelper(el).getDocument();
    -  var viewport = goog.style.getVisibleRectForElement(doc.body);
    -  var viewportRect = goog.math.Rect.createFromBox(viewport);
    -  return goog.dom.contains(doc, el) &&
    -      goog.style.getBounds(el).intersects(viewportRect);
    -};
    -
    -
    -/**
    - * This is essentially goog.style.getStyle_. goog.style.getStyle_ is private
    - * and is not a recommended way for general purpose style extractor. For the
    - * purposes of layout testing, we only use this function for retrieving
    - * 'visiblity' and 'display' style.
    - * @param {!Element} element The element to retrieve the style from.
    - * @param {string} style Style property name.
    - * @return {string} Style value.
    - * @private
    - */
    -goog.testing.style.getAvailableStyle_ = function(element, style) {
    -  return goog.style.getComputedStyle(element, style) ||
    -      goog.style.getCascadedStyle(element, style) ||
    -      goog.style.getStyle(element, style);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/style/style_test.html b/src/database/third_party/closure-library/closure/goog/testing/style/style_test.html
    deleted file mode 100644
    index dad03e1b4de..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/style/style_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   goog.testing.style Tests
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.styleTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/style/style_test.js b/src/database/third_party/closure-library/closure/goog/testing/style/style_test.js
    deleted file mode 100644
    index adb665ee18f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/style/style_test.js
    +++ /dev/null
    @@ -1,157 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.styleTest');
    -goog.setTestOnly('goog.testing.styleTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.style');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.style');
    -
    -var div1;
    -var div2;
    -
    -function setUp() {
    -  var createDiv = function(color) {
    -    var div = goog.dom.createDom(
    -        'div',
    -        {
    -          style: 'position:absolute;top:0;left:0;' +
    -              'width:200px;height:100px;' +
    -              'background-color:' + color,
    -          innerHTML: 'abc'
    -        });
    -    document.body.appendChild(div);
    -    return div;
    -  };
    -
    -  div1 = createDiv('#EEE');
    -  div2 = createDiv('#F00');
    -}
    -
    -
    -function tearDown() {
    -  if (div1.parentNode)
    -    div1.parentNode.removeChild(div1);
    -  if (div2.parentNode)
    -    div2.parentNode.removeChild(div2);
    -
    -  div1 = null;
    -  div2 = null;
    -}
    -
    -
    -function testIsVisible() {
    -  assertTrue('The div should be detected as visible.',
    -             goog.testing.style.isVisible(div1));
    -
    -  // Tests with hidden element
    -  goog.style.setElementShown(div1, false /* display */);
    -  assertFalse('The div should be detected as not visible.',
    -              goog.testing.style.isVisible(div1));
    -}
    -
    -function testIsOnScreen() {
    -  var el = document.createElement('div');
    -  document.body.appendChild(el);
    -
    -  var dom = goog.dom.getDomHelper(el);
    -  var winScroll = dom.getDocumentScroll();
    -  var winSize = dom.getViewportSize();
    -
    -  el.style.position = 'absolute';
    -  goog.style.setSize(el, 100, 100);
    -
    -  goog.style.setPosition(el, winScroll.x, winScroll.y);
    -  assertTrue('An element fully on the screen is on screen.',
    -      goog.testing.style.isOnScreen(el));
    -
    -  goog.style.setPosition(el, winScroll.x - 10, winScroll.y - 10);
    -  assertTrue(
    -      'An element partially off the top-left of the screen is on screen.',
    -      goog.testing.style.isOnScreen(el));
    -
    -  goog.style.setPosition(el, winScroll.x - 150, winScroll.y - 10);
    -  assertFalse(
    -      'An element completely off the top of the screen is off screen.',
    -      goog.testing.style.isOnScreen(el));
    -
    -  goog.style.setPosition(el, winScroll.x - 10, winScroll.y - 150);
    -  assertFalse(
    -      'An element completely off the left of the screen is off screen.',
    -      goog.testing.style.isOnScreen(el));
    -
    -  goog.style.setPosition(el, winScroll.x + winSize.width + 1, winScroll.y);
    -  assertFalse(
    -      'An element completely off the right of the screen is off screen.',
    -      goog.testing.style.isOnScreen(el));
    -
    -  goog.style.setPosition(el, winScroll.x, winScroll.y + winSize.height + 1);
    -  assertFalse(
    -      'An element completely off the bottom of the screen is off screen.',
    -      goog.testing.style.isOnScreen(el));
    -
    -  goog.style.setPosition(el, winScroll.x + winSize.width - 10, winScroll.y);
    -  assertTrue(
    -      'An element partially off the right of the screen is on screen.',
    -      goog.testing.style.isOnScreen(el));
    -
    -  goog.style.setPosition(el, winScroll.x, winScroll.y + winSize.height - 10);
    -  assertTrue(
    -      'An element partially off the bottom of the screen is on screen.',
    -      goog.testing.style.isOnScreen(el));
    -
    -  var el2 = document.createElement('div');
    -  el2.style.position = 'absolute';
    -  goog.style.setSize(el2, 100, 100);
    -  goog.style.setPosition(el2, winScroll.x, winScroll.y);
    -  assertFalse('An element not in the DOM is not on screen.',
    -              goog.testing.style.isOnScreen(el2));
    -}
    -
    -function testHasVisibleDimensions() {
    -  goog.style.setSize(div1, 0, 0);
    -  assertFalse('0x0 should not be considered visible dimensions.',
    -              goog.testing.style.hasVisibleDimensions(div1));
    -  goog.style.setSize(div1, 10, 0);
    -  assertFalse('10x0 should not be considered visible dimensions.',
    -              goog.testing.style.hasVisibleDimensions(div1));
    -  goog.style.setSize(div1, 10, 10);
    -  assertTrue('10x10 should be considered visible dimensions.',
    -             goog.testing.style.hasVisibleDimensions(div1));
    -  goog.style.setSize(div1, 0, 10);
    -  assertFalse('0x10 should not be considered visible dimensions.',
    -              goog.testing.style.hasVisibleDimensions(div1));
    -}
    -
    -function testIntersects() {
    -  // No intersection
    -  goog.style.setPosition(div1, 0, 0);
    -  goog.style.setPosition(div2, 500, 500);
    -  assertFalse('The divs should not be determined to itersect.',
    -              goog.testing.style.intersects(div1, div2));
    -
    -  // Some intersection
    -  goog.style.setPosition(div1, 0, 0);
    -  goog.style.setPosition(div2, 50, 50);
    -  assertTrue('The divs should be determined to itersect.',
    -             goog.testing.style.intersects(div1, div2));
    -
    -  // Completely superimposed.
    -  goog.style.setPosition(div1, 0, 0);
    -  goog.style.setPosition(div2, 0, 0);
    -  assertTrue('The divs should be determined to itersect.',
    -             goog.testing.style.intersects(div1, div2));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/testcase.js b/src/database/third_party/closure-library/closure/goog/testing/testcase.js
    deleted file mode 100644
    index 2200e2f304a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/testcase.js
    +++ /dev/null
    @@ -1,1476 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A class representing a set of test functions to be run.
    - *
    - * Testing code should not have dependencies outside of goog.testing so as to
    - * reduce the chance of masking missing dependencies.
    - *
    - * This file does not compile correctly with --collapse_properties. Use
    - * --property_renaming=ALL_UNQUOTED instead.
    - *
    - */
    -
    -goog.provide('goog.testing.TestCase');
    -goog.provide('goog.testing.TestCase.Error');
    -goog.provide('goog.testing.TestCase.Order');
    -goog.provide('goog.testing.TestCase.Result');
    -goog.provide('goog.testing.TestCase.Test');
    -
    -goog.require('goog.Promise');
    -goog.require('goog.Thenable');
    -goog.require('goog.object');
    -goog.require('goog.testing.asserts');
    -goog.require('goog.testing.stacktrace');
    -
    -
    -
    -/**
    - * A class representing a JsUnit test case.  A TestCase is made up of a number
    - * of test functions which can be run.  Individual test cases can override the
    - * following functions to set up their test environment:
    - *   - runTests - completely override the test's runner
    - *   - setUpPage - called before any of the test functions are run
    - *   - tearDownPage - called after all tests are finished
    - *   - setUp - called before each of the test functions
    - *   - tearDown - called after each of the test functions
    - *   - shouldRunTests - called before a test run, all tests are skipped if it
    - *                      returns false.  Can be used to disable tests on browsers
    - *                      where they aren't expected to pass.
    - *
    - * Use {@link #autoDiscoverLifecycle} and {@link #autoDiscoverTests}
    - *
    - * @param {string=} opt_name The name of the test case, defaults to
    - *     'Untitled Test Case'.
    - * @constructor
    - */
    -goog.testing.TestCase = function(opt_name) {
    -  /**
    -   * A name for the test case.
    -   * @type {string}
    -   * @private
    -   */
    -  this.name_ = opt_name || 'Untitled Test Case';
    -
    -  /**
    -   * Array of test functions that can be executed.
    -   * @type {!Array<!goog.testing.TestCase.Test>}
    -   * @private
    -   */
    -  this.tests_ = [];
    -
    -  /**
    -   * Set of test names and/or indices to execute, or null if all tests should
    -   * be executed.
    -   *
    -   * Indices are included to allow automation tools to run a subset of the
    -   * tests without knowing the exact contents of the test file.
    -   *
    -   * Indices should only be used with SORTED ordering.
    -   *
    -   * Example valid values:
    -   * <ul>
    -   * <li>[testName]
    -   * <li>[testName1, testName2]
    -   * <li>[2] - will run the 3rd test in the order specified
    -   * <li>[1,3,5]
    -   * <li>[testName1, testName2, 3, 5] - will work
    -   * <ul>
    -   * @type {Object}
    -   * @private
    -   */
    -  this.testsToRun_ = null;
    -
    -  /** @private {function(!goog.testing.TestCase.Result)} */
    -  this.runNextTestCallback_ = goog.nullFunction;
    -
    -  /**
    -   * The number of {@link runNextTest_} frames currently on the stack.
    -   * When this exceeds {@link MAX_STACK_DEPTH_}, test execution is rescheduled
    -   * for a later tick of the event loop.
    -   * @see {finishTestInvocation_}
    -   * @private {number}
    -   */
    -  this.depth_ = 0;
    -
    -  /** @private {goog.testing.TestCase.Test} */
    -  this.curTest_ = null;
    -
    -  var search = '';
    -  if (goog.global.location) {
    -    search = goog.global.location.search;
    -  }
    -
    -  // Parse the 'runTests' query parameter into a set of test names and/or
    -  // test indices.
    -  var runTestsMatch = search.match(/(?:\?|&)runTests=([^?&]+)/i);
    -  if (runTestsMatch) {
    -    this.testsToRun_ = {};
    -    var arr = runTestsMatch[1].split(',');
    -    for (var i = 0, len = arr.length; i < len; i++) {
    -      this.testsToRun_[arr[i]] = 1;
    -    }
    -  }
    -
    -  // Checks the URL for a valid order param.
    -  var orderMatch = search.match(/(?:\?|&)order=(natural|random|sorted)/i);
    -  if (orderMatch) {
    -    this.order = orderMatch[1];
    -  }
    -
    -  /**
    -   * Object used to encapsulate the test results.
    -   * @type {!goog.testing.TestCase.Result}
    -   * @protected
    -   * @suppress {underscore|visibility}
    -   */
    -  this.result_ = new goog.testing.TestCase.Result(this);
    -};
    -
    -
    -/**
    - * The order to run the auto-discovered tests.
    - * @enum {string}
    - */
    -goog.testing.TestCase.Order = {
    -  /**
    -   * This is browser dependent and known to be different in FF and Safari
    -   * compared to others.
    -   */
    -  NATURAL: 'natural',
    -
    -  /** Random order. */
    -  RANDOM: 'random',
    -
    -  /** Sorted based on the name. */
    -  SORTED: 'sorted'
    -};
    -
    -
    -/**
    - * @return {string} The name of the test.
    - */
    -goog.testing.TestCase.prototype.getName = function() {
    -  return this.name_;
    -};
    -
    -
    -/**
    - * The maximum amount of time in milliseconds that the test case can take
    - * before it is forced to yield and reschedule. This prevents the test runner
    - * from blocking the browser and potentially hurting the test harness.
    - * @type {number}
    - */
    -goog.testing.TestCase.maxRunTime = 200;
    -
    -
    -/**
    - * The maximum number of {@link runNextTest_} frames that can be on the stack
    - * before the test case is forced to yield and reschedule. Although modern
    - * browsers can handle thousands of stack frames, this is set conservatively
    - * because maximum stack depth has never been standardized, and engine-specific
    - * techniques like tail cail optimization can affect the exact depth.
    - * @private @const
    - */
    -goog.testing.TestCase.MAX_STACK_DEPTH_ = 100;
    -
    -
    -/**
    - * The order to run the auto-discovered tests in.
    - * @type {string}
    - */
    -goog.testing.TestCase.prototype.order = goog.testing.TestCase.Order.SORTED;
    -
    -
    -/**
    - * Save a reference to {@code window.setTimeout}, so any code that overrides the
    - * default behavior (the MockClock, for example) doesn't affect our runner.
    - * @type {function((Function|string), number=, *=): number}
    - * @private
    - */
    -goog.testing.TestCase.protectedSetTimeout_ = goog.global.setTimeout;
    -
    -
    -/**
    - * Save a reference to {@code window.clearTimeout}, so any code that overrides
    - * the default behavior (e.g. MockClock) doesn't affect our runner.
    - * @type {function((null|number|undefined)): void}
    - * @private
    - */
    -goog.testing.TestCase.protectedClearTimeout_ = goog.global.clearTimeout;
    -
    -
    -/**
    - * Save a reference to {@code window.Date}, so any code that overrides
    - * the default behavior doesn't affect our runner.
    - * @type {function(new: Date)}
    - * @private
    - */
    -goog.testing.TestCase.protectedDate_ = Date;
    -
    -
    -/**
    - * Saved string referencing goog.global.setTimeout's string serialization.  IE
    - * sometimes fails to uphold equality for setTimeout, but the string version
    - * stays the same.
    - * @type {string}
    - * @private
    - */
    -goog.testing.TestCase.setTimeoutAsString_ = String(goog.global.setTimeout);
    -
    -
    -/**
    - * TODO(user) replace this with prototype.currentTest.
    - * Name of the current test that is running, or null if none is running.
    - * @type {?string}
    - */
    -goog.testing.TestCase.currentTestName = null;
    -
    -
    -/**
    - * Avoid a dependency on goog.userAgent and keep our own reference of whether
    - * the browser is IE.
    - * @type {boolean}
    - */
    -goog.testing.TestCase.IS_IE = typeof opera == 'undefined' &&
    -    !!goog.global.navigator &&
    -    goog.global.navigator.userAgent.indexOf('MSIE') != -1;
    -
    -
    -/**
    - * Exception object that was detected before a test runs.
    - * @type {*}
    - * @protected
    - */
    -goog.testing.TestCase.prototype.exceptionBeforeTest;
    -
    -
    -/**
    - * Whether the test case has ever tried to execute.
    - * @type {boolean}
    - */
    -goog.testing.TestCase.prototype.started = false;
    -
    -
    -/**
    - * Whether the test case is running.
    - * @type {boolean}
    - */
    -goog.testing.TestCase.prototype.running = false;
    -
    -
    -/**
    - * Timestamp for when the test was started.
    - * @type {number}
    - * @private
    - */
    -goog.testing.TestCase.prototype.startTime_ = 0;
    -
    -
    -/**
    - * Time since the last batch of tests was started, if batchTime exceeds
    - * {@link #maxRunTime} a timeout will be used to stop the tests blocking the
    - * browser and a new batch will be started.
    - * @type {number}
    - * @private
    - */
    -goog.testing.TestCase.prototype.batchTime_ = 0;
    -
    -
    -/**
    - * Pointer to the current test.
    - * @type {number}
    - * @private
    - */
    -goog.testing.TestCase.prototype.currentTestPointer_ = 0;
    -
    -
    -/**
    - * Optional callback that will be executed when the test has finalized.
    - * @type {Function}
    - * @private
    - */
    -goog.testing.TestCase.prototype.onCompleteCallback_ = null;
    -
    -
    -/**
    - * Adds a new test to the test case.
    - * @param {goog.testing.TestCase.Test} test The test to add.
    - */
    -goog.testing.TestCase.prototype.add = function(test) {
    -  if (this.started) {
    -    throw Error('Tests cannot be added after execute() has been called. ' +
    -                'Test: ' + test.name);
    -  }
    -
    -  this.tests_.push(test);
    -};
    -
    -
    -/**
    - * Creates and adds a new test.
    - *
    - * Convenience function to make syntax less awkward when not using automatic
    - * test discovery.
    - *
    - * @param {string} name The test name.
    - * @param {!Function} ref Reference to the test function.
    - * @param {!Object=} opt_scope Optional scope that the test function should be
    - *     called in.
    - */
    -goog.testing.TestCase.prototype.addNewTest = function(name, ref, opt_scope) {
    -  var test = new goog.testing.TestCase.Test(name, ref, opt_scope || this);
    -  this.add(test);
    -};
    -
    -
    -/**
    - * Sets the tests.
    - * @param {!Array<goog.testing.TestCase.Test>} tests A new test array.
    - * @protected
    - */
    -goog.testing.TestCase.prototype.setTests = function(tests) {
    -  this.tests_ = tests;
    -};
    -
    -
    -/**
    - * Gets the tests.
    - * @return {!Array<goog.testing.TestCase.Test>} The test array.
    - */
    -goog.testing.TestCase.prototype.getTests = function() {
    -  return this.tests_;
    -};
    -
    -
    -/**
    - * Returns the number of tests contained in the test case.
    - * @return {number} The number of tests.
    - */
    -goog.testing.TestCase.prototype.getCount = function() {
    -  return this.tests_.length;
    -};
    -
    -
    -/**
    - * Returns the number of tests actually run in the test case, i.e. subtracting
    - * any which are skipped.
    - * @return {number} The number of un-ignored tests.
    - */
    -goog.testing.TestCase.prototype.getActuallyRunCount = function() {
    -  return this.testsToRun_ ? goog.object.getCount(this.testsToRun_) : 0;
    -};
    -
    -
    -/**
    - * Returns the current test and increments the pointer.
    - * @return {goog.testing.TestCase.Test} The current test case.
    - */
    -goog.testing.TestCase.prototype.next = function() {
    -  var test;
    -  while ((test = this.tests_[this.currentTestPointer_++])) {
    -    if (!this.testsToRun_ || this.testsToRun_[test.name] ||
    -        this.testsToRun_[this.currentTestPointer_ - 1]) {
    -      return test;
    -    }
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * Resets the test case pointer, so that next returns the first test.
    - */
    -goog.testing.TestCase.prototype.reset = function() {
    -  this.currentTestPointer_ = 0;
    -  this.result_ = new goog.testing.TestCase.Result(this);
    -};
    -
    -
    -/**
    - * Sets the callback function that should be executed when the tests have
    - * completed.
    - * @param {Function} fn The callback function.
    - */
    -goog.testing.TestCase.prototype.setCompletedCallback = function(fn) {
    -  this.onCompleteCallback_ = fn;
    -};
    -
    -
    -/**
    - * Can be overridden in test classes to indicate whether the tests in a case
    - * should be run in that particular situation.  For example, this could be used
    - * to stop tests running in a particular browser, where browser support for
    - * the class under test was absent.
    - * @return {boolean} Whether any of the tests in the case should be run.
    - */
    -goog.testing.TestCase.prototype.shouldRunTests = function() {
    -  return true;
    -};
    -
    -
    -/**
    - * Executes the tests, yielding asynchronously if execution time exceeds
    - * {@link maxRunTime}. There is no guarantee that the test case has finished
    - * once this method has returned. To be notified when the test case
    - * has finished, use {@link #setCompletedCallback} or
    - * {@link #runTestsReturningPromise}.
    - */
    -goog.testing.TestCase.prototype.execute = function() {
    -  if (!this.prepareForRun_()) {
    -    return;
    -  }
    -  this.log('Starting tests: ' + this.name_);
    -  this.cycleTests();
    -};
    -
    -
    -/**
    - * Sets up the internal state of the test case for a run.
    - * @return {boolean} If false, preparation failed because the test case
    - *     is not supposed to run in the present environment.
    - * @private
    - */
    -goog.testing.TestCase.prototype.prepareForRun_ = function() {
    -  this.started = true;
    -  this.reset();
    -  this.startTime_ = this.now();
    -  this.running = true;
    -  this.result_.totalCount = this.getCount();
    -  if (!this.shouldRunTests()) {
    -    this.log('shouldRunTests() returned false, skipping these tests.');
    -    this.result_.testSuppressed = true;
    -    this.finalize();
    -    return false;
    -  }
    -  return true;
    -};
    -
    -
    -/**
    - * Finalizes the test case, called when the tests have finished executing.
    - */
    -goog.testing.TestCase.prototype.finalize = function() {
    -  this.saveMessage('Done');
    -
    -  this.tearDownPage();
    -
    -  var restoredSetTimeout =
    -      goog.testing.TestCase.protectedSetTimeout_ == goog.global.setTimeout &&
    -      goog.testing.TestCase.protectedClearTimeout_ == goog.global.clearTimeout;
    -  if (!restoredSetTimeout && goog.testing.TestCase.IS_IE &&
    -      String(goog.global.setTimeout) ==
    -          goog.testing.TestCase.setTimeoutAsString_) {
    -    // In strange cases, IE's value of setTimeout *appears* to change, but
    -    // the string representation stays stable.
    -    restoredSetTimeout = true;
    -  }
    -
    -  if (!restoredSetTimeout) {
    -    var message = 'ERROR: Test did not restore setTimeout and clearTimeout';
    -    this.saveMessage(message);
    -    var err = new goog.testing.TestCase.Error(this.name_, message);
    -    this.result_.errors.push(err);
    -  }
    -  goog.global.clearTimeout = goog.testing.TestCase.protectedClearTimeout_;
    -  goog.global.setTimeout = goog.testing.TestCase.protectedSetTimeout_;
    -  this.endTime_ = this.now();
    -  this.running = false;
    -  this.result_.runTime = this.endTime_ - this.startTime_;
    -  this.result_.numFilesLoaded = this.countNumFilesLoaded_();
    -  this.result_.complete = true;
    -
    -  this.log(this.result_.getSummary());
    -  if (this.result_.isSuccess()) {
    -    this.log('Tests complete');
    -  } else {
    -    this.log('Tests Failed');
    -  }
    -  if (this.onCompleteCallback_) {
    -    var fn = this.onCompleteCallback_;
    -    // Execute's the completed callback in the context of the global object.
    -    fn();
    -    this.onCompleteCallback_ = null;
    -  }
    -};
    -
    -
    -/**
    - * Saves a message to the result set.
    - * @param {string} message The message to save.
    - */
    -goog.testing.TestCase.prototype.saveMessage = function(message) {
    -  this.result_.messages.push(this.getTimeStamp_() + '  ' + message);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the test case is running inside the multi test
    - *     runner.
    - */
    -goog.testing.TestCase.prototype.isInsideMultiTestRunner = function() {
    -  var top = goog.global['top'];
    -  return top && typeof top['_allTests'] != 'undefined';
    -};
    -
    -
    -/**
    - * Logs an object to the console, if available.
    - * @param {*} val The value to log. Will be ToString'd.
    - */
    -goog.testing.TestCase.prototype.log = function(val) {
    -  if (!this.isInsideMultiTestRunner() && goog.global.console) {
    -    if (typeof val == 'string') {
    -      val = this.getTimeStamp_() + ' : ' + val;
    -    }
    -    if (val instanceof Error && val.stack) {
    -      // Chrome does console.log asynchronously in a different process
    -      // (http://code.google.com/p/chromium/issues/detail?id=50316).
    -      // This is an acute problem for Errors, which almost never survive.
    -      // Grab references to the immutable strings so they survive.
    -      goog.global.console.log(val, val.message, val.stack);
    -      // TODO(gboyer): Consider for Chrome cloning any object if we can ensure
    -      // there are no circular references.
    -    } else {
    -      goog.global.console.log(val);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the test was a success.
    - */
    -goog.testing.TestCase.prototype.isSuccess = function() {
    -  return !!this.result_ && this.result_.isSuccess();
    -};
    -
    -
    -/**
    - * Returns a string detailing the results from the test.
    - * @param {boolean=} opt_verbose If true results will include data about all
    - *     tests, not just what failed.
    - * @return {string} The results from the test.
    - */
    -goog.testing.TestCase.prototype.getReport = function(opt_verbose) {
    -  var rv = [];
    -
    -  if (this.running) {
    -    rv.push(this.name_ + ' [RUNNING]');
    -  } else {
    -    var label = this.result_.isSuccess() ? 'PASSED' : 'FAILED';
    -    rv.push(this.name_ + ' [' + label + ']');
    -  }
    -
    -  if (goog.global.location) {
    -    rv.push(this.trimPath_(goog.global.location.href));
    -  }
    -
    -  rv.push(this.result_.getSummary());
    -
    -  if (opt_verbose) {
    -    rv.push('.', this.result_.messages.join('\n'));
    -  } else if (!this.result_.isSuccess()) {
    -    rv.push(this.result_.errors.join('\n'));
    -  }
    -
    -  rv.push(' ');
    -
    -  return rv.join('\n');
    -};
    -
    -
    -/**
    - * Returns the test results.
    - * @return {!goog.testing.TestCase.Result}
    - * @package
    - */
    -goog.testing.TestCase.prototype.getResult = function() {
    -  return this.result_;
    -};
    -
    -
    -/**
    - * Returns the amount of time it took for the test to run.
    - * @return {number} The run time, in milliseconds.
    - */
    -goog.testing.TestCase.prototype.getRunTime = function() {
    -  return this.result_.runTime;
    -};
    -
    -
    -/**
    - * Returns the number of script files that were loaded in order to run the test.
    - * @return {number} The number of script files.
    - */
    -goog.testing.TestCase.prototype.getNumFilesLoaded = function() {
    -  return this.result_.numFilesLoaded;
    -};
    -
    -
    -/**
    - * Returns the test results object: a map from test names to a list of test
    - * failures (if any exist).
    - * @return {!Object<string, !Array<string>>} Tests results object.
    - */
    -goog.testing.TestCase.prototype.getTestResults = function() {
    -  return this.result_.resultsByName;
    -};
    -
    -
    -/**
    - * Executes each of the tests, yielding asynchronously if execution time
    - * exceeds {@link #maxRunTime}. There is no guarantee that the test case
    - * has finished execution once this method has returned.
    - * To be notified when the test case has finished execution, use
    - * {@link #setCompletedCallback} or {@link #runTestsReturningPromise}.
    - *
    - * Overridable by the individual test case.  This allows test cases to defer
    - * when the test is actually started.  If overridden, finalize must be called
    - * by the test to indicate it has finished.
    - */
    -goog.testing.TestCase.prototype.runTests = function() {
    -  try {
    -    this.setUpPage();
    -  } catch (e) {
    -    this.exceptionBeforeTest = e;
    -  }
    -  this.execute();
    -};
    -
    -
    -/**
    - * Executes each of the tests, returning a promise that resolves with the
    - * test results once they are done running.
    - * @return {!IThenable.<!goog.testing.TestCase.Result>}
    - * @final
    - * @package
    - */
    -goog.testing.TestCase.prototype.runTestsReturningPromise = function() {
    -  try {
    -    this.setUpPage();
    -  } catch (e) {
    -    this.exceptionBeforeTest = e;
    -  }
    -  if (!this.prepareForRun_()) {
    -    return goog.Promise.resolve(this.result_);
    -  }
    -  this.log('Starting tests: ' + this.name_);
    -  this.saveMessage('Start');
    -  this.batchTime_ = this.now();
    -  return new goog.Promise(function(resolve) {
    -    this.runNextTestCallback_ = resolve;
    -    this.runNextTest_();
    -  }, this);
    -};
    -
    -
    -/**
    - * Executes the next test method synchronously or with promises, depending on
    - * the test method's return value.
    - *
    - * If the test method returns a promise, the next test method will run once
    - * the promise is resolved or rejected. If the test method does not
    - * return a promise, it is assumed to be synchronous, and execution proceeds
    - * immediately to the next test method. This means that test cases can run
    - * partially synchronously and partially asynchronously, depending on
    - * the return values of their test methods. In particular, a test case
    - * executes synchronously until the first promise is returned from a
    - * test method (or until a resource limit is reached; see
    - * {@link finishTestInvocation_}).
    - * @private
    - */
    -goog.testing.TestCase.prototype.runNextTest_ = function() {
    -  this.curTest_ = this.next();
    -  if (!this.curTest_ || !this.running) {
    -    this.finalize();
    -    this.runNextTestCallback_(this.result_);
    -    return;
    -  }
    -  this.result_.runCount++;
    -  this.log('Running test: ' + this.curTest_.name);
    -  if (this.maybeFailTestEarly(this.curTest_)) {
    -    this.finishTestInvocation_();
    -    return;
    -  }
    -  goog.testing.TestCase.currentTestName = this.curTest_.name;
    -  this.invokeTestFunction_(
    -      this.setUp, this.safeRunTest_, this.safeTearDown_);
    -};
    -
    -
    -/**
    - * Calls the given test function, handling errors appropriately.
    - * @private
    - */
    -goog.testing.TestCase.prototype.safeRunTest_ = function() {
    -  this.invokeTestFunction_(
    -      goog.bind(this.curTest_.ref, this.curTest_.scope),
    -      this.safeTearDown_,
    -      this.safeTearDown_);
    -};
    -
    -
    -/**
    - * Calls {@link tearDown}, handling errors appropriately.
    - * @param {*=} opt_error Error associated with the test, if any.
    - * @private
    - */
    -goog.testing.TestCase.prototype.safeTearDown_ = function(opt_error) {
    -  if (arguments.length == 1) {
    -    this.doError(this.curTest_, opt_error);
    -  }
    -  this.invokeTestFunction_(
    -      this.tearDown, this.finishTestInvocation_, this.finishTestInvocation_);
    -};
    -
    -
    -/**
    - * Calls the given {@code fn}, then calls either {@code onSuccess} or
    - * {@code onFailure}, either synchronously or using promises, depending on
    - * {@code fn}'s return value.
    - *
    - * If {@code fn} throws an exception, {@code onFailure} is called immediately
    - * with the exception.
    - *
    - * If {@code fn} returns a promise, and the promise is eventually resolved,
    - * {@code onSuccess} is called with no arguments. If the promise is eventually
    - * rejected, {@code onFailure} is called with the rejection reason.
    - *
    - * Otherwise, if {@code fn} neither returns a promise nor throws an exception,
    - * {@code onSuccess} is called immediately with no arguments.
    - *
    - * {@code fn}, {@code onSuccess}, and {@code onFailure} are all called with
    - * the TestCase instance as the method receiver.
    - *
    - * @param {function()} fn The function to call.
    - * @param {function()} onSuccess Success callback.
    - * @param {function(*)} onFailure Failure callback.
    - * @private
    - */
    -goog.testing.TestCase.prototype.invokeTestFunction_ = function(
    -    fn, onSuccess, onFailure) {
    -  try {
    -    var retval = fn.call(this);
    -    if (goog.Thenable.isImplementedBy(retval) ||
    -        goog.isFunction(retval && retval['then'])) {
    -      var self = this;
    -      retval.then(
    -          function() {
    -            self.resetBatchTimeAfterPromise_();
    -            onSuccess.call(self);
    -          },
    -          function(e) {
    -            self.resetBatchTimeAfterPromise_();
    -            onFailure.call(self, e);
    -          });
    -    } else {
    -      onSuccess.call(this);
    -    }
    -  } catch (e) {
    -    onFailure.call(this, e);
    -  }
    -};
    -
    -
    -/**
    - * Resets the batch run timer. This should only be called after resolving a
    - * promise since Promise.then() has an implicit yield.
    - * @private
    - */
    -goog.testing.TestCase.prototype.resetBatchTimeAfterPromise_ = function() {
    -  this.batchTime_ = this.now();
    -};
    -
    -
    -/**
    - * Finishes up bookkeeping for the current test function, and schedules
    - * the next test function to run, either immediately or asychronously.
    - * @param {*=} opt_error Optional error resulting from the test invocation.
    - * @private
    - */
    -goog.testing.TestCase.prototype.finishTestInvocation_ = function(opt_error) {
    -  if (arguments.length == 1) {
    -    this.doError(this.curTest_, opt_error);
    -  }
    -
    -  // If no errors have been recorded for the test, it is a success.
    -  if (!(this.curTest_.name in this.result_.resultsByName) ||
    -      !this.result_.resultsByName[this.curTest_.name].length) {
    -    this.doSuccess(this.curTest_);
    -  }
    -
    -  goog.testing.TestCase.currentTestName = null;
    -
    -  // If the test case has consumed too much time or stack space,
    -  // yield to avoid blocking the browser. Otherwise, proceed to the next test.
    -  if (this.depth_ > goog.testing.TestCase.MAX_STACK_DEPTH_ ||
    -      this.now() - this.batchTime_ > goog.testing.TestCase.maxRunTime) {
    -    this.saveMessage('Breaking async');
    -    this.batchTime_ = this.now();
    -    this.depth_ = 0;
    -    this.timeout(goog.bind(this.runNextTest_, this), 0);
    -  } else {
    -    ++this.depth_;
    -    this.runNextTest_();
    -  }
    -};
    -
    -
    -/**
    - * Reorders the tests depending on the {@code order} field.
    - * @param {Array<goog.testing.TestCase.Test>} tests An array of tests to
    - *     reorder.
    - * @private
    - */
    -goog.testing.TestCase.prototype.orderTests_ = function(tests) {
    -  switch (this.order) {
    -    case goog.testing.TestCase.Order.RANDOM:
    -      // Fisher-Yates shuffle
    -      var i = tests.length;
    -      while (i > 1) {
    -        // goog.math.randomInt is inlined to reduce dependencies.
    -        var j = Math.floor(Math.random() * i); // exclusive
    -        i--;
    -        var tmp = tests[i];
    -        tests[i] = tests[j];
    -        tests[j] = tmp;
    -      }
    -      break;
    -
    -    case goog.testing.TestCase.Order.SORTED:
    -      tests.sort(function(t1, t2) {
    -        if (t1.name == t2.name) {
    -          return 0;
    -        }
    -        return t1.name < t2.name ? -1 : 1;
    -      });
    -      break;
    -
    -      // Do nothing for NATURAL.
    -  }
    -};
    -
    -
    -/**
    - * Gets list of objects that potentially contain test cases. For IE 8 and below,
    - * this is the global "this" (for properties set directly on the global this or
    - * window) and the RuntimeObject (for global variables and functions). For all
    - * other browsers, the array simply contains the global this.
    - *
    - * @param {string=} opt_prefix An optional prefix. If specified, only get things
    - *     under this prefix. Note that the prefix is only honored in IE, since it
    - *     supports the RuntimeObject:
    - *     http://msdn.microsoft.com/en-us/library/ff521039%28VS.85%29.aspx
    - *     TODO: Remove this option.
    - * @return {!Array<!Object>} A list of objects that should be inspected.
    - */
    -goog.testing.TestCase.prototype.getGlobals = function(opt_prefix) {
    -  return goog.testing.TestCase.getGlobals(opt_prefix);
    -};
    -
    -
    -/**
    - * Gets list of objects that potentially contain test cases. For IE 8 and below,
    - * this is the global "this" (for properties set directly on the global this or
    - * window) and the RuntimeObject (for global variables and functions). For all
    - * other browsers, the array simply contains the global this.
    - *
    - * @param {string=} opt_prefix An optional prefix. If specified, only get things
    - *     under this prefix. Note that the prefix is only honored in IE, since it
    - *     supports the RuntimeObject:
    - *     http://msdn.microsoft.com/en-us/library/ff521039%28VS.85%29.aspx
    - *     TODO: Remove this option.
    - * @return {!Array<!Object>} A list of objects that should be inspected.
    - */
    -goog.testing.TestCase.getGlobals = function(opt_prefix) {
    -  // Look in the global scope for most browsers, on IE we use the little known
    -  // RuntimeObject which holds references to all globals. We reference this
    -  // via goog.global so that there isn't an aliasing that throws an exception
    -  // in Firefox.
    -  return typeof goog.global['RuntimeObject'] != 'undefined' ?
    -      [goog.global['RuntimeObject']((opt_prefix || '') + '*'), goog.global] :
    -      [goog.global];
    -};
    -
    -
    -/**
    - * Gets called before any tests are executed.  Can be overridden to set up the
    - * environment for the whole test case.
    - */
    -goog.testing.TestCase.prototype.setUpPage = function() {};
    -
    -
    -/**
    - * Gets called after all tests have been executed.  Can be overridden to tear
    - * down the entire test case.
    - */
    -goog.testing.TestCase.prototype.tearDownPage = function() {};
    -
    -
    -/**
    - * Gets called before every goog.testing.TestCase.Test is been executed. Can be
    - * overridden to add set up functionality to each test.
    - */
    -goog.testing.TestCase.prototype.setUp = function() {};
    -
    -
    -/**
    - * Gets called after every goog.testing.TestCase.Test has been executed. Can be
    - * overriden to add tear down functionality to each test.
    - */
    -goog.testing.TestCase.prototype.tearDown = function() {};
    -
    -
    -/**
    - * @return {string} The function name prefix used to auto-discover tests.
    - * @protected
    - */
    -goog.testing.TestCase.prototype.getAutoDiscoveryPrefix = function() {
    -  return 'test';
    -};
    -
    -
    -/**
    - * @return {number} Time since the last batch of tests was started.
    - * @protected
    - */
    -goog.testing.TestCase.prototype.getBatchTime = function() {
    -  return this.batchTime_;
    -};
    -
    -
    -/**
    - * @param {number} batchTime Time since the last batch of tests was started.
    - * @protected
    - */
    -goog.testing.TestCase.prototype.setBatchTime = function(batchTime) {
    -  this.batchTime_ = batchTime;
    -};
    -
    -
    -/**
    - * Creates a {@code goog.testing.TestCase.Test} from an auto-discovered
    - *     function.
    - * @param {string} name The name of the function.
    - * @param {function() : void} ref The auto-discovered function.
    - * @return {!goog.testing.TestCase.Test} The newly created test.
    - * @protected
    - */
    -goog.testing.TestCase.prototype.createTestFromAutoDiscoveredFunction =
    -    function(name, ref) {
    -  return new goog.testing.TestCase.Test(name, ref, goog.global);
    -};
    -
    -
    -/**
    - * Adds any functions defined in the global scope that correspond to
    - * lifecycle events for the test case. Overrides setUp, tearDown, setUpPage,
    - * tearDownPage and runTests if they are defined.
    - */
    -goog.testing.TestCase.prototype.autoDiscoverLifecycle = function() {
    -  if (goog.global['setUp']) {
    -    this.setUp = goog.bind(goog.global['setUp'], goog.global);
    -  }
    -  if (goog.global['tearDown']) {
    -    this.tearDown = goog.bind(goog.global['tearDown'], goog.global);
    -  }
    -  if (goog.global['setUpPage']) {
    -    this.setUpPage = goog.bind(goog.global['setUpPage'], goog.global);
    -  }
    -  if (goog.global['tearDownPage']) {
    -    this.tearDownPage = goog.bind(goog.global['tearDownPage'], goog.global);
    -  }
    -  if (goog.global['runTests']) {
    -    this.runTests = goog.bind(goog.global['runTests'], goog.global);
    -  }
    -  if (goog.global['shouldRunTests']) {
    -    this.shouldRunTests = goog.bind(goog.global['shouldRunTests'], goog.global);
    -  }
    -};
    -
    -
    -/**
    - * Adds any functions defined in the global scope that are prefixed with "test"
    - * to the test case.
    - */
    -goog.testing.TestCase.prototype.autoDiscoverTests = function() {
    -  var prefix = this.getAutoDiscoveryPrefix();
    -  var testSources = this.getGlobals(prefix);
    -
    -  var foundTests = [];
    -
    -  for (var i = 0; i < testSources.length; i++) {
    -    var testSource = testSources[i];
    -    for (var name in testSource) {
    -      if ((new RegExp('^' + prefix)).test(name)) {
    -        var ref;
    -        try {
    -          ref = testSource[name];
    -        } catch (ex) {
    -          // NOTE(brenneman): When running tests from a file:// URL on Firefox
    -          // 3.5 for Windows, any reference to goog.global.sessionStorage raises
    -          // an "Operation is not supported" exception. Ignore any exceptions
    -          // raised by simply accessing global properties.
    -          ref = undefined;
    -        }
    -
    -        if (goog.isFunction(ref)) {
    -          foundTests.push(this.createTestFromAutoDiscoveredFunction(name, ref));
    -        }
    -      }
    -    }
    -  }
    -
    -  this.orderTests_(foundTests);
    -
    -  for (var i = 0; i < foundTests.length; i++) {
    -    this.add(foundTests[i]);
    -  }
    -
    -  this.log(this.getCount() + ' tests auto-discovered');
    -
    -  // TODO(user): Do this as a separate call. Unfortunately, a lot of projects
    -  // currently override autoDiscoverTests and expect lifecycle events to be
    -  // registered as a part of this call.
    -  this.autoDiscoverLifecycle();
    -};
    -
    -
    -/**
    - * Checks to see if the test should be marked as failed before it is run.
    - *
    - * If there was an error in setUpPage, we treat that as a failure for all tests
    - * and mark them all as having failed.
    - *
    - * @param {goog.testing.TestCase.Test} testCase The current test case.
    - * @return {boolean} Whether the test was marked as failed.
    - * @protected
    - */
    -goog.testing.TestCase.prototype.maybeFailTestEarly = function(testCase) {
    -  if (this.exceptionBeforeTest) {
    -    // We just use the first error to report an error on a failed test.
    -    this.curTest_.name = 'setUpPage for ' + this.curTest_.name;
    -    this.doError(this.curTest_, this.exceptionBeforeTest);
    -    return true;
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Cycles through the tests, yielding asynchronously if the execution time
    - * execeeds {@link #maxRunTime}. In particular, there is no guarantee that
    - * the test case has finished execution once this method has returned.
    - * To be notified when the test case has finished execution, use
    - * {@link #setCompletedCallback} or {@link #runTestsReturningPromise}.
    - */
    -goog.testing.TestCase.prototype.cycleTests = function() {
    -  this.saveMessage('Start');
    -  this.batchTime_ = this.now();
    -  if (this.running) {
    -    this.runNextTestCallback_ = goog.nullFunction;
    -    // Kick off the tests. runNextTest_ will schedule all of the tests,
    -    // using a mixture of synchronous and asynchronous strategies.
    -    this.runNextTest_();
    -  }
    -};
    -
    -
    -/**
    - * Counts the number of files that were loaded for dependencies that are
    - * required to run the test.
    - * @return {number} The number of files loaded.
    - * @private
    - */
    -goog.testing.TestCase.prototype.countNumFilesLoaded_ = function() {
    -  var scripts = document.getElementsByTagName('script');
    -  var count = 0;
    -  for (var i = 0, n = scripts.length; i < n; i++) {
    -    if (scripts[i].src) {
    -      count++;
    -    }
    -  }
    -  return count;
    -};
    -
    -
    -/**
    - * Calls a function after a delay, using the protected timeout.
    - * @param {Function} fn The function to call.
    - * @param {number} time Delay in milliseconds.
    - * @return {number} The timeout id.
    - * @protected
    - */
    -goog.testing.TestCase.prototype.timeout = function(fn, time) {
    -  // NOTE: invoking protectedSetTimeout_ as a member of goog.testing.TestCase
    -  // would result in an Illegal Invocation error. The method must be executed
    -  // with the global context.
    -  var protectedSetTimeout = goog.testing.TestCase.protectedSetTimeout_;
    -  return protectedSetTimeout(fn, time);
    -};
    -
    -
    -/**
    - * Clears a timeout created by {@code this.timeout()}.
    - * @param {number} id A timeout id.
    - * @protected
    - */
    -goog.testing.TestCase.prototype.clearTimeout = function(id) {
    -  // NOTE: see execution note for protectedSetTimeout above.
    -  var protectedClearTimeout = goog.testing.TestCase.protectedClearTimeout_;
    -  protectedClearTimeout(id);
    -};
    -
    -
    -/**
    - * @return {number} The current time in milliseconds, don't use goog.now as some
    - *     tests override it.
    - * @protected
    - */
    -goog.testing.TestCase.prototype.now = function() {
    -  // Cannot use "new goog.testing.TestCase.protectedDate_()" due to b/8323223.
    -  var protectedDate = goog.testing.TestCase.protectedDate_;
    -  return new protectedDate().getTime();
    -};
    -
    -
    -/**
    - * Returns the current time.
    - * @return {string} HH:MM:SS.
    - * @private
    - */
    -goog.testing.TestCase.prototype.getTimeStamp_ = function() {
    -  // Cannot use "new goog.testing.TestCase.protectedDate_()" due to b/8323223.
    -  var protectedDate = goog.testing.TestCase.protectedDate_;
    -  var d = new protectedDate();
    -
    -  // Ensure millis are always 3-digits
    -  var millis = '00' + d.getMilliseconds();
    -  millis = millis.substr(millis.length - 3);
    -
    -  return this.pad_(d.getHours()) + ':' + this.pad_(d.getMinutes()) + ':' +
    -         this.pad_(d.getSeconds()) + '.' + millis;
    -};
    -
    -
    -/**
    - * Pads a number to make it have a leading zero if it's less than 10.
    - * @param {number} number The number to pad.
    - * @return {string} The resulting string.
    - * @private
    - */
    -goog.testing.TestCase.prototype.pad_ = function(number) {
    -  return number < 10 ? '0' + number : String(number);
    -};
    -
    -
    -/**
    - * Trims a path to be only that after google3.
    - * @param {string} path The path to trim.
    - * @return {string} The resulting string.
    - * @private
    - */
    -goog.testing.TestCase.prototype.trimPath_ = function(path) {
    -  return path.substring(path.indexOf('google3') + 8);
    -};
    -
    -
    -/**
    - * Handles a test that passed.
    - * @param {goog.testing.TestCase.Test} test The test that passed.
    - * @protected
    - */
    -goog.testing.TestCase.prototype.doSuccess = function(test) {
    -  this.result_.successCount++;
    -  // An empty list of error messages indicates that the test passed.
    -  // If we already have a failure for this test, do not set to empty list.
    -  if (!(test.name in this.result_.resultsByName)) {
    -    this.result_.resultsByName[test.name] = [];
    -  }
    -  var message = test.name + ' : PASSED';
    -  this.saveMessage(message);
    -  this.log(message);
    -};
    -
    -
    -/**
    - * Handles a test that failed.
    - * @param {goog.testing.TestCase.Test} test The test that failed.
    - * @param {*=} opt_e The exception object associated with the
    - *     failure or a string.
    - * @protected
    - */
    -goog.testing.TestCase.prototype.doError = function(test, opt_e) {
    -  var message = test.name + ' : FAILED';
    -  this.log(message);
    -  this.saveMessage(message);
    -  var err = this.logError(test.name, opt_e);
    -  this.result_.errors.push(err);
    -  if (test.name in this.result_.resultsByName) {
    -    this.result_.resultsByName[test.name].push(err.toString());
    -  } else {
    -    this.result_.resultsByName[test.name] = [err.toString()];
    -  }
    -};
    -
    -
    -/**
    - * @param {string} name Failed test name.
    - * @param {*=} opt_e The exception object associated with the
    - *     failure or a string.
    - * @return {!goog.testing.TestCase.Error} Error object.
    - */
    -goog.testing.TestCase.prototype.logError = function(name, opt_e) {
    -  var errMsg = null;
    -  var stack = null;
    -  if (opt_e) {
    -    this.log(opt_e);
    -    if (goog.isString(opt_e)) {
    -      errMsg = opt_e;
    -    } else {
    -      errMsg = opt_e.message || opt_e.description || opt_e.toString();
    -      stack = opt_e.stack ? goog.testing.stacktrace.canonicalize(opt_e.stack) :
    -          opt_e['stackTrace'];
    -    }
    -  } else {
    -    errMsg = 'An unknown error occurred';
    -  }
    -  var err = new goog.testing.TestCase.Error(name, errMsg, stack);
    -
    -  // Avoid double logging.
    -  if (!opt_e || !opt_e['isJsUnitException'] ||
    -      !opt_e['loggedJsUnitException']) {
    -    this.saveMessage(err.toString());
    -  }
    -  if (opt_e && opt_e['isJsUnitException']) {
    -    opt_e['loggedJsUnitException'] = true;
    -  }
    -
    -  return err;
    -};
    -
    -
    -
    -/**
    - * A class representing a single test function.
    - * @param {string} name The test name.
    - * @param {Function} ref Reference to the test function.
    - * @param {Object=} opt_scope Optional scope that the test function should be
    - *     called in.
    - * @constructor
    - */
    -goog.testing.TestCase.Test = function(name, ref, opt_scope) {
    -  /**
    -   * The name of the test.
    -   * @type {string}
    -   */
    -  this.name = name;
    -
    -  /**
    -   * Reference to the test function.
    -   * @type {Function}
    -   */
    -  this.ref = ref;
    -
    -  /**
    -   * Scope that the test function should be called in.
    -   * @type {Object}
    -   */
    -  this.scope = opt_scope || null;
    -};
    -
    -
    -/**
    - * Executes the test function.
    - * @package
    - */
    -goog.testing.TestCase.Test.prototype.execute = function() {
    -  this.ref.call(this.scope);
    -};
    -
    -
    -
    -/**
    - * A class for representing test results.  A bag of public properties.
    - * @param {goog.testing.TestCase} testCase The test case that owns this result.
    - * @constructor
    - * @final
    - */
    -goog.testing.TestCase.Result = function(testCase) {
    -  /**
    -   * The test case that owns this result.
    -   * @type {goog.testing.TestCase}
    -   * @private
    -   */
    -  this.testCase_ = testCase;
    -
    -  /**
    -   * Total number of tests that should have been run.
    -   * @type {number}
    -   */
    -  this.totalCount = 0;
    -
    -  /**
    -   * Total number of tests that were actually run.
    -   * @type {number}
    -   */
    -  this.runCount = 0;
    -
    -  /**
    -   * Number of successful tests.
    -   * @type {number}
    -   */
    -  this.successCount = 0;
    -
    -  /**
    -   * The amount of time the tests took to run.
    -   * @type {number}
    -   */
    -  this.runTime = 0;
    -
    -  /**
    -   * The number of files loaded to run this test.
    -   * @type {number}
    -   */
    -  this.numFilesLoaded = 0;
    -
    -  /**
    -   * Whether this test case was suppressed by shouldRunTests() returning false.
    -   * @type {boolean}
    -   */
    -  this.testSuppressed = false;
    -
    -  /**
    -   * Test results for each test that was run. The test name is always added
    -   * as the key in the map, and the array of strings is an optional list
    -   * of failure messages. If the array is empty, the test passed. Otherwise,
    -   * the test failed.
    -   * @type {!Object<string, !Array<string>>}
    -   */
    -  this.resultsByName = {};
    -
    -  /**
    -   * Errors encountered while running the test.
    -   * @type {!Array<goog.testing.TestCase.Error>}
    -   */
    -  this.errors = [];
    -
    -  /**
    -   * Messages to show the user after running the test.
    -   * @type {!Array<string>}
    -   */
    -  this.messages = [];
    -
    -  /**
    -   * Whether the tests have completed.
    -   * @type {boolean}
    -   */
    -  this.complete = false;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the test was successful.
    - */
    -goog.testing.TestCase.Result.prototype.isSuccess = function() {
    -  return this.complete && this.errors.length == 0;
    -};
    -
    -
    -/**
    - * @return {string} A summary of the tests, including total number of tests that
    - *     passed, failed, and the time taken.
    - */
    -goog.testing.TestCase.Result.prototype.getSummary = function() {
    -  var summary = this.runCount + ' of ' + this.totalCount + ' tests run in ' +
    -      this.runTime + 'ms.\n';
    -  if (this.testSuppressed) {
    -    summary += 'Tests not run because shouldRunTests() returned false.';
    -  } else {
    -    var failures = this.totalCount - this.successCount;
    -    var suppressionMessage = '';
    -
    -    var countOfRunTests = this.testCase_.getActuallyRunCount();
    -    if (countOfRunTests) {
    -      failures = countOfRunTests - this.successCount;
    -      suppressionMessage = ', ' +
    -          (this.totalCount - countOfRunTests) + ' suppressed by querystring';
    -    }
    -    summary += this.successCount + ' passed, ' +
    -        failures + ' failed' + suppressionMessage + '.\n' +
    -        Math.round(this.runTime / this.runCount) + ' ms/test. ' +
    -        this.numFilesLoaded + ' files loaded.';
    -  }
    -
    -  return summary;
    -};
    -
    -
    -/**
    - * Initializes the given test case with the global test runner 'G_testRunner'.
    - * @param {goog.testing.TestCase} testCase The test case to install.
    - */
    -goog.testing.TestCase.initializeTestRunner = function(testCase) {
    -  testCase.autoDiscoverTests();
    -  var gTestRunner = goog.global['G_testRunner'];
    -  if (gTestRunner) {
    -    gTestRunner['initialize'](testCase);
    -  } else {
    -    throw Error('G_testRunner is undefined. Please ensure goog.testing.jsunit' +
    -        ' is included.');
    -  }
    -};
    -
    -
    -
    -/**
    - * A class representing an error thrown by the test
    - * @param {string} source The name of the test which threw the error.
    - * @param {string} message The error message.
    - * @param {string=} opt_stack A string showing the execution stack.
    - * @constructor
    - * @final
    - */
    -goog.testing.TestCase.Error = function(source, message, opt_stack) {
    -  /**
    -   * The name of the test which threw the error.
    -   * @type {string}
    -   */
    -  this.source = source;
    -
    -  /**
    -   * Reference to the test function.
    -   * @type {string}
    -   */
    -  this.message = message;
    -
    -  /**
    -   * Scope that the test function should be called in.
    -   * @type {?string}
    -   */
    -  this.stack = opt_stack || null;
    -};
    -
    -
    -/**
    - * Returns a string representing the error object.
    - * @return {string} A string representation of the error.
    - * @override
    - */
    -goog.testing.TestCase.Error.prototype.toString = function() {
    -  return 'ERROR in ' + this.source + '\n' +
    -      this.message + (this.stack ? '\n' + this.stack : '');
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/testcase_test.js b/src/database/third_party/closure-library/closure/goog/testing/testcase_test.js
    deleted file mode 100644
    index ff70bd3b1ff..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/testcase_test.js
    +++ /dev/null
    @@ -1,276 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.TestCaseTest');
    -goog.setTestOnly('goog.testing.TestCaseTest');
    -
    -goog.require('goog.Promise');
    -goog.require('goog.testing.TestCase');
    -goog.require('goog.testing.jsunit');
    -
    -
    -// Dual of fail().
    -var ok = function() { assertTrue(true); };
    -
    -// Native Promise-based equivalent of ok().
    -var okPromise = function() { return Promise.resolve(null); };
    -
    -// Native Promise-based equivalent of fail().
    -var failPromise = function() { return Promise.reject(null); };
    -
    -// goog.Promise-based equivalent of ok().
    -var okGoogPromise = function() { return goog.Promise.resolve(null); };
    -
    -// goog.Promise-based equivalent of fail().
    -var failGoogPromise = function() { return goog.Promise.reject(null); };
    -
    -function testEmptyTestCase() {
    -  var testCase = new goog.testing.TestCase();
    -  testCase.runTests();
    -  assertTrue(testCase.isSuccess());
    -  var result = testCase.getResult();
    -  assertTrue(result.complete);
    -  assertEquals(0, result.totalCount);
    -  assertEquals(0, result.runCount);
    -  assertEquals(0, result.successCount);
    -  assertEquals(0, result.errors.length);
    -}
    -
    -function testEmptyTestCaseReturningPromise() {
    -  return new goog.testing.TestCase().runTestsReturningPromise().
    -      then(function(result) {
    -        assertTrue(result.complete);
    -        assertEquals(0, result.totalCount);
    -        assertEquals(0, result.runCount);
    -        assertEquals(0, result.successCount);
    -        assertEquals(0, result.errors.length);
    -      });
    -}
    -
    -function testTestCase_SyncSuccess() {
    -  var testCase = new goog.testing.TestCase();
    -  testCase.addNewTest('foo', ok);
    -  testCase.runTests();
    -  assertTrue(testCase.isSuccess());
    -  var result = testCase.getResult();
    -  assertTrue(result.complete);
    -  assertEquals(1, result.totalCount);
    -  assertEquals(1, result.runCount);
    -  assertEquals(1, result.successCount);
    -  assertEquals(0, result.errors.length);
    -}
    -
    -function testTestCaseReturningPromise_SyncSuccess() {
    -  var testCase = new goog.testing.TestCase();
    -  testCase.addNewTest('foo', ok);
    -  return testCase.runTestsReturningPromise().then(function(result) {
    -    assertTrue(result.complete);
    -    assertEquals(1, result.totalCount);
    -    assertEquals(1, result.runCount);
    -    assertEquals(1, result.successCount);
    -    assertEquals(0, result.errors.length);
    -  });
    -}
    -
    -function testTestCaseReturningPromise_GoogPromiseResolve() {
    -  var testCase = new goog.testing.TestCase();
    -  testCase.addNewTest('foo', okGoogPromise);
    -  return testCase.runTestsReturningPromise().then(function(result) {
    -    assertTrue(result.complete);
    -    assertEquals(1, result.totalCount);
    -    assertEquals(1, result.runCount);
    -    assertEquals(1, result.successCount);
    -    assertEquals(0, result.errors.length);
    -  });
    -}
    -
    -function testTestCaseReturningPromise_PromiseResolve() {
    -  if (!('Promise' in goog.global)) {
    -    return;
    -  }
    -  var testCase = new goog.testing.TestCase();
    -  testCase.addNewTest('foo', okPromise);
    -  return testCase.runTestsReturningPromise().then(function(result) {
    -    assertTrue(result.complete);
    -    assertEquals(1, result.totalCount);
    -    assertEquals(1, result.runCount);
    -    assertEquals(1, result.successCount);
    -    assertEquals(0, result.errors.length);
    -  });
    -}
    -
    -function testTestCase_SyncFailure() {
    -  var testCase = new goog.testing.TestCase();
    -  testCase.addNewTest('foo', fail);
    -  testCase.runTests();
    -  assertFalse(testCase.isSuccess());
    -  var result = testCase.getResult();
    -  assertTrue(result.complete);
    -  assertEquals(1, result.totalCount);
    -  assertEquals(1, result.runCount);
    -  assertEquals(0, result.successCount);
    -  assertEquals(1, result.errors.length);
    -  assertEquals('foo', result.errors[0].source);
    -}
    -
    -function testTestCaseReturningPromise_SyncFailure() {
    -  var testCase = new goog.testing.TestCase();
    -  testCase.addNewTest('foo', fail);
    -  return testCase.runTestsReturningPromise().then(function(result) {
    -    assertFalse(testCase.isSuccess());
    -    assertTrue(result.complete);
    -    assertEquals(1, result.totalCount);
    -    assertEquals(1, result.runCount);
    -    assertEquals(0, result.successCount);
    -    assertEquals(1, result.errors.length);
    -    assertEquals('foo', result.errors[0].source);
    -  });
    -}
    -
    -function testTestCaseReturningPromise_GoogPromiseReject() {
    -  var testCase = new goog.testing.TestCase();
    -  testCase.addNewTest('foo', failGoogPromise);
    -  return testCase.runTestsReturningPromise().then(function(result) {
    -    assertFalse(testCase.isSuccess());
    -    assertTrue(result.complete);
    -    assertEquals(1, result.totalCount);
    -    assertEquals(1, result.runCount);
    -    assertEquals(0, result.successCount);
    -    assertEquals(1, result.errors.length);
    -    assertEquals('foo', result.errors[0].source);
    -  });
    -}
    -
    -function testTestCaseReturningPromise_PromiseReject() {
    -  if (!('Promise' in goog.global)) {
    -    return;
    -  }
    -  var testCase = new goog.testing.TestCase();
    -  testCase.addNewTest('foo', failPromise);
    -  return testCase.runTestsReturningPromise().then(function(result) {
    -    assertFalse(testCase.isSuccess());
    -    assertTrue(result.complete);
    -    assertEquals(1, result.totalCount);
    -    assertEquals(1, result.runCount);
    -    assertEquals(0, result.successCount);
    -    assertEquals(1, result.errors.length);
    -    assertEquals('foo', result.errors[0].source);
    -  });
    -}
    -
    -function testTestCase_SyncSuccess_SyncFailure() {
    -  var testCase = new goog.testing.TestCase();
    -  testCase.addNewTest('foo', ok);
    -  testCase.addNewTest('bar', fail);
    -  testCase.runTests();
    -  assertFalse(testCase.isSuccess());
    -  var result = testCase.getResult();
    -  assertTrue(result.complete);
    -  assertEquals(2, result.totalCount);
    -  assertEquals(2, result.runCount);
    -  assertEquals(1, result.successCount);
    -  assertEquals(1, result.errors.length);
    -  assertEquals('bar', result.errors[0].source);
    -}
    -
    -function testTestCaseReturningPromise_SyncSuccess_SyncFailure() {
    -  var testCase = new goog.testing.TestCase();
    -  testCase.addNewTest('foo', ok);
    -  testCase.addNewTest('bar', fail);
    -  return testCase.runTestsReturningPromise().then(function(result) {
    -    assertTrue(result.complete);
    -    assertEquals(2, result.totalCount);
    -    assertEquals(2, result.runCount);
    -    assertEquals(1, result.successCount);
    -    assertEquals(1, result.errors.length);
    -    assertEquals('bar', result.errors[0].source);
    -  });
    -}
    -
    -function testTestCaseReturningPromise_GoogPromiseResolve_GoogPromiseReject() {
    -  var testCase = new goog.testing.TestCase();
    -  testCase.addNewTest('foo', okGoogPromise);
    -  testCase.addNewTest('bar', failGoogPromise);
    -  return testCase.runTestsReturningPromise().then(function(result) {
    -    assertTrue(result.complete);
    -    assertEquals(2, result.totalCount);
    -    assertEquals(2, result.runCount);
    -    assertEquals(1, result.successCount);
    -    assertEquals(1, result.errors.length);
    -    assertEquals('bar', result.errors[0].source);
    -  });
    -}
    -
    -function testTestCaseReturningPromise_PromiseResolve_PromiseReject() {
    -  if (!('Promise' in goog.global)) {
    -    return;
    -  }
    -  var testCase = new goog.testing.TestCase();
    -  testCase.addNewTest('foo', okPromise);
    -  testCase.addNewTest('bar', failPromise);
    -  return testCase.runTestsReturningPromise().then(function(result) {
    -    assertTrue(result.complete);
    -    assertEquals(2, result.totalCount);
    -    assertEquals(2, result.runCount);
    -    assertEquals(1, result.successCount);
    -    assertEquals(1, result.errors.length);
    -    assertEquals('bar', result.errors[0].source);
    -  });
    -}
    -
    -function testTestCaseReturningPromise_PromiseResolve_GoogPromiseReject() {
    -  if (!('Promise' in goog.global)) {
    -    return;
    -  }
    -  var testCase = new goog.testing.TestCase();
    -  testCase.addNewTest('foo', okPromise);
    -  testCase.addNewTest('bar', failGoogPromise);
    -  return testCase.runTestsReturningPromise().then(function(result) {
    -    assertTrue(result.complete);
    -    assertEquals(2, result.totalCount);
    -    assertEquals(2, result.runCount);
    -    assertEquals(1, result.successCount);
    -    assertEquals(1, result.errors.length);
    -    assertEquals('bar', result.errors[0].source);
    -  });
    -}
    -
    -function testTestCaseReturningPromise_GoogPromiseResolve_PromiseReject() {
    -  if (!('Promise' in goog.global)) {
    -    return;
    -  }
    -  var testCase = new goog.testing.TestCase();
    -  testCase.addNewTest('foo', okGoogPromise);
    -  testCase.addNewTest('bar', failPromise);
    -  return testCase.runTestsReturningPromise().then(function(result) {
    -    assertTrue(result.complete);
    -    assertEquals(2, result.totalCount);
    -    assertEquals(2, result.runCount);
    -    assertEquals(1, result.successCount);
    -    assertEquals(1, result.errors.length);
    -    assertEquals('bar', result.errors[0].source);
    -  });
    -}
    -
    -function testTestCaseNeverRun() {
    -  var testCase = new goog.testing.TestCase();
    -  testCase.addNewTest('foo', fail);
    -  // Missing testCase.runTests()
    -  var result = testCase.getResult();
    -  assertFalse(result.complete);
    -  assertEquals(0, result.totalCount);
    -  assertEquals(0, result.runCount);
    -  assertEquals(0, result.successCount);
    -  assertEquals(0, result.errors.length);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/testqueue.js b/src/database/third_party/closure-library/closure/goog/testing/testqueue.js
    deleted file mode 100644
    index 4ead7846016..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/testqueue.js
    +++ /dev/null
    @@ -1,66 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Generic queue for writing unit tests.
    - */
    -
    -goog.provide('goog.testing.TestQueue');
    -
    -
    -
    -/**
    - * Generic queue for writing unit tests
    - * @constructor
    - */
    -goog.testing.TestQueue = function() {
    -  /**
    -   * Events that have accumulated
    -   * @type {Array<Object>}
    -   * @private
    -   */
    -  this.events_ = [];
    -};
    -
    -
    -/**
    - * Adds a new event onto the queue.
    - * @param {Object} event The event to queue.
    - */
    -goog.testing.TestQueue.prototype.enqueue = function(event) {
    -  this.events_.push(event);
    -};
    -
    -
    -/**
    - * Returns whether the queue is empty.
    - * @return {boolean} Whether the queue is empty.
    - */
    -goog.testing.TestQueue.prototype.isEmpty = function() {
    -  return this.events_.length == 0;
    -};
    -
    -
    -/**
    - * Gets the next event from the queue. Throws an exception if the queue is
    - * empty.
    - * @param {string=} opt_comment Comment if the queue is empty.
    - * @return {Object} The next event from the queue.
    - */
    -goog.testing.TestQueue.prototype.dequeue = function(opt_comment) {
    -  if (this.isEmpty()) {
    -    throw Error('Handler is empty: ' + opt_comment);
    -  }
    -  return this.events_.shift();
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/testrunner.js b/src/database/third_party/closure-library/closure/goog/testing/testrunner.js
    deleted file mode 100644
    index a05041f4e79..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/testrunner.js
    +++ /dev/null
    @@ -1,439 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview The test runner is a singleton object that is used to execute
    - * a goog.testing.TestCases, display the results, and expose the results to
    - * Selenium for automation.  If a TestCase hasn't been registered with the
    - * runner by the time window.onload occurs, the testRunner will try to auto-
    - * discover JsUnit style test pages.
    - *
    - * The hooks for selenium are (see http://go/selenium-hook-setup):-
    - *  - Boolean G_testRunner.isFinished()
    - *  - Boolean G_testRunner.isSuccess()
    - *  - String G_testRunner.getReport()
    - *  - number G_testRunner.getRunTime()
    - *  - Object<string, Array<string>> G_testRunner.getTestResults()
    - *
    - * Testing code should not have dependencies outside of goog.testing so as to
    - * reduce the chance of masking missing dependencies.
    - *
    - */
    -
    -goog.provide('goog.testing.TestRunner');
    -
    -goog.require('goog.testing.TestCase');
    -
    -
    -
    -/**
    - * Construct a test runner.
    - *
    - * NOTE(user): This is currently pretty weird, I'm essentially trying to
    - * create a wrapper that the Selenium test can hook into to query the state of
    - * the running test case, while making goog.testing.TestCase general.
    - *
    - * @constructor
    - */
    -goog.testing.TestRunner = function() {
    -  /**
    -   * Errors that occurred in the window.
    -   * @type {Array<string>}
    -   */
    -  this.errors = [];
    -};
    -
    -
    -/**
    - * Reference to the active test case.
    - * @type {goog.testing.TestCase?}
    - */
    -goog.testing.TestRunner.prototype.testCase = null;
    -
    -
    -/**
    - * Whether the test runner has been initialized yet.
    - * @type {boolean}
    - */
    -goog.testing.TestRunner.prototype.initialized = false;
    -
    -
    -/**
    - * Element created in the document to add test results to.
    - * @type {Element}
    - * @private
    - */
    -goog.testing.TestRunner.prototype.logEl_ = null;
    -
    -
    -/**
    - * Function to use when filtering errors.
    - * @type {(function(string))?}
    - * @private
    - */
    -goog.testing.TestRunner.prototype.errorFilter_ = null;
    -
    -
    -/**
    - * Whether an empty test case counts as an error.
    - * @type {boolean}
    - * @private
    - */
    -goog.testing.TestRunner.prototype.strict_ = true;
    -
    -
    -/**
    - * Initializes the test runner.
    - * @param {goog.testing.TestCase} testCase The test case to initialize with.
    - */
    -goog.testing.TestRunner.prototype.initialize = function(testCase) {
    -  if (this.testCase && this.testCase.running) {
    -    throw Error('The test runner is already waiting for a test to complete');
    -  }
    -  this.testCase = testCase;
    -  this.initialized = true;
    -};
    -
    -
    -/**
    - * By default, the test runner is strict, and fails if it runs an empty
    - * test case.
    - * @param {boolean} strict Whether the test runner should fail on an empty
    - *     test case.
    - */
    -goog.testing.TestRunner.prototype.setStrict = function(strict) {
    -  this.strict_ = strict;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the test runner should fail on an empty
    - *     test case.
    - */
    -goog.testing.TestRunner.prototype.isStrict = function() {
    -  return this.strict_;
    -};
    -
    -
    -/**
    - * Returns true if the test runner is initialized.
    - * Used by Selenium Hooks.
    - * @return {boolean} Whether the test runner is active.
    - */
    -goog.testing.TestRunner.prototype.isInitialized = function() {
    -  return this.initialized;
    -};
    -
    -
    -/**
    - * Returns true if the test runner is finished.
    - * Used by Selenium Hooks.
    - * @return {boolean} Whether the test runner is active.
    - */
    -goog.testing.TestRunner.prototype.isFinished = function() {
    -  return this.errors.length > 0 ||
    -      this.initialized && !!this.testCase && this.testCase.started &&
    -      !this.testCase.running;
    -};
    -
    -
    -/**
    - * Returns true if the test case didn't fail.
    - * Used by Selenium Hooks.
    - * @return {boolean} Whether the current test returned successfully.
    - */
    -goog.testing.TestRunner.prototype.isSuccess = function() {
    -  return !this.hasErrors() && !!this.testCase && this.testCase.isSuccess();
    -};
    -
    -
    -/**
    - * Returns true if the test case runner has errors that were caught outside of
    - * the test case.
    - * @return {boolean} Whether there were JS errors.
    - */
    -goog.testing.TestRunner.prototype.hasErrors = function() {
    -  return this.errors.length > 0;
    -};
    -
    -
    -/**
    - * Logs an error that occurred.  Used in the case of environment setting up
    - * an onerror handler.
    - * @param {string} msg Error message.
    - */
    -goog.testing.TestRunner.prototype.logError = function(msg) {
    -  if (!this.errorFilter_ || this.errorFilter_.call(null, msg)) {
    -    this.errors.push(msg);
    -  }
    -};
    -
    -
    -/**
    - * Log failure in current running test.
    - * @param {Error} ex Exception.
    - */
    -goog.testing.TestRunner.prototype.logTestFailure = function(ex) {
    -  var testName = /** @type {string} */ (goog.testing.TestCase.currentTestName);
    -  if (this.testCase) {
    -    this.testCase.logError(testName, ex);
    -  } else {
    -    // NOTE: Do not forget to log the original exception raised.
    -    throw new Error('Test runner not initialized with a test case. Original ' +
    -                    'exception: ' + ex.message);
    -  }
    -};
    -
    -
    -/**
    - * Sets a function to use as a filter for errors.
    - * @param {function(string)} fn Filter function.
    - */
    -goog.testing.TestRunner.prototype.setErrorFilter = function(fn) {
    -  this.errorFilter_ = fn;
    -};
    -
    -
    -/**
    - * Returns a report of the test case that ran.
    - * Used by Selenium Hooks.
    - * @param {boolean=} opt_verbose If true results will include data about all
    - *     tests, not just what failed.
    - * @return {string} A report summary of the test.
    - */
    -goog.testing.TestRunner.prototype.getReport = function(opt_verbose) {
    -  var report = [];
    -  if (this.testCase) {
    -    report.push(this.testCase.getReport(opt_verbose));
    -  }
    -  if (this.errors.length > 0) {
    -    report.push('JavaScript errors detected by test runner:');
    -    report.push.apply(report, this.errors);
    -    report.push('\n');
    -  }
    -  return report.join('\n');
    -};
    -
    -
    -/**
    - * Returns the amount of time it took for the test to run.
    - * Used by Selenium Hooks.
    - * @return {number} The run time, in milliseconds.
    - */
    -goog.testing.TestRunner.prototype.getRunTime = function() {
    -  return this.testCase ? this.testCase.getRunTime() : 0;
    -};
    -
    -
    -/**
    - * Returns the number of script files that were loaded in order to run the test.
    - * @return {number} The number of script files.
    - */
    -goog.testing.TestRunner.prototype.getNumFilesLoaded = function() {
    -  return this.testCase ? this.testCase.getNumFilesLoaded() : 0;
    -};
    -
    -
    -/**
    - * Executes a test case and prints the results to the window.
    - */
    -goog.testing.TestRunner.prototype.execute = function() {
    -  if (!this.testCase) {
    -    throw Error('The test runner must be initialized with a test case ' +
    -                'before execute can be called.');
    -  }
    -
    -  if (this.strict_ && this.testCase.getCount() == 0) {
    -    throw Error(
    -        'No tests found in given test case: ' +
    -        this.testCase.getName() + ' ' +
    -        'By default, the test runner fails if a test case has no tests. ' +
    -        'To modify this behavior, see goog.testing.TestRunner\'s ' +
    -        'setStrict() method, or G_testRunner.setStrict()');
    -  }
    -
    -  this.testCase.setCompletedCallback(goog.bind(this.onComplete_, this));
    -  if (goog.testing.TestRunner.shouldUsePromises_(this.testCase)) {
    -    this.testCase.runTestsReturningPromise();
    -  } else {
    -    this.testCase.runTests();
    -  }
    -};
    -
    -
    -/**
    - * @param {!goog.testing.TestCase} testCase
    - * @return {boolean}
    - * @private
    - */
    -goog.testing.TestRunner.shouldUsePromises_ = function(testCase) {
    -  return testCase.constructor === goog.testing.TestCase;
    -};
    -
    -
    -/**
    - * Writes the results to the document when the test case completes.
    - * @private
    - */
    -goog.testing.TestRunner.prototype.onComplete_ = function() {
    -  var log = this.testCase.getReport(true);
    -  if (this.errors.length > 0) {
    -    log += '\n' + this.errors.join('\n');
    -  }
    -
    -  if (!this.logEl_) {
    -    var el = document.getElementById('closureTestRunnerLog');
    -    if (el == null) {
    -      el = document.createElement('div');
    -      document.body.appendChild(el);
    -    }
    -    this.logEl_ = el;
    -  }
    -
    -  // Highlight the page to indicate the overall outcome.
    -  this.writeLog(log);
    -
    -  // TODO(chrishenry): Make this work with multiple test cases (b/8603638).
    -  var runAgainLink = document.createElement('a');
    -  runAgainLink.style.display = 'inline-block';
    -  runAgainLink.style.fontSize = 'small';
    -  runAgainLink.style.marginBottom = '16px';
    -  runAgainLink.href = '';
    -  runAgainLink.onclick = goog.bind(function() {
    -    this.execute();
    -    return false;
    -  }, this);
    -  runAgainLink.innerHTML = 'Run again without reloading';
    -  this.logEl_.appendChild(runAgainLink);
    -};
    -
    -
    -/**
    - * Writes a nicely formatted log out to the document.
    - * @param {string} log The string to write.
    - */
    -goog.testing.TestRunner.prototype.writeLog = function(log) {
    -  var lines = log.split('\n');
    -  for (var i = 0; i < lines.length; i++) {
    -    var line = lines[i];
    -    var color;
    -    var isFailOrError = /FAILED/.test(line) || /ERROR/.test(line);
    -    if (/PASSED/.test(line)) {
    -      color = 'darkgreen';
    -    } else if (isFailOrError) {
    -      color = 'darkred';
    -    } else {
    -      color = '#333';
    -    }
    -    var div = document.createElement('div');
    -    if (line.substr(0, 2) == '> ') {
    -      // The stack trace may contain links so it has to be interpreted as HTML.
    -      div.innerHTML = line;
    -    } else {
    -      div.appendChild(document.createTextNode(line));
    -    }
    -
    -    var testNameMatch =
    -        /(\S+) (\[[^\]]*] )?: (FAILED|ERROR|PASSED)/.exec(line);
    -    if (testNameMatch) {
    -      // Build a URL to run the test individually.  If this test was already
    -      // part of another subset test, we need to overwrite the old runTests
    -      // query parameter.  We also need to do this without bringing in any
    -      // extra dependencies, otherwise we could mask missing dependency bugs.
    -      var newSearch = 'runTests=' + testNameMatch[1];
    -      var search = window.location.search;
    -      if (search) {
    -        var oldTests = /runTests=([^&]*)/.exec(search);
    -        if (oldTests) {
    -          newSearch = search.substr(0, oldTests.index) +
    -                      newSearch +
    -                      search.substr(oldTests.index + oldTests[0].length);
    -        } else {
    -          newSearch = search + '&' + newSearch;
    -        }
    -      } else {
    -        newSearch = '?' + newSearch;
    -      }
    -      var href = window.location.href;
    -      var hash = window.location.hash;
    -      if (hash && hash.charAt(0) != '#') {
    -        hash = '#' + hash;
    -      }
    -      href = href.split('#')[0].split('?')[0] + newSearch + hash;
    -
    -      // Add the link.
    -      var a = document.createElement('A');
    -      a.innerHTML = '(run individually)';
    -      a.style.fontSize = '0.8em';
    -      a.style.color = '#888';
    -      a.href = href;
    -      div.appendChild(document.createTextNode(' '));
    -      div.appendChild(a);
    -    }
    -
    -    div.style.color = color;
    -    div.style.font = 'normal 100% monospace';
    -    div.style.wordWrap = 'break-word';
    -    if (i == 0) {
    -      // Highlight the first line as a header that indicates the test outcome.
    -      div.style.padding = '20px';
    -      div.style.marginBottom = '10px';
    -      if (isFailOrError) {
    -        div.style.border = '5px solid ' + color;
    -        div.style.backgroundColor = '#ffeeee';
    -      } else {
    -        div.style.border = '1px solid black';
    -        div.style.backgroundColor = '#eeffee';
    -      }
    -    }
    -
    -    try {
    -      div.style.whiteSpace = 'pre-wrap';
    -    } catch (e) {
    -      // NOTE(brenneman): IE raises an exception when assigning to pre-wrap.
    -      // Thankfully, it doesn't collapse whitespace when using monospace fonts,
    -      // so it will display correctly if we ignore the exception.
    -    }
    -
    -    if (i < 2) {
    -      div.style.fontWeight = 'bold';
    -    }
    -    this.logEl_.appendChild(div);
    -  }
    -};
    -
    -
    -/**
    - * Logs a message to the current test case.
    - * @param {string} s The text to output to the log.
    - */
    -goog.testing.TestRunner.prototype.log = function(s) {
    -  if (this.testCase) {
    -    this.testCase.log(s);
    -  }
    -};
    -
    -
    -// TODO(nnaze): Properly handle serving test results when multiple test cases
    -// are run.
    -/**
    - * @return {Object<string, !Array<string>>} A map of test names to a list of
    - * test failures (if any) to provide formatted data for the test runner.
    - */
    -goog.testing.TestRunner.prototype.getTestResults = function() {
    -  if (this.testCase) {
    -    return this.testCase.getTestResults();
    -  }
    -  return null;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/ui/rendererasserts.js b/src/database/third_party/closure-library/closure/goog/testing/ui/rendererasserts.js
    deleted file mode 100644
    index 33b5b92477a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/ui/rendererasserts.js
    +++ /dev/null
    @@ -1,58 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Additional asserts for testing ControlRenderers.
    - *
    - * @author mkretzschmar@google.com (Martin Kretzschmar)
    - */
    -
    -goog.provide('goog.testing.ui.rendererasserts');
    -
    -goog.require('goog.testing.asserts');
    -goog.require('goog.ui.ControlRenderer');
    -
    -
    -/**
    - * Assert that a control renderer constructor doesn't call getCssClass.
    - *
    - * @param {?function(new:goog.ui.ControlRenderer)} rendererClassUnderTest The
    - *     renderer constructor to test.
    - */
    -goog.testing.ui.rendererasserts.assertNoGetCssClassCallsInConstructor =
    -    function(rendererClassUnderTest) {
    -  var getCssClassCalls = 0;
    -
    -  /**
    -   * @constructor
    -   * @extends {goog.ui.ControlRenderer}
    -   * @final
    -   */
    -  function TestControlRenderer() {
    -    rendererClassUnderTest.call(this);
    -  }
    -  goog.inherits(TestControlRenderer, rendererClassUnderTest);
    -
    -  /** @override */
    -  TestControlRenderer.prototype.getCssClass = function() {
    -    getCssClassCalls++;
    -    return TestControlRenderer.superClass_.getCssClass.call(this);
    -  };
    -
    -  var testControlRenderer = new TestControlRenderer();
    -
    -  assertEquals('Constructors should not call getCssClass, ' +
    -      'getCustomRenderer must be able to override it post construction.',
    -      0, getCssClassCalls);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/ui/rendererasserts_test.html b/src/database/third_party/closure-library/closure/goog/testing/ui/rendererasserts_test.html
    deleted file mode 100644
    index 287b6382e87..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/ui/rendererasserts_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -Author: mkretzschmar@google.com (Martin Kretzschmar)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.testing.ui.rendererasserts
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.ui.rendererassertsTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/ui/rendererasserts_test.js b/src/database/third_party/closure-library/closure/goog/testing/ui/rendererasserts_test.js
    deleted file mode 100644
    index b144c70e75b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/ui/rendererasserts_test.js
    +++ /dev/null
    @@ -1,46 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.ui.rendererassertsTest');
    -goog.setTestOnly('goog.testing.ui.rendererassertsTest');
    -
    -goog.require('goog.testing.asserts');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.ui.rendererasserts');
    -goog.require('goog.ui.ControlRenderer');
    -
    -function testSuccess() {
    -  function GoodRenderer() {}
    -
    -  goog.testing.ui.rendererasserts.
    -      assertNoGetCssClassCallsInConstructor(GoodRenderer);
    -}
    -
    -function testFailure() {
    -  function BadRenderer() {
    -    goog.ui.ControlRenderer.call(this);
    -    this.myClass = this.getCssClass();
    -  }
    -  goog.inherits(BadRenderer, goog.ui.ControlRenderer);
    -
    -  var ex = assertThrows(
    -      'Expected assertNoGetCssClassCallsInConstructor to fail.',
    -      function() {
    -        goog.testing.ui.rendererasserts.
    -            assertNoGetCssClassCallsInConstructor(BadRenderer);
    -      });
    -  assertTrue('Expected assertNoGetCssClassCallsInConstructor to throw a' +
    -      ' jsunit exception', ex.isJsUnitException);
    -  assertContains('getCssClass', ex.message);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/ui/rendererharness.js b/src/database/third_party/closure-library/closure/goog/testing/ui/rendererharness.js
    deleted file mode 100644
    index 43d955cf7f2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/ui/rendererharness.js
    +++ /dev/null
    @@ -1,177 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -// All Rights Reserved
    -
    -/**
    - * @fileoverview A driver for testing renderers.
    - *
    - * @author nicksantos@google.com (Nick Santos)
    - */
    -
    -goog.provide('goog.testing.ui.RendererHarness');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.dom.NodeType');
    -goog.require('goog.testing.asserts');
    -goog.require('goog.testing.dom');
    -
    -
    -
    -/**
    - * A driver for testing renderers.
    - *
    - * @param {goog.ui.ControlRenderer} renderer A renderer to test.
    - * @param {Element} renderParent The parent of the element where controls will
    - *     be rendered.
    - * @param {Element} decorateParent The parent of the element where controls will
    - *     be decorated.
    - * @constructor
    - * @extends {goog.Disposable}
    - * @final
    - */
    -goog.testing.ui.RendererHarness = function(renderer, renderParent,
    -    decorateParent) {
    -  goog.Disposable.call(this);
    -
    -  /**
    -   * The renderer under test.
    -   * @type {goog.ui.ControlRenderer}
    -   * @private
    -   */
    -  this.renderer_ = renderer;
    -
    -  /**
    -   * The parent of the element where controls will be rendered.
    -   * @type {Element}
    -   * @private
    -   */
    -  this.renderParent_ = renderParent;
    -
    -  /**
    -   * The original HTML of the render element.
    -   * @type {string}
    -   * @private
    -   */
    -  this.renderHtml_ = renderParent.innerHTML;
    -
    -  /**
    -   * Teh parent of the element where controls will be decorated.
    -   * @type {Element}
    -   * @private
    -   */
    -  this.decorateParent_ = decorateParent;
    -
    -  /**
    -   * The original HTML of the decorated element.
    -   * @type {string}
    -   * @private
    -   */
    -  this.decorateHtml_ = decorateParent.innerHTML;
    -};
    -goog.inherits(goog.testing.ui.RendererHarness, goog.Disposable);
    -
    -
    -/**
    - * A control to create by decoration.
    - * @type {goog.ui.Control}
    - * @private
    - */
    -goog.testing.ui.RendererHarness.prototype.decorateControl_;
    -
    -
    -/**
    - * A control to create by rendering.
    - * @type {goog.ui.Control}
    - * @private
    - */
    -goog.testing.ui.RendererHarness.prototype.renderControl_;
    -
    -
    -/**
    - * Whether all the necessary assert methods have been called.
    - * @type {boolean}
    - * @private
    - */
    -goog.testing.ui.RendererHarness.prototype.verified_ = false;
    -
    -
    -/**
    - * Attach a control and render its DOM.
    - * @param {goog.ui.Control} control A control.
    - * @return {Element} The element created.
    - */
    -goog.testing.ui.RendererHarness.prototype.attachControlAndRender =
    -    function(control) {
    -  this.renderControl_ = control;
    -
    -  control.setRenderer(this.renderer_);
    -  control.render(this.renderParent_);
    -  return control.getElement();
    -};
    -
    -
    -/**
    - * Attach a control and decorate the element given in the constructor.
    - * @param {goog.ui.Control} control A control.
    - * @return {Element} The element created.
    - */
    -goog.testing.ui.RendererHarness.prototype.attachControlAndDecorate =
    -    function(control) {
    -  this.decorateControl_ = control;
    -
    -  control.setRenderer(this.renderer_);
    -
    -  var child = this.decorateParent_.firstChild;
    -  assertEquals('The decorated node must be an element',
    -               goog.dom.NodeType.ELEMENT, child.nodeType);
    -  control.decorate(/** @type {!Element} */ (child));
    -  return control.getElement();
    -};
    -
    -
    -/**
    - * Assert that the rendered element and the decorated element match.
    - */
    -goog.testing.ui.RendererHarness.prototype.assertDomMatches = function() {
    -  assert('Both elements were not generated',
    -         !!(this.renderControl_ && this.decorateControl_));
    -  goog.testing.dom.assertHtmlMatches(
    -      this.renderControl_.getElement().innerHTML,
    -      this.decorateControl_.getElement().innerHTML);
    -  this.verified_ = true;
    -};
    -
    -
    -/**
    - * Destroy the harness, verifying that all assertions had been checked.
    - * @override
    - * @protected
    - */
    -goog.testing.ui.RendererHarness.prototype.disposeInternal = function() {
    -  // If the harness was not verified appropriately, throw an exception.
    -  assert('Expected assertDomMatches to be called',
    -         this.verified_ || !this.renderControl_ || !this.decorateControl_);
    -
    -  if (this.decorateControl_) {
    -    this.decorateControl_.dispose();
    -  }
    -  if (this.renderControl_) {
    -    this.renderControl_.dispose();
    -  }
    -
    -  this.renderParent_.innerHTML = this.renderHtml_;
    -  this.decorateParent_.innerHTML = this.decorateHtml_;
    -
    -  goog.testing.ui.RendererHarness.superClass_.disposeInternal.call(this);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/ui/style.js b/src/database/third_party/closure-library/closure/goog/testing/ui/style.js
    deleted file mode 100644
    index 2b162c4fd5a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/ui/style.js
    +++ /dev/null
    @@ -1,140 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Tools for testing Closure renderers against static markup
    - * spec pages.
    - *
    - */
    -
    -goog.provide('goog.testing.ui.style');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.testing.asserts');
    -
    -
    -/**
    - * Uses document.write to add an iFrame to the page with the reference path in
    - * the src attribute. Used for loading an html file containing reference
    - * structures to test against into the page. Should be called within the body of
    - * the jsunit test page.
    - * @param {string} referencePath A path to a reference HTML file.
    - */
    -goog.testing.ui.style.writeReferenceFrame = function(referencePath) {
    -  document.write('<iframe id="reference" name="reference" ' +
    -      'src="' + referencePath + '"></iframe>');
    -};
    -
    -
    -/**
    - * Returns a reference to the first element child of a node with the given id
    - * from the page loaded into the reference iFrame. Used to retrieve a particular
    - * reference DOM structure to test against.
    - * @param {string} referenceId The id of a container element for a reference
    - *   structure in the reference page.
    - * @return {Node} The root element of the reference structure.
    - */
    -goog.testing.ui.style.getReferenceNode = function(referenceId) {
    -  return goog.dom.getFirstElementChild(
    -      window.frames['reference'].document.getElementById(referenceId));
    -};
    -
    -
    -/**
    - * Returns an array of all element children of a given node.
    - * @param {Node} element The node to get element children of.
    - * @return {!Array<!Node>} An array of all the element children.
    - */
    -goog.testing.ui.style.getElementChildren = function(element) {
    -  var first = goog.dom.getFirstElementChild(element);
    -  if (!first) {
    -    return [];
    -  }
    -  var children = [first], next;
    -  while (next = goog.dom.getNextElementSibling(children[children.length - 1])) {
    -    children.push(next);
    -  }
    -  return children;
    -};
    -
    -
    -/**
    - * Tests whether a given node is a "content" node of a reference structure,
    - * which means it is allowed to have arbitrary children.
    - * @param {Node} element The node to test.
    - * @return {boolean} Whether the given node is a content node or not.
    - */
    -goog.testing.ui.style.isContentNode = function(element) {
    -  return element.className.indexOf('content') != -1;
    -};
    -
    -
    -/**
    - * Tests that the structure, node names, and classes of the given element are
    - * the same as the reference structure with the given id. Throws an error if the
    - * element doesn't have the same nodes at each level of the DOM with the same
    - * classes on each. The test ignores all DOM structure within content nodes.
    - * @param {Node} element The root node of the DOM structure to test.
    - * @param {string} referenceId The id of the container for the reference
    - *   structure to test against.
    - */
    -goog.testing.ui.style.assertStructureMatchesReference = function(element,
    -    referenceId) {
    -  goog.testing.ui.style.assertStructureMatchesReferenceInner_(element,
    -      goog.testing.ui.style.getReferenceNode(referenceId));
    -};
    -
    -
    -/**
    - * A recursive function for comparing structure, node names, and classes between
    - * a test and reference DOM structure. Throws an error if one of these things
    - * doesn't match. Used internally by
    - * {@link goog.testing.ui.style.assertStructureMatchesReference}.
    - * @param {Node} element DOM element to test.
    - * @param {Node} reference DOM element to use as a reference (test against).
    - * @private
    - */
    -goog.testing.ui.style.assertStructureMatchesReferenceInner_ = function(element,
    -    reference) {
    -  if (!element && !reference) {
    -    return;
    -  }
    -  assertTrue('Expected two elements.', !!element && !!reference);
    -  assertEquals('Expected nodes to have the same nodeName.',
    -      element.nodeName, reference.nodeName);
    -  var testElem = goog.asserts.assertElement(element);
    -  var refElem = goog.asserts.assertElement(reference);
    -  var elementClasses = goog.dom.classlist.get(testElem);
    -  goog.array.forEach(goog.dom.classlist.get(refElem), function(referenceClass) {
    -    assertContains('Expected test node to have all reference classes.',
    -        referenceClass, elementClasses);
    -  });
    -  // Call assertStructureMatchesReferenceInner_ on all element children
    -  // unless this is a content node
    -  var elChildren = goog.testing.ui.style.getElementChildren(element),
    -      refChildren = goog.testing.ui.style.getElementChildren(reference);
    -  if (!goog.testing.ui.style.isContentNode(reference)) {
    -    if (elChildren.length != refChildren.length) {
    -      assertEquals('Expected same number of children for a non-content node.',
    -          elChildren.length, refChildren.length);
    -    }
    -    for (var i = 0; i < elChildren.length; i++) {
    -      goog.testing.ui.style.assertStructureMatchesReferenceInner_(elChildren[i],
    -          refChildren[i]);
    -    }
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/ui/style_reference.html b/src/database/third_party/closure-library/closure/goog/testing/ui/style_reference.html
    deleted file mode 100644
    index c60a51ffd8c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/ui/style_reference.html
    +++ /dev/null
    @@ -1,27 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -  <title>Closure Unit Tests - goog.testing.ui.style Reference HTML</title>
    -</head>
    -<body>
    -
    -  <div id="reference">
    -    <div class="one two three">
    -      <div class="four five"></div>
    -      <div class="six seven content">
    -        Content
    -      </div>
    -    </div>
    -  </div>
    -
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/ui/style_test.html b/src/database/third_party/closure-library/closure/goog/testing/ui/style_test.html
    deleted file mode 100644
    index a657efd5e07..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/ui/style_test.html
    +++ /dev/null
    @@ -1,75 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.testing.ui.style
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.testing.ui.styleTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="correct">
    -    <div class="one two three">
    -      <div class="four five"></div>
    -      <div class="six seven content">
    -        <div></div>
    -        Blah
    -      </div>
    -    </div>
    -  </div>
    -
    -  <div id="missing-class">
    -    <div class="one two three">
    -      <div class="five"></div>
    -      <div class="six seven content">
    -        <div></div>
    -        Blah
    -      </div>
    -    </div>
    -  </div>
    -
    -  <div id="extra-class">
    -    <div class="one two three">
    -      <div class="four five five-point-five"></div>
    -      <div class="six seven content">
    -        <div></div>
    -        Blah
    -      </div>
    -    </div>
    -  </div>
    -
    -  <div id="missing-child">
    -    <div class="one two three">
    -      <div class="six seven content">
    -        <div></div>
    -        Blah
    -      </div>
    -    </div>
    -  </div>
    -
    -  <div id="extra-child">
    -    <div class="one two three">
    -      <div class="four five">
    -        <div class="five-point-five"></div>
    -      </div>
    -      <div class="six seven content">
    -        <div></div>
    -        Blah
    -      </div>
    -    </div>
    -  </div>
    -
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/ui/style_test.js b/src/database/third_party/closure-library/closure/goog/testing/ui/style_test.js
    deleted file mode 100644
    index 1d1b3aaa0f8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/ui/style_test.js
    +++ /dev/null
    @@ -1,73 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.testing.ui.styleTest');
    -goog.setTestOnly('goog.testing.ui.styleTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.ui.style');
    -
    -// Write iFrame tag to load reference FastUI markup. Then, our tests will
    -// compare the generated markup to the reference markup.
    -var refPath = 'style_reference.html';
    -goog.testing.ui.style.writeReferenceFrame(refPath);
    -
    -// assertStructureMatchesReference should succeed if the structure, node
    -// names, and classes match.
    -function testCorrect() {
    -  var el = goog.dom.getFirstElementChild(goog.dom.getElement('correct'));
    -  goog.testing.ui.style.assertStructureMatchesReference(el, 'reference');
    -}
    -
    -// assertStructureMatchesReference should fail if one of the nodes is
    -// missing a class.
    -function testMissingClass() {
    -  var el = goog.dom.getFirstElementChild(
    -      goog.dom.getElement('missing-class'));
    -  var e = assertThrows(function() {
    -    goog.testing.ui.style.assertStructureMatchesReference(el, 'reference');
    -  });
    -  assertContains('all reference classes', e.message);
    -}
    -
    -// assertStructureMatchesReference should NOT fail if one of the nodes has
    -// an additional class.
    -function testExtraClass() {
    -  var el = goog.dom.getFirstElementChild(
    -      goog.dom.getElement('extra-class'));
    -  goog.testing.ui.style.assertStructureMatchesReference(el, 'reference');
    -}
    -
    -// assertStructureMatchesReference should fail if there is a missing child
    -// node somewhere in the DOM structure.
    -function testMissingChild() {
    -  var el = goog.dom.getFirstElementChild(
    -      goog.dom.getElement('missing-child'));
    -  var e = assertThrows(function() {
    -    goog.testing.ui.style.assertStructureMatchesReference(el, 'reference');
    -  });
    -  assertContains('same number of children', e.message);
    -}
    -
    -// assertStructureMatchesReference should fail if there is an extra child
    -// node somewhere in the DOM structure.
    -function testExtraChild() {
    -  var el = goog.dom.getFirstElementChild(
    -      goog.dom.getElement('extra-child'));
    -  var e = assertThrows(function() {
    -    goog.testing.ui.style.assertStructureMatchesReference(el, 'reference');
    -  });
    -  assertContains('same number of children', e.message);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/testing/watchers.js b/src/database/third_party/closure-library/closure/goog/testing/watchers.js
    deleted file mode 100644
    index a242a57e309..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/testing/watchers.js
    +++ /dev/null
    @@ -1,46 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Simple notifiers for the Closure testing framework.
    - *
    - * @author johnlenz@google.com (John Lenz)
    - */
    -
    -goog.provide('goog.testing.watchers');
    -
    -
    -/** @private {!Array<function()>} */
    -goog.testing.watchers.resetWatchers_ = [];
    -
    -
    -/**
    - * Fires clock reset watching functions.
    - */
    -goog.testing.watchers.signalClockReset = function() {
    -  var watchers = goog.testing.watchers.resetWatchers_;
    -  for (var i = 0; i < watchers.length; i++) {
    -    goog.testing.watchers.resetWatchers_[i]();
    -  }
    -};
    -
    -
    -/**
    - * Enqueues a function to be called when the clock used for setTimeout is reset.
    - * @param {function()} fn
    - */
    -goog.testing.watchers.watchClockReset = function(fn) {
    -  goog.testing.watchers.resetWatchers_.push(fn);
    -};
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/timer/timer.js b/src/database/third_party/closure-library/closure/goog/timer/timer.js
    deleted file mode 100644
    index 19a26b68070..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/timer/timer.js
    +++ /dev/null
    @@ -1,329 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A timer class to which other classes and objects can
    - * listen on.  This is only an abstraction above setInterval.
    - *
    - * @see ../demos/timers.html
    - */
    -
    -goog.provide('goog.Timer');
    -
    -goog.require('goog.Promise');
    -goog.require('goog.events.EventTarget');
    -
    -
    -
    -/**
    - * Class for handling timing events.
    - *
    - * @param {number=} opt_interval Number of ms between ticks (Default: 1ms).
    - * @param {Object=} opt_timerObject  An object that has setTimeout, setInterval,
    - *     clearTimeout and clearInterval (eg Window).
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - */
    -goog.Timer = function(opt_interval, opt_timerObject) {
    -  goog.events.EventTarget.call(this);
    -
    -  /**
    -   * Number of ms between ticks
    -   * @type {number}
    -   * @private
    -   */
    -  this.interval_ = opt_interval || 1;
    -
    -  /**
    -   * An object that implements setTimeout, setInterval, clearTimeout and
    -   * clearInterval. We default to the window object. Changing this on
    -   * goog.Timer.prototype changes the object for all timer instances which can
    -   * be useful if your environment has some other implementation of timers than
    -   * the window object.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.timerObject_ = opt_timerObject || goog.Timer.defaultTimerObject;
    -
    -  /**
    -   * Cached tick_ bound to the object for later use in the timer.
    -   * @type {Function}
    -   * @private
    -   */
    -  this.boundTick_ = goog.bind(this.tick_, this);
    -
    -  /**
    -   * Firefox browser often fires the timer event sooner
    -   * (sometimes MUCH sooner) than the requested timeout. So we
    -   * compare the time to when the event was last fired, and
    -   * reschedule if appropriate. See also goog.Timer.intervalScale
    -   * @type {number}
    -   * @private
    -   */
    -  this.last_ = goog.now();
    -};
    -goog.inherits(goog.Timer, goog.events.EventTarget);
    -
    -
    -/**
    - * Maximum timeout value.
    - *
    - * Timeout values too big to fit into a signed 32-bit integer may cause
    - * overflow in FF, Safari, and Chrome, resulting in the timeout being
    - * scheduled immediately.  It makes more sense simply not to schedule these
    - * timeouts, since 24.8 days is beyond a reasonable expectation for the
    - * browser to stay open.
    - *
    - * @type {number}
    - * @private
    - */
    -goog.Timer.MAX_TIMEOUT_ = 2147483647;
    -
    -
    -/**
    - * A timer ID that cannot be returned by any known implmentation of
    - * Window.setTimeout.  Passing this value to window.clearTimeout should
    - * therefore be a no-op.
    - *
    - * @const {number}
    - * @private
    - */
    -goog.Timer.INVALID_TIMEOUT_ID_ = -1;
    -
    -
    -/**
    - * Whether this timer is enabled
    - * @type {boolean}
    - */
    -goog.Timer.prototype.enabled = false;
    -
    -
    -/**
    - * An object that implements setTimout, setInterval, clearTimeout and
    - * clearInterval. We default to the global object. Changing
    - * goog.Timer.defaultTimerObject changes the object for all timer instances
    - * which can be useful if your environment has some other implementation of
    - * timers you'd like to use.
    - * @type {Object}
    - */
    -goog.Timer.defaultTimerObject = goog.global;
    -
    -
    -/**
    - * A variable that controls the timer error correction. If the
    - * timer is called before the requested interval times
    - * intervalScale, which often happens on mozilla, the timer is
    - * rescheduled. See also this.last_
    - * @type {number}
    - */
    -goog.Timer.intervalScale = 0.8;
    -
    -
    -/**
    - * Variable for storing the result of setInterval
    - * @type {?number}
    - * @private
    - */
    -goog.Timer.prototype.timer_ = null;
    -
    -
    -/**
    - * Gets the interval of the timer.
    - * @return {number} interval Number of ms between ticks.
    - */
    -goog.Timer.prototype.getInterval = function() {
    -  return this.interval_;
    -};
    -
    -
    -/**
    - * Sets the interval of the timer.
    - * @param {number} interval Number of ms between ticks.
    - */
    -goog.Timer.prototype.setInterval = function(interval) {
    -  this.interval_ = interval;
    -  if (this.timer_ && this.enabled) {
    -    // Stop and then start the timer to reset the interval.
    -    this.stop();
    -    this.start();
    -  } else if (this.timer_) {
    -    this.stop();
    -  }
    -};
    -
    -
    -/**
    - * Callback for the setTimeout used by the timer
    - * @private
    - */
    -goog.Timer.prototype.tick_ = function() {
    -  if (this.enabled) {
    -    var elapsed = goog.now() - this.last_;
    -    if (elapsed > 0 &&
    -        elapsed < this.interval_ * goog.Timer.intervalScale) {
    -      this.timer_ = this.timerObject_.setTimeout(this.boundTick_,
    -          this.interval_ - elapsed);
    -      return;
    -    }
    -
    -    // Prevents setInterval from registering a duplicate timeout when called
    -    // in the timer event handler.
    -    if (this.timer_) {
    -      this.timerObject_.clearTimeout(this.timer_);
    -      this.timer_ = null;
    -    }
    -
    -    this.dispatchTick();
    -    // The timer could be stopped in the timer event handler.
    -    if (this.enabled) {
    -      this.timer_ = this.timerObject_.setTimeout(this.boundTick_,
    -          this.interval_);
    -      this.last_ = goog.now();
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Dispatches the TICK event. This is its own method so subclasses can override.
    - */
    -goog.Timer.prototype.dispatchTick = function() {
    -  this.dispatchEvent(goog.Timer.TICK);
    -};
    -
    -
    -/**
    - * Starts the timer.
    - */
    -goog.Timer.prototype.start = function() {
    -  this.enabled = true;
    -
    -  // If there is no interval already registered, start it now
    -  if (!this.timer_) {
    -    // IMPORTANT!
    -    // window.setInterval in FireFox has a bug - it fires based on
    -    // absolute time, rather than on relative time. What this means
    -    // is that if a computer is sleeping/hibernating for 24 hours
    -    // and the timer interval was configured to fire every 1000ms,
    -    // then after the PC wakes up the timer will fire, in rapid
    -    // succession, 3600*24 times.
    -    // This bug is described here and is already fixed, but it will
    -    // take time to propagate, so for now I am switching this over
    -    // to setTimeout logic.
    -    //     https://bugzilla.mozilla.org/show_bug.cgi?id=376643
    -    //
    -    this.timer_ = this.timerObject_.setTimeout(this.boundTick_,
    -        this.interval_);
    -    this.last_ = goog.now();
    -  }
    -};
    -
    -
    -/**
    - * Stops the timer.
    - */
    -goog.Timer.prototype.stop = function() {
    -  this.enabled = false;
    -  if (this.timer_) {
    -    this.timerObject_.clearTimeout(this.timer_);
    -    this.timer_ = null;
    -  }
    -};
    -
    -
    -/** @override */
    -goog.Timer.prototype.disposeInternal = function() {
    -  goog.Timer.superClass_.disposeInternal.call(this);
    -  this.stop();
    -  delete this.timerObject_;
    -};
    -
    -
    -/**
    - * Constant for the timer's event type
    - * @type {string}
    - */
    -goog.Timer.TICK = 'tick';
    -
    -
    -/**
    - * Calls the given function once, after the optional pause.
    - *
    - * The function is always called asynchronously, even if the delay is 0. This
    - * is a common trick to schedule a function to run after a batch of browser
    - * event processing.
    - *
    - * @param {function(this:SCOPE)|{handleEvent:function()}|null} listener Function
    - *     or object that has a handleEvent method.
    - * @param {number=} opt_delay Milliseconds to wait; default is 0.
    - * @param {SCOPE=} opt_handler Object in whose scope to call the listener.
    - * @return {number} A handle to the timer ID.
    - * @template SCOPE
    - */
    -goog.Timer.callOnce = function(listener, opt_delay, opt_handler) {
    -  if (goog.isFunction(listener)) {
    -    if (opt_handler) {
    -      listener = goog.bind(listener, opt_handler);
    -    }
    -  } else if (listener && typeof listener.handleEvent == 'function') {
    -    // using typeof to prevent strict js warning
    -    listener = goog.bind(listener.handleEvent, listener);
    -  } else {
    -    throw Error('Invalid listener argument');
    -  }
    -
    -  if (opt_delay > goog.Timer.MAX_TIMEOUT_) {
    -    // Timeouts greater than MAX_INT return immediately due to integer
    -    // overflow in many browsers.  Since MAX_INT is 24.8 days, just don't
    -    // schedule anything at all.
    -    return goog.Timer.INVALID_TIMEOUT_ID_;
    -  } else {
    -    return goog.Timer.defaultTimerObject.setTimeout(
    -        listener, opt_delay || 0);
    -  }
    -};
    -
    -
    -/**
    - * Clears a timeout initiated by callOnce
    - * @param {?number} timerId a timer ID.
    - */
    -goog.Timer.clear = function(timerId) {
    -  goog.Timer.defaultTimerObject.clearTimeout(timerId);
    -};
    -
    -
    -/**
    - * @param {number} delay Milliseconds to wait.
    - * @param {(RESULT|goog.Thenable<RESULT>|Thenable)=} opt_result The value
    - *     with which the promise will be resolved.
    - * @return {!goog.Promise<RESULT>} A promise that will be resolved after
    - *     the specified delay, unless it is canceled first.
    - * @template RESULT
    - */
    -goog.Timer.promise = function(delay, opt_result) {
    -  var timerKey = null;
    -  return new goog.Promise(function(resolve, reject) {
    -    timerKey = goog.Timer.callOnce(function() {
    -      resolve(opt_result);
    -    }, delay);
    -    if (timerKey == goog.Timer.INVALID_TIMEOUT_ID_) {
    -      reject(new Error('Failed to schedule timer.'));
    -    }
    -  }).thenCatch(function(error) {
    -    // Clear the timer. The most likely reason is "cancel" signal.
    -    goog.Timer.clear(timerKey);
    -    throw error;
    -  });
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/timer/timer_test.html b/src/database/third_party/closure-library/closure/goog/timer/timer_test.html
    deleted file mode 100644
    index 94513d3a687..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/timer/timer_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.Timer
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.TimerTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/timer/timer_test.js b/src/database/third_party/closure-library/closure/goog/timer/timer_test.js
    deleted file mode 100644
    index 2a03e54961b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/timer/timer_test.js
    +++ /dev/null
    @@ -1,149 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.TimerTest');
    -goog.setTestOnly('goog.TimerTest');
    -
    -goog.require('goog.Promise');
    -goog.require('goog.Timer');
    -goog.require('goog.events');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.jsunit');
    -
    -var intervalIds = {};
    -var intervalIdCounter = 0;
    -var mockClock;
    -var maxDuration = 60 * 1000; // 60s
    -
    -function setUp() {
    -  mockClock = new goog.testing.MockClock(true /* install */);
    -}
    -
    -function tearDown() {
    -  mockClock.dispose();
    -}
    -
    -// Run a test for 60s and see how many counts we get
    -function runTest(string, ticks, number) {
    -  var t = new goog.Timer(ticks);
    -  var count = 0;
    -  goog.events.listen(t, 'tick', function(evt) {
    -    count++;
    -  });
    -  t.start();
    -  mockClock.tick(maxDuration);
    -  assertEquals(string, number, count);
    -  t.stop();
    -  goog.events.removeAll(t);
    -}
    -
    -
    -function test100msTicks() {
    -  // Desc, interval in ms, expected ticks in 60s
    -  runTest('10 ticks per second for 60 seconds', 100, 600);
    -}
    -
    -function test500msTicks() {
    -  runTest('2 ticks per second for 60 seconds', 500, 120);
    -}
    -
    -function test1sTicks() {
    -  runTest('1 tick per second for 60 seconds', 1000, 60);
    -}
    -
    -function test2sTicks() {
    -  runTest('1 tick every 2 seconds for 60 seconds', 2000, 30);
    -}
    -
    -function test5sTicks() {
    -  runTest('1 tick every 5 seconds for 60 seconds', 5000, 12);
    -}
    -
    -function test10sTicks() {
    -  runTest('1 tick every 10 seconds for 60 seconds', 10000, 6);
    -}
    -
    -function test30sTicks() {
    -  runTest('1 tick every 30 seconds for 60 seconds', 30000, 2);
    -}
    -
    -function test60sTicks() {
    -  runTest('1 tick every 60 seconds', 60000, 1);
    -}
    -
    -function testCallOnce() {
    -  var c = 0;
    -  var actualTimeoutId = goog.Timer.callOnce(
    -      function() {
    -        if (c > 0) {
    -          assertTrue('callOnce should only be called once', false);
    -        }
    -        c++;
    -      });
    -  assertEquals('callOnce should return the timeout ID',
    -      mockClock.getTimeoutsMade(), actualTimeoutId);
    -
    -  var obj = {c: 0};
    -  goog.Timer.callOnce(function() {
    -    if (this.c > 0) {
    -      assertTrue('callOnce should only be called once', false);
    -    }
    -    assertEquals(obj, this);
    -    this.c++;
    -  }, 1, obj);
    -  mockClock.tick(maxDuration);
    -}
    -
    -function testCallOnceIgnoresTimeoutsTooLarge() {
    -  var failCallback = goog.partial(fail, 'Timeout should never be called');
    -  assertEquals('Timeouts slightly too large should yield a timer ID of -1',
    -      -1, goog.Timer.callOnce(failCallback, 2147483648));
    -  assertEquals('Infinite timeouts should yield a timer ID of -1',
    -      -1, goog.Timer.callOnce(failCallback, Infinity));
    -}
    -
    -function testPromise() {
    -  var c = 0;
    -  goog.Timer.promise(1, 'A').then(function(result) {
    -    c++;
    -    assertEquals('promise should return resolved value', 'A', result);
    -  });
    -  mockClock.tick(10);
    -  assertEquals('promise must be yielded once and only once', 1, c);
    -}
    -
    -function testPromise_cancel() {
    -  var c = 0;
    -  goog.Timer.promise(1, 'A').then(function(result) {
    -    fail('promise must not be resolved');
    -  }, function(reason) {
    -    c++;
    -    assertTrue('promise must fail due to cancel signal',
    -        reason instanceof goog.Promise.CancellationError);
    -  }).cancel();
    -  mockClock.tick(10);
    -  assertEquals('promise must be canceled once and only once', 1, c);
    -}
    -
    -function testPromise_timeoutTooLarge() {
    -  var c = 0;
    -  goog.Timer.promise(2147483648, 'A').then(function(result) {
    -    fail('promise must not be resolved');
    -  }, function(reason) {
    -    c++;
    -    assertTrue('promise must be rejected', reason instanceof Error);
    -  });
    -  mockClock.tick(10);
    -  assertEquals('promise must be rejected once and only once', 1, c);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/tweak/entries.js b/src/database/third_party/closure-library/closure/goog/tweak/entries.js
    deleted file mode 100644
    index 6ee7175aa6e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/tweak/entries.js
    +++ /dev/null
    @@ -1,1002 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Definitions for all tweak entries.
    - * The class hierarchy is as follows (abstract entries are denoted with a *):
    - * BaseEntry(id, description) *
    - *   -> ButtonAction(buttons in the UI)
    - *   -> BaseSetting(query parameter) *
    - *     -> BooleanGroup(child booleans)
    - *     -> BasePrimitiveSetting(value, defaultValue) *
    - *       -> BooleanSetting
    - *       -> StringSetting
    - *       -> NumericSetting
    - *       -> BooleanInGroupSetting(token)
    - * Most clients should not use these classes directly, but instead use the API
    - * defined in tweak.js. One possible use case for directly using them is to
    - * register tweaks that are not known at compile time.
    - *
    - * @author agrieve@google.com (Andrew Grieve)
    - */
    -
    -goog.provide('goog.tweak.BaseEntry');
    -goog.provide('goog.tweak.BasePrimitiveSetting');
    -goog.provide('goog.tweak.BaseSetting');
    -goog.provide('goog.tweak.BooleanGroup');
    -goog.provide('goog.tweak.BooleanInGroupSetting');
    -goog.provide('goog.tweak.BooleanSetting');
    -goog.provide('goog.tweak.ButtonAction');
    -goog.provide('goog.tweak.NumericSetting');
    -goog.provide('goog.tweak.StringSetting');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.log');
    -goog.require('goog.object');
    -
    -
    -
    -/**
    - * Base class for all Registry entries.
    - * @param {string} id The ID for the entry. Must contain only letters,
    - *     numbers, underscores and periods.
    - * @param {string} description A description of what the entry does.
    - * @constructor
    - */
    -goog.tweak.BaseEntry = function(id, description) {
    -  /**
    -   * An ID to uniquely identify the entry.
    -   * @type {string}
    -   * @private
    -   */
    -  this.id_ = id;
    -
    -  /**
    -   * A descriptive label for the entry.
    -   * @type {string}
    -   */
    -  this.label = id;
    -
    -  /**
    -   * A description of what this entry does.
    -   * @type {string}
    -   */
    -  this.description = description;
    -
    -  /**
    -   * Functions to be called whenever a setting is changed or a button is
    -   * clicked.
    -   * @type {!Array<!Function>}
    -   * @private
    -   */
    -  this.callbacks_ = [];
    -};
    -
    -
    -/**
    - * The logger for this class.
    - * @type {goog.log.Logger}
    - * @protected
    - */
    -goog.tweak.BaseEntry.prototype.logger =
    -    goog.log.getLogger('goog.tweak.BaseEntry');
    -
    -
    -/**
    - * Whether a restart is required for changes to the setting to take effect.
    - * @type {boolean}
    - * @private
    - */
    -goog.tweak.BaseEntry.prototype.restartRequired_ = true;
    -
    -
    -/**
    - * @return {string} Returns the entry's ID.
    - */
    -goog.tweak.BaseEntry.prototype.getId = function() {
    -  return this.id_;
    -};
    -
    -
    -/**
    - * Returns whether a restart is required for changes to the setting to take
    - * effect.
    - * @return {boolean} The value.
    - */
    -goog.tweak.BaseEntry.prototype.isRestartRequired = function() {
    -  return this.restartRequired_;
    -};
    -
    -
    -/**
    - * Sets whether a restart is required for changes to the setting to take
    - * effect.
    - * @param {boolean} value The new value.
    - */
    -goog.tweak.BaseEntry.prototype.setRestartRequired = function(value) {
    -  this.restartRequired_ = value;
    -};
    -
    -
    -/**
    - * Adds a callback that should be called when the setting has changed (or when
    - * an action has been clicked).
    - * @param {!Function} callback The callback to add.
    - */
    -goog.tweak.BaseEntry.prototype.addCallback = function(callback) {
    -  this.callbacks_.push(callback);
    -};
    -
    -
    -/**
    - * Removes a callback that was added by addCallback.
    - * @param {!Function} callback The callback to add.
    - */
    -goog.tweak.BaseEntry.prototype.removeCallback = function(callback) {
    -  goog.array.remove(this.callbacks_, callback);
    -};
    -
    -
    -/**
    - * Calls all registered callbacks.
    - */
    -goog.tweak.BaseEntry.prototype.fireCallbacks = function() {
    -  for (var i = 0, callback; callback = this.callbacks_[i]; ++i) {
    -    callback(this);
    -  }
    -};
    -
    -
    -
    -/**
    - * Base class for all tweak entries that are settings. Settings are entries
    - * that are associated with a query parameter.
    - * @param {string} id The ID for the setting.
    - * @param {string} description A description of what the setting does.
    - * @constructor
    - * @extends {goog.tweak.BaseEntry}
    - */
    -goog.tweak.BaseSetting = function(id, description) {
    -  goog.tweak.BaseEntry.call(this, id, description);
    -  // Apply this restriction for settings since they turn in to query
    -  // parameters. For buttons, it's not really important.
    -  goog.asserts.assert(!/[^A-Za-z0-9._]/.test(id),
    -      'Tweak id contains illegal characters: ', id);
    -
    -  /**
    -   * The value of this setting's query parameter.
    -   * @type {string|undefined}
    -   * @protected
    -   */
    -  this.initialQueryParamValue;
    -
    -  /**
    -   * The query parameter that controls this setting.
    -   * @type {?string}
    -   * @private
    -   */
    -  this.paramName_ = this.getId().toLowerCase();
    -};
    -goog.inherits(goog.tweak.BaseSetting, goog.tweak.BaseEntry);
    -
    -
    -/**
    - * States of initialization. Entries are initialized lazily in order to allow
    - * their initialization to happen in multiple statements.
    - * @enum {number}
    - * @private
    - */
    -goog.tweak.BaseSetting.InitializeState_ = {
    -  // The start state for all settings.
    -  NOT_INITIALIZED: 0,
    -  // This is used to allow concrete classes to call assertNotInitialized()
    -  // during their initialize() function.
    -  INITIALIZING: 1,
    -  // One a setting is initialized, it may no longer change its configuration
    -  // settings (associated query parameter, token, etc).
    -  INITIALIZED: 2
    -};
    -
    -
    -/**
    - * The logger for this class.
    - * @type {goog.log.Logger}
    - * @protected
    - * @override
    - */
    -goog.tweak.BaseSetting.prototype.logger =
    -    goog.log.getLogger('goog.tweak.BaseSetting');
    -
    -
    -/**
    - * Whether initialize() has been called (or is in the middle of being called).
    - * @type {goog.tweak.BaseSetting.InitializeState_}
    - * @private
    - */
    -goog.tweak.BaseSetting.prototype.initializeState_ =
    -    goog.tweak.BaseSetting.InitializeState_.NOT_INITIALIZED;
    -
    -
    -/**
    - * Sets the value of the entry based on the value of the query parameter. Once
    - * this is called, configuration settings (associated query parameter, token,
    - * etc) may not be changed.
    - * @param {?string} value The part of the query param for this setting after
    - *     the '='. Null if it is not present.
    - * @protected
    - */
    -goog.tweak.BaseSetting.prototype.initialize = goog.abstractMethod;
    -
    -
    -/**
    - * Returns the value to be used in the query parameter for this tweak.
    - * @return {?string} The encoded value. Null if the value is set to its
    - *     default.
    - */
    -goog.tweak.BaseSetting.prototype.getNewValueEncoded = goog.abstractMethod;
    -
    -
    -/**
    - * Asserts that this tweak has not been initialized yet.
    - * @param {string} funcName Function name to use in the assertion message.
    - * @protected
    - */
    -goog.tweak.BaseSetting.prototype.assertNotInitialized = function(funcName) {
    -  goog.asserts.assert(this.initializeState_ !=
    -      goog.tweak.BaseSetting.InitializeState_.INITIALIZED,
    -      'Cannot call ' + funcName + ' after the tweak as been initialized.');
    -};
    -
    -
    -/**
    - * Returns whether the setting is currently being initialized.
    - * @return {boolean} Whether the setting is currently being initialized.
    - * @protected
    - */
    -goog.tweak.BaseSetting.prototype.isInitializing = function() {
    -  return this.initializeState_ ==
    -      goog.tweak.BaseSetting.InitializeState_.INITIALIZING;
    -};
    -
    -
    -/**
    - * Sets the initial query parameter value for this setting. May not be called
    - * after the setting has been initialized.
    - * @param {string} value The inital query parameter value for this setting.
    - */
    -goog.tweak.BaseSetting.prototype.setInitialQueryParamValue = function(value) {
    -  this.assertNotInitialized('setInitialQueryParamValue');
    -  this.initialQueryParamValue = value;
    -};
    -
    -
    -/**
    - * Returns the name of the query parameter used for this setting.
    - * @return {?string} The param name. Null if no query parameter is directly
    - *     associated with the setting.
    - */
    -goog.tweak.BaseSetting.prototype.getParamName = function() {
    -  return this.paramName_;
    -};
    -
    -
    -/**
    - * Sets the name of the query parameter used for this setting. If null is
    - * passed the the setting will not appear in the top-level query string.
    - * @param {?string} value The new value.
    - */
    -goog.tweak.BaseSetting.prototype.setParamName = function(value) {
    -  this.assertNotInitialized('setParamName');
    -  this.paramName_ = value;
    -};
    -
    -
    -/**
    - * Applies the default value or query param value if this is the first time
    - * that the function has been called.
    - * @protected
    - */
    -goog.tweak.BaseSetting.prototype.ensureInitialized = function() {
    -  if (this.initializeState_ ==
    -      goog.tweak.BaseSetting.InitializeState_.NOT_INITIALIZED) {
    -    // Instead of having only initialized / not initialized, there is a
    -    // separate in-between state so that functions that call
    -    // assertNotInitialized() will not fail when called inside of the
    -    // initialize().
    -    this.initializeState_ =
    -        goog.tweak.BaseSetting.InitializeState_.INITIALIZING;
    -    var value = this.initialQueryParamValue == undefined ? null :
    -        this.initialQueryParamValue;
    -    this.initialize(value);
    -    this.initializeState_ =
    -        goog.tweak.BaseSetting.InitializeState_.INITIALIZED;
    -  }
    -};
    -
    -
    -
    -/**
    - * Base class for all settings that wrap primitive values.
    - * @param {string} id The ID for the setting.
    - * @param {string} description A description of what the setting does.
    - * @param {*} defaultValue The default value for this setting.
    - * @constructor
    - * @extends {goog.tweak.BaseSetting}
    - */
    -goog.tweak.BasePrimitiveSetting = function(id, description, defaultValue) {
    -  goog.tweak.BaseSetting.call(this, id, description);
    -  /**
    -   * The default value of the setting.
    -   * @type {*}
    -   * @private
    -   */
    -  this.defaultValue_ = defaultValue;
    -
    -  /**
    -   * The value of the tweak.
    -   * @type {*}
    -   * @private
    -   */
    -  this.value_;
    -
    -  /**
    -   * The value of the tweak once "Apply Tweaks" is pressed.
    -   * @type {*}
    -   * @private
    -   */
    -  this.newValue_;
    -};
    -goog.inherits(goog.tweak.BasePrimitiveSetting, goog.tweak.BaseSetting);
    -
    -
    -/**
    - * The logger for this class.
    - * @type {goog.log.Logger}
    - * @protected
    - * @override
    - */
    -goog.tweak.BasePrimitiveSetting.prototype.logger =
    -    goog.log.getLogger('goog.tweak.BasePrimitiveSetting');
    -
    -
    -/**
    - * Returns the query param encoded representation of the setting's value.
    - * @return {string} The encoded value.
    - * @protected
    - */
    -goog.tweak.BasePrimitiveSetting.prototype.encodeNewValue =
    -    goog.abstractMethod;
    -
    -
    -/**
    - * If the setting has the restartRequired option, then returns its inital
    - * value. Otherwise, returns its current value.
    - * @return {*} The value.
    - */
    -goog.tweak.BasePrimitiveSetting.prototype.getValue = function() {
    -  this.ensureInitialized();
    -  return this.value_;
    -};
    -
    -
    -/**
    - * Returns the value of the setting to use once "Apply Tweaks" is clicked.
    - * @return {*} The value.
    - */
    -goog.tweak.BasePrimitiveSetting.prototype.getNewValue = function() {
    -  this.ensureInitialized();
    -  return this.newValue_;
    -};
    -
    -
    -/**
    - * Sets the value of the setting. If the setting has the restartRequired
    - * option, then the value will not be changed until the "Apply Tweaks" button
    - * is clicked. If it does not have the option, the value will be update
    - * immediately and all registered callbacks will be called.
    - * @param {*} value The value.
    - */
    -goog.tweak.BasePrimitiveSetting.prototype.setValue = function(value) {
    -  this.ensureInitialized();
    -  var changed = this.newValue_ != value;
    -  this.newValue_ = value;
    -  // Don't fire callbacks if we are currently in the initialize() method.
    -  if (this.isInitializing()) {
    -    this.value_ = value;
    -  } else {
    -    if (!this.isRestartRequired()) {
    -      // Update the current value only if the tweak has been marked as not
    -      // needing a restart.
    -      this.value_ = value;
    -    }
    -    if (changed) {
    -      this.fireCallbacks();
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Returns the default value for this setting.
    - * @return {*} The default value.
    - */
    -goog.tweak.BasePrimitiveSetting.prototype.getDefaultValue = function() {
    -  return this.defaultValue_;
    -};
    -
    -
    -/**
    - * Sets the default value for the tweak.
    - * @param {*} value The new value.
    - */
    -goog.tweak.BasePrimitiveSetting.prototype.setDefaultValue =
    -    function(value) {
    -  this.assertNotInitialized('setDefaultValue');
    -  this.defaultValue_ = value;
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.tweak.BasePrimitiveSetting.prototype.getNewValueEncoded = function() {
    -  this.ensureInitialized();
    -  return this.newValue_ == this.defaultValue_ ? null : this.encodeNewValue();
    -};
    -
    -
    -
    -/**
    - * A registry setting for string values.
    - * @param {string} id The ID for the setting.
    - * @param {string} description A description of what the setting does.
    - * @constructor
    - * @extends {goog.tweak.BasePrimitiveSetting}
    - * @final
    - */
    -goog.tweak.StringSetting = function(id, description) {
    -  goog.tweak.BasePrimitiveSetting.call(this, id, description, '');
    -  /**
    -   * Valid values for the setting.
    -   * @type {Array<string>|undefined}
    -   */
    -  this.validValues_;
    -};
    -goog.inherits(goog.tweak.StringSetting, goog.tweak.BasePrimitiveSetting);
    -
    -
    -/**
    - * The logger for this class.
    - * @type {goog.log.Logger}
    - * @protected
    - * @override
    - */
    -goog.tweak.StringSetting.prototype.logger =
    -    goog.log.getLogger('goog.tweak.StringSetting');
    -
    -
    -/**
    - * @override
    - * @return {string} The tweaks's value.
    - */
    -goog.tweak.StringSetting.prototype.getValue;
    -
    -
    -/**
    - * @override
    - * @return {string} The tweaks's new value.
    - */
    -goog.tweak.StringSetting.prototype.getNewValue;
    -
    -
    -/**
    - * @override
    - * @param {string} value The tweaks's value.
    - */
    -goog.tweak.StringSetting.prototype.setValue;
    -
    -
    -/**
    - * @override
    - * @param {string} value The default value.
    - */
    -goog.tweak.StringSetting.prototype.setDefaultValue;
    -
    -
    -/**
    - * @override
    - * @return {string} The default value.
    - */
    -goog.tweak.StringSetting.prototype.getDefaultValue;
    -
    -
    -/**
    - * @override
    - */
    -goog.tweak.StringSetting.prototype.encodeNewValue = function() {
    -  return this.getNewValue();
    -};
    -
    -
    -/**
    - * Sets the valid values for the setting.
    - * @param {Array<string>|undefined} values Valid values.
    - */
    -goog.tweak.StringSetting.prototype.setValidValues = function(values) {
    -  this.assertNotInitialized('setValidValues');
    -  this.validValues_ = values;
    -  // Set the default value to the first value in the list if the current
    -  // default value is not within it.
    -  if (values && !goog.array.contains(values, this.getDefaultValue())) {
    -    this.setDefaultValue(values[0]);
    -  }
    -};
    -
    -
    -/**
    - * Returns the valid values for the setting.
    - * @return {Array<string>|undefined} Valid values.
    - */
    -goog.tweak.StringSetting.prototype.getValidValues = function() {
    -  return this.validValues_;
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.tweak.StringSetting.prototype.initialize = function(value) {
    -  if (value == null) {
    -    this.setValue(this.getDefaultValue());
    -  } else {
    -    var validValues = this.validValues_;
    -    if (validValues) {
    -      // Make the query parameter values case-insensitive since users might
    -      // type them by hand. Make the capitalization that is actual used come
    -      // from the list of valid values.
    -      value = value.toLowerCase();
    -      for (var i = 0, il = validValues.length; i < il; ++i) {
    -        if (value == validValues[i].toLowerCase()) {
    -          this.setValue(validValues[i]);
    -          return;
    -        }
    -      }
    -      // Warn if the value is not in the list of allowed values.
    -      goog.log.warning(this.logger, 'Tweak ' + this.getId() +
    -          ' has value outside of expected range:' + value);
    -    }
    -    this.setValue(value);
    -  }
    -};
    -
    -
    -
    -/**
    - * A registry setting for numeric values.
    - * @param {string} id The ID for the setting.
    - * @param {string} description A description of what the setting does.
    - * @constructor
    - * @extends {goog.tweak.BasePrimitiveSetting}
    - * @final
    - */
    -goog.tweak.NumericSetting = function(id, description) {
    -  goog.tweak.BasePrimitiveSetting.call(this, id, description, 0);
    -  /**
    -   * Valid values for the setting.
    -   * @type {Array<number>|undefined}
    -   */
    -  this.validValues_;
    -};
    -goog.inherits(goog.tweak.NumericSetting, goog.tweak.BasePrimitiveSetting);
    -
    -
    -/**
    - * The logger for this class.
    - * @type {goog.log.Logger}
    - * @protected
    - * @override
    - */
    -goog.tweak.NumericSetting.prototype.logger =
    -    goog.log.getLogger('goog.tweak.NumericSetting');
    -
    -
    -/**
    - * @override
    - * @return {number} The tweaks's value.
    - */
    -goog.tweak.NumericSetting.prototype.getValue;
    -
    -
    -/**
    - * @override
    - * @return {number} The tweaks's new value.
    - */
    -goog.tweak.NumericSetting.prototype.getNewValue;
    -
    -
    -/**
    - * @override
    - * @param {number} value The tweaks's value.
    - */
    -goog.tweak.NumericSetting.prototype.setValue;
    -
    -
    -/**
    - * @override
    - * @param {number} value The default value.
    - */
    -goog.tweak.NumericSetting.prototype.setDefaultValue;
    -
    -
    -/**
    - * @override
    - * @return {number} The default value.
    - */
    -goog.tweak.NumericSetting.prototype.getDefaultValue;
    -
    -
    -/**
    - * @override
    - */
    -goog.tweak.NumericSetting.prototype.encodeNewValue = function() {
    -  return '' + this.getNewValue();
    -};
    -
    -
    -/**
    - * Sets the valid values for the setting.
    - * @param {Array<number>|undefined} values Valid values.
    - */
    -goog.tweak.NumericSetting.prototype.setValidValues =
    -    function(values) {
    -  this.assertNotInitialized('setValidValues');
    -  this.validValues_ = values;
    -  // Set the default value to the first value in the list if the current
    -  // default value is not within it.
    -  if (values && !goog.array.contains(values, this.getDefaultValue())) {
    -    this.setDefaultValue(values[0]);
    -  }
    -};
    -
    -
    -/**
    - * Returns the valid values for the setting.
    - * @return {Array<number>|undefined} Valid values.
    - */
    -goog.tweak.NumericSetting.prototype.getValidValues = function() {
    -  return this.validValues_;
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.tweak.NumericSetting.prototype.initialize = function(value) {
    -  if (value == null) {
    -    this.setValue(this.getDefaultValue());
    -  } else {
    -    var coercedValue = +value;
    -    // Warn if the value is not in the list of allowed values.
    -    if (this.validValues_ &&
    -        !goog.array.contains(this.validValues_, coercedValue)) {
    -      goog.log.warning(this.logger, 'Tweak ' + this.getId() +
    -          ' has value outside of expected range: ' + value);
    -    }
    -
    -    if (isNaN(coercedValue)) {
    -      goog.log.warning(this.logger, 'Tweak ' + this.getId() +
    -          ' has value of NaN, resetting to ' + this.getDefaultValue());
    -      this.setValue(this.getDefaultValue());
    -    } else {
    -      this.setValue(coercedValue);
    -    }
    -  }
    -};
    -
    -
    -
    -/**
    - * A registry setting that can be either true of false.
    - * @param {string} id The ID for the setting.
    - * @param {string} description A description of what the setting does.
    - * @constructor
    - * @extends {goog.tweak.BasePrimitiveSetting}
    - */
    -goog.tweak.BooleanSetting = function(id, description) {
    -  goog.tweak.BasePrimitiveSetting.call(this, id, description, false);
    -};
    -goog.inherits(goog.tweak.BooleanSetting, goog.tweak.BasePrimitiveSetting);
    -
    -
    -/**
    - * The logger for this class.
    - * @type {goog.log.Logger}
    - * @protected
    - * @override
    - */
    -goog.tweak.BooleanSetting.prototype.logger =
    -    goog.log.getLogger('goog.tweak.BooleanSetting');
    -
    -
    -/**
    - * @override
    - * @return {boolean} The tweaks's value.
    - */
    -goog.tweak.BooleanSetting.prototype.getValue;
    -
    -
    -/**
    - * @override
    - * @return {boolean} The tweaks's new value.
    - */
    -goog.tweak.BooleanSetting.prototype.getNewValue;
    -
    -
    -/**
    - * @override
    - * @param {boolean} value The tweaks's value.
    - */
    -goog.tweak.BooleanSetting.prototype.setValue;
    -
    -
    -/**
    - * @override
    - * @param {boolean} value The default value.
    - */
    -goog.tweak.BooleanSetting.prototype.setDefaultValue;
    -
    -
    -/**
    - * @override
    - * @return {boolean} The default value.
    - */
    -goog.tweak.BooleanSetting.prototype.getDefaultValue;
    -
    -
    -/**
    - * @override
    - */
    -goog.tweak.BooleanSetting.prototype.encodeNewValue = function() {
    -  return this.getNewValue() ? '1' : '0';
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.tweak.BooleanSetting.prototype.initialize = function(value) {
    -  if (value == null) {
    -    this.setValue(this.getDefaultValue());
    -  } else {
    -    value = value.toLowerCase();
    -    this.setValue(value == 'true' || value == '1');
    -  }
    -};
    -
    -
    -
    -/**
    - * An entry in a BooleanGroup.
    - * @param {string} id The ID for the setting.
    - * @param {string} description A description of what the setting does.
    - * @param {!goog.tweak.BooleanGroup} group The group that this entry belongs
    - *     to.
    - * @constructor
    - * @extends {goog.tweak.BooleanSetting}
    - * @final
    - */
    -goog.tweak.BooleanInGroupSetting = function(id, description, group) {
    -  goog.tweak.BooleanSetting.call(this, id, description);
    -
    -  /**
    -   * The token to use in the query parameter.
    -   * @type {string}
    -   * @private
    -   */
    -  this.token_ = this.getId().toLowerCase();
    -
    -  /**
    -   * The BooleanGroup that this setting belongs to.
    -   * @type {!goog.tweak.BooleanGroup}
    -   * @private
    -   */
    -  this.group_ = group;
    -
    -  // Take setting out of top-level query parameter list.
    -  goog.tweak.BooleanInGroupSetting.superClass_.setParamName.call(this,
    -      null);
    -};
    -goog.inherits(goog.tweak.BooleanInGroupSetting, goog.tweak.BooleanSetting);
    -
    -
    -/**
    - * The logger for this class.
    - * @type {goog.log.Logger}
    - * @protected
    - * @override
    - */
    -goog.tweak.BooleanInGroupSetting.prototype.logger =
    -    goog.log.getLogger('goog.tweak.BooleanInGroupSetting');
    -
    -
    -/**
    - * @override
    - */
    -goog.tweak.BooleanInGroupSetting.prototype.setParamName = function(value) {
    -  goog.asserts.fail('Use setToken() for BooleanInGroupSetting.');
    -};
    -
    -
    -/**
    - * Sets the token to use in the query parameter.
    - * @param {string} value The value.
    - */
    -goog.tweak.BooleanInGroupSetting.prototype.setToken = function(value) {
    -  this.token_ = value;
    -};
    -
    -
    -/**
    - * Returns the token to use in the query parameter.
    - * @return {string} The value.
    - */
    -goog.tweak.BooleanInGroupSetting.prototype.getToken = function() {
    -  return this.token_;
    -};
    -
    -
    -/**
    - * Returns the BooleanGroup that this setting belongs to.
    - * @return {!goog.tweak.BooleanGroup} The BooleanGroup that this setting
    - *     belongs to.
    - */
    -goog.tweak.BooleanInGroupSetting.prototype.getGroup = function() {
    -  return this.group_;
    -};
    -
    -
    -
    -/**
    - * A registry setting that contains a group of boolean subfield, where all
    - * entries modify the same query parameter. For example:
    - *     ?foo=setting1,-setting2
    - * @param {string} id The ID for the setting.
    - * @param {string} description A description of what the setting does.
    - * @constructor
    - * @extends {goog.tweak.BaseSetting}
    - * @final
    - */
    -goog.tweak.BooleanGroup = function(id, description) {
    -  goog.tweak.BaseSetting.call(this, id, description);
    -
    -  /**
    -   * A map of token->child entry.
    -   * @type {!Object<!goog.tweak.BooleanSetting>}
    -   * @private
    -   */
    -  this.entriesByToken_ = {};
    -
    -
    -  /**
    -   * A map of token->true/false for all tokens that appeared in the query
    -   * parameter.
    -   * @type {!Object<boolean>}
    -   * @private
    -   */
    -  this.queryParamValues_ = {};
    -
    -};
    -goog.inherits(goog.tweak.BooleanGroup, goog.tweak.BaseSetting);
    -
    -
    -/**
    - * The logger for this class.
    - * @type {goog.log.Logger}
    - * @protected
    - * @override
    - */
    -goog.tweak.BooleanGroup.prototype.logger =
    -    goog.log.getLogger('goog.tweak.BooleanGroup');
    -
    -
    -/**
    - * Returns the map of token->boolean settings.
    - * @return {!Object<!goog.tweak.BooleanSetting>} The child settings.
    - */
    -goog.tweak.BooleanGroup.prototype.getChildEntries = function() {
    -  return this.entriesByToken_;
    -};
    -
    -
    -/**
    - * Adds the given BooleanSetting to the group.
    - * @param {goog.tweak.BooleanInGroupSetting} boolEntry The entry.
    - */
    -goog.tweak.BooleanGroup.prototype.addChild = function(boolEntry) {
    -  this.ensureInitialized();
    -
    -  var token = boolEntry.getToken();
    -  var lcToken = token.toLowerCase();
    -  goog.asserts.assert(!this.entriesByToken_[lcToken],
    -      'Multiple bools registered with token "%s" in group: %s', token,
    -      this.getId());
    -  this.entriesByToken_[lcToken] = boolEntry;
    -
    -  // Initialize from query param.
    -  var value = this.queryParamValues_[lcToken];
    -  if (value != undefined) {
    -    boolEntry.initialQueryParamValue = value ? '1' : '0';
    -  }
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.tweak.BooleanGroup.prototype.initialize = function(value) {
    -  var queryParamValues = {};
    -
    -  if (value) {
    -    var tokens = value.split(/\s*,\s*/);
    -    for (var i = 0; i < tokens.length; ++i) {
    -      var token = tokens[i].toLowerCase();
    -      var negative = token.charAt(0) == '-';
    -      if (negative) {
    -        token = token.substr(1);
    -      }
    -      queryParamValues[token] = !negative;
    -    }
    -  }
    -  this.queryParamValues_ = queryParamValues;
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.tweak.BooleanGroup.prototype.getNewValueEncoded = function() {
    -  this.ensureInitialized();
    -  var nonDefaultValues = [];
    -  // Sort the keys so that the generate value is stable.
    -  var keys = goog.object.getKeys(this.entriesByToken_);
    -  keys.sort();
    -  for (var i = 0, entry; entry = this.entriesByToken_[keys[i]]; ++i) {
    -    var encodedValue = entry.getNewValueEncoded();
    -    if (encodedValue != null) {
    -      nonDefaultValues.push((entry.getNewValue() ? '' : '-') +
    -          entry.getToken());
    -    }
    -  }
    -  return nonDefaultValues.length ? nonDefaultValues.join(',') : null;
    -};
    -
    -
    -
    -/**
    - * A registry action (a button).
    - * @param {string} id The ID for the setting.
    - * @param {string} description A description of what the setting does.
    - * @param {!Function} callback Function to call when the button is clicked.
    - * @constructor
    - * @extends {goog.tweak.BaseEntry}
    - * @final
    - */
    -goog.tweak.ButtonAction = function(id, description, callback) {
    -  goog.tweak.BaseEntry.call(this, id, description);
    -  this.addCallback(callback);
    -  this.setRestartRequired(false);
    -};
    -goog.inherits(goog.tweak.ButtonAction, goog.tweak.BaseEntry);
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/tweak/entries_test.html b/src/database/third_party/closure-library/closure/goog/tweak/entries_test.html
    deleted file mode 100644
    index 21919c69ed6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/tweak/entries_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<!--
    -Author: agrieve@google.com (Andrew Grieve)
    --->
    -<html>
    - <!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.tweak.BaseEntry
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.tweak.BaseEntryTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/tweak/entries_test.js b/src/database/third_party/closure-library/closure/goog/tweak/entries_test.js
    deleted file mode 100644
    index 4726291e49a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/tweak/entries_test.js
    +++ /dev/null
    @@ -1,85 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.tweak.BaseEntryTest');
    -goog.setTestOnly('goog.tweak.BaseEntryTest');
    -
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.jsunit');
    -/** @suppress {extraRequire} needed for createRegistryEntries. */
    -goog.require('goog.tweak.testhelpers');
    -
    -var mockControl;
    -
    -function setUp() {
    -  mockControl = new goog.testing.MockControl();
    -}
    -
    -function tearDown() {
    -  goog.tweak.registry_ = null;
    -  mockControl.$verifyAll();
    -}
    -
    -function testGetValue_defaultValues() {
    -  createRegistryEntries('');
    -  assertFalse('wrong initial value for bool', boolEntry.getValue());
    -  assertEquals('wrong initial value for enum', 'A', strEnumEntry.getValue());
    -  assertEquals('wrong initial value for str', '', strEntry.getValue());
    -
    -  assertEquals('wrong initial value for bool2', true, boolEntry2.getValue());
    -  assertEquals('wrong initial value for enum2', 1, numEnumEntry.getValue());
    -  assertEquals('wrong initial value for str2', 'foo', strEntry2.getValue());
    -
    -  assertFalse('wrong initial value for BoolOne', boolOneEntry.getValue());
    -  assertTrue('wrong initial value for BoolTwo', boolTwoEntry.getValue());
    -}
    -
    -function testGetValue_nonDefaultValues() {
    -  createRegistryEntries('?bool=1&enum=C');
    -  // These have the restartRequired option set.
    -  boolEntry.setValue(false);
    -  strEntry.setValue('foo');
    -  numEntry.setValue(5);
    -  assertTrue('wrong value for boolean', boolEntry.getValue());
    -  assertEquals('wrong value for string', strEntry.getDefaultValue(),
    -      strEntry.getValue());
    -  assertEquals('wrong value for num', numEntry.getDefaultValue(),
    -      numEntry.getValue());
    -
    -  // These do not have the restartRequired option set.
    -  strEnumEntry.setValue('B');
    -  boolOneEntry.setValue(true);
    -  assertEquals('wrong value for strEnum', 'B', strEnumEntry.getValue());
    -  assertEquals('wrong value for boolOne', true, boolOneEntry.getValue());
    -}
    -
    -function testCallbacks() {
    -  createRegistryEntries('');
    -  var mockCallback = mockControl.createFunctionMock();
    -  boolEntry.addCallback(mockCallback);
    -  boolOneEntry.addCallback(mockCallback);
    -  strEnumEntry.addCallback(mockCallback);
    -  numEnumEntry.addCallback(mockCallback);
    -
    -  mockCallback(boolEntry);
    -  mockCallback(boolOneEntry);
    -  mockCallback(strEnumEntry);
    -  mockCallback(numEnumEntry);
    -  mockControl.$replayAll();
    -
    -  boolEntry.setValue(true);
    -  boolOneEntry.setValue(true);
    -  strEnumEntry.setValue('C');
    -  numEnumEntry.setValue(3);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/tweak/registry.js b/src/database/third_party/closure-library/closure/goog/tweak/registry.js
    deleted file mode 100644
    index 8866e87765d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/tweak/registry.js
    +++ /dev/null
    @@ -1,315 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Definition for goog.tweak.Registry.
    - * Most clients should not use this class directly, but instead use the API
    - * defined in tweak.js. One possible use case for directly using TweakRegistry
    - * is to register tweaks that are not known at compile time.
    - *
    - * @author agrieve@google.com (Andrew Grieve)
    - */
    -
    -goog.provide('goog.tweak.Registry');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.log');
    -goog.require('goog.string');
    -goog.require('goog.tweak.BasePrimitiveSetting');
    -goog.require('goog.tweak.BaseSetting');
    -goog.require('goog.tweak.BooleanSetting');
    -goog.require('goog.tweak.NumericSetting');
    -goog.require('goog.tweak.StringSetting');
    -goog.require('goog.uri.utils');
    -
    -
    -
    -/**
    - * Singleton that manages all tweaks. This should be instantiated only from
    - * goog.tweak.getRegistry().
    - * @param {string} queryParams Value of window.location.search.
    - * @param {!Object<string|number|boolean>} compilerOverrides Default value
    - *     overrides set by the compiler.
    - * @constructor
    - * @final
    - */
    -goog.tweak.Registry = function(queryParams, compilerOverrides) {
    -  /**
    -   * A map of entry id -> entry object
    -   * @type {!Object<!goog.tweak.BaseEntry>}
    -   * @private
    -   */
    -  this.entryMap_ = {};
    -
    -  /**
    -   * The map of query params to use when initializing entry settings.
    -   * @type {!Object<string>}
    -   * @private
    -   */
    -  this.parsedQueryParams_ = goog.tweak.Registry.parseQueryParams(queryParams);
    -
    -  /**
    -   * List of callbacks to call when a new entry is registered.
    -   * @type {!Array<!Function>}
    -   * @private
    -   */
    -  this.onRegisterListeners_ = [];
    -
    -  /**
    -   * A map of entry ID -> default value override for overrides set by the
    -   * compiler.
    -   * @type {!Object<string|number|boolean>}
    -   * @private
    -   */
    -  this.compilerDefaultValueOverrides_ = compilerOverrides;
    -
    -  /**
    -   * A map of entry ID -> default value override for overrides set by
    -   * goog.tweak.overrideDefaultValue().
    -   * @type {!Object<string|number|boolean>}
    -   * @private
    -   */
    -  this.defaultValueOverrides_ = {};
    -};
    -
    -
    -/**
    - * The logger for this class.
    - * @type {goog.log.Logger}
    - * @private
    - */
    -goog.tweak.Registry.prototype.logger_ =
    -    goog.log.getLogger('goog.tweak.Registry');
    -
    -
    -/**
    - * Simple parser for query params. Makes all keys lower-case.
    - * @param {string} queryParams The part of the url between the ? and the #.
    - * @return {!Object<string>} map of key->value.
    - */
    -goog.tweak.Registry.parseQueryParams = function(queryParams) {
    -  // Strip off the leading ? and split on &.
    -  var parts = queryParams.substr(1).split('&');
    -  var ret = {};
    -
    -  for (var i = 0, il = parts.length; i < il; ++i) {
    -    var entry = parts[i].split('=');
    -    if (entry[0]) {
    -      ret[goog.string.urlDecode(entry[0]).toLowerCase()] =
    -          goog.string.urlDecode(entry[1] || '');
    -    }
    -  }
    -  return ret;
    -};
    -
    -
    -/**
    - * Registers the given tweak setting/action.
    - * @param {goog.tweak.BaseEntry} entry The entry.
    - */
    -goog.tweak.Registry.prototype.register = function(entry) {
    -  var id = entry.getId();
    -  var oldBaseEntry = this.entryMap_[id];
    -  if (oldBaseEntry) {
    -    if (oldBaseEntry == entry) {
    -      goog.log.warning(this.logger_, 'Tweak entry registered twice: ' + id);
    -      return;
    -    }
    -    goog.asserts.fail(
    -        'Tweak entry registered twice and with different types: ' + id);
    -  }
    -
    -  // Check for a default value override, either from compiler flags or from a
    -  // call to overrideDefaultValue().
    -  var defaultValueOverride = (id in this.compilerDefaultValueOverrides_) ?
    -      this.compilerDefaultValueOverrides_[id] : this.defaultValueOverrides_[id];
    -  if (goog.isDef(defaultValueOverride)) {
    -    goog.asserts.assertInstanceof(entry, goog.tweak.BasePrimitiveSetting,
    -        'Cannot set the default value of non-primitive setting %s',
    -        entry.label);
    -    entry.setDefaultValue(defaultValueOverride);
    -  }
    -
    -  // Set its value from the query params.
    -  if (entry instanceof goog.tweak.BaseSetting) {
    -    if (entry.getParamName()) {
    -      entry.setInitialQueryParamValue(
    -          this.parsedQueryParams_[entry.getParamName()]);
    -    }
    -  }
    -
    -  this.entryMap_[id] = entry;
    -  // Call all listeners.
    -  for (var i = 0, callback; callback = this.onRegisterListeners_[i]; ++i) {
    -    callback(entry);
    -  }
    -};
    -
    -
    -/**
    - * Adds a callback to be called whenever a new tweak is added.
    - * @param {!Function} func The callback.
    - */
    -goog.tweak.Registry.prototype.addOnRegisterListener = function(func) {
    -  this.onRegisterListeners_.push(func);
    -};
    -
    -
    -/**
    - * @param {string} id The unique string that identifies this entry.
    - * @return {boolean} Whether a tweak with the given ID is registered.
    - */
    -goog.tweak.Registry.prototype.hasEntry = function(id) {
    -  return id in this.entryMap_;
    -};
    -
    -
    -/**
    - * Returns the BaseEntry with the given ID. Asserts if it does not exists.
    - * @param {string} id The unique string that identifies this entry.
    - * @return {!goog.tweak.BaseEntry} The entry.
    - */
    -goog.tweak.Registry.prototype.getEntry = function(id) {
    -  var ret = this.entryMap_[id];
    -  goog.asserts.assert(ret, 'Tweak not registered: %s', id);
    -  return ret;
    -};
    -
    -
    -/**
    - * Returns the boolean setting with the given ID. Asserts if the ID does not
    - * refer to a registered entry or if it refers to one of the wrong type.
    - * @param {string} id The unique string that identifies this entry.
    - * @return {!goog.tweak.BooleanSetting} The entry.
    - */
    -goog.tweak.Registry.prototype.getBooleanSetting = function(id) {
    -  var entry = this.getEntry(id);
    -  goog.asserts.assertInstanceof(entry, goog.tweak.BooleanSetting,
    -      'getBooleanSetting called on wrong type of BaseSetting');
    -  return /** @type {!goog.tweak.BooleanSetting} */ (entry);
    -};
    -
    -
    -/**
    - * Returns the string setting with the given ID. Asserts if the ID does not
    - * refer to a registered entry or if it refers to one of the wrong type.
    - * @param {string} id The unique string that identifies this entry.
    - * @return {!goog.tweak.StringSetting} The entry.
    - */
    -goog.tweak.Registry.prototype.getStringSetting = function(id) {
    -  var entry = this.getEntry(id);
    -  goog.asserts.assertInstanceof(entry, goog.tweak.StringSetting,
    -      'getStringSetting called on wrong type of BaseSetting');
    -  return /** @type {!goog.tweak.StringSetting} */ (entry);
    -};
    -
    -
    -/**
    - * Returns the numeric setting with the given ID. Asserts if the ID does not
    - * refer to a registered entry or if it refers to one of the wrong type.
    - * @param {string} id The unique string that identifies this entry.
    - * @return {!goog.tweak.NumericSetting} The entry.
    - */
    -goog.tweak.Registry.prototype.getNumericSetting = function(id) {
    -  var entry = this.getEntry(id);
    -  goog.asserts.assertInstanceof(entry, goog.tweak.NumericSetting,
    -      'getNumericSetting called on wrong type of BaseSetting');
    -  return /** @type {!goog.tweak.NumericSetting} */ (entry);
    -};
    -
    -
    -/**
    - * Creates and returns an array of all BaseSetting objects with an associted
    - * query parameter.
    - * @param {boolean} excludeChildEntries Exclude BooleanInGroupSettings.
    - * @param {boolean} excludeNonSettings Exclude entries that are not subclasses
    - *     of BaseSetting.
    - * @return {!Array<!goog.tweak.BaseSetting>} The settings.
    - */
    -goog.tweak.Registry.prototype.extractEntries =
    -    function(excludeChildEntries, excludeNonSettings) {
    -  var entries = [];
    -  for (var id in this.entryMap_) {
    -    var entry = this.entryMap_[id];
    -    if (entry instanceof goog.tweak.BaseSetting) {
    -      if (excludeChildEntries && !entry.getParamName()) {
    -        continue;
    -      }
    -    } else if (excludeNonSettings) {
    -      continue;
    -    }
    -    entries.push(entry);
    -  }
    -  return entries;
    -};
    -
    -
    -/**
    - * Returns the query part of the URL that will apply all set tweaks.
    - * @param {string=} opt_existingSearchStr The part of the url between the ? and
    - *     the #. Uses window.location.search if not given.
    - * @return {string} The query string.
    - */
    -goog.tweak.Registry.prototype.makeUrlQuery =
    -    function(opt_existingSearchStr) {
    -  var existingParams = opt_existingSearchStr == undefined ?
    -      window.location.search : opt_existingSearchStr;
    -
    -  var sortedEntries = this.extractEntries(true /* excludeChildEntries */,
    -                                          true /* excludeNonSettings */);
    -  // Sort the params so that the urlQuery has stable ordering.
    -  sortedEntries.sort(function(a, b) {
    -    return goog.array.defaultCompare(a.getParamName(), b.getParamName());
    -  });
    -
    -  // Add all values that are not set to their defaults.
    -  var keysAndValues = [];
    -  for (var i = 0, entry; entry = sortedEntries[i]; ++i) {
    -    var encodedValue = entry.getNewValueEncoded();
    -    if (encodedValue != null) {
    -      keysAndValues.push(entry.getParamName(), encodedValue);
    -    }
    -    // Strip all tweak query params from the existing query string. This will
    -    // make the final query string contain only the tweak settings that are set
    -    // to their non-default values and also maintain non-tweak related query
    -    // parameters.
    -    existingParams = goog.uri.utils.removeParam(existingParams,
    -        encodeURIComponent(/** @type {string} */ (entry.getParamName())));
    -  }
    -
    -  var tweakParams = goog.uri.utils.buildQueryData(keysAndValues);
    -  // Decode spaces and commas in order to make the URL more readable.
    -  tweakParams = tweakParams.replace(/%2C/g, ',').replace(/%20/g, '+');
    -  return !tweakParams ? existingParams :
    -      existingParams ? existingParams + '&' + tweakParams :
    -      '?' + tweakParams;
    -};
    -
    -
    -/**
    - * Sets a default value to use for the given tweak instead of the one passed
    - * to the register* function. This function must be called before the tweak is
    - * registered.
    - * @param {string} id The unique string that identifies the entry.
    - * @param {string|number|boolean} value The replacement value to be used as the
    - *     default value for the setting.
    - */
    -goog.tweak.Registry.prototype.overrideDefaultValue = function(id, value) {
    -  goog.asserts.assert(!this.hasEntry(id),
    -      'goog.tweak.overrideDefaultValue must be called before the tweak is ' +
    -      'registered. Tweak: %s', id);
    -  this.defaultValueOverrides_[id] = value;
    -};
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/tweak/registry_test.html b/src/database/third_party/closure-library/closure/goog/tweak/registry_test.html
    deleted file mode 100644
    index 9e7cfae884d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/tweak/registry_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<!--
    -Author: agrieve@google.com (Andrew Grieve)
    --->
    -<html>
    - <!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.tweak.Registry
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.tweak.RegistryTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/tweak/registry_test.js b/src/database/third_party/closure-library/closure/goog/tweak/registry_test.js
    deleted file mode 100644
    index fda18d71965..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/tweak/registry_test.js
    +++ /dev/null
    @@ -1,137 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.tweak.RegistryTest');
    -goog.setTestOnly('goog.tweak.RegistryTest');
    -
    -goog.require('goog.asserts.AssertionError');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.tweak');
    -/** @suppress {extraRequire} needed for createRegistryEntries. */
    -goog.require('goog.tweak.testhelpers');
    -
    -var registry;
    -
    -function setUp() {
    -  createRegistryEntries('');
    -  registry = goog.tweak.getRegistry();
    -}
    -
    -function tearDown() {
    -  goog.tweak.registry_ = null;
    -}
    -
    -function testGetBaseEntry() {
    -  // Initial values
    -  assertEquals('wrong bool1 object', boolEntry,
    -      registry.getBooleanSetting('Bool'));
    -  assertEquals('wrong string object', strEntry,
    -      registry.getStringSetting('Str'));
    -  assertEquals('wrong numeric object', numEntry,
    -      registry.getNumericSetting('Num'));
    -  assertEquals('wrong button object', buttonEntry,
    -      registry.getEntry('Button'));
    -  assertEquals('wrong button object', boolGroup,
    -      registry.getEntry('BoolGroup'));
    -}
    -
    -function testInitializeFromQueryParams() {
    -  var testCase = 0;
    -  function assertQuery(queryStr, boolValue, enumValue, strValue, subBoolValue,
    -      subBoolValue2) {
    -    createRegistryEntries(queryStr);
    -    assertEquals('Wrong bool value for query: ' + queryStr, boolValue,
    -        boolEntry.getValue());
    -    assertEquals('Wrong enum value for query: ' + queryStr, enumValue,
    -        strEnumEntry.getValue());
    -    assertEquals('Wrong str value for query: ' + queryStr, strValue,
    -        strEntry.getValue());
    -    assertEquals('Wrong BoolOne value for query: ' + queryStr, subBoolValue,
    -        boolOneEntry.getValue());
    -    assertEquals('Wrong BoolTwo value for query: ' + queryStr, subBoolValue2,
    -        boolTwoEntry.getValue());
    -  }
    -  assertQuery('?dummy=1&bool=&enum=&s=', false, '', '', false, true);
    -  assertQuery('?bool=0&enum=A&s=a', false, 'A', 'a', false, true);
    -  assertQuery('?bool=1&enum=A', true, 'A', '', false, true);
    -  assertQuery('?bool=true&enum=B&s=as+df', true, 'B', 'as df', false, true);
    -  assertQuery('?enum=C', false, 'C', '', false, true);
    -  assertQuery('?enum=C&boolgroup=-booltwo', false, 'C', '', false, false);
    -  assertQuery('?enum=C&boolgroup=b1,-booltwo', false, 'C', '', true, false);
    -  assertQuery('?enum=C&boolgroup=b1', false, 'C', '', true, true);
    -  assertQuery('?s=a+b%20c%26', false, 'A', 'a b c&', false, true);
    -}
    -
    -function testMakeUrlQuery() {
    -  assertEquals('All values are default.',
    -      '', registry.makeUrlQuery(''));
    -  assertEquals('All values are default - with existing params.',
    -      '?super=pudu', registry.makeUrlQuery('?super=pudu'));
    -
    -  boolEntry.setValue(true);
    -  numEnumEntry.setValue(2);
    -  strEntry.setValue('f o&o');
    -  assertEquals('Wrong query string 1.',
    -      '?bool=1&enum2=2&s=f+o%26o',
    -      registry.makeUrlQuery('?bool=1'));
    -  assertEquals('Wrong query string 1 - with existing params.',
    -      '?super=pudu&bool=1&enum2=2&s=f+o%26o',
    -      registry.makeUrlQuery('?bool=0&s=g&super=pudu'));
    -
    -  boolOneEntry.setValue(true);
    -  assertEquals('Wrong query string 2.',
    -      '?bool=1&boolgroup=B1&enum2=2&s=f+o%26o',
    -      registry.makeUrlQuery(''));
    -
    -  boolTwoEntry.setValue(false);
    -  assertEquals('Wrong query string 3.',
    -      '?bool=1&boolgroup=B1,-booltwo&enum2=2&s=f+o%26o',
    -      registry.makeUrlQuery(''));
    -}
    -
    -function testOverrideDefaultValue_calledBefore() {
    -  registry.overrideDefaultValue('b', false);
    -  registry.overrideDefaultValue('b', true);
    -  goog.tweak.registerBoolean('b', 'b desc');
    -  var bEntry = registry.getEntry('b');
    -  assertTrue('Default value should be true.', bEntry.getDefaultValue());
    -  assertTrue('Value should be true.', bEntry.getValue());
    -}
    -
    -function testOverrideDefaultValue_calledAfter() {
    -  var exception = assertThrows('Should assert.', function() {
    -    registry.overrideDefaultValue('Bool2', false);
    -  });
    -  assertTrue('Wrong exception',
    -      exception instanceof goog.asserts.AssertionError);
    -}
    -
    -function testCompilerOverrideDefaultValue() {
    -  createRegistryEntries('', { 'b': true });
    -  registry = goog.tweak.getRegistry();
    -  goog.tweak.registerBoolean('b', 'b desc');
    -  var bEntry = registry.getEntry('b');
    -  assertTrue('Default value should be true.', bEntry.getDefaultValue());
    -  assertTrue('Value should be true.', bEntry.getValue());
    -}
    -
    -function testCompilerAndJsOverrideDefaultValue() {
    -  createRegistryEntries('', { 'b': false });
    -  registry = goog.tweak.getRegistry();
    -  registry.overrideDefaultValue('b', true);
    -  goog.tweak.registerBoolean('b', 'b desc', true);
    -  var bEntry = registry.getEntry('b');
    -  assertFalse('Default value should be false.', bEntry.getDefaultValue());
    -  assertFalse('Value should be false.', bEntry.getValue());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/tweak/testhelpers.js b/src/database/third_party/closure-library/closure/goog/tweak/testhelpers.js
    deleted file mode 100644
    index b1427d0a30a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/tweak/testhelpers.js
    +++ /dev/null
    @@ -1,123 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Common test functions for tweak unit tests.
    - *
    - * @author agrieve@google.com (Andrew Grieve)
    - * @package
    - */
    -
    -goog.provide('goog.tweak.testhelpers');
    -
    -goog.setTestOnly();
    -
    -goog.require('goog.tweak');
    -goog.require('goog.tweak.BooleanGroup');
    -goog.require('goog.tweak.BooleanInGroupSetting');
    -goog.require('goog.tweak.BooleanSetting');
    -goog.require('goog.tweak.ButtonAction');
    -goog.require('goog.tweak.NumericSetting');
    -goog.require('goog.tweak.Registry');
    -goog.require('goog.tweak.StringSetting');
    -
    -
    -var boolEntry;
    -var boolEntry2;
    -var strEntry;
    -var strEntry2;
    -var strEnumEntry;
    -var numEntry;
    -var numEnumEntry;
    -var boolGroup;
    -var boolOneEntry;
    -var boolTwoEntry;
    -var buttonEntry;
    -
    -
    -/**
    - * Creates a registry with some entries in it.
    - * @param {string} queryParams The query parameter string to use for the
    - *     registry.
    - * @param {!Object<string|number|boolean>=} opt_compilerOverrides Compiler
    - *     overrides.
    - * @suppress {accessControls} Private state is accessed for test purposes.
    - */
    -function createRegistryEntries(queryParams, opt_compilerOverrides) {
    -  // Initialize the registry with the given query string.
    -  var registry =
    -      new goog.tweak.Registry(queryParams, opt_compilerOverrides || {});
    -  goog.tweak.registry_ = registry;
    -
    -  boolEntry = new goog.tweak.BooleanSetting('Bool', 'The bool1');
    -  registry.register(boolEntry);
    -
    -  boolEntry2 = new goog.tweak.BooleanSetting('Bool2', 'The bool2');
    -  boolEntry2.setDefaultValue(true);
    -  registry.register(boolEntry2);
    -
    -  strEntry = new goog.tweak.StringSetting('Str', 'The str1');
    -  strEntry.setParamName('s');
    -  registry.register(strEntry);
    -
    -  strEntry2 = new goog.tweak.StringSetting('Str2', 'The str2');
    -  strEntry2.setDefaultValue('foo');
    -  registry.register(strEntry2);
    -
    -  strEnumEntry = new goog.tweak.StringSetting('Enum', 'The enum');
    -  strEnumEntry.setValidValues(['A', 'B', 'C']);
    -  strEnumEntry.setRestartRequired(false);
    -  registry.register(strEnumEntry);
    -
    -  numEntry = new goog.tweak.NumericSetting('Num', 'The num');
    -  numEntry.setDefaultValue(99);
    -  registry.register(numEntry);
    -
    -  numEnumEntry = new goog.tweak.NumericSetting('Enum2', 'The 2nd enum');
    -  numEnumEntry.setValidValues([1, 2, 3]);
    -  numEnumEntry.setRestartRequired(false);
    -  numEnumEntry.label = 'Enum the second&';
    -  registry.register(numEnumEntry);
    -
    -  boolGroup = new goog.tweak.BooleanGroup('BoolGroup', 'The bool group');
    -  registry.register(boolGroup);
    -
    -  boolOneEntry = new goog.tweak.BooleanInGroupSetting('BoolOne', 'Desc for 1',
    -      boolGroup);
    -  boolOneEntry.setToken('B1');
    -  boolOneEntry.setRestartRequired(false);
    -  boolGroup.addChild(boolOneEntry);
    -  registry.register(boolOneEntry);
    -
    -  boolTwoEntry = new goog.tweak.BooleanInGroupSetting('BoolTwo', 'Desc for 2',
    -      boolGroup);
    -  boolTwoEntry.setDefaultValue(true);
    -  boolGroup.addChild(boolTwoEntry);
    -  registry.register(boolTwoEntry);
    -
    -  buttonEntry = new goog.tweak.ButtonAction('Button', 'The Btn',
    -      goog.nullFunction);
    -  buttonEntry.label = '<btn>';
    -  registry.register(buttonEntry);
    -
    -  var nsBoolGroup = new goog.tweak.BooleanGroup('foo.bar.BoolGroup',
    -      'Namespaced Bool Group');
    -  registry.register(nsBoolGroup);
    -  var nsBool = new goog.tweak.BooleanInGroupSetting('foo.bar.BoolOne',
    -      'Desc for Namespaced 1', nsBoolGroup);
    -  nsBoolGroup.addChild(nsBool);
    -  registry.register(nsBool);
    -}
    -
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/tweak/tweak.js b/src/database/third_party/closure-library/closure/goog/tweak/tweak.js
    deleted file mode 100644
    index 1ba9f07e2de..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/tweak/tweak.js
    +++ /dev/null
    @@ -1,301 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides facilities for creating and querying tweaks.
    - * @see http://code.google.com/p/closure-library/wiki/UsingTweaks
    - *
    - * @author agrieve@google.com (Andrew Grieve)
    - */
    -
    -goog.provide('goog.tweak');
    -goog.provide('goog.tweak.ConfigParams');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.tweak.BaseSetting');
    -goog.require('goog.tweak.BooleanGroup');
    -goog.require('goog.tweak.BooleanInGroupSetting');
    -goog.require('goog.tweak.BooleanSetting');
    -goog.require('goog.tweak.ButtonAction');
    -goog.require('goog.tweak.NumericSetting');
    -goog.require('goog.tweak.Registry');
    -goog.require('goog.tweak.StringSetting');
    -
    -
    -/**
    - * Calls to this function are overridden by the compiler by the processTweaks
    - * pass. It returns the overrides to default values for tweaks set by compiler
    - * options.
    - * @return {!Object<number|string|boolean>} A map of tweakId -> defaultValue.
    - * @private
    - */
    -goog.tweak.getCompilerOverrides_ = function() {
    -  return {};
    -};
    -
    -
    -/**
    - * The global reference to the registry, if it exists.
    - * @type {goog.tweak.Registry}
    - * @private
    - */
    -goog.tweak.registry_ = null;
    -
    -
    -/**
    - * The boolean group set by beginBooleanGroup and cleared by endBooleanGroup.
    - * @type {goog.tweak.BooleanGroup}
    - * @private
    - */
    -goog.tweak.activeBooleanGroup_ = null;
    -
    -
    -/**
    - * Returns/creates the registry singleton.
    - * @return {!goog.tweak.Registry} The tweak registry.
    - */
    -goog.tweak.getRegistry = function() {
    -  if (!goog.tweak.registry_) {
    -    var queryString = window.location.search;
    -    var overrides = goog.tweak.getCompilerOverrides_();
    -    goog.tweak.registry_ = new goog.tweak.Registry(queryString, overrides);
    -  }
    -  return goog.tweak.registry_;
    -};
    -
    -
    -/**
    - * Type for configParams.
    - * TODO(agrieve): Remove |Object when optional fields in struct types are
    - *     implemented.
    - * @typedef {{
    - *     label:(string|undefined),
    - *     validValues:(!Array<string>|!Array<number>|undefined),
    - *     paramName:(string|undefined),
    - *     restartRequired:(boolean|undefined),
    - *     callback:(Function|undefined),
    - *     token:(string|undefined)
    - *     }|!Object}
    - */
    -goog.tweak.ConfigParams;
    -
    -
    -/**
    - * Applies all extra configuration parameters in configParams.
    - * @param {!goog.tweak.BaseEntry} entry The entry to apply them to.
    - * @param {!goog.tweak.ConfigParams} configParams Extra configuration
    - *     parameters.
    - * @private
    - */
    -goog.tweak.applyConfigParams_ = function(entry, configParams) {
    -  if (configParams.label) {
    -    entry.label = configParams.label;
    -    delete configParams.label;
    -  }
    -  if (configParams.validValues) {
    -    goog.asserts.assert(entry instanceof goog.tweak.StringSetting ||
    -        entry instanceof goog.tweak.NumericSetting,
    -        'Cannot set validValues on tweak: %s', entry.getId());
    -    entry.setValidValues(configParams.validValues);
    -    delete configParams.validValues;
    -  }
    -  if (goog.isDef(configParams.paramName)) {
    -    goog.asserts.assertInstanceof(entry, goog.tweak.BaseSetting,
    -        'Cannot set paramName on tweak: %s', entry.getId());
    -    entry.setParamName(configParams.paramName);
    -    delete configParams.paramName;
    -  }
    -  if (goog.isDef(configParams.restartRequired)) {
    -    entry.setRestartRequired(configParams.restartRequired);
    -    delete configParams.restartRequired;
    -  }
    -  if (configParams.callback) {
    -    entry.addCallback(configParams.callback);
    -    delete configParams.callback;
    -    goog.asserts.assert(
    -        !entry.isRestartRequired() || (configParams.restartRequired == false),
    -        'Tweak %s should set restartRequired: false, when adding a callback.',
    -        entry.getId());
    -  }
    -  if (configParams.token) {
    -    goog.asserts.assertInstanceof(entry, goog.tweak.BooleanInGroupSetting,
    -        'Cannot set token on tweak: %s', entry.getId());
    -    entry.setToken(configParams.token);
    -    delete configParams.token;
    -  }
    -  for (var key in configParams) {
    -    goog.asserts.fail('Unknown config options (' + key + '=' +
    -        configParams[key] + ') for tweak ' + entry.getId());
    -  }
    -};
    -
    -
    -/**
    - * Registers a tweak using the given factoryFunc.
    - * @param {!goog.tweak.BaseEntry} entry The entry to register.
    - * @param {boolean|string|number=} opt_defaultValue Default value.
    - * @param {goog.tweak.ConfigParams=} opt_configParams Extra
    - *     configuration parameters.
    - * @private
    - */
    -goog.tweak.doRegister_ = function(entry, opt_defaultValue, opt_configParams) {
    -  if (opt_configParams) {
    -    goog.tweak.applyConfigParams_(entry, opt_configParams);
    -  }
    -  if (opt_defaultValue != undefined) {
    -    entry.setDefaultValue(opt_defaultValue);
    -  }
    -  if (goog.tweak.activeBooleanGroup_) {
    -    goog.asserts.assertInstanceof(entry, goog.tweak.BooleanInGroupSetting,
    -        'Forgot to end Boolean Group: %s',
    -        goog.tweak.activeBooleanGroup_.getId());
    -    goog.tweak.activeBooleanGroup_.addChild(
    -        /** @type {!goog.tweak.BooleanInGroupSetting} */ (entry));
    -  }
    -  goog.tweak.getRegistry().register(entry);
    -};
    -
    -
    -/**
    - * Creates and registers a group of BooleanSettings that are all set by a
    - * single query parameter. A call to goog.tweak.endBooleanGroup() must be used
    - * to close this group. Only goog.tweak.registerBoolean() calls are allowed with
    - * the beginBooleanGroup()/endBooleanGroup().
    - * @param {string} id The unique ID for the setting.
    - * @param {string} description A description of what the setting does.
    - * @param {goog.tweak.ConfigParams=} opt_configParams Extra configuration
    - *     parameters.
    - */
    -goog.tweak.beginBooleanGroup = function(id, description, opt_configParams) {
    -  var entry = new goog.tweak.BooleanGroup(id, description);
    -  goog.tweak.doRegister_(entry, undefined, opt_configParams);
    -  goog.tweak.activeBooleanGroup_ = entry;
    -};
    -
    -
    -/**
    - * Stops adding boolean entries to the active boolean group.
    - */
    -goog.tweak.endBooleanGroup = function() {
    -  goog.tweak.activeBooleanGroup_ = null;
    -};
    -
    -
    -/**
    - * Creates and registers a BooleanSetting.
    - * @param {string} id The unique ID for the setting.
    - * @param {string} description A description of what the setting does.
    - * @param {boolean=} opt_defaultValue The default value for the setting.
    - * @param {goog.tweak.ConfigParams=} opt_configParams Extra configuration
    - *     parameters.
    - */
    -goog.tweak.registerBoolean =
    -    function(id, description, opt_defaultValue, opt_configParams) {
    -  // TODO(agrieve): There is a bug in the compiler that causes these calls not
    -  //     to be stripped without this outer if. Might be Issue #90.
    -  if (goog.tweak.activeBooleanGroup_) {
    -    var entry = new goog.tweak.BooleanInGroupSetting(id, description,
    -        goog.tweak.activeBooleanGroup_);
    -  } else {
    -    entry = new goog.tweak.BooleanSetting(id, description);
    -  }
    -  goog.tweak.doRegister_(entry, opt_defaultValue, opt_configParams);
    -};
    -
    -
    -/**
    - * Creates and registers a StringSetting.
    - * @param {string} id The unique ID for the setting.
    - * @param {string} description A description of what the setting does.
    - * @param {string=} opt_defaultValue The default value for the setting.
    - * @param {goog.tweak.ConfigParams=} opt_configParams Extra configuration
    - *     parameters.
    - */
    -goog.tweak.registerString =
    -    function(id, description, opt_defaultValue, opt_configParams) {
    -  goog.tweak.doRegister_(new goog.tweak.StringSetting(id, description),
    -                         opt_defaultValue, opt_configParams);
    -};
    -
    -
    -/**
    - * Creates and registers a NumericSetting.
    - * @param {string} id The unique ID for the setting.
    - * @param {string} description A description of what the setting does.
    - * @param {number=} opt_defaultValue The default value for the setting.
    - * @param {goog.tweak.ConfigParams=} opt_configParams Extra configuration
    - *     parameters.
    - */
    -goog.tweak.registerNumber =
    -    function(id, description, opt_defaultValue, opt_configParams) {
    -  goog.tweak.doRegister_(new goog.tweak.NumericSetting(id, description),
    -                         opt_defaultValue, opt_configParams);
    -};
    -
    -
    -/**
    - * Creates and registers a ButtonAction.
    - * @param {string} id The unique ID for the setting.
    - * @param {string} description A description of what the action does.
    - * @param {!Function} callback Function to call when the button is clicked.
    - * @param {string=} opt_label The button text (instead of the ID).
    - */
    -goog.tweak.registerButton = function(id, description, callback, opt_label) {
    -  var tweak = new goog.tweak.ButtonAction(id, description, callback);
    -  tweak.label = opt_label || tweak.label;
    -  goog.tweak.doRegister_(tweak);
    -};
    -
    -
    -/**
    - * Sets a default value to use for the given tweak instead of the one passed
    - * to the register* function. This function must be called before the tweak is
    - * registered.
    - * @param {string} id The unique string that identifies the entry.
    - * @param {string|number|boolean} value The new default value for the tweak.
    - */
    -goog.tweak.overrideDefaultValue = function(id, value) {
    -  goog.tweak.getRegistry().overrideDefaultValue(id, value);
    -};
    -
    -
    -/**
    - * Returns the value of the boolean setting with the given ID.
    - * @param {string} id The unique string that identifies this entry.
    - * @return {boolean} The value of the tweak.
    - */
    -goog.tweak.getBoolean = function(id) {
    -  return goog.tweak.getRegistry().getBooleanSetting(id).getValue();
    -};
    -
    -
    -/**
    - * Returns the value of the string setting with the given ID,
    - * @param {string} id The unique string that identifies this entry.
    - * @return {string} The value of the tweak.
    - */
    -goog.tweak.getString = function(id) {
    -  return goog.tweak.getRegistry().getStringSetting(id).getValue();
    -};
    -
    -
    -/**
    - * Returns the value of the numeric setting with the given ID.
    - * @param {string} id The unique string that identifies this entry.
    - * @return {number} The value of the tweak.
    - */
    -goog.tweak.getNumber = function(id) {
    -  return goog.tweak.getRegistry().getNumericSetting(id).getValue();
    -};
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/tweak/tweakui.js b/src/database/third_party/closure-library/closure/goog/tweak/tweakui.js
    deleted file mode 100644
    index 768f110ab4d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/tweak/tweakui.js
    +++ /dev/null
    @@ -1,836 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A UI for editing tweak settings / clicking tweak actions.
    - *
    - * @author agrieve@google.com (Andrew Grieve)
    - */
    -
    -goog.provide('goog.tweak.EntriesPanel');
    -goog.provide('goog.tweak.TweakUi');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.safe');
    -goog.require('goog.html.SafeHtml');
    -goog.require('goog.object');
    -goog.require('goog.string.Const');
    -goog.require('goog.style');
    -goog.require('goog.tweak');
    -goog.require('goog.tweak.BaseEntry');
    -goog.require('goog.tweak.BooleanGroup');
    -goog.require('goog.tweak.BooleanInGroupSetting');
    -goog.require('goog.tweak.BooleanSetting');
    -goog.require('goog.tweak.ButtonAction');
    -goog.require('goog.tweak.NumericSetting');
    -goog.require('goog.tweak.StringSetting');
    -goog.require('goog.ui.Zippy');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * A UI for editing tweak settings / clicking tweak actions.
    - * @param {!goog.tweak.Registry} registry The registry to render.
    - * @param {goog.dom.DomHelper=} opt_domHelper The DomHelper to render with.
    - * @constructor
    - * @final
    - */
    -goog.tweak.TweakUi = function(registry, opt_domHelper) {
    -  /**
    -   * The registry to create a UI from.
    -   * @type {!goog.tweak.Registry}
    -   * @private
    -   */
    -  this.registry_ = registry;
    -
    -  /**
    -   * The element to display when the UI is visible.
    -   * @type {goog.tweak.EntriesPanel|undefined}
    -   * @private
    -   */
    -  this.entriesPanel_;
    -
    -  /**
    -   * The DomHelper to render with.
    -   * @type {!goog.dom.DomHelper}
    -   * @private
    -   */
    -  this.domHelper_ = opt_domHelper || goog.dom.getDomHelper();
    -
    -  // Listen for newly registered entries (happens with lazy-loaded modules).
    -  registry.addOnRegisterListener(goog.bind(this.onNewRegisteredEntry_, this));
    -};
    -
    -
    -/**
    - * The CSS class name unique to the root tweak panel div.
    - * @type {string}
    - * @private
    - */
    -goog.tweak.TweakUi.ROOT_PANEL_CLASS_ = goog.getCssName('goog-tweak-root');
    -
    -
    -/**
    - * The CSS class name unique to the tweak entry div.
    - * @type {string}
    - * @private
    - */
    -goog.tweak.TweakUi.ENTRY_CSS_CLASS_ = goog.getCssName('goog-tweak-entry');
    -
    -
    -/**
    - * The CSS classes for each tweak entry div.
    - * @type {string}
    - * @private
    - */
    -goog.tweak.TweakUi.ENTRY_CSS_CLASSES_ = goog.tweak.TweakUi.ENTRY_CSS_CLASS_ +
    -    ' ' + goog.getCssName('goog-inline-block');
    -
    -
    -/**
    - * The CSS classes for each namespace tweak entry div.
    - * @type {string}
    - * @private
    - */
    -goog.tweak.TweakUi.ENTRY_GROUP_CSS_CLASSES_ =
    -    goog.tweak.TweakUi.ENTRY_CSS_CLASS_;
    -
    -
    -/**
    - * Marker that the style sheet has already been installed.
    - * @type {string}
    - * @private
    - */
    -goog.tweak.TweakUi.STYLE_SHEET_INSTALLED_MARKER_ =
    -    '__closure_tweak_installed_';
    -
    -
    -/**
    - * CSS used by TweakUI.
    - * @type {string}
    - * @private
    - */
    -goog.tweak.TweakUi.CSS_STYLES_ = (function() {
    -  var MOBILE = goog.userAgent.MOBILE;
    -  var IE = goog.userAgent.IE;
    -  var ENTRY_CLASS = '.' + goog.tweak.TweakUi.ENTRY_CSS_CLASS_;
    -  var ROOT_PANEL_CLASS = '.' + goog.tweak.TweakUi.ROOT_PANEL_CLASS_;
    -  var GOOG_INLINE_BLOCK_CLASS = '.' + goog.getCssName('goog-inline-block');
    -  var ret = ROOT_PANEL_CLASS + '{background:#ffc; padding:0 4px}';
    -  // Make this work even if the user hasn't included common.css.
    -  if (!IE) {
    -    ret += GOOG_INLINE_BLOCK_CLASS + '{display:inline-block}';
    -  }
    -  // Space things out vertically for touch UIs.
    -  if (MOBILE) {
    -    ret += ROOT_PANEL_CLASS + ',' + ROOT_PANEL_CLASS + ' fieldset{' +
    -        'line-height:2em;' + '}';
    -  }
    -  return ret;
    -})();
    -
    -
    -/**
    - * Creates a TweakUi if tweaks are enabled.
    - * @param {goog.dom.DomHelper=} opt_domHelper The DomHelper to render with.
    - * @return {!Element|undefined} The root UI element or undefined if tweaks are
    - *     not enabled.
    - */
    -goog.tweak.TweakUi.create = function(opt_domHelper) {
    -  var registry = goog.tweak.getRegistry();
    -  if (registry) {
    -    var ui = new goog.tweak.TweakUi(registry, opt_domHelper);
    -    ui.render();
    -    return ui.getRootElement();
    -  }
    -};
    -
    -
    -/**
    - * Creates a TweakUi inside of a show/hide link.
    - * @param {goog.dom.DomHelper=} opt_domHelper The DomHelper to render with.
    - * @return {!Element|undefined} The root UI element or undefined if tweaks are
    - *     not enabled.
    - */
    -goog.tweak.TweakUi.createCollapsible = function(opt_domHelper) {
    -  var registry = goog.tweak.getRegistry();
    -  if (registry) {
    -    var dh = opt_domHelper || goog.dom.getDomHelper();
    -
    -    // The following strings are for internal debugging only.  No translation
    -    // necessary.  Do NOT wrap goog.getMsg() around these strings.
    -    var showLink = dh.createDom('a', {href: 'javascript:;'}, 'Show Tweaks');
    -    var hideLink = dh.createDom('a', {href: 'javascript:;'}, 'Hide Tweaks');
    -    var ret = dh.createDom('div', null, showLink);
    -
    -    var lazyCreate = function() {
    -      // Lazily render the UI.
    -      var ui = new goog.tweak.TweakUi(
    -          /** @type {!goog.tweak.Registry} */ (registry), dh);
    -      ui.render();
    -      // Put the hide link on the same line as the "Show Descriptions" link.
    -      // Set the style lazily because we can.
    -      hideLink.style.marginRight = '10px';
    -      var tweakElem = ui.getRootElement();
    -      tweakElem.insertBefore(hideLink, tweakElem.firstChild);
    -      ret.appendChild(tweakElem);
    -      return tweakElem;
    -    };
    -    new goog.ui.Zippy(showLink, lazyCreate, false /* expanded */, hideLink);
    -    return ret;
    -  }
    -};
    -
    -
    -/**
    - * Compares the given entries. Orders alphabetically and groups buttons and
    - * expandable groups.
    - * @param {goog.tweak.BaseEntry} a The first entry to compare.
    - * @param {goog.tweak.BaseEntry} b The second entry to compare.
    - * @return {number} Refer to goog.array.defaultCompare.
    - * @private
    - */
    -goog.tweak.TweakUi.entryCompare_ = function(a, b) {
    -  return (
    -      goog.array.defaultCompare(a instanceof goog.tweak.NamespaceEntry_,
    -          b instanceof goog.tweak.NamespaceEntry_) ||
    -      goog.array.defaultCompare(a instanceof goog.tweak.BooleanGroup,
    -          b instanceof goog.tweak.BooleanGroup) ||
    -      goog.array.defaultCompare(a instanceof goog.tweak.ButtonAction,
    -          b instanceof goog.tweak.ButtonAction) ||
    -      goog.array.defaultCompare(a.label, b.label) ||
    -      goog.array.defaultCompare(a.getId(), b.getId()));
    -};
    -
    -
    -/**
    - * @param {!goog.tweak.BaseEntry} entry The entry.
    - * @return {boolean} Returns whether the given entry contains sub-entries.
    - * @private
    - */
    -goog.tweak.TweakUi.isGroupEntry_ = function(entry) {
    -  return entry instanceof goog.tweak.NamespaceEntry_ ||
    -      entry instanceof goog.tweak.BooleanGroup;
    -};
    -
    -
    -/**
    - * Returns the list of entries from the given boolean group.
    - * @param {!goog.tweak.BooleanGroup} group The group to get the entries from.
    - * @return {!Array<!goog.tweak.BaseEntry>} The sorted entries.
    - * @private
    - */
    -goog.tweak.TweakUi.extractBooleanGroupEntries_ = function(group) {
    -  var ret = goog.object.getValues(group.getChildEntries());
    -  ret.sort(goog.tweak.TweakUi.entryCompare_);
    -  return ret;
    -};
    -
    -
    -/**
    - * @param {!goog.tweak.BaseEntry} entry The entry.
    - * @return {string} Returns the namespace for the entry, or '' if it is not
    - *     namespaced.
    - * @private
    - */
    -goog.tweak.TweakUi.extractNamespace_ = function(entry) {
    -  var namespaceMatch = /.+(?=\.)/.exec(entry.getId());
    -  return namespaceMatch ? namespaceMatch[0] : '';
    -};
    -
    -
    -/**
    - * @param {!goog.tweak.BaseEntry} entry The entry.
    - * @return {string} Returns the part of the label after the last period, unless
    - *     the label has been explicly set (it is different from the ID).
    - * @private
    - */
    -goog.tweak.TweakUi.getNamespacedLabel_ = function(entry) {
    -  var label = entry.label;
    -  if (label == entry.getId()) {
    -    label = label.substr(label.lastIndexOf('.') + 1);
    -  }
    -  return label;
    -};
    -
    -
    -/**
    - * @return {!Element} The root element. Must not be called before render().
    - */
    -goog.tweak.TweakUi.prototype.getRootElement = function() {
    -  goog.asserts.assert(this.entriesPanel_,
    -      'TweakUi.getRootElement called before render().');
    -  return this.entriesPanel_.getRootElement();
    -};
    -
    -
    -/**
    - * Reloads the page with query parameters set by the UI.
    - * @private
    - */
    -goog.tweak.TweakUi.prototype.restartWithAppliedTweaks_ = function() {
    -  var queryString = this.registry_.makeUrlQuery();
    -  var wnd = this.domHelper_.getWindow();
    -  if (queryString != wnd.location.search) {
    -    wnd.location.search = queryString;
    -  } else {
    -    wnd.location.reload();
    -  }
    -};
    -
    -
    -/**
    - * Installs the required CSS styles.
    - * @private
    - */
    -goog.tweak.TweakUi.prototype.installStyles_ = function() {
    -  // Use an marker to install the styles only once per document.
    -  // Styles are injected via JS instead of in a separate style sheet so that
    -  // they are automatically excluded when tweaks are stripped out.
    -  var doc = this.domHelper_.getDocument();
    -  if (!(goog.tweak.TweakUi.STYLE_SHEET_INSTALLED_MARKER_ in doc)) {
    -    goog.style.installStyles(
    -        goog.tweak.TweakUi.CSS_STYLES_, doc);
    -    doc[goog.tweak.TweakUi.STYLE_SHEET_INSTALLED_MARKER_] = true;
    -  }
    -};
    -
    -
    -/**
    - * Creates the element to display when the UI is visible.
    - * @return {!Element} The root element.
    - */
    -goog.tweak.TweakUi.prototype.render = function() {
    -  this.installStyles_();
    -  var dh = this.domHelper_;
    -  // The submit button
    -  var submitButton = dh.createDom('button', {style: 'font-weight:bold'},
    -      'Apply Tweaks');
    -  submitButton.onclick = goog.bind(this.restartWithAppliedTweaks_, this);
    -
    -  var rootPanel = new goog.tweak.EntriesPanel([], dh);
    -  var rootPanelDiv = rootPanel.render(submitButton);
    -  rootPanelDiv.className += ' ' + goog.tweak.TweakUi.ROOT_PANEL_CLASS_;
    -  this.entriesPanel_ = rootPanel;
    -
    -  var entries = this.registry_.extractEntries(true /* excludeChildEntries */,
    -      false /* excludeNonSettings */);
    -  for (var i = 0, entry; entry = entries[i]; i++) {
    -    this.insertEntry_(entry);
    -  }
    -
    -  return rootPanelDiv;
    -};
    -
    -
    -/**
    - * Updates the UI with the given entry.
    - * @param {!goog.tweak.BaseEntry} entry The newly registered entry.
    - * @private
    - */
    -goog.tweak.TweakUi.prototype.onNewRegisteredEntry_ = function(entry) {
    -  if (this.entriesPanel_) {
    -    this.insertEntry_(entry);
    -  }
    -};
    -
    -
    -/**
    - * Updates the UI with the given entry.
    - * @param {!goog.tweak.BaseEntry} entry The newly registered entry.
    - * @private
    - */
    -goog.tweak.TweakUi.prototype.insertEntry_ = function(entry) {
    -  var panel = this.entriesPanel_;
    -  var namespace = goog.tweak.TweakUi.extractNamespace_(entry);
    -
    -  if (namespace) {
    -    // Find the NamespaceEntry that the entry belongs to.
    -    var namespaceEntryId = goog.tweak.NamespaceEntry_.ID_PREFIX + namespace;
    -    var nsPanel = panel.childPanels[namespaceEntryId];
    -    if (nsPanel) {
    -      panel = nsPanel;
    -    } else {
    -      entry = new goog.tweak.NamespaceEntry_(namespace, [entry]);
    -    }
    -  }
    -  if (entry instanceof goog.tweak.BooleanInGroupSetting) {
    -    var group = entry.getGroup();
    -    // BooleanGroup entries are always registered before their
    -    // BooleanInGroupSettings.
    -    panel = panel.childPanels[group.getId()];
    -  }
    -  goog.asserts.assert(panel, 'Missing panel for entry %s', entry.getId());
    -  panel.insertEntry(entry);
    -};
    -
    -
    -
    -/**
    - * The body of the tweaks UI and also used for BooleanGroup.
    - * @param {!Array<!goog.tweak.BaseEntry>} entries The entries to show in the
    - *     panel.
    - * @param {goog.dom.DomHelper=} opt_domHelper The DomHelper to render with.
    - * @constructor
    - * @final
    - */
    -goog.tweak.EntriesPanel = function(entries, opt_domHelper) {
    -  /**
    -   * The entries to show in the panel.
    -   * @type {!Array<!goog.tweak.BaseEntry>} entries
    -   * @private
    -   */
    -  this.entries_ = entries;
    -
    -  var self = this;
    -  /**
    -   * The bound onclick handler for the help question marks.
    -   * @this {Element}
    -   * @private
    -   */
    -  this.boundHelpOnClickHandler_ = function() {
    -    self.onHelpClick_(this.parentNode);
    -  };
    -
    -  /**
    -   * The element that contains the UI.
    -   * @type {Element}
    -   * @private
    -   */
    -  this.rootElem_;
    -
    -  /**
    -   * The element that contains all of the settings and the endElement.
    -   * @type {Element}
    -   * @private
    -   */
    -  this.mainPanel_;
    -
    -  /**
    -   * Flips between true/false each time the "Toggle Descriptions" link is
    -   * clicked.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.showAllDescriptionsState_;
    -
    -  /**
    -   * The DomHelper to render with.
    -   * @type {!goog.dom.DomHelper}
    -   * @private
    -   */
    -  this.domHelper_ = opt_domHelper || goog.dom.getDomHelper();
    -
    -  /**
    -   * Map of tweak ID -> EntriesPanel for child panels (BooleanGroups).
    -   * @type {!Object<!goog.tweak.EntriesPanel>}
    -   */
    -  this.childPanels = {};
    -};
    -
    -
    -/**
    - * @return {!Element} Returns the expanded element. Must not be called before
    - *     render().
    - */
    -goog.tweak.EntriesPanel.prototype.getRootElement = function() {
    -  goog.asserts.assert(this.rootElem_,
    -      'EntriesPanel.getRootElement called before render().');
    -  return /** @type {!Element} */ (this.rootElem_);
    -};
    -
    -
    -/**
    - * Creates and returns the expanded element.
    - * The markup looks like:
    - * <div>
    - *   <a>Show Descriptions</a>
    - *   <div>
    - *      ...
    - *      {endElement}
    - *   </div>
    - * </div>
    - * @param {Element|DocumentFragment=} opt_endElement Element to insert after all
    - *     tweak entries.
    - * @return {!Element} The root element for the panel.
    - */
    -goog.tweak.EntriesPanel.prototype.render = function(opt_endElement) {
    -  var dh = this.domHelper_;
    -  var entries = this.entries_;
    -  var ret = dh.createDom('div');
    -
    -  var showAllDescriptionsLink = dh.createDom('a', {
    -    href: 'javascript:;',
    -    onclick: goog.bind(this.toggleAllDescriptions, this)
    -  }, 'Toggle all Descriptions');
    -  ret.appendChild(showAllDescriptionsLink);
    -
    -  // Add all of the entries.
    -  var mainPanel = dh.createElement('div');
    -  this.mainPanel_ = mainPanel;
    -  for (var i = 0, entry; entry = entries[i]; i++) {
    -    mainPanel.appendChild(this.createEntryElem_(entry));
    -  }
    -
    -  if (opt_endElement) {
    -    mainPanel.appendChild(opt_endElement);
    -  }
    -  ret.appendChild(mainPanel);
    -  this.rootElem_ = ret;
    -  return /** @type {!Element} */ (ret);
    -};
    -
    -
    -/**
    - * Inserts the given entry into the panel.
    - * @param {!goog.tweak.BaseEntry} entry The entry to insert.
    - */
    -goog.tweak.EntriesPanel.prototype.insertEntry = function(entry) {
    -  var insertIndex = -goog.array.binarySearch(this.entries_, entry,
    -      goog.tweak.TweakUi.entryCompare_) - 1;
    -  goog.asserts.assert(insertIndex >= 0, 'insertEntry failed for %s',
    -      entry.getId());
    -  goog.array.insertAt(this.entries_, entry, insertIndex);
    -  this.mainPanel_.insertBefore(
    -      this.createEntryElem_(entry),
    -      // IE doesn't like 'undefined' here.
    -      this.mainPanel_.childNodes[insertIndex] || null);
    -};
    -
    -
    -/**
    - * Creates and returns a form element for the given entry.
    - * @param {!goog.tweak.BaseEntry} entry The entry.
    - * @return {!Element} The root DOM element for the entry.
    - * @private
    - */
    -goog.tweak.EntriesPanel.prototype.createEntryElem_ = function(entry) {
    -  var dh = this.domHelper_;
    -  var isGroupEntry = goog.tweak.TweakUi.isGroupEntry_(entry);
    -  var classes = isGroupEntry ? goog.tweak.TweakUi.ENTRY_GROUP_CSS_CLASSES_ :
    -      goog.tweak.TweakUi.ENTRY_CSS_CLASSES_;
    -  // Containers should not use label tags or else all descendent inputs will be
    -  // connected on desktop browsers.
    -  var containerNodeName = isGroupEntry ? 'span' : 'label';
    -  var ret = dh.createDom('div', classes,
    -      dh.createDom(containerNodeName, {
    -        // Make the hover text the description.
    -        title: entry.description,
    -        style: 'color:' + (entry.isRestartRequired() ? '' : 'blue')
    -      }, this.createTweakEntryDom_(entry)),
    -      // Add the expandable help question mark.
    -      this.createHelpElem_(entry));
    -  return ret;
    -};
    -
    -
    -/**
    - * Click handler for the help link.
    - * @param {Node} entryDiv The div that contains the tweak.
    - * @private
    - */
    -goog.tweak.EntriesPanel.prototype.onHelpClick_ = function(entryDiv) {
    -  this.showDescription_(entryDiv, !entryDiv.style.display);
    -};
    -
    -
    -/**
    - * Twiddle the DOM so that the entry within the given span is shown/hidden.
    - * @param {Node} entryDiv The div that contains the tweak.
    - * @param {boolean} show True to show, false to hide.
    - * @private
    - */
    -goog.tweak.EntriesPanel.prototype.showDescription_ =
    -    function(entryDiv, show) {
    -  var descriptionElem = entryDiv.lastChild.lastChild;
    -  goog.style.setElementShown(/** @type {Element} */ (descriptionElem), show);
    -  entryDiv.style.display = show ? 'block' : '';
    -};
    -
    -
    -/**
    - * Creates and returns a help element for the given entry.
    - * @param {goog.tweak.BaseEntry} entry The entry.
    - * @return {!Element} The root element of the created DOM.
    - * @private
    - */
    -goog.tweak.EntriesPanel.prototype.createHelpElem_ = function(entry) {
    -  // The markup looks like:
    -  // <span onclick=...><b>?</b><span>{description}</span></span>
    -  var ret = this.domHelper_.createElement('span');
    -  goog.dom.safe.setInnerHtml(ret, goog.html.SafeHtml.concat(
    -      goog.html.SafeHtml.create('b',
    -          {'style': goog.string.Const.from('padding:0 1em 0 .5em')}, '?'),
    -      goog.html.SafeHtml.create('span',
    -          {'style': goog.string.Const.from('display:none;color:#666')})));
    -  ret.onclick = this.boundHelpOnClickHandler_;
    -  // IE<9 doesn't support lastElementChild.
    -  var descriptionElem = /** @type {!Element} */ (ret.lastChild);
    -  if (entry.isRestartRequired()) {
    -    goog.dom.setTextContent(descriptionElem, entry.description);
    -  } else {
    -    goog.dom.safe.setInnerHtml(descriptionElem, goog.html.SafeHtml.concat(
    -        goog.html.SafeHtml.htmlEscape(entry.description),
    -        goog.html.SafeHtml.create('span',
    -            {'style': goog.string.Const.from('color: blue')},
    -            '(no restart required)')));
    -  }
    -  return ret;
    -};
    -
    -
    -/**
    - * Show all entry descriptions (has the same effect as clicking on all ?'s).
    - */
    -goog.tweak.EntriesPanel.prototype.toggleAllDescriptions = function() {
    -  var show = !this.showAllDescriptionsState_;
    -  this.showAllDescriptionsState_ = show;
    -  var entryDivs = this.domHelper_.getElementsByTagNameAndClass('div',
    -      goog.tweak.TweakUi.ENTRY_CSS_CLASS_, this.rootElem_);
    -  for (var i = 0, div; div = entryDivs[i]; i++) {
    -    this.showDescription_(div, show);
    -  }
    -};
    -
    -
    -/**
    - * Creates the DOM element to control the given enum setting.
    - * @param {!goog.tweak.StringSetting|!goog.tweak.NumericSetting} tweak The
    - *     setting.
    - * @param {string} label The label for the entry.
    - * @param {!Function} onchangeFunc onchange event handler.
    - * @return {!DocumentFragment} The DOM element.
    - * @private
    - */
    -goog.tweak.EntriesPanel.prototype.createComboBoxDom_ =
    -    function(tweak, label, onchangeFunc) {
    -  // The markup looks like:
    -  // Label: <select><option></option></select>
    -  var dh = this.domHelper_;
    -  var ret = dh.getDocument().createDocumentFragment();
    -  ret.appendChild(dh.createTextNode(label + ': '));
    -  var selectElem = dh.createElement('select');
    -  var values = tweak.getValidValues();
    -  for (var i = 0, il = values.length; i < il; ++i) {
    -    var optionElem = dh.createElement('option');
    -    optionElem.text = String(values[i]);
    -    // Setting the option tag's value is required for selectElem.value to work
    -    // properly.
    -    optionElem.value = String(values[i]);
    -    selectElem.appendChild(optionElem);
    -  }
    -  ret.appendChild(selectElem);
    -
    -  // Set the value and add a callback.
    -  selectElem.value = tweak.getNewValue();
    -  selectElem.onchange = onchangeFunc;
    -  tweak.addCallback(function() {
    -    selectElem.value = tweak.getNewValue();
    -  });
    -  return ret;
    -};
    -
    -
    -/**
    - * Creates the DOM element to control the given boolean setting.
    - * @param {!goog.tweak.BooleanSetting} tweak The setting.
    - * @param {string} label The label for the entry.
    - * @return {!DocumentFragment} The DOM elements.
    - * @private
    - */
    -goog.tweak.EntriesPanel.prototype.createBooleanSettingDom_ =
    -    function(tweak, label) {
    -  var dh = this.domHelper_;
    -  var ret = dh.getDocument().createDocumentFragment();
    -  var checkbox = dh.createDom('input', {type: 'checkbox'});
    -  ret.appendChild(checkbox);
    -  ret.appendChild(dh.createTextNode(label));
    -
    -  // Needed on IE6 to ensure the textbox doesn't get cleared
    -  // when added to the DOM.
    -  checkbox.defaultChecked = tweak.getNewValue();
    -
    -  checkbox.checked = tweak.getNewValue();
    -  checkbox.onchange = function() {
    -    tweak.setValue(checkbox.checked);
    -  };
    -  tweak.addCallback(function() {
    -    checkbox.checked = tweak.getNewValue();
    -  });
    -  return ret;
    -};
    -
    -
    -/**
    - * Creates the DOM for a BooleanGroup or NamespaceEntry.
    - * @param {!goog.tweak.BooleanGroup|!goog.tweak.NamespaceEntry_} entry The
    - *     entry.
    - * @param {string} label The label for the entry.
    - * @param {!Array<goog.tweak.BaseEntry>} childEntries The child entries.
    - * @return {!DocumentFragment} The DOM element.
    - * @private
    - */
    -goog.tweak.EntriesPanel.prototype.createSubPanelDom_ = function(entry, label,
    -    childEntries) {
    -  var dh = this.domHelper_;
    -  var toggleLink = dh.createDom('a', {href: 'javascript:;'},
    -      label + ' \xBB');
    -  var toggleLink2 = dh.createDom('a', {href: 'javascript:;'},
    -      '\xAB ' + label);
    -  toggleLink2.style.marginRight = '10px';
    -
    -  var innerUi = new goog.tweak.EntriesPanel(childEntries, dh);
    -  this.childPanels[entry.getId()] = innerUi;
    -
    -  var elem = innerUi.render();
    -  // Move the toggle descriptions link into the legend.
    -  var descriptionsLink = elem.firstChild;
    -  var childrenElem = dh.createDom('fieldset',
    -      goog.getCssName('goog-inline-block'),
    -      dh.createDom('legend', null, toggleLink2, descriptionsLink),
    -      elem);
    -
    -  new goog.ui.Zippy(toggleLink, childrenElem, false /* expanded */,
    -      toggleLink2);
    -
    -  var ret = dh.getDocument().createDocumentFragment();
    -  ret.appendChild(toggleLink);
    -  ret.appendChild(childrenElem);
    -  return ret;
    -};
    -
    -
    -/**
    - * Creates the DOM element to control the given string setting.
    - * @param {!goog.tweak.StringSetting|!goog.tweak.NumericSetting} tweak The
    - *     setting.
    - * @param {string} label The label for the entry.
    - * @param {!Function} onchangeFunc onchange event handler.
    - * @return {!DocumentFragment} The DOM element.
    - * @private
    - */
    -goog.tweak.EntriesPanel.prototype.createTextBoxDom_ =
    -    function(tweak, label, onchangeFunc) {
    -  var dh = this.domHelper_;
    -  var ret = dh.getDocument().createDocumentFragment();
    -  ret.appendChild(dh.createTextNode(label + ': '));
    -  var textBox = dh.createDom('input', {
    -    value: tweak.getNewValue(),
    -    // TODO(agrieve): Make size configurable or autogrow.
    -    size: 5,
    -    onblur: onchangeFunc
    -  });
    -  ret.appendChild(textBox);
    -  tweak.addCallback(function() {
    -    textBox.value = tweak.getNewValue();
    -  });
    -  return ret;
    -};
    -
    -
    -/**
    - * Creates the DOM element to control the given button action.
    - * @param {!goog.tweak.ButtonAction} tweak The action.
    - * @param {string} label The label for the entry.
    - * @return {!Element} The DOM element.
    - * @private
    - */
    -goog.tweak.EntriesPanel.prototype.createButtonActionDom_ =
    -    function(tweak, label) {
    -  return this.domHelper_.createDom('button', {
    -    onclick: goog.bind(tweak.fireCallbacks, tweak)
    -  }, label);
    -};
    -
    -
    -/**
    - * Creates the DOM element to control the given entry.
    - * @param {!goog.tweak.BaseEntry} entry The entry.
    - * @return {!Element|!DocumentFragment} The DOM element.
    - * @private
    - */
    -goog.tweak.EntriesPanel.prototype.createTweakEntryDom_ = function(entry) {
    -  var label = goog.tweak.TweakUi.getNamespacedLabel_(entry);
    -  if (entry instanceof goog.tweak.BooleanSetting) {
    -    return this.createBooleanSettingDom_(entry, label);
    -  } else if (entry instanceof goog.tweak.BooleanGroup) {
    -    var childEntries = goog.tweak.TweakUi.extractBooleanGroupEntries_(entry);
    -    return this.createSubPanelDom_(entry, label, childEntries);
    -  } else if (entry instanceof goog.tweak.StringSetting) {
    -    /** @this {Element} */
    -    var setValueFunc = function() {
    -      entry.setValue(this.value);
    -    };
    -    return entry.getValidValues() ?
    -        this.createComboBoxDom_(entry, label, setValueFunc) :
    -        this.createTextBoxDom_(entry, label, setValueFunc);
    -  } else if (entry instanceof goog.tweak.NumericSetting) {
    -    setValueFunc = function() {
    -      // Reset the value if it's not a number.
    -      if (isNaN(this.value)) {
    -        this.value = entry.getNewValue();
    -      } else {
    -        entry.setValue(+this.value);
    -      }
    -    };
    -    return entry.getValidValues() ?
    -        this.createComboBoxDom_(entry, label, setValueFunc) :
    -        this.createTextBoxDom_(entry, label, setValueFunc);
    -  } else if (entry instanceof goog.tweak.NamespaceEntry_) {
    -    return this.createSubPanelDom_(entry, entry.label, entry.entries);
    -  }
    -  goog.asserts.assertInstanceof(entry, goog.tweak.ButtonAction,
    -      'invalid entry: %s', entry);
    -  return this.createButtonActionDom_(
    -      /** @type {!goog.tweak.ButtonAction} */ (entry), label);
    -};
    -
    -
    -
    -/**
    - * Entries used to represent the collapsible namespace links. These entries are
    - * never registered with the TweakRegistry, but are contained within the
    - * collection of entries within TweakPanels.
    - * @param {string} namespace The namespace for the entry.
    - * @param {!Array<!goog.tweak.BaseEntry>} entries Entries within the namespace.
    - * @constructor
    - * @extends {goog.tweak.BaseEntry}
    - * @private
    - */
    -goog.tweak.NamespaceEntry_ = function(namespace, entries) {
    -  goog.tweak.BaseEntry.call(this,
    -      goog.tweak.NamespaceEntry_.ID_PREFIX + namespace,
    -      'Tweaks within the ' + namespace + ' namespace.');
    -
    -  /**
    -   * Entries within this namespace.
    -   * @type {!Array<!goog.tweak.BaseEntry>}
    -   */
    -  this.entries = entries;
    -
    -  this.label = namespace;
    -};
    -goog.inherits(goog.tweak.NamespaceEntry_, goog.tweak.BaseEntry);
    -
    -
    -/**
    - * Prefix for the IDs of namespace entries used to ensure that they do not
    - * conflict with regular entries.
    - * @type {string}
    - */
    -goog.tweak.NamespaceEntry_.ID_PREFIX = '!';
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/tweak/tweakui_test.html b/src/database/third_party/closure-library/closure/goog/tweak/tweakui_test.html
    deleted file mode 100644
    index 201fe277d48..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/tweak/tweakui_test.html
    +++ /dev/null
    @@ -1,27 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    -Author: agrieve@google.com (Andrew Grieve)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.tweak.TweakUi
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.tweak.TweakUiTest');
    -  </script>
    -  <link rel="stylesheet" type="text/css" href="../css/common.css" />
    - </head>
    - <body>
    -  <div id="root">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/tweak/tweakui_test.js b/src/database/third_party/closure-library/closure/goog/tweak/tweakui_test.js
    deleted file mode 100644
    index e0f11fc53ab..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/tweak/tweakui_test.js
    +++ /dev/null
    @@ -1,275 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.tweak.TweakUiTest');
    -goog.setTestOnly('goog.tweak.TweakUiTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.string');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.tweak');
    -goog.require('goog.tweak.TweakUi');
    -/** @suppress {extraRequire} needed for createRegistryEntries. */
    -goog.require('goog.tweak.testhelpers');
    -
    -var root;
    -var registry;
    -var EXPECTED_ENTRIES_COUNT = 14;
    -
    -function setUp() {
    -  root = document.getElementById('root');
    -  // Make both test cases use the same entries in order to be able to test that
    -  // having two UIs on the same page does not cause trouble.
    -  createRegistryEntries('');
    -  registry = goog.tweak.getRegistry();
    -}
    -
    -function tearDown() {
    -  goog.tweak.activeBooleanGroup_ = null;
    -  // When debugging a single test, don't clear out the DOM.
    -  if (window.location.search.indexOf('runTests') == -1) {
    -    root.innerHTML = '';
    -  }
    -}
    -
    -function tearDownPage() {
    -  // When debugging a single test, don't clear out the DOM.
    -  if (window.location.search.indexOf('runTests') != -1) {
    -    return;
    -  }
    -  // Create both registries for interactive testing.
    -  createRegistryEntries('');
    -  registry = goog.tweak.getRegistry();
    -  // Add an extra tweak for testing the creation of tweaks after the UI has
    -  // already been rendered.
    -  var entryCounter = 0;
    -  goog.tweak.registerButton('CreateNewTweak', 'Creates a new tweak. Meant ' +
    -      'to simulate a tweak being registered in a lazy-loaded module.',
    -      function() {
    -        goog.tweak.registerBoolean(
    -            'Lazy' + ++entryCounter, 'Lazy-loaded tweak.');
    -      });
    -  goog.tweak.registerButton('CreateNewTweakInNamespace1',
    -      'Creates a new tweak within a namespace. Meant to simulate a tweak ' +
    -      'being registered in a lazy-loaded module.', function() {
    -        goog.tweak.registerString(
    -            'foo.bar.Lazy' + ++entryCounter, 'Lazy-loaded tweak.');
    -      });
    -  goog.tweak.registerButton('CreateNewTweakInNamespace2',
    -      'Creates a new tweak within a namespace. Meant to simulate a tweak ' +
    -      'being registered in a lazy-loaded module.', function() {
    -        goog.tweak.registerNumber(
    -            'foo.bar.baz.Lazy' + ++entryCounter, 'Lazy combo', 3,
    -            {validValues: [1, 2, 3], label: 'Lazy!'});
    -      });
    -
    -  var label = document.createElement('h3');
    -  label.innerHTML = 'TweakUi:';
    -  root.appendChild(label);
    -  createUi(false);
    -
    -  label = document.createElement('h3');
    -  label.innerHTML = 'Collapsible:';
    -  root.appendChild(label);
    -  createUi(true);
    -}
    -
    -function createUi(collapsible) {
    -  var tweakUiElem = collapsible ? goog.tweak.TweakUi.createCollapsible() :
    -      goog.tweak.TweakUi.create();
    -  root.appendChild(tweakUiElem);
    -}
    -
    -function getAllEntryDivs() {
    -  return goog.dom.getElementsByTagNameAndClass('div',
    -      goog.tweak.TweakUi.ENTRY_CSS_CLASS_);
    -}
    -
    -function getEntryDiv(entry) {
    -  var label = goog.tweak.TweakUi.getNamespacedLabel_(entry);
    -  var allDivs = getAllEntryDivs();
    -  var ret;
    -  for (var i = 0, div; div = allDivs[i]; i++) {
    -    var divText = goog.dom.getTextContent(div);
    -    if (goog.string.startsWith(divText, label) &&
    -        goog.string.contains(divText, entry.description)) {
    -      assertFalse('Found multiple divs matching entry ' + entry.getId(), !!ret);
    -      ret = div;
    -    }
    -  }
    -  assertTrue('getEntryDiv failed for ' + entry.getId(), !!ret);
    -  return ret;
    -}
    -
    -function getEntryInput(entry) {
    -  var div = getEntryDiv(entry);
    -  return div.getElementsByTagName('input')[0] ||
    -      div.getElementsByTagName('select')[0];
    -}
    -
    -function testCreate() {
    -  createUi(false);
    -  assertEquals('Wrong number of entry divs.', EXPECTED_ENTRIES_COUNT,
    -      getAllEntryDivs().length);
    -
    -  assertFalse('checkbox should not be checked 1',
    -      getEntryInput(boolEntry).checked);
    -  assertTrue('checkbox should be checked 2',
    -      getEntryInput(boolEntry2).checked);
    -  // Enusre custom labels are being used.
    -  var html = document.getElementsByTagName('button')[0].innerHTML;
    -  assertTrue('Button label is wrong', html.indexOf('&lt;btn&gt;') > -1);
    -  html = getEntryDiv(numEnumEntry).innerHTML;
    -  assertTrue('Enum2 label is wrong', html.indexOf('second&amp;') > -1);
    -}
    -
    -function testToggleBooleanSetting() {
    -  boolEntry.setValue(true);
    -  createUi(false);
    -
    -  assertTrue('checkbox should be checked',
    -      getEntryInput(boolEntry).checked);
    -
    -  boolEntry.setValue(false);
    -  assertFalse('checkbox should not be checked 1',
    -      getEntryInput(boolEntry).checked);
    -}
    -
    -function testToggleStringSetting() {
    -  strEntry.setValue('val1');
    -  createUi(false);
    -
    -  assertEquals('Textbox has wrong value 1',
    -      'val1', getEntryInput(strEntry).value);
    -
    -  strEntry.setValue('val2');
    -  assertEquals('Textbox has wrong value 2',
    -      'val2', getEntryInput(strEntry).value);
    -}
    -
    -function testToggleStringEnumSetting() {
    -  strEnumEntry.setValue('B');
    -  createUi(false);
    -
    -  assertEquals('wrong value 1',
    -      'B', getEntryInput(strEnumEntry).value);
    -
    -  strEnumEntry.setValue('C');
    -  assertEquals('wrong value 2',
    -      'C', getEntryInput(strEnumEntry).value);
    -}
    -
    -
    -function testToggleNumericSetting() {
    -  numEntry.setValue(3);
    -  createUi(false);
    -
    -  assertEquals('wrong value 1',
    -      '3', getEntryInput(numEntry).value);
    -
    -  numEntry.setValue(4);
    -  assertEquals('wrong value 2',
    -      '4', getEntryInput(numEntry).value);
    -}
    -
    -function testToggleNumericEnumSetting() {
    -  numEnumEntry.setValue(2);
    -  createUi(false);
    -
    -  assertEquals('wrong value 1',
    -      '2', getEntryInput(numEnumEntry).value);
    -
    -  numEnumEntry.setValue(3);
    -  assertEquals('wrong value 2',
    -      '3', getEntryInput(numEnumEntry).value);
    -}
    -
    -function testClickBooleanSetting() {
    -  createUi(false);
    -
    -  var input = getEntryInput(boolEntry);
    -  input.checked = true;
    -  input.onchange();
    -  assertTrue('setting should be true', boolEntry.getNewValue());
    -  input.checked = false;
    -  input.onchange();
    -  assertFalse('setting should be false', boolEntry.getNewValue());
    -}
    -
    -function testToggleDescriptions() {
    -  createUi(false);
    -  var toggleLink = root.getElementsByTagName('a')[0];
    -  var heightBefore = root.offsetHeight;
    -  toggleLink.onclick();
    -  assertTrue('Expected div height to grow from toggle descriptions.',
    -      root.offsetHeight > heightBefore);
    -  toggleLink.onclick();
    -  assertEquals('Expected div height to revert from toggle descriptions.',
    -      heightBefore, root.offsetHeight);
    -}
    -
    -function assertEntryOrder(entryId1, entryId2) {
    -  var entry1 = registry.getEntry(entryId1);
    -  var entry2 = registry.getEntry(entryId2);
    -  var div1 = getEntryDiv(entry1);
    -  var div2 = getEntryDiv(entry2);
    -  var order = goog.dom.compareNodeOrder(div1, div2);
    -  assertTrue(entry1.getId() + ' should be before ' + entry2.getId(), order < 0);
    -}
    -
    -function testAddEntry() {
    -  createUi(false);
    -  goog.tweak.registerBoolean('Lazy1', 'Lazy-loaded tweak.');
    -  goog.tweak.registerBoolean('Lazy2', 'Lazy-loaded tweak.',
    -      /* defaultValue */ false, { restartRequired: false });
    -  goog.tweak.beginBooleanGroup('LazyGroup', 'Lazy-loaded tweak.');
    -  goog.tweak.registerBoolean('Lazy3', 'Lazy-loaded tweak.');
    -  goog.tweak.endBooleanGroup();
    -
    -  assertEquals('Wrong number of entry divs.', EXPECTED_ENTRIES_COUNT + 4,
    -      getAllEntryDivs().length);
    -  assertEntryOrder('Enum2', 'Lazy1');
    -  assertEntryOrder('Lazy1', 'Lazy2');
    -  assertEntryOrder('Lazy2', 'Num');
    -  assertEntryOrder('BoolGroup', 'Lazy3');
    -}
    -
    -function testAddNamespacedEntries() {
    -  createUi(false);
    -  goog.tweak.beginBooleanGroup('NS.LazyGroup', 'Lazy-loaded tweak.');
    -  goog.tweak.registerBoolean('NS.InGroup', 'Lazy-loaded tweak.');
    -  goog.tweak.endBooleanGroup();
    -  goog.tweak.registerBoolean('NS.Banana', 'Lazy-loaded tweak.');
    -  goog.tweak.registerBoolean('NS.Apple', 'Lazy-loaded tweak.');
    -
    -  assertEquals('Wrong number of entry divs.', EXPECTED_ENTRIES_COUNT + 5,
    -      getAllEntryDivs().length);
    -  assertEntryOrder('Enum2', 'NS.Apple');
    -  assertEntryOrder('NS.Apple', 'NS.Banana');
    -  assertEntryOrder('NS.Banana', 'NS.InGroup');
    -}
    -
    -function testCollapsibleIsLazy() {
    -  if (document.createEvent) {
    -    createUi(true);
    -    assertEquals('Expected no entry divs.', 0, getAllEntryDivs().length);
    -    var showLink = root.getElementsByTagName('a')[0];
    -    var event = document.createEvent('MouseEvents');
    -    event.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false,
    -        false, false, false, 0, null);
    -    showLink.dispatchEvent(event);
    -    assertEquals('Wrong number of entry divs.', EXPECTED_ENTRIES_COUNT,
    -        getAllEntryDivs().length);
    -  }
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/abstractspellchecker.js b/src/database/third_party/closure-library/closure/goog/ui/abstractspellchecker.js
    deleted file mode 100644
    index d085a57073f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/abstractspellchecker.js
    +++ /dev/null
    @@ -1,1229 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Abstract base class for spell checker implementations.
    - *
    - * The spell checker supports two modes - synchronous and asynchronous.
    - *
    - * In synchronous mode subclass calls processText_ which processes all the text
    - * given to it before it returns. If the text string is very long, it could
    - * cause warnings from the browser that considers the script to be
    - * busy-looping.
    - *
    - * Asynchronous mode allows breaking processing large text segments without
    - * encountering stop script warnings by rescheduling remaining parts of the
    - * text processing to another stack.
    - *
    - * In asynchronous mode abstract spell checker keeps track of a number of text
    - * chunks that have been processed after the very beginning, and returns every
    - * so often so that the calling function could reschedule its execution on a
    - * different stack (for example by calling setInterval(0)).
    - *
    - * @author eae@google.com (Emil A Eklund)
    - */
    -
    -goog.provide('goog.ui.AbstractSpellChecker');
    -goog.provide('goog.ui.AbstractSpellChecker.AsyncResult');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.NodeType');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.dom.selection');
    -goog.require('goog.events');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventType');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.spell.SpellCheck');
    -goog.require('goog.structs.Set');
    -goog.require('goog.style');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.MenuItem');
    -goog.require('goog.ui.MenuSeparator');
    -goog.require('goog.ui.PopupMenu');
    -
    -
    -
    -/**
    - * Abstract base class for spell checker editor implementations. Provides basic
    - * functionality such as word lookup and caching.
    - *
    - * @param {goog.spell.SpellCheck} spellCheck Instance of the SpellCheck
    - *     support object to use. A single instance can be shared by multiple editor
    - *     components.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @constructor
    - * @extends {goog.ui.Component}
    - */
    -goog.ui.AbstractSpellChecker = function(spellCheck, opt_domHelper) {
    -  goog.ui.Component.call(this, opt_domHelper);
    -
    -  /**
    -   * Handler to use for caching and lookups.
    -   * @type {goog.spell.SpellCheck}
    -   * @protected
    -   */
    -  this.spellCheck = spellCheck;
    -
    -  /**
    -   * Word to element references. Used by replace/ignore.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.wordElements_ = {};
    -
    -  /**
    -   * List of all 'edit word' input elements.
    -   * @type {Array<Element>}
    -   * @private
    -   */
    -  this.inputElements_ = [];
    -
    -  /**
    -   * Global regular expression for splitting a string into individual words and
    -   * blocks of separators. Matches zero or one word followed by zero or more
    -   * separators.
    -   * @type {RegExp}
    -   * @private
    -   */
    -  this.splitRegex_ = new RegExp(
    -      '([^' + goog.spell.SpellCheck.WORD_BOUNDARY_CHARS + ']*)' +
    -      '([' + goog.spell.SpellCheck.WORD_BOUNDARY_CHARS + ']*)', 'g');
    -
    -  goog.events.listen(this.spellCheck,
    -      goog.spell.SpellCheck.EventType.WORD_CHANGED, this.onWordChanged_,
    -      false, this);
    -};
    -goog.inherits(goog.ui.AbstractSpellChecker, goog.ui.Component);
    -goog.tagUnsealableClass(goog.ui.AbstractSpellChecker);
    -
    -
    -/**
    - * The prefix to mark keys with.
    - * @type {string}
    - * @private
    - */
    -goog.ui.AbstractSpellChecker.KEY_PREFIX_ = ':';
    -
    -
    -/**
    - * The attribute name for original element contents (to offer subsequent
    - * correction menu).
    - * @type {string}
    - * @private
    - */
    -goog.ui.AbstractSpellChecker.ORIGINAL_ = 'g-spell-original';
    -
    -
    -/**
    - * Suggestions menu.
    - *
    - * @type {goog.ui.PopupMenu|undefined}
    - * @private
    - */
    -goog.ui.AbstractSpellChecker.prototype.menu_;
    -
    -
    -/**
    - * Separator between suggestions and ignore in suggestions menu.
    - *
    - * @type {goog.ui.MenuSeparator|undefined}
    - * @private
    - */
    -goog.ui.AbstractSpellChecker.prototype.menuSeparator_;
    -
    -
    -/**
    - * Menu item for ignore option.
    - *
    - * @type {goog.ui.MenuItem|undefined}
    - * @private
    - */
    -goog.ui.AbstractSpellChecker.prototype.menuIgnore_;
    -
    -
    -/**
    - * Menu item for edit word option.
    - *
    - * @type {goog.ui.MenuItem|undefined}
    - * @private
    - */
    -goog.ui.AbstractSpellChecker.prototype.menuEdit_;
    -
    -
    -/**
    - * Whether the correction UI is visible.
    - *
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.AbstractSpellChecker.prototype.isVisible_ = false;
    -
    -
    -/**
    - * Cache for corrected words. All corrected words are reverted to their original
    - * status on resume. Therefore that status is never written to the cache and is
    - * instead indicated by this set.
    - *
    - * @type {goog.structs.Set|undefined}
    - * @private
    - */
    -goog.ui.AbstractSpellChecker.prototype.correctedWords_;
    -
    -
    -/**
    - * Class name for suggestions menu.
    - *
    - * @type {string}
    - */
    -goog.ui.AbstractSpellChecker.prototype.suggestionsMenuClassName =
    -    goog.getCssName('goog-menu');
    -
    -
    -/**
    - * Whether corrected words should be highlighted.
    - *
    - * @type {boolean}
    - */
    -goog.ui.AbstractSpellChecker.prototype.markCorrected = false;
    -
    -
    -/**
    - * Word the correction menu is displayed for.
    - *
    - * @type {string|undefined}
    - * @private
    - */
    -goog.ui.AbstractSpellChecker.prototype.activeWord_;
    -
    -
    -/**
    - * Element the correction menu is displayed for.
    - *
    - * @type {Element|undefined}
    - * @private
    - */
    -goog.ui.AbstractSpellChecker.prototype.activeElement_;
    -
    -
    -/**
    - * Indicator that the spell checker is running in the asynchronous mode.
    - *
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.AbstractSpellChecker.prototype.asyncMode_ = false;
    -
    -
    -/**
    - * Maximum number of words to process on a single stack in asynchronous mode.
    - *
    - * @type {number}
    - * @private
    - */
    -goog.ui.AbstractSpellChecker.prototype.asyncWordsPerBatch_ = 1000;
    -
    -
    -/**
    - * Current text to process when running in the asynchronous mode.
    - *
    - * @type {string|undefined}
    - * @private
    - */
    -goog.ui.AbstractSpellChecker.prototype.asyncText_;
    -
    -
    -/**
    - * Current start index of the range that spell-checked correctly.
    - *
    - * @type {number|undefined}
    - * @private
    - */
    -goog.ui.AbstractSpellChecker.prototype.asyncRangeStart_;
    -
    -
    -/**
    - * Current node with which the asynchronous text is associated.
    - *
    - * @type {Node|undefined}
    - * @private
    - */
    -goog.ui.AbstractSpellChecker.prototype.asyncNode_;
    -
    -
    -/**
    - * Number of elements processed in the asyncronous mode since last yield.
    - *
    - * @type {number}
    - * @private
    - */
    -goog.ui.AbstractSpellChecker.prototype.processedElementsCount_ = 0;
    -
    -
    -/**
    - * Markers for the text that does not need to be included in the processing.
    - *
    - * For rich text editor this is a list of strings formatted as
    - * tagName.className or className. If both are specified, the element will be
    - * excluded if BOTH are matched. If only a className is specified, then we will
    - * exclude regions with the className. If only one marker is needed, it may be
    - * passed as a string.
    - * For plain text editor this is a RegExp that matches the excluded text.
    - *
    - * Used exclusively by the derived classes
    - *
    - * @type {Array<string>|string|RegExp|undefined}
    - * @protected
    - */
    -goog.ui.AbstractSpellChecker.prototype.excludeMarker;
    -
    -
    -/**
    - * Numeric Id of the element that has focus. 0 when not set.
    - *
    - * @private {number}
    - */
    -goog.ui.AbstractSpellChecker.prototype.focusedElementIndex_ = 0;
    -
    -
    -/**
    - * Index for the most recently added misspelled word.
    - *
    - * @private {number}
    - */
    -goog.ui.AbstractSpellChecker.prototype.lastIndex_ = 0;
    -
    -
    -/**
    - * @return {goog.spell.SpellCheck} The handler used for caching and lookups.
    - */
    -goog.ui.AbstractSpellChecker.prototype.getSpellCheck = function() {
    -  return this.spellCheck;
    -};
    -
    -
    -/**
    - * @return {goog.spell.SpellCheck} The handler used for caching and lookups.
    - * @override
    - * @suppress {checkTypes} This method makes no sense. It overrides
    - *     Component's getHandler with something different.
    - * @deprecated Use #getSpellCheck instead.
    - */
    -goog.ui.AbstractSpellChecker.prototype.getHandler = function() {
    -  return this.getSpellCheck();
    -};
    -
    -
    -/**
    - * Sets the spell checker used for caching and lookups.
    - * @param {goog.spell.SpellCheck} spellCheck The handler used for caching and
    - *     lookups.
    - */
    -goog.ui.AbstractSpellChecker.prototype.setSpellCheck = function(spellCheck) {
    -  this.spellCheck = spellCheck;
    -};
    -
    -
    -/**
    - * Sets the handler used for caching and lookups.
    - * @param {goog.spell.SpellCheck} handler The handler used for caching and
    - *     lookups.
    - * @deprecated Use #setSpellCheck instead.
    - */
    -goog.ui.AbstractSpellChecker.prototype.setHandler = function(handler) {
    -  this.setSpellCheck(handler);
    -};
    -
    -
    -/**
    - * @return {goog.ui.PopupMenu|undefined} The suggestions menu.
    - * @protected
    - */
    -goog.ui.AbstractSpellChecker.prototype.getMenu = function() {
    -  return this.menu_;
    -};
    -
    -
    -/**
    - * @return {goog.ui.MenuItem|undefined} The menu item for edit word option.
    - * @protected
    - */
    -goog.ui.AbstractSpellChecker.prototype.getMenuEdit = function() {
    -  return this.menuEdit_;
    -};
    -
    -
    -/**
    - * @return {number} The index of the latest misspelled word to be added.
    - * @protected
    - */
    -goog.ui.AbstractSpellChecker.prototype.getLastIndex = function() {
    -  return this.lastIndex_;
    -};
    -
    -
    -/**
    - * @return {number} Increments and returns the index for the next misspelled
    - *     word to be added.
    - * @protected
    - */
    -goog.ui.AbstractSpellChecker.prototype.getNextIndex = function() {
    -  return ++this.lastIndex_;
    -};
    -
    -
    -/**
    - * Sets the marker for the excluded text.
    - *
    - * {@see goog.ui.AbstractSpellChecker.prototype.excludeMarker}
    - *
    - * @param {Array<string>|string|RegExp|null} marker A RegExp for plain text
    - *        or class names for the rich text spell checker for the elements to
    - *        exclude from checking.
    - */
    -goog.ui.AbstractSpellChecker.prototype.setExcludeMarker = function(marker) {
    -  this.excludeMarker = marker || undefined;
    -};
    -
    -
    -/**
    - * Checks spelling for all text.
    - * Should be overridden by implementation.
    - */
    -goog.ui.AbstractSpellChecker.prototype.check = function() {
    -  this.isVisible_ = true;
    -  if (this.markCorrected) {
    -    this.correctedWords_ = new goog.structs.Set();
    -  }
    -};
    -
    -
    -/**
    - * Hides correction UI.
    - * Should be overridden by implementation.
    - */
    -goog.ui.AbstractSpellChecker.prototype.resume = function() {
    -  this.isVisible_ = false;
    -  this.clearWordElements();
    -  this.lastIndex_ = 0;
    -  this.setFocusedElementIndex(0);
    -
    -  var input;
    -  while (input = this.inputElements_.pop()) {
    -    input.parentNode.replaceChild(
    -        this.getDomHelper().createTextNode(input.value), input);
    -  }
    -
    -  if (this.correctedWords_) {
    -    this.correctedWords_.clear();
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the correction ui is visible.
    - */
    -goog.ui.AbstractSpellChecker.prototype.isVisible = function() {
    -  return this.isVisible_;
    -};
    -
    -
    -/**
    - * Clears the word to element references map used by replace/ignore.
    - * @protected
    - */
    -goog.ui.AbstractSpellChecker.prototype.clearWordElements = function() {
    -  this.wordElements_ = {};
    -};
    -
    -
    -/**
    - * Ignores spelling of word.
    - *
    - * @param {string} word Word to add.
    - */
    -goog.ui.AbstractSpellChecker.prototype.ignoreWord = function(word) {
    -  this.spellCheck.setWordStatus(word,
    -      goog.spell.SpellCheck.WordStatus.IGNORED);
    -};
    -
    -
    -/**
    - * Edits a word.
    - *
    - * @param {Element} el An element wrapping the word that should be edited.
    - * @param {string} old Word to edit.
    - * @private
    - */
    -goog.ui.AbstractSpellChecker.prototype.editWord_ = function(el, old) {
    -  var input = this.getDomHelper().createDom(
    -      'input', {'type': 'text', 'value': old});
    -  var w = goog.style.getSize(el).width;
    -
    -  // Minimum width to ensure there's always enough room to type.
    -  if (w < 50) {
    -    w = 50;
    -  }
    -  input.style.width = w + 'px';
    -  el.parentNode.replaceChild(input, el);
    -  try {
    -    input.focus();
    -    goog.dom.selection.setCursorPosition(input, old.length);
    -  } catch (o) { }
    -
    -  this.inputElements_.push(input);
    -};
    -
    -
    -/**
    - * Replaces word.
    - *
    - * @param {Element} el An element wrapping the word that should be replaced.
    - * @param {string} old Word that was replaced.
    - * @param {string} word Word to replace with.
    - */
    -goog.ui.AbstractSpellChecker.prototype.replaceWord = function(el, old, word) {
    -  if (old != word) {
    -    if (!el.getAttribute(goog.ui.AbstractSpellChecker.ORIGINAL_)) {
    -      el.setAttribute(goog.ui.AbstractSpellChecker.ORIGINAL_, old);
    -    }
    -    goog.dom.setTextContent(el, word);
    -
    -    var status = this.spellCheck.checkWord(word);
    -
    -    // Indicate that the word is corrected unless the status is 'INVALID'.
    -    // (if markCorrected is enabled).
    -    if (this.markCorrected && this.correctedWords_ &&
    -        status != goog.spell.SpellCheck.WordStatus.INVALID) {
    -      this.correctedWords_.add(word);
    -      status = goog.spell.SpellCheck.WordStatus.CORRECTED;
    -    }
    -
    -    // Avoid potential collision with the built-in object namespace. For
    -    // example, 'watch' is a reserved name in FireFox.
    -    var oldIndex = goog.ui.AbstractSpellChecker.toInternalKey_(old);
    -    var newIndex = goog.ui.AbstractSpellChecker.toInternalKey_(word);
    -
    -    // Remove reference between old word and element
    -    var elements = this.wordElements_[oldIndex];
    -    goog.array.remove(elements, el);
    -
    -    if (status != goog.spell.SpellCheck.WordStatus.VALID) {
    -      // Create reference between new word and element
    -      if (this.wordElements_[newIndex]) {
    -        this.wordElements_[newIndex].push(el);
    -      } else {
    -        this.wordElements_[newIndex] = [el];
    -      }
    -    }
    -
    -    // Update element based on status.
    -    this.updateElement(el, word, status);
    -
    -    this.dispatchEvent(goog.events.EventType.CHANGE);
    -  }
    -};
    -
    -
    -/**
    - * Retrieves the array of suggested spelling choices.
    - *
    - * @return {Array<string>} Suggested spelling choices.
    - * @private
    - */
    -goog.ui.AbstractSpellChecker.prototype.getSuggestions_ = function() {
    -  // Add new suggestion entries.
    -  var suggestions = this.spellCheck.getSuggestions(
    -      /** @type {string} */ (this.activeWord_));
    -  if (!suggestions[0]) {
    -    var originalWord = this.activeElement_.getAttribute(
    -        goog.ui.AbstractSpellChecker.ORIGINAL_);
    -    if (originalWord && originalWord != this.activeWord_) {
    -      suggestions = this.spellCheck.getSuggestions(originalWord);
    -    }
    -  }
    -  return suggestions;
    -};
    -
    -
    -/**
    - * Displays suggestions menu.
    - *
    - * @param {Element} el Element to display menu for.
    - * @param {goog.events.BrowserEvent|goog.math.Coordinate=} opt_pos Position to
    - *     display menu at relative to the viewport (in client coordinates), or a
    - *     mouse event.
    - */
    -goog.ui.AbstractSpellChecker.prototype.showSuggestionsMenu = function(el,
    -                                                                      opt_pos) {
    -  this.activeWord_ = goog.dom.getTextContent(el);
    -  this.activeElement_ = el;
    -
    -  // Remove suggestion entries from menu, if any.
    -  while (this.menu_.getChildAt(0) != this.menuSeparator_) {
    -    this.menu_.removeChildAt(0, true).dispose();
    -  }
    -
    -  // Add new suggestion entries.
    -  var suggestions = this.getSuggestions_();
    -  for (var suggestion, i = 0; suggestion = suggestions[i]; i++) {
    -    this.menu_.addChildAt(new goog.ui.MenuItem(
    -        suggestion, suggestion, this.getDomHelper()), i, true);
    -  }
    -
    -  if (!suggestions[0]) {
    -    /** @desc Item shown in menu when no suggestions are available. */
    -    var MSG_SPELL_NO_SUGGESTIONS = goog.getMsg('No Suggestions');
    -    var item = new goog.ui.MenuItem(
    -        MSG_SPELL_NO_SUGGESTIONS, '', this.getDomHelper());
    -    item.setEnabled(false);
    -    this.menu_.addChildAt(item, 0, true);
    -  }
    -
    -  // Show 'Edit word' option if {@link markCorrected} is enabled and don't show
    -  // 'Ignore' option for corrected words.
    -  if (this.markCorrected) {
    -    var corrected = this.correctedWords_ &&
    -                    this.correctedWords_.contains(this.activeWord_);
    -    this.menuIgnore_.setVisible(!corrected);
    -    this.menuEdit_.setVisible(true);
    -  } else {
    -    this.menuIgnore_.setVisible(true);
    -    this.menuEdit_.setVisible(false);
    -  }
    -
    -  if (opt_pos) {
    -    if (!(opt_pos instanceof goog.math.Coordinate)) { // it's an event
    -      var posX = opt_pos.clientX;
    -      var posY = opt_pos.clientY;
    -      // Certain implementations which derive from AbstractSpellChecker
    -      // use an iframe in which case the coordinates are relative to
    -      // that iframe's view port.
    -      if (this.getElement().contentDocument ||
    -          this.getElement().contentWindow) {
    -        var offset = goog.style.getClientPosition(this.getElement());
    -        posX += offset.x;
    -        posY += offset.y;
    -      }
    -      opt_pos = new goog.math.Coordinate(posX, posY);
    -    }
    -    this.menu_.showAt(opt_pos.x, opt_pos.y);
    -  } else {
    -    this.menu_.setVisible(true);
    -  }
    -};
    -
    -
    -/**
    - * Initializes suggestions menu. Populates menu with separator and ignore option
    - * that are always valid. Suggestions are later added above the separator.
    - *
    - * @protected
    - */
    -goog.ui.AbstractSpellChecker.prototype.initSuggestionsMenu = function() {
    -  this.menu_ = new goog.ui.PopupMenu(this.getDomHelper());
    -  this.menuSeparator_ = new goog.ui.MenuSeparator(this.getDomHelper());
    -
    -  // Leave alone setAllowAutoFocus at default (true). This allows menu to get
    -  // keyboard focus and thus allowing non-mouse users to get to the menu.
    -
    -  /** @desc Ignore entry in suggestions menu. */
    -  var MSG_SPELL_IGNORE = goog.getMsg('Ignore');
    -
    -  /** @desc Edit word entry in suggestions menu. */
    -  var MSG_SPELL_EDIT_WORD = goog.getMsg('Edit Word');
    -
    -  this.menu_.addChild(this.menuSeparator_, true);
    -  this.menuIgnore_ =
    -      new goog.ui.MenuItem(MSG_SPELL_IGNORE, '', this.getDomHelper());
    -  this.menu_.addChild(this.menuIgnore_, true);
    -  this.menuEdit_ =
    -      new goog.ui.MenuItem(MSG_SPELL_EDIT_WORD, '', this.getDomHelper());
    -  this.menuEdit_.setVisible(false);
    -  this.menu_.addChild(this.menuEdit_, true);
    -  this.menu_.setParent(this);
    -  this.menu_.render();
    -
    -  var menuElement = this.menu_.getElement();
    -  goog.asserts.assert(menuElement);
    -  goog.dom.classlist.add(menuElement,
    -      this.suggestionsMenuClassName);
    -
    -  goog.events.listen(this.menu_, goog.ui.Component.EventType.ACTION,
    -      this.onCorrectionAction, false, this);
    -};
    -
    -
    -/**
    - * Handles correction menu actions.
    - *
    - * @param {goog.events.Event} event Action event.
    - * @protected
    - */
    -goog.ui.AbstractSpellChecker.prototype.onCorrectionAction = function(event) {
    -  var word = /** @type {string} */ (this.activeWord_);
    -  var el = /** @type {Element} */ (this.activeElement_);
    -  if (event.target == this.menuIgnore_) {
    -    this.ignoreWord(word);
    -  } else if (event.target == this.menuEdit_) {
    -    this.editWord_(el, word);
    -  } else {
    -    this.replaceWord(el, word, event.target.getModel());
    -    this.dispatchEvent(goog.ui.Component.EventType.CHANGE);
    -  }
    -
    -  delete this.activeWord_;
    -  delete this.activeElement_;
    -};
    -
    -
    -/**
    - * Removes spell-checker markup and restore the node to text.
    - *
    - * @param {Element} el Word element. MUST have a text node child.
    - * @protected
    - */
    -goog.ui.AbstractSpellChecker.prototype.removeMarkup = function(el) {
    -  var firstChild = el.firstChild;
    -  var text = firstChild.nodeValue;
    -
    -  if (el.nextSibling &&
    -      el.nextSibling.nodeType == goog.dom.NodeType.TEXT) {
    -    if (el.previousSibling &&
    -        el.previousSibling.nodeType == goog.dom.NodeType.TEXT) {
    -      el.previousSibling.nodeValue = el.previousSibling.nodeValue + text +
    -          el.nextSibling.nodeValue;
    -      this.getDomHelper().removeNode(el.nextSibling);
    -    } else {
    -      el.nextSibling.nodeValue = text + el.nextSibling.nodeValue;
    -    }
    -  } else if (el.previousSibling &&
    -      el.previousSibling.nodeType == goog.dom.NodeType.TEXT) {
    -    el.previousSibling.nodeValue += text;
    -  } else {
    -    el.parentNode.insertBefore(firstChild, el);
    -  }
    -
    -  this.getDomHelper().removeNode(el);
    -};
    -
    -
    -/**
    - * Updates element based on word status. Either converts it to a text node, or
    - * merges it with the previous or next text node if the status of the world is
    - * VALID, in which case the element itself is eliminated.
    - *
    - * @param {Element} el Word element.
    - * @param {string} word Word to update status for.
    - * @param {goog.spell.SpellCheck.WordStatus} status Status of word.
    - * @protected
    - */
    -goog.ui.AbstractSpellChecker.prototype.updateElement =
    -    function(el, word, status) {
    -  if (this.markCorrected && this.correctedWords_ &&
    -      this.correctedWords_.contains(word)) {
    -    status = goog.spell.SpellCheck.WordStatus.CORRECTED;
    -  }
    -  if (status == goog.spell.SpellCheck.WordStatus.VALID) {
    -    this.removeMarkup(el);
    -  } else {
    -    goog.dom.setProperties(el, this.getElementProperties(status));
    -  }
    -};
    -
    -
    -/**
    - * Generates unique Ids for spell checker elements.
    - * @param {number=} opt_id Id to suffix with.
    - * @return {string} Unique element id.
    - * @protected
    - */
    -goog.ui.AbstractSpellChecker.prototype.makeElementId = function(opt_id) {
    -  return this.getId() + '.' + (opt_id ? opt_id : this.getNextIndex());
    -};
    -
    -
    -/**
    - * Returns the span element that matches the given number index.
    - * @param {number} index Number index that is used in the element id.
    - * @return {Element} The matching span element or null if no span matches.
    - * @protected
    - */
    -goog.ui.AbstractSpellChecker.prototype.getElementByIndex = function(index) {
    -  return this.getDomHelper().getElement(this.makeElementId(index));
    -};
    -
    -
    -/**
    - * Creates an element for a specified word and stores a reference to it.
    - *
    - * @param {string} word Word to create element for.
    - * @param {goog.spell.SpellCheck.WordStatus} status Status of word.
    - * @return {!HTMLSpanElement} The created element.
    - * @protected
    - */
    -goog.ui.AbstractSpellChecker.prototype.createWordElement = function(
    -    word, status) {
    -  var parameters = this.getElementProperties(status);
    -
    -  // Add id & tabindex as necessary.
    -  if (!parameters['id']) {
    -    parameters['id'] = this.makeElementId();
    -  }
    -  if (!parameters['tabIndex']) {
    -    parameters['tabIndex'] = -1;
    -  }
    -
    -  var el = /** @type {!HTMLSpanElement} */
    -      (this.getDomHelper().createDom('span', parameters, word));
    -  goog.a11y.aria.setRole(el, 'menuitem');
    -  goog.a11y.aria.setState(el, 'haspopup', true);
    -  this.registerWordElement(word, el);
    -
    -  return el;
    -};
    -
    -
    -/**
    - * Stores a reference to word element.
    - *
    - * @param {string} word The word to store.
    - * @param {HTMLSpanElement} el The element associated with it.
    - * @protected
    - */
    -goog.ui.AbstractSpellChecker.prototype.registerWordElement = function(
    -    word, el) {
    -  // Avoid potential collision with the built-in object namespace. For
    -  // example, 'watch' is a reserved name in FireFox.
    -  var index = goog.ui.AbstractSpellChecker.toInternalKey_(word);
    -  if (this.wordElements_[index]) {
    -    this.wordElements_[index].push(el);
    -  } else {
    -    this.wordElements_[index] = [el];
    -  }
    -};
    -
    -
    -/**
    - * Returns desired element properties for the specified status.
    - * Should be overridden by implementation.
    - *
    - * @param {goog.spell.SpellCheck.WordStatus} status Status of word.
    - * @return {Object} Properties to apply to the element.
    - * @protected
    - */
    -goog.ui.AbstractSpellChecker.prototype.getElementProperties =
    -    goog.abstractMethod;
    -
    -
    -/**
    - * Handles word change events and updates the word elements accordingly.
    - *
    - * @param {goog.spell.SpellCheck.WordChangedEvent} event The event object.
    - * @private
    - */
    -goog.ui.AbstractSpellChecker.prototype.onWordChanged_ = function(event) {
    -  // Avoid potential collision with the built-in object namespace. For
    -  // example, 'watch' is a reserved name in FireFox.
    -  var index = goog.ui.AbstractSpellChecker.toInternalKey_(event.word);
    -  var elements = this.wordElements_[index];
    -  if (elements) {
    -    for (var el, i = 0; el = elements[i]; i++) {
    -      this.updateElement(el, event.word, event.status);
    -    }
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.AbstractSpellChecker.prototype.disposeInternal = function() {
    -  if (this.isVisible_) {
    -    // Clears wordElements_
    -    this.resume();
    -  }
    -
    -  goog.events.unlisten(this.spellCheck,
    -      goog.spell.SpellCheck.EventType.WORD_CHANGED, this.onWordChanged_,
    -      false, this);
    -
    -  if (this.menu_) {
    -    this.menu_.dispose();
    -    delete this.menu_;
    -    delete this.menuIgnore_;
    -    delete this.menuSeparator_;
    -  }
    -  delete this.spellCheck;
    -  delete this.wordElements_;
    -
    -  goog.ui.AbstractSpellChecker.superClass_.disposeInternal.call(this);
    -};
    -
    -
    -/**
    - * Precharges local dictionary cache. This is optional, but greatly reduces
    - * amount of subsequent churn in the DOM tree because most of the words become
    - * known from the very beginning.
    - *
    - * @param {string} text Text to process.
    - * @param {number} words Max number of words to scan.
    - * @return {number} number of words actually scanned.
    - * @protected
    - */
    -goog.ui.AbstractSpellChecker.prototype.populateDictionary = function(text,
    -                                                                     words) {
    -  this.splitRegex_.lastIndex = 0;
    -  var result;
    -  var numScanned = 0;
    -  while (result = this.splitRegex_.exec(text)) {
    -    if (result[0].length == 0) {
    -      break;
    -    }
    -    var word = result[1];
    -    if (word) {
    -      this.spellCheck.checkWord(word);
    -      ++numScanned;
    -      if (numScanned >= words) {
    -        break;
    -      }
    -    }
    -  }
    -  this.spellCheck.processPending();
    -  return numScanned;
    -};
    -
    -
    -/**
    - * Processes word.
    - * Should be overridden by implementation.
    - *
    - * @param {Node} node Node containing word.
    - * @param {string} text Word to process.
    - * @param {goog.spell.SpellCheck.WordStatus} status Status of the word.
    - * @protected
    - */
    -goog.ui.AbstractSpellChecker.prototype.processWord = function(
    -    node, text, status) {
    -  throw Error('Need to override processWord_ in derivative class');
    -};
    -
    -
    -/**
    - * Processes range of text that checks out (contains no unrecognized words).
    - * Should be overridden by implementation. May contain words and separators.
    - *
    - * @param {Node} node Node containing text range.
    - * @param {string} text text to process.
    - * @protected
    - */
    -goog.ui.AbstractSpellChecker.prototype.processRange = function(node, text) {
    -  throw Error('Need to override processRange_ in derivative class');
    -};
    -
    -
    -/**
    - * Starts asynchronous processing mode.
    - *
    - * @protected
    - */
    -goog.ui.AbstractSpellChecker.prototype.initializeAsyncMode = function() {
    -  if (this.asyncMode_ || this.processedElementsCount_ ||
    -      this.asyncText_ != null || this.asyncNode_) {
    -    throw Error('Async mode already in progress.');
    -  }
    -  this.asyncMode_ = true;
    -  this.processedElementsCount_ = 0;
    -  delete this.asyncText_;
    -  this.asyncRangeStart_ = 0;
    -  delete this.asyncNode_;
    -
    -  this.blockReadyEvents();
    -};
    -
    -
    -/**
    - * Finalizes asynchronous processing mode. Should be called after there is no
    - * more text to process and processTextAsync and/or continueAsyncProcessing
    - * returned FINISHED.
    - *
    - * @protected
    - */
    -goog.ui.AbstractSpellChecker.prototype.finishAsyncProcessing = function() {
    -  if (!this.asyncMode_ || this.asyncText_ != null || this.asyncNode_) {
    -    throw Error('Async mode not started or there is still text to process.');
    -  }
    -  this.asyncMode_ = false;
    -  this.processedElementsCount_ = 0;
    -
    -  this.unblockReadyEvents();
    -  this.spellCheck.processPending();
    -};
    -
    -
    -/**
    - * Blocks processing of spell checker READY events. This is used in dictionary
    - * recharge and async mode so that completion is not signaled prematurely.
    - *
    - * @protected
    - */
    -goog.ui.AbstractSpellChecker.prototype.blockReadyEvents = function() {
    -  goog.events.listen(this.spellCheck, goog.spell.SpellCheck.EventType.READY,
    -      goog.events.Event.stopPropagation, true);
    -};
    -
    -
    -/**
    - * Unblocks processing of spell checker READY events. This is used in
    - * dictionary recharge and async mode so that completion is not signaled
    - * prematurely.
    - *
    - * @protected
    - */
    -goog.ui.AbstractSpellChecker.prototype.unblockReadyEvents = function() {
    -  goog.events.unlisten(this.spellCheck, goog.spell.SpellCheck.EventType.READY,
    -      goog.events.Event.stopPropagation, true);
    -};
    -
    -
    -/**
    - * Splits text into individual words and blocks of separators. Calls virtual
    - * processWord_ and processRange_ methods.
    - *
    - * @param {Node} node Node containing text.
    - * @param {string} text Text to process.
    - * @return {goog.ui.AbstractSpellChecker.AsyncResult} operation result.
    - * @protected
    - */
    -goog.ui.AbstractSpellChecker.prototype.processTextAsync = function(
    -    node, text) {
    -  if (!this.asyncMode_ || this.asyncText_ != null || this.asyncNode_) {
    -    throw Error('Not in async mode or previous text has not been processed.');
    -  }
    -
    -  this.splitRegex_.lastIndex = 0;
    -  var stringSegmentStart = 0;
    -
    -  var result;
    -  while (result = this.splitRegex_.exec(text)) {
    -    if (result[0].length == 0) {
    -      break;
    -    }
    -    var word = result[1];
    -    if (word) {
    -      var status = this.spellCheck.checkWord(word);
    -      if (status != goog.spell.SpellCheck.WordStatus.VALID) {
    -        var preceedingText = text.substr(stringSegmentStart, result.index -
    -            stringSegmentStart);
    -        if (preceedingText) {
    -          this.processRange(node, preceedingText);
    -        }
    -        stringSegmentStart = result.index + word.length;
    -        this.processWord(node, word, status);
    -      }
    -    }
    -    this.processedElementsCount_++;
    -    if (this.processedElementsCount_ > this.asyncWordsPerBatch_) {
    -      this.asyncText_ = text;
    -      this.asyncRangeStart_ = stringSegmentStart;
    -      this.asyncNode_ = node;
    -      this.processedElementsCount_ = 0;
    -      return goog.ui.AbstractSpellChecker.AsyncResult.PENDING;
    -    }
    -  }
    -
    -  var leftoverText = text.substr(stringSegmentStart);
    -  if (leftoverText) {
    -    this.processRange(node, leftoverText);
    -  }
    -
    -  return goog.ui.AbstractSpellChecker.AsyncResult.DONE;
    -};
    -
    -
    -/**
    - * Continues processing started by processTextAsync. Calls virtual
    - * processWord_ and processRange_ methods.
    - *
    - * @return {goog.ui.AbstractSpellChecker.AsyncResult} operation result.
    - * @protected
    - */
    -goog.ui.AbstractSpellChecker.prototype.continueAsyncProcessing = function() {
    -  if (!this.asyncMode_ || this.asyncText_ == null || !this.asyncNode_) {
    -    throw Error('Not in async mode or processing not started.');
    -  }
    -  var node = /** @type {Node} */ (this.asyncNode_);
    -  var stringSegmentStart = this.asyncRangeStart_;
    -  goog.asserts.assertNumber(stringSegmentStart);
    -  var text = this.asyncText_;
    -
    -  var result;
    -  while (result = this.splitRegex_.exec(text)) {
    -    if (result[0].length == 0) {
    -      break;
    -    }
    -    var word = result[1];
    -    if (word) {
    -      var status = this.spellCheck.checkWord(word);
    -      if (status != goog.spell.SpellCheck.WordStatus.VALID) {
    -        var preceedingText = text.substr(stringSegmentStart, result.index -
    -            stringSegmentStart);
    -        if (preceedingText) {
    -          this.processRange(node, preceedingText);
    -        }
    -        stringSegmentStart = result.index + word.length;
    -        this.processWord(node, word, status);
    -      }
    -    }
    -    this.processedElementsCount_++;
    -    if (this.processedElementsCount_ > this.asyncWordsPerBatch_) {
    -      this.processedElementsCount_ = 0;
    -      this.asyncRangeStart_ = stringSegmentStart;
    -      return goog.ui.AbstractSpellChecker.AsyncResult.PENDING;
    -    }
    -  }
    -  delete this.asyncText_;
    -  this.asyncRangeStart_ = 0;
    -  delete this.asyncNode_;
    -
    -  var leftoverText = text.substr(stringSegmentStart);
    -  if (leftoverText) {
    -    this.processRange(node, leftoverText);
    -  }
    -
    -  return goog.ui.AbstractSpellChecker.AsyncResult.DONE;
    -};
    -
    -
    -/**
    - * Converts a word to an internal key representation. This is necessary to
    - * avoid collisions with object's internal namespace. Only words that are
    - * reserved need to be escaped.
    - *
    - * @param {string} word The word to map.
    - * @return {string} The index.
    - * @private
    - */
    -goog.ui.AbstractSpellChecker.toInternalKey_ = function(word) {
    -  if (word in Object.prototype) {
    -    return goog.ui.AbstractSpellChecker.KEY_PREFIX_ + word;
    -  }
    -  return word;
    -};
    -
    -
    -/**
    - * Navigate keyboard focus in the given direction.
    - *
    - * @param {goog.ui.AbstractSpellChecker.Direction} direction The direction to
    - *     navigate in.
    - * @return {boolean} Whether the action is handled here.  If not handled
    - *     here, the initiating event may be propagated.
    - * @protected
    - */
    -goog.ui.AbstractSpellChecker.prototype.navigate = function(direction) {
    -  var handled = false;
    -  var isMovingToNextWord =
    -      direction == goog.ui.AbstractSpellChecker.Direction.NEXT;
    -  var focusedIndex = this.getFocusedElementIndex();
    -
    -  var el;
    -  do {
    -    // Determine new index based on given direction.
    -    focusedIndex += isMovingToNextWord ? 1 : -1;
    -
    -    if (focusedIndex < 1 || focusedIndex > this.getLastIndex()) {
    -      // Exit the loop, because this focusedIndex cannot have an element.
    -      handled = true;
    -      break;
    -    }
    -
    -    // Word elements are removed during the correction action. If no element is
    -    // found for the new focusedIndex, then try again with the next value.
    -  } while (!(el = this.getElementByIndex(focusedIndex)));
    -
    -  if (el) {
    -    this.setFocusedElementIndex(focusedIndex);
    -    this.focusOnElement(el);
    -    handled = true;
    -  }
    -
    -  return handled;
    -};
    -
    -
    -/**
    - * Returns the index of the currently focussed invalid word element. This index
    - * starts at one instead of zero.
    - *
    - * @return {number} the index of the currently focussed element
    - * @protected
    - */
    -goog.ui.AbstractSpellChecker.prototype.getFocusedElementIndex = function() {
    -  return this.focusedElementIndex_;
    -};
    -
    -
    -/**
    - * Sets the index of the currently focussed invalid word element. This index
    - * should start at one instead of zero.
    - *
    - * @param {number} focusElementIndex the index of the currently focussed element
    - * @protected
    - */
    -goog.ui.AbstractSpellChecker.prototype.setFocusedElementIndex =
    -    function(focusElementIndex) {
    -  this.focusedElementIndex_ = focusElementIndex;
    -};
    -
    -
    -/**
    - * Sets the focus on the provided word element.
    - *
    - * @param {Element} element The word element that should receive focus.
    - * @protected
    - */
    -goog.ui.AbstractSpellChecker.prototype.focusOnElement = function(element) {
    -  element.focus();
    -};
    -
    -
    -/**
    - * Constants for representing the direction while navigating.
    - *
    - * @enum {number}
    - */
    -goog.ui.AbstractSpellChecker.Direction = {
    -  PREVIOUS: 0,
    -  NEXT: 1
    -};
    -
    -
    -/**
    - * Constants for the result of asynchronous processing.
    - * @enum {number}
    - */
    -goog.ui.AbstractSpellChecker.AsyncResult = {
    -  /**
    -   * Caller must reschedule operation and call continueAsyncProcessing on the
    -   * new stack frame.
    -   */
    -  PENDING: 1,
    -  /**
    -   * Current element has been fully processed. Caller can call
    -   * processTextAsync or finishAsyncProcessing.
    -   */
    -  DONE: 2
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/ac/ac.js b/src/database/third_party/closure-library/closure/goog/ui/ac/ac.js
    deleted file mode 100644
    index 910289510c0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/ac/ac.js
    +++ /dev/null
    @@ -1,50 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Utility methods supporting the autocomplete package.
    - *
    - * @see ../../demos/autocomplete-basic.html
    - */
    -
    -goog.provide('goog.ui.ac');
    -
    -goog.require('goog.ui.ac.ArrayMatcher');
    -goog.require('goog.ui.ac.AutoComplete');
    -goog.require('goog.ui.ac.InputHandler');
    -goog.require('goog.ui.ac.Renderer');
    -
    -
    -/**
    - * Factory function for building a basic autocomplete widget that autocompletes
    - * an inputbox or text area from a data array.
    - * @param {Array<?>} data Data array.
    - * @param {Element} input Input element or text area.
    - * @param {boolean=} opt_multi Whether to allow multiple entries separated with
    - *     semi-colons or commas.
    - * @param {boolean=} opt_useSimilar use similar matches. e.g. "gost" => "ghost".
    - * @return {!goog.ui.ac.AutoComplete} A new autocomplete object.
    - */
    -goog.ui.ac.createSimpleAutoComplete =
    -    function(data, input, opt_multi, opt_useSimilar) {
    -  var matcher = new goog.ui.ac.ArrayMatcher(data, !opt_useSimilar);
    -  var renderer = new goog.ui.ac.Renderer();
    -  var inputHandler = new goog.ui.ac.InputHandler(null, null, !!opt_multi);
    -
    -  var autoComplete = new goog.ui.ac.AutoComplete(
    -      matcher, renderer, inputHandler);
    -  inputHandler.attachAutoComplete(autoComplete);
    -  inputHandler.attachInputs(input);
    -  return autoComplete;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/ac/ac_test.html b/src/database/third_party/closure-library/closure/goog/ui/ac/ac_test.html
    deleted file mode 100644
    index 9a1de80b0fb..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/ac/ac_test.html
    +++ /dev/null
    @@ -1,28 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -
    -  Integration tests for the entire autocomplete package.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.ac.AutoComplete
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.ui.acTest');
    -  </script>
    - </head>
    - <body id="body">
    -  <input type="text" id="input" />
    -  <input type="text" id="user" value="For manual testing" />
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/ac/ac_test.js b/src/database/third_party/closure-library/closure/goog/ui/ac/ac_test.js
    deleted file mode 100644
    index a6e1967e28f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/ac/ac_test.js
    +++ /dev/null
    @@ -1,209 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.acTest');
    -goog.setTestOnly('goog.ui.acTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.NodeType');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.dom.selection');
    -goog.require('goog.events');
    -goog.require('goog.events.BrowserEvent');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.style');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.ac');
    -goog.require('goog.userAgent');
    -var autocomplete;
    -var data = ['ab', 'aab', 'aaab'];
    -var input;
    -var mockClock;
    -
    -function setUpPage() {
    -  goog.ui.ac.createSimpleAutoComplete(data, goog.dom.getElement('user'), true,
    -      false);
    -}
    -
    -function setUp() {
    -  mockClock = new goog.testing.MockClock(true);
    -  input = goog.dom.getElement('input');
    -  input.value = '';
    -  autocomplete = goog.ui.ac.createSimpleAutoComplete(data, input, true, false);
    -}
    -
    -function tearDown() {
    -  autocomplete.dispose();
    -  mockClock.dispose();
    -}
    -
    -//=========================================================================
    -// Utility methods
    -
    -
    -/**
    - * Fire listeners of a given type that are listening to the event's
    - * currentTarget.
    - *
    - * @param {goog.events.BrowserEvent} event
    - */
    -function simulateEvent(event) {
    -  goog.events.fireListeners(
    -      event.currentTarget, event.type, true, event);
    -  goog.events.fireListeners(
    -      event.currentTarget, event.type, false, event);
    -}
    -
    -
    -/**
    - * Fire all key event listeners that are listening to the input element.
    - *
    - * @param {number} keyCode The key code.
    - */
    -function simulateAllKeyEventsOnInput(keyCode) {
    -  var eventTypes = [
    -    goog.events.EventType.KEYDOWN,
    -    goog.events.EventType.KEYPRESS,
    -    goog.events.EventType.KEYUP
    -  ];
    -
    -  goog.array.forEach(eventTypes,
    -      function(type) {
    -        var event = new goog.events.Event(type, input);
    -        event.keyCode = keyCode;
    -        simulateEvent(new goog.events.BrowserEvent(event, input));
    -      });
    -}
    -
    -
    -/**
    - * @param {string} text
    - * @return {Node} Node whose inner text maches the given text.
    - */
    -function findNodeByInnerText(text) {
    -  return goog.dom.findNode(document.body, function(node) {
    -    try {
    -      var display = goog.userAgent.IE ?
    -          goog.style.getCascadedStyle(node, 'display') :
    -          goog.style.getComputedStyle(node, 'display');
    -
    -      return goog.dom.getRawTextContent(node) == text &&
    -          'none' != display && node.nodeType == goog.dom.NodeType.ELEMENT;
    -    } catch (e) {
    -      return false;
    -    }
    -  });
    -}
    -
    -//=========================================================================
    -// Tests
    -
    -
    -/**
    - * Ensure that the display of the autocompleter works.
    - */
    -function testBasicDisplay() {
    -  simulateAllKeyEventsOnInput(goog.events.KeyCodes.DOWN);
    -
    -  input.value = 'a';
    -  simulateAllKeyEventsOnInput(goog.events.KeyCodes.A);
    -  mockClock.tick(500);
    -
    -  var nodes = [
    -    findNodeByInnerText(data[0]),
    -    findNodeByInnerText(data[1]),
    -    findNodeByInnerText(data[2])
    -  ];
    -  assert(!!nodes[0]);
    -  assert(!!nodes[1]);
    -  assert(!!nodes[2]);
    -  assert(goog.style.isUnselectable(nodes[0]));
    -  assert(goog.style.isUnselectable(nodes[1]));
    -  assert(goog.style.isUnselectable(nodes[2]));
    -
    -  input.value = 'aa';
    -  simulateAllKeyEventsOnInput(goog.events.KeyCodes.A);
    -  mockClock.tick(500);
    -
    -  assertFalse(!!findNodeByInnerText(data[0]));
    -  assert(!!findNodeByInnerText(data[1]));
    -  assert(!!findNodeByInnerText(data[2]));
    -}
    -
    -
    -/**
    - * Ensure that key navigation with multiple inputs work
    - */
    -function testKeyNavigation() {
    -  simulateAllKeyEventsOnInput(goog.events.KeyCodes.DOWN);
    -
    -  input.value = 'c, a';
    -  goog.dom.selection.setCursorPosition(input, 'c, a'.length);
    -  simulateAllKeyEventsOnInput(goog.events.KeyCodes.A);
    -  mockClock.tick(500);
    -
    -  assert(document.body.innerHTML, !!findNodeByInnerText(data[1]));
    -  assert(!!findNodeByInnerText(data[2]));
    -
    -  var selected = goog.asserts.assertElement(findNodeByInnerText(data[0]));
    -  assertTrue('Should have new standard active class',
    -      goog.dom.classlist.contains(selected, 'ac-active'));
    -  assertTrue('Should have legacy active class',
    -      goog.dom.classlist.contains(selected, 'active'));
    -
    -  simulateAllKeyEventsOnInput(goog.events.KeyCodes.DOWN);
    -  assertFalse(goog.dom.classlist.contains(
    -      goog.asserts.assertElement(findNodeByInnerText(data[0])), 'ac-active'));
    -  assert(goog.dom.classlist.contains(
    -      goog.asserts.assertElement(findNodeByInnerText(data[1])), 'ac-active'));
    -
    -  simulateAllKeyEventsOnInput(goog.events.KeyCodes.ENTER);
    -  assertEquals('c, aab, ', input.value);
    -}
    -
    -
    -/**
    - * Ensure that mouse navigation with multiple inputs works.
    - */
    -function testMouseNavigation() {
    -  simulateAllKeyEventsOnInput(goog.events.KeyCodes.DOWN);
    -
    -  input.value = 'c, a';
    -  goog.dom.selection.setCursorPosition(input, 'c, a'.length);
    -  simulateAllKeyEventsOnInput(goog.events.KeyCodes.A);
    -  mockClock.tick(500);
    -
    -  var secondOption = goog.asserts.assertElement(findNodeByInnerText(data[1]));
    -  var parent = secondOption.parentNode;
    -  assertFalse(goog.dom.classlist.contains(secondOption, 'ac-active'));
    -
    -  var mouseOver = new goog.events.Event(
    -      goog.events.EventType.MOUSEOVER, secondOption);
    -  simulateEvent(new goog.events.BrowserEvent(mouseOver, parent));
    -  assert(goog.dom.classlist.contains(secondOption, 'ac-active'));
    -
    -  var mouseDown = new goog.events.Event(
    -      goog.events.EventType.MOUSEDOWN, secondOption);
    -  simulateEvent(new goog.events.BrowserEvent(mouseDown, parent));
    -  var mouseClick = new goog.events.Event(
    -      goog.events.EventType.CLICK, secondOption);
    -  simulateEvent(new goog.events.BrowserEvent(mouseClick, parent));
    -
    -  assertEquals('c, aab, ', input.value);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/ac/arraymatcher.js b/src/database/third_party/closure-library/closure/goog/ui/ac/arraymatcher.js
    deleted file mode 100644
    index 6d41584e4cb..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/ac/arraymatcher.js
    +++ /dev/null
    @@ -1,216 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Basic class for matching words in an array.
    - *
    - */
    -
    -
    -goog.provide('goog.ui.ac.ArrayMatcher');
    -
    -goog.require('goog.string');
    -
    -
    -
    -/**
    - * Basic class for matching words in an array
    - * @constructor
    - * @param {Array<?>} rows Dictionary of items to match.  Can be objects if they
    - *     have a toString method that returns the value to match against.
    - * @param {boolean=} opt_noSimilar if true, do not do similarity matches for the
    - *     input token against the dictionary.
    - */
    -goog.ui.ac.ArrayMatcher = function(rows, opt_noSimilar) {
    -  this.rows_ = rows || [];
    -  this.useSimilar_ = !opt_noSimilar;
    -};
    -
    -
    -/**
    - * Replaces the rows that this object searches over.
    - * @param {Array<?>} rows Dictionary of items to match.
    - */
    -goog.ui.ac.ArrayMatcher.prototype.setRows = function(rows) {
    -  this.rows_ = rows || [];
    -};
    -
    -
    -/**
    - * Function used to pass matches to the autocomplete
    - * @param {string} token Token to match.
    - * @param {number} maxMatches Max number of matches to return.
    - * @param {Function} matchHandler callback to execute after matching.
    - * @param {string=} opt_fullString The full string from the input box.
    - */
    -goog.ui.ac.ArrayMatcher.prototype.requestMatchingRows =
    -    function(token, maxMatches, matchHandler, opt_fullString) {
    -
    -  var matches = this.useSimilar_ ?
    -      goog.ui.ac.ArrayMatcher.getMatchesForRows(token, maxMatches, this.rows_) :
    -      this.getPrefixMatches(token, maxMatches);
    -
    -  matchHandler(token, matches);
    -};
    -
    -
    -/**
    - * Matches the token against the specified rows, first looking for prefix
    - * matches and if that fails, then looking for similar matches.
    - *
    - * @param {string} token Token to match.
    - * @param {number} maxMatches Max number of matches to return.
    - * @param {!Array<?>} rows Rows to search for matches. Can be objects if they
    - *     have a toString method that returns the value to match against.
    - * @return {!Array<?>} Rows that match.
    - */
    -goog.ui.ac.ArrayMatcher.getMatchesForRows =
    -    function(token, maxMatches, rows) {
    -  var matches =
    -      goog.ui.ac.ArrayMatcher.getPrefixMatchesForRows(token, maxMatches, rows);
    -
    -  if (matches.length == 0) {
    -    matches = goog.ui.ac.ArrayMatcher.getSimilarMatchesForRows(token,
    -        maxMatches, rows);
    -  }
    -  return matches;
    -};
    -
    -
    -/**
    - * Matches the token against the start of words in the row.
    - * @param {string} token Token to match.
    - * @param {number} maxMatches Max number of matches to return.
    - * @return {!Array<?>} Rows that match.
    - */
    -goog.ui.ac.ArrayMatcher.prototype.getPrefixMatches =
    -    function(token, maxMatches) {
    -  return goog.ui.ac.ArrayMatcher.getPrefixMatchesForRows(token, maxMatches,
    -      this.rows_);
    -};
    -
    -
    -/**
    - * Matches the token against the start of words in the row.
    - * @param {string} token Token to match.
    - * @param {number} maxMatches Max number of matches to return.
    - * @param {!Array<?>} rows Rows to search for matches. Can be objects if they have
    - *     a toString method that returns the value to match against.
    - * @return {!Array<?>} Rows that match.
    - */
    -goog.ui.ac.ArrayMatcher.getPrefixMatchesForRows =
    -    function(token, maxMatches, rows) {
    -  var matches = [];
    -
    -  if (token != '') {
    -    var escapedToken = goog.string.regExpEscape(token);
    -    var matcher = new RegExp('(^|\\W+)' + escapedToken, 'i');
    -
    -    for (var i = 0; i < rows.length && matches.length < maxMatches; i++) {
    -      var row = rows[i];
    -      if (String(row).match(matcher)) {
    -        matches.push(row);
    -      }
    -    }
    -  }
    -  return matches;
    -};
    -
    -
    -/**
    - * Matches the token against similar rows, by calculating "distance" between the
    - * terms.
    - * @param {string} token Token to match.
    - * @param {number} maxMatches Max number of matches to return.
    - * @return {!Array<?>} The best maxMatches rows.
    - */
    -goog.ui.ac.ArrayMatcher.prototype.getSimilarRows = function(token, maxMatches) {
    -  return goog.ui.ac.ArrayMatcher.getSimilarMatchesForRows(token, maxMatches,
    -      this.rows_);
    -};
    -
    -
    -/**
    - * Matches the token against similar rows, by calculating "distance" between the
    - * terms.
    - * @param {string} token Token to match.
    - * @param {number} maxMatches Max number of matches to return.
    - * @param {!Array<?>} rows Rows to search for matches. Can be objects
    - *     if they have a toString method that returns the value to
    - *     match against.
    - * @return {!Array<?>} The best maxMatches rows.
    - */
    -goog.ui.ac.ArrayMatcher.getSimilarMatchesForRows =
    -    function(token, maxMatches, rows) {
    -  var results = [];
    -
    -  for (var index = 0; index < rows.length; index++) {
    -    var row = rows[index];
    -    var str = token.toLowerCase();
    -    var txt = String(row).toLowerCase();
    -    var score = 0;
    -
    -    if (txt.indexOf(str) != -1) {
    -      score = parseInt((txt.indexOf(str) / 4).toString(), 10);
    -
    -    } else {
    -      var arr = str.split('');
    -
    -      var lastPos = -1;
    -      var penalty = 10;
    -
    -      for (var i = 0, c; c = arr[i]; i++) {
    -        var pos = txt.indexOf(c);
    -
    -        if (pos > lastPos) {
    -          var diff = pos - lastPos - 1;
    -
    -          if (diff > penalty - 5) {
    -            diff = penalty - 5;
    -          }
    -
    -          score += diff;
    -
    -          lastPos = pos;
    -        } else {
    -          score += penalty;
    -          penalty += 5;
    -        }
    -      }
    -    }
    -
    -    if (score < str.length * 6) {
    -      results.push({
    -        str: row,
    -        score: score,
    -        index: index
    -      });
    -    }
    -  }
    -
    -  results.sort(function(a, b) {
    -    var diff = a.score - b.score;
    -    if (diff != 0) {
    -      return diff;
    -    }
    -    return a.index - b.index;
    -  });
    -
    -  var matches = [];
    -  for (var i = 0; i < maxMatches && i < results.length; i++) {
    -    matches.push(results[i].str);
    -  }
    -
    -  return matches;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/ac/arraymatcher_test.html b/src/database/third_party/closure-library/closure/goog/ui/ac/arraymatcher_test.html
    deleted file mode 100644
    index a6f044c709b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/ac/arraymatcher_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.ac.ArrayMatcher
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.ui.ac.ArrayMatcherTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/ac/arraymatcher_test.js b/src/database/third_party/closure-library/closure/goog/ui/ac/arraymatcher_test.js
    deleted file mode 100644
    index c778a87dd41..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/ac/arraymatcher_test.js
    +++ /dev/null
    @@ -1,133 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.ac.ArrayMatcherTest');
    -goog.setTestOnly('goog.ui.ac.ArrayMatcherTest');
    -
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.ac.ArrayMatcher');
    -// TODO(arv): Add more useful tests for the similarity matching.
    -
    -var ArrayMatcher = goog.ui.ac.ArrayMatcher;
    -
    -function testRequestingRows() {
    -  var items = ['a', 'Ab', 'abc', 'ba', 'ca'];
    -  var am = new ArrayMatcher(items, true);
    -
    -  var res;
    -  function matcher(token, matches) {
    -    assertEquals('a', token);
    -    res = matches;
    -    assertEquals('Should have three matches', 3, matches.length);
    -    assertEquals('a', matches[0]);
    -    assertEquals('Ab', matches[1]);
    -    assertEquals('abc', matches[2]);
    -  }
    -
    -  am.requestMatchingRows('a', 10, matcher);
    -  var res2 = goog.ui.ac.ArrayMatcher.getMatchesForRows('a', 10, items);
    -  assertArrayEquals(res, res2);
    -}
    -
    -function testRequestingRowsMaxMatches() {
    -  var items = ['a', 'Ab', 'abc', 'ba', 'ca'];
    -  var am = new ArrayMatcher(items, true);
    -
    -  function matcher(token, matches) {
    -    assertEquals('a', token);
    -    assertEquals('Should have two matches', 2, matches.length);
    -    assertEquals('a', matches[0]);
    -    assertEquals('Ab', matches[1]);
    -  }
    -
    -  am.requestMatchingRows('a', 2, matcher);
    -}
    -
    -function testRequestingRowsSimilarMatches() {
    -  // No prefix matches so use similar
    -  var items = ['b', 'c', 'ba', 'ca'];
    -  var am = new ArrayMatcher(items, false);
    -
    -  function matcher(token, matches) {
    -    assertEquals('a', token);
    -    assertEquals('Should have two matches', 2, matches.length);
    -    assertEquals('ba', matches[0]);
    -    assertEquals('ca', matches[1]);
    -  }
    -
    -  am.requestMatchingRows('a', 10, matcher);
    -}
    -
    -function testRequestingRowsSimilarMatchesMaxMatches() {
    -  // No prefix matches so use similar
    -  var items = ['b', 'c', 'ba', 'ca'];
    -  var am = new ArrayMatcher(items, false);
    -
    -  function matcher(token, matches) {
    -    assertEquals('a', token);
    -    assertEquals('Should have one match', 1, matches.length);
    -    assertEquals('ba', matches[0]);
    -  }
    -
    -  am.requestMatchingRows('a', 1, matcher);
    -}
    -
    -function testGetPrefixMatches() {
    -  var items = ['a', 'b', 'c'];
    -  var am = new ArrayMatcher(items, true);
    -
    -  var res = am.getPrefixMatches('a', 10);
    -  assertEquals('Should have one match', 1, res.length);
    -  assertEquals('Should return \'a\'', 'a', res[0]);
    -  var res2 = goog.ui.ac.ArrayMatcher.getPrefixMatchesForRows('a', 10, items);
    -  assertArrayEquals(res, res2);
    -}
    -
    -function testGetPrefixMatchesMaxMatches() {
    -  var items = ['a', 'Ab', 'abc', 'ba', 'ca'];
    -  var am = new ArrayMatcher(items, true);
    -
    -  var res = am.getPrefixMatches('a', 2);
    -  assertEquals('Should have two matches', 2, res.length);
    -  assertEquals('a', res[0]);
    -}
    -
    -function testGetPrefixMatchesEmptyToken() {
    -  var items = ['a', 'b', 'c'];
    -  var am = new ArrayMatcher(items, true);
    -
    -  var res = am.getPrefixMatches('', 10);
    -  assertEquals('Should have no matches', 0, res.length);
    -}
    -
    -function testGetSimilarRows() {
    -  var items = ['xa', 'xb', 'xc'];
    -  var am = new ArrayMatcher(items, true);
    -
    -  var res = am.getSimilarRows('a', 10);
    -  assertEquals('Should have one match', 1, res.length);
    -  assertEquals('xa', res[0]);
    -  var res2 = goog.ui.ac.ArrayMatcher.getSimilarMatchesForRows('a', 10, items);
    -  assertArrayEquals(res, res2);
    -}
    -
    -function testGetSimilarRowsMaxMatches() {
    -  var items = ['xa', 'xAa', 'xaAa'];
    -  var am = new ArrayMatcher(items, true);
    -
    -  var res = am.getSimilarRows('a', 2);
    -  assertEquals('Should have two matches', 2, res.length);
    -  assertEquals('xa', res[0]);
    -  assertEquals('xAa', res[1]);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/ac/autocomplete.js b/src/database/third_party/closure-library/closure/goog/ui/ac/autocomplete.js
    deleted file mode 100644
    index 4d710fdca17..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/ac/autocomplete.js
    +++ /dev/null
    @@ -1,921 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Gmail-like AutoComplete logic.
    - *
    - * @see ../../demos/autocomplete-basic.html
    - */
    -
    -goog.provide('goog.ui.ac.AutoComplete');
    -goog.provide('goog.ui.ac.AutoComplete.EventType');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.events');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.object');
    -
    -
    -
    -/**
    - * This is the central manager class for an AutoComplete instance. The matcher
    - * can specify disabled rows that should not be hilited or selected by
    - * implementing <code>isRowDisabled(row):boolean</code> for each autocomplete
    - * row. No row will be considered disabled if this method is not implemented.
    - *
    - * @param {Object} matcher A data source and row matcher, implements
    - *        <code>requestMatchingRows(token, maxMatches, matchCallback)</code>.
    - * @param {goog.events.EventTarget} renderer An object that implements
    - *        <code>
    - *          isVisible():boolean<br>
    - *          renderRows(rows:Array, token:string, target:Element);<br>
    - *          hiliteId(row-id:number);<br>
    - *          dismiss();<br>
    - *          dispose():
    - *        </code>.
    - * @param {Object} selectionHandler An object that implements
    - *        <code>
    - *          selectRow(row);<br>
    - *          update(opt_force);
    - *        </code>.
    - *
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - */
    -goog.ui.ac.AutoComplete = function(matcher, renderer, selectionHandler) {
    -  goog.events.EventTarget.call(this);
    -
    -  /**
    -   * A data-source which provides autocomplete suggestions.
    -   *
    -   * TODO(chrishenry): Tighten the type to !goog.ui.ac.AutoComplete.Matcher.
    -   *
    -   * @type {Object}
    -   * @protected
    -   * @suppress {underscore|visibility}
    -   */
    -  this.matcher_ = matcher;
    -
    -  /**
    -   * A handler which interacts with the input DOM element (textfield, textarea,
    -   * or richedit).
    -   *
    -   * TODO(chrishenry): Tighten the type to !Object.
    -   *
    -   * @type {Object}
    -   * @protected
    -   * @suppress {underscore|visibility}
    -   */
    -  this.selectionHandler_ = selectionHandler;
    -
    -  /**
    -   * A renderer to render/show/highlight/hide the autocomplete menu.
    -   * @type {goog.events.EventTarget}
    -   * @protected
    -   * @suppress {underscore|visibility}
    -   */
    -  this.renderer_ = renderer;
    -  goog.events.listen(
    -      renderer,
    -      [
    -        goog.ui.ac.AutoComplete.EventType.HILITE,
    -        goog.ui.ac.AutoComplete.EventType.SELECT,
    -        goog.ui.ac.AutoComplete.EventType.CANCEL_DISMISS,
    -        goog.ui.ac.AutoComplete.EventType.DISMISS
    -      ],
    -      this.handleEvent, false, this);
    -
    -  /**
    -   * Currently typed token which will be used for completion.
    -   * @type {?string}
    -   * @protected
    -   * @suppress {underscore|visibility}
    -   */
    -  this.token_ = null;
    -
    -  /**
    -   * Autocomplete suggestion items.
    -   * @type {Array<?>}
    -   * @protected
    -   * @suppress {underscore|visibility}
    -   */
    -  this.rows_ = [];
    -
    -  /**
    -   * Id of the currently highlighted row.
    -   * @type {number}
    -   * @protected
    -   * @suppress {underscore|visibility}
    -   */
    -  this.hiliteId_ = -1;
    -
    -  /**
    -   * Id of the first row in autocomplete menu. Note that new ids are assigned
    -   * everytime new suggestions are fetched.
    -   *
    -   * TODO(chrishenry): Figure out what subclass does with this value
    -   * and whether we should expose a more proper API.
    -   *
    -   * @type {number}
    -   * @protected
    -   * @suppress {underscore|visibility}
    -   */
    -  this.firstRowId_ = 0;
    -
    -  /**
    -   * The target HTML node for displaying.
    -   * @type {Element}
    -   * @protected
    -   * @suppress {underscore|visibility}
    -   */
    -  this.target_ = null;
    -
    -  /**
    -   * The timer id for dismissing autocomplete menu with a delay.
    -   * @type {?number}
    -   * @private
    -   */
    -  this.dismissTimer_ = null;
    -
    -  /**
    -   * Mapping from text input element to the anchor element. If the
    -   * mapping does not exist, the input element will act as the anchor
    -   * element.
    -   * @type {Object<Element>}
    -   * @private
    -   */
    -  this.inputToAnchorMap_ = {};
    -};
    -goog.inherits(goog.ui.ac.AutoComplete, goog.events.EventTarget);
    -
    -
    -/**
    - * The maximum number of matches that should be returned
    - * @type {number}
    - * @private
    - */
    -goog.ui.ac.AutoComplete.prototype.maxMatches_ = 10;
    -
    -
    -/**
    - * True iff the first row should automatically be highlighted
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.ac.AutoComplete.prototype.autoHilite_ = true;
    -
    -
    -/**
    - * True iff the user can unhilight all rows by pressing the up arrow.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.ac.AutoComplete.prototype.allowFreeSelect_ = false;
    -
    -
    -/**
    - * True iff item selection should wrap around from last to first. If
    - *     allowFreeSelect_ is on in conjunction, there is a step of free selection
    - *     before wrapping.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.ac.AutoComplete.prototype.wrap_ = false;
    -
    -
    -/**
    - * Whether completion from suggestion triggers fetching new suggestion.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.ac.AutoComplete.prototype.triggerSuggestionsOnUpdate_ = false;
    -
    -
    -/**
    - * Events associated with the autocomplete
    - * @enum {string}
    - */
    -goog.ui.ac.AutoComplete.EventType = {
    -
    -  /** A row has been highlighted by the renderer */
    -  ROW_HILITE: 'rowhilite',
    -
    -  // Note: The events below are used for internal autocomplete events only and
    -  // should not be used in non-autocomplete code.
    -
    -  /** A row has been mouseovered and should be highlighted by the renderer. */
    -  HILITE: 'hilite',
    -
    -  /** A row has been selected by the renderer */
    -  SELECT: 'select',
    -
    -  /** A dismiss event has occurred */
    -  DISMISS: 'dismiss',
    -
    -  /** Event that cancels a dismiss event */
    -  CANCEL_DISMISS: 'canceldismiss',
    -
    -  /**
    -   * Field value was updated.  A row field is included and is non-null when a
    -   * row has been selected.  The value of the row typically includes fields:
    -   * contactData and formattedValue as well as a toString function (though none
    -   * of these fields are guaranteed to exist).  The row field may be used to
    -   * return custom-type row data.
    -   */
    -  UPDATE: 'update',
    -
    -  /**
    -   * The list of suggestions has been updated, usually because either the list
    -   * has opened, or because the user has typed another character and the
    -   * suggestions have been updated, or the user has dismissed the autocomplete.
    -   */
    -  SUGGESTIONS_UPDATE: 'suggestionsupdate'
    -};
    -
    -
    -/**
    - * @typedef {{
    - *   requestMatchingRows:(!Function|undefined),
    - *   isRowDisabled:(!Function|undefined)
    - * }}
    - */
    -goog.ui.ac.AutoComplete.Matcher;
    -
    -
    -/**
    - * @return {!Object} The data source providing the `autocomplete
    - *     suggestions.
    - */
    -goog.ui.ac.AutoComplete.prototype.getMatcher = function() {
    -  return goog.asserts.assert(this.matcher_);
    -};
    -
    -
    -/**
    - * Sets the data source providing the autocomplete suggestions.
    - *
    - * See constructor documentation for the interface.
    - *
    - * @param {!Object} matcher The matcher.
    - * @protected
    - */
    -goog.ui.ac.AutoComplete.prototype.setMatcher = function(matcher) {
    -  this.matcher_ = matcher;
    -};
    -
    -
    -/**
    - * @return {!Object} The handler used to interact with the input DOM
    - *     element (textfield, textarea, or richedit), e.g. to update the
    - *     input DOM element with selected value.
    - * @protected
    - */
    -goog.ui.ac.AutoComplete.prototype.getSelectionHandler = function() {
    -  return goog.asserts.assert(this.selectionHandler_);
    -};
    -
    -
    -/**
    - * @return {goog.events.EventTarget} The renderer that
    - *     renders/shows/highlights/hides the autocomplete menu.
    - *     See constructor documentation for the expected renderer API.
    - */
    -goog.ui.ac.AutoComplete.prototype.getRenderer = function() {
    -  return this.renderer_;
    -};
    -
    -
    -/**
    - * Sets the renderer that renders/shows/highlights/hides the autocomplete
    - * menu.
    - *
    - * See constructor documentation for the expected renderer API.
    - *
    - * @param {goog.events.EventTarget} renderer The renderer.
    - * @protected
    - */
    -goog.ui.ac.AutoComplete.prototype.setRenderer = function(renderer) {
    -  this.renderer_ = renderer;
    -};
    -
    -
    -/**
    - * @return {?string} The currently typed token used for completion.
    - * @protected
    - */
    -goog.ui.ac.AutoComplete.prototype.getToken = function() {
    -  return this.token_;
    -};
    -
    -
    -/**
    - * Sets the current token (without changing the rendered autocompletion).
    - *
    - * NOTE(chrishenry): This method will likely go away when we figure
    - * out a better API.
    - *
    - * @param {?string} token The new token.
    - * @protected
    - */
    -goog.ui.ac.AutoComplete.prototype.setTokenInternal = function(token) {
    -  this.token_ = token;
    -};
    -
    -
    -/**
    - * @param {number} index The suggestion index, must be within the
    - *     interval [0, this.getSuggestionCount()).
    - * @return {Object} The currently suggested item at the given index
    - *     (or null if there is none).
    - */
    -goog.ui.ac.AutoComplete.prototype.getSuggestion = function(index) {
    -  return this.rows_[index];
    -};
    -
    -
    -/**
    - * @return {!Array<?>} The current autocomplete suggestion items.
    - */
    -goog.ui.ac.AutoComplete.prototype.getAllSuggestions = function() {
    -  return goog.asserts.assert(this.rows_);
    -};
    -
    -
    -/**
    - * @return {number} The number of currently suggested items.
    - */
    -goog.ui.ac.AutoComplete.prototype.getSuggestionCount = function() {
    -  return this.rows_.length;
    -};
    -
    -
    -/**
    - * @return {number} The id (not index!) of the currently highlighted row.
    - */
    -goog.ui.ac.AutoComplete.prototype.getHighlightedId = function() {
    -  return this.hiliteId_;
    -};
    -
    -
    -/**
    - * Generic event handler that handles any events this object is listening to.
    - * @param {goog.events.Event} e Event Object.
    - */
    -goog.ui.ac.AutoComplete.prototype.handleEvent = function(e) {
    -  var matcher = /** @type {?goog.ui.ac.AutoComplete.Matcher} */ (this.matcher_);
    -
    -  if (e.target == this.renderer_) {
    -    switch (e.type) {
    -      case goog.ui.ac.AutoComplete.EventType.HILITE:
    -        this.hiliteId(/** @type {number} */ (e.row));
    -        break;
    -
    -      case goog.ui.ac.AutoComplete.EventType.SELECT:
    -        var rowDisabled = false;
    -
    -        // e.row can be either a valid row id or empty.
    -        if (goog.isNumber(e.row)) {
    -          var rowId = e.row;
    -          var index = this.getIndexOfId(rowId);
    -          var row = this.rows_[index];
    -
    -          // Make sure the row selected is not a disabled row.
    -          rowDisabled = !!row && matcher.isRowDisabled &&
    -              matcher.isRowDisabled(row);
    -          if (row && !rowDisabled && this.hiliteId_ != rowId) {
    -            // Event target row not currently highlighted - fix the mismatch.
    -            this.hiliteId(rowId);
    -          }
    -        }
    -        if (!rowDisabled) {
    -          // Note that rowDisabled can be false even if e.row does not
    -          // contain a valid row ID; at least one client depends on us
    -          // proceeding anyway.
    -          this.selectHilited();
    -        }
    -        break;
    -
    -      case goog.ui.ac.AutoComplete.EventType.CANCEL_DISMISS:
    -        this.cancelDelayedDismiss();
    -        break;
    -
    -      case goog.ui.ac.AutoComplete.EventType.DISMISS:
    -        this.dismissOnDelay();
    -        break;
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Sets the max number of matches to fetch from the Matcher.
    - *
    - * @param {number} max Max number of matches.
    - */
    -goog.ui.ac.AutoComplete.prototype.setMaxMatches = function(max) {
    -  this.maxMatches_ = max;
    -};
    -
    -
    -/**
    - * Sets whether or not the first row should be highlighted by default.
    - *
    - * @param {boolean} autoHilite true iff the first row should be
    - *      highlighted by default.
    - */
    -goog.ui.ac.AutoComplete.prototype.setAutoHilite = function(autoHilite) {
    -  this.autoHilite_ = autoHilite;
    -};
    -
    -
    -/**
    - * Sets whether or not the up/down arrow can unhilite all rows.
    - *
    - * @param {boolean} allowFreeSelect true iff the up arrow can unhilite all rows.
    - */
    -goog.ui.ac.AutoComplete.prototype.setAllowFreeSelect =
    -    function(allowFreeSelect) {
    -  this.allowFreeSelect_ = allowFreeSelect;
    -};
    -
    -
    -/**
    - * Sets whether or not selections can wrap around the edges.
    - *
    - * @param {boolean} wrap true iff sections should wrap around the edges.
    - */
    -goog.ui.ac.AutoComplete.prototype.setWrap = function(wrap) {
    -  this.wrap_ = wrap;
    -};
    -
    -
    -/**
    - * Sets whether or not to request new suggestions immediately after completion
    - * of a suggestion.
    - *
    - * @param {boolean} triggerSuggestionsOnUpdate true iff completion should fetch
    - *     new suggestions.
    - */
    -goog.ui.ac.AutoComplete.prototype.setTriggerSuggestionsOnUpdate = function(
    -    triggerSuggestionsOnUpdate) {
    -  this.triggerSuggestionsOnUpdate_ = triggerSuggestionsOnUpdate;
    -};
    -
    -
    -/**
    - * Sets the token to match against.  This triggers calls to the Matcher to
    - * fetch the matches (up to maxMatches), and then it triggers a call to
    - * <code>renderer.renderRows()</code>.
    - *
    - * @param {string} token The string for which to search in the Matcher.
    - * @param {string=} opt_fullString Optionally, the full string in the input
    - *     field.
    - */
    -goog.ui.ac.AutoComplete.prototype.setToken = function(token, opt_fullString) {
    -  if (this.token_ == token) {
    -    return;
    -  }
    -  this.token_ = token;
    -  this.matcher_.requestMatchingRows(this.token_,
    -      this.maxMatches_, goog.bind(this.matchListener_, this), opt_fullString);
    -  this.cancelDelayedDismiss();
    -};
    -
    -
    -/**
    - * Gets the current target HTML node for displaying autocomplete UI.
    - * @return {Element} The current target HTML node for displaying autocomplete
    - *     UI.
    - */
    -goog.ui.ac.AutoComplete.prototype.getTarget = function() {
    -  return this.target_;
    -};
    -
    -
    -/**
    - * Sets the current target HTML node for displaying autocomplete UI.
    - * Can be an implementation specific definition of how to display UI in relation
    - * to the target node.
    - * This target will be passed into  <code>renderer.renderRows()</code>
    - *
    - * @param {Element} target The current target HTML node for displaying
    - *     autocomplete UI.
    - */
    -goog.ui.ac.AutoComplete.prototype.setTarget = function(target) {
    -  this.target_ = target;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the autocomplete's renderer is open.
    - */
    -goog.ui.ac.AutoComplete.prototype.isOpen = function() {
    -  return this.renderer_.isVisible();
    -};
    -
    -
    -/**
    - * @return {number} Number of rows in the autocomplete.
    - * @deprecated Use this.getSuggestionCount().
    - */
    -goog.ui.ac.AutoComplete.prototype.getRowCount = function() {
    -  return this.getSuggestionCount();
    -};
    -
    -
    -/**
    - * Moves the hilite to the next non-disabled row.
    - * Calls renderer.hiliteId() when there's something to do.
    - * @return {boolean} Returns true on a successful hilite.
    - */
    -goog.ui.ac.AutoComplete.prototype.hiliteNext = function() {
    -  var lastId = this.firstRowId_ + this.rows_.length - 1;
    -  var toHilite = this.hiliteId_;
    -  // Hilite the next row, skipping any disabled rows.
    -  for (var i = 0; i < this.rows_.length; i++) {
    -    // Increment to the next row.
    -    if (toHilite >= this.firstRowId_ && toHilite < lastId) {
    -      toHilite++;
    -    } else if (toHilite == -1) {
    -      toHilite = this.firstRowId_;
    -    } else if (this.allowFreeSelect_ && toHilite == lastId) {
    -      this.hiliteId(-1);
    -      return false;
    -    } else if (this.wrap_ && toHilite == lastId) {
    -      toHilite = this.firstRowId_;
    -    } else {
    -      return false;
    -    }
    -
    -    if (this.hiliteId(toHilite)) {
    -      return true;
    -    }
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Moves the hilite to the previous non-disabled row.  Calls
    - * renderer.hiliteId() when there's something to do.
    - * @return {boolean} Returns true on a successful hilite.
    - */
    -goog.ui.ac.AutoComplete.prototype.hilitePrev = function() {
    -  var lastId = this.firstRowId_ + this.rows_.length - 1;
    -  var toHilite = this.hiliteId_;
    -  // Hilite the previous row, skipping any disabled rows.
    -  for (var i = 0; i < this.rows_.length; i++) {
    -    // Decrement to the previous row.
    -    if (toHilite > this.firstRowId_) {
    -      toHilite--;
    -    } else if (this.allowFreeSelect_ && toHilite == this.firstRowId_) {
    -      this.hiliteId(-1);
    -      return false;
    -    } else if (this.wrap_ && (toHilite == -1 || toHilite == this.firstRowId_)) {
    -      toHilite = lastId;
    -    } else {
    -      return false;
    -    }
    -
    -    if (this.hiliteId(toHilite)) {
    -      return true;
    -    }
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Hilites the id if it's valid and the row is not disabled, otherwise does
    - * nothing.
    - * @param {number} id A row id (not index).
    - * @return {boolean} Whether the id was hilited. Returns false if the row is
    - *     disabled.
    - */
    -goog.ui.ac.AutoComplete.prototype.hiliteId = function(id) {
    -  var index = this.getIndexOfId(id);
    -  var row = this.rows_[index];
    -  var rowDisabled = !!row && this.matcher_.isRowDisabled &&
    -      this.matcher_.isRowDisabled(row);
    -  if (!rowDisabled) {
    -    this.hiliteId_ = id;
    -    this.renderer_.hiliteId(id);
    -    return index != -1;
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Hilites the index, if it's valid and the row is not disabled, otherwise does
    - * nothing.
    - * @param {number} index The row's index.
    - * @return {boolean} Whether the index was hilited.
    - */
    -goog.ui.ac.AutoComplete.prototype.hiliteIndex = function(index) {
    -  return this.hiliteId(this.getIdOfIndex_(index));
    -};
    -
    -
    -/**
    - * If there are any current matches, this passes the hilited row data to
    - * <code>selectionHandler.selectRow()</code>
    - * @return {boolean} Whether there are any current matches.
    - */
    -goog.ui.ac.AutoComplete.prototype.selectHilited = function() {
    -  var index = this.getIndexOfId(this.hiliteId_);
    -  if (index != -1) {
    -    var selectedRow = this.rows_[index];
    -    var suppressUpdate = this.selectionHandler_.selectRow(selectedRow);
    -    if (this.triggerSuggestionsOnUpdate_) {
    -      this.token_ = null;
    -      this.dismissOnDelay();
    -    } else {
    -      this.dismiss();
    -    }
    -    if (!suppressUpdate) {
    -      this.dispatchEvent({
    -        type: goog.ui.ac.AutoComplete.EventType.UPDATE,
    -        row: selectedRow,
    -        index: index
    -      });
    -      if (this.triggerSuggestionsOnUpdate_) {
    -        this.selectionHandler_.update(true);
    -      }
    -    }
    -    return true;
    -  } else {
    -    this.dismiss();
    -    this.dispatchEvent(
    -        {
    -          type: goog.ui.ac.AutoComplete.EventType.UPDATE,
    -          row: null,
    -          index: null
    -        });
    -    return false;
    -  }
    -};
    -
    -
    -/**
    - * Returns whether or not the autocomplete is open and has a highlighted row.
    - * @return {boolean} Whether an autocomplete row is highlighted.
    - */
    -goog.ui.ac.AutoComplete.prototype.hasHighlight = function() {
    -  return this.isOpen() && this.getIndexOfId(this.hiliteId_) != -1;
    -};
    -
    -
    -/**
    - * Clears out the token, rows, and hilite, and calls
    - * <code>renderer.dismiss()</code>
    - */
    -goog.ui.ac.AutoComplete.prototype.dismiss = function() {
    -  this.hiliteId_ = -1;
    -  this.token_ = null;
    -  this.firstRowId_ += this.rows_.length;
    -  this.rows_ = [];
    -  window.clearTimeout(this.dismissTimer_);
    -  this.dismissTimer_ = null;
    -  this.renderer_.dismiss();
    -  this.dispatchEvent(goog.ui.ac.AutoComplete.EventType.SUGGESTIONS_UPDATE);
    -  this.dispatchEvent(goog.ui.ac.AutoComplete.EventType.DISMISS);
    -};
    -
    -
    -/**
    - * Call a dismiss after a delay, if there's already a dismiss active, ignore.
    - */
    -goog.ui.ac.AutoComplete.prototype.dismissOnDelay = function() {
    -  if (!this.dismissTimer_) {
    -    this.dismissTimer_ = window.setTimeout(goog.bind(this.dismiss, this), 100);
    -  }
    -};
    -
    -
    -/**
    - * Cancels any delayed dismiss events immediately.
    - * @return {boolean} Whether a delayed dismiss was cancelled.
    - * @private
    - */
    -goog.ui.ac.AutoComplete.prototype.immediatelyCancelDelayedDismiss_ =
    -    function() {
    -  if (this.dismissTimer_) {
    -    window.clearTimeout(this.dismissTimer_);
    -    this.dismissTimer_ = null;
    -    return true;
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Cancel the active delayed dismiss if there is one.
    - */
    -goog.ui.ac.AutoComplete.prototype.cancelDelayedDismiss = function() {
    -  // Under certain circumstances a cancel event occurs immediately prior to a
    -  // delayedDismiss event that it should be cancelling. To handle this situation
    -  // properly, a timer is used to stop that event.
    -  // Using only the timer creates undesirable behavior when the cancel occurs
    -  // less than 10ms before the delayed dismiss timout ends. If that happens the
    -  // clearTimeout() will occur too late and have no effect.
    -  if (!this.immediatelyCancelDelayedDismiss_()) {
    -    window.setTimeout(goog.bind(this.immediatelyCancelDelayedDismiss_, this),
    -        10);
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.ac.AutoComplete.prototype.disposeInternal = function() {
    -  goog.ui.ac.AutoComplete.superClass_.disposeInternal.call(this);
    -  delete this.inputToAnchorMap_;
    -  this.renderer_.dispose();
    -  this.selectionHandler_.dispose();
    -  this.matcher_ = null;
    -};
    -
    -
    -/**
    - * Callback passed to Matcher when requesting matches for a token.
    - * This might be called synchronously, or asynchronously, or both, for
    - * any implementation of a Matcher.
    - * If the Matcher calls this back, with the same token this AutoComplete
    - * has set currently, then this will package the matching rows in object
    - * of the form
    - * <pre>
    - * {
    - *   id: an integer ID unique to this result set and AutoComplete instance,
    - *   data: the raw row data from Matcher
    - * }
    - * </pre>
    - *
    - * @param {string} matchedToken Token that corresponds with the rows.
    - * @param {!Array<?>} rows Set of data that match the given token.
    - * @param {(boolean|goog.ui.ac.RenderOptions)=} opt_options If true,
    - *     keeps the currently hilited (by index) element hilited. If false not.
    - *     Otherwise a RenderOptions object.
    - * @private
    - */
    -goog.ui.ac.AutoComplete.prototype.matchListener_ =
    -    function(matchedToken, rows, opt_options) {
    -  if (this.token_ != matchedToken) {
    -    // Matcher's response token doesn't match current token.
    -    // This is probably an async response that came in after
    -    // the token was changed, so don't do anything.
    -    return;
    -  }
    -
    -  this.renderRows(rows, opt_options);
    -};
    -
    -
    -/**
    - * Renders the rows and adds highlighting.
    - * @param {!Array<?>} rows Set of data that match the given token.
    - * @param {(boolean|goog.ui.ac.RenderOptions)=} opt_options If true,
    - *     keeps the currently hilited (by index) element hilited. If false not.
    - *     Otherwise a RenderOptions object.
    - */
    -goog.ui.ac.AutoComplete.prototype.renderRows = function(rows, opt_options) {
    -  // The optional argument should be a RenderOptions object.  It can be a
    -  // boolean for backwards compatibility, defaulting to false.
    -  var optionsObj = goog.typeOf(opt_options) == 'object' && opt_options;
    -
    -  var preserveHilited =
    -      optionsObj ? optionsObj.getPreserveHilited() : opt_options;
    -  var indexToHilite = preserveHilited ? this.getIndexOfId(this.hiliteId_) : -1;
    -
    -  // Current token matches the matcher's response token.
    -  this.firstRowId_ += this.rows_.length;
    -  this.rows_ = rows;
    -  var rendRows = [];
    -  for (var i = 0; i < rows.length; ++i) {
    -    rendRows.push({
    -      id: this.getIdOfIndex_(i),
    -      data: rows[i]
    -    });
    -  }
    -
    -  var anchor = null;
    -  if (this.target_) {
    -    anchor = this.inputToAnchorMap_[goog.getUid(this.target_)] || this.target_;
    -  }
    -  this.renderer_.setAnchorElement(anchor);
    -  this.renderer_.renderRows(rendRows, this.token_, this.target_);
    -
    -  var autoHilite = this.autoHilite_;
    -  if (optionsObj && optionsObj.getAutoHilite() !== undefined) {
    -    autoHilite = optionsObj.getAutoHilite();
    -  }
    -  this.hiliteId_ = -1;
    -  if ((autoHilite || indexToHilite >= 0) &&
    -      rendRows.length != 0 &&
    -      this.token_) {
    -    if (indexToHilite >= 0) {
    -      this.hiliteId(this.getIdOfIndex_(indexToHilite));
    -    } else {
    -      // Hilite the first non-disabled row.
    -      this.hiliteNext();
    -    }
    -  }
    -  this.dispatchEvent(goog.ui.ac.AutoComplete.EventType.SUGGESTIONS_UPDATE);
    -};
    -
    -
    -/**
    - * Gets the index corresponding to a particular id.
    - * @param {number} id A unique id for the row.
    - * @return {number} A valid index into rows_, or -1 if the id is invalid.
    - * @protected
    - */
    -goog.ui.ac.AutoComplete.prototype.getIndexOfId = function(id) {
    -  var index = id - this.firstRowId_;
    -  if (index < 0 || index >= this.rows_.length) {
    -    return -1;
    -  }
    -  return index;
    -};
    -
    -
    -/**
    - * Gets the id corresponding to a particular index.  (Does no checking.)
    - * @param {number} index The index of a row in the result set.
    - * @return {number} The id that currently corresponds to that index.
    - * @private
    - */
    -goog.ui.ac.AutoComplete.prototype.getIdOfIndex_ = function(index) {
    -  return this.firstRowId_ + index;
    -};
    -
    -
    -/**
    - * Attach text areas or input boxes to the autocomplete by DOM reference.  After
    - * elements are attached to the autocomplete, when a user types they will see
    - * the autocomplete drop down.
    - * @param {...Element} var_args Variable args: Input or text area elements to
    - *     attach the autocomplete too.
    - */
    -goog.ui.ac.AutoComplete.prototype.attachInputs = function(var_args) {
    -  // Delegate to the input handler
    -  var inputHandler = /** @type {goog.ui.ac.InputHandler} */
    -      (this.selectionHandler_);
    -  inputHandler.attachInputs.apply(inputHandler, arguments);
    -};
    -
    -
    -/**
    - * Detach text areas or input boxes to the autocomplete by DOM reference.
    - * @param {...Element} var_args Variable args: Input or text area elements to
    - *     detach from the autocomplete.
    - */
    -goog.ui.ac.AutoComplete.prototype.detachInputs = function(var_args) {
    -  // Delegate to the input handler
    -  var inputHandler = /** @type {goog.ui.ac.InputHandler} */
    -      (this.selectionHandler_);
    -  inputHandler.detachInputs.apply(inputHandler, arguments);
    -
    -  // Remove mapping from input to anchor if one exists.
    -  goog.array.forEach(arguments, function(input) {
    -    goog.object.remove(this.inputToAnchorMap_, goog.getUid(input));
    -  }, this);
    -};
    -
    -
    -/**
    - * Attaches the autocompleter to a text area or text input element
    - * with an anchor element. The anchor element is the element the
    - * autocomplete box will be positioned against.
    - * @param {Element} inputElement The input element. May be 'textarea',
    - *     text 'input' element, or any other element that exposes similar
    - *     interface.
    - * @param {Element} anchorElement The anchor element.
    - */
    -goog.ui.ac.AutoComplete.prototype.attachInputWithAnchor = function(
    -    inputElement, anchorElement) {
    -  this.inputToAnchorMap_[goog.getUid(inputElement)] = anchorElement;
    -  this.attachInputs(inputElement);
    -};
    -
    -
    -/**
    - * Forces an update of the display.
    - * @param {boolean=} opt_force Whether to force an update.
    - */
    -goog.ui.ac.AutoComplete.prototype.update = function(opt_force) {
    -  var inputHandler = /** @type {goog.ui.ac.InputHandler} */
    -      (this.selectionHandler_);
    -  inputHandler.update(opt_force);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/ac/autocomplete_test.html b/src/database/third_party/closure-library/closure/goog/ui/ac/autocomplete_test.html
    deleted file mode 100644
    index e35cc7eba69..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/ac/autocomplete_test.html
    +++ /dev/null
    @@ -1,26 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.ac.AutoComplete
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.ac.AutoCompleteTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="test-area">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/ac/autocomplete_test.js b/src/database/third_party/closure-library/closure/goog/ui/ac/autocomplete_test.js
    deleted file mode 100644
    index 359a255d00e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/ac/autocomplete_test.js
    +++ /dev/null
    @@ -1,1678 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.ac.AutoCompleteTest');
    -goog.setTestOnly('goog.ui.ac.AutoCompleteTest');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.dom');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.string');
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.mockmatchers');
    -goog.require('goog.ui.ac.AutoComplete');
    -goog.require('goog.ui.ac.InputHandler');
    -goog.require('goog.ui.ac.RenderOptions');
    -goog.require('goog.ui.ac.Renderer');
    -
    -
    -
    -/**
    - * Mock DataStore
    - * @constructor
    - */
    -function MockDS(opt_autoHilite) {
    -  this.autoHilite_ = opt_autoHilite;
    -  var disabledRow = {
    -    match: function(str) {return this.text.match(str);},
    -    rowDisabled: true,
    -    text: 'hello@u.edu'
    -  };
    -  this.rows_ = [
    -    '"Slartibartfast Theadore" <fjordmaster@magrathea.com>',
    -    '"Zaphod Beeblebrox" <theprez@universe.gov>',
    -    '"Ford Prefect" <ford@theguide.com>',
    -    '"Arthur Dent" <has.no.tea@gmail.com>',
    -    '"Marvin The Paranoid Android" <marv@googlemail.com>',
    -    'the.mice@magrathea.com',
    -    'the.mice@myotherdomain.com',
    -    'hello@a.com',
    -    disabledRow,
    -    'row@u.edu',
    -    'person@a.edu'
    -  ];
    -  this.isRowDisabled = function(row) {
    -    return !!row.rowDisabled;
    -  };
    -}
    -
    -MockDS.prototype.requestMatchingRows = function(token, maxMatches,
    -                                                matchHandler) {
    -  var escapedToken = goog.string.regExpEscape(token);
    -  var matcher = new RegExp('(^|\\W+)' + escapedToken);
    -  var matches = [];
    -  for (var i = 0; i < this.rows_.length && matches.length < maxMatches; ++i) {
    -    var row = this.rows_[i];
    -    if (row.match(matcher)) {
    -      matches.push(row);
    -    }
    -  }
    -  if (this.autoHilite_ === undefined) {
    -    matchHandler(token, matches);
    -  } else {
    -    var options = new goog.ui.ac.RenderOptions();
    -    options.setAutoHilite(this.autoHilite_);
    -    matchHandler(token, matches, options);
    -  }
    -};
    -
    -
    -/**
    - * Mock Selection Handler
    - */
    -
    -function MockSelect() {
    -}
    -goog.inherits(MockSelect, goog.events.EventTarget);
    -
    -MockSelect.prototype.selectRow = function(row) {
    -  this.selectedRow = row;
    -};
    -
    -
    -
    -/**
    - * Renderer subclass that exposes additional private members for testing.
    - * @constructor
    - */
    -function TestRend() {
    -  goog.ui.ac.Renderer.call(this, goog.dom.getElement('test-area'));
    -}
    -goog.inherits(TestRend, goog.ui.ac.Renderer);
    -
    -TestRend.prototype.getRenderedRows = function() {
    -  return this.rows_;
    -};
    -
    -TestRend.prototype.getHilitedRowIndex = function() {
    -  return this.hilitedRow_;
    -};
    -
    -TestRend.prototype.getHilitedRowDiv = function() {
    -  return this.rowDivs_[this.hilitedRow_];
    -};
    -
    -TestRend.prototype.getRowDiv = function(index) {
    -  return this.rowDivs_[index];
    -};
    -
    -var handler;
    -var inputElement;
    -var mockControl;
    -
    -function setUp() {
    -  inputElement = goog.dom.createDom('input', {type: 'text'});
    -  handler = new goog.events.EventHandler();
    -  mockControl = new goog.testing.MockControl();
    -}
    -
    -function tearDown() {
    -  handler.dispose();
    -  mockControl.$tearDown();
    -  goog.dom.removeChildren(goog.dom.getElement('test-area'));
    -}
    -
    -
    -/**
    - * Make sure results are truncated (or not) by setMaxMatches.
    - */
    -function testMaxMatches() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -
    -  ac.setMaxMatches(2);
    -  ac.setToken('the');
    -  assertEquals(2, rend.getRenderedRows().length);
    -  ac.setToken('');
    -
    -  ac.setMaxMatches(3);
    -  ac.setToken('the');
    -  assertEquals(3, rend.getRenderedRows().length);
    -  ac.setToken('');
    -
    -  ac.setMaxMatches(1000);
    -  ac.setToken('the');
    -  assertEquals(4, rend.getRenderedRows().length);
    -  ac.setToken('');
    -}
    -
    -function testHiliteViaMouse() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var updates = 0;
    -  var row = null;
    -  var rowNode = null;
    -  handler.listen(rend,
    -      goog.ui.ac.AutoComplete.EventType.ROW_HILITE,
    -      function(evt) {
    -        updates++;
    -        rowNode = evt.rowNode;
    -      });
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setMaxMatches(4);
    -  ac.setToken('the');
    -  // Need to set the startRenderingRows_ time to something long ago, otherwise
    -  // the mouse event will not be fired.  (The autocomplete logic waits for some
    -  // time to pass after rendering before firing mouseover events.)
    -  rend.startRenderingRows_ = -1;
    -  var hilitedRowDiv = rend.getRowDiv(3);
    -  goog.testing.events.fireMouseOverEvent(hilitedRowDiv);
    -  assertEquals(2, updates);
    -  assertTrue(goog.string.contains(rowNode.innerHTML, 'mice@myotherdomain.com'));
    -}
    -
    -function testMouseClickBeforeHilite() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setMaxMatches(4);
    -  ac.setToken('the');
    -  // Need to set the startRenderingRows_ time to something long ago, otherwise
    -  // the mouse event will not be fired.  (The autocomplete logic waits for some
    -  // time to pass after rendering before firing mouseover events.)
    -  rend.startRenderingRows_ = -1;
    -
    -  // hilite row 3...
    -  var hilitedRowDiv = rend.getRowDiv(3);
    -  goog.testing.events.fireMouseOverEvent(hilitedRowDiv);
    -
    -  // but click row 2, to simulate mouse getting ahead of focus.
    -  var targetRowDiv = rend.getRowDiv(2);
    -  goog.testing.events.fireClickEvent(targetRowDiv);
    -
    -  assertEquals('the.mice@magrathea.com', select.selectedRow);
    -}
    -
    -function testMouseClickOnFirstRowBeforeHilite() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setAutoHilite(false);
    -  ac.setMaxMatches(4);
    -  ac.setToken('the');
    -
    -  // Click the first row before highlighting it, to simulate mouse getting ahead
    -  // of focus.
    -  var targetRowDiv = rend.getRowDiv(0);
    -  goog.testing.events.fireClickEvent(targetRowDiv);
    -
    -  assertEquals(
    -      '"Zaphod Beeblebrox" <theprez@universe.gov>', select.selectedRow);
    -}
    -
    -function testMouseClickOnRowAfterBlur() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var ih = new goog.ui.ac.InputHandler();
    -  ih.attachInput(inputElement);
    -
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, ih);
    -  goog.testing.events.fireFocusEvent(inputElement);
    -  ac.setToken('the');
    -  var targetRowDiv = rend.getRowDiv(0);
    -
    -  // Simulate the user clicking on an autocomplete row in the short time between
    -  // blur and autocomplete dismissal.
    -  goog.testing.events.fireBlurEvent(inputElement);
    -  assertNotThrows(function() {
    -    goog.testing.events.fireClickEvent(targetRowDiv);
    -  });
    -}
    -
    -
    -/*
    - * Send AutoComplete a SELECT event with empty string for the row. We can't
    - * simulate with a simple mouse click, so we dispatch the event directly.
    - */
    -function testSelectEventEmptyRow() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setMaxMatches(4);
    -  ac.setToken('the');
    -  rend.startRenderingRows_ = -1;
    -
    -  // hilight row 2 ('the.mice@...')
    -  var hilitedRowDiv = rend.getRowDiv(2);
    -  goog.testing.events.fireMouseOverEvent(hilitedRowDiv);
    -  assertUndefined(select.selectedRow);
    -
    -  // Dispatch an event that does not specify a row.
    -  rend.dispatchEvent({
    -    type: goog.ui.ac.AutoComplete.EventType.SELECT,
    -    row: ''
    -  });
    -
    -  assertEquals('the.mice@magrathea.com', select.selectedRow);
    -}
    -
    -function testSuggestionsUpdateEvent() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  var updates = 0;
    -  handler.listen(ac,
    -      goog.ui.ac.AutoComplete.EventType.SUGGESTIONS_UPDATE,
    -      function() {
    -        updates++;
    -      });
    -
    -  ac.setToken('the');
    -  assertEquals(1, updates);
    -
    -  ac.setToken('beeb');
    -  assertEquals(2, updates);
    -
    -  ac.setToken('ford');
    -  assertEquals(3, updates);
    -
    -  ac.dismiss();
    -  assertEquals(4, updates);
    -
    -  ac.setToken('dent');
    -  assertEquals(5, updates);
    -}
    -
    -function checkHilitedIndex(renderer, index) {
    -  assertEquals(index, renderer.getHilitedRowIndex());
    -}
    -
    -function testGetRowCount() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  assertEquals(0, ac.getRowCount());
    -
    -  ac.setToken('Zaphod');
    -  assertEquals(1, ac.getRowCount());
    -
    -  ac.setMaxMatches(2);
    -  ac.setToken('the');
    -  assertEquals(2, ac.getRowCount());
    -}
    -
    -
    -/**
    - * Try using next and prev to navigate past the ends with default behavior of
    - * allowFreeSelect_ and wrap_.
    - */
    -function testHiliteNextPrev_default() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -
    -  var updates = 0;
    -  handler.listen(rend,
    -      goog.ui.ac.AutoComplete.EventType.ROW_HILITE,
    -      function() {
    -        updates++;
    -      });
    -
    -  // make sure 'next' and 'prev' don't explode before any token is set
    -  ac.hiliteNext();
    -  ac.hilitePrev();
    -  ac.setMaxMatches(4);
    -  assertEquals(0, rend.getRenderedRows().length);
    -
    -  // check a few times
    -  for (var i = 0; i < 3; ++i) {
    -    ac.setToken('');
    -    ac.setToken('the');
    -    assertEquals(4, rend.getRenderedRows().length);
    -    // check to see if we can select the last of the 4 items
    -    checkHilitedIndex(rend, 0);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 1);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 2);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 3);
    -    // try going over the edge
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 3);
    -
    -    // go back down
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 2);
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 1);
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 0);
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 0);
    -  }
    -  // 21 changes in the loop above (3 * 7)
    -  assertEquals(21, updates);
    -}
    -
    -
    -/**
    - * Try using next and prev to navigate past the ends with default behavior of
    - * allowFreeSelect_ and wrap_ and with a disabled first row.
    - */
    -function testHiliteNextPrevWithDisabledFirstRow_default() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -
    -  var updates = 0;
    -  handler.listen(rend,
    -      goog.ui.ac.AutoComplete.EventType.ROW_HILITE,
    -      function() {
    -        updates++;
    -      });
    -
    -  // make sure 'next' and 'prev' don't explode before any token is set
    -  ac.hiliteNext();
    -  ac.hilitePrev();
    -  ac.setMaxMatches(3);
    -  assertEquals(0, rend.getRenderedRows().length);
    -
    -  // check a few times with disabled first row
    -  for (var i = 0; i < 3; ++i) {
    -    ac.setToken('');
    -    ac.setToken('edu');
    -    assertEquals(3, rend.getRenderedRows().length);
    -    // The first row is disabled, second should be highlighted.
    -    checkHilitedIndex(rend, 1);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 2);
    -    // try going over the edge
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 2);
    -
    -    // go back down
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 1);
    -    // First row is disabled, make sure we don't highlight it.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 1);
    -  }
    -  // 9 changes in the loop above (3 * 3)
    -  assertEquals(9, updates);
    -}
    -
    -
    -/**
    - * Try using next and prev to navigate past the ends with default behavior of
    - * allowFreeSelect_ and wrap_ and with a disabled middle row.
    - */
    -function testHiliteNextPrevWithDisabledMiddleRow_default() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -
    -  var updates = 0;
    -  handler.listen(rend,
    -      goog.ui.ac.AutoComplete.EventType.ROW_HILITE,
    -      function() {
    -        updates++;
    -      });
    -
    -  // make sure 'next' and 'prev' don't explode before any token is set
    -  ac.hiliteNext();
    -  ac.hilitePrev();
    -  ac.setMaxMatches(3);
    -  assertEquals(0, rend.getRenderedRows().length);
    -
    -  // check a few times with disabled middle row
    -  for (var i = 0; i < 3; ++i) {
    -    ac.setToken('');
    -    ac.setToken('u');
    -    assertEquals(3, rend.getRenderedRows().length);
    -    checkHilitedIndex(rend, 0);
    -    ac.hiliteNext();
    -    // Second row is disabled and should be skipped.
    -    checkHilitedIndex(rend, 2);
    -    // try going over the edge
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 2);
    -
    -    // go back down
    -    ac.hilitePrev();
    -    // Second row is disabled, make sure we don't highlight it.
    -    checkHilitedIndex(rend, 0);
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 0);
    -  }
    -  // 9 changes in the loop above (3 * 3)
    -  assertEquals(9, updates);
    -}
    -
    -
    -/**
    - * Try using next and prev to navigate past the ends with default behavior of
    - * allowFreeSelect_ and wrap_ and with a disabled last row.
    - */
    -function testHiliteNextPrevWithDisabledLastRow_default() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -
    -  var updates = 0;
    -  handler.listen(rend,
    -      goog.ui.ac.AutoComplete.EventType.ROW_HILITE,
    -      function() {
    -        updates++;
    -      });
    -
    -  // make sure 'next' and 'prev' don't explode before any token is set
    -  ac.hiliteNext();
    -  ac.hilitePrev();
    -  ac.setMaxMatches(3);
    -  assertEquals(0, rend.getRenderedRows().length);
    -
    -  // check a few times with disabled last row
    -  for (var i = 0; i < 3; ++i) {
    -    ac.setToken('');
    -    ac.setToken('h');
    -    assertEquals(3, rend.getRenderedRows().length);
    -    checkHilitedIndex(rend, 0);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 1);
    -    // try going over the edge since last row is disabled
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 1);
    -
    -    // go back down
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 0);
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 0);
    -  }
    -  // 9 changes in the loop above (3 * 3)
    -  assertEquals(9, updates);
    -}
    -
    -
    -/**
    - * Try using next and prev to navigate past the ends with wrap_ off and
    - * allowFreeSelect_ on.
    - */
    -function testHiliteNextPrev_allowFreeSelect() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setAllowFreeSelect(true);
    -
    -  // make sure 'next' and 'prev' don't explode before any token is set
    -  ac.hiliteNext();
    -  ac.hilitePrev();
    -  ac.setMaxMatches(4);
    -  assertEquals(0, rend.getRenderedRows().length);
    -
    -  // check a few times
    -  for (var i = 0; i < 3; ++i) {
    -    ac.setToken('');
    -    ac.setToken('the');
    -    assertEquals(4, rend.getRenderedRows().length);
    -    // check to see if we can select the last of the 4 items
    -    checkHilitedIndex(rend, 0);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 1);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 2);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 3);
    -    // try going over the edge. Since allowFreeSelect is on, this will
    -    // deselect the last row.
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, -1);
    -
    -    // go back down the list
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 0);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 1);
    -
    -    // go back up the list.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 0);
    -    // go back above the first, deselects first.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, -1);
    -  }
    -}
    -
    -
    -/**
    - * Try using next and prev to navigate past the ends with wrap_ off and
    - * allowFreeSelect_ on, and a disabled first row.
    - */
    -function testHiliteNextPrevWithDisabledFirstRow_allowFreeSelect() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setAllowFreeSelect(true);
    -
    -  // make sure 'next' and 'prev' don't explode before any token is set
    -  ac.hiliteNext();
    -  ac.hilitePrev();
    -  ac.setMaxMatches(4);
    -  assertEquals(0, rend.getRenderedRows().length);
    -
    -  // check a few times with disabled first row
    -  for (var i = 0; i < 3; ++i) {
    -    ac.setToken('');
    -    ac.setToken('edu');
    -    assertEquals(3, rend.getRenderedRows().length);
    -    // The first row is disabled, second should be highlighted.
    -    checkHilitedIndex(rend, 1);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 2);
    -    // Try going over the edge. Since allowFreeSelect is on, this will
    -    // deselect the last row.
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, -1);
    -
    -    // go back down the list, first row is disabled
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 1);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 2);
    -
    -    // go back up the list.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 1);
    -    // first is disabled, so deselect the second.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, -1);
    -  }
    -}
    -
    -
    -/**
    - * Try using next and prev to navigate past the ends with wrap_ off and
    - * allowFreeSelect_ on, and a disabled middle row.
    - */
    -function testHiliteNextPrevWithDisabledMiddleRow_allowFreeSelect() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setAllowFreeSelect(true);
    -
    -  // make sure 'next' and 'prev' don't explode before any token is set
    -  ac.hiliteNext();
    -  ac.hilitePrev();
    -  ac.setMaxMatches(4);
    -  assertEquals(0, rend.getRenderedRows().length);
    -
    -  // check a few times with disabled middle row
    -  for (var i = 0; i < 3; ++i) {
    -    ac.setToken('');
    -    ac.setToken('u');
    -    assertEquals(3, rend.getRenderedRows().length);
    -    checkHilitedIndex(rend, 0);
    -    ac.hiliteNext();
    -    // Second row is disabled and should be skipped.
    -    checkHilitedIndex(rend, 2);
    -    // try going over the edge. Since allowFreeSelect is on, this will
    -    // deselect the last row.
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, -1);
    -
    -    // go back down the list
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 0);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 2);
    -
    -    // go back up the list.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 0);
    -    // go back above the first, deselects first.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, -1);
    -  }
    -}
    -
    -
    -/**
    - * Try using next and prev to navigate past the ends with wrap_ off and
    - * allowFreeSelect_ on, and a disabled last row.
    - */
    -function testHiliteNextPrevWithDisabledLastRow_allowFreeSelect() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setAllowFreeSelect(true);
    -
    -  // make sure 'next' and 'prev' don't explode before any token is set
    -  ac.hiliteNext();
    -  ac.hilitePrev();
    -  ac.setMaxMatches(4);
    -  assertEquals(0, rend.getRenderedRows().length);
    -
    -  // check a few times with disabled last row
    -  for (var i = 0; i < 3; ++i) {
    -    ac.setToken('');
    -    ac.setToken('h');
    -    assertEquals(3, rend.getRenderedRows().length);
    -    checkHilitedIndex(rend, 0);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 1);
    -    // try going over the edge since last row is disabled. Since allowFreeSelect
    -    // is on, this will deselect the last row.
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, -1);
    -
    -    // go back down the list
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 0);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 1);
    -
    -    // go back up the list.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 0);
    -    // go back above the first, deselects first.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, -1);
    -  }
    -}
    -
    -
    -/**
    - * Try using next and prev to navigate past the ends with wrap_ on
    - * allowFreeSelect_ off.
    - */
    -function testHiliteNextPrev_wrap() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setWrap(true);
    -
    -  // make sure 'next' and 'prev' don't explode before any token is set
    -  ac.hiliteNext();
    -  ac.hilitePrev();
    -  ac.setMaxMatches(4);
    -  assertEquals(0, rend.getRenderedRows().length);
    -
    -  // check a few times
    -  for (var i = 0; i < 3; ++i) {
    -    ac.setToken('');
    -    ac.setToken('the');
    -    assertEquals(4, rend.getRenderedRows().length);
    -    // check to see if we can select the last of the 4 items
    -    checkHilitedIndex(rend, 0);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 1);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 2);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 3);
    -    // try going over the edge. Since wrap is on, this will go back to 0.
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 0);
    -
    -    // go back down the list
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 1);
    -
    -    // go back up the list.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 0);
    -    // go back above the first, selects last.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 3);
    -  }
    -}
    -
    -
    -/**
    - * Try using next and prev to navigate past the ends with wrap_ on
    - * allowFreeSelect_ off and a disabled first row.
    - */
    -function testHiliteNextPrevWithDisabledFirstRow_wrap() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setWrap(true);
    -
    -  // make sure 'next' and 'prev' don't explode before any token is set
    -  ac.hiliteNext();
    -  ac.hilitePrev();
    -  ac.setMaxMatches(4);
    -  assertEquals(0, rend.getRenderedRows().length);
    -
    -  // check a few times with disabled first row
    -  for (var i = 0; i < 3; ++i) {
    -    ac.setToken('');
    -    ac.setToken('edu');
    -    assertEquals(3, rend.getRenderedRows().length);
    -    // The first row is disabled, second should be highlighted.
    -    checkHilitedIndex(rend, 1);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 2);
    -    // try going over the edge. Since wrap is on and first row is disabled,
    -    // this will go back to 1.
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 1);
    -
    -    // go back down the list
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 2);
    -
    -    // go back up the list.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 1);
    -    // first is disabled, so wrap and select the last.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 2);
    -  }
    -}
    -
    -
    -/**
    - * Try using next and prev to navigate past the ends with wrap_ on
    - * allowFreeSelect_ off and a disabled middle row.
    - */
    -function testHiliteNextPrevWithDisabledMiddleRow_wrap() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setWrap(true);
    -
    -  // make sure 'next' and 'prev' don't explode before any token is set
    -  ac.hiliteNext();
    -  ac.hilitePrev();
    -  ac.setMaxMatches(4);
    -  assertEquals(0, rend.getRenderedRows().length);
    -
    -  // check a few times with disabled middle row
    -  for (var i = 0; i < 3; ++i) {
    -    ac.setToken('');
    -    ac.setToken('u');
    -    assertEquals(3, rend.getRenderedRows().length);
    -    checkHilitedIndex(rend, 0);
    -    ac.hiliteNext();
    -    // Second row is disabled and should be skipped.
    -    checkHilitedIndex(rend, 2);
    -    // try going over the edge. Since wrap is on, this will go back to 0.
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 0);
    -
    -    // go back down the list
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 2);
    -
    -    // go back up the list.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 0);
    -    // go back above the first, selects last.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 2);
    -  }
    -}
    -
    -
    -/**
    - * Try using next and prev to navigate past the ends with wrap_ on
    - * allowFreeSelect_ off and a disabled last row.
    - */
    -function testHiliteNextPrevWithDisabledLastRow_wrap() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setWrap(true);
    -
    -  // make sure 'next' and 'prev' don't explode before any token is set
    -  ac.hiliteNext();
    -  ac.hilitePrev();
    -  ac.setMaxMatches(4);
    -  assertEquals(0, rend.getRenderedRows().length);
    -
    -  // check a few times with disabled last row
    -  for (var i = 0; i < 3; ++i) {
    -    ac.setToken('');
    -    ac.setToken('h');
    -    assertEquals(3, rend.getRenderedRows().length);
    -    checkHilitedIndex(rend, 0);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 1);
    -    // try going over the edge since last row is disabled. Since wrap is on,
    -    // this will go back to 0.
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 0);
    -
    -    // go back down the list
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 1);
    -
    -    // go back up the list.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 0);
    -    // go back above the first, since wrap is on and last row is disabled, this
    -    // will select the second last.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 1);
    -  }
    -}
    -
    -
    -/**
    - * Try using next and prev to navigate past the ends with wrap_ on
    - * allowFreeSelect_ on.
    - */
    -function testHiliteNextPrev_wrapAndAllowFreeSelect() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setWrap(true);
    -  ac.setAllowFreeSelect(true);
    -
    -  // make sure 'next' and 'prev' don't explode before any token is set
    -  ac.hiliteNext();
    -  ac.hilitePrev();
    -  ac.setMaxMatches(4);
    -  assertEquals(0, rend.getRenderedRows().length);
    -
    -  // check a few times
    -  for (var i = 0; i < 3; ++i) {
    -    ac.setToken('');
    -    ac.setToken('the');
    -    assertEquals(4, rend.getRenderedRows().length);
    -    // check to see if we can select the last of the 4 items
    -    checkHilitedIndex(rend, 0);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 1);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 2);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 3);
    -    // try going over the edge. Since free select is on, this should go
    -    // to -1.
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, -1);
    -
    -    // go back down the list
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 0);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 1);
    -
    -    // go back up the list.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 0);
    -    // go back above the first, free select.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, -1);
    -    // wrap to last
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 3);
    -  }
    -}
    -
    -
    -/**
    - * Try using next and prev to navigate past the ends with wrap_ on
    - * allowFreeSelect_ on and a disabled first row.
    - */
    -function testHiliteNextPrevWithDisabledFirstRow_wrapAndAllowFreeSelect() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setWrap(true);
    -  ac.setAllowFreeSelect(true);
    -
    -  // make sure 'next' and 'prev' don't explode before any token is set
    -  ac.hiliteNext();
    -  ac.hilitePrev();
    -  ac.setMaxMatches(4);
    -  assertEquals(0, rend.getRenderedRows().length);
    -
    -  // check a few times with disabled first row
    -  for (var i = 0; i < 3; ++i) {
    -    ac.setToken('');
    -    ac.setToken('edu');
    -    assertEquals(3, rend.getRenderedRows().length);
    -    // The first row is disabled, second should be highlighted.
    -    checkHilitedIndex(rend, 1);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 2);
    -    // try going over the edge. Since free select is on, this should go to -1.
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, -1);
    -
    -    // go back down the list, fist row is disabled
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 1);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 2);
    -
    -    // go back up the list.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 1);
    -    // go back above the first, free select.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, -1);
    -    // wrap to last
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 2);
    -  }
    -}
    -
    -
    -/**
    - * Try using next and prev to navigate past the ends with wrap_ on
    - * allowFreeSelect_ on and a disabled middle row.
    - */
    -function testHiliteNextPrevWithDisabledMiddleRow_wrapAndAllowFreeSelect() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setWrap(true);
    -  ac.setAllowFreeSelect(true);
    -
    -  // make sure 'next' and 'prev' don't explode before any token is set
    -  ac.hiliteNext();
    -  ac.hilitePrev();
    -  ac.setMaxMatches(4);
    -  assertEquals(0, rend.getRenderedRows().length);
    -
    -  // check a few times with disabled middle row
    -  for (var i = 0; i < 3; ++i) {
    -    ac.setToken('');
    -    ac.setToken('u');
    -    assertEquals(3, rend.getRenderedRows().length);
    -    checkHilitedIndex(rend, 0);
    -    ac.hiliteNext();
    -    // Second row is disabled and should be skipped.
    -    checkHilitedIndex(rend, 2);
    -    // try going over the edge. Since free select is on, this should go to -1
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, -1);
    -
    -    // go back down the list
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 0);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 2);
    -
    -    // go back up the list.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 0);
    -    // go back above the first, free select.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, -1);
    -    // wrap to last
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 2);
    -  }
    -}
    -
    -
    -/**
    - * Try using next and prev to navigate past the ends with wrap_ on
    - * allowFreeSelect_ on and a disabled last row.
    - */
    -function testHiliteNextPrevWithDisabledLastRow_wrapAndAllowFreeSelect() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setWrap(true);
    -  ac.setAllowFreeSelect(true);
    -
    -  // make sure 'next' and 'prev' don't explode before any token is set
    -  ac.hiliteNext();
    -  ac.hilitePrev();
    -  ac.setMaxMatches(4);
    -  assertEquals(0, rend.getRenderedRows().length);
    -
    -  // check a few times with disabled last row
    -  for (var i = 0; i < 3; ++i) {
    -    ac.setToken('');
    -    ac.setToken('h');
    -    assertEquals(3, rend.getRenderedRows().length);
    -    checkHilitedIndex(rend, 0);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 1);
    -    // try going over the edge since last row is disabled. Since free select is
    -    // on, this should go to -1
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, -1);
    -
    -    // go back down the list
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 0);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 1);
    -
    -    // go back up the list.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 0);
    -    // go back above the first, free select.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, -1);
    -    // wrap to the second last, since last is disabled.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 1);
    -  }
    -}
    -
    -
    -/**
    - * Try using next and prev to navigate past the ends with wrap_ on
    - * allowFreeSelect_ on AND turn autoHilite_ off.
    - */
    -function testHiliteNextPrev_wrapAndAllowFreeSelectNoAutoHilite() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setWrap(true);
    -  ac.setAllowFreeSelect(true);
    -  ac.setAutoHilite(false);
    -
    -  // make sure 'next' and 'prev' don't explode before any token is set
    -  ac.hiliteNext();
    -  ac.hilitePrev();
    -  ac.setMaxMatches(4);
    -  assertEquals(0, rend.getRenderedRows().length);
    -
    -  // check a few times
    -  for (var i = 0; i < 3; ++i) {
    -    ac.setToken('');
    -    ac.setToken('the');
    -    assertEquals(4, rend.getRenderedRows().length);
    -    // check to see if we can select the last of the 4 items.
    -    // Initially nothing should be selected since autoHilite_ is off.
    -    checkHilitedIndex(rend, -1);
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 3);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, -1);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 0);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 1);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 2);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 3);
    -    // try going over the edge. Since free select is on, this should go
    -    // to -1.
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, -1);
    -
    -    // go back down the list
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 0);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 1);
    -
    -    // go back up the list.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 0);
    -    // go back above the first, free select.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, -1);
    -    // wrap to last
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 3);
    -  }
    -}
    -
    -
    -/**
    - * Try using next and prev to navigate past the ends with wrap_ on
    - * allowFreeSelect_ on AND turn autoHilite_ off, and a disabled first row.
    - */
    -function testHiliteNextPrevWithDisabledFirstRow_wrapAndAllowFreeSelectNoAutoHilite() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setWrap(true);
    -  ac.setAllowFreeSelect(true);
    -  ac.setAutoHilite(false);
    -
    -  // make sure 'next' and 'prev' don't explode before any token is set
    -  ac.hiliteNext();
    -  ac.hilitePrev();
    -  ac.setMaxMatches(4);
    -  assertEquals(0, rend.getRenderedRows().length);
    -
    -  // check a few times with disabled first row
    -  for (var i = 0; i < 3; ++i) {
    -    ac.setToken('');
    -    ac.setToken('edu');
    -    assertEquals(3, rend.getRenderedRows().length);
    -    // Initially nothing should be selected since autoHilite_ is off.
    -    checkHilitedIndex(rend, -1);
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 2);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, -1);
    -    ac.hiliteNext();
    -    // First row is disabled.
    -    checkHilitedIndex(rend, 1);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 2);
    -    // try going over the edge. Since free select is on, this should go to -1
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, -1);
    -
    -    // go back down the list, first row is disabled
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 1);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 2);
    -
    -    // go back up the list.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 1);
    -    // go back above the first, free select.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, -1);
    -    // wrap to last
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 2);
    -  }
    -}
    -
    -
    -/**
    - * Try using next and prev to navigate past the ends with wrap_ on
    - * allowFreeSelect_ on AND turn autoHilite_ off, and a disabled middle row.
    - */
    -function testHiliteNextPrevWithDisabledMiddleRow_wrapAndAllowFreeSelectNoAutoHilite() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setWrap(true);
    -  ac.setAllowFreeSelect(true);
    -  ac.setAutoHilite(false);
    -
    -  // make sure 'next' and 'prev' don't explode before any token is set
    -  ac.hiliteNext();
    -  ac.hilitePrev();
    -  ac.setMaxMatches(4);
    -  assertEquals(0, rend.getRenderedRows().length);
    -
    -  // check a few times with disabled middle row
    -  for (var i = 0; i < 3; ++i) {
    -    ac.setToken('');
    -    ac.setToken('u');
    -    assertEquals(3, rend.getRenderedRows().length);
    -    // Initially nothing should be selected since autoHilite_ is off.
    -    checkHilitedIndex(rend, -1);
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 2);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, -1);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 0);
    -    ac.hiliteNext();
    -    // Second row is disabled
    -    checkHilitedIndex(rend, 2);
    -    // try going over the edge. Since free select is on, this should go to -1.
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, -1);
    -
    -    // go back down the list
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 0);
    -    ac.hiliteNext();
    -    // Second row is disabled.
    -    checkHilitedIndex(rend, 2);
    -
    -    // go back up the list.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 0);
    -    // go back above the first, free select.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, -1);
    -    // wrap to last
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 2);
    -  }
    -}
    -
    -
    -/**
    - * Try using next and prev to navigate past the ends with wrap_ on
    - * allowFreeSelect_ on AND turn autoHilite_ off, and a disabled last row.
    - */
    -function testHiliteNextPrevWithDisabledLastRow_wrapAndAllowFreeSelectNoAutoHilite() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setWrap(true);
    -  ac.setAllowFreeSelect(true);
    -  ac.setAutoHilite(false);
    -
    -  // make sure 'next' and 'prev' don't explode before any token is set
    -  ac.hiliteNext();
    -  ac.hilitePrev();
    -  ac.setMaxMatches(4);
    -  assertEquals(0, rend.getRenderedRows().length);
    -
    -  // check a few times with disabled last row
    -  for (var i = 0; i < 3; ++i) {
    -    ac.setToken('');
    -    ac.setToken('h');
    -    assertEquals(3, rend.getRenderedRows().length);
    -    // Initially nothing should be selected since autoHilite_ is off.
    -    checkHilitedIndex(rend, -1);
    -    ac.hilitePrev();
    -    // Last row is disabled
    -    checkHilitedIndex(rend, 1);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, -1);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 0);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 1);
    -    // try going over the edge. Since free select is on, this should go to -1.
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, -1);
    -
    -    // go back down the list
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 0);
    -    ac.hiliteNext();
    -    checkHilitedIndex(rend, 1);
    -
    -    // go back up the list.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 0);
    -    // go back above the first, free select.
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, -1);
    -    // wrap to last
    -    ac.hilitePrev();
    -    checkHilitedIndex(rend, 1);
    -  }
    -}
    -
    -function testHiliteWithChangingNumberOfRows() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setAutoHilite(true);
    -  ac.setMaxMatches(4);
    -
    -  ac.setToken('m');
    -  assertEquals(4, rend.getRenderedRows().length);
    -  checkHilitedIndex(rend, 0);
    -
    -  ac.setToken('ma');
    -  assertEquals(3, rend.getRenderedRows().length);
    -  checkHilitedIndex(rend, 0);
    -
    -  // Hilite the second element
    -  var id = rend.getRenderedRows()[1].id;
    -  ac.hiliteId(id);
    -
    -  ac.setToken('mar');
    -  assertEquals(1, rend.getRenderedRows().length);
    -  checkHilitedIndex(rend, 0);
    -
    -  ac.setToken('ma');
    -  assertEquals(3, rend.getRenderedRows().length);
    -  checkHilitedIndex(rend, 0);
    -
    -  // Hilite the second element
    -  var id = rend.getRenderedRows()[1].id;
    -  ac.hiliteId(id);
    -
    -  ac.setToken('m');
    -  assertEquals(4, rend.getRenderedRows().length);
    -  checkHilitedIndex(rend, 0);
    -}
    -
    -
    -/**
    - * Checks that autohilite is disabled when there is no token; this allows the
    - * user to tab out of an empty autocomplete.
    - */
    -function testNoAutoHiliteWhenTokenIsEmpty() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setWrap(true);
    -  ac.setAllowFreeSelect(true);
    -  ac.setAutoHilite(true);
    -  ac.setMaxMatches(4);
    -
    -  ac.setToken('');
    -  assertEquals(4, rend.getRenderedRows().length);
    -  // No token; nothing should be hilited.
    -  checkHilitedIndex(rend, -1);
    -
    -  ac.setToken('the');
    -  assertEquals(4, rend.getRenderedRows().length);
    -  // Now there is a token, so the first row should be highlighted.
    -  checkHilitedIndex(rend, 0);
    -}
    -
    -
    -/**
    - * Checks that opt_preserveHilited works.
    - */
    -function testPreserveHilitedWithoutAutoHilite() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setWrap(true);
    -  ac.setAllowFreeSelect(true);
    -  ac.setMaxMatches(4);
    -  ac.setAutoHilite(false);
    -
    -  ac.setToken('m');
    -  assertEquals(4, rend.getRenderedRows().length);
    -  // No token; nothing should be hilited.
    -  checkHilitedIndex(rend, -1);
    -
    -  // Hilite the second element
    -  var id = rend.getRenderedRows()[1].id;
    -  ac.hiliteId(id);
    -
    -  checkHilitedIndex(rend, 1);
    -
    -  // Re-render and check if the second element is still hilited
    -  ac.renderRows(rend.getRenderedRows(), true /* preserve hilite */);
    -
    -  checkHilitedIndex(rend, 1);
    -
    -  // Re-render without preservation
    -  ac.renderRows(rend.getRenderedRows());
    -
    -  checkHilitedIndex(rend, -1);
    -}
    -
    -
    -/**
    - * Checks that the autohilite argument "true" of the matcher is used.
    - */
    -function testAutoHiliteFromMatcherTrue() {
    -  var ds = new MockDS(true);
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setWrap(true);
    -  ac.setAllowFreeSelect(true);
    -  ac.setAutoHilite(false);  // Will be overruled.
    -  ac.setMaxMatches(4);
    -
    -  ac.setToken('the');
    -  assertEquals(4, rend.getRenderedRows().length);
    -  // The first row should be highlighted.
    -  checkHilitedIndex(rend, 0);
    -}
    -
    -
    -/**
    - * Checks that the autohilite argument "false" of the matcher is used.
    - */
    -function testAutoHiliteFromMatcherFalse() {
    -  var ds = new MockDS(false);
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setWrap(true);
    -  ac.setAllowFreeSelect(true);
    -  ac.setAutoHilite(true);  // Will be overruled.
    -  ac.setMaxMatches(4);
    -
    -  ac.setToken('the');
    -  assertEquals(4, rend.getRenderedRows().length);
    -  // The first row should not be highlighted.
    -  checkHilitedIndex(rend, -1);
    -}
    -
    -
    -/**
    - * Hilite using ids, the way mouse-based hiliting would work.
    - */
    -function testHiliteId() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -
    -  // check a few times
    -  for (var i = 0; i < 3; ++i) {
    -    ac.setToken('m');
    -    assertEquals(4, rend.getRenderedRows().length);
    -    // try hiliting all 3
    -    for (var x = 0; x < 4; ++x) {
    -      var id = rend.getRenderedRows()[x].id;
    -      ac.hiliteId(id);
    -      assertEquals(ac.getIdOfIndex_(x), id);
    -    }
    -  }
    -}
    -
    -
    -/**
    - * Test selecting the hilited row
    - */
    -function testSelection() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac;
    -
    -  // try with default selection
    -  ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setToken('m');
    -  ac.selectHilited();
    -  assertEquals('"Slartibartfast Theadore" <fjordmaster@magrathea.com>',
    -               select.selectedRow);
    -
    -  // try second item
    -  ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setToken('the');
    -  ac.hiliteNext();
    -  ac.selectHilited();
    -  assertEquals('"Ford Prefect" <ford@theguide.com>',
    -               select.selectedRow);
    -}
    -
    -
    -/**
    - * Dismiss when empty and non-empty
    - */
    -function testDismiss() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -
    -  // dismiss empty
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  var dismissed = 0;
    -  handler.listen(ac,
    -      goog.ui.ac.AutoComplete.EventType.DISMISS,
    -      function() {
    -        dismissed++;
    -      });
    -  ac.dismiss();
    -  assertEquals(1, dismissed);
    -
    -  ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setToken('sir not seen in this picture');
    -  ac.dismiss();
    -
    -  // dismiss with contents
    -  ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setToken('t');
    -  ac.dismiss();
    -}
    -
    -function testTriggerSuggestionsOnUpdate() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -
    -  var dismissCalled = 0;
    -  rend.dismiss = function() {
    -    dismissCalled++;
    -  };
    -
    -  var updateCalled = 0;
    -  select.update = function(opt_force) {
    -    updateCalled++;
    -  };
    -
    -  // Normally, menu is dismissed after selecting row (without updating).
    -  ac.setToken('the');
    -  ac.selectHilited();
    -  assertEquals(1, dismissCalled);
    -  assertEquals(0, updateCalled);
    -
    -  // But not if we re-trigger on update.
    -  ac.setTriggerSuggestionsOnUpdate(true);
    -  ac.setToken('the');
    -  ac.selectHilited();
    -  assertEquals(1, dismissCalled);
    -  assertEquals(1, updateCalled);
    -}
    -
    -function testDispose() {
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setToken('the');
    -  ac.dispose();
    -}
    -
    -
    -/**
    - * Ensure that activedescendant is updated properly.
    - */
    -function testRolesAndStates() {
    -  function checkActiveDescendant(activeDescendant) {
    -    assertNotNull(inputElement);
    -    assertEquals(
    -        goog.a11y.aria.getActiveDescendant(inputElement),
    -        activeDescendant);
    -  }
    -  function checkRole(el, role) {
    -    assertNotNull(el);
    -    assertEquals(goog.a11y.aria.getRole(el), role);
    -  }
    -  var ds = new MockDS();
    -  var rend = new TestRend();
    -  var select = new MockSelect();
    -  var ac = new goog.ui.ac.AutoComplete(ds, rend, select);
    -  ac.setTarget(inputElement);
    -
    -  // initially activedescendant is not set
    -  checkActiveDescendant(null);
    -
    -  // highlight the matching row and check that activedescendant updates
    -  ac.setToken('');
    -  ac.setToken('the');
    -  ac.hiliteNext();
    -  checkActiveDescendant(rend.getHilitedRowDiv());
    -
    -  // highligted row should have a role of 'option'
    -  checkRole(rend.getHilitedRowDiv(), goog.a11y.aria.Role.OPTION);
    -
    -  // closing the autocomplete should clear activedescendant
    -  ac.dismiss();
    -  checkActiveDescendant(null);
    -}
    -
    -function testAttachInputWithAnchor() {
    -  var anchorElement = goog.dom.createDom('div', null, inputElement);
    -
    -  var mockRenderer = mockControl.createLooseMock(
    -      goog.ui.ac.Renderer, true);
    -  mockRenderer.setAnchorElement(anchorElement);
    -  var ignore = goog.testing.mockmatchers.ignoreArgument;
    -  mockRenderer.renderRows(ignore, ignore, inputElement);
    -
    -  var mockInputHandler = mockControl.createLooseMock(
    -      goog.ui.ac.InputHandler, true);
    -  mockInputHandler.attachInputs(inputElement);
    -
    -  mockControl.$replayAll();
    -  var autoComplete = new goog.ui.ac.AutoComplete(
    -      null, mockRenderer, mockInputHandler);
    -  autoComplete.attachInputWithAnchor(inputElement, anchorElement);
    -  autoComplete.setTarget(inputElement);
    -
    -  autoComplete.renderRows(['abc', 'def']);
    -  mockControl.$verifyAll();
    -}
    -
    -function testDetachInputWithAnchor() {
    -  var mockRenderer = mockControl.createLooseMock(
    -      goog.ui.ac.Renderer, true);
    -  var mockInputHandler = mockControl.createLooseMock(
    -      goog.ui.ac.InputHandler, true);
    -  var anchorElement = goog.dom.createDom('div', null, inputElement);
    -  var inputElement2 = goog.dom.createDom('input', {type: 'text'});
    -  var anchorElement2 = goog.dom.createDom('div', null, inputElement2);
    -
    -  mockControl.$replayAll();
    -  var autoComplete = new goog.ui.ac.AutoComplete(
    -      null, mockRenderer, mockInputHandler);
    -
    -  autoComplete.attachInputWithAnchor(inputElement, anchorElement);
    -  autoComplete.attachInputWithAnchor(inputElement2, anchorElement2);
    -  autoComplete.detachInputs(inputElement, inputElement2);
    -
    -  assertFalse(goog.getUid(inputElement) in autoComplete.inputToAnchorMap_);
    -  assertFalse(goog.getUid(inputElement2) in autoComplete.inputToAnchorMap_);
    -  mockControl.$verifyAll();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/ac/cachingmatcher.js b/src/database/third_party/closure-library/closure/goog/ui/ac/cachingmatcher.js
    deleted file mode 100644
    index 74ea2529764..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/ac/cachingmatcher.js
    +++ /dev/null
    @@ -1,273 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Matcher which maintains a client-side cache on top of some
    - * other matcher.
    - * @author reinerp@google.com (Reiner Pope)
    - */
    -
    -
    -goog.provide('goog.ui.ac.CachingMatcher');
    -
    -goog.require('goog.array');
    -goog.require('goog.async.Throttle');
    -goog.require('goog.ui.ac.ArrayMatcher');
    -goog.require('goog.ui.ac.RenderOptions');
    -
    -
    -
    -/**
    - * A matcher which wraps another (typically slow) matcher and
    - * keeps a client-side cache of the results. For instance, you can use this to
    - * wrap a RemoteArrayMatcher to hide the latency of the underlying matcher
    - * having to make ajax request.
    - *
    - * Objects in the cache are deduped on their stringified forms.
    - *
    - * Note - when the user types a character, they will instantly get a set of
    - * local results, and then some time later, the results from the server will
    - * show up.
    - *
    - * @constructor
    - * @param {!Object} baseMatcher The underlying matcher to use. Must implement
    - *     requestMatchingRows.
    - * @final
    - */
    -goog.ui.ac.CachingMatcher = function(baseMatcher) {
    -  /** @private {!Array<!Object>}} The cache. */
    -  this.rows_ = [];
    -
    -  /**
    -   * Set of stringified rows, for fast deduping. Each element of this.rows_
    -   * is stored in rowStrings_ as (' ' + row) to ensure we avoid builtin
    -   * properties like 'toString'.
    -   * @private {Object<string, boolean>}
    -   */
    -  this.rowStrings_ = {};
    -
    -  /**
    -   * Maximum number of rows in the cache. If the cache grows larger than this,
    -   * the entire cache will be emptied.
    -   * @private {number}
    -   */
    -  this.maxCacheSize_ = 1000;
    -
    -  /** @private {!Object} The underlying matcher to use. */
    -  this.baseMatcher_ = baseMatcher;
    -
    -  /**
    -   * Local matching function.
    -   * @private {function(string, number, !Array<!Object>): !Array<!Object>}
    -   */
    -  this.getMatchesForRows_ = goog.ui.ac.ArrayMatcher.getMatchesForRows;
    -
    -  /** @private {number} Number of matches to request from the base matcher. */
    -  this.baseMatcherMaxMatches_ = 100;
    -
    -  /** @private {goog.async.Throttle} */
    -  this.throttledTriggerBaseMatch_ =
    -      new goog.async.Throttle(this.triggerBaseMatch_, 150, this);
    -
    -  /** @private {string} */
    -  this.mostRecentToken_ = '';
    -
    -  /** @private {Function} */
    -  this.mostRecentMatchHandler_ = null;
    -
    -  /** @private {number} */
    -  this.mostRecentMaxMatches_ = 10;
    -
    -  /**
    -   * The set of rows which we last displayed.
    -   *
    -   * NOTE(reinerp): The need for this is subtle. When a server result comes
    -   * back, we don't want to suddenly change the list of results without the user
    -   * doing anything. So we make sure to add the new server results to the end of
    -   * the currently displayed list.
    -   *
    -   * We need to keep track of the last rows we displayed, because the "similar
    -   * matcher" we use locally might otherwise reorder results.
    -   *
    -   * @private {Array<!Object>}
    -   */
    -  this.mostRecentMatches_ = [];
    -};
    -
    -
    -/**
    - * Sets the number of milliseconds with which to throttle the match requests
    - * on the underlying matcher.
    - *
    - * Default value: 150.
    - *
    - * @param {number} throttleTime .
    - */
    -goog.ui.ac.CachingMatcher.prototype.setThrottleTime = function(throttleTime) {
    -  this.throttledTriggerBaseMatch_ =
    -      new goog.async.Throttle(this.triggerBaseMatch_, throttleTime, this);
    -};
    -
    -
    -/**
    - * Sets the maxMatches to use for the base matcher. If the base matcher makes
    - * AJAX requests, it may help to make this a large number so that the local
    - * cache gets populated quickly.
    - *
    - * Default value: 100.
    - *
    - * @param {number} maxMatches The value to set.
    - */
    -goog.ui.ac.CachingMatcher.prototype.setBaseMatcherMaxMatches =
    -    function(maxMatches) {
    -  this.baseMatcherMaxMatches_ = maxMatches;
    -};
    -
    -
    -/**
    - * Sets the maximum size of the local cache. If the local cache grows larger
    - * than this size, it will be emptied.
    - *
    - * Default value: 1000.
    - *
    - * @param {number} maxCacheSize .
    - */
    -goog.ui.ac.CachingMatcher.prototype.setMaxCacheSize = function(maxCacheSize) {
    -  this.maxCacheSize_ = maxCacheSize;
    -};
    -
    -
    -/**
    - * Sets the local matcher to use.
    - *
    - * The local matcher should be a function with the same signature as
    - * {@link goog.ui.ac.ArrayMatcher.getMatchesForRows}, i.e. its arguments are
    - * searchToken, maxMatches, rowsToSearch; and it returns a list of matching
    - * rows.
    - *
    - * Default value: {@link goog.ui.ac.ArrayMatcher.getMatchesForRows}.
    - *
    - * @param {function(string, number, !Array<!Object>): !Array<!Object>}
    - *     localMatcher
    - */
    -goog.ui.ac.CachingMatcher.prototype.setLocalMatcher = function(localMatcher) {
    -  this.getMatchesForRows_ = localMatcher;
    -};
    -
    -
    -/**
    - * Function used to pass matches to the autocomplete.
    - * @param {string} token Token to match.
    - * @param {number} maxMatches Max number of matches to return.
    - * @param {Function} matchHandler callback to execute after matching.
    - */
    -goog.ui.ac.CachingMatcher.prototype.requestMatchingRows =
    -    function(token, maxMatches, matchHandler) {
    -  this.mostRecentMaxMatches_ = maxMatches;
    -  this.mostRecentToken_ = token;
    -  this.mostRecentMatchHandler_ = matchHandler;
    -  this.throttledTriggerBaseMatch_.fire();
    -
    -  var matches = this.getMatchesForRows_(token, maxMatches, this.rows_);
    -  matchHandler(token, matches);
    -  this.mostRecentMatches_ = matches;
    -};
    -
    -
    -/**
    - * Adds the specified rows to the cache.
    - * @param {!Array<!Object>} rows .
    - * @private
    - */
    -goog.ui.ac.CachingMatcher.prototype.addRows_ = function(rows) {
    -  goog.array.forEach(rows, function(row) {
    -    // The ' ' prefix is to avoid colliding with builtins like toString.
    -    if (!this.rowStrings_[' ' + row]) {
    -      this.rows_.push(row);
    -      this.rowStrings_[' ' + row] = true;
    -    }
    -  }, this);
    -};
    -
    -
    -/**
    - * Checks if the cache is larger than the maximum cache size. If so clears it.
    - * @private
    - */
    -goog.ui.ac.CachingMatcher.prototype.clearCacheIfTooLarge_ = function() {
    -  if (this.rows_.length > this.maxCacheSize_) {
    -    this.rows_ = [];
    -    this.rowStrings_ = {};
    -  }
    -};
    -
    -
    -/**
    - * Triggers a match request against the base matcher. This function is
    - * unthrottled, so don't call it directly; instead use
    - * this.throttledTriggerBaseMatch_.
    - * @private
    - */
    -goog.ui.ac.CachingMatcher.prototype.triggerBaseMatch_ = function() {
    -  this.baseMatcher_.requestMatchingRows(this.mostRecentToken_,
    -      this.baseMatcherMaxMatches_, goog.bind(this.onBaseMatch_, this));
    -};
    -
    -
    -/**
    - * Handles a match response from the base matcher.
    - * @param {string} token The token against which the base match was called.
    - * @param {!Array<!Object>} matches The matches returned by the base matcher.
    - * @private
    - */
    -goog.ui.ac.CachingMatcher.prototype.onBaseMatch_ = function(token, matches) {
    -  // NOTE(reinerp): The user might have typed some more characters since the
    -  // base matcher request was sent out, which manifests in that token might be
    -  // older than this.mostRecentToken_. We make sure to do our local matches
    -  // using this.mostRecentToken_ rather than token so that we display results
    -  // relevant to what the user is seeing right now.
    -
    -  // NOTE(reinerp): We compute a diff between the currently displayed results
    -  // and the new results we would get now that the server results have come
    -  // back. Using this diff, we make sure the new results are only added to the
    -  // end of the list of results. See the documentation on
    -  // this.mostRecentMatches_ for details
    -
    -  this.addRows_(matches);
    -
    -  var oldMatchesSet = {};
    -  goog.array.forEach(this.mostRecentMatches_, function(match) {
    -    // The ' ' prefix is to avoid colliding with builtins like toString.
    -    oldMatchesSet[' ' + match] = true;
    -  });
    -  var newMatches = this.getMatchesForRows_(this.mostRecentToken_,
    -      this.mostRecentMaxMatches_, this.rows_);
    -  newMatches = goog.array.filter(newMatches, function(match) {
    -    return !(oldMatchesSet[' ' + match]);
    -  });
    -  newMatches = this.mostRecentMatches_.concat(newMatches)
    -      .slice(0, this.mostRecentMaxMatches_);
    -
    -  this.mostRecentMatches_ = newMatches;
    -
    -  // We've gone to the effort of keeping the existing rows as before, so let's
    -  // make sure to keep them highlighted.
    -  var options = new goog.ui.ac.RenderOptions();
    -  options.setPreserveHilited(true);
    -  this.mostRecentMatchHandler_(this.mostRecentToken_, newMatches, options);
    -
    -  // We clear the cache *after* running the local match, so we don't
    -  // suddenly remove results just because the remote match came back.
    -  this.clearCacheIfTooLarge_();
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/ac/cachingmatcher_test.html b/src/database/third_party/closure-library/closure/goog/ui/ac/cachingmatcher_test.html
    deleted file mode 100644
    index 1f78421f06e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/ac/cachingmatcher_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.ac.ArrayMatcher
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.ac.CachingMatcherTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/ac/cachingmatcher_test.js b/src/database/third_party/closure-library/closure/goog/ui/ac/cachingmatcher_test.js
    deleted file mode 100644
    index 9d4344ae218..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/ac/cachingmatcher_test.js
    +++ /dev/null
    @@ -1,214 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.ac.CachingMatcherTest');
    -goog.setTestOnly('goog.ui.ac.CachingMatcherTest');
    -
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.mockmatchers');
    -goog.require('goog.ui.ac.CachingMatcher');
    -ignoreArgument = goog.testing.mockmatchers.ignoreArgument;
    -
    -
    -
    -/**
    - * Fake version of Throttle which only fires when we call permitOne().
    - * @constructor
    - * @suppress {missingProvide}
    - */
    -goog.async.Throttle = function(fn, time, self) {
    -  this.fn = fn;
    -  this.time = time;
    -  this.self = self;
    -  this.numFires = 0;
    -};
    -
    -
    -/** @suppress {missingProvide} */
    -goog.async.Throttle.prototype.fire = function() {
    -  this.numFires++;
    -};
    -
    -
    -/** @suppress {missingProvide} */
    -goog.async.Throttle.prototype.permitOne = function() {
    -  if (this.numFires == 0) {
    -    return;
    -  }
    -  this.fn.call(this.self);
    -  this.numFires = 0;
    -};
    -
    -// Actual tests.
    -var mockControl;
    -var mockMatcher;
    -var mockHandler;
    -var matcher;
    -
    -function setUp() {
    -  mockControl = new goog.testing.MockControl();
    -  mockMatcher = {
    -    requestMatchingRows: mockControl.createFunctionMock('requestMatchingRows')
    -  };
    -  mockHandler = mockControl.createFunctionMock('matchHandler');
    -  matcher = new goog.ui.ac.CachingMatcher(mockMatcher);
    -}
    -
    -function tearDown() {
    -  mockControl.$tearDown();
    -}
    -
    -function testLocalThenRemoteMatch() {
    -  // We immediately get the local match.
    -  mockHandler('foo', []);
    -  mockControl.$replayAll();
    -  matcher.requestMatchingRows('foo', 12, mockHandler);
    -  mockControl.$verifyAll();
    -  mockControl.$resetAll();
    -
    -  // Now we run the remote match.
    -  mockHandler('foo', ['foo1', 'foo2'], ignoreArgument);
    -  mockMatcher.requestMatchingRows('foo', 100, ignoreArgument)
    -      .$does(function(token, maxResults, matchHandler) {
    -        matchHandler('foo', ['foo1', 'foo2', 'bar3']);
    -      });
    -  mockControl.$replayAll();
    -  matcher.throttledTriggerBaseMatch_.permitOne();
    -  mockControl.$verifyAll();
    -  mockControl.$resetAll();
    -}
    -
    -function testCacheSize() {
    -  matcher.setMaxCacheSize(4);
    -
    -  // First we populate, but not overflow the cache.
    -  mockHandler('foo', []);
    -  mockHandler('foo', ['foo111', 'foo222'], ignoreArgument);
    -  mockMatcher.requestMatchingRows('foo', 100, ignoreArgument)
    -      .$does(function(token, maxResults, matchHandler) {
    -        matchHandler('foo', ['foo111', 'foo222', 'bar333']);
    -      });
    -  mockControl.$replayAll();
    -  matcher.requestMatchingRows('foo', 12, mockHandler);
    -  matcher.throttledTriggerBaseMatch_.permitOne();
    -  mockControl.$verifyAll();
    -  mockControl.$resetAll();
    -
    -  // Now we verify the cache is populated.
    -  mockHandler('foo1', ['foo111']);
    -  mockControl.$replayAll();
    -  matcher.requestMatchingRows('foo1', 12, mockHandler);
    -  mockControl.$verifyAll();
    -  mockControl.$resetAll();
    -
    -  // Now we overflow the cache. Check that the remote results show the first
    -  // time we get them back, even though they overflow the cache.
    -  mockHandler('foo11', ['foo111']);
    -  mockHandler('foo11', ['foo111', 'foo112', 'foo113', 'foo114'],
    -              ignoreArgument);
    -  mockMatcher.requestMatchingRows('foo11', 100, ignoreArgument)
    -      .$does(function(token, maxResults, matchHandler) {
    -        matchHandler('foo11', ['foo111', 'foo112', 'foo113', 'foo114']);
    -      });
    -  mockControl.$replayAll();
    -  matcher.requestMatchingRows('foo11', 12, mockHandler);
    -  matcher.throttledTriggerBaseMatch_.permitOne();
    -  mockControl.$verifyAll();
    -  mockControl.$resetAll();
    -
    -  // Now check that the cache is empty.
    -  mockHandler('foo11', []);
    -  mockControl.$replayAll();
    -  matcher.requestMatchingRows('foo11', 12, mockHandler);
    -  mockControl.$verifyAll();
    -  mockControl.$resetAll();
    -}
    -
    -function testSimilarMatchingDoesntReorderResults() {
    -  // Populate the cache. We get two prefix matches.
    -  mockHandler('ba', []);
    -  mockHandler('ba', ['bar', 'baz', 'bam'], ignoreArgument);
    -  mockMatcher.requestMatchingRows('ba', 100, ignoreArgument)
    -      .$does(function(token, maxResults, matchHandler) {
    -        matchHandler('ba', ['bar', 'baz', 'bam']);
    -      });
    -  mockControl.$replayAll();
    -  matcher.requestMatchingRows('ba', 12, mockHandler);
    -  matcher.throttledTriggerBaseMatch_.permitOne();
    -  mockControl.$verifyAll();
    -  mockControl.$resetAll();
    -
    -  // The user types another character. The local match gives us two similar
    -  // matches, but no prefix matches. The remote match returns a prefix match,
    -  // which would normally be ranked above the similar matches, but gets ranked
    -  // below the similar matches because the user hasn't typed any more
    -  // characters.
    -  mockHandler('bad', ['bar', 'baz', 'bam']);
    -  mockHandler('bad', ['bar', 'baz', 'bam', 'bad', 'badder', 'baddest'],
    -              ignoreArgument);
    -  mockMatcher.requestMatchingRows('bad', 100, ignoreArgument)
    -      .$does(function(token, maxResults, matchHandler) {
    -        matchHandler('bad', ['bad', 'badder', 'baddest']);
    -      });
    -  mockControl.$replayAll();
    -  matcher.requestMatchingRows('bad', 12, mockHandler);
    -  matcher.throttledTriggerBaseMatch_.permitOne();
    -  mockControl.$verifyAll();
    -  mockControl.$resetAll();
    -
    -  // The user types yet another character, which allows the prefix matches to
    -  // jump to the top of the list of suggestions.
    -  mockHandler('badd', ['badder', 'baddest']);
    -  mockControl.$replayAll();
    -  matcher.requestMatchingRows('badd', 12, mockHandler);
    -  mockControl.$verifyAll();
    -  mockControl.$resetAll();
    -}
    -
    -function testSetThrottleTime() {
    -  assertEquals(150, matcher.throttledTriggerBaseMatch_.time);
    -  matcher.setThrottleTime(234);
    -  assertEquals(234, matcher.throttledTriggerBaseMatch_.time);
    -}
    -
    -function testSetBaseMatcherMaxMatches() {
    -  mockHandler('foo', []); // Local match
    -  mockMatcher.requestMatchingRows('foo', 789, ignoreArgument);
    -  mockControl.$replayAll();
    -  matcher.setBaseMatcherMaxMatches();
    -  matcher.requestMatchingRows('foo', 12, mockHandler);
    -}
    -
    -function testSetLocalMatcher() {
    -  // Use a local matcher which just sorts all the rows alphabetically.
    -  function sillyMatcher(token, maxMatches, rows) {
    -    rows = rows.concat([]);
    -    rows.sort();
    -    return rows;
    -  }
    -
    -  mockHandler('foo', []);
    -  mockHandler('foo', ['a', 'b', 'c'], ignoreArgument);
    -  mockMatcher.requestMatchingRows('foo', 100, ignoreArgument)
    -      .$does(function(token, maxResults, matchHandler) {
    -        matchHandler('foo', ['b', 'a', 'c']);
    -      });
    -  mockControl.$replayAll();
    -  matcher.setLocalMatcher(sillyMatcher);
    -  matcher.requestMatchingRows('foo', 12, mockHandler);
    -  matcher.throttledTriggerBaseMatch_.permitOne();
    -  mockControl.$verifyAll();
    -  mockControl.$resetAll();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/ac/inputhandler.js b/src/database/third_party/closure-library/closure/goog/ui/ac/inputhandler.js
    deleted file mode 100644
    index bedc799a323..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/ac/inputhandler.js
    +++ /dev/null
    @@ -1,1327 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Class for managing the interactions between an
    - * auto-complete object and a text-input or textarea.
    - *
    - * IME note:
    - *
    - * We used to suspend autocomplete while there are IME preedit characters, but
    - * now for parity with Search we do not. We still detect the beginning and end
    - * of IME entry because we need to listen to more events while an IME commit is
    - * happening, but we update continuously as the user types.
    - *
    - * IMEs vary across operating systems, browsers, and even input languages. This
    - * class tries to handle IME for:
    - * - Windows x {FF3, IE7, Chrome} x MS IME 2002 (Japanese)
    - * - Mac     x {FF3, Safari3}     x Kotoeri (Japanese)
    - * - Linux   x {FF3}              x UIM + Anthy (Japanese)
    - *
    - * TODO(user): We cannot handle {Mac, Linux} x FF3 correctly.
    - * TODO(user): We need to support Windows x Google IME.
    - *
    - * This class was tested with hiragana input. The event sequence when inputting
    - * 'ai<enter>' with IME on (which commits two characters) is as follows:
    - *
    - * Notation: [key down code, key press, key up code]
    - *           key code or +: event fired
    - *           -: event not fired
    - *
    - * - Win/FF3: [WIN_IME, +, A], [-, -, ENTER]
    - *            Note: No events are fired for 'i'.
    - *
    - * - Win/IE7: [WIN_IME, -, A], [WIN_IME, -, I], [WIN_IME, -, ENTER]
    - *
    - * - Win/Chrome: Same as Win/IE7
    - *
    - * - Mac/FF3: [A, -, A], [I, -, I], [ENTER, -, ENTER]
    - *
    - * - Mac/Safari3: Same as Win/IE7
    - *
    - * - Linux/FF3: No events are generated.
    - *
    - * With IME off,
    - *
    - * - ALL: [A, +, A], [I, +, I], [ENTER, +, ENTER]
    - *        Note: Key code of key press event varies across configuration.
    - *
    - * With Microsoft Pinyin IME 3.0 (Simplified Chinese),
    - *
    - * - Win/IE7: Same as Win/IE7 with MS IME 2002 (Japanese)
    - *
    - *   The issue with this IME is that the key sequence that ends preedit is not
    - *   a single ENTER key up.
    - *   - ENTER key up following either ENTER or SPACE ends preedit.
    - *   - SPACE key up following even number of LEFT, RIGHT, or SPACE (any
    - *     combination) ends preedit.
    - *   TODO(user): We only support SPACE-then-ENTER sequence.
    - *   TODO(mpd): With the change to autocomplete during IME, this might not be an
    - *   issue. Remove this comment once tested.
    - *
    - * With Microsoft Korean IME 2002,
    - *
    - * - Win/IE7: Same as Win/IE7 with MS IME 2002 (Japanese), but there is no
    - *   sequence that ends the preedit.
    - *
    - * The following is the algorithm we use to detect IME preedit:
    - *
    - * - WIN_IME key down starts predit.
    - * - (1) ENTER key up or (2) CTRL-M key up ends preedit.
    - * - Any key press not immediately following WIN_IME key down signifies that
    - *   preedit has ended.
    - *
    - * If you need to change this algorithm, please note the OS, browser, language,
    - * and behavior above so that we can avoid regressions. Contact mpd or yuzo
    - * if you have questions or concerns.
    - *
    - */
    -
    -
    -goog.provide('goog.ui.ac.InputHandler');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.Timer');
    -goog.require('goog.a11y.aria');
    -goog.require('goog.dom');
    -goog.require('goog.dom.selection');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.events.KeyHandler');
    -goog.require('goog.string');
    -goog.require('goog.userAgent');
    -goog.require('goog.userAgent.product');
    -
    -
    -
    -/**
    - * Class for managing the interaction between an auto-complete object and a
    - * text-input or textarea.
    - *
    - * @param {?string=} opt_separators Separators to split multiple entries.
    - *     If none passed, uses ',' and ';'.
    - * @param {?string=} opt_literals Characters used to delimit text literals.
    - * @param {?boolean=} opt_multi Whether to allow multiple entries
    - *     (Default: true).
    - * @param {?number=} opt_throttleTime Number of milliseconds to throttle
    - *     keyevents with (Default: 150). Use -1 to disable updates on typing. Note
    - *     that typing the separator will update autocomplete suggestions.
    - * @constructor
    - * @extends {goog.Disposable}
    - */
    -goog.ui.ac.InputHandler = function(opt_separators, opt_literals,
    -    opt_multi, opt_throttleTime) {
    -  goog.Disposable.call(this);
    -  var throttleTime = opt_throttleTime || 150;
    -
    -  /**
    -   * Whether this input accepts multiple values
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.multi_ = opt_multi != null ? opt_multi : true;
    -
    -  // Set separators depends on this.multi_ being set correctly
    -  this.setSeparators(opt_separators ||
    -      goog.ui.ac.InputHandler.STANDARD_LIST_SEPARATORS);
    -
    -  /**
    -   * Characters that are used to delimit literal text. Separarator characters
    -   * found within literal text are not processed as separators
    -   * @type {string}
    -   * @private
    -   */
    -  this.literals_ = opt_literals || '';
    -
    -  /**
    -   * Whether to prevent highlighted item selection when tab is pressed.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.preventSelectionOnTab_ = false;
    -
    -  /**
    -   * Whether to prevent the default behavior (moving focus to another element)
    -   * when tab is pressed.  This occurs by default only for multi-value mode.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.preventDefaultOnTab_ = this.multi_;
    -
    -  /**
    -   * A timer object used to monitor for changes when an element is active.
    -   *
    -   * TODO(user): Consider tuning the throttle time, so that it takes into
    -   * account the length of the token.  When the token is short it is likely to
    -   * match lots of rows, therefore we want to check less frequently.  Even
    -   * something as simple as <3-chars = 150ms, then 100ms otherwise.
    -   *
    -   * @type {goog.Timer}
    -   * @private
    -   */
    -  this.timer_ = throttleTime > 0 ? new goog.Timer(throttleTime) : null;
    -
    -  /**
    -   * Event handler used by the input handler to manage events.
    -   * @type {goog.events.EventHandler<!goog.ui.ac.InputHandler>}
    -   * @private
    -   */
    -  this.eh_ = new goog.events.EventHandler(this);
    -
    -  /**
    -   * Event handler to help us find an input element that already has the focus.
    -   * @type {goog.events.EventHandler<!goog.ui.ac.InputHandler>}
    -   * @private
    -   */
    -  this.activateHandler_ = new goog.events.EventHandler(this);
    -
    -  /**
    -   * The keyhandler used for listening on most key events.  This takes care of
    -   * abstracting away some of the browser differences.
    -   * @type {goog.events.KeyHandler}
    -   * @private
    -   */
    -  this.keyHandler_ = new goog.events.KeyHandler();
    -
    -  /**
    -   * The last key down key code.
    -   * @type {number}
    -   * @private
    -   */
    -  this.lastKeyCode_ = -1;  // Initialize to a non-existent value.
    -};
    -goog.inherits(goog.ui.ac.InputHandler, goog.Disposable);
    -
    -
    -/**
    - * Whether or not we need to pause the execution of the blur handler in order
    - * to allow the execution of the selection handler to run first. This is
    - * currently true when running on IOS version prior to 4.2, since we need
    - * some special logic for these devices to handle bug 4484488.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.ac.InputHandler.REQUIRES_ASYNC_BLUR_ =
    -    (goog.userAgent.product.IPHONE || goog.userAgent.product.IPAD) &&
    -        // Check the webkit version against the version for iOS 4.2.1.
    -        !goog.userAgent.isVersionOrHigher('533.17.9');
    -
    -
    -/**
    - * Standard list separators.
    - * @type {string}
    - * @const
    - */
    -goog.ui.ac.InputHandler.STANDARD_LIST_SEPARATORS = ',;';
    -
    -
    -/**
    - * Literals for quotes.
    - * @type {string}
    - * @const
    - */
    -goog.ui.ac.InputHandler.QUOTE_LITERALS = '"';
    -
    -
    -/**
    - * The AutoComplete instance this inputhandler is associated with.
    - * @type {goog.ui.ac.AutoComplete}
    - */
    -goog.ui.ac.InputHandler.prototype.ac_;
    -
    -
    -/**
    - * Characters that can be used to split multiple entries in an input string
    - * @type {string}
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.separators_;
    -
    -
    -/**
    - * The separator we use to reconstruct the string
    - * @type {string}
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.defaultSeparator_;
    -
    -
    -/**
    - * Regular expression used from trimming tokens or null for no trimming.
    - * @type {RegExp}
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.trimmer_;
    -
    -
    -/**
    - * Regular expression to test whether a separator exists
    - * @type {RegExp}
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.separatorCheck_;
    -
    -
    -/**
    - * Should auto-completed tokens be wrapped in whitespace?  Used in selectRow.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.whitespaceWrapEntries_ = true;
    -
    -
    -/**
    - * Should the occurrence of a literal indicate a token boundary?
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.generateNewTokenOnLiteral_ = true;
    -
    -
    -/**
    - * Whether to flip the orientation of up & down for hiliting next
    - * and previous autocomplete entries.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.upsideDown_ = false;
    -
    -
    -/**
    - * If we're in 'multi' mode, does typing a separator force the updating of
    - * suggestions?
    - * For example, if somebody finishes typing "obama, hillary,", should the last
    - * comma trigger updating suggestions in a guaranteed manner? Especially useful
    - * when the suggestions depend on complete keywords. Note that "obama, hill"
    - * (a leading sub-string of "obama, hillary" will lead to different and possibly
    - * irrelevant suggestions.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.separatorUpdates_ = true;
    -
    -
    -/**
    - * If we're in 'multi' mode, does typing a separator force the current term to
    - * autocomplete?
    - * For example, if 'tomato' is a suggested completion and the user has typed
    - * 'to,', do we autocomplete to turn that into 'tomato,'?
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.separatorSelects_ = true;
    -
    -
    -/**
    - * The id of the currently active timeout, so it can be cleared if required.
    - * @type {?number}
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.activeTimeoutId_ = null;
    -
    -
    -/**
    - * The element that is currently active.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.activeElement_ = null;
    -
    -
    -/**
    - * The previous value of the active element.
    - * @type {string}
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.lastValue_ = '';
    -
    -
    -/**
    - * Flag used to indicate that the IME key has been seen and we need to wait for
    - * the up event.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.waitingForIme_ = false;
    -
    -
    -/**
    - * Flag used to indicate that the user just selected a row and we should
    - * therefore ignore the change of the input value.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.rowJustSelected_ = false;
    -
    -
    -/**
    - * Flag indicating whether the result list should be updated continuously
    - * during typing or only after a short pause.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.updateDuringTyping_ = true;
    -
    -
    -/**
    - * Attach an instance of an AutoComplete
    - * @param {goog.ui.ac.AutoComplete} ac Autocomplete object.
    - */
    -goog.ui.ac.InputHandler.prototype.attachAutoComplete = function(ac) {
    -  this.ac_ = ac;
    -};
    -
    -
    -/**
    - * Returns the associated autocomplete instance.
    - * @return {goog.ui.ac.AutoComplete} The associated autocomplete instance.
    - */
    -goog.ui.ac.InputHandler.prototype.getAutoComplete = function() {
    -  return this.ac_;
    -};
    -
    -
    -/**
    - * Returns the current active element.
    - * @return {Element} The currently active element.
    - */
    -goog.ui.ac.InputHandler.prototype.getActiveElement = function() {
    -  return this.activeElement_;
    -};
    -
    -
    -/**
    - * Returns the value of the current active element.
    - * @return {string} The value of the current active element.
    - */
    -goog.ui.ac.InputHandler.prototype.getValue = function() {
    -  return this.activeElement_.value;
    -};
    -
    -
    -/**
    - * Sets the value of the current active element.
    - * @param {string} value The new value.
    - */
    -goog.ui.ac.InputHandler.prototype.setValue = function(value) {
    -  this.activeElement_.value = value;
    -};
    -
    -
    -/**
    - * Returns the current cursor position.
    - * @return {number} The index of the cursor position.
    - */
    -goog.ui.ac.InputHandler.prototype.getCursorPosition = function() {
    -  return goog.dom.selection.getStart(this.activeElement_);
    -};
    -
    -
    -/**
    - * Sets the cursor at the given position.
    - * @param {number} pos The index of the cursor position.
    - */
    -goog.ui.ac.InputHandler.prototype.setCursorPosition = function(pos) {
    -  goog.dom.selection.setStart(this.activeElement_, pos);
    -  goog.dom.selection.setEnd(this.activeElement_, pos);
    -};
    -
    -
    -/**
    - * Attaches the input handler to a target element. The target element
    - * should be a textarea, input box, or other focusable element with the
    - * same interface.
    - * @param {Element|goog.events.EventTarget} target An element to attach the
    - *     input handler too.
    - */
    -goog.ui.ac.InputHandler.prototype.attachInput = function(target) {
    -  if (goog.dom.isElement(target)) {
    -    var el = /** @type {!Element} */ (target);
    -    goog.a11y.aria.setState(el, 'haspopup', true);
    -  }
    -
    -  this.eh_.listen(target, goog.events.EventType.FOCUS, this.handleFocus);
    -  this.eh_.listen(target, goog.events.EventType.BLUR, this.handleBlur);
    -
    -  if (!this.activeElement_) {
    -    this.activateHandler_.listen(
    -        target, goog.events.EventType.KEYDOWN,
    -        this.onKeyDownOnInactiveElement_);
    -
    -    // Don't wait for a focus event if the element already has focus.
    -    if (goog.dom.isElement(target)) {
    -      var ownerDocument = goog.dom.getOwnerDocument(
    -          /** @type {Element} */ (target));
    -      if (goog.dom.getActiveElement(ownerDocument) == target) {
    -        this.processFocus(/** @type {!Element} */ (target));
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Detaches the input handler from the provided element.
    - * @param {Element|goog.events.EventTarget} target An element to detach the
    - *     input handler from.
    - */
    -goog.ui.ac.InputHandler.prototype.detachInput = function(target) {
    -  if (target == this.activeElement_) {
    -    this.handleBlur();
    -  }
    -  this.eh_.unlisten(target, goog.events.EventType.FOCUS, this.handleFocus);
    -  this.eh_.unlisten(target, goog.events.EventType.BLUR, this.handleBlur);
    -
    -  if (!this.activeElement_) {
    -    this.activateHandler_.unlisten(
    -        target, goog.events.EventType.KEYDOWN,
    -        this.onKeyDownOnInactiveElement_);
    -  }
    -};
    -
    -
    -/**
    - * Attaches the input handler to multiple elements.
    - * @param {...Element} var_args Elements to attach the input handler too.
    - */
    -goog.ui.ac.InputHandler.prototype.attachInputs = function(var_args) {
    -  for (var i = 0; i < arguments.length; i++) {
    -    this.attachInput(arguments[i]);
    -  }
    -};
    -
    -
    -/**
    - * Detaches the input handler from multuple elements.
    - * @param {...Element} var_args Variable arguments for elements to unbind from.
    - */
    -goog.ui.ac.InputHandler.prototype.detachInputs = function(var_args) {
    -  for (var i = 0; i < arguments.length; i++) {
    -    this.detachInput(arguments[i]);
    -  }
    -};
    -
    -
    -/**
    - * Selects the given row.  Implements the SelectionHandler interface.
    - * @param {Object} row The row to select.
    - * @param {boolean=} opt_multi Should this be treated as a single or multi-token
    - *     auto-complete?  Overrides previous setting of opt_multi on constructor.
    - * @return {boolean} Whether to suppress the update event.
    - */
    -goog.ui.ac.InputHandler.prototype.selectRow = function(row, opt_multi) {
    -  if (this.activeElement_) {
    -    this.setTokenText(row.toString(), opt_multi);
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Sets the text of the current token without updating the autocomplete
    - * choices.
    - * @param {string} tokenText The text for the current token.
    - * @param {boolean=} opt_multi Should this be treated as a single or multi-token
    - *     auto-complete?  Overrides previous setting of opt_multi on constructor.
    - * @protected
    - */
    -goog.ui.ac.InputHandler.prototype.setTokenText =
    -    function(tokenText, opt_multi) {
    -  if (goog.isDef(opt_multi) ? opt_multi : this.multi_) {
    -    var index = this.getTokenIndex_(this.getValue(), this.getCursorPosition());
    -
    -    // Break up the current input string.
    -    var entries = this.splitInput_(this.getValue());
    -
    -    // Get the new value, ignoring whitespace associated with the entry.
    -    var replaceValue = tokenText;
    -
    -    // Only add punctuation if there isn't already a separator available.
    -    if (!this.separatorCheck_.test(replaceValue)) {
    -      replaceValue = goog.string.trimRight(replaceValue) +
    -                     this.defaultSeparator_;
    -    }
    -
    -    // Ensure there's whitespace wrapping the entries, if whitespaceWrapEntries_
    -    // has been set to true.
    -    if (this.whitespaceWrapEntries_) {
    -      if (index != 0 && !goog.string.isEmptyOrWhitespace(entries[index - 1])) {
    -        replaceValue = ' ' + replaceValue;
    -      }
    -      // Add a space only if it's the last token; otherwise, we assume the
    -      // next token already has the proper spacing.
    -      if (index == entries.length - 1) {
    -        replaceValue = replaceValue + ' ';
    -      }
    -    }
    -
    -    // If the token needs changing, then update the input box and move the
    -    // cursor to the correct position.
    -    if (replaceValue != entries[index]) {
    -
    -      // Replace the value in the array.
    -      entries[index] = replaceValue;
    -
    -      var el = this.activeElement_;
    -      // If there is an uncommitted IME in Firefox or IE 9, setting the value
    -      // fails and results in actually clearing the value that's already in the
    -      // input.
    -      // The FF bug is http://bugzilla.mozilla.org/show_bug.cgi?id=549674
    -      // Blurring before setting the value works around this problem. We'd like
    -      // to do this only if there is an uncommitted IME, but this isn't possible
    -      // to detect. Since text editing is finicky we restrict this
    -      // workaround to Firefox and IE 9 where it's necessary.
    -      if (goog.userAgent.GECKO ||
    -          (goog.userAgent.IE && goog.userAgent.isVersionOrHigher('9'))) {
    -        el.blur();
    -      }
    -      // Join the array and replace the contents of the input.
    -      el.value = entries.join('');
    -
    -      // Calculate which position to put the cursor at.
    -      var pos = 0;
    -      for (var i = 0; i <= index; i++) {
    -        pos += entries[i].length;
    -      }
    -
    -      // Set the cursor.
    -      el.focus();
    -      this.setCursorPosition(pos);
    -    }
    -  } else {
    -    this.setValue(tokenText);
    -  }
    -
    -  // Avoid triggering an autocomplete just because the value changed.
    -  this.rowJustSelected_ = true;
    -};
    -
    -
    -/** @override */
    -goog.ui.ac.InputHandler.prototype.disposeInternal = function() {
    -  goog.ui.ac.InputHandler.superClass_.disposeInternal.call(this);
    -  if (this.activeTimeoutId_ != null) {
    -    // Need to check against null explicitly because 0 is a valid value.
    -    window.clearTimeout(this.activeTimeoutId_);
    -  }
    -  this.eh_.dispose();
    -  delete this.eh_;
    -  this.activateHandler_.dispose();
    -  this.keyHandler_.dispose();
    -  goog.dispose(this.timer_);
    -};
    -
    -
    -/**
    - * Sets the entry separator characters.
    - *
    - * @param {string} separators The separator characters to set.
    - * @param {string=} opt_defaultSeparators The defaultSeparator character to set.
    - */
    -goog.ui.ac.InputHandler.prototype.setSeparators =
    -    function(separators, opt_defaultSeparators) {
    -  this.separators_ = separators;
    -  this.defaultSeparator_ =
    -      goog.isDefAndNotNull(opt_defaultSeparators) ?
    -      opt_defaultSeparators : this.separators_.substring(0, 1);
    -
    -  var wspaceExp = this.multi_ ? '[\\s' + this.separators_ + ']+' : '[\\s]+';
    -
    -  this.trimmer_ = new RegExp('^' + wspaceExp + '|' + wspaceExp + '$', 'g');
    -  this.separatorCheck_ = new RegExp('\\s*[' + this.separators_ + ']$');
    -};
    -
    -
    -/**
    - * Sets whether to flip the orientation of up & down for hiliting next
    - * and previous autocomplete entries.
    - * @param {boolean} upsideDown Whether the orientation is upside down.
    - */
    -goog.ui.ac.InputHandler.prototype.setUpsideDown = function(upsideDown) {
    -  this.upsideDown_ = upsideDown;
    -};
    -
    -
    -/**
    - * Sets whether auto-completed tokens should be wrapped with whitespace.
    - * @param {boolean} newValue boolean value indicating whether or not
    - *     auto-completed tokens should be wrapped with whitespace.
    - */
    -goog.ui.ac.InputHandler.prototype.setWhitespaceWrapEntries =
    -    function(newValue) {
    -  this.whitespaceWrapEntries_ = newValue;
    -};
    -
    -
    -/**
    - * Sets whether new tokens should be generated from literals.  That is, should
    - * hello'world be two tokens, assuming ' is a literal?
    - * @param {boolean} newValue boolean value indicating whether or not
    - * new tokens should be generated from literals.
    - */
    -goog.ui.ac.InputHandler.prototype.setGenerateNewTokenOnLiteral =
    -    function(newValue) {
    -  this.generateNewTokenOnLiteral_ = newValue;
    -};
    -
    -
    -/**
    - * Sets the regular expression used to trim the tokens before passing them to
    - * the matcher:  every substring that matches the given regular expression will
    - * be removed.  This can also be set to null to disable trimming.
    - * @param {RegExp} trimmer Regexp to use for trimming or null to disable it.
    - */
    -goog.ui.ac.InputHandler.prototype.setTrimmingRegExp = function(trimmer) {
    -  this.trimmer_ = trimmer;
    -};
    -
    -
    -/**
    - * Sets whether we will prevent the default input behavior (moving focus to the
    - * next focusable  element) on TAB.
    - * @param {boolean} newValue Whether to preventDefault on TAB.
    - */
    -goog.ui.ac.InputHandler.prototype.setPreventDefaultOnTab = function(newValue) {
    -  this.preventDefaultOnTab_ = newValue;
    -};
    -
    -
    -/**
    - * Sets whether we will prevent highlighted item selection on TAB.
    - * @param {boolean} newValue Whether to prevent selection on TAB.
    - */
    -goog.ui.ac.InputHandler.prototype.setPreventSelectionOnTab =
    -    function(newValue) {
    -  this.preventSelectionOnTab_ = newValue;
    -};
    -
    -
    -/**
    - * Sets whether separators perform autocomplete.
    - * @param {boolean} newValue Whether to autocomplete on separators.
    - */
    -goog.ui.ac.InputHandler.prototype.setSeparatorCompletes = function(newValue) {
    -  this.separatorUpdates_ = newValue;
    -  this.separatorSelects_ = newValue;
    -};
    -
    -
    -/**
    - * Sets whether separators perform autocomplete.
    - * @param {boolean} newValue Whether to autocomplete on separators.
    - */
    -goog.ui.ac.InputHandler.prototype.setSeparatorSelects = function(newValue) {
    -  this.separatorSelects_ = newValue;
    -};
    -
    -
    -/**
    - * Gets the time to wait before updating the results. If the update during
    - * typing flag is switched on, this delay counts from the last update,
    - * otherwise from the last keypress.
    - * @return {number} Throttle time in milliseconds.
    - */
    -goog.ui.ac.InputHandler.prototype.getThrottleTime = function() {
    -  return this.timer_ ? this.timer_.getInterval() : -1;
    -};
    -
    -
    -/**
    - * Sets whether a row has just been selected.
    - * @param {boolean} justSelected Whether or not the row has just been selected.
    - */
    -goog.ui.ac.InputHandler.prototype.setRowJustSelected = function(justSelected) {
    -  this.rowJustSelected_ = justSelected;
    -};
    -
    -
    -/**
    - * Sets the time to wait before updating the results.
    - * @param {number} time New throttle time in milliseconds.
    - */
    -goog.ui.ac.InputHandler.prototype.setThrottleTime = function(time) {
    -  if (time < 0) {
    -    this.timer_.dispose();
    -    this.timer_ = null;
    -    return;
    -  }
    -  if (this.timer_) {
    -    this.timer_.setInterval(time);
    -  } else {
    -    this.timer_ = new goog.Timer(time);
    -  }
    -};
    -
    -
    -/**
    - * Gets whether the result list is updated during typing.
    - * @return {boolean} Value of the flag.
    - */
    -goog.ui.ac.InputHandler.prototype.getUpdateDuringTyping = function() {
    -  return this.updateDuringTyping_;
    -};
    -
    -
    -/**
    - * Sets whether the result list should be updated during typing.
    - * @param {boolean} value New value of the flag.
    - */
    -goog.ui.ac.InputHandler.prototype.setUpdateDuringTyping = function(value) {
    -  this.updateDuringTyping_ = value;
    -};
    -
    -
    -/**
    - * Handles a key event.
    - * @param {goog.events.BrowserEvent} e Browser event object.
    - * @return {boolean} True if the key event was handled.
    - * @protected
    - */
    -goog.ui.ac.InputHandler.prototype.handleKeyEvent = function(e) {
    -  switch (e.keyCode) {
    -
    -    // If the menu is open and 'down' caused a change then prevent the default
    -    // action and prevent scrolling.  If the box isn't a multi autocomplete
    -    // and the menu isn't open, we force it open now.
    -    case goog.events.KeyCodes.DOWN:
    -      if (this.ac_.isOpen()) {
    -        this.moveDown_();
    -        e.preventDefault();
    -        return true;
    -
    -      } else if (!this.multi_) {
    -        this.update(true);
    -        e.preventDefault();
    -        return true;
    -      }
    -      break;
    -
    -    // If the menu is open and 'up' caused a change then prevent the default
    -    // action and prevent scrolling.
    -    case goog.events.KeyCodes.UP:
    -      if (this.ac_.isOpen()) {
    -        this.moveUp_();
    -        e.preventDefault();
    -        return true;
    -      }
    -      break;
    -
    -    // If tab key is pressed, select the current highlighted item.  The default
    -    // action is also prevented if the input is a multi input, to prevent the
    -    // user tabbing out of the field.
    -    case goog.events.KeyCodes.TAB:
    -      if (this.ac_.isOpen() && !e.shiftKey && !this.preventSelectionOnTab_) {
    -        // Ensure the menu is up to date before completing.
    -        this.update();
    -        if (this.ac_.selectHilited() && this.preventDefaultOnTab_) {
    -          e.preventDefault();
    -          return true;
    -        }
    -      } else {
    -        this.ac_.dismiss();
    -      }
    -      break;
    -
    -    // On enter, just select the highlighted row.
    -    case goog.events.KeyCodes.ENTER:
    -      if (this.ac_.isOpen()) {
    -        // Ensure the menu is up to date before completing.
    -        this.update();
    -        if (this.ac_.selectHilited()) {
    -          e.preventDefault();
    -          e.stopPropagation();
    -          return true;
    -        }
    -      } else {
    -        this.ac_.dismiss();
    -      }
    -      break;
    -
    -    // On escape tell the autocomplete to dismiss.
    -    case goog.events.KeyCodes.ESC:
    -      if (this.ac_.isOpen()) {
    -        this.ac_.dismiss();
    -        e.preventDefault();
    -        e.stopPropagation();
    -        return true;
    -      }
    -      break;
    -
    -    // The IME keycode indicates an IME sequence has started, we ignore all
    -    // changes until we get an enter key-up.
    -    case goog.events.KeyCodes.WIN_IME:
    -      if (!this.waitingForIme_) {
    -        this.startWaitingForIme_();
    -        return true;
    -      }
    -      break;
    -
    -    default:
    -      if (this.timer_ && !this.updateDuringTyping_) {
    -        // Waits throttle time before sending the request again.
    -        this.timer_.stop();
    -        this.timer_.start();
    -      }
    -  }
    -
    -  return this.handleSeparator_(e);
    -};
    -
    -
    -/**
    - * Handles a key event for a separator key.
    - * @param {goog.events.BrowserEvent} e Browser event object.
    - * @return {boolean} True if the key event was handled.
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.handleSeparator_ = function(e) {
    -  var isSeparatorKey = this.multi_ && e.charCode &&
    -      this.separators_.indexOf(String.fromCharCode(e.charCode)) != -1;
    -  if (this.separatorUpdates_ && isSeparatorKey) {
    -    this.update();
    -  }
    -  if (this.separatorSelects_ && isSeparatorKey) {
    -    if (this.ac_.selectHilited()) {
    -      e.preventDefault();
    -      return true;
    -    }
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether this inputhandler need to listen on key-up.
    - * @protected
    - */
    -goog.ui.ac.InputHandler.prototype.needKeyUpListener = function() {
    -  return false;
    -};
    -
    -
    -/**
    - * Handles the key up event. Registered only if needKeyUpListener returns true.
    - * @param {goog.events.Event} e The keyup event.
    - * @return {boolean} Whether an action was taken or not.
    - * @protected
    - */
    -goog.ui.ac.InputHandler.prototype.handleKeyUp = function(e) {
    -  return false;
    -};
    -
    -
    -/**
    - * Adds the necessary input event handlers.
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.addEventHandlers_ = function() {
    -  this.keyHandler_.attach(this.activeElement_);
    -  this.eh_.listen(
    -      this.keyHandler_, goog.events.KeyHandler.EventType.KEY, this.onKey_);
    -  if (this.needKeyUpListener()) {
    -    this.eh_.listen(this.activeElement_,
    -        goog.events.EventType.KEYUP, this.handleKeyUp);
    -  }
    -  this.eh_.listen(this.activeElement_,
    -      goog.events.EventType.MOUSEDOWN, this.onMouseDown_);
    -
    -  // IE also needs a keypress to check if the user typed a separator
    -  if (goog.userAgent.IE) {
    -    this.eh_.listen(this.activeElement_,
    -        goog.events.EventType.KEYPRESS, this.onIeKeyPress_);
    -  }
    -};
    -
    -
    -/**
    - * Removes the necessary input event handlers.
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.removeEventHandlers_ = function() {
    -  this.eh_.unlisten(
    -      this.keyHandler_, goog.events.KeyHandler.EventType.KEY, this.onKey_);
    -  this.keyHandler_.detach();
    -  this.eh_.unlisten(this.activeElement_,
    -      goog.events.EventType.KEYUP, this.handleKeyUp);
    -  this.eh_.unlisten(this.activeElement_,
    -      goog.events.EventType.MOUSEDOWN, this.onMouseDown_);
    -
    -  if (goog.userAgent.IE) {
    -    this.eh_.unlisten(this.activeElement_,
    -        goog.events.EventType.KEYPRESS, this.onIeKeyPress_);
    -  }
    -
    -  if (this.waitingForIme_) {
    -    this.stopWaitingForIme_();
    -  }
    -};
    -
    -
    -/**
    - * Handles an element getting focus.
    - * @param {goog.events.Event} e Browser event object.
    - * @protected
    - */
    -goog.ui.ac.InputHandler.prototype.handleFocus = function(e) {
    -  this.processFocus(/** @type {Element} */ (e.target || null));
    -};
    -
    -
    -/**
    - * Registers handlers for the active element when it receives focus.
    - * @param {Element} target The element to focus.
    - * @protected
    - */
    -goog.ui.ac.InputHandler.prototype.processFocus = function(target) {
    -  this.activateHandler_.removeAll();
    -
    -  if (this.ac_) {
    -    this.ac_.cancelDelayedDismiss();
    -  }
    -
    -  // Double-check whether the active element has actually changed.
    -  // This is a fix for Safari 3, which fires spurious focus events.
    -  if (target != this.activeElement_) {
    -    this.activeElement_ = target;
    -    if (this.timer_) {
    -      this.timer_.start();
    -      this.eh_.listen(this.timer_, goog.Timer.TICK, this.onTick_);
    -    }
    -    this.lastValue_ = this.getValue();
    -    this.addEventHandlers_();
    -  }
    -};
    -
    -
    -/**
    - * Handles an element blurring.
    - * @param {goog.events.Event=} opt_e Browser event object.
    - * @protected
    - */
    -goog.ui.ac.InputHandler.prototype.handleBlur = function(opt_e) {
    -  // Phones running iOS prior to version 4.2.
    -  if (goog.ui.ac.InputHandler.REQUIRES_ASYNC_BLUR_) {
    -    // @bug 4484488 This is required so that the menu works correctly on
    -    // iOS prior to version 4.2. Otherwise, the blur action closes the menu
    -    // before the menu button click can be processed.
    -    // In order to fix the bug, we set a timeout to process the blur event, so
    -    // that any pending selection event can be processed first.
    -    this.activeTimeoutId_ =
    -        window.setTimeout(goog.bind(this.processBlur, this), 0);
    -    return;
    -  } else {
    -    this.processBlur();
    -  }
    -};
    -
    -
    -/**
    - * Helper function that does the logic to handle an element blurring.
    - * @protected
    - */
    -goog.ui.ac.InputHandler.prototype.processBlur = function() {
    -  // it's possible that a blur event could fire when there's no active element,
    -  // in the case where attachInput was called on an input that already had
    -  // the focus
    -  if (this.activeElement_) {
    -    this.removeEventHandlers_();
    -    this.activeElement_ = null;
    -
    -    if (this.timer_) {
    -      this.timer_.stop();
    -      this.eh_.unlisten(this.timer_, goog.Timer.TICK, this.onTick_);
    -    }
    -
    -    if (this.ac_) {
    -      // Pause dismissal slightly to take into account any other events that
    -      // might fire on the renderer (e.g. a click will lose the focus).
    -      this.ac_.dismissOnDelay();
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Handles the timer's tick event.  Calculates the current token, and reports
    - * any update to the autocomplete.
    - * @param {goog.events.Event} e Browser event object.
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.onTick_ = function(e) {
    -  this.update();
    -};
    -
    -
    -/**
    - * Handles typing in an inactive input element. Activate it.
    - * @param {goog.events.BrowserEvent} e Browser event object.
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.onKeyDownOnInactiveElement_ = function(e) {
    -  this.handleFocus(e);
    -};
    -
    -
    -/**
    - * Handles typing in the active input element.  Checks if the key is a special
    - * key and does the relevent action as appropriate.
    - * @param {goog.events.BrowserEvent} e Browser event object.
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.onKey_ = function(e) {
    -  this.lastKeyCode_ = e.keyCode;
    -  if (this.ac_) {
    -    this.handleKeyEvent(e);
    -  }
    -};
    -
    -
    -/**
    - * Handles a KEYPRESS event generated by typing in the active input element.
    - * Checks if IME input is ended.
    - * @param {goog.events.BrowserEvent} e Browser event object.
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.onKeyPress_ = function(e) {
    -  if (this.waitingForIme_ &&
    -      this.lastKeyCode_ != goog.events.KeyCodes.WIN_IME) {
    -    this.stopWaitingForIme_();
    -  }
    -};
    -
    -
    -/**
    - * Handles the key-up event.  This is only ever used by Mac FF or when we are in
    - * an IME entry scenario.
    - * @param {goog.events.BrowserEvent} e Browser event object.
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.onKeyUp_ = function(e) {
    -  if (this.waitingForIme_ &&
    -      (e.keyCode == goog.events.KeyCodes.ENTER ||
    -       (e.keyCode == goog.events.KeyCodes.M && e.ctrlKey))) {
    -    this.stopWaitingForIme_();
    -  }
    -};
    -
    -
    -/**
    - * Handles mouse-down event.
    - * @param {goog.events.BrowserEvent} e Browser event object.
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.onMouseDown_ = function(e) {
    -  if (this.ac_) {
    -    this.handleMouseDown(e);
    -  }
    -};
    -
    -
    -/**
    - * For subclasses to override to handle the mouse-down event.
    - * @param {goog.events.BrowserEvent} e Browser event object.
    - * @protected
    - */
    -goog.ui.ac.InputHandler.prototype.handleMouseDown = function(e) {
    -};
    -
    -
    -/**
    - * Starts waiting for IME.
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.startWaitingForIme_ = function() {
    -  if (this.waitingForIme_) {
    -    return;
    -  }
    -  this.eh_.listen(
    -      this.activeElement_, goog.events.EventType.KEYUP, this.onKeyUp_);
    -  this.eh_.listen(
    -      this.activeElement_, goog.events.EventType.KEYPRESS, this.onKeyPress_);
    -  this.waitingForIme_ = true;
    -};
    -
    -
    -/**
    - * Stops waiting for IME.
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.stopWaitingForIme_ = function() {
    -  if (!this.waitingForIme_) {
    -    return;
    -  }
    -  this.waitingForIme_ = false;
    -  this.eh_.unlisten(
    -      this.activeElement_, goog.events.EventType.KEYPRESS, this.onKeyPress_);
    -  this.eh_.unlisten(
    -      this.activeElement_, goog.events.EventType.KEYUP, this.onKeyUp_);
    -};
    -
    -
    -/**
    - * Handles the key-press event for IE, checking to see if the user typed a
    - * separator character.
    - * @param {goog.events.BrowserEvent} e Browser event object.
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.onIeKeyPress_ = function(e) {
    -  this.handleSeparator_(e);
    -};
    -
    -
    -/**
    - * Checks if an update has occurred and notified the autocomplete of the new
    - * token.
    - * @param {boolean=} opt_force If true the menu will be forced to update.
    - */
    -goog.ui.ac.InputHandler.prototype.update = function(opt_force) {
    -  if (this.activeElement_ &&
    -      (opt_force || this.getValue() != this.lastValue_)) {
    -    if (opt_force || !this.rowJustSelected_) {
    -      var token = this.parseToken();
    -
    -      if (this.ac_) {
    -        this.ac_.setTarget(this.activeElement_);
    -        this.ac_.setToken(token, this.getValue());
    -      }
    -    }
    -    this.lastValue_ = this.getValue();
    -  }
    -  this.rowJustSelected_ = false;
    -};
    -
    -
    -/**
    - * Parses a text area or input box for the currently highlighted token.
    - * @return {string} Token to complete.
    - * @protected
    - */
    -goog.ui.ac.InputHandler.prototype.parseToken = function() {
    -  return this.parseToken_();
    -};
    -
    -
    -/**
    - * Moves hilite up.  May hilite next or previous depending on orientation.
    - * @return {boolean} True if successful.
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.moveUp_ = function() {
    -  return this.upsideDown_ ? this.ac_.hiliteNext() : this.ac_.hilitePrev();
    -};
    -
    -
    -/**
    - * Moves hilite down.  May hilite next or previous depending on orientation.
    - * @return {boolean} True if successful.
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.moveDown_ = function() {
    -  return this.upsideDown_ ? this.ac_.hilitePrev() : this.ac_.hiliteNext();
    -};
    -
    -
    -/**
    - * Parses a text area or input box for the currently highlighted token.
    - * @return {string} Token to complete.
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.parseToken_ = function() {
    -  var caret = this.getCursorPosition();
    -  var text = this.getValue();
    -  return this.trim_(this.splitInput_(text)[this.getTokenIndex_(text, caret)]);
    -};
    -
    -
    -/**
    - * Trims a token of characters that we want to ignore
    - * @param {string} text string to trim.
    - * @return {string} Trimmed string.
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.trim_ = function(text) {
    -  return this.trimmer_ ? String(text).replace(this.trimmer_, '') : text;
    -};
    -
    -
    -/**
    - * Gets the index of the currently highlighted token
    - * @param {string} text string to parse.
    - * @param {number} caret Position of cursor in string.
    - * @return {number} Index of token.
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.getTokenIndex_ = function(text, caret) {
    -  // Split up the input string into multiple entries
    -  var entries = this.splitInput_(text);
    -
    -  // Short-circuit to select the last entry
    -  if (caret == text.length) return entries.length - 1;
    -
    -  // Calculate which of the entries the cursor is currently in
    -  var current = 0;
    -  for (var i = 0, pos = 0; i < entries.length && pos <= caret; i++) {
    -    pos += entries[i].length;
    -    current = i;
    -  }
    -
    -  // Get the token for the current item
    -  return current;
    -};
    -
    -
    -/**
    - * Splits an input string of text at the occurance of a character in
    - * {@link goog.ui.ac.InputHandler.prototype.separators_} and creates
    - * an array of tokens.  Each token may contain additional whitespace and
    - * formatting marks.  If necessary use
    - * {@link goog.ui.ac.InputHandler.prototype.trim_} to clean up the
    - * entries.
    - *
    - * @param {string} text Input text.
    - * @return {!Array<string>} Parsed array.
    - * @private
    - */
    -goog.ui.ac.InputHandler.prototype.splitInput_ = function(text) {
    -  if (!this.multi_) {
    -    return [text];
    -  }
    -
    -  var arr = String(text).split('');
    -  var parts = [];
    -  var cache = [];
    -
    -  for (var i = 0, inLiteral = false; i < arr.length; i++) {
    -    if (this.literals_ && this.literals_.indexOf(arr[i]) != -1) {
    -      if (this.generateNewTokenOnLiteral_ && !inLiteral) {
    -        parts.push(cache.join(''));
    -        cache.length = 0;
    -      }
    -      cache.push(arr[i]);
    -      inLiteral = !inLiteral;
    -
    -    } else if (!inLiteral && this.separators_.indexOf(arr[i]) != -1) {
    -      cache.push(arr[i]);
    -      parts.push(cache.join(''));
    -      cache.length = 0;
    -
    -    } else {
    -      cache.push(arr[i]);
    -    }
    -  }
    -  parts.push(cache.join(''));
    -
    -  return parts;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/ac/inputhandler_test.html b/src/database/third_party/closure-library/closure/goog/ui/ac/inputhandler_test.html
    deleted file mode 100644
    index 583348dbea1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/ac/inputhandler_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.ac.InputHandler
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.ac.InputHandlerTest');
    -  </script>
    - </head>
    - <body>
    -  <input type="text" id="textInput" style="display:none" />
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/ac/inputhandler_test.js b/src/database/third_party/closure-library/closure/goog/ui/ac/inputhandler_test.js
    deleted file mode 100644
    index a2f1192d614..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/ac/inputhandler_test.js
    +++ /dev/null
    @@ -1,716 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.ac.InputHandlerTest');
    -goog.setTestOnly('goog.ui.ac.InputHandlerTest');
    -
    -goog.require('goog.dom.selection');
    -goog.require('goog.events.BrowserEvent');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.functions');
    -goog.require('goog.object');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.ac.InputHandler');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Mock out the input element.
    - * @constructor
    - */
    -function MockElement() {
    -  goog.events.EventTarget.call(this);
    -  this.setAttributeNS = function() {};
    -  this.setAttribute = function(key, value) { this[key] = value; };
    -  this.focus = function() {};
    -  this.blur = function() {};
    -  this.ownerDocument = document;
    -  this.selectionStart = 0;
    -}
    -goog.inherits(MockElement, goog.events.EventTarget);
    -
    -
    -
    -/**
    - * @constructor
    - */
    -function MockAutoCompleter() {
    -  this.setToken = null;
    -  this.setTokenWasCalled = false;
    -  this.selectHilitedWasCalled = false;
    -  this.dismissWasCalled = false;
    -  this.getTarget = function() { return mockElement };
    -  this.setTarget = function() { };
    -  this.setToken = function(token) {
    -    this.setTokenWasCalled = true;
    -    this.setToken = token;
    -  };
    -  this.selectHilited = function() {
    -    this.selectHilitedWasCalled = true;
    -    return true; // Success.
    -  };
    -  this.cancelDelayedDismiss = function() { };
    -  this.dismissOnDelay = function() {};
    -  this.dismiss = function() { this.dismissWasCalled = true; };
    -  this.isOpen = goog.functions.TRUE;
    -}
    -
    -
    -
    -/**
    - * MockInputHandler simulates key events for testing the IME behavior of
    - * InputHandler.
    - * @constructor
    - */
    -function MockInputHandler() {
    -  goog.ui.ac.InputHandler.call(this);
    -
    -  this.ac_ = new MockAutoCompleter();
    -  this.cursorPosition_ = 0;
    -
    -  this.attachInput(mockElement);
    -}
    -goog.inherits(MockInputHandler, goog.ui.ac.InputHandler);
    -
    -
    -/** Checks for updates to the text area, should not happen during IME. */
    -MockInputHandler.prototype.update = function() {
    -  this.updates++;
    -};
    -
    -
    -/** Simulates key events. */
    -MockInputHandler.prototype.fireKeyEvents = function(
    -    keyCode, down, press, up, opt_properties) {
    -  if (down) this.fireEvent('keydown', keyCode, opt_properties);
    -  if (press) this.fireEvent('keypress', keyCode, opt_properties);
    -  if (up) this.fireEvent('keyup', keyCode, opt_properties);
    -};
    -
    -
    -/** Simulates an event. */
    -MockInputHandler.prototype.fireEvent = function(
    -    type, keyCode, opt_properties) {
    -  var e = {};
    -  e.type = type;
    -  e.keyCode = keyCode;
    -  e.preventDefault = function() {};
    -  if (!goog.userAgent.IE) {
    -    e.which = type == 'keydown' ? keyCode : 0;
    -  }
    -  if (opt_properties) {
    -    goog.object.extend(e, opt_properties);
    -  }
    -  e = new goog.events.BrowserEvent(e);
    -  mockElement.dispatchEvent(e);
    -};
    -
    -MockInputHandler.prototype.setCursorPosition = function(cursorPosition) {
    -  this.cursorPosition_ = cursorPosition;
    -};
    -
    -MockInputHandler.prototype.getCursorPosition = function() {
    -  return this.cursorPosition_;
    -};
    -
    -// Variables used by all test
    -var mh = null;
    -var oldMac, oldWin, oldLinux, oldIe, oldFf, oldWebkit, oldVersion;
    -var oldUsesKeyDown;
    -var mockElement;
    -var mockClock;
    -
    -function setUp() {
    -  oldMac = goog.userAgent.MAC;
    -  oldWin = goog.userAgent.WINDOWS;
    -  oldLinux = goog.userAgent.LINUX;
    -  oldIe = goog.userAgent.IE;
    -  oldFf = goog.userAgent.GECKO;
    -  oldWebkit = goog.userAgent.WEBKIT;
    -  oldVersion = goog.userAgent.VERSION;
    -  oldUsesKeyDown = goog.events.KeyHandler.USES_KEYDOWN_;
    -  mockClock = new goog.testing.MockClock(true);
    -  mockElement = new MockElement;
    -  mh = new MockInputHandler;
    -}
    -
    -function tearDown() {
    -  goog.userAgent.MAC = oldMac;
    -  goog.userAgent.WINDOWS = oldWin;
    -  goog.userAgent.LINUX = oldLinux;
    -  goog.userAgent.IE = oldIe;
    -  goog.userAgent.GECKO = oldFf;
    -  goog.userAgent.WEBKIT = oldWebkit;
    -  goog.userAgent.VERSION = oldVersion;
    -  goog.events.KeyHandler.USES_KEYDOWN_ = oldUsesKeyDown;
    -  mockClock.dispose();
    -  mockElement.dispose();
    -}
    -
    -
    -/** Used to simulate behavior of Windows/Firefox3 */
    -function simulateWinFirefox3() {
    -  goog.userAgent.MAC = false;
    -  goog.userAgent.WINDOWS = true;
    -  goog.userAgent.LINUX = false;
    -  goog.userAgent.IE = false;
    -  goog.userAgent.GECKO = true;
    -  goog.userAgent.WEBKIT = false;
    -  goog.events.KeyHandler.USES_KEYDOWN_ = false;
    -}
    -
    -
    -/** Used to simulate behavior of Windows/InternetExplorer7 */
    -function simulateWinIe7() {
    -  goog.userAgent.MAC = false;
    -  goog.userAgent.WINDOWS = true;
    -  goog.userAgent.LINUX = false;
    -  goog.userAgent.IE = true;
    -  goog.userAgent.DOCUMENT_MODE = 7;
    -  goog.userAgent.GECKO = false;
    -  goog.userAgent.WEBKIT = false;
    -  goog.events.KeyHandler.USES_KEYDOWN_ = true;
    -}
    -
    -
    -/** Used to simulate behavior of Windows/Chrome */
    -function simulateWinChrome() {
    -  goog.userAgent.MAC = false;
    -  goog.userAgent.WINDOWS = true;
    -  goog.userAgent.LINUX = false;
    -  goog.userAgent.IE = false;
    -  goog.userAgent.GECKO = false;
    -  goog.userAgent.WEBKIT = true;
    -  goog.userAgent.VERSION = '525';
    -  goog.events.KeyHandler.USES_KEYDOWN_ = true;
    -}
    -
    -
    -/** Used to simulate behavior of Mac/Firefox3 */
    -function simulateMacFirefox3() {
    -  goog.userAgent.MAC = true;
    -  goog.userAgent.WINDOWS = false;
    -  goog.userAgent.LINUX = false;
    -  goog.userAgent.IE = false;
    -  goog.userAgent.GECKO = true;
    -  goog.userAgent.WEBKIT = false;
    -  goog.events.KeyHandler.USES_KEYDOWN_ = true;
    -}
    -
    -
    -/** Used to simulate behavior of Mac/Safari3 */
    -function simulateMacSafari3() {
    -  goog.userAgent.MAC = true;
    -  goog.userAgent.WINDOWS = false;
    -  goog.userAgent.LINUX = false;
    -  goog.userAgent.IE = false;
    -  goog.userAgent.GECKO = false;
    -  goog.userAgent.WEBKIT = true;
    -  goog.userAgent.VERSION = '525';
    -  goog.events.KeyHandler.USES_KEYDOWN_ = true;
    -}
    -
    -
    -/** Used to simulate behavior of Linux/Firefox3 */
    -function simulateLinuxFirefox3() {
    -  goog.userAgent.MAC = false;
    -  goog.userAgent.WINDOWS = false;
    -  goog.userAgent.LINUX = true;
    -  goog.userAgent.IE = false;
    -  goog.userAgent.GECKO = true;
    -  goog.userAgent.WEBKIT = false;
    -  goog.events.KeyHandler.USES_KEYDOWN_ = true;
    -}
    -
    -
    -/** Test the normal, non-IME case */
    -function testRegularKey() {
    -  // Each key fires down, press, and up in that order, and each should
    -  // trigger an autocomplete update
    -  assertFalse('IME should not be triggered', mh.waitingForIme_);
    -
    -  mh.fireKeyEvents(goog.events.KeyCodes.K, true, true, true);
    -  assertFalse('IME should not be triggered by K', mh.waitingForIme_);
    -
    -  mh.fireKeyEvents(goog.events.KeyCodes.A, true, true, true);
    -  assertFalse('IME should not be triggered by A', mh.waitingForIme_);
    -}
    -
    -
    -/**
    - * This test simulates the key inputs generated by pressing
    - * '<ime_on>a<enter>i<ime_off>u' using the Japanese IME
    - * on Windows/Firefox3.
    - */
    -function testImeWinFirefox3() {
    -  simulateWinFirefox3();
    -  mh.fireEvent('focus', '');
    -  assertFalse('IME should not be triggered', mh.waitingForIme_);
    -
    -  // ime_on
    -
    -  // a
    -  mh.fireKeyEvents(goog.events.KeyCodes.WIN_IME, true, true, false);
    -  // Event is not generated for key code a.
    -  assertTrue('IME should be triggered', mh.waitingForIme_);
    -
    -  // enter
    -  mh.fireKeyEvents(goog.events.KeyCodes.ENTER, false, false, true);
    -  assertFalse('IME should not be triggered', mh.waitingForIme_);
    -
    -  // i
    -  mh.fireKeyEvents(goog.events.KeyCodes.WIN_IME, true, true, false);
    -  // Event is not generated for key code i.
    -  assertTrue('IME should be triggered', mh.waitingForIme_);
    -
    -  // ime_off
    -
    -  // u
    -  mh.fireKeyEvents(goog.events.KeyCodes.U, true, true, true);
    -  assertFalse('IME should not be triggered', mh.waitingForIme_);
    -
    -  mh.fireEvent('blur', '');
    -}
    -
    -
    -/**
    - * This test simulates the key inputs generated by pressing
    - * '<ime_on>a<enter>i<ime_off>u' using the Japanese IME
    - * on Windows/InternetExplorer7.
    - */
    -function testImeWinIe7() {
    -  simulateWinIe7();
    -  mh.fireEvent('focus', '');
    -  assertFalse('IME should not be triggered', mh.waitingForIme_);
    -
    -  // ime_on
    -
    -  // a
    -  mh.fireKeyEvents(goog.events.KeyCodes.WIN_IME, true, false, false);
    -  mh.fireKeyEvents(goog.events.KeyCodes.A, false, false, true);
    -  assertTrue('IME should be triggered', mh.waitingForIme_);
    -
    -  // enter
    -  mh.fireKeyEvents(goog.events.KeyCodes.WIN_IME, true, false, false);
    -  mh.fireKeyEvents(goog.events.KeyCodes.ENTER, false, false, true);
    -  assertFalse('IME should not be triggered', mh.waitingForIme_);
    -
    -  // i
    -  mh.fireKeyEvents(goog.events.KeyCodes.WIN_IME, true, false, false);
    -  mh.fireKeyEvents(goog.events.KeyCodes.I, false, false, true);
    -  assertTrue('IME should be triggered', mh.waitingForIme_);
    -
    -  // ime_off
    -
    -  // u
    -  mh.fireKeyEvents(goog.events.KeyCodes.U, true, true, true);
    -  assertFalse('IME should not be triggered', mh.waitingForIme_);
    -
    -  mh.fireEvent('blur', '');
    -}
    -
    -
    -/**
    - * This test simulates the key inputs generated by pressing
    - * '<ime_on>a<enter>i<ime_off>u' using the Japanese IME
    - * on Windows/Chrome.
    - */
    -function testImeWinChrome() {
    -  simulateWinChrome();
    -  mh.fireEvent('focus', '');
    -  assertFalse('IME should not be triggered', mh.waitingForIme_);
    -
    -  // ime_on
    -
    -  // a
    -  mh.fireKeyEvents(goog.events.KeyCodes.WIN_IME, true, false, false);
    -  mh.fireKeyEvents(goog.events.KeyCodes.A, false, false, true);
    -  assertTrue('IME should be triggered', mh.waitingForIme_);
    -
    -  // enter
    -  mh.fireKeyEvents(goog.events.KeyCodes.WIN_IME, true, false, false);
    -  mh.fireKeyEvents(goog.events.KeyCodes.ENTER, false, false, true);
    -  assertFalse('IME should not be triggered', mh.waitingForIme_);
    -
    -  // i
    -  mh.fireKeyEvents(goog.events.KeyCodes.WIN_IME, true, false, false);
    -  mh.fireKeyEvents(goog.events.KeyCodes.I, false, false, true);
    -  assertTrue('IME should be triggered', mh.waitingForIme_);
    -
    -  // ime_off
    -
    -  // u
    -  mh.fireKeyEvents(goog.events.KeyCodes.U, true, true, true);
    -  assertFalse('IME should not be triggered', mh.waitingForIme_);
    -
    -  mh.fireEvent('blur', '');
    -}
    -
    -
    -/**
    - * This test simulates the key inputs generated by pressing
    - * '<ime_on>a<enter>i<ime_off>u' using the Japanese IME
    - * on Mac/Firefox3.
    - */
    -function testImeMacFirefox3() {
    -  // TODO(user): Currently our code cannot distinguish preedit characters
    -  // from normal ones for Mac/Firefox3.
    -  // Enable this test after we fix it.
    -
    -  simulateMacFirefox3();
    -  mh.fireEvent('focus', '');
    -  assertFalse('IME should not be triggered', mh.waitingForIme_);
    -
    -  // ime_on
    -
    -  // a
    -  mh.fireKeyEvents(goog.events.KeyCodes.WIN_IME, true, true, false);
    -  assertTrue('IME should be triggered', mh.waitingForIme_);
    -  mh.fireKeyEvents(goog.events.KeyCodes.A, true, false, true);
    -  assertTrue('IME should be triggered', mh.waitingForIme_);
    -
    -  // enter
    -  mh.fireKeyEvents(goog.events.KeyCodes.ENTER, true, true, true);
    -  assertFalse('IME should not be triggered', mh.waitingForIme_);
    -
    -  // i
    -  mh.fireKeyEvents(goog.events.KeyCodes.WIN_IME, true, true, false);
    -  mh.fireKeyEvents(goog.events.KeyCodes.I, true, false, true);
    -  assertTrue('IME should be triggered', mh.waitingForIme_);
    -
    -  // ime_off
    -
    -  // u
    -  mh.fireKeyEvents(goog.events.KeyCodes.U, true, true, true);
    -  assertFalse('IME should not be triggered', mh.waitingForIme_);
    -
    -  mh.fireEvent('blur', '');
    -}
    -
    -
    -/**
    - * This test simulates the key inputs generated by pressing
    - * '<ime_on>a<enter>i<ime_off>u' using the Japanese IME
    - * on Mac/Safari3.
    - */
    -function testImeMacSafari3() {
    -  simulateMacSafari3();
    -  mh.fireEvent('focus', '');
    -  assertFalse('IME should not be triggered', mh.waitingForIme_);
    -
    -  // ime_on
    -
    -  // a
    -  mh.fireKeyEvents(goog.events.KeyCodes.WIN_IME, true, false, false);
    -  mh.fireKeyEvents(goog.events.KeyCodes.A, false, false, true);
    -  assertTrue('IME should be triggered', mh.waitingForIme_);
    -
    -  // enter
    -  mh.fireKeyEvents(goog.events.KeyCodes.WIN_IME, true, false, false);
    -  mh.fireKeyEvents(goog.events.KeyCodes.ENTER, false, false, true);
    -  assertFalse('IME should not be triggered', mh.waitingForIme_);
    -
    -  // i
    -  mh.fireKeyEvents(goog.events.KeyCodes.WIN_IME, true, false, false);
    -  mh.fireKeyEvents(goog.events.KeyCodes.I, false, false, true);
    -  assertTrue('IME should be triggered', mh.waitingForIme_);
    -
    -  // ime_off
    -
    -  // u
    -  mh.fireKeyEvents(goog.events.KeyCodes.U, true, true, true);
    -  assertFalse('IME should not be triggered', mh.waitingForIme_);
    -
    -  mh.fireEvent('blur', '');
    -}
    -
    -
    -/**
    - * This test simulates the key inputs generated by pressing
    - * '<ime_on>a<enter>i<ime_off>u' using the Japanese IME
    - * on Linux/Firefox3.
    - */
    -function testImeLinuxFirefox3() {
    -  // TODO(user): Currently our code cannot distinguish preedit characters
    -  // from normal ones for Linux/Firefox3.
    -  // Enable this test after we fix it.
    -
    -
    -  simulateLinuxFirefox3();
    -  mh.fireEvent('focus', '');
    -  assertFalse('IME should not be triggered', mh.waitingForIme_);
    -
    -  // ime_on
    -  mh.fireKeyEvents(goog.events.KeyCodes.WIN_IME, true, true, false);
    -
    -  // a
    -  mh.fireKeyEvents(goog.events.KeyCodes.A, true, false, true);
    -  assertTrue('IME should be triggered', mh.waitingForIme_);
    -
    -  // enter
    -  mh.fireKeyEvents(goog.events.KeyCodes.ENTER, true, true, true);
    -  assertFalse('IME should not be triggered', mh.waitingForIme_);
    -
    -  // i
    -  mh.fireKeyEvents(goog.events.KeyCodes.WIN_IME, true, true, false);
    -  mh.fireKeyEvents(goog.events.KeyCodes.I, true, false, true);
    -  assertTrue('IME should be triggered', mh.waitingForIme_);
    -
    -  // ime_off
    -
    -  // u
    -  mh.fireKeyEvents(goog.events.KeyCodes.U, true, true, true);
    -  assertFalse('IME should not be triggered', mh.waitingForIme_);
    -
    -  mh.fireEvent('blur', '');
    -}
    -
    -
    -/**
    - * Check attaching to an EventTarget instead of an element.
    - */
    -function testAttachEventTarget() {
    -  var target = new goog.events.EventTarget();
    -
    -  assertNull(mh.activeElement_);
    -  mh.attachInput(target);
    -  assertNull(mh.activeElement_);
    -
    -  mockElement.dispatchEvent(new goog.events.Event('focus', mockElement));
    -  assertEquals(mockElement, mh.activeElement_);
    -
    -  mh.detachInput(target);
    -}
    -
    -
    -/**
    - * Make sure that the active element handling works.
    - */
    -function testActiveElement() {
    -  assertNull(mh.activeElement_);
    -
    -  mockElement.dispatchEvent('keydown');
    -  assertEquals(mockElement, mh.activeElement_);
    -
    -  mockElement.dispatchEvent('blur');
    -  assertNull(mh.activeElement_);
    -
    -  mockElement.dispatchEvent('focus');
    -  assertEquals(mockElement, mh.activeElement_);
    -
    -  mh.detachInput(mockElement);
    -  assertNull(mh.activeElement_);
    -}
    -
    -
    -/**
    - * We can attach an EventTarget that isn't an element.
    - */
    -function testAttachEventTarget() {
    -  var target = new goog.events.EventTarget();
    -
    -  assertNull(mh.activeElement_);
    -  mh.attachInput(target);
    -  assertNull(mh.activeElement_);
    -
    -  target.dispatchEvent(new goog.events.Event('focus', mockElement));
    -  assertEquals(mockElement, mh.activeElement_);
    -
    -  mh.detachInput(target);
    -}
    -
    -
    -/**
    - * Make sure an already-focused element becomes active immediately.
    - */
    -function testActiveElementAlreadyFocused() {
    -  var element = document.getElementById('textInput');
    -  element.style.display = '';
    -  element.focus();
    -
    -  assertNull(mh.activeElement_);
    -
    -  mh.attachInput(element);
    -  assertEquals(element, mh.activeElement_);
    -
    -  mh.detachInput(element);
    -  element.style.display = 'none';
    -}
    -
    -function testUpdateDoesNotTriggerSetTokenForSelectRow() {
    -
    -  var ih = new goog.ui.ac.InputHandler();
    -
    -  // Set up our input handler with the necessary mocks
    -  var mockAutoCompleter = new MockAutoCompleter();
    -  ih.ac_ = mockAutoCompleter;
    -  ih.activeElement_ = mockElement;
    -
    -  var row = {};
    -  ih.selectRow(row, false);
    -
    -  ih.update();
    -  assertFalse('update should not call setToken on selectRow',
    -              mockAutoCompleter.setTokenWasCalled);
    -
    -  ih.update();
    -  assertFalse('update should not call setToken on selectRow',
    -              mockAutoCompleter.setTokenWasCalled);
    -}
    -
    -function testSetTokenText() {
    -
    -  var ih = new MockInputHandler();
    -
    -  // Set up our input handler with the necessary mocks
    -  var mockAutoCompleter = new MockAutoCompleter();
    -  ih.ac_ = mockAutoCompleter;
    -  ih.activeElement_ = mockElement;
    -  mockElement.value = 'bob, wal, joey';
    -  ih.setCursorPosition(8);
    -
    -  ih.setTokenText('waldo', true /* multi-row */);
    -
    -  assertEquals('bob, waldo, joey', mockElement.value);
    -}
    -
    -function testSetTokenTextLeftHandSideOfToken() {
    -
    -  var ih = new MockInputHandler();
    -  ih.setSeparators(' ');
    -  ih.setWhitespaceWrapEntries(false);
    -
    -  // Set up our input handler with the necessary mocks
    -  var mockAutoCompleter = new MockAutoCompleter();
    -  ih.ac_ = mockAutoCompleter;
    -  ih.activeElement_ = mockElement;
    -  mockElement.value = 'foo bar';
    -  // Sets cursor position right before 'bar'
    -  ih.setCursorPosition(4);
    -
    -  ih.setTokenText('bar', true /* multi-row */);
    -
    -  assertEquals('foo bar ', mockElement.value);
    -}
    -
    -function testEmptyTokenWithSeparator() {
    -  var ih = new goog.ui.ac.InputHandler();
    -  var mockAutoCompleter = new MockAutoCompleter();
    -  ih.ac_ = mockAutoCompleter;
    -  ih.activeElement_ = mockElement;
    -  mockElement.value = ', ,';
    -  // Sets cursor position before the second comma
    -  goog.dom.selection.setStart(mockElement, 2);
    -
    -  ih.update();
    -  assertTrue('update should call setToken on selectRow',
    -      mockAutoCompleter.setTokenWasCalled);
    -  assertEquals('update should be called with empty string',
    -      '', mockAutoCompleter.setToken);
    -}
    -
    -function testNonEmptyTokenWithSeparator() {
    -  var ih = new goog.ui.ac.InputHandler();
    -  var mockAutoCompleter = new MockAutoCompleter();
    -  ih.ac_ = mockAutoCompleter;
    -  ih.activeElement_ = mockElement;
    -  mockElement.value = ', joe ,';
    -  // Sets cursor position before the second comma
    -  goog.dom.selection.setStart(mockElement, 5);
    -
    -  ih.update();
    -  assertTrue('update should call setToken on selectRow',
    -      mockAutoCompleter.setTokenWasCalled);
    -  assertEquals('update should be called with expected string',
    -      'joe', mockAutoCompleter.setToken);
    -}
    -
    -function testGetThrottleTime() {
    -  var ih = new goog.ui.ac.InputHandler();
    -  ih.setThrottleTime(999);
    -  assertEquals('throttle time set+get', 999, ih.getThrottleTime());
    -}
    -
    -function testGetUpdateDuringTyping() {
    -  var ih = new goog.ui.ac.InputHandler();
    -  ih.setUpdateDuringTyping(false);
    -  assertFalse('update during typing set+get', ih.getUpdateDuringTyping());
    -}
    -
    -function testEnterToSelect() {
    -  mh.fireEvent('focus', '');
    -  mh.fireKeyEvents(goog.events.KeyCodes.ENTER, true, true, true);
    -  assertTrue('Should hilite', mh.ac_.selectHilitedWasCalled);
    -  assertFalse('Should NOT be dismissed', mh.ac_.dismissWasCalled);
    -}
    -
    -function testEnterDoesNotSelectWhenClosed() {
    -  mh.fireEvent('focus', '');
    -  mh.ac_.isOpen = goog.functions.FALSE;
    -  mh.fireKeyEvents(goog.events.KeyCodes.ENTER, true, true, true);
    -  assertFalse('Should NOT hilite', mh.ac_.selectHilitedWasCalled);
    -  assertTrue('Should be dismissed', mh.ac_.dismissWasCalled);
    -}
    -
    -function testTabToSelect() {
    -  mh.fireEvent('focus', '');
    -  mh.fireKeyEvents(goog.events.KeyCodes.TAB, true, true, true);
    -  assertTrue('Should hilite', mh.ac_.selectHilitedWasCalled);
    -  assertFalse('Should NOT be dismissed', mh.ac_.dismissWasCalled);
    -}
    -
    -function testTabDoesNotSelectWhenClosed() {
    -  mh.fireEvent('focus', '');
    -  mh.ac_.isOpen = goog.functions.FALSE;
    -  mh.fireKeyEvents(goog.events.KeyCodes.TAB, true, true, true);
    -  assertFalse('Should NOT hilite', mh.ac_.selectHilitedWasCalled);
    -  assertTrue('Should be dismissed', mh.ac_.dismissWasCalled);
    -}
    -
    -function testShiftTabDoesNotSelect() {
    -  mh.fireEvent('focus', '');
    -  mh.ac_.isOpen = goog.functions.TRUE;
    -  mh.fireKeyEvents(goog.events.KeyCodes.TAB, true, true, true,
    -      {shiftKey: true});
    -  assertFalse('Should NOT hilite', mh.ac_.selectHilitedWasCalled);
    -  assertTrue('Should be dismissed', mh.ac_.dismissWasCalled);
    -}
    -
    -function testEmptySeparatorUsesDefaults() {
    -  var inputHandler = new goog.ui.ac.InputHandler('');
    -  assertFalse(inputHandler.separatorCheck_.test(''));
    -  assertFalse(inputHandler.separatorCheck_.test('x'));
    -  assertTrue(inputHandler.separatorCheck_.test(','));
    -}
    -
    -function testMultipleSeparatorUsesEmptyDefaults() {
    -  var inputHandler = new goog.ui.ac.InputHandler(',\n', null, true);
    -  inputHandler.setWhitespaceWrapEntries(false);
    -  inputHandler.setSeparators(',\n', '');
    -
    -  // Set up our input handler with the necessary mocks
    -  var mockAutoCompleter = new MockAutoCompleter();
    -  inputHandler.ac_ = mockAutoCompleter;
    -  inputHandler.activeElement_ = mockElement;
    -  mockElement.value = 'bob,wal';
    -  inputHandler.setCursorPosition(8);
    -
    -  inputHandler.setTokenText('waldo', true /* multi-row */);
    -
    -  assertEquals('bob,waldo', mockElement.value);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/ac/remote.js b/src/database/third_party/closure-library/closure/goog/ui/ac/remote.js
    deleted file mode 100644
    index 121b98d9383..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/ac/remote.js
    +++ /dev/null
    @@ -1,114 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Factory class to create a simple autocomplete that will match
    - * from an array of data provided via ajax.
    - *
    - * @see ../../demos/autocompleteremote.html
    - */
    -
    -goog.provide('goog.ui.ac.Remote');
    -
    -goog.require('goog.ui.ac.AutoComplete');
    -goog.require('goog.ui.ac.InputHandler');
    -goog.require('goog.ui.ac.RemoteArrayMatcher');
    -goog.require('goog.ui.ac.Renderer');
    -
    -
    -
    -/**
    - * Factory class for building a remote autocomplete widget that autocompletes
    - * an inputbox or text area from a data array provided via ajax.
    - * @param {string} url The Uri which generates the auto complete matches.
    - * @param {Element} input Input element or text area.
    - * @param {boolean=} opt_multi Whether to allow multiple entries; defaults
    - *     to false.
    - * @param {boolean=} opt_useSimilar Whether to use similar matches; e.g.
    - *     "gost" => "ghost".
    - * @constructor
    - * @extends {goog.ui.ac.AutoComplete}
    - */
    -goog.ui.ac.Remote = function(url, input, opt_multi, opt_useSimilar) {
    -  var matcher = new goog.ui.ac.RemoteArrayMatcher(url, !opt_useSimilar);
    -  this.matcher_ = matcher;
    -
    -  var renderer = new goog.ui.ac.Renderer();
    -
    -  var inputhandler = new goog.ui.ac.InputHandler(null, null, !!opt_multi, 300);
    -
    -  goog.ui.ac.AutoComplete.call(this, matcher, renderer, inputhandler);
    -
    -  inputhandler.attachAutoComplete(this);
    -  inputhandler.attachInputs(input);
    -};
    -goog.inherits(goog.ui.ac.Remote, goog.ui.ac.AutoComplete);
    -
    -
    -/**
    - * Set whether or not standard highlighting should be used when rendering rows.
    - * @param {boolean} useStandardHighlighting true if standard highlighting used.
    - */
    -goog.ui.ac.Remote.prototype.setUseStandardHighlighting =
    -    function(useStandardHighlighting) {
    -  this.renderer_.setUseStandardHighlighting(useStandardHighlighting);
    -};
    -
    -
    -/**
    - * Gets the attached InputHandler object.
    - * @return {goog.ui.ac.InputHandler} The input handler.
    - */
    -goog.ui.ac.Remote.prototype.getInputHandler = function() {
    -  return /** @type {goog.ui.ac.InputHandler} */ (
    -      this.selectionHandler_);
    -};
    -
    -
    -/**
    - * Set the send method ("GET", "POST") for the matcher.
    - * @param {string} method The send method; default: GET.
    - */
    -goog.ui.ac.Remote.prototype.setMethod = function(method) {
    -  this.matcher_.setMethod(method);
    -};
    -
    -
    -/**
    - * Set the post data for the matcher.
    - * @param {string} content Post data.
    - */
    -goog.ui.ac.Remote.prototype.setContent = function(content) {
    -  this.matcher_.setContent(content);
    -};
    -
    -
    -/**
    - * Set the HTTP headers for the matcher.
    - * @param {Object|goog.structs.Map} headers Map of headers to add to the
    - *     request.
    - */
    -goog.ui.ac.Remote.prototype.setHeaders = function(headers) {
    -  this.matcher_.setHeaders(headers);
    -};
    -
    -
    -/**
    - * Set the timeout interval for the matcher.
    - * @param {number} interval Number of milliseconds after which an
    - *     incomplete request will be aborted; 0 means no timeout is set.
    - */
    -goog.ui.ac.Remote.prototype.setTimeoutInterval = function(interval) {
    -  this.matcher_.setTimeoutInterval(interval);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/ac/remotearraymatcher.js b/src/database/third_party/closure-library/closure/goog/ui/ac/remotearraymatcher.js
    deleted file mode 100644
    index d2b6c235a70..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/ac/remotearraymatcher.js
    +++ /dev/null
    @@ -1,274 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Class that retrieves autocomplete matches via an ajax call.
    - *
    - */
    -
    -goog.provide('goog.ui.ac.RemoteArrayMatcher');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.Uri');
    -goog.require('goog.events');
    -goog.require('goog.json');
    -goog.require('goog.net.EventType');
    -goog.require('goog.net.XhrIo');
    -
    -
    -
    -/**
    - * An array matcher that requests matches via ajax.
    - * @param {string} url The Uri which generates the auto complete matches.  The
    - *     search term is passed to the server as the 'token' query param.
    - * @param {boolean=} opt_noSimilar If true, request that the server does not do
    - *     similarity matches for the input token against the dictionary.
    - *     The value is sent to the server as the 'use_similar' query param which is
    - *     either "1" (opt_noSimilar==false) or "0" (opt_noSimilar==true).
    - * @param {goog.net.XmlHttpFactory=} opt_xmlHttpFactory Specify the
    - *     XmlHttpFactory used to retrieve the matches.
    - * @constructor
    - * @extends {goog.Disposable}
    - */
    -goog.ui.ac.RemoteArrayMatcher =
    -    function(url, opt_noSimilar, opt_xmlHttpFactory) {
    -  goog.Disposable.call(this);
    -
    -  /**
    -   * The base URL for the ajax call.  The token and max_matches are added as
    -   * query params.
    -   * @type {string}
    -   * @private
    -   */
    -  this.url_ = url;
    -
    -  /**
    -   * Whether similar matches should be found as well.  This is sent as a hint
    -   * to the server only.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.useSimilar_ = !opt_noSimilar;
    -
    -  /**
    -   * The XhrIo object used for making remote requests.  When a new request
    -   * is made, the current one is aborted and the new one sent.
    -   * @type {goog.net.XhrIo}
    -   * @private
    -   */
    -  this.xhr_ = new goog.net.XhrIo(opt_xmlHttpFactory);
    -};
    -goog.inherits(goog.ui.ac.RemoteArrayMatcher, goog.Disposable);
    -
    -
    -/**
    - * The HTTP send method (GET, POST) to use when making the ajax call.
    - * @type {string}
    - * @private
    - */
    -goog.ui.ac.RemoteArrayMatcher.prototype.method_ = 'GET';
    -
    -
    -/**
    - * Data to submit during a POST.
    - * @type {string|undefined}
    - * @private
    - */
    -goog.ui.ac.RemoteArrayMatcher.prototype.content_ = undefined;
    -
    -
    -/**
    - * Headers to send with every HTTP request.
    - * @type {Object|goog.structs.Map}
    - * @private
    - */
    -goog.ui.ac.RemoteArrayMatcher.prototype.headers_ = null;
    -
    -
    -/**
    - * Key to the listener on XHR. Used to clear previous listeners.
    - * @type {goog.events.Key}
    - * @private
    - */
    -goog.ui.ac.RemoteArrayMatcher.prototype.lastListenerKey_ = null;
    -
    -
    -/**
    - * Set the send method ("GET", "POST").
    - * @param {string} method The send method; default: GET.
    - */
    -goog.ui.ac.RemoteArrayMatcher.prototype.setMethod = function(method) {
    -  this.method_ = method;
    -};
    -
    -
    -/**
    - * Set the post data.
    - * @param {string} content Post data.
    - */
    -goog.ui.ac.RemoteArrayMatcher.prototype.setContent = function(content) {
    -  this.content_ = content;
    -};
    -
    -
    -/**
    - * Set the HTTP headers.
    - * @param {Object|goog.structs.Map} headers Map of headers to add to the
    - *     request.
    - */
    -goog.ui.ac.RemoteArrayMatcher.prototype.setHeaders = function(headers) {
    -  this.headers_ = headers;
    -};
    -
    -
    -/**
    - * Set the timeout interval.
    - * @param {number} interval Number of milliseconds after which an
    - *     incomplete request will be aborted; 0 means no timeout is set.
    - */
    -goog.ui.ac.RemoteArrayMatcher.prototype.setTimeoutInterval =
    -    function(interval) {
    -  this.xhr_.setTimeoutInterval(interval);
    -};
    -
    -
    -/**
    - * Builds a complete GET-style URL, given the base URI and autocomplete related
    - * parameter values.
    - * <b>Override this to build any customized lookup URLs.</b>
    - * <b>Can be used to change request method and any post content as well.</b>
    - * @param {string} uri The base URI of the request target.
    - * @param {string} token Current token in autocomplete.
    - * @param {number} maxMatches Maximum number of matches required.
    - * @param {boolean} useSimilar A hint to the server.
    - * @param {string=} opt_fullString Complete text in the input element.
    - * @return {?string} The complete url. Return null if no request should be sent.
    - * @protected
    - */
    -goog.ui.ac.RemoteArrayMatcher.prototype.buildUrl = function(uri,
    -    token, maxMatches, useSimilar, opt_fullString) {
    -  var url = new goog.Uri(uri);
    -  url.setParameterValue('token', token);
    -  url.setParameterValue('max_matches', String(maxMatches));
    -  url.setParameterValue('use_similar', String(Number(useSimilar)));
    -  return url.toString();
    -};
    -
    -
    -/**
    - * Returns whether the suggestions should be updated?
    - * <b>Override this to prevent updates eg - when token is empty.</b>
    - * @param {string} uri The base URI of the request target.
    - * @param {string} token Current token in autocomplete.
    - * @param {number} maxMatches Maximum number of matches required.
    - * @param {boolean} useSimilar A hint to the server.
    - * @param {string=} opt_fullString Complete text in the input element.
    - * @return {boolean} Whether new matches be requested.
    - * @protected
    - */
    -goog.ui.ac.RemoteArrayMatcher.prototype.shouldRequestMatches =
    -    function(uri, token, maxMatches, useSimilar, opt_fullString) {
    -  return true;
    -};
    -
    -
    -/**
    - * Parses and retrieves the array of suggestions from XHR response.
    - * <b>Override this if the response is not a simple JSON array.</b>
    - * @param {string} responseText The XHR response text.
    - * @return {Array<string>} The array of suggestions.
    - * @protected
    - */
    -goog.ui.ac.RemoteArrayMatcher.prototype.parseResponseText = function(
    -    responseText) {
    -
    -  var matches = [];
    -  // If there is no response text, unsafeParse will throw a syntax error.
    -  if (responseText) {
    -    /** @preserveTry */
    -    try {
    -      matches = goog.json.unsafeParse(responseText);
    -    } catch (exception) {
    -    }
    -  }
    -  return /** @type {Array<string>} */ (matches);
    -};
    -
    -
    -/**
    - * Handles the XHR response.
    - * @param {string} token The XHR autocomplete token.
    - * @param {Function} matchHandler The AutoComplete match handler.
    - * @param {goog.events.Event} event The XHR success event.
    - */
    -goog.ui.ac.RemoteArrayMatcher.prototype.xhrCallback = function(token,
    -    matchHandler, event) {
    -  var text = event.target.getResponseText();
    -  matchHandler(token, this.parseResponseText(text));
    -};
    -
    -
    -/**
    - * Retrieve a set of matching rows from the server via ajax.
    - * @param {string} token The text that should be matched; passed to the server
    - *     as the 'token' query param.
    - * @param {number} maxMatches The maximum number of matches requested from the
    - *     server; passed as the 'max_matches' query param.  The server is
    - *     responsible for limiting the number of matches that are returned.
    - * @param {Function} matchHandler Callback to execute on the result after
    - *     matching.
    - * @param {string=} opt_fullString The full string from the input box.
    - */
    -goog.ui.ac.RemoteArrayMatcher.prototype.requestMatchingRows =
    -    function(token, maxMatches, matchHandler, opt_fullString) {
    -
    -  if (!this.shouldRequestMatches(this.url_, token, maxMatches, this.useSimilar_,
    -      opt_fullString)) {
    -    return;
    -  }
    -  // Set the query params on the URL.
    -  var url = this.buildUrl(this.url_, token, maxMatches, this.useSimilar_,
    -      opt_fullString);
    -  if (!url) {
    -    // Do nothing if there is no URL.
    -    return;
    -  }
    -
    -  // The callback evals the server response and calls the match handler on
    -  // the array of matches.
    -  var callback = goog.bind(this.xhrCallback, this, token, matchHandler);
    -
    -  // Abort the current request and issue the new one; prevent requests from
    -  // being queued up by the browser with a slow server
    -  if (this.xhr_.isActive()) {
    -    this.xhr_.abort();
    -  }
    -  // This ensures if previous XHR is aborted or ends with error, the
    -  // corresponding success-callbacks are cleared.
    -  if (this.lastListenerKey_) {
    -    goog.events.unlistenByKey(this.lastListenerKey_);
    -  }
    -  // Listen once ensures successful callback gets cleared by itself.
    -  this.lastListenerKey_ = goog.events.listenOnce(this.xhr_,
    -      goog.net.EventType.SUCCESS, callback);
    -  this.xhr_.send(url, this.method_, this.content_, this.headers_);
    -};
    -
    -
    -/** @override */
    -goog.ui.ac.RemoteArrayMatcher.prototype.disposeInternal = function() {
    -  this.xhr_.dispose();
    -  goog.ui.ac.RemoteArrayMatcher.superClass_.disposeInternal.call(
    -      this);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/ac/remotearraymatcher_test.html b/src/database/third_party/closure-library/closure/goog/ui/ac/remotearraymatcher_test.html
    deleted file mode 100644
    index f8804075883..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/ac/remotearraymatcher_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.ac.RemoteArrayMatcher
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.ac.RemoteArrayMatcherTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/ac/remotearraymatcher_test.js b/src/database/third_party/closure-library/closure/goog/ui/ac/remotearraymatcher_test.js
    deleted file mode 100644
    index 65080ce3162..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/ac/remotearraymatcher_test.js
    +++ /dev/null
    @@ -1,67 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.ac.RemoteArrayMatcherTest');
    -goog.setTestOnly('goog.ui.ac.RemoteArrayMatcherTest');
    -
    -goog.require('goog.json');
    -goog.require('goog.net.XhrIo');
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.net.XhrIo');
    -goog.require('goog.ui.ac.RemoteArrayMatcher');
    -var url = 'http://www.google.com';
    -var token = 'goog';
    -var maxMatches = 5;
    -var fullToken = 'google';
    -
    -var responseJsonText = "['eric', 'larry', 'sergey', 'marissa', 'pupius']";
    -var responseJson = goog.json.unsafeParse(responseJsonText);
    -
    -var mockControl;
    -var mockMatchHandler;
    -
    -
    -function setUp() {
    -  goog.net.XhrIo = goog.testing.net.XhrIo;
    -  mockControl = new goog.testing.MockControl();
    -  mockMatchHandler = mockControl.createFunctionMock();
    -}
    -
    -function testRequestMatchingRows_noSimilarTrue() {
    -  var matcher = new goog.ui.ac.RemoteArrayMatcher(url);
    -  mockMatchHandler(token, responseJson);
    -  mockControl.$replayAll();
    -  matcher.requestMatchingRows(token, maxMatches, mockMatchHandler, fullToken);
    -  matcher.xhr_.simulateResponse(200, responseJsonText);
    -  mockControl.$verifyAll();
    -  mockControl.$resetAll();
    -}
    -
    -function testRequestMatchingRows_twoCalls() {
    -  var matcher = new goog.ui.ac.RemoteArrayMatcher(url);
    -
    -  var dummyMatchHandler = mockControl.createFunctionMock();
    -
    -  mockMatchHandler(token, responseJson);
    -  mockControl.$replayAll();
    -
    -  matcher.requestMatchingRows(token, maxMatches, dummyMatchHandler,
    -      fullToken);
    -
    -  matcher.requestMatchingRows(token, maxMatches, mockMatchHandler, fullToken);
    -  matcher.xhr_.simulateResponse(200, responseJsonText);
    -  mockControl.$verifyAll();
    -  mockControl.$resetAll();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/ac/renderer.js b/src/database/third_party/closure-library/closure/goog/ui/ac/renderer.js
    deleted file mode 100644
    index 49b494f8f2b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/ac/renderer.js
    +++ /dev/null
    @@ -1,1100 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Class for rendering the results of an auto complete and
    - * allow the user to select an row.
    - *
    - */
    -
    -goog.provide('goog.ui.ac.Renderer');
    -goog.provide('goog.ui.ac.Renderer.CustomRenderer');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.dispose');
    -goog.require('goog.dom');
    -goog.require('goog.dom.NodeType');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -goog.require('goog.fx.dom.FadeInAndShow');
    -goog.require('goog.fx.dom.FadeOutAndHide');
    -goog.require('goog.positioning');
    -goog.require('goog.positioning.Corner');
    -goog.require('goog.positioning.Overflow');
    -goog.require('goog.string');
    -goog.require('goog.style');
    -goog.require('goog.ui.IdGenerator');
    -goog.require('goog.ui.ac.AutoComplete');
    -
    -
    -
    -/**
    - * Class for rendering the results of an auto-complete in a drop down list.
    - *
    - * @constructor
    - * @param {Element=} opt_parentNode optional reference to the parent element
    - *     that will hold the autocomplete elements. goog.dom.getDocument().body
    - *     will be used if this is null.
    - * @param {?({renderRow}|{render})=} opt_customRenderer Custom full renderer to
    - *     render each row. Should be something with a renderRow or render method.
    - * @param {boolean=} opt_rightAlign Determines if the autocomplete will always
    - *     be right aligned. False by default.
    - * @param {boolean=} opt_useStandardHighlighting Determines if standard
    - *     highlighting should be applied to each row of data. Standard highlighting
    - *     bolds every matching substring for a given token in each row. True by
    - *     default.
    - * @extends {goog.events.EventTarget}
    - */
    -goog.ui.ac.Renderer = function(opt_parentNode, opt_customRenderer,
    -    opt_rightAlign, opt_useStandardHighlighting) {
    -  goog.ui.ac.Renderer.base(this, 'constructor');
    -
    -  /**
    -   * Reference to the parent element that will hold the autocomplete elements
    -   * @type {Element}
    -   * @private
    -   */
    -  this.parent_ = opt_parentNode || goog.dom.getDocument().body;
    -
    -  /**
    -   * Dom helper for the parent element's document.
    -   * @type {goog.dom.DomHelper}
    -   * @private
    -   */
    -  this.dom_ = goog.dom.getDomHelper(this.parent_);
    -
    -  /**
    -   * Whether to reposition the autocomplete UI below the target node
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.reposition_ = !opt_parentNode;
    -
    -  /**
    -   * Reference to the main element that controls the rendered autocomplete
    -   * @type {Element}
    -   * @private
    -   */
    -  this.element_ = null;
    -
    -  /**
    -   * The current token that has been entered
    -   * @type {string}
    -   * @private
    -   */
    -  this.token_ = '';
    -
    -  /**
    -   * Array used to store the current set of rows being displayed
    -   * @type {Array<!Object>}
    -   * @private
    -   */
    -  this.rows_ = [];
    -
    -  /**
    -   * Array of the node divs that hold each result that is being displayed.
    -   * @type {Array<Element>}
    -   * @protected
    -   * @suppress {underscore|visibility}
    -   */
    -  this.rowDivs_ = [];
    -
    -  /**
    -   * The index of the currently highlighted row
    -   * @type {number}
    -   * @protected
    -   * @suppress {underscore|visibility}
    -   */
    -  this.hilitedRow_ = -1;
    -
    -  /**
    -   * The time that the rendering of the menu rows started
    -   * @type {number}
    -   * @protected
    -   * @suppress {underscore|visibility}
    -   */
    -  this.startRenderingRows_ = -1;
    -
    -  /**
    -   * Store the current state for the renderer
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.visible_ = false;
    -
    -  /**
    -   * Classname for the main element.  This must be a single valid class name.
    -   * @type {string}
    -   */
    -  this.className = goog.getCssName('ac-renderer');
    -
    -  /**
    -   * Classname for row divs.  This must be a single valid class name.
    -   * @type {string}
    -   */
    -  this.rowClassName = goog.getCssName('ac-row');
    -
    -  // TODO(gboyer): Remove this as soon as we remove references and ensure that
    -  // no groups are pushing javascript using this.
    -  /**
    -   * The old class name for active row.  This name is deprecated because its
    -   * name is generic enough that a typical implementation would require a
    -   * descendant selector.
    -   * Active row will have rowClassName & activeClassName &
    -   * legacyActiveClassName.
    -   * @type {string}
    -   * @private
    -   */
    -  this.legacyActiveClassName_ = goog.getCssName('active');
    -
    -  /**
    -   * Class name for active row div.  This must be a single valid class name.
    -   * Active row will have rowClassName & activeClassName &
    -   * legacyActiveClassName.
    -   * @type {string}
    -   */
    -  this.activeClassName = goog.getCssName('ac-active');
    -
    -  /**
    -   * Class name for the bold tag highlighting the matched part of the text.
    -   * @type {string}
    -   */
    -  this.highlightedClassName = goog.getCssName('ac-highlighted');
    -
    -  /**
    -   * Custom full renderer
    -   * @type {?({renderRow}|{render})}
    -   * @private
    -   */
    -  this.customRenderer_ = opt_customRenderer || null;
    -
    -  /**
    -   * Flag to indicate whether standard highlighting should be applied.
    -   * this is set to true if left unspecified to retain existing
    -   * behaviour for autocomplete clients
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.useStandardHighlighting_ = opt_useStandardHighlighting != null ?
    -      opt_useStandardHighlighting : true;
    -
    -  /**
    -   * Flag to indicate whether matches should be done on whole words instead
    -   * of any string.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.matchWordBoundary_ = true;
    -
    -  /**
    -   * Flag to set all tokens as highlighted in the autocomplete row.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.highlightAllTokens_ = false;
    -
    -  /**
    -   * Determines if the autocomplete will always be right aligned
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.rightAlign_ = !!opt_rightAlign;
    -
    -  /**
    -   * Whether to align with top of target field
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.topAlign_ = false;
    -
    -  /**
    -   * Duration (in msec) of fade animation when menu is shown/hidden.
    -   * Setting to 0 (default) disables animation entirely.
    -   * @type {number}
    -   * @private
    -   */
    -  this.menuFadeDuration_ = 0;
    -
    -  /**
    -   * Whether we should limit the dropdown from extending past the bottom of the
    -   * screen and instead show a scrollbar on the dropdown.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.showScrollbarsIfTooLarge_ = false;
    -
    -  /**
    -   * Animation in progress, if any.
    -   * @type {goog.fx.Animation|undefined}
    -   */
    -  this.animation_;
    -};
    -goog.inherits(goog.ui.ac.Renderer, goog.events.EventTarget);
    -
    -
    -/**
    - * The anchor element to position the rendered autocompleter against.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.ac.Renderer.prototype.anchorElement_;
    -
    -
    -/**
    - * The element on which to base the width of the autocomplete.
    - * @type {Node}
    - * @private
    - */
    -goog.ui.ac.Renderer.prototype.widthProvider_;
    -
    -
    -/**
    - * A flag used to make sure we highlight only one match in the rendered row.
    - * @private {boolean}
    - */
    -goog.ui.ac.Renderer.prototype.wasHighlightedAtLeastOnce_;
    -
    -
    -/**
    - * The delay before mouseover events are registered, in milliseconds
    - * @type {number}
    - * @const
    - */
    -goog.ui.ac.Renderer.DELAY_BEFORE_MOUSEOVER = 300;
    -
    -
    -/**
    - * Gets the renderer's element.
    - * @return {Element} The  main element that controls the rendered autocomplete.
    - */
    -goog.ui.ac.Renderer.prototype.getElement = function() {
    -  return this.element_;
    -};
    -
    -
    -/**
    - * Sets the width provider element. The provider is only used on redraw and as
    - * such will not automatically update on resize.
    - * @param {Node} widthProvider The element whose width should be mirrored.
    - */
    -goog.ui.ac.Renderer.prototype.setWidthProvider = function(widthProvider) {
    -  this.widthProvider_ = widthProvider;
    -};
    -
    -
    -/**
    - * Set whether to align autocomplete to top of target element
    - * @param {boolean} align If true, align to top.
    - */
    -goog.ui.ac.Renderer.prototype.setTopAlign = function(align) {
    -  this.topAlign_ = align;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether we should be aligning to the top of
    - *     the target element.
    - */
    -goog.ui.ac.Renderer.prototype.getTopAlign = function() {
    -  return this.topAlign_;
    -};
    -
    -
    -/**
    - * Set whether to align autocomplete to the right of the target element.
    - * @param {boolean} align If true, align to right.
    - */
    -goog.ui.ac.Renderer.prototype.setRightAlign = function(align) {
    -  this.rightAlign_ = align;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the autocomplete menu should be right aligned.
    - */
    -goog.ui.ac.Renderer.prototype.getRightAlign = function() {
    -  return this.rightAlign_;
    -};
    -
    -
    -/**
    - * @param {boolean} show Whether we should limit the dropdown from extending
    - *     past the bottom of the screen and instead show a scrollbar on the
    - *     dropdown.
    - */
    -goog.ui.ac.Renderer.prototype.setShowScrollbarsIfTooLarge = function(show) {
    -  this.showScrollbarsIfTooLarge_ = show;
    -};
    -
    -
    -/**
    - * Set whether or not standard highlighting should be used when rendering rows.
    - * @param {boolean} useStandardHighlighting true if standard highlighting used.
    - */
    -goog.ui.ac.Renderer.prototype.setUseStandardHighlighting =
    -    function(useStandardHighlighting) {
    -  this.useStandardHighlighting_ = useStandardHighlighting;
    -};
    -
    -
    -/**
    - * @param {boolean} matchWordBoundary Determines whether matches should be
    - *     higlighted only when the token matches text at a whole-word boundary.
    - *     True by default.
    - */
    -goog.ui.ac.Renderer.prototype.setMatchWordBoundary =
    -    function(matchWordBoundary) {
    -  this.matchWordBoundary_ = matchWordBoundary;
    -};
    -
    -
    -/**
    - * Set whether or not to highlight all matching tokens rather than just the
    - * first.
    - * @param {boolean} highlightAllTokens Whether to highlight all matching tokens
    - *     rather than just the first.
    - */
    -goog.ui.ac.Renderer.prototype.setHighlightAllTokens =
    -    function(highlightAllTokens) {
    -  this.highlightAllTokens_ = highlightAllTokens;
    -};
    -
    -
    -/**
    - * Sets the duration (in msec) of the fade animation when menu is shown/hidden.
    - * Setting to 0 (default) disables animation entirely.
    - * @param {number} duration Duration (in msec) of the fade animation (or 0 for
    - *     no animation).
    - */
    -goog.ui.ac.Renderer.prototype.setMenuFadeDuration = function(duration) {
    -  this.menuFadeDuration_ = duration;
    -};
    -
    -
    -/**
    - * Sets the anchor element for the subsequent call to renderRows.
    - * @param {Element} anchor The anchor element.
    - */
    -goog.ui.ac.Renderer.prototype.setAnchorElement = function(anchor) {
    -  this.anchorElement_ = anchor;
    -};
    -
    -
    -/**
    - * @return {Element} The anchor element.
    - * @protected
    - */
    -goog.ui.ac.Renderer.prototype.getAnchorElement = function() {
    -  return this.anchorElement_;
    -};
    -
    -
    -/**
    - * Render the autocomplete UI
    - *
    - * @param {Array<!Object>} rows Matching UI rows.
    - * @param {string} token Token we are currently matching against.
    - * @param {Element=} opt_target Current HTML node, will position popup beneath
    - *     this node.
    - */
    -goog.ui.ac.Renderer.prototype.renderRows = function(rows, token, opt_target) {
    -  this.token_ = token;
    -  this.rows_ = rows;
    -  this.hilitedRow_ = -1;
    -  this.startRenderingRows_ = goog.now();
    -  this.target_ = opt_target;
    -  this.rowDivs_ = [];
    -  this.redraw();
    -};
    -
    -
    -/**
    - * Hide the object.
    - */
    -goog.ui.ac.Renderer.prototype.dismiss = function() {
    -  if (this.target_) {
    -    goog.a11y.aria.setActiveDescendant(this.target_, null);
    -  }
    -  if (this.visible_) {
    -    this.visible_ = false;
    -
    -    // Clear ARIA popup role for the target input box.
    -    if (this.target_) {
    -      goog.a11y.aria.setState(this.target_,
    -          goog.a11y.aria.State.HASPOPUP,
    -          false);
    -    }
    -
    -    if (this.menuFadeDuration_ > 0) {
    -      goog.dispose(this.animation_);
    -      this.animation_ = new goog.fx.dom.FadeOutAndHide(this.element_,
    -          this.menuFadeDuration_);
    -      this.animation_.play();
    -    } else {
    -      goog.style.setElementShown(this.element_, false);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Show the object.
    - */
    -goog.ui.ac.Renderer.prototype.show = function() {
    -  if (!this.visible_) {
    -    this.visible_ = true;
    -
    -    // Set ARIA roles and states for the target input box.
    -    if (this.target_) {
    -      goog.a11y.aria.setRole(this.target_,
    -          goog.a11y.aria.Role.COMBOBOX);
    -      goog.a11y.aria.setState(this.target_,
    -          goog.a11y.aria.State.AUTOCOMPLETE,
    -          'list');
    -      goog.a11y.aria.setState(this.target_,
    -          goog.a11y.aria.State.HASPOPUP,
    -          true);
    -    }
    -
    -    if (this.menuFadeDuration_ > 0) {
    -      goog.dispose(this.animation_);
    -      this.animation_ = new goog.fx.dom.FadeInAndShow(this.element_,
    -          this.menuFadeDuration_);
    -      this.animation_.play();
    -    } else {
    -      goog.style.setElementShown(this.element_, true);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} True if the object is visible.
    - */
    -goog.ui.ac.Renderer.prototype.isVisible = function() {
    -  return this.visible_;
    -};
    -
    -
    -/**
    - * Sets the 'active' class of the nth item.
    - * @param {number} index Index of the item to highlight.
    - */
    -goog.ui.ac.Renderer.prototype.hiliteRow = function(index) {
    -  var row = index >= 0 && index < this.rows_.length ?
    -      this.rows_[index] : undefined;
    -  var rowDiv = index >= 0 && index < this.rowDivs_.length ?
    -      this.rowDivs_[index] : undefined;
    -
    -  var evtObj = /** @lends {goog.events.Event.prototype} */ ({
    -    type: goog.ui.ac.AutoComplete.EventType.ROW_HILITE,
    -    rowNode: rowDiv,
    -    row: row ? row.data : null
    -  });
    -  if (this.dispatchEvent(evtObj)) {
    -    this.hiliteNone();
    -    this.hilitedRow_ = index;
    -    if (rowDiv) {
    -      goog.dom.classlist.addAll(rowDiv, [this.activeClassName,
    -        this.legacyActiveClassName_]);
    -      if (this.target_) {
    -        goog.a11y.aria.setActiveDescendant(this.target_, rowDiv);
    -      }
    -      goog.style.scrollIntoContainerView(rowDiv, this.element_);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Removes the 'active' class from the currently selected row.
    - */
    -goog.ui.ac.Renderer.prototype.hiliteNone = function() {
    -  if (this.hilitedRow_ >= 0) {
    -    goog.dom.classlist.removeAll(
    -        goog.asserts.assert(this.rowDivs_[this.hilitedRow_]),
    -        [this.activeClassName, this.legacyActiveClassName_]);
    -  }
    -};
    -
    -
    -/**
    - * Sets the 'active' class of the item with a given id.
    - * @param {number} id Id of the row to hilight. If id is -1 then no rows get
    - *     hilited.
    - */
    -goog.ui.ac.Renderer.prototype.hiliteId = function(id) {
    -  if (id == -1) {
    -    this.hiliteRow(-1);
    -  } else {
    -    for (var i = 0; i < this.rows_.length; i++) {
    -      if (this.rows_[i].id == id) {
    -        this.hiliteRow(i);
    -        return;
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Sets CSS classes on autocomplete conatainer element.
    - *
    - * @param {Element} elem The container element.
    - * @private
    - */
    -goog.ui.ac.Renderer.prototype.setMenuClasses_ = function(elem) {
    -  goog.asserts.assert(elem);
    -  // Legacy clients may set the renderer's className to a space-separated list
    -  // or even have a trailing space.
    -  goog.dom.classlist.addAll(elem, goog.string.trim(this.className).split(' '));
    -};
    -
    -
    -/**
    - * If the main HTML element hasn't been made yet, creates it and appends it
    - * to the parent.
    - * @private
    - */
    -goog.ui.ac.Renderer.prototype.maybeCreateElement_ = function() {
    -  if (!this.element_) {
    -    // Make element and add it to the parent
    -    var el = this.dom_.createDom('div', {style: 'display:none'});
    -    if (this.showScrollbarsIfTooLarge_) {
    -      // Make sure that the dropdown will get scrollbars if it isn't large
    -      // enough to show all rows.
    -      el.style.overflowY = 'auto';
    -    }
    -    this.element_ = el;
    -    this.setMenuClasses_(el);
    -    goog.a11y.aria.setRole(el, goog.a11y.aria.Role.LISTBOX);
    -
    -    el.id = goog.ui.IdGenerator.getInstance().getNextUniqueId();
    -
    -    this.dom_.appendChild(this.parent_, el);
    -
    -    // Add this object as an event handler
    -    goog.events.listen(el, goog.events.EventType.CLICK,
    -                       this.handleClick_, false, this);
    -    goog.events.listen(el, goog.events.EventType.MOUSEDOWN,
    -                       this.handleMouseDown_, false, this);
    -    goog.events.listen(el, goog.events.EventType.MOUSEOVER,
    -                       this.handleMouseOver_, false, this);
    -  }
    -};
    -
    -
    -/**
    - * Redraw (or draw if this is the first call) the rendered auto-complete drop
    - * down.
    - */
    -goog.ui.ac.Renderer.prototype.redraw = function() {
    -  // Create the element if it doesn't yet exist
    -  this.maybeCreateElement_();
    -
    -  // For top aligned with target (= bottom aligned element),
    -  // we need to hide and then add elements while hidden to prevent
    -  // visible repositioning
    -  if (this.topAlign_) {
    -    this.element_.style.visibility = 'hidden';
    -  }
    -
    -  if (this.widthProvider_) {
    -    var width = this.widthProvider_.clientWidth + 'px';
    -    this.element_.style.minWidth = width;
    -  }
    -
    -  // Remove the current child nodes
    -  this.rowDivs_.length = 0;
    -  this.dom_.removeChildren(this.element_);
    -
    -  // Generate the new rows (use forEach so we can change rows_ from an
    -  // array to a different datastructure if required)
    -  if (this.customRenderer_ && this.customRenderer_.render) {
    -    this.customRenderer_.render(this, this.element_, this.rows_, this.token_);
    -  } else {
    -    var curRow = null;
    -    goog.array.forEach(this.rows_, function(row) {
    -      row = this.renderRowHtml(row, this.token_);
    -      if (this.topAlign_) {
    -        // Aligned with top of target = best match at bottom
    -        this.element_.insertBefore(row, curRow);
    -      } else {
    -        this.dom_.appendChild(this.element_, row);
    -      }
    -      curRow = row;
    -    }, this);
    -  }
    -
    -  // Don't show empty result sets
    -  if (this.rows_.length == 0) {
    -    this.dismiss();
    -    return;
    -  } else {
    -    this.show();
    -  }
    -
    -  this.reposition();
    -
    -  // Make the autocompleter unselectable, so that it
    -  // doesn't steal focus from the input field when clicked.
    -  goog.style.setUnselectable(this.element_, true);
    -};
    -
    -
    -/**
    - * @return {goog.positioning.Corner} The anchor corner to position the popup at.
    - * @protected
    - */
    -goog.ui.ac.Renderer.prototype.getAnchorCorner = function() {
    -  var anchorCorner = this.rightAlign_ ?
    -      goog.positioning.Corner.BOTTOM_RIGHT :
    -      goog.positioning.Corner.BOTTOM_LEFT;
    -  if (this.topAlign_) {
    -    anchorCorner = goog.positioning.flipCornerVertical(anchorCorner);
    -  }
    -  return anchorCorner;
    -};
    -
    -
    -/**
    - * Repositions the auto complete popup relative to the location node, if it
    - * exists and the auto position has been set.
    - */
    -goog.ui.ac.Renderer.prototype.reposition = function() {
    -  if (this.target_ && this.reposition_) {
    -    var anchorElement = this.anchorElement_ || this.target_;
    -    var anchorCorner = this.getAnchorCorner();
    -
    -    var overflowMode = goog.positioning.Overflow.ADJUST_X_EXCEPT_OFFSCREEN;
    -    if (this.showScrollbarsIfTooLarge_) {
    -      // positionAtAnchor will set the height of this.element_ when it runs
    -      // (because of RESIZE_HEIGHT), and it will never increase it relative to
    -      // its current value when it runs again. But if the user scrolls their
    -      // page, then we might actually want a bigger height when the dropdown is
    -      // displayed next time. So we clear the height before calling
    -      // positionAtAnchor, so it is free to set the height as large as it
    -      // chooses.
    -      this.element_.style.height = '';
    -      overflowMode |= goog.positioning.Overflow.RESIZE_HEIGHT;
    -    }
    -
    -    goog.positioning.positionAtAnchor(
    -        anchorElement, anchorCorner,
    -        this.element_, goog.positioning.flipCornerVertical(anchorCorner),
    -        null, null, overflowMode);
    -
    -    if (this.topAlign_) {
    -      // This flickers, but is better than the alternative of positioning
    -      // in the wrong place and then moving.
    -      this.element_.style.visibility = 'visible';
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Sets whether the renderer should try to determine where to position the
    - * drop down.
    - * @param {boolean} auto Whether to autoposition the drop down.
    - */
    -goog.ui.ac.Renderer.prototype.setAutoPosition = function(auto) {
    -  this.reposition_ = auto;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the drop down will be autopositioned.
    - * @protected
    - */
    -goog.ui.ac.Renderer.prototype.getAutoPosition = function() {
    -  return this.reposition_;
    -};
    -
    -
    -/**
    - * @return {Element} The target element.
    - * @protected
    - */
    -goog.ui.ac.Renderer.prototype.getTarget = function() {
    -  return this.target_;
    -};
    -
    -
    -/**
    - * Disposes of the renderer and its associated HTML.
    - * @override
    - * @protected
    - */
    -goog.ui.ac.Renderer.prototype.disposeInternal = function() {
    -  if (this.element_) {
    -    goog.events.unlisten(this.element_, goog.events.EventType.CLICK,
    -        this.handleClick_, false, this);
    -    goog.events.unlisten(this.element_, goog.events.EventType.MOUSEDOWN,
    -        this.handleMouseDown_, false, this);
    -    goog.events.unlisten(this.element_, goog.events.EventType.MOUSEOVER,
    -        this.handleMouseOver_, false, this);
    -    this.dom_.removeNode(this.element_);
    -    this.element_ = null;
    -    this.visible_ = false;
    -  }
    -
    -  goog.dispose(this.animation_);
    -  this.parent_ = null;
    -
    -  goog.ui.ac.Renderer.base(this, 'disposeInternal');
    -};
    -
    -
    -/**
    - * Generic function that takes a row and renders a DOM structure for that row.
    - *
    - * Normally this will only be matching a maximum of 20 or so items.  Even with
    - * 40 rows, DOM this building is fine.
    - *
    - * @param {Object} row Object representing row.
    - * @param {string} token Token to highlight.
    - * @param {Node} node The node to render into.
    - * @private
    - */
    -goog.ui.ac.Renderer.prototype.renderRowContents_ =
    -    function(row, token, node) {
    -  goog.dom.setTextContent(node, row.data.toString());
    -};
    -
    -
    -/**
    - * Goes through a node and all of its child nodes, replacing HTML text that
    - * matches a token with <b>token</b>.
    - * The replacement will happen on the first match or all matches depending on
    - * this.highlightAllTokens_ value.
    - *
    - * @param {Node} node Node to match.
    - * @param {string|Array<string>} tokenOrArray Token to match or array of tokens
    - *     to match.  By default, only the first match will be highlighted.  If
    - *     highlightAllTokens is set, then all tokens appearing at the start of a
    - *     word, in whatever order and however many times, will be highlighted.
    - * @private
    - */
    -goog.ui.ac.Renderer.prototype.startHiliteMatchingText_ =
    -    function(node, tokenOrArray) {
    -  this.wasHighlightedAtLeastOnce_ = false;
    -  this.hiliteMatchingText_(node, tokenOrArray);
    -};
    -
    -
    -/**
    - * @param {Node} node Node to match.
    - * @param {string|Array<string>} tokenOrArray Token to match or array of tokens
    - *     to match.
    - * @private
    - */
    -goog.ui.ac.Renderer.prototype.hiliteMatchingText_ =
    -    function(node, tokenOrArray) {
    -  if (!this.highlightAllTokens_ && this.wasHighlightedAtLeastOnce_) {
    -    return;
    -  }
    -
    -  if (node.nodeType == goog.dom.NodeType.TEXT) {
    -    var rest = null;
    -    if (goog.isArray(tokenOrArray) &&
    -        tokenOrArray.length > 1 &&
    -        !this.highlightAllTokens_) {
    -      rest = goog.array.slice(tokenOrArray, 1);
    -    }
    -
    -    var token = this.getTokenRegExp_(tokenOrArray);
    -    if (token.length == 0) return;
    -
    -    var text = node.nodeValue;
    -
    -    // Create a regular expression to match a token at the beginning of a line
    -    // or preceeded by non-alpha-numeric characters. Note: token could have |
    -    // operators in it, so we need to parenthesise it before adding \b to it.
    -    // or preceeded by non-alpha-numeric characters
    -    //
    -    // NOTE(user): When using word matches, this used to have
    -    // a (^|\\W+) clause where it now has \\b but it caused various
    -    // browsers to hang on really long strings. The (^|\\W+) matcher was also
    -    // unnecessary, because \b already checks that the character before the
    -    // is a non-word character, and ^ matches the start of the line or following
    -    // a line terminator character, which is also \W. The regexp also used to
    -    // have a capturing match before the \\b, which would capture the
    -    // non-highlighted content, but that caused the regexp matching to run much
    -    // slower than the current version.
    -    var re = this.matchWordBoundary_ ?
    -        new RegExp('\\b(?:' + token + ')', 'gi') :
    -        new RegExp(token, 'gi');
    -    var textNodes = [];
    -    var lastIndex = 0;
    -
    -    // Find all matches
    -    // Note: text.split(re) has inconsistencies between IE and FF, so
    -    // manually recreated the logic
    -    var match = re.exec(text);
    -    var numMatches = 0;
    -    while (match) {
    -      numMatches++;
    -      textNodes.push(text.substring(lastIndex, match.index));
    -      textNodes.push(text.substring(match.index, re.lastIndex));
    -      lastIndex = re.lastIndex;
    -      match = re.exec(text);
    -    }
    -    textNodes.push(text.substring(lastIndex));
    -
    -    // Replace the tokens with bolded text.  Each pair of textNodes
    -    // (starting at index idx) includes a node of text before the bolded
    -    // token, and a node (at idx + 1) consisting of what should be
    -    // enclosed in bold tags.
    -    if (textNodes.length > 1) {
    -      var maxNumToBold = !this.highlightAllTokens_ ? 1 : numMatches;
    -      for (var i = 0; i < maxNumToBold; i++) {
    -        var idx = 2 * i;
    -
    -        node.nodeValue = textNodes[idx];
    -        var boldTag = this.dom_.createElement('b');
    -        boldTag.className = this.highlightedClassName;
    -        this.dom_.appendChild(boldTag,
    -            this.dom_.createTextNode(textNodes[idx + 1]));
    -        boldTag = node.parentNode.insertBefore(boldTag, node.nextSibling);
    -        node.parentNode.insertBefore(this.dom_.createTextNode(''),
    -            boldTag.nextSibling);
    -        node = boldTag.nextSibling;
    -      }
    -
    -      // Append the remaining text nodes to the end.
    -      var remainingTextNodes = goog.array.slice(textNodes, maxNumToBold * 2);
    -      node.nodeValue = remainingTextNodes.join('');
    -
    -      this.wasHighlightedAtLeastOnce_ = true;
    -    } else if (rest) {
    -      this.hiliteMatchingText_(node, rest);
    -    }
    -  } else {
    -    var child = node.firstChild;
    -    while (child) {
    -      var nextChild = child.nextSibling;
    -      this.hiliteMatchingText_(child, tokenOrArray);
    -      child = nextChild;
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Transforms a token into a string ready to be put into the regular expression
    - * in hiliteMatchingText_.
    - * @param {string|Array<string>} tokenOrArray The token or array to get the
    - *     regex string from.
    - * @return {string} The regex-ready token.
    - * @private
    - */
    -goog.ui.ac.Renderer.prototype.getTokenRegExp_ = function(tokenOrArray) {
    -  var token = '';
    -
    -  if (!tokenOrArray) {
    -    return token;
    -  }
    -
    -  if (goog.isArray(tokenOrArray)) {
    -    // Remove invalid tokens from the array, which may leave us with nothing.
    -    tokenOrArray = goog.array.filter(tokenOrArray, function(str) {
    -      return !goog.string.isEmptyOrWhitespace(goog.string.makeSafe(str));
    -    });
    -  }
    -
    -  // If highlighting all tokens, join them with '|' so the regular expression
    -  // will match on any of them.
    -  if (this.highlightAllTokens_) {
    -    if (goog.isArray(tokenOrArray)) {
    -      var tokenArray = goog.array.map(tokenOrArray, goog.string.regExpEscape);
    -      token = tokenArray.join('|');
    -    } else {
    -      // Remove excess whitespace from the string so bars will separate valid
    -      // tokens in the regular expression.
    -      token = goog.string.collapseWhitespace(tokenOrArray);
    -
    -      token = goog.string.regExpEscape(token);
    -      token = token.replace(/ /g, '|');
    -    }
    -  } else {
    -    // Not highlighting all matching tokens.  If tokenOrArray is a string, use
    -    // that as the token.  If it is an array, use the first element in the
    -    // array.
    -    // TODO(user): why is this this way?. We should match against all
    -    // tokens in the array, but only accept the first match.
    -    if (goog.isArray(tokenOrArray)) {
    -      token = tokenOrArray.length > 0 ?
    -          goog.string.regExpEscape(tokenOrArray[0]) : '';
    -    } else {
    -      // For the single-match string token, we refuse to match anything if
    -      // the string begins with a non-word character, as matches by definition
    -      // can only occur at the start of a word. (This also handles the
    -      // goog.string.isEmptyOrWhitespace(goog.string.makeSafe(tokenOrArray)) case.)
    -      if (!/^\W/.test(tokenOrArray)) {
    -        token = goog.string.regExpEscape(tokenOrArray);
    -      }
    -    }
    -  }
    -
    -  return token;
    -};
    -
    -
    -/**
    - * Render a row by creating a div and then calling row rendering callback or
    - * default row handler
    - *
    - * @param {Object} row Object representing row.
    - * @param {string} token Token to highlight.
    - * @return {!Element} An element with the rendered HTML.
    - */
    -goog.ui.ac.Renderer.prototype.renderRowHtml = function(row, token) {
    -  // Create and return the element.
    -  var elem = this.dom_.createDom('div', {
    -    className: this.rowClassName,
    -    id: goog.ui.IdGenerator.getInstance().getNextUniqueId()
    -  });
    -  goog.a11y.aria.setRole(elem, goog.a11y.aria.Role.OPTION);
    -  if (this.customRenderer_ && this.customRenderer_.renderRow) {
    -    this.customRenderer_.renderRow(row, token, elem);
    -  } else {
    -    this.renderRowContents_(row, token, elem);
    -  }
    -
    -  if (token && this.useStandardHighlighting_) {
    -    this.startHiliteMatchingText_(elem, token);
    -  }
    -
    -  goog.dom.classlist.add(elem, this.rowClassName);
    -  this.rowDivs_.push(elem);
    -  return elem;
    -};
    -
    -
    -/**
    - * Given an event target looks up through the parents till it finds a div.  Once
    - * found it will then look to see if that is one of the childnodes, if it is
    - * then the index is returned, otherwise -1 is returned.
    - * @param {Element} et HtmlElement.
    - * @return {number} Index corresponding to event target.
    - * @private
    - */
    -goog.ui.ac.Renderer.prototype.getRowFromEventTarget_ = function(et) {
    -  while (et && et != this.element_ &&
    -      !goog.dom.classlist.contains(et, this.rowClassName)) {
    -    et = /** @type {Element} */ (et.parentNode);
    -  }
    -  return et ? goog.array.indexOf(this.rowDivs_, et) : -1;
    -};
    -
    -
    -/**
    - * Handle the click events.  These are redirected to the AutoComplete object
    - * which then makes a callback to select the correct row.
    - * @param {goog.events.Event} e Browser event object.
    - * @private
    - */
    -goog.ui.ac.Renderer.prototype.handleClick_ = function(e) {
    -  var index = this.getRowFromEventTarget_(/** @type {Element} */ (e.target));
    -  if (index >= 0) {
    -    this.dispatchEvent(/** @lends {goog.events.Event.prototype} */ ({
    -      type: goog.ui.ac.AutoComplete.EventType.SELECT,
    -      row: this.rows_[index].id
    -    }));
    -  }
    -  e.stopPropagation();
    -};
    -
    -
    -/**
    - * Handle the mousedown event and prevent the AC from losing focus.
    - * @param {goog.events.Event} e Browser event object.
    - * @private
    - */
    -goog.ui.ac.Renderer.prototype.handleMouseDown_ = function(e) {
    -  e.stopPropagation();
    -  e.preventDefault();
    -};
    -
    -
    -/**
    - * Handle the mousing events.  These are redirected to the AutoComplete object
    - * which then makes a callback to set the correctly highlighted row.  This is
    - * because the AutoComplete can move the focus as well, and there is no sense
    - * duplicating the code
    - * @param {goog.events.Event} e Browser event object.
    - * @private
    - */
    -goog.ui.ac.Renderer.prototype.handleMouseOver_ = function(e) {
    -  var index = this.getRowFromEventTarget_(/** @type {Element} */ (e.target));
    -  if (index >= 0) {
    -    if ((goog.now() - this.startRenderingRows_) <
    -        goog.ui.ac.Renderer.DELAY_BEFORE_MOUSEOVER) {
    -      return;
    -    }
    -
    -    this.dispatchEvent({
    -      type: goog.ui.ac.AutoComplete.EventType.HILITE,
    -      row: this.rows_[index].id
    -    });
    -  }
    -};
    -
    -
    -
    -/**
    - * Class allowing different implementations to custom render the autocomplete.
    - * Extending classes should override the render function.
    - * @constructor
    - */
    -goog.ui.ac.Renderer.CustomRenderer = function() {
    -};
    -
    -
    -/**
    - * Renders the autocomplete box. May be set to null.
    - *
    - * Because of the type, this function cannot be documented with param JSDoc.
    - *
    - * The function expects the following parameters:
    - *
    - * renderer, goog.ui.ac.Renderer: The autocomplete renderer.
    - * element, Element: The main element that controls the rendered autocomplete.
    - * rows, Array: The current set of rows being displayed.
    - * token, string: The current token that has been entered. *
    - *
    - * @type {function(goog.ui.ac.Renderer, Element, Array, string)|
    - *        null|undefined}
    - */
    -goog.ui.ac.Renderer.CustomRenderer.prototype.render = function(
    -    renderer, element, rows, token) {
    -};
    -
    -
    -/**
    - * Generic function that takes a row and renders a DOM structure for that row.
    - * @param {Object} row Object representing row.
    - * @param {string} token Token to highlight.
    - * @param {Node} node The node to render into.
    - */
    -goog.ui.ac.Renderer.CustomRenderer.prototype.renderRow =
    -    function(row, token, node) {
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/ac/renderer_test.html b/src/database/third_party/closure-library/closure/goog/ui/ac/renderer_test.html
    deleted file mode 100644
    index 39149c08f66..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/ac/renderer_test.html
    +++ /dev/null
    @@ -1,38 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.ac.Renderer
    -  </title>
    -  <style type="text/css">
    -   #viewport {
    -  width: 400px;
    -  height: 200px;
    -  overflow: hidden; /* Suppress scroll bars to get consistent cross-browser resizing */
    -  position: relative;
    -}
    -  </style>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.ac.RendererTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="someElement">Click target</div>
    -  <div id="target">Target</div>
    -  <div id="viewport">
    -    Parent (viewport) element for some tests
    -    <div id="viewportTarget">Target for viewport tests</div>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/ac/renderer_test.js b/src/database/third_party/closure-library/closure/goog/ui/ac/renderer_test.js
    deleted file mode 100644
    index 03a40aac4aa..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/ac/renderer_test.js
    +++ /dev/null
    @@ -1,730 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.ac.RendererTest');
    -goog.setTestOnly('goog.ui.ac.RendererTest');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events');
    -goog.require('goog.fx.dom.FadeInAndShow');
    -goog.require('goog.fx.dom.FadeOutAndHide');
    -goog.require('goog.string');
    -goog.require('goog.style');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.ac.AutoComplete');
    -goog.require('goog.ui.ac.Renderer');
    -var renderer;
    -var rendRows = [];
    -var someElement;
    -var target;
    -var viewport;
    -var viewportTarget;
    -var propertyReplacer;
    -
    -function setUpPage() {
    -  someElement = goog.dom.getElement('someElement');
    -  target = goog.dom.getElement('target');
    -  viewport = goog.dom.getElement('viewport');
    -  viewportTarget = goog.dom.getElement('viewportTarget');
    -  propertyReplacer = new goog.testing.PropertyReplacer();
    -}
    -
    -
    -// One-time set up of rows formatted for the renderer.
    -var rows = [
    -  'Amanda Annie Anderson',
    -  'Frankie Manning',
    -  'Louis D Armstrong',
    -  // NOTE(user): sorry about this test input, but it has caused problems
    -  // in the past, so I want to make sure to test against it.
    -  'Foo Bar................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................',
    -  '<div><div>test</div></div>',
    -  '<div><div>test1</div><div>test2</div></div>',
    -  '<div>random test string<div>test1</div><div><div>test2</div><div>test3</div></div></div>'
    -];
    -
    -for (var i = 0; i < rows.length; i++) {
    -  rendRows.push({
    -    id: i,
    -    data: rows[i]
    -  });
    -}
    -
    -function setUp() {
    -  renderer = new goog.ui.ac.Renderer();
    -  renderer.rowDivs_ = [];
    -  renderer.target_ = target;
    -}
    -
    -function tearDown() {
    -  renderer.dispose();
    -  propertyReplacer.reset();
    -}
    -
    -function testBasicMatchingWithHtmlRow() {
    -  // '<div><div>test</div></div>'
    -  var row = rendRows[4];
    -  var token = 'te';
    -  enableHtmlRendering(renderer);
    -  var node = renderer.renderRowHtml(row, token);
    -  var boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 1);
    -}
    -
    -function testShouldMatchOnlyOncePerDefaultWithComplexHtmlStrings() {
    -  // '<div><div>test1</div><div>test2</div></div>'
    -  var row = rendRows[5];
    -  var token = 'te';
    -  enableHtmlRendering(renderer);
    -  var node = renderer.renderRowHtml(row, token);
    -  var boldTagElArray = node.getElementsByTagName('b');
    -
    -  // It should match and render highlighting for the first 'test1' and
    -  // stop here. This is the default behavior of the renderer.
    -  assertNumBoldTags(boldTagElArray, 1);
    -}
    -
    -function testShouldMatchMultipleTimesWithComplexHtmlStrings() {
    -  renderer.setHighlightAllTokens(true);
    -
    -  // '<div><div>test1</div><div>test2</div></div>'
    -  var row = rendRows[5];
    -  var token = 'te';
    -  enableHtmlRendering(renderer);
    -  var node = renderer.renderRowHtml(row, token);
    -  var boldTagElArray = node.getElementsByTagName('b');
    -
    -  // It should match and render highlighting for both 'test1' and 'test2'.
    -  assertNumBoldTags(boldTagElArray, 2);
    -
    -  // Try again with a more complex HTML string.
    -  // '<div>random test string<div>test1</div><div><div>test2</div><div>test3</div></div></div>'
    -  row = rendRows[6];
    -  node = renderer.renderRowHtml(row, token);
    -  boldTagElArray = node.getElementsByTagName('b');
    -  // It should match 'test', 'test1', 'test2' and 'test3' wherever they are in the
    -  // DOM tree.
    -  assertNumBoldTags(boldTagElArray, 4);
    -}
    -
    -function testBasicStringTokenHighlightingUsingUniversalMatching() {
    -  var row = rendRows[0];  // 'Amanda Annie Anderson'
    -  renderer.setMatchWordBoundary(false);
    -
    -  // Should highlight first match only.
    -  var token = 'A';
    -  var node = renderer.renderRowHtml(row, token);
    -  var boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 1);
    -  assertPreviousNodeText(boldTagElArray[0], '');
    -  assertHighlightedText(boldTagElArray[0], 'A');
    -  assertLastNodeText(node, 'manda Annie Anderson');
    -
    -  // Match should be case insensitive, and should match tokens in the
    -  // middle of words if useWordMatching is turned off ("an" in Amanda).
    -  var token = 'an';
    -  var node = renderer.renderRowHtml(row, token);
    -  var boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 1);
    -  assertPreviousNodeText(boldTagElArray[0], 'Am');
    -  assertHighlightedText(boldTagElArray[0], 'an');
    -  assertLastNodeText(node, 'da Annie Anderson');
    -
    -  // Should only match on non-empty strings.
    -  token = '';
    -  node = renderer.renderRowHtml(row, token);
    -  boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 0);
    -  assertLastNodeText(node, 'Amanda Annie Anderson');
    -
    -  // Should not match leading whitespace.
    -  token = ' an';
    -  node = renderer.renderRowHtml(row, token);
    -  boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 0);
    -  assertLastNodeText(node, 'Amanda Annie Anderson');
    -}
    -
    -function testBasicStringTokenHighlighting() {
    -  var row = rendRows[0];  // 'Amanda Annie Anderson'
    -
    -  // Should highlight first match only.
    -  var token = 'A';
    -  var node = renderer.renderRowHtml(row, token);
    -  var boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 1);
    -  assertPreviousNodeText(boldTagElArray[0], '');
    -  assertHighlightedText(boldTagElArray[0], 'A');
    -  assertLastNodeText(node, 'manda Annie Anderson');
    -
    -  // Should only match on non-empty strings.
    -  token = '';
    -  node = renderer.renderRowHtml(row, token);
    -  boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 0);
    -  assertLastNodeText(node, 'Amanda Annie Anderson');
    -
    -  // Match should be case insensitive, and should not match tokens in the
    -  // middle of words ("an" in Amanda).
    -  token = 'an';
    -  node = renderer.renderRowHtml(row, token);
    -  boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 1);
    -  assertPreviousNodeText(boldTagElArray[0], 'Amanda ');
    -  assertHighlightedText(boldTagElArray[0], 'An');
    -  assertLastNodeText(node, 'nie Anderson');
    -
    -  // Should not match whitespace.
    -  token = ' ';
    -  node = renderer.renderRowHtml(row, token);
    -  boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 0);
    -  assertLastNodeText(node, 'Amanda Annie Anderson');
    -
    -  // Should not match leading whitespace since all matches are at the start of
    -  // word boundaries.
    -  token = ' an';
    -  node = renderer.renderRowHtml(row, token);
    -  boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 0);
    -  assertLastNodeText(node, 'Amanda Annie Anderson');
    -
    -  // Should match trailing whitespace.
    -  token = 'annie ';
    -  node = renderer.renderRowHtml(row, token);
    -  boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 1);
    -  assertPreviousNodeText(boldTagElArray[0], 'Amanda ');
    -  assertHighlightedText(boldTagElArray[0], 'Annie ');
    -  assertLastNodeText(node, 'Anderson');
    -
    -  // Should match across whitespace.
    -  row = rendRows[2]; // 'Louis D Armstrong'
    -  token = 'd a';
    -  node = renderer.renderRowHtml(row, token);
    -  boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 1);
    -  assertPreviousNodeText(boldTagElArray[0], 'Louis ');
    -  assertHighlightedText(boldTagElArray[0], 'D A');
    -  assertLastNodeText(node, 'rmstrong');
    -
    -  // Should match the last token.
    -  token = 'aRmStRoNg';
    -  node = renderer.renderRowHtml(row, token);
    -  boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 1);
    -  assertPreviousNodeText(boldTagElArray[0], 'Louis D ');
    -  assertHighlightedText(boldTagElArray[0], 'Armstrong');
    -  assertLastNodeText(node, '');
    -}
    -
    -// The name of this function is fortuitous, in that it gets tested
    -// last on FF. The lazy regexp on FF is particularly slow, and causes
    -// the test to take a long time, and sometimes time out when run on forge
    -// because it triggers the test runner to go back to the event loop...
    -function testPathologicalInput() {
    -  // Should not hang on bizarrely long strings
    -  var row = rendRows[3]; // pathological row
    -  var token = 'foo';
    -  var node = renderer.renderRowHtml(row, token);
    -  var boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 1);
    -  assertHighlightedText(boldTagElArray[0], 'Foo');
    -  assert(goog.string.startsWith(
    -      boldTagElArray[0].nextSibling.nodeValue, ' Bar...'));
    -}
    -
    -function testBasicArrayTokenHighlighting() {
    -  var row = rendRows[1];  // 'Frankie Manning'
    -
    -  // Only the first match in the array should be highlighted.
    -  var token = ['f', 'm'];
    -  var node = renderer.renderRowHtml(row, token);
    -  var boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 1);
    -  assertPreviousNodeText(boldTagElArray[0], '');
    -  assertHighlightedText(boldTagElArray[0], 'F');
    -  assertLastNodeText(node, 'rankie Manning');
    -
    -  // Only the first match in the array should be highlighted.
    -  token = ['m', 'f'];
    -  node = renderer.renderRowHtml(row, token);
    -  boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 1);
    -  assertPreviousNodeText(boldTagElArray[0], 'Frankie ');
    -  assertHighlightedText(boldTagElArray[0], 'M');
    -  assertLastNodeText(node, 'anning');
    -
    -  // Skip tokens that do not match.
    -  token = ['asdf', 'f'];
    -  node = renderer.renderRowHtml(row, token);
    -  boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 1);
    -  assertPreviousNodeText(boldTagElArray[0], '');
    -  assertHighlightedText(boldTagElArray[0], 'F');
    -  assertLastNodeText(node, 'rankie Manning');
    -
    -  // Highlight nothing if no tokens match.
    -  token = ['Foo', 'bar', 'baz'];
    -  node = renderer.renderRowHtml(row, token);
    -  boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 0);
    -  assertLastNodeText(node, 'Frankie Manning');
    -
    -  // Empty array should not match.
    -  token = [];
    -  node = renderer.renderRowHtml(row, token);
    -  boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 0);
    -  assertLastNodeText(node, 'Frankie Manning');
    -
    -  // Empty string in array should not match.
    -  token = [''];
    -  node = renderer.renderRowHtml(row, token);
    -  boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 0);
    -  assertLastNodeText(node, 'Frankie Manning');
    -
    -  // Whitespace in array should not match.
    -  token = [' '];
    -  node = renderer.renderRowHtml(row, token);
    -  boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 0);
    -  assertLastNodeText(node, 'Frankie Manning');
    -
    -  // Whitespace entries in array should not match.
    -  token = [' ', 'man'];
    -  node = renderer.renderRowHtml(row, token);
    -  boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 1);
    -  assertPreviousNodeText(boldTagElArray[0], 'Frankie ');
    -  assertHighlightedText(boldTagElArray[0], 'Man');
    -  assertLastNodeText(node, 'ning');
    -
    -  // Whitespace in array entry should match as a whole token.
    -  row = rendRows[2]; // 'Louis D Armstrong'
    -  token = ['d arm', 'lou'];
    -  node = renderer.renderRowHtml(row, token);
    -  boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 1);
    -  assertPreviousNodeText(boldTagElArray[0], 'Louis ');
    -  assertHighlightedText(boldTagElArray[0], 'D Arm');
    -  assertLastNodeText(node, 'strong');
    -}
    -
    -function testHighlightAllTokensSingleTokenHighlighting() {
    -  renderer.setHighlightAllTokens(true);
    -  var row = rendRows[0];  // 'Amanda Annie Anderson'
    -
    -  // All matches at the start of the word should be highlighted when
    -  // highlightAllTokens is set.
    -  var token = 'a';
    -  var node = renderer.renderRowHtml(row, token);
    -  var boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 3);
    -  assertPreviousNodeText(boldTagElArray[0], '');
    -  assertHighlightedText(boldTagElArray[0], 'A');
    -  assertPreviousNodeText(boldTagElArray[1], 'manda ');
    -  assertHighlightedText(boldTagElArray[1], 'A');
    -  assertPreviousNodeText(boldTagElArray[2], 'nnie ');
    -  assertHighlightedText(boldTagElArray[2], 'A');
    -  assertLastNodeText(node, 'nderson');
    -
    -  // Should not match on empty string.
    -  token = '';
    -  node = renderer.renderRowHtml(row, token);
    -  boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 0);
    -  assertLastNodeText(node, 'Amanda Annie Anderson');
    -
    -  // Match should be case insensitive.
    -  token = 'AN';
    -  node = renderer.renderRowHtml(row, token);
    -  boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 2);
    -  assertPreviousNodeText(boldTagElArray[0], 'Amanda ');
    -  assertHighlightedText(boldTagElArray[0], 'An');
    -  assertPreviousNodeText(boldTagElArray[1], 'nie ');
    -  assertHighlightedText(boldTagElArray[1], 'An');
    -  assertLastNodeText(node, 'derson');
    -
    -  // Should not match on whitespace.
    -  token = ' ';
    -  node = renderer.renderRowHtml(row, token);
    -  boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 0);
    -  assertLastNodeText(node, 'Amanda Annie Anderson');
    -
    -  // When highlighting all tokens, should match despite leading whitespace.
    -  token = '  am';
    -  node = renderer.renderRowHtml(row, token);
    -  boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 1);
    -  assertPreviousNodeText(boldTagElArray[0], '');
    -  assertHighlightedText(boldTagElArray[0], 'Am');
    -  assertLastNodeText(node, 'anda Annie Anderson');
    -
    -  // Should match with trailing whitepsace.
    -  token = 'ann   ';
    -  node = renderer.renderRowHtml(row, token);
    -  boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 1);
    -  assertPreviousNodeText(boldTagElArray[0], 'Amanda ');
    -  assertHighlightedText(boldTagElArray[0], 'Ann');
    -  assertLastNodeText(node, 'ie Anderson');
    -}
    -
    -function testHighlightAllTokensMultipleStringTokenHighlighting() {
    -  renderer.setHighlightAllTokens(true);
    -  var row = rendRows[1];  // 'Frankie Manning'
    -
    -  // Each individual space-separated token should match.
    -  var token = 'm F';
    -  var node = renderer.renderRowHtml(row, token);
    -  var boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 2);
    -  assertPreviousNodeText(boldTagElArray[0], '');
    -  assertHighlightedText(boldTagElArray[0], 'F');
    -  assertPreviousNodeText(boldTagElArray[1], 'rankie ');
    -  assertHighlightedText(boldTagElArray[1], 'M');
    -  assertLastNodeText(node, 'anning');
    -}
    -
    -function testHighlightAllTokensArrayTokenHighlighting() {
    -  renderer.setHighlightAllTokens(true);
    -  var row = rendRows[0];  // 'Amanda Annie Anderson'
    -
    -  // All tokens in the array should match.
    -  var token = ['AM', 'AN'];
    -  var node = renderer.renderRowHtml(row, token);
    -  var boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 3);
    -  assertPreviousNodeText(boldTagElArray[0], '');
    -  assertHighlightedText(boldTagElArray[0], 'Am');
    -  assertPreviousNodeText(boldTagElArray[1], 'anda ');
    -  assertHighlightedText(boldTagElArray[1], 'An');
    -  assertPreviousNodeText(boldTagElArray[2], 'nie ');
    -  assertHighlightedText(boldTagElArray[2], 'An');
    -  assertLastNodeText(node, 'derson');
    -
    -  // Empty array should not match.
    -  token = [];
    -  node = renderer.renderRowHtml(row, token);
    -  boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 0);
    -  assertLastNodeText(node, 'Amanda Annie Anderson');
    -
    -  // Empty string in array should not match.
    -  token = [''];
    -  node = renderer.renderRowHtml(row, token);
    -  boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 0);
    -  assertLastNodeText(node, 'Amanda Annie Anderson');
    -
    -  // Whitespace in array should not match.
    -  token = [' '];
    -  node = renderer.renderRowHtml(row, token);
    -  boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 0);
    -  assertLastNodeText(node, 'Amanda Annie Anderson');
    -
    -  // Empty string entries in array should not match.
    -  token = ['', 'Ann'];
    -  node = renderer.renderRowHtml(row, token);
    -  boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 1);
    -  assertPreviousNodeText(boldTagElArray[0], 'Amanda ');
    -  assertHighlightedText(boldTagElArray[0], 'Ann');
    -  assertLastNodeText(node, 'ie Anderson');
    -
    -  // Whitespace entries in array should not match.
    -  token = [' ', 'And'];
    -  node = renderer.renderRowHtml(row, token);
    -  boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 1);
    -  assertPreviousNodeText(boldTagElArray[0], 'Amanda Annie ');
    -  assertHighlightedText(boldTagElArray[0], 'And');
    -  assertLastNodeText(node, 'erson');
    -
    -  // Whitespace in array entry should match as a whole token.
    -  token = ['annie a', 'Am'];
    -  node = renderer.renderRowHtml(row, token);
    -  var boldTagElArray = node.getElementsByTagName('b');
    -  assertNumBoldTags(boldTagElArray, 2);
    -  assertPreviousNodeText(boldTagElArray[0], '');
    -  assertHighlightedText(boldTagElArray[0], 'Am');
    -  assertPreviousNodeText(boldTagElArray[1], 'anda ');
    -  assertHighlightedText(boldTagElArray[1], 'Annie A');
    -  assertLastNodeText(node, 'nderson');
    -}
    -
    -function testMenuFadeDuration() {
    -  var hideCalled = false;
    -  var hideAnimCalled = false;
    -  var showCalled = false;
    -  var showAnimCalled = false;
    -
    -  propertyReplacer.set(goog.style, 'setElementShown', function(el, state) {
    -    if (state) {
    -      showCalled = true;
    -    } else {
    -      hideCalled = true;
    -    }
    -  });
    -
    -  propertyReplacer.set(goog.fx.dom.FadeInAndShow.prototype, 'play',
    -      function() {
    -        showAnimCalled = true;
    -      });
    -
    -  propertyReplacer.set(goog.fx.dom.FadeOutAndHide.prototype, 'play',
    -      function() {
    -        hideAnimCalled = true;
    -      });
    -
    -  // Default behavior does show/hide but not animations.
    -
    -  renderer.show();
    -  assertTrue(showCalled);
    -  assertFalse(showAnimCalled);
    -
    -  renderer.dismiss();
    -  assertTrue(hideCalled);
    -  assertFalse(hideAnimCalled);
    -
    -  // But animations can be turned on.
    -
    -  showCalled = false;
    -  hideCalled = false;
    -  renderer.setMenuFadeDuration(100);
    -
    -  renderer.show();
    -  assertFalse(showCalled);
    -  assertTrue(showAnimCalled);
    -
    -  renderer.dismiss();
    -  assertFalse(hideCalled);
    -  assertTrue(hideAnimCalled);
    -}
    -
    -function testAriaTags() {
    -  renderer.maybeCreateElement_();
    -
    -  assertNotNull(target);
    -  assertEvaluatesToFalse('The role should be empty.',
    -      goog.a11y.aria.getRole(target));
    -  assertEquals('',
    -      goog.a11y.aria.getState(target,
    -          goog.a11y.aria.State.AUTOCOMPLETE));
    -  assertEquals('',
    -      goog.a11y.aria.getState(target,
    -          goog.a11y.aria.State.HASPOPUP));
    -
    -  renderer.show();
    -  assertEquals(goog.a11y.aria.Role.COMBOBOX, goog.a11y.aria.getRole(
    -      target));
    -  assertEquals('list',
    -      goog.a11y.aria.getState(target,
    -          goog.a11y.aria.State.AUTOCOMPLETE));
    -  assertEquals('true',
    -      goog.a11y.aria.getState(target,
    -          goog.a11y.aria.State.HASPOPUP));
    -
    -  renderer.dismiss();
    -  assertEquals(goog.a11y.aria.Role.COMBOBOX, goog.a11y.aria.getRole(
    -      target));
    -  assertEquals('list',
    -      goog.a11y.aria.getState(target,
    -          goog.a11y.aria.State.AUTOCOMPLETE));
    -  assertEquals('false',
    -      goog.a11y.aria.getState(target,
    -          goog.a11y.aria.State.HASPOPUP));
    -}
    -
    -function testHiliteRowWithDefaultRenderer() {
    -  renderer.renderRows(rendRows, '');
    -  renderer.hiliteRow(2);
    -  assertEquals(2, renderer.hilitedRow_);
    -  assertTrue(goog.dom.classlist.contains(
    -      renderer.rowDivs_[2], renderer.activeClassName));
    -}
    -
    -function testHiliteRowWithCustomRenderer() {
    -  goog.dispose(renderer);
    -
    -  // Use a custom renderer that doesn't put the result divs as direct children
    -  // of this.element_.
    -  var customRenderer = {
    -    render: function(renderer, element, rows, token) {
    -      // Put all of the results into a results holder div that is a child of
    -      // this.element_.
    -      var resultsHolder = goog.dom.createDom('div');
    -      goog.dom.appendChild(element, resultsHolder);
    -      for (var i = 0, row; row = rows[i]; ++i) {
    -        var node = renderer.renderRowHtml(row, token);
    -        goog.dom.appendChild(resultsHolder, node);
    -      }
    -    }
    -  };
    -  renderer = new goog.ui.ac.Renderer(null, customRenderer);
    -
    -  // Make sure we can still highlight the row at position 2 even though
    -  // this.element_.childNodes contains only a single child.
    -  renderer.renderRows(rendRows, '');
    -  renderer.hiliteRow(2);
    -  assertEquals(2, renderer.hilitedRow_);
    -  assertTrue(goog.dom.classlist.contains(
    -      renderer.rowDivs_[2], renderer.activeClassName));
    -}
    -
    -function testReposition() {
    -  renderer.renderRows(rendRows, '', target);
    -  var el = renderer.getElement();
    -  el.style.position = 'absolute';
    -  el.style.width = '100px';
    -
    -  renderer.setAutoPosition(true);
    -  renderer.redraw();
    -
    -  var rendererOffset = goog.style.getPageOffset(renderer.getElement());
    -  var rendererSize = goog.style.getSize(renderer.getElement());
    -  var targetOffset = goog.style.getPageOffset(target);
    -  var targetSize = goog.style.getSize(target);
    -
    -  assertEquals(0 + targetOffset.x, rendererOffset.x);
    -  assertRoughlyEquals(
    -      targetOffset.y + targetSize.height, rendererOffset.y, 1);
    -}
    -
    -function testRepositionWithRightAlign() {
    -  renderer.renderRows(rendRows, '', target);
    -  var el = renderer.getElement();
    -  el.style.position = 'absolute';
    -  el.style.width = '150px';
    -
    -  renderer.setAutoPosition(true);
    -  renderer.setRightAlign(true);
    -  renderer.redraw();
    -
    -  var rendererOffset = goog.style.getPageOffset(renderer.getElement());
    -  var rendererSize = goog.style.getSize(renderer.getElement());
    -  var targetOffset = goog.style.getPageOffset(target);
    -  var targetSize = goog.style.getSize(target);
    -
    -  assertRoughlyEquals(
    -      targetOffset.x + targetSize.width,
    -      rendererOffset.x + rendererSize.width,
    -      1);
    -  assertRoughlyEquals(
    -      targetOffset.y + targetSize.height, rendererOffset.y, 1);
    -}
    -
    -function testRepositionResizeHeight() {
    -  renderer = new goog.ui.ac.Renderer(viewport);
    -  // Render the first 4 rows from test set.
    -  renderer.renderRows(rendRows.slice(0, 4), '', viewportTarget);
    -  renderer.setAutoPosition(true);
    -  renderer.setShowScrollbarsIfTooLarge(true);
    -
    -  // Stick a huge row in the dropdown element, to make sure it won't fit in the viewport.
    -  var hugeRow = goog.dom.createDom('div', {style: 'height:1000px'});
    -  goog.dom.appendChild(renderer.getElement(), hugeRow);
    -
    -  renderer.reposition();
    -
    -  var rendererOffset = goog.style.getPageOffset(renderer.getElement());
    -  var rendererSize = goog.style.getSize(renderer.getElement());
    -  var viewportOffset = goog.style.getPageOffset(viewport);
    -  var viewportSize = goog.style.getSize(viewport);
    -
    -  assertRoughlyEquals(
    -      viewportOffset.y + viewportSize.height,
    -      rendererSize.height + rendererOffset.y,
    -      1);
    -
    -  // Remove the huge row, and make sure that the dropdown element gets shrunk.
    -  renderer.getElement().removeChild(hugeRow);
    -  renderer.reposition();
    -
    -  rendererOffset = goog.style.getPageOffset(renderer.getElement());
    -  rendererSize = goog.style.getSize(renderer.getElement());
    -  viewportOffset = goog.style.getPageOffset(viewport);
    -  viewportSize = goog.style.getSize(viewport);
    -
    -  assertTrue((rendererSize.height + rendererOffset.y) < (viewportOffset.y + viewportSize.height));
    -}
    -
    -function testHiliteEvent() {
    -  renderer.renderRows(rendRows, '');
    -
    -  var hiliteEventFired = false;
    -  goog.events.listenOnce(renderer,
    -      goog.ui.ac.AutoComplete.EventType.ROW_HILITE,
    -      function(e) {
    -        hiliteEventFired = true;
    -        assertEquals(e.row, rendRows[1].data);
    -      });
    -  renderer.hiliteRow(1);
    -  assertTrue(hiliteEventFired);
    -
    -  hiliteEventFired = false;
    -  goog.events.listenOnce(renderer,
    -      goog.ui.ac.AutoComplete.EventType.ROW_HILITE,
    -      function(e) {
    -        hiliteEventFired = true;
    -        assertNull(e.row);
    -      });
    -  renderer.hiliteRow(rendRows.length); // i.e. out of bounds.
    -  assertTrue(hiliteEventFired);
    -}
    -
    -// ------- Helper functions -------
    -
    -// The default rowRenderer will escape any HTML in the row content.
    -// Activating HTML rendering will allow HTML strings to be rendered to DOM
    -// instead of being escaped.
    -function enableHtmlRendering(renderer) {
    -  renderer.customRenderer_ = {
    -    renderRow: function(row, token, node) {
    -      node.innerHTML = row.data.toString();
    -    }
    -  };
    -}
    -
    -function assertNumBoldTags(boldTagElArray, expectedNum) {
    -  assertEquals('Incorrect number of bold tags', expectedNum,
    -      boldTagElArray.length);
    -}
    -
    -function assertPreviousNodeText(boldTag, expectedText) {
    -  var prevNode = boldTag.previousSibling;
    -  assertEquals('Expected text before the token does not match', expectedText,
    -      prevNode.nodeValue);
    -}
    -
    -function assertHighlightedText(boldTag, expectedHighlightedText) {
    -  assertEquals('Incorrect text bolded', expectedHighlightedText,
    -      boldTag.innerHTML);
    -}
    -
    -function assertLastNodeText(node, expectedText) {
    -  var lastNode = node.lastChild;
    -  assertEquals('Incorrect text in the last node', expectedText,
    -      lastNode.nodeValue);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/ac/renderoptions.js b/src/database/third_party/closure-library/closure/goog/ui/ac/renderoptions.js
    deleted file mode 100644
    index 2f99b2b16ff..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/ac/renderoptions.js
    +++ /dev/null
    @@ -1,80 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Options for rendering matches.
    - *
    - */
    -
    -goog.provide('goog.ui.ac.RenderOptions');
    -
    -
    -
    -/**
    - * A simple class that contains options for rendering a set of autocomplete
    - * matches.  Used as an optional argument in the callback from the matcher.
    - * @constructor
    - */
    -goog.ui.ac.RenderOptions = function() {
    -};
    -
    -
    -/**
    - * Whether the current highlighting is to be preserved when displaying the new
    - * set of matches.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.ac.RenderOptions.prototype.preserveHilited_ = false;
    -
    -
    -/**
    - * Whether the first match is to be highlighted.  When undefined the autoHilite
    - * flag of the autocomplete is used.
    - * @type {boolean|undefined}
    - * @private
    - */
    -goog.ui.ac.RenderOptions.prototype.autoHilite_;
    -
    -
    -/**
    - * @param {boolean} flag The new value for the preserveHilited_ flag.
    - */
    -goog.ui.ac.RenderOptions.prototype.setPreserveHilited = function(flag) {
    -  this.preserveHilited_ = flag;
    -};
    -
    -
    -/**
    - * @return {boolean} The value of the preserveHilited_ flag.
    - */
    -goog.ui.ac.RenderOptions.prototype.getPreserveHilited = function() {
    -  return this.preserveHilited_;
    -};
    -
    -
    -/**
    - * @param {boolean} flag The new value for the autoHilite_ flag.
    - */
    -goog.ui.ac.RenderOptions.prototype.setAutoHilite = function(flag) {
    -  this.autoHilite_ = flag;
    -};
    -
    -
    -/**
    - * @return {boolean|undefined} The value of the autoHilite_ flag.
    - */
    -goog.ui.ac.RenderOptions.prototype.getAutoHilite = function() {
    -  return this.autoHilite_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/ac/richinputhandler.js b/src/database/third_party/closure-library/closure/goog/ui/ac/richinputhandler.js
    deleted file mode 100644
    index 4e8faee6347..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/ac/richinputhandler.js
    +++ /dev/null
    @@ -1,58 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Class for managing the interactions between a rich autocomplete
    - * object and a text-input or textarea.
    - *
    - */
    -
    -goog.provide('goog.ui.ac.RichInputHandler');
    -
    -goog.require('goog.ui.ac.InputHandler');
    -
    -
    -
    -/**
    - * Class for managing the interaction between an autocomplete object and a
    - * text-input or textarea.
    - * @param {?string=} opt_separators Seperators to split multiple entries.
    - * @param {?string=} opt_literals Characters used to delimit text literals.
    - * @param {?boolean=} opt_multi Whether to allow multiple entries
    - *     (Default: true).
    - * @param {?number=} opt_throttleTime Number of milliseconds to throttle
    - *     keyevents with (Default: 150).
    - * @constructor
    - * @extends {goog.ui.ac.InputHandler}
    - */
    -goog.ui.ac.RichInputHandler = function(opt_separators, opt_literals,
    -    opt_multi, opt_throttleTime) {
    -  goog.ui.ac.InputHandler.call(this, opt_separators, opt_literals,
    -      opt_multi, opt_throttleTime);
    -};
    -goog.inherits(goog.ui.ac.RichInputHandler, goog.ui.ac.InputHandler);
    -
    -
    -/**
    - * Selects the given rich row.  The row's select(target) method is called.
    - * @param {Object} row The row to select.
    - * @return {boolean} Whether to suppress the update event.
    - * @override
    - */
    -goog.ui.ac.RichInputHandler.prototype.selectRow = function(row) {
    -  var suppressUpdate = goog.ui.ac.RichInputHandler.superClass_
    -      .selectRow.call(this, row);
    -  row.select(this.ac_.getTarget());
    -  return suppressUpdate;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/ac/richremote.js b/src/database/third_party/closure-library/closure/goog/ui/ac/richremote.js
    deleted file mode 100644
    index 5b5f9023432..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/ac/richremote.js
    +++ /dev/null
    @@ -1,113 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Factory class to create a rich autocomplete that will match
    - * from an array of data provided via ajax.  The server returns a complex data
    - * structure that is used with client-side javascript functions to render the
    - * results.
    - *
    - * The server sends a list of the form:
    - *   [["type1", {...}, {...}, ...], ["type2", {...}, {...}, ...], ...]
    - * The first element of each sublist is a string designating the type of the
    - * hashes in the sublist, each of which represents one match.  The type string
    - * must be the name of a function(item) which converts the hash into a rich
    - * row that contains both a render(node, token) and a select(target) method.
    - * The render method is called by the renderer when rendering the rich row,
    - * and the select method is called by the RichInputHandler when the rich row is
    - * selected.
    - *
    - * @see ../../demos/autocompleterichremote.html
    - */
    -
    -goog.provide('goog.ui.ac.RichRemote');
    -
    -goog.require('goog.ui.ac.AutoComplete');
    -goog.require('goog.ui.ac.Remote');
    -goog.require('goog.ui.ac.Renderer');
    -goog.require('goog.ui.ac.RichInputHandler');
    -goog.require('goog.ui.ac.RichRemoteArrayMatcher');
    -
    -
    -
    -/**
    - * Factory class to create a rich autocomplete widget that autocompletes an
    - * inputbox or textarea from data provided via ajax.  The server returns a
    - * complex data structure that is used with client-side javascript functions to
    - * render the results.
    - *
    - * This class makes use of goog.html.legacyconversions and provides no
    - * HTML-type-safe alternative. As such, it is not compatible with
    - * code that sets goog.html.legacyconversions.ALLOW_LEGACY_CONVERSIONS to
    - * false.
    - *
    - * @param {string} url The Uri which generates the auto complete matches.
    - * @param {Element} input Input element or text area.
    - * @param {boolean=} opt_multi Whether to allow multiple entries; defaults
    - *     to false.
    - * @param {boolean=} opt_useSimilar Whether to use similar matches; e.g.
    - *     "gost" => "ghost".
    - * @constructor
    - * @extends {goog.ui.ac.Remote}
    - */
    -goog.ui.ac.RichRemote = function(url, input, opt_multi, opt_useSimilar) {
    -  // Create a custom renderer that renders rich rows.  The renderer calls
    -  // row.render(node, token) for each row.
    -  var customRenderer = {};
    -  customRenderer.renderRow = function(row, token, node) {
    -    return row.data.render(node, token);
    -  };
    -
    -  /**
    -   * A standard renderer that uses a custom row renderer to display the
    -   * rich rows generated by this autocomplete widget.
    -   * @type {goog.ui.ac.Renderer}
    -   * @private
    -   */
    -  var renderer = new goog.ui.ac.Renderer(null, customRenderer);
    -  this.renderer_ = renderer;
    -
    -  /**
    -   * A remote matcher that parses rich results returned by the server.
    -   * @type {goog.ui.ac.RichRemoteArrayMatcher}
    -   * @private
    -   */
    -  var matcher = new goog.ui.ac.RichRemoteArrayMatcher(url,
    -      !opt_useSimilar);
    -  this.matcher_ = matcher;
    -
    -  /**
    -   * An input handler that calls select on a row when it is selected.
    -   * @type {goog.ui.ac.RichInputHandler}
    -   * @private
    -   */
    -  var inputhandler = new goog.ui.ac.RichInputHandler(null, null,
    -      !!opt_multi, 300);
    -
    -  // Create the widget and connect it to the input handler.
    -  goog.ui.ac.AutoComplete.call(this, matcher, renderer, inputhandler);
    -  inputhandler.attachAutoComplete(this);
    -  inputhandler.attachInputs(input);
    -};
    -goog.inherits(goog.ui.ac.RichRemote, goog.ui.ac.Remote);
    -
    -
    -/**
    - * Set the filter that is called before the array matches are returned.
    - * @param {Function} rowFilter A function(rows) that returns an array of rows as
    - *     a subset of the rows input array.
    - */
    -goog.ui.ac.RichRemote.prototype.setRowFilter = function(rowFilter) {
    -  this.matcher_.setRowFilter(rowFilter);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/ac/richremotearraymatcher.js b/src/database/third_party/closure-library/closure/goog/ui/ac/richremotearraymatcher.js
    deleted file mode 100644
    index b48d90c35a9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/ac/richremotearraymatcher.js
    +++ /dev/null
    @@ -1,144 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Class that retrieves rich autocomplete matches, represented as
    - * a structured list of lists, via an ajax call.  The first element of each
    - * sublist is the name of a client-side javascript function that converts the
    - * remaining sublist elements into rich rows.
    - *
    - */
    -
    -goog.provide('goog.ui.ac.RichRemoteArrayMatcher');
    -
    -goog.require('goog.dom.safe');
    -goog.require('goog.html.legacyconversions');
    -goog.require('goog.json');
    -goog.require('goog.ui.ac.RemoteArrayMatcher');
    -
    -
    -
    -/**
    - * An array matcher that requests rich matches via ajax and converts them into
    - * rich rows.
    - *
    - * This class makes use of goog.html.legacyconversions and provides no
    - * HTML-type-safe alternative. As such, it is not compatible with
    - * code that sets goog.html.legacyconversions.ALLOW_LEGACY_CONVERSIONS to
    - * false.
    - *
    - * @param {string} url The Uri which generates the auto complete matches.  The
    - *     search term is passed to the server as the 'token' query param.
    - * @param {boolean=} opt_noSimilar If true, request that the server does not do
    - *     similarity matches for the input token against the dictionary.
    - *     The value is sent to the server as the 'use_similar' query param which is
    - *     either "1" (opt_noSimilar==false) or "0" (opt_noSimilar==true).
    - * @constructor
    - * @extends {goog.ui.ac.RemoteArrayMatcher}
    - */
    -goog.ui.ac.RichRemoteArrayMatcher = function(url, opt_noSimilar) {
    -  // requestMatchingRows() sets innerHTML directly from unsanitized/unescaped
    -  // server-data, with no form of type-safety. Because requestMatchingRows is
    -  // used polymorphically (for example, from
    -  // goog.ui.ac.AutoComplete.prototype.setToken) it is undesirable to have
    -  // Conformance legacyconversions rule for it. Doing so would cause the
    -  // respective check rule fire from all such places which polymorphically
    -  // call requestMatchingRows(); such calls are safe as long as they're not to
    -  // RichRemoteArrayMatcher.
    -  goog.html.legacyconversions.throwIfConversionsDisallowed();
    -  goog.ui.ac.RemoteArrayMatcher.call(this, url, opt_noSimilar);
    -
    -  /**
    -   * A function(rows) that is called before the array matches are returned.
    -   * It runs client-side and filters the results given by the server before
    -   * being rendered by the client.
    -   * @type {Function}
    -   * @private
    -   */
    -  this.rowFilter_ = null;
    -
    -};
    -goog.inherits(goog.ui.ac.RichRemoteArrayMatcher, goog.ui.ac.RemoteArrayMatcher);
    -
    -
    -/**
    - * Set the filter that is called before the array matches are returned.
    - * @param {Function} rowFilter A function(rows) that returns an array of rows as
    - *     a subset of the rows input array.
    - */
    -goog.ui.ac.RichRemoteArrayMatcher.prototype.setRowFilter = function(rowFilter) {
    -  this.rowFilter_ = rowFilter;
    -};
    -
    -
    -/**
    - * Retrieve a set of matching rows from the server via ajax and convert them
    - * into rich rows.
    - * @param {string} token The text that should be matched; passed to the server
    - *     as the 'token' query param.
    - * @param {number} maxMatches The maximum number of matches requested from the
    - *     server; passed as the 'max_matches' query param. The server is
    - *     responsible for limiting the number of matches that are returned.
    - * @param {Function} matchHandler Callback to execute on the result after
    - *     matching.
    - * @override
    - */
    -goog.ui.ac.RichRemoteArrayMatcher.prototype.requestMatchingRows =
    -    function(token, maxMatches, matchHandler) {
    -  // The RichRemoteArrayMatcher must map over the results and filter them
    -  // before calling the request matchHandler.  This is done by passing
    -  // myMatchHandler to RemoteArrayMatcher.requestMatchingRows which maps,
    -  // filters, and then calls matchHandler.
    -  var myMatchHandler = goog.bind(function(token, matches) {
    -    /** @preserveTry */
    -    try {
    -      var rows = [];
    -      for (var i = 0; i < matches.length; i++) {
    -        var func =  /** @type {!Function} */
    -            (goog.json.unsafeParse(matches[i][0]));
    -        for (var j = 1; j < matches[i].length; j++) {
    -          var richRow = func(matches[i][j]);
    -          rows.push(richRow);
    -
    -          // If no render function was provided, set the node's innerHTML.
    -          if (typeof richRow.render == 'undefined') {
    -            richRow.render = function(node, token) {
    -              goog.dom.safe.setInnerHtml(node,
    -                  goog.html.legacyconversions.safeHtmlFromString(
    -                      richRow.toString()));
    -            };
    -          }
    -
    -          // If no select function was provided, set the text of the input.
    -          if (typeof richRow.select == 'undefined') {
    -            richRow.select = function(target) {
    -              target.value = richRow.toString();
    -            };
    -          }
    -        }
    -      }
    -      if (this.rowFilter_) {
    -        rows = this.rowFilter_(rows);
    -      }
    -      matchHandler(token, rows);
    -    } catch (exception) {
    -      // TODO(user): Is this what we want?
    -      matchHandler(token, []);
    -    }
    -  }, this);
    -
    -  // Call the super's requestMatchingRows with myMatchHandler
    -  goog.ui.ac.RichRemoteArrayMatcher.superClass_
    -      .requestMatchingRows.call(this, token, maxMatches, myMatchHandler);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/activitymonitor.js b/src/database/third_party/closure-library/closure/goog/ui/activitymonitor.js
    deleted file mode 100644
    index 51f91dec136..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/activitymonitor.js
    +++ /dev/null
    @@ -1,348 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Activity Monitor.
    - *
    - * Fires throttled events when a user interacts with the specified document.
    - * This class also exposes the amount of time since the last user event.
    - *
    - * If you would prefer to get BECOME_ACTIVE and BECOME_IDLE events when the
    - * user changes states, then you should use the IdleTimer class instead.
    - *
    - */
    -
    -goog.provide('goog.ui.ActivityMonitor');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -
    -
    -
    -/**
    - * Once initialized with a document, the activity monitor can be queried for
    - * the current idle time.
    - *
    - * @param {goog.dom.DomHelper|Array<goog.dom.DomHelper>=} opt_domHelper
    - *     DomHelper which contains the document(s) to listen to.  If null, the
    - *     default document is usedinstead.
    - * @param {boolean=} opt_useBubble Whether to use the bubble phase to listen for
    - *     events. By default listens on the capture phase so that it won't miss
    - *     events that get stopPropagation/cancelBubble'd. However, this can cause
    - *     problems in IE8 if the page loads multiple scripts that include the
    - *     closure event handling code.
    - *
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - */
    -goog.ui.ActivityMonitor = function(opt_domHelper, opt_useBubble) {
    -  goog.events.EventTarget.call(this);
    -
    -  /**
    -   * Array of documents that are being listened to.
    -   * @type {Array<Document>}
    -   * @private
    -   */
    -  this.documents_ = [];
    -
    -  /**
    -   * Whether to use the bubble phase to listen for events.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.useBubble_ = !!opt_useBubble;
    -
    -  /**
    -   * The event handler.
    -   * @type {goog.events.EventHandler<!goog.ui.ActivityMonitor>}
    -   * @private
    -   */
    -  this.eventHandler_ = new goog.events.EventHandler(this);
    -
    -  /**
    -   * Whether the current window is an iframe.
    -   * TODO(user): Move to goog.dom.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.isIframe_ = window.parent != window;
    -
    -  if (!opt_domHelper) {
    -    this.addDocument(goog.dom.getDomHelper().getDocument());
    -  } else if (goog.isArray(opt_domHelper)) {
    -    for (var i = 0; i < opt_domHelper.length; i++) {
    -      this.addDocument(opt_domHelper[i].getDocument());
    -    }
    -  } else {
    -    this.addDocument(opt_domHelper.getDocument());
    -  }
    -
    -  /**
    -   * The time (in milliseconds) of the last user event.
    -   * @type {number}
    -   * @private
    -   */
    -  this.lastEventTime_ = goog.now();
    -
    -};
    -goog.inherits(goog.ui.ActivityMonitor, goog.events.EventTarget);
    -goog.tagUnsealableClass(goog.ui.ActivityMonitor);
    -
    -
    -/**
    - * The last event type that was detected.
    - * @type {string}
    - * @private
    - */
    -goog.ui.ActivityMonitor.prototype.lastEventType_ = '';
    -
    -
    -/**
    - * The mouse x-position after the last user event.
    - * @type {number}
    - * @private
    - */
    -goog.ui.ActivityMonitor.prototype.lastMouseX_;
    -
    -
    -/**
    - * The mouse y-position after the last user event.
    - * @type {number}
    - * @private
    - */
    -goog.ui.ActivityMonitor.prototype.lastMouseY_;
    -
    -
    -/**
    - * The earliest time that another throttled ACTIVITY event will be dispatched
    - * @type {number}
    - * @private
    - */
    -goog.ui.ActivityMonitor.prototype.minEventTime_ = 0;
    -
    -
    -/**
    - * Minimum amount of time in ms between throttled ACTIVITY events
    - * @type {number}
    - */
    -goog.ui.ActivityMonitor.MIN_EVENT_SPACING = 3 * 1000;
    -
    -
    -/**
    - * If a user executes one of these events, s/he is considered not idle.
    - * @type {Array<goog.events.EventType>}
    - * @private
    - */
    -goog.ui.ActivityMonitor.userEventTypesBody_ = [
    -  goog.events.EventType.CLICK,
    -  goog.events.EventType.DBLCLICK,
    -  goog.events.EventType.MOUSEDOWN,
    -  goog.events.EventType.MOUSEMOVE,
    -  goog.events.EventType.MOUSEUP
    -];
    -
    -
    -/**
    - * If a user executes one of these events, s/he is considered not idle.
    - * Note: monitoring touch events within iframe cause problems in iOS.
    - * @type {Array<goog.events.EventType>}
    - * @private
    - */
    -goog.ui.ActivityMonitor.userTouchEventTypesBody_ = [
    -  goog.events.EventType.TOUCHEND,
    -  goog.events.EventType.TOUCHMOVE,
    -  goog.events.EventType.TOUCHSTART
    -];
    -
    -
    -/**
    - * If a user executes one of these events, s/he is considered not idle.
    - * @type {Array<goog.events.EventType>}
    - * @private
    - */
    -goog.ui.ActivityMonitor.userEventTypesDocuments_ =
    -    [goog.events.EventType.KEYDOWN, goog.events.EventType.KEYUP];
    -
    -
    -/**
    - * Event constants for the activity monitor.
    - * @enum {string}
    - */
    -goog.ui.ActivityMonitor.Event = {
    -  /** Event fired when the user does something interactive */
    -  ACTIVITY: 'activity'
    -};
    -
    -
    -/** @override */
    -goog.ui.ActivityMonitor.prototype.disposeInternal = function() {
    -  goog.ui.ActivityMonitor.superClass_.disposeInternal.call(this);
    -  this.eventHandler_.dispose();
    -  this.eventHandler_ = null;
    -  delete this.documents_;
    -};
    -
    -
    -/**
    - * Adds a document to those being monitored by this class.
    - *
    - * @param {Document} doc Document to monitor.
    - */
    -goog.ui.ActivityMonitor.prototype.addDocument = function(doc) {
    -  if (goog.array.contains(this.documents_, doc)) {
    -    return;
    -  }
    -  this.documents_.push(doc);
    -  var useCapture = !this.useBubble_;
    -
    -  var eventsToListenTo = goog.array.concat(
    -      goog.ui.ActivityMonitor.userEventTypesDocuments_,
    -      goog.ui.ActivityMonitor.userEventTypesBody_);
    -
    -  if (!this.isIframe_) {
    -    // Monitoring touch events in iframe causes problems interacting with text
    -    // fields in iOS (input text, textarea, contenteditable, select/copy/paste),
    -    // so just ignore these events. This shouldn't matter much given that a
    -    // touchstart event followed by touchend event produces a click event,
    -    // which is being monitored correctly.
    -    goog.array.extend(eventsToListenTo,
    -        goog.ui.ActivityMonitor.userTouchEventTypesBody_);
    -  }
    -
    -  this.eventHandler_.listen(doc, eventsToListenTo, this.handleEvent_,
    -      useCapture);
    -};
    -
    -
    -/**
    - * Removes a document from those being monitored by this class.
    - *
    - * @param {Document} doc Document to monitor.
    - */
    -goog.ui.ActivityMonitor.prototype.removeDocument = function(doc) {
    -  if (this.isDisposed()) {
    -    return;
    -  }
    -  goog.array.remove(this.documents_, doc);
    -  var useCapture = !this.useBubble_;
    -
    -  var eventsToUnlistenTo = goog.array.concat(
    -      goog.ui.ActivityMonitor.userEventTypesDocuments_,
    -      goog.ui.ActivityMonitor.userEventTypesBody_);
    -
    -  if (!this.isIframe_) {
    -    // See note above about monitoring touch events in iframe.
    -    goog.array.extend(eventsToUnlistenTo,
    -        goog.ui.ActivityMonitor.userTouchEventTypesBody_);
    -  }
    -
    -  this.eventHandler_.unlisten(doc, eventsToUnlistenTo, this.handleEvent_,
    -      useCapture);
    -};
    -
    -
    -/**
    - * Updates the last event time when a user action occurs.
    - * @param {goog.events.BrowserEvent} e Event object.
    - * @private
    - */
    -goog.ui.ActivityMonitor.prototype.handleEvent_ = function(e) {
    -  var update = false;
    -  switch (e.type) {
    -    case goog.events.EventType.MOUSEMOVE:
    -      // In FF 1.5, we get spurious mouseover and mouseout events when the UI
    -      // redraws. We only want to update the idle time if the mouse has moved.
    -      if (typeof this.lastMouseX_ == 'number' &&
    -          this.lastMouseX_ != e.clientX ||
    -          typeof this.lastMouseY_ == 'number' &&
    -          this.lastMouseY_ != e.clientY) {
    -        update = true;
    -      }
    -      this.lastMouseX_ = e.clientX;
    -      this.lastMouseY_ = e.clientY;
    -      break;
    -    default:
    -      update = true;
    -  }
    -
    -  if (update) {
    -    var type = goog.asserts.assertString(e.type);
    -    this.updateIdleTime(goog.now(), type);
    -  }
    -};
    -
    -
    -/**
    - * Updates the last event time to be the present time, useful for non-DOM
    - * events that should update idle time.
    - */
    -goog.ui.ActivityMonitor.prototype.resetTimer = function() {
    -  this.updateIdleTime(goog.now(), 'manual');
    -};
    -
    -
    -/**
    - * Updates the idle time and fires an event if time has elapsed since
    - * the last update.
    - * @param {number} eventTime Time (in MS) of the event that cleared the idle
    - *     timer.
    - * @param {string} eventType Type of the event, used only for debugging.
    - * @protected
    - */
    -goog.ui.ActivityMonitor.prototype.updateIdleTime = function(
    -    eventTime, eventType) {
    -  // update internal state noting whether the user was idle
    -  this.lastEventTime_ = eventTime;
    -  this.lastEventType_ = eventType;
    -
    -  // dispatch event
    -  if (eventTime > this.minEventTime_) {
    -    this.dispatchEvent(goog.ui.ActivityMonitor.Event.ACTIVITY);
    -    this.minEventTime_ = eventTime + goog.ui.ActivityMonitor.MIN_EVENT_SPACING;
    -  }
    -};
    -
    -
    -/**
    - * Returns the amount of time the user has been idle.
    - * @param {number=} opt_now The current time can optionally be passed in for the
    - *     computation to avoid an extra Date allocation.
    - * @return {number} The amount of time in ms that the user has been idle.
    - */
    -goog.ui.ActivityMonitor.prototype.getIdleTime = function(opt_now) {
    -  var now = opt_now || goog.now();
    -  return now - this.lastEventTime_;
    -};
    -
    -
    -/**
    - * Returns the type of the last user event.
    - * @return {string} event type.
    - */
    -goog.ui.ActivityMonitor.prototype.getLastEventType = function() {
    -  return this.lastEventType_;
    -};
    -
    -
    -/**
    - * Returns the time of the last event
    - * @return {number} last event time.
    - */
    -goog.ui.ActivityMonitor.prototype.getLastEventTime = function() {
    -  return this.lastEventTime_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/activitymonitor_test.html b/src/database/third_party/closure-library/closure/goog/ui/activitymonitor_test.html
    deleted file mode 100644
    index 582d6aed988..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/activitymonitor_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.ActivityMonitor
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.ActivityMonitorTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="mydiv">
    -   foo
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/activitymonitor_test.js b/src/database/third_party/closure-library/closure/goog/ui/activitymonitor_test.js
    deleted file mode 100644
    index a3b8f9aaca1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/activitymonitor_test.js
    +++ /dev/null
    @@ -1,147 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.ActivityMonitorTest');
    -goog.setTestOnly('goog.ui.ActivityMonitorTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventType');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -goog.require('goog.ui.ActivityMonitor');
    -
    -var mockClock;
    -var stubs = new goog.testing.PropertyReplacer();
    -var mydiv;
    -
    -function setUp() {
    -  mydiv = document.getElementById('mydiv');
    -  mockClock = new goog.testing.MockClock(true);
    -  // ActivityMonitor initializes a private to 0 which it compares to now(),
    -  // so tests fail unless we start the mock clock with something besides 0.
    -  mockClock.tick(1);
    -}
    -
    -function tearDown() {
    -  mockClock.dispose();
    -  stubs.reset();
    -}
    -
    -function testIdle() {
    -  var activityMonitor = new goog.ui.ActivityMonitor();
    -  assertEquals('Upon creation, last event time should be creation time',
    -      mockClock.getCurrentTime(), activityMonitor.getLastEventTime());
    -
    -  mockClock.tick(1000);
    -  activityMonitor.resetTimer();
    -  var resetTime = mockClock.getCurrentTime();
    -  assertEquals('Upon reset, last event time should be reset time',
    -      resetTime, activityMonitor.getLastEventTime());
    -  assertEquals('Upon reset, idle time should be zero',
    -      0, activityMonitor.getIdleTime());
    -
    -  mockClock.tick(1000);
    -  assertEquals('1s after reset, last event time should be reset time',
    -      resetTime, activityMonitor.getLastEventTime());
    -  assertEquals('1s after reset, idle time should be 1s',
    -      1000, activityMonitor.getIdleTime());
    -}
    -
    -function testEventFired() {
    -  var activityMonitor = new goog.ui.ActivityMonitor();
    -  var listener = goog.testing.recordFunction();
    -  goog.events.listen(activityMonitor, goog.ui.ActivityMonitor.Event.ACTIVITY,
    -                     listener);
    -
    -  mockClock.tick(1000);
    -  goog.testing.events.fireClickEvent(mydiv);
    -  assertEquals('Activity event should fire when click happens after creation',
    -               1, listener.getCallCount());
    -
    -  mockClock.tick(3000);
    -  goog.testing.events.fireClickEvent(mydiv);
    -  assertEquals('Activity event should not fire when click happens 3s or ' +
    -               'less since the last activity', 1, listener.getCallCount());
    -
    -  mockClock.tick(1);
    -  goog.testing.events.fireClickEvent(mydiv);
    -  assertEquals('Activity event should fire when click happens more than ' +
    -               '3s since the last activity', 2, listener.getCallCount());
    -}
    -
    -function testEventFiredWhenPropagationStopped() {
    -  var activityMonitor = new goog.ui.ActivityMonitor();
    -  var listener = goog.testing.recordFunction();
    -  goog.events.listen(activityMonitor, goog.ui.ActivityMonitor.Event.ACTIVITY,
    -                     listener);
    -
    -  goog.events.listenOnce(mydiv, goog.events.EventType.CLICK,
    -                         goog.events.Event.stopPropagation);
    -  goog.testing.events.fireClickEvent(mydiv);
    -  assertEquals('Activity event should fire despite click propagation ' +
    -      'stopped because listening on capture', 1, listener.getCallCount());
    -}
    -
    -function testEventNotFiredWhenPropagationStopped() {
    -  var activityMonitor = new goog.ui.ActivityMonitor(undefined, true);
    -  var listener = goog.testing.recordFunction();
    -  goog.events.listen(activityMonitor, goog.ui.ActivityMonitor.Event.ACTIVITY,
    -                     listener);
    -
    -  goog.events.listenOnce(mydiv, goog.events.EventType.CLICK,
    -                         goog.events.Event.stopPropagation);
    -  goog.testing.events.fireClickEvent(mydiv);
    -  assertEquals('Activity event should not fire since click propagation ' +
    -      'stopped and listening on bubble', 0, listener.getCallCount());
    -}
    -
    -function testTouchSequenceFired() {
    -  var activityMonitor = new goog.ui.ActivityMonitor();
    -  var listener = goog.testing.recordFunction();
    -  goog.events.listen(activityMonitor, goog.ui.ActivityMonitor.Event.ACTIVITY,
    -                     listener);
    -
    -  mockClock.tick(1000);
    -  goog.testing.events.fireTouchSequence(mydiv);
    -  assertEquals('Activity event should fire when touch happens after creation',
    -               1, listener.getCallCount());
    -
    -  mockClock.tick(3000);
    -  goog.testing.events.fireTouchSequence(mydiv);
    -  assertEquals('Activity event should not fire when touch happens 3s or ' +
    -               'less since the last activity', 1, listener.getCallCount());
    -
    -  mockClock.tick(1);
    -  goog.testing.events.fireTouchSequence(mydiv);
    -  assertEquals('Activity event should fire when touch happens more than ' +
    -               '3s since the last activity', 2, listener.getCallCount());
    -}
    -
    -function testAddDocument_duplicate() {
    -  var defaultDoc = goog.dom.getDomHelper().getDocument();
    -  var activityMonitor = new goog.ui.ActivityMonitor();
    -  assertEquals(1, activityMonitor.documents_.length);
    -  assertEquals(defaultDoc, activityMonitor.documents_[0]);
    -  var listenerCount = activityMonitor.eventHandler_.getListenerCount();
    -
    -  activityMonitor.addDocument(defaultDoc);
    -  assertEquals(1, activityMonitor.documents_.length);
    -  assertEquals(defaultDoc, activityMonitor.documents_[0]);
    -  assertEquals(listenerCount, activityMonitor.eventHandler_.getListenerCount());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/advancedtooltip.js b/src/database/third_party/closure-library/closure/goog/ui/advancedtooltip.js
    deleted file mode 100644
    index d7b9e9d93a7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/advancedtooltip.js
    +++ /dev/null
    @@ -1,367 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Advanced tooltip widget implementation.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - * @see ../demos/advancedtooltip.html
    - */
    -
    -goog.provide('goog.ui.AdvancedTooltip');
    -
    -goog.require('goog.events');
    -goog.require('goog.events.EventType');
    -goog.require('goog.math.Box');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.style');
    -goog.require('goog.ui.Tooltip');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Advanced tooltip widget with cursor tracking abilities. Works like a regular
    - * tooltip but can track the cursor position and direction to determine if the
    - * tooltip should be dismissed or remain open.
    - *
    - * @param {Element|string=} opt_el Element to display tooltip for, either
    - *     element reference or string id.
    - * @param {?string=} opt_str Text message to display in tooltip.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @constructor
    - * @extends {goog.ui.Tooltip}
    - */
    -goog.ui.AdvancedTooltip = function(opt_el, opt_str, opt_domHelper) {
    -  goog.ui.Tooltip.call(this, opt_el, opt_str, opt_domHelper);
    -};
    -goog.inherits(goog.ui.AdvancedTooltip, goog.ui.Tooltip);
    -goog.tagUnsealableClass(goog.ui.AdvancedTooltip);
    -
    -
    -/**
    - * Whether to track the cursor and thereby close the tooltip if it moves away
    - * from the tooltip and keep it open if it moves towards it.
    - *
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.AdvancedTooltip.prototype.cursorTracking_ = false;
    -
    -
    -/**
    - * Delay in milliseconds before tooltips are hidden if cursor tracking is
    - * enabled and the cursor is moving away from the tooltip.
    - *
    - * @type {number}
    - * @private
    - */
    -goog.ui.AdvancedTooltip.prototype.cursorTrackingHideDelayMs_ = 100;
    -
    -
    -/**
    - * Box object representing a margin around the tooltip where the cursor is
    - * allowed without dismissing the tooltip.
    - *
    - * @type {goog.math.Box}
    - * @private
    - */
    -goog.ui.AdvancedTooltip.prototype.hotSpotPadding_;
    -
    -
    -/**
    - * Bounding box.
    - *
    - * @type {goog.math.Box}
    - * @private
    - */
    -goog.ui.AdvancedTooltip.prototype.boundingBox_;
    -
    -
    -/**
    - * Anchor bounding box.
    - *
    - * @type {goog.math.Box}
    - * @private
    - */
    -goog.ui.AdvancedTooltip.prototype.anchorBox_;
    -
    -
    -/**
    - * Whether the cursor tracking is active.
    - *
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.AdvancedTooltip.prototype.tracking_ = false;
    -
    -
    -/**
    - * Sets margin around the tooltip where the cursor is allowed without dismissing
    - * the tooltip.
    - *
    - * @param {goog.math.Box=} opt_box The margin around the tooltip.
    - */
    -goog.ui.AdvancedTooltip.prototype.setHotSpotPadding = function(opt_box) {
    -  this.hotSpotPadding_ = opt_box || null;
    -};
    -
    -
    -/**
    - * @return {goog.math.Box} box The margin around the tooltip where the cursor is
    - *     allowed without dismissing the tooltip.
    - */
    -goog.ui.AdvancedTooltip.prototype.getHotSpotPadding = function() {
    -  return this.hotSpotPadding_;
    -};
    -
    -
    -/**
    - * Sets whether to track the cursor and thereby close the tooltip if it moves
    - * away from the tooltip and keep it open if it moves towards it.
    - *
    - * @param {boolean} b Whether to track the cursor.
    - */
    -goog.ui.AdvancedTooltip.prototype.setCursorTracking = function(b) {
    -  this.cursorTracking_ = b;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether to track the cursor and thereby close the tooltip
    - *     if it moves away from the tooltip and keep it open if it moves towards
    - *     it.
    - */
    -goog.ui.AdvancedTooltip.prototype.getCursorTracking = function() {
    -  return this.cursorTracking_;
    -};
    -
    -
    -/**
    - * Sets delay in milliseconds before tooltips are hidden if cursor tracking is
    - * enabled and the cursor is moving away from the tooltip.
    - *
    - * @param {number} delay The delay in milliseconds.
    - */
    -goog.ui.AdvancedTooltip.prototype.setCursorTrackingHideDelayMs =
    -    function(delay) {
    -  this.cursorTrackingHideDelayMs_ = delay;
    -};
    -
    -
    -/**
    - * @return {number} The delay in milliseconds before tooltips are hidden if
    - *     cursor tracking is enabled and the cursor is moving away from the
    - *     tooltip.
    - */
    -goog.ui.AdvancedTooltip.prototype.getCursorTrackingHideDelayMs = function() {
    -  return this.cursorTrackingHideDelayMs_;
    -};
    -
    -
    -/**
    - * Called after the popup is shown.
    - * @protected
    - * @suppress {underscore|visibility}
    - * @override
    - */
    -goog.ui.AdvancedTooltip.prototype.onShow_ = function() {
    -  goog.ui.AdvancedTooltip.superClass_.onShow_.call(this);
    -
    -  this.boundingBox_ = goog.style.getBounds(this.getElement()).toBox();
    -  if (this.anchor) {
    -    this.anchorBox_ = goog.style.getBounds(this.anchor).toBox();
    -  }
    -
    -  this.tracking_ = this.cursorTracking_;
    -  goog.events.listen(this.getDomHelper().getDocument(),
    -                     goog.events.EventType.MOUSEMOVE,
    -                     this.handleMouseMove, false, this);
    -};
    -
    -
    -/**
    - * Called after the popup is hidden.
    - * @protected
    - * @suppress {underscore|visibility}
    - * @override
    - */
    -goog.ui.AdvancedTooltip.prototype.onHide_ = function() {
    -  goog.events.unlisten(this.getDomHelper().getDocument(),
    -                       goog.events.EventType.MOUSEMOVE,
    -                       this.handleMouseMove, false, this);
    -
    -  this.boundingBox_ = null;
    -  this.anchorBox_ = null;
    -  this.tracking_ = false;
    -
    -  goog.ui.AdvancedTooltip.superClass_.onHide_.call(this);
    -};
    -
    -
    -/**
    - * Returns true if the mouse is in the tooltip.
    - * @return {boolean} True if the mouse is in the tooltip.
    - */
    -goog.ui.AdvancedTooltip.prototype.isMouseInTooltip = function() {
    -  return this.isCoordinateInTooltip(this.cursorPosition);
    -};
    -
    -
    -/**
    - * Checks whether the supplied coordinate is inside the tooltip, including
    - * padding if any.
    - * @param {goog.math.Coordinate} coord Coordinate being tested.
    - * @return {boolean} Whether the coord is in the tooltip.
    - * @override
    - */
    -goog.ui.AdvancedTooltip.prototype.isCoordinateInTooltip = function(coord) {
    -  // Check if coord is inside the bounding box of the tooltip
    -  if (this.hotSpotPadding_) {
    -    var offset = goog.style.getPageOffset(this.getElement());
    -    var size = goog.style.getSize(this.getElement());
    -    return offset.x - this.hotSpotPadding_.left <= coord.x &&
    -        coord.x <= offset.x + size.width + this.hotSpotPadding_.right &&
    -        offset.y - this.hotSpotPadding_.top <= coord.y &&
    -        coord.y <= offset.y + size.height + this.hotSpotPadding_.bottom;
    -  }
    -
    -  return goog.ui.AdvancedTooltip.superClass_.isCoordinateInTooltip.call(this,
    -                                                                        coord);
    -};
    -
    -
    -/**
    - * Checks if supplied coordinate is in the tooltip, its triggering anchor, or
    - * a tooltip that has been triggered by a child of this tooltip.
    - * Called from handleMouseMove to determine if hide timer should be started,
    - * and from maybeHide to determine if tooltip should be hidden.
    - * @param {goog.math.Coordinate} coord Coordinate being tested.
    - * @return {boolean} Whether coordinate is in the anchor, the tooltip, or any
    - *     tooltip whose anchor is a child of this tooltip.
    - * @private
    - */
    -goog.ui.AdvancedTooltip.prototype.isCoordinateActive_ = function(coord) {
    -  if ((this.anchorBox_ && this.anchorBox_.contains(coord)) ||
    -      this.isCoordinateInTooltip(coord)) {
    -    return true;
    -  }
    -
    -  // Check if mouse might be in active child element.
    -  var childTooltip = this.getChildTooltip();
    -  return !!childTooltip && childTooltip.isCoordinateInTooltip(coord);
    -};
    -
    -
    -/**
    - * Called by timer from mouse out handler. Hides tooltip if cursor is still
    - * outside element and tooltip.
    - * @param {Element} el Anchor when hide timer was started.
    - * @override
    - */
    -goog.ui.AdvancedTooltip.prototype.maybeHide = function(el) {
    -  this.hideTimer = undefined;
    -  if (el == this.anchor) {
    -    // Check if cursor is inside the bounding box of the tooltip or the element
    -    // that triggered it, or if tooltip is active (possibly due to receiving
    -    // the focus), or if there is a nested tooltip being shown.
    -    if (!this.isCoordinateActive_(this.cursorPosition) &&
    -        !this.getActiveElement() &&
    -        !this.hasActiveChild()) {
    -      // Under certain circumstances gecko fires ghost mouse events with the
    -      // coordinates 0, 0 regardless of the cursors position.
    -      if (goog.userAgent.GECKO && this.cursorPosition.x == 0 &&
    -          this.cursorPosition.y == 0) {
    -        return;
    -      }
    -      this.setVisible(false);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Handler for mouse move events.
    - *
    - * @param {goog.events.BrowserEvent} event Event object.
    - * @protected
    - * @override
    - */
    -goog.ui.AdvancedTooltip.prototype.handleMouseMove = function(event) {
    -  var startTimer = this.isVisible();
    -  if (this.boundingBox_) {
    -    var scroll = this.getDomHelper().getDocumentScroll();
    -    var c = new goog.math.Coordinate(event.clientX + scroll.x,
    -        event.clientY + scroll.y);
    -    if (this.isCoordinateActive_(c)) {
    -      startTimer = false;
    -    } else if (this.tracking_) {
    -      var prevDist = goog.math.Box.distance(this.boundingBox_,
    -          this.cursorPosition);
    -      var currDist = goog.math.Box.distance(this.boundingBox_, c);
    -      startTimer = currDist >= prevDist;
    -    }
    -  }
    -
    -  if (startTimer) {
    -    this.startHideTimer();
    -
    -    // Even though the mouse coordinate is not on the tooltip (or nested child),
    -    // they may have an active element because of a focus event.  Don't let
    -    // that prevent us from taking down the tooltip(s) on this mouse move.
    -    this.setActiveElement(null);
    -    var childTooltip = this.getChildTooltip();
    -    if (childTooltip) {
    -      childTooltip.setActiveElement(null);
    -    }
    -  } else if (this.getState() == goog.ui.Tooltip.State.WAITING_TO_HIDE) {
    -    this.clearHideTimer();
    -  }
    -
    -  goog.ui.AdvancedTooltip.superClass_.handleMouseMove.call(this, event);
    -};
    -
    -
    -/**
    - * Handler for mouse over events for the tooltip element.
    - *
    - * @param {goog.events.BrowserEvent} event Event object.
    - * @protected
    - * @override
    - */
    -goog.ui.AdvancedTooltip.prototype.handleTooltipMouseOver = function(event) {
    -  if (this.getActiveElement() != this.getElement()) {
    -    this.tracking_ = false;
    -    this.setActiveElement(this.getElement());
    -  }
    -};
    -
    -
    -/**
    - * Override hide delay with cursor tracking hide delay while tracking.
    - * @return {number} Hide delay to use.
    - * @override
    - */
    -goog.ui.AdvancedTooltip.prototype.getHideDelayMs = function() {
    -  return this.tracking_ ? this.cursorTrackingHideDelayMs_ :
    -      goog.ui.AdvancedTooltip.base(this, 'getHideDelayMs');
    -};
    -
    -
    -/**
    - * Forces the recalculation of the hotspot on the next mouse over event.
    - * @deprecated Not ever necessary to call this function. Hot spot is calculated
    - *     as neccessary.
    - */
    -goog.ui.AdvancedTooltip.prototype.resetHotSpot = goog.nullFunction;
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/advancedtooltip_test.html b/src/database/third_party/closure-library/closure/goog/ui/advancedtooltip_test.html
    deleted file mode 100644
    index 980c58eecec..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/advancedtooltip_test.html
    +++ /dev/null
    @@ -1,33 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.AdvancedTooltip
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.AdvancedTooltipTest');
    -  </script>
    - </head>
    - <body>
    -  <p>
    -   <span id="hovertarget">
    -    Hover Here For Popup
    -    <span id="childtarget">
    -     Child of target
    -    </span>
    -   </span>
    -  </p>
    -  <p id="notpopup">
    -   Content
    -  </p>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/advancedtooltip_test.js b/src/database/third_party/closure-library/closure/goog/ui/advancedtooltip_test.js
    deleted file mode 100644
    index 4e1e78edf49..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/advancedtooltip_test.js
    +++ /dev/null
    @@ -1,287 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.AdvancedTooltipTest');
    -goog.setTestOnly('goog.ui.AdvancedTooltipTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventType');
    -goog.require('goog.math.Box');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.style');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.AdvancedTooltip');
    -goog.require('goog.ui.Tooltip');
    -goog.require('goog.userAgent');
    -
    -var att;
    -var clock;
    -var anchor;
    -var elsewhere;
    -var popup;
    -
    -var SHOWDELAY = 50;
    -var HIDEDELAY = 250;
    -var TRACKINGDELAY = 100;
    -
    -function isWindowTooSmall() {
    -  // Firefox 3 fails if the window is too small.
    -  return goog.userAgent.GECKO &&
    -      (window.innerWidth < 350 || window.innerHeight < 100);
    -}
    -
    -function setUp() {
    -  popup = goog.dom.createDom('span',
    -      {id: 'popup', style: 'position:absolute;top:300;left:300'}, 'Hello');
    -  att = new goog.ui.AdvancedTooltip('hovertarget');
    -  att.setElement(popup);
    -  att.setCursorTracking(true);
    -  att.setHotSpotPadding(new goog.math.Box(10, 10, 10, 10));
    -  att.setShowDelayMs(SHOWDELAY);
    -  att.setHideDelayMs(HIDEDELAY);
    -  att.setCursorTrackingHideDelayMs(TRACKINGDELAY);
    -  att.setMargin(new goog.math.Box(300, 0, 0, 300));
    -
    -  clock = new goog.testing.MockClock(true);
    -
    -  anchor = goog.dom.getElement('hovertarget');
    -  elsewhere = goog.dom.getElement('notpopup');
    -}
    -
    -function tearDown() {
    -  // tooltip needs to be hidden as well as disposed of so that it doesn't
    -  // leave global state hanging around to trip up other tests.
    -  if (att.isVisible()) {
    -    att.onHide_();
    -  }
    -  att.dispose();
    -  clock.uninstall();
    -}
    -
    -function assertVisible(msg, element) {
    -  if (element) {
    -    assertEquals(msg, 'visible', element.style.visibility);
    -  } else {
    -    assertEquals('visible', msg.style.visibility);
    -  }
    -}
    -
    -function assertHidden(msg, element) {
    -  if (element) {
    -    assertEquals(msg, 'hidden', element.style.visibility);
    -  } else {
    -    assertEquals('hidden', msg.style.visibility);
    -  }
    -}
    -
    -
    -/**
    - * Helper function to fire events related to moving a mouse from one element
    - * to another. Fires mouseout, mouseover, and mousemove event.
    - * @param {Element} from Element the mouse is moving from.
    - * @param {Element} to Element the mouse is moving to.
    - */
    -function fireMouseEvents(from, to) {
    -  goog.testing.events.fireMouseOutEvent(from, to);
    -  goog.testing.events.fireMouseOverEvent(to, from);
    -  var bounds = goog.style.getBounds(to);
    -  goog.testing.events.fireMouseMoveEvent(
    -      document, new goog.math.Coordinate(bounds.left + 1, bounds.top + 1));
    -}
    -
    -function testCursorTracking() {
    -  if (isWindowTooSmall()) {
    -    return;
    -  }
    -
    -  var oneThirdOfTheWay, twoThirdsOfTheWay;
    -
    -  oneThirdOfTheWay = new goog.math.Coordinate(100, 100);
    -  twoThirdsOfTheWay = new goog.math.Coordinate(200, 200);
    -
    -  goog.testing.events.fireMouseOverEvent(anchor, elsewhere);
    -  clock.tick(SHOWDELAY);
    -  assertVisible('Mouse over anchor should show popup', popup);
    -
    -  goog.testing.events.fireMouseOutEvent(anchor, elsewhere);
    -  goog.testing.events.fireMouseMoveEvent(document, oneThirdOfTheWay);
    -  clock.tick(HIDEDELAY);
    -  assertVisible("Moving mouse towards popup shouldn't hide it", popup);
    -
    -  goog.testing.events.fireMouseMoveEvent(document, twoThirdsOfTheWay);
    -  goog.testing.events.fireMouseMoveEvent(document, oneThirdOfTheWay);
    -  clock.tick(TRACKINGDELAY);
    -  assertHidden('Moving mouse away from popup should hide it', popup);
    -
    -  goog.testing.events.fireMouseMoveEvent(document, twoThirdsOfTheWay);
    -  goog.testing.events.fireBrowserEvent(new goog.events.Event(
    -      goog.events.EventType.FOCUS, anchor));
    -  clock.tick(SHOWDELAY);
    -  assertVisible('Set focus shows popup', popup);
    -  goog.testing.events.fireMouseMoveEvent(document, oneThirdOfTheWay);
    -  clock.tick(TRACKINGDELAY);
    -  assertHidden('Mouse move after focus should hide popup', popup);
    -}
    -
    -function testPadding() {
    -  if (isWindowTooSmall()) {
    -    return;
    -  }
    -
    -  goog.testing.events.fireMouseOverEvent(anchor, elsewhere);
    -  clock.tick(SHOWDELAY);
    -
    -  var attBounds = goog.style.getBounds(popup);
    -  var inPadding = new goog.math.Coordinate(attBounds.left - 5,
    -                                           attBounds.top - 5);
    -  var outOfPadding = new goog.math.Coordinate(attBounds.left - 15,
    -                                              attBounds.top - 15);
    -
    -  fireMouseEvents(anchor, popup);
    -  goog.testing.events.fireMouseOutEvent(popup, elsewhere);
    -  goog.testing.events.fireMouseMoveEvent(document, inPadding);
    -  clock.tick(HIDEDELAY);
    -  assertVisible("Mouse out of popup but within padding shouldn't hide it",
    -                popup);
    -
    -  goog.testing.events.fireMouseMoveEvent(document, outOfPadding);
    -  clock.tick(HIDEDELAY);
    -  assertHidden('Mouse move beyond popup padding should hide it', popup);
    -}
    -
    -
    -function testAnchorWithChild() {
    -  var child = goog.dom.getElement('childtarget');
    -
    -  fireMouseEvents(elsewhere, anchor);
    -  fireMouseEvents(anchor, child);
    -  clock.tick(SHOWDELAY);
    -  assertVisible('Mouse into child of anchor should still show popup', popup);
    -
    -  fireMouseEvents(child, anchor);
    -  clock.tick(HIDEDELAY);
    -  assertVisible('Mouse from child to anchor should still show popup', popup);
    -}
    -
    -function testNestedTooltip() {
    -  if (!isWindowTooSmall()) {
    -    checkNestedTooltips(false);
    -  }
    -}
    -
    -function testNestedAdvancedTooltip() {
    -  if (!isWindowTooSmall()) {
    -    checkNestedTooltips(true);
    -  }
    -}
    -
    -function testResizingTooltipWhileShown() {
    -  fireMouseEvents(elsewhere, anchor);
    -  clock.tick(SHOWDELAY);
    -  popup.style.height = '100px';
    -  var attBounds = goog.style.getBounds(popup);
    -  var inPadding = new goog.math.Coordinate(
    -      attBounds.left + 5, attBounds.top + attBounds.height + 5);
    -  var outOfPadding = new goog.math.Coordinate(
    -      attBounds.left + 5, attBounds.top + attBounds.height + 15);
    -
    -  fireMouseEvents(anchor, popup);
    -  goog.testing.events.fireMouseOutEvent(popup, elsewhere);
    -  goog.testing.events.fireMouseMoveEvent(document, inPadding);
    -  clock.tick(HIDEDELAY);
    -  assertVisible("Mouse out of popup but within padding shouldn't hide it",
    -                popup);
    -
    -  goog.testing.events.fireMouseMoveEvent(document, outOfPadding);
    -  clock.tick(HIDEDELAY);
    -  assertHidden('Mouse move beyond popup padding should hide it', popup);
    -}
    -
    -function checkNestedTooltips(useAdvancedTooltip) {
    -  popup.appendChild(goog.dom.createDom(
    -      'span', {id: 'nestedAnchor'}, 'Nested Anchor'));
    -  var nestedAnchor = goog.dom.getElement('nestedAnchor');
    -  var nestedTooltip;
    -  if (useAdvancedTooltip) {
    -    nestedTooltip = new goog.ui.AdvancedTooltip(nestedAnchor, 'popup');
    -  } else {
    -    nestedTooltip = new goog.ui.Tooltip(nestedAnchor, 'popup');
    -  }
    -  var nestedPopup = nestedTooltip.getElement();
    -  nestedTooltip.setShowDelayMs(SHOWDELAY);
    -  nestedTooltip.setHideDelayMs(HIDEDELAY);
    -
    -  fireMouseEvents(elsewhere, anchor);
    -  clock.tick(SHOWDELAY);
    -  fireMouseEvents(anchor, popup);
    -  fireMouseEvents(popup, nestedAnchor);
    -  clock.tick(SHOWDELAY + HIDEDELAY);
    -  assertVisible('Mouse into nested anchor should show popup', nestedPopup);
    -  assertVisible('Mouse into nested anchor should not hide parent', popup);
    -  fireMouseEvents(nestedAnchor, elsewhere);
    -  clock.tick(HIDEDELAY);
    -  assertHidden('Mouse out of nested popup should hide it', nestedPopup);
    -  clock.tick(HIDEDELAY);
    -  assertHidden('Mouse out of nested popup should eventually hide parent',
    -               popup);
    -
    -  goog.testing.events.fireBrowserEvent(new goog.events.Event(
    -      goog.events.EventType.FOCUS, anchor));
    -  clock.tick(SHOWDELAY);
    -  goog.testing.events.fireBrowserEvent(new goog.events.Event(
    -      goog.events.EventType.BLUR, anchor));
    -  goog.testing.events.fireBrowserEvent(new goog.events.Event(
    -      goog.events.EventType.FOCUS, nestedAnchor));
    -  clock.tick(SHOWDELAY + HIDEDELAY);
    -  assertVisible("Moving focus to child anchor doesn't hide parent", popup);
    -  assertVisible('Set focus shows nested popup', nestedPopup);
    -
    -  goog.testing.events.fireBrowserEvent(new goog.events.Event(
    -      goog.events.EventType.BLUR, nestedAnchor));
    -  goog.testing.events.fireBrowserEvent(new goog.events.Event(
    -      goog.events.EventType.FOCUS, anchor));
    -  clock.tick(HIDEDELAY + HIDEDELAY);
    -  assertHidden('Lose focus hides nested popup', nestedPopup);
    -  assertVisible(
    -      "Moving focus from nested anchor to parent doesn't hide parent", popup);
    -
    -  goog.testing.events.fireBrowserEvent(new goog.events.Event(
    -      goog.events.EventType.BLUR, anchor));
    -  goog.testing.events.fireBrowserEvent(new goog.events.Event(
    -      goog.events.EventType.FOCUS, nestedAnchor));
    -  clock.tick(SHOWDELAY);
    -  goog.testing.events.fireBrowserEvent(new goog.events.Event(
    -      goog.events.EventType.BLUR, nestedAnchor));
    -  clock.tick(HIDEDELAY);
    -  assertHidden('Lose focus hides nested popup', nestedPopup);
    -  clock.tick(HIDEDELAY);
    -  assertHidden('Nested anchor losing focus hides parent', popup);
    -
    -  goog.testing.events.fireBrowserEvent(new goog.events.Event(
    -      goog.events.EventType.FOCUS, anchor));
    -  clock.tick(SHOWDELAY);
    -  goog.testing.events.fireBrowserEvent(new goog.events.Event(
    -      goog.events.EventType.BLUR, anchor));
    -  goog.testing.events.fireBrowserEvent(new goog.events.Event(
    -      goog.events.EventType.FOCUS, nestedAnchor));
    -  clock.tick(SHOWDELAY);
    -  var coordElsewhere = new goog.math.Coordinate(1, 1);
    -  goog.testing.events.fireMouseMoveEvent(document, coordElsewhere);
    -  clock.tick(HIDEDELAY);
    -  assertHidden('Mouse move should hide parent with active child', popup);
    -  assertHidden('Mouse move should hide nested popup', nestedPopup);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/animatedzippy.js b/src/database/third_party/closure-library/closure/goog/ui/animatedzippy.js
    deleted file mode 100644
    index 62aec7127e5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/animatedzippy.js
    +++ /dev/null
    @@ -1,200 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Animated zippy widget implementation.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - * @see ../demos/zippy.html
    - */
    -
    -goog.provide('goog.ui.AnimatedZippy');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.fx.Animation');
    -goog.require('goog.fx.Transition');
    -goog.require('goog.fx.easing');
    -goog.require('goog.ui.Zippy');
    -goog.require('goog.ui.ZippyEvent');
    -
    -
    -
    -/**
    - * Zippy widget. Expandable/collapsible container, clicking the header toggles
    - * the visibility of the content.
    - *
    - * @param {Element|string|null} header Header element, either element
    - *     reference, string id or null if no header exists.
    - * @param {Element|string} content Content element, either element reference or
    - *     string id.
    - * @param {boolean=} opt_expanded Initial expanded/visibility state. Defaults to
    - *     false.
    - * @param {goog.dom.DomHelper=} opt_domHelper An optional DOM helper.
    - * @constructor
    - * @extends {goog.ui.Zippy}
    - */
    -goog.ui.AnimatedZippy = function(header, content, opt_expanded, opt_domHelper) {
    -  var domHelper = opt_domHelper || goog.dom.getDomHelper();
    -
    -  // Create wrapper element and move content into it.
    -  var elWrapper = domHelper.createDom('div', {'style': 'overflow:hidden'});
    -  var elContent = domHelper.getElement(content);
    -  elContent.parentNode.replaceChild(elWrapper, elContent);
    -  elWrapper.appendChild(elContent);
    -
    -  /**
    -   * Content wrapper, used for animation.
    -   * @type {Element}
    -   * @private
    -   */
    -  this.elWrapper_ = elWrapper;
    -
    -  /**
    -   * Reference to animation or null if animation is not active.
    -   * @type {goog.fx.Animation}
    -   * @private
    -   */
    -  this.anim_ = null;
    -
    -  // Call constructor of super class.
    -  goog.ui.Zippy.call(this, header, elContent, opt_expanded,
    -      undefined, domHelper);
    -
    -  // Set initial state.
    -  // NOTE: Set the class names as well otherwise animated zippys
    -  // start with empty class names.
    -  var expanded = this.isExpanded();
    -  this.elWrapper_.style.display = expanded ? '' : 'none';
    -  this.updateHeaderClassName(expanded);
    -};
    -goog.inherits(goog.ui.AnimatedZippy, goog.ui.Zippy);
    -goog.tagUnsealableClass(goog.ui.AnimatedZippy);
    -
    -
    -/**
    - * Duration of expand/collapse animation, in milliseconds.
    - * @type {number}
    - */
    -goog.ui.AnimatedZippy.prototype.animationDuration = 500;
    -
    -
    -/**
    - * Acceleration function for expand/collapse animation.
    - * @type {!Function}
    - */
    -goog.ui.AnimatedZippy.prototype.animationAcceleration = goog.fx.easing.easeOut;
    -
    -
    -/**
    - * @return {boolean} Whether the zippy is in the process of being expanded or
    - *     collapsed.
    - */
    -goog.ui.AnimatedZippy.prototype.isBusy = function() {
    -  return this.anim_ != null;
    -};
    -
    -
    -/**
    - * Sets expanded state.
    - *
    - * @param {boolean} expanded Expanded/visibility state.
    - * @override
    - */
    -goog.ui.AnimatedZippy.prototype.setExpanded = function(expanded) {
    -  if (this.isExpanded() == expanded && !this.anim_) {
    -    return;
    -  }
    -
    -  // Reset display property of wrapper to allow content element to be
    -  // measured.
    -  if (this.elWrapper_.style.display == 'none') {
    -    this.elWrapper_.style.display = '';
    -  }
    -
    -  // Measure content element.
    -  var h = this.getContentElement().offsetHeight;
    -
    -  // Stop active animation (if any) and determine starting height.
    -  var startH = 0;
    -  if (this.anim_) {
    -    expanded = this.isExpanded();
    -    goog.events.removeAll(this.anim_);
    -    this.anim_.stop(false);
    -
    -    var marginTop = parseInt(this.getContentElement().style.marginTop, 10);
    -    startH = h - Math.abs(marginTop);
    -  } else {
    -    startH = expanded ? 0 : h;
    -  }
    -
    -  // Updates header class name after the animation has been stopped.
    -  this.updateHeaderClassName(expanded);
    -
    -  // Set up expand/collapse animation.
    -  this.anim_ = new goog.fx.Animation([0, startH],
    -                                     [0, expanded ? h : 0],
    -                                     this.animationDuration,
    -                                     this.animationAcceleration);
    -
    -  var events = [goog.fx.Transition.EventType.BEGIN,
    -                goog.fx.Animation.EventType.ANIMATE,
    -                goog.fx.Transition.EventType.END];
    -  goog.events.listen(this.anim_, events, this.onAnimate_, false, this);
    -  goog.events.listen(this.anim_,
    -                     goog.fx.Transition.EventType.END,
    -                     goog.bind(this.onAnimationCompleted_, this, expanded));
    -
    -  // Start animation.
    -  this.anim_.play(false);
    -};
    -
    -
    -/**
    - * Called during animation
    - *
    - * @param {goog.events.Event} e The event.
    - * @private
    - */
    -goog.ui.AnimatedZippy.prototype.onAnimate_ = function(e) {
    -  var contentElement = this.getContentElement();
    -  var h = contentElement.offsetHeight;
    -  contentElement.style.marginTop = (e.y - h) + 'px';
    -};
    -
    -
    -/**
    - * Called once the expand/collapse animation has completed.
    - *
    - * @param {boolean} expanded Expanded/visibility state.
    - * @private
    - */
    -goog.ui.AnimatedZippy.prototype.onAnimationCompleted_ = function(expanded) {
    -  // Fix wrong end position if the content has changed during the animation.
    -  if (expanded) {
    -    this.getContentElement().style.marginTop = '0';
    -  }
    -
    -  goog.events.removeAll(/** @type {!goog.fx.Animation} */ (this.anim_));
    -  this.setExpandedInternal(expanded);
    -  this.anim_ = null;
    -
    -  if (!expanded) {
    -    this.elWrapper_.style.display = 'none';
    -  }
    -
    -  // Fire toggle event.
    -  this.dispatchEvent(new goog.ui.ZippyEvent(goog.ui.Zippy.Events.TOGGLE,
    -                                            this, expanded));
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/animatedzippy_test.html b/src/database/third_party/closure-library/closure/goog/ui/animatedzippy_test.html
    deleted file mode 100644
    index d9b59953aca..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/animatedzippy_test.html
    +++ /dev/null
    @@ -1,57 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.AnimatedZippy
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.ui.AnimatedZippyTest');
    -  </script>
    -  <style type="text/css">
    -   .demo {
    -      border: solid 1px red;
    -      margin: 0 0 20px 0;
    -    }
    -
    -    .demo h2 {
    -      background-color: yellow;
    -      border: solid 1px #ccc;
    -      padding: 2px;
    -      margin: 0;
    -      font-size: 100%;
    -    }
    -
    -    .demo div {
    -      border: solid 1px #ccc;
    -      padding: 2px;
    -    }
    -  </style>
    - </head>
    - <body>
    -  <div class="demo" id="d1">
    -   <h2 id="t1">
    -    handler
    -   </h2>
    -   <div id="c1">
    -    sem. Suspendisse porta felis ac ipsum. Sed tincidunt dui vitae nulla. Ut
    -    blandit. Nunc non neque. Mauris placerat. Vestibulum mollis tellus id dolor.
    -    Phasellus ac dolor molestie nunc euismod aliquam. Mauris tellus ipsum,
    -    fringilla id, tincidunt eu, vestibulum sit amet, metus. Quisque congue
    -    varius
    -    ligula. Quisque ornare mollis enim. Aliquam erat volutpat. Nulla mattis
    -    venenatis magna.
    -   </div>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/animatedzippy_test.js b/src/database/third_party/closure-library/closure/goog/ui/animatedzippy_test.js
    deleted file mode 100644
    index a024a9d73aa..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/animatedzippy_test.js
    +++ /dev/null
    @@ -1,93 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.AnimatedZippyTest');
    -goog.setTestOnly('goog.ui.AnimatedZippyTest');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.functions');
    -goog.require('goog.fx.Animation');
    -goog.require('goog.fx.Transition');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.asserts');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.AnimatedZippy');
    -goog.require('goog.ui.Zippy');
    -
    -var animatedZippy;
    -var animatedZippyHeaderEl;
    -var propertyReplacer;
    -
    -function setUp() {
    -  animatedZippyHeaderEl = goog.dom.getElement('t1');
    -  goog.asserts.assert(animatedZippyHeaderEl);
    -  animatedZippy = new goog.ui.AnimatedZippy(animatedZippyHeaderEl,
    -      goog.dom.getElement('c1'));
    -
    -  propertyReplacer = new goog.testing.PropertyReplacer();
    -}
    -
    -function tearDown() {
    -  propertyReplacer.reset();
    -  animatedZippy.dispose();
    -}
    -
    -function testConstructor() {
    -  assertNotNull('must not be null', animatedZippy);
    -}
    -
    -function testExpandCollapse() {
    -  var animationsPlayed = 0;
    -  var toggleEventsFired = 0;
    -
    -  propertyReplacer.replace(goog.fx.Animation.prototype, 'play', function() {
    -    animationsPlayed++;
    -    this.dispatchAnimationEvent(goog.fx.Transition.EventType.END);
    -  });
    -  propertyReplacer.replace(goog.ui.AnimatedZippy.prototype, 'onAnimate_',
    -      goog.functions.NULL);
    -
    -  goog.events.listenOnce(animatedZippy, goog.ui.Zippy.Events.TOGGLE,
    -      function(e) {
    -        toggleEventsFired++;
    -        assertTrue('TOGGLE event must be for expansion', e.expanded);
    -        assertEquals('expanded must be true', true,
    -            animatedZippy.isExpanded());
    -        assertEquals('aria-expanded must be true', 'true',
    -            goog.a11y.aria.getState(animatedZippyHeaderEl,
    -                goog.a11y.aria.State.EXPANDED));
    -      });
    -
    -  animatedZippy.expand();
    -
    -  goog.events.listenOnce(animatedZippy, goog.ui.Zippy.Events.TOGGLE,
    -      function(e) {
    -        toggleEventsFired++;
    -        assertFalse('TOGGLE event must be for collapse', e.expanded);
    -        assertEquals('expanded must be false', false,
    -            animatedZippy.isExpanded());
    -        assertEquals('aria-expanded must be false', 'false',
    -            goog.a11y.aria.getState(animatedZippyHeaderEl,
    -            goog.a11y.aria.State.EXPANDED));
    -      });
    -
    -  animatedZippy.collapse();
    -
    -  assertEquals('animations must play', 2, animationsPlayed);
    -  assertEquals('TOGGLE events must fire', 2, toggleEventsFired);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/attachablemenu.js b/src/database/third_party/closure-library/closure/goog/ui/attachablemenu.js
    deleted file mode 100644
    index bc13986de81..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/attachablemenu.js
    +++ /dev/null
    @@ -1,476 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Definition of the AttachableMenu class.
    - *
    - */
    -
    -goog.provide('goog.ui.AttachableMenu');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.string');
    -goog.require('goog.style');
    -goog.require('goog.ui.ItemEvent');
    -goog.require('goog.ui.MenuBase');
    -goog.require('goog.ui.PopupBase');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * An implementation of a menu that can attach itself to DOM element that
    - * are annotated appropriately.
    - *
    - * The following attributes are used by the AttachableMenu
    - *
    - * menu-item - Should be set on DOM elements that function as items in the
    - * menu that can be selected.
    - * classNameSelected - A class that will be added to the element's class names
    - * when the item is selected via keyboard or mouse.
    - *
    - * @param {Element=} opt_element A DOM element for the popup.
    - * @constructor
    - * @extends {goog.ui.MenuBase}
    - * @deprecated Use goog.ui.PopupMenu.
    - * @final
    - */
    -goog.ui.AttachableMenu = function(opt_element) {
    -  goog.ui.MenuBase.call(this, opt_element);
    -};
    -goog.inherits(goog.ui.AttachableMenu, goog.ui.MenuBase);
    -goog.tagUnsealableClass(goog.ui.AttachableMenu);
    -
    -
    -/**
    - * The currently selected element (mouse was moved over it or keyboard arrows)
    - * @type {Element}
    - * @private
    - */
    -goog.ui.AttachableMenu.prototype.selectedElement_ = null;
    -
    -
    -/**
    - * Class name to append to a menu item's class when it's selected
    - * @type {string}
    - * @private
    - */
    -goog.ui.AttachableMenu.prototype.itemClassName_ = 'menu-item';
    -
    -
    -/**
    - * Class name to append to a menu item's class when it's selected
    - * @type {string}
    - * @private
    - */
    -goog.ui.AttachableMenu.prototype.selectedItemClassName_ = 'menu-item-selected';
    -
    -
    -/**
    - * Keep track of when the last key was pressed so that a keydown-scroll doesn't
    - * trigger a mouseover event
    - * @type {number}
    - * @private
    - */
    -goog.ui.AttachableMenu.prototype.lastKeyDown_ = goog.now();
    -
    -
    -/** @override */
    -goog.ui.AttachableMenu.prototype.disposeInternal = function() {
    -  goog.ui.AttachableMenu.superClass_.disposeInternal.call(this);
    -  this.selectedElement_ = null;
    -};
    -
    -
    -/**
    - * Sets the class name to use for menu items
    - *
    - * @return {string} The class name to use for items.
    - */
    -goog.ui.AttachableMenu.prototype.getItemClassName = function() {
    -  return this.itemClassName_;
    -};
    -
    -
    -/**
    - * Sets the class name to use for menu items
    - *
    - * @param {string} name The class name to use for items.
    - */
    -goog.ui.AttachableMenu.prototype.setItemClassName = function(name) {
    -  this.itemClassName_ = name;
    -};
    -
    -
    -/**
    - * Sets the class name to use for selected menu items
    - * todo(user) - reevaluate if we can simulate pseudo classes in IE
    - *
    - * @return {string} The class name to use for selected items.
    - */
    -goog.ui.AttachableMenu.prototype.getSelectedItemClassName = function() {
    -  return this.selectedItemClassName_;
    -};
    -
    -
    -/**
    - * Sets the class name to use for selected menu items
    - * todo(user) - reevaluate if we can simulate pseudo classes in IE
    - *
    - * @param {string} name The class name to use for selected items.
    - */
    -goog.ui.AttachableMenu.prototype.setSelectedItemClassName = function(name) {
    -  this.selectedItemClassName_ = name;
    -};
    -
    -
    -/**
    - * Returns the selected item
    - *
    - * @return {Element} The item selected or null if no item is selected.
    - * @override
    - */
    -goog.ui.AttachableMenu.prototype.getSelectedItem = function() {
    -  return this.selectedElement_;
    -};
    -
    -
    -/** @override */
    -goog.ui.AttachableMenu.prototype.setSelectedItem = function(obj) {
    -  var elt = /** @type {Element} */ (obj);
    -  if (this.selectedElement_) {
    -    goog.dom.classlist.remove(this.selectedElement_,
    -        this.selectedItemClassName_);
    -  }
    -
    -  this.selectedElement_ = elt;
    -
    -  var el = this.getElement();
    -  goog.asserts.assert(el, 'The attachable menu DOM element cannot be null.');
    -  if (this.selectedElement_) {
    -    goog.dom.classlist.add(this.selectedElement_, this.selectedItemClassName_);
    -
    -    if (elt.id) {
    -      // Update activedescendant to reflect the new selection. ARIA roles for
    -      // menu and menuitem can be set statically (thru Soy templates, for
    -      // example) whereas this needs to be updated as the selection changes.
    -      goog.a11y.aria.setState(el, goog.a11y.aria.State.ACTIVEDESCENDANT,
    -          elt.id);
    -    }
    -
    -    var top = this.selectedElement_.offsetTop;
    -    var height = this.selectedElement_.offsetHeight;
    -    var scrollTop = el.scrollTop;
    -    var scrollHeight = el.offsetHeight;
    -
    -    // If the menu is scrollable this scrolls the selected item into view
    -    // (this has no effect when the menu doesn't scroll)
    -    if (top < scrollTop) {
    -      el.scrollTop = top;
    -    } else if (top + height > scrollTop + scrollHeight) {
    -      el.scrollTop = top + height - scrollHeight;
    -    }
    -  } else {
    -    // Clear off activedescendant to reflect no selection.
    -    goog.a11y.aria.setState(el, goog.a11y.aria.State.ACTIVEDESCENDANT, '');
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.AttachableMenu.prototype.showPopupElement = function() {
    -  // The scroll position cannot be set for hidden (display: none) elements in
    -  // gecko browsers.
    -  var el = /** @type {Element} */ (this.getElement());
    -  goog.style.setElementShown(el, true);
    -  el.scrollTop = 0;
    -  el.style.visibility = 'visible';
    -};
    -
    -
    -/**
    - * Called after the menu is shown.
    - * @protected
    - * @suppress {underscore|visibility}
    - * @override
    - */
    -goog.ui.AttachableMenu.prototype.onShow_ = function() {
    -  goog.ui.AttachableMenu.superClass_.onShow_.call(this);
    -
    -  // In IE, focusing the menu causes weird scrolling to happen. Focusing the
    -  // first child makes the scroll behavior better, and the key handling still
    -  // works. In FF, focusing the first child causes us to lose key events, so we
    -  // still focus the menu.
    -  var el = this.getElement();
    -  goog.userAgent.IE ? el.firstChild.focus() :
    -      el.focus();
    -};
    -
    -
    -/**
    - * Returns the next or previous item. Used for up/down arrows.
    - *
    - * @param {boolean} prev True to go to the previous element instead of next.
    - * @return {Element} The next or previous element.
    - * @protected
    - */
    -goog.ui.AttachableMenu.prototype.getNextPrevItem = function(prev) {
    -  // first find the index of the next element
    -  var elements = this.getElement().getElementsByTagName('*');
    -  var elementCount = elements.length;
    -  var index;
    -  // if there is a selected element, find its index and then inc/dec by one
    -  if (this.selectedElement_) {
    -    for (var i = 0; i < elementCount; i++) {
    -      if (elements[i] == this.selectedElement_) {
    -        index = prev ? i - 1 : i + 1;
    -        break;
    -      }
    -    }
    -  }
    -
    -  // if no selected element, start from beginning or end
    -  if (!goog.isDef(index)) {
    -    index = prev ? elementCount - 1 : 0;
    -  }
    -
    -  // iterate forward or backwards through the elements finding the next
    -  // menu item
    -  for (var i = 0; i < elementCount; i++) {
    -    var multiplier = prev ? -1 : 1;
    -    var nextIndex = index + (multiplier * i) % elementCount;
    -
    -    // if overflowed/underflowed, wrap around
    -    if (nextIndex < 0) {
    -      nextIndex += elementCount;
    -    } else if (nextIndex >= elementCount) {
    -      nextIndex -= elementCount;
    -    }
    -
    -    if (this.isMenuItem_(elements[nextIndex])) {
    -      return elements[nextIndex];
    -    }
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * Mouse over handler for the menu.
    - * @param {goog.events.Event} e The event object.
    - * @protected
    - * @override
    - */
    -goog.ui.AttachableMenu.prototype.onMouseOver = function(e) {
    -  var eltItem = this.getAncestorMenuItem_(/** @type {Element} */ (e.target));
    -  if (eltItem == null) {
    -    return;
    -  }
    -
    -  // Stop the keydown triggering a mouseover in FF.
    -  if (goog.now() - this.lastKeyDown_ > goog.ui.PopupBase.DEBOUNCE_DELAY_MS) {
    -    this.setSelectedItem(eltItem);
    -  }
    -};
    -
    -
    -/**
    - * Mouse out handler for the menu.
    - * @param {goog.events.Event} e The event object.
    - * @protected
    - * @override
    - */
    -goog.ui.AttachableMenu.prototype.onMouseOut = function(e) {
    -  var eltItem = this.getAncestorMenuItem_(/** @type {Element} */ (e.target));
    -  if (eltItem == null) {
    -    return;
    -  }
    -
    -  // Stop the keydown triggering a mouseout in FF.
    -  if (goog.now() - this.lastKeyDown_ > goog.ui.PopupBase.DEBOUNCE_DELAY_MS) {
    -    this.setSelectedItem(null);
    -  }
    -};
    -
    -
    -/**
    - * Mouse down handler for the menu. Prevents default to avoid text selection.
    - * @param {!goog.events.Event} e The event object.
    - * @protected
    - * @override
    - */
    -goog.ui.AttachableMenu.prototype.onMouseDown = goog.events.Event.preventDefault;
    -
    -
    -/**
    - * Mouse up handler for the menu.
    - * @param {goog.events.Event} e The event object.
    - * @protected
    - * @override
    - */
    -goog.ui.AttachableMenu.prototype.onMouseUp = function(e) {
    -  var eltItem = this.getAncestorMenuItem_(/** @type {Element} */ (e.target));
    -  if (eltItem == null) {
    -    return;
    -  }
    -  this.setVisible(false);
    -  this.onItemSelected_(eltItem);
    -};
    -
    -
    -/**
    - * Key down handler for the menu.
    - * @param {goog.events.KeyEvent} e The event object.
    - * @protected
    - * @override
    - */
    -goog.ui.AttachableMenu.prototype.onKeyDown = function(e) {
    -  switch (e.keyCode) {
    -    case goog.events.KeyCodes.DOWN:
    -      this.setSelectedItem(this.getNextPrevItem(false));
    -      this.lastKeyDown_ = goog.now();
    -      break;
    -    case goog.events.KeyCodes.UP:
    -      this.setSelectedItem(this.getNextPrevItem(true));
    -      this.lastKeyDown_ = goog.now();
    -      break;
    -    case goog.events.KeyCodes.ENTER:
    -      if (this.selectedElement_) {
    -        this.onItemSelected_();
    -        this.setVisible(false);
    -      }
    -      break;
    -    case goog.events.KeyCodes.ESC:
    -      this.setVisible(false);
    -      break;
    -    default:
    -      if (e.charCode) {
    -        var charStr = String.fromCharCode(e.charCode);
    -        this.selectByName_(charStr, 1, true);
    -      }
    -      break;
    -  }
    -  // Prevent the browser's default keydown behaviour when the menu is open,
    -  // e.g. keyboard scrolling.
    -  e.preventDefault();
    -
    -  // Stop propagation to prevent application level keyboard shortcuts from
    -  // firing.
    -  e.stopPropagation();
    -
    -  this.dispatchEvent(e);
    -};
    -
    -
    -/**
    - * Find an item that has the given prefix and select it.
    - *
    - * @param {string} prefix The entered prefix, so far.
    - * @param {number=} opt_direction 1 to search forward from the selection
    - *     (default), -1 to search backward (e.g. to go to the previous match).
    - * @param {boolean=} opt_skip True if should skip the current selection,
    - *     unless no other item has the given prefix.
    - * @private
    - */
    -goog.ui.AttachableMenu.prototype.selectByName_ =
    -    function(prefix, opt_direction, opt_skip) {
    -  var elements = this.getElement().getElementsByTagName('*');
    -  var elementCount = elements.length;
    -  var index;
    -
    -  if (elementCount == 0) {
    -    return;
    -  }
    -
    -  if (!this.selectedElement_ ||
    -      (index = goog.array.indexOf(elements, this.selectedElement_)) == -1) {
    -    // no selection or selection isn't known => start at the beginning
    -    index = 0;
    -  }
    -
    -  var start = index;
    -  var re = new RegExp('^' + goog.string.regExpEscape(prefix), 'i');
    -  var skip = opt_skip && this.selectedElement_;
    -  var dir = opt_direction || 1;
    -
    -  do {
    -    if (elements[index] != skip && this.isMenuItem_(elements[index])) {
    -      var name = goog.dom.getTextContent(elements[index]);
    -      if (name.match(re)) {
    -        break;
    -      }
    -    }
    -    index += dir;
    -    if (index == elementCount) {
    -      index = 0;
    -    } else if (index < 0) {
    -      index = elementCount - 1;
    -    }
    -  } while (index != start);
    -
    -  if (this.selectedElement_ != elements[index]) {
    -    this.setSelectedItem(elements[index]);
    -  }
    -};
    -
    -
    -/**
    - * Dispatch an ITEM_ACTION event when an item is selected
    - * @param {Object=} opt_item Item selected.
    - * @private
    - */
    -goog.ui.AttachableMenu.prototype.onItemSelected_ = function(opt_item) {
    -  this.dispatchEvent(new goog.ui.ItemEvent(goog.ui.MenuBase.Events.ITEM_ACTION,
    -      this, opt_item || this.selectedElement_));
    -};
    -
    -
    -/**
    - * Returns whether the specified element is a menu item.
    - * @param {Element} elt The element to find a menu item ancestor of.
    - * @return {boolean} Whether the specified element is a menu item.
    - * @private
    - */
    -goog.ui.AttachableMenu.prototype.isMenuItem_ = function(elt) {
    -  return !!elt && goog.dom.classlist.contains(elt, this.itemClassName_);
    -};
    -
    -
    -/**
    - * Returns the menu-item scoping the specified element, or null if there is
    - * none.
    - * @param {Element|undefined} elt The element to find a menu item ancestor of.
    - * @return {Element} The menu-item scoping the specified element, or null if
    - *     there is none.
    - * @private
    - */
    -goog.ui.AttachableMenu.prototype.getAncestorMenuItem_ = function(elt) {
    -  if (elt) {
    -    var ownerDocumentBody = goog.dom.getOwnerDocument(elt).body;
    -    while (elt != null && elt != ownerDocumentBody) {
    -      if (this.isMenuItem_(elt)) {
    -        return elt;
    -      }
    -      elt = /** @type {Element} */ (elt.parentNode);
    -    }
    -  }
    -  return null;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/bidiinput.js b/src/database/third_party/closure-library/closure/goog/ui/bidiinput.js
    deleted file mode 100644
    index 602a4343e48..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/bidiinput.js
    +++ /dev/null
    @@ -1,180 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Component for an input field with bidi direction automatic
    - * detection. The input element directionality is automatically set according
    - * to the contents (value) of the element.
    - *
    - * @see ../demos/bidiinput.html
    - */
    -
    -
    -goog.provide('goog.ui.BidiInput');
    -
    -
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.InputHandler');
    -goog.require('goog.i18n.bidi');
    -goog.require('goog.i18n.bidi.Dir');
    -goog.require('goog.ui.Component');
    -
    -
    -
    -/**
    - * Default implementation of BidiInput.
    - *
    - * @param {goog.dom.DomHelper=} opt_domHelper  Optional DOM helper.
    - * @constructor
    - * @extends {goog.ui.Component}
    - */
    -goog.ui.BidiInput = function(opt_domHelper) {
    -  goog.ui.Component.call(this, opt_domHelper);
    -};
    -goog.inherits(goog.ui.BidiInput, goog.ui.Component);
    -goog.tagUnsealableClass(goog.ui.BidiInput);
    -
    -
    -/**
    - * The input handler that provides the input event.
    - * @type {goog.events.InputHandler?}
    - * @private
    - */
    -goog.ui.BidiInput.prototype.inputHandler_ = null;
    -
    -
    -/**
    - * Decorates the given HTML element as a BidiInput. The HTML element can be an
    - * input element with type='text', a textarea element, or any contenteditable.
    - * Overrides {@link goog.ui.Component#decorateInternal}.  Considered protected.
    - * @param {Element} element  Element to decorate.
    - * @protected
    - * @override
    - */
    -goog.ui.BidiInput.prototype.decorateInternal = function(element) {
    -  goog.ui.BidiInput.superClass_.decorateInternal.call(this, element);
    -  this.init_();
    -};
    -
    -
    -/**
    - * Creates the element for the text input.
    - * @protected
    - * @override
    - */
    -goog.ui.BidiInput.prototype.createDom = function() {
    -  this.setElementInternal(
    -      this.getDomHelper().createDom('input', {'type': 'text'}));
    -  this.init_();
    -};
    -
    -
    -/**
    - * Initializes the events and initial text direction.
    - * Called from either decorate or createDom, after the input field has
    - * been created.
    - * @private
    - */
    -goog.ui.BidiInput.prototype.init_ = function() {
    -  // Set initial direction by current text
    -  this.setDirection_();
    -
    -  // Listen to value change events
    -  this.inputHandler_ = new goog.events.InputHandler(this.getElement());
    -  goog.events.listen(this.inputHandler_,
    -      goog.events.InputHandler.EventType.INPUT,
    -      this.setDirection_, false, this);
    -};
    -
    -
    -/**
    - * Set the direction of the input element based on the current value. If the
    - * value does not have any strongly directional characters, remove the dir
    - * attribute so that the direction is inherited instead.
    - * This method is called when the user changes the input element value, or
    - * when a program changes the value using
    - * {@link goog.ui.BidiInput#setValue}
    - * @private
    - */
    -goog.ui.BidiInput.prototype.setDirection_ = function() {
    -  var element = this.getElement();
    -  var text = this.getValue();
    -  switch (goog.i18n.bidi.estimateDirection(text)) {
    -    case (goog.i18n.bidi.Dir.LTR):
    -      element.dir = 'ltr';
    -      break;
    -    case (goog.i18n.bidi.Dir.RTL):
    -      element.dir = 'rtl';
    -      break;
    -    default:
    -      // Default for no direction, inherit from document.
    -      element.removeAttribute('dir');
    -  }
    -};
    -
    -
    -/**
    - * Returns the direction of the input element.
    - * @return {?string} Return 'rtl' for right-to-left text,
    - *     'ltr' for left-to-right text, or null if the value itself is not
    - *     enough to determine directionality (e.g. an empty value), and the
    - *     direction is inherited from a parent element (typically the body
    - *     element).
    - */
    -goog.ui.BidiInput.prototype.getDirection = function() {
    -  var dir = this.getElement().dir;
    -  if (dir == '') {
    -    dir = null;
    -  }
    -  return dir;
    -};
    -
    -
    -/**
    - * Sets the value of the underlying input field, and sets the direction
    - * according to the given value.
    - * @param {string} value  The Value to set in the underlying input field.
    - */
    -goog.ui.BidiInput.prototype.setValue = function(value) {
    -  var element = this.getElement();
    -  if (goog.isDefAndNotNull(element.value)) {
    -    element.value = value;
    -  } else {
    -    goog.dom.setTextContent(element, value);
    -  }
    -  this.setDirection_();
    -};
    -
    -
    -/**
    - * Returns the value of the underlying input field.
    - * @return {string} Value of the underlying input field.
    - */
    -goog.ui.BidiInput.prototype.getValue = function() {
    -  var element = this.getElement();
    -  return goog.isDefAndNotNull(element.value) ? element.value :
    -      goog.dom.getRawTextContent(element);
    -};
    -
    -
    -/** @override */
    -goog.ui.BidiInput.prototype.disposeInternal = function() {
    -  if (this.inputHandler_) {
    -    goog.events.removeAll(this.inputHandler_);
    -    this.inputHandler_.dispose();
    -    this.inputHandler_ = null;
    -    goog.ui.BidiInput.superClass_.disposeInternal.call(this);
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/bidiinput_test.html b/src/database/third_party/closure-library/closure/goog/ui/bidiinput_test.html
    deleted file mode 100644
    index 13999f16516..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/bidiinput_test.html
    +++ /dev/null
    @@ -1,31 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.BidiInput
    -  </title>
    -  <script type="text/javascript" src="../base.js">
    -  </script>
    -  <script type="text/javascript">
    -   goog.require('goog.ui.BidiInputTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="textDiv">
    -   <input type="text" id="emptyText" value="" />
    -   <input type="text" id="bidiText" value="hello, world!" />
    -   <div id="bidiTextDiv" contenteditable="true">
    -    hello,world!
    -   </div>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/bidiinput_test.js b/src/database/third_party/closure-library/closure/goog/ui/bidiinput_test.js
    deleted file mode 100644
    index ae6d1eecbb3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/bidiinput_test.js
    +++ /dev/null
    @@ -1,122 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.BidiInputTest');
    -goog.setTestOnly('goog.ui.BidiInputTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.BidiInput');
    -
    -function setUp() {
    -  document.body.focus();
    -}
    -
    -function tearDown() {
    -  document.getElementById('emptyText').value = '';
    -  document.getElementById('bidiText').value = 'hello, world!';
    -}
    -
    -function testEmptyInput() {
    -  var bidiInput = new goog.ui.BidiInput();
    -  var emptyText = goog.dom.getElement('emptyText');
    -  bidiInput.decorate(emptyText);
    -  assertEquals('', bidiInput.getValue());
    -  bidiInput.setValue('hello!');
    -  assertEquals('hello!', bidiInput.getValue());
    -}
    -
    -function testSetDirection() {
    -  var shalomInHebrew = '\u05e9\u05dc\u05d5\u05dd';
    -  var isAGoodLanguageInHebrew =
    -      '\u05d4\u05d9\u05d0 \u05e9\u05e4\u05d4 \u05d8\u05d5\u05d1\u05d4';
    -  var learnInHebrew = '\u05dc\u05de\u05d3';
    -
    -  var bidiInput = new goog.ui.BidiInput();
    -  var bidiText = goog.dom.getElement('bidiText');
    -  bidiInput.decorate(bidiText);
    -  assertEquals('ltr', bidiInput.getDirection());
    -
    -  bidiInput.setValue(shalomInHebrew);
    -  assertEquals('rtl', bidiInput.getDirection());
    -
    -  bidiInput.setValue('hello!');
    -  assertEquals('ltr', bidiInput.getDirection());
    -
    -  bidiInput.setValue(':) , ? ! ' + shalomInHebrew);
    -  assertEquals('rtl', bidiInput.getDirection());
    -
    -  bidiInput.setValue(':) , ? ! hello!');
    -  assertEquals('ltr', bidiInput.getDirection());
    -
    -  bidiInput.setValue('   ;)   ');
    -  assertEquals(null, bidiInput.getDirection());
    -
    -  bidiInput.setValue(shalomInHebrew + ', how are you today?');
    -  assertEquals('ltr', bidiInput.getDirection());
    -
    -  bidiInput.setValue('Hello is ' + shalomInHebrew + ' in Hebrew');
    -  assertEquals('ltr', bidiInput.getDirection());
    -
    -  bidiInput.setValue('JavaScript ' + isAGoodLanguageInHebrew);
    -  assertEquals('rtl', bidiInput.getDirection());
    -
    -  bidiInput.setValue(learnInHebrew + ' JavaScript');
    -  assertEquals('rtl', bidiInput.getDirection());
    -
    -  bidiInput.setValue('');
    -  assertEquals(null, bidiInput.getDirection());
    -}
    -
    -function testSetDirection_inContenteditableDiv() {
    -  var shalomInHebrew = '\u05e9\u05dc\u05d5\u05dd';
    -  var isAGoodLanguageInHebrew =
    -      '\u05d4\u05d9\u05d0 \u05e9\u05e4\u05d4 \u05d8\u05d5\u05d1\u05d4';
    -  var learnInHebrew = '\u05dc\u05de\u05d3';
    -
    -  var bidiInput = new goog.ui.BidiInput();
    -  var bidiTextDiv = goog.dom.getElement('bidiTextDiv');
    -  bidiInput.decorate(bidiTextDiv);
    -  assertEquals('ltr', bidiInput.getDirection());
    -
    -  bidiInput.setValue(shalomInHebrew);
    -  assertEquals('rtl', bidiInput.getDirection());
    -
    -  bidiInput.setValue('hello!');
    -  assertEquals('ltr', bidiInput.getDirection());
    -
    -  bidiInput.setValue(':) , ? ! ' + shalomInHebrew);
    -  assertEquals('rtl', bidiInput.getDirection());
    -
    -  bidiInput.setValue(':) , ? ! hello!');
    -  assertEquals('ltr', bidiInput.getDirection());
    -
    -  bidiInput.setValue('   ;)   ');
    -  assertEquals(null, bidiInput.getDirection());
    -
    -  bidiInput.setValue(shalomInHebrew + ', how are you today?');
    -  assertEquals('ltr', bidiInput.getDirection());
    -
    -  bidiInput.setValue('Hello is ' + shalomInHebrew + ' in Hebrew');
    -  assertEquals('ltr', bidiInput.getDirection());
    -
    -  bidiInput.setValue('JavaScript ' + isAGoodLanguageInHebrew);
    -  assertEquals('rtl', bidiInput.getDirection());
    -
    -  bidiInput.setValue(learnInHebrew + ' JavaScript');
    -  assertEquals('rtl', bidiInput.getDirection());
    -
    -  bidiInput.setValue('');
    -  assertEquals(null, bidiInput.getDirection());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/bubble.js b/src/database/third_party/closure-library/closure/goog/ui/bubble.js
    deleted file mode 100644
    index 64d910303c5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/bubble.js
    +++ /dev/null
    @@ -1,490 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Definition of the Bubble class.
    - *
    - *
    - * @see ../demos/bubble.html
    - *
    - * TODO: support decoration and addChild
    - */
    -
    -goog.provide('goog.ui.Bubble');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.dom.safe');
    -goog.require('goog.events');
    -goog.require('goog.events.EventType');
    -goog.require('goog.html.SafeHtml');
    -goog.require('goog.html.legacyconversions');
    -goog.require('goog.math.Box');
    -goog.require('goog.positioning');
    -goog.require('goog.positioning.AbsolutePosition');
    -goog.require('goog.positioning.AnchoredPosition');
    -goog.require('goog.positioning.Corner');
    -goog.require('goog.positioning.CornerBit');
    -goog.require('goog.string.Const');
    -goog.require('goog.style');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.Popup');
    -
    -
    -goog.scope(function() {
    -var SafeHtml = goog.html.SafeHtml;
    -
    -
    -
    -/**
    - * The Bubble provides a general purpose bubble implementation that can be
    - * anchored to a particular element and displayed for a period of time.
    - *
    - * @param {string|!goog.html.SafeHtml|Element} message HTML or an element
    - *     to display inside the bubble. If possible pass a SafeHtml; string
    - *     is supported for backwards-compatibility only and uses
    - *     goog.html.legacyconversions.
    - * @param {Object=} opt_config The configuration
    - *     for the bubble. If not specified, the default configuration will be
    - *     used. {@see goog.ui.Bubble.defaultConfig}.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @constructor
    - * @extends {goog.ui.Component}
    - */
    -goog.ui.Bubble = function(message, opt_config, opt_domHelper) {
    -  goog.ui.Component.call(this, opt_domHelper);
    -
    -  if (goog.isString(message)) {
    -    message = goog.html.legacyconversions.safeHtmlFromString(message);
    -  }
    -
    -  /**
    -   * The HTML string or element to display inside the bubble.
    -   *
    -   * @type {!goog.html.SafeHtml|Element}
    -   * @private
    -   */
    -  this.message_ = message;
    -
    -  /**
    -   * The Popup element used to position and display the bubble.
    -   *
    -   * @type {goog.ui.Popup}
    -   * @private
    -   */
    -  this.popup_ = new goog.ui.Popup();
    -
    -  /**
    -   * Configuration map that contains bubble's UI elements.
    -   *
    -   * @type {Object}
    -   * @private
    -   */
    -  this.config_ = opt_config || goog.ui.Bubble.defaultConfig;
    -
    -  /**
    -   * Id of the close button for this bubble.
    -   *
    -   * @type {string}
    -   * @private
    -   */
    -  this.closeButtonId_ = this.makeId('cb');
    -
    -  /**
    -   * Id of the div for the embedded element.
    -   *
    -   * @type {string}
    -   * @private
    -   */
    -  this.messageId_ = this.makeId('mi');
    -
    -};
    -goog.inherits(goog.ui.Bubble, goog.ui.Component);
    -goog.tagUnsealableClass(goog.ui.Bubble);
    -
    -
    -/**
    - * In milliseconds, timeout after which the button auto-hides. Null means
    - * infinite.
    - * @type {?number}
    - * @private
    - */
    -goog.ui.Bubble.prototype.timeout_ = null;
    -
    -
    -/**
    - * Key returned by the bubble timer.
    - * @type {?number}
    - * @private
    - */
    -goog.ui.Bubble.prototype.timerId_ = 0;
    -
    -
    -/**
    - * Key returned by the listen function for the close button.
    - * @type {goog.events.Key}
    - * @private
    - */
    -goog.ui.Bubble.prototype.listener_ = null;
    -
    -
    -
    -/** @override */
    -goog.ui.Bubble.prototype.createDom = function() {
    -  goog.ui.Bubble.superClass_.createDom.call(this);
    -
    -  var element = this.getElement();
    -  element.style.position = 'absolute';
    -  element.style.visibility = 'hidden';
    -
    -  this.popup_.setElement(element);
    -};
    -
    -
    -/**
    - * Attaches the bubble to an anchor element. Computes the positioning and
    - * orientation of the bubble.
    - *
    - * @param {Element} anchorElement The element to which we are attaching.
    - */
    -goog.ui.Bubble.prototype.attach = function(anchorElement) {
    -  this.setAnchoredPosition_(
    -      anchorElement, this.computePinnedCorner_(anchorElement));
    -};
    -
    -
    -/**
    - * Sets the corner of the bubble to used in the positioning algorithm.
    - *
    - * @param {goog.positioning.Corner} corner The bubble corner used for
    - *     positioning constants.
    - */
    -goog.ui.Bubble.prototype.setPinnedCorner = function(corner) {
    -  this.popup_.setPinnedCorner(corner);
    -};
    -
    -
    -/**
    - * Sets the position of the bubble. Pass null for corner in AnchoredPosition
    - * for corner to be computed automatically.
    - *
    - * @param {goog.positioning.AbstractPosition} position The position of the
    - *     bubble.
    - */
    -goog.ui.Bubble.prototype.setPosition = function(position) {
    -  if (position instanceof goog.positioning.AbsolutePosition) {
    -    this.popup_.setPosition(position);
    -  } else if (position instanceof goog.positioning.AnchoredPosition) {
    -    this.setAnchoredPosition_(position.element, position.corner);
    -  } else {
    -    throw Error('Bubble only supports absolute and anchored positions!');
    -  }
    -};
    -
    -
    -/**
    - * Sets the timeout after which bubble hides itself.
    - *
    - * @param {number} timeout Timeout of the bubble.
    - */
    -goog.ui.Bubble.prototype.setTimeout = function(timeout) {
    -  this.timeout_ = timeout;
    -};
    -
    -
    -/**
    - * Sets whether the bubble should be automatically hidden whenever user clicks
    - * outside the bubble element.
    - *
    - * @param {boolean} autoHide Whether to hide if user clicks outside the bubble.
    - */
    -goog.ui.Bubble.prototype.setAutoHide = function(autoHide) {
    -  this.popup_.setAutoHide(autoHide);
    -};
    -
    -
    -/**
    - * Sets whether the bubble should be visible.
    - *
    - * @param {boolean} visible Desired visibility state.
    - */
    -goog.ui.Bubble.prototype.setVisible = function(visible) {
    -  if (visible && !this.popup_.isVisible()) {
    -    this.configureElement_();
    -  }
    -  this.popup_.setVisible(visible);
    -  if (!this.popup_.isVisible()) {
    -    this.unconfigureElement_();
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the bubble is visible.
    - */
    -goog.ui.Bubble.prototype.isVisible = function() {
    -  return this.popup_.isVisible();
    -};
    -
    -
    -/** @override */
    -goog.ui.Bubble.prototype.disposeInternal = function() {
    -  this.unconfigureElement_();
    -  this.popup_.dispose();
    -  this.popup_ = null;
    -  goog.ui.Bubble.superClass_.disposeInternal.call(this);
    -};
    -
    -
    -/**
    - * Creates element's contents and configures all timers. This is called on
    - * setVisible(true).
    - * @private
    - */
    -goog.ui.Bubble.prototype.configureElement_ = function() {
    -  if (!this.isInDocument()) {
    -    throw Error('You must render the bubble before showing it!');
    -  }
    -
    -  var element = this.getElement();
    -  var corner = this.popup_.getPinnedCorner();
    -  goog.dom.safe.setInnerHtml(/** @type {!Element} */ (element),
    -      this.computeHtmlForCorner_(corner));
    -
    -  if (!(this.message_ instanceof SafeHtml)) {
    -    var messageDiv = this.getDomHelper().getElement(this.messageId_);
    -    this.getDomHelper().appendChild(messageDiv, this.message_);
    -  }
    -  var closeButton = this.getDomHelper().getElement(this.closeButtonId_);
    -  this.listener_ = goog.events.listen(closeButton,
    -      goog.events.EventType.CLICK, this.hideBubble_, false, this);
    -
    -  if (this.timeout_) {
    -    this.timerId_ = goog.Timer.callOnce(this.hideBubble_, this.timeout_, this);
    -  }
    -};
    -
    -
    -/**
    - * Gets rid of the element's contents and all assoicated timers and listeners.
    - * This is called on dispose as well as on setVisible(false).
    - * @private
    - */
    -goog.ui.Bubble.prototype.unconfigureElement_ = function() {
    -  if (this.listener_) {
    -    goog.events.unlistenByKey(this.listener_);
    -    this.listener_ = null;
    -  }
    -  if (this.timerId_) {
    -    goog.Timer.clear(this.timerId_);
    -    this.timerId_ = null;
    -  }
    -
    -  var element = this.getElement();
    -  if (element) {
    -    this.getDomHelper().removeChildren(element);
    -    goog.dom.safe.setInnerHtml(element, goog.html.SafeHtml.EMPTY);
    -  }
    -};
    -
    -
    -/**
    - * Computes bubble position based on anchored element.
    - *
    - * @param {Element} anchorElement The element to which we are attaching.
    - * @param {goog.positioning.Corner} corner The bubble corner used for
    - *     positioning.
    - * @private
    - */
    -goog.ui.Bubble.prototype.setAnchoredPosition_ = function(anchorElement,
    -    corner) {
    -  this.popup_.setPinnedCorner(corner);
    -  var margin = this.createMarginForCorner_(corner);
    -  this.popup_.setMargin(margin);
    -  var anchorCorner = goog.positioning.flipCorner(corner);
    -  this.popup_.setPosition(new goog.positioning.AnchoredPosition(
    -      anchorElement, anchorCorner));
    -};
    -
    -
    -/**
    - * Hides the bubble. This is called asynchronously by timer of event processor
    - * for the mouse click on the close button.
    - * @private
    - */
    -goog.ui.Bubble.prototype.hideBubble_ = function() {
    -  this.setVisible(false);
    -};
    -
    -
    -/**
    - * Returns an AnchoredPosition that will position the bubble optimally
    - * given the position of the anchor element and the size of the viewport.
    - *
    - * @param {Element} anchorElement The element to which the bubble is attached.
    - * @return {!goog.positioning.AnchoredPosition} The AnchoredPosition
    - *     to give to {@link #setPosition}.
    - */
    -goog.ui.Bubble.prototype.getComputedAnchoredPosition = function(anchorElement) {
    -  return new goog.positioning.AnchoredPosition(
    -      anchorElement, this.computePinnedCorner_(anchorElement));
    -};
    -
    -
    -/**
    - * Computes the pinned corner for the bubble.
    - *
    - * @param {Element} anchorElement The element to which the button is attached.
    - * @return {goog.positioning.Corner} The pinned corner.
    - * @private
    - */
    -goog.ui.Bubble.prototype.computePinnedCorner_ = function(anchorElement) {
    -  var doc = this.getDomHelper().getOwnerDocument(anchorElement);
    -  var viewportElement = goog.style.getClientViewportElement(doc);
    -  var viewportWidth = viewportElement.offsetWidth;
    -  var viewportHeight = viewportElement.offsetHeight;
    -  var anchorElementOffset = goog.style.getPageOffset(anchorElement);
    -  var anchorElementSize = goog.style.getSize(anchorElement);
    -  var anchorType = 0;
    -  // right margin or left?
    -  if (viewportWidth - anchorElementOffset.x - anchorElementSize.width >
    -      anchorElementOffset.x) {
    -    anchorType += 1;
    -  }
    -  // attaches to the top or to the bottom?
    -  if (viewportHeight - anchorElementOffset.y - anchorElementSize.height >
    -      anchorElementOffset.y) {
    -    anchorType += 2;
    -  }
    -  return goog.ui.Bubble.corners_[anchorType];
    -};
    -
    -
    -/**
    - * Computes the right offset for a given bubble corner
    - * and creates a margin element for it. This is done to have the
    - * button anchor element on its frame rather than on the corner.
    - *
    - * @param {goog.positioning.Corner} corner The corner.
    - * @return {!goog.math.Box} the computed margin. Only left or right fields are
    - *     non-zero, but they may be negative.
    - * @private
    - */
    -goog.ui.Bubble.prototype.createMarginForCorner_ = function(corner) {
    -  var margin = new goog.math.Box(0, 0, 0, 0);
    -  if (corner & goog.positioning.CornerBit.RIGHT) {
    -    margin.right -= this.config_.marginShift;
    -  } else {
    -    margin.left -= this.config_.marginShift;
    -  }
    -  return margin;
    -};
    -
    -
    -/**
    - * Computes the HTML string for a given bubble orientation.
    - *
    - * @param {goog.positioning.Corner} corner The corner.
    - * @return {!goog.html.SafeHtml} The HTML string to place inside the
    - *     bubble's popup.
    - * @private
    - */
    -goog.ui.Bubble.prototype.computeHtmlForCorner_ = function(corner) {
    -  var bubbleTopClass;
    -  var bubbleBottomClass;
    -  switch (corner) {
    -    case goog.positioning.Corner.TOP_LEFT:
    -      bubbleTopClass = this.config_.cssBubbleTopLeftAnchor;
    -      bubbleBottomClass = this.config_.cssBubbleBottomNoAnchor;
    -      break;
    -    case goog.positioning.Corner.TOP_RIGHT:
    -      bubbleTopClass = this.config_.cssBubbleTopRightAnchor;
    -      bubbleBottomClass = this.config_.cssBubbleBottomNoAnchor;
    -      break;
    -    case goog.positioning.Corner.BOTTOM_LEFT:
    -      bubbleTopClass = this.config_.cssBubbleTopNoAnchor;
    -      bubbleBottomClass = this.config_.cssBubbleBottomLeftAnchor;
    -      break;
    -    case goog.positioning.Corner.BOTTOM_RIGHT:
    -      bubbleTopClass = this.config_.cssBubbleTopNoAnchor;
    -      bubbleBottomClass = this.config_.cssBubbleBottomRightAnchor;
    -      break;
    -    default:
    -      throw Error('This corner type is not supported by bubble!');
    -  }
    -  var message = null;
    -  if (this.message_ instanceof SafeHtml) {
    -    message = this.message_;
    -  } else {
    -    message = SafeHtml.create('div', {'id': this.messageId_});
    -  }
    -
    -  var tableRows = goog.html.SafeHtml.concat(
    -      SafeHtml.create('tr', {},
    -          SafeHtml.create('td', {'colspan': 4, 'class': bubbleTopClass})),
    -      SafeHtml.create('tr', {}, SafeHtml.concat(
    -          SafeHtml.create('td', {'class': this.config_.cssBubbleLeft }),
    -          SafeHtml.create('td',
    -              {'class': this.config_.cssBubbleFont, 'style':
    -                goog.string.Const.from('padding:0 4px;background:white')},
    -              message),
    -          SafeHtml.create('td',
    -              {'id': this.closeButtonId_,
    -                'class': this.config_.cssCloseButton }),
    -          SafeHtml.create('td', {'class': this.config_.cssBubbleRight }))),
    -      SafeHtml.create('tr', {},
    -          SafeHtml.create('td', {'colspan': 4, 'class': bubbleBottomClass})));
    -
    -  return SafeHtml.create('table',
    -      {'border': 0, 'cellspacing': 0, 'cellpadding': 0,
    -        'width': this.config_.bubbleWidth,
    -        'style': goog.string.Const.from('z-index:1')},
    -      tableRows);
    -};
    -
    -
    -/**
    - * A default configuration for the bubble.
    - *
    - * @type {Object}
    - */
    -goog.ui.Bubble.defaultConfig = {
    -  bubbleWidth: 147,
    -  marginShift: 60,
    -  cssBubbleFont: goog.getCssName('goog-bubble-font'),
    -  cssCloseButton: goog.getCssName('goog-bubble-close-button'),
    -  cssBubbleTopRightAnchor: goog.getCssName('goog-bubble-top-right-anchor'),
    -  cssBubbleTopLeftAnchor: goog.getCssName('goog-bubble-top-left-anchor'),
    -  cssBubbleTopNoAnchor: goog.getCssName('goog-bubble-top-no-anchor'),
    -  cssBubbleBottomRightAnchor:
    -      goog.getCssName('goog-bubble-bottom-right-anchor'),
    -  cssBubbleBottomLeftAnchor: goog.getCssName('goog-bubble-bottom-left-anchor'),
    -  cssBubbleBottomNoAnchor: goog.getCssName('goog-bubble-bottom-no-anchor'),
    -  cssBubbleLeft: goog.getCssName('goog-bubble-left'),
    -  cssBubbleRight: goog.getCssName('goog-bubble-right')
    -};
    -
    -
    -/**
    - * An auxiliary array optimizing the corner computation.
    - *
    - * @type {Array<goog.positioning.Corner>}
    - * @private
    - */
    -goog.ui.Bubble.corners_ = [
    -  goog.positioning.Corner.BOTTOM_RIGHT,
    -  goog.positioning.Corner.BOTTOM_LEFT,
    -  goog.positioning.Corner.TOP_RIGHT,
    -  goog.positioning.Corner.TOP_LEFT
    -];
    -});  // goog.scope
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/button.js b/src/database/third_party/closure-library/closure/goog/ui/button.js
    deleted file mode 100644
    index 08cf69c1331..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/button.js
    +++ /dev/null
    @@ -1,214 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A button control. This implementation extends {@link
    - * goog.ui.Control}.
    - *
    - * @author attila@google.com (Attila Bodis)
    - * @see ../demos/button.html
    - */
    -
    -goog.provide('goog.ui.Button');
    -goog.provide('goog.ui.Button.Side');
    -
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.events.KeyHandler');
    -goog.require('goog.ui.ButtonRenderer');
    -goog.require('goog.ui.ButtonSide');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.Control');
    -goog.require('goog.ui.NativeButtonRenderer');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * A button control, rendered as a native browser button by default.
    - *
    - * @param {goog.ui.ControlContent=} opt_content Text caption or existing DOM
    - *     structure to display as the button's caption (if any).
    - * @param {goog.ui.ButtonRenderer=} opt_renderer Renderer used to render or
    - *     decorate the button; defaults to {@link goog.ui.NativeButtonRenderer}.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @constructor
    - * @extends {goog.ui.Control}
    - */
    -goog.ui.Button = function(opt_content, opt_renderer, opt_domHelper) {
    -  goog.ui.Control.call(this, opt_content, opt_renderer ||
    -      goog.ui.NativeButtonRenderer.getInstance(), opt_domHelper);
    -};
    -goog.inherits(goog.ui.Button, goog.ui.Control);
    -goog.tagUnsealableClass(goog.ui.Button);
    -
    -
    -/**
    - * Constants for button sides, see {@link goog.ui.Button.prototype.setCollapsed}
    - * for details. Aliased from goog.ui.ButtonSide to support legacy users without
    - * creating a circular dependency in {@link goog.ui.ButtonRenderer}.
    - * @enum {number}
    - * @deprecated use {@link goog.ui.ButtonSide} instead.
    - */
    -goog.ui.Button.Side = goog.ui.ButtonSide;
    -
    -
    -/**
    - * Value associated with the button.
    - * @type {*}
    - * @private
    - */
    -goog.ui.Button.prototype.value_;
    -
    -
    -/**
    - * Tooltip text for the button, displayed on hover.
    - * @type {string|undefined}
    - * @private
    - */
    -goog.ui.Button.prototype.tooltip_;
    -
    -
    -// goog.ui.Button API implementation.
    -
    -
    -/**
    - * Returns the value associated with the button.
    - * @return {*} Button value (undefined if none).
    - */
    -goog.ui.Button.prototype.getValue = function() {
    -  return this.value_;
    -};
    -
    -
    -/**
    - * Sets the value associated with the button, and updates its DOM.
    - * @param {*} value New button value.
    - */
    -goog.ui.Button.prototype.setValue = function(value) {
    -  this.value_ = value;
    -  var renderer = /** @type {!goog.ui.ButtonRenderer} */ (this.getRenderer());
    -  renderer.setValue(this.getElement(), /** @type {string} */ (value));
    -};
    -
    -
    -/**
    - * Sets the value associated with the button.  Unlike {@link #setValue},
    - * doesn't update the button's DOM.  Considered protected; to be called only
    - * by renderer code during element decoration.
    - * @param {*} value New button value.
    - * @protected
    - */
    -goog.ui.Button.prototype.setValueInternal = function(value) {
    -  this.value_ = value;
    -};
    -
    -
    -/**
    - * Returns the tooltip for the button.
    - * @return {string|undefined} Tooltip text (undefined if none).
    - */
    -goog.ui.Button.prototype.getTooltip = function() {
    -  return this.tooltip_;
    -};
    -
    -
    -/**
    - * Sets the tooltip for the button, and updates its DOM.
    - * @param {string} tooltip New tooltip text.
    - */
    -goog.ui.Button.prototype.setTooltip = function(tooltip) {
    -  this.tooltip_ = tooltip;
    -  this.getRenderer().setTooltip(this.getElement(), tooltip);
    -};
    -
    -
    -/**
    - * Sets the tooltip for the button.  Unlike {@link #setTooltip}, doesn't update
    - * the button's DOM.  Considered protected; to be called only by renderer code
    - * during element decoration.
    - * @param {string} tooltip New tooltip text.
    - * @protected
    - */
    -goog.ui.Button.prototype.setTooltipInternal = function(tooltip) {
    -  this.tooltip_ = tooltip;
    -};
    -
    -
    -/**
    - * Collapses the border on one or both sides of the button, allowing it to be
    - * combined with the adjancent button(s), forming a single UI componenet with
    - * multiple targets.
    - * @param {number} sides Bitmap of one or more {@link goog.ui.ButtonSide}s for
    - *     which borders should be collapsed.
    - */
    -goog.ui.Button.prototype.setCollapsed = function(sides) {
    -  this.getRenderer().setCollapsed(this, sides);
    -};
    -
    -
    -// goog.ui.Control & goog.ui.Component API implementation.
    -
    -
    -/** @override */
    -goog.ui.Button.prototype.disposeInternal = function() {
    -  goog.ui.Button.superClass_.disposeInternal.call(this);
    -  delete this.value_;
    -  delete this.tooltip_;
    -};
    -
    -
    -/** @override */
    -goog.ui.Button.prototype.enterDocument = function() {
    -  goog.ui.Button.superClass_.enterDocument.call(this);
    -  if (this.isSupportedState(goog.ui.Component.State.FOCUSED)) {
    -    var keyTarget = this.getKeyEventTarget();
    -    if (keyTarget) {
    -      this.getHandler().listen(keyTarget, goog.events.EventType.KEYUP,
    -          this.handleKeyEventInternal);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Attempts to handle a keyboard event; returns true if the event was handled,
    - * false otherwise.  If the button is enabled and the Enter/Space key was
    - * pressed, handles the event by dispatching an {@code ACTION} event,
    - * and returns true. Overrides {@link goog.ui.Control#handleKeyEventInternal}.
    - * @param {goog.events.KeyEvent} e Key event to handle.
    - * @return {boolean} Whether the key event was handled.
    - * @protected
    - * @override
    - */
    -goog.ui.Button.prototype.handleKeyEventInternal = function(e) {
    -  if (e.keyCode == goog.events.KeyCodes.ENTER &&
    -      e.type == goog.events.KeyHandler.EventType.KEY ||
    -      e.keyCode == goog.events.KeyCodes.SPACE &&
    -      e.type == goog.events.EventType.KEYUP) {
    -    return this.performActionInternal(e);
    -  }
    -  // Return true for space keypress (even though the event is handled on keyup)
    -  // as preventDefault needs to be called up keypress to take effect in IE and
    -  // WebKit.
    -  return e.keyCode == goog.events.KeyCodes.SPACE;
    -};
    -
    -
    -// Register a decorator factory function for goog.ui.Buttons.
    -goog.ui.registry.setDecoratorByClassName(goog.ui.ButtonRenderer.CSS_CLASS,
    -    function() {
    -      return new goog.ui.Button(null);
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/button_perf.html b/src/database/third_party/closure-library/closure/goog/ui/button_perf.html
    deleted file mode 100644
    index 859b47de340..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/button_perf.html
    +++ /dev/null
    @@ -1,176 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -Author:  attila@google.com (Attila Bodis)
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -  <title>Closure Performance Tests - goog.ui.Button</title>
    -  <link rel="stylesheet" type="text/css" href="../testing/performancetable.css" />
    -  <script src="../base.js"></script>
    -  <script>
    -    goog.require('goog.dom');
    -    goog.require('goog.events');
    -    goog.require('goog.events.EventHandler');
    -    goog.require('goog.events.EventType');
    -    goog.require('goog.testing.PerformanceTable');
    -    goog.require('goog.testing.jsunit');
    -    goog.require('goog.ui.Button');
    -  </script>
    -</head>
    -<body>
    -  <h1>goog.ui.Button Performance Tests</h1>
    -  <p>
    -    <b>User-agent:</b> <script>document.write(navigator.userAgent);</script>
    -  </p>
    -  <div id="perfTable"></div>
    -  <hr>
    -  <div id="renderSandbox"></div>
    -  <div id="decorateSandbox"></div>
    -  <script>
    -    // The sandboxen.
    -    var renderSandbox = goog.dom.getElement('renderSandbox');
    -    var decorateSandbox = goog.dom.getElement('decorateSandbox');
    -
    -    // Arrays of rendered/decorated buttons (so we can dispose of them).
    -    var renderedButtons;
    -    var decoratedButtons;
    -
    -    // 0-based index of the button currently being rendered/decorated.
    -    var renderIndex;
    -    var decorateIndex;
    -
    -    // Element currently being decorated.
    -    var elementToDecorate;
    -
    -    // Number of buttons to create/decorate per test run.
    -    var SAMPLES_PER_RUN = 200;
    -
    -    // The performance table.
    -    var table;
    -
    -    function setUpPage() {
    -      table = new goog.testing.PerformanceTable(
    -          goog.dom.getElement('perfTable'));
    -    }
    -
    -    // Sets up a render test.
    -    function setUpRenderTest() {
    -      renderedButtons = [];
    -      renderIndex = 0;
    -    }
    -
    -    // Cleans up after a render test.
    -    function cleanUpAfterRenderTest() {
    -      for (var i = 0, count = renderedButtons.length; i < count; i++) {
    -        renderedButtons[i].dispose();
    -      }
    -      renderedButtons = null;
    -      goog.dom.removeChildren(renderSandbox);
    -    }
    -
    -    // Sets up a decorate test.
    -    function setUpDecorateTest(opt_count) {
    -      var count = opt_count || 1000;
    -      for (var i = 0; i < count; i++) {
    -        decorateSandbox.appendChild(goog.dom.createDom('button', 'goog-button',
    -            'W00t!'));
    -      }
    -      elementToDecorate = decorateSandbox.firstChild;
    -      decoratedButtons = [];
    -      decorateIndex = 0;
    -    }
    -
    -    // Cleans up after a decorate test.
    -    function cleanUpAfterDecorateTest() {
    -      for (var i = 0, count = decoratedButtons.length; i < count; i++) {
    -        decoratedButtons[i].dispose();
    -      }
    -      decoratedButtons = null;
    -      goog.dom.removeChildren(decorateSandbox);
    -    }
    -
    -    // Renders the given number of buttons.  Since children are appended to
    -    // the same parent element in each performance test run, we keep track of
    -    // the current index via the global renderIndex variable.
    -    function renderButtons(count, autoDetectBiDi) {
    -      for (var i = 0; i < count; i++) {
    -        var button = new goog.ui.Button('W00t!');
    -        if (!autoDetectBiDi) {
    -          button.setRightToLeft(false);
    -        }
    -        button.render(renderSandbox);
    -        renderedButtons[renderIndex++] = button;
    -      }
    -    }
    -
    -    // Decorates "count" buttons.  The decorate sandbox contains enough child
    -    // elements for the whole test, but we only decorate up to "count" elements
    -    // per test run, so we need to keep track of where we are via the global
    -    // decorateIndex and elementToDecorate variables.
    -    function decorateButtons(count, autoDetectBiDi) {
    -      for (var i = 0; i < count; i++) {
    -        var next = elementToDecorate.nextSibling;
    -        var button = new goog.ui.Button();
    -        if (!autoDetectBiDi) {
    -          button.setRightToLeft(false);
    -        }
    -        button.decorate(elementToDecorate);
    -        decoratedButtons[decorateIndex++] = button;
    -        elementToDecorate = next;
    -      }
    -    }
    -
    -    function testRender() {
    -      setUpRenderTest();
    -      table.run(
    -          goog.partial(renderButtons, SAMPLES_PER_RUN, true),
    -          'Render ' + SAMPLES_PER_RUN + ' buttons (default)');
    -      cleanUpAfterRenderTest();
    -      assertEquals('The expected number of buttons must have been rendered',
    -          SAMPLES_PER_RUN * table.getTimer().getNumSamples(), renderIndex);
    -    }
    -
    -    function testDecorate() {
    -      setUpDecorateTest(SAMPLES_PER_RUN * table.getTimer().getNumSamples());
    -      table.run(
    -          goog.partial(decorateButtons, SAMPLES_PER_RUN, true),
    -          'Decorate ' + SAMPLES_PER_RUN + ' buttons (default)');
    -      cleanUpAfterDecorateTest();
    -      assertEquals('The expected number of buttons must have been decorated',
    -          SAMPLES_PER_RUN * table.getTimer().getNumSamples(),
    -          decorateIndex);
    -      assertNull('All buttons must have been decorated', elementToDecorate);
    -    }
    -
    -    function testRenderNoBiDiAutoDetect() {
    -      setUpRenderTest();
    -      table.run(
    -          goog.partial(renderButtons, SAMPLES_PER_RUN, false),
    -          'Render ' + SAMPLES_PER_RUN + ' buttons (no BiDi auto-detect)');
    -      cleanUpAfterRenderTest();
    -      assertEquals('The expected number of buttons must have been rendered',
    -          SAMPLES_PER_RUN * table.getTimer().getNumSamples(),
    -          renderIndex);
    -    }
    -
    -    function testDecorateNoBiDiAutoDetect() {
    -      setUpDecorateTest(SAMPLES_PER_RUN * table.getTimer().getNumSamples());
    -      table.run(
    -          goog.partial(decorateButtons, SAMPLES_PER_RUN, false),
    -          'Decorate ' + SAMPLES_PER_RUN + ' buttons (no BiDi auto-detect)');
    -      cleanUpAfterDecorateTest();
    -      assertEquals('The expected number of buttons must have been decorated',
    -          SAMPLES_PER_RUN * table.getTimer().getNumSamples(),
    -          decorateIndex);
    -      assertNull('All buttons must have been decorated', elementToDecorate);
    -    }
    -  </script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/button_test.html b/src/database/third_party/closure-library/closure/goog/ui/button_test.html
    deleted file mode 100644
    index 3940a5e6331..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/button_test.html
    +++ /dev/null
    @@ -1,34 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -Author: nicksantos@google.com (Nick Santos)
    -Author: attila@google.com (Attila Bodis)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.Button
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.ui.ButtonTest');
    -  </script>
    - </head>
    - <body>
    -  <p>
    -   Here's a button defined in markup:
    -  </p>
    -  <button id="demoButton" role="button">
    -   Foo
    -  </button>
    -  <div id="sandbox">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/button_test.js b/src/database/third_party/closure-library/closure/goog/ui/button_test.js
    deleted file mode 100644
    index 1878a02fa25..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/button_test.js
    +++ /dev/null
    @@ -1,283 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.ButtonTest');
    -goog.setTestOnly('goog.ui.ButtonTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.events.KeyHandler');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.Button');
    -goog.require('goog.ui.ButtonRenderer');
    -goog.require('goog.ui.ButtonSide');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.NativeButtonRenderer');
    -
    -var sandbox;
    -var button;
    -var clonedButtonDom;
    -var demoButtonElement;
    -
    -function setUp() {
    -  sandbox = goog.dom.getElement('sandbox');
    -  button = new goog.ui.Button();
    -  demoButtonElement = goog.dom.getElement('demoButton');
    -  clonedButtonDom = demoButtonElement.cloneNode(true);
    -}
    -
    -function tearDown() {
    -  button.dispose();
    -  demoButtonElement.parentNode.replaceChild(clonedButtonDom,
    -      demoButtonElement);
    -  goog.dom.removeChildren(sandbox);
    -}
    -
    -function testConstructor() {
    -  assertNotNull('Button must not be null', button);
    -  assertEquals('Renderer must default to expected value',
    -      goog.ui.NativeButtonRenderer.getInstance(), button.getRenderer());
    -
    -  var fakeDomHelper = {};
    -  var testButton = new goog.ui.Button('Hello',
    -      goog.ui.ButtonRenderer.getInstance(), fakeDomHelper);
    -  assertEquals('Content must have expected value', 'Hello',
    -      testButton.getContent());
    -  assertEquals('Renderer must have expected value',
    -      goog.ui.ButtonRenderer.getInstance(), testButton.getRenderer());
    -  assertEquals('DOM helper must have expected value', fakeDomHelper,
    -      testButton.getDomHelper());
    -  testButton.dispose();
    -}
    -
    -function testGetSetValue() {
    -  assertUndefined('Button\'s value must default to undefined',
    -      button.getValue());
    -  button.setValue(17);
    -  assertEquals('Button must have expected value', 17, button.getValue());
    -  button.render(sandbox);
    -  assertEquals('Button element must have expected value', '17',
    -      button.getElement().value);
    -  button.setValue('foo');
    -  assertEquals('Button element must have updated value', 'foo',
    -      button.getElement().value);
    -  button.setValueInternal('bar');
    -  assertEquals('Button must have new internal value', 'bar',
    -      button.getValue());
    -  assertEquals('Button element must be unchanged', 'foo',
    -      button.getElement().value);
    -}
    -
    -function testGetSetTooltip() {
    -  assertUndefined('Button\'s tooltip must default to undefined',
    -      button.getTooltip());
    -  button.setTooltip('Hello');
    -  assertEquals('Button must have expected tooltip', 'Hello',
    -      button.getTooltip());
    -  button.render(sandbox);
    -  assertEquals('Button element must have expected title', 'Hello',
    -      button.getElement().title);
    -  button.setTooltip('Goodbye');
    -  assertEquals('Button element must have updated title', 'Goodbye',
    -      button.getElement().title);
    -  button.setTooltipInternal('World');
    -  assertEquals('Button must have new internal tooltip', 'World',
    -      button.getTooltip());
    -  assertEquals('Button element must be unchanged', 'Goodbye',
    -      button.getElement().title);
    -}
    -
    -function testSetCollapsed() {
    -  assertNull('Button must not have any collapsed styling by default',
    -      button.getExtraClassNames());
    -  button.setCollapsed(goog.ui.ButtonSide.START);
    -  assertSameElements('Button must have the start side collapsed',
    -      ['goog-button-collapse-left'], button.getExtraClassNames());
    -  button.render(sandbox);
    -  assertSameElements('Button element must have the start side collapsed',
    -      ['goog-button', 'goog-button-collapse-left'],
    -      goog.dom.classlist.get(button.getElement()));
    -  button.setCollapsed(goog.ui.ButtonSide.BOTH);
    -  assertSameElements('Button must have both sides collapsed',
    -      ['goog-button-collapse-left', 'goog-button-collapse-right'],
    -      button.getExtraClassNames());
    -  assertSameElements('Button element must have both sides collapsed', [
    -    'goog-button',
    -    'goog-button-collapse-left',
    -    'goog-button-collapse-right'
    -  ], goog.dom.classlist.get(button.getElement()));
    -}
    -
    -function testDispose() {
    -  assertFalse('Button must not have been disposed of', button.isDisposed());
    -  button.render(sandbox);
    -  button.setValue('foo');
    -  button.setTooltip('bar');
    -  button.dispose();
    -  assertTrue('Button must have been disposed of', button.isDisposed());
    -  assertUndefined('Button\'s value must have been deleted',
    -      button.getValue());
    -  assertUndefined('Button\'s tooltip must have been deleted',
    -      button.getTooltip());
    -}
    -
    -function testBasicButtonBehavior() {
    -  var dispatchedActionCount = 0;
    -  var handleAction = function() {
    -    dispatchedActionCount++;
    -  };
    -  goog.events.listen(button, goog.ui.Component.EventType.ACTION,
    -      handleAction);
    -
    -  button.decorate(demoButtonElement);
    -  goog.testing.events.fireClickSequence(demoButtonElement);
    -  assertEquals('Button must have dispatched ACTION on click', 1,
    -      dispatchedActionCount);
    -
    -  dispatchedActionCount = 0;
    -  var e = new goog.events.Event(goog.events.KeyHandler.EventType.KEY,
    -      button);
    -  e.keyCode = goog.events.KeyCodes.ENTER;
    -  button.handleKeyEvent(e);
    -  assertEquals('Enabled button must have dispatched ACTION on Enter key', 1,
    -      dispatchedActionCount);
    -
    -  dispatchedActionCount = 0;
    -  e = new goog.events.Event(goog.events.EventType.KEYUP, button);
    -  e.keyCode = goog.events.KeyCodes.SPACE;
    -  button.handleKeyEvent(e);
    -  assertEquals('Enabled button must have dispatched ACTION on Space key', 1,
    -      dispatchedActionCount);
    -
    -  goog.events.unlisten(button, goog.ui.Component.EventType.ACTION,
    -      handleAction);
    -}
    -
    -function testDisabledButtonBehavior() {
    -  var dispatchedActionCount = 0;
    -  var handleAction = function() {
    -    dispatchedActionCount++;
    -  };
    -  goog.events.listen(button, goog.ui.Component.EventType.ACTION,
    -      handleAction);
    -
    -  button.setEnabled(false);
    -
    -  dispatchedActionCount = 0;
    -  button.handleKeyEvent({keyCode: goog.events.KeyCodes.ENTER});
    -  assertEquals('Disabled button must not dispatch ACTION on Enter key',
    -      0, dispatchedActionCount);
    -
    -  dispatchedActionCount = 0;
    -  button.handleKeyEvent({
    -    keyCode: goog.events.KeyCodes.SPACE,
    -    type: goog.events.EventType.KEYUP
    -  });
    -  assertEquals('Disabled button must not have dispatched ACTION on Space',
    -      0, dispatchedActionCount);
    -
    -  goog.events.unlisten(button, goog.ui.Component.EventType.ACTION,
    -      handleAction);
    -}
    -
    -function testSpaceFireActionOnKeyUp() {
    -  var dispatchedActionCount = 0;
    -  var handleAction = function() {
    -    dispatchedActionCount++;
    -  };
    -  goog.events.listen(button, goog.ui.Component.EventType.ACTION,
    -      handleAction);
    -
    -  dispatchedActionCount = 0;
    -  e = new goog.events.Event(goog.events.KeyHandler.EventType.KEY, button);
    -  e.keyCode = goog.events.KeyCodes.SPACE;
    -  button.handleKeyEvent(e);
    -  assertEquals('Button must not have dispatched ACTION on Space keypress',
    -      0, dispatchedActionCount);
    -  assertEquals('The default action (scrolling) must have been prevented ' +
    -               'for Space keypress',
    -               false,
    -               e.returnValue_);
    -
    -
    -  dispatchedActionCount = 0;
    -  e = new goog.events.Event(goog.events.EventType.KEYUP, button);
    -  e.keyCode = goog.events.KeyCodes.SPACE;
    -  button.handleKeyEvent(e);
    -  assertEquals('Button must have dispatched ACTION on Space keyup',
    -      1, dispatchedActionCount);
    -
    -  goog.events.unlisten(button, goog.ui.Component.EventType.ACTION,
    -      handleAction);
    -}
    -
    -function testEnterFireActionOnKeyPress() {
    -  var dispatchedActionCount = 0;
    -  var handleAction = function() {
    -    dispatchedActionCount++;
    -  };
    -  goog.events.listen(button, goog.ui.Component.EventType.ACTION,
    -      handleAction);
    -
    -  dispatchedActionCount = 0;
    -  e = new goog.events.Event(goog.events.KeyHandler.EventType.KEY, button);
    -  e.keyCode = goog.events.KeyCodes.ENTER;
    -  button.handleKeyEvent(e);
    -  assertEquals('Button must have dispatched ACTION on Enter keypress',
    -      1, dispatchedActionCount);
    -
    -  dispatchedActionCount = 0;
    -  e = new goog.events.Event(goog.events.EventType.KEYUP, button);
    -  e.keyCode = goog.events.KeyCodes.ENTER;
    -  button.handleKeyEvent(e);
    -  assertEquals('Button must not have dispatched ACTION on Enter keyup',
    -      0, dispatchedActionCount);
    -
    -  goog.events.unlisten(button, goog.ui.Component.EventType.ACTION,
    -      handleAction);
    -}
    -
    -function testSetAriaLabel() {
    -  assertNull('Button must not have aria label by default',
    -      button.getAriaLabel());
    -  button.setAriaLabel('Button 1');
    -  button.render();
    -  assertEquals('Button element must have expected aria-label', 'Button 1',
    -      button.getElement().getAttribute('aria-label'));
    -  button.setAriaLabel('Button 2');
    -  assertEquals('Button element must have updated aria-label', 'Button 2',
    -      button.getElement().getAttribute('aria-label'));
    -}
    -
    -function testSetAriaLabel_decorate() {
    -  assertNull('Button must not have aria label by default',
    -      button.getAriaLabel());
    -  button.setAriaLabel('Button 1');
    -  button.decorate(demoButtonElement);
    -  var el = button.getElementStrict();
    -  assertEquals('Button element must have expected aria-label', 'Button 1',
    -      el.getAttribute('aria-label'));
    -  assertEquals('Button element must have expected aria-role', 'button',
    -      el.getAttribute('role'));
    -  button.setAriaLabel('Button 2');
    -  assertEquals('Button element must have updated aria-label', 'Button 2',
    -      el.getAttribute('aria-label'));
    -  assertEquals('Button element must have expected aria-role', 'button',
    -      el.getAttribute('role'));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/buttonrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/buttonrenderer.js
    deleted file mode 100644
    index 8d8f7c0fc76..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/buttonrenderer.js
    +++ /dev/null
    @@ -1,219 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Default renderer for {@link goog.ui.Button}s.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.ButtonRenderer');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.asserts');
    -goog.require('goog.ui.ButtonSide');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.ControlRenderer');
    -
    -
    -
    -/**
    - * Default renderer for {@link goog.ui.Button}s.  Extends the superclass with
    - * the following button-specific API methods:
    - * <ul>
    - *   <li>{@code getValue} - returns the button element's value
    - *   <li>{@code setValue} - updates the button element to reflect its new value
    - *   <li>{@code getTooltip} - returns the button element's tooltip text
    - *   <li>{@code setTooltip} - updates the button element's tooltip text
    - *   <li>{@code setCollapsed} - removes one or both of the button element's
    - *       borders
    - * </ul>
    - * For alternate renderers, see {@link goog.ui.NativeButtonRenderer},
    - * {@link goog.ui.CustomButtonRenderer}, and {@link goog.ui.FlatButtonRenderer}.
    - * @constructor
    - * @extends {goog.ui.ControlRenderer}
    - */
    -goog.ui.ButtonRenderer = function() {
    -  goog.ui.ControlRenderer.call(this);
    -};
    -goog.inherits(goog.ui.ButtonRenderer, goog.ui.ControlRenderer);
    -goog.addSingletonGetter(goog.ui.ButtonRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.ButtonRenderer.CSS_CLASS = goog.getCssName('goog-button');
    -
    -
    -/**
    - * Returns the ARIA role to be applied to buttons.
    - * @return {goog.a11y.aria.Role|undefined} ARIA role.
    - * @override
    - */
    -goog.ui.ButtonRenderer.prototype.getAriaRole = function() {
    -  return goog.a11y.aria.Role.BUTTON;
    -};
    -
    -
    -/**
    - * Updates the button's ARIA (accessibility) state if the button is being
    - * treated as a checkbox. Also makes sure that attributes which aren't
    - * supported by buttons aren't being added.
    - * @param {Element} element Element whose ARIA state is to be updated.
    - * @param {goog.ui.Component.State} state Component state being enabled or
    - *     disabled.
    - * @param {boolean} enable Whether the state is being enabled or disabled.
    - * @protected
    - * @override
    - */
    -goog.ui.ButtonRenderer.prototype.updateAriaState = function(element, state,
    -    enable) {
    -  switch (state) {
    -    // If button has CHECKED or SELECTED state, assign aria-pressed
    -    case goog.ui.Component.State.SELECTED:
    -    case goog.ui.Component.State.CHECKED:
    -      goog.asserts.assert(element,
    -          'The button DOM element cannot be null.');
    -      goog.a11y.aria.setState(element, goog.a11y.aria.State.PRESSED, enable);
    -      break;
    -    default:
    -    case goog.ui.Component.State.OPENED:
    -    case goog.ui.Component.State.DISABLED:
    -      goog.ui.ButtonRenderer.base(
    -          this, 'updateAriaState', element, state, enable);
    -      break;
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.ButtonRenderer.prototype.createDom = function(button) {
    -  var element = goog.ui.ButtonRenderer.base(this, 'createDom', button);
    -  this.setTooltip(element, button.getTooltip());
    -
    -  var value = button.getValue();
    -  if (value) {
    -    this.setValue(element, value);
    -  }
    -
    -  // If this is a toggle button, set ARIA state
    -  if (button.isSupportedState(goog.ui.Component.State.CHECKED)) {
    -    this.updateAriaState(element, goog.ui.Component.State.CHECKED,
    -                         button.isChecked());
    -  }
    -
    -  return element;
    -};
    -
    -
    -/** @override */
    -goog.ui.ButtonRenderer.prototype.decorate = function(button, element) {
    -  // The superclass implementation takes care of common attributes; we only
    -  // need to set the value and the tooltip.
    -  element = goog.ui.ButtonRenderer.superClass_.decorate.call(this, button,
    -      element);
    -
    -  button.setValueInternal(this.getValue(element));
    -  button.setTooltipInternal(this.getTooltip(element));
    -
    -  // If this is a toggle button, set ARIA state
    -  if (button.isSupportedState(goog.ui.Component.State.CHECKED)) {
    -    this.updateAriaState(element, goog.ui.Component.State.CHECKED,
    -                         button.isChecked());
    -  }
    -
    -  return element;
    -};
    -
    -
    -/**
    - * Takes a button's root element, and returns the value associated with it.
    - * No-op in the base class.
    - * @param {Element} element The button's root element.
    - * @return {string|undefined} The button's value (undefined if none).
    - */
    -goog.ui.ButtonRenderer.prototype.getValue = goog.nullFunction;
    -
    -
    -/**
    - * Takes a button's root element and a value, and updates the element to reflect
    - * the new value.  No-op in the base class.
    - * @param {Element} element The button's root element.
    - * @param {string} value New value.
    - */
    -goog.ui.ButtonRenderer.prototype.setValue = goog.nullFunction;
    -
    -
    -/**
    - * Takes a button's root element, and returns its tooltip text.
    - * @param {Element} element The button's root element.
    - * @return {string|undefined} The tooltip text.
    - */
    -goog.ui.ButtonRenderer.prototype.getTooltip = function(element) {
    -  return element.title;
    -};
    -
    -
    -/**
    - * Takes a button's root element and a tooltip string, and updates the element
    - * with the new tooltip.
    - * @param {Element} element The button's root element.
    - * @param {string} tooltip New tooltip text.
    - * @protected
    - */
    -goog.ui.ButtonRenderer.prototype.setTooltip = function(element, tooltip) {
    -  if (element) {
    -    // Don't set a title attribute if there isn't a tooltip. Blank title
    -    // attributes can be interpreted incorrectly by screen readers.
    -    if (tooltip) {
    -      element.title = tooltip;
    -    } else {
    -      element.removeAttribute('title');
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Collapses the border on one or both sides of the button, allowing it to be
    - * combined with the adjacent button(s), forming a single UI componenet with
    - * multiple targets.
    - * @param {goog.ui.Button} button Button to update.
    - * @param {number} sides Bitmap of one or more {@link goog.ui.ButtonSide}s for
    - *     which borders should be collapsed.
    - * @protected
    - */
    -goog.ui.ButtonRenderer.prototype.setCollapsed = function(button, sides) {
    -  var isRtl = button.isRightToLeft();
    -  var collapseLeftClassName =
    -      goog.getCssName(this.getStructuralCssClass(), 'collapse-left');
    -  var collapseRightClassName =
    -      goog.getCssName(this.getStructuralCssClass(), 'collapse-right');
    -
    -  button.enableClassName(isRtl ? collapseRightClassName : collapseLeftClassName,
    -      !!(sides & goog.ui.ButtonSide.START));
    -  button.enableClassName(isRtl ? collapseLeftClassName : collapseRightClassName,
    -      !!(sides & goog.ui.ButtonSide.END));
    -};
    -
    -
    -/** @override */
    -goog.ui.ButtonRenderer.prototype.getCssClass = function() {
    -  return goog.ui.ButtonRenderer.CSS_CLASS;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/buttonrenderer_test.html b/src/database/third_party/closure-library/closure/goog/ui/buttonrenderer_test.html
    deleted file mode 100644
    index cf9af634b66..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/buttonrenderer_test.html
    +++ /dev/null
    @@ -1,27 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -Author: attila@google.com (Attila Bodis)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.ButtonRenderer
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.ButtonRendererTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="sandbox">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/buttonrenderer_test.js b/src/database/third_party/closure-library/closure/goog/ui/buttonrenderer_test.js
    deleted file mode 100644
    index 029f9d67245..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/buttonrenderer_test.js
    +++ /dev/null
    @@ -1,242 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.ButtonRendererTest');
    -goog.setTestOnly('goog.ui.ButtonRendererTest');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.testing.ExpectedFailures');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.ui.rendererasserts');
    -goog.require('goog.ui.Button');
    -goog.require('goog.ui.ButtonRenderer');
    -goog.require('goog.ui.ButtonSide');
    -goog.require('goog.ui.Component');
    -
    -var button, buttonRenderer, testRenderer;
    -var sandbox;
    -var expectedFailures;
    -
    -function setUpPage() {
    -  sandbox = goog.dom.getElement('sandbox');
    -  expectedFailures = new goog.testing.ExpectedFailures();
    -}
    -
    -
    -
    -/**
    - * A subclass of ButtonRenderer that overrides
    - * {@code getStructuralCssClass} for testing purposes.
    - * @constructor
    - * @extends {goog.ui.ControlRenderer}
    - */
    -function TestRenderer() {
    -  goog.ui.ButtonRenderer.call(this);
    -}
    -goog.inherits(TestRenderer, goog.ui.ButtonRenderer);
    -goog.addSingletonGetter(TestRenderer);
    -
    -
    -/** @override */
    -TestRenderer.prototype.getStructuralCssClass = function() {
    -  return 'goog-base';
    -};
    -
    -function setUp() {
    -  buttonRenderer = goog.ui.ButtonRenderer.getInstance();
    -  button = new goog.ui.Button('Hello', buttonRenderer);
    -  testRenderer = TestRenderer.getInstance();
    -}
    -
    -function tearDown() {
    -  button.dispose();
    -  goog.dom.removeChildren(sandbox);
    -  expectedFailures.handleTearDown();
    -}
    -
    -function testConstructor() {
    -  assertNotNull('ButtonRenderer singleton instance must not be null',
    -      buttonRenderer);
    -}
    -
    -function testGetAriaRole() {
    -  assertEquals('ButtonRenderer\'s ARIA role must have expected value',
    -      goog.a11y.aria.Role.BUTTON, buttonRenderer.getAriaRole());
    -}
    -
    -function testCreateDom() {
    -  var element = buttonRenderer.createDom(button);
    -  assertNotNull('Element must not be null', element);
    -  assertEquals('Element must be a DIV', 'DIV', element.tagName);
    -  assertHTMLEquals('Element must have expected structure',
    -      '<div class="goog-button">Hello</div>',
    -      goog.dom.getOuterHtml(element));
    -
    -  button.setTooltip('Hello, world!');
    -  button.setValue('foo');
    -  element = buttonRenderer.createDom(button);
    -  assertNotNull('Element must not be null', element);
    -  assertEquals('Element must be a DIV', 'DIV', element.tagName);
    -  assertSameElements('Element must have expected class name',
    -      ['goog-button'], goog.dom.classlist.get(element));
    -  assertEquals('Element must have expected title', 'Hello, world!',
    -      element.title);
    -  assertUndefined('Element must have no value', element.value);
    -  assertEquals('Element must have expected contents', 'Hello',
    -      element.innerHTML);
    -
    -  button.setSupportedState(goog.ui.Component.State.CHECKED, true);
    -  var element = buttonRenderer.createDom(button);
    -  assertEquals('button\'s aria-pressed attribute must be false', 'false',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.PRESSED));
    -}
    -
    -function testSetTooltip() {
    -  button.createDom();
    -  button.setTooltip('tooltip');
    -  assertEquals('tooltip', button.getElement().title);
    -  button.setTooltip('');
    -  assertEquals('', button.getElement().title);
    -  // IE7 doesn't support hasAttribute.
    -  if (button.getElement().hasAttribute) {
    -    assertFalse(button.getElement().hasAttribute('title'));
    -  }
    -}
    -
    -function testCreateDomAriaState() {
    -  button.setSupportedState(goog.ui.Component.State.CHECKED, true);
    -  button.setChecked(true);
    -  var element = buttonRenderer.createDom(button);
    -
    -  assertEquals('button\'s aria-pressed attribute must be true', 'true',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.PRESSED));
    -}
    -
    -function testUseAriaPressedForSelected() {
    -  button.setSupportedState(goog.ui.Component.State.SELECTED, true);
    -  button.setSelected(true);
    -  button.setRenderer(buttonRenderer);
    -  button.render();
    -  var element = button.getElement();
    -
    -  assertEquals('button\'s aria-pressed attribute must be true', 'true',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.PRESSED));
    -  assertEquals('button\'s aria-selected attribute must be empty', '',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.SELECTED));
    -}
    -
    -function testAriaDisabled() {
    -  button.setEnabled(false);
    -  button.setRenderer(buttonRenderer);
    -  button.render();
    -  var element = button.getElement();
    -
    -  assertEquals('button\'s aria-disabled attribute must be true', 'true',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.DISABLED));
    -}
    -
    -function testDecorate() {
    -  sandbox.innerHTML =
    -      '<div id="foo">Foo</div>\n' +
    -      '<div id="bar" title="Hello, world!">Bar</div>\n' +
    -      '<div id="toggle">Toggle</div>';
    -
    -  var foo = new goog.ui.Button(null, buttonRenderer);
    -  foo.decorate(goog.dom.getElement('foo'));
    -  assertEquals('foo\'s tooltip must be the empty string', '',
    -      foo.getTooltip());
    -  foo.dispose();
    -
    -  var bar = new goog.ui.Button(null, buttonRenderer);
    -  bar.decorate(goog.dom.getElement('bar'));
    -  assertEquals('bar\'s tooltip must be initialized', 'Hello, world!',
    -      bar.getTooltip());
    -  bar.dispose();
    -
    -  var toggle = new goog.ui.Button(null, buttonRenderer);
    -  toggle.setSupportedState(goog.ui.Component.State.CHECKED, true);
    -  var element = goog.dom.getElement('toggle');
    -  assertNotNull(element);
    -  toggle.decorate(element);
    -  assertEquals('toggle\'s aria-pressed attribute must be false', 'false',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.PRESSED));
    -  toggle.dispose();
    -}
    -
    -function testCollapse() {
    -  buttonRenderer.setCollapsed(button, goog.ui.ButtonSide.START);
    -  assertSameElements('Button should have class to collapse start',
    -      ['goog-button-collapse-left'], button.getExtraClassNames());
    -  buttonRenderer.setCollapsed(button, goog.ui.ButtonSide.END);
    -  assertSameElements('Button should have class to collapse end',
    -      ['goog-button-collapse-right'], button.getExtraClassNames());
    -  buttonRenderer.setCollapsed(button, goog.ui.ButtonSide.BOTH);
    -  assertSameElements('Button should have classes to collapse both',
    -      ['goog-button-collapse-left', 'goog-button-collapse-right'],
    -      button.getExtraClassNames());
    -}
    -
    -function testCollapseRtl() {
    -  button.setRightToLeft(true);
    -  buttonRenderer.setCollapsed(button, goog.ui.ButtonSide.START);
    -  assertSameElements('Button should have class to collapse start',
    -      ['goog-button-collapse-right'], button.getExtraClassNames());
    -  buttonRenderer.setCollapsed(button, goog.ui.ButtonSide.END);
    -  assertSameElements('Button should have class to collapse end',
    -      ['goog-button-collapse-left'], button.getExtraClassNames());
    -  buttonRenderer.setCollapsed(button, goog.ui.ButtonSide.BOTH);
    -  assertSameElements('Button should have classes to collapse both',
    -      ['goog-button-collapse-left', 'goog-button-collapse-right'],
    -      button.getExtraClassNames());
    -}
    -
    -function testCollapseWithStructuralClass() {
    -  testRenderer.setCollapsed(button, goog.ui.ButtonSide.BOTH);
    -  assertSameElements('Should use structural class for collapse classes',
    -      ['goog-base-collapse-left', 'goog-base-collapse-right'],
    -      button.getExtraClassNames());
    -}
    -
    -function testUpdateAriaState() {
    -  var element = buttonRenderer.createDom(button);
    -  buttonRenderer.updateAriaState(element, goog.ui.Component.State.CHECKED,
    -      true);
    -  assertEquals('Button must have pressed ARIA state', 'true',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.PRESSED));
    -
    -  // Test for updating a state other than CHECKED
    -  buttonRenderer.updateAriaState(element, goog.ui.Component.State.DISABLED,
    -      true);
    -  assertEquals('Button must have disabled ARIA state', 'true',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.DISABLED));
    -
    -  buttonRenderer.updateAriaState(element, goog.ui.Component.State.CHECKED,
    -      false);
    -  assertEquals('Control must no longer have pressed ARIA state',
    -      'false',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.PRESSED));
    -  buttonRenderer.updateAriaState(element, goog.ui.Component.State.SELECTED,
    -      true);
    -  assertEquals('Button must have pressed ARIA state', 'true',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.PRESSED));
    -}
    -
    -function testDoesntCallGetCssClassInConstructor() {
    -  goog.testing.ui.rendererasserts.
    -      assertNoGetCssClassCallsInConstructor(goog.ui.ButtonRenderer);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/buttonside.js b/src/database/third_party/closure-library/closure/goog/ui/buttonside.js
    deleted file mode 100644
    index 75a5df38815..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/buttonside.js
    +++ /dev/null
    @@ -1,41 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Enum for button side constants. In its own file so as to not
    - * cause a circular dependency with {@link goog.ui.ButtonRenderer}.
    - *
    - * @author doughtie@google.com (Gavin Doughtie)
    - */
    -
    -goog.provide('goog.ui.ButtonSide');
    -
    -
    -/**
    - * Constants for button sides, see {@link goog.ui.Button.prototype.setCollapsed}
    - * for details.
    - * @enum {number}
    - */
    -goog.ui.ButtonSide = {
    -  /** Neither side. */
    -  NONE: 0,
    -  /** Left for LTR, right for RTL. */
    -  START: 1,
    -  /** Right for LTR, left for RTL. */
    -  END: 2,
    -  /** Both sides. */
    -  BOTH: 3
    -};
    -
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/charcounter.js b/src/database/third_party/closure-library/closure/goog/ui/charcounter.js
    deleted file mode 100644
    index 89e659a6038..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/charcounter.js
    +++ /dev/null
    @@ -1,199 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Character counter widget implementation.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - * @see ../demos/charcounter.html
    - */
    -
    -goog.provide('goog.ui.CharCounter');
    -goog.provide('goog.ui.CharCounter.Display');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.InputHandler');
    -
    -
    -
    -/**
    - * CharCounter widget. Counts the number of characters in a input field or a
    - * text box and displays the number of additional characters that may be
    - * entered before the maximum length is reached.
    - *
    - * @extends {goog.events.EventTarget}
    - * @param {HTMLInputElement|HTMLTextAreaElement} elInput Input or text area
    - *     element to count the number of characters in.
    - * @param {Element} elCount HTML element to display the remaining number of
    - *     characters in. You can pass in null for this if you don't want to expose
    - *     the number of chars remaining.
    - * @param {number} maxLength The maximum length.
    - * @param {goog.ui.CharCounter.Display=} opt_displayMode Display mode for this
    - *     char counter. Defaults to {@link goog.ui.CharCounter.Display.REMAINING}.
    - * @constructor
    - * @final
    - */
    -goog.ui.CharCounter = function(elInput, elCount, maxLength, opt_displayMode) {
    -  goog.events.EventTarget.call(this);
    -
    -  /**
    -   * Input or text area element to count the number of characters in.
    -   * @type {HTMLInputElement|HTMLTextAreaElement}
    -   * @private
    -   */
    -  this.elInput_ = elInput;
    -
    -  /**
    -   * HTML element to display the remaining number of characters in.
    -   * @type {Element}
    -   * @private
    -   */
    -  this.elCount_ = elCount;
    -
    -  /**
    -   * The maximum length.
    -   * @type {number}
    -   * @private
    -   */
    -  this.maxLength_ = maxLength;
    -
    -  /**
    -   * The display mode for this char counter.
    -   * @type {!goog.ui.CharCounter.Display}
    -   * @private
    -   */
    -  this.display_ = opt_displayMode || goog.ui.CharCounter.Display.REMAINING;
    -
    -  elInput.removeAttribute('maxlength');
    -
    -  /**
    -   * The input handler that provides the input event.
    -   * @type {goog.events.InputHandler}
    -   * @private
    -   */
    -  this.inputHandler_ = new goog.events.InputHandler(elInput);
    -
    -  goog.events.listen(this.inputHandler_,
    -      goog.events.InputHandler.EventType.INPUT, this.onChange_, false, this);
    -
    -  this.checkLength();
    -};
    -goog.inherits(goog.ui.CharCounter, goog.events.EventTarget);
    -
    -
    -/**
    - * Display mode for the char counter.
    - * @enum {number}
    - */
    -goog.ui.CharCounter.Display = {
    -  /** Widget displays the number of characters remaining (the default). */
    -  REMAINING: 0,
    -  /** Widget displays the number of characters entered. */
    -  INCREMENTAL: 1
    -};
    -
    -
    -/**
    - * Sets the maximum length.
    - *
    - * @param {number} maxLength The maximum length.
    - */
    -goog.ui.CharCounter.prototype.setMaxLength = function(maxLength) {
    -  this.maxLength_ = maxLength;
    -  this.checkLength();
    -};
    -
    -
    -/**
    - * Returns the maximum length.
    - *
    - * @return {number} The maximum length.
    - */
    -goog.ui.CharCounter.prototype.getMaxLength = function() {
    -  return this.maxLength_;
    -};
    -
    -
    -/**
    - * Sets the display mode.
    - *
    - * @param {!goog.ui.CharCounter.Display} displayMode The display mode.
    - */
    -goog.ui.CharCounter.prototype.setDisplayMode = function(displayMode) {
    -  this.display_ = displayMode;
    -  this.checkLength();
    -};
    -
    -
    -/**
    - * Returns the display mode.
    - *
    - * @return {!goog.ui.CharCounter.Display} The display mode.
    - */
    -goog.ui.CharCounter.prototype.getDisplayMode = function() {
    -  return this.display_;
    -};
    -
    -
    -/**
    - * Change event handler for input field.
    - *
    - * @param {goog.events.BrowserEvent} event Change event.
    - * @private
    - */
    -goog.ui.CharCounter.prototype.onChange_ = function(event) {
    -  this.checkLength();
    -};
    -
    -
    -/**
    - * Checks length of text in input field and updates the counter. Truncates text
    - * if the maximum lengths is exceeded.
    - */
    -goog.ui.CharCounter.prototype.checkLength = function() {
    -  var count = this.elInput_.value.length;
    -
    -  // There's no maxlength property for textareas so instead we truncate the
    -  // text if it gets too long. It's also used to truncate the text in a input
    -  // field if the maximum length is changed.
    -  if (count > this.maxLength_) {
    -
    -    var scrollTop = this.elInput_.scrollTop;
    -    var scrollLeft = this.elInput_.scrollLeft;
    -
    -    this.elInput_.value = this.elInput_.value.substring(0, this.maxLength_);
    -    count = this.maxLength_;
    -
    -    this.elInput_.scrollTop = scrollTop;
    -    this.elInput_.scrollLeft = scrollLeft;
    -  }
    -
    -  if (this.elCount_) {
    -    var incremental = this.display_ == goog.ui.CharCounter.Display.INCREMENTAL;
    -    goog.dom.setTextContent(
    -        this.elCount_,
    -        String(incremental ? count : this.maxLength_ - count));
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.CharCounter.prototype.disposeInternal = function() {
    -  goog.ui.CharCounter.superClass_.disposeInternal.call(this);
    -  delete this.elInput_;
    -  this.inputHandler_.dispose();
    -  this.inputHandler_ = null;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/charcounter_test.html b/src/database/third_party/closure-library/closure/goog/ui/charcounter_test.html
    deleted file mode 100644
    index ca2f375fd7c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/charcounter_test.html
    +++ /dev/null
    @@ -1,29 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.CharCounter
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.CharCounterTest');
    -  </script>
    - </head>
    - <body>
    -  <textarea id="test-textarea-id">
    -  </textarea>
    -  <div>
    -   Characters remaining:
    -   <span class="char-count">
    -   </span>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/charcounter_test.js b/src/database/third_party/closure-library/closure/goog/ui/charcounter_test.js
    deleted file mode 100644
    index 50b4bd11771..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/charcounter_test.js
    +++ /dev/null
    @@ -1,218 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.CharCounterTest');
    -goog.setTestOnly('goog.ui.CharCounterTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.testing.asserts');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.CharCounter');
    -goog.require('goog.userAgent');
    -
    -var countElement, charCounter, inputElement;
    -var incremental = goog.ui.CharCounter.Display.INCREMENTAL;
    -var remaining = goog.ui.CharCounter.Display.REMAINING;
    -var maxLength = 25;
    -
    -function setUp() {
    -  inputElement = goog.dom.getElement('test-textarea-id');
    -  inputElement.value = '';
    -  countElement = goog.dom.getElementByClass('char-count');
    -  goog.dom.setTextContent(countElement, '');
    -  charCounter =
    -      new goog.ui.CharCounter(inputElement, countElement, maxLength);
    -}
    -
    -function tearDown() {
    -  charCounter.dispose();
    -}
    -
    -function setupCheckLength(content, mode) {
    -  inputElement.value = content;
    -  charCounter.setDisplayMode(mode);
    -  charCounter.checkLength();
    -}
    -
    -function testConstructor() {
    -  assertNotNull('Character counter can not be null', charCounter);
    -  assertEquals(maxLength.toString(), goog.dom.getTextContent(countElement));
    -}
    -
    -function testSetMaxLength() {
    -  charCounter.setMaxLength(10);
    -  assertEquals('10', goog.dom.getTextContent(countElement));
    -
    -  var tooLongContent = 'This is too long text content';
    -  inputElement.value = tooLongContent;
    -  charCounter.setMaxLength(10);
    -  assertEquals('0', goog.dom.getTextContent(countElement));
    -  assertEquals('This is to', inputElement.value);
    -}
    -
    -function testGetMaxLength() {
    -  assertEquals(maxLength, charCounter.getMaxLength());
    -}
    -
    -function testSetDisplayMode() {
    -  // Test counter to be in incremental mode
    -  charCounter.setDisplayMode(incremental);
    -  assertEquals('0', goog.dom.getTextContent(countElement));
    -
    -  // Test counter to be in remaining mode
    -  charCounter.setDisplayMode(remaining);
    -  assertEquals(maxLength.toString(), goog.dom.getTextContent(countElement));
    -}
    -
    -function testGetDisplayMode() {
    -  assertEquals(remaining, charCounter.getDisplayMode());
    -
    -  var incrementalCharCounter = new goog.ui.CharCounter(
    -      inputElement, countElement, maxLength, incremental);
    -  assertEquals(incremental, incrementalCharCounter.getDisplayMode());
    -}
    -
    -function testCheckLength() {
    -  // Test the characters remaining in DOM
    -  setupCheckLength('', remaining);
    -  assertEquals(maxLength.toString(), goog.dom.getTextContent(countElement));
    -
    -  // Test the characters incremental in DOM
    -  setupCheckLength('', incremental);
    -  assertEquals('0', goog.dom.getTextContent(countElement));
    -}
    -
    -function testCheckLength_limitedContent() {
    -  var limitedContent = 'Limited text content';
    -  var limitedContentLength = limitedContent.length;
    -  var remainingLimitedContentLength = maxLength - limitedContentLength;
    -
    -  // Set some content and test the characters remaining in DOM
    -  setupCheckLength(limitedContent, remaining);
    -
    -  assertEquals(limitedContent, inputElement.value);
    -  assertEquals(remainingLimitedContentLength.toString(),
    -      goog.dom.getTextContent(countElement));
    -
    -  // Test the characters incremented in DOM with limited content
    -  charCounter.setDisplayMode(incremental);
    -  charCounter.checkLength();
    -
    -  assertEquals(limitedContent, inputElement.value);
    -  assertEquals(limitedContentLength.toString(),
    -      goog.dom.getTextContent(countElement));
    -}
    -
    -function testCheckLength_overflowContent() {
    -  var tooLongContent = 'This is too long text content';
    -  var truncatedContent = 'This is too long text con';
    -
    -  // Set content longer than the maxLength and test the characters remaining
    -  // in DOM with overflowing content
    -  setupCheckLength(tooLongContent, remaining);
    -
    -  assertEquals(truncatedContent, inputElement.value);
    -  assertEquals('0', goog.dom.getTextContent(countElement));
    -
    -  // Set content longer than the maxLength and test the characters
    -  // incremented in DOM with overflowing content
    -  setupCheckLength(tooLongContent, incremental);
    -
    -  assertEquals(truncatedContent, inputElement.value);
    -  assertEquals(maxLength.toString(), goog.dom.getTextContent(countElement));
    -}
    -
    -function testCheckLength_newLineContent() {
    -  var newLineContent = 'New\nline';
    -  var newLineContentLength = newLineContent.length;
    -  var remainingNewLineContentLength = maxLength - newLineContentLength;
    -
    -  var carriageReturnContent = 'New\r\nline';
    -  var carriageReturnContentLength = carriageReturnContent.length;
    -  var remainingCarriageReturnContentLength =
    -      maxLength - carriageReturnContentLength;
    -
    -  // Set some content with new line characters and test the characters
    -  // remaining in DOM
    -  setupCheckLength(newLineContent, remaining);
    -
    -  // Test for IE 7,8 which appends \r to \n
    -  if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9.0')) {
    -    assertEquals(carriageReturnContent, inputElement.value);
    -    assertEquals(remainingCarriageReturnContentLength.toString(),
    -        goog.dom.getTextContent(countElement));
    -  } else {
    -    assertEquals(newLineContent, inputElement.value);
    -    assertEquals(remainingNewLineContentLength.toString(),
    -        goog.dom.getTextContent(countElement));
    -  }
    -
    -  // Set some content with new line characters and test the characters
    -  // incremental in DOM
    -  setupCheckLength(newLineContent, incremental);
    -
    -  // Test for IE 7,8 which appends \r to \n
    -  if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9.0')) {
    -    assertEquals(carriageReturnContent, inputElement.value);
    -    assertEquals(carriageReturnContentLength.toString(),
    -        goog.dom.getTextContent(countElement));
    -  } else {
    -    assertEquals(newLineContent, inputElement.value);
    -    assertEquals(newLineContentLength.toString(),
    -        goog.dom.getTextContent(countElement));
    -  }
    -}
    -
    -function testCheckLength_carriageReturnContent() {
    -  var newLineContent = 'New\nline';
    -  var newLineContentLength = newLineContent.length;
    -  var remainingNewLineContentLength = maxLength - newLineContentLength;
    -
    -  var carriageReturnContent = 'New\r\nline';
    -  var carriageReturnContentLength = carriageReturnContent.length;
    -  var remainingCarriageReturnContentLength =
    -      maxLength - carriageReturnContentLength;
    -
    -  // Set some content with carriage return characters and test the
    -  // characters remaining in DOM
    -  setupCheckLength(carriageReturnContent, remaining);
    -
    -  // Test for IE 7,8
    -  if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9.0')) {
    -    assertEquals(carriageReturnContent, inputElement.value);
    -    assertEquals(remainingCarriageReturnContentLength.toString(),
    -        goog.dom.getTextContent(countElement));
    -  } else {
    -    // Others replace \r\n with \n
    -    assertEquals(newLineContent, inputElement.value);
    -    assertEquals(remainingNewLineContentLength.toString(),
    -        goog.dom.getTextContent(countElement));
    -  }
    -
    -  // Set some content with carriage return characters and test the
    -  // characters incremental in DOM
    -  setupCheckLength(carriageReturnContent, incremental);
    -
    -  // Test for IE 7,8
    -  if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9.0')) {
    -    assertEquals(carriageReturnContent, inputElement.value);
    -    assertEquals(carriageReturnContentLength.toString(),
    -        goog.dom.getTextContent(countElement));
    -  } else {
    -    // Others replace \r\n with \n
    -    assertEquals(newLineContent, inputElement.value);
    -    assertEquals(newLineContentLength.toString(),
    -        goog.dom.getTextContent(countElement));
    -  }
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/charpicker.js b/src/database/third_party/closure-library/closure/goog/ui/charpicker.js
    deleted file mode 100644
    index 193bbc208a5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/charpicker.js
    +++ /dev/null
    @@ -1,921 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Character Picker widget for picking any Unicode character.
    - *
    - * @see ../demos/charpicker.html
    - */
    -
    -goog.provide('goog.ui.CharPicker');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.InputHandler');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.events.KeyHandler');
    -goog.require('goog.i18n.CharListDecompressor');
    -goog.require('goog.i18n.uChar');
    -goog.require('goog.structs.Set');
    -goog.require('goog.style');
    -goog.require('goog.ui.Button');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.ContainerScroller');
    -goog.require('goog.ui.FlatButtonRenderer');
    -goog.require('goog.ui.HoverCard');
    -goog.require('goog.ui.LabelInput');
    -goog.require('goog.ui.Menu');
    -goog.require('goog.ui.MenuButton');
    -goog.require('goog.ui.MenuItem');
    -goog.require('goog.ui.Tooltip');
    -
    -
    -
    -/**
    - * Character Picker Class. This widget can be used to pick any Unicode
    - * character by traversing a category-subcategory structure or by inputing its
    - * hex value.
    - *
    - * See charpicker.html demo for example usage.
    - * @param {goog.i18n.CharPickerData} charPickerData Category names and charlist.
    - * @param {!goog.i18n.uChar.NameFetcher} charNameFetcher Object which fetches
    - *     the names of the characters that are shown in the widget. These names
    - *     may be stored locally or come from an external source.
    - * @param {Array<string>=} opt_recents List of characters to be displayed in
    - *     resently selected characters area.
    - * @param {number=} opt_initCategory Sequence number of initial category.
    - * @param {number=} opt_initSubcategory Sequence number of initial subcategory.
    - * @param {number=} opt_rowCount Number of rows in the grid.
    - * @param {number=} opt_columnCount Number of columns in the grid.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @constructor
    - * @extends {goog.ui.Component}
    - * @final
    - */
    -goog.ui.CharPicker = function(charPickerData, charNameFetcher, opt_recents,
    -                              opt_initCategory, opt_initSubcategory,
    -                              opt_rowCount, opt_columnCount, opt_domHelper) {
    -  goog.ui.Component.call(this, opt_domHelper);
    -
    -  /**
    -   * Object used to retrieve character names.
    -   * @type {!goog.i18n.uChar.NameFetcher}
    -   * @private
    -   */
    -  this.charNameFetcher_ = charNameFetcher;
    -
    -  /**
    -   * Object containing character lists and category names.
    -   * @type {goog.i18n.CharPickerData}
    -   * @private
    -   */
    -  this.data_ = charPickerData;
    -
    -  /**
    -   * The category number to be used on widget init.
    -   * @type {number}
    -   * @private
    -   */
    -  this.initCategory_ = opt_initCategory || 0;
    -
    -  /**
    -   * The subcategory number to be used on widget init.
    -   * @type {number}
    -   * @private
    -   */
    -  this.initSubcategory_ = opt_initSubcategory || 0;
    -
    -  /**
    -   * Number of columns in the grid.
    -   * @type {number}
    -   * @private
    -   */
    -  this.columnCount_ = opt_columnCount || 10;
    -
    -  /**
    -   * Number of entries to be added to the grid.
    -   * @type {number}
    -   * @private
    -   */
    -  this.gridsize_ = (opt_rowCount || 10) * this.columnCount_;
    -
    -  /**
    -   * Number of the recently selected characters displayed.
    -   * @type {number}
    -   * @private
    -   */
    -  this.recentwidth_ = this.columnCount_ + 1;
    -
    -  /**
    -   * List of recently used characters.
    -   * @type {Array<string>}
    -   * @private
    -   */
    -  this.recents_ = opt_recents || [];
    -
    -  /**
    -   * Handler for events.
    -   * @type {goog.events.EventHandler<!goog.ui.CharPicker>}
    -   * @private
    -   */
    -  this.eventHandler_ = new goog.events.EventHandler(this);
    -
    -  /**
    -   * Decompressor used to get the list of characters from a base88 encoded
    -   * character list.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.decompressor_ = new goog.i18n.CharListDecompressor();
    -};
    -goog.inherits(goog.ui.CharPicker, goog.ui.Component);
    -
    -
    -/**
    - * The last selected character.
    - * @type {?string}
    - * @private
    - */
    -goog.ui.CharPicker.prototype.selectedChar_ = null;
    -
    -
    -/**
    - * Set of formatting characters whose display need to be swapped with nbsp
    - * to prevent layout issues.
    - * @type {goog.structs.Set}
    - * @private
    - */
    -goog.ui.CharPicker.prototype.layoutAlteringChars_ = null;
    -
    -
    -/**
    - * The top category menu.
    - * @type {goog.ui.Menu}
    - * @private
    - */
    -goog.ui.CharPicker.prototype.menu_ = null;
    -
    -
    -/**
    - * The top category menu button.
    - * @type {goog.ui.MenuButton}
    - * @private
    - */
    -goog.ui.CharPicker.prototype.menubutton_ = null;
    -
    -
    -/**
    - * The subcategory menu.
    - * @type {goog.ui.Menu}
    - * @private
    - */
    -goog.ui.CharPicker.prototype.submenu_ = null;
    -
    -
    -/**
    - * The subcategory menu button.
    - * @type {goog.ui.MenuButton}
    - * @private
    - */
    -goog.ui.CharPicker.prototype.submenubutton_ = null;
    -
    -
    -/** @type {number} */
    -goog.ui.CharPicker.prototype.itempos;
    -
    -
    -/** @type {!Array<string>} */
    -goog.ui.CharPicker.prototype.items;
    -
    -
    -/** @private {!goog.events.KeyHandler} */
    -goog.ui.CharPicker.prototype.keyHandler_;
    -
    -
    -/**
    - * Category index used to index the data tables.
    - * @type {number}
    - */
    -goog.ui.CharPicker.prototype.category;
    -
    -
    -/** @private {Element} */
    -goog.ui.CharPicker.prototype.stick_ = null;
    -
    -
    -/**
    - * The element representing the number of rows visible in the grid.
    - * This along with goog.ui.CharPicker.stick_ would help to create a scrollbar
    - * of right size.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.CharPicker.prototype.stickwrap_ = null;
    -
    -
    -/**
    - * The component containing all the buttons for each character in display.
    - * @type {goog.ui.Component}
    - * @private
    - */
    -goog.ui.CharPicker.prototype.grid_ = null;
    -
    -
    -/**
    - * The component used for extra information about the character set displayed.
    - * @type {goog.ui.Component}
    - * @private
    - */
    -goog.ui.CharPicker.prototype.notice_ = null;
    -
    -
    -/**
    - * Grid displaying recently selected characters.
    - * @type {goog.ui.Component}
    - * @private
    - */
    -goog.ui.CharPicker.prototype.recentgrid_ = null;
    -
    -
    -/**
    - * Input field for entering the hex value of the character.
    - * @type {goog.ui.Component}
    - * @private
    - */
    -goog.ui.CharPicker.prototype.input_ = null;
    -
    -
    -/**
    - * OK button for entering hex value of the character.
    - * @private {goog.ui.Button}
    - */
    -goog.ui.CharPicker.prototype.okbutton_ = null;
    -
    -
    -/**
    - * Element displaying character name in preview.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.CharPicker.prototype.charNameEl_ = null;
    -
    -
    -/**
    - * Element displaying character in preview.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.CharPicker.prototype.zoomEl_ = null;
    -
    -
    -/**
    - * Element displaying character number (codepoint) in preview.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.CharPicker.prototype.unicodeEl_ = null;
    -
    -
    -/**
    - * Hover card for displaying the preview of a character.
    - * Preview would contain character in large size and its U+ notation. It would
    - * also display the name, if available.
    - * @type {goog.ui.HoverCard}
    - * @private
    - */
    -goog.ui.CharPicker.prototype.hc_ = null;
    -
    -
    -/**
    - * Gets the last selected character.
    - * @return {?string} The last selected character.
    - */
    -goog.ui.CharPicker.prototype.getSelectedChar = function() {
    -  return this.selectedChar_;
    -};
    -
    -
    -/**
    - * Gets the list of characters user selected recently.
    - * @return {Array<string>} The recent character list.
    - */
    -goog.ui.CharPicker.prototype.getRecentChars = function() {
    -  return this.recents_;
    -};
    -
    -
    -/** @override */
    -goog.ui.CharPicker.prototype.createDom = function() {
    -  goog.ui.CharPicker.superClass_.createDom.call(this);
    -
    -  this.decorateInternal(this.getDomHelper().createElement('div'));
    -};
    -
    -
    -/** @override */
    -goog.ui.CharPicker.prototype.disposeInternal = function() {
    -  goog.dispose(this.hc_);
    -  this.hc_ = null;
    -  goog.dispose(this.eventHandler_);
    -  this.eventHandler_ = null;
    -  goog.ui.CharPicker.superClass_.disposeInternal.call(this);
    -};
    -
    -
    -/** @override */
    -goog.ui.CharPicker.prototype.decorateInternal = function(element) {
    -  goog.ui.CharPicker.superClass_.decorateInternal.call(this, element);
    -
    -  // The chars below cause layout disruption or too narrow to hover:
    -  // \u0020, \u00AD, \u2000 - \u200f, \u2028 - \u202f, \u3000, \ufeff
    -  var chrs = this.decompressor_.toCharList(':2%C^O80V1H2s2G40Q%s0');
    -  this.layoutAlteringChars_ = new goog.structs.Set(chrs);
    -
    -  this.menu_ = new goog.ui.Menu(this.getDomHelper());
    -
    -  var categories = this.data_.categories;
    -  for (var i = 0; i < this.data_.categories.length; i++) {
    -    this.menu_.addChild(this.createMenuItem_(i, categories[i]), true);
    -  }
    -
    -  this.menubutton_ = new goog.ui.MenuButton('Category Menu', this.menu_,
    -      /* opt_renderer */ undefined, this.getDomHelper());
    -  this.addChild(this.menubutton_, true);
    -
    -  this.submenu_ = new goog.ui.Menu(this.getDomHelper());
    -
    -  this.submenubutton_ = new goog.ui.MenuButton('Subcategory Menu',
    -      this.submenu_, /* opt_renderer */ undefined, this.getDomHelper());
    -  this.addChild(this.submenubutton_, true);
    -
    -  // The containing component for grid component and the scroller.
    -  var gridcontainer = new goog.ui.Component(this.getDomHelper());
    -  this.addChild(gridcontainer, true);
    -
    -  var stickwrap = new goog.ui.Component(this.getDomHelper());
    -  gridcontainer.addChild(stickwrap, true);
    -  this.stickwrap_ = stickwrap.getElement();
    -
    -  var stick = new goog.ui.Component(this.getDomHelper());
    -  stickwrap.addChild(stick, true);
    -  this.stick_ = stick.getElement();
    -
    -  this.grid_ = new goog.ui.Component(this.getDomHelper());
    -  gridcontainer.addChild(this.grid_, true);
    -
    -  this.notice_ = new goog.ui.Component(this.getDomHelper());
    -  this.notice_.setElementInternal(this.getDomHelper().createDom('div'));
    -  this.addChild(this.notice_, true);
    -
    -  // The component used for displaying 'Recent Selections' label.
    -  /**
    -   * @desc The text label above the list of recently selected characters.
    -   */
    -  var MSG_CHAR_PICKER_RECENT_SELECTIONS = goog.getMsg('Recent Selections:');
    -  var recenttext = new goog.ui.Component(this.getDomHelper());
    -  recenttext.setElementInternal(this.getDomHelper().createDom('span', null,
    -      MSG_CHAR_PICKER_RECENT_SELECTIONS));
    -  this.addChild(recenttext, true);
    -
    -  this.recentgrid_ = new goog.ui.Component(this.getDomHelper());
    -  this.addChild(this.recentgrid_, true);
    -
    -  // The component used for displaying 'U+'.
    -  var uplus = new goog.ui.Component(this.getDomHelper());
    -  uplus.setElementInternal(this.getDomHelper().createDom('span', null, 'U+'));
    -  this.addChild(uplus, true);
    -
    -  /**
    -   * @desc The text inside the input box to specify the hex code of a character.
    -   */
    -  var MSG_CHAR_PICKER_HEX_INPUT = goog.getMsg('Hex Input');
    -  this.input_ = new goog.ui.LabelInput(
    -      MSG_CHAR_PICKER_HEX_INPUT, this.getDomHelper());
    -  this.addChild(this.input_, true);
    -
    -  this.okbutton_ = new goog.ui.Button(
    -      'OK', /* opt_renderer */ undefined, this.getDomHelper());
    -  this.addChild(this.okbutton_, true);
    -  this.okbutton_.setEnabled(false);
    -
    -  this.zoomEl_ = this.getDomHelper().createDom('div',
    -      {id: 'zoom', className: goog.getCssName('goog-char-picker-char-zoom')});
    -
    -  this.charNameEl_ = this.getDomHelper().createDom('div',
    -      {id: 'charName', className: goog.getCssName('goog-char-picker-name')});
    -
    -  this.unicodeEl_ = this.getDomHelper().createDom('div',
    -      {id: 'unicode', className: goog.getCssName('goog-char-picker-unicode')});
    -
    -  var card = this.getDomHelper().createDom('div',
    -      {'id': 'preview'},
    -      this.zoomEl_, this.charNameEl_, this.unicodeEl_);
    -  goog.style.setElementShown(card, false);
    -  this.hc_ = new goog.ui.HoverCard({'DIV': 'char'},
    -      /* opt_checkDescendants */ undefined, this.getDomHelper());
    -  this.hc_.setElement(card);
    -  var self = this;
    -
    -  /**
    -   * Function called by hover card just before it is visible to collect data.
    -   */
    -  function onBeforeShow() {
    -    var trigger = self.hc_.getAnchorElement();
    -    var ch = self.getChar_(trigger);
    -    if (ch) {
    -      goog.dom.setTextContent(self.zoomEl_, self.displayChar_(ch));
    -      goog.dom.setTextContent(self.unicodeEl_, goog.i18n.uChar.toHexString(ch));
    -      // Clear the character name since we don't want to show old data because
    -      // it is retrieved asynchronously and the DOM object is re-used
    -      goog.dom.setTextContent(self.charNameEl_, '');
    -      self.charNameFetcher_.getName(ch, function(charName) {
    -        if (charName) {
    -          goog.dom.setTextContent(self.charNameEl_, charName);
    -        }
    -      });
    -    }
    -  }
    -
    -  goog.events.listen(this.hc_, goog.ui.HoverCard.EventType.BEFORE_SHOW,
    -                     onBeforeShow);
    -  goog.asserts.assert(element);
    -  goog.dom.classlist.add(element, goog.getCssName('goog-char-picker'));
    -  goog.dom.classlist.add(goog.asserts.assert(this.stick_),
    -                         goog.getCssName('goog-stick'));
    -  goog.dom.classlist.add(goog.asserts.assert(this.stickwrap_),
    -                         goog.getCssName('goog-stickwrap'));
    -  goog.dom.classlist.add(
    -      goog.asserts.assert(gridcontainer.getElement()),
    -      goog.getCssName('goog-char-picker-grid-container'));
    -  goog.dom.classlist.add(
    -      goog.asserts.assert(this.grid_.getElement()),
    -      goog.getCssName('goog-char-picker-grid'));
    -  goog.dom.classlist.add(
    -      goog.asserts.assert(this.recentgrid_.getElement()),
    -      goog.getCssName('goog-char-picker-grid'));
    -  goog.dom.classlist.add(
    -      goog.asserts.assert(this.recentgrid_.getElement()),
    -      goog.getCssName('goog-char-picker-recents'));
    -
    -  goog.dom.classlist.add(
    -      goog.asserts.assert(this.notice_.getElement()),
    -      goog.getCssName('goog-char-picker-notice'));
    -  goog.dom.classlist.add(
    -      goog.asserts.assert(uplus.getElement()),
    -      goog.getCssName('goog-char-picker-uplus'));
    -  goog.dom.classlist.add(
    -      goog.asserts.assert(this.input_.getElement()),
    -      goog.getCssName('goog-char-picker-input-box'));
    -  goog.dom.classlist.add(
    -      goog.asserts.assert(this.okbutton_.getElement()),
    -      goog.getCssName('goog-char-picker-okbutton'));
    -  goog.dom.classlist.add(
    -      goog.asserts.assert(card),
    -      goog.getCssName('goog-char-picker-hovercard'));
    -
    -  this.hc_.className = goog.getCssName('goog-char-picker-hovercard');
    -
    -  this.grid_.buttoncount = this.gridsize_;
    -  this.recentgrid_.buttoncount = this.recentwidth_;
    -  this.populateGridWithButtons_(this.grid_);
    -  this.populateGridWithButtons_(this.recentgrid_);
    -
    -  this.updateGrid_(this.recentgrid_, this.recents_);
    -  this.setSelectedCategory_(this.initCategory_, this.initSubcategory_);
    -  new goog.ui.ContainerScroller(this.menu_);
    -  new goog.ui.ContainerScroller(this.submenu_);
    -
    -  goog.dom.classlist.add(
    -      goog.asserts.assert(this.menu_.getElement()),
    -      goog.getCssName('goog-char-picker-menu'));
    -  goog.dom.classlist.add(
    -      goog.asserts.assert(this.submenu_.getElement()),
    -      goog.getCssName('goog-char-picker-menu'));
    -};
    -
    -
    -/** @override */
    -goog.ui.CharPicker.prototype.enterDocument = function() {
    -  goog.ui.CharPicker.superClass_.enterDocument.call(this);
    -  var inputkh = new goog.events.InputHandler(this.input_.getElement());
    -  this.keyHandler_ = new goog.events.KeyHandler(this.input_.getElement());
    -
    -  // Stop the propagation of ACTION events at menu and submenu buttons.
    -  // If stopped at capture phase, the button will not be set to normal state.
    -  // If not stopped, the user widget will receive the event, which is
    -  // undesired. User widget should receive an event only on the character
    -  // click.
    -  this.eventHandler_.
    -      listen(
    -          this.menubutton_,
    -          goog.ui.Component.EventType.ACTION,
    -          goog.events.Event.stopPropagation).
    -      listen(
    -          this.submenubutton_,
    -          goog.ui.Component.EventType.ACTION,
    -          goog.events.Event.stopPropagation).
    -      listen(
    -          this,
    -          goog.ui.Component.EventType.ACTION,
    -          this.handleSelectedItem_,
    -          true).
    -      listen(
    -          inputkh,
    -          goog.events.InputHandler.EventType.INPUT,
    -          this.handleInput_).
    -      listen(
    -          this.keyHandler_,
    -          goog.events.KeyHandler.EventType.KEY,
    -          this.handleEnter_).
    -      listen(
    -          this.recentgrid_,
    -          goog.ui.Component.EventType.FOCUS,
    -          this.handleFocus_).
    -      listen(
    -          this.grid_,
    -          goog.ui.Component.EventType.FOCUS,
    -          this.handleFocus_);
    -
    -  goog.events.listen(this.okbutton_.getElement(),
    -      goog.events.EventType.MOUSEDOWN, this.handleOkClick_, true, this);
    -
    -  goog.events.listen(this.stickwrap_, goog.events.EventType.SCROLL,
    -      this.handleScroll_, true, this);
    -};
    -
    -
    -/**
    - * Handles the button focus by updating the aria label with the character name
    - * so it becomes possible to get spoken feedback while tabbing through the
    - * visible symbols.
    - * @param {goog.events.Event} e The focus event.
    - * @private
    - */
    -goog.ui.CharPicker.prototype.handleFocus_ = function(e) {
    -  var button = e.target;
    -  var element = button.getElement();
    -  var ch = this.getChar_(element);
    -
    -  // Clear the aria label to avoid speaking the old value in case the button
    -  // element has no char attribute or the character name cannot be retrieved.
    -  goog.a11y.aria.setState(element, goog.a11y.aria.State.LABEL, '');
    -
    -  if (ch) {
    -    // This is working with screen readers because the call to getName is
    -    // synchronous once the values have been prefetched by the RemoteNameFetcher
    -    // and because it is always synchronous when using the LocalNameFetcher.
    -    // Also, the special character itself is not used as the label because some
    -    // screen readers, notably ChromeVox, are not able to speak them.
    -    // TODO(user): Consider changing the NameFetcher API to provide a
    -    // method that lets the caller retrieve multiple character names at once
    -    // so that this asynchronous gymnastic can be avoided.
    -    this.charNameFetcher_.getName(ch, function(charName) {
    -      if (charName) {
    -        goog.a11y.aria.setState(
    -            element, goog.a11y.aria.State.LABEL, charName);
    -      }
    -    });
    -  }
    -};
    -
    -
    -/**
    - * On scroll, updates the grid with characters correct to the scroll position.
    - * @param {goog.events.Event} e Scroll event to handle.
    - * @private
    - */
    -goog.ui.CharPicker.prototype.handleScroll_ = function(e) {
    -  var height = e.target.scrollHeight;
    -  var top = e.target.scrollTop;
    -  var itempos = Math.ceil(top * this.items.length / (this.columnCount_ *
    -      height)) * this.columnCount_;
    -  if (this.itempos != itempos) {
    -    this.itempos = itempos;
    -    this.modifyGridWithItems_(this.grid_, this.items, itempos);
    -  }
    -  e.stopPropagation();
    -};
    -
    -
    -/**
    - * On a menu click, sets correct character set in the grid; on a grid click
    - * accept the character as the selected one and adds to recent selection, if not
    - * already present.
    - * @param {goog.events.Event} e Event for the click on menus or grid.
    - * @private
    - */
    -goog.ui.CharPicker.prototype.handleSelectedItem_ = function(e) {
    -  var parent = /** @type {goog.ui.Component} */ (e.target).getParent();
    -  if (parent == this.menu_) {
    -    this.menu_.setVisible(false);
    -    this.setSelectedCategory_(e.target.getValue());
    -  } else if (parent == this.submenu_) {
    -    this.submenu_.setVisible(false);
    -    this.setSelectedSubcategory_(e.target.getValue());
    -  } else if (parent == this.grid_) {
    -    var button = e.target.getElement();
    -    this.selectedChar_ = this.getChar_(button);
    -    this.updateRecents_(this.selectedChar_);
    -  } else if (parent == this.recentgrid_) {
    -    this.selectedChar_ = this.getChar_(e.target.getElement());
    -  }
    -};
    -
    -
    -/**
    - * When user types the characters displays the preview. Enables the OK button,
    - * if the character is valid.
    - * @param {goog.events.Event} e Event for typing in input field.
    - * @private
    - */
    -goog.ui.CharPicker.prototype.handleInput_ = function(e) {
    -  var ch = this.getInputChar();
    -  if (ch) {
    -    goog.dom.setTextContent(this.zoomEl_, ch);
    -    goog.dom.setTextContent(this.unicodeEl_, goog.i18n.uChar.toHexString(ch));
    -    goog.dom.setTextContent(this.charNameEl_, '');
    -    var coord =
    -        new goog.ui.Tooltip.ElementTooltipPosition(this.input_.getElement());
    -    this.hc_.setPosition(coord);
    -    this.hc_.triggerForElement(this.input_.getElement());
    -    this.okbutton_.setEnabled(true);
    -  } else {
    -    this.hc_.cancelTrigger();
    -    this.hc_.setVisible(false);
    -    this.okbutton_.setEnabled(false);
    -  }
    -};
    -
    -
    -/**
    - * On OK click accepts the character and updates the recent char list.
    - * @param {goog.events.Event=} opt_event Event for click on OK button.
    - * @return {boolean} Indicates whether to propagate event.
    - * @private
    - */
    -goog.ui.CharPicker.prototype.handleOkClick_ = function(opt_event) {
    -  var ch = this.getInputChar();
    -  if (ch && ch.charCodeAt(0)) {
    -    this.selectedChar_ = ch;
    -    this.updateRecents_(ch);
    -    return true;
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Behaves exactly like the OK button on Enter key.
    - * @param {goog.events.KeyEvent} e Event for enter on the input field.
    - * @return {boolean} Indicates whether to propagate event.
    - * @private
    - */
    -goog.ui.CharPicker.prototype.handleEnter_ = function(e) {
    -  if (e.keyCode == goog.events.KeyCodes.ENTER) {
    -    return this.handleOkClick_() ?
    -        this.dispatchEvent(goog.ui.Component.EventType.ACTION) : false;
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Gets the character from the event target.
    - * @param {Element} e Event target containing the 'char' attribute.
    - * @return {string} The character specified in the event.
    - * @private
    - */
    -goog.ui.CharPicker.prototype.getChar_ = function(e) {
    -  return e.getAttribute('char');
    -};
    -
    -
    -/**
    - * Creates a menu entry for either the category listing or subcategory listing.
    - * @param {number} id Id to be used for the entry.
    - * @param {string} caption Text displayed for the menu item.
    - * @return {!goog.ui.MenuItem} Menu item to be added to the menu listing.
    - * @private
    - */
    -goog.ui.CharPicker.prototype.createMenuItem_ = function(id, caption) {
    -  var item = new goog.ui.MenuItem(caption, /* model */ id, this.getDomHelper());
    -  item.setVisible(true);
    -  return item;
    -};
    -
    -
    -/**
    - * Sets the category and updates the submenu items and grid accordingly.
    - * @param {number} category Category index used to index the data tables.
    - * @param {number=} opt_subcategory Subcategory index used with category index.
    - * @private
    - */
    -goog.ui.CharPicker.prototype.setSelectedCategory_ = function(category,
    -                                                             opt_subcategory) {
    -  this.category = category;
    -  this.menubutton_.setCaption(this.data_.categories[category]);
    -  while (this.submenu_.hasChildren()) {
    -    this.submenu_.removeChildAt(0, true).dispose();
    -  }
    -
    -  var subcategories = this.data_.subcategories[category];
    -  var charList = this.data_.charList[category];
    -  for (var i = 0; i < subcategories.length; i++) {
    -    var item = this.createMenuItem_(i, subcategories[i]);
    -    this.submenu_.addChild(item, true);
    -  }
    -  this.setSelectedSubcategory_(opt_subcategory || 0);
    -};
    -
    -
    -/**
    - * Sets the subcategory and updates the grid accordingly.
    - * @param {number} subcategory Sub-category index used to index the data tables.
    - * @private
    - */
    -goog.ui.CharPicker.prototype.setSelectedSubcategory_ = function(subcategory) {
    -  var subcategories = this.data_.subcategories;
    -  var name = subcategories[this.category][subcategory];
    -  this.submenubutton_.setCaption(name);
    -  this.setSelectedGrid_(this.category, subcategory);
    -};
    -
    -
    -/**
    - * Updates the grid according to a given category and subcategory.
    - * @param {number} category Index to the category table.
    - * @param {number} subcategory Index to the subcategory table.
    - * @private
    - */
    -goog.ui.CharPicker.prototype.setSelectedGrid_ = function(category,
    -    subcategory) {
    -  var charLists = this.data_.charList;
    -  var charListStr = charLists[category][subcategory];
    -  var content = this.decompressor_.toCharList(charListStr);
    -  this.charNameFetcher_.prefetch(charListStr);
    -  this.updateGrid_(this.grid_, content);
    -};
    -
    -
    -/**
    - * Updates the grid with new character list.
    - * @param {goog.ui.Component} grid The grid which is updated with a new set of
    - *     characters.
    - * @param {Array<string>} items Characters to be added to the grid.
    - * @private
    - */
    -goog.ui.CharPicker.prototype.updateGrid_ = function(grid, items) {
    -  if (grid == this.grid_) {
    -    /**
    -     * @desc The message used when there are invisible characters like space
    -     *     or format control characters.
    -     */
    -    var MSG_PLEASE_HOVER =
    -        goog.getMsg('Please hover over each cell for the character name.');
    -
    -    goog.dom.setTextContent(this.notice_.getElement(),
    -        this.charNameFetcher_.isNameAvailable(
    -            items[0]) ? MSG_PLEASE_HOVER : '');
    -    this.items = items;
    -    if (this.stickwrap_.offsetHeight > 0) {
    -      this.stick_.style.height =
    -          this.stickwrap_.offsetHeight * items.length / this.gridsize_ + 'px';
    -    } else {
    -      // This is the last ditch effort if height is not avaialble.
    -      // Maximum of 3em is assumed to the the cell height. Extra space after
    -      // last character in the grid is OK.
    -      this.stick_.style.height = 3 * this.columnCount_ * items.length /
    -          this.gridsize_ + 'em';
    -    }
    -    this.stickwrap_.scrollTop = 0;
    -  }
    -
    -  this.modifyGridWithItems_(grid, items, 0);
    -};
    -
    -
    -/**
    - * Updates the grid with new character list for a given starting point.
    - * @param {goog.ui.Component} grid The grid which is updated with a new set of
    - *     characters.
    - * @param {Array<string>} items Characters to be added to the grid.
    - * @param {number} start The index from which the characters should be
    - *     displayed.
    - * @private
    - */
    -goog.ui.CharPicker.prototype.modifyGridWithItems_ = function(grid, items,
    -    start) {
    -  for (var buttonpos = 0, itempos = start;
    -       buttonpos < grid.buttoncount && itempos < items.length;
    -       buttonpos++, itempos++) {
    -    this.modifyCharNode_(
    -        /** @type {!goog.ui.Button} */ (grid.getChildAt(buttonpos)),
    -        items[itempos]);
    -  }
    -
    -  for (; buttonpos < grid.buttoncount; buttonpos++) {
    -    grid.getChildAt(buttonpos).setVisible(false);
    -  }
    -};
    -
    -
    -/**
    - * Creates the grid for characters to displayed for selection.
    - * @param {goog.ui.Component} grid The grid which is updated with a new set of
    - *     characters.
    - * @private
    - */
    -goog.ui.CharPicker.prototype.populateGridWithButtons_ = function(grid) {
    -  for (var i = 0; i < grid.buttoncount; i++) {
    -    var button = new goog.ui.Button(' ',
    -                                    goog.ui.FlatButtonRenderer.getInstance(),
    -                                    this.getDomHelper());
    -
    -    // Dispatch the focus event so we can update the aria description while
    -    // the user tabs through the cells.
    -    button.setDispatchTransitionEvents(goog.ui.Component.State.FOCUSED, true);
    -
    -    grid.addChild(button, true);
    -    button.setVisible(false);
    -
    -    var buttonEl = button.getElement();
    -    goog.asserts.assert(buttonEl, 'The button DOM element cannot be null.');
    -
    -    // Override the button role so the user doesn't hear "button" each time he
    -    // tabs through the cells.
    -    goog.a11y.aria.removeRole(buttonEl);
    -  }
    -};
    -
    -
    -/**
    - * Updates the grid cell with new character.
    - * @param {goog.ui.Button} button This button is popped up for new character.
    - * @param {string} ch Character to be displayed by the button.
    - * @private
    - */
    -goog.ui.CharPicker.prototype.modifyCharNode_ = function(button, ch) {
    -  var text = this.displayChar_(ch);
    -  var buttonEl = button.getElement();
    -  goog.dom.setTextContent(buttonEl, text);
    -  buttonEl.setAttribute('char', ch);
    -  button.setVisible(true);
    -};
    -
    -
    -/**
    - * Adds a given character to the recent character list.
    - * @param {string} character Character to be added to the recent list.
    - * @private
    - */
    -goog.ui.CharPicker.prototype.updateRecents_ = function(character) {
    -  if (character && character.charCodeAt(0) &&
    -      !goog.array.contains(this.recents_, character)) {
    -    this.recents_.unshift(character);
    -    if (this.recents_.length > this.recentwidth_) {
    -      this.recents_.pop();
    -    }
    -    this.updateGrid_(this.recentgrid_, this.recents_);
    -  }
    -};
    -
    -
    -/**
    - * Gets the user inputed unicode character.
    - * @return {string} Unicode character inputed by user.
    - */
    -goog.ui.CharPicker.prototype.getInputChar = function() {
    -  var text = this.input_.getValue();
    -  var code = parseInt(text, 16);
    -  return /** @type {string} */ (goog.i18n.uChar.fromCharCode(code));
    -};
    -
    -
    -/**
    - * Gets the display character for the given character.
    - * @param {string} ch Character whose display is fetched.
    - * @return {string} The display of the given character.
    - * @private
    - */
    -goog.ui.CharPicker.prototype.displayChar_ = function(ch) {
    -  return this.layoutAlteringChars_.contains(ch) ? '\u00A0' : ch;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/charpicker_test.html b/src/database/third_party/closure-library/closure/goog/ui/charpicker_test.html
    deleted file mode 100644
    index 989b832e71b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/charpicker_test.html
    +++ /dev/null
    @@ -1,26 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.CharPicker
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.CharPickerTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="charpicker">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/charpicker_test.js b/src/database/third_party/closure-library/closure/goog/ui/charpicker_test.js
    deleted file mode 100644
    index fe0765e6ad6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/charpicker_test.js
    +++ /dev/null
    @@ -1,87 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.CharPickerTest');
    -goog.setTestOnly('goog.ui.CharPickerTest');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.dispose');
    -goog.require('goog.dom');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventType');
    -goog.require('goog.i18n.CharPickerData');
    -goog.require('goog.i18n.uChar.NameFetcher');
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.mockmatchers');
    -goog.require('goog.ui.CharPicker');
    -goog.require('goog.ui.FlatButtonRenderer');
    -
    -var charPicker, charPickerData, charPickerElement;
    -var mockControl, charNameFetcherMock;
    -
    -function setUp() {
    -  mockControl = new goog.testing.MockControl();
    -  charNameFetcherMock = mockControl.createLooseMock(
    -      goog.i18n.uChar.NameFetcher, true /* opt_ignoreUnexpectedCalls */);
    -
    -  charPickerData = new goog.i18n.CharPickerData();
    -  charPickerElement = goog.dom.getElement('charpicker');
    -
    -  charPicker = new goog.ui.CharPicker(
    -      charPickerData, charNameFetcherMock);
    -}
    -
    -function tearDown() {
    -  goog.dispose(charPicker);
    -  goog.dom.removeChildren(charPickerElement);
    -  mockControl.$tearDown();
    -}
    -
    -function testAriaLabelIsUpdatedOnFocus() {
    -  var character = '←';
    -  var characterName = 'right arrow';
    -
    -  charNameFetcherMock.getName(
    -      character,
    -      goog.testing.mockmatchers.isFunction).
    -      $does(function(c, callback) {
    -        callback(characterName);
    -      });
    -
    -  mockControl.$replayAll();
    -
    -  charPicker.decorate(charPickerElement);
    -
    -  // Get the first button elements within the grid div and override its
    -  // char attribute so the test doesn't depend on the actual grid content.
    -  var gridElement = goog.dom.getElementByClass(
    -      goog.getCssName('goog-char-picker-grid'), charPickerElement);
    -  var buttonElement = goog.dom.getElementsByClass(
    -      goog.ui.FlatButtonRenderer.CSS_CLASS, gridElement)[0];
    -  buttonElement.setAttribute('char', character);
    -
    -  // Trigger a focus event on the button element.
    -  goog.testing.events.fireBrowserEvent(new goog.events.Event(
    -      goog.events.EventType.FOCUS, buttonElement));
    -
    -  mockControl.$verifyAll();
    -
    -  var ariaLabel = goog.a11y.aria.getState(
    -      buttonElement, goog.a11y.aria.State.LABEL);
    -  assertEquals('The aria label should be updated when the button' +
    -      'gains focus.', characterName, ariaLabel);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/checkbox.js b/src/database/third_party/closure-library/closure/goog/ui/checkbox.js
    deleted file mode 100644
    index a76d1d78b3e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/checkbox.js
    +++ /dev/null
    @@ -1,272 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Tristate checkbox widget.
    - *
    - * @see ../demos/checkbox.html
    - */
    -
    -goog.provide('goog.ui.Checkbox');
    -goog.provide('goog.ui.Checkbox.State');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.string');
    -goog.require('goog.ui.CheckboxRenderer');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.Control');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * 3-state checkbox widget. Fires CHECK or UNCHECK events before toggled and
    - * CHANGE event after toggled by user.
    - * The checkbox can also be enabled/disabled and get focused and highlighted.
    - *
    - * @param {goog.ui.Checkbox.State=} opt_checked Checked state to set.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @param {goog.ui.CheckboxRenderer=} opt_renderer Renderer used to render or
    - *     decorate the checkbox; defaults to {@link goog.ui.CheckboxRenderer}.
    - * @constructor
    - * @extends {goog.ui.Control}
    - */
    -goog.ui.Checkbox = function(opt_checked, opt_domHelper, opt_renderer) {
    -  var renderer = opt_renderer || goog.ui.CheckboxRenderer.getInstance();
    -  goog.ui.Control.call(this, null, renderer, opt_domHelper);
    -  // The checkbox maintains its own tri-state CHECKED state.
    -  // The control class maintains DISABLED, ACTIVE, and FOCUSED (which enable tab
    -  // navigation, and keyHandling with SPACE).
    -
    -  /**
    -   * Checked state of the checkbox.
    -   * @type {goog.ui.Checkbox.State}
    -   * @private
    -   */
    -  this.checked_ = goog.isDef(opt_checked) ?
    -      opt_checked : goog.ui.Checkbox.State.UNCHECKED;
    -};
    -goog.inherits(goog.ui.Checkbox, goog.ui.Control);
    -goog.tagUnsealableClass(goog.ui.Checkbox);
    -
    -
    -/**
    - * Possible checkbox states.
    - * @enum {?boolean}
    - */
    -goog.ui.Checkbox.State = {
    -  CHECKED: true,
    -  UNCHECKED: false,
    -  UNDETERMINED: null
    -};
    -
    -
    -/**
    - * Label element bound to the checkbox.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.Checkbox.prototype.label_ = null;
    -
    -
    -/**
    - * @return {goog.ui.Checkbox.State} Checked state of the checkbox.
    - */
    -goog.ui.Checkbox.prototype.getChecked = function() {
    -  return this.checked_;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the checkbox is checked.
    - * @override
    - */
    -goog.ui.Checkbox.prototype.isChecked = function() {
    -  return this.checked_ == goog.ui.Checkbox.State.CHECKED;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the checkbox is not checked.
    - */
    -goog.ui.Checkbox.prototype.isUnchecked = function() {
    -  return this.checked_ == goog.ui.Checkbox.State.UNCHECKED;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the checkbox is in partially checked state.
    - */
    -goog.ui.Checkbox.prototype.isUndetermined = function() {
    -  return this.checked_ == goog.ui.Checkbox.State.UNDETERMINED;
    -};
    -
    -
    -/**
    - * Sets the checked state of the checkbox.
    - * @param {?boolean} checked The checked state to set.
    - * @override
    - */
    -goog.ui.Checkbox.prototype.setChecked = function(checked) {
    -  if (checked != this.checked_) {
    -    this.checked_ = /** @type {goog.ui.Checkbox.State} */ (checked);
    -    this.getRenderer().setCheckboxState(this.getElement(), this.checked_);
    -  }
    -};
    -
    -
    -/**
    - * Sets the checked state for the checkbox.  Unlike {@link #setChecked},
    - * doesn't update the checkbox's DOM.  Considered protected; to be called
    - * only by renderer code during element decoration.
    - * @param {goog.ui.Checkbox.State} checked New checkbox state.
    - */
    -goog.ui.Checkbox.prototype.setCheckedInternal = function(checked) {
    -  this.checked_ = checked;
    -};
    -
    -
    -/**
    - * Binds an HTML element to the checkbox which if clicked toggles the checkbox.
    - * Behaves the same way as the 'label' HTML tag. The label element has to be the
    - * direct or non-direct ancestor of the checkbox element because it will get the
    - * focus when keyboard support is implemented.
    - * Note: Control#enterDocument also sets aria-label on the element but
    - * Checkbox#enterDocument sets aria-labeledby on the same element which
    - * overrides the aria-label in all modern screen readers.
    - *
    - * @param {Element} label The label control to set. If null, only the checkbox
    - *     reacts to clicks.
    - */
    -goog.ui.Checkbox.prototype.setLabel = function(label) {
    -  if (this.isInDocument()) {
    -    this.exitDocument();
    -    this.label_ = label;
    -    this.enterDocument();
    -  } else {
    -    this.label_ = label;
    -  }
    -};
    -
    -
    -/**
    - * Toggles the checkbox. State transitions:
    - * <ul>
    - *   <li>unchecked -> checked
    - *   <li>undetermined -> checked
    - *   <li>checked -> unchecked
    - * </ul>
    - */
    -goog.ui.Checkbox.prototype.toggle = function() {
    -  this.setChecked(this.checked_ ? goog.ui.Checkbox.State.UNCHECKED :
    -      goog.ui.Checkbox.State.CHECKED);
    -};
    -
    -
    -/** @override */
    -goog.ui.Checkbox.prototype.enterDocument = function() {
    -  goog.ui.Checkbox.base(this, 'enterDocument');
    -  if (this.isHandleMouseEvents()) {
    -    var handler = this.getHandler();
    -    // Listen to the label, if it was set.
    -    if (this.label_) {
    -      // Any mouse events that happen to the associated label should have the
    -      // same effect on the checkbox as if they were happening to the checkbox
    -      // itself.
    -      handler.
    -          listen(this.label_, goog.events.EventType.CLICK,
    -              this.handleClickOrSpace_).
    -          listen(this.label_, goog.events.EventType.MOUSEOVER,
    -              this.handleMouseOver).
    -          listen(this.label_, goog.events.EventType.MOUSEOUT,
    -              this.handleMouseOut).
    -          listen(this.label_, goog.events.EventType.MOUSEDOWN,
    -              this.handleMouseDown).
    -          listen(this.label_, goog.events.EventType.MOUSEUP,
    -              this.handleMouseUp);
    -    }
    -    // Checkbox needs to explicitly listen for click event.
    -    handler.listen(this.getElement(),
    -        goog.events.EventType.CLICK, this.handleClickOrSpace_);
    -  }
    -
    -  // Set aria label.
    -  var checkboxElement = this.getElementStrict();
    -  if (this.label_ && checkboxElement != this.label_ &&
    -      goog.string.isEmptyOrWhitespace(goog.a11y.aria.getLabel(checkboxElement))) {
    -    if (!this.label_.id) {
    -      this.label_.id = this.makeId('lbl');
    -    }
    -    goog.a11y.aria.setState(checkboxElement,
    -        goog.a11y.aria.State.LABELLEDBY,
    -        this.label_.id);
    -  }
    -};
    -
    -
    -/**
    - * Fix for tabindex not being updated so that disabled checkbox is not
    - * focusable. In particular this fails in Chrome.
    - * Note: in general tabIndex=-1 will prevent from keyboard focus but enables
    - * mouse focus, however in this case the control class prevents mouse focus.
    - * @override
    - */
    -goog.ui.Checkbox.prototype.setEnabled = function(enabled) {
    -  goog.ui.Checkbox.base(this, 'setEnabled', enabled);
    -  var el = this.getElement();
    -  if (el) {
    -    el.tabIndex = this.isEnabled() ? 0 : -1;
    -  }
    -};
    -
    -
    -/**
    - * Handles the click event.
    - * @param {!goog.events.BrowserEvent} e The event.
    - * @private
    - */
    -goog.ui.Checkbox.prototype.handleClickOrSpace_ = function(e) {
    -  e.stopPropagation();
    -  var eventType = this.checked_ ? goog.ui.Component.EventType.UNCHECK :
    -      goog.ui.Component.EventType.CHECK;
    -  if (this.isEnabled() && !e.target.href && this.dispatchEvent(eventType)) {
    -    e.preventDefault();  // Prevent scrolling in Chrome if SPACE is pressed.
    -    this.toggle();
    -    this.dispatchEvent(goog.ui.Component.EventType.CHANGE);
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.Checkbox.prototype.handleKeyEventInternal = function(e) {
    -  if (e.keyCode == goog.events.KeyCodes.SPACE) {
    -    this.performActionInternal(e);
    -    this.handleClickOrSpace_(e);
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Register this control so it can be created from markup.
    - */
    -goog.ui.registry.setDecoratorByClassName(
    -    goog.ui.CheckboxRenderer.CSS_CLASS,
    -    function() {
    -      return new goog.ui.Checkbox();
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/checkbox_test.html b/src/database/third_party/closure-library/closure/goog/ui/checkbox_test.html
    deleted file mode 100644
    index 6cbbd2d61b6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/checkbox_test.html
    +++ /dev/null
    @@ -1,38 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.Checkbox
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.ui.CheckboxTest');
    -  </script>
    - </head>
    - <body>
    -  <div>
    -   <span id="decorate" class="goog-checkbox">
    -   </span>
    -   <span id="normal" class="goog-checkbox">
    -   </span>
    -   <span id="checked" class="goog-checkbox goog-checkbox-checked">
    -   </span>
    -   <span id="unchecked" class="goog-checkbox goog-checkbox-unchecked">
    -   </span>
    -   <span id="undetermined" class="goog-checkbox goog-checkbox-undetermined">
    -   </span>
    -   <span id="disabled" class="goog-checkbox goog-checkbox-disabled">
    -   </span>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/checkbox_test.js b/src/database/third_party/closure-library/closure/goog/ui/checkbox_test.js
    deleted file mode 100644
    index 54558d1cd36..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/checkbox_test.js
    +++ /dev/null
    @@ -1,451 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.CheckboxTest');
    -goog.setTestOnly('goog.ui.CheckboxTest');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.Checkbox');
    -goog.require('goog.ui.CheckboxRenderer');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.ControlRenderer');
    -goog.require('goog.ui.decorate');
    -
    -var checkbox;
    -
    -function setUp() {
    -  checkbox = new goog.ui.Checkbox();
    -}
    -
    -function tearDown() {
    -  checkbox.dispose();
    -}
    -
    -function testClassNames() {
    -  checkbox.createDom();
    -
    -  checkbox.setChecked(false);
    -  assertSameElements('classnames of unchecked checkbox',
    -      ['goog-checkbox', 'goog-checkbox-unchecked'],
    -      goog.dom.classlist.get(checkbox.getElement()));
    -
    -  checkbox.setChecked(true);
    -  assertSameElements('classnames of checked checkbox',
    -      ['goog-checkbox', 'goog-checkbox-checked'],
    -      goog.dom.classlist.get(checkbox.getElement()));
    -
    -  checkbox.setChecked(null);
    -  assertSameElements('classnames of partially checked checkbox',
    -      ['goog-checkbox', 'goog-checkbox-undetermined'],
    -      goog.dom.classlist.get(checkbox.getElement()));
    -
    -  checkbox.setEnabled(false);
    -  assertSameElements('classnames of partially checked disabled checkbox',
    -      ['goog-checkbox',
    -       'goog-checkbox-undetermined',
    -       'goog-checkbox-disabled'],
    -      goog.dom.classlist.get(checkbox.getElement()));
    -}
    -
    -function testIsEnabled() {
    -  assertTrue('enabled by default', checkbox.isEnabled());
    -  checkbox.setEnabled(false);
    -  assertFalse('has been disabled', checkbox.isEnabled());
    -}
    -
    -function testCheckedState() {
    -  assertTrue('unchecked by default', !checkbox.isChecked() &&
    -      checkbox.isUnchecked() && !checkbox.isUndetermined());
    -
    -  checkbox.setChecked(true);
    -  assertTrue('set to checked', checkbox.isChecked() &&
    -      !checkbox.isUnchecked() && !checkbox.isUndetermined());
    -
    -  checkbox.setChecked(null);
    -  assertTrue('set to partially checked', !checkbox.isChecked() &&
    -      !checkbox.isUnchecked() && checkbox.isUndetermined());
    -}
    -
    -function testToggle() {
    -  checkbox.setChecked(null);
    -  checkbox.toggle();
    -  assertTrue('undetermined -> checked', checkbox.getChecked());
    -  checkbox.toggle();
    -  assertFalse('checked -> unchecked', checkbox.getChecked());
    -  checkbox.toggle();
    -  assertTrue('unchecked -> checked', checkbox.getChecked());
    -}
    -
    -function testEvents() {
    -  checkbox.render();
    -
    -  var events = [];
    -  goog.events.listen(checkbox,
    -      [
    -        goog.ui.Component.EventType.ACTION,
    -        goog.ui.Component.EventType.CHECK,
    -        goog.ui.Component.EventType.UNCHECK,
    -        goog.ui.Component.EventType.CHANGE
    -      ],
    -      function(e) {
    -        events.push(e.type);
    -      });
    -
    -  checkbox.setEnabled(false);
    -  goog.testing.events.fireClickSequence(checkbox.getElement());
    -  assertArrayEquals('disabled => no events', [], events);
    -  assertFalse('checked state did not change', checkbox.getChecked());
    -  events = [];
    -
    -  checkbox.setEnabled(true);
    -  goog.testing.events.fireClickSequence(checkbox.getElement());
    -  assertArrayEquals('ACTION+CHECK+CHANGE fired',
    -      [
    -        goog.ui.Component.EventType.ACTION,
    -        goog.ui.Component.EventType.CHECK,
    -        goog.ui.Component.EventType.CHANGE
    -      ],
    -      events);
    -  assertTrue('checkbox became checked', checkbox.getChecked());
    -  events = [];
    -
    -  goog.testing.events.fireClickSequence(checkbox.getElement());
    -  assertArrayEquals('ACTION+UNCHECK+CHANGE fired',
    -      [
    -        goog.ui.Component.EventType.ACTION,
    -        goog.ui.Component.EventType.UNCHECK,
    -        goog.ui.Component.EventType.CHANGE
    -      ],
    -      events);
    -  assertFalse('checkbox became unchecked', checkbox.getChecked());
    -  events = [];
    -
    -  goog.events.listen(checkbox, goog.ui.Component.EventType.CHECK,
    -      function(e) {
    -        e.preventDefault();
    -      });
    -  goog.testing.events.fireClickSequence(checkbox.getElement());
    -  assertArrayEquals('ACTION+CHECK fired',
    -      [
    -        goog.ui.Component.EventType.ACTION,
    -        goog.ui.Component.EventType.CHECK
    -      ],
    -      events);
    -  assertFalse('toggling has been prevented', checkbox.getChecked());
    -}
    -
    -function testCheckboxAriaLabelledby() {
    -  var label = goog.dom.createElement('div');
    -  var label2 = goog.dom.createElement('div', {id: checkbox.makeId('foo')});
    -  document.body.appendChild(label);
    -  document.body.appendChild(label2);
    -  try {
    -    checkbox.setChecked(false);
    -    checkbox.setLabel(label);
    -    checkbox.render(label);
    -    assertNotNull(checkbox.getElement());
    -    assertEquals(label.id,
    -        goog.a11y.aria.getState(checkbox.getElement(),
    -            goog.a11y.aria.State.LABELLEDBY));
    -
    -    checkbox.setLabel(label2);
    -    assertEquals(label2.id,
    -        goog.a11y.aria.getState(checkbox.getElement(),
    -            goog.a11y.aria.State.LABELLEDBY));
    -  } finally {
    -    document.body.removeChild(label);
    -    document.body.removeChild(label2);
    -  }
    -}
    -
    -function testLabel() {
    -  var label = goog.dom.createElement('div');
    -  document.body.appendChild(label);
    -  try {
    -    checkbox.setChecked(false);
    -    checkbox.setLabel(label);
    -    checkbox.render(label);
    -
    -    // Clicking on label toggles checkbox.
    -    goog.testing.events.fireClickSequence(label);
    -    assertTrue('checkbox toggled if the label is clicked',
    -        checkbox.getChecked());
    -    goog.testing.events.fireClickSequence(checkbox.getElement());
    -    assertFalse('checkbox toggled if it is clicked', checkbox.getChecked());
    -
    -    // Test that mouse events on the label have the correct effect on the
    -    // checkbox state when it is enabled.
    -    checkbox.setEnabled(true);
    -    goog.testing.events.fireMouseOverEvent(label);
    -    assertTrue(checkbox.hasState(goog.ui.Component.State.HOVER));
    -    assertContains('checkbox gets hover state on mouse over',
    -        'goog-checkbox-hover', goog.dom.classlist.get(checkbox.getElement()));
    -    goog.testing.events.fireMouseDownEvent(label);
    -    assertTrue(checkbox.hasState(goog.ui.Component.State.ACTIVE));
    -    assertContains('checkbox gets active state on label mousedown',
    -        'goog-checkbox-active',
    -        goog.dom.classlist.get(checkbox.getElement()));
    -    goog.testing.events.fireMouseOutEvent(checkbox.getElement());
    -    assertFalse(checkbox.hasState(goog.ui.Component.State.HOVER));
    -    assertNotContains('checkbox does not have hover state after mouse out',
    -        'goog-checkbox-hover', goog.dom.classlist.get(checkbox.getElement()));
    -    assertFalse(checkbox.hasState(goog.ui.Component.State.ACTIVE));
    -    assertNotContains('checkbox does not have active state after mouse out',
    -        'goog-checkbox-active', goog.dom.classlist.get(checkbox.getElement()));
    -
    -    // Test label mouse events on disabled checkbox.
    -    checkbox.setEnabled(false);
    -    goog.testing.events.fireMouseOverEvent(label);
    -    assertFalse(checkbox.hasState(goog.ui.Component.State.HOVER));
    -    assertNotContains(
    -        'disabled checkbox does not get hover state on mouseover',
    -        'goog-checkbox-hover', goog.dom.classlist.get(checkbox.getElement()));
    -    goog.testing.events.fireMouseDownEvent(label);
    -    assertFalse(checkbox.hasState(goog.ui.Component.State.ACTIVE));
    -    assertNotContains('disabled checkbox does not get active state mousedown',
    -        'goog-checkbox-active',
    -        goog.dom.classlist.get(checkbox.getElement()));
    -    goog.testing.events.fireMouseOutEvent(checkbox.getElement());
    -    assertFalse(checkbox.hasState(goog.ui.Component.State.ACTIVE));
    -    assertNotContains('checkbox does not get stuck in hover state',
    -        'goog-checkbox-hover', goog.dom.classlist.get(checkbox.getElement()));
    -
    -    // Making the label null prevents it from affecting checkbox state.
    -    checkbox.setEnabled(true);
    -    checkbox.setLabel(null);
    -    goog.testing.events.fireClickSequence(label);
    -    assertFalse('label element deactivated', checkbox.getChecked());
    -    goog.testing.events.fireClickSequence(checkbox.getElement());
    -    assertTrue('checkbox still active', checkbox.getChecked());
    -  } finally {
    -    document.body.removeChild(label);
    -  }
    -}
    -
    -function testConstructor() {
    -  assertEquals('state is unchecked', goog.ui.Checkbox.State.UNCHECKED,
    -      checkbox.getChecked());
    -
    -  var testCheckboxWithState = new goog.ui.Checkbox(
    -      goog.ui.Checkbox.State.UNDETERMINED);
    -  assertNotNull('checkbox created with custom state', testCheckboxWithState);
    -  assertEquals('checkbox state is undetermined',
    -      goog.ui.Checkbox.State.UNDETERMINED,
    -      testCheckboxWithState.getChecked());
    -  testCheckboxWithState.dispose();
    -}
    -
    -function testCustomRenderer() {
    -  var cssClass = 'my-custom-checkbox';
    -  var renderer = goog.ui.ControlRenderer.getCustomRenderer(
    -      goog.ui.CheckboxRenderer, cssClass);
    -  var customCheckbox = new goog.ui.Checkbox(
    -      undefined, undefined, renderer);
    -  customCheckbox.createDom();
    -  assertElementsEquals(
    -      ['my-custom-checkbox', 'my-custom-checkbox-unchecked'],
    -      goog.dom.classlist.get(customCheckbox.getElement()));
    -  customCheckbox.setChecked(true);
    -  assertElementsEquals(
    -      ['my-custom-checkbox', 'my-custom-checkbox-checked'],
    -      goog.dom.classlist.get(customCheckbox.getElement()));
    -  customCheckbox.setChecked(null);
    -  assertElementsEquals(
    -      ['my-custom-checkbox', 'my-custom-checkbox-undetermined'],
    -      goog.dom.classlist.get(customCheckbox.getElement()));
    -  customCheckbox.dispose();
    -}
    -
    -function testGetAriaRole() {
    -  checkbox.createDom();
    -  assertNotNull(checkbox.getElement());
    -  assertEquals("Checkbox's ARIA role should be 'checkbox'",
    -      goog.a11y.aria.Role.CHECKBOX,
    -      goog.a11y.aria.getRole(checkbox.getElement()));
    -}
    -
    -function testCreateDomUpdateAriaState() {
    -  checkbox.createDom();
    -  assertNotNull(checkbox.getElement());
    -  assertEquals('Checkbox must have default false ARIA state aria-checked',
    -      'false', goog.a11y.aria.getState(checkbox.getElement(),
    -          goog.a11y.aria.State.CHECKED));
    -
    -  checkbox.setChecked(goog.ui.Checkbox.State.CHECKED);
    -  assertEquals('Checkbox must have true ARIA state aria-checked', 'true',
    -      goog.a11y.aria.getState(checkbox.getElement(),
    -          goog.a11y.aria.State.CHECKED));
    -
    -  checkbox.setChecked(goog.ui.Checkbox.State.UNCHECKED);
    -  assertEquals('Checkbox must have false ARIA state aria-checked', 'false',
    -      goog.a11y.aria.getState(checkbox.getElement(),
    -          goog.a11y.aria.State.CHECKED));
    -
    -  checkbox.setChecked(goog.ui.Checkbox.State.UNDETERMINED);
    -  assertEquals('Checkbox must have mixed ARIA state aria-checked', 'mixed',
    -      goog.a11y.aria.getState(checkbox.getElement(),
    -          goog.a11y.aria.State.CHECKED));
    -}
    -
    -function testDecorateUpdateAriaState() {
    -  var decorateSpan = goog.dom.getElement('decorate');
    -  checkbox.decorate(decorateSpan);
    -
    -  assertEquals('Checkbox must have default false ARIA state aria-checked',
    -      'false', goog.a11y.aria.getState(checkbox.getElement(),
    -          goog.a11y.aria.State.CHECKED));
    -
    -  checkbox.setChecked(goog.ui.Checkbox.State.CHECKED);
    -  assertEquals('Checkbox must have true ARIA state aria-checked', 'true',
    -      goog.a11y.aria.getState(checkbox.getElement(),
    -          goog.a11y.aria.State.CHECKED));
    -
    -  checkbox.setChecked(goog.ui.Checkbox.State.UNCHECKED);
    -  assertEquals('Checkbox must have false ARIA state aria-checked', 'false',
    -      goog.a11y.aria.getState(checkbox.getElement(),
    -          goog.a11y.aria.State.CHECKED));
    -
    -  checkbox.setChecked(goog.ui.Checkbox.State.UNDETERMINED);
    -  assertEquals('Checkbox must have mixed ARIA state aria-checked', 'mixed',
    -      goog.a11y.aria.getState(checkbox.getElement(),
    -          goog.a11y.aria.State.CHECKED));
    -}
    -
    -function testSpaceKey() {
    -  var normalSpan = goog.dom.getElement('normal');
    -
    -  checkbox.decorate(normalSpan);
    -  assertEquals('default state is unchecked',
    -      goog.ui.Checkbox.State.UNCHECKED, checkbox.getChecked());
    -  goog.testing.events.fireKeySequence(normalSpan, goog.events.KeyCodes.SPACE);
    -  assertEquals('SPACE toggles checkbox to be checked',
    -      goog.ui.Checkbox.State.CHECKED, checkbox.getChecked());
    -  goog.testing.events.fireKeySequence(normalSpan, goog.events.KeyCodes.SPACE);
    -  assertEquals('another SPACE toggles checkbox to be unchecked',
    -      goog.ui.Checkbox.State.UNCHECKED, checkbox.getChecked());
    -
    -  // Enter for example doesn't work
    -  goog.testing.events.fireKeySequence(normalSpan, goog.events.KeyCodes.ENTER);
    -  assertEquals('Enter leaves checkbox unchecked',
    -      goog.ui.Checkbox.State.UNCHECKED, checkbox.getChecked());
    -}
    -
    -function testSpaceKeyFiresEvents() {
    -  var normalSpan = goog.dom.getElement('normal');
    -
    -  checkbox.decorate(normalSpan);
    -  var events = [];
    -  goog.events.listen(checkbox,
    -      [
    -        goog.ui.Component.EventType.ACTION,
    -        goog.ui.Component.EventType.CHECK,
    -        goog.ui.Component.EventType.UNCHECK,
    -        goog.ui.Component.EventType.CHANGE
    -      ],
    -      function(e) {
    -        events.push(e.type);
    -      });
    -
    -  assertEquals('Unexpected default state.',
    -      goog.ui.Checkbox.State.UNCHECKED, checkbox.getChecked());
    -  goog.testing.events.fireKeySequence(normalSpan, goog.events.KeyCodes.SPACE);
    -  assertArrayEquals('Unexpected events fired when checking with spacebar.',
    -      [
    -        goog.ui.Component.EventType.ACTION,
    -        goog.ui.Component.EventType.CHECK,
    -        goog.ui.Component.EventType.CHANGE
    -      ],
    -      events);
    -  assertEquals('Unexpected state after checking.',
    -      goog.ui.Checkbox.State.CHECKED, checkbox.getChecked());
    -
    -  events = [];
    -  goog.testing.events.fireKeySequence(normalSpan, goog.events.KeyCodes.SPACE);
    -  assertArrayEquals('Unexpected events fired when unchecking with spacebar.',
    -      [
    -        goog.ui.Component.EventType.ACTION,
    -        goog.ui.Component.EventType.UNCHECK,
    -        goog.ui.Component.EventType.CHANGE
    -      ],
    -      events);
    -  assertEquals('Unexpected state after unchecking.',
    -      goog.ui.Checkbox.State.UNCHECKED, checkbox.getChecked());
    -
    -  events = [];
    -  goog.events.listenOnce(checkbox, goog.ui.Component.EventType.CHECK,
    -      function(e) {
    -        e.preventDefault();
    -      });
    -  goog.testing.events.fireKeySequence(normalSpan, goog.events.KeyCodes.SPACE);
    -  assertArrayEquals('Unexpected events fired when checking with spacebar and ' +
    -      'the check event is cancelled.',
    -      [
    -        goog.ui.Component.EventType.ACTION,
    -        goog.ui.Component.EventType.CHECK
    -      ],
    -      events);
    -  assertEquals('Unexpected state after check event is cancelled.',
    -      goog.ui.Checkbox.State.UNCHECKED, checkbox.getChecked());
    -}
    -
    -function testDecorate() {
    -  var normalSpan = goog.dom.getElement('normal');
    -  var checkedSpan = goog.dom.getElement('checked');
    -  var uncheckedSpan = goog.dom.getElement('unchecked');
    -  var undeterminedSpan = goog.dom.getElement('undetermined');
    -  var disabledSpan = goog.dom.getElement('disabled');
    -
    -  validateCheckBox(normalSpan, goog.ui.Checkbox.State.UNCHECKED);
    -  validateCheckBox(checkedSpan, goog.ui.Checkbox.State.CHECKED);
    -  validateCheckBox(uncheckedSpan, goog.ui.Checkbox.State.UNCHECKED);
    -  validateCheckBox(undeterminedSpan, goog.ui.Checkbox.State.UNDETERMINED);
    -  validateCheckBox(disabledSpan, goog.ui.Checkbox.State.UNCHECKED, true);
    -}
    -
    -function validateCheckBox(span, state, opt_disabled) {
    -  var testCheckbox = goog.ui.decorate(span);
    -  assertNotNull('checkbox created', testCheckbox);
    -  assertEquals('decorate was successful',
    -      goog.ui.Checkbox, testCheckbox.constructor);
    -  assertEquals('checkbox state should be: ' + state, state,
    -      testCheckbox.getChecked());
    -  assertEquals('checkbox is ' + (!opt_disabled ? 'enabled' : 'disabled'),
    -      !opt_disabled, testCheckbox.isEnabled());
    -  testCheckbox.dispose();
    -}
    -
    -function testSetAriaLabel() {
    -  assertNull('Checkbox must not have aria label by default',
    -      checkbox.getAriaLabel());
    -  checkbox.setAriaLabel('Checkbox 1');
    -  checkbox.render();
    -  var el = checkbox.getElementStrict();
    -  assertEquals('Checkbox element must have expected aria-label', 'Checkbox 1',
    -      el.getAttribute('aria-label'));
    -  assertEquals('Checkbox element must have expected aria-role', 'checkbox',
    -      el.getAttribute('role'));
    -  checkbox.setAriaLabel('Checkbox 2');
    -  assertEquals('Checkbox element must have updated aria-label', 'Checkbox 2',
    -      el.getAttribute('aria-label'));
    -  assertEquals('Checkbox element must have expected aria-role', 'checkbox',
    -      el.getAttribute('role'));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/checkboxmenuitem.js b/src/database/third_party/closure-library/closure/goog/ui/checkboxmenuitem.js
    deleted file mode 100644
    index 29127016bea..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/checkboxmenuitem.js
    +++ /dev/null
    @@ -1,53 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A menu item class that supports checkbox semantics.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.CheckBoxMenuItem');
    -
    -goog.require('goog.ui.MenuItem');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * Class representing a checkbox menu item.  This is just a convenience class
    - * that extends {@link goog.ui.MenuItem} by making it checkable.
    - *
    - * @param {goog.ui.ControlContent} content Text caption or DOM structure to
    - *     display as the content of the item (use to add icons or styling to
    - *     menus).
    - * @param {*=} opt_model Data/model associated with the menu item.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper used for
    - *     document interactions.
    - * @constructor
    - * @extends {goog.ui.MenuItem}
    - */
    -goog.ui.CheckBoxMenuItem = function(content, opt_model, opt_domHelper) {
    -  goog.ui.MenuItem.call(this, content, opt_model, opt_domHelper);
    -  this.setCheckable(true);
    -};
    -goog.inherits(goog.ui.CheckBoxMenuItem, goog.ui.MenuItem);
    -
    -
    -// Register a decorator factory function for goog.ui.CheckBoxMenuItems.
    -goog.ui.registry.setDecoratorByClassName(
    -    goog.getCssName('goog-checkbox-menuitem'), function() {
    -      // CheckBoxMenuItem defaults to using MenuItemRenderer.
    -      return new goog.ui.CheckBoxMenuItem(null);
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/checkboxrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/checkboxrenderer.js
    deleted file mode 100644
    index 5a423b434cd..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/checkboxrenderer.js
    +++ /dev/null
    @@ -1,190 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Default renderer for {@link goog.ui.Checkbox}s.
    - *
    - */
    -
    -goog.provide('goog.ui.CheckboxRenderer');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.object');
    -goog.require('goog.ui.ControlRenderer');
    -
    -
    -
    -/**
    - * Default renderer for {@link goog.ui.Checkbox}s.  Extends the superclass
    - * to support checkbox states:
    - * @constructor
    - * @extends {goog.ui.ControlRenderer}
    - */
    -goog.ui.CheckboxRenderer = function() {
    -  goog.ui.CheckboxRenderer.base(this, 'constructor');
    -};
    -goog.inherits(goog.ui.CheckboxRenderer, goog.ui.ControlRenderer);
    -goog.addSingletonGetter(goog.ui.CheckboxRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.CheckboxRenderer.CSS_CLASS = goog.getCssName('goog-checkbox');
    -
    -
    -/** @override */
    -goog.ui.CheckboxRenderer.prototype.createDom = function(checkbox) {
    -  var element = checkbox.getDomHelper().createDom(
    -      'span', this.getClassNames(checkbox).join(' '));
    -
    -  var state = checkbox.getChecked();
    -  this.setCheckboxState(element, state);
    -
    -  return element;
    -};
    -
    -
    -/** @override */
    -goog.ui.CheckboxRenderer.prototype.decorate = function(checkbox, element) {
    -  // The superclass implementation takes care of common attributes; we only
    -  // need to set the checkbox state.
    -  element = goog.ui.CheckboxRenderer.base(this, 'decorate', checkbox, element);
    -  goog.asserts.assert(element);
    -  var classes = goog.dom.classlist.get(element);
    -  // Update the checked state of the element based on its css classNames
    -  // with the following order: undetermined -> checked -> unchecked.
    -  var checked = /** @suppress {missingRequire} */ (
    -      goog.ui.Checkbox.State.UNCHECKED);
    -  if (goog.array.contains(classes,
    -      this.getClassForCheckboxState(
    -          /** @suppress {missingRequire} */
    -          goog.ui.Checkbox.State.UNDETERMINED))) {
    -    checked = (/** @suppress {missingRequire} */
    -        goog.ui.Checkbox.State.UNDETERMINED);
    -  } else if (goog.array.contains(classes,
    -      this.getClassForCheckboxState(
    -          /** @suppress {missingRequire} */ goog.ui.Checkbox.State.CHECKED))) {
    -    checked = /** @suppress {missingRequire} */ goog.ui.Checkbox.State.CHECKED;
    -  } else if (goog.array.contains(classes,
    -      this.getClassForCheckboxState(/** @suppress {missingRequire} */
    -          goog.ui.Checkbox.State.UNCHECKED))) {
    -    checked = (/** @suppress {missingRequire} */
    -        goog.ui.Checkbox.State.UNCHECKED);
    -  }
    -  checkbox.setCheckedInternal(checked);
    -  goog.asserts.assert(element, 'The element cannot be null.');
    -  goog.a11y.aria.setState(element, goog.a11y.aria.State.CHECKED,
    -      this.ariaStateFromCheckState_(checked));
    -
    -  return element;
    -};
    -
    -
    -/**
    - * Returns the ARIA role to be applied to checkboxes.
    - * @return {goog.a11y.aria.Role} ARIA role.
    - * @override
    - */
    -goog.ui.CheckboxRenderer.prototype.getAriaRole = function() {
    -  return goog.a11y.aria.Role.CHECKBOX;
    -};
    -
    -
    -/**
    - * Updates the appearance of the control in response to a checkbox state
    - * change.
    - * @param {Element} element Checkbox element.
    - * @param {goog.ui.Checkbox.State} state Updated checkbox state.
    - */
    -goog.ui.CheckboxRenderer.prototype.setCheckboxState = function(
    -    element, state) {
    -  if (element) {
    -    goog.asserts.assert(element);
    -    var classToAdd = this.getClassForCheckboxState(state);
    -    goog.asserts.assert(classToAdd);
    -    goog.asserts.assert(element);
    -    if (goog.dom.classlist.contains(element, classToAdd)) {
    -      return;
    -    }
    -    goog.object.forEach(
    -        /** @suppress {missingRequire} */ goog.ui.Checkbox.State,
    -        function(state) {
    -          var className = this.getClassForCheckboxState(state);
    -          goog.asserts.assert(element);
    -          goog.dom.classlist.enable(element, className,
    -                                    className == classToAdd);
    -        }, this);
    -    goog.a11y.aria.setState(element, goog.a11y.aria.State.CHECKED,
    -        this.ariaStateFromCheckState_(state));
    -  }
    -};
    -
    -
    -/**
    - * Gets the checkbox's ARIA (accessibility) state from its checked state.
    - * @param {goog.ui.Checkbox.State} state Checkbox state.
    - * @return {string} The value of goog.a11y.aria.state.CHECKED. Either 'true',
    - *     'false', or 'mixed'.
    - * @private
    - */
    -goog.ui.CheckboxRenderer.prototype.ariaStateFromCheckState_ = function(state) {
    -  if (state ==
    -      /** @suppress {missingRequire} */ goog.ui.Checkbox.State.UNDETERMINED) {
    -    return 'mixed';
    -  } else if (state ==
    -             /** @suppress {missingRequire} */ goog.ui.Checkbox.State.CHECKED) {
    -    return 'true';
    -  } else {
    -    return 'false';
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.CheckboxRenderer.prototype.getCssClass = function() {
    -  return goog.ui.CheckboxRenderer.CSS_CLASS;
    -};
    -
    -
    -/**
    - * Takes a single {@link goog.ui.Checkbox.State}, and returns the
    - * corresponding CSS class name.
    - * @param {goog.ui.Checkbox.State} state Checkbox state.
    - * @return {string} CSS class representing the given state.
    - * @protected
    - */
    -goog.ui.CheckboxRenderer.prototype.getClassForCheckboxState = function(state) {
    -  var baseClass = this.getStructuralCssClass();
    -  if (state ==
    -      /** @suppress {missingRequire} */ goog.ui.Checkbox.State.CHECKED) {
    -    return goog.getCssName(baseClass, 'checked');
    -  } else if (state ==
    -             /** @suppress {missingRequire} */
    -             goog.ui.Checkbox.State.UNCHECKED) {
    -    return goog.getCssName(baseClass, 'unchecked');
    -  } else if (state ==
    -             /** @suppress {missingRequire} */
    -             goog.ui.Checkbox.State.UNDETERMINED) {
    -    return goog.getCssName(baseClass, 'undetermined');
    -  }
    -  throw Error('Invalid checkbox state: ' + state);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/colorbutton.js b/src/database/third_party/closure-library/closure/goog/ui/colorbutton.js
    deleted file mode 100644
    index fc598789c0b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/colorbutton.js
    +++ /dev/null
    @@ -1,59 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A color button rendered via
    - * {@link goog.ui.ColorButtonRenderer}.
    - *
    - */
    -
    -goog.provide('goog.ui.ColorButton');
    -
    -goog.require('goog.ui.Button');
    -goog.require('goog.ui.ColorButtonRenderer');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * A color button control.  Identical to {@link goog.ui.Button}, except it
    - * defaults its renderer to {@link goog.ui.ColorButtonRenderer}.
    - * This button displays a particular color and is clickable.
    - * It is primarily useful with {@link goog.ui.ColorSplitBehavior} to cache the
    - * last selected color.
    - *
    - * @param {goog.ui.ControlContent} content Text caption or existing DOM
    - *    structure to display as the button's caption.
    - * @param {goog.ui.ButtonRenderer=} opt_renderer Optional renderer used to
    - *    render or decorate the button; defaults to
    - *    {@link goog.ui.ColorButtonRenderer}.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *    document interaction.
    - * @constructor
    - * @extends {goog.ui.Button}
    - * @final
    - */
    -goog.ui.ColorButton = function(content, opt_renderer, opt_domHelper) {
    -  goog.ui.Button.call(this, content, opt_renderer ||
    -      goog.ui.ColorButtonRenderer.getInstance(), opt_domHelper);
    -};
    -goog.inherits(goog.ui.ColorButton, goog.ui.Button);
    -
    -// Register a decorator factory function for goog.ui.ColorButtons.
    -goog.ui.registry.setDecoratorByClassName(goog.ui.ColorButtonRenderer.CSS_CLASS,
    -    function() {
    -      // ColorButton defaults to using ColorButtonRenderer.
    -      return new goog.ui.ColorButton(null);
    -    });
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/colorbutton_test.html b/src/database/third_party/closure-library/closure/goog/ui/colorbutton_test.html
    deleted file mode 100644
    index 3828ae3d531..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/colorbutton_test.html
    +++ /dev/null
    @@ -1,26 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.ColorButton
    -  </title>
    -  <script type="text/javascript" src="../base.js">
    -  </script>
    -  <script type="text/javascript">
    -   goog.require('goog.ui.ColorButtonTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="buttonDiv">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/colorbutton_test.js b/src/database/third_party/closure-library/closure/goog/ui/colorbutton_test.js
    deleted file mode 100644
    index b3f21b6da31..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/colorbutton_test.js
    +++ /dev/null
    @@ -1,64 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.ColorButtonTest');
    -goog.setTestOnly('goog.ui.ColorButtonTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.ColorButton');
    -goog.require('goog.ui.decorate');
    -
    -var button, button2;
    -var buttonDiv;
    -
    -function setUp() {
    -  buttonDiv = goog.dom.getElement('buttonDiv');
    -}
    -
    -function tearDown() {
    -  goog.dom.removeChildren(buttonDiv);
    -  goog.dispose(button);
    -  goog.dispose(button2);
    -  button = null;
    -  button2 = null;
    -}
    -
    -function testRender() {
    -  button = new goog.ui.ColorButton('test');
    -  assertNotNull('button should be valid', button);
    -  button.render(buttonDiv);
    -  assertColorButton(button.getElement());
    -}
    -
    -function testDecorate() {
    -  var colorDiv = goog.dom.createDom('div', 'goog-color-button');
    -  goog.dom.appendChild(buttonDiv, colorDiv);
    -  button2 = goog.ui.decorate(colorDiv);
    -  assertNotNull('button should be valid', button2);
    -  assertColorButton(button2.getElement());
    -}
    -
    -function assertColorButton(div) {
    -  assertTrue('button className contains goog-color-button',
    -      goog.array.contains(goog.dom.classlist.get(div), 'goog-color-button'));
    -  var caption = goog.asserts.assertElement(
    -      div.firstChild.firstChild.firstChild);
    -  assertTrue('caption className contains goog-color-button',
    -      goog.array.contains(goog.dom.classlist.get(caption),
    -          'goog-color-button'));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/colorbuttonrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/colorbuttonrenderer.js
    deleted file mode 100644
    index 97e6ffffc9c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/colorbuttonrenderer.js
    +++ /dev/null
    @@ -1,75 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Renderer for {@link goog.ui.ColorButton}s.
    - *
    - */
    -
    -goog.provide('goog.ui.ColorButtonRenderer');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.functions');
    -goog.require('goog.ui.ColorMenuButtonRenderer');
    -
    -
    -
    -/**
    - * Renderer for {@link goog.ui.ColorButton}s.
    - * Uses {@link goog.ui.ColorMenuButton}s but disables the dropdown.
    - *
    - * @constructor
    - * @extends {goog.ui.ColorMenuButtonRenderer}
    - * @final
    - */
    -goog.ui.ColorButtonRenderer = function() {
    -  goog.ui.ColorButtonRenderer.base(this, 'constructor');
    -
    -  /**
    -   * @override
    -   */
    -  // TODO(user): enable disabling the dropdown in goog.ui.ColorMenuButton
    -  this.createDropdown = goog.functions.NULL;
    -
    -};
    -goog.inherits(goog.ui.ColorButtonRenderer, goog.ui.ColorMenuButtonRenderer);
    -goog.addSingletonGetter(goog.ui.ColorButtonRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer. Additionally, applies class to the button's caption.
    - * @type {string}
    - */
    -goog.ui.ColorButtonRenderer.CSS_CLASS = goog.getCssName('goog-color-button');
    -
    -
    -/** @override */
    -goog.ui.ColorButtonRenderer.prototype.createCaption = function(content, dom) {
    -  var caption = goog.ui.ColorButtonRenderer.base(
    -      this, 'createCaption', content, dom);
    -  goog.asserts.assert(caption);
    -  goog.dom.classlist.add(caption, goog.ui.ColorButtonRenderer.CSS_CLASS);
    -  return caption;
    -};
    -
    -
    -/** @override */
    -goog.ui.ColorButtonRenderer.prototype.initializeDom = function(button) {
    -  goog.ui.ColorButtonRenderer.base(this, 'initializeDom', button);
    -  goog.dom.classlist.add(
    -      goog.asserts.assert(button.getElement()),
    -      goog.ui.ColorButtonRenderer.CSS_CLASS);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/colormenubutton.js b/src/database/third_party/closure-library/closure/goog/ui/colormenubutton.js
    deleted file mode 100644
    index 8bf833b1378..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/colormenubutton.js
    +++ /dev/null
    @@ -1,215 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A color menu button.  Extends {@link goog.ui.MenuButton} by
    - * showing the currently selected color in the button caption.
    - *
    - * @author robbyw@google.com (Robby Walker)
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.ColorMenuButton');
    -
    -goog.require('goog.array');
    -goog.require('goog.object');
    -goog.require('goog.ui.ColorMenuButtonRenderer');
    -goog.require('goog.ui.ColorPalette');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.Menu');
    -goog.require('goog.ui.MenuButton');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * A color menu button control.  Extends {@link goog.ui.MenuButton} by adding
    - * an API for getting and setting the currently selected color from a menu of
    - * color palettes.
    - *
    - * @param {goog.ui.ControlContent} content Text caption or existing DOM
    - *     structure to display as the button's caption.
    - * @param {goog.ui.Menu=} opt_menu Menu to render under the button when clicked;
    - *     should contain at least one {@link goog.ui.ColorPalette} if present.
    - * @param {goog.ui.MenuButtonRenderer=} opt_renderer Button renderer;
    - *     defaults to {@link goog.ui.ColorMenuButtonRenderer}.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @constructor
    - * @extends {goog.ui.MenuButton}
    - */
    -goog.ui.ColorMenuButton = function(content, opt_menu, opt_renderer,
    -    opt_domHelper) {
    -  goog.ui.MenuButton.call(this, content, opt_menu, opt_renderer ||
    -      goog.ui.ColorMenuButtonRenderer.getInstance(), opt_domHelper);
    -};
    -goog.inherits(goog.ui.ColorMenuButton, goog.ui.MenuButton);
    -
    -
    -/**
    - * Default color palettes.
    - * @type {!Object}
    - */
    -goog.ui.ColorMenuButton.PALETTES = {
    -  /** Default grayscale colors. */
    -  GRAYSCALE: [
    -    '#000', '#444', '#666', '#999', '#ccc', '#eee', '#f3f3f3', '#fff'
    -  ],
    -
    -  /** Default solid colors. */
    -  SOLID: [
    -    '#f00', '#f90', '#ff0', '#0f0', '#0ff', '#00f', '#90f', '#f0f'
    -  ],
    -
    -  /** Default pastel colors. */
    -  PASTEL: [
    -    '#f4cccc', '#fce5cd', '#fff2cc', '#d9ead3', '#d0e0e3', '#cfe2f3', '#d9d2e9',
    -    '#ead1dc',
    -    '#ea9999', '#f9cb9c', '#ffe599', '#b6d7a8', '#a2c4c9', '#9fc5e8', '#b4a7d6',
    -    '#d5a6bd',
    -    '#e06666', '#f6b26b', '#ffd966', '#93c47d', '#76a5af', '#6fa8dc', '#8e7cc3',
    -    '#c27ba0',
    -    '#cc0000', '#e69138', '#f1c232', '#6aa84f', '#45818e', '#3d85c6', '#674ea7',
    -    '#a64d79',
    -    '#990000', '#b45f06', '#bf9000', '#38761d', '#134f5c', '#0b5394', '#351c75',
    -    '#741b47',
    -    '#660000', '#783f04', '#7f6000', '#274e13', '#0c343d', '#073763', '#20124d',
    -    '#4c1130'
    -  ]
    -};
    -
    -
    -/**
    - * Value for the "no color" menu item object in the color menu (if present).
    - * The {@link goog.ui.ColorMenuButton#handleMenuAction} method interprets
    - * ACTION events dispatched by an item with this value as meaning "clear the
    - * selected color."
    - * @type {string}
    - */
    -goog.ui.ColorMenuButton.NO_COLOR = 'none';
    -
    -
    -/**
    - * Factory method that creates and returns a new {@link goog.ui.Menu} instance
    - * containing default color palettes.
    - * @param {Array<goog.ui.Control>=} opt_extraItems Optional extra menu items to
    - *     add before the color palettes.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @return {!goog.ui.Menu} Color menu.
    - */
    -goog.ui.ColorMenuButton.newColorMenu = function(opt_extraItems, opt_domHelper) {
    -  var menu = new goog.ui.Menu(opt_domHelper);
    -
    -  if (opt_extraItems) {
    -    goog.array.forEach(opt_extraItems, function(item) {
    -      menu.addChild(item, true);
    -    });
    -  }
    -
    -  goog.object.forEach(goog.ui.ColorMenuButton.PALETTES, function(colors) {
    -    var palette = new goog.ui.ColorPalette(colors, null, opt_domHelper);
    -    palette.setSize(8);
    -    menu.addChild(palette, true);
    -  });
    -
    -  return menu;
    -};
    -
    -
    -/**
    - * Returns the currently selected color (null if none).
    - * @return {string} The selected color.
    - */
    -goog.ui.ColorMenuButton.prototype.getSelectedColor = function() {
    -  return /** @type {string} */ (this.getValue());
    -};
    -
    -
    -/**
    - * Sets the selected color, or clears the selected color if the argument is
    - * null or not any of the available color choices.
    - * @param {?string} color New color.
    - */
    -goog.ui.ColorMenuButton.prototype.setSelectedColor = function(color) {
    -  this.setValue(color);
    -};
    -
    -
    -/**
    - * Sets the value associated with the color menu button.  Overrides
    - * {@link goog.ui.Button#setValue} by interpreting the value as a color
    - * spec string.
    - * @param {*} value New button value; should be a color spec string.
    - * @override
    - */
    -goog.ui.ColorMenuButton.prototype.setValue = function(value) {
    -  var color = /** @type {?string} */ (value);
    -  for (var i = 0, item; item = this.getItemAt(i); i++) {
    -    if (typeof item.setSelectedColor == 'function') {
    -      // This menu item looks like a color palette.
    -      item.setSelectedColor(color);
    -    }
    -  }
    -  goog.ui.ColorMenuButton.superClass_.setValue.call(this, color);
    -};
    -
    -
    -/**
    - * Handles {@link goog.ui.Component.EventType.ACTION} events dispatched by
    - * the menu item clicked by the user.  Updates the button, calls the superclass
    - * implementation to hide the menu, stops the propagation of the event, and
    - * dispatches an ACTION event on behalf of the button itself.  Overrides
    - * {@link goog.ui.MenuButton#handleMenuAction}.
    - * @param {goog.events.Event} e Action event to handle.
    - * @override
    - */
    -goog.ui.ColorMenuButton.prototype.handleMenuAction = function(e) {
    -  if (typeof e.target.getSelectedColor == 'function') {
    -    // User clicked something that looks like a color palette.
    -    this.setValue(e.target.getSelectedColor());
    -  } else if (e.target.getValue() == goog.ui.ColorMenuButton.NO_COLOR) {
    -    // User clicked the special "no color" menu item.
    -    this.setValue(null);
    -  }
    -  goog.ui.ColorMenuButton.superClass_.handleMenuAction.call(this, e);
    -  e.stopPropagation();
    -  this.dispatchEvent(goog.ui.Component.EventType.ACTION);
    -};
    -
    -
    -/**
    - * Opens or closes the menu.  Overrides {@link goog.ui.MenuButton#setOpen} by
    - * generating a default color menu on the fly if needed.
    - * @param {boolean} open Whether to open or close the menu.
    - * @param {goog.events.Event=} opt_e Mousedown event that caused the menu to
    - *     be opened.
    - * @override
    - */
    -goog.ui.ColorMenuButton.prototype.setOpen = function(open, opt_e) {
    -  if (open && this.getItemCount() == 0) {
    -    this.setMenu(
    -        goog.ui.ColorMenuButton.newColorMenu(null, this.getDomHelper()));
    -    this.setValue(/** @type {?string} */ (this.getValue()));
    -  }
    -  goog.ui.ColorMenuButton.superClass_.setOpen.call(this, open, opt_e);
    -};
    -
    -
    -// Register a decorator factory function for goog.ui.ColorMenuButtons.
    -goog.ui.registry.setDecoratorByClassName(
    -    goog.ui.ColorMenuButtonRenderer.CSS_CLASS,
    -    function() {
    -      return new goog.ui.ColorMenuButton(null);
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/colormenubuttonrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/colormenubuttonrenderer.js
    deleted file mode 100644
    index 51cd1be1b88..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/colormenubuttonrenderer.js
    +++ /dev/null
    @@ -1,147 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Renderer for {@link goog.ui.ColorMenuButton}s.
    - *
    - * @author robbyw@google.com (Robby Walker)
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.ColorMenuButtonRenderer');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.color');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.ui.MenuButtonRenderer');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Renderer for {@link goog.ui.ColorMenuButton}s.
    - * @constructor
    - * @extends {goog.ui.MenuButtonRenderer}
    - */
    -goog.ui.ColorMenuButtonRenderer = function() {
    -  goog.ui.MenuButtonRenderer.call(this);
    -};
    -goog.inherits(goog.ui.ColorMenuButtonRenderer, goog.ui.MenuButtonRenderer);
    -goog.addSingletonGetter(goog.ui.ColorMenuButtonRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.ColorMenuButtonRenderer.CSS_CLASS =
    -    goog.getCssName('goog-color-menu-button');
    -
    -
    -/**
    - * Overrides the superclass implementation by wrapping the caption text or DOM
    - * structure in a color indicator element.  Creates the following DOM structure:
    - *   <div class="goog-inline-block goog-menu-button-caption">
    - *     <div class="goog-color-menu-button-indicator">
    - *       Contents...
    - *     </div>
    - *   </div>
    - * The 'goog-color-menu-button-indicator' style should be defined to have a
    - * bottom border of nonzero width and a default color that blends into its
    - * background.
    - * @param {goog.ui.ControlContent} content Text caption or DOM structure.
    - * @param {goog.dom.DomHelper} dom DOM helper, used for document interaction.
    - * @return {Element} Caption element.
    - * @override
    - */
    -goog.ui.ColorMenuButtonRenderer.prototype.createCaption = function(content,
    -    dom) {
    -  return goog.ui.ColorMenuButtonRenderer.superClass_.createCaption.call(this,
    -      goog.ui.ColorMenuButtonRenderer.wrapCaption(content, dom), dom);
    -};
    -
    -
    -/**
    - * Wrap a caption in a div with the color-menu-button-indicator CSS class.
    - * @param {goog.ui.ControlContent} content Text caption or DOM structure.
    - * @param {goog.dom.DomHelper} dom DOM helper, used for document interaction.
    - * @return {!Element} Caption element.
    - */
    -goog.ui.ColorMenuButtonRenderer.wrapCaption = function(content, dom) {
    -  return dom.createDom('div',
    -      goog.getCssName(goog.ui.ColorMenuButtonRenderer.CSS_CLASS, 'indicator'),
    -      content);
    -};
    -
    -
    -/**
    - * Takes a color menu button control's root element and a value object
    - * (which is assumed to be a color), and updates the button's DOM to reflect
    - * the new color.  Overrides {@link goog.ui.ButtonRenderer#setValue}.
    - * @param {Element} element The button control's root element (if rendered).
    - * @param {*} value New value; assumed to be a color spec string.
    - * @override
    - */
    -goog.ui.ColorMenuButtonRenderer.prototype.setValue = function(element, value) {
    -  if (element) {
    -    goog.ui.ColorMenuButtonRenderer.setCaptionValue(
    -        this.getContentElement(element), value);
    -  }
    -};
    -
    -
    -/**
    - * Takes a control's content element and a value object (which is assumed
    - * to be a color), and updates its DOM to reflect the new color.
    - * @param {Element} caption A content element of a control.
    - * @param {*} value New value; assumed to be a color spec string.
    - */
    -goog.ui.ColorMenuButtonRenderer.setCaptionValue = function(caption, value) {
    -  // Assume that the caption's first child is the indicator.
    -  if (caption && caption.firstChild) {
    -    // Normalize the value to a hex color spec or null (otherwise setting
    -    // borderBottomColor will cause a JS error on IE).
    -    var hexColor;
    -
    -    var strValue = /** @type {string} */ (value);
    -    hexColor = strValue && goog.color.isValidColor(strValue) ?
    -        goog.color.parse(strValue).hex :
    -        null;
    -
    -    // Stupid IE6/7 doesn't do transparent borders.
    -    // TODO(attila): Add user-agent version check when IE8 comes out...
    -    caption.firstChild.style.borderBottomColor = hexColor ||
    -        (goog.userAgent.IE ? '' : 'transparent');
    -  }
    -};
    -
    -
    -/**
    - * Initializes the button's DOM when it enters the document.  Overrides the
    - * superclass implementation by making sure the button's color indicator is
    - * initialized.
    - * @param {goog.ui.Control} button goog.ui.ColorMenuButton whose DOM is to be
    - *     initialized as it enters the document.
    - * @override
    - */
    -goog.ui.ColorMenuButtonRenderer.prototype.initializeDom = function(button) {
    -  var buttonElement = button.getElement();
    -  goog.asserts.assert(buttonElement);
    -  this.setValue(buttonElement, button.getValue());
    -  goog.dom.classlist.add(buttonElement,
    -      goog.ui.ColorMenuButtonRenderer.CSS_CLASS);
    -  goog.ui.ColorMenuButtonRenderer.superClass_.initializeDom.call(this,
    -      button);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/colormenubuttonrenderer_test.html b/src/database/third_party/closure-library/closure/goog/ui/colormenubuttonrenderer_test.html
    deleted file mode 100644
    index b5a7be8ee02..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/colormenubuttonrenderer_test.html
    +++ /dev/null
    @@ -1,31 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -
    -  @author nicksantos@google.com (Nick Santos)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests for ColorMenuButtonRenderer
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.ColorMenuButtonTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="root">
    -   <!-- A parent to attach rendered buttons to -->
    -   <div id="parent"></div>
    -   <!-- A button to decorate -->
    -   <div id="decoratedButton"><div>Foo</div></div></div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/colormenubuttonrenderer_test.js b/src/database/third_party/closure-library/closure/goog/ui/colormenubuttonrenderer_test.js
    deleted file mode 100644
    index 5205be36909..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/colormenubuttonrenderer_test.js
    +++ /dev/null
    @@ -1,71 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.ColorMenuButtonTest');
    -goog.setTestOnly('goog.ui.ColorMenuButtonTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.ui.RendererHarness');
    -goog.require('goog.testing.ui.rendererasserts');
    -goog.require('goog.ui.ColorMenuButton');
    -goog.require('goog.ui.ColorMenuButtonRenderer');
    -goog.require('goog.userAgent');
    -
    -var harness;
    -
    -function setUp() {
    -  harness = new goog.testing.ui.RendererHarness(
    -      goog.ui.ColorMenuButtonRenderer.getInstance(),
    -      goog.dom.getElement('parent'),
    -      goog.dom.getElement('decoratedButton'));
    -}
    -
    -function tearDown() {
    -  harness.dispose();
    -}
    -
    -function testEquality() {
    -  harness.attachControlAndRender(
    -      new goog.ui.ColorMenuButton('Foo'));
    -  harness.attachControlAndDecorate(
    -      new goog.ui.ColorMenuButton());
    -  harness.assertDomMatches();
    -}
    -
    -function testWrapCaption() {
    -  var caption = goog.dom.createDom('div', null, 'Foo');
    -  var wrappedCaption = goog.ui.ColorMenuButtonRenderer.wrapCaption(caption,
    -      goog.dom.getDomHelper());
    -  assertNotEquals('Caption should have been wrapped', caption, wrappedCaption);
    -  assertEquals('Wrapped caption should have indicator css class',
    -      'goog-color-menu-button-indicator', wrappedCaption.className);
    -}
    -
    -function testSetCaptionValue() {
    -  var caption = goog.dom.createDom('div', null, 'Foo');
    -  var wrappedCaption = goog.ui.ColorMenuButtonRenderer.wrapCaption(caption,
    -      goog.dom.getDomHelper());
    -  goog.ui.ColorMenuButtonRenderer.setCaptionValue(wrappedCaption, 'red');
    -
    -  var expectedColor =
    -      goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9) ?
    -      '#ff0000' : 'rgb(255, 0, 0)';
    -  assertEquals(expectedColor, caption.style.borderBottomColor);
    -}
    -
    -function testDoesntCallGetCssClassInConstructor() {
    -  goog.testing.ui.rendererasserts.
    -      assertNoGetCssClassCallsInConstructor(goog.ui.ColorMenuButtonRenderer);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/colorpalette.js b/src/database/third_party/closure-library/closure/goog/ui/colorpalette.js
    deleted file mode 100644
    index f1a271e18e8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/colorpalette.js
    +++ /dev/null
    @@ -1,178 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A control for representing a palette of colors, that the user
    - * can highlight or select via the keyboard or the mouse.
    - *
    - */
    -
    -goog.provide('goog.ui.ColorPalette');
    -
    -goog.require('goog.array');
    -goog.require('goog.color');
    -goog.require('goog.style');
    -goog.require('goog.ui.Palette');
    -goog.require('goog.ui.PaletteRenderer');
    -
    -
    -
    -/**
    - * A color palette is a grid of color swatches that the user can highlight or
    - * select via the keyboard or the mouse.  The selection state of the palette is
    - * controlled by a selection model.  When the user makes a selection, the
    - * component fires an ACTION event.  Event listeners may retrieve the selected
    - * color using the {@link #getSelectedColor} method.
    - *
    - * @param {Array<string>=} opt_colors Array of colors in any valid CSS color
    - *     format.
    - * @param {goog.ui.PaletteRenderer=} opt_renderer Renderer used to render or
    - *     decorate the palette; defaults to {@link goog.ui.PaletteRenderer}.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @constructor
    - * @extends {goog.ui.Palette}
    - */
    -goog.ui.ColorPalette = function(opt_colors, opt_renderer, opt_domHelper) {
    -  /**
    -   * Array of colors to show in the palette.
    -   * @type {Array<string>}
    -   * @private
    -   */
    -  this.colors_ = opt_colors || [];
    -
    -  goog.ui.Palette.call(this, null,
    -      opt_renderer || goog.ui.PaletteRenderer.getInstance(), opt_domHelper);
    -
    -  // Set the colors separately from the super call since we need the correct
    -  // DomHelper to be initialized for this class.
    -  this.setColors(this.colors_);
    -};
    -goog.inherits(goog.ui.ColorPalette, goog.ui.Palette);
    -goog.tagUnsealableClass(goog.ui.ColorPalette);
    -
    -
    -/**
    - * Array of normalized colors. Initialized lazily as often never needed.
    - * @type {?Array<string>}
    - * @private
    - */
    -goog.ui.ColorPalette.prototype.normalizedColors_ = null;
    -
    -
    -/**
    - * Array of labels for the colors. Will be used for the tooltips and
    - * accessibility.
    - * @type {?Array<string>}
    - * @private
    - */
    -goog.ui.ColorPalette.prototype.labels_ = null;
    -
    -
    -/**
    - * Returns the array of colors represented in the color palette.
    - * @return {Array<string>} Array of colors.
    - */
    -goog.ui.ColorPalette.prototype.getColors = function() {
    -  return this.colors_;
    -};
    -
    -
    -/**
    - * Sets the colors that are contained in the palette.
    - * @param {Array<string>} colors Array of colors in any valid CSS color format.
    - * @param {Array<string>=} opt_labels The array of labels to be used as
    - *        tooltips. When not provided, the color value will be used.
    - */
    -goog.ui.ColorPalette.prototype.setColors = function(colors, opt_labels) {
    -  this.colors_ = colors;
    -  this.labels_ = opt_labels || null;
    -  this.normalizedColors_ = null;
    -  this.setContent(this.createColorNodes());
    -};
    -
    -
    -/**
    - * @return {?string} The current selected color in hex, or null.
    - */
    -goog.ui.ColorPalette.prototype.getSelectedColor = function() {
    -  var selectedItem = /** @type {Element} */ (this.getSelectedItem());
    -  if (selectedItem) {
    -    var color = goog.style.getStyle(selectedItem, 'background-color');
    -    return goog.ui.ColorPalette.parseColor_(color);
    -  } else {
    -    return null;
    -  }
    -};
    -
    -
    -/**
    - * Sets the selected color.  Clears the selection if the argument is null or
    - * can't be parsed as a color.
    - * @param {?string} color The color to set as selected; null clears the
    - *     selection.
    - */
    -goog.ui.ColorPalette.prototype.setSelectedColor = function(color) {
    -  var hexColor = goog.ui.ColorPalette.parseColor_(color);
    -  if (!this.normalizedColors_) {
    -    this.normalizedColors_ = goog.array.map(this.colors_, function(color) {
    -      return goog.ui.ColorPalette.parseColor_(color);
    -    });
    -  }
    -  this.setSelectedIndex(hexColor ?
    -      goog.array.indexOf(this.normalizedColors_, hexColor) : -1);
    -};
    -
    -
    -/**
    - * @return {!Array<!Node>} An array of DOM nodes for each color.
    - * @protected
    - */
    -goog.ui.ColorPalette.prototype.createColorNodes = function() {
    -  return goog.array.map(this.colors_, function(color, index) {
    -    var swatch = this.getDomHelper().createDom('div', {
    -      'class': goog.getCssName(this.getRenderer().getCssClass(),
    -          'colorswatch'),
    -      'style': 'background-color:' + color
    -    });
    -    if (this.labels_ && this.labels_[index]) {
    -      swatch.title = this.labels_[index];
    -    } else {
    -      swatch.title = color.charAt(0) == '#' ?
    -          'RGB (' + goog.color.hexToRgb(color).join(', ') + ')' : color;
    -    }
    -    return swatch;
    -  }, this);
    -};
    -
    -
    -/**
    - * Takes a string, attempts to parse it as a color spec, and returns a
    - * normalized hex color spec if successful (null otherwise).
    - * @param {?string} color String possibly containing a color spec; may be null.
    - * @return {?string} Normalized hex color spec, or null if the argument can't
    - *     be parsed as a color.
    - * @private
    - */
    -goog.ui.ColorPalette.parseColor_ = function(color) {
    -  if (color) {
    -    /** @preserveTry */
    -    try {
    -      return goog.color.parse(color).hex;
    -    } catch (ex) {
    -      // Fall through.
    -    }
    -  }
    -  return null;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/colorpalette_test.html b/src/database/third_party/closure-library/closure/goog/ui/colorpalette_test.html
    deleted file mode 100644
    index da4da9c8478..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/colorpalette_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!-- Author:  attila@google.com (Attila Bodis) -->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.ColorPalette
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.ColorPaletteTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="sandbox">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/colorpalette_test.js b/src/database/third_party/closure-library/closure/goog/ui/colorpalette_test.js
    deleted file mode 100644
    index e9628261edc..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/colorpalette_test.js
    +++ /dev/null
    @@ -1,169 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.ColorPaletteTest');
    -goog.setTestOnly('goog.ui.ColorPaletteTest');
    -
    -goog.require('goog.color');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.ColorPalette');
    -
    -var emptyPalette, samplePalette;
    -
    -function setUp() {
    -  emptyPalette = new goog.ui.ColorPalette();
    -  samplePalette = new goog.ui.ColorPalette([
    -    'red', '#00FF00', 'rgb(0, 0, 255)'
    -  ]);
    -  samplePalette.setSelectedColor('blue');
    -}
    -
    -function tearDown() {
    -  emptyPalette.dispose();
    -  samplePalette.dispose();
    -  document.getElementById('sandbox').innerHTML = '';
    -}
    -
    -function testEmptyColorPalette() {
    -  var colors = emptyPalette.getColors();
    -  assertNotNull(colors);
    -  assertEquals(0, colors.length);
    -
    -  var nodes = emptyPalette.getContent();
    -  assertNotNull(nodes);
    -  assertEquals(0, nodes.length);
    -}
    -
    -function testSampleColorPalette() {
    -  var colors = samplePalette.getColors();
    -  assertNotNull(colors);
    -  assertEquals(3, colors.length);
    -  assertEquals('red', colors[0]);
    -  assertEquals('#00FF00', colors[1]);
    -  assertEquals('rgb(0, 0, 255)', colors[2]);
    -
    -  var nodes = samplePalette.getContent();
    -  assertNotNull(nodes);
    -  assertEquals(3, nodes.length);
    -  assertEquals('goog-palette-colorswatch', nodes[0].className);
    -  assertEquals('goog-palette-colorswatch', nodes[1].className);
    -  assertEquals('goog-palette-colorswatch', nodes[2].className);
    -  assertEquals('#ff0000',
    -      goog.color.parse(nodes[0].style.backgroundColor).hex);
    -  assertEquals('#00ff00',
    -      goog.color.parse(nodes[1].style.backgroundColor).hex);
    -  assertEquals('#0000ff',
    -      goog.color.parse(nodes[2].style.backgroundColor).hex);
    -}
    -
    -function testGetColors() {
    -  var emptyColors = emptyPalette.getColors();
    -  assertNotNull(emptyColors);
    -  assertEquals(0, emptyColors.length);
    -
    -  var sampleColors = samplePalette.getColors();
    -  assertNotNull(sampleColors);
    -  assertEquals(3, sampleColors.length);
    -  assertEquals('red', sampleColors[0]);
    -  assertEquals('#00FF00', sampleColors[1]);
    -  assertEquals('rgb(0, 0, 255)', sampleColors[2]);
    -}
    -
    -function testSetColors() {
    -  emptyPalette.setColors(['black', '#FFFFFF']);
    -
    -  var colors = emptyPalette.getColors();
    -  assertNotNull(colors);
    -  assertEquals(2, colors.length);
    -  assertEquals('black', colors[0]);
    -  assertEquals('#FFFFFF', colors[1]);
    -
    -  var nodes = emptyPalette.getContent();
    -  assertNotNull(nodes);
    -  assertEquals(2, nodes.length);
    -  assertEquals('goog-palette-colorswatch', nodes[0].className);
    -  assertEquals('goog-palette-colorswatch', nodes[1].className);
    -  assertEquals('#000000',
    -      goog.color.parse(nodes[0].style.backgroundColor).hex);
    -  assertEquals('#ffffff',
    -      goog.color.parse(nodes[1].style.backgroundColor).hex);
    -  assertEquals('black', nodes[0].title);
    -  assertEquals('RGB (255, 255, 255)', nodes[1].title);
    -
    -  samplePalette.setColors(['#336699', 'cyan']);
    -
    -  var newColors = samplePalette.getColors();
    -  assertNotNull(newColors);
    -  assertEquals(2, newColors.length);
    -  assertEquals('#336699', newColors[0]);
    -  assertEquals('cyan', newColors[1]);
    -
    -  var newNodes = samplePalette.getContent();
    -  assertNotNull(newNodes);
    -  assertEquals(2, newNodes.length);
    -  assertEquals('goog-palette-colorswatch', newNodes[0].className);
    -  assertEquals('goog-palette-colorswatch', newNodes[1].className);
    -  assertEquals('#336699',
    -      goog.color.parse(newNodes[0].style.backgroundColor).hex);
    -  assertEquals('#00ffff',
    -      goog.color.parse(newNodes[1].style.backgroundColor).hex);
    -}
    -
    -function testSetColorsWithLabels() {
    -  emptyPalette.setColors(['#00f', '#FFFFFF', 'black'], ['blue', 'white']);
    -  var nodes = emptyPalette.getContent();
    -  assertEquals('blue', nodes[0].title);
    -  assertEquals('white', nodes[1].title);
    -  assertEquals('black', nodes[2].title);
    -}
    -
    -function testRender() {
    -  samplePalette.render(document.getElementById('sandbox'));
    -
    -  assertTrue(samplePalette.isInDocument());
    -
    -  var elem = samplePalette.getElement();
    -  assertNotNull(elem);
    -  assertEquals('DIV', elem.tagName);
    -  assertEquals('goog-palette', elem.className);
    -
    -  var table = elem.firstChild;
    -  assertEquals('TABLE', table.tagName);
    -  assertEquals('goog-palette-table', table.className);
    -}
    -
    -function testGetSelectedColor() {
    -  assertNull(emptyPalette.getSelectedColor());
    -  assertEquals('#0000ff', samplePalette.getSelectedColor());
    -}
    -
    -function testSetSelectedColor() {
    -  emptyPalette.setSelectedColor('red');
    -  assertNull(emptyPalette.getSelectedColor());
    -
    -  samplePalette.setSelectedColor('red');
    -  assertEquals('#ff0000', samplePalette.getSelectedColor());
    -  samplePalette.setSelectedColor(17); // Invalid color spec.
    -  assertNull(samplePalette.getSelectedColor());
    -
    -  samplePalette.setSelectedColor('rgb(0, 255, 0)');
    -  assertEquals('#00ff00', samplePalette.getSelectedColor());
    -  samplePalette.setSelectedColor(false); // Invalid color spec.
    -  assertNull(samplePalette.getSelectedColor());
    -
    -  samplePalette.setSelectedColor('#0000FF');
    -  assertEquals('#0000ff', samplePalette.getSelectedColor());
    -  samplePalette.setSelectedColor(null); // Invalid color spec.
    -  assertNull(samplePalette.getSelectedColor());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/colorpicker.js b/src/database/third_party/closure-library/closure/goog/ui/colorpicker.js
    deleted file mode 100644
    index 1be8120149b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/colorpicker.js
    +++ /dev/null
    @@ -1,345 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A color picker component.  A color picker can compose several
    - * instances of goog.ui.ColorPalette.
    - *
    - * NOTE: The ColorPicker is in a state of transition towards the common
    - * component/control/container interface we are developing.  If the API changes
    - * we will do our best to update your code.  The end result will be that a
    - * color picker will compose multiple color palettes.  In the simple case this
    - * will be one grid, but may consistute 3 distinct grids, a custom color picker
    - * or even a color wheel.
    - *
    - */
    -
    -goog.provide('goog.ui.ColorPicker');
    -goog.provide('goog.ui.ColorPicker.EventType');
    -
    -goog.require('goog.ui.ColorPalette');
    -goog.require('goog.ui.Component');
    -
    -
    -
    -/**
    - * Create a new, empty color picker.
    - *
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @param {goog.ui.ColorPalette=} opt_colorPalette Optional color palette to
    - *     use for this color picker.
    - * @extends {goog.ui.Component}
    - * @constructor
    - * @final
    - */
    -goog.ui.ColorPicker = function(opt_domHelper, opt_colorPalette) {
    -  goog.ui.Component.call(this, opt_domHelper);
    -
    -  /**
    -   * The color palette used inside the color picker.
    -   * @type {goog.ui.ColorPalette?}
    -   * @private
    -   */
    -  this.colorPalette_ = opt_colorPalette || null;
    -
    -  this.getHandler().listen(
    -      this, goog.ui.Component.EventType.ACTION, this.onColorPaletteAction_);
    -};
    -goog.inherits(goog.ui.ColorPicker, goog.ui.Component);
    -
    -
    -/**
    - * Default number of columns in the color palette. May be overridden by calling
    - * setSize.
    - *
    - * @type {number}
    - */
    -goog.ui.ColorPicker.DEFAULT_NUM_COLS = 5;
    -
    -
    -/**
    - * Constants for event names.
    - * @enum {string}
    - */
    -goog.ui.ColorPicker.EventType = {
    -  CHANGE: 'change'
    -};
    -
    -
    -/**
    - * Whether the component is focusable.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.ColorPicker.prototype.focusable_ = true;
    -
    -
    -/**
    - * Gets the array of colors displayed by the color picker.
    - * Modifying this array will lead to unexpected behavior.
    - * @return {Array<string>?} The colors displayed by this widget.
    - */
    -goog.ui.ColorPicker.prototype.getColors = function() {
    -  return this.colorPalette_ ? this.colorPalette_.getColors() : null;
    -};
    -
    -
    -/**
    - * Sets the array of colors to be displayed by the color picker.
    - * @param {Array<string>} colors The array of colors to be added.
    - */
    -goog.ui.ColorPicker.prototype.setColors = function(colors) {
    -  // TODO(user): Don't add colors directly, we should add palettes and the
    -  // picker should support multiple palettes.
    -  if (!this.colorPalette_) {
    -    this.createColorPalette_(colors);
    -  } else {
    -    this.colorPalette_.setColors(colors);
    -  }
    -};
    -
    -
    -/**
    - * Sets the array of colors to be displayed by the color picker.
    - * @param {Array<string>} colors The array of colors to be added.
    - * @deprecated Use setColors.
    - */
    -goog.ui.ColorPicker.prototype.addColors = function(colors) {
    -  this.setColors(colors);
    -};
    -
    -
    -/**
    - * Sets the size of the palette.  Will throw an error after the picker has been
    - * rendered.
    - * @param {goog.math.Size|number} size The size of the grid.
    - */
    -goog.ui.ColorPicker.prototype.setSize = function(size) {
    -  // TODO(user): The color picker should contain multiple palettes which will
    -  // all be resized at this point.
    -  if (!this.colorPalette_) {
    -    this.createColorPalette_([]);
    -  }
    -  this.colorPalette_.setSize(size);
    -};
    -
    -
    -/**
    - * Gets the number of columns displayed.
    - * @return {goog.math.Size?} The size of the grid.
    - */
    -goog.ui.ColorPicker.prototype.getSize = function() {
    -  return this.colorPalette_ ? this.colorPalette_.getSize() : null;
    -};
    -
    -
    -/**
    - * Sets the number of columns.  Will throw an error after the picker has been
    - * rendered.
    - * @param {number} n The number of columns.
    - * @deprecated Use setSize.
    - */
    -goog.ui.ColorPicker.prototype.setColumnCount = function(n) {
    -  this.setSize(n);
    -};
    -
    -
    -/**
    - * @return {number} The index of the color selected.
    - */
    -goog.ui.ColorPicker.prototype.getSelectedIndex = function() {
    -  return this.colorPalette_ ? this.colorPalette_.getSelectedIndex() : -1;
    -};
    -
    -
    -/**
    - * Sets which color is selected. A value that is out-of-range means that no
    - * color is selected.
    - * @param {number} ind The index in this.colors_ of the selected color.
    - */
    -goog.ui.ColorPicker.prototype.setSelectedIndex = function(ind) {
    -  if (this.colorPalette_) {
    -    this.colorPalette_.setSelectedIndex(ind);
    -  }
    -};
    -
    -
    -/**
    - * Gets the color that is currently selected in this color picker.
    - * @return {?string} The hex string of the color selected, or null if no
    - *     color is selected.
    - */
    -goog.ui.ColorPicker.prototype.getSelectedColor = function() {
    -  return this.colorPalette_ ? this.colorPalette_.getSelectedColor() : null;
    -};
    -
    -
    -/**
    - * Sets which color is selected.  Noop if the color palette hasn't been created
    - * yet.
    - * @param {string} color The selected color.
    - */
    -goog.ui.ColorPicker.prototype.setSelectedColor = function(color) {
    -  // TODO(user): This will set the color in the first available palette that
    -  // contains it
    -  if (this.colorPalette_) {
    -    this.colorPalette_.setSelectedColor(color);
    -  }
    -};
    -
    -
    -/**
    - * Returns true if the component is focusable, false otherwise.  The default
    - * is true.  Focusable components always have a tab index and allocate a key
    - * handler to handle keyboard events while focused.
    - * @return {boolean} True iff the component is focusable.
    - */
    -goog.ui.ColorPicker.prototype.isFocusable = function() {
    -  return this.focusable_;
    -};
    -
    -
    -/**
    - * Sets whether the component is focusable.  The default is true.
    - * Focusable components always have a tab index and allocate a key handler to
    - * handle keyboard events while focused.
    - * @param {boolean} focusable True iff the component is focusable.
    - */
    -goog.ui.ColorPicker.prototype.setFocusable = function(focusable) {
    -  this.focusable_ = focusable;
    -  if (this.colorPalette_) {
    -    this.colorPalette_.setSupportedState(goog.ui.Component.State.FOCUSED,
    -        focusable);
    -  }
    -};
    -
    -
    -/**
    - * ColorPickers cannot be used to decorate pre-existing html, since the
    - * structure they build is fairly complicated.
    - * @param {Element} element Element to decorate.
    - * @return {boolean} Returns always false.
    - * @override
    - */
    -goog.ui.ColorPicker.prototype.canDecorate = function(element) {
    -  return false;
    -};
    -
    -
    -/**
    - * Renders the color picker inside the provided element. This will override the
    - * current content of the element.
    - * @override
    - */
    -goog.ui.ColorPicker.prototype.enterDocument = function() {
    -  goog.ui.ColorPicker.superClass_.enterDocument.call(this);
    -  if (this.colorPalette_) {
    -    this.colorPalette_.render(this.getElement());
    -  }
    -  this.getElement().unselectable = 'on';
    -};
    -
    -
    -/** @override */
    -goog.ui.ColorPicker.prototype.disposeInternal = function() {
    -  goog.ui.ColorPicker.superClass_.disposeInternal.call(this);
    -  if (this.colorPalette_) {
    -    this.colorPalette_.dispose();
    -    this.colorPalette_ = null;
    -  }
    -};
    -
    -
    -/**
    - * Sets the focus to the color picker's palette.
    - */
    -goog.ui.ColorPicker.prototype.focus = function() {
    -  if (this.colorPalette_) {
    -    this.colorPalette_.getElement().focus();
    -  }
    -};
    -
    -
    -/**
    - * Handles actions from the color palette.
    - *
    - * @param {goog.events.Event} e The event.
    - * @private
    - */
    -goog.ui.ColorPicker.prototype.onColorPaletteAction_ = function(e) {
    -  e.stopPropagation();
    -  this.dispatchEvent(goog.ui.ColorPicker.EventType.CHANGE);
    -};
    -
    -
    -/**
    - * Create a color palette for the color picker.
    - * @param {Array<string>} colors Array of colors.
    - * @private
    - */
    -goog.ui.ColorPicker.prototype.createColorPalette_ = function(colors) {
    -  // TODO(user): The color picker should eventually just contain a number of
    -  // palettes and manage the interactions between them.  This will go away then.
    -  var cp = new goog.ui.ColorPalette(colors, null, this.getDomHelper());
    -  cp.setSize(goog.ui.ColorPicker.DEFAULT_NUM_COLS);
    -  cp.setSupportedState(goog.ui.Component.State.FOCUSED, this.focusable_);
    -  // TODO(user): Use addChild(cp, true) and remove calls to render.
    -  this.addChild(cp);
    -  this.colorPalette_ = cp;
    -  if (this.isInDocument()) {
    -    this.colorPalette_.render(this.getElement());
    -  }
    -};
    -
    -
    -/**
    - * Returns an unrendered instance of the color picker.  The colors and layout
    - * are a simple color grid, the same as the old Gmail color picker.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @return {!goog.ui.ColorPicker} The unrendered instance.
    - */
    -goog.ui.ColorPicker.createSimpleColorGrid = function(opt_domHelper) {
    -  var cp = new goog.ui.ColorPicker(opt_domHelper);
    -  cp.setSize(7);
    -  cp.setColors(goog.ui.ColorPicker.SIMPLE_GRID_COLORS);
    -  return cp;
    -};
    -
    -
    -/**
    - * Array of colors for a 7-cell wide simple-grid color picker.
    - * @type {Array<string>}
    - */
    -goog.ui.ColorPicker.SIMPLE_GRID_COLORS = [
    -  // grays
    -  '#ffffff', '#cccccc', '#c0c0c0', '#999999', '#666666', '#333333', '#000000',
    -  // reds
    -  '#ffcccc', '#ff6666', '#ff0000', '#cc0000', '#990000', '#660000', '#330000',
    -  // oranges
    -  '#ffcc99', '#ff9966', '#ff9900', '#ff6600', '#cc6600', '#993300', '#663300',
    -  // yellows
    -  '#ffff99', '#ffff66', '#ffcc66', '#ffcc33', '#cc9933', '#996633', '#663333',
    -  // olives
    -  '#ffffcc', '#ffff33', '#ffff00', '#ffcc00', '#999900', '#666600', '#333300',
    -  // greens
    -  '#99ff99', '#66ff99', '#33ff33', '#33cc00', '#009900', '#006600', '#003300',
    -  // turquoises
    -  '#99ffff', '#33ffff', '#66cccc', '#00cccc', '#339999', '#336666', '#003333',
    -  // blues
    -  '#ccffff', '#66ffff', '#33ccff', '#3366ff', '#3333ff', '#000099', '#000066',
    -  // purples
    -  '#ccccff', '#9999ff', '#6666cc', '#6633ff', '#6600cc', '#333399', '#330099',
    -  // violets
    -  '#ffccff', '#ff99ff', '#cc66cc', '#cc33cc', '#993399', '#663366', '#330033'
    -];
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/colorsplitbehavior.js b/src/database/third_party/closure-library/closure/goog/ui/colorsplitbehavior.js
    deleted file mode 100644
    index 3aa7ab0992c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/colorsplitbehavior.js
    +++ /dev/null
    @@ -1,61 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Behavior for combining a color button and a menu.
    - *
    - * @see ../demos/split.html
    - */
    -
    -goog.provide('goog.ui.ColorSplitBehavior');
    -
    -goog.require('goog.ui.ColorMenuButton');
    -goog.require('goog.ui.SplitBehavior');
    -
    -
    -
    -/**
    - * Constructs a ColorSplitBehavior for combining a color button and a menu.
    - * To use this, provide a goog.ui.ColorButton which will be attached with
    - * a goog.ui.ColorMenuButton (with no caption).
    - * Whenever a color is selected from the ColorMenuButton, it will be placed in
    - * the ColorButton and the user can apply it over and over (by clicking the
    - * ColorButton).
    - * Primary use case - setting the color of text/background in a text editor.
    - *
    - * @param {!goog.ui.Button} colorButton A button to interact with a color menu
    - *     button (preferably a goog.ui.ColorButton).
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @extends {goog.ui.SplitBehavior}
    - * @constructor
    - * @final
    - */
    -goog.ui.ColorSplitBehavior = function(colorButton, opt_domHelper) {
    -  goog.ui.ColorSplitBehavior.base(this, 'constructor', colorButton,
    -      new goog.ui.ColorMenuButton(goog.ui.ColorSplitBehavior.ZERO_WIDTH_SPACE_),
    -      goog.ui.SplitBehavior.DefaultHandlers.VALUE,
    -      undefined,
    -      opt_domHelper);
    -};
    -goog.inherits(goog.ui.ColorSplitBehavior, goog.ui.SplitBehavior);
    -
    -
    -/**
    - * A zero width space character.
    - * @type {string}
    - * @private
    - */
    -goog.ui.ColorSplitBehavior.ZERO_WIDTH_SPACE_ = '\uFEFF';
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/combobox.js b/src/database/third_party/closure-library/closure/goog/ui/combobox.js
    deleted file mode 100644
    index 5f7d9c1ed46..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/combobox.js
    +++ /dev/null
    @@ -1,987 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A combo box control that allows user input with
    - * auto-suggestion from a limited set of options.
    - *
    - * @see ../demos/combobox.html
    - */
    -
    -goog.provide('goog.ui.ComboBox');
    -goog.provide('goog.ui.ComboBoxItem');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.InputHandler');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.events.KeyHandler');
    -goog.require('goog.log');
    -goog.require('goog.positioning.Corner');
    -goog.require('goog.positioning.MenuAnchoredPosition');
    -goog.require('goog.string');
    -goog.require('goog.style');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.ItemEvent');
    -goog.require('goog.ui.LabelInput');
    -goog.require('goog.ui.Menu');
    -goog.require('goog.ui.MenuItem');
    -goog.require('goog.ui.MenuSeparator');
    -goog.require('goog.ui.registry');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * A ComboBox control.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @param {goog.ui.Menu=} opt_menu Optional menu component.
    - *     This menu is disposed of by this control.
    - * @param {goog.ui.LabelInput=} opt_labelInput Optional label input.
    - *     This label input is disposed of by this control.
    - * @extends {goog.ui.Component}
    - * @constructor
    - */
    -goog.ui.ComboBox = function(opt_domHelper, opt_menu, opt_labelInput) {
    -  goog.ui.Component.call(this, opt_domHelper);
    -
    -  this.labelInput_ = opt_labelInput || new goog.ui.LabelInput();
    -  this.enabled_ = true;
    -
    -  // TODO(user): Allow lazy creation of menus/menu items
    -  this.menu_ = opt_menu || new goog.ui.Menu(this.getDomHelper());
    -  this.setupMenu_();
    -};
    -goog.inherits(goog.ui.ComboBox, goog.ui.Component);
    -goog.tagUnsealableClass(goog.ui.ComboBox);
    -
    -
    -/**
    - * Number of milliseconds to wait before dismissing combobox after blur.
    - * @type {number}
    - */
    -goog.ui.ComboBox.BLUR_DISMISS_TIMER_MS = 250;
    -
    -
    -/**
    - * A logger to help debugging of combo box behavior.
    - * @type {goog.log.Logger}
    - * @private
    - */
    -goog.ui.ComboBox.prototype.logger_ =
    -    goog.log.getLogger('goog.ui.ComboBox');
    -
    -
    -/**
    - * Whether the combo box is enabled.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.ComboBox.prototype.enabled_;
    -
    -
    -/**
    - * Keyboard event handler to manage key events dispatched by the input element.
    - * @type {goog.events.KeyHandler}
    - * @private
    - */
    -goog.ui.ComboBox.prototype.keyHandler_;
    -
    -
    -/**
    - * Input handler to take care of firing events when the user inputs text in
    - * the input.
    - * @type {goog.events.InputHandler?}
    - * @private
    - */
    -goog.ui.ComboBox.prototype.inputHandler_ = null;
    -
    -
    -/**
    - * The last input token.
    - * @type {?string}
    - * @private
    - */
    -goog.ui.ComboBox.prototype.lastToken_ = null;
    -
    -
    -/**
    - * A LabelInput control that manages the focus/blur state of the input box.
    - * @type {goog.ui.LabelInput?}
    - * @private
    - */
    -goog.ui.ComboBox.prototype.labelInput_ = null;
    -
    -
    -/**
    - * Drop down menu for the combo box.  Will be created at construction time.
    - * @type {goog.ui.Menu?}
    - * @private
    - */
    -goog.ui.ComboBox.prototype.menu_ = null;
    -
    -
    -/**
    - * The cached visible count.
    - * @type {number}
    - * @private
    - */
    -goog.ui.ComboBox.prototype.visibleCount_ = -1;
    -
    -
    -/**
    - * The input element.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.ComboBox.prototype.input_ = null;
    -
    -
    -/**
    - * The match function.  The first argument for the match function will be
    - * a MenuItem's caption and the second will be the token to evaluate.
    - * @type {Function}
    - * @private
    - */
    -goog.ui.ComboBox.prototype.matchFunction_ = goog.string.startsWith;
    -
    -
    -/**
    - * Element used as the combo boxes button.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.ComboBox.prototype.button_ = null;
    -
    -
    -/**
    - * Default text content for the input box when it is unchanged and unfocussed.
    - * @type {string}
    - * @private
    - */
    -goog.ui.ComboBox.prototype.defaultText_ = '';
    -
    -
    -/**
    - * Name for the input box created
    - * @type {string}
    - * @private
    - */
    -goog.ui.ComboBox.prototype.fieldName_ = '';
    -
    -
    -/**
    - * Timer identifier for delaying the dismissal of the combo menu.
    - * @type {?number}
    - * @private
    - */
    -goog.ui.ComboBox.prototype.dismissTimer_ = null;
    -
    -
    -/**
    - * True if the unicode inverted triangle should be displayed in the dropdown
    - * button. Defaults to false.
    - * @type {boolean} useDropdownArrow
    - * @private
    - */
    -goog.ui.ComboBox.prototype.useDropdownArrow_ = false;
    -
    -
    -/**
    - * Create the DOM objects needed for the combo box.  A span and text input.
    - * @override
    - */
    -goog.ui.ComboBox.prototype.createDom = function() {
    -  this.input_ = this.getDomHelper().createDom(
    -      'input', {name: this.fieldName_, type: 'text', autocomplete: 'off'});
    -  this.button_ = this.getDomHelper().createDom('span',
    -      goog.getCssName('goog-combobox-button'));
    -  this.setElementInternal(this.getDomHelper().createDom('span',
    -      goog.getCssName('goog-combobox'), this.input_, this.button_));
    -  if (this.useDropdownArrow_) {
    -    goog.dom.setTextContent(this.button_, '\u25BC');
    -    goog.style.setUnselectable(this.button_, true /* unselectable */);
    -  }
    -  this.input_.setAttribute('label', this.defaultText_);
    -  this.labelInput_.decorate(this.input_);
    -  this.menu_.setFocusable(false);
    -  if (!this.menu_.isInDocument()) {
    -    this.addChild(this.menu_, true);
    -  }
    -};
    -
    -
    -/**
    - * Enables/Disables the combo box.
    - * @param {boolean} enabled Whether to enable (true) or disable (false) the
    - *     combo box.
    - */
    -goog.ui.ComboBox.prototype.setEnabled = function(enabled) {
    -  this.enabled_ = enabled;
    -  this.labelInput_.setEnabled(enabled);
    -  goog.dom.classlist.enable(
    -      goog.asserts.assert(this.getElement()),
    -      goog.getCssName('goog-combobox-disabled'), !enabled);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the menu item is enabled.
    - */
    -goog.ui.ComboBox.prototype.isEnabled = function() {
    -  return this.enabled_;
    -};
    -
    -
    -/** @override */
    -goog.ui.ComboBox.prototype.enterDocument = function() {
    -  goog.ui.ComboBox.superClass_.enterDocument.call(this);
    -
    -  var handler = this.getHandler();
    -  handler.listen(this.getElement(),
    -      goog.events.EventType.MOUSEDOWN, this.onComboMouseDown_);
    -  handler.listen(this.getDomHelper().getDocument(),
    -      goog.events.EventType.MOUSEDOWN, this.onDocClicked_);
    -
    -  handler.listen(this.input_,
    -      goog.events.EventType.BLUR, this.onInputBlur_);
    -
    -  this.keyHandler_ = new goog.events.KeyHandler(this.input_);
    -  handler.listen(this.keyHandler_,
    -      goog.events.KeyHandler.EventType.KEY, this.handleKeyEvent);
    -
    -  this.inputHandler_ = new goog.events.InputHandler(this.input_);
    -  handler.listen(this.inputHandler_,
    -      goog.events.InputHandler.EventType.INPUT, this.onInputEvent_);
    -
    -  handler.listen(this.menu_,
    -      goog.ui.Component.EventType.ACTION, this.onMenuSelected_);
    -};
    -
    -
    -/** @override */
    -goog.ui.ComboBox.prototype.exitDocument = function() {
    -  this.keyHandler_.dispose();
    -  delete this.keyHandler_;
    -  this.inputHandler_.dispose();
    -  this.inputHandler_ = null;
    -  goog.ui.ComboBox.superClass_.exitDocument.call(this);
    -};
    -
    -
    -/**
    - * Combo box currently can't decorate elements.
    - * @return {boolean} The value false.
    - * @override
    - */
    -goog.ui.ComboBox.prototype.canDecorate = function() {
    -  return false;
    -};
    -
    -
    -/** @override */
    -goog.ui.ComboBox.prototype.disposeInternal = function() {
    -  goog.ui.ComboBox.superClass_.disposeInternal.call(this);
    -
    -  this.clearDismissTimer_();
    -
    -  this.labelInput_.dispose();
    -  this.menu_.dispose();
    -
    -  this.labelInput_ = null;
    -  this.menu_ = null;
    -  this.input_ = null;
    -  this.button_ = null;
    -};
    -
    -
    -/**
    - * Dismisses the menu and resets the value of the edit field.
    - */
    -goog.ui.ComboBox.prototype.dismiss = function() {
    -  this.clearDismissTimer_();
    -  this.hideMenu_();
    -  this.menu_.setHighlightedIndex(-1);
    -};
    -
    -
    -/**
    - * Adds a new menu item at the end of the menu.
    - * @param {goog.ui.MenuItem} item Menu item to add to the menu.
    - */
    -goog.ui.ComboBox.prototype.addItem = function(item) {
    -  this.menu_.addChild(item, true);
    -  this.visibleCount_ = -1;
    -};
    -
    -
    -/**
    - * Adds a new menu item at a specific index in the menu.
    - * @param {goog.ui.MenuItem} item Menu item to add to the menu.
    - * @param {number} n Index at which to insert the menu item.
    - */
    -goog.ui.ComboBox.prototype.addItemAt = function(item, n) {
    -  this.menu_.addChildAt(item, n, true);
    -  this.visibleCount_ = -1;
    -};
    -
    -
    -/**
    - * Removes an item from the menu and disposes it.
    - * @param {goog.ui.MenuItem} item The menu item to remove.
    - */
    -goog.ui.ComboBox.prototype.removeItem = function(item) {
    -  var child = this.menu_.removeChild(item, true);
    -  if (child) {
    -    child.dispose();
    -    this.visibleCount_ = -1;
    -  }
    -};
    -
    -
    -/**
    - * Remove all of the items from the ComboBox menu
    - */
    -goog.ui.ComboBox.prototype.removeAllItems = function() {
    -  for (var i = this.getItemCount() - 1; i >= 0; --i) {
    -    this.removeItem(this.getItemAt(i));
    -  }
    -};
    -
    -
    -/**
    - * Removes a menu item at a given index in the menu.
    - * @param {number} n Index of item.
    - */
    -goog.ui.ComboBox.prototype.removeItemAt = function(n) {
    -  var child = this.menu_.removeChildAt(n, true);
    -  if (child) {
    -    child.dispose();
    -    this.visibleCount_ = -1;
    -  }
    -};
    -
    -
    -/**
    - * Returns a reference to the menu item at a given index.
    - * @param {number} n Index of menu item.
    - * @return {goog.ui.MenuItem?} Reference to the menu item.
    - */
    -goog.ui.ComboBox.prototype.getItemAt = function(n) {
    -  return /** @type {goog.ui.MenuItem?} */(this.menu_.getChildAt(n));
    -};
    -
    -
    -/**
    - * Returns the number of items in the list, including non-visible items,
    - * such as separators.
    - * @return {number} Number of items in the menu for this combobox.
    - */
    -goog.ui.ComboBox.prototype.getItemCount = function() {
    -  return this.menu_.getChildCount();
    -};
    -
    -
    -/**
    - * @return {goog.ui.Menu} The menu that pops up.
    - */
    -goog.ui.ComboBox.prototype.getMenu = function() {
    -  return this.menu_;
    -};
    -
    -
    -/**
    - * @return {Element} The input element.
    - */
    -goog.ui.ComboBox.prototype.getInputElement = function() {
    -  return this.input_;
    -};
    -
    -
    -/**
    - * @return {goog.ui.LabelInput} A LabelInput control that manages the
    - *     focus/blur state of the input box.
    - */
    -goog.ui.ComboBox.prototype.getLabelInput = function() {
    -  return this.labelInput_;
    -};
    -
    -
    -/**
    - * @return {number} The number of visible items in the menu.
    - * @private
    - */
    -goog.ui.ComboBox.prototype.getNumberOfVisibleItems_ = function() {
    -  if (this.visibleCount_ == -1) {
    -    var count = 0;
    -    for (var i = 0, n = this.menu_.getChildCount(); i < n; i++) {
    -      var item = this.menu_.getChildAt(i);
    -      if (!(item instanceof goog.ui.MenuSeparator) && item.isVisible()) {
    -        count++;
    -      }
    -    }
    -    this.visibleCount_ = count;
    -  }
    -
    -  goog.log.info(this.logger_,
    -      'getNumberOfVisibleItems() - ' + this.visibleCount_);
    -  return this.visibleCount_;
    -};
    -
    -
    -/**
    - * Sets the match function to be used when filtering the combo box menu.
    - * @param {Function} matchFunction The match function to be used when filtering
    - *     the combo box menu.
    - */
    -goog.ui.ComboBox.prototype.setMatchFunction = function(matchFunction) {
    -  this.matchFunction_ = matchFunction;
    -};
    -
    -
    -/**
    - * @return {Function} The match function for the combox box.
    - */
    -goog.ui.ComboBox.prototype.getMatchFunction = function() {
    -  return this.matchFunction_;
    -};
    -
    -
    -/**
    - * Sets the default text for the combo box.
    - * @param {string} text The default text for the combo box.
    - */
    -goog.ui.ComboBox.prototype.setDefaultText = function(text) {
    -  this.defaultText_ = text;
    -  if (this.labelInput_) {
    -    this.labelInput_.setLabel(this.defaultText_);
    -  }
    -};
    -
    -
    -/**
    - * @return {string} text The default text for the combox box.
    - */
    -goog.ui.ComboBox.prototype.getDefaultText = function() {
    -  return this.defaultText_;
    -};
    -
    -
    -/**
    - * Sets the field name for the combo box.
    - * @param {string} fieldName The field name for the combo box.
    - */
    -goog.ui.ComboBox.prototype.setFieldName = function(fieldName) {
    -  this.fieldName_ = fieldName;
    -};
    -
    -
    -/**
    - * @return {string} The field name for the combo box.
    - */
    -goog.ui.ComboBox.prototype.getFieldName = function() {
    -  return this.fieldName_;
    -};
    -
    -
    -/**
    - * Set to true if a unicode inverted triangle should be displayed in the
    - * dropdown button.
    - * This option defaults to false for backwards compatibility.
    - * @param {boolean} useDropdownArrow True to use the dropdown arrow.
    - */
    -goog.ui.ComboBox.prototype.setUseDropdownArrow = function(useDropdownArrow) {
    -  this.useDropdownArrow_ = !!useDropdownArrow;
    -};
    -
    -
    -/**
    - * Sets the current value of the combo box.
    - * @param {string} value The new value.
    - */
    -goog.ui.ComboBox.prototype.setValue = function(value) {
    -  goog.log.info(this.logger_, 'setValue() - ' + value);
    -  if (this.labelInput_.getValue() != value) {
    -    this.labelInput_.setValue(value);
    -    this.handleInputChange_();
    -  }
    -};
    -
    -
    -/**
    - * @return {string} The current value of the combo box.
    - */
    -goog.ui.ComboBox.prototype.getValue = function() {
    -  return this.labelInput_.getValue();
    -};
    -
    -
    -/**
    - * @return {string} HTML escaped token.
    - */
    -goog.ui.ComboBox.prototype.getToken = function() {
    -  // TODO(user): Remove HTML escaping and fix the existing calls.
    -  return goog.string.htmlEscape(this.getTokenText_());
    -};
    -
    -
    -/**
    - * @return {string} The token for the current cursor position in the
    - *     input box, when multi-input is disabled it will be the full input value.
    - * @private
    - */
    -goog.ui.ComboBox.prototype.getTokenText_ = function() {
    -  // TODO(user): Implement multi-input such that getToken returns a substring
    -  // of the whole input delimited by commas.
    -  return goog.string.trim(this.labelInput_.getValue().toLowerCase());
    -};
    -
    -
    -/**
    - * @private
    - */
    -goog.ui.ComboBox.prototype.setupMenu_ = function() {
    -  var sm = this.menu_;
    -  sm.setVisible(false);
    -  sm.setAllowAutoFocus(false);
    -  sm.setAllowHighlightDisabled(true);
    -};
    -
    -
    -/**
    - * Shows the menu if it isn't already showing.  Also positions the menu
    - * correctly, resets the menu item visibilities and highlights the relevent
    - * item.
    - * @param {boolean} showAll Whether to show all items, with the first matching
    - *     item highlighted.
    - * @private
    - */
    -goog.ui.ComboBox.prototype.maybeShowMenu_ = function(showAll) {
    -  var isVisible = this.menu_.isVisible();
    -  var numVisibleItems = this.getNumberOfVisibleItems_();
    -
    -  if (isVisible && numVisibleItems == 0) {
    -    goog.log.fine(this.logger_, 'no matching items, hiding');
    -    this.hideMenu_();
    -
    -  } else if (!isVisible && numVisibleItems > 0) {
    -    if (showAll) {
    -      goog.log.fine(this.logger_, 'showing menu');
    -      this.setItemVisibilityFromToken_('');
    -      this.setItemHighlightFromToken_(this.getTokenText_());
    -    }
    -    // In Safari 2.0, when clicking on the combox box, the blur event is
    -    // received after the click event that invokes this function. Since we want
    -    // to cancel the dismissal after the blur event is processed, we have to
    -    // wait for all event processing to happen.
    -    goog.Timer.callOnce(this.clearDismissTimer_, 1, this);
    -
    -    this.showMenu_();
    -  }
    -
    -  this.positionMenu();
    -};
    -
    -
    -/**
    - * Positions the menu.
    - * @protected
    - */
    -goog.ui.ComboBox.prototype.positionMenu = function() {
    -  if (this.menu_ && this.menu_.isVisible()) {
    -    var position = new goog.positioning.MenuAnchoredPosition(this.getElement(),
    -        goog.positioning.Corner.BOTTOM_START, true);
    -    position.reposition(this.menu_.getElement(),
    -        goog.positioning.Corner.TOP_START);
    -  }
    -};
    -
    -
    -/**
    - * Show the menu and add an active class to the combo box's element.
    - * @private
    - */
    -goog.ui.ComboBox.prototype.showMenu_ = function() {
    -  this.menu_.setVisible(true);
    -  goog.dom.classlist.add(
    -      goog.asserts.assert(this.getElement()),
    -      goog.getCssName('goog-combobox-active'));
    -};
    -
    -
    -/**
    - * Hide the menu and remove the active class from the combo box's element.
    - * @private
    - */
    -goog.ui.ComboBox.prototype.hideMenu_ = function() {
    -  this.menu_.setVisible(false);
    -  goog.dom.classlist.remove(
    -      goog.asserts.assert(this.getElement()),
    -      goog.getCssName('goog-combobox-active'));
    -};
    -
    -
    -/**
    - * Clears the dismiss timer if it's active.
    - * @private
    - */
    -goog.ui.ComboBox.prototype.clearDismissTimer_ = function() {
    -  if (this.dismissTimer_) {
    -    goog.Timer.clear(this.dismissTimer_);
    -    this.dismissTimer_ = null;
    -  }
    -};
    -
    -
    -/**
    - * Event handler for when the combo box area has been clicked.
    - * @param {goog.events.BrowserEvent} e The browser event.
    - * @private
    - */
    -goog.ui.ComboBox.prototype.onComboMouseDown_ = function(e) {
    -  // We only want this event on the element itself or the input or the button.
    -  if (this.enabled_ &&
    -      (e.target == this.getElement() || e.target == this.input_ ||
    -       goog.dom.contains(this.button_, /** @type {Node} */ (e.target)))) {
    -    if (this.menu_.isVisible()) {
    -      goog.log.fine(this.logger_, 'Menu is visible, dismissing');
    -      this.dismiss();
    -    } else {
    -      goog.log.fine(this.logger_, 'Opening dropdown');
    -      this.maybeShowMenu_(true);
    -      if (goog.userAgent.OPERA) {
    -        // select() doesn't focus <input> elements in Opera.
    -        this.input_.focus();
    -      }
    -      this.input_.select();
    -      this.menu_.setMouseButtonPressed(true);
    -      // Stop the click event from stealing focus
    -      e.preventDefault();
    -    }
    -  }
    -  // Stop the event from propagating outside of the combo box
    -  e.stopPropagation();
    -};
    -
    -
    -/**
    - * Event handler for when the document is clicked.
    - * @param {goog.events.BrowserEvent} e The browser event.
    - * @private
    - */
    -goog.ui.ComboBox.prototype.onDocClicked_ = function(e) {
    -  if (!goog.dom.contains(
    -      this.menu_.getElement(), /** @type {Node} */ (e.target))) {
    -    goog.log.info(this.logger_, 'onDocClicked_() - dismissing immediately');
    -    this.dismiss();
    -  }
    -};
    -
    -
    -/**
    - * Handle the menu's select event.
    - * @param {goog.events.Event} e The event.
    - * @private
    - */
    -goog.ui.ComboBox.prototype.onMenuSelected_ = function(e) {
    -  goog.log.info(this.logger_, 'onMenuSelected_()');
    -  var item = /** @type {!goog.ui.MenuItem} */ (e.target);
    -  // Stop propagation of the original event and redispatch to allow the menu
    -  // select to be cancelled at this level. i.e. if a menu item should cause
    -  // some behavior such as a user prompt instead of assigning the caption as
    -  // the value.
    -  if (this.dispatchEvent(new goog.ui.ItemEvent(
    -      goog.ui.Component.EventType.ACTION, this, item))) {
    -    var caption = item.getCaption();
    -    goog.log.fine(this.logger_,
    -        'Menu selection: ' + caption + '. Dismissing menu');
    -    if (this.labelInput_.getValue() != caption) {
    -      this.labelInput_.setValue(caption);
    -      this.dispatchEvent(goog.ui.Component.EventType.CHANGE);
    -    }
    -    this.dismiss();
    -  }
    -  e.stopPropagation();
    -};
    -
    -
    -/**
    - * Event handler for when the input box looses focus -- hide the menu
    - * @param {goog.events.BrowserEvent} e The browser event.
    - * @private
    - */
    -goog.ui.ComboBox.prototype.onInputBlur_ = function(e) {
    -  goog.log.info(this.logger_, 'onInputBlur_() - delayed dismiss');
    -  this.clearDismissTimer_();
    -  this.dismissTimer_ = goog.Timer.callOnce(
    -      this.dismiss, goog.ui.ComboBox.BLUR_DISMISS_TIMER_MS, this);
    -};
    -
    -
    -/**
    - * Handles keyboard events from the input box.  Returns true if the combo box
    - * was able to handle the event, false otherwise.
    - * @param {goog.events.KeyEvent} e Key event to handle.
    - * @return {boolean} Whether the event was handled by the combo box.
    - * @protected
    - * @suppress {visibility} performActionInternal
    - */
    -goog.ui.ComboBox.prototype.handleKeyEvent = function(e) {
    -  var isMenuVisible = this.menu_.isVisible();
    -
    -  // Give the menu a chance to handle the event.
    -  if (isMenuVisible && this.menu_.handleKeyEvent(e)) {
    -    return true;
    -  }
    -
    -  // The menu is either hidden or didn't handle the event.
    -  var handled = false;
    -  switch (e.keyCode) {
    -    case goog.events.KeyCodes.ESC:
    -      // If the menu is visible and the user hit Esc, dismiss the menu.
    -      if (isMenuVisible) {
    -        goog.log.fine(this.logger_,
    -            'Dismiss on Esc: ' + this.labelInput_.getValue());
    -        this.dismiss();
    -        handled = true;
    -      }
    -      break;
    -    case goog.events.KeyCodes.TAB:
    -      // If the menu is open and an option is highlighted, activate it.
    -      if (isMenuVisible) {
    -        var highlighted = this.menu_.getHighlighted();
    -        if (highlighted) {
    -          goog.log.fine(this.logger_,
    -              'Select on Tab: ' + this.labelInput_.getValue());
    -          highlighted.performActionInternal(e);
    -          handled = true;
    -        }
    -      }
    -      break;
    -    case goog.events.KeyCodes.UP:
    -    case goog.events.KeyCodes.DOWN:
    -      // If the menu is hidden and the user hit the up/down arrow, show it.
    -      if (!isMenuVisible) {
    -        goog.log.fine(this.logger_, 'Up/Down - maybe show menu');
    -        this.maybeShowMenu_(true);
    -        handled = true;
    -      }
    -      break;
    -  }
    -
    -  if (handled) {
    -    e.preventDefault();
    -  }
    -
    -  return handled;
    -};
    -
    -
    -/**
    - * Handles the content of the input box changing.
    - * @param {goog.events.Event} e The INPUT event to handle.
    - * @private
    - */
    -goog.ui.ComboBox.prototype.onInputEvent_ = function(e) {
    -  // If the key event is text-modifying, update the menu.
    -  goog.log.fine(this.logger_,
    -      'Key is modifying: ' + this.labelInput_.getValue());
    -  this.handleInputChange_();
    -};
    -
    -
    -/**
    - * Handles the content of the input box changing, either because of user
    - * interaction or programmatic changes.
    - * @private
    - */
    -goog.ui.ComboBox.prototype.handleInputChange_ = function() {
    -  var token = this.getTokenText_();
    -  this.setItemVisibilityFromToken_(token);
    -  if (goog.dom.getActiveElement(this.getDomHelper().getDocument()) ==
    -      this.input_) {
    -    // Do not alter menu visibility unless the user focus is currently on the
    -    // combobox (otherwise programmatic changes may cause the menu to become
    -    // visible).
    -    this.maybeShowMenu_(false);
    -  }
    -  var highlighted = this.menu_.getHighlighted();
    -  if (token == '' || !highlighted || !highlighted.isVisible()) {
    -    this.setItemHighlightFromToken_(token);
    -  }
    -  this.lastToken_ = token;
    -  this.dispatchEvent(goog.ui.Component.EventType.CHANGE);
    -};
    -
    -
    -/**
    - * Loops through all menu items setting their visibility according to a token.
    - * @param {string} token The token.
    - * @private
    - */
    -goog.ui.ComboBox.prototype.setItemVisibilityFromToken_ = function(token) {
    -  goog.log.info(this.logger_, 'setItemVisibilityFromToken_() - ' + token);
    -  var isVisibleItem = false;
    -  var count = 0;
    -  var recheckHidden = !this.matchFunction_(token, this.lastToken_);
    -
    -  for (var i = 0, n = this.menu_.getChildCount(); i < n; i++) {
    -    var item = this.menu_.getChildAt(i);
    -    if (item instanceof goog.ui.MenuSeparator) {
    -      // Ensure that separators are only shown if there is at least one visible
    -      // item before them.
    -      item.setVisible(isVisibleItem);
    -      isVisibleItem = false;
    -    } else if (item instanceof goog.ui.MenuItem) {
    -      if (!item.isVisible() && !recheckHidden) continue;
    -
    -      var caption = item.getCaption();
    -      var visible = this.isItemSticky_(item) ||
    -          caption && this.matchFunction_(caption.toLowerCase(), token);
    -      if (typeof item.setFormatFromToken == 'function') {
    -        item.setFormatFromToken(token);
    -      }
    -      item.setVisible(!!visible);
    -      isVisibleItem = visible || isVisibleItem;
    -
    -    } else {
    -      // Assume all other items are correctly using their visibility.
    -      isVisibleItem = item.isVisible() || isVisibleItem;
    -    }
    -
    -    if (!(item instanceof goog.ui.MenuSeparator) && item.isVisible()) {
    -      count++;
    -    }
    -  }
    -
    -  this.visibleCount_ = count;
    -};
    -
    -
    -/**
    - * Highlights the first token that matches the given token.
    - * @param {string} token The token.
    - * @private
    - */
    -goog.ui.ComboBox.prototype.setItemHighlightFromToken_ = function(token) {
    -  goog.log.info(this.logger_, 'setItemHighlightFromToken_() - ' + token);
    -
    -  if (token == '') {
    -    this.menu_.setHighlightedIndex(-1);
    -    return;
    -  }
    -
    -  for (var i = 0, n = this.menu_.getChildCount(); i < n; i++) {
    -    var item = this.menu_.getChildAt(i);
    -    var caption = item.getCaption();
    -    if (caption && this.matchFunction_(caption.toLowerCase(), token)) {
    -      this.menu_.setHighlightedIndex(i);
    -      if (item.setFormatFromToken) {
    -        item.setFormatFromToken(token);
    -      }
    -      return;
    -    }
    -  }
    -  this.menu_.setHighlightedIndex(-1);
    -};
    -
    -
    -/**
    - * Returns true if the item has an isSticky method and the method returns true.
    - * @param {goog.ui.MenuItem} item The item.
    - * @return {boolean} Whether the item has an isSticky method and the method
    - *     returns true.
    - * @private
    - */
    -goog.ui.ComboBox.prototype.isItemSticky_ = function(item) {
    -  return typeof item.isSticky == 'function' && item.isSticky();
    -};
    -
    -
    -
    -/**
    - * Class for combo box items.
    - * @param {goog.ui.ControlContent} content Text caption or DOM structure to
    - *     display as the content of the item (use to add icons or styling to
    - *     menus).
    - * @param {Object=} opt_data Identifying data for the menu item.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional dom helper used for dom
    - *     interactions.
    - * @param {goog.ui.MenuItemRenderer=} opt_renderer Optional renderer.
    - * @constructor
    - * @extends {goog.ui.MenuItem}
    - */
    -goog.ui.ComboBoxItem = function(content, opt_data, opt_domHelper,
    -    opt_renderer) {
    -  goog.ui.MenuItem.call(this, content, opt_data, opt_domHelper, opt_renderer);
    -};
    -goog.inherits(goog.ui.ComboBoxItem, goog.ui.MenuItem);
    -goog.tagUnsealableClass(goog.ui.ComboBoxItem);
    -
    -
    -// Register a decorator factory function for goog.ui.ComboBoxItems.
    -goog.ui.registry.setDecoratorByClassName(goog.getCssName('goog-combobox-item'),
    -    function() {
    -      // ComboBoxItem defaults to using MenuItemRenderer.
    -      return new goog.ui.ComboBoxItem(null);
    -    });
    -
    -
    -/**
    - * Whether the menu item is sticky, non-sticky items will be hidden as the
    - * user types.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.ComboBoxItem.prototype.isSticky_ = false;
    -
    -
    -/**
    - * Sets the menu item to be sticky or not sticky.
    - * @param {boolean} sticky Whether the menu item should be sticky.
    - */
    -goog.ui.ComboBoxItem.prototype.setSticky = function(sticky) {
    -  this.isSticky_ = sticky;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the menu item is sticky.
    - */
    -goog.ui.ComboBoxItem.prototype.isSticky = function() {
    -  return this.isSticky_;
    -};
    -
    -
    -/**
    - * Sets the format for a menu item based on a token, bolding the token.
    - * @param {string} token The token.
    - */
    -goog.ui.ComboBoxItem.prototype.setFormatFromToken = function(token) {
    -  if (this.isEnabled()) {
    -    var caption = this.getCaption();
    -    var index = caption.toLowerCase().indexOf(token);
    -    if (index >= 0) {
    -      var domHelper = this.getDomHelper();
    -      this.setContent([
    -        domHelper.createTextNode(caption.substr(0, index)),
    -        domHelper.createDom('b', null, caption.substr(index, token.length)),
    -        domHelper.createTextNode(caption.substr(index + token.length))
    -      ]);
    -    }
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/combobox_test.html b/src/database/third_party/closure-library/closure/goog/ui/combobox_test.html
    deleted file mode 100644
    index 92c109a36e0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/combobox_test.html
    +++ /dev/null
    @@ -1,48 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -
    -  @author gboyer@google.com (Garrett Boyer)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.ComboBox
    -  </title>
    -  <style type="text/css">
    -   .goog-menu {
    -  position: absolute;
    -}
    -  </style>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.ComboBoxTest');
    -  </script>
    - </head>
    - <body>
    -  <h2 style="color:red">
    -   This test is rudimentary.
    -The fact that it passes should not (yet) make you too confident.
    -  </h2>
    -  <div id="combo">
    -  </div>
    -  <div id="menu">
    -   <div class="goog-combobox-item">
    -    Red
    -   </div>
    -   <div class="goog-combobox-item">
    -    Green
    -   </div>
    -   <div class="goog-combobox-item">
    -    Blue
    -   </div>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/combobox_test.js b/src/database/third_party/closure-library/closure/goog/ui/combobox_test.js
    deleted file mode 100644
    index 3a3f6541136..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/combobox_test.js
    +++ /dev/null
    @@ -1,271 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.ComboBoxTest');
    -goog.setTestOnly('goog.ui.ComboBoxTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.ComboBox');
    -goog.require('goog.ui.ComboBoxItem');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.ControlRenderer');
    -goog.require('goog.ui.LabelInput');
    -goog.require('goog.ui.Menu');
    -goog.require('goog.ui.MenuItem');
    -
    -var comboBox;
    -var input;
    -
    -function setUp() {
    -  goog.dom.getElement('combo').innerHTML = '';
    -
    -  comboBox = new goog.ui.ComboBox();
    -  comboBox.setDefaultText('Select a color...');
    -  comboBox.addItem(new goog.ui.ComboBoxItem('Red'));
    -  comboBox.addItem(new goog.ui.ComboBoxItem('Maroon'));
    -  comboBox.addItem(new goog.ui.ComboBoxItem('Gre<en'));
    -  comboBox.addItem(new goog.ui.ComboBoxItem('Blue'));
    -  comboBox.addItem(new goog.ui.ComboBoxItem('Royal Blue'));
    -  comboBox.addItem(new goog.ui.ComboBoxItem('Yellow'));
    -  comboBox.addItem(new goog.ui.ComboBoxItem('Magenta'));
    -  comboBox.addItem(new goog.ui.ComboBoxItem('Mouve'));
    -  comboBox.addItem(new goog.ui.ComboBoxItem('Grey'));
    -  comboBox.render(goog.dom.getElement('combo'));
    -
    -  input = comboBox.getInputElement();
    -}
    -
    -function tearDown() {
    -  comboBox.dispose();
    -}
    -
    -function testInputElementAttributes() {
    -  var comboBox = new goog.ui.ComboBox();
    -  comboBox.setFieldName('a_form_field');
    -  comboBox.createDom();
    -  var inputElement = comboBox.getInputElement();
    -  assertEquals('text', inputElement.type);
    -  assertEquals('a_form_field', inputElement.name);
    -  assertEquals('off', inputElement.autocomplete);
    -  comboBox.dispose();
    -}
    -
    -function testSetDefaultText() {
    -  assertEquals('Select a color...', comboBox.getDefaultText());
    -  comboBox.setDefaultText('new default text...');
    -  assertEquals('new default text...', comboBox.getDefaultText());
    -  assertEquals('new default text...', comboBox.labelInput_.getLabel());
    -}
    -
    -function testGetMenu() {
    -  assertTrue('Menu should be instance of goog.ui.Menu',
    -      comboBox.getMenu() instanceof goog.ui.Menu);
    -  assertEquals('Menu should have correct number of children',
    -      9, comboBox.getMenu().getChildCount());
    -}
    -
    -function testMenuBeginsInvisible() {
    -  assertFalse('Menu should begin invisible', comboBox.getMenu().isVisible());
    -}
    -
    -function testClickCausesPopup() {
    -  goog.testing.events.fireClickSequence(input);
    -  assertTrue('Menu becomes visible after click',
    -      comboBox.getMenu().isVisible());
    -}
    -
    -function testUpKeyCausesPopup() {
    -  goog.testing.events.fireKeySequence(input, goog.events.KeyCodes.UP);
    -  assertTrue('Menu becomes visible after UP key',
    -      comboBox.getMenu().isVisible());
    -}
    -
    -function testActionSelectsItem() {
    -  comboBox.getMenu().getItemAt(2).dispatchEvent(
    -      goog.ui.Component.EventType.ACTION);
    -  assertEquals('Gre<en', input.value);
    -}
    -
    -function testActionSelectsItemWithModel() {
    -  var itemWithModel = new goog.ui.MenuItem('one', 1);
    -  comboBox.addItem(itemWithModel);
    -  itemWithModel.dispatchEvent(goog.ui.Component.EventType.ACTION);
    -  assertEquals('one', comboBox.getValue());
    -}
    -
    -function testRedisplayMenuAfterBackspace() {
    -  input.value = 'mx';
    -  comboBox.onInputEvent_();
    -  input.value = 'm';
    -  comboBox.onInputEvent_();
    -  assertEquals('Three items should be displayed',
    -      3, comboBox.getNumberOfVisibleItems_());
    -}
    -
    -function testExternallyCreatedMenu() {
    -  var menu = new goog.ui.Menu();
    -  menu.decorate(goog.dom.getElement('menu'));
    -  assertTrue('Menu items should be instances of goog.ui.ComboBoxItem',
    -      menu.getChildAt(0) instanceof goog.ui.ComboBoxItem);
    -
    -  comboBox = new goog.ui.ComboBox(null, menu);
    -  comboBox.render(goog.dom.getElement('combo'));
    -
    -  input = comboBox.getElement().getElementsByTagName(
    -      goog.dom.TagName.INPUT)[0];
    -  menu.getItemAt(2).dispatchEvent(
    -      goog.ui.Component.EventType.ACTION);
    -  assertEquals('Blue', input.value);
    -}
    -
    -function testRecomputeVisibleCountAfterChangingItems() {
    -  input.value = 'Black';
    -  comboBox.onInputEvent_();
    -  assertEquals('No items should be displayed',
    -      0, comboBox.getNumberOfVisibleItems_());
    -  comboBox.addItem(new goog.ui.ComboBoxItem('Black'));
    -  assertEquals('One item should be displayed',
    -      1, comboBox.getNumberOfVisibleItems_());
    -
    -  input.value = 'Red';
    -  comboBox.onInputEvent_();
    -  assertEquals('One item should be displayed',
    -      1, comboBox.getNumberOfVisibleItems_());
    -  comboBox.removeItemAt(0);  // Red
    -  assertEquals('No items should be displayed',
    -      0, comboBox.getNumberOfVisibleItems_());
    -}
    -
    -function testSetEnabled() {
    -  // By default, everything should be enabled.
    -  assertFalse('Text input should initially not be disabled', input.disabled);
    -  assertFalse('Text input should initially not look disabled',
    -      goog.dom.classlist.contains(input,
    -      goog.getCssName(goog.ui.LabelInput.prototype.labelCssClassName,
    -          'disabled')));
    -  assertFalse('Combo box should initially not look disabled',
    -      goog.dom.classlist.contains(comboBox.getElement(),
    -      goog.getCssName('goog-combobox-disabled')));
    -  goog.testing.events.fireClickSequence(comboBox.getElement());
    -  assertTrue('Menu initially becomes visible after click',
    -      comboBox.getMenu().isVisible());
    -  goog.testing.events.fireClickSequence(document);
    -  assertFalse('Menu initially becomes invisible after document click',
    -      comboBox.getMenu().isVisible());
    -
    -  assertTrue(comboBox.isEnabled());
    -  comboBox.setEnabled(false);
    -  assertFalse(comboBox.isEnabled());
    -  assertTrue('Text input should be disabled after being disabled',
    -      input.disabled);
    -  assertTrue('Text input should appear disabled after being disabled',
    -      goog.dom.classlist.contains(input,
    -      goog.getCssName(goog.ui.LabelInput.prototype.labelCssClassName,
    -          'disabled')));
    -  assertTrue('Combo box should appear disabled after being disabled',
    -      goog.dom.classlist.contains(comboBox.getElement(),
    -      goog.getCssName('goog-combobox-disabled')));
    -  goog.testing.events.fireClickSequence(comboBox.getElement());
    -  assertFalse('Menu should not become visible after click if disabled',
    -      comboBox.getMenu().isVisible());
    -
    -  comboBox.setEnabled(true);
    -  assertTrue(comboBox.isEnabled());
    -  assertFalse('Text input should not be disabled after being re-enabled',
    -      input.disabled);
    -  assertFalse('Text input should not appear disabled after being re-enabled',
    -      goog.dom.classlist.contains(input,
    -      goog.getCssName(goog.ui.LabelInput.prototype.labelCssClassName,
    -          'disabled')));
    -  assertFalse('Combo box should not appear disabled after being re-enabled',
    -      goog.dom.classlist.contains(comboBox.getElement(),
    -      goog.getCssName('goog-combobox-disabled')));
    -  goog.testing.events.fireClickSequence(comboBox.getElement());
    -  assertTrue('Menu becomes visible after click when re-enabled',
    -      comboBox.getMenu().isVisible());
    -  goog.testing.events.fireClickSequence(document);
    -  assertFalse('Menu becomes invisible after document click when re-enabled',
    -      comboBox.getMenu().isVisible());
    -}
    -
    -function testSetFormatFromToken() {
    -  var item = new goog.ui.ComboBoxItem('ABc');
    -  item.setFormatFromToken('b');
    -  var div = goog.dom.createDom('div');
    -  new goog.ui.ControlRenderer().setContent(div, item.getContent());
    -  assertTrue(div.innerHTML == 'A<b>B</b>c' || div.innerHTML == 'A<B>B</B>c');
    -}
    -
    -function testSetValue() {
    -  var clock = new goog.testing.MockClock(/* autoInstall */ true);
    -
    -  // Get the input focus. Note that both calls are needed to correctly
    -  // simulate the focus (and setting document.activeElement) across all
    -  // browsers.
    -  input.focus();
    -  goog.testing.events.fireClickSequence(input);
    -
    -  // Simulate text input.
    -  input.value = 'Black';
    -  comboBox.onInputEvent_();
    -  clock.tick();
    -  assertEquals('No items should be displayed',
    -      0, comboBox.getNumberOfVisibleItems_());
    -  assertFalse('Menu should be invisible', comboBox.getMenu().isVisible());
    -
    -  // Programmatic change with the input focus causes the menu visibility to
    -  // change if needed.
    -  comboBox.setValue('Blue');
    -  clock.tick();
    -  assertTrue('Menu should be visible1', comboBox.getMenu().isVisible());
    -  assertEquals('One item should be displayed',
    -      1, comboBox.getNumberOfVisibleItems_());
    -
    -  // Simulate user input to ensure all the items are invisible again, then
    -  // blur away.
    -  input.value = 'Black';
    -  comboBox.onInputEvent_();
    -  clock.tick();
    -  input.blur();
    -  document.body.focus();
    -  clock.tick(goog.ui.ComboBox.BLUR_DISMISS_TIMER_MS);
    -  assertEquals('No items should be displayed',
    -      0, comboBox.getNumberOfVisibleItems_());
    -  assertFalse('Menu should be invisible', comboBox.getMenu().isVisible());
    -
    -  // Programmatic change without the input focus does not pop up the menu,
    -  // but still updates the list of visible items within it.
    -  comboBox.setValue('Blue');
    -  clock.tick();
    -  assertFalse('Menu should be invisible', comboBox.getMenu().isVisible());
    -  assertEquals('Menu should contain one item',
    -      1, comboBox.getNumberOfVisibleItems_());
    -
    -  // Click on the combobox. The entire menu becomes visible, the last item
    -  // (programmatically) set is highlighted.
    -  goog.testing.events.fireClickSequence(comboBox.getElement());
    -  assertTrue('Menu should be visible2', comboBox.getMenu().isVisible());
    -  assertEquals('All items should be displayed',
    -      comboBox.getMenu().getItemCount(), comboBox.getNumberOfVisibleItems_());
    -  assertEquals('The last item set should be highlighted',
    -      /* Blue= */ 3, comboBox.getMenu().getHighlightedIndex());
    -
    -  clock.uninstall();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/component.js b/src/database/third_party/closure-library/closure/goog/ui/component.js
    deleted file mode 100644
    index b8806fde440..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/component.js
    +++ /dev/null
    @@ -1,1297 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Abstract class for all UI components. This defines the standard
    - * design pattern that all UI components should follow.
    - *
    - * @author attila@google.com (Attila Bodis)
    - * @see ../demos/samplecomponent.html
    - * @see http://code.google.com/p/closure-library/wiki/IntroToComponents
    - */
    -
    -goog.provide('goog.ui.Component');
    -goog.provide('goog.ui.Component.Error');
    -goog.provide('goog.ui.Component.EventType');
    -goog.provide('goog.ui.Component.State');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.NodeType');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.object');
    -goog.require('goog.style');
    -goog.require('goog.ui.IdGenerator');
    -
    -
    -
    -/**
    - * Default implementation of UI component.
    - *
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - */
    -goog.ui.Component = function(opt_domHelper) {
    -  goog.events.EventTarget.call(this);
    -  /**
    -   * DomHelper used to interact with the document, allowing components to be
    -   * created in a different window.
    -   * @protected {!goog.dom.DomHelper}
    -   * @suppress {underscore|visibility}
    -   */
    -  this.dom_ = opt_domHelper || goog.dom.getDomHelper();
    -
    -  /**
    -   * Whether the component is rendered right-to-left.  Right-to-left is set
    -   * lazily when {@link #isRightToLeft} is called the first time, unless it has
    -   * been set by calling {@link #setRightToLeft} explicitly.
    -   * @private {?boolean}
    -   */
    -  this.rightToLeft_ = goog.ui.Component.defaultRightToLeft_;
    -
    -  /**
    -   * Unique ID of the component, lazily initialized in {@link
    -   * goog.ui.Component#getId} if needed.  This property is strictly private and
    -   * must not be accessed directly outside of this class!
    -   * @private {?string}
    -   */
    -  this.id_ = null;
    -
    -  /**
    -   * Whether the component is in the document.
    -   * @private {boolean}
    -   */
    -  this.inDocument_ = false;
    -
    -  // TODO(attila): Stop referring to this private field in subclasses.
    -  /**
    -   * The DOM element for the component.
    -   * @private {Element}
    -   */
    -  this.element_ = null;
    -
    -  /**
    -   * Event handler.
    -   * TODO(user): rename it to handler_ after all component subclasses in
    -   * inside Google have been cleaned up.
    -   * Code search: http://go/component_code_search
    -   * @private {goog.events.EventHandler|undefined}
    -   */
    -  this.googUiComponentHandler_ = void 0;
    -
    -  /**
    -   * Arbitrary data object associated with the component.  Such as meta-data.
    -   * @private {*}
    -   */
    -  this.model_ = null;
    -
    -  /**
    -   * Parent component to which events will be propagated.  This property is
    -   * strictly private and must not be accessed directly outside of this class!
    -   * @private {goog.ui.Component?}
    -   */
    -  this.parent_ = null;
    -
    -  /**
    -   * Array of child components.  Lazily initialized on first use.  Must be kept
    -   * in sync with {@code childIndex_}.  This property is strictly private and
    -   * must not be accessed directly outside of this class!
    -   * @private {Array<goog.ui.Component>?}
    -   */
    -  this.children_ = null;
    -
    -  /**
    -   * Map of child component IDs to child components.  Used for constant-time
    -   * random access to child components by ID.  Lazily initialized on first use.
    -   * Must be kept in sync with {@code children_}.  This property is strictly
    -   * private and must not be accessed directly outside of this class!
    -   *
    -   * We use a plain Object, not a {@link goog.structs.Map}, for simplicity.
    -   * This means components can't have children with IDs such as 'constructor' or
    -   * 'valueOf', but this shouldn't really be an issue in practice, and if it is,
    -   * we can always fix it later without changing the API.
    -   *
    -   * @private {Object}
    -   */
    -  this.childIndex_ = null;
    -
    -  /**
    -   * Flag used to keep track of whether a component decorated an already
    -   * existing element or whether it created the DOM itself.
    -   *
    -   * If an element is decorated, dispose will leave the node in the document.
    -   * It is up to the app to remove the node.
    -   *
    -   * If an element was rendered, dispose will remove the node automatically.
    -   *
    -   * @private {boolean}
    -   */
    -  this.wasDecorated_ = false;
    -};
    -goog.inherits(goog.ui.Component, goog.events.EventTarget);
    -
    -
    -/**
    - * @define {boolean} Whether to support calling decorate with an element that is
    - *     not yet in the document. If true, we check if the element is in the
    - *     document, and avoid calling enterDocument if it isn't. If false, we
    - *     maintain legacy behavior (always call enterDocument from decorate).
    - */
    -goog.define('goog.ui.Component.ALLOW_DETACHED_DECORATION', false);
    -
    -
    -/**
    - * Generator for unique IDs.
    - * @type {goog.ui.IdGenerator}
    - * @private
    - */
    -goog.ui.Component.prototype.idGenerator_ = goog.ui.IdGenerator.getInstance();
    -
    -
    -// TODO(gboyer): See if we can remove this and just check goog.i18n.bidi.IS_RTL.
    -/**
    - * @define {number} Defines the default BIDI directionality.
    - *     0: Unknown.
    - *     1: Left-to-right.
    - *     -1: Right-to-left.
    - */
    -goog.define('goog.ui.Component.DEFAULT_BIDI_DIR', 0);
    -
    -
    -/**
    - * The default right to left value.
    - * @type {?boolean}
    - * @private
    - */
    -goog.ui.Component.defaultRightToLeft_ =
    -    (goog.ui.Component.DEFAULT_BIDI_DIR == 1) ? false :
    -    (goog.ui.Component.DEFAULT_BIDI_DIR == -1) ? true : null;
    -
    -
    -/**
    - * Common events fired by components so that event propagation is useful.  Not
    - * all components are expected to dispatch or listen for all event types.
    - * Events dispatched before a state transition should be cancelable to prevent
    - * the corresponding state change.
    - * @enum {string}
    - */
    -goog.ui.Component.EventType = {
    -  /** Dispatched before the component becomes visible. */
    -  BEFORE_SHOW: 'beforeshow',
    -
    -  /**
    -   * Dispatched after the component becomes visible.
    -   * NOTE(user): For goog.ui.Container, this actually fires before containers
    -   * are shown.  Use goog.ui.Container.EventType.AFTER_SHOW if you want an event
    -   * that fires after a goog.ui.Container is shown.
    -   */
    -  SHOW: 'show',
    -
    -  /** Dispatched before the component becomes hidden. */
    -  HIDE: 'hide',
    -
    -  /** Dispatched before the component becomes disabled. */
    -  DISABLE: 'disable',
    -
    -  /** Dispatched before the component becomes enabled. */
    -  ENABLE: 'enable',
    -
    -  /** Dispatched before the component becomes highlighted. */
    -  HIGHLIGHT: 'highlight',
    -
    -  /** Dispatched before the component becomes un-highlighted. */
    -  UNHIGHLIGHT: 'unhighlight',
    -
    -  /** Dispatched before the component becomes activated. */
    -  ACTIVATE: 'activate',
    -
    -  /** Dispatched before the component becomes deactivated. */
    -  DEACTIVATE: 'deactivate',
    -
    -  /** Dispatched before the component becomes selected. */
    -  SELECT: 'select',
    -
    -  /** Dispatched before the component becomes un-selected. */
    -  UNSELECT: 'unselect',
    -
    -  /** Dispatched before a component becomes checked. */
    -  CHECK: 'check',
    -
    -  /** Dispatched before a component becomes un-checked. */
    -  UNCHECK: 'uncheck',
    -
    -  /** Dispatched before a component becomes focused. */
    -  FOCUS: 'focus',
    -
    -  /** Dispatched before a component becomes blurred. */
    -  BLUR: 'blur',
    -
    -  /** Dispatched before a component is opened (expanded). */
    -  OPEN: 'open',
    -
    -  /** Dispatched before a component is closed (collapsed). */
    -  CLOSE: 'close',
    -
    -  /** Dispatched after a component is moused over. */
    -  ENTER: 'enter',
    -
    -  /** Dispatched after a component is moused out of. */
    -  LEAVE: 'leave',
    -
    -  /** Dispatched after the user activates the component. */
    -  ACTION: 'action',
    -
    -  /** Dispatched after the external-facing state of a component is changed. */
    -  CHANGE: 'change'
    -};
    -
    -
    -/**
    - * Errors thrown by the component.
    - * @enum {string}
    - */
    -goog.ui.Component.Error = {
    -  /**
    -   * Error when a method is not supported.
    -   */
    -  NOT_SUPPORTED: 'Method not supported',
    -
    -  /**
    -   * Error when the given element can not be decorated.
    -   */
    -  DECORATE_INVALID: 'Invalid element to decorate',
    -
    -  /**
    -   * Error when the component is already rendered and another render attempt is
    -   * made.
    -   */
    -  ALREADY_RENDERED: 'Component already rendered',
    -
    -  /**
    -   * Error when an attempt is made to set the parent of a component in a way
    -   * that would result in an inconsistent object graph.
    -   */
    -  PARENT_UNABLE_TO_BE_SET: 'Unable to set parent component',
    -
    -  /**
    -   * Error when an attempt is made to add a child component at an out-of-bounds
    -   * index.  We don't support sparse child arrays.
    -   */
    -  CHILD_INDEX_OUT_OF_BOUNDS: 'Child component index out of bounds',
    -
    -  /**
    -   * Error when an attempt is made to remove a child component from a component
    -   * other than its parent.
    -   */
    -  NOT_OUR_CHILD: 'Child is not in parent component',
    -
    -  /**
    -   * Error when an operation requiring DOM interaction is made when the
    -   * component is not in the document
    -   */
    -  NOT_IN_DOCUMENT: 'Operation not supported while component is not in document',
    -
    -  /**
    -   * Error when an invalid component state is encountered.
    -   */
    -  STATE_INVALID: 'Invalid component state'
    -};
    -
    -
    -/**
    - * Common component states.  Components may have distinct appearance depending
    - * on what state(s) apply to them.  Not all components are expected to support
    - * all states.
    - * @enum {number}
    - */
    -goog.ui.Component.State = {
    -  /**
    -   * Union of all supported component states.
    -   */
    -  ALL: 0xFF,
    -
    -  /**
    -   * Component is disabled.
    -   * @see goog.ui.Component.EventType.DISABLE
    -   * @see goog.ui.Component.EventType.ENABLE
    -   */
    -  DISABLED: 0x01,
    -
    -  /**
    -   * Component is highlighted.
    -   * @see goog.ui.Component.EventType.HIGHLIGHT
    -   * @see goog.ui.Component.EventType.UNHIGHLIGHT
    -   */
    -  HOVER: 0x02,
    -
    -  /**
    -   * Component is active (or "pressed").
    -   * @see goog.ui.Component.EventType.ACTIVATE
    -   * @see goog.ui.Component.EventType.DEACTIVATE
    -   */
    -  ACTIVE: 0x04,
    -
    -  /**
    -   * Component is selected.
    -   * @see goog.ui.Component.EventType.SELECT
    -   * @see goog.ui.Component.EventType.UNSELECT
    -   */
    -  SELECTED: 0x08,
    -
    -  /**
    -   * Component is checked.
    -   * @see goog.ui.Component.EventType.CHECK
    -   * @see goog.ui.Component.EventType.UNCHECK
    -   */
    -  CHECKED: 0x10,
    -
    -  /**
    -   * Component has focus.
    -   * @see goog.ui.Component.EventType.FOCUS
    -   * @see goog.ui.Component.EventType.BLUR
    -   */
    -  FOCUSED: 0x20,
    -
    -  /**
    -   * Component is opened (expanded).  Applies to tree nodes, menu buttons,
    -   * submenus, zippys (zippies?), etc.
    -   * @see goog.ui.Component.EventType.OPEN
    -   * @see goog.ui.Component.EventType.CLOSE
    -   */
    -  OPENED: 0x40
    -};
    -
    -
    -/**
    - * Static helper method; returns the type of event components are expected to
    - * dispatch when transitioning to or from the given state.
    - * @param {goog.ui.Component.State} state State to/from which the component
    - *     is transitioning.
    - * @param {boolean} isEntering Whether the component is entering or leaving the
    - *     state.
    - * @return {goog.ui.Component.EventType} Event type to dispatch.
    - */
    -goog.ui.Component.getStateTransitionEvent = function(state, isEntering) {
    -  switch (state) {
    -    case goog.ui.Component.State.DISABLED:
    -      return isEntering ? goog.ui.Component.EventType.DISABLE :
    -          goog.ui.Component.EventType.ENABLE;
    -    case goog.ui.Component.State.HOVER:
    -      return isEntering ? goog.ui.Component.EventType.HIGHLIGHT :
    -          goog.ui.Component.EventType.UNHIGHLIGHT;
    -    case goog.ui.Component.State.ACTIVE:
    -      return isEntering ? goog.ui.Component.EventType.ACTIVATE :
    -          goog.ui.Component.EventType.DEACTIVATE;
    -    case goog.ui.Component.State.SELECTED:
    -      return isEntering ? goog.ui.Component.EventType.SELECT :
    -          goog.ui.Component.EventType.UNSELECT;
    -    case goog.ui.Component.State.CHECKED:
    -      return isEntering ? goog.ui.Component.EventType.CHECK :
    -          goog.ui.Component.EventType.UNCHECK;
    -    case goog.ui.Component.State.FOCUSED:
    -      return isEntering ? goog.ui.Component.EventType.FOCUS :
    -          goog.ui.Component.EventType.BLUR;
    -    case goog.ui.Component.State.OPENED:
    -      return isEntering ? goog.ui.Component.EventType.OPEN :
    -          goog.ui.Component.EventType.CLOSE;
    -    default:
    -      // Fall through.
    -  }
    -
    -  // Invalid state.
    -  throw Error(goog.ui.Component.Error.STATE_INVALID);
    -};
    -
    -
    -/**
    - * Set the default right-to-left value. This causes all component's created from
    - * this point foward to have the given value. This is useful for cases where
    - * a given page is always in one directionality, avoiding unnecessary
    - * right to left determinations.
    - * @param {?boolean} rightToLeft Whether the components should be rendered
    - *     right-to-left. Null iff components should determine their directionality.
    - */
    -goog.ui.Component.setDefaultRightToLeft = function(rightToLeft) {
    -  goog.ui.Component.defaultRightToLeft_ = rightToLeft;
    -};
    -
    -
    -/**
    - * Gets the unique ID for the instance of this component.  If the instance
    - * doesn't already have an ID, generates one on the fly.
    - * @return {string} Unique component ID.
    - */
    -goog.ui.Component.prototype.getId = function() {
    -  return this.id_ || (this.id_ = this.idGenerator_.getNextUniqueId());
    -};
    -
    -
    -/**
    - * Assigns an ID to this component instance.  It is the caller's responsibility
    - * to guarantee that the ID is unique.  If the component is a child of a parent
    - * component, then the parent component's child index is updated to reflect the
    - * new ID; this may throw an error if the parent already has a child with an ID
    - * that conflicts with the new ID.
    - * @param {string} id Unique component ID.
    - */
    -goog.ui.Component.prototype.setId = function(id) {
    -  if (this.parent_ && this.parent_.childIndex_) {
    -    // Update the parent's child index.
    -    goog.object.remove(this.parent_.childIndex_, this.id_);
    -    goog.object.add(this.parent_.childIndex_, id, this);
    -  }
    -
    -  // Update the component ID.
    -  this.id_ = id;
    -};
    -
    -
    -/**
    - * Gets the component's element.
    - * @return {Element} The element for the component.
    - */
    -goog.ui.Component.prototype.getElement = function() {
    -  return this.element_;
    -};
    -
    -
    -/**
    - * Gets the component's element. This differs from getElement in that
    - * it assumes that the element exists (i.e. the component has been
    - * rendered/decorated) and will cause an assertion error otherwise (if
    - * assertion is enabled).
    - * @return {!Element} The element for the component.
    - */
    -goog.ui.Component.prototype.getElementStrict = function() {
    -  var el = this.element_;
    -  goog.asserts.assert(
    -      el, 'Can not call getElementStrict before rendering/decorating.');
    -  return el;
    -};
    -
    -
    -/**
    - * Sets the component's root element to the given element.  Considered
    - * protected and final.
    - *
    - * This should generally only be called during createDom. Setting the element
    - * does not actually change which element is rendered, only the element that is
    - * associated with this UI component.
    - *
    - * This should only be used by subclasses and its associated renderers.
    - *
    - * @param {Element} element Root element for the component.
    - */
    -goog.ui.Component.prototype.setElementInternal = function(element) {
    -  this.element_ = element;
    -};
    -
    -
    -/**
    - * Returns an array of all the elements in this component's DOM with the
    - * provided className.
    - * @param {string} className The name of the class to look for.
    - * @return {!goog.array.ArrayLike} The items found with the class name provided.
    - */
    -goog.ui.Component.prototype.getElementsByClass = function(className) {
    -  return this.element_ ?
    -      this.dom_.getElementsByClass(className, this.element_) : [];
    -};
    -
    -
    -/**
    - * Returns the first element in this component's DOM with the provided
    - * className.
    - * @param {string} className The name of the class to look for.
    - * @return {Element} The first item with the class name provided.
    - */
    -goog.ui.Component.prototype.getElementByClass = function(className) {
    -  return this.element_ ?
    -      this.dom_.getElementByClass(className, this.element_) : null;
    -};
    -
    -
    -/**
    - * Similar to {@code getElementByClass} except that it expects the
    - * element to be present in the dom thus returning a required value. Otherwise,
    - * will assert.
    - * @param {string} className The name of the class to look for.
    - * @return {!Element} The first item with the class name provided.
    - */
    -goog.ui.Component.prototype.getRequiredElementByClass = function(className) {
    -  var el = this.getElementByClass(className);
    -  goog.asserts.assert(el, 'Expected element in component with class: %s',
    -      className);
    -  return el;
    -};
    -
    -
    -/**
    - * Returns the event handler for this component, lazily created the first time
    - * this method is called.
    - * @return {!goog.events.EventHandler<T>} Event handler for this component.
    - * @protected
    - * @this T
    - * @template T
    - */
    -goog.ui.Component.prototype.getHandler = function() {
    -  // TODO(user): templated "this" values currently result in "this" being
    -  // "unknown" in the body of the function.
    -  var self = /** @type {goog.ui.Component} */ (this);
    -  if (!self.googUiComponentHandler_) {
    -    self.googUiComponentHandler_ = new goog.events.EventHandler(self);
    -  }
    -  return self.googUiComponentHandler_;
    -};
    -
    -
    -/**
    - * Sets the parent of this component to use for event bubbling.  Throws an error
    - * if the component already has a parent or if an attempt is made to add a
    - * component to itself as a child.  Callers must use {@code removeChild}
    - * or {@code removeChildAt} to remove components from their containers before
    - * calling this method.
    - * @see goog.ui.Component#removeChild
    - * @see goog.ui.Component#removeChildAt
    - * @param {goog.ui.Component} parent The parent component.
    - */
    -goog.ui.Component.prototype.setParent = function(parent) {
    -  if (this == parent) {
    -    // Attempting to add a child to itself is an error.
    -    throw Error(goog.ui.Component.Error.PARENT_UNABLE_TO_BE_SET);
    -  }
    -
    -  if (parent && this.parent_ && this.id_ && this.parent_.getChild(this.id_) &&
    -      this.parent_ != parent) {
    -    // This component is already the child of some parent, so it should be
    -    // removed using removeChild/removeChildAt first.
    -    throw Error(goog.ui.Component.Error.PARENT_UNABLE_TO_BE_SET);
    -  }
    -
    -  this.parent_ = parent;
    -  goog.ui.Component.superClass_.setParentEventTarget.call(this, parent);
    -};
    -
    -
    -/**
    - * Returns the component's parent, if any.
    - * @return {goog.ui.Component?} The parent component.
    - */
    -goog.ui.Component.prototype.getParent = function() {
    -  return this.parent_;
    -};
    -
    -
    -/**
    - * Overrides {@link goog.events.EventTarget#setParentEventTarget} to throw an
    - * error if the parent component is set, and the argument is not the parent.
    - * @override
    - */
    -goog.ui.Component.prototype.setParentEventTarget = function(parent) {
    -  if (this.parent_ && this.parent_ != parent) {
    -    throw Error(goog.ui.Component.Error.NOT_SUPPORTED);
    -  }
    -  goog.ui.Component.superClass_.setParentEventTarget.call(this, parent);
    -};
    -
    -
    -/**
    - * Returns the dom helper that is being used on this component.
    - * @return {!goog.dom.DomHelper} The dom helper used on this component.
    - */
    -goog.ui.Component.prototype.getDomHelper = function() {
    -  return this.dom_;
    -};
    -
    -
    -/**
    - * Determines whether the component has been added to the document.
    - * @return {boolean} TRUE if rendered. Otherwise, FALSE.
    - */
    -goog.ui.Component.prototype.isInDocument = function() {
    -  return this.inDocument_;
    -};
    -
    -
    -/**
    - * Creates the initial DOM representation for the component.  The default
    - * implementation is to set this.element_ = div.
    - */
    -goog.ui.Component.prototype.createDom = function() {
    -  this.element_ = this.dom_.createElement('div');
    -};
    -
    -
    -/**
    - * Renders the component.  If a parent element is supplied, the component's
    - * element will be appended to it.  If there is no optional parent element and
    - * the element doesn't have a parentNode then it will be appended to the
    - * document body.
    - *
    - * If this component has a parent component, and the parent component is
    - * not in the document already, then this will not call {@code enterDocument}
    - * on this component.
    - *
    - * Throws an Error if the component is already rendered.
    - *
    - * @param {Element=} opt_parentElement Optional parent element to render the
    - *    component into.
    - */
    -goog.ui.Component.prototype.render = function(opt_parentElement) {
    -  this.render_(opt_parentElement);
    -};
    -
    -
    -/**
    - * Renders the component before another element. The other element should be in
    - * the document already.
    - *
    - * Throws an Error if the component is already rendered.
    - *
    - * @param {Node} sibling Node to render the component before.
    - */
    -goog.ui.Component.prototype.renderBefore = function(sibling) {
    -  this.render_(/** @type {Element} */ (sibling.parentNode),
    -               sibling);
    -};
    -
    -
    -/**
    - * Renders the component.  If a parent element is supplied, the component's
    - * element will be appended to it.  If there is no optional parent element and
    - * the element doesn't have a parentNode then it will be appended to the
    - * document body.
    - *
    - * If this component has a parent component, and the parent component is
    - * not in the document already, then this will not call {@code enterDocument}
    - * on this component.
    - *
    - * Throws an Error if the component is already rendered.
    - *
    - * @param {Element=} opt_parentElement Optional parent element to render the
    - *    component into.
    - * @param {Node=} opt_beforeNode Node before which the component is to
    - *    be rendered.  If left out the node is appended to the parent element.
    - * @private
    - */
    -goog.ui.Component.prototype.render_ = function(opt_parentElement,
    -                                               opt_beforeNode) {
    -  if (this.inDocument_) {
    -    throw Error(goog.ui.Component.Error.ALREADY_RENDERED);
    -  }
    -
    -  if (!this.element_) {
    -    this.createDom();
    -  }
    -
    -  if (opt_parentElement) {
    -    opt_parentElement.insertBefore(this.element_, opt_beforeNode || null);
    -  } else {
    -    this.dom_.getDocument().body.appendChild(this.element_);
    -  }
    -
    -  // If this component has a parent component that isn't in the document yet,
    -  // we don't call enterDocument() here.  Instead, when the parent component
    -  // enters the document, the enterDocument() call will propagate to its
    -  // children, including this one.  If the component doesn't have a parent
    -  // or if the parent is already in the document, we call enterDocument().
    -  if (!this.parent_ || this.parent_.isInDocument()) {
    -    this.enterDocument();
    -  }
    -};
    -
    -
    -/**
    - * Decorates the element for the UI component. If the element is in the
    - * document, the enterDocument method will be called.
    - *
    - * If goog.ui.Component.ALLOW_DETACHED_DECORATION is false, the caller must
    - * pass an element that is in the document.
    - *
    - * @param {Element} element Element to decorate.
    - */
    -goog.ui.Component.prototype.decorate = function(element) {
    -  if (this.inDocument_) {
    -    throw Error(goog.ui.Component.Error.ALREADY_RENDERED);
    -  } else if (element && this.canDecorate(element)) {
    -    this.wasDecorated_ = true;
    -
    -    // Set the DOM helper of the component to match the decorated element.
    -    var doc = goog.dom.getOwnerDocument(element);
    -    if (!this.dom_ || this.dom_.getDocument() != doc) {
    -      this.dom_ = goog.dom.getDomHelper(element);
    -    }
    -
    -    // Call specific component decorate logic.
    -    this.decorateInternal(element);
    -
    -    // If supporting detached decoration, check that element is in doc.
    -    if (!goog.ui.Component.ALLOW_DETACHED_DECORATION ||
    -        goog.dom.contains(doc, element)) {
    -      this.enterDocument();
    -    }
    -  } else {
    -    throw Error(goog.ui.Component.Error.DECORATE_INVALID);
    -  }
    -};
    -
    -
    -/**
    - * Determines if a given element can be decorated by this type of component.
    - * This method should be overridden by inheriting objects.
    - * @param {Element} element Element to decorate.
    - * @return {boolean} True if the element can be decorated, false otherwise.
    - */
    -goog.ui.Component.prototype.canDecorate = function(element) {
    -  return true;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the component was decorated.
    - */
    -goog.ui.Component.prototype.wasDecorated = function() {
    -  return this.wasDecorated_;
    -};
    -
    -
    -/**
    - * Actually decorates the element. Should be overridden by inheriting objects.
    - * This method can assume there are checks to ensure the component has not
    - * already been rendered have occurred and that enter document will be called
    - * afterwards. This method is considered protected.
    - * @param {Element} element Element to decorate.
    - * @protected
    - */
    -goog.ui.Component.prototype.decorateInternal = function(element) {
    -  this.element_ = element;
    -};
    -
    -
    -/**
    - * Called when the component's element is known to be in the document. Anything
    - * using document.getElementById etc. should be done at this stage.
    - *
    - * If the component contains child components, this call is propagated to its
    - * children.
    - */
    -goog.ui.Component.prototype.enterDocument = function() {
    -  this.inDocument_ = true;
    -
    -  // Propagate enterDocument to child components that have a DOM, if any.
    -  // If a child was decorated before entering the document (permitted when
    -  // goog.ui.Component.ALLOW_DETACHED_DECORATION is true), its enterDocument
    -  // will be called here.
    -  this.forEachChild(function(child) {
    -    if (!child.isInDocument() && child.getElement()) {
    -      child.enterDocument();
    -    }
    -  });
    -};
    -
    -
    -/**
    - * Called by dispose to clean up the elements and listeners created by a
    - * component, or by a parent component/application who has removed the
    - * component from the document but wants to reuse it later.
    - *
    - * If the component contains child components, this call is propagated to its
    - * children.
    - *
    - * It should be possible for the component to be rendered again once this method
    - * has been called.
    - */
    -goog.ui.Component.prototype.exitDocument = function() {
    -  // Propagate exitDocument to child components that have been rendered, if any.
    -  this.forEachChild(function(child) {
    -    if (child.isInDocument()) {
    -      child.exitDocument();
    -    }
    -  });
    -
    -  if (this.googUiComponentHandler_) {
    -    this.googUiComponentHandler_.removeAll();
    -  }
    -
    -  this.inDocument_ = false;
    -};
    -
    -
    -/**
    - * Disposes of the component.  Calls {@code exitDocument}, which is expected to
    - * remove event handlers and clean up the component.  Propagates the call to
    - * the component's children, if any. Removes the component's DOM from the
    - * document unless it was decorated.
    - * @override
    - * @protected
    - */
    -goog.ui.Component.prototype.disposeInternal = function() {
    -  if (this.inDocument_) {
    -    this.exitDocument();
    -  }
    -
    -  if (this.googUiComponentHandler_) {
    -    this.googUiComponentHandler_.dispose();
    -    delete this.googUiComponentHandler_;
    -  }
    -
    -  // Disposes of the component's children, if any.
    -  this.forEachChild(function(child) {
    -    child.dispose();
    -  });
    -
    -  // Detach the component's element from the DOM, unless it was decorated.
    -  if (!this.wasDecorated_ && this.element_) {
    -    goog.dom.removeNode(this.element_);
    -  }
    -
    -  this.children_ = null;
    -  this.childIndex_ = null;
    -  this.element_ = null;
    -  this.model_ = null;
    -  this.parent_ = null;
    -
    -  goog.ui.Component.superClass_.disposeInternal.call(this);
    -};
    -
    -
    -/**
    - * Helper function for subclasses that gets a unique id for a given fragment,
    - * this can be used by components to generate unique string ids for DOM
    - * elements.
    - * @param {string} idFragment A partial id.
    - * @return {string} Unique element id.
    - */
    -goog.ui.Component.prototype.makeId = function(idFragment) {
    -  return this.getId() + '.' + idFragment;
    -};
    -
    -
    -/**
    - * Makes a collection of ids.  This is a convenience method for makeId.  The
    - * object's values are the id fragments and the new values are the generated
    - * ids.  The key will remain the same.
    - * @param {Object} object The object that will be used to create the ids.
    - * @return {!Object} An object of id keys to generated ids.
    - */
    -goog.ui.Component.prototype.makeIds = function(object) {
    -  var ids = {};
    -  for (var key in object) {
    -    ids[key] = this.makeId(object[key]);
    -  }
    -  return ids;
    -};
    -
    -
    -/**
    - * Returns the model associated with the UI component.
    - * @return {*} The model.
    - */
    -goog.ui.Component.prototype.getModel = function() {
    -  return this.model_;
    -};
    -
    -
    -/**
    - * Sets the model associated with the UI component.
    - * @param {*} obj The model.
    - */
    -goog.ui.Component.prototype.setModel = function(obj) {
    -  this.model_ = obj;
    -};
    -
    -
    -/**
    - * Helper function for returning the fragment portion of an id generated using
    - * makeId().
    - * @param {string} id Id generated with makeId().
    - * @return {string} Fragment.
    - */
    -goog.ui.Component.prototype.getFragmentFromId = function(id) {
    -  return id.substring(this.getId().length + 1);
    -};
    -
    -
    -/**
    - * Helper function for returning an element in the document with a unique id
    - * generated using makeId().
    - * @param {string} idFragment The partial id.
    - * @return {Element} The element with the unique id, or null if it cannot be
    - *     found.
    - */
    -goog.ui.Component.prototype.getElementByFragment = function(idFragment) {
    -  if (!this.inDocument_) {
    -    throw Error(goog.ui.Component.Error.NOT_IN_DOCUMENT);
    -  }
    -  return this.dom_.getElement(this.makeId(idFragment));
    -};
    -
    -
    -/**
    - * Adds the specified component as the last child of this component.  See
    - * {@link goog.ui.Component#addChildAt} for detailed semantics.
    - *
    - * @see goog.ui.Component#addChildAt
    - * @param {goog.ui.Component} child The new child component.
    - * @param {boolean=} opt_render If true, the child component will be rendered
    - *    into the parent.
    - */
    -goog.ui.Component.prototype.addChild = function(child, opt_render) {
    -  // TODO(gboyer): addChildAt(child, this.getChildCount(), false) will
    -  // reposition any already-rendered child to the end.  Instead, perhaps
    -  // addChild(child, false) should never reposition the child; instead, clients
    -  // that need the repositioning will use addChildAt explicitly.  Right now,
    -  // clients can get around this by calling addChild before calling decorate.
    -  this.addChildAt(child, this.getChildCount(), opt_render);
    -};
    -
    -
    -/**
    - * Adds the specified component as a child of this component at the given
    - * 0-based index.
    - *
    - * Both {@code addChild} and {@code addChildAt} assume the following contract
    - * between parent and child components:
    - *  <ul>
    - *    <li>the child component's element must be a descendant of the parent
    - *        component's element, and
    - *    <li>the DOM state of the child component must be consistent with the DOM
    - *        state of the parent component (see {@code isInDocument}) in the
    - *        steady state -- the exception is to addChildAt(child, i, false) and
    - *        then immediately decorate/render the child.
    - *  </ul>
    - *
    - * In particular, {@code parent.addChild(child)} will throw an error if the
    - * child component is already in the document, but the parent isn't.
    - *
    - * Clients of this API may call {@code addChild} and {@code addChildAt} with
    - * {@code opt_render} set to true.  If {@code opt_render} is true, calling these
    - * methods will automatically render the child component's element into the
    - * parent component's element. If the parent does not yet have an element, then
    - * {@code createDom} will automatically be invoked on the parent before
    - * rendering the child.
    - *
    - * Invoking {@code parent.addChild(child, true)} will throw an error if the
    - * child component is already in the document, regardless of the parent's DOM
    - * state.
    - *
    - * If {@code opt_render} is true and the parent component is not already
    - * in the document, {@code enterDocument} will not be called on this component
    - * at this point.
    - *
    - * Finally, this method also throws an error if the new child already has a
    - * different parent, or the given index is out of bounds.
    - *
    - * @see goog.ui.Component#addChild
    - * @param {goog.ui.Component} child The new child component.
    - * @param {number} index 0-based index at which the new child component is to be
    - *    added; must be between 0 and the current child count (inclusive).
    - * @param {boolean=} opt_render If true, the child component will be rendered
    - *    into the parent.
    - * @return {void} Nada.
    - */
    -goog.ui.Component.prototype.addChildAt = function(child, index, opt_render) {
    -  goog.asserts.assert(!!child, 'Provided element must not be null.');
    -
    -  if (child.inDocument_ && (opt_render || !this.inDocument_)) {
    -    // Adding a child that's already in the document is an error, except if the
    -    // parent is also in the document and opt_render is false (e.g. decorate()).
    -    throw Error(goog.ui.Component.Error.ALREADY_RENDERED);
    -  }
    -
    -  if (index < 0 || index > this.getChildCount()) {
    -    // Allowing sparse child arrays would lead to strange behavior, so we don't.
    -    throw Error(goog.ui.Component.Error.CHILD_INDEX_OUT_OF_BOUNDS);
    -  }
    -
    -  // Create the index and the child array on first use.
    -  if (!this.childIndex_ || !this.children_) {
    -    this.childIndex_ = {};
    -    this.children_ = [];
    -  }
    -
    -  // Moving child within component, remove old reference.
    -  if (child.getParent() == this) {
    -    goog.object.set(this.childIndex_, child.getId(), child);
    -    goog.array.remove(this.children_, child);
    -
    -  // Add the child to this component.  goog.object.add() throws an error if
    -  // a child with the same ID already exists.
    -  } else {
    -    goog.object.add(this.childIndex_, child.getId(), child);
    -  }
    -
    -  // Set the parent of the child to this component.  This throws an error if
    -  // the child is already contained by another component.
    -  child.setParent(this);
    -  goog.array.insertAt(this.children_, child, index);
    -
    -  if (child.inDocument_ && this.inDocument_ && child.getParent() == this) {
    -    // Changing the position of an existing child, move the DOM node (if
    -    // necessary).
    -    var contentElement = this.getContentElement();
    -    var insertBeforeElement = contentElement.childNodes[index] || null;
    -    if (insertBeforeElement != child.getElement()) {
    -      contentElement.insertBefore(child.getElement(), insertBeforeElement);
    -    }
    -  } else if (opt_render) {
    -    // If this (parent) component doesn't have a DOM yet, call createDom now
    -    // to make sure we render the child component's element into the correct
    -    // parent element (otherwise render_ with a null first argument would
    -    // render the child into the document body, which is almost certainly not
    -    // what we want).
    -    if (!this.element_) {
    -      this.createDom();
    -    }
    -    // Render the child into the parent at the appropriate location.  Note that
    -    // getChildAt(index + 1) returns undefined if inserting at the end.
    -    // TODO(attila): We should have a renderer with a renderChildAt API.
    -    var sibling = this.getChildAt(index + 1);
    -    // render_() calls enterDocument() if the parent is already in the document.
    -    child.render_(this.getContentElement(), sibling ? sibling.element_ : null);
    -  } else if (this.inDocument_ && !child.inDocument_ && child.element_ &&
    -      child.element_.parentNode &&
    -      // Under some circumstances, IE8 implicitly creates a Document Fragment
    -      // for detached nodes, so ensure the parent is an Element as it should be.
    -      child.element_.parentNode.nodeType == goog.dom.NodeType.ELEMENT) {
    -    // We don't touch the DOM, but if the parent is in the document, and the
    -    // child element is in the document but not marked as such, then we call
    -    // enterDocument on the child.
    -    // TODO(gboyer): It would be nice to move this condition entirely, but
    -    // there's a large risk of breaking existing applications that manually
    -    // append the child to the DOM and then call addChild.
    -    child.enterDocument();
    -  }
    -};
    -
    -
    -/**
    - * Returns the DOM element into which child components are to be rendered,
    - * or null if the component itself hasn't been rendered yet.  This default
    - * implementation returns the component's root element.  Subclasses with
    - * complex DOM structures must override this method.
    - * @return {Element} Element to contain child elements (null if none).
    - */
    -goog.ui.Component.prototype.getContentElement = function() {
    -  return this.element_;
    -};
    -
    -
    -/**
    - * Returns true if the component is rendered right-to-left, false otherwise.
    - * The first time this function is invoked, the right-to-left rendering property
    - * is set if it has not been already.
    - * @return {boolean} Whether the control is rendered right-to-left.
    - */
    -goog.ui.Component.prototype.isRightToLeft = function() {
    -  if (this.rightToLeft_ == null) {
    -    this.rightToLeft_ = goog.style.isRightToLeft(this.inDocument_ ?
    -        this.element_ : this.dom_.getDocument().body);
    -  }
    -  return /** @type {boolean} */(this.rightToLeft_);
    -};
    -
    -
    -/**
    - * Set is right-to-left. This function should be used if the component needs
    - * to know the rendering direction during dom creation (i.e. before
    - * {@link #enterDocument} is called and is right-to-left is set).
    - * @param {boolean} rightToLeft Whether the component is rendered
    - *     right-to-left.
    - */
    -goog.ui.Component.prototype.setRightToLeft = function(rightToLeft) {
    -  if (this.inDocument_) {
    -    throw Error(goog.ui.Component.Error.ALREADY_RENDERED);
    -  }
    -  this.rightToLeft_ = rightToLeft;
    -};
    -
    -
    -/**
    - * Returns true if the component has children.
    - * @return {boolean} True if the component has children.
    - */
    -goog.ui.Component.prototype.hasChildren = function() {
    -  return !!this.children_ && this.children_.length != 0;
    -};
    -
    -
    -/**
    - * Returns the number of children of this component.
    - * @return {number} The number of children.
    - */
    -goog.ui.Component.prototype.getChildCount = function() {
    -  return this.children_ ? this.children_.length : 0;
    -};
    -
    -
    -/**
    - * Returns an array containing the IDs of the children of this component, or an
    - * empty array if the component has no children.
    - * @return {!Array<string>} Child component IDs.
    - */
    -goog.ui.Component.prototype.getChildIds = function() {
    -  var ids = [];
    -
    -  // We don't use goog.object.getKeys(this.childIndex_) because we want to
    -  // return the IDs in the correct order as determined by this.children_.
    -  this.forEachChild(function(child) {
    -    // addChild()/addChildAt() guarantee that the child array isn't sparse.
    -    ids.push(child.getId());
    -  });
    -
    -  return ids;
    -};
    -
    -
    -/**
    - * Returns the child with the given ID, or null if no such child exists.
    - * @param {string} id Child component ID.
    - * @return {goog.ui.Component?} The child with the given ID; null if none.
    - */
    -goog.ui.Component.prototype.getChild = function(id) {
    -  // Use childIndex_ for O(1) access by ID.
    -  return (this.childIndex_ && id) ? /** @type {goog.ui.Component} */ (
    -      goog.object.get(this.childIndex_, id)) || null : null;
    -};
    -
    -
    -/**
    - * Returns the child at the given index, or null if the index is out of bounds.
    - * @param {number} index 0-based index.
    - * @return {goog.ui.Component?} The child at the given index; null if none.
    - */
    -goog.ui.Component.prototype.getChildAt = function(index) {
    -  // Use children_ for access by index.
    -  return this.children_ ? this.children_[index] || null : null;
    -};
    -
    -
    -/**
    - * Calls the given function on each of this component's children in order.  If
    - * {@code opt_obj} is provided, it will be used as the 'this' object in the
    - * function when called.  The function should take two arguments:  the child
    - * component and its 0-based index.  The return value is ignored.
    - * @param {function(this:T,?,number):?} f The function to call for every
    - * child component; should take 2 arguments (the child and its index).
    - * @param {T=} opt_obj Used as the 'this' object in f when called.
    - * @template T
    - */
    -goog.ui.Component.prototype.forEachChild = function(f, opt_obj) {
    -  if (this.children_) {
    -    goog.array.forEach(this.children_, f, opt_obj);
    -  }
    -};
    -
    -
    -/**
    - * Returns the 0-based index of the given child component, or -1 if no such
    - * child is found.
    - * @param {goog.ui.Component?} child The child component.
    - * @return {number} 0-based index of the child component; -1 if not found.
    - */
    -goog.ui.Component.prototype.indexOfChild = function(child) {
    -  return (this.children_ && child) ? goog.array.indexOf(this.children_, child) :
    -      -1;
    -};
    -
    -
    -/**
    - * Removes the given child from this component, and returns it.  Throws an error
    - * if the argument is invalid or if the specified child isn't found in the
    - * parent component.  The argument can either be a string (interpreted as the
    - * ID of the child component to remove) or the child component itself.
    - *
    - * If {@code opt_unrender} is true, calls {@link goog.ui.component#exitDocument}
    - * on the removed child, and subsequently detaches the child's DOM from the
    - * document.  Otherwise it is the caller's responsibility to clean up the child
    - * component's DOM.
    - *
    - * @see goog.ui.Component#removeChildAt
    - * @param {string|goog.ui.Component|null} child The ID of the child to remove,
    - *    or the child component itself.
    - * @param {boolean=} opt_unrender If true, calls {@code exitDocument} on the
    - *    removed child component, and detaches its DOM from the document.
    - * @return {goog.ui.Component} The removed component, if any.
    - */
    -goog.ui.Component.prototype.removeChild = function(child, opt_unrender) {
    -  if (child) {
    -    // Normalize child to be the object and id to be the ID string.  This also
    -    // ensures that the child is really ours.
    -    var id = goog.isString(child) ? child : child.getId();
    -    child = this.getChild(id);
    -
    -    if (id && child) {
    -      goog.object.remove(this.childIndex_, id);
    -      goog.array.remove(this.children_, child);
    -
    -      if (opt_unrender) {
    -        // Remove the child component's DOM from the document.  We have to call
    -        // exitDocument first (see documentation).
    -        child.exitDocument();
    -        if (child.element_) {
    -          goog.dom.removeNode(child.element_);
    -        }
    -      }
    -
    -      // Child's parent must be set to null after exitDocument is called
    -      // so that the child can unlisten to its parent if required.
    -      child.setParent(null);
    -    }
    -  }
    -
    -  if (!child) {
    -    throw Error(goog.ui.Component.Error.NOT_OUR_CHILD);
    -  }
    -
    -  return /** @type {!goog.ui.Component} */(child);
    -};
    -
    -
    -/**
    - * Removes the child at the given index from this component, and returns it.
    - * Throws an error if the argument is out of bounds, or if the specified child
    - * isn't found in the parent.  See {@link goog.ui.Component#removeChild} for
    - * detailed semantics.
    - *
    - * @see goog.ui.Component#removeChild
    - * @param {number} index 0-based index of the child to remove.
    - * @param {boolean=} opt_unrender If true, calls {@code exitDocument} on the
    - *    removed child component, and detaches its DOM from the document.
    - * @return {goog.ui.Component} The removed component, if any.
    - */
    -goog.ui.Component.prototype.removeChildAt = function(index, opt_unrender) {
    -  // removeChild(null) will throw error.
    -  return this.removeChild(this.getChildAt(index), opt_unrender);
    -};
    -
    -
    -/**
    - * Removes every child component attached to this one and returns them.
    - *
    - * @see goog.ui.Component#removeChild
    - * @param {boolean=} opt_unrender If true, calls {@link #exitDocument} on the
    - *    removed child components, and detaches their DOM from the document.
    - * @return {!Array<goog.ui.Component>} The removed components if any.
    - */
    -goog.ui.Component.prototype.removeChildren = function(opt_unrender) {
    -  var removedChildren = [];
    -  while (this.hasChildren()) {
    -    removedChildren.push(this.removeChildAt(0, opt_unrender));
    -  }
    -  return removedChildren;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/component_test.html b/src/database/third_party/closure-library/closure/goog/ui/component_test.html
    deleted file mode 100644
    index 3c4923a2c9d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/component_test.html
    +++ /dev/null
    @@ -1,27 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -Author: attila@google.com (Attila Bodis)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.Component
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.ComponentTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="sandbox">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/component_test.js b/src/database/third_party/closure-library/closure/goog/ui/component_test.js
    deleted file mode 100644
    index 405779e642f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/component_test.js
    +++ /dev/null
    @@ -1,892 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.ComponentTest');
    -goog.setTestOnly('goog.ui.ComponentTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.DomHelper');
    -goog.require('goog.dom.NodeType');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.Component');
    -
    -var component;
    -var propertyReplacer = new goog.testing.PropertyReplacer();
    -var sandbox;
    -
    -function setUp() {
    -  sandbox = goog.dom.getElement('sandbox');
    -  component = new goog.ui.Component();
    -}
    -
    -function tearDown() {
    -  component.dispose();
    -  goog.dom.removeChildren(sandbox);
    -  propertyReplacer.reset();
    -}
    -
    -function testConstructor() {
    -  assertTrue('Instance must be non-null and have the expected class',
    -      component instanceof goog.ui.Component);
    -  assertTrue('DOM helper must be non-null and have the expected class',
    -      component.dom_ instanceof goog.dom.DomHelper);
    -
    -  var fakeDom = {};
    -  var otherComponent = new goog.ui.Component(fakeDom);
    -  assertEquals('DOM helper must refer to expected object', fakeDom,
    -      otherComponent.dom_);
    -
    -  otherComponent.dispose();
    -}
    -
    -function testGetId() {
    -  assertNull('Component ID should be initialized to null', component.id_);
    -  var id = component.getId();
    -  assertNotNull('Component ID should be generated on demand', id);
    -  assertEquals('Subsequent calls to getId() must return same value', id,
    -      component.getId());
    -}
    -
    -function testSetId() {
    -  component.setId('myId');
    -  assertEquals('getId() must return explicitly set ID', 'myId',
    -      component.getId());
    -
    -  var child = new goog.ui.Component();
    -  var childId = child.getId();
    -  component.addChild(child);
    -  assertEquals('Parent component must find child by ID', child,
    -      component.getChild(childId));
    -
    -  child.setId('someNewId');
    -  assertEquals('Parent component must find child by new ID', child,
    -      component.getChild('someNewId'));
    -
    -  child.dispose();
    -}
    -
    -function testGetSetElement() {
    -  assertNull('Element must be null by default', component.getElement());
    -  var element = goog.dom.createElement(goog.dom.TagName.DIV);
    -  component.setElementInternal(element);
    -  assertEquals('getElement() must return expected element', element,
    -      component.getElement());
    -}
    -
    -function testGetSetParent() {
    -  assertNull('Parent must be null by default', component.getParent());
    -
    -  var parent = new goog.ui.Component();
    -  component.setParent(parent);
    -  assertEquals('getParent() must return expected component', parent,
    -      component.getParent());
    -
    -  component.setParent(null);
    -  assertNull('Parent must be null', component.getParent());
    -
    -  assertThrows('Setting a component\'s parent to itself must throw error',
    -      function() {
    -        component.setParent(component);
    -      });
    -
    -  parent.addChild(component);
    -  assertEquals('getParent() must return expected component', parent,
    -      component.getParent());
    -  assertThrows('Changing a child component\'s parent must throw error',
    -      function() {
    -        component.setParent(new goog.ui.Component());
    -      });
    -
    -  parent.dispose();
    -}
    -
    -function testGetParentEventTarget() {
    -  assertNull('Parent event target must be null by default',
    -      component.getParentEventTarget());
    -
    -  var parent = new goog.ui.Component();
    -  component.setParent(parent);
    -  assertEquals('Parent event target must be the parent component', parent,
    -      component.getParentEventTarget());
    -  assertThrows('Directly setting the parent event target to other than ' +
    -      'the parent component when the parent component is set must throw ' +
    -      'error',
    -      function() {
    -        component.setParentEventTarget(new goog.ui.Component());
    -      });
    -
    -  parent.dispose();
    -}
    -
    -function testSetParentEventTarget() {
    -  var parentEventTarget = new goog.events.EventTarget();
    -  component.setParentEventTarget(parentEventTarget);
    -  assertEquals('Parent component must be null', null,
    -      component.getParent());
    -
    -  parentEventTarget.dispose();
    -}
    -
    -function testGetDomHelper() {
    -  var domHelper = new goog.dom.DomHelper();
    -  var component = new goog.ui.Component(domHelper);
    -  assertEquals('Component must return the same DomHelper passed', domHelper,
    -      component.getDomHelper());
    -}
    -
    -function testIsInDocument() {
    -  assertFalse('Component must not be in the document by default',
    -      component.isInDocument());
    -  component.enterDocument();
    -  assertTrue('Component must be in the document', component.isInDocument());
    -}
    -
    -function testCreateDom() {
    -  assertNull('Component must not have DOM by default',
    -      component.getElement());
    -  component.createDom();
    -  assertEquals('Component\'s DOM must be an element node',
    -      goog.dom.NodeType.ELEMENT, component.getElement().nodeType);
    -}
    -
    -function testRender() {
    -  assertFalse('Component must not be in the document by default',
    -      component.isInDocument());
    -  assertNull('Component must not have DOM by default',
    -      component.getElement());
    -  assertFalse('wasDecorated() must be false before component is rendered',
    -      component.wasDecorated());
    -
    -  component.render(sandbox);
    -  assertTrue('Rendered component must be in the document',
    -      component.isInDocument());
    -  assertEquals('Component\'s element must be a child of the parent element',
    -      sandbox, component.getElement().parentNode);
    -  assertFalse('wasDecorated() must still be false for rendered component',
    -      component.wasDecorated());
    -
    -  assertThrows('Trying to re-render component must throw error',
    -      function() {
    -        component.render();
    -      });
    -}
    -
    -function testRender_NoParent() {
    -  component.render();
    -  assertTrue('Rendered component must be in the document',
    -      component.isInDocument());
    -  assertEquals('Component\'s element must be a child of the document body',
    -      document.body, component.getElement().parentNode);
    -}
    -
    -function testRender_ParentNotInDocument() {
    -  var parent = new goog.ui.Component();
    -  component.setParent(parent);
    -
    -  assertFalse('Parent component must not be in the document',
    -      parent.isInDocument());
    -  assertFalse('Child component must not be in the document',
    -      component.isInDocument());
    -  assertNull('Child component must not have DOM', component.getElement());
    -
    -  component.render();
    -  assertFalse('Parent component must not be in the document',
    -      parent.isInDocument());
    -  assertFalse('Child component must not be in the document',
    -      component.isInDocument());
    -  assertNotNull('Child component must have DOM', component.getElement());
    -
    -  parent.dispose();
    -}
    -
    -
    -function testRenderBefore() {
    -  var sibling = goog.dom.createElement(goog.dom.TagName.DIV);
    -  sandbox.appendChild(sibling);
    -
    -  component.renderBefore(sibling);
    -  assertTrue('Rendered component must be in the document',
    -      component.isInDocument());
    -  assertEquals('Component\'s element must be a child of the parent element',
    -      sandbox, component.getElement().parentNode);
    -  assertEquals('Component\'s element must have expected nextSibling',
    -      sibling, component.getElement().nextSibling);
    -}
    -
    -
    -function testRenderChild() {
    -  var parent = new goog.ui.Component();
    -
    -  parent.createDom();
    -  assertFalse('Parent must not be in the document', parent.isInDocument());
    -  assertNotNull('Parent must have a DOM', parent.getElement());
    -
    -  parent.addChild(component);
    -  assertFalse('Child must not be in the document',
    -      component.isInDocument());
    -  assertNull('Child must not have a DOM', component.getElement());
    -
    -  component.render(parent.getElement());
    -  assertFalse('Parent must not be in the document', parent.isInDocument());
    -  assertFalse('Child must not be in the document if the parent isn\'t',
    -      component.isInDocument());
    -  assertNotNull('Child must have a DOM', component.getElement());
    -  assertEquals('Child\'s element must be a child of the parent\'s element',
    -      parent.getElement(), component.getElement().parentNode);
    -
    -  parent.render(sandbox);
    -  assertTrue('Parent must be in the document', parent.isInDocument());
    -  assertTrue('Child must be in the document', component.isInDocument());
    -
    -  parent.dispose();
    -}
    -
    -function testDecorate() {
    -  sandbox.innerHTML = '<div id="foo">Foo</div>';
    -  var foo = goog.dom.getElement('foo');
    -
    -  assertFalse('wasDecorated() must be false by default',
    -      component.wasDecorated());
    -
    -  component.decorate(foo);
    -  assertTrue('Component must be in the document', component.isInDocument());
    -  assertEquals('Component\'s element must be the decorated element', foo,
    -      component.getElement());
    -  assertTrue('wasDecorated() must be true for decorated component',
    -      component.wasDecorated());
    -
    -  assertThrows('Trying to decorate with a control already in the document' +
    -      ' must throw error',
    -      function() {
    -        component.decorate(foo);
    -      });
    -}
    -
    -function testDecorate_AllowDetached_NotInDocument() {
    -  goog.ui.Component.ALLOW_DETACHED_DECORATION = true;
    -  var element = document.createElement('div');
    -  component.decorate(element);
    -  assertFalse('Component should not call enterDocument when decorated ' +
    -      'with an element that is not in the document.',
    -      component.isInDocument());
    -  goog.ui.Component.ALLOW_DETACHED_DECORATION = false;
    -}
    -
    -function testDecorate_AllowDetached_InDocument() {
    -  goog.ui.Component.ALLOW_DETACHED_DECORATION = true;
    -  var element = document.createElement('div');
    -  sandbox.appendChild(element);
    -  component.decorate(element);
    -  assertTrue('Component should call enterDocument when decorated ' +
    -      'with an element that is in the document.',
    -      component.isInDocument());
    -  goog.ui.Component.ALLOW_DETACHED_DECORATION = false;
    -}
    -
    -function testCannotDecorate() {
    -  sandbox.innerHTML = '<div id="foo">Foo</div>';
    -  var foo = goog.dom.getElement('foo');
    -
    -  // Have canDecorate() return false.
    -  propertyReplacer.set(component, 'canDecorate', function() {
    -    return false;
    -  });
    -
    -  assertThrows('Trying to decorate an element for which canDecorate()' +
    -      ' returns false must throw error',
    -      function() {
    -        component.decorate(foo);
    -      });
    -}
    -
    -function testCanDecorate() {
    -  assertTrue('canDecorate() must return true by default',
    -      component.canDecorate(sandbox));
    -}
    -
    -function testWasDecorated() {
    -  assertFalse('wasDecorated() must return false by default',
    -      component.wasDecorated());
    -}
    -
    -function testDecorateInternal() {
    -  assertNull('Element must be null by default', component.getElement());
    -  var element = goog.dom.createElement(goog.dom.TagName.DIV);
    -  component.decorateInternal(element);
    -  assertEquals('Element must have expected value', element,
    -      component.getElement());
    -}
    -
    -function testGetElementAndGetElementsByClass() {
    -  sandbox.innerHTML =
    -      '<ul id="task-list">' +
    -      '<li class="task">Unclog drain' +
    -      '</ul>' +
    -      '<ul id="completed-tasks">' +
    -      '<li id="groceries" class="task">Buy groceries' +
    -      '<li class="task">Rotate tires' +
    -      '<li class="task">Clean kitchen' +
    -      '</ul>' +
    -      assertNull(
    -      'Should be nothing to return before the component has a DOM',
    -      component.getElementByClass('task'));
    -  assertEquals('Should return an empty list before the component has a DOM',
    -               0,
    -               component.getElementsByClass('task').length);
    -
    -  component.decorate(goog.dom.getElement('completed-tasks'));
    -  assertEquals(
    -      'getElementByClass() should return the first completed task',
    -      'groceries',
    -      component.getElementByClass('task').id);
    -  assertEquals(
    -      'getElementsByClass() should return only the completed tasks',
    -      3,
    -      component.getElementsByClass('task').length);
    -}
    -
    -function testGetRequiredElementByClass() {
    -  sandbox.innerHTML =
    -      '<ul id="task-list">' +
    -      '<li class="task">Unclog drain' +
    -      '</ul>' +
    -      '<ul id="completed-tasks">' +
    -      '<li id="groceries" class="task">Buy groceries' +
    -      '<li class="task">Rotate tires' +
    -      '<li class="task">Clean kitchen' +
    -      '</ul>';
    -  component.decorate(goog.dom.getElement('completed-tasks'));
    -  assertEquals(
    -      'getRequiredElementByClass() should return the first completed task',
    -      'groceries',
    -      component.getRequiredElementByClass('task').id);
    -  assertThrows('Attempting to retrieve a required element that does not' +
    -      'exist should fail', function() {
    -        component.getRequiredElementByClass('undefinedClass');
    -      });
    -}
    -
    -function testEnterExitDocument() {
    -  var c1 = new goog.ui.Component();
    -  var c2 = new goog.ui.Component();
    -
    -  component.addChild(c1);
    -  component.addChild(c2);
    -
    -  component.createDom();
    -  c1.createDom();
    -  c2.createDom();
    -
    -  assertFalse('Parent must not be in the document',
    -      component.isInDocument());
    -  assertFalse('Neither child must be in the document',
    -      c1.isInDocument() || c2.isInDocument());
    -
    -  component.enterDocument();
    -  assertTrue('Parent must be in the document', component.isInDocument());
    -  assertTrue('Both children must be in the document',
    -      c1.isInDocument() && c2.isInDocument());
    -
    -  component.exitDocument();
    -  assertFalse('Parent must not be in the document',
    -      component.isInDocument());
    -  assertFalse('Neither child must be in the document',
    -      c1.isInDocument() || c2.isInDocument());
    -
    -  c1.dispose();
    -  c2.dispose();
    -}
    -
    -function testDispose() {
    -  var c1, c2;
    -
    -  component.createDom();
    -  component.addChild((c1 = new goog.ui.Component()), true);
    -  component.addChild((c2 = new goog.ui.Component()), true);
    -
    -  var element = component.getElement();
    -  var c1Element = c1.getElement();
    -  var c2Element = c2.getElement();
    -
    -  component.render(sandbox);
    -  assertTrue('Parent must be in the document', component.isInDocument());
    -  assertEquals('Parent\'s element must be a child of the sandbox element',
    -      sandbox, element.parentNode);
    -  assertTrue('Both children must be in the document',
    -      c1.isInDocument() && c2.isInDocument());
    -  assertEquals('First child\'s element must be a child of the parent\'s' +
    -      ' element', element, c1Element.parentNode);
    -  assertEquals('Second child\'s element must be a child of the parent\'s' +
    -      ' element', element, c2Element.parentNode);
    -
    -  assertFalse('Parent must not have been disposed of',
    -      component.isDisposed());
    -  assertFalse('Neither child must have been disposed of',
    -      c1.isDisposed() || c2.isDisposed());
    -
    -  component.dispose();
    -  assertTrue('Parent must have been disposed of', component.isDisposed());
    -  assertFalse('Parent must not be in the document',
    -      component.isInDocument());
    -  assertNotEquals('Parent\'s element must no longer be a child of the' +
    -      ' sandbox element', sandbox, element.parentNode);
    -  assertTrue('Both children must have been disposed of',
    -      c1.isDisposed() && c2.isDisposed());
    -  assertFalse('Neither child must be in the document',
    -      c1.isInDocument() || c2.isInDocument());
    -  assertNotEquals('First child\'s element must no longer be a child of' +
    -      ' the parent\'s element', element, c1Element.parentNode);
    -  assertNotEquals('Second child\'s element must no longer be a child of' +
    -      ' the parent\'s element', element, c2Element.parentNode);
    -}
    -
    -function testDispose_Decorated() {
    -  sandbox.innerHTML = '<div id="foo">Foo</div>';
    -  var foo = goog.dom.getElement('foo');
    -
    -  component.decorate(foo);
    -  assertTrue('Component must be in the document', component.isInDocument());
    -  assertFalse('Component must not have been disposed of',
    -      component.isDisposed());
    -  assertEquals('Component\'s element must have expected value', foo,
    -      component.getElement());
    -  assertEquals('Decorated element must be a child of the sandbox', sandbox,
    -      foo.parentNode);
    -
    -  component.dispose();
    -  assertFalse('Component must not be in the document',
    -      component.isInDocument());
    -  assertTrue('Component must have been disposed of',
    -      component.isDisposed());
    -  assertNull('Component\'s element must be null', component.getElement());
    -  assertEquals('Previously decorated element must still be a child of the' +
    -      ' sandbox', sandbox, foo.parentNode);
    -}
    -
    -function testMakeIdAndGetFragmentFromId() {
    -  assertEquals('Unique id must have expected value',
    -      component.getId() + '.foo', component.makeId('foo'));
    -  assertEquals('Fragment must have expected value', 'foo',
    -      component.getFragmentFromId(component.makeId('foo')));
    -}
    -
    -function testMakeIdsWithObject() {
    -  var EnumDef = {
    -    ENUM_1: 'enum 1',
    -    ENUM_2: 'enum 2',
    -    ENUM_3: 'enum 3'
    -  };
    -  var ids = component.makeIds(EnumDef);
    -  assertEquals(component.makeId(EnumDef.ENUM_1), ids.ENUM_1);
    -  assertEquals(component.makeId(EnumDef.ENUM_2), ids.ENUM_2);
    -  assertEquals(component.makeId(EnumDef.ENUM_3), ids.ENUM_3);
    -}
    -
    -function testGetElementByFragment() {
    -  component.render(sandbox);
    -
    -  var element = component.dom_.createDom('DIV', {
    -    id: component.makeId('foo')
    -  }, 'Hello');
    -  sandbox.appendChild(element);
    -
    -  assertEquals('Element must have expected value', element,
    -      component.getElementByFragment('foo'));
    -}
    -
    -function testGetSetModel() {
    -  assertNull('Model must be null by default', component.getModel());
    -
    -  var model = 'someModel';
    -  component.setModel(model);
    -  assertEquals('Model must have expected value', model,
    -      component.getModel());
    -
    -  component.setModel(null);
    -  assertNull('Model must be null', component.getModel());
    -}
    -
    -function testAddChild() {
    -  var child = new goog.ui.Component();
    -  child.setId('child');
    -
    -  assertFalse('Parent must not be in the document',
    -      component.isInDocument());
    -
    -  component.addChild(child);
    -  assertTrue('Parent must have children.', component.hasChildren());
    -  assertEquals('Child must have expected parent', component,
    -      child.getParent());
    -  assertEquals('Parent must find child by ID', child,
    -      component.getChild('child'));
    -}
    -
    -function testAddChild_Render() {
    -  var child = new goog.ui.Component();
    -
    -  component.render(sandbox);
    -  assertTrue('Parent must be in the document', component.isInDocument());
    -  assertEquals('Parent must be in the sandbox', sandbox,
    -      component.getElement().parentNode);
    -
    -  component.addChild(child, true);
    -  assertTrue('Child must be in the document', child.isInDocument());
    -  assertEquals('Child element must be a child of the parent element',
    -      component.getElement(), child.getElement().parentNode);
    -}
    -
    -function testAddChild_DomOnly() {
    -  var child = new goog.ui.Component();
    -
    -  component.createDom();
    -  assertNotNull('Parent must have a DOM', component.getElement());
    -  assertFalse('Parent must not be in the document',
    -      component.isInDocument());
    -
    -  component.addChild(child, true);
    -  assertNotNull('Child must have a DOM', child.getElement());
    -  assertEquals('Child element must be a child of the parent element',
    -      component.getElement(), child.getElement().parentNode);
    -  assertFalse('Child must not be in the document', child.isInDocument());
    -}
    -
    -function testAddChildAt() {
    -  var a = new goog.ui.Component();
    -  var b = new goog.ui.Component();
    -  var c = new goog.ui.Component();
    -  var d = new goog.ui.Component();
    -
    -  a.setId('a');
    -  b.setId('b');
    -  c.setId('c');
    -  d.setId('d');
    -
    -  component.addChildAt(b, 0);
    -  assertEquals('b', component.getChildIds().join(''));
    -  component.addChildAt(d, 1);
    -  assertEquals('bd', component.getChildIds().join(''));
    -  component.addChildAt(a, 0);
    -  assertEquals('abd', component.getChildIds().join(''));
    -  component.addChildAt(c, 2);
    -  assertEquals('abcd', component.getChildIds().join(''));
    -
    -  assertEquals(a, component.getChildAt(0));
    -  assertEquals(b, component.getChildAt(1));
    -  assertEquals(c, component.getChildAt(2));
    -  assertEquals(d, component.getChildAt(3));
    -
    -  assertThrows('Adding child at out-of-bounds index must throw error',
    -      function() {
    -        component.addChildAt(new goog.ui.Component(), 5);
    -      });
    -}
    -
    -function testAddChildAtThrowsIfNull() {
    -  assertThrows('Adding a null child must throw an error',
    -      function() {
    -        component.addChildAt(null, 0);
    -      });
    -}
    -
    -function testHasChildren() {
    -  assertFalse('Component must not have children', component.hasChildren());
    -
    -  component.addChildAt(new goog.ui.Component(), 0);
    -  assertTrue('Component must have children', component.hasChildren());
    -
    -  component.removeChildAt(0);
    -  assertFalse('Component must not have children', component.hasChildren());
    -}
    -
    -function testGetChildCount() {
    -  assertEquals('Component must have 0 children', 0,
    -      component.getChildCount());
    -
    -  component.addChild(new goog.ui.Component());
    -  assertEquals('Component must have 1 child', 1,
    -      component.getChildCount());
    -
    -  component.addChild(new goog.ui.Component());
    -  assertEquals('Component must have 2 children', 2,
    -      component.getChildCount());
    -
    -  component.removeChildAt(1);
    -  assertEquals('Component must have 1 child', 1,
    -      component.getChildCount());
    -
    -  component.removeChildAt(0);
    -  assertEquals('Component must have 0 children', 0,
    -      component.getChildCount());
    -}
    -
    -function testGetChildIds() {
    -  var a = new goog.ui.Component();
    -  var b = new goog.ui.Component();
    -
    -  a.setId('a');
    -  b.setId('b');
    -
    -  component.addChild(a);
    -  assertEquals('a', component.getChildIds().join(''));
    -
    -  component.addChild(b);
    -  assertEquals('ab', component.getChildIds().join(''));
    -
    -  var ids = component.getChildIds();
    -  ids.push('c');
    -  assertEquals('Changes to the array returned by getChildIds() must not' +
    -      ' affect the component', 'ab', component.getChildIds().join(''));
    -}
    -
    -function testGetChild() {
    -  assertNull('Parent must have no children', component.getChild('myId'));
    -
    -  var c = new goog.ui.Component();
    -  c.setId('myId');
    -  component.addChild(c);
    -  assertEquals('Parent must find child by ID', c,
    -      component.getChild('myId'));
    -
    -  c.setId('newId');
    -  assertNull('Parent must not find child by old ID',
    -      component.getChild('myId'));
    -  assertEquals('Parent must find child by new ID', c,
    -      component.getChild('newId'));
    -}
    -
    -function testGetChildAt() {
    -  var a = new goog.ui.Component();
    -  var b = new goog.ui.Component();
    -
    -  a.setId('a');
    -  b.setId('b');
    -
    -  component.addChildAt(a, 0);
    -  assertEquals('Parent must find child by index', a,
    -      component.getChildAt(0));
    -
    -  component.addChildAt(b, 1);
    -  assertEquals('Parent must find child by index', b,
    -      component.getChildAt(1));
    -
    -  assertNull('Parent must return null for out-of-bounds index',
    -      component.getChildAt(3));
    -}
    -
    -function testForEachChild() {
    -  var invoked = false;
    -  component.forEachChild(function(child) {
    -    assertNotNull('Child must never be null', child);
    -    invoked = true;
    -  });
    -  assertFalse('forEachChild must not call its argument if the parent has ' +
    -      'no children', invoked);
    -
    -  component.addChild(new goog.ui.Component());
    -  component.addChild(new goog.ui.Component());
    -  component.addChild(new goog.ui.Component());
    -  var callCount = 0;
    -  component.forEachChild(function(child, index) {
    -    assertEquals(component, this);
    -    callCount++;
    -  }, component);
    -  assertEquals(3, callCount);
    -}
    -
    -function testIndexOfChild() {
    -  var a = new goog.ui.Component();
    -  var b = new goog.ui.Component();
    -  var c = new goog.ui.Component();
    -
    -  a.setId('a');
    -  b.setId('b');
    -  c.setId('c');
    -
    -  component.addChild(a);
    -  assertEquals(0, component.indexOfChild(a));
    -
    -  component.addChild(b);
    -  assertEquals(1, component.indexOfChild(b));
    -
    -  component.addChild(c);
    -  assertEquals(2, component.indexOfChild(c));
    -
    -  assertEquals('indexOfChild must return -1 for nonexistent child', -1,
    -      component.indexOfChild(new goog.ui.Component()));
    -}
    -
    -function testRemoveChild() {
    -  var a = new goog.ui.Component();
    -  var b = new goog.ui.Component();
    -  var c = new goog.ui.Component();
    -
    -  a.setId('a');
    -  b.setId('b');
    -  c.setId('c');
    -
    -  component.addChild(a);
    -  component.addChild(b);
    -  component.addChild(c);
    -
    -  assertEquals('Parent must remove and return child', c,
    -      component.removeChild(c));
    -  assertNull('Parent must no longer contain this child',
    -      component.getChild('c'));
    -
    -  assertEquals('Parent must remove and return child by ID', b,
    -      component.removeChild('b'));
    -  assertNull('Parent must no longer contain this child',
    -      component.getChild('b'));
    -
    -  assertEquals('Parent must remove and return child by index', a,
    -      component.removeChildAt(0));
    -  assertNull('Parent must no longer contain this child',
    -      component.getChild('a'));
    -}
    -
    -function testMovingChildrenUsingAddChildAt() {
    -  component.render(sandbox);
    -
    -  var a = new goog.ui.Component();
    -  var b = new goog.ui.Component();
    -  var c = new goog.ui.Component();
    -  var d = new goog.ui.Component();
    -  a.setElementInternal(goog.dom.createElement('a'));
    -  b.setElementInternal(goog.dom.createElement('b'));
    -  c.setElementInternal(goog.dom.createElement('c'));
    -  d.setElementInternal(goog.dom.createElement('d'));
    -
    -  a.setId('a');
    -  b.setId('b');
    -  c.setId('c');
    -  d.setId('d');
    -
    -  component.addChild(a, true);
    -  component.addChild(b, true);
    -  component.addChild(c, true);
    -  component.addChild(d, true);
    -
    -  assertEquals('abcd', component.getChildIds().join(''));
    -  assertEquals(a, component.getChildAt(0));
    -  assertEquals(b, component.getChildAt(1));
    -  assertEquals(c, component.getChildAt(2));
    -  assertEquals(d, component.getChildAt(3));
    -
    -  // Move child d to the top and b to the bottom.
    -  component.addChildAt(d, 0);
    -  component.addChildAt(b, 3);
    -
    -  assertEquals('dacb', component.getChildIds().join(''));
    -  assertEquals(d, component.getChildAt(0));
    -  assertEquals(a, component.getChildAt(1));
    -  assertEquals(c, component.getChildAt(2));
    -  assertEquals(b, component.getChildAt(3));
    -
    -  // Move child a to the top, and check that DOM nodes are in correct order.
    -  component.addChildAt(a, 0);
    -  assertEquals('adcb', component.getChildIds().join(''));
    -  assertEquals(a, component.getChildAt(0));
    -  assertEquals(a.getElement(), component.getElement().childNodes[0]);
    -}
    -
    -function testAddChildAfterDomCreatedDoesNotEnterDocument() {
    -  var parent = new goog.ui.Component();
    -  var child = new goog.ui.Component();
    -
    -  var nestedDiv = goog.dom.createDom('div');
    -  parent.setElementInternal(
    -      goog.dom.createDom('div', undefined, nestedDiv));
    -  parent.render();
    -
    -  // Now add a child, whose DOM already exists. This happens, for example,
    -  // if the child itself performs an addChild(x, true).
    -  child.createDom();
    -  parent.addChild(child, false);
    -  // The parent shouldn't call enterDocument on the child, since the child
    -  // actually isn't in the document yet.
    -  assertFalse(child.isInDocument());
    -
    -  // Now, actually render the child; it should be in the document.
    -  child.render(nestedDiv);
    -  assertTrue(child.isInDocument());
    -  assertEquals('Child should be rendered in the expected div',
    -      nestedDiv, child.getElement().parentNode);
    -}
    -
    -function testAddChildAfterDomManuallyInserted() {
    -  var parent = new goog.ui.Component();
    -  var child = new goog.ui.Component();
    -
    -  var nestedDiv = goog.dom.createDom('div');
    -  parent.setElementInternal(
    -      goog.dom.createDom('div', undefined, nestedDiv));
    -  parent.render();
    -
    -  // This sequence is weird, but some people do it instead of just manually
    -  // doing render.  The addChild will detect that the child is in the DOM
    -  // and call enterDocument.
    -  child.createDom();
    -  nestedDiv.appendChild(child.getElement());
    -  parent.addChild(child, false);
    -
    -  assertTrue(child.isInDocument());
    -  assertEquals('Child should be rendered in the expected div',
    -      nestedDiv, child.getElement().parentNode);
    -}
    -
    -function testRemoveChildren() {
    -  var a = new goog.ui.Component();
    -  var b = new goog.ui.Component();
    -  var c = new goog.ui.Component();
    -
    -  component.addChild(a);
    -  component.addChild(b);
    -  component.addChild(c);
    -
    -  a.setId('a');
    -  b.setId('b');
    -  c.setId('c');
    -
    -  assertArrayEquals('Parent must remove and return children.', [a, b, c],
    -      component.removeChildren());
    -  assertNull('Parent must no longer contain this child',
    -      component.getChild('a'));
    -  assertNull('Parent must no longer contain this child',
    -      component.getChild('b'));
    -  assertNull('Parent must no longer contain this child',
    -      component.getChild('c'));
    -}
    -
    -function testRemoveChildren_Unrender() {
    -  var a = new goog.ui.Component();
    -  var b = new goog.ui.Component();
    -
    -  component.render(sandbox);
    -  component.addChild(a);
    -  component.addChild(b);
    -
    -  assertArrayEquals('Prent must remove and return children.', [a, b],
    -      component.removeChildren(true));
    -  assertNull('Parent must no longer contain this child',
    -      component.getChild('a'));
    -  assertFalse('Child must no longer be in the document.',
    -      a.isInDocument());
    -  assertNull('Parent must no longer contain this child',
    -      component.getChild('b'));
    -  assertFalse('Child must no longer be in the document.',
    -      b.isInDocument());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/container.js b/src/database/third_party/closure-library/closure/goog/ui/container.js
    deleted file mode 100644
    index 3d7579a189c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/container.js
    +++ /dev/null
    @@ -1,1354 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Base class for containers that host {@link goog.ui.Control}s,
    - * such as menus and toolbars.  Provides default keyboard and mouse event
    - * handling and child management, based on a generalized version of
    - * {@link goog.ui.Menu}.
    - *
    - * @author attila@google.com (Attila Bodis)
    - * @see ../demos/container.html
    - */
    -// TODO(attila):  Fix code/logic duplication between this and goog.ui.Control.
    -// TODO(attila):  Maybe pull common stuff all the way up into Component...?
    -
    -goog.provide('goog.ui.Container');
    -goog.provide('goog.ui.Container.EventType');
    -goog.provide('goog.ui.Container.Orientation');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.events.KeyHandler');
    -goog.require('goog.object');
    -goog.require('goog.style');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.ContainerRenderer');
    -goog.require('goog.ui.Control');
    -
    -
    -
    -/**
    - * Base class for containers.  Extends {@link goog.ui.Component} by adding
    - * the following:
    - *  <ul>
    - *    <li>a {@link goog.events.KeyHandler}, to simplify keyboard handling,
    - *    <li>a pluggable <em>renderer</em> framework, to simplify the creation of
    - *        containers without the need to subclass this class,
    - *    <li>methods to manage child controls hosted in the container,
    - *    <li>default mouse and keyboard event handling methods.
    - *  </ul>
    - * @param {?goog.ui.Container.Orientation=} opt_orientation Container
    - *     orientation; defaults to {@code VERTICAL}.
    - * @param {goog.ui.ContainerRenderer=} opt_renderer Renderer used to render or
    - *     decorate the container; defaults to {@link goog.ui.ContainerRenderer}.
    - * @param {goog.dom.DomHelper=} opt_domHelper DOM helper, used for document
    - *     interaction.
    - * @extends {goog.ui.Component}
    - * @constructor
    - */
    -goog.ui.Container = function(opt_orientation, opt_renderer, opt_domHelper) {
    -  goog.ui.Component.call(this, opt_domHelper);
    -  this.renderer_ = opt_renderer || goog.ui.ContainerRenderer.getInstance();
    -  this.orientation_ = opt_orientation || this.renderer_.getDefaultOrientation();
    -};
    -goog.inherits(goog.ui.Container, goog.ui.Component);
    -goog.tagUnsealableClass(goog.ui.Container);
    -
    -
    -/**
    - * Container-specific events.
    - * @enum {string}
    - */
    -goog.ui.Container.EventType = {
    -  /**
    -   * Dispatched after a goog.ui.Container becomes visible. Non-cancellable.
    -   * NOTE(user): This event really shouldn't exist, because the
    -   * goog.ui.Component.EventType.SHOW event should behave like this one. But the
    -   * SHOW event for containers has been behaving as other components'
    -   * BEFORE_SHOW event for a long time, and too much code relies on that old
    -   * behavior to fix it now.
    -   */
    -  AFTER_SHOW: 'aftershow',
    -
    -  /**
    -   * Dispatched after a goog.ui.Container becomes invisible. Non-cancellable.
    -   */
    -  AFTER_HIDE: 'afterhide'
    -};
    -
    -
    -/**
    - * Container orientation constants.
    - * @enum {string}
    - */
    -goog.ui.Container.Orientation = {
    -  HORIZONTAL: 'horizontal',
    -  VERTICAL: 'vertical'
    -};
    -
    -
    -/**
    - * Allows an alternative element to be set to receive key events, otherwise
    - * defers to the renderer's element choice.
    - * @type {Element|undefined}
    - * @private
    - */
    -goog.ui.Container.prototype.keyEventTarget_ = null;
    -
    -
    -/**
    - * Keyboard event handler.
    - * @type {goog.events.KeyHandler?}
    - * @private
    - */
    -goog.ui.Container.prototype.keyHandler_ = null;
    -
    -
    -/**
    - * Renderer for the container.  Defaults to {@link goog.ui.ContainerRenderer}.
    - * @type {goog.ui.ContainerRenderer?}
    - * @private
    - */
    -goog.ui.Container.prototype.renderer_ = null;
    -
    -
    -/**
    - * Container orientation; determines layout and default keyboard navigation.
    - * @type {?goog.ui.Container.Orientation}
    - * @private
    - */
    -goog.ui.Container.prototype.orientation_ = null;
    -
    -
    -/**
    - * Whether the container is set to be visible.  Defaults to true.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.Container.prototype.visible_ = true;
    -
    -
    -/**
    - * Whether the container is enabled and reacting to keyboard and mouse events.
    - * Defaults to true.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.Container.prototype.enabled_ = true;
    -
    -
    -/**
    - * Whether the container supports keyboard focus.  Defaults to true.  Focusable
    - * containers have a {@code tabIndex} and can be navigated to via the keyboard.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.Container.prototype.focusable_ = true;
    -
    -
    -/**
    - * The 0-based index of the currently highlighted control in the container
    - * (-1 if none).
    - * @type {number}
    - * @private
    - */
    -goog.ui.Container.prototype.highlightedIndex_ = -1;
    -
    -
    -/**
    - * The currently open (expanded) control in the container (null if none).
    - * @type {goog.ui.Control?}
    - * @private
    - */
    -goog.ui.Container.prototype.openItem_ = null;
    -
    -
    -/**
    - * Whether the mouse button is held down.  Defaults to false.  This flag is set
    - * when the user mouses down over the container, and remains set until they
    - * release the mouse button.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.Container.prototype.mouseButtonPressed_ = false;
    -
    -
    -/**
    - * Whether focus of child components should be allowed.  Only effective if
    - * focusable_ is set to false.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.Container.prototype.allowFocusableChildren_ = false;
    -
    -
    -/**
    - * Whether highlighting a child component should also open it.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.Container.prototype.openFollowsHighlight_ = true;
    -
    -
    -/**
    - * Map of DOM IDs to child controls.  Each key is the DOM ID of a child
    - * control's root element; each value is a reference to the child control
    - * itself.  Used for looking up the child control corresponding to a DOM
    - * node in O(1) time.
    - * @type {Object}
    - * @private
    - */
    -goog.ui.Container.prototype.childElementIdMap_ = null;
    -
    -
    -// Event handler and renderer management.
    -
    -
    -/**
    - * Returns the DOM element on which the container is listening for keyboard
    - * events (null if none).
    - * @return {Element} Element on which the container is listening for key
    - *     events.
    - */
    -goog.ui.Container.prototype.getKeyEventTarget = function() {
    -  // Delegate to renderer, unless we've set an explicit target.
    -  return this.keyEventTarget_ || this.renderer_.getKeyEventTarget(this);
    -};
    -
    -
    -/**
    - * Attaches an element on which to listen for key events.
    - * @param {Element|undefined} element The element to attach, or null/undefined
    - *     to attach to the default element.
    - */
    -goog.ui.Container.prototype.setKeyEventTarget = function(element) {
    -  if (this.focusable_) {
    -    var oldTarget = this.getKeyEventTarget();
    -    var inDocument = this.isInDocument();
    -
    -    this.keyEventTarget_ = element;
    -    var newTarget = this.getKeyEventTarget();
    -
    -    if (inDocument) {
    -      // Unlisten for events on the old key target.  Requires us to reset
    -      // key target state temporarily.
    -      this.keyEventTarget_ = oldTarget;
    -      this.enableFocusHandling_(false);
    -      this.keyEventTarget_ = element;
    -
    -      // Listen for events on the new key target.
    -      this.getKeyHandler().attach(newTarget);
    -      this.enableFocusHandling_(true);
    -    }
    -  } else {
    -    throw Error('Can\'t set key event target for container ' +
    -        'that doesn\'t support keyboard focus!');
    -  }
    -};
    -
    -
    -/**
    - * Returns the keyboard event handler for this container, lazily created the
    - * first time this method is called.  The keyboard event handler listens for
    - * keyboard events on the container's key event target, as determined by its
    - * renderer.
    - * @return {!goog.events.KeyHandler} Keyboard event handler for this container.
    - */
    -goog.ui.Container.prototype.getKeyHandler = function() {
    -  return this.keyHandler_ ||
    -      (this.keyHandler_ = new goog.events.KeyHandler(this.getKeyEventTarget()));
    -};
    -
    -
    -/**
    - * Returns the renderer used by this container to render itself or to decorate
    - * an existing element.
    - * @return {goog.ui.ContainerRenderer} Renderer used by the container.
    - */
    -goog.ui.Container.prototype.getRenderer = function() {
    -  return this.renderer_;
    -};
    -
    -
    -/**
    - * Registers the given renderer with the container.  Changing renderers after
    - * the container has already been rendered or decorated is an error.
    - * @param {goog.ui.ContainerRenderer} renderer Renderer used by the container.
    - */
    -goog.ui.Container.prototype.setRenderer = function(renderer) {
    -  if (this.getElement()) {
    -    // Too late.
    -    throw Error(goog.ui.Component.Error.ALREADY_RENDERED);
    -  }
    -
    -  this.renderer_ = renderer;
    -};
    -
    -
    -// Standard goog.ui.Component implementation.
    -
    -
    -/**
    - * Creates the container's DOM.
    - * @override
    - */
    -goog.ui.Container.prototype.createDom = function() {
    -  // Delegate to renderer.
    -  this.setElementInternal(this.renderer_.createDom(this));
    -};
    -
    -
    -/**
    - * Returns the DOM element into which child components are to be rendered,
    - * or null if the container itself hasn't been rendered yet.  Overrides
    - * {@link goog.ui.Component#getContentElement} by delegating to the renderer.
    - * @return {Element} Element to contain child elements (null if none).
    - * @override
    - */
    -goog.ui.Container.prototype.getContentElement = function() {
    -  // Delegate to renderer.
    -  return this.renderer_.getContentElement(this.getElement());
    -};
    -
    -
    -/**
    - * Returns true if the given element can be decorated by this container.
    - * Overrides {@link goog.ui.Component#canDecorate}.
    - * @param {Element} element Element to decorate.
    - * @return {boolean} True iff the element can be decorated.
    - * @override
    - */
    -goog.ui.Container.prototype.canDecorate = function(element) {
    -  // Delegate to renderer.
    -  return this.renderer_.canDecorate(element);
    -};
    -
    -
    -/**
    - * Decorates the given element with this container. Overrides {@link
    - * goog.ui.Component#decorateInternal}.  Considered protected.
    - * @param {Element} element Element to decorate.
    - * @override
    - */
    -goog.ui.Container.prototype.decorateInternal = function(element) {
    -  // Delegate to renderer.
    -  this.setElementInternal(this.renderer_.decorate(this, element));
    -  // Check whether the decorated element is explicitly styled to be invisible.
    -  if (element.style.display == 'none') {
    -    this.visible_ = false;
    -  }
    -};
    -
    -
    -/**
    - * Configures the container after its DOM has been rendered, and sets up event
    - * handling.  Overrides {@link goog.ui.Component#enterDocument}.
    - * @override
    - */
    -goog.ui.Container.prototype.enterDocument = function() {
    -  goog.ui.Container.superClass_.enterDocument.call(this);
    -
    -  this.forEachChild(function(child) {
    -    if (child.isInDocument()) {
    -      this.registerChildId_(child);
    -    }
    -  }, this);
    -
    -  var elem = this.getElement();
    -
    -  // Call the renderer's initializeDom method to initialize the container's DOM.
    -  this.renderer_.initializeDom(this);
    -
    -  // Initialize visibility (opt_force = true, so we don't dispatch events).
    -  this.setVisible(this.visible_, true);
    -
    -  // Handle events dispatched by child controls.
    -  this.getHandler().
    -      listen(this, goog.ui.Component.EventType.ENTER,
    -          this.handleEnterItem).
    -      listen(this, goog.ui.Component.EventType.HIGHLIGHT,
    -          this.handleHighlightItem).
    -      listen(this, goog.ui.Component.EventType.UNHIGHLIGHT,
    -          this.handleUnHighlightItem).
    -      listen(this, goog.ui.Component.EventType.OPEN, this.handleOpenItem).
    -      listen(this, goog.ui.Component.EventType.CLOSE, this.handleCloseItem).
    -
    -      // Handle mouse events.
    -      listen(elem, goog.events.EventType.MOUSEDOWN, this.handleMouseDown).
    -      listen(goog.dom.getOwnerDocument(elem), goog.events.EventType.MOUSEUP,
    -          this.handleDocumentMouseUp).
    -
    -      // Handle mouse events on behalf of controls in the container.
    -      listen(elem, [
    -        goog.events.EventType.MOUSEDOWN,
    -        goog.events.EventType.MOUSEUP,
    -        goog.events.EventType.MOUSEOVER,
    -        goog.events.EventType.MOUSEOUT,
    -        goog.events.EventType.CONTEXTMENU
    -      ], this.handleChildMouseEvents);
    -
    -  // If the container is focusable, set up keyboard event handling.
    -  if (this.isFocusable()) {
    -    this.enableFocusHandling_(true);
    -  }
    -};
    -
    -
    -/**
    - * Sets up listening for events applicable to focusable containers.
    - * @param {boolean} enable Whether to enable or disable focus handling.
    - * @private
    - */
    -goog.ui.Container.prototype.enableFocusHandling_ = function(enable) {
    -  var handler = this.getHandler();
    -  var keyTarget = this.getKeyEventTarget();
    -  if (enable) {
    -    handler.
    -        listen(keyTarget, goog.events.EventType.FOCUS, this.handleFocus).
    -        listen(keyTarget, goog.events.EventType.BLUR, this.handleBlur).
    -        listen(this.getKeyHandler(), goog.events.KeyHandler.EventType.KEY,
    -            this.handleKeyEvent);
    -  } else {
    -    handler.
    -        unlisten(keyTarget, goog.events.EventType.FOCUS, this.handleFocus).
    -        unlisten(keyTarget, goog.events.EventType.BLUR, this.handleBlur).
    -        unlisten(this.getKeyHandler(), goog.events.KeyHandler.EventType.KEY,
    -            this.handleKeyEvent);
    -  }
    -};
    -
    -
    -/**
    - * Cleans up the container before its DOM is removed from the document, and
    - * removes event handlers.  Overrides {@link goog.ui.Component#exitDocument}.
    - * @override
    - */
    -goog.ui.Container.prototype.exitDocument = function() {
    -  // {@link #setHighlightedIndex} has to be called before
    -  // {@link goog.ui.Component#exitDocument}, otherwise it has no effect.
    -  this.setHighlightedIndex(-1);
    -
    -  if (this.openItem_) {
    -    this.openItem_.setOpen(false);
    -  }
    -
    -  this.mouseButtonPressed_ = false;
    -
    -  goog.ui.Container.superClass_.exitDocument.call(this);
    -};
    -
    -
    -/** @override */
    -goog.ui.Container.prototype.disposeInternal = function() {
    -  goog.ui.Container.superClass_.disposeInternal.call(this);
    -
    -  if (this.keyHandler_) {
    -    this.keyHandler_.dispose();
    -    this.keyHandler_ = null;
    -  }
    -
    -  this.keyEventTarget_ = null;
    -  this.childElementIdMap_ = null;
    -  this.openItem_ = null;
    -  this.renderer_ = null;
    -};
    -
    -
    -// Default event handlers.
    -
    -
    -/**
    - * Handles ENTER events raised by child controls when they are navigated to.
    - * @param {goog.events.Event} e ENTER event to handle.
    - * @return {boolean} Whether to prevent handleMouseOver from handling
    - *    the event.
    - */
    -goog.ui.Container.prototype.handleEnterItem = function(e) {
    -  // Allow the Control to highlight itself.
    -  return true;
    -};
    -
    -
    -/**
    - * Handles HIGHLIGHT events dispatched by items in the container when
    - * they are highlighted.
    - * @param {goog.events.Event} e Highlight event to handle.
    - */
    -goog.ui.Container.prototype.handleHighlightItem = function(e) {
    -  var index = this.indexOfChild(/** @type {goog.ui.Control} */ (e.target));
    -  if (index > -1 && index != this.highlightedIndex_) {
    -    var item = this.getHighlighted();
    -    if (item) {
    -      // Un-highlight previously highlighted item.
    -      item.setHighlighted(false);
    -    }
    -
    -    this.highlightedIndex_ = index;
    -    item = this.getHighlighted();
    -
    -    if (this.isMouseButtonPressed()) {
    -      // Activate item when mouse button is pressed, to allow MacOS-style
    -      // dragging to choose menu items.  Although this should only truly
    -      // happen if the highlight is due to mouse movements, there is little
    -      // harm in doing it for keyboard or programmatic highlights.
    -      item.setActive(true);
    -    }
    -
    -    // Update open item if open item needs follow highlight.
    -    if (this.openFollowsHighlight_ &&
    -        this.openItem_ && item != this.openItem_) {
    -      if (item.isSupportedState(goog.ui.Component.State.OPENED)) {
    -        item.setOpen(true);
    -      } else {
    -        this.openItem_.setOpen(false);
    -      }
    -    }
    -  }
    -
    -  var element = this.getElement();
    -  goog.asserts.assert(element,
    -      'The DOM element for the container cannot be null.');
    -  if (e.target.getElement() != null) {
    -    goog.a11y.aria.setState(element,
    -        goog.a11y.aria.State.ACTIVEDESCENDANT,
    -        e.target.getElement().id);
    -  }
    -};
    -
    -
    -/**
    - * Handles UNHIGHLIGHT events dispatched by items in the container when
    - * they are unhighlighted.
    - * @param {goog.events.Event} e Unhighlight event to handle.
    - */
    -goog.ui.Container.prototype.handleUnHighlightItem = function(e) {
    -  if (e.target == this.getHighlighted()) {
    -    this.highlightedIndex_ = -1;
    -  }
    -  var element = this.getElement();
    -  goog.asserts.assert(element,
    -      'The DOM element for the container cannot be null.');
    -  // Setting certain ARIA attributes to empty strings is problematic.
    -  // Just remove the attribute instead.
    -  goog.a11y.aria.removeState(element, goog.a11y.aria.State.ACTIVEDESCENDANT);
    -};
    -
    -
    -/**
    - * Handles OPEN events dispatched by items in the container when they are
    - * opened.
    - * @param {goog.events.Event} e Open event to handle.
    - */
    -goog.ui.Container.prototype.handleOpenItem = function(e) {
    -  var item = /** @type {goog.ui.Control} */ (e.target);
    -  if (item && item != this.openItem_ && item.getParent() == this) {
    -    if (this.openItem_) {
    -      this.openItem_.setOpen(false);
    -    }
    -    this.openItem_ = item;
    -  }
    -};
    -
    -
    -/**
    - * Handles CLOSE events dispatched by items in the container when they are
    - * closed.
    - * @param {goog.events.Event} e Close event to handle.
    - */
    -goog.ui.Container.prototype.handleCloseItem = function(e) {
    -  if (e.target == this.openItem_) {
    -    this.openItem_ = null;
    -  }
    -};
    -
    -
    -/**
    - * Handles mousedown events over the container.  The default implementation
    - * sets the "mouse button pressed" flag and, if the container is focusable,
    - * grabs keyboard focus.
    - * @param {goog.events.BrowserEvent} e Mousedown event to handle.
    - */
    -goog.ui.Container.prototype.handleMouseDown = function(e) {
    -  if (this.enabled_) {
    -    this.setMouseButtonPressed(true);
    -  }
    -
    -  var keyTarget = this.getKeyEventTarget();
    -  if (keyTarget && goog.dom.isFocusableTabIndex(keyTarget)) {
    -    // The container is configured to receive keyboard focus.
    -    keyTarget.focus();
    -  } else {
    -    // The control isn't configured to receive keyboard focus; prevent it
    -    // from stealing focus or destroying the selection.
    -    e.preventDefault();
    -  }
    -};
    -
    -
    -/**
    - * Handles mouseup events over the document.  The default implementation
    - * clears the "mouse button pressed" flag.
    - * @param {goog.events.BrowserEvent} e Mouseup event to handle.
    - */
    -goog.ui.Container.prototype.handleDocumentMouseUp = function(e) {
    -  this.setMouseButtonPressed(false);
    -};
    -
    -
    -/**
    - * Handles mouse events originating from nodes belonging to the controls hosted
    - * in the container.  Locates the child control based on the DOM node that
    - * dispatched the event, and forwards the event to the control for handling.
    - * @param {goog.events.BrowserEvent} e Mouse event to handle.
    - */
    -goog.ui.Container.prototype.handleChildMouseEvents = function(e) {
    -  var control = this.getOwnerControl(/** @type {Node} */ (e.target));
    -  if (control) {
    -    // Child control identified; forward the event.
    -    switch (e.type) {
    -      case goog.events.EventType.MOUSEDOWN:
    -        control.handleMouseDown(e);
    -        break;
    -      case goog.events.EventType.MOUSEUP:
    -        control.handleMouseUp(e);
    -        break;
    -      case goog.events.EventType.MOUSEOVER:
    -        control.handleMouseOver(e);
    -        break;
    -      case goog.events.EventType.MOUSEOUT:
    -        control.handleMouseOut(e);
    -        break;
    -      case goog.events.EventType.CONTEXTMENU:
    -        control.handleContextMenu(e);
    -        break;
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Returns the child control that owns the given DOM node, or null if no such
    - * control is found.
    - * @param {Node} node DOM node whose owner is to be returned.
    - * @return {goog.ui.Control?} Control hosted in the container to which the node
    - *     belongs (if found).
    - * @protected
    - */
    -goog.ui.Container.prototype.getOwnerControl = function(node) {
    -  // Ensure that this container actually has child controls before
    -  // looking up the owner.
    -  if (this.childElementIdMap_) {
    -    var elem = this.getElement();
    -    // See http://b/2964418 . IE9 appears to evaluate '!=' incorrectly, so
    -    // using '!==' instead.
    -    // TODO(user): Possibly revert this change if/when IE9 fixes the issue.
    -    while (node && node !== elem) {
    -      var id = node.id;
    -      if (id in this.childElementIdMap_) {
    -        return this.childElementIdMap_[id];
    -      }
    -      node = node.parentNode;
    -    }
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * Handles focus events raised when the container's key event target receives
    - * keyboard focus.
    - * @param {goog.events.BrowserEvent} e Focus event to handle.
    - */
    -goog.ui.Container.prototype.handleFocus = function(e) {
    -  // No-op in the base class.
    -};
    -
    -
    -/**
    - * Handles blur events raised when the container's key event target loses
    - * keyboard focus.  The default implementation clears the highlight index.
    - * @param {goog.events.BrowserEvent} e Blur event to handle.
    - */
    -goog.ui.Container.prototype.handleBlur = function(e) {
    -  this.setHighlightedIndex(-1);
    -  this.setMouseButtonPressed(false);
    -  // If the container loses focus, and one of its children is open, close it.
    -  if (this.openItem_) {
    -    this.openItem_.setOpen(false);
    -  }
    -};
    -
    -
    -/**
    - * Attempts to handle a keyboard event, if the control is enabled, by calling
    - * {@link handleKeyEventInternal}.  Considered protected; should only be used
    - * within this package and by subclasses.
    - * @param {goog.events.KeyEvent} e Key event to handle.
    - * @return {boolean} Whether the key event was handled.
    - */
    -goog.ui.Container.prototype.handleKeyEvent = function(e) {
    -  if (this.isEnabled() && this.isVisible() &&
    -      (this.getChildCount() != 0 || this.keyEventTarget_) &&
    -      this.handleKeyEventInternal(e)) {
    -    e.preventDefault();
    -    e.stopPropagation();
    -    return true;
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Attempts to handle a keyboard event; returns true if the event was handled,
    - * false otherwise.  If the container is enabled, and a child is highlighted,
    - * calls the child control's {@code handleKeyEvent} method to give the control
    - * a chance to handle the event first.
    - * @param {goog.events.KeyEvent} e Key event to handle.
    - * @return {boolean} Whether the event was handled by the container (or one of
    - *     its children).
    - */
    -goog.ui.Container.prototype.handleKeyEventInternal = function(e) {
    -  // Give the highlighted control the chance to handle the key event.
    -  var highlighted = this.getHighlighted();
    -  if (highlighted && typeof highlighted.handleKeyEvent == 'function' &&
    -      highlighted.handleKeyEvent(e)) {
    -    return true;
    -  }
    -
    -  // Give the open control the chance to handle the key event.
    -  if (this.openItem_ && this.openItem_ != highlighted &&
    -      typeof this.openItem_.handleKeyEvent == 'function' &&
    -      this.openItem_.handleKeyEvent(e)) {
    -    return true;
    -  }
    -
    -  // Do not handle the key event if any modifier key is pressed.
    -  if (e.shiftKey || e.ctrlKey || e.metaKey || e.altKey) {
    -    return false;
    -  }
    -
    -  // Either nothing is highlighted, or the highlighted control didn't handle
    -  // the key event, so attempt to handle it here.
    -  switch (e.keyCode) {
    -    case goog.events.KeyCodes.ESC:
    -      if (this.isFocusable()) {
    -        this.getKeyEventTarget().blur();
    -      } else {
    -        return false;
    -      }
    -      break;
    -
    -    case goog.events.KeyCodes.HOME:
    -      this.highlightFirst();
    -      break;
    -
    -    case goog.events.KeyCodes.END:
    -      this.highlightLast();
    -      break;
    -
    -    case goog.events.KeyCodes.UP:
    -      if (this.orientation_ == goog.ui.Container.Orientation.VERTICAL) {
    -        this.highlightPrevious();
    -      } else {
    -        return false;
    -      }
    -      break;
    -
    -    case goog.events.KeyCodes.LEFT:
    -      if (this.orientation_ == goog.ui.Container.Orientation.HORIZONTAL) {
    -        if (this.isRightToLeft()) {
    -          this.highlightNext();
    -        } else {
    -          this.highlightPrevious();
    -        }
    -      } else {
    -        return false;
    -      }
    -      break;
    -
    -    case goog.events.KeyCodes.DOWN:
    -      if (this.orientation_ == goog.ui.Container.Orientation.VERTICAL) {
    -        this.highlightNext();
    -      } else {
    -        return false;
    -      }
    -      break;
    -
    -    case goog.events.KeyCodes.RIGHT:
    -      if (this.orientation_ == goog.ui.Container.Orientation.HORIZONTAL) {
    -        if (this.isRightToLeft()) {
    -          this.highlightPrevious();
    -        } else {
    -          this.highlightNext();
    -        }
    -      } else {
    -        return false;
    -      }
    -      break;
    -
    -    default:
    -      return false;
    -  }
    -
    -  return true;
    -};
    -
    -
    -// Child component management.
    -
    -
    -/**
    - * Creates a DOM ID for the child control and registers it to an internal
    - * hash table to be able to find it fast by id.
    - * @param {goog.ui.Component} child The child control. Its root element has
    - *     to be created yet.
    - * @private
    - */
    -goog.ui.Container.prototype.registerChildId_ = function(child) {
    -  // Map the DOM ID of the control's root element to the control itself.
    -  var childElem = child.getElement();
    -
    -  // If the control's root element doesn't have a DOM ID assign one.
    -  var id = childElem.id || (childElem.id = child.getId());
    -
    -  // Lazily create the child element ID map on first use.
    -  if (!this.childElementIdMap_) {
    -    this.childElementIdMap_ = {};
    -  }
    -  this.childElementIdMap_[id] = child;
    -};
    -
    -
    -/**
    - * Adds the specified control as the last child of this container.  See
    - * {@link goog.ui.Container#addChildAt} for detailed semantics.
    - * @param {goog.ui.Component} child The new child control.
    - * @param {boolean=} opt_render Whether the new child should be rendered
    - *     immediately after being added (defaults to false).
    - * @override
    - */
    -goog.ui.Container.prototype.addChild = function(child, opt_render) {
    -  goog.asserts.assertInstanceof(child, goog.ui.Control,
    -      'The child of a container must be a control');
    -  goog.ui.Container.superClass_.addChild.call(this, child, opt_render);
    -};
    -
    -
    -/**
    - * Overrides {@link goog.ui.Container#getChild} to make it clear that it
    - * only returns {@link goog.ui.Control}s.
    - * @param {string} id Child component ID.
    - * @return {goog.ui.Control} The child with the given ID; null if none.
    - * @override
    - */
    -goog.ui.Container.prototype.getChild;
    -
    -
    -/**
    - * Overrides {@link goog.ui.Container#getChildAt} to make it clear that it
    - * only returns {@link goog.ui.Control}s.
    - * @param {number} index 0-based index.
    - * @return {goog.ui.Control} The child with the given ID; null if none.
    - * @override
    - */
    -goog.ui.Container.prototype.getChildAt;
    -
    -
    -/**
    - * Adds the control as a child of this container at the given 0-based index.
    - * Overrides {@link goog.ui.Component#addChildAt} by also updating the
    - * container's highlight index.  Since {@link goog.ui.Component#addChild} uses
    - * {@link #addChildAt} internally, we only need to override this method.
    - * @param {goog.ui.Component} control New child.
    - * @param {number} index Index at which the new child is to be added.
    - * @param {boolean=} opt_render Whether the new child should be rendered
    - *     immediately after being added (defaults to false).
    - * @override
    - */
    -goog.ui.Container.prototype.addChildAt = function(control, index, opt_render) {
    -  goog.asserts.assertInstanceof(control, goog.ui.Control);
    -
    -  // Make sure the child control dispatches HIGHLIGHT, UNHIGHLIGHT, OPEN, and
    -  // CLOSE events, and that it doesn't steal keyboard focus.
    -  control.setDispatchTransitionEvents(goog.ui.Component.State.HOVER, true);
    -  control.setDispatchTransitionEvents(goog.ui.Component.State.OPENED, true);
    -  if (this.isFocusable() || !this.isFocusableChildrenAllowed()) {
    -    control.setSupportedState(goog.ui.Component.State.FOCUSED, false);
    -  }
    -
    -  // Disable mouse event handling by child controls.
    -  control.setHandleMouseEvents(false);
    -
    -  var srcIndex = (control.getParent() == this) ?
    -      this.indexOfChild(control) : -1;
    -
    -  // Let the superclass implementation do the work.
    -  goog.ui.Container.superClass_.addChildAt.call(this, control, index,
    -      opt_render);
    -
    -  if (control.isInDocument() && this.isInDocument()) {
    -    this.registerChildId_(control);
    -  }
    -
    -  this.updateHighlightedIndex_(srcIndex, index);
    -};
    -
    -
    -/**
    - * Updates the highlighted index when children are added or moved.
    - * @param {number} fromIndex Index of the child before it was moved, or -1 if
    - *     the child was added.
    - * @param {number} toIndex Index of the child after it was moved or added.
    - * @private
    - */
    -goog.ui.Container.prototype.updateHighlightedIndex_ = function(
    -    fromIndex, toIndex) {
    -  if (fromIndex == -1) {
    -    fromIndex = this.getChildCount();
    -  }
    -  if (fromIndex == this.highlightedIndex_) {
    -    // The highlighted element itself was moved.
    -    this.highlightedIndex_ = Math.min(this.getChildCount() - 1, toIndex);
    -  } else if (fromIndex > this.highlightedIndex_ &&
    -      toIndex <= this.highlightedIndex_) {
    -    // The control was added or moved behind the highlighted index.
    -    this.highlightedIndex_++;
    -  } else if (fromIndex < this.highlightedIndex_ &&
    -      toIndex > this.highlightedIndex_) {
    -    // The control was moved from before to behind the highlighted index.
    -    this.highlightedIndex_--;
    -  }
    -};
    -
    -
    -/**
    - * Removes a child control.  Overrides {@link goog.ui.Component#removeChild} by
    - * updating the highlight index.  Since {@link goog.ui.Component#removeChildAt}
    - * uses {@link #removeChild} internally, we only need to override this method.
    - * @param {string|goog.ui.Component} control The ID of the child to remove, or
    - *     the control itself.
    - * @param {boolean=} opt_unrender Whether to call {@code exitDocument} on the
    - *     removed control, and detach its DOM from the document (defaults to
    - *     false).
    - * @return {goog.ui.Control} The removed control, if any.
    - * @override
    - */
    -goog.ui.Container.prototype.removeChild = function(control, opt_unrender) {
    -  control = goog.isString(control) ? this.getChild(control) : control;
    -  goog.asserts.assertInstanceof(control, goog.ui.Control);
    -
    -  if (control) {
    -    var index = this.indexOfChild(control);
    -    if (index != -1) {
    -      if (index == this.highlightedIndex_) {
    -        control.setHighlighted(false);
    -        this.highlightedIndex_ = -1;
    -      } else if (index < this.highlightedIndex_) {
    -        this.highlightedIndex_--;
    -      }
    -    }
    -
    -    // Remove the mapping from the child element ID map.
    -    var childElem = control.getElement();
    -    if (childElem && childElem.id && this.childElementIdMap_) {
    -      goog.object.remove(this.childElementIdMap_, childElem.id);
    -    }
    -  }
    -
    -  control = /** @type {!goog.ui.Control} */ (
    -      goog.ui.Container.superClass_.removeChild.call(this, control,
    -          opt_unrender));
    -
    -  // Re-enable mouse event handling (in case the control is reused elsewhere).
    -  control.setHandleMouseEvents(true);
    -
    -  return control;
    -};
    -
    -
    -// Container state management.
    -
    -
    -/**
    - * Returns the container's orientation.
    - * @return {?goog.ui.Container.Orientation} Container orientation.
    - */
    -goog.ui.Container.prototype.getOrientation = function() {
    -  return this.orientation_;
    -};
    -
    -
    -/**
    - * Sets the container's orientation.
    - * @param {goog.ui.Container.Orientation} orientation Container orientation.
    - */
    -// TODO(attila): Do we need to support containers with dynamic orientation?
    -goog.ui.Container.prototype.setOrientation = function(orientation) {
    -  if (this.getElement()) {
    -    // Too late.
    -    throw Error(goog.ui.Component.Error.ALREADY_RENDERED);
    -  }
    -
    -  this.orientation_ = orientation;
    -};
    -
    -
    -/**
    - * Returns true if the container's visibility is set to visible, false if
    - * it is set to hidden.  A container that is set to hidden is guaranteed
    - * to be hidden from the user, but the reverse isn't necessarily true.
    - * A container may be set to visible but can otherwise be obscured by another
    - * element, rendered off-screen, or hidden using direct CSS manipulation.
    - * @return {boolean} Whether the container is set to be visible.
    - */
    -goog.ui.Container.prototype.isVisible = function() {
    -  return this.visible_;
    -};
    -
    -
    -/**
    - * Shows or hides the container.  Does nothing if the container already has
    - * the requested visibility.  Otherwise, dispatches a SHOW or HIDE event as
    - * appropriate, giving listeners a chance to prevent the visibility change.
    - * @param {boolean} visible Whether to show or hide the container.
    - * @param {boolean=} opt_force If true, doesn't check whether the container
    - *     already has the requested visibility, and doesn't dispatch any events.
    - * @return {boolean} Whether the visibility was changed.
    - */
    -goog.ui.Container.prototype.setVisible = function(visible, opt_force) {
    -  if (opt_force || (this.visible_ != visible && this.dispatchEvent(visible ?
    -      goog.ui.Component.EventType.SHOW : goog.ui.Component.EventType.HIDE))) {
    -    this.visible_ = visible;
    -
    -    var elem = this.getElement();
    -    if (elem) {
    -      goog.style.setElementShown(elem, visible);
    -      if (this.isFocusable()) {
    -        // Enable keyboard access only for enabled & visible containers.
    -        this.renderer_.enableTabIndex(this.getKeyEventTarget(),
    -            this.enabled_ && this.visible_);
    -      }
    -      if (!opt_force) {
    -        this.dispatchEvent(this.visible_ ?
    -            goog.ui.Container.EventType.AFTER_SHOW :
    -            goog.ui.Container.EventType.AFTER_HIDE);
    -      }
    -    }
    -
    -    return true;
    -  }
    -
    -  return false;
    -};
    -
    -
    -/**
    - * Returns true if the container is enabled, false otherwise.
    - * @return {boolean} Whether the container is enabled.
    - */
    -goog.ui.Container.prototype.isEnabled = function() {
    -  return this.enabled_;
    -};
    -
    -
    -/**
    - * Enables/disables the container based on the {@code enable} argument.
    - * Dispatches an {@code ENABLED} or {@code DISABLED} event prior to changing
    - * the container's state, which may be caught and canceled to prevent the
    - * container from changing state.  Also enables/disables child controls.
    - * @param {boolean} enable Whether to enable or disable the container.
    - */
    -goog.ui.Container.prototype.setEnabled = function(enable) {
    -  if (this.enabled_ != enable && this.dispatchEvent(enable ?
    -      goog.ui.Component.EventType.ENABLE :
    -      goog.ui.Component.EventType.DISABLE)) {
    -    if (enable) {
    -      // Flag the container as enabled first, then update children.  This is
    -      // because controls can't be enabled if their parent is disabled.
    -      this.enabled_ = true;
    -      this.forEachChild(function(child) {
    -        // Enable child control unless it is flagged.
    -        if (child.wasDisabled) {
    -          delete child.wasDisabled;
    -        } else {
    -          child.setEnabled(true);
    -        }
    -      });
    -    } else {
    -      // Disable children first, then flag the container as disabled.  This is
    -      // because controls can't be disabled if their parent is already disabled.
    -      this.forEachChild(function(child) {
    -        // Disable child control, or flag it if it's already disabled.
    -        if (child.isEnabled()) {
    -          child.setEnabled(false);
    -        } else {
    -          child.wasDisabled = true;
    -        }
    -      });
    -      this.enabled_ = false;
    -      this.setMouseButtonPressed(false);
    -    }
    -
    -    if (this.isFocusable()) {
    -      // Enable keyboard access only for enabled & visible components.
    -      this.renderer_.enableTabIndex(this.getKeyEventTarget(),
    -          enable && this.visible_);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Returns true if the container is focusable, false otherwise.  The default
    - * is true.  Focusable containers always have a tab index and allocate a key
    - * handler to handle keyboard events while focused.
    - * @return {boolean} Whether the component is focusable.
    - */
    -goog.ui.Container.prototype.isFocusable = function() {
    -  return this.focusable_;
    -};
    -
    -
    -/**
    - * Sets whether the container is focusable.  The default is true.  Focusable
    - * containers always have a tab index and allocate a key handler to handle
    - * keyboard events while focused.
    - * @param {boolean} focusable Whether the component is to be focusable.
    - */
    -goog.ui.Container.prototype.setFocusable = function(focusable) {
    -  if (focusable != this.focusable_ && this.isInDocument()) {
    -    this.enableFocusHandling_(focusable);
    -  }
    -  this.focusable_ = focusable;
    -  if (this.enabled_ && this.visible_) {
    -    this.renderer_.enableTabIndex(this.getKeyEventTarget(), focusable);
    -  }
    -};
    -
    -
    -/**
    - * Returns true if the container allows children to be focusable, false
    - * otherwise.  Only effective if the container is not focusable.
    - * @return {boolean} Whether children should be focusable.
    - */
    -goog.ui.Container.prototype.isFocusableChildrenAllowed = function() {
    -  return this.allowFocusableChildren_;
    -};
    -
    -
    -/**
    - * Sets whether the container allows children to be focusable, false
    - * otherwise.  Only effective if the container is not focusable.
    - * @param {boolean} focusable Whether the children should be focusable.
    - */
    -goog.ui.Container.prototype.setFocusableChildrenAllowed = function(focusable) {
    -  this.allowFocusableChildren_ = focusable;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether highlighting a child component should also open it.
    - */
    -goog.ui.Container.prototype.isOpenFollowsHighlight = function() {
    -  return this.openFollowsHighlight_;
    -};
    -
    -
    -/**
    - * Sets whether highlighting a child component should also open it.
    - * @param {boolean} follow Whether highlighting a child component also opens it.
    - */
    -goog.ui.Container.prototype.setOpenFollowsHighlight = function(follow) {
    -  this.openFollowsHighlight_ = follow;
    -};
    -
    -
    -// Highlight management.
    -
    -
    -/**
    - * Returns the index of the currently highlighted item (-1 if none).
    - * @return {number} Index of the currently highlighted item.
    - */
    -goog.ui.Container.prototype.getHighlightedIndex = function() {
    -  return this.highlightedIndex_;
    -};
    -
    -
    -/**
    - * Highlights the item at the given 0-based index (if any).  If another item
    - * was previously highlighted, it is un-highlighted.
    - * @param {number} index Index of item to highlight (-1 removes the current
    - *     highlight).
    - */
    -goog.ui.Container.prototype.setHighlightedIndex = function(index) {
    -  var child = this.getChildAt(index);
    -  if (child) {
    -    child.setHighlighted(true);
    -  } else if (this.highlightedIndex_ > -1) {
    -    this.getHighlighted().setHighlighted(false);
    -  }
    -};
    -
    -
    -/**
    - * Highlights the given item if it exists and is a child of the container;
    - * otherwise un-highlights the currently highlighted item.
    - * @param {goog.ui.Control} item Item to highlight.
    - */
    -goog.ui.Container.prototype.setHighlighted = function(item) {
    -  this.setHighlightedIndex(this.indexOfChild(item));
    -};
    -
    -
    -/**
    - * Returns the currently highlighted item (if any).
    - * @return {goog.ui.Control?} Highlighted item (null if none).
    - */
    -goog.ui.Container.prototype.getHighlighted = function() {
    -  return this.getChildAt(this.highlightedIndex_);
    -};
    -
    -
    -/**
    - * Highlights the first highlightable item in the container
    - */
    -goog.ui.Container.prototype.highlightFirst = function() {
    -  this.highlightHelper(function(index, max) {
    -    return (index + 1) % max;
    -  }, this.getChildCount() - 1);
    -};
    -
    -
    -/**
    - * Highlights the last highlightable item in the container.
    - */
    -goog.ui.Container.prototype.highlightLast = function() {
    -  this.highlightHelper(function(index, max) {
    -    index--;
    -    return index < 0 ? max - 1 : index;
    -  }, 0);
    -};
    -
    -
    -/**
    - * Highlights the next highlightable item (or the first if nothing is currently
    - * highlighted).
    - */
    -goog.ui.Container.prototype.highlightNext = function() {
    -  this.highlightHelper(function(index, max) {
    -    return (index + 1) % max;
    -  }, this.highlightedIndex_);
    -};
    -
    -
    -/**
    - * Highlights the previous highlightable item (or the last if nothing is
    - * currently highlighted).
    - */
    -goog.ui.Container.prototype.highlightPrevious = function() {
    -  this.highlightHelper(function(index, max) {
    -    index--;
    -    return index < 0 ? max - 1 : index;
    -  }, this.highlightedIndex_);
    -};
    -
    -
    -/**
    - * Helper function that manages the details of moving the highlight among
    - * child controls in response to keyboard events.
    - * @param {function(number, number) : number} fn Function that accepts the
    - *     current and maximum indices, and returns the next index to check.
    - * @param {number} startIndex Start index.
    - * @return {boolean} Whether the highlight has changed.
    - * @protected
    - */
    -goog.ui.Container.prototype.highlightHelper = function(fn, startIndex) {
    -  // If the start index is -1 (meaning there's nothing currently highlighted),
    -  // try starting from the currently open item, if any.
    -  var curIndex = startIndex < 0 ?
    -      this.indexOfChild(this.openItem_) : startIndex;
    -  var numItems = this.getChildCount();
    -
    -  curIndex = fn.call(this, curIndex, numItems);
    -  var visited = 0;
    -  while (visited <= numItems) {
    -    var control = this.getChildAt(curIndex);
    -    if (control && this.canHighlightItem(control)) {
    -      this.setHighlightedIndexFromKeyEvent(curIndex);
    -      return true;
    -    }
    -    visited++;
    -    curIndex = fn.call(this, curIndex, numItems);
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Returns whether the given item can be highlighted.
    - * @param {goog.ui.Control} item The item to check.
    - * @return {boolean} Whether the item can be highlighted.
    - * @protected
    - */
    -goog.ui.Container.prototype.canHighlightItem = function(item) {
    -  return item.isVisible() && item.isEnabled() &&
    -      item.isSupportedState(goog.ui.Component.State.HOVER);
    -};
    -
    -
    -/**
    - * Helper method that sets the highlighted index to the given index in response
    - * to a keyboard event.  The base class implementation simply calls the
    - * {@link #setHighlightedIndex} method, but subclasses can override this
    - * behavior as needed.
    - * @param {number} index Index of item to highlight.
    - * @protected
    - */
    -goog.ui.Container.prototype.setHighlightedIndexFromKeyEvent = function(index) {
    -  this.setHighlightedIndex(index);
    -};
    -
    -
    -/**
    - * Returns the currently open (expanded) control in the container (null if
    - * none).
    - * @return {goog.ui.Control?} The currently open control.
    - */
    -goog.ui.Container.prototype.getOpenItem = function() {
    -  return this.openItem_;
    -};
    -
    -
    -/**
    - * Returns true if the mouse button is pressed, false otherwise.
    - * @return {boolean} Whether the mouse button is pressed.
    - */
    -goog.ui.Container.prototype.isMouseButtonPressed = function() {
    -  return this.mouseButtonPressed_;
    -};
    -
    -
    -/**
    - * Sets or clears the "mouse button pressed" flag.
    - * @param {boolean} pressed Whether the mouse button is presed.
    - */
    -goog.ui.Container.prototype.setMouseButtonPressed = function(pressed) {
    -  this.mouseButtonPressed_ = pressed;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/container_perf.html b/src/database/third_party/closure-library/closure/goog/ui/container_perf.html
    deleted file mode 100644
    index 40486afb605..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/container_perf.html
    +++ /dev/null
    @@ -1,55 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -  <title>Closure Performance Tests - goog.ui.Container</title>
    -  <link rel="stylesheet" type="text/css" href="../testing/performancetable.css"/>
    -  <script src="../base.js"></script>
    -  <script>
    -    goog.require('goog.testing.PerformanceTable');
    -    goog.require('goog.testing.jsunit');
    -    goog.require('goog.ui.Container');
    -    goog.require('goog.ui.Control');
    -  </script>
    -</head>
    -<body>
    -  <h1>goog.ui.Container Performance Tests</h1>
    -  <p>
    -    <strong>User-agent:</strong>
    -    <script>document.write(navigator.userAgent);</script>
    -  </p>
    -  <div id="perfTable"></div>
    -  <hr>
    -
    -  <script>
    -    var table = new goog.testing.PerformanceTable(
    -        goog.dom.getElement('perfTable'));
    -
    -    // Number of controls to add to the container per test run.
    -    var SAMPLES_PER_RUN = 500;
    -
    -    function testContainerAddChild() {
    -      var description = 'Add ' + SAMPLES_PER_RUN +
    -          ' child controls to the container with immediate rendering';
    -      table.run(function() {
    -        var container = new goog.ui.Container();
    -        for (var i = 0; i < SAMPLES_PER_RUN; i++) {
    -          container.addChild(new goog.ui.Control(), true);
    -        }
    -        container.render();
    -        assertEquals('container child count', SAMPLES_PER_RUN,
    -              container.getChildCount());
    -        container.dispose();
    -      }, description);
    -    }
    -  </script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/container_test.html b/src/database/third_party/closure-library/closure/goog/ui/container_test.html
    deleted file mode 100644
    index 6e562cb4983..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/container_test.html
    +++ /dev/null
    @@ -1,27 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -Author:  attila@google.com (Attila Bodis)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.Container
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.ContainerTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="sandbox">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/container_test.js b/src/database/third_party/closure-library/closure/goog/ui/container_test.js
    deleted file mode 100644
    index 85334b81d29..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/container_test.js
    +++ /dev/null
    @@ -1,612 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.ContainerTest');
    -goog.setTestOnly('goog.ui.ContainerTest');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.events.KeyEvent');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.Container');
    -goog.require('goog.ui.Control');
    -
    -var sandbox;
    -var containerElement;
    -var container;
    -var keyContainer;
    -var listContainer;
    -
    -function setUpPage() {
    -  sandbox = goog.dom.getElement('sandbox');
    -}
    -
    -function setUp() {
    -  container = new goog.ui.Container();
    -  keyContainer = null;
    -  listContainer = null;
    -
    -  sandbox.innerHTML =
    -      '<div id="containerElement" class="goog-container">\n' +
    -      '  <div class="goog-control" id="hello">Hello</div>\n' +
    -      '  <div class="goog-control" id="world">World</div>\n' +
    -      '</div>';
    -  containerElement = goog.dom.getElement('containerElement');
    -}
    -
    -function tearDown() {
    -  goog.dom.removeChildren(sandbox);
    -  container.dispose();
    -  goog.dispose(keyContainer);
    -  goog.dispose(listContainer);
    -}
    -
    -function testDecorateHidden() {
    -  containerElement.style.display = 'none';
    -
    -  assertTrue('Container must be visible', container.isVisible());
    -  container.decorate(containerElement);
    -  assertFalse('Container must be hidden', container.isVisible());
    -  container.forEachChild(function(control) {
    -    assertTrue('Child control ' + control.getId() + ' must report being ' +
    -        'visible, even if in a hidden container', control.isVisible());
    -  });
    -}
    -
    -function testDecorateDisabled() {
    -  goog.dom.classlist.add(containerElement, 'goog-container-disabled');
    -
    -  assertTrue('Container must be enabled', container.isEnabled());
    -  container.decorate(containerElement);
    -  assertFalse('Container must be disabled', container.isEnabled());
    -  container.forEachChild(function(control) {
    -    assertFalse('Child control ' + control.getId() + ' must be disabled, ' +
    -        'because the host container is disabled', control.isEnabled());
    -  });
    -}
    -
    -function testDecorateFocusableContainer() {
    -  container.decorate(containerElement);
    -  assertTrue('Container must be focusable', container.isFocusable());
    -  container.forEachChild(function(control) {
    -    assertFalse('Child control ' + control.getId() + ' must not be ' +
    -        'focusable',
    -        control.isSupportedState(goog.ui.Component.State.FOCUSED));
    -  });
    -}
    -
    -function testDecorateFocusableChildrenContainer() {
    -  container.setFocusable(false);
    -  container.setFocusableChildrenAllowed(true);
    -  container.decorate(containerElement);
    -  assertFalse('Container must not be focusable', container.isFocusable());
    -  container.forEachChild(function(control) {
    -    assertTrue('Child control ' + control.getId() + ' must be ' +
    -        'focusable',
    -        control.isSupportedState(goog.ui.Component.State.FOCUSED));
    -  });
    -}
    -
    -function testHighlightOnEnter() {
    -  // This interaction test ensures that containers enforce that children
    -  // get highlighted on mouseover, and that one and only one child may
    -  // be highlighted at a time.  Although integration tests aren't the
    -  // best, it's difficult to test these event-based interactions due to
    -  // their disposition toward the "misunderstood contract" problem.
    -
    -  container.decorate(containerElement);
    -  assertFalse('Child 0 should initially not be highlighted',
    -      container.getChildAt(0).isHighlighted());
    -
    -  goog.testing.events.fireMouseOverEvent(
    -      container.getChildAt(0).getElement(), sandbox);
    -  assertTrue('Child 0 should become highlighted after a mouse over',
    -      container.getChildAt(0).isHighlighted());
    -  assertEquals('Child 0 should be the active descendant',
    -      container.getChildAt(0).getElement(),
    -      goog.a11y.aria.getActiveDescendant(container.getElement()));
    -
    -  goog.testing.events.fireMouseOverEvent(
    -      container.getChildAt(1).getElement(),
    -      container.getChildAt(0).getElement());
    -  assertFalse('Child 0 should lose highlight when child 1 is moused ' +
    -      'over, even if no mouseout occurs.',
    -      container.getChildAt(0).isHighlighted());
    -  assertTrue('Child 1 should now be highlighted.',
    -      container.getChildAt(1).isHighlighted());
    -  assertEquals('Child 1 should be the active descendant',
    -      container.getChildAt(1).getElement(),
    -      goog.a11y.aria.getActiveDescendant(container.getElement()));
    -}
    -
    -function testHighlightOnEnterPreventable() {
    -  container.decorate(containerElement);
    -  goog.events.listen(container, goog.ui.Component.EventType.ENTER,
    -      function(event) {
    -        event.preventDefault();
    -      });
    -  goog.testing.events.fireMouseOverEvent(
    -      container.getChildAt(0).getElement(), sandbox);
    -  assertFalse('Child 0 should not be highlighted if preventDefault called',
    -      container.getChildAt(0).isHighlighted());
    -}
    -
    -function testHighlightDisabled() {
    -  // Another interaction test.  Already tested in control_test.
    -  container.decorate(containerElement);
    -  container.getChildAt(0).setEnabled(false);
    -  goog.testing.events.fireMouseOverEvent(
    -      container.getChildAt(0).getElement(), sandbox);
    -  assertFalse('Disabled children should not be highlighted',
    -      container.getChildAt(0).isHighlighted());
    -}
    -
    -function testGetOwnerControl() {
    -  container.decorate(containerElement);
    -
    -  assertEquals('Must return appropriate control given an element in the ' +
    -      'control.',
    -      container.getChildAt(1),
    -      container.getOwnerControl(container.getChildAt(1).getElement()));
    -
    -  assertNull('Must return null for element not associated with control.',
    -      container.getOwnerControl(document.body));
    -  assertNull('Must return null if given null node',
    -      container.getOwnerControl(null));
    -}
    -
    -function testShowEvent() {
    -  container.decorate(containerElement);
    -  container.setVisible(false);
    -  var eventFired = false;
    -  goog.events.listen(container, goog.ui.Component.EventType.SHOW,
    -      function() {
    -        assertFalse('Container must not be visible when SHOW event is ' +
    -                    'fired',
    -                    container.isVisible());
    -        eventFired = true;
    -      });
    -  container.setVisible(true);
    -  assertTrue('SHOW event expected', eventFired);
    -}
    -
    -function testAfterShowEvent() {
    -  container.decorate(containerElement);
    -  container.setVisible(false);
    -  var eventFired = false;
    -  goog.events.listen(container, goog.ui.Container.EventType.AFTER_SHOW,
    -      function() {
    -        assertTrue('Container must be visible when AFTER_SHOW event is ' +
    -                   'fired',
    -                   container.isVisible());
    -        eventFired = true;
    -      });
    -  container.setVisible(true);
    -  assertTrue('AFTER_SHOW event expected', eventFired);
    -}
    -
    -function testHideEvents() {
    -  var events = [];
    -  container.decorate(containerElement);
    -  container.setVisible(true);
    -  var eventFired = false;
    -  goog.events.listen(container, goog.ui.Component.EventType.HIDE,
    -      function(e) {
    -        assertTrue(
    -            'Container must be visible when HIDE event is fired',
    -            container.isVisible());
    -        events.push(e.type);
    -      });
    -  goog.events.listen(container, goog.ui.Container.EventType.AFTER_HIDE,
    -      function(e) {
    -        assertFalse(
    -            'Container must not be visible when AFTER_HIDE event is fired',
    -            container.isVisible());
    -        events.push(e.type);
    -      });
    -  container.setVisible(false);
    -  assertArrayEquals('HIDE event followed by AFTER_HIDE expected', [
    -    goog.ui.Component.EventType.HIDE,
    -    goog.ui.Container.EventType.AFTER_HIDE
    -  ], events);
    -}
    -
    -
    -
    -/**
    - * Test container to which the elements have to be added with
    - * {@code container.addChild(element, false)}
    - * @constructor
    - * @extends {goog.ui.Container}
    - */
    -function ListContainer() {
    -  goog.ui.Container.call(this);
    -}
    -goog.inherits(ListContainer, goog.ui.Container);
    -
    -
    -/** @override */
    -ListContainer.prototype.createDom = function() {
    -  ListContainer.superClass_.createDom.call(this);
    -  var ul = this.getDomHelper().createDom('ul');
    -  this.forEachChild(function(child) {
    -    child.createDom();
    -    var childEl = child.getElement();
    -    ul.appendChild(this.getDomHelper().createDom('li', {}, childEl));
    -  }, this);
    -  this.getContentElement().appendChild(ul);
    -};
    -
    -function testGetOwnerControlWithNoRenderingInAddChild() {
    -  listContainer = new ListContainer();
    -  var control = new goog.ui.Control('item');
    -  listContainer.addChild(control);
    -  listContainer.render();
    -  var ownerControl = listContainer.getOwnerControl(control.getElement());
    -
    -  assertEquals('Control was added with addChild(control, false)',
    -      control, ownerControl);
    -}
    -
    -
    -
    -/**
    - * Test container for tracking key events being handled.
    - * @constructor
    - * @extends {goog.ui.Container}
    - */
    -function KeyHandlingContainer() {
    -  goog.ui.Container.call(this);
    -  this.keyEventsHandled = 0;
    -}
    -goog.inherits(KeyHandlingContainer, goog.ui.Container);
    -
    -
    -/** @override */
    -KeyHandlingContainer.prototype.handleKeyEventInternal = function() {
    -  this.keyEventsHandled++;
    -  return false;
    -};
    -
    -function testHandleKeyEvent_onlyHandlesWhenVisible() {
    -  keyContainer = new KeyHandlingContainer();
    -  keyContainer.decorate(containerElement);
    -
    -  keyContainer.setVisible(false);
    -  keyContainer.handleKeyEvent(new goog.events.Event());
    -  assertEquals('No key events should be handled',
    -      0, keyContainer.keyEventsHandled);
    -
    -  keyContainer.setVisible(true);
    -  keyContainer.handleKeyEvent(new goog.events.Event());
    -  assertEquals('One key event should be handled',
    -      1, keyContainer.keyEventsHandled);
    -}
    -
    -function testHandleKeyEvent_onlyHandlesWhenEnabled() {
    -  keyContainer = new KeyHandlingContainer();
    -  keyContainer.decorate(containerElement);
    -  keyContainer.setVisible(true);
    -
    -  keyContainer.setEnabled(false);
    -  keyContainer.handleKeyEvent(new goog.events.Event());
    -  assertEquals('No key events should be handled',
    -      0, keyContainer.keyEventsHandled);
    -
    -  keyContainer.setEnabled(true);
    -  keyContainer.handleKeyEvent(new goog.events.Event());
    -  assertEquals('One key event should be handled',
    -      1, keyContainer.keyEventsHandled);
    -}
    -
    -function testHandleKeyEvent_childlessContainersIgnoreKeyEvents() {
    -  keyContainer = new KeyHandlingContainer();
    -  keyContainer.render();
    -  keyContainer.setVisible(true);
    -
    -  keyContainer.handleKeyEvent(new goog.events.Event());
    -  assertEquals('No key events should be handled',
    -      0, keyContainer.keyEventsHandled);
    -
    -  keyContainer.addChild(new goog.ui.Control());
    -  keyContainer.handleKeyEvent(new goog.events.Event());
    -  assertEquals('One key event should be handled',
    -      1, keyContainer.keyEventsHandled);
    -}
    -
    -function testHandleKeyEvent_alwaysHandlesWithKeyEventTarget() {
    -  keyContainer = new KeyHandlingContainer();
    -  keyContainer.render();
    -  keyContainer.setKeyEventTarget(goog.dom.createDom('div'));
    -  keyContainer.setVisible(true);
    -
    -  keyContainer.handleKeyEvent(new goog.events.Event());
    -  assertEquals('One key events should be handled',
    -      1, keyContainer.keyEventsHandled);
    -}
    -
    -function testHandleKeyEventInternal_onlyHandlesUnmodified() {
    -  container.setKeyEventTarget(sandbox);
    -  var event = new goog.events.KeyEvent(
    -      goog.events.KeyCodes.ESC, 0, false, null);
    -
    -  var propertyNames = [
    -    'shiftKey',
    -    'altKey',
    -    'ctrlKey',
    -    'metaKey'
    -  ];
    -
    -  // Verify that the event is not handled whenever a modifier key is true.
    -  for (var i = 0, propertyName; propertyName = propertyNames[i]; i++) {
    -    assertTrue('Event should be handled when modifer key is not pressed.',
    -        container.handleKeyEventInternal(event));
    -    event[propertyName] = true;
    -    assertFalse('Event should not be handled when modifer key is pressed.',
    -        container.handleKeyEventInternal(event));
    -    event[propertyName] = false;
    -  }
    -}
    -
    -function testOpenFollowsHighlight() {
    -  container.decorate(containerElement);
    -  container.setOpenFollowsHighlight(true);
    -  assertTrue('isOpenFollowsHighlight should return true',
    -      container.isOpenFollowsHighlight());
    -
    -  // Make the children openable.
    -  container.forEachChild(function(child) {
    -    child.setSupportedState(goog.ui.Component.State.OPENED, true);
    -  });
    -  // Open child 1 initially.
    -  container.getChildAt(1).setOpen(true);
    -
    -  assertFalse('Child 0 should initially not be highlighted',
    -      container.getChildAt(0).isHighlighted());
    -  goog.testing.events.fireMouseOverEvent(
    -      container.getChildAt(0).getElement(), sandbox);
    -  assertTrue('Child 0 should become highlighted after a mouse over',
    -      container.getChildAt(0).isHighlighted());
    -  assertTrue('Child 0 should become open after higlighted',
    -      container.getChildAt(0).isOpen());
    -  assertFalse('Child 1 should become closed once 0 is open',
    -      container.getChildAt(1).isOpen());
    -  assertEquals('OpenItem should be child 0',
    -      container.getChildAt(0), container.getOpenItem());
    -}
    -
    -function testOpenNotFollowsHighlight() {
    -  container.decorate(containerElement);
    -  container.setOpenFollowsHighlight(false);
    -  assertFalse('isOpenFollowsHighlight should return false',
    -      container.isOpenFollowsHighlight());
    -
    -  // Make the children openable.
    -  container.forEachChild(function(child) {
    -    child.setSupportedState(goog.ui.Component.State.OPENED, true);
    -  });
    -  // Open child 1 initially.
    -  container.getChildAt(1).setOpen(true);
    -
    -  assertFalse('Child 0 should initially not be highlighted',
    -      container.getChildAt(0).isHighlighted());
    -  goog.testing.events.fireMouseOverEvent(
    -      container.getChildAt(0).getElement(), sandbox);
    -  assertTrue('Child 0 should become highlighted after a mouse over',
    -      container.getChildAt(0).isHighlighted());
    -  assertFalse('Child 0 should remain closed after higlighted',
    -      container.getChildAt(0).isOpen());
    -  assertTrue('Child 1 should remain open',
    -      container.getChildAt(1).isOpen());
    -  assertEquals('OpenItem should be child 1',
    -      container.getChildAt(1), container.getOpenItem());
    -}
    -
    -function testRemoveChild() {
    -  goog.dom.removeChildren(containerElement);
    -  container.decorate(containerElement);
    -
    -  var a = new goog.ui.Control('A');
    -  var b = new goog.ui.Control('B');
    -  var c = new goog.ui.Control('C');
    -
    -  a.setId('a');
    -  b.setId('b');
    -  c.setId('c');
    -
    -  container.addChild(a, true);
    -  container.addChild(b, true);
    -  container.addChild(c, true);
    -
    -  container.setHighlightedIndex(2);
    -
    -  assertEquals('Parent must remove and return child by ID', b,
    -      container.removeChild('b'));
    -  assertNull('Parent must no longer contain this child',
    -      container.getChild('b'));
    -  assertEquals('Highlighted index must be decreased', 1,
    -      container.getHighlightedIndex());
    -  assertTrue('The removed control must handle its own mouse events',
    -      b.isHandleMouseEvents());
    -
    -  assertEquals('Parent must remove and return child', c,
    -      container.removeChild(c));
    -  assertNull('Parent must no longer contain this child',
    -      container.getChild('c'));
    -  assertFalse('This child must no longer be highlighted',
    -      c.isHighlighted());
    -  assertTrue('The removed control must handle its own mouse events',
    -      c.isHandleMouseEvents());
    -
    -  assertEquals('Parent must remove and return child by index', a,
    -      container.removeChildAt(0));
    -  assertNull('Parent must no longer contain this child',
    -      container.getChild('a'));
    -  assertTrue('The removed control must handle its own mouse events',
    -      a.isHandleMouseEvents());
    -}
    -
    -function testRemoveHighlightedDisposedChild() {
    -  goog.dom.removeChildren(containerElement);
    -  container.decorate(containerElement);
    -
    -  var a = new goog.ui.Control('A');
    -  container.addChild(a, true);
    -
    -  container.setHighlightedIndex(0);
    -  a.dispose();
    -  container.removeChild(a);
    -  container.dispose();
    -}
    -
    -
    -/**
    - * Checks that getHighlighted() returns the expected value and checks
    - * that the child at this index is highlighted and other children are not.
    - * @param {string} explanation Message indicating what is expected.
    - * @param {number} index Expected return value of getHighlightedIndex().
    - */
    -function assertHighlightedIndex(explanation, index) {
    -  assertEquals(explanation, index, container.getHighlightedIndex());
    -  for (var i = 0; i < container.getChildCount(); i++) {
    -    if (i == index) {
    -      assertTrue('Child at highlighted index should be highlighted',
    -          container.getChildAt(i).isHighlighted());
    -    } else {
    -      assertFalse('Only child at highlighted index should be highlighted',
    -          container.getChildAt(i).isHighlighted());
    -    }
    -  }
    -}
    -
    -function testUpdateHighlightedIndex_updatesWhenChildrenAreAdded() {
    -  goog.dom.removeChildren(containerElement);
    -  container.decorate(containerElement);
    -
    -  var a = new goog.ui.Control('A');
    -  var b = new goog.ui.Control('B');
    -  var c = new goog.ui.Control('C');
    -
    -  container.addChild(a);
    -  container.setHighlightedIndex(0);
    -  assertHighlightedIndex('Highlighted index should match set value', 0);
    -
    -  // Add child before the highlighted one.
    -  container.addChildAt(b, 0);
    -  assertHighlightedIndex('Highlighted index should be increased', 1);
    -
    -  // Add child after the highlighted one.
    -  container.addChildAt(c, 2);
    -  assertHighlightedIndex('Highlighted index should not change', 1);
    -
    -  container.dispose();
    -}
    -
    -function testUpdateHighlightedIndex_updatesWhenChildrenAreMoved() {
    -  goog.dom.removeChildren(containerElement);
    -  container.decorate(containerElement);
    -
    -  var a = new goog.ui.Control('A');
    -  var b = new goog.ui.Control('B');
    -  var c = new goog.ui.Control('C');
    -
    -  container.addChild(a);
    -  container.addChild(b);
    -  container.addChild(c);
    -
    -  // Highlight 'c' and swap 'a' and 'b'
    -  // [a, b, c] -> [a, b, *c] -> [b, a, *c] (* indicates the highlighted child)
    -  container.setHighlightedIndex(2);
    -  container.addChildAt(a, 1, false);
    -  assertHighlightedIndex('Highlighted index should not change', 2);
    -
    -  // Move the highlighted child 'c' from index 2 to index 1.
    -  // [b, a, *c] -> [b, *c, a]
    -  container.addChildAt(c, 1, false);
    -  assertHighlightedIndex('Highlighted index must follow the moved child', 1);
    -
    -  // Take the element in front of the highlighted index and move it behind it.
    -  // [b, *c, a] -> [*c, a, b]
    -  container.addChildAt(b, 2, false);
    -  assertHighlightedIndex('Highlighted index must be decreased', 0);
    -
    -  // And move the element back to the front.
    -  // [*c, a, b] -> [b, *c, a]
    -  container.addChildAt(b, 0, false);
    -  assertHighlightedIndex('Highlighted index must be increased', 1);
    -
    -  container.dispose();
    -}
    -
    -function testUpdateHighlightedIndex_notChangedOnNoOp() {
    -  goog.dom.removeChildren(containerElement);
    -  container.decorate(containerElement);
    -
    -  container.addChild(new goog.ui.Control('A'));
    -  container.addChild(new goog.ui.Control('B'));
    -  container.setHighlightedIndex(1);
    -
    -  // Re-add a child to its current position.
    -  container.addChildAt(container.getChildAt(0), 0, false);
    -  assertHighlightedIndex('Highlighted index must not change', 1);
    -
    -  container.dispose();
    -}
    -
    -function testUpdateHighlightedIndex_notChangedWhenNoChildSelected() {
    -  goog.dom.removeChildren(containerElement);
    -  container.decorate(containerElement);
    -
    -  var a = new goog.ui.Control('A');
    -  var b = new goog.ui.Control('B');
    -  var c = new goog.ui.Control('C');
    -  container.addChild(a);
    -  container.addChild(b);
    -  container.addChild(c);
    -
    -  // Move children around.
    -  container.addChildAt(a, 2, false);
    -  container.addChildAt(b, 1, false);
    -  container.addChildAt(c, 2, false);
    -
    -  assertHighlightedIndex('Highlighted index must not change', -1);
    -
    -  container.dispose();
    -}
    -
    -function testUpdateHighlightedIndex_indexStaysInBoundsWhenMovedToMaxIndex() {
    -  goog.dom.removeChildren(containerElement);
    -  container.decorate(containerElement);
    -
    -  var a = new goog.ui.Control('A');
    -  var b = new goog.ui.Control('B');
    -  container.addChild(a);
    -  container.addChild(b);
    -
    -  // Move higlighted child to an index one behind last child.
    -  container.setHighlightedIndex(0);
    -  container.addChildAt(a, 2);
    -
    -  assertEquals('Child should be moved to index 1', a, container.getChildAt(1));
    -  assertEquals('Child count should not change', 2, container.getChildCount());
    -  assertHighlightedIndex('Highlighted index must point to new index', 1);
    -
    -  container.dispose();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/containerrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/containerrenderer.js
    deleted file mode 100644
    index c6ac213fdd0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/containerrenderer.js
    +++ /dev/null
    @@ -1,374 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Base class for container renderers.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.ContainerRenderer');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.dom.NodeType');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.string');
    -goog.require('goog.style');
    -goog.require('goog.ui.registry');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Default renderer for {@link goog.ui.Container}.  Can be used as-is, but
    - * subclasses of Container will probably want to use renderers specifically
    - * tailored for them by extending this class.
    - * @param {string=} opt_ariaRole Optional ARIA role used for the element.
    - * @constructor
    - */
    -goog.ui.ContainerRenderer = function(opt_ariaRole) {
    -  // By default, the ARIA role is unspecified.
    -  /** @private {string|undefined} */
    -  this.ariaRole_ = opt_ariaRole;
    -};
    -goog.addSingletonGetter(goog.ui.ContainerRenderer);
    -
    -
    -/**
    - * Constructs a new renderer and sets the CSS class that the renderer will use
    - * as the base CSS class to apply to all elements rendered by that renderer.
    - * An example to use this function using a menu is:
    - *
    - * <pre>
    - * var myCustomRenderer = goog.ui.ContainerRenderer.getCustomRenderer(
    - *     goog.ui.MenuRenderer, 'my-special-menu');
    - * var newMenu = new goog.ui.Menu(opt_domHelper, myCustomRenderer);
    - * </pre>
    - *
    - * Your styles for the menu can now be:
    - * <pre>
    - * .my-special-menu { }
    - * </pre>
    - *
    - * <em>instead</em> of
    - * <pre>
    - * .CSS_MY_SPECIAL_MENU .goog-menu { }
    - * </pre>
    - *
    - * You would want to use this functionality when you want an instance of a
    - * component to have specific styles different than the other components of the
    - * same type in your application.  This avoids using descendant selectors to
    - * apply the specific styles to this component.
    - *
    - * @param {Function} ctor The constructor of the renderer you want to create.
    - * @param {string} cssClassName The name of the CSS class for this renderer.
    - * @return {goog.ui.ContainerRenderer} An instance of the desired renderer with
    - *     its getCssClass() method overridden to return the supplied custom CSS
    - *     class name.
    - */
    -goog.ui.ContainerRenderer.getCustomRenderer = function(ctor, cssClassName) {
    -  var renderer = new ctor();
    -
    -  /**
    -   * Returns the CSS class to be applied to the root element of components
    -   * rendered using this renderer.
    -   * @return {string} Renderer-specific CSS class.
    -   */
    -  renderer.getCssClass = function() {
    -    return cssClassName;
    -  };
    -
    -  return renderer;
    -};
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of containers rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.ContainerRenderer.CSS_CLASS = goog.getCssName('goog-container');
    -
    -
    -/**
    - * Returns the ARIA role to be applied to the container.
    - * See http://wiki/Main/ARIA for more info.
    - * @return {undefined|string} ARIA role.
    - */
    -goog.ui.ContainerRenderer.prototype.getAriaRole = function() {
    -  return this.ariaRole_;
    -};
    -
    -
    -/**
    - * Enables or disables the tab index of the element.  Only elements with a
    - * valid tab index can receive focus.
    - * @param {Element} element Element whose tab index is to be changed.
    - * @param {boolean} enable Whether to add or remove the element's tab index.
    - */
    -goog.ui.ContainerRenderer.prototype.enableTabIndex = function(element, enable) {
    -  if (element) {
    -    element.tabIndex = enable ? 0 : -1;
    -  }
    -};
    -
    -
    -/**
    - * Creates and returns the container's root element.  The default
    - * simply creates a DIV and applies the renderer's own CSS class name to it.
    - * To be overridden in subclasses.
    - * @param {goog.ui.Container} container Container to render.
    - * @return {Element} Root element for the container.
    - */
    -goog.ui.ContainerRenderer.prototype.createDom = function(container) {
    -  return container.getDomHelper().createDom('div',
    -      this.getClassNames(container).join(' '));
    -};
    -
    -
    -/**
    - * Returns the DOM element into which child components are to be rendered,
    - * or null if the container hasn't been rendered yet.
    - * @param {Element} element Root element of the container whose content element
    - *     is to be returned.
    - * @return {Element} Element to contain child elements (null if none).
    - */
    -goog.ui.ContainerRenderer.prototype.getContentElement = function(element) {
    -  return element;
    -};
    -
    -
    -/**
    - * Default implementation of {@code canDecorate}; returns true if the element
    - * is a DIV, false otherwise.
    - * @param {Element} element Element to decorate.
    - * @return {boolean} Whether the renderer can decorate the element.
    - */
    -goog.ui.ContainerRenderer.prototype.canDecorate = function(element) {
    -  return element.tagName == 'DIV';
    -};
    -
    -
    -/**
    - * Default implementation of {@code decorate} for {@link goog.ui.Container}s.
    - * Decorates the element with the container, and attempts to decorate its child
    - * elements.  Returns the decorated element.
    - * @param {goog.ui.Container} container Container to decorate the element.
    - * @param {Element} element Element to decorate.
    - * @return {!Element} Decorated element.
    - */
    -goog.ui.ContainerRenderer.prototype.decorate = function(container, element) {
    -  // Set the container's ID to the decorated element's DOM ID, if any.
    -  if (element.id) {
    -    container.setId(element.id);
    -  }
    -
    -  // Configure the container's state based on the CSS class names it has.
    -  var baseClass = this.getCssClass();
    -  var hasBaseClass = false;
    -  var classNames = goog.dom.classlist.get(element);
    -  if (classNames) {
    -    goog.array.forEach(classNames, function(className) {
    -      if (className == baseClass) {
    -        hasBaseClass = true;
    -      } else if (className) {
    -        this.setStateFromClassName(container, className, baseClass);
    -      }
    -    }, this);
    -  }
    -
    -  if (!hasBaseClass) {
    -    // Make sure the container's root element has the renderer's own CSS class.
    -    goog.dom.classlist.add(element, baseClass);
    -  }
    -
    -  // Decorate the element's children, if applicable.  This should happen after
    -  // the container's own state has been initialized, since how children are
    -  // decorated may depend on the state of the container.
    -  this.decorateChildren(container, this.getContentElement(element));
    -
    -  return element;
    -};
    -
    -
    -/**
    - * Sets the container's state based on the given CSS class name, encountered
    - * during decoration.  CSS class names that don't represent container states
    - * are ignored.  Considered protected; subclasses should override this method
    - * to support more states and CSS class names.
    - * @param {goog.ui.Container} container Container to update.
    - * @param {string} className CSS class name.
    - * @param {string} baseClass Base class name used as the root of state-specific
    - *     class names (typically the renderer's own class name).
    - * @protected
    - */
    -goog.ui.ContainerRenderer.prototype.setStateFromClassName = function(container,
    -    className, baseClass) {
    -  if (className == goog.getCssName(baseClass, 'disabled')) {
    -    container.setEnabled(false);
    -  } else if (className == goog.getCssName(baseClass, 'horizontal')) {
    -    container.setOrientation(goog.ui.Container.Orientation.HORIZONTAL);
    -  } else if (className == goog.getCssName(baseClass, 'vertical')) {
    -    container.setOrientation(goog.ui.Container.Orientation.VERTICAL);
    -  }
    -};
    -
    -
    -/**
    - * Takes a container and an element that may contain child elements, decorates
    - * the child elements, and adds the corresponding components to the container
    - * as child components.  Any non-element child nodes (e.g. empty text nodes
    - * introduced by line breaks in the HTML source) are removed from the element.
    - * @param {goog.ui.Container} container Container whose children are to be
    - *     discovered.
    - * @param {Element} element Element whose children are to be decorated.
    - * @param {Element=} opt_firstChild the first child to be decorated.
    - */
    -goog.ui.ContainerRenderer.prototype.decorateChildren = function(container,
    -    element, opt_firstChild) {
    -  if (element) {
    -    var node = opt_firstChild || element.firstChild, next;
    -    // Tag soup HTML may result in a DOM where siblings have different parents.
    -    while (node && node.parentNode == element) {
    -      // Get the next sibling here, since the node may be replaced or removed.
    -      next = node.nextSibling;
    -      if (node.nodeType == goog.dom.NodeType.ELEMENT) {
    -        // Decorate element node.
    -        var child = this.getDecoratorForChild(/** @type {!Element} */(node));
    -        if (child) {
    -          // addChild() may need to look at the element.
    -          child.setElementInternal(/** @type {!Element} */(node));
    -          // If the container is disabled, mark the child disabled too.  See
    -          // bug 1263729.  Note that this must precede the call to addChild().
    -          if (!container.isEnabled()) {
    -            child.setEnabled(false);
    -          }
    -          container.addChild(child);
    -          child.decorate(/** @type {!Element} */(node));
    -        }
    -      } else if (!node.nodeValue || goog.string.trim(node.nodeValue) == '') {
    -        // Remove empty text node, otherwise madness ensues (e.g. controls that
    -        // use goog-inline-block will flicker and shift on hover on Gecko).
    -        element.removeChild(node);
    -      }
    -      node = next;
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Inspects the element, and creates an instance of {@link goog.ui.Control} or
    - * an appropriate subclass best suited to decorate it.  Returns the control (or
    - * null if no suitable class was found).  This default implementation uses the
    - * element's CSS class to find the appropriate control class to instantiate.
    - * May be overridden in subclasses.
    - * @param {Element} element Element to decorate.
    - * @return {goog.ui.Control?} A new control suitable to decorate the element
    - *     (null if none).
    - */
    -goog.ui.ContainerRenderer.prototype.getDecoratorForChild = function(element) {
    -  return /** @type {goog.ui.Control} */ (
    -      goog.ui.registry.getDecorator(element));
    -};
    -
    -
    -/**
    - * Initializes the container's DOM when the container enters the document.
    - * Called from {@link goog.ui.Container#enterDocument}.
    - * @param {goog.ui.Container} container Container whose DOM is to be initialized
    - *     as it enters the document.
    - */
    -goog.ui.ContainerRenderer.prototype.initializeDom = function(container) {
    -  var elem = container.getElement();
    -  goog.asserts.assert(elem, 'The container DOM element cannot be null.');
    -  // Make sure the container's element isn't selectable.  On Gecko, recursively
    -  // marking each child element unselectable is expensive and unnecessary, so
    -  // only mark the root element unselectable.
    -  goog.style.setUnselectable(elem, true, goog.userAgent.GECKO);
    -
    -  // IE doesn't support outline:none, so we have to use the hideFocus property.
    -  if (goog.userAgent.IE) {
    -    elem.hideFocus = true;
    -  }
    -
    -  // Set the ARIA role.
    -  var ariaRole = this.getAriaRole();
    -  if (ariaRole) {
    -    goog.a11y.aria.setRole(elem, ariaRole);
    -  }
    -};
    -
    -
    -/**
    - * Returns the element within the container's DOM that should receive keyboard
    - * focus (null if none).  The default implementation returns the container's
    - * root element.
    - * @param {goog.ui.Container} container Container whose key event target is
    - *     to be returned.
    - * @return {Element} Key event target (null if none).
    - */
    -goog.ui.ContainerRenderer.prototype.getKeyEventTarget = function(container) {
    -  return container.getElement();
    -};
    -
    -
    -/**
    - * Returns the CSS class to be applied to the root element of containers
    - * rendered using this renderer.
    - * @return {string} Renderer-specific CSS class.
    - */
    -goog.ui.ContainerRenderer.prototype.getCssClass = function() {
    -  return goog.ui.ContainerRenderer.CSS_CLASS;
    -};
    -
    -
    -/**
    - * Returns all CSS class names applicable to the given container, based on its
    - * state.  The array of class names returned includes the renderer's own CSS
    - * class, followed by a CSS class indicating the container's orientation,
    - * followed by any state-specific CSS classes.
    - * @param {goog.ui.Container} container Container whose CSS classes are to be
    - *     returned.
    - * @return {!Array<string>} Array of CSS class names applicable to the
    - *     container.
    - */
    -goog.ui.ContainerRenderer.prototype.getClassNames = function(container) {
    -  var baseClass = this.getCssClass();
    -  var isHorizontal =
    -      container.getOrientation() == goog.ui.Container.Orientation.HORIZONTAL;
    -  var classNames = [
    -    baseClass,
    -    (isHorizontal ?
    -        goog.getCssName(baseClass, 'horizontal') :
    -        goog.getCssName(baseClass, 'vertical'))
    -  ];
    -  if (!container.isEnabled()) {
    -    classNames.push(goog.getCssName(baseClass, 'disabled'));
    -  }
    -  return classNames;
    -};
    -
    -
    -/**
    - * Returns the default orientation of containers rendered or decorated by this
    - * renderer.  The base class implementation returns {@code VERTICAL}.
    - * @return {goog.ui.Container.Orientation} Default orientation for containers
    - *     created or decorated by this renderer.
    - */
    -goog.ui.ContainerRenderer.prototype.getDefaultOrientation = function() {
    -  return goog.ui.Container.Orientation.VERTICAL;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/containerrenderer_test.html b/src/database/third_party/closure-library/closure/goog/ui/containerrenderer_test.html
    deleted file mode 100644
    index b1dd9ac6475..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/containerrenderer_test.html
    +++ /dev/null
    @@ -1,27 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -Author:  attila@google.com (Attila Bodis)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.ContainerRenderer
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.ContainerRendererTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="sandbox">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/containerrenderer_test.js b/src/database/third_party/closure-library/closure/goog/ui/containerrenderer_test.js
    deleted file mode 100644
    index 4eef812f98a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/containerrenderer_test.js
    +++ /dev/null
    @@ -1,225 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.ContainerRendererTest');
    -goog.setTestOnly('goog.ui.ContainerRendererTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.style');
    -goog.require('goog.testing.ExpectedFailures');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.ui.rendererasserts');
    -goog.require('goog.ui.Container');
    -goog.require('goog.ui.ContainerRenderer');
    -goog.require('goog.userAgent');
    -
    -var renderer;
    -var expectedFailures;
    -var stubs = new goog.testing.PropertyReplacer();
    -
    -function setUpPage() {
    -  expectedFailures = new goog.testing.ExpectedFailures();
    -}
    -
    -function setUp() {
    -  var sandbox = goog.dom.getElement('sandbox');
    -
    -  sandbox.appendChild(goog.dom.createDom('span', {
    -    id: 'noTabIndex'
    -  }, 'Test'));
    -  sandbox.appendChild(goog.dom.createDom('div', {
    -    id: 'container',
    -    'class': 'goog-container-horizontal'
    -  }, goog.dom.createDom('div', {
    -    id: 'control',
    -    'class': 'goog-control'
    -  }, 'Hello, world!')));
    -
    -  renderer = goog.ui.ContainerRenderer.getInstance();
    -}
    -
    -function tearDown() {
    -  goog.dom.getElement('sandbox').innerHTML = '';
    -  stubs.reset();
    -  expectedFailures.handleTearDown();
    -}
    -
    -function testGetInstance() {
    -  assertTrue('getInstance() must return a ContainerRenderer',
    -      renderer instanceof goog.ui.ContainerRenderer);
    -  assertEquals('getInstance() must return the same object each time',
    -      renderer, goog.ui.ContainerRenderer.getInstance());
    -}
    -
    -function testGetCustomRenderer() {
    -  var cssClass = 'special-css-class';
    -  var containerRenderer = goog.ui.ContainerRenderer.getCustomRenderer(
    -      goog.ui.ContainerRenderer, cssClass);
    -  assertEquals(
    -      'Renderer should have returned the custom CSS class.',
    -      cssClass,
    -      containerRenderer.getCssClass());
    -}
    -
    -function testGetAriaRole() {
    -  assertUndefined('ARIA role must be undefined', renderer.getAriaRole());
    -}
    -
    -function testEnableTabIndex() {
    -  var container = goog.dom.getElement('container');
    -  assertFalse('Container must not have any tab index',
    -      goog.dom.isFocusableTabIndex(container));
    -
    -  // WebKit on Mac doesn't support tabIndex for arbitrary DOM elements
    -  // until version 527 or later.
    -  expectedFailures.expectFailureFor(goog.userAgent.WEBKIT &&
    -      goog.userAgent.MAC && !goog.userAgent.isVersionOrHigher('527'));
    -  try {
    -    renderer.enableTabIndex(container, true);
    -    assertTrue('Container must have a tab index',
    -        goog.dom.isFocusableTabIndex(container));
    -    assertEquals('Container\'s tab index must be 0', 0, container.tabIndex);
    -
    -    renderer.enableTabIndex(container, false);
    -    assertFalse('Container must not have a tab index',
    -        goog.dom.isFocusableTabIndex(container));
    -    assertEquals('Container\'s tab index must be -1', -1,
    -        container.tabIndex);
    -  } catch (e) {
    -    expectedFailures.handleException(e);
    -  }
    -}
    -
    -function testCreateDom() {
    -  var horizontal = new goog.ui.Container(
    -      goog.ui.Container.Orientation.HORIZONTAL);
    -  var element1 = renderer.createDom(horizontal);
    -  assertEquals('Element must be a DIV', 'DIV', element1.tagName);
    -  assertEquals('Element must have the expected class name',
    -      'goog-container goog-container-horizontal',
    -      element1.className);
    -
    -  var vertical = new goog.ui.Container(
    -      goog.ui.Container.Orientation.VERTICAL);
    -  var element2 = renderer.createDom(vertical);
    -  assertEquals('Element must be a DIV', 'DIV', element2.tagName);
    -  assertEquals('Element must have the expected class name',
    -      'goog-container goog-container-vertical',
    -      element2.className);
    -}
    -
    -function testGetContentElement() {
    -  assertNull('getContentElement() must return null if element is null',
    -      renderer.getContentElement(null));
    -  var element = goog.dom.getElement('container');
    -  assertEquals('getContentElement() must return its argument',
    -      element, renderer.getContentElement(element));
    -}
    -
    -function testCanDecorate() {
    -  assertFalse('canDecorate() must return false for a SPAN',
    -      renderer.canDecorate(goog.dom.getElement('noTabIndex')));
    -  assertTrue('canDecorate() must return true for a DIV',
    -      renderer.canDecorate(goog.dom.getElement('container')));
    -}
    -
    -function testDecorate() {
    -  var container = new goog.ui.Container();
    -  var element = goog.dom.getElement('container');
    -
    -  assertFalse('Container must not be in the document',
    -      container.isInDocument());
    -  container.decorate(element);
    -  assertTrue('Container must be in the document',
    -      container.isInDocument());
    -
    -  assertEquals('Container\'s ID must match the decorated element\'s ID',
    -      element.id, container.getId());
    -  assertEquals('Element must have the expected class name',
    -      'goog-container-horizontal goog-container', element.className);
    -  assertEquals('Container must have one child', 1,
    -      container.getChildCount());
    -  assertEquals('Child component\'s ID must be as expected', 'control',
    -      container.getChildAt(0).getId());
    -
    -  assertThrows('Redecorating must throw error', function() {
    -    container.decorate(element);
    -  });
    -}
    -
    -function testDecorateWithCustomContainerElement() {
    -  var element = goog.dom.getElement('container');
    -  var alternateContainerElement = goog.dom.createElement('div');
    -  element.appendChild(alternateContainerElement);
    -
    -  var container = new goog.ui.Container();
    -  stubs.set(renderer, 'getContentElement', function() {
    -    return alternateContainerElement;
    -  });
    -
    -  assertFalse('Container must not be in the document',
    -      container.isInDocument());
    -  container.decorate(element);
    -  assertTrue('Container must be in the document',
    -      container.isInDocument());
    -
    -  assertEquals('Container\'s ID must match the decorated element\'s ID',
    -      element.id, container.getId());
    -  assertEquals('Element must have the expected class name',
    -      'goog-container-horizontal goog-container', element.className);
    -  assertEquals('Container must have 0 children', 0,
    -      container.getChildCount());
    -
    -  assertThrows('Redecorating must throw error', function() {
    -    container.decorate(element);
    -  });
    -}
    -
    -function testSetStateFromClassName() {
    -  var container = new goog.ui.Container();
    -
    -  assertEquals('Container must be vertical',
    -      goog.ui.Container.Orientation.VERTICAL, container.getOrientation());
    -  renderer.setStateFromClassName(container, 'goog-container-horizontal',
    -      'goog-container');
    -  assertEquals('Container must be horizontal',
    -      goog.ui.Container.Orientation.HORIZONTAL, container.getOrientation());
    -  renderer.setStateFromClassName(container, 'goog-container-vertical',
    -      'goog-container');
    -  assertEquals('Container must be vertical',
    -      goog.ui.Container.Orientation.VERTICAL, container.getOrientation());
    -
    -  assertTrue('Container must be enabled', container.isEnabled());
    -  renderer.setStateFromClassName(container, 'goog-container-disabled',
    -      'goog-container');
    -  assertFalse('Container must be disabled', container.isEnabled());
    -}
    -
    -function testInitializeDom() {
    -  var container = new goog.ui.Container();
    -  var element = goog.dom.getElement('container');
    -  container.decorate(element);
    -
    -  assertTrue('Container\'s root element must be unselectable',
    -      goog.style.isUnselectable(container.getElement()));
    -
    -  assertEquals('On IE, container\'s root element must have hideFocus=true',
    -      goog.userAgent.IE, !!container.getElement().hideFocus);
    -}
    -
    -function testDoesntCallGetCssClassInConstructor() {
    -  goog.testing.ui.rendererasserts.
    -      assertNoGetCssClassCallsInConstructor(goog.ui.ContainerRenderer);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/containerscroller.js b/src/database/third_party/closure-library/closure/goog/ui/containerscroller.js
    deleted file mode 100644
    index c67a94566b4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/containerscroller.js
    +++ /dev/null
    @@ -1,223 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Scroll behavior that can be added onto a container.
    - * @author gboyer@google.com (Garry Boyer)
    - */
    -
    -goog.provide('goog.ui.ContainerScroller');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.Timer');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.style');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.Container');
    -
    -
    -
    -/**
    - * Plug-on scrolling behavior for a container.
    - *
    - * Use this to style containers, such as pop-up menus, to be scrolling, and
    - * automatically keep the highlighted element visible.
    - *
    - * To use this, first style your container with the desired overflow
    - * properties and height to achieve vertical scrolling.  Also, the scrolling
    - * div should have no vertical padding, for two reasons: it is difficult to
    - * compensate for, and is generally not what you want due to the strange way
    - * CSS handles padding on the scrolling dimension.
    - *
    - * The container must already be rendered before this may be constructed.
    - *
    - * @param {!goog.ui.Container} container The container to attach behavior to.
    - * @constructor
    - * @extends {goog.Disposable}
    - * @final
    - */
    -goog.ui.ContainerScroller = function(container) {
    -  goog.Disposable.call(this);
    -
    -  /**
    -   * The container that we are bestowing scroll behavior on.
    -   * @type {!goog.ui.Container}
    -   * @private
    -   */
    -  this.container_ = container;
    -
    -  /**
    -   * Event handler for this object.
    -   * @type {!goog.events.EventHandler<!goog.ui.ContainerScroller>}
    -   * @private
    -   */
    -  this.eventHandler_ = new goog.events.EventHandler(this);
    -
    -  this.eventHandler_.listen(container, goog.ui.Component.EventType.HIGHLIGHT,
    -      this.onHighlight_);
    -  this.eventHandler_.listen(container, goog.ui.Component.EventType.ENTER,
    -      this.onEnter_);
    -  this.eventHandler_.listen(container, goog.ui.Container.EventType.AFTER_SHOW,
    -      this.onAfterShow_);
    -  this.eventHandler_.listen(container, goog.ui.Component.EventType.HIDE,
    -      this.onHide_);
    -
    -  // TODO(gboyer): Allow a ContainerScroller to be attached with a Container
    -  // before the container is rendered.
    -
    -  this.doScrolling_(true);
    -};
    -goog.inherits(goog.ui.ContainerScroller, goog.Disposable);
    -
    -
    -/**
    - * The last target the user hovered over.
    - *
    - * @see #onEnter_
    - * @type {goog.ui.Component}
    - * @private
    - */
    -goog.ui.ContainerScroller.prototype.lastEnterTarget_ = null;
    -
    -
    -/**
    - * The scrollTop of the container before it was hidden.
    - * Used to restore the scroll position when the container is shown again.
    - * @type {?number}
    - * @private
    - */
    -goog.ui.ContainerScroller.prototype.scrollTopBeforeHide_ = null;
    -
    -
    -/**
    - * Whether we are disabling the default handler for hovering.
    - *
    - * @see #onEnter_
    - * @see #temporarilyDisableHover_
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.ContainerScroller.prototype.disableHover_ = false;
    -
    -
    -/**
    - * Handles hover events on the container's children.
    - *
    - * Helps enforce two constraints: scrolling should not cause mouse highlights,
    - * and mouse highlights should not cause scrolling.
    - *
    - * @param {goog.events.Event} e The container's ENTER event.
    - * @private
    - */
    -goog.ui.ContainerScroller.prototype.onEnter_ = function(e) {
    -  if (this.disableHover_) {
    -    // The container was scrolled recently.  Since the mouse may be over the
    -    // container, stop the default action of the ENTER event from causing
    -    // highlights.
    -    e.preventDefault();
    -  } else {
    -    // The mouse is moving and causing hover events.  Stop the resulting
    -    // highlight (if it happens) from causing a scroll.
    -    this.lastEnterTarget_ = /** @type {goog.ui.Component} */ (e.target);
    -  }
    -};
    -
    -
    -/**
    - * Handles highlight events on the container's children.
    - * @param {goog.events.Event} e The container's highlight event.
    - * @private
    - */
    -goog.ui.ContainerScroller.prototype.onHighlight_ = function(e) {
    -  this.doScrolling_();
    -};
    -
    -
    -/**
    - * Handles AFTER_SHOW events on the container. Makes the container
    - * scroll to the previously scrolled position (if there was one),
    - * then adjust it to make the highlighted element be in view (if there is one).
    - * If there was no previous scroll position, then center the highlighted
    - * element (if there is one).
    - * @param {goog.events.Event} e The container's AFTER_SHOW event.
    - * @private
    - */
    -goog.ui.ContainerScroller.prototype.onAfterShow_ = function(e) {
    -  if (this.scrollTopBeforeHide_ != null) {
    -    this.container_.getElement().scrollTop = this.scrollTopBeforeHide_;
    -    // Make sure the highlighted item is still visible, in case the list
    -    // or its hilighted item has changed.
    -    this.doScrolling_(false);
    -  } else {
    -    this.doScrolling_(true);
    -  }
    -};
    -
    -
    -/**
    - * Handles hide events on the container. Clears out the last enter target,
    - * since it is no longer applicable, and remembers the scroll position of
    - * the menu so that it can be restored when the menu is reopened.
    - * @param {goog.events.Event} e The container's hide event.
    - * @private
    - */
    -goog.ui.ContainerScroller.prototype.onHide_ = function(e) {
    -  if (e.target == this.container_) {
    -    this.lastEnterTarget_ = null;
    -    this.scrollTopBeforeHide_ = this.container_.getElement().scrollTop;
    -  }
    -};
    -
    -
    -/**
    - * Centers the currently highlighted item, if this is scrollable.
    - * @param {boolean=} opt_center Whether to center the highlighted element
    - *     rather than simply ensure it is in view.  Useful for the first
    - *     render.
    - * @private
    - */
    -goog.ui.ContainerScroller.prototype.doScrolling_ = function(opt_center) {
    -  var highlighted = this.container_.getHighlighted();
    -
    -  // Only scroll if we're visible and there is a highlighted item.
    -  if (this.container_.isVisible() && highlighted &&
    -      highlighted != this.lastEnterTarget_) {
    -    var element = this.container_.getElement();
    -    goog.style.scrollIntoContainerView(highlighted.getElement(), element,
    -        opt_center);
    -    this.temporarilyDisableHover_();
    -    this.lastEnterTarget_ = null;
    -  }
    -};
    -
    -
    -/**
    - * Temporarily disables hover events from changing highlight.
    - * @see #onEnter_
    - * @private
    - */
    -goog.ui.ContainerScroller.prototype.temporarilyDisableHover_ = function() {
    -  this.disableHover_ = true;
    -  goog.Timer.callOnce(function() {
    -    this.disableHover_ = false;
    -  }, 0, this);
    -};
    -
    -
    -/** @override */
    -goog.ui.ContainerScroller.prototype.disposeInternal = function() {
    -  goog.ui.ContainerScroller.superClass_.disposeInternal.call(this);
    -  this.eventHandler_.dispose();
    -  this.lastEnterTarget_ = null;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/containerscroller_test.html b/src/database/third_party/closure-library/closure/goog/ui/containerscroller_test.html
    deleted file mode 100644
    index b828e0bad24..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/containerscroller_test.html
    +++ /dev/null
    @@ -1,74 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -Author:  gboyer@google.com (Garrett Boyer)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.ContainerScroller
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.ContainerScrollerTest');
    -  </script>
    -  <style type="text/css">
    -   .goog-container {
    -  height: 100px;
    -  overflow-y: auto;
    -  overflow-x: hidden;
    -  position: relative;
    -  /* Give a border and margin to ensure ContainerScroller is tolerant to
    -   * them.  It is, however, not tolerant to padding. */
    -  border: 11px solid #666;
    -  margin: 7px 13px 17px 19px;
    -}
    -.goog-control {
    -  font-size: 10px;
    -  height: 14px;
    -  padding: 3px;
    -}
    -  </style>
    - </head>
    - <body>
    -  <div id="sandbox" class="goog-container">
    -   <div class="goog-control" id="control-0">
    -    0
    -   </div>
    -   <div class="goog-control" id="control-1">
    -    1
    -   </div>
    -   <div class="goog-control" id="control-2">
    -    2
    -   </div>
    -   <div class="goog-control" id="control-3">
    -    3
    -   </div>
    -   <div class="goog-control" id="control-4">
    -    4
    -   </div>
    -   <div class="goog-control" id="control-5">
    -    5
    -   </div>
    -   <div class="goog-control" id="control-6">
    -    6
    -   </div>
    -   <div class="goog-control" id="control-7">
    -    7
    -   </div>
    -   <div class="goog-control" id="control-8">
    -    8
    -   </div>
    -   <div class="goog-control" id="control-9">
    -    9
    -   </div>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/containerscroller_test.js b/src/database/third_party/closure-library/closure/goog/ui/containerscroller_test.js
    deleted file mode 100644
    index 952051666ae..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/containerscroller_test.js
    +++ /dev/null
    @@ -1,182 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.ContainerScrollerTest');
    -goog.setTestOnly('goog.ui.ContainerScrollerTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.Container');
    -goog.require('goog.ui.ContainerScroller');
    -
    -var sandbox;
    -var sandboxHtml;
    -var container;
    -var mockClock;
    -var scroller;
    -
    -function setUpPage() {
    -  sandbox = goog.dom.getElement('sandbox');
    -  sandboxHtml = sandbox.innerHTML;
    -}
    -
    -function setUp() {
    -  container = new goog.ui.Container();
    -  container.decorate(sandbox);
    -  container.getElement().scrollTop = 0;
    -  mockClock = new goog.testing.MockClock(true);
    -  scroller = null;
    -}
    -
    -function tearDown() {
    -  container.dispose();
    -  if (scroller) {
    -    scroller.dispose();
    -  }
    -  // Tick one second to clear all the extra registered events.
    -  mockClock.tick(1000);
    -  mockClock.uninstall();
    -  sandbox.innerHTML = sandboxHtml;
    -}
    -
    -function testHighlightFirstStaysAtTop() {
    -  scroller = new goog.ui.ContainerScroller(container);
    -  container.getChildAt(0).setHighlighted(true);
    -  assertEquals(0, container.getElement().scrollTop);
    -}
    -
    -function testHighlightSecondStaysAtTop() {
    -  scroller = new goog.ui.ContainerScroller(container);
    -  container.getChildAt(1).setHighlighted(true);
    -  assertEquals(0, container.getElement().scrollTop);
    -}
    -
    -function testHighlightSecondLastScrollsNearTheBottom() {
    -  scroller = new goog.ui.ContainerScroller(container);
    -  container.getChildAt(8).setHighlighted(true);
    -  assertEquals('Since scrolling is lazy, when highlighting the second' +
    -      ' last, the item should be the last visible one.',
    -      80, container.getElement().scrollTop);
    -}
    -
    -function testHighlightLastScrollsToBottom() {
    -  scroller = new goog.ui.ContainerScroller(container);
    -  container.getChildAt(9).setHighlighted(true);
    -  assertEquals(100, container.getElement().scrollTop);
    -}
    -
    -function testScrollRestoreIfStillVisible() {
    -  scroller = new goog.ui.ContainerScroller(container);
    -  container.getChildAt(9).setHighlighted(true);
    -  var scrollTop = container.getElement().scrollTop;
    -  container.setVisible(false);
    -  container.setVisible(true);
    -  assertEquals('Scroll position should be the same after restore, if it ' +
    -               'still makes highlighted item visible',
    -               scrollTop, container.getElement().scrollTop);
    -}
    -
    -function testNoScrollRestoreIfNotVisible() {
    -  scroller = new goog.ui.ContainerScroller(container);
    -  container.getElement().scrollTop = 100;
    -  container.setVisible(false);
    -  container.getChildAt(0).setHighlighted(true);
    -  container.setVisible(true);
    -  assertNotEquals('Scroll position should not be the same after restore, if ' +
    -                  'the scroll position when the menu was hidden no longer ' +
    -                  'makes the highlighted item visible when the container is ' +
    -                  'shown again',
    -      100, container.getElement().scrollTop);
    -}
    -
    -function testCenterOnHighlightedOnFirstOpen() {
    -  container.setVisible(false);
    -  scroller = new goog.ui.ContainerScroller(container);
    -  container.getChildAt(4).setHighlighted(true);
    -  container.setVisible(true);
    -  // #2 should be at the top when 4 is centered, meaning a scroll top
    -  // of 40 pixels.
    -  assertEquals(
    -      'On the very first display of the scroller, the item should be ' +
    -      'centered, rather than just assured in view.',
    -      40, container.getElement().scrollTop);
    -}
    -
    -function testHighlightsAreIgnoredInResponseToScrolling() {
    -  scroller = new goog.ui.ContainerScroller(container);
    -  container.getChildAt(9).setHighlighted(true);
    -  goog.testing.events.fireMouseOverEvent(
    -      goog.dom.getElement('control-5'),
    -      goog.dom.getElement('control-9'));
    -  assertEquals('Mouseovers due to scrolls should be ignored',
    -      9, container.getHighlightedIndex());
    -}
    -
    -function testHighlightsAreNotIgnoredWhenNotScrolling() {
    -  scroller = new goog.ui.ContainerScroller(container);
    -  container.getChildAt(5).setHighlighted(true);
    -  mockClock.tick(1000);
    -  goog.testing.events.fireMouseOutEvent(
    -      goog.dom.getElement('control-5'),
    -      goog.dom.getElement('control-6'));
    -  goog.testing.events.fireMouseOverEvent(
    -      goog.dom.getElement('control-6'),
    -      goog.dom.getElement('control-5'));
    -  assertEquals('Mousovers not due to scrolls should not be ignored',
    -      6, container.getHighlightedIndex());
    -}
    -
    -function testFastSynchronousHighlightsNotIgnored() {
    -  scroller = new goog.ui.ContainerScroller(container);
    -  // Whereas subsequent highlights from mouseovers due to a scroll, should
    -  // be ignored, they should not ignored if they are made synchronusly
    -  // from the code and not from a mouseover.  Imagine how bad it would be
    -  // if you could only set the highligted index a certain number of
    -  // times in the same execution context.
    -  container.getChildAt(9).setHighlighted(true);
    -  container.getChildAt(1).setHighlighted(true);
    -  assertEquals('Synchronous highlights should NOT be ignored.',
    -      1, container.getHighlightedIndex());
    -  container.getChildAt(8).setHighlighted(true);
    -  assertEquals('Synchronous highlights should NOT be ignored.',
    -      8, container.getHighlightedIndex());
    -}
    -
    -function testInitialItemIsCentered() {
    -  container.getChildAt(4).setHighlighted(true);
    -  scroller = new goog.ui.ContainerScroller(container);
    -  // #2 should be at the top when 4 is centered, meaning a scroll top
    -  // of 40 pixels.
    -  assertEquals(
    -      'On the very first attachment of the scroller, the item should be ' +
    -      'centered, rather than just assured in view.',
    -      40, container.getElement().scrollTop);
    -}
    -
    -function testInitialItemIsCenteredTopItem() {
    -  container.getChildAt(0).setHighlighted(true);
    -  scroller = new goog.ui.ContainerScroller(container);
    -  assertEquals(0, container.getElement().scrollTop);
    -}
    -
    -function testHidingMenuItemsDoesntAffectContainerScroller() {
    -  scroller = new goog.ui.ContainerScroller(container);
    -  container.getElement = function() {
    -    fail('getElement() must not be called when a control in the container is ' +
    -         'being hidden');
    -  };
    -  container.getChildAt(0).setVisible(false);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/control.js b/src/database/third_party/closure-library/closure/goog/ui/control.js
    deleted file mode 100644
    index 477b165090c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/control.js
    +++ /dev/null
    @@ -1,1423 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Base class for UI controls such as buttons, menus, menu items,
    - * toolbar buttons, etc.  The implementation is based on a generalized version
    - * of {@link goog.ui.MenuItem}.
    - * TODO(attila):  If the renderer framework works well, pull it into Component.
    - *
    - * @author attila@google.com (Attila Bodis)
    - * @see ../demos/control.html
    - * @see http://code.google.com/p/closure-library/wiki/IntroToControls
    - */
    -
    -goog.provide('goog.ui.Control');
    -
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.events.KeyHandler');
    -goog.require('goog.string');
    -goog.require('goog.ui.Component');
    -/** @suppress {extraRequire} */
    -goog.require('goog.ui.ControlContent');
    -goog.require('goog.ui.ControlRenderer');
    -goog.require('goog.ui.decorate');
    -goog.require('goog.ui.registry');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Base class for UI controls.  Extends {@link goog.ui.Component} by adding
    - * the following:
    - *  <ul>
    - *    <li>a {@link goog.events.KeyHandler}, to simplify keyboard handling,
    - *    <li>a pluggable <em>renderer</em> framework, to simplify the creation of
    - *        simple controls without the need to subclass this class,
    - *    <li>the notion of component <em>content</em>, like a text caption or DOM
    - *        structure displayed in the component (e.g. a button label),
    - *    <li>getter and setter for component content, as well as a getter and
    - *        setter specifically for caption text (for convenience),
    - *    <li>support for hiding/showing the component,
    -      <li>fine-grained control over supported states and state transition
    -          events, and
    - *    <li>default mouse and keyboard event handling.
    - *  </ul>
    - * This class has sufficient built-in functionality for most simple UI controls.
    - * All controls dispatch SHOW, HIDE, ENTER, LEAVE, and ACTION events on show,
    - * hide, mouseover, mouseout, and user action, respectively.  Additional states
    - * are also supported.  See closure/demos/control.html
    - * for example usage.
    - * @param {goog.ui.ControlContent=} opt_content Text caption or DOM structure
    - *     to display as the content of the control (if any).
    - * @param {goog.ui.ControlRenderer=} opt_renderer Renderer used to render or
    - *     decorate the component; defaults to {@link goog.ui.ControlRenderer}.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @constructor
    - * @extends {goog.ui.Component}
    - */
    -goog.ui.Control = function(opt_content, opt_renderer, opt_domHelper) {
    -  goog.ui.Component.call(this, opt_domHelper);
    -  this.renderer_ = opt_renderer ||
    -      goog.ui.registry.getDefaultRenderer(this.constructor);
    -  this.setContentInternal(goog.isDef(opt_content) ? opt_content : null);
    -
    -  /** @private {?string} The control's aria-label. */
    -  this.ariaLabel_ = null;
    -};
    -goog.inherits(goog.ui.Control, goog.ui.Component);
    -goog.tagUnsealableClass(goog.ui.Control);
    -
    -
    -// Renderer registry.
    -// TODO(attila): Refactor existing usages inside Google in a follow-up CL.
    -
    -
    -/**
    - * Maps a CSS class name to a function that returns a new instance of
    - * {@link goog.ui.Control} or a subclass thereof, suitable to decorate
    - * an element that has the specified CSS class.  UI components that extend
    - * {@link goog.ui.Control} and want {@link goog.ui.Container}s to be able
    - * to discover and decorate elements using them should register a factory
    - * function via this API.
    - * @param {string} className CSS class name.
    - * @param {Function} decoratorFunction Function that takes no arguments and
    - *     returns a new instance of a control to decorate an element with the
    - *     given class.
    - * @deprecated Use {@link goog.ui.registry.setDecoratorByClassName} instead.
    - */
    -goog.ui.Control.registerDecorator = goog.ui.registry.setDecoratorByClassName;
    -
    -
    -/**
    - * Takes an element and returns a new instance of {@link goog.ui.Control}
    - * or a subclass, suitable to decorate it (based on the element's CSS class).
    - * @param {Element} element Element to decorate.
    - * @return {goog.ui.Control?} New control instance to decorate the element
    - *     (null if none).
    - * @deprecated Use {@link goog.ui.registry.getDecorator} instead.
    - */
    -goog.ui.Control.getDecorator =
    -    /** @type {function(Element): goog.ui.Control} */ (
    -        goog.ui.registry.getDecorator);
    -
    -
    -/**
    - * Takes an element, and decorates it with a {@link goog.ui.Control} instance
    - * if a suitable decorator is found.
    - * @param {Element} element Element to decorate.
    - * @return {goog.ui.Control?} New control instance that decorates the element
    - *     (null if none).
    - * @deprecated Use {@link goog.ui.decorate} instead.
    - */
    -goog.ui.Control.decorate = /** @type {function(Element): goog.ui.Control} */ (
    -    goog.ui.decorate);
    -
    -
    -/**
    - * Renderer associated with the component.
    - * @type {goog.ui.ControlRenderer|undefined}
    - * @private
    - */
    -goog.ui.Control.prototype.renderer_;
    -
    -
    -/**
    - * Text caption or DOM structure displayed in the component.
    - * @type {goog.ui.ControlContent}
    - * @private
    - */
    -goog.ui.Control.prototype.content_ = null;
    -
    -
    -/**
    - * Current component state; a bit mask of {@link goog.ui.Component.State}s.
    - * @type {number}
    - * @private
    - */
    -goog.ui.Control.prototype.state_ = 0x00;
    -
    -
    -/**
    - * A bit mask of {@link goog.ui.Component.State}s this component supports.
    - * @type {number}
    - * @private
    - */
    -goog.ui.Control.prototype.supportedStates_ =
    -    goog.ui.Component.State.DISABLED |
    -    goog.ui.Component.State.HOVER |
    -    goog.ui.Component.State.ACTIVE |
    -    goog.ui.Component.State.FOCUSED;
    -
    -
    -/**
    - * A bit mask of {@link goog.ui.Component.State}s for which this component
    - * provides default event handling.  For example, a component that handles
    - * the HOVER state automatically will highlight itself on mouseover, whereas
    - * a component that doesn't handle HOVER automatically will only dispatch
    - * ENTER and LEAVE events but not call {@link setHighlighted} on itself.
    - * By default, components provide default event handling for all states.
    - * Controls hosted in containers (e.g. menu items in a menu, or buttons in a
    - * toolbar) will typically want to have their container manage their highlight
    - * state.  Selectable controls managed by a selection model will also typically
    - * want their selection state to be managed by the model.
    - * @type {number}
    - * @private
    - */
    -goog.ui.Control.prototype.autoStates_ = goog.ui.Component.State.ALL;
    -
    -
    -/**
    - * A bit mask of {@link goog.ui.Component.State}s for which this component
    - * dispatches state transition events.  Because events are expensive, the
    - * default behavior is to not dispatch any state transition events at all.
    - * Use the {@link #setDispatchTransitionEvents} API to request transition
    - * events  as needed.  Subclasses may enable transition events by default.
    - * Controls hosted in containers or managed by a selection model will typically
    - * want to dispatch transition events.
    - * @type {number}
    - * @private
    - */
    -goog.ui.Control.prototype.statesWithTransitionEvents_ = 0x00;
    -
    -
    -/**
    - * Component visibility.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.Control.prototype.visible_ = true;
    -
    -
    -/**
    - * Keyboard event handler.
    - * @type {goog.events.KeyHandler}
    - * @private
    - */
    -goog.ui.Control.prototype.keyHandler_;
    -
    -
    -/**
    - * Additional class name(s) to apply to the control's root element, if any.
    - * @type {Array<string>?}
    - * @private
    - */
    -goog.ui.Control.prototype.extraClassNames_ = null;
    -
    -
    -/**
    - * Whether the control should listen for and handle mouse events; defaults to
    - * true.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.Control.prototype.handleMouseEvents_ = true;
    -
    -
    -/**
    - * Whether the control allows text selection within its DOM.  Defaults to false.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.Control.prototype.allowTextSelection_ = false;
    -
    -
    -/**
    - * The control's preferred ARIA role.
    - * @type {?goog.a11y.aria.Role}
    - * @private
    - */
    -goog.ui.Control.prototype.preferredAriaRole_ = null;
    -
    -
    -// Event handler and renderer management.
    -
    -
    -/**
    - * Returns true if the control is configured to handle its own mouse events,
    - * false otherwise.  Controls not hosted in {@link goog.ui.Container}s have
    - * to handle their own mouse events, but controls hosted in containers may
    - * allow their parent to handle mouse events on their behalf.  Considered
    - * protected; should only be used within this package and by subclasses.
    - * @return {boolean} Whether the control handles its own mouse events.
    - */
    -goog.ui.Control.prototype.isHandleMouseEvents = function() {
    -  return this.handleMouseEvents_;
    -};
    -
    -
    -/**
    - * Enables or disables mouse event handling for the control.  Containers may
    - * use this method to disable mouse event handling in their child controls.
    - * Considered protected; should only be used within this package and by
    - * subclasses.
    - * @param {boolean} enable Whether to enable or disable mouse event handling.
    - */
    -goog.ui.Control.prototype.setHandleMouseEvents = function(enable) {
    -  if (this.isInDocument() && enable != this.handleMouseEvents_) {
    -    // Already in the document; need to update event handler.
    -    this.enableMouseEventHandling_(enable);
    -  }
    -  this.handleMouseEvents_ = enable;
    -};
    -
    -
    -/**
    - * Returns the DOM element on which the control is listening for keyboard
    - * events (null if none).
    - * @return {Element} Element on which the control is listening for key
    - *     events.
    - */
    -goog.ui.Control.prototype.getKeyEventTarget = function() {
    -  // Delegate to renderer.
    -  return this.renderer_.getKeyEventTarget(this);
    -};
    -
    -
    -/**
    - * Returns the keyboard event handler for this component, lazily created the
    - * first time this method is called.  Considered protected; should only be
    - * used within this package and by subclasses.
    - * @return {!goog.events.KeyHandler} Keyboard event handler for this component.
    - * @protected
    - */
    -goog.ui.Control.prototype.getKeyHandler = function() {
    -  return this.keyHandler_ || (this.keyHandler_ = new goog.events.KeyHandler());
    -};
    -
    -
    -/**
    - * Returns the renderer used by this component to render itself or to decorate
    - * an existing element.
    - * @return {goog.ui.ControlRenderer|undefined} Renderer used by the component
    - *     (undefined if none).
    - */
    -goog.ui.Control.prototype.getRenderer = function() {
    -  return this.renderer_;
    -};
    -
    -
    -/**
    - * Registers the given renderer with the component.  Changing renderers after
    - * the component has entered the document is an error.
    - * @param {goog.ui.ControlRenderer} renderer Renderer used by the component.
    - * @throws {Error} If the control is already in the document.
    - */
    -goog.ui.Control.prototype.setRenderer = function(renderer) {
    -  if (this.isInDocument()) {
    -    // Too late.
    -    throw Error(goog.ui.Component.Error.ALREADY_RENDERED);
    -  }
    -
    -  if (this.getElement()) {
    -    // The component has already been rendered, but isn't yet in the document.
    -    // Replace the renderer and delete the current DOM, so it can be re-rendered
    -    // using the new renderer the next time someone calls render().
    -    this.setElementInternal(null);
    -  }
    -
    -  this.renderer_ = renderer;
    -};
    -
    -
    -// Support for additional styling.
    -
    -
    -/**
    - * Returns any additional class name(s) to be applied to the component's
    - * root element, or null if no extra class names are needed.
    - * @return {Array<string>?} Additional class names to be applied to
    - *     the component's root element (null if none).
    - */
    -goog.ui.Control.prototype.getExtraClassNames = function() {
    -  return this.extraClassNames_;
    -};
    -
    -
    -/**
    - * Adds the given class name to the list of classes to be applied to the
    - * component's root element.
    - * @param {string} className Additional class name to be applied to the
    - *     component's root element.
    - */
    -goog.ui.Control.prototype.addClassName = function(className) {
    -  if (className) {
    -    if (this.extraClassNames_) {
    -      if (!goog.array.contains(this.extraClassNames_, className)) {
    -        this.extraClassNames_.push(className);
    -      }
    -    } else {
    -      this.extraClassNames_ = [className];
    -    }
    -    this.renderer_.enableExtraClassName(this, className, true);
    -  }
    -};
    -
    -
    -/**
    - * Removes the given class name from the list of classes to be applied to
    - * the component's root element.
    - * @param {string} className Class name to be removed from the component's root
    - *     element.
    - */
    -goog.ui.Control.prototype.removeClassName = function(className) {
    -  if (className && this.extraClassNames_ &&
    -      goog.array.remove(this.extraClassNames_, className)) {
    -    if (this.extraClassNames_.length == 0) {
    -      this.extraClassNames_ = null;
    -    }
    -    this.renderer_.enableExtraClassName(this, className, false);
    -  }
    -};
    -
    -
    -/**
    - * Adds or removes the given class name to/from the list of classes to be
    - * applied to the component's root element.
    - * @param {string} className CSS class name to add or remove.
    - * @param {boolean} enable Whether to add or remove the class name.
    - */
    -goog.ui.Control.prototype.enableClassName = function(className, enable) {
    -  if (enable) {
    -    this.addClassName(className);
    -  } else {
    -    this.removeClassName(className);
    -  }
    -};
    -
    -
    -// Standard goog.ui.Component implementation.
    -
    -
    -/**
    - * Creates the control's DOM.  Overrides {@link goog.ui.Component#createDom} by
    - * delegating DOM manipulation to the control's renderer.
    - * @override
    - */
    -goog.ui.Control.prototype.createDom = function() {
    -  var element = this.renderer_.createDom(this);
    -  this.setElementInternal(element);
    -
    -  // Initialize ARIA role.
    -  this.renderer_.setAriaRole(element, this.getPreferredAriaRole());
    -
    -  // Initialize text selection.
    -  if (!this.isAllowTextSelection()) {
    -    // The renderer is assumed to create selectable elements.  Since making
    -    // elements unselectable is expensive, only do it if needed (bug 1037090).
    -    this.renderer_.setAllowTextSelection(element, false);
    -  }
    -
    -  // Initialize visibility.
    -  if (!this.isVisible()) {
    -    // The renderer is assumed to create visible elements. Since hiding
    -    // elements can be expensive, only do it if needed (bug 1037105).
    -    this.renderer_.setVisible(element, false);
    -  }
    -};
    -
    -
    -/**
    - * Returns the control's preferred ARIA role. This can be used by a control to
    - * override the role that would be assigned by the renderer.  This is useful in
    - * cases where a different ARIA role is appropriate for a control because of the
    - * context in which it's used.  E.g., a {@link goog.ui.MenuButton} added to a
    - * {@link goog.ui.Select} should have an ARIA role of LISTBOX and not MENUITEM.
    - * @return {?goog.a11y.aria.Role} This control's preferred ARIA role or null if
    - *     no preferred ARIA role is set.
    - */
    -goog.ui.Control.prototype.getPreferredAriaRole = function() {
    -  return this.preferredAriaRole_;
    -};
    -
    -
    -/**
    - * Sets the control's preferred ARIA role. This can be used to override the role
    - * that would be assigned by the renderer.  This is useful in cases where a
    - * different ARIA role is appropriate for a control because of the
    - * context in which it's used.  E.g., a {@link goog.ui.MenuButton} added to a
    - * {@link goog.ui.Select} should have an ARIA role of LISTBOX and not MENUITEM.
    - * @param {goog.a11y.aria.Role} role This control's preferred ARIA role.
    - */
    -goog.ui.Control.prototype.setPreferredAriaRole = function(role) {
    -  this.preferredAriaRole_ = role;
    -};
    -
    -
    -/**
    - * Gets the control's aria label.
    - * @return {?string} This control's aria label.
    - */
    -goog.ui.Control.prototype.getAriaLabel = function() {
    -  return this.ariaLabel_;
    -};
    -
    -
    -/**
    - * Sets the control's aria label. This can be used to assign aria label to the
    - * element after it is rendered.
    - * @param {string} label The string to set as the aria label for this control.
    - *     No escaping is done on this value.
    - */
    -goog.ui.Control.prototype.setAriaLabel = function(label) {
    -  this.ariaLabel_ = label;
    -  var element = this.getElement();
    -  if (element) {
    -    this.renderer_.setAriaLabel(element, label);
    -  }
    -};
    -
    -
    -/**
    - * Returns the DOM element into which child components are to be rendered,
    - * or null if the control itself hasn't been rendered yet.  Overrides
    - * {@link goog.ui.Component#getContentElement} by delegating to the renderer.
    - * @return {Element} Element to contain child elements (null if none).
    - * @override
    - */
    -goog.ui.Control.prototype.getContentElement = function() {
    -  // Delegate to renderer.
    -  return this.renderer_.getContentElement(this.getElement());
    -};
    -
    -
    -/**
    - * Returns true if the given element can be decorated by this component.
    - * Overrides {@link goog.ui.Component#canDecorate}.
    - * @param {Element} element Element to decorate.
    - * @return {boolean} Whether the element can be decorated by this component.
    - * @override
    - */
    -goog.ui.Control.prototype.canDecorate = function(element) {
    -  // Controls support pluggable renderers; delegate to the renderer.
    -  return this.renderer_.canDecorate(element);
    -};
    -
    -
    -/**
    - * Decorates the given element with this component. Overrides {@link
    - * goog.ui.Component#decorateInternal} by delegating DOM manipulation
    - * to the control's renderer.
    - * @param {Element} element Element to decorate.
    - * @protected
    - * @override
    - */
    -goog.ui.Control.prototype.decorateInternal = function(element) {
    -  element = this.renderer_.decorate(this, element);
    -  this.setElementInternal(element);
    -
    -  // Initialize ARIA role.
    -  this.renderer_.setAriaRole(element, this.getPreferredAriaRole());
    -
    -  // Initialize text selection.
    -  if (!this.isAllowTextSelection()) {
    -    // Decorated elements are assumed to be selectable.  Since making elements
    -    // unselectable is expensive, only do it if needed (bug 1037090).
    -    this.renderer_.setAllowTextSelection(element, false);
    -  }
    -
    -  // Initialize visibility based on the decorated element's styling.
    -  this.visible_ = element.style.display != 'none';
    -};
    -
    -
    -/**
    - * Configures the component after its DOM has been rendered, and sets up event
    - * handling.  Overrides {@link goog.ui.Component#enterDocument}.
    - * @override
    - */
    -goog.ui.Control.prototype.enterDocument = function() {
    -  goog.ui.Control.superClass_.enterDocument.call(this);
    -
    -  // Call the renderer's setAriaStates method to set element's aria attributes.
    -  this.renderer_.setAriaStates(this, this.getElementStrict());
    -
    -  // Call the renderer's initializeDom method to configure properties of the
    -  // control's DOM that can only be done once it's in the document.
    -  this.renderer_.initializeDom(this);
    -
    -  // Initialize event handling if at least one state other than DISABLED is
    -  // supported.
    -  if (this.supportedStates_ & ~goog.ui.Component.State.DISABLED) {
    -    // Initialize mouse event handling if the control is configured to handle
    -    // its own mouse events.  (Controls hosted in containers don't need to
    -    // handle their own mouse events.)
    -    if (this.isHandleMouseEvents()) {
    -      this.enableMouseEventHandling_(true);
    -    }
    -
    -    // Initialize keyboard event handling if the control is focusable and has
    -    // a key event target.  (Controls hosted in containers typically aren't
    -    // focusable, allowing their container to handle keyboard events for them.)
    -    if (this.isSupportedState(goog.ui.Component.State.FOCUSED)) {
    -      var keyTarget = this.getKeyEventTarget();
    -      if (keyTarget) {
    -        var keyHandler = this.getKeyHandler();
    -        keyHandler.attach(keyTarget);
    -        this.getHandler().
    -            listen(keyHandler, goog.events.KeyHandler.EventType.KEY,
    -                this.handleKeyEvent).
    -            listen(keyTarget, goog.events.EventType.FOCUS,
    -                this.handleFocus).
    -            listen(keyTarget, goog.events.EventType.BLUR,
    -                this.handleBlur);
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Enables or disables mouse event handling on the control.
    - * @param {boolean} enable Whether to enable mouse event handling.
    - * @private
    - */
    -goog.ui.Control.prototype.enableMouseEventHandling_ = function(enable) {
    -  var handler = this.getHandler();
    -  var element = this.getElement();
    -  if (enable) {
    -    handler.
    -        listen(element, goog.events.EventType.MOUSEOVER, this.handleMouseOver).
    -        listen(element, goog.events.EventType.MOUSEDOWN, this.handleMouseDown).
    -        listen(element, goog.events.EventType.MOUSEUP, this.handleMouseUp).
    -        listen(element, goog.events.EventType.MOUSEOUT, this.handleMouseOut);
    -    if (this.handleContextMenu != goog.nullFunction) {
    -      handler.listen(element, goog.events.EventType.CONTEXTMENU,
    -          this.handleContextMenu);
    -    }
    -    if (goog.userAgent.IE) {
    -      handler.listen(element, goog.events.EventType.DBLCLICK,
    -          this.handleDblClick);
    -    }
    -  } else {
    -    handler.
    -        unlisten(element, goog.events.EventType.MOUSEOVER,
    -            this.handleMouseOver).
    -        unlisten(element, goog.events.EventType.MOUSEDOWN,
    -            this.handleMouseDown).
    -        unlisten(element, goog.events.EventType.MOUSEUP, this.handleMouseUp).
    -        unlisten(element, goog.events.EventType.MOUSEOUT, this.handleMouseOut);
    -    if (this.handleContextMenu != goog.nullFunction) {
    -      handler.unlisten(element, goog.events.EventType.CONTEXTMENU,
    -          this.handleContextMenu);
    -    }
    -    if (goog.userAgent.IE) {
    -      handler.unlisten(element, goog.events.EventType.DBLCLICK,
    -          this.handleDblClick);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Cleans up the component before its DOM is removed from the document, and
    - * removes event handlers.  Overrides {@link goog.ui.Component#exitDocument}
    - * by making sure that components that are removed from the document aren't
    - * focusable (i.e. have no tab index).
    - * @override
    - */
    -goog.ui.Control.prototype.exitDocument = function() {
    -  goog.ui.Control.superClass_.exitDocument.call(this);
    -  if (this.keyHandler_) {
    -    this.keyHandler_.detach();
    -  }
    -  if (this.isVisible() && this.isEnabled()) {
    -    this.renderer_.setFocusable(this, false);
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.Control.prototype.disposeInternal = function() {
    -  goog.ui.Control.superClass_.disposeInternal.call(this);
    -  if (this.keyHandler_) {
    -    this.keyHandler_.dispose();
    -    delete this.keyHandler_;
    -  }
    -  delete this.renderer_;
    -  this.content_ = null;
    -  this.extraClassNames_ = null;
    -};
    -
    -
    -// Component content management.
    -
    -
    -/**
    - * Returns the text caption or DOM structure displayed in the component.
    - * @return {goog.ui.ControlContent} Text caption or DOM structure
    - *     comprising the component's contents.
    - */
    -goog.ui.Control.prototype.getContent = function() {
    -  return this.content_;
    -};
    -
    -
    -/**
    - * Sets the component's content to the given text caption, element, or array of
    - * nodes.  (If the argument is an array of nodes, it must be an actual array,
    - * not an array-like object.)
    - * @param {goog.ui.ControlContent} content Text caption or DOM
    - *     structure to set as the component's contents.
    - */
    -goog.ui.Control.prototype.setContent = function(content) {
    -  // Controls support pluggable renderers; delegate to the renderer.
    -  this.renderer_.setContent(this.getElement(), content);
    -
    -  // setContentInternal needs to be after the renderer, since the implementation
    -  // may depend on the content being in the DOM.
    -  this.setContentInternal(content);
    -};
    -
    -
    -/**
    - * Sets the component's content to the given text caption, element, or array
    - * of nodes.  Unlike {@link #setContent}, doesn't modify the component's DOM.
    - * Called by renderers during element decoration.
    - *
    - * This should only be used by subclasses and its associated renderers.
    - *
    - * @param {goog.ui.ControlContent} content Text caption or DOM structure
    - *     to set as the component's contents.
    - */
    -goog.ui.Control.prototype.setContentInternal = function(content) {
    -  this.content_ = content;
    -};
    -
    -
    -/**
    - * @return {string} Text caption of the control or empty string if none.
    - */
    -goog.ui.Control.prototype.getCaption = function() {
    -  var content = this.getContent();
    -  if (!content) {
    -    return '';
    -  }
    -  var caption =
    -      goog.isString(content) ? content :
    -      goog.isArray(content) ? goog.array.map(content,
    -          goog.dom.getRawTextContent).join('') :
    -      goog.dom.getTextContent(/** @type {!Node} */ (content));
    -  return goog.string.collapseBreakingSpaces(caption);
    -};
    -
    -
    -/**
    - * Sets the text caption of the component.
    - * @param {string} caption Text caption of the component.
    - */
    -goog.ui.Control.prototype.setCaption = function(caption) {
    -  this.setContent(caption);
    -};
    -
    -
    -// Component state management.
    -
    -
    -/** @override */
    -goog.ui.Control.prototype.setRightToLeft = function(rightToLeft) {
    -  // The superclass implementation ensures the control isn't in the document.
    -  goog.ui.Control.superClass_.setRightToLeft.call(this, rightToLeft);
    -
    -  var element = this.getElement();
    -  if (element) {
    -    this.renderer_.setRightToLeft(element, rightToLeft);
    -  }
    -};
    -
    -
    -/**
    - * Returns true if the control allows text selection within its DOM, false
    - * otherwise.  Controls that disallow text selection have the appropriate
    - * unselectable styling applied to their elements.  Note that controls hosted
    - * in containers will report that they allow text selection even if their
    - * container disallows text selection.
    - * @return {boolean} Whether the control allows text selection.
    - */
    -goog.ui.Control.prototype.isAllowTextSelection = function() {
    -  return this.allowTextSelection_;
    -};
    -
    -
    -/**
    - * Allows or disallows text selection within the control's DOM.
    - * @param {boolean} allow Whether the control should allow text selection.
    - */
    -goog.ui.Control.prototype.setAllowTextSelection = function(allow) {
    -  this.allowTextSelection_ = allow;
    -
    -  var element = this.getElement();
    -  if (element) {
    -    this.renderer_.setAllowTextSelection(element, allow);
    -  }
    -};
    -
    -
    -/**
    - * Returns true if the component's visibility is set to visible, false if
    - * it is set to hidden.  A component that is set to hidden is guaranteed
    - * to be hidden from the user, but the reverse isn't necessarily true.
    - * A component may be set to visible but can otherwise be obscured by another
    - * element, rendered off-screen, or hidden using direct CSS manipulation.
    - * @return {boolean} Whether the component is visible.
    - */
    -goog.ui.Control.prototype.isVisible = function() {
    -  return this.visible_;
    -};
    -
    -
    -/**
    - * Shows or hides the component.  Does nothing if the component already has
    - * the requested visibility.  Otherwise, dispatches a SHOW or HIDE event as
    - * appropriate, giving listeners a chance to prevent the visibility change.
    - * When showing a component that is both enabled and focusable, ensures that
    - * its key target has a tab index.  When hiding a component that is enabled
    - * and focusable, blurs its key target and removes its tab index.
    - * @param {boolean} visible Whether to show or hide the component.
    - * @param {boolean=} opt_force If true, doesn't check whether the component
    - *     already has the requested visibility, and doesn't dispatch any events.
    - * @return {boolean} Whether the visibility was changed.
    - */
    -goog.ui.Control.prototype.setVisible = function(visible, opt_force) {
    -  if (opt_force || (this.visible_ != visible && this.dispatchEvent(visible ?
    -      goog.ui.Component.EventType.SHOW : goog.ui.Component.EventType.HIDE))) {
    -    var element = this.getElement();
    -    if (element) {
    -      this.renderer_.setVisible(element, visible);
    -    }
    -    if (this.isEnabled()) {
    -      this.renderer_.setFocusable(this, visible);
    -    }
    -    this.visible_ = visible;
    -    return true;
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Returns true if the component is enabled, false otherwise.
    - * @return {boolean} Whether the component is enabled.
    - */
    -goog.ui.Control.prototype.isEnabled = function() {
    -  return !this.hasState(goog.ui.Component.State.DISABLED);
    -};
    -
    -
    -/**
    - * Returns true if the control has a parent that is itself disabled, false
    - * otherwise.
    - * @return {boolean} Whether the component is hosted in a disabled container.
    - * @private
    - */
    -goog.ui.Control.prototype.isParentDisabled_ = function() {
    -  var parent = this.getParent();
    -  return !!parent && typeof parent.isEnabled == 'function' &&
    -      !parent.isEnabled();
    -};
    -
    -
    -/**
    - * Enables or disables the component.  Does nothing if this state transition
    - * is disallowed.  If the component is both visible and focusable, updates its
    - * focused state and tab index as needed.  If the component is being disabled,
    - * ensures that it is also deactivated and un-highlighted first.  Note that the
    - * component's enabled/disabled state is "locked" as long as it is hosted in a
    - * {@link goog.ui.Container} that is itself disabled; this is to prevent clients
    - * from accidentally re-enabling a control that is in a disabled container.
    - * @param {boolean} enable Whether to enable or disable the component.
    - * @see #isTransitionAllowed
    - */
    -goog.ui.Control.prototype.setEnabled = function(enable) {
    -  if (!this.isParentDisabled_() &&
    -      this.isTransitionAllowed(goog.ui.Component.State.DISABLED, !enable)) {
    -    if (!enable) {
    -      this.setActive(false);
    -      this.setHighlighted(false);
    -    }
    -    if (this.isVisible()) {
    -      this.renderer_.setFocusable(this, enable);
    -    }
    -    this.setState(goog.ui.Component.State.DISABLED, !enable, true);
    -  }
    -};
    -
    -
    -/**
    - * Returns true if the component is currently highlighted, false otherwise.
    - * @return {boolean} Whether the component is highlighted.
    - */
    -goog.ui.Control.prototype.isHighlighted = function() {
    -  return this.hasState(goog.ui.Component.State.HOVER);
    -};
    -
    -
    -/**
    - * Highlights or unhighlights the component.  Does nothing if this state
    - * transition is disallowed.
    - * @param {boolean} highlight Whether to highlight or unhighlight the component.
    - * @see #isTransitionAllowed
    - */
    -goog.ui.Control.prototype.setHighlighted = function(highlight) {
    -  if (this.isTransitionAllowed(goog.ui.Component.State.HOVER, highlight)) {
    -    this.setState(goog.ui.Component.State.HOVER, highlight);
    -  }
    -};
    -
    -
    -/**
    - * Returns true if the component is active (pressed), false otherwise.
    - * @return {boolean} Whether the component is active.
    - */
    -goog.ui.Control.prototype.isActive = function() {
    -  return this.hasState(goog.ui.Component.State.ACTIVE);
    -};
    -
    -
    -/**
    - * Activates or deactivates the component.  Does nothing if this state
    - * transition is disallowed.
    - * @param {boolean} active Whether to activate or deactivate the component.
    - * @see #isTransitionAllowed
    - */
    -goog.ui.Control.prototype.setActive = function(active) {
    -  if (this.isTransitionAllowed(goog.ui.Component.State.ACTIVE, active)) {
    -    this.setState(goog.ui.Component.State.ACTIVE, active);
    -  }
    -};
    -
    -
    -/**
    - * Returns true if the component is selected, false otherwise.
    - * @return {boolean} Whether the component is selected.
    - */
    -goog.ui.Control.prototype.isSelected = function() {
    -  return this.hasState(goog.ui.Component.State.SELECTED);
    -};
    -
    -
    -/**
    - * Selects or unselects the component.  Does nothing if this state transition
    - * is disallowed.
    - * @param {boolean} select Whether to select or unselect the component.
    - * @see #isTransitionAllowed
    - */
    -goog.ui.Control.prototype.setSelected = function(select) {
    -  if (this.isTransitionAllowed(goog.ui.Component.State.SELECTED, select)) {
    -    this.setState(goog.ui.Component.State.SELECTED, select);
    -  }
    -};
    -
    -
    -/**
    - * Returns true if the component is checked, false otherwise.
    - * @return {boolean} Whether the component is checked.
    - */
    -goog.ui.Control.prototype.isChecked = function() {
    -  return this.hasState(goog.ui.Component.State.CHECKED);
    -};
    -
    -
    -/**
    - * Checks or unchecks the component.  Does nothing if this state transition
    - * is disallowed.
    - * @param {boolean} check Whether to check or uncheck the component.
    - * @see #isTransitionAllowed
    - */
    -goog.ui.Control.prototype.setChecked = function(check) {
    -  if (this.isTransitionAllowed(goog.ui.Component.State.CHECKED, check)) {
    -    this.setState(goog.ui.Component.State.CHECKED, check);
    -  }
    -};
    -
    -
    -/**
    - * Returns true if the component is styled to indicate that it has keyboard
    - * focus, false otherwise.  Note that {@code isFocused()} returning true
    - * doesn't guarantee that the component's key event target has keyborad focus,
    - * only that it is styled as such.
    - * @return {boolean} Whether the component is styled to indicate as having
    - *     keyboard focus.
    - */
    -goog.ui.Control.prototype.isFocused = function() {
    -  return this.hasState(goog.ui.Component.State.FOCUSED);
    -};
    -
    -
    -/**
    - * Applies or removes styling indicating that the component has keyboard focus.
    - * Note that unlike the other "set" methods, this method is called as a result
    - * of the component's element having received or lost keyboard focus, not the
    - * other way around, so calling {@code setFocused(true)} doesn't guarantee that
    - * the component's key event target has keyboard focus, only that it is styled
    - * as such.
    - * @param {boolean} focused Whether to apply or remove styling to indicate that
    - *     the component's element has keyboard focus.
    - */
    -goog.ui.Control.prototype.setFocused = function(focused) {
    -  if (this.isTransitionAllowed(goog.ui.Component.State.FOCUSED, focused)) {
    -    this.setState(goog.ui.Component.State.FOCUSED, focused);
    -  }
    -};
    -
    -
    -/**
    - * Returns true if the component is open (expanded), false otherwise.
    - * @return {boolean} Whether the component is open.
    - */
    -goog.ui.Control.prototype.isOpen = function() {
    -  return this.hasState(goog.ui.Component.State.OPENED);
    -};
    -
    -
    -/**
    - * Opens (expands) or closes (collapses) the component.  Does nothing if this
    - * state transition is disallowed.
    - * @param {boolean} open Whether to open or close the component.
    - * @see #isTransitionAllowed
    - */
    -goog.ui.Control.prototype.setOpen = function(open) {
    -  if (this.isTransitionAllowed(goog.ui.Component.State.OPENED, open)) {
    -    this.setState(goog.ui.Component.State.OPENED, open);
    -  }
    -};
    -
    -
    -/**
    - * Returns the component's state as a bit mask of {@link
    - * goog.ui.Component.State}s.
    - * @return {number} Bit mask representing component state.
    - */
    -goog.ui.Control.prototype.getState = function() {
    -  return this.state_;
    -};
    -
    -
    -/**
    - * Returns true if the component is in the specified state, false otherwise.
    - * @param {goog.ui.Component.State} state State to check.
    - * @return {boolean} Whether the component is in the given state.
    - */
    -goog.ui.Control.prototype.hasState = function(state) {
    -  return !!(this.state_ & state);
    -};
    -
    -
    -/**
    - * Sets or clears the given state on the component, and updates its styling
    - * accordingly.  Does nothing if the component is already in the correct state
    - * or if it doesn't support the specified state.  Doesn't dispatch any state
    - * transition events; use advisedly.
    - * @param {goog.ui.Component.State} state State to set or clear.
    - * @param {boolean} enable Whether to set or clear the state (if supported).
    - * @param {boolean=} opt_calledFrom Prevents looping with setEnabled.
    - */
    -goog.ui.Control.prototype.setState = function(state, enable, opt_calledFrom) {
    -  if (!opt_calledFrom && state == goog.ui.Component.State.DISABLED) {
    -    this.setEnabled(!enable);
    -    return;
    -  }
    -  if (this.isSupportedState(state) && enable != this.hasState(state)) {
    -    // Delegate actual styling to the renderer, since it is DOM-specific.
    -    this.renderer_.setState(this, state, enable);
    -    this.state_ = enable ? this.state_ | state : this.state_ & ~state;
    -  }
    -};
    -
    -
    -/**
    - * Sets the component's state to the state represented by a bit mask of
    - * {@link goog.ui.Component.State}s.  Unlike {@link #setState}, doesn't
    - * update the component's styling, and doesn't reject unsupported states.
    - * Called by renderers during element decoration.  Considered protected;
    - * should only be used within this package and by subclasses.
    - *
    - * This should only be used by subclasses and its associated renderers.
    - *
    - * @param {number} state Bit mask representing component state.
    - */
    -goog.ui.Control.prototype.setStateInternal = function(state) {
    -  this.state_ = state;
    -};
    -
    -
    -/**
    - * Returns true if the component supports the specified state, false otherwise.
    - * @param {goog.ui.Component.State} state State to check.
    - * @return {boolean} Whether the component supports the given state.
    - */
    -goog.ui.Control.prototype.isSupportedState = function(state) {
    -  return !!(this.supportedStates_ & state);
    -};
    -
    -
    -/**
    - * Enables or disables support for the given state. Disabling support
    - * for a state while the component is in that state is an error.
    - * @param {goog.ui.Component.State} state State to support or de-support.
    - * @param {boolean} support Whether the component should support the state.
    - * @throws {Error} If disabling support for a state the control is currently in.
    - */
    -goog.ui.Control.prototype.setSupportedState = function(state, support) {
    -  if (this.isInDocument() && this.hasState(state) && !support) {
    -    // Since we hook up event handlers in enterDocument(), this is an error.
    -    throw Error(goog.ui.Component.Error.ALREADY_RENDERED);
    -  }
    -
    -  if (!support && this.hasState(state)) {
    -    // We are removing support for a state that the component is currently in.
    -    this.setState(state, false);
    -  }
    -
    -  this.supportedStates_ = support ?
    -      this.supportedStates_ | state : this.supportedStates_ & ~state;
    -};
    -
    -
    -/**
    - * Returns true if the component provides default event handling for the state,
    - * false otherwise.
    - * @param {goog.ui.Component.State} state State to check.
    - * @return {boolean} Whether the component provides default event handling for
    - *     the state.
    - */
    -goog.ui.Control.prototype.isAutoState = function(state) {
    -  return !!(this.autoStates_ & state) && this.isSupportedState(state);
    -};
    -
    -
    -/**
    - * Enables or disables automatic event handling for the given state(s).
    - * @param {number} states Bit mask of {@link goog.ui.Component.State}s for which
    - *     default event handling is to be enabled or disabled.
    - * @param {boolean} enable Whether the component should provide default event
    - *     handling for the state(s).
    - */
    -goog.ui.Control.prototype.setAutoStates = function(states, enable) {
    -  this.autoStates_ = enable ?
    -      this.autoStates_ | states : this.autoStates_ & ~states;
    -};
    -
    -
    -/**
    - * Returns true if the component is set to dispatch transition events for the
    - * given state, false otherwise.
    - * @param {goog.ui.Component.State} state State to check.
    - * @return {boolean} Whether the component dispatches transition events for
    - *     the state.
    - */
    -goog.ui.Control.prototype.isDispatchTransitionEvents = function(state) {
    -  return !!(this.statesWithTransitionEvents_ & state) &&
    -      this.isSupportedState(state);
    -};
    -
    -
    -/**
    - * Enables or disables transition events for the given state(s).  Controls
    - * handle state transitions internally by default, and only dispatch state
    - * transition events if explicitly requested to do so by calling this method.
    - * @param {number} states Bit mask of {@link goog.ui.Component.State}s for
    - *     which transition events should be enabled or disabled.
    - * @param {boolean} enable Whether transition events should be enabled.
    - */
    -goog.ui.Control.prototype.setDispatchTransitionEvents = function(states,
    -    enable) {
    -  this.statesWithTransitionEvents_ = enable ?
    -      this.statesWithTransitionEvents_ | states :
    -      this.statesWithTransitionEvents_ & ~states;
    -};
    -
    -
    -/**
    - * Returns true if the transition into or out of the given state is allowed to
    - * proceed, false otherwise.  A state transition is allowed under the following
    - * conditions:
    - * <ul>
    - *   <li>the component supports the state,
    - *   <li>the component isn't already in the target state,
    - *   <li>either the component is configured not to dispatch events for this
    - *       state transition, or a transition event was dispatched and wasn't
    - *       canceled by any event listener, and
    - *   <li>the component hasn't been disposed of
    - * </ul>
    - * Considered protected; should only be used within this package and by
    - * subclasses.
    - * @param {goog.ui.Component.State} state State to/from which the control is
    - *     transitioning.
    - * @param {boolean} enable Whether the control is entering or leaving the state.
    - * @return {boolean} Whether the state transition is allowed to proceed.
    - * @protected
    - */
    -goog.ui.Control.prototype.isTransitionAllowed = function(state, enable) {
    -  return this.isSupportedState(state) &&
    -      this.hasState(state) != enable &&
    -      (!(this.statesWithTransitionEvents_ & state) || this.dispatchEvent(
    -          goog.ui.Component.getStateTransitionEvent(state, enable))) &&
    -      !this.isDisposed();
    -};
    -
    -
    -// Default event handlers, to be overridden in subclasses.
    -
    -
    -/**
    - * Handles mouseover events.  Dispatches an ENTER event; if the event isn't
    - * canceled, the component is enabled, and it supports auto-highlighting,
    - * highlights the component.  Considered protected; should only be used
    - * within this package and by subclasses.
    - * @param {goog.events.BrowserEvent} e Mouse event to handle.
    - */
    -goog.ui.Control.prototype.handleMouseOver = function(e) {
    -  // Ignore mouse moves between descendants.
    -  if (!goog.ui.Control.isMouseEventWithinElement_(e, this.getElement()) &&
    -      this.dispatchEvent(goog.ui.Component.EventType.ENTER) &&
    -      this.isEnabled() &&
    -      this.isAutoState(goog.ui.Component.State.HOVER)) {
    -    this.setHighlighted(true);
    -  }
    -};
    -
    -
    -/**
    - * Handles mouseout events.  Dispatches a LEAVE event; if the event isn't
    - * canceled, and the component supports auto-highlighting, deactivates and
    - * un-highlights the component.  Considered protected; should only be used
    - * within this package and by subclasses.
    - * @param {goog.events.BrowserEvent} e Mouse event to handle.
    - */
    -goog.ui.Control.prototype.handleMouseOut = function(e) {
    -  if (!goog.ui.Control.isMouseEventWithinElement_(e, this.getElement()) &&
    -      this.dispatchEvent(goog.ui.Component.EventType.LEAVE)) {
    -    if (this.isAutoState(goog.ui.Component.State.ACTIVE)) {
    -      // Deactivate on mouseout; otherwise we lose track of the mouse button.
    -      this.setActive(false);
    -    }
    -    if (this.isAutoState(goog.ui.Component.State.HOVER)) {
    -      this.setHighlighted(false);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Handles contextmenu events.
    - * @param {goog.events.BrowserEvent} e Event to handle.
    - */
    -goog.ui.Control.prototype.handleContextMenu = goog.nullFunction;
    -
    -
    -/**
    - * Checks if a mouse event (mouseover or mouseout) occured below an element.
    - * @param {goog.events.BrowserEvent} e Mouse event (should be mouseover or
    - *     mouseout).
    - * @param {Element} elem The ancestor element.
    - * @return {boolean} Whether the event has a relatedTarget (the element the
    - *     mouse is coming from) and it's a descendent of elem.
    - * @private
    - */
    -goog.ui.Control.isMouseEventWithinElement_ = function(e, elem) {
    -  // If relatedTarget is null, it means there was no previous element (e.g.
    -  // the mouse moved out of the window).  Assume this means that the mouse
    -  // event was not within the element.
    -  return !!e.relatedTarget && goog.dom.contains(elem, e.relatedTarget);
    -};
    -
    -
    -/**
    - * Handles mousedown events.  If the component is enabled, highlights and
    - * activates it.  If the component isn't configured for keyboard access,
    - * prevents it from receiving keyboard focus.  Considered protected; should
    - * only be used within this package and by subclasses.
    - * @param {goog.events.Event} e Mouse event to handle.
    - */
    -goog.ui.Control.prototype.handleMouseDown = function(e) {
    -  if (this.isEnabled()) {
    -    // Highlight enabled control on mousedown, regardless of the mouse button.
    -    if (this.isAutoState(goog.ui.Component.State.HOVER)) {
    -      this.setHighlighted(true);
    -    }
    -
    -    // For the left button only, activate the control, and focus its key event
    -    // target (if supported).
    -    if (e.isMouseActionButton()) {
    -      if (this.isAutoState(goog.ui.Component.State.ACTIVE)) {
    -        this.setActive(true);
    -      }
    -      if (this.renderer_.isFocusable(this)) {
    -        this.getKeyEventTarget().focus();
    -      }
    -    }
    -  }
    -
    -  // Cancel the default action unless the control allows text selection.
    -  if (!this.isAllowTextSelection() && e.isMouseActionButton()) {
    -    e.preventDefault();
    -  }
    -};
    -
    -
    -/**
    - * Handles mouseup events.  If the component is enabled, highlights it.  If
    - * the component has previously been activated, performs its associated action
    - * by calling {@link performActionInternal}, then deactivates it.  Considered
    - * protected; should only be used within this package and by subclasses.
    - * @param {goog.events.Event} e Mouse event to handle.
    - */
    -goog.ui.Control.prototype.handleMouseUp = function(e) {
    -  if (this.isEnabled()) {
    -    if (this.isAutoState(goog.ui.Component.State.HOVER)) {
    -      this.setHighlighted(true);
    -    }
    -    if (this.isActive() &&
    -        this.performActionInternal(e) &&
    -        this.isAutoState(goog.ui.Component.State.ACTIVE)) {
    -      this.setActive(false);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Handles dblclick events.  Should only be registered if the user agent is
    - * IE.  If the component is enabled, performs its associated action by calling
    - * {@link performActionInternal}.  This is used to allow more performant
    - * buttons in IE.  In IE, no mousedown event is fired when that mousedown will
    - * trigger a dblclick event.  Because of this, a user clicking quickly will
    - * only cause ACTION events to fire on every other click.  This is a workaround
    - * to generate ACTION events for every click.  Unfortunately, this workaround
    - * won't ever trigger the ACTIVE state.  This is roughly the same behaviour as
    - * if this were a 'button' element with a listener on mouseup.  Considered
    - * protected; should only be used within this package and by subclasses.
    - * @param {goog.events.Event} e Mouse event to handle.
    - */
    -goog.ui.Control.prototype.handleDblClick = function(e) {
    -  if (this.isEnabled()) {
    -    this.performActionInternal(e);
    -  }
    -};
    -
    -
    -/**
    - * Performs the appropriate action when the control is activated by the user.
    - * The default implementation first updates the checked and selected state of
    - * controls that support them, then dispatches an ACTION event.  Considered
    - * protected; should only be used within this package and by subclasses.
    - * @param {goog.events.Event} e Event that triggered the action.
    - * @return {boolean} Whether the action is allowed to proceed.
    - * @protected
    - */
    -goog.ui.Control.prototype.performActionInternal = function(e) {
    -  if (this.isAutoState(goog.ui.Component.State.CHECKED)) {
    -    this.setChecked(!this.isChecked());
    -  }
    -  if (this.isAutoState(goog.ui.Component.State.SELECTED)) {
    -    this.setSelected(true);
    -  }
    -  if (this.isAutoState(goog.ui.Component.State.OPENED)) {
    -    this.setOpen(!this.isOpen());
    -  }
    -
    -  var actionEvent = new goog.events.Event(goog.ui.Component.EventType.ACTION,
    -      this);
    -  if (e) {
    -    actionEvent.altKey = e.altKey;
    -    actionEvent.ctrlKey = e.ctrlKey;
    -    actionEvent.metaKey = e.metaKey;
    -    actionEvent.shiftKey = e.shiftKey;
    -    actionEvent.platformModifierKey = e.platformModifierKey;
    -  }
    -  return this.dispatchEvent(actionEvent);
    -};
    -
    -
    -/**
    - * Handles focus events on the component's key event target element.  If the
    - * component is focusable, updates its state and styling to indicate that it
    - * now has keyboard focus.  Considered protected; should only be used within
    - * this package and by subclasses.  <b>Warning:</b> IE dispatches focus and
    - * blur events asynchronously!
    - * @param {goog.events.Event} e Focus event to handle.
    - */
    -goog.ui.Control.prototype.handleFocus = function(e) {
    -  if (this.isAutoState(goog.ui.Component.State.FOCUSED)) {
    -    this.setFocused(true);
    -  }
    -};
    -
    -
    -/**
    - * Handles blur events on the component's key event target element.  Always
    - * deactivates the component.  In addition, if the component is focusable,
    - * updates its state and styling to indicate that it no longer has keyboard
    - * focus.  Considered protected; should only be used within this package and
    - * by subclasses.  <b>Warning:</b> IE dispatches focus and blur events
    - * asynchronously!
    - * @param {goog.events.Event} e Blur event to handle.
    - */
    -goog.ui.Control.prototype.handleBlur = function(e) {
    -  if (this.isAutoState(goog.ui.Component.State.ACTIVE)) {
    -    this.setActive(false);
    -  }
    -  if (this.isAutoState(goog.ui.Component.State.FOCUSED)) {
    -    this.setFocused(false);
    -  }
    -};
    -
    -
    -/**
    - * Attempts to handle a keyboard event, if the component is enabled and visible,
    - * by calling {@link handleKeyEventInternal}.  Considered protected; should only
    - * be used within this package and by subclasses.
    - * @param {goog.events.KeyEvent} e Key event to handle.
    - * @return {boolean} Whether the key event was handled.
    - */
    -goog.ui.Control.prototype.handleKeyEvent = function(e) {
    -  if (this.isVisible() && this.isEnabled() &&
    -      this.handleKeyEventInternal(e)) {
    -    e.preventDefault();
    -    e.stopPropagation();
    -    return true;
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Attempts to handle a keyboard event; returns true if the event was handled,
    - * false otherwise.  Considered protected; should only be used within this
    - * package and by subclasses.
    - * @param {goog.events.KeyEvent} e Key event to handle.
    - * @return {boolean} Whether the key event was handled.
    - * @protected
    - */
    -goog.ui.Control.prototype.handleKeyEventInternal = function(e) {
    -  return e.keyCode == goog.events.KeyCodes.ENTER &&
    -      this.performActionInternal(e);
    -};
    -
    -
    -// Register the default renderer for goog.ui.Controls.
    -goog.ui.registry.setDefaultRenderer(goog.ui.Control, goog.ui.ControlRenderer);
    -
    -
    -// Register a decorator factory function for goog.ui.Controls.
    -goog.ui.registry.setDecoratorByClassName(goog.ui.ControlRenderer.CSS_CLASS,
    -    function() {
    -      return new goog.ui.Control(null);
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/control_perf.html b/src/database/third_party/closure-library/closure/goog/ui/control_perf.html
    deleted file mode 100644
    index 901195ba1e3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/control_perf.html
    +++ /dev/null
    @@ -1,166 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -Author:  attila@google.com (Attila Bodis)
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -  <title>Closure Performance Tests - goog.ui.Control</title>
    -  <link rel="stylesheet" type="text/css" href="../testing/performancetable.css" />
    -  <script src="../base.js"></script>
    -  <script>
    -    goog.require('goog.dom');
    -    goog.require('goog.testing.PerformanceTable');
    -    goog.require('goog.testing.jsunit');
    -    goog.require('goog.ui.Control');
    -  </script>
    -</head>
    -<body>
    -  <h1>goog.ui.Control Performance Tests</h1>
    -  <p>
    -    <b>User-agent:</b> <script>document.write(navigator.userAgent);</script>
    -  </p>
    -  <div id="perfTable"></div>
    -  <hr>
    -  <div id="renderSandbox"></div>
    -  <div id="decorateSandbox"></div>
    -  <script>
    -    // The sandboxen.
    -    var renderSandbox = goog.dom.getElement('renderSandbox');
    -    var decorateSandbox = goog.dom.getElement('decorateSandbox');
    -
    -    // Arrays of rendered/decorated controls (so we can dispose of them).
    -    var renderedControls;
    -    var decoratedControls;
    -
    -    // 0-based index of the control currently being rendered/decorated.
    -    var renderIndex;
    -    var decorateIndex;
    -
    -    // Element currently being decorated.
    -    var elementToDecorate;
    -
    -    // Number of controls to create/decorate per test run.
    -    var SAMPLES_PER_RUN = 100;
    -
    -    // The performance table.
    -    var table;
    -
    -    // Sets up a render test.
    -    function setUpRenderTest() {
    -      renderedControls = [];
    -      renderIndex = 0;
    -    }
    -
    -    // Cleans up after a render test.
    -    function cleanUpAfterRenderTest() {
    -      for (var i = 0, count = renderedControls.length; i < count; i++) {
    -        renderedControls[i].dispose();
    -      }
    -      renderedControls = null;
    -      goog.dom.removeChildren(renderSandbox);
    -    }
    -
    -    // Sets up a decorate test.
    -    function setUpDecorateTest(opt_count) {
    -      var count = opt_count || 1000;
    -      for (var i = 0; i < count; i++) {
    -        decorateSandbox.appendChild(goog.dom.createDom('div', 'goog-control',
    -            'W00t!'));
    -      }
    -      elementToDecorate = decorateSandbox.firstChild;
    -      decoratedControls = [];
    -      decorateIndex = 0;
    -    }
    -
    -    // Cleans up after a decorate test.
    -    function cleanUpAfterDecorateTest() {
    -      for (var i = 0, count = decoratedControls.length; i < count; i++) {
    -        decoratedControls[i].dispose();
    -      }
    -      decoratedControls = null;
    -      goog.dom.removeChildren(decorateSandbox);
    -    }
    -
    -    // Renders the given number of controls.  Since children are appended to
    -    // the same parent element in each performance test run, we keep track of
    -    // the current index via the global renderIndex variable.
    -    function renderControls(count, autoDetectBiDi) {
    -      for (var i = 0; i < count; i++) {
    -        var control = new goog.ui.Control('W00t!');
    -        if (!autoDetectBiDi) {
    -          control.setRightToLeft(false);
    -        }
    -        control.render(renderSandbox);
    -        renderedControls[renderIndex++] = control;
    -      }
    -    }
    -
    -    // Decorates "count" controls.  The decorate sandbox contains enough child
    -    // elements for the whole test, but we only decorate up to "count" elements
    -    // per test run, so we need to keep track of where we are via the global
    -    // decorateIndex and elementToDecorate variables.
    -    function decorateControls(count, autoDetectBiDi) {
    -      for (var i = 0; i < count; i++) {
    -        var next = elementToDecorate.nextSibling;
    -        var control = new goog.ui.Control();
    -        if (!autoDetectBiDi) {
    -          control.setRightToLeft(false);
    -        }
    -        control.decorate(elementToDecorate);
    -        decoratedControls[decorateIndex++] = control;
    -        elementToDecorate = next;
    -      }
    -    }
    -
    -    function setUpPage() {
    -      table = new goog.testing.PerformanceTable(
    -          goog.dom.getElement('perfTable'));
    -    }
    -
    -    function testRender() {
    -      setUpRenderTest();
    -      table.run(goog.partial(renderControls, SAMPLES_PER_RUN, true),
    -          'Render ' + SAMPLES_PER_RUN + ' controls (default)');
    -      cleanUpAfterRenderTest();
    -      assertEquals('The expected number of controls must have been rendered',
    -          SAMPLES_PER_RUN * table.getTimer().getNumSamples(), renderIndex);
    -    }
    -
    -    function testDecorate() {
    -      setUpDecorateTest(SAMPLES_PER_RUN * table.getTimer().getNumSamples());
    -      table.run(goog.partial(decorateControls, SAMPLES_PER_RUN, true),
    -          'Decorate ' + SAMPLES_PER_RUN + ' controls (default)');
    -      cleanUpAfterDecorateTest();
    -      assertEquals('The expected number of controls must have been decorated',
    -          SAMPLES_PER_RUN * table.getTimer().getNumSamples(), decorateIndex);
    -      assertNull('All controls must have been decorated', elementToDecorate);
    -    }
    -
    -    function testRenderNoBiDiAutoDetect() {
    -      setUpRenderTest();
    -      table.run(goog.partial(renderControls, SAMPLES_PER_RUN, false),
    -          'Render ' + SAMPLES_PER_RUN + ' controls (no BiDi auto-detect)');
    -      cleanUpAfterRenderTest();
    -      assertEquals('The expected number of controls must have been rendered',
    -          SAMPLES_PER_RUN * table.getTimer().getNumSamples(), renderIndex);
    -    }
    -
    -    function testDecorateNoBiDiAutoDetect() {
    -      setUpDecorateTest(SAMPLES_PER_RUN * table.getTimer().getNumSamples());
    -      table.run(goog.partial(decorateControls, SAMPLES_PER_RUN, false),
    -          'Decorate ' + SAMPLES_PER_RUN + ' controls (no BiDi auto-detect)');
    -      cleanUpAfterDecorateTest();
    -      assertEquals('The expected number of controls must have been decorated',
    -          SAMPLES_PER_RUN * table.getTimer().getNumSamples(), decorateIndex);
    -      assertNull('All controls must have been decorated', elementToDecorate);
    -    }
    -  </script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/control_test.html b/src/database/third_party/closure-library/closure/goog/ui/control_test.html
    deleted file mode 100644
    index 0e045ff57ce..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/control_test.html
    +++ /dev/null
    @@ -1,27 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -Author: attila@google.com (Attila Bodis)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.Control
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.ControlTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="sandbox">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/control_test.js b/src/database/third_party/closure-library/closure/goog/ui/control_test.js
    deleted file mode 100644
    index 75b01fd1be8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/control_test.js
    +++ /dev/null
    @@ -1,2383 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.ControlTest');
    -goog.setTestOnly('goog.ui.ControlTest');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events');
    -goog.require('goog.events.BrowserEvent');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.object');
    -goog.require('goog.string');
    -goog.require('goog.style');
    -goog.require('goog.testing.ExpectedFailures');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.events.Event');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.Control');
    -goog.require('goog.ui.ControlRenderer');
    -goog.require('goog.ui.registry');
    -goog.require('goog.userAgent');
    -
    -// Disabled due to problems on farm.
    -var testFocus = false;
    -
    -var control;
    -
    -var ALL_EVENTS = goog.object.getValues(goog.ui.Component.EventType);
    -var events = {};
    -var expectedFailures;
    -var sandbox;
    -var aria = goog.a11y.aria;
    -var State = goog.a11y.aria.State;
    -
    -function setUpPage() {
    -  expectedFailures = new goog.testing.ExpectedFailures();
    -  sandbox = document.getElementById('sandbox');
    -}
    -
    -
    -
    -/**
    - * A dummy renderer, for testing purposes.
    - * @constructor
    - * @extends {goog.ui.ControlRenderer}
    - */
    -function TestRenderer() {
    -  goog.ui.ControlRenderer.call(this);
    -}
    -goog.inherits(TestRenderer, goog.ui.ControlRenderer);
    -
    -
    -/**
    - * Initializes the testcase prior to execution.
    - */
    -function setUp() {
    -  control = new goog.ui.Control('Hello');
    -  control.setDispatchTransitionEvents(goog.ui.Component.State.ALL, true);
    -  goog.events.listen(control, ALL_EVENTS, countEvent);
    -}
    -
    -
    -/**
    - * Cleans up after executing the testcase.
    - */
    -function tearDown() {
    -  control.dispose();
    -  expectedFailures.handleTearDown();
    -  goog.dom.removeChildren(sandbox);
    -  resetEventCount();
    -}
    -
    -
    -/**
    - * Resets the global counter for events dispatched by test objects.
    - */
    -function resetEventCount() {
    -  goog.object.clear(events);
    -}
    -
    -
    -/**
    - * Increments the global counter for events of this type.
    - * @param {goog.events.Event} e Event to count.
    - */
    -function countEvent(e) {
    -  var type = e.type;
    -  var target = e.target;
    -
    -  if (!events[target]) {
    -    events[target] = {};
    -  }
    -
    -  if (events[target][type]) {
    -    events[target][type]++;
    -  } else {
    -    events[target][type] = 1;
    -  }
    -}
    -
    -
    -/**
    - * Returns the number of times test objects dispatched events of the given
    - * type since the global counter was last reset.
    - * @param {goog.ui.Control} target Event target.
    - * @param {string} type Event type.
    - * @return {number} Number of events of this type.
    - */
    -function getEventCount(target, type) {
    -  return events[target] && events[target][type] || 0;
    -}
    -
    -
    -/**
    - * Returns true if no events were dispatched since the last reset.
    - * @return {boolean} Whether no events have been dispatched since the last
    - *     reset.
    - */
    -function noEventsDispatched() {
    -  return !events || goog.object.isEmpty(events);
    -}
    -
    -
    -/**
    - * Returns the number of event listeners created by the control.
    - * @param {goog.ui.Control} control Control whose event listers are to be
    - *     counted.
    - * @return {number} Number of event listeners.
    - */
    -function getListenerCount(control) {
    -  return control.googUiComponentHandler_ ?
    -      goog.object.getCount(control.getHandler().keys_) : 0;
    -}
    -
    -
    -/**
    - * Simulates a mousedown event on the given element, including focusing it.
    - * @param {Element} element Element on which to simulate mousedown.
    - * @param {goog.events.BrowserEvent.MouseButton=} opt_button Mouse button;
    - *     defaults to {@code goog.events.BrowserEvent.MouseButton.LEFT}.
    - * @return {boolean} Whether the event was allowed to proceed.
    - */
    -function fireMouseDownAndFocus(element, opt_button) {
    -  var result = goog.testing.events.fireMouseDownEvent(element, opt_button);
    -  if (result) {
    -    // Browsers move focus for all buttons, not just the left button.
    -    element.focus();
    -  }
    -  return result;
    -}
    -
    -
    -/**
    - * @return {boolean} Whether we're on Mac Safari 3.x.
    - */
    -function isMacSafari3() {
    -  return goog.userAgent.WEBKIT && goog.userAgent.MAC &&
    -      !goog.userAgent.isVersionOrHigher('527');
    -}
    -
    -
    -/**
    - * Tests the {@link goog.ui.Control} constructor.
    - */
    -function testConstructor() {
    -  assertNotNull('Constructed control must not be null', control);
    -  assertEquals('Content must have expected value', 'Hello',
    -      control.getContent());
    -  assertEquals('Renderer must default to the registered renderer',
    -      goog.ui.registry.getDefaultRenderer(goog.ui.Control),
    -      control.getRenderer());
    -
    -  var content = goog.dom.createDom('div', null, 'Hello',
    -      goog.dom.createDom('b', null, 'World'));
    -  var testRenderer = new TestRenderer();
    -  var fakeDomHelper = {};
    -  var foo = new goog.ui.Control(content, testRenderer, fakeDomHelper);
    -  assertNotNull('Constructed object must not be null', foo);
    -  assertEquals('Content must have expected value', content,
    -      foo.getContent());
    -  assertEquals('Renderer must have expected value', testRenderer,
    -      foo.getRenderer());
    -  assertEquals('DOM helper must have expected value', fakeDomHelper,
    -      foo.getDomHelper());
    -  foo.dispose();
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#getHandler}.
    - */
    -function testGetHandler() {
    -  assertUndefined('Event handler must be undefined before getHandler() ' +
    -      'is called', control.googUiComponentHandler_);
    -  var handler = control.getHandler();
    -  assertNotNull('Event handler must not be null', handler);
    -  assertEquals('getHandler() must return the same instance if called again',
    -      handler, control.getHandler());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#isHandleMouseEvents}.
    - */
    -function testIsHandleMouseEvents() {
    -  assertTrue('Controls must handle their own mouse events by default',
    -      control.isHandleMouseEvents());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#setHandleMouseEvents}.
    - */
    -function testSetHandleMouseEvents() {
    -  assertTrue('Control must handle its own mouse events by default',
    -      control.isHandleMouseEvents());
    -  control.setHandleMouseEvents(false);
    -  assertFalse('Control must no longer handle its own mouse events',
    -      control.isHandleMouseEvents());
    -  control.setHandleMouseEvents(true);
    -  assertTrue('Control must once again handle its own mouse events',
    -      control.isHandleMouseEvents());
    -  control.render(sandbox);
    -  assertTrue('Rendered control must handle its own mouse events',
    -      control.isHandleMouseEvents());
    -  control.setHandleMouseEvents(false);
    -  assertFalse('Rendered control must no longer handle its own mouse events',
    -      control.isHandleMouseEvents());
    -  control.setHandleMouseEvents(true);
    -  assertTrue('Rendered control must once again handle its own mouse events',
    -      control.isHandleMouseEvents());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#getKeyEventTarget}.
    - */
    -function testGetKeyEventTarget() {
    -  assertNull('Key event target of control without DOM must be null',
    -      control.getKeyEventTarget());
    -  control.createDom();
    -  assertEquals('Key event target of control with DOM must be its element',
    -      control.getElement(), control.getKeyEventTarget());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#getKeyHandler}.
    - */
    -function testGetKeyHandler() {
    -  assertUndefined('Key handler must be undefined before getKeyHandler() ' +
    -      'is called', control.keyHandler_);
    -  var keyHandler = control.getKeyHandler();
    -  assertNotNull('Key handler must not be null', keyHandler);
    -  assertEquals('getKeyHandler() must return the same instance if called ' +
    -      'again', keyHandler, control.getKeyHandler());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#getRenderer}.
    - */
    -function testGetRenderer() {
    -  assertEquals('Renderer must be the default registered renderer',
    -      goog.ui.registry.getDefaultRenderer(goog.ui.Control),
    -      control.getRenderer());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#setRenderer}.
    - */
    -function testSetRenderer() {
    -  control.createDom();
    -  assertNotNull('Control must have a DOM', control.getElement());
    -  assertFalse('Control must not be in the document',
    -      control.isInDocument());
    -  assertEquals('Renderer must be the default registered renderer',
    -      goog.ui.registry.getDefaultRenderer(goog.ui.Control),
    -      control.getRenderer());
    -
    -  var testRenderer = new TestRenderer();
    -  control.setRenderer(testRenderer);
    -  assertNull('Control must not have a DOM after its renderer is reset',
    -      control.getElement());
    -  assertFalse('Control still must not be in the document',
    -      control.isInDocument());
    -  assertEquals('Renderer must have expected value', testRenderer,
    -      control.getRenderer());
    -
    -  control.render(sandbox);
    -  assertTrue('Control must be in the document', control.isInDocument());
    -
    -  assertThrows('Resetting the renderer after the control has entered ' +
    -      'the document must throw error',
    -      function() {
    -        control.setRenderer({});
    -      });
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#getExtraClassNames}.
    - */
    -function testGetExtraClassNames() {
    -  assertNull('Control must not have any extra class names by default',
    -      control.getExtraClassNames());
    -}
    -
    -
    -/**
    -  * Tests {@link goog.ui.Control#addExtraClassName} and
    -  * {@link goog.ui.Control#removeExtraClassName}.
    -  */
    -function testAddRemoveClassName() {
    -  assertNull('Control must not have any extra class names by default',
    -      control.getExtraClassNames());
    -  control.addClassName('foo');
    -  assertArrayEquals('Control must have expected extra class names',
    -      ['foo'], control.getExtraClassNames());
    -  assertNull('Control must not have a DOM', control.getElement());
    -
    -  control.createDom();
    -  assertSameElements('Control\'s element must have expected class names',
    -      ['goog-control', 'foo'],
    -      goog.dom.classlist.get(control.getElement()));
    -
    -  control.addClassName('bar');
    -  assertArrayEquals('Control must have expected extra class names',
    -      ['foo', 'bar'], control.getExtraClassNames());
    -  assertSameElements('Control\'s element must have expected class names',
    -      ['goog-control', 'foo', 'bar'],
    -      goog.dom.classlist.get(control.getElement()));
    -
    -  control.addClassName('bar');
    -  assertArrayEquals('Adding the same class name again must be a no-op',
    -      ['foo', 'bar'], control.getExtraClassNames());
    -  assertSameElements('Adding the same class name again must be a no-op',
    -      ['goog-control', 'foo', 'bar'],
    -      goog.dom.classlist.get(control.getElement()));
    -
    -  control.addClassName(null);
    -  assertArrayEquals('Adding null class name must be a no-op',
    -      ['foo', 'bar'], control.getExtraClassNames());
    -  assertSameElements('Adding null class name must be a no-op',
    -      ['goog-control', 'foo', 'bar'],
    -      goog.dom.classlist.get(control.getElement()));
    -
    -  control.removeClassName(null);
    -  assertArrayEquals('Removing null class name must be a no-op',
    -      ['foo', 'bar'], control.getExtraClassNames());
    -  assertSameElements('Removing null class name must be a no-op',
    -      ['goog-control', 'foo', 'bar'],
    -      goog.dom.classlist.get(control.getElement()));
    -
    -  control.removeClassName('foo');
    -  assertArrayEquals('Control must have expected extra class names',
    -      ['bar'], control.getExtraClassNames());
    -  assertSameElements('Control\'s element must have expected class names',
    -      ['goog-control', 'bar'],
    -      goog.dom.classlist.get(control.getElement()));
    -
    -  control.removeClassName('bar');
    -  assertNull('Control must not have any extra class names',
    -      control.getExtraClassNames());
    -  assertSameElements('Control\'s element must have expected class names',
    -      ['goog-control'],
    -      goog.dom.classlist.get(control.getElement()));
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#enableClassName}.
    - */
    -function testEnableClassName() {
    -  assertNull('Control must not have any extra class names by default',
    -      control.getExtraClassNames());
    -
    -  control.enableClassName('foo', true);
    -  assertArrayEquals('Control must have expected extra class names',
    -      ['foo'], control.getExtraClassNames());
    -
    -  control.enableClassName('bar', true);
    -  assertArrayEquals('Control must have expected extra class names',
    -      ['foo', 'bar'], control.getExtraClassNames());
    -
    -  control.enableClassName('bar', true);
    -  assertArrayEquals('Enabling the same class name again must be a no-op',
    -      ['foo', 'bar'], control.getExtraClassNames());
    -
    -  control.enableClassName(null);
    -  assertArrayEquals('Enabling null class name must be a no-op',
    -      ['foo', 'bar'], control.getExtraClassNames());
    -
    -  control.enableClassName('foo', false);
    -  assertArrayEquals('Control must have expected extra class names',
    -      ['bar'], control.getExtraClassNames());
    -
    -  control.enableClassName('bar', false);
    -  assertNull('Control must not have any extra class names',
    -      control.getExtraClassNames());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#createDom}.
    - */
    -function testCreateDom() {
    -  assertNull('Control must not have a DOM by default',
    -      control.getElement());
    -  assertFalse('Control must not allow text selection by default',
    -      control.isAllowTextSelection());
    -  assertTrue('Control must be visible by default', control.isVisible());
    -
    -  control.createDom();
    -  assertNotNull('Control must have a DOM', control.getElement());
    -  assertTrue('Control\'s element must be unselectable',
    -      goog.style.isUnselectable(control.getElement()));
    -  assertTrue('Control\'s element must be visible',
    -      control.getElement().style.display != 'none');
    -
    -  control.setAllowTextSelection(true);
    -  control.createDom();
    -  assertFalse('Control\'s element must be selectable',
    -      goog.style.isUnselectable(control.getElement()));
    -
    -  control.setVisible(false);
    -  control.createDom();
    -  assertTrue('Control\'s element must be hidden',
    -      control.getElement().style.display == 'none');
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#getContentElement}.
    - */
    -function testGetContentElement() {
    -  assertNull('Unrendered control must not have a content element',
    -      control.getContentElement());
    -  control.createDom();
    -  assertEquals('Control\'s content element must equal its root element',
    -      control.getElement(), control.getContentElement());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#canDecorate}.
    - */
    -function testCanDecorate() {
    -  assertTrue(control.canDecorate(goog.dom.createElement('div')));
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#decorateInternal}.
    - */
    -function testDecorateInternal() {
    -  sandbox.innerHTML = '<div id="foo">Hello, <b>World</b>!</div>';
    -  var foo = goog.dom.getElement('foo');
    -  control.decorate(foo);
    -  assertEquals('Decorated control\'s element must have expected value',
    -      foo, control.getElement());
    -  assertTrue('Element must be unselectable',
    -      goog.style.isUnselectable(control.getElement()));
    -  assertTrue('Element must be visible',
    -      control.getElement().style.display != 'none');
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#decorateInternal} with a control that
    - * allows text selection.
    - */
    -function testDecorateInternalForSelectableControl() {
    -  sandbox.innerHTML = '<div id="foo">Hello, <b>World</b>!</div>';
    -  var foo = goog.dom.getElement('foo');
    -  control.setAllowTextSelection(true);
    -  control.decorate(foo);
    -  assertEquals('Decorated control\'s element must have expected value',
    -      foo, control.getElement());
    -  assertFalse('Element must be selectable',
    -      goog.style.isUnselectable(control.getElement()));
    -  assertTrue('Control must be visible', control.isVisible());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#decorateInternal} with a hidden element.
    - */
    -function testDecorateInternalForHiddenElement() {
    -  sandbox.innerHTML = '<div id="foo" style="display:none">Hello!</div>';
    -  var foo = goog.dom.getElement('foo');
    -  control.decorate(foo);
    -  assertEquals('Decorated control\'s element must have expected value',
    -      foo, control.getElement());
    -  assertTrue('Element must be unselectable',
    -      goog.style.isUnselectable(control.getElement()));
    -  assertFalse('Control must be hidden', control.isVisible());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#enterDocument}.
    - */
    -function testEnterDocument() {
    -  control.render(sandbox);
    -  assertTrue('Control must be in the document', control.isInDocument());
    -  if (goog.userAgent.IE) {
    -    assertEquals('Control must have 5 mouse & 3 key event listeners on IE',
    -        8, getListenerCount(control));
    -  } else {
    -    assertEquals('Control must have 4 mouse and 3 key event listeners', 7,
    -        getListenerCount(control));
    -  }
    -  assertEquals('Control\'s key event handler must be attached to its ' +
    -      'key event target', control.getKeyEventTarget(),
    -      control.getKeyHandler().element_);
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#enterDocument} for a control that doesn't
    - * handle mouse events.
    - */
    -function testEnterDocumentForControlWithoutMouseHandling() {
    -  control.setHandleMouseEvents(false);
    -  control.render(sandbox);
    -  assertTrue('Control must be in the document', control.isInDocument());
    -  assertEquals('Control must have 3 key event listeners', 3,
    -      getListenerCount(control));
    -  assertEquals('Control\'s key event handler must be attached to its ' +
    -      'key event target', control.getKeyEventTarget(),
    -      control.getKeyHandler().element_);
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#enterDocument} for a control that isn't
    - * focusable.
    - */
    -function testEnterDocumentForNonFocusableControl() {
    -  control.setSupportedState(goog.ui.Component.State.FOCUSED, false);
    -  control.render(sandbox);
    -  assertTrue('Control must be in the document', control.isInDocument());
    -  if (goog.userAgent.IE) {
    -    assertEquals('Control must have 5 mouse event listeners on IE', 5,
    -        getListenerCount(control));
    -  } else {
    -    assertEquals('Control must have 4 mouse event listeners', 4,
    -        getListenerCount(control));
    -  }
    -  assertUndefined('Control must not have a key event handler',
    -      control.keyHandler_);
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#enterDocument} for a control that doesn't
    - * need to do any event handling.
    - */
    -function testEnterDocumentForControlWithoutEventHandlers() {
    -  control.setHandleMouseEvents(false);
    -  control.setSupportedState(goog.ui.Component.State.FOCUSED, false);
    -  control.render(sandbox);
    -  assertTrue('Control must be in the document', control.isInDocument());
    -  assertEquals('Control must have 0 event listeners', 0,
    -      getListenerCount(control));
    -  assertUndefined('Control must not have an event handler',
    -      control.googUiComponentHandler_);
    -  assertUndefined('Control must not have a key event handler',
    -      control.keyHandler_);
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#exitDocument}.
    - */
    -function testExitDocument() {
    -  control.render(sandbox);
    -  assertTrue('Control must be in the document', control.isInDocument());
    -  if (goog.userAgent.IE) {
    -    assertEquals('Control must have 5 mouse & 3 key event listeners on IE',
    -        8, getListenerCount(control));
    -  } else {
    -    assertEquals('Control must have 4 mouse and 3 key event listeners', 7,
    -        getListenerCount(control));
    -  }
    -  assertEquals('Control\'s key event handler must be attached to its ' +
    -      'key event target', control.getKeyEventTarget(),
    -      control.getKeyHandler().element_);
    -  // Expected to fail on Mac Safari prior to version 527.
    -  expectedFailures.expectFailureFor(isMacSafari3());
    -  try {
    -    assertTrue('Control\'s element must support keyboard focus',
    -        goog.dom.isFocusableTabIndex(control.getKeyEventTarget()));
    -  } catch (e) {
    -    expectedFailures.handleException(e);
    -  }
    -
    -  control.exitDocument();
    -  assertFalse('Control must no longer be in the document',
    -      control.isInDocument());
    -  assertEquals('Control must have no event listeners', 0,
    -      getListenerCount(control));
    -  assertNull('Control\'s key event handler must be unattached',
    -      control.getKeyHandler().element_);
    -  assertFalse('Control\'s element must no longer support keyboard focus',
    -      goog.dom.isFocusableTabIndex(control.getKeyEventTarget()));
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#dispose}.
    - */
    -function testDispose() {
    -  control.render(sandbox);
    -  var handler = control.getHandler();
    -  var keyHandler = control.getKeyHandler();
    -  control.dispose();
    -  assertFalse('Control must no longer be in the document',
    -      control.isInDocument());
    -  assertTrue('Control must have been disposed of', control.isDisposed());
    -  assertUndefined('Renderer must have been deleted', control.getRenderer());
    -  assertNull('Content must be nulled out', control.getContent());
    -  assertTrue('Event handler must have been disposed of',
    -      handler.isDisposed());
    -  assertUndefined('Event handler must have been deleted',
    -      control.googUiComponentHandler_);
    -  assertTrue('Key handler must have been disposed of',
    -      keyHandler.isDisposed());
    -  assertUndefined('Key handler must have been deleted',
    -      control.keyHandler_);
    -  assertNull('Extra class names must have been nulled out',
    -      control.getExtraClassNames());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#getContent}.
    - */
    -function testGetContent() {
    -  assertNull('Empty control must have null content',
    -      (new goog.ui.Control(null)).getContent());
    -  assertEquals('Control must have expected content', 'Hello',
    -      control.getContent());
    -  control.render(sandbox);
    -  assertEquals('Control must have expected content after rendering',
    -      'Hello', control.getContent());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#getContent}.
    - */
    -function testGetContentForDecoratedControl() {
    -  sandbox.innerHTML =
    -      '<div id="empty"></div>\n' +
    -      '<div id="text">Hello, world!</div>\n' +
    -      '<div id="element"><span>Foo</span></div>\n' +
    -      '<div id="nodelist">Hello, <b>world</b>!</div>\n';
    -
    -  var empty = new goog.ui.Control(null);
    -  empty.decorate(goog.dom.getElement('empty'));
    -  assertNull('Content of control decorating empty DIV must be null',
    -      empty.getContent());
    -  empty.dispose();
    -
    -  var text = new goog.ui.Control(null);
    -  text.decorate(goog.dom.getElement('text'));
    -  assertEquals('Content of control decorating DIV with text contents ' +
    -      'must be as expected', 'Hello, world!', text.getContent().nodeValue);
    -  text.dispose();
    -
    -  var element = new goog.ui.Control(null);
    -  element.decorate(goog.dom.getElement('element'));
    -  assertEquals('Content of control decorating DIV with element child ' +
    -      'must be as expected', goog.dom.getElement('element').firstChild,
    -      element.getContent());
    -  element.dispose();
    -
    -  var nodelist = new goog.ui.Control(null);
    -  nodelist.decorate(goog.dom.getElement('nodelist'));
    -  assertSameElements('Content of control decorating DIV with mixed ' +
    -      'contents must be as expected',
    -      goog.dom.getElement('nodelist').childNodes, nodelist.getContent());
    -  nodelist.dispose();
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#setAriaLabel}.
    - */
    -function testSetAriaLabel_render() {
    -  assertNull('Controls must not have any aria label by default',
    -      control.getAriaLabel());
    -
    -  control.setAriaLabel('label');
    -  assertEquals('Control must have aria label', 'label', control.getAriaLabel());
    -
    -  control.render(sandbox);
    -
    -  var elem = control.getElementStrict();
    -  assertEquals(
    -      'Element must have control\'s aria label after rendering',
    -      'label',
    -      goog.a11y.aria.getLabel(elem));
    -
    -  control.setAriaLabel('new label');
    -  assertEquals('Element must have the new aria label',
    -      'new label',
    -      goog.a11y.aria.getLabel(elem));
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#setAriaLabel}.
    - */
    -function testSetAriaLabel_decorate() {
    -  assertNull('Controls must not have any aria label by default',
    -      control.getAriaLabel());
    -
    -  control.setAriaLabel('label');
    -  assertEquals('Control must have aria label', 'label', control.getAriaLabel());
    -
    -  sandbox.innerHTML = '<div id="nodelist" role="button">' +
    -      'Hello, <b>world</b>!</div>';
    -  control.decorate(goog.dom.getElement('nodelist'));
    -
    -  var elem = control.getElementStrict();
    -  assertEquals(
    -      'Element must have control\'s aria label after rendering',
    -      'label',
    -      goog.a11y.aria.getLabel(elem));
    -  assertEquals(
    -      'Element must have the correct role',
    -      'button',
    -      elem.getAttribute('role'));
    -
    -  control.setAriaLabel('new label');
    -  assertEquals('Element must have the new aria label',
    -      'new label',
    -      goog.a11y.aria.getLabel(elem));
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#setContent}.
    - */
    -function testSetContent() {
    -  control.setContent('Bye');
    -  assertEquals('Unrendered control control must have expected contents',
    -      'Bye', control.getContent());
    -  assertNull('No DOM must be created by setContent', control.getElement());
    -
    -  control.createDom();
    -  assertEquals('Rendered control\'s DOM must have expected contents',
    -      'Bye', control.getElement().innerHTML);
    -
    -  control.setContent(null);
    -  assertNull('Rendered control must have expected contents',
    -      control.getContent());
    -  assertEquals('Rendered control\'s DOM must have expected contents',
    -      '', control.getElement().innerHTML);
    -
    -  control.setContent([goog.dom.createDom('div', null,
    -      goog.dom.createDom('span', null, 'Hello')), 'World']);
    -  assertHTMLEquals('Control\'s DOM must be updated',
    -      '<div><span>Hello</span></div>World', control.getElement().innerHTML);
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#setContentInternal}.
    - */
    -function testSetContentInternal() {
    -  control.render(sandbox);
    -  assertEquals('Control must have expected content after rendering',
    -      'Hello', control.getContent());
    -  control.setContentInternal('Bye');
    -  assertEquals('Control must have expected contents',
    -      'Bye', control.getContent());
    -  assertEquals('Control\'s DOM must be unchanged', 'Hello',
    -      control.getElement().innerHTML);
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#getCaption}.
    - */
    -function testGetCaption() {
    -  assertEquals('Empty control\'s caption must be empty string', '',
    -      (new goog.ui.Control(null)).getCaption());
    -
    -  assertEquals('Caption must have expected value', 'Hello',
    -      control.getCaption());
    -
    -  sandbox.innerHTML = '<div id="nodelist">Hello, <b>world</b>!</div>';
    -  control.decorate(goog.dom.getElement('nodelist'));
    -  assertEquals('Caption must have expected value', 'Hello, world!',
    -      control.getCaption());
    -
    -  var arrayContent = goog.array.clone(goog.dom.htmlToDocumentFragment(
    -      ' <b> foo</b><i>  bar</i> ').childNodes);
    -  control.setContent(arrayContent);
    -  assertEquals('whitespaces must be normalized in the caption',
    -      'foo bar', control.getCaption());
    -
    -  control.setContent('\xa0foo');
    -  assertEquals('indenting spaces must be kept', '\xa0foo',
    -      control.getCaption());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#setCaption}.
    - */
    -function testSetCaption() {
    -  control.setCaption('Hello, world!');
    -  assertEquals('Control must have a string caption "Hello, world!"',
    -      'Hello, world!', control.getCaption());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#setRightToLeft}.
    - */
    -function testSetRightToLeft() {
    -  control.createDom();
    -  assertFalse('Control\'s element must not have right-to-left class',
    -      goog.dom.classlist.contains(control.getElement(),
    -          'goog-control-rtl'));
    -  control.setRightToLeft(true);
    -  assertTrue('Control\'s element must have right-to-left class',
    -      goog.dom.classlist.contains(control.getElement(),
    -          'goog-control-rtl'));
    -  control.render(sandbox);
    -  assertThrows('Changing the render direction of a control already in ' +
    -      'the document is an error',
    -      function() {
    -        control.setRightToLeft(false);
    -      });
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#isAllowTextSelection}.
    - */
    -function testIsAllowTextSelection() {
    -  assertFalse('Controls must not allow text selection by default',
    -      control.isAllowTextSelection());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#setAllowTextSelection}.
    - */
    -function testSetAllowTextSelection() {
    -  assertFalse('Controls must not allow text selection by default',
    -      control.isAllowTextSelection());
    -
    -  control.setAllowTextSelection(true);
    -  assertTrue('Control must allow text selection',
    -      control.isAllowTextSelection());
    -
    -  control.setAllowTextSelection(false);
    -  assertFalse('Control must no longer allow text selection',
    -      control.isAllowTextSelection());
    -
    -  control.render(sandbox);
    -
    -  assertFalse('Control must not allow text selection even after rendered',
    -      control.isAllowTextSelection());
    -
    -  control.setAllowTextSelection(true);
    -  assertTrue('Control must once again allow text selection',
    -      control.isAllowTextSelection());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#isVisible}.
    - */
    -function testIsVisible() {
    -  assertTrue('Controls must be visible by default', control.isVisible());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#setVisible} before it is rendered.
    - */
    -function testSetVisible() {
    -  assertFalse('setVisible(true) must return false if already visible',
    -      control.setVisible(true));
    -  assertTrue('No events must have been dispatched', noEventsDispatched());
    -
    -  assertTrue('setVisible(false) must return true if previously visible',
    -      control.setVisible(false));
    -  assertEquals('One HIDE event must have been dispatched',
    -      1, getEventCount(control, goog.ui.Component.EventType.HIDE));
    -  assertFalse('Control must no longer be visible', control.isVisible());
    -
    -  assertTrue('setVisible(true) must return true if previously hidden',
    -      control.setVisible(true));
    -  assertEquals('One SHOW event must have been dispatched',
    -      1, getEventCount(control, goog.ui.Component.EventType.SHOW));
    -  assertTrue('Control must be visible', control.isVisible());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#setVisible} after it is rendered.
    - */
    -function testSetVisibleForRenderedControl() {
    -  control.render(sandbox);
    -  assertTrue('No events must have been dispatched during rendering',
    -      noEventsDispatched());
    -
    -  assertFalse('setVisible(true) must return false if already visible',
    -      control.setVisible(true));
    -  assertTrue('No events must have been dispatched', noEventsDispatched());
    -  assertTrue('Control\'s element must be visible',
    -      control.getElement().style.display != 'none');
    -
    -  assertTrue('setVisible(false) must return true if previously visible',
    -      control.setVisible(false));
    -  assertEquals('One HIDE event must have been dispatched',
    -      1, getEventCount(control, goog.ui.Component.EventType.HIDE));
    -  assertFalse('Control must no longer be visible', control.isVisible());
    -  assertTrue('Control\'s element must be hidden',
    -      control.getElement().style.display == 'none');
    -
    -  assertTrue('setVisible(true) must return true if previously hidden',
    -      control.setVisible(true));
    -  assertEquals('One SHOW event must have been dispatched',
    -      1, getEventCount(control, goog.ui.Component.EventType.SHOW));
    -  assertTrue('Control must be visible', control.isVisible());
    -  assertTrue('Control\'s element must be visible',
    -      control.getElement().style.display != 'none');
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#setVisible} for disabled non-focusable
    - * controls.
    - */
    -function testSetVisibleForDisabledNonFocusableControl() {
    -  // Hidden, disabled, non-focusable control becoming visible.
    -  control.setEnabled(false);
    -  control.setSupportedState(goog.ui.Component.State.FOCUSED, false);
    -  control.render(sandbox);
    -  assertTrue('Control must be visible', control.isVisible());
    -  assertFalse('Control must not have a tab index',
    -      goog.dom.isFocusableTabIndex(control.getKeyEventTarget()));
    -
    -  // Visible, disabled, non-focusable control becoming hidden.
    -  control.getKeyEventTarget().focus();
    -  assertEquals('Control must not have dispatched FOCUS', 0,
    -      getEventCount(control, goog.ui.Component.EventType.FOCUS));
    -  assertFalse('Control must not have keyboard focus', control.isFocused());
    -  control.setVisible(false);
    -  assertFalse('Control must be hidden', control.isVisible());
    -  assertFalse('Control must not have a tab index',
    -      goog.dom.isFocusableTabIndex(control.getKeyEventTarget()));
    -  assertEquals('Control must have dispatched HIDE', 1,
    -      getEventCount(control, goog.ui.Component.EventType.HIDE));
    -  assertEquals('Control must not have dispatched BLUR', 0,
    -      getEventCount(control, goog.ui.Component.EventType.BLUR));
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#setVisible} for disabled focusable controls.
    - */
    -function testSetVisibleForDisabledFocusableControl() {
    -  // Hidden, disabled, focusable control becoming visible.
    -  control.setEnabled(false);
    -  control.setSupportedState(goog.ui.Component.State.FOCUSED, true);
    -  control.render(sandbox);
    -  assertTrue('Control must be visible', control.isVisible());
    -  assertFalse('Control must not have a tab index',
    -      goog.dom.isFocusableTabIndex(control.getKeyEventTarget()));
    -
    -  // Visible, disabled, focusable control becoming hidden.
    -  control.getKeyEventTarget().focus();
    -  assertEquals('Control must not have dispatched FOCUS', 0,
    -      getEventCount(control, goog.ui.Component.EventType.FOCUS));
    -  assertFalse('Control must not have keyboard focus', control.isFocused());
    -  control.setVisible(false);
    -  assertFalse('Control must be hidden', control.isVisible());
    -  assertFalse('Control must not have a tab index',
    -      goog.dom.isFocusableTabIndex(control.getKeyEventTarget()));
    -  assertEquals('Control must have dispatched HIDE', 1,
    -      getEventCount(control, goog.ui.Component.EventType.HIDE));
    -  assertEquals('Control must not have dispatched BLUR', 0,
    -      getEventCount(control, goog.ui.Component.EventType.BLUR));
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#setVisible} for enabled non-focusable
    - * controls.
    - */
    -function testSetVisibleForEnabledNonFocusableControl() {
    -  // Hidden, enabled, non-focusable control becoming visible.
    -  control.setEnabled(true);
    -  control.setSupportedState(goog.ui.Component.State.FOCUSED, false);
    -  control.render(sandbox);
    -  assertTrue('Control must be visible', control.isVisible());
    -  assertFalse('Control must not have a tab index',
    -      goog.dom.isFocusableTabIndex(control.getKeyEventTarget()));
    -
    -  if (testFocus) {
    -    // Visible, enabled, non-focusable control becoming hidden.
    -    control.getKeyEventTarget().focus();
    -    assertEquals('Control must not have dispatched FOCUS', 0,
    -        getEventCount(control, goog.ui.Component.EventType.FOCUS));
    -    assertFalse('Control must not have keyboard focus',
    -        control.isFocused());
    -    control.setVisible(false);
    -    assertFalse('Control must be hidden', control.isVisible());
    -    assertFalse('Control must not have a tab index',
    -        goog.dom.isFocusableTabIndex(control.getKeyEventTarget()));
    -    assertEquals('Control must have dispatched HIDE', 1,
    -        getEventCount(control, goog.ui.Component.EventType.HIDE));
    -    assertEquals('Control must not have dispatched BLUR', 0,
    -        getEventCount(control, goog.ui.Component.EventType.BLUR));
    -  }
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#setVisible} for enabled focusable controls.
    - */
    -function testSetVisibleForEnabledFocusableControl() {
    -  // Hidden, enabled, focusable control becoming visible.
    -  control.setEnabled(true);
    -  control.setSupportedState(goog.ui.Component.State.FOCUSED, true);
    -  control.render(sandbox);
    -  assertTrue('Control must be visible', control.isVisible());
    -
    -  if (testFocus) {
    -    // Expected to fail on Mac Safari prior to version 527.
    -    expectedFailures.expectFailureFor(isMacSafari3());
    -    try {
    -      // Mac Safari currently doesn't support tabIndex on arbitrary
    -      // elements.
    -      assertTrue('Control must have a tab index',
    -          goog.dom.isFocusableTabIndex(control.getKeyEventTarget()));
    -    } catch (e) {
    -      expectedFailures.handleException(e);
    -    }
    -
    -    // Visible, enabled, focusable control becoming hidden.
    -    control.getKeyEventTarget().focus();
    -
    -    // Expected to fail on IE.
    -    expectedFailures.expectFailureFor(goog.userAgent.IE);
    -    try {
    -      // IE dispatches focus and blur events asynchronously!
    -      assertEquals('Control must have dispatched FOCUS', 1,
    -          getEventCount(control, goog.ui.Component.EventType.FOCUS));
    -      assertTrue('Control must have keyboard focus', control.isFocused());
    -    } catch (e) {
    -      expectedFailures.handleException(e);
    -    }
    -
    -    control.setVisible(false);
    -    assertFalse('Control must be hidden', control.isVisible());
    -    assertFalse('Control must not have a tab index',
    -        goog.dom.isFocusableTabIndex(control.getKeyEventTarget()));
    -    assertEquals('Control must have dispatched HIDE', 1,
    -        getEventCount(control, goog.ui.Component.EventType.HIDE));
    -
    -    // Expected to fail on IE.
    -    expectedFailures.expectFailureFor(goog.userAgent.IE);
    -    try {
    -      // IE dispatches focus and blur events asynchronously!
    -      assertEquals('Control must have dispatched BLUR', 1,
    -          getEventCount(control, goog.ui.Component.EventType.BLUR));
    -      assertFalse('Control must no longer have keyboard focus',
    -          control.isFocused());
    -    } catch (e) {
    -      expectedFailures.handleException(e);
    -    }
    -  }
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#isEnabled}.
    - */
    -function testIsEnabled() {
    -  assertTrue('Controls must be enabled by default', control.isEnabled());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#setEnabled}.
    - */
    -function testSetEnabled() {
    -  control.render(sandbox);
    -  control.setHighlighted(true);
    -  control.setActive(true);
    -  control.getKeyEventTarget().focus();
    -
    -  resetEventCount();
    -
    -  control.setEnabled(true);
    -  assertTrue('No events must have been dispatched', noEventsDispatched());
    -  assertTrue('Control must be enabled', control.isEnabled());
    -  assertTrue('Control must be highlighted', control.isHighlighted());
    -  assertTrue('Control must be active', control.isActive());
    -  var elem = control.getElementStrict();
    -  assertTrue('Control element must not have aria-disabled',
    -      goog.string.isEmptyOrWhitespace(aria.getState(elem, State.DISABLED)));
    -  assertEquals('Control element must have a tabIndex of 0', 0,
    -      goog.string.toNumber(elem.getAttribute('tabIndex') || ''));
    -
    -  if (testFocus) {
    -    // Expected to fail on IE and Mac Safari 3.  IE calls focus handlers
    -    // asynchronously, and Mac Safari 3 doesn't support keyboard focus.
    -    expectedFailures.expectFailureFor(goog.userAgent.IE);
    -    expectedFailures.expectFailureFor(isMacSafari3());
    -    try {
    -      assertTrue('Control must be focused', control.isFocused());
    -    } catch (e) {
    -      expectedFailures.handleException(e);
    -    }
    -  }
    -
    -  resetEventCount();
    -
    -  control.setEnabled(false);
    -  assertEquals('One DISABLE event must have been dispatched', 1,
    -      getEventCount(control, goog.ui.Component.EventType.DISABLE));
    -  assertFalse('Control must be disabled', control.isEnabled());
    -  assertFalse('Control must not be highlighted', control.isHighlighted());
    -  assertFalse('Control must not be active', control.isActive());
    -  assertFalse('Control must not be focused', control.isFocused());
    -  assertEquals('Control element must have aria-disabled true', 'true',
    -      aria.getState(control.getElementStrict(), State.DISABLED));
    -  assertNull('Control element must not have a tabIndex',
    -      control.getElement().getAttribute('tabIndex'));
    -
    -  control.setEnabled(true);
    -  control.exitDocument();
    -  var cssClass = goog.getCssName(goog.ui.ControlRenderer.CSS_CLASS, 'disabled');
    -  var element = goog.dom.createDom('div', {tabIndex: 0});
    -  element.className = cssClass;
    -  goog.dom.appendChild(sandbox, element);
    -  control.decorate(element);
    -  assertEquals('Control element must have aria-disabled true', 'true',
    -      aria.getState(control.getElementStrict(), State.DISABLED));
    -  assertNull('Control element must not have a tabIndex',
    -      control.getElement().getAttribute('tabIndex'));
    -  control.setEnabled(true);
    -  elem = control.getElementStrict();
    -  assertEquals('Control element must have aria-disabled false', 'false',
    -      aria.getState(elem, State.DISABLED));
    -  assertEquals('Control element must have tabIndex 0', 0,
    -      goog.string.toNumber(elem.getAttribute('tabIndex') || ''));
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#setState} when using
    - * goog.ui.Component.State.DISABLED.
    - */
    -function testSetStateWithDisabled() {
    -  control.render(sandbox);
    -  control.setHighlighted(true);
    -  control.setActive(true);
    -  control.getKeyEventTarget().focus();
    -
    -  resetEventCount();
    -
    -  control.setState(goog.ui.Component.State.DISABLED, false);
    -  assertTrue('No events must have been dispatched', noEventsDispatched());
    -  assertTrue('Control must be enabled', control.isEnabled());
    -  assertTrue('Control must be highlighted', control.isHighlighted());
    -  assertTrue('Control must be active', control.isActive());
    -  assertTrue('Control element must not have aria-disabled', goog.string.isEmptyOrWhitespace(
    -      aria.getState(control.getElementStrict(), State.DISABLED)));
    -  assertEquals('Control element must have a tabIndex of 0', 0,
    -      goog.string.toNumber(
    -          control.getElement().getAttribute('tabIndex') || ''));
    -
    -  if (testFocus) {
    -    // Expected to fail on IE and Mac Safari 3.  IE calls focus handlers
    -    // asynchronously, and Mac Safari 3 doesn't support keyboard focus.
    -    expectedFailures.expectFailureFor(goog.userAgent.IE);
    -    expectedFailures.expectFailureFor(isMacSafari3());
    -    try {
    -      assertTrue('Control must be focused', control.isFocused());
    -    } catch (e) {
    -      expectedFailures.handleException(e);
    -    }
    -  }
    -
    -  resetEventCount();
    -
    -  control.setState(goog.ui.Component.State.DISABLED, true);
    -  assertEquals('One DISABLE event must have been dispatched', 1,
    -      getEventCount(control, goog.ui.Component.EventType.DISABLE));
    -  assertFalse('Control must be disabled', control.isEnabled());
    -  assertFalse('Control must not be highlighted', control.isHighlighted());
    -  assertFalse('Control must not be active', control.isActive());
    -  assertFalse('Control must not be focused', control.isFocused());
    -  assertEquals('Control element must have aria-disabled true', 'true',
    -      aria.getState(control.getElementStrict(), State.DISABLED));
    -  assertNull('Control element must not have a tabIndex',
    -      control.getElement().getAttribute('tabIndex'));
    -
    -  control.setState(goog.ui.Component.State.DISABLED, false);
    -  control.exitDocument();
    -  var cssClass = goog.getCssName(goog.ui.ControlRenderer.CSS_CLASS, 'disabled');
    -  var element = goog.dom.createDom('div', {tabIndex: 0});
    -  element.className = cssClass;
    -  goog.dom.appendChild(sandbox, element);
    -  control.decorate(element);
    -  assertEquals('Control element must have aria-disabled true', 'true',
    -      aria.getState(control.getElementStrict(), State.DISABLED));
    -  assertNull('Control element must not have a tabIndex',
    -      control.getElement().getAttribute('tabIndex'));
    -  control.setState(goog.ui.Component.State.DISABLED, false);
    -  elem = control.getElementStrict();
    -  assertEquals('Control element must have aria-disabled false', 'false',
    -      aria.getState(elem, State.DISABLED));
    -  assertEquals('Control element must have tabIndex 0', 0,
    -      goog.string.toNumber(elem.getAttribute('tabIndex') || ''));
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#setEnabled} when the control has a parent.
    - */
    -function testSetEnabledWithParent() {
    -  var child = new goog.ui.Control(null);
    -  child.setDispatchTransitionEvents(goog.ui.Component.State.ALL, true);
    -  control.addChild(child, true /* opt_render */);
    -  control.setEnabled(false);
    -
    -  resetEventCount();
    -
    -  assertFalse('Parent must be disabled', control.isEnabled());
    -  assertTrue('Child must be enabled', child.isEnabled());
    -
    -  child.setEnabled(false);
    -  assertTrue('No events must have been dispatched when child is disabled',
    -      noEventsDispatched());
    -  assertTrue('Child must still be enabled', child.isEnabled());
    -
    -  resetEventCount();
    -
    -  control.setEnabled(true);
    -  assertEquals('One ENABLE event must have been dispatched by the parent',
    -      1, getEventCount(control, goog.ui.Component.EventType.ENABLE));
    -  assertTrue('Parent must be enabled', control.isEnabled());
    -  assertTrue('Child must still be enabled', child.isEnabled());
    -
    -  resetEventCount();
    -
    -  child.setEnabled(false);
    -  assertEquals('One DISABLE event must have been dispatched by the child',
    -      1, getEventCount(child, goog.ui.Component.EventType.DISABLE));
    -  assertTrue('Parent must still be enabled', control.isEnabled());
    -  assertFalse('Child must now be disabled', child.isEnabled());
    -
    -  resetEventCount();
    -
    -  control.setEnabled(false);
    -  assertEquals('One DISABLE event must have been dispatched by the parent',
    -      1, getEventCount(control, goog.ui.Component.EventType.DISABLE));
    -  assertFalse('Parent must now be disabled', control.isEnabled());
    -  assertFalse('Child must still be disabled', child.isEnabled());
    -
    -  child.dispose();
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#isHighlighted}.
    - */
    -function testIsHighlighted() {
    -  assertFalse('Controls must not be highlighted by default',
    -      control.isHighlighted());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#setHighlighted}.
    - */
    -function testSetHighlighted() {
    -  control.setSupportedState(goog.ui.Component.State.HOVER, false);
    -
    -  control.setHighlighted(true);
    -  assertFalse('Control must not be highlighted, because it isn\'t ' +
    -      'highlightable', control.isHighlighted());
    -  assertTrue('Control must not have dispatched any events',
    -      noEventsDispatched());
    -
    -  control.setSupportedState(goog.ui.Component.State.HOVER, true);
    -
    -  control.setHighlighted(true);
    -  assertTrue('Control must be highlighted', control.isHighlighted());
    -  assertEquals('Control must have dispatched a HIGHLIGHT event', 1,
    -      getEventCount(control, goog.ui.Component.EventType.HIGHLIGHT));
    -
    -  control.setHighlighted(true);
    -  assertTrue('Control must still be highlighted', control.isHighlighted());
    -  assertEquals('Control must not dispatch more HIGHLIGHT events', 1,
    -      getEventCount(control, goog.ui.Component.EventType.HIGHLIGHT));
    -
    -  control.setHighlighted(false);
    -  assertFalse('Control must not be highlighted', control.isHighlighted());
    -  assertEquals('Control must have dispatched an UNHIGHLIGHT event', 1,
    -      getEventCount(control, goog.ui.Component.EventType.UNHIGHLIGHT));
    -  control.setEnabled(false);
    -  assertFalse('Control must be disabled', control.isEnabled());
    -
    -  control.setHighlighted(true);
    -  assertTrue('Control must be highlighted, even when disabled',
    -      control.isHighlighted());
    -  assertEquals('Control must have dispatched another HIGHLIGHT event', 2,
    -      getEventCount(control, goog.ui.Component.EventType.HIGHLIGHT));
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#isActive}.
    - */
    -function testIsActive() {
    -  assertFalse('Controls must not be active by default', control.isActive());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#setActive}.
    - */
    -function testSetActive() {
    -  control.setSupportedState(goog.ui.Component.State.ACTIVE, false);
    -
    -  control.setActive(true);
    -  assertFalse('Control must not be active, because it isn\'t activateable',
    -      control.isActive());
    -  assertTrue('Control must not have dispatched any events',
    -      noEventsDispatched());
    -
    -  control.setSupportedState(goog.ui.Component.State.ACTIVE, true);
    -
    -  control.setActive(true);
    -  assertTrue('Control must be active', control.isActive());
    -  assertEquals('Control must have dispatched an ACTIVATE event', 1,
    -      getEventCount(control, goog.ui.Component.EventType.ACTIVATE));
    -
    -  control.setActive(true);
    -  assertTrue('Control must still be active', control.isActive());
    -  assertEquals('Control must not dispatch more ACTIVATE events', 1,
    -      getEventCount(control, goog.ui.Component.EventType.ACTIVATE));
    -
    -  control.setEnabled(false);
    -  assertFalse('Control must be disabled', control.isEnabled());
    -  assertFalse('Control must not be active', control.isActive());
    -  assertEquals('Control must have dispatched a DEACTIVATE event', 1,
    -      getEventCount(control, goog.ui.Component.EventType.DEACTIVATE));
    -}
    -
    -
    -/**
    - * Tests disposing the control from an action event handler.
    - */
    -function testDisposeOnAction() {
    -  goog.events.listen(control, goog.ui.Component.EventType.ACTION,
    -      function(e) {
    -        control.dispose();
    -      });
    -
    -  // Control must not throw an exception if disposed of in an ACTION event
    -  // handler.
    -  control.performActionInternal();
    -  control.setActive(true);
    -  assertTrue('Control should have been disposed of', control.isDisposed());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#isSelected}.
    - */
    -function testIsSelected() {
    -  assertFalse('Controls must not be selected by default',
    -      control.isSelected());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#setSelected}.
    - */
    -function testSetSelected() {
    -  control.setSupportedState(goog.ui.Component.State.SELECTED, false);
    -
    -  control.setSelected(true);
    -  assertFalse('Control must not be selected, because it isn\'t selectable',
    -      control.isSelected());
    -  assertTrue('Control must not have dispatched any events',
    -      noEventsDispatched());
    -
    -  control.setSupportedState(goog.ui.Component.State.SELECTED, true);
    -
    -  control.setSelected(true);
    -  assertTrue('Control must be selected', control.isSelected());
    -  assertEquals('Control must have dispatched a SELECT event', 1,
    -      getEventCount(control, goog.ui.Component.EventType.SELECT));
    -
    -  control.setSelected(true);
    -  assertTrue('Control must still be selected', control.isSelected());
    -  assertEquals('Control must not dispatch more SELECT events', 1,
    -      getEventCount(control, goog.ui.Component.EventType.SELECT));
    -
    -  control.setSelected(false);
    -  assertFalse('Control must not be selected', control.isSelected());
    -  assertEquals('Control must have dispatched an UNSELECT event', 1,
    -      getEventCount(control, goog.ui.Component.EventType.UNSELECT));
    -  control.setEnabled(false);
    -  assertFalse('Control must be disabled', control.isEnabled());
    -
    -  control.setSelected(true);
    -  assertTrue('Control must be selected, even when disabled',
    -      control.isSelected());
    -  assertEquals('Control must have dispatched another SELECT event', 2,
    -      getEventCount(control, goog.ui.Component.EventType.SELECT));
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#isChecked}.
    - */
    -function testIsChecked() {
    -  assertFalse('Controls must not be checked by default',
    -      control.isChecked());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#setChecked}.
    - */
    -function testSetChecked() {
    -  control.setSupportedState(goog.ui.Component.State.CHECKED, false);
    -
    -  control.setChecked(true);
    -  assertFalse('Control must not be checked, because it isn\'t checkable',
    -      control.isChecked());
    -  assertTrue('Control must not have dispatched any events',
    -      noEventsDispatched());
    -
    -  control.setSupportedState(goog.ui.Component.State.CHECKED, true);
    -
    -  control.setChecked(true);
    -  assertTrue('Control must be checked', control.isChecked());
    -  assertEquals('Control must have dispatched a CHECK event', 1,
    -      getEventCount(control, goog.ui.Component.EventType.CHECK));
    -
    -  control.setChecked(true);
    -  assertTrue('Control must still be checked', control.isChecked());
    -  assertEquals('Control must not dispatch more CHECK events', 1,
    -      getEventCount(control, goog.ui.Component.EventType.CHECK));
    -
    -  control.setChecked(false);
    -  assertFalse('Control must not be checked', control.isChecked());
    -  assertEquals('Control must have dispatched an UNCHECK event', 1,
    -      getEventCount(control, goog.ui.Component.EventType.UNCHECK));
    -  control.setEnabled(false);
    -  assertFalse('Control must be disabled', control.isEnabled());
    -
    -  control.setChecked(true);
    -  assertTrue('Control must be checked, even when disabled',
    -      control.isChecked());
    -  assertEquals('Control must have dispatched another CHECK event', 2,
    -      getEventCount(control, goog.ui.Component.EventType.CHECK));
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#isFocused}.
    - */
    -function testIsFocused() {
    -  assertFalse('Controls must not be focused by default',
    -      control.isFocused());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#setFocused}.
    - */
    -function testSetFocused() {
    -  control.setSupportedState(goog.ui.Component.State.FOCUSED, false);
    -
    -  control.setFocused(true);
    -  assertFalse('Control must not be focused, because it isn\'t focusable',
    -      control.isFocused());
    -  assertTrue('Control must not have dispatched any events',
    -      noEventsDispatched());
    -
    -  control.setSupportedState(goog.ui.Component.State.FOCUSED, true);
    -
    -  control.setFocused(true);
    -  assertTrue('Control must be focused', control.isFocused());
    -  assertEquals('Control must have dispatched a FOCUS event', 1,
    -      getEventCount(control, goog.ui.Component.EventType.FOCUS));
    -
    -  control.setFocused(true);
    -  assertTrue('Control must still be focused', control.isFocused());
    -  assertEquals('Control must not dispatch more FOCUS events', 1,
    -      getEventCount(control, goog.ui.Component.EventType.FOCUS));
    -
    -  control.setFocused(false);
    -  assertFalse('Control must not be focused', control.isFocused());
    -  assertEquals('Control must have dispatched an BLUR event', 1,
    -      getEventCount(control, goog.ui.Component.EventType.BLUR));
    -  control.setEnabled(false);
    -  assertFalse('Control must be disabled', control.isEnabled());
    -
    -  control.setFocused(true);
    -  assertTrue('Control must be focused, even when disabled',
    -      control.isFocused());
    -  assertEquals('Control must have dispatched another FOCUS event', 2,
    -      getEventCount(control, goog.ui.Component.EventType.FOCUS));
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#isOpen}.
    - */
    -function testIsOpen() {
    -  assertFalse('Controls must not be open by default', control.isOpen());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#setOpen}.
    - */
    -function testSetOpen() {
    -  control.setSupportedState(goog.ui.Component.State.OPENED, false);
    -
    -  control.setOpen(true);
    -  assertFalse('Control must not be opened, because it isn\'t openable',
    -      control.isOpen());
    -  assertTrue('Control must not have dispatched any events',
    -      noEventsDispatched());
    -
    -  control.setSupportedState(goog.ui.Component.State.OPENED, true);
    -
    -  control.setOpen(true);
    -  assertTrue('Control must be opened', control.isOpen());
    -  assertEquals('Control must have dispatched a OPEN event', 1,
    -      getEventCount(control, goog.ui.Component.EventType.OPEN));
    -
    -  control.setOpen(true);
    -  assertTrue('Control must still be opened', control.isOpen());
    -  assertEquals('Control must not dispatch more OPEN events', 1,
    -      getEventCount(control, goog.ui.Component.EventType.OPEN));
    -
    -  control.setOpen(false);
    -  assertFalse('Control must not be opened', control.isOpen());
    -  assertEquals('Control must have dispatched an CLOSE event', 1,
    -      getEventCount(control, goog.ui.Component.EventType.CLOSE));
    -  control.setEnabled(false);
    -  assertFalse('Control must be disabled', control.isEnabled());
    -
    -  control.setOpen(true);
    -  assertTrue('Control must be opened, even when disabled',
    -      control.isOpen());
    -  assertEquals('Control must have dispatched another OPEN event', 2,
    -      getEventCount(control, goog.ui.Component.EventType.OPEN));
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#getState}.
    - */
    -function testGetState() {
    -  assertEquals('Controls must be in the default state', 0x00,
    -      control.getState());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#hasState}.
    - */
    -function testHasState() {
    -  assertFalse('Control must not be disabled',
    -      control.hasState(goog.ui.Component.State.DISABLED));
    -  assertFalse('Control must not be in the HOVER state',
    -      control.hasState(goog.ui.Component.State.HOVER));
    -  assertFalse('Control must not be active',
    -      control.hasState(goog.ui.Component.State.ACTIVE));
    -  assertFalse('Control must not be selected',
    -      control.hasState(goog.ui.Component.State.SELECTED));
    -  assertFalse('Control must not be checked',
    -      control.hasState(goog.ui.Component.State.CHECKED));
    -  assertFalse('Control must not be focused',
    -      control.hasState(goog.ui.Component.State.FOCUSED));
    -  assertFalse('Control must not be open',
    -      control.hasState(goog.ui.Component.State.OPEN));
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#setState}.
    - */
    -function testSetState() {
    -  control.createDom();
    -  control.setSupportedState(goog.ui.Component.State.ACTIVE, false);
    -
    -  assertFalse('Control must not be active',
    -      control.hasState(goog.ui.Component.State.ACTIVE));
    -  control.setState(goog.ui.Component.State.ACTIVE, true);
    -  assertFalse('Control must still be inactive (because it doesn\'t ' +
    -      'support the ACTIVE state)',
    -      control.hasState(goog.ui.Component.State.ACTIVE));
    -
    -  control.setSupportedState(goog.ui.Component.State.ACTIVE, true);
    -
    -  control.setState(goog.ui.Component.State.ACTIVE, true);
    -  assertTrue('Control must be active',
    -      control.hasState(goog.ui.Component.State.ACTIVE));
    -  assertTrue('Control must have the active CSS style',
    -      goog.dom.classlist.contains(control.getElement(),
    -          'goog-control-active'));
    -
    -  control.setState(goog.ui.Component.State.ACTIVE, true);
    -  assertTrue('Control must still be active',
    -      control.hasState(goog.ui.Component.State.ACTIVE));
    -  assertTrue('Control must still have the active CSS style',
    -      goog.dom.classlist.contains(control.getElement(),
    -          'goog-control-active'));
    -
    -  assertTrue('No events must have been dispatched', noEventsDispatched());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#setStateInternal}.
    - */
    -function testSetStateInternal() {
    -  control.setStateInternal(0x00);
    -  assertEquals('State should be 0x00', 0x00, control.getState());
    -  control.setStateInternal(0x17);
    -  assertEquals('State should be 0x17', 0x17, control.getState());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#isSupportedState}.
    - */
    -function testIsSupportedState() {
    -  assertTrue('Control must support DISABLED',
    -      control.isSupportedState(goog.ui.Component.State.DISABLED));
    -  assertTrue('Control must support HOVER',
    -      control.isSupportedState(goog.ui.Component.State.HOVER));
    -  assertTrue('Control must support ACTIVE',
    -      control.isSupportedState(goog.ui.Component.State.ACTIVE));
    -  assertTrue('Control must support FOCUSED',
    -      control.isSupportedState(goog.ui.Component.State.FOCUSED));
    -  assertFalse('Control must no support SELECTED',
    -      control.isSupportedState(goog.ui.Component.State.SELECTED));
    -  assertFalse('Control must no support CHECKED',
    -      control.isSupportedState(goog.ui.Component.State.CHECKED));
    -  assertFalse('Control must no support OPENED',
    -      control.isSupportedState(goog.ui.Component.State.OPENED));
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#setSupportedState}.
    - */
    -function testSetSupportedState() {
    -  control.setSupportedState(goog.ui.Component.State.HOVER, true);
    -  assertTrue('Control must still support HOVER',
    -      control.isSupportedState(goog.ui.Component.State.HOVER));
    -
    -  control.setSupportedState(goog.ui.Component.State.HOVER, false);
    -  assertFalse('Control must no longer support HOVER',
    -      control.isSupportedState(goog.ui.Component.State.HOVER));
    -
    -  control.setState(goog.ui.Component.State.ACTIVE, true);
    -  control.setSupportedState(goog.ui.Component.State.ACTIVE, false);
    -  assertFalse('Control must no longer support ACTIVE',
    -      control.isSupportedState(goog.ui.Component.State.ACTIVE));
    -  assertFalse('Control must no longer be in the ACTIVE state',
    -      control.hasState(goog.ui.Component.State.ACTIVE));
    -
    -  control.render(sandbox);
    -
    -  control.setSupportedState(goog.ui.Component.State.FOCUSED, true);
    -  control.setState(goog.ui.Component.State.FOCUSED, true);
    -
    -  assertThrows('Must not be able to disable support for the FOCUSED ' +
    -      "state for a control that's already in the document and focused",
    -      function() {
    -        control.setSupportedState(goog.ui.Component.State.FOCUSED, false);
    -      });
    -
    -  assertTrue('No events must have been dispatched', noEventsDispatched());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#isAutoState}.
    - */
    -function testIsAutoState() {
    -  assertTrue('Control must have DISABLED as an auto-state',
    -      control.isAutoState(goog.ui.Component.State.DISABLED));
    -  assertTrue('Control must have HOVER as an auto-state',
    -      control.isAutoState(goog.ui.Component.State.HOVER));
    -  assertTrue('Control must have ACTIVE as an auto-state',
    -      control.isAutoState(goog.ui.Component.State.ACTIVE));
    -  assertTrue('Control must have FOCUSED as an auto-state',
    -      control.isAutoState(goog.ui.Component.State.FOCUSED));
    -
    -  assertFalse('Control must not have SELECTED as an auto-state',
    -      control.isAutoState(goog.ui.Component.State.SELECTED));
    -  assertFalse('Control must not have CHECKED as an auto-state',
    -      control.isAutoState(goog.ui.Component.State.CHECKED));
    -  assertFalse('Control must not have OPENED as an auto-state',
    -      control.isAutoState(goog.ui.Component.State.OPENED));
    -
    -  assertTrue('No events must have been dispatched', noEventsDispatched());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#setAutoStates}.
    - */
    -function testSetAutoStates() {
    -  control.setAutoStates(goog.ui.Component.State.HOVER, false);
    -  assertFalse('Control must not have HOVER as an auto-state',
    -      control.isAutoState(goog.ui.Component.State.HOVER));
    -
    -  control.setAutoStates(goog.ui.Component.State.ACTIVE |
    -      goog.ui.Component.State.FOCUSED, false);
    -  assertFalse('Control must not have ACTIVE as an auto-state',
    -      control.isAutoState(goog.ui.Component.State.ACTIVE));
    -  assertFalse('Control must not have FOCUSED as an auto-state',
    -      control.isAutoState(goog.ui.Component.State.FOCUSED));
    -
    -  control.setSupportedState(goog.ui.Component.State.FOCUSED, false);
    -  control.setAutoStates(goog.ui.Component.State.FOCUSED, true);
    -  assertFalse('Control must not have FOCUSED as an auto-state if it no ' +
    -      'longer supports FOCUSED',
    -      control.isAutoState(goog.ui.Component.State.FOCUSED));
    -
    -  assertTrue('No events must have been dispatched', noEventsDispatched());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#isDispatchTransitionEvents}.
    - */
    -function testIsDispatchTransitionEvents() {
    -  assertTrue('Control must dispatch DISABLED transition events',
    -      control.isDispatchTransitionEvents(goog.ui.Component.State.DISABLED));
    -  assertTrue('Control must dispatch HOVER transition events',
    -      control.isDispatchTransitionEvents(goog.ui.Component.State.HOVER));
    -  assertTrue('Control must dispatch ACTIVE transition events',
    -      control.isDispatchTransitionEvents(goog.ui.Component.State.ACTIVE));
    -  assertTrue('Control must dispatch FOCUSED transition events',
    -      control.isDispatchTransitionEvents(goog.ui.Component.State.FOCUSED));
    -
    -  assertFalse('Control must not dispatch SELECTED transition events',
    -      control.isDispatchTransitionEvents(goog.ui.Component.State.SELECTED));
    -  assertFalse('Control must not dispatch CHECKED transition events',
    -      control.isDispatchTransitionEvents(goog.ui.Component.State.CHECKED));
    -  assertFalse('Control must not dispatch OPENED transition events',
    -      control.isDispatchTransitionEvents(goog.ui.Component.State.OPENED));
    -
    -  assertTrue('No events must have been dispatched', noEventsDispatched());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#setDispatchTransitionEvents}.
    - */
    -function testSetDispatchTransitionEvents() {
    -  control.setDispatchTransitionEvents(goog.ui.Component.State.HOVER, false);
    -  assertFalse('Control must not dispatch HOVER transition events',
    -      control.isDispatchTransitionEvents(goog.ui.Component.State.HOVER));
    -
    -  control.setSupportedState(goog.ui.Component.State.SELECTED, true);
    -  control.setDispatchTransitionEvents(goog.ui.Component.State.SELECTED,
    -      true);
    -  assertTrue('Control must dispatch SELECTED transition events',
    -      control.isDispatchTransitionEvents(goog.ui.Component.State.SELECTED));
    -
    -  assertTrue('No events must have been dispatched', noEventsDispatched());
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#isTransitionAllowed}.
    - */
    -function testIsTransitionAllowed() {
    -  assertTrue('Control must support the HOVER state',
    -      control.isSupportedState(goog.ui.Component.State.HOVER));
    -  assertFalse('Control must not be in the HOVER state',
    -      control.hasState(goog.ui.Component.State.HOVER));
    -  assertTrue('Control must dispatch HOVER transition events',
    -      control.isDispatchTransitionEvents(goog.ui.Component.State.HOVER));
    -
    -  assertTrue('Control must be allowed to transition to the HOVER state',
    -      control.isTransitionAllowed(goog.ui.Component.State.HOVER, true));
    -  assertEquals('Control must have dispatched one HIGHLIGHT event', 1,
    -      getEventCount(control, goog.ui.Component.EventType.HIGHLIGHT));
    -  assertFalse('Control must not be highlighted',
    -      control.hasState(goog.ui.Component.State.HOVER));
    -
    -  control.setState(goog.ui.Component.State.HOVER, true);
    -  control.setDispatchTransitionEvents(goog.ui.Component.State.HOVER, false);
    -
    -  assertTrue('Control must be allowed to transition from the HOVER state',
    -      control.isTransitionAllowed(goog.ui.Component.State.HOVER, false));
    -  assertEquals('Control must not have dispatched any UNHIGHLIGHT events', 0,
    -      getEventCount(control, goog.ui.Component.EventType.UNHIGHLIGHT));
    -  assertTrue('Control must still be highlighted',
    -      control.hasState(goog.ui.Component.State.HOVER));
    -
    -  control.setSupportedState(goog.ui.Component.State.FOCUSED, false);
    -  resetEventCount();
    -
    -  assertFalse('Control doesn\'t support the FOCUSED state',
    -      control.isSupportedState(goog.ui.Component.State.FOCUSED));
    -  assertFalse('Control must not be FOCUSED',
    -      control.hasState(goog.ui.Component.State.FOCUSED));
    -  assertFalse('Control must not be allowed to transition to the FOCUSED ' +
    -      'state',
    -      control.isTransitionAllowed(goog.ui.Component.State.FOCUSED, true));
    -  assertEquals('Control must not have dispatched any FOCUS events', 0,
    -      getEventCount(control, goog.ui.Component.EventType.FOCUS));
    -
    -  control.setEnabled(false);
    -  resetEventCount();
    -
    -  assertTrue('Control must support the DISABLED state',
    -      control.isSupportedState(goog.ui.Component.State.DISABLED));
    -  assertTrue('Control must be DISABLED',
    -      control.hasState(goog.ui.Component.State.DISABLED));
    -  assertFalse('Control must not be allowed to transition to the DISABLED ' +
    -      'state, because it is already there',
    -      control.isTransitionAllowed(goog.ui.Component.State.DISABLED, true));
    -  assertEquals('Control must not have dispatched any ENABLE events', 0,
    -      getEventCount(control, goog.ui.Component.EventType.ENABLE));
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#handleKeyEvent}.
    - */
    -function testHandleKeyEvent() {
    -  control.render();
    -  control.isVisible = control.isEnabled = function() {
    -    return true;
    -  };
    -
    -
    -  goog.testing.events.fireKeySequence(
    -      control.getKeyEventTarget(), goog.events.KeyCodes.A);
    -
    -  assertEquals('Control must not have dispatched an ACTION event', 0,
    -      getEventCount(control, goog.ui.Component.EventType.ACTION));
    -
    -  goog.testing.events.fireKeySequence(
    -      control.getKeyEventTarget(), goog.events.KeyCodes.ENTER);
    -  assertEquals('Control must have dispatched an ACTION event', 1,
    -      getEventCount(control, goog.ui.Component.EventType.ACTION));
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#performActionInternal}.
    - */
    -function testPerformActionInternal() {
    -  assertFalse('Control must not be checked', control.isChecked());
    -  assertFalse('Control must not be selected', control.isSelected());
    -  assertFalse('Control must not be open', control.isOpen());
    -
    -  control.performActionInternal();
    -
    -  assertFalse('Control must not be checked', control.isChecked());
    -  assertFalse('Control must not be selected', control.isSelected());
    -  assertFalse('Control must not be open', control.isOpen());
    -  assertEquals('Control must have dispatched an ACTION event', 1,
    -      getEventCount(control, goog.ui.Component.EventType.ACTION));
    -
    -  control.setSupportedState(goog.ui.Component.State.CHECKED, true);
    -  control.setSupportedState(goog.ui.Component.State.SELECTED, true);
    -  control.setSupportedState(goog.ui.Component.State.OPENED, true);
    -
    -  control.performActionInternal();
    -
    -  assertTrue('Control must be checked', control.isChecked());
    -  assertTrue('Control must be selected', control.isSelected());
    -  assertTrue('Control must be open', control.isOpen());
    -  assertEquals('Control must have dispatched a CHECK event', 1,
    -      getEventCount(control, goog.ui.Component.EventType.CHECK));
    -  assertEquals('Control must have dispatched a SELECT event', 1,
    -      getEventCount(control, goog.ui.Component.EventType.SELECT));
    -  assertEquals('Control must have dispatched a OPEN event', 1,
    -      getEventCount(control, goog.ui.Component.EventType.OPEN));
    -  assertEquals('Control must have dispatched another ACTION event', 2,
    -      getEventCount(control, goog.ui.Component.EventType.ACTION));
    -
    -  control.performActionInternal();
    -
    -  assertFalse('Control must not be checked', control.isChecked());
    -  assertTrue('Control must be selected', control.isSelected());
    -  assertFalse('Control must not be open', control.isOpen());
    -  assertEquals('Control must have dispatched an UNCHECK event', 1,
    -      getEventCount(control, goog.ui.Component.EventType.UNCHECK));
    -  assertEquals('Control must not have dispatched an UNSELECT event', 0,
    -      getEventCount(control, goog.ui.Component.EventType.UNSELECT));
    -  assertEquals('Control must have dispatched a CLOSE event', 1,
    -      getEventCount(control, goog.ui.Component.EventType.CLOSE));
    -  assertEquals('Control must have dispatched another ACTION event', 3,
    -      getEventCount(control, goog.ui.Component.EventType.ACTION));
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#handleMouseOver}.
    - */
    -function testHandleMouseOver() {
    -  control.setContent(goog.dom.createDom('span', {id: 'caption'}, 'Hello'));
    -  control.render(sandbox);
    -
    -  var element = control.getElement();
    -  var caption = goog.dom.getElement('caption');
    -
    -  // Verify baseline assumptions.
    -  assertTrue('Caption must be contained within the control',
    -      goog.dom.contains(element, caption));
    -  assertTrue('Control must be enabled', control.isEnabled());
    -  assertTrue('HOVER must be an auto-state',
    -      control.isAutoState(goog.ui.Component.State.HOVER));
    -  assertFalse('Control must not start out highlighted',
    -      control.isHighlighted());
    -
    -  // Scenario 1:  relatedTarget is contained within the control's DOM.
    -  goog.testing.events.fireMouseOverEvent(element, caption);
    -  assertTrue('No events must have been dispatched for internal mouse move',
    -      noEventsDispatched());
    -  assertFalse('Control must not be highlighted for internal mouse move',
    -      control.isHighlighted());
    -  resetEventCount();
    -
    -  // Scenario 2:  preventDefault() is called on the ENTER event.
    -  var key = goog.events.listen(control, goog.ui.Component.EventType.ENTER,
    -      function(e) {
    -        e.preventDefault();
    -      });
    -  goog.testing.events.fireMouseOverEvent(element, sandbox);
    -  assertEquals('Control must have dispatched 1 ENTER event', 1,
    -      getEventCount(control, goog.ui.Component.EventType.ENTER));
    -  assertFalse('Control must not be highlighted if ENTER is canceled',
    -      control.isHighlighted());
    -  goog.events.unlistenByKey(key);
    -  resetEventCount();
    -
    -  // Scenario 3:  Control is disabled.
    -  control.setEnabled(false);
    -  goog.testing.events.fireMouseOverEvent(element, sandbox);
    -  assertEquals('Control must dispatch ENTER event on mouseover even if ' +
    -      'disabled', 1,
    -      getEventCount(control, goog.ui.Component.EventType.ENTER));
    -  assertFalse('Control must not be highlighted if it is disabled',
    -      control.isHighlighted());
    -  control.setEnabled(true);
    -  resetEventCount();
    -
    -  // Scenario 4:  HOVER is not an auto-state.
    -  control.setAutoStates(goog.ui.Component.State.HOVER, false);
    -  goog.testing.events.fireMouseOverEvent(element, sandbox);
    -  assertEquals('Control must dispatch ENTER event on mouseover even if ' +
    -      'HOVER is not an auto-state', 1,
    -      getEventCount(control, goog.ui.Component.EventType.ENTER));
    -  assertFalse('Control must not be highlighted if HOVER isn\'t an auto-' +
    -      'state', control.isHighlighted());
    -  control.setAutoStates(goog.ui.Component.State.HOVER, true);
    -  resetEventCount();
    -
    -  // Scenario 5:  All is well.
    -  goog.testing.events.fireMouseOverEvent(element, sandbox);
    -  assertEquals('Control must dispatch ENTER event on mouseover', 1,
    -      getEventCount(control, goog.ui.Component.EventType.ENTER));
    -  assertEquals('Control must dispatch HIGHLIGHT event on mouseover', 1,
    -      getEventCount(control, goog.ui.Component.EventType.HIGHLIGHT));
    -  assertTrue('Control must be highlighted', control.isHighlighted());
    -  resetEventCount();
    -
    -  // Scenario 6: relatedTarget is null
    -  control.setHighlighted(false);
    -  goog.testing.events.fireMouseOverEvent(element, null);
    -  assertEquals('Control must dispatch ENTER event on mouseover', 1,
    -      getEventCount(control, goog.ui.Component.EventType.ENTER));
    -  assertEquals('Control must dispatch HIGHLIGHT event on mouseover', 1,
    -      getEventCount(control, goog.ui.Component.EventType.HIGHLIGHT));
    -  assertTrue('Control must be highlighted', control.isHighlighted());
    -  resetEventCount();
    -}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#handleMouseOut}.
    - */
    -function testHandleMouseOut() {
    -  control.setContent(goog.dom.createDom('span', {id: 'caption'}, 'Hello'));
    -  control.setHighlighted(true);
    -  control.setActive(true);
    -
    -  resetEventCount();
    -
    -  control.render(sandbox);
    -
    -  var element = control.getElement();
    -  var caption = goog.dom.getElement('caption');
    -
    -  // Verify baseline assumptions.
    -  assertTrue('Caption must be contained within the control',
    -      goog.dom.contains(element, caption));
    -  assertTrue('Control must be enabled', control.isEnabled());
    -  assertTrue('HOVER must be an auto-state',
    -      control.isAutoState(goog.ui.Component.State.HOVER));
    -  assertTrue('ACTIVE must be an auto-state',
    -      control.isAutoState(goog.ui.Component.State.ACTIVE));
    -  assertTrue('Control must start out highlighted', control.isHighlighted());
    -  assertTrue('Control must start out active', control.isActive());
    -
    -  // Scenario 1:  relatedTarget is contained within the control's DOM.
    -  goog.testing.events.fireMouseOutEvent(element, caption);
    -  assertTrue('No events must have been dispatched for internal mouse move',
    -      noEventsDispatched());
    -  assertTrue('Control must not be un-highlighted for internal mouse move',
    -      control.isHighlighted());
    -  assertTrue('Control must not be deactivated for internal mouse move',
    -      control.isActive());
    -  resetEventCount();
    -
    -  // Scenario 2:  preventDefault() is called on the LEAVE event.
    -  var key = goog.events.listen(control, goog.ui.Component.EventType.LEAVE,
    -      function(e) {
    -        e.preventDefault();
    -      });
    -  goog.testing.events.fireMouseOutEvent(element, sandbox);
    -  assertEquals('Control must have dispatched 1 LEAVE event', 1,
    -      getEventCount(control, goog.ui.Component.EventType.LEAVE));
    -  assertTrue('Control must not be un-highlighted if LEAVE is canceled',
    -      control.isHighlighted());
    -  assertTrue('Control must not be deactivated if LEAVE is canceled',
    -      control.isActive());
    -  goog.events.unlistenByKey(key);
    -  resetEventCount();
    -
    -  // Scenario 3:  ACTIVE is not an auto-state.
    -  control.setAutoStates(goog.ui.Component.State.ACTIVE, false);
    -  goog.testing.events.fireMouseOutEvent(element, sandbox);
    -  assertEquals('Control must dispatch LEAVE event on mouseout even if ' +
    -      'ACTIVE is not an auto-state', 1,
    -      getEventCount(control, goog.ui.Component.EventType.LEAVE));
    -  assertTrue('Control must not be deactivated if ACTIVE isn\'t an auto-' +
    -      'state', control.isActive());
    -  assertFalse('Control must be un-highlighted even if ACTIVE isn\'t an ' +
    -      'auto-state', control.isHighlighted());
    -  control.setAutoStates(goog.ui.Component.State.ACTIVE, true);
    -  control.setHighlighted(true);
    -  resetEventCount();
    -
    -  // Scenario 4:  HOVER is not an auto-state.
    -  control.setAutoStates(goog.ui.Component.State.HOVER, false);
    -  goog.testing.events.fireMouseOutEvent(element, sandbox);
    -  assertEquals('Control must dispatch LEAVE event on mouseout even if ' +
    -      'HOVER is not an auto-state', 1,
    -      getEventCount(control, goog.ui.Component.EventType.LEAVE));
    -  assertFalse('Control must be deactivated even if HOVER isn\'t an auto-' +
    -      'state', control.isActive());
    -  assertTrue('Control must not be un-highlighted if HOVER isn\'t an auto-' +
    -      'state', control.isHighlighted());
    -  control.setAutoStates(goog.ui.Component.State.HOVER, true);
    -  control.setActive(true);
    -  resetEventCount();
    -
    -  // Scenario 5:  All is well.
    -  goog.testing.events.fireMouseOutEvent(element, sandbox);
    -  assertEquals('Control must dispatch LEAVE event on mouseout', 1,
    -      getEventCount(control, goog.ui.Component.EventType.LEAVE));
    -  assertEquals('Control must dispatch DEACTIVATE event on mouseout', 1,
    -      getEventCount(control, goog.ui.Component.EventType.DEACTIVATE));
    -  assertEquals('Control must dispatch UNHIGHLIGHT event on mouseout', 1,
    -      getEventCount(control, goog.ui.Component.EventType.UNHIGHLIGHT));
    -  assertFalse('Control must be deactivated', control.isActive());
    -  assertFalse('Control must be unhighlighted', control.isHighlighted());
    -  resetEventCount();
    -
    -  // Scenario 6: relatedTarget is null
    -  control.setActive(true);
    -  control.setHighlighted(true);
    -  goog.testing.events.fireMouseOutEvent(element, null);
    -  assertEquals('Control must dispatch LEAVE event on mouseout', 1,
    -      getEventCount(control, goog.ui.Component.EventType.LEAVE));
    -  assertEquals('Control must dispatch DEACTIVATE event on mouseout', 1,
    -      getEventCount(control, goog.ui.Component.EventType.DEACTIVATE));
    -  assertEquals('Control must dispatch UNHIGHLIGHT event on mouseout', 1,
    -      getEventCount(control, goog.ui.Component.EventType.UNHIGHLIGHT));
    -  assertFalse('Control must be deactivated', control.isActive());
    -  assertFalse('Control must be unhighlighted', control.isHighlighted());
    -  resetEventCount();
    -}
    -
    -function testIsMouseEventWithinElement() {
    -  var child = goog.dom.createElement('div');
    -  var parent = goog.dom.createDom('div', null, child);
    -  var notChild = goog.dom.createElement('div');
    -
    -  var event = new goog.testing.events.Event('mouseout');
    -  event.relatedTarget = child;
    -  assertTrue('Event is within element',
    -             goog.ui.Control.isMouseEventWithinElement_(event, parent));
    -
    -  var event = new goog.testing.events.Event('mouseout');
    -  event.relatedTarget = notChild;
    -  assertFalse('Event is not within element',
    -              goog.ui.Control.isMouseEventWithinElement_(event, parent));
    -}
    -
    -function testHandleMouseDown() {
    -  control.render(sandbox);
    -  assertFalse('preventDefault() must have been called for control that ' +
    -      'doesn\'t support text selection',
    -      fireMouseDownAndFocus(control.getElement()));
    -  assertTrue('Control must be highlighted', control.isHighlighted());
    -  assertTrue('Control must be active', control.isActive());
    -
    -  if (testFocus) {
    -    // Expected to fail on IE and Mac Safari 3.  IE calls focus handlers
    -    // asynchronously, and Mac Safari 3 doesn't support keyboard focus.
    -    expectedFailures.expectFailureFor(goog.userAgent.IE);
    -    expectedFailures.expectFailureFor(isMacSafari3());
    -    try {
    -      assertTrue('Control must be focused', control.isFocused());
    -    } catch (e) {
    -      expectedFailures.handleException(e);
    -    }
    -  }
    -}
    -
    -function testHandleMouseDownForDisabledControl() {
    -  control.setEnabled(false);
    -  control.render(sandbox);
    -  assertFalse('preventDefault() must have been called for control that ' +
    -      'doesn\'t support text selection',
    -      fireMouseDownAndFocus(control.getElement()));
    -  assertFalse('Control must not be highlighted', control.isHighlighted());
    -  assertFalse('Control must not be active', control.isActive());
    -  if (testFocus) {
    -    assertFalse('Control must not be focused', control.isFocused());
    -  }
    -}
    -
    -function testHandleMouseDownForNoHoverAutoState() {
    -  control.setAutoStates(goog.ui.Component.State.HOVER, false);
    -  control.render(sandbox);
    -  assertFalse('preventDefault() must have been called for control that ' +
    -      'doesn\'t support text selection',
    -      fireMouseDownAndFocus(control.getElement()));
    -  assertFalse('Control must not be highlighted', control.isHighlighted());
    -  assertTrue('Control must be active', control.isActive());
    -
    -  if (testFocus) {
    -    // Expected to fail on IE and Mac Safari 3.  IE calls focus handlers
    -    // asynchronously, and Mac Safari 3 doesn't support keyboard focus.
    -    expectedFailures.expectFailureFor(goog.userAgent.IE);
    -    expectedFailures.expectFailureFor(isMacSafari3());
    -    try {
    -      assertTrue('Control must be focused', control.isFocused());
    -    } catch (e) {
    -      expectedFailures.handleException(e);
    -    }
    -  }
    -}
    -
    -function testHandleMouseDownForRightMouseButton() {
    -  control.render(sandbox);
    -  assertTrue('preventDefault() must not have been called for right ' +
    -      'mouse button', fireMouseDownAndFocus(control.getElement(),
    -      goog.events.BrowserEvent.MouseButton.RIGHT));
    -  assertTrue('Control must be highlighted', control.isHighlighted());
    -  assertFalse('Control must not be active', control.isActive());
    -
    -  if (testFocus) {
    -    // Expected to fail on IE and Mac Safari 3.  IE calls focus handlers
    -    // asynchronously, and Mac Safari 3 doesn't support keyboard focus.
    -    expectedFailures.expectFailureFor(goog.userAgent.IE);
    -    expectedFailures.expectFailureFor(isMacSafari3());
    -    try {
    -      assertTrue('Control must be focused', control.isFocused());
    -    } catch (e) {
    -      expectedFailures.handleException(e);
    -    }
    -  }
    -}
    -
    -function testHandleMouseDownForNoActiveAutoState() {
    -  control.setAutoStates(goog.ui.Component.State.ACTIVE, false);
    -  control.render(sandbox);
    -  assertFalse('preventDefault() must have been called for control that ' +
    -      'doesn\'t support text selection',
    -      fireMouseDownAndFocus(control.getElement()));
    -  assertTrue('Control must be highlighted', control.isHighlighted());
    -  assertFalse('Control must not be active', control.isActive());
    -
    -  if (testFocus) {
    -    // Expected to fail on IE and Mac Safari 3.  IE calls focus handlers
    -    // asynchronously, and Mac Safari 3 doesn't support keyboard focus.
    -    expectedFailures.expectFailureFor(goog.userAgent.IE);
    -    expectedFailures.expectFailureFor(isMacSafari3());
    -    try {
    -      assertTrue('Control must be focused', control.isFocused());
    -    } catch (e) {
    -      expectedFailures.handleException(e);
    -    }
    -  }
    -}
    -
    -function testHandleMouseDownForNonFocusableControl() {
    -  control.setSupportedState(goog.ui.Component.State.FOCUSED, false);
    -  control.render(sandbox);
    -  assertFalse('preventDefault() must have been called for control that ' +
    -      'doesn\'t support text selection',
    -      fireMouseDownAndFocus(control.getElement()));
    -  assertTrue('Control must be highlighted', control.isHighlighted());
    -  assertTrue('Control must be active', control.isActive());
    -  assertFalse('Control must not be focused', control.isFocused());
    -}
    -
    -// TODO(attila): Find out why this is flaky on FF2/Linux and FF1.5/Win.
    -//function testHandleMouseDownForSelectableControl() {
    -//  control.setAllowTextSelection(true);
    -//  control.render(sandbox);
    -//  assertTrue('preventDefault() must not have been called for control ' +
    -//      'that supports text selection',
    -//      fireMouseDownAndFocus(control.getElement()));
    -//  assertTrue('Control must be highlighted', control.isHighlighted());
    -//  assertTrue('Control must be active', control.isActive());
    -//  // Expected to fail on IE and Mac Safari 3.  IE calls focus handlers
    -//  // asynchronously, and Mac Safari 3 doesn't support keyboard focus.
    -//  expectedFailures.expectFailureFor(goog.userAgent.IE);
    -//  expectedFailures.expectFailureFor(isMacSafari3());
    -//  try {
    -//    assertTrue('Control must be focused', control.isFocused());
    -//  } catch (e) {
    -//    expectedFailures.handleException(e);
    -//  }
    -//}
    -
    -
    -/**
    - * Tests {@link goog.ui.Control#handleMouseUp}.
    - */
    -function testHandleMouseUp() {
    -  control.setActive(true);
    -
    -  // Override performActionInternal() for testing purposes.
    -  var actionPerformed = false;
    -  control.performActionInternal = function() {
    -    actionPerformed = true;
    -    return true;
    -  };
    -
    -  resetEventCount();
    -
    -  control.render(sandbox);
    -  var element = control.getElement();
    -
    -  // Verify baseline assumptions.
    -  assertTrue('Control must be enabled', control.isEnabled());
    -  assertTrue('HOVER must be an auto-state',
    -      control.isAutoState(goog.ui.Component.State.HOVER));
    -  assertTrue('ACTIVE must be an auto-state',
    -      control.isAutoState(goog.ui.Component.State.ACTIVE));
    -  assertFalse('Control must not start out highlighted',
    -      control.isHighlighted());
    -  assertTrue('Control must start out active', control.isActive());
    -
    -  // Scenario 1:  Control is disabled.
    -  control.setEnabled(false);
    -  goog.testing.events.fireMouseUpEvent(element);
    -  assertFalse('Disabled control must not highlight on mouseup',
    -      control.isHighlighted());
    -  assertFalse('No action must have been performed', actionPerformed);
    -  control.setActive(true);
    -  control.setEnabled(true);
    -
    -  // Scenario 2:  HOVER is not an auto-state.
    -  control.setAutoStates(goog.ui.Component.State.HOVER, false);
    -  goog.testing.events.fireMouseUpEvent(element);
    -  assertFalse('Control must not highlight on mouseup if HOVER isn\'t an ' +
    -      'auto-state', control.isHighlighted());
    -  assertTrue('Action must have been performed even if HOVER isn\'t an ' +
    -      'auto-state', actionPerformed);
    -  assertFalse('Control must have been deactivated on mouseup even if ' +
    -      'HOVER isn\'t an auto-state', control.isActive());
    -  actionPerformed = false;
    -  control.setActive(true);
    -  control.setAutoStates(goog.ui.Component.State.HOVER, true);
    -
    -  // Scenario 3:  Control is not active.
    -  control.setActive(false);
    -  goog.testing.events.fireMouseUpEvent(element);
    -  assertTrue('Control must highlight on mouseup, even if inactive',
    -      control.isHighlighted());
    -  assertFalse('No action must have been performed if control is inactive',
    -      actionPerformed);
    -  assertFalse('Inactive control must remain inactive after mouseup',
    -      control.isActive());
    -  control.setHighlighted(false);
    -  control.setActive(true);
    -
    -  // Scenario 4:  performActionInternal() returns false.
    -  control.performActionInternal = function() {
    -    actionPerformed = true;
    -    return false;
    -  };
    -  goog.testing.events.fireMouseUpEvent(element);
    -  assertTrue('Control must highlight on mouseup, even if no action is ' +
    -      'performed', control.isHighlighted());
    -  assertTrue('performActionInternal must have been called',
    -      actionPerformed);
    -  assertTrue('Control must not deactivate if performActionInternal ' +
    -      'returns false', control.isActive());
    -  control.setHighlighted(false);
    -  actionPerformed = false;
    -  control.performActionInternal = function() {
    -    actionPerformed = true;
    -    return true;
    -  };
    -
    -  // Scenario 5:  ACTIVE is not an auto-state.
    -  control.setAutoStates(goog.ui.Component.State.ACTIVE, false);
    -  goog.testing.events.fireMouseUpEvent(element);
    -  assertTrue('Control must highlight on mouseup even if ACTIVE isn\'t an ' +
    -      'auto-state', control.isHighlighted());
    -  assertTrue('Action must have been performed even if ACTIVE isn\'t an ' +
    -      'auto-state', actionPerformed);
    -  assertTrue('Control must not have been deactivated on mouseup if ' +
    -      'ACTIVE isn\'t an auto-state', control.isActive());
    -  actionPerformed = false;
    -  control.setHighlighted(false);
    -  control.setAutoStates(goog.ui.Component.State.ACTIVE, true);
    -
    -  // Scenario 6:  All is well.
    -  goog.testing.events.fireMouseUpEvent(element);
    -  assertTrue('Control must highlight on mouseup', control.isHighlighted());
    -  assertTrue('Action must have been performed', actionPerformed);
    -  assertFalse('Control must have been deactivated', control.isActive());
    -}
    -
    -function testDefaultConstructor() {
    -  var control = new goog.ui.Control();
    -  assertNull(control.getContent());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/controlcontent.js b/src/database/third_party/closure-library/closure/goog/ui/controlcontent.js
    deleted file mode 100644
    index 907bec61ed8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/controlcontent.js
    +++ /dev/null
    @@ -1,28 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Type declaration for control content.
    - *
    - * @author nicksantos@google.com (Nick Santos)
    - */
    -goog.provide('goog.ui.ControlContent');
    -
    -
    -/**
    - * Type declaration for text caption or DOM structure to be used as the content
    - * of {@link goog.ui.Control}s.
    - * @typedef {string|Node|Array<Node>|NodeList}
    - */
    -goog.ui.ControlContent;
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/controlrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/controlrenderer.js
    deleted file mode 100644
    index 52ac0db80dd..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/controlrenderer.js
    +++ /dev/null
    @@ -1,947 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Base class for control renderers.
    - * TODO(attila):  If the renderer framework works well, pull it into Component.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.ControlRenderer');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.object');
    -goog.require('goog.string');
    -goog.require('goog.style');
    -goog.require('goog.ui.Component');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Default renderer for {@link goog.ui.Control}s.  Can be used as-is, but
    - * subclasses of Control will probably want to use renderers specifically
    - * tailored for them by extending this class.  Controls that use renderers
    - * delegate one or more of the following API methods to the renderer:
    - * <ul>
    - *    <li>{@code createDom} - renders the DOM for the component
    - *    <li>{@code canDecorate} - determines whether an element can be decorated
    - *        by the component
    - *    <li>{@code decorate} - decorates an existing element with the component
    - *    <li>{@code setState} - updates the appearance of the component based on
    - *        its state
    - *    <li>{@code getContent} - returns the component's content
    - *    <li>{@code setContent} - sets the component's content
    - * </ul>
    - * Controls are stateful; renderers, on the other hand, should be stateless and
    - * reusable.
    - * @constructor
    - */
    -goog.ui.ControlRenderer = function() {
    -};
    -goog.addSingletonGetter(goog.ui.ControlRenderer);
    -goog.tagUnsealableClass(goog.ui.ControlRenderer);
    -
    -
    -/**
    - * Constructs a new renderer and sets the CSS class that the renderer will use
    - * as the base CSS class to apply to all elements rendered by that renderer.
    - * An example to use this function using a color palette:
    - *
    - * <pre>
    - * var myCustomRenderer = goog.ui.ControlRenderer.getCustomRenderer(
    - *     goog.ui.PaletteRenderer, 'my-special-palette');
    - * var newColorPalette = new goog.ui.ColorPalette(
    - *     colors, myCustomRenderer, opt_domHelper);
    - * </pre>
    - *
    - * Your CSS can look like this now:
    - * <pre>
    - * .my-special-palette { }
    - * .my-special-palette-table { }
    - * .my-special-palette-cell { }
    - * etc.
    - * </pre>
    - *
    - * <em>instead</em> of
    - * <pre>
    - * .CSS_MY_SPECIAL_PALETTE .goog-palette { }
    - * .CSS_MY_SPECIAL_PALETTE .goog-palette-table { }
    - * .CSS_MY_SPECIAL_PALETTE .goog-palette-cell { }
    - * etc.
    - * </pre>
    - *
    - * You would want to use this functionality when you want an instance of a
    - * component to have specific styles different than the other components of the
    - * same type in your application.  This avoids using descendant selectors to
    - * apply the specific styles to this component.
    - *
    - * @param {Function} ctor The constructor of the renderer you are trying to
    - *     create.
    - * @param {string} cssClassName The name of the CSS class for this renderer.
    - * @return {goog.ui.ControlRenderer} An instance of the desired renderer with
    - *     its getCssClass() method overridden to return the supplied custom CSS
    - *     class name.
    - */
    -goog.ui.ControlRenderer.getCustomRenderer = function(ctor, cssClassName) {
    -  var renderer = new ctor();
    -
    -  /**
    -   * Returns the CSS class to be applied to the root element of components
    -   * rendered using this renderer.
    -   * @return {string} Renderer-specific CSS class.
    -   */
    -  renderer.getCssClass = function() {
    -    return cssClassName;
    -  };
    -
    -  return renderer;
    -};
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.ControlRenderer.CSS_CLASS = goog.getCssName('goog-control');
    -
    -
    -/**
    - * Array of arrays of CSS classes that we want composite classes added and
    - * removed for in IE6 and lower as a workaround for lack of multi-class CSS
    - * selector support.
    - *
    - * Subclasses that have accompanying CSS requiring this workaround should define
    - * their own static IE6_CLASS_COMBINATIONS constant and override
    - * getIe6ClassCombinations to return it.
    - *
    - * For example, if your stylesheet uses the selector .button.collapse-left
    - * (and is compiled to .button_collapse-left for the IE6 version of the
    - * stylesheet,) you should include ['button', 'collapse-left'] in this array
    - * and the class button_collapse-left will be applied to the root element
    - * whenever both button and collapse-left are applied individually.
    - *
    - * Members of each class name combination will be joined with underscores in the
    - * order that they're defined in the array. You should alphabetize them (for
    - * compatibility with the CSS compiler) unless you are doing something special.
    - * @type {Array<Array<string>>}
    - */
    -goog.ui.ControlRenderer.IE6_CLASS_COMBINATIONS = [];
    -
    -
    -/**
    - * Map of component states to corresponding ARIA attributes.  Since the mapping
    - * of component states to ARIA attributes is neither component- nor
    - * renderer-specific, this is a static property of the renderer class, and is
    - * initialized on first use.
    - * @type {Object<goog.ui.Component.State, goog.a11y.aria.State>}
    - * @private
    - */
    -goog.ui.ControlRenderer.ariaAttributeMap_;
    -
    -
    -/**
    - * Map of certain ARIA states to ARIA roles that support them. Used for checked
    - * and selected Component states because they are used on Components with ARIA
    - * roles that do not support the corresponding ARIA state.
    - * @private {!Object<goog.a11y.aria.Role, goog.a11y.aria.State>}
    - * @const
    - */
    -goog.ui.ControlRenderer.TOGGLE_ARIA_STATE_MAP_ = goog.object.create(
    -    goog.a11y.aria.Role.BUTTON, goog.a11y.aria.State.PRESSED,
    -    goog.a11y.aria.Role.CHECKBOX, goog.a11y.aria.State.CHECKED,
    -    goog.a11y.aria.Role.MENU_ITEM, goog.a11y.aria.State.SELECTED,
    -    goog.a11y.aria.Role.MENU_ITEM_CHECKBOX, goog.a11y.aria.State.CHECKED,
    -    goog.a11y.aria.Role.MENU_ITEM_RADIO, goog.a11y.aria.State.CHECKED,
    -    goog.a11y.aria.Role.RADIO, goog.a11y.aria.State.CHECKED,
    -    goog.a11y.aria.Role.TAB, goog.a11y.aria.State.SELECTED,
    -    goog.a11y.aria.Role.TREEITEM, goog.a11y.aria.State.SELECTED);
    -
    -
    -/**
    - * Returns the ARIA role to be applied to the control.
    - * See http://wiki/Main/ARIA for more info.
    - * @return {goog.a11y.aria.Role|undefined} ARIA role.
    - */
    -goog.ui.ControlRenderer.prototype.getAriaRole = function() {
    -  // By default, the ARIA role is unspecified.
    -  return undefined;
    -};
    -
    -
    -/**
    - * Returns the control's contents wrapped in a DIV, with the renderer's own
    - * CSS class and additional state-specific classes applied to it.
    - * @param {goog.ui.Control} control Control to render.
    - * @return {Element} Root element for the control.
    - */
    -goog.ui.ControlRenderer.prototype.createDom = function(control) {
    -  // Create and return DIV wrapping contents.
    -  var element = control.getDomHelper().createDom(
    -      'div', this.getClassNames(control).join(' '), control.getContent());
    -
    -  return element;
    -};
    -
    -
    -/**
    - * Takes the control's root element and returns the parent element of the
    - * control's contents.  Since by default controls are rendered as a single
    - * DIV, the default implementation returns the element itself.  Subclasses
    - * with more complex DOM structures must override this method as needed.
    - * @param {Element} element Root element of the control whose content element
    - *     is to be returned.
    - * @return {Element} The control's content element.
    - */
    -goog.ui.ControlRenderer.prototype.getContentElement = function(element) {
    -  return element;
    -};
    -
    -
    -/**
    - * Updates the control's DOM by adding or removing the specified class name
    - * to/from its root element. May add additional combined classes as needed in
    - * IE6 and lower. Because of this, subclasses should use this method when
    - * modifying class names on the control's root element.
    - * @param {goog.ui.Control|Element} control Control instance (or root element)
    - *     to be updated.
    - * @param {string} className CSS class name to add or remove.
    - * @param {boolean} enable Whether to add or remove the class name.
    - */
    -goog.ui.ControlRenderer.prototype.enableClassName = function(control,
    -    className, enable) {
    -  var element = /** @type {Element} */ (
    -      control.getElement ? control.getElement() : control);
    -  if (element) {
    -    var classNames = [className];
    -
    -    // For IE6, we need to enable any combined classes involving this class
    -    // as well.
    -    // TODO(user): Remove this as IE6 is no longer in use.
    -    if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('7')) {
    -      classNames = this.getAppliedCombinedClassNames_(
    -          goog.dom.classlist.get(element), className);
    -      classNames.push(className);
    -    }
    -
    -    goog.dom.classlist.enableAll(element, classNames, enable);
    -  }
    -};
    -
    -
    -/**
    - * Updates the control's DOM by adding or removing the specified extra class
    - * name to/from its element.
    - * @param {goog.ui.Control} control Control to be updated.
    - * @param {string} className CSS class name to add or remove.
    - * @param {boolean} enable Whether to add or remove the class name.
    - */
    -goog.ui.ControlRenderer.prototype.enableExtraClassName = function(control,
    -    className, enable) {
    -  // The base class implementation is trivial; subclasses should override as
    -  // needed.
    -  this.enableClassName(control, className, enable);
    -};
    -
    -
    -/**
    - * Returns true if this renderer can decorate the element, false otherwise.
    - * The default implementation always returns true.
    - * @param {Element} element Element to decorate.
    - * @return {boolean} Whether the renderer can decorate the element.
    - */
    -goog.ui.ControlRenderer.prototype.canDecorate = function(element) {
    -  return true;
    -};
    -
    -
    -/**
    - * Default implementation of {@code decorate} for {@link goog.ui.Control}s.
    - * Initializes the control's ID, content, and state based on the ID of the
    - * element, its child nodes, and its CSS classes, respectively.  Returns the
    - * element.
    - * @param {goog.ui.Control} control Control instance to decorate the element.
    - * @param {Element} element Element to decorate.
    - * @return {Element} Decorated element.
    - */
    -goog.ui.ControlRenderer.prototype.decorate = function(control, element) {
    -  // Set the control's ID to the decorated element's DOM ID, if any.
    -  if (element.id) {
    -    control.setId(element.id);
    -  }
    -
    -  // Set the control's content to the decorated element's content.
    -  var contentElem = this.getContentElement(element);
    -  if (contentElem && contentElem.firstChild) {
    -    control.setContentInternal(contentElem.firstChild.nextSibling ?
    -        goog.array.clone(contentElem.childNodes) : contentElem.firstChild);
    -  } else {
    -    control.setContentInternal(null);
    -  }
    -
    -  // Initialize the control's state based on the decorated element's CSS class.
    -  // This implementation is optimized to minimize object allocations, string
    -  // comparisons, and DOM access.
    -  var state = 0x00;
    -  var rendererClassName = this.getCssClass();
    -  var structuralClassName = this.getStructuralCssClass();
    -  var hasRendererClassName = false;
    -  var hasStructuralClassName = false;
    -  var hasCombinedClassName = false;
    -  var classNames = goog.array.toArray(goog.dom.classlist.get(element));
    -  goog.array.forEach(classNames, function(className) {
    -    if (!hasRendererClassName && className == rendererClassName) {
    -      hasRendererClassName = true;
    -      if (structuralClassName == rendererClassName) {
    -        hasStructuralClassName = true;
    -      }
    -    } else if (!hasStructuralClassName && className == structuralClassName) {
    -      hasStructuralClassName = true;
    -    } else {
    -      state |= this.getStateFromClass(className);
    -    }
    -    if (this.getStateFromClass(className) == goog.ui.Component.State.DISABLED) {
    -      goog.asserts.assertElement(contentElem);
    -      if (goog.dom.isFocusableTabIndex(contentElem)) {
    -        goog.dom.setFocusableTabIndex(contentElem, false);
    -      }
    -    }
    -  }, this);
    -  control.setStateInternal(state);
    -
    -  // Make sure the element has the renderer's CSS classes applied, as well as
    -  // any extra class names set on the control.
    -  if (!hasRendererClassName) {
    -    classNames.push(rendererClassName);
    -    if (structuralClassName == rendererClassName) {
    -      hasStructuralClassName = true;
    -    }
    -  }
    -  if (!hasStructuralClassName) {
    -    classNames.push(structuralClassName);
    -  }
    -  var extraClassNames = control.getExtraClassNames();
    -  if (extraClassNames) {
    -    classNames.push.apply(classNames, extraClassNames);
    -  }
    -
    -  // For IE6, rewrite all classes on the decorated element if any combined
    -  // classes apply.
    -  if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('7')) {
    -    var combinedClasses = this.getAppliedCombinedClassNames_(
    -        classNames);
    -    if (combinedClasses.length > 0) {
    -      classNames.push.apply(classNames, combinedClasses);
    -      hasCombinedClassName = true;
    -    }
    -  }
    -
    -  // Only write to the DOM if new class names had to be added to the element.
    -  if (!hasRendererClassName || !hasStructuralClassName ||
    -      extraClassNames || hasCombinedClassName) {
    -    goog.dom.classlist.set(element, classNames.join(' '));
    -  }
    -
    -  return element;
    -};
    -
    -
    -/**
    - * Initializes the control's DOM by configuring properties that can only be set
    - * after the DOM has entered the document.  This implementation sets up BiDi
    - * and keyboard focus.  Called from {@link goog.ui.Control#enterDocument}.
    - * @param {goog.ui.Control} control Control whose DOM is to be initialized
    - *     as it enters the document.
    - */
    -goog.ui.ControlRenderer.prototype.initializeDom = function(control) {
    -  // Initialize render direction (BiDi).  We optimize the left-to-right render
    -  // direction by assuming that elements are left-to-right by default, and only
    -  // updating their styling if they are explicitly set to right-to-left.
    -  if (control.isRightToLeft()) {
    -    this.setRightToLeft(control.getElement(), true);
    -  }
    -
    -  // Initialize keyboard focusability (tab index).  We assume that components
    -  // aren't focusable by default (i.e have no tab index), and only touch the
    -  // DOM if the component is focusable, enabled, and visible, and therefore
    -  // needs a tab index.
    -  if (control.isEnabled()) {
    -    this.setFocusable(control, control.isVisible());
    -  }
    -};
    -
    -
    -/**
    - * Sets the element's ARIA role.
    - * @param {Element} element Element to update.
    - * @param {?goog.a11y.aria.Role=} opt_preferredRole The preferred ARIA role.
    - */
    -goog.ui.ControlRenderer.prototype.setAriaRole = function(element,
    -    opt_preferredRole) {
    -  var ariaRole = opt_preferredRole || this.getAriaRole();
    -  if (ariaRole) {
    -    goog.asserts.assert(element,
    -        'The element passed as a first parameter cannot be null.');
    -    var currentRole = goog.a11y.aria.getRole(element);
    -    if (ariaRole == currentRole) {
    -      return;
    -    }
    -    goog.a11y.aria.setRole(element, ariaRole);
    -  }
    -};
    -
    -
    -/**
    - * Sets the element's ARIA attributes, including distinguishing between
    - * universally supported ARIA properties and ARIA states that are only
    - * supported by certain ARIA roles. Only attributes which are initialized to be
    - * true will be set.
    - * @param {!goog.ui.Control} control Control whose ARIA state will be updated.
    - * @param {!Element} element Element whose ARIA state is to be updated.
    - */
    -goog.ui.ControlRenderer.prototype.setAriaStates = function(control, element) {
    -  goog.asserts.assert(control);
    -  goog.asserts.assert(element);
    -
    -  var ariaLabel = control.getAriaLabel();
    -  if (goog.isDefAndNotNull(ariaLabel)) {
    -    this.setAriaLabel(element, ariaLabel);
    -  }
    -
    -  if (!control.isVisible()) {
    -    goog.a11y.aria.setState(
    -        element, goog.a11y.aria.State.HIDDEN, !control.isVisible());
    -  }
    -  if (!control.isEnabled()) {
    -    this.updateAriaState(
    -        element, goog.ui.Component.State.DISABLED, !control.isEnabled());
    -  }
    -  if (control.isSupportedState(goog.ui.Component.State.SELECTED)) {
    -    this.updateAriaState(
    -        element, goog.ui.Component.State.SELECTED, control.isSelected());
    -  }
    -  if (control.isSupportedState(goog.ui.Component.State.CHECKED)) {
    -    this.updateAriaState(
    -        element, goog.ui.Component.State.CHECKED, control.isChecked());
    -  }
    -  if (control.isSupportedState(goog.ui.Component.State.OPENED)) {
    -    this.updateAriaState(
    -        element, goog.ui.Component.State.OPENED, control.isOpen());
    -  }
    -};
    -
    -
    -/**
    - * Sets the element's ARIA label. This should be overriden by subclasses that
    - * don't apply the role directly on control.element_.
    - * @param {!Element} element Element whose ARIA label is to be updated.
    - * @param {string} ariaLabel Label to add to the element.
    - */
    -goog.ui.ControlRenderer.prototype.setAriaLabel = function(element, ariaLabel) {
    -  goog.a11y.aria.setLabel(element, ariaLabel);
    -};
    -
    -
    -/**
    - * Allows or disallows text selection within the control's DOM.
    - * @param {Element} element The control's root element.
    - * @param {boolean} allow Whether the element should allow text selection.
    - */
    -goog.ui.ControlRenderer.prototype.setAllowTextSelection = function(element,
    -    allow) {
    -  // On all browsers other than IE and Opera, it isn't necessary to recursively
    -  // apply unselectable styling to the element's children.
    -  goog.style.setUnselectable(element, !allow,
    -      !goog.userAgent.IE && !goog.userAgent.OPERA);
    -};
    -
    -
    -/**
    - * Applies special styling to/from the control's element if it is rendered
    - * right-to-left, and removes it if it is rendered left-to-right.
    - * @param {Element} element The control's root element.
    - * @param {boolean} rightToLeft Whether the component is rendered
    - *     right-to-left.
    - */
    -goog.ui.ControlRenderer.prototype.setRightToLeft = function(element,
    -    rightToLeft) {
    -  this.enableClassName(element,
    -      goog.getCssName(this.getStructuralCssClass(), 'rtl'), rightToLeft);
    -};
    -
    -
    -/**
    - * Returns true if the control's key event target supports keyboard focus
    - * (based on its {@code tabIndex} attribute), false otherwise.
    - * @param {goog.ui.Control} control Control whose key event target is to be
    - *     checked.
    - * @return {boolean} Whether the control's key event target is focusable.
    - */
    -goog.ui.ControlRenderer.prototype.isFocusable = function(control) {
    -  var keyTarget;
    -  if (control.isSupportedState(goog.ui.Component.State.FOCUSED) &&
    -      (keyTarget = control.getKeyEventTarget())) {
    -    return goog.dom.isFocusableTabIndex(keyTarget);
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Updates the control's key event target to make it focusable or non-focusable
    - * via its {@code tabIndex} attribute.  Does nothing if the control doesn't
    - * support the {@code FOCUSED} state, or if it has no key event target.
    - * @param {goog.ui.Control} control Control whose key event target is to be
    - *     updated.
    - * @param {boolean} focusable Whether to enable keyboard focus support on the
    - *     control's key event target.
    - */
    -goog.ui.ControlRenderer.prototype.setFocusable = function(control, focusable) {
    -  var keyTarget;
    -  if (control.isSupportedState(goog.ui.Component.State.FOCUSED) &&
    -      (keyTarget = control.getKeyEventTarget())) {
    -    if (!focusable && control.isFocused()) {
    -      // Blur before hiding.  Note that IE calls onblur handlers asynchronously.
    -      try {
    -        keyTarget.blur();
    -      } catch (e) {
    -        // TODO(user|user):  Find out why this fails on IE.
    -      }
    -      // The blur event dispatched by the key event target element when blur()
    -      // was called on it should have been handled by the control's handleBlur()
    -      // method, so at this point the control should no longer be focused.
    -      // However, blur events are unreliable on IE and FF3, so if at this point
    -      // the control is still focused, we trigger its handleBlur() method
    -      // programmatically.
    -      if (control.isFocused()) {
    -        control.handleBlur(null);
    -      }
    -    }
    -    // Don't overwrite existing tab index values unless needed.
    -    if (goog.dom.isFocusableTabIndex(keyTarget) != focusable) {
    -      goog.dom.setFocusableTabIndex(keyTarget, focusable);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Shows or hides the element.
    - * @param {Element} element Element to update.
    - * @param {boolean} visible Whether to show the element.
    - */
    -goog.ui.ControlRenderer.prototype.setVisible = function(element, visible) {
    -  // The base class implementation is trivial; subclasses should override as
    -  // needed.  It should be possible to do animated reveals, for example.
    -  goog.style.setElementShown(element, visible);
    -  if (element) {
    -    goog.a11y.aria.setState(element, goog.a11y.aria.State.HIDDEN, !visible);
    -  }
    -};
    -
    -
    -/**
    - * Updates the appearance of the control in response to a state change.
    - * @param {goog.ui.Control} control Control instance to update.
    - * @param {goog.ui.Component.State} state State to enable or disable.
    - * @param {boolean} enable Whether the control is entering or exiting the state.
    - */
    -goog.ui.ControlRenderer.prototype.setState = function(control, state, enable) {
    -  var element = control.getElement();
    -  if (element) {
    -    var className = this.getClassForState(state);
    -    if (className) {
    -      this.enableClassName(control, className, enable);
    -    }
    -    this.updateAriaState(element, state, enable);
    -  }
    -};
    -
    -
    -/**
    - * Updates the element's ARIA (accessibility) attributes , including
    - * distinguishing between universally supported ARIA properties and ARIA states
    - * that are only supported by certain ARIA roles.
    - * @param {Element} element Element whose ARIA state is to be updated.
    - * @param {goog.ui.Component.State} state Component state being enabled or
    - *     disabled.
    - * @param {boolean} enable Whether the state is being enabled or disabled.
    - * @protected
    - */
    -goog.ui.ControlRenderer.prototype.updateAriaState = function(element, state,
    -    enable) {
    -  // Ensure the ARIA attribute map exists.
    -  if (!goog.ui.ControlRenderer.ariaAttributeMap_) {
    -    goog.ui.ControlRenderer.ariaAttributeMap_ = goog.object.create(
    -        goog.ui.Component.State.DISABLED, goog.a11y.aria.State.DISABLED,
    -        goog.ui.Component.State.SELECTED, goog.a11y.aria.State.SELECTED,
    -        goog.ui.Component.State.CHECKED, goog.a11y.aria.State.CHECKED,
    -        goog.ui.Component.State.OPENED, goog.a11y.aria.State.EXPANDED);
    -  }
    -  goog.asserts.assert(element,
    -      'The element passed as a first parameter cannot be null.');
    -  var ariaAttr = goog.ui.ControlRenderer.getAriaStateForAriaRole_(
    -      element, goog.ui.ControlRenderer.ariaAttributeMap_[state]);
    -  if (ariaAttr) {
    -    goog.a11y.aria.setState(element, ariaAttr, enable);
    -  }
    -};
    -
    -
    -/**
    - * Returns the appropriate ARIA attribute based on ARIA role if the ARIA
    - * attribute is an ARIA state.
    - * @param {!Element} element The element from which to get the ARIA role for
    - * matching ARIA state.
    - * @param {goog.a11y.aria.State} attr The ARIA attribute to check to see if it
    - * can be applied to the given ARIA role.
    - * @return {goog.a11y.aria.State} An ARIA attribute that can be applied to the
    - * given ARIA role.
    - * @private
    - */
    -goog.ui.ControlRenderer.getAriaStateForAriaRole_ = function(element, attr) {
    -  var role = goog.a11y.aria.getRole(element);
    -  if (!role) {
    -    return attr;
    -  }
    -  role = /** @type {goog.a11y.aria.Role} */ (role);
    -  var matchAttr = goog.ui.ControlRenderer.TOGGLE_ARIA_STATE_MAP_[role] || attr;
    -  return goog.ui.ControlRenderer.isAriaState_(attr) ? matchAttr : attr;
    -};
    -
    -
    -/**
    - * Determines if the given ARIA attribute is an ARIA property or ARIA state.
    - * @param {goog.a11y.aria.State} attr The ARIA attribute to classify.
    - * @return {boolean} If the ARIA attribute is an ARIA state.
    - * @private
    - */
    -goog.ui.ControlRenderer.isAriaState_ = function(attr) {
    -  return attr == goog.a11y.aria.State.CHECKED ||
    -      attr == goog.a11y.aria.State.SELECTED;
    -};
    -
    -
    -/**
    - * Takes a control's root element, and sets its content to the given text
    - * caption or DOM structure.  The default implementation replaces the children
    - * of the given element.  Renderers that create more complex DOM structures
    - * must override this method accordingly.
    - * @param {Element} element The control's root element.
    - * @param {goog.ui.ControlContent} content Text caption or DOM structure to be
    - *     set as the control's content. The DOM nodes will not be cloned, they
    - *     will only moved under the content element of the control.
    - */
    -goog.ui.ControlRenderer.prototype.setContent = function(element, content) {
    -  var contentElem = this.getContentElement(element);
    -  if (contentElem) {
    -    goog.dom.removeChildren(contentElem);
    -    if (content) {
    -      if (goog.isString(content)) {
    -        goog.dom.setTextContent(contentElem, content);
    -      } else {
    -        var childHandler = function(child) {
    -          if (child) {
    -            var doc = goog.dom.getOwnerDocument(contentElem);
    -            contentElem.appendChild(goog.isString(child) ?
    -                doc.createTextNode(child) : child);
    -          }
    -        };
    -        if (goog.isArray(content)) {
    -          // Array of nodes.
    -          goog.array.forEach(content, childHandler);
    -        } else if (goog.isArrayLike(content) && !('nodeType' in content)) {
    -          // NodeList. The second condition filters out TextNode which also has
    -          // length attribute but is not array like. The nodes have to be cloned
    -          // because childHandler removes them from the list during iteration.
    -          goog.array.forEach(
    -              goog.array.clone(/** @type {!NodeList} */(content)),
    -              childHandler);
    -        } else {
    -          // Node or string.
    -          childHandler(content);
    -        }
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Returns the element within the component's DOM that should receive keyboard
    - * focus (null if none).  The default implementation returns the control's root
    - * element.
    - * @param {goog.ui.Control} control Control whose key event target is to be
    - *     returned.
    - * @return {Element} The key event target.
    - */
    -goog.ui.ControlRenderer.prototype.getKeyEventTarget = function(control) {
    -  return control.getElement();
    -};
    -
    -
    -// CSS class name management.
    -
    -
    -/**
    - * Returns the CSS class name to be applied to the root element of all
    - * components rendered or decorated using this renderer.  The class name
    - * is expected to uniquely identify the renderer class, i.e. no two
    - * renderer classes are expected to share the same CSS class name.
    - * @return {string} Renderer-specific CSS class name.
    - */
    -goog.ui.ControlRenderer.prototype.getCssClass = function() {
    -  return goog.ui.ControlRenderer.CSS_CLASS;
    -};
    -
    -
    -/**
    - * Returns an array of combinations of classes to apply combined class names for
    - * in IE6 and below. See {@link IE6_CLASS_COMBINATIONS} for more detail. This
    - * method doesn't reference {@link IE6_CLASS_COMBINATIONS} so that it can be
    - * compiled out, but subclasses should return their IE6_CLASS_COMBINATIONS
    - * static constant instead.
    - * @return {Array<Array<string>>} Array of class name combinations.
    - */
    -goog.ui.ControlRenderer.prototype.getIe6ClassCombinations = function() {
    -  return [];
    -};
    -
    -
    -/**
    - * Returns the name of a DOM structure-specific CSS class to be applied to the
    - * root element of all components rendered or decorated using this renderer.
    - * Unlike the class name returned by {@link #getCssClass}, the structural class
    - * name may be shared among different renderers that generate similar DOM
    - * structures.  The structural class name also serves as the basis of derived
    - * class names used to identify and style structural elements of the control's
    - * DOM, as well as the basis for state-specific class names.  The default
    - * implementation returns the same class name as {@link #getCssClass}, but
    - * subclasses are expected to override this method as needed.
    - * @return {string} DOM structure-specific CSS class name (same as the renderer-
    - *     specific CSS class name by default).
    - */
    -goog.ui.ControlRenderer.prototype.getStructuralCssClass = function() {
    -  return this.getCssClass();
    -};
    -
    -
    -/**
    - * Returns all CSS class names applicable to the given control, based on its
    - * state.  The return value is an array of strings containing
    - * <ol>
    - *   <li>the renderer-specific CSS class returned by {@link #getCssClass},
    - *       followed by
    - *   <li>the structural CSS class returned by {@link getStructuralCssClass} (if
    - *       different from the renderer-specific CSS class), followed by
    - *   <li>any state-specific classes returned by {@link #getClassNamesForState},
    - *       followed by
    - *   <li>any extra classes returned by the control's {@code getExtraClassNames}
    - *       method and
    - *   <li>for IE6 and lower, additional combined classes from
    - *       {@link getAppliedCombinedClassNames_}.
    - * </ol>
    - * Since all controls have at least one renderer-specific CSS class name, this
    - * method is guaranteed to return an array of at least one element.
    - * @param {goog.ui.Control} control Control whose CSS classes are to be
    - *     returned.
    - * @return {!Array<string>} Array of CSS class names applicable to the control.
    - * @protected
    - */
    -goog.ui.ControlRenderer.prototype.getClassNames = function(control) {
    -  var cssClass = this.getCssClass();
    -
    -  // Start with the renderer-specific class name.
    -  var classNames = [cssClass];
    -
    -  // Add structural class name, if different.
    -  var structuralCssClass = this.getStructuralCssClass();
    -  if (structuralCssClass != cssClass) {
    -    classNames.push(structuralCssClass);
    -  }
    -
    -  // Add state-specific class names, if any.
    -  var classNamesForState = this.getClassNamesForState(control.getState());
    -  classNames.push.apply(classNames, classNamesForState);
    -
    -  // Add extra class names, if any.
    -  var extraClassNames = control.getExtraClassNames();
    -  if (extraClassNames) {
    -    classNames.push.apply(classNames, extraClassNames);
    -  }
    -
    -  // Add composite classes for IE6 support
    -  if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('7')) {
    -    classNames.push.apply(classNames,
    -        this.getAppliedCombinedClassNames_(classNames));
    -  }
    -
    -  return classNames;
    -};
    -
    -
    -/**
    - * Returns an array of all the combined class names that should be applied based
    - * on the given list of classes. Checks the result of
    - * {@link getIe6ClassCombinations} for any combinations that have all
    - * members contained in classes. If a combination matches, the members are
    - * joined with an underscore (in order), and added to the return array.
    - *
    - * If opt_includedClass is provided, return only the combined classes that have
    - * all members contained in classes AND include opt_includedClass as well.
    - * opt_includedClass is added to classes as well.
    - * @param {goog.array.ArrayLike<string>} classes Array-like thing of classes to
    - *     return matching combined classes for.
    - * @param {?string=} opt_includedClass If provided, get only the combined
    - *     classes that include this one.
    - * @return {!Array<string>} Array of combined class names that should be
    - *     applied.
    - * @private
    - */
    -goog.ui.ControlRenderer.prototype.getAppliedCombinedClassNames_ = function(
    -    classes, opt_includedClass) {
    -  var toAdd = [];
    -  if (opt_includedClass) {
    -    classes = classes.concat([opt_includedClass]);
    -  }
    -  goog.array.forEach(this.getIe6ClassCombinations(), function(combo) {
    -    if (goog.array.every(combo, goog.partial(goog.array.contains, classes)) &&
    -        (!opt_includedClass || goog.array.contains(combo, opt_includedClass))) {
    -      toAdd.push(combo.join('_'));
    -    }
    -  });
    -  return toAdd;
    -};
    -
    -
    -/**
    - * Takes a bit mask of {@link goog.ui.Component.State}s, and returns an array
    - * of the appropriate class names representing the given state, suitable to be
    - * applied to the root element of a component rendered using this renderer, or
    - * null if no state-specific classes need to be applied.  This default
    - * implementation uses the renderer's {@link getClassForState} method to
    - * generate each state-specific class.
    - * @param {number} state Bit mask of component states.
    - * @return {!Array<string>} Array of CSS class names representing the given
    - *     state.
    - * @protected
    - */
    -goog.ui.ControlRenderer.prototype.getClassNamesForState = function(state) {
    -  var classNames = [];
    -  while (state) {
    -    // For each enabled state, push the corresponding CSS class name onto
    -    // the classNames array.
    -    var mask = state & -state;  // Least significant bit
    -    classNames.push(this.getClassForState(
    -        /** @type {goog.ui.Component.State} */ (mask)));
    -    state &= ~mask;
    -  }
    -  return classNames;
    -};
    -
    -
    -/**
    - * Takes a single {@link goog.ui.Component.State}, and returns the
    - * corresponding CSS class name (null if none).
    - * @param {goog.ui.Component.State} state Component state.
    - * @return {string|undefined} CSS class representing the given state (undefined
    - *     if none).
    - * @protected
    - */
    -goog.ui.ControlRenderer.prototype.getClassForState = function(state) {
    -  if (!this.classByState_) {
    -    this.createClassByStateMap_();
    -  }
    -  return this.classByState_[state];
    -};
    -
    -
    -/**
    - * Takes a single CSS class name which may represent a component state, and
    - * returns the corresponding component state (0x00 if none).
    - * @param {string} className CSS class name, possibly representing a component
    - *     state.
    - * @return {goog.ui.Component.State} state Component state corresponding
    - *     to the given CSS class (0x00 if none).
    - * @protected
    - */
    -goog.ui.ControlRenderer.prototype.getStateFromClass = function(className) {
    -  if (!this.stateByClass_) {
    -    this.createStateByClassMap_();
    -  }
    -  var state = parseInt(this.stateByClass_[className], 10);
    -  return /** @type {goog.ui.Component.State} */ (isNaN(state) ? 0x00 : state);
    -};
    -
    -
    -/**
    - * Creates the lookup table of states to classes, used during state changes.
    - * @private
    - */
    -goog.ui.ControlRenderer.prototype.createClassByStateMap_ = function() {
    -  var baseClass = this.getStructuralCssClass();
    -
    -  // This ensures space-separated css classnames are not allowed, which some
    -  // ControlRenderers had been doing.  See http://b/13694665.
    -  var isValidClassName = !goog.string.contains(
    -      goog.string.normalizeWhitespace(baseClass), ' ');
    -  goog.asserts.assert(isValidClassName,
    -      'ControlRenderer has an invalid css class: \'' + baseClass + '\'');
    -
    -  /**
    -   * Map of component states to state-specific structural class names,
    -   * used when changing the DOM in response to a state change.  Precomputed
    -   * and cached on first use to minimize object allocations and string
    -   * concatenation.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.classByState_ = goog.object.create(
    -      goog.ui.Component.State.DISABLED, goog.getCssName(baseClass, 'disabled'),
    -      goog.ui.Component.State.HOVER, goog.getCssName(baseClass, 'hover'),
    -      goog.ui.Component.State.ACTIVE, goog.getCssName(baseClass, 'active'),
    -      goog.ui.Component.State.SELECTED, goog.getCssName(baseClass, 'selected'),
    -      goog.ui.Component.State.CHECKED, goog.getCssName(baseClass, 'checked'),
    -      goog.ui.Component.State.FOCUSED, goog.getCssName(baseClass, 'focused'),
    -      goog.ui.Component.State.OPENED, goog.getCssName(baseClass, 'open'));
    -};
    -
    -
    -/**
    - * Creates the lookup table of classes to states, used during decoration.
    - * @private
    - */
    -goog.ui.ControlRenderer.prototype.createStateByClassMap_ = function() {
    -  // We need the classByState_ map so we can transpose it.
    -  if (!this.classByState_) {
    -    this.createClassByStateMap_();
    -  }
    -
    -  /**
    -   * Map of state-specific structural class names to component states,
    -   * used during element decoration.  Precomputed and cached on first use
    -   * to minimize object allocations and string concatenation.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.stateByClass_ = goog.object.transpose(this.classByState_);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/controlrenderer_test.html b/src/database/third_party/closure-library/closure/goog/ui/controlrenderer_test.html
    deleted file mode 100644
    index 1cfce6a8ba7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/controlrenderer_test.html
    +++ /dev/null
    @@ -1,27 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -Author: attila@google.com (Attila Bodis)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.ControlRenderer
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.ControlRendererTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="sandbox">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/controlrenderer_test.js b/src/database/third_party/closure-library/closure/goog/ui/controlrenderer_test.js
    deleted file mode 100644
    index 7709c748bd2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/controlrenderer_test.js
    +++ /dev/null
    @@ -1,1194 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.ControlRendererTest');
    -goog.setTestOnly('goog.ui.ControlRendererTest');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.dom');
    -goog.require('goog.dom.NodeType');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.object');
    -goog.require('goog.style');
    -goog.require('goog.testing.ExpectedFailures');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.Control');
    -goog.require('goog.ui.ControlRenderer');
    -goog.require('goog.userAgent');
    -
    -var control, controlRenderer, testRenderer, propertyReplacer;
    -var sandbox;
    -var expectedFailures;
    -
    -function setUpPage() {
    -  sandbox = goog.dom.getElement('sandbox');
    -  expectedFailures = new goog.testing.ExpectedFailures();
    -}
    -
    -
    -
    -/**
    - * A subclass of ControlRenderer that overrides {@code getAriaRole} and
    - * {@code getStructuralCssClass} for testing purposes.
    - * @constructor
    - * @extends {goog.ui.ControlRenderer}
    - */
    -function TestRenderer() {
    -  goog.ui.ControlRenderer.call(this);
    -}
    -goog.inherits(TestRenderer, goog.ui.ControlRenderer);
    -goog.addSingletonGetter(TestRenderer);
    -
    -TestRenderer.CSS_CLASS = 'goog-button';
    -
    -TestRenderer.IE6_CLASS_COMBINATIONS = [
    -  ['combined', 'goog-base-hover', 'goog-button'],
    -  ['combined', 'goog-base-disabled', 'goog-button'],
    -  ['combined', 'combined2', 'goog-base-hover', 'goog-base-rtl',
    -   'goog-button']
    -];
    -
    -
    -/** @override */
    -TestRenderer.prototype.getAriaRole = function() {
    -  return goog.a11y.aria.Role.BUTTON;
    -};
    -
    -
    -/** @override */
    -TestRenderer.prototype.getCssClass = function() {
    -  return TestRenderer.CSS_CLASS;
    -};
    -
    -
    -/** @override */
    -TestRenderer.prototype.getStructuralCssClass = function() {
    -  return 'goog-base';
    -};
    -
    -
    -/** @override */
    -TestRenderer.prototype.getIe6ClassCombinations = function() {
    -  return TestRenderer.IE6_CLASS_COMBINATIONS;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether we're on Mac Safari 3.x.
    - */
    -function isMacSafari3() {
    -  return goog.userAgent.WEBKIT && goog.userAgent.MAC &&
    -      !goog.userAgent.isVersionOrHigher('527');
    -}
    -
    -
    -/**
    - * @return {boolean} Whether we're on IE6 or lower.
    - */
    -function isIe6() {
    -  return goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('7');
    -}
    -
    -function setUp() {
    -  control = new goog.ui.Control('Hello');
    -  controlRenderer = goog.ui.ControlRenderer.getInstance();
    -  testRenderer = TestRenderer.getInstance();
    -  propertyReplacer = new goog.testing.PropertyReplacer();
    -}
    -
    -function tearDown() {
    -  propertyReplacer.reset();
    -  control.dispose();
    -  expectedFailures.handleTearDown();
    -  control = null;
    -  controlRenderer = null;
    -  testRenderer = null;
    -  goog.dom.removeChildren(sandbox);
    -}
    -
    -function testConstructor() {
    -  assertNotNull('ControlRenderer singleton instance must not be null',
    -      controlRenderer);
    -  assertNotNull('TestRenderer singleton instance must not be null',
    -      testRenderer);
    -}
    -
    -function testGetCustomRenderer() {
    -  var cssClass = 'special-css-class';
    -  var renderer = goog.ui.ControlRenderer.getCustomRenderer(
    -      goog.ui.ControlRenderer, cssClass);
    -  assertEquals(
    -      'Renderer should have returned the custom CSS class.',
    -      cssClass,
    -      renderer.getCssClass());
    -}
    -
    -function testGetAriaRole() {
    -  assertUndefined('ControlRenderer\'s ARIA role must be undefined',
    -      controlRenderer.getAriaRole());
    -  assertEquals('TestRenderer\'s ARIA role must have expected value',
    -      goog.a11y.aria.Role.BUTTON, testRenderer.getAriaRole());
    -}
    -
    -function testCreateDom() {
    -  assertHTMLEquals('ControlRenderer must create correct DOM',
    -      '<div class="goog-control">Hello</div>',
    -      goog.dom.getOuterHtml(controlRenderer.createDom(control)));
    -  assertHTMLEquals('TestRenderer must create correct DOM',
    -      '<div class="goog-button goog-base">Hello</div>',
    -      goog.dom.getOuterHtml(testRenderer.createDom(control)));
    -}
    -
    -function testGetContentElement() {
    -  assertEquals('getContentElement() must return its argument', sandbox,
    -      controlRenderer.getContentElement(sandbox));
    -}
    -
    -function testEnableExtraClassName() {
    -  // enableExtraClassName() must be a no-op if control has no DOM.
    -  controlRenderer.enableExtraClassName(control, 'foo', true);
    -
    -  control.createDom();
    -  var element = control.getElement();
    -
    -  controlRenderer.enableExtraClassName(control, 'foo', true);
    -  assertSameElements('Extra class name must have been added',
    -      ['goog-control', 'foo'], goog.dom.classlist.get(element));
    -
    -  controlRenderer.enableExtraClassName(control, 'foo', true);
    -  assertSameElements('Enabling existing extra class name must be a no-op',
    -      ['goog-control', 'foo'], goog.dom.classlist.get(element));
    -
    -  controlRenderer.enableExtraClassName(control, 'bar', false);
    -  assertSameElements('Disabling nonexistent class name must be a no-op',
    -      ['goog-control', 'foo'], goog.dom.classlist.get(element));
    -
    -  controlRenderer.enableExtraClassName(control, 'foo', false);
    -  assertSameElements('Extra class name must have been removed',
    -      ['goog-control'], goog.dom.classlist.get(element));
    -}
    -
    -function testCanDecorate() {
    -  assertTrue('canDecorate() must return true',
    -      controlRenderer.canDecorate());
    -}
    -
    -function testDecorate() {
    -  sandbox.innerHTML = '<div id="foo">Hello, world!</div>';
    -  var foo = goog.dom.getElement('foo');
    -  var element = controlRenderer.decorate(control, foo);
    -
    -  assertEquals('decorate() must return its argument', foo, element);
    -  assertEquals('Decorated control\'s ID must be set', 'foo',
    -      control.getId());
    -  assertTrue('Decorated control\'s content must be a text node',
    -      control.getContent().nodeType == goog.dom.NodeType.TEXT);
    -  assertEquals('Decorated control\'s content must have expected value',
    -      'Hello, world!', control.getContent().nodeValue);
    -  assertEquals('Decorated control\'s state must be as expected', 0x00,
    -      control.getState());
    -  assertSameElements('Decorated element\'s classes must be as expected',
    -      ['goog-control'], goog.dom.classlist.get(element));
    -}
    -
    -function testDecorateComplexDom() {
    -  sandbox.innerHTML = '<div id="foo"><i>Hello</i>,<b>world</b>!</div>';
    -  var foo = goog.dom.getElement('foo');
    -  var element = controlRenderer.decorate(control, foo);
    -
    -  assertEquals('decorate() must return its argument', foo, element);
    -  assertEquals('Decorated control\'s ID must be set', 'foo',
    -      control.getId());
    -  assertTrue('Decorated control\'s content must be an array',
    -      goog.isArray(control.getContent()));
    -  assertEquals('Decorated control\'s content must have expected length', 4,
    -      control.getContent().length);
    -  assertEquals('Decorated control\'s state must be as expected', 0x00,
    -      control.getState());
    -  assertSameElements('Decorated element\'s classes must be as expected',
    -      ['goog-control'], goog.dom.classlist.get(element));
    -}
    -
    -function testDecorateWithClasses() {
    -  sandbox.innerHTML =
    -      '<div id="foo" class="app goog-base-disabled goog-base-hover"></div>';
    -  var foo = goog.dom.getElement('foo');
    -
    -  control.addClassName('extra');
    -  var element = testRenderer.decorate(control, foo);
    -
    -  assertEquals('decorate() must return its argument', foo, element);
    -  assertEquals('Decorated control\'s ID must be set', 'foo',
    -      control.getId());
    -  assertNull('Decorated control\'s content must be null',
    -      control.getContent());
    -  assertEquals('Decorated control\'s state must be as expected',
    -      goog.ui.Component.State.DISABLED | goog.ui.Component.State.HOVER,
    -      control.getState());
    -  assertSameElements('Decorated element\'s classes must be as expected', [
    -    'app',
    -    'extra',
    -    'goog-base',
    -    'goog-base-disabled',
    -    'goog-base-hover',
    -    'goog-button'
    -  ], goog.dom.classlist.get(element));
    -}
    -
    -function testDecorateOptimization() {
    -  // Temporarily replace goog.dom.classlist.set().
    -  propertyReplacer.set(goog.dom.classlist, 'set', function() {
    -    fail('goog.dom.classlist.set() must not be called');
    -  });
    -
    -  // Since foo has all required classes, goog.dom.classlist.set() must not be
    -  // called at all.
    -  sandbox.innerHTML = '<div id="foo" class="goog-control">Foo</div>';
    -  controlRenderer.decorate(control, goog.dom.getElement('foo'));
    -
    -  // Since bar has all required classes, goog.dom.classlist.set() must not be
    -  // called at all.
    -  sandbox.innerHTML = '<div id="bar" class="goog-base goog-button">Bar' +
    -      '</div>';
    -  testRenderer.decorate(control, goog.dom.getElement('bar'));
    -
    -  // Since baz has all required classes, goog.dom.classlist.set() must not be
    -  // called at all.
    -  sandbox.innerHTML = '<div id="baz" class="goog-base goog-button ' +
    -      'goog-button-disabled">Baz</div>';
    -  testRenderer.decorate(control, goog.dom.getElement('baz'));
    -}
    -
    -function testInitializeDom() {
    -  var renderer = new goog.ui.ControlRenderer();
    -
    -  // Replace setRightToLeft().
    -  renderer.setRightToLeft = function() {
    -    fail('setRightToLeft() must not be called');
    -  };
    -
    -  // When a control with default render direction enters the document,
    -  // setRightToLeft() must not be called.
    -  control.setRenderer(renderer);
    -  control.render(sandbox);
    -
    -  // When a control in the default state (enabled, visible, focusable)
    -  // enters the document, it must get a tab index.
    -  // Expected to fail on Mac Safari 3, because it doesn't support tab index.
    -  expectedFailures.expectFailureFor(isMacSafari3());
    -  try {
    -    assertTrue('Enabled, visible, focusable control must have tab index',
    -        goog.dom.isFocusableTabIndex(control.getElement()));
    -  } catch (e) {
    -    expectedFailures.handleException(e);
    -  }
    -}
    -
    -function testInitializeDomDecorated() {
    -  var renderer = new goog.ui.ControlRenderer();
    -
    -  // Replace setRightToLeft().
    -  renderer.setRightToLeft = function() {
    -    fail('setRightToLeft() must not be called');
    -  };
    -
    -  sandbox.innerHTML = '<div id="foo" class="goog-control">Foo</div>';
    -
    -  // When a control with default render direction enters the document,
    -  // setRightToLeft() must not be called.
    -  control.setRenderer(renderer);
    -  control.decorate(goog.dom.getElement('foo'));
    -
    -  // When a control in the default state (enabled, visible, focusable)
    -  // enters the document, it must get a tab index.
    -  // Expected to fail on Mac Safari 3, because it doesn't support tab index.
    -  expectedFailures.expectFailureFor(isMacSafari3());
    -  try {
    -    assertTrue('Enabled, visible, focusable control must have tab index',
    -        goog.dom.isFocusableTabIndex(control.getElement()));
    -  } catch (e) {
    -    expectedFailures.handleException(e);
    -  }
    -}
    -
    -function testInitializeDomDisabledBiDi() {
    -  var renderer = new goog.ui.ControlRenderer();
    -
    -  // Replace setFocusable().
    -  renderer.setFocusable = function() {
    -    fail('setFocusable() must not be called');
    -  };
    -
    -  // When a disabled control enters the document, setFocusable() must not
    -  // be called.
    -  control.setEnabled(false);
    -  control.setRightToLeft(true);
    -  control.setRenderer(renderer);
    -  control.render(sandbox);
    -
    -  // When a right-to-left control enters the document, special stying must
    -  // be applied.
    -  assertSameElements('BiDi control must have right-to-left class',
    -      ['goog-control', 'goog-control-disabled', 'goog-control-rtl'],
    -      goog.dom.classlist.get(control.getElement()));
    -}
    -
    -function testInitializeDomDisabledBiDiDecorated() {
    -  var renderer = new goog.ui.ControlRenderer();
    -
    -  // Replace setFocusable().
    -  renderer.setFocusable = function() {
    -    fail('setFocusable() must not be called');
    -  };
    -
    -  sandbox.innerHTML =
    -      '<div dir="rtl">\n' +
    -      '  <div id="foo" class="goog-control-disabled">Foo</div>\n' +
    -      '</div>\n';
    -
    -  // When a disabled control enters the document, setFocusable() must not
    -  // be called.
    -  control.setRenderer(renderer);
    -  control.decorate(goog.dom.getElement('foo'));
    -
    -  // When a right-to-left control enters the document, special stying must
    -  // be applied.
    -  assertSameElements('BiDi control must have right-to-left class',
    -      ['goog-control', 'goog-control-disabled', 'goog-control-rtl'],
    -      goog.dom.classlist.get(control.getElement()));
    -}
    -
    -function testSetAriaRole() {
    -  sandbox.innerHTML = '<div id="foo">Foo</div><div id="bar">Bar</div>';
    -
    -  var foo = goog.dom.getElement('foo');
    -  assertNotNull(foo);
    -  controlRenderer.setAriaRole(foo);
    -  assertEvaluatesToFalse('The role should be empty.',
    -      goog.a11y.aria.getRole(foo));
    -  var bar = goog.dom.getElement('bar');
    -  assertNotNull(bar);
    -  testRenderer.setAriaRole(bar);
    -  assertEquals('Element must have expected ARIA role',
    -      goog.a11y.aria.Role.BUTTON, goog.a11y.aria.getRole(bar));
    -}
    -
    -function testSetAriaStatesHidden() {
    -  sandbox.innerHTML = '<div id="foo">Foo</div><div id="bar">Bar</div>';
    -  var foo = goog.dom.getElement('foo');
    -
    -  control.setVisible(true);
    -  controlRenderer.setAriaStates(control, foo);
    -
    -  assertEquals('ControlRenderer did not set aria-hidden.', '',
    -      goog.a11y.aria.getState(foo, goog.a11y.aria.State.HIDDEN));
    -
    -  control.setVisible(false);
    -  controlRenderer.setAriaStates(control, foo);
    -
    -  assertEquals('ControlRenderer did not set aria-hidden.', 'true',
    -      goog.a11y.aria.getState(foo, goog.a11y.aria.State.HIDDEN));
    -}
    -
    -function testSetAriaStatesDisabled() {
    -  sandbox.innerHTML = '<div id="foo">Foo</div><div id="bar">Bar</div>';
    -  var foo = goog.dom.getElement('foo');
    -
    -  control.setEnabled(true);
    -  controlRenderer.setAriaStates(control, foo);
    -
    -  assertEquals('ControlRenderer did not set aria-disabled.', '',
    -      goog.a11y.aria.getState(foo, goog.a11y.aria.State.DISABLED));
    -
    -  control.setEnabled(false);
    -  controlRenderer.setAriaStates(control, foo);
    -
    -  assertEquals('ControlRenderer did not set aria-disabled.', 'true',
    -      goog.a11y.aria.getState(foo, goog.a11y.aria.State.DISABLED));
    -}
    -
    -function testSetAriaStatesSelected() {
    -  sandbox.innerHTML = '<div id="foo">Foo</div><div id="bar">Bar</div>';
    -  var foo = goog.dom.getElement('foo');
    -  control.setSupportedState(goog.ui.Component.State.SELECTED, true);
    -
    -  control.setSelected(true);
    -  controlRenderer.setAriaStates(control, foo);
    -
    -  assertEquals('ControlRenderer did not set aria-selected.', 'true',
    -      goog.a11y.aria.getState(foo, goog.a11y.aria.State.SELECTED));
    -
    -  control.setSelected(false);
    -  controlRenderer.setAriaStates(control, foo);
    -
    -  assertEquals('ControlRenderer did not set aria-selected.', 'false',
    -      goog.a11y.aria.getState(foo, goog.a11y.aria.State.SELECTED));
    -}
    -
    -function testSetAriaStatesChecked() {
    -  sandbox.innerHTML = '<div id="foo">Foo</div><div id="bar">Bar</div>';
    -  var foo = goog.dom.getElement('foo');
    -  control.setSupportedState(goog.ui.Component.State.CHECKED, true);
    -
    -  control.setChecked(true);
    -  controlRenderer.setAriaStates(control, foo);
    -
    -  assertEquals('ControlRenderer did not set aria-checked.', 'true',
    -      goog.a11y.aria.getState(foo, goog.a11y.aria.State.CHECKED));
    -
    -  control.setChecked(false);
    -  controlRenderer.setAriaStates(control, foo);
    -
    -  assertEquals('ControlRenderer did not set aria-checked.', 'false',
    -      goog.a11y.aria.getState(foo, goog.a11y.aria.State.CHECKED));
    -}
    -
    -function testSetAriaStatesExpanded() {
    -  sandbox.innerHTML = '<div id="foo">Foo</div><div id="bar">Bar</div>';
    -  var foo = goog.dom.getElement('foo');
    -  control.setSupportedState(goog.ui.Component.State.OPENED, true);
    -
    -  control.setOpen(true);
    -  controlRenderer.setAriaStates(control, foo);
    -
    -  assertEquals('ControlRenderer did not set aria-expanded.', 'true',
    -      goog.a11y.aria.getState(foo, goog.a11y.aria.State.EXPANDED));
    -
    -  control.setOpen(false);
    -  controlRenderer.setAriaStates(control, foo);
    -
    -  assertEquals('ControlRenderer did not set aria-expanded.', 'false',
    -      goog.a11y.aria.getState(foo, goog.a11y.aria.State.EXPANDED));
    -}
    -
    -function testSetAllowTextSelection() {
    -  sandbox.innerHTML = '<div id="foo"><span>Foo</span></div>';
    -  var foo = goog.dom.getElement('foo');
    -
    -  controlRenderer.setAllowTextSelection(foo, false);
    -  assertTrue('Parent element must be unselectable on all browsers',
    -      goog.style.isUnselectable(foo));
    -  if (goog.userAgent.IE || goog.userAgent.OPERA) {
    -    assertTrue('On IE and Opera, child element must also be unselectable',
    -        goog.style.isUnselectable(foo.firstChild));
    -  } else {
    -    assertFalse('On browsers other than IE and Opera, the child element ' +
    -        'must not be unselectable',
    -        goog.style.isUnselectable(foo.firstChild));
    -  }
    -
    -  controlRenderer.setAllowTextSelection(foo, true);
    -  assertFalse('Parent element must be selectable',
    -      goog.style.isUnselectable(foo));
    -  assertFalse('Child element must be unselectable',
    -      goog.style.isUnselectable(foo.firstChild));
    -}
    -
    -function testSetRightToLeft() {
    -  sandbox.innerHTML = '<div id="foo">Foo</div><div id="bar">Bar</div>';
    -
    -  var foo = goog.dom.getElement('foo');
    -  controlRenderer.setRightToLeft(foo, true);
    -  assertSameElements('Element must have right-to-left class applied',
    -      ['goog-control-rtl'], goog.dom.classlist.get(foo));
    -  controlRenderer.setRightToLeft(foo, false);
    -  assertSameElements('Element must not have right-to-left class applied',
    -      [], goog.dom.classlist.get(foo));
    -
    -  var bar = goog.dom.getElement('bar');
    -  testRenderer.setRightToLeft(bar, true);
    -  assertSameElements('Element must have right-to-left class applied',
    -      ['goog-base-rtl'], goog.dom.classlist.get(bar));
    -  testRenderer.setRightToLeft(bar, false);
    -  assertSameElements('Element must not have right-to-left class applied',
    -      [], goog.dom.classlist.get(bar));
    -}
    -
    -function testIsFocusable() {
    -  control.render(sandbox);
    -  // Expected to fail on Mac Safari 3, because it doesn't support tab index.
    -  expectedFailures.expectFailureFor(isMacSafari3());
    -  try {
    -    assertTrue('Control\'s key event target must be focusable',
    -        controlRenderer.isFocusable(control));
    -  } catch (e) {
    -    expectedFailures.handleException(e);
    -  }
    -}
    -
    -function testIsFocusableForNonFocusableControl() {
    -  control.setSupportedState(goog.ui.Component.State.FOCUSED, false);
    -  control.render(sandbox);
    -  assertFalse('Non-focusable control\'s key event target must not be ' +
    -      'focusable', controlRenderer.isFocusable(control));
    -}
    -
    -function testIsFocusableForControlWithoutKeyEventTarget() {
    -  // Unrendered control has no key event target.
    -  assertNull('Unrendered control must not have key event target',
    -      control.getKeyEventTarget());
    -  assertFalse('isFocusable() must return null if no key event target',
    -      controlRenderer.isFocusable(control));
    -}
    -
    -function testSetFocusable() {
    -  control.render(sandbox);
    -  controlRenderer.setFocusable(control, false);
    -  assertFalse('Control\'s key event target must not have tab index',
    -      goog.dom.isFocusableTabIndex(control.getKeyEventTarget()));
    -  controlRenderer.setFocusable(control, true);
    -  // Expected to fail on Mac Safari 3, because it doesn't support tab index.
    -  expectedFailures.expectFailureFor(isMacSafari3());
    -  try {
    -    assertTrue('Control\'s key event target must have focusable tab index',
    -        goog.dom.isFocusableTabIndex(control.getKeyEventTarget()));
    -  } catch (e) {
    -    expectedFailures.handleException(e);
    -  }
    -}
    -
    -function testSetFocusableForNonFocusableControl() {
    -  control.setSupportedState(goog.ui.Component.State.FOCUSED, false);
    -  control.render(sandbox);
    -  assertFalse('Non-focusable control\'s key event target must not be ' +
    -      'focusable',
    -      goog.dom.isFocusableTabIndex(control.getKeyEventTarget()));
    -  controlRenderer.setFocusable(control, true);
    -  assertFalse('Non-focusable control\'s key event target must not be ' +
    -      'focusable, even after calling setFocusable(true)',
    -      goog.dom.isFocusableTabIndex(control.getKeyEventTarget()));
    -}
    -
    -function testSetVisible() {
    -  sandbox.innerHTML = '<div id="foo">Foo</div>';
    -  var foo = goog.dom.getElement('foo');
    -  assertTrue('Element must be visible', foo.style.display != 'none');
    -  controlRenderer.setVisible(foo, true);
    -  assertEquals('ControlRenderer did not set aria-hidden.', 'false',
    -      goog.a11y.aria.getState(foo, goog.a11y.aria.State.HIDDEN));
    -  assertTrue('Element must still be visible', foo.style.display != 'none');
    -  controlRenderer.setVisible(foo, false);
    -  assertEquals('ControlRenderer did not set aria-hidden.', 'true',
    -      goog.a11y.aria.getState(foo, goog.a11y.aria.State.HIDDEN));
    -  assertTrue('Element must be hidden', foo.style.display == 'none');
    -}
    -
    -function testSetState() {
    -  control.setRenderer(testRenderer);
    -  control.createDom();
    -  var element = control.getElement();
    -  assertNotNull(element);
    -  assertSameElements('Control must have expected class names',
    -      ['goog-button', 'goog-base'], goog.dom.classlist.get(element));
    -  assertEquals('Control must not have disabled ARIA state', '',
    -      goog.a11y.aria.getState(element,
    -          goog.a11y.aria.State.DISABLED));
    -
    -  testRenderer.setState(control, goog.ui.Component.State.DISABLED, true);
    -  assertSameElements('Control must have disabled class name',
    -      ['goog-button', 'goog-base', 'goog-base-disabled'],
    -      goog.dom.classlist.get(element));
    -  assertEquals('Control must have disabled ARIA state', 'true',
    -      goog.a11y.aria.getState(element,
    -          goog.a11y.aria.State.DISABLED));
    -
    -  testRenderer.setState(control, goog.ui.Component.State.DISABLED, false);
    -  assertSameElements('Control must no longer have disabled class name',
    -      ['goog-button', 'goog-base'], goog.dom.classlist.get(element));
    -  assertEquals('Control must not have disabled ARIA state',
    -      'false',
    -      goog.a11y.aria.getState(element,
    -          goog.a11y.aria.State.DISABLED));
    -
    -  testRenderer.setState(control, 0xFFFFFF, true);
    -  assertSameElements('Class names must be unchanged for invalid state',
    -      ['goog-button', 'goog-base'], goog.dom.classlist.get(element));
    -}
    -
    -function testUpdateAriaStateDisabled() {
    -  control.createDom();
    -  var element = control.getElement();
    -  assertNotNull(element);
    -  controlRenderer.updateAriaState(element, goog.ui.Component.State.DISABLED,
    -      true);
    -  assertEquals('Control must have disabled ARIA state', 'true',
    -      goog.a11y.aria.getState(element,
    -          goog.a11y.aria.State.DISABLED));
    -
    -  controlRenderer.updateAriaState(element, goog.ui.Component.State.DISABLED,
    -      false);
    -  assertEquals('Control must no longer have disabled ARIA state',
    -      'false',
    -      goog.a11y.aria.getState(element,
    -          goog.a11y.aria.State.DISABLED));
    -}
    -
    -function testSetAriaStatesRender_ariaStateDisabled() {
    -  control.setEnabled(false);
    -  var renderer = new goog.ui.ControlRenderer();
    -  control.setRenderer(renderer);
    -  control.render(sandbox);
    -  var element = control.getElement();
    -  assertNotNull(element);
    -  assertFalse('Control must be disabled', control.isEnabled());
    -  assertEquals('Control must have disabled ARIA state', 'true',
    -      goog.a11y.aria.getState(element,
    -      goog.a11y.aria.State.DISABLED));
    -}
    -
    -function testSetAriaStatesDecorate_ariaStateDisabled() {
    -  sandbox.innerHTML =
    -      '<div id="foo" class="app goog-base-disabled"></div>';
    -  var element = goog.dom.getElement('foo');
    -
    -  control.setRenderer(testRenderer);
    -  control.decorate(element);
    -  assertNotNull(element);
    -  assertFalse('Control must be disabled', control.isEnabled());
    -  assertEquals('Control must have disabled ARIA state', 'true',
    -      goog.a11y.aria.getState(element,
    -      goog.a11y.aria.State.DISABLED));
    -}
    -
    -function testUpdateAriaStateSelected() {
    -  control.createDom();
    -  var element = control.getElement();
    -  assertNotNull(element);
    -  controlRenderer.updateAriaState(element, goog.ui.Component.State.SELECTED,
    -      true);
    -  assertEquals('Control must have selected ARIA state', 'true',
    -      goog.a11y.aria.getState(element,
    -          goog.a11y.aria.State.SELECTED));
    -
    -  controlRenderer.updateAriaState(element, goog.ui.Component.State.SELECTED,
    -      false);
    -  assertEquals('Control must no longer have selected ARIA state',
    -      'false',
    -      goog.a11y.aria.getState(element,
    -          goog.a11y.aria.State.SELECTED));
    -}
    -
    -function testSetAriaStatesRender_ariaStateSelected() {
    -  control.setSupportedState(goog.ui.Component.State.SELECTED, true);
    -  control.setSelected(true);
    -
    -  var renderer = new goog.ui.ControlRenderer();
    -  control.setRenderer(renderer);
    -  control.render(sandbox);
    -  var element = control.getElement();
    -  assertNotNull(element);
    -  assertTrue('Control must be selected', control.isSelected());
    -  assertEquals('Control must have selected ARIA state', 'true',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.SELECTED));
    -}
    -
    -function testSetAriaStatesRender_ariaStateNotSelected() {
    -  control.setSupportedState(goog.ui.Component.State.SELECTED, true);
    -
    -  var renderer = new goog.ui.ControlRenderer();
    -  control.setRenderer(renderer);
    -  control.render(sandbox);
    -  var element = control.getElement();
    -  assertNotNull(element);
    -  assertFalse('Control must not be selected', control.isSelected());
    -  assertEquals('Control must have not-selected ARIA state', 'false',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.SELECTED));
    -}
    -
    -function testSetAriaStatesDecorate_ariaStateSelected() {
    -  control.setSupportedState(goog.ui.Component.State.SELECTED, true);
    -
    -  sandbox.innerHTML =
    -      '<div id="foo" class="app goog-control-selected"></div>';
    -  var element = goog.dom.getElement('foo');
    -
    -  control.setRenderer(controlRenderer);
    -  control.decorate(element);
    -  assertNotNull(element);
    -  assertTrue('Control must be selected', control.isSelected());
    -  assertEquals('Control must have selected ARIA state', 'true',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.SELECTED));
    -}
    -
    -function testUpdateAriaStateChecked() {
    -  control.createDom();
    -  var element = control.getElement();
    -  assertNotNull(element);
    -  controlRenderer.updateAriaState(element, goog.ui.Component.State.CHECKED,
    -      true);
    -  assertEquals('Control must have checked ARIA state', 'true',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.CHECKED));
    -
    -  controlRenderer.updateAriaState(element, goog.ui.Component.State.CHECKED,
    -      false);
    -  assertEquals('Control must no longer have checked ARIA state',
    -      'false',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.CHECKED));
    -}
    -
    -function testSetAriaStatesRender_ariaStateChecked() {
    -  control.setSupportedState(goog.ui.Component.State.CHECKED, true);
    -  control.setChecked(true);
    -
    -  var renderer = new goog.ui.ControlRenderer();
    -  control.setRenderer(renderer);
    -  control.render(sandbox);
    -  var element = control.getElement();
    -  assertNotNull(element);
    -  assertTrue('Control must be checked', control.isChecked());
    -  assertEquals('Control must have checked ARIA state', 'true',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.CHECKED));
    -}
    -
    -function testSetAriaStatesDecorate_ariaStateChecked() {
    -  sandbox.innerHTML =
    -      '<div id="foo" class="app goog-control-checked"></div>';
    -  var element = goog.dom.getElement('foo');
    -
    -  control.setSupportedState(goog.ui.Component.State.CHECKED, true);
    -  control.decorate(element);
    -  assertNotNull(element);
    -  assertTrue('Control must be checked', control.isChecked());
    -  assertEquals('Control must have checked ARIA state', 'true',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.CHECKED));
    -}
    -
    -function testUpdateAriaStateOpened() {
    -  control.createDom();
    -  var element = control.getElement();
    -  assertNotNull(element);
    -  controlRenderer.updateAriaState(element, goog.ui.Component.State.OPENED,
    -      true);
    -  assertEquals('Control must have expanded ARIA state', 'true',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.EXPANDED));
    -
    -  controlRenderer.updateAriaState(element, goog.ui.Component.State.OPENED,
    -      false);
    -  assertEquals('Control must no longer have expanded ARIA state',
    -      'false',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.EXPANDED));
    -}
    -
    -function testSetAriaStatesRender_ariaStateOpened() {
    -  control.setSupportedState(goog.ui.Component.State.OPENED, true);
    -  control.setOpen(true);
    -
    -  var renderer = new goog.ui.ControlRenderer();
    -  control.setRenderer(renderer);
    -  control.render(sandbox);
    -  var element = control.getElement();
    -  assertNotNull(element);
    -  assertTrue('Control must be opened', control.isOpen());
    -  assertEquals('Control must have expanded ARIA state', 'true',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.EXPANDED));
    -}
    -
    -function testSetAriaStatesDecorate_ariaStateOpened() {
    -  sandbox.innerHTML =
    -      '<div id="foo" class="app goog-base-open"></div>';
    -  var element = goog.dom.getElement('foo');
    -
    -  control.setSupportedState(goog.ui.Component.State.OPENED, true);
    -  control.setRenderer(testRenderer);
    -  control.decorate(element);
    -  assertNotNull(element);
    -  assertTrue('Control must be opened', control.isOpen());
    -  assertEquals('Control must have expanded ARIA state', 'true',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.EXPANDED));
    -}
    -
    -function testSetAriaStateRoleNotInMap() {
    -  sandbox.innerHTML = '<div id="foo" role="option">Hello, world!</div>';
    -  control.setRenderer(controlRenderer);
    -  control.setSupportedState(goog.ui.Component.State.CHECKED, true);
    -  var element = goog.dom.getElement('foo');
    -  control.decorate(element);
    -  assertEquals('Element should have ARIA role option.',
    -      goog.a11y.aria.Role.OPTION, goog.a11y.aria.getRole(element));
    -  control.setStateInternal(goog.ui.Component.State.DISABLED, true);
    -  controlRenderer.setAriaStates(control, element);
    -  assertEquals('Element should have aria-disabled true', 'true',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.DISABLED));
    -  control.setStateInternal(goog.ui.Component.State.CHECKED, true);
    -  controlRenderer.setAriaStates(control, element);
    -  assertEquals('Element should have aria-checked true', 'true',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.CHECKED));
    -}
    -
    -function testSetAriaStateRoleInMapMatches() {
    -  sandbox.innerHTML = '<div id="foo" role="checkbox">Hello, world!</div>';
    -  control.setRenderer(controlRenderer);
    -  control.setSupportedState(goog.ui.Component.State.CHECKED, true);
    -  var element = goog.dom.getElement('foo');
    -  control.decorate(element);
    -  assertEquals('Element should have ARIA role checkbox.',
    -      goog.a11y.aria.Role.CHECKBOX, goog.a11y.aria.getRole(element));
    -  control.setStateInternal(goog.ui.Component.State.DISABLED, true);
    -  controlRenderer.setAriaStates(control, element);
    -  assertEquals('Element should have aria-disabled true', 'true',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.DISABLED));
    -  control.setStateInternal(goog.ui.Component.State.CHECKED, true);
    -  controlRenderer.setAriaStates(control, element);
    -  assertEquals('Element should have aria-checked true', 'true',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.CHECKED));
    -}
    -
    -function testSetAriaStateRoleInMapNotMatches() {
    -  sandbox.innerHTML = '<div id="foo" role="button">Hello, world!</div>';
    -  control.setRenderer(controlRenderer);
    -  control.setSupportedState(goog.ui.Component.State.CHECKED, true);
    -  var element = goog.dom.getElement('foo');
    -  control.decorate(element);
    -  assertEquals('Element should have ARIA role button.',
    -      goog.a11y.aria.Role.BUTTON, goog.a11y.aria.getRole(element));
    -  control.setStateInternal(goog.ui.Component.State.DISABLED, true);
    -  controlRenderer.setAriaStates(control, element);
    -  assertEquals('Element should have aria-disabled true', 'true',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.DISABLED));
    -  control.setStateInternal(goog.ui.Component.State.CHECKED, true);
    -  controlRenderer.setAriaStates(control, element);
    -  assertEquals('Element should have aria-pressed true', 'true',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.PRESSED));
    -  assertEquals('Element should not have aria-checked', '',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.CHECKED));
    -}
    -
    -function testToggleAriaStateMap() {
    -  var map = goog.object.create(
    -      goog.a11y.aria.Role.BUTTON, goog.a11y.aria.State.PRESSED,
    -      goog.a11y.aria.Role.CHECKBOX, goog.a11y.aria.State.CHECKED,
    -      goog.a11y.aria.Role.MENU_ITEM, goog.a11y.aria.State.SELECTED,
    -      goog.a11y.aria.Role.MENU_ITEM_CHECKBOX, goog.a11y.aria.State.CHECKED,
    -      goog.a11y.aria.Role.MENU_ITEM_RADIO, goog.a11y.aria.State.CHECKED,
    -      goog.a11y.aria.Role.RADIO, goog.a11y.aria.State.CHECKED,
    -      goog.a11y.aria.Role.TAB, goog.a11y.aria.State.SELECTED,
    -      goog.a11y.aria.Role.TREEITEM, goog.a11y.aria.State.SELECTED);
    -  for (var key in map) {
    -    assertTrue('Toggle ARIA state map incorrect.',
    -        key in goog.ui.ControlRenderer.TOGGLE_ARIA_STATE_MAP_);
    -    assertEquals('Toggle ARIA state map incorrect.', map[key],
    -        goog.ui.ControlRenderer.TOGGLE_ARIA_STATE_MAP_[key]);
    -  }
    -}
    -function testSetContent() {
    -  sandbox.innerHTML = 'Hello, world!';
    -  controlRenderer.setContent(sandbox, 'Not so fast!');
    -  assertEquals('Element must contain expected text value', 'Not so fast!',
    -      goog.dom.getTextContent(sandbox));
    -}
    -
    -function testSetContentNull() {
    -  sandbox.innerHTML = 'Hello, world!';
    -  controlRenderer.setContent(sandbox, null);
    -  assertEquals('Element must have no child nodes', 0,
    -      sandbox.childNodes.length);
    -  assertEquals('Element must contain expected text value', '',
    -      goog.dom.getTextContent(sandbox));
    -}
    -
    -function testSetContentEmpty() {
    -  sandbox.innerHTML = 'Hello, world!';
    -  controlRenderer.setContent(sandbox, '');
    -  assertEquals('Element must not have children', 0,
    -      sandbox.childNodes.length);
    -  assertEquals('Element must contain expected text value', '',
    -      goog.dom.getTextContent(sandbox));
    -}
    -
    -function testSetContentWhitespace() {
    -  sandbox.innerHTML = 'Hello, world!';
    -  controlRenderer.setContent(sandbox, ' ');
    -  assertEquals('Element must have one child', 1,
    -      sandbox.childNodes.length);
    -  assertEquals('Child must be a text node', goog.dom.NodeType.TEXT,
    -      sandbox.firstChild.nodeType);
    -  assertEquals('Element must contain expected text value', ' ',
    -      goog.dom.getTextContent(sandbox));
    -}
    -
    -function testSetContentTextNode() {
    -  sandbox.innerHTML = 'Hello, world!';
    -  controlRenderer.setContent(sandbox, document.createTextNode('Text'));
    -  assertEquals('Element must have one child', 1,
    -      sandbox.childNodes.length);
    -  assertEquals('Child must be a text node', goog.dom.NodeType.TEXT,
    -      sandbox.firstChild.nodeType);
    -  assertEquals('Element must contain expected text value', 'Text',
    -      goog.dom.getTextContent(sandbox));
    -}
    -
    -function testSetContentElementNode() {
    -  sandbox.innerHTML = 'Hello, world!';
    -  controlRenderer.setContent(sandbox,
    -      goog.dom.createDom('div', {id: 'foo'}, 'Foo'));
    -  assertEquals('Element must have one child', 1,
    -      sandbox.childNodes.length);
    -  assertEquals('Child must be an element node', goog.dom.NodeType.ELEMENT,
    -      sandbox.firstChild.nodeType);
    -  assertHTMLEquals('Element must contain expected HTML',
    -      '<div id="foo">Foo</div>', sandbox.innerHTML);
    -}
    -
    -function testSetContentArray() {
    -  sandbox.innerHTML = 'Hello, world!';
    -  controlRenderer.setContent(sandbox,
    -      ['Hello, ', goog.dom.createDom('b', null, 'world'), '!']);
    -  assertEquals('Element must have three children', 3,
    -      sandbox.childNodes.length);
    -  assertEquals('1st child must be a text node', goog.dom.NodeType.TEXT,
    -      sandbox.childNodes[0].nodeType);
    -  assertEquals('2nd child must be an element', goog.dom.NodeType.ELEMENT,
    -      sandbox.childNodes[1].nodeType);
    -  assertEquals('3rd child must be a text node', goog.dom.NodeType.TEXT,
    -      sandbox.childNodes[2].nodeType);
    -  assertHTMLEquals('Element must contain expected HTML',
    -      'Hello, <b>world</b>!', sandbox.innerHTML);
    -}
    -
    -function testSetContentNodeList() {
    -  sandbox.innerHTML = 'Hello, world!';
    -  var div = goog.dom.createDom('div', null, 'Hello, ',
    -      goog.dom.createDom('b', null, 'world'), '!');
    -  controlRenderer.setContent(sandbox, div.childNodes);
    -  assertEquals('Element must have three children', 3,
    -      sandbox.childNodes.length);
    -  assertEquals('1st child must be a text node', goog.dom.NodeType.TEXT,
    -      sandbox.childNodes[0].nodeType);
    -  assertEquals('2nd child must be an element', goog.dom.NodeType.ELEMENT,
    -      sandbox.childNodes[1].nodeType);
    -  assertEquals('3rd child must be a text node', goog.dom.NodeType.TEXT,
    -      sandbox.childNodes[2].nodeType);
    -  assertHTMLEquals('Element must contain expected HTML',
    -      'Hello, <b>world</b>!', sandbox.innerHTML);
    -}
    -
    -function testGetKeyEventTarget() {
    -  assertNull('Key event target for unrendered control must be null',
    -      controlRenderer.getKeyEventTarget(control));
    -  control.createDom();
    -  assertEquals('Key event target for rendered control must be its element',
    -      control.getElement(), controlRenderer.getKeyEventTarget(control));
    -}
    -
    -function testGetCssClass() {
    -  assertEquals('ControlRenderer\'s CSS class must have expected value',
    -      goog.ui.ControlRenderer.CSS_CLASS, controlRenderer.getCssClass());
    -  assertEquals('TestRenderer\'s CSS class must have expected value',
    -      TestRenderer.CSS_CLASS, testRenderer.getCssClass());
    -}
    -
    -function testGetStructuralCssClass() {
    -  assertEquals('ControlRenderer\'s structural class must be its CSS class',
    -      controlRenderer.getCssClass(),
    -      controlRenderer.getStructuralCssClass());
    -  assertEquals('TestRenderer\'s structural class must have expected value',
    -      'goog-base', testRenderer.getStructuralCssClass());
    -}
    -
    -function testGetClassNames() {
    -  // These tests use assertArrayEquals, because the order is significant.
    -  assertArrayEquals('ControlRenderer must return expected class names ' +
    -      'in the expected order',
    -      ['goog-control'],
    -      controlRenderer.getClassNames(control));
    -  assertArrayEquals('TestRenderer must return expected class names ' +
    -      'in the expected order',
    -      ['goog-button', 'goog-base'],
    -      testRenderer.getClassNames(control));
    -}
    -
    -function testGetClassNamesForControlWithState() {
    -  control.setStateInternal(goog.ui.Component.State.HOVER |
    -      goog.ui.Component.State.ACTIVE);
    -
    -  // These tests use assertArrayEquals, because the order is significant.
    -  assertArrayEquals('ControlRenderer must return expected class names ' +
    -      'in the expected order',
    -      ['goog-control', 'goog-control-hover', 'goog-control-active'],
    -      controlRenderer.getClassNames(control));
    -  assertArrayEquals('TestRenderer must return expected class names ' +
    -      'in the expected order',
    -      ['goog-button', 'goog-base', 'goog-base-hover', 'goog-base-active'],
    -      testRenderer.getClassNames(control));
    -}
    -
    -function testGetClassNamesForControlWithExtraClassNames() {
    -  control.addClassName('foo');
    -  control.addClassName('bar');
    -
    -  // These tests use assertArrayEquals, because the order is significant.
    -  assertArrayEquals('ControlRenderer must return expected class names ' +
    -      'in the expected order',
    -      ['goog-control', 'foo', 'bar'],
    -      controlRenderer.getClassNames(control));
    -  assertArrayEquals('TestRenderer must return expected class names ' +
    -      'in the expected order',
    -      ['goog-button', 'goog-base', 'foo', 'bar'],
    -      testRenderer.getClassNames(control));
    -}
    -
    -function testGetClassNamesForControlWithStateAndExtraClassNames() {
    -  control.setStateInternal(goog.ui.Component.State.HOVER |
    -      goog.ui.Component.State.ACTIVE);
    -  control.addClassName('foo');
    -  control.addClassName('bar');
    -
    -  // These tests use assertArrayEquals, because the order is significant.
    -  assertArrayEquals('ControlRenderer must return expected class names ' +
    -      'in the expected order', [
    -        'goog-control',
    -        'goog-control-hover',
    -        'goog-control-active',
    -        'foo',
    -        'bar'
    -      ], controlRenderer.getClassNames(control));
    -  assertArrayEquals('TestRenderer must return expected class names ' +
    -      'in the expected order', [
    -        'goog-button',
    -        'goog-base',
    -        'goog-base-hover',
    -        'goog-base-active',
    -        'foo',
    -        'bar'
    -      ], testRenderer.getClassNames(control));
    -}
    -
    -function testGetClassNamesForState() {
    -  // These tests use assertArrayEquals, because the order is significant.
    -  assertArrayEquals('ControlRenderer must return expected class names ' +
    -      'in the expected order',
    -      ['goog-control-hover', 'goog-control-checked'],
    -      controlRenderer.getClassNamesForState(goog.ui.Component.State.HOVER |
    -          goog.ui.Component.State.CHECKED));
    -  assertArrayEquals('TestRenderer must return expected class names ' +
    -      'in the expected order',
    -      ['goog-base-hover', 'goog-base-checked'],
    -      testRenderer.getClassNamesForState(goog.ui.Component.State.HOVER |
    -          goog.ui.Component.State.CHECKED));
    -}
    -
    -function testGetClassForState() {
    -  var renderer = new goog.ui.ControlRenderer();
    -  assertUndefined('State-to-class map must not exist until first use',
    -      renderer.classByState_);
    -  assertEquals('Renderer must return expected class name for SELECTED',
    -      'goog-control-selected',
    -      renderer.getClassForState(goog.ui.Component.State.SELECTED));
    -  assertUndefined('Renderer must return undefined for invalid state',
    -      renderer.getClassForState('foo'));
    -}
    -
    -function testGetStateFromClass() {
    -  var renderer = new goog.ui.ControlRenderer();
    -  assertUndefined('Class-to-state map must not exist until first use',
    -      renderer.stateByClass_);
    -  assertEquals('Renderer must return expected state',
    -      goog.ui.Component.State.SELECTED,
    -      renderer.getStateFromClass('goog-control-selected'));
    -  assertEquals('Renderer must return 0x00 for unknown class',
    -      0x00,
    -      renderer.getStateFromClass('goog-control-annoyed'));
    -}
    -
    -function testIe6ClassCombinationsCreateDom() {
    -  control.setRenderer(testRenderer);
    -
    -  control.enableClassName('combined', true);
    -
    -  control.createDom();
    -  var element = control.getElement();
    -
    -  testRenderer.setState(control, goog.ui.Component.State.DISABLED, true);
    -  var expectedClasses = [
    -    'combined',
    -    'goog-base',
    -    'goog-base-disabled',
    -    'goog-button'
    -  ];
    -  if (isIe6()) {
    -    assertSameElements('IE6 and lower should have one combined class',
    -        expectedClasses.concat(['combined_goog-base-disabled_goog-button']),
    -        goog.dom.classlist.get(element));
    -  } else {
    -    assertSameElements('Non IE6 browsers should not have a combined class',
    -        expectedClasses, goog.dom.classlist.get(element));
    -  }
    -
    -  testRenderer.setState(control, goog.ui.Component.State.DISABLED, false);
    -  testRenderer.setState(control, goog.ui.Component.State.HOVER, true);
    -  var expectedClasses = [
    -    'combined',
    -    'goog-base',
    -    'goog-base-hover',
    -    'goog-button'
    -  ];
    -  if (isIe6()) {
    -    assertSameElements('IE6 and lower should have one combined class',
    -        expectedClasses.concat(['combined_goog-base-hover_goog-button']),
    -        goog.dom.classlist.get(element));
    -  } else {
    -    assertSameElements('Non IE6 browsers should not have a combined class',
    -        expectedClasses, goog.dom.classlist.get(element));
    -  }
    -
    -  testRenderer.setRightToLeft(element, true);
    -  testRenderer.enableExtraClassName(control, 'combined2', true);
    -  var expectedClasses = [
    -    'combined',
    -    'combined2',
    -    'goog-base',
    -    'goog-base-hover',
    -    'goog-base-rtl',
    -    'goog-button'
    -  ];
    -  if (isIe6()) {
    -    assertSameElements('IE6 and lower should have two combined class',
    -        expectedClasses.concat([
    -          'combined_goog-base-hover_goog-button',
    -          'combined_combined2_goog-base-hover_goog-base-rtl_goog-button'
    -        ]), goog.dom.classlist.get(element));
    -  } else {
    -    assertSameElements('Non IE6 browsers should not have a combined class',
    -        expectedClasses, goog.dom.classlist.get(element));
    -  }
    -
    -}
    -
    -function testIe6ClassCombinationsDecorate() {
    -  sandbox.innerHTML =
    -      '<div id="foo" class="combined goog-base-hover"></div>';
    -  var foo = goog.dom.getElement('foo');
    -
    -  var element = testRenderer.decorate(control, foo);
    -
    -  var expectedClasses = [
    -    'combined',
    -    'goog-base',
    -    'goog-base-hover',
    -    'goog-button'
    -  ];
    -  if (isIe6()) {
    -    assertSameElements('IE6 and lower should have one combined class',
    -        expectedClasses.concat(['combined_goog-base-hover_goog-button']),
    -        goog.dom.classlist.get(element));
    -  } else {
    -    assertSameElements('Non IE6 browsers should not have a combined class',
    -        expectedClasses, goog.dom.classlist.get(element));
    -  }
    -
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/cookieeditor.js b/src/database/third_party/closure-library/closure/goog/ui/cookieeditor.js
    deleted file mode 100644
    index 6c7ee7b0d31..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/cookieeditor.js
    +++ /dev/null
    @@ -1,185 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Displays and edits the value of a cookie.
    - * Intended only for debugging.
    - */
    -goog.provide('goog.ui.CookieEditor');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.events.EventType');
    -goog.require('goog.net.cookies');
    -goog.require('goog.string');
    -goog.require('goog.style');
    -goog.require('goog.ui.Component');
    -
    -
    -
    -/**
    - * Displays and edits the value of a cookie.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @constructor
    - * @extends {goog.ui.Component}
    - * @final
    - */
    -goog.ui.CookieEditor = function(opt_domHelper) {
    -  goog.ui.CookieEditor.base(this, 'constructor', opt_domHelper);
    -};
    -goog.inherits(goog.ui.CookieEditor, goog.ui.Component);
    -
    -
    -/**
    - * Cookie key.
    - * @type {?string}
    - * @private
    - */
    -goog.ui.CookieEditor.prototype.cookieKey_;
    -
    -
    -/**
    - * Text area.
    - * @type {HTMLTextAreaElement}
    - * @private
    - */
    -goog.ui.CookieEditor.prototype.textAreaElem_;
    -
    -
    -/**
    - * Clear button.
    - * @type {HTMLButtonElement}
    - * @private
    - */
    -goog.ui.CookieEditor.prototype.clearButtonElem_;
    -
    -
    -/**
    - * Invalid value warning text.
    - * @type {HTMLSpanElement}
    - * @private
    - */
    -goog.ui.CookieEditor.prototype.valueWarningElem_;
    -
    -
    -/**
    - * Update button.
    - * @type {HTMLButtonElement}
    - * @private
    - */
    -goog.ui.CookieEditor.prototype.updateButtonElem_;
    -
    -
    -// TODO(user): add combobox for user to select different cookies
    -/**
    - * Sets the cookie which this component will edit.
    - * @param {string} cookieKey Cookie key.
    - */
    -goog.ui.CookieEditor.prototype.selectCookie = function(cookieKey) {
    -  goog.asserts.assert(goog.net.cookies.isValidName(cookieKey));
    -  this.cookieKey_ = cookieKey;
    -  if (this.textAreaElem_) {
    -    this.textAreaElem_.value = goog.net.cookies.get(cookieKey) || '';
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.CookieEditor.prototype.canDecorate = function() {
    -  return false;
    -};
    -
    -
    -/** @override */
    -goog.ui.CookieEditor.prototype.createDom = function() {
    -  // Debug-only, so we don't need i18n.
    -  this.clearButtonElem_ = /** @type {!HTMLButtonElement} */ (goog.dom.createDom(
    -      goog.dom.TagName.BUTTON, /* attributes */ null, 'Clear'));
    -  this.updateButtonElem_ =
    -      /** @type {!HTMLButtonElement} */ (goog.dom.createDom(
    -          goog.dom.TagName.BUTTON, /* attributes */ null, 'Update'));
    -  var value = this.cookieKey_ && goog.net.cookies.get(this.cookieKey_);
    -  this.textAreaElem_ = /** @type {!HTMLTextAreaElement} */ (goog.dom.createDom(
    -      goog.dom.TagName.TEXTAREA, /* attibutes */ null, value || ''));
    -  this.valueWarningElem_ = /** @type {!HTMLSpanElement} */ (goog.dom.createDom(
    -      goog.dom.TagName.SPAN, /* attibutes */ {
    -        'style': 'display:none;color:red'
    -      }, 'Invalid cookie value.'));
    -  this.setElementInternal(goog.dom.createDom(goog.dom.TagName.DIV,
    -      /* attibutes */ null,
    -      this.valueWarningElem_,
    -      goog.dom.createDom(goog.dom.TagName.BR),
    -      this.textAreaElem_,
    -      goog.dom.createDom(goog.dom.TagName.BR),
    -      this.clearButtonElem_,
    -      this.updateButtonElem_));
    -};
    -
    -
    -/** @override */
    -goog.ui.CookieEditor.prototype.enterDocument = function() {
    -  goog.ui.CookieEditor.base(this, 'enterDocument');
    -  this.getHandler().listen(this.clearButtonElem_,
    -      goog.events.EventType.CLICK,
    -      this.handleClear_);
    -  this.getHandler().listen(this.updateButtonElem_,
    -      goog.events.EventType.CLICK,
    -      this.handleUpdate_);
    -};
    -
    -
    -/**
    - * Handles user clicking clear button.
    - * @param {!goog.events.Event} e The click event.
    - * @private
    - */
    -goog.ui.CookieEditor.prototype.handleClear_ = function(e) {
    -  if (this.cookieKey_) {
    -    goog.net.cookies.remove(this.cookieKey_);
    -  }
    -  this.textAreaElem_.value = '';
    -};
    -
    -
    -/**
    - * Handles user clicking update button.
    - * @param {!goog.events.Event} e The click event.
    - * @private
    - */
    -goog.ui.CookieEditor.prototype.handleUpdate_ = function(e) {
    -  if (this.cookieKey_) {
    -    var value = this.textAreaElem_.value;
    -    if (value) {
    -      // Strip line breaks.
    -      value = goog.string.stripNewlines(value);
    -    }
    -    if (goog.net.cookies.isValidValue(value)) {
    -      goog.net.cookies.set(this.cookieKey_, value);
    -      goog.style.setElementShown(this.valueWarningElem_, false);
    -    } else {
    -      goog.style.setElementShown(this.valueWarningElem_, true);
    -    }
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.CookieEditor.prototype.disposeInternal = function() {
    -  this.clearButtonElem_ = null;
    -  this.cookieKey_ = null;
    -  this.textAreaElem_ = null;
    -  this.updateButtonElem_ = null;
    -  this.valueWarningElem_ = null;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/cookieeditor_test.html b/src/database/third_party/closure-library/closure/goog/ui/cookieeditor_test.html
    deleted file mode 100644
    index 0399a99090d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/cookieeditor_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.CookieEditor
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.CookieEditorTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="test_container">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/cookieeditor_test.js b/src/database/third_party/closure-library/closure/goog/ui/cookieeditor_test.js
    deleted file mode 100644
    index f3f9ed17f9b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/cookieeditor_test.js
    +++ /dev/null
    @@ -1,104 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.CookieEditorTest');
    -goog.setTestOnly('goog.ui.CookieEditorTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventType');
    -goog.require('goog.net.cookies');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.CookieEditor');
    -
    -var COOKIE_KEY = 'my_fabulous_cookie';
    -var COOKIE_VALUES;
    -
    -goog.net.cookies.get = function(key) {
    -  return COOKIE_VALUES[key];
    -};
    -
    -goog.net.cookies.set = function(key, value) {
    -  return COOKIE_VALUES[key] = value;
    -};
    -
    -goog.net.cookies.remove = function(key, value) {
    -  delete COOKIE_VALUES[key];
    -};
    -
    -function setUp() {
    -  goog.dom.removeChildren(goog.dom.getElement('test_container'));
    -  COOKIE_VALUES = {};
    -}
    -
    -function newCookieEditor(opt_cookieValue) {
    -  // Set cookie.
    -  if (opt_cookieValue) {
    -    goog.net.cookies.set(COOKIE_KEY, opt_cookieValue);
    -  }
    -
    -  // Render editor.
    -  var editor = new goog.ui.CookieEditor();
    -  editor.selectCookie(COOKIE_KEY);
    -  editor.render(goog.dom.getElement('test_container'));
    -  assertEquals('wrong text area value', opt_cookieValue || '',
    -      editor.textAreaElem_.value || '');
    -
    -  return editor;
    -}
    -
    -function testRender() {
    -  // Render editor.
    -  var editor = newCookieEditor();
    -
    -  // All expected elements created?
    -  var elem = editor.getElement();
    -  assertNotNullNorUndefined('missing element', elem);
    -  assertNotNullNorUndefined('missing clear button', editor.clearButtonElem_);
    -  assertNotNullNorUndefined('missing update button',
    -      editor.updateButtonElem_);
    -  assertNotNullNorUndefined('missing text area', editor.textAreaElem_);
    -}
    -
    -function testEditCookie() {
    -  // Render editor.
    -  var editor = newCookieEditor();
    -
    -  // Invalid value.
    -  var newValue = 'my bad value;';
    -  editor.textAreaElem_.value = newValue;
    -  goog.testing.events.fireBrowserEvent(new goog.events.Event(
    -      goog.events.EventType.CLICK, editor.updateButtonElem_));
    -  assertTrue('unexpected cookie value', !goog.net.cookies.get(COOKIE_KEY));
    -
    -  // Valid value.
    -  newValue = 'my fabulous value';
    -  editor.textAreaElem_.value = newValue;
    -  goog.testing.events.fireBrowserEvent(new goog.events.Event(
    -      goog.events.EventType.CLICK, editor.updateButtonElem_));
    -  assertEquals('wrong cookie value', newValue,
    -      goog.net.cookies.get(COOKIE_KEY));
    -}
    -
    -function testClearCookie() {
    -  // Render editor.
    -  var value = 'I will be cleared';
    -  var editor = newCookieEditor(value);
    -
    -  // Clear value.
    -  goog.testing.events.fireBrowserEvent(new goog.events.Event(
    -      goog.events.EventType.CLICK, editor.clearButtonElem_));
    -  assertTrue('unexpected cookie value', !goog.net.cookies.get(COOKIE_KEY));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/css3buttonrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/css3buttonrenderer.js
    deleted file mode 100644
    index e29cb78987e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/css3buttonrenderer.js
    +++ /dev/null
    @@ -1,154 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview An alternative imageless button renderer that uses CSS3 rather
    - * than voodoo to render custom buttons with rounded corners and dimensionality
    - * (via a subtle flat shadow on the bottom half of the button) without the use
    - * of images.
    - *
    - * Based on the Custom Buttons 3.1 visual specification, see
    - * http://go/custombuttons
    - *
    - * Tested and verified to work in Gecko 1.9.2+ and WebKit 528+.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - * @see ../demos/css3button.html
    - */
    -
    -goog.provide('goog.ui.Css3ButtonRenderer');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.ui.Button');
    -goog.require('goog.ui.ButtonRenderer');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.INLINE_BLOCK_CLASSNAME');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * Custom renderer for {@link goog.ui.Button}s. Css3 buttons can contain
    - * almost arbitrary HTML content, will flow like inline elements, but can be
    - * styled like block-level elements.
    - *
    - * @constructor
    - * @extends {goog.ui.ButtonRenderer}
    - * @final
    - */
    -goog.ui.Css3ButtonRenderer = function() {
    -  goog.ui.ButtonRenderer.call(this);
    -};
    -goog.inherits(goog.ui.Css3ButtonRenderer, goog.ui.ButtonRenderer);
    -
    -
    -/**
    - * The singleton instance of this renderer class.
    - * @type {goog.ui.Css3ButtonRenderer?}
    - * @private
    - */
    -goog.ui.Css3ButtonRenderer.instance_ = null;
    -goog.addSingletonGetter(goog.ui.Css3ButtonRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.Css3ButtonRenderer.CSS_CLASS = goog.getCssName('goog-css3-button');
    -
    -
    -/** @override */
    -goog.ui.Css3ButtonRenderer.prototype.getContentElement = function(element) {
    -  return /** @type {Element} */ (element);
    -};
    -
    -
    -/**
    - * Returns the button's contents wrapped in the following DOM structure:
    - *    <div class="goog-inline-block goog-css3-button">
    - *      Contents...
    - *    </div>
    - * Overrides {@link goog.ui.ButtonRenderer#createDom}.
    - * @param {goog.ui.Control} control goog.ui.Button to render.
    - * @return {!Element} Root element for the button.
    - * @override
    - */
    -goog.ui.Css3ButtonRenderer.prototype.createDom = function(control) {
    -  var button = /** @type {goog.ui.Button} */ (control);
    -  var classNames = this.getClassNames(button);
    -  var attr = {
    -    'class': goog.ui.INLINE_BLOCK_CLASSNAME + ' ' + classNames.join(' '),
    -    'title': button.getTooltip() || ''
    -  };
    -  return button.getDomHelper().createDom('div', attr, button.getContent());
    -};
    -
    -
    -/**
    - * Returns true if this renderer can decorate the element.  Overrides
    - * {@link goog.ui.ButtonRenderer#canDecorate} by returning true if the
    - * element is a DIV, false otherwise.
    - * @param {Element} element Element to decorate.
    - * @return {boolean} Whether the renderer can decorate the element.
    - * @override
    - */
    -goog.ui.Css3ButtonRenderer.prototype.canDecorate = function(element) {
    -  return element.tagName == goog.dom.TagName.DIV;
    -};
    -
    -
    -/** @override */
    -goog.ui.Css3ButtonRenderer.prototype.decorate = function(button, element) {
    -  goog.asserts.assert(element);
    -  goog.dom.classlist.addAll(element,
    -      [goog.ui.INLINE_BLOCK_CLASSNAME, this.getCssClass()]);
    -  return goog.ui.Css3ButtonRenderer.superClass_.decorate.call(this, button,
    -      element);
    -};
    -
    -
    -/**
    - * Returns the CSS class to be applied to the root element of components
    - * rendered using this renderer.
    - * @return {string} Renderer-specific CSS class.
    - * @override
    - */
    -goog.ui.Css3ButtonRenderer.prototype.getCssClass = function() {
    -  return goog.ui.Css3ButtonRenderer.CSS_CLASS;
    -};
    -
    -
    -// Register a decorator factory function for goog.ui.Css3ButtonRenderer.
    -goog.ui.registry.setDecoratorByClassName(
    -    goog.ui.Css3ButtonRenderer.CSS_CLASS,
    -    function() {
    -      return new goog.ui.Button(null,
    -          goog.ui.Css3ButtonRenderer.getInstance());
    -    });
    -
    -
    -// Register a decorator factory function for toggle buttons using the
    -// goog.ui.Css3ButtonRenderer.
    -goog.ui.registry.setDecoratorByClassName(
    -    goog.getCssName('goog-css3-toggle-button'),
    -    function() {
    -      var button = new goog.ui.Button(null,
    -          goog.ui.Css3ButtonRenderer.getInstance());
    -      button.setSupportedState(goog.ui.Component.State.CHECKED, true);
    -      return button;
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/css3menubuttonrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/css3menubuttonrenderer.js
    deleted file mode 100644
    index 7e6f24b9e2e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/css3menubuttonrenderer.js
    +++ /dev/null
    @@ -1,146 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview An alternative imageless button renderer that uses CSS3 rather
    - * than voodoo to render custom buttons with rounded corners and dimensionality
    - * (via a subtle flat shadow on the bottom half of the button) without the use
    - * of images.
    - *
    - * Based on the Custom Buttons 3.1 visual specification, see
    - * http://go/custombuttons
    - *
    - * Tested and verified to work in Gecko 1.9.2+ and WebKit 528+.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - * @see ../demos/css3menubutton.html
    - */
    -
    -goog.provide('goog.ui.Css3MenuButtonRenderer');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.ui.INLINE_BLOCK_CLASSNAME');
    -goog.require('goog.ui.MenuButton');
    -goog.require('goog.ui.MenuButtonRenderer');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * Custom renderer for {@link goog.ui.MenuButton}s. Css3 buttons can contain
    - * almost arbitrary HTML content, will flow like inline elements, but can be
    - * styled like block-level elements.
    - *
    - * @constructor
    - * @extends {goog.ui.MenuButtonRenderer}
    - * @final
    - */
    -goog.ui.Css3MenuButtonRenderer = function() {
    -  goog.ui.MenuButtonRenderer.call(this);
    -};
    -goog.inherits(goog.ui.Css3MenuButtonRenderer, goog.ui.MenuButtonRenderer);
    -
    -
    -/**
    - * The singleton instance of this renderer class.
    - * @type {goog.ui.Css3MenuButtonRenderer?}
    - * @private
    - */
    -goog.ui.Css3MenuButtonRenderer.instance_ = null;
    -goog.addSingletonGetter(goog.ui.Css3MenuButtonRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.Css3MenuButtonRenderer.CSS_CLASS = goog.getCssName('goog-css3-button');
    -
    -
    -/** @override */
    -goog.ui.Css3MenuButtonRenderer.prototype.getContentElement = function(element) {
    -  if (element) {
    -    var captionElem = goog.dom.getElementsByTagNameAndClass(
    -        '*', goog.getCssName(this.getCssClass(), 'caption'), element)[0];
    -    return captionElem;
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * Returns true if this renderer can decorate the element.  Overrides
    - * {@link goog.ui.MenuButtonRenderer#canDecorate} by returning true if the
    - * element is a DIV, false otherwise.
    - * @param {Element} element Element to decorate.
    - * @return {boolean} Whether the renderer can decorate the element.
    - * @override
    - */
    -goog.ui.Css3MenuButtonRenderer.prototype.canDecorate = function(element) {
    -  return element.tagName == goog.dom.TagName.DIV;
    -};
    -
    -
    -/**
    - * Takes a text caption or existing DOM structure, and returns the content
    - * wrapped in a pseudo-rounded-corner box.  Creates the following DOM structure:
    - *  <div class="goog-inline-block goog-css3-button goog-css3-menu-button">
    - *    <div class="goog-css3-button-caption">Contents...</div>
    - *    <div class="goog-css3-button-dropdown"></div>
    - *  </div>
    - *
    - * Used by both {@link #createDom} and {@link #decorate}.  To be overridden
    - * by subclasses.
    - * @param {goog.ui.ControlContent} content Text caption or DOM structure to wrap
    - *     in a box.
    - * @param {goog.dom.DomHelper} dom DOM helper, used for document interaction.
    - * @return {!Element} Pseudo-rounded-corner box containing the content.
    - * @override
    - */
    -goog.ui.Css3MenuButtonRenderer.prototype.createButton = function(content, dom) {
    -  var baseClass = this.getCssClass();
    -  var inlineBlock = goog.ui.INLINE_BLOCK_CLASSNAME + ' ';
    -  return dom.createDom('div', inlineBlock,
    -      dom.createDom('div', [goog.getCssName(baseClass, 'caption'),
    -                            goog.getCssName('goog-inline-block')],
    -                    content),
    -      dom.createDom('div', [goog.getCssName(baseClass, 'dropdown'),
    -                            goog.getCssName('goog-inline-block')]));
    -};
    -
    -
    -/**
    - * Returns the CSS class to be applied to the root element of components
    - * rendered using this renderer.
    - * @return {string} Renderer-specific CSS class.
    - * @override
    - */
    -goog.ui.Css3MenuButtonRenderer.prototype.getCssClass = function() {
    -  return goog.ui.Css3MenuButtonRenderer.CSS_CLASS;
    -};
    -
    -
    -// Register a decorator factory function for goog.ui.Css3MenuButtonRenderer.
    -// Since we're using goog-css3-button as the base class in order to get the
    -// same styling as goog.ui.Css3ButtonRenderer, we need to be explicit about
    -// giving goog-css3-menu-button here.
    -goog.ui.registry.setDecoratorByClassName(
    -    goog.getCssName('goog-css3-menu-button'),
    -    function() {
    -      return new goog.ui.MenuButton(null, null,
    -          goog.ui.Css3MenuButtonRenderer.getInstance());
    -    });
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/cssnames.js b/src/database/third_party/closure-library/closure/goog/ui/cssnames.js
    deleted file mode 100644
    index 4ad5419ba5a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/cssnames.js
    +++ /dev/null
    @@ -1,29 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Common CSS class name constants.
    - *
    - * @author mkretzschmar@google.com (Martin Kretzschmar)
    - */
    -
    -goog.provide('goog.ui.INLINE_BLOCK_CLASSNAME');
    -
    -
    -/**
    - * CSS class name for applying the "display: inline-block" property in a
    - * cross-browser way.
    - * @type {string}
    - */
    -goog.ui.INLINE_BLOCK_CLASSNAME = goog.getCssName('goog-inline-block');
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/custombutton.js b/src/database/third_party/closure-library/closure/goog/ui/custombutton.js
    deleted file mode 100644
    index 15f728468d8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/custombutton.js
    +++ /dev/null
    @@ -1,58 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A button rendered via {@link goog.ui.CustomButtonRenderer}.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.CustomButton');
    -
    -goog.require('goog.ui.Button');
    -goog.require('goog.ui.CustomButtonRenderer');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * A custom button control.  Identical to {@link goog.ui.Button}, except it
    - * defaults its renderer to {@link goog.ui.CustomButtonRenderer}.  One could
    - * just as easily pass {@code goog.ui.CustomButtonRenderer.getInstance()} to
    - * the {@link goog.ui.Button} constructor and get the same result.  Provided
    - * for convenience.
    - *
    - * @param {goog.ui.ControlContent} content Text caption or existing DOM
    - *    structure to display as the button's caption.
    - * @param {goog.ui.ButtonRenderer=} opt_renderer Optional renderer used to
    - *    render or decorate the button; defaults to
    - *    {@link goog.ui.CustomButtonRenderer}.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *    document interaction.
    - * @constructor
    - * @extends {goog.ui.Button}
    - */
    -goog.ui.CustomButton = function(content, opt_renderer, opt_domHelper) {
    -  goog.ui.Button.call(this, content, opt_renderer ||
    -      goog.ui.CustomButtonRenderer.getInstance(), opt_domHelper);
    -};
    -goog.inherits(goog.ui.CustomButton, goog.ui.Button);
    -
    -
    -// Register a decorator factory function for goog.ui.CustomButtons.
    -goog.ui.registry.setDecoratorByClassName(goog.ui.CustomButtonRenderer.CSS_CLASS,
    -    function() {
    -      // CustomButton defaults to using CustomButtonRenderer.
    -      return new goog.ui.CustomButton(null);
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/custombuttonrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/custombuttonrenderer.js
    deleted file mode 100644
    index 40150acd7eb..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/custombuttonrenderer.js
    +++ /dev/null
    @@ -1,270 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A custom button renderer that uses CSS voodoo to render a
    - * button-like object with fake rounded corners.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.CustomButtonRenderer');
    -
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.asserts');
    -goog.require('goog.dom.NodeType');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.string');
    -goog.require('goog.ui.ButtonRenderer');
    -goog.require('goog.ui.INLINE_BLOCK_CLASSNAME');
    -
    -
    -
    -/**
    - * Custom renderer for {@link goog.ui.Button}s.  Custom buttons can contain
    - * almost arbitrary HTML content, will flow like inline elements, but can be
    - * styled like block-level elements.
    - *
    - * @constructor
    - * @extends {goog.ui.ButtonRenderer}
    - */
    -goog.ui.CustomButtonRenderer = function() {
    -  goog.ui.ButtonRenderer.call(this);
    -};
    -goog.inherits(goog.ui.CustomButtonRenderer, goog.ui.ButtonRenderer);
    -goog.addSingletonGetter(goog.ui.CustomButtonRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.CustomButtonRenderer.CSS_CLASS = goog.getCssName('goog-custom-button');
    -
    -
    -/**
    - * Returns the button's contents wrapped in the following DOM structure:
    - *    <div class="goog-inline-block goog-custom-button">
    - *      <div class="goog-inline-block goog-custom-button-outer-box">
    - *        <div class="goog-inline-block goog-custom-button-inner-box">
    - *          Contents...
    - *        </div>
    - *      </div>
    - *    </div>
    - * Overrides {@link goog.ui.ButtonRenderer#createDom}.
    - * @param {goog.ui.Control} control goog.ui.Button to render.
    - * @return {!Element} Root element for the button.
    - * @override
    - */
    -goog.ui.CustomButtonRenderer.prototype.createDom = function(control) {
    -  var button = /** @type {goog.ui.Button} */ (control);
    -  var classNames = this.getClassNames(button);
    -  var attributes = {
    -    'class': goog.ui.INLINE_BLOCK_CLASSNAME + ' ' + classNames.join(' ')
    -  };
    -  var buttonElement = button.getDomHelper().createDom('div', attributes,
    -      this.createButton(button.getContent(), button.getDomHelper()));
    -  this.setTooltip(
    -      buttonElement, /** @type {!string}*/ (button.getTooltip()));
    -
    -  return buttonElement;
    -};
    -
    -
    -/**
    - * Returns the ARIA role to be applied to custom buttons.
    - * @return {goog.a11y.aria.Role|undefined} ARIA role.
    - * @override
    - */
    -goog.ui.CustomButtonRenderer.prototype.getAriaRole = function() {
    -  return goog.a11y.aria.Role.BUTTON;
    -};
    -
    -
    -/**
    - * Takes the button's root element and returns the parent element of the
    - * button's contents.  Overrides the superclass implementation by taking
    - * the nested DIV structure of custom buttons into account.
    - * @param {Element} element Root element of the button whose content
    - *     element is to be returned.
    - * @return {Element} The button's content element (if any).
    - * @override
    - */
    -goog.ui.CustomButtonRenderer.prototype.getContentElement = function(element) {
    -  return element && element.firstChild &&
    -      /** @type {Element} */ (element.firstChild.firstChild);
    -};
    -
    -
    -/**
    - * Takes a text caption or existing DOM structure, and returns the content
    - * wrapped in a pseudo-rounded-corner box.  Creates the following DOM structure:
    - *  <div class="goog-inline-block goog-custom-button-outer-box">
    - *    <div class="goog-inline-block goog-custom-button-inner-box">
    - *      Contents...
    - *    </div>
    - *  </div>
    - * Used by both {@link #createDom} and {@link #decorate}.  To be overridden
    - * by subclasses.
    - * @param {goog.ui.ControlContent} content Text caption or DOM structure to wrap
    - *     in a box.
    - * @param {goog.dom.DomHelper} dom DOM helper, used for document interaction.
    - * @return {Element} Pseudo-rounded-corner box containing the content.
    - */
    -goog.ui.CustomButtonRenderer.prototype.createButton = function(content, dom) {
    -  return dom.createDom('div',
    -      goog.ui.INLINE_BLOCK_CLASSNAME + ' ' +
    -      goog.getCssName(this.getCssClass(), 'outer-box'),
    -      dom.createDom('div',
    -          goog.ui.INLINE_BLOCK_CLASSNAME + ' ' +
    -          goog.getCssName(this.getCssClass(), 'inner-box'), content));
    -};
    -
    -
    -/**
    - * Returns true if this renderer can decorate the element.  Overrides
    - * {@link goog.ui.ButtonRenderer#canDecorate} by returning true if the
    - * element is a DIV, false otherwise.
    - * @param {Element} element Element to decorate.
    - * @return {boolean} Whether the renderer can decorate the element.
    - * @override
    - */
    -goog.ui.CustomButtonRenderer.prototype.canDecorate = function(element) {
    -  return element.tagName == 'DIV';
    -};
    -
    -
    -/**
    - * Check if the button's element has a box structure.
    - * @param {goog.ui.Button} button Button instance whose structure is being
    - *     checked.
    - * @param {Element} element Element of the button.
    - * @return {boolean} Whether the element has a box structure.
    - * @protected
    - */
    -goog.ui.CustomButtonRenderer.prototype.hasBoxStructure = function(
    -    button, element) {
    -  var outer = button.getDomHelper().getFirstElementChild(element);
    -  var outerClassName = goog.getCssName(this.getCssClass(), 'outer-box');
    -  if (outer && goog.dom.classlist.contains(outer, outerClassName)) {
    -
    -    var inner = button.getDomHelper().getFirstElementChild(outer);
    -    var innerClassName = goog.getCssName(this.getCssClass(), 'inner-box');
    -    if (inner && goog.dom.classlist.contains(inner, innerClassName)) {
    -      // We have a proper box structure.
    -      return true;
    -    }
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Takes an existing element and decorates it with the custom button control.
    - * Initializes the control's ID, content, tooltip, value, and state based
    - * on the ID of the element, its child nodes, and its CSS classes, respectively.
    - * Returns the element.  Overrides {@link goog.ui.ButtonRenderer#decorate}.
    - * @param {goog.ui.Control} control Button instance to decorate the element.
    - * @param {Element} element Element to decorate.
    - * @return {Element} Decorated element.
    - * @override
    - */
    -goog.ui.CustomButtonRenderer.prototype.decorate = function(control, element) {
    -  goog.asserts.assert(element);
    -
    -  var button = /** @type {goog.ui.Button} */ (control);
    -  // Trim text nodes in the element's child node list; otherwise madness
    -  // ensues (i.e. on Gecko, buttons will flicker and shift when moused over).
    -  goog.ui.CustomButtonRenderer.trimTextNodes_(element, true);
    -  goog.ui.CustomButtonRenderer.trimTextNodes_(element, false);
    -
    -  // Create the buttom dom if it has not been created.
    -  if (!this.hasBoxStructure(button, element)) {
    -    element.appendChild(
    -        this.createButton(element.childNodes, button.getDomHelper()));
    -  }
    -
    -  goog.dom.classlist.addAll(element,
    -      [goog.ui.INLINE_BLOCK_CLASSNAME, this.getCssClass()]);
    -  return goog.ui.CustomButtonRenderer.superClass_.decorate.call(this, button,
    -      element);
    -};
    -
    -
    -/**
    - * Returns the CSS class to be applied to the root element of components
    - * rendered using this renderer.
    - * @return {string} Renderer-specific CSS class.
    - * @override
    - */
    -goog.ui.CustomButtonRenderer.prototype.getCssClass = function() {
    -  return goog.ui.CustomButtonRenderer.CSS_CLASS;
    -};
    -
    -
    -/**
    - * Takes an element and removes leading or trailing whitespace from the start
    - * or the end of its list of child nodes.  The Boolean argument determines
    - * whether to trim from the start or the end of the node list.  Empty text
    - * nodes are removed, and the first non-empty text node is trimmed from the
    - * left or the right as appropriate.  For example,
    - *    <div class="goog-inline-block">
    - *      #text ""
    - *      #text "\n    Hello "
    - *      <span>...</span>
    - *      #text " World!    \n"
    - *      #text ""
    - *    </div>
    - * becomes
    - *    <div class="goog-inline-block">
    - *      #text "Hello "
    - *      <span>...</span>
    - *      #text " World!"
    - *    </div>
    - * This is essential for Gecko, where leading/trailing whitespace messes with
    - * the layout of elements with -moz-inline-box (used in goog-inline-block), and
    - * optional but harmless for non-Gecko.
    - *
    - * @param {Element} element Element whose child node list is to be trimmed.
    - * @param {boolean} fromStart Whether to trim from the start or from the end.
    - * @private
    - */
    -goog.ui.CustomButtonRenderer.trimTextNodes_ = function(element, fromStart) {
    -  if (element) {
    -    var node = fromStart ? element.firstChild : element.lastChild, next;
    -    // Tag soup HTML may result in a DOM where siblings have different parents.
    -    while (node && node.parentNode == element) {
    -      // Get the next/previous sibling here, since the node may be removed.
    -      next = fromStart ? node.nextSibling : node.previousSibling;
    -      if (node.nodeType == goog.dom.NodeType.TEXT) {
    -        // Found a text node.
    -        var text = node.nodeValue;
    -        if (goog.string.trim(text) == '') {
    -          // Found an empty text node; remove it.
    -          element.removeChild(node);
    -        } else {
    -          // Found a non-empty text node; trim from the start/end, then exit.
    -          node.nodeValue = fromStart ?
    -              goog.string.trimLeft(text) : goog.string.trimRight(text);
    -          break;
    -        }
    -      } else {
    -        // Found a non-text node; done.
    -        break;
    -      }
    -      node = next;
    -    }
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/customcolorpalette.js b/src/database/third_party/closure-library/closure/goog/ui/customcolorpalette.js
    deleted file mode 100644
    index f66a0de05bd..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/customcolorpalette.js
    +++ /dev/null
    @@ -1,140 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A color palette with a button for adding additional colors
    - * manually.
    - *
    - */
    -
    -goog.provide('goog.ui.CustomColorPalette');
    -
    -goog.require('goog.color');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.ui.ColorPalette');
    -goog.require('goog.ui.Component');
    -
    -
    -
    -/**
    - * A custom color palette is a grid of color swatches and a button that allows
    - * the user to add additional colors to the palette
    - *
    - * @param {Array<string>} initColors Array of initial colors to populate the
    - *     palette with.
    - * @param {goog.ui.PaletteRenderer=} opt_renderer Renderer used to render or
    - *     decorate the palette; defaults to {@link goog.ui.PaletteRenderer}.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @constructor
    - * @extends {goog.ui.ColorPalette}
    - * @final
    - */
    -goog.ui.CustomColorPalette = function(initColors, opt_renderer, opt_domHelper) {
    -  goog.ui.ColorPalette.call(this, initColors, opt_renderer, opt_domHelper);
    -  this.setSupportedState(goog.ui.Component.State.OPENED, true);
    -};
    -goog.inherits(goog.ui.CustomColorPalette, goog.ui.ColorPalette);
    -
    -
    -/**
    - * Returns an array of DOM nodes for each color, and an additional cell with a
    - * '+'.
    - * @return {!Array<Node>} Array of div elements.
    - * @override
    - */
    -goog.ui.CustomColorPalette.prototype.createColorNodes = function() {
    -  /** @desc Hover caption for the button that allows the user to add a color. */
    -  var MSG_CLOSURE_CUSTOM_COLOR_BUTTON = goog.getMsg('Add a color');
    -
    -  var nl = goog.ui.CustomColorPalette.base(this, 'createColorNodes');
    -  nl.push(goog.dom.createDom('div', {
    -    'class': goog.getCssName('goog-palette-customcolor'),
    -    'title': MSG_CLOSURE_CUSTOM_COLOR_BUTTON
    -  }, '+'));
    -  return nl;
    -};
    -
    -
    -/**
    - * @override
    - * @param {goog.events.Event} e Mouse or key event that triggered the action.
    - * @return {boolean} True if the action was allowed to proceed, false otherwise.
    - */
    -goog.ui.CustomColorPalette.prototype.performActionInternal = function(e) {
    -  var item = /** @type {Element} */ (this.getHighlightedItem());
    -  if (item) {
    -    if (goog.dom.classlist.contains(
    -        item, goog.getCssName('goog-palette-customcolor'))) {
    -      // User activated the special "add custom color" swatch.
    -      this.promptForCustomColor();
    -    } else {
    -      // User activated a normal color swatch.
    -      this.setSelectedItem(item);
    -      return this.dispatchEvent(goog.ui.Component.EventType.ACTION);
    -    }
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Prompts the user to enter a custom color.  Currently uses a window.prompt
    - * but could be updated to use a dialog box with a WheelColorPalette.
    - */
    -goog.ui.CustomColorPalette.prototype.promptForCustomColor = function() {
    -  /** @desc Default custom color dialog. */
    -  var MSG_CLOSURE_CUSTOM_COLOR_PROMPT = goog.getMsg(
    -      'Input custom color, i.e. pink, #F00, #D015FF or rgb(100, 50, 25)');
    -
    -  // A CustomColorPalette is considered "open" while the color selection prompt
    -  // is open.  Enabling state transition events for the OPENED state and
    -  // listening for OPEN events allows clients to save the selection before
    -  // it is destroyed (see e.g. bug 1064701).
    -  var response = null;
    -  this.setOpen(true);
    -  if (this.isOpen()) {
    -    // The OPEN event wasn't canceled; prompt for custom color.
    -    response = window.prompt(MSG_CLOSURE_CUSTOM_COLOR_PROMPT, '#FFFFFF');
    -    this.setOpen(false);
    -  }
    -
    -  if (!response) {
    -    // The user hit cancel
    -    return;
    -  }
    -
    -  var color;
    -  /** @preserveTry */
    -  try {
    -    color = goog.color.parse(response).hex;
    -  } catch (er) {
    -    /** @desc Alert message sent when the input string is not a valid color. */
    -    var MSG_CLOSURE_CUSTOM_COLOR_INVALID_INPUT = goog.getMsg(
    -        'ERROR: "{$color}" is not a valid color.', {'color': response});
    -    alert(MSG_CLOSURE_CUSTOM_COLOR_INVALID_INPUT);
    -    return;
    -  }
    -
    -  // TODO(user): This is relatively inefficient.  Consider adding
    -  // functionality to palette to add individual items after render time.
    -  var colors = this.getColors();
    -  colors.push(color);
    -  this.setColors(colors);
    -
    -  // Set the selected color to the new color and notify listeners of the action.
    -  this.setSelectedColor(color);
    -  this.dispatchEvent(goog.ui.Component.EventType.ACTION);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/customcolorpalette_test.html b/src/database/third_party/closure-library/closure/goog/ui/customcolorpalette_test.html
    deleted file mode 100644
    index 1931af0dd64..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/customcolorpalette_test.html
    +++ /dev/null
    @@ -1,28 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   CustomColorPalette Unit Tests
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script src="../deps.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.CustomColorPaletteTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="sandbox">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/customcolorpalette_test.js b/src/database/third_party/closure-library/closure/goog/ui/customcolorpalette_test.js
    deleted file mode 100644
    index 3881c42cc9b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/customcolorpalette_test.js
    +++ /dev/null
    @@ -1,55 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.CustomColorPaletteTest');
    -goog.setTestOnly('goog.ui.CustomColorPaletteTest');
    -
    -goog.require('goog.dom.TagName');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.CustomColorPalette');
    -
    -var samplePalette;
    -
    -function setUp() {
    -  samplePalette = new goog.ui.CustomColorPalette();
    -}
    -
    -function tearDown() {
    -  samplePalette.dispose();
    -  document.getElementById('sandbox').innerHTML = '';
    -}
    -
    -function testRender() {
    -  samplePalette.render(document.getElementById('sandbox'));
    -
    -  assertTrue('Palette must have been rendered',
    -             samplePalette.isInDocument());
    -
    -  var elem = samplePalette.getElement();
    -  assertNotNull('The palette element should not be null', elem);
    -  assertEquals('The palette element should have the right tag name',
    -               goog.dom.TagName.DIV, elem.tagName);
    -
    -  assertTrue('The custom color palette should have the right class name',
    -             goog.dom.classlist.contains(elem, 'goog-palette'));
    -}
    -
    -function testSetColors() {
    -  var colorSet = ['#e06666', '#f6b26b', '#ffd966', '#93c47d', '#76a5af',
    -    '#6fa8dc', '#8e7cc3'];
    -  samplePalette.setColors(colorSet);
    -  assertSameElements('The palette should have the correct set of colors',
    -                     colorSet, samplePalette.getColors());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/datepicker.js b/src/database/third_party/closure-library/closure/goog/ui/datepicker.js
    deleted file mode 100644
    index a4605232633..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/datepicker.js
    +++ /dev/null
    @@ -1,1549 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Date picker implementation.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - * @see ../demos/datepicker.html
    - */
    -
    -goog.provide('goog.ui.DatePicker');
    -goog.provide('goog.ui.DatePicker.Events');
    -goog.provide('goog.ui.DatePickerEvent');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.asserts');
    -goog.require('goog.date.Date');
    -goog.require('goog.date.DateRange');
    -goog.require('goog.date.Interval');
    -goog.require('goog.dom');
    -goog.require('goog.dom.NodeType');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyHandler');
    -goog.require('goog.i18n.DateTimeFormat');
    -goog.require('goog.i18n.DateTimePatterns');
    -goog.require('goog.i18n.DateTimeSymbols');
    -goog.require('goog.style');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.DefaultDatePickerRenderer');
    -goog.require('goog.ui.IdGenerator');
    -
    -
    -
    -/**
    - * DatePicker widget. Allows a single date to be selected from a calendar like
    - * view.
    - *
    - * @param {goog.date.Date|Date=} opt_date Date to initialize the date picker
    - *     with, defaults to the current date.
    - * @param {Object=} opt_dateTimeSymbols Date and time symbols to use.
    - *     Defaults to goog.i18n.DateTimeSymbols if not set.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @param {goog.ui.DatePickerRenderer=} opt_renderer Optional Date picker
    - *     renderer.
    - * @constructor
    - * @extends {goog.ui.Component}
    - */
    -goog.ui.DatePicker = function(opt_date, opt_dateTimeSymbols, opt_domHelper,
    -    opt_renderer) {
    -  goog.ui.Component.call(this, opt_domHelper);
    -
    -  /**
    -   * Date and time symbols to use.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.symbols_ = opt_dateTimeSymbols || goog.i18n.DateTimeSymbols;
    -
    -  this.wdayNames_ = this.symbols_.STANDALONESHORTWEEKDAYS;
    -
    -  // The DateTimeFormat object uses the global goog.i18n.DateTimeSymbols
    -  // for initialization. So we save the original value, the global object,
    -  // create the formatters, then restore the original value.
    -  var tempSymbols = goog.i18n.DateTimeSymbols;  // save
    -  goog.i18n.DateTimeSymbols = this.symbols_;
    -
    -  // Formatters for the various areas of the picker
    -  this.i18nDateFormatterDay_ = new goog.i18n.DateTimeFormat('d');
    -  this.i18nDateFormatterDay2_ = new goog.i18n.DateTimeFormat('dd');
    -  this.i18nDateFormatterWeek_ = new goog.i18n.DateTimeFormat('w');
    -
    -  // Previous implementation did not use goog.i18n.DateTimePatterns,
    -  // so it is likely most developers did not set it.
    -  // This is why the fallback to a hard-coded string (just in case).
    -  var patYear = goog.i18n.DateTimePatterns.YEAR_FULL || 'y';
    -  this.i18nDateFormatterYear_ = new goog.i18n.DateTimeFormat(patYear);
    -  var patMMMMy = goog.i18n.DateTimePatterns.YEAR_MONTH_FULL || 'MMMM y';
    -  this.i18nDateFormatterMonthYear_ = new goog.i18n.DateTimeFormat(patMMMMy);
    -
    -  goog.i18n.DateTimeSymbols = tempSymbols;  // restore
    -
    -  /**
    -   * @type {!goog.ui.DatePickerRenderer}
    -   * @private
    -   */
    -  this.renderer_ = opt_renderer || new goog.ui.DefaultDatePickerRenderer(
    -      this.getBaseCssClass(), this.getDomHelper());
    -
    -  /**
    -   * Selected date.
    -   * @type {goog.date.Date}
    -   * @private
    -   */
    -  this.date_ = new goog.date.Date(opt_date);
    -  this.date_.setFirstWeekCutOffDay(this.symbols_.FIRSTWEEKCUTOFFDAY);
    -  this.date_.setFirstDayOfWeek(this.symbols_.FIRSTDAYOFWEEK);
    -
    -  /**
    -   * Active month.
    -   * @type {goog.date.Date}
    -   * @private
    -   */
    -  this.activeMonth_ = this.date_.clone();
    -  this.activeMonth_.setDate(1);
    -
    -  /**
    -   * Class names to apply to the weekday columns.
    -   * @type {Array<string>}
    -   * @private
    -   */
    -  this.wdayStyles_ = ['', '', '', '', '', '', ''];
    -  this.wdayStyles_[this.symbols_.WEEKENDRANGE[0]] =
    -      goog.getCssName(this.getBaseCssClass(), 'wkend-start');
    -  this.wdayStyles_[this.symbols_.WEEKENDRANGE[1]] =
    -      goog.getCssName(this.getBaseCssClass(), 'wkend-end');
    -
    -  /**
    -   * Object that is being used to cache key handlers.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.keyHandlers_ = {};
    -
    -  /**
    -   * Collection of dates that make up the date picker.
    -   * @type {!Array<!Array<!goog.date.Date>>}
    -   * @private
    -   */
    -  this.grid_ = [];
    -
    -  /** @private {Array<!Array<Element>>} */
    -  this.elTable_;
    -
    -  /**
    -   * TODO(tbreisacher): Remove external references to this field,
    -   * and make it private.
    -   * @type {Element}
    -   */
    -  this.tableBody_;
    -
    -  /** @private {Element} */
    -  this.tableFoot_;
    -
    -  /** @private {Element} */
    -  this.elYear_;
    -
    -  /** @private {Element} */
    -  this.elMonth_;
    -
    -  /** @private {Element} */
    -  this.elToday_;
    -
    -  /** @private {Element} */
    -  this.elNone_;
    -
    -  /** @private {Element} */
    -  this.menu_;
    -
    -  /** @private {Element} */
    -  this.menuSelected_;
    -
    -  /** @private {function(Element)} */
    -  this.menuCallback_;
    -};
    -goog.inherits(goog.ui.DatePicker, goog.ui.Component);
    -goog.tagUnsealableClass(goog.ui.DatePicker);
    -
    -
    -/**
    - * Flag indicating if the number of weeks shown should be fixed.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.DatePicker.prototype.showFixedNumWeeks_ = true;
    -
    -
    -/**
    - * Flag indicating if days from other months should be shown.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.DatePicker.prototype.showOtherMonths_ = true;
    -
    -
    -/**
    - * Range of dates which are selectable by the user.
    - * @type {goog.date.DateRange}
    - * @private
    - */
    -goog.ui.DatePicker.prototype.userSelectableDateRange_ =
    -    goog.date.DateRange.allTime();
    -
    -
    -/**
    - * Flag indicating if extra week(s) always should be added at the end. If not
    - * set the extra week is added at the beginning if the number of days shown
    - * from the previous month is less then the number from the next month.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.DatePicker.prototype.extraWeekAtEnd_ = true;
    -
    -
    -/**
    - * Flag indicating if week numbers should be shown.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.DatePicker.prototype.showWeekNum_ = true;
    -
    -
    -/**
    - * Flag indicating if weekday names should be shown.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.DatePicker.prototype.showWeekdays_ = true;
    -
    -
    -/**
    - * Flag indicating if none is a valid selection. Also controls if the none
    - * button should be shown or not.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.DatePicker.prototype.allowNone_ = true;
    -
    -
    -/**
    - * Flag indicating if the today button should be shown.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.DatePicker.prototype.showToday_ = true;
    -
    -
    -/**
    - * Flag indicating if the picker should use a simple navigation menu that only
    - * contains controls for navigating to the next and previous month. The default
    - * navigation menu contains controls for navigating to the next/previous month,
    - * next/previous year, and menus for jumping to specific months and years.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.DatePicker.prototype.simpleNavigation_ = false;
    -
    -
    -/**
    - * Custom decorator function. Takes a goog.date.Date object, returns a String
    - * representing a CSS class or null if no special styling applies
    - * @type {Function}
    - * @private
    - */
    -goog.ui.DatePicker.prototype.decoratorFunction_ = null;
    -
    -
    -/**
    - * Flag indicating if the dates should be printed as a two charater date.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.DatePicker.prototype.longDateFormat_ = false;
    -
    -
    -/**
    - * Element for navigation row on a datepicker.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.DatePicker.prototype.elNavRow_ = null;
    -
    -
    -/**
    - * Element for the month/year in the navigation row.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.DatePicker.prototype.elMonthYear_ = null;
    -
    -
    -/**
    - * Element for footer row on a datepicker.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.DatePicker.prototype.elFootRow_ = null;
    -
    -
    -/**
    - * Generator for unique table cell IDs.
    - * @type {goog.ui.IdGenerator}
    - * @private
    - */
    -goog.ui.DatePicker.prototype.cellIdGenerator_ =
    -    goog.ui.IdGenerator.getInstance();
    -
    -
    -/**
    - * Name of base CSS class of datepicker.
    - * @type {string}
    - * @private
    - */
    -goog.ui.DatePicker.BASE_CSS_CLASS_ = goog.getCssName('goog-date-picker');
    -
    -
    -/**
    - * The numbers of years to show before and after the current one in the
    - * year pull-down menu. A total of YEAR_MENU_RANGE * 2 + 1 will be shown.
    - * Example: for range = 2 and year 2013 => [2011, 2012, 2013, 2014, 2015]
    - * @const {number}
    - * @private
    - */
    -goog.ui.DatePicker.YEAR_MENU_RANGE_ = 5;
    -
    -
    -/**
    - * Constants for event names
    - *
    - * @const
    - */
    -goog.ui.DatePicker.Events = {
    -  CHANGE: 'change',
    -  CHANGE_ACTIVE_MONTH: 'changeActiveMonth',
    -  SELECT: 'select'
    -};
    -
    -
    -/**
    - * @deprecated Use isInDocument.
    - */
    -goog.ui.DatePicker.prototype.isCreated =
    -    goog.ui.DatePicker.prototype.isInDocument;
    -
    -
    -/**
    - * @return {number} The first day of week, 0 = Monday, 6 = Sunday.
    - */
    -goog.ui.DatePicker.prototype.getFirstWeekday = function() {
    -  return this.activeMonth_.getFirstDayOfWeek();
    -};
    -
    -
    -/**
    - * Returns the class name associated with specified weekday.
    - * @param {number} wday The week day number to get the class name for.
    - * @return {string} The class name associated with specified weekday.
    - */
    -goog.ui.DatePicker.prototype.getWeekdayClass = function(wday) {
    -  return this.wdayStyles_[wday];
    -};
    -
    -
    -/**
    - * @return {boolean} Whether a fixed number of weeks should be showed. If not
    - *     only weeks for the current month will be shown.
    - */
    -goog.ui.DatePicker.prototype.getShowFixedNumWeeks = function() {
    -  return this.showFixedNumWeeks_;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether a days from the previous and/or next month should
    - *     be shown.
    - */
    -goog.ui.DatePicker.prototype.getShowOtherMonths = function() {
    -  return this.showOtherMonths_;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether a the extra week(s) added always should be at the
    - *     end. Only applicable if a fixed number of weeks are shown.
    - */
    -goog.ui.DatePicker.prototype.getExtraWeekAtEnd = function() {
    -  return this.extraWeekAtEnd_;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether week numbers should be shown.
    - */
    -goog.ui.DatePicker.prototype.getShowWeekNum = function() {
    -  return this.showWeekNum_;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether weekday names should be shown.
    - */
    -goog.ui.DatePicker.prototype.getShowWeekdayNames = function() {
    -  return this.showWeekdays_;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether none is a valid selection.
    - */
    -goog.ui.DatePicker.prototype.getAllowNone = function() {
    -  return this.allowNone_;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the today button should be shown.
    - */
    -goog.ui.DatePicker.prototype.getShowToday = function() {
    -  return this.showToday_;
    -};
    -
    -
    -/**
    - * Returns base CSS class. This getter is used to get base CSS class part.
    - * All CSS class names in component are created as:
    - *   goog.getCssName(this.getBaseCssClass(), 'CLASS_NAME')
    - * @return {string} Base CSS class.
    - */
    -goog.ui.DatePicker.prototype.getBaseCssClass = function() {
    -  return goog.ui.DatePicker.BASE_CSS_CLASS_;
    -};
    -
    -
    -/**
    - * Sets the first day of week
    - *
    - * @param {number} wday Week day, 0 = Monday, 6 = Sunday.
    - */
    -goog.ui.DatePicker.prototype.setFirstWeekday = function(wday) {
    -  this.activeMonth_.setFirstDayOfWeek(wday);
    -  this.updateCalendarGrid_();
    -  this.redrawWeekdays_();
    -};
    -
    -
    -/**
    - * Sets class name associated with specified weekday.
    - *
    - * @param {number} wday Week day, 0 = Monday, 6 = Sunday.
    - * @param {string} className Class name.
    - */
    -goog.ui.DatePicker.prototype.setWeekdayClass = function(wday, className) {
    -  this.wdayStyles_[wday] = className;
    -  this.redrawCalendarGrid_();
    -};
    -
    -
    -/**
    - * Sets whether a fixed number of weeks should be showed. If not only weeks
    - * for the current month will be showed.
    - *
    - * @param {boolean} b Whether a fixed number of weeks should be showed.
    - */
    -goog.ui.DatePicker.prototype.setShowFixedNumWeeks = function(b) {
    -  this.showFixedNumWeeks_ = b;
    -  this.updateCalendarGrid_();
    -};
    -
    -
    -/**
    - * Sets whether a days from the previous and/or next month should be shown.
    - *
    - * @param {boolean} b Whether a days from the previous and/or next month should
    - *     be shown.
    - */
    -goog.ui.DatePicker.prototype.setShowOtherMonths = function(b) {
    -  this.showOtherMonths_ = b;
    -  this.redrawCalendarGrid_();
    -};
    -
    -
    -/**
    - * Sets the range of dates which may be selected by the user.
    - *
    - * @param {goog.date.DateRange} dateRange The range of selectable dates.
    - */
    -goog.ui.DatePicker.prototype.setUserSelectableDateRange =
    -    function(dateRange) {
    -  this.userSelectableDateRange_ = dateRange;
    -};
    -
    -
    -/**
    - * Determine if a date may be selected by the user.
    - *
    - * @param {goog.date.Date} date The date to be tested.
    - * @return {boolean} Whether the user may select this date.
    - * @private
    - */
    -goog.ui.DatePicker.prototype.isUserSelectableDate_ = function(date) {
    -  return this.userSelectableDateRange_.contains(date);
    -};
    -
    -
    -/**
    - * Sets whether the picker should use a simple navigation menu that only
    - * contains controls for navigating to the next and previous month. The default
    - * navigation menu contains controls for navigating to the next/previous month,
    - * next/previous year, and menus for jumping to specific months and years.
    - *
    - * @param {boolean} b Whether to use a simple navigation menu.
    - */
    -goog.ui.DatePicker.prototype.setUseSimpleNavigationMenu = function(b) {
    -  this.simpleNavigation_ = b;
    -  this.updateNavigationRow_();
    -  this.updateCalendarGrid_();
    -};
    -
    -
    -/**
    - * Sets whether a the extra week(s) added always should be at the end. Only
    - * applicable if a fixed number of weeks are shown.
    - *
    - * @param {boolean} b Whether a the extra week(s) added always should be at the
    - *     end.
    - */
    -goog.ui.DatePicker.prototype.setExtraWeekAtEnd = function(b) {
    -  this.extraWeekAtEnd_ = b;
    -  this.updateCalendarGrid_();
    -};
    -
    -
    -/**
    - * Sets whether week numbers should be shown.
    - *
    - * @param {boolean} b Whether week numbers should be shown.
    - */
    -goog.ui.DatePicker.prototype.setShowWeekNum = function(b) {
    -  this.showWeekNum_ = b;
    -  // The navigation and footer rows may rely on the number of visible columns,
    -  // so we update them when adding/removing the weeknum column.
    -  this.updateNavigationRow_();
    -  this.updateFooterRow_();
    -  this.updateCalendarGrid_();
    -};
    -
    -
    -/**
    - * Sets whether weekday names should be shown.
    - *
    - * @param {boolean} b Whether weekday names should be shown.
    - */
    -goog.ui.DatePicker.prototype.setShowWeekdayNames = function(b) {
    -  this.showWeekdays_ = b;
    -  this.redrawWeekdays_();
    -  this.redrawCalendarGrid_();
    -};
    -
    -
    -/**
    - * Sets whether the picker uses narrow weekday names ('M', 'T', 'W', ...).
    - *
    - * The default behavior is to use short names ('Mon', 'Tue', 'Wed', ...).
    - *
    - * @param {boolean} b Whether to use narrow weekday names.
    - */
    -goog.ui.DatePicker.prototype.setUseNarrowWeekdayNames = function(b) {
    -  this.wdayNames_ = b ? this.symbols_.STANDALONENARROWWEEKDAYS :
    -      this.symbols_.STANDALONESHORTWEEKDAYS;
    -  this.redrawWeekdays_();
    -};
    -
    -
    -/**
    - * Sets whether none is a valid selection.
    - *
    - * @param {boolean} b Whether none is a valid selection.
    - */
    -goog.ui.DatePicker.prototype.setAllowNone = function(b) {
    -  this.allowNone_ = b;
    -  if (this.elNone_) {
    -    this.updateTodayAndNone_();
    -  }
    -};
    -
    -
    -/**
    - * Sets whether the today button should be shown.
    - *
    - * @param {boolean} b Whether the today button should be shown.
    - */
    -goog.ui.DatePicker.prototype.setShowToday = function(b) {
    -  this.showToday_ = b;
    -  if (this.elToday_) {
    -    this.updateTodayAndNone_();
    -  }
    -};
    -
    -
    -/**
    - * Updates the display style of the None and Today buttons as well as hides the
    - * table foot if both are hidden.
    - * @private
    - */
    -goog.ui.DatePicker.prototype.updateTodayAndNone_ = function() {
    -  goog.style.setElementShown(this.elToday_, this.showToday_);
    -  goog.style.setElementShown(this.elNone_, this.allowNone_);
    -  goog.style.setElementShown(this.tableFoot_,
    -                             this.showToday_ || this.allowNone_);
    -};
    -
    -
    -/**
    - * Sets the decorator function. The function should have the interface of
    - *   {string} f({goog.date.Date});
    - * and return a String representing a CSS class to decorate the cell
    - * corresponding to the date specified.
    - *
    - * @param {Function} f The decorator function.
    - */
    -goog.ui.DatePicker.prototype.setDecorator = function(f) {
    -  this.decoratorFunction_ = f;
    -};
    -
    -
    -/**
    - * Sets whether the date will be printed in long format. In long format, dates
    - * such as '1' will be printed as '01'.
    - *
    - * @param {boolean} b Whethere dates should be printed in long format.
    - */
    -goog.ui.DatePicker.prototype.setLongDateFormat = function(b) {
    -  this.longDateFormat_ = b;
    -  this.redrawCalendarGrid_();
    -};
    -
    -
    -/**
    - * Changes the active month to the previous one.
    - */
    -goog.ui.DatePicker.prototype.previousMonth = function() {
    -  this.activeMonth_.add(new goog.date.Interval(goog.date.Interval.MONTHS, -1));
    -  this.updateCalendarGrid_();
    -  this.fireChangeActiveMonthEvent_();
    -};
    -
    -
    -/**
    - * Changes the active month to the next one.
    - */
    -goog.ui.DatePicker.prototype.nextMonth = function() {
    -  this.activeMonth_.add(new goog.date.Interval(goog.date.Interval.MONTHS, 1));
    -  this.updateCalendarGrid_();
    -  this.fireChangeActiveMonthEvent_();
    -};
    -
    -
    -/**
    - * Changes the active year to the previous one.
    - */
    -goog.ui.DatePicker.prototype.previousYear = function() {
    -  this.activeMonth_.add(new goog.date.Interval(goog.date.Interval.YEARS, -1));
    -  this.updateCalendarGrid_();
    -  this.fireChangeActiveMonthEvent_();
    -};
    -
    -
    -/**
    - * Changes the active year to the next one.
    - */
    -goog.ui.DatePicker.prototype.nextYear = function() {
    -  this.activeMonth_.add(new goog.date.Interval(goog.date.Interval.YEARS, 1));
    -  this.updateCalendarGrid_();
    -  this.fireChangeActiveMonthEvent_();
    -};
    -
    -
    -/**
    - * Selects the current date.
    - */
    -goog.ui.DatePicker.prototype.selectToday = function() {
    -  this.setDate(new goog.date.Date());
    -};
    -
    -
    -/**
    - * Clears the selection.
    - */
    -goog.ui.DatePicker.prototype.selectNone = function() {
    -  if (this.allowNone_) {
    -    this.setDate(null);
    -  }
    -};
    -
    -
    -/**
    - * @return {!goog.date.Date} The active month displayed.
    - */
    -goog.ui.DatePicker.prototype.getActiveMonth = function() {
    -  return this.activeMonth_.clone();
    -};
    -
    -
    -/**
    - * @return {goog.date.Date} The selected date or null if nothing is selected.
    - */
    -goog.ui.DatePicker.prototype.getDate = function() {
    -  return this.date_ && this.date_.clone();
    -};
    -
    -
    -/**
    - * @param {number} row The row in the grid.
    - * @param {number} col The column in the grid.
    - * @return {goog.date.Date} The date in the grid or null if there is none.
    - */
    -goog.ui.DatePicker.prototype.getDateAt = function(row, col) {
    -  return this.grid_[row] ?
    -      this.grid_[row][col] ? this.grid_[row][col].clone() : null : null;
    -};
    -
    -
    -/**
    - * Returns a date element given a row and column. In elTable_, the elements that
    - * represent dates are 1 indexed because of other elements such as headers.
    - * This corrects for the offset and makes the API 0 indexed.
    - *
    - * @param {number} row The row in the element table.
    - * @param {number} col The column in the element table.
    - * @return {Element} The element in the grid or null if there is none.
    - * @protected
    - */
    -goog.ui.DatePicker.prototype.getDateElementAt = function(row, col) {
    -  if (row < 0 || col < 0) {
    -    return null;
    -  }
    -  var adjustedRow = row + 1;
    -  return this.elTable_[adjustedRow] ?
    -      this.elTable_[adjustedRow][col + 1] || null : null;
    -};
    -
    -
    -/**
    - * Sets the selected date.
    - *
    - * @param {goog.date.Date|Date} date Date to select or null to select nothing.
    - */
    -goog.ui.DatePicker.prototype.setDate = function(date) {
    -  // Check if the month has been changed.
    -  var sameMonth = date == this.date_ || date && this.date_ &&
    -      date.getFullYear() == this.date_.getFullYear() &&
    -      date.getMonth() == this.date_.getMonth();
    -
    -  // Check if the date has been changed.
    -  var sameDate = date == this.date_ || sameMonth &&
    -      date.getDate() == this.date_.getDate();
    -
    -  // Set current date to clone of supplied goog.date.Date or Date.
    -  this.date_ = date && new goog.date.Date(date);
    -
    -  // Set current month
    -  if (date) {
    -    this.activeMonth_.set(this.date_);
    -    this.activeMonth_.setDate(1);
    -  }
    -
    -  // Update calendar grid even if the date has not changed as even if today is
    -  // selected another month can be displayed.
    -  this.updateCalendarGrid_();
    -
    -  // TODO(eae): Standardize selection and change events with other components.
    -  // Fire select event.
    -  var selectEvent = new goog.ui.DatePickerEvent(
    -      goog.ui.DatePicker.Events.SELECT, this, this.date_);
    -  this.dispatchEvent(selectEvent);
    -
    -  // Fire change event.
    -  if (!sameDate) {
    -    var changeEvent = new goog.ui.DatePickerEvent(
    -        goog.ui.DatePicker.Events.CHANGE, this, this.date_);
    -    this.dispatchEvent(changeEvent);
    -  }
    -
    -  // Fire change active month event.
    -  if (!sameMonth) {
    -    this.fireChangeActiveMonthEvent_();
    -  }
    -};
    -
    -
    -/**
    - * Updates the navigation row (navigating months and maybe years) in the navRow_
    - * element of a created picker.
    - * @private
    - */
    -goog.ui.DatePicker.prototype.updateNavigationRow_ = function() {
    -  if (!this.elNavRow_) {
    -    return;
    -  }
    -  var row = this.elNavRow_;
    -
    -  // Clear the navigation row.
    -  while (row.firstChild) {
    -    row.removeChild(row.firstChild);
    -  }
    -
    -  var fullDateFormat = this.symbols_.DATEFORMATS[
    -      goog.i18n.DateTimeFormat.Format.FULL_DATE].toLowerCase();
    -  this.renderer_.renderNavigationRow(
    -      row, this.simpleNavigation_, this.showWeekNum_, fullDateFormat);
    -
    -  if (this.simpleNavigation_) {
    -    this.addPreventDefaultClickHandler_(row,
    -        goog.getCssName(this.getBaseCssClass(), 'previousMonth'),
    -        this.previousMonth);
    -    this.addPreventDefaultClickHandler_(row,
    -        goog.getCssName(this.getBaseCssClass(), 'nextMonth'),
    -        this.nextMonth);
    -
    -    this.elMonthYear_ = goog.dom.getElementByClass(
    -        goog.getCssName(this.getBaseCssClass(), 'monthyear'),
    -        row);
    -  } else {
    -    this.addPreventDefaultClickHandler_(row,
    -        goog.getCssName(this.getBaseCssClass(), 'previousMonth'),
    -        this.previousMonth);
    -    this.addPreventDefaultClickHandler_(row,
    -        goog.getCssName(this.getBaseCssClass(), 'nextMonth'),
    -        this.nextMonth);
    -    this.addPreventDefaultClickHandler_(row,
    -        goog.getCssName(this.getBaseCssClass(), 'month'),
    -        this.showMonthMenu_);
    -
    -    this.addPreventDefaultClickHandler_(row,
    -        goog.getCssName(this.getBaseCssClass(), 'previousYear'),
    -        this.previousYear);
    -    this.addPreventDefaultClickHandler_(row,
    -        goog.getCssName(this.getBaseCssClass(), 'nextYear'),
    -        this.nextYear);
    -    this.addPreventDefaultClickHandler_(row,
    -        goog.getCssName(this.getBaseCssClass(), 'year'),
    -        this.showYearMenu_);
    -
    -    this.elMonth_ = goog.dom.getElementByClass(
    -        goog.getCssName(this.getBaseCssClass(), 'month'), row);
    -    this.elYear_ = goog.dom.getDomHelper().getElementByClass(
    -        goog.getCssName(this.getBaseCssClass(), 'year'), row);
    -  }
    -};
    -
    -
    -/**
    - * Setup click handler with prevent default.
    - *
    - * @param {!Element} parentElement The parent element of the element. This is
    - *     needed because the element in question might not be in the dom yet.
    - * @param {string} cssName The CSS class name of the element to attach a click
    - *     handler.
    - * @param {Function} handlerFunction The click handler function.
    - * @private
    - */
    -goog.ui.DatePicker.prototype.addPreventDefaultClickHandler_ =
    -    function(parentElement, cssName, handlerFunction) {
    -  var element = goog.dom.getElementByClass(cssName, parentElement);
    -  this.getHandler().listen(element,
    -      goog.events.EventType.CLICK,
    -      function(e) {
    -        e.preventDefault();
    -        handlerFunction.call(this, e);
    -      });
    -};
    -
    -
    -/**
    - * Updates the footer row (with select buttons) in the footRow_ element of a
    - * created picker.
    - * @private
    - */
    -goog.ui.DatePicker.prototype.updateFooterRow_ = function() {
    -  if (!this.elFootRow_) {
    -    return;
    -  }
    -
    -  var row = this.elFootRow_;
    -
    -  // Clear the footer row.
    -  goog.dom.removeChildren(row);
    -
    -  this.renderer_.renderFooterRow(row, this.showWeekNum_);
    -
    -  this.addPreventDefaultClickHandler_(row,
    -      goog.getCssName(this.getBaseCssClass(), 'today-btn'),
    -      this.selectToday);
    -  this.addPreventDefaultClickHandler_(row,
    -      goog.getCssName(this.getBaseCssClass(), 'none-btn'),
    -      this.selectNone);
    -
    -  this.elToday_ = goog.dom.getElementByClass(
    -      goog.getCssName(this.getBaseCssClass(), 'today-btn'), row);
    -  this.elNone_ = goog.dom.getElementByClass(
    -      goog.getCssName(this.getBaseCssClass(), 'none-btn'), row);
    -
    -  this.updateTodayAndNone_();
    -};
    -
    -
    -/** @override */
    -goog.ui.DatePicker.prototype.decorateInternal = function(el) {
    -  goog.ui.DatePicker.superClass_.decorateInternal.call(this, el);
    -  goog.asserts.assert(el);
    -  goog.dom.classlist.add(el, this.getBaseCssClass());
    -
    -  var table = this.dom_.createElement('table');
    -  var thead = this.dom_.createElement('thead');
    -  var tbody = this.dom_.createElement('tbody');
    -  var tfoot = this.dom_.createElement('tfoot');
    -
    -  goog.a11y.aria.setRole(tbody, 'grid');
    -  tbody.tabIndex = '0';
    -
    -  // As per comment in colorpicker: table.tBodies and table.tFoot should not be
    -  // used because of a bug in Safari, hence using an instance variable
    -  this.tableBody_ = tbody;
    -  this.tableFoot_ = tfoot;
    -
    -  var row = this.dom_.createElement('tr');
    -  row.className = goog.getCssName(this.getBaseCssClass(), 'head');
    -  this.elNavRow_ = row;
    -  this.updateNavigationRow_();
    -
    -  thead.appendChild(row);
    -
    -  var cell;
    -  this.elTable_ = [];
    -  for (var i = 0; i < 7; i++) {
    -    row = this.dom_.createElement('tr');
    -    this.elTable_[i] = [];
    -    for (var j = 0; j < 8; j++) {
    -      cell = this.dom_.createElement(j == 0 || i == 0 ? 'th' : 'td');
    -      if ((j == 0 || i == 0) && j != i) {
    -        cell.className = (j == 0) ?
    -            goog.getCssName(this.getBaseCssClass(), 'week') :
    -            goog.getCssName(this.getBaseCssClass(), 'wday');
    -        goog.a11y.aria.setRole(cell, j == 0 ? 'rowheader' : 'columnheader');
    -      }
    -      row.appendChild(cell);
    -      this.elTable_[i][j] = cell;
    -    }
    -    tbody.appendChild(row);
    -  }
    -
    -  row = this.dom_.createElement('tr');
    -  row.className = goog.getCssName(this.getBaseCssClass(), 'foot');
    -  this.elFootRow_ = row;
    -  this.updateFooterRow_();
    -  tfoot.appendChild(row);
    -
    -
    -  table.cellSpacing = '0';
    -  table.cellPadding = '0';
    -  table.appendChild(thead);
    -  table.appendChild(tbody);
    -  table.appendChild(tfoot);
    -  el.appendChild(table);
    -
    -  this.redrawWeekdays_();
    -  this.updateCalendarGrid_();
    -
    -  el.tabIndex = 0;
    -};
    -
    -
    -/** @override */
    -goog.ui.DatePicker.prototype.createDom = function() {
    -  goog.ui.DatePicker.superClass_.createDom.call(this);
    -  this.decorateInternal(this.getElement());
    -};
    -
    -
    -/** @override */
    -goog.ui.DatePicker.prototype.enterDocument = function() {
    -  goog.ui.DatePicker.superClass_.enterDocument.call(this);
    -
    -  var eh = this.getHandler();
    -  eh.listen(this.tableBody_, goog.events.EventType.CLICK,
    -      this.handleGridClick_);
    -  eh.listen(this.getKeyHandlerForElement_(this.getElement()),
    -      goog.events.KeyHandler.EventType.KEY, this.handleGridKeyPress_);
    -};
    -
    -
    -/** @override */
    -goog.ui.DatePicker.prototype.exitDocument = function() {
    -  goog.ui.DatePicker.superClass_.exitDocument.call(this);
    -  this.destroyMenu_();
    -  for (var uid in this.keyHandlers_) {
    -    this.keyHandlers_[uid].dispose();
    -  }
    -  this.keyHandlers_ = {};
    -};
    -
    -
    -/**
    - * @deprecated Use decorate instead.
    - */
    -goog.ui.DatePicker.prototype.create =
    -    goog.ui.DatePicker.prototype.decorate;
    -
    -
    -/** @override */
    -goog.ui.DatePicker.prototype.disposeInternal = function() {
    -  goog.ui.DatePicker.superClass_.disposeInternal.call(this);
    -
    -  this.elTable_ = null;
    -  this.tableBody_ = null;
    -  this.tableFoot_ = null;
    -  this.elNavRow_ = null;
    -  this.elFootRow_ = null;
    -  this.elMonth_ = null;
    -  this.elMonthYear_ = null;
    -  this.elYear_ = null;
    -  this.elToday_ = null;
    -  this.elNone_ = null;
    -};
    -
    -
    -/**
    - * Click handler for date grid.
    - *
    - * @param {goog.events.BrowserEvent} event Click event.
    - * @private
    - */
    -goog.ui.DatePicker.prototype.handleGridClick_ = function(event) {
    -  if (event.target.tagName == 'TD') {
    -    // colIndex/rowIndex is broken in Safari, find position by looping
    -    var el, x = -2, y = -2; // first col/row is for weekday/weeknum
    -    for (el = event.target; el; el = el.previousSibling, x++) {}
    -    for (el = event.target.parentNode; el; el = el.previousSibling, y++) {}
    -    var obj = this.grid_[y][x];
    -    if (this.isUserSelectableDate_(obj)) {
    -      this.setDate(obj.clone());
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Keypress handler for date grid.
    - *
    - * @param {goog.events.BrowserEvent} event Keypress event.
    - * @private
    - */
    -goog.ui.DatePicker.prototype.handleGridKeyPress_ = function(event) {
    -  var months, days;
    -  switch (event.keyCode) {
    -    case 33: // Page up
    -      event.preventDefault();
    -      months = -1;
    -      break;
    -    case 34: // Page down
    -      event.preventDefault();
    -      months = 1;
    -      break;
    -    case 37: // Left
    -      event.preventDefault();
    -      days = -1;
    -      break;
    -    case 39: // Right
    -      event.preventDefault();
    -      days = 1;
    -      break;
    -    case 38: // Down
    -      event.preventDefault();
    -      days = -7;
    -      break;
    -    case 40: // Up
    -      event.preventDefault();
    -      days = 7;
    -      break;
    -    case 36: // Home
    -      event.preventDefault();
    -      this.selectToday();
    -    case 46: // Delete
    -      event.preventDefault();
    -      this.selectNone();
    -    default:
    -      return;
    -  }
    -  var date;
    -  if (this.date_) {
    -    date = this.date_.clone();
    -    date.add(new goog.date.Interval(0, months, days));
    -  } else {
    -    date = this.activeMonth_.clone();
    -    date.setDate(1);
    -  }
    -  if (this.isUserSelectableDate_(date)) {
    -    this.setDate(date);
    -  }
    -};
    -
    -
    -/**
    - * Click handler for month button. Opens month selection menu.
    - *
    - * @param {goog.events.BrowserEvent} event Click event.
    - * @private
    - */
    -goog.ui.DatePicker.prototype.showMonthMenu_ = function(event) {
    -  event.stopPropagation();
    -
    -  var list = [];
    -  for (var i = 0; i < 12; i++) {
    -    list.push(this.symbols_.STANDALONEMONTHS[i]);
    -  }
    -  this.createMenu_(this.elMonth_, list, this.handleMonthMenuClick_,
    -      this.symbols_.STANDALONEMONTHS[this.activeMonth_.getMonth()]);
    -};
    -
    -
    -/**
    - * Click handler for year button. Opens year selection menu.
    - *
    - * @param {goog.events.BrowserEvent} event Click event.
    - * @private
    - */
    -goog.ui.DatePicker.prototype.showYearMenu_ = function(event) {
    -  event.stopPropagation();
    -
    -  var list = [];
    -  var year = this.activeMonth_.getFullYear();
    -  var loopDate = this.activeMonth_.clone();
    -  for (var i = -goog.ui.DatePicker.YEAR_MENU_RANGE_;
    -      i <= goog.ui.DatePicker.YEAR_MENU_RANGE_; i++) {
    -    loopDate.setFullYear(year + i);
    -    list.push(this.i18nDateFormatterYear_.format(loopDate));
    -  }
    -  this.createMenu_(this.elYear_, list, this.handleYearMenuClick_,
    -      this.i18nDateFormatterYear_.format(this.activeMonth_));
    -};
    -
    -
    -/**
    - * Call back function for month menu.
    - *
    - * @param {Element} target Selected item.
    - * @private
    - */
    -goog.ui.DatePicker.prototype.handleMonthMenuClick_ = function(target) {
    -  var itemIndex = Number(target.getAttribute('itemIndex'));
    -  this.activeMonth_.setMonth(itemIndex);
    -  this.updateCalendarGrid_();
    -
    -  if (this.elMonth_.focus) {
    -    this.elMonth_.focus();
    -  }
    -};
    -
    -
    -/**
    - * Call back function for year menu.
    - *
    - * @param {Element} target Selected item.
    - * @private
    - */
    -goog.ui.DatePicker.prototype.handleYearMenuClick_ = function(target) {
    -  if (target.firstChild.nodeType == goog.dom.NodeType.TEXT) {
    -    // We use the same technique used for months to get the position of the
    -    // item in the menu, as the year is not necessarily numeric.
    -    var itemIndex = Number(target.getAttribute('itemIndex'));
    -    var year = this.activeMonth_.getFullYear();
    -    this.activeMonth_.setFullYear(year + itemIndex -
    -        goog.ui.DatePicker.YEAR_MENU_RANGE_);
    -    this.updateCalendarGrid_();
    -  }
    -
    -  this.elYear_.focus();
    -};
    -
    -
    -/**
    - * Support function for menu creation.
    - *
    - * @param {Element} srcEl Button to create menu for.
    - * @param {Array<string>} items List of items to populate menu with.
    - * @param {function(Element)} method Call back method.
    - * @param {string} selected Item to mark as selected in menu.
    - * @private
    - */
    -goog.ui.DatePicker.prototype.createMenu_ = function(srcEl, items, method,
    -                                                    selected) {
    -  this.destroyMenu_();
    -
    -  var el = this.dom_.createElement('div');
    -  el.className = goog.getCssName(this.getBaseCssClass(), 'menu');
    -
    -  this.menuSelected_ = null;
    -
    -  var ul = this.dom_.createElement('ul');
    -  for (var i = 0; i < items.length; i++) {
    -    var li = this.dom_.createDom('li', null, items[i]);
    -    li.setAttribute('itemIndex', i);
    -    if (items[i] == selected) {
    -      this.menuSelected_ = li;
    -    }
    -    ul.appendChild(li);
    -  }
    -  el.appendChild(ul);
    -  el.style.left = srcEl.offsetLeft + srcEl.parentNode.offsetLeft + 'px';
    -  el.style.top = srcEl.offsetTop + 'px';
    -  el.style.width = srcEl.clientWidth + 'px';
    -  this.elMonth_.parentNode.appendChild(el);
    -
    -  this.menu_ = el;
    -  if (!this.menuSelected_) {
    -    this.menuSelected_ = /** @type {Element} */ (ul.firstChild);
    -  }
    -  this.menuSelected_.className =
    -      goog.getCssName(this.getBaseCssClass(), 'menu-selected');
    -  this.menuCallback_ = method;
    -
    -  var eh = this.getHandler();
    -  eh.listen(this.menu_, goog.events.EventType.CLICK, this.handleMenuClick_);
    -  eh.listen(this.getKeyHandlerForElement_(this.menu_),
    -      goog.events.KeyHandler.EventType.KEY, this.handleMenuKeyPress_);
    -  eh.listen(this.dom_.getDocument(), goog.events.EventType.CLICK,
    -      this.destroyMenu_);
    -  el.tabIndex = 0;
    -  el.focus();
    -};
    -
    -
    -/**
    - * Click handler for menu.
    - *
    - * @param {goog.events.BrowserEvent} event Click event.
    - * @private
    - */
    -goog.ui.DatePicker.prototype.handleMenuClick_ = function(event) {
    -  event.stopPropagation();
    -
    -  this.destroyMenu_();
    -  if (this.menuCallback_) {
    -    this.menuCallback_(/** @type {Element} */ (event.target));
    -  }
    -};
    -
    -
    -/**
    - * Keypress handler for menu.
    - *
    - * @param {goog.events.BrowserEvent} event Keypress event.
    - * @private
    - */
    -goog.ui.DatePicker.prototype.handleMenuKeyPress_ = function(event) {
    -  // Prevent the grid keypress handler from catching the keypress event.
    -  event.stopPropagation();
    -
    -  var el;
    -  var menuSelected = this.menuSelected_;
    -  switch (event.keyCode) {
    -    case 35: // End
    -      event.preventDefault();
    -      el = menuSelected.parentNode.lastChild;
    -      break;
    -    case 36: // Home
    -      event.preventDefault();
    -      el = menuSelected.parentNode.firstChild;
    -      break;
    -    case 38: // Up
    -      event.preventDefault();
    -      el = menuSelected.previousSibling;
    -      break;
    -    case 40: // Down
    -      event.preventDefault();
    -      el = menuSelected.nextSibling;
    -      break;
    -    case 13: // Enter
    -    case 9: // Tab
    -    case 0: // Space
    -      event.preventDefault();
    -      this.destroyMenu_();
    -      this.menuCallback_(menuSelected);
    -      break;
    -  }
    -  if (el && el != menuSelected) {
    -    menuSelected.className = '';
    -    el.className = goog.getCssName(this.getBaseCssClass(), 'menu-selected');
    -    this.menuSelected_ = /** @type {!Element} */ (el);
    -  }
    -};
    -
    -
    -/**
    - * Support function for menu destruction.
    - * @private
    - */
    -goog.ui.DatePicker.prototype.destroyMenu_ = function() {
    -  if (this.menu_) {
    -    var eh = this.getHandler();
    -    eh.unlisten(this.menu_, goog.events.EventType.CLICK, this.handleMenuClick_);
    -    eh.unlisten(this.getKeyHandlerForElement_(this.menu_),
    -        goog.events.KeyHandler.EventType.KEY, this.handleMenuKeyPress_);
    -    eh.unlisten(this.dom_.getDocument(), goog.events.EventType.CLICK,
    -        this.destroyMenu_);
    -    goog.dom.removeNode(this.menu_);
    -    delete this.menu_;
    -  }
    -};
    -
    -
    -/**
    - * Determines the dates/weekdays for the current month and builds an in memory
    - * representation of the calendar.
    - *
    - * @private
    - */
    -goog.ui.DatePicker.prototype.updateCalendarGrid_ = function() {
    -  if (!this.getElement()) {
    -    return;
    -  }
    -
    -  var date = this.activeMonth_.clone();
    -  date.setDate(1);
    -
    -  // Show year name of select month
    -  if (this.elMonthYear_) {
    -    goog.dom.setTextContent(this.elMonthYear_,
    -        this.i18nDateFormatterMonthYear_.format(date));
    -  }
    -  if (this.elMonth_) {
    -    goog.dom.setTextContent(this.elMonth_,
    -        this.symbols_.STANDALONEMONTHS[date.getMonth()]);
    -  }
    -  if (this.elYear_) {
    -    goog.dom.setTextContent(this.elYear_,
    -        this.i18nDateFormatterYear_.format(date));
    -  }
    -
    -  var wday = date.getWeekday();
    -  var days = date.getNumberOfDaysInMonth();
    -
    -  // Determine how many days to show for previous month
    -  date.add(new goog.date.Interval(goog.date.Interval.MONTHS, -1));
    -  date.setDate(date.getNumberOfDaysInMonth() - (wday - 1));
    -
    -  if (this.showFixedNumWeeks_ && !this.extraWeekAtEnd_ && days + wday < 33) {
    -    date.add(new goog.date.Interval(goog.date.Interval.DAYS, -7));
    -  }
    -
    -  // Create weekday/day grid
    -  var dayInterval = new goog.date.Interval(goog.date.Interval.DAYS, 1);
    -  this.grid_ = [];
    -  for (var y = 0; y < 6; y++) { // Weeks
    -    this.grid_[y] = [];
    -    for (var x = 0; x < 7; x++) { // Weekdays
    -      this.grid_[y][x] = date.clone();
    -      date.add(dayInterval);
    -    }
    -  }
    -
    -  this.redrawCalendarGrid_();
    -};
    -
    -
    -/**
    - * Draws calendar view from in memory representation and applies class names
    - * depending on the selection, weekday and whatever the day belongs to the
    - * active month or not.
    - * @private
    - */
    -goog.ui.DatePicker.prototype.redrawCalendarGrid_ = function() {
    -  if (!this.getElement()) {
    -    return;
    -  }
    -
    -  var month = this.activeMonth_.getMonth();
    -  var today = new goog.date.Date();
    -  var todayYear = today.getFullYear();
    -  var todayMonth = today.getMonth();
    -  var todayDate = today.getDate();
    -
    -  // Draw calendar week by week, a worst case month has six weeks.
    -  for (var y = 0; y < 6; y++) {
    -
    -    // Draw week number, if enabled
    -    if (this.showWeekNum_) {
    -      goog.dom.setTextContent(this.elTable_[y + 1][0],
    -          this.i18nDateFormatterWeek_.format(this.grid_[y][0]));
    -      goog.dom.classlist.set(this.elTable_[y + 1][0],
    -          goog.getCssName(this.getBaseCssClass(), 'week'));
    -    } else {
    -      goog.dom.setTextContent(this.elTable_[y + 1][0], '');
    -      goog.dom.classlist.set(this.elTable_[y + 1][0], '');
    -    }
    -
    -    for (var x = 0; x < 7; x++) {
    -      var o = this.grid_[y][x];
    -      var el = this.elTable_[y + 1][x + 1];
    -
    -      // Assign a unique element id (required for setting the active descendant
    -      // ARIA role) unless already set.
    -      if (!el.id) {
    -        el.id = this.cellIdGenerator_.getNextUniqueId();
    -      }
    -      goog.asserts.assert(el, 'The table DOM element cannot be null.');
    -      goog.a11y.aria.setRole(el, 'gridcell');
    -      var classes = [goog.getCssName(this.getBaseCssClass(), 'date')];
    -      if (!this.isUserSelectableDate_(o)) {
    -        classes.push(goog.getCssName(this.getBaseCssClass(),
    -            'unavailable-date'));
    -      }
    -      if (this.showOtherMonths_ || o.getMonth() == month) {
    -        // Date belongs to previous or next month
    -        if (o.getMonth() != month) {
    -          classes.push(goog.getCssName(this.getBaseCssClass(), 'other-month'));
    -        }
    -
    -        // Apply styles set by setWeekdayClass
    -        var wday = (x + this.activeMonth_.getFirstDayOfWeek() + 7) % 7;
    -        if (this.wdayStyles_[wday]) {
    -          classes.push(this.wdayStyles_[wday]);
    -        }
    -
    -        // Current date
    -        if (o.getDate() == todayDate && o.getMonth() == todayMonth &&
    -            o.getFullYear() == todayYear) {
    -          classes.push(goog.getCssName(this.getBaseCssClass(), 'today'));
    -        }
    -
    -        // Selected date
    -        if (this.date_ && o.getDate() == this.date_.getDate() &&
    -            o.getMonth() == this.date_.getMonth() &&
    -            o.getFullYear() == this.date_.getFullYear()) {
    -          classes.push(goog.getCssName(this.getBaseCssClass(), 'selected'));
    -          goog.asserts.assert(this.tableBody_,
    -              'The table body DOM element cannot be null');
    -          goog.a11y.aria.setState(this.tableBody_, 'activedescendant', el.id);
    -        }
    -
    -        // Custom decorator
    -        if (this.decoratorFunction_) {
    -          var customClass = this.decoratorFunction_(o);
    -          if (customClass) {
    -            classes.push(customClass);
    -          }
    -        }
    -
    -        // Set cell text to the date and apply classes.
    -        var formatedDate = this.longDateFormat_ ?
    -            this.i18nDateFormatterDay2_.format(o) :
    -            this.i18nDateFormatterDay_.format(o);
    -        goog.dom.setTextContent(el, formatedDate);
    -        // Date belongs to previous or next month and showOtherMonths is false,
    -        // clear text and classes.
    -      } else {
    -        goog.dom.setTextContent(el, '');
    -      }
    -      goog.dom.classlist.set(el, classes.join(' '));
    -    }
    -
    -    // Hide the either the last one or last two weeks if they contain no days
    -    // from the active month and the showFixedNumWeeks is false. The first four
    -    // weeks are always shown as no month has less than 28 days).
    -    if (y >= 4) {
    -      var parentEl = /** @type {Element} */ (
    -          this.elTable_[y + 1][0].parentElement ||
    -          this.elTable_[y + 1][0].parentNode);
    -      goog.style.setElementShown(parentEl,
    -          this.grid_[y][0].getMonth() == month || this.showFixedNumWeeks_);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Fires the CHANGE_ACTIVE_MONTH event.
    - * @private
    - */
    -goog.ui.DatePicker.prototype.fireChangeActiveMonthEvent_ = function() {
    -  var changeMonthEvent = new goog.ui.DatePickerEvent(
    -      goog.ui.DatePicker.Events.CHANGE_ACTIVE_MONTH,
    -      this,
    -      this.getActiveMonth());
    -  this.dispatchEvent(changeMonthEvent);
    -};
    -
    -
    -/**
    - * Draw weekday names, if enabled. Start with whatever day has been set as the
    - * first day of week.
    - * @private
    - */
    -goog.ui.DatePicker.prototype.redrawWeekdays_ = function() {
    -  if (!this.getElement()) {
    -    return;
    -  }
    -  if (this.showWeekdays_) {
    -    for (var x = 0; x < 7; x++) {
    -      var el = this.elTable_[0][x + 1];
    -      var wday = (x + this.activeMonth_.getFirstDayOfWeek() + 7) % 7;
    -      goog.dom.setTextContent(el, this.wdayNames_[(wday + 1) % 7]);
    -    }
    -  }
    -  var parentEl =  /** @type {Element} */ (this.elTable_[0][0].parentElement ||
    -      this.elTable_[0][0].parentNode);
    -  goog.style.setElementShown(parentEl, this.showWeekdays_);
    -};
    -
    -
    -/**
    - * Returns the key handler for an element and caches it so that it can be
    - * retrieved at a later point.
    - * @param {Element} el The element to get the key handler for.
    - * @return {goog.events.KeyHandler} The key handler for the element.
    - * @private
    - */
    -goog.ui.DatePicker.prototype.getKeyHandlerForElement_ = function(el) {
    -  var uid = goog.getUid(el);
    -  if (!(uid in this.keyHandlers_)) {
    -    this.keyHandlers_[uid] = new goog.events.KeyHandler(el);
    -  }
    -  return this.keyHandlers_[uid];
    -};
    -
    -
    -
    -/**
    - * Object representing a date picker event.
    - *
    - * @param {string} type Event type.
    - * @param {goog.ui.DatePicker} target Date picker initiating event.
    - * @param {goog.date.Date} date Selected date.
    - * @constructor
    - * @extends {goog.events.Event}
    - * @final
    - */
    -goog.ui.DatePickerEvent = function(type, target, date) {
    -  goog.events.Event.call(this, type, target);
    -
    -  /**
    -   * The selected date
    -   * @type {goog.date.Date}
    -   */
    -  this.date = date;
    -};
    -goog.inherits(goog.ui.DatePickerEvent, goog.events.Event);
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/datepicker_test.html b/src/database/third_party/closure-library/closure/goog/ui/datepicker_test.html
    deleted file mode 100644
    index 36eb7f619d2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/datepicker_test.html
    +++ /dev/null
    @@ -1,26 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.DatePicker
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.DatePickerTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="sandbox">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/datepicker_test.js b/src/database/third_party/closure-library/closure/goog/ui/datepicker_test.js
    deleted file mode 100644
    index 36523032d6a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/datepicker_test.js
    +++ /dev/null
    @@ -1,362 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.DatePickerTest');
    -goog.setTestOnly('goog.ui.DatePickerTest');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.date.Date');
    -goog.require('goog.date.DateRange');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events');
    -goog.require('goog.i18n.DateTimeSymbols');
    -goog.require('goog.i18n.DateTimeSymbols_en_US');
    -goog.require('goog.i18n.DateTimeSymbols_zh_HK');
    -goog.require('goog.style');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.DatePicker');
    -
    -var picker;
    -var $$ = goog.dom.getElementsByTagNameAndClass;
    -var sandbox;
    -
    -function setUpPage() {
    -  sandbox = goog.dom.getElement('sandbox');
    -}
    -
    -function tearDown() {
    -  picker.dispose();
    -  goog.dom.removeChildren(sandbox);
    -}
    -
    -function testIsMonthOnLeft() {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_en_US;
    -  picker = new goog.ui.DatePicker();
    -  picker.create(sandbox);
    -  var head = $$('tr', 'goog-date-picker-head')[0];
    -  var month = $$('button', 'goog-date-picker-month',
    -      head.firstChild)[0];
    -  assertSameElements(
    -      'Button element must have expected class names',
    -      ['goog-date-picker-btn', 'goog-date-picker-month'],
    -      goog.dom.classlist.get(month)
    -  );
    -}
    -
    -function testIsYearOnLeft() {
    -  goog.i18n.DateTimeSymbols = goog.i18n.DateTimeSymbols_zh_HK;
    -  picker = new goog.ui.DatePicker();
    -  picker.create(sandbox);
    -  var head = $$('tr', 'goog-date-picker-head')[0];
    -  var year = $$('button', 'goog-date-picker-year',
    -      head.firstChild)[0];
    -  assertSameElements(
    -      'Button element must have expected class names',
    -      ['goog-date-picker-btn', 'goog-date-picker-year'],
    -      goog.dom.classlist.get(year)
    -  );
    -}
    -
    -function testHidingOfTableFoot0() {
    -  picker = new goog.ui.DatePicker();
    -  picker.setAllowNone(false);
    -  picker.setShowToday(false);
    -  picker.create(sandbox);
    -  var tFoot = $$('tfoot')[0];
    -  assertFalse(goog.style.isElementShown(tFoot));
    -}
    -
    -function testHidingOfTableFoot1() {
    -  picker = new goog.ui.DatePicker();
    -  picker.setAllowNone(false);
    -  picker.setShowToday(true);
    -  picker.create(sandbox);
    -  var tFoot = $$('tfoot')[0];
    -  assertTrue(goog.style.isElementShown(tFoot));
    -}
    -
    -function testHidingOfTableFoot2() {
    -  picker = new goog.ui.DatePicker();
    -  picker.setAllowNone(true);
    -  picker.setShowToday(false);
    -  picker.create(sandbox);
    -  var tFoot = $$('tfoot')[0];
    -  assertTrue(goog.style.isElementShown(tFoot));
    -}
    -
    -function testHidingOfTableFoot3() {
    -  picker = new goog.ui.DatePicker();
    -  picker.setAllowNone(true);
    -  picker.setShowToday(true);
    -  picker.create(sandbox);
    -  var tFoot = $$('tfoot')[0];
    -  assertTrue(goog.style.isElementShown(tFoot));
    -}
    -
    -function testHidingOfTableFootAfterCreate0() {
    -  picker = new goog.ui.DatePicker();
    -  picker.create(sandbox);
    -  picker.setAllowNone(false);
    -  picker.setShowToday(false);
    -  var tFoot = $$('tfoot')[0];
    -  assertFalse(goog.style.isElementShown(tFoot));
    -}
    -
    -function testHidingOfTableFootAfterCreate1() {
    -  picker = new goog.ui.DatePicker();
    -  picker.create(sandbox);
    -  picker.setAllowNone(false);
    -  picker.setShowToday(true);
    -  var tFoot = $$('tfoot')[0];
    -  assertTrue(goog.style.isElementShown(tFoot));
    -}
    -
    -function testHidingOfTableFootAfterCreate2() {
    -  picker = new goog.ui.DatePicker();
    -  picker.create(sandbox);
    -  picker.setAllowNone(true);
    -  picker.setShowToday(false);
    -  var tFoot = $$('tfoot')[0];
    -  assertTrue(goog.style.isElementShown(tFoot));
    -}
    -
    -function testHidingOfTableFootAfterCreate3() {
    -  picker = new goog.ui.DatePicker();
    -  picker.create(sandbox);
    -  picker.setAllowNone(true);
    -  picker.setShowToday(true);
    -  var tFoot = $$('tfoot')[0];
    -  assertTrue(goog.style.isElementShown(tFoot));
    -}
    -
    -function testLongDateFormat() {
    -  picker = new goog.ui.DatePicker();
    -  picker.create(sandbox);
    -  picker.setLongDateFormat(true);
    -  var dates = $$('td', 'goog-date-picker-date');
    -  for (var i = 0; i < dates.length; i++) {
    -    assertEquals(2, goog.dom.getTextContent(dates[i]).length);
    -  }
    -}
    -
    -function testGetActiveMonth() {
    -  picker = new goog.ui.DatePicker(new Date(2000, 5, 5));
    -  var month = picker.getActiveMonth();
    -  assertObjectEquals(new goog.date.Date(2000, 5, 1), month);
    -
    -  month.setMonth(10);
    -  assertObjectEquals('modifying the returned object is safe',
    -      new goog.date.Date(2000, 5, 1), picker.getActiveMonth());
    -}
    -
    -function testGetDate() {
    -  picker = new goog.ui.DatePicker(new Date(2000, 0, 1));
    -  var date = picker.getDate();
    -  assertObjectEquals(new goog.date.Date(2000, 0, 1), date);
    -
    -  date.setMonth(1);
    -  assertObjectEquals('modifying the returned date is safe',
    -      new goog.date.Date(2000, 0, 1), picker.getDate());
    -
    -  picker.setDate(null);
    -  assertNull('no date is selected', picker.getDate());
    -}
    -
    -function testGetDateAt() {
    -  picker = new goog.ui.DatePicker();
    -  picker.create(sandbox);
    -  picker.setDate(new Date(2000, 5, 5));
    -  var date = picker.getDateAt(0, 0);
    -  assertTrue(date.equals(picker.grid_[0][0]));
    -
    -  date.setMonth(1);
    -  assertFalse(date.equals(picker.grid_[0][0]));
    -}
    -
    -function testGetDateAt_NotInGrid() {
    -  picker = new goog.ui.DatePicker();
    -  picker.create(sandbox);
    -  picker.setDate(new Date(2000, 5, 5));
    -  var date = picker.getDateAt(-1, 0);
    -  assertNull(date);
    -
    -  date = picker.getDateAt(0, -1);
    -  assertNull(date);
    -}
    -
    -function testGetDateElementAt() {
    -  picker = new goog.ui.DatePicker();
    -  picker.create(sandbox);
    -  picker.setDate(new Date(2000, 5, 5));
    -  var element = picker.getDateElementAt(0, 0);
    -  assertEquals('td', element.tagName.toLowerCase());
    -  assertObjectEquals(element, picker.elTable_[1][1]);
    -}
    -
    -function testGetDateElementAt_NotInTable() {
    -  picker = new goog.ui.DatePicker();
    -  picker.create(sandbox);
    -  picker.setDate(new Date(2000, 5, 5));
    -  var element = picker.getDateElementAt(-1, 0);
    -  assertNull(element);
    -
    -  element = picker.getDateElementAt(0, -1);
    -  assertNull(element);
    -
    -  element = picker.getDateElementAt(picker.elTable_.length - 1, 0);
    -  assertNull(element);
    -
    -  element = picker.getDateElementAt(0, picker.elTable_[0].length - 1);
    -  assertNull(element);
    -}
    -
    -function testSetDate() {
    -  picker = new goog.ui.DatePicker();
    -  picker.createDom();
    -  picker.enterDocument();
    -  var selectEvents = 0;
    -  var changeEvents = 0;
    -  var changeActiveMonthEvents = 0;
    -  goog.events.listen(picker, goog.ui.DatePicker.Events.SELECT,
    -      function() {
    -        selectEvents++;
    -      });
    -  goog.events.listen(picker, goog.ui.DatePicker.Events.CHANGE,
    -      function() {
    -        changeEvents++;
    -      });
    -  goog.events.listen(picker, goog.ui.DatePicker.Events.CHANGE_ACTIVE_MONTH,
    -      function() {
    -        changeActiveMonthEvents++;
    -      });
    -
    -  // Set date.
    -  picker.setDate(new Date(2010, 1, 26));
    -  assertEquals('no select event dispatched', 1, selectEvents);
    -  assertEquals('no change event dispatched', 1, changeEvents);
    -  assertEquals('no change active month event dispatched',
    -      1, changeActiveMonthEvents);
    -  assertTrue('date is set',
    -      new goog.date.Date(2010, 1, 26).equals(picker.getDate()));
    -
    -  // Set date to same date.
    -  picker.setDate(new Date(2010, 1, 26));
    -  assertEquals('1 select event dispatched', 2, selectEvents);
    -  assertEquals('no change event dispatched', 1, changeEvents);
    -  assertEquals('no change active month event dispatched',
    -      1, changeActiveMonthEvents);
    -
    -  // Set date to different date.
    -  picker.setDate(new Date(2010, 1, 27));
    -  assertEquals('another select event dispatched', 3, selectEvents);
    -  assertEquals('1 change event dispatched', 2, changeEvents);
    -  assertEquals('2 change active month events dispatched',
    -      1, changeActiveMonthEvents);
    -
    -  // Set date to a date in a different month.
    -  picker.setDate(new Date(2010, 2, 27));
    -  assertEquals('another select event dispatched', 4, selectEvents);
    -  assertEquals('another change event dispatched', 3, changeEvents);
    -  assertEquals('3 change active month event dispatched',
    -      2, changeActiveMonthEvents);
    -
    -  // Set date to none.
    -  picker.setDate(null);
    -  assertEquals('another select event dispatched', 5, selectEvents);
    -  assertEquals('another change event dispatched', 4, changeEvents);
    -  assertNull('date cleared', picker.getDate());
    -}
    -
    -function testChangeActiveMonth() {
    -  picker = new goog.ui.DatePicker();
    -  var changeActiveMonthEvents = 0;
    -  goog.events.listen(picker, goog.ui.DatePicker.Events.CHANGE_ACTIVE_MONTH,
    -      function() {
    -        changeActiveMonthEvents++;
    -      });
    -
    -  // Set date.
    -  picker.setDate(new Date(2010, 1, 26));
    -  assertEquals('no change active month event dispatched',
    -      1, changeActiveMonthEvents);
    -  assertTrue('date is set',
    -      new goog.date.Date(2010, 1, 26).equals(picker.getDate()));
    -
    -  // Change to next month.
    -  picker.nextMonth();
    -  assertEquals('1 change active month event dispatched',
    -      2, changeActiveMonthEvents);
    -  assertTrue('date should still be the same',
    -      new goog.date.Date(2010, 1, 26).equals(picker.getDate()));
    -
    -  // Change to next year.
    -  picker.nextYear();
    -  assertEquals('2 change active month events dispatched',
    -      3, changeActiveMonthEvents);
    -
    -  // Change to previous month.
    -  picker.previousMonth();
    -  assertEquals('3 change active month events dispatched',
    -      4, changeActiveMonthEvents);
    -
    -  // Change to previous year.
    -  picker.previousYear();
    -  assertEquals('4 change active month events dispatched',
    -      5, changeActiveMonthEvents);
    -}
    -
    -function testUserSelectableDates() {
    -  var dateRange = new goog.date.DateRange(
    -      new goog.date.Date(2010, 1, 25), new goog.date.Date(2010, 1, 27));
    -  picker = new goog.ui.DatePicker();
    -  picker.setUserSelectableDateRange(dateRange);
    -  assertFalse('should not be selectable date',
    -              picker.isUserSelectableDate_(new goog.date.Date(2010, 1, 24)));
    -  assertTrue('should be a selectable date',
    -      picker.isUserSelectableDate_(new goog.date.Date(2010, 1, 25)));
    -  assertTrue('should be a selectable date',
    -      picker.isUserSelectableDate_(new goog.date.Date(2010, 1, 26)));
    -  assertTrue('should be a selectable date',
    -      picker.isUserSelectableDate_(new goog.date.Date(2010, 1, 27)));
    -  assertFalse('should not be selectable date',
    -              picker.isUserSelectableDate_(new goog.date.Date(2010, 1, 28)));
    -}
    -
    -function testUniqueCellIds() {
    -  picker = new goog.ui.DatePicker();
    -  picker.render();
    -  var cells = goog.dom.getElementsByTagNameAndClass('td', undefined,
    -      picker.getElement());
    -  var existingIds = {};
    -  var numCells = cells.length;
    -  for (var i = 0; i < numCells; i++) {
    -    assertNotNull(cells[i]);
    -    if (goog.a11y.aria.getRole(cells[i]) == goog.a11y.aria.Role.GRIDCELL) {
    -      assertNonEmptyString('cell id is non empty', cells[i].id);
    -      assertUndefined('cell id is not unique',
    -          existingIds[cells[i].id]);
    -      existingIds[cells[i].id] = 1;
    -    }
    -  }
    -}
    -
    -function testDecoratePreservesClasses() {
    -  picker = new goog.ui.DatePicker();
    -  var div = goog.dom.createDom('div', 'existing-class');
    -  picker.decorate(div);
    -  assertTrue(goog.dom.classlist.contains(div, picker.getBaseCssClass()));
    -  assertTrue(goog.dom.classlist.contains(div, 'existing-class'));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/datepickerrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/datepickerrenderer.js
    deleted file mode 100644
    index 7bc5224638f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/datepickerrenderer.js
    +++ /dev/null
    @@ -1,55 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview The renderer interface for {@link goog.ui.DatePicker}.
    - *
    - * @see ../demos/datepicker.html
    - */
    -
    -goog.provide('goog.ui.DatePickerRenderer');
    -
    -
    -
    -/**
    - * The renderer for {@link goog.ui.DatePicker}. Renders the date picker's
    - * navigation header and footer.
    - * @interface
    - */
    -goog.ui.DatePickerRenderer = function() {};
    -
    -
    -/**
    - * Render the navigation row.
    - *
    - * @param {!Element} row The parent element to render the component into.
    - * @param {boolean} simpleNavigation Whether the picker should render a simple
    - *     navigation menu that only contains controls for navigating to the next
    - *     and previous month. The default navigation menu contains controls for
    - *     navigating to the next/previous month, next/previous year, and menus for
    - *     jumping to specific months and years.
    - * @param {boolean} showWeekNum Whether week numbers should be shown.
    - * @param {string} fullDateFormat The full date format.
    - *     {@see goog.i18n.DateTimeSymbols}.
    - */
    -goog.ui.DatePickerRenderer.prototype.renderNavigationRow = goog.abstractMethod;
    -
    -
    -/**
    - * Render the footer row.
    - *
    - * @param {!Element} row The parent element to render the component into.
    - * @param {boolean} showWeekNum Whether week numbers should be shown.
    - */
    -goog.ui.DatePickerRenderer.prototype.renderFooterRow = goog.abstractMethod;
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/decorate.js b/src/database/third_party/closure-library/closure/goog/ui/decorate.js
    deleted file mode 100644
    index 0cf9c2dff6f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/decorate.js
    +++ /dev/null
    @@ -1,38 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides a function that decorates an element based on its CSS
    - * class name.
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.decorate');
    -
    -goog.require('goog.ui.registry');
    -
    -
    -/**
    - * Decorates the element with a suitable {@link goog.ui.Component} instance, if
    - * a matching decorator is found.
    - * @param {Element} element Element to decorate.
    - * @return {goog.ui.Component?} New component instance, decorating the element.
    - */
    -goog.ui.decorate = function(element) {
    -  var decorator = goog.ui.registry.getDecorator(element);
    -  if (decorator) {
    -    decorator.decorate(element);
    -  }
    -  return decorator;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/decorate_test.html b/src/database/third_party/closure-library/closure/goog/ui/decorate_test.html
    deleted file mode 100644
    index 7d333366174..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/decorate_test.html
    +++ /dev/null
    @@ -1,33 +0,0 @@
    -<!DOCTYPE html>
    -<!--
    -Author: attila@google.com (Attila Bodis)
    --->
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.registry
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.ui.decorateTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="x" class="fake-component-x">
    -  </div>
    -  <div id="y" class="fake-component-y fake-component-x">
    -  </div>
    -  <div id="z" class="fake-component-z">
    -  </div>
    -  <div id="u">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/decorate_test.js b/src/database/third_party/closure-library/closure/goog/ui/decorate_test.js
    deleted file mode 100644
    index 961715a6f19..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/decorate_test.js
    +++ /dev/null
    @@ -1,102 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.decorateTest');
    -goog.setTestOnly('goog.ui.decorateTest');
    -
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.decorate');
    -goog.require('goog.ui.registry');
    -// Fake component and renderer implementations, for testing only.
    -
    -// UnknownComponent has no default renderer or decorator registered.
    -function UnknownComponent() {
    -}
    -
    -// FakeComponentX's default renderer is FakeRenderer.  It also has a
    -// decorator.
    -function FakeComponentX() {
    -  this.element = null;
    -}
    -
    -FakeComponentX.prototype.decorate = function(element) {
    -  this.element = element;
    -};
    -
    -// FakeComponentY doesn't have an explicitly registered default
    -// renderer; it should inherit the default renderer from its superclass.
    -// It does have a decorator registered.
    -function FakeComponentY() {
    -  FakeComponentX.call(this);
    -}
    -goog.inherits(FakeComponentY, FakeComponentX);
    -
    -// FakeComponentZ is just another component.  Its default renderer is
    -// FakeSingletonRenderer, but it has no decorator registered.
    -function FakeComponentZ() {
    -}
    -
    -// FakeRenderer is a stateful renderer.
    -function FakeRenderer() {
    -}
    -
    -// FakeSingletonRenderer is a stateless renderer that can be used as a
    -// singleton.
    -function FakeSingletonRenderer() {
    -}
    -
    -FakeSingletonRenderer.instance_ = new FakeSingletonRenderer();
    -
    -FakeSingletonRenderer.getInstance = function() {
    -  return FakeSingletonRenderer.instance_;
    -};
    -
    -function setUp() {
    -  goog.ui.registry.setDefaultRenderer(FakeComponentX, FakeRenderer);
    -  goog.ui.registry.setDefaultRenderer(FakeComponentZ,
    -      FakeSingletonRenderer);
    -
    -  goog.ui.registry.setDecoratorByClassName('fake-component-x',
    -      function() {
    -        return new FakeComponentX();
    -      });
    -  goog.ui.registry.setDecoratorByClassName('fake-component-y',
    -      function() {
    -        return new FakeComponentY();
    -      });
    -}
    -
    -function tearDown() {
    -  goog.ui.registry.reset();
    -}
    -
    -function testDecorate() {
    -  var dx = goog.ui.decorate(document.getElementById('x'));
    -  assertTrue('Decorator for element with fake-component-x class must be ' +
    -      'a FakeComponentX', dx instanceof FakeComponentX);
    -  assertEquals('Element x must have been decorated',
    -      document.getElementById('x'), dx.element);
    -
    -  var dy = goog.ui.decorate(document.getElementById('y'));
    -  assertTrue('Decorator for element with fake-component-y class must be ' +
    -      'a FakeComponentY', dy instanceof FakeComponentY);
    -  assertEquals('Element y must have been decorated',
    -      document.getElementById('y'), dy.element);
    -
    -  var dz = goog.ui.decorate(document.getElementById('z'));
    -  assertNull('Decorator for element with unknown class must be null', dz);
    -
    -  var du = goog.ui.decorate(document.getElementById('u'));
    -  assertNull('Decorator for element without CSS class must be null', du);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/defaultdatepickerrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/defaultdatepickerrenderer.js
    deleted file mode 100644
    index d13e7757e84..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/defaultdatepickerrenderer.js
    +++ /dev/null
    @@ -1,202 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview The default renderer for {@link goog.ui.DatePicker}.
    - *
    - * @see ../demos/datepicker.html
    - */
    -
    -goog.provide('goog.ui.DefaultDatePickerRenderer');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -/** @suppress {extraRequire} Interface. */
    -goog.require('goog.ui.DatePickerRenderer');
    -
    -
    -
    -/**
    - * Default renderer for {@link goog.ui.DatePicker}. Renders the date picker's
    - * navigation header and footer.
    - *
    - * @param {string} baseCssClass Name of base CSS class of the date picker.
    - * @param {goog.dom.DomHelper=} opt_domHelper DOM helper.
    - * @constructor
    - * @implements {goog.ui.DatePickerRenderer}
    - */
    -goog.ui.DefaultDatePickerRenderer = function(baseCssClass, opt_domHelper) {
    -  /**
    -   * Name of base CSS class of datepicker
    -   * @type {string}
    -   * @private
    -   */
    -  this.baseCssClass_ = baseCssClass;
    -
    -  /**
    -   * @type {!goog.dom.DomHelper}
    -   * @private
    -   */
    -  this.dom_ = opt_domHelper || goog.dom.getDomHelper();
    -};
    -
    -
    -/**
    - * Returns the dom helper that is being used on this component.
    - * @return {!goog.dom.DomHelper} The dom helper used on this component.
    - */
    -goog.ui.DefaultDatePickerRenderer.prototype.getDomHelper = function() {
    -  return this.dom_;
    -};
    -
    -
    -/**
    - * Returns base CSS class. This getter is used to get base CSS class part.
    - * All CSS class names in component are created as:
    - *   goog.getCssName(this.getBaseCssClass(), 'CLASS_NAME')
    - * @return {string} Base CSS class.
    - */
    -goog.ui.DefaultDatePickerRenderer.prototype.getBaseCssClass = function() {
    -  return this.baseCssClass_;
    -};
    -
    -
    -/**
    - * Render the navigation row (navigating months and maybe years).
    - *
    - * @param {!Element} row The parent element to render the component into.
    - * @param {boolean} simpleNavigation Whether the picker should render a simple
    - *     navigation menu that only contains controls for navigating to the next
    - *     and previous month. The default navigation menu contains controls for
    - *     navigating to the next/previous month, next/previous year, and menus for
    - *     jumping to specific months and years.
    - * @param {boolean} showWeekNum Whether week numbers should be shown.
    - * @param {string} fullDateFormat The full date format.
    - *     {@see goog.i18n.DateTimeSymbols}.
    - * @override
    - */
    -goog.ui.DefaultDatePickerRenderer.prototype.renderNavigationRow =
    -    function(row, simpleNavigation, showWeekNum, fullDateFormat) {
    -  // Populate the navigation row according to the configured navigation mode.
    -  var cell, monthCell, yearCell;
    -
    -  if (simpleNavigation) {
    -    cell = this.getDomHelper().createElement(goog.dom.TagName.TD);
    -    cell.colSpan = showWeekNum ? 1 : 2;
    -    this.createButton_(cell, '\u00AB',
    -        goog.getCssName(this.getBaseCssClass(), 'previousMonth'));  // <<
    -    row.appendChild(cell);
    -
    -    cell = this.getDomHelper().createElement(goog.dom.TagName.TD);
    -    cell.colSpan = showWeekNum ? 6 : 5;
    -    cell.className = goog.getCssName(this.getBaseCssClass(), 'monthyear');
    -    row.appendChild(cell);
    -
    -    cell = this.getDomHelper().createElement(goog.dom.TagName.TD);
    -    this.createButton_(cell, '\u00BB',
    -        goog.getCssName(this.getBaseCssClass(), 'nextMonth'));  // >>
    -    row.appendChild(cell);
    -
    -  } else {
    -    monthCell = this.getDomHelper().createElement(goog.dom.TagName.TD);
    -    monthCell.colSpan = 5;
    -    this.createButton_(monthCell, '\u00AB',
    -        goog.getCssName(this.getBaseCssClass(), 'previousMonth'));  // <<
    -    this.createButton_(monthCell, '',
    -        goog.getCssName(this.getBaseCssClass(), 'month'));
    -    this.createButton_(monthCell, '\u00BB',
    -        goog.getCssName(this.getBaseCssClass(), 'nextMonth'));  // >>
    -
    -    yearCell = this.getDomHelper().createElement(goog.dom.TagName.TD);
    -    yearCell.colSpan = 3;
    -    this.createButton_(yearCell, '\u00AB',
    -        goog.getCssName(this.getBaseCssClass(), 'previousYear'));  // <<
    -    this.createButton_(yearCell, '',
    -        goog.getCssName(this.getBaseCssClass(), 'year'));
    -    this.createButton_(yearCell, '\u00BB',
    -        goog.getCssName(this.getBaseCssClass(), 'nextYear'));  // <<
    -
    -    // If the date format has year ('y') appearing first before month ('m'),
    -    // show the year on the left hand side of the datepicker popup.  Otherwise,
    -    // show the month on the left side.  This check assumes the data to be
    -    // valid, and that all date formats contain month and year.
    -    if (fullDateFormat.indexOf('y') < fullDateFormat.indexOf('m')) {
    -      row.appendChild(yearCell);
    -      row.appendChild(monthCell);
    -    } else {
    -      row.appendChild(monthCell);
    -      row.appendChild(yearCell);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Render the footer row (with select buttons).
    - *
    - * @param {!Element} row The parent element to render the component into.
    - * @param {boolean} showWeekNum Whether week numbers should be shown.
    - * @override
    - */
    -goog.ui.DefaultDatePickerRenderer.prototype.renderFooterRow =
    -    function(row, showWeekNum) {
    -  // Populate the footer row with buttons for Today and None.
    -  var cell = this.getDomHelper().createElement(goog.dom.TagName.TD);
    -  cell.colSpan = showWeekNum ? 2 : 3;
    -  cell.className = goog.getCssName(this.getBaseCssClass(), 'today-cont');
    -
    -  /** @desc Label for button that selects the current date. */
    -  var MSG_DATEPICKER_TODAY_BUTTON_LABEL = goog.getMsg('Today');
    -  this.createButton_(cell, MSG_DATEPICKER_TODAY_BUTTON_LABEL,
    -      goog.getCssName(this.getBaseCssClass(), 'today-btn'));
    -  row.appendChild(cell);
    -
    -  cell = this.getDomHelper().createElement(goog.dom.TagName.TD);
    -  cell.colSpan = showWeekNum ? 4 : 3;
    -  row.appendChild(cell);
    -
    -  cell = this.getDomHelper().createElement(goog.dom.TagName.TD);
    -  cell.colSpan = 2;
    -  cell.className = goog.getCssName(this.getBaseCssClass(), 'none-cont');
    -
    -  /** @desc Label for button that clears the selection. */
    -  var MSG_DATEPICKER_NONE = goog.getMsg('None');
    -  this.createButton_(cell, MSG_DATEPICKER_NONE,
    -      goog.getCssName(this.getBaseCssClass(), 'none-btn'));
    -  row.appendChild(cell);
    -};
    -
    -
    -/**
    - * Support function for button creation.
    - *
    - * @param {Element} parentNode Container the button should be added to.
    - * @param {string} label Button label.
    - * @param {string=} opt_className Class name for button, which will be used
    - *    in addition to "goog-date-picker-btn".
    - * @private
    - * @return {!Element} The created button element.
    - */
    -goog.ui.DefaultDatePickerRenderer.prototype.createButton_ =
    -    function(parentNode, label, opt_className) {
    -  var classes = [goog.getCssName(this.getBaseCssClass(), 'btn')];
    -  if (opt_className) {
    -    classes.push(opt_className);
    -  }
    -  var el = this.getDomHelper().createElement(goog.dom.TagName.BUTTON);
    -  el.className = classes.join(' ');
    -  el.appendChild(this.getDomHelper().createTextNode(label));
    -  parentNode.appendChild(el);
    -  return el;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/dialog.js b/src/database/third_party/closure-library/closure/goog/ui/dialog.js
    deleted file mode 100644
    index 81c1910d345..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/dialog.js
    +++ /dev/null
    @@ -1,1603 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Class for showing simple modal dialog boxes.
    - *
    - * TODO(user):
    - *   * Standardize CSS class names with other components
    - *   * Add functionality to "host" other components in content area
    - *   * Abstract out ButtonSet and make it more general
    - * @see ../demos/dialog.html
    - */
    -
    -goog.provide('goog.ui.Dialog');
    -goog.provide('goog.ui.Dialog.ButtonSet');
    -goog.provide('goog.ui.Dialog.ButtonSet.DefaultButtons');
    -goog.provide('goog.ui.Dialog.DefaultButtonCaptions');
    -goog.provide('goog.ui.Dialog.DefaultButtonKeys');
    -goog.provide('goog.ui.Dialog.Event');
    -goog.provide('goog.ui.Dialog.EventType');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.NodeType');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.dom.safe');
    -goog.require('goog.events');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.fx.Dragger');
    -goog.require('goog.html.SafeHtml');
    -goog.require('goog.html.legacyconversions');
    -goog.require('goog.math.Rect');
    -goog.require('goog.string');
    -goog.require('goog.structs.Map');
    -goog.require('goog.style');
    -goog.require('goog.ui.ModalPopup');
    -
    -
    -
    -/**
    - * Class for showing simple dialog boxes.
    - * The Html structure of the dialog box is:
    - * <pre>
    - *  Element         Function                Class-name, modal-dialog = default
    - * ----------------------------------------------------------------------------
    - * - iframe         Iframe mask              modal-dialog-bg
    - * - div            Background mask          modal-dialog-bg
    - * - div            Dialog area              modal-dialog
    - *     - div        Title bar                modal-dialog-title
    - *        - span                             modal-dialog-title-text
    - *          - text  Title text               N/A
    - *        - span                             modal-dialog-title-close
    - *          - ??    Close box                N/A
    - *     - div        Content area             modal-dialog-content
    - *        - ??      User specified content   N/A
    - *     - div        Button area              modal-dialog-buttons
    - *        - button                           N/A
    - *        - button
    - *        - ...
    - * </pre>
    - * @constructor
    - * @param {string=} opt_class CSS class name for the dialog element, also used
    - *     as a class name prefix for related elements; defaults to modal-dialog.
    - *     This should be a single, valid CSS class name.
    - * @param {boolean=} opt_useIframeMask Work around windowed controls z-index
    - *     issue by using an iframe instead of a div for bg element.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper; see {@link
    - *     goog.ui.Component} for semantics.
    - * @extends {goog.ui.ModalPopup}
    - */
    -goog.ui.Dialog = function(opt_class, opt_useIframeMask, opt_domHelper) {
    -  goog.ui.Dialog.base(this, 'constructor', opt_useIframeMask, opt_domHelper);
    -
    -  /**
    -   * CSS class name for the dialog element, also used as a class name prefix for
    -   * related elements.  Defaults to goog.getCssName('modal-dialog').
    -   * @type {string}
    -   * @private
    -   */
    -  this.class_ = opt_class || goog.getCssName('modal-dialog');
    -
    -  this.buttons_ = goog.ui.Dialog.ButtonSet.createOkCancel();
    -};
    -goog.inherits(goog.ui.Dialog, goog.ui.ModalPopup);
    -goog.tagUnsealableClass(goog.ui.Dialog);
    -
    -
    -/**
    - * Button set.  Default to Ok/Cancel.
    - * @type {goog.ui.Dialog.ButtonSet}
    - * @private
    - */
    -goog.ui.Dialog.prototype.buttons_;
    -
    -
    -/**
    - * Whether the escape key closes this dialog.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.Dialog.prototype.escapeToCancel_ = true;
    -
    -
    -/**
    - * Whether this dialog should include a title close button.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.Dialog.prototype.hasTitleCloseButton_ = true;
    -
    -
    -/**
    - * Whether the dialog is modal. Defaults to true.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.Dialog.prototype.modal_ = true;
    -
    -
    -/**
    - * Whether the dialog is draggable. Defaults to true.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.Dialog.prototype.draggable_ = true;
    -
    -
    -/**
    - * Opacity for background mask.  Defaults to 50%.
    - * @type {number}
    - * @private
    - */
    -goog.ui.Dialog.prototype.backgroundElementOpacity_ = 0.50;
    -
    -
    -/**
    - * Dialog's title.
    - * @type {string}
    - * @private
    - */
    -goog.ui.Dialog.prototype.title_ = '';
    -
    -
    -/**
    - * Dialog's content (HTML).
    - * @type {goog.html.SafeHtml}
    - * @private
    - */
    -goog.ui.Dialog.prototype.content_ = null;
    -
    -
    -/**
    - * Dragger.
    - * @type {goog.fx.Dragger}
    - * @private
    - */
    -goog.ui.Dialog.prototype.dragger_ = null;
    -
    -
    -/**
    - * Whether the dialog should be disposed when it is hidden.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.Dialog.prototype.disposeOnHide_ = false;
    -
    -
    -/**
    - * Element for the title bar.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.Dialog.prototype.titleEl_ = null;
    -
    -
    -/**
    - * Element for the text area of the title bar.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.Dialog.prototype.titleTextEl_ = null;
    -
    -
    -/**
    - * Id of element for the text area of the title bar.
    - * @type {?string}
    - * @private
    - */
    -goog.ui.Dialog.prototype.titleTextId_ = null;
    -
    -
    -/**
    - * Element for the close box area of the title bar.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.Dialog.prototype.titleCloseEl_ = null;
    -
    -
    -/**
    - * Element for the content area.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.Dialog.prototype.contentEl_ = null;
    -
    -
    -/**
    - * Element for the button bar.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.Dialog.prototype.buttonEl_ = null;
    -
    -
    -/**
    - * The dialog's preferred ARIA role.
    - * @type {goog.a11y.aria.Role}
    - * @private
    - */
    -goog.ui.Dialog.prototype.preferredAriaRole_ = goog.a11y.aria.Role.DIALOG;
    -
    -
    -/** @override */
    -goog.ui.Dialog.prototype.getCssClass = function() {
    -  return this.class_;
    -};
    -
    -
    -/**
    - * Sets the title.
    - * @param {string} title The title text.
    - */
    -goog.ui.Dialog.prototype.setTitle = function(title) {
    -  this.title_ = title;
    -  if (this.titleTextEl_) {
    -    goog.dom.setTextContent(this.titleTextEl_, title);
    -  }
    -};
    -
    -
    -/**
    - * Gets the title.
    - * @return {string} The title.
    - */
    -goog.ui.Dialog.prototype.getTitle = function() {
    -  return this.title_;
    -};
    -
    -
    -/**
    - * Allows arbitrary HTML to be set in the content element.
    - * TODO(user): Deprecate in favor of setSafeHtmlContent, once developer docs on
    - * using goog.html.SafeHtml are in place.
    - * @param {string} html Content HTML.
    - */
    -goog.ui.Dialog.prototype.setContent = function(html) {
    -  this.setSafeHtmlContent(goog.html.legacyconversions.safeHtmlFromString(html));
    -};
    -
    -
    -/**
    - * Allows arbitrary HTML to be set in the content element.
    - * @param {!goog.html.SafeHtml} html Content HTML.
    - */
    -goog.ui.Dialog.prototype.setSafeHtmlContent = function(html) {
    -  this.content_ = html;
    -  if (this.contentEl_) {
    -    goog.dom.safe.setInnerHtml(this.contentEl_, html);
    -  }
    -};
    -
    -
    -/**
    - * Gets the content HTML of the content element as a plain string.
    - *
    - * Note that this method returns the HTML markup that was previously set via
    - * setContent(). In particular, the HTML returned by this method does not
    - * reflect any changes to the content element's DOM that were made my means
    - * other than setContent().
    - *
    - * @return {string} Content HTML.
    - */
    -goog.ui.Dialog.prototype.getContent = function() {
    -  return this.content_ != null ?
    -      goog.html.SafeHtml.unwrap(this.content_) : '';
    -};
    -
    -
    -/**
    - * Gets the content HTML of the content element.
    - * @return {goog.html.SafeHtml} Content HTML.
    - */
    -goog.ui.Dialog.prototype.getSafeHtmlContent = function() {
    -  return this.content_;
    -};
    -
    -
    -/**
    - * Returns the dialog's preferred ARIA role. This can be used to override the
    - * default dialog role, e.g. with an ARIA role of ALERTDIALOG for a simple
    - * warning or confirmation dialog.
    - * @return {goog.a11y.aria.Role} This dialog's preferred ARIA role.
    - */
    -goog.ui.Dialog.prototype.getPreferredAriaRole = function() {
    -  return this.preferredAriaRole_;
    -};
    -
    -
    -/**
    - * Sets the dialog's preferred ARIA role. This can be used to override the
    - * default dialog role, e.g. with an ARIA role of ALERTDIALOG for a simple
    - * warning or confirmation dialog.
    - * @param {goog.a11y.aria.Role} role This dialog's preferred ARIA role.
    - */
    -goog.ui.Dialog.prototype.setPreferredAriaRole = function(role) {
    -  this.preferredAriaRole_ = role;
    -};
    -
    -
    -/**
    - * Renders if the DOM is not created.
    - * @private
    - */
    -goog.ui.Dialog.prototype.renderIfNoDom_ = function() {
    -  if (!this.getElement()) {
    -    // TODO(gboyer): Ideally we'd only create the DOM, but many applications
    -    // are requiring this behavior.  Eventually, it would be best if the
    -    // element getters could return null if the elements have not been
    -    // created.
    -    this.render();
    -  }
    -};
    -
    -
    -/**
    - * Returns the content element so that more complicated things can be done with
    - * the content area.  Renders if the DOM is not yet created.  Overrides
    - * {@link goog.ui.Component#getContentElement}.
    - * @return {Element} The content element.
    - * @override
    - */
    -goog.ui.Dialog.prototype.getContentElement = function() {
    -  this.renderIfNoDom_();
    -  return this.contentEl_;
    -};
    -
    -
    -/**
    - * Returns the title element so that more complicated things can be done with
    - * the title.  Renders if the DOM is not yet created.
    - * @return {Element} The title element.
    - */
    -goog.ui.Dialog.prototype.getTitleElement = function() {
    -  this.renderIfNoDom_();
    -  return this.titleEl_;
    -};
    -
    -
    -/**
    - * Returns the title text element so that more complicated things can be done
    - * with the text of the title.  Renders if the DOM is not yet created.
    - * @return {Element} The title text element.
    - */
    -goog.ui.Dialog.prototype.getTitleTextElement = function() {
    -  this.renderIfNoDom_();
    -  return this.titleTextEl_;
    -};
    -
    -
    -/**
    - * Returns the title close element so that more complicated things can be done
    - * with the close area of the title.  Renders if the DOM is not yet created.
    - * @return {Element} The close box.
    - */
    -goog.ui.Dialog.prototype.getTitleCloseElement = function() {
    -  this.renderIfNoDom_();
    -  return this.titleCloseEl_;
    -};
    -
    -
    -/**
    - * Returns the button element so that more complicated things can be done with
    - * the button area.  Renders if the DOM is not yet created.
    - * @return {Element} The button container element.
    - */
    -goog.ui.Dialog.prototype.getButtonElement = function() {
    -  this.renderIfNoDom_();
    -  return this.buttonEl_;
    -};
    -
    -
    -/**
    - * Returns the dialog element so that more complicated things can be done with
    - * the dialog box.  Renders if the DOM is not yet created.
    - * @return {Element} The dialog element.
    - */
    -goog.ui.Dialog.prototype.getDialogElement = function() {
    -  this.renderIfNoDom_();
    -  return this.getElement();
    -};
    -
    -
    -/**
    - * Returns the background mask element so that more complicated things can be
    - * done with the background region.  Renders if the DOM is not yet created.
    - * @return {Element} The background mask element.
    - * @override
    - */
    -goog.ui.Dialog.prototype.getBackgroundElement = function() {
    -  this.renderIfNoDom_();
    -  return goog.ui.Dialog.base(this, 'getBackgroundElement');
    -};
    -
    -
    -/**
    - * Gets the opacity of the background mask.
    - * @return {number} Background mask opacity.
    - */
    -goog.ui.Dialog.prototype.getBackgroundElementOpacity = function() {
    -  return this.backgroundElementOpacity_;
    -};
    -
    -
    -/**
    - * Sets the opacity of the background mask.
    - * @param {number} opacity Background mask opacity.
    - */
    -goog.ui.Dialog.prototype.setBackgroundElementOpacity = function(opacity) {
    -  this.backgroundElementOpacity_ = opacity;
    -
    -  if (this.getElement()) {
    -    var bgEl = this.getBackgroundElement();
    -    if (bgEl) {
    -      goog.style.setOpacity(bgEl, this.backgroundElementOpacity_);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Sets the modal property of the dialog. In case the dialog is already
    - * inDocument, renders the modal background elements according to the specified
    - * modal parameter.
    - *
    - * Note that non-modal dialogs cannot use an iframe mask.
    - *
    - * @param {boolean} modal Whether the dialog is modal.
    - */
    -goog.ui.Dialog.prototype.setModal = function(modal) {
    -  if (modal != this.modal_) {
    -    this.setModalInternal_(modal);
    -  }
    -};
    -
    -
    -/**
    - * Sets the modal property of the dialog.
    - * @param {boolean} modal Whether the dialog is modal.
    - * @private
    - */
    -goog.ui.Dialog.prototype.setModalInternal_ = function(modal) {
    -  this.modal_ = modal;
    -  if (this.isInDocument()) {
    -    var dom = this.getDomHelper();
    -    var bg = this.getBackgroundElement();
    -    var bgIframe = this.getBackgroundIframe();
    -    if (modal) {
    -      if (bgIframe) {
    -        dom.insertSiblingBefore(bgIframe, this.getElement());
    -      }
    -      dom.insertSiblingBefore(bg, this.getElement());
    -    } else {
    -      dom.removeNode(bgIframe);
    -      dom.removeNode(bg);
    -    }
    -  }
    -  if (this.isVisible()) {
    -    this.setA11YDetectBackground(modal);
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} modal Whether the dialog is modal.
    - */
    -goog.ui.Dialog.prototype.getModal = function() {
    -  return this.modal_;
    -};
    -
    -
    -/**
    - * @return {string} The CSS class name for the dialog element.
    - */
    -goog.ui.Dialog.prototype.getClass = function() {
    -  return this.getCssClass();
    -};
    -
    -
    -/**
    - * Sets whether the dialog can be dragged.
    - * @param {boolean} draggable Whether the dialog can be dragged.
    - */
    -goog.ui.Dialog.prototype.setDraggable = function(draggable) {
    -  this.draggable_ = draggable;
    -  this.setDraggingEnabled_(draggable && this.isInDocument());
    -};
    -
    -
    -/**
    - * Returns a dragger for moving the dialog and adds a class for the move cursor.
    - * Defaults to allow dragging of the title only, but can be overridden if
    - * different drag targets or dragging behavior is desired.
    - * @return {!goog.fx.Dragger} The created dragger instance.
    - * @protected
    - */
    -goog.ui.Dialog.prototype.createDragger = function() {
    -  return new goog.fx.Dragger(this.getElement(), this.titleEl_);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the dialog is draggable.
    - */
    -goog.ui.Dialog.prototype.getDraggable = function() {
    -  return this.draggable_;
    -};
    -
    -
    -/**
    - * Enables or disables dragging.
    - * @param {boolean} enabled Whether to enable it.
    - * @private
    - */
    -goog.ui.Dialog.prototype.setDraggingEnabled_ = function(enabled) {
    -  // This isn't ideal, but the quickest and easiest way to append
    -  // title-draggable to the last class in the class_ string, then trim and
    -  // split the string into an array (in case the dialog was set up with
    -  // multiple, space-separated class names).
    -  var classNames = goog.string.trim(goog.getCssName(this.class_,
    -      'title-draggable')).split(' ');
    -
    -  if (this.getElement()) {
    -    if (enabled) {
    -      goog.dom.classlist.addAll(
    -          goog.asserts.assert(this.titleEl_), classNames);
    -    } else {
    -      goog.dom.classlist.removeAll(
    -          goog.asserts.assert(this.titleEl_), classNames);
    -    }
    -  }
    -
    -  if (enabled && !this.dragger_) {
    -    this.dragger_ = this.createDragger();
    -    goog.dom.classlist.addAll(goog.asserts.assert(this.titleEl_), classNames);
    -    goog.events.listen(this.dragger_, goog.fx.Dragger.EventType.START,
    -        this.setDraggerLimits_, false, this);
    -  } else if (!enabled && this.dragger_) {
    -    this.dragger_.dispose();
    -    this.dragger_ = null;
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.Dialog.prototype.createDom = function() {
    -  goog.ui.Dialog.base(this, 'createDom');
    -  var element = this.getElement();
    -  goog.asserts.assert(element, 'getElement() returns null');
    -
    -  var dom = this.getDomHelper();
    -  this.titleEl_ = dom.createDom('div', goog.getCssName(this.class_, 'title'),
    -      this.titleTextEl_ = dom.createDom(
    -          'span',
    -          {'className': goog.getCssName(this.class_, 'title-text'),
    -            'id': this.getId()},
    -          this.title_),
    -      this.titleCloseEl_ = dom.createDom(
    -          'span', goog.getCssName(this.class_, 'title-close'))),
    -  goog.dom.append(element, this.titleEl_,
    -      this.contentEl_ = dom.createDom('div',
    -          goog.getCssName(this.class_, 'content')),
    -      this.buttonEl_ = dom.createDom('div',
    -          goog.getCssName(this.class_, 'buttons')));
    -
    -  // Make the title and close button behave correctly with screen readers.
    -  // Note: this is only being added if the dialog is not decorated. Decorators
    -  // are expected to add aria label, role, and tab indexing in their templates.
    -  goog.a11y.aria.setRole(this.titleTextEl_, goog.a11y.aria.Role.HEADING);
    -  goog.a11y.aria.setRole(this.titleCloseEl_, goog.a11y.aria.Role.BUTTON);
    -  goog.dom.setFocusableTabIndex(this.titleCloseEl_, true);
    -  goog.a11y.aria.setLabel(this.titleCloseEl_,
    -      goog.ui.Dialog.MSG_GOOG_UI_DIALOG_CLOSE_);
    -
    -  this.titleTextId_ = this.titleTextEl_.id;
    -  goog.a11y.aria.setRole(element, this.getPreferredAriaRole());
    -  goog.a11y.aria.setState(element, goog.a11y.aria.State.LABELLEDBY,
    -      this.titleTextId_ || '');
    -  // If setContent() was called before createDom(), make sure the inner HTML of
    -  // the content element is initialized.
    -  if (this.content_) {
    -    goog.dom.safe.setInnerHtml(this.contentEl_, this.content_);
    -  }
    -  goog.style.setElementShown(this.titleCloseEl_, this.hasTitleCloseButton_);
    -
    -  // Render the buttons.
    -  if (this.buttons_) {
    -    this.buttons_.attachToElement(this.buttonEl_);
    -  }
    -  goog.style.setElementShown(this.buttonEl_, !!this.buttons_);
    -  this.setBackgroundElementOpacity(this.backgroundElementOpacity_);
    -};
    -
    -
    -/** @override */
    -goog.ui.Dialog.prototype.decorateInternal = function(element) {
    -  goog.ui.Dialog.base(this, 'decorateInternal', element);
    -  var dialogElement = this.getElement();
    -  goog.asserts.assert(dialogElement,
    -      'The DOM element for dialog cannot be null.');
    -  // Decorate or create the content element.
    -  var contentClass = goog.getCssName(this.class_, 'content');
    -  this.contentEl_ = goog.dom.getElementsByTagNameAndClass(
    -      null, contentClass, dialogElement)[0];
    -  if (!this.contentEl_) {
    -    this.contentEl_ = this.getDomHelper().createDom('div', contentClass);
    -    if (this.content_) {
    -      goog.dom.safe.setInnerHtml(this.contentEl_, this.content_);
    -    }
    -    dialogElement.appendChild(this.contentEl_);
    -  }
    -
    -  // Decorate or create the title bar element.
    -  var titleClass = goog.getCssName(this.class_, 'title');
    -  var titleTextClass = goog.getCssName(this.class_, 'title-text');
    -  var titleCloseClass = goog.getCssName(this.class_, 'title-close');
    -  this.titleEl_ = goog.dom.getElementsByTagNameAndClass(
    -      null, titleClass, dialogElement)[0];
    -  if (this.titleEl_) {
    -    // Only look for title text & title close elements if a title bar element
    -    // was found.  Otherwise assume that the entire title bar has to be
    -    // created from scratch.
    -    this.titleTextEl_ = goog.dom.getElementsByTagNameAndClass(
    -        null, titleTextClass, this.titleEl_)[0];
    -    this.titleCloseEl_ = goog.dom.getElementsByTagNameAndClass(
    -        null, titleCloseClass, this.titleEl_)[0];
    -  } else {
    -    // Create the title bar element and insert it before the content area.
    -    // This is useful if the element to decorate only includes a content area.
    -    this.titleEl_ = this.getDomHelper().createDom('div', titleClass);
    -    dialogElement.insertBefore(this.titleEl_, this.contentEl_);
    -  }
    -
    -  // Decorate or create the title text element.
    -  if (this.titleTextEl_) {
    -    this.title_ = goog.dom.getTextContent(this.titleTextEl_);
    -    // Give the title text element an id if it doesn't already have one.
    -    if (!this.titleTextEl_.id) {
    -      this.titleTextEl_.id = this.getId();
    -    }
    -  } else {
    -    this.titleTextEl_ = goog.dom.createDom(
    -        'span', {'className': titleTextClass, 'id': this.getId()});
    -    this.titleEl_.appendChild(this.titleTextEl_);
    -  }
    -  this.titleTextId_ = this.titleTextEl_.id;
    -  goog.a11y.aria.setState(dialogElement, goog.a11y.aria.State.LABELLEDBY,
    -      this.titleTextId_ || '');
    -  // Decorate or create the title close element.
    -  if (!this.titleCloseEl_) {
    -    this.titleCloseEl_ = this.getDomHelper().createDom('span', titleCloseClass);
    -    this.titleEl_.appendChild(this.titleCloseEl_);
    -  }
    -  goog.style.setElementShown(this.titleCloseEl_, this.hasTitleCloseButton_);
    -
    -  // Decorate or create the button container element.
    -  var buttonsClass = goog.getCssName(this.class_, 'buttons');
    -  this.buttonEl_ = goog.dom.getElementsByTagNameAndClass(
    -      null, buttonsClass, dialogElement)[0];
    -  if (this.buttonEl_) {
    -    // Button container element found.  Create empty button set and use it to
    -    // decorate the button container.
    -    this.buttons_ = new goog.ui.Dialog.ButtonSet(this.getDomHelper());
    -    this.buttons_.decorate(this.buttonEl_);
    -  } else {
    -    // Create new button container element, and render a button set into it.
    -    this.buttonEl_ = this.getDomHelper().createDom('div', buttonsClass);
    -    dialogElement.appendChild(this.buttonEl_);
    -    if (this.buttons_) {
    -      this.buttons_.attachToElement(this.buttonEl_);
    -    }
    -    goog.style.setElementShown(this.buttonEl_, !!this.buttons_);
    -  }
    -  this.setBackgroundElementOpacity(this.backgroundElementOpacity_);
    -};
    -
    -
    -/** @override */
    -goog.ui.Dialog.prototype.enterDocument = function() {
    -  goog.ui.Dialog.base(this, 'enterDocument');
    -
    -  // Listen for keyboard events while the dialog is visible.
    -  this.getHandler().
    -      listen(this.getElement(), goog.events.EventType.KEYDOWN, this.onKey_).
    -      listen(this.getElement(), goog.events.EventType.KEYPRESS, this.onKey_);
    -
    -  // NOTE: see bug 1163154 for an example of an edge case where making the
    -  // dialog visible in response to a KEYDOWN will result in a CLICK event
    -  // firing on the default button (immediately closing the dialog) if the key
    -  // that fired the KEYDOWN is also normally used to activate controls
    -  // (i.e. SPACE/ENTER).
    -  //
    -  // This could be worked around by attaching the onButtonClick_ handler in a
    -  // setTimeout, but that was deemed undesirable.
    -  this.getHandler().listen(this.buttonEl_, goog.events.EventType.CLICK,
    -      this.onButtonClick_);
    -
    -  // Add drag support.
    -  this.setDraggingEnabled_(this.draggable_);
    -
    -  // Add event listeners to the close box and the button container.
    -  this.getHandler().listen(
    -      this.titleCloseEl_, goog.events.EventType.CLICK,
    -      this.onTitleCloseClick_);
    -
    -  var element = this.getElement();
    -  goog.asserts.assert(element, 'The DOM element for dialog cannot be null');
    -  goog.a11y.aria.setRole(element, this.getPreferredAriaRole());
    -  if (this.titleTextEl_.id !== '') {
    -    goog.a11y.aria.setState(element, goog.a11y.aria.State.LABELLEDBY,
    -        this.titleTextEl_.id);
    -  }
    -
    -  if (!this.modal_) {
    -    this.setModalInternal_(false);
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.Dialog.prototype.exitDocument = function() {
    -  if (this.isVisible()) {
    -    this.setVisible(false);
    -  }
    -
    -  // Remove drag support.
    -  this.setDraggingEnabled_(false);
    -
    -  goog.ui.Dialog.base(this, 'exitDocument');
    -};
    -
    -
    -/**
    - * Sets the visibility of the dialog box and moves focus to the
    - * default button. Lazily renders the component if needed. After this
    - * method returns, isVisible() will always return the new state, even
    - * if there is a transition.
    - * @param {boolean} visible Whether the dialog should be visible.
    - * @override
    - */
    -goog.ui.Dialog.prototype.setVisible = function(visible) {
    -  if (visible == this.isVisible()) {
    -    return;
    -  }
    -
    -  // If the dialog hasn't been rendered yet, render it now.
    -  if (!this.isInDocument()) {
    -    this.render();
    -  }
    -
    -  goog.ui.Dialog.base(this, 'setVisible', visible);
    -};
    -
    -
    -/**
    - * @override
    - * @suppress {deprecated} AFTER_SHOW is deprecated earlier in this file.
    - */
    -goog.ui.Dialog.prototype.onShow = function() {
    -  goog.ui.Dialog.base(this, 'onShow');
    -  this.dispatchEvent(goog.ui.Dialog.EventType.AFTER_SHOW);
    -};
    -
    -
    -/**
    - * @override
    - * @suppress {deprecated} AFTER_HIDE is deprecated earlier in this file.
    - */
    -goog.ui.Dialog.prototype.onHide = function() {
    -  goog.ui.Dialog.base(this, 'onHide');
    -  this.dispatchEvent(goog.ui.Dialog.EventType.AFTER_HIDE);
    -  if (this.disposeOnHide_) {
    -    this.dispose();
    -  }
    -};
    -
    -
    -/**
    - * Sets dragger limits when dragging is started.
    - * @param {!goog.events.Event} e goog.fx.Dragger.EventType.START event.
    - * @private
    - */
    -goog.ui.Dialog.prototype.setDraggerLimits_ = function(e) {
    -  var doc = this.getDomHelper().getDocument();
    -  var win = goog.dom.getWindow(doc) || window;
    -
    -  // Take the max of scroll height and view height for cases in which document
    -  // does not fill screen.
    -  var viewSize = goog.dom.getViewportSize(win);
    -  var w = Math.max(doc.body.scrollWidth, viewSize.width);
    -  var h = Math.max(doc.body.scrollHeight, viewSize.height);
    -
    -  var dialogSize = goog.style.getSize(this.getElement());
    -  if (goog.style.getComputedPosition(this.getElement()) == 'fixed') {
    -    // Ensure position:fixed dialogs can't be dragged beyond the viewport.
    -    this.dragger_.setLimits(new goog.math.Rect(0, 0,
    -        Math.max(0, viewSize.width - dialogSize.width),
    -        Math.max(0, viewSize.height - dialogSize.height)));
    -  } else {
    -    this.dragger_.setLimits(new goog.math.Rect(0, 0,
    -        w - dialogSize.width, h - dialogSize.height));
    -  }
    -};
    -
    -
    -/**
    - * Handles a click on the title close area.
    - * @param {goog.events.BrowserEvent} e Browser's event object.
    - * @private
    - */
    -goog.ui.Dialog.prototype.onTitleCloseClick_ = function(e) {
    -  this.handleTitleClose_();
    -};
    -
    -
    -/**
    - * Performs the action of closing the dialog in response to the title close
    - * button being interacted with. General purpose method to be called by click
    - * and button event handlers.
    - * @private
    - */
    -goog.ui.Dialog.prototype.handleTitleClose_ = function() {
    -  if (!this.hasTitleCloseButton_) {
    -    return;
    -  }
    -
    -  var bs = this.getButtonSet();
    -  var key = bs && bs.getCancel();
    -  // Only if there is a valid cancel button is an event dispatched.
    -  if (key) {
    -    var caption = /** @type {Element|string} */(bs.get(key));
    -    if (this.dispatchEvent(new goog.ui.Dialog.Event(key, caption))) {
    -      this.setVisible(false);
    -    }
    -  } else {
    -    this.setVisible(false);
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} Whether this dialog has a title close button.
    - */
    -goog.ui.Dialog.prototype.getHasTitleCloseButton = function() {
    -  return this.hasTitleCloseButton_;
    -};
    -
    -
    -/**
    - * Sets whether the dialog should have a close button in the title bar. There
    - * will always be an element for the title close button, but setting this
    - * parameter to false will cause it to be hidden and have no active listener.
    - * @param {boolean} b Whether this dialog should have a title close button.
    - */
    -goog.ui.Dialog.prototype.setHasTitleCloseButton = function(b) {
    -  this.hasTitleCloseButton_ = b;
    -  if (this.titleCloseEl_) {
    -    goog.style.setElementShown(this.titleCloseEl_, this.hasTitleCloseButton_);
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the escape key should close this dialog.
    - */
    -goog.ui.Dialog.prototype.isEscapeToCancel = function() {
    -  return this.escapeToCancel_;
    -};
    -
    -
    -/**
    - * @param {boolean} b Whether the escape key should close this dialog.
    - */
    -goog.ui.Dialog.prototype.setEscapeToCancel = function(b) {
    -  this.escapeToCancel_ = b;
    -};
    -
    -
    -/**
    - * Sets whether the dialog should be disposed when it is hidden.  By default
    - * dialogs are not disposed when they are hidden.
    - * @param {boolean} b Whether the dialog should get disposed when it gets
    - *     hidden.
    - */
    -goog.ui.Dialog.prototype.setDisposeOnHide = function(b) {
    -  this.disposeOnHide_ = b;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the dialog should be disposed when it is hidden.
    - */
    -goog.ui.Dialog.prototype.getDisposeOnHide = function() {
    -  return this.disposeOnHide_;
    -};
    -
    -
    -/** @override */
    -goog.ui.Dialog.prototype.disposeInternal = function() {
    -  this.titleCloseEl_ = null;
    -  this.buttonEl_ = null;
    -  goog.ui.Dialog.base(this, 'disposeInternal');
    -};
    -
    -
    -/**
    - * Sets the button set to use.
    - * Note: Passing in null will cause no button set to be rendered.
    - * @param {goog.ui.Dialog.ButtonSet?} buttons The button set to use.
    - */
    -goog.ui.Dialog.prototype.setButtonSet = function(buttons) {
    -  this.buttons_ = buttons;
    -  if (this.buttonEl_) {
    -    if (this.buttons_) {
    -      this.buttons_.attachToElement(this.buttonEl_);
    -    } else {
    -      goog.dom.safe.setInnerHtml(
    -          this.buttonEl_, goog.html.SafeHtml.EMPTY);
    -    }
    -    goog.style.setElementShown(this.buttonEl_, !!this.buttons_);
    -  }
    -};
    -
    -
    -/**
    - * Returns the button set being used.
    - * @return {goog.ui.Dialog.ButtonSet?} The button set being used.
    - */
    -goog.ui.Dialog.prototype.getButtonSet = function() {
    -  return this.buttons_;
    -};
    -
    -
    -/**
    - * Handles a click on the button container.
    - * @param {goog.events.BrowserEvent} e Browser's event object.
    - * @private
    - */
    -goog.ui.Dialog.prototype.onButtonClick_ = function(e) {
    -  var button = this.findParentButton_(/** @type {Element} */ (e.target));
    -  if (button && !button.disabled) {
    -    var key = button.name;
    -    var caption = /** @type {Element|string} */(
    -        this.getButtonSet().get(key));
    -    if (this.dispatchEvent(new goog.ui.Dialog.Event(key, caption))) {
    -      this.setVisible(false);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Finds the parent button of an element (or null if there was no button
    - * parent).
    - * @param {Element} element The element that was clicked on.
    - * @return {Element} Returns the parent button or null if not found.
    - * @private
    - */
    -goog.ui.Dialog.prototype.findParentButton_ = function(element) {
    -  var el = element;
    -  while (el != null && el != this.buttonEl_) {
    -    if (el.tagName == 'BUTTON') {
    -      return /** @type {Element} */(el);
    -    }
    -    el = el.parentNode;
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * Handles keydown and keypress events, and dismisses the popup if cancel is
    - * pressed.  If there is a cancel action in the ButtonSet, than that will be
    - * fired.  Also prevents tabbing out of the dialog.
    - * @param {goog.events.BrowserEvent} e Browser's event object.
    - * @private
    - */
    -goog.ui.Dialog.prototype.onKey_ = function(e) {
    -  var close = false;
    -  var hasHandler = false;
    -  var buttonSet = this.getButtonSet();
    -  var target = e.target;
    -
    -  if (e.type == goog.events.EventType.KEYDOWN) {
    -    // Escape and tab can only properly be handled in keydown handlers.
    -    if (this.escapeToCancel_ && e.keyCode == goog.events.KeyCodes.ESC) {
    -      // Only if there is a valid cancel button is an event dispatched.
    -      var cancel = buttonSet && buttonSet.getCancel();
    -
    -      // Users may expect to hit escape on a SELECT element.
    -      var isSpecialFormElement =
    -          target.tagName == 'SELECT' && !target.disabled;
    -
    -      if (cancel && !isSpecialFormElement) {
    -        hasHandler = true;
    -
    -        var caption = buttonSet.get(cancel);
    -        close = this.dispatchEvent(
    -            new goog.ui.Dialog.Event(cancel,
    -                /** @type {Element|null|string} */(caption)));
    -      } else if (!isSpecialFormElement) {
    -        close = true;
    -      }
    -    } else if (e.keyCode == goog.events.KeyCodes.TAB && e.shiftKey &&
    -        target == this.getElement()) {
    -      // Prevent the user from shift-tabbing backwards out of the dialog box.
    -      // Instead, set up a wrap in focus backward to the end of the dialog.
    -      this.setupBackwardTabWrap();
    -    }
    -  } else if (e.keyCode == goog.events.KeyCodes.ENTER) {
    -    // Only handle ENTER in keypress events, in case the action opens a
    -    // popup window.
    -    var key;
    -    if (target.tagName == 'BUTTON' && !target.disabled) {
    -      // If the target is a button and it's enabled, we can fire that button's
    -      // handler.
    -      key = target.name;
    -    } else if (target == this.titleCloseEl_) {
    -      // if the title 'close' button is in focus, close the dialog
    -      this.handleTitleClose_();
    -    } else if (buttonSet) {
    -      // Try to fire the default button's handler (if one exists), but only if
    -      // the button is enabled.
    -      var defaultKey = buttonSet.getDefault();
    -      var defaultButton = defaultKey && buttonSet.getButton(defaultKey);
    -
    -      // Users may expect to hit enter on a TEXTAREA, SELECT or an A element.
    -      var isSpecialFormElement =
    -          (target.tagName == 'TEXTAREA' || target.tagName == 'SELECT' ||
    -           target.tagName == 'A') && !target.disabled;
    -
    -      if (defaultButton && !defaultButton.disabled && !isSpecialFormElement) {
    -        key = defaultKey;
    -      }
    -    }
    -    if (key && buttonSet) {
    -      hasHandler = true;
    -      close = this.dispatchEvent(
    -          new goog.ui.Dialog.Event(key, String(buttonSet.get(key))));
    -    }
    -  } else if (target == this.titleCloseEl_ &&
    -      e.keyCode == goog.events.KeyCodes.SPACE) {
    -    // if the title 'close' button is in focus on 'SPACE,' close the dialog
    -    this.handleTitleClose_();
    -  }
    -
    -  if (close || hasHandler) {
    -    e.stopPropagation();
    -    e.preventDefault();
    -  }
    -
    -  if (close) {
    -    this.setVisible(false);
    -  }
    -};
    -
    -
    -
    -/**
    - * Dialog event class.
    - * @param {string} key Key identifier for the button.
    - * @param {string|Element} caption Caption on the button (might be i18nlized).
    - * @constructor
    - * @extends {goog.events.Event}
    - */
    -goog.ui.Dialog.Event = function(key, caption) {
    -  this.type = goog.ui.Dialog.EventType.SELECT;
    -  this.key = key;
    -  this.caption = caption;
    -};
    -goog.inherits(goog.ui.Dialog.Event, goog.events.Event);
    -
    -
    -/**
    - * Event type constant for dialog events.
    - * TODO(attila): Change this to goog.ui.Dialog.EventType.SELECT.
    - * @type {string}
    - * @deprecated Use goog.ui.Dialog.EventType.SELECT.
    - */
    -goog.ui.Dialog.SELECT_EVENT = 'dialogselect';
    -
    -
    -/**
    - * Events dispatched by dialogs.
    - * @enum {string}
    - */
    -goog.ui.Dialog.EventType = {
    -  /**
    -   * Dispatched when the user closes the dialog.
    -   * The dispatched event will always be of type {@link goog.ui.Dialog.Event}.
    -   * Canceling the event will prevent the dialog from closing.
    -   */
    -  SELECT: 'dialogselect',
    -
    -  /**
    -   * Dispatched after the dialog is closed. Not cancelable.
    -   * @deprecated Use goog.ui.PopupBase.EventType.HIDE.
    -   */
    -  AFTER_HIDE: 'afterhide',
    -
    -  /**
    -   * Dispatched after the dialog is shown. Not cancelable.
    -   * @deprecated Use goog.ui.PopupBase.EventType.SHOW.
    -   */
    -  AFTER_SHOW: 'aftershow'
    -};
    -
    -
    -
    -/**
    - * A button set defines the behaviour of a set of buttons that the dialog can
    - * show.  Uses the {@link goog.structs.Map} interface.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper; see {@link
    - *    goog.ui.Component} for semantics.
    - * @constructor
    - * @extends {goog.structs.Map}
    - */
    -goog.ui.Dialog.ButtonSet = function(opt_domHelper) {
    -  // TODO(attila):  Refactor ButtonSet to extend goog.ui.Component?
    -  this.dom_ = opt_domHelper || goog.dom.getDomHelper();
    -  goog.structs.Map.call(this);
    -};
    -goog.inherits(goog.ui.Dialog.ButtonSet, goog.structs.Map);
    -goog.tagUnsealableClass(goog.ui.Dialog.ButtonSet);
    -
    -
    -/**
    - * A CSS className for this component.
    - * @type {string}
    - * @private
    - */
    -goog.ui.Dialog.ButtonSet.prototype.class_ = goog.getCssName('goog-buttonset');
    -
    -
    -/**
    - * The button that has default focus (references key in buttons_ map).
    - * @type {?string}
    - * @private
    - */
    -goog.ui.Dialog.ButtonSet.prototype.defaultButton_ = null;
    -
    -
    -/**
    - * Optional container the button set should be rendered into.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.Dialog.ButtonSet.prototype.element_ = null;
    -
    -
    -/**
    - * The button whose action is associated with the escape key and the X button
    - * on the dialog.
    - * @type {?string}
    - * @private
    - */
    -goog.ui.Dialog.ButtonSet.prototype.cancelButton_ = null;
    -
    -
    -/**
    - * Adds a button to the button set.  Buttons will be displayed in the order they
    - * are added.
    - *
    - * @param {*} key Key used to identify the button in events.
    - * @param {*} caption A string caption or a DOM node that can be
    - *     appended to a button element.
    - * @param {boolean=} opt_isDefault Whether this button is the default button,
    - *     Dialog will dispatch for this button if enter is pressed.
    - * @param {boolean=} opt_isCancel Whether this button has the same behaviour as
    - *    cancel.  If escape is pressed this button will fire.
    - * @return {!goog.ui.Dialog.ButtonSet} The button set, to make it easy to chain
    - *    "set" calls and build new ButtonSets.
    - * @override
    - */
    -goog.ui.Dialog.ButtonSet.prototype.set = function(key, caption,
    -    opt_isDefault, opt_isCancel) {
    -  goog.structs.Map.prototype.set.call(this, key, caption);
    -
    -  if (opt_isDefault) {
    -    this.defaultButton_ = /** @type {?string} */ (key);
    -  }
    -  if (opt_isCancel) {
    -    this.cancelButton_ = /** @type {?string} */ (key);
    -  }
    -
    -  return this;
    -};
    -
    -
    -/**
    - * Adds a button (an object with a key and caption) to this button set. Buttons
    - * will be displayed in the order they are added.
    - * @see goog.ui.Dialog.DefaultButtons
    - * @param {{key: string, caption: string}} button The button key and caption.
    - * @param {boolean=} opt_isDefault Whether this button is the default button.
    - *     Dialog will dispatch for this button if enter is pressed.
    - * @param {boolean=} opt_isCancel Whether this button has the same behavior as
    - *     cancel. If escape is pressed this button will fire.
    - * @return {!goog.ui.Dialog.ButtonSet} The button set, to make it easy to chain
    - *     "addButton" calls and build new ButtonSets.
    - */
    -goog.ui.Dialog.ButtonSet.prototype.addButton = function(button, opt_isDefault,
    -    opt_isCancel) {
    -  return this.set(button.key, button.caption, opt_isDefault, opt_isCancel);
    -};
    -
    -
    -/**
    - * Attaches the button set to an element, rendering it inside.
    - * @param {Element} el Container.
    - */
    -goog.ui.Dialog.ButtonSet.prototype.attachToElement = function(el) {
    -  this.element_ = el;
    -  this.render();
    -};
    -
    -
    -/**
    - * Renders the button set inside its container element.
    - */
    -goog.ui.Dialog.ButtonSet.prototype.render = function() {
    -  if (this.element_) {
    -    goog.dom.safe.setInnerHtml(
    -        this.element_, goog.html.SafeHtml.EMPTY);
    -    var domHelper = goog.dom.getDomHelper(this.element_);
    -    this.forEach(function(caption, key) {
    -      var button = domHelper.createDom('button', {'name': key}, caption);
    -      if (key == this.defaultButton_) {
    -        button.className = goog.getCssName(this.class_, 'default');
    -      }
    -      this.element_.appendChild(button);
    -    }, this);
    -  }
    -};
    -
    -
    -/**
    - * Decorates the given element by adding any {@code button} elements found
    - * among its descendants to the button set.  The first button found is assumed
    - * to be the default and will receive focus when the button set is rendered.
    - * If a button with a name of {@link goog.ui.Dialog.DefaultButtonKeys.CANCEL}
    - * is found, it is assumed to have "Cancel" semantics.
    - * TODO(attila):  ButtonSet should be a goog.ui.Component.  Really.
    - * @param {Element} element The element to decorate; should contain buttons.
    - */
    -goog.ui.Dialog.ButtonSet.prototype.decorate = function(element) {
    -  if (!element || element.nodeType != goog.dom.NodeType.ELEMENT) {
    -    return;
    -  }
    -
    -  this.element_ = element;
    -  var buttons = this.element_.getElementsByTagName('button');
    -  for (var i = 0, button, key, caption; button = buttons[i]; i++) {
    -    // Buttons should have a "name" attribute and have their caption defined by
    -    // their innerHTML, but not everyone knows this, and we should play nice.
    -    key = button.name || button.id;
    -    caption = goog.dom.getTextContent(button) || button.value;
    -    if (key) {
    -      var isDefault = i == 0;
    -      var isCancel = button.name == goog.ui.Dialog.DefaultButtonKeys.CANCEL;
    -      this.set(key, caption, isDefault, isCancel);
    -      if (isDefault) {
    -        goog.dom.classlist.add(button, goog.getCssName(this.class_,
    -            'default'));
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Gets the component's element.
    - * @return {Element} The element for the component.
    - * TODO(user): Remove after refactoring to goog.ui.Component.
    - */
    -goog.ui.Dialog.ButtonSet.prototype.getElement = function() {
    -  return this.element_;
    -};
    -
    -
    -/**
    - * Returns the dom helper that is being used on this component.
    - * @return {!goog.dom.DomHelper} The dom helper used on this component.
    - * TODO(user): Remove after refactoring to goog.ui.Component.
    - */
    -goog.ui.Dialog.ButtonSet.prototype.getDomHelper = function() {
    -  return this.dom_;
    -};
    -
    -
    -/**
    - * Sets the default button.
    - * @param {?string} key The default button.
    - */
    -goog.ui.Dialog.ButtonSet.prototype.setDefault = function(key) {
    -  this.defaultButton_ = key;
    -};
    -
    -
    -/**
    - * Returns the default button.
    - * @return {?string} The default button.
    - */
    -goog.ui.Dialog.ButtonSet.prototype.getDefault = function() {
    -  return this.defaultButton_;
    -};
    -
    -
    -/**
    - * Sets the cancel button.
    - * @param {?string} key The cancel button.
    - */
    -goog.ui.Dialog.ButtonSet.prototype.setCancel = function(key) {
    -  this.cancelButton_ = key;
    -};
    -
    -
    -/**
    - * Returns the cancel button.
    - * @return {?string} The cancel button.
    - */
    -goog.ui.Dialog.ButtonSet.prototype.getCancel = function() {
    -  return this.cancelButton_;
    -};
    -
    -
    -/**
    - * Returns the HTML Button element.
    - * @param {string} key The button to return.
    - * @return {Element} The button, if found else null.
    - */
    -goog.ui.Dialog.ButtonSet.prototype.getButton = function(key) {
    -  var buttons = this.getAllButtons();
    -  for (var i = 0, nextButton; nextButton = buttons[i]; i++) {
    -    if (nextButton.name == key || nextButton.id == key) {
    -      return nextButton;
    -    }
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * Returns all the HTML Button elements in the button set container.
    - * @return {!NodeList} A live NodeList of the buttons.
    - */
    -goog.ui.Dialog.ButtonSet.prototype.getAllButtons = function() {
    -  return this.element_.getElementsByTagName(goog.dom.TagName.BUTTON);
    -};
    -
    -
    -/**
    - * Enables or disables a button in this set by key. If the button is not found,
    - * does nothing.
    - * @param {string} key The button to enable or disable.
    - * @param {boolean} enabled True to enable; false to disable.
    - */
    -goog.ui.Dialog.ButtonSet.prototype.setButtonEnabled = function(key, enabled) {
    -  var button = this.getButton(key);
    -  if (button) {
    -    button.disabled = !enabled;
    -  }
    -};
    -
    -
    -/**
    - * Enables or disables all of the buttons in this set.
    - * @param {boolean} enabled True to enable; false to disable.
    - */
    -goog.ui.Dialog.ButtonSet.prototype.setAllButtonsEnabled = function(enabled) {
    -  var allButtons = this.getAllButtons();
    -  for (var i = 0, button; button = allButtons[i]; i++) {
    -    button.disabled = !enabled;
    -  }
    -};
    -
    -
    -/**
    - * The keys used to identify standard buttons in events.
    - * @enum {string}
    - */
    -goog.ui.Dialog.DefaultButtonKeys = {
    -  OK: 'ok',
    -  CANCEL: 'cancel',
    -  YES: 'yes',
    -  NO: 'no',
    -  SAVE: 'save',
    -  CONTINUE: 'continue'
    -};
    -
    -
    -/**
    - * @desc Standard caption for the dialog 'OK' button.
    - * @private
    - */
    -goog.ui.Dialog.MSG_DIALOG_OK_ = goog.getMsg('OK');
    -
    -
    -/**
    - * @desc Standard caption for the dialog 'Cancel' button.
    - * @private
    - */
    -goog.ui.Dialog.MSG_DIALOG_CANCEL_ = goog.getMsg('Cancel');
    -
    -
    -/**
    - * @desc Standard caption for the dialog 'Yes' button.
    - * @private
    - */
    -goog.ui.Dialog.MSG_DIALOG_YES_ = goog.getMsg('Yes');
    -
    -
    -/**
    - * @desc Standard caption for the dialog 'No' button.
    - * @private
    - */
    -goog.ui.Dialog.MSG_DIALOG_NO_ = goog.getMsg('No');
    -
    -
    -/**
    - * @desc Standard caption for the dialog 'Save' button.
    - * @private
    - */
    -goog.ui.Dialog.MSG_DIALOG_SAVE_ = goog.getMsg('Save');
    -
    -
    -/**
    - * @desc Standard caption for the dialog 'Continue' button.
    - * @private
    - */
    -goog.ui.Dialog.MSG_DIALOG_CONTINUE_ = goog.getMsg('Continue');
    -
    -
    -/**
    - * @desc Standard label for the dialog 'X' (close) button.
    - * @private
    - */
    -goog.ui.Dialog.MSG_GOOG_UI_DIALOG_CLOSE_ = goog.getMsg('Close');
    -
    -
    -/**
    - * The default captions for the default buttons.
    - * @enum {string}
    - */
    -goog.ui.Dialog.DefaultButtonCaptions = {
    -  OK: goog.ui.Dialog.MSG_DIALOG_OK_,
    -  CANCEL: goog.ui.Dialog.MSG_DIALOG_CANCEL_,
    -  YES: goog.ui.Dialog.MSG_DIALOG_YES_,
    -  NO: goog.ui.Dialog.MSG_DIALOG_NO_,
    -  SAVE: goog.ui.Dialog.MSG_DIALOG_SAVE_,
    -  CONTINUE: goog.ui.Dialog.MSG_DIALOG_CONTINUE_
    -};
    -
    -
    -/**
    - * The standard buttons (keys associated with captions).
    - * @enum {{key: string, caption: string}}
    - */
    -goog.ui.Dialog.ButtonSet.DefaultButtons = {
    -  OK: {
    -    key: goog.ui.Dialog.DefaultButtonKeys.OK,
    -    caption: goog.ui.Dialog.DefaultButtonCaptions.OK
    -  },
    -  CANCEL: {
    -    key: goog.ui.Dialog.DefaultButtonKeys.CANCEL,
    -    caption: goog.ui.Dialog.DefaultButtonCaptions.CANCEL
    -  },
    -  YES: {
    -    key: goog.ui.Dialog.DefaultButtonKeys.YES,
    -    caption: goog.ui.Dialog.DefaultButtonCaptions.YES
    -  },
    -  NO: {
    -    key: goog.ui.Dialog.DefaultButtonKeys.NO,
    -    caption: goog.ui.Dialog.DefaultButtonCaptions.NO
    -  },
    -  SAVE: {
    -    key: goog.ui.Dialog.DefaultButtonKeys.SAVE,
    -    caption: goog.ui.Dialog.DefaultButtonCaptions.SAVE
    -  },
    -  CONTINUE: {
    -    key: goog.ui.Dialog.DefaultButtonKeys.CONTINUE,
    -    caption: goog.ui.Dialog.DefaultButtonCaptions.CONTINUE
    -  }
    -};
    -
    -
    -/**
    - * Creates a new ButtonSet with a single 'OK' button, which is also set with
    - * cancel button semantics so that pressing escape will close the dialog.
    - * @return {!goog.ui.Dialog.ButtonSet} The created ButtonSet.
    - */
    -goog.ui.Dialog.ButtonSet.createOk = function() {
    -  return new goog.ui.Dialog.ButtonSet().
    -      addButton(goog.ui.Dialog.ButtonSet.DefaultButtons.OK, true, true);
    -};
    -
    -
    -/**
    - * Creates a new ButtonSet with 'OK' (default) and 'Cancel' buttons.
    - * @return {!goog.ui.Dialog.ButtonSet} The created ButtonSet.
    - */
    -goog.ui.Dialog.ButtonSet.createOkCancel = function() {
    -  return new goog.ui.Dialog.ButtonSet().
    -      addButton(goog.ui.Dialog.ButtonSet.DefaultButtons.OK, true).
    -      addButton(goog.ui.Dialog.ButtonSet.DefaultButtons.CANCEL, false, true);
    -};
    -
    -
    -/**
    - * Creates a new ButtonSet with 'Yes' (default) and 'No' buttons.
    - * @return {!goog.ui.Dialog.ButtonSet} The created ButtonSet.
    - */
    -goog.ui.Dialog.ButtonSet.createYesNo = function() {
    -  return new goog.ui.Dialog.ButtonSet().
    -      addButton(goog.ui.Dialog.ButtonSet.DefaultButtons.YES, true).
    -      addButton(goog.ui.Dialog.ButtonSet.DefaultButtons.NO, false, true);
    -};
    -
    -
    -/**
    - * Creates a new ButtonSet with 'Yes', 'No' (default), and 'Cancel' buttons.
    - * @return {!goog.ui.Dialog.ButtonSet} The created ButtonSet.
    - */
    -goog.ui.Dialog.ButtonSet.createYesNoCancel = function() {
    -  return new goog.ui.Dialog.ButtonSet().
    -      addButton(goog.ui.Dialog.ButtonSet.DefaultButtons.YES).
    -      addButton(goog.ui.Dialog.ButtonSet.DefaultButtons.NO, true).
    -      addButton(goog.ui.Dialog.ButtonSet.DefaultButtons.CANCEL, false, true);
    -};
    -
    -
    -/**
    - * Creates a new ButtonSet with 'Continue', 'Save', and 'Cancel' (default)
    - * buttons.
    - * @return {!goog.ui.Dialog.ButtonSet} The created ButtonSet.
    - */
    -goog.ui.Dialog.ButtonSet.createContinueSaveCancel = function() {
    -  return new goog.ui.Dialog.ButtonSet().
    -      addButton(goog.ui.Dialog.ButtonSet.DefaultButtons.CONTINUE).
    -      addButton(goog.ui.Dialog.ButtonSet.DefaultButtons.SAVE).
    -      addButton(goog.ui.Dialog.ButtonSet.DefaultButtons.CANCEL, true, true);
    -};
    -
    -
    -// TODO(user): These shared instances should be phased out.
    -(function() {
    -  if (typeof document != 'undefined') {
    -    /** @deprecated Use goog.ui.Dialog.ButtonSet#createOk. */
    -    goog.ui.Dialog.ButtonSet.OK = goog.ui.Dialog.ButtonSet.createOk();
    -
    -    /** @deprecated Use goog.ui.Dialog.ButtonSet#createOkCancel. */
    -    goog.ui.Dialog.ButtonSet.OK_CANCEL =
    -        goog.ui.Dialog.ButtonSet.createOkCancel();
    -
    -    /** @deprecated Use goog.ui.Dialog.ButtonSet#createYesNo. */
    -    goog.ui.Dialog.ButtonSet.YES_NO = goog.ui.Dialog.ButtonSet.createYesNo();
    -
    -    /** @deprecated Use goog.ui.Dialog.ButtonSet#createYesNoCancel. */
    -    goog.ui.Dialog.ButtonSet.YES_NO_CANCEL =
    -        goog.ui.Dialog.ButtonSet.createYesNoCancel();
    -
    -    /** @deprecated Use goog.ui.Dialog.ButtonSet#createContinueSaveCancel. */
    -    goog.ui.Dialog.ButtonSet.CONTINUE_SAVE_CANCEL =
    -        goog.ui.Dialog.ButtonSet.createContinueSaveCancel();
    -  }
    -})();
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/dialog_test.html b/src/database/third_party/closure-library/closure/goog/ui/dialog_test.html
    deleted file mode 100644
    index 99697c58b5f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/dialog_test.html
    +++ /dev/null
    @@ -1,26 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.Dialog
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.DialogTest');
    -  </script>
    - </head>
    - <body>
    -  <iframe id="f" src="javascript:'&lt;input&gt;'">
    -   <input />
    -   '">
    -  </iframe>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/dialog_test.js b/src/database/third_party/closure-library/closure/goog/ui/dialog_test.js
    deleted file mode 100644
    index 8f9221172f1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/dialog_test.js
    +++ /dev/null
    @@ -1,844 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.DialogTest');
    -goog.setTestOnly('goog.ui.DialogTest');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.fx.css3');
    -goog.require('goog.html.SafeHtml');
    -goog.require('goog.html.testing');
    -goog.require('goog.style');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -goog.require('goog.ui.Dialog');
    -goog.require('goog.userAgent');
    -var bodyChildElement;
    -var decorateTarget;
    -var dialog;
    -var mockClock;
    -var stubs = new goog.testing.PropertyReplacer();
    -
    -function setUp() {
    -  mockClock = new goog.testing.MockClock(true);
    -  bodyChildElement = document.createElement('div');
    -  document.body.appendChild(bodyChildElement);
    -  dialog = new goog.ui.Dialog();
    -  var buttons = new goog.ui.Dialog.ButtonSet();
    -  buttons.set(goog.ui.Dialog.DefaultButtonKeys.CANCEL,
    -      'Foo!',
    -      false,
    -      true);
    -  buttons.set(goog.ui.Dialog.DefaultButtonKeys.OK,
    -      'OK',
    -      true);
    -  dialog.setButtonSet(buttons);
    -  dialog.setVisible(true);
    -
    -  decorateTarget = goog.dom.createDom('div');
    -  document.body.appendChild(decorateTarget);
    -
    -  // Reset global flags to their defaults.
    -  /** @suppress {missingRequire} */
    -  stubs.set(goog.html.legacyconversions, 'ALLOW_LEGACY_CONVERSIONS', true);
    -}
    -
    -function tearDown() {
    -  dialog.dispose();
    -  goog.dom.removeNode(bodyChildElement);
    -  goog.dom.removeNode(decorateTarget);
    -  mockClock.dispose();
    -}
    -
    -function testCrossFrameFocus() {
    -  // Firefox (3.6, maybe future versions) fails this test when there are too
    -  // many other test files being run concurrently.
    -  if (goog.userAgent.IE || goog.userAgent.GECKO) {
    -    return;
    -  }
    -  dialog.setVisible(false);
    -  var iframeWindow = goog.dom.getElement('f').contentWindow;
    -  var iframeInput = iframeWindow.document.getElementsByTagName('input')[0];
    -  dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK);
    -  var dialogElement = dialog.getElement();
    -  var focusCounter = 0;
    -  goog.events.listen(dialogElement, 'focus', function() {
    -    focusCounter++;
    -  });
    -  iframeInput.focus();
    -  dialog.setVisible(true);
    -  dialog.setVisible(false);
    -  iframeInput.focus();
    -  dialog.setVisible(true);
    -  assertEquals(2, focusCounter);
    -}
    -
    -function testNoDisabledButtonFocus() {
    -  dialog.setVisible(false);
    -  var buttonEl =
    -      dialog.getButtonSet().getButton(goog.ui.Dialog.DefaultButtonKeys.OK);
    -  buttonEl.disabled = true;
    -  var focused = false;
    -  buttonEl.focus = function() {
    -    focused = true;
    -  };
    -  dialog.setVisible(true);
    -  assertFalse('Should not have called focus on disabled button', focused);
    -}
    -
    -function testNoTitleClose() {
    -  assertTrue(goog.style.isElementShown(dialog.getTitleCloseElement()));
    -  dialog.setHasTitleCloseButton(false);
    -  assertFalse(goog.style.isElementShown(dialog.getTitleCloseElement()));
    -}
    -
    -
    -/**
    - * Helper that clicks the first button in the dialog and checks if that
    - * results in a goog.ui.Dialog.EventType.SELECT being dispatched.
    - * @param {boolean} disableButton Whether to disable the button being
    - *     tested.
    - * @return {boolean} Whether a goog.ui.Dialog.EventType.SELECT was dispatched.
    - */
    -function checkSelectDispatchedOnButtonClick(disableButton) {
    -  var aButton = dialog.getButtonElement().getElementsByTagName('BUTTON')[0];
    -  assertNotEquals(aButton, null);
    -  aButton.disabled = disableButton;
    -  var wasCalled = false;
    -  var callRecorder = function() { wasCalled = true; };
    -  goog.events.listen(dialog, goog.ui.Dialog.EventType.SELECT, callRecorder);
    -  goog.testing.events.fireClickSequence(aButton);
    -  return wasCalled;
    -}
    -
    -function testButtonClicksDispatchSelectEvents() {
    -  assertTrue('Select event should be dispatched' +
    -             ' when clicking on an enabled button',
    -      checkSelectDispatchedOnButtonClick(false));
    -}
    -
    -function testDisabledButtonClicksDontDispatchSelectEvents() {
    -  assertFalse('Select event should not be dispatched' +
    -              ' when clicking on a disabled button',
    -      checkSelectDispatchedOnButtonClick(true));
    -}
    -
    -function testEnterKeyDispatchesDefaultSelectEvents() {
    -  var okButton = dialog.getButtonElement().getElementsByTagName('BUTTON')[1];
    -  assertNotEquals(okButton, null);
    -  var wasCalled = false;
    -  var callRecorder = function() { wasCalled = true; };
    -  goog.events.listen(dialog, goog.ui.Dialog.EventType.SELECT, callRecorder);
    -  // Test that event is not dispatched when default button is disabled.
    -  okButton.disabled = true;
    -  goog.testing.events.fireKeySequence(dialog.getElement(),
    -                                      goog.events.KeyCodes.ENTER);
    -  assertFalse(wasCalled);
    -  // Test that event is dispatched when default button is enabled.
    -  okButton.disabled = false;
    -  goog.testing.events.fireKeySequence(dialog.getElement(),
    -                                      goog.events.KeyCodes.ENTER);
    -  assertTrue(wasCalled);
    -}
    -
    -function testEnterKeyOnDisabledDefaultButtonDoesNotDispatchSelectEvents() {
    -  var okButton = dialog.getButtonElement().getElementsByTagName('BUTTON')[1];
    -  okButton.focus();
    -
    -  var callRecorder = goog.testing.recordFunction();
    -  goog.events.listen(dialog, goog.ui.Dialog.EventType.SELECT, callRecorder);
    -
    -  okButton.disabled = true;
    -  goog.testing.events.fireKeySequence(okButton, goog.events.KeyCodes.ENTER);
    -  assertEquals(0, callRecorder.getCallCount());
    -
    -  okButton.disabled = false;
    -  goog.testing.events.fireKeySequence(okButton, goog.events.KeyCodes.ENTER);
    -  assertEquals(1, callRecorder.getCallCount());
    -}
    -
    -function testEnterKeyDoesNothingOnSpecialFormElements() {
    -  checkEnterKeyDoesNothingOnSpecialFormElement(
    -      '<textarea>Hello dialog</textarea>',
    -      'TEXTAREA');
    -
    -  checkEnterKeyDoesNothingOnSpecialFormElement(
    -      '<select>Selection</select>',
    -      'SELECT');
    -
    -  checkEnterKeyDoesNothingOnSpecialFormElement(
    -      '<a href="http://google.com">Hello dialog</a>',
    -      'A');
    -}
    -
    -function checkEnterKeyDoesNothingOnSpecialFormElement(content, tagName) {
    -  // TODO(user): Switch to setSafeHtmlContent here and elsewhere.
    -  dialog.setContent(content);
    -  var formElement = dialog.getContentElement().
    -      getElementsByTagName(tagName)[0];
    -  var wasCalled = false;
    -  var callRecorder = function() {
    -    wasCalled = true;
    -  };
    -  goog.events.listen(dialog, goog.ui.Dialog.EventType.SELECT, callRecorder);
    -
    -  // Enter does not fire on the enabled form element.
    -  goog.testing.events.fireKeySequence(formElement,
    -      goog.events.KeyCodes.ENTER);
    -  assertFalse(wasCalled);
    -
    -  // Enter fires on the disabled form element.
    -  formElement.disabled = true;
    -  goog.testing.events.fireKeySequence(formElement,
    -      goog.events.KeyCodes.ENTER);
    -  assertTrue(wasCalled);
    -}
    -
    -function testEscapeKeyDoesNothingOnSpecialFormElements() {
    -  dialog.setContent('<select><option>Hello</option>' +
    -      '<option>dialog</option></select>');
    -  var select = dialog.getContentElement().
    -      getElementsByTagName('SELECT')[0];
    -  var wasCalled = false;
    -  var callRecorder = function() {
    -    wasCalled = true;
    -  };
    -  goog.events.listen(dialog, goog.ui.Dialog.EventType.SELECT, callRecorder);
    -
    -  // Escape does not fire on the enabled select box.
    -  goog.testing.events.fireKeySequence(select,
    -      goog.events.KeyCodes.ESC);
    -  assertFalse(wasCalled);
    -
    -  // Escape fires on the disabled select.
    -  select.disabled = true;
    -  goog.testing.events.fireKeySequence(select,
    -      goog.events.KeyCodes.ESC);
    -  assertTrue(wasCalled);
    -}
    -
    -function testEscapeCloses() {
    -  // If escapeCloses is set to false, the dialog should ignore the escape key
    -  assertTrue(dialog.isEscapeToCancel());
    -  dialog.setEscapeToCancel(false);
    -  assertFalse(dialog.isEscapeToCancel());
    -
    -  var buttons = new goog.ui.Dialog.ButtonSet();
    -  buttons.set(goog.ui.Dialog.DefaultButtonKeys.OK, 'OK', true);
    -  dialog.setButtonSet(buttons);
    -  goog.testing.events.fireKeySequence(dialog.getContentElement(),
    -      goog.events.KeyCodes.ESC);
    -  assertTrue(dialog.isVisible());
    -
    -  // Having a cancel button should make no difference, escape should still not
    -  // work.
    -  buttons.set(goog.ui.Dialog.DefaultButtonKeys.CANCEL, 'Foo!', false, true);
    -  dialog.setButtonSet(buttons);
    -  goog.testing.events.fireKeySequence(dialog.getContentElement(),
    -      goog.events.KeyCodes.ESC);
    -  assertTrue(dialog.isVisible());
    -}
    -
    -function testKeydownClosesWithoutButtonSet() {
    -  // Clear button set
    -  dialog.setButtonSet(null);
    -
    -  // Create a custom button.
    -  dialog.setContent('<button id="button" name="ok">OK</button>');
    -  var wasCalled = false;
    -  function called() {
    -    wasCalled = true;
    -  }
    -  var element = goog.dom.getElement('button');
    -  goog.events.listen(element, goog.events.EventType.KEYPRESS, called);
    -  // Listen for 'Enter' on the button.
    -  // This tests using a dialog with no ButtonSet that has been set. Uses
    -  // a custom button.  The callback should be called with no exception thrown.
    -  goog.testing.events.fireKeySequence(element, goog.events.KeyCodes.ENTER);
    -  assertTrue('Should have gotten event on the button.', wasCalled);
    -}
    -
    -function testEnterKeyWithoutDefaultDoesNotPreventPropagation() {
    -  var buttons = new goog.ui.Dialog.ButtonSet();
    -  buttons.set(goog.ui.Dialog.DefaultButtonKeys.CANCEL,
    -      'Foo!',
    -      false);
    -  // Set a button set without a default selected button
    -  dialog.setButtonSet(buttons);
    -  dialog.setContent('<span id="linkel" tabindex="0">Link Span</span>');
    -
    -  var call = false;
    -  function called() {
    -    call = true;
    -  }
    -  var element = document.getElementById('linkel');
    -  goog.events.listen(element, goog.events.EventType.KEYDOWN, called);
    -  goog.testing.events.fireKeySequence(element, goog.events.KeyCodes.ENTER);
    -
    -  assertTrue('Should have gotten event on the link', call);
    -}
    -
    -function testPreventDefaultedSelectCausesStopPropagation() {
    -  dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK_CANCEL);
    -
    -  var callCount = 0;
    -  var keypressCount = 0;
    -  var keydownCount = 0;
    -
    -  var preventDefaulter = function(e) {
    -    e.preventDefault();
    -  };
    -
    -  goog.events.listen(
    -      dialog, goog.ui.Dialog.EventType.SELECT, preventDefaulter);
    -  goog.events.listen(
    -      document.body, goog.events.EventType.KEYPRESS, function() {
    -        keypressCount++;
    -      });
    -  goog.events.listen(
    -      document.body, goog.events.EventType.KEYDOWN, function() {
    -        keydownCount++;
    -      });
    -
    -  // Ensure that if the SELECT event is prevented, all key events
    -  // are still stopped from propagating.
    -  goog.testing.events.fireKeySequence(
    -      dialog.getElement(), goog.events.KeyCodes.ENTER);
    -  assertEquals('The KEYPRESS should be stopped', 0, keypressCount);
    -  assertEquals('The KEYDOWN should not be stopped', 1, keydownCount);
    -
    -  keypressCount = 0;
    -  keydownCount = 0;
    -  goog.testing.events.fireKeySequence(
    -      dialog.getElement(), goog.events.KeyCodes.ESC);
    -  assertEquals('The KEYDOWN should be stopped', 0, keydownCount);
    -  // Note: Some browsers don't yield keypresses on escape, so don't check.
    -
    -  goog.events.unlisten(
    -      dialog, goog.ui.Dialog.EventType.SELECT, preventDefaulter);
    -
    -  keypressCount = 0;
    -  keydownCount = 0;
    -  goog.testing.events.fireKeySequence(
    -      dialog.getElement(), goog.events.KeyCodes.ENTER);
    -  assertEquals('The KEYPRESS should be stopped', 0, keypressCount);
    -  assertEquals('The KEYDOWN should not be stopped', 1, keydownCount);
    -}
    -
    -function testEnterKeyHandledInKeypress() {
    -  var inKeyPress = false;
    -  goog.events.listen(
    -      document.body, goog.events.EventType.KEYPRESS,
    -      function() {
    -        inKeyPress = true;
    -      }, true /* capture */);
    -  goog.events.listen(
    -      document.body, goog.events.EventType.KEYPRESS,
    -      function() {
    -        inKeyPress = false;
    -      }, false /* !capture */);
    -  var selectCalled = false;
    -  goog.events.listen(
    -      dialog, goog.ui.Dialog.EventType.SELECT, function() {
    -        selectCalled = true;
    -        assertTrue(
    -            'Select must be dispatched during keypress to allow popups',
    -            inKeyPress);
    -      });
    -
    -  goog.testing.events.fireKeySequence(
    -      dialog.getElement(), goog.events.KeyCodes.ENTER);
    -  assertTrue(selectCalled);
    -}
    -
    -function testShiftTabAtTopSetsUpWrapAndDoesNotPreventPropagation() {
    -  dialog.setupBackwardTabWrap = goog.testing.recordFunction();
    -  shiftTabRecorder = goog.testing.recordFunction();
    -
    -  goog.events.listen(
    -      dialog.getElement(), goog.events.EventType.KEYDOWN, shiftTabRecorder);
    -  var shiftProperties = { shiftKey: true };
    -  goog.testing.events.fireKeySequence(
    -      dialog.getElement(), goog.events.KeyCodes.TAB, shiftProperties);
    -
    -  assertNotNull('Should have gotten event on Shift+TAB',
    -      shiftTabRecorder.getLastCall());
    -  assertNotNull('Backward tab wrap should have been set up',
    -      dialog.setupBackwardTabWrap.getLastCall());
    -}
    -
    -function testButtonsWithContentsDispatchSelectEvents() {
    -  var aButton = dialog.getButtonElement().getElementsByTagName('BUTTON')[0];
    -  var aSpan = document.createElement('SPAN');
    -  aButton.appendChild(aSpan);
    -  var wasCalled = false;
    -  var callRecorder = function() { wasCalled = true; };
    -  goog.events.listen(dialog, goog.ui.Dialog.EventType.SELECT, callRecorder);
    -  goog.testing.events.fireClickSequence(aSpan);
    -  assertTrue(wasCalled);
    -}
    -
    -function testAfterHideEvent() {
    -  var wasCalled = false;
    -  var callRecorder = function() { wasCalled = true; };
    -  goog.events.listen(dialog, goog.ui.Dialog.EventType.AFTER_HIDE,
    -      callRecorder);
    -  dialog.setVisible(false);
    -  assertTrue(wasCalled);
    -}
    -
    -function testAfterShowEvent() {
    -  dialog.setVisible(false);
    -  var wasCalled = false;
    -  var callRecorder = function() { wasCalled = true; };
    -  goog.events.listen(dialog, goog.ui.Dialog.EventType.AFTER_SHOW,
    -      callRecorder);
    -  dialog.setVisible(true);
    -  assertTrue(wasCalled);
    -}
    -
    -function testCannedButtonSets() {
    -  dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK);
    -  assertButtons([goog.ui.Dialog.DefaultButtonKeys.OK]);
    -
    -  dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK_CANCEL);
    -  assertButtons([goog.ui.Dialog.DefaultButtonKeys.OK,
    -                 goog.ui.Dialog.DefaultButtonKeys.CANCEL]);
    -
    -  dialog.setButtonSet(goog.ui.Dialog.ButtonSet.YES_NO);
    -  assertButtons([goog.ui.Dialog.DefaultButtonKeys.YES,
    -                 goog.ui.Dialog.DefaultButtonKeys.NO]);
    -
    -  dialog.setButtonSet(goog.ui.Dialog.ButtonSet.YES_NO_CANCEL);
    -  assertButtons([goog.ui.Dialog.DefaultButtonKeys.YES,
    -                 goog.ui.Dialog.DefaultButtonKeys.NO,
    -                 goog.ui.Dialog.DefaultButtonKeys.CANCEL]);
    -
    -  dialog.setButtonSet(goog.ui.Dialog.ButtonSet.CONTINUE_SAVE_CANCEL);
    -  assertButtons([goog.ui.Dialog.DefaultButtonKeys.CONTINUE,
    -                 goog.ui.Dialog.DefaultButtonKeys.SAVE,
    -                 goog.ui.Dialog.DefaultButtonKeys.CANCEL]);
    -}
    -
    -function testFactoryButtonSets() {
    -  dialog.setButtonSet(goog.ui.Dialog.ButtonSet.createOk());
    -  assertButtons([goog.ui.Dialog.DefaultButtonKeys.OK]);
    -
    -  dialog.setButtonSet(goog.ui.Dialog.ButtonSet.createOkCancel());
    -  assertButtons([goog.ui.Dialog.DefaultButtonKeys.OK,
    -                 goog.ui.Dialog.DefaultButtonKeys.CANCEL]);
    -
    -  dialog.setButtonSet(goog.ui.Dialog.ButtonSet.createYesNo());
    -  assertButtons([goog.ui.Dialog.DefaultButtonKeys.YES,
    -                 goog.ui.Dialog.DefaultButtonKeys.NO]);
    -
    -  dialog.setButtonSet(goog.ui.Dialog.ButtonSet.createYesNoCancel());
    -  assertButtons([goog.ui.Dialog.DefaultButtonKeys.YES,
    -                 goog.ui.Dialog.DefaultButtonKeys.NO,
    -                 goog.ui.Dialog.DefaultButtonKeys.CANCEL]);
    -
    -  dialog.setButtonSet(goog.ui.Dialog.ButtonSet.createContinueSaveCancel());
    -  assertButtons([goog.ui.Dialog.DefaultButtonKeys.CONTINUE,
    -                 goog.ui.Dialog.DefaultButtonKeys.SAVE,
    -                 goog.ui.Dialog.DefaultButtonKeys.CANCEL]);
    -}
    -
    -function testDefaultButtonClassName() {
    -  var key = 'someKey';
    -  var msg = 'someMessage';
    -  var isDefault = false;
    -  var buttonSetOne = new goog.ui.Dialog.ButtonSet().set(key, msg, isDefault);
    -  dialog.setButtonSet(buttonSetOne);
    -  var defaultClassName = goog.getCssName(buttonSetOne.class_, 'default');
    -  var buttonOne = buttonSetOne.getButton(key);
    -  assertNotEquals(defaultClassName, buttonOne.className);
    -  var isDefault = true;
    -  var buttonSetTwo = new goog.ui.Dialog.ButtonSet().set(key, msg, isDefault);
    -  dialog.setButtonSet(buttonSetTwo);
    -  var buttonTwo = buttonSetTwo.getButton(key);
    -  assertEquals(defaultClassName, buttonTwo.className);
    -}
    -
    -function testGetButton() {
    -  dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK);
    -  var buttons = document.getElementsByName(
    -      goog.ui.Dialog.DefaultButtonKeys.OK);
    -  assertEquals(buttons[0], dialog.getButtonSet().getButton(
    -      goog.ui.Dialog.DefaultButtonKeys.OK));
    -}
    -
    -function testGetAllButtons() {
    -  dialog.setButtonSet(goog.ui.Dialog.ButtonSet.YES_NO_CANCEL);
    -  var buttons = dialog.getElement().getElementsByTagName(
    -      goog.dom.TagName.BUTTON);
    -  for (var i = 0; i < buttons.length; i++) {
    -    assertEquals(buttons[i], dialog.getButtonSet().getAllButtons()[i]);
    -  }
    -}
    -
    -function testSetButtonEnabled() {
    -  var buttonSet = goog.ui.Dialog.ButtonSet.createYesNoCancel();
    -  dialog.setButtonSet(buttonSet);
    -  assertFalse(
    -      buttonSet.getButton(goog.ui.Dialog.DefaultButtonKeys.NO).disabled);
    -  buttonSet.setButtonEnabled(goog.ui.Dialog.DefaultButtonKeys.NO, false);
    -  assertTrue(
    -      buttonSet.getButton(goog.ui.Dialog.DefaultButtonKeys.NO).disabled);
    -  buttonSet.setButtonEnabled(goog.ui.Dialog.DefaultButtonKeys.NO, true);
    -  assertFalse(
    -      buttonSet.getButton(goog.ui.Dialog.DefaultButtonKeys.NO).disabled);
    -}
    -
    -function testSetAllButtonsEnabled() {
    -  var buttonSet = goog.ui.Dialog.ButtonSet.createContinueSaveCancel();
    -  dialog.setButtonSet(buttonSet);
    -  var buttons = buttonSet.getAllButtons();
    -  for (var i = 0; i < buttons.length; i++) {
    -    assertFalse(buttons[i].disabled);
    -  }
    -
    -  buttonSet.setAllButtonsEnabled(false);
    -  for (var i = 0; i < buttons.length; i++) {
    -    assertTrue(buttons[i].disabled);
    -  }
    -
    -  buttonSet.setAllButtonsEnabled(true);
    -  for (var i = 0; i < buttons.length; i++) {
    -    assertFalse(buttons[i].disabled);
    -  }
    -}
    -
    -function testIframeMask() {
    -  var prevNumFrames =
    -      goog.dom.getElementsByTagNameAndClass(goog.dom.TagName.IFRAME).length;
    -  // generate a new dialog
    -  dialog.dispose();
    -  dialog = new goog.ui.Dialog(null, true /* iframe mask */);
    -  dialog.setVisible(true);
    -
    -  // Test that the dialog added one iframe to the document.
    -  // The absolute number of iframes should not be tested because,
    -  // in certain cases, the test runner itself can can add an iframe
    -  // to the document as part of a strategy not to block the UI for too long.
    -  // See goog.async.nextTick.getSetImmediateEmulator_.
    -  var curNumFrames =
    -      goog.dom.getElementsByTagNameAndClass(goog.dom.TagName.IFRAME).length;
    -  assertEquals(
    -      'No iframe mask created', prevNumFrames + 1, curNumFrames);
    -}
    -
    -function testNonModalDialog() {
    -  var prevNumFrames =
    -      goog.dom.getElementsByTagNameAndClass(goog.dom.TagName.IFRAME).length;
    -  // generate a new dialog
    -  dialog.dispose();
    -  dialog = new goog.ui.Dialog(null, true /* iframe mask */);
    -  dialog.setModal(false);
    -  assertAriaHidden(false);
    -  dialog.setVisible(true);
    -  assertAriaHidden(true);
    -
    -  // Test that the dialog did not change the number of iframes in the document.
    -  // The absolute number of iframes should not be tested because,
    -  // in certain cases, the test runner itself can can add an iframe
    -  // to the document as part of a strategy not to block the UI for too long.
    -  // See goog.async.nextTick.getSetImmediateEmulator_.
    -  var curNumFrames =
    -      goog.dom.getElementsByTagNameAndClass(goog.dom.TagName.IFRAME).length;
    -  assertEquals(
    -      'Iframe mask created for modal dialog', prevNumFrames, curNumFrames);
    -}
    -
    -function testSwapModalForOpenDialog() {
    -  dialog.dispose();
    -  dialog = new goog.ui.Dialog(null, true /* iframe mask */);
    -  assertAriaHidden(false);
    -  dialog.setVisible(true);
    -  assertAriaHidden(true);
    -  dialog.setModal(false);
    -  assertAriaHidden(false);
    -  assertFalse('IFrame bg element should not be in dom',
    -      goog.dom.contains(document.body, dialog.getBackgroundIframe()));
    -  assertFalse('bg element should not be in dom',
    -      goog.dom.contains(document.body, dialog.getBackgroundElement()));
    -
    -  dialog.setModal(true);
    -  assertAriaHidden(true);
    -  assertTrue('IFrame bg element should be in dom',
    -      goog.dom.contains(document.body, dialog.getBackgroundIframe()));
    -  assertTrue('bg element should be in dom',
    -      goog.dom.contains(document.body, dialog.getBackgroundElement()));
    -
    -  assertEquals('IFrame bg element is a child of body',
    -      document.body, dialog.getBackgroundIframe().parentNode);
    -  assertEquals('bg element is a child of body',
    -      document.body, dialog.getBackgroundElement().parentNode);
    -
    -  assertTrue('IFrame bg element should visible',
    -      goog.style.isElementShown(dialog.getBackgroundIframe()));
    -  assertTrue('bg element should be visible',
    -      goog.style.isElementShown(dialog.getBackgroundElement()));
    -}
    -
    -
    -/**
    - * Assert that the dialog has buttons with the given keys in the correct
    - * order.
    - * @param {Array<string>} keys An array of button keys.
    - */
    -function assertButtons(keys) {
    -  var buttons = dialog.getElement().getElementsByTagName(
    -      goog.dom.TagName.BUTTON);
    -  var actualKeys = [];
    -  for (var i = 0; i < buttons.length; i++) {
    -    actualKeys[i] = buttons[i].name;
    -  }
    -  assertArrayEquals(keys, actualKeys);
    -}
    -
    -function testButtonSetOkFiresDialogEventOnEscape() {
    -  dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK);
    -  var wasCalled = false;
    -  var callRecorder = function() { wasCalled = true; };
    -  goog.events.listen(dialog, goog.ui.Dialog.EventType.SELECT,
    -      callRecorder);
    -  goog.testing.events.fireKeySequence(
    -      dialog.getElement(), goog.events.KeyCodes.ESC);
    -  assertTrue(wasCalled);
    -}
    -
    -function testHideButtons_afterRender() {
    -  dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK);
    -  assertTrue(goog.style.isElementShown(dialog.buttonEl_));
    -  dialog.setButtonSet(null);
    -  assertFalse(goog.style.isElementShown(dialog.buttonEl_));
    -  dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK);
    -  assertTrue(goog.style.isElementShown(dialog.buttonEl_));
    -}
    -
    -function testHideButtons_beforeRender() {
    -  dialog.dispose();
    -
    -  dialog = new goog.ui.Dialog();
    -  dialog.setButtonSet(null);
    -  dialog.setVisible(true);
    -  assertFalse(goog.style.isElementShown(dialog.buttonEl_));
    -  dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK);
    -  assertTrue(goog.style.isElementShown(dialog.buttonEl_));
    -}
    -
    -function testHideButtons_beforeDecorate() {
    -  dialog.dispose();
    -
    -  dialog = new goog.ui.Dialog();
    -  dialog.setButtonSet(null);
    -  dialog.decorate(decorateTarget);
    -  dialog.setVisible(true);
    -  assertFalse(goog.style.isElementShown(dialog.buttonEl_));
    -  dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK);
    -  assertTrue(goog.style.isElementShown(dialog.buttonEl_));
    -}
    -
    -function testAriaLabelledBy_render() {
    -  dialog.dispose();
    -
    -  dialog = new goog.ui.Dialog();
    -  dialog.render();
    -  assertTrue(!!dialog.getTitleTextElement().id);
    -  assertNotNull(dialog.getElement());
    -  assertEquals(dialog.getTitleTextElement().id,
    -      goog.a11y.aria.getState(dialog.getElement(),
    -          'labelledby'));
    -}
    -
    -function testAriaLabelledBy_decorate() {
    -  dialog.dispose();
    -
    -  dialog = new goog.ui.Dialog();
    -  dialog.decorate(decorateTarget);
    -  dialog.setVisible(true);
    -  assertTrue(!!dialog.getTitleTextElement().id);
    -  assertNotNull(dialog.getElement());
    -  assertEquals(dialog.getTitleTextElement().id,
    -      goog.a11y.aria.getState(dialog.getElement(),
    -          'labelledby'));
    -}
    -
    -
    -function testPreferredAriaRole_renderDefault() {
    -  dialog.dispose();
    -
    -  dialog = new goog.ui.Dialog();
    -  dialog.render();
    -  assertNotNull(dialog.getElement());
    -  assertEquals(dialog.getPreferredAriaRole(),
    -      goog.a11y.aria.getRole(dialog.getElement()));
    -}
    -
    -function testPreferredAriaRole_decorateDefault() {
    -  dialog.dispose();
    -
    -  dialog = new goog.ui.Dialog();
    -  dialog.decorate(decorateTarget);
    -  assertNotNull(dialog.getElement());
    -  assertEquals(dialog.getPreferredAriaRole(),
    -      goog.a11y.aria.getRole(dialog.getElement()));
    -}
    -
    -function testPreferredAriaRole_renderOverride() {
    -  dialog.dispose();
    -
    -  dialog = new goog.ui.Dialog();
    -  dialog.setPreferredAriaRole(goog.a11y.aria.Role.ALERTDIALOG);
    -  dialog.render();
    -  assertNotNull(dialog.getElement());
    -  assertEquals(goog.a11y.aria.Role.ALERTDIALOG,
    -      goog.a11y.aria.getRole(dialog.getElement()));
    -}
    -
    -function testPreferredAriaRole_decorateOverride() {
    -  dialog.dispose();
    -
    -  dialog = new goog.ui.Dialog();
    -  dialog.setPreferredAriaRole(goog.a11y.aria.Role.ALERTDIALOG);
    -  dialog.decorate(decorateTarget);
    -  assertNotNull(dialog.getElement());
    -  assertEquals(goog.a11y.aria.Role.ALERTDIALOG,
    -      goog.a11y.aria.getRole(dialog.getElement()));
    -}
    -
    -function testDefaultOpacityIsAppliedOnRender() {
    -  dialog.dispose();
    -
    -  dialog = new goog.ui.Dialog();
    -  dialog.render();
    -  assertEquals(0.5, goog.style.getOpacity(dialog.getBackgroundElement()));
    -}
    -
    -function testDefaultOpacityIsAppliedOnDecorate() {
    -  dialog.dispose();
    -
    -  dialog = new goog.ui.Dialog();
    -  dialog.decorate(decorateTarget);
    -  assertEquals(0.5, goog.style.getOpacity(dialog.getBackgroundElement()));
    -}
    -
    -function testDraggableStyle() {
    -  assertTrue('draggable CSS class is set', goog.dom.classlist.contains(
    -      dialog.titleEl_, 'modal-dialog-title-draggable'));
    -  dialog.setDraggable(false);
    -  assertFalse('draggable CSS class is removed', goog.dom.classlist.contains(
    -      dialog.titleEl_, 'modal-dialog-title-draggable'));
    -}
    -
    -function testDraggingLifecycle() {
    -  dialog.dispose();
    -
    -  dialog = new goog.ui.Dialog();
    -  dialog.setDraggerLimits_ = goog.testing.recordFunction();
    -  dialog.createDom();
    -  assertNull('dragger is not created in createDom', dialog.dragger_);
    -
    -  dialog.setVisible(true);
    -  assertNotNull('dragger is created when the dialog is rendered',
    -      dialog.dragger_);
    -
    -  assertNull('dragging limits are not set just before dragging',
    -      dialog.setDraggerLimits_.getLastCall());
    -  goog.testing.events.fireMouseDownEvent(dialog.titleEl_);
    -  assertNotNull('dragging limits are set',
    -      dialog.setDraggerLimits_.getLastCall());
    -
    -  dialog.exitDocument();
    -  assertNull('dragger is cleaned up in exitDocument', dialog.dragger_);
    -}
    -
    -function testDisposingVisibleDialogWithTransitionsDoesNotThrowException() {
    -  var transition = goog.fx.css3.fadeIn(dialog.getElement(),
    -      0.1 /* duration */);
    -
    -  dialog.setTransition(transition, transition, transition, transition);
    -  dialog.setVisible(true);
    -  dialog.dispose();
    -  // Nothing to assert. We only want to ensure that there is no error.
    -}
    -
    -function testEventsDuringAnimation() {
    -  dialog.dispose();
    -  dialog = new goog.ui.Dialog();
    -  dialog.render();
    -  dialog.setTransition(
    -      goog.fx.css3.fadeIn(dialog.getElement(), 1),
    -      goog.fx.css3.fadeIn(dialog.getBackgroundElement(), 1),
    -      goog.fx.css3.fadeOut(dialog.getElement(), 1),
    -      goog.fx.css3.fadeOut(dialog.getBackgroundElement(), 1));
    -  dialog.setVisible(true);
    -  assertTrue(dialog.isVisible());
    -
    -  var buttonSet = dialog.getButtonSet();
    -  var button = buttonSet.getButton(buttonSet.getDefault());
    -
    -  // The button event fires while the animation is still going.
    -  goog.testing.events.fireClickSequence(button);
    -  mockClock.tick(2000);
    -  assertFalse(dialog.isVisible());
    -}
    -
    -function testHtmlContent() {
    -  dialog.setSafeHtmlContent(goog.html.testing.newSafeHtmlForTest(
    -      '<span class="theSpan">Hello</span>'));
    -  var spanEl =
    -      goog.dom.getElementByClass('theSpan', dialog.getContentElement());
    -  assertEquals('Hello', goog.dom.getTextContent(spanEl));
    -  assertEquals('<span class="theSpan">Hello</span>', dialog.getContent());
    -  assertEquals('<span class="theSpan">Hello</span>',
    -               goog.html.SafeHtml.unwrap(dialog.getSafeHtmlContent()));
    -}
    -
    -function testSetContent_guardedByGlobalFlag() {
    -  /** @suppress {missingRequire} */
    -  stubs.set(goog.html.legacyconversions, 'ALLOW_LEGACY_CONVERSIONS', false);
    -  assertEquals(
    -      'Error: Legacy conversion from string to goog.html types is disabled',
    -      assertThrows(function() {
    -        dialog.setContent('<img src="blag" onerror="evil();">');
    -      }).message);
    -}
    -
    -function testFocus() {
    -  // Focus should go to the dialog element.
    -  document.body.focus();
    -  dialog.focus();
    -  assertEquals(dialog.getElement(), document.activeElement);
    -}
    -
    -// Asserts that a test element which is a child of the document body has the
    -// aria property 'hidden' set on it, or not.
    -function assertAriaHidden(expectedHidden) {
    -  var expectedString = expectedHidden ? 'true' : '';
    -  assertEquals(expectedString,
    -      goog.a11y.aria.getState(bodyChildElement,
    -          goog.a11y.aria.State.HIDDEN));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/dimensionpicker.js b/src/database/third_party/closure-library/closure/goog/ui/dimensionpicker.js
    deleted file mode 100644
    index 81ff25c41b6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/dimensionpicker.js
    +++ /dev/null
    @@ -1,318 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A dimension picker control.  A dimension picker allows the
    - * user to visually select a row and column count.
    - *
    - * @author robbyw@google.com (Robby Walker)
    - * @see ../demos/dimensionpicker.html
    - * @see ../demos/dimensionpicker_rtl.html
    - */
    -
    -goog.provide('goog.ui.DimensionPicker');
    -
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.math.Size');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.Control');
    -goog.require('goog.ui.DimensionPickerRenderer');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * A dimension picker allows the user to visually select a row and column
    - * count using their mouse and keyboard.
    - *
    - * The currently selected dimension is controlled by an ACTION event.  Event
    - * listeners may retrieve the selected item using the
    - * {@link #getValue} method.
    - *
    - * @param {goog.ui.DimensionPickerRenderer=} opt_renderer Renderer used to
    - *     render or decorate the palette; defaults to
    - *     {@link goog.ui.DimensionPickerRenderer}.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @constructor
    - * @extends {goog.ui.Control}
    - * @final
    - */
    -goog.ui.DimensionPicker = function(opt_renderer, opt_domHelper) {
    -  goog.ui.Control.call(this, null,
    -      opt_renderer || goog.ui.DimensionPickerRenderer.getInstance(),
    -      opt_domHelper);
    -
    -  this.size_ = new goog.math.Size(this.minColumns, this.minRows);
    -};
    -goog.inherits(goog.ui.DimensionPicker, goog.ui.Control);
    -
    -
    -/**
    - * Minimum number of columns to show in the grid.
    - * @type {number}
    - */
    -goog.ui.DimensionPicker.prototype.minColumns = 5;
    -
    -
    -/**
    - * Minimum number of rows to show in the grid.
    - * @type {number}
    - */
    -goog.ui.DimensionPicker.prototype.minRows = 5;
    -
    -
    -/**
    - * Maximum number of columns to show in the grid.
    - * @type {number}
    - */
    -goog.ui.DimensionPicker.prototype.maxColumns = 20;
    -
    -
    -/**
    - * Maximum number of rows to show in the grid.
    - * @type {number}
    - */
    -goog.ui.DimensionPicker.prototype.maxRows = 20;
    -
    -
    -/**
    - * Palette dimensions (columns x rows).
    - * @type {goog.math.Size}
    - * @private
    - */
    -goog.ui.DimensionPicker.prototype.size_;
    -
    -
    -/**
    - * Currently highlighted row count.
    - * @type {number}
    - * @private
    - */
    -goog.ui.DimensionPicker.prototype.highlightedRows_ = 1;
    -
    -
    -/**
    - * Currently highlighted column count.
    - * @type {number}
    - * @private
    - */
    -goog.ui.DimensionPicker.prototype.highlightedColumns_ = 1;
    -
    -
    -/** @override */
    -goog.ui.DimensionPicker.prototype.enterDocument = function() {
    -  goog.ui.DimensionPicker.superClass_.enterDocument.call(this);
    -
    -  var handler = this.getHandler();
    -  handler.
    -      listen(this.getRenderer().getMouseMoveElement(this),
    -          goog.events.EventType.MOUSEMOVE, this.handleMouseMove).
    -      listen(this.getDomHelper().getWindow(), goog.events.EventType.RESIZE,
    -          this.handleWindowResize);
    -
    -  var parent = this.getParent();
    -  if (parent) {
    -    handler.listen(parent, goog.ui.Component.EventType.SHOW, this.handleShow_);
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.DimensionPicker.prototype.exitDocument = function() {
    -  goog.ui.DimensionPicker.superClass_.exitDocument.call(this);
    -
    -  var handler = this.getHandler();
    -  handler.
    -      unlisten(this.getRenderer().getMouseMoveElement(this),
    -          goog.events.EventType.MOUSEMOVE, this.handleMouseMove).
    -      unlisten(this.getDomHelper().getWindow(), goog.events.EventType.RESIZE,
    -          this.handleWindowResize);
    -
    -  var parent = this.getParent();
    -  if (parent) {
    -    handler.unlisten(parent, goog.ui.Component.EventType.SHOW,
    -        this.handleShow_);
    -  }
    -};
    -
    -
    -/**
    - * Resets the highlighted size when the picker is shown.
    - * @private
    - */
    -goog.ui.DimensionPicker.prototype.handleShow_ = function() {
    -  if (this.isVisible()) {
    -    this.setValue(1, 1);
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.DimensionPicker.prototype.disposeInternal = function() {
    -  goog.ui.DimensionPicker.superClass_.disposeInternal.call(this);
    -  delete this.size_;
    -};
    -
    -
    -// Palette event handling.
    -
    -
    -/**
    - * Handles mousemove events.  Determines which palette size was moused over and
    - * highlights it.
    - * @param {goog.events.BrowserEvent} e Mouse event to handle.
    - * @protected
    - */
    -goog.ui.DimensionPicker.prototype.handleMouseMove = function(e) {
    -  var highlightedSizeX = this.getRenderer().getGridOffsetX(this,
    -      this.isRightToLeft() ? e.target.offsetWidth - e.offsetX : e.offsetX);
    -  var highlightedSizeY = this.getRenderer().getGridOffsetY(this, e.offsetY);
    -
    -  this.setValue(highlightedSizeX, highlightedSizeY);
    -};
    -
    -
    -/**
    - * Handles window resize events.  Ensures no scrollbars are introduced by the
    - * renderer's mouse catcher.
    - * @param {goog.events.Event} e Resize event to handle.
    - * @protected
    - */
    -goog.ui.DimensionPicker.prototype.handleWindowResize = function(e) {
    -  this.getRenderer().positionMouseCatcher(this);
    -};
    -
    -
    -/**
    - * Handle key events if supported, so the user can use the keyboard to
    - * manipulate the highlighted rows and columns.
    - * @param {goog.events.KeyEvent} e The key event object.
    - * @return {boolean} Whether the key event was handled.
    - * @override
    - */
    -goog.ui.DimensionPicker.prototype.handleKeyEvent = function(e) {
    -  var rows = this.highlightedRows_;
    -  var columns = this.highlightedColumns_;
    -  switch (e.keyCode) {
    -    case goog.events.KeyCodes.DOWN:
    -      rows++;
    -      break;
    -    case goog.events.KeyCodes.UP:
    -      rows--;
    -      break;
    -    case goog.events.KeyCodes.LEFT:
    -      if (this.isRightToLeft()) {
    -        columns++;
    -      } else {
    -        if (columns == 1) {
    -          // Delegate to parent.
    -          return false;
    -        } else {
    -          columns--;
    -        }
    -      }
    -      break;
    -    case goog.events.KeyCodes.RIGHT:
    -      if (this.isRightToLeft()) {
    -        if (columns == 1) {
    -          // Delegate to parent.
    -          return false;
    -        } else {
    -          columns--;
    -        }
    -      } else {
    -        columns++;
    -      }
    -      break;
    -    default:
    -      return goog.ui.DimensionPicker.superClass_.handleKeyEvent.call(this, e);
    -  }
    -  this.setValue(columns, rows);
    -  return true;
    -};
    -
    -
    -// Palette management.
    -
    -
    -/**
    - * @return {goog.math.Size} Current table size shown (columns x rows).
    - */
    -goog.ui.DimensionPicker.prototype.getSize = function() {
    -  return this.size_;
    -};
    -
    -
    -/**
    - * @return {!goog.math.Size} size The currently highlighted dimensions.
    - */
    -goog.ui.DimensionPicker.prototype.getValue = function() {
    -  return new goog.math.Size(this.highlightedColumns_, this.highlightedRows_);
    -};
    -
    -
    -/**
    - * Sets the currently highlighted dimensions. If the dimensions are not valid
    - * (not between 1 and the maximum number of columns/rows to show), they will
    - * be changed to the closest valid value.
    - * @param {(number|!goog.math.Size)} columns The number of columns to highlight,
    - *     or a goog.math.Size object containing both.
    - * @param {number=} opt_rows The number of rows to highlight.  Can be
    - *     omitted when columns is a good.math.Size object.
    - */
    -goog.ui.DimensionPicker.prototype.setValue = function(columns,
    -    opt_rows) {
    -  if (!goog.isDef(opt_rows)) {
    -    columns = /** @type {!goog.math.Size} */ (columns);
    -    opt_rows = columns.height;
    -    columns = columns.width;
    -  } else {
    -    columns = /** @type {number} */ (columns);
    -  }
    -
    -  // Ensure that the row and column values are within the minimum value (1) and
    -  // maxmimum values.
    -  columns = Math.max(1, columns);
    -  opt_rows = Math.max(1, opt_rows);
    -  columns = Math.min(this.maxColumns, columns);
    -  opt_rows = Math.min(this.maxRows, opt_rows);
    -
    -  if (this.highlightedColumns_ != columns ||
    -      this.highlightedRows_ != opt_rows) {
    -    var renderer = this.getRenderer();
    -    // Show one more row/column than highlighted so the user understands the
    -    // palette can grow.
    -    this.size_.width = Math.max(
    -        Math.min(columns + 1, this.maxColumns), this.minColumns);
    -    this.size_.height = Math.max(
    -        Math.min(opt_rows + 1, this.maxRows), this.minRows);
    -    renderer.updateSize(this, this.getElement());
    -
    -    this.highlightedColumns_ = columns;
    -    this.highlightedRows_ = opt_rows;
    -    renderer.setHighlightedSize(this, columns, opt_rows);
    -  }
    -};
    -
    -
    -/**
    - * Register this control so it can be created from markup
    - */
    -goog.ui.registry.setDecoratorByClassName(
    -    goog.ui.DimensionPickerRenderer.CSS_CLASS,
    -    function() {
    -      return new goog.ui.DimensionPicker();
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/dimensionpicker_test.html b/src/database/third_party/closure-library/closure/goog/ui/dimensionpicker_test.html
    deleted file mode 100644
    index 038626d1261..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/dimensionpicker_test.html
    +++ /dev/null
    @@ -1,29 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -  Author: robbyw@google.com (Robby Walker)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.DimensionPicker
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.ui.DimensionPickerTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="render">
    -  </div>
    -  <div id="decorate">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/dimensionpicker_test.js b/src/database/third_party/closure-library/closure/goog/ui/dimensionpicker_test.js
    deleted file mode 100644
    index bb3cbe3d887..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/dimensionpicker_test.js
    +++ /dev/null
    @@ -1,249 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.DimensionPickerTest');
    -goog.setTestOnly('goog.ui.DimensionPickerTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.math.Size');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.ui.rendererasserts');
    -goog.require('goog.ui.DimensionPicker');
    -goog.require('goog.ui.DimensionPickerRenderer');
    -
    -var picker;
    -var render;
    -var decorate;
    -
    -function setUpPage() {
    -  render = goog.dom.getElement('render');
    -  decorate = goog.dom.getElement('decorate');
    -}
    -
    -function setUp() {
    -  picker = new goog.ui.DimensionPicker();
    -  render.innerHTML = '';
    -  decorate.innerHTML = '';
    -}
    -
    -function tearDown() {
    -  picker.dispose();
    -}
    -
    -function testConstructor() {
    -  assertNotNull('Should have successful construction', picker);
    -  assertNull('Should not be in document', picker.getElement());
    -}
    -
    -function testRender() {
    -  picker.render(render);
    -
    -  assertEquals('Should create 1 child', 1, render.childNodes.length);
    -  assertEquals('Should be a div', goog.dom.TagName.DIV,
    -      render.firstChild.tagName);
    -}
    -
    -function testDecorate() {
    -  picker.decorate(decorate);
    -
    -  assertNotEquals('Should add several children', decorate.firstChild,
    -      decorate.lastChild);
    -}
    -
    -function testHighlightedSize() {
    -  picker.render(render);
    -
    -  var size = picker.getValue();
    -  assertEquals('Should have 1 column highlighted initially.',
    -      1, size.width);
    -  assertEquals('Should have 1 row highlighted initially.',
    -      1, size.height);
    -
    -  picker.setValue(1, 2);
    -  size = picker.getValue();
    -  assertEquals('Should have 1 column highlighted.', 1, size.width);
    -  assertEquals('Should have 2 rows highlighted.', 2, size.height);
    -
    -  picker.setValue(new goog.math.Size(3, 4));
    -  size = picker.getValue();
    -  assertEquals('Should have 3 columns highlighted.', 3, size.width);
    -  assertEquals('Should have 4 rows highlighted.', 4, size.height);
    -
    -  picker.setValue(new goog.math.Size(-3, 0));
    -  size = picker.getValue();
    -  assertEquals('Should have 1 column highlighted when passed a negative ' +
    -      'column value.', 1, size.width);
    -  assertEquals('Should have 1 row highlighted when passed 0 as the row ' +
    -      'value.', 1, size.height);
    -
    -  picker.setValue(picker.maxColumns + 10, picker.maxRows + 2);
    -  size = picker.getValue();
    -  assertEquals('Column value should be decreased to match max columns ' +
    -      'if it is too high.', picker.maxColumns, size.width);
    -  assertEquals('Row value should be decreased to match max rows ' +
    -      'if it is too high.', picker.maxRows, size.height);
    -}
    -
    -function testSizeShown() {
    -  picker.render(render);
    -
    -  var size = picker.getSize();
    -  assertEquals('Should have 5 columns visible', 5, size.width);
    -  assertEquals('Should have 5 rows visible', 5, size.height);
    -
    -  picker.setValue(4, 4);
    -  size = picker.getSize();
    -  assertEquals('Should have 5 columns visible', 5, size.width);
    -  assertEquals('Should have 5 rows visible', 5, size.height);
    -
    -  picker.setValue(12, 13);
    -  size = picker.getSize();
    -  assertEquals('Should have 13 columns visible', 13, size.width);
    -  assertEquals('Should have 14 rows visible', 14, size.height);
    -
    -  picker.setValue(20, 20);
    -  size = picker.getSize();
    -  assertEquals('Should have 20 columns visible', 20, size.width);
    -  assertEquals('Should have 20 rows visible', 20, size.height);
    -
    -  picker.setValue(2, 3);
    -  size = picker.getSize();
    -  assertEquals('Should have 5 columns visible', 5, size.width);
    -  assertEquals('Should have 5 rows visible', 5, size.height);
    -}
    -
    -function testHandleMove() {
    -  picker.render(render);
    -  var renderer = picker.getRenderer();
    -  var mouseMoveElem = renderer.getMouseMoveElement(picker);
    -
    -  picker.rightToLeft_ = false;
    -  var e = {
    -    target: mouseMoveElem,
    -    offsetX: 18, // Each grid square currently a magic 18px.
    -    offsetY: 36
    -  };
    -
    -  picker.handleMouseMove(e);
    -  var size = picker.getValue();
    -  assertEquals('Should have 1 column highlighted', 1, size.width);
    -  assertEquals('Should have 2 rows highlighted', 2, size.height);
    -
    -  picker.rightToLeft_ = true;
    -
    -  picker.handleMouseMove(e);
    -  var size = picker.getValue();
    -  // In RTL we pick from the right side of the picker, so an offsetX of 0
    -  // would actually mean select all columns.
    -  assertEquals('Should have columns to the right of the mouse highlighted',
    -      Math.ceil((mouseMoveElem.offsetWidth - e.offsetX) / 18), size.width);
    -  assertEquals('Should have 2 rows highlighted', 2, size.height);
    -}
    -
    -function testHandleKeyboardEvents() {
    -  picker.render(render);
    -
    -  picker.rightToLeft_ = false;
    -
    -  var result = picker.handleKeyEvent({keyCode: goog.events.KeyCodes.DOWN});
    -  var size = picker.getValue();
    -  assertEquals('Should have 1 column highlighted', 1, size.width);
    -  assertEquals('Should have 2 rows highlighted', 2, size.height);
    -  assertTrue('Should handle DOWN key event', result);
    -
    -  result = picker.handleKeyEvent({keyCode: goog.events.KeyCodes.RIGHT});
    -  size = picker.getValue();
    -  assertEquals('Should have 2 column highlighted', 2, size.width);
    -  assertEquals('Should have 2 rows highlighted', 2, size.height);
    -  assertTrue('Should handle RIGHT key event', result);
    -
    -  result = picker.handleKeyEvent({keyCode: goog.events.KeyCodes.UP});
    -  size = picker.getValue();
    -  assertEquals('Should have 2 column highlighted', 2, size.width);
    -  assertEquals('Should have 1 rows highlighted', 1, size.height);
    -  assertTrue('Should handle UP key event', result);
    -
    -  // Pressing UP when there is only 1 row should be handled but has no
    -  // effect.
    -  result = picker.handleKeyEvent({keyCode: goog.events.KeyCodes.UP});
    -  size = picker.getValue();
    -  assertEquals('Should have 2 column highlighted', 2, size.width);
    -  assertEquals('Should have 1 rows highlighted', 1, size.height);
    -  assertTrue('Should handle UP key event', result);
    -
    -  result = picker.handleKeyEvent({keyCode: goog.events.KeyCodes.LEFT});
    -  size = picker.getValue();
    -  assertEquals('Should have 2 column highlighted', 1, size.width);
    -  assertEquals('Should have 1 rows highlighted', 1, size.height);
    -  assertTrue('Should handle LEFT key event', result);
    -
    -  // Pressing LEFT when there is only 1 row should not be handled
    -  //allowing SubMenu to close.
    -  result = picker.handleKeyEvent({keyCode: goog.events.KeyCodes.LEFT});
    -  assertFalse(
    -      'Should not handle LEFT key event when there is only one column',
    -      result);
    -
    -  picker.rightToLeft_ = true;
    -
    -  // In RTL the roles of the LEFT and RIGHT keys are swapped.
    -  result = picker.handleKeyEvent({keyCode: goog.events.KeyCodes.LEFT});
    -  size = picker.getValue();
    -  assertEquals('Should have 2 column highlighted', 2, size.width);
    -  assertEquals('Should have 2 rows highlighted', 1, size.height);
    -  assertTrue('Should handle LEFT key event', result);
    -
    -  result = picker.handleKeyEvent({keyCode: goog.events.KeyCodes.RIGHT});
    -  size = picker.getValue();
    -  assertEquals('Should have 2 column highlighted', 1, size.width);
    -  assertEquals('Should have 1 rows highlighted', 1, size.height);
    -  assertTrue('Should handle RIGHT key event', result);
    -
    -  result = picker.handleKeyEvent({keyCode: goog.events.KeyCodes.RIGHT});
    -  assertFalse(
    -      'Should not handle RIGHT key event when there is only one column',
    -      result);
    -}
    -
    -function testDispose() {
    -  var element = picker.getElement();
    -  picker.render(render);
    -  picker.dispose();
    -  assertTrue('Picker should have been disposed of', picker.isDisposed());
    -  assertNull('Picker element reference should have been nulled out',
    -      picker.getElement());
    -}
    -
    -function testRendererDoesntCallGetCssClassInConstructor() {
    -  goog.testing.ui.rendererasserts.
    -      assertNoGetCssClassCallsInConstructor(
    -          goog.ui.DimensionPickerRenderer);
    -}
    -
    -function testSetAriaLabel() {
    -  assertNull('Picker must not have aria label by default',
    -      picker.getAriaLabel());
    -  picker.setAriaLabel('My picker');
    -  picker.render(render);
    -  var element = picker.getElementStrict();
    -  assertNotNull('Element must not be null', element);
    -  assertEquals('Picker element must have expected aria-label', 'My picker',
    -      element.getAttribute('aria-label'));
    -  assertTrue(goog.dom.isFocusableTabIndex(element));
    -  picker.setAriaLabel('My new picker');
    -  assertEquals('Picker element must have updated aria-label', 'My new picker',
    -      element.getAttribute('aria-label'));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/dimensionpickerrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/dimensionpickerrenderer.js
    deleted file mode 100644
    index b0553dc24c5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/dimensionpickerrenderer.js
    +++ /dev/null
    @@ -1,420 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview The default renderer for a goog.dom.DimensionPicker.  A
    - * dimension picker allows the user to visually select a row and column count.
    - * It looks like a palette but in order to minimize DOM load it is rendered.
    - * using CSS background tiling instead of as a grid of nodes.
    - *
    - * @author robbyw@google.com (Robby Walker)
    - */
    -
    -goog.provide('goog.ui.DimensionPickerRenderer');
    -
    -goog.require('goog.a11y.aria.Announcer');
    -goog.require('goog.a11y.aria.LivePriority');
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.i18n.bidi');
    -goog.require('goog.style');
    -goog.require('goog.ui.ControlRenderer');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Default renderer for {@link goog.ui.DimensionPicker}s.  Renders the
    - * palette as two divs, one with the un-highlighted background, and one with the
    - * highlighted background.
    - *
    - * @constructor
    - * @extends {goog.ui.ControlRenderer}
    - */
    -goog.ui.DimensionPickerRenderer = function() {
    -  goog.ui.ControlRenderer.call(this);
    -
    -  /** @private {goog.a11y.aria.Announcer} */
    -  this.announcer_ = new goog.a11y.aria.Announcer();
    -};
    -goog.inherits(goog.ui.DimensionPickerRenderer, goog.ui.ControlRenderer);
    -goog.addSingletonGetter(goog.ui.DimensionPickerRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.DimensionPickerRenderer.CSS_CLASS =
    -    goog.getCssName('goog-dimension-picker');
    -
    -
    -/**
    - * Return the underlying div for the given outer element.
    - * @param {Element} element The root element.
    - * @return {Element} The underlying div.
    - * @private
    - */
    -goog.ui.DimensionPickerRenderer.prototype.getUnderlyingDiv_ = function(
    -    element) {
    -  return element.firstChild.childNodes[1];
    -};
    -
    -
    -/**
    - * Return the highlight div for the given outer element.
    - * @param {Element} element The root element.
    - * @return {Element} The highlight div.
    - * @private
    - */
    -goog.ui.DimensionPickerRenderer.prototype.getHighlightDiv_ = function(
    -    element) {
    -  return /** @type {Element} */ (element.firstChild.lastChild);
    -};
    -
    -
    -/**
    - * Return the status message div for the given outer element.
    - * @param {Element} element The root element.
    - * @return {Element} The status message div.
    - * @private
    - */
    -goog.ui.DimensionPickerRenderer.prototype.getStatusDiv_ = function(
    -    element) {
    -  return /** @type {Element} */ (element.lastChild);
    -};
    -
    -
    -/**
    - * Return the invisible mouse catching div for the given outer element.
    - * @param {Element} element The root element.
    - * @return {Element} The invisible mouse catching div.
    - * @private
    - */
    -goog.ui.DimensionPickerRenderer.prototype.getMouseCatcher_ = function(
    -    element) {
    -  return /** @type {Element} */ (element.firstChild.firstChild);
    -};
    -
    -
    -/**
    - * Overrides {@link goog.ui.ControlRenderer#canDecorate} to allow decorating
    - * empty DIVs only.
    - * @param {Element} element The element to check.
    - * @return {boolean} Whether if the element is an empty div.
    - * @override
    - */
    -goog.ui.DimensionPickerRenderer.prototype.canDecorate = function(
    -    element) {
    -  return element.tagName == goog.dom.TagName.DIV && !element.firstChild;
    -};
    -
    -
    -/**
    - * Overrides {@link goog.ui.ControlRenderer#decorate} to decorate empty DIVs.
    - * @param {goog.ui.Control} control goog.ui.DimensionPicker to decorate.
    - * @param {Element} element The element to decorate.
    - * @return {Element} The decorated element.
    - * @override
    - */
    -goog.ui.DimensionPickerRenderer.prototype.decorate = function(control,
    -    element) {
    -  var palette = /** @type {goog.ui.DimensionPicker} */ (control);
    -  goog.ui.DimensionPickerRenderer.superClass_.decorate.call(this,
    -      palette, element);
    -
    -  this.addElementContents_(palette, element);
    -  this.updateSize(palette, element);
    -
    -  return element;
    -};
    -
    -
    -/**
    - * Scales various elements in order to update the palette's size.
    - * @param {goog.ui.DimensionPicker} palette The palette object.
    - * @param {Element} element The element to set the style of.
    - */
    -goog.ui.DimensionPickerRenderer.prototype.updateSize =
    -    function(palette, element) {
    -  var size = palette.getSize();
    -
    -  element.style.width = size.width + 'em';
    -
    -  var underlyingDiv = this.getUnderlyingDiv_(element);
    -  underlyingDiv.style.width = size.width + 'em';
    -  underlyingDiv.style.height = size.height + 'em';
    -
    -  if (palette.isRightToLeft()) {
    -    this.adjustParentDirection_(palette, element);
    -  }
    -};
    -
    -
    -/**
    - * Adds the appropriate content elements to the given outer DIV.
    - * @param {goog.ui.DimensionPicker} palette The palette object.
    - * @param {Element} element The element to decorate.
    - * @private
    - */
    -goog.ui.DimensionPickerRenderer.prototype.addElementContents_ = function(
    -    palette, element) {
    -  // First we create a single div containing three stacked divs.  The bottom div
    -  // catches mouse events.  We can't use document level mouse move detection as
    -  // we could lose events to iframes.  This is especially important in Firefox 2
    -  // in which TrogEdit creates iframes. The middle div uses a css tiled
    -  // background image to represent deselected tiles.  The top div uses a
    -  // different css tiled background image to represent selected tiles.
    -  var mouseCatcherDiv = palette.getDomHelper().createDom(goog.dom.TagName.DIV,
    -      goog.getCssName(this.getCssClass(), 'mousecatcher'));
    -  var unhighlightedDiv = palette.getDomHelper().createDom(goog.dom.TagName.DIV,
    -      {
    -        'class': goog.getCssName(this.getCssClass(), 'unhighlighted'),
    -        'style': 'width:100%;height:100%'
    -      });
    -  var highlightedDiv = palette.getDomHelper().createDom(goog.dom.TagName.DIV,
    -      goog.getCssName(this.getCssClass(), 'highlighted'));
    -  element.appendChild(
    -      palette.getDomHelper().createDom(goog.dom.TagName.DIV,
    -          {'style': 'width:100%;height:100%'},
    -          mouseCatcherDiv, unhighlightedDiv, highlightedDiv));
    -
    -  // Lastly we add a div to store the text version of the current state.
    -  element.appendChild(palette.getDomHelper().createDom(goog.dom.TagName.DIV,
    -      goog.getCssName(this.getCssClass(), 'status')));
    -};
    -
    -
    -/**
    - * Creates a div and adds the appropriate contents to it.
    - * @param {goog.ui.Control} control Picker to render.
    - * @return {!Element} Root element for the palette.
    - * @override
    - */
    -goog.ui.DimensionPickerRenderer.prototype.createDom = function(control) {
    -  var palette = /** @type {goog.ui.DimensionPicker} */ (control);
    -  var classNames = this.getClassNames(palette);
    -  // Hide the element from screen readers so they don't announce "1 of 1" for
    -  // the perceived number of items in the palette.
    -  var element = palette.getDomHelper().createDom(goog.dom.TagName.DIV, {
    -    'class': classNames ? classNames.join(' ') : '',
    -    'aria-hidden': 'true'
    -  });
    -  this.addElementContents_(palette, element);
    -  this.updateSize(palette, element);
    -  return element;
    -};
    -
    -
    -/**
    - * Initializes the control's DOM when the control enters the document.  Called
    - * from {@link goog.ui.Control#enterDocument}.
    - * @param {goog.ui.Control} control Palette whose DOM is to be
    - *     initialized as it enters the document.
    - * @override
    - */
    -goog.ui.DimensionPickerRenderer.prototype.initializeDom = function(
    -    control) {
    -  var palette = /** @type {goog.ui.DimensionPicker} */ (control);
    -  goog.ui.DimensionPickerRenderer.superClass_.initializeDom.call(this, palette);
    -
    -  // Make the displayed highlighted size match the dimension picker's value.
    -  var highlightedSize = palette.getValue();
    -  this.setHighlightedSize(palette,
    -      highlightedSize.width, highlightedSize.height);
    -
    -  this.positionMouseCatcher(palette);
    -};
    -
    -
    -/**
    - * Get the element to listen for mouse move events on.
    - * @param {goog.ui.DimensionPicker} palette The palette to listen on.
    - * @return {Element} The element to listen for mouse move events on.
    - */
    -goog.ui.DimensionPickerRenderer.prototype.getMouseMoveElement = function(
    -    palette) {
    -  return /** @type {Element} */ (palette.getElement().firstChild);
    -};
    -
    -
    -/**
    - * Returns the x offset in to the grid for the given mouse x position.
    - * @param {goog.ui.DimensionPicker} palette The table size palette.
    - * @param {number} x The mouse event x position.
    - * @return {number} The x offset in to the grid.
    - */
    -goog.ui.DimensionPickerRenderer.prototype.getGridOffsetX = function(
    -    palette, x) {
    -  // TODO(robbyw): Don't rely on magic 18 - measure each palette's em size.
    -  return Math.min(palette.maxColumns, Math.ceil(x / 18));
    -};
    -
    -
    -/**
    - * Returns the y offset in to the grid for the given mouse y position.
    - * @param {goog.ui.DimensionPicker} palette The table size palette.
    - * @param {number} y The mouse event y position.
    - * @return {number} The y offset in to the grid.
    - */
    -goog.ui.DimensionPickerRenderer.prototype.getGridOffsetY = function(
    -    palette, y) {
    -  return Math.min(palette.maxRows, Math.ceil(y / 18));
    -};
    -
    -
    -/**
    - * Sets the highlighted size. Does nothing if the palette hasn't been rendered.
    - * @param {goog.ui.DimensionPicker} palette The table size palette.
    - * @param {number} columns The number of columns to highlight.
    - * @param {number} rows The number of rows to highlight.
    - */
    -goog.ui.DimensionPickerRenderer.prototype.setHighlightedSize = function(
    -    palette, columns, rows) {
    -  var element = palette.getElement();
    -  // Can't update anything if DimensionPicker hasn't been rendered.
    -  if (!element) {
    -    return;
    -  }
    -
    -  // Style the highlight div.
    -  var style = this.getHighlightDiv_(element).style;
    -  style.width = columns + 'em';
    -  style.height = rows + 'em';
    -
    -  // Explicitly set style.right so the element grows to the left when increase
    -  // in width.
    -  if (palette.isRightToLeft()) {
    -    style.right = '0';
    -  }
    -
    -  /**
    -   * @desc The dimension of the columns and rows currently selected in the
    -   * dimension picker, as text that can be spoken by a screen reader.
    -   */
    -  var MSG_DIMENSION_PICKER_HIGHLIGHTED_DIMENSIONS = goog.getMsg(
    -      '{$numCols} by {$numRows}',
    -      {'numCols': columns, 'numRows': rows});
    -  this.announcer_.say(MSG_DIMENSION_PICKER_HIGHLIGHTED_DIMENSIONS,
    -      goog.a11y.aria.LivePriority.ASSERTIVE);
    -
    -  // Update the size text.
    -  goog.dom.setTextContent(this.getStatusDiv_(element),
    -      goog.i18n.bidi.enforceLtrInText(columns + ' x ' + rows));
    -};
    -
    -
    -/**
    - * Position the mouse catcher such that it receives mouse events past the
    - * selectedsize up to the maximum size.  Takes care to not introduce scrollbars.
    - * Should be called on enter document and when the window changes size.
    - * @param {goog.ui.DimensionPicker} palette The table size palette.
    - */
    -goog.ui.DimensionPickerRenderer.prototype.positionMouseCatcher = function(
    -    palette) {
    -  var mouseCatcher = this.getMouseCatcher_(palette.getElement());
    -  var doc = goog.dom.getOwnerDocument(mouseCatcher);
    -  var body = doc.body;
    -
    -  var position = goog.style.getRelativePosition(mouseCatcher, body);
    -
    -  // Hide the mouse catcher so it doesn't affect the body's scroll size.
    -  mouseCatcher.style.display = 'none';
    -
    -  // Compute the maximum size the catcher can be without introducing scrolling.
    -  var xAvailableEm = (palette.isRightToLeft() && position.x > 0) ?
    -      Math.floor(position.x / 18) :
    -      Math.floor((body.scrollWidth - position.x) / 18);
    -
    -  // Computing available height is more complicated - we need to check the
    -  // window's inner height.
    -  var height;
    -  if (goog.userAgent.IE) {
    -    // Offset 20px to make up for scrollbar size.
    -    height = goog.style.getClientViewportElement(body).scrollHeight - 20;
    -  } else {
    -    var win = goog.dom.getWindow(doc);
    -    // Offset 20px to make up for scrollbar size.
    -    height = Math.max(win.innerHeight, body.scrollHeight) - 20;
    -  }
    -  var yAvailableEm = Math.floor((height - position.y) / 18);
    -
    -  // Resize and display the mouse catcher.
    -  mouseCatcher.style.width = Math.min(palette.maxColumns, xAvailableEm) + 'em';
    -  mouseCatcher.style.height = Math.min(palette.maxRows, yAvailableEm) + 'em';
    -  mouseCatcher.style.display = '';
    -
    -  // Explicitly set style.right so the mouse catcher is positioned on the left
    -  // side instead of right.
    -  if (palette.isRightToLeft()) {
    -    mouseCatcher.style.right = '0';
    -  }
    -};
    -
    -
    -/**
    - * Returns the CSS class to be applied to the root element of components
    - * rendered using this renderer.
    - * @return {string} Renderer-specific CSS class.
    - * @override
    - */
    -goog.ui.DimensionPickerRenderer.prototype.getCssClass = function() {
    -  return goog.ui.DimensionPickerRenderer.CSS_CLASS;
    -};
    -
    -
    -/**
    - * This function adjusts the positioning from 'left' and 'top' to 'right' and
    - * 'top' as appropriate for RTL control.  This is so when the dimensionpicker
    - * grow in width, the containing element grow to the left instead of right.
    - * This won't be necessary if goog.ui.SubMenu rendering code would position RTL
    - * control with 'right' and 'top'.
    - * @private
    - *
    - * @param {goog.ui.DimensionPicker} palette The palette object.
    - * @param {Element} element The palette's element.
    - */
    -goog.ui.DimensionPickerRenderer.prototype.adjustParentDirection_ =
    -    function(palette, element) {
    -  var parent = palette.getParent();
    -  if (parent) {
    -    var parentElement = parent.getElement();
    -
    -    // Anchors the containing element to the right so it grows to the left
    -    // when it increase in width.
    -    var right = goog.style.getStyle(parentElement, 'right');
    -    if (right == '') {
    -      var parentPos = goog.style.getPosition(parentElement);
    -      var parentSize = goog.style.getSize(parentElement);
    -      if (parentSize.width != 0 && parentPos.x != 0) {
    -        var visibleRect = goog.style.getBounds(
    -            goog.style.getClientViewportElement());
    -        var visibleWidth = visibleRect.width;
    -        right = visibleWidth - parentPos.x - parentSize.width;
    -        goog.style.setStyle(parentElement, 'right', right + 'px');
    -      }
    -    }
    -
    -    // When a table is inserted, the containing elemet's position is
    -    // recalculated the next time it shows, set left back to '' to prevent
    -    // extra white space on the left.
    -    var left = goog.style.getStyle(parentElement, 'left');
    -    if (left != '') {
    -      goog.style.setStyle(parentElement, 'left', '');
    -    }
    -  } else {
    -    goog.style.setStyle(element, 'right', '0px');
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/dimensionpickerrenderer_test.html b/src/database/third_party/closure-library/closure/goog/ui/dimensionpickerrenderer_test.html
    deleted file mode 100644
    index 8f8f9b6c4bc..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/dimensionpickerrenderer_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests for DimensionPickerRenderer
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.DimensionPickerRendererTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/dimensionpickerrenderer_test.js b/src/database/third_party/closure-library/closure/goog/ui/dimensionpickerrenderer_test.js
    deleted file mode 100644
    index 7410182d0ab..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/dimensionpickerrenderer_test.js
    +++ /dev/null
    @@ -1,55 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.DimensionPickerRendererTest');
    -goog.setTestOnly('goog.ui.DimensionPickerRendererTest');
    -
    -goog.require('goog.a11y.aria.LivePriority');
    -goog.require('goog.array');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -goog.require('goog.ui.DimensionPicker');
    -goog.require('goog.ui.DimensionPickerRenderer');
    -
    -
    -var renderer;
    -var picker;
    -
    -function setUp() {
    -  renderer = new goog.ui.DimensionPickerRenderer();
    -  picker = new goog.ui.DimensionPicker(renderer);
    -}
    -
    -function tearDown() {
    -  picker.dispose();
    -}
    -
    -
    -/**
    - * Tests that the right aria label is added when the highlighted
    - * size changes.
    - */
    -function testSetHighlightedSizeUpdatesLiveRegion() {
    -  picker.render();
    -
    -  var sayFunction = goog.testing.recordFunction();
    -  renderer.announcer_.say = sayFunction;
    -  renderer.setHighlightedSize(picker, 3, 7);
    -
    -  assertEquals(1, sayFunction.getCallCount());
    -
    -  assertTrue(goog.array.equals(
    -      ['3 by 7', goog.a11y.aria.LivePriority.ASSERTIVE],
    -      sayFunction.getLastCall().getArguments()));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/dragdropdetector.js b/src/database/third_party/closure-library/closure/goog/ui/dragdropdetector.js
    deleted file mode 100644
    index f0445460781..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/dragdropdetector.js
    +++ /dev/null
    @@ -1,647 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Detects images dragged and dropped on to the window.
    - *
    - * @author robbyw@google.com (Robby Walker)
    - */
    -
    -goog.provide('goog.ui.DragDropDetector');
    -goog.provide('goog.ui.DragDropDetector.EventType');
    -goog.provide('goog.ui.DragDropDetector.ImageDropEvent');
    -goog.provide('goog.ui.DragDropDetector.LinkDropEvent');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.string');
    -goog.require('goog.style');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Creates a new drag and drop detector.
    - * @param {string=} opt_filePath The URL of the page to use for the detector.
    - *     It should contain the same contents as dragdropdetector_target.html in
    - *     the demos directory.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - * @final
    - */
    -goog.ui.DragDropDetector = function(opt_filePath) {
    -  goog.ui.DragDropDetector.base(this, 'constructor');
    -
    -  var iframe = goog.dom.createDom(goog.dom.TagName.IFRAME, {
    -    'frameborder': 0
    -  });
    -  // In Firefox, we do all drop detection with an IFRAME.  In IE, we only use
    -  // the IFRAME to capture copied, non-linked images.  (When we don't need it,
    -  // we put a text INPUT before it and push it off screen.)
    -  iframe.className = goog.userAgent.IE ?
    -      goog.getCssName(
    -          goog.ui.DragDropDetector.BASE_CSS_NAME_, 'ie-editable-iframe') :
    -      goog.getCssName(
    -          goog.ui.DragDropDetector.BASE_CSS_NAME_, 'w3c-editable-iframe');
    -  iframe.src = opt_filePath || goog.ui.DragDropDetector.DEFAULT_FILE_PATH_;
    -
    -  this.element_ = /** @type {!HTMLIFrameElement} */ (iframe);
    -
    -  this.handler_ = new goog.events.EventHandler(this);
    -  this.handler_.listen(iframe, goog.events.EventType.LOAD, this.initIframe_);
    -
    -  if (goog.userAgent.IE) {
    -    // In IE, we have to bounce between an INPUT for catching links and an
    -    // IFRAME for catching images.
    -    this.textInput_ = goog.dom.createDom(goog.dom.TagName.INPUT, {
    -      'type': 'text',
    -      'className': goog.getCssName(
    -          goog.ui.DragDropDetector.BASE_CSS_NAME_, 'ie-input')
    -    });
    -
    -    this.root_ = goog.dom.createDom(goog.dom.TagName.DIV,
    -        goog.getCssName(goog.ui.DragDropDetector.BASE_CSS_NAME_, 'ie-div'),
    -        this.textInput_, iframe);
    -  } else {
    -    this.root_ = iframe;
    -  }
    -
    -  document.body.appendChild(this.root_);
    -};
    -goog.inherits(goog.ui.DragDropDetector, goog.events.EventTarget);
    -
    -
    -/**
    - * Drag and drop event types.
    - * @enum {string}
    - */
    -goog.ui.DragDropDetector.EventType = {
    -  IMAGE_DROPPED: 'onimagedrop',
    -  LINK_DROPPED: 'onlinkdrop'
    -};
    -
    -
    -/**
    - * Browser specific drop event type.
    - * @type {string}
    - * @private
    - */
    -goog.ui.DragDropDetector.DROP_EVENT_TYPE_ = goog.userAgent.IE ?
    -    goog.events.EventType.DROP : 'dragdrop';
    -
    -
    -/**
    - * Initial value for clientX and clientY indicating that the location has
    - * never been updated.
    - */
    -goog.ui.DragDropDetector.INIT_POSITION = -10000;
    -
    -
    -/**
    - * Prefix for all CSS names.
    - * @type {string}
    - * @private
    - */
    -goog.ui.DragDropDetector.BASE_CSS_NAME_ = goog.getCssName('goog-dragdrop');
    -
    -
    -/**
    - * @desc Message shown to users to inform them that they can't drag and drop
    - *     local files.
    - */
    -goog.ui.DragDropDetector.MSG_DRAG_DROP_LOCAL_FILE_ERROR = goog.getMsg(
    -    'It is not possible to drag ' +
    -    'and drop image files at this time.\nPlease drag an image from your web ' +
    -    'browser.');
    -
    -
    -/**
    - * @desc Message shown to users trying to drag and drop protected images from
    - *     Flickr, etc.
    - */
    -goog.ui.DragDropDetector.MSG_DRAG_DROP_PROTECTED_FILE_ERROR = goog.getMsg(
    -    'The image you are ' +
    -    'trying to drag has been blocked by the hosting site.');
    -
    -
    -/**
    - * A map of special case information for URLs that cannot be dropped.  Each
    - * entry is of the form:
    - *     regex: url regex
    - *     message: user visible message about this special case
    - * @type {Array<{regex: RegExp, message: string}>}
    - * @private
    - */
    -goog.ui.DragDropDetector.SPECIAL_CASE_URLS_ = [
    -  {
    -    regex: /^file:\/\/\//,
    -    message: goog.ui.DragDropDetector.MSG_DRAG_DROP_LOCAL_FILE_ERROR
    -  },
    -  {
    -    regex: /flickr(.*)spaceball.gif$/,
    -    message: goog.ui.DragDropDetector.MSG_DRAG_DROP_PROTECTED_FILE_ERROR
    -  }
    -];
    -
    -
    -/**
    - * Regex that matches anything that looks kind of like a URL.  It matches
    - * nonspacechars://nonspacechars
    - * @type {RegExp}
    - * @private
    - */
    -goog.ui.DragDropDetector.URL_LIKE_REGEX_ = /^\S+:\/\/\S*$/;
    -
    -
    -/**
    - * Path to the dragdrop.html file.
    - * @type {string}
    - * @private
    - */
    -goog.ui.DragDropDetector.DEFAULT_FILE_PATH_ = 'dragdropdetector_target.html';
    -
    -
    -/**
    - * Our event handler object.
    - * @type {goog.events.EventHandler}
    - * @private
    - */
    -goog.ui.DragDropDetector.prototype.handler_;
    -
    -
    -/**
    - * The root element (the IFRAME on most browsers, the DIV on IE).
    - * @type {Element}
    - * @private
    - */
    -goog.ui.DragDropDetector.prototype.root_;
    -
    -
    -/**
    - * The text INPUT element used to detect link drops on IE.  null on Firefox.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.DragDropDetector.prototype.textInput_;
    -
    -
    -/**
    - * The iframe element.
    - * @type {HTMLIFrameElement}
    - * @private
    - */
    -goog.ui.DragDropDetector.prototype.element_;
    -
    -
    -/**
    - * The iframe's window, null if the iframe hasn't loaded yet.
    - * @type {Window}
    - * @private
    - */
    -goog.ui.DragDropDetector.prototype.window_ = null;
    -
    -
    -/**
    - * The iframe's document, null if the iframe hasn't loaded yet.
    - * @type {Document}
    - * @private
    - */
    -goog.ui.DragDropDetector.prototype.document_ = null;
    -
    -
    -/**
    - * The iframe's body, null if the iframe hasn't loaded yet.
    - * @type {HTMLBodyElement}
    - * @private
    - */
    -goog.ui.DragDropDetector.prototype.body_ = null;
    -
    -
    -/**
    - * Whether we are in "screen cover" mode in which the iframe or div is
    - * covering the entire screen.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.DragDropDetector.prototype.isCoveringScreen_ = false;
    -
    -
    -/**
    - * The last position of the mouse while dragging.
    - * @type {goog.math.Coordinate}
    - * @private
    - */
    -goog.ui.DragDropDetector.prototype.mousePosition_ = null;
    -
    -
    -/**
    - * Initialize the iframe after it has loaded.
    - * @private
    - */
    -goog.ui.DragDropDetector.prototype.initIframe_ = function() {
    -  // Set up a holder for position data.
    -  this.mousePosition_ = new goog.math.Coordinate(
    -      goog.ui.DragDropDetector.INIT_POSITION,
    -      goog.ui.DragDropDetector.INIT_POSITION);
    -
    -  // Set up pointers to the important parts of the IFrame.
    -  this.window_ = this.element_.contentWindow;
    -  this.document_ = this.window_.document;
    -  this.body_ = this.document_.body;
    -
    -  if (goog.userAgent.GECKO) {
    -    this.document_.designMode = 'on';
    -  } else if (!goog.userAgent.IE) {
    -    // Bug 1667110
    -    // In IE, we only set the IFrame body as content-editable when we bring it
    -    // into view at the top of the page.  Otherwise it may take focus when the
    -    // page is loaded, scrolling the user far offscreen.
    -    // Note that this isn't easily unit-testable, since it depends on a
    -    // browser-specific behavior with content-editable areas.
    -    this.body_.contentEditable = true;
    -  }
    -
    -  this.handler_.listen(document.body, goog.events.EventType.DRAGENTER,
    -      this.coverScreen_);
    -
    -  if (goog.userAgent.IE) {
    -    // IE only events.
    -    // Set up events on the IFrame.
    -    this.handler_.
    -        listen(this.body_,
    -            [goog.events.EventType.DRAGENTER, goog.events.EventType.DRAGOVER],
    -            goog.ui.DragDropDetector.enforceCopyEffect_).
    -        listen(this.body_, goog.events.EventType.MOUSEOUT,
    -            this.switchToInput_).
    -        listen(this.body_, goog.events.EventType.DRAGLEAVE,
    -            this.uncoverScreen_).
    -        listen(this.body_, goog.ui.DragDropDetector.DROP_EVENT_TYPE_,
    -            function(e) {
    -              this.trackMouse_(e);
    -
    -              // The drop event occurs before the content is added to the
    -              // iframe.  We setTimeout so that handleNodeInserted_ is called
    -              //  after the content is in the document.
    -              goog.global.setTimeout(
    -                  goog.bind(this.handleNodeInserted_, this, e), 0);
    -              return true;
    -            }).
    -
    -        // Set up events on the DIV.
    -        listen(this.root_,
    -            [goog.events.EventType.DRAGENTER, goog.events.EventType.DRAGOVER],
    -            this.handleNewDrag_).
    -        listen(this.root_,
    -            [
    -              goog.events.EventType.MOUSEMOVE,
    -              goog.events.EventType.KEYPRESS
    -            ], this.uncoverScreen_).
    -
    -        // Set up events on the text INPUT.
    -        listen(this.textInput_, goog.events.EventType.DRAGOVER,
    -            goog.events.Event.preventDefault).
    -        listen(this.textInput_, goog.ui.DragDropDetector.DROP_EVENT_TYPE_,
    -            this.handleInputDrop_);
    -  } else {
    -    // W3C events.
    -    this.handler_.
    -        listen(this.body_, goog.ui.DragDropDetector.DROP_EVENT_TYPE_,
    -            function(e) {
    -              this.trackMouse_(e);
    -              this.uncoverScreen_();
    -            }).
    -        listen(this.body_,
    -            [goog.events.EventType.MOUSEMOVE, goog.events.EventType.KEYPRESS],
    -            this.uncoverScreen_).
    -
    -        // Detect content insertion.
    -        listen(this.document_, 'DOMNodeInserted',
    -            this.handleNodeInserted_);
    -  }
    -};
    -
    -
    -/**
    - * Enforce that anything dragged over the IFRAME is copied in to it, rather
    - * than making it navigate to a different URL.
    - * @param {goog.events.BrowserEvent} e The event to enforce copying on.
    - * @private
    - */
    -goog.ui.DragDropDetector.enforceCopyEffect_ = function(e) {
    -  var event = e.getBrowserEvent();
    -  // This function is only called on IE.
    -  if (event.dataTransfer.dropEffect.toLowerCase() != 'copy') {
    -    event.dataTransfer.dropEffect = 'copy';
    -  }
    -};
    -
    -
    -/**
    - * Cover the screen with the iframe.
    - * @param {goog.events.BrowserEvent} e The event that caused this function call.
    - * @private
    - */
    -goog.ui.DragDropDetector.prototype.coverScreen_ = function(e) {
    -  // Don't do anything if the drop effect is 'none' and we are in IE.
    -  // It is set to 'none' in cases like dragging text inside a text area.
    -  if (goog.userAgent.IE &&
    -      e.getBrowserEvent().dataTransfer.dropEffect == 'none') {
    -    return;
    -  }
    -
    -  if (!this.isCoveringScreen_) {
    -    this.isCoveringScreen_ = true;
    -    if (goog.userAgent.IE) {
    -      goog.style.setStyle(this.root_, 'top', '0');
    -      this.body_.contentEditable = true;
    -      this.switchToInput_(e);
    -    } else {
    -      goog.style.setStyle(this.root_, 'height', '5000px');
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Uncover the screen.
    - * @private
    - */
    -goog.ui.DragDropDetector.prototype.uncoverScreen_ = function() {
    -  if (this.isCoveringScreen_) {
    -    this.isCoveringScreen_ = false;
    -    if (goog.userAgent.IE) {
    -      this.body_.contentEditable = false;
    -      goog.style.setStyle(this.root_, 'top', '-5000px');
    -    } else {
    -      goog.style.setStyle(this.root_, 'height', '10px');
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Re-insert the INPUT into the DIV.  Does nothing when the DIV is off screen.
    - * @param {goog.events.BrowserEvent} e The event that caused this function call.
    - * @private
    - */
    -goog.ui.DragDropDetector.prototype.switchToInput_ = function(e) {
    -  // This is only called on IE.
    -  if (this.isCoveringScreen_) {
    -    goog.style.setElementShown(this.textInput_, true);
    -  }
    -};
    -
    -
    -/**
    - * Remove the text INPUT so the IFRAME is showing.  Does nothing when the DIV is
    - * off screen.
    - * @param {goog.events.BrowserEvent} e The event that caused this function call.
    - * @private
    - */
    -goog.ui.DragDropDetector.prototype.switchToIframe_ = function(e) {
    -  // This is only called on IE.
    -  if (this.isCoveringScreen_) {
    -    goog.style.setElementShown(this.textInput_, false);
    -  }
    -};
    -
    -
    -/**
    - * Handle a new drag event.
    - * @param {goog.events.BrowserEvent} e The event object.
    - * @return {boolean|undefined} Returns false in IE to cancel the event.
    - * @private
    - */
    -goog.ui.DragDropDetector.prototype.handleNewDrag_ = function(e) {
    -  var event = e.getBrowserEvent();
    -
    -  // This is only called on IE.
    -  if (event.dataTransfer.dropEffect == 'link') {
    -    this.switchToInput_(e);
    -    e.preventDefault();
    -    return false;
    -  }
    -
    -  // Things that aren't links can be placed in the contentEditable iframe.
    -  this.switchToIframe_(e);
    -
    -  // No need to return true since for events return true is the same as no
    -  // return.
    -};
    -
    -
    -/**
    - * Handle mouse tracking.
    - * @param {goog.events.BrowserEvent} e The event object.
    - * @private
    - */
    -goog.ui.DragDropDetector.prototype.trackMouse_ = function(e) {
    -  this.mousePosition_.x = e.clientX;
    -  this.mousePosition_.y = e.clientY;
    -
    -  // Check if the event is coming from within the iframe.
    -  if (goog.dom.getOwnerDocument(/** @type {Node} */ (e.target)) != document) {
    -    var iframePosition = goog.style.getClientPosition(this.element_);
    -    this.mousePosition_.x += iframePosition.x;
    -    this.mousePosition_.y += iframePosition.y;
    -  }
    -};
    -
    -
    -/**
    - * Handle a drop on the IE text INPUT.
    - * @param {goog.events.BrowserEvent} e The event object.
    - * @private
    - */
    -goog.ui.DragDropDetector.prototype.handleInputDrop_ = function(e) {
    -  this.dispatchEvent(
    -      new goog.ui.DragDropDetector.LinkDropEvent(
    -          e.getBrowserEvent().dataTransfer.getData('Text')));
    -  this.uncoverScreen_();
    -  e.preventDefault();
    -};
    -
    -
    -/**
    - * Clear the contents of the iframe.
    - * @private
    - */
    -goog.ui.DragDropDetector.prototype.clearContents_ = function() {
    -  if (goog.userAgent.WEBKIT) {
    -    // Since this is called on a mutation event for the nodes we are going to
    -    // clear, calling this right away crashes some versions of WebKit.  Wait
    -    // until the events are finished.
    -    goog.global.setTimeout(goog.bind(function() {
    -      goog.dom.setTextContent(this, '');
    -    }, this.body_), 0);
    -  } else {
    -    this.document_.execCommand('selectAll', false, null);
    -    this.document_.execCommand('delete', false, null);
    -    this.document_.execCommand('selectAll', false, null);
    -  }
    -};
    -
    -
    -/**
    - * Event handler called when the content of the iframe changes.
    - * @param {goog.events.BrowserEvent} e The event that caused this function call.
    - * @private
    - */
    -goog.ui.DragDropDetector.prototype.handleNodeInserted_ = function(e) {
    -  var uri;
    -
    -  if (this.body_.innerHTML.indexOf('<') == -1) {
    -    // If the document contains no tags (i.e. is just text), try it out.
    -    uri = goog.string.trim(goog.dom.getTextContent(this.body_));
    -
    -    // See if it looks kind of like a url.
    -    if (!uri.match(goog.ui.DragDropDetector.URL_LIKE_REGEX_)) {
    -      uri = null;
    -    }
    -  }
    -
    -  if (!uri) {
    -    var imgs = this.body_.getElementsByTagName(goog.dom.TagName.IMG);
    -    if (imgs && imgs.length) {
    -      // TODO(robbyw): Grab all the images, instead of just the first.
    -      var img = imgs[0];
    -      uri = img.src;
    -    }
    -  }
    -
    -  if (uri) {
    -    var specialCases = goog.ui.DragDropDetector.SPECIAL_CASE_URLS_;
    -    var len = specialCases.length;
    -    for (var i = 0; i < len; i++) {
    -      var specialCase = specialCases[i];
    -      if (uri.match(specialCase.regex)) {
    -        alert(specialCase.message);
    -        break;
    -      }
    -    }
    -
    -    // If no special cases matched, add the image.
    -    if (i == len) {
    -      this.dispatchEvent(
    -          new goog.ui.DragDropDetector.ImageDropEvent(
    -              uri, this.mousePosition_));
    -      return;
    -    }
    -  }
    -
    -  var links = this.body_.getElementsByTagName(goog.dom.TagName.A);
    -  if (links) {
    -    for (i = 0, len = links.length; i < len; i++) {
    -      this.dispatchEvent(
    -          new goog.ui.DragDropDetector.LinkDropEvent(links[i].href));
    -    }
    -  }
    -
    -  this.clearContents_();
    -  this.uncoverScreen_();
    -};
    -
    -
    -/** @override */
    -goog.ui.DragDropDetector.prototype.disposeInternal = function() {
    -  goog.ui.DragDropDetector.base(this, 'disposeInternal');
    -  this.handler_.dispose();
    -  this.handler_ = null;
    -};
    -
    -
    -
    -/**
    - * Creates a new image drop event object.
    - * @param {string} url The url of the dropped image.
    - * @param {goog.math.Coordinate} position The screen position where the drop
    - *     occurred.
    - * @constructor
    - * @extends {goog.events.Event}
    - * @final
    - */
    -goog.ui.DragDropDetector.ImageDropEvent = function(url, position) {
    -  goog.ui.DragDropDetector.ImageDropEvent.base(this, 'constructor',
    -      goog.ui.DragDropDetector.EventType.IMAGE_DROPPED);
    -
    -  /**
    -   * The url of the image that was dropped.
    -   * @type {string}
    -   * @private
    -   */
    -  this.url_ = url;
    -
    -  /**
    -   * The screen position where the drop occurred.
    -   * @type {goog.math.Coordinate}
    -   * @private
    -   */
    -  this.position_ = position;
    -};
    -goog.inherits(goog.ui.DragDropDetector.ImageDropEvent,
    -    goog.events.Event);
    -
    -
    -/**
    - * @return {string} The url of the image that was dropped.
    - */
    -goog.ui.DragDropDetector.ImageDropEvent.prototype.getUrl = function() {
    -  return this.url_;
    -};
    -
    -
    -/**
    - * @return {goog.math.Coordinate} The screen position where the drop occurred.
    - *     This may be have x and y of goog.ui.DragDropDetector.INIT_POSITION,
    - *     indicating the drop position is unknown.
    - */
    -goog.ui.DragDropDetector.ImageDropEvent.prototype.getPosition = function() {
    -  return this.position_;
    -};
    -
    -
    -
    -/**
    - * Creates a new link drop event object.
    - * @param {string} url The url of the dropped link.
    - * @constructor
    - * @extends {goog.events.Event}
    - * @final
    - */
    -goog.ui.DragDropDetector.LinkDropEvent = function(url) {
    -  goog.ui.DragDropDetector.LinkDropEvent.base(this, 'constructor',
    -      goog.ui.DragDropDetector.EventType.LINK_DROPPED);
    -
    -  /**
    -   * The url of the link that was dropped.
    -   * @type {string}
    -   * @private
    -   */
    -  this.url_ = url;
    -};
    -goog.inherits(goog.ui.DragDropDetector.LinkDropEvent,
    -    goog.events.Event);
    -
    -
    -/**
    - * @return {string} The url of the link that was dropped.
    - */
    -goog.ui.DragDropDetector.LinkDropEvent.prototype.getUrl = function() {
    -  return this.url_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/drilldownrow.js b/src/database/third_party/closure-library/closure/goog/ui/drilldownrow.js
    deleted file mode 100644
    index f1a9d2d35ee..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/drilldownrow.js
    +++ /dev/null
    @@ -1,484 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Tree-like drilldown components for HTML tables.
    - *
    - * This component supports expanding and collapsing groups of rows in
    - * HTML tables.  The behavior is like typical Tree widgets, but tables
    - * need special support to enable the tree behaviors.
    - *
    - * Any row or rows in an HTML table can be DrilldownRows.  The root
    - * DrilldownRow nodes are always visible in the table, but the rest show
    - * or hide as input events expand and collapse their ancestors.
    - *
    - * Programming them:  Top-level DrilldownRows are made by decorating
    - * a TR element.  Children are made with addChild or addChildAt, and
    - * are entered into the document by the render() method.
    - *
    - * A DrilldownRow can have any number of children.  If it has no children
    - * it can be loaded, not loaded, or with a load in progress.
    - * Top-level DrilldownRows are always displayed (though setting
    - * style.display on a containing DOM node could make one be not
    - * visible to the user).  A DrilldownRow can be expanded, or not.  A
    - * DrilldownRow displays if all of its ancestors are expanded.
    - *
    - * Set up event handlers and style each row for the application in an
    - * enterDocument method.
    - *
    - * Children normally render into the document lazily, at the first
    - * moment when all ancestors are expanded.
    - *
    - * @see ../demos/drilldownrow.html
    - */
    -
    -// TODO(user): Build support for dynamically loading DrilldownRows,
    -// probably using automplete as an example to follow.
    -
    -// TODO(user): Make DrilldownRows accessible through the keyboard.
    -
    -// The render method is redefined in this class because when addChildAt renders
    -// the new child it assumes that the child's DOM node will be a child
    -// of the parent component's DOM node, but all DOM nodes of DrilldownRows
    -// in the same tree of DrilldownRows are siblings to each other.
    -//
    -// Arguments (or lack of arguments) to the render methods in Component
    -// all determine the place of the new DOM node in the DOM tree, but
    -// the place of a new DrilldownRow in the DOM needs to be determined by
    -// its position in the tree of DrilldownRows.
    -
    -goog.provide('goog.ui.DrilldownRow');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.ui.Component');
    -
    -
    -
    -/**
    - * Builds a DrilldownRow component, which can overlay a tree
    - * structure onto sections of an HTML table.
    - *
    - * @param {Object=} opt_properties This parameter can contain:
    - *   contents:  if present, user data identifying
    - *     the information loaded into the row and its children.
    - *   loaded: initializes the isLoaded property, defaults to true.
    - *   expanded: DrilldownRow expanded or not, default is true.
    - *   html: String of HTML, relevant and required for DrilldownRows to be
    - *     added as children.  Ignored when decorating an existing table row.
    - *   decorator: Function that accepts one DrilldownRow argument, and
    - *     should customize and style the row.  The default is to call
    - *     goog.ui.DrilldownRow.decorator.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @constructor
    - * @extends {goog.ui.Component}
    - * @final
    - */
    -goog.ui.DrilldownRow = function(opt_properties, opt_domHelper) {
    -  goog.ui.Component.call(this, opt_domHelper);
    -  var properties = opt_properties || {};
    -
    -  // Initialize instance variables.
    -
    -  /**
    -   * String of HTML to initialize the DOM structure for the table row.
    -   * Should have the form '<tr attr="etc">Row contents here</tr>'.
    -   * @type {string}
    -   * @private
    -   */
    -  this.html_ = properties.html;
    -
    -  /**
    -   * Controls whether this component's children will show when it shows.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.expanded_ = typeof properties.expanded != 'undefined' ?
    -      properties.expanded : true;
    -
    -  /**
    -   * If this component's DOM element is created from a string of
    -   * HTML, this is the function to call when it is entered into the DOM tree.
    -   * @type {Function} args are DrilldownRow and goog.events.EventHandler
    -   *   of the DrilldownRow.
    -   * @private
    -   */
    -  this.decoratorFn_ = properties.decorator || goog.ui.DrilldownRow.decorate;
    -
    -  /**
    -   * Is the DrilldownRow to be displayed?  If it is rendered, this mirrors
    -   * the style.display of the DrilldownRow's row.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.displayed_ = true;
    -};
    -goog.inherits(goog.ui.DrilldownRow, goog.ui.Component);
    -
    -
    -/**
    - * Example object with properties of the form accepted by the class
    - * constructor.  These are educational and show the compiler that
    - * these properties can be set so it doesn't emit warnings.
    - */
    -goog.ui.DrilldownRow.sampleProperties = {
    -  html: '<tr><td>Sample</td><td>Sample</td></tr>',
    -  loaded: true,
    -  decorator: function(selfObj, handler) {
    -    // When the mouse is hovering, add CSS class goog-drilldown-hover.
    -    goog.ui.DrilldownRow.decorate(selfObj);
    -    var row = selfObj.getElement();
    -    handler.listen(row, 'mouseover', function() {
    -      goog.dom.classlist.add(row, goog.getCssName('goog-drilldown-hover'));
    -    });
    -    handler.listen(row, 'mouseout', function() {
    -      goog.dom.classlist.remove(row, goog.getCssName('goog-drilldown-hover'));
    -    });
    -  }
    -};
    -
    -
    -//
    -// Implementations of Component methods.
    -//
    -
    -
    -/**
    - * The base class method calls its superclass method and this
    - * drilldown's 'decorator' method as defined in the constructor.
    - * @override
    - */
    -goog.ui.DrilldownRow.prototype.enterDocument = function() {
    -  goog.ui.DrilldownRow.superClass_.enterDocument.call(this);
    -  this.decoratorFn_(this, this.getHandler());
    -};
    -
    -
    -/** @override */
    -goog.ui.DrilldownRow.prototype.createDom = function() {
    -  this.setElementInternal(goog.ui.DrilldownRow.createRowNode_(
    -      this.html_, this.getDomHelper().getDocument()));
    -};
    -
    -
    -/**
    - * A top-level DrilldownRow decorates a TR element.
    - *
    - * @param {Element} node The element to test for decorability.
    - * @return {boolean} true iff the node is a TR.
    - * @override
    - */
    -goog.ui.DrilldownRow.prototype.canDecorate = function(node) {
    -  return node.tagName == 'TR';
    -};
    -
    -
    -/**
    - * Child drilldowns are rendered when needed.
    - *
    - * @param {goog.ui.Component} child New DrilldownRow child to be added.
    - * @param {number} index position to be occupied by the child.
    - * @param {boolean=} opt_render true to force immediate rendering.
    - * @override
    - */
    -goog.ui.DrilldownRow.prototype.addChildAt = function(child, index, opt_render) {
    -  goog.asserts.assertInstanceof(child, goog.ui.DrilldownRow);
    -  goog.ui.DrilldownRow.superClass_.addChildAt.call(this, child, index, false);
    -  child.setDisplayable_(this.isVisible_() && this.isExpanded());
    -  if (opt_render && !child.isInDocument()) {
    -    child.render();
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.DrilldownRow.prototype.removeChild = function(child) {
    -  goog.dom.removeNode(child.getElement());
    -  return goog.ui.DrilldownRow.superClass_.removeChild.call(this, child);
    -};
    -
    -
    -/**
    - * Rendering of DrilldownRow's is on need, do not call this directly
    - * from application code.
    - *
    - * Rendering a DrilldownRow places it according to its position in its
    - * tree of DrilldownRows.  DrilldownRows cannot be placed any other
    - * way so this method does not use any arguments.  This does not call
    - * the base class method and does not modify any of this
    - * DrilldownRow's children.
    - * @override
    - */
    -goog.ui.DrilldownRow.prototype.render = function() {
    -  if (arguments.length) {
    -    throw Error('A DrilldownRow cannot be placed under a specific parent.');
    -  } else {
    -    var parent = this.getParent();
    -    if (!parent.isInDocument()) {
    -      throw Error('Cannot render child of un-rendered parent');
    -    }
    -    // The new child's TR node needs to go just after the last TR
    -    // of the part of the parent's subtree that is to the left
    -    // of this.  The subtree includes the parent.
    -    goog.asserts.assertInstanceof(parent, goog.ui.DrilldownRow);
    -    var previous = parent.previousRenderedChild_(this);
    -    var row;
    -    if (previous) {
    -      goog.asserts.assertInstanceof(previous, goog.ui.DrilldownRow);
    -      row = previous.lastRenderedLeaf_().getElement();
    -    } else {
    -      row = parent.getElement();
    -    }
    -    row = /** @type {Element} */ (row.nextSibling);
    -    // Render the child row component into the document.
    -    if (row) {
    -      this.renderBefore(row);
    -    } else {
    -      // Render at the end of the parent of this DrilldownRow's
    -      // DOM element.
    -      var tbody = /** @type {Element} */ (parent.getElement().parentNode);
    -      goog.ui.DrilldownRow.superClass_.render.call(this, tbody);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Finds the numeric index of this child within its parent Component.
    - * Throws an exception if it has no parent.
    - *
    - * @return {number} index of this within the children of the parent Component.
    - */
    -goog.ui.DrilldownRow.prototype.findIndex = function() {
    -  var parent = this.getParent();
    -  if (!parent) {
    -    throw Error('Component has no parent');
    -  }
    -  return parent.indexOfChild(this);
    -};
    -
    -
    -//
    -// Type-specific operations
    -//
    -
    -
    -/**
    - * Returns the expanded state of the DrilldownRow.
    - *
    - * @return {boolean} true iff this is expanded.
    - */
    -goog.ui.DrilldownRow.prototype.isExpanded = function() {
    -  return this.expanded_;
    -};
    -
    -
    -/**
    - * Sets the expanded state of this DrilldownRow: makes all children
    - * displayable or not displayable corresponding to the expanded state.
    - *
    - * @param {boolean} expanded whether this should be expanded or not.
    - */
    -goog.ui.DrilldownRow.prototype.setExpanded = function(expanded) {
    -  if (expanded != this.expanded_) {
    -    this.expanded_ = expanded;
    -    var elem = this.getElement();
    -    goog.asserts.assert(elem);
    -    goog.dom.classlist.toggle(elem,
    -        goog.getCssName('goog-drilldown-expanded'));
    -    goog.dom.classlist.toggle(elem,
    -        goog.getCssName('goog-drilldown-collapsed'));
    -    if (this.isVisible_()) {
    -      this.forEachChild(function(child) {
    -        child.setDisplayable_(expanded);
    -      });
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Returns this DrilldownRow's level in the tree.  Top level is 1.
    - *
    - * @return {number} depth of this DrilldownRow in its tree of drilldowns.
    - */
    -goog.ui.DrilldownRow.prototype.getDepth = function() {
    -  for (var component = this, depth = 0;
    -       component instanceof goog.ui.DrilldownRow;
    -       component = component.getParent(), depth++) {}
    -  return depth;
    -};
    -
    -
    -/**
    - * This static function is a default decorator that adds HTML at the
    - * beginning of the first cell to display indentation and an expander
    - * image; sets up a click handler on the toggler; initializes a class
    - * for the row: either goog-drilldown-expanded or
    - * goog-drilldown-collapsed, depending on the initial state of the
    - * DrilldownRow; and sets up a click event handler on the toggler
    - * element.
    - *
    - * This creates a DIV with class=toggle.  Your application can set up
    - * CSS style rules something like this:
    - *
    - * tr.goog-drilldown-expanded .toggle {
    - *   background-image: url('minus.png');
    - * }
    - *
    - * tr.goog-drilldown-collapsed .toggle {
    - *   background-image: url('plus.png');
    - * }
    - *
    - * These background images show whether the DrilldownRow is expanded.
    - *
    - * @param {goog.ui.DrilldownRow} selfObj DrilldownRow to be decorated.
    - */
    -goog.ui.DrilldownRow.decorate = function(selfObj) {
    -  var depth = selfObj.getDepth();
    -  var row = selfObj.getElement();
    -  goog.asserts.assert(row);
    -  if (!row.cells) {
    -    throw Error('No cells');
    -  }
    -  var cell = row.cells[0];
    -  var html = '<div style="float: left; width: ' + depth +
    -      'em;"><div class=toggle style="width: 1em; float: right;">' +
    -      '&nbsp;</div></div>';
    -  var fragment = selfObj.getDomHelper().htmlToDocumentFragment(html);
    -  cell.insertBefore(fragment, cell.firstChild);
    -  goog.dom.classlist.add(row, selfObj.isExpanded() ?
    -      goog.getCssName('goog-drilldown-expanded') :
    -      goog.getCssName('goog-drilldown-collapsed'));
    -  // Default mouse event handling:
    -  var toggler = fragment.getElementsByTagName('div')[0];
    -  var key = selfObj.getHandler().listen(toggler, 'click', function(event) {
    -    selfObj.setExpanded(!selfObj.isExpanded());
    -  });
    -};
    -
    -
    -//
    -// Private methods
    -//
    -
    -
    -/**
    - * Turn display of a DrilldownRow on or off.  If the DrilldownRow has not
    - * yet been rendered, this renders it.  This propagates the effect
    - * of the change recursively as needed -- children displaying iff the
    - * parent is displayed and expanded.
    - *
    - * @param {boolean} display state, true iff display is desired.
    - * @private
    - */
    -goog.ui.DrilldownRow.prototype.setDisplayable_ = function(display) {
    -  if (display && !this.isInDocument()) {
    -    this.render();
    -  }
    -  if (this.displayed_ == display) {
    -    return;
    -  }
    -  this.displayed_ = display;
    -  if (this.isInDocument()) {
    -    this.getElement().style.display = display ? '' : 'none';
    -  }
    -  var selfObj = this;
    -  this.forEachChild(function(child) {
    -    child.setDisplayable_(display && selfObj.expanded_);
    -  });
    -};
    -
    -
    -/**
    - * True iff this and all its DrilldownRow parents are displayable.  The
    - * value is an approximation to actual visibility, since it does not
    - * look at whether DOM nodes containing the top-level component have
    - * display: none, visibility: hidden or are otherwise not displayable.
    - * So this visibility is relative to the top-level component.
    - *
    - * @return {boolean} visibility of this relative to its top-level drilldown.
    - * @private
    - */
    -goog.ui.DrilldownRow.prototype.isVisible_ = function() {
    -  for (var component = this;
    -       component instanceof goog.ui.DrilldownRow;
    -       component = component.getParent()) {
    -    if (!component.displayed_)
    -      return false;
    -  }
    -  return true;
    -};
    -
    -
    -/**
    - * Create and return a TR element from HTML that looks like
    - * "<tr> ... </tr>".
    - *
    - * @param {string} html for one row.
    - * @param {Document} doc object to hold the Element.
    - * @return {Element} table row node created from the HTML.
    - * @private
    - */
    -goog.ui.DrilldownRow.createRowNode_ = function(html, doc) {
    -  // Note: this may be slow.
    -  var tableHtml = '<table>' + html + '</table>';
    -  var div = doc.createElement('div');
    -  div.innerHTML = tableHtml;
    -  return div.firstChild.rows[0];
    -};
    -
    -
    -/**
    - * Get the recursively rightmost child that is in the document.
    - *
    - * @return {goog.ui.DrilldownRow} rightmost child currently entered in
    - *     the document, potentially this DrilldownRow.  If this is in the
    - *     document, result is non-null.
    - * @private
    - */
    -goog.ui.DrilldownRow.prototype.lastRenderedLeaf_ = function() {
    -  var leaf = null;
    -  for (var node = this;
    -       node && node.isInDocument();
    -       // Node will become undefined if parent has no children.
    -       node = node.getChildAt(node.getChildCount() - 1)) {
    -    leaf = node;
    -  }
    -  return /** @type {goog.ui.DrilldownRow} */ (leaf);
    -};
    -
    -
    -/**
    - * Search this node's direct children for the last one that is in the
    - * document and is before the given child.
    - * @param {goog.ui.DrilldownRow} child The child to stop the search at.
    - * @return {goog.ui.Component?} The last child component before the given child
    - *     that is in the document.
    - * @private
    - */
    -goog.ui.DrilldownRow.prototype.previousRenderedChild_ = function(child) {
    -  for (var i = this.getChildCount() - 1; i >= 0; i--) {
    -    if (this.getChildAt(i) == child) {
    -      for (var j = i - 1; j >= 0; j--) {
    -        var prev = this.getChildAt(j);
    -        if (prev.isInDocument()) {
    -          return prev;
    -        }
    -      }
    -    }
    -  }
    -  return null;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/drilldownrow_test.html b/src/database/third_party/closure-library/closure/goog/ui/drilldownrow_test.html
    deleted file mode 100644
    index c193aeaf1dd..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/drilldownrow_test.html
    +++ /dev/null
    @@ -1,65 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    -Author: nicksantos@google.com (Nick Santos)
    --->
    - <head>
    -  <title>
    -   DrilldownRow Tests
    -  </title>
    -  <script type="text/javascript" src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.ui.DrilldownRowTest');
    -  </script>
    -  <style type="text/css">
    -   .toggle {
    -  cursor: pointer;
    -  cursor: hand;
    -  background-repeat: none;
    -  background-position: right;
    -}
    -
    -tr.goog-drilldown-expanded .toggle {
    -  background-image: url('../images/minus.png');
    -}
    -
    -tr.goog-drilldown-collapsed .toggle {
    -  background-image: url('../images/plus.png');
    -}
    -
    -tr.goog-drilldown-hover td {
    -  background-color: #CCCCFF;
    -}
    -
    -td {
    -  background-color: white;
    -}
    -  </style>
    - </head>
    - <body>
    -  <table id="table" style="background-color: silver">
    -   <tr>
    -    <th>
    -     Column Head
    -    </th>
    -    <th>
    -     Second Head
    -    </th>
    -   </tr>
    -   <tr id="firstRow">
    -    <td>
    -     First row
    -    </td>
    -    <td>
    -     Second column
    -    </td>
    -   </tr>
    -  </table>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/drilldownrow_test.js b/src/database/third_party/closure-library/closure/goog/ui/drilldownrow_test.js
    deleted file mode 100644
    index 7aa7bf1ac06..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/drilldownrow_test.js
    +++ /dev/null
    @@ -1,47 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.DrilldownRowTest');
    -goog.setTestOnly('goog.ui.DrilldownRowTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.DrilldownRow');
    -
    -function testMakeRows() {
    -  var ff = goog.dom.getElement('firstRow');
    -  var d = new goog.ui.DrilldownRow({});
    -  var d1 = new goog.ui.DrilldownRow(
    -      {html: '<tr><td>Second row</td><td>Second column</td></tr>'}
    -      );
    -  var d2 = new goog.ui.DrilldownRow(
    -      {html: '<tr><td>Third row</td><td>Second column</td></tr>'}
    -      );
    -  var d21 = new goog.ui.DrilldownRow(
    -      {html: '<tr><td>Fourth row</td><td>Second column</td></tr>'}
    -      );
    -  var d22 = new goog.ui.DrilldownRow(goog.ui.DrilldownRow.sampleProperties);
    -  d.decorate(ff);
    -  d.addChild(d1, true);
    -  d.addChild(d2, true);
    -  d2.addChild(d21, true);
    -  d2.addChild(d22, true);
    -
    -  assertThrows(function() {
    -    d.findIndex();
    -  });
    -
    -  assertEquals(0, d1.findIndex());
    -  assertEquals(1, d2.findIndex());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/editor/abstractdialog.js b/src/database/third_party/closure-library/closure/goog/ui/editor/abstractdialog.js
    deleted file mode 100644
    index 0ef5912eeb4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/editor/abstractdialog.js
    +++ /dev/null
    @@ -1,444 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Wrapper around {@link goog.ui.Dialog}, to provide
    - * dialogs that are smarter about interacting with a rich text editor.
    - *
    - * @author nicksantos@google.com (Nick Santos)
    - */
    -
    -goog.provide('goog.ui.editor.AbstractDialog');
    -goog.provide('goog.ui.editor.AbstractDialog.Builder');
    -goog.provide('goog.ui.editor.AbstractDialog.EventType');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.string');
    -goog.require('goog.ui.Dialog');
    -goog.require('goog.ui.PopupBase');
    -
    -
    -// *** Public interface ***************************************************** //
    -
    -
    -
    -/**
    - * Creates an object that represents a dialog box.
    - * @param {goog.dom.DomHelper} domHelper DomHelper to be used to create the
    - * dialog's dom structure.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - */
    -goog.ui.editor.AbstractDialog = function(domHelper) {
    -  goog.events.EventTarget.call(this);
    -  this.dom = domHelper;
    -};
    -goog.inherits(goog.ui.editor.AbstractDialog, goog.events.EventTarget);
    -
    -
    -/**
    - * Causes the dialog box to appear, centered on the screen. Lazily creates the
    - * dialog if needed.
    - */
    -goog.ui.editor.AbstractDialog.prototype.show = function() {
    -  // Lazily create the wrapped dialog to be shown.
    -  if (!this.dialogInternal_) {
    -    this.dialogInternal_ = this.createDialogControl();
    -    this.dialogInternal_.listen(goog.ui.PopupBase.EventType.HIDE,
    -        this.handleAfterHide_, false, this);
    -  }
    -
    -  this.dialogInternal_.setVisible(true);
    -};
    -
    -
    -/**
    - * Hides the dialog, causing AFTER_HIDE to fire.
    - */
    -goog.ui.editor.AbstractDialog.prototype.hide = function() {
    -  if (this.dialogInternal_) {
    -    // This eventually fires the wrapped dialog's AFTER_HIDE event, calling our
    -    // handleAfterHide_().
    -    this.dialogInternal_.setVisible(false);
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the dialog is open.
    - */
    -goog.ui.editor.AbstractDialog.prototype.isOpen = function() {
    -  return !!this.dialogInternal_ && this.dialogInternal_.isVisible();
    -};
    -
    -
    -/**
    - * Runs the handler registered on the OK button event and closes the dialog if
    - * that handler succeeds.
    - * This is useful in cases such as double-clicking an item in the dialog is
    - * equivalent to selecting it and clicking the default button.
    - * @protected
    - */
    -goog.ui.editor.AbstractDialog.prototype.processOkAndClose = function() {
    -  // Fake an OK event from the wrapped dialog control.
    -  var evt = new goog.ui.Dialog.Event(goog.ui.Dialog.DefaultButtonKeys.OK, null);
    -  if (this.handleOk(evt)) {
    -    // handleOk calls dispatchEvent, so if any listener calls preventDefault it
    -    // will return false and we won't hide the dialog.
    -    this.hide();
    -  }
    -};
    -
    -
    -// *** Dialog events ******************************************************** //
    -
    -
    -/**
    - * Event type constants for events the dialog fires.
    - * @enum {string}
    - */
    -goog.ui.editor.AbstractDialog.EventType = {
    -  // This event is fired after the dialog is hidden, no matter if it was closed
    -  // via OK or Cancel or is being disposed without being hidden first.
    -  AFTER_HIDE: 'afterhide',
    -  // Either the cancel or OK events can be canceled via preventDefault or by
    -  // returning false from their handlers to stop the dialog from closing.
    -  CANCEL: 'cancel',
    -  OK: 'ok'
    -};
    -
    -
    -// *** Inner helper class *************************************************** //
    -
    -
    -
    -/**
    - * A builder class for the dialog control. All methods except build return this.
    - * @param {goog.ui.editor.AbstractDialog} editorDialog Editor dialog object
    - *     that will wrap the wrapped dialog object this builder will create.
    - * @constructor
    - */
    -goog.ui.editor.AbstractDialog.Builder = function(editorDialog) {
    -  // We require the editor dialog to be passed in so that the builder can set up
    -  // ok/cancel listeners by default, making it easier for most dialogs.
    -  this.editorDialog_ = editorDialog;
    -  this.wrappedDialog_ = new goog.ui.Dialog('', true, this.editorDialog_.dom);
    -  this.buttonSet_ = new goog.ui.Dialog.ButtonSet(this.editorDialog_.dom);
    -  this.buttonHandlers_ = {};
    -  this.addClassName(goog.getCssName('tr-dialog'));
    -};
    -
    -
    -/**
    - * Sets the title of the dialog.
    - * @param {string} title Title HTML (escaped).
    - * @return {!goog.ui.editor.AbstractDialog.Builder} This.
    - */
    -goog.ui.editor.AbstractDialog.Builder.prototype.setTitle = function(title) {
    -  this.wrappedDialog_.setTitle(title);
    -  return this;
    -};
    -
    -
    -/**
    - * Adds an OK button to the dialog. Clicking this button will cause {@link
    - * handleOk} to run, subsequently dispatching an OK event.
    - * @param {string=} opt_label The caption for the button, if not "OK".
    - * @return {!goog.ui.editor.AbstractDialog.Builder} This.
    - */
    -goog.ui.editor.AbstractDialog.Builder.prototype.addOkButton =
    -    function(opt_label) {
    -  var key = goog.ui.Dialog.DefaultButtonKeys.OK;
    -  /** @desc Label for an OK button in an editor dialog. */
    -  var MSG_TR_DIALOG_OK = goog.getMsg('OK');
    -  // True means this is the default/OK button.
    -  this.buttonSet_.set(key, opt_label || MSG_TR_DIALOG_OK, true);
    -  this.buttonHandlers_[key] = goog.bind(this.editorDialog_.handleOk,
    -                                        this.editorDialog_);
    -  return this;
    -};
    -
    -
    -/**
    - * Adds a Cancel button to the dialog. Clicking this button will cause {@link
    - * handleCancel} to run, subsequently dispatching a CANCEL event.
    - * @param {string=} opt_label The caption for the button, if not "Cancel".
    - * @return {!goog.ui.editor.AbstractDialog.Builder} This.
    - */
    -goog.ui.editor.AbstractDialog.Builder.prototype.addCancelButton =
    -    function(opt_label) {
    -  var key = goog.ui.Dialog.DefaultButtonKeys.CANCEL;
    -  /** @desc Label for a cancel button in an editor dialog. */
    -  var MSG_TR_DIALOG_CANCEL = goog.getMsg('Cancel');
    -  // False means it's not the OK button, true means it's the Cancel button.
    -  this.buttonSet_.set(key, opt_label || MSG_TR_DIALOG_CANCEL, false, true);
    -  this.buttonHandlers_[key] = goog.bind(this.editorDialog_.handleCancel,
    -                                        this.editorDialog_);
    -  return this;
    -};
    -
    -
    -/**
    - * Adds a custom button to the dialog.
    - * @param {string} label The caption for the button.
    - * @param {function(goog.ui.Dialog.EventType):*} handler Function called when
    - *     the button is clicked. It is recommended that this function be a method
    - *     in the concrete subclass of AbstractDialog using this Builder, and that
    - *     it dispatch an event (see {@link handleOk}).
    - * @param {string=} opt_buttonId Identifier to be used to access the button when
    - *     calling AbstractDialog.getButtonElement().
    - * @return {!goog.ui.editor.AbstractDialog.Builder} This.
    - */
    -goog.ui.editor.AbstractDialog.Builder.prototype.addButton =
    -    function(label, handler, opt_buttonId) {
    -  // We don't care what the key is, just that we can match the button with the
    -  // handler function later.
    -  var key = opt_buttonId || goog.string.createUniqueString();
    -  this.buttonSet_.set(key, label);
    -  this.buttonHandlers_[key] = handler;
    -  return this;
    -};
    -
    -
    -/**
    - * Puts a CSS class on the dialog's main element.
    - * @param {string} className The class to add.
    - * @return {!goog.ui.editor.AbstractDialog.Builder} This.
    - */
    -goog.ui.editor.AbstractDialog.Builder.prototype.addClassName =
    -    function(className) {
    -  goog.dom.classlist.add(
    -      goog.asserts.assert(this.wrappedDialog_.getDialogElement()), className);
    -  return this;
    -};
    -
    -
    -/**
    - * Sets the content element of the dialog.
    - * @param {Element} contentElem An element for the main body.
    - * @return {!goog.ui.editor.AbstractDialog.Builder} This.
    - */
    -goog.ui.editor.AbstractDialog.Builder.prototype.setContent =
    -    function(contentElem) {
    -  goog.dom.appendChild(this.wrappedDialog_.getContentElement(), contentElem);
    -  return this;
    -};
    -
    -
    -/**
    - * Builds the wrapped dialog control. May only be called once, after which
    - * no more methods may be called on this builder.
    - * @return {!goog.ui.Dialog} The wrapped dialog control.
    - */
    -goog.ui.editor.AbstractDialog.Builder.prototype.build = function() {
    -  if (this.buttonSet_.isEmpty()) {
    -    // If caller didn't set any buttons, add an OK and Cancel button by default.
    -    this.addOkButton();
    -    this.addCancelButton();
    -  }
    -  this.wrappedDialog_.setButtonSet(this.buttonSet_);
    -
    -  var handlers = this.buttonHandlers_;
    -  this.buttonHandlers_ = null;
    -  this.wrappedDialog_.listen(goog.ui.Dialog.EventType.SELECT,
    -      // Listen for the SELECT event, which means a button was clicked, and
    -      // call the handler associated with that button via the key property.
    -      function(e) {
    -        if (handlers[e.key]) {
    -          return handlers[e.key](e);
    -        }
    -      });
    -
    -  // All editor dialogs are modal.
    -  this.wrappedDialog_.setModal(true);
    -
    -  var dialog = this.wrappedDialog_;
    -  this.wrappedDialog_ = null;
    -  return dialog;
    -};
    -
    -
    -/**
    - * Editor dialog that will wrap the wrapped dialog this builder will create.
    - * @type {goog.ui.editor.AbstractDialog}
    - * @private
    - */
    -goog.ui.editor.AbstractDialog.Builder.prototype.editorDialog_;
    -
    -
    -/**
    - * wrapped dialog control being built by this builder.
    - * @type {goog.ui.Dialog}
    - * @private
    - */
    -goog.ui.editor.AbstractDialog.Builder.prototype.wrappedDialog_;
    -
    -
    -/**
    - * Set of buttons to be added to the wrapped dialog control.
    - * @type {goog.ui.Dialog.ButtonSet}
    - * @private
    - */
    -goog.ui.editor.AbstractDialog.Builder.prototype.buttonSet_;
    -
    -
    -/**
    - * Map from keys that will be returned in the wrapped dialog SELECT events to
    - * handler functions to be called to handle those events.
    - * @type {Object}
    - * @private
    - */
    -goog.ui.editor.AbstractDialog.Builder.prototype.buttonHandlers_;
    -
    -
    -// *** Protected interface ************************************************** //
    -
    -
    -/**
    - * The DOM helper for the parent document.
    - * @type {goog.dom.DomHelper}
    - * @protected
    - */
    -goog.ui.editor.AbstractDialog.prototype.dom;
    -
    -
    -/**
    - * Creates and returns the goog.ui.Dialog control that is being wrapped
    - * by this object.
    - * @return {!goog.ui.Dialog} Created Dialog control.
    - * @protected
    - */
    -goog.ui.editor.AbstractDialog.prototype.createDialogControl =
    -    goog.abstractMethod;
    -
    -
    -/**
    - * Returns the HTML Button element for the OK button in this dialog.
    - * @return {Element} The button element if found, else null.
    - * @protected
    - */
    -goog.ui.editor.AbstractDialog.prototype.getOkButtonElement = function() {
    -  return this.getButtonElement(goog.ui.Dialog.DefaultButtonKeys.OK);
    -};
    -
    -
    -/**
    - * Returns the HTML Button element for the Cancel button in this dialog.
    - * @return {Element} The button element if found, else null.
    - * @protected
    - */
    -goog.ui.editor.AbstractDialog.prototype.getCancelButtonElement = function() {
    -  return this.getButtonElement(goog.ui.Dialog.DefaultButtonKeys.CANCEL);
    -};
    -
    -
    -/**
    - * Returns the HTML Button element for the button added to this dialog with
    - * the given button id.
    - * @param {string} buttonId The id of the button to get.
    - * @return {Element} The button element if found, else null.
    - * @protected
    - */
    -goog.ui.editor.AbstractDialog.prototype.getButtonElement = function(buttonId) {
    -  return this.dialogInternal_.getButtonSet().getButton(buttonId);
    -};
    -
    -
    -/**
    - * Creates and returns the event object to be used when dispatching the OK
    - * event to listeners, or returns null to prevent the dialog from closing.
    - * Subclasses should override this to return their own subclass of
    - * goog.events.Event that includes all data a plugin would need from the dialog.
    - * @param {goog.events.Event} e The event object dispatched by the wrapped
    - *     dialog.
    - * @return {goog.events.Event} The event object to be used when dispatching the
    - *     OK event to listeners.
    - * @protected
    - */
    -goog.ui.editor.AbstractDialog.prototype.createOkEvent = goog.abstractMethod;
    -
    -
    -/**
    - * Handles the event dispatched by the wrapped dialog control when the user
    - * clicks the OK button. Attempts to create the OK event object and dispatches
    - * it if successful.
    - * @param {goog.ui.Dialog.Event} e wrapped dialog OK event object.
    - * @return {boolean} Whether the default action (closing the dialog) should
    - *     still be executed. This will be false if the OK event could not be
    - *     created to be dispatched, or if any listener to that event returs false
    - *     or calls preventDefault.
    - * @protected
    - */
    -goog.ui.editor.AbstractDialog.prototype.handleOk = function(e) {
    -  var eventObj = this.createOkEvent(e);
    -  if (eventObj) {
    -    return this.dispatchEvent(eventObj);
    -  } else {
    -    return false;
    -  }
    -};
    -
    -
    -/**
    - * Handles the event dispatched by the wrapped dialog control when the user
    - * clicks the Cancel button. Simply dispatches a CANCEL event.
    - * @return {boolean} Returns false if any of the handlers called prefentDefault
    - *     on the event or returned false themselves.
    - * @protected
    - */
    -goog.ui.editor.AbstractDialog.prototype.handleCancel = function() {
    -  return this.dispatchEvent(goog.ui.editor.AbstractDialog.EventType.CANCEL);
    -};
    -
    -
    -/**
    - * Disposes of the dialog. If the dialog is open, it will be hidden and
    - * AFTER_HIDE will be dispatched.
    - * @override
    - * @protected
    - */
    -goog.ui.editor.AbstractDialog.prototype.disposeInternal = function() {
    -  if (this.dialogInternal_) {
    -    this.hide();
    -
    -    this.dialogInternal_.dispose();
    -    this.dialogInternal_ = null;
    -  }
    -
    -  goog.ui.editor.AbstractDialog.superClass_.disposeInternal.call(this);
    -};
    -
    -
    -// *** Private implementation *********************************************** //
    -
    -
    -/**
    - * The wrapped dialog widget.
    - * @type {goog.ui.Dialog}
    - * @private
    - */
    -goog.ui.editor.AbstractDialog.prototype.dialogInternal_;
    -
    -
    -/**
    - * Cleans up after the dialog is hidden and fires the AFTER_HIDE event. Should
    - * be a listener for the wrapped dialog's AFTER_HIDE event.
    - * @private
    - */
    -goog.ui.editor.AbstractDialog.prototype.handleAfterHide_ = function() {
    -  this.dispatchEvent(goog.ui.editor.AbstractDialog.EventType.AFTER_HIDE);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/editor/abstractdialog_test.html b/src/database/third_party/closure-library/closure/goog/ui/editor/abstractdialog_test.html
    deleted file mode 100644
    index 7109fb4bf3e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/editor/abstractdialog_test.html
    +++ /dev/null
    @@ -1,28 +0,0 @@
    -<!DOCTYPE html>
    -<!--
    -  All Rights Reserved.
    -
    -  @author nicksantos@google.com (Nick Santos)
    -  @author marcosalmeida@google.com (Marcos Almeida)
    --->
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.editor.AbstractDialog
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.editor.AbstractDialogTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/editor/abstractdialog_test.js b/src/database/third_party/closure-library/closure/goog/ui/editor/abstractdialog_test.js
    deleted file mode 100644
    index 2ad4d7dc867..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/editor/abstractdialog_test.js
    +++ /dev/null
    @@ -1,483 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.editor.AbstractDialogTest');
    -goog.setTestOnly('goog.ui.editor.AbstractDialogTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.DomHelper');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.mockmatchers.ArgumentMatcher');
    -goog.require('goog.ui.editor.AbstractDialog');
    -goog.require('goog.userAgent');
    -
    -function shouldRunTests() {
    -  // Test disabled in IE7 due to flakiness. See b/4269021.
    -  return !(goog.userAgent.IE && goog.userAgent.isVersionOrHigher('7'));
    -}
    -
    -var dialog;
    -var builder;
    -
    -var mockCtrl;
    -var mockAfterHideHandler;
    -var mockOkHandler;
    -var mockCancelHandler;
    -var mockCustomButtonHandler;
    -
    -var CUSTOM_EVENT = 'customEvent';
    -var CUSTOM_BUTTON_ID = 'customButton';
    -
    -
    -function setUp() {
    -  mockCtrl = new goog.testing.MockControl();
    -  mockAfterHideHandler = mockCtrl.createLooseMock(goog.events.EventHandler);
    -  mockOkHandler = mockCtrl.createLooseMock(goog.events.EventHandler);
    -  mockCancelHandler = mockCtrl.createLooseMock(goog.events.EventHandler);
    -  mockCustomButtonHandler = mockCtrl.createLooseMock(goog.events.EventHandler);
    -}
    -
    -function tearDown() {
    -  if (dialog) {
    -    mockAfterHideHandler.$setIgnoreUnexpectedCalls(true);
    -    dialog.dispose();
    -  }
    -}
    -
    -
    -/**
    - * Sets up the mock event handler to expect an AFTER_HIDE event.
    - */
    -function expectAfterHide() {
    -  mockAfterHideHandler.handleEvent(
    -      new goog.testing.mockmatchers.ArgumentMatcher(function(arg) {
    -        return arg.type ==
    -               goog.ui.editor.AbstractDialog.EventType.AFTER_HIDE;
    -      }));
    -}
    -
    -
    -/**
    - * Sets up the mock event handler to expect an OK event.
    - */
    -function expectOk() {
    -  mockOkHandler.handleEvent(new goog.testing.mockmatchers.ArgumentMatcher(
    -      function(arg) {
    -        return arg.type == goog.ui.editor.AbstractDialog.EventType.OK;
    -      }));
    -}
    -
    -
    -/**
    - * Sets up the mock event handler to expect an OK event and to call
    - * preventDefault when handling it.
    - */
    -function expectOkPreventDefault() {
    -  expectOk();
    -  mockOkHandler.$does(function(e) {
    -    e.preventDefault();
    -  });
    -}
    -
    -
    -/**
    - * Sets up the mock event handler to expect an OK event and to return false
    - * when handling it.
    - */
    -function expectOkReturnFalse() {
    -  expectOk();
    -  mockOkHandler.$returns(false);
    -}
    -
    -
    -/**
    - * Sets up the mock event handler to expect a CANCEL event.
    - */
    -function expectCancel() {
    -  mockCancelHandler.handleEvent(new goog.testing.mockmatchers.ArgumentMatcher(
    -      function(arg) {
    -        return arg.type == goog.ui.editor.AbstractDialog.EventType.CANCEL;
    -      }));
    -}
    -
    -
    -/**
    - * Sets up the mock event handler to expect a custom button event.
    - */
    -function expectCustomButton() {
    -  mockCustomButtonHandler.handleEvent(
    -      new goog.testing.mockmatchers.ArgumentMatcher(function(arg) {
    -        return arg.type == CUSTOM_EVENT;
    -      }));
    -}
    -
    -
    -/**
    - * Helper to create the dialog being tested in each test. Since NewDialog is
    - * abstract, needs to add a concrete version of any abstract methods. Also
    - * creates up the global builder variable which should be set up after the call
    - * to this method.
    - * @return {goog.ui.editor.AbstractDialog} The dialog.
    - */
    -function createTestDialog() {
    -  var dialog = new goog.ui.editor.AbstractDialog(new goog.dom.DomHelper());
    -  builder = new goog.ui.editor.AbstractDialog.Builder(dialog);
    -  dialog.createDialogControl = function() {
    -    return builder.build();
    -  };
    -  dialog.createOkEvent = function(e) {
    -    return new goog.events.Event(goog.ui.editor.AbstractDialog.EventType.OK);
    -  };
    -  dialog.addEventListener(goog.ui.editor.AbstractDialog.EventType.AFTER_HIDE,
    -                          mockAfterHideHandler);
    -  dialog.addEventListener(goog.ui.editor.AbstractDialog.EventType.OK,
    -                          mockOkHandler);
    -  dialog.addEventListener(goog.ui.editor.AbstractDialog.EventType.CANCEL,
    -                          mockCancelHandler);
    -  dialog.addEventListener(CUSTOM_EVENT, mockCustomButtonHandler);
    -  return dialog;
    -}
    -
    -
    -/**
    - * Asserts that the given dialog is open.
    - * @param {string} msg Message to be printed in case of failure.
    - * @param {goog.ui.editor.AbstractDialog} dialog Dialog to be tested.
    - */
    -function assertOpen(msg, dialog) {
    -  assertTrue(msg + ' [AbstractDialog.isOpen()]', dialog && dialog.isOpen());
    -}
    -
    -
    -/**
    - * Asserts that the given dialog is closed.
    - * @param {string} msg Message to be printed in case of failure.
    - * @param {goog.ui.editor.AbstractDialog} dialog Dialog to be tested.
    - */
    -function assertNotOpen(msg, dialog) {
    -  assertFalse(msg + ' [AbstractDialog.isOpen()]', dialog && dialog.isOpen());
    -}
    -
    -
    -/**
    - * Tests that if you create a dialog and hide it without having shown it, no
    - * errors occur.
    - */
    -function testCreateAndHide() {
    -  dialog = createTestDialog();
    -  mockCtrl.$replayAll();
    -
    -  assertNotOpen('Dialog should not be open after creation', dialog);
    -  dialog.hide();
    -  assertNotOpen('Dialog should not be open after hide()', dialog);
    -
    -  mockCtrl.$verifyAll(); // Verifies AFTER_HIDE was not dispatched.
    -}
    -
    -
    -/**
    - * Tests that when you show and hide a dialog the flags indicating open are
    - * correct and the AFTER_HIDE event is dispatched (and no errors happen).
    - */
    -function testShowAndHide() {
    -  dialog = createTestDialog();
    -  expectAfterHide(dialog);
    -  mockCtrl.$replayAll();
    -
    -  assertNotOpen('Dialog should not be open before show()', dialog);
    -  dialog.show();
    -  assertOpen('Dialog should be open after show()', dialog);
    -  dialog.hide();
    -  assertNotOpen('Dialog should not be open after hide()', dialog);
    -
    -  mockCtrl.$verifyAll(); // Verifies AFTER_HIDE was dispatched.
    -}
    -
    -
    -/**
    - * Tests that when you show and dispose a dialog (without hiding it first) the
    - * flags indicating open are correct and the AFTER_HIDE event is dispatched (and
    - * no errors happen).
    - */
    -function testShowAndDispose() {
    -  dialog = createTestDialog();
    -  expectAfterHide(dialog);
    -  mockCtrl.$replayAll();
    -
    -  assertNotOpen('Dialog should not be open before show()', dialog);
    -  dialog.show();
    -  assertOpen('Dialog should be open after show()', dialog);
    -  dialog.dispose();
    -  assertNotOpen('Dialog should not be open after dispose()', dialog);
    -
    -  mockCtrl.$verifyAll(); // Verifies AFTER_HIDE was dispatched.
    -}
    -
    -
    -/**
    - * Tests that when you dispose a dialog (without ever showing it first) the
    - * flags indicating open are correct and the AFTER_HIDE event is never
    - * dispatched (and no errors happen).
    - */
    -function testDisposeWithoutShow() {
    -  dialog = createTestDialog();
    -  mockCtrl.$replayAll();
    -
    -  assertNotOpen('Dialog should not be open before dispose()', dialog);
    -  dialog.dispose();
    -  assertNotOpen('Dialog should not be open after dispose()', dialog);
    -
    -  mockCtrl.$verifyAll(); // Verifies AFTER_HIDE was NOT dispatched.
    -}
    -
    -
    -/**
    - * Tests that labels set in the builder can be found in the resulting dialog's
    - * HTML.
    - */
    -function testBasicLayout() {
    -  dialog = createTestDialog();
    -  mockCtrl.$replayAll();
    -
    -  // create some dialog content
    -  var content = goog.dom.createDom('div', null, 'The Content');
    -  builder.setTitle('The Title')
    -      .setContent(content)
    -      .addOkButton('The OK Button')
    -      .addCancelButton()
    -      .addButton('The Apply Button', goog.nullFunction)
    -      .addClassName('myClassName');
    -  dialog.show();
    -
    -  var dialogElem = dialog.dialogInternal_.getElement();
    -  var html = dialogElem.innerHTML;
    -  // TODO(user): This is really insufficient. If the title and content
    -  // were swapped this test would still pass!
    -  assertContains('Dialog html should contain title', '>The Title<', html);
    -  assertContains('Dialog html should contain content', '>The Content<', html);
    -  assertContains('Dialog html should contain custom OK button label',
    -                 '>The OK Button<',
    -                 html);
    -  assertContains('Dialog html should contain default Cancel button label',
    -                 '>Cancel<',
    -                 html);
    -  assertContains('Dialog html should contain custom button label',
    -                 '>The Apply Button<',
    -                 html);
    -  assertTrue('Dialog should have default Closure class',
    -             goog.dom.classlist.contains(dialogElem, 'modal-dialog'));
    -  assertTrue('Dialog should have our custom class',
    -             goog.dom.classlist.contains(dialogElem, 'myClassName'));
    -
    -  mockCtrl.$verifyAll();
    -}
    -
    -
    -/**
    - * Tests that clicking the OK button dispatches the OK event and closes the
    - * dialog (dispatching the AFTER_HIDE event too).
    - */
    -function testOk() {
    -  dialog = createTestDialog();
    -  expectOk(dialog);
    -  expectAfterHide(dialog);
    -  mockCtrl.$replayAll();
    -
    -  dialog.show();
    -  goog.testing.events.fireClickSequence(dialog.getOkButtonElement());
    -  assertNotOpen('Dialog should not be open after clicking OK', dialog);
    -
    -  mockCtrl.$verifyAll();
    -}
    -
    -
    -/**
    - * Tests that hitting the enter key dispatches the OK event and closes the
    - * dialog (dispatching the AFTER_HIDE event too).
    - */
    -function testEnter() {
    -  dialog = createTestDialog();
    -  expectOk(dialog);
    -  expectAfterHide(dialog);
    -  mockCtrl.$replayAll();
    -
    -  dialog.show();
    -  goog.testing.events.fireKeySequence(dialog.dialogInternal_.getElement(),
    -                                      goog.events.KeyCodes.ENTER);
    -  assertNotOpen('Dialog should not be open after hitting enter', dialog);
    -
    -  mockCtrl.$verifyAll();
    -}
    -
    -
    -/**
    - * Tests that clicking the Cancel button dispatches the CANCEL event and closes
    - * the dialog (dispatching the AFTER_HIDE event too).
    - */
    -function testCancel() {
    -  dialog = createTestDialog();
    -  expectCancel(dialog);
    -  expectAfterHide(dialog);
    -  mockCtrl.$replayAll();
    -
    -  builder.addCancelButton('My Cancel Button');
    -
    -  dialog.show();
    -  goog.testing.events.fireClickSequence(dialog.getCancelButtonElement());
    -  assertNotOpen('Dialog should not be open after clicking Cancel', dialog);
    -
    -  mockCtrl.$verifyAll();
    -}
    -
    -
    -/**
    - * Tests that hitting the escape key dispatches the CANCEL event and closes
    - * the dialog (dispatching the AFTER_HIDE event too).
    - */
    -function testEscape() {
    -  dialog = createTestDialog();
    -  expectCancel(dialog);
    -  expectAfterHide(dialog);
    -  mockCtrl.$replayAll();
    -
    -  dialog.show();
    -  goog.testing.events.fireKeySequence(dialog.dialogInternal_.getElement(),
    -                                      goog.events.KeyCodes.ESC);
    -  assertNotOpen('Dialog should not be open after hitting escape', dialog);
    -
    -  mockCtrl.$verifyAll();
    -}
    -
    -
    -/**
    - * Tests that clicking the custom button dispatches the custom event and closes
    - * the dialog (dispatching the AFTER_HIDE event too).
    - */
    -function testCustomButton() {
    -  dialog = createTestDialog();
    -  expectCustomButton(dialog);
    -  expectAfterHide(dialog);
    -  mockCtrl.$replayAll();
    -
    -  builder.addButton('My Custom Button',
    -      function() {
    -        dialog.dispatchEvent(CUSTOM_EVENT);
    -      },
    -      CUSTOM_BUTTON_ID);
    -
    -  dialog.show();
    -  goog.testing.events.fireClickSequence(
    -      dialog.getButtonElement(CUSTOM_BUTTON_ID));
    -  assertNotOpen('Dialog should not be open after clicking custom button',
    -                dialog);
    -
    -  mockCtrl.$verifyAll();
    -}
    -
    -
    -/**
    - * Tests that if the OK handler calls preventDefault, the dialog doesn't close.
    - */
    -function testOkPreventDefault() {
    -  dialog = createTestDialog();
    -  expectOkPreventDefault(dialog);
    -  mockCtrl.$replayAll();
    -
    -  dialog.show();
    -  goog.testing.events.fireClickSequence(dialog.getOkButtonElement());
    -  assertOpen('Dialog should not be closed because preventDefault was called',
    -             dialog);
    -
    -  mockCtrl.$verifyAll();
    -}
    -
    -
    -/**
    - * Tests that if the OK handler returns false, the dialog doesn't close.
    - */
    -function testOkReturnFalse() {
    -  dialog = createTestDialog();
    -  expectOkReturnFalse(dialog);
    -  mockCtrl.$replayAll();
    -
    -  dialog.show();
    -  goog.testing.events.fireClickSequence(dialog.getOkButtonElement());
    -  assertOpen('Dialog should not be closed because handler returned false',
    -             dialog);
    -
    -  mockCtrl.$verifyAll();
    -}
    -
    -
    -/**
    - * Tests that if creating the OK event fails, no event is dispatched and the
    - * dialog doesn't close.
    - */
    -function testCreateOkEventFail() {
    -  dialog = createTestDialog();
    -  dialog.createOkEvent = function() { // Override our mock createOkEvent.
    -    return null;
    -  };
    -  mockCtrl.$replayAll();
    -
    -  dialog.show();
    -  goog.testing.events.fireClickSequence(dialog.getOkButtonElement());
    -  assertOpen('Dialog should not be closed because OK event creation failed',
    -             dialog);
    -
    -  mockCtrl.$verifyAll(); // Verifies that no event was dispatched.
    -}
    -
    -
    -/**
    - * Tests that processOkAndClose() dispatches the OK event and closes the
    - * dialog (dispatching the AFTER_HIDE event too).
    - */
    -function testProcessOkAndClose() {
    -  dialog = createTestDialog();
    -  expectOk(dialog);
    -  expectAfterHide(dialog);
    -  mockCtrl.$replayAll();
    -
    -  dialog.show();
    -  dialog.processOkAndClose();
    -  assertNotOpen('Dialog should not be open after processOkAndClose()', dialog);
    -
    -  mockCtrl.$verifyAll();
    -}
    -
    -
    -/**
    - * Tests that if the OK handler triggered by processOkAndClose calls
    - * preventDefault, the dialog doesn't close (in the old implementation this
    - * failed due to not great design, so this is sort of a regression test).
    - */
    -function testProcessOkAndClosePreventDefault() {
    -  dialog = createTestDialog();
    -  expectOkPreventDefault(dialog);
    -  mockCtrl.$replayAll();
    -
    -  dialog.show();
    -  dialog.processOkAndClose();
    -  assertOpen('Dialog should not be closed because preventDefault was called',
    -      dialog);
    -
    -  mockCtrl.$verifyAll();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/editor/bubble.js b/src/database/third_party/closure-library/closure/goog/ui/editor/bubble.js
    deleted file mode 100644
    index 2259aaf5584..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/editor/bubble.js
    +++ /dev/null
    @@ -1,559 +0,0 @@
    -// Copyright 2005 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Bubble component - handles display, hiding, etc. of the
    - * actual bubble UI.
    - *
    - * This is used exclusively by code within the editor package, and should not
    - * be used directly.
    - *
    - * @author robbyw@google.com (Robby Walker)
    - */
    -
    -goog.provide('goog.ui.editor.Bubble');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.dom.ViewportSizeMonitor');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.editor.style');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -goog.require('goog.functions');
    -goog.require('goog.log');
    -goog.require('goog.math.Box');
    -goog.require('goog.object');
    -goog.require('goog.positioning');
    -goog.require('goog.positioning.Corner');
    -goog.require('goog.positioning.Overflow');
    -goog.require('goog.positioning.OverflowStatus');
    -goog.require('goog.string');
    -goog.require('goog.style');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.PopupBase');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Property bubble UI element.
    - * @param {Element} parent The parent element for this bubble.
    - * @param {number} zIndex The z index to draw the bubble at.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - */
    -goog.ui.editor.Bubble = function(parent, zIndex) {
    -  goog.ui.editor.Bubble.base(this, 'constructor');
    -
    -  /**
    -   * Dom helper for the document the bubble should be shown in.
    -   * @type {!goog.dom.DomHelper}
    -   * @private
    -   */
    -  this.dom_ = goog.dom.getDomHelper(parent);
    -
    -  /**
    -   * Event handler for this bubble.
    -   * @type {goog.events.EventHandler<!goog.ui.editor.Bubble>}
    -   * @private
    -   */
    -  this.eventHandler_ = new goog.events.EventHandler(this);
    -
    -  /**
    -   * Object that monitors the application window for size changes.
    -   * @type {goog.dom.ViewportSizeMonitor}
    -   * @private
    -   */
    -  this.viewPortSizeMonitor_ = new goog.dom.ViewportSizeMonitor(
    -      this.dom_.getWindow());
    -
    -  /**
    -   * Maps panel ids to panels.
    -   * @type {Object<goog.ui.editor.Bubble.Panel_>}
    -   * @private
    -   */
    -  this.panels_ = {};
    -
    -  /**
    -   * Container element for the entire bubble.  This may contain elements related
    -   * to look and feel or styling of the bubble.
    -   * @type {Element}
    -   * @private
    -   */
    -  this.bubbleContainer_ =
    -      this.dom_.createDom(goog.dom.TagName.DIV,
    -          {'className': goog.ui.editor.Bubble.BUBBLE_CLASSNAME});
    -
    -  goog.style.setElementShown(this.bubbleContainer_, false);
    -  goog.dom.appendChild(parent, this.bubbleContainer_);
    -  goog.style.setStyle(this.bubbleContainer_, 'zIndex', zIndex);
    -
    -  /**
    -   * Container element for the bubble panels - this should be some inner element
    -   * within (or equal to) bubbleContainer.
    -   * @type {Element}
    -   * @private
    -   */
    -  this.bubbleContents_ = this.createBubbleDom(this.dom_, this.bubbleContainer_);
    -
    -  /**
    -   * Element showing the close box.
    -   * @type {!Element}
    -   * @private
    -   */
    -  this.closeBox_ = this.dom_.createDom(goog.dom.TagName.DIV, {
    -    'className': goog.getCssName('tr_bubble_closebox'),
    -    'innerHTML': '&nbsp;'
    -  });
    -  this.bubbleContents_.appendChild(this.closeBox_);
    -
    -  // We make bubbles unselectable so that clicking on them does not steal focus
    -  // or move the cursor away from the element the bubble is attached to.
    -  goog.editor.style.makeUnselectable(this.bubbleContainer_, this.eventHandler_);
    -
    -  /**
    -   * Popup that controls showing and hiding the bubble at the appropriate
    -   * position.
    -   * @type {goog.ui.PopupBase}
    -   * @private
    -   */
    -  this.popup_ = new goog.ui.PopupBase(this.bubbleContainer_);
    -};
    -goog.inherits(goog.ui.editor.Bubble, goog.events.EventTarget);
    -
    -
    -/**
    - * The css class name of the bubble container element.
    - * @type {string}
    - */
    -goog.ui.editor.Bubble.BUBBLE_CLASSNAME = goog.getCssName('tr_bubble');
    -
    -
    -/**
    - * Creates and adds DOM for the bubble UI to the given container.  This default
    - * implementation just returns the container itself.
    - * @param {!goog.dom.DomHelper} dom DOM helper to use.
    - * @param {!Element} container Element to add the new elements to.
    - * @return {!Element} The element where bubble content should be added.
    - * @protected
    - */
    -goog.ui.editor.Bubble.prototype.createBubbleDom = function(dom, container) {
    -  return container;
    -};
    -
    -
    -/**
    - * A logger for goog.ui.editor.Bubble.
    - * @type {goog.log.Logger}
    - * @protected
    - */
    -goog.ui.editor.Bubble.prototype.logger =
    -    goog.log.getLogger('goog.ui.editor.Bubble');
    -
    -
    -/** @override */
    -goog.ui.editor.Bubble.prototype.disposeInternal = function() {
    -  goog.ui.editor.Bubble.base(this, 'disposeInternal');
    -
    -  goog.dom.removeNode(this.bubbleContainer_);
    -  this.bubbleContainer_ = null;
    -
    -  this.eventHandler_.dispose();
    -  this.eventHandler_ = null;
    -
    -  this.viewPortSizeMonitor_.dispose();
    -  this.viewPortSizeMonitor_ = null;
    -};
    -
    -
    -/**
    - * @return {Element} The element that where the bubble's contents go.
    - */
    -goog.ui.editor.Bubble.prototype.getContentElement = function() {
    -  return this.bubbleContents_;
    -};
    -
    -
    -/**
    - * @return {Element} The element that contains the bubble.
    - * @protected
    - */
    -goog.ui.editor.Bubble.prototype.getContainerElement = function() {
    -  return this.bubbleContainer_;
    -};
    -
    -
    -/**
    - * @return {goog.events.EventHandler<T>} The event handler.
    - * @protected
    - * @this T
    - * @template T
    - */
    -goog.ui.editor.Bubble.prototype.getEventHandler = function() {
    -  return this.eventHandler_;
    -};
    -
    -
    -/**
    - * Handles user resizing of window.
    - * @private
    - */
    -goog.ui.editor.Bubble.prototype.handleWindowResize_ = function() {
    -  if (this.isVisible()) {
    -    this.reposition();
    -  }
    -};
    -
    -
    -/**
    - * Sets whether the bubble dismisses itself when the user clicks outside of it.
    - * @param {boolean} autoHide Whether to autohide on an external click.
    - */
    -goog.ui.editor.Bubble.prototype.setAutoHide = function(autoHide) {
    -  this.popup_.setAutoHide(autoHide);
    -};
    -
    -
    -/**
    - * Returns whether there is already a panel of the given type.
    - * @param {string} type Type of panel to check.
    - * @return {boolean} Whether there is already a panel of the given type.
    - */
    -goog.ui.editor.Bubble.prototype.hasPanelOfType = function(type) {
    -  return goog.object.some(this.panels_, function(panel) {
    -    return panel.type == type;
    -  });
    -};
    -
    -
    -/**
    - * Adds a panel to the bubble.
    - * @param {string} type The type of bubble panel this is.  Should usually be
    - *     the same as the tagName of the targetElement.  This ensures multiple
    - *     bubble panels don't appear for the same element.
    - * @param {string} title The title of the panel.
    - * @param {Element} targetElement The target element of the bubble.
    - * @param {function(Element): void} contentFn Function that when called with
    - *     a container element, will add relevant panel content to it.
    - * @param {boolean=} opt_preferTopPosition Whether to prefer placing the bubble
    - *     above the element instead of below it.  Defaults to preferring below.
    - *     If any panel prefers the top position, the top position is used.
    - * @return {string} The id of the panel.
    - */
    -goog.ui.editor.Bubble.prototype.addPanel = function(type, title, targetElement,
    -    contentFn, opt_preferTopPosition) {
    -  var id = goog.string.createUniqueString();
    -  var panel = new goog.ui.editor.Bubble.Panel_(this.dom_, id, type, title,
    -      targetElement, !opt_preferTopPosition);
    -  this.panels_[id] = panel;
    -
    -  // Insert the panel in string order of type.  Technically we could use binary
    -  // search here but n is really small (probably 0 - 2) so it's not worth it.
    -  // The last child of bubbleContents_ is the close box so we take care not
    -  // to treat it as a panel element, and we also ensure it stays as the last
    -  // element.  The intention here is not to create any artificial order, but
    -  // just to ensure that it is always consistent.
    -  var nextElement;
    -  for (var i = 0, len = this.bubbleContents_.childNodes.length - 1; i < len;
    -       i++) {
    -    var otherChild = this.bubbleContents_.childNodes[i];
    -    var otherPanel = this.panels_[otherChild.id];
    -    if (otherPanel.type > type) {
    -      nextElement = otherChild;
    -      break;
    -    }
    -  }
    -  goog.dom.insertSiblingBefore(panel.element,
    -      nextElement || this.bubbleContents_.lastChild);
    -
    -  contentFn(panel.getContentElement());
    -  goog.editor.style.makeUnselectable(panel.element, this.eventHandler_);
    -
    -  var numPanels = goog.object.getCount(this.panels_);
    -  if (numPanels == 1) {
    -    this.openBubble_();
    -  } else if (numPanels == 2) {
    -    goog.dom.classlist.add(
    -        goog.asserts.assert(this.bubbleContainer_),
    -        goog.getCssName('tr_multi_bubble'));
    -  }
    -  this.reposition();
    -
    -  return id;
    -};
    -
    -
    -/**
    - * Removes the panel with the given id.
    - * @param {string} id The id of the panel.
    - */
    -goog.ui.editor.Bubble.prototype.removePanel = function(id) {
    -  var panel = this.panels_[id];
    -  goog.dom.removeNode(panel.element);
    -  delete this.panels_[id];
    -
    -  var numPanels = goog.object.getCount(this.panels_);
    -  if (numPanels <= 1) {
    -    goog.dom.classlist.remove(
    -        goog.asserts.assert(this.bubbleContainer_),
    -        goog.getCssName('tr_multi_bubble'));
    -  }
    -
    -  if (numPanels == 0) {
    -    this.closeBubble_();
    -  } else {
    -    this.reposition();
    -  }
    -};
    -
    -
    -/**
    - * Opens the bubble.
    - * @private
    - */
    -goog.ui.editor.Bubble.prototype.openBubble_ = function() {
    -  this.eventHandler_.
    -      listen(this.closeBox_, goog.events.EventType.CLICK,
    -          this.closeBubble_).
    -      listen(this.viewPortSizeMonitor_,
    -          goog.events.EventType.RESIZE, this.handleWindowResize_).
    -      listen(this.popup_, goog.ui.PopupBase.EventType.HIDE,
    -          this.handlePopupHide);
    -
    -  this.popup_.setVisible(true);
    -  this.reposition();
    -};
    -
    -
    -/**
    - * Closes the bubble.
    - * @private
    - */
    -goog.ui.editor.Bubble.prototype.closeBubble_ = function() {
    -  this.popup_.setVisible(false);
    -};
    -
    -
    -/**
    - * Handles the popup's hide event by removing all panels and dispatching a
    - * HIDE event.
    - * @protected
    - */
    -goog.ui.editor.Bubble.prototype.handlePopupHide = function() {
    -  // Remove the panel elements.
    -  for (var panelId in this.panels_) {
    -    goog.dom.removeNode(this.panels_[panelId].element);
    -  }
    -
    -  // Update the state to reflect no panels.
    -  this.panels_ = {};
    -  goog.dom.classlist.remove(
    -      goog.asserts.assert(this.bubbleContainer_),
    -      goog.getCssName('tr_multi_bubble'));
    -
    -  this.eventHandler_.removeAll();
    -  this.dispatchEvent(goog.ui.Component.EventType.HIDE);
    -};
    -
    -
    -/**
    - * Returns the visibility of the bubble.
    - * @return {boolean} True if visible false if not.
    - */
    -goog.ui.editor.Bubble.prototype.isVisible = function() {
    -  return this.popup_.isVisible();
    -};
    -
    -
    -/**
    - * The vertical clearance in pixels between the bottom of the targetElement
    - * and the edge of the bubble.
    - * @type {number}
    - * @private
    - */
    -goog.ui.editor.Bubble.VERTICAL_CLEARANCE_ = goog.userAgent.IE ? 4 : 2;
    -
    -
    -/**
    - * Bubble's margin box to be passed to goog.positioning.
    - * @type {goog.math.Box}
    - * @private
    - */
    -goog.ui.editor.Bubble.MARGIN_BOX_ = new goog.math.Box(
    -    goog.ui.editor.Bubble.VERTICAL_CLEARANCE_, 0,
    -    goog.ui.editor.Bubble.VERTICAL_CLEARANCE_, 0);
    -
    -
    -/**
    - * Returns the margin box.
    - * @return {goog.math.Box}
    - * @protected
    - */
    -goog.ui.editor.Bubble.prototype.getMarginBox = function() {
    -  return goog.ui.editor.Bubble.MARGIN_BOX_;
    -};
    -
    -
    -/**
    - * Positions and displays this bubble below its targetElement. Assumes that
    - * the bubbleContainer is already contained in the document object it applies
    - * to.
    - */
    -goog.ui.editor.Bubble.prototype.reposition = function() {
    -  var targetElement = null;
    -  var preferBottomPosition = true;
    -  for (var panelId in this.panels_) {
    -    var panel = this.panels_[panelId];
    -    // We don't care which targetElement we get, so we just take the last one.
    -    targetElement = panel.targetElement;
    -    preferBottomPosition = preferBottomPosition && panel.preferBottomPosition;
    -  }
    -  var status = goog.positioning.OverflowStatus.FAILED;
    -
    -  // Fix for bug when bubbleContainer and targetElement have
    -  // opposite directionality, the bubble should anchor to the END of
    -  // the targetElement instead of START.
    -  var reverseLayout = (goog.style.isRightToLeft(this.bubbleContainer_) !=
    -      goog.style.isRightToLeft(targetElement));
    -
    -  // Try to put the bubble at the bottom of the target unless the plugin has
    -  // requested otherwise.
    -  if (preferBottomPosition) {
    -    status = this.positionAtAnchor_(reverseLayout ?
    -        goog.positioning.Corner.BOTTOM_END :
    -        goog.positioning.Corner.BOTTOM_START,
    -        goog.positioning.Corner.TOP_START,
    -        goog.positioning.Overflow.ADJUST_X | goog.positioning.Overflow.FAIL_Y);
    -  }
    -
    -  if (status & goog.positioning.OverflowStatus.FAILED) {
    -    // Try to put it at the top of the target if there is not enough
    -    // space at the bottom.
    -    status = this.positionAtAnchor_(reverseLayout ?
    -        goog.positioning.Corner.TOP_END : goog.positioning.Corner.TOP_START,
    -        goog.positioning.Corner.BOTTOM_START,
    -        goog.positioning.Overflow.ADJUST_X | goog.positioning.Overflow.FAIL_Y);
    -  }
    -
    -  if (status & goog.positioning.OverflowStatus.FAILED) {
    -    // Put it at the bottom again with adjustment if there is no
    -    // enough space at the top.
    -    status = this.positionAtAnchor_(reverseLayout ?
    -        goog.positioning.Corner.BOTTOM_END :
    -        goog.positioning.Corner.BOTTOM_START,
    -        goog.positioning.Corner.TOP_START,
    -        goog.positioning.Overflow.ADJUST_X |
    -        goog.positioning.Overflow.ADJUST_Y);
    -    if (status & goog.positioning.OverflowStatus.FAILED) {
    -      goog.log.warning(this.logger,
    -          'reposition(): positionAtAnchor() failed with ' + status);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * A helper for reposition() - positions the bubble in regards to the position
    - * of the elements the bubble is attached to.
    - * @param {goog.positioning.Corner} targetCorner The corner of
    - *     the target element.
    - * @param {goog.positioning.Corner} bubbleCorner The corner of the bubble.
    - * @param {number} overflow Overflow handling mode bitmap,
    - *     {@see goog.positioning.Overflow}.
    - * @return {number} Status bitmap, {@see goog.positioning.OverflowStatus}.
    - * @private
    - */
    -goog.ui.editor.Bubble.prototype.positionAtAnchor_ = function(
    -    targetCorner, bubbleCorner, overflow) {
    -  var targetElement = null;
    -  for (var panelId in this.panels_) {
    -    // For now, we use the outermost element.  This assumes the multiple
    -    // elements this panel is showing for contain each other - in the event
    -    // that is not generally the case this may need to be updated to pick
    -    // the lowest or highest element depending on targetCorner.
    -    var candidate = this.panels_[panelId].targetElement;
    -    if (!targetElement || goog.dom.contains(candidate, targetElement)) {
    -      targetElement = this.panels_[panelId].targetElement;
    -    }
    -  }
    -  return goog.positioning.positionAtAnchor(
    -      targetElement, targetCorner, this.bubbleContainer_,
    -      bubbleCorner, null, this.getMarginBox(), overflow,
    -      null, this.getViewportBox());
    -};
    -
    -
    -/**
    - * Returns the viewport box to use when positioning the bubble.
    - * @return {goog.math.Box}
    - * @protected
    - */
    -goog.ui.editor.Bubble.prototype.getViewportBox = goog.functions.NULL;
    -
    -
    -
    -/**
    - * Private class used to describe a bubble panel.
    - * @param {goog.dom.DomHelper} dom DOM helper used to create the panel.
    - * @param {string} id ID of the panel.
    - * @param {string} type Type of the panel.
    - * @param {string} title Title of the panel.
    - * @param {Element} targetElement Element the panel is showing for.
    - * @param {boolean} preferBottomPosition Whether this panel prefers to show
    - *     below the target element.
    - * @constructor
    - * @private
    - */
    -goog.ui.editor.Bubble.Panel_ = function(dom, id, type, title, targetElement,
    -    preferBottomPosition) {
    -  /**
    -   * The type of bubble panel.
    -   * @type {string}
    -   */
    -  this.type = type;
    -
    -  /**
    -   * The target element of this bubble panel.
    -   * @type {Element}
    -   */
    -  this.targetElement = targetElement;
    -
    -  /**
    -   * Whether the panel prefers to be placed below the target element.
    -   * @type {boolean}
    -   */
    -  this.preferBottomPosition = preferBottomPosition;
    -
    -  /**
    -   * The element containing this panel.
    -   */
    -  this.element = dom.createDom(goog.dom.TagName.DIV,
    -      {className: goog.getCssName('tr_bubble_panel'), id: id},
    -      dom.createDom(goog.dom.TagName.DIV,
    -          {className: goog.getCssName('tr_bubble_panel_title')},
    -          title ? title + ':' : ''), // TODO(robbyw): Does this work in bidi?
    -      dom.createDom(goog.dom.TagName.DIV,
    -          {className: goog.getCssName('tr_bubble_panel_content')}));
    -};
    -
    -
    -/**
    - * @return {Element} The element in the panel where content should go.
    - */
    -goog.ui.editor.Bubble.Panel_.prototype.getContentElement = function() {
    -  return /** @type {Element} */ (this.element.lastChild);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/editor/bubble_test.html b/src/database/third_party/closure-library/closure/goog/ui/editor/bubble_test.html
    deleted file mode 100644
    index c2bfe2a4383..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/editor/bubble_test.html
    +++ /dev/null
    @@ -1,30 +0,0 @@
    -<!DOCTYPE html>
    -<!--
    -  All Rights Reserved.
    -
    -  @author tildahl@google.com (Michael Tildahl)
    -  @author robbyw@google.com (Robby Walker)
    --->
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.editor.Bubble
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.editor.BubbleTest');
    -  </script>
    -  <link rel="stylesheet" type="text/css" href="../../css/editor/bubble.css" />
    - </head>
    - <body>
    -  <div id="field"></div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/editor/bubble_test.js b/src/database/third_party/closure-library/closure/goog/ui/editor/bubble_test.js
    deleted file mode 100644
    index dae1e4f5a03..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/editor/bubble_test.js
    +++ /dev/null
    @@ -1,255 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.editor.BubbleTest');
    -goog.setTestOnly('goog.ui.editor.BubbleTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.events');
    -goog.require('goog.events.EventType');
    -goog.require('goog.positioning.Corner');
    -goog.require('goog.positioning.OverflowStatus');
    -goog.require('goog.string');
    -goog.require('goog.style');
    -goog.require('goog.testing.editor.TestHelper');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.editor.Bubble');
    -
    -var testHelper;
    -var fieldDiv;
    -var bubble;
    -var link;
    -var link2;
    -var panelId;
    -
    -function setUpPage() {
    -  fieldDiv = goog.dom.getElement('field');
    -  var viewportSize = goog.dom.getViewportSize();
    -  // Some tests depends on enough size of viewport.
    -  if (viewportSize.width < 600 || viewportSize.height < 440) {
    -    window.moveTo(0, 0);
    -    window.resizeTo(640, 480);
    -  }
    -}
    -
    -function setUp() {
    -  testHelper = new goog.testing.editor.TestHelper(fieldDiv);
    -  testHelper.setUpEditableElement();
    -
    -  bubble = new goog.ui.editor.Bubble(document.body, 999);
    -
    -  fieldDiv.innerHTML = '<a href="http://www.google.com">Google</a>' +
    -      '<a href="http://www.google.com">Google2</a>';
    -  link = fieldDiv.firstChild;
    -  link2 = fieldDiv.lastChild;
    -
    -  window.scrollTo(0, 0);
    -  goog.style.setStyle(document.body, 'direction', 'ltr');
    -  goog.style.setStyle(document.getElementById('field'), 'position', 'static');
    -}
    -
    -function tearDown() {
    -  if (panelId) {
    -    bubble.removePanel(panelId);
    -  }
    -  testHelper.tearDownEditableElement();
    -}
    -
    -
    -/**
    - * This is a helper function for setting up the target element with a
    - * given direction.
    - *
    - * @param {string} dir The direction of the target element, 'ltr' or 'rtl'.
    - * @param {boolean=} opt_preferTopPosition Whether to prefer placing the bubble
    - *     above the element instead of below it.  Defaults to preferring below.
    - */
    -function prepareTargetWithGivenDirection(dir, opt_preferTopPosition) {
    -  goog.style.setStyle(document.body, 'direction', dir);
    -
    -  fieldDiv.style.direction = dir;
    -  fieldDiv.innerHTML = '<a href="http://www.google.com">Google</a>';
    -  link = fieldDiv.firstChild;
    -
    -  panelId = bubble.addPanel('A', 'Link', link, function(el) {
    -    el.innerHTML = '<div style="border:1px solid blue;">B</div>';
    -  }, opt_preferTopPosition);
    -}
    -
    -
    -/**
    - * This is a helper function for getting the expected position of the bubble.
    - * (align to the right or the left of the target element).  Align left by
    - * default and align right if opt_alignRight is true. The expected Y is
    - * unaffected by alignment.
    - *
    - * @param {boolean=} opt_alignRight Sets the expected alignment to be right.
    - */
    -function getExpectedBubblePositionWithGivenAlignment(opt_alignRight) {
    -  var targetPosition = goog.style.getFramedPageOffset(link, window);
    -  var targetWidth = link.offsetWidth;
    -  var bubbleSize = goog.style.getSize(bubble.bubbleContainer_);
    -  var expectedBubbleX = opt_alignRight ?
    -      targetPosition.x + targetWidth - bubbleSize.width : targetPosition.x;
    -  var expectedBubbleY = link.offsetHeight + targetPosition.y +
    -      goog.ui.editor.Bubble.VERTICAL_CLEARANCE_;
    -
    -  return {
    -    x: expectedBubbleX,
    -    y: expectedBubbleY
    -  };
    -}
    -
    -function testCreateBubbleWithLinkPanel() {
    -  var id = goog.string.createUniqueString();
    -  panelId = bubble.addPanel('A', 'Link', link, function(container) {
    -    container.innerHTML = '<span id="' + id + '">Test</span>';
    -  });
    -  assertNotNull('Bubble should be created', bubble.bubbleContents_);
    -  assertNotNull('Added element should be present', goog.dom.getElement(id));
    -  assertTrue('Bubble should be visible', bubble.isVisible());
    -}
    -
    -function testCloseBubble() {
    -  testCreateBubbleWithLinkPanel();
    -
    -  var count = 0;
    -  goog.events.listen(bubble, goog.ui.Component.EventType.HIDE, function() {
    -    count++;
    -  });
    -
    -  bubble.removePanel(panelId);
    -  panelId = null;
    -
    -  assertFalse('Bubble should not be visible', bubble.isVisible());
    -  assertEquals('Hide event should be dispatched', 1, count);
    -}
    -
    -function testCloseBox() {
    -  testCreateBubbleWithLinkPanel();
    -
    -  var count = 0;
    -  goog.events.listen(bubble, goog.ui.Component.EventType.HIDE, function() {
    -    count++;
    -  });
    -
    -  var closeBox = goog.dom.getElementsByTagNameAndClass(
    -      goog.dom.TagName.DIV, 'tr_bubble_closebox', bubble.bubbleContainer_)[0];
    -  goog.testing.events.fireClickSequence(closeBox);
    -  panelId = null;
    -
    -  assertFalse('Bubble should not be visible', bubble.isVisible());
    -  assertEquals('Hide event should be dispatched', 1, count);
    -}
    -
    -function testViewPortSizeMonitorEvent() {
    -  testCreateBubbleWithLinkPanel();
    -
    -  var numCalled = 0;
    -  bubble.reposition = function() {
    -    numCalled++;
    -  };
    -
    -  assertNotUndefined('viewPortSizeMonitor_ should not be undefined',
    -      bubble.viewPortSizeMonitor_);
    -  bubble.viewPortSizeMonitor_.dispatchEvent(goog.events.EventType.RESIZE);
    -
    -  assertEquals('reposition not called', 1, numCalled);
    -}
    -
    -function testBubblePositionPreferTop() {
    -  called = false;
    -  bubble.positionAtAnchor_ = function(targetCorner, bubbleCorner, overflow) {
    -    called = true;
    -
    -    // Assert that the bubble is positioned below the target.
    -    assertEquals(goog.positioning.Corner.TOP_START, targetCorner);
    -    assertEquals(goog.positioning.Corner.BOTTOM_START, bubbleCorner);
    -
    -    return goog.positioning.OverflowStatus.NONE;
    -  };
    -  prepareTargetWithGivenDirection('ltr', true);
    -  assertTrue(called);
    -}
    -
    -function testBubblePosition() {
    -  panelId = bubble.addPanel('A', 'Link', link, goog.nullFunction);
    -  var CLEARANCE = goog.ui.editor.Bubble.VERTICAL_CLEARANCE_;
    -  var bubbleContainer = bubble.bubbleContainer_;
    -
    -  // The field is at a normal place, alomost the top of the viewport, and
    -  // there is enough space at the bottom of the field.
    -  var targetPos = goog.style.getFramedPageOffset(link, window);
    -  var targetSize = goog.style.getSize(link);
    -  var pos = goog.style.getFramedPageOffset(bubbleContainer);
    -  assertEquals(targetPos.y + targetSize.height + CLEARANCE, pos.y);
    -  assertEquals(targetPos.x, pos.x);
    -
    -  // Move the target to the bottom of the viewport.
    -  var field = document.getElementById('field');
    -  var fieldPos = goog.style.getFramedPageOffset(field, window);
    -  fieldPos.y += bubble.dom_.getViewportSize().height -
    -      (targetPos.y + targetSize.height);
    -  goog.style.setStyle(field, 'position', 'absolute');
    -  goog.style.setPosition(field, fieldPos);
    -  bubble.reposition();
    -  var bubbleSize = goog.style.getSize(bubbleContainer);
    -  targetPosition = goog.style.getFramedPageOffset(link, window);
    -  pos = goog.style.getFramedPageOffset(bubbleContainer);
    -  assertEquals(targetPosition.y - CLEARANCE - bubbleSize.height, pos.y);
    -}
    -
    -function testBubblePositionRightAligned() {
    -  prepareTargetWithGivenDirection('rtl');
    -
    -  var expectedPos = getExpectedBubblePositionWithGivenAlignment(true);
    -  var pos = goog.style.getFramedPageOffset(bubble.bubbleContainer_);
    -  assertRoughlyEquals(expectedPos.x, pos.x, 0.1);
    -  assertRoughlyEquals(expectedPos.y, pos.y, 0.1);
    -}
    -
    -
    -/**
    - * Test for bug 1955511, the bubble should align to the right side
    - * of the target element when the bubble is RTL, regardless of the
    - * target element's directionality.
    - */
    -function testBubblePositionLeftToRight() {
    -  goog.style.setStyle(bubble.bubbleContainer_, 'direction', 'ltr');
    -  prepareTargetWithGivenDirection('rtl');
    -
    -  var expectedPos = getExpectedBubblePositionWithGivenAlignment();
    -  var pos = goog.style.getFramedPageOffset(bubble.bubbleContainer_);
    -  assertRoughlyEquals(expectedPos.x, pos.x, 0.1);
    -  assertRoughlyEquals(expectedPos.y, pos.y, 0.1);
    -}
    -
    -
    -/**
    - * Test for bug 1955511, the bubble should align to the left side
    - * of the target element when the bubble is LTR, regardless of the
    - * target element's directionality.
    - */
    -function testBubblePositionRightToLeft() {
    -  goog.style.setStyle(bubble.bubbleContainer_, 'direction', 'rtl');
    -  prepareTargetWithGivenDirection('ltr');
    -
    -  var expectedPos = getExpectedBubblePositionWithGivenAlignment(true);
    -  var pos = goog.style.getFramedPageOffset(bubble.bubbleContainer_);
    -  assertEquals(expectedPos.x, pos.x);
    -  assertEquals(expectedPos.y, pos.y);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/editor/defaulttoolbar.js b/src/database/third_party/closure-library/closure/goog/ui/editor/defaulttoolbar.js
    deleted file mode 100644
    index 9ddb3716f55..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/editor/defaulttoolbar.js
    +++ /dev/null
    @@ -1,1066 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Factory functions for creating a default editing toolbar.
    - *
    - * @author attila@google.com (Attila Bodis)
    - * @see ../../demos/editor/editor.html
    - */
    -
    -goog.provide('goog.ui.editor.ButtonDescriptor');
    -goog.provide('goog.ui.editor.DefaultToolbar');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.editor.Command');
    -goog.require('goog.style');
    -goog.require('goog.ui.editor.ToolbarFactory');
    -goog.require('goog.ui.editor.messages');
    -goog.require('goog.userAgent');
    -
    -// Font menu creation.
    -
    -
    -/** @desc Font menu item caption for the default sans-serif font. */
    -goog.ui.editor.DefaultToolbar.MSG_FONT_NORMAL = goog.getMsg('Normal');
    -
    -
    -/** @desc Font menu item caption for the default serif font. */
    -goog.ui.editor.DefaultToolbar.MSG_FONT_NORMAL_SERIF =
    -    goog.getMsg('Normal / serif');
    -
    -
    -/**
    - * Common font descriptors for all locales.  Each descriptor has the following
    - * attributes:
    - * <ul>
    - *   <li>{@code caption} - Caption to show in the font menu (e.g. 'Tahoma')
    - *   <li>{@code value} - Value for the corresponding 'font-family' CSS style
    - *       (e.g. 'Tahoma, Arial, sans-serif')
    - * </ul>
    - * @type {!Array<{caption:string, value:string}>}
    - * @private
    - */
    -goog.ui.editor.DefaultToolbar.FONTS_ = [
    -  {
    -    caption: goog.ui.editor.DefaultToolbar.MSG_FONT_NORMAL,
    -    value: 'arial,sans-serif'
    -  },
    -  {
    -    caption: goog.ui.editor.DefaultToolbar.MSG_FONT_NORMAL_SERIF,
    -    value: 'times new roman,serif'
    -  },
    -  {caption: 'Courier New', value: 'courier new,monospace'},
    -  {caption: 'Georgia', value: 'georgia,serif'},
    -  {caption: 'Trebuchet', value: 'trebuchet ms,sans-serif'},
    -  {caption: 'Verdana', value: 'verdana,sans-serif'}
    -];
    -
    -
    -/**
    - * Locale-specific font descriptors.  The object is a map of locale strings to
    - * arrays of font descriptors.
    - * @type {!Object<!Array<{caption:string, value:string}>>}
    - * @private
    - */
    -goog.ui.editor.DefaultToolbar.I18N_FONTS_ = {
    -  'ja': [{
    -    caption: '\uff2d\uff33 \uff30\u30b4\u30b7\u30c3\u30af',
    -    value: 'ms pgothic,sans-serif'
    -  }, {
    -    caption: '\uff2d\uff33 \uff30\u660e\u671d',
    -    value: 'ms pmincho,serif'
    -  }, {
    -    caption: '\uff2d\uff33 \u30b4\u30b7\u30c3\u30af',
    -    value: 'ms gothic,monospace'
    -  }],
    -  'ko': [{
    -    caption: '\uad74\ub9bc',
    -    value: 'gulim,sans-serif'
    -  }, {
    -    caption: '\ubc14\ud0d5',
    -    value: 'batang,serif'
    -  }, {
    -    caption: '\uad74\ub9bc\uccb4',
    -    value: 'gulimche,monospace'
    -  }],
    -  'zh-tw': [{
    -    caption: '\u65b0\u7d30\u660e\u9ad4',
    -    value: 'pmingliu,serif'
    -  }, {
    -    caption: '\u7d30\u660e\u9ad4',
    -    value: 'mingliu,serif'
    -  }],
    -  'zh-cn': [{
    -    caption: '\u5b8b\u4f53',
    -    value: 'simsun,serif'
    -  }, {
    -    caption: '\u9ed1\u4f53',
    -    value: 'simhei,sans-serif'
    -  }, {
    -    caption: 'MS Song',
    -    value: 'ms song,monospace'
    -  }]
    -};
    -
    -
    -/**
    - * Default locale for font names.
    - * @type {string}
    - * @private
    - */
    -goog.ui.editor.DefaultToolbar.locale_ = 'en-us';
    -
    -
    -/**
    - * Sets the locale for the font names.  If not set, defaults to 'en-us'.
    - * Used only for default creation of font names name.  Must be set
    - * before font name menu is created.
    - * @param {string} locale Locale to use for the toolbar font names.
    - */
    -goog.ui.editor.DefaultToolbar.setLocale = function(locale) {
    -  goog.ui.editor.DefaultToolbar.locale_ = locale;
    -};
    -
    -
    -/**
    - * Initializes the given font menu button by adding default fonts to the menu.
    - * If goog.ui.editor.DefaultToolbar.setLocale was called to specify a locale
    - * for which locale-specific default fonts exist, those are added before
    - * common fonts.
    - * @param {!goog.ui.Select} button Font menu button.
    - */
    -goog.ui.editor.DefaultToolbar.addDefaultFonts = function(button) {
    -  // Normalize locale to lowercase, with a hyphen (see bug 1036165).
    -  var locale =
    -      goog.ui.editor.DefaultToolbar.locale_.replace(/_/, '-').toLowerCase();
    -  // Add locale-specific default fonts, if any.
    -  var fontlist = [];
    -
    -  if (locale in goog.ui.editor.DefaultToolbar.I18N_FONTS_) {
    -    fontlist = goog.ui.editor.DefaultToolbar.I18N_FONTS_[locale];
    -  }
    -  if (fontlist.length) {
    -    goog.ui.editor.ToolbarFactory.addFonts(button, fontlist);
    -  }
    -  // Add locale-independent default fonts.
    -  goog.ui.editor.ToolbarFactory.addFonts(button,
    -      goog.ui.editor.DefaultToolbar.FONTS_);
    -};
    -
    -
    -// Font size menu creation.
    -
    -
    -/** @desc Font size menu item caption for the 'Small' size. */
    -goog.ui.editor.DefaultToolbar.MSG_FONT_SIZE_SMALL = goog.getMsg('Small');
    -
    -
    -/** @desc Font size menu item caption for the 'Normal' size. */
    -goog.ui.editor.DefaultToolbar.MSG_FONT_SIZE_NORMAL = goog.getMsg('Normal');
    -
    -
    -/** @desc Font size menu item caption for the 'Large' size. */
    -goog.ui.editor.DefaultToolbar.MSG_FONT_SIZE_LARGE = goog.getMsg('Large');
    -
    -
    -/** @desc Font size menu item caption for the 'Huge' size. */
    -goog.ui.editor.DefaultToolbar.MSG_FONT_SIZE_HUGE = goog.getMsg('Huge');
    -
    -
    -/**
    - * Font size descriptors, each with the following attributes:
    - * <ul>
    - *   <li>{@code caption} - Caption to show in the font size menu (e.g. 'Huge')
    - *   <li>{@code value} - Value for the corresponding HTML font size (e.g. 6)
    - * </ul>
    - * @type {!Array<{caption:string, value:number}>}
    - * @private
    - */
    -goog.ui.editor.DefaultToolbar.FONT_SIZES_ = [
    -  {caption: goog.ui.editor.DefaultToolbar.MSG_FONT_SIZE_SMALL, value: 1},
    -  {caption: goog.ui.editor.DefaultToolbar.MSG_FONT_SIZE_NORMAL, value: 2},
    -  {caption: goog.ui.editor.DefaultToolbar.MSG_FONT_SIZE_LARGE, value: 4},
    -  {caption: goog.ui.editor.DefaultToolbar.MSG_FONT_SIZE_HUGE, value: 6}
    -];
    -
    -
    -/**
    - * Initializes the given font size menu button by adding default font sizes to
    - * it.
    - * @param {!goog.ui.Select} button Font size menu button.
    - */
    -goog.ui.editor.DefaultToolbar.addDefaultFontSizes = function(button) {
    -  goog.ui.editor.ToolbarFactory.addFontSizes(button,
    -      goog.ui.editor.DefaultToolbar.FONT_SIZES_);
    -};
    -
    -
    -// Header format menu creation.
    -
    -
    -/** @desc Caption for "Heading" block format option. */
    -goog.ui.editor.DefaultToolbar.MSG_FORMAT_HEADING = goog.getMsg('Heading');
    -
    -
    -/** @desc Caption for "Subheading" block format option. */
    -goog.ui.editor.DefaultToolbar.MSG_FORMAT_SUBHEADING = goog.getMsg('Subheading');
    -
    -
    -/** @desc Caption for "Minor heading" block format option. */
    -goog.ui.editor.DefaultToolbar.MSG_FORMAT_MINOR_HEADING =
    -    goog.getMsg('Minor heading');
    -
    -
    -/** @desc Caption for "Normal" block format option. */
    -goog.ui.editor.DefaultToolbar.MSG_FORMAT_NORMAL = goog.getMsg('Normal');
    -
    -
    -/**
    - * Format option descriptors, each with the following attributes:
    - * <ul>
    - *   <li>{@code caption} - Caption to show in the menu (e.g. 'Minor heading')
    - *   <li>{@code command} - Corresponding {@link goog.dom.TagName} (e.g.
    - *       'H4')
    - * </ul>
    - * @type {!Array<{caption: string, command: !goog.dom.TagName}>}
    - * @private
    - */
    -goog.ui.editor.DefaultToolbar.FORMAT_OPTIONS_ = [
    -  {
    -    caption: goog.ui.editor.DefaultToolbar.MSG_FORMAT_HEADING,
    -    command: goog.dom.TagName.H2
    -  },
    -  {
    -    caption: goog.ui.editor.DefaultToolbar.MSG_FORMAT_SUBHEADING,
    -    command: goog.dom.TagName.H3
    -  },
    -  {
    -    caption: goog.ui.editor.DefaultToolbar.MSG_FORMAT_MINOR_HEADING,
    -    command: goog.dom.TagName.H4
    -  },
    -  {
    -    caption: goog.ui.editor.DefaultToolbar.MSG_FORMAT_NORMAL,
    -    command: goog.dom.TagName.P
    -  }
    -];
    -
    -
    -/**
    - * Initializes the given "Format block" menu button by adding default format
    - * options to the menu.
    - * @param {!goog.ui.Select} button "Format block" menu button.
    - */
    -goog.ui.editor.DefaultToolbar.addDefaultFormatOptions = function(button) {
    -  goog.ui.editor.ToolbarFactory.addFormatOptions(button,
    -      goog.ui.editor.DefaultToolbar.FORMAT_OPTIONS_);
    -};
    -
    -
    -/**
    - * Creates a {@link goog.ui.Toolbar} containing a default set of editor
    - * toolbar buttons, and renders it into the given parent element.
    - * @param {!Element} elem Toolbar parent element.
    - * @param {boolean=} opt_isRightToLeft Whether the editor chrome is
    - *     right-to-left; defaults to the directionality of the toolbar parent
    - *     element.
    - * @return {!goog.ui.Toolbar} Default editor toolbar, rendered into the given
    - *     parent element.
    - * @see goog.ui.editor.DefaultToolbar.DEFAULT_BUTTONS
    - */
    -goog.ui.editor.DefaultToolbar.makeDefaultToolbar = function(elem,
    -    opt_isRightToLeft) {
    -  var isRightToLeft = opt_isRightToLeft || goog.style.isRightToLeft(elem);
    -  var buttons = isRightToLeft ?
    -      goog.ui.editor.DefaultToolbar.DEFAULT_BUTTONS_RTL :
    -      goog.ui.editor.DefaultToolbar.DEFAULT_BUTTONS;
    -  return goog.ui.editor.DefaultToolbar.makeToolbar(buttons, elem,
    -      opt_isRightToLeft);
    -};
    -
    -
    -/**
    - * Creates a {@link goog.ui.Toolbar} containing the specified set of
    - * toolbar buttons, and renders it into the given parent element.  Each
    - * item in the {@code items} array must either be a
    - * {@link goog.editor.Command} (to create a built-in button) or a subclass
    - * of {@link goog.ui.Control} (to create a custom control).
    - * @param {!Array<string|goog.ui.Control>} items Toolbar items; each must
    - *     be a {@link goog.editor.Command} or a {@link goog.ui.Control}.
    - * @param {!Element} elem Toolbar parent element.
    - * @param {boolean=} opt_isRightToLeft Whether the editor chrome is
    - *     right-to-left; defaults to the directionality of the toolbar parent
    - *     element.
    - * @return {!goog.ui.Toolbar} Editor toolbar, rendered into the given parent
    - *     element.
    - */
    -goog.ui.editor.DefaultToolbar.makeToolbar = function(items, elem,
    -    opt_isRightToLeft) {
    -  var domHelper = goog.dom.getDomHelper(elem);
    -  var controls = [];
    -
    -  for (var i = 0, button; button = items[i]; i++) {
    -    if (goog.isString(button)) {
    -      button = goog.ui.editor.DefaultToolbar.makeBuiltInToolbarButton(button,
    -          domHelper);
    -    }
    -    if (button) {
    -      controls.push(button);
    -    }
    -  }
    -
    -  return goog.ui.editor.ToolbarFactory.makeToolbar(controls, elem,
    -      opt_isRightToLeft);
    -};
    -
    -
    -/**
    - * Creates an instance of a subclass of {@link goog.ui.Button} for the given
    - * {@link goog.editor.Command}, or null if no built-in button exists for the
    - * command.  Note that this function is only intended to create built-in
    - * buttons; please don't try to hack it!
    - * @param {string} command Editor command ID.
    - * @param {goog.dom.DomHelper=} opt_domHelper DOM helper, used for DOM
    - *     creation; defaults to the current document if unspecified.
    - * @return {goog.ui.Button} Toolbar button (null if no built-in button exists
    - *     for the command).
    - */
    -goog.ui.editor.DefaultToolbar.makeBuiltInToolbarButton = function(command,
    -    opt_domHelper) {
    -  var button;
    -  var descriptor = goog.ui.editor.DefaultToolbar.buttons_[command];
    -  if (descriptor) {
    -    // Default the factory method to makeToggleButton, since most built-in
    -    // toolbar buttons are toggle buttons. See also
    -    // goog.ui.editor.DefaultToolbar.button_list_.
    -    var factory = descriptor.factory ||
    -        goog.ui.editor.ToolbarFactory.makeToggleButton;
    -    var id = descriptor.command;
    -    var tooltip = descriptor.tooltip;
    -    var caption = descriptor.caption;
    -    var classNames = descriptor.classes;
    -    // Default the DOM helper to the one for the current document.
    -    var domHelper = opt_domHelper || goog.dom.getDomHelper();
    -    // Instantiate the button based on the descriptor.
    -    button = factory(id, tooltip, caption, classNames, null, domHelper);
    -    // If this button's state should be queried when updating the toolbar,
    -    // set the button object's queryable property to true.
    -    if (descriptor.queryable) {
    -      button.queryable = true;
    -    }
    -  }
    -  return button;
    -};
    -
    -
    -/**
    - * A set of built-in buttons to display in the default editor toolbar.
    - * @type {!Array<string>}
    - */
    -goog.ui.editor.DefaultToolbar.DEFAULT_BUTTONS = [
    -  goog.editor.Command.IMAGE,
    -  goog.editor.Command.LINK,
    -  goog.editor.Command.BOLD,
    -  goog.editor.Command.ITALIC,
    -  goog.editor.Command.UNORDERED_LIST,
    -  goog.editor.Command.FONT_COLOR,
    -  goog.editor.Command.FONT_FACE,
    -  goog.editor.Command.FONT_SIZE,
    -  goog.editor.Command.JUSTIFY_LEFT,
    -  goog.editor.Command.JUSTIFY_CENTER,
    -  goog.editor.Command.JUSTIFY_RIGHT,
    -  goog.editor.Command.EDIT_HTML
    -];
    -
    -
    -/**
    - * A set of built-in buttons to display in the default editor toolbar when
    - * the editor chrome is right-to-left (BiDi mode only).
    - * @type {!Array<string>}
    - */
    -goog.ui.editor.DefaultToolbar.DEFAULT_BUTTONS_RTL = [
    -  goog.editor.Command.IMAGE,
    -  goog.editor.Command.LINK,
    -  goog.editor.Command.BOLD,
    -  goog.editor.Command.ITALIC,
    -  goog.editor.Command.UNORDERED_LIST,
    -  goog.editor.Command.FONT_COLOR,
    -  goog.editor.Command.FONT_FACE,
    -  goog.editor.Command.FONT_SIZE,
    -  goog.editor.Command.JUSTIFY_RIGHT,
    -  goog.editor.Command.JUSTIFY_CENTER,
    -  goog.editor.Command.JUSTIFY_LEFT,
    -  goog.editor.Command.DIR_RTL,
    -  goog.editor.Command.DIR_LTR,
    -  goog.editor.Command.EDIT_HTML
    -];
    -
    -
    -/**
    - * Creates a toolbar button with the given ID, tooltip, and caption.  Applies
    - * any custom CSS class names to the button's caption element.  This button
    - * is designed to be used as the RTL button.
    - * @param {string} id Button ID; must equal a {@link goog.editor.Command} for
    - *     built-in buttons, anything else for custom buttons.
    - * @param {string} tooltip Tooltip to be shown on hover.
    - * @param {goog.ui.ControlContent} caption Button caption.
    - * @param {string=} opt_classNames CSS class name(s) to apply to the caption
    - *     element.
    - * @param {goog.ui.ButtonRenderer=} opt_renderer Button renderer; defaults to
    - *     {@link goog.ui.ToolbarButtonRenderer} if unspecified.
    - * @param {goog.dom.DomHelper=} opt_domHelper DOM helper, used for DOM
    - *     creation; defaults to the current document if unspecified.
    - * @return {!goog.ui.Button} A toolbar button.
    - * @private
    - */
    -goog.ui.editor.DefaultToolbar.rtlButtonFactory_ = function(id, tooltip,
    -    caption, opt_classNames, opt_renderer, opt_domHelper) {
    -  var button = goog.ui.editor.ToolbarFactory.makeToggleButton(id, tooltip,
    -      caption, opt_classNames, opt_renderer, opt_domHelper);
    -  button.updateFromValue = function(value) {
    -    // Enable/disable right-to-left text editing mode in the toolbar.
    -    var isRtl = !!value;
    -    // Enable/disable a marker class on the toolbar's root element; the rest is
    -    // done using CSS scoping in editortoolbar.css.  This changes
    -    // direction-senitive toolbar icons (like indent/outdent)
    -    goog.dom.classlist.enable(
    -        goog.asserts.assert(button.getParent().getElement()),
    -        goog.getCssName('tr-rtl-mode'), isRtl);
    -    button.setChecked(isRtl);
    -  };
    -  return button;
    -};
    -
    -
    -/**
    - * Creates a toolbar button with the given ID, tooltip, and caption.  Applies
    - * any custom CSS class names to the button's caption element.  Designed to
    - * be used to create undo and redo buttons.
    - * @param {string} id Button ID; must equal a {@link goog.editor.Command} for
    - *     built-in buttons, anything else for custom buttons.
    - * @param {string} tooltip Tooltip to be shown on hover.
    - * @param {goog.ui.ControlContent} caption Button caption.
    - * @param {string=} opt_classNames CSS class name(s) to apply to the caption
    - *     element.
    - * @param {goog.ui.ButtonRenderer=} opt_renderer Button renderer; defaults to
    - *     {@link goog.ui.ToolbarButtonRenderer} if unspecified.
    - * @param {goog.dom.DomHelper=} opt_domHelper DOM helper, used for DOM
    - *     creation; defaults to the current document if unspecified.
    - * @return {!goog.ui.Button} A toolbar button.
    - * @private
    - */
    -goog.ui.editor.DefaultToolbar.undoRedoButtonFactory_ = function(id, tooltip,
    -    caption, opt_classNames, opt_renderer, opt_domHelper) {
    -  var button = goog.ui.editor.ToolbarFactory.makeButton(id, tooltip,
    -      caption, opt_classNames, opt_renderer, opt_domHelper);
    -  button.updateFromValue = function(value) {
    -    button.setEnabled(value);
    -  };
    -  return button;
    -};
    -
    -
    -/**
    - * Creates a toolbar button with the given ID, tooltip, and caption.  Applies
    - * any custom CSS class names to the button's caption element.  Used to create
    - * a font face button, filled with default fonts.
    - * @param {string} id Button ID; must equal a {@link goog.editor.Command} for
    - *     built-in buttons, anything else for custom buttons.
    - * @param {string} tooltip Tooltip to be shown on hover.
    - * @param {goog.ui.ControlContent} caption Button caption.
    - * @param {string=} opt_classNames CSS class name(s) to apply to the caption
    - *     element.
    - * @param {goog.ui.MenuButtonRenderer=} opt_renderer Button renderer; defaults
    - *     to {@link goog.ui.ToolbarMenuButtonRenderer} if unspecified.
    - * @param {goog.dom.DomHelper=} opt_domHelper DOM helper, used for DOM
    - *     creation; defaults to the current document if unspecified.
    - * @return {!goog.ui.Button} A toolbar button.
    - * @private
    - */
    -goog.ui.editor.DefaultToolbar.fontFaceFactory_ = function(id, tooltip,
    -    caption, opt_classNames, opt_renderer, opt_domHelper) {
    -  var button = goog.ui.editor.ToolbarFactory.makeSelectButton(id, tooltip,
    -      caption, opt_classNames, opt_renderer, opt_domHelper);
    -  goog.ui.editor.DefaultToolbar.addDefaultFonts(button);
    -  button.setDefaultCaption(goog.ui.editor.DefaultToolbar.MSG_FONT_NORMAL);
    -  // Font options don't have keyboard accelerators.
    -  goog.dom.classlist.add(
    -      goog.asserts.assert(button.getMenu().getContentElement()),
    -      goog.getCssName('goog-menu-noaccel'));
    -
    -  // How to update this button's state.
    -  button.updateFromValue = function(value) {
    -    // Normalize value to null or a non-empty string (sometimes we get
    -    // the empty string, sometimes we get false...), extract the substring
    -    // up to the first comma to get the primary font name, and normalize
    -    // to lowercase.  This allows us to map a font spec like "Arial,
    -    // Helvetica, sans-serif" to a font menu item.
    -    // TODO (attila): Try to make this more robust.
    -    var item = null;
    -    if (value && value.length > 0) {
    -      item = /** @type {goog.ui.MenuItem} */ (button.getMenu().getChild(
    -          goog.ui.editor.ToolbarFactory.getPrimaryFont(value)));
    -    }
    -    var selectedItem = button.getSelectedItem();
    -    if (item != selectedItem) {
    -      button.setSelectedItem(item);
    -    }
    -  };
    -  return button;
    -};
    -
    -
    -/**
    - * Creates a toolbar button with the given ID, tooltip, and caption.  Applies
    - * any custom CSS class names to the button's caption element. Use to create a
    - * font size button, filled with default font sizes.
    - * @param {string} id Button ID; must equal a {@link goog.editor.Command} for
    - *     built-in buttons, anything else for custom buttons.
    - * @param {string} tooltip Tooltip to be shown on hover.
    - * @param {goog.ui.ControlContent} caption Button caption.
    - * @param {string=} opt_classNames CSS class name(s) to apply to the caption
    - *     element.
    - * @param {goog.ui.MenuButtonRenderer=} opt_renderer Button renderer; defaults
    - *     to {@link goog.ui.ToolbarMebuButtonRenderer} if unspecified.
    - * @param {goog.dom.DomHelper=} opt_domHelper DOM helper, used for DOM
    - *     creation; defaults to the current document if unspecified.
    - * @return {!goog.ui.Button} A toolbar button.
    - * @private
    - */
    -goog.ui.editor.DefaultToolbar.fontSizeFactory_ = function(id, tooltip,
    -    caption, opt_classNames, opt_renderer, opt_domHelper) {
    -  var button = goog.ui.editor.ToolbarFactory.makeSelectButton(id, tooltip,
    -      caption, opt_classNames, opt_renderer, opt_domHelper);
    -  goog.ui.editor.DefaultToolbar.addDefaultFontSizes(button);
    -  button.setDefaultCaption(goog.ui.editor.DefaultToolbar.MSG_FONT_SIZE_NORMAL);
    -  // Font size options don't have keyboard accelerators.
    -  goog.dom.classlist.add(
    -      goog.asserts.assert(button.getMenu().getContentElement()),
    -      goog.getCssName('goog-menu-noaccel'));
    -  // How to update this button's state.
    -  button.updateFromValue = function(value) {
    -    // Webkit pre-534.7 returns a string like '32px' instead of the equivalent
    -    // integer, so normalize that first.
    -    // NOTE(user): Gecko returns "6" so can't just normalize all
    -    // strings, only ones ending in "px".
    -    if (goog.isString(value) &&
    -        goog.style.getLengthUnits(value) == 'px') {
    -      value = goog.ui.editor.ToolbarFactory.getLegacySizeFromPx(
    -          parseInt(value, 10));
    -    }
    -    // Normalize value to null or a positive integer (sometimes we get
    -    // the empty string, sometimes we get false, or -1 if the above
    -    // normalization didn't match to a particular 0-7 size)
    -    value = value > 0 ? value : null;
    -    if (value != button.getValue()) {
    -      button.setValue(value);
    -    }
    -  };
    -  return button;
    -};
    -
    -
    -/**
    - * Function to update the state of a color menu button.
    - * @param {goog.ui.ToolbarColorMenuButton} button The button to which the
    - *     color menu is attached.
    - * @param {number} color Color value to update to.
    - * @private
    - */
    -goog.ui.editor.DefaultToolbar.colorUpdateFromValue_ = function(button, color) {
    -  var value = color;
    -  /** @preserveTry */
    -  try {
    -    if (goog.userAgent.IE) {
    -      // IE returns a number that, converted to hex, is a BGR color.
    -      // Convert from decimal to BGR to RGB.
    -      var hex = '000000' + value.toString(16);
    -      var bgr = hex.substr(hex.length - 6, 6);
    -      value = '#' + bgr.substring(4, 6) + bgr.substring(2, 4) +
    -          bgr.substring(0, 2);
    -    }
    -    if (value != button.getValue()) {
    -      button.setValue(/** @type {string} */ (value));
    -    }
    -  } catch (ex) {
    -    // TODO(attila): Find out when/why this happens.
    -  }
    -};
    -
    -
    -/**
    - * Creates a toolbar button with the given ID, tooltip, and caption.  Applies
    - * any custom CSS class names to the button's caption element. Use to create
    - * a font color button.
    - * @param {string} id Button ID; must equal a {@link goog.editor.Command} for
    - *     built-in buttons, anything else for custom buttons.
    - * @param {string} tooltip Tooltip to be shown on hover.
    - * @param {goog.ui.ControlContent} caption Button caption.
    - * @param {string=} opt_classNames CSS class name(s) to apply to the caption
    - *     element.
    - * @param {goog.ui.ColorMenuButtonRenderer=} opt_renderer Button renderer;
    - *     defaults to {@link goog.ui.ToolbarColorMenuButtonRenderer} if
    - *     unspecified.
    - * @param {goog.dom.DomHelper=} opt_domHelper DOM helper, used for DOM
    - *     creation; defaults to the current document if unspecified.
    - * @return {!goog.ui.Button} A toolbar button.
    - * @private
    - */
    -goog.ui.editor.DefaultToolbar.fontColorFactory_ = function(id, tooltip,
    -    caption, opt_classNames, opt_renderer, opt_domHelper) {
    -  var button = goog.ui.editor.ToolbarFactory.makeColorMenuButton(id, tooltip,
    -      caption, opt_classNames, opt_renderer, opt_domHelper);
    -  // Initialize default foreground color.
    -  button.setSelectedColor('#000');
    -  button.updateFromValue = goog.partial(
    -      goog.ui.editor.DefaultToolbar.colorUpdateFromValue_, button);
    -  return button;
    -};
    -
    -
    -/**
    - * Creates a toolbar button with the given ID, tooltip, and caption.  Applies
    - * any custom CSS class names to the button's caption element. Use to create
    - * a font background color button.
    - * @param {string} id Button ID; must equal a {@link goog.editor.Command} for
    - *     built-in buttons, anything else for custom buttons.
    - * @param {string} tooltip Tooltip to be shown on hover.
    - * @param {goog.ui.ControlContent} caption Button caption.
    - * @param {string=} opt_classNames CSS class name(s) to apply to the caption
    - *     element.
    - * @param {goog.ui.ColorMenuButtonRenderer=} opt_renderer Button renderer;
    - *     defaults to {@link goog.ui.ToolbarColorMenuButtonRenderer} if
    - *     unspecified.
    - * @param {goog.dom.DomHelper=} opt_domHelper DOM helper, used for DOM
    - *     creation; defaults to the current document if unspecified.
    - * @return {!goog.ui.Button} A toolbar button.
    - * @private
    - */
    -goog.ui.editor.DefaultToolbar.backgroundColorFactory_ = function(id, tooltip,
    -    caption, opt_classNames, opt_renderer, opt_domHelper) {
    -  var button = goog.ui.editor.ToolbarFactory.makeColorMenuButton(id,
    -      tooltip, caption, opt_classNames, opt_renderer, opt_domHelper);
    -  // Initialize default background color.
    -  button.setSelectedColor('#FFF');
    -  button.updateFromValue = goog.partial(
    -      goog.ui.editor.DefaultToolbar.colorUpdateFromValue_, button);
    -  return button;
    -};
    -
    -
    -/**
    - * Creates a toolbar button with the given ID, tooltip, and caption.  Applies
    - * any custom CSS class names to the button's caption element. Use to create
    - * the format menu, prefilled with default formats.
    - * @param {string} id Button ID; must equal a {@link goog.editor.Command} for
    - *     built-in buttons, anything else for custom buttons.
    - * @param {string} tooltip Tooltip to be shown on hover.
    - * @param {goog.ui.ControlContent} caption Button caption.
    - * @param {string=} opt_classNames CSS class name(s) to apply to the caption
    - *     element.
    - * @param {goog.ui.MenuButtonRenderer=} opt_renderer Button renderer;
    - *     defaults to
    - *     {@link goog.ui.ToolbarMenuButtonRenderer} if unspecified.
    - * @param {goog.dom.DomHelper=} opt_domHelper DOM helper, used for DOM
    - *     creation; defaults to the current document if unspecified.
    - * @return {!goog.ui.Button} A toolbar button.
    - * @private
    - */
    -goog.ui.editor.DefaultToolbar.formatBlockFactory_ = function(id, tooltip,
    -    caption, opt_classNames, opt_renderer, opt_domHelper) {
    -  var button = goog.ui.editor.ToolbarFactory.makeSelectButton(id, tooltip,
    -      caption, opt_classNames, opt_renderer, opt_domHelper);
    -  goog.ui.editor.DefaultToolbar.addDefaultFormatOptions(button);
    -  button.setDefaultCaption(goog.ui.editor.DefaultToolbar.MSG_FORMAT_NORMAL);
    -  // Format options don't have keyboard accelerators.
    -  goog.dom.classlist.add(
    -      goog.asserts.assert(button.getMenu().getContentElement()),
    -      goog.getCssName('goog-menu-noaccel'));
    -  // How to update this button.
    -  button.updateFromValue = function(value) {
    -    // Normalize value to null or a nonempty string (sometimes we get
    -    // the empty string, sometimes we get false...)
    -    value = value && value.length > 0 ? value : null;
    -    if (value != button.getValue()) {
    -      button.setValue(value);
    -    }
    -  };
    -  return button;
    -};
    -
    -
    -// Messages used for tooltips and captions.
    -
    -
    -/** @desc Format menu tooltip. */
    -goog.ui.editor.DefaultToolbar.MSG_FORMAT_BLOCK_TITLE = goog.getMsg('Format');
    -
    -
    -/** @desc Format menu caption. */
    -goog.ui.editor.DefaultToolbar.MSG_FORMAT_BLOCK_CAPTION = goog.getMsg('Format');
    -
    -
    -/** @desc Undo button tooltip. */
    -goog.ui.editor.DefaultToolbar.MSG_UNDO_TITLE = goog.getMsg('Undo');
    -
    -
    -/** @desc Redo button tooltip. */
    -goog.ui.editor.DefaultToolbar.MSG_REDO_TITLE = goog.getMsg('Redo');
    -
    -
    -/** @desc Font menu tooltip. */
    -goog.ui.editor.DefaultToolbar.MSG_FONT_FACE_TITLE = goog.getMsg('Font');
    -
    -
    -/** @desc Font size menu tooltip. */
    -goog.ui.editor.DefaultToolbar.MSG_FONT_SIZE_TITLE = goog.getMsg('Font size');
    -
    -
    -/** @desc Text foreground color menu tooltip. */
    -goog.ui.editor.DefaultToolbar.MSG_FONT_COLOR_TITLE = goog.getMsg('Text color');
    -
    -
    -/** @desc Bold button tooltip. */
    -goog.ui.editor.DefaultToolbar.MSG_BOLD_TITLE = goog.getMsg('Bold');
    -
    -
    -/** @desc Italic button tooltip. */
    -goog.ui.editor.DefaultToolbar.MSG_ITALIC_TITLE = goog.getMsg('Italic');
    -
    -
    -/** @desc Underline button tooltip. */
    -goog.ui.editor.DefaultToolbar.MSG_UNDERLINE_TITLE = goog.getMsg('Underline');
    -
    -
    -/** @desc Text background color menu tooltip. */
    -goog.ui.editor.DefaultToolbar.MSG_BACKGROUND_COLOR_TITLE =
    -    goog.getMsg('Text background color');
    -
    -
    -/** @desc Link button tooltip. */
    -goog.ui.editor.DefaultToolbar.MSG_LINK_TITLE =
    -    goog.getMsg('Add or remove link');
    -
    -
    -/** @desc Numbered list button tooltip. */
    -goog.ui.editor.DefaultToolbar.MSG_ORDERED_LIST_TITLE =
    -    goog.getMsg('Numbered list');
    -
    -
    -/** @desc Bullet list button tooltip. */
    -goog.ui.editor.DefaultToolbar.MSG_UNORDERED_LIST_TITLE =
    -    goog.getMsg('Bullet list');
    -
    -
    -/** @desc Outdent button tooltip. */
    -goog.ui.editor.DefaultToolbar.MSG_OUTDENT_TITLE =
    -    goog.getMsg('Decrease indent');
    -
    -
    -/** @desc Indent button tooltip. */
    -goog.ui.editor.DefaultToolbar.MSG_INDENT_TITLE = goog.getMsg('Increase indent');
    -
    -
    -/** @desc Align left button tooltip. */
    -goog.ui.editor.DefaultToolbar.MSG_ALIGN_LEFT_TITLE = goog.getMsg('Align left');
    -
    -
    -/** @desc Align center button tooltip. */
    -goog.ui.editor.DefaultToolbar.MSG_ALIGN_CENTER_TITLE =
    -    goog.getMsg('Align center');
    -
    -
    -/** @desc Align right button tooltip. */
    -goog.ui.editor.DefaultToolbar.MSG_ALIGN_RIGHT_TITLE =
    -    goog.getMsg('Align right');
    -
    -
    -/** @desc Justify button tooltip. */
    -goog.ui.editor.DefaultToolbar.MSG_JUSTIFY_TITLE = goog.getMsg('Justify');
    -
    -
    -/** @desc Remove formatting button tooltip. */
    -goog.ui.editor.DefaultToolbar.MSG_REMOVE_FORMAT_TITLE =
    -    goog.getMsg('Remove formatting');
    -
    -
    -/** @desc Insert image button tooltip. */
    -goog.ui.editor.DefaultToolbar.MSG_IMAGE_TITLE = goog.getMsg('Insert image');
    -
    -
    -/** @desc Strike through button tooltip. */
    -goog.ui.editor.DefaultToolbar.MSG_STRIKE_THROUGH_TITLE =
    -    goog.getMsg('Strikethrough');
    -
    -
    -/** @desc Left-to-right button tooltip. */
    -goog.ui.editor.DefaultToolbar.MSG_DIR_LTR_TITLE = goog.getMsg('Left-to-right');
    -
    -
    -/** @desc Right-to-left button tooltip. */
    -goog.ui.editor.DefaultToolbar.MSG_DIR_RTL_TITLE = goog.getMsg('Right-to-left');
    -
    -
    -/** @desc Blockquote button tooltip. */
    -goog.ui.editor.DefaultToolbar.MSG_BLOCKQUOTE_TITLE = goog.getMsg('Quote');
    -
    -
    -/** @desc Edit HTML button tooltip. */
    -goog.ui.editor.DefaultToolbar.MSG_EDIT_HTML_TITLE =
    -    goog.getMsg('Edit HTML source');
    -
    -
    -/** @desc Subscript button tooltip. */
    -goog.ui.editor.DefaultToolbar.MSG_SUBSCRIPT = goog.getMsg('Subscript');
    -
    -
    -/** @desc Superscript button tooltip. */
    -goog.ui.editor.DefaultToolbar.MSG_SUPERSCRIPT = goog.getMsg('Superscript');
    -
    -
    -/** @desc Edit HTML button caption. */
    -goog.ui.editor.DefaultToolbar.MSG_EDIT_HTML_CAPTION = goog.getMsg('Edit HTML');
    -
    -
    -/**
    - * Map of {@code goog.editor.Command}s to toolbar button descriptor objects,
    - * each of which has the following attributes:
    - * <ul>
    - *   <li>{@code command} - The command corresponding to the
    - *       button (mandatory)
    - *   <li>{@code tooltip} - Tooltip text (optional); if unspecified, the button
    - *       has no hover text
    - *   <li>{@code caption} - Caption to display on the button (optional); if
    - *       unspecified, the button has no text caption
    - *   <li>{@code classes} - CSS class name(s) to be applied to the button's
    - *       element when rendered (optional); if unspecified, defaults to
    - *       'tr-icon'
    - *       plus 'tr-' followed by the command ID, but without any leading '+'
    - *       character (e.g. if the command ID is '+undo', then {@code classes}
    - *       defaults to 'tr-icon tr-undo')
    - *   <li>{@code factory} - factory function used to create the button, which
    - *       must accept {@code id}, {@code tooltip}, {@code caption}, and
    - *       {@code classes} as arguments, and must return an instance of
    - *       {@link goog.ui.Button} or an appropriate subclass (optional); if
    - *       unspecified, defaults to
    - *       {@link goog.ui.editor.DefaultToolbar.makeToggleButton},
    - *       since most built-in toolbar buttons are toggle buttons
    - *   <li>(@code queryable} - Whether the button's state should be queried
    - *       when updating the toolbar (optional).
    - * </ul>
    - * Note that this object is only used for creating toolbar buttons for
    - * built-in editor commands; custom buttons aren't listed here.  Please don't
    - * try to hack this!
    - * @private {!Object<!goog.ui.editor.ButtonDescriptor>}.
    - */
    -goog.ui.editor.DefaultToolbar.buttons_ = {};
    -
    -
    -/**
    - * @typedef {{command: string, tooltip: ?string,
    - *   caption: ?goog.ui.ControlContent, classes: ?string,
    - *   factory: ?function(string, string, goog.ui.ControlContent, ?string,
    - *       goog.ui.ButtonRenderer, goog.dom.DomHelper):goog.ui.Button,
    - *   queryable:?boolean}}
    - */
    -goog.ui.editor.ButtonDescriptor;
    -
    -
    -/**
    - * Built-in toolbar button descriptors.  See
    - * {@link goog.ui.editor.DefaultToolbar.buttons_} for details on button
    - * descriptor objects.  This array is processed at JS parse time; each item is
    - * inserted into {@link goog.ui.editor.DefaultToolbar.buttons_}, and the array
    - * itself is deleted and (hopefully) garbage-collected.
    - * @private {Array<!goog.ui.editor.ButtonDescriptor>}
    - */
    -goog.ui.editor.DefaultToolbar.button_list_ = [{
    -  command: goog.editor.Command.UNDO,
    -  tooltip: goog.ui.editor.DefaultToolbar.MSG_UNDO_TITLE,
    -  classes: goog.getCssName('tr-icon') + ' ' + goog.getCssName('tr-undo'),
    -  factory: goog.ui.editor.DefaultToolbar.undoRedoButtonFactory_,
    -  queryable: true
    -}, {
    -  command: goog.editor.Command.REDO,
    -  tooltip: goog.ui.editor.DefaultToolbar.MSG_REDO_TITLE,
    -  classes: goog.getCssName('tr-icon') + ' ' + goog.getCssName('tr-redo'),
    -  factory: goog.ui.editor.DefaultToolbar.undoRedoButtonFactory_,
    -  queryable: true
    -}, {
    -  command: goog.editor.Command.FONT_FACE,
    -  tooltip: goog.ui.editor.DefaultToolbar.MSG_FONT_FACE_TITLE,
    -  classes: goog.getCssName('tr-fontName'),
    -  factory: goog.ui.editor.DefaultToolbar.fontFaceFactory_,
    -  queryable: true
    -}, {
    -  command: goog.editor.Command.FONT_SIZE,
    -  tooltip: goog.ui.editor.DefaultToolbar.MSG_FONT_SIZE_TITLE,
    -  classes: goog.getCssName('tr-fontSize'),
    -  factory: goog.ui.editor.DefaultToolbar.fontSizeFactory_,
    -  queryable: true
    -}, {
    -  command: goog.editor.Command.BOLD,
    -  tooltip: goog.ui.editor.DefaultToolbar.MSG_BOLD_TITLE,
    -  classes: goog.getCssName('tr-icon') + ' ' + goog.getCssName('tr-bold'),
    -  queryable: true
    -}, {
    -  command: goog.editor.Command.ITALIC,
    -  tooltip: goog.ui.editor.DefaultToolbar.MSG_ITALIC_TITLE,
    -  classes: goog.getCssName('tr-icon') + ' ' + goog.getCssName('tr-italic'),
    -  queryable: true
    -}, {
    -  command: goog.editor.Command.UNDERLINE,
    -  tooltip: goog.ui.editor.DefaultToolbar.MSG_UNDERLINE_TITLE,
    -  classes: goog.getCssName('tr-icon') + ' ' + goog.getCssName('tr-underline'),
    -  queryable: true
    -}, {
    -  command: goog.editor.Command.FONT_COLOR,
    -  tooltip: goog.ui.editor.DefaultToolbar.MSG_FONT_COLOR_TITLE,
    -  classes: goog.getCssName('tr-icon') + ' ' + goog.getCssName('tr-foreColor'),
    -  factory: goog.ui.editor.DefaultToolbar.fontColorFactory_,
    -  queryable: true
    -}, {
    -  command: goog.editor.Command.BACKGROUND_COLOR,
    -  tooltip: goog.ui.editor.DefaultToolbar.MSG_BACKGROUND_COLOR_TITLE,
    -  classes: goog.getCssName('tr-icon') + ' ' + goog.getCssName('tr-backColor'),
    -  factory: goog.ui.editor.DefaultToolbar.backgroundColorFactory_,
    -  queryable: true
    -}, {
    -  command: goog.editor.Command.LINK,
    -  tooltip: goog.ui.editor.DefaultToolbar.MSG_LINK_TITLE,
    -  caption: goog.ui.editor.messages.MSG_LINK_CAPTION,
    -  classes: goog.getCssName('tr-link'),
    -  queryable: true
    -}, {
    -  command: goog.editor.Command.ORDERED_LIST,
    -  tooltip: goog.ui.editor.DefaultToolbar.MSG_ORDERED_LIST_TITLE,
    -  classes: goog.getCssName('tr-icon') + ' ' +
    -      goog.getCssName('tr-insertOrderedList'),
    -  queryable: true
    -}, {
    -  command: goog.editor.Command.UNORDERED_LIST,
    -  tooltip: goog.ui.editor.DefaultToolbar.MSG_UNORDERED_LIST_TITLE,
    -  classes: goog.getCssName('tr-icon') + ' ' +
    -      goog.getCssName('tr-insertUnorderedList'),
    -  queryable: true
    -}, {
    -  command: goog.editor.Command.OUTDENT,
    -  tooltip: goog.ui.editor.DefaultToolbar.MSG_OUTDENT_TITLE,
    -  classes: goog.getCssName('tr-icon') + ' ' + goog.getCssName('tr-outdent'),
    -  factory: goog.ui.editor.ToolbarFactory.makeButton
    -}, {
    -  command: goog.editor.Command.INDENT,
    -  tooltip: goog.ui.editor.DefaultToolbar.MSG_INDENT_TITLE,
    -  classes: goog.getCssName('tr-icon') + ' ' + goog.getCssName('tr-indent'),
    -  factory: goog.ui.editor.ToolbarFactory.makeButton
    -}, {
    -  command: goog.editor.Command.JUSTIFY_LEFT,
    -  tooltip: goog.ui.editor.DefaultToolbar.MSG_ALIGN_LEFT_TITLE,
    -  classes: goog.getCssName('tr-icon') + ' ' +
    -      goog.getCssName('tr-justifyLeft'),
    -  queryable: true
    -}, {
    -  command: goog.editor.Command.JUSTIFY_CENTER,
    -  tooltip: goog.ui.editor.DefaultToolbar.MSG_ALIGN_CENTER_TITLE,
    -  classes: goog.getCssName('tr-icon') + ' ' +
    -      goog.getCssName('tr-justifyCenter'),
    -  queryable: true
    -}, {
    -  command: goog.editor.Command.JUSTIFY_RIGHT,
    -  tooltip: goog.ui.editor.DefaultToolbar.MSG_ALIGN_RIGHT_TITLE,
    -  classes: goog.getCssName('tr-icon') + ' ' +
    -      goog.getCssName('tr-justifyRight'),
    -  queryable: true
    -}, {
    -  command: goog.editor.Command.JUSTIFY_FULL,
    -  tooltip: goog.ui.editor.DefaultToolbar.MSG_JUSTIFY_TITLE,
    -  classes: goog.getCssName('tr-icon') + ' ' +
    -      goog.getCssName('tr-justifyFull'),
    -  queryable: true
    -}, {
    -  command: goog.editor.Command.REMOVE_FORMAT,
    -  tooltip: goog.ui.editor.DefaultToolbar.MSG_REMOVE_FORMAT_TITLE,
    -  classes: goog.getCssName('tr-icon') + ' ' +
    -      goog.getCssName('tr-removeFormat'),
    -  factory: goog.ui.editor.ToolbarFactory.makeButton
    -}, {
    -  command: goog.editor.Command.IMAGE,
    -  tooltip: goog.ui.editor.DefaultToolbar.MSG_IMAGE_TITLE,
    -  classes: goog.getCssName('tr-icon') + ' ' + goog.getCssName('tr-image'),
    -  factory: goog.ui.editor.ToolbarFactory.makeButton
    -}, {
    -  command: goog.editor.Command.STRIKE_THROUGH,
    -  tooltip: goog.ui.editor.DefaultToolbar.MSG_STRIKE_THROUGH_TITLE,
    -  classes: goog.getCssName('tr-icon') + ' ' +
    -      goog.getCssName('tr-strikeThrough'),
    -  queryable: true
    -}, {
    -  command: goog.editor.Command.SUBSCRIPT,
    -  tooltip: goog.ui.editor.DefaultToolbar.MSG_SUBSCRIPT,
    -  classes: goog.getCssName('tr-icon') + ' ' + goog.getCssName('tr-subscript'),
    -  queryable: true
    -} , {
    -  command: goog.editor.Command.SUPERSCRIPT,
    -  tooltip: goog.ui.editor.DefaultToolbar.MSG_SUPERSCRIPT,
    -  classes: goog.getCssName('tr-icon') + ' ' +
    -      goog.getCssName('tr-superscript'),
    -  queryable: true
    -}, {
    -  command: goog.editor.Command.DIR_LTR,
    -  tooltip: goog.ui.editor.DefaultToolbar.MSG_DIR_LTR_TITLE,
    -  classes: goog.getCssName('tr-icon') + ' ' + goog.getCssName('tr-ltr'),
    -  queryable: true
    -}, {
    -  command: goog.editor.Command.DIR_RTL,
    -  tooltip: goog.ui.editor.DefaultToolbar.MSG_DIR_RTL_TITLE,
    -  classes: goog.getCssName('tr-icon') + ' ' + goog.getCssName('tr-rtl'),
    -  factory: goog.ui.editor.DefaultToolbar.rtlButtonFactory_,
    -  queryable: true
    -}, {
    -  command: goog.editor.Command.BLOCKQUOTE,
    -  tooltip: goog.ui.editor.DefaultToolbar.MSG_BLOCKQUOTE_TITLE,
    -  classes: goog.getCssName('tr-icon') + ' ' +
    -      goog.getCssName('tr-BLOCKQUOTE'),
    -  queryable: true
    -}, {
    -  command: goog.editor.Command.FORMAT_BLOCK,
    -  tooltip: goog.ui.editor.DefaultToolbar.MSG_FORMAT_BLOCK_TITLE,
    -  caption: goog.ui.editor.DefaultToolbar.MSG_FORMAT_BLOCK_CAPTION,
    -  classes: goog.getCssName('tr-formatBlock'),
    -  factory: goog.ui.editor.DefaultToolbar.formatBlockFactory_,
    -  queryable: true
    -}, {
    -  command: goog.editor.Command.EDIT_HTML,
    -  tooltip: goog.ui.editor.DefaultToolbar.MSG_EDIT_HTML_TITLE,
    -  caption: goog.ui.editor.DefaultToolbar.MSG_EDIT_HTML_CAPTION,
    -  classes: goog.getCssName('tr-editHtml'),
    -  factory: goog.ui.editor.ToolbarFactory.makeButton
    -}];
    -
    -
    -(function() {
    -  // Create the goog.ui.editor.DefaultToolbar.buttons_ map from
    -  // goog.ui.editor.DefaultToolbar.button_list_.
    -  for (var i = 0, button;
    -      button = goog.ui.editor.DefaultToolbar.button_list_[i]; i++) {
    -    goog.ui.editor.DefaultToolbar.buttons_[button.command] = button;
    -  }
    -
    -  // goog.ui.editor.DefaultToolbar.button_list_ is no longer needed
    -  // once the map is ready.
    -  goog.ui.editor.DefaultToolbar.button_list_ = null;
    -})();
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/editor/linkdialog.js b/src/database/third_party/closure-library/closure/goog/ui/editor/linkdialog.js
    deleted file mode 100644
    index 83c63ef150e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/editor/linkdialog.js
    +++ /dev/null
    @@ -1,1063 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A dialog for editing/creating a link.
    - *
    - * @author robbyw@google.com (Robby Walker)
    - */
    -
    -goog.provide('goog.ui.editor.LinkDialog');
    -goog.provide('goog.ui.editor.LinkDialog.BeforeTestLinkEvent');
    -goog.provide('goog.ui.editor.LinkDialog.EventType');
    -goog.provide('goog.ui.editor.LinkDialog.OkEvent');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.dom.safe');
    -goog.require('goog.editor.BrowserFeature');
    -goog.require('goog.editor.Link');
    -goog.require('goog.editor.focus');
    -goog.require('goog.editor.node');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.InputHandler');
    -goog.require('goog.html.SafeHtml');
    -goog.require('goog.string');
    -goog.require('goog.string.Unicode');
    -goog.require('goog.style');
    -goog.require('goog.ui.Button');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.LinkButtonRenderer');
    -goog.require('goog.ui.editor.AbstractDialog');
    -goog.require('goog.ui.editor.TabPane');
    -goog.require('goog.ui.editor.messages');
    -goog.require('goog.userAgent');
    -goog.require('goog.window');
    -
    -
    -
    -/**
    - * A type of goog.ui.editor.AbstractDialog for editing/creating a link.
    - * @param {goog.dom.DomHelper} domHelper DomHelper to be used to create the
    - *     dialog's dom structure.
    - * @param {goog.editor.Link} link The target link.
    - * @constructor
    - * @extends {goog.ui.editor.AbstractDialog}
    - * @final
    - */
    -goog.ui.editor.LinkDialog = function(domHelper, link) {
    -  goog.ui.editor.LinkDialog.base(this, 'constructor', domHelper);
    -
    -  /**
    -   * The link being modified by this dialog.
    -   * @type {goog.editor.Link}
    -   * @private
    -   */
    -  this.targetLink_ = link;
    -
    -  /**
    -   * The event handler for this dialog.
    -   * @type {goog.events.EventHandler<!goog.ui.editor.LinkDialog>}
    -   * @private
    -   */
    -  this.eventHandler_ = new goog.events.EventHandler(this);
    -  this.registerDisposable(this.eventHandler_);
    -
    -  /**
    -   * Optional warning to show about email addresses.
    -   * @type {goog.html.SafeHtml}
    -   * @private
    -   */
    -  this.emailWarning_ = null;
    -
    -  /**
    -   * Whether to show a checkbox where the user can choose to have the link open
    -   * in a new window.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.showOpenLinkInNewWindow_ = false;
    -
    -  /**
    -   * Whether the "open link in new window" checkbox should be checked when the
    -   * dialog is shown, and also whether it was checked last time the dialog was
    -   * closed.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.isOpenLinkInNewWindowChecked_ = false;
    -
    -  /**
    -   * Whether to show a checkbox where the user can choose to have 'rel=nofollow'
    -   * attribute added to the link.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.showRelNoFollow_ = false;
    -
    -  /**
    -   * InputHandler object to listen for changes in the url input field.
    -   * @type {goog.events.InputHandler}
    -   * @private
    -   */
    -  this.urlInputHandler_ = null;
    -
    -  /**
    -   * InputHandler object to listen for changes in the email input field.
    -   * @type {goog.events.InputHandler}
    -   * @private
    -   */
    -  this.emailInputHandler_ = null;
    -
    -  /**
    -   * InputHandler object to listen for changes in the text to display input
    -   * field.
    -   * @type {goog.events.InputHandler}
    -   * @private
    -   */
    -  this.textInputHandler_ = null;
    -
    -  /**
    -   * The tab bar where the url and email tabs are.
    -   * @type {goog.ui.editor.TabPane}
    -   * @private
    -   */
    -  this.tabPane_ = null;
    -
    -  /**
    -   * The div element holding the link's display text input.
    -   * @type {HTMLDivElement}
    -   * @private
    -   */
    -  this.textToDisplayDiv_ = null;
    -
    -  /**
    -   * The input element holding the link's display text.
    -   * @type {HTMLInputElement}
    -   * @private
    -   */
    -  this.textToDisplayInput_ = null;
    -
    -  /**
    -   * Whether or not the feature of automatically generating the display text is
    -   * enabled.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.autogenFeatureEnabled_ = true;
    -
    -  /**
    -   * Whether or not we should automatically generate the display text.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.autogenerateTextToDisplay_ = false;
    -
    -  /**
    -   * Whether or not automatic generation of the display text is disabled.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.disableAutogen_ = false;
    -
    -  /**
    -   * The input element (checkbox) to indicate that the link should open in a new
    -   * window.
    -   * @type {HTMLInputElement}
    -   * @private
    -   */
    -  this.openInNewWindowCheckbox_ = null;
    -
    -  /**
    -   * The input element (checkbox) to indicate that the link should have
    -   * 'rel=nofollow' attribute.
    -   * @type {HTMLInputElement}
    -   * @private
    -   */
    -  this.relNoFollowCheckbox_ = null;
    -
    -  /**
    -   * Whether to stop leaking the page's url via the referrer header when the
    -   * "test this link" link is clicked.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.stopReferrerLeaks_ = false;
    -};
    -goog.inherits(goog.ui.editor.LinkDialog, goog.ui.editor.AbstractDialog);
    -
    -
    -/**
    - * Events specific to the link dialog.
    - * @enum {string}
    - */
    -goog.ui.editor.LinkDialog.EventType = {
    -  BEFORE_TEST_LINK: 'beforetestlink'
    -};
    -
    -
    -
    -/**
    - * OK event object for the link dialog.
    - * @param {string} linkText Text the user chose to display for the link.
    - * @param {string} linkUrl Url the user chose for the link to point to.
    - * @param {boolean} openInNewWindow Whether the link should open in a new window
    - *     when clicked.
    - * @param {boolean} noFollow Whether the link should have 'rel=nofollow'
    - *     attribute.
    - * @constructor
    - * @extends {goog.events.Event}
    - * @final
    - */
    -goog.ui.editor.LinkDialog.OkEvent = function(
    -    linkText, linkUrl, openInNewWindow, noFollow) {
    -  goog.ui.editor.LinkDialog.OkEvent.base(this, 'constructor',
    -      goog.ui.editor.AbstractDialog.EventType.OK);
    -
    -  /**
    -   * The text of the link edited in the dialog.
    -   * @type {string}
    -   */
    -  this.linkText = linkText;
    -
    -  /**
    -   * The url of the link edited in the dialog.
    -   * @type {string}
    -   */
    -  this.linkUrl = linkUrl;
    -
    -  /**
    -   * Whether the link should open in a new window when clicked.
    -   * @type {boolean}
    -   */
    -  this.openInNewWindow = openInNewWindow;
    -
    -  /**
    -   * Whether the link should have 'rel=nofollow' attribute.
    -   * @type {boolean}
    -   */
    -  this.noFollow = noFollow;
    -};
    -goog.inherits(goog.ui.editor.LinkDialog.OkEvent, goog.events.Event);
    -
    -
    -
    -/**
    - * Event fired before testing a link by opening it in another window.
    - * Calling preventDefault will stop the link from being opened.
    - * @param {string} url Url of the link being tested.
    - * @constructor
    - * @extends {goog.events.Event}
    - * @final
    - */
    -goog.ui.editor.LinkDialog.BeforeTestLinkEvent = function(url) {
    -  goog.ui.editor.LinkDialog.BeforeTestLinkEvent.base(this, 'constructor',
    -      goog.ui.editor.LinkDialog.EventType.BEFORE_TEST_LINK);
    -
    -  /**
    -   * The url of the link being tested.
    -   * @type {string}
    -   */
    -  this.url = url;
    -};
    -goog.inherits(goog.ui.editor.LinkDialog.BeforeTestLinkEvent, goog.events.Event);
    -
    -
    -/**
    - * Sets the warning message to show to users about including email addresses on
    - * public web pages.
    - * @param {!goog.html.SafeHtml} emailWarning Warning message to show users about
    - *     including email addresses on the web.
    - */
    -goog.ui.editor.LinkDialog.prototype.setEmailWarning = function(
    -    emailWarning) {
    -  this.emailWarning_ = emailWarning;
    -};
    -
    -
    -/**
    - * Tells the dialog to show a checkbox where the user can choose to have the
    - * link open in a new window.
    - * @param {boolean} startChecked Whether to check the checkbox the first
    - *     time the dialog is shown. Subesquent times the checkbox will remember its
    - *     previous state.
    - */
    -goog.ui.editor.LinkDialog.prototype.showOpenLinkInNewWindow = function(
    -    startChecked) {
    -  this.showOpenLinkInNewWindow_ = true;
    -  this.isOpenLinkInNewWindowChecked_ = startChecked;
    -};
    -
    -
    -/**
    - * Tells the dialog to show a checkbox where the user can choose to add
    - * 'rel=nofollow' attribute to the link.
    - */
    -goog.ui.editor.LinkDialog.prototype.showRelNoFollow = function() {
    -  this.showRelNoFollow_ = true;
    -};
    -
    -
    -/** @override */
    -goog.ui.editor.LinkDialog.prototype.show = function() {
    -  goog.ui.editor.LinkDialog.base(this, 'show');
    -
    -
    -  this.selectAppropriateTab_(this.textToDisplayInput_.value,
    -                             this.getTargetUrl_());
    -  this.syncOkButton_();
    -
    -  if (this.showOpenLinkInNewWindow_) {
    -    if (!this.targetLink_.isNew()) {
    -      // If link is not new, checkbox should reflect current target.
    -      this.isOpenLinkInNewWindowChecked_ =
    -          this.targetLink_.getAnchor().target == '_blank';
    -    }
    -    this.openInNewWindowCheckbox_.checked = this.isOpenLinkInNewWindowChecked_;
    -  }
    -
    -  if (this.showRelNoFollow_) {
    -    this.relNoFollowCheckbox_.checked =
    -        goog.ui.editor.LinkDialog.hasNoFollow(this.targetLink_.getAnchor().rel);
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.editor.LinkDialog.prototype.hide = function() {
    -  this.disableAutogenFlag_(false);
    -  goog.ui.editor.LinkDialog.base(this, 'hide');
    -};
    -
    -
    -/**
    - * Tells the dialog whether to show the 'text to display' div.
    - * When the target element of the dialog is an image, there is no link text
    - * to modify. This function can be used for this kind of situations.
    - * @param {boolean} visible Whether to make 'text to display' div visible.
    - */
    -goog.ui.editor.LinkDialog.prototype.setTextToDisplayVisible = function(
    -    visible) {
    -  if (this.textToDisplayDiv_) {
    -    goog.style.setStyle(this.textToDisplayDiv_, 'display',
    -                        visible ? 'block' : 'none');
    -  }
    -};
    -
    -
    -/**
    - * Tells the plugin whether to stop leaking the page's url via the referrer
    - * header when the "test this link" link is clicked.
    - * @param {boolean} stop Whether to stop leaking the referrer.
    - */
    -goog.ui.editor.LinkDialog.prototype.setStopReferrerLeaks = function(stop) {
    -  this.stopReferrerLeaks_ = stop;
    -};
    -
    -
    -/**
    - * Tells the dialog whether the autogeneration of text to display is to be
    - * enabled.
    - * @param {boolean} enable Whether to enable the feature.
    - */
    -goog.ui.editor.LinkDialog.prototype.setAutogenFeatureEnabled = function(
    -    enable) {
    -  this.autogenFeatureEnabled_ = enable;
    -};
    -
    -
    -/**
    - * Checks if {@code str} contains {@code "nofollow"} as a separate word.
    - * @param {string} str String to be tested.  This is usually {@code rel}
    - *     attribute of an {@code HTMLAnchorElement} object.
    - * @return {boolean} {@code true} if {@code str} contains {@code nofollow}.
    - */
    -goog.ui.editor.LinkDialog.hasNoFollow = function(str) {
    -  return goog.ui.editor.LinkDialog.NO_FOLLOW_REGEX_.test(str);
    -};
    -
    -
    -/**
    - * Removes {@code "nofollow"} from {@code rel} if it's present as a separate
    - * word.
    - * @param {string} rel Input string.  This is usually {@code rel} attribute of
    - *     an {@code HTMLAnchorElement} object.
    - * @return {string} {@code rel} with any {@code "nofollow"} removed.
    - */
    -goog.ui.editor.LinkDialog.removeNoFollow = function(rel) {
    -  return rel.replace(goog.ui.editor.LinkDialog.NO_FOLLOW_REGEX_, '');
    -};
    -
    -
    -// *** Protected interface ************************************************** //
    -
    -
    -/** @override */
    -goog.ui.editor.LinkDialog.prototype.createDialogControl = function() {
    -  var builder = new goog.ui.editor.AbstractDialog.Builder(this);
    -  builder.setTitle(goog.ui.editor.messages.MSG_EDIT_LINK)
    -      .setContent(this.createDialogContent_());
    -  return builder.build();
    -};
    -
    -
    -/**
    - * Creates and returns the event object to be used when dispatching the OK
    - * event to listeners based on which tab is currently selected and the contents
    - * of the input fields of that tab.
    - * @return {!goog.ui.editor.LinkDialog.OkEvent} The event object to be used when
    - *     dispatching the OK event to listeners.
    - * @protected
    - * @override
    - */
    -goog.ui.editor.LinkDialog.prototype.createOkEvent = function() {
    -  if (this.tabPane_.getCurrentTabId() ==
    -      goog.ui.editor.LinkDialog.Id_.EMAIL_ADDRESS_TAB) {
    -    return this.createOkEventFromEmailTab_();
    -  } else {
    -    return this.createOkEventFromWebTab_();
    -  }
    -};
    -
    -
    -// *** Private implementation *********************************************** //
    -
    -
    -/**
    - * Regular expression that matches {@code nofollow} value in an
    - * {@code * HTMLAnchorElement}'s {@code rel} element.
    - * @type {RegExp}
    - * @private
    - */
    -goog.ui.editor.LinkDialog.NO_FOLLOW_REGEX_ = /\bnofollow\b/i;
    -
    -
    -/**
    - * Creates contents of this dialog.
    - * @return {!Element} Contents of the dialog as a DOM element.
    - * @private
    - */
    -goog.ui.editor.LinkDialog.prototype.createDialogContent_ = function() {
    -  this.textToDisplayDiv_ = /** @type {!HTMLDivElement} */(
    -      this.buildTextToDisplayDiv_());
    -  var content = this.dom.createDom(goog.dom.TagName.DIV, null,
    -      this.textToDisplayDiv_);
    -
    -  this.tabPane_ = new goog.ui.editor.TabPane(this.dom,
    -      goog.ui.editor.messages.MSG_LINK_TO);
    -  this.registerDisposable(this.tabPane_);
    -  this.tabPane_.addTab(goog.ui.editor.LinkDialog.Id_.ON_WEB_TAB,
    -      goog.ui.editor.messages.MSG_ON_THE_WEB,
    -      goog.ui.editor.messages.MSG_ON_THE_WEB_TIP,
    -      goog.ui.editor.LinkDialog.BUTTON_GROUP_,
    -      this.buildTabOnTheWeb_());
    -  this.tabPane_.addTab(goog.ui.editor.LinkDialog.Id_.EMAIL_ADDRESS_TAB,
    -      goog.ui.editor.messages.MSG_EMAIL_ADDRESS,
    -      goog.ui.editor.messages.MSG_EMAIL_ADDRESS_TIP,
    -      goog.ui.editor.LinkDialog.BUTTON_GROUP_,
    -      this.buildTabEmailAddress_());
    -  this.tabPane_.render(content);
    -
    -  this.eventHandler_.listen(this.tabPane_, goog.ui.Component.EventType.SELECT,
    -      this.onChangeTab_);
    -
    -  if (this.showOpenLinkInNewWindow_) {
    -    content.appendChild(this.buildOpenInNewWindowDiv_());
    -  }
    -  if (this.showRelNoFollow_) {
    -    content.appendChild(this.buildRelNoFollowDiv_());
    -  }
    -
    -  return content;
    -};
    -
    -
    -/**
    - * Builds and returns the text to display section of the edit link dialog.
    - * @return {!Element} A div element to be appended into the dialog div.
    - * @private
    - */
    -goog.ui.editor.LinkDialog.prototype.buildTextToDisplayDiv_ = function() {
    -  var table = this.dom.createTable(1, 2);
    -  table.cellSpacing = '0';
    -  table.cellPadding = '0';
    -  table.style.fontSize = '10pt';
    -  // Build the text to display input.
    -  var textToDisplayDiv = this.dom.createDom(goog.dom.TagName.DIV);
    -  var html = goog.html.SafeHtml.create('span', {
    -    'style': {
    -      'position': 'relative',
    -      'bottom': '2px',
    -      'padding-right': '1px',
    -      'white-space': 'nowrap'
    -    },
    -    id: goog.ui.editor.LinkDialog.Id_.TEXT_TO_DISPLAY_LABEL
    -  }, [goog.ui.editor.messages.MSG_TEXT_TO_DISPLAY, goog.string.Unicode.NBSP]);
    -  goog.dom.safe.setInnerHtml(table.rows[0].cells[0], html);
    -  this.textToDisplayInput_ = /** @type {!HTMLInputElement} */(
    -      this.dom.createDom(goog.dom.TagName.INPUT,
    -          {id: goog.ui.editor.LinkDialog.Id_.TEXT_TO_DISPLAY}));
    -  var textInput = this.textToDisplayInput_;
    -  // 98% prevents scroll bars in standards mode.
    -  // TODO(robbyw): Is this necessary for quirks mode?
    -  goog.style.setStyle(textInput, 'width', '98%');
    -  goog.style.setStyle(table.rows[0].cells[1], 'width', '100%');
    -  goog.dom.appendChild(table.rows[0].cells[1], textInput);
    -
    -  goog.a11y.aria.setState(/** @type {!Element} */ (textInput),
    -      goog.a11y.aria.State.LABELLEDBY,
    -      goog.ui.editor.LinkDialog.Id_.TEXT_TO_DISPLAY_LABEL);
    -  textInput.value = this.targetLink_.getCurrentText();
    -
    -  this.textInputHandler_ = new goog.events.InputHandler(textInput);
    -  this.registerDisposable(this.textInputHandler_);
    -  this.eventHandler_.listen(this.textInputHandler_,
    -      goog.events.InputHandler.EventType.INPUT, this.onTextToDisplayEdit_);
    -
    -  goog.dom.appendChild(textToDisplayDiv, table);
    -  return textToDisplayDiv;
    -};
    -
    -
    -/**
    - * Builds and returns the "checkbox to open the link in a new window" section of
    - * the edit link dialog.
    - * @return {!Element} A div element to be appended into the dialog div.
    - * @private
    - */
    -goog.ui.editor.LinkDialog.prototype.buildOpenInNewWindowDiv_ = function() {
    -  this.openInNewWindowCheckbox_ = /** @type {!HTMLInputElement} */(
    -      this.dom.createDom(goog.dom.TagName.INPUT, {'type': 'checkbox'}));
    -  return this.dom.createDom(goog.dom.TagName.DIV, null,
    -      this.dom.createDom(goog.dom.TagName.LABEL, null,
    -                         this.openInNewWindowCheckbox_,
    -                         goog.ui.editor.messages.MSG_OPEN_IN_NEW_WINDOW));
    -};
    -
    -
    -/**
    - * Creates a DIV with a checkbox for {@code rel=nofollow} option.
    - * @return {!Element} Newly created DIV element.
    - * @private
    - */
    -goog.ui.editor.LinkDialog.prototype.buildRelNoFollowDiv_ = function() {
    -  /** @desc Checkbox text for adding 'rel=nofollow' attribute to a link. */
    -  var MSG_ADD_REL_NOFOLLOW_ATTR = goog.getMsg(
    -      "Add '{$relNoFollow}' attribute ({$linkStart}Learn more{$linkEnd})", {
    -        'relNoFollow': 'rel=nofollow',
    -        'linkStart': '<a href="http://support.google.com/webmasters/bin/' +
    -            'answer.py?hl=en&answer=96569" target="_blank">',
    -        'linkEnd': '</a>'
    -      });
    -
    -  this.relNoFollowCheckbox_ = /** @type {!HTMLInputElement} */(
    -      this.dom.createDom(goog.dom.TagName.INPUT, {'type': 'checkbox'}));
    -  return this.dom.createDom(goog.dom.TagName.DIV, null,
    -      this.dom.createDom(goog.dom.TagName.LABEL, null,
    -          this.relNoFollowCheckbox_,
    -          goog.dom.htmlToDocumentFragment(MSG_ADD_REL_NOFOLLOW_ATTR)));
    -};
    -
    -
    -/**
    -* Builds and returns the div containing the tab "On the web".
    -* @return {!Element} The div element containing the tab.
    -* @private
    -*/
    -goog.ui.editor.LinkDialog.prototype.buildTabOnTheWeb_ = function() {
    -  var onTheWebDiv = this.dom.createElement(goog.dom.TagName.DIV);
    -
    -  var headingDiv = this.dom.createDom(goog.dom.TagName.DIV, {},
    -      this.dom.createDom(goog.dom.TagName.B, {},
    -          goog.ui.editor.messages.MSG_WHAT_URL));
    -  var urlInput = this.dom.createDom(goog.dom.TagName.INPUT,
    -      {
    -        id: goog.ui.editor.LinkDialog.Id_.ON_WEB_INPUT,
    -        className: goog.ui.editor.LinkDialog.TARGET_INPUT_CLASSNAME_
    -      });
    -  goog.a11y.aria.setState(urlInput,
    -      goog.a11y.aria.State.LABELLEDBY,
    -      goog.ui.editor.LinkDialog.Id_.ON_WEB_TAB);
    -  // IE throws on unknown values for type.
    -  if (!goog.userAgent.IE) {
    -    // On browsers that support Web Forms 2.0, allow autocompletion of URLs.
    -    // (As of now, this is only supported by Opera 9)
    -    urlInput.type = 'url';
    -  }
    -
    -  if (goog.editor.BrowserFeature.NEEDS_99_WIDTH_IN_STANDARDS_MODE &&
    -      goog.editor.node.isStandardsMode(urlInput)) {
    -    urlInput.style.width = '99%';
    -  }
    -
    -  var inputDiv = this.dom.createDom(goog.dom.TagName.DIV, null, urlInput);
    -
    -  this.urlInputHandler_ = new goog.events.InputHandler(urlInput);
    -  this.registerDisposable(this.urlInputHandler_);
    -  this.eventHandler_.listen(this.urlInputHandler_,
    -      goog.events.InputHandler.EventType.INPUT,
    -      this.onUrlOrEmailInputChange_);
    -
    -  var testLink = new goog.ui.Button(goog.ui.editor.messages.MSG_TEST_THIS_LINK,
    -      goog.ui.LinkButtonRenderer.getInstance(),
    -      this.dom);
    -  testLink.render(inputDiv);
    -  testLink.getElement().style.marginTop = '1em';
    -  this.eventHandler_.listen(testLink,
    -      goog.ui.Component.EventType.ACTION,
    -      this.onWebTestLink_);
    -
    -  // Build the "On the web" explanation text div.
    -  var explanationDiv = this.dom.createDom(goog.dom.TagName.DIV,
    -      goog.ui.editor.LinkDialog.EXPLANATION_TEXT_CLASSNAME_);
    -  goog.dom.safe.setInnerHtml(explanationDiv,
    -      goog.ui.editor.messages.getTrLinkExplanationSafeHtml());
    -  onTheWebDiv.appendChild(headingDiv);
    -  onTheWebDiv.appendChild(inputDiv);
    -  onTheWebDiv.appendChild(explanationDiv);
    -
    -  return onTheWebDiv;
    -};
    -
    -
    -/**
    - * Builds and returns the div containing the tab "Email address".
    - * @return {!Element} the div element containing the tab.
    - * @private
    - */
    -goog.ui.editor.LinkDialog.prototype.buildTabEmailAddress_ = function() {
    -  var emailTab = this.dom.createDom(goog.dom.TagName.DIV);
    -
    -  var headingDiv = this.dom.createDom(goog.dom.TagName.DIV, {},
    -      this.dom.createDom(goog.dom.TagName.B, {},
    -          goog.ui.editor.messages.MSG_WHAT_EMAIL));
    -  goog.dom.appendChild(emailTab, headingDiv);
    -  var emailInput = this.dom.createDom(goog.dom.TagName.INPUT,
    -      {
    -        id: goog.ui.editor.LinkDialog.Id_.EMAIL_ADDRESS_INPUT,
    -        className: goog.ui.editor.LinkDialog.TARGET_INPUT_CLASSNAME_
    -      });
    -  goog.a11y.aria.setState(emailInput,
    -      goog.a11y.aria.State.LABELLEDBY,
    -      goog.ui.editor.LinkDialog.Id_.EMAIL_ADDRESS_TAB);
    -
    -  if (goog.editor.BrowserFeature.NEEDS_99_WIDTH_IN_STANDARDS_MODE &&
    -      goog.editor.node.isStandardsMode(emailInput)) {
    -    // Standards mode sizes this too large.
    -    emailInput.style.width = '99%';
    -  }
    -
    -  goog.dom.appendChild(emailTab, emailInput);
    -
    -  this.emailInputHandler_ = new goog.events.InputHandler(emailInput);
    -  this.registerDisposable(this.emailInputHandler_);
    -  this.eventHandler_.listen(this.emailInputHandler_,
    -      goog.events.InputHandler.EventType.INPUT,
    -      this.onUrlOrEmailInputChange_);
    -
    -  goog.dom.appendChild(emailTab,
    -      this.dom.createDom(goog.dom.TagName.DIV,
    -          {
    -            id: goog.ui.editor.LinkDialog.Id_.EMAIL_WARNING,
    -            className: goog.ui.editor.LinkDialog.EMAIL_WARNING_CLASSNAME_,
    -            style: 'visibility:hidden'
    -          }, goog.ui.editor.messages.MSG_INVALID_EMAIL));
    -
    -  if (this.emailWarning_) {
    -    var explanationDiv = this.dom.createDom(goog.dom.TagName.DIV,
    -        goog.ui.editor.LinkDialog.EXPLANATION_TEXT_CLASSNAME_);
    -    goog.dom.safe.setInnerHtml(explanationDiv, this.emailWarning_);
    -    goog.dom.appendChild(emailTab, explanationDiv);
    -  }
    -  return emailTab;
    -};
    -
    -
    -/**
    - * Returns the url that the target points to.
    - * @return {string} The url that the target points to.
    - * @private
    - */
    -goog.ui.editor.LinkDialog.prototype.getTargetUrl_ = function() {
    -  // Get the href-attribute through getAttribute() rather than the href property
    -  // because Google-Toolbar on Firefox with "Send with Gmail" turned on
    -  // modifies the href-property of 'mailto:' links but leaves the attribute
    -  // untouched.
    -  return this.targetLink_.getAnchor().getAttribute('href') || '';
    -};
    -
    -
    -/**
    - * Selects the correct tab based on the URL, and fills in its inputs.
    - * For new links, it suggests a url based on the link text.
    - * @param {string} text The inner text of the link.
    - * @param {string} url The href for the link.
    - * @private
    - */
    -goog.ui.editor.LinkDialog.prototype.selectAppropriateTab_ = function(
    -    text, url) {
    -  if (this.isNewLink_()) {
    -    // Newly created non-empty link: try to infer URL from the link text.
    -    this.guessUrlAndSelectTab_(text);
    -  } else if (goog.editor.Link.isMailto(url)) {
    -    // The link is for an email.
    -    this.tabPane_.setSelectedTabId(
    -        goog.ui.editor.LinkDialog.Id_.EMAIL_ADDRESS_TAB);
    -    this.dom.getElement(goog.ui.editor.LinkDialog.Id_.EMAIL_ADDRESS_INPUT)
    -        .value = url.substring(url.indexOf(':') + 1);
    -    this.setAutogenFlagFromCurInput_();
    -  } else {
    -    // No specific tab was appropriate, default to on the web tab.
    -    this.tabPane_.setSelectedTabId(goog.ui.editor.LinkDialog.Id_.ON_WEB_TAB);
    -    this.dom.getElement(goog.ui.editor.LinkDialog.Id_.ON_WEB_INPUT)
    -        .value = this.isNewLink_() ? 'http://' : url;
    -    this.setAutogenFlagFromCurInput_();
    -  }
    -};
    -
    -
    -/**
    - * Select a url/tab based on the link's text. This function is simply
    - * the isNewLink_() == true case of selectAppropriateTab_().
    - * @param {string} text The inner text of the link.
    - * @private
    - */
    -goog.ui.editor.LinkDialog.prototype.guessUrlAndSelectTab_ = function(text) {
    -  if (goog.editor.Link.isLikelyEmailAddress(text)) {
    -    // The text is for an email address.
    -    this.tabPane_.setSelectedTabId(
    -        goog.ui.editor.LinkDialog.Id_.EMAIL_ADDRESS_TAB);
    -    this.dom.getElement(goog.ui.editor.LinkDialog.Id_.EMAIL_ADDRESS_INPUT)
    -        .value = text;
    -    this.setAutogenFlag_(true);
    -    // TODO(user): Why disable right after enabling? What bug are we
    -    // working around?
    -    this.disableAutogenFlag_(true);
    -  } else if (goog.editor.Link.isLikelyUrl(text)) {
    -    // The text is for a web URL.
    -    this.tabPane_.setSelectedTabId(goog.ui.editor.LinkDialog.Id_.ON_WEB_TAB);
    -    this.dom.getElement(goog.ui.editor.LinkDialog.Id_.ON_WEB_INPUT)
    -        .value = text;
    -    this.setAutogenFlag_(true);
    -    this.disableAutogenFlag_(true);
    -  } else {
    -    // No meaning could be deduced from text, choose a default tab.
    -    if (!this.targetLink_.getCurrentText()) {
    -      this.setAutogenFlag_(true);
    -    }
    -    this.tabPane_.setSelectedTabId(goog.ui.editor.LinkDialog.Id_.ON_WEB_TAB);
    -  }
    -};
    -
    -
    -/**
    - * Called on a change to the url or email input. If either one of those tabs
    - * is active, sets the OK button to enabled/disabled accordingly.
    - * @private
    - */
    -goog.ui.editor.LinkDialog.prototype.syncOkButton_ = function() {
    -  var inputValue;
    -  if (this.tabPane_.getCurrentTabId() ==
    -      goog.ui.editor.LinkDialog.Id_.EMAIL_ADDRESS_TAB) {
    -    inputValue = this.dom.getElement(
    -        goog.ui.editor.LinkDialog.Id_.EMAIL_ADDRESS_INPUT).value;
    -    this.toggleInvalidEmailWarning_(inputValue != '' &&
    -        !goog.editor.Link.isLikelyEmailAddress(inputValue));
    -  } else if (this.tabPane_.getCurrentTabId() ==
    -      goog.ui.editor.LinkDialog.Id_.ON_WEB_TAB) {
    -    inputValue = this.dom.getElement(
    -        goog.ui.editor.LinkDialog.Id_.ON_WEB_INPUT).value;
    -  } else {
    -    return;
    -  }
    -  this.getOkButtonElement().disabled =
    -      goog.string.isEmptyOrWhitespace(inputValue);
    -};
    -
    -
    -/**
    - * Show/hide the Invalid Email Address warning.
    - * @param {boolean} on Whether to show the warning.
    - * @private
    - */
    -goog.ui.editor.LinkDialog.prototype.toggleInvalidEmailWarning_ = function(on) {
    -  this.dom.getElement(goog.ui.editor.LinkDialog.Id_.EMAIL_WARNING)
    -      .style.visibility = (on ? 'visible' : 'hidden');
    -};
    -
    -
    -/**
    - * Changes the autogenerateTextToDisplay flag so that text to
    - * display stops autogenerating.
    - * @private
    - */
    -goog.ui.editor.LinkDialog.prototype.onTextToDisplayEdit_ = function() {
    -  var inputEmpty = this.textToDisplayInput_.value == '';
    -  if (inputEmpty) {
    -    this.setAutogenFlag_(true);
    -  } else {
    -    this.setAutogenFlagFromCurInput_();
    -  }
    -};
    -
    -
    -/**
    - * The function called when hitting OK with the "On the web" tab current.
    - * @return {!goog.ui.editor.LinkDialog.OkEvent} The event object to be used when
    - *     dispatching the OK event to listeners.
    - * @private
    - */
    -goog.ui.editor.LinkDialog.prototype.createOkEventFromWebTab_ = function() {
    -  var input = /** @type {HTMLInputElement} */(
    -      this.dom.getElement(goog.ui.editor.LinkDialog.Id_.ON_WEB_INPUT));
    -  var linkURL = input.value;
    -  if (goog.editor.Link.isLikelyEmailAddress(linkURL)) {
    -    // Make sure that if user types in an e-mail address, it becomes "mailto:".
    -    return this.createOkEventFromEmailTab_(
    -        goog.ui.editor.LinkDialog.Id_.ON_WEB_INPUT);
    -  } else {
    -    if (linkURL.search(/:/) < 0) {
    -      linkURL = 'http://' + goog.string.trimLeft(linkURL);
    -    }
    -    return this.createOkEventFromUrl_(linkURL);
    -  }
    -};
    -
    -
    -/**
    - * The function called when hitting OK with the "email address" tab current.
    - * @param {string=} opt_inputId Id of an alternate input to check.
    - * @return {!goog.ui.editor.LinkDialog.OkEvent} The event object to be used when
    - *     dispatching the OK event to listeners.
    - * @private
    - */
    -goog.ui.editor.LinkDialog.prototype.createOkEventFromEmailTab_ = function(
    -    opt_inputId) {
    -  var linkURL = this.dom.getElement(
    -      opt_inputId || goog.ui.editor.LinkDialog.Id_.EMAIL_ADDRESS_INPUT).value;
    -  linkURL = 'mailto:' + linkURL;
    -  return this.createOkEventFromUrl_(linkURL);
    -};
    -
    -
    -/**
    - * Function to test a link from the on the web tab.
    - * @private
    - */
    -goog.ui.editor.LinkDialog.prototype.onWebTestLink_ = function() {
    -  var input = /** @type {HTMLInputElement} */(
    -      this.dom.getElement(goog.ui.editor.LinkDialog.Id_.ON_WEB_INPUT));
    -  var url = input.value;
    -  if (url.search(/:/) < 0) {
    -    url = 'http://' + goog.string.trimLeft(url);
    -  }
    -  if (this.dispatchEvent(
    -      new goog.ui.editor.LinkDialog.BeforeTestLinkEvent(url))) {
    -    var win = this.dom.getWindow();
    -    var size = goog.dom.getViewportSize(win);
    -    var openOptions = {
    -      target: '_blank',
    -      width: Math.max(size.width - 50, 50),
    -      height: Math.max(size.height - 50, 50),
    -      toolbar: true,
    -      scrollbars: true,
    -      location: true,
    -      statusbar: false,
    -      menubar: true,
    -      'resizable': true,
    -      'noreferrer': this.stopReferrerLeaks_
    -    };
    -    goog.window.open(url, openOptions, win);
    -  }
    -};
    -
    -
    -/**
    - * Called whenever the url or email input is edited. If the text to display
    - * matches the text to display, turn on auto. Otherwise if auto is on, update
    - * the text to display based on the url.
    - * @private
    - */
    -goog.ui.editor.LinkDialog.prototype.onUrlOrEmailInputChange_ = function() {
    -  if (this.autogenerateTextToDisplay_) {
    -    this.setTextToDisplayFromAuto_();
    -  } else if (this.textToDisplayInput_.value == '') {
    -    this.setAutogenFlagFromCurInput_();
    -  }
    -  this.syncOkButton_();
    -};
    -
    -
    -/**
    - * Called when the currently selected tab changes.
    - * @param {goog.events.Event} e The tab change event.
    - * @private
    - */
    -goog.ui.editor.LinkDialog.prototype.onChangeTab_ = function(e) {
    -  var tab = /** @type {goog.ui.Tab} */ (e.target);
    -
    -  // Focus on the input field in the selected tab.
    -  var input = this.dom.getElement(tab.getId() +
    -      goog.ui.editor.LinkDialog.Id_.TAB_INPUT_SUFFIX);
    -  goog.editor.focus.focusInputField(input);
    -
    -  // For some reason, IE does not fire onpropertychange events when the width
    -  // is specified as a percentage, which breaks the InputHandlers.
    -  input.style.width = '';
    -  input.style.width = input.offsetWidth + 'px';
    -
    -  this.syncOkButton_();
    -  this.setTextToDisplayFromAuto_();
    -};
    -
    -
    -/**
    - * If autogen is turned on, set the value of text to display based on the
    - * current selection or url.
    - * @private
    - */
    -goog.ui.editor.LinkDialog.prototype.setTextToDisplayFromAuto_ = function() {
    -  if (this.autogenFeatureEnabled_ && this.autogenerateTextToDisplay_) {
    -    var inputId = this.tabPane_.getCurrentTabId() +
    -        goog.ui.editor.LinkDialog.Id_.TAB_INPUT_SUFFIX;
    -    this.textToDisplayInput_.value =
    -        /** @type {HTMLInputElement} */(this.dom.getElement(inputId)).value;
    -  }
    -};
    -
    -
    -/**
    - * Turn on the autogenerate text to display flag, and set some sort of indicator
    - * that autogen is on.
    - * @param {boolean} val Boolean value to set autogenerate to.
    - * @private
    - */
    -goog.ui.editor.LinkDialog.prototype.setAutogenFlag_ = function(val) {
    -  // TODO(user): This whole autogen thing is very confusing. It needs
    -  // to be refactored and/or explained.
    -  this.autogenerateTextToDisplay_ = val;
    -};
    -
    -
    -/**
    - * Disables autogen so that onUrlOrEmailInputChange_ doesn't act in cases
    - * that are undesirable.
    - * @param {boolean} autogen Boolean value to set disableAutogen to.
    - * @private
    - */
    -goog.ui.editor.LinkDialog.prototype.disableAutogenFlag_ = function(autogen) {
    -  this.setAutogenFlag_(!autogen);
    -  this.disableAutogen_ = autogen;
    -};
    -
    -
    -/**
    - * Creates an OK event from the text to display input and the specified link.
    - * If text to display input is empty, then generate the auto value for it.
    - * @return {!goog.ui.editor.LinkDialog.OkEvent} The event object to be used when
    - *     dispatching the OK event to listeners.
    - * @param {string} url Url the target element should point to.
    - * @private
    - */
    -goog.ui.editor.LinkDialog.prototype.createOkEventFromUrl_ = function(url) {
    -  // Fill in the text to display input in case it is empty.
    -  this.setTextToDisplayFromAuto_();
    -  if (this.showOpenLinkInNewWindow_) {
    -    // Save checkbox state for next time.
    -    this.isOpenLinkInNewWindowChecked_ = this.openInNewWindowCheckbox_.checked;
    -  }
    -  return new goog.ui.editor.LinkDialog.OkEvent(this.textToDisplayInput_.value,
    -      url, this.showOpenLinkInNewWindow_ && this.isOpenLinkInNewWindowChecked_,
    -      this.showRelNoFollow_ && this.relNoFollowCheckbox_.checked);
    -};
    -
    -
    -/**
    - * If an email or url is being edited, set autogenerate to on if the text to
    - * display matches the url.
    - * @private
    - */
    -goog.ui.editor.LinkDialog.prototype.setAutogenFlagFromCurInput_ = function() {
    -  var autogen = false;
    -  if (!this.disableAutogen_) {
    -    var tabInput = this.dom.getElement(this.tabPane_.getCurrentTabId() +
    -        goog.ui.editor.LinkDialog.Id_.TAB_INPUT_SUFFIX);
    -    autogen = (tabInput.value == this.textToDisplayInput_.value);
    -  }
    -  this.setAutogenFlag_(autogen);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the link is new.
    - * @private
    - */
    -goog.ui.editor.LinkDialog.prototype.isNewLink_ = function() {
    -  return this.targetLink_.isNew();
    -};
    -
    -
    -/**
    - * IDs for relevant DOM elements.
    - * @enum {string}
    - * @private
    - */
    -goog.ui.editor.LinkDialog.Id_ = {
    -  TEXT_TO_DISPLAY: 'linkdialog-text',
    -  TEXT_TO_DISPLAY_LABEL: 'linkdialog-text-label',
    -  ON_WEB_TAB: 'linkdialog-onweb',
    -  ON_WEB_INPUT: 'linkdialog-onweb-tab-input',
    -  EMAIL_ADDRESS_TAB: 'linkdialog-email',
    -  EMAIL_ADDRESS_INPUT: 'linkdialog-email-tab-input',
    -  EMAIL_WARNING: 'linkdialog-email-warning',
    -  TAB_INPUT_SUFFIX: '-tab-input'
    -};
    -
    -
    -/**
    - * Base name for the radio buttons group.
    - * @type {string}
    - * @private
    - */
    -goog.ui.editor.LinkDialog.BUTTON_GROUP_ = 'linkdialog-buttons';
    -
    -
    -/**
    - * Class name for the url and email input elements.
    - * @type {string}
    - * @private
    - */
    -goog.ui.editor.LinkDialog.TARGET_INPUT_CLASSNAME_ =
    -    goog.getCssName('tr-link-dialog-target-input');
    -
    -
    -/**
    - * Class name for the email address warning element.
    - * @type {string}
    - * @private
    - */
    -goog.ui.editor.LinkDialog.EMAIL_WARNING_CLASSNAME_ =
    -    goog.getCssName('tr-link-dialog-email-warning');
    -
    -
    -/**
    - * Class name for the explanation text elements.
    - * @type {string}
    - * @private
    - */
    -goog.ui.editor.LinkDialog.EXPLANATION_TEXT_CLASSNAME_ =
    -    goog.getCssName('tr-link-dialog-explanation-text');
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/editor/linkdialog_test.html b/src/database/third_party/closure-library/closure/goog/ui/editor/linkdialog_test.html
    deleted file mode 100644
    index f64c70209a8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/editor/linkdialog_test.html
    +++ /dev/null
    @@ -1,30 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   goog.ui.editor.LinkDialog Tests
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.editor.LinkDialogTest');
    -  </script>
    -  <link rel="stylesheet" href="../../css/dialog.css" />
    -  <link rel="stylesheet" href="../../css/linkbutton.css" />
    -  <link rel="stylesheet" href="../../css/editor/dialog.css" />
    -  <link rel="stylesheet" href="../../css/editor/linkdialog.css" />
    - </head>
    - <body>
    -  <iframe id="appWindowIframe" src="javascript:''">
    -  </iframe>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/editor/linkdialog_test.js b/src/database/third_party/closure-library/closure/goog/ui/editor/linkdialog_test.js
    deleted file mode 100644
    index f493525c491..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/editor/linkdialog_test.js
    +++ /dev/null
    @@ -1,666 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.editor.LinkDialogTest');
    -goog.setTestOnly('goog.ui.editor.LinkDialogTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.DomHelper');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.editor.BrowserFeature');
    -goog.require('goog.editor.Link');
    -goog.require('goog.events');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.style');
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.dom');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.events.Event');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.mockmatchers');
    -goog.require('goog.testing.mockmatchers.ArgumentMatcher');
    -goog.require('goog.ui.editor.AbstractDialog');
    -goog.require('goog.ui.editor.LinkDialog');
    -goog.require('goog.ui.editor.messages');
    -goog.require('goog.userAgent');
    -
    -var dialog;
    -var mockCtrl;
    -var mockLink;
    -var mockOkHandler;
    -var mockGetViewportSize;
    -var mockWindowOpen;
    -var isNew;
    -var anchorElem;
    -var stubs = new goog.testing.PropertyReplacer();
    -
    -var ANCHOR_TEXT = 'anchor text';
    -var ANCHOR_URL = 'http://www.google.com/';
    -var ANCHOR_EMAIL = 'm@r.cos';
    -var ANCHOR_MAILTO = 'mailto:' + ANCHOR_EMAIL;
    -
    -function setUp() {
    -  anchorElem = goog.dom.createElement(goog.dom.TagName.A);
    -  goog.dom.appendChild(goog.dom.getDocument().body, anchorElem);
    -
    -  mockCtrl = new goog.testing.MockControl();
    -  mockLink = mockCtrl.createLooseMock(goog.editor.Link);
    -  mockOkHandler = mockCtrl.createLooseMock(goog.events.EventHandler);
    -
    -  isNew = false;
    -  mockLink.isNew();
    -  mockLink.$anyTimes();
    -  mockLink.$does(function() {
    -    return isNew;
    -  });
    -  mockLink.getCurrentText();
    -  mockLink.$anyTimes();
    -  mockLink.$does(function() {
    -    return anchorElem.innerHTML;
    -  });
    -  mockLink.setTextAndUrl(goog.testing.mockmatchers.isString,
    -      goog.testing.mockmatchers.isString);
    -  mockLink.$anyTimes();
    -  mockLink.$does(function(text, url) {
    -    anchorElem.innerHTML = text;
    -    anchorElem.href = url;
    -  });
    -  mockLink.$registerArgumentListVerifier('placeCursorRightOf', function() {
    -    return true;
    -  });
    -  mockLink.placeCursorRightOf(goog.testing.mockmatchers.iBoolean);
    -  mockLink.$anyTimes();
    -  mockLink.getAnchor();
    -  mockLink.$anyTimes();
    -  mockLink.$returns(anchorElem);
    -
    -  mockWindowOpen = mockCtrl.createFunctionMock('open');
    -  stubs.set(window, 'open', mockWindowOpen);
    -}
    -
    -function tearDown() {
    -  dialog.dispose();
    -  goog.dom.removeNode(anchorElem);
    -  stubs.reset();
    -}
    -
    -function setUpAnchor(href, text, opt_isNew, opt_target, opt_rel) {
    -  anchorElem.href = href;
    -  anchorElem.innerHTML = text;
    -  isNew = !!opt_isNew;
    -  if (opt_target) {
    -    anchorElem.target = opt_target;
    -  }
    -  if (opt_rel) {
    -    anchorElem.rel = opt_rel;
    -  }
    -}
    -
    -
    -/**
    - * Creates and shows the dialog to be tested.
    - * @param {Document=} opt_document Document to render the dialog into.
    - *     Defaults to the main window's document.
    - * @param {boolean=} opt_openInNewWindow Whether the open in new window
    - *     checkbox should be shown.
    - * @param {boolean=} opt_noFollow Whether rel=nofollow checkbox should be
    - *     shown.
    - */
    -function createAndShow(opt_document, opt_openInNewWindow, opt_noFollow) {
    -  dialog = new goog.ui.editor.LinkDialog(new goog.dom.DomHelper(opt_document),
    -                                         mockLink);
    -  if (opt_openInNewWindow) {
    -    dialog.showOpenLinkInNewWindow(false);
    -  }
    -  if (opt_noFollow) {
    -    dialog.showRelNoFollow();
    -  }
    -  dialog.addEventListener(goog.ui.editor.AbstractDialog.EventType.OK,
    -      mockOkHandler);
    -  dialog.show();
    -}
    -
    -
    -/**
    - * Sets up the mock event handler to expect an OK event with the given text
    - * and url.
    - */
    -function expectOk(linkText, linkUrl, opt_openInNewWindow, opt_noFollow) {
    -  mockOkHandler.handleEvent(new goog.testing.mockmatchers.ArgumentMatcher(
    -      function(arg) {
    -        return arg.type == goog.ui.editor.AbstractDialog.EventType.OK &&
    -               arg.linkText == linkText &&
    -               arg.linkUrl == linkUrl &&
    -               arg.openInNewWindow == !!opt_openInNewWindow &&
    -               arg.noFollow == !!opt_noFollow;
    -      },
    -      '{linkText: ' + linkText + ', linkUrl: ' + linkUrl +
    -          ', openInNewWindow: ' + opt_openInNewWindow +
    -          ', noFollow: ' + opt_noFollow + '}'));
    -}
    -
    -
    -/**
    - * Return true if we should use active element in our tests.
    - * @return {boolean} .
    - */
    -function useActiveElement() {
    -  return goog.editor.BrowserFeature.HAS_ACTIVE_ELEMENT ||
    -      goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher(9);
    -}
    -
    -
    -/**
    - * Tests that when you show the dialog for a new link, you can switch
    - * to the URL view.
    - * @param {Document=} opt_document Document to render the dialog into.
    - *     Defaults to the main window's document.
    - */
    -function testShowNewLinkSwitchToUrl(opt_document) {
    -  mockCtrl.$replayAll();
    -  setUpAnchor('', '', true); // Must be done before creating the dialog.
    -  createAndShow(opt_document);
    -
    -  var webRadio = dialog.dom.getElement(
    -      goog.ui.editor.LinkDialog.Id_.ON_WEB_TAB).firstChild;
    -  var emailRadio = dialog.dom.getElement(
    -      goog.ui.editor.LinkDialog.Id_.EMAIL_ADDRESS_TAB).firstChild;
    -  assertTrue('Web Radio Button selected', webRadio.checked);
    -  assertFalse('Email Radio Button selected', emailRadio.checked);
    -  if (useActiveElement()) {
    -    assertEquals('Focus should be on url input',
    -        getUrlInput(),
    -        dialog.dom.getActiveElement());
    -  }
    -
    -  emailRadio.click();
    -  assertFalse('Web Radio Button selected', webRadio.checked);
    -  assertTrue('Email Radio Button selected', emailRadio.checked);
    -  if (useActiveElement()) {
    -    assertEquals('Focus should be on url input',
    -        getEmailInput(),
    -        dialog.dom.getActiveElement());
    -  }
    -
    -  mockCtrl.$verifyAll();
    -}
    -
    -
    -/**
    - * Tests that when you show the dialog for a new link, the input fields are
    - * empty, the web tab is selected and focus is in the url input field.
    - * @param {Document=} opt_document Document to render the dialog into.
    - *     Defaults to the main window's document.
    - */
    -function testShowForNewLink(opt_document) {
    -  mockCtrl.$replayAll();
    -  setUpAnchor('', '', true); // Must be done before creating the dialog.
    -  createAndShow(opt_document);
    -
    -  assertEquals('Display text input field should be empty',
    -               '',
    -               getDisplayInputText());
    -  assertEquals('Url input field should be empty',
    -               '',
    -               getUrlInputText());
    -  assertEquals('On the web tab should be selected',
    -               goog.ui.editor.LinkDialog.Id_.ON_WEB,
    -               dialog.curTabId_);
    -  if (useActiveElement()) {
    -    assertEquals('Focus should be on url input',
    -                 getUrlInput(),
    -                 dialog.dom.getActiveElement());
    -  }
    -
    -  mockCtrl.$verifyAll();
    -}
    -
    -
    -/**
    - * Fakes that the mock field is using an iframe and does the same test as
    - * testShowForNewLink().
    - */
    -function testShowForNewLinkWithDiffAppWindow() {
    -  testShowForNewLink(goog.dom.getElement('appWindowIframe').contentDocument);
    -}
    -
    -
    -/**
    - * Tests that when you show the dialog for a url link, the input fields are
    - * filled in, the web tab is selected and focus is in the url input field.
    - */
    -function testShowForUrlLink() {
    -  mockCtrl.$replayAll();
    -  setUpAnchor(ANCHOR_URL, ANCHOR_TEXT);
    -  createAndShow();
    -
    -  assertEquals('Display text input field should be filled in',
    -               ANCHOR_TEXT,
    -               getDisplayInputText());
    -  assertEquals('Url input field should be filled in',
    -               ANCHOR_URL,
    -               getUrlInputText());
    -  assertEquals('On the web tab should be selected',
    -               goog.ui.editor.LinkDialog.Id_.ON_WEB,
    -               dialog.curTabId_);
    -  if (useActiveElement()) {
    -    assertEquals('Focus should be on url input',
    -                 getUrlInput(),
    -                 dialog.dom.getActiveElement());
    -  }
    -
    -  mockCtrl.$verifyAll();
    -}
    -
    -
    -/**
    - * Tests that when you show the dialog for a mailto link, the input fields are
    - * filled in, the email tab is selected and focus is in the email input field.
    - */
    -function testShowForMailtoLink() {
    -  mockCtrl.$replayAll();
    -  setUpAnchor(ANCHOR_MAILTO, ANCHOR_TEXT);
    -  createAndShow();
    -
    -  assertEquals('Display text input field should be filled in',
    -               ANCHOR_TEXT,
    -               getDisplayInputText());
    -  assertEquals('Email input field should be filled in',
    -               ANCHOR_EMAIL, // The 'mailto:' is not in the input!
    -               getEmailInputText());
    -  assertEquals('Email tab should be selected',
    -               goog.ui.editor.LinkDialog.Id_.EMAIL_ADDRESS,
    -               dialog.curTabId_);
    -  if (useActiveElement()) {
    -    assertEquals('Focus should be on email input',
    -                 getEmailInput(),
    -                 dialog.dom.getActiveElement());
    -  }
    -
    -  mockCtrl.$verifyAll();
    -}
    -
    -
    -/**
    - * Tests that the display text is autogenerated from the url input in the
    - * right situations (and not generated when appropriate too).
    - */
    -function testAutogeneration() {
    -  mockCtrl.$replayAll();
    -  setUpAnchor('', '', true);
    -  createAndShow();
    -
    -  // Simulate typing a url when everything is empty, should autogen.
    -  setUrlInputText(ANCHOR_URL);
    -  assertEquals('Display text should have been autogenerated',
    -               ANCHOR_URL,
    -               getDisplayInputText());
    -
    -  // Simulate typing text when url is set, afterwards should not autogen.
    -  setDisplayInputText(ANCHOR_TEXT);
    -  setUrlInputText(ANCHOR_MAILTO);
    -  assertNotEquals('Display text should not have been autogenerated',
    -                  ANCHOR_MAILTO,
    -                  getDisplayInputText());
    -  assertEquals('Display text should have remained the same',
    -               ANCHOR_TEXT,
    -               getDisplayInputText());
    -
    -  // Simulate typing text equal to existing url, afterwards should autogen.
    -  setDisplayInputText(ANCHOR_MAILTO);
    -  setUrlInputText(ANCHOR_URL);
    -  assertEquals('Display text should have been autogenerated',
    -               ANCHOR_URL,
    -               getDisplayInputText());
    -
    -  mockCtrl.$verifyAll();
    -}
    -
    -
    -/**
    - * Tests that the display text is not autogenerated from the url input in all
    - * situations when the autogeneration feature is turned off.
    - */
    -function testAutogenerationOff() {
    -  mockCtrl.$replayAll();
    -
    -  setUpAnchor('', '', true);
    -  createAndShow();
    -
    -  // Disable the autogen feature
    -  dialog.setAutogenFeatureEnabled(false);
    -
    -  // Simulate typing a url when everything is empty, should not autogen.
    -  setUrlInputText(ANCHOR_URL);
    -  assertEquals('Display text should not have been autogenerated',
    -               '',
    -               getDisplayInputText());
    -
    -  // Simulate typing text when url is set, afterwards should not autogen.
    -  setDisplayInputText(ANCHOR_TEXT);
    -  setUrlInputText(ANCHOR_MAILTO);
    -  assertNotEquals('Display text should not have been autogenerated',
    -                  ANCHOR_MAILTO,
    -                  getDisplayInputText());
    -  assertEquals('Display text should have remained the same',
    -               ANCHOR_TEXT,
    -               getDisplayInputText());
    -
    -  // Simulate typing text equal to existing url, afterwards should not
    -  // autogen.
    -  setDisplayInputText(ANCHOR_MAILTO);
    -  setUrlInputText(ANCHOR_URL);
    -  assertEquals('Display text should not have been autogenerated',
    -               ANCHOR_MAILTO,
    -               getDisplayInputText());
    -
    -  mockCtrl.$verifyAll();
    -}
    -
    -
    -/**
    - * Tests that clicking OK with the url tab selected dispatches an event with
    - * the proper link data.
    - */
    -function testOkForUrl() {
    -  expectOk(ANCHOR_TEXT, ANCHOR_URL);
    -  mockCtrl.$replayAll();
    -  setUpAnchor('', '', true);
    -  createAndShow();
    -
    -  dialog.tabPane_.setSelectedTabId(goog.ui.editor.LinkDialog.Id_.ON_WEB_TAB);
    -  setDisplayInputText(ANCHOR_TEXT);
    -  setUrlInputText(ANCHOR_URL);
    -  goog.testing.events.fireClickSequence(dialog.getOkButtonElement());
    -
    -  mockCtrl.$verifyAll();
    -}
    -
    -
    -/**
    - * Tests that clicking OK with the url tab selected but with an email address
    - * in the url field dispatches an event with the proper link data.
    - */
    -function testOkForUrlWithEmail() {
    -  expectOk(ANCHOR_TEXT, ANCHOR_MAILTO);
    -  mockCtrl.$replayAll();
    -  setUpAnchor('', '', true);
    -  createAndShow();
    -
    -  dialog.tabPane_.setSelectedTabId(goog.ui.editor.LinkDialog.Id_.ON_WEB_TAB);
    -  setDisplayInputText(ANCHOR_TEXT);
    -  setUrlInputText(ANCHOR_EMAIL);
    -  goog.testing.events.fireClickSequence(dialog.getOkButtonElement());
    -
    -  mockCtrl.$verifyAll();
    -}
    -
    -
    -/**
    - * Tests that clicking OK with the email tab selected dispatches an event with
    - * the proper link data.
    - */
    -function testOkForEmail() {
    -  expectOk(ANCHOR_TEXT, ANCHOR_MAILTO);
    -  mockCtrl.$replayAll();
    -  setUpAnchor('', '', true);
    -  createAndShow();
    -
    -  dialog.tabPane_.setSelectedTabId(
    -      goog.ui.editor.LinkDialog.Id_.EMAIL_ADDRESS_TAB);
    -
    -  setDisplayInputText(ANCHOR_TEXT);
    -  setEmailInputText(ANCHOR_EMAIL);
    -  goog.testing.events.fireClickSequence(dialog.getOkButtonElement());
    -
    -  mockCtrl.$verifyAll();
    -}
    -
    -function testOpenLinkInNewWindowNewLink() {
    -  expectOk(ANCHOR_TEXT, ANCHOR_URL, true);
    -  expectOk(ANCHOR_TEXT, ANCHOR_URL, false);
    -  mockCtrl.$replayAll();
    -
    -  setUpAnchor('', '', true);
    -  createAndShow(undefined, true);
    -  dialog.tabPane_.setSelectedTabId(goog.ui.editor.LinkDialog.Id_.ON_WEB_TAB);
    -  setDisplayInputText(ANCHOR_TEXT);
    -  setUrlInputText(ANCHOR_URL);
    -
    -  assertFalse('"Open in new window" should start unchecked',
    -      getOpenInNewWindowCheckboxChecked());
    -  setOpenInNewWindowCheckboxChecked(true);
    -  assertTrue('"Open in new window" should have gotten checked',
    -      getOpenInNewWindowCheckboxChecked());
    -  goog.testing.events.fireClickSequence(dialog.getOkButtonElement());
    -
    -  // Reopen same dialog
    -  dialog.show();
    -  dialog.tabPane_.setSelectedTabId(goog.ui.editor.LinkDialog.Id_.ON_WEB_TAB);
    -  setDisplayInputText(ANCHOR_TEXT);
    -  setUrlInputText(ANCHOR_URL);
    -
    -  assertTrue('"Open in new window" should remember it was checked',
    -      getOpenInNewWindowCheckboxChecked());
    -  setOpenInNewWindowCheckboxChecked(false);
    -  assertFalse('"Open in new window" should have gotten unchecked',
    -      getOpenInNewWindowCheckboxChecked());
    -  goog.testing.events.fireClickSequence(dialog.getOkButtonElement());
    -}
    -
    -function testOpenLinkInNewWindowExistingLink() {
    -  mockCtrl.$replayAll();
    -
    -  // Edit an existing link that already opens in a new window.
    -  setUpAnchor('', '', false, '_blank');
    -  createAndShow(undefined, true);
    -  dialog.tabPane_.setSelectedTabId(goog.ui.editor.LinkDialog.Id_.ON_WEB_TAB);
    -  setDisplayInputText(ANCHOR_TEXT);
    -  setUrlInputText(ANCHOR_URL);
    -
    -  assertTrue('"Open in new window" should start checked for existing link',
    -      getOpenInNewWindowCheckboxChecked());
    -
    -  mockCtrl.$verifyAll();
    -}
    -
    -function testRelNoFollowNewLink() {
    -  expectOk(ANCHOR_TEXT, ANCHOR_URL, null, true);
    -  expectOk(ANCHOR_TEXT, ANCHOR_URL, null, false);
    -  mockCtrl.$replayAll();
    -
    -  setUpAnchor('', '', true, true);
    -  createAndShow(null, null, true);
    -  dialog.tabPane_.setSelectedTabId(goog.ui.editor.LinkDialog.Id_.ON_WEB_TAB);
    -  setDisplayInputText(ANCHOR_TEXT);
    -  setUrlInputText(ANCHOR_URL);
    -  assertFalse('rel=nofollow should start unchecked',
    -      dialog.relNoFollowCheckbox_.checked);
    -
    -  // Check rel=nofollow and close the dialog.
    -  dialog.relNoFollowCheckbox_.checked = true;
    -  goog.testing.events.fireClickSequence(dialog.getOkButtonElement());
    -
    -  // Reopen the same dialog.
    -  anchorElem.rel = 'foo nofollow bar';
    -  dialog.show();
    -  dialog.tabPane_.setSelectedTabId(goog.ui.editor.LinkDialog.Id_.ON_WEB_TAB);
    -  setDisplayInputText(ANCHOR_TEXT);
    -  setUrlInputText(ANCHOR_URL);
    -  assertTrue('rel=nofollow should start checked when reopening the dialog',
    -      dialog.relNoFollowCheckbox_.checked);
    -}
    -
    -function testRelNoFollowExistingLink() {
    -  mockCtrl.$replayAll();
    -
    -  setUpAnchor('', '', null, null, 'foo nofollow bar');
    -  createAndShow(null, null, true);
    -  assertTrue('rel=nofollow should start checked for existing link',
    -      dialog.relNoFollowCheckbox_.checked);
    -
    -  mockCtrl.$verifyAll();
    -}
    -
    -
    -/**
    - * Test that clicking on the test button opens a new window with the correct
    - * options.
    - */
    -function testWebTestButton() {
    -  if (goog.userAgent.GECKO) {
    -    // TODO(robbyw): Figure out why this is flaky and fix it.
    -    return;
    -  }
    -
    -  var width, height;
    -  mockWindowOpen(ANCHOR_URL, '_blank',
    -      new goog.testing.mockmatchers.ArgumentMatcher(function(str) {
    -        return str == 'width=' + width + ',height=' + height +
    -            ',toolbar=1,scrollbars=1,location=1,statusbar=0,' +
    -            'menubar=1,resizable=1';
    -      }, '3rd arg: (string) window.open() options'));
    -
    -  mockCtrl.$replayAll();
    -  setUpAnchor(ANCHOR_URL, ANCHOR_TEXT);
    -  createAndShow();
    -
    -  // Measure viewport after opening dialog because that might cause scrollbars
    -  // to appear and reduce the viewport size.
    -  var size = goog.dom.getViewportSize(window);
    -  width = Math.max(size.width - 50, 50);
    -  height = Math.max(size.height - 50, 50);
    -
    -  var testLink = goog.testing.dom.findTextNode(
    -      goog.ui.editor.messages.MSG_TEST_THIS_LINK,
    -      dialog.dialogInternal_.getElement());
    -  goog.testing.events.fireClickSequence(testLink.parentNode);
    -
    -  mockCtrl.$verifyAll();
    -}
    -
    -
    -/**
    - * Test that clicking on the test button does not open a new window when
    - * the event is canceled.
    - */
    -function testWebTestButtonPreventDefault() {
    -  mockCtrl.$replayAll();
    -  setUpAnchor(ANCHOR_URL, ANCHOR_TEXT);
    -  createAndShow();
    -
    -  goog.events.listen(dialog,
    -      goog.ui.editor.LinkDialog.EventType.BEFORE_TEST_LINK,
    -      function(e) {
    -        assertEquals(e.url, ANCHOR_URL);
    -        e.preventDefault();
    -      });
    -  var testLink = goog.testing.dom.findTextNode(
    -      goog.ui.editor.messages.MSG_TEST_THIS_LINK,
    -      dialog.dialogInternal_.getElement());
    -  goog.testing.events.fireClickSequence(testLink.parentNode);
    -
    -  mockCtrl.$verifyAll();
    -}
    -
    -
    -/**
    - * Test that the setTextToDisplayVisible() correctly works.
    - * options.
    - */
    -function testSetTextToDisplayVisible() {
    -  mockCtrl.$replayAll();
    -  setUpAnchor('', '', true);
    -  createAndShow();
    -
    -  assertNotEquals('none',
    -                  goog.style.getStyle(dialog.textToDisplayDiv_, 'display'));
    -  dialog.setTextToDisplayVisible(false);
    -  assertEquals('none',
    -               goog.style.getStyle(dialog.textToDisplayDiv_, 'display'));
    -  dialog.setTextToDisplayVisible(true);
    -  assertNotEquals('none',
    -                  goog.style.getStyle(dialog.textToDisplayDiv_, 'display'));
    -
    -  mockCtrl.$verifyAll();
    -}
    -
    -function getDisplayInput() {
    -  return dialog.dom.getElement(goog.ui.editor.LinkDialog.Id_.TEXT_TO_DISPLAY);
    -}
    -
    -function getDisplayInputText() {
    -  return getDisplayInput().value;
    -}
    -
    -function setDisplayInputText(text) {
    -  var textInput = getDisplayInput();
    -  textInput.value = text;
    -  // Fire event so that dialog behaves like when user types.
    -  fireInputEvent(textInput, goog.events.KeyCodes.M);
    -}
    -
    -function getUrlInput() {
    -  var elt = dialog.dom.getElement(goog.ui.editor.LinkDialog.Id_.ON_WEB_INPUT);
    -  assertNotNullNorUndefined('UrlInput must be found', elt);
    -  return elt;
    -}
    -
    -function getUrlInputText() {
    -  return getUrlInput().value;
    -}
    -
    -function setUrlInputText(text) {
    -  var urlInput = getUrlInput();
    -  urlInput.value = text;
    -  // Fire event so that dialog behaves like when user types.
    -  fireInputEvent(dialog.urlInputHandler_, goog.events.KeyCodes.M);
    -}
    -
    -function getEmailInput() {
    -  var elt = dialog.dom.getElement(
    -      goog.ui.editor.LinkDialog.Id_.EMAIL_ADDRESS_INPUT);
    -  assertNotNullNorUndefined('EmailInput must be found', elt);
    -  return elt;
    -}
    -
    -function getEmailInputText() {
    -  return getEmailInput().value;
    -}
    -
    -function setEmailInputText(text) {
    -  var emailInput = getEmailInput();
    -  emailInput.value = text;
    -  // Fire event so that dialog behaves like when user types.
    -  fireInputEvent(dialog.emailInputHandler_, goog.events.KeyCodes.M);
    -}
    -
    -function getOpenInNewWindowCheckboxChecked() {
    -  return dialog.openInNewWindowCheckbox_.checked;
    -}
    -
    -function setOpenInNewWindowCheckboxChecked(checked) {
    -  dialog.openInNewWindowCheckbox_.checked = checked;
    -}
    -
    -function fireInputEvent(input, keyCode) {
    -  var inputEvent = new goog.testing.events.Event(goog.events.EventType.INPUT,
    -      input);
    -  inputEvent.keyCode = keyCode;
    -  inputEvent.charCode = keyCode;
    -  goog.testing.events.fireBrowserEvent(inputEvent);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/editor/messages.js b/src/database/third_party/closure-library/closure/goog/ui/editor/messages.js
    deleted file mode 100644
    index 614c97b22d1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/editor/messages.js
    +++ /dev/null
    @@ -1,148 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Messages common to Editor UI components.
    - *
    - * @author robbyw@google.com (Robby Walker)
    - */
    -
    -goog.provide('goog.ui.editor.messages');
    -
    -goog.require('goog.html.uncheckedconversions');
    -goog.require('goog.string.Const');
    -
    -
    -/** @desc Link button / bubble caption. */
    -goog.ui.editor.messages.MSG_LINK_CAPTION = goog.getMsg('Link');
    -
    -
    -/** @desc Title for the dialog that edits a link. */
    -goog.ui.editor.messages.MSG_EDIT_LINK = goog.getMsg('Edit Link');
    -
    -
    -/** @desc Prompt the user for the text of the link they've written. */
    -goog.ui.editor.messages.MSG_TEXT_TO_DISPLAY = goog.getMsg('Text to display:');
    -
    -
    -/** @desc Prompt the user for the URL of the link they've created. */
    -goog.ui.editor.messages.MSG_LINK_TO = goog.getMsg('Link to:');
    -
    -
    -/** @desc Prompt the user to type a web address for their link. */
    -goog.ui.editor.messages.MSG_ON_THE_WEB = goog.getMsg('Web address');
    -
    -
    -/** @desc More details on what linking to a web address involves.. */
    -goog.ui.editor.messages.MSG_ON_THE_WEB_TIP = goog.getMsg(
    -    'Link to a page or file somewhere else on the web');
    -
    -
    -/**
    - * @desc Text for a button that allows the user to test the link that
    - *     they created.
    - */
    -goog.ui.editor.messages.MSG_TEST_THIS_LINK = goog.getMsg('Test this link');
    -
    -
    -/**
    - * @desc Explanation for how to create a link with the link-editing dialog.
    - */
    -goog.ui.editor.messages.MSG_TR_LINK_EXPLANATION = goog.getMsg(
    -    '{$startBold}Not sure what to put in the box?{$endBold} ' +
    -    'First, find the page on the web that you want to ' +
    -    'link to. (A {$searchEngineLink}search engine{$endLink} ' +
    -    'might be useful.) Then, copy the web address from ' +
    -    "the box in your browser's address bar, and paste it into " +
    -    'the box above.',
    -    {'startBold': '<b>',
    -      'endBold': '</b>',
    -      'searchEngineLink': "<a href='http://www.google.com/' target='_new'>",
    -      'endLink': '</a>'});
    -
    -
    -/**
    - * @return {!goog.html.SafeHtml} SafeHtml version of MSG_TR_LINK_EXPLANATION.
    - */
    -goog.ui.editor.messages.getTrLinkExplanationSafeHtml = function() {
    -  return goog.html.uncheckedconversions.
    -      safeHtmlFromStringKnownToSatisfyTypeContract(
    -          goog.string.Const.from('Parameterless translation'),
    -          goog.ui.editor.messages.MSG_TR_LINK_EXPLANATION);
    -};
    -
    -
    -/** @desc Prompt for the URL of a link that the user is creating. */
    -goog.ui.editor.messages.MSG_WHAT_URL = goog.getMsg(
    -    'To what URL should this link go?');
    -
    -
    -/**
    - * @desc Prompt for an email address, so that the user can create a link
    - *    that sends an email.
    - */
    -goog.ui.editor.messages.MSG_EMAIL_ADDRESS = goog.getMsg('Email address');
    -
    -
    -/**
    - * @desc Explanation of the prompt for an email address in a link.
    - */
    -goog.ui.editor.messages.MSG_EMAIL_ADDRESS_TIP = goog.getMsg(
    -    'Link to an email address');
    -
    -
    -/** @desc Error message when the user enters an invalid email address. */
    -goog.ui.editor.messages.MSG_INVALID_EMAIL = goog.getMsg(
    -    'Invalid email address');
    -
    -
    -/**
    - * @desc When the user creates a mailto link, asks them what email
    - *     address clicking on this link will send mail to.
    - */
    -goog.ui.editor.messages.MSG_WHAT_EMAIL = goog.getMsg(
    -    'To what email address should this link?');
    -
    -
    -/**
    - * @desc Warning about the dangers of creating links with email
    - *     addresses in them.
    - */
    -goog.ui.editor.messages.MSG_EMAIL_EXPLANATION = goog.getMsg(
    -    '{$preb}Be careful.{$postb} ' +
    -    'Remember that any time you include an email address on a web page, ' +
    -    'nasty spammers can find it too.', {'preb': '<b>', 'postb': '</b>'});
    -
    -
    -/**
    - * @return {!goog.html.SafeHtml} SafeHtml version of MSG_EMAIL_EXPLANATION.
    - */
    -goog.ui.editor.messages.getEmailExplanationSafeHtml = function() {
    -  return goog.html.uncheckedconversions.
    -      safeHtmlFromStringKnownToSatisfyTypeContract(
    -          goog.string.Const.from('Parameterless translation'),
    -          goog.ui.editor.messages.MSG_EMAIL_EXPLANATION);
    -};
    -
    -
    -/**
    - * @desc Label for the checkbox that allows the user to specify what when this
    - *     link is clicked, it should be opened in a new window.
    - */
    -goog.ui.editor.messages.MSG_OPEN_IN_NEW_WINDOW = goog.getMsg(
    -    'Open this link in a new window');
    -
    -
    -/** @desc Image bubble caption. */
    -goog.ui.editor.messages.MSG_IMAGE_CAPTION = goog.getMsg('Image');
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/editor/tabpane.js b/src/database/third_party/closure-library/closure/goog/ui/editor/tabpane.js
    deleted file mode 100644
    index 7a5ec92506b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/editor/tabpane.js
    +++ /dev/null
    @@ -1,201 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Tabbed pane with style and functionality specific to
    - * Editor dialogs.
    - *
    - * @author robbyw@google.com (Robby Walker)
    - */
    -
    -goog.provide('goog.ui.editor.TabPane');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventType');
    -goog.require('goog.style');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.Control');
    -goog.require('goog.ui.Tab');
    -goog.require('goog.ui.TabBar');
    -
    -
    -
    -/**
    - * Creates a new Editor-style tab pane.
    - * @param {goog.dom.DomHelper} dom The dom helper for the window to create this
    - *     tab pane in.
    - * @param {string=} opt_caption Optional caption of the tab pane.
    - * @constructor
    - * @extends {goog.ui.Component}
    - * @final
    - */
    -goog.ui.editor.TabPane = function(dom, opt_caption) {
    -  goog.ui.editor.TabPane.base(this, 'constructor', dom);
    -
    -  /**
    -   * The event handler used to register events.
    -   * @type {goog.events.EventHandler<!goog.ui.editor.TabPane>}
    -   * @private
    -   */
    -  this.eventHandler_ = new goog.events.EventHandler(this);
    -  this.registerDisposable(this.eventHandler_);
    -
    -  /**
    -   * The tab bar used to render the tabs.
    -   * @type {goog.ui.TabBar}
    -   * @private
    -   */
    -  this.tabBar_ = new goog.ui.TabBar(goog.ui.TabBar.Location.START,
    -      undefined, this.dom_);
    -  this.tabBar_.setFocusable(false);
    -
    -  /**
    -   * The content element.
    -   * @private
    -   */
    -  this.tabContent_ = this.dom_.createDom(goog.dom.TagName.DIV,
    -      {className: goog.getCssName('goog-tab-content')});
    -
    -  /**
    -   * The currently selected radio button.
    -   * @type {Element}
    -   * @private
    -   */
    -  this.selectedRadio_ = null;
    -
    -  /**
    -   * The currently visible tab content.
    -   * @type {Element}
    -   * @private
    -   */
    -  this.visibleContent_ = null;
    -
    -
    -  // Add the caption as the first element in the tab bar.
    -  if (opt_caption) {
    -    var captionControl = new goog.ui.Control(opt_caption, undefined,
    -        this.dom_);
    -    captionControl.addClassName(goog.getCssName('tr-tabpane-caption'));
    -    captionControl.setEnabled(false);
    -    this.tabBar_.addChild(captionControl, true);
    -  }
    -};
    -goog.inherits(goog.ui.editor.TabPane, goog.ui.Component);
    -
    -
    -/**
    - * @return {string} The ID of the content element for the current tab.
    - */
    -goog.ui.editor.TabPane.prototype.getCurrentTabId = function() {
    -  return this.tabBar_.getSelectedTab().getId();
    -};
    -
    -
    -/**
    - * Selects the tab with the given id.
    - * @param {string} id Id of the tab to select.
    - */
    -goog.ui.editor.TabPane.prototype.setSelectedTabId = function(id) {
    -  this.tabBar_.setSelectedTab(this.tabBar_.getChild(id));
    -};
    -
    -
    -/**
    - * Adds a tab to the tab pane.
    - * @param {string} id The id of the tab to add.
    - * @param {string} caption The caption of the tab.
    - * @param {string} tooltip The tooltip for the tab.
    - * @param {string} groupName for the radio button group.
    - * @param {Element} content The content element to show when this tab is
    - *     selected.
    - */
    -goog.ui.editor.TabPane.prototype.addTab = function(id, caption, tooltip,
    -    groupName, content) {
    -  var radio = this.dom_.createDom(goog.dom.TagName.INPUT,
    -      {
    -        name: groupName,
    -        type: 'radio'
    -      });
    -
    -  var tab = new goog.ui.Tab([radio, this.dom_.createTextNode(caption)],
    -      undefined, this.dom_);
    -  tab.setId(id);
    -  tab.setTooltip(tooltip);
    -  this.tabBar_.addChild(tab, true);
    -
    -  // When you navigate the radio buttons with TAB and then the Arrow keys on
    -  // Chrome and FF, you get a CLICK event on them, and the radio button
    -  // is selected.  You don't get a SELECT at all.  We listen for SELECT
    -  // nonetheless because it's possible that some browser will issue only
    -  // SELECT.
    -  this.eventHandler_.listen(radio,
    -      [goog.events.EventType.SELECT, goog.events.EventType.CLICK],
    -      goog.bind(this.tabBar_.setSelectedTab, this.tabBar_, tab));
    -
    -  content.id = id + '-tab';
    -  this.tabContent_.appendChild(content);
    -  goog.style.setElementShown(content, false);
    -};
    -
    -
    -/** @override */
    -goog.ui.editor.TabPane.prototype.enterDocument = function() {
    -  goog.ui.editor.TabPane.base(this, 'enterDocument');
    -
    -  // Get the root element and add a class name to it.
    -  var root = this.getElement();
    -  goog.asserts.assert(root);
    -  goog.dom.classlist.add(root, goog.getCssName('tr-tabpane'));
    -
    -  // Add the tabs.
    -  this.addChild(this.tabBar_, true);
    -  this.eventHandler_.listen(this.tabBar_, goog.ui.Component.EventType.SELECT,
    -      this.handleTabSelect_);
    -
    -  // Add the tab content.
    -  root.appendChild(this.tabContent_);
    -
    -  // Add an element to clear the tab float.
    -  root.appendChild(
    -      this.dom_.createDom(goog.dom.TagName.DIV,
    -          {className: goog.getCssName('goog-tab-bar-clear')}));
    -};
    -
    -
    -/**
    - * Handles a tab change.
    - * @param {goog.events.Event} e The browser change event.
    - * @private
    - */
    -goog.ui.editor.TabPane.prototype.handleTabSelect_ = function(e) {
    -  var tab = /** @type {goog.ui.Tab} */ (e.target);
    -
    -  // Show the tab content.
    -  if (this.visibleContent_) {
    -    goog.style.setElementShown(this.visibleContent_, false);
    -  }
    -  this.visibleContent_ = this.dom_.getElement(tab.getId() + '-tab');
    -  goog.style.setElementShown(this.visibleContent_, true);
    -
    -  // Select the appropriate radio button (and deselect the current one).
    -  if (this.selectedRadio_) {
    -    this.selectedRadio_.checked = false;
    -  }
    -  this.selectedRadio_ = tab.getElement().getElementsByTagName(
    -      goog.dom.TagName.INPUT)[0];
    -  this.selectedRadio_.checked = true;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/editor/toolbarcontroller.js b/src/database/third_party/closure-library/closure/goog/ui/editor/toolbarcontroller.js
    deleted file mode 100644
    index 299780ad65b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/editor/toolbarcontroller.js
    +++ /dev/null
    @@ -1,296 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A class for managing the editor toolbar.
    - *
    - * @author attila@google.com (Attila Bodis)
    - * @see ../../demos/editor/editor.html
    - */
    -
    -goog.provide('goog.ui.editor.ToolbarController');
    -
    -goog.require('goog.editor.Field');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.ui.Component');
    -
    -
    -
    -/**
    - * A class for managing the editor toolbar.  Acts as a bridge between
    - * a {@link goog.editor.Field} and a {@link goog.ui.Toolbar}.
    - *
    - * The {@code toolbar} argument must be an instance of {@link goog.ui.Toolbar}
    - * or a subclass.  This class doesn't care how the toolbar was created.  As
    - * long as one or more controls hosted  in the toolbar have IDs that match
    - * built-in {@link goog.editor.Command}s, they will function as expected.  It is
    - * the caller's responsibility to ensure that the toolbar is already rendered
    - * or that it decorates an existing element.
    - *
    - *
    - * @param {!goog.editor.Field} field Editable field to be controlled by the
    - *     toolbar.
    - * @param {!goog.ui.Toolbar} toolbar Toolbar to control the editable field.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - */
    -goog.ui.editor.ToolbarController = function(field, toolbar) {
    -  goog.events.EventTarget.call(this);
    -
    -  /**
    -   * Event handler to listen for field events and user actions.
    -   * @type {!goog.events.EventHandler<!goog.ui.editor.ToolbarController>}
    -   * @private
    -   */
    -  this.handler_ = new goog.events.EventHandler(this);
    -
    -  /**
    -   * The field instance controlled by the toolbar.
    -   * @type {!goog.editor.Field}
    -   * @private
    -   */
    -  this.field_ = field;
    -
    -  /**
    -   * The toolbar that controls the field.
    -   * @type {!goog.ui.Toolbar}
    -   * @private
    -   */
    -  this.toolbar_ = toolbar;
    -
    -  /**
    -   * Editing commands whose state is to be queried when updating the toolbar.
    -   * @type {!Array<string>}
    -   * @private
    -   */
    -  this.queryCommands_ = [];
    -
    -  // Iterate over all buttons, and find those which correspond to
    -  // queryable commands. Add them to the list of commands to query on
    -  // each COMMAND_VALUE_CHANGE event.
    -  this.toolbar_.forEachChild(function(button) {
    -    if (button.queryable) {
    -      this.queryCommands_.push(this.getComponentId(button.getId()));
    -    }
    -  }, this);
    -
    -  // Make sure the toolbar doesn't steal keyboard focus.
    -  this.toolbar_.setFocusable(false);
    -
    -  // Hook up handlers that update the toolbar in response to field events,
    -  // and to execute editor commands in response to toolbar events.
    -  this.handler_.
    -      listen(this.field_, goog.editor.Field.EventType.COMMAND_VALUE_CHANGE,
    -          this.updateToolbar).
    -      listen(this.toolbar_, goog.ui.Component.EventType.ACTION,
    -          this.handleAction);
    -};
    -goog.inherits(goog.ui.editor.ToolbarController, goog.events.EventTarget);
    -
    -
    -/**
    - * Returns the Closure component ID of the control that corresponds to the
    - * given {@link goog.editor.Command} constant.
    - * Subclasses may override this method if they want to use a custom mapping
    - * scheme from commands to controls.
    - * @param {string} command Editor command.
    - * @return {string} Closure component ID of the corresponding toolbar
    - *     control, if any.
    - * @protected
    - */
    -goog.ui.editor.ToolbarController.prototype.getComponentId = function(command) {
    -  // The default implementation assumes that the component ID is the same as
    -  // the command constant.
    -  return command;
    -};
    -
    -
    -/**
    - * Returns the {@link goog.editor.Command} constant
    - * that corresponds to the given Closure component ID.  Subclasses may override
    - * this method if they want to use a custom mapping scheme from controls to
    - * commands.
    - * @param {string} id Closure component ID of a toolbar control.
    - * @return {string} Editor command or dialog constant corresponding to the
    - *     toolbar control, if any.
    - * @protected
    - */
    -goog.ui.editor.ToolbarController.prototype.getCommand = function(id) {
    -  // The default implementation assumes that the component ID is the same as
    -  // the command constant.
    -  return id;
    -};
    -
    -
    -/**
    - * Returns the event handler object for the editor toolbar.  Useful for classes
    - * that extend {@code goog.ui.editor.ToolbarController}.
    - * @return {!goog.events.EventHandler<T>} The event handler object.
    - * @protected
    - * @this T
    - * @template T
    - */
    -goog.ui.editor.ToolbarController.prototype.getHandler = function() {
    -  return this.handler_;
    -};
    -
    -
    -/**
    - * Returns the field instance managed by the toolbar.  Useful for
    - * classes that extend {@code goog.ui.editor.ToolbarController}.
    - * @return {!goog.editor.Field} The field managed by the toolbar.
    - * @protected
    - */
    -goog.ui.editor.ToolbarController.prototype.getField = function() {
    -  return this.field_;
    -};
    -
    -
    -/**
    - * Returns the toolbar UI component that manages the editor.  Useful for
    - * classes that extend {@code goog.ui.editor.ToolbarController}.
    - * @return {!goog.ui.Toolbar} The toolbar UI component.
    - */
    -goog.ui.editor.ToolbarController.prototype.getToolbar = function() {
    -  return this.toolbar_;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the toolbar is visible.
    - */
    -goog.ui.editor.ToolbarController.prototype.isVisible = function() {
    -  return this.toolbar_.isVisible();
    -};
    -
    -
    -/**
    - * Shows or hides the toolbar.
    - * @param {boolean} visible Whether to show or hide the toolbar.
    - */
    -goog.ui.editor.ToolbarController.prototype.setVisible = function(visible) {
    -  this.toolbar_.setVisible(visible);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the toolbar is enabled.
    - */
    -goog.ui.editor.ToolbarController.prototype.isEnabled = function() {
    -  return this.toolbar_.isEnabled();
    -};
    -
    -
    -/**
    - * Enables or disables the toolbar.
    - * @param {boolean} enabled Whether to enable or disable the toolbar.
    - */
    -goog.ui.editor.ToolbarController.prototype.setEnabled = function(enabled) {
    -  this.toolbar_.setEnabled(enabled);
    -};
    -
    -
    -/**
    - * Programmatically blurs the editor toolbar, un-highlighting the currently
    - * highlighted item, and closing the currently open menu (if any).
    - */
    -goog.ui.editor.ToolbarController.prototype.blur = function() {
    -  // We can't just call this.toolbar_.getElement().blur(), because the toolbar
    -  // element itself isn't focusable, so goog.ui.Container#handleBlur isn't
    -  // registered to handle blur events.
    -  this.toolbar_.handleBlur(null);
    -};
    -
    -
    -/** @override */
    -goog.ui.editor.ToolbarController.prototype.disposeInternal = function() {
    -  goog.ui.editor.ToolbarController.superClass_.disposeInternal.call(this);
    -  if (this.handler_) {
    -    this.handler_.dispose();
    -    delete this.handler_;
    -  }
    -  if (this.toolbar_) {
    -    this.toolbar_.dispose();
    -    delete this.toolbar_;
    -  }
    -  delete this.field_;
    -  delete this.queryCommands_;
    -};
    -
    -
    -/**
    - * Updates the toolbar in response to editor events.  Specifically, updates
    - * button states based on {@code COMMAND_VALUE_CHANGE} events, reflecting the
    - * effective formatting of the selection.
    - * @param {goog.events.Event} e Editor event to handle.
    - * @protected
    - */
    -goog.ui.editor.ToolbarController.prototype.updateToolbar = function(e) {
    -  if (!this.toolbar_.isEnabled() ||
    -      !this.dispatchEvent(goog.ui.Component.EventType.CHANGE)) {
    -    return;
    -  }
    -
    -  var state;
    -
    -  /** @preserveTry */
    -  try {
    -    /** @type {Array<string>} */
    -    e.commands; // Added by dispatchEvent.
    -
    -    // If the COMMAND_VALUE_CHANGE event specifies which commands changed
    -    // state, then we only need to update those ones, otherwise update all
    -    // commands.
    -    state = /** @type {Object} */ (
    -        this.field_.queryCommandValue(e.commands || this.queryCommands_));
    -  } catch (ex) {
    -    // TODO(attila): Find out when/why this happens.
    -    state = {};
    -  }
    -
    -  this.updateToolbarFromState(state);
    -};
    -
    -
    -/**
    - * Updates the toolbar to reflect a given state.
    - * @param {Object} state Object mapping editor commands to values.
    - */
    -goog.ui.editor.ToolbarController.prototype.updateToolbarFromState =
    -    function(state) {
    -  for (var command in state) {
    -    var button = this.toolbar_.getChild(this.getComponentId(command));
    -    if (button) {
    -      var value = state[command];
    -      if (button.updateFromValue) {
    -        button.updateFromValue(value);
    -      } else {
    -        button.setChecked(!!value);
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Handles {@code ACTION} events dispatched by toolbar buttons in response to
    - * user actions by executing the corresponding field command.
    - * @param {goog.events.Event} e Action event to handle.
    - * @protected
    - */
    -goog.ui.editor.ToolbarController.prototype.handleAction = function(e) {
    -  var command = this.getCommand(e.target.getId());
    -  this.field_.execCommand(command, e.target.getValue());
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/editor/toolbarfactory.js b/src/database/third_party/closure-library/closure/goog/ui/editor/toolbarfactory.js
    deleted file mode 100644
    index d179e184042..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/editor/toolbarfactory.js
    +++ /dev/null
    @@ -1,439 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Generic factory functions for creating the building blocks for
    - * an editor toolbar.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.editor.ToolbarFactory');
    -
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.string');
    -goog.require('goog.string.Unicode');
    -goog.require('goog.style');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.Container');
    -goog.require('goog.ui.Option');
    -goog.require('goog.ui.Toolbar');
    -goog.require('goog.ui.ToolbarButton');
    -goog.require('goog.ui.ToolbarColorMenuButton');
    -goog.require('goog.ui.ToolbarMenuButton');
    -goog.require('goog.ui.ToolbarRenderer');
    -goog.require('goog.ui.ToolbarSelect');
    -goog.require('goog.userAgent');
    -
    -
    -/**
    - * Takes a font spec (e.g. "Arial, Helvetica, sans-serif") and returns the
    - * primary font name, normalized to lowercase (e.g. "arial").
    - * @param {string} fontSpec Font specification.
    - * @return {string} The primary font name, in lowercase.
    - */
    -goog.ui.editor.ToolbarFactory.getPrimaryFont = function(fontSpec) {
    -  var i = fontSpec.indexOf(',');
    -  var fontName = (i != -1 ? fontSpec.substring(0, i) : fontSpec).toLowerCase();
    -  // Strip leading/trailing quotes from the font name (bug 1050118).
    -  return goog.string.stripQuotes(fontName, '"\'');
    -};
    -
    -
    -/**
    - * Bulk-adds fonts to the given font menu button.  The argument must be an
    - * array of font descriptor objects, each of which must have the following
    - * attributes:
    - * <ul>
    - *   <li>{@code caption} - Caption to show in the font menu (e.g. 'Tahoma')
    - *   <li>{@code value} - Value for the corresponding 'font-family' CSS style
    - *       (e.g. 'Tahoma, Arial, sans-serif')
    - * </ul>
    - * @param {!goog.ui.Select} button Font menu button.
    - * @param {!Array<{caption: string, value: string}>} fonts Array of
    - *     font descriptors.
    - */
    -goog.ui.editor.ToolbarFactory.addFonts = function(button, fonts) {
    -  goog.array.forEach(fonts, function(font) {
    -    goog.ui.editor.ToolbarFactory.addFont(button, font.caption, font.value);
    -  });
    -};
    -
    -
    -/**
    - * Adds a menu item to the given font menu button.  The first font listed in
    - * the {@code value} argument is considered the font ID, so adding two items
    - * whose CSS style starts with the same font may lead to unpredictable results.
    - * @param {!goog.ui.Select} button Font menu button.
    - * @param {string} caption Caption to show for the font menu.
    - * @param {string} value Value for the corresponding 'font-family' CSS style.
    - */
    -goog.ui.editor.ToolbarFactory.addFont = function(button, caption, value) {
    -  // The font ID is the first font listed in the CSS style, normalized to
    -  // lowercase.
    -  var id = goog.ui.editor.ToolbarFactory.getPrimaryFont(value);
    -
    -  // Construct the option, and add it to the button.
    -  var option = new goog.ui.Option(caption, value, button.getDomHelper());
    -  option.setId(id);
    -  button.addItem(option);
    -
    -  // Captions are shown in their own font.
    -  option.getContentElement().style.fontFamily = value;
    -};
    -
    -
    -/**
    - * Bulk-adds font sizes to the given font size menu button.  The argument must
    - * be an array of font size descriptor objects, each of which must have the
    - * following attributes:
    - * <ul>
    - *   <li>{@code caption} - Caption to show in the font size menu (e.g. 'Huge')
    - *   <li>{@code value} - Value for the corresponding HTML font size (e.g. 6)
    - * </ul>
    - * @param {!goog.ui.Select} button Font size menu button.
    - * @param {!Array<{caption: string, value:number}>} sizes Array of font
    - *     size descriptors.
    - */
    -goog.ui.editor.ToolbarFactory.addFontSizes = function(button, sizes) {
    -  goog.array.forEach(sizes, function(size) {
    -    goog.ui.editor.ToolbarFactory.addFontSize(button, size.caption, size.value);
    -  });
    -};
    -
    -
    -/**
    - * Adds a menu item to the given font size menu button.  The {@code value}
    - * argument must be a legacy HTML font size in the 0-7 range.
    - * @param {!goog.ui.Select} button Font size menu button.
    - * @param {string} caption Caption to show in the font size menu.
    - * @param {number} value Value for the corresponding HTML font size.
    - */
    -goog.ui.editor.ToolbarFactory.addFontSize = function(button, caption, value) {
    -  // Construct the option, and add it to the button.
    -  var option = new goog.ui.Option(caption, value, button.getDomHelper());
    -  button.addItem(option);
    -
    -  // Adjust the font size of the menu item and the height of the checkbox
    -  // element after they've been rendered by addItem().  Captions are shown in
    -  // the corresponding font size, and lining up the checkbox is tricky.
    -  var content = option.getContentElement();
    -  content.style.fontSize =
    -      goog.ui.editor.ToolbarFactory.getPxFromLegacySize(value) + 'px';
    -  content.firstChild.style.height = '1.1em';
    -};
    -
    -
    -/**
    - * Converts a legacy font size specification into an equivalent pixel size.
    - * For example, {@code &lt;font size="6"&gt;} is {@code font-size: 32px;}, etc.
    - * @param {number} fontSize Legacy font size spec in the 0-7 range.
    - * @return {number} Equivalent pixel size.
    - */
    -goog.ui.editor.ToolbarFactory.getPxFromLegacySize = function(fontSize) {
    -  return goog.ui.editor.ToolbarFactory.LEGACY_SIZE_TO_PX_MAP_[fontSize] || 10;
    -};
    -
    -
    -/**
    - * Converts a pixel font size specification into an equivalent legacy size.
    - * For example, {@code font-size: 32px;} is {@code &lt;font size="6"&gt;}, etc.
    - * If the given pixel size doesn't exactly match one of the legacy sizes, -1 is
    - * returned.
    - * @param {number} px Pixel font size.
    - * @return {number} Equivalent legacy size spec in the 0-7 range, or -1 if none
    - *     exists.
    - */
    -goog.ui.editor.ToolbarFactory.getLegacySizeFromPx = function(px) {
    -  // Use lastIndexOf to get the largest legacy size matching the pixel size
    -  // (most notably returning 1 instead of 0 for 10px).
    -  return goog.array.lastIndexOf(
    -      goog.ui.editor.ToolbarFactory.LEGACY_SIZE_TO_PX_MAP_, px);
    -};
    -
    -
    -/**
    - * Map of legacy font sizes (0-7) to equivalent pixel sizes.
    - * @type {!Array<number>}
    - * @private
    - */
    -goog.ui.editor.ToolbarFactory.LEGACY_SIZE_TO_PX_MAP_ =
    -    [10, 10, 13, 16, 18, 24, 32, 48];
    -
    -
    -/**
    - * Bulk-adds format options to the given "Format block" menu button.  The
    - * argument must be an array of format option descriptor objects, each of
    - * which must have the following attributes:
    - * <ul>
    - *   <li>{@code caption} - Caption to show in the menu (e.g. 'Minor heading')
    - *   <li>{@code command} - Corresponding {@link goog.dom.TagName} (e.g.
    - *       'H4')
    - * </ul>
    - * @param {!goog.ui.Select} button "Format block" menu button.
    - * @param {!Array<{caption: string, command: goog.dom.TagName}>} formats Array
    - *     of format option descriptors.
    - */
    -goog.ui.editor.ToolbarFactory.addFormatOptions = function(button, formats) {
    -  goog.array.forEach(formats, function(format) {
    -    goog.ui.editor.ToolbarFactory.addFormatOption(button, format.caption,
    -        format.command);
    -  });
    -};
    -
    -
    -/**
    - * Adds a menu item to the given "Format block" menu button.
    - * @param {!goog.ui.Select} button "Format block" menu button.
    - * @param {string} caption Caption to show in the menu.
    - * @param {goog.dom.TagName} tag Corresponding block format tag.
    - */
    -goog.ui.editor.ToolbarFactory.addFormatOption = function(button, caption, tag) {
    -  // Construct the option, and add it to the button.
    -  // TODO(attila): Create boring but functional menu item for now...
    -  var buttonDom = button.getDomHelper();
    -  var option = new goog.ui.Option(buttonDom.createDom(goog.dom.TagName.DIV,
    -      null, caption), tag, buttonDom);
    -  option.setId(tag);
    -  button.addItem(option);
    -};
    -
    -
    -/**
    - * Creates a {@link goog.ui.Toolbar} containing the specified set of
    - * toolbar buttons, and renders it into the given parent element.  Each
    - * item in the {@code items} array must a {@link goog.ui.Control}.
    - * @param {!Array<goog.ui.Control>} items Toolbar items; each must
    - *     be a {@link goog.ui.Control}.
    - * @param {!Element} elem Toolbar parent element.
    - * @param {boolean=} opt_isRightToLeft Whether the editor chrome is
    - *     right-to-left; defaults to the directionality of the toolbar parent
    - *     element.
    - * @return {!goog.ui.Toolbar} Editor toolbar, rendered into the given parent
    - *     element.
    - */
    -goog.ui.editor.ToolbarFactory.makeToolbar = function(items, elem,
    -    opt_isRightToLeft) {
    -  var domHelper = goog.dom.getDomHelper(elem);
    -
    -  // Create an empty horizontal toolbar using the default renderer.
    -  var toolbar = new goog.ui.Toolbar(goog.ui.ToolbarRenderer.getInstance(),
    -      goog.ui.Container.Orientation.HORIZONTAL, domHelper);
    -
    -  // Optimization:  Explicitly test for the directionality of the parent
    -  // element here, so we can set it for both the toolbar and its children,
    -  // saving a lot of expensive calls to goog.style.isRightToLeft() during
    -  // rendering.
    -  var isRightToLeft = opt_isRightToLeft || goog.style.isRightToLeft(elem);
    -  toolbar.setRightToLeft(isRightToLeft);
    -
    -  // Optimization:  Set the toolbar to non-focusable before it is rendered,
    -  // to avoid creating unnecessary keyboard event handler objects.
    -  toolbar.setFocusable(false);
    -
    -  for (var i = 0, button; button = items[i]; i++) {
    -    // Optimization:  Set the button to non-focusable before it is rendered,
    -    // to avoid creating unnecessary keyboard event handler objects.  Also set
    -    // the directionality of the button explicitly, to avoid expensive calls
    -    // to goog.style.isRightToLeft() during rendering.
    -    button.setSupportedState(goog.ui.Component.State.FOCUSED, false);
    -    button.setRightToLeft(isRightToLeft);
    -    toolbar.addChild(button, true);
    -  }
    -
    -  toolbar.render(elem);
    -  return toolbar;
    -};
    -
    -
    -/**
    - * Creates a toolbar button with the given ID, tooltip, and caption.  Applies
    - * any custom CSS class names to the button's caption element.
    - * @param {string} id Button ID; must equal a {@link goog.editor.Command} for
    - *     built-in buttons, anything else for custom buttons.
    - * @param {string} tooltip Tooltip to be shown on hover.
    - * @param {goog.ui.ControlContent} caption Button caption.
    - * @param {string=} opt_classNames CSS class name(s) to apply to the caption
    - *     element.
    - * @param {goog.ui.ButtonRenderer=} opt_renderer Button renderer; defaults to
    - *     {@link goog.ui.ToolbarButtonRenderer} if unspecified.
    - * @param {goog.dom.DomHelper=} opt_domHelper DOM helper, used for DOM
    - *     creation; defaults to the current document if unspecified.
    - * @return {!goog.ui.Button} A toolbar button.
    - */
    -goog.ui.editor.ToolbarFactory.makeButton = function(id, tooltip, caption,
    -    opt_classNames, opt_renderer, opt_domHelper) {
    -  var button = new goog.ui.ToolbarButton(
    -      goog.ui.editor.ToolbarFactory.createContent_(caption, opt_classNames,
    -          opt_domHelper),
    -      opt_renderer,
    -      opt_domHelper);
    -  button.setId(id);
    -  button.setTooltip(tooltip);
    -  return button;
    -};
    -
    -
    -/**
    - * Creates a toggle button with the given ID, tooltip, and caption. Applies
    - * any custom CSS class names to the button's caption element. The button
    - * returned has checkbox-like toggle semantics.
    - * @param {string} id Button ID; must equal a {@link goog.editor.Command} for
    - *     built-in buttons, anything else for custom buttons.
    - * @param {string} tooltip Tooltip to be shown on hover.
    - * @param {goog.ui.ControlContent} caption Button caption.
    - * @param {string=} opt_classNames CSS class name(s) to apply to the caption
    - *     element.
    - * @param {goog.ui.ButtonRenderer=} opt_renderer Button renderer; defaults to
    - *     {@link goog.ui.ToolbarButtonRenderer} if unspecified.
    - * @param {goog.dom.DomHelper=} opt_domHelper DOM helper, used for DOM
    - *     creation; defaults to the current document if unspecified.
    - * @return {!goog.ui.Button} A toggle button.
    - */
    -goog.ui.editor.ToolbarFactory.makeToggleButton = function(id, tooltip, caption,
    -    opt_classNames, opt_renderer, opt_domHelper) {
    -  var button = goog.ui.editor.ToolbarFactory.makeButton(id, tooltip, caption,
    -      opt_classNames, opt_renderer, opt_domHelper);
    -  button.setSupportedState(goog.ui.Component.State.CHECKED, true);
    -  return button;
    -};
    -
    -
    -/**
    - * Creates a menu button with the given ID, tooltip, and caption. Applies
    - * any custom CSS class names to the button's caption element.  The button
    - * returned doesn't have an actual menu attached; use {@link
    - * goog.ui.MenuButton#setMenu} to attach a {@link goog.ui.Menu} to the
    - * button.
    - * @param {string} id Button ID; must equal a {@link goog.editor.Command} for
    - *     built-in buttons, anything else for custom buttons.
    - * @param {string} tooltip Tooltip to be shown on hover.
    - * @param {goog.ui.ControlContent} caption Button caption.
    - * @param {string=} opt_classNames CSS class name(s) to apply to the caption
    - *     element.
    - * @param {goog.ui.ButtonRenderer=} opt_renderer Button renderer; defaults to
    - *     {@link goog.ui.ToolbarMenuButtonRenderer} if unspecified.
    - * @param {goog.dom.DomHelper=} opt_domHelper DOM helper, used for DOM
    - *     creation; defaults to the current document if unspecified.
    - * @return {!goog.ui.MenuButton} A menu button.
    - */
    -goog.ui.editor.ToolbarFactory.makeMenuButton = function(id, tooltip, caption,
    -    opt_classNames, opt_renderer, opt_domHelper) {
    -  var button = new goog.ui.ToolbarMenuButton(
    -      goog.ui.editor.ToolbarFactory.createContent_(caption, opt_classNames,
    -          opt_domHelper),
    -      null,
    -      opt_renderer,
    -      opt_domHelper);
    -  button.setId(id);
    -  button.setTooltip(tooltip);
    -  return button;
    -};
    -
    -
    -/**
    - * Creates a select button with the given ID, tooltip, and caption. Applies
    - * any custom CSS class names to the button's root element.  The button
    - * returned doesn't have an actual menu attached; use {@link
    - * goog.ui.Select#setMenu} to attach a {@link goog.ui.Menu} containing
    - * {@link goog.ui.Option}s to the select button.
    - * @param {string} id Button ID; must equal a {@link goog.editor.Command} for
    - *     built-in buttons, anything else for custom buttons.
    - * @param {string} tooltip Tooltip to be shown on hover.
    - * @param {goog.ui.ControlContent} caption Button caption; used as the
    - *     default caption when nothing is selected.
    - * @param {string=} opt_classNames CSS class name(s) to apply to the button's
    - *     root element.
    - * @param {goog.ui.MenuButtonRenderer=} opt_renderer Button renderer;
    - *     defaults to {@link goog.ui.ToolbarMenuButtonRenderer} if unspecified.
    - * @param {goog.dom.DomHelper=} opt_domHelper DOM helper, used for DOM
    - *     creation; defaults to the current document if unspecified.
    - * @return {!goog.ui.Select} A select button.
    - */
    -goog.ui.editor.ToolbarFactory.makeSelectButton = function(id, tooltip, caption,
    -    opt_classNames, opt_renderer, opt_domHelper) {
    -  var button = new goog.ui.ToolbarSelect(null, null,
    -      opt_renderer,
    -      opt_domHelper);
    -  if (opt_classNames) {
    -    // Unlike the other button types, for goog.ui.Select buttons we apply the
    -    // extra class names to the root element, because for select buttons the
    -    // caption isn't stable (as it changes each time the selection changes).
    -    goog.array.forEach(opt_classNames.split(/\s+/), button.addClassName,
    -        button);
    -  }
    -  button.addClassName(goog.getCssName('goog-toolbar-select'));
    -  button.setDefaultCaption(caption);
    -  button.setId(id);
    -  button.setTooltip(tooltip);
    -  return button;
    -};
    -
    -
    -/**
    - * Creates a color menu button with the given ID, tooltip, and caption.
    - * Applies any custom CSS class names to the button's caption element.  The
    - * button is created with a default color menu containing standard color
    - * palettes.
    - * @param {string} id Button ID; must equal a {@link goog.editor.Command} for
    - *     built-in toolbar buttons, but can be anything else for custom buttons.
    - * @param {string} tooltip Tooltip to be shown on hover.
    - * @param {goog.ui.ControlContent} caption Button caption.
    - * @param {string=} opt_classNames CSS class name(s) to apply to the caption
    - *     element.
    - * @param {goog.ui.ColorMenuButtonRenderer=} opt_renderer Button renderer;
    - *     defaults to {@link goog.ui.ToolbarColorMenuButtonRenderer}
    - *     if unspecified.
    - * @param {goog.dom.DomHelper=} opt_domHelper DOM helper, used for DOM
    - *     creation; defaults to the current document if unspecified.
    - * @return {!goog.ui.ColorMenuButton} A color menu button.
    - */
    -goog.ui.editor.ToolbarFactory.makeColorMenuButton = function(id, tooltip,
    -    caption, opt_classNames, opt_renderer, opt_domHelper) {
    -  var button = new goog.ui.ToolbarColorMenuButton(
    -      goog.ui.editor.ToolbarFactory.createContent_(caption, opt_classNames,
    -          opt_domHelper),
    -      null,
    -      opt_renderer,
    -      opt_domHelper);
    -  button.setId(id);
    -  button.setTooltip(tooltip);
    -  return button;
    -};
    -
    -
    -/**
    - * Creates a new DIV that wraps a button caption, optionally applying CSS
    - * class names to it.  Used as a helper function in button factory methods.
    - * @param {goog.ui.ControlContent} caption Button caption.
    - * @param {string=} opt_classNames CSS class name(s) to apply to the DIV that
    - *     wraps the caption (if any).
    - * @param {goog.dom.DomHelper=} opt_domHelper DOM helper, used for DOM
    - *     creation; defaults to the current document if unspecified.
    - * @return {!Element} DIV that wraps the caption.
    - * @private
    - */
    -goog.ui.editor.ToolbarFactory.createContent_ = function(caption, opt_classNames,
    -    opt_domHelper) {
    -  // FF2 doesn't like empty DIVs, especially when rendered right-to-left.
    -  if ((!caption || caption == '') && goog.userAgent.GECKO &&
    -      !goog.userAgent.isVersionOrHigher('1.9a')) {
    -    caption = goog.string.Unicode.NBSP;
    -  }
    -  return (opt_domHelper || goog.dom.getDomHelper()).createDom(
    -      goog.dom.TagName.DIV,
    -      opt_classNames ? {'class' : opt_classNames} : null, caption);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/editor/toolbarfactory_test.html b/src/database/third_party/closure-library/closure/goog/ui/editor/toolbarfactory_test.html
    deleted file mode 100644
    index e77e4be7b6c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/editor/toolbarfactory_test.html
    +++ /dev/null
    @@ -1,28 +0,0 @@
    -<!DOCTYPE html>
    -<!--
    -  All Rights Reserved.
    -
    -  @author jparent@google.com (Julie Parent)
    --->
    -<html>
    - <!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.editor.ToolbarFactory
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.editor.ToolbarFactoryTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="myField">foo</div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/editor/toolbarfactory_test.js b/src/database/third_party/closure-library/closure/goog/ui/editor/toolbarfactory_test.js
    deleted file mode 100644
    index 440c897bc96..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/editor/toolbarfactory_test.js
    +++ /dev/null
    @@ -1,73 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.editor.ToolbarFactoryTest');
    -goog.setTestOnly('goog.ui.editor.ToolbarFactoryTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.testing.ExpectedFailures');
    -goog.require('goog.testing.editor.TestHelper');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.editor.ToolbarFactory');
    -goog.require('goog.userAgent');
    -
    -var helper;
    -var expectedFailures;
    -
    -function setUpPage() {
    -  helper = new goog.testing.editor.TestHelper(goog.dom.getElement('myField'));
    -  expectedFailures = new goog.testing.ExpectedFailures();
    -}
    -
    -function setUp() {
    -  helper.setUpEditableElement();
    -}
    -
    -function tearDown() {
    -  helper.tearDownEditableElement();
    -  expectedFailures.handleTearDown();
    -}
    -
    -
    -/**
    - * Makes sure we have the correct conversion table in
    - * goog.ui.editor.ToolbarFactory.LEGACY_SIZE_TO_PX_MAP_. Can only be tested in
    - * a browser that takes legacy size values as input to execCommand but returns
    - * pixel size values from queryCommandValue. That's OK because that's the only
    - * situation where this conversion table's precision is critical. (When it's
    - * used to size the labels of the font size menu options it's ok if it's a few
    - * pixels off.)
    - */
    -function testGetLegacySizeFromPx() {
    -  // We will be warned if other browsers start behaving like webkit pre-534.7.
    -  expectedFailures.expectFailureFor(
    -      !goog.userAgent.WEBKIT ||
    -      (goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher('534.7')));
    -  try {
    -    var fieldElem = goog.dom.getElement('myField');
    -    // Start from 1 because size 0 is bogus (becomes 16px, legacy size 3).
    -    for (var i = 1; i <
    -        goog.ui.editor.ToolbarFactory.LEGACY_SIZE_TO_PX_MAP_.length; i++) {
    -      helper.select(fieldElem, 0, fieldElem, 1);
    -      document.execCommand('fontSize', false, i);
    -      helper.select('foo', 1);
    -      var value = document.queryCommandValue('fontSize');
    -      assertEquals('Px size ' + value + ' should convert to legacy size ' + i,
    -          i, goog.ui.editor.ToolbarFactory.getLegacySizeFromPx(
    -              parseInt(value, 10)));
    -    }
    -  } catch (e) {
    -    expectedFailures.handleException(e);
    -  }
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/emoji/emoji.js b/src/database/third_party/closure-library/closure/goog/ui/emoji/emoji.js
    deleted file mode 100644
    index af1b6eb4169..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/emoji/emoji.js
    +++ /dev/null
    @@ -1,73 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Emoji implementation.
    - *
    - */
    -
    -goog.provide('goog.ui.emoji.Emoji');
    -
    -
    -
    -/**
    - * Creates an emoji.
    - *
    - * A simple wrapper for an emoji.
    - *
    - * @param {string} url URL pointing to the source image for the emoji.
    - * @param {string} id The id of the emoji, e.g., 'std.1'.
    - * @constructor
    - * @final
    - */
    -goog.ui.emoji.Emoji = function(url, id) {
    -  /**
    -   * The URL pointing to the source image for the emoji
    -   *
    -   * @type {string}
    -   * @private
    -   */
    -  this.url_ = url;
    -
    -  /**
    -   * The id of the emoji
    -   *
    -   * @type {string}
    -   * @private
    -   */
    -  this.id_ = id;
    -};
    -
    -
    -/**
    - * The name of the goomoji attribute, used for emoji image elements.
    - * @type {string}
    - */
    -goog.ui.emoji.Emoji.ATTRIBUTE = 'goomoji';
    -
    -
    -/**
    - * @return {string} The URL for this emoji.
    - */
    -goog.ui.emoji.Emoji.prototype.getUrl = function() {
    -  return this.url_;
    -};
    -
    -
    -/**
    - * @return {string} The id of this emoji.
    - */
    -goog.ui.emoji.Emoji.prototype.getId = function() {
    -  return this.id_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/emoji/emojipalette.js b/src/database/third_party/closure-library/closure/goog/ui/emoji/emojipalette.js
    deleted file mode 100644
    index 77518c4b820..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/emoji/emojipalette.js
    +++ /dev/null
    @@ -1,288 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Emoji Palette implementation. This provides a UI widget for
    - * choosing an emoji from a palette of possible choices. EmojiPalettes are
    - * contained within EmojiPickers.
    - *
    - * See ../demos/popupemojipicker.html for an example of how to instantiate
    - * an emoji picker.
    - *
    - * Based on goog.ui.ColorPicker (colorpicker.js).
    - *
    - */
    -
    -goog.provide('goog.ui.emoji.EmojiPalette');
    -
    -goog.require('goog.events.EventType');
    -goog.require('goog.net.ImageLoader');
    -goog.require('goog.ui.Palette');
    -goog.require('goog.ui.emoji.Emoji');
    -goog.require('goog.ui.emoji.EmojiPaletteRenderer');
    -
    -
    -
    -/**
    - * A page of emoji to be displayed in an EmojiPicker.
    - *
    - * @param {Array<Array<?>>} emoji List of emoji for this page.
    -  * @param {?string=} opt_urlPrefix Prefix that should be prepended to all URL.
    - * @param {goog.ui.PaletteRenderer=} opt_renderer Renderer used to render or
    - *     decorate the palette; defaults to {@link goog.ui.PaletteRenderer}.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @extends {goog.ui.Palette}
    - * @constructor
    - * @final
    - */
    -goog.ui.emoji.EmojiPalette = function(emoji,
    -                                      opt_urlPrefix,
    -                                      opt_renderer,
    -                                      opt_domHelper) {
    -  goog.ui.Palette.call(this,
    -                       null,
    -                       opt_renderer ||
    -                       new goog.ui.emoji.EmojiPaletteRenderer(null),
    -                       opt_domHelper);
    -  /**
    -   * All the different emoji that this palette can display. Maps emoji ids
    -   * (string) to the goog.ui.emoji.Emoji for that id.
    -   *
    -   * @type {Object}
    -   * @private
    -   */
    -  this.emojiCells_ = {};
    -
    -  /**
    -   * Map of emoji id to index into this.emojiCells_.
    -   *
    -   * @type {Object}
    -   * @private
    -   */
    -  this.emojiMap_ = {};
    -
    -  /**
    -   * List of the animated emoji in this palette. Each internal array is of type
    -   * [HTMLDivElement, goog.ui.emoji.Emoji], and represents the palette item
    -   * for that animated emoji, and the Emoji object.
    -   *
    -   * @type {Array<Array<(HTMLDivElement|goog.ui.emoji.Emoji)>>}
    -   * @private
    -   */
    -  this.animatedEmoji_ = [];
    -
    -  this.urlPrefix_ = opt_urlPrefix || '';
    -
    -  /**
    -   * Palette items that are displayed on this page of the emoji picker. Each
    -   * item is a div wrapped around a div or an img.
    -   *
    -   * @type {Array<HTMLDivElement>}
    -   * @private
    -   */
    -  this.emoji_ = this.getEmojiArrayFromProperties_(emoji);
    -
    -  this.setContent(this.emoji_);
    -};
    -goog.inherits(goog.ui.emoji.EmojiPalette, goog.ui.Palette);
    -
    -
    -/**
    - * Indicates a prefix that should be prepended to all URLs of images in this
    - * emojipalette. This provides an optimization if the URLs are long, so that
    - * the client does not have to send a long string for each emoji.
    - *
    - * @type {string}
    - * @private
    - */
    -goog.ui.emoji.EmojiPalette.prototype.urlPrefix_ = '';
    -
    -
    -/**
    - * Whether the emoji images have been loaded.
    - *
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.emoji.EmojiPalette.prototype.imagesLoaded_ = false;
    -
    -
    -/**
    - * Image loader for loading animated emoji.
    - *
    - * @type {goog.net.ImageLoader}
    - * @private
    - */
    -goog.ui.emoji.EmojiPalette.prototype.imageLoader_;
    -
    -
    -/**
    - * Helps create an array of emoji palette items from an array of emoji
    - * properties. Each element will be either a div with background-image set to
    - * a sprite, or an img element pointing directly to an emoji, and all elements
    - * are wrapped with an outer div for alignment issues (i.e., this allows
    - * centering the inner div).
    - *
    - * @param {Object} emojiGroup The group of emoji for this page.
    - * @return {!Array<!HTMLDivElement>} The emoji items.
    - * @private
    - */
    -goog.ui.emoji.EmojiPalette.prototype.getEmojiArrayFromProperties_ =
    -    function(emojiGroup) {
    -  var emojiItems = [];
    -
    -  for (var i = 0; i < emojiGroup.length; i++) {
    -    var url = emojiGroup[i][0];
    -    var id = emojiGroup[i][1];
    -    var spriteInfo = emojiGroup[i][2];
    -    var displayUrl = spriteInfo ? spriteInfo.getUrl() :
    -                     this.urlPrefix_ + url;
    -
    -    var item = this.getRenderer().createPaletteItem(
    -        this.getDomHelper(), id, spriteInfo, displayUrl);
    -    emojiItems.push(item);
    -
    -    var emoji = new goog.ui.emoji.Emoji(url, id);
    -    this.emojiCells_[id] = emoji;
    -    this.emojiMap_[id] = i;
    -
    -    // Keep track of sprited emoji that are animated, for later loading.
    -    if (spriteInfo && spriteInfo.isAnimated()) {
    -      this.animatedEmoji_.push([item, emoji]);
    -    }
    -  }
    -
    -  // Create the image loader now so that tests can access it before it has
    -  // started loading images.
    -  if (this.animatedEmoji_.length > 0) {
    -    this.imageLoader_ = new goog.net.ImageLoader();
    -  }
    -
    -  this.imagesLoaded_ = true;
    -  return emojiItems;
    -};
    -
    -
    -/**
    - * Sends off requests for all the animated emoji and replaces their static
    - * sprites when the images are done downloading.
    - */
    -goog.ui.emoji.EmojiPalette.prototype.loadAnimatedEmoji = function() {
    -  if (this.animatedEmoji_.length > 0) {
    -    for (var i = 0; i < this.animatedEmoji_.length; i++) {
    -      var emoji =
    -          /** @type {goog.ui.emoji.Emoji} */ (this.animatedEmoji_[i][1]);
    -      var url = this.urlPrefix_ + emoji.getUrl();
    -
    -      this.imageLoader_.addImage(emoji.getId(), url);
    -    }
    -
    -    this.getHandler().listen(this.imageLoader_, goog.events.EventType.LOAD,
    -        this.handleImageLoad_);
    -    this.imageLoader_.start();
    -  }
    -};
    -
    -
    -/**
    - * Handles image load events from the ImageLoader.
    - *
    - * @param {goog.events.Event} e The event object.
    - * @private
    - */
    -goog.ui.emoji.EmojiPalette.prototype.handleImageLoad_ = function(e) {
    -  var id = e.target.id;
    -  var url = e.target.src;
    -  // Just to be safe, we check to make sure we have an id and src url from
    -  // the event target, which the ImageLoader sets to an Image object.
    -  if (id && url) {
    -    var item = this.emoji_[this.emojiMap_[id]];
    -    if (item) {
    -      this.getRenderer().updateAnimatedPaletteItem(item, e.target);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Returns the image loader that this palette uses. Used for testing.
    - *
    - * @return {goog.net.ImageLoader} the image loader.
    - */
    -goog.ui.emoji.EmojiPalette.prototype.getImageLoader = function() {
    -  return this.imageLoader_;
    -};
    -
    -
    -/** @override */
    -goog.ui.emoji.EmojiPalette.prototype.disposeInternal = function() {
    -  goog.ui.emoji.EmojiPalette.superClass_.disposeInternal.call(this);
    -
    -  if (this.imageLoader_) {
    -    this.imageLoader_.dispose();
    -    this.imageLoader_ = null;
    -  }
    -  this.animatedEmoji_ = null;
    -  this.emojiCells_ = null;
    -  this.emojiMap_ = null;
    -  this.emoji_ = null;
    -};
    -
    -
    -/**
    - * Returns a goomoji id from an img or the containing td, or null if none
    - * exists for that element.
    - *
    - * @param {Element} el The element to get the Goomoji id from.
    - * @return {?string} A goomoji id from an img or the containing td, or null if
    - *     none exists for that element.
    - * @private
    - */
    -goog.ui.emoji.EmojiPalette.prototype.getGoomojiIdFromElement_ = function(el) {
    -  if (!el) {
    -    return null;
    -  }
    -
    -  var item = this.getRenderer().getContainingItem(this, el);
    -  return item ? item.getAttribute(goog.ui.emoji.Emoji.ATTRIBUTE) : null;
    -};
    -
    -
    -/**
    - * @return {goog.ui.emoji.Emoji} The currently selected emoji from this palette.
    - */
    -goog.ui.emoji.EmojiPalette.prototype.getSelectedEmoji = function() {
    -  var elem = /** @type {Element} */ (this.getSelectedItem());
    -  var goomojiId = this.getGoomojiIdFromElement_(elem);
    -  return this.emojiCells_[goomojiId];
    -};
    -
    -
    -/**
    - * @return {number} The number of emoji managed by this palette.
    - */
    -goog.ui.emoji.EmojiPalette.prototype.getNumberOfEmoji = function() {
    -  return this.emojiCells_.length;
    -};
    -
    -
    -/**
    - * Returns the index of the specified emoji within this palette.
    - *
    - * @param {string} id Id of the emoji to look up.
    - * @return {number} The index of the specified emoji within this palette.
    - */
    -goog.ui.emoji.EmojiPalette.prototype.getEmojiIndex = function(id) {
    -  return this.emojiMap_[id];
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/emoji/emojipaletterenderer.js b/src/database/third_party/closure-library/closure/goog/ui/emoji/emojipaletterenderer.js
    deleted file mode 100644
    index ece47dbf2c8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/emoji/emojipaletterenderer.js
    +++ /dev/null
    @@ -1,209 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Emoji Palette renderer implementation.
    - *
    - */
    -
    -goog.provide('goog.ui.emoji.EmojiPaletteRenderer');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.asserts');
    -goog.require('goog.dom.NodeType');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.style');
    -goog.require('goog.ui.PaletteRenderer');
    -goog.require('goog.ui.emoji.Emoji');
    -
    -
    -
    -/**
    - * Renders an emoji palette.
    - *
    - * @param {?string} defaultImgUrl Url of the img that should be used to fill up
    - *     the cells in the emoji table, to prevent jittering. Will be stretched
    - *     to the emoji cell size. A good image is a transparent dot.
    - * @constructor
    - * @extends {goog.ui.PaletteRenderer}
    - */
    -goog.ui.emoji.EmojiPaletteRenderer = function(defaultImgUrl) {
    -  goog.ui.PaletteRenderer.call(this);
    -
    -  this.defaultImgUrl_ = defaultImgUrl;
    -};
    -goog.inherits(goog.ui.emoji.EmojiPaletteRenderer, goog.ui.PaletteRenderer);
    -
    -
    -/**
    - * Globally unique ID sequence for cells rendered by this renderer class.
    - * @type {number}
    - * @private
    - */
    -goog.ui.emoji.EmojiPaletteRenderer.cellId_ = 0;
    -
    -
    -/**
    - * Url of the img that should be used for cells in the emoji palette that are
    - * not filled with emoji, i.e., after all the emoji have already been placed
    - * on a page.
    - *
    - * @type {?string}
    - * @private
    - */
    -goog.ui.emoji.EmojiPaletteRenderer.prototype.defaultImgUrl_ = null;
    -
    -
    -/** @override */
    -goog.ui.emoji.EmojiPaletteRenderer.getCssClass = function() {
    -  return goog.getCssName('goog-ui-emojipalette');
    -};
    -
    -
    -/**
    - * Creates a palette item from the given emoji data.
    - *
    - * @param {goog.dom.DomHelper} dom DOM helper for constructing DOM elements.
    - * @param {string} id Goomoji id for the emoji.
    - * @param {goog.ui.emoji.SpriteInfo} spriteInfo Spriting info for the emoji.
    - * @param {string} displayUrl URL of the image served for this cell, whether
    - *     an individual emoji image or a sprite.
    - * @return {!HTMLDivElement} The palette item for this emoji.
    - */
    -goog.ui.emoji.EmojiPaletteRenderer.prototype.createPaletteItem =
    -    function(dom, id, spriteInfo, displayUrl) {
    -  var el;
    -
    -  if (spriteInfo) {
    -    var cssClass = spriteInfo.getCssClass();
    -    if (cssClass) {
    -      el = dom.createDom('div', cssClass);
    -    } else {
    -      el = this.buildElementFromSpriteMetadata(dom, spriteInfo, displayUrl);
    -    }
    -  } else {
    -    el = dom.createDom('img', {'src': displayUrl});
    -  }
    -
    -  var outerdiv =
    -      dom.createDom('div', goog.getCssName('goog-palette-cell-wrapper'), el);
    -  outerdiv.setAttribute(goog.ui.emoji.Emoji.ATTRIBUTE, id);
    -  return /** @type {!HTMLDivElement} */ (outerdiv);
    -};
    -
    -
    -/**
    - * Modifies a palette item containing an animated emoji, in response to the
    - * animated emoji being successfully downloaded.
    - *
    - * @param {Element} item The palette item to update.
    - * @param {Image} animatedImg An Image object containing the animated emoji.
    - */
    -goog.ui.emoji.EmojiPaletteRenderer.prototype.updateAnimatedPaletteItem =
    -    function(item, animatedImg) {
    -  // An animated emoji is one that had sprite info for a static version and is
    -  // now being updated. See createPaletteItem for the structure of the palette
    -  // items we're modifying.
    -
    -  var inner = /** @type {Element} */ (item.firstChild);
    -  goog.asserts.assert(inner);
    -  // The first case is a palette item with a CSS class representing the sprite,
    -  // and an animated emoji.
    -  var classes = goog.dom.classlist.get(inner);
    -  if (classes && classes.length == 1) {
    -    inner.className = '';
    -  }
    -
    -  goog.style.setStyle(inner, {
    -    'width': animatedImg.width,
    -    'height': animatedImg.height,
    -    'background-image': 'url(' + animatedImg.src + ')',
    -    'background-position': '0 0'
    -  });
    -};
    -
    -
    -/**
    - * Builds the inner contents of a palette item out of sprite metadata.
    - *
    - * @param {goog.dom.DomHelper} dom DOM helper for constructing DOM elements.
    - * @param {goog.ui.emoji.SpriteInfo} spriteInfo The metadata to create the css
    - *     for the sprite.
    - * @param {string} displayUrl The URL of the image for this cell.
    - * @return {HTMLDivElement} The inner element for a palette item.
    - */
    -goog.ui.emoji.EmojiPaletteRenderer.prototype.buildElementFromSpriteMetadata =
    -    function(dom, spriteInfo, displayUrl) {
    -  var width = spriteInfo.getWidthCssValue();
    -  var height = spriteInfo.getHeightCssValue();
    -  var x = spriteInfo.getXOffsetCssValue();
    -  var y = spriteInfo.getYOffsetCssValue();
    -
    -  var el = dom.createDom('div');
    -  goog.style.setStyle(el, {
    -    'width': width,
    -    'height': height,
    -    'background-image': 'url(' + displayUrl + ')',
    -    'background-repeat': 'no-repeat',
    -    'background-position': x + ' ' + y
    -  });
    -
    -  return /** @type {!HTMLDivElement} */ (el);
    -};
    -
    -
    -/** @override */
    -goog.ui.emoji.EmojiPaletteRenderer.prototype.createCell = function(node, dom) {
    -  // Create a cell with  the default img if we're out of items, in order to
    -  // prevent jitter in the table. If there's no default img url, just create an
    -  // empty div, to prevent trying to fetch a null url.
    -  if (!node) {
    -    var elem = this.defaultImgUrl_ ?
    -               dom.createDom('img', {'src': this.defaultImgUrl_}) :
    -               dom.createDom('div');
    -    node = dom.createDom('div', goog.getCssName('goog-palette-cell-wrapper'),
    -                         elem);
    -  }
    -
    -  var cell = dom.createDom('td', {
    -    'class': goog.getCssName(this.getCssClass(), 'cell'),
    -    // Cells must have an ID, for accessibility, so we generate one here.
    -    'id': this.getCssClass() + '-cell-' +
    -        goog.ui.emoji.EmojiPaletteRenderer.cellId_++
    -  }, node);
    -  goog.a11y.aria.setRole(cell, 'gridcell');
    -  return cell;
    -};
    -
    -
    -/**
    - * Returns the item corresponding to the given node, or null if the node is
    - * neither a palette cell nor part of a palette item.
    - * @param {goog.ui.Palette} palette Palette in which to look for the item.
    - * @param {Node} node Node to look for.
    - * @return {Node} The corresponding palette item (null if not found).
    - * @override
    - */
    -goog.ui.emoji.EmojiPaletteRenderer.prototype.getContainingItem =
    -    function(palette, node) {
    -  var root = palette.getElement();
    -  while (node && node.nodeType == goog.dom.NodeType.ELEMENT && node != root) {
    -    if (node.tagName == 'TD') {
    -      return node.firstChild;
    -    }
    -    node = node.parentNode;
    -  }
    -
    -  return null;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/emoji/emojipicker.js b/src/database/third_party/closure-library/closure/goog/ui/emoji/emojipicker.js
    deleted file mode 100644
    index e50fdfb5fdb..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/emoji/emojipicker.js
    +++ /dev/null
    @@ -1,803 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Emoji Picker implementation. This provides a UI widget for
    - * choosing an emoji from a grid of possible choices.
    - *
    - * @see ../demos/popupemojipicker.html for an example of how to instantiate
    - * an emoji picker.
    - *
    - * Based on goog.ui.ColorPicker (colorpicker.js).
    - *
    - * @see ../../demos/popupemojipicker.html
    - */
    -
    -goog.provide('goog.ui.emoji.EmojiPicker');
    -
    -goog.require('goog.log');
    -goog.require('goog.style');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.TabPane');
    -goog.require('goog.ui.emoji.Emoji');
    -goog.require('goog.ui.emoji.EmojiPalette');
    -goog.require('goog.ui.emoji.EmojiPaletteRenderer');
    -goog.require('goog.ui.emoji.ProgressiveEmojiPaletteRenderer');
    -
    -
    -
    -/**
    - * Creates a new, empty emoji picker. An emoji picker is a grid of emoji, each
    - * cell of the grid containing a single emoji. The picker may contain multiple
    - * pages of emoji.
    - *
    - * When a user selects an emoji, by either clicking or pressing enter, the
    - * picker fires a goog.ui.Component.EventType.ACTION event with the id. The
    - * client listens on this event and in the handler can retrieve the id of the
    - * selected emoji and do something with it, for instance, inserting an image
    - * tag into a rich text control. An emoji picker does not maintain state. That
    - * is, once an emoji is selected, the emoji picker does not remember which emoji
    - * was selected.
    - *
    - * The emoji picker is implemented as a tabpane with each tabpage being a table.
    - * Each of the tables are the same size to prevent jittering when switching
    - * between pages.
    - *
    - * @param {string} defaultImgUrl Url of the img that should be used to fill up
    - *     the cells in the emoji table, to prevent jittering. Should be the same
    - *     size as the emoji.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @extends {goog.ui.Component}
    - * @constructor
    - */
    -goog.ui.emoji.EmojiPicker = function(defaultImgUrl, opt_domHelper) {
    -  goog.ui.Component.call(this, opt_domHelper);
    -
    -  this.defaultImgUrl_ = defaultImgUrl;
    -
    -  /**
    -   * Emoji that this picker displays.
    -   *
    -   * @type {Array<Object>}
    -   * @private
    -   */
    -  this.emoji_ = [];
    -
    -  /**
    -   * Pages of this emoji picker.
    -   *
    -   * @type {Array<goog.ui.emoji.EmojiPalette>}
    -   * @private
    -   */
    -  this.pages_ = [];
    -
    -  /**
    -   * Keeps track of which pages in the picker have been loaded. Used for delayed
    -   * loading of tabs.
    -   *
    -   * @type {Array<boolean>}
    -   * @private
    -   */
    -  this.pageLoadStatus_ = [];
    -
    -  /**
    -   * Tabpane to hold the pages of this emojipicker.
    -   *
    -   * @type {goog.ui.TabPane}
    -   * @private
    -   */
    -  this.tabPane_ = null;
    -
    -  this.getHandler().listen(this, goog.ui.Component.EventType.ACTION,
    -      this.onEmojiPaletteAction_);
    -};
    -goog.inherits(goog.ui.emoji.EmojiPicker, goog.ui.Component);
    -
    -
    -/**
    - * Default number of rows per grid of emoji.
    - *
    - * @type {number}
    - */
    -goog.ui.emoji.EmojiPicker.DEFAULT_NUM_ROWS = 5;
    -
    -
    -/**
    - * Default number of columns per grid of emoji.
    - *
    - * @type {number}
    - */
    -goog.ui.emoji.EmojiPicker.DEFAULT_NUM_COLS = 10;
    -
    -
    -/**
    - * Default location of the tabs in relation to the emoji grids.
    - *
    - * @type {goog.ui.TabPane.TabLocation}
    - */
    -goog.ui.emoji.EmojiPicker.DEFAULT_TAB_LOCATION =
    -    goog.ui.TabPane.TabLocation.TOP;
    -
    -
    -/** @private {goog.ui.emoji.Emoji} */
    -goog.ui.emoji.EmojiPicker.prototype.selectedEmoji_;
    -
    -
    -/** @private {goog.ui.emoji.EmojiPaletteRenderer} */
    -goog.ui.emoji.EmojiPicker.prototype.renderer_;
    -
    -
    -/**
    - * Number of rows per grid of emoji.
    - *
    - * @type {number}
    - * @private
    - */
    -goog.ui.emoji.EmojiPicker.prototype.numRows_ =
    -    goog.ui.emoji.EmojiPicker.DEFAULT_NUM_ROWS;
    -
    -
    -/**
    - * Number of columns per grid of emoji.
    - *
    - * @type {number}
    - * @private
    - */
    -goog.ui.emoji.EmojiPicker.prototype.numCols_ =
    -    goog.ui.emoji.EmojiPicker.DEFAULT_NUM_COLS;
    -
    -
    -/**
    - * Whether the number of rows in the picker should be automatically determined
    - * by the specified number of columns so as to minimize/eliminate jitter when
    - * switching between tabs.
    - *
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.emoji.EmojiPicker.prototype.autoSizeByColumnCount_ = true;
    -
    -
    -/**
    - * Location of the tabs for the picker tabpane.
    - *
    - * @type {goog.ui.TabPane.TabLocation}
    - * @private
    - */
    -goog.ui.emoji.EmojiPicker.prototype.tabLocation_ =
    -    goog.ui.emoji.EmojiPicker.DEFAULT_TAB_LOCATION;
    -
    -
    -/**
    - * Whether the component is focusable.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.emoji.EmojiPicker.prototype.focusable_ = true;
    -
    -
    -/**
    - * Url of the img that should be used for cells in the emoji picker that are
    - * not filled with emoji, i.e., after all the emoji have already been placed
    - * on a page.
    - *
    - * @type {string}
    - * @private
    - */
    -goog.ui.emoji.EmojiPicker.prototype.defaultImgUrl_;
    -
    -
    -/**
    - * If present, indicates a prefix that should be prepended to all URLs
    - * of images in this emojipicker. This provides an optimization if the URLs
    - * are long, so that the client does not have to send a long string for each
    - * emoji.
    - *
    - * @type {string|undefined}
    - * @private
    - */
    -goog.ui.emoji.EmojiPicker.prototype.urlPrefix_;
    -
    -
    -/**
    - * If true, delay loading the images for the emojipalettes until after
    - * construction. This gives a better user experience before the images are in
    - * the cache, since other widgets waiting for construction of the emojipalettes
    - * won't have to wait for all the images (which may be a substantial amount) to
    - * load.
    - *
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.emoji.EmojiPicker.prototype.delayedLoad_ = false;
    -
    -
    -/**
    - * Whether to use progressive rendering in the emojipicker's palette, if using
    - * sprited imgs. If true, then uses img tags, which most browsers render
    - * progressively (i.e., as the data comes in). If false, then uses div tags
    - * with the background-image, which some newer browsers render progressively
    - * but older ones do not.
    - *
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.emoji.EmojiPicker.prototype.progressiveRender_ = false;
    -
    -
    -/**
    - * Whether to require the caller to manually specify when to start loading
    - * animated emoji. This is primarily for unittests to be able to test the
    - * structure of the emojipicker palettes before and after the animated emoji
    - * have been loaded.
    - *
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.emoji.EmojiPicker.prototype.manualLoadOfAnimatedEmoji_ = false;
    -
    -
    -/**
    - * Index of the active page in the picker.
    - *
    - * @type {number}
    - * @private
    - */
    -goog.ui.emoji.EmojiPicker.prototype.activePage_ = -1;
    -
    -
    -/**
    - * Adds a group of emoji to the picker.
    - *
    - * @param {string|Element} title Title for the group.
    - * @param {Array<Array<string>>} emojiGroup A new group of emoji to be added
    - *    Each internal array contains [emojiUrl, emojiId].
    - */
    -goog.ui.emoji.EmojiPicker.prototype.addEmojiGroup =
    -    function(title, emojiGroup) {
    -  this.emoji_.push({title: title, emoji: emojiGroup});
    -};
    -
    -
    -/**
    - * Gets the number of rows per grid in the emoji picker.
    - *
    - * @return {number} number of rows per grid.
    - */
    -goog.ui.emoji.EmojiPicker.prototype.getNumRows = function() {
    -  return this.numRows_;
    -};
    -
    -
    -/**
    - * Gets the number of columns per grid in the emoji picker.
    - *
    - * @return {number} number of columns per grid.
    - */
    -goog.ui.emoji.EmojiPicker.prototype.getNumColumns = function() {
    -  return this.numCols_;
    -};
    -
    -
    -/**
    - * Sets the number of rows per grid in the emoji picker. This should only be
    - * called before the picker has been rendered.
    - *
    - * @param {number} numRows Number of rows per grid.
    - */
    -goog.ui.emoji.EmojiPicker.prototype.setNumRows = function(numRows) {
    -  this.numRows_ = numRows;
    -};
    -
    -
    -/**
    - * Sets the number of columns per grid in the emoji picker. This should only be
    - * called before the picker has been rendered.
    - *
    - * @param {number} numCols Number of columns per grid.
    - */
    -goog.ui.emoji.EmojiPicker.prototype.setNumColumns = function(numCols) {
    -  this.numCols_ = numCols;
    -};
    -
    -
    -/**
    - * Sets whether to automatically size the emojipicker based on the number of
    - * columns and the number of emoji in each group, so as to reduce jitter.
    - *
    - * @param {boolean} autoSize Whether to automatically size the picker.
    - */
    -goog.ui.emoji.EmojiPicker.prototype.setAutoSizeByColumnCount =
    -    function(autoSize) {
    -  this.autoSizeByColumnCount_ = autoSize;
    -};
    -
    -
    -/**
    - * Sets the location of the tabs in relation to the emoji grids. This should
    - * only be called before the picker has been rendered.
    - *
    - * @param {goog.ui.TabPane.TabLocation} tabLocation The location of the tabs.
    - */
    -goog.ui.emoji.EmojiPicker.prototype.setTabLocation = function(tabLocation) {
    -  this.tabLocation_ = tabLocation;
    -};
    -
    -
    -/**
    - * Sets whether loading of images should be delayed until after dom creation.
    - * Thus, this function must be called before {@link #createDom}. If set to true,
    - * the client must call {@link #loadImages} when they wish the images to be
    - * loaded.
    - *
    - * @param {boolean} shouldDelay Whether to delay loading the images.
    - */
    -goog.ui.emoji.EmojiPicker.prototype.setDelayedLoad = function(shouldDelay) {
    -  this.delayedLoad_ = shouldDelay;
    -};
    -
    -
    -/**
    - * Sets whether to require the caller to manually specify when to start loading
    - * animated emoji. This is primarily for unittests to be able to test the
    - * structure of the emojipicker palettes before and after the animated emoji
    - * have been loaded. This only affects sprited emojipickers with sprite data
    - * for animated emoji.
    - *
    - * @param {boolean} manual Whether to load animated emoji manually.
    - */
    -goog.ui.emoji.EmojiPicker.prototype.setManualLoadOfAnimatedEmoji =
    -    function(manual) {
    -  this.manualLoadOfAnimatedEmoji_ = manual;
    -};
    -
    -
    -/**
    - * Returns true if the component is focusable, false otherwise.  The default
    - * is true.  Focusable components always have a tab index and allocate a key
    - * handler to handle keyboard events while focused.
    - * @return {boolean} Whether the component is focusable.
    - */
    -goog.ui.emoji.EmojiPicker.prototype.isFocusable = function() {
    -  return this.focusable_;
    -};
    -
    -
    -/**
    - * Sets whether the component is focusable.  The default is true.
    - * Focusable components always have a tab index and allocate a key handler to
    - * handle keyboard events while focused.
    - * @param {boolean} focusable Whether the component is focusable.
    - */
    -goog.ui.emoji.EmojiPicker.prototype.setFocusable = function(focusable) {
    -  this.focusable_ = focusable;
    -  for (var i = 0; i < this.pages_.length; i++) {
    -    if (this.pages_[i]) {
    -      this.pages_[i].setSupportedState(goog.ui.Component.State.FOCUSED,
    -                                       focusable);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Sets the URL prefix for the emoji URLs.
    - *
    - * @param {string} urlPrefix Prefix that should be prepended to all URLs.
    - */
    -goog.ui.emoji.EmojiPicker.prototype.setUrlPrefix = function(urlPrefix) {
    -  this.urlPrefix_ = urlPrefix;
    -};
    -
    -
    -/**
    - * Sets the progressive rendering aspect of this emojipicker. Must be called
    - * before createDom to have an effect.
    - *
    - * @param {boolean} progressive Whether this picker should render progressively.
    - */
    -goog.ui.emoji.EmojiPicker.prototype.setProgressiveRender =
    -    function(progressive) {
    -  this.progressiveRender_ = progressive;
    -};
    -
    -
    -
    -/**
    - * Adjusts the number of rows to be the maximum row count out of all the emoji
    - * groups, in order to prevent jitter in switching among the tabs.
    - *
    - * @private
    - */
    -goog.ui.emoji.EmojiPicker.prototype.adjustNumRowsIfNecessary_ = function() {
    -  var currentMax = 0;
    -
    -  for (var i = 0; i < this.emoji_.length; i++) {
    -    var numEmoji = this.emoji_[i].emoji.length;
    -    var rowsNeeded = Math.ceil(numEmoji / this.numCols_);
    -    if (rowsNeeded > currentMax) {
    -      currentMax = rowsNeeded;
    -    }
    -  }
    -
    -  this.setNumRows(currentMax);
    -};
    -
    -
    -/**
    - * Causes the emoji imgs to be loaded into the picker. Used for delayed loading.
    - * No-op if delayed loading is not set.
    - */
    -goog.ui.emoji.EmojiPicker.prototype.loadImages = function() {
    -  if (!this.delayedLoad_) {
    -    return;
    -  }
    -
    -  // Load the first page only
    -  this.loadPage_(0);
    -  this.activePage_ = 0;
    -};
    -
    -
    -/**
    - * @override
    - * @suppress {deprecated} Using deprecated goog.ui.TabPane.
    - */
    -goog.ui.emoji.EmojiPicker.prototype.createDom = function() {
    -  this.setElementInternal(this.getDomHelper().createDom('div'));
    -
    -  if (this.autoSizeByColumnCount_) {
    -    this.adjustNumRowsIfNecessary_();
    -  }
    -
    -  if (this.emoji_.length == 0) {
    -    throw Error('Must add some emoji to the picker');
    -  }
    -
    -  // If there is more than one group of emoji, we construct a tabpane
    -  if (this.emoji_.length > 1) {
    -    // Give the tabpane a div to use as its content element, since tabpane
    -    // overwrites the CSS class of the element it's passed
    -    var div = this.getDomHelper().createDom('div');
    -    this.getElement().appendChild(div);
    -    this.tabPane_ = new goog.ui.TabPane(div,
    -                                        this.tabLocation_,
    -                                        this.getDomHelper(),
    -                                        true  /* use MOUSEDOWN */);
    -  }
    -
    -  this.renderer_ = this.progressiveRender_ ?
    -      new goog.ui.emoji.ProgressiveEmojiPaletteRenderer(this.defaultImgUrl_) :
    -      new goog.ui.emoji.EmojiPaletteRenderer(this.defaultImgUrl_);
    -
    -  for (var i = 0; i < this.emoji_.length; i++) {
    -    var emoji = this.emoji_[i].emoji;
    -    var page = this.delayedLoad_ ?
    -               this.createPlaceholderEmojiPage_(emoji) :
    -               this.createEmojiPage_(emoji, i);
    -    this.pages_.push(page);
    -  }
    -
    -  this.activePage_ = 0;
    -  this.getElement().tabIndex = 0;
    -};
    -
    -
    -/**
    - * Used by unittests to manually load the animated emoji for this picker.
    - */
    -goog.ui.emoji.EmojiPicker.prototype.manuallyLoadAnimatedEmoji = function() {
    -  for (var i = 0; i < this.pages_.length; i++) {
    -    this.pages_[i].loadAnimatedEmoji();
    -  }
    -};
    -
    -
    -/**
    - * Creates a page if it has not already been loaded. This has the side effects
    - * of setting the load status of the page to true.
    - *
    - * @param {Array<Array<string>>} emoji Emoji for this page. See
    - *     {@link addEmojiGroup} for more details.
    - * @param {number} index Index of the page in the emojipicker.
    - * @return {goog.ui.emoji.EmojiPalette} the emoji page.
    - * @private
    - */
    -goog.ui.emoji.EmojiPicker.prototype.createEmojiPage_ = function(emoji, index) {
    -  // Safeguard against trying to create the same page twice
    -  if (this.pageLoadStatus_[index]) {
    -    return null;
    -  }
    -
    -  var palette = new goog.ui.emoji.EmojiPalette(emoji,
    -                                               this.urlPrefix_,
    -                                               this.renderer_,
    -                                               this.getDomHelper());
    -  if (!this.manualLoadOfAnimatedEmoji_) {
    -    palette.loadAnimatedEmoji();
    -  }
    -  palette.setSize(this.numCols_, this.numRows_);
    -  palette.setSupportedState(goog.ui.Component.State.FOCUSED, this.focusable_);
    -  palette.createDom();
    -  palette.setParent(this);
    -
    -  this.pageLoadStatus_[index] = true;
    -
    -  return palette;
    -};
    -
    -
    -/**
    - * Returns an array of emoji whose real URLs have been replaced with the
    - * default img URL. Used for delayed loading.
    - *
    - * @param {Array<Array<string>>} emoji Original emoji array.
    - * @return {!Array<!Array<string>>} emoji array with all emoji pointing to the
    - *     default img.
    - * @private
    - */
    -goog.ui.emoji.EmojiPicker.prototype.getPlaceholderEmoji_ = function(emoji) {
    -  var placeholderEmoji = [];
    -
    -  for (var i = 0; i < emoji.length; i++) {
    -    placeholderEmoji.push([this.defaultImgUrl_, emoji[i][1]]);
    -  }
    -
    -  return placeholderEmoji;
    -};
    -
    -
    -/**
    - * Creates an emoji page using placeholder emoji pointing to the default
    - * img instead of the real emoji. Used for delayed loading.
    - *
    - * @param {Array<Array<string>>} emoji Emoji for this page. See
    - *     {@link addEmojiGroup} for more details.
    - * @return {!goog.ui.emoji.EmojiPalette} the emoji page.
    - * @private
    - */
    -goog.ui.emoji.EmojiPicker.prototype.createPlaceholderEmojiPage_ =
    -    function(emoji) {
    -  var placeholderEmoji = this.getPlaceholderEmoji_(emoji);
    -
    -  var palette = new goog.ui.emoji.EmojiPalette(placeholderEmoji,
    -                                               null,  // no url prefix
    -                                               this.renderer_,
    -                                               this.getDomHelper());
    -  palette.setSize(this.numCols_, this.numRows_);
    -  palette.setSupportedState(goog.ui.Component.State.FOCUSED, this.focusable_);
    -  palette.createDom();
    -  palette.setParent(this);
    -
    -  return palette;
    -};
    -
    -
    -/**
    - * EmojiPickers cannot be used to decorate pre-existing html, since the
    - * structure they build is fairly complicated.
    - * @param {Element} element Element to decorate.
    - * @return {boolean} Returns always false.
    - * @override
    - */
    -goog.ui.emoji.EmojiPicker.prototype.canDecorate = function(element) {
    -  return false;
    -};
    -
    -
    -/**
    - * @override
    - * @suppress {deprecated} Using deprecated goog.ui.TabPane.
    - */
    -goog.ui.emoji.EmojiPicker.prototype.enterDocument = function() {
    -  goog.ui.emoji.EmojiPicker.superClass_.enterDocument.call(this);
    -
    -  for (var i = 0; i < this.pages_.length; i++) {
    -    this.pages_[i].enterDocument();
    -    var pageElement = this.pages_[i].getElement();
    -
    -    // Add a new tab to the tabpane if there's more than one group of emoji.
    -    // If there is just one group of emoji, then we simply use the single
    -    // page's element as the content for the picker
    -    if (this.pages_.length > 1) {
    -      // Create a simple default title containg the page number if the title
    -      // was not provided in the emoji group params
    -      var title = this.emoji_[i].title || (i + 1);
    -      this.tabPane_.addPage(new goog.ui.TabPane.TabPage(
    -          pageElement, title, this.getDomHelper()));
    -    } else {
    -      this.getElement().appendChild(pageElement);
    -    }
    -  }
    -
    -  // Initialize listeners. Note that we need to initialize this listener
    -  // after createDom, because addPage causes the goog.ui.TabPane.Events.CHANGE
    -  // event to fire, but we only want the handler (which loads delayed images)
    -  // to run after the picker has been constructed.
    -  if (this.tabPane_) {
    -    this.getHandler().listen(
    -        this.tabPane_, goog.ui.TabPane.Events.CHANGE, this.onPageChanged_);
    -
    -    // Make the tabpane unselectable so that changing tabs doesn't disturb the
    -    // cursor
    -    goog.style.setUnselectable(this.tabPane_.getElement(), true);
    -  }
    -
    -  this.getElement().unselectable = 'on';
    -};
    -
    -
    -/** @override */
    -goog.ui.emoji.EmojiPicker.prototype.exitDocument = function() {
    -  goog.ui.emoji.EmojiPicker.superClass_.exitDocument.call(this);
    -  for (var i = 0; i < this.pages_.length; i++) {
    -    this.pages_[i].exitDocument();
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.emoji.EmojiPicker.prototype.disposeInternal = function() {
    -  goog.ui.emoji.EmojiPicker.superClass_.disposeInternal.call(this);
    -
    -  if (this.tabPane_) {
    -    this.tabPane_.dispose();
    -    this.tabPane_ = null;
    -  }
    -
    -  for (var i = 0; i < this.pages_.length; i++) {
    -    this.pages_[i].dispose();
    -  }
    -  this.pages_.length = 0;
    -};
    -
    -
    -/**
    - * @return {string} CSS class for the root element of EmojiPicker.
    - */
    -goog.ui.emoji.EmojiPicker.prototype.getCssClass = function() {
    -  return goog.getCssName('goog-ui-emojipicker');
    -};
    -
    -
    -/**
    - * Returns the currently selected emoji from this picker. If the picker is
    - * using the URL prefix optimization, allocates a new emoji object with the
    - * full URL. This method is meant to be used by clients of the emojipicker,
    - * e.g., in a listener on goog.ui.component.EventType.ACTION that wants to use
    - * the just-selected emoji.
    - *
    - * @return {goog.ui.emoji.Emoji} The currently selected emoji from this picker.
    - */
    -goog.ui.emoji.EmojiPicker.prototype.getSelectedEmoji = function() {
    -  return this.urlPrefix_ ?
    -      new goog.ui.emoji.Emoji(this.urlPrefix_ + this.selectedEmoji_.getId(),
    -                              this.selectedEmoji_.getId()) :
    -      this.selectedEmoji_;
    -};
    -
    -
    -/**
    - * Returns the number of emoji groups in this picker.
    - *
    - * @return {number} The number of emoji groups in this picker.
    - */
    -goog.ui.emoji.EmojiPicker.prototype.getNumEmojiGroups = function() {
    -  return this.emoji_.length;
    -};
    -
    -
    -/**
    - * Returns a page from the picker. This should be considered protected, and is
    - * ONLY FOR TESTING.
    - *
    - * @param {number} index Index of the page to return.
    - * @return {goog.ui.emoji.EmojiPalette?} the page at the specified index or null
    - *     if none exists.
    - */
    -goog.ui.emoji.EmojiPicker.prototype.getPage = function(index) {
    -  return this.pages_[index];
    -};
    -
    -
    -/**
    - * Returns all the pages from the picker. This should be considered protected,
    - * and is ONLY FOR TESTING.
    - *
    - * @return {Array<goog.ui.emoji.EmojiPalette>?} the pages in the picker or
    - *     null if none exist.
    - */
    -goog.ui.emoji.EmojiPicker.prototype.getPages = function() {
    -  return this.pages_;
    -};
    -
    -
    -/**
    - * Returns the tabpane if this is a multipage picker. This should be considered
    - * protected, and is ONLY FOR TESTING.
    - *
    - * @return {goog.ui.TabPane} the tabpane if it is a multipage picker,
    - *     or null if it does not exist or is a single page picker.
    - */
    -goog.ui.emoji.EmojiPicker.prototype.getTabPane = function() {
    -  return this.tabPane_;
    -};
    -
    -
    -/**
    - * @return {goog.ui.emoji.EmojiPalette} The active page of the emoji picker.
    - * @private
    - */
    -goog.ui.emoji.EmojiPicker.prototype.getActivePage_ = function() {
    -  return this.pages_[this.activePage_];
    -};
    -
    -
    -/**
    - * Handles actions from the EmojiPalettes that this picker contains.
    - *
    - * @param {goog.ui.Component.EventType} e The event object.
    - * @private
    - */
    -goog.ui.emoji.EmojiPicker.prototype.onEmojiPaletteAction_ = function(e) {
    -  this.selectedEmoji_ = this.getActivePage_().getSelectedEmoji();
    -};
    -
    -
    -/**
    - * Handles changes in the active page in the tabpane.
    - *
    - * @param {goog.ui.TabPaneEvent} e The event object.
    - * @private
    - */
    -goog.ui.emoji.EmojiPicker.prototype.onPageChanged_ = function(e) {
    -  var index = /** @type {number} */ (e.page.getIndex());
    -  this.loadPage_(index);
    -  this.activePage_ = index;
    -};
    -
    -
    -/**
    - * Loads a page into the picker if it has not yet been loaded.
    - *
    - * @param {number} index Index of the page to load.
    - * @private
    - * @suppress {deprecated} Using deprecated goog.ui.TabPane.
    - */
    -goog.ui.emoji.EmojiPicker.prototype.loadPage_ = function(index) {
    -  if (index < 0 || index > this.pages_.length) {
    -    throw Error('Index out of bounds');
    -  }
    -
    -  if (!this.pageLoadStatus_[index]) {
    -    var oldPage = this.pages_[index];
    -    this.pages_[index] = this.createEmojiPage_(this.emoji_[index].emoji,
    -                                               index);
    -    this.pages_[index].enterDocument();
    -    var pageElement = this.pages_[index].getElement();
    -    if (this.pages_.length > 1) {
    -      this.tabPane_.removePage(index);
    -      var title = this.emoji_[index].title || (index + 1);
    -      this.tabPane_.addPage(new goog.ui.TabPane.TabPage(
    -          pageElement, title, this.getDomHelper()), index);
    -      this.tabPane_.setSelectedIndex(index);
    -    } else {
    -      var el = this.getElement();
    -      el.appendChild(pageElement);
    -    }
    -    if (oldPage) {
    -      oldPage.dispose();
    -    }
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/emoji/emojipicker_test.html b/src/database/third_party/closure-library/closure/goog/ui/emoji/emojipicker_test.html
    deleted file mode 100644
    index ab59b7ad175..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/emoji/emojipicker_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.emoji.EmojiPicker
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -  goog.require('goog.ui.emoji.EmojiPickerTest');
    -  </script>
    -  <link rel="stylesheet" href="../../demos/css/emojisprite.css" />
    - </head>
    - <body>
    -  <div id="test1">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/emoji/emojipicker_test.js b/src/database/third_party/closure-library/closure/goog/ui/emoji/emojipicker_test.js
    deleted file mode 100644
    index 759c5814d6a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/emoji/emojipicker_test.js
    +++ /dev/null
    @@ -1,910 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.emoji.EmojiPickerTest');
    -goog.setTestOnly('goog.ui.emoji.EmojiPickerTest');
    -
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.style');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.emoji.Emoji');
    -goog.require('goog.ui.emoji.EmojiPicker');
    -goog.require('goog.ui.emoji.SpriteInfo');
    -var handler;
    -
    -function setUp() {
    -  handler = new goog.events.EventHandler();
    -}
    -
    -function tearDown() {
    -  handler.removeAll();
    -}
    -
    -// 26 emoji
    -var emojiGroup1 = [
    -  'Emoji 1',
    -  [
    -   ['../../demos/emoji/200.gif', 'std.200'],
    -   ['../../demos/emoji/201.gif', 'std.201'],
    -   ['../../demos/emoji/202.gif', 'std.202'],
    -   ['../../demos/emoji/203.gif', 'std.203'],
    -   ['../../demos/emoji/204.gif', 'std.204'],
    -   ['../../demos/emoji/200.gif', 'std.200'],
    -   ['../../demos/emoji/201.gif', 'std.201'],
    -   ['../../demos/emoji/202.gif', 'std.202'],
    -   ['../../demos/emoji/203.gif', 'std.203'],
    -   ['../../demos/emoji/204.gif', 'std.204'],
    -   ['../../demos/emoji/200.gif', 'std.200'],
    -   ['../../demos/emoji/201.gif', 'std.201'],
    -   ['../../demos/emoji/202.gif', 'std.202'],
    -   ['../../demos/emoji/203.gif', 'std.203'],
    -   ['../../demos/emoji/204.gif', 'std.204'],
    -   ['../../demos/emoji/200.gif', 'std.200'],
    -   ['../../demos/emoji/201.gif', 'std.201'],
    -   ['../../demos/emoji/202.gif', 'std.202'],
    -   ['../../demos/emoji/203.gif', 'std.203'],
    -   ['../../demos/emoji/204.gif', 'std.204'],
    -   ['../../demos/emoji/200.gif', 'std.200'],
    -   ['../../demos/emoji/201.gif', 'std.201'],
    -   ['../../demos/emoji/202.gif', 'std.202'],
    -   ['../../demos/emoji/203.gif', 'std.203'],
    -   ['../../demos/emoji/204.gif', 'std.204'],
    -   ['../../demos/emoji/200.gif', 'std.200']
    -  ]];
    -
    -// 20 emoji
    -var emojiGroup2 = [
    -  'Emoji 2',
    -  [
    -   ['../../demos/emoji/200.gif', 'std.200'],
    -   ['../../demos/emoji/201.gif', 'std.201'],
    -   ['../../demos/emoji/202.gif', 'std.202'],
    -   ['../../demos/emoji/203.gif', 'std.203'],
    -   ['../../demos/emoji/204.gif', 'std.204'],
    -   ['../../demos/emoji/200.gif', 'std.200'],
    -   ['../../demos/emoji/201.gif', 'std.201'],
    -   ['../../demos/emoji/202.gif', 'std.202'],
    -   ['../../demos/emoji/203.gif', 'std.203'],
    -   ['../../demos/emoji/204.gif', 'std.204'],
    -   ['../../demos/emoji/200.gif', 'std.200'],
    -   ['../../demos/emoji/201.gif', 'std.201'],
    -   ['../../demos/emoji/202.gif', 'std.202'],
    -   ['../../demos/emoji/203.gif', 'std.203'],
    -   ['../../demos/emoji/204.gif', 'std.204'],
    -   ['../../demos/emoji/200.gif', 'std.200'],
    -   ['../../demos/emoji/201.gif', 'std.201'],
    -   ['../../demos/emoji/202.gif', 'std.202'],
    -   ['../../demos/emoji/203.gif', 'std.203'],
    -   ['../../demos/emoji/204.gif', 'std.204']
    -  ]];
    -
    -// 20 emoji
    -var emojiGroup3 = [
    -  'Emoji 3',
    -  [
    -   ['../../demos/emoji/200.gif', 'std.200'],
    -   ['../../demos/emoji/201.gif', 'std.201'],
    -   ['../../demos/emoji/202.gif', 'std.202'],
    -   ['../../demos/emoji/203.gif', 'std.203'],
    -   ['../../demos/emoji/204.gif', 'std.204'],
    -   ['../../demos/emoji/200.gif', 'std.200'],
    -   ['../../demos/emoji/201.gif', 'std.201'],
    -   ['../../demos/emoji/202.gif', 'std.202'],
    -   ['../../demos/emoji/203.gif', 'std.203'],
    -   ['../../demos/emoji/204.gif', 'std.204'],
    -   ['../../demos/emoji/200.gif', 'std.200'],
    -   ['../../demos/emoji/201.gif', 'std.201'],
    -   ['../../demos/emoji/202.gif', 'std.202'],
    -   ['../../demos/emoji/203.gif', 'std.203'],
    -   ['../../demos/emoji/204.gif', 'std.204'],
    -   ['../../demos/emoji/200.gif', 'std.200'],
    -   ['../../demos/emoji/201.gif', 'std.201'],
    -   ['../../demos/emoji/202.gif', 'std.202'],
    -   ['../../demos/emoji/203.gif', 'std.203'],
    -   ['../../demos/emoji/204.gif', 'std.204']
    -  ]];
    -
    -var sprite = '../../demos/emoji/sprite.png';
    -var sprite2 = '../../demos/emoji/sprite2.png';
    -
    -
    -/**
    - * Creates a SpriteInfo object with the specified properties. If the image is
    - * sprited via CSS, then only the first parameter needs a value. If the image
    - * is sprited via metadata, then the first parameter should be left null.
    - *
    - * @param {?string} cssClass CSS class to properly display the sprited image.
    - * @param {string=} opt_url Url of the sprite image.
    - * @param {number=} opt_width Width of the image being sprited.
    - * @param {number=} opt_height Height of the image being sprited.
    - * @param {number=} opt_xOffset Positive x offset of the image being sprited
    - *     within the sprite.
    - * @param {number=} opt_yOffset Positive y offset of the image being sprited
    - *     within the sprite.
    - * @param {boolean=} opt_animated Whether the sprite info is for an animated
    - *     emoji.
    - */
    -function si(cssClass, opt_url, opt_width, opt_height, opt_xOffset,
    -            opt_yOffset, opt_animated) {
    -  return new goog.ui.emoji.SpriteInfo(cssClass, opt_url, opt_width,
    -      opt_height, opt_xOffset, opt_yOffset, opt_animated);
    -}
    -
    -// Contains a mix of sprited emoji via css, sprited emoji via metadata, and
    -// non-sprited emoji
    -var spritedEmoji1 = [
    -  'Emoji 1',
    -  [
    -   ['../../demos/emoji/200.gif', 'std.200', si('SPRITE_200')],
    -   ['../../demos/emoji/201.gif', 'std.201', si('SPRITE_201')],
    -   ['../../demos/emoji/202.gif', 'std.202', si('SPRITE_202')],
    -   ['../../demos/emoji/203.gif', 'std.203', si('SPRITE_203')],
    -   ['../../demos/emoji/204.gif', 'std.204', si('SPRITE_204')],
    -   ['../../demos/emoji/200.gif', 'std.200', si('SPRITE_200')],
    -   ['../../demos/emoji/201.gif', 'std.201', si('SPRITE_201')],
    -   ['../../demos/emoji/202.gif', 'std.202', si('SPRITE_202')],
    -   ['../../demos/emoji/203.gif', 'std.203', si('SPRITE_203')],
    -   ['../../demos/emoji/2BE.gif', 'std.2BE',
    -    si(null, sprite, 18, 18, 36, 54)],
    -   ['../../demos/emoji/2BF.gif', 'std.2BF',
    -    si(null, sprite, 18, 18, 0, 126)],
    -   ['../../demos/emoji/2C0.gif', 'std.2C0',
    -    si(null, sprite, 18, 18, 18, 305)],
    -   ['../../demos/emoji/2C1.gif', 'std.2C1',
    -    si(null, sprite, 18, 18, 0, 287)],
    -   ['../../demos/emoji/2C2.gif', 'std.2C2',
    -    si(null, sprite, 18, 18, 18, 126)],
    -   ['../../demos/emoji/2C3.gif', 'std.2C3',
    -    si(null, sprite, 18, 18, 36, 234)],
    -   ['../../demos/emoji/2C4.gif', 'std.2C4',
    -    si(null, sprite, 18, 18, 36, 72)],
    -   ['../../demos/emoji/2C5.gif', 'std.2C5',
    -    si(null, sprite, 18, 18, 54, 54)],
    -   ['../../demos/emoji/200.gif', 'std.200'],
    -   ['../../demos/emoji/201.gif', 'std.201'],
    -   ['../../demos/emoji/202.gif', 'std.202'],
    -   ['../../demos/emoji/203.gif', 'std.203'],
    -   ['../../demos/emoji/204.gif', 'std.204'],
    -   ['../../demos/emoji/200.gif', 'std.200'],
    -   ['../../demos/emoji/201.gif', 'std.201'],
    -   ['../../demos/emoji/202.gif', 'std.202'],
    -   ['../../demos/emoji/203.gif', 'std.203']
    -  ]];
    -
    -// This group contains a mix of sprited emoji via css, sprited emoji via
    -// metadata, and non-sprited emoji.
    -var spritedEmoji2 = [
    -  'Emoji 1',
    -  [
    -   ['../../demos/emoji/200.gif', 'std.200', si('SPRITE_200')],
    -   ['../../demos/emoji/201.gif', 'std.201', si('SPRITE_201')],
    -   ['../../demos/emoji/202.gif', 'std.202', si('SPRITE_202')],
    -   ['../../demos/emoji/203.gif', 'std.203', si('SPRITE_203')],
    -   ['../../demos/emoji/204.gif', 'std.204', si('SPRITE_204')],
    -   ['../../demos/emoji/200.gif', 'std.200', si('SPRITE_200')],
    -   ['../../demos/emoji/201.gif', 'std.201', si('SPRITE_201')],
    -   ['../../demos/emoji/202.gif', 'std.202', si('SPRITE_202')],
    -   ['../../demos/emoji/203.gif', 'std.203', si('SPRITE_203')],
    -   ['../../demos/emoji/2BE.gif', 'std.2BE',
    -    si(null, sprite, 18, 18, 36, 54)],
    -   ['../../demos/emoji/2BF.gif', 'std.2BF',
    -    si(null, sprite, 18, 18, 0, 126)],
    -   ['../../demos/emoji/2C0.gif', 'std.2C0',
    -    si(null, sprite, 18, 18, 18, 305)],
    -   ['../../demos/emoji/2C1.gif', 'std.2C1',
    -    si(null, sprite, 18, 18, 0, 287)],
    -   ['../../demos/emoji/2C2.gif', 'std.2C2',
    -    si(null, sprite, 18, 18, 18, 126)],
    -   ['../../demos/emoji/2C3.gif', 'std.2C3',
    -    si(null, sprite, 18, 18, 36, 234)],
    -   ['../../demos/emoji/2C4.gif', 'std.2C4',
    -    si(null, sprite, 18, 18, 36, 72)],
    -   ['../../demos/emoji/2C5.gif', 'std.2C5',
    -    si(null, sprite, 18, 18, 54, 54)],
    -   ['../../demos/emoji/2C6.gif', 'std.2C6'],
    -   ['../../demos/emoji/2C7.gif', 'std.2C7'],
    -   ['../../demos/emoji/2C8.gif', 'std.2C8'],
    -   ['../../demos/emoji/2C9.gif', 'std.2C9'],
    -   ['../../demos/emoji/2CA.gif', 'std.2CA',
    -    si(null, sprite2, 18, 20, 36, 72, 1)],
    -   ['../../demos/emoji/2E3.gif', 'std.2E3',
    -    si(null, sprite2, 18, 18, 0, 0, 1)],
    -   ['../../demos/emoji/2EF.gif', 'std.2EF',
    -    si(null, sprite2, 18, 20, 0, 300, 1)],
    -   ['../../demos/emoji/2F1.gif', 'std.2F1',
    -    si(null, sprite2, 18, 18, 0, 320, 1)]
    -  ]];
    -
    -var emojiGroups = [emojiGroup1, emojiGroup2, emojiGroup3];
    -
    -function testConstructAndRenderOnePageEmojiPicker() {
    -  var picker = new goog.ui.emoji.EmojiPicker('../../demos/emoji/none.gif');
    -  picker.addEmojiGroup(emojiGroup1[0], emojiGroup1[1]);
    -  picker.render();
    -  picker.dispose();
    -}
    -
    -function testConstructAndRenderMultiPageEmojiPicker() {
    -  var picker = new goog.ui.emoji.EmojiPicker('../../demos/emoji/none.gif');
    -  picker.addEmojiGroup(emojiGroup1[0], emojiGroup1[1]);
    -  picker.addEmojiGroup(emojiGroup2[0], emojiGroup2[1]);
    -  picker.addEmojiGroup(emojiGroup3[0], emojiGroup3[1]);
    -  picker.render();
    -  picker.dispose();
    -}
    -
    -function testExitDocumentCleansUpProperlyForSinglePageEmojiPicker() {
    -  var picker = new goog.ui.emoji.EmojiPicker('../../demos/emoji/none.gif');
    -  picker.addEmojiGroup(emojiGroup1[0], emojiGroup1[1]);
    -  picker.render();
    -  picker.enterDocument();
    -  picker.exitDocument();
    -  picker.dispose();
    -}
    -
    -function testExitDocumentCleansUpProperlyForMultiPageEmojiPicker() {
    -  var picker = new goog.ui.emoji.EmojiPicker('../../demos/emoji/none.gif');
    -  picker.addEmojiGroup(emojiGroup1[0], emojiGroup1[1]);
    -  picker.addEmojiGroup(emojiGroup2[0], emojiGroup2[1]);
    -  picker.render();
    -  picker.enterDocument();
    -  picker.exitDocument();
    -  picker.dispose();
    -}
    -
    -function testNumGroups() {
    -  var picker = new goog.ui.emoji.EmojiPicker('../../demos/emoji/none.gif');
    -
    -  for (var i = 0; i < emojiGroups.length; i++) {
    -    picker.addEmojiGroup(emojiGroups[i][0], emojiGroups[i][1]);
    -  }
    -
    -  assertTrue(picker.getNumEmojiGroups() == emojiGroups.length);
    -}
    -
    -function testAdjustNumRowsIfNecessaryIsCorrect() {
    -  var picker = new goog.ui.emoji.EmojiPicker('../../demos/emoji/none.gif');
    -  picker.addEmojiGroup(emojiGroup1[0], emojiGroup1[1]);
    -  picker.setAutoSizeByColumnCount(true);
    -  picker.setNumColumns(5);
    -  assertEquals(5, picker.getNumColumns());
    -  assertEquals(goog.ui.emoji.EmojiPicker.DEFAULT_NUM_ROWS, picker.getNumRows());
    -
    -  picker.adjustNumRowsIfNecessary_();
    -
    -  // The emojiGroup has 26 emoji. ceil(26/5) should give 6 rows.
    -  assertEquals(6, picker.getNumRows());
    -
    -  // Change col count to 10, should give 3 rows.
    -  picker.setNumColumns(10);
    -  picker.adjustNumRowsIfNecessary_();
    -  assertEquals(3, picker.getNumRows());
    -
    -  // Add another gruop, with 20 emoji. Deliberately set the number of rows too
    -  // low. It should adjust it to three to accommodate the emoji in the first
    -  // group.
    -  picker.addEmojiGroup(emojiGroup2[0], emojiGroup2[1]);
    -  picker.setNumColumns(10);
    -  picker.setNumRows(2);
    -  picker.adjustNumRowsIfNecessary_();
    -  assertEquals(3, picker.getNumRows());
    -}
    -
    -
    -/**
    - * Helper for testDelayedLoad. Returns true if the two paths end with the same
    - * file.
    - *
    - * E.g., ('../../cool.gif', 'file:///home/usr/somewhere/cool.gif') --> true
    - *
    - * @param {string} path1 First url
    - * @param {string} path2 Second url
    - */
    -function checkPathsEndWithSameFile(path1, path2) {
    -  var pieces1 = path1.split('/');
    -  var file1 = pieces1[pieces1.length - 1];
    -  var pieces2 = path2.split('/');
    -  var file2 = pieces2[pieces2.length - 1];
    -
    -  return file1 == file2;
    -}
    -
    -
    -/**
    - * Gets the emoji URL from a palette element. Palette elements are divs or
    - * imgs wrapped in an outer div. The returns the background-image if it's a div,
    - * or the src attribute if it's an image.
    - *
    - * @param {Element} element Element to get the image url for
    - * @return {string}
    - */
    -function getImageUrl(element) {
    -  element = element.firstChild;  // get the wrapped element
    -  if (element.tagName == 'IMG') {
    -    return element.src;
    -  } else {
    -    var url = goog.style.getStyle(element, 'background-image');
    -    url = url.replace(/url\(/, '');
    -    url = url.replace(/\)/, '');
    -    return url;
    -  }
    -}
    -
    -
    -/**
    - * Checks that the content of an emojipicker page is all images pointing to
    - * the default img.
    - *
    - * @param {goog.ui.emoji.EmojiPalette} page The page of the picker to check
    - * @param {string} defaultImgUrl The url of the default img
    - */
    -function checkContentIsDefaultImg(page, defaultImgUrl) {
    -  var content = page.getContent();
    -
    -  for (var i = 0; i < content.length; i++) {
    -    var url = getImageUrl(content[i]);
    -    assertTrue('img src should be ' + defaultImgUrl + ' but is ' +
    -               url,
    -               checkPathsEndWithSameFile(url, defaultImgUrl));
    -  }
    -}
    -
    -
    -/**
    - * Checks that the content of an emojipicker page is the specified emoji and
    - * the default img after the emoji are all used.
    - *
    - * @param {goog.ui.emoji.EmojiPalette} page The page of the picker to check
    - * @param {Array<Array<string>>} emojiList List of emoji that should be in the
    - *     palette
    - * @param {string} defaultImgUrl The url of the default img
    - */
    -function checkContentIsEmojiImages(page, emojiList, defaultImg) {
    -  var content = page.getContent();
    -
    -  for (var i = 0; i < content.length; i++) {
    -    var url = getImageUrl(content[i]);
    -    if (i < emojiList.length) {
    -      assertTrue('Paths should end with the same file: ' +
    -                 url + ', ' + emojiList[i][0],
    -                 checkPathsEndWithSameFile(url, emojiList[i][0]));
    -    } else {
    -      assertTrue('Paths should end with the same file: ' +
    -                 url + ', ' + defaultImg,
    -                 checkPathsEndWithSameFile(url, defaultImg));
    -    }
    -  }
    -}
    -
    -
    -function testNonDelayedLoadPaletteCreationForSinglePagePicker() {
    -  var defaultImg = '../../demos/emoji/none.gif';
    -  var picker = new goog.ui.emoji.EmojiPicker(defaultImg);
    -  picker.setDelayedLoad(false);
    -  picker.addEmojiGroup(emojiGroup1[0], emojiGroup1[1]);
    -  picker.render();
    -
    -  var page = picker.getPage(0);
    -  assertTrue('Page should be in the document but is not', page.isInDocument());
    -
    -  // The content should be the actual emoji images now, with the remainder set
    -  // to the default img
    -  checkContentIsEmojiImages(page, emojiGroup1[1], defaultImg);
    -
    -  picker.dispose();
    -}
    -
    -
    -function testNonDelayedLoadPaletteCreationForMultiPagePicker() {
    -  var defaultImg = '../../demos/emoji/none.gif';
    -  var picker = new goog.ui.emoji.EmojiPicker(defaultImg);
    -  picker.setDelayedLoad(false);
    -
    -  for (var i = 0; i < emojiGroups.length; i++) {
    -    picker.addEmojiGroup(emojiGroups[i][0], emojiGroups[i][1]);
    -  }
    -
    -  picker.render();
    -
    -  for (var i = 0; i < emojiGroups.length; i++) {
    -    var page = picker.getPage(i);
    -    assertTrue('Page ' + i + ' should be in the document but is not',
    -               page.isInDocument());
    -    checkContentIsEmojiImages(page, emojiGroups[i][1], defaultImg);
    -  }
    -
    -  picker.dispose();
    -}
    -
    -
    -function testDelayedLoadPaletteCreationForSinglePagePicker() {
    -  var defaultImg = '../../demos/emoji/none.gif';
    -  var picker = new goog.ui.emoji.EmojiPicker(defaultImg);
    -  picker.setDelayedLoad(true);
    -  picker.addEmojiGroup(emojiGroup1[0], emojiGroup1[1]);
    -  picker.render();
    -
    -  // At this point the picker should have pages filled with the default img
    -  checkContentIsDefaultImg(picker.getPage(0), defaultImg);
    -
    -  // Now load the images
    -  picker.loadImages();
    -
    -  var page = picker.getPage(0);
    -  assertTrue('Page should be in the document but is not', page.isInDocument());
    -
    -  // The content should be the actual emoji images now, with the remainder set
    -  // to the default img
    -  checkContentIsEmojiImages(page, emojiGroup1[1], defaultImg);
    -
    -  picker.dispose();
    -}
    -
    -
    -function testGetSelectedEmoji() {
    -  var defaultImg = '../../demos/emoji/none.gif';
    -  var picker = new goog.ui.emoji.EmojiPicker(defaultImg);
    -  picker.setDelayedLoad(false);
    -  picker.addEmojiGroup(emojiGroup1[0], emojiGroup1[1]);
    -  picker.render();
    -
    -  var palette = picker.getPage(0);
    -
    -  // No emoji should be selected yet
    -  assertUndefined(palette.getSelectedEmoji());
    -
    -  // Artificially select the first emoji
    -  palette.setSelectedIndex(0);
    -
    -  // Now we should get the first emoji back. See emojiGroup1 above.
    -  var emoji = palette.getSelectedEmoji();
    -  assertEquals(emoji.getId(), 'std.200');
    -  assertEquals(emoji.getUrl(), '../../demos/emoji/200.gif');
    -
    -  picker.dispose();
    -}
    -
    -
    -function testGetSelectedEmoji_click() {
    -  var defaultImg = '../../demos/emoji/none.gif';
    -  var picker = new goog.ui.emoji.EmojiPicker(defaultImg);
    -  picker.setDelayedLoad(false);
    -  picker.addEmojiGroup(emojiGroup1[0], emojiGroup1[1]);
    -  picker.render();
    -
    -  var palette = picker.getPage(0);
    -  // Artificially select the an emoji
    -  palette.setSelectedIndex(2);
    -  var element = palette.getSelectedItem();
    -  palette.setSelectedIndex(0);  // Select a different emoji.
    -
    -  var eventSent;
    -  handler.listen(picker, goog.ui.Component.EventType.ACTION,
    -      function(e) {
    -        eventSent = e;
    -      });
    -  goog.testing.events.fireClickSequence(element, undefined, undefined,
    -      { shiftKey: false });
    -
    -  // Now we should get the first emoji back. See emojiGroup1 above.
    -  var emoji = picker.getSelectedEmoji();
    -  assertEquals(emoji.getId(), 'std.202');
    -  assertEquals(emoji.getUrl(), '../../demos/emoji/202.gif');
    -  assertFalse(eventSent.shiftKey);
    -
    -  picker.dispose();
    -}
    -
    -
    -function testGetSelectedEmoji_shiftClick() {
    -  var defaultImg = '../../demos/emoji/none.gif';
    -  var picker = new goog.ui.emoji.EmojiPicker(defaultImg);
    -  picker.setDelayedLoad(false);
    -  picker.addEmojiGroup(emojiGroup1[0], emojiGroup1[1]);
    -  picker.render();
    -
    -  var palette = picker.getPage(0);
    -  // Artificially select the an emoji
    -  palette.setSelectedIndex(3);
    -  var element = palette.getSelectedItem();
    -  palette.setSelectedIndex(0);  // Select a different emoji.
    -
    -  var eventSent;
    -  handler.listen(picker, goog.ui.Component.EventType.ACTION,
    -      function(e) {
    -        eventSent = e;
    -      });
    -  goog.testing.events.fireClickSequence(element, undefined, undefined,
    -      { shiftKey: true });
    -
    -  // Now we should get the first emoji back. See emojiGroup1 above.
    -  var emoji = picker.getSelectedEmoji();
    -  assertEquals(emoji.getId(), 'std.203');
    -  assertEquals(emoji.getUrl(), '../../demos/emoji/203.gif');
    -  assertTrue(eventSent.shiftKey);
    -
    -  picker.dispose();
    -}
    -
    -
    -/**
    - * Checks and verifies the structure of a non-progressively-rendered
    - * emojipicker.
    - *
    - * @param {goog.ui.emoji.EmojiPalette} palette Emoji palette to check.
    - * @param {Array<Array<string>>} emoji Emoji that should be in the palette.
    - */
    -function checkStructureForNonProgressivePicker(palette, emoji) {
    -  // We can hackily check the items by selecting an item and then getting the
    -  // selected item.
    -  for (var i = 0; i < emoji[1].length; i++) {
    -    palette.setSelectedIndex(i);
    -    var emojiInfo = emoji[1][i];
    -    var cell = palette.getSelectedItem();
    -    var inner = /** @type {Element} */ (cell.firstChild);
    -
    -    // Check that the cell is a div wrapped around something else, and that the
    -    // outer div contains the goomoji attribute
    -    assertEquals('The palette item should be a div wrapped around something',
    -        cell.tagName, 'DIV');
    -    assertNotNull('The outer div is not wrapped around another element', inner);
    -    assertEquals('The palette item should have the goomoji attribute',
    -        cell.getAttribute(goog.ui.emoji.Emoji.ATTRIBUTE), emojiInfo[1]);
    -
    -    // Now check the contents of the cells
    -    var spriteInfo = emojiInfo[2];
    -    if (spriteInfo) {
    -      assertEquals(inner.tagName, 'DIV');
    -      var cssClass = spriteInfo.getCssClass();
    -      if (cssClass) {
    -        assertTrue('Sprite should have its CSS class set',
    -            goog.dom.classlist.contains(inner, cssClass));
    -      } else {
    -        checkPathsEndWithSameFile(
    -            goog.style.getStyle(inner, 'background-image'),
    -            spriteInfo.getUrl());
    -        assertEquals(spriteInfo.getWidthCssValue(),
    -            goog.style.getStyle(inner, 'width'));
    -        assertEquals(spriteInfo.getHeightCssValue(),
    -            goog.style.getStyle(inner, 'height'));
    -        assertEquals((spriteInfo.getXOffsetCssValue() + ' ' +
    -                      spriteInfo.getYOffsetCssValue()).replace(/px/g, '').
    -            replace(/pt/g, ''),
    -            goog.style.getStyle(inner,
    -                'background-position').replace(/px/g, '').
    -                replace(/pt/g, ''));
    -      }
    -    } else {
    -      // A non-sprited emoji is just an img
    -      assertEquals(inner.tagName, 'IMG');
    -      checkPathsEndWithSameFile(inner.src, emojiInfo[0]);
    -    }
    -  }
    -}
    -
    -
    -/**
    - * Checks and verifies the structure of a progressively-rendered emojipicker.
    - *
    - * @param {goog.ui.emoji.EmojiPalette} palette Emoji palette to check.
    - * @param {Array<Array<string>>} emoji Emoji that should be in the palette.
    - */
    -function checkStructureForProgressivePicker(palette, emoji) {
    -  // We can hackily check the items by selecting an item and then getting the
    -  // selected item.
    -  for (var i = 0; i < emoji[1].length; i++) {
    -    palette.setSelectedIndex(i);
    -    var emojiInfo = emoji[1][i];
    -    var cell = palette.getSelectedItem();
    -    var inner = /** @type {Element} */ (cell.firstChild);
    -
    -    // Check that the cell is a div wrapped around something else, and that the
    -    // outer div contains the goomoji attribute
    -    assertEquals('The palette item should be a div wrapped around something',
    -        cell.tagName, 'DIV');
    -    assertNotNull('The outer div is not wrapped around another element', inner);
    -    assertEquals('The palette item should have the goomoji attribute',
    -        cell.getAttribute(goog.ui.emoji.Emoji.ATTRIBUTE), emojiInfo[1]);
    -
    -    // Now check the contents of the cells
    -    var spriteInfo = emojiInfo[2];
    -    if (spriteInfo) {
    -      var cssClass = spriteInfo.getCssClass();
    -      if (cssClass) {
    -        assertEquals('DIV', inner.tagName);
    -        assertTrue('Sprite should have its CSS class set',
    -            goog.dom.classlist.contains(inner, cssClass));
    -      } else {
    -        // There's an inner div wrapping an img tag
    -        assertEquals('DIV', inner.tagName);
    -        var img = inner.firstChild;
    -        assertNotNull('Div should be wrapping something', img);
    -        assertEquals('IMG', img.tagName);
    -        checkPathsEndWithSameFile(img.src, spriteInfo.getUrl());
    -        assertEquals(spriteInfo.getWidthCssValue(),
    -                     goog.style.getStyle(inner, 'width'));
    -        assertEquals(spriteInfo.getHeightCssValue(),
    -                     goog.style.getStyle(inner, 'height'));
    -        assertEquals(spriteInfo.getXOffsetCssValue().replace(/px/, '').
    -            replace(/pt/, ''),
    -            goog.style.getStyle(img, 'left').replace(/px/, '').
    -                replace(/pt/, ''));
    -        assertEquals(spriteInfo.getYOffsetCssValue().replace(/px/, '').
    -            replace(/pt/, ''),
    -            goog.style.getStyle(img, 'top').replace(/px/, '').
    -                replace(/pt/, ''));
    -      }
    -    } else {
    -      // A non-sprited emoji is just an img
    -      assertEquals(inner.tagName, 'IMG');
    -      checkPathsEndWithSameFile(inner.src, emojiInfo[0]);
    -    }
    -  }
    -}
    -
    -
    -/**
    - * Checks and verifies the structure of a non-progressive fast-loading picker
    - * after the animated emoji have loaded.
    - *
    - * @param {goog.ui.emoji.EmojiPalette} palette Emoji palette to check.
    - * @param {Array<Array<string>>} emoji Emoji that should be in the palette.
    - */
    -function checkPostLoadStructureForFastLoadNonProgressivePicker(palette, emoji) {
    -  for (var i = 0; i < emoji[1].length; i++) {
    -    palette.setSelectedIndex(i);
    -    var emojiInfo = emoji[1][i];
    -    var cell = palette.getSelectedItem();
    -    var inner = /** @type {Element} */ (cell.firstChild);
    -
    -    // Check that the cell is a div wrapped around something else, and that the
    -    // outer div contains the goomoji attribute
    -    assertEquals('The palette item should be a div wrapped around something',
    -        cell.tagName, 'DIV');
    -    assertNotNull('The outer div is not wrapped around another element', inner);
    -    assertEquals('The palette item should have the goomoji attribute',
    -        cell.getAttribute(goog.ui.emoji.Emoji.ATTRIBUTE), emojiInfo[1]);
    -
    -    // Now check the contents of the cells
    -    var url = emojiInfo[0];   // url of the animated emoji
    -    var spriteInfo = emojiInfo[2];
    -    if (spriteInfo) {
    -      assertEquals(inner.tagName, 'DIV');
    -      if (spriteInfo.isAnimated()) {
    -        var img = new Image();
    -        img.src = url;
    -        checkPathsEndWithSameFile(
    -            goog.style.getStyle(inner, 'background-image'),
    -            url);
    -        assertEquals(String(img.width), goog.style.getStyle(inner, 'width').
    -            replace(/px/g, '').replace(/pt/g, ''));
    -        assertEquals(String(img.height), goog.style.getStyle(inner, 'height').
    -            replace(/px/g, '').replace(/pt/g, ''));
    -        assertEquals('0 0', goog.style.getStyle(inner,
    -            'background-position').replace(/px/g, '').
    -            replace(/pt/g, ''));
    -      } else {
    -        var cssClass = spriteInfo.getCssClass();
    -        if (cssClass) {
    -          assertTrue('Sprite should have its CSS class set',
    -              goog.dom.classlist.contains(inner, cssClass));
    -        } else {
    -          checkPathsEndWithSameFile(
    -              goog.style.getStyle(inner, 'background-image'),
    -              spriteInfo.getUrl());
    -          assertEquals(spriteInfo.getWidthCssValue(),
    -              goog.style.getStyle(inner, 'width'));
    -          assertEquals(spriteInfo.getHeightCssValue(),
    -              goog.style.getStyle(inner, 'height'));
    -          assertEquals((spriteInfo.getXOffsetCssValue() + ' ' +
    -                        spriteInfo.getYOffsetCssValue()).replace(/px/g, '').
    -              replace(/pt/g, ''),
    -              goog.style.getStyle(inner,
    -                  'background-position').replace(/px/g, '').
    -                  replace(/pt/g, ''));
    -        }
    -      }
    -    } else {
    -      // A non-sprited emoji is just an img
    -      assertEquals(inner.tagName, 'IMG');
    -      checkPathsEndWithSameFile(inner.src, emojiInfo[0]);
    -    }
    -  }
    -}
    -
    -
    -/**
    - * Checks and verifies the structure of a progressive fast-loading picker
    - * after the animated emoji have loaded.
    - *
    - * @param {goog.ui.emoji.EmojiPalette} palette Emoji palette to check.
    - * @param {Array<Array<string>>} emoji Emoji that should be in the palette.
    - */
    -function checkPostLoadStructureForFastLoadProgressivePicker(palette, emoji) {
    -  for (var i = 0; i < emoji[1].length; i++) {
    -    palette.setSelectedIndex(i);
    -    var emojiInfo = emoji[1][i];
    -    var cell = palette.getSelectedItem();
    -    var inner = /** @type {Element} */ (cell.firstChild);
    -
    -    // Check that the cell is a div wrapped around something else, and that the
    -    // outer div contains the goomoji attribute
    -    assertEquals('The palette item should be a div wrapped around something',
    -        cell.tagName, 'DIV');
    -    assertNotNull('The outer div is not wrapped around another element', inner);
    -    assertEquals('The palette item should have the goomoji attribute',
    -        cell.getAttribute(goog.ui.emoji.Emoji.ATTRIBUTE), emojiInfo[1]);
    -
    -    // Now check the contents of the cells
    -    var url = emojiInfo[0];  // url of the animated emoji
    -    var spriteInfo = emojiInfo[2];
    -    if (spriteInfo) {
    -      if (spriteInfo.isAnimated()) {
    -        var testImg = new Image();
    -        testImg.src = url;
    -        var img = inner.firstChild;
    -        checkPathsEndWithSameFile(img.src, url);
    -        assertEquals(testImg.width, img.width);
    -        assertEquals(testImg.height, img.height);
    -        assertEquals('0', goog.style.getStyle(img, 'left').replace(/px/g, '').
    -            replace(/pt/g, ''));
    -        assertEquals('0', goog.style.getStyle(img, 'top').replace(/px/g, '').
    -            replace(/pt/g, ''));
    -      } else {
    -        var cssClass = spriteInfo.getCssClass();
    -        if (cssClass) {
    -          assertEquals('DIV', inner.tagName);
    -          assertTrue('Sprite should have its CSS class set',
    -              goog.dom.classlist.contains(inner, cssClass));
    -        } else {
    -          // There's an inner div wrapping an img tag
    -          assertEquals('DIV', inner.tagName);
    -          var img = inner.firstChild;
    -          assertNotNull('Div should be wrapping something', img);
    -          assertEquals('IMG', img.tagName);
    -          checkPathsEndWithSameFile(img.src, spriteInfo.getUrl());
    -          assertEquals(spriteInfo.getWidthCssValue(),
    -              goog.style.getStyle(inner, 'width'));
    -          assertEquals(spriteInfo.getHeightCssValue(),
    -              goog.style.getStyle(inner, 'height'));
    -          assertEquals(spriteInfo.getXOffsetCssValue().replace(/px/, '').
    -              replace(/pt/, ''),
    -              goog.style.getStyle(img, 'left').replace(/px/, '').
    -                  replace(/pt/, ''));
    -          assertEquals(spriteInfo.getYOffsetCssValue().replace(/px/, '').
    -              replace(/pt/, ''),
    -              goog.style.getStyle(img, 'top').replace(/px/, '').
    -                  replace(/pt/, ''));
    -        }
    -      }
    -    } else {
    -      // A non-sprited emoji is just an img
    -      assertEquals(inner.tagName, 'IMG');
    -      checkPathsEndWithSameFile(inner.src, emojiInfo[0]);
    -    }
    -  }
    -}
    -
    -
    -function testPreLoadCellConstructionForFastLoadingNonProgressive() {
    -  var defaultImg = '../../demos/emoji/none.gif';
    -  var picker = new goog.ui.emoji.EmojiPicker(defaultImg);
    -  picker.setDelayedLoad(false);
    -  picker.setManualLoadOfAnimatedEmoji(true);
    -  picker.setProgressiveRender(false);
    -  picker.addEmojiGroup(spritedEmoji2[0], spritedEmoji2[1]);
    -  picker.render();
    -
    -  var palette = picker.getPage(0);
    -
    -  checkStructureForNonProgressivePicker(palette, spritedEmoji2);
    -
    -  picker.dispose();
    -}
    -
    -
    -function testPreLoadCellConstructionForFastLoadingProgressive() {
    -  var defaultImg = '../../demos/emoji/none.gif';
    -  var picker = new goog.ui.emoji.EmojiPicker(defaultImg);
    -  picker.setDelayedLoad(false);
    -  picker.setManualLoadOfAnimatedEmoji(true);
    -  picker.setProgressiveRender(true);
    -  picker.addEmojiGroup(spritedEmoji2[0], spritedEmoji2[1]);
    -  picker.render();
    -
    -  var palette = picker.getPage(0);
    -
    -  checkStructureForProgressivePicker(palette, spritedEmoji2);
    -
    -  picker.dispose();
    -}
    -
    -
    -function testCellConstructionForNonProgressiveRenderingSpriting() {
    -  var defaultImg = '../../demos/emoji/none.gif';
    -  var picker = new goog.ui.emoji.EmojiPicker(defaultImg);
    -  picker.setDelayedLoad(false);
    -  picker.addEmojiGroup(spritedEmoji1[0], spritedEmoji1[1]);
    -  picker.render();
    -
    -  var palette = picker.getPage(0);
    -
    -  checkStructureForNonProgressivePicker(palette, spritedEmoji1);
    -  picker.dispose();
    -}
    -
    -
    -function testCellConstructionForProgressiveRenderingSpriting() {
    -  var defaultImg = '../../demos/emoji/none.gif';
    -  var picker = new goog.ui.emoji.EmojiPicker(defaultImg);
    -  picker.setDelayedLoad(false);
    -  picker.setProgressiveRender(true);
    -  picker.addEmojiGroup(spritedEmoji1[0], spritedEmoji1[1]);
    -  picker.render();
    -
    -  var palette = picker.getPage(0);
    -
    -  checkStructureForProgressivePicker(palette, spritedEmoji1);
    -
    -  picker.dispose();
    -}
    -
    -
    -function testDelayedLoadPaletteCreationForMultiPagePicker() {
    -  var defaultImg = '../../demos/emoji/none.gif';
    -  var picker = new goog.ui.emoji.EmojiPicker(defaultImg);
    -  picker.setDelayedLoad(true);
    -
    -  for (var i = 0; i < emojiGroups.length; i++) {
    -    picker.addEmojiGroup(emojiGroups[i][0], emojiGroups[i][1]);
    -  }
    -
    -  picker.render();
    -
    -  // At this point the picker should have pages filled with the default img
    -  for (var i = 0; i < emojiGroups.length; i++) {
    -    checkContentIsDefaultImg(picker.getPage(i), defaultImg);
    -  }
    -
    -  // Now load the images
    -  picker.loadImages();
    -
    -  // The first page should be loaded
    -  var page = picker.getPage(0);
    -  assertTrue('Page ' + i + ' should be in the document but is not',
    -             page.isInDocument());
    -  checkContentIsEmojiImages(page, emojiGroups[0][1], defaultImg);
    -
    -  // The other pages should all be filled with the default img since they are
    -  // lazily loaded
    -  for (var i = 1; i < 3; i++) {
    -    checkContentIsDefaultImg(picker.getPage(i), defaultImg);
    -  }
    -
    -  // Activate the other two pages so that their images get loaded, and check
    -  // that they're now loaded correctly
    -  var tabPane = picker.getTabPane();
    -
    -  for (var i = 1; i < 3; i++) {
    -    tabPane.setSelectedIndex(i);
    -    page = picker.getPage(i);
    -    assertTrue(page.isInDocument());
    -    checkContentIsEmojiImages(page, emojiGroups[i][1], defaultImg);
    -  }
    -
    -  picker.dispose();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/emoji/fast_nonprogressive_emojipicker_test.html b/src/database/third_party/closure-library/closure/goog/ui/emoji/fast_nonprogressive_emojipicker_test.html
    deleted file mode 100644
    index f7dd25c2da0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/emoji/fast_nonprogressive_emojipicker_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.emoji.EmojiPicker
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.ui.emoji.FastNonProgressiveEmojiPickerTest');
    -  </script>
    -  <link rel="stylesheet" href="../../demos/css/emojisprite.css" />
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/emoji/fast_nonprogressive_emojipicker_test.js b/src/database/third_party/closure-library/closure/goog/ui/emoji/fast_nonprogressive_emojipicker_test.js
    deleted file mode 100644
    index adec7b27a2e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/emoji/fast_nonprogressive_emojipicker_test.js
    +++ /dev/null
    @@ -1,248 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.emoji.FastNonProgressiveEmojiPickerTest');
    -goog.setTestOnly('goog.ui.emoji.FastNonProgressiveEmojiPickerTest');
    -
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events');
    -goog.require('goog.events.EventType');
    -goog.require('goog.net.EventType');
    -goog.require('goog.style');
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.emoji.Emoji');
    -goog.require('goog.ui.emoji.EmojiPicker');
    -goog.require('goog.ui.emoji.SpriteInfo');
    -goog.require('goog.userAgent');
    -var sprite = '../../demos/emoji/sprite.png';
    -var sprite2 = '../../demos/emoji/sprite2.png';
    -
    -
    -/**
    - * Creates a SpriteInfo object with the specified properties. If the image is
    - * sprited via CSS, then only the first parameter needs a value. If the image
    - * is sprited via metadata, then the first parameter should be left null.
    - *
    - * @param {?string} cssClass CSS class to properly display the sprited image.
    - * @param {string=} opt_url Url of the sprite image.
    - * @param {number=} opt_width Width of the image being sprited.
    - * @param {number=} opt_height Height of the image being sprited.
    - * @param {number=} opt_xOffset Positive x offset of the image being sprited
    - *     within the sprite.
    - * @param {number=} opt_yOffset Positive y offset of the image being sprited
    - *     within the sprite.
    - * @param {boolean=} opt_animated Whether the sprite info is for an animated
    - *     emoji.
    - */
    -function si(cssClass, opt_url, opt_width, opt_height, opt_xOffset,
    -            opt_yOffset, opt_animated) {
    -  return new goog.ui.emoji.SpriteInfo(cssClass, opt_url, opt_width,
    -      opt_height, opt_xOffset, opt_yOffset, opt_animated);
    -}
    -
    -
    -// This group contains a mix of sprited emoji via css, sprited emoji via
    -// metadata, and non-sprited emoji.
    -var spritedEmoji2 = [
    -  'Emoji 1',
    -  [
    -   ['../../demos/emoji/200.gif', 'std.200', si('SPRITE_200')],
    -   ['../../demos/emoji/201.gif', 'std.201', si('SPRITE_201')],
    -   ['../../demos/emoji/202.gif', 'std.202', si('SPRITE_202')],
    -   ['../../demos/emoji/203.gif', 'std.203', si('SPRITE_203')],
    -   ['../../demos/emoji/204.gif', 'std.204', si('SPRITE_204')],
    -   ['../../demos/emoji/205.gif', 'std.205', si('SPRITE_205')],
    -   ['../../demos/emoji/206.gif', 'std.206', si('SPRITE_206')],
    -   ['../../demos/emoji/2BC.gif', 'std.2BC', si('SPRITE_2BC')],
    -   ['../../demos/emoji/2BD.gif', 'std.2BD', si('SPRITE_2BD')],
    -   ['../../demos/emoji/2BE.gif', 'std.2BE',
    -    si(null, sprite, 18, 18, 36, 54)],
    -   ['../../demos/emoji/2BF.gif', 'std.2BF',
    -    si(null, sprite, 18, 18, 0, 126)],
    -   ['../../demos/emoji/2C0.gif', 'std.2C0',
    -    si(null, sprite, 18, 18, 18, 305)],
    -   ['../../demos/emoji/2C1.gif', 'std.2C1',
    -    si(null, sprite, 18, 18, 0, 287)],
    -   ['../../demos/emoji/2C2.gif', 'std.2C2',
    -    si(null, sprite, 18, 18, 18, 126)],
    -   ['../../demos/emoji/2C3.gif', 'std.2C3',
    -    si(null, sprite, 18, 18, 36, 234)],
    -   ['../../demos/emoji/2C4.gif', 'std.2C4',
    -    si(null, sprite, 18, 18, 36, 72)],
    -   ['../../demos/emoji/2C5.gif', 'std.2C5',
    -    si(null, sprite, 18, 18, 54, 54)],
    -   ['../../demos/emoji/2C6.gif', 'std.2C6'],
    -   ['../../demos/emoji/2C7.gif', 'std.2C7'],
    -   ['../../demos/emoji/2C8.gif', 'std.2C8'],
    -   ['../../demos/emoji/2C9.gif', 'std.2C9'],
    -   ['../../demos/emoji/2CA.gif', 'std.2CA',
    -    si(null, sprite2, 18, 20, 36, 72, 1)],
    -   ['../../demos/emoji/2E3.gif', 'std.2E3',
    -    si(null, sprite2, 18, 18, 0, 0, 1)],
    -   ['../../demos/emoji/2EF.gif', 'std.2EF',
    -    si(null, sprite2, 18, 20, 0, 300, 1)],
    -   ['../../demos/emoji/2F1.gif', 'std.2F1',
    -    si(null, sprite2, 18, 18, 0, 320, 1)]
    -  ]];
    -
    -
    -/**
    - * Returns true if the two paths end with the same file.
    - *
    - * E.g., ('../../cool.gif', 'file:///home/usr/somewhere/cool.gif') --> true
    - *
    - * @param {string} path1 First url
    - * @param {string} path2 Second url
    - */
    -function checkPathsEndWithSameFile(path1, path2) {
    -  var pieces1 = path1.split('/');
    -  var file1 = pieces1[pieces1.length - 1];
    -  var pieces2 = path2.split('/');
    -  var file2 = pieces2[pieces2.length - 1];
    -
    -  return file1 == file2;
    -}
    -
    -
    -/**
    - * Checks and verifies the structure of a non-progressive fast-loading picker
    - * after the animated emoji have loaded.
    - *
    - * @param {goog.ui.emoji.EmojiPalette} palette Emoji palette to check.
    - * @param {Array<Array<string>>} emoji Emoji that should be in the palette.
    - * @param {Object} images Map of id -> Image for the images loaded in this
    - *     picker.
    - */
    -function checkPostLoadStructureForFastLoadNonProgressivePicker(palette,
    -                                                               emoji,
    -                                                               images) {
    -  for (var i = 0; i < emoji[1].length; i++) {
    -    palette.setSelectedIndex(i);
    -    var emojiInfo = emoji[1][i];
    -    var cell = palette.getSelectedItem();
    -    var id = cell.getAttribute(goog.ui.emoji.Emoji.ATTRIBUTE);
    -    var inner = /** @type {Element} */ (cell.firstChild);
    -
    -    // Check that the cell is a div wrapped around something else, and that the
    -    // outer div contains the goomoji attribute
    -    assertEquals('The palette item should be a div wrapped around something',
    -        cell.tagName, 'DIV');
    -    assertNotNull('The outer div is not wrapped around another element', inner);
    -    assertEquals('The palette item should have the goomoji attribute',
    -        cell.getAttribute(goog.ui.emoji.Emoji.ATTRIBUTE), emojiInfo[1]);
    -
    -    // Now check the contents of the cells
    -    var url = emojiInfo[0];   // url of the animated emoji
    -    var spriteInfo = emojiInfo[2];
    -    if (spriteInfo) {
    -      assertEquals(inner.tagName, 'DIV');
    -      if (spriteInfo.isAnimated()) {
    -        var img = images[id];
    -        checkPathsEndWithSameFile(
    -            goog.style.getStyle(inner, 'background-image'),
    -            url);
    -        assertEquals(String(img.width), goog.style.getStyle(inner, 'width').
    -            replace(/px/g, '').replace(/pt/g, ''));
    -        assertEquals(String(img.height), goog.style.getStyle(inner, 'height').
    -            replace(/px/g, '').replace(/pt/g, ''));
    -        assertEquals('0 0', goog.style.getStyle(inner,
    -            'background-position').replace(/px/g, '').
    -            replace(/pt/g, ''));
    -      } else {
    -        var cssClass = spriteInfo.getCssClass();
    -        if (cssClass) {
    -          assertTrue('Sprite should have its CSS class set',
    -              goog.dom.classlist.contains(inner, cssClass));
    -        } else {
    -          checkPathsEndWithSameFile(
    -              goog.style.getStyle(inner, 'background-image'),
    -              spriteInfo.getUrl());
    -          assertEquals(spriteInfo.getWidthCssValue(),
    -              goog.style.getStyle(inner, 'width'));
    -          assertEquals(spriteInfo.getHeightCssValue(),
    -              goog.style.getStyle(inner, 'height'));
    -          assertEquals((spriteInfo.getXOffsetCssValue() + ' ' +
    -                        spriteInfo.getYOffsetCssValue()).replace(/px/g, '').
    -              replace(/pt/g, ''),
    -              goog.style.getStyle(inner,
    -                  'background-position').replace(/px/g, '').
    -                  replace(/pt/g, ''));
    -        }
    -      }
    -    } else {
    -      // A non-sprited emoji is just an img
    -      assertEquals(inner.tagName, 'IMG');
    -      checkPathsEndWithSameFile(inner.src, emojiInfo[0]);
    -    }
    -  }
    -}
    -
    -var testCase = new goog.testing.AsyncTestCase(document.title);
    -testCase.stepTimeout = 4 * 1000;
    -
    -testCase.setUpPage = function() {
    -  this.waitForAsync('setUpPage');
    -  var defaultImg = '../../demos/emoji/none.gif';
    -  this.picker = new goog.ui.emoji.EmojiPicker(defaultImg);
    -  this.picker.setDelayedLoad(false);
    -  this.picker.setManualLoadOfAnimatedEmoji(true);
    -  this.picker.setProgressiveRender(false);
    -  this.picker.addEmojiGroup(spritedEmoji2[0], spritedEmoji2[1]);
    -  this.picker.render();
    -
    -  this.palette = this.picker.getPage(0);
    -  var imageLoader = this.palette.getImageLoader();
    -  this.images = {};
    -
    -  goog.events.listen(imageLoader, goog.net.EventType.COMPLETE,
    -      this.onImageLoaderComplete, false, this);
    -  goog.events.listen(imageLoader, goog.events.EventType.LOAD,
    -      this.onImageLoaded, false, this);
    -
    -  // Now we load the animated emoji and check the structure again. The animated
    -  // emoji will be different.
    -  this.picker.manuallyLoadAnimatedEmoji();
    -};
    -
    -testCase.onImageLoaded = function(e) {
    -  var image = e.target;
    -  this.log('Image loaded: ' + image.src);
    -  this.images[image.id] = image;
    -};
    -
    -testCase.onImageLoaderComplete = function(e) {
    -  this.log('Image loading complete');
    -  this.continueTesting();
    -};
    -
    -testCase.tearDownPage = function() {
    -  this.picker.dispose();
    -};
    -
    -testCase.addNewTest('testStructure', function() {
    -  // Bug 2280968
    -  if (goog.userAgent.IE && goog.userAgent.VERSION == '6.0') {
    -    this.log('Not testing emojipicker structure');
    -    return;
    -  }
    -
    -  this.log('Testing emojipicker structure');
    -  checkPostLoadStructureForFastLoadNonProgressivePicker(this.palette,
    -      spritedEmoji2, this.images);
    -});
    -
    -
    -// Standalone Closure Test Runner.
    -G_testRunner.initialize(testCase);
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/emoji/fast_progressive_emojipicker_test.html b/src/database/third_party/closure-library/closure/goog/ui/emoji/fast_progressive_emojipicker_test.html
    deleted file mode 100644
    index d91dcbe99f5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/emoji/fast_progressive_emojipicker_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.emoji.EmojiPicker
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.ui.emoji.FastProgressiveEmojiPickerTest');
    -  </script>
    -  <link rel="stylesheet" href="../../demos/css/emojisprite.css" />
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/emoji/fast_progressive_emojipicker_test.js b/src/database/third_party/closure-library/closure/goog/ui/emoji/fast_progressive_emojipicker_test.js
    deleted file mode 100644
    index 4b5e4ed5e90..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/emoji/fast_progressive_emojipicker_test.js
    +++ /dev/null
    @@ -1,248 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.emoji.FastProgressiveEmojiPickerTest');
    -goog.setTestOnly('goog.ui.emoji.FastProgressiveEmojiPickerTest');
    -
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events');
    -goog.require('goog.events.EventType');
    -goog.require('goog.net.EventType');
    -goog.require('goog.style');
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.emoji.Emoji');
    -goog.require('goog.ui.emoji.EmojiPicker');
    -goog.require('goog.ui.emoji.SpriteInfo');
    -var sprite = '../../demos/emoji/sprite.png';
    -var sprite2 = '../../demos/emoji/sprite2.png';
    -
    -
    -/**
    - * Creates a SpriteInfo object with the specified properties. If the image is
    - * sprited via CSS, then only the first parameter needs a value. If the image
    - * is sprited via metadata, then the first parameter should be left null.
    - *
    - * @param {?string} cssClass CSS class to properly display the sprited image.
    - * @param {string=} opt_url Url of the sprite image.
    - * @param {number=} opt_width Width of the image being sprited.
    - * @param {number=} opt_height Height of the image being sprited.
    - * @param {number=} opt_xOffset Positive x offset of the image being sprited
    - *     within the sprite.
    - * @param {number=} opt_yOffset Positive y offset of the image being sprited
    - *     within the sprite.
    - * @param {boolean=} opt_animated Whether the sprite info is for an animated
    - *     emoji.
    - */
    -function si(cssClass, opt_url, opt_width, opt_height, opt_xOffset,
    -            opt_yOffset, opt_animated) {
    -  return new goog.ui.emoji.SpriteInfo(cssClass, opt_url, opt_width,
    -      opt_height, opt_xOffset, opt_yOffset, opt_animated);
    -}
    -
    -// This group contains a mix of sprited emoji via css, sprited emoji via
    -// metadata, and non-sprited emoji.
    -var spritedEmoji2 = [
    -  'Emoji 1',
    -  [
    -   ['../../demos/emoji/200.gif', 'std.200', si('SPRITE_200')],
    -   ['../../demos/emoji/201.gif', 'std.201', si('SPRITE_201')],
    -   ['../../demos/emoji/202.gif', 'std.202', si('SPRITE_202')],
    -   ['../../demos/emoji/203.gif', 'std.203', si('SPRITE_203')],
    -   ['../../demos/emoji/204.gif', 'std.204', si('SPRITE_204')],
    -   ['../../demos/emoji/205.gif', 'std.205', si('SPRITE_205')],
    -   ['../../demos/emoji/206.gif', 'std.206', si('SPRITE_206')],
    -   ['../../demos/emoji/2BC.gif', 'std.2BC', si('SPRITE_2BC')],
    -   ['../../demos/emoji/2BD.gif', 'std.2BD', si('SPRITE_2BD')],
    -   ['../../demos/emoji/2BE.gif', 'std.2BE',
    -    si(null, sprite, 18, 18, 36, 54)],
    -   ['../../demos/emoji/2BF.gif', 'std.2BF',
    -    si(null, sprite, 18, 18, 0, 126)],
    -   ['../../demos/emoji/2C0.gif', 'std.2C0',
    -    si(null, sprite, 18, 18, 18, 305)],
    -   ['../../demos/emoji/2C1.gif', 'std.2C1',
    -    si(null, sprite, 18, 18, 0, 287)],
    -   ['../../demos/emoji/2C2.gif', 'std.2C2',
    -    si(null, sprite, 18, 18, 18, 126)],
    -   ['../../demos/emoji/2C3.gif', 'std.2C3',
    -    si(null, sprite, 18, 18, 36, 234)],
    -   ['../../demos/emoji/2C4.gif', 'std.2C4',
    -    si(null, sprite, 18, 18, 36, 72)],
    -   ['../../demos/emoji/2C5.gif', 'std.2C5',
    -    si(null, sprite, 18, 18, 54, 54)],
    -   ['../../demos/emoji/2C6.gif', 'std.2C6'],
    -   ['../../demos/emoji/2C7.gif', 'std.2C7'],
    -   ['../../demos/emoji/2C8.gif', 'std.2C8'],
    -   ['../../demos/emoji/2C9.gif', 'std.2C9'],
    -   ['../../demos/emoji/2CA.gif', 'std.2CA',
    -    si(null, sprite2, 18, 20, 36, 72, 1)],
    -   ['../../demos/emoji/2E3.gif', 'std.2E3',
    -    si(null, sprite2, 18, 18, 0, 0, 1)],
    -   ['../../demos/emoji/2EF.gif', 'std.2EF',
    -    si(null, sprite2, 18, 20, 0, 300, 1)],
    -   ['../../demos/emoji/2F1.gif', 'std.2F1',
    -    si(null, sprite2, 18, 18, 0, 320, 1)]
    -  ]];
    -
    -
    -/**
    - * Returns true if the two paths end with the same file.
    - *
    - * E.g., ('../../cool.gif', 'file:///home/usr/somewhere/cool.gif') --> true
    - *
    - * @param {string} path1 First url
    - * @param {string} path2 Second url
    - */
    -function checkPathsEndWithSameFile(path1, path2) {
    -  var pieces1 = path1.split('/');
    -  var file1 = pieces1[pieces1.length - 1];
    -  var pieces2 = path2.split('/');
    -  var file2 = pieces2[pieces2.length - 1];
    -
    -  return file1 == file2;
    -}
    -
    -
    -/**
    - * Checks and verifies the structure of a progressive fast-loading picker
    - * after the animated emoji have loaded.
    - *
    - * @param {goog.ui.emoji.EmojiPalette} palette Emoji palette to check.
    - * @param {Array<Array<string>>} emoji Emoji that should be in the palette.
    - * @param {Object} images Map of id -> Image for the images loaded in this
    - *     picker.
    - */
    -function checkPostLoadStructureForFastLoadProgressivePicker(palette,
    -                                                            emoji,
    -                                                            images) {
    -  for (var i = 0; i < emoji[1].length; i++) {
    -    palette.setSelectedIndex(i);
    -    var emojiInfo = emoji[1][i];
    -    var cell = palette.getSelectedItem();
    -    var id = cell.getAttribute(goog.ui.emoji.Emoji.ATTRIBUTE);
    -    var inner = /** @type {Element} */ (cell.firstChild);
    -
    -    // Check that the cell is a div wrapped around something else, and that the
    -    // outer div contains the goomoji attribute
    -    assertEquals('The palette item should be a div wrapped around something',
    -        cell.tagName, 'DIV');
    -    assertNotNull('The outer div is not wrapped around another element', inner);
    -    assertEquals('The palette item should have the goomoji attribute',
    -        cell.getAttribute(goog.ui.emoji.Emoji.ATTRIBUTE), emojiInfo[1]);
    -
    -    // Now check the contents of the cells
    -    var url = emojiInfo[0];  // url of the animated emoji
    -    var spriteInfo = emojiInfo[2];
    -    if (spriteInfo) {
    -      if (spriteInfo.isAnimated()) {
    -        var testImg = images[id];
    -        var img = inner.firstChild;
    -        checkPathsEndWithSameFile(img.src, url);
    -        assertEquals(testImg.width, img.width);
    -        assertEquals(testImg.height, img.height);
    -        assertEquals('0', goog.style.getStyle(img, 'left').replace(/px/g, '').
    -            replace(/pt/g, ''));
    -        assertEquals('0', goog.style.getStyle(img, 'top').replace(/px/g, '').
    -            replace(/pt/g, ''));
    -      } else {
    -        var cssClass = spriteInfo.getCssClass();
    -        if (cssClass) {
    -          assertEquals('DIV', inner.tagName);
    -          assertTrue('Sprite should have its CSS class set',
    -              goog.dom.classlist.contains(inner, cssClass));
    -        } else {
    -          // There's an inner div wrapping an img tag
    -          assertEquals('DIV', inner.tagName);
    -          var img = inner.firstChild;
    -          assertNotNull('Div should be wrapping something', img);
    -          assertEquals('IMG', img.tagName);
    -          checkPathsEndWithSameFile(img.src, spriteInfo.getUrl());
    -          assertEquals(spriteInfo.getWidthCssValue(),
    -              goog.style.getStyle(inner, 'width'));
    -          assertEquals(spriteInfo.getHeightCssValue(),
    -              goog.style.getStyle(inner, 'height'));
    -          assertEquals(spriteInfo.getXOffsetCssValue().replace(/px/, '').
    -              replace(/pt/, ''),
    -              goog.style.getStyle(img, 'left').replace(/px/, '').
    -                  replace(/pt/, ''));
    -          assertEquals(spriteInfo.getYOffsetCssValue().replace(/px/, '').
    -              replace(/pt/, ''),
    -              goog.style.getStyle(img, 'top').replace(/px/, '').
    -                  replace(/pt/, ''));
    -        }
    -      }
    -    } else {
    -      // A non-sprited emoji is just an img
    -      assertEquals(inner.tagName, 'IMG');
    -      checkPathsEndWithSameFile(inner.src, emojiInfo[0]);
    -    }
    -  }
    -}
    -
    -var testCase = new goog.testing.AsyncTestCase(document.title);
    -testCase.stepTimeout = 4 * 1000;
    -
    -testCase.setUpPage = function() {
    -  testCase.waitForAsync('setUpPage');
    -  var defaultImg = '../../demos/emoji/none.gif';
    -  this.picker = new goog.ui.emoji.EmojiPicker(defaultImg);
    -  this.picker.setDelayedLoad(false);
    -  this.picker.setManualLoadOfAnimatedEmoji(true);
    -  this.picker.setProgressiveRender(true);
    -  this.picker.addEmojiGroup(spritedEmoji2[0], spritedEmoji2[1]);
    -  this.picker.render();
    -
    -  this.palette = this.picker.getPage(0);
    -  var imageLoader = this.palette.getImageLoader();
    -  this.images = {};
    -
    -  goog.events.listen(imageLoader, goog.net.EventType.COMPLETE,
    -      this.onImageLoaderComplete, false, this);
    -  goog.events.listen(imageLoader, goog.events.EventType.LOAD,
    -      this.onImageLoaded, false, this);
    -
    -  // Now we load the animated emoji and check the structure again. The animated
    -  // emoji will be different.
    -  this.picker.manuallyLoadAnimatedEmoji();
    -};
    -
    -testCase.onImageLoaded = function(e) {
    -  var image = e.target;
    -  this.log('Image loaded: ' + image.src);
    -  this.images[image.id] = image;
    -};
    -
    -testCase.onImageLoaderComplete = function(e) {
    -  this.log('Image loading complete');
    -  this.continueTesting();
    -};
    -
    -testCase.tearDownPage = function() {
    -  this.picker.dispose();
    -};
    -
    -
    -
    -testCase.addNewTest('testStructure', function() {
    -  // Bug 2280968
    -  this.log('Not testing emojipicker structure');
    -  return;
    -
    -  this.log('Testing emojipicker structure');
    -  checkPostLoadStructureForFastLoadProgressivePicker(this.palette,
    -      spritedEmoji2, this.images);
    -});
    -
    -// Standalone Closure Test Runner.
    -G_testRunner.initialize(testCase);
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/emoji/popupemojipicker.js b/src/database/third_party/closure-library/closure/goog/ui/emoji/popupemojipicker.js
    deleted file mode 100644
    index 8318f9a8dfc..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/emoji/popupemojipicker.js
    +++ /dev/null
    @@ -1,411 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Popup Emoji Picker implementation. This provides a UI widget
    - * for choosing an emoji from a grid of possible choices. The widget is a popup,
    - * so it is suitable for a toolbar, for instance the TrogEdit toolbar.
    - *
    - * @see ../demos/popupemojipicker.html for an example of how to instantiate
    - * an emoji picker.
    - *
    - * See goog.ui.emoji.EmojiPicker in emojipicker.js for more details.
    - *
    - * Based on goog.ui.PopupColorPicker (popupcolorpicker.js).
    - *
    - * @see ../../demos/popupemojipicker.html
    - */
    -
    -goog.provide('goog.ui.emoji.PopupEmojiPicker');
    -
    -goog.require('goog.events.EventType');
    -goog.require('goog.positioning.AnchoredPosition');
    -goog.require('goog.positioning.Corner');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.Popup');
    -goog.require('goog.ui.emoji.EmojiPicker');
    -
    -
    -
    -/**
    - * Constructs a popup emoji picker widget.
    - *
    - * @param {string} defaultImgUrl Url of the img that should be used to fill up
    - *     the cells in the emoji table, to prevent jittering. Should be the same
    - *     size as the emoji.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @extends {goog.ui.Component}
    - * @constructor
    - * @final
    - */
    -goog.ui.emoji.PopupEmojiPicker =
    -    function(defaultImgUrl, opt_domHelper) {
    -  goog.ui.Component.call(this, opt_domHelper);
    -
    -  this.emojiPicker_ = new goog.ui.emoji.EmojiPicker(defaultImgUrl,
    -                                                    opt_domHelper);
    -  this.addChild(this.emojiPicker_);
    -
    -  this.getHandler().listen(this.emojiPicker_,
    -      goog.ui.Component.EventType.ACTION, this.onEmojiPicked_);
    -};
    -goog.inherits(goog.ui.emoji.PopupEmojiPicker, goog.ui.Component);
    -
    -
    -/**
    - * Instance of an emoji picker control.
    - * @type {goog.ui.emoji.EmojiPicker}
    - * @private
    - */
    -goog.ui.emoji.PopupEmojiPicker.prototype.emojiPicker_ = null;
    -
    -
    -/**
    - * Instance of goog.ui.Popup used to manage the behavior of the emoji picker.
    - * @type {goog.ui.Popup}
    - * @private
    - */
    -goog.ui.emoji.PopupEmojiPicker.prototype.popup_ = null;
    -
    -
    -/**
    - * Reference to the element that triggered the last popup.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.emoji.PopupEmojiPicker.prototype.lastTarget_ = null;
    -
    -
    -/**
    - * Whether the emoji picker can accept focus.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.emoji.PopupEmojiPicker.prototype.focusable_ = true;
    -
    -
    -/**
    - * If true, then the emojipicker will toggle off if it is already visible.
    - * Default is true.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.emoji.PopupEmojiPicker.prototype.toggleMode_ = true;
    -
    -
    -/**
    - * Adds a group of emoji to the picker.
    - *
    - * @param {string|Element} title Title for the group.
    - * @param {Array<Array<?>>} emojiGroup A new group of emoji to be added. Each
    - *    internal array contains [emojiUrl, emojiId].
    - */
    -goog.ui.emoji.PopupEmojiPicker.prototype.addEmojiGroup =
    -    function(title, emojiGroup) {
    -  this.emojiPicker_.addEmojiGroup(title, emojiGroup);
    -};
    -
    -
    -/**
    - * Sets whether the emoji picker should toggle if it is already open.
    - * @param {boolean} toggle The toggle mode to use.
    - */
    -goog.ui.emoji.PopupEmojiPicker.prototype.setToggleMode = function(toggle) {
    -  this.toggleMode_ = toggle;
    -};
    -
    -
    -/**
    - * Gets whether the emojipicker is in toggle mode
    - * @return {boolean} toggle.
    - */
    -goog.ui.emoji.PopupEmojiPicker.prototype.getToggleMode = function() {
    -  return this.toggleMode_;
    -};
    -
    -
    -/**
    - * Sets whether loading of images should be delayed until after dom creation.
    - * Thus, this function must be called before {@link #createDom}. If set to true,
    - * the client must call {@link #loadImages} when they wish the images to be
    - * loaded.
    - *
    - * @param {boolean} shouldDelay Whether to delay loading the images.
    - */
    -goog.ui.emoji.PopupEmojiPicker.prototype.setDelayedLoad =
    -    function(shouldDelay) {
    -  if (this.emojiPicker_) {
    -    this.emojiPicker_.setDelayedLoad(shouldDelay);
    -  }
    -};
    -
    -
    -/**
    - * Sets whether the emoji picker can accept focus.
    - * @param {boolean} focusable Whether the emoji picker should accept focus.
    - */
    -goog.ui.emoji.PopupEmojiPicker.prototype.setFocusable = function(focusable) {
    -  this.focusable_ = focusable;
    -  if (this.emojiPicker_) {
    -    // TODO(user): In next revision sort the behavior of passing state to
    -    // children correctly
    -    this.emojiPicker_.setFocusable(focusable);
    -  }
    -};
    -
    -
    -/**
    - * Sets the URL prefix for the emoji URLs.
    - *
    - * @param {string} urlPrefix Prefix that should be prepended to all URLs.
    - */
    -goog.ui.emoji.PopupEmojiPicker.prototype.setUrlPrefix = function(urlPrefix) {
    -  this.emojiPicker_.setUrlPrefix(urlPrefix);
    -};
    -
    -
    -/**
    - * Sets the location of the tabs in relation to the emoji grids. This should
    - * only be called before the picker has been rendered.
    - *
    - * @param {goog.ui.TabPane.TabLocation} tabLocation The location of the tabs.
    - */
    -goog.ui.emoji.PopupEmojiPicker.prototype.setTabLocation =
    -    function(tabLocation) {
    -  this.emojiPicker_.setTabLocation(tabLocation);
    -};
    -
    -
    -/**
    - * Sets the number of rows per grid in the emoji picker. This should only be
    - * called before the picker has been rendered.
    - *
    - * @param {number} numRows Number of rows per grid.
    - */
    -goog.ui.emoji.PopupEmojiPicker.prototype.setNumRows = function(numRows) {
    -  this.emojiPicker_.setNumRows(numRows);
    -};
    -
    -
    -/**
    - * Sets the number of columns per grid in the emoji picker. This should only be
    - * called before the picker has been rendered.
    - *
    - * @param {number} numCols Number of columns per grid.
    - */
    -goog.ui.emoji.PopupEmojiPicker.prototype.setNumColumns = function(numCols) {
    -  this.emojiPicker_.setNumColumns(numCols);
    -};
    -
    -
    -/**
    - * Sets the progressive rendering aspect of this emojipicker. Must be called
    - * before createDom to have an effect.
    - *
    - * @param {boolean} progressive Whether the picker should render progressively.
    - */
    -goog.ui.emoji.PopupEmojiPicker.prototype.setProgressiveRender =
    -    function(progressive) {
    -  if (this.emojiPicker_) {
    -    this.emojiPicker_.setProgressiveRender(progressive);
    -  }
    -};
    -
    -
    -/**
    - * Returns the number of emoji groups in this picker.
    - *
    - * @return {number} The number of emoji groups in this picker.
    - */
    -goog.ui.emoji.PopupEmojiPicker.prototype.getNumEmojiGroups = function() {
    -  return this.emojiPicker_.getNumEmojiGroups();
    -};
    -
    -
    -/**
    - * Causes the emoji imgs to be loaded into the picker. Used for delayed loading.
    - */
    -goog.ui.emoji.PopupEmojiPicker.prototype.loadImages = function() {
    -  if (this.emojiPicker_) {
    -    this.emojiPicker_.loadImages();
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.emoji.PopupEmojiPicker.prototype.createDom = function() {
    -  goog.ui.emoji.PopupEmojiPicker.superClass_.createDom.call(this);
    -
    -  this.emojiPicker_.createDom();
    -
    -  this.getElement().className = goog.getCssName('goog-ui-popupemojipicker');
    -  this.getElement().appendChild(this.emojiPicker_.getElement());
    -
    -  this.popup_ = new goog.ui.Popup(this.getElement());
    -  this.getElement().unselectable = 'on';
    -};
    -
    -
    -/** @override */
    -goog.ui.emoji.PopupEmojiPicker.prototype.disposeInternal = function() {
    -  goog.ui.emoji.PopupEmojiPicker.superClass_.disposeInternal.call(this);
    -  this.emojiPicker_ = null;
    -  this.lastTarget_ = null;
    -  if (this.popup_) {
    -    this.popup_.dispose();
    -    this.popup_ = null;
    -  }
    -};
    -
    -
    -/**
    - * Attaches the popup emoji picker to an element.
    - *
    - * @param {Element} element The element to attach to.
    - */
    -goog.ui.emoji.PopupEmojiPicker.prototype.attach = function(element) {
    -  // TODO(user): standardize event type, popups should use MOUSEDOWN, but
    -  // currently apps are using click.
    -  this.getHandler().listen(element, goog.events.EventType.CLICK, this.show_);
    -};
    -
    -
    -/**
    - * Detatches the popup emoji picker from an element.
    - *
    - * @param {Element} element The element to detach from.
    - */
    -goog.ui.emoji.PopupEmojiPicker.prototype.detach = function(element) {
    -  this.getHandler().unlisten(element, goog.events.EventType.CLICK, this.show_);
    -};
    -
    -
    -/**
    - * @return {goog.ui.emoji.EmojiPicker} The emoji picker instance.
    - */
    -goog.ui.emoji.PopupEmojiPicker.prototype.getEmojiPicker = function() {
    -  return this.emojiPicker_;
    -};
    -
    -
    -/**
    - * Returns whether the Popup dismisses itself when the user clicks outside of
    - * it.
    - * @return {boolean} Whether the Popup autohides on an external click.
    - */
    -goog.ui.emoji.PopupEmojiPicker.prototype.getAutoHide = function() {
    -  return !!this.popup_ && this.popup_.getAutoHide();
    -};
    -
    -
    -/**
    - * Sets whether the Popup dismisses itself when the user clicks outside of it -
    - * must be called after the Popup has been created (in createDom()),
    - * otherwise it does nothing.
    - *
    - * @param {boolean} autoHide Whether to autohide on an external click.
    - */
    -goog.ui.emoji.PopupEmojiPicker.prototype.setAutoHide = function(autoHide) {
    -  if (this.popup_) {
    -    this.popup_.setAutoHide(autoHide);
    -  }
    -};
    -
    -
    -/**
    - * Returns the region inside which the Popup dismisses itself when the user
    - * clicks, or null if it was not set. Null indicates the entire document is
    - * the autohide region.
    - * @return {Element} The DOM element for autohide, or null if it hasn't been
    - *     set.
    - */
    -goog.ui.emoji.PopupEmojiPicker.prototype.getAutoHideRegion = function() {
    -  return this.popup_ && this.popup_.getAutoHideRegion();
    -};
    -
    -
    -/**
    - * Sets the region inside which the Popup dismisses itself when the user
    - * clicks - must be called after the Popup has been created (in createDom()),
    - * otherwise it does nothing.
    - *
    - * @param {Element} element The DOM element for autohide.
    - */
    -goog.ui.emoji.PopupEmojiPicker.prototype.setAutoHideRegion = function(element) {
    -  if (this.popup_) {
    -    this.popup_.setAutoHideRegion(element);
    -  }
    -};
    -
    -
    -/**
    - * Returns the {@link goog.ui.PopupBase} from this picker. Returns null if the
    - * popup has not yet been created.
    - *
    - * NOTE: This should *ONLY* be called from tests. If called before createDom(),
    - * this should return null.
    - *
    - * @return {goog.ui.PopupBase?} The popup, or null if it hasn't been created.
    - */
    -goog.ui.emoji.PopupEmojiPicker.prototype.getPopup = function() {
    -  return this.popup_;
    -};
    -
    -
    -/**
    - * @return {Element} The last element that triggered the popup.
    - */
    -goog.ui.emoji.PopupEmojiPicker.prototype.getLastTarget = function() {
    -  return this.lastTarget_;
    -};
    -
    -
    -/**
    - * @return {goog.ui.emoji.Emoji} The currently selected emoji.
    - */
    -goog.ui.emoji.PopupEmojiPicker.prototype.getSelectedEmoji = function() {
    -  return this.emojiPicker_.getSelectedEmoji();
    -};
    -
    -
    -/**
    - * Handles click events on the element this picker is attached to and shows the
    - * emoji picker in a popup.
    - *
    - * @param {goog.events.BrowserEvent} e The browser event.
    - * @private
    - */
    -goog.ui.emoji.PopupEmojiPicker.prototype.show_ = function(e) {
    -  if (this.popup_.isOrWasRecentlyVisible() && this.toggleMode_ &&
    -      this.lastTarget_ == e.currentTarget) {
    -    this.popup_.setVisible(false);
    -    return;
    -  }
    -
    -  this.lastTarget_ = /** @type {Element} */ (e.currentTarget);
    -  this.popup_.setPosition(new goog.positioning.AnchoredPosition(
    -      this.lastTarget_, goog.positioning.Corner.BOTTOM_LEFT));
    -  this.popup_.setVisible(true);
    -};
    -
    -
    -/**
    - * Handles selection of an emoji.
    - *
    - * @param {goog.events.Event} e The event object.
    - * @private
    - */
    -goog.ui.emoji.PopupEmojiPicker.prototype.onEmojiPicked_ = function(e) {
    -  this.popup_.setVisible(false);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/emoji/popupemojipicker_test.html b/src/database/third_party/closure-library/closure/goog/ui/emoji/popupemojipicker_test.html
    deleted file mode 100644
    index 33d53782548..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/emoji/popupemojipicker_test.html
    +++ /dev/null
    @@ -1,26 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.emoji.PopupEmojiPicker
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.ui.emoji.PopupEmojiPickerTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="containingDiv">
    -   <button id="button1">
    -   </button>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/emoji/popupemojipicker_test.js b/src/database/third_party/closure-library/closure/goog/ui/emoji/popupemojipicker_test.js
    deleted file mode 100644
    index 0f7b3291871..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/emoji/popupemojipicker_test.js
    +++ /dev/null
    @@ -1,71 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.emoji.PopupEmojiPickerTest');
    -goog.setTestOnly('goog.ui.emoji.PopupEmojiPickerTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.emoji.PopupEmojiPicker');
    -var emojiGroup1 = [
    -  'Emoji 1',
    -  [
    -   ['../../demos/emoji/200.gif', 'std.200'],
    -   ['../../demos/emoji/201.gif', 'std.201']
    -  ]];
    -
    -var emojiGroup2 = [
    -  'Emoji 2',
    -  [
    -   ['../../demos/emoji/2D0.gif', 'std.2D0'],
    -   ['../../demos/emoji/2D1.gif', 'std.2D1']
    -  ]];
    -
    -var emojiGroup3 = [
    -  'Emoji 3',
    -  [
    -   ['../../demos/emoji/2E4.gif', 'std.2E4'],
    -   ['../../demos/emoji/2E5.gif', 'std.2E5']
    -  ]];
    -
    -function testConstructAndRenderPopupEmojiPicker() {
    -  var picker = new goog.ui.emoji.PopupEmojiPicker(
    -      '../../demos/emoji/none.gif');
    -  picker.addEmojiGroup(emojiGroup1[0], emojiGroup1[1]);
    -  picker.addEmojiGroup(emojiGroup2[0], emojiGroup2[1]);
    -  picker.addEmojiGroup(emojiGroup3[0], emojiGroup3[1]);
    -  picker.render();
    -  picker.attach(document.getElementById('button1'));
    -  picker.dispose();
    -}
    -
    -// Unittest to ensure that the popup gets created in createDom().
    -function testPopupCreation() {
    -  var picker = new goog.ui.emoji.PopupEmojiPicker();
    -  picker.addEmojiGroup(emojiGroup1[0], emojiGroup1[1]);
    -  picker.createDom();
    -  assertNotNull(picker.getPopup());
    -}
    -
    -
    -function testAutoHideIsSetProperly() {
    -  var picker = new goog.ui.emoji.PopupEmojiPicker();
    -  picker.addEmojiGroup(emojiGroup1[0], emojiGroup1[1]);
    -  picker.createDom();
    -  picker.setAutoHide(true);
    -  var containingDiv = goog.dom.getElement('containingDiv');
    -  picker.setAutoHideRegion(containingDiv);
    -  assertTrue(picker.getAutoHide());
    -  assertEquals(containingDiv, picker.getAutoHideRegion());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/emoji/progressiveemojipaletterenderer.js b/src/database/third_party/closure-library/closure/goog/ui/emoji/progressiveemojipaletterenderer.js
    deleted file mode 100644
    index c6896a65f17..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/emoji/progressiveemojipaletterenderer.js
    +++ /dev/null
    @@ -1,99 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Progressive Emoji Palette renderer implementation.
    - *
    - */
    -
    -goog.provide('goog.ui.emoji.ProgressiveEmojiPaletteRenderer');
    -
    -goog.require('goog.style');
    -goog.require('goog.ui.emoji.EmojiPaletteRenderer');
    -
    -
    -
    -/**
    - * Progressively renders an emoji palette. The progressive renderer tries to
    - * use img tags instead of background-image for sprited emoji, since most
    - * browsers render img tags progressively (i.e., as the data comes in), while
    - * only very new browsers render background-image progressively.
    - *
    - * @param {string} defaultImgUrl Url of the img that should be used to fill up
    - *     the cells in the emoji table, to prevent jittering. Will be stretched
    - *     to the emoji cell size. A good image is a transparent dot.
    - * @constructor
    - * @extends {goog.ui.emoji.EmojiPaletteRenderer}
    - * @final
    - */
    -goog.ui.emoji.ProgressiveEmojiPaletteRenderer = function(defaultImgUrl) {
    -  goog.ui.emoji.EmojiPaletteRenderer.call(this, defaultImgUrl);
    -};
    -goog.inherits(goog.ui.emoji.ProgressiveEmojiPaletteRenderer,
    -              goog.ui.emoji.EmojiPaletteRenderer);
    -
    -
    -/** @override */
    -goog.ui.emoji.ProgressiveEmojiPaletteRenderer.prototype.
    -    buildElementFromSpriteMetadata = function(dom, spriteInfo, displayUrl) {
    -  var width = spriteInfo.getWidthCssValue();
    -  var height = spriteInfo.getHeightCssValue();
    -  var x = spriteInfo.getXOffsetCssValue();
    -  var y = spriteInfo.getYOffsetCssValue();
    -  // Need this extra div for proper vertical centering.
    -  var inner = dom.createDom('img', {'src': displayUrl});
    -  var el = /** @type {!HTMLDivElement} */ (dom.createDom('div',
    -      goog.getCssName('goog-palette-cell-extra'), inner));
    -  goog.style.setStyle(el, {
    -    'width': width,
    -    'height': height,
    -    'overflow': 'hidden',
    -    'position': 'relative'
    -  });
    -  goog.style.setStyle(inner, {
    -    'left': x,
    -    'top': y,
    -    'position': 'absolute'
    -  });
    -
    -  return el;
    -};
    -
    -
    -/** @override */
    -goog.ui.emoji.ProgressiveEmojiPaletteRenderer.prototype.
    -    updateAnimatedPaletteItem = function(item, animatedImg) {
    -  // Just to be safe, we check for the existence of the img element within this
    -  // palette item before attempting to modify it.
    -  var img;
    -  var el = item.firstChild;
    -  while (el) {
    -    if ('IMG' == el.tagName) {
    -      img = /** @type {!Element} */ (el);
    -      break;
    -    }
    -    el = el.firstChild;
    -  }
    -  if (!el) {
    -    return;
    -  }
    -
    -  img.width = animatedImg.width;
    -  img.height = animatedImg.height;
    -  goog.style.setStyle(img, {
    -    'left': 0,
    -    'top': 0
    -  });
    -  img.src = animatedImg.src;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/emoji/spriteinfo.js b/src/database/third_party/closure-library/closure/goog/ui/emoji/spriteinfo.js
    deleted file mode 100644
    index 22f053d9b0f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/emoji/spriteinfo.js
    +++ /dev/null
    @@ -1,213 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview SpriteInfo implementation. This is a simple wrapper class to
    - * hold CSS metadata needed for sprited emoji.
    - *
    - * @see ../demos/popupemojipicker.html or emojipicker_test.html for examples
    - * of how to use this class.
    - *
    - */
    -goog.provide('goog.ui.emoji.SpriteInfo');
    -
    -
    -
    -/**
    - * Creates a SpriteInfo object with the specified properties. If the image is
    - * sprited via CSS, then only the first parameter needs a value. If the image
    - * is sprited via metadata, then the first parameter should be left null.
    - *
    - * @param {?string} cssClass CSS class to properly display the sprited image.
    - * @param {string=} opt_url Url of the sprite image.
    - * @param {number=} opt_width Width of the image being sprited.
    - * @param {number=} opt_height Height of the image being sprited.
    - * @param {number=} opt_xOffset Positive x offset of the image being sprited
    - *     within the sprite.
    - * @param {number=} opt_yOffset Positive y offset of the image being sprited
    - *     within the sprite.
    - * @param {boolean=} opt_animated Whether the sprite is animated.
    - * @constructor
    - * @final
    - */
    -goog.ui.emoji.SpriteInfo = function(cssClass, opt_url, opt_width, opt_height,
    -                                    opt_xOffset, opt_yOffset, opt_animated) {
    -  if (cssClass != null) {
    -    this.cssClass_ = cssClass;
    -  } else {
    -    if (opt_url == undefined || opt_width === undefined ||
    -        opt_height === undefined || opt_xOffset == undefined ||
    -        opt_yOffset === undefined) {
    -      throw Error('Sprite info is not fully specified');
    -    }
    -
    -    this.url_ = opt_url;
    -    this.width_ = opt_width;
    -    this.height_ = opt_height;
    -    this.xOffset_ = opt_xOffset;
    -    this.yOffset_ = opt_yOffset;
    -  }
    -
    -  this.animated_ = !!opt_animated;
    -};
    -
    -
    -/**
    - * Name of the CSS class to properly display the sprited image.
    - * @type {string}
    - * @private
    - */
    -goog.ui.emoji.SpriteInfo.prototype.cssClass_;
    -
    -
    -/**
    - * Url of the sprite image.
    - * @type {string|undefined}
    - * @private
    - */
    -goog.ui.emoji.SpriteInfo.prototype.url_;
    -
    -
    -/**
    - * Width of the image being sprited.
    - * @type {number|undefined}
    - * @private
    - */
    -goog.ui.emoji.SpriteInfo.prototype.width_;
    -
    -
    -/**
    - * Height of the image being sprited.
    - * @type {number|undefined}
    - * @private
    - */
    -goog.ui.emoji.SpriteInfo.prototype.height_;
    -
    -
    -/**
    - * Positive x offset of the image being sprited within the sprite.
    - * @type {number|undefined}
    - * @private
    - */
    -goog.ui.emoji.SpriteInfo.prototype.xOffset_;
    -
    -
    -/**
    - * Positive y offset of the image being sprited within the sprite.
    - * @type {number|undefined}
    - * @private
    - */
    -goog.ui.emoji.SpriteInfo.prototype.yOffset_;
    -
    -
    -/**
    - * Whether the emoji specified by the sprite is animated.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.emoji.SpriteInfo.prototype.animated_;
    -
    -
    -/**
    - * Returns the css class of the sprited image.
    - * @return {?string} Name of the CSS class to properly display the sprited
    - *     image.
    - */
    -goog.ui.emoji.SpriteInfo.prototype.getCssClass = function() {
    -  return this.cssClass_ || null;
    -};
    -
    -
    -/**
    - * Returns the url of the sprite image.
    - * @return {?string} Url of the sprite image.
    - */
    -goog.ui.emoji.SpriteInfo.prototype.getUrl = function() {
    -  return this.url_ || null;
    -};
    -
    -
    -/**
    - * Returns whether the emoji specified by this sprite is animated.
    - * @return {boolean} Whether the emoji is animated.
    - */
    -goog.ui.emoji.SpriteInfo.prototype.isAnimated = function() {
    -  return this.animated_;
    -};
    -
    -
    -/**
    - * Returns the width of the image being sprited, appropriate for a CSS value.
    - * @return {string} The width of the image being sprited.
    - */
    -goog.ui.emoji.SpriteInfo.prototype.getWidthCssValue = function() {
    -  return goog.ui.emoji.SpriteInfo.getCssPixelValue_(this.width_);
    -};
    -
    -
    -/**
    - * Returns the height of the image being sprited, appropriate for a CSS value.
    - * @return {string} The height of the image being sprited.
    - */
    -goog.ui.emoji.SpriteInfo.prototype.getHeightCssValue = function() {
    -  return goog.ui.emoji.SpriteInfo.getCssPixelValue_(this.height_);
    -};
    -
    -
    -/**
    - * Returns the x offset of the image being sprited within the sprite,
    - * appropriate for a CSS value.
    - * @return {string} The x offset of the image being sprited within the sprite.
    - */
    -goog.ui.emoji.SpriteInfo.prototype.getXOffsetCssValue = function() {
    -  return goog.ui.emoji.SpriteInfo.getOffsetCssValue_(this.xOffset_);
    -};
    -
    -
    -/**
    - * Returns the positive y offset of the image being sprited within the sprite,
    - * appropriate for a CSS value.
    - * @return {string} The y offset of the image being sprited within the sprite.
    - */
    -goog.ui.emoji.SpriteInfo.prototype.getYOffsetCssValue = function() {
    -  return goog.ui.emoji.SpriteInfo.getOffsetCssValue_(this.yOffset_);
    -};
    -
    -
    -/**
    - * Returns a string appropriate for use as a CSS value. If the value is zero,
    - * then there is no unit appended.
    - *
    - * @param {number|undefined} value A number to be turned into a
    - *     CSS size/location value.
    - * @return {string} A string appropriate for use as a CSS value.
    - * @private
    - */
    -goog.ui.emoji.SpriteInfo.getCssPixelValue_ = function(value) {
    -  return !value ? '0' : value + 'px';
    -};
    -
    -
    -/**
    - * Returns a string appropriate for use as a CSS value for a position offset,
    - * such as the position argument for sprites.
    - *
    - * @param {number|undefined} posOffset A positive offset for a position.
    - * @return {string} A string appropriate for use as a CSS value.
    - * @private
    - */
    -goog.ui.emoji.SpriteInfo.getOffsetCssValue_ = function(posOffset) {
    -  var offset = goog.ui.emoji.SpriteInfo.getCssPixelValue_(posOffset);
    -  return offset == '0' ? offset : '-' + offset;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/emoji/spriteinfo_test.html b/src/database/third_party/closure-library/closure/goog/ui/emoji/spriteinfo_test.html
    deleted file mode 100644
    index 0af1922cdf3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/emoji/spriteinfo_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.emoji.SpriteInfo
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.ui.emoji.SpriteInfoTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/emoji/spriteinfo_test.js b/src/database/third_party/closure-library/closure/goog/ui/emoji/spriteinfo_test.js
    deleted file mode 100644
    index c1a4e3c7170..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/emoji/spriteinfo_test.js
    +++ /dev/null
    @@ -1,45 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.emoji.SpriteInfoTest');
    -goog.setTestOnly('goog.ui.emoji.SpriteInfoTest');
    -
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.emoji.SpriteInfo');
    -function testGetCssValues() {
    -  var si = new goog.ui.emoji.SpriteInfo(null, 'im/s.png', 10, 10, 0, 128);
    -  assertEquals('10px', si.getWidthCssValue());
    -  assertEquals('10px', si.getHeightCssValue());
    -  assertEquals('0', si.getXOffsetCssValue());
    -  assertEquals('-128px', si.getYOffsetCssValue());
    -}
    -
    -function testIncompletelySpecifiedSpriteInfoFails() {
    -  assertThrows('CSS class can\'t be null if the rest of the metadata ' +
    -               'isn\'t specified', function() {
    -        new goog.ui.emoji.SpriteInfo(null)});
    -
    -  assertThrows('Can\'t create an incompletely specified sprite info',
    -      function() {
    -        new goog.ui.emoji.SpriteInfo(null, 's.png', 10);
    -      });
    -
    -  assertThrows('Can\'t create an incompletely specified sprite info',
    -      function() {
    -        new goog.ui.emoji.SpriteInfo(null, 's.png', 10, 10);
    -      });
    -
    -  assertThrows('Can\'t create an incompletely specified sprite info',
    -      function() {new goog.ui.emoji.SpriteInfo(null, 's.png', 10, 10, 0);});
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/filteredmenu.js b/src/database/third_party/closure-library/closure/goog/ui/filteredmenu.js
    deleted file mode 100644
    index a5e5fd142ec..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/filteredmenu.js
    +++ /dev/null
    @@ -1,633 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Menu where items can be filtered based on user keyboard input.
    - * If a filter is specified only the items matching it will be displayed.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - * @see ../demos/filteredmenu.html
    - */
    -
    -
    -goog.provide('goog.ui.FilteredMenu');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.AutoCompleteValues');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.InputHandler');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.object');
    -goog.require('goog.string');
    -goog.require('goog.style');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.FilterObservingMenuItem');
    -goog.require('goog.ui.Menu');
    -goog.require('goog.ui.MenuItem');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Filtered menu class.
    - * @param {goog.ui.MenuRenderer=} opt_renderer Renderer used to render filtered
    - *     menu; defaults to {@link goog.ui.MenuRenderer}.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @constructor
    - * @extends {goog.ui.Menu}
    - */
    -goog.ui.FilteredMenu = function(opt_renderer, opt_domHelper) {
    -  goog.ui.Menu.call(this, opt_domHelper, opt_renderer);
    -};
    -goog.inherits(goog.ui.FilteredMenu, goog.ui.Menu);
    -goog.tagUnsealableClass(goog.ui.FilteredMenu);
    -
    -
    -/**
    - * Events fired by component.
    - * @enum {string}
    - */
    -goog.ui.FilteredMenu.EventType = {
    -  /** Dispatched after the component filter criteria has been changed. */
    -  FILTER_CHANGED: 'filterchange'
    -};
    -
    -
    -/**
    - * Filter menu element ids.
    - * @enum {string}
    - * @private
    - */
    -goog.ui.FilteredMenu.Id_ = {
    -  CONTENT_ELEMENT: 'content-el'
    -};
    -
    -
    -/**
    - * Filter input element.
    - * @type {Element|undefined}
    - * @private
    - */
    -goog.ui.FilteredMenu.prototype.filterInput_;
    -
    -
    -/**
    - * The input handler that provides the input event.
    - * @type {goog.events.InputHandler|undefined}
    - * @private
    - */
    -goog.ui.FilteredMenu.prototype.inputHandler_;
    -
    -
    -/**
    - * Maximum number of characters for filter input.
    - * @type {number}
    - * @private
    - */
    -goog.ui.FilteredMenu.prototype.maxLength_ = 0;
    -
    -
    -/**
    - * Label displayed in the filter input when no text has been entered.
    - * @type {string}
    - * @private
    - */
    -goog.ui.FilteredMenu.prototype.label_ = '';
    -
    -
    -/**
    - * Label element.
    - * @type {Element|undefined}
    - * @private
    - */
    -goog.ui.FilteredMenu.prototype.labelEl_;
    -
    -
    -/**
    - * Whether multiple items can be entered comma separated.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.FilteredMenu.prototype.allowMultiple_ = false;
    -
    -
    -/**
    - * List of items entered in the search box if multiple entries are allowed.
    - * @type {Array<string>|undefined}
    - * @private
    - */
    -goog.ui.FilteredMenu.prototype.enteredItems_;
    -
    -
    -/**
    - * Index of first item that should be affected by the filter. Menu items with
    - * a lower index will not be affected by the filter.
    - * @type {number}
    - * @private
    - */
    -goog.ui.FilteredMenu.prototype.filterFromIndex_ = 0;
    -
    -
    -/**
    - * Filter applied to the menu.
    - * @type {string|undefined|null}
    - * @private
    - */
    -goog.ui.FilteredMenu.prototype.filterStr_;
    -
    -
    -/**
    - * @private {Element}
    - */
    -goog.ui.FilteredMenu.prototype.contentElement_;
    -
    -
    -/**
    - * Map of child nodes that shouldn't be affected by filtering.
    - * @type {Object|undefined}
    - * @private
    - */
    -goog.ui.FilteredMenu.prototype.persistentChildren_;
    -
    -
    -/** @override */
    -goog.ui.FilteredMenu.prototype.createDom = function() {
    -  goog.ui.FilteredMenu.superClass_.createDom.call(this);
    -
    -  var dom = this.getDomHelper();
    -  var el = dom.createDom('div',
    -      goog.getCssName(this.getRenderer().getCssClass(), 'filter'),
    -      this.labelEl_ = dom.createDom('div', null, this.label_),
    -      this.filterInput_ = dom.createDom('input', {'type': 'text'}));
    -  var element = this.getElement();
    -  dom.appendChild(element, el);
    -  var contentElementId = this.makeId(goog.ui.FilteredMenu.Id_.CONTENT_ELEMENT);
    -  this.contentElement_ = dom.createDom('div', goog.object.create(
    -      'class', goog.getCssName(this.getRenderer().getCssClass(), 'content'),
    -      'id', contentElementId));
    -  dom.appendChild(element, this.contentElement_);
    -
    -  this.initFilterInput_();
    -
    -  goog.a11y.aria.setState(this.filterInput_, goog.a11y.aria.State.AUTOCOMPLETE,
    -      goog.a11y.aria.AutoCompleteValues.LIST);
    -  goog.a11y.aria.setState(this.filterInput_, goog.a11y.aria.State.OWNS,
    -      contentElementId);
    -  goog.a11y.aria.setState(this.filterInput_, goog.a11y.aria.State.EXPANDED,
    -      true);
    -};
    -
    -
    -/**
    - * Helper method that initializes the filter input element.
    - * @private
    - */
    -goog.ui.FilteredMenu.prototype.initFilterInput_ = function() {
    -  this.setFocusable(true);
    -  this.setKeyEventTarget(this.filterInput_);
    -
    -  // Workaround for mozilla bug #236791.
    -  if (goog.userAgent.GECKO) {
    -    this.filterInput_.setAttribute('autocomplete', 'off');
    -  }
    -
    -  if (this.maxLength_) {
    -    this.filterInput_.maxLength = this.maxLength_;
    -  }
    -};
    -
    -
    -/**
    - * Sets up listeners and prepares the filter functionality.
    - * @private
    - */
    -goog.ui.FilteredMenu.prototype.setUpFilterListeners_ = function() {
    -  if (!this.inputHandler_ && this.filterInput_) {
    -    this.inputHandler_ = new goog.events.InputHandler(
    -        /** @type {Element} */ (this.filterInput_));
    -    goog.style.setUnselectable(this.filterInput_, false);
    -    goog.events.listen(this.inputHandler_,
    -                       goog.events.InputHandler.EventType.INPUT,
    -                       this.handleFilterEvent, false, this);
    -    goog.events.listen(this.filterInput_.parentNode,
    -                       goog.events.EventType.CLICK,
    -                       this.onFilterLabelClick_, false, this);
    -    if (this.allowMultiple_) {
    -      this.enteredItems_ = [];
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Tears down listeners and resets the filter functionality.
    - * @private
    - */
    -goog.ui.FilteredMenu.prototype.tearDownFilterListeners_ = function() {
    -  if (this.inputHandler_) {
    -    goog.events.unlisten(this.inputHandler_,
    -                         goog.events.InputHandler.EventType.INPUT,
    -                         this.handleFilterEvent, false, this);
    -    goog.events.unlisten(this.filterInput_.parentNode,
    -                         goog.events.EventType.CLICK,
    -                         this.onFilterLabelClick_, false, this);
    -
    -    this.inputHandler_.dispose();
    -    this.inputHandler_ = undefined;
    -    this.enteredItems_ = undefined;
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.FilteredMenu.prototype.setVisible = function(show, opt_force, opt_e) {
    -  var visibilityChanged = goog.ui.FilteredMenu.superClass_.setVisible.call(this,
    -      show, opt_force, opt_e);
    -  if (visibilityChanged && show && this.isInDocument()) {
    -    this.setFilter('');
    -    this.setUpFilterListeners_();
    -  } else if (visibilityChanged && !show) {
    -    this.tearDownFilterListeners_();
    -  }
    -
    -  return visibilityChanged;
    -};
    -
    -
    -/** @override */
    -goog.ui.FilteredMenu.prototype.disposeInternal = function() {
    -  this.tearDownFilterListeners_();
    -  this.filterInput_ = undefined;
    -  this.labelEl_ = undefined;
    -  goog.ui.FilteredMenu.superClass_.disposeInternal.call(this);
    -};
    -
    -
    -/**
    - * Sets the filter label (the label displayed in the filter input element if no
    - * text has been entered).
    - * @param {?string} label Label text.
    - */
    -goog.ui.FilteredMenu.prototype.setFilterLabel = function(label) {
    -  this.label_ = label || '';
    -  if (this.labelEl_) {
    -    goog.dom.setTextContent(this.labelEl_, this.label_);
    -  }
    -};
    -
    -
    -/**
    - * @return {string} The filter label.
    - */
    -goog.ui.FilteredMenu.prototype.getFilterLabel = function() {
    -  return this.label_;
    -};
    -
    -
    -/**
    - * Sets the filter string.
    - * @param {?string} str Filter string.
    - */
    -goog.ui.FilteredMenu.prototype.setFilter = function(str) {
    -  if (this.filterInput_) {
    -    this.filterInput_.value = str;
    -    this.filterItems_(str);
    -  }
    -};
    -
    -
    -/**
    - * Returns the filter string.
    - * @return {string} Current filter or an an empty string.
    - */
    -goog.ui.FilteredMenu.prototype.getFilter = function() {
    -  return this.filterInput_ && goog.isString(this.filterInput_.value) ?
    -      this.filterInput_.value : '';
    -};
    -
    -
    -/**
    - * Sets the index of first item that should be affected by the filter. Menu
    - * items with a lower index will not be affected by the filter.
    - * @param {number} index Index of first item that should be affected by filter.
    - */
    -goog.ui.FilteredMenu.prototype.setFilterFromIndex = function(index) {
    -  this.filterFromIndex_ = index;
    -};
    -
    -
    -/**
    - * Returns the index of first item that is affected by the filter.
    - * @return {number} Index of first item that is affected by filter.
    - */
    -goog.ui.FilteredMenu.prototype.getFilterFromIndex = function() {
    -  return this.filterFromIndex_;
    -};
    -
    -
    -/**
    - * Gets a list of items entered in the search box.
    - * @return {!Array<string>} The entered items.
    - */
    -goog.ui.FilteredMenu.prototype.getEnteredItems = function() {
    -  return this.enteredItems_ || [];
    -};
    -
    -
    -/**
    - * Sets whether multiple items can be entered comma separated.
    - * @param {boolean} b Whether multiple items can be entered.
    - */
    -goog.ui.FilteredMenu.prototype.setAllowMultiple = function(b) {
    -  this.allowMultiple_ = b;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether multiple items can be entered comma separated.
    - */
    -goog.ui.FilteredMenu.prototype.getAllowMultiple = function() {
    -  return this.allowMultiple_;
    -};
    -
    -
    -/**
    - * Sets whether the specified child should be affected (shown/hidden) by the
    - * filter criteria.
    - * @param {goog.ui.Component} child Child to change.
    - * @param {boolean} persistent Whether the child should be persistent.
    - */
    -goog.ui.FilteredMenu.prototype.setPersistentVisibility = function(child,
    -                                                                  persistent) {
    -  if (!this.persistentChildren_) {
    -    this.persistentChildren_ = {};
    -  }
    -  this.persistentChildren_[child.getId()] = persistent;
    -};
    -
    -
    -/**
    - * Returns whether the specified child should be affected (shown/hidden) by the
    - * filter criteria.
    - * @param {goog.ui.Component} child Menu item to check.
    - * @return {boolean} Whether the menu item is persistent.
    - */
    -goog.ui.FilteredMenu.prototype.hasPersistentVisibility = function(child) {
    -  return !!(this.persistentChildren_ &&
    -            this.persistentChildren_[child.getId()]);
    -};
    -
    -
    -/**
    - * Handles filter input events.
    - * @param {goog.events.BrowserEvent} e The event object.
    - */
    -goog.ui.FilteredMenu.prototype.handleFilterEvent = function(e) {
    -  this.filterItems_(this.filterInput_.value);
    -
    -  // Highlight the first visible item unless there's already a highlighted item.
    -  var highlighted = this.getHighlighted();
    -  if (!highlighted || !highlighted.isVisible()) {
    -    this.highlightFirst();
    -  }
    -  this.dispatchEvent(goog.ui.FilteredMenu.EventType.FILTER_CHANGED);
    -};
    -
    -
    -/**
    - * Shows/hides elements based on the supplied filter.
    - * @param {?string} str Filter string.
    - * @private
    - */
    -goog.ui.FilteredMenu.prototype.filterItems_ = function(str) {
    -  // Do nothing unless the filter string has changed.
    -  if (this.filterStr_ == str) {
    -    return;
    -  }
    -
    -  if (this.labelEl_) {
    -    this.labelEl_.style.visibility = str == '' ? 'visible' : 'hidden';
    -  }
    -
    -  if (this.allowMultiple_ && this.enteredItems_) {
    -    // Matches all non space characters after the last comma.
    -    var lastWordRegExp = /^(.+),[ ]*([^,]*)$/;
    -    var matches = str.match(lastWordRegExp);
    -    // matches[1] is the string up to, but not including, the last comma and
    -    // matches[2] the part after the last comma. If there are no non-space
    -    // characters after the last comma matches[2] is undefined.
    -    var items = matches && matches[1] ? matches[1].split(',') : [];
    -
    -    // If the number of comma separated items has changes recreate the
    -    // entered items array and fire a change event.
    -    if (str.substr(str.length - 1, 1) == ',' ||
    -        items.length != this.enteredItems_.length) {
    -      var lastItem = items[items.length - 1] || '';
    -
    -      // Auto complete text in input box based on the highlighted item.
    -      if (this.getHighlighted() && lastItem != '') {
    -        var caption = this.getHighlighted().getCaption();
    -        if (caption.toLowerCase().indexOf(lastItem.toLowerCase()) == 0) {
    -          items[items.length - 1] = caption;
    -          this.filterInput_.value = items.join(',') + ',';
    -        }
    -      }
    -      this.enteredItems_ = items;
    -      this.dispatchEvent(goog.ui.Component.EventType.CHANGE);
    -      this.setHighlightedIndex(-1);
    -    }
    -
    -    if (matches) {
    -      str = matches.length > 2 ? goog.string.trim(matches[2]) : '';
    -    }
    -  }
    -
    -  var matcher = new RegExp('(^|[- ,_/.:])' +
    -      goog.string.regExpEscape(str), 'i');
    -  for (var child, i = this.filterFromIndex_; child = this.getChildAt(i); i++) {
    -    if (child instanceof goog.ui.FilterObservingMenuItem) {
    -      child.callObserver(str);
    -    } else if (!this.hasPersistentVisibility(child)) {
    -      // Only show items matching the filter and highlight the part of the
    -      // caption that matches.
    -      var caption = child.getCaption();
    -      if (caption) {
    -        var matchArray = caption.match(matcher);
    -        if (str == '' || matchArray) {
    -          child.setVisible(true);
    -          var pos = caption.indexOf(matchArray[0]);
    -
    -          // If position is non zero increase by one to skip the separator.
    -          if (pos) {
    -            pos++;
    -          }
    -          this.boldContent_(child, pos, str.length);
    -        } else {
    -          child.setVisible(false);
    -        }
    -      } else {
    -
    -        // Hide separators and other items without a caption if a filter string
    -        // has been entered.
    -        child.setVisible(str == '');
    -      }
    -    }
    -  }
    -  this.filterStr_ = str;
    -};
    -
    -
    -/**
    - * Updates the content of the given menu item, bolding the part of its caption
    - * from start and through the next len characters.
    - * @param {!goog.ui.Control} child The control to bold content on.
    - * @param {number} start The index at which to start bolding.
    - * @param {number} len How many characters to bold.
    - * @private
    - */
    -goog.ui.FilteredMenu.prototype.boldContent_ = function(child, start, len) {
    -  var caption = child.getCaption();
    -  var boldedCaption;
    -  if (len == 0) {
    -    boldedCaption = this.getDomHelper().createTextNode(caption);
    -  } else {
    -    var preMatch = caption.substr(0, start);
    -    var match = caption.substr(start, len);
    -    var postMatch = caption.substr(start + len);
    -    boldedCaption = this.getDomHelper().createDom(
    -        'span',
    -        null,
    -        preMatch,
    -        this.getDomHelper().createDom('b', null, match),
    -        postMatch);
    -  }
    -  var accelerator = child.getAccelerator && child.getAccelerator();
    -  if (accelerator) {
    -    child.setContent([boldedCaption, this.getDomHelper().createDom('span',
    -        goog.ui.MenuItem.ACCELERATOR_CLASS, accelerator)]);
    -  } else {
    -    child.setContent(boldedCaption);
    -  }
    -};
    -
    -
    -/**
    - * Handles the menu's behavior for a key event. The highlighted menu item will
    - * be given the opportunity to handle the key behavior.
    - * @param {goog.events.KeyEvent} e A browser event.
    - * @return {boolean} Whether the event was handled.
    - * @override
    - */
    -goog.ui.FilteredMenu.prototype.handleKeyEventInternal = function(e) {
    -  // Home, end and the arrow keys are normally used to change the selected menu
    -  // item. Return false here to prevent the menu from preventing the default
    -  // behavior for HOME, END and any key press with a modifier.
    -  if (e.shiftKey || e.ctrlKey || e.altKey ||
    -      e.keyCode == goog.events.KeyCodes.HOME ||
    -      e.keyCode == goog.events.KeyCodes.END) {
    -    return false;
    -  }
    -
    -  if (e.keyCode == goog.events.KeyCodes.ESC) {
    -    this.dispatchEvent(goog.ui.Component.EventType.BLUR);
    -    return true;
    -  }
    -
    -  return goog.ui.FilteredMenu.superClass_.handleKeyEventInternal.call(this, e);
    -};
    -
    -
    -/**
    - * Sets the highlighted index, unless the HIGHLIGHT event is intercepted and
    - * cancelled.  -1 = no highlight. Also scrolls the menu item into view.
    - * @param {number} index Index of menu item to highlight.
    - * @override
    - */
    -goog.ui.FilteredMenu.prototype.setHighlightedIndex = function(index) {
    -  goog.ui.FilteredMenu.superClass_.setHighlightedIndex.call(this, index);
    -  var contentEl = this.getContentElement();
    -  var el = this.getHighlighted() ? this.getHighlighted().getElement() : null;
    -  if (this.filterInput_) {
    -    goog.a11y.aria.setActiveDescendant(this.filterInput_, el);
    -  }
    -
    -  if (el && goog.dom.contains(contentEl, el)) {
    -    var contentTop = goog.userAgent.IE && !goog.userAgent.isVersionOrHigher(8) ?
    -        0 : contentEl.offsetTop;
    -
    -    // IE (tested on IE8) sometime does not scroll enough by about
    -    // 1px. So we add 1px to the scroll amount. This still looks ok in
    -    // other browser except for the most degenerate case (menu height <=
    -    // item height).
    -
    -    // Scroll down if the highlighted item is below the bottom edge.
    -    var diff = (el.offsetTop + el.offsetHeight - contentTop) -
    -        (contentEl.clientHeight + contentEl.scrollTop) + 1;
    -    contentEl.scrollTop += Math.max(diff, 0);
    -
    -    // Scroll up if the highlighted item is above the top edge.
    -    diff = contentEl.scrollTop - (el.offsetTop - contentTop) + 1;
    -    contentEl.scrollTop -= Math.max(diff, 0);
    -  }
    -};
    -
    -
    -/**
    - * Handles clicks on the filter label. Focuses the input element.
    - * @param {goog.events.BrowserEvent} e A browser event.
    - * @private
    - */
    -goog.ui.FilteredMenu.prototype.onFilterLabelClick_ = function(e) {
    -  this.filterInput_.focus();
    -};
    -
    -
    -/** @override */
    -goog.ui.FilteredMenu.prototype.getContentElement = function() {
    -  return this.contentElement_ || this.getElement();
    -};
    -
    -
    -/**
    - * Returns the filter input element.
    - * @return {Element} Input element.
    - */
    -goog.ui.FilteredMenu.prototype.getFilterInputElement = function() {
    -  return this.filterInput_ || null;
    -};
    -
    -
    -/** @override */
    -goog.ui.FilteredMenu.prototype.decorateInternal = function(element) {
    -  this.setElementInternal(element);
    -
    -  // Decorate the menu content.
    -  this.decorateContent(element);
    -
    -  // Locate internally managed elements.
    -  var el = this.getDomHelper().getElementsByTagNameAndClass('div',
    -      goog.getCssName(this.getRenderer().getCssClass(), 'filter'), element)[0];
    -  this.labelEl_ = goog.dom.getFirstElementChild(el);
    -  this.filterInput_ = goog.dom.getNextElementSibling(this.labelEl_);
    -  this.contentElement_ = goog.dom.getNextElementSibling(el);
    -
    -  // Decorate additional menu items (like 'apply').
    -  this.getRenderer().decorateChildren(this, el.parentNode,
    -      this.contentElement_);
    -
    -  this.initFilterInput_();
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/filteredmenu_test.html b/src/database/third_party/closure-library/closure/goog/ui/filteredmenu_test.html
    deleted file mode 100644
    index 36ee121f6d4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/filteredmenu_test.html
    +++ /dev/null
    @@ -1,61 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -
    -  @author eae@google.com (Emil A Eklund)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.FilteredMenu
    -  </title>
    -  <style>
    -   .goog-menu {
    -  position: absolute;
    -  background: #eee;
    -  border: 1px solid #aaa;
    -  font: menu;
    -}
    -.goog-menu-content {
    -  height: 2em;
    -  overflow: auto;
    -}
    -
    -#testmenu {
    -  right: 5px;
    -  bottom: 5px;
    -}
    -  </style>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.FilteredMenuTest');
    -  </script>
    - </head>
    - <body>
    -  <div>
    -    <div id="wrapper">
    -      <div id="sandbox"></div>
    -    </div>
    -
    -    <div id="testmenu" class="goog-menu goog-menu-vertical">
    -      <div class="goog-menu-filter">
    -        <div></div>
    -        <input tabindex="0" autocomplete="off" type="text">
    -      </div>
    -      <div class="goog-menu-content">
    -        <div class="goog-menuitem">Apple<span class="goog-menuitem-accel">A</span></div>
    -        <div class="goog-menuitem">Lemon</div>
    -        <div class="goog-menuitem">Orange</div>
    -        <div class="goog-menuitem">Strawberry</div>
    -      </div>
    -    </div>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/filteredmenu_test.js b/src/database/third_party/closure-library/closure/goog/ui/filteredmenu_test.js
    deleted file mode 100644
    index 63a0de69cc3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/filteredmenu_test.js
    +++ /dev/null
    @@ -1,308 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.FilteredMenuTest');
    -goog.setTestOnly('goog.ui.FilteredMenuTest');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.AutoCompleteValues');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.math.Rect');
    -goog.require('goog.style');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.FilteredMenu');
    -goog.require('goog.ui.MenuItem');
    -
    -var sandbox;
    -
    -function setUp() {
    -  sandbox = goog.dom.getElement('sandbox');
    -}
    -
    -
    -function tearDown() {
    -  sandbox.innerHTML = '';
    -}
    -
    -
    -function testRender() {
    -  menu = new goog.ui.FilteredMenu();
    -  menu.addItem(new goog.ui.MenuItem('Menu Item 1'));
    -  menu.addItem(new goog.ui.MenuItem('Menu Item 2'));
    -  menu.render(sandbox);
    -
    -  assertEquals('Menu should contain two items.', 2, menu.getChildCount());
    -  assertEquals('Caption of first menu item should match supplied value.',
    -               'Menu Item 1',
    -               menu.getItemAt(0).getCaption());
    -  assertEquals('Caption of second menu item should match supplied value.',
    -               'Menu Item 2',
    -               menu.getItemAt(1).getCaption());
    -  assertTrue('Caption of first item should be in document.',
    -      sandbox.innerHTML.indexOf('Menu Item 1') != -1);
    -  assertTrue('Caption of second item should be in document.',
    -      sandbox.innerHTML.indexOf('Menu Item 2') != -1);
    -
    -  menu.dispose();
    -}
    -
    -
    -function testDecorate() {
    -  menu = new goog.ui.FilteredMenu();
    -  menu.decorate(goog.dom.getElement('testmenu'));
    -
    -  assertEquals('Menu should contain four items.', 4, menu.getChildCount());
    -  assertEquals('Caption of menu item should match decorated element',
    -               'Apple',
    -               menu.getItemAt(0).getCaption());
    -  assertEquals('Accelerator of menu item should match accelerator element',
    -               'A',
    -               menu.getItemAt(0).getAccelerator());
    -  assertEquals('Caption of menu item should match decorated element',
    -               'Lemon',
    -               menu.getItemAt(1).getCaption());
    -  assertEquals('Caption of menu item should match decorated element',
    -               'Orange',
    -               menu.getItemAt(2).getCaption());
    -  assertEquals('Caption of menu item should match decorated element',
    -               'Strawberry',
    -               menu.getItemAt(3).getCaption());
    -
    -  menu.dispose();
    -}
    -
    -
    -function testFilter() {
    -  menu = new goog.ui.FilteredMenu();
    -  menu.addItem(new goog.ui.MenuItem('Family'));
    -  menu.addItem(new goog.ui.MenuItem('Friends'));
    -  menu.addItem(new goog.ui.MenuItem('Photos'));
    -  menu.addItem(new goog.ui.MenuItem([
    -    goog.dom.createTextNode('Work'),
    -    goog.dom.createDom('span', goog.ui.MenuItem.ACCELERATOR_CLASS, 'W')
    -  ]));
    -
    -  menu.render(sandbox);
    -
    -  // Check menu items.
    -  assertEquals('Family should be the first label in the move to menu',
    -               'Family', menu.getChildAt(0).getCaption());
    -  assertEquals('Friends should be the second label in the move to menu',
    -               'Friends', menu.getChildAt(1).getCaption());
    -  assertEquals('Photos should be the third label in the move to menu',
    -               'Photos', menu.getChildAt(2).getCaption());
    -  assertEquals('Work should be the fourth label in the move to menu',
    -               'Work', menu.getChildAt(3).getCaption());
    -
    -  // Filter menu.
    -  menu.setFilter('W');
    -  assertFalse('Family should not be visible when the menu is filtered',
    -              menu.getChildAt(0).isVisible());
    -  assertFalse('Friends should not be visible when the menu is filtered',
    -              menu.getChildAt(1).isVisible());
    -  assertFalse('Photos should not be visible when the menu is filtered',
    -              menu.getChildAt(2).isVisible());
    -  assertTrue('Work should be visible when the menu is filtered',
    -             menu.getChildAt(3).isVisible());
    -  // Check accelerator.
    -  assertEquals('The accelerator for Work should be present',
    -               'W', menu.getChildAt(3).getAccelerator());
    -
    -  menu.setFilter('W,');
    -  for (var i = 0; i < menu.getChildCount(); i++) {
    -    assertFalse('W, should not match anything with allowMultiple set to false',
    -        menu.getChildAt(i).isVisible());
    -  }
    -
    -  // Clear filter.
    -  menu.setFilter('');
    -  for (var i = 0; i < menu.getChildCount(); i++) {
    -    assertTrue('All items should be visible', menu.getChildAt(i).isVisible());
    -  }
    -
    -  menu.dispose();
    -}
    -
    -
    -function testFilterAllowMultiple() {
    -  menu = new goog.ui.FilteredMenu();
    -  menu.setAllowMultiple(true);
    -  menu.addItem(new goog.ui.MenuItem('Family'));
    -  menu.addItem(new goog.ui.MenuItem('Friends'));
    -  menu.addItem(new goog.ui.MenuItem('Photos'));
    -  menu.addItem(new goog.ui.MenuItem('Work'));
    -
    -  menu.render(sandbox);
    -
    -  // Filter menu.
    -  menu.setFilter('W,');
    -  for (var i = 0; i < menu.getChildCount(); i++) {
    -    assertTrue('W, should show all items with allowMultiple set to true',
    -               menu.getChildAt(i).isVisible());
    -  }
    -
    -  // Filter second label.
    -  menu.setFilter('Work,P');
    -  assertFalse('Family should not be visible when the menu is filtered',
    -              menu.getChildAt(0).isVisible());
    -  assertFalse('Friends should not be visible when the menu is filtered',
    -              menu.getChildAt(1).isVisible());
    -  assertTrue('Photos should be visible when the menu is filtered',
    -             menu.getChildAt(2).isVisible());
    -  assertFalse('Work should not be visible when the menu is filtered',
    -              menu.getChildAt(3).isVisible());
    -
    -  // Clear filter.
    -  menu.setFilter('');
    -  for (var i = 0; i < menu.getChildCount(); i++) {
    -    assertTrue('All items should be visible', menu.getChildAt(i).isVisible());
    -  }
    -
    -  menu.dispose();
    -}
    -
    -
    -function testFilterWordBoundary() {
    -  menu = new goog.ui.FilteredMenu();
    -  menu.addItem(new goog.ui.MenuItem('Vacation Photos'));
    -  menu.addItem(new goog.ui.MenuItem('Work'));
    -  menu.addItem(new goog.ui.MenuItem('Receipts & Invoices'));
    -  menu.addItem(new goog.ui.MenuItem('Invitations'));
    -  menu.addItem(new goog.ui.MenuItem('3.Family'));
    -  menu.addItem(new goog.ui.MenuItem('No:Farm'));
    -  menu.addItem(new goog.ui.MenuItem('Syd/Family'));
    -
    -  menu.render(sandbox);
    -
    -  // Filter menu.
    -  menu.setFilter('Photos');
    -  assertTrue('Vacation Photos should be visible when the menu is filtered',
    -             menu.getChildAt(0).isVisible());
    -  assertFalse('Work should not be visible when the menu is filtered',
    -              menu.getChildAt(1).isVisible());
    -  assertFalse('Receipts & Invoices should not be visible when the menu is ' +
    -              'filtered',
    -              menu.getChildAt(2).isVisible());
    -  assertFalse('Invitations should not be visible when the menu is filtered',
    -              menu.getChildAt(3).isVisible());
    -
    -  menu.setFilter('I');
    -  assertFalse('Vacation Photos should not be visible when the menu is filtered',
    -      menu.getChildAt(0).isVisible());
    -  assertFalse('Work should not be visible when the menu is filtered',
    -              menu.getChildAt(1).isVisible());
    -  assertTrue('Receipts & Invoices should be visible when the menu is filtered',
    -             menu.getChildAt(2).isVisible());
    -  assertTrue('Invitations should be visible when the menu is filtered',
    -             menu.getChildAt(3).isVisible());
    -
    -  menu.setFilter('Fa');
    -  assertTrue('3.Family should be visible when the menu is filtered',
    -             menu.getChildAt(4).isVisible());
    -  assertTrue('No:Farm should be visible when the menu is filtered',
    -             menu.getChildAt(5).isVisible());
    -  assertTrue('Syd/Family should be visible when the menu is filtered',
    -             menu.getChildAt(6).isVisible());
    -
    -  menu.dispose();
    -}
    -
    -
    -function testScrollIntoView() {
    -  menu = new goog.ui.FilteredMenu();
    -  menu.addItem(new goog.ui.MenuItem('Family'));
    -  menu.addItem(new goog.ui.MenuItem('Friends'));
    -  menu.addItem(new goog.ui.MenuItem('Photos'));
    -  menu.addItem(new goog.ui.MenuItem('Work'));
    -  menu.render(sandbox);
    -
    -  menu.setHighlightedIndex(0);
    -  assertTrue('Highlighted item should be visible', isHighlightedVisible(menu));
    -  menu.setHighlightedIndex(1);
    -  assertTrue('Highlighted item should be visible', isHighlightedVisible(menu));
    -  menu.setHighlightedIndex(2);
    -  assertTrue('Highlighted item should be visible', isHighlightedVisible(menu));
    -  menu.setHighlightedIndex(3);
    -  assertTrue('Highlighted item should be visible', isHighlightedVisible(menu));
    -  menu.setHighlightedIndex(0);
    -  assertTrue('Highlighted item should be visible', isHighlightedVisible(menu));
    -
    -  menu.dispose();
    -}
    -
    -function testEscapeKeyHandling() {
    -  menu = new goog.ui.FilteredMenu();
    -  menu.addItem(new goog.ui.MenuItem('Family'));
    -  menu.addItem(new goog.ui.MenuItem('Friends'));
    -  menu.render(sandbox);
    -
    -  var gotKeyCode = false;
    -  var wrapper = document.getElementById('wrapper');
    -  goog.events.listenOnce(wrapper, goog.events.EventType.KEYPRESS, function(e) {
    -    gotKeyCode = true;
    -  });
    -  goog.testing.events.fireKeySequence(menu.getFilterInputElement(),
    -      goog.events.KeyCodes.ESC);
    -  assertFalse('ESC key should not propagate out to parent', gotKeyCode);
    -}
    -
    -
    -function testAriaRoles() {
    -  menu = new goog.ui.FilteredMenu();
    -  menu.addItem(new goog.ui.MenuItem('Item 1'));
    -  menu.render(sandbox);
    -
    -  var input = menu.getFilterInputElement();
    -  assertEquals(goog.a11y.aria.AutoCompleteValues.LIST,
    -      goog.a11y.aria.getState(input, goog.a11y.aria.State.AUTOCOMPLETE));
    -  assertEquals(menu.getContentElement().id,
    -      goog.a11y.aria.getState(input, goog.a11y.aria.State.OWNS));
    -  assertEquals('true',
    -      goog.a11y.aria.getState(input, goog.a11y.aria.State.EXPANDED));
    -}
    -
    -
    -function testInputActiveDecendant() {
    -  menu = new goog.ui.FilteredMenu();
    -  var menuItem1 = new goog.ui.MenuItem('Item 1');
    -  var menuItem2 = new goog.ui.MenuItem('Item 2');
    -  menu.addItem(menuItem1);
    -  menu.addItem(menuItem2);
    -  menu.render(sandbox);
    -
    -  assertNull(goog.a11y.aria.getActiveDescendant(menu.getFilterInputElement()));
    -  menu.setHighlightedIndex(0);
    -  assertEquals(menuItem1.getElementStrict(),
    -      goog.a11y.aria.getActiveDescendant(menu.getFilterInputElement()));
    -  menu.setHighlightedIndex(1);
    -  assertEquals(menuItem2.getElementStrict(),
    -      goog.a11y.aria.getActiveDescendant(menu.getFilterInputElement()));
    -}
    -
    -
    -function isHighlightedVisible(menu) {
    -  var contRect = goog.style.getBounds(menu.getContentElement());
    -  // Expands the containing rectangle by 1px on top and bottom. The test
    -  // sometime fails with 1px out of bound on FF6/Linux. This is not
    -  // consistently reproducible.
    -  contRect = new goog.math.Rect(
    -      contRect.left, contRect.top - 1, contRect.width, contRect.height + 2);
    -  var itemRect = goog.style.getBounds(menu.getHighlighted().getElement());
    -  return contRect.contains(itemRect);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/filterobservingmenuitem.js b/src/database/third_party/closure-library/closure/goog/ui/filterobservingmenuitem.js
    deleted file mode 100644
    index 2bee3f8474e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/filterobservingmenuitem.js
    +++ /dev/null
    @@ -1,98 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Menu item observing the filter text in a
    - * {@link goog.ui.FilteredMenu}. The observer method is called when the filter
    - * text changes and allows the menu item to update its content and state based
    - * on the filter.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - */
    -
    -goog.provide('goog.ui.FilterObservingMenuItem');
    -
    -goog.require('goog.ui.FilterObservingMenuItemRenderer');
    -goog.require('goog.ui.MenuItem');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * Class representing a filter observing menu item.
    - *
    - * @param {goog.ui.ControlContent} content Text caption or DOM structure to
    - *     display as the content of the item (use to add icons or styling to
    - *     menus).
    - * @param {*=} opt_model Data/model associated with the menu item.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper used for
    - *     document interactions.
    - * @param {goog.ui.MenuItemRenderer=} opt_renderer Optional renderer.
    - * @constructor
    - * @extends {goog.ui.MenuItem}
    - */
    -goog.ui.FilterObservingMenuItem = function(content, opt_model, opt_domHelper,
    -                                           opt_renderer) {
    -  goog.ui.MenuItem.call(this, content, opt_model, opt_domHelper,
    -      opt_renderer || new goog.ui.FilterObservingMenuItemRenderer());
    -};
    -goog.inherits(goog.ui.FilterObservingMenuItem, goog.ui.MenuItem);
    -goog.tagUnsealableClass(goog.ui.FilterObservingMenuItem);
    -
    -
    -/**
    - * Function called when the filter text changes.
    - * @type {Function} function(goog.ui.FilterObservingMenuItem, string)
    - * @private
    - */
    -goog.ui.FilterObservingMenuItem.prototype.observer_ = null;
    -
    -
    -/** @override */
    -goog.ui.FilterObservingMenuItem.prototype.enterDocument = function() {
    -  goog.ui.FilterObservingMenuItem.superClass_.enterDocument.call(this);
    -  this.callObserver();
    -};
    -
    -
    -/**
    - * Sets the observer functions.
    - * @param {Function} f function(goog.ui.FilterObservingMenuItem, string).
    - */
    -goog.ui.FilterObservingMenuItem.prototype.setObserver = function(f) {
    -  this.observer_ = f;
    -  this.callObserver();
    -};
    -
    -
    -/**
    - * Calls the observer function if one has been specified.
    - * @param {?string=} opt_str Filter string.
    - */
    -goog.ui.FilterObservingMenuItem.prototype.callObserver = function(opt_str) {
    -  if (this.observer_) {
    -    this.observer_(this, opt_str || '');
    -  }
    -};
    -
    -
    -// Register a decorator factory function for
    -// goog.ui.FilterObservingMenuItemRenderer.
    -goog.ui.registry.setDecoratorByClassName(
    -    goog.ui.FilterObservingMenuItemRenderer.CSS_CLASS,
    -    function() {
    -      // FilterObservingMenuItem defaults to using
    -      // FilterObservingMenuItemRenderer.
    -      return new goog.ui.FilterObservingMenuItem(null);
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/filterobservingmenuitemrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/filterobservingmenuitemrenderer.js
    deleted file mode 100644
    index 52894d295a3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/filterobservingmenuitemrenderer.js
    +++ /dev/null
    @@ -1,63 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Menu item observing the filter text in a
    - * {@link goog.ui.FilteredMenu}. The observer method is called when the filter
    - * text changes and allows the menu item to update its content and state based
    - * on the filter.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - */
    -
    -goog.provide('goog.ui.FilterObservingMenuItemRenderer');
    -
    -goog.require('goog.ui.MenuItemRenderer');
    -
    -
    -
    -/**
    - * Default renderer for {@link goog.ui.FilterObservingMenuItem}s. Each item has
    - * the following structure:
    - *    <div class="goog-filterobsmenuitem"><div>...(content)...</div></div>
    - *
    - * @constructor
    - * @extends {goog.ui.MenuItemRenderer}
    - * @final
    - */
    -goog.ui.FilterObservingMenuItemRenderer = function() {
    -  goog.ui.MenuItemRenderer.call(this);
    -};
    -goog.inherits(goog.ui.FilterObservingMenuItemRenderer,
    -              goog.ui.MenuItemRenderer);
    -goog.addSingletonGetter(goog.ui.FilterObservingMenuItemRenderer);
    -
    -
    -/**
    - * CSS class name the renderer applies to menu item elements.
    - * @type {string}
    - */
    -goog.ui.FilterObservingMenuItemRenderer.CSS_CLASS =
    -    goog.getCssName('goog-filterobsmenuitem');
    -
    -
    -/**
    - * Returns the CSS class to be applied to menu items rendered using this
    - * renderer.
    - * @return {string} Renderer-specific CSS class.
    - * @override
    - */
    -goog.ui.FilterObservingMenuItemRenderer.prototype.getCssClass = function() {
    -  return goog.ui.FilterObservingMenuItemRenderer.CSS_CLASS;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/flatbuttonrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/flatbuttonrenderer.js
    deleted file mode 100644
    index bb5b742fc11..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/flatbuttonrenderer.js
    +++ /dev/null
    @@ -1,147 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Similiar functionality of {@link goog.ui.ButtonRenderer},
    - * but uses a <div> element instead of a <button> or <input> element.
    - *
    - */
    -
    -goog.provide('goog.ui.FlatButtonRenderer');
    -
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.asserts');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.ui.Button');
    -goog.require('goog.ui.ButtonRenderer');
    -goog.require('goog.ui.INLINE_BLOCK_CLASSNAME');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * Flat renderer for {@link goog.ui.Button}s.  Flat buttons can contain
    - * almost arbitrary HTML content, will flow like inline elements, but can be
    - * styled like block-level elements.
    - * @constructor
    - * @extends {goog.ui.ButtonRenderer}
    - */
    -goog.ui.FlatButtonRenderer = function() {
    -  goog.ui.ButtonRenderer.call(this);
    -};
    -goog.inherits(goog.ui.FlatButtonRenderer, goog.ui.ButtonRenderer);
    -goog.addSingletonGetter(goog.ui.FlatButtonRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.FlatButtonRenderer.CSS_CLASS = goog.getCssName('goog-flat-button');
    -
    -
    -/**
    - * Returns the control's contents wrapped in a div element, with
    - * the renderer's own CSS class and additional state-specific classes applied
    - * to it, and the button's disabled attribute set or cleared as needed.
    - * Overrides {@link goog.ui.ButtonRenderer#createDom}.
    - * @param {goog.ui.Control} button Button to render.
    - * @return {!Element} Root element for the button.
    - * @override
    - */
    -goog.ui.FlatButtonRenderer.prototype.createDom = function(button) {
    -  var classNames = this.getClassNames(button);
    -  var attributes = {
    -    'class': goog.ui.INLINE_BLOCK_CLASSNAME + ' ' + classNames.join(' ')
    -  };
    -  var element = button.getDomHelper().createDom(
    -      'div', attributes, button.getContent());
    -  this.setTooltip(element, button.getTooltip());
    -  return element;
    -};
    -
    -
    -/**
    - * Returns the ARIA role to be applied to flat buttons.
    - * @return {goog.a11y.aria.Role|undefined} ARIA role.
    - * @override
    - */
    -goog.ui.FlatButtonRenderer.prototype.getAriaRole = function() {
    -  return goog.a11y.aria.Role.BUTTON;
    -};
    -
    -
    -/**
    - * Returns true if this renderer can decorate the element.  Overrides
    - * {@link goog.ui.ButtonRenderer#canDecorate} by returning true if the
    - * element is a DIV, false otherwise.
    - * @param {Element} element Element to decorate.
    - * @return {boolean} Whether the renderer can decorate the element.
    - * @override
    - */
    -goog.ui.FlatButtonRenderer.prototype.canDecorate = function(element) {
    -  return element.tagName == 'DIV';
    -};
    -
    -
    -/**
    - * Takes an existing element and decorates it with the flat button control.
    - * Initializes the control's ID, content, tooltip, value, and state based
    - * on the ID of the element, its child nodes, and its CSS classes, respectively.
    - * Returns the element.  Overrides {@link goog.ui.ButtonRenderer#decorate}.
    - * @param {goog.ui.Control} button Button instance to decorate the element.
    - * @param {Element} element Element to decorate.
    - * @return {Element} Decorated element.
    - * @override
    - */
    -goog.ui.FlatButtonRenderer.prototype.decorate = function(button, element) {
    -  goog.asserts.assert(element);
    -  goog.dom.classlist.add(element, goog.ui.INLINE_BLOCK_CLASSNAME);
    -  return goog.ui.FlatButtonRenderer.superClass_.decorate.call(this, button,
    -      element);
    -};
    -
    -
    -/**
    - * Flat buttons can't use the value attribute since they are div elements.
    - * Overrides {@link goog.ui.ButtonRenderer#getValue} to prevent trying to
    - * access the element's value.
    - * @param {Element} element The button control's root element.
    - * @return {string} Value not valid for flat buttons.
    - * @override
    - */
    -goog.ui.FlatButtonRenderer.prototype.getValue = function(element) {
    -  // Flat buttons don't store their value in the DOM.
    -  return '';
    -};
    -
    -
    -/**
    - * Returns the CSS class to be applied to the root element of components
    - * rendered using this renderer.
    - * @return {string} Renderer-specific CSS class.
    - * @override
    - */
    -goog.ui.FlatButtonRenderer.prototype.getCssClass = function() {
    -  return goog.ui.FlatButtonRenderer.CSS_CLASS;
    -};
    -
    -
    -// Register a decorator factory function for Flat Buttons.
    -goog.ui.registry.setDecoratorByClassName(goog.ui.FlatButtonRenderer.CSS_CLASS,
    -    function() {
    -      // Uses goog.ui.Button, but with FlatButtonRenderer.
    -      return new goog.ui.Button(null, goog.ui.FlatButtonRenderer.getInstance());
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/flatmenubuttonrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/flatmenubuttonrenderer.js
    deleted file mode 100644
    index a3455b85632..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/flatmenubuttonrenderer.js
    +++ /dev/null
    @@ -1,208 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Similiar functionality of {@link goog.ui.MenuButtonRenderer},
    - * but inherits from {@link goog.ui.FlatButtonRenderer} instead of
    - * {@link goog.ui.CustomButtonRenderer}. This creates a simpler menu button
    - * that will look more like a traditional <select> menu.
    - *
    - */
    -
    -goog.provide('goog.ui.FlatMenuButtonRenderer');
    -
    -goog.require('goog.dom');
    -goog.require('goog.style');
    -goog.require('goog.ui.FlatButtonRenderer');
    -goog.require('goog.ui.INLINE_BLOCK_CLASSNAME');
    -goog.require('goog.ui.Menu');
    -goog.require('goog.ui.MenuButton');
    -goog.require('goog.ui.MenuRenderer');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * Flat Menu Button renderer. Creates a simpler version of
    - * {@link goog.ui.MenuButton} that doesn't look like a button and
    - * doesn't have rounded corners. Uses just a <div> and looks more like
    - * a traditional <select> element.
    - * @constructor
    - * @extends {goog.ui.FlatButtonRenderer}
    - */
    -goog.ui.FlatMenuButtonRenderer = function() {
    -  goog.ui.FlatButtonRenderer.call(this);
    -};
    -goog.inherits(goog.ui.FlatMenuButtonRenderer, goog.ui.FlatButtonRenderer);
    -goog.addSingletonGetter(goog.ui.FlatMenuButtonRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.FlatMenuButtonRenderer.CSS_CLASS =
    -    goog.getCssName('goog-flat-menu-button');
    -
    -
    -/**
    - * Returns the button's contents wrapped in the following DOM structure:
    - *    <div class="goog-inline-block goog-flat-menu-button">
    - *        <div class="goog-inline-block goog-flat-menu-button-caption">
    - *          Contents...
    - *        </div>
    - *        <div class="goog-inline-block goog-flat-menu-button-dropdown">
    - *          &nbsp;
    - *        </div>
    - *    </div>
    - * Overrides {@link goog.ui.FlatButtonRenderer#createDom}.
    - * @param {goog.ui.Control} control Button to render.
    - * @return {!Element} Root element for the button.
    - * @override
    - */
    -goog.ui.FlatMenuButtonRenderer.prototype.createDom = function(control) {
    -  var button = /** @type {goog.ui.Button} */ (control);
    -  var classNames = this.getClassNames(button);
    -  var attributes = {
    -    'class': goog.ui.INLINE_BLOCK_CLASSNAME + ' ' + classNames.join(' ')
    -  };
    -  var element = button.getDomHelper().createDom('div', attributes,
    -      [this.createCaption(button.getContent(), button.getDomHelper()),
    -       this.createDropdown(button.getDomHelper())]);
    -  this.setTooltip(
    -      element, /** @type {!string}*/ (button.getTooltip()));
    -  return element;
    -};
    -
    -
    -/**
    - * Takes the button's root element and returns the parent element of the
    - * button's contents.
    - * @param {Element} element Root element of the button whose content
    - * element is to be returned.
    - * @return {Element} The button's content element (if any).
    - * @override
    - */
    -goog.ui.FlatMenuButtonRenderer.prototype.getContentElement = function(element) {
    -  return element && /** @type {Element} */ (element.firstChild);
    -};
    -
    -
    -/**
    - * Takes an element, decorates it with the menu button control, and returns
    - * the element.  Overrides {@link goog.ui.CustomButtonRenderer#decorate} by
    - * looking for a child element that can be decorated by a menu, and if it
    - * finds one, decorates it and attaches it to the menu button.
    - * @param {goog.ui.Control} button Menu button to decorate the element.
    - * @param {Element} element Element to decorate.
    - * @return {Element} Decorated element.
    - * @override
    - */
    -goog.ui.FlatMenuButtonRenderer.prototype.decorate = function(button, element) {
    -  // TODO(user): MenuButtonRenderer uses the exact same code.
    -  // Refactor this block to its own module where both can use it.
    -  var menuElem = goog.dom.getElementsByTagNameAndClass(
    -      '*', goog.ui.MenuRenderer.CSS_CLASS, element)[0];
    -  if (menuElem) {
    -    // Move the menu element directly under the body, but hide it first; see
    -    // bug 1089244.
    -    goog.style.setElementShown(menuElem, false);
    -    button.getDomHelper().getDocument().body.appendChild(menuElem);
    -
    -    // Decorate the menu and attach it to the button.
    -    var menu = new goog.ui.Menu();
    -    menu.decorate(menuElem);
    -    button.setMenu(menu);
    -  }
    -
    -  // Add the caption if it's not already there.
    -  var captionElem = goog.dom.getElementsByTagNameAndClass(
    -      '*', goog.getCssName(this.getCssClass(), 'caption'), element)[0];
    -  if (!captionElem) {
    -    element.appendChild(
    -        this.createCaption(element.childNodes, button.getDomHelper()));
    -  }
    -
    -  // Add the dropdown icon if it's not already there.
    -  var dropdownElem = goog.dom.getElementsByTagNameAndClass(
    -      '*', goog.getCssName(this.getCssClass(), 'dropdown'), element)[0];
    -  if (!dropdownElem) {
    -    element.appendChild(this.createDropdown(button.getDomHelper()));
    -  }
    -
    -  // Let the superclass do the rest.
    -  return goog.ui.FlatMenuButtonRenderer.superClass_.decorate.call(this, button,
    -      element);
    -};
    -
    -
    -/**
    - * Takes a text caption or existing DOM structure, and returns it wrapped in
    - * an appropriately-styled DIV.  Creates the following DOM structure:
    - *    <div class="goog-inline-block goog-flat-menu-button-caption">
    - *      Contents...
    - *    </div>
    - * @param {goog.ui.ControlContent} content Text caption or DOM structure to wrap
    - *     in a box.
    - * @param {goog.dom.DomHelper} dom DOM helper, used for document interaction.
    - * @return {Element} Caption element.
    - */
    -goog.ui.FlatMenuButtonRenderer.prototype.createCaption = function(content,
    -                                                                  dom) {
    -  return dom.createDom('div',
    -      goog.ui.INLINE_BLOCK_CLASSNAME + ' ' +
    -      goog.getCssName(this.getCssClass(), 'caption'), content);
    -};
    -
    -
    -/**
    - * Returns an appropriately-styled DIV containing a dropdown arrow element.
    - * Creates the following DOM structure:
    - *    <div class="goog-inline-block goog-flat-menu-button-dropdown">
    - *      &nbsp;
    - *    </div>
    - * @param {goog.dom.DomHelper} dom DOM helper, used for document interaction.
    - * @return {!Element} Dropdown element.
    - */
    -goog.ui.FlatMenuButtonRenderer.prototype.createDropdown = function(dom) {
    -  // 00A0 is &nbsp;
    -  return dom.createDom('div', {
    -    'class': goog.ui.INLINE_BLOCK_CLASSNAME + ' ' +
    -        goog.getCssName(this.getCssClass(), 'dropdown'),
    -    'aria-hidden': true
    -  }, '\u00A0');
    -};
    -
    -
    -/**
    - * Returns the CSS class to be applied to the root element of components
    - * rendered using this renderer.
    - * @return {string} Renderer-specific CSS class.
    - * @override
    - */
    -goog.ui.FlatMenuButtonRenderer.prototype.getCssClass = function() {
    -  return goog.ui.FlatMenuButtonRenderer.CSS_CLASS;
    -};
    -
    -
    -// Register a decorator factory function for Flat Menu Buttons.
    -goog.ui.registry.setDecoratorByClassName(
    -    goog.ui.FlatMenuButtonRenderer.CSS_CLASS,
    -    function() {
    -      // Uses goog.ui.MenuButton, but with FlatMenuButtonRenderer.
    -      return new goog.ui.MenuButton(null, null,
    -          goog.ui.FlatMenuButtonRenderer.getInstance());
    -    });
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/formpost.js b/src/database/third_party/closure-library/closure/goog/ui/formpost.js
    deleted file mode 100644
    index 1c7fa572809..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/formpost.js
    +++ /dev/null
    @@ -1,108 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Utility for making the browser submit a hidden form, which can
    - * be used to effect a POST from JavaScript.
    - *
    - */
    -
    -goog.provide('goog.ui.FormPost');
    -
    -goog.require('goog.array');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.dom.safe');
    -goog.require('goog.html.SafeHtml');
    -goog.require('goog.ui.Component');
    -
    -
    -
    -/**
    - * Creates a formpost object.
    - * @constructor
    - * @extends {goog.ui.Component}
    - * @param {goog.dom.DomHelper=} opt_dom The DOM helper.
    - * @final
    - */
    -goog.ui.FormPost = function(opt_dom) {
    -  goog.ui.Component.call(this, opt_dom);
    -};
    -goog.inherits(goog.ui.FormPost, goog.ui.Component);
    -
    -
    -/** @override */
    -goog.ui.FormPost.prototype.createDom = function() {
    -  this.setElementInternal(this.getDomHelper().createDom(goog.dom.TagName.FORM,
    -      {'method': 'POST', 'style': 'display:none'}));
    -};
    -
    -
    -/**
    - * Constructs a POST request and directs the browser as if a form were
    - * submitted.
    - * @param {Object} parameters Object with parameter values. Values can be
    - *     strings, numbers, or arrays of strings or numbers.
    - * @param {string=} opt_url The destination URL. If not specified, uses the
    - *     current URL for window for the DOM specified in the constructor.
    - * @param {string=} opt_target An optional name of a window in which to open the
    - *     URL. If not specified, uses the window for the DOM specified in the
    - *     constructor.
    - */
    -goog.ui.FormPost.prototype.post = function(parameters, opt_url, opt_target) {
    -  var form = this.getElement();
    -  if (!form) {
    -    this.render();
    -    form = this.getElement();
    -  }
    -  form.action = opt_url || '';
    -  form.target = opt_target || '';
    -  this.setParameters_(form, parameters);
    -  form.submit();
    -};
    -
    -
    -/**
    - * Creates hidden inputs in a form to match parameters.
    - * @param {!Element} form The form element.
    - * @param {Object} parameters Object with parameter values. Values can be
    - *     strings, numbers, or arrays of strings or numbers.
    - * @private
    - */
    -goog.ui.FormPost.prototype.setParameters_ = function(form, parameters) {
    -  var name, value, html = [];
    -  for (name in parameters) {
    -    value = parameters[name];
    -    if (goog.isArrayLike(value)) {
    -      goog.array.forEach(value, goog.bind(function(innerValue) {
    -        html.push(this.createInput_(name, String(innerValue)));
    -      }, this));
    -    } else {
    -      html.push(this.createInput_(name, String(value)));
    -    }
    -  }
    -  goog.dom.safe.setInnerHtml(form, goog.html.SafeHtml.concat(html));
    -};
    -
    -
    -/**
    - * Creates a hidden <input> tag.
    - * @param {string} name The name of the input.
    - * @param {string} value The value of the input.
    - * @return {!goog.html.SafeHtml}
    - * @private
    - */
    -goog.ui.FormPost.prototype.createInput_ = function(name, value) {
    -  return goog.html.SafeHtml.create('input',
    -      {'type': 'hidden', 'name': name, 'value': value});
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/formpost_test.html b/src/database/third_party/closure-library/closure/goog/ui/formpost_test.html
    deleted file mode 100644
    index 2a831ce555e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/formpost_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.FormPost
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.FormPostTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/formpost_test.js b/src/database/third_party/closure-library/closure/goog/ui/formpost_test.js
    deleted file mode 100644
    index a80246fc772..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/formpost_test.js
    +++ /dev/null
    @@ -1,109 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.FormPostTest');
    -goog.setTestOnly('goog.ui.FormPostTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.object');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.FormPost');
    -goog.require('goog.userAgent.product');
    -goog.require('goog.userAgent.product.isVersion');
    -
    -var TARGET = 'target';
    -var ACTION_URL = 'http://url/';
    -var formPost;
    -var parameters;
    -var submits;
    -var originalCreateDom = goog.ui.FormPost.prototype.createDom;
    -
    -function isChrome7or8() {
    -  // Temporarily disabled in Chrome 7 & 8. See b/3176768
    -  if (goog.userAgent.product.CHROME &&
    -      goog.userAgent.product.isVersion('7.0') &&
    -      !goog.userAgent.product.isVersion('8.0')) {
    -    return false;
    -  }
    -
    -  return true;
    -}
    -
    -function setUp() {
    -  formPost = new goog.ui.FormPost();
    -  submits = 0;
    -
    -  // Replace the form's submit method with a fake.
    -  goog.ui.FormPost.prototype.createDom = function() {
    -    originalCreateDom.apply(this, arguments);
    -
    -    this.getElement().submit = function() { submits++ };
    -  };
    -  parameters = {'foo': 'bar', 'baz': 1, 'array': [0, 'yes']};
    -}
    -
    -function tearDown() {
    -  formPost.dispose();
    -  goog.ui.FormPost.prototype.createDom = originalCreateDom;
    -}
    -
    -function testPost() {
    -  formPost.post(parameters, ACTION_URL, TARGET);
    -  expectUrlAndParameters_(ACTION_URL, TARGET, parameters);
    -}
    -
    -function testPostWithDefaults() {
    -  // Temporarily disabled in Chrome 7. See See b/3176768
    -  if (isChrome7or8) {
    -    return;
    -  }
    -  formPost = new goog.ui.FormPost();
    -  formPost.post(parameters);
    -  expectUrlAndParameters_('', '', parameters);
    -}
    -
    -function expectUrlAndParameters_(url, target, parameters) {
    -  var form = formPost.getElement();
    -  assertEquals('element must be a form',
    -      goog.dom.TagName.FORM, form.tagName);
    -  assertEquals('form must be hidden', 'none', form.style.display);
    -  assertEquals('form method must be POST',
    -      'POST', form.method.toUpperCase());
    -  assertEquals('submits', 1, submits);
    -  assertEquals('action attribute', url, form.action);
    -  assertEquals('target attribute', target, form.target);
    -  var inputs = goog.dom.getElementsByTagNameAndClass(
    -      goog.dom.TagName.INPUT, null, form);
    -  var formValues = {};
    -  for (var i = 0, input = inputs[i]; input = inputs[i]; i++) {
    -    if (goog.isArray(formValues[input.name])) {
    -      formValues[input.name].push(input.value);
    -    } else if (input.name in formValues) {
    -      formValues[input.name] = [formValues[input.name], input.value];
    -    } else {
    -      formValues[input.name] = input.value;
    -    }
    -  }
    -  var expected = goog.object.map(parameters, valueToString);
    -  assertObjectEquals('form values must match', expected, formValues);
    -}
    -
    -function valueToString(value) {
    -  if (goog.isArray(value)) {
    -    return goog.array.map(value, valueToString);
    -  }
    -  return String(value);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/gauge.js b/src/database/third_party/closure-library/closure/goog/ui/gauge.js
    deleted file mode 100644
    index 80ceecfbcb7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/gauge.js
    +++ /dev/null
    @@ -1,1012 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Gauge UI component, using browser vector graphics.
    - * @see ../demos/gauge.html
    - */
    -
    -
    -goog.provide('goog.ui.Gauge');
    -goog.provide('goog.ui.GaugeColoredRange');
    -
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.asserts');
    -goog.require('goog.events');
    -goog.require('goog.fx.Animation');
    -goog.require('goog.fx.Transition');
    -goog.require('goog.fx.easing');
    -goog.require('goog.graphics');
    -goog.require('goog.graphics.Font');
    -goog.require('goog.graphics.Path');
    -goog.require('goog.graphics.SolidFill');
    -goog.require('goog.math');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.GaugeTheme');
    -
    -
    -
    -/**
    - * Information on how to decorate a range in the gauge.
    - * This is an internal-only class.
    - * @param {number} fromValue The range start (minimal) value.
    - * @param {number} toValue The range end (maximal) value.
    - * @param {string} backgroundColor Color to fill the range background with.
    - * @constructor
    - * @final
    - */
    -goog.ui.GaugeColoredRange = function(fromValue, toValue, backgroundColor) {
    -
    -  /**
    -   * The range start (minimal) value.
    -   * @type {number}
    -   */
    -  this.fromValue = fromValue;
    -
    -
    -  /**
    -   * The range end (maximal) value.
    -   * @type {number}
    -   */
    -  this.toValue = toValue;
    -
    -
    -  /**
    -   * Color to fill the range background with.
    -   * @type {string}
    -   */
    -  this.backgroundColor = backgroundColor;
    -};
    -
    -
    -
    -/**
    - * A UI component that displays a gauge.
    - * A gauge displayes a current value within a round axis that represents a
    - * given range.
    - * The gauge is built from an external border, and internal border inside it,
    - * ticks and labels inside the internal border, and a needle that points to
    - * the current value.
    - * @param {number} width The width in pixels.
    - * @param {number} height The height in pixels.
    - * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper object for the
    - *     document we want to render in.
    - * @constructor
    - * @extends {goog.ui.Component}
    - * @final
    - */
    -goog.ui.Gauge = function(width, height, opt_domHelper) {
    -  goog.ui.Component.call(this, opt_domHelper);
    -
    -  /**
    -   * The width in pixels of this component.
    -   * @type {number}
    -   * @private
    -   */
    -  this.width_ = width;
    -
    -
    -  /**
    -   * The height in pixels of this component.
    -   * @type {number}
    -   * @private
    -   */
    -  this.height_ = height;
    -
    -
    -  /**
    -   * The underlying graphics.
    -   * @type {goog.graphics.AbstractGraphics}
    -   * @private
    -   */
    -  this.graphics_ = goog.graphics.createGraphics(width, height,
    -      null, null, opt_domHelper);
    -
    -
    -  /**
    -   * Colors to paint the background of certain ranges (optional).
    -   * @type {Array<goog.ui.GaugeColoredRange>}
    -   * @private
    -   */
    -  this.rangeColors_ = [];
    -};
    -goog.inherits(goog.ui.Gauge, goog.ui.Component);
    -
    -
    -/**
    - * Constant for a background color for a gauge area.
    - */
    -goog.ui.Gauge.RED = '#ffc0c0';
    -
    -
    -/**
    - * Constant for a background color for a gauge area.
    - */
    -goog.ui.Gauge.GREEN = '#c0ffc0';
    -
    -
    -/**
    - * Constant for a background color for a gauge area.
    - */
    -goog.ui.Gauge.YELLOW = '#ffffa0';
    -
    -
    -/**
    - * The radius of the entire gauge from the canvas size.
    - * @type {number}
    - */
    -goog.ui.Gauge.FACTOR_RADIUS_FROM_SIZE = 0.45;
    -
    -
    -/**
    - * The ratio of internal gauge radius from entire radius.
    - * The remaining area is the border around the gauge.
    - * @type {number}
    - */
    -goog.ui.Gauge.FACTOR_MAIN_AREA = 0.9;
    -
    -
    -/**
    - * The ratio of the colored background area for value ranges.
    - * The colored area width is computed as
    - * InternalRadius * (1 - FACTOR_COLOR_RADIUS)
    - * @type {number}
    - */
    -goog.ui.Gauge.FACTOR_COLOR_RADIUS = 0.75;
    -
    -
    -/**
    - * The ratio of the major ticks length start position, from the radius.
    - * The major ticks length width is computed as
    - * InternalRadius * (1 - FACTOR_MAJOR_TICKS)
    - * @type {number}
    - */
    -goog.ui.Gauge.FACTOR_MAJOR_TICKS = 0.8;
    -
    -
    -/**
    - * The ratio of the minor ticks length start position, from the radius.
    - * The minor ticks length width is computed as
    - * InternalRadius * (1 - FACTOR_MINOR_TICKS)
    - * @type {number}
    - */
    -goog.ui.Gauge.FACTOR_MINOR_TICKS = 0.9;
    -
    -
    -/**
    - * The length of the needle front (value facing) from the internal radius.
    - * The needle front is the part of the needle that points to the value.
    - * @type {number}
    - */
    -goog.ui.Gauge.FACTOR_NEEDLE_FRONT = 0.95;
    -
    -
    -/**
    - * The length of the needle back relative to the internal radius.
    - * The needle back is the part of the needle that points away from the value.
    - * @type {number}
    - */
    -goog.ui.Gauge.FACTOR_NEEDLE_BACK = 0.3;
    -
    -
    -/**
    - * The width of the needle front at the hinge.
    - * This is the width of the curve control point, the actual width is
    - * computed by the curve itself.
    - * @type {number}
    - */
    -goog.ui.Gauge.FACTOR_NEEDLE_WIDTH = 0.07;
    -
    -
    -/**
    - * The width (radius) of the needle hinge from the gauge radius.
    - * @type {number}
    - */
    -goog.ui.Gauge.FACTOR_NEEDLE_HINGE = 0.15;
    -
    -
    -/**
    - * The title font size (height) for titles relative to the internal radius.
    - * @type {number}
    - */
    -goog.ui.Gauge.FACTOR_TITLE_FONT_SIZE = 0.16;
    -
    -
    -/**
    - * The offset of the title from the center, relative to the internal radius.
    - * @type {number}
    - */
    -goog.ui.Gauge.FACTOR_TITLE_OFFSET = 0.35;
    -
    -
    -/**
    - * The formatted value font size (height) relative to the internal radius.
    - * @type {number}
    - */
    -goog.ui.Gauge.FACTOR_VALUE_FONT_SIZE = 0.18;
    -
    -
    -/**
    - * The title font size (height) for tick labels relative to the internal radius.
    - * @type {number}
    - */
    -goog.ui.Gauge.FACTOR_TICK_LABEL_FONT_SIZE = 0.14;
    -
    -
    -/**
    - * The offset of the formatted value down from the center, relative to the
    - * internal radius.
    - * @type {number}
    - */
    -goog.ui.Gauge.FACTOR_VALUE_OFFSET = 0.75;
    -
    -
    -/**
    - * The font name for title text.
    - * @type {string}
    - */
    -goog.ui.Gauge.TITLE_FONT_NAME = 'arial';
    -
    -
    -/**
    - * The maximal size of a step the needle can move (percent from size of range).
    - * If the needle needs to move more, it will be moved in animated steps, to
    - * show a smooth transition between values.
    - * @type {number}
    - */
    -goog.ui.Gauge.NEEDLE_MOVE_MAX_STEP = 0.02;
    -
    -
    -/**
    - * Time in miliseconds for animating a move of the value pointer.
    - * @type {number}
    - */
    -goog.ui.Gauge.NEEDLE_MOVE_TIME = 400;
    -
    -
    -/**
    - * Tolerance factor for how much values can exceed the range (being too
    - * low or too high). The value is presented as a position (percentage).
    - * @type {number}
    - */
    -goog.ui.Gauge.MAX_EXCEED_POSITION_POSITION = 0.02;
    -
    -
    -/**
    - * The minimal value that can be displayed.
    - * @private
    - * @type {number}
    - */
    -goog.ui.Gauge.prototype.minValue_ = 0;
    -
    -
    -/**
    - * The maximal value that can be displayed.
    - * @private
    - * @type {number}
    - */
    -goog.ui.Gauge.prototype.maxValue_ = 100;
    -
    -
    -/**
    - * The number of major tick sections.
    - * @private
    - * @type {number}
    - */
    -goog.ui.Gauge.prototype.majorTicks_ = 5;
    -
    -
    -/**
    - * The number of minor tick sections in each major tick section.
    - * @private
    - * @type {number}
    - */
    -goog.ui.Gauge.prototype.minorTicks_ = 2;
    -
    -
    -/**
    - * The current value that needs to be displayed in the gauge.
    - * @private
    - * @type {number}
    - */
    -goog.ui.Gauge.prototype.value_ = 0;
    -
    -
    -/**
    - * The current value formatted into a String.
    - * @private
    - * @type {?string}
    - */
    -goog.ui.Gauge.prototype.formattedValue_ = null;
    -
    -
    -/**
    - * The current colors theme.
    - * @private
    - * @type {goog.ui.GaugeTheme?}
    - */
    -goog.ui.Gauge.prototype.theme_ = null;
    -
    -
    -/**
    - * Title to display above the gauge center.
    - * @private
    - * @type {?string}
    - */
    -goog.ui.Gauge.prototype.titleTop_ = null;
    -
    -
    -/**
    - * Title to display below the gauge center.
    - * @private
    - * @type {?string}
    - */
    -goog.ui.Gauge.prototype.titleBottom_ = null;
    -
    -
    -/**
    - * Font to use for drawing titles.
    - * If null (default), computed dynamically with a size relative to the
    - * gauge radius.
    - * @private
    - * @type {goog.graphics.Font?}
    - */
    -goog.ui.Gauge.prototype.titleFont_ = null;
    -
    -
    -/**
    - * Font to use for drawing the formatted value.
    - * If null (default), computed dynamically with a size relative to the
    - * gauge radius.
    - * @private
    - * @type {goog.graphics.Font?}
    - */
    -goog.ui.Gauge.prototype.valueFont_ = null;
    -
    -
    -/**
    - * Font to use for drawing tick labels.
    - * If null (default), computed dynamically with a size relative to the
    - * gauge radius.
    - * @private
    - * @type {goog.graphics.Font?}
    - */
    -goog.ui.Gauge.prototype.tickLabelFont_ = null;
    -
    -
    -/**
    - * The size in angles of the gauge axis area.
    - * @private
    - * @type {number}
    - */
    -goog.ui.Gauge.prototype.angleSpan_ = 270;
    -
    -
    -/**
    - * The radius for drawing the needle.
    - * Computed on full redraw, and used on every animation step of moving
    - * the needle.
    - * @type {number}
    - * @private
    - */
    -goog.ui.Gauge.prototype.needleRadius_ = 0;
    -
    -
    -/**
    - * The group elemnt of the needle. Contains all elements that change when the
    - * gauge value changes.
    - * @type {goog.graphics.GroupElement?}
    - * @private
    - */
    -goog.ui.Gauge.prototype.needleGroup_ = null;
    -
    -
    -/**
    - * The current position (0-1) of the visible needle.
    - * Initially set to null to prevent animation on first opening of the gauge.
    - * @type {?number}
    - * @private
    - */
    -goog.ui.Gauge.prototype.needleValuePosition_ = null;
    -
    -
    -/**
    - * Text labels to display by major tick marks.
    - * @type {Array<string>?}
    - * @private
    - */
    -goog.ui.Gauge.prototype.majorTickLabels_ = null;
    -
    -
    -/**
    - * Animation object while needle is being moved (animated).
    - * @type {goog.fx.Animation?}
    - * @private
    - */
    -goog.ui.Gauge.prototype.animation_ = null;
    -
    -
    -/**
    - * @return {number} The minimum value of the range.
    - */
    -goog.ui.Gauge.prototype.getMinimum = function() {
    -  return this.minValue_;
    -};
    -
    -
    -/**
    - * Sets the minimum value of the range
    - * @param {number} min The minimum value of the range.
    - */
    -goog.ui.Gauge.prototype.setMinimum = function(min) {
    -  this.minValue_ = min;
    -  var element = this.getElement();
    -  if (element) {
    -    goog.a11y.aria.setState(element, 'valuemin', min);
    -  }
    -};
    -
    -
    -/**
    - * @return {number} The maximum value of the range.
    - */
    -goog.ui.Gauge.prototype.getMaximum = function() {
    -  return this.maxValue_;
    -};
    -
    -
    -/**
    - * Sets the maximum number of the range
    - * @param {number} max The maximum value of the range.
    - */
    -goog.ui.Gauge.prototype.setMaximum = function(max) {
    -  this.maxValue_ = max;
    -
    -  var element = this.getElement();
    -  if (element) {
    -    goog.a11y.aria.setState(element, 'valuemax', max);
    -  }
    -};
    -
    -
    -/**
    - * Sets the current value range displayed by the gauge.
    - * @param {number} value The current value for the gauge. This value
    - *     determines the position of the needle of the gauge.
    - * @param {string=} opt_formattedValue The string value to show in the gauge.
    - *     If not specified, no string value will be displayed.
    - */
    -goog.ui.Gauge.prototype.setValue = function(value, opt_formattedValue) {
    -  this.value_ = value;
    -  this.formattedValue_ = opt_formattedValue || null;
    -
    -  this.stopAnimation_(); // Stop the active animation if exists
    -
    -  // Compute desired value position (normalize value to range 0-1)
    -  var valuePosition = this.valueToRangePosition_(value);
    -  if (this.needleValuePosition_ == null) {
    -    // No animation on initial display
    -    this.needleValuePosition_ = valuePosition;
    -    this.drawValue_();
    -  } else {
    -    // Animate move
    -    this.animation_ = new goog.fx.Animation([this.needleValuePosition_],
    -        [valuePosition],
    -        goog.ui.Gauge.NEEDLE_MOVE_TIME,
    -        goog.fx.easing.inAndOut);
    -
    -    var events = [goog.fx.Transition.EventType.BEGIN,
    -                  goog.fx.Animation.EventType.ANIMATE,
    -                  goog.fx.Transition.EventType.END];
    -    goog.events.listen(this.animation_, events, this.onAnimate_, false, this);
    -    goog.events.listen(this.animation_, goog.fx.Transition.EventType.END,
    -        this.onAnimateEnd_, false, this);
    -
    -    // Start animation
    -    this.animation_.play(false);
    -  }
    -
    -  var element = this.getElement();
    -  if (element) {
    -    goog.a11y.aria.setState(element, 'valuenow', this.value_);
    -  }
    -};
    -
    -
    -/**
    - * Sets the number of major tick sections and minor tick sections.
    - * @param {number} majorUnits The number of major tick sections.
    - * @param {number} minorUnits The number of minor tick sections for each major
    - *     tick section.
    - */
    -goog.ui.Gauge.prototype.setTicks = function(majorUnits, minorUnits) {
    -  this.majorTicks_ = Math.max(1, majorUnits);
    -  this.minorTicks_ = Math.max(1, minorUnits);
    -  this.draw_();
    -};
    -
    -
    -/**
    - * Sets the labels of the major ticks.
    - * @param {Array<string>} tickLabels A text label for each major tick value.
    - */
    -goog.ui.Gauge.prototype.setMajorTickLabels = function(tickLabels) {
    -  this.majorTickLabels_ = tickLabels;
    -  this.draw_();
    -};
    -
    -
    -/**
    - * Sets the top title of the gauge.
    - * The top title is displayed above the center.
    - * @param {string} text The top title text.
    - */
    -goog.ui.Gauge.prototype.setTitleTop = function(text) {
    -  this.titleTop_ = text;
    -  this.draw_();
    -};
    -
    -
    -/**
    - * Sets the bottom title of the gauge.
    - * The top title is displayed below the center.
    - * @param {string} text The bottom title text.
    - */
    -goog.ui.Gauge.prototype.setTitleBottom = function(text) {
    -  this.titleBottom_ = text;
    -  this.draw_();
    -};
    -
    -
    -/**
    - * Sets the font for displaying top and bottom titles.
    - * @param {goog.graphics.Font} font The font for titles.
    - */
    -goog.ui.Gauge.prototype.setTitleFont = function(font) {
    -  this.titleFont_ = font;
    -  this.draw_();
    -};
    -
    -
    -/**
    - * Sets the font for displaying the formatted value.
    - * @param {goog.graphics.Font} font The font for displaying the value.
    - */
    -goog.ui.Gauge.prototype.setValueFont = function(font) {
    -  this.valueFont_ = font;
    -  this.drawValue_();
    -};
    -
    -
    -/**
    - * Sets the color theme for drawing the gauge.
    - * @param {goog.ui.GaugeTheme} theme The color theme to use.
    - */
    -goog.ui.Gauge.prototype.setTheme = function(theme) {
    -  this.theme_ = theme;
    -  this.draw_();
    -};
    -
    -
    -/**
    - * Set the background color for a range of values on the gauge.
    - * @param {number} fromValue The lower (start) value of the colored range.
    - * @param {number} toValue The higher (end) value of the colored range.
    - * @param {string} color The color name to paint the range with. For example
    - *     'red', '#ffcc00' or constants like goog.ui.Gauge.RED.
    - */
    -goog.ui.Gauge.prototype.addBackgroundColor = function(fromValue, toValue,
    -    color) {
    -  this.rangeColors_.push(
    -      new goog.ui.GaugeColoredRange(fromValue, toValue, color));
    -  this.draw_();
    -};
    -
    -
    -/**
    - * Creates the DOM representation of the graphics area.
    - * @override
    - */
    -goog.ui.Gauge.prototype.createDom = function() {
    -  this.setElementInternal(this.getDomHelper().createDom(
    -      'div', goog.getCssName('goog-gauge'), this.graphics_.getElement()));
    -};
    -
    -
    -/**
    - * Clears the entire graphics area.
    - * @private
    - */
    -goog.ui.Gauge.prototype.clear_ = function() {
    -  this.graphics_.clear();
    -  this.needleGroup_ = null;
    -};
    -
    -
    -/**
    - * Redraw the entire gauge.
    - * @private
    - */
    -goog.ui.Gauge.prototype.draw_ = function() {
    -  if (!this.isInDocument()) {
    -    return;
    -  }
    -
    -  this.clear_();
    -
    -  var x, y;
    -  var size = Math.min(this.width_, this.height_);
    -  var r = Math.round(goog.ui.Gauge.FACTOR_RADIUS_FROM_SIZE * size);
    -  var cx = this.width_ / 2;
    -  var cy = this.height_ / 2;
    -
    -  var theme = this.theme_;
    -  if (!theme) {
    -    // Lazy allocation of default theme, common to all instances
    -    theme = goog.ui.Gauge.prototype.theme_ = new goog.ui.GaugeTheme();
    -  }
    -
    -  // Draw main circle frame around gauge
    -  var graphics = this.graphics_;
    -  var stroke = this.theme_.getExternalBorderStroke();
    -  var fill = theme.getExternalBorderFill(cx, cy, r);
    -  graphics.drawCircle(cx, cy, r, stroke, fill);
    -
    -  r -= stroke.getWidth();
    -  r = Math.round(r * goog.ui.Gauge.FACTOR_MAIN_AREA);
    -  stroke = theme.getInternalBorderStroke();
    -  fill = theme.getInternalBorderFill(cx, cy, r);
    -  graphics.drawCircle(cx, cy, r, stroke, fill);
    -  r -= stroke.getWidth() * 2;
    -
    -  // Draw Background with external and internal borders
    -  var rBackgroundInternal = r * goog.ui.Gauge.FACTOR_COLOR_RADIUS;
    -  for (var i = 0; i < this.rangeColors_.length; i++) {
    -    var rangeColor = this.rangeColors_[i];
    -    var fromValue = rangeColor.fromValue;
    -    var toValue = rangeColor.toValue;
    -    var path = new goog.graphics.Path();
    -    var fromAngle = this.valueToAngle_(fromValue);
    -    var toAngle = this.valueToAngle_(toValue);
    -    // Move to outer point at "from" angle
    -    path.moveTo(
    -        cx + goog.math.angleDx(fromAngle, r),
    -        cy + goog.math.angleDy(fromAngle, r));
    -    // Arc to outer point at "to" angle
    -    path.arcTo(r, r, fromAngle, toAngle - fromAngle);
    -    // Line to inner point at "to" angle
    -    path.lineTo(
    -        cx + goog.math.angleDx(toAngle, rBackgroundInternal),
    -        cy + goog.math.angleDy(toAngle, rBackgroundInternal));
    -    // Arc to inner point at "from" angle
    -    path.arcTo(
    -        rBackgroundInternal, rBackgroundInternal, toAngle, fromAngle - toAngle);
    -    path.close();
    -    fill = new goog.graphics.SolidFill(rangeColor.backgroundColor);
    -    graphics.drawPath(path, null, fill);
    -  }
    -
    -  // Draw titles
    -  if (this.titleTop_ || this.titleBottom_) {
    -    var font = this.titleFont_;
    -    if (!font) {
    -      // Lazy creation of font
    -      var fontSize =
    -          Math.round(r * goog.ui.Gauge.FACTOR_TITLE_FONT_SIZE);
    -      font = new goog.graphics.Font(
    -          fontSize, goog.ui.Gauge.TITLE_FONT_NAME);
    -      this.titleFont_ = font;
    -    }
    -    fill = new goog.graphics.SolidFill(theme.getTitleColor());
    -    if (this.titleTop_) {
    -      y = cy - Math.round(r * goog.ui.Gauge.FACTOR_TITLE_OFFSET);
    -      graphics.drawTextOnLine(this.titleTop_, 0, y, this.width_, y,
    -          'center', font, null, fill);
    -    }
    -    if (this.titleBottom_) {
    -      y = cy + Math.round(r * goog.ui.Gauge.FACTOR_TITLE_OFFSET);
    -      graphics.drawTextOnLine(this.titleBottom_, 0, y, this.width_, y,
    -          'center', font, null, fill);
    -    }
    -  }
    -
    -  // Draw tick marks
    -  var majorTicks = this.majorTicks_;
    -  var minorTicks = this.minorTicks_;
    -  var rMajorTickInternal = r * goog.ui.Gauge.FACTOR_MAJOR_TICKS;
    -  var rMinorTickInternal = r * goog.ui.Gauge.FACTOR_MINOR_TICKS;
    -  var ticks = majorTicks * minorTicks;
    -  var valueRange = this.maxValue_ - this.minValue_;
    -  var tickValueSpan = valueRange / ticks;
    -  var majorTicksPath = new goog.graphics.Path();
    -  var minorTicksPath = new goog.graphics.Path();
    -
    -  var tickLabelFill = new goog.graphics.SolidFill(theme.getTickLabelColor());
    -  var tickLabelFont = this.tickLabelFont_;
    -  if (!tickLabelFont) {
    -    tickLabelFont = new goog.graphics.Font(
    -        Math.round(r * goog.ui.Gauge.FACTOR_TICK_LABEL_FONT_SIZE),
    -        goog.ui.Gauge.TITLE_FONT_NAME);
    -  }
    -  var tickLabelFontSize = tickLabelFont.size;
    -
    -  for (var i = 0; i <= ticks; i++) {
    -    var angle = this.valueToAngle_(i * tickValueSpan + this.minValue_);
    -    var isMajorTick = i % minorTicks == 0;
    -    var rInternal = isMajorTick ? rMajorTickInternal : rMinorTickInternal;
    -    var path = isMajorTick ? majorTicksPath : minorTicksPath;
    -    x = cx + goog.math.angleDx(angle, rInternal);
    -    y = cy + goog.math.angleDy(angle, rInternal);
    -    path.moveTo(x, y);
    -    x = cx + goog.math.angleDx(angle, r);
    -    y = cy + goog.math.angleDy(angle, r);
    -    path.lineTo(x, y);
    -
    -    // Draw the tick's label for major ticks
    -    if (isMajorTick && this.majorTickLabels_) {
    -      var tickIndex = Math.floor(i / minorTicks);
    -      var label = this.majorTickLabels_[tickIndex];
    -      if (label) {
    -        x = cx + goog.math.angleDx(angle, rInternal - tickLabelFontSize / 2);
    -        y = cy + goog.math.angleDy(angle, rInternal - tickLabelFontSize / 2);
    -        var x1, x2;
    -        var align = 'center';
    -        if (angle > 280 || angle < 90) {
    -          align = 'right';
    -          x1 = 0;
    -          x2 = x;
    -        } else if (angle >= 90 && angle < 260) {
    -          align = 'left';
    -          x1 = x;
    -          x2 = this.width_;
    -        } else {
    -          // Values around top (angle 260-280) are centered around point
    -          var dw = Math.min(x, this.width_ - x); // Nearest side border
    -          x1 = x - dw;
    -          x2 = x + dw;
    -          y += Math.round(tickLabelFontSize / 4); // Movea bit down
    -        }
    -        graphics.drawTextOnLine(label, x1, y, x2, y,
    -            align, tickLabelFont, null, tickLabelFill);
    -      }
    -    }
    -  }
    -  stroke = theme.getMinorTickStroke();
    -  graphics.drawPath(minorTicksPath, stroke, null);
    -  stroke = theme.getMajorTickStroke();
    -  graphics.drawPath(majorTicksPath, stroke, null);
    -
    -  // Draw the needle and the value label. Stop animation when doing
    -  // full redraw and jump to the final value position.
    -  this.stopAnimation_();
    -  this.needleRadius_ = r;
    -  this.drawValue_();
    -};
    -
    -
    -/**
    - * Handle animation events while the hand is moving.
    - * @param {goog.fx.AnimationEvent} e The event.
    - * @private
    - */
    -goog.ui.Gauge.prototype.onAnimate_ = function(e) {
    -  this.needleValuePosition_ = e.x;
    -  this.drawValue_();
    -};
    -
    -
    -/**
    - * Handle animation events when hand move is complete.
    - * @private
    - */
    -goog.ui.Gauge.prototype.onAnimateEnd_ = function() {
    -  this.stopAnimation_();
    -};
    -
    -
    -/**
    - * Stop the current animation, if it is active.
    - * @private
    - */
    -goog.ui.Gauge.prototype.stopAnimation_ = function() {
    -  if (this.animation_) {
    -    goog.events.removeAll(this.animation_);
    -    this.animation_.stop(false);
    -    this.animation_ = null;
    -  }
    -};
    -
    -
    -/**
    - * Convert a value to the position in the range. The returned position
    - * is a value between 0 and 1, where 0 indicates the lowest range value,
    - * 1 is the highest range, and any value in between is proportional
    - * to mapping the range to (0-1).
    - * If the value is not within the range, the returned value may be a bit
    - * lower than 0, or a bit higher than 1. This is done so that values out
    - * of range will be displayed just a bit outside of the gauge axis.
    - * @param {number} value The value to convert.
    - * @private
    - * @return {number} The range position.
    - */
    -goog.ui.Gauge.prototype.valueToRangePosition_ = function(value) {
    -  var valueRange = this.maxValue_ - this.minValue_;
    -  var valuePct = (value - this.minValue_) / valueRange; // 0 to 1
    -
    -  // If value is out of range, trim it not to be too much out of range
    -  valuePct = Math.max(valuePct,
    -      -goog.ui.Gauge.MAX_EXCEED_POSITION_POSITION);
    -  valuePct = Math.min(valuePct,
    -      1 + goog.ui.Gauge.MAX_EXCEED_POSITION_POSITION);
    -
    -  return valuePct;
    -};
    -
    -
    -/**
    - * Convert a value to an angle based on the value range and angle span
    - * @param {number} value The value.
    - * @return {number} The angle where this value is located on the round
    - *     axis, based on the range and angle span.
    - * @private
    - */
    -goog.ui.Gauge.prototype.valueToAngle_ = function(value) {
    -  var valuePct = this.valueToRangePosition_(value);
    -  return this.valuePositionToAngle_(valuePct);
    -};
    -
    -
    -/**
    - * Convert a value-position (percent in the range) to an angle based on
    - * the angle span. A value-position is a value that has been proportinally
    - * adjusted to a value betwwen 0-1, proportionaly to the range.
    - * @param {number} valuePct The value.
    - * @return {number} The angle where this value is located on the round
    - *     axis, based on the range and angle span.
    - * @private
    - */
    -goog.ui.Gauge.prototype.valuePositionToAngle_ = function(valuePct) {
    -  var startAngle = goog.math.standardAngle((360 - this.angleSpan_) / 2 + 90);
    -  return this.angleSpan_ * valuePct + startAngle;
    -};
    -
    -
    -/**
    - * Draw the elements that depend on the current value (the needle and
    - * the formatted value). This function is called whenever a value is changed
    - * or when the entire gauge is redrawn.
    - * @private
    - */
    -goog.ui.Gauge.prototype.drawValue_ = function() {
    -  if (!this.isInDocument()) {
    -    return;
    -  }
    -
    -  var r = this.needleRadius_;
    -  var graphics = this.graphics_;
    -  var theme = this.theme_;
    -  var cx = this.width_ / 2;
    -  var cy = this.height_ / 2;
    -  var angle = this.valuePositionToAngle_(
    -      /** @type {number} */(this.needleValuePosition_));
    -
    -  // Compute the needle path
    -  var frontRadius =
    -      Math.round(r * goog.ui.Gauge.FACTOR_NEEDLE_FRONT);
    -  var backRadius =
    -      Math.round(r * goog.ui.Gauge.FACTOR_NEEDLE_BACK);
    -  var frontDx = goog.math.angleDx(angle, frontRadius);
    -  var frontDy = goog.math.angleDy(angle, frontRadius);
    -  var backDx = goog.math.angleDx(angle, backRadius);
    -  var backDy = goog.math.angleDy(angle, backRadius);
    -  var angleRight = goog.math.standardAngle(angle + 90);
    -  var distanceControlPointBase = r * goog.ui.Gauge.FACTOR_NEEDLE_WIDTH;
    -  var controlPointMidDx = goog.math.angleDx(angleRight,
    -      distanceControlPointBase);
    -  var controlPointMidDy = goog.math.angleDy(angleRight,
    -      distanceControlPointBase);
    -
    -  var path = new goog.graphics.Path();
    -  path.moveTo(cx + frontDx, cy + frontDy);
    -  path.curveTo(cx + controlPointMidDx, cy + controlPointMidDy,
    -      cx - backDx + (controlPointMidDx / 2),
    -      cy - backDy + (controlPointMidDy / 2),
    -      cx - backDx, cy - backDy);
    -  path.curveTo(cx - backDx - (controlPointMidDx / 2),
    -      cy - backDy - (controlPointMidDy / 2),
    -      cx - controlPointMidDx, cy - controlPointMidDy,
    -      cx + frontDx, cy + frontDy);
    -
    -  // Draw the needle hinge
    -  var rh = Math.round(r * goog.ui.Gauge.FACTOR_NEEDLE_HINGE);
    -
    -  // Clean previous needle
    -  var needleGroup = this.needleGroup_;
    -  if (needleGroup) {
    -    needleGroup.clear();
    -  } else {
    -    needleGroup = this.needleGroup_ = graphics.createGroup();
    -  }
    -
    -  // Draw current formatted value if provided.
    -  if (this.formattedValue_) {
    -    var font = this.valueFont_;
    -    if (!font) {
    -      var fontSize =
    -          Math.round(r * goog.ui.Gauge.FACTOR_VALUE_FONT_SIZE);
    -      font = new goog.graphics.Font(fontSize,
    -          goog.ui.Gauge.TITLE_FONT_NAME);
    -      font.bold = true;
    -      this.valueFont_ = font;
    -    }
    -    var fill = new goog.graphics.SolidFill(theme.getValueColor());
    -    var y = cy + Math.round(r * goog.ui.Gauge.FACTOR_VALUE_OFFSET);
    -    graphics.drawTextOnLine(this.formattedValue_, 0, y, this.width_, y,
    -        'center', font, null, fill, needleGroup);
    -  }
    -
    -  // Draw the needle
    -  var stroke = theme.getNeedleStroke();
    -  var fill = theme.getNeedleFill(cx, cy, rh);
    -  graphics.drawPath(path, stroke, fill, needleGroup);
    -  stroke = theme.getHingeStroke();
    -  fill = theme.getHingeFill(cx, cy, rh);
    -  graphics.drawCircle(cx, cy, rh, stroke, fill, needleGroup);
    -};
    -
    -
    -/**
    - * Redraws the entire gauge.
    - * Should be called after theme colors have been changed.
    - */
    -goog.ui.Gauge.prototype.redraw = function() {
    -  this.draw_();
    -};
    -
    -
    -/** @override */
    -goog.ui.Gauge.prototype.enterDocument = function() {
    -  goog.ui.Gauge.superClass_.enterDocument.call(this);
    -
    -  // set roles and states
    -  var el = this.getElement();
    -  goog.asserts.assert(el, 'The DOM element for the gauge cannot be null.');
    -  goog.a11y.aria.setRole(el, 'progressbar');
    -  goog.a11y.aria.setState(el, 'live', 'polite');
    -  goog.a11y.aria.setState(el, 'valuemin', this.minValue_);
    -  goog.a11y.aria.setState(el, 'valuemax', this.maxValue_);
    -  goog.a11y.aria.setState(el, 'valuenow', this.value_);
    -  this.draw_();
    -};
    -
    -
    -/** @override */
    -goog.ui.Gauge.prototype.exitDocument = function() {
    -  goog.ui.Gauge.superClass_.exitDocument.call(this);
    -  this.stopAnimation_();
    -};
    -
    -
    -/** @override */
    -goog.ui.Gauge.prototype.disposeInternal = function() {
    -  this.stopAnimation_();
    -  this.graphics_.dispose();
    -  delete this.graphics_;
    -  delete this.needleGroup_;
    -  delete this.theme_;
    -  delete this.rangeColors_;
    -  goog.ui.Gauge.superClass_.disposeInternal.call(this);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/gaugetheme.js b/src/database/third_party/closure-library/closure/goog/ui/gaugetheme.js
    deleted file mode 100644
    index 52008d424e8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/gaugetheme.js
    +++ /dev/null
    @@ -1,170 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview The color theme used by a gauge (goog.ui.Guage).
    - */
    -
    -
    -goog.provide('goog.ui.GaugeTheme');
    -
    -
    -goog.require('goog.graphics.LinearGradient');
    -goog.require('goog.graphics.SolidFill');
    -goog.require('goog.graphics.Stroke');
    -
    -
    -
    -/**
    - * A class for the default color theme for a Gauge.
    - * Users can extend this class to provide a custom color theme, and apply the
    - * custom color theme by calling  {@link goog.ui.Gauge#setTheme}.
    - * @constructor
    - * @final
    - */
    -goog.ui.GaugeTheme = function() {
    -};
    -
    -
    -/**
    - * Returns the stroke for the external border of the gauge.
    - * @return {!goog.graphics.Stroke} The stroke to use.
    - */
    -goog.ui.GaugeTheme.prototype.getExternalBorderStroke = function() {
    -  return new goog.graphics.Stroke(1, '#333333');
    -};
    -
    -
    -/**
    - * Returns the fill for the external border of the gauge.
    - * @param {number} cx X coordinate of the center of the gauge.
    - * @param {number} cy Y coordinate of the center of the gauge.
    - * @param {number} r Radius of the gauge.
    - * @return {!goog.graphics.Fill} The fill to use.
    - */
    -goog.ui.GaugeTheme.prototype.getExternalBorderFill = function(cx, cy, r) {
    -  return new goog.graphics.LinearGradient(cx + r, cy - r, cx - r, cy + r,
    -      '#f7f7f7', '#cccccc');
    -};
    -
    -
    -/**
    - * Returns the stroke for the internal border of the gauge.
    - * @return {!goog.graphics.Stroke} The stroke to use.
    - */
    -goog.ui.GaugeTheme.prototype.getInternalBorderStroke = function() {
    -  return new goog.graphics.Stroke(2, '#e0e0e0');
    -};
    -
    -
    -/**
    - * Returns the fill for the internal border of the gauge.
    - * @param {number} cx X coordinate of the center of the gauge.
    - * @param {number} cy Y coordinate of the center of the gauge.
    - * @param {number} r Radius of the gauge.
    - * @return {!goog.graphics.Fill} The fill to use.
    - */
    -goog.ui.GaugeTheme.prototype.getInternalBorderFill = function(cx, cy, r) {
    -  return new goog.graphics.SolidFill('#f7f7f7');
    -};
    -
    -
    -/**
    - * Returns the stroke for the major ticks of the gauge.
    - * @return {!goog.graphics.Stroke} The stroke to use.
    - */
    -goog.ui.GaugeTheme.prototype.getMajorTickStroke = function() {
    -  return new goog.graphics.Stroke(2, '#333333');
    -};
    -
    -
    -/**
    - * Returns the stroke for the minor ticks of the gauge.
    - * @return {!goog.graphics.Stroke} The stroke to use.
    - */
    -goog.ui.GaugeTheme.prototype.getMinorTickStroke = function() {
    -  return new goog.graphics.Stroke(1, '#666666');
    -};
    -
    -
    -/**
    - * Returns the stroke for the hinge at the center of the gauge.
    - * @return {!goog.graphics.Stroke} The stroke to use.
    - */
    -goog.ui.GaugeTheme.prototype.getHingeStroke = function() {
    -  return new goog.graphics.Stroke(1, '#666666');
    -};
    -
    -
    -/**
    - * Returns the fill for the hinge at the center of the gauge.
    - * @param {number} cx  X coordinate of the center of the gauge.
    - * @param {number} cy  Y coordinate of the center of the gauge.
    - * @param {number} r  Radius of the hinge.
    - * @return {!goog.graphics.Fill} The fill to use.
    - */
    -goog.ui.GaugeTheme.prototype.getHingeFill = function(cx, cy, r) {
    -  return new goog.graphics.LinearGradient(cx + r, cy - r, cx - r, cy + r,
    -      '#4684ee', '#3776d6');
    -};
    -
    -
    -/**
    - * Returns the stroke for the gauge needle.
    - * @return {!goog.graphics.Stroke} The stroke to use.
    - */
    -goog.ui.GaugeTheme.prototype.getNeedleStroke = function() {
    -  return new goog.graphics.Stroke(1, '#c63310');
    -};
    -
    -
    -/**
    - * Returns the fill for the hinge at the center of the gauge.
    - * @param {number} cx X coordinate of the center of the gauge.
    - * @param {number} cy Y coordinate of the center of the gauge.
    - * @param {number} r Radius of the gauge.
    - * @return {!goog.graphics.Fill} The fill to use.
    - */
    -goog.ui.GaugeTheme.prototype.getNeedleFill = function(cx, cy, r) {
    -  // Make needle a bit transparent so that text underneeth is still visible.
    -  return new goog.graphics.SolidFill('#dc3912', 0.7);
    -};
    -
    -
    -/**
    - * Returns the color for the gauge title.
    - * @return {string} The color to use.
    - */
    -goog.ui.GaugeTheme.prototype.getTitleColor = function() {
    -  return '#333333';
    -};
    -
    -
    -/**
    - * Returns the color for the gauge value.
    - * @return {string} The color to use.
    - */
    -goog.ui.GaugeTheme.prototype.getValueColor = function() {
    -  return 'black';
    -};
    -
    -
    -/**
    - * Returns the color for the labels (formatted values) of tick marks.
    - * @return {string} The color to use.
    - */
    -goog.ui.GaugeTheme.prototype.getTickLabelColor = function() {
    -  return '#333333';
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/hovercard.js b/src/database/third_party/closure-library/closure/goog/ui/hovercard.js
    deleted file mode 100644
    index d6ed3c77e7d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/hovercard.js
    +++ /dev/null
    @@ -1,458 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Show hovercards with a delay after the mouse moves over an
    - * element of a specified type and with a specific attribute.
    - *
    - * @see ../demos/hovercard.html
    - */
    -
    -goog.provide('goog.ui.HoverCard');
    -goog.provide('goog.ui.HoverCard.EventType');
    -goog.provide('goog.ui.HoverCard.TriggerEvent');
    -
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventType');
    -goog.require('goog.ui.AdvancedTooltip');
    -goog.require('goog.ui.PopupBase');
    -goog.require('goog.ui.Tooltip');
    -
    -
    -
    -/**
    - * Create a hover card object.  Hover cards extend tooltips in that they don't
    - * have to be manually attached to each element that can cause them to display.
    - * Instead, you can create a function that gets called when the mouse goes over
    - * any element on your page, and returns whether or not the hovercard should be
    - * shown for that element.
    - *
    - * Alternatively, you can define a map of tag names to the attribute name each
    - * tag should have for that tag to trigger the hover card.  See example below.
    - *
    - * Hovercards can also be triggered manually by calling
    - * {@code triggerForElement}, shown without a delay by calling
    - * {@code showForElement}, or triggered over other elements by calling
    - * {@code attach}.  For the latter two cases, the application is responsible
    - * for calling {@code detach} when finished.
    - *
    - * HoverCard objects fire a TRIGGER event when the mouse moves over an element
    - * that can trigger a hovercard, and BEFORE_SHOW when the hovercard is
    - * about to be shown.  Clients can respond to these events and can prevent the
    - * hovercard from being triggered or shown.
    - *
    - * @param {Function|Object} isAnchor Function that returns true if a given
    - *     element should trigger the hovercard.  Alternatively, it can be a map of
    - *     tag names to the attribute that the tag should have in order to trigger
    - *     the hovercard, e.g., {A: 'href'} for all links.  Tag names must be all
    - *     upper case; attribute names are case insensitive.
    - * @param {boolean=} opt_checkDescendants Use false for a performance gain if
    - *     you are sure that none of your triggering elements have child elements.
    - *     Default is true.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper to use for
    - *     creating and rendering the hovercard element.
    - * @param {Document=} opt_triggeringDocument Optional document to use in place
    - *     of the one included in the DomHelper for finding triggering elements.
    - *     Defaults to the document included in the DomHelper.
    - * @constructor
    - * @extends {goog.ui.AdvancedTooltip}
    - */
    -goog.ui.HoverCard = function(isAnchor, opt_checkDescendants, opt_domHelper,
    -    opt_triggeringDocument) {
    -  goog.ui.AdvancedTooltip.call(this, null, null, opt_domHelper);
    -
    -  if (goog.isFunction(isAnchor)) {
    -    // Override default implementation of {@code isAnchor_}.
    -    this.isAnchor_ = isAnchor;
    -  } else {
    -
    -    /**
    -     * Map of tag names to attribute names that will trigger a hovercard.
    -     * @type {Object}
    -     * @private
    -     */
    -    this.anchors_ = isAnchor;
    -  }
    -
    -  /**
    -   * Whether anchors may have child elements.  If true, then we need to check
    -   * the parent chain of any mouse over event to see if any of those elements
    -   * could be anchors.  Default is true.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.checkDescendants_ = opt_checkDescendants != false;
    -
    -  /**
    -   * Array of anchor elements that should be detached when we are no longer
    -   * associated with them.
    -   * @type {!Array<Element>}
    -   * @private
    -   */
    -  this.tempAttachedAnchors_ = [];
    -
    -  /**
    -   * Document containing the triggering elements, to which we listen for
    -   * mouseover events.
    -   * @type {Document}
    -   * @private
    -   */
    -  this.document_ = opt_triggeringDocument || (opt_domHelper ?
    -      opt_domHelper.getDocument() : goog.dom.getDocument());
    -
    -  goog.events.listen(this.document_, goog.events.EventType.MOUSEOVER,
    -                     this.handleTriggerMouseOver_, false, this);
    -};
    -goog.inherits(goog.ui.HoverCard, goog.ui.AdvancedTooltip);
    -goog.tagUnsealableClass(goog.ui.HoverCard);
    -
    -
    -/**
    - * Enum for event type fired by HoverCard.
    - * @enum {string}
    - */
    -goog.ui.HoverCard.EventType = {
    -  TRIGGER: 'trigger',
    -  CANCEL_TRIGGER: 'canceltrigger',
    -  BEFORE_SHOW: goog.ui.PopupBase.EventType.BEFORE_SHOW,
    -  SHOW: goog.ui.PopupBase.EventType.SHOW,
    -  BEFORE_HIDE: goog.ui.PopupBase.EventType.BEFORE_HIDE,
    -  HIDE: goog.ui.PopupBase.EventType.HIDE
    -};
    -
    -
    -/** @override */
    -goog.ui.HoverCard.prototype.disposeInternal = function() {
    -  goog.ui.HoverCard.superClass_.disposeInternal.call(this);
    -
    -  goog.events.unlisten(this.document_, goog.events.EventType.MOUSEOVER,
    -                       this.handleTriggerMouseOver_, false, this);
    -};
    -
    -
    -/**
    - * Anchor of hovercard currently being shown.  This may be different from
    - * {@code anchor} property if a second hovercard is triggered, when
    - * {@code anchor} becomes the second hovercard while {@code currentAnchor_}
    - * is still the old (but currently displayed) anchor.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.HoverCard.prototype.currentAnchor_;
    -
    -
    -/**
    - * Maximum number of levels to search up the dom when checking descendants.
    - * @type {number}
    - * @private
    - */
    -goog.ui.HoverCard.prototype.maxSearchSteps_;
    -
    -
    -/**
    - * This function can be overridden by passing a function as the first parameter
    - * to the constructor.
    - * @param {Node} node Node to test.
    - * @return {boolean} Whether or not hovercard should be shown.
    - * @private
    - */
    -goog.ui.HoverCard.prototype.isAnchor_ = function(node) {
    -  return node.tagName in this.anchors_ &&
    -      !!node.getAttribute(this.anchors_[node.tagName]);
    -};
    -
    -
    -/**
    - * If the user mouses over an element with the correct tag and attribute, then
    - * trigger the hovercard for that element.  If anchors could have children, then
    - * we also need to check the parent chain of the given element.
    - * @param {goog.events.Event} e Mouse over event.
    - * @private
    - */
    -goog.ui.HoverCard.prototype.handleTriggerMouseOver_ = function(e) {
    -  var target = /** @type {Element} */ (e.target);
    -  // Target might be null when hovering over disabled input textboxes in IE.
    -  if (!target) {
    -    return;
    -  }
    -  if (this.isAnchor_(target)) {
    -    this.setPosition(null);
    -    this.triggerForElement(target);
    -  } else if (this.checkDescendants_) {
    -    var trigger = goog.dom.getAncestor(target,
    -                                       goog.bind(this.isAnchor_, this),
    -                                       false,
    -                                       this.maxSearchSteps_);
    -    if (trigger) {
    -      this.setPosition(null);
    -      this.triggerForElement(/** @type {!Element} */ (trigger));
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Triggers the hovercard to show after a delay.
    - * @param {Element} anchorElement Element that is triggering the hovercard.
    - * @param {goog.positioning.AbstractPosition=} opt_pos Position to display
    - *     hovercard.
    - * @param {Object=} opt_data Data to pass to the onTrigger event.
    - */
    -goog.ui.HoverCard.prototype.triggerForElement = function(anchorElement,
    -                                                         opt_pos, opt_data) {
    -  if (anchorElement == this.currentAnchor_) {
    -    // Element is already showing, just make sure it doesn't hide.
    -    this.clearHideTimer();
    -    return;
    -  }
    -  if (anchorElement == this.anchor) {
    -    // Hovercard is pending, no need to retrigger.
    -    return;
    -  }
    -
    -  // If a previous hovercard was being triggered, cancel it.
    -  this.maybeCancelTrigger_();
    -
    -  // Create a new event for this trigger
    -  var triggerEvent = new goog.ui.HoverCard.TriggerEvent(
    -      goog.ui.HoverCard.EventType.TRIGGER, this, anchorElement, opt_data);
    -
    -  if (!this.getElements().contains(anchorElement)) {
    -    this.attach(anchorElement);
    -    this.tempAttachedAnchors_.push(anchorElement);
    -  }
    -  this.anchor = anchorElement;
    -  if (!this.onTrigger(triggerEvent)) {
    -    this.onCancelTrigger();
    -    return;
    -  }
    -  var pos = opt_pos || this.position_;
    -  this.startShowTimer(anchorElement,
    -      /** @type {goog.positioning.AbstractPosition} */ (pos));
    -};
    -
    -
    -/**
    - * Sets the current anchor element at the time that the hovercard is shown.
    - * @param {Element} anchor New current anchor element, or null if there is
    - *     no current anchor.
    - * @private
    - */
    -goog.ui.HoverCard.prototype.setCurrentAnchor_ = function(anchor) {
    -  if (anchor != this.currentAnchor_) {
    -    this.detachTempAnchor_(this.currentAnchor_);
    -  }
    -  this.currentAnchor_ = anchor;
    -};
    -
    -
    -/**
    - * If given anchor is in the list of temporarily attached anchors, then
    - * detach and remove from the list.
    - * @param {Element|undefined} anchor Anchor element that we may want to detach
    - *     from.
    - * @private
    - */
    -goog.ui.HoverCard.prototype.detachTempAnchor_ = function(anchor) {
    -  var pos = goog.array.indexOf(this.tempAttachedAnchors_, anchor);
    -  if (pos != -1) {
    -    this.detach(anchor);
    -    this.tempAttachedAnchors_.splice(pos, 1);
    -  }
    -};
    -
    -
    -/**
    - * Called when an element triggers the hovercard.  This will return false
    - * if an event handler sets preventDefault to true, which will prevent
    - * the hovercard from being shown.
    - * @param {!goog.ui.HoverCard.TriggerEvent} triggerEvent Event object to use
    - *     for trigger event.
    - * @return {boolean} Whether hovercard should be shown or cancelled.
    - * @protected
    - */
    -goog.ui.HoverCard.prototype.onTrigger = function(triggerEvent) {
    -  return this.dispatchEvent(triggerEvent);
    -};
    -
    -
    -/**
    - * Abort pending hovercard showing, if any.
    - */
    -goog.ui.HoverCard.prototype.cancelTrigger = function() {
    -  this.clearShowTimer();
    -  this.onCancelTrigger();
    -};
    -
    -
    -/**
    - * If hovercard is in the process of being triggered, then cancel it.
    - * @private
    - */
    -goog.ui.HoverCard.prototype.maybeCancelTrigger_ = function() {
    -  if (this.getState() == goog.ui.Tooltip.State.WAITING_TO_SHOW ||
    -      this.getState() == goog.ui.Tooltip.State.UPDATING) {
    -    this.cancelTrigger();
    -  }
    -};
    -
    -
    -/**
    - * This method gets called when we detect that a trigger event will not lead
    - * to the hovercard being shown.
    - * @protected
    - */
    -goog.ui.HoverCard.prototype.onCancelTrigger = function() {
    -  var event = new goog.ui.HoverCard.TriggerEvent(
    -      goog.ui.HoverCard.EventType.CANCEL_TRIGGER, this, this.anchor || null);
    -  this.dispatchEvent(event);
    -  this.detachTempAnchor_(this.anchor);
    -  delete this.anchor;
    -};
    -
    -
    -/**
    - * Gets the DOM element that triggered the current hovercard.  Note that in
    - * the TRIGGER or CANCEL_TRIGGER events, the current hovercard's anchor may not
    - * be the one that caused the event, so use the event's anchor property instead.
    - * @return {Element} Object that caused the currently displayed hovercard (or
    - *     pending hovercard if none is displayed) to be triggered.
    - */
    -goog.ui.HoverCard.prototype.getAnchorElement = function() {
    -  // this.currentAnchor_ is only set if the hovercard is showing.  If it isn't
    -  // showing yet, then use this.anchor as the pending anchor.
    -  return /** @type {Element} */ (this.currentAnchor_ || this.anchor);
    -};
    -
    -
    -/**
    - * Make sure we detach from temp anchor when we are done displaying hovercard.
    - * @protected
    - * @suppress {underscore|visibility}
    - * @override
    - */
    -goog.ui.HoverCard.prototype.onHide_ = function() {
    -  goog.ui.HoverCard.superClass_.onHide_.call(this);
    -  this.setCurrentAnchor_(null);
    -};
    -
    -
    -/**
    - * This mouse over event is only received if the anchor is already attached.
    - * If it was attached manually, then it may need to be triggered.
    - * @param {goog.events.BrowserEvent} event Mouse over event.
    - * @override
    - */
    -goog.ui.HoverCard.prototype.handleMouseOver = function(event) {
    -  // If this is a child of a triggering element, find the triggering element.
    -  var trigger = this.getAnchorFromElement(
    -      /** @type {Element} */ (event.target));
    -
    -  // If we moused over an element different from the one currently being
    -  // triggered (if any), then trigger this new element.
    -  if (trigger && trigger != this.anchor) {
    -    this.triggerForElement(trigger);
    -    return;
    -  }
    -
    -  goog.ui.HoverCard.superClass_.handleMouseOver.call(this, event);
    -};
    -
    -
    -/**
    - * If the mouse moves out of the trigger while we're being triggered, then
    - * cancel it.
    - * @param {goog.events.BrowserEvent} event Mouse out or blur event.
    - * @override
    - */
    -goog.ui.HoverCard.prototype.handleMouseOutAndBlur = function(event) {
    -  // Get ready to see if a trigger should be cancelled.
    -  var anchor = this.anchor;
    -  var state = this.getState();
    -  goog.ui.HoverCard.superClass_.handleMouseOutAndBlur.call(this, event);
    -  if (state != this.getState() &&
    -      (state == goog.ui.Tooltip.State.WAITING_TO_SHOW ||
    -       state == goog.ui.Tooltip.State.UPDATING)) {
    -    // Tooltip's handleMouseOutAndBlur method sets anchor to null.  Reset
    -    // so that the cancel trigger event will have the right data, and so that
    -    // it will be properly detached.
    -    this.anchor = anchor;
    -    this.onCancelTrigger();  // This will remove and detach the anchor.
    -  }
    -};
    -
    -
    -/**
    - * Called by timer from mouse over handler. If this is called and the hovercard
    - * is not shown for whatever reason, then send a cancel trigger event.
    - * @param {Element} el Element to show tooltip for.
    - * @param {goog.positioning.AbstractPosition=} opt_pos Position to display popup
    - *     at.
    - * @override
    - */
    -goog.ui.HoverCard.prototype.maybeShow = function(el, opt_pos) {
    -  goog.ui.HoverCard.superClass_.maybeShow.call(this, el, opt_pos);
    -
    -  if (!this.isVisible()) {
    -    this.cancelTrigger();
    -  } else {
    -    this.setCurrentAnchor_(el);
    -  }
    -};
    -
    -
    -/**
    - * Sets the max number of levels to search up the dom if checking descendants.
    - * @param {number} maxSearchSteps Maximum number of levels to search up the
    - *     dom if checking descendants.
    - */
    -goog.ui.HoverCard.prototype.setMaxSearchSteps = function(maxSearchSteps) {
    -  if (!maxSearchSteps) {
    -    this.checkDescendants_ = false;
    -  } else if (this.checkDescendants_) {
    -    this.maxSearchSteps_ = maxSearchSteps;
    -  }
    -};
    -
    -
    -
    -/**
    - * Create a trigger event for specified anchor and optional data.
    - * @param {goog.ui.HoverCard.EventType} type Event type.
    - * @param {goog.ui.HoverCard} target Hovercard that is triggering the event.
    - * @param {Element} anchor Element that triggered event.
    - * @param {Object=} opt_data Optional data to be available in the TRIGGER event.
    - * @constructor
    - * @extends {goog.events.Event}
    - * @final
    - */
    -goog.ui.HoverCard.TriggerEvent = function(type, target, anchor, opt_data) {
    -  goog.events.Event.call(this, type, target);
    -
    -  /**
    -   * Element that triggered the hovercard event.
    -   * @type {Element}
    -   */
    -  this.anchor = anchor;
    -
    -  /**
    -   * Optional data to be passed to the listener.
    -   * @type {Object|undefined}
    -   */
    -  this.data = opt_data;
    -};
    -goog.inherits(goog.ui.HoverCard.TriggerEvent, goog.events.Event);
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/hovercard_test.html b/src/database/third_party/closure-library/closure/goog/ui/hovercard_test.html
    deleted file mode 100644
    index 5618e21b071..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/hovercard_test.html
    +++ /dev/null
    @@ -1,55 +0,0 @@
    -<html>
    - <!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.HoverCard
    -  </title>
    -  <style type="text/css">
    -   .goog-tooltip {
    -    background: infobackground;
    -    color: infotext;
    -    border: 1px solid infotext;
    -    padding: 1px;
    -    font:menu;
    -  }
    -  </style>
    -  <script type="text/javascript" src="../base.js">
    -  </script>
    -  <script type="text/javascript">
    -   goog.require('goog.ui.HoverCardTest');
    -  </script>
    - </head>
    - <body>
    -  <p id="notpopup">
    -   Content
    -  </p>
    -  <span id="john" email="john@gmail.com">
    -   Span for John that can trigger a
    -    hovercard.
    -  </span>
    -  <br />
    -  <span id="jane">
    -   Span for Jane that doesn't trigger a hovercard (no email
    -    attribute)
    -  </span>
    -  <br />
    -  <span id="james" email="james@gmail.com">
    -   Span for James that can trigger a
    -    hovercard
    -   <span id="child">
    -    Child of james
    -   </span>
    -  </span>
    -  <br />
    -  <div id="bill" email="bill@gmail.com">
    -   Doesn't trigger for Bill because
    -    it's a div
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/hovercard_test.js b/src/database/third_party/closure-library/closure/goog/ui/hovercard_test.js
    deleted file mode 100644
    index 6193db4fcaf..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/hovercard_test.js
    +++ /dev/null
    @@ -1,355 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.HoverCardTest');
    -goog.setTestOnly('goog.ui.HoverCardTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.style');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.events.Event');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.HoverCard');
    -
    -var timer = new goog.testing.MockClock();
    -var card;
    -
    -// Variables for mocks
    -var triggeredElement;
    -var cancelledElement;
    -var showDelay;
    -var shownCard;
    -var hideDelay;
    -
    -// spans
    -var john;
    -var jane;
    -var james;
    -var bill;
    -var child;
    -
    -// Inactive
    -var elsewhere;
    -var offAnchor;
    -
    -function setUpPage() {
    -  john = goog.dom.getElement('john');
    -  jane = goog.dom.getElement('jane');
    -  james = goog.dom.getElement('james');
    -  bill = goog.dom.getElement('bill');
    -  child = goog.dom.getElement('child');
    -}
    -
    -function setUp() {
    -  timer.install();
    -  triggeredElement = null;
    -  cancelledElement = null;
    -  showDelay = null;
    -  shownCard = null;
    -  hideDelay = null;
    -  elsewhere = goog.dom.getElement('notpopup');
    -  offAnchor = new goog.math.Coordinate(1, 1);
    -}
    -
    -function initCard(opt_isAnchor, opt_checkChildren, opt_maxSearchSteps) {
    -  var isAnchor = opt_isAnchor || {SPAN: 'email'};
    -  card = new goog.ui.HoverCard(isAnchor, opt_checkChildren);
    -  card.setText('Test hovercard');
    -
    -  if (opt_maxSearchSteps != null) {
    -    card.setMaxSearchSteps(opt_maxSearchSteps);
    -  }
    -
    -  goog.events.listen(card, goog.ui.HoverCard.EventType.TRIGGER, onTrigger);
    -  goog.events.listen(card, goog.ui.HoverCard.EventType.CANCEL_TRIGGER,
    -                     onCancel);
    -  goog.events.listen(card, goog.ui.HoverCard.EventType.BEFORE_SHOW,
    -                     onBeforeShow);
    -
    -  // This gets around the problem where AdvancedToolTip thinks it's
    -  // receiving a ghost event because cursor position hasn't moved off of
    -  // (0, 0).
    -  card.cursorPosition = new goog.math.Coordinate(1, 1);
    -}
    -
    -// Event handlers
    -function onTrigger(event) {
    -  triggeredElement = event.anchor;
    -  if (showDelay) {
    -    card.setShowDelayMs(showDelay);
    -  }
    -  return true;
    -}
    -
    -function onCancel(event) {
    -  cancelledElement = event.anchor;
    -}
    -
    -function onBeforeShow() {
    -  shownCard = card.getAnchorElement();
    -  if (hideDelay) {
    -    card.setHideDelayMs(hideDelay);
    -  }
    -  return true;
    -}
    -
    -function tearDown() {
    -  card.dispose();
    -  timer.uninstall();
    -}
    -
    -
    -/**
    - * Verify that hovercard displays and goes away under normal circumstances.
    - */
    -function testTrigger() {
    -  initCard();
    -
    -  // Mouse over correct element fires trigger
    -  showDelay = 500;
    -  goog.testing.events.fireMouseOverEvent(john, elsewhere);
    -  assertEquals('Hovercard should have triggered', john,
    -               triggeredElement);
    -
    -  // Show card after delay
    -  timer.tick(showDelay - 1);
    -  assertNull('Card should not have shown', shownCard);
    -  assertFalse(card.isVisible());
    -  hideDelay = 5000;
    -  timer.tick(1);
    -  assertEquals('Card should have shown', john, shownCard);
    -  assertTrue(card.isVisible());
    -
    -  // Mouse out leads to hide delay
    -  goog.testing.events.fireMouseOutEvent(john, elsewhere);
    -  goog.testing.events.fireMouseMoveEvent(document, offAnchor);
    -  timer.tick(hideDelay - 1);
    -  assertTrue('Card should still be visible', card.isVisible());
    -  timer.tick(10);
    -  assertFalse('Card should be hidden', card.isVisible());
    -}
    -
    -
    -/**
    - * Verify that CANCEL_TRIGGER event occurs when mouse goes out of
    - * triggering element before hovercard is shown.
    - */
    -function testOnCancel() {
    -  initCard();
    -
    -  showDelay = 500;
    -  goog.testing.events.fireMouseOverEvent(john, elsewhere);
    -  timer.tick(showDelay - 1);
    -  goog.testing.events.fireMouseOutEvent(john, elsewhere);
    -  goog.testing.events.fireMouseMoveEvent(document, offAnchor);
    -  timer.tick(10);
    -  assertFalse('Card should be hidden', card.isVisible());
    -  assertEquals('Should have cancelled trigger', john, cancelledElement);
    -}
    -
    -
    -/**
    - * Verify that mousing over non-triggering elements don't interfere.
    - */
    -function testMouseOverNonTrigger() {
    -  initCard();
    -
    -  // Mouse over correct element fires trigger
    -  showDelay = 500;
    -  goog.testing.events.fireMouseOverEvent(john, elsewhere);
    -  timer.tick(showDelay);
    -
    -  // Mouse over and out other element does nothing
    -  triggeredElement = null;
    -  goog.testing.events.fireMouseOverEvent(jane, elsewhere);
    -  timer.tick(showDelay + 1);
    -  assertNull(triggeredElement);
    -}
    -
    -
    -/**
    - * Verify that a mouse over event with no target will not break
    - * hover card.
    - */
    -function testMouseOverNoTarget() {
    -  initCard();
    -  card.handleTriggerMouseOver_(new goog.testing.events.Event());
    -}
    -
    -
    -/**
    - * Verify that mousing over a second trigger before the first one shows
    - * will correctly cancel the first and show the second.
    - */
    -function testMultipleTriggers() {
    -  initCard();
    -
    -  // Test second trigger when first one still pending
    -  showDelay = 500;
    -  hideDelay = 1000;
    -  goog.testing.events.fireMouseOverEvent(john, elsewhere);
    -  timer.tick(250);
    -  goog.testing.events.fireMouseOutEvent(john, james);
    -  goog.testing.events.fireMouseOverEvent(james, john);
    -  // First trigger should cancel because it isn't showing yet
    -  assertEquals('Should cancel first trigger', john, cancelledElement);
    -  timer.tick(300);
    -  assertFalse(card.isVisible());
    -  timer.tick(250);
    -  assertEquals('Should show second card', james, shownCard);
    -  assertTrue(card.isVisible());
    -
    -  goog.testing.events.fireMouseOutEvent(james, john);
    -  goog.testing.events.fireMouseOverEvent(john, james);
    -  assertEquals('Should still show second card', james,
    -               card.getAnchorElement());
    -  assertTrue(card.isVisible());
    -
    -  shownCard = null;
    -  timer.tick(501);
    -  assertEquals('Should show first card again', john, shownCard);
    -  assertTrue(card.isVisible());
    -
    -  // Test that cancelling while another is showing gives correct cancel
    -  // information
    -  cancelledElement = null;
    -  goog.testing.events.fireMouseOutEvent(john, james);
    -  goog.testing.events.fireMouseOverEvent(james, john);
    -  goog.testing.events.fireMouseOutEvent(james, elsewhere);
    -  assertEquals('Should cancel second card', james, cancelledElement);
    -}
    -
    -
    -/**
    - * Verify manual triggering.
    - */
    -function testManualTrigger() {
    -  initCard();
    -
    -  // Doesn't normally trigger for div tag
    -  showDelay = 500;
    -  goog.testing.events.fireMouseOverEvent(bill, elsewhere);
    -  timer.tick(showDelay);
    -  assertFalse(card.isVisible());
    -
    -  // Manually trigger element
    -  card.triggerForElement(bill);
    -  hideDelay = 600;
    -  timer.tick(showDelay);
    -  assertTrue(card.isVisible());
    -  goog.testing.events.fireMouseOutEvent(bill, elsewhere);
    -  goog.testing.events.fireMouseMoveEvent(document, offAnchor);
    -  timer.tick(hideDelay);
    -  assertFalse(card.isVisible());
    -}
    -
    -
    -/**
    - * Verify creating with isAnchor function.
    - */
    -function testIsAnchor() {
    -  // Initialize card so only bill triggers it.
    -  initCard(function(element) {
    -    return element == bill;
    -  });
    -
    -  showDelay = 500;
    -  goog.testing.events.fireMouseOverEvent(bill, elsewhere);
    -  timer.tick(showDelay);
    -  assertTrue('Should trigger card', card.isVisible());
    -
    -  hideDelay = 300;
    -  goog.testing.events.fireMouseOutEvent(bill, elsewhere);
    -  goog.testing.events.fireMouseMoveEvent(document, offAnchor);
    -  timer.tick(hideDelay);
    -  assertFalse(card.isVisible());
    -
    -  goog.testing.events.fireMouseOverEvent(john, elsewhere);
    -  timer.tick(showDelay);
    -  assertFalse('Should not trigger card', card.isVisible());
    -}
    -
    -
    -/**
    - * Verify mouse over child of anchor triggers hovercard.
    - */
    -function testAnchorWithChildren() {
    -  initCard();
    -
    -  showDelay = 500;
    -  goog.testing.events.fireMouseOverEvent(james, elsewhere);
    -  timer.tick(250);
    -
    -  // Moving from an anchor to a child of that anchor shouldn't cancel
    -  // or retrigger.
    -  var childBounds = goog.style.getBounds(child);
    -  var inChild = new goog.math.Coordinate(childBounds.left + 1,
    -                                         childBounds.top + 1);
    -  goog.testing.events.fireMouseOutEvent(james, child);
    -  goog.testing.events.fireMouseMoveEvent(child, inChild);
    -  assertNull("Shouldn't cancel trigger", cancelledElement);
    -  triggeredElement = null;
    -  goog.testing.events.fireMouseOverEvent(child, james);
    -  assertNull("Shouldn't retrigger card", triggeredElement);
    -  timer.tick(250);
    -  assertTrue('Card should show with original delay', card.isVisible());
    -
    -  hideDelay = 300;
    -  goog.testing.events.fireMouseOutEvent(child, elsewhere);
    -  goog.testing.events.fireMouseMoveEvent(child, offAnchor);
    -  timer.tick(hideDelay);
    -  assertFalse(card.isVisible());
    -
    -  goog.testing.events.fireMouseOverEvent(child, elsewhere);
    -  timer.tick(showDelay);
    -  assertTrue('Mouse over child should trigger card', card.isVisible());
    -}
    -
    -function testNoTriggerWithMaxSearchSteps() {
    -  initCard(undefined, true, 0);
    -
    -  showDelay = 500;
    -  goog.testing.events.fireMouseOverEvent(child, elsewhere);
    -  timer.tick(showDelay);
    -  assertFalse('Should not trigger card', card.isVisible());
    -}
    -
    -function testTriggerWithMaxSearchSteps() {
    -  initCard(undefined, true, 2);
    -
    -  showDelay = 500;
    -  goog.testing.events.fireMouseOverEvent(child, elsewhere);
    -  timer.tick(showDelay);
    -  assertTrue('Should trigger card', card.isVisible());
    -}
    -
    -function testPositionAfterSecondTriggerWithMaxSearchSteps() {
    -  initCard(undefined, true, 2);
    -
    -  showDelay = 500;
    -  goog.testing.events.fireMouseOverEvent(john, elsewhere);
    -  timer.tick(showDelay);
    -  assertTrue('Should trigger card', card.isVisible());
    -  assertEquals('Card cursor x coordinate should be 1',
    -      card.position_.coordinate.x, 1);
    -  card.cursorPosition = new goog.math.Coordinate(2, 2);
    -  goog.testing.events.fireMouseOverEvent(child, elsewhere);
    -  timer.tick(showDelay);
    -  assertTrue('Should trigger card', card.isVisible());
    -  assertEquals('Card cursor x coordinate should be 2',
    -      card.position_.coordinate.x, 2);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/hsvapalette.js b/src/database/third_party/closure-library/closure/goog/ui/hsvapalette.js
    deleted file mode 100644
    index 4c3abf75970..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/hsvapalette.js
    +++ /dev/null
    @@ -1,295 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview An HSVA (hue/saturation/value/alpha) color palette/picker
    - * implementation.
    - * Without the styles from the demo css file, only a hex color label and input
    - * field show up.
    - *
    - * @author chrisn@google.com (Chris Nokleberg)
    - * @see ../demos/hsvapalette.html
    - */
    -
    -goog.provide('goog.ui.HsvaPalette');
    -
    -goog.require('goog.array');
    -goog.require('goog.color.alpha');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.events');
    -goog.require('goog.events.EventType');
    -goog.require('goog.style');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.HsvPalette');
    -
    -
    -
    -/**
    - * Creates an HSVA palette. Allows a user to select the hue, saturation,
    - * value/brightness and alpha/opacity.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @param {string=} opt_color Optional initial color, without alpha (default is
    - *     red).
    - * @param {number=} opt_alpha Optional initial alpha (default is 1).
    - * @param {string=} opt_class Optional base for creating classnames (default is
    - *     'goog-hsva-palette').
    - * @extends {goog.ui.HsvPalette}
    - * @constructor
    - * @final
    - */
    -goog.ui.HsvaPalette = function(opt_domHelper, opt_color, opt_alpha, opt_class) {
    -  goog.ui.HsvaPalette.base(
    -      this, 'constructor', opt_domHelper, opt_color, opt_class);
    -
    -  /**
    -   * Alpha transparency of the currently selected color, in [0, 1]. When
    -   * undefined, the palette will behave as a non-transparent HSV palette,
    -   * assuming full opacity.
    -   * @type {number}
    -   * @private
    -   */
    -  this.alpha_ = goog.isDef(opt_alpha) ? opt_alpha : 1;
    -
    -  /**
    -   * @override
    -   */
    -  this.className = opt_class || goog.getCssName('goog-hsva-palette');
    -};
    -goog.inherits(goog.ui.HsvaPalette, goog.ui.HsvPalette);
    -
    -
    -/**
    - * DOM element representing the alpha background image.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.HsvaPalette.prototype.aImageEl_;
    -
    -
    -/**
    - * DOM element representing the alpha handle.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.HsvaPalette.prototype.aHandleEl_;
    -
    -
    -/**
    - * DOM element representing the swatch backdrop image.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.HsvaPalette.prototype.swatchBackdropEl_;
    -
    -
    -/** @override */
    -goog.ui.HsvaPalette.prototype.getAlpha = function() {
    -  return this.alpha_;
    -};
    -
    -
    -/**
    - * Sets which color is selected and update the UI. The passed color should be
    - * in #rrggbb format. The alpha value will be set to 1.
    - * @param {number} alpha The selected alpha value, in [0, 1].
    - */
    -goog.ui.HsvaPalette.prototype.setAlpha = function(alpha) {
    -  this.setColorAlphaHelper_(this.color, alpha);
    -};
    -
    -
    -/**
    - * Sets which color is selected and update the UI. The passed color should be
    - * in #rrggbb format. The alpha value will be set to 1.
    - * @param {string} color The selected color.
    - * @override
    - */
    -goog.ui.HsvaPalette.prototype.setColor = function(color) {
    -  this.setColorAlphaHelper_(color, 1);
    -};
    -
    -
    -/**
    - * Gets the color that is currently selected in this color picker, in #rrggbbaa
    - * format.
    - * @return {string} The string of the selected color with alpha.
    - */
    -goog.ui.HsvaPalette.prototype.getColorRgbaHex = function() {
    -  var alphaHex = Math.floor(this.alpha_ * 255).toString(16);
    -  return this.color + (alphaHex.length == 1 ? '0' + alphaHex : alphaHex);
    -};
    -
    -
    -/**
    - * Sets which color is selected and update the UI. The passed color should be
    - * in #rrggbbaa format. The alpha value will be set to 1.
    - * @param {string} color The selected color with alpha.
    - */
    -goog.ui.HsvaPalette.prototype.setColorRgbaHex = function(color) {
    -  var parsed = goog.ui.HsvaPalette.parseColorRgbaHex_(color);
    -  this.setColorAlphaHelper_(parsed[0], parsed[1]);
    -};
    -
    -
    -/**
    - * Sets which color and alpha value are selected and update the UI. The passed
    - * color should be in #rrggbb format.
    - * @param {string} color The selected color in #rrggbb format.
    - * @param {number} alpha The selected alpha value, in [0, 1].
    - * @private
    - */
    -goog.ui.HsvaPalette.prototype.setColorAlphaHelper_ = function(color, alpha) {
    -  var colorChange = this.color != color;
    -  var alphaChange = this.alpha_ != alpha;
    -  this.alpha_ = alpha;
    -  this.color = color;
    -  if (colorChange) {
    -    // This is to prevent multiple event dispatches.
    -    this.setColorInternal(color);
    -  }
    -  if (colorChange || alphaChange) {
    -    this.updateUi();
    -    this.dispatchEvent(goog.ui.Component.EventType.ACTION);
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.HsvaPalette.prototype.createDom = function() {
    -  goog.ui.HsvaPalette.base(this, 'createDom');
    -
    -  var dom = this.getDomHelper();
    -  this.aImageEl_ = dom.createDom(
    -      goog.dom.TagName.DIV, goog.getCssName(this.className, 'a-image'));
    -  this.aHandleEl_ = dom.createDom(
    -      goog.dom.TagName.DIV, goog.getCssName(this.className, 'a-handle'));
    -  this.swatchBackdropEl_ = dom.createDom(
    -      goog.dom.TagName.DIV, goog.getCssName(this.className, 'swatch-backdrop'));
    -  var element = this.getElement();
    -  dom.appendChild(element, this.aImageEl_);
    -  dom.appendChild(element, this.aHandleEl_);
    -  dom.appendChild(element, this.swatchBackdropEl_);
    -};
    -
    -
    -/** @override */
    -goog.ui.HsvaPalette.prototype.disposeInternal = function() {
    -  goog.ui.HsvaPalette.base(this, 'disposeInternal');
    -
    -  delete this.aImageEl_;
    -  delete this.aHandleEl_;
    -  delete this.swatchBackdropEl_;
    -};
    -
    -
    -/** @override */
    -goog.ui.HsvaPalette.prototype.updateUi = function() {
    -  goog.ui.HsvaPalette.base(this, 'updateUi');
    -  if (this.isInDocument()) {
    -    var a = this.alpha_ * 255;
    -    var top = this.aImageEl_.offsetTop -
    -        Math.floor(this.aHandleEl_.offsetHeight / 2) +
    -        this.aImageEl_.offsetHeight * ((255 - a) / 255);
    -    this.aHandleEl_.style.top = top + 'px';
    -    this.aImageEl_.style.backgroundColor = this.color;
    -    goog.style.setOpacity(this.swatchElement, a / 255);
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.HsvaPalette.prototype.updateInput = function() {
    -  if (!goog.array.equals([this.color, this.alpha_],
    -      goog.ui.HsvaPalette.parseUserInput_(this.inputElement.value))) {
    -    this.inputElement.value = this.getColorRgbaHex();
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.HsvaPalette.prototype.handleMouseDown = function(e) {
    -  goog.ui.HsvaPalette.base(this, 'handleMouseDown', e);
    -  if (e.target == this.aImageEl_ || e.target == this.aHandleEl_) {
    -    // Setup value change listeners
    -    var b = goog.style.getBounds(this.valueBackgroundImageElement);
    -    this.handleMouseMoveA_(b, e);
    -    this.mouseMoveListener = goog.events.listen(
    -        this.getDomHelper().getDocument(),
    -        goog.events.EventType.MOUSEMOVE,
    -        goog.bind(this.handleMouseMoveA_, this, b));
    -    this.mouseUpListener = goog.events.listen(
    -        this.getDomHelper().getDocument(),
    -        goog.events.EventType.MOUSEUP, this.handleMouseUp, false, this);
    -  }
    -};
    -
    -
    -/**
    - * Handles mousemove events on the document once a drag operation on the alpha
    - * slider has started.
    - * @param {goog.math.Rect} b Boundaries of the value slider object at the start
    - *     of the drag operation.
    - * @param {goog.events.Event} e Event object.
    - * @private
    - */
    -goog.ui.HsvaPalette.prototype.handleMouseMoveA_ = function(b, e) {
    -  e.preventDefault();
    -  var vportPos = this.getDomHelper().getDocumentScroll();
    -  var newA = (b.top + b.height - Math.min(
    -      Math.max(vportPos.y + e.clientY, b.top),
    -      b.top + b.height)) / b.height;
    -  this.setAlpha(newA);
    -};
    -
    -
    -/** @override */
    -goog.ui.HsvaPalette.prototype.handleInput = function(e) {
    -  var parsed = goog.ui.HsvaPalette.parseUserInput_(this.inputElement.value);
    -  if (parsed) {
    -    this.setColorAlphaHelper_(parsed[0], parsed[1]);
    -  }
    -};
    -
    -
    -/**
    - * Parses an #rrggbb or #rrggbbaa color string.
    - * @param {string} value User-entered color value.
    - * @return {Array<?>} A two element array [color, alpha], where color is
    - *     #rrggbb and alpha is in [0, 1]. Null if the argument was invalid.
    - * @private
    - */
    -goog.ui.HsvaPalette.parseUserInput_ = function(value) {
    -  if (/^#?[0-9a-f]{8}$/i.test(value)) {
    -    return goog.ui.HsvaPalette.parseColorRgbaHex_(value);
    -  } else if (/^#?[0-9a-f]{6}$/i.test(value)) {
    -    return [value, 1];
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * Parses a #rrggbbaa color string.
    - * @param {string} color The color and alpha in #rrggbbaa format.
    - * @return {!Array<?>} A two element array [color, alpha], where color is
    - *     #rrggbb and alpha is in [0, 1].
    - * @private
    - */
    -goog.ui.HsvaPalette.parseColorRgbaHex_ = function(color) {
    -  var hex = goog.color.alpha.parse(color).hex;
    -  return [
    -    goog.color.alpha.extractHexColor(hex),
    -    parseInt(goog.color.alpha.extractAlpha(hex), 16) / 255
    -  ];
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/hsvapalette_test.html b/src/database/third_party/closure-library/closure/goog/ui/hsvapalette_test.html
    deleted file mode 100644
    index 228ad9e4441..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/hsvapalette_test.html
    +++ /dev/null
    @@ -1,28 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   HsvaPalette Unit Tests
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script src="../deps.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.HsvaPaletteTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="sandbox">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/hsvapalette_test.js b/src/database/third_party/closure-library/closure/goog/ui/hsvapalette_test.js
    deleted file mode 100644
    index 174801e04f4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/hsvapalette_test.js
    +++ /dev/null
    @@ -1,144 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.HsvaPaletteTest');
    -goog.setTestOnly('goog.ui.HsvaPaletteTest');
    -
    -goog.require('goog.color.alpha');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events.Event');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.style');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.HsvaPalette');
    -goog.require('goog.userAgent');
    -
    -var samplePalette;
    -var eventWasFired = false;
    -var stubs = new goog.testing.PropertyReplacer();
    -
    -function setUp() {
    -  samplePalette = new goog.ui.HsvaPalette();
    -}
    -
    -function tearDown() {
    -  samplePalette.dispose();
    -  stubs.reset();
    -}
    -
    -function testZeroAlpha() {
    -  var palette = new goog.ui.HsvaPalette(null, undefined, 0);
    -  assertEquals(0, palette.getAlpha());
    -}
    -
    -function testOptionalInitialColor() {
    -  var alpha = 0.5;
    -  var color = '#0000ff';
    -  var palette = new goog.ui.HsvaPalette(null, color, alpha);
    -  assertEquals(color, palette.getColor());
    -  assertEquals(alpha, palette.getAlpha());
    -}
    -
    -function testCustomClassName() {
    -  var customClassName = 'custom-plouf';
    -  var customClassPalette =
    -      new goog.ui.HsvaPalette(null, null, null, customClassName);
    -  customClassPalette.createDom();
    -  assertTrue(goog.dom.classlist.contains(customClassPalette.getElement(),
    -      customClassName));
    -}
    -
    -function testSetColor() {
    -  var color = '#abcdef01';
    -  samplePalette.setColorRgbaHex(color);
    -  assertEquals(color,
    -      goog.color.alpha.parse(samplePalette.getColorRgbaHex()).hex);
    -  color = 'abcdef01';
    -  samplePalette.setColorRgbaHex(color);
    -  assertEquals('#' + color,
    -      goog.color.alpha.parse(samplePalette.getColorRgbaHex()).hex);
    -}
    -
    -function testRender() {
    -  samplePalette.render(document.getElementById('sandbox'));
    -
    -  assertTrue(samplePalette.isInDocument());
    -
    -  var elem = samplePalette.getElement();
    -  assertNotNull(elem);
    -  assertEquals(goog.dom.TagName.DIV, elem.tagName);
    -
    -  if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('7')) {
    -    assertSameElements('On IE6, the noalpha class must be present',
    -        ['goog-hsva-palette', 'goog-hsva-palette-noalpha'],
    -        goog.dom.classlist.get(elem));
    -  } else {
    -    assertEquals('The noalpha class must not be present',
    -        'goog-hsva-palette', elem.className);
    -  }
    -}
    -
    -function testInputColor() {
    -  samplePalette.render(document.getElementById('sandbox'));
    -  var color = '#00112233';
    -  samplePalette.inputElement.value = color;
    -  samplePalette.handleInput(null);
    -  assertEquals(color,
    -      goog.color.alpha.parse(samplePalette.getColorRgbaHex()).hex);
    -}
    -
    -function testHandleMouseMoveAlpha() {
    -  samplePalette.render(document.getElementById('sandbox'));
    -  stubs.set(goog.dom, 'getPageScroll', function() {
    -    return new goog.math.Coordinate(0, 0);
    -  });
    -
    -  // Lowering the opacity of a dark, opaque red should yield a
    -  // more transparent red.
    -  samplePalette.setColorRgbaHex('#630c0000');
    -  goog.style.setPageOffset(samplePalette.aImageEl_, 0, 0);
    -  goog.style.setSize(samplePalette.aImageEl_, 10, 100);
    -  var boundaries = goog.style.getBounds(samplePalette.aImageEl_);
    -
    -  var event = new goog.events.Event();
    -  event.clientY = boundaries.top;
    -  samplePalette.handleMouseMoveA_(boundaries, event);
    -
    -  assertEquals('#630c00ff', samplePalette.getColorRgbaHex());
    -}
    -
    -function testSwatchOpacity() {
    -  samplePalette.render(document.getElementById('sandbox'));
    -
    -  samplePalette.setAlpha(1);
    -  assertEquals(1, goog.style.getOpacity(samplePalette.swatchElement));
    -
    -  samplePalette.setAlpha(0x99 / 0xff);
    -  assertEquals(0.6, goog.style.getOpacity(samplePalette.swatchElement));
    -
    -  samplePalette.setAlpha(0);
    -  assertEquals(0, goog.style.getOpacity(samplePalette.swatchElement));
    -}
    -
    -function testNoTransparencyBehavior() {
    -  samplePalette.render(document.getElementById('sandbox'));
    -
    -  samplePalette.inputElement.value = '#abcdef22';
    -  samplePalette.handleInput(null);
    -  samplePalette.inputElement.value = '#abcdef';
    -  samplePalette.handleInput(null);
    -  assertEquals(1, goog.style.getOpacity(samplePalette.swatchElement));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/hsvpalette.js b/src/database/third_party/closure-library/closure/goog/ui/hsvpalette.js
    deleted file mode 100644
    index 18d272b05b2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/hsvpalette.js
    +++ /dev/null
    @@ -1,524 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview An HSV (hue/saturation/value) color palette/picker
    - * implementation. Inspired by examples like
    - * http://johndyer.name/lab/colorpicker/ and the author's initial work. This
    - * control allows for more control in picking colors than a simple swatch-based
    - * palette. Without the styles from the demo css file, only a hex color label
    - * and input field show up.
    - *
    - * @author arv@google.com (Erik Arvidsson)
    - * @see ../demos/hsvpalette.html
    - */
    -
    -goog.provide('goog.ui.HsvPalette');
    -
    -goog.require('goog.color');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.events');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.InputHandler');
    -goog.require('goog.style');
    -goog.require('goog.style.bidi');
    -goog.require('goog.ui.Component');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Creates an HSV palette. Allows a user to select the hue, saturation and
    - * value/brightness.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @param {string=} opt_color Optional initial color (default is red).
    - * @param {string=} opt_class Optional base for creating classnames (default is
    - *     goog.getCssName('goog-hsv-palette')).
    - * @extends {goog.ui.Component}
    - * @constructor
    - */
    -goog.ui.HsvPalette = function(opt_domHelper, opt_color, opt_class) {
    -  goog.ui.Component.call(this, opt_domHelper);
    -
    -  this.setColorInternal(opt_color || '#f00');
    -
    -  /**
    -   * The base class name for the component.
    -   * @type {string}
    -   * @protected
    -   */
    -  this.className = opt_class || goog.getCssName('goog-hsv-palette');
    -
    -  /**
    -   * The document which is being listened to.
    -   * type {HTMLDocument}
    -   * @private
    -   */
    -  this.document_ = this.getDomHelper().getDocument();
    -};
    -goog.inherits(goog.ui.HsvPalette, goog.ui.Component);
    -// TODO(user): Make this inherit from goog.ui.Control and split this into
    -// a control and a renderer.
    -goog.tagUnsealableClass(goog.ui.HsvPalette);
    -
    -
    -/**
    - * @desc Label for an input field where a user can enter a hexadecimal color
    - * specification, such as #ff0000 for red.
    - * @private
    - */
    -goog.ui.HsvPalette.MSG_HSV_PALETTE_HEX_COLOR_ = goog.getMsg('Hex color');
    -
    -
    -/**
    - * DOM element representing the hue/saturation background image.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.HsvPalette.prototype.hsImageEl_;
    -
    -
    -/**
    - * DOM element representing the hue/saturation handle.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.HsvPalette.prototype.hsHandleEl_;
    -
    -
    -/**
    - * DOM element representing the value background image.
    - * @type {Element}
    - * @protected
    - */
    -goog.ui.HsvPalette.prototype.valueBackgroundImageElement;
    -
    -
    -/**
    - * DOM element representing the value handle.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.HsvPalette.prototype.vHandleEl_;
    -
    -
    -/**
    - * DOM element representing the current color swatch.
    - * @type {Element}
    - * @protected
    - */
    -goog.ui.HsvPalette.prototype.swatchElement;
    -
    -
    -/**
    - * DOM element representing the hex color input text field.
    - * @type {Element}
    - * @protected
    - */
    -goog.ui.HsvPalette.prototype.inputElement;
    -
    -
    -/**
    - * Input handler object for the hex value input field.
    - * @type {goog.events.InputHandler}
    - * @private
    - */
    -goog.ui.HsvPalette.prototype.inputHandler_;
    -
    -
    -/**
    - * Listener key for the mousemove event (during a drag operation).
    - * @type {goog.events.Key}
    - * @protected
    - */
    -goog.ui.HsvPalette.prototype.mouseMoveListener;
    -
    -
    -/**
    - * Listener key for the mouseup event (during a drag operation).
    - * @type {goog.events.Key}
    - * @protected
    - */
    -goog.ui.HsvPalette.prototype.mouseUpListener;
    -
    -
    -/** @private {!goog.color.Hsv} */
    -goog.ui.HsvPalette.prototype.hsv_;
    -
    -
    -/**
    - * Hex representation of the color.
    - * @protected {string}
    - */
    -goog.ui.HsvPalette.prototype.color;
    -
    -
    -/**
    - * Gets the color that is currently selected in this color picker.
    - * @return {string} The string of the selected color.
    - */
    -goog.ui.HsvPalette.prototype.getColor = function() {
    -  return this.color;
    -};
    -
    -
    -/**
    - * Alpha transparency of the currently selected color, in [0, 1].
    - * For the HSV palette this always returns 1. The HSVA palette overrides
    - * this method.
    - * @return {number} The current alpha value.
    - */
    -goog.ui.HsvPalette.prototype.getAlpha = function() {
    -  return 1;
    -};
    -
    -
    -/**
    - * Updates the text entry field.
    - * @protected
    - */
    -goog.ui.HsvPalette.prototype.updateInput = function() {
    -  var parsed;
    -  try {
    -    parsed = goog.color.parse(this.inputElement.value).hex;
    -  } catch (e) {
    -    // ignore
    -  }
    -  if (this.color != parsed) {
    -    this.inputElement.value = this.color;
    -  }
    -};
    -
    -
    -/**
    - * Sets which color is selected and update the UI.
    - * @param {string} color The selected color.
    - */
    -goog.ui.HsvPalette.prototype.setColor = function(color) {
    -  if (color != this.color) {
    -    this.setColorInternal(color);
    -    this.updateUi();
    -    this.dispatchEvent(goog.ui.Component.EventType.ACTION);
    -  }
    -};
    -
    -
    -/**
    - * Sets which color is selected.
    - * @param {string} color The selected color.
    - * @protected
    - */
    -goog.ui.HsvPalette.prototype.setColorInternal = function(color) {
    -  var rgbHex = goog.color.parse(color).hex;
    -  var rgbArray = goog.color.hexToRgb(rgbHex);
    -  this.hsv_ = goog.color.rgbArrayToHsv(rgbArray);
    -  // Hue is divided by 360 because the documentation for goog.color is currently
    -  // incorrect.
    -  // TODO(user): Fix this, see http://1324469 .
    -  this.hsv_[0] = this.hsv_[0] / 360;
    -  this.color = rgbHex;
    -};
    -
    -
    -/**
    - * Alters the hue, saturation, and/or value of the currently selected color and
    - * updates the UI.
    - * @param {?number=} opt_hue (optional) hue in [0, 1].
    - * @param {?number=} opt_saturation (optional) saturation in [0, 1].
    - * @param {?number=} opt_value (optional) value in [0, 255].
    - */
    -goog.ui.HsvPalette.prototype.setHsv = function(opt_hue,
    -                                               opt_saturation,
    -                                               opt_value) {
    -  if (opt_hue != null || opt_saturation != null || opt_value != null) {
    -    this.setHsv_(opt_hue, opt_saturation, opt_value);
    -    this.updateUi();
    -    this.dispatchEvent(goog.ui.Component.EventType.ACTION);
    -  }
    -};
    -
    -
    -/**
    - * Alters the hue, saturation, and/or value of the currently selected color.
    - * @param {?number=} opt_hue (optional) hue in [0, 1].
    - * @param {?number=} opt_saturation (optional) saturation in [0, 1].
    - * @param {?number=} opt_value (optional) value in [0, 255].
    - * @private
    - */
    -goog.ui.HsvPalette.prototype.setHsv_ = function(opt_hue,
    -                                                opt_saturation,
    -                                                opt_value) {
    -  this.hsv_[0] = (opt_hue != null) ? opt_hue : this.hsv_[0];
    -  this.hsv_[1] = (opt_saturation != null) ? opt_saturation : this.hsv_[1];
    -  this.hsv_[2] = (opt_value != null) ? opt_value : this.hsv_[2];
    -  // Hue is multiplied by 360 because the documentation for goog.color is
    -  // currently incorrect.
    -  // TODO(user): Fix this, see http://1324469 .
    -  this.color = goog.color.hsvArrayToHex([
    -    this.hsv_[0] * 360,
    -    this.hsv_[1],
    -    this.hsv_[2]
    -  ]);
    -};
    -
    -
    -/**
    - * HsvPalettes cannot be used to decorate pre-existing html, since the
    - * structure they build is fairly complicated.
    - * @param {Element} element Element to decorate.
    - * @return {boolean} Returns always false.
    - * @override
    - */
    -goog.ui.HsvPalette.prototype.canDecorate = function(element) {
    -  return false;
    -};
    -
    -
    -/** @override */
    -goog.ui.HsvPalette.prototype.createDom = function() {
    -  var dom = this.getDomHelper();
    -  var noalpha = (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('7')) ?
    -      ' ' + goog.getCssName(this.className, 'noalpha') : '';
    -
    -  var backdrop = dom.createDom(goog.dom.TagName.DIV,
    -      goog.getCssName(this.className, 'hs-backdrop'));
    -
    -  this.hsHandleEl_ = dom.createDom(goog.dom.TagName.DIV,
    -      goog.getCssName(this.className, 'hs-handle'));
    -
    -  this.hsImageEl_ = dom.createDom(goog.dom.TagName.DIV,
    -      goog.getCssName(this.className, 'hs-image'),
    -      this.hsHandleEl_);
    -
    -  this.valueBackgroundImageElement = dom.createDom(
    -      goog.dom.TagName.DIV,
    -      goog.getCssName(this.className, 'v-image'));
    -
    -  this.vHandleEl_ = dom.createDom(
    -      goog.dom.TagName.DIV,
    -      goog.getCssName(this.className, 'v-handle'));
    -
    -  this.swatchElement = dom.createDom(goog.dom.TagName.DIV,
    -      goog.getCssName(this.className, 'swatch'));
    -
    -  this.inputElement = dom.createDom('input', {
    -    'class': goog.getCssName(this.className, 'input'),
    -    'aria-label': goog.ui.HsvPalette.MSG_HSV_PALETTE_HEX_COLOR_,
    -    'type': 'text', 'dir': 'ltr'
    -  });
    -
    -  var labelElement = dom.createDom('label', null, this.inputElement);
    -
    -  var element = dom.createDom(goog.dom.TagName.DIV,
    -      this.className + noalpha,
    -      backdrop,
    -      this.hsImageEl_,
    -      this.valueBackgroundImageElement,
    -      this.vHandleEl_,
    -      this.swatchElement,
    -      labelElement);
    -
    -  this.setElementInternal(element);
    -
    -  // TODO(arv): Set tabIndex
    -};
    -
    -
    -/**
    - * Renders the color picker inside the provided element. This will override the
    - * current content of the element.
    - * @override
    - */
    -goog.ui.HsvPalette.prototype.enterDocument = function() {
    -  goog.ui.HsvPalette.superClass_.enterDocument.call(this);
    -
    -  // TODO(user): Accessibility.
    -
    -  this.updateUi();
    -
    -  var handler = this.getHandler();
    -  handler.listen(this.getElement(), goog.events.EventType.MOUSEDOWN,
    -      this.handleMouseDown);
    -
    -  // Cannot create InputHandler in createDom because IE throws an exception
    -  // on document.activeElement
    -  if (!this.inputHandler_) {
    -    this.inputHandler_ = new goog.events.InputHandler(this.inputElement);
    -  }
    -
    -  handler.listen(this.inputHandler_,
    -      goog.events.InputHandler.EventType.INPUT, this.handleInput);
    -};
    -
    -
    -/** @override */
    -goog.ui.HsvPalette.prototype.disposeInternal = function() {
    -  goog.ui.HsvPalette.superClass_.disposeInternal.call(this);
    -
    -  delete this.hsImageEl_;
    -  delete this.hsHandleEl_;
    -  delete this.valueBackgroundImageElement;
    -  delete this.vHandleEl_;
    -  delete this.swatchElement;
    -  delete this.inputElement;
    -  if (this.inputHandler_) {
    -    this.inputHandler_.dispose();
    -    delete this.inputHandler_;
    -  }
    -  goog.events.unlistenByKey(this.mouseMoveListener);
    -  goog.events.unlistenByKey(this.mouseUpListener);
    -};
    -
    -
    -/**
    - * Updates the position, opacity, and styles for the UI representation of the
    - * palette.
    - * @protected
    - */
    -goog.ui.HsvPalette.prototype.updateUi = function() {
    -  if (this.isInDocument()) {
    -    var h = this.hsv_[0];
    -    var s = this.hsv_[1];
    -    var v = this.hsv_[2];
    -
    -    var left = this.hsImageEl_.offsetWidth * h;
    -
    -    // We don't use a flipped gradient image in RTL, so we need to flip the
    -    // offset in RTL so that it still hovers over the correct color on the
    -    // gradiant.
    -    if (this.isRightToLeft()) {
    -      left = this.hsImageEl_.offsetWidth - left;
    -    }
    -
    -    // We also need to account for the handle size.
    -    var handleOffset = Math.ceil(this.hsHandleEl_.offsetWidth / 2);
    -    left -= handleOffset;
    -
    -    var top = this.hsImageEl_.offsetHeight * (1 - s);
    -    // Account for the handle size.
    -    top -= Math.ceil(this.hsHandleEl_.offsetHeight / 2);
    -
    -    goog.style.bidi.setPosition(this.hsHandleEl_, left, top,
    -        this.isRightToLeft());
    -
    -    top = this.valueBackgroundImageElement.offsetTop -
    -        Math.floor(this.vHandleEl_.offsetHeight / 2) +
    -        this.valueBackgroundImageElement.offsetHeight * ((255 - v) / 255);
    -
    -    this.vHandleEl_.style.top = top + 'px';
    -    goog.style.setOpacity(this.hsImageEl_, (v / 255));
    -
    -    goog.style.setStyle(this.valueBackgroundImageElement, 'background-color',
    -        goog.color.hsvToHex(this.hsv_[0] * 360, this.hsv_[1], 255));
    -
    -    goog.style.setStyle(this.swatchElement, 'background-color', this.color);
    -    goog.style.setStyle(this.swatchElement, 'color',
    -                        (this.hsv_[2] > 255 / 2) ? '#000' : '#fff');
    -    this.updateInput();
    -  }
    -};
    -
    -
    -/**
    - * Handles mousedown events on palette UI elements.
    - * @param {goog.events.BrowserEvent} e Event object.
    - * @protected
    - */
    -goog.ui.HsvPalette.prototype.handleMouseDown = function(e) {
    -  if (e.target == this.valueBackgroundImageElement ||
    -      e.target == this.vHandleEl_) {
    -    // Setup value change listeners
    -    var b = goog.style.getBounds(this.valueBackgroundImageElement);
    -    this.handleMouseMoveV_(b, e);
    -    this.mouseMoveListener = goog.events.listen(this.document_,
    -        goog.events.EventType.MOUSEMOVE,
    -        goog.bind(this.handleMouseMoveV_, this, b));
    -    this.mouseUpListener = goog.events.listen(this.document_,
    -        goog.events.EventType.MOUSEUP, this.handleMouseUp, false, this);
    -  } else if (e.target == this.hsImageEl_ || e.target == this.hsHandleEl_) {
    -    // Setup hue/saturation change listeners
    -    var b = goog.style.getBounds(this.hsImageEl_);
    -    this.handleMouseMoveHs_(b, e);
    -    this.mouseMoveListener = goog.events.listen(this.document_,
    -        goog.events.EventType.MOUSEMOVE,
    -        goog.bind(this.handleMouseMoveHs_, this, b));
    -    this.mouseUpListener = goog.events.listen(this.document_,
    -        goog.events.EventType.MOUSEUP, this.handleMouseUp, false, this);
    -  }
    -};
    -
    -
    -/**
    - * Handles mousemove events on the document once a drag operation on the value
    - * slider has started.
    - * @param {goog.math.Rect} b Boundaries of the value slider object at the start
    - *     of the drag operation.
    - * @param {goog.events.BrowserEvent} e Event object.
    - * @private
    - */
    -goog.ui.HsvPalette.prototype.handleMouseMoveV_ = function(b, e) {
    -  e.preventDefault();
    -  var vportPos = this.getDomHelper().getDocumentScroll();
    -
    -  var height = Math.min(
    -      Math.max(vportPos.y + e.clientY, b.top),
    -      b.top + b.height);
    -
    -  var newV = Math.round(
    -      255 * (b.top + b.height - height) / b.height);
    -
    -  this.setHsv(null, null, newV);
    -};
    -
    -
    -/**
    - * Handles mousemove events on the document once a drag operation on the
    - * hue/saturation slider has started.
    - * @param {goog.math.Rect} b Boundaries of the value slider object at the start
    - *     of the drag operation.
    - * @param {goog.events.BrowserEvent} e Event object.
    - * @private
    - */
    -goog.ui.HsvPalette.prototype.handleMouseMoveHs_ = function(b, e) {
    -  e.preventDefault();
    -  var vportPos = this.getDomHelper().getDocumentScroll();
    -  var newH = (Math.min(Math.max(vportPos.x + e.clientX, b.left),
    -      b.left + b.width) - b.left) / b.width;
    -  var newS = (-Math.min(Math.max(vportPos.y + e.clientY, b.top),
    -      b.top + b.height) + b.top + b.height) / b.height;
    -  this.setHsv(newH, newS, null);
    -};
    -
    -
    -/**
    - * Handles mouseup events on the document, which ends a drag operation.
    - * @param {goog.events.Event} e Event object.
    - * @protected
    - */
    -goog.ui.HsvPalette.prototype.handleMouseUp = function(e) {
    -  goog.events.unlistenByKey(this.mouseMoveListener);
    -  goog.events.unlistenByKey(this.mouseUpListener);
    -};
    -
    -
    -/**
    - * Handles input events on the hex value input field.
    - * @param {goog.events.Event} e Event object.
    - * @protected
    - */
    -goog.ui.HsvPalette.prototype.handleInput = function(e) {
    -  if (/^#?[0-9a-f]{6}$/i.test(this.inputElement.value)) {
    -    this.setColor(this.inputElement.value);
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/hsvpalette_test.html b/src/database/third_party/closure-library/closure/goog/ui/hsvpalette_test.html
    deleted file mode 100644
    index 1f2919eccd7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/hsvpalette_test.html
    +++ /dev/null
    @@ -1,34 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <!--
    -This test has not yet been updated to run on IE8. See http://b/hotlist?id=36311
    --->
    -  <!--meta http-equiv="X-UA-Compatible" content="IE=edge"-->
    -  <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
    -  <title>
    -   HsvPalette Unit Tests
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script src="../deps.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.HsvPaletteTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="sandbox">
    -  </div>
    -  <div id="sandboxRtl" dir="rtl">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/hsvpalette_test.js b/src/database/third_party/closure-library/closure/goog/ui/hsvpalette_test.js
    deleted file mode 100644
    index 8edeb389505..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/hsvpalette_test.js
    +++ /dev/null
    @@ -1,208 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.HsvPaletteTest');
    -goog.setTestOnly('goog.ui.HsvPaletteTest');
    -
    -goog.require('goog.color');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events');
    -goog.require('goog.events.Event');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.style');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.HsvPalette');
    -goog.require('goog.userAgent');
    -
    -var samplePalette;
    -var eventWasFired = false;
    -var stubs = new goog.testing.PropertyReplacer();
    -
    -function setUp() {
    -  samplePalette = new goog.ui.HsvPalette();
    -}
    -
    -function tearDown() {
    -  samplePalette.dispose();
    -  stubs.reset();
    -}
    -
    -function testRtl() {
    -  samplePalette.render(document.getElementById('sandboxRtl'));
    -  var color = '#ffffff';
    -  samplePalette.inputElement.value = color;
    -  samplePalette.handleInput(null);
    -  var expectedRight = samplePalette.hsImageEl_.offsetWidth -
    -      Math.ceil(samplePalette.hsHandleEl_.offsetWidth / 2);
    -  assertEquals(expectedRight + 'px',
    -      samplePalette.hsHandleEl_.style['right']);
    -  assertEquals('', samplePalette.hsHandleEl_.style['left']);
    -}
    -
    -function testOptionalInitialColor() {
    -  var initialColor = '#0000ff';
    -  var customInitialPalette = new goog.ui.HsvPalette(null, initialColor);
    -  assertEquals(initialColor,
    -      goog.color.parse(customInitialPalette.getColor()).hex);
    -}
    -
    -function testCustomClassName() {
    -  var customClassName = 'custom-plouf';
    -  var customClassPalette =
    -      new goog.ui.HsvPalette(null, null, customClassName);
    -  customClassPalette.createDom();
    -  assertTrue(goog.dom.classlist.contains(customClassPalette.getElement(),
    -      customClassName));
    -}
    -
    -function testCannotDecorate() {
    -  assertFalse(samplePalette.canDecorate());
    -}
    -
    -function testSetColor() {
    -  var color = '#abcdef';
    -  samplePalette.setColor(color);
    -  assertEquals(color, goog.color.parse(samplePalette.getColor()).hex);
    -  color = 'abcdef';
    -  samplePalette.setColor(color);
    -  assertEquals('#' + color, goog.color.parse(samplePalette.getColor()).hex);
    -}
    -
    -function testChangeEvent() {
    -  // TODO(user): Add functionality to goog.testing.events to assert
    -  // an event was fired.
    -  goog.events.listen(samplePalette, goog.ui.Component.EventType.ACTION,
    -      function() {eventWasFired = true;});
    -  samplePalette.setColor('#123456');
    -  assertTrue(eventWasFired);
    -}
    -
    -function testSetHsv() {
    -  // Start from red.
    -  samplePalette.setColor('#ff0000');
    -
    -  // Setting hue to 0.5 should yield cyan.
    -  samplePalette.setHsv(0.5, null, null);
    -  assertEquals('#00ffff', goog.color.parse(samplePalette.getColor()).hex);
    -
    -  // Setting saturation to 0 should yield white.
    -  samplePalette.setHsv(null, 0, null);
    -  assertEquals('#ffffff',
    -      goog.color.parse(samplePalette.getColor()).hex);
    -
    -  // Setting value/brightness to 0 should yield black.
    -  samplePalette.setHsv(null, null, 0);
    -  assertEquals('#000000', goog.color.parse(samplePalette.getColor()).hex);
    -}
    -
    -function testRender() {
    -  samplePalette.render(document.getElementById('sandbox'));
    -
    -  assertTrue(samplePalette.isInDocument());
    -
    -  var elem = samplePalette.getElement();
    -  assertNotNull(elem);
    -  assertEquals(goog.dom.TagName.DIV, elem.tagName);
    -
    -  if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('7')) {
    -    assertSameElements('On IE6, the noalpha class must be present',
    -        ['goog-hsv-palette', 'goog-hsv-palette-noalpha'],
    -        goog.dom.classlist.get(elem));
    -  } else {
    -    assertEquals('The noalpha class must not be present',
    -        'goog-hsv-palette', elem.className);
    -  }
    -}
    -
    -function testSwatchTextIsReadable() {
    -  samplePalette.render(document.getElementById('sandbox'));
    -
    -  var swatchElement = samplePalette.swatchElement;
    -
    -  // Text should be black when background is light.
    -  samplePalette.setColor('#ccffff');
    -  assertEquals('#000000',
    -      goog.color.parse(goog.style.getStyle(swatchElement,
    -      'color')).hex);
    -
    -  // Text should be white when background is dark.
    -  samplePalette.setColor('#410800');
    -  assertEquals('#ffffff',
    -      goog.color.parse(goog.style.getStyle(swatchElement,
    -      'color')).hex);
    -}
    -
    -function testInputColor() {
    -  samplePalette.render(document.getElementById('sandbox'));
    -  var color = '#001122';
    -  samplePalette.inputElement.value = color;
    -  samplePalette.handleInput(null);
    -  assertEquals(color, goog.color.parse(samplePalette.getColor()).hex);
    -}
    -
    -function testHandleMouseMoveValue() {
    -  samplePalette.render(document.getElementById('sandbox'));
    -  stubs.set(goog.dom, 'getPageScroll', function() {
    -    return new goog.math.Coordinate(0, 0);
    -  });
    -
    -  // Raising the value/brightness of a dark red should yield a lighter red.
    -  samplePalette.setColor('#630c00');
    -  goog.style.setPageOffset(samplePalette.valueBackgroundImageElement, 0, 0);
    -  goog.style.setSize(samplePalette.valueBackgroundImageElement, 10, 100);
    -  var boundaries = goog.style.getBounds(
    -      samplePalette.valueBackgroundImageElement, 0, 0);
    -
    -  var event = new goog.events.Event();
    -  event.clientY = -50;
    -  // TODO(user): Use
    -  // goog.testing.events.fireMouseDownEvent(
    -  //     samplePalette.valueBackgroundImageElement);
    -  // when google.testing.events support specifying properties of the event
    -  // or find out how tod o it if it already supports it.
    -  samplePalette.handleMouseMoveV_(boundaries, event);
    -  assertEquals('#ff1e00', goog.color.parse(samplePalette.getColor()).hex);
    -}
    -
    -function testHandleMouseMoveHueSaturation() {
    -  samplePalette.render(document.getElementById('sandbox'));
    -  stubs.set(goog.dom, 'getPageScroll', function() {
    -    return new goog.math.Coordinate(0, 0);
    -  });
    -
    -  // The following hue/saturation selection should yield a light yellow.
    -  goog.style.setPageOffset(samplePalette.hsImageEl_, 0, 0);
    -  goog.style.setSize(samplePalette.hsImageEl_, 100, 100);
    -  var boundaries = goog.style.getBounds(samplePalette.hsImageEl_);
    -
    -  var event = new goog.events.Event();
    -  event.clientX = 20;
    -  event.clientY = 85;
    -  // TODO(user): Use goog.testing.events when appropriate (see above).
    -  samplePalette.handleMouseMoveHs_(boundaries, event);
    -  // TODO(user): Fix the main code for this, see bug #1324469.
    -  // NOTE(gboyer): It's a little better than before due to the
    -  // goog.style getBoundingClientRect fix, but still not the same. :-(
    -  if (goog.userAgent.IE) {
    -    var expectedColor = '#ffe0b2';
    -  } else {
    -    var expectedColor = '#ffeec4';
    -  }
    -
    -  assertEquals(expectedColor,
    -      goog.color.parse(samplePalette.getColor()).hex);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/idgenerator.js b/src/database/third_party/closure-library/closure/goog/ui/idgenerator.js
    deleted file mode 100644
    index c018a3857d2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/idgenerator.js
    +++ /dev/null
    @@ -1,48 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Generator for unique element IDs.
    - *
    - */
    -
    -goog.provide('goog.ui.IdGenerator');
    -
    -
    -
    -/**
    - * Creates a new id generator.
    - * @constructor
    - * @final
    - */
    -goog.ui.IdGenerator = function() {
    -};
    -goog.addSingletonGetter(goog.ui.IdGenerator);
    -
    -
    -/**
    - * Next unique ID to use
    - * @type {number}
    - * @private
    - */
    -goog.ui.IdGenerator.prototype.nextId_ = 0;
    -
    -
    -/**
    - * Gets the next unique ID.
    - * @return {string} The next unique identifier.
    - */
    -goog.ui.IdGenerator.prototype.getNextUniqueId = function() {
    -  return ':' + (this.nextId_++).toString(36);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/idletimer.js b/src/database/third_party/closure-library/closure/goog/ui/idletimer.js
    deleted file mode 100644
    index 8053fe0d683..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/idletimer.js
    +++ /dev/null
    @@ -1,300 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Idle Timer.
    - *
    - * Keeps track of transitions between active and idle. This class is built on
    - * top of ActivityMonitor. Whenever an active user becomes idle, this class
    - * dispatches a BECOME_IDLE event. Whenever an idle user becomes active, this
    - * class dispatches a BECOME_ACTIVE event. The amount of inactive time it
    - * takes for a user to be considered idle is specified by the client, and
    - * different instances of this class can all use different thresholds.
    - *
    - */
    -
    -goog.provide('goog.ui.IdleTimer');
    -goog.require('goog.Timer');
    -goog.require('goog.events');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.structs.Set');
    -goog.require('goog.ui.ActivityMonitor');
    -
    -
    -
    -/**
    - * Event target that will give notification of state changes between active and
    - * idle. This class is designed to require few resources while the user is
    - * active.
    - * @param {number} idleThreshold Amount of time in ms at which we consider the
    - *     user has gone idle.
    - * @param {goog.ui.ActivityMonitor=} opt_activityMonitor The activity monitor
    - *     keeping track of user interaction. Defaults to a default-constructed
    - *     activity monitor. If a default activity monitor is used then this class
    - *     will dispose of it. If an activity monitor is passed in then the caller
    - *     remains responsible for disposing of it.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - * @final
    - */
    -goog.ui.IdleTimer = function(idleThreshold, opt_activityMonitor) {
    -  goog.events.EventTarget.call(this);
    -
    -  var activityMonitor = opt_activityMonitor ||
    -      this.getDefaultActivityMonitor_();
    -
    -  /**
    -   * The amount of time in ms at which we consider the user has gone idle
    -   * @type {number}
    -   * @private
    -   */
    -  this.idleThreshold_ = idleThreshold;
    -
    -  /**
    -   * The activity monitor keeping track of user interaction
    -   * @type {goog.ui.ActivityMonitor}
    -   * @private
    -   */
    -  this.activityMonitor_ = activityMonitor;
    -
    -  /**
    -   * Cached onActivityTick_ bound to the object for later use
    -   * @type {Function}
    -   * @private
    -   */
    -  this.boundOnActivityTick_ = goog.bind(this.onActivityTick_, this);
    -
    -  // Decide whether the user is currently active or idle. This method will
    -  // check whether it is correct to start with the user in the active state.
    -  this.maybeStillActive_();
    -};
    -goog.inherits(goog.ui.IdleTimer, goog.events.EventTarget);
    -
    -
    -/**
    - * Whether a listener is currently registered for an idle timer event. On
    - * initialization, the user is assumed to be active.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.IdleTimer.prototype.hasActivityListener_ = false;
    -
    -
    -/**
    - * Handle to the timer ID used for checking ongoing activity, or null
    - * @type {?number}
    - * @private
    - */
    -goog.ui.IdleTimer.prototype.onActivityTimerId_ = null;
    -
    -
    -/**
    - * Whether the user is currently idle
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.IdleTimer.prototype.isIdle_ = false;
    -
    -
    -/**
    - * The default activity monitor created by this class, if any
    - * @type {goog.ui.ActivityMonitor?}
    - * @private
    - */
    -goog.ui.IdleTimer.defaultActivityMonitor_ = null;
    -
    -
    -/**
    - * The idle timers that currently reference the default activity monitor
    - * @type {goog.structs.Set}
    - * @private
    - */
    -goog.ui.IdleTimer.defaultActivityMonitorReferences_ = new goog.structs.Set();
    -
    -
    -/**
    - * Event constants for the idle timer event target
    - * @enum {string}
    - */
    -goog.ui.IdleTimer.Event = {
    -  /** Event fired when an idle user transitions into the active state */
    -  BECOME_ACTIVE: 'active',
    -  /** Event fired when an active user transitions into the idle state */
    -  BECOME_IDLE: 'idle'
    -};
    -
    -
    -/**
    - * Gets the default activity monitor used by this class. If a default has not
    - * been created yet, then a new one will be created.
    - * @return {!goog.ui.ActivityMonitor} The default activity monitor.
    - * @private
    - */
    -goog.ui.IdleTimer.prototype.getDefaultActivityMonitor_ = function() {
    -  goog.ui.IdleTimer.defaultActivityMonitorReferences_.add(this);
    -  if (goog.ui.IdleTimer.defaultActivityMonitor_ == null) {
    -    goog.ui.IdleTimer.defaultActivityMonitor_ = new goog.ui.ActivityMonitor();
    -  }
    -  return goog.ui.IdleTimer.defaultActivityMonitor_;
    -};
    -
    -
    -/**
    - * Removes the reference to the default activity monitor. If there are no more
    - * references then the default activity monitor gets disposed.
    - * @private
    - */
    -goog.ui.IdleTimer.prototype.maybeDisposeDefaultActivityMonitor_ = function() {
    -  goog.ui.IdleTimer.defaultActivityMonitorReferences_.remove(this);
    -  if (goog.ui.IdleTimer.defaultActivityMonitor_ != null &&
    -      goog.ui.IdleTimer.defaultActivityMonitorReferences_.isEmpty()) {
    -    goog.ui.IdleTimer.defaultActivityMonitor_.dispose();
    -    goog.ui.IdleTimer.defaultActivityMonitor_ = null;
    -  }
    -};
    -
    -
    -/**
    - * Checks whether the user is active. If the user is still active, then a timer
    - * is started to check again later.
    - * @private
    - */
    -goog.ui.IdleTimer.prototype.maybeStillActive_ = function() {
    -  // See how long before the user would go idle. The user is considered idle
    -  // after the idle time has passed, not exactly when the idle time arrives.
    -  var remainingIdleThreshold = this.idleThreshold_ + 1 -
    -      (goog.now() - this.activityMonitor_.getLastEventTime());
    -  if (remainingIdleThreshold > 0) {
    -    // The user is still active. Check again later.
    -    this.onActivityTimerId_ = goog.Timer.callOnce(
    -        this.boundOnActivityTick_, remainingIdleThreshold);
    -  } else {
    -    // The user has not been active recently.
    -    this.becomeIdle_();
    -  }
    -};
    -
    -
    -/**
    - * Handler for the timeout used for checking ongoing activity
    - * @private
    - */
    -goog.ui.IdleTimer.prototype.onActivityTick_ = function() {
    -  // The timer has fired.
    -  this.onActivityTimerId_ = null;
    -
    -  // The maybeStillActive method will restart the timer, if appropriate.
    -  this.maybeStillActive_();
    -};
    -
    -
    -/**
    - * Transitions from the active state to the idle state
    - * @private
    - */
    -goog.ui.IdleTimer.prototype.becomeIdle_ = function() {
    -  this.isIdle_ = true;
    -
    -  // The idle timer will send notification when the user does something
    -  // interactive.
    -  goog.events.listen(this.activityMonitor_,
    -      goog.ui.ActivityMonitor.Event.ACTIVITY,
    -      this.onActivity_, false, this);
    -  this.hasActivityListener_ = true;
    -
    -  // Notify clients of the state change.
    -  this.dispatchEvent(goog.ui.IdleTimer.Event.BECOME_IDLE);
    -};
    -
    -
    -/**
    - * Handler for idle timer events when the user does something interactive
    - * @param {goog.events.Event} e The event object.
    - * @private
    - */
    -goog.ui.IdleTimer.prototype.onActivity_ = function(e) {
    -  this.becomeActive_();
    -};
    -
    -
    -/**
    - * Transitions from the idle state to the active state
    - * @private
    - */
    -goog.ui.IdleTimer.prototype.becomeActive_ = function() {
    -  this.isIdle_ = false;
    -
    -  // Stop listening to every interactive event.
    -  this.removeActivityListener_();
    -
    -  // Notify clients of the state change.
    -  this.dispatchEvent(goog.ui.IdleTimer.Event.BECOME_ACTIVE);
    -
    -  // Periodically check whether the user has gone inactive.
    -  this.maybeStillActive_();
    -};
    -
    -
    -/**
    - * Removes the activity listener, if necessary
    - * @private
    - */
    -goog.ui.IdleTimer.prototype.removeActivityListener_ = function() {
    -  if (this.hasActivityListener_) {
    -    goog.events.unlisten(this.activityMonitor_,
    -        goog.ui.ActivityMonitor.Event.ACTIVITY,
    -        this.onActivity_, false, this);
    -    this.hasActivityListener_ = false;
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.IdleTimer.prototype.disposeInternal = function() {
    -  this.removeActivityListener_();
    -  if (this.onActivityTimerId_ != null) {
    -    goog.global.clearTimeout(this.onActivityTimerId_);
    -    this.onActivityTimerId_ = null;
    -  }
    -  this.maybeDisposeDefaultActivityMonitor_();
    -  goog.ui.IdleTimer.superClass_.disposeInternal.call(this);
    -};
    -
    -
    -/**
    - * @return {number} the amount of time at which we consider the user has gone
    - *     idle in ms.
    - */
    -goog.ui.IdleTimer.prototype.getIdleThreshold = function() {
    -  return this.idleThreshold_;
    -};
    -
    -
    -/**
    - * @return {goog.ui.ActivityMonitor} the activity monitor keeping track of user
    - *     interaction.
    - */
    -goog.ui.IdleTimer.prototype.getActivityMonitor = function() {
    -  return this.activityMonitor_;
    -};
    -
    -
    -/**
    - * Returns true if there has been no user action for at least the specified
    - * interval, and false otherwise
    - * @return {boolean} true if the user is idle, false otherwise.
    - */
    -goog.ui.IdleTimer.prototype.isIdle = function() {
    -  return this.isIdle_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/idletimer_test.html b/src/database/third_party/closure-library/closure/goog/ui/idletimer_test.html
    deleted file mode 100644
    index d399e995d44..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/idletimer_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.IdleTimer
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.IdleTimerTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/idletimer_test.js b/src/database/third_party/closure-library/closure/goog/ui/idletimer_test.js
    deleted file mode 100644
    index 35d10ad1c82..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/idletimer_test.js
    +++ /dev/null
    @@ -1,97 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.IdleTimerTest');
    -goog.setTestOnly('goog.ui.IdleTimerTest');
    -
    -goog.require('goog.events');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.IdleTimer');
    -goog.require('goog.ui.MockActivityMonitor');
    -
    -var clock;
    -
    -function setUp() {
    -  clock = new goog.testing.MockClock(true);
    -  goog.now = goog.bind(clock.getCurrentTime, clock);
    -}
    -
    -function tearDown() {
    -  clock.dispose();
    -}
    -
    -
    -/**
    - * Tests whether an event is fired when the user becomes idle
    - */
    -function testBecomeIdle() {
    -  var idleThreshold = 1000;
    -  var mockActivityMonitor = new goog.ui.MockActivityMonitor();
    -  var idleTimer = new goog.ui.IdleTimer(idleThreshold, mockActivityMonitor);
    -
    -  mockActivityMonitor.simulateEvent();
    -  assertFalse('Precondition: user should be active', idleTimer.isIdle());
    -
    -  var onBecomeIdleCount = 0;
    -  var onBecomeIdle = function() {
    -    onBecomeIdleCount += 1;
    -  };
    -  goog.events.listen(idleTimer,
    -      goog.ui.IdleTimer.Event.BECOME_IDLE,
    -      onBecomeIdle);
    -
    -  clock.tick(idleThreshold);
    -  mockActivityMonitor.simulateEvent();
    -  clock.tick(idleThreshold);
    -  assert('The BECOME_IDLE event fired too early', onBecomeIdleCount == 0);
    -  assertFalse('The user should still be active', idleTimer.isIdle());
    -
    -  clock.tick(1);
    -  assert('The BECOME_IDLE event fired too late', onBecomeIdleCount == 1);
    -  assert('The user should be idle', idleTimer.isIdle());
    -
    -  idleTimer.dispose();
    -}
    -
    -
    -/**
    - * Tests whether an event is fired when the user becomes active
    - */
    -function testBecomeActive() {
    -  var idleThreshold = 1000;
    -  var mockActivityMonitor = new goog.ui.MockActivityMonitor();
    -  var idleTimer = new goog.ui.IdleTimer(idleThreshold, mockActivityMonitor);
    -
    -  clock.tick(idleThreshold + 1);
    -  assert('Precondition: user should be idle', idleTimer.isIdle());
    -
    -  var onBecomeActiveCount = 0;
    -  var onBecomeActive = function() {
    -    onBecomeActiveCount += 1;
    -  };
    -  goog.events.listen(idleTimer,
    -      goog.ui.IdleTimer.Event.BECOME_ACTIVE,
    -      onBecomeActive);
    -
    -  clock.tick(idleThreshold);
    -  assert('The BECOME_ACTIVE event fired too early', onBecomeActiveCount == 0);
    -  assert('The user should still be idle', idleTimer.isIdle());
    -
    -  mockActivityMonitor.simulateEvent();
    -  assert('The BECOME_ACTIVE event fired too late', onBecomeActiveCount == 1);
    -  assertFalse('The user should be active', idleTimer.isIdle());
    -
    -  idleTimer.dispose();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/iframemask.js b/src/database/third_party/closure-library/closure/goog/ui/iframemask.js
    deleted file mode 100644
    index 48ac98edfdb..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/iframemask.js
    +++ /dev/null
    @@ -1,258 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Iframe shims, to protect controls on the underlying page
    - * from bleeding through popups.
    - *
    - * @author gboyer@google.com (Garrett Boyer)
    - * @author nicksantos@google.com (Nick Santos) (Ported to Closure)
    - */
    -
    -
    -goog.provide('goog.ui.IframeMask');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.Timer');
    -goog.require('goog.dom');
    -goog.require('goog.dom.iframe');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.style');
    -
    -
    -
    -/**
    - * Controller for an iframe mask. The mask is only valid in the current
    - * document, or else the document of the given DOM helper.
    - *
    - * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper for the relevant
    - *     document.
    - * @param {goog.structs.Pool=} opt_iframePool An optional source of iframes.
    - *     Iframes will be grabbed from the pool when they're needed and returned
    - *     to the pool (but still attached to the DOM) when they're done.
    - * @constructor
    - * @extends {goog.Disposable}
    - */
    -goog.ui.IframeMask = function(opt_domHelper, opt_iframePool) {
    -  goog.Disposable.call(this);
    -
    -  /**
    -   * The DOM helper for this document.
    -   * @type {goog.dom.DomHelper}
    -   * @private
    -   */
    -  this.dom_ = opt_domHelper || goog.dom.getDomHelper();
    -
    -  /**
    -   * An Element to snap the mask to. If none is given, defaults to
    -   * a full-screen iframe mask.
    -   * @type {Element}
    -   * @private
    -   */
    -  this.snapElement_ = this.dom_.getDocument().documentElement;
    -
    -  /**
    -   * An event handler for listening to popups and the like.
    -   * @type {goog.events.EventHandler<!goog.ui.IframeMask>}
    -   * @private
    -   */
    -  this.handler_ = new goog.events.EventHandler(this);
    -
    -  /**
    -   * An iframe pool.
    -   * @type {goog.structs.Pool|undefined}
    -   * @private
    -   */
    -  this.iframePool_ = opt_iframePool;
    -};
    -goog.inherits(goog.ui.IframeMask, goog.Disposable);
    -goog.tagUnsealableClass(goog.ui.IframeMask);
    -
    -
    -/**
    - * An iframe.
    - * @type {HTMLIFrameElement}
    - * @private
    - */
    -goog.ui.IframeMask.prototype.iframe_;
    -
    -
    -/**
    - * The z-index of the iframe mask.
    - * @type {number}
    - * @private
    - */
    -goog.ui.IframeMask.prototype.zIndex_ = 1;
    -
    -
    -/**
    - * The opacity of the iframe mask, expressed as a value between 0 and 1, with
    - * 1 being totally opaque.
    - * @type {number}
    - * @private
    - */
    -goog.ui.IframeMask.prototype.opacity_ = 0;
    -
    -
    -/**
    - * Removes the iframe from the DOM.
    - * @override
    - * @protected
    - */
    -goog.ui.IframeMask.prototype.disposeInternal = function() {
    -  if (this.iframePool_) {
    -    this.iframePool_.releaseObject(
    -        /** @type {HTMLIFrameElement} */ (this.iframe_));
    -  } else {
    -    goog.dom.removeNode(this.iframe_);
    -  }
    -  this.iframe_ = null;
    -
    -  this.handler_.dispose();
    -  this.handler_ = null;
    -
    -  goog.ui.IframeMask.superClass_.disposeInternal.call(this);
    -};
    -
    -
    -/**
    - * CSS for a hidden iframe.
    - * @type {string}
    - * @private
    - */
    -goog.ui.IframeMask.HIDDEN_CSS_TEXT_ =
    -    'position:absolute;display:none;z-index:1';
    -
    -
    -/**
    - * Removes the mask from the screen.
    - */
    -goog.ui.IframeMask.prototype.hideMask = function() {
    -  if (this.iframe_) {
    -    this.iframe_.style.cssText = goog.ui.IframeMask.HIDDEN_CSS_TEXT_;
    -    if (this.iframePool_) {
    -      this.iframePool_.releaseObject(this.iframe_);
    -      this.iframe_ = null;
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Gets the iframe to use as a mask. Creates a new one if one has not been
    - * created yet.
    - * @return {!HTMLIFrameElement} The iframe.
    - * @private
    - */
    -goog.ui.IframeMask.prototype.getIframe_ = function() {
    -  if (!this.iframe_) {
    -    this.iframe_ = this.iframePool_ ?
    -        /** @type {HTMLIFrameElement} */ (this.iframePool_.getObject()) :
    -        goog.dom.iframe.createBlank(this.dom_);
    -    this.iframe_.style.cssText = goog.ui.IframeMask.HIDDEN_CSS_TEXT_;
    -    this.dom_.getDocument().body.appendChild(this.iframe_);
    -  }
    -  return this.iframe_;
    -};
    -
    -
    -/**
    - * Applies the iframe mask to the screen.
    - */
    -goog.ui.IframeMask.prototype.applyMask = function() {
    -  var iframe = this.getIframe_();
    -  var bounds = goog.style.getBounds(this.snapElement_);
    -  iframe.style.cssText =
    -      'position:absolute;' +
    -      'left:' + bounds.left + 'px;' +
    -      'top:' + bounds.top + 'px;' +
    -      'width:' + bounds.width + 'px;' +
    -      'height:' + bounds.height + 'px;' +
    -      'z-index:' + this.zIndex_;
    -  goog.style.setOpacity(iframe, this.opacity_);
    -  iframe.style.display = 'block';
    -};
    -
    -
    -/**
    - * Sets the opacity of the mask. Will take effect the next time the mask
    - * is applied.
    - * @param {number} opacity A value between 0 and 1, with 1 being
    - *     totally opaque.
    - */
    -goog.ui.IframeMask.prototype.setOpacity = function(opacity) {
    -  this.opacity_ = opacity;
    -};
    -
    -
    -/**
    - * Sets the z-index of the mask. Will take effect the next time the mask
    - * is applied.
    - * @param {number} zIndex A z-index value.
    - */
    -goog.ui.IframeMask.prototype.setZIndex = function(zIndex) {
    -  this.zIndex_ = zIndex;
    -};
    -
    -
    -/**
    - * Sets the element to use as the bounds of the mask. Takes effect immediately.
    - * @param {Element} snapElement The snap element, which the iframe will be
    - *     "snapped" around.
    - */
    -goog.ui.IframeMask.prototype.setSnapElement = function(snapElement) {
    -  this.snapElement_ = snapElement;
    -  if (this.iframe_ && goog.style.isElementShown(this.iframe_)) {
    -    this.applyMask();
    -  }
    -};
    -
    -
    -/**
    - * Listens on the specified target, hiding and showing the iframe mask
    - * when the given event types are dispatched.
    - * @param {goog.events.EventTarget} target The event target to listen on.
    - * @param {string} showEvent When this event fires, the mask will be applied.
    - * @param {string} hideEvent When this event fires, the mask will be hidden.
    - * @param {Element=} opt_snapElement When the mask is applied, it will
    - *     automatically snap to this element. If no element is specified, it will
    - *     use the default snap element.
    - */
    -goog.ui.IframeMask.prototype.listenOnTarget = function(target, showEvent,
    -    hideEvent, opt_snapElement) {
    -  var timerKey;
    -  this.handler_.listen(target, showEvent, function() {
    -    if (opt_snapElement) {
    -      this.setSnapElement(opt_snapElement);
    -    }
    -    // Check out the iframe asynchronously, so we don't block the SHOW
    -    // event and cause a bounce.
    -    timerKey = goog.Timer.callOnce(this.applyMask, 0, this);
    -  });
    -  this.handler_.listen(target, hideEvent, function() {
    -    if (timerKey) {
    -      goog.Timer.clear(timerKey);
    -      timerKey = null;
    -    }
    -    this.hideMask();
    -  });
    -};
    -
    -
    -/**
    - * Removes all handlers attached by listenOnTarget.
    - */
    -goog.ui.IframeMask.prototype.removeHandlers = function() {
    -  this.handler_.removeAll();
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/iframemask_test.html b/src/database/third_party/closure-library/closure/goog/ui/iframemask_test.html
    deleted file mode 100644
    index 98b6f4d60c6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/iframemask_test.html
    +++ /dev/null
    @@ -1,38 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -
    -  @author gboyer@google.com (Garrett Boyer)
    -  @author nicksantos@google.com (Nick Santos) (Ported to Closure)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   goog.ui.IframeMask Unit Test
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.IframeMaskTest');
    -  </script>
    -  <style type="text/css">
    -   #popup {
    -  position: absolute;
    -  left: 100px;
    -  top: 900px; /* so that you can see unit test failures */
    -  width: 300px;
    -  height: 400px;
    -}
    -  </style>
    - </head>
    - <body>
    -  <div id="sandbox">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/iframemask_test.js b/src/database/third_party/closure-library/closure/goog/ui/iframemask_test.js
    deleted file mode 100644
    index 4dd24b3dfcb..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/iframemask_test.js
    +++ /dev/null
    @@ -1,214 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.IframeMaskTest');
    -goog.setTestOnly('goog.ui.IframeMaskTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.dom.iframe');
    -goog.require('goog.structs.Pool');
    -goog.require('goog.style');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.StrictMock');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.IframeMask');
    -goog.require('goog.ui.Popup');
    -goog.require('goog.ui.PopupBase');
    -goog.require('goog.userAgent');
    -
    -var iframeMask;
    -var mockClock;
    -
    -function setUp() {
    -  goog.dom.getElement('sandbox').innerHTML = '<div id="popup"></div>';
    -  mockClock = new goog.testing.MockClock(true);
    -
    -  iframeMask = new goog.ui.IframeMask();
    -}
    -
    -function tearDown() {
    -  iframeMask.dispose();
    -  mockClock.dispose();
    -
    -  assertNoIframes();
    -}
    -
    -function findOneAndOnlyIframe() {
    -  var iframes = document.getElementsByTagName(goog.dom.TagName.IFRAME);
    -  assertEquals('There should be exactly 1 iframe in the document',
    -      1, iframes.length);
    -  return iframes[0];
    -}
    -
    -function assertNoIframes() {
    -  assertEquals('Expected no iframes in the document', 0,
    -      goog.dom.getElementsByTagNameAndClass(goog.dom.TagName.IFRAME).length);
    -}
    -
    -function testApplyFullScreenMask() {
    -  iframeMask.applyMask();
    -
    -  var iframe = findOneAndOnlyIframe();
    -  assertEquals('block', iframe.style.display);
    -  assertEquals('absolute', iframe.style.position);
    -
    -  // coerce zindex to a string
    -  assertEquals('1', iframe.style.zIndex + '');
    -
    -  iframeMask.hideMask();
    -  assertEquals('none', iframe.style.display);
    -}
    -
    -function testApplyOpacity() {
    -  iframeMask.setOpacity(0.3);
    -  iframeMask.applyMask();
    -
    -  if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9)) {
    -    assertContains('Expected opactity to be set in the CSS style',
    -        '30', findOneAndOnlyIframe().style.cssText);
    -  } else {
    -    assertContains('Expected opactity to be set in the CSS style',
    -        '0.3', findOneAndOnlyIframe().style.cssText);
    -  }
    -}
    -
    -function testApplyZIndex() {
    -  iframeMask.setZIndex(5);
    -  iframeMask.applyMask();
    -
    -  // coerce zindex to a string
    -  assertEquals('5', findOneAndOnlyIframe().style.zIndex + '');
    -}
    -
    -function testSnapElement() {
    -  iframeMask.setSnapElement(goog.dom.getElement('popup'));
    -  iframeMask.applyMask();
    -
    -  var iframe = findOneAndOnlyIframe();
    -  var bounds = goog.style.getBounds(iframe);
    -  assertEquals(100, bounds.left);
    -  assertEquals(900, bounds.top);
    -  assertEquals(300, bounds.width);
    -  assertEquals(400, bounds.height);
    -
    -  iframeMask.setSnapElement(document.documentElement);
    -
    -  // Make sure that snapping to a different element changes the bounds.
    -  assertNotEquals('Snap element not updated',
    -      400, goog.style.getBounds(iframe).height);
    -}
    -
    -function testAttachToPopup() {
    -  var popup = new goog.ui.Popup(goog.dom.getElement('popup'));
    -  iframeMask.listenOnTarget(popup, goog.ui.PopupBase.EventType.SHOW,
    -      goog.ui.PopupBase.EventType.HIDE, goog.dom.getElement('popup'));
    -
    -  assertNoIframes();
    -  popup.setVisible(true);
    -  assertNoIframes();
    -
    -  // Tick because the showing of the iframe mask happens asynchronously.
    -  // (Otherwise the handling of the mousedown can take so long that a bounce
    -  // occurs).
    -  mockClock.tick(1);
    -
    -  var iframe = findOneAndOnlyIframe();
    -  var bounds = goog.style.getBounds(iframe);
    -  assertEquals(300, bounds.width);
    -  assertEquals(400, bounds.height);
    -  assertEquals('block', iframe.style.display);
    -
    -  popup.setVisible(false);
    -  assertEquals('none', iframe.style.display);
    -}
    -
    -function testQuickHidingPopup() {
    -  var popup = new goog.ui.Popup(goog.dom.getElement('popup'));
    -  iframeMask.listenOnTarget(popup, goog.ui.PopupBase.EventType.SHOW,
    -      goog.ui.PopupBase.EventType.HIDE);
    -
    -  assertNoIframes();
    -  popup.setVisible(true);
    -  assertNoIframes();
    -  popup.setVisible(false);
    -  assertNoIframes();
    -
    -  // Tick because the showing of the iframe mask happens asynchronously.
    -  // (Otherwise the handling of the mousedown can take so long that a bounce
    -  // occurs).
    -  mockClock.tick(1);
    -  assertNoIframes();
    -}
    -
    -function testRemoveHandlers() {
    -  var popup = new goog.ui.Popup(goog.dom.getElement('popup'));
    -  iframeMask.listenOnTarget(popup, goog.ui.PopupBase.EventType.SHOW,
    -      goog.ui.PopupBase.EventType.HIDE);
    -  iframeMask.removeHandlers();
    -  popup.setVisible(true);
    -
    -  // Tick because the showing of the iframe mask happens asynchronously.
    -  // (Otherwise the handling of the mousedown can take so long that a bounce
    -  // occurs).
    -  mockClock.tick(1);
    -  assertNoIframes();
    -}
    -
    -function testIframePool() {
    -  var iframe = goog.dom.iframe.createBlank(goog.dom.getDomHelper());
    -  var mockPool = new goog.testing.StrictMock(goog.structs.Pool);
    -  mockPool.getObject();
    -  mockPool.$returns(iframe);
    -
    -  mockPool.$replay();
    -
    -  iframeMask.dispose();
    -
    -  // Create a new iframe mask with a pool, and verify that it checks
    -  // its iframe out of the pool instead of creating one.
    -  iframeMask = new goog.ui.IframeMask(null, mockPool);
    -  iframeMask.applyMask();
    -  mockPool.$verify();
    -  findOneAndOnlyIframe();
    -
    -  mockPool.$reset();
    -
    -  mockPool.releaseObject(iframe);
    -  mockPool.$replay();
    -
    -  // When the iframe mask has a pool, the pool is responsible for
    -  // removing the iframe from the DOM.
    -  iframeMask.hideMask();
    -  mockPool.$verify();
    -  findOneAndOnlyIframe();
    -
    -  // And showing the iframe again should check it out of the pool again.
    -  mockPool.$reset();
    -  mockPool.getObject();
    -  mockPool.$returns(iframe);
    -  mockPool.$replay();
    -
    -  iframeMask.applyMask();
    -  mockPool.$verify();
    -
    -  // When the test is over, the iframe mask should be disposed. Make sure
    -  // that the pool removes the iframe from the page.
    -  mockPool.$reset();
    -  mockPool.releaseObject(iframe);
    -  mockPool.$does(function() {
    -    goog.dom.removeNode(iframe);
    -  });
    -  mockPool.$replay();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/imagelessbuttonrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/imagelessbuttonrenderer.js
    deleted file mode 100644
    index d4c36d0bbde..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/imagelessbuttonrenderer.js
    +++ /dev/null
    @@ -1,207 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview An alternative custom button renderer that uses even more CSS
    - * voodoo than the default implementation to render custom buttons with fake
    - * rounded corners and dimensionality (via a subtle flat shadow on the bottom
    - * half of the button) without the use of images.
    - *
    - * Based on the Custom Buttons 3.1 visual specification, see
    - * http://go/custombuttons
    - *
    - * @author eae@google.com (Emil A Eklund)
    - * @see ../demos/imagelessbutton.html
    - */
    -
    -goog.provide('goog.ui.ImagelessButtonRenderer');
    -
    -goog.require('goog.dom.classlist');
    -goog.require('goog.ui.Button');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.CustomButtonRenderer');
    -goog.require('goog.ui.INLINE_BLOCK_CLASSNAME');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * Custom renderer for {@link goog.ui.Button}s. Imageless buttons can contain
    - * almost arbitrary HTML content, will flow like inline elements, but can be
    - * styled like block-level elements.
    - *
    - * @deprecated These contain a lot of unnecessary DOM for modern user agents.
    - *     Please use a simpler button renderer like css3buttonrenderer.
    - * @constructor
    - * @extends {goog.ui.CustomButtonRenderer}
    - */
    -goog.ui.ImagelessButtonRenderer = function() {
    -  goog.ui.CustomButtonRenderer.call(this);
    -};
    -goog.inherits(goog.ui.ImagelessButtonRenderer, goog.ui.CustomButtonRenderer);
    -
    -
    -/**
    - * The singleton instance of this renderer class.
    - * @type {goog.ui.ImagelessButtonRenderer?}
    - * @private
    - */
    -goog.ui.ImagelessButtonRenderer.instance_ = null;
    -goog.addSingletonGetter(goog.ui.ImagelessButtonRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.ImagelessButtonRenderer.CSS_CLASS =
    -    goog.getCssName('goog-imageless-button');
    -
    -
    -/**
    - * Returns the button's contents wrapped in the following DOM structure:
    - *    <div class="goog-inline-block goog-imageless-button">
    - *      <div class="goog-inline-block goog-imageless-button-outer-box">
    - *        <div class="goog-imageless-button-inner-box">
    - *          <div class="goog-imageless-button-pos-box">
    - *            <div class="goog-imageless-button-top-shadow">&nbsp;</div>
    - *            <div class="goog-imageless-button-content">Contents...</div>
    - *          </div>
    - *        </div>
    - *      </div>
    - *    </div>
    - * @override
    - */
    -goog.ui.ImagelessButtonRenderer.prototype.createDom;
    -
    -
    -/** @override */
    -goog.ui.ImagelessButtonRenderer.prototype.getContentElement = function(
    -    element) {
    -  return /** @type {Element} */ (element && element.firstChild &&
    -      element.firstChild.firstChild &&
    -      element.firstChild.firstChild.firstChild.lastChild);
    -};
    -
    -
    -/**
    - * Takes a text caption or existing DOM structure, and returns the content
    - * wrapped in a pseudo-rounded-corner box.  Creates the following DOM structure:
    - *  <div class="goog-inline-block goog-imageless-button-outer-box">
    - *    <div class="goog-inline-block goog-imageless-button-inner-box">
    - *      <div class="goog-imageless-button-pos">
    - *        <div class="goog-imageless-button-top-shadow">&nbsp;</div>
    - *        <div class="goog-imageless-button-content">Contents...</div>
    - *      </div>
    - *    </div>
    - *  </div>
    - * Used by both {@link #createDom} and {@link #decorate}.  To be overridden
    - * by subclasses.
    - * @param {goog.ui.ControlContent} content Text caption or DOM structure to wrap
    - *     in a box.
    - * @param {goog.dom.DomHelper} dom DOM helper, used for document interaction.
    - * @return {Element} Pseudo-rounded-corner box containing the content.
    - * @override
    - */
    -goog.ui.ImagelessButtonRenderer.prototype.createButton = function(content,
    -                                                                  dom) {
    -  var baseClass = this.getCssClass();
    -  var inlineBlock = goog.ui.INLINE_BLOCK_CLASSNAME + ' ';
    -  return dom.createDom('div',
    -      inlineBlock + goog.getCssName(baseClass, 'outer-box'),
    -      dom.createDom('div',
    -          inlineBlock + goog.getCssName(baseClass, 'inner-box'),
    -          dom.createDom('div', goog.getCssName(baseClass, 'pos'),
    -              dom.createDom('div', goog.getCssName(baseClass, 'top-shadow'),
    -                  '\u00A0'),
    -              dom.createDom('div', goog.getCssName(baseClass, 'content'),
    -                  content))));
    -};
    -
    -
    -/**
    - * Check if the button's element has a box structure.
    - * @param {goog.ui.Button} button Button instance whose structure is being
    - *     checked.
    - * @param {Element} element Element of the button.
    - * @return {boolean} Whether the element has a box structure.
    - * @protected
    - * @override
    - */
    -goog.ui.ImagelessButtonRenderer.prototype.hasBoxStructure = function(
    -    button, element) {
    -  var outer = button.getDomHelper().getFirstElementChild(element);
    -  var outerClassName = goog.getCssName(this.getCssClass(), 'outer-box');
    -  if (outer && goog.dom.classlist.contains(outer, outerClassName)) {
    -
    -    var inner = button.getDomHelper().getFirstElementChild(outer);
    -    var innerClassName = goog.getCssName(this.getCssClass(), 'inner-box');
    -    if (inner && goog.dom.classlist.contains(inner, innerClassName)) {
    -
    -      var pos = button.getDomHelper().getFirstElementChild(inner);
    -      var posClassName = goog.getCssName(this.getCssClass(), 'pos');
    -      if (pos && goog.dom.classlist.contains(pos, posClassName)) {
    -
    -        var shadow = button.getDomHelper().getFirstElementChild(pos);
    -        var shadowClassName = goog.getCssName(
    -            this.getCssClass(), 'top-shadow');
    -        if (shadow && goog.dom.classlist.contains(shadow, shadowClassName)) {
    -
    -          var content = button.getDomHelper().getNextElementSibling(shadow);
    -          var contentClassName = goog.getCssName(
    -              this.getCssClass(), 'content');
    -          if (content &&
    -              goog.dom.classlist.contains(content, contentClassName)) {
    -            // We have a proper box structure.
    -            return true;
    -          }
    -        }
    -      }
    -    }
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Returns the CSS class to be applied to the root element of components
    - * rendered using this renderer.
    - * @return {string} Renderer-specific CSS class.
    - * @override
    - */
    -goog.ui.ImagelessButtonRenderer.prototype.getCssClass = function() {
    -  return goog.ui.ImagelessButtonRenderer.CSS_CLASS;
    -};
    -
    -
    -// Register a decorator factory function for goog.ui.ImagelessButtonRenderer.
    -goog.ui.registry.setDecoratorByClassName(
    -    goog.ui.ImagelessButtonRenderer.CSS_CLASS,
    -    function() {
    -      return new goog.ui.Button(null,
    -          goog.ui.ImagelessButtonRenderer.getInstance());
    -    });
    -
    -
    -// Register a decorator factory function for toggle buttons using the
    -// goog.ui.ImagelessButtonRenderer.
    -goog.ui.registry.setDecoratorByClassName(
    -    goog.getCssName('goog-imageless-toggle-button'),
    -    function() {
    -      var button = new goog.ui.Button(null,
    -          goog.ui.ImagelessButtonRenderer.getInstance());
    -      button.setSupportedState(goog.ui.Component.State.CHECKED, true);
    -      return button;
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/imagelessmenubuttonrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/imagelessmenubuttonrenderer.js
    deleted file mode 100644
    index 1ad27d66e0e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/imagelessmenubuttonrenderer.js
    +++ /dev/null
    @@ -1,210 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview An alternative custom button renderer that uses even more CSS
    - * voodoo than the default implementation to render custom buttons with fake
    - * rounded corners and dimensionality (via a subtle flat shadow on the bottom
    - * half of the button) without the use of images.
    - *
    - * Based on the Custom Buttons 3.1 visual specification, see
    - * http://go/custombuttons
    - *
    - * @author eae@google.com (Emil A Eklund)
    - * @see ../demos/imagelessmenubutton.html
    - */
    -
    -goog.provide('goog.ui.ImagelessMenuButtonRenderer');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.ui.INLINE_BLOCK_CLASSNAME');
    -goog.require('goog.ui.MenuButton');
    -goog.require('goog.ui.MenuButtonRenderer');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * Custom renderer for {@link goog.ui.MenuButton}s. Imageless buttons can
    - * contain almost arbitrary HTML content, will flow like inline elements, but
    - * can be styled like block-level elements.
    - *
    - * @deprecated These contain a lot of unnecessary DOM for modern user agents.
    - *     Please use a simpler button renderer like css3buttonrenderer.
    - * @constructor
    - * @extends {goog.ui.MenuButtonRenderer}
    - * @final
    - */
    -goog.ui.ImagelessMenuButtonRenderer = function() {
    -  goog.ui.MenuButtonRenderer.call(this);
    -};
    -goog.inherits(goog.ui.ImagelessMenuButtonRenderer, goog.ui.MenuButtonRenderer);
    -
    -
    -/**
    - * The singleton instance of this renderer class.
    - * @type {goog.ui.ImagelessMenuButtonRenderer?}
    - * @private
    - */
    -goog.ui.ImagelessMenuButtonRenderer.instance_ = null;
    -goog.addSingletonGetter(goog.ui.ImagelessMenuButtonRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.ImagelessMenuButtonRenderer.CSS_CLASS =
    -    goog.getCssName('goog-imageless-button');
    -
    -
    -/** @override */
    -goog.ui.ImagelessMenuButtonRenderer.prototype.getContentElement = function(
    -    element) {
    -  if (element) {
    -    var captionElem = goog.dom.getElementsByTagNameAndClass(
    -        '*', goog.getCssName(this.getCssClass(), 'caption'), element)[0];
    -    return captionElem;
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * Returns true if this renderer can decorate the element.  Overrides
    - * {@link goog.ui.MenuButtonRenderer#canDecorate} by returning true if the
    - * element is a DIV, false otherwise.
    - * @param {Element} element Element to decorate.
    - * @return {boolean} Whether the renderer can decorate the element.
    - * @override
    - */
    -goog.ui.ImagelessMenuButtonRenderer.prototype.canDecorate = function(element) {
    -  return element.tagName == goog.dom.TagName.DIV;
    -};
    -
    -
    -/**
    - * Takes a text caption or existing DOM structure, and returns the content
    - * wrapped in a pseudo-rounded-corner box.  Creates the following DOM structure:
    - *  <div class="goog-inline-block goog-imageless-button">
    - *    <div class="goog-inline-block goog-imageless-button-outer-box">
    - *      <div class="goog-imageless-button-inner-box">
    - *        <div class="goog-imageless-button-pos-box">
    - *          <div class="goog-imageless-button-top-shadow">&nbsp;</div>
    - *          <div class="goog-imageless-button-content
    - *                      goog-imageless-menubutton-caption">Contents...
    - *          </div>
    - *          <div class="goog-imageless-menubutton-dropdown"></div>
    - *        </div>
    - *      </div>
    - *    </div>
    - *  </div>
    -
    - * Used by both {@link #createDom} and {@link #decorate}.  To be overridden
    - * by subclasses.
    - * @param {goog.ui.ControlContent} content Text caption or DOM structure to wrap
    - *     in a box.
    - * @param {goog.dom.DomHelper} dom DOM helper, used for document interaction.
    - * @return {!Element} Pseudo-rounded-corner box containing the content.
    - * @override
    - */
    -goog.ui.ImagelessMenuButtonRenderer.prototype.createButton = function(content,
    -                                                                      dom) {
    -  var baseClass = this.getCssClass();
    -  var inlineBlock = goog.ui.INLINE_BLOCK_CLASSNAME + ' ';
    -  return dom.createDom('div',
    -      inlineBlock + goog.getCssName(baseClass, 'outer-box'),
    -      dom.createDom('div',
    -          inlineBlock + goog.getCssName(baseClass, 'inner-box'),
    -          dom.createDom('div', goog.getCssName(baseClass, 'pos'),
    -              dom.createDom('div', goog.getCssName(baseClass, 'top-shadow'),
    -                  '\u00A0'),
    -              dom.createDom('div', [goog.getCssName(baseClass, 'content'),
    -                                    goog.getCssName(baseClass, 'caption'),
    -                                    goog.getCssName('goog-inline-block')],
    -                            content),
    -              dom.createDom('div', [goog.getCssName(baseClass, 'dropdown'),
    -                                    goog.getCssName('goog-inline-block')]))));
    -};
    -
    -
    -/**
    - * Check if the button's element has a box structure.
    - * @param {goog.ui.Button} button Button instance whose structure is being
    - *     checked.
    - * @param {Element} element Element of the button.
    - * @return {boolean} Whether the element has a box structure.
    - * @protected
    - * @override
    - */
    -goog.ui.ImagelessMenuButtonRenderer.prototype.hasBoxStructure = function(
    -    button, element) {
    -  var outer = button.getDomHelper().getFirstElementChild(element);
    -  var outerClassName = goog.getCssName(this.getCssClass(), 'outer-box');
    -  if (outer && goog.dom.classlist.contains(outer, outerClassName)) {
    -
    -    var inner = button.getDomHelper().getFirstElementChild(outer);
    -    var innerClassName = goog.getCssName(this.getCssClass(), 'inner-box');
    -    if (inner && goog.dom.classlist.contains(inner, innerClassName)) {
    -
    -      var pos = button.getDomHelper().getFirstElementChild(inner);
    -      var posClassName = goog.getCssName(this.getCssClass(), 'pos');
    -      if (pos && goog.dom.classlist.contains(pos, posClassName)) {
    -
    -        var shadow = button.getDomHelper().getFirstElementChild(pos);
    -        var shadowClassName = goog.getCssName(
    -            this.getCssClass(), 'top-shadow');
    -        if (shadow && goog.dom.classlist.contains(shadow, shadowClassName)) {
    -
    -          var content = button.getDomHelper().getNextElementSibling(shadow);
    -          var contentClassName = goog.getCssName(
    -              this.getCssClass(), 'content');
    -          if (content &&
    -              goog.dom.classlist.contains(content, contentClassName)) {
    -            // We have a proper box structure.
    -            return true;
    -          }
    -        }
    -      }
    -    }
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Returns the CSS class to be applied to the root element of components
    - * rendered using this renderer.
    - * @return {string} Renderer-specific CSS class.
    - * @override
    - */
    -goog.ui.ImagelessMenuButtonRenderer.prototype.getCssClass = function() {
    -  return goog.ui.ImagelessMenuButtonRenderer.CSS_CLASS;
    -};
    -
    -
    -// Register a decorator factory function for
    -// goog.ui.ImagelessMenuButtonRenderer. Since we're using goog-imageless-button
    -// as the base class in order to get the same styling as
    -// goog.ui.ImagelessButtonRenderer, we need to be explicit about giving
    -// goog-imageless-menu-button here.
    -goog.ui.registry.setDecoratorByClassName(
    -    goog.getCssName('goog-imageless-menu-button'),
    -    function() {
    -      return new goog.ui.MenuButton(null, null,
    -          goog.ui.ImagelessMenuButtonRenderer.getInstance());
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/inputdatepicker.js b/src/database/third_party/closure-library/closure/goog/ui/inputdatepicker.js
    deleted file mode 100644
    index 1613c797679..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/inputdatepicker.js
    +++ /dev/null
    @@ -1,339 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Input Date Picker implementation.  Pairs a
    - * goog.ui.PopupDatePicker with an input element and handles the input from
    - * either.
    - *
    - * @see ../demos/inputdatepicker.html
    - */
    -
    -goog.provide('goog.ui.InputDatePicker');
    -
    -goog.require('goog.date.DateTime');
    -goog.require('goog.dom');
    -goog.require('goog.string');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.DatePicker');
    -goog.require('goog.ui.PopupBase');
    -goog.require('goog.ui.PopupDatePicker');
    -
    -
    -
    -/**
    - * Input date picker widget.
    - *
    - * @param {goog.i18n.DateTimeFormat} dateTimeFormatter A formatter instance
    - *     used to format the date picker's date for display in the input element.
    - * @param {goog.i18n.DateTimeParse} dateTimeParser A parser instance used to
    - *     parse the input element's string as a date to set the picker.
    - * @param {goog.ui.DatePicker=} opt_datePicker Optional DatePicker.  This
    - *     enables the use of a custom date-picker instance.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @extends {goog.ui.Component}
    - * @constructor
    - */
    -goog.ui.InputDatePicker = function(
    -    dateTimeFormatter, dateTimeParser, opt_datePicker, opt_domHelper) {
    -  goog.ui.Component.call(this, opt_domHelper);
    -
    -  this.dateTimeFormatter_ = dateTimeFormatter;
    -  this.dateTimeParser_ = dateTimeParser;
    -
    -  this.popupDatePicker_ = new goog.ui.PopupDatePicker(
    -      opt_datePicker, opt_domHelper);
    -  this.addChild(this.popupDatePicker_);
    -  this.popupDatePicker_.setAllowAutoFocus(false);
    -};
    -goog.inherits(goog.ui.InputDatePicker, goog.ui.Component);
    -goog.tagUnsealableClass(goog.ui.InputDatePicker);
    -
    -
    -/**
    - * Used to format the date picker's date for display in the input element.
    - * @type {goog.i18n.DateTimeFormat}
    - * @private
    - */
    -goog.ui.InputDatePicker.prototype.dateTimeFormatter_ = null;
    -
    -
    -/**
    - * Used to parse the input element's string as a date to set the picker.
    - * @type {goog.i18n.DateTimeParse}
    - * @private
    - */
    -goog.ui.InputDatePicker.prototype.dateTimeParser_ = null;
    -
    -
    -/**
    - * The instance of goog.ui.PopupDatePicker used to pop up and select the date.
    - * @type {goog.ui.PopupDatePicker}
    - * @private
    - */
    -goog.ui.InputDatePicker.prototype.popupDatePicker_ = null;
    -
    -
    -/**
    - * The element that the PopupDatePicker should be parented to. Defaults to the
    - * body element of the page.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.InputDatePicker.prototype.popupParentElement_ = null;
    -
    -
    -/**
    - * Returns the PopupDatePicker's internal DatePicker instance.  This can be
    - * used to customize the date picker's styling.
    - *
    - * @return {goog.ui.DatePicker} The internal DatePicker instance.
    - */
    -goog.ui.InputDatePicker.prototype.getDatePicker = function() {
    -  return this.popupDatePicker_.getDatePicker();
    -};
    -
    -
    -/**
    - * Returns the PopupDatePicker instance.
    - *
    - * @return {goog.ui.PopupDatePicker} Popup instance.
    - */
    -goog.ui.InputDatePicker.prototype.getPopupDatePicker = function() {
    -  return this.popupDatePicker_;
    -};
    -
    -
    -/**
    - * Returns the selected date, if any.  Compares the dates from the date picker
    - * and the input field, causing them to be synced if different.
    - * @return {goog.date.Date?} The selected date, if any.
    - */
    -goog.ui.InputDatePicker.prototype.getDate = function() {
    -
    -  // The user expectation is that the date be whatever the input shows.
    -  // This method biases towards the input value to conform to that expectation.
    -
    -  var inputDate = this.getInputValueAsDate_();
    -  var pickerDate = this.popupDatePicker_.getDate();
    -
    -  if (inputDate && pickerDate) {
    -    if (!inputDate.equals(pickerDate)) {
    -      this.popupDatePicker_.setDate(inputDate);
    -    }
    -  } else {
    -    this.popupDatePicker_.setDate(null);
    -  }
    -
    -  return inputDate;
    -};
    -
    -
    -/**
    - * Sets the selected date.  See goog.ui.PopupDatePicker.setDate().
    - * @param {goog.date.Date?} date The date to set.
    - */
    -goog.ui.InputDatePicker.prototype.setDate = function(date) {
    -  this.popupDatePicker_.setDate(date);
    -};
    -
    -
    -/**
    - * Sets the value of the input element.  This can be overridden to support
    - * alternative types of input setting.
    - *
    - * @param {string} value The value to set.
    - */
    -goog.ui.InputDatePicker.prototype.setInputValue = function(value) {
    -  var el = this.getElement();
    -  if (el.labelInput_) {
    -    var labelInput = /** @type {goog.ui.LabelInput} */ (el.labelInput_);
    -    labelInput.setValue(value);
    -  } else {
    -    el.value = value;
    -  }
    -};
    -
    -
    -/**
    - * Returns the value of the input element.  This can be overridden to support
    - * alternative types of input getting.
    - *
    - * @return {string} The input value.
    - */
    -goog.ui.InputDatePicker.prototype.getInputValue = function() {
    -  var el = this.getElement();
    -  if (el.labelInput_) {
    -    var labelInput = /** @type {goog.ui.LabelInput} */ (el.labelInput_);
    -    return labelInput.getValue();
    -  } else {
    -    return el.value;
    -  }
    -};
    -
    -
    -/**
    - * Sets the value of the input element from date object.
    - *
    - * @param {?goog.date.Date} date The value to set.
    - * @private
    - */
    -goog.ui.InputDatePicker.prototype.setInputValueAsDate_ = function(date) {
    -  this.setInputValue(date ? this.dateTimeFormatter_.format(date) : '');
    -};
    -
    -
    -/**
    - * Gets the input element value and attempts to parse it as a date.
    - *
    - * @return {goog.date.Date?} The date object is returned if the parse
    - *      is successful, null is returned on failure.
    - * @private
    - */
    -goog.ui.InputDatePicker.prototype.getInputValueAsDate_ = function() {
    -  var value = goog.string.trim(this.getInputValue());
    -  if (value) {
    -    var date = new goog.date.DateTime();
    -    // DateTime needed as parse assumes it can call getHours(), getMinutes(),
    -    // etc, on the date if hours and minutes aren't defined.
    -    if (this.dateTimeParser_.strictParse(value, date) > 0) {
    -      // Parser with YYYY format string will interpret 1 as year 1 A.D.
    -      // However, datepicker.setDate() method will change it into 1901.
    -      // Same is true for any other pattern when number entered by user is
    -      // different from number of digits in the pattern. (YY and 1 will be 1AD).
    -      // See i18n/datetimeparse.js
    -      // Conversion happens in goog.date.Date/DateTime constructor
    -      // when it calls new Date(year...). See ui/datepicker.js.
    -      return date;
    -    }
    -  }
    -
    -  return null;
    -};
    -
    -
    -/**
    - * Creates an input element for use with the popup date picker.
    - * @override
    - */
    -goog.ui.InputDatePicker.prototype.createDom = function() {
    -  this.setElementInternal(
    -      this.getDomHelper().createDom('input', {'type': 'text'}));
    -  this.popupDatePicker_.createDom();
    -};
    -
    -
    -/**
    - * Sets the element that the PopupDatePicker should be parented to. If not set,
    - * defaults to the body element of the page.
    - * @param {Element} el The element that the PopupDatePicker should be parented
    - *     to.
    - */
    -goog.ui.InputDatePicker.prototype.setPopupParentElement = function(el) {
    -  this.popupParentElement_ = el;
    -};
    -
    -
    -/** @override */
    -goog.ui.InputDatePicker.prototype.enterDocument = function() {
    -  goog.ui.InputDatePicker.superClass_.enterDocument.call(this);
    -  var el = this.getElement();
    -
    -  (this.popupParentElement_ || this.getDomHelper().getDocument().body).
    -      appendChild(this.popupDatePicker_.getElement());
    -  this.popupDatePicker_.enterDocument();
    -  this.popupDatePicker_.attach(el);
    -
    -  // Set the date picker to have the input's initial value, if any.
    -  this.popupDatePicker_.setDate(this.getInputValueAsDate_());
    -
    -  var handler = this.getHandler();
    -  handler.listen(this.popupDatePicker_, goog.ui.DatePicker.Events.CHANGE,
    -                 this.onDateChanged_);
    -  handler.listen(this.popupDatePicker_, goog.ui.PopupBase.EventType.SHOW,
    -                 this.onPopup_);
    -};
    -
    -
    -/** @override */
    -goog.ui.InputDatePicker.prototype.exitDocument = function() {
    -  goog.ui.InputDatePicker.superClass_.exitDocument.call(this);
    -  var el = this.getElement();
    -
    -  this.popupDatePicker_.detach(el);
    -  this.popupDatePicker_.exitDocument();
    -  goog.dom.removeNode(this.popupDatePicker_.getElement());
    -};
    -
    -
    -/** @override */
    -goog.ui.InputDatePicker.prototype.decorateInternal = function(element) {
    -  goog.ui.InputDatePicker.superClass_.decorateInternal.call(this, element);
    -
    -  this.popupDatePicker_.createDom();
    -};
    -
    -
    -/** @override */
    -goog.ui.InputDatePicker.prototype.disposeInternal = function() {
    -  goog.ui.InputDatePicker.superClass_.disposeInternal.call(this);
    -  this.popupDatePicker_.dispose();
    -  this.popupDatePicker_ = null;
    -  this.popupParentElement_ = null;
    -};
    -
    -
    -/**
    - * See goog.ui.PopupDatePicker.showPopup().
    - * @param {Element} element Reference element for displaying the popup -- popup
    - *     will appear at the bottom-left corner of this element.
    - */
    -goog.ui.InputDatePicker.prototype.showForElement = function(element) {
    -  this.popupDatePicker_.showPopup(element);
    -};
    -
    -
    -/**
    - * See goog.ui.PopupDatePicker.hidePopup().
    - */
    -goog.ui.InputDatePicker.prototype.hidePopup = function() {
    -  this.popupDatePicker_.hidePopup();
    -};
    -
    -
    -/**
    - * Event handler for popup date picker popup events.
    - *
    - * @param {goog.events.Event} e popup event.
    - * @private
    - */
    -goog.ui.InputDatePicker.prototype.onPopup_ = function(e) {
    -  var inputValueAsDate = this.getInputValueAsDate_();
    -  this.setDate(inputValueAsDate);
    -  // don't overwrite the input value with empty date if input is not valid
    -  if (inputValueAsDate) {
    -    this.setInputValueAsDate_(this.getDatePicker().getDate());
    -  }
    -};
    -
    -
    -/**
    - * Event handler for date change events.  Called when the date changes.
    - *
    - * @param {goog.ui.DatePickerEvent} e Date change event.
    - * @private
    - */
    -goog.ui.InputDatePicker.prototype.onDateChanged_ = function(e) {
    -  this.setInputValueAsDate_(e.date);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/inputdatepicker_test.html b/src/database/third_party/closure-library/closure/goog/ui/inputdatepicker_test.html
    deleted file mode 100644
    index afc340a070f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/inputdatepicker_test.html
    +++ /dev/null
    @@ -1,29 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -Author: bolinfest@google.com (Michael Bolin)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.InputDatePicker
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.InputDatePickerTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="renderElement">
    -  </div>
    -  <div id="popupParent">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/inputdatepicker_test.js b/src/database/third_party/closure-library/closure/goog/ui/inputdatepicker_test.js
    deleted file mode 100644
    index 5a43cf8af07..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/inputdatepicker_test.js
    +++ /dev/null
    @@ -1,130 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.InputDatePickerTest');
    -goog.setTestOnly('goog.ui.InputDatePickerTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.i18n.DateTimeFormat');
    -goog.require('goog.i18n.DateTimeParse');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.InputDatePicker');
    -
    -var dateTimeFormatter = new goog.i18n.DateTimeFormat('MM/dd/yyyy');
    -var dateTimeParser = new goog.i18n.DateTimeParse('MM/dd/yyyy');
    -
    -var inputDatePicker;
    -var popupDatePicker;
    -
    -function setUp() {
    -}
    -
    -function tearDown() {
    -  if (inputDatePicker) {
    -    inputDatePicker.dispose();
    -  }
    -  if (popupDatePicker) {
    -    popupDatePicker.dispose();
    -  }
    -  goog.dom.getElement('renderElement').innerHTML = '';
    -  goog.dom.getElement('popupParent').innerHTML = '';
    -}
    -
    -
    -/**
    - * Ensure that if setPopupParentElement is not called, that the
    - * PopupDatePicker is parented to the body element.
    - */
    -function test_setPopupParentElementDefault() {
    -  setPopupParentElement_(null);
    -  assertEquals('PopupDatePicker should be parented to the body element',
    -      document.body,
    -      popupDatePicker.getElement().parentNode);
    -}
    -
    -
    -/**
    - * Ensure that if setPopupParentElement is called, that the
    - * PopupDatePicker is parented to the specified element.
    - */
    -function test_setPopupParentElement() {
    -  var popupParentElement = goog.dom.getElement('popupParent');
    -  setPopupParentElement_(popupParentElement);
    -  assertEquals('PopupDatePicker should be parented to the popupParent DIV',
    -      popupParentElement,
    -      popupDatePicker.getElement().parentNode);
    -}
    -
    -
    -/**
    - * Creates a new InputDatePicker and calls setPopupParentElement with the
    - * specified element, if provided. If el is null, then setPopupParentElement
    - * is not called.
    - * @param {Element} el If non-null, the argument to pass to
    - *     inputDatePicker.setPopupParentElement().
    - * @private
    - */
    -function setPopupParentElement_(el) {
    -  inputDatePicker = new goog.ui.InputDatePicker(
    -      dateTimeFormatter,
    -      dateTimeParser);
    -
    -  if (el) {
    -    inputDatePicker.setPopupParentElement(el);
    -  }
    -
    -  inputDatePicker.render(goog.dom.getElement('renderElement'));
    -  popupDatePicker = inputDatePicker.popupDatePicker_;
    -}
    -
    -
    -function test_ItParsesDataCorrectly() {
    -  inputDatePicker = new goog.ui.InputDatePicker(
    -      dateTimeFormatter,
    -      dateTimeParser);
    -  inputDatePicker.render(goog.dom.getElement('renderElement'));
    -
    -  inputDatePicker.createDom();
    -  inputDatePicker.setInputValue('8/9/2009');
    -
    -  var parsedDate = inputDatePicker.getInputValueAsDate_();
    -  assertEquals(2009, parsedDate.getYear());
    -  assertEquals(7, parsedDate.getMonth()); // Months start from 0
    -  assertEquals(9, parsedDate.getDate());
    -}
    -
    -function test_ItUpdatesItsValueOnPopupShown() {
    -  inputDatePicker = new goog.ui.InputDatePicker(
    -      dateTimeFormatter,
    -      dateTimeParser);
    -
    -  setPopupParentElement_(null);
    -  inputDatePicker.setInputValue('1/1/1');
    -  inputDatePicker.showForElement(document.body);
    -  var inputValue = inputDatePicker.getInputValue();
    -  assertEquals('01/01/0001', inputValue);
    -}
    -
    -function test_ItDoesNotClearInputOnPopupShown() {
    -  // if popup does not have a date set, don't update input value
    -  inputDatePicker = new goog.ui.InputDatePicker(
    -      dateTimeFormatter,
    -      dateTimeParser);
    -
    -  setPopupParentElement_(null);
    -  inputDatePicker.setInputValue('i_am_not_a_date');
    -  inputDatePicker.showForElement(document.body);
    -  var inputValue = inputDatePicker.getInputValue();
    -  assertEquals('i_am_not_a_date', inputValue);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/itemevent.js b/src/database/third_party/closure-library/closure/goog/ui/itemevent.js
    deleted file mode 100644
    index fb127b5e057..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/itemevent.js
    +++ /dev/null
    @@ -1,51 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Definition of the goog.ui.ItemEvent class.
    - *
    - */
    -
    -goog.provide('goog.ui.ItemEvent');
    -
    -
    -goog.require('goog.events.Event');
    -
    -
    -
    -/**
    - * Generic ui event class for events that take a single item like a menu click
    - * event.
    - *
    - * @constructor
    - * @extends {goog.events.Event}
    - * @param {string} type Event Type.
    - * @param {Object} target Reference to the object that is the target
    - *                        of this event.
    - * @param {Object} item The item that was clicked.
    - * @final
    - */
    -goog.ui.ItemEvent = function(type, target, item) {
    -  goog.events.Event.call(this, type, target);
    -
    -  /**
    -   * Item for the event. The type of this object is specific to the type
    -   * of event. For a menu, it would be the menu item that was clicked. For a
    -   * listbox selection, it would be the listitem that was selected.
    -   *
    -   * @type {Object}
    -   */
    -  this.item = item;
    -};
    -goog.inherits(goog.ui.ItemEvent, goog.events.Event);
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/keyboardshortcuthandler.js b/src/database/third_party/closure-library/closure/goog/ui/keyboardshortcuthandler.js
    deleted file mode 100644
    index 5745e959715..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/keyboardshortcuthandler.js
    +++ /dev/null
    @@ -1,1158 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Generic keyboard shortcut handler.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - * @see ../demos/keyboardshortcuts.html
    - */
    -
    -goog.provide('goog.ui.KeyboardShortcutEvent');
    -goog.provide('goog.ui.KeyboardShortcutHandler');
    -goog.provide('goog.ui.KeyboardShortcutHandler.EventType');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.events');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.events.KeyNames');
    -goog.require('goog.object');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Component for handling keyboard shortcuts. A shortcut is registered and bound
    - * to a specific identifier. Once the shortcut is triggered an event is fired
    - * with the identifier for the shortcut. This allows keyboard shortcuts to be
    - * customized without modifying the code that listens for them.
    - *
    - * Supports keyboard shortcuts triggered by a single key, a stroke stroke (key
    - * plus at least one modifier) and a sequence of keys or strokes.
    - *
    - * @param {goog.events.EventTarget|EventTarget} keyTarget Event target that the
    - *     key event listener is attached to, typically the applications root
    - *     container.
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - */
    -goog.ui.KeyboardShortcutHandler = function(keyTarget) {
    -  goog.events.EventTarget.call(this);
    -
    -  /**
    -   * Registered keyboard shortcuts tree. Stored as a map with the keyCode and
    -   * modifier(s) as the key and either a list of further strokes or the shortcut
    -   * task identifier as the value.
    -   * @type {!goog.ui.KeyboardShortcutHandler.SequenceTree_}
    -   * @see #makeStroke_
    -   * @private
    -   */
    -  this.shortcuts_ = {};
    -
    -  /**
    -   * The currently active shortcut sequence tree, which represents the position
    -   * in the complete shortcuts_ tree reached by recent key strokes.
    -   * @type {!goog.ui.KeyboardShortcutHandler.SequenceTree_}
    -   * @private
    -   */
    -  this.currentTree_ = this.shortcuts_;
    -
    -  /**
    -   * The time (in ms, epoch time) of the last keystroke which made progress in
    -   * the shortcut sequence tree (i.e. the time that currentTree_ was last set).
    -   * Used for timing out stroke sequences.
    -   * @type {number}
    -   * @private
    -   */
    -  this.lastStrokeTime_ = 0;
    -
    -  /**
    -   * List of numeric key codes for keys that are safe to always regarded as
    -   * shortcuts, even if entered in a textarea or input field.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.globalKeys_ = goog.object.createSet(
    -      goog.ui.KeyboardShortcutHandler.DEFAULT_GLOBAL_KEYS_);
    -
    -  /**
    -   * List of input types that should only accept ENTER as a shortcut.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.textInputs_ = goog.object.createSet(
    -      goog.ui.KeyboardShortcutHandler.DEFAULT_TEXT_INPUTS_);
    -
    -  /**
    -   * Whether to always prevent the default action if a shortcut event is fired.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.alwaysPreventDefault_ = true;
    -
    -  /**
    -   * Whether to always stop propagation if a shortcut event is fired.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.alwaysStopPropagation_ = false;
    -
    -  /**
    -   * Whether to treat all shortcuts as if they had been passed
    -   * to setGlobalKeys().
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.allShortcutsAreGlobal_ = false;
    -
    -  /**
    -   * Whether to treat shortcuts with modifiers as if they had been passed
    -   * to setGlobalKeys().  Ignored if allShortcutsAreGlobal_ is true.  Applies
    -   * only to form elements (not content-editable).
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.modifierShortcutsAreGlobal_ = true;
    -
    -  /**
    -   * Whether to treat space key as a shortcut when the focused element is a
    -   * checkbox, radiobutton or button.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.allowSpaceKeyOnButtons_ = false;
    -
    -  /**
    -   * Tracks the currently pressed shortcut key, for Firefox.
    -   * @type {?number}
    -   * @private
    -   */
    -  this.activeShortcutKeyForGecko_ = null;
    -
    -  this.initializeKeyListener(keyTarget);
    -};
    -goog.inherits(goog.ui.KeyboardShortcutHandler, goog.events.EventTarget);
    -goog.tagUnsealableClass(goog.ui.KeyboardShortcutHandler);
    -
    -
    -
    -/**
    - * A node in a keyboard shortcut sequence tree. A node is either:
    - * 1. A terminal node with a non-nullable shortcut string which is the
    - *    identifier for the shortcut triggered by traversing the tree to that node.
    - * 2. An internal node with a null shortcut string and a
    - *    {@code goog.ui.KeyboardShortcutHandler.SequenceTree_} representing the
    - *    continued stroke sequences from this node.
    - * For clarity, the static factory methods for creating internal and terminal
    - * nodes below should be used rather than using this constructor directly.
    - * @param {string=} opt_shortcut The shortcut identifier, for terminal nodes.
    - * @constructor
    - * @struct
    - * @private
    - */
    -goog.ui.KeyboardShortcutHandler.SequenceNode_ = function(opt_shortcut) {
    -  /** @const {?string} The shorcut action identifier, for terminal nodes. */
    -  this.shortcut = opt_shortcut || null;
    -
    -  /** @const {goog.ui.KeyboardShortcutHandler.SequenceTree_} */
    -  this.next = opt_shortcut ? null : {};
    -};
    -
    -
    -/**
    - * Creates a terminal shortcut sequence node for the given shortcut identifier.
    - * @param {string} shortcut The shortcut identifier.
    - * @return {!goog.ui.KeyboardShortcutHandler.SequenceNode_}
    - * @private
    - */
    -goog.ui.KeyboardShortcutHandler.createTerminalNode_ = function(shortcut) {
    -  return new goog.ui.KeyboardShortcutHandler.SequenceNode_(shortcut);
    -};
    -
    -
    -/**
    - * Creates an internal shortcut sequence node - a non-terminal part of a
    - * keyboard sequence.
    - * @return {!goog.ui.KeyboardShortcutHandler.SequenceNode_}
    - * @private
    - */
    -goog.ui.KeyboardShortcutHandler.createInternalNode_ = function() {
    -  return new goog.ui.KeyboardShortcutHandler.SequenceNode_();
    -};
    -
    -
    -/**
    - * A map of strokes (represented as numbers) to the nodes reached by those
    - * strokes.
    - * @typedef {Object<number, goog.ui.KeyboardShortcutHandler.SequenceNode_>}
    - * @private
    - */
    -goog.ui.KeyboardShortcutHandler.SequenceTree_;
    -
    -
    -/**
    - * Maximum allowed delay, in milliseconds, allowed between the first and second
    - * key in a key sequence.
    - * @type {number}
    - */
    -goog.ui.KeyboardShortcutHandler.MAX_KEY_SEQUENCE_DELAY = 1500; // 1.5 sec
    -
    -
    -/**
    - * Bit values for modifier keys.
    - * @enum {number}
    - */
    -goog.ui.KeyboardShortcutHandler.Modifiers = {
    -  NONE: 0,
    -  SHIFT: 1,
    -  CTRL: 2,
    -  ALT: 4,
    -  META: 8
    -};
    -
    -
    -/**
    - * Keys marked as global by default.
    - * @type {Array<goog.events.KeyCodes>}
    - * @private
    - */
    -goog.ui.KeyboardShortcutHandler.DEFAULT_GLOBAL_KEYS_ = [
    -  goog.events.KeyCodes.ESC,
    -  goog.events.KeyCodes.F1,
    -  goog.events.KeyCodes.F2,
    -  goog.events.KeyCodes.F3,
    -  goog.events.KeyCodes.F4,
    -  goog.events.KeyCodes.F5,
    -  goog.events.KeyCodes.F6,
    -  goog.events.KeyCodes.F7,
    -  goog.events.KeyCodes.F8,
    -  goog.events.KeyCodes.F9,
    -  goog.events.KeyCodes.F10,
    -  goog.events.KeyCodes.F11,
    -  goog.events.KeyCodes.F12,
    -  goog.events.KeyCodes.PAUSE
    -];
    -
    -
    -/**
    - * Text input types to allow only ENTER shortcuts.
    - * Web Forms 2.0 for HTML5: Section 4.10.7 from 29 May 2012.
    - * @type {Array<string>}
    - * @private
    - */
    -goog.ui.KeyboardShortcutHandler.DEFAULT_TEXT_INPUTS_ = [
    -  'color',
    -  'date',
    -  'datetime',
    -  'datetime-local',
    -  'email',
    -  'month',
    -  'number',
    -  'password',
    -  'search',
    -  'tel',
    -  'text',
    -  'time',
    -  'url',
    -  'week'
    -];
    -
    -
    -/**
    - * Events.
    - * @enum {string}
    - */
    -goog.ui.KeyboardShortcutHandler.EventType = {
    -  SHORTCUT_TRIGGERED: 'shortcut',
    -  SHORTCUT_PREFIX: 'shortcut_'
    -};
    -
    -
    -/**
    - * Cache for name to key code lookup.
    - * @type {Object.<number>}
    - * @private
    - */
    -goog.ui.KeyboardShortcutHandler.nameToKeyCodeCache_;
    -
    -
    -/**
    - * Target on which to listen for key events.
    - * @type {goog.events.EventTarget|EventTarget}
    - * @private
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.keyTarget_;
    -
    -
    -/**
    - * Due to a bug in the way that Gecko on Mac handles cut/copy/paste key events
    - * using the meta key, it is necessary to fake the keyDown for the action key
    - * (C,V,X) by capturing it on keyUp.
    - * Because users will often release the meta key a slight moment before they
    - * release the action key, we need this variable that will store whether the
    - * meta key has been released recently.
    - * It will be cleared after a short delay in the key handling logic.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.metaKeyRecentlyReleased_;
    -
    -
    -/**
    - * Whether a key event is a printable-key event. Windows uses ctrl+alt
    - * (alt-graph) keys to type characters on European keyboards. For such keys, we
    - * cannot identify whether these keys are used for typing characters when
    - * receiving keydown events. Therefore, we set this flag when we receive their
    - * respective keypress events and fire shortcut events only when we do not
    - * receive them.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.isPrintableKey_;
    -
    -
    -/**
    - * Static method for getting the key code for a given key.
    - * @param {string} name Name of key.
    - * @return {number} The key code.
    - */
    -goog.ui.KeyboardShortcutHandler.getKeyCode = function(name) {
    -  // Build reverse lookup object the first time this method is called.
    -  if (!goog.ui.KeyboardShortcutHandler.nameToKeyCodeCache_) {
    -    var map = {};
    -    for (var key in goog.events.KeyNames) {
    -      // Explicitly convert the stringified map keys to numbers and normalize.
    -      map[goog.events.KeyNames[key]] =
    -          goog.events.KeyCodes.normalizeKeyCode(parseInt(key, 10));
    -    }
    -    goog.ui.KeyboardShortcutHandler.nameToKeyCodeCache_ = map;
    -  }
    -
    -  // Check if key is in cache.
    -  return goog.ui.KeyboardShortcutHandler.nameToKeyCodeCache_[name];
    -};
    -
    -
    -/**
    - * Sets whether to always prevent the default action when a shortcut event is
    - * fired. If false, the default action is prevented only if preventDefault is
    - * called on either of the corresponding SHORTCUT_TRIGGERED or SHORTCUT_PREFIX
    - * events. If true, the default action is prevented whenever a shortcut event
    - * is fired. The default value is true.
    - * @param {boolean} alwaysPreventDefault Whether to always call preventDefault.
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.setAlwaysPreventDefault = function(
    -    alwaysPreventDefault) {
    -  this.alwaysPreventDefault_ = alwaysPreventDefault;
    -};
    -
    -
    -/**
    - * Returns whether the default action will always be prevented when a shortcut
    - * event is fired. The default value is true.
    - * @see #setAlwaysPreventDefault
    - * @return {boolean} Whether preventDefault will always be called.
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.getAlwaysPreventDefault = function() {
    -  return this.alwaysPreventDefault_;
    -};
    -
    -
    -/**
    - * Sets whether to always stop propagation for the event when fired. If false,
    - * the propagation is stopped only if stopPropagation is called on either of the
    - * corresponding SHORT_CUT_TRIGGERED or SHORTCUT_PREFIX events. If true, the
    - * event is prevented from propagating beyond its target whenever it is fired.
    - * The default value is false.
    - * @param {boolean} alwaysStopPropagation Whether to always call
    - *     stopPropagation.
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.setAlwaysStopPropagation = function(
    -    alwaysStopPropagation) {
    -  this.alwaysStopPropagation_ = alwaysStopPropagation;
    -};
    -
    -
    -/**
    - * Returns whether the event will always be stopped from propagating beyond its
    - * target when a shortcut event is fired. The default value is false.
    - * @see #setAlwaysStopPropagation
    - * @return {boolean} Whether stopPropagation will always be called.
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.getAlwaysStopPropagation =
    -    function() {
    -  return this.alwaysStopPropagation_;
    -};
    -
    -
    -/**
    - * Sets whether to treat all shortcuts (including modifier shortcuts) as if the
    - * keys had been passed to the setGlobalKeys function.
    - * @param {boolean} allShortcutsGlobal Whether to treat all shortcuts as global.
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.setAllShortcutsAreGlobal = function(
    -    allShortcutsGlobal) {
    -  this.allShortcutsAreGlobal_ = allShortcutsGlobal;
    -};
    -
    -
    -/**
    - * Returns whether all shortcuts (including modifier shortcuts) are treated as
    - * if the keys had been passed to the setGlobalKeys function.
    - * @see #setAllShortcutsAreGlobal
    - * @return {boolean} Whether all shortcuts are treated as globals.
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.getAllShortcutsAreGlobal =
    -    function() {
    -  return this.allShortcutsAreGlobal_;
    -};
    -
    -
    -/**
    - * Sets whether to treat shortcuts with modifiers as if the keys had been
    - * passed to the setGlobalKeys function.  Ignored if you have called
    - * setAllShortcutsAreGlobal(true).  Applies only to form elements (not
    - * content-editable).
    - * @param {boolean} modifierShortcutsGlobal Whether to treat shortcuts with
    - *     modifiers as global.
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.setModifierShortcutsAreGlobal =
    -    function(modifierShortcutsGlobal) {
    -  this.modifierShortcutsAreGlobal_ = modifierShortcutsGlobal;
    -};
    -
    -
    -/**
    - * Returns whether shortcuts with modifiers are treated as if the keys had been
    - * passed to the setGlobalKeys function.  Ignored if you have called
    - * setAllShortcutsAreGlobal(true).  Applies only to form elements (not
    - * content-editable).
    - * @see #setModifierShortcutsAreGlobal
    - * @return {boolean} Whether shortcuts with modifiers are treated as globals.
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.getModifierShortcutsAreGlobal =
    -    function() {
    -  return this.modifierShortcutsAreGlobal_;
    -};
    -
    -
    -/**
    - * Sets whether to treat space key as a shortcut when the focused element is a
    - * checkbox, radiobutton or button.
    - * @param {boolean} allowSpaceKeyOnButtons Whether to treat space key as a
    - *     shortcut when the focused element is a checkbox, radiobutton or button.
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.setAllowSpaceKeyOnButtons = function(
    -    allowSpaceKeyOnButtons) {
    -  this.allowSpaceKeyOnButtons_ = allowSpaceKeyOnButtons;
    -};
    -
    -
    -/**
    - * Registers a keyboard shortcut.
    - * @param {string} identifier Identifier for the task performed by the keyboard
    - *                 combination. Multiple shortcuts can be provided for the same
    - *                 task by specifying the same identifier.
    - * @param {...(number|string|Array<number>)} var_args See below.
    - *
    - * param {number} keyCode Numeric code for key
    - * param {number=} opt_modifiers Bitmap indicating required modifier keys.
    - *                goog.ui.KeyboardShortcutHandler.Modifiers.SHIFT, CONTROL,
    - *                ALT, or META.
    - *
    - * The last two parameters can be repeated any number of times to create a
    - * shortcut using a sequence of strokes. Instead of varagrs the second parameter
    - * could also be an array where each element would be ragarded as a parameter.
    - *
    - * A string representation of the shortcut can be supplied instead of the last
    - * two parameters. In that case the method only takes two arguments, the
    - * identifier and the string.
    - *
    - * Examples:
    - *   g               registerShortcut(str, G_KEYCODE)
    - *   Ctrl+g          registerShortcut(str, G_KEYCODE, CTRL)
    - *   Ctrl+Shift+g    registerShortcut(str, G_KEYCODE, CTRL | SHIFT)
    - *   Ctrl+g a        registerShortcut(str, G_KEYCODE, CTRL, A_KEYCODE)
    - *   Ctrl+g Shift+a  registerShortcut(str, G_KEYCODE, CTRL, A_KEYCODE, SHIFT)
    - *   g a             registerShortcut(str, G_KEYCODE, NONE, A_KEYCODE)
    - *
    - * Examples using string representation for shortcuts:
    - *   g               registerShortcut(str, 'g')
    - *   Ctrl+g          registerShortcut(str, 'ctrl+g')
    - *   Ctrl+Shift+g    registerShortcut(str, 'ctrl+shift+g')
    - *   Ctrl+g a        registerShortcut(str, 'ctrl+g a')
    - *   Ctrl+g Shift+a  registerShortcut(str, 'ctrl+g shift+a')
    - *   g a             registerShortcut(str, 'g a').
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.registerShortcut = function(
    -    identifier, var_args) {
    -
    -  // Add shortcut to shortcuts_ tree
    -  goog.ui.KeyboardShortcutHandler.setShortcut_(
    -      this.shortcuts_, this.interpretStrokes_(1, arguments), identifier);
    -};
    -
    -
    -/**
    - * Unregisters a keyboard shortcut by keyCode and modifiers or string
    - * representation of sequence.
    - *
    - * param {number} keyCode Numeric code for key
    - * param {number=} opt_modifiers Bitmap indicating required modifier keys.
    - *                 goog.ui.KeyboardShortcutHandler.Modifiers.SHIFT, CONTROL,
    - *                 ALT, or META.
    - *
    - * The two parameters can be repeated any number of times to create a shortcut
    - * using a sequence of strokes.
    - *
    - * A string representation of the shortcut can be supplied instead see
    - * {@link #registerShortcut} for syntax. In that case the method only takes one
    - * argument.
    - *
    - * @param {...(number|string|Array<number>)} var_args String representation, or
    - *     array or list of alternating key codes and modifiers.
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.unregisterShortcut = function(
    -    var_args) {
    -  // Remove shortcut from tree.
    -  goog.ui.KeyboardShortcutHandler.unsetShortcut_(
    -      this.shortcuts_, this.interpretStrokes_(0, arguments));
    -};
    -
    -
    -/**
    - * Verifies if a particular keyboard shortcut is registered already. It has
    - * the same interface as the unregistering of shortcuts.
    - *
    - * param {number} keyCode Numeric code for key
    - * param {number=} opt_modifiers Bitmap indicating required modifier keys.
    - *                 goog.ui.KeyboardShortcutHandler.Modifiers.SHIFT, CONTROL,
    - *                 ALT, or META.
    - *
    - * The two parameters can be repeated any number of times to create a shortcut
    - * using a sequence of strokes.
    - *
    - * A string representation of the shortcut can be supplied instead see
    - * {@link #registerShortcut} for syntax. In that case the method only takes one
    - * argument.
    - *
    - * @param {...(number|string|Array<number>)} var_args String representation, or
    - *     array or list of alternating key codes and modifiers.
    - * @return {boolean} Whether the specified keyboard shortcut is registered.
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.isShortcutRegistered = function(
    -    var_args) {
    -  return this.checkShortcut_(this.interpretStrokes_(0, arguments));
    -};
    -
    -
    -/**
    - * Parses the variable arguments for registerShortcut and unregisterShortcut.
    - * @param {number} initialIndex The first index of "args" to treat as
    - *     variable arguments.
    - * @param {Object} args The "arguments" array passed
    - *     to registerShortcut or unregisterShortcut.  Please see the comments in
    - *     registerShortcut for list of allowed forms.
    - * @return {!Array<number>} The sequence of strokes, represented as numbers.
    - * @private
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.interpretStrokes_ = function(
    -    initialIndex, args) {
    -  var strokes;
    -
    -  // Build strokes array from string.
    -  if (goog.isString(args[initialIndex])) {
    -    strokes = goog.array.map(
    -        goog.ui.KeyboardShortcutHandler.parseStringShortcut(args[initialIndex]),
    -        function(stroke) {
    -          goog.asserts.assertNumber(
    -              stroke.keyCode, 'A non-modifier key is needed in each stroke.');
    -          return goog.ui.KeyboardShortcutHandler.makeStroke_(
    -              stroke.keyCode, stroke.modifiers);
    -        });
    -
    -  // Build strokes array from arguments list or from array.
    -  } else {
    -    var strokesArgs = args, i = initialIndex;
    -    if (goog.isArray(args[initialIndex])) {
    -      strokesArgs = args[initialIndex];
    -      i = 0;
    -    }
    -
    -    strokes = [];
    -    for (; i < strokesArgs.length; i += 2) {
    -      strokes.push(goog.ui.KeyboardShortcutHandler.makeStroke_(
    -          strokesArgs[i], strokesArgs[i + 1]));
    -    }
    -  }
    -
    -  return strokes;
    -};
    -
    -
    -/**
    - * Unregisters all keyboard shortcuts.
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.unregisterAll = function() {
    -  this.shortcuts_ = {};
    -};
    -
    -
    -/**
    - * Sets the global keys; keys that are safe to always regarded as shortcuts,
    - * even if entered in a textarea or input field.
    - * @param {Array<number>} keys List of keys.
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.setGlobalKeys = function(keys) {
    -  this.globalKeys_ = goog.object.createSet(keys);
    -};
    -
    -
    -/**
    - * @return {!Array<string>} The global keys, i.e. keys that are safe to always
    - *     regard as shortcuts, even if entered in a textarea or input field.
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.getGlobalKeys = function() {
    -  return goog.object.getKeys(this.globalKeys_);
    -};
    -
    -
    -/** @override */
    -goog.ui.KeyboardShortcutHandler.prototype.disposeInternal = function() {
    -  goog.ui.KeyboardShortcutHandler.superClass_.disposeInternal.call(this);
    -  this.unregisterAll();
    -  this.clearKeyListener();
    -};
    -
    -
    -/**
    - * Returns event type for a specific shortcut.
    - * @param {string} identifier Identifier for the shortcut task.
    - * @return {string} Theh event type.
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.getEventType =
    -    function(identifier) {
    -
    -  return goog.ui.KeyboardShortcutHandler.EventType.SHORTCUT_PREFIX + identifier;
    -};
    -
    -
    -/**
    - * Builds stroke array from string representation of shortcut.
    - * @param {string} s String representation of shortcut.
    - * @return {!Array<!{keyCode: ?number, modifiers: number}>} The stroke array.  A
    - *     null keyCode means no non-modifier key was part of the stroke.
    - */
    -goog.ui.KeyboardShortcutHandler.parseStringShortcut = function(s) {
    -  // Normalize whitespace and force to lower case.
    -  s = s.replace(/[ +]*\+[ +]*/g, '+').replace(/[ ]+/g, ' ').toLowerCase();
    -
    -  // Build strokes array from string, space separates strokes, plus separates
    -  // individual keys.
    -  var groups = s.split(' ');
    -  var strokes = [];
    -  for (var group, i = 0; group = groups[i]; i++) {
    -    var keys = group.split('+');
    -    // Explicitly re-initialize key data (JS does not have block scoping).
    -    var keyCode = null;
    -    var modifiers = goog.ui.KeyboardShortcutHandler.Modifiers.NONE;
    -    for (var key, j = 0; key = keys[j]; j++) {
    -      switch (key) {
    -        case 'shift':
    -          modifiers |= goog.ui.KeyboardShortcutHandler.Modifiers.SHIFT;
    -          continue;
    -        case 'ctrl':
    -          modifiers |= goog.ui.KeyboardShortcutHandler.Modifiers.CTRL;
    -          continue;
    -        case 'alt':
    -          modifiers |= goog.ui.KeyboardShortcutHandler.Modifiers.ALT;
    -          continue;
    -        case 'meta':
    -          modifiers |= goog.ui.KeyboardShortcutHandler.Modifiers.META;
    -          continue;
    -      }
    -      if (!goog.isNull(keyCode)) {
    -        goog.asserts.fail('At most one non-modifier key can be in a stroke.');
    -      }
    -      keyCode = goog.ui.KeyboardShortcutHandler.getKeyCode(key);
    -      goog.asserts.assertNumber(
    -          keyCode, 'Key name not found in goog.events.KeyNames: ' + key);
    -      break;
    -    }
    -    strokes.push({keyCode: keyCode, modifiers: modifiers});
    -  }
    -
    -  return strokes;
    -};
    -
    -
    -/**
    - * Adds a key event listener that triggers {@link #handleKeyDown_} when keys
    - * are pressed.
    - * @param {goog.events.EventTarget|EventTarget} keyTarget Event target that the
    - *     event listener should be attached to.
    - * @protected
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.initializeKeyListener =
    -    function(keyTarget) {
    -  this.keyTarget_ = keyTarget;
    -
    -  goog.events.listen(this.keyTarget_, goog.events.EventType.KEYDOWN,
    -      this.handleKeyDown_, false, this);
    -
    -  if (goog.userAgent.GECKO) {
    -    goog.events.listen(this.keyTarget_, goog.events.EventType.KEYUP,
    -        this.handleGeckoKeyUp_, false, this);
    -  }
    -
    -  // Windows uses ctrl+alt keys (a.k.a. alt-graph keys) for typing characters
    -  // on European keyboards (e.g. ctrl+alt+e for an an euro sign.) Unfortunately,
    -  // Windows browsers except Firefox does not have any methods except listening
    -  // keypress and keyup events to identify if ctrl+alt keys are really used for
    -  // inputting characters. Therefore, we listen to these events and prevent
    -  // firing shortcut-key events if ctrl+alt keys are used for typing characters.
    -  if (goog.userAgent.WINDOWS && !goog.userAgent.GECKO) {
    -    goog.events.listen(this.keyTarget_, goog.events.EventType.KEYPRESS,
    -                       this.handleWindowsKeyPress_, false, this);
    -    goog.events.listen(this.keyTarget_, goog.events.EventType.KEYUP,
    -                       this.handleWindowsKeyUp_, false, this);
    -  }
    -};
    -
    -
    -/**
    - * Handler for when a keyup event is fired in Firefox (Gecko).
    - * @param {goog.events.BrowserEvent} e The key event.
    - * @private
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.handleGeckoKeyUp_ = function(e) {
    -  // Due to a bug in the way that Gecko on Mac handles cut/copy/paste key events
    -  // using the meta key, it is necessary to fake the keyDown for the action keys
    -  // (C,V,X) by capturing it on keyUp.
    -  // This is because the keyDown events themselves are not fired by the browser
    -  // in this case.
    -  // Because users will often release the meta key a slight moment before they
    -  // release the action key, we need to store whether the meta key has been
    -  // released recently to avoid "flaky" cutting/pasting behavior.
    -  if (goog.userAgent.MAC) {
    -    if (e.keyCode == goog.events.KeyCodes.MAC_FF_META) {
    -      this.metaKeyRecentlyReleased_ = true;
    -      goog.Timer.callOnce(function() {
    -        this.metaKeyRecentlyReleased_ = false;
    -      }, 400, this);
    -      return;
    -    }
    -
    -    var metaKey = e.metaKey || this.metaKeyRecentlyReleased_;
    -    if ((e.keyCode == goog.events.KeyCodes.C ||
    -        e.keyCode == goog.events.KeyCodes.X ||
    -        e.keyCode == goog.events.KeyCodes.V) && metaKey) {
    -      e.metaKey = metaKey;
    -      this.handleKeyDown_(e);
    -    }
    -  }
    -
    -  // Firefox triggers buttons on space keyUp instead of keyDown.  So if space
    -  // keyDown activated a shortcut, do NOT also trigger the focused button.
    -  if (goog.events.KeyCodes.SPACE == this.activeShortcutKeyForGecko_ &&
    -      goog.events.KeyCodes.SPACE == e.keyCode) {
    -    e.preventDefault();
    -  }
    -  this.activeShortcutKeyForGecko_ = null;
    -};
    -
    -
    -/**
    - * Returns whether this event is possibly used for typing a printable character.
    - * Windows uses ctrl+alt (a.k.a. alt-graph) keys for typing characters on
    - * European keyboards. Since only Firefox provides a method that can identify
    - * whether ctrl+alt keys are used for typing characters, we need to check
    - * whether Windows sends a keypress event to prevent firing shortcut event if
    - * this event is used for typing characters.
    - * @param {goog.events.BrowserEvent} e The key event.
    - * @return {boolean} Whether this event is a possible printable-key event.
    - * @private
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.isPossiblePrintableKey_ =
    -    function(e) {
    -  return goog.userAgent.WINDOWS && !goog.userAgent.GECKO &&
    -      e.ctrlKey && e.altKey && !e.shiftKey;
    -};
    -
    -
    -/**
    - * Handler for when a keypress event is fired on Windows.
    - * @param {goog.events.BrowserEvent} e The key event.
    - * @private
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.handleWindowsKeyPress_ = function(e) {
    -  // When this keypress event consists of a printable character, set the flag to
    -  // prevent firing shortcut key events when we receive the succeeding keyup
    -  // event. We accept all Unicode characters except control ones since this
    -  // keyCode may be a non-ASCII character.
    -  if (e.keyCode > 0x20 && this.isPossiblePrintableKey_(e)) {
    -    this.isPrintableKey_ = true;
    -  }
    -};
    -
    -
    -/**
    - * Handler for when a keyup event is fired on Windows.
    - * @param {goog.events.BrowserEvent} e The key event.
    - * @private
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.handleWindowsKeyUp_ = function(e) {
    -  // For possible printable-key events, try firing a shortcut-key event only
    -  // when this event is not used for typing a character.
    -  if (!this.isPrintableKey_ && this.isPossiblePrintableKey_(e)) {
    -    this.handleKeyDown_(e);
    -  }
    -};
    -
    -
    -/**
    - * Removes the listener that was added by link {@link #initializeKeyListener}.
    - * @protected
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.clearKeyListener = function() {
    -  goog.events.unlisten(this.keyTarget_, goog.events.EventType.KEYDOWN,
    -      this.handleKeyDown_, false, this);
    -  if (goog.userAgent.GECKO) {
    -    goog.events.unlisten(this.keyTarget_, goog.events.EventType.KEYUP,
    -        this.handleGeckoKeyUp_, false, this);
    -  }
    -  if (goog.userAgent.WINDOWS && !goog.userAgent.GECKO) {
    -    goog.events.unlisten(this.keyTarget_, goog.events.EventType.KEYPRESS,
    -        this.handleWindowsKeyPress_, false, this);
    -    goog.events.unlisten(this.keyTarget_, goog.events.EventType.KEYUP,
    -        this.handleWindowsKeyUp_, false, this);
    -  }
    -  this.keyTarget_ = null;
    -};
    -
    -
    -/**
    - * Adds a shortcut stroke sequence to the given sequence tree. Recursive.
    - * @param {!goog.ui.KeyboardShortcutHandler.SequenceTree_} tree The stroke
    - *     sequence tree to add to.
    - * @param {Array<number>} strokes Array of strokes for shortcut.
    - * @param {string} identifier Identifier for the task performed by shortcut.
    - * @private
    - */
    -goog.ui.KeyboardShortcutHandler.setShortcut_ = function(
    -    tree, strokes, identifier) {
    -  var stroke = strokes.shift();
    -  var node = tree[stroke];
    -  if (node && (strokes.length == 0 || node.shortcut)) {
    -    // This new shortcut would override an existing shortcut or shortcut prefix
    -    // (since the new strokes end at an existing node), or an existing shortcut
    -    // would be triggered by the prefix to this new shortcut (since there is
    -    // already a terminal node on the path we are trying to create).
    -    throw Error('Keyboard shortcut conflicts with existing shortcut');
    -  }
    -
    -  if (strokes.length) {
    -    node = goog.object.setIfUndefined(tree, stroke.toString(),
    -        goog.ui.KeyboardShortcutHandler.createInternalNode_());
    -    goog.ui.KeyboardShortcutHandler.setShortcut_(
    -        goog.asserts.assert(node.next, 'An internal node must have a next map'),
    -        strokes, identifier);
    -  } else {
    -    // Add a terminal node.
    -    tree[stroke] =
    -        goog.ui.KeyboardShortcutHandler.createTerminalNode_(identifier);
    -  }
    -};
    -
    -
    -/**
    - * Removes a shortcut stroke sequence from the given sequence tree, pruning any
    - * dead branches of the tree. Recursive.
    - * @param {!goog.ui.KeyboardShortcutHandler.SequenceTree_} tree The stroke
    - *     sequence tree to remove from.
    - * @param {Array<number>} strokes Array of strokes for shortcut to remove.
    - * @private
    - */
    -goog.ui.KeyboardShortcutHandler.unsetShortcut_ = function(tree, strokes) {
    -  var stroke = strokes.shift();
    -  var node = tree[stroke];
    -
    -  if (!node) {
    -    // The given stroke sequence is not in the tree.
    -    return;
    -  }
    -  if (strokes.length == 0) {
    -    // Base case - the end of the stroke sequence.
    -    if (!node.shortcut) {
    -      // The given stroke sequence does not end at a terminal node.
    -      return;
    -    }
    -    delete tree[stroke];
    -  } else {
    -    if (!node.next) {
    -      // The given stroke sequence is not in the tree.
    -      return;
    -    }
    -    // Recursively remove the rest of the shortcut sequence from the node.next
    -    // subtree.
    -    goog.ui.KeyboardShortcutHandler.unsetShortcut_(node.next, strokes);
    -    if (goog.object.isEmpty(node.next)) {
    -      // The node.next subtree is now empty (the last stroke in it was just
    -      // removed), so prune this dead branch of the tree.
    -      delete tree[stroke];
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Checks if a particular keyboard shortcut is registered.
    - * @param {Array<number>} strokes Strokes array.
    - * @return {boolean} True iff the keyboard is registred.
    - * @private
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.checkShortcut_ = function(strokes) {
    -  var tree = this.shortcuts_;
    -  while (strokes.length > 0 && tree) {
    -    var node = tree[strokes.shift()];
    -    if (!node) {
    -      return false;
    -    }
    -    if (strokes.length == 0 && node.shortcut) {
    -      return true;
    -    }
    -    tree = node.next;
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Constructs key from key code and modifiers.
    - *
    - * The lower 8 bits are used for the key code, the following 3 for modifiers and
    - * the remaining bits are unused.
    - *
    - * @param {number} keyCode Numeric key code.
    - * @param {number} modifiers Required modifiers.
    - * @return {number} The key.
    - * @private
    - */
    -goog.ui.KeyboardShortcutHandler.makeStroke_ = function(keyCode, modifiers) {
    -  // Make sure key code is just 8 bits and OR it with the modifiers left shifted
    -  // 8 bits.
    -  return (keyCode & 255) | (modifiers << 8);
    -};
    -
    -
    -/**
    - * Keypress handler.
    - * @param {goog.events.BrowserEvent} event Keypress event.
    - * @private
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.handleKeyDown_ = function(event) {
    -  if (!this.isValidShortcut_(event)) {
    -    return;
    -  }
    -  // For possible printable-key events, we cannot identify whether the events
    -  // are used for typing characters until we receive respective keyup events.
    -  // Therefore, we handle this event when we receive a succeeding keyup event
    -  // to verify this event is not used for typing characters.
    -  if (event.type == 'keydown' && this.isPossiblePrintableKey_(event)) {
    -    this.isPrintableKey_ = false;
    -    return;
    -  }
    -
    -  var keyCode = goog.events.KeyCodes.normalizeKeyCode(event.keyCode);
    -
    -  var modifiers =
    -      (event.shiftKey ? goog.ui.KeyboardShortcutHandler.Modifiers.SHIFT : 0) |
    -      (event.ctrlKey ? goog.ui.KeyboardShortcutHandler.Modifiers.CTRL : 0) |
    -      (event.altKey ? goog.ui.KeyboardShortcutHandler.Modifiers.ALT : 0) |
    -      (event.metaKey ? goog.ui.KeyboardShortcutHandler.Modifiers.META : 0);
    -  var stroke = goog.ui.KeyboardShortcutHandler.makeStroke_(keyCode, modifiers);
    -
    -  if (!this.currentTree_[stroke] || this.hasSequenceTimedOut_()) {
    -    // Either this stroke does not continue any active sequence, or the
    -    // currently active sequence has timed out. Reset shortcut tree progress.
    -    this.setCurrentTree_(this.shortcuts_);
    -  }
    -
    -  var node = this.currentTree_[stroke];
    -  if (!node) {
    -    // This stroke does not correspond to a shortcut or continued sequence.
    -    return;
    -  }
    -  if (node.next) {
    -    // This stroke does not trigger a shortcut, but entered stroke(s) are a part
    -    // of a sequence. Progress in the sequence tree and record time to allow the
    -    // following stroke(s) to trigger the shortcut.
    -    this.setCurrentTree_(node.next);
    -    // Prevent default action so that the rest of the stroke sequence can be
    -    // completed.
    -    event.preventDefault();
    -    return;
    -  }
    -  // This stroke triggers a shortcut. Any active sequence has been completed, so
    -  // reset the sequence tree.
    -  this.setCurrentTree_(this.shortcuts_);
    -
    -  // Dispatch the triggered keyboard shortcut event. In addition to the generic
    -  // keyboard shortcut event a more specific fine grained one, specific for the
    -  // shortcut identifier, is fired.
    -  if (this.alwaysPreventDefault_) {
    -    event.preventDefault();
    -  }
    -
    -  if (this.alwaysStopPropagation_) {
    -    event.stopPropagation();
    -  }
    -
    -  var shortcut = goog.asserts.assertString(
    -      node.shortcut, 'A terminal node must have a string shortcut identifier.');
    -  // Dispatch SHORTCUT_TRIGGERED event
    -  var target = /** @type {Node} */ (event.target);
    -  var triggerEvent = new goog.ui.KeyboardShortcutEvent(
    -      goog.ui.KeyboardShortcutHandler.EventType.SHORTCUT_TRIGGERED, shortcut,
    -      target);
    -  var retVal = this.dispatchEvent(triggerEvent);
    -
    -  // Dispatch SHORTCUT_PREFIX_<identifier> event
    -  var prefixEvent = new goog.ui.KeyboardShortcutEvent(
    -      goog.ui.KeyboardShortcutHandler.EventType.SHORTCUT_PREFIX + shortcut,
    -      shortcut, target);
    -  retVal &= this.dispatchEvent(prefixEvent);
    -
    -  // The default action is prevented if 'preventDefault' was
    -  // called on either event, or if a listener returned false.
    -  if (!retVal) {
    -    event.preventDefault();
    -  }
    -
    -  // For Firefox, track which shortcut key was pushed.
    -  if (goog.userAgent.GECKO) {
    -    this.activeShortcutKeyForGecko_ = keyCode;
    -  }
    -};
    -
    -
    -/**
    - * Checks if a given keypress event may be treated as a shortcut.
    - * @param {goog.events.BrowserEvent} event Keypress event.
    - * @return {boolean} Whether to attempt to process the event as a shortcut.
    - * @private
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.isValidShortcut_ = function(event) {
    -  var keyCode = event.keyCode;
    -
    -  // Ignore Ctrl, Shift and ALT
    -  if (keyCode == goog.events.KeyCodes.SHIFT ||
    -      keyCode == goog.events.KeyCodes.CTRL ||
    -      keyCode == goog.events.KeyCodes.ALT) {
    -    return false;
    -  }
    -  var el = /** @type {Element} */ (event.target);
    -  var isFormElement =
    -      el.tagName == 'TEXTAREA' || el.tagName == 'INPUT' ||
    -      el.tagName == 'BUTTON' || el.tagName == 'SELECT';
    -
    -  var isContentEditable = !isFormElement && (el.isContentEditable ||
    -      (el.ownerDocument && el.ownerDocument.designMode == 'on'));
    -
    -  if (!isFormElement && !isContentEditable) {
    -    return true;
    -  }
    -  // Always allow keys registered as global to be used (typically Esc, the
    -  // F-keys and other keys that are not typically used to manipulate text).
    -  if (this.globalKeys_[keyCode] || this.allShortcutsAreGlobal_) {
    -    return true;
    -  }
    -  if (isContentEditable) {
    -    // For events originating from an element in editing mode we only let
    -    // global key codes through.
    -    return false;
    -  }
    -  // Event target is one of (TEXTAREA, INPUT, BUTTON, SELECT).
    -  // Allow modifier shortcuts, unless we shouldn't.
    -  if (this.modifierShortcutsAreGlobal_ && (
    -      event.altKey || event.ctrlKey || event.metaKey)) {
    -    return true;
    -  }
    -  // Allow ENTER to be used as shortcut for text inputs.
    -  if (el.tagName == 'INPUT' && this.textInputs_[el.type]) {
    -    return keyCode == goog.events.KeyCodes.ENTER;
    -  }
    -  // Checkboxes, radiobuttons and buttons. Allow all but SPACE as shortcut.
    -  if (el.tagName == 'INPUT' || el.tagName == 'BUTTON') {
    -    // TODO(gboyer): If more flexibility is needed, create protected helper
    -    // methods for each case (e.g. button, input, etc).
    -    if (this.allowSpaceKeyOnButtons_) {
    -      return true;
    -    } else {
    -      return keyCode != goog.events.KeyCodes.SPACE;
    -    }
    -  }
    -  // Don't allow any additional shortcut keys for textareas or selects.
    -  return false;
    -};
    -
    -
    -/**
    - * @return {boolean} True iff the current stroke sequence has timed out.
    - * @private
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.hasSequenceTimedOut_ = function() {
    -  return goog.now() - this.lastStrokeTime_ >=
    -      goog.ui.KeyboardShortcutHandler.MAX_KEY_SEQUENCE_DELAY;
    -};
    -
    -
    -/**
    - * Sets the current keyboard shortcut sequence tree and updates the last stroke
    - * time.
    - * @param {!goog.ui.KeyboardShortcutHandler.SequenceTree_} tree
    - * @private
    - */
    -goog.ui.KeyboardShortcutHandler.prototype.setCurrentTree_ = function(tree) {
    -  this.currentTree_ = tree;
    -  this.lastStrokeTime_ = goog.now();
    -};
    -
    -
    -
    -/**
    - * Object representing a keyboard shortcut event.
    - * @param {string} type Event type.
    - * @param {string} identifier Task identifier for the triggered shortcut.
    - * @param {Node|goog.events.EventTarget} target Target the original key press
    - *     event originated from.
    - * @extends {goog.events.Event}
    - * @constructor
    - * @final
    - */
    -goog.ui.KeyboardShortcutEvent = function(type, identifier, target) {
    -  goog.events.Event.call(this, type, target);
    -
    -  /**
    -   * Task identifier for the triggered shortcut
    -   * @type {string}
    -   */
    -  this.identifier = identifier;
    -};
    -goog.inherits(goog.ui.KeyboardShortcutEvent, goog.events.Event);
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/keyboardshortcuthandler_test.html b/src/database/third_party/closure-library/closure/goog/ui/keyboardshortcuthandler_test.html
    deleted file mode 100644
    index d5c2e948a46..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/keyboardshortcuthandler_test.html
    +++ /dev/null
    @@ -1,54 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <!-- Author:  gboyer@google.com (Garrett Boyer) -->
    -  <title>
    -   Closure Unit Tests - goog.ui.KeyboardShortcutHandler
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.KeyboardShortcutHandlerTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="rootDiv">
    -   <div id="targetDiv">
    -    The test presses keys on me!
    -   </div>
    -   <button id="targetButton">
    -    A Button
    -   </button>
    -   <input type="checkbox" id="targetCheckBox" />
    -   <input type="color" id="targetColor" value="#FF0000" />
    -   <input type="date" id="targetDate" value="1995-12-31" />
    -   <input type="datetime" id="targetDateTime" value="1995-12-31T23:59:59.99Z" />
    -   <input type="datetime-local" id="targetDateTimeLocal" value="1995-12-31T23:59:59.99" />
    -   <input type="email" id="targetEmail" value="test@google.com" />
    -   <input type="month" id="targetMonth" value="1995-12" />
    -   <input type="number" id="targetNumber" value="12345" />
    -   <input type="password" id="targetPassword" value="password" />
    -   <input type="search" id="targetSearch" value="search terms" />
    -   <input type="tel" id="targetTel" value="555 1212" />
    -   <input type="text" id="targetText" value="text box" />
    -   <input type="time" id="targetTime" value="12:00" />
    -   <input type="url" id="targetUrl" value="http://www.google.com" />
    -   <input type="week" id="targetWeek" value="2005-W52" />
    -   <select id="targetSelect">
    -    <option>
    -     select
    -    </option>
    -   </select>
    -   <textarea id="targetTextArea">
    -    text area
    -   </textarea>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/keyboardshortcuthandler_test.js b/src/database/third_party/closure-library/closure/goog/ui/keyboardshortcuthandler_test.js
    deleted file mode 100644
    index 80591055fb2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/keyboardshortcuthandler_test.js
    +++ /dev/null
    @@ -1,737 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.KeyboardShortcutHandlerTest');
    -goog.setTestOnly('goog.ui.KeyboardShortcutHandlerTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.BrowserEvent');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.StrictMock');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.KeyboardShortcutHandler');
    -goog.require('goog.userAgent');
    -
    -var Modifiers = goog.ui.KeyboardShortcutHandler.Modifiers;
    -var KeyCodes = goog.events.KeyCodes;
    -
    -var handler;
    -var targetDiv;
    -var listener;
    -var mockClock;
    -var stubs = new goog.testing.PropertyReplacer();
    -
    -
    -/**
    - * Fires a keypress on the target div.
    - * @return {boolean} The returnValue of the sequence: false if
    - *     preventDefault() was called on any of the events, true otherwise.
    - */
    -function fire(keycode, opt_extraProperties, opt_element) {
    -  return goog.testing.events.fireKeySequence(
    -      opt_element || targetDiv, keycode, opt_extraProperties);
    -}
    -
    -function fireAltGraphKey(keycode, keyPressKeyCode, opt_extraProperties,
    -                         opt_element) {
    -  return goog.testing.events.fireNonAsciiKeySequence(
    -      opt_element || targetDiv, keycode, keyPressKeyCode,
    -      opt_extraProperties);
    -}
    -
    -function setUp() {
    -  targetDiv = goog.dom.getElement('targetDiv');
    -  handler = new goog.ui.KeyboardShortcutHandler(
    -      goog.dom.getElement('rootDiv'));
    -
    -  // Create a mock event listener in order to set expectations on what
    -  // events are fired.  We create a fake class whose only method is
    -  // shortcutFired(shortcut identifier).
    -  listener = new goog.testing.StrictMock(
    -      {shortcutFired: goog.nullFunction});
    -  goog.events.listen(
    -      handler,
    -      goog.ui.KeyboardShortcutHandler.EventType.SHORTCUT_TRIGGERED,
    -      function(event) { listener.shortcutFired(event.identifier); });
    -
    -  // Set up a fake clock, because keyboard shortcuts *are* time
    -  // sensitive.
    -  mockClock = new goog.testing.MockClock(true);
    -}
    -
    -function tearDown() {
    -  mockClock.uninstall();
    -  handler.dispose();
    -  stubs.reset();
    -}
    -
    -function testAllowsSingleLetterKeyBindingsSpecifiedAsString() {
    -  listener.shortcutFired('lettergee');
    -  listener.$replay();
    -
    -  handler.registerShortcut('lettergee', 'g');
    -  fire(KeyCodes.G);
    -
    -  listener.$verify();
    -}
    -
    -function testAllowsSingleLetterKeyBindingsSpecifiedAsKeyCode() {
    -  listener.shortcutFired('lettergee');
    -  listener.$replay();
    -
    -  handler.registerShortcut('lettergee', KeyCodes.G);
    -  fire(KeyCodes.G);
    -
    -  listener.$verify();
    -}
    -
    -function testDoesntFireWhenWrongKeyIsPressed() {
    -  listener.$replay(); // no events expected
    -
    -  handler.registerShortcut('letterjay', 'j');
    -  fire(KeyCodes.G);
    -
    -  listener.$verify();
    -}
    -
    -function testAllowsControlAndLetterSpecifiedAsAString() {
    -  listener.shortcutFired('lettergee');
    -  listener.$replay();
    -
    -  handler.registerShortcut('lettergee', 'ctrl+g');
    -  fire(KeyCodes.G, {ctrlKey: true});
    -
    -  listener.$verify();
    -}
    -
    -function testAllowsControlAndLetterSpecifiedAsArgSequence() {
    -  listener.shortcutFired('lettergeectrl');
    -  listener.$replay();
    -
    -  handler.registerShortcut('lettergeectrl',
    -      KeyCodes.G, Modifiers.CTRL);
    -  fire(KeyCodes.G, {ctrlKey: true});
    -
    -  listener.$verify();
    -}
    -
    -function testAllowsControlAndLetterSpecifiedAsArray() {
    -  listener.shortcutFired('lettergeectrl');
    -  listener.$replay();
    -
    -  handler.registerShortcut('lettergeectrl',
    -      [KeyCodes.G, Modifiers.CTRL]);
    -  fire(KeyCodes.G, {ctrlKey: true});
    -
    -  listener.$verify();
    -}
    -
    -function testAllowsShift() {
    -  listener.shortcutFired('lettergeeshift');
    -  listener.$replay();
    -
    -  handler.registerShortcut('lettergeeshift',
    -      [KeyCodes.G, Modifiers.SHIFT]);
    -  fire(KeyCodes.G, {shiftKey: true});
    -
    -  listener.$verify();
    -}
    -
    -function testAllowsAlt() {
    -  listener.shortcutFired('lettergeealt');
    -  listener.$replay();
    -
    -  handler.registerShortcut('lettergeealt',
    -      [KeyCodes.G, Modifiers.ALT]);
    -  fire(KeyCodes.G, {altKey: true});
    -
    -  listener.$verify();
    -}
    -
    -function testAllowsMeta() {
    -  listener.shortcutFired('lettergeemeta');
    -  listener.$replay();
    -
    -  handler.registerShortcut('lettergeemeta',
    -      [KeyCodes.G, Modifiers.META]);
    -  fire(KeyCodes.G, {metaKey: true});
    -
    -  listener.$verify();
    -}
    -
    -function testAllowsMultipleModifiers() {
    -  listener.shortcutFired('lettergeectrlaltshift');
    -  listener.$replay();
    -
    -  handler.registerShortcut('lettergeectrlaltshift',
    -      KeyCodes.G, Modifiers.CTRL | Modifiers.ALT | Modifiers.SHIFT);
    -  fire(KeyCodes.G, {ctrlKey: true, altKey: true, shiftKey: true});
    -
    -  listener.$verify();
    -}
    -
    -function testAllowsMultipleModifiersSpecifiedAsString() {
    -  listener.shortcutFired('lettergeectrlaltshiftmeta');
    -  listener.$replay();
    -
    -  handler.registerShortcut('lettergeectrlaltshiftmeta',
    -      'ctrl+shift+alt+meta+g');
    -  fire(KeyCodes.G,
    -      {ctrlKey: true, altKey: true, shiftKey: true, metaKey: true});
    -
    -  listener.$verify();
    -}
    -
    -function testPreventsDefaultOnReturnFalse() {
    -  listener.shortcutFired('x');
    -  listener.$replay();
    -
    -  handler.registerShortcut('x', 'x');
    -  var key = goog.events.listen(handler,
    -      goog.ui.KeyboardShortcutHandler.EventType.SHORTCUT_TRIGGERED,
    -      function(event) { return false });
    -
    -  assertFalse('return false in listener must prevent default',
    -              fire(KeyCodes.X));
    -
    -  listener.$verify();
    -
    -  goog.events.unlistenByKey(key);
    -}
    -
    -function testPreventsDefaultWhenExceptionThrown() {
    -  handler.registerShortcut('x', 'x');
    -  handler.setAlwaysPreventDefault(true);
    -  goog.events.listenOnce(handler,
    -      goog.ui.KeyboardShortcutHandler.EventType.SHORTCUT_TRIGGERED,
    -      function(event) { throw new Error('x'); });
    -
    -  // We can't use the standard infrastructure to detect that
    -  // the event was preventDefaulted, because of the exception.
    -  var callCount = 0;
    -  stubs.set(goog.events.BrowserEvent.prototype, 'preventDefault',
    -      function() {
    -        callCount++;
    -      });
    -
    -  var e = assertThrows(goog.partial(fire, KeyCodes.X));
    -  assertEquals('x', e.message);
    -
    -  assertEquals(1, callCount);
    -}
    -
    -function testDoesntFireWhenUserForgetsRequiredModifier() {
    -  listener.$replay(); // no events expected
    -
    -  handler.registerShortcut('lettergeectrl',
    -      KeyCodes.G, Modifiers.CTRL);
    -  fire(KeyCodes.G);
    -
    -  listener.$verify();
    -}
    -
    -function testDoesntFireIfTooManyModifiersPressed() {
    -  listener.$replay(); // no events expected
    -
    -  handler.registerShortcut('lettergeectrl',
    -      KeyCodes.G, Modifiers.CTRL);
    -  fire(KeyCodes.G, {ctrlKey: true, metaKey: true});
    -
    -  listener.$verify();
    -}
    -
    -function testDoesntFireIfAnyRequiredModifierForgotten() {
    -  listener.$replay(); // no events expected
    -
    -  handler.registerShortcut('lettergeectrlaltshift',
    -      KeyCodes.G, Modifiers.CTRL | Modifiers.ALT | Modifiers.SHIFT);
    -  fire(KeyCodes.G, {altKey: true, shiftKey: true});
    -
    -  listener.$verify();
    -}
    -
    -function testAllowsMultiKeySequenceSpecifiedAsArray() {
    -  listener.shortcutFired('quitemacs');
    -  listener.$replay();
    -
    -  handler.registerShortcut('quitemacs',
    -      [KeyCodes.X, Modifiers.CTRL,
    -       KeyCodes.C]);
    -  assertFalse(fire(KeyCodes.X, {ctrlKey: true}));
    -  fire(KeyCodes.C);
    -
    -  listener.$verify();
    -}
    -
    -function testAllowsMultiKeySequenceSpecifiedAsArguments() {
    -  listener.shortcutFired('quitvi');
    -  listener.$replay();
    -
    -  handler.registerShortcut('quitvi',
    -      KeyCodes.SEMICOLON, Modifiers.SHIFT,
    -      KeyCodes.Q, Modifiers.NONE,
    -      KeyCodes.NUM_ONE, Modifiers.SHIFT);
    -  var shiftProperties = { shiftKey: true };
    -  assertFalse(fire(KeyCodes.SEMICOLON, shiftProperties));
    -  assertFalse(fire(KeyCodes.Q));
    -  fire(KeyCodes.NUM_ONE, shiftProperties);
    -
    -  listener.$verify();
    -}
    -
    -function testMultiKeyEventIsNotFiredIfUserIsTooSlow() {
    -  listener.$replay(); // no events expected
    -
    -  handler.registerShortcut('quitemacs',
    -      [KeyCodes.X, Modifiers.CTRL,
    -       KeyCodes.C]);
    -
    -  fire(KeyCodes.X, {ctrlKey: true});
    -
    -  // Wait 3 seconds before hitting C.  Although the actual limit is 1500
    -  // at time of writing, it's best not to over-specify functionality.
    -  mockClock.tick(3000);
    -
    -  fire(KeyCodes.C);
    -
    -  listener.$verify();
    -}
    -
    -function testAllowsMultipleAHandlers() {
    -  listener.shortcutFired('quitvi');
    -  listener.shortcutFired('letterex');
    -  listener.shortcutFired('quitemacs');
    -  listener.$replay();
    -
    -  // register 3 handlers in 3 diferent ways
    -  handler.registerShortcut('quitvi',
    -      KeyCodes.SEMICOLON, Modifiers.SHIFT,
    -      KeyCodes.Q, Modifiers.NONE,
    -      KeyCodes.NUM_ONE, Modifiers.SHIFT);
    -  handler.registerShortcut('quitemacs',
    -      [KeyCodes.X, Modifiers.CTRL,
    -       KeyCodes.C]);
    -  handler.registerShortcut('letterex', 'x');
    -
    -
    -  // quit vi
    -  var shiftProperties = { shiftKey: true };
    -  fire(KeyCodes.SEMICOLON, shiftProperties);
    -  fire(KeyCodes.Q);
    -  fire(KeyCodes.NUM_ONE, shiftProperties);
    -
    -  // then press the letter x
    -  fire(KeyCodes.X);
    -
    -  // then quit emacs
    -  fire(KeyCodes.X, {ctrlKey: true});
    -  fire(KeyCodes.C);
    -
    -  listener.$verify();
    -}
    -
    -function testCanRemoveOneHandler() {
    -  listener.shortcutFired('letterex');
    -  listener.$replay();
    -
    -  // register 2 handlers, then remove quitvi
    -  handler.registerShortcut('quitvi',
    -      KeyCodes.COLON, Modifiers.NONE,
    -      KeyCodes.Q, Modifiers.NONE,
    -      KeyCodes.EXCLAMATION, Modifiers.NONE);
    -  handler.registerShortcut('letterex', 'x');
    -  handler.unregisterShortcut(
    -      KeyCodes.COLON, Modifiers.NONE,
    -      KeyCodes.Q, Modifiers.NONE,
    -      KeyCodes.EXCLAMATION, Modifiers.NONE);
    -
    -  // call the "quit VI" keycodes, even though it is removed
    -  fire(KeyCodes.COLON);
    -  fire(KeyCodes.Q);
    -  fire(KeyCodes.EXCLAMATION);
    -
    -  // press the letter x
    -  fire(KeyCodes.X);
    -
    -  listener.$verify();
    -}
    -
    -function testCanRemoveTwoHandlers() {
    -  listener.$replay(); // no events expected
    -
    -  handler.registerShortcut('quitemacs',
    -      [KeyCodes.X, Modifiers.CTRL,
    -       KeyCodes.C]);
    -  handler.registerShortcut('letterex', 'x');
    -  handler.unregisterShortcut(
    -      [KeyCodes.X, Modifiers.CTRL,
    -       KeyCodes.C]);
    -  handler.unregisterShortcut('x');
    -
    -  fire(KeyCodes.X, {ctrlKey: true});
    -  fire(KeyCodes.C);
    -  fire(KeyCodes.X);
    -
    -  listener.$verify();
    -}
    -
    -function testIsShortcutRegistered_single() {
    -  assertFalse(handler.isShortcutRegistered('x'));
    -  handler.registerShortcut('letterex', 'x');
    -  assertTrue(handler.isShortcutRegistered('x'));
    -  handler.unregisterShortcut('x');
    -  assertFalse(handler.isShortcutRegistered('x'));
    -}
    -
    -function testIsShortcutRegistered_multi() {
    -  assertFalse(handler.isShortcutRegistered('a'));
    -  assertFalse(handler.isShortcutRegistered('a b'));
    -  assertFalse(handler.isShortcutRegistered('a b c'));
    -
    -  handler.registerShortcut('ab', 'a b');
    -
    -  assertFalse(handler.isShortcutRegistered('a'));
    -  assertTrue(handler.isShortcutRegistered('a b'));
    -  assertFalse(handler.isShortcutRegistered('a b c'));
    -
    -  handler.unregisterShortcut('a b');
    -
    -  assertFalse(handler.isShortcutRegistered('a'));
    -  assertFalse(handler.isShortcutRegistered('a b'));
    -  assertFalse(handler.isShortcutRegistered('a b c'));
    -}
    -
    -function testUnregister_subsequence() {
    -  // Unregistering a partial sequence should not orphan shortcuts further in the
    -  // sequence.
    -  handler.registerShortcut('abc', 'a b c');
    -  handler.unregisterShortcut('a b');
    -  assertTrue(handler.isShortcutRegistered('a b c'));
    -}
    -
    -function testUnregister_supersequence() {
    -  // Unregistering a sequence that extends beyond a registered sequence should
    -  // do nothing.
    -  handler.registerShortcut('ab', 'a b');
    -  handler.unregisterShortcut('a b c');
    -  assertTrue(handler.isShortcutRegistered('a b'));
    -}
    -
    -function testUnregister_partialMatchSequence() {
    -  // Unregistering a sequence that partially matches a registered sequence
    -  // should do nothing.
    -  handler.registerShortcut('abc', 'a b c');
    -  handler.unregisterShortcut('a b x');
    -  assertTrue(handler.isShortcutRegistered('a b c'));
    -}
    -
    -function testUnregister_deadBranch() {
    -  // Unregistering a sequence should prune any dead branches in the tree.
    -  handler.registerShortcut('abc', 'a b c');
    -  handler.unregisterShortcut('a b c');
    -  // Default is not should not be prevented in the A key stroke because the A
    -  // branch has been removed from the tree.
    -  assertTrue(fire(KeyCodes.A));
    -}
    -
    -
    -/**
    - * Registers a slew of keyboard shortcuts to test each primary category
    - * of shortcuts.
    - */
    -function registerEnterSpaceXF1AltY() {
    -  // Enter and space are specially handled keys.
    -  handler.registerShortcut('enter', KeyCodes.ENTER);
    -  handler.registerShortcut('space', KeyCodes.SPACE);
    -  // 'x' should be treated as text in many contexts
    -  handler.registerShortcut('x', 'x');
    -  // F1 is a global shortcut.
    -  handler.registerShortcut('global', KeyCodes.F1);
    -  // Alt-Y has modifiers, which pass through most form elements.
    -  handler.registerShortcut('withAlt', 'alt+y');
    -}
    -
    -
    -/**
    - * Fires enter, space, X, F1, and Alt-Y keys on a widget.
    - * @param {Element} target The element on which to fire the events.
    - */
    -function fireEnterSpaceXF1AltY(target) {
    -  fire(KeyCodes.ENTER, undefined, target);
    -  fire(KeyCodes.SPACE, undefined, target);
    -  fire(KeyCodes.X, undefined, target);
    -  fire(KeyCodes.F1, undefined, target);
    -  fire(KeyCodes.Y, {altKey: true}, target);
    -}
    -
    -function testIgnoreNonGlobalShortcutsInSelect() {
    -  var targetSelect = goog.dom.getElement('targetSelect');
    -
    -  listener.shortcutFired('global');
    -  listener.shortcutFired('withAlt');
    -  listener.$replay();
    -
    -  registerEnterSpaceXF1AltY();
    -  fireEnterSpaceXF1AltY(goog.dom.getElement('targetSelect'));
    -
    -  listener.$verify();
    -}
    -
    -function testIgnoreNonGlobalShortcutsInTextArea() {
    -  listener.shortcutFired('global');
    -  listener.shortcutFired('withAlt');
    -  listener.$replay();
    -
    -  registerEnterSpaceXF1AltY();
    -  fireEnterSpaceXF1AltY(goog.dom.getElement('targetTextArea'));
    -
    -  listener.$verify();
    -}
    -
    -
    -/**
    - * Checks that the shortcuts are fired on each target.
    - * @param {Array<string>} shortcuts A list of shortcut identifiers.
    - * @param {Array<string>} targets A list of element IDs.
    - * @param {function(Element)} fireEvents Function that fires events.
    - */
    -function expectShortcutsOnTargets(shortcuts, targets, fireEvents) {
    -  for (var i = 0, ii = targets.length; i < ii; i++) {
    -    for (var j = 0, jj = shortcuts.length; j < jj; j++) {
    -      listener.shortcutFired(shortcuts[j]);
    -    }
    -    listener.$replay();
    -    fireEvents(goog.dom.getElement(targets[i]));
    -    listener.$verify();
    -    listener.$reset();
    -  }
    -}
    -
    -function testIgnoreShortcutsExceptEnterInTextInputFields() {
    -  var targets = [
    -    'targetColor',
    -    'targetDate',
    -    'targetDateTime',
    -    'targetDateTimeLocal',
    -    'targetEmail',
    -    'targetMonth',
    -    'targetNumber',
    -    'targetPassword',
    -    'targetSearch',
    -    'targetTel',
    -    'targetText',
    -    'targetTime',
    -    'targetUrl',
    -    'targetWeek'
    -  ];
    -  registerEnterSpaceXF1AltY();
    -  expectShortcutsOnTargets(
    -      ['enter', 'global', 'withAlt'], targets, fireEnterSpaceXF1AltY);
    -}
    -
    -function testIgnoreSpaceInCheckBoxAndButton() {
    -  registerEnterSpaceXF1AltY();
    -  expectShortcutsOnTargets(
    -      ['enter', 'x', 'global', 'withAlt'],
    -      ['targetCheckBox', 'targetButton'],
    -      fireEnterSpaceXF1AltY);
    -}
    -
    -function testIgnoreNonGlobalShortcutsInContentEditable() {
    -  // Don't set design mode in later IE as javascripts don't run when in
    -  // that mode.
    -  var setDesignMode = !goog.userAgent.IE ||
    -      !goog.userAgent.isVersionOrHigher('9');
    -  try {
    -    if (setDesignMode) {
    -      document.designMode = 'on';
    -    }
    -    targetDiv.contentEditable = 'true';
    -
    -    // Expect only global shortcuts.
    -    listener.shortcutFired('global');
    -    listener.$replay();
    -
    -    registerEnterSpaceXF1AltY();
    -    fireEnterSpaceXF1AltY(targetDiv);
    -
    -    listener.$verify();
    -  } finally {
    -    if (setDesignMode) {
    -      document.designMode = 'off';
    -    }
    -    targetDiv.contentEditable = 'false';
    -  }
    -}
    -
    -function testSetAllShortcutsAreGlobal() {
    -  handler.setAllShortcutsAreGlobal(true);
    -  registerEnterSpaceXF1AltY();
    -
    -  expectShortcutsOnTargets(
    -      ['enter', 'space', 'x', 'global', 'withAlt'], ['targetTextArea'],
    -      fireEnterSpaceXF1AltY);
    -}
    -
    -function testSetModifierShortcutsAreGlobalFalse() {
    -  handler.setModifierShortcutsAreGlobal(false);
    -  registerEnterSpaceXF1AltY();
    -
    -  expectShortcutsOnTargets(
    -      ['global'], ['targetTextArea'], fireEnterSpaceXF1AltY);
    -}
    -
    -function testAltGraphKeyOnUSLayout() {
    -  // Windows does not assign printable characters to any ctrl+alt keys of
    -  // the US layout. This test verifies we fire shortcut events when typing
    -  // ctrl+alt keys on the US layout.
    -  listener.shortcutFired('letterOne');
    -  listener.shortcutFired('letterTwo');
    -  listener.shortcutFired('letterThree');
    -  listener.shortcutFired('letterFour');
    -  listener.shortcutFired('letterFive');
    -  if (goog.userAgent.WINDOWS && !goog.userAgent.GECKO) {
    -    listener.$replay();
    -
    -    handler.registerShortcut('letterOne', 'ctrl+alt+1');
    -    handler.registerShortcut('letterTwo', 'ctrl+alt+2');
    -    handler.registerShortcut('letterThree', 'ctrl+alt+3');
    -    handler.registerShortcut('letterFour', 'ctrl+alt+4');
    -    handler.registerShortcut('letterFive', 'ctrl+alt+5');
    -
    -    // Send key events on the English (United States) layout.
    -    fireAltGraphKey(KeyCodes.ONE, 0, {ctrlKey: true, altKey: true});
    -    fireAltGraphKey(KeyCodes.TWO, 0, {ctrlKey: true, altKey: true});
    -    fireAltGraphKey(KeyCodes.THREE, 0, {ctrlKey: true, altKey: true});
    -    fireAltGraphKey(KeyCodes.FOUR, 0, {ctrlKey: true, altKey: true});
    -    fireAltGraphKey(KeyCodes.FIVE, 0, {ctrlKey: true, altKey: true});
    -
    -    listener.$verify();
    -  }
    -}
    -
    -function testAltGraphKeyOnFrenchLayout() {
    -  // Windows assigns printable characters to ctrl+alt+[2-5] keys of the
    -  // French layout. This test verifies we fire shortcut events only when
    -  // we type ctrl+alt+1 keys on the French layout.
    -  listener.shortcutFired('letterOne');
    -  if (goog.userAgent.WINDOWS && !goog.userAgent.GECKO) {
    -    listener.$replay();
    -
    -    handler.registerShortcut('letterOne', 'ctrl+alt+1');
    -    handler.registerShortcut('letterTwo', 'ctrl+alt+2');
    -    handler.registerShortcut('letterThree', 'ctrl+alt+3');
    -    handler.registerShortcut('letterFour', 'ctrl+alt+4');
    -    handler.registerShortcut('letterFive', 'ctrl+alt+5');
    -
    -    // Send key events on the French (France) layout.
    -    fireAltGraphKey(KeyCodes.ONE, 0, {ctrlKey: true, altKey: true});
    -    fireAltGraphKey(KeyCodes.TWO, 0x0303, {ctrlKey: true, altKey: true});
    -    fireAltGraphKey(KeyCodes.THREE, 0x0023, {ctrlKey: true, altKey: true});
    -    fireAltGraphKey(KeyCodes.FOUR, 0x007b, {ctrlKey: true, altKey: true});
    -    fireAltGraphKey(KeyCodes.FIVE, 0x205b, {ctrlKey: true, altKey: true});
    -
    -    listener.$verify();
    -  }
    -}
    -
    -function testAltGraphKeyOnSpanishLayout() {
    -  // Windows assigns printable characters to ctrl+alt+[1-5] keys of the
    -  // Spanish layout. This test verifies we do not fire shortcut events at
    -  // all when typing ctrl+alt+[1-5] keys on the Spanish layout.
    -  if (goog.userAgent.WINDOWS && !goog.userAgent.GECKO) {
    -    listener.$replay();
    -
    -    handler.registerShortcut('letterOne', 'ctrl+alt+1');
    -    handler.registerShortcut('letterTwo', 'ctrl+alt+2');
    -    handler.registerShortcut('letterThree', 'ctrl+alt+3');
    -    handler.registerShortcut('letterFour', 'ctrl+alt+4');
    -    handler.registerShortcut('letterFive', 'ctrl+alt+5');
    -
    -    // Send key events on the Spanish (Spain) layout.
    -    fireAltGraphKey(KeyCodes.ONE, 0x007c, {ctrlKey: true, altKey: true});
    -    fireAltGraphKey(KeyCodes.TWO, 0x0040, {ctrlKey: true, altKey: true});
    -    fireAltGraphKey(KeyCodes.THREE, 0x0023, {ctrlKey: true, altKey: true});
    -    fireAltGraphKey(KeyCodes.FOUR, 0x0303, {ctrlKey: true, altKey: true});
    -    fireAltGraphKey(KeyCodes.FIVE, 0x20ac, {ctrlKey: true, altKey: true});
    -
    -    listener.$verify();
    -  }
    -}
    -
    -function testNumpadKeyShortcuts() {
    -  var testCases = [
    -    ['letterNumpad0', 'num-0', KeyCodes.NUM_ZERO],
    -    ['letterNumpad1', 'num-1', KeyCodes.NUM_ONE],
    -    ['letterNumpad2', 'num-2', KeyCodes.NUM_TWO],
    -    ['letterNumpad3', 'num-3', KeyCodes.NUM_THREE],
    -    ['letterNumpad4', 'num-4', KeyCodes.NUM_FOUR],
    -    ['letterNumpad5', 'num-5', KeyCodes.NUM_FIVE],
    -    ['letterNumpad6', 'num-6', KeyCodes.NUM_SIX],
    -    ['letterNumpad7', 'num-7', KeyCodes.NUM_SEVEN],
    -    ['letterNumpad8', 'num-8', KeyCodes.NUM_EIGHT],
    -    ['letterNumpad9', 'num-9', KeyCodes.NUM_NINE],
    -    ['letterNumpadMultiply', 'num-multiply', KeyCodes.NUM_MULTIPLY],
    -    ['letterNumpadPlus', 'num-plus', KeyCodes.NUM_PLUS],
    -    ['letterNumpadMinus', 'num-minus', KeyCodes.NUM_MINUS],
    -    ['letterNumpadPERIOD', 'num-period', KeyCodes.NUM_PERIOD],
    -    ['letterNumpadDIVISION', 'num-division', KeyCodes.NUM_DIVISION]
    -  ];
    -  for (var i = 0; i < testCases.length; ++i) {
    -    listener.shortcutFired(testCases[i][0]);
    -  }
    -  listener.$replay();
    -
    -  // Register shortcuts for numpad keys and send numpad-key events.
    -  for (var i = 0; i < testCases.length; ++i) {
    -    handler.registerShortcut(testCases[i][0], testCases[i][1]);
    -    fire(testCases[i][2]);
    -  }
    -  listener.$verify();
    -}
    -
    -function testGeckoShortcuts() {
    -  listener.shortcutFired('1');
    -  listener.$replay();
    -
    -  handler.registerShortcut('1', 'semicolon');
    -
    -  if (goog.userAgent.GECKO) {
    -    fire(goog.events.KeyCodes.FF_SEMICOLON);
    -  } else {
    -    fire(goog.events.KeyCodes.SEMICOLON);
    -  }
    -
    -  listener.$verify();
    -}
    -
    -function testRegisterShortcut_modifierOnly() {
    -  assertThrows('Registering a shortcut with just modifiers should fail.',
    -      goog.bind(handler.registerShortcut, handler, 'name', 'Shift'));
    -}
    -
    -function testParseStringShortcut_unknownKey() {
    -  assertThrows('Unknown keys should fail.', goog.bind(
    -      goog.ui.KeyboardShortcutHandler.parseStringShortcut, null, 'NotAKey'));
    -}
    -
    -// Regression test for failure to reset keyCode between strokes.
    -function testParseStringShortcut_resetKeyCode() {
    -  var strokes = goog.ui.KeyboardShortcutHandler.parseStringShortcut('A Shift');
    -  assertNull('The second stroke only has a modifier key.', strokes[1].keyCode);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/labelinput.js b/src/database/third_party/closure-library/closure/goog/ui/labelinput.js
    deleted file mode 100644
    index a894f41fdfa..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/labelinput.js
    +++ /dev/null
    @@ -1,612 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview This behavior is applied to a text input and it shows a text
    - * message inside the element if the user hasn't entered any text.
    - *
    - * This uses the HTML5 placeholder attribute where it is supported.
    - *
    - * This is ported from http://go/labelinput.js
    - *
    - * Known issue: Safari does not allow you get to the window object from a
    - * document. We need that to listen to the onload event. For now we hard code
    - * the window to the current window.
    - *
    - * Known issue: We need to listen to the form submit event but we attach the
    - * event only once (when created or when it is changed) so if you move the DOM
    - * node to another form it will not be cleared correctly before submitting.
    - *
    - * @author arv@google.com (Erik Arvidsson)
    - * @see ../demos/labelinput.html
    - */
    -
    -goog.provide('goog.ui.LabelInput');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventType');
    -goog.require('goog.ui.Component');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * This creates the label input object.
    - * @param {string=} opt_label The text to show as the label.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @extends {goog.ui.Component}
    - * @constructor
    - */
    -goog.ui.LabelInput = function(opt_label, opt_domHelper) {
    -  goog.ui.Component.call(this, opt_domHelper);
    -
    -  /**
    -   * The text to show as the label.
    -   * @type {string}
    -   * @private
    -   */
    -  this.label_ = opt_label || '';
    -};
    -goog.inherits(goog.ui.LabelInput, goog.ui.Component);
    -goog.tagUnsealableClass(goog.ui.LabelInput);
    -
    -
    -/**
    - * Variable used to store the element value on keydown and restore it on
    - * keypress.  See {@link #handleEscapeKeys_}
    - * @type {?string}
    - * @private
    - */
    -goog.ui.LabelInput.prototype.ffKeyRestoreValue_ = null;
    -
    -
    -/**
    - * The label restore delay after leaving the input.
    - * @type {number} Delay for restoring the label.
    - * @protected
    - */
    -goog.ui.LabelInput.prototype.labelRestoreDelayMs = 10;
    -
    -
    -/** @private {boolean} */
    -goog.ui.LabelInput.prototype.inFocusAndSelect_;
    -
    -
    -/** @private {boolean} */
    -goog.ui.LabelInput.prototype.formAttached_;
    -
    -
    -/**
    - * Indicates whether the browser supports the placeholder attribute, new in
    - * HTML5.
    - * @type {?boolean}
    - * @private
    - */
    -goog.ui.LabelInput.SUPPORTS_PLACEHOLDER_;
    -
    -
    -/**
    - * Checks browser support for placeholder attribute.
    - * @return {boolean} Whether placeholder attribute is supported.
    - * @private
    - */
    -goog.ui.LabelInput.isPlaceholderSupported_ = function() {
    -  if (!goog.isDefAndNotNull(goog.ui.LabelInput.SUPPORTS_PLACEHOLDER_)) {
    -    goog.ui.LabelInput.SUPPORTS_PLACEHOLDER_ = (
    -        'placeholder' in document.createElement('input'));
    -  }
    -  return goog.ui.LabelInput.SUPPORTS_PLACEHOLDER_;
    -};
    -
    -
    -/**
    - * @type {goog.events.EventHandler}
    - * @private
    - */
    -goog.ui.LabelInput.prototype.eventHandler_;
    -
    -
    -/**
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.LabelInput.prototype.hasFocus_ = false;
    -
    -
    -/**
    - * Creates the DOM nodes needed for the label input.
    - * @override
    - */
    -goog.ui.LabelInput.prototype.createDom = function() {
    -  this.setElementInternal(
    -      this.getDomHelper().createDom('input', {'type': 'text'}));
    -};
    -
    -
    -/**
    - * Decorates an existing HTML input element as a label input. If the element
    - * has a "label" attribute then that will be used as the label property for the
    - * label input object.
    - * @param {Element} element The HTML input element to decorate.
    - * @override
    - */
    -goog.ui.LabelInput.prototype.decorateInternal = function(element) {
    -  goog.ui.LabelInput.superClass_.decorateInternal.call(this, element);
    -  if (!this.label_) {
    -    this.label_ = element.getAttribute('label') || '';
    -  }
    -
    -  // Check if we're attaching to an element that already has focus.
    -  if (goog.dom.getActiveElement(goog.dom.getOwnerDocument(element)) ==
    -      element) {
    -    this.hasFocus_ = true;
    -    var el = this.getElement();
    -    goog.asserts.assert(el);
    -    goog.dom.classlist.remove(el, this.labelCssClassName);
    -  }
    -
    -  if (goog.ui.LabelInput.isPlaceholderSupported_()) {
    -    this.getElement().placeholder = this.label_;
    -  }
    -  var labelInputElement = this.getElement();
    -  goog.asserts.assert(labelInputElement,
    -      'The label input element cannot be null.');
    -  goog.a11y.aria.setState(labelInputElement,
    -      goog.a11y.aria.State.LABEL,
    -      this.label_);
    -};
    -
    -
    -/** @override */
    -goog.ui.LabelInput.prototype.enterDocument = function() {
    -  goog.ui.LabelInput.superClass_.enterDocument.call(this);
    -  this.attachEvents_();
    -  this.check_();
    -
    -  // Make it easy for other closure widgets to play nicely with inputs using
    -  // LabelInput:
    -  this.getElement().labelInput_ = this;
    -};
    -
    -
    -/** @override */
    -goog.ui.LabelInput.prototype.exitDocument = function() {
    -  goog.ui.LabelInput.superClass_.exitDocument.call(this);
    -  this.detachEvents_();
    -
    -  this.getElement().labelInput_ = null;
    -};
    -
    -
    -/**
    - * Attaches the events we need to listen to.
    - * @private
    - */
    -goog.ui.LabelInput.prototype.attachEvents_ = function() {
    -  var eh = new goog.events.EventHandler(this);
    -  eh.listen(this.getElement(), goog.events.EventType.FOCUS, this.handleFocus_);
    -  eh.listen(this.getElement(), goog.events.EventType.BLUR, this.handleBlur_);
    -
    -  if (goog.ui.LabelInput.isPlaceholderSupported_()) {
    -    this.eventHandler_ = eh;
    -    return;
    -  }
    -
    -  if (goog.userAgent.GECKO) {
    -    eh.listen(this.getElement(), [
    -      goog.events.EventType.KEYPRESS,
    -      goog.events.EventType.KEYDOWN,
    -      goog.events.EventType.KEYUP
    -    ], this.handleEscapeKeys_);
    -  }
    -
    -  // IE sets defaultValue upon load so we need to test that as well.
    -  var d = goog.dom.getOwnerDocument(this.getElement());
    -  var w = goog.dom.getWindow(d);
    -  eh.listen(w, goog.events.EventType.LOAD, this.handleWindowLoad_);
    -
    -  this.eventHandler_ = eh;
    -  this.attachEventsToForm_();
    -};
    -
    -
    -/**
    - * Adds a listener to the form so that we can clear the input before it is
    - * submitted.
    - * @private
    - */
    -goog.ui.LabelInput.prototype.attachEventsToForm_ = function() {
    -  // in case we have are in a form we need to make sure the label is not
    -  // submitted
    -  if (!this.formAttached_ && this.eventHandler_ && this.getElement().form) {
    -    this.eventHandler_.listen(this.getElement().form,
    -                              goog.events.EventType.SUBMIT,
    -                              this.handleFormSubmit_);
    -    this.formAttached_ = true;
    -  }
    -};
    -
    -
    -/**
    - * Stops listening to the events.
    - * @private
    - */
    -goog.ui.LabelInput.prototype.detachEvents_ = function() {
    -  if (this.eventHandler_) {
    -    this.eventHandler_.dispose();
    -    this.eventHandler_ = null;
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.LabelInput.prototype.disposeInternal = function() {
    -  goog.ui.LabelInput.superClass_.disposeInternal.call(this);
    -  this.detachEvents_();
    -};
    -
    -
    -/**
    - * The CSS class name to add to the input when the user has not entered a
    - * value.
    - */
    -goog.ui.LabelInput.prototype.labelCssClassName =
    -    goog.getCssName('label-input-label');
    -
    -
    -/**
    - * Handler for the focus event.
    - * @param {goog.events.Event} e The event object passed in to the event handler.
    - * @private
    - */
    -goog.ui.LabelInput.prototype.handleFocus_ = function(e) {
    -  this.hasFocus_ = true;
    -  var el = this.getElement();
    -  goog.asserts.assert(el);
    -  goog.dom.classlist.remove(el, this.labelCssClassName);
    -  if (goog.ui.LabelInput.isPlaceholderSupported_()) {
    -    return;
    -  }
    -  if (!this.hasChanged() && !this.inFocusAndSelect_) {
    -    var me = this;
    -    var clearValue = function() {
    -      // Component could be disposed by the time this is called.
    -      if (me.getElement()) {
    -        me.getElement().value = '';
    -      }
    -    };
    -    if (goog.userAgent.IE) {
    -      goog.Timer.callOnce(clearValue, 10);
    -    } else {
    -      clearValue();
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Handler for the blur event.
    - * @param {goog.events.Event} e The event object passed in to the event handler.
    - * @private
    - */
    -goog.ui.LabelInput.prototype.handleBlur_ = function(e) {
    -  // We listen to the click event when we enter focusAndSelect mode so we can
    -  // fake an artificial focus when the user clicks on the input box. However,
    -  // if the user clicks on something else (and we lose focus), there is no
    -  // need for an artificial focus event.
    -  if (!goog.ui.LabelInput.isPlaceholderSupported_()) {
    -    this.eventHandler_.unlisten(
    -        this.getElement(), goog.events.EventType.CLICK, this.handleFocus_);
    -    this.ffKeyRestoreValue_ = null;
    -  }
    -  this.hasFocus_ = false;
    -  this.check_();
    -};
    -
    -
    -/**
    - * Handler for key events in Firefox.
    - *
    - * If the escape key is pressed when a text input has not been changed manually
    - * since being focused, the text input will revert to its previous value.
    - * Firefox does not honor preventDefault for the escape key. The revert happens
    - * after the keydown event and before every keypress. We therefore store the
    - * element's value on keydown and restore it on keypress. The restore value is
    - * nullified on keyup so that {@link #getValue} returns the correct value.
    - *
    - * IE and Chrome don't have this problem, Opera blurs in the input box
    - * completely in a way that preventDefault on the escape key has no effect.
    - *
    - * @param {goog.events.BrowserEvent} e The event object passed in to
    - *     the event handler.
    - * @private
    - */
    -goog.ui.LabelInput.prototype.handleEscapeKeys_ = function(e) {
    -  if (e.keyCode == 27) {
    -    if (e.type == goog.events.EventType.KEYDOWN) {
    -      this.ffKeyRestoreValue_ = this.getElement().value;
    -    } else if (e.type == goog.events.EventType.KEYPRESS) {
    -      this.getElement().value = /** @type {string} */ (this.ffKeyRestoreValue_);
    -    } else if (e.type == goog.events.EventType.KEYUP) {
    -      this.ffKeyRestoreValue_ = null;
    -    }
    -    e.preventDefault();
    -  }
    -};
    -
    -
    -/**
    - * Handler for the submit event of the form element.
    - * @param {goog.events.Event} e The event object passed in to the event handler.
    - * @private
    - */
    -goog.ui.LabelInput.prototype.handleFormSubmit_ = function(e) {
    -  if (!this.hasChanged()) {
    -    this.getElement().value = '';
    -    // allow form to be sent before restoring value
    -    goog.Timer.callOnce(this.handleAfterSubmit_, 10, this);
    -  }
    -};
    -
    -
    -/**
    - * Restore value after submit
    - * @private
    - */
    -goog.ui.LabelInput.prototype.handleAfterSubmit_ = function() {
    -  if (!this.hasChanged()) {
    -    this.getElement().value = this.label_;
    -  }
    -};
    -
    -
    -/**
    - * Handler for the load event the window. This is needed because
    - * IE sets defaultValue upon load.
    - * @param {Event} e The event object passed in to the event handler.
    - * @private
    - */
    -goog.ui.LabelInput.prototype.handleWindowLoad_ = function(e) {
    -  this.check_();
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the control is currently focused on.
    - */
    -goog.ui.LabelInput.prototype.hasFocus = function() {
    -  return this.hasFocus_;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the value has been changed by the user.
    - */
    -goog.ui.LabelInput.prototype.hasChanged = function() {
    -  return !!this.getElement() && this.getElement().value != '' &&
    -      this.getElement().value != this.label_;
    -};
    -
    -
    -/**
    - * Clears the value of the input element without resetting the default text.
    - */
    -goog.ui.LabelInput.prototype.clear = function() {
    -  this.getElement().value = '';
    -
    -  // Reset ffKeyRestoreValue_ when non-null
    -  if (this.ffKeyRestoreValue_ != null) {
    -    this.ffKeyRestoreValue_ = '';
    -  }
    -};
    -
    -
    -/**
    - * Clears the value of the input element and resets the default text.
    - */
    -goog.ui.LabelInput.prototype.reset = function() {
    -  if (this.hasChanged()) {
    -    this.clear();
    -    this.check_();
    -  }
    -};
    -
    -
    -/**
    - * Use this to set the value through script to ensure that the label state is
    - * up to date
    - * @param {string} s The new value for the input.
    - */
    -goog.ui.LabelInput.prototype.setValue = function(s) {
    -  if (this.ffKeyRestoreValue_ != null) {
    -    this.ffKeyRestoreValue_ = s;
    -  }
    -  this.getElement().value = s;
    -  this.check_();
    -};
    -
    -
    -/**
    - * Returns the current value of the text box, returning an empty string if the
    - * search box is the default value
    - * @return {string} The value of the input box.
    - */
    -goog.ui.LabelInput.prototype.getValue = function() {
    -  if (this.ffKeyRestoreValue_ != null) {
    -    // Fix the Firefox from incorrectly reporting the value to calling code
    -    // that attached the listener to keypress before the labelinput
    -    return this.ffKeyRestoreValue_;
    -  }
    -  return this.hasChanged() ? /** @type {string} */ (this.getElement().value) :
    -      '';
    -};
    -
    -
    -/**
    - * Sets the label text as aria-label, and placeholder when supported.
    - * @param {string} label The text to show as the label.
    - */
    -goog.ui.LabelInput.prototype.setLabel = function(label) {
    -  var labelInputElement = this.getElement();
    -
    -  if (goog.ui.LabelInput.isPlaceholderSupported_()) {
    -    if (labelInputElement) {
    -      labelInputElement.placeholder = label;
    -    }
    -    this.label_ = label;
    -  } else if (!this.hasChanged()) {
    -    // The this.hasChanged() call relies on non-placeholder behavior checking
    -    // prior to setting this.label_ - it also needs to happen prior to the
    -    // this.restoreLabel_() call.
    -    if (labelInputElement) {
    -      labelInputElement.value = '';
    -    }
    -    this.label_ = label;
    -    this.restoreLabel_();
    -  }
    -  // Check if this has been called before DOM structure building
    -  if (labelInputElement) {
    -    goog.a11y.aria.setState(labelInputElement,
    -        goog.a11y.aria.State.LABEL,
    -        this.label_);
    -  }
    -};
    -
    -
    -/**
    - * @return {string} The text to show as the label.
    - */
    -goog.ui.LabelInput.prototype.getLabel = function() {
    -  return this.label_;
    -};
    -
    -
    -/**
    - * Checks the state of the input element
    - * @private
    - */
    -goog.ui.LabelInput.prototype.check_ = function() {
    -  var labelInputElement = this.getElement();
    -  goog.asserts.assert(labelInputElement,
    -      'The label input element cannot be null.');
    -  if (!goog.ui.LabelInput.isPlaceholderSupported_()) {
    -    // if we haven't got a form yet try now
    -    this.attachEventsToForm_();
    -  } else if (this.getElement().placeholder != this.label_) {
    -    this.getElement().placeholder = this.label_;
    -  }
    -  goog.a11y.aria.setState(labelInputElement,
    -      goog.a11y.aria.State.LABEL,
    -      this.label_);
    -
    -  if (!this.hasChanged()) {
    -    if (!this.inFocusAndSelect_ && !this.hasFocus_) {
    -      var el = this.getElement();
    -      goog.asserts.assert(el);
    -      goog.dom.classlist.add(el, this.labelCssClassName);
    -    }
    -
    -    // Allow browser to catchup with CSS changes before restoring the label.
    -    if (!goog.ui.LabelInput.isPlaceholderSupported_()) {
    -      goog.Timer.callOnce(this.restoreLabel_, this.labelRestoreDelayMs,
    -          this);
    -    }
    -  } else {
    -    var el = this.getElement();
    -    goog.asserts.assert(el);
    -    goog.dom.classlist.remove(el, this.labelCssClassName);
    -  }
    -};
    -
    -
    -/**
    - * This method focuses the input and selects all the text. If the value hasn't
    - * changed it will set the value to the label so that the label text is
    - * selected.
    - */
    -goog.ui.LabelInput.prototype.focusAndSelect = function() {
    -  // We need to check whether the input has changed before focusing
    -  var hc = this.hasChanged();
    -  this.inFocusAndSelect_ = true;
    -  this.getElement().focus();
    -  if (!hc && !goog.ui.LabelInput.isPlaceholderSupported_()) {
    -    this.getElement().value = this.label_;
    -  }
    -  this.getElement().select();
    -
    -  // Since the object now has focus, we won't get a focus event when they
    -  // click in the input element. The expected behavior when you click on
    -  // the default text is that it goes away and allows you to type...so we
    -  // have to fire an artificial focus event when we're in focusAndSelect mode.
    -  if (goog.ui.LabelInput.isPlaceholderSupported_()) {
    -    return;
    -  }
    -  if (this.eventHandler_) {
    -    this.eventHandler_.listenOnce(
    -        this.getElement(), goog.events.EventType.CLICK, this.handleFocus_);
    -  }
    -
    -  // set to false in timer to let IE trigger the focus event
    -  goog.Timer.callOnce(this.focusAndSelect_, 10, this);
    -};
    -
    -
    -/**
    - * Enables/Disables the label input.
    - * @param {boolean} enabled Whether to enable (true) or disable (false) the
    - *     label input.
    - */
    -goog.ui.LabelInput.prototype.setEnabled = function(enabled) {
    -  this.getElement().disabled = !enabled;
    -  var el = this.getElement();
    -  goog.asserts.assert(el);
    -  goog.dom.classlist.enable(el,
    -      goog.getCssName(this.labelCssClassName, 'disabled'), !enabled);
    -};
    -
    -
    -/**
    - * @return {boolean} True if the label input is enabled, false otherwise.
    - */
    -goog.ui.LabelInput.prototype.isEnabled = function() {
    -  return !this.getElement().disabled;
    -};
    -
    -
    -/**
    - * @private
    - */
    -goog.ui.LabelInput.prototype.focusAndSelect_ = function() {
    -  this.inFocusAndSelect_ = false;
    -};
    -
    -
    -/**
    - * Sets the value of the input element to label.
    - * @private
    - */
    -goog.ui.LabelInput.prototype.restoreLabel_ = function() {
    -  // Check again in case something changed since this was scheduled.
    -  // We check that the element is still there since this is called by a timer
    -  // and the dispose method may have been called prior to this.
    -  if (this.getElement() && !this.hasChanged() && !this.hasFocus_) {
    -    this.getElement().value = this.label_;
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/labelinput_test.html b/src/database/third_party/closure-library/closure/goog/ui/labelinput_test.html
    deleted file mode 100644
    index 74f8ef011b0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/labelinput_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.LabelInput
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.LabelInputTest');
    -  </script>
    - </head>
    - <body>
    -  <input id="i" type="text" />
    -  <input id="p" type="text" placeholder="browser-ignorant placeholder" />
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/labelinput_test.js b/src/database/third_party/closure-library/closure/goog/ui/labelinput_test.js
    deleted file mode 100644
    index d739feda485..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/labelinput_test.js
    +++ /dev/null
    @@ -1,250 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.LabelInputTest');
    -goog.setTestOnly('goog.ui.LabelInputTest');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events.EventType');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.events.Event');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.LabelInput');
    -goog.require('goog.userAgent');
    -
    -var labelInput;
    -var mockClock;
    -
    -function setUp() {
    -  mockClock = new goog.testing.MockClock(true);
    -}
    -
    -function tearDown() {
    -  mockClock.dispose();
    -  labelInput.dispose();
    -}
    -
    -function testGetLabel() {
    -  labelInput = new goog.ui.LabelInput();
    -  assertEquals('no label', '', labelInput.getLabel());
    -
    -  labelInput = new goog.ui.LabelInput('search');
    -  assertEquals('label is given in the ctor', 'search', labelInput.getLabel());
    -}
    -
    -function testSetLabel() {
    -  labelInput = new goog.ui.LabelInput();
    -  labelInput.setLabel('search');
    -  assertEquals('label is set', 'search', labelInput.getLabel());
    -
    -  labelInput.createDom();
    -  labelInput.enterDocument();
    -  mockClock.tick(10);
    -  assertNotNull(labelInput.getElement());
    -  assertLabelValue(labelInput, 'search');
    -
    -  labelInput.setLabel('new label');
    -  assertLabelValue(labelInput, 'new label');
    -}
    -
    -function assertLabelValue(labelInput, expectedLabel) {
    -  assertEquals(
    -      'label should have aria-label attribute \'' + expectedLabel + '\'',
    -      expectedLabel, goog.a11y.aria.getState(labelInput.getElement(),
    -          goog.a11y.aria.State.LABEL));
    -  // When browsers support the placeholder attribute, we use that instead of
    -  // the value property - and this test will fail.
    -  if (!isPlaceholderSupported()) {
    -    assertEquals(
    -        'label is updated', expectedLabel, labelInput.getElement().value);
    -  } else {
    -    assertEquals('value is empty', '', labelInput.getElement().value);
    -  }
    -}
    -
    -function testPlaceholderAttribute() {
    -  labelInput = new goog.ui.LabelInput();
    -  labelInput.setLabel('search');
    -
    -  // Some browsers don't support the placeholder attribute, in which case we
    -  // this test will fail.
    -  if (! isPlaceholderSupported()) {
    -    return;
    -  }
    -
    -  labelInput.createDom();
    -  labelInput.enterDocument();
    -  mockClock.tick(10);
    -  assertEquals('label should have placeholder attribute \'search\'', 'search',
    -      labelInput.getElement().placeholder);
    -
    -  labelInput.setLabel('new label');
    -  assertEquals('label should have aria-label attribute \'new label\'',
    -      'new label', labelInput.getElement().placeholder);
    -}
    -
    -function testDecorateElementWithExistingPlaceholderAttribute() {
    -  labelInput = new goog.ui.LabelInput();
    -  labelInput.setLabel('search');
    -
    -  labelInput.decorate(goog.dom.getElement('p'));
    -  labelInput.enterDocument();
    -  mockClock.tick(10);
    -
    -  // The presence of an existing placeholder doesn't necessarily mean the
    -  // browser supports placeholders. Make sure labels are used for browsers
    -  // without placeholder support:
    -  if (isPlaceholderSupported()) {
    -    assertEquals('label should have placeholder attribute \'search\'', 'search',
    -        labelInput.getElement().placeholder);
    -  } else {
    -    assertNotNull(labelInput.getElement());
    -    assertEquals('label is rendered', 'search', labelInput.getElement().value);
    -    assertEquals('label should have aria-label attribute \'search\'', 'search',
    -        goog.a11y.aria.getState(labelInput.getElement(),
    -            goog.a11y.aria.State.LABEL));
    -  }
    -}
    -
    -function testDecorateElementWithFocus() {
    -  labelInput = new goog.ui.LabelInput();
    -  labelInput.setLabel('search');
    -
    -  var decoratedElement = goog.dom.getElement('i');
    -
    -  decoratedElement.value = '';
    -  decoratedElement.focus();
    -
    -  labelInput.decorate(decoratedElement);
    -  labelInput.enterDocument();
    -  mockClock.tick(10);
    -
    -  assertEquals('label for pre-focused input should not have LABEL_CLASS_NAME',
    -      -1,
    -      labelInput.getElement().className.indexOf(labelInput.labelCssClassName));
    -
    -  if (!isPlaceholderSupported()) {
    -    assertEquals('label rendered for pre-focused element',
    -        '', labelInput.getElement().value);
    -    // NOTE(user): element.blur() doesn't seem to trigger the BLUR event in
    -    // IE in the test environment. This could be related to the IE issues with
    -    // testClassName() below.
    -    goog.testing.events.fireBrowserEvent(
    -        new goog.testing.events.Event(
    -            goog.events.EventType.BLUR, decoratedElement));
    -    mockClock.tick(10);
    -    assertEquals('label not rendered for blurred element',
    -        'search', labelInput.getElement().value);
    -  }
    -}
    -
    -function testDecorateElementWithFocusDelay() {
    -  if (isPlaceholderSupported()) {
    -    return; // Delay only affects the older browsers.
    -  }
    -  var placeholder = 'search';
    -
    -  labelInput = new goog.ui.LabelInput();
    -  labelInput.setLabel(placeholder);
    -  var delay = 150;
    -  labelInput.labelRestoreDelayMs = delay;
    -
    -  var decoratedElement = goog.dom.getElement('i');
    -
    -  decoratedElement.value = '';
    -  decoratedElement.focus();
    -
    -  labelInput.decorate(decoratedElement);
    -  labelInput.enterDocument();
    -  // wait for all initial setup to settle
    -  mockClock.tick(delay);
    -
    -  // NOTE(user): element.blur() doesn't seem to trigger the BLUR event in
    -  // IE in the test environment. This could be related to the IE issues with
    -  // testClassName() below.
    -  goog.testing.events.fireBrowserEvent(
    -      new goog.testing.events.Event(
    -          goog.events.EventType.BLUR, decoratedElement));
    -
    -  mockClock.tick(delay - 1);
    -  assertEquals('label should not be restored before labelRestoreDelay',
    -      '', labelInput.getElement().value);
    -
    -  mockClock.tick(1);
    -  assertEquals('label not rendered for blurred element with labelRestoreDelay',
    -      placeholder, labelInput.getElement().value);
    -}
    -
    -function testClassName() {
    -  labelInput = new goog.ui.LabelInput();
    -
    -  // IE always fails this test, suspect it is a focus issue.
    -  if (goog.userAgent.IE) {
    -    return;
    -  }
    -  // FF does not perform focus if the window is not active in the first place.
    -  if (goog.userAgent.GECKO && document.hasFocus && !document.hasFocus()) {
    -    return;
    -  }
    -
    -  labelInput.decorate(goog.dom.getElement('i'));
    -  labelInput.setLabel('search');
    -
    -  var el = labelInput.getElement();
    -  assertTrue('label before focus should have LABEL_CLASS_NAME',
    -      goog.dom.classlist.contains(el, labelInput.labelCssClassName));
    -
    -  labelInput.getElement().focus();
    -
    -  assertFalse('label after focus should not have LABEL_CLASS_NAME',
    -      goog.dom.classlist.contains(el, labelInput.labelCssClassName));
    -
    -  labelInput.getElement().blur();
    -
    -  assertTrue('label after blur should have LABEL_CLASS_NAME',
    -      goog.dom.classlist.contains(el, labelInput.labelCssClassName));
    -}
    -
    -function isPlaceholderSupported() {
    -  if (goog.dom.getElement('i').placeholder != null) {
    -    return true;
    -  }
    -}
    -
    -function testEnable() {
    -  labelInput = new goog.ui.LabelInput();
    -  labelInput.createDom();
    -  labelInput.enterDocument();
    -
    -  var labelElement = labelInput.getElement();
    -  var disabledClass = goog.getCssName(labelInput.labelCssClassName, 'disabled');
    -
    -  assertTrue('label should be enabled', labelInput.isEnabled());
    -  assertFalse('label should not have the disabled class',
    -      goog.dom.classlist.contains(labelElement, disabledClass));
    -
    -  labelInput.setEnabled(false);
    -  assertFalse('label should be disabled', labelInput.isEnabled());
    -  assertTrue('label should have the disabled class',
    -      goog.dom.classlist.contains(labelElement, disabledClass));
    -
    -  labelInput.setEnabled(true);
    -  assertTrue('label should be enabled', labelInput.isEnabled());
    -  assertFalse('label should not have the disabled class',
    -      goog.dom.classlist.contains(labelElement, disabledClass));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/linkbuttonrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/linkbuttonrenderer.js
    deleted file mode 100644
    index 4f720adaaf1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/linkbuttonrenderer.js
    +++ /dev/null
    @@ -1,67 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Similiar to {@link goog.ui.FlatButtonRenderer},
    - * but underlines text instead of adds borders.
    - *
    - * For accessibility reasons, it is best to use this with a goog.ui.Button
    - * instead of an A element for links that perform actions in the page.  Links
    - * that have an href and open a new page can and should remain as A elements.
    - *
    - * @author robbyw@google.com (Robby Walker)
    - */
    -
    -goog.provide('goog.ui.LinkButtonRenderer');
    -
    -goog.require('goog.ui.Button');
    -goog.require('goog.ui.FlatButtonRenderer');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * Link renderer for {@link goog.ui.Button}s.  Link buttons can contain
    - * almost arbitrary HTML content, will flow like inline elements, but can be
    - * styled like block-level elements.
    - * @constructor
    - * @extends {goog.ui.FlatButtonRenderer}
    - */
    -goog.ui.LinkButtonRenderer = function() {
    -  goog.ui.FlatButtonRenderer.call(this);
    -};
    -goog.inherits(goog.ui.LinkButtonRenderer, goog.ui.FlatButtonRenderer);
    -goog.addSingletonGetter(goog.ui.LinkButtonRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.LinkButtonRenderer.CSS_CLASS = goog.getCssName('goog-link-button');
    -
    -
    -/** @override */
    -goog.ui.LinkButtonRenderer.prototype.getCssClass = function() {
    -  return goog.ui.LinkButtonRenderer.CSS_CLASS;
    -};
    -
    -
    -// Register a decorator factory function for Link Buttons.
    -goog.ui.registry.setDecoratorByClassName(goog.ui.LinkButtonRenderer.CSS_CLASS,
    -    function() {
    -      // Uses goog.ui.Button, but with LinkButtonRenderer.
    -      return new goog.ui.Button(null, goog.ui.LinkButtonRenderer.getInstance());
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/flashobject.js b/src/database/third_party/closure-library/closure/goog/ui/media/flashobject.js
    deleted file mode 100644
    index 6940672d3db..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/flashobject.js
    +++ /dev/null
    @@ -1,631 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Wrapper on a Flash object embedded in the HTML page.
    - * This class contains routines for writing the HTML to create the Flash object
    - * using a goog.ui.Component approach. Tested on Firefox 1.5, 2 and 3, IE6, 7,
    - * Konqueror, Chrome and Safari.
    - *
    - * Based on http://go/flashobject.js
    - *
    - * Based on the following compatibility test suite:
    - * http://www.bobbyvandersluis.com/flashembed/testsuite/
    - *
    - * TODO(user): take a look at swfobject, and maybe use it instead of the current
    - * flash embedding method.
    - *
    - * Examples of usage:
    - *
    - * <pre>
    - *   var url = goog.html.TrustedResourceUrl.fromConstant(
    - *       goog.string.Const.from('https://hostname/flash.swf'))
    - *   var flash = new goog.ui.media.FlashObject(url);
    - *   flash.setFlashVar('myvar', 'foo');
    - *   flash.render(goog.dom.getElement('parent'));
    - * </pre>
    - *
    - * TODO(user, jessan): create a goog.ui.media.BrowserInterfaceFlashObject that
    - * subclasses goog.ui.media.FlashObject to provide all the goodness of
    - * http://go/browserinterface.as
    - *
    - */
    -
    -goog.provide('goog.ui.media.FlashObject');
    -goog.provide('goog.ui.media.FlashObject.ScriptAccessLevel');
    -goog.provide('goog.ui.media.FlashObject.Wmodes');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.dom.safe');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventType');
    -goog.require('goog.html.SafeUrl');
    -goog.require('goog.html.TrustedResourceUrl');
    -goog.require('goog.html.flash');
    -goog.require('goog.html.legacyconversions');
    -goog.require('goog.log');
    -goog.require('goog.object');
    -goog.require('goog.string');
    -goog.require('goog.structs.Map');
    -goog.require('goog.style');
    -goog.require('goog.ui.Component');
    -goog.require('goog.userAgent');
    -goog.require('goog.userAgent.flash');
    -
    -
    -
    -/**
    - * A very simple flash wrapper, that allows you to create flash object
    - * programmatically, instead of embedding your own HTML. It extends
    - * {@link goog.ui.Component}, which makes it very easy to be embedded on the
    - * page.
    - *
    - * @param {string|!goog.html.TrustedResourceUrl} flashUrl The Flash SWF URL.
    - *     If possible pass a TrustedResourceUrl. string is supported
    - *     for backwards-compatibility only, uses goog.html.legacyconversions,
    - *     and will be sanitized with goog.html.SafeUrl.sanitize() before being
    - *     used.
    - * @param {goog.dom.DomHelper=} opt_domHelper An optional DomHelper.
    - * @extends {goog.ui.Component}
    - * @constructor
    - */
    -goog.ui.media.FlashObject = function(flashUrl, opt_domHelper) {
    -  goog.ui.Component.call(this, opt_domHelper);
    -
    -  var trustedResourceUrl;
    -  if (flashUrl instanceof goog.html.TrustedResourceUrl) {
    -    trustedResourceUrl = flashUrl;
    -  } else {
    -    var flashUrlSanitized =
    -        goog.html.SafeUrl.unwrap(goog.html.SafeUrl.sanitize(flashUrl));
    -    trustedResourceUrl = goog.html.legacyconversions
    -        .trustedResourceUrlFromString(flashUrlSanitized);
    -  }
    -
    -  /**
    -   * The URL of the flash movie to be embedded.
    -   *
    -   * @type {!goog.html.TrustedResourceUrl}
    -   * @private
    -   */
    -  this.flashUrl_ = trustedResourceUrl;
    -
    -  /**
    -   * An event handler used to handle events consistently between browsers.
    -   * @type {goog.events.EventHandler<!goog.ui.media.FlashObject>}
    -   * @private
    -   */
    -  this.eventHandler_ = new goog.events.EventHandler(this);
    -
    -  /**
    -   * A map of variables to be passed to the flash movie.
    -   *
    -   * @type {goog.structs.Map}
    -   * @private
    -   */
    -  this.flashVars_ = new goog.structs.Map();
    -};
    -goog.inherits(goog.ui.media.FlashObject, goog.ui.Component);
    -
    -
    -/**
    - * Different states of loaded-ness in which the SWF itself can be
    - *
    - * Talked about at:
    - * http://kb.adobe.com/selfservice/viewContent.do?externalId=tn_12059&sliceId=1
    - *
    - * @enum {number}
    - * @private
    - */
    -goog.ui.media.FlashObject.SwfReadyStates_ = {
    -  LOADING: 0,
    -  UNINITIALIZED: 1,
    -  LOADED: 2,
    -  INTERACTIVE: 3,
    -  COMPLETE: 4
    -};
    -
    -
    -/**
    - * The different modes for displaying a SWF. Note that different wmodes
    - * can result in different bugs in different browsers and also that
    - * both OPAQUE and TRANSPARENT will result in a performance hit.
    - *
    - * @enum {string}
    - */
    -goog.ui.media.FlashObject.Wmodes = {
    -  /**
    -   * Allows for z-ordering of the SWF.
    -   */
    -  OPAQUE: 'opaque',
    -
    -  /**
    -   * Allows for z-ordering of the SWF and plays the SWF with a transparent BG.
    -   */
    -  TRANSPARENT: 'transparent',
    -
    -  /**
    -   * The default wmode. Does not allow for z-ordering of the SWF.
    -   */
    -  WINDOW: 'window'
    -};
    -
    -
    -/**
    - * The different levels of allowScriptAccess.
    - *
    - * Talked about at:
    - * http://kb2.adobe.com/cps/164/tn_16494.html
    - *
    - * @enum {string}
    - */
    -goog.ui.media.FlashObject.ScriptAccessLevel = {
    -  /*
    -   * The flash object can always communicate with its container page.
    -   */
    -  ALWAYS: 'always',
    -
    -  /*
    -   * The flash object can only communicate with its container page if they are
    -   * hosted in the same domain.
    -   */
    -  SAME_DOMAIN: 'sameDomain',
    -
    -  /*
    -   * The flash can not communicate with its container page.
    -   */
    -  NEVER: 'never'
    -};
    -
    -
    -/**
    - * The component CSS namespace.
    - *
    - * @type {string}
    - */
    -goog.ui.media.FlashObject.CSS_CLASS = goog.getCssName('goog-ui-media-flash');
    -
    -
    -/**
    - * The flash object CSS class.
    - *
    - * @type {string}
    - */
    -goog.ui.media.FlashObject.FLASH_CSS_CLASS =
    -    goog.getCssName('goog-ui-media-flash-object');
    -
    -
    -/**
    - * A logger used for debugging.
    - *
    - * @type {goog.log.Logger}
    - * @private
    - */
    -goog.ui.media.FlashObject.prototype.logger_ =
    -    goog.log.getLogger('goog.ui.media.FlashObject');
    -
    -
    -/**
    - * The wmode for the SWF.
    - *
    - * @type {goog.ui.media.FlashObject.Wmodes}
    - * @private
    - */
    -goog.ui.media.FlashObject.prototype.wmode_ =
    -    goog.ui.media.FlashObject.Wmodes.WINDOW;
    -
    -
    -/**
    - * The minimum required flash version.
    - *
    - * @type {?string}
    - * @private
    - */
    -goog.ui.media.FlashObject.prototype.requiredVersion_;
    -
    -
    -/**
    - * The flash movie width.
    - *
    - * @type {string}
    - * @private
    - */
    -goog.ui.media.FlashObject.prototype.width_;
    -
    -
    -/**
    - * The flash movie height.
    - *
    - * @type {string}
    - * @private
    - */
    -goog.ui.media.FlashObject.prototype.height_;
    -
    -
    -/**
    - * The flash movie background color.
    - *
    - * @type {string}
    - * @private
    - */
    -goog.ui.media.FlashObject.prototype.backgroundColor_ = '#000000';
    -
    -
    -/**
    - * The flash movie allowScriptAccess setting.
    - *
    - * @type {string}
    - * @private
    - */
    -goog.ui.media.FlashObject.prototype.allowScriptAccess_ =
    -    goog.ui.media.FlashObject.ScriptAccessLevel.SAME_DOMAIN;
    -
    -
    -/**
    - * Sets the flash movie Wmode.
    - *
    - * @param {goog.ui.media.FlashObject.Wmodes} wmode the flash movie Wmode.
    - * @return {!goog.ui.media.FlashObject} The flash object instance for chaining.
    - */
    -goog.ui.media.FlashObject.prototype.setWmode = function(wmode) {
    -  this.wmode_ = wmode;
    -  return this;
    -};
    -
    -
    -/**
    - * @return {string} Returns the flash movie wmode.
    - */
    -goog.ui.media.FlashObject.prototype.getWmode = function() {
    -  return this.wmode_;
    -};
    -
    -
    -/**
    - * Adds flash variables.
    - *
    - * @param {goog.structs.Map|Object} map A key-value map of variables.
    - * @return {!goog.ui.media.FlashObject} The flash object instance for chaining.
    - */
    -goog.ui.media.FlashObject.prototype.addFlashVars = function(map) {
    -  this.flashVars_.addAll(map);
    -  return this;
    -};
    -
    -
    -/**
    - * Sets a flash variable.
    - *
    - * @param {string} key The name of the flash variable.
    - * @param {string} value The value of the flash variable.
    - * @return {!goog.ui.media.FlashObject} The flash object instance for chaining.
    - */
    -goog.ui.media.FlashObject.prototype.setFlashVar = function(key, value) {
    -  this.flashVars_.set(key, value);
    -  return this;
    -};
    -
    -
    -/**
    - * Sets flash variables. You can either pass a Map of key->value pairs or you
    - * can pass a key, value pair to set a specific variable.
    - *
    - * TODO(user, martino): Get rid of this method.
    - *
    - * @deprecated Use {@link #addFlashVars} or {@link #setFlashVar} instead.
    - * @param {goog.structs.Map|Object|string} flashVar A map of variables (given
    - *    as a goog.structs.Map or an Object literal) or a key to the optional
    - *    {@code opt_value}.
    - * @param {string=} opt_value The optional value for the flashVar key.
    - * @return {!goog.ui.media.FlashObject} The flash object instance for chaining.
    - */
    -goog.ui.media.FlashObject.prototype.setFlashVars = function(flashVar,
    -                                                            opt_value) {
    -  if (flashVar instanceof goog.structs.Map ||
    -      goog.typeOf(flashVar) == 'object') {
    -    this.addFlashVars(/**@type {!goog.structs.Map|!Object}*/(flashVar));
    -  } else {
    -    goog.asserts.assert(goog.isString(flashVar) && goog.isDef(opt_value),
    -        'Invalid argument(s)');
    -    this.setFlashVar(/**@type {string}*/(flashVar),
    -                     /**@type {string}*/(opt_value));
    -  }
    -  return this;
    -};
    -
    -
    -/**
    - * @return {goog.structs.Map} The current flash variables.
    - */
    -goog.ui.media.FlashObject.prototype.getFlashVars = function() {
    -  return this.flashVars_;
    -};
    -
    -
    -/**
    - * Sets the background color of the movie.
    - *
    - * @param {string} color The new color to be set.
    - * @return {!goog.ui.media.FlashObject} The flash object instance for chaining.
    - */
    -goog.ui.media.FlashObject.prototype.setBackgroundColor = function(color) {
    -  this.backgroundColor_ = color;
    -  return this;
    -};
    -
    -
    -/**
    - * @return {string} The background color of the movie.
    - */
    -goog.ui.media.FlashObject.prototype.getBackgroundColor = function() {
    -  return this.backgroundColor_;
    -};
    -
    -
    -/**
    - * Sets the allowScriptAccess setting of the movie.
    - *
    - * @param {string} value The new value to be set.
    - * @return {!goog.ui.media.FlashObject} The flash object instance for chaining.
    - */
    -goog.ui.media.FlashObject.prototype.setAllowScriptAccess = function(value) {
    -  this.allowScriptAccess_ = value;
    -  return this;
    -};
    -
    -
    -/**
    - * @return {string} The allowScriptAccess setting color of the movie.
    - */
    -goog.ui.media.FlashObject.prototype.getAllowScriptAccess = function() {
    -  return this.allowScriptAccess_;
    -};
    -
    -
    -/**
    - * Sets the width and height of the movie.
    - *
    - * @param {number|string} width The width of the movie.
    - * @param {number|string} height The height of the movie.
    - * @return {!goog.ui.media.FlashObject} The flash object instance for chaining.
    - */
    -goog.ui.media.FlashObject.prototype.setSize = function(width, height) {
    -  this.width_ = goog.isString(width) ? width : Math.round(width) + 'px';
    -  this.height_ = goog.isString(height) ? height : Math.round(height) + 'px';
    -  if (this.getElement()) {
    -    goog.style.setSize(this.getFlashElement(), this.width_, this.height_);
    -  }
    -  return this;
    -};
    -
    -
    -/**
    - * @return {?string} The flash required version.
    - */
    -goog.ui.media.FlashObject.prototype.getRequiredVersion = function() {
    -  return this.requiredVersion_;
    -};
    -
    -
    -/**
    - * Sets the minimum flash required version.
    - *
    - * @param {?string} version The minimum required version for this movie to work,
    - *     or null if you want to unset it.
    - * @return {!goog.ui.media.FlashObject} The flash object instance for chaining.
    - */
    -goog.ui.media.FlashObject.prototype.setRequiredVersion = function(version) {
    -  this.requiredVersion_ = version;
    -  return this;
    -};
    -
    -
    -/**
    - * Returns whether this SWF has a minimum required flash version.
    - *
    - * @return {boolean} Whether a required version was set or not.
    - */
    -goog.ui.media.FlashObject.prototype.hasRequiredVersion = function() {
    -  return this.requiredVersion_ != null;
    -};
    -
    -
    -/**
    - * Writes the Flash embedding {@code HTMLObjectElement} to this components root
    - * element and adds listeners for all events to handle them consistently.
    - * @override
    - */
    -goog.ui.media.FlashObject.prototype.enterDocument = function() {
    -  goog.ui.media.FlashObject.superClass_.enterDocument.call(this);
    -
    -  // The SWF tag must be written after this component's element is appended to
    -  // the DOM. Otherwise Flash's ExternalInterface is broken in IE.
    -  goog.dom.safe.setInnerHtml(
    -      /** @type {!Element} */ (this.getElement()), this.createSwfTag_());
    -  if (this.width_ && this.height_) {
    -    this.setSize(this.width_, this.height_);
    -  }
    -
    -  // Sinks all the events on the bubble phase.
    -  //
    -  // Flash plugins propagates events from/to the plugin to the browser
    -  // inconsistently:
    -  //
    -  // 1) FF2 + linux: the flash plugin will stop the propagation of all events
    -  // from the plugin to the browser.
    -  // 2) FF3 + mac: the flash plugin will propagate events on the <embed> object
    -  // but that will get propagated to its parents.
    -  // 3) Safari 3.1.1 + mac: the flash plugin will propagate the event to the
    -  // <object> tag that event will propagate to its parents.
    -  // 4) IE7 + windows: the flash plugin  will eat all events, not propagating
    -  // anything to the javascript.
    -  // 5) Chrome + windows: the flash plugin will eat all events, not propagating
    -  // anything to the javascript.
    -  //
    -  // To overcome this inconsistency, all events from/to the plugin are sinked,
    -  // since you can't assume that the events will be propagated.
    -  //
    -  // NOTE(user): we only sink events on the bubbling phase, since there are no
    -  // inexpensive/scalable way to stop events on the capturing phase unless we
    -  // added an event listener on the document for each flash object.
    -  this.eventHandler_.listen(
    -      this.getElement(),
    -      goog.object.getValues(goog.events.EventType),
    -      goog.events.Event.stopPropagation);
    -};
    -
    -
    -/**
    - * Creates the DOM structure.
    - *
    - * @override
    - */
    -goog.ui.media.FlashObject.prototype.createDom = function() {
    -  if (this.hasRequiredVersion() &&
    -      !goog.userAgent.flash.isVersion(
    -          /** @type {string} */ (this.getRequiredVersion()))) {
    -    goog.log.warning(this.logger_, 'Required flash version not found:' +
    -        this.getRequiredVersion());
    -    throw Error(goog.ui.Component.Error.NOT_SUPPORTED);
    -  }
    -
    -  var element = this.getDomHelper().createElement('div');
    -  element.className = goog.ui.media.FlashObject.CSS_CLASS;
    -  this.setElementInternal(element);
    -};
    -
    -
    -/**
    - * Creates the HTML to embed the flash object.
    - *
    - * @return {!goog.html.SafeHtml} Browser appropriate HTML to add the SWF to the
    - *     DOM.
    - * @private
    - */
    -goog.ui.media.FlashObject.prototype.createSwfTag_ = function() {
    -  var keys = this.flashVars_.getKeys();
    -  var values = this.flashVars_.getValues();
    -  var flashVars = [];
    -  for (var i = 0; i < keys.length; i++) {
    -    var key = goog.string.urlEncode(keys[i]);
    -    var value = goog.string.urlEncode(values[i]);
    -    flashVars.push(key + '=' + value);
    -  }
    -  var flashVarsString = flashVars.join('&');
    -  if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(11)) {
    -    return this.createSwfTagOldIe_(flashVarsString);
    -  } else {
    -    return this.createSwfTagModern_(flashVarsString);
    -  }
    -};
    -
    -
    -/**
    - * Creates the HTML to embed the flash object for IE>=11 and other browsers.
    - *
    - * @param {string} flashVars The value of the FlashVars attribute.
    - * @return {!goog.html.SafeHtml} Browser appropriate HTML to add the SWF to the
    - *     DOM.
    - * @private
    - */
    -goog.ui.media.FlashObject.prototype.createSwfTagModern_ = function(flashVars) {
    -  return goog.html.flash.createEmbed(
    -      this.flashUrl_,
    -      {
    -        'AllowScriptAccess': this.allowScriptAccess_,
    -        'allowFullScreen': 'true',
    -        'allowNetworking': 'all',
    -        'bgcolor': this.backgroundColor_,
    -        'class': goog.ui.media.FlashObject.FLASH_CSS_CLASS,
    -        'FlashVars': flashVars,
    -        'id': this.getId(),
    -        'name': this.getId(),
    -        'quality': 'high',
    -        'SeamlessTabbing': 'false',
    -        'wmode': this.wmode_
    -      });
    -};
    -
    -
    -/**
    - * Creates the HTML to embed the flash object for IE<11.
    - *
    - * @param {string} flashVars The value of the FlashVars attribute.
    - * @return {!goog.html.SafeHtml} Browser appropriate HTML to add the SWF to the
    - *     DOM.
    - * @private
    - */
    -goog.ui.media.FlashObject.prototype.createSwfTagOldIe_ = function(flashVars) {
    -  return goog.html.flash.createObjectForOldIe(
    -      this.flashUrl_,
    -      {
    -        'allowFullScreen': 'true',
    -        'AllowScriptAccess': this.allowScriptAccess_,
    -        'allowNetworking': 'all',
    -        'bgcolor': this.backgroundColor_,
    -        'FlashVars': flashVars,
    -        'quality': 'high',
    -        'SeamlessTabbing': 'false',
    -        'wmode': this.wmode_
    -      },
    -      {
    -        'class': goog.ui.media.FlashObject.FLASH_CSS_CLASS,
    -        'id': this.getId(),
    -        'name': this.getId()
    -      });
    -};
    -
    -
    -/**
    - * @return {HTMLObjectElement} The flash element or null if the element can't
    - *     be found.
    - */
    -goog.ui.media.FlashObject.prototype.getFlashElement = function() {
    -  return /** @type {HTMLObjectElement} */(this.getElement() ?
    -      this.getElement().firstChild : null);
    -};
    -
    -
    -/** @override */
    -goog.ui.media.FlashObject.prototype.disposeInternal = function() {
    -  goog.ui.media.FlashObject.superClass_.disposeInternal.call(this);
    -  this.flashVars_ = null;
    -
    -  this.eventHandler_.dispose();
    -  this.eventHandler_ = null;
    -};
    -
    -
    -/**
    - * @return {boolean} whether the SWF has finished loading or not.
    - */
    -goog.ui.media.FlashObject.prototype.isLoaded = function() {
    -  if (!this.isInDocument() || !this.getElement()) {
    -    return false;
    -  }
    -
    -  if (this.getFlashElement().readyState &&
    -      this.getFlashElement().readyState ==
    -          goog.ui.media.FlashObject.SwfReadyStates_.COMPLETE) {
    -    return true;
    -  }
    -
    -  if (this.getFlashElement().PercentLoaded &&
    -      this.getFlashElement().PercentLoaded() == 100) {
    -    return true;
    -  }
    -
    -  return false;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/flashobject_test.html b/src/database/third_party/closure-library/closure/goog/ui/media/flashobject_test.html
    deleted file mode 100644
    index 0a548c6cb10..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/flashobject_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.media.FlashObject
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.ui.media.FlashObjectTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/flashobject_test.js b/src/database/third_party/closure-library/closure/goog/ui/media/flashobject_test.js
    deleted file mode 100644
    index b7fb0fcacb3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/flashobject_test.js
    +++ /dev/null
    @@ -1,347 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.media.FlashObjectTest');
    -goog.setTestOnly('goog.ui.media.FlashObjectTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.DomHelper');
    -goog.require('goog.events');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventType');
    -goog.require('goog.html.SafeUrl');
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.media.FlashObject');
    -goog.require('goog.userAgent');
    -
    -
    -var FLASH_URL = 'http://www.youtube.com/v/RbI7cCp0v6w&hl=en&fs=1';
    -var control = new goog.testing.MockControl();
    -var domHelper = control.createLooseMock(goog.dom.DomHelper);
    -// TODO(user): mocking window.document throws exceptions in FF2. find out how
    -// to mock it.
    -var documentHelper = {body: control.createLooseMock(goog.dom.DomHelper)};
    -var element = goog.dom.createElement('div');
    -
    -function setUp() {
    -  control.$resetAll();
    -  domHelper.getDocument().$returns(documentHelper).$anyTimes();
    -  domHelper.createElement('div').$returns(element).$anyTimes();
    -  documentHelper.body.appendChild(element).$anyTimes();
    -}
    -
    -function tearDown() {
    -  control.$verifyAll();
    -}
    -
    -function getFlashVarsFromElement(flash) {
    -  var el = flash.getFlashElement();
    -
    -  // This should work in everything except IE:
    -  if (el.hasAttribute && el.hasAttribute('flashvars'))
    -    return el.getAttribute('flashvars');
    -
    -  // For IE: find and return the value of the correct param element:
    -  el = el.firstChild;
    -  while (el) {
    -    if (el.name == 'FlashVars') {
    -      return el.value;
    -    }
    -    el = el.nextSibling;
    -  }
    -  return '';
    -}
    -
    -function testInstantiationAndRendering() {
    -  control.$replayAll();
    -
    -  var flash = new goog.ui.media.FlashObject(FLASH_URL, domHelper);
    -  flash.render();
    -  flash.dispose();
    -}
    -
    -function testRenderedWithCorrectAttributes() {
    -  if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(11)) {
    -    return;
    -  }
    -
    -  control.$replayAll();
    -
    -  var flash = new goog.ui.media.FlashObject(FLASH_URL, domHelper);
    -  flash.setAllowScriptAccess('allowScriptAccess');
    -  flash.setBackgroundColor('backgroundColor');
    -  flash.setId('id');
    -  flash.setFlashVars({'k1': 'v1', 'k2': 'v2'});
    -  flash.setWmode('wmode');
    -  flash.render();
    -
    -  var el = flash.getFlashElement();
    -  assertEquals('true', el.getAttribute('allowFullScreen'));
    -  assertEquals('all', el.getAttribute('allowNetworking'));
    -  assertEquals('allowScriptAccess', el.getAttribute('allowScriptAccess'));
    -  assertEquals(
    -      goog.ui.media.FlashObject.FLASH_CSS_CLASS, el.getAttribute('class'));
    -  assertEquals('k1=v1&k2=v2', el.getAttribute('FlashVars'));
    -  assertEquals('id', el.getAttribute('id'));
    -  assertEquals('id', el.getAttribute('name'));
    -  assertEquals('https://www.macromedia.com/go/getflashplayer',
    -      el.getAttribute('pluginspage'));
    -  assertEquals('high', el.getAttribute('quality'));
    -  assertEquals('false', el.getAttribute('SeamlessTabbing'));
    -  assertEquals(FLASH_URL, el.getAttribute('src'));
    -  assertEquals('application/x-shockwave-flash',
    -      el.getAttribute('type'));
    -  assertEquals('wmode', el.getAttribute('wmode'));
    -}
    -
    -function testRenderedWithCorrectAttributesOldIe() {
    -  if (!goog.userAgent.IE || goog.userAgent.isDocumentModeOrHigher(11)) {
    -    return;
    -  }
    -
    -  control.$replayAll();
    -
    -  var flash = new goog.ui.media.FlashObject(FLASH_URL, domHelper);
    -  flash.setAllowScriptAccess('allowScriptAccess');
    -  flash.setBackgroundColor('backgroundColor');
    -  flash.setId('id');
    -  flash.setFlashVars({'k1': 'v1', 'k2': 'v2'});
    -  flash.setWmode('wmode');
    -  flash.render();
    -
    -  var el = flash.getFlashElement();
    -  assertEquals('class',
    -      goog.ui.media.FlashObject.FLASH_CSS_CLASS, el.getAttribute('class'));
    -  assertEquals('clsid:d27cdb6e-ae6d-11cf-96b8-444553540000',
    -      el.getAttribute('classid'));
    -  assertEquals('id', 'id', el.getAttribute('id'));
    -  assertEquals('name', 'id', el.getAttribute('name'));
    -
    -  assertContainsParam(el, 'allowFullScreen', 'true');
    -  assertContainsParam(el, 'allowNetworking', 'all');
    -  assertContainsParam(el, 'AllowScriptAccess', 'allowScriptAccess');
    -  assertContainsParam(el, 'bgcolor', 'backgroundColor');
    -  assertContainsParam(el, 'FlashVars', 'FlashVars');
    -  assertContainsParam(el, 'movie', FLASH_URL);
    -  assertContainsParam(el, 'quality', 'high');
    -  assertContainsParam(el, 'SeamlessTabbing', 'false');
    -  assertContainsParam(el, 'wmode', 'wmode');
    -
    -}
    -
    -function testUrlIsSanitized() {
    -  if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(11)) {
    -    return;
    -  }
    -
    -  control.$replayAll();
    -
    -  var flash = new goog.ui.media.FlashObject('javascript:evil', domHelper);
    -  flash.render();
    -  var el = flash.getFlashElement();
    -
    -  assertEquals(goog.html.SafeUrl.INNOCUOUS_STRING, el.getAttribute('src'));
    -}
    -
    -function testUrlIsSanitizedOldIe() {
    -  if (!goog.userAgent.IE || goog.userAgent.isDocumentModeOrHigher(11)) {
    -    return;
    -  }
    -
    -  control.$replayAll();
    -
    -  var flash = new goog.ui.media.FlashObject('javascript:evil', domHelper);
    -  flash.render();
    -  var el = flash.getFlashElement();
    -
    -  assertContainsParam(el, 'movie', goog.html.SafeUrl.INNOCUOUS_STRING);
    -}
    -
    -function assertContainsParam(element, expectedName, expectedValue) {
    -  var failureMsg = 'Expected param with name \"' + expectedName +
    -      '\" and value \"' + expectedValue + '\". Not found in child nodes: ' +
    -      element.innerHTML;
    -  for (var i = 0; i < element.childNodes.length; i++) {
    -    var child = element.childNodes[i];
    -    var name = child.getAttribute('name');
    -    if (name === expectedName) {
    -      if (!child.getAttribute('value') === expectedValue) {
    -        fail(failureMsg);
    -      }
    -      return;
    -    }
    -  }
    -  fail(failureMsg);
    -}
    -
    -function testSetFlashVar() {
    -  control.$replayAll();
    -
    -  var flash = new goog.ui.media.FlashObject(FLASH_URL, domHelper);
    -
    -  assertTrue(flash.getFlashVars().isEmpty());
    -  flash.setFlashVar('foo', 'bar');
    -  flash.setFlashVar('hello', 'world');
    -  assertFalse(flash.getFlashVars().isEmpty());
    -
    -  flash.render();
    -
    -  assertEquals('foo=bar&hello=world', getFlashVarsFromElement(flash));
    -  flash.dispose();
    -}
    -
    -function testAddFlashVars() {
    -  control.$replayAll();
    -
    -  var flash = new goog.ui.media.FlashObject(FLASH_URL, domHelper);
    -
    -  assertTrue(flash.getFlashVars().isEmpty());
    -  flash.addFlashVars({
    -    'using': 'an',
    -    'object': 'literal'
    -  });
    -  assertFalse(flash.getFlashVars().isEmpty());
    -
    -  flash.render();
    -
    -  assertEquals('using=an&object=literal', getFlashVarsFromElement(flash));
    -  flash.dispose();
    -}
    -
    -
    -/**
    - * @deprecated Remove once setFlashVars is removed.
    - */
    -function testSetFlashVarsUsingFalseAsTheValue() {
    -  control.$replayAll();
    -
    -  var flash = new goog.ui.media.FlashObject(FLASH_URL, domHelper);
    -
    -  assertTrue(flash.getFlashVars().isEmpty());
    -  flash.setFlashVars('beEvil', false);
    -  assertFalse(flash.getFlashVars().isEmpty());
    -
    -  flash.render();
    -
    -  assertEquals('beEvil=false', getFlashVarsFromElement(flash));
    -  flash.dispose();
    -}
    -
    -
    -/**
    - * @deprecated Remove once setFlashVars is removed.
    - */
    -function testSetFlashVarsWithWrongArgument() {
    -  control.$replayAll();
    -
    -  assertThrows(function() {
    -    var flash = new goog.ui.media.FlashObject(FLASH_URL, domHelper);
    -    flash.setFlashVars('foo=bar');
    -    flash.dispose();
    -  });
    -}
    -
    -function testSetFlashVarUrlEncoding() {
    -  control.$replayAll();
    -
    -  var flash = new goog.ui.media.FlashObject(FLASH_URL, domHelper);
    -  flash.setFlashVar('foo', 'bar and some extra spaces');
    -  flash.render();
    -  assertEquals('foo=bar%20and%20some%20extra%20spaces',
    -      getFlashVarsFromElement(flash));
    -  flash.dispose();
    -}
    -
    -function testThrowsRequiredVersionOfFlashNotAvailable() {
    -  control.$replayAll();
    -
    -  var flash = new goog.ui.media.FlashObject(FLASH_URL, domHelper);
    -  flash.setRequiredVersion('999.999.999');
    -
    -  assertTrue(flash.hasRequiredVersion());
    -
    -  assertThrows(function() {
    -    flash.render();
    -  });
    -
    -  flash.dispose();
    -}
    -
    -function testIsLoadedAfterDispose() {
    -  control.$replayAll();
    -
    -  var flash = new goog.ui.media.FlashObject(FLASH_URL, domHelper);
    -  flash.render();
    -  // TODO(user): find out a way to test the loadness of flash movies on
    -  // asynchronous tests. if debugger; is left here, the test pass. if removed
    -  // the test fails. that happens because flash needs some time to be
    -  // considered loaded, after flash.render() is called (like img.src i guess).
    -  //debugger;
    -  //assertTrue(flash.isLoaded());
    -  flash.dispose();
    -  assertFalse(flash.isLoaded());
    -}
    -
    -function testXssAttacks() {
    -  control.$replayAll();
    -
    -  called = false;
    -  var injection = '' +
    -      '">' +
    -      '</embed>' +
    -      '<script>called = true; // evil arbitrary js injected here<\/script>' +
    -      '<embed src=""';
    -  var flash = new goog.ui.media.FlashObject(injection, domHelper);
    -  flash.render();
    -  // Makes sure FlashObject html escapes user input.
    -  // NOTE(user): this test fails if the URL is not HTML escaped, showing that
    -  // html escaping is necessary to avoid attacks.
    -  assertFalse(called);
    -}
    -
    -function testPropagatesEventsConsistently() {
    -  var event = control.createLooseMock(goog.events.Event);
    -
    -  // we expect any event to have its propagation stopped.
    -  event.stopPropagation();
    -
    -  control.$replayAll();
    -
    -  var flash = new goog.ui.media.FlashObject(FLASH_URL, domHelper);
    -  flash.render();
    -  event.target = flash.getElement();
    -  event.type = goog.events.EventType.CLICK;
    -  goog.testing.events.fireBrowserEvent(event);
    -  flash.dispose();
    -}
    -
    -function testEventsGetsSinked() {
    -  var called = false;
    -  var flash = new goog.ui.media.FlashObject(FLASH_URL);
    -  var parent = goog.dom.createElement('div');
    -  flash.render(parent);
    -
    -  goog.events.listen(parent, goog.events.EventType.CLICK, function(e) {
    -    called = true;
    -  });
    -
    -  assertFalse(called);
    -
    -  goog.testing.events.fireClickSequence(flash.getElement());
    -
    -  assertFalse(called);
    -  flash.dispose();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/flickr.js b/src/database/third_party/closure-library/closure/goog/ui/media/flickr.js
    deleted file mode 100644
    index b34755a4e4a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/flickr.js
    +++ /dev/null
    @@ -1,314 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview provides a reusable FlickrSet photo UI component given a public
    - * FlickrSetModel.
    - *
    - * goog.ui.media.FlickrSet is actually a {@link goog.ui.ControlRenderer}, a
    - * stateless class - that could/should be used as a Singleton with the static
    - * method {@code goog.ui.media.FlickrSet.getInstance} -, that knows how to
    - * render Flickr sets. It is designed to be used with a {@link goog.ui.Control},
    - * which will actually control the media renderer and provide the
    - * {@link goog.ui.Component} base. This design guarantees that all different
    - * types of medias will behave alike but will look different.
    - *
    - * goog.ui.media.FlickrSet expects a {@code goog.ui.media.FlickrSetModel} on
    - * {@code goog.ui.Control.getModel} as data models, and renders a flash object
    - * that will show the contents of that set.
    - *
    - * Example of usage:
    - *
    - * <pre>
    - *   var flickrSet = goog.ui.media.FlickrSetModel.newInstance(flickrSetUrl);
    - *   goog.ui.media.FlickrSet.newControl(flickrSet).render();
    - * </pre>
    - *
    - * FlickrSet medias currently support the following states:
    - *
    - * <ul>
    - *   <li> {@link goog.ui.Component.State.DISABLED}: shows 'flash not available'
    - *   <li> {@link goog.ui.Component.State.HOVER}: mouse cursor is over the video
    - *   <li> {@link goog.ui.Component.State.SELECTED}: flash video is shown
    - * </ul>
    - *
    - * Which can be accessed by
    - * <pre>
    - *   video.setEnabled(true);
    - *   video.setHighlighted(true);
    - *   video.setSelected(true);
    - * </pre>
    - *
    - *
    - * @supported IE6, FF2+, Safari. Requires flash to actually work.
    - *
    - * TODO(user): Support non flash users. Maybe show a link to the Flick set,
    - * or fetch the data and rendering it using javascript (instead of a broken
    - * 'You need to install flash' message).
    - */
    -
    -goog.provide('goog.ui.media.FlickrSet');
    -goog.provide('goog.ui.media.FlickrSetModel');
    -
    -goog.require('goog.html.TrustedResourceUrl');
    -goog.require('goog.string.Const');
    -goog.require('goog.ui.media.FlashObject');
    -goog.require('goog.ui.media.Media');
    -goog.require('goog.ui.media.MediaModel');
    -goog.require('goog.ui.media.MediaRenderer');
    -
    -
    -
    -/**
    - * Subclasses a goog.ui.media.MediaRenderer to provide a FlickrSet specific
    - * media renderer.
    - *
    - * This class knows how to parse FlickrSet URLs, and render the DOM structure
    - * of flickr set players. This class is meant to be used as a singleton static
    - * stateless class, that takes {@code goog.ui.media.Media} instances and renders
    - * it. It expects {@code goog.ui.media.Media.getModel} to return a well formed,
    - * previously constructed, set id {@see goog.ui.media.FlickrSet.parseUrl},
    - * which is the data model this renderer will use to construct the DOM
    - * structure. {@see goog.ui.media.FlickrSet.newControl} for a example of
    - * constructing a control with this renderer.
    - *
    - * This design is patterned after
    - * http://go/closure_control_subclassing
    - *
    - * It uses {@link goog.ui.media.FlashObject} to embed the flash object.
    - *
    - * @constructor
    - * @extends {goog.ui.media.MediaRenderer}
    - * @final
    - */
    -goog.ui.media.FlickrSet = function() {
    -  goog.ui.media.MediaRenderer.call(this);
    -};
    -goog.inherits(goog.ui.media.FlickrSet, goog.ui.media.MediaRenderer);
    -goog.addSingletonGetter(goog.ui.media.FlickrSet);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - *
    - * @type {string}
    - */
    -goog.ui.media.FlickrSet.CSS_CLASS = goog.getCssName('goog-ui-media-flickrset');
    -
    -
    -/**
    - * Flash player URL. Uses Flickr's flash player by default.
    - *
    - * @type {!goog.html.TrustedResourceUrl}
    - * @private
    - */
    -goog.ui.media.FlickrSet.flashUrl_ = goog.html.TrustedResourceUrl.fromConstant(
    -    goog.string.Const.from(
    -        'http://www.flickr.com/apps/slideshow/show.swf?v=63961'));
    -
    -
    -/**
    - * A static convenient method to construct a goog.ui.media.Media control out of
    - * a FlickrSet URL. It extracts the set id information on the URL, sets it
    - * as the data model goog.ui.media.FlickrSet renderer uses, sets the states
    - * supported by the renderer, and returns a Control that binds everything
    - * together. This is what you should be using for constructing FlickrSet videos,
    - * except if you need more fine control over the configuration.
    - *
    - * @param {goog.ui.media.FlickrSetModel} dataModel The Flickr Set data model.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @return {!goog.ui.media.Media} A Control binded to the FlickrSet renderer.
    - * @throws exception in case {@code flickrSetUrl} is an invalid flickr set URL.
    - * TODO(user): use {@link goog.ui.media.MediaModel} once it is checked in.
    - */
    -goog.ui.media.FlickrSet.newControl = function(dataModel, opt_domHelper) {
    -  var control = new goog.ui.media.Media(
    -      dataModel, goog.ui.media.FlickrSet.getInstance(), opt_domHelper);
    -  control.setSelected(true);
    -  return control;
    -};
    -
    -
    -/**
    - * A static method that sets which flash URL this class should use. Use this if
    - * you want to host your own flash flickr player.
    - *
    - * @param {!goog.html.TrustedResourceUrl} flashUrl The URL of the flash flickr
    - *     player.
    - */
    -goog.ui.media.FlickrSet.setFlashUrl = function(flashUrl) {
    -  goog.ui.media.FlickrSet.flashUrl_ = flashUrl;
    -};
    -
    -
    -/**
    - * Creates the initial DOM structure of the flickr set, which is basically a
    - * the flash object pointing to a flickr set player.
    - *
    - * @param {goog.ui.Control} c The media control.
    - * @return {!Element} The DOM structure that represents this control.
    - * @override
    - */
    -goog.ui.media.FlickrSet.prototype.createDom = function(c) {
    -  var control = /** @type {goog.ui.media.Media} */ (c);
    -  var div = goog.ui.media.FlickrSet.superClass_.createDom.call(this, control);
    -
    -  var model =
    -      /** @type {goog.ui.media.FlickrSetModel} */ (control.getDataModel());
    -
    -  // TODO(user): find out what is the policy about hosting this SWF. figure out
    -  // if it works over https.
    -  var flash = new goog.ui.media.FlashObject(
    -      model.getPlayer().getTrustedResourceUrl(),
    -      control.getDomHelper());
    -  flash.addFlashVars(model.getPlayer().getVars());
    -  flash.render(div);
    -
    -  return div;
    -};
    -
    -
    -/**
    - * Returns the CSS class to be applied to the root element of components
    - * rendered using this renderer.
    - * @return {string} Renderer-specific CSS class.
    - * @override
    - */
    -goog.ui.media.FlickrSet.prototype.getCssClass = function() {
    -  return goog.ui.media.FlickrSet.CSS_CLASS;
    -};
    -
    -
    -
    -/**
    - * The {@code goog.ui.media.FlickrAlbum} media data model. It stores a required
    - * {@code userId} and {@code setId} fields, sets the flickr Set URL, and
    - * allows a few optional parameters.
    - *
    - * @param {string} userId The flickr userId associated with this set.
    - * @param {string} setId The flickr setId associated with this set.
    - * @param {string=} opt_caption An optional caption of the flickr set.
    - * @param {string=} opt_description An optional description of the flickr set.
    - * @constructor
    - * @extends {goog.ui.media.MediaModel}
    - * @final
    - */
    -goog.ui.media.FlickrSetModel = function(userId,
    -                                        setId,
    -                                        opt_caption,
    -                                        opt_description) {
    -  goog.ui.media.MediaModel.call(
    -      this,
    -      goog.ui.media.FlickrSetModel.buildUrl(userId, setId),
    -      opt_caption,
    -      opt_description,
    -      goog.ui.media.MediaModel.MimeType.FLASH);
    -
    -  /**
    -   * The Flickr user id.
    -   * @type {string}
    -   * @private
    -   */
    -  this.userId_ = userId;
    -
    -  /**
    -   * The Flickr set id.
    -   * @type {string}
    -   * @private
    -   */
    -  this.setId_ = setId;
    -
    -  var flashVars = {
    -    'offsite': 'true',
    -    'lang': 'en',
    -    'page_show_url': '/photos/' + userId + '/sets/' + setId + '/show/',
    -    'page_show_back_url': '/photos/' + userId + '/sets/' + setId,
    -    'set_id': setId
    -  };
    -
    -  var player = new goog.ui.media.MediaModel.Player(
    -      goog.ui.media.FlickrSet.flashUrl_, flashVars);
    -
    -  this.setPlayer(player);
    -};
    -goog.inherits(goog.ui.media.FlickrSetModel, goog.ui.media.MediaModel);
    -
    -
    -/**
    - * Regular expression used to extract the username and set id out of the flickr
    - * URLs.
    - *
    - * Copied from http://go/markdownlite.js and {@link FlickrExtractor.xml}.
    - *
    - * @type {RegExp}
    - * @private
    - * @const
    - */
    -goog.ui.media.FlickrSetModel.MATCHER_ =
    -    /(?:http:\/\/)?(?:www\.)?flickr\.com\/(?:photos\/([\d\w@\-]+)\/sets\/(\d+))\/?/i;
    -
    -
    -/**
    - * Takes a {@code flickrSetUrl} and extracts the flickr username and set id.
    - *
    - * @param {string} flickrSetUrl A Flickr set URL.
    - * @param {string=} opt_caption An optional caption of the flickr set.
    - * @param {string=} opt_description An optional description of the flickr set.
    - * @return {!goog.ui.media.FlickrSetModel} The data model that represents the
    - *     Flickr set.
    - * @throws exception in case the parsing fails
    - */
    -goog.ui.media.FlickrSetModel.newInstance = function(flickrSetUrl,
    -                                                    opt_caption,
    -                                                    opt_description) {
    -  if (goog.ui.media.FlickrSetModel.MATCHER_.test(flickrSetUrl)) {
    -    var data = goog.ui.media.FlickrSetModel.MATCHER_.exec(flickrSetUrl);
    -    return new goog.ui.media.FlickrSetModel(
    -        data[1], data[2], opt_caption, opt_description);
    -  }
    -  throw Error('failed to parse flickr url: ' + flickrSetUrl);
    -};
    -
    -
    -/**
    - * Takes a flickr username and set id and returns an URL.
    - *
    - * @param {string} userId The owner of the set.
    - * @param {string} setId The set id.
    - * @return {string} The URL of the set.
    - */
    -goog.ui.media.FlickrSetModel.buildUrl = function(userId, setId) {
    -  return 'http://flickr.com/photos/' + userId + '/sets/' + setId;
    -};
    -
    -
    -/**
    - * Gets the Flickr user id.
    - * @return {string} The Flickr user id.
    - */
    -goog.ui.media.FlickrSetModel.prototype.getUserId = function() {
    -  return this.userId_;
    -};
    -
    -
    -/**
    - * Gets the Flickr set id.
    - * @return {string} The Flickr set id.
    - */
    -goog.ui.media.FlickrSetModel.prototype.getSetId = function() {
    -  return this.setId_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/flickr_test.html b/src/database/third_party/closure-library/closure/goog/ui/media/flickr_test.html
    deleted file mode 100644
    index daa388c1730..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/flickr_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.media.FlickrSet
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.ui.media.FlickrSetTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/flickr_test.js b/src/database/third_party/closure-library/closure/goog/ui/media/flickr_test.js
    deleted file mode 100644
    index abe6393245b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/flickr_test.js
    +++ /dev/null
    @@ -1,106 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.media.FlickrSetTest');
    -goog.setTestOnly('goog.ui.media.FlickrSetTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.html.testing');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.media.FlashObject');
    -goog.require('goog.ui.media.FlickrSet');
    -goog.require('goog.ui.media.FlickrSetModel');
    -goog.require('goog.ui.media.Media');
    -var flickr;
    -var control;
    -var FLICKR_USER = 'ingawalker';
    -var FLICKR_SET = '72057594102831547';
    -var FLICKRSET_URL =
    -    'http://flickr.com/photos/' + FLICKR_USER + '/sets/' + FLICKR_SET;
    -var parent = goog.dom.createElement('div');
    -
    -function setUp() {
    -  flickr = new goog.ui.media.FlickrSet();
    -  var set = new goog.ui.media.FlickrSetModel(FLICKR_USER, FLICKR_SET,
    -      'caption');
    -  control = new goog.ui.media.Media(set, flickr);
    -}
    -
    -function tearDown() {
    -  control.dispose();
    -}
    -
    -function testBasicRendering() {
    -  control.render(parent);
    -  var el = goog.dom.getElementsByTagNameAndClass(
    -      'div', goog.ui.media.FlickrSet.CSS_CLASS, parent);
    -  assertEquals(1, el.length);
    -  assertEquals(FLICKRSET_URL, control.getDataModel().getUrl());
    -}
    -
    -function testParsingUrl() {
    -  assertExtractsCorrectly(FLICKR_USER, FLICKR_SET, FLICKRSET_URL);
    -  // user id with @ sign
    -  assertExtractsCorrectly('30441750@N06', '7215760789302468',
    -      'http://flickr.com/photos/30441750@N06/sets/7215760789302468/');
    -  // user id with - sign
    -  assertExtractsCorrectly('30441750-N06', '7215760789302468',
    -      'http://flickr.com/photos/30441750-N06/sets/7215760789302468/');
    -
    -  var invalidUrl = 'http://invalidUrl/filename.doc';
    -  var e = assertThrows('', function() {
    -    goog.ui.media.FlickrSetModel.newInstance(invalidUrl);
    -  });
    -  assertEquals('failed to parse flickr url: ' + invalidUrl, e.message);
    -}
    -
    -function testBuildingUrl() {
    -  assertEquals(FLICKRSET_URL,
    -      goog.ui.media.FlickrSetModel.buildUrl(
    -          FLICKR_USER, FLICKR_SET, FLICKRSET_URL));
    -}
    -
    -function testCreatingModel() {
    -  var model = new goog.ui.media.FlickrSetModel(FLICKR_USER, FLICKR_SET);
    -  assertEquals(FLICKR_USER, model.getUserId());
    -  assertEquals(FLICKR_SET, model.getSetId());
    -  assertEquals(FLICKRSET_URL, model.getUrl());
    -  assertUndefined(model.getCaption());
    -}
    -
    -function testSettingWhichFlashUrlToUse() {
    -  goog.ui.media.FlickrSet.setFlashUrl(
    -      goog.html.testing.newTrustedResourceUrlForTest('http://foo'));
    -  assertEquals('http://foo',
    -      goog.ui.media.FlickrSet.flashUrl_.getTypedStringValue());
    -}
    -
    -function testCreatingDomOnInitialState() {
    -  control.render(parent);
    -  var caption = goog.dom.getElementsByTagNameAndClass(
    -      'div',
    -      goog.ui.media.FlickrSet.CSS_CLASS + '-caption',
    -      parent);
    -  assertEquals(1, caption.length);
    -
    -  var flash = goog.dom.getElementsByTagNameAndClass(
    -      'div', goog.ui.media.FlashObject.CSS_CLASS, parent);
    -  assertEquals(1, flash.length);
    -}
    -
    -function assertExtractsCorrectly(expectedUserId, expectedSetId, url) {
    -  var flickr = goog.ui.media.FlickrSetModel.newInstance(url);
    -  assertEquals('userId for ' + url, expectedUserId, flickr.getUserId());
    -  assertEquals('setId for ' + url, expectedSetId, flickr.getSetId());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/googlevideo.js b/src/database/third_party/closure-library/closure/goog/ui/media/googlevideo.js
    deleted file mode 100644
    index 10cc4c90a8a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/googlevideo.js
    +++ /dev/null
    @@ -1,283 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview provides a reusable GoogleVideo UI component given a public
    - * GoogleVideo video URL.
    - *
    - * goog.ui.media.GoogleVideo is actually a {@link goog.ui.ControlRenderer}, a
    - * stateless class - that could/should be used as a Singleton with the static
    - * method {@code goog.ui.media.GoogleVideo.getInstance} -, that knows how to
    - * render GoogleVideo videos. It is designed to be used with a
    - * {@link goog.ui.Control}, which will actually control the media renderer and
    - * provide the {@link goog.ui.Component} base. This design guarantees that all
    - * different types of medias will behave alike but will look different.
    - *
    - * goog.ui.media.GoogleVideo expects {@code goog.ui.media.GoogleVideoModel} on
    - * {@code goog.ui.Control.getModel} as data models, and renders a flash object
    - * that will show the contents of that video.
    - *
    - * Example of usage:
    - *
    - * <pre>
    - *   var video = goog.ui.media.GoogleVideoModel.newInstance(
    - *       'http://video.google.com/videoplay?docid=6698933542780842398');
    - *   goog.ui.media.GoogleVideo.newControl(video).render();
    - * </pre>
    - *
    - * GoogleVideo medias currently support the following states:
    - *
    - * <ul>
    - *   <li> {@link goog.ui.Component.State.DISABLED}: shows 'flash not available'
    - *   <li> {@link goog.ui.Component.State.HOVER}: mouse cursor is over the video
    - *   <li> {@link goog.ui.Component.State.SELECTED}: flash video is shown
    - * </ul>
    - *
    - * Which can be accessed by
    - * <pre>
    - *   video.setEnabled(true);
    - *   video.setHighlighted(true);
    - *   video.setSelected(true);
    - * </pre>
    - *
    - *
    - * @supported IE6+, FF2+, Chrome, Safari. Requires flash to actually work.
    - */
    -
    -
    -goog.provide('goog.ui.media.GoogleVideo');
    -goog.provide('goog.ui.media.GoogleVideoModel');
    -
    -goog.require('goog.string');
    -goog.require('goog.ui.media.FlashObject');
    -goog.require('goog.ui.media.Media');
    -goog.require('goog.ui.media.MediaModel');
    -goog.require('goog.ui.media.MediaRenderer');
    -
    -
    -
    -/**
    - * Subclasses a goog.ui.media.MediaRenderer to provide a GoogleVideo specific
    - * media renderer.
    - *
    - * This class knows how to parse GoogleVideo URLs, and render the DOM structure
    - * of GoogleVideo video players. This class is meant to be used as a singleton
    - * static stateless class, that takes {@code goog.ui.media.Media} instances and
    - * renders it. It expects {@code goog.ui.media.Media.getModel} to return a well
    - * formed, previously constructed, GoogleVideo video id, which is the data model
    - * this renderer will use to construct the DOM structure.
    - * {@see goog.ui.media.GoogleVideo.newControl} for a example of constructing a
    - * control with this renderer.
    - *
    - * This design is patterned after http://go/closure_control_subclassing
    - *
    - * It uses {@link goog.ui.media.FlashObject} to embed the flash object.
    - *
    - * @constructor
    - * @extends {goog.ui.media.MediaRenderer}
    - * @final
    - */
    -goog.ui.media.GoogleVideo = function() {
    -  goog.ui.media.MediaRenderer.call(this);
    -};
    -goog.inherits(goog.ui.media.GoogleVideo, goog.ui.media.MediaRenderer);
    -goog.addSingletonGetter(goog.ui.media.GoogleVideo);
    -
    -
    -/**
    - * A static convenient method to construct a goog.ui.media.Media control out of
    - * a GoogleVideo model. It sets it as the data model goog.ui.media.GoogleVideo
    - * renderer uses, sets the states supported by the renderer, and returns a
    - * Control that binds everything together. This is what you should be using for
    - * constructing GoogleVideo videos, except if you need finer control over the
    - * configuration.
    - *
    - * @param {goog.ui.media.GoogleVideoModel} dataModel The GoogleVideo data model.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @return {!goog.ui.media.Media} A Control binded to the GoogleVideo renderer.
    - */
    -goog.ui.media.GoogleVideo.newControl = function(dataModel, opt_domHelper) {
    -  var control = new goog.ui.media.Media(
    -      dataModel,
    -      goog.ui.media.GoogleVideo.getInstance(),
    -      opt_domHelper);
    -  // GoogleVideo videos don't have any thumbnail for now, so we show the
    -  // "selected" version of the UI at the start, which is the flash player.
    -  control.setSelected(true);
    -  return control;
    -};
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - *
    - * @type {string}
    - */
    -goog.ui.media.GoogleVideo.CSS_CLASS =
    -    goog.getCssName('goog-ui-media-googlevideo');
    -
    -
    -/**
    - * Creates the initial DOM structure of the GoogleVideo video, which is
    - * basically a the flash object pointing to a GoogleVideo video player.
    - *
    - * @param {goog.ui.Control} c The media control.
    - * @return {!Element} The DOM structure that represents this control.
    - * @override
    - */
    -goog.ui.media.GoogleVideo.prototype.createDom = function(c) {
    -  var control = /** @type {goog.ui.media.Media} */ (c);
    -  var div = goog.ui.media.GoogleVideo.base(this, 'createDom', control);
    -
    -  var dataModel =
    -      /** @type {goog.ui.media.GoogleVideoModel} */ (control.getDataModel());
    -
    -  var flash = new goog.ui.media.FlashObject(
    -      dataModel.getPlayer().getTrustedResourceUrl(),
    -      control.getDomHelper());
    -  flash.render(div);
    -
    -  return div;
    -};
    -
    -
    -/**
    - * Returns the CSS class to be applied to the root element of components
    - * rendered using this renderer.
    - *
    - * @return {string} Renderer-specific CSS class.
    - * @override
    - */
    -goog.ui.media.GoogleVideo.prototype.getCssClass = function() {
    -  return goog.ui.media.GoogleVideo.CSS_CLASS;
    -};
    -
    -
    -
    -/**
    - * The {@code goog.ui.media.GoogleVideo} media data model. It stores a required
    - * {@code videoId} field, sets the GoogleVideo URL, and allows a few optional
    - * parameters.
    - *
    - * @param {string} videoId The GoogleVideo video id.
    - * @param {string=} opt_caption An optional caption of the GoogleVideo video.
    - * @param {string=} opt_description An optional description of the GoogleVideo
    - *     video.
    - * @param {boolean=} opt_autoplay Whether to autoplay video.
    - * @constructor
    - * @extends {goog.ui.media.MediaModel}
    - * @final
    - */
    -goog.ui.media.GoogleVideoModel = function(videoId, opt_caption, opt_description,
    -                                          opt_autoplay) {
    -  goog.ui.media.MediaModel.call(
    -      this,
    -      goog.ui.media.GoogleVideoModel.buildUrl(videoId),
    -      opt_caption,
    -      opt_description,
    -      goog.ui.media.MediaModel.MimeType.FLASH);
    -
    -  /**
    -   * The GoogleVideo video id.
    -   * @type {string}
    -   * @private
    -   */
    -  this.videoId_ = videoId;
    -
    -  this.setPlayer(new goog.ui.media.MediaModel.Player(
    -      goog.ui.media.GoogleVideoModel.buildFlashUrl(videoId, opt_autoplay)));
    -};
    -goog.inherits(goog.ui.media.GoogleVideoModel, goog.ui.media.MediaModel);
    -
    -
    -/**
    - * Regular expression used to extract the GoogleVideo video id (docid) out of
    - * GoogleVideo URLs.
    - *
    - * @type {RegExp}
    - * @private
    - * @const
    - */
    -goog.ui.media.GoogleVideoModel.MATCHER_ =
    -    /^http:\/\/(?:www\.)?video\.google\.com\/videoplay.*[\?#]docid=(-?[0-9]+)#?$/i;
    -
    -
    -/**
    - * A auxiliary static method that parses a GoogleVideo URL, extracting the ID of
    - * the video, and builds a GoogleVideoModel.
    - *
    - * @param {string} googleVideoUrl A GoogleVideo video URL.
    - * @param {string=} opt_caption An optional caption of the GoogleVideo video.
    - * @param {string=} opt_description An optional description of the GoogleVideo
    - *     video.
    - * @param {boolean=} opt_autoplay Whether to autoplay video.
    - * @return {!goog.ui.media.GoogleVideoModel} The data model that represents the
    - *     GoogleVideo URL.
    - * @see goog.ui.media.GoogleVideoModel.getVideoId()
    - * @throws Error in case the parsing fails.
    - */
    -goog.ui.media.GoogleVideoModel.newInstance = function(googleVideoUrl,
    -                                                      opt_caption,
    -                                                      opt_description,
    -                                                      opt_autoplay) {
    -  if (goog.ui.media.GoogleVideoModel.MATCHER_.test(googleVideoUrl)) {
    -    var data = goog.ui.media.GoogleVideoModel.MATCHER_.exec(googleVideoUrl);
    -    return new goog.ui.media.GoogleVideoModel(
    -        data[1], opt_caption, opt_description, opt_autoplay);
    -  }
    -
    -  throw Error('failed to parse video id from GoogleVideo url: ' +
    -      googleVideoUrl);
    -};
    -
    -
    -/**
    - * The opposite of {@code goog.ui.media.GoogleVideo.newInstance}: it takes a
    - * videoId and returns a GoogleVideo URL.
    - *
    - * @param {string} videoId The GoogleVideo video ID.
    - * @return {string} The GoogleVideo URL.
    - */
    -goog.ui.media.GoogleVideoModel.buildUrl = function(videoId) {
    -  return 'http://video.google.com/videoplay?docid=' +
    -      goog.string.urlEncode(videoId);
    -};
    -
    -
    -/**
    - * An auxiliary method that builds URL of the flash movie to be embedded,
    - * out of the GoogleVideo video id.
    - *
    - * @param {string} videoId The GoogleVideo video ID.
    - * @param {boolean=} opt_autoplay Whether the flash movie should start playing
    - *     as soon as it is shown, or if it should show a 'play' button.
    - * @return {string} The flash URL to be embedded on the page.
    - */
    -goog.ui.media.GoogleVideoModel.buildFlashUrl = function(videoId, opt_autoplay) {
    -  var autoplay = opt_autoplay ? '&autoplay=1' : '';
    -  return 'http://video.google.com/googleplayer.swf?docid=' +
    -      goog.string.urlEncode(videoId) +
    -      '&hl=en&fs=true' + autoplay;
    -};
    -
    -
    -/**
    - * Gets the GoogleVideo video id.
    - * @return {string} The GoogleVideo video id.
    - */
    -goog.ui.media.GoogleVideoModel.prototype.getVideoId = function() {
    -  return this.videoId_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/googlevideo_test.html b/src/database/third_party/closure-library/closure/goog/ui/media/googlevideo_test.html
    deleted file mode 100644
    index 28b71845ba3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/googlevideo_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.media.GoogleVideo
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.ui.media.GoogleVideoTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/googlevideo_test.js b/src/database/third_party/closure-library/closure/goog/ui/media/googlevideo_test.js
    deleted file mode 100644
    index 09131868d7a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/googlevideo_test.js
    +++ /dev/null
    @@ -1,94 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.media.GoogleVideoTest');
    -goog.setTestOnly('goog.ui.media.GoogleVideoTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.media.FlashObject');
    -goog.require('goog.ui.media.GoogleVideo');
    -goog.require('goog.ui.media.GoogleVideoModel');
    -goog.require('goog.ui.media.Media');
    -var video;
    -var control;
    -var VIDEO_URL_PREFIX = 'http://video.google.com/videoplay?docid=';
    -var VIDEO_ID = '7582902000166025817';
    -var VIDEO_URL = VIDEO_URL_PREFIX + VIDEO_ID;
    -var parent = goog.dom.createElement('div');
    -
    -function setUp() {
    -  video = new goog.ui.media.GoogleVideo();
    -  var model = new goog.ui.media.GoogleVideoModel(VIDEO_ID, 'video caption');
    -  control = new goog.ui.media.Media(model, video);
    -  control.setSelected(true);
    -}
    -
    -function tearDown() {
    -  control.dispose();
    -}
    -
    -function testBasicRendering() {
    -  control.render(parent);
    -  var el = goog.dom.getElementsByTagNameAndClass(
    -      'div', goog.ui.media.GoogleVideo.CSS_CLASS, parent);
    -  assertEquals(1, el.length);
    -  assertEquals(VIDEO_URL, control.getDataModel().getUrl());
    -}
    -
    -function testParsingUrl() {
    -  assertExtractsCorrectly(VIDEO_ID, VIDEO_URL);
    -  // Test a url with # at the end.
    -  assertExtractsCorrectly(VIDEO_ID, VIDEO_URL + '#');
    -  // Test a url with a negative docid.
    -  assertExtractsCorrectly('-123', VIDEO_URL_PREFIX + '-123');
    -  // Test a url with two docids. The valid one is the second.
    -  assertExtractsCorrectly('123', VIDEO_URL + '#docid=123');
    -
    -  var invalidUrl = 'http://invalidUrl/filename.doc';
    -  var e = assertThrows('parser expects a well formed URL', function() {
    -    goog.ui.media.GoogleVideoModel.newInstance(invalidUrl);
    -  });
    -  assertEquals('failed to parse video id from GoogleVideo url: ' + invalidUrl,
    -      e.message);
    -}
    -
    -function testBuildingUrl() {
    -  assertEquals(VIDEO_URL, goog.ui.media.GoogleVideoModel.buildUrl(VIDEO_ID));
    -}
    -
    -function testCreatingModel() {
    -  var model = new goog.ui.media.GoogleVideoModel(VIDEO_ID);
    -  assertEquals(VIDEO_ID, model.getVideoId());
    -  assertEquals(VIDEO_URL, model.getUrl());
    -  assertUndefined(model.getCaption());
    -}
    -
    -function testCreatingDomOnInitialState() {
    -  control.render(parent);
    -  var caption = goog.dom.getElementsByTagNameAndClass(
    -      'div',
    -      goog.ui.media.GoogleVideo.CSS_CLASS + '-caption',
    -      parent);
    -  assertEquals(1, caption.length);
    -
    -  var flash = goog.dom.getElementsByTagNameAndClass(
    -      'div', goog.ui.media.FlashObject.CSS_CLASS, parent);
    -  assertEquals(1, flash.length);
    -}
    -
    -function assertExtractsCorrectly(expectedVideoId, url) {
    -  var model = goog.ui.media.GoogleVideoModel.newInstance(url);
    -  assertEquals('Video id for ' + url, expectedVideoId, model.getVideoId());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/media.js b/src/database/third_party/closure-library/closure/goog/ui/media/media.js
    deleted file mode 100644
    index 3001c5c299d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/media.js
    +++ /dev/null
    @@ -1,288 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides the base goog.ui.Control and goog.ui.ControlRenderer
    - * for media types, as well as a media model consistent with the Yahoo Media RSS
    - * specification {@link http://search.yahoo.com/mrss/}.
    - *
    - * The goog.ui.media.* package is basically a set of goog.ui.ControlRenderers
    - * subclasses (such as goog.ui.media.Youtube, goog.ui.media.Picasa, etc) that
    - * should all work with the same goog.ui.Control (goog.ui.media.Media) logic.
    - *
    - * This design guarantees that all different types of medias will behave alike
    - * (in a base level) but will look different.
    - *
    - * In MVC terms, {@link goog.ui.media.Media} is the Controller,
    - * {@link goog.ui.media.MediaRenderer} + CSS definitions are the View and
    - * {@code goog.ui.media.MediaModel} is the data Model. Typically,
    - * MediaRenderer will be subclassed to provide media specific renderers.
    - * MediaRenderer subclasses are also responsible for defining the data model.
    - *
    - * This design is strongly patterned after:
    - * http://go/closure_control_subclassing
    - *
    - * goog.ui.media.MediaRenderer handles the basic common ways to display media,
    - * such as displaying tooltips, frames, minimize/maximize buttons, play buttons,
    - * etc. Its subclasses are responsible for rendering media specific DOM
    - * structures, like youtube flash players, picasa albums, etc.
    - *
    - * goog.ui.media.Media handles the Control of Medias, by listening to events
    - * and firing the appropriate actions. It knows about the existence of captions,
    - * minimize/maximize buttons, and takes all the actions needed to change states,
    - * including delegating the UI actions to MediaRenderers.
    - *
    - * Although MediaRenderer is a base class designed to be subclassed, it can
    - * be used by itself:
    - *
    - * <pre>
    - *   var renderer = new goog.ui.media.MediaRenderer();
    - *   var control = new goog.ui.media.Media('hello world', renderer);
    - *   var control.render(goog.dom.getElement('mediaHolder'));
    - * </pre>
    - *
    - * It requires a few CSS rules to be defined, which you should use to control
    - * how the component is displayed. {@link goog.ui.ControlRenderer}s is very CSS
    - * intensive, which separates the UI structure (the HTML DOM elements, which is
    - * created by the {@code goog.ui.media.MediaRenderer}) from the UI view (which
    - * nodes are visible, which aren't, where they are positioned. These are defined
    - * on the CSS rules for each state). A few examples of CSS selectors that needs
    - * to be defined are:
    - *
    - * <ul>
    - *   <li>.goog-ui-media
    - *   <li>.goog-ui-media-hover
    - *   <li>.goog-ui-media-selected
    - * </ul>
    - *
    - * If you want to have different custom renderers CSS namespaces (eg. you may
    - * want to show a small thumbnail, or you may want to hide the caption, etc),
    - * you can do so by using:
    - *
    - * <pre>
    - *   var renderer = goog.ui.ControlRenderer.getCustomRenderer(
    - *       goog.ui.media.MediaRenderer, 'my-custom-namespace');
    - *   var media = new goog.ui.media.Media('', renderer);
    - *   media.render(goog.dom.getElement('parent'));
    - * </pre>
    - *
    - * Which will allow you to set your own .my-custom-namespace-hover,
    - * .my-custom-namespace-selected CSS selectors.
    - *
    - * NOTE(user): it seems like an overkill to subclass goog.ui.Control instead of
    - * using a factory, but we wanted to make sure we had more control over the
    - * events for future media implementations. Since we intent to use it in many
    - * different places, it makes sense to have a more flexible design that lets us
    - * control the inner workings of goog.ui.Control.
    - *
    - * TODO(user): implement, as needed, the Media specific state changes UI, such
    - * as minimize/maximize buttons, expand/close buttons, etc.
    - *
    - */
    -
    -goog.provide('goog.ui.media.Media');
    -goog.provide('goog.ui.media.MediaRenderer');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.style');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.Control');
    -goog.require('goog.ui.ControlRenderer');
    -
    -
    -
    -/**
    - * Provides the control mechanism of media types.
    - *
    - * @param {goog.ui.media.MediaModel} dataModel The data model to be used by the
    - *     renderer.
    - * @param {goog.ui.ControlRenderer=} opt_renderer Renderer used to render or
    - *     decorate the component; defaults to {@link goog.ui.ControlRenderer}.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @constructor
    - * @extends {goog.ui.Control}
    - * @final
    - */
    -goog.ui.media.Media = function(dataModel, opt_renderer, opt_domHelper) {
    -  goog.ui.Control.call(this, null, opt_renderer, opt_domHelper);
    -
    -  // Sets up the data model.
    -  this.setDataModel(dataModel);
    -  this.setSupportedState(goog.ui.Component.State.OPENED, true);
    -  this.setSupportedState(goog.ui.Component.State.SELECTED, true);
    -  // TODO(user): had to do this to for mouseDownHandler not to
    -  // e.preventDefault(), because it was not allowing the event to reach the
    -  // flash player. figure out a better way to not e.preventDefault().
    -  this.setAllowTextSelection(true);
    -
    -  // Media items don't use RTL styles, so avoid accessing computed styles to
    -  // figure out if the control is RTL.
    -  this.setRightToLeft(false);
    -};
    -goog.inherits(goog.ui.media.Media, goog.ui.Control);
    -
    -
    -/**
    - * The media data model used on the renderer.
    - *
    - * @type {goog.ui.media.MediaModel}
    - * @private
    - */
    -goog.ui.media.Media.prototype.dataModel_;
    -
    -
    -/**
    - * Sets the media model to be used on the renderer.
    - * @param {goog.ui.media.MediaModel} dataModel The media model the renderer
    - *     should use.
    - */
    -goog.ui.media.Media.prototype.setDataModel = function(dataModel) {
    -  this.dataModel_ = dataModel;
    -};
    -
    -
    -/**
    - * Gets the media model renderer is using.
    - * @return {goog.ui.media.MediaModel} The media model being used.
    - */
    -goog.ui.media.Media.prototype.getDataModel = function() {
    -  return this.dataModel_;
    -};
    -
    -
    -
    -/**
    - * Base class of all media renderers. Provides the common renderer functionality
    - * of medias.
    - *
    - * The current common functionality shared by Medias is to have an outer frame
    - * that gets highlighted on mouse hover.
    - *
    - * TODO(user): implement more common UI behavior, as needed.
    - *
    - * NOTE(user): I am not enjoying how the subclasses are changing their state
    - * through setState() ... maybe provide abstract methods like
    - * goog.ui.media.MediaRenderer.prototype.preview = goog.abstractMethod;
    - * goog.ui.media.MediaRenderer.prototype.play = goog.abstractMethod;
    - * goog.ui.media.MediaRenderer.prototype.minimize = goog.abstractMethod;
    - * goog.ui.media.MediaRenderer.prototype.maximize = goog.abstractMethod;
    - * and call them on this parent class setState ?
    - *
    - * @constructor
    - * @extends {goog.ui.ControlRenderer}
    - */
    -goog.ui.media.MediaRenderer = function() {
    -  goog.ui.ControlRenderer.call(this);
    -};
    -goog.inherits(goog.ui.media.MediaRenderer, goog.ui.ControlRenderer);
    -
    -
    -/**
    - * Builds the common DOM structure of medias. Builds an outer div, and appends
    - * a child div with the {@code goog.ui.Control.getContent} content. Marks the
    - * caption with a {@code this.getClassClass()} + '-caption' css flag, so that
    - * specific renderers can hide/show the caption as desired.
    - *
    - * @param {goog.ui.Control} control The control instance.
    - * @return {!Element} The DOM structure that represents control.
    - * @override
    - */
    -goog.ui.media.MediaRenderer.prototype.createDom = function(control) {
    -  goog.asserts.assertInstanceof(control, goog.ui.media.Media);
    -  var domHelper = control.getDomHelper();
    -  var div = domHelper.createElement('div');
    -  div.className = this.getClassNames(control).join(' ');
    -
    -  var dataModel = control.getDataModel();
    -
    -  // Only creates DOMs if the data is available.
    -  if (dataModel.getCaption()) {
    -    var caption = domHelper.createElement('div');
    -    caption.className = goog.getCssName(this.getCssClass(), 'caption');
    -    caption.appendChild(domHelper.createDom(
    -        'p', goog.getCssName(this.getCssClass(), 'caption-text'),
    -        dataModel.getCaption()));
    -    domHelper.appendChild(div, caption);
    -  }
    -
    -  if (dataModel.getDescription()) {
    -    var description = domHelper.createElement('div');
    -    description.className = goog.getCssName(this.getCssClass(), 'description');
    -    description.appendChild(domHelper.createDom(
    -        'p', goog.getCssName(this.getCssClass(), 'description-text'),
    -        dataModel.getDescription()));
    -    domHelper.appendChild(div, description);
    -  }
    -
    -  // Creates thumbnails of the media.
    -  var thumbnails = dataModel.getThumbnails() || [];
    -  for (var index = 0; index < thumbnails.length; index++) {
    -    var thumbnail = thumbnails[index];
    -    var thumbnailElement = domHelper.createElement('img');
    -    thumbnailElement.src = thumbnail.getUrl();
    -    thumbnailElement.className = this.getThumbnailCssName(index);
    -
    -    // Check that the size is defined and that the size's height and width
    -    // are defined. Undefined height and width is deprecated but still
    -    // seems to exist in some cases.
    -    var size = thumbnail.getSize();
    -
    -    if (size && goog.isDefAndNotNull(size.height) &&
    -        goog.isDefAndNotNull(size.width)) {
    -      goog.style.setSize(thumbnailElement, size);
    -    }
    -    domHelper.appendChild(div, thumbnailElement);
    -  }
    -
    -  if (dataModel.getPlayer()) {
    -    // if medias have players, allow UI for a play button.
    -    var playButton = domHelper.createElement('div');
    -    playButton.className = goog.getCssName(this.getCssClass(), 'playbutton');
    -    domHelper.appendChild(div, playButton);
    -  }
    -
    -  control.setElementInternal(div);
    -
    -  this.setState(
    -      control,
    -      /** @type {goog.ui.Component.State} */ (control.getState()),
    -      true);
    -
    -  return div;
    -};
    -
    -
    -/**
    - * Returns a renamable CSS class name for a numbered thumbnail. The default
    - * implementation generates the class names goog-ui-media-thumbnail0,
    - * goog-ui-media-thumbnail1, and the generic goog-ui-media-thumbnailn.
    - * Subclasses can override this method when their media requires additional
    - * specific class names (Applications are supposed to know how many thumbnails
    - * media will have).
    - *
    - * @param {number} index The thumbnail index.
    - * @return {string} CSS class name.
    - * @protected
    - */
    -goog.ui.media.MediaRenderer.prototype.getThumbnailCssName = function(index) {
    -  switch (index) {
    -    case 0: return goog.getCssName(this.getCssClass(), 'thumbnail0');
    -    case 1: return goog.getCssName(this.getCssClass(), 'thumbnail1');
    -    case 2: return goog.getCssName(this.getCssClass(), 'thumbnail2');
    -    case 3: return goog.getCssName(this.getCssClass(), 'thumbnail3');
    -    case 4: return goog.getCssName(this.getCssClass(), 'thumbnail4');
    -    default: return goog.getCssName(this.getCssClass(), 'thumbnailn');
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/media_test.html b/src/database/third_party/closure-library/closure/goog/ui/media/media_test.html
    deleted file mode 100644
    index ef31c83cb82..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/media_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.media.Media
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.ui.media.MediaTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/media_test.js b/src/database/third_party/closure-library/closure/goog/ui/media/media_test.js
    deleted file mode 100644
    index d61e0d20d63..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/media_test.js
    +++ /dev/null
    @@ -1,130 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.media.MediaTest');
    -goog.setTestOnly('goog.ui.media.MediaTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.math.Size');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.ControlRenderer');
    -goog.require('goog.ui.media.Media');
    -goog.require('goog.ui.media.MediaModel');
    -goog.require('goog.ui.media.MediaRenderer');
    -var control;  // The name 'media' collides with a built-in var in Chrome.
    -var renderer;
    -var model;
    -
    -function setUp() {
    -  renderer = new goog.ui.media.MediaRenderer();
    -  model = new goog.ui.media.MediaModel(
    -      'http://url.com', 'a caption', 'a description');
    -  control = new goog.ui.media.Media(model, renderer);
    -}
    -
    -function tearDown() {
    -  control.dispose();
    -}
    -
    -function testBasicElements() {
    -  var model = new goog.ui.media.MediaModel(
    -      'http://url.com', 'a caption', 'a description');
    -  var thumb1 = new goog.ui.media.MediaModel.Thumbnail(
    -      'http://thumb.com/small.jpg', new goog.math.Size(320, 288));
    -  var thumb2 = new goog.ui.media.MediaModel.Thumbnail(
    -      'http://thumb.com/big.jpg', new goog.math.Size(800, 600));
    -  model.setThumbnails([thumb1, thumb2]);
    -  model.setPlayer(new goog.ui.media.MediaModel.Player(
    -      'http://media/player.swf'));
    -  var control = new goog.ui.media.Media(model, renderer);
    -  control.render();
    -
    -  var caption = goog.dom.getElementsByTagNameAndClass(
    -      undefined,
    -      goog.ui.ControlRenderer.CSS_CLASS + '-caption');
    -  var description = goog.dom.getElementsByTagNameAndClass(
    -      undefined,
    -      goog.ui.ControlRenderer.CSS_CLASS + '-description');
    -  var thumbnail0 = goog.dom.getElementsByTagNameAndClass(
    -      'img',
    -      goog.ui.ControlRenderer.CSS_CLASS + '-thumbnail0');
    -  var thumbnail1 = goog.dom.getElementsByTagNameAndClass(
    -      'img',
    -      goog.ui.ControlRenderer.CSS_CLASS + '-thumbnail1');
    -  var player = goog.dom.getElementsByTagNameAndClass(
    -      'iframe',
    -      goog.ui.ControlRenderer.CSS_CLASS + '-player');
    -
    -  assertNotNull(caption);
    -  assertEquals(1, caption.length);
    -  assertNotNull(description);
    -  assertEquals(1, description.length);
    -  assertNotNull(thumbnail0);
    -  assertEquals(1, thumbnail0.length);
    -  assertEquals('320px', thumbnail0[0].style.width);
    -  assertEquals('288px', thumbnail0[0].style.height);
    -  assertEquals('http://thumb.com/small.jpg', thumbnail0[0].src);
    -  assertNotNull(thumbnail1);
    -  assertEquals(1, thumbnail1.length);
    -  assertEquals('800px', thumbnail1[0].style.width);
    -  assertEquals('600px', thumbnail1[0].style.height);
    -  assertEquals('http://thumb.com/big.jpg', thumbnail1[0].src);
    -  // players are only shown when media is selected
    -  assertNotNull(player);
    -  assertEquals(0, player.length);
    -
    -  control.dispose();
    -}
    -
    -function testDoesntCreatesCaptionIfUnavailable() {
    -  var incompleteModel = new goog.ui.media.MediaModel(
    -      'http://url.com', undefined, 'a description');
    -  incompleteMedia = new goog.ui.media.Media('', renderer);
    -  incompleteMedia.setDataModel(incompleteModel);
    -  incompleteMedia.render();
    -  var caption = goog.dom.getElementsByTagNameAndClass(
    -      undefined,
    -      goog.ui.ControlRenderer.CSS_CLASS + '-caption');
    -  var description = goog.dom.getElementsByTagNameAndClass(
    -      undefined,
    -      goog.ui.ControlRenderer.CSS_CLASS + '-description');
    -  assertEquals(0, caption.length);
    -  assertNotNull(description);
    -  incompleteMedia.dispose();
    -}
    -
    -function testSetAriaLabel() {
    -  var model = new goog.ui.media.MediaModel(
    -      'http://url.com', 'a caption', 'a description');
    -  var thumb1 = new goog.ui.media.MediaModel.Thumbnail(
    -      'http://thumb.com/small.jpg', new goog.math.Size(320, 288));
    -  var thumb2 = new goog.ui.media.MediaModel.Thumbnail(
    -      'http://thumb.com/big.jpg', new goog.math.Size(800, 600));
    -  model.setThumbnails([thumb1, thumb2]);
    -  model.setPlayer(new goog.ui.media.MediaModel.Player(
    -      'http://media/player.swf'));
    -  var control = new goog.ui.media.Media(model, renderer);
    -  assertNull('Media must not have aria label by default',
    -      control.getAriaLabel());
    -  control.setAriaLabel('My media');
    -  control.render();
    -  var element = control.getElementStrict();
    -  assertNotNull('Element must not be null', element);
    -  assertEquals('Media element must have expected aria-label', 'My media',
    -      element.getAttribute('aria-label'));
    -  assertTrue(goog.dom.isFocusableTabIndex(element));
    -  control.setAriaLabel('My new media');
    -  assertEquals('Media element must have updated aria-label', 'My new media',
    -      element.getAttribute('aria-label'));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/mediamodel.js b/src/database/third_party/closure-library/closure/goog/ui/media/mediamodel.js
    deleted file mode 100644
    index 35654cf799b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/mediamodel.js
    +++ /dev/null
    @@ -1,978 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides the base media model consistent with the Yahoo Media
    - * RSS specification {@link http://search.yahoo.com/mrss/}.
    - */
    -
    -goog.provide('goog.ui.media.MediaModel');
    -goog.provide('goog.ui.media.MediaModel.Category');
    -goog.provide('goog.ui.media.MediaModel.Credit');
    -goog.provide('goog.ui.media.MediaModel.Credit.Role');
    -goog.provide('goog.ui.media.MediaModel.Credit.Scheme');
    -goog.provide('goog.ui.media.MediaModel.Medium');
    -goog.provide('goog.ui.media.MediaModel.MimeType');
    -goog.provide('goog.ui.media.MediaModel.Player');
    -goog.provide('goog.ui.media.MediaModel.SubTitle');
    -goog.provide('goog.ui.media.MediaModel.Thumbnail');
    -
    -goog.require('goog.array');
    -goog.require('goog.html.TrustedResourceUrl');
    -goog.require('goog.html.legacyconversions');
    -
    -
    -
    -/**
    - * An base data value class for all media data models.
    - *
    - * MediaModels are exact matches to the fields defined in the Yahoo RSS media
    - * specification {@link http://search.yahoo.com/mrss/}.
    - *
    - * The current common data shared by medias is to have URLs, mime types,
    - * captions, descriptions, thumbnails and players. Some of these may not be
    - * available, or applications may not want to render them, so {@code null}
    - * values are allowed. {@code goog.ui.media.MediaRenderer} checks whether the
    - * values are available before creating DOMs for them.
    - *
    - * TODO(user): support asynchronous data models by subclassing
    - * {@link goog.events.EventTarget} or {@link goog.ds.DataNode}. Understand why
    - * {@link http://goto/datanode} is not available in closure. Add setters to
    - * MediaModel once this is supported.
    - *
    - * @param {string=} opt_url An optional URL of the media.
    - * @param {string=} opt_caption An optional caption of the media.
    - * @param {string=} opt_description An optional description of the media.
    - * @param {goog.ui.media.MediaModel.MimeType=} opt_type The type of the media.
    - * @param {goog.ui.media.MediaModel.Medium=} opt_medium The medium of the media.
    - * @param {number=} opt_duration The duration of the media in seconds.
    - * @param {number=} opt_width The width of the media in pixels.
    - * @param {number=} opt_height The height of the media in pixels.
    - * @constructor
    - */
    -goog.ui.media.MediaModel = function(opt_url,
    -                                    opt_caption,
    -                                    opt_description,
    -                                    opt_type,
    -                                    opt_medium,
    -                                    opt_duration,
    -                                    opt_width,
    -                                    opt_height) {
    -  /**
    -   * The URL of the media.
    -   * @type {string|undefined}
    -   * @private
    -   */
    -  this.url_ = opt_url;
    -
    -  /**
    -   * The caption of the media.
    -   * @type {string|undefined}
    -   * @private
    -   */
    -  this.caption_ = opt_caption;
    -
    -  /**
    -   * A description of the media, typically user generated comments about it.
    -   * @type {string|undefined}
    -   * @private
    -   */
    -  this.description_ = opt_description;
    -
    -  /**
    -   * The mime type of the media.
    -   * @type {goog.ui.media.MediaModel.MimeType|undefined}
    -   * @private
    -   */
    -  this.type_ = opt_type;
    -
    -  /**
    -   * The medium of the media.
    -   * @type {goog.ui.media.MediaModel.Medium|undefined}
    -   * @private
    -   */
    -  this.medium_ = opt_medium;
    -
    -  /**
    -   * The duration of the media in seconds.
    -   * @type {number|undefined}
    -   * @private
    -   */
    -  this.duration_ = opt_duration;
    -
    -  /**
    -   * The width of the media in pixels.
    -   * @type {number|undefined}
    -   * @private
    -   */
    -  this.width_ = opt_width;
    -
    -  /**
    -   * The height of the media in pixels.
    -   * @type {number|undefined}
    -   * @private
    -   */
    -  this.height_ = opt_height;
    -
    -  /**
    -   * A list of thumbnails representations of the media (eg different sizes of
    -   * the same photo, etc).
    -   * @type {Array<goog.ui.media.MediaModel.Thumbnail>}
    -   * @private
    -   */
    -  this.thumbnails_ = [];
    -
    -  /**
    -   * The list of categories that are applied to this media.
    -   * @type {Array<goog.ui.media.MediaModel.Category>}
    -   * @private
    -   */
    -  this.categories_ = [];
    -
    -  /**
    -   * The list of credits that pertain to this media object.
    -   * @type {!Array<goog.ui.media.MediaModel.Credit>}
    -   * @private
    -   */
    -  this.credits_ = [];
    -
    -  /**
    -   * The list of subtitles for the media object.
    -   * @type {Array<goog.ui.media.MediaModel.SubTitle>}
    -   * @private
    -   */
    -  this.subTitles_ = [];
    -};
    -
    -
    -/**
    - * The supported media mime types, a subset of the media types found here:
    - * {@link http://www.iana.org/assignments/media-types/} and here
    - * {@link http://en.wikipedia.org/wiki/Internet_media_type}
    - * @enum {string}
    - */
    -goog.ui.media.MediaModel.MimeType = {
    -  HTML: 'text/html',
    -  PLAIN: 'text/plain',
    -  FLASH: 'application/x-shockwave-flash',
    -  JPEG: 'image/jpeg',
    -  GIF: 'image/gif',
    -  PNG: 'image/png'
    -};
    -
    -
    -/**
    - * Supported mediums, found here:
    - * {@link http://video.search.yahoo.com/mrss}
    - * @enum {string}
    - */
    -goog.ui.media.MediaModel.Medium = {
    -  IMAGE: 'image',
    -  AUDIO: 'audio',
    -  VIDEO: 'video',
    -  DOCUMENT: 'document',
    -  EXECUTABLE: 'executable'
    -};
    -
    -
    -/**
    - * The media player.
    - * @type {goog.ui.media.MediaModel.Player}
    - * @private
    - */
    -goog.ui.media.MediaModel.prototype.player_;
    -
    -
    -/**
    - * Gets the URL of this media.
    - * @return {string|undefined} The URL of the media.
    - */
    -goog.ui.media.MediaModel.prototype.getUrl = function() {
    -  return this.url_;
    -};
    -
    -
    -/**
    - * Sets the URL of this media.
    - * @param {string} url The URL of the media.
    - * @return {!goog.ui.media.MediaModel} The object itself, used for chaining.
    - */
    -goog.ui.media.MediaModel.prototype.setUrl = function(url) {
    -  this.url_ = url;
    -  return this;
    -};
    -
    -
    -/**
    - * Gets the caption of this media.
    - * @return {string|undefined} The caption of the media.
    - */
    -goog.ui.media.MediaModel.prototype.getCaption = function() {
    -  return this.caption_;
    -};
    -
    -
    -/**
    - * Sets the caption of this media.
    - * @param {string} caption The caption of the media.
    - * @return {!goog.ui.media.MediaModel} The object itself, used for chaining.
    - */
    -goog.ui.media.MediaModel.prototype.setCaption = function(caption) {
    -  this.caption_ = caption;
    -  return this;
    -};
    -
    -
    -/**
    - * Gets the media mime type.
    - * @return {goog.ui.media.MediaModel.MimeType|undefined} The media mime type.
    - */
    -goog.ui.media.MediaModel.prototype.getType = function() {
    -  return this.type_;
    -};
    -
    -
    -/**
    - * Sets the media mime type.
    - * @param {goog.ui.media.MediaModel.MimeType} type The media mime type.
    - * @return {!goog.ui.media.MediaModel} The object itself, used for chaining.
    - */
    -goog.ui.media.MediaModel.prototype.setType = function(type) {
    -  this.type_ = type;
    -  return this;
    -};
    -
    -
    -/**
    - * Gets the media medium.
    - * @return {goog.ui.media.MediaModel.Medium|undefined} The media medium.
    - */
    -goog.ui.media.MediaModel.prototype.getMedium = function() {
    -  return this.medium_;
    -};
    -
    -
    -/**
    - * Sets the media medium.
    - * @param {goog.ui.media.MediaModel.Medium} medium The media medium.
    - * @return {!goog.ui.media.MediaModel} The object itself, used for chaining.
    - */
    -goog.ui.media.MediaModel.prototype.setMedium = function(medium) {
    -  this.medium_ = medium;
    -  return this;
    -};
    -
    -
    -/**
    - * Gets the description of this media.
    - * @return {string|undefined} The description of the media.
    - */
    -goog.ui.media.MediaModel.prototype.getDescription = function() {
    -  return this.description_;
    -};
    -
    -
    -/**
    - * Sets the description of this media.
    - * @param {string} description The description of the media.
    - * @return {!goog.ui.media.MediaModel} The object itself, used for chaining.
    - */
    -goog.ui.media.MediaModel.prototype.setDescription = function(description) {
    -  this.description_ = description;
    -  return this;
    -};
    -
    -
    -/**
    - * Gets the thumbnail urls.
    - * @return {Array<goog.ui.media.MediaModel.Thumbnail>} The list of thumbnails.
    - */
    -goog.ui.media.MediaModel.prototype.getThumbnails = function() {
    -  return this.thumbnails_;
    -};
    -
    -
    -/**
    - * Sets the thumbnail list.
    - * @param {Array<goog.ui.media.MediaModel.Thumbnail>} thumbnails The list of
    - *     thumbnail.
    - * @return {!goog.ui.media.MediaModel} The object itself, used for chaining.
    - */
    -goog.ui.media.MediaModel.prototype.setThumbnails = function(thumbnails) {
    -  this.thumbnails_ = thumbnails;
    -  return this;
    -};
    -
    -
    -/**
    - * Gets the duration of the media.
    - * @return {number|undefined} The duration in seconds.
    - */
    -goog.ui.media.MediaModel.prototype.getDuration = function() {
    -  return this.duration_;
    -};
    -
    -
    -/**
    - * Sets duration of the media.
    - * @param {number} duration The duration of the media, in seconds.
    - * @return {!goog.ui.media.MediaModel} The object itself, used for chaining.
    - */
    -goog.ui.media.MediaModel.prototype.setDuration = function(duration) {
    -  this.duration_ = duration;
    -  return this;
    -};
    -
    -
    -/**
    - * Gets the width of the media in pixels.
    - * @return {number|undefined} The width in pixels.
    - */
    -goog.ui.media.MediaModel.prototype.getWidth = function() {
    -  return this.width_;
    -};
    -
    -
    -/**
    - * Sets the width of the media.
    - * @param {number} width The width of the media, in pixels.
    - * @return {!goog.ui.media.MediaModel} The object itself, used for chaining.
    - */
    -goog.ui.media.MediaModel.prototype.setWidth = function(width) {
    -  this.width_ = width;
    -  return this;
    -};
    -
    -
    -/**
    - * Gets the height of the media in pixels.
    - * @return {number|undefined} The height in pixels.
    - */
    -goog.ui.media.MediaModel.prototype.getHeight = function() {
    -  return this.height_;
    -};
    -
    -
    -/**
    - * Sets the height of the media.
    - * @param {number} height The height of the media, in pixels.
    - * @return {!goog.ui.media.MediaModel} The object itself, used for chaining.
    - */
    -goog.ui.media.MediaModel.prototype.setHeight = function(height) {
    -  this.height_ = height;
    -  return this;
    -};
    -
    -
    -/**
    - * Gets the player data.
    - * @return {goog.ui.media.MediaModel.Player|undefined} The media player data.
    - */
    -goog.ui.media.MediaModel.prototype.getPlayer = function() {
    -  return this.player_;
    -};
    -
    -
    -/**
    - * Sets the player data.
    - * @param {goog.ui.media.MediaModel.Player} player The media player data.
    - * @return {!goog.ui.media.MediaModel} The object itself, used for chaining.
    - */
    -goog.ui.media.MediaModel.prototype.setPlayer = function(player) {
    -  this.player_ = player;
    -  return this;
    -};
    -
    -
    -/**
    - * Gets the categories of the media.
    - * @return {Array<goog.ui.media.MediaModel.Category>} The categories of the
    - *     media.
    - */
    -goog.ui.media.MediaModel.prototype.getCategories = function() {
    -  return this.categories_;
    -};
    -
    -
    -/**
    - * Sets the categories of the media
    - * @param {Array<goog.ui.media.MediaModel.Category>} categories The categories
    - *     of the media.
    - * @return {!goog.ui.media.MediaModel} The object itself, used for chaining.
    - */
    -goog.ui.media.MediaModel.prototype.setCategories = function(categories) {
    -  this.categories_ = categories;
    -  return this;
    -};
    -
    -
    -/**
    - * Finds the first category with the given scheme.
    - * @param {string} scheme The scheme to search for.
    - * @return {goog.ui.media.MediaModel.Category} The category that has the
    - *     given scheme. May be null.
    - */
    -goog.ui.media.MediaModel.prototype.findCategoryWithScheme = function(scheme) {
    -  if (!this.categories_) {
    -    return null;
    -  }
    -  var category = goog.array.find(this.categories_, function(category) {
    -    return category ? (scheme == category.getScheme()) : false;
    -  });
    -  return /** @type {goog.ui.media.MediaModel.Category} */ (category);
    -};
    -
    -
    -/**
    - * Gets the credits of the media.
    - * @return {!Array<goog.ui.media.MediaModel.Credit>} The credits of the media.
    - */
    -goog.ui.media.MediaModel.prototype.getCredits = function() {
    -  return this.credits_;
    -};
    -
    -
    -/**
    - * Sets the credits of the media
    - * @param {!Array<goog.ui.media.MediaModel.Credit>} credits The credits of the
    - *     media.
    - * @return {!goog.ui.media.MediaModel} The object itself, used for chaining.
    - */
    -goog.ui.media.MediaModel.prototype.setCredits = function(credits) {
    -  this.credits_ = credits;
    -  return this;
    -};
    -
    -
    -/**
    - * Finds all credits with the given role.
    - * @param {string} role The role to search for.
    - * @return {!Array<!goog.ui.media.MediaModel.Credit>} An array of credits
    - *     with the given role. May be empty.
    - */
    -goog.ui.media.MediaModel.prototype.findCreditsWithRole = function(role) {
    -  var credits = goog.array.filter(this.credits_, function(credit) {
    -    return role == credit.getRole();
    -  });
    -  return /** @type {!Array<!goog.ui.media.MediaModel.Credit>} */ (credits);
    -};
    -
    -
    -/**
    - * Gets the subtitles for the media.
    - * @return {Array<goog.ui.media.MediaModel.SubTitle>} The subtitles.
    - */
    -goog.ui.media.MediaModel.prototype.getSubTitles = function() {
    -  return this.subTitles_;
    -};
    -
    -
    -/**
    - * Sets the subtitles for the media
    - * @param {Array<goog.ui.media.MediaModel.SubTitle>} subtitles The subtitles.
    - * @return {!goog.ui.media.MediaModel} The object itself.
    - */
    -goog.ui.media.MediaModel.prototype.setSubTitles = function(subtitles) {
    -  this.subTitles_ = subtitles;
    -  return this;
    -};
    -
    -
    -
    -/**
    - * Constructs a thumbnail containing details of the thumbnail's image URL and
    - * optionally its size.
    - * @param {string} url The URL of the thumbnail's image.
    - * @param {goog.math.Size=} opt_size The size of the thumbnail's image if known.
    - * @constructor
    - * @final
    - */
    -goog.ui.media.MediaModel.Thumbnail = function(url, opt_size) {
    -  /**
    -   * The thumbnail's image URL.
    -   * @type {string}
    -   * @private
    -   */
    -  this.url_ = url;
    -
    -  /**
    -   * The size of the thumbnail's image if known.
    -   * @type {goog.math.Size}
    -   * @private
    -   */
    -  this.size_ = opt_size || null;
    -};
    -
    -
    -/**
    - * Gets the thumbnail URL.
    - * @return {string} The thumbnail's image URL.
    - */
    -goog.ui.media.MediaModel.Thumbnail.prototype.getUrl = function() {
    -  return this.url_;
    -};
    -
    -
    -/**
    - * Sets the thumbnail URL.
    - * @param {string} url The thumbnail's image URL.
    - * @return {!goog.ui.media.MediaModel.Thumbnail} The object itself, used for
    - *     chaining.
    - */
    -goog.ui.media.MediaModel.Thumbnail.prototype.setUrl = function(url) {
    -  this.url_ = url;
    -  return this;
    -};
    -
    -
    -/**
    - * Gets the thumbnail size.
    - * @return {goog.math.Size} The size of the thumbnail's image if known.
    - */
    -goog.ui.media.MediaModel.Thumbnail.prototype.getSize = function() {
    -  return this.size_;
    -};
    -
    -
    -/**
    - * Sets the thumbnail size.
    - * @param {goog.math.Size} size The size of the thumbnail's image.
    - * @return {!goog.ui.media.MediaModel.Thumbnail} The object itself, used for
    - *     chaining.
    - */
    -goog.ui.media.MediaModel.Thumbnail.prototype.setSize = function(size) {
    -  this.size_ = size;
    -  return this;
    -};
    -
    -
    -
    -/**
    - * Constructs a player containing details of the player's URL and
    - * optionally its size.
    - * @param {string|!goog.html.TrustedResourceUrl} url The URL of the player.
    - * @param {Object=} opt_vars Optional map of arguments to the player.
    - * @param {goog.math.Size=} opt_size The size of the player if known.
    - * @constructor
    - * @final
    - */
    -goog.ui.media.MediaModel.Player = function(url, opt_vars, opt_size) {
    -  /**
    -   * The player's URL.
    -   * @type {!goog.html.TrustedResourceUrl}
    -   * @private
    -   */
    -  this.trustedResourceUrl_ = url instanceof goog.html.TrustedResourceUrl ? url :
    -      goog.html.legacyconversions.trustedResourceUrlFromString(url);
    -
    -  /**
    -   * Player arguments, typically flash arguments.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.vars_ = opt_vars || null;
    -
    -  /**
    -   * The size of the player if known.
    -   * @type {goog.math.Size}
    -   * @private
    -   */
    -  this.size_ = opt_size || null;
    -};
    -
    -
    -/**
    - * Gets the player URL.
    - * @return {!goog.html.TrustedResourceUrl} The player's URL.
    - */
    -goog.ui.media.MediaModel.Player.prototype.getTrustedResourceUrl = function() {
    -  return this.trustedResourceUrl_;
    -};
    -
    -
    -/**
    - * Gets the player URL.
    - * @return {string} The player's URL.
    - */
    -goog.ui.media.MediaModel.Player.prototype.getUrl = function() {
    -  return this.trustedResourceUrl_.getTypedStringValue();
    -};
    -
    -
    -/**
    - * Sets the player URL.
    - * @param {string|!goog.html.TrustedResourceUrl} url The player's URL.
    - * @return {!goog.ui.media.MediaModel.Player} The object itself, used for
    - *     chaining.
    - */
    -goog.ui.media.MediaModel.Player.prototype.setUrl = function(url) {
    -  this.trustedResourceUrl_ = url instanceof goog.html.TrustedResourceUrl ? url :
    -      goog.html.legacyconversions.trustedResourceUrlFromString(url);
    -  return this;
    -};
    -
    -
    -/**
    - * Gets the player arguments.
    - * @return {Object} The media player arguments.
    - */
    -goog.ui.media.MediaModel.Player.prototype.getVars = function() {
    -  return this.vars_;
    -};
    -
    -
    -/**
    - * Sets the player arguments.
    - * @param {Object} vars The media player arguments.
    - * @return {!goog.ui.media.MediaModel.Player} The object itself, used for
    - *     chaining.
    - */
    -goog.ui.media.MediaModel.Player.prototype.setVars = function(vars) {
    -  this.vars_ = vars;
    -  return this;
    -};
    -
    -
    -/**
    - * Gets the size of the player.
    - * @return {goog.math.Size} The size of the player if known.
    - */
    -goog.ui.media.MediaModel.Player.prototype.getSize = function() {
    -  return this.size_;
    -};
    -
    -
    -/**
    - * Sets the size of the player.
    - * @param {goog.math.Size} size The size of the player.
    - * @return {!goog.ui.media.MediaModel.Player} The object itself, used for
    - *     chaining.
    - */
    -goog.ui.media.MediaModel.Player.prototype.setSize = function(size) {
    -  this.size_ = size;
    -  return this;
    -};
    -
    -
    -
    -/**
    - * A taxonomy to be set that gives an indication of the type of media content,
    - * and its particular contents.
    - * @param {string} scheme The URI that identifies the categorization scheme.
    - * @param {string} value The value of the category.
    - * @param {string=} opt_label The human readable label that can be displayed in
    - *     end user applications.
    - * @constructor
    - * @final
    - */
    -goog.ui.media.MediaModel.Category = function(scheme, value, opt_label) {
    -  /**
    -   * The URI that identifies the categorization scheme.
    -   * @type {string}
    -   * @private
    -   */
    -  this.scheme_ = scheme;
    -
    -  /**
    -   * The value of the category.
    -   * @type {string}
    -   * @private
    -   */
    -  this.value_ = value;
    -
    -  /**
    -   * The human readable label that can be displayed in end user applications.
    -   * @type {string}
    -   * @private
    -   */
    -  this.label_ = opt_label || '';
    -};
    -
    -
    -/**
    - * Gets the category scheme.
    - * @return {string} The category scheme URI.
    - */
    -goog.ui.media.MediaModel.Category.prototype.getScheme = function() {
    -  return this.scheme_;
    -};
    -
    -
    -/**
    - * Sets the category scheme.
    - * @param {string} scheme The category's scheme.
    - * @return {!goog.ui.media.MediaModel.Category} The object itself, used for
    - *     chaining.
    - */
    -goog.ui.media.MediaModel.Category.prototype.setScheme = function(scheme) {
    -  this.scheme_ = scheme;
    -  return this;
    -};
    -
    -
    -/**
    - * Gets the categor's value.
    - * @return {string} The category's value.
    - */
    -goog.ui.media.MediaModel.Category.prototype.getValue = function() {
    -  return this.value_;
    -};
    -
    -
    -/**
    - * Sets the category value.
    - * @param {string} value The category value to be set.
    - * @return {!goog.ui.media.MediaModel.Category} The object itself, used for
    - *     chaining.
    - */
    -goog.ui.media.MediaModel.Category.prototype.setValue = function(value) {
    -  this.value_ = value;
    -  return this;
    -};
    -
    -
    -/**
    - * Gets the label of the category.
    - * @return {string} The label of the category.
    - */
    -goog.ui.media.MediaModel.Category.prototype.getLabel = function() {
    -  return this.label_;
    -};
    -
    -
    -/**
    - * Sets the label of the category.
    - * @param {string} label The label of the category.
    - * @return {!goog.ui.media.MediaModel.Category} The object itself, used for
    - *     chaining.
    - */
    -goog.ui.media.MediaModel.Category.prototype.setLabel = function(label) {
    -  this.label_ = label;
    -  return this;
    -};
    -
    -
    -
    -/**
    - * Indicates an entity that has contributed to a media object. Based on
    - * 'media.credit' in the rss spec.
    - * @param {string} value The name of the entity being credited.
    - * @param {goog.ui.media.MediaModel.Credit.Role=} opt_role The role the entity
    - *     played.
    - * @param {goog.ui.media.MediaModel.Credit.Scheme=} opt_scheme The URI that
    - *     identifies the role scheme.
    - * @constructor
    - * @final
    - */
    -goog.ui.media.MediaModel.Credit = function(value, opt_role, opt_scheme) {
    -  /**
    -   * The name of entity being credited.
    -   * @type {string}
    -   * @private
    -   */
    -  this.value_ = value;
    -
    -  /**
    -   * The role the entity played.
    -   * @type {goog.ui.media.MediaModel.Credit.Role|undefined}
    -   * @private
    -   */
    -  this.role_ = opt_role;
    -
    -  /**
    -   * The URI that identifies the role scheme
    -   * @type {goog.ui.media.MediaModel.Credit.Scheme|undefined}
    -   * @private
    -   */
    -  this.scheme_ = opt_scheme;
    -};
    -
    -
    -/**
    - * The types of known roles.
    - * @enum {string}
    - */
    -goog.ui.media.MediaModel.Credit.Role = {
    -  UPLOADER: 'uploader',
    -  OWNER: 'owner'
    -};
    -
    -
    -/**
    - * The types of known schemes.
    - * @enum {string}
    - */
    -goog.ui.media.MediaModel.Credit.Scheme = {
    -  EUROPEAN_BROADCASTING: 'urn:ebu',
    -  YAHOO: 'urn:yvs',
    -  YOUTUBE: 'urn:youtube'
    -};
    -
    -
    -/**
    - * Gets the name of the entity being credited.
    - * @return {string} The name of the entity.
    - */
    -goog.ui.media.MediaModel.Credit.prototype.getValue = function() {
    -  return this.value_;
    -};
    -
    -
    -/**
    - * Sets the value of the credit object.
    - * @param {string} value The value.
    - * @return {!goog.ui.media.MediaModel.Credit} The object itself.
    - */
    -goog.ui.media.MediaModel.Credit.prototype.setValue = function(value) {
    -  this.value_ = value;
    -  return this;
    -};
    -
    -
    -/**
    - * Gets the role of the entity being credited.
    - * @return {goog.ui.media.MediaModel.Credit.Role|undefined} The role of the
    - *     entity.
    - */
    -goog.ui.media.MediaModel.Credit.prototype.getRole = function() {
    -  return this.role_;
    -};
    -
    -
    -/**
    - * Sets the role of the credit object.
    - * @param {goog.ui.media.MediaModel.Credit.Role} role The role.
    - * @return {!goog.ui.media.MediaModel.Credit} The object itself.
    - */
    -goog.ui.media.MediaModel.Credit.prototype.setRole = function(role) {
    -  this.role_ = role;
    -  return this;
    -};
    -
    -
    -/**
    - * Gets the scheme of the credit object.
    - * @return {goog.ui.media.MediaModel.Credit.Scheme|undefined} The URI that
    - *     identifies the role scheme.
    - */
    -goog.ui.media.MediaModel.Credit.prototype.getScheme = function() {
    -  return this.scheme_;
    -};
    -
    -
    -/**
    - * Sets the scheme of the credit object.
    - * @param {goog.ui.media.MediaModel.Credit.Scheme} scheme The scheme.
    - * @return {!goog.ui.media.MediaModel.Credit} The object itself.
    - */
    -goog.ui.media.MediaModel.Credit.prototype.setScheme = function(scheme) {
    -  this.scheme_ = scheme;
    -  return this;
    -};
    -
    -
    -
    -/**
    - * A reference to the subtitle URI for a media object.
    - * Implements the 'media.subTitle' in the rss spec.
    - *
    - * @param {string} href The subtitle's URI.
    - *     to fetch the subtitle file.
    - * @param {string} lang An RFC 3066 language.
    - * @param {string} type The MIME type of the URI.
    - * @constructor
    - * @final
    - */
    -goog.ui.media.MediaModel.SubTitle = function(href, lang, type) {
    -  /**
    -   * The subtitle href.
    -   * @type {string}
    -   * @private
    -   */
    -  this.href_ = href;
    -
    -  /**
    -   * The RFC 3066 language.
    -   * @type {string}
    -   * @private
    -   */
    -  this.lang_ = lang;
    -
    -  /**
    -   * The MIME type of the resource.
    -   * @type {string}
    -   * @private
    -   */
    -  this.type_ = type;
    -};
    -
    -
    -/**
    - * Sets the href for the subtitle object.
    - * @param {string} href The subtitle's URI.
    - * @return {!goog.ui.media.MediaModel.SubTitle} The object itself.
    - */
    -goog.ui.media.MediaModel.SubTitle.prototype.setHref = function(href) {
    -  this.href_ = href;
    -  return this;
    -};
    -
    -
    -/**
    - * Get the href for the subtitle object.
    - * @return {string} href The subtitle's URI.
    - */
    -goog.ui.media.MediaModel.SubTitle.prototype.getHref = function() {
    -  return this.href_;
    -};
    -
    -
    -/**
    - * Sets the language for the subtitle object.
    - * @param {string} lang The RFC 3066 language.
    - * @return {!goog.ui.media.MediaModel.SubTitle} The object itself.
    - */
    -goog.ui.media.MediaModel.SubTitle.prototype.setLang = function(lang) {
    -  this.lang_ = lang;
    -  return this;
    -};
    -
    -
    -/**
    - * Get the lang for the subtitle object.
    - * @return {string} lang The RFC 3066 language.
    - */
    -goog.ui.media.MediaModel.SubTitle.prototype.getLang = function() {
    -  return this.lang_;
    -};
    -
    -
    -/**
    - * Sets the type for the subtitle object.
    - * @param {string} type The MIME type.
    - * @return {!goog.ui.media.MediaModel.SubTitle} The object itself.
    - */
    -goog.ui.media.MediaModel.SubTitle.prototype.setType = function(type) {
    -  this.type_ = type;
    -  return this;
    -};
    -
    -
    -/**
    - * Get the type for the subtitle object.
    - * @return {string} type The MIME type.
    - */
    -goog.ui.media.MediaModel.SubTitle.prototype.getType = function() {
    -  return this.type_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/mediamodel_test.html b/src/database/third_party/closure-library/closure/goog/ui/media/mediamodel_test.html
    deleted file mode 100644
    index 69493e1891d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/mediamodel_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -          deboer@google.com (James deBoer)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.media.MediaModel
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.ui.media.MediaModelTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/mediamodel_test.js b/src/database/third_party/closure-library/closure/goog/ui/media/mediamodel_test.js
    deleted file mode 100644
    index 8c012a03ff8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/mediamodel_test.js
    +++ /dev/null
    @@ -1,95 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.media.MediaModelTest');
    -goog.setTestOnly('goog.ui.media.MediaModelTest');
    -
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.media.MediaModel');
    -
    -
    -/**
    - * A simple model used in many tests.
    - */
    -var model;
    -
    -function setUp() {
    -  model = new goog.ui.media.MediaModel(
    -      'http://url.com', 'a caption', 'a description');
    -}
    -
    -function testMediaModel() {
    -  assertEquals('http://url.com', model.getUrl());
    -  assertEquals('a caption', model.getCaption());
    -  assertEquals('a description', model.getDescription());
    -
    -  var incompleteModel = new goog.ui.media.MediaModel(
    -      'http://foo.bar',
    -      undefined,
    -      'This media has no caption but has a description and a URL');
    -  assertEquals('http://foo.bar', incompleteModel.getUrl());
    -  assertUndefined(incompleteModel.getCaption());
    -  assertEquals('This media has no caption but has a description and a URL',
    -      incompleteModel.getDescription());
    -  assertArrayEquals([], incompleteModel.getThumbnails());
    -}
    -
    -function testMediaModelFindCategoryWithScheme() {
    -  assertNull(model.findCategoryWithScheme('no such scheme'));
    -
    -  model.setCategories([
    -    new goog.ui.media.MediaModel.Category('scheme-a', 'value-a'),
    -    new goog.ui.media.MediaModel.Category('scheme-b', 'value-b')
    -  ]);
    -  assertNull(model.findCategoryWithScheme('no such scheme'));
    -  assertEquals('value-a',
    -      model.findCategoryWithScheme('scheme-a').getValue());
    -  assertEquals('value-b',
    -      model.findCategoryWithScheme('scheme-b').getValue());
    -}
    -
    -
    -function testMediaModelFindCreditsWithRole() {
    -  assertEquals(0, model.findCreditsWithRole('no such role').length);
    -
    -  model.setCredits([
    -    new goog.ui.media.MediaModel.Credit('value-a', 'role-a'),
    -    new goog.ui.media.MediaModel.Credit('value-a2', 'role-a'),
    -    new goog.ui.media.MediaModel.Credit('value-b', 'role-b')
    -  ]);
    -
    -  assertEquals(0, model.findCreditsWithRole('no such role').length);
    -  assertEquals(2, model.findCreditsWithRole('role-a').length);
    -  assertEquals('value-a',
    -      model.findCreditsWithRole('role-a')[0].getValue());
    -  assertEquals('value-a2',
    -      model.findCreditsWithRole('role-a')[1].getValue());
    -  assertEquals('value-b',
    -      model.findCreditsWithRole('role-b')[0].getValue());
    -}
    -
    -function testMediaModelSubtitles() {
    -  model.setSubTitles([
    -    new goog.ui.media.MediaModel.SubTitle(
    -        'uri', '*', 'application/tts+xml')
    -  ]);
    -  assertEquals(1, model.getSubTitles().length);
    -  assertEquals('uri', model.getSubTitles()[0].getHref());
    -  assertEquals('*', model.getSubTitles()[0].getLang());
    -  assertEquals('application/tts+xml', model.getSubTitles()[0].getType());
    -}
    -
    -function testMediaModelNoSubtitles() {
    -  assertEquals(0, model.getSubTitles().length);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/mp3.js b/src/database/third_party/closure-library/closure/goog/ui/media/mp3.js
    deleted file mode 100644
    index d42450ff744..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/mp3.js
    +++ /dev/null
    @@ -1,226 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview provides a reusable mp3 UI component given a mp3 URL.
    - *
    - * goog.ui.media.Mp3 is actually a {@link goog.ui.ControlRenderer}, a stateless
    - * class - that could/should be used as a Singleton with the static method
    - * {@code goog.ui.media.Mp3.getInstance} -, that knows how to render Mp3s. It is
    - * designed to be used with a {@link goog.ui.Control}, which will actually
    - * control the media renderer and provide the {@link goog.ui.Component} base.
    - * This design guarantees that all different types of medias will behave alike
    - * but will look different.
    - *
    - * goog.ui.media.Mp3 expects mp3 urls on {@code goog.ui.Control.getModel} as
    - * data models, and render a flash object that will play that URL.
    - *
    - * Example of usage:
    - *
    - * <pre>
    - *   goog.ui.media.Mp3.newControl('http://hostname/file.mp3').render();
    - * </pre>
    - *
    - * Mp3 medias currently support the following states:
    - *
    - * <ul>
    - *   <li> {@link goog.ui.Component.State.DISABLED}: shows 'flash not available'
    - *   <li> {@link goog.ui.Component.State.HOVER}: mouse cursor is over the mp3
    - *   <li> {@link goog.ui.Component.State.SELECTED}: mp3 is playing
    - * </ul>
    - *
    - * Which can be accessed by
    - *
    - * <pre>
    - *   mp3.setEnabled(true);
    - *   mp3.setHighlighted(true);
    - *   mp3.setSelected(true);
    - * </pre>
    - *
    - *
    - * @supported IE6, FF2+, Safari. Requires flash to actually work.
    - *
    - * TODO(user): test on other browsers
    - */
    -
    -goog.provide('goog.ui.media.Mp3');
    -
    -goog.require('goog.string');
    -goog.require('goog.ui.media.FlashObject');
    -goog.require('goog.ui.media.Media');
    -goog.require('goog.ui.media.MediaRenderer');
    -
    -
    -
    -/**
    - * Subclasses a goog.ui.media.MediaRenderer to provide a Mp3 specific media
    - * renderer.
    - *
    - * This class knows how to parse mp3 URLs, and render the DOM structure
    - * of mp3 flash players. This class is meant to be used as a singleton static
    - * stateless class, that takes {@code goog.ui.media.Media} instances and renders
    - * it. It expects {@code goog.ui.media.Media.getModel} to return a well formed,
    - * previously checked, mp3 URL {@see goog.ui.media.PicasaAlbum.parseUrl},
    - * which is the data model this renderer will use to construct the DOM
    - * structure. {@see goog.ui.media.PicasaAlbum.newControl} for an example of
    - * constructing a control with this renderer.
    - *
    - * This design is patterned after http://go/closure_control_subclassing
    - *
    - * It uses {@link goog.ui.media.FlashObject} to embed the flash object.
    - *
    - * @constructor
    - * @extends {goog.ui.media.MediaRenderer}
    - * @final
    - */
    -goog.ui.media.Mp3 = function() {
    -  goog.ui.media.MediaRenderer.call(this);
    -};
    -goog.inherits(goog.ui.media.Mp3, goog.ui.media.MediaRenderer);
    -goog.addSingletonGetter(goog.ui.media.Mp3);
    -
    -
    -/**
    - * Flash player arguments. We expect that {@code flashUrl_} will contain a flash
    - * movie that takes an audioUrl parameter on its URL, containing the URL of the
    - * mp3 to be played.
    - *
    - * @type {string}
    - * @private
    - */
    -goog.ui.media.Mp3.PLAYER_ARGUMENTS_ = 'audioUrl=%s';
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - *
    - * @type {string}
    - */
    -goog.ui.media.Mp3.CSS_CLASS = goog.getCssName('goog-ui-media-mp3');
    -
    -
    -/**
    - * Flash player URL. Uses Google Reader's mp3 flash player by default.
    - *
    - * @type {string}
    - * @private
    - */
    -goog.ui.media.Mp3.flashUrl_ =
    -    'http://www.google.com/reader/ui/3523697345-audio-player.swf';
    -
    -
    -/**
    - * Regular expression to check if a given URL is a valid mp3 URL.
    - *
    - * Copied from http://go/markdownlite.js.
    -
    - *
    - * NOTE(user): although it would be easier to use goog.string.endsWith('.mp3'),
    - * in the future, we want to provide media inlining, which is basically getting
    - * a text and replacing all mp3 references with an mp3 player, so it makes sense
    - * to share the same regular expression to match everything.
    - *
    - * @type {RegExp}
    - */
    -goog.ui.media.Mp3.MATCHER =
    -    /(https?:\/\/[\w-%&\/.=:#\+~\(\)]+\.(mp3)+(\?[\w-%&\/.=:#\+~\(\)]+)?)/i;
    -
    -
    -/**
    - * A static convenient method to construct a goog.ui.media.Media control out of
    - * a mp3 URL. It checks the mp3 URL, sets it as the data model
    - * goog.ui.media.Mp3 renderer uses, sets the states supported by the renderer,
    - * and returns a Control that binds everything together. This is what you
    - * should be using for constructing Mp3 videos, except if you need more fine
    - * control over the configuration.
    - *
    - * @param {goog.ui.media.MediaModel} dataModel A media model that must contain
    - *     an mp3 url on {@code dataModel.getUrl}.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @return {!goog.ui.media.Media} A goog.ui.Control subclass with the mp3
    - *     renderer.
    - */
    -goog.ui.media.Mp3.newControl = function(dataModel, opt_domHelper) {
    -  var control = new goog.ui.media.Media(
    -      dataModel,
    -      goog.ui.media.Mp3.getInstance(),
    -      opt_domHelper);
    -  // mp3 ui doesn't have a non selected view: it shows the mp3 player by
    -  // default.
    -  control.setSelected(true);
    -  return control;
    -};
    -
    -
    -/**
    - * A static method that sets which flash URL this class should use. Use this if
    - * you want to host your own flash mp3 player.
    - *
    - * @param {string} flashUrl The URL of the flash mp3 player.
    - */
    -goog.ui.media.Mp3.setFlashUrl = function(flashUrl) {
    -  goog.ui.media.Mp3.flashUrl_ = flashUrl;
    -};
    -
    -
    -/**
    - * A static method that builds a URL that will contain the flash player that
    - * will play the {@code mp3Url}.
    - *
    - * @param {string} mp3Url The URL of the mp3 music.
    - * @return {string} An URL of a flash player that will know how to play the
    - *     given {@code mp3Url}.
    - */
    -goog.ui.media.Mp3.buildFlashUrl = function(mp3Url) {
    -  var flashUrl = goog.ui.media.Mp3.flashUrl_ + '?' + goog.string.subs(
    -      goog.ui.media.Mp3.PLAYER_ARGUMENTS_,
    -      goog.string.urlEncode(mp3Url));
    -  return flashUrl;
    -};
    -
    -
    -/**
    - * Creates the initial DOM structure of a mp3 video, which is basically a
    - * the flash object pointing to a flash mp3 player.
    - *
    - * @param {goog.ui.Control} c The media control.
    - * @return {!Element} A DOM structure that represents the control.
    - * @override
    - */
    -goog.ui.media.Mp3.prototype.createDom = function(c) {
    -  var control = /** @type {goog.ui.media.Media} */ (c);
    -  var div = goog.ui.media.Mp3.superClass_.createDom.call(this, control);
    -
    -  var dataModel =
    -      /** @type {goog.ui.media.MediaModel} */ (control.getDataModel());
    -  var flash = new goog.ui.media.FlashObject(
    -      dataModel.getPlayer().getTrustedResourceUrl(), control.getDomHelper());
    -  flash.setFlashVar('playerMode', 'embedded');
    -  flash.render(div);
    -
    -  return div;
    -};
    -
    -
    -/**
    - * Returns the CSS class to be applied to the root element of components
    - * rendered using this renderer.
    - * @return {string} Renderer-specific CSS class.
    - * @override
    - */
    -goog.ui.media.Mp3.prototype.getCssClass = function() {
    -  return goog.ui.media.Mp3.CSS_CLASS;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/mp3_test.html b/src/database/third_party/closure-library/closure/goog/ui/media/mp3_test.html
    deleted file mode 100644
    index 37a61ecdb9c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/mp3_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.media.Mp3
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.ui.media.Mp3Test');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/mp3_test.js b/src/database/third_party/closure-library/closure/goog/ui/media/mp3_test.js
    deleted file mode 100644
    index 5456c04f490..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/mp3_test.js
    +++ /dev/null
    @@ -1,66 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.media.Mp3Test');
    -goog.setTestOnly('goog.ui.media.Mp3Test');
    -
    -goog.require('goog.dom');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.media.FlashObject');
    -goog.require('goog.ui.media.Media');
    -goog.require('goog.ui.media.MediaModel');
    -goog.require('goog.ui.media.Mp3');
    -var mp3;
    -var control;
    -var MP3_URL = 'http://www.shellworld.net/~davidsky/surf-oxy.mp3';
    -var parent = goog.dom.createElement('div');
    -
    -function setUp() {
    -  mp3 = goog.ui.media.Mp3.getInstance();
    -  var flashUrl = goog.ui.media.Mp3.buildFlashUrl(MP3_URL);
    -  var model = new goog.ui.media.MediaModel(MP3_URL, 'mp3 caption', '');
    -  model.setPlayer(new goog.ui.media.MediaModel.Player(flashUrl));
    -  control = new goog.ui.media.Media(model, mp3);
    -  control.setSelected(true);
    -}
    -
    -function tearDown() {
    -  control.dispose();
    -}
    -
    -function testBasicRendering() {
    -  control.render(parent);
    -  var el = goog.dom.getElementsByTagNameAndClass(
    -      'div', goog.ui.media.Mp3.CSS_CLASS, parent);
    -  assertEquals(1, el.length);
    -}
    -
    -function testParsingUrl() {
    -  assertTrue(goog.ui.media.Mp3.MATCHER.test(MP3_URL));
    -  assertFalse(
    -      goog.ui.media.Mp3.MATCHER.test('http://invalidUrl/filename.doc'));
    -}
    -
    -function testCreatingDomOnInitialState() {
    -  control.render(parent);
    -  var caption = goog.dom.getElementsByTagNameAndClass(
    -      'div',
    -      goog.ui.media.Mp3.CSS_CLASS + '-caption',
    -      parent);
    -  assertEquals(1, caption.length);
    -
    -  var flash = goog.dom.getElementsByTagNameAndClass(
    -      undefined, goog.ui.media.FlashObject.CSS_CLASS, parent);
    -  assertEquals(1, flash.length);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/photo.js b/src/database/third_party/closure-library/closure/goog/ui/media/photo.js
    deleted file mode 100644
    index b2a9fa3fdb0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/photo.js
    +++ /dev/null
    @@ -1,143 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview provides a reusable photo UI component that renders photos that
    - * contains metadata (such as captions, description, thumbnail/high resolution
    - * versions, etc).
    - *
    - * goog.ui.media.Photo is actually a {@link goog.ui.ControlRenderer},
    - * a stateless class - that could/should be used as a Singleton with the static
    - * method {@code goog.ui.media.Photo.getInstance} -, that knows how to render
    - * Photos. It is designed to be used with a {@link goog.ui.Control}, which will
    - * actually control the media renderer and provide the {@link goog.ui.Component}
    - * base. This design guarantees that all different types of medias will behave
    - * alike but will look different.
    - *
    - * goog.ui.media.Photo expects {@code goog.ui.media.MediaModel} on
    - * {@code goog.ui.Control.getModel} as data models.
    - *
    - * Example of usage:
    - *
    - * <pre>
    - *   var photo = goog.ui.media.Photo.newControl(
    - *       new goog.ui.media.MediaModel('http://hostname/file.jpg'));
    - *   photo.render(goog.dom.getElement('parent'));
    - * </pre>
    - *
    - * Photo medias currently support the following states:
    - *
    - * <ul>
    - *   <li> {@link goog.ui.Component.State.HOVER}: mouse cursor is over the photo.
    - *   <li> {@link goog.ui.Component.State.SELECTED}: photo is being displayed.
    - * </ul>
    - *
    - * Which can be accessed by
    - *
    - * <pre>
    - *   photo.setHighlighted(true);
    - *   photo.setSelected(true);
    - * </pre>
    - *
    - */
    -
    -goog.provide('goog.ui.media.Photo');
    -
    -goog.require('goog.ui.media.Media');
    -goog.require('goog.ui.media.MediaRenderer');
    -
    -
    -
    -/**
    - * Subclasses a goog.ui.media.MediaRenderer to provide a Photo specific media
    - * renderer. Provides a base class for any other renderer that wants to display
    - * photos.
    - *
    - * This class is meant to be used as a singleton static stateless class, that
    - * takes {@code goog.ui.media.Media} instances and renders it.
    - *
    - * This design is patterned after
    - * http://go/closure_control_subclassing
    - *
    - * @constructor
    - * @extends {goog.ui.media.MediaRenderer}
    - * @final
    - */
    -goog.ui.media.Photo = function() {
    -  goog.ui.media.MediaRenderer.call(this);
    -};
    -goog.inherits(goog.ui.media.Photo, goog.ui.media.MediaRenderer);
    -goog.addSingletonGetter(goog.ui.media.Photo);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - *
    - * @type {string}
    - */
    -goog.ui.media.Photo.CSS_CLASS = goog.getCssName('goog-ui-media-photo');
    -
    -
    -/**
    - * A static convenient method to construct a goog.ui.media.Media control out of
    - * a photo {@code goog.ui.media.MediaModel}. It sets it as the data model
    - * goog.ui.media.Photo renderer uses, sets the states supported by the renderer,
    - * and returns a Control that binds everything together. This is what you
    - * should be using for constructing Photos, except if you need finer control
    - * over the configuration.
    - *
    - * @param {goog.ui.media.MediaModel} dataModel The photo data model.
    - * @return {!goog.ui.media.Media} A goog.ui.Control subclass with the photo
    - *     renderer.
    - */
    -goog.ui.media.Photo.newControl = function(dataModel) {
    -  var control = new goog.ui.media.Media(
    -      dataModel,
    -      goog.ui.media.Photo.getInstance());
    -  return control;
    -};
    -
    -
    -/**
    - * Creates the initial DOM structure of a photo.
    - *
    - * @param {goog.ui.Control} c The media control.
    - * @return {!Element} A DOM structure that represents the control.
    - * @override
    - */
    -goog.ui.media.Photo.prototype.createDom = function(c) {
    -  var control = /** @type {goog.ui.media.Media} */ (c);
    -  var div = goog.ui.media.Photo.superClass_.createDom.call(this, control);
    -
    -  var img = control.getDomHelper().createDom('img', {
    -    src: control.getDataModel().getPlayer().getUrl(),
    -    className: goog.getCssName(this.getCssClass(), 'image')
    -  });
    -
    -  div.appendChild(img);
    -
    -  return div;
    -};
    -
    -
    -/**
    - * Returns the CSS class to be applied to the root element of components
    - * rendered using this renderer.
    - * @return {string} Renderer-specific CSS class.
    - * @override
    - */
    -goog.ui.media.Photo.prototype.getCssClass = function() {
    -  return goog.ui.media.Photo.CSS_CLASS;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/photo_test.html b/src/database/third_party/closure-library/closure/goog/ui/media/photo_test.html
    deleted file mode 100644
    index e29c32e943b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/photo_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.media.Photo
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.ui.media.PhotoTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/photo_test.js b/src/database/third_party/closure-library/closure/goog/ui/media/photo_test.js
    deleted file mode 100644
    index 580f7e1fb97..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/photo_test.js
    +++ /dev/null
    @@ -1,49 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.media.PhotoTest');
    -goog.setTestOnly('goog.ui.media.PhotoTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.media.MediaModel');
    -goog.require('goog.ui.media.Photo');
    -var control;
    -var PHOTO_URL = 'http://foo/bar.jpg';
    -
    -function setUp() {
    -  var photo = new goog.ui.media.MediaModel(PHOTO_URL, 'title', 'description');
    -  photo.setPlayer(new goog.ui.media.MediaModel.Player(PHOTO_URL));
    -  control = goog.ui.media.Photo.newControl(photo);
    -}
    -
    -function tearDown() {
    -  control.dispose();
    -}
    -
    -function testBasicRendering() {
    -  control.render();
    -  var el = goog.dom.getElementsByTagNameAndClass('div',
    -      goog.ui.media.Photo.CSS_CLASS);
    -  assertEquals(1, el.length);
    -  var img = goog.dom.getElementsByTagNameAndClass('img',
    -      goog.ui.media.Photo.CSS_CLASS + '-image');
    -  assertEquals(1, img.length);
    -  var caption = goog.dom.getElementsByTagNameAndClass('div',
    -      goog.ui.media.Photo.CSS_CLASS + '-caption');
    -  assertEquals(1, caption.length);
    -  var content = goog.dom.getElementsByTagNameAndClass('div',
    -      goog.ui.media.Photo.CSS_CLASS + '-description');
    -  assertEquals(1, content.length);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/picasa.js b/src/database/third_party/closure-library/closure/goog/ui/media/picasa.js
    deleted file mode 100644
    index b61d17e8f2b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/picasa.js
    +++ /dev/null
    @@ -1,327 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview provides a reusable picasa album UI component given a public
    - * picasa album URL.
    - *
    - * TODO(user): implement the javascript viewer, for users without flash. Get it
    - * from the Gmail Picasa gadget.
    - *
    - * goog.ui.media.PicasaAlbum is actually a {@link goog.ui.ControlRenderer}, a
    - * stateless class - that could/should be used as a Singleton with the static
    - * method {@code goog.ui.media.PicasaAlbum.getInstance} -, that knows how to
    - * render picasa albums. It is designed to be used with a
    - * {@link goog.ui.Control}, which will actually control the media renderer and
    - * provide the {@link goog.ui.Component} base. This design guarantees that all
    - * different types of medias will behave alike but will look different.
    - *
    - * goog.ui.media.PicasaAlbum expects {@code goog.ui.media.PicasaAlbumModel}s on
    - * {@code goog.ui.Control.getModel} as data models, and render a flash object
    - * that will show a slideshow with the contents of that album URL.
    - *
    - * Example of usage:
    - *
    - * <pre>
    - *   var album = goog.ui.media.PicasaAlbumModel.newInstance(
    - *       'http://picasaweb.google.com/username/SanFranciscoCalifornia');
    - *   goog.ui.media.PicasaAlbum.newControl(album).render();
    - * </pre>
    - *
    - * picasa medias currently support the following states:
    - *
    - * <ul>
    - *   <li> {@link goog.ui.Component.State.DISABLED}: shows 'flash not available'
    - *   <li> {@link goog.ui.Component.State.HOVER}: mouse cursor is over the album
    - *   <li> {@link goog.ui.Component.State.SELECTED}: flash album is shown
    - * </ul>
    - *
    - * Which can be accessed by
    - *
    - * <pre>
    - *   picasa.setEnabled(true);
    - *   picasa.setHighlighted(true);
    - *   picasa.setSelected(true);
    - * </pre>
    - *
    - *
    - * @supported IE6, FF2+, Safari. Requires flash to actually work.
    - *
    - * TODO(user): test on other browsers
    - */
    -
    -goog.provide('goog.ui.media.PicasaAlbum');
    -goog.provide('goog.ui.media.PicasaAlbumModel');
    -
    -goog.require('goog.html.TrustedResourceUrl');
    -goog.require('goog.string.Const');
    -goog.require('goog.ui.media.FlashObject');
    -goog.require('goog.ui.media.Media');
    -goog.require('goog.ui.media.MediaModel');
    -goog.require('goog.ui.media.MediaRenderer');
    -
    -
    -
    -/**
    - * Subclasses a goog.ui.media.MediaRenderer to provide a Picasa specific media
    - * renderer.
    - *
    - * This class knows how to parse picasa URLs, and render the DOM structure
    - * of picasa album players and previews. This class is meant to be used as a
    - * singleton static stateless class, that takes {@code goog.ui.media.Media}
    - * instances and renders it. It expects {@code goog.ui.media.Media.getModel} to
    - * return a well formed, previously constructed, object with a user and album
    - * fields {@see goog.ui.media.PicasaAlbum.parseUrl}, which is the data model
    - * this renderer will use to construct the DOM structure.
    - * {@see goog.ui.media.PicasaAlbum.newControl} for a example of constructing a
    - * control with this renderer.
    - *
    - * goog.ui.media.PicasaAlbum currently displays a picasa-made flash slideshow
    - * with the photos, but could possibly display a handwritten js photo viewer,
    - * in case flash is not available.
    - *
    - * This design is patterned after http://go/closure_control_subclassing
    - *
    - * It uses {@link goog.ui.media.FlashObject} to embed the flash object.
    - *
    - * @constructor
    - * @extends {goog.ui.media.MediaRenderer}
    - * @final
    - */
    -goog.ui.media.PicasaAlbum = function() {
    -  goog.ui.media.MediaRenderer.call(this);
    -};
    -goog.inherits(goog.ui.media.PicasaAlbum, goog.ui.media.MediaRenderer);
    -goog.addSingletonGetter(goog.ui.media.PicasaAlbum);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - *
    - * @type {string}
    - */
    -goog.ui.media.PicasaAlbum.CSS_CLASS = goog.getCssName('goog-ui-media-picasa');
    -
    -
    -/**
    - * A static convenient method to construct a goog.ui.media.Media control out of
    - * a picasa data model. It sets it as the data model goog.ui.media.PicasaAlbum
    - * renderer uses, sets the states supported by the renderer, and returns a
    - * Control that binds everything together. This is what you should be using for
    - * constructing Picasa albums, except if you need finer control over the
    - * configuration.
    - *
    - * @param {goog.ui.media.PicasaAlbumModel} dataModel A picasa album data model.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @return {!goog.ui.media.Media} A Control instance binded to the Picasa
    - *     renderer.
    - */
    -goog.ui.media.PicasaAlbum.newControl = function(dataModel, opt_domHelper) {
    -  var control = new goog.ui.media.Media(
    -      dataModel,
    -      goog.ui.media.PicasaAlbum.getInstance(),
    -      opt_domHelper);
    -  control.setSelected(true);
    -  return control;
    -};
    -
    -
    -/**
    - * Creates the initial DOM structure of the picasa album, which is basically a
    - * the flash object pointing to a flash picasa album player.
    - *
    - * @param {goog.ui.Control} c The media control.
    - * @return {!Element} The DOM structure that represents the control.
    - * @override
    - */
    -goog.ui.media.PicasaAlbum.prototype.createDom = function(c) {
    -  var control = /** @type {goog.ui.media.Media} */ (c);
    -  var div = goog.ui.media.PicasaAlbum.superClass_.createDom.call(this, control);
    -
    -  var picasaAlbum =
    -      /** @type {goog.ui.media.PicasaAlbumModel} */ (control.getDataModel());
    -  var authParam =
    -      picasaAlbum.getAuthKey() ? ('&authkey=' + picasaAlbum.getAuthKey()) : '';
    -  var flash = new goog.ui.media.FlashObject(
    -      picasaAlbum.getPlayer().getTrustedResourceUrl(),
    -      control.getDomHelper());
    -  flash.addFlashVars(picasaAlbum.getPlayer().getVars());
    -  flash.render(div);
    -
    -  return div;
    -};
    -
    -
    -/**
    - * Returns the CSS class to be applied to the root element of components
    - * rendered using this renderer.
    - * @return {string} Renderer-specific CSS class.
    - * @override
    - */
    -goog.ui.media.PicasaAlbum.prototype.getCssClass = function() {
    -  return goog.ui.media.PicasaAlbum.CSS_CLASS;
    -};
    -
    -
    -
    -/**
    - * The {@code goog.ui.media.PicasaAlbum} media data model. It stores a required
    - * {@code userId} and {@code albumId} fields, sets the picasa album URL, and
    - * allows a few optional parameters.
    - *
    - * @param {string} userId The picasa userId associated with this album.
    - * @param {string} albumId The picasa albumId associated with this album.
    - * @param {string=} opt_authKey An optional authentication key, used on private
    - *     albums.
    - * @param {string=} opt_caption An optional caption of the picasa album.
    - * @param {string=} opt_description An optional description of the picasa album.
    - * @param {boolean=} opt_autoplay Whether to autoplay the slideshow.
    - * @constructor
    - * @extends {goog.ui.media.MediaModel}
    - * @final
    - */
    -goog.ui.media.PicasaAlbumModel = function(userId,
    -                                          albumId,
    -                                          opt_authKey,
    -                                          opt_caption,
    -                                          opt_description,
    -                                          opt_autoplay) {
    -  goog.ui.media.MediaModel.call(
    -      this,
    -      goog.ui.media.PicasaAlbumModel.buildUrl(userId, albumId),
    -      opt_caption,
    -      opt_description,
    -      goog.ui.media.MediaModel.MimeType.FLASH);
    -
    -  /**
    -   * The Picasa user id.
    -   * @type {string}
    -   * @private
    -   */
    -  this.userId_ = userId;
    -
    -  /**
    -   * The Picasa album id.
    -   * @type {string}
    -   * @private
    -   */
    -  this.albumId_ = albumId;
    -
    -  /**
    -   * The Picasa authentication key, used on private albums.
    -   * @type {?string}
    -   * @private
    -   */
    -  this.authKey_ = opt_authKey || null;
    -
    -  var authParam = opt_authKey ? ('&authkey=' + opt_authKey) : '';
    -
    -  var flashVars = {
    -    'host': 'picasaweb.google.com',
    -    'RGB': '0x000000',
    -    'feed': 'http://picasaweb.google.com/data/feed/api/user/' +
    -        userId + '/album/' + albumId + '?kind=photo&alt=rss' + authParam
    -  };
    -  flashVars[opt_autoplay ? 'autoplay' : 'noautoplay'] = '1';
    -
    -  var flashUrl = goog.html.TrustedResourceUrl.fromConstant(
    -      goog.string.Const.from(
    -          'http://picasaweb.google.com/s/c/bin/slideshow.swf'));
    -  var player = new goog.ui.media.MediaModel.Player(flashUrl, flashVars);
    -
    -  this.setPlayer(player);
    -};
    -goog.inherits(goog.ui.media.PicasaAlbumModel, goog.ui.media.MediaModel);
    -
    -
    -/**
    - * Regular expression used to extract the picasa username and albumid out of
    - * picasa URLs.
    - *
    - * Copied from http://go/markdownlite.js,
    - * and {@link PicasaWebExtractor.xml}.
    - *
    - * @type {RegExp}
    - * @private
    - * @const
    - */
    -goog.ui.media.PicasaAlbumModel.MATCHER_ =
    -    /https?:\/\/(?:www\.)?picasaweb\.(?:google\.)?com\/([\d\w\.]+)\/([\d\w_\-\.]+)(?:\?[\w\d\-_=&amp;;\.]*&?authKey=([\w\d\-_=;\.]+))?(?:#([\d]+)?)?/im;
    -
    -
    -/**
    - * Gets a {@code picasaUrl} and extracts the user and album id.
    - *
    - * @param {string} picasaUrl A picasa album URL.
    - * @param {string=} opt_caption An optional caption of the picasa album.
    - * @param {string=} opt_description An optional description of the picasa album.
    - * @param {boolean=} opt_autoplay Whether to autoplay the slideshow.
    - * @return {!goog.ui.media.PicasaAlbumModel} The picasa album data model that
    - *     represents the picasa URL.
    - * @throws exception in case the parsing fails
    - */
    -goog.ui.media.PicasaAlbumModel.newInstance = function(picasaUrl,
    -                                                      opt_caption,
    -                                                      opt_description,
    -                                                      opt_autoplay) {
    -  if (goog.ui.media.PicasaAlbumModel.MATCHER_.test(picasaUrl)) {
    -    var data = goog.ui.media.PicasaAlbumModel.MATCHER_.exec(picasaUrl);
    -    return new goog.ui.media.PicasaAlbumModel(
    -        data[1], data[2], data[3], opt_caption, opt_description, opt_autoplay);
    -  }
    -  throw Error('failed to parse user and album from picasa url: ' + picasaUrl);
    -};
    -
    -
    -/**
    - * The opposite of {@code newInstance}: takes an {@code userId} and an
    - * {@code albumId} and builds a URL.
    - *
    - * @param {string} userId The user that owns the album.
    - * @param {string} albumId The album id.
    - * @return {string} The URL of the album.
    - */
    -goog.ui.media.PicasaAlbumModel.buildUrl = function(userId, albumId) {
    -  return 'http://picasaweb.google.com/' + userId + '/' + albumId;
    -};
    -
    -
    -/**
    - * Gets the Picasa user id.
    - * @return {string} The Picasa user id.
    - */
    -goog.ui.media.PicasaAlbumModel.prototype.getUserId = function() {
    -  return this.userId_;
    -};
    -
    -
    -/**
    - * Gets the Picasa album id.
    - * @return {string} The Picasa album id.
    - */
    -goog.ui.media.PicasaAlbumModel.prototype.getAlbumId = function() {
    -  return this.albumId_;
    -};
    -
    -
    -/**
    - * Gets the Picasa album authentication key.
    - * @return {?string} The Picasa album authentication key.
    - */
    -goog.ui.media.PicasaAlbumModel.prototype.getAuthKey = function() {
    -  return this.authKey_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/picasa_test.html b/src/database/third_party/closure-library/closure/goog/ui/media/picasa_test.html
    deleted file mode 100644
    index 9d60c989808..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/picasa_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.media.Picasa
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.ui.media.PicasaTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/picasa_test.js b/src/database/third_party/closure-library/closure/goog/ui/media/picasa_test.js
    deleted file mode 100644
    index 4e44d4dd811..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/picasa_test.js
    +++ /dev/null
    @@ -1,110 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.media.PicasaTest');
    -goog.setTestOnly('goog.ui.media.PicasaTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.media.FlashObject');
    -goog.require('goog.ui.media.Media');
    -goog.require('goog.ui.media.PicasaAlbum');
    -goog.require('goog.ui.media.PicasaAlbumModel');
    -var picasa;
    -var control;
    -var PICASA_USERNAME = 'username';
    -var PICASA_ALBUM = 'albumname';
    -var PICASA_URL = 'http://picasaweb.google.com/' + PICASA_USERNAME + '/' +
    -    PICASA_ALBUM;
    -var parent = goog.dom.createElement('div');
    -
    -function setUp() {
    -  picasa = new goog.ui.media.PicasaAlbum();
    -  var model = new goog.ui.media.PicasaAlbumModel(PICASA_USERNAME,
    -      PICASA_ALBUM, null, 'album title');
    -  control = new goog.ui.media.Media(model, picasa);
    -  control.setSelected(true);
    -}
    -
    -function tearDown() {
    -  control.dispose();
    -}
    -
    -function testBasicRendering() {
    -  control.render(parent);
    -  var el = goog.dom.getElementsByTagNameAndClass(
    -      'div', goog.ui.media.PicasaAlbum.CSS_CLASS, parent);
    -  assertEquals(1, el.length);
    -  assertEquals(PICASA_URL, control.getDataModel().getUrl());
    -}
    -
    -function testParsingUrl() {
    -  assertExtractsCorrectly(PICASA_USERNAME, PICASA_ALBUM, null, PICASA_URL);
    -  assertExtractsCorrectly('foo', 'bar', null,
    -      'https://picasaweb.google.com/foo/bar');
    -  assertExtractsCorrectly('foo', 'bar', null,
    -      'https://www.picasaweb.google.com/foo/bar');
    -  assertExtractsCorrectly('foo', 'bar', null,
    -      'https://www.picasaweb.com/foo/bar');
    -  assertExtractsCorrectly('foo', 'bar', '8Hzg1CUUAZM',
    -      'https://www.picasaweb.com/foo/bar?authkey=8Hzg1CUUAZM#');
    -  assertExtractsCorrectly('foo', 'bar', '8Hzg1CUUAZM',
    -      'https://www.picasaweb.com/foo/bar?foo=bar&authkey=8Hzg1CUUAZM#');
    -  assertExtractsCorrectly('foo', 'bar', '8Hzg1CUUAZM',
    -      'https://www.picasaweb.com/foo/bar?foo=bar&authkey=8Hzg1CUUAZM&' +
    -          'hello=world#');
    -
    -  var invalidUrl = 'http://invalidUrl/watch?v=dMH0bHeiRNg';
    -  var e = assertThrows('parser expects a well formed URL', function() {
    -    goog.ui.media.PicasaAlbumModel.newInstance(invalidUrl);
    -  });
    -  assertEquals(
    -      'failed to parse user and album from picasa url: ' + invalidUrl,
    -      e.message);
    -}
    -
    -function testBuildingUrl() {
    -  assertEquals(PICASA_URL,
    -      goog.ui.media.PicasaAlbumModel.buildUrl(PICASA_USERNAME, PICASA_ALBUM));
    -}
    -
    -function testCreatingModel() {
    -  var model = new goog.ui.media.PicasaAlbumModel(
    -      PICASA_USERNAME, PICASA_ALBUM);
    -  assertEquals(PICASA_USERNAME, model.getUserId());
    -  assertEquals(PICASA_ALBUM, model.getAlbumId());
    -  assertEquals(PICASA_URL, model.getUrl());
    -  assertUndefined(model.getCaption());
    -}
    -
    -function testCreatingDomOnInitialState() {
    -  control.render(parent);
    -  var caption = goog.dom.getElementsByTagNameAndClass(
    -      'div',
    -      goog.ui.media.PicasaAlbum.CSS_CLASS + '-caption',
    -      parent);
    -  assertEquals(1, caption.length);
    -
    -  var flash = goog.dom.getElementsByTagNameAndClass(
    -      'div', goog.ui.media.FlashObject.CSS_CLASS, parent);
    -  assertEquals(1, flash.length);
    -}
    -
    -function assertExtractsCorrectly(
    -    expectedUserId, expectedAlbumId, expectedAuthKey, url) {
    -  var model = goog.ui.media.PicasaAlbumModel.newInstance(url);
    -  assertEquals('User for ' + url, expectedUserId, model.getUserId());
    -  assertEquals('Album for ' + url, expectedAlbumId, model.getAlbumId());
    -  assertEquals('AuthKey for ' + url, expectedAuthKey, model.getAuthKey());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/vimeo.js b/src/database/third_party/closure-library/closure/goog/ui/media/vimeo.js
    deleted file mode 100644
    index 92ef50d3c62..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/vimeo.js
    +++ /dev/null
    @@ -1,278 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview provides a reusable Vimeo video UI component given a public
    - * Vimeo video URL.
    - *
    - * goog.ui.media.Vimeo is actually a {@link goog.ui.ControlRenderer}, a
    - * stateless class - that could/should be used as a Singleton with the static
    - * method {@code goog.ui.media.Vimeo.getInstance} -, that knows how to render
    - * video videos. It is designed to be used with a {@link goog.ui.Control},
    - * which will actually control the media renderer and provide the
    - * {@link goog.ui.Component} base. This design guarantees that all different
    - * types of medias will behave alike but will look different.
    - *
    - * goog.ui.media.Vimeo expects vimeo video IDs on
    - * {@code goog.ui.Control.getModel} as data models, and renders a flash object
    - * that will show the contents of that video.
    - *
    - * Example of usage:
    - *
    - * <pre>
    - *   var video = goog.ui.media.VimeoModel.newInstance('http://vimeo.com/30012');
    - *   goog.ui.media.Vimeo.newControl(video).render();
    - * </pre>
    - *
    - * Vimeo medias currently support the following states:
    - *
    - * <ul>
    - *   <li> {@link goog.ui.Component.State.DISABLED}: shows 'flash not available'
    - *   <li> {@link goog.ui.Component.State.HOVER}: mouse cursor is over the video
    - *   <li> {@link goog.ui.Component.State.SELECTED}: flash video is shown
    - * </ul>
    - *
    - * Which can be accessed by
    - * <pre>
    - *   video.setEnabled(true);
    - *   video.setHighlighted(true);
    - *   video.setSelected(true);
    - * </pre>
    - *
    - *
    - * @supported IE6, FF2+, Safari. Requires flash to actually work.
    - *
    - * TODO(user): test on other browsers
    - */
    -
    -goog.provide('goog.ui.media.Vimeo');
    -goog.provide('goog.ui.media.VimeoModel');
    -
    -goog.require('goog.string');
    -goog.require('goog.ui.media.FlashObject');
    -goog.require('goog.ui.media.Media');
    -goog.require('goog.ui.media.MediaModel');
    -goog.require('goog.ui.media.MediaRenderer');
    -
    -
    -
    -/**
    - * Subclasses a goog.ui.media.MediaRenderer to provide a Vimeo specific media
    - * renderer.
    - *
    - * This class knows how to parse Vimeo URLs, and render the DOM structure
    - * of vimeo video players. This class is meant to be used as a singleton static
    - * stateless class, that takes {@code goog.ui.media.Media} instances and renders
    - * it. It expects {@code goog.ui.media.Media.getModel} to return a well formed,
    - * previously constructed, vimeoId {@see goog.ui.media.Vimeo.parseUrl}, which is
    - * the data model this renderer will use to construct the DOM structure.
    - * {@see goog.ui.media.Vimeo.newControl} for a example of constructing a control
    - * with this renderer.
    - *
    - * This design is patterned after http://go/closure_control_subclassing
    - *
    - * It uses {@link goog.ui.media.FlashObject} to embed the flash object.
    - *
    - * @constructor
    - * @extends {goog.ui.media.MediaRenderer}
    - * @final
    - */
    -goog.ui.media.Vimeo = function() {
    -  goog.ui.media.MediaRenderer.call(this);
    -};
    -goog.inherits(goog.ui.media.Vimeo, goog.ui.media.MediaRenderer);
    -goog.addSingletonGetter(goog.ui.media.Vimeo);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - *
    - * @type {string}
    - */
    -goog.ui.media.Vimeo.CSS_CLASS = goog.getCssName('goog-ui-media-vimeo');
    -
    -
    -/**
    - * A static convenient method to construct a goog.ui.media.Media control out of
    - * a Vimeo URL. It extracts the videoId information on the URL, sets it
    - * as the data model goog.ui.media.Vimeo renderer uses, sets the states
    - * supported by the renderer, and returns a Control that binds everything
    - * together. This is what you should be using for constructing Vimeo videos,
    - * except if you need more fine control over the configuration.
    - *
    - * @param {goog.ui.media.VimeoModel} dataModel A vimeo video URL.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @return {!goog.ui.media.Media} A Control binded to the Vimeo renderer.
    - */
    -goog.ui.media.Vimeo.newControl = function(dataModel, opt_domHelper) {
    -  var control = new goog.ui.media.Media(
    -      dataModel, goog.ui.media.Vimeo.getInstance(), opt_domHelper);
    -  // vimeo videos don't have any thumbnail for now, so we show the
    -  // "selected" version of the UI at the start, which is the
    -  // flash player.
    -  control.setSelected(true);
    -  return control;
    -};
    -
    -
    -/**
    - * Creates the initial DOM structure of the vimeo video, which is basically a
    - * the flash object pointing to a vimeo video player.
    - *
    - * @param {goog.ui.Control} c The media control.
    - * @return {!Element} The DOM structure that represents this control.
    - * @override
    - */
    -goog.ui.media.Vimeo.prototype.createDom = function(c) {
    -  var control = /** @type {goog.ui.media.Media} */ (c);
    -  var div = goog.ui.media.Vimeo.superClass_.createDom.call(this, control);
    -
    -  var dataModel =
    -      /** @type {goog.ui.media.VimeoModel} */ (control.getDataModel());
    -
    -  var flash = new goog.ui.media.FlashObject(
    -      dataModel.getPlayer().getTrustedResourceUrl(),
    -      control.getDomHelper());
    -  flash.render(div);
    -
    -  return div;
    -};
    -
    -
    -/**
    - * Returns the CSS class to be applied to the root element of components
    - * rendered using this renderer.
    - * @return {string} Renderer-specific CSS class.
    - * @override
    - */
    -goog.ui.media.Vimeo.prototype.getCssClass = function() {
    -  return goog.ui.media.Vimeo.CSS_CLASS;
    -};
    -
    -
    -
    -/**
    - * The {@code goog.ui.media.Vimeo} media data model. It stores a required
    - * {@code videoId} field, sets the vimeo URL, and allows a few optional
    - * parameters.
    - *
    - * @param {string} videoId The vimeo video id.
    - * @param {string=} opt_caption An optional caption of the vimeo video.
    - * @param {string=} opt_description An optional description of the vimeo video.
    - * @param {boolean=} opt_autoplay Whether to autoplay video.
    - * @constructor
    - * @extends {goog.ui.media.MediaModel}
    - * @final
    - */
    -goog.ui.media.VimeoModel = function(videoId, opt_caption, opt_description,
    -                                    opt_autoplay) {
    -  goog.ui.media.MediaModel.call(
    -      this,
    -      goog.ui.media.VimeoModel.buildUrl(videoId),
    -      opt_caption,
    -      opt_description,
    -      goog.ui.media.MediaModel.MimeType.FLASH);
    -
    -  /**
    -   * The Vimeo video id.
    -   * @type {string}
    -   * @private
    -   */
    -  this.videoId_ = videoId;
    -
    -  this.setPlayer(new goog.ui.media.MediaModel.Player(
    -      goog.ui.media.VimeoModel.buildFlashUrl(videoId, opt_autoplay)));
    -};
    -goog.inherits(goog.ui.media.VimeoModel, goog.ui.media.MediaModel);
    -
    -
    -/**
    - * Regular expression used to extract the vimeo video id out of vimeo URLs.
    - *
    - * Copied from http://go/markdownlite.js
    - *
    - * TODO(user): add support to https.
    - *
    - * @type {RegExp}
    - * @private
    - * @const
    - */
    -goog.ui.media.VimeoModel.MATCHER_ =
    -    /https?:\/\/(?:www\.)?vimeo\.com\/(?:hd#)?([0-9]+)/i;
    -
    -
    -/**
    - * Takes a {@code vimeoUrl} and extracts the video id.
    - *
    - * @param {string} vimeoUrl A vimeo video URL.
    - * @param {string=} opt_caption An optional caption of the vimeo video.
    - * @param {string=} opt_description An optional description of the vimeo video.
    - * @param {boolean=} opt_autoplay Whether to autoplay video.
    - * @return {!goog.ui.media.VimeoModel} The vimeo data model that represents this
    - *     URL.
    - * @throws exception in case the parsing fails
    - */
    -goog.ui.media.VimeoModel.newInstance = function(vimeoUrl,
    -                                                opt_caption,
    -                                                opt_description,
    -                                                opt_autoplay) {
    -  if (goog.ui.media.VimeoModel.MATCHER_.test(vimeoUrl)) {
    -    var data = goog.ui.media.VimeoModel.MATCHER_.exec(vimeoUrl);
    -    return new goog.ui.media.VimeoModel(
    -        data[1], opt_caption, opt_description, opt_autoplay);
    -  }
    -  throw Error('failed to parse vimeo url: ' + vimeoUrl);
    -};
    -
    -
    -/**
    - * The opposite of {@code goog.ui.media.Vimeo.parseUrl}: it takes a videoId
    - * and returns a vimeo URL.
    - *
    - * @param {string} videoId The vimeo video ID.
    - * @return {string} The vimeo URL.
    - */
    -goog.ui.media.VimeoModel.buildUrl = function(videoId) {
    -  return 'http://vimeo.com/' + goog.string.urlEncode(videoId);
    -};
    -
    -
    -/**
    - * Builds a flash url from the vimeo {@code videoId}.
    - *
    - * @param {string} videoId The vimeo video ID.
    - * @param {boolean=} opt_autoplay Whether the flash movie should start playing
    - *     as soon as it is shown, or if it should show a 'play' button.
    - * @return {string} The vimeo flash URL.
    - */
    -goog.ui.media.VimeoModel.buildFlashUrl = function(videoId, opt_autoplay) {
    -  var autoplay = opt_autoplay ? '&autoplay=1' : '';
    -  return 'http://vimeo.com/moogaloop.swf?clip_id=' +
    -      goog.string.urlEncode(videoId) +
    -      '&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0color=&' +
    -      'fullscreen=1' + autoplay;
    -};
    -
    -
    -/**
    - * Gets the Vimeo video id.
    - * @return {string} The Vimeo video id.
    - */
    -goog.ui.media.VimeoModel.prototype.getVideoId = function() {
    -  return this.videoId_;
    -};
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/vimeo_test.html b/src/database/third_party/closure-library/closure/goog/ui/media/vimeo_test.html
    deleted file mode 100644
    index 66dfa290325..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/vimeo_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.media.Vimeo
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.ui.media.VimeoTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/vimeo_test.js b/src/database/third_party/closure-library/closure/goog/ui/media/vimeo_test.js
    deleted file mode 100644
    index db7f6d9f8cf..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/vimeo_test.js
    +++ /dev/null
    @@ -1,91 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.media.VimeoTest');
    -goog.setTestOnly('goog.ui.media.VimeoTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.media.FlashObject');
    -goog.require('goog.ui.media.Media');
    -goog.require('goog.ui.media.Vimeo');
    -goog.require('goog.ui.media.VimeoModel');
    -var vimeo;
    -var control;
    -var VIMEO_ID = '3001295';
    -var VIMEO_URL = 'http://vimeo.com/' + VIMEO_ID;
    -var VIMEO_URL_HD = 'http://vimeo.com/hd#' + VIMEO_ID;
    -var VIMEO_URL_SECURE = 'https://vimeo.com/' + VIMEO_ID;
    -var parent = goog.dom.createElement('div');
    -
    -function setUp() {
    -  vimeo = new goog.ui.media.Vimeo();
    -  var model = new goog.ui.media.VimeoModel(VIMEO_ID, 'vimeo caption');
    -  control = new goog.ui.media.Media(model, vimeo);
    -  control.setSelected(true);
    -}
    -
    -function tearDown() {
    -  control.dispose();
    -}
    -
    -function testBasicRendering() {
    -  control.render(parent);
    -  var el = goog.dom.getElementsByTagNameAndClass(
    -      'div', goog.ui.media.Vimeo.CSS_CLASS, parent);
    -  assertEquals(1, el.length);
    -  assertEquals(VIMEO_URL, control.getDataModel().getUrl());
    -}
    -
    -function testParsingUrl() {
    -  assertExtractsCorrectly(VIMEO_ID, VIMEO_URL);
    -  assertExtractsCorrectly(VIMEO_ID, VIMEO_URL_HD);
    -  assertExtractsCorrectly(VIMEO_ID, VIMEO_URL_SECURE);
    -
    -  var invalidUrl = 'http://invalidUrl/filename.doc';
    -  var e = assertThrows('parser expects a well formed URL', function() {
    -    goog.ui.media.VimeoModel.newInstance(invalidUrl);
    -  });
    -  assertEquals('failed to parse vimeo url: ' + invalidUrl, e.message);
    -}
    -
    -function testBuildingUrl() {
    -  assertEquals(
    -      VIMEO_URL, goog.ui.media.VimeoModel.buildUrl(VIMEO_ID));
    -}
    -
    -function testCreatingModel() {
    -  var model = new goog.ui.media.VimeoModel(VIMEO_ID);
    -  assertEquals(VIMEO_ID, model.getVideoId());
    -  assertEquals(VIMEO_URL, model.getUrl());
    -  assertUndefined(model.getCaption());
    -}
    -
    -function testCreatingDomOnInitialState() {
    -  control.render(parent);
    -  var caption = goog.dom.getElementsByTagNameAndClass(
    -      'div',
    -      goog.ui.media.Vimeo.CSS_CLASS + '-caption',
    -      parent);
    -  assertEquals(1, caption.length);
    -
    -  var flash = goog.dom.getElementsByTagNameAndClass(
    -      'div', goog.ui.media.FlashObject.CSS_CLASS, parent);
    -  assertEquals(1, flash.length);
    -}
    -
    -function assertExtractsCorrectly(expectedVideoId, url) {
    -  var model = goog.ui.media.VimeoModel.newInstance(url);
    -  assertEquals('Video id for ' + url, expectedVideoId, model.getVideoId());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/youtube.js b/src/database/third_party/closure-library/closure/goog/ui/media/youtube.js
    deleted file mode 100644
    index 4c1d1ee5070..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/youtube.js
    +++ /dev/null
    @@ -1,358 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview provides a reusable youtube UI component given a youtube data
    - * model.
    - *
    - * goog.ui.media.Youtube is actually a {@link goog.ui.ControlRenderer}, a
    - * stateless class - that could/should be used as a Singleton with the static
    - * method {@code goog.ui.media.Youtube.getInstance} -, that knows how to render
    - * youtube videos. It is designed to be used with a {@link goog.ui.Control},
    - * which will actually control the media renderer and provide the
    - * {@link goog.ui.Component} base. This design guarantees that all different
    - * types of medias will behave alike but will look different.
    - *
    - * goog.ui.media.Youtube expects {@code goog.ui.media.YoutubeModel} on
    - * {@code goog.ui.Control.getModel} as data models, and render a flash object
    - * that will play that URL.
    - *
    - * Example of usage:
    - *
    - * <pre>
    - *   var video = goog.ui.media.YoutubeModel.newInstance(
    - *       'http://www.youtube.com/watch?v=ddl5f44spwQ');
    - *   goog.ui.media.Youtube.newControl(video).render();
    - * </pre>
    - *
    - * youtube medias currently support the following states:
    - *
    - * <ul>
    - *   <li> {@link goog.ui.Component.State.DISABLED}: shows 'flash not available'
    - *   <li> {@link goog.ui.Component.State.HOVER}: mouse cursor is over the video
    - *   <li> {@link !goog.ui.Component.State.SELECTED}: a static thumbnail is shown
    - *   <li> {@link goog.ui.Component.State.SELECTED}: video is playing
    - * </ul>
    - *
    - * Which can be accessed by
    - * <pre>
    - *   youtube.setEnabled(true);
    - *   youtube.setHighlighted(true);
    - *   youtube.setSelected(true);
    - * </pre>
    - *
    - * This package also provides a few static auxiliary methods, such as:
    - *
    - * <pre>
    - * var videoId = goog.ui.media.Youtube.parseUrl(
    - *     'http://www.youtube.com/watch?v=ddl5f44spwQ');
    - * </pre>
    - *
    - *
    - * @supported IE6, FF2+, Safari. Requires flash to actually work.
    - *
    - * TODO(user): test on other browsers
    - */
    -
    -
    -goog.provide('goog.ui.media.Youtube');
    -goog.provide('goog.ui.media.YoutubeModel');
    -
    -goog.require('goog.string');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.media.FlashObject');
    -goog.require('goog.ui.media.Media');
    -goog.require('goog.ui.media.MediaModel');
    -goog.require('goog.ui.media.MediaRenderer');
    -
    -
    -
    -/**
    - * Subclasses a goog.ui.media.MediaRenderer to provide a Youtube specific media
    - * renderer.
    - *
    - * This class knows how to parse youtube urls, and render the DOM structure
    - * of youtube video players and previews. This class is meant to be used as a
    - * singleton static stateless class, that takes {@code goog.ui.media.Media}
    - * instances and renders it. It expects {@code goog.ui.media.Media.getModel} to
    - * return a well formed, previously constructed, youtube video id, which is the
    - * data model this renderer will use to construct the DOM structure.
    - * {@see goog.ui.media.Youtube.newControl} for a example of constructing a
    - * control with this renderer.
    - *
    - * goog.ui.media.Youtube currently supports all {@link goog.ui.Component.State}.
    - * It will change its DOM structure between SELECTED and !SELECTED, and rely on
    - * CSS definitions on the others. On !SELECTED, the renderer will render a
    - * youtube static <img>, with a thumbnail of the video. On SELECTED, the
    - * renderer will append to the DOM a flash object, that contains the youtube
    - * video.
    - *
    - * This design is patterned after http://go/closure_control_subclassing
    - *
    - * It uses {@link goog.ui.media.FlashObject} to embed the flash object.
    - *
    - * @constructor
    - * @extends {goog.ui.media.MediaRenderer}
    - * @final
    - */
    -goog.ui.media.Youtube = function() {
    -  goog.ui.media.MediaRenderer.call(this);
    -};
    -goog.inherits(goog.ui.media.Youtube, goog.ui.media.MediaRenderer);
    -goog.addSingletonGetter(goog.ui.media.Youtube);
    -
    -
    -/**
    - * A static convenient method to construct a goog.ui.media.Media control out of
    - * a youtube model. It sets it as the data model goog.ui.media.Youtube renderer
    - * uses, sets the states supported by the renderer, and returns a Control that
    - * binds everything together. This is what you should be using for constructing
    - * Youtube videos, except if you need finer control over the configuration.
    - *
    - * @param {goog.ui.media.YoutubeModel} youtubeModel The youtube data model.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @return {!goog.ui.media.Media} A Control binded to the youtube renderer.
    - */
    -goog.ui.media.Youtube.newControl = function(youtubeModel, opt_domHelper) {
    -  var control = new goog.ui.media.Media(
    -      youtubeModel,
    -      goog.ui.media.Youtube.getInstance(),
    -      opt_domHelper);
    -  control.setStateInternal(goog.ui.Component.State.ACTIVE);
    -  return control;
    -};
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.media.Youtube.CSS_CLASS = goog.getCssName('goog-ui-media-youtube');
    -
    -
    -/**
    - * Changes the state of a {@code control}. Currently only changes the DOM
    - * structure when the youtube movie is SELECTED (by default fired by a MOUSEUP
    - * on the thumbnail), which means we have to embed the youtube flash video and
    - * play it.
    - *
    - * @param {goog.ui.Control} c The media control.
    - * @param {goog.ui.Component.State} state The state to be set or cleared.
    - * @param {boolean} enable Whether the state is enabled or disabled.
    - * @override
    - */
    -goog.ui.media.Youtube.prototype.setState = function(c, state, enable) {
    -  var control = /** @type {goog.ui.media.Media} */ (c);
    -  goog.ui.media.Youtube.superClass_.setState.call(this, control, state, enable);
    -
    -  // control.createDom has to be called before any state is set.
    -  // Use control.setStateInternal if you need to set states
    -  if (!control.getElement()) {
    -    throw Error(goog.ui.Component.Error.STATE_INVALID);
    -  }
    -
    -  var domHelper = control.getDomHelper();
    -  var dataModel =
    -      /** @type {goog.ui.media.YoutubeModel} */ (control.getDataModel());
    -
    -  if (!!(state & goog.ui.Component.State.SELECTED) && enable) {
    -    var flashEls = domHelper.getElementsByTagNameAndClass(
    -        'div',
    -        goog.ui.media.FlashObject.CSS_CLASS,
    -        control.getElement());
    -    if (flashEls.length > 0) {
    -      return;
    -    }
    -    var youtubeFlash = new goog.ui.media.FlashObject(
    -        dataModel.getPlayer().getTrustedResourceUrl(),
    -        domHelper);
    -    control.addChild(youtubeFlash, true);
    -  }
    -};
    -
    -
    -/**
    - * Returns the CSS class to be applied to the root element of components
    - * rendered using this renderer.
    - *
    - * @return {string} Renderer-specific CSS class.
    - * @override
    - */
    -goog.ui.media.Youtube.prototype.getCssClass = function() {
    -  return goog.ui.media.Youtube.CSS_CLASS;
    -};
    -
    -
    -
    -/**
    - * The {@code goog.ui.media.Youtube} media data model. It stores a required
    - * {@code videoId} field, sets the youtube URL, and allows a few optional
    - * parameters.
    - *
    - * @param {string} videoId The youtube video id.
    - * @param {string=} opt_caption An optional caption of the youtube video.
    - * @param {string=} opt_description An optional description of the youtube
    - *     video.
    - * @constructor
    - * @extends {goog.ui.media.MediaModel}
    - * @final
    - */
    -goog.ui.media.YoutubeModel = function(videoId, opt_caption, opt_description) {
    -  goog.ui.media.MediaModel.call(
    -      this,
    -      goog.ui.media.YoutubeModel.buildUrl(videoId),
    -      opt_caption,
    -      opt_description,
    -      goog.ui.media.MediaModel.MimeType.FLASH);
    -
    -  /**
    -   * The Youtube video id.
    -   * @type {string}
    -   * @private
    -   */
    -  this.videoId_ = videoId;
    -
    -  this.setThumbnails([new goog.ui.media.MediaModel.Thumbnail(
    -      goog.ui.media.YoutubeModel.getThumbnailUrl(videoId))]);
    -
    -  this.setPlayer(new goog.ui.media.MediaModel.Player(
    -      goog.ui.media.YoutubeModel.getFlashUrl(videoId, true)));
    -};
    -goog.inherits(goog.ui.media.YoutubeModel, goog.ui.media.MediaModel);
    -
    -
    -/**
    - * A youtube regular expression matcher. It matches the VIDEOID of URLs like
    - * http://www.youtube.com/watch?v=VIDEOID. Based on:
    - * googledata/contentonebox/opencob/specs/common/YTPublicExtractorCard.xml
    - * @type {RegExp}
    - * @private
    - * @const
    - */
    -// Be careful about the placement of the dashes in the character classes. Eg,
    -// use "[\\w=-]" instead of "[\\w-=]" if you mean to include the dash as a
    -// character and not create a character range like "[a-f]".
    -goog.ui.media.YoutubeModel.MATCHER_ = new RegExp(
    -    // Lead in.
    -    'https?://(?:[a-zA-Z]{1,3}\\.)?' +
    -    // Watch URL prefix.  This should handle new URLs of the form:
    -    // http://www.youtube.com/watch#!v=jqxENMKaeCU&feature=related
    -    // where the parameters appear after "#!" instead of "?".
    -    '(?:youtube\\.com/watch|youtu\\.be/watch)' +
    -    // Get the video id:
    -    // The video ID is a parameter v=[videoid] either right after the "?"
    -    // or after some other parameters.
    -    '(?:\\?(?:[\\w=-]+&(?:amp;)?)*v=([\\w-]+)' +
    -    '(?:&(?:amp;)?[\\w=-]+)*)?' +
    -    // Get any extra arguments in the URL's hash part.
    -    '(?:#[!]?(?:' +
    -    // Video ID from the v=[videoid] parameter, optionally surrounded by other
    -    // & separated parameters.
    -    '(?:(?:[\\w=-]+&(?:amp;)?)*(?:v=([\\w-]+))' +
    -    '(?:&(?:amp;)?[\\w=-]+)*)' +
    -    '|' +
    -    // Continue supporting "?" for the video ID
    -    // and "#" for other hash parameters.
    -    '(?:[\\w=&-]+)' +
    -    '))?' +
    -    // Should terminate with a non-word, non-dash (-) character.
    -    '[^\\w-]?', 'i');
    -
    -
    -/**
    - * A auxiliary static method that parses a youtube URL, extracting the ID of the
    - * video, and builds a YoutubeModel.
    - *
    - * @param {string} youtubeUrl A youtube URL.
    - * @param {string=} opt_caption An optional caption of the youtube video.
    - * @param {string=} opt_description An optional description of the youtube
    - *     video.
    - * @return {!goog.ui.media.YoutubeModel} The data model that represents the
    - *     youtube URL.
    - * @see goog.ui.media.YoutubeModel.getVideoId()
    - * @throws Error in case the parsing fails.
    - */
    -goog.ui.media.YoutubeModel.newInstance = function(youtubeUrl,
    -                                                  opt_caption,
    -                                                  opt_description) {
    -  var extract = goog.ui.media.YoutubeModel.MATCHER_.exec(youtubeUrl);
    -  if (extract) {
    -    var videoId = extract[1] || extract[2];
    -    return new goog.ui.media.YoutubeModel(
    -        videoId, opt_caption, opt_description);
    -  }
    -
    -  throw Error('failed to parse video id from youtube url: ' + youtubeUrl);
    -};
    -
    -
    -/**
    - * The opposite of {@code goog.ui.media.Youtube.newInstance}: it takes a videoId
    - * and returns a youtube URL.
    - *
    - * @param {string} videoId The youtube video ID.
    - * @return {string} The youtube URL.
    - */
    -goog.ui.media.YoutubeModel.buildUrl = function(videoId) {
    -  return 'http://www.youtube.com/watch?v=' + goog.string.urlEncode(videoId);
    -};
    -
    -
    -/**
    - * A static auxiliary method that builds a static image URL with a preview of
    - * the youtube video.
    - *
    - * NOTE(user): patterned after Gmail's gadgets/youtube,
    - *
    - * TODO(user): how do I specify the width/height of the resulting image on the
    - * url ? is there an official API for http://ytimg.com ?
    - *
    - * @param {string} youtubeId The youtube video ID.
    - * @return {string} An URL that contains an image with a preview of the youtube
    - *     movie.
    - */
    -goog.ui.media.YoutubeModel.getThumbnailUrl = function(youtubeId) {
    -  return 'http://i.ytimg.com/vi/' + youtubeId + '/default.jpg';
    -};
    -
    -
    -/**
    - * A static auxiliary method that builds URL of the flash movie to be embedded,
    - * out of the youtube video id.
    - *
    - * @param {string} videoId The youtube video ID.
    - * @param {boolean=} opt_autoplay Whether the flash movie should start playing
    - *     as soon as it is shown, or if it should show a 'play' button.
    - * @return {string} The flash URL to be embedded on the page.
    - */
    -goog.ui.media.YoutubeModel.getFlashUrl = function(videoId, opt_autoplay) {
    -  var autoplay = opt_autoplay ? '&autoplay=1' : '';
    -  // YouTube video ids are extracted from youtube URLs, which are user
    -  // generated input. the video id is later used to embed a flash object,
    -  // which is generated through HTML construction. We goog.string.urlEncode
    -  // the video id to make sure the URL is safe to be embedded.
    -  return 'http://www.youtube.com/v/' + goog.string.urlEncode(videoId) +
    -      '&hl=en&fs=1' + autoplay;
    -};
    -
    -
    -/**
    - * Gets the Youtube video id.
    - * @return {string} The Youtube video id.
    - */
    -goog.ui.media.YoutubeModel.prototype.getVideoId = function() {
    -  return this.videoId_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/youtube_test.html b/src/database/third_party/closure-library/closure/goog/ui/media/youtube_test.html
    deleted file mode 100644
    index 76b98476983..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/youtube_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.media.Youtube
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.ui.media.YoutubeTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/media/youtube_test.js b/src/database/third_party/closure-library/closure/goog/ui/media/youtube_test.js
    deleted file mode 100644
    index 234cbddfa40..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/media/youtube_test.js
    +++ /dev/null
    @@ -1,259 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.media.YoutubeTest');
    -goog.setTestOnly('goog.ui.media.YoutubeTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.media.FlashObject');
    -goog.require('goog.ui.media.Youtube');
    -goog.require('goog.ui.media.YoutubeModel');
    -var youtube;
    -var control;
    -var YOUTUBE_VIDEO_ID = 'dMH0bHeiRNg';
    -var YOUTUBE_URL = 'http://www.youtube.com/watch?v=' + YOUTUBE_VIDEO_ID;
    -var parent = goog.dom.createElement('div');
    -
    -function setUp() {
    -  var model = new goog.ui.media.YoutubeModel(
    -      YOUTUBE_VIDEO_ID, 'evolution of dance');
    -  control = goog.ui.media.Youtube.newControl(model);
    -}
    -
    -function tearDown() {
    -  control.dispose();
    -}
    -
    -function testBasicRendering() {
    -  control.render(parent);
    -  var el = goog.dom.getElementsByTagNameAndClass('div',
    -      goog.ui.media.Youtube.CSS_CLASS, parent);
    -  assertEquals(1, el.length);
    -  assertEquals(YOUTUBE_URL, control.getDataModel().getUrl());
    -}
    -
    -function testParsingUrl() {
    -  // a simple link
    -  assertExtractsCorrectly(
    -      'uddeBVmKTqE',
    -      'http://www.youtube.com/watch?v=uddeBVmKTqE');
    -  // a simple mobile link
    -  assertExtractsCorrectly(
    -      'uddeBVmKTqE',
    -      'http://m.youtube.com/watch?v=uddeBVmKTqE');
    -  // a secure mobile link
    -  assertExtractsCorrectly(
    -      'uddeBVmKTqE',
    -      'https://m.youtube.com/watch?v=uddeBVmKTqE');
    -  // a simple short link
    -  assertExtractsCorrectly(
    -      'uddeBVmKTqE',
    -      'http://youtu.be/watch?v=uddeBVmKTqE');
    -  // a secure short link
    -  assertExtractsCorrectly(
    -      'uddeBVmKTqE',
    -      'https://youtu.be/watch?v=uddeBVmKTqE');
    -  // a channel link
    -  assertExtractsCorrectly(
    -      '4Pb9e1uu3EQ',
    -      'http://www.youtube.com/watch?v=4Pb9e1uu3EQ&feature=channel');
    -  // a UK link
    -  assertExtractsCorrectly(
    -      'xqWXO87TlH4',
    -      'http://uk.youtube.com/watch?gl=GB&hl=en-GB&v=xqWXO87TlH4');
    -  // an India link
    -  assertExtractsCorrectly(
    -      '10FKWOn4qGA',
    -      'http://www.youtube.com/watch?gl=IN&hl=en-GB&v=10FKWOn4qGA');
    -  // an ad
    -  assertExtractsCorrectly(
    -      'wk1_kDJhyBk',
    -      'http://www.youtube.com/watch?v=wk1_kDJhyBk&feature=yva-video-display');
    -  // a related video
    -  assertExtractsCorrectly(
    -      '7qL2PuLF0SI',
    -      'http://www.youtube.com/watch?v=7qL2PuLF0SI&feature=related');
    -  // with a timestamp
    -  assertExtractsCorrectly(
    -      'siJZXtsdfsf',
    -      'http://www.youtube.com/watch?v=siJZXtsdfsf#t=2m59s');
    -  // with a timestamp and multiple hash params
    -  assertExtractsCorrectly(
    -      'siJZXtabdef',
    -      'http://www.youtube.com/watch?v=siJZXtabdef#t=1m59s&videos=foo');
    -  // with a timestamp, multiple regular and hash params
    -  assertExtractsCorrectly(
    -      'siJZXtabxyz',
    -      'http://www.youtube.com/watch?foo=bar&v=siJZXtabxyz&x=y#t=1m30s' +
    -          '&videos=bar');
    -  // only hash params
    -  assertExtractsCorrectly(
    -      'MWBpQoPwT3U',
    -      'http://www.youtube.com/watch#!playnext=1&playnext_from=TL' +
    -          '&videos=RX1XPmgerGo&v=MWBpQoPwT3U');
    -  // only hash params
    -  assertExtractsCorrectly(
    -      'MWBpQoPwT3V',
    -      'http://www.youtube.com/watch#!playnext=1&playnext_from=TL' +
    -          '&videos=RX1XPmgerGp&v=MWBpQoPwT3V&foo=bar');
    -  assertExtractsCorrectly(
    -      'jqxENMKaeCU',
    -      'http://www.youtube.com/watch#!v=jqxENMKaeCU&feature=related');
    -  // Lots of query params, some of them w/ numbers, one of them before the
    -  // video ID
    -  assertExtractsCorrectly(
    -      'qbce2yN81mE',
    -      'http://www.youtube.com/watch?usg=AFQjCNFf90T3fekgdVBmPp-Wgya5_CTSaw' +
    -          '&v=qbce2yN81mE&source=video&vgc=rss');
    -  assertExtractsCorrectly(
    -      'Lc-8onVA5Jk',
    -      'http://www.youtube.com/watch?v=Lc-8onVA5Jk&feature=dir');
    -  // Last character in the video ID is '-' (a non-word but valid character)
    -  // and the video ID is the last query parameter
    -  assertExtractsCorrectly(
    -      'Lc-8onV5Jk-',
    -      'http://www.youtube.com/watch?v=Lc-8onV5Jk-');
    -
    -  var invalidUrls = [
    -    'http://invalidUrl/watch?v=dMH0bHeiRNg',
    -    'http://www$youtube.com/watch?v=dMH0bHeiRNg',
    -    'http://www.youtube$com/watch?v=dMH0bHeiRNg',
    -    'http://w_w.youtube.com/watch?v=dMH0bHeiRNg'
    -  ];
    -  for (var i = 0, j = invalidUrls.length; i < j; ++i) {
    -    var e = assertThrows('parser expects a well formed URL', function() {
    -      goog.ui.media.YoutubeModel.newInstance(invalidUrls[i]);
    -    });
    -    assertEquals(
    -        'failed to parse video id from youtube url: ' + invalidUrls[i],
    -        e.message);
    -  }
    -}
    -
    -function testBuildingUrl() {
    -  assertEquals(
    -      YOUTUBE_URL, goog.ui.media.YoutubeModel.buildUrl(YOUTUBE_VIDEO_ID));
    -}
    -
    -function testCreatingModel() {
    -  var model = new goog.ui.media.YoutubeModel(YOUTUBE_VIDEO_ID);
    -  assertEquals(YOUTUBE_VIDEO_ID, model.getVideoId());
    -  assertEquals(YOUTUBE_URL, model.getUrl());
    -  assertUndefined(model.getCaption());
    -}
    -
    -function testCreatingDomOnInitialState() {
    -  control.render(parent);
    -  var preview = goog.dom.getElementsByTagNameAndClass(
    -      'img',
    -      goog.ui.media.Youtube.CSS_CLASS + '-thumbnail0',
    -      parent);
    -  assertEquals(1, preview.length);
    -
    -  var caption = goog.dom.getElementsByTagNameAndClass(
    -      'div',
    -      goog.ui.media.Youtube.CSS_CLASS + '-caption',
    -      parent);
    -  assertEquals(1, caption.length);
    -
    -  var flash = goog.dom.getElementsByTagNameAndClass('div',
    -      goog.ui.media.FlashObject.CSS_CLASS);
    -  assertEquals(0, flash.length);
    -}
    -
    -function testCreatingDomOnSelectedState() {
    -  control.render(parent);
    -  control.setSelected(true);
    -  var preview = goog.dom.getElementsByTagNameAndClass(
    -      'img',
    -      goog.ui.media.Youtube.CSS_CLASS + '-preview',
    -      parent);
    -  assertEquals(0, preview.length);
    -
    -  var caption = goog.dom.getElementsByTagNameAndClass(
    -      'div',
    -      goog.ui.media.Youtube.CSS_CLASS + '-caption',
    -      parent);
    -  assertEquals(1, caption.length);
    -
    -  var flash = goog.dom.getElementsByTagNameAndClass('div',
    -      goog.ui.media.FlashObject.CSS_CLASS, parent);
    -  assertEquals(1, flash.length);
    -}
    -
    -function testSettingSelectedStateAfterRender() {
    -  control.render(parent);
    -  control.setSelected(true);
    -
    -  var preview = goog.dom.getElementsByTagNameAndClass(
    -      'img',
    -      goog.ui.media.Youtube.CSS_CLASS + '-preview',
    -      parent);
    -  assertEquals(0, preview.length);
    -
    -  var caption = goog.dom.getElementsByTagNameAndClass(
    -      'div',
    -      goog.ui.media.Youtube.CSS_CLASS + '-caption',
    -      parent);
    -  assertEquals(1, caption.length);
    -
    -  var flash = goog.dom.getElementsByTagNameAndClass('div',
    -      goog.ui.media.FlashObject.CSS_CLASS, parent);
    -  assertEquals(1, flash.length);
    -
    -  control.setSelected(false);
    -
    -  var preview = goog.dom.getElementsByTagNameAndClass(
    -      'img',
    -      goog.ui.media.Youtube.CSS_CLASS + '-thumbnail0',
    -      parent);
    -  assertEquals(1, preview.length);
    -
    -  var caption = goog.dom.getElementsByTagNameAndClass(
    -      'div',
    -      goog.ui.media.Youtube.CSS_CLASS + '-caption',
    -      parent);
    -  assertEquals(1, caption.length);
    -
    -  // setting select as false doesn't actually remove the flash movie from
    -  // the DOM tree, which means that setting selected to true won't actually
    -  // restart the movie. TODO(user): fix this.
    -  var flash = goog.dom.getElementsByTagNameAndClass('div',
    -      goog.ui.media.FlashObject.CSS_CLASS, parent);
    -  assertEquals(1, flash.length);
    -
    -  control.setSelected(true);
    -
    -  var flash = goog.dom.getElementsByTagNameAndClass('div',
    -      goog.ui.media.FlashObject.CSS_CLASS, parent);
    -  assertEquals(1, flash.length);
    -}
    -
    -function testUrlMatcher() {
    -  var matcher = goog.ui.media.YoutubeModel.MATCHER_;
    -  assertTrue(matcher.test('http://www.youtube.com/watch?v=55D-ybnYQSs'));
    -  assertTrue(matcher.test('https://youtube.com/watch?v=55D-ybnYQSs'));
    -  assertTrue(
    -      matcher.test('https://youtube.com/watch?blarg=blop&v=55D-ybnYQSs'));
    -  assertTrue(matcher.test('http://www.youtube.com/watch?v=55D-ybnYQSs#wee'));
    -
    -  assertFalse(matcher.test('http://www.cnn.com/watch?v=55D-ybnYQSs#wee'));
    -  assertFalse(matcher.test('ftp://www.youtube.com/watch?v=55D-ybnYQSs#wee'));
    -}
    -
    -function assertExtractsCorrectly(expectedVideoId, url) {
    -  var youtube = goog.ui.media.YoutubeModel.newInstance(url);
    -  assertEquals('videoid for ' + url, expectedVideoId, youtube.getVideoId());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/menu.js b/src/database/third_party/closure-library/closure/goog/ui/menu.js
    deleted file mode 100644
    index 0575786b1e9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/menu.js
    +++ /dev/null
    @@ -1,477 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A base menu class that supports key and mouse events. The menu
    - * can be bound to an existing HTML structure or can generate its own DOM.
    - *
    - * To decorate, the menu should be bound to an element containing children
    - * with the classname 'goog-menuitem'.  HRs will be classed as separators.
    - *
    - * Decorate Example:
    - * <div id="menu" class="goog-menu" tabIndex="0">
    - *   <div class="goog-menuitem">Google</div>
    - *   <div class="goog-menuitem">Yahoo</div>
    - *   <div class="goog-menuitem">MSN</div>
    - *   <hr>
    - *   <div class="goog-menuitem">New...</div>
    - * </div>
    - * <script>
    - *
    - * var menu = new goog.ui.Menu();
    - * menu.decorate(goog.dom.getElement('menu'));
    - *
    - * TESTED=FireFox 2.0, IE6, Opera 9, Chrome.
    - * TODO(user): Key handling is flaky in Opera and Chrome
    - * TODO(user): Rename all references of "item" to child since menu is
    - * essentially very generic and could, in theory, host a date or color picker.
    - *
    - * @see ../demos/menu.html
    - * @see ../demos/menus.html
    - */
    -
    -goog.provide('goog.ui.Menu');
    -goog.provide('goog.ui.Menu.EventType');
    -
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.string');
    -goog.require('goog.style');
    -goog.require('goog.ui.Component.EventType');
    -goog.require('goog.ui.Component.State');
    -goog.require('goog.ui.Container');
    -goog.require('goog.ui.Container.Orientation');
    -goog.require('goog.ui.MenuHeader');
    -goog.require('goog.ui.MenuItem');
    -goog.require('goog.ui.MenuRenderer');
    -goog.require('goog.ui.MenuSeparator');
    -
    -// The dependencies MenuHeader, MenuItem, and MenuSeparator are implicit.
    -// There are no references in the code, but we need to load these
    -// classes before goog.ui.Menu.
    -
    -
    -
    -// TODO(robbyw): Reverse constructor argument order for consistency.
    -/**
    - * A basic menu class.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @param {goog.ui.MenuRenderer=} opt_renderer Renderer used to render or
    - *     decorate the container; defaults to {@link goog.ui.MenuRenderer}.
    - * @constructor
    - * @extends {goog.ui.Container}
    - */
    -goog.ui.Menu = function(opt_domHelper, opt_renderer) {
    -  goog.ui.Container.call(this, goog.ui.Container.Orientation.VERTICAL,
    -      opt_renderer || goog.ui.MenuRenderer.getInstance(), opt_domHelper);
    -
    -  // Unlike Containers, Menus aren't keyboard-accessible by default.  This line
    -  // preserves backwards compatibility with code that depends on menus not
    -  // receiving focus - e.g. {@code goog.ui.MenuButton}.
    -  this.setFocusable(false);
    -};
    -goog.inherits(goog.ui.Menu, goog.ui.Container);
    -goog.tagUnsealableClass(goog.ui.Menu);
    -
    -
    -// TODO(robbyw): Remove this and all references to it.
    -// Please ensure that BEFORE_SHOW behavior is not disrupted as a result.
    -/**
    - * Event types dispatched by the menu.
    - * @enum {string}
    - * @deprecated Use goog.ui.Component.EventType.
    - */
    -goog.ui.Menu.EventType = {
    -  /** Dispatched before the menu becomes visible */
    -  BEFORE_SHOW: goog.ui.Component.EventType.BEFORE_SHOW,
    -
    -  /** Dispatched when the menu is shown */
    -  SHOW: goog.ui.Component.EventType.SHOW,
    -
    -  /** Dispatched before the menu becomes hidden */
    -  BEFORE_HIDE: goog.ui.Component.EventType.HIDE,
    -
    -  /** Dispatched when the menu is hidden */
    -  HIDE: goog.ui.Component.EventType.HIDE
    -};
    -
    -
    -// TODO(robbyw): Remove this and all references to it.
    -/**
    - * CSS class for menus.
    - * @type {string}
    - * @deprecated Use goog.ui.MenuRenderer.CSS_CLASS.
    - */
    -goog.ui.Menu.CSS_CLASS = goog.ui.MenuRenderer.CSS_CLASS;
    -
    -
    -/**
    - * Coordinates of the mousedown event that caused this menu to be made visible.
    - * Used to prevent the consequent mouseup event due to a simple click from
    - * activating a menu item immediately. Considered protected; should only be used
    - * within this package or by subclasses.
    - * @type {goog.math.Coordinate|undefined}
    - */
    -goog.ui.Menu.prototype.openingCoords;
    -
    -
    -/**
    - * Whether the menu can move the focus to its key event target when it is
    - * shown.  Default = true
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.Menu.prototype.allowAutoFocus_ = true;
    -
    -
    -/**
    - * Whether the menu should use windows syle behavior and allow disabled menu
    - * items to be highlighted (though not selectable).  Defaults to false
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.Menu.prototype.allowHighlightDisabled_ = false;
    -
    -
    -/**
    - * Returns the CSS class applied to menu elements, also used as the prefix for
    - * derived styles, if any.  Subclasses should override this method as needed.
    - * Considered protected.
    - * @return {string} The CSS class applied to menu elements.
    - * @protected
    - * @deprecated Use getRenderer().getCssClass().
    - */
    -goog.ui.Menu.prototype.getCssClass = function() {
    -  return this.getRenderer().getCssClass();
    -};
    -
    -
    -/**
    - * Returns whether the provided element is to be considered inside the menu for
    - * purposes such as dismissing the menu on an event.  This is so submenus can
    - * make use of elements outside their own DOM.
    - * @param {Element} element The element to test for.
    - * @return {boolean} Whether the provided element is to be considered inside
    - *     the menu.
    - */
    -goog.ui.Menu.prototype.containsElement = function(element) {
    -  if (this.getRenderer().containsElement(this, element)) {
    -    return true;
    -  }
    -
    -  for (var i = 0, count = this.getChildCount(); i < count; i++) {
    -    var child = this.getChildAt(i);
    -    if (typeof child.containsElement == 'function' &&
    -        child.containsElement(element)) {
    -      return true;
    -    }
    -  }
    -
    -  return false;
    -};
    -
    -
    -/**
    - * Adds a new menu item at the end of the menu.
    - * @param {goog.ui.MenuHeader|goog.ui.MenuItem|goog.ui.MenuSeparator} item Menu
    - *     item to add to the menu.
    - * @deprecated Use {@link #addChild} instead, with true for the second argument.
    - */
    -goog.ui.Menu.prototype.addItem = function(item) {
    -  this.addChild(item, true);
    -};
    -
    -
    -/**
    - * Adds a new menu item at a specific index in the menu.
    - * @param {goog.ui.MenuHeader|goog.ui.MenuItem|goog.ui.MenuSeparator} item Menu
    - *     item to add to the menu.
    - * @param {number} n Index at which to insert the menu item.
    - * @deprecated Use {@link #addChildAt} instead, with true for the third
    - *     argument.
    - */
    -goog.ui.Menu.prototype.addItemAt = function(item, n) {
    -  this.addChildAt(item, n, true);
    -};
    -
    -
    -/**
    - * Removes an item from the menu and disposes of it.
    - * @param {goog.ui.MenuHeader|goog.ui.MenuItem|goog.ui.MenuSeparator} item The
    - *     menu item to remove.
    - * @deprecated Use {@link #removeChild} instead.
    - */
    -goog.ui.Menu.prototype.removeItem = function(item) {
    -  var removedChild = this.removeChild(item, true);
    -  if (removedChild) {
    -    removedChild.dispose();
    -  }
    -};
    -
    -
    -/**
    - * Removes a menu item at a given index in the menu and disposes of it.
    - * @param {number} n Index of item.
    - * @deprecated Use {@link #removeChildAt} instead.
    - */
    -goog.ui.Menu.prototype.removeItemAt = function(n) {
    -  var removedChild = this.removeChildAt(n, true);
    -  if (removedChild) {
    -    removedChild.dispose();
    -  }
    -};
    -
    -
    -/**
    - * Returns a reference to the menu item at a given index.
    - * @param {number} n Index of menu item.
    - * @return {goog.ui.MenuHeader|goog.ui.MenuItem|goog.ui.MenuSeparator|null}
    - *     Reference to the menu item.
    - * @deprecated Use {@link #getChildAt} instead.
    - */
    -goog.ui.Menu.prototype.getItemAt = function(n) {
    -  return /** @type {goog.ui.MenuItem?} */(this.getChildAt(n));
    -};
    -
    -
    -/**
    - * Returns the number of items in the menu (including separators).
    - * @return {number} The number of items in the menu.
    - * @deprecated Use {@link #getChildCount} instead.
    - */
    -goog.ui.Menu.prototype.getItemCount = function() {
    -  return this.getChildCount();
    -};
    -
    -
    -/**
    - * Returns an array containing the menu items contained in the menu.
    - * @return {!Array<goog.ui.MenuItem>} An array of menu items.
    - * @deprecated Use getChildAt, forEachChild, and getChildCount.
    - */
    -goog.ui.Menu.prototype.getItems = function() {
    -  // TODO(user): Remove reference to getItems and instead use getChildAt,
    -  // forEachChild, and getChildCount
    -  var children = [];
    -  this.forEachChild(function(child) {
    -    children.push(child);
    -  });
    -  return children;
    -};
    -
    -
    -/**
    - * Sets the position of the menu relative to the view port.
    - * @param {number|goog.math.Coordinate} x Left position or coordinate obj.
    - * @param {number=} opt_y Top position.
    - */
    -goog.ui.Menu.prototype.setPosition = function(x, opt_y) {
    -  // NOTE(user): It is necessary to temporarily set the display from none, so
    -  // that the position gets set correctly.
    -  var visible = this.isVisible();
    -  if (!visible) {
    -    goog.style.setElementShown(this.getElement(), true);
    -  }
    -  goog.style.setPageOffset(this.getElement(), x, opt_y);
    -  if (!visible) {
    -    goog.style.setElementShown(this.getElement(), false);
    -  }
    -};
    -
    -
    -/**
    - * Gets the page offset of the menu, or null if the menu isn't visible
    - * @return {goog.math.Coordinate?} Object holding the x-y coordinates of the
    - *     menu or null if the menu is not visible.
    - */
    -goog.ui.Menu.prototype.getPosition = function() {
    -  return this.isVisible() ? goog.style.getPageOffset(this.getElement()) : null;
    -};
    -
    -
    -/**
    - * Sets whether the menu can automatically move focus to its key event target
    - * when it is set to visible.
    - * @param {boolean} allow Whether the menu can automatically move focus to its
    - *     key event target when it is set to visible.
    - */
    -goog.ui.Menu.prototype.setAllowAutoFocus = function(allow) {
    -  this.allowAutoFocus_ = allow;
    -  if (allow) {
    -    this.setFocusable(true);
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the menu can automatically move focus to its key
    - *     event target when it is set to visible.
    - */
    -goog.ui.Menu.prototype.getAllowAutoFocus = function() {
    -  return this.allowAutoFocus_;
    -};
    -
    -
    -/**
    - * Sets whether the menu will highlight disabled menu items or skip to the next
    - * active item.
    - * @param {boolean} allow Whether the menu will highlight disabled menu items or
    - *     skip to the next active item.
    - */
    -goog.ui.Menu.prototype.setAllowHighlightDisabled = function(allow) {
    -  this.allowHighlightDisabled_ = allow;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the menu will highlight disabled menu items or skip
    - *     to the next active item.
    - */
    -goog.ui.Menu.prototype.getAllowHighlightDisabled = function() {
    -  return this.allowHighlightDisabled_;
    -};
    -
    -
    -/**
    - * @override
    - * @param {goog.events.Event=} opt_e Mousedown event that caused this menu to
    - *     be made visible (ignored if show is false).
    - */
    -goog.ui.Menu.prototype.setVisible = function(show, opt_force, opt_e) {
    -  var visibilityChanged = goog.ui.Menu.superClass_.setVisible.call(this, show,
    -      opt_force);
    -  if (visibilityChanged && show && this.isInDocument() &&
    -      this.allowAutoFocus_) {
    -    this.getKeyEventTarget().focus();
    -  }
    -  if (show && opt_e && goog.isNumber(opt_e.clientX)) {
    -    this.openingCoords = new goog.math.Coordinate(opt_e.clientX, opt_e.clientY);
    -  } else {
    -    this.openingCoords = null;
    -  }
    -  return visibilityChanged;
    -};
    -
    -
    -/** @override */
    -goog.ui.Menu.prototype.handleEnterItem = function(e) {
    -  if (this.allowAutoFocus_) {
    -    this.getKeyEventTarget().focus();
    -  }
    -
    -  return goog.ui.Menu.superClass_.handleEnterItem.call(this, e);
    -};
    -
    -
    -/**
    - * Highlights the next item that begins with the specified string.  If no
    - * (other) item begins with the given string, the selection is unchanged.
    - * @param {string} charStr The prefix to match.
    - * @return {boolean} Whether a matching prefix was found.
    - */
    -goog.ui.Menu.prototype.highlightNextPrefix = function(charStr) {
    -  var re = new RegExp('^' + goog.string.regExpEscape(charStr), 'i');
    -  return this.highlightHelper(function(index, max) {
    -    // Index is >= -1 because it is set to -1 when nothing is selected.
    -    var start = index < 0 ? 0 : index;
    -    var wrapped = false;
    -
    -    // We always start looking from one after the current, because we
    -    // keep the current selection only as a last resort. This makes the
    -    // loop a little awkward in the case where there is no current
    -    // selection, as we need to stop somewhere but can't just stop
    -    // when index == start, which is why we need the 'wrapped' flag.
    -    do {
    -      ++index;
    -      if (index == max) {
    -        index = 0;
    -        wrapped = true;
    -      }
    -      var name = this.getChildAt(index).getCaption();
    -      if (name && name.match(re)) {
    -        return index;
    -      }
    -    } while (!wrapped || index != start);
    -    return this.getHighlightedIndex();
    -  }, this.getHighlightedIndex());
    -};
    -
    -
    -/** @override */
    -goog.ui.Menu.prototype.canHighlightItem = function(item) {
    -  return (this.allowHighlightDisabled_ || item.isEnabled()) &&
    -      item.isVisible() && item.isSupportedState(goog.ui.Component.State.HOVER);
    -};
    -
    -
    -/** @override */
    -goog.ui.Menu.prototype.decorateInternal = function(element) {
    -  this.decorateContent(element);
    -  goog.ui.Menu.superClass_.decorateInternal.call(this, element);
    -};
    -
    -
    -/** @override */
    -goog.ui.Menu.prototype.handleKeyEventInternal = function(e) {
    -  var handled = goog.ui.Menu.base(this, 'handleKeyEventInternal', e);
    -  if (!handled) {
    -    // Loop through all child components, and for each menu item call its
    -    // key event handler so that keyboard mnemonics can be handled.
    -    this.forEachChild(function(menuItem) {
    -      if (!handled && menuItem.getMnemonic &&
    -          menuItem.getMnemonic() == e.keyCode) {
    -        if (this.isEnabled()) {
    -          this.setHighlighted(menuItem);
    -        }
    -        // We still delegate to handleKeyEvent, so that it can handle
    -        // enabled/disabled state.
    -        handled = menuItem.handleKeyEvent(e);
    -      }
    -    }, this);
    -  }
    -  return handled;
    -};
    -
    -
    -/** @override */
    -goog.ui.Menu.prototype.setHighlightedIndex = function(index) {
    -  goog.ui.Menu.base(this, 'setHighlightedIndex', index);
    -
    -  // Bring the highlighted item into view. This has no effect if the menu is not
    -  // scrollable.
    -  var child = this.getChildAt(index);
    -  if (child) {
    -    goog.style.scrollIntoContainerView(child.getElement(), this.getElement());
    -  }
    -};
    -
    -
    -/**
    - * Decorate menu items located in any descendent node which as been explicitly
    - * marked as a 'content' node.
    - * @param {Element} element Element to decorate.
    - * @protected
    - */
    -goog.ui.Menu.prototype.decorateContent = function(element) {
    -  var renderer = this.getRenderer();
    -  var contentElements = this.getDomHelper().getElementsByTagNameAndClass('div',
    -      goog.getCssName(renderer.getCssClass(), 'content'), element);
    -
    -  // Some versions of IE do not like it when you access this nodeList
    -  // with invalid indices. See
    -  // http://code.google.com/p/closure-library/issues/detail?id=373
    -  var length = contentElements.length;
    -  for (var i = 0; i < length; i++) {
    -    renderer.decorateChildren(this, contentElements[i]);
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/menu_test.html b/src/database/third_party/closure-library/closure/goog/ui/menu_test.html
    deleted file mode 100644
    index 469462eda83..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/menu_test.html
    +++ /dev/null
    @@ -1,89 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -
    -  @author nicksantos@google.com (Nick Santos)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.Menu
    -  </title>
    -  <style type="text/css">
    -   .goog-menu {
    -  position: absolute;
    -  color: #aaa;
    -}
    -
    -.goog-scrollable-menu {
    -  max-height:30px;
    -  overflow-y:auto;
    -}
    -  </style>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.MenuTest');
    -  </script>
    - </head>
    - <body>
    -  <p>
    -   Here's a menu defined in markup:
    -  </p>
    -  <div id="demoMenu" class="goog-menu">
    -   <div id="menuItem1" class="goog-menuitem">
    -    Annual Report.pdf
    -   </div>
    -   <div id="menuItem2" class="goog-menuitem">
    -    Quarterly Update.pdf
    -   </div>
    -   <div id="menuItem3" class="goog-menuitem">
    -    Enemies List.txt
    -   </div>
    -  </div>
    -  <p>
    -   Here's a menu which has been rendered with an explicit content node:
    -  </p>
    -  <div id="complexMenu" class="goog-menu">
    -   <div style="border:1px solid black;">
    -    <div class="goog-menu-content">
    -     <div id="complexItem1" class="goog-menuitem">
    -      Drizzle
    -     </div>
    -     <div id="complexItem2" class="goog-menuitem">
    -      Rain
    -     </div>
    -     <div id="complexItem3" class="goog-menuitem">
    -      Deluge
    -     </div>
    -    </div>
    -   </div>
    -  </div>
    -  <p>
    -   Here's a scrollable menu:
    -  </p>
    -  <div id="scrollableMenu" class="goog-menu goog-scrollable-menu">
    -   <div id="scrollableMenuItem1" class="goog-menuitem">
    -    Auk
    -   </div>
    -   <div id="scrollableMenuItem2" class="goog-menuitem">
    -    Bird
    -   </div>
    -   <div id="scrollableMenuItem3" class="goog-menuitem">
    -    Crow
    -   </div>
    -   <div id="scrollableMenuItem4" class="goog-menuitem">
    -    Duck
    -   </div>
    -   <div id="scrollableMenuItem5" class="goog-menuitem">
    -    Emu
    -   </div>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/menu_test.js b/src/database/third_party/closure-library/closure/goog/ui/menu_test.js
    deleted file mode 100644
    index d9a495ce490..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/menu_test.js
    +++ /dev/null
    @@ -1,114 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.MenuTest');
    -goog.setTestOnly('goog.ui.MenuTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.Menu');
    -
    -var menu;
    -var clonedMenuDom;
    -
    -function setUp() {
    -  clonedMenuDom = goog.dom.getElement('demoMenu').cloneNode(true);
    -
    -  menu = new goog.ui.Menu();
    -}
    -
    -function tearDown() {
    -  menu.dispose();
    -
    -  var element = goog.dom.getElement('demoMenu');
    -  element.parentNode.replaceChild(clonedMenuDom, element);
    -}
    -
    -
    -/** @bug 1463524 */
    -function testMouseupDoesntActivateMenuItemImmediately() {
    -  menu.decorate(goog.dom.getElement('demoMenu'));
    -
    -  var fakeEvent = {clientX: 42, clientY: 42};
    -  var itemElem = goog.dom.getElement('menuItem2');
    -  var coords = new goog.math.Coordinate(42, 42);
    -
    -  var menuItem = menu.getChildAt(1);
    -  var actionDispatched = false;
    -  goog.events.listen(menuItem, goog.ui.Component.EventType.ACTION,
    -      function(e) {
    -        actionDispatched = true;
    -      });
    -
    -  menu.setVisible(true, false, fakeEvent);
    -  // Makes the menu item active so it can be selected on mouseup.
    -  menuItem.setActive(true);
    -
    -  goog.testing.events.fireMouseUpEvent(itemElem, undefined, coords);
    -  assertFalse('ACTION should not be dispatched after the initial mouseup',
    -              actionDispatched);
    -
    -  goog.testing.events.fireMouseUpEvent(itemElem, undefined, coords);
    -  assertTrue('ACTION should be dispatched after the second mouseup',
    -             actionDispatched);
    -
    -}
    -
    -function testHoverBehavior() {
    -  menu.decorate(goog.dom.getElement('demoMenu'));
    -
    -  goog.testing.events.fireMouseOverEvent(goog.dom.getElement('menuItem2'),
    -      document.body);
    -  assertEquals(1, menu.getHighlightedIndex());
    -
    -  menu.exitDocument();
    -  assertEquals(-1, menu.getHighlightedIndex());
    -}
    -
    -function testIndirectionDecoration() {
    -  menu.decorate(goog.dom.getElement('complexMenu'));
    -
    -  goog.testing.events.fireMouseOverEvent(goog.dom.getElement('complexItem3'),
    -      document.body);
    -  assertEquals(2, menu.getHighlightedIndex());
    -
    -  menu.exitDocument();
    -  assertEquals(-1, menu.getHighlightedIndex());
    -}
    -
    -function testSetHighlightedIndex() {
    -  menu.decorate(goog.dom.getElement('scrollableMenu'));
    -  assertEquals(0, menu.getElement().scrollTop);
    -
    -  // Scroll down
    -  var element = goog.dom.getElement('scrollableMenuItem4');
    -  menu.setHighlightedIndex(3);
    -  assertTrue(element.offsetTop >= menu.getElement().scrollTop);
    -  assertTrue(element.offsetTop <=
    -      menu.getElement().scrollTop + menu.getElement().offsetHeight);
    -
    -  // Scroll up
    -  element = goog.dom.getElement('scrollableMenuItem3');
    -  menu.setHighlightedIndex(2);
    -  assertTrue(element.offsetTop >= menu.getElement().scrollTop);
    -  assertTrue(element.offsetTop <=
    -      menu.getElement().scrollTop + menu.getElement().offsetHeight);
    -
    -  menu.exitDocument();
    -  assertEquals(-1, menu.getHighlightedIndex());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/menubar.js b/src/database/third_party/closure-library/closure/goog/ui/menubar.js
    deleted file mode 100644
    index 6afc3f8111d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/menubar.js
    +++ /dev/null
    @@ -1,44 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A base menu bar factory. Can be bound to an existing
    - * HTML structure or can generate its own DOM.
    - *
    - * To decorate, the menu bar should be bound to an element containing children
    - * with the classname 'goog-menu-button'.  See menubar.html for example.
    - *
    - * @see ../demos/menubar.html
    - */
    -
    -goog.provide('goog.ui.menuBar');
    -
    -goog.require('goog.ui.Container');
    -goog.require('goog.ui.MenuBarRenderer');
    -
    -
    -/**
    - * The menuBar factory creates a new menu bar.
    - * @param {goog.ui.ContainerRenderer=} opt_renderer Renderer used to render or
    - *     decorate the menu bar; defaults to {@link goog.ui.MenuBarRenderer}.
    - * @param {goog.dom.DomHelper=} opt_domHelper DOM helper, used for document
    - *     interaction.
    - * @return {!goog.ui.Container} The created menu bar.
    - */
    -goog.ui.menuBar.create = function(opt_renderer, opt_domHelper) {
    -  return new goog.ui.Container(
    -      null,
    -      opt_renderer ? opt_renderer : goog.ui.MenuBarRenderer.getInstance(),
    -      opt_domHelper);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/menubardecorator.js b/src/database/third_party/closure-library/closure/goog/ui/menubardecorator.js
    deleted file mode 100644
    index 2272e5f03b3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/menubardecorator.js
    +++ /dev/null
    @@ -1,35 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Definition of MenuBarRenderer decorator, a static call into
    - * the goog.ui.registry.
    - *
    - * @see ../demos/menubar.html
    - */
    -
    -/** @suppress {extraProvide} */
    -goog.provide('goog.ui.menuBarDecorator');
    -
    -goog.require('goog.ui.MenuBarRenderer');
    -goog.require('goog.ui.menuBar');
    -goog.require('goog.ui.registry');
    -
    -
    -/**
    - * Register a decorator factory function. 'goog-menubar' defaults to
    - * goog.ui.MenuBarRenderer.
    - */
    -goog.ui.registry.setDecoratorByClassName(goog.ui.MenuBarRenderer.CSS_CLASS,
    -    goog.ui.menuBar.create);
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/menubarrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/menubarrenderer.js
    deleted file mode 100644
    index df8ea969850..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/menubarrenderer.js
    +++ /dev/null
    @@ -1,68 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Renderer for {@link goog.ui.menuBar}.
    - *
    - */
    -
    -goog.provide('goog.ui.MenuBarRenderer');
    -
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.ui.Container');
    -goog.require('goog.ui.ContainerRenderer');
    -
    -
    -
    -/**
    - * Default renderer for {@link goog.ui.menuBar}s, based on {@link
    - * goog.ui.ContainerRenderer}.
    - * @constructor
    - * @extends {goog.ui.ContainerRenderer}
    - * @final
    - */
    -goog.ui.MenuBarRenderer = function() {
    -  goog.ui.MenuBarRenderer.base(this, 'constructor',
    -      goog.a11y.aria.Role.MENUBAR);
    -};
    -goog.inherits(goog.ui.MenuBarRenderer, goog.ui.ContainerRenderer);
    -goog.addSingletonGetter(goog.ui.MenuBarRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of elements rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.MenuBarRenderer.CSS_CLASS = goog.getCssName('goog-menubar');
    -
    -
    -/**
    - * @override
    - */
    -goog.ui.MenuBarRenderer.prototype.getCssClass = function() {
    -  return goog.ui.MenuBarRenderer.CSS_CLASS;
    -};
    -
    -
    -/**
    - * Returns the default orientation of containers rendered or decorated by this
    - * renderer.  This implementation returns {@code HORIZONTAL}.
    - * @return {goog.ui.Container.Orientation} Default orientation for containers
    - *     created or decorated by this renderer.
    - * @override
    - */
    -goog.ui.MenuBarRenderer.prototype.getDefaultOrientation = function() {
    -  return goog.ui.Container.Orientation.HORIZONTAL;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/menubase.js b/src/database/third_party/closure-library/closure/goog/ui/menubase.js
    deleted file mode 100644
    index 23f0b525e84..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/menubase.js
    +++ /dev/null
    @@ -1,190 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Definition of the MenuBase class.
    - *
    - */
    -
    -goog.provide('goog.ui.MenuBase');
    -
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyHandler');
    -goog.require('goog.ui.Popup');
    -
    -
    -
    -/**
    - * The MenuBase class provides an abstract base class for different
    - * implementations of menu controls.
    - *
    - * @param {Element=} opt_element A DOM element for the popup.
    - * @deprecated Use goog.ui.Menu.
    - * @constructor
    - * @extends {goog.ui.Popup}
    - */
    -goog.ui.MenuBase = function(opt_element) {
    -  goog.ui.Popup.call(this, opt_element);
    -
    -  /**
    -   * Event handler for simplifiying adding/removing listeners.
    -   * @type {goog.events.EventHandler<!goog.ui.MenuBase>}
    -   * @private
    -   */
    -  this.eventHandler_ = new goog.events.EventHandler(this);
    -
    -  /**
    -   * KeyHandler to cope with the vagaries of cross-browser key events.
    -   * @type {goog.events.KeyHandler}
    -   * @private
    -   */
    -  this.keyHandler_ = new goog.events.KeyHandler(this.getElement());
    -};
    -goog.inherits(goog.ui.MenuBase, goog.ui.Popup);
    -
    -
    -/**
    - * Events fired by the Menu
    - */
    -goog.ui.MenuBase.Events = {};
    -
    -
    -/**
    - * Event fired by the Menu when an item is "clicked".
    - */
    -goog.ui.MenuBase.Events.ITEM_ACTION = 'itemaction';
    -
    -
    -/** @override */
    -goog.ui.MenuBase.prototype.disposeInternal = function() {
    -  goog.ui.MenuBase.superClass_.disposeInternal.call(this);
    -  this.eventHandler_.dispose();
    -  this.keyHandler_.dispose();
    -};
    -
    -
    -/**
    - * Called after the menu is shown. Derived classes can override to hook this
    - * event but should make sure to call the parent class method.
    - *
    - * @protected
    - * @suppress {underscore|visibility}
    - * @override
    - */
    -goog.ui.MenuBase.prototype.onShow_ = function() {
    -  goog.ui.MenuBase.superClass_.onShow_.call(this);
    -
    -  // register common event handlers for derived classes
    -  var el = this.getElement();
    -  this.eventHandler_.listen(
    -      el, goog.events.EventType.MOUSEOVER, this.onMouseOver);
    -  this.eventHandler_.listen(
    -      el, goog.events.EventType.MOUSEOUT, this.onMouseOut);
    -  this.eventHandler_.listen(
    -      el, goog.events.EventType.MOUSEDOWN, this.onMouseDown);
    -  this.eventHandler_.listen(
    -      el, goog.events.EventType.MOUSEUP, this.onMouseUp);
    -
    -  this.eventHandler_.listen(
    -      this.keyHandler_,
    -      goog.events.KeyHandler.EventType.KEY,
    -      this.onKeyDown);
    -};
    -
    -
    -/**
    - * Called after the menu is hidden. Derived classes can override to hook this
    - * event but should make sure to call the parent class method.
    - * @param {Object=} opt_target Target of the event causing the hide.
    - * @protected
    - * @suppress {underscore|visibility}
    - * @override
    - */
    -goog.ui.MenuBase.prototype.onHide_ = function(opt_target) {
    -  goog.ui.MenuBase.superClass_.onHide_.call(this, opt_target);
    -
    -  // remove listeners when hidden
    -  this.eventHandler_.removeAll();
    -};
    -
    -
    -/**
    - * Returns the selected item
    - *
    - * @return {Object} The item selected or null if no item is selected.
    - */
    -goog.ui.MenuBase.prototype.getSelectedItem = function() {
    -  return null;
    -};
    -
    -
    -/**
    - * Sets the selected item
    - *
    - * @param {Object} item The item to select. The type of this item is specific
    - *     to the menu class.
    - */
    -goog.ui.MenuBase.prototype.setSelectedItem = function(item) {
    -};
    -
    -
    -/**
    - * Mouse over handler for the menu. Derived classes should override.
    - *
    - * @param {goog.events.Event} e The event object.
    - * @protected
    - */
    -goog.ui.MenuBase.prototype.onMouseOver = function(e) {
    -};
    -
    -
    -/**
    - * Mouse out handler for the menu. Derived classes should override.
    - *
    - * @param {goog.events.Event} e The event object.
    - * @protected
    - */
    -goog.ui.MenuBase.prototype.onMouseOut = function(e) {
    -};
    -
    -
    -/**
    - * Mouse down handler for the menu. Derived classes should override.
    - *
    - * @param {!goog.events.Event} e The event object.
    - * @protected
    - */
    -goog.ui.MenuBase.prototype.onMouseDown = function(e) {
    -};
    -
    -
    -/**
    - * Mouse up handler for the menu. Derived classes should override.
    - *
    - * @param {goog.events.Event} e The event object.
    - * @protected
    - */
    -goog.ui.MenuBase.prototype.onMouseUp = function(e) {
    -};
    -
    -
    -/**
    - * Key down handler for the menu. Derived classes should override.
    - *
    - * @param {goog.events.KeyEvent} e The event object.
    - * @protected
    - */
    -goog.ui.MenuBase.prototype.onKeyDown = function(e) {
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/menubutton.js b/src/database/third_party/closure-library/closure/goog/ui/menubutton.js
    deleted file mode 100644
    index c9e20fd977b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/menubutton.js
    +++ /dev/null
    @@ -1,1052 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A menu button control.
    - *
    - * @author attila@google.com (Attila Bodis)
    - * @see ../demos/menubutton.html
    - */
    -
    -goog.provide('goog.ui.MenuButton');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.events.KeyHandler');
    -goog.require('goog.math.Box');
    -goog.require('goog.math.Rect');
    -goog.require('goog.positioning');
    -goog.require('goog.positioning.Corner');
    -goog.require('goog.positioning.MenuAnchoredPosition');
    -goog.require('goog.positioning.Overflow');
    -goog.require('goog.style');
    -goog.require('goog.ui.Button');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.IdGenerator');
    -goog.require('goog.ui.Menu');
    -goog.require('goog.ui.MenuButtonRenderer');
    -goog.require('goog.ui.MenuItem');
    -goog.require('goog.ui.MenuRenderer');
    -goog.require('goog.ui.registry');
    -goog.require('goog.userAgent');
    -goog.require('goog.userAgent.product');
    -
    -
    -
    -/**
    - * A menu button control.  Extends {@link goog.ui.Button} by composing a button
    - * with a dropdown arrow and a popup menu.
    - *
    - * @param {goog.ui.ControlContent=} opt_content Text caption or existing DOM
    - *     structure to display as the button's caption (if any).
    - * @param {goog.ui.Menu=} opt_menu Menu to render under the button when clicked.
    - * @param {goog.ui.ButtonRenderer=} opt_renderer Renderer used to render or
    - *     decorate the menu button; defaults to {@link goog.ui.MenuButtonRenderer}.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @param {!goog.ui.MenuRenderer=} opt_menuRenderer Renderer used to render or
    - *     decorate the menu; defaults to {@link goog.ui.MenuRenderer}.
    - * @constructor
    - * @extends {goog.ui.Button}
    - */
    -goog.ui.MenuButton = function(opt_content, opt_menu, opt_renderer,
    -    opt_domHelper, opt_menuRenderer) {
    -  goog.ui.Button.call(this, opt_content, opt_renderer ||
    -      goog.ui.MenuButtonRenderer.getInstance(), opt_domHelper);
    -
    -  // Menu buttons support the OPENED state.
    -  this.setSupportedState(goog.ui.Component.State.OPENED, true);
    -
    -  /**
    -   * The menu position on this button.
    -   * @type {!goog.positioning.AnchoredPosition}
    -   * @private
    -   */
    -  this.menuPosition_ = new goog.positioning.MenuAnchoredPosition(
    -      null, goog.positioning.Corner.BOTTOM_START);
    -
    -  if (opt_menu) {
    -    this.setMenu(opt_menu);
    -  }
    -  this.menuMargin_ = null;
    -  this.timer_ = new goog.Timer(500);  // 0.5 sec
    -
    -  // Phones running iOS prior to version 4.2.
    -  if ((goog.userAgent.product.IPHONE || goog.userAgent.product.IPAD) &&
    -      // Check the webkit version against the version for iOS 4.2.1.
    -      !goog.userAgent.isVersionOrHigher('533.17.9')) {
    -    // @bug 4322060 This is required so that the menu works correctly on
    -    // iOS prior to version 4.2. Otherwise, the blur action closes the menu
    -    // before the menu button click can be processed.
    -    this.setFocusablePopupMenu(true);
    -  }
    -
    -  /** @private {!goog.ui.MenuRenderer} */
    -  this.menuRenderer_ = opt_menuRenderer || goog.ui.MenuRenderer.getInstance();
    -};
    -goog.inherits(goog.ui.MenuButton, goog.ui.Button);
    -goog.tagUnsealableClass(goog.ui.MenuButton);
    -
    -
    -/**
    - * The menu.
    - * @type {goog.ui.Menu|undefined}
    - * @private
    - */
    -goog.ui.MenuButton.prototype.menu_;
    -
    -
    -/**
    - * The position element.  If set, use positionElement_ to position the
    - * popup menu instead of the default which is to use the menu button element.
    - * @type {Element|undefined}
    - * @private
    - */
    -goog.ui.MenuButton.prototype.positionElement_;
    -
    -
    -/**
    - * The margin to apply to the menu's position when it is shown.  If null, no
    - * margin will be applied.
    - * @type {goog.math.Box}
    - * @private
    - */
    -goog.ui.MenuButton.prototype.menuMargin_;
    -
    -
    -/**
    - * Whether the attached popup menu is focusable or not (defaults to false).
    - * Popup menus attached to menu buttons usually don't need to be focusable,
    - * i.e. the button retains keyboard focus, and forwards key events to the
    - * menu for processing.  However, menus like {@link goog.ui.FilteredMenu}
    - * need to be focusable.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.MenuButton.prototype.isFocusablePopupMenu_ = false;
    -
    -
    -/**
    - * A Timer to correct menu position.
    - * @type {goog.Timer}
    - * @private
    - */
    -goog.ui.MenuButton.prototype.timer_;
    -
    -
    -/**
    - * The bounding rectangle of the button element.
    - * @type {goog.math.Rect}
    - * @private
    - */
    -goog.ui.MenuButton.prototype.buttonRect_;
    -
    -
    -/**
    - * The viewport rectangle.
    - * @type {goog.math.Box}
    - * @private
    - */
    -goog.ui.MenuButton.prototype.viewportBox_;
    -
    -
    -/**
    - * The original size.
    - * @type {goog.math.Size|undefined}
    - * @private
    - */
    -goog.ui.MenuButton.prototype.originalSize_;
    -
    -
    -/**
    - * Do we render the drop down menu as a sibling to the label, or at the end
    - * of the current dom?
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.MenuButton.prototype.renderMenuAsSibling_ = false;
    -
    -
    -/**
    - * Whether to select the first item in the menu when it is opened using
    - * enter or space. By default, the first item is selected only when
    - * opened by a key up or down event. When this is on, the first item will
    - * be selected due to any of the four events.
    - * @private
    - */
    -goog.ui.MenuButton.prototype.selectFirstOnEnterOrSpace_ = false;
    -
    -
    -/**
    - * Sets up event handlers specific to menu buttons.
    - * @override
    - */
    -goog.ui.MenuButton.prototype.enterDocument = function() {
    -  goog.ui.MenuButton.superClass_.enterDocument.call(this);
    -  this.attachKeyDownEventListener_(true);
    -  if (this.menu_) {
    -    this.attachMenuEventListeners_(this.menu_, true);
    -  }
    -  goog.a11y.aria.setState(this.getElementStrict(),
    -      goog.a11y.aria.State.HASPOPUP, !!this.menu_);
    -};
    -
    -
    -/**
    - * Removes event handlers specific to menu buttons, and ensures that the
    - * attached menu also exits the document.
    - * @override
    - */
    -goog.ui.MenuButton.prototype.exitDocument = function() {
    -  goog.ui.MenuButton.superClass_.exitDocument.call(this);
    -  this.attachKeyDownEventListener_(false);
    -  if (this.menu_) {
    -    this.setOpen(false);
    -    this.menu_.exitDocument();
    -    this.attachMenuEventListeners_(this.menu_, false);
    -
    -    var menuElement = this.menu_.getElement();
    -    if (menuElement) {
    -      goog.dom.removeNode(menuElement);
    -    }
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.MenuButton.prototype.disposeInternal = function() {
    -  goog.ui.MenuButton.superClass_.disposeInternal.call(this);
    -  if (this.menu_) {
    -    this.menu_.dispose();
    -    delete this.menu_;
    -  }
    -  delete this.positionElement_;
    -  this.timer_.dispose();
    -};
    -
    -
    -/**
    - * Handles mousedown events.  Invokes the superclass implementation to dispatch
    - * an ACTIVATE event and activate the button.  Also toggles the visibility of
    - * the attached menu.
    - * @param {goog.events.Event} e Mouse event to handle.
    - * @override
    - * @protected
    - */
    -goog.ui.MenuButton.prototype.handleMouseDown = function(e) {
    -  goog.ui.MenuButton.superClass_.handleMouseDown.call(this, e);
    -  if (this.isActive()) {
    -    // The component was allowed to activate; toggle menu visibility.
    -    this.setOpen(!this.isOpen(), e);
    -    if (this.menu_) {
    -      this.menu_.setMouseButtonPressed(this.isOpen());
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Handles mouseup events.  Invokes the superclass implementation to dispatch
    - * an ACTION event and deactivate the button.
    - * @param {goog.events.Event} e Mouse event to handle.
    - * @override
    - * @protected
    - */
    -goog.ui.MenuButton.prototype.handleMouseUp = function(e) {
    -  goog.ui.MenuButton.superClass_.handleMouseUp.call(this, e);
    -  if (this.menu_ && !this.isActive()) {
    -    this.menu_.setMouseButtonPressed(false);
    -  }
    -};
    -
    -
    -/**
    - * Performs the appropriate action when the menu button is activated by the
    - * user.  Overrides the superclass implementation by not dispatching an {@code
    - * ACTION} event, because menu buttons exist only to reveal menus, not to
    - * perform actions themselves.  Calls {@link #setActive} to deactivate the
    - * button.
    - * @param {goog.events.Event} e Mouse or key event that triggered the action.
    - * @return {boolean} Whether the action was allowed to proceed.
    - * @override
    - * @protected
    - */
    -goog.ui.MenuButton.prototype.performActionInternal = function(e) {
    -  this.setActive(false);
    -  return true;
    -};
    -
    -
    -/**
    - * Handles mousedown events over the document.  If the mousedown happens over
    - * an element unrelated to the component, hides the menu.
    - * TODO(attila): Reconcile this with goog.ui.Popup (and handle frames/windows).
    - * @param {goog.events.BrowserEvent} e Mouse event to handle.
    - * @protected
    - */
    -goog.ui.MenuButton.prototype.handleDocumentMouseDown = function(e) {
    -  if (this.menu_ &&
    -      this.menu_.isVisible() &&
    -      !this.containsElement(/** @type {Element} */ (e.target))) {
    -    // User clicked somewhere else in the document while the menu was visible;
    -    // dismiss menu.
    -    this.setOpen(false);
    -  }
    -};
    -
    -
    -/**
    - * Returns true if the given element is to be considered part of the component,
    - * even if it isn't a DOM descendant of the component's root element.
    - * @param {Element} element Element to test (if any).
    - * @return {boolean} Whether the element is considered part of the component.
    - * @protected
    - */
    -goog.ui.MenuButton.prototype.containsElement = function(element) {
    -  return element && goog.dom.contains(this.getElement(), element) ||
    -      this.menu_ && this.menu_.containsElement(element) || false;
    -};
    -
    -
    -/** @override */
    -goog.ui.MenuButton.prototype.handleKeyEventInternal = function(e) {
    -  // Handle SPACE on keyup and all other keys on keypress.
    -  if (e.keyCode == goog.events.KeyCodes.SPACE) {
    -    // Prevent page scrolling in Chrome.
    -    e.preventDefault();
    -    if (e.type != goog.events.EventType.KEYUP) {
    -      // Ignore events because KeyCodes.SPACE is handled further down.
    -      return true;
    -    }
    -  } else if (e.type != goog.events.KeyHandler.EventType.KEY) {
    -    return false;
    -  }
    -
    -  if (this.menu_ && this.menu_.isVisible()) {
    -    // Menu is open.
    -    var isEnterOrSpace = e.keyCode == goog.events.KeyCodes.ENTER ||
    -        e.keyCode == goog.events.KeyCodes.SPACE;
    -    var handledByMenu = this.menu_.handleKeyEvent(e);
    -    if (e.keyCode == goog.events.KeyCodes.ESC || isEnterOrSpace) {
    -      // Dismiss the menu.
    -      this.setOpen(false);
    -      return true;
    -    }
    -    return handledByMenu;
    -  }
    -
    -  if (e.keyCode == goog.events.KeyCodes.DOWN ||
    -      e.keyCode == goog.events.KeyCodes.UP ||
    -      e.keyCode == goog.events.KeyCodes.SPACE ||
    -      e.keyCode == goog.events.KeyCodes.ENTER) {
    -    // Menu is closed, and the user hit the down/up/space/enter key; open menu.
    -    this.setOpen(true, e);
    -    return true;
    -  }
    -
    -  // Key event wasn't handled by the component.
    -  return false;
    -};
    -
    -
    -/**
    - * Handles {@code ACTION} events dispatched by an activated menu item.
    - * @param {goog.events.Event} e Action event to handle.
    - * @protected
    - */
    -goog.ui.MenuButton.prototype.handleMenuAction = function(e) {
    -  // Close the menu on click.
    -  this.setOpen(false);
    -};
    -
    -
    -/**
    - * Handles {@code BLUR} events dispatched by the popup menu by closing it.
    - * Only registered if the menu is focusable.
    - * @param {goog.events.Event} e Blur event dispatched by a focusable menu.
    - */
    -goog.ui.MenuButton.prototype.handleMenuBlur = function(e) {
    -  // Close the menu when it reports that it lost focus, unless the button is
    -  // pressed (active).
    -  if (!this.isActive()) {
    -    this.setOpen(false);
    -  }
    -};
    -
    -
    -/**
    - * Handles blur events dispatched by the button's key event target when it
    - * loses keyboard focus by closing the popup menu (unless it is focusable).
    - * Only registered if the button is focusable.
    - * @param {goog.events.Event} e Blur event dispatched by the menu button.
    - * @override
    - * @protected
    - */
    -goog.ui.MenuButton.prototype.handleBlur = function(e) {
    -  if (!this.isFocusablePopupMenu()) {
    -    this.setOpen(false);
    -  }
    -  goog.ui.MenuButton.superClass_.handleBlur.call(this, e);
    -};
    -
    -
    -/**
    - * Returns the menu attached to the button.  If no menu is attached, creates a
    - * new empty menu.
    - * @return {goog.ui.Menu} Popup menu attached to the menu button.
    - */
    -goog.ui.MenuButton.prototype.getMenu = function() {
    -  if (!this.menu_) {
    -    this.setMenu(new goog.ui.Menu(this.getDomHelper(), this.menuRenderer_));
    -  }
    -  return this.menu_ || null;
    -};
    -
    -
    -/**
    - * Replaces the menu attached to the button with the argument, and returns the
    - * previous menu (if any).
    - * @param {goog.ui.Menu?} menu New menu to be attached to the menu button (null
    - *     to remove the menu).
    - * @return {goog.ui.Menu|undefined} Previous menu (undefined if none).
    - */
    -goog.ui.MenuButton.prototype.setMenu = function(menu) {
    -  var oldMenu = this.menu_;
    -
    -  // Do nothing unless the new menu is different from the current one.
    -  if (menu != oldMenu) {
    -    if (oldMenu) {
    -      this.setOpen(false);
    -      if (this.isInDocument()) {
    -        this.attachMenuEventListeners_(oldMenu, false);
    -      }
    -      delete this.menu_;
    -    }
    -    if (this.isInDocument()) {
    -      goog.a11y.aria.setState(this.getElementStrict(),
    -          goog.a11y.aria.State.HASPOPUP, !!menu);
    -    }
    -    if (menu) {
    -      this.menu_ = menu;
    -      menu.setParent(this);
    -      menu.setVisible(false);
    -      menu.setAllowAutoFocus(this.isFocusablePopupMenu());
    -      if (this.isInDocument()) {
    -        this.attachMenuEventListeners_(menu, true);
    -      }
    -    }
    -  }
    -
    -  return oldMenu;
    -};
    -
    -
    -/**
    - * Specify which positioning algorithm to use.
    - *
    - * This method is preferred over the fine-grained positioning methods like
    - * setPositionElement, setAlignMenuToStart, and setScrollOnOverflow. Calling
    - * this method will override settings by those methods.
    - *
    - * @param {goog.positioning.AnchoredPosition} position The position of the
    - *     Menu the button. If the position has a null anchor, we will use the
    - *     menubutton element as the anchor.
    - */
    -goog.ui.MenuButton.prototype.setMenuPosition = function(position) {
    -  if (position) {
    -    this.menuPosition_ = position;
    -    this.positionElement_ = position.element;
    -  }
    -};
    -
    -
    -/**
    - * Sets an element for anchoring the menu.
    - * @param {Element} positionElement New element to use for
    - *     positioning the dropdown menu.  Null to use the default behavior
    - *     of positioning to this menu button.
    - */
    -goog.ui.MenuButton.prototype.setPositionElement = function(
    -    positionElement) {
    -  this.positionElement_ = positionElement;
    -  this.positionMenu();
    -};
    -
    -
    -/**
    - * Sets a margin that will be applied to the menu's position when it is shown.
    - * If null, no margin will be applied.
    - * @param {goog.math.Box} margin Margin to apply.
    - */
    -goog.ui.MenuButton.prototype.setMenuMargin = function(margin) {
    -  this.menuMargin_ = margin;
    -};
    -
    -
    -/**
    - * Sets whether to select the first item in the menu when it is opened using
    - * enter or space. By default, the first item is selected only when
    - * opened by a key up or down event. When this is on, the first item will
    - * be selected due to any of the four events.
    - * @param {boolean} select
    - */
    -goog.ui.MenuButton.prototype.setSelectFirstOnEnterOrSpace = function(select) {
    -  this.selectFirstOnEnterOrSpace_ = select;
    -};
    -
    -
    -/**
    - * Adds a new menu item at the end of the menu.
    - * @param {goog.ui.MenuItem|goog.ui.MenuSeparator|goog.ui.Control} item Menu
    - *     item to add to the menu.
    - */
    -goog.ui.MenuButton.prototype.addItem = function(item) {
    -  this.getMenu().addChild(item, true);
    -};
    -
    -
    -/**
    - * Adds a new menu item at the specific index in the menu.
    - * @param {goog.ui.MenuItem|goog.ui.MenuSeparator} item Menu item to add to the
    - *     menu.
    - * @param {number} index Index at which to insert the menu item.
    - */
    -goog.ui.MenuButton.prototype.addItemAt = function(item, index) {
    -  this.getMenu().addChildAt(item, index, true);
    -};
    -
    -
    -/**
    - * Removes the item from the menu and disposes of it.
    - * @param {goog.ui.MenuItem|goog.ui.MenuSeparator} item The menu item to remove.
    - */
    -goog.ui.MenuButton.prototype.removeItem = function(item) {
    -  var child = this.getMenu().removeChild(item, true);
    -  if (child) {
    -    child.dispose();
    -  }
    -};
    -
    -
    -/**
    - * Removes the menu item at a given index in the menu and disposes of it.
    - * @param {number} index Index of item.
    - */
    -goog.ui.MenuButton.prototype.removeItemAt = function(index) {
    -  var child = this.getMenu().removeChildAt(index, true);
    -  if (child) {
    -    child.dispose();
    -  }
    -};
    -
    -
    -/**
    - * Returns the menu item at a given index.
    - * @param {number} index Index of menu item.
    - * @return {goog.ui.MenuItem?} Menu item (null if not found).
    - */
    -goog.ui.MenuButton.prototype.getItemAt = function(index) {
    -  return this.menu_ ?
    -      /** @type {goog.ui.MenuItem} */ (this.menu_.getChildAt(index)) : null;
    -};
    -
    -
    -/**
    - * Returns the number of items in the menu (including separators).
    - * @return {number} The number of items in the menu.
    - */
    -goog.ui.MenuButton.prototype.getItemCount = function() {
    -  return this.menu_ ? this.menu_.getChildCount() : 0;
    -};
    -
    -
    -/**
    - * Shows/hides the menu button based on the value of the argument.  Also hides
    - * the popup menu if the button is being hidden.
    - * @param {boolean} visible Whether to show or hide the button.
    - * @param {boolean=} opt_force If true, doesn't check whether the component
    - *     already has the requested visibility, and doesn't dispatch any events.
    - * @return {boolean} Whether the visibility was changed.
    - * @override
    - */
    -goog.ui.MenuButton.prototype.setVisible = function(visible, opt_force) {
    -  var visibilityChanged = goog.ui.MenuButton.superClass_.setVisible.call(this,
    -      visible, opt_force);
    -  if (visibilityChanged && !this.isVisible()) {
    -    this.setOpen(false);
    -  }
    -  return visibilityChanged;
    -};
    -
    -
    -/**
    - * Enables/disables the menu button based on the value of the argument, and
    - * updates its CSS styling.  Also hides the popup menu if the button is being
    - * disabled.
    - * @param {boolean} enable Whether to enable or disable the button.
    - * @override
    - */
    -goog.ui.MenuButton.prototype.setEnabled = function(enable) {
    -  goog.ui.MenuButton.superClass_.setEnabled.call(this, enable);
    -  if (!this.isEnabled()) {
    -    this.setOpen(false);
    -  }
    -};
    -
    -
    -// TODO(nicksantos): AlignMenuToStart and ScrollOnOverflow and PositionElement
    -// should all be deprecated, in favor of people setting their own
    -// AnchoredPosition with the parameters they need. Right now, we try
    -// to be backwards-compatible as possible, but this is incomplete because
    -// the APIs are non-orthogonal.
    -
    -
    -/**
    - * @return {boolean} Whether the menu is aligned to the start of the button
    - *     (left if the render direction is left-to-right, right if the render
    - *     direction is right-to-left).
    - */
    -goog.ui.MenuButton.prototype.isAlignMenuToStart = function() {
    -  var corner = this.menuPosition_.corner;
    -  return corner == goog.positioning.Corner.BOTTOM_START ||
    -      corner == goog.positioning.Corner.TOP_START;
    -};
    -
    -
    -/**
    - * Sets whether the menu is aligned to the start or the end of the button.
    - * @param {boolean} alignToStart Whether the menu is to be aligned to the start
    - *     of the button (left if the render direction is left-to-right, right if
    - *     the render direction is right-to-left).
    - */
    -goog.ui.MenuButton.prototype.setAlignMenuToStart = function(alignToStart) {
    -  this.menuPosition_.corner = alignToStart ?
    -      goog.positioning.Corner.BOTTOM_START :
    -      goog.positioning.Corner.BOTTOM_END;
    -};
    -
    -
    -/**
    - * Sets whether the menu should scroll when it's too big to fix vertically on
    - * the screen.  The css of the menu element should have overflow set to auto.
    - * Note: Adding or removing items while the menu is open will not work correctly
    - * if scrollOnOverflow is on.
    - * @param {boolean} scrollOnOverflow Whether the menu should scroll when too big
    - *     to fit on the screen.  If false, adjust logic will be used to try and
    - *     reposition the menu to fit.
    - */
    -goog.ui.MenuButton.prototype.setScrollOnOverflow = function(scrollOnOverflow) {
    -  if (this.menuPosition_.setLastResortOverflow) {
    -    var overflowX = goog.positioning.Overflow.ADJUST_X;
    -    var overflowY = scrollOnOverflow ?
    -        goog.positioning.Overflow.RESIZE_HEIGHT :
    -        goog.positioning.Overflow.ADJUST_Y;
    -    this.menuPosition_.setLastResortOverflow(overflowX | overflowY);
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} Wether the menu will scroll when it's to big to fit
    - *     vertically on the screen.
    - */
    -goog.ui.MenuButton.prototype.isScrollOnOverflow = function() {
    -  return this.menuPosition_.getLastResortOverflow &&
    -      !!(this.menuPosition_.getLastResortOverflow() &
    -         goog.positioning.Overflow.RESIZE_HEIGHT);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the attached menu is focusable.
    - */
    -goog.ui.MenuButton.prototype.isFocusablePopupMenu = function() {
    -  return this.isFocusablePopupMenu_;
    -};
    -
    -
    -/**
    - * Sets whether the attached popup menu is focusable.  If the popup menu is
    - * focusable, it may steal keyboard focus from the menu button, so the button
    - * will not hide the menu on blur.
    - * @param {boolean} focusable Whether the attached menu is focusable.
    - */
    -goog.ui.MenuButton.prototype.setFocusablePopupMenu = function(focusable) {
    -  // TODO(attila):  The menu itself should advertise whether it is focusable.
    -  this.isFocusablePopupMenu_ = focusable;
    -};
    -
    -
    -/**
    - * Sets whether to render the menu as a sibling element of the button.
    - * Normally, the menu is a child of document.body.  This option is useful if
    - * you need the menu to inherit styles from a common parent element, or if you
    - * otherwise need it to share a parent element for desired event handling.  One
    - * example of the latter is if the parent is in a goog.ui.Popup, to ensure that
    - * clicks on the menu are considered being within the popup.
    - * @param {boolean} renderMenuAsSibling Whether we render the menu at the end
    - *     of the dom or as a sibling to the button/label that renders the drop
    - *     down.
    - */
    -goog.ui.MenuButton.prototype.setRenderMenuAsSibling = function(
    -    renderMenuAsSibling) {
    -  this.renderMenuAsSibling_ = renderMenuAsSibling;
    -};
    -
    -
    -/**
    - * Reveals the menu and hooks up menu-specific event handling.
    - * @deprecated Use {@link #setOpen} instead.
    - */
    -goog.ui.MenuButton.prototype.showMenu = function() {
    -  this.setOpen(true);
    -};
    -
    -
    -/**
    - * Hides the menu and cleans up menu-specific event handling.
    - * @deprecated Use {@link #setOpen} instead.
    - */
    -goog.ui.MenuButton.prototype.hideMenu = function() {
    -  this.setOpen(false);
    -};
    -
    -
    -/**
    - * Opens or closes the attached popup menu.
    - * @param {boolean} open Whether to open or close the menu.
    - * @param {goog.events.Event=} opt_e Event that caused the menu to be opened.
    - * @override
    - */
    -goog.ui.MenuButton.prototype.setOpen = function(open, opt_e) {
    -  goog.ui.MenuButton.superClass_.setOpen.call(this, open);
    -  if (this.menu_ && this.hasState(goog.ui.Component.State.OPENED) == open) {
    -    if (open) {
    -      if (!this.menu_.isInDocument()) {
    -        if (this.renderMenuAsSibling_) {
    -          // When we render the menu in the same parent as this button, we
    -          // prefer to add it immediately after the button. This way, the screen
    -          // readers will go to the menu on the very next element after the
    -          // button is read.
    -          var nextElementSibling =
    -              goog.dom.getNextElementSibling(this.getElement());
    -          if (nextElementSibling) {
    -            this.menu_.renderBefore(nextElementSibling);
    -          } else {
    -            this.menu_.render(/** @type {Element} */ (
    -                this.getElement().parentNode));
    -          }
    -        } else {
    -          this.menu_.render();
    -        }
    -      }
    -      this.viewportBox_ =
    -          goog.style.getVisibleRectForElement(this.getElement());
    -      this.buttonRect_ = goog.style.getBounds(this.getElement());
    -      this.positionMenu();
    -
    -      // As per aria spec, highlight the first element in the menu when
    -      // keyboarding up or down. Thus, the first menu item will be announced
    -      // for screen reader users. If selectFirstOnEnterOrSpace is set, do this
    -      // for enter or space as well.
    -      var isEnterOrSpace = !!opt_e &&
    -          (opt_e.keyCode == goog.events.KeyCodes.ENTER ||
    -           opt_e.keyCode == goog.events.KeyCodes.SPACE);
    -      var isUpOrDown = !!opt_e &&
    -          (opt_e.keyCode == goog.events.KeyCodes.DOWN ||
    -           opt_e.keyCode == goog.events.KeyCodes.UP);
    -      var focus = isUpOrDown ||
    -          (isEnterOrSpace && this.selectFirstOnEnterOrSpace_);
    -      if (focus) {
    -        this.menu_.highlightFirst();
    -      } else {
    -        this.menu_.setHighlightedIndex(-1);
    -      }
    -    } else {
    -      this.setActive(false);
    -      this.menu_.setMouseButtonPressed(false);
    -
    -      var element = this.getElement();
    -      // Clear any remaining a11y state.
    -      if (element) {
    -        goog.a11y.aria.setState(element,
    -            goog.a11y.aria.State.ACTIVEDESCENDANT,
    -            '');
    -        goog.a11y.aria.setState(element,
    -            goog.a11y.aria.State.OWNS,
    -            '');
    -      }
    -
    -      // Clear any sizes that might have been stored.
    -      if (goog.isDefAndNotNull(this.originalSize_)) {
    -        this.originalSize_ = undefined;
    -        var elem = this.menu_.getElement();
    -        if (elem) {
    -          goog.style.setSize(elem, '', '');
    -        }
    -      }
    -    }
    -    this.menu_.setVisible(open, false, opt_e);
    -    // In Pivot Tables the menu button somehow gets disposed of during the
    -    // setVisible call, causing attachPopupListeners_ to fail.
    -    // TODO(user): Debug what happens.
    -    if (!this.isDisposed()) {
    -      this.attachPopupListeners_(open);
    -    }
    -  }
    -  if (this.menu_ && this.menu_.getElement()) {
    -    // Remove the aria-hidden state on the menu element so that it won't be
    -    // hidden to screen readers if it's inside a dialog (see b/17610491).
    -    goog.a11y.aria.removeState(
    -        this.menu_.getElementStrict(), goog.a11y.aria.State.HIDDEN);
    -  }
    -};
    -
    -
    -/**
    - * Resets the MenuButton's size.  This is useful for cases where items are added
    - * or removed from the menu and scrollOnOverflow is on.  In those cases the
    - * menu will not behave correctly and resize itself unless this is called
    - * (usually followed by positionMenu()).
    - */
    -goog.ui.MenuButton.prototype.invalidateMenuSize = function() {
    -  this.originalSize_ = undefined;
    -};
    -
    -
    -/**
    - * Positions the menu under the button.  May be called directly in cases when
    - * the menu size is known to change.
    - */
    -goog.ui.MenuButton.prototype.positionMenu = function() {
    -  if (!this.menu_.isInDocument()) {
    -    return;
    -  }
    -
    -  var positionElement = this.positionElement_ || this.getElement();
    -  var position = this.menuPosition_;
    -  this.menuPosition_.element = positionElement;
    -
    -  var elem = this.menu_.getElement();
    -  if (!this.menu_.isVisible()) {
    -    elem.style.visibility = 'hidden';
    -    goog.style.setElementShown(elem, true);
    -  }
    -
    -  if (!this.originalSize_ && this.isScrollOnOverflow()) {
    -    this.originalSize_ = goog.style.getSize(elem);
    -  }
    -  var popupCorner = goog.positioning.flipCornerVertical(position.corner);
    -  position.reposition(elem, popupCorner, this.menuMargin_, this.originalSize_);
    -
    -  if (!this.menu_.isVisible()) {
    -    goog.style.setElementShown(elem, false);
    -    elem.style.visibility = 'visible';
    -  }
    -};
    -
    -
    -/**
    - * Periodically repositions the menu while it is visible.
    - *
    - * @param {goog.events.Event} e An event object.
    - * @private
    - */
    -goog.ui.MenuButton.prototype.onTick_ = function(e) {
    -  // Call positionMenu() only if the button position or size was
    -  // changed, or if the window's viewport was changed.
    -  var currentButtonRect = goog.style.getBounds(this.getElement());
    -  var currentViewport = goog.style.getVisibleRectForElement(this.getElement());
    -  if (!goog.math.Rect.equals(this.buttonRect_, currentButtonRect) ||
    -      !goog.math.Box.equals(this.viewportBox_, currentViewport)) {
    -    this.buttonRect_ = currentButtonRect;
    -    this.viewportBox_ = currentViewport;
    -    this.positionMenu();
    -  }
    -};
    -
    -
    -/**
    - * Attaches or detaches menu event listeners to/from the given menu.
    - * Called each time a menu is attached to or detached from the button.
    - * @param {goog.ui.Menu} menu Menu on which to listen for events.
    - * @param {boolean} attach Whether to attach or detach event listeners.
    - * @private
    - */
    -goog.ui.MenuButton.prototype.attachMenuEventListeners_ = function(menu,
    -    attach) {
    -  var handler = this.getHandler();
    -  var method = attach ? handler.listen : handler.unlisten;
    -
    -  // Handle events dispatched by menu items.
    -  method.call(handler, menu, goog.ui.Component.EventType.ACTION,
    -      this.handleMenuAction);
    -  method.call(handler, menu, goog.ui.Component.EventType.CLOSE,
    -      this.handleCloseItem);
    -  method.call(handler, menu, goog.ui.Component.EventType.HIGHLIGHT,
    -      this.handleHighlightItem);
    -  method.call(handler, menu, goog.ui.Component.EventType.UNHIGHLIGHT,
    -      this.handleUnHighlightItem);
    -};
    -
    -
    -/**
    - * Attaches or detaches a keydown event listener to/from the given element.
    - * Called each time the button enters or exits the document.
    - * @param {boolean} attach Whether to attach or detach the event listener.
    - * @private
    - */
    -goog.ui.MenuButton.prototype.attachKeyDownEventListener_ = function(attach) {
    -  var handler = this.getHandler();
    -  var method = attach ? handler.listen : handler.unlisten;
    -
    -  // Handle keydown events dispatched by the button.
    -  method.call(handler, this.getElement(), goog.events.EventType.KEYDOWN,
    -      this.handleKeyDownEvent_);
    -};
    -
    -
    -/**
    - * Handles {@code HIGHLIGHT} events dispatched by the attached menu.
    - * @param {goog.events.Event} e Highlight event to handle.
    - */
    -goog.ui.MenuButton.prototype.handleHighlightItem = function(e) {
    -  var targetEl = e.target.getElement();
    -  if (targetEl) {
    -    this.setAriaActiveDescendant_(targetEl);
    -  }
    -};
    -
    -
    -/**
    - * Handles {@code KEYDOWN} events dispatched by the button element. When the
    - * button is focusable and the menu is present and visible, prevents the event
    - * from propagating since the desired behavior is only to close the menu.
    - * @param {goog.events.Event} e KeyDown event to handle.
    - * @private
    - */
    -goog.ui.MenuButton.prototype.handleKeyDownEvent_ = function(e) {
    -  if (this.isSupportedState(goog.ui.Component.State.FOCUSED) &&
    -      this.getKeyEventTarget() && this.menu_ && this.menu_.isVisible()) {
    -    e.stopPropagation();
    -  }
    -};
    -
    -
    -/**
    - * Handles UNHIGHLIGHT events dispatched by the associated menu.
    - * @param {goog.events.Event} e Unhighlight event to handle.
    - */
    -goog.ui.MenuButton.prototype.handleUnHighlightItem = function(e) {
    -  if (!this.menu_.getHighlighted()) {
    -    var element = this.getElement();
    -    goog.asserts.assert(element, 'The menu button DOM element cannot be null.');
    -    goog.a11y.aria.setState(element,
    -        goog.a11y.aria.State.ACTIVEDESCENDANT, '');
    -    goog.a11y.aria.setState(element,
    -        goog.a11y.aria.State.OWNS, '');
    -  }
    -};
    -
    -
    -/**
    - * Handles {@code CLOSE} events dispatched by the associated menu.
    - * @param {goog.events.Event} e Close event to handle.
    - */
    -goog.ui.MenuButton.prototype.handleCloseItem = function(e) {
    -  // When a submenu is closed by pressing left arrow, no highlight event is
    -  // dispatched because the newly focused item was already highlighted, so this
    -  // scenario is handled by listening for the submenu close event instead.
    -  if (this.isOpen() && e.target instanceof goog.ui.MenuItem) {
    -    var menuItem = /** @type {!goog.ui.MenuItem} */ (e.target);
    -    var menuItemEl = menuItem.getElement();
    -    if (menuItem.isVisible() && menuItem.isHighlighted() &&
    -        menuItemEl != null) {
    -      this.setAriaActiveDescendant_(menuItemEl);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Updates the aria-activedescendant attribute to the given target element.
    - * @param {!Element} targetEl The target element.
    - * @private
    - */
    -goog.ui.MenuButton.prototype.setAriaActiveDescendant_ = function(targetEl) {
    -  var element = this.getElement();
    -  goog.asserts.assert(element, 'The menu button DOM element cannot be null.');
    -
    -  // If target element has an activedescendant, then set this control's
    -  // activedescendant to that, otherwise set it to the target element. This is
    -  // a workaround for some screen readers which do not handle
    -  // aria-activedescendant redirection properly.
    -  var targetActiveDescendant = goog.a11y.aria.getActiveDescendant(targetEl);
    -  var activeDescendant = targetActiveDescendant || targetEl;
    -
    -  if (!activeDescendant.id) {
    -    // Create an id if there isn't one already.
    -    var idGenerator = goog.ui.IdGenerator.getInstance();
    -    activeDescendant.id = idGenerator.getNextUniqueId();
    -  }
    -
    -  goog.a11y.aria.setActiveDescendant(element, activeDescendant);
    -  goog.a11y.aria.setState(
    -      element, goog.a11y.aria.State.OWNS, activeDescendant.id);
    -};
    -
    -
    -/**
    - * Attaches or detaches event listeners depending on whether the popup menu
    - * is being shown or hidden.  Starts listening for document mousedown events
    - * and for menu blur events when the menu is shown, and stops listening for
    - * these events when it is hidden.  Called from {@link #setOpen}.
    - * @param {boolean} attach Whether to attach or detach event listeners.
    - * @private
    - */
    -goog.ui.MenuButton.prototype.attachPopupListeners_ = function(attach) {
    -  var handler = this.getHandler();
    -  var method = attach ? handler.listen : handler.unlisten;
    -
    -  // Listen for document mousedown events in the capture phase, because
    -  // the target may stop propagation of the event in the bubble phase.
    -  method.call(handler, this.getDomHelper().getDocument(),
    -      goog.events.EventType.MOUSEDOWN, this.handleDocumentMouseDown, true);
    -
    -  // Only listen for blur events dispatched by the menu if it is focusable.
    -  if (this.isFocusablePopupMenu()) {
    -    method.call(handler, /** @type {!goog.events.EventTarget} */ (this.menu_),
    -        goog.ui.Component.EventType.BLUR, this.handleMenuBlur);
    -  }
    -
    -  method.call(handler, this.timer_, goog.Timer.TICK, this.onTick_);
    -  if (attach) {
    -    this.timer_.start();
    -  } else {
    -    this.timer_.stop();
    -  }
    -};
    -
    -
    -// Register a decorator factory function for goog.ui.MenuButtons.
    -goog.ui.registry.setDecoratorByClassName(goog.ui.MenuButtonRenderer.CSS_CLASS,
    -    function() {
    -      // MenuButton defaults to using MenuButtonRenderer.
    -      return new goog.ui.MenuButton(null);
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/menubutton_test.html b/src/database/third_party/closure-library/closure/goog/ui/menubutton_test.html
    deleted file mode 100644
    index 60858ebb654..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/menubutton_test.html
    +++ /dev/null
    @@ -1,60 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -
    -  @author nicksantos@google.com (Nick Santos)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.MenuButton
    -  </title>
    -  <style type="text/css">
    -   .goog-menu {
    -  position: absolute;
    -  color: #aaa;
    -}
    -  </style>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.MenuButtonTest');
    -  </script>
    - </head>
    - <body>
    -  <iframe id="iframe1" src="menubutton_test_frame.html" width="400" height="400">
    -  </iframe>
    -  <div id="positionElement" style="position: absolute; left: 205px">
    -  </div>
    -  <p>
    -   Here's a menubutton defined in markup:
    -  </p>
    -  <div id="siblingTest">
    -  </div>
    -  <div id="demoMenuButton" class="goog-menu-button">
    -   <div id="demoMenu" class="goog-menu">
    -    <div id="menuItem1" class="goog-menuitem">
    -     Annual Report.pdf
    -    </div>
    -    <div id="menuItem2" class="goog-menuitem">
    -     Quarterly Update.pdf
    -    </div>
    -    <div id="menuItem3" class="goog-menuitem">
    -     Enemies List.txt
    -    </div>
    -   </div>
    -  </div>
    -  <div id="button1" class="goog-menu-button">
    -  </div>
    -  <div id="button2" class="goog-menu-button">
    -  </div>
    -  <div id="footer">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/menubutton_test.js b/src/database/third_party/closure-library/closure/goog/ui/menubutton_test.js
    deleted file mode 100644
    index 24be05541e2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/menubutton_test.js
    +++ /dev/null
    @@ -1,843 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.MenuButtonTest');
    -goog.setTestOnly('goog.ui.MenuButtonTest');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.events.KeyHandler');
    -goog.require('goog.positioning');
    -goog.require('goog.positioning.Corner');
    -goog.require('goog.positioning.MenuAnchoredPosition');
    -goog.require('goog.positioning.Overflow');
    -goog.require('goog.style');
    -goog.require('goog.testing.ExpectedFailures');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.Menu');
    -goog.require('goog.ui.MenuButton');
    -goog.require('goog.ui.MenuItem');
    -goog.require('goog.ui.SubMenu');
    -goog.require('goog.userAgent');
    -goog.require('goog.userAgent.product');
    -goog.require('goog.userAgent.product.isVersion');
    -
    -var menuButton;
    -var clonedMenuButtonDom;
    -var expectedFailures;
    -
    -function setUpPage() {
    -  expectedFailures = new goog.testing.ExpectedFailures();
    -}
    -
    -// Mock out goog.positioning.positionAtCoordinate to always ignore failure when
    -// the window is too small, since we don't care about the viewport size on
    -// the selenium farm.
    -// TODO(nicksantos): Move this into a common location if we ever have enough
    -// code for a general goog.testing.ui library.
    -var originalPositionAtCoordinate = goog.positioning.positionAtCoordinate;
    -goog.positioning.positionAtCoordinate = function(absolutePos, movableElement,
    -    movableElementCorner, opt_margin, opt_viewport, opt_overflow,
    -    opt_preferredSize) {
    -  return originalPositionAtCoordinate.call(this, absolutePos, movableElement,
    -      movableElementCorner, opt_margin, opt_viewport,
    -      goog.positioning.Overflow.IGNORE, opt_preferredSize);
    -};
    -
    -function MyFakeEvent(keyCode, opt_eventType) {
    -  this.type = opt_eventType || goog.events.KeyHandler.EventType.KEY;
    -  this.keyCode = keyCode;
    -  this.propagationStopped = false;
    -  this.preventDefault = goog.nullFunction;
    -  this.stopPropagation = function() {
    -    this.propagationStopped = true;
    -  };
    -}
    -
    -function setUp() {
    -  window.scrollTo(0, 0);
    -
    -  var viewportSize = goog.dom.getViewportSize();
    -  // Some tests need enough size viewport.
    -  if (viewportSize.width < 600 || viewportSize.height < 600) {
    -    window.moveTo(0, 0);
    -    window.resizeTo(640, 640);
    -  }
    -
    -  clonedMenuButtonDom = goog.dom.getElement('demoMenuButton').cloneNode(true);
    -
    -  menuButton = new goog.ui.MenuButton();
    -}
    -
    -function tearDown() {
    -  expectedFailures.handleTearDown();
    -  menuButton.dispose();
    -
    -  var element = goog.dom.getElement('demoMenuButton');
    -  element.parentNode.replaceChild(clonedMenuButtonDom, element);
    -}
    -
    -
    -/**
    - * Check if the aria-haspopup property is set correctly.
    - */
    -function checkHasPopUp() {
    -  menuButton.enterDocument();
    -  assertFalse('Menu button must have aria-haspopup attribute set to false',
    -      goog.a11y.aria.getState(menuButton.getElement(),
    -      goog.a11y.aria.State.HASPOPUP));
    -  var menu = new goog.ui.Menu();
    -  menu.createDom();
    -  menuButton.setMenu(menu);
    -  assertTrue('Menu button must have aria-haspopup attribute set to true',
    -      goog.a11y.aria.getState(menuButton.getElement(),
    -      goog.a11y.aria.State.HASPOPUP));
    -  menuButton.setMenu(null);
    -  assertFale('Menu button must have aria-haspopup attribute set to false',
    -      goog.a11y.aria.getState(menuButton.getElement(),
    -      goog.a11y.aria.State.HASPOPUP));
    -}
    -
    -
    -/**
    - * Open the menu and click on the menu item inside.
    - * Check if the aria-haspopup property is set correctly.
    - */
    -function testBasicButtonBehavior() {
    -  var node = goog.dom.getElement('demoMenuButton');
    -  menuButton.decorate(node);
    -
    -  assertEquals('Menu button must have aria-haspopup attribute set to true',
    -      'true', goog.a11y.aria.getState(menuButton.getElement(),
    -      goog.a11y.aria.State.HASPOPUP));
    -
    -  goog.testing.events.fireClickSequence(node);
    -
    -  assertTrue('Menu must open after click', menuButton.isOpen());
    -
    -  var menuItemClicked = 0;
    -  var lastMenuItemClicked = null;
    -  goog.events.listen(menuButton.getMenu(),
    -      goog.ui.Component.EventType.ACTION,
    -      function(e) {
    -        menuItemClicked++;
    -        lastMenuItemClicked = e.target;
    -      });
    -
    -  var menuItem2 = goog.dom.getElement('menuItem2');
    -  goog.testing.events.fireClickSequence(menuItem2);
    -  assertFalse('Menu must close on clicking when open', menuButton.isOpen());
    -  assertEquals('Number of menu items clicked should be 1', 1, menuItemClicked);
    -  assertEquals('menuItem2 should be the last menuitem clicked', menuItem2,
    -      lastMenuItemClicked.getElement());
    -}
    -
    -
    -/**
    - * Open the menu, highlight first menuitem and then the second.
    - * Check if the aria-activedescendant property is set correctly.
    - */
    -function testHighlightItemBehavior() {
    -  var node = goog.dom.getElement('demoMenuButton');
    -  menuButton.decorate(node);
    -  goog.testing.events.fireClickSequence(node);
    -
    -  assertTrue('Menu must open after click', menuButton.isOpen());
    -
    -  menuButton.handleKeyEvent(new MyFakeEvent(goog.events.KeyCodes.DOWN));
    -  assertNotNull(menuButton.getElement());
    -  assertEquals('First menuitem must be the aria-activedescendant',
    -      'menuItem1', goog.a11y.aria.getState(menuButton.getElement(),
    -      goog.a11y.aria.State.ACTIVEDESCENDANT));
    -
    -  menuButton.handleKeyEvent(new MyFakeEvent(goog.events.KeyCodes.DOWN));
    -  assertEquals('Second menuitem must be the aria-activedescendant',
    -      'menuItem2', goog.a11y.aria.getState(menuButton.getElement(),
    -      goog.a11y.aria.State.ACTIVEDESCENDANT));
    -}
    -
    -
    -/**
    - * Check that the appropriate items are selected when menus are opened with the
    - * keyboard and setSelectFirstOnEnterOrSpace is not set.
    - */
    -function testHighlightFirstOnOpen() {
    -  var node = goog.dom.getElement('demoMenuButton');
    -  menuButton.decorate(node);
    -  menuButton.handleKeyEvent(new MyFakeEvent(goog.events.KeyCodes.ENTER));
    -  assertEquals(
    -      'By default no items should be highlighted when opened with enter.',
    -      null, menuButton.getMenu().getHighlighted());
    -
    -  menuButton.setOpen(false);
    -  menuButton.handleKeyEvent(new MyFakeEvent(goog.events.KeyCodes.DOWN));
    -  assertTrue('Menu must open after down key', menuButton.isOpen());
    -  assertEquals('First menuitem must be highlighted',
    -      'menuItem1', menuButton.getMenu().getHighlighted().getElement().id);
    -}
    -
    -
    -/**
    - * Check that the appropriate items are selected when menus are opened with the
    - * keyboard, setSelectFirstOnEnterOrSpace is not set, and the first menu item is
    - * disabled.
    - */
    -function testHighlightFirstOnOpen_withFirstDisabled() {
    -  var node = goog.dom.getElement('demoMenuButton');
    -  menuButton.decorate(node);
    -  var menu = menuButton.getMenu();
    -  menu.getItemAt(0).setEnabled(false);
    -
    -  menuButton.handleKeyEvent(new MyFakeEvent(goog.events.KeyCodes.ENTER));
    -  assertEquals(
    -      'By default no items should be highlighted when opened with enter.',
    -      null, menuButton.getMenu().getHighlighted());
    -
    -  menuButton.setOpen(false);
    -  menuButton.handleKeyEvent(new MyFakeEvent(goog.events.KeyCodes.DOWN));
    -  assertTrue('Menu must open after down key', menuButton.isOpen());
    -  assertEquals('First enabled menuitem must be highlighted',
    -      'menuItem2', menuButton.getMenu().getHighlighted().getElement().id);
    -}
    -
    -
    -/**
    - * Check that the appropriate items are selected when menus are opened with the
    - * keyboard and setSelectFirstOnEnterOrSpace is set.
    - */
    -function testHighlightFirstOnOpen_withEnterOrSpaceSet() {
    -  var node = goog.dom.getElement('demoMenuButton');
    -  menuButton.decorate(node);
    -  menuButton.setSelectFirstOnEnterOrSpace(true);
    -  menuButton.handleKeyEvent(new MyFakeEvent(goog.events.KeyCodes.ENTER));
    -  assertEquals('The first item should be highlighted when opened with enter ' +
    -      'after setting selectFirstOnEnterOrSpace',
    -      'menuItem1', menuButton.getMenu().getHighlighted().getElement().id);
    -}
    -
    -
    -/**
    - * Check that the appropriate item is selected when a menu is opened with the
    - * keyboard, setSelectFirstOnEnterOrSpace is true, and the first menu item is
    - * disabled.
    - */
    -function testHighlightFirstOnOpen_withEnterOrSpaceSetAndFirstDisabled() {
    -  var node = goog.dom.getElement('demoMenuButton');
    -  menuButton.decorate(node);
    -  menuButton.setSelectFirstOnEnterOrSpace(true);
    -  var menu = menuButton.getMenu();
    -  menu.getItemAt(0).setEnabled(false);
    -
    -  menuButton.handleKeyEvent(new MyFakeEvent(goog.events.KeyCodes.ENTER));
    -  assertEquals('The first enabled item should be highlighted when opened ' +
    -      'with enter after setting selectFirstOnEnterOrSpace',
    -      'menuItem2', menuButton.getMenu().getHighlighted().getElement().id);
    -}
    -
    -
    -/**
    - * Open the menu, enter a submenu and then back out of it.
    - * Check if the aria-activedescendant property is set correctly.
    - */
    -function testCloseSubMenuBehavior() {
    -  var node = goog.dom.getElement('demoMenuButton');
    -  menuButton.decorate(node);
    -  var menu = menuButton.getMenu();
    -  var subMenu = new goog.ui.SubMenu('Submenu');
    -  menu.addItem(subMenu);
    -  subMenu.getElement().id = 'subMenu';
    -  var subMenuMenu = new goog.ui.Menu();
    -  subMenu.setMenu(subMenuMenu);
    -  var subMenuItem = new goog.ui.MenuItem('Submenu item 1');
    -  subMenuMenu.addItem(subMenuItem);
    -  subMenuItem.getElement().id = 'subMenuItem1';
    -  menuButton.setOpen(true);
    -
    -  for (var i = 0; i < 4; i++) {
    -    menuButton.handleKeyEvent(new MyFakeEvent(goog.events.KeyCodes.DOWN));
    -  }
    -  assertEquals('Submenu must be the aria-activedescendant',
    -      'subMenu', goog.a11y.aria.getState(menuButton.getElement(),
    -          goog.a11y.aria.State.ACTIVEDESCENDANT));
    -
    -  menuButton.handleKeyEvent(new MyFakeEvent(goog.events.KeyCodes.RIGHT));
    -  assertEquals('Submenu item 1 must be the aria-activedescendant',
    -      'subMenuItem1', goog.a11y.aria.getState(menuButton.getElement(),
    -          goog.a11y.aria.State.ACTIVEDESCENDANT));
    -
    -  menuButton.handleKeyEvent(new MyFakeEvent(goog.events.KeyCodes.LEFT));
    -  assertEquals('Submenu must be the aria-activedescendant',
    -      'subMenu', goog.a11y.aria.getState(menuButton.getElement(),
    -          goog.a11y.aria.State.ACTIVEDESCENDANT));
    -}
    -
    -
    -/**
    - * Make sure the menu opens when enter is pressed.
    - */
    -function testEnterOpensMenu() {
    -  var node = goog.dom.getElement('demoMenuButton');
    -  menuButton.decorate(node);
    -  menuButton.handleKeyEvent(new MyFakeEvent(goog.events.KeyCodes.ENTER));
    -  assertTrue('Menu must open after enter', menuButton.isOpen());
    -}
    -
    -
    -/**
    - * Tests the behavior of the enter and space keys when the menu is open.
    - */
    -function testSpaceOrEnterClosesMenu() {
    -  var node = goog.dom.getElement('demoMenuButton');
    -  menuButton.decorate(node);
    -
    -  menuButton.setOpen(true);
    -  menuButton.handleKeyEvent(new MyFakeEvent(goog.events.KeyCodes.ENTER));
    -  assertFalse('Menu should close after pressing Enter', menuButton.isOpen());
    -
    -  menuButton.setOpen(true);
    -  menuButton.handleKeyEvent(new MyFakeEvent(goog.events.KeyCodes.SPACE,
    -      goog.events.EventType.KEYUP));
    -  assertFalse('Menu should close after pressing Space', menuButton.isOpen());
    -}
    -
    -
    -/**
    - * Tests that a keydown event of the escape key propagates normally when the
    - * menu is closed.
    - */
    -function testStopEscapePropagationMenuClosed() {
    -  var node = goog.dom.getElement('demoMenuButton');
    -  var fakeEvent = new MyFakeEvent(
    -      goog.events.KeyCodes.ESCAPE, goog.events.EventType.KEYDOWN);
    -  menuButton.decorate(node);
    -  menuButton.setOpen(false);
    -
    -  menuButton.handleKeyDownEvent_(fakeEvent);
    -  assertFalse('Event propagation was erroneously stopped.',
    -      fakeEvent.propagationStopped);
    -}
    -
    -
    -/**
    - * Tests that a keydown event of the escape key is prevented from propagating
    - * when the menu is open.
    - */
    -function testStopEscapePropagationMenuOpen() {
    -  var node = goog.dom.getElement('demoMenuButton');
    -  var fakeEvent = new MyFakeEvent(
    -      goog.events.KeyCodes.ESCAPE, goog.events.EventType.KEYDOWN);
    -  menuButton.decorate(node);
    -  menuButton.setOpen(true);
    -
    -  menuButton.handleKeyDownEvent_(fakeEvent);
    -  assertTrue(
    -      'Event propagation was not stopped.', fakeEvent.propagationStopped);
    -}
    -
    -
    -/**
    - * Open the menu and click on the menu item inside after exiting and entering
    - * the document once, to test proper setup/teardown behavior of MenuButton.
    - */
    -function testButtonAfterEnterDocument() {
    -  var node = goog.dom.getElement('demoMenuButton');
    -  menuButton.decorate(node);
    -
    -  menuButton.exitDocument();
    -  menuButton.enterDocument();
    -
    -  goog.testing.events.fireClickSequence(node);
    -  assertTrue('Menu must open after click', menuButton.isOpen());
    -
    -  var menuItem2 = goog.dom.getElement('menuItem2');
    -  goog.testing.events.fireClickSequence(menuItem2);
    -  assertFalse('Menu must close on clicking when open', menuButton.isOpen());
    -}
    -
    -
    -/**
    - * Renders the menu button, moves its menu and then repositions to make sure the
    - * position is more or less ok.
    - */
    -function testPositionMenu() {
    -  var node = goog.dom.getElement('demoMenuButton');
    -  menuButton.decorate(node);
    -  var menu = menuButton.getMenu();
    -  menu.setVisible(true, true);
    -
    -  // Move to 500, 500
    -  menu.setPosition(500, 500);
    -
    -  // Now reposition and make sure position is more or less ok.
    -  menuButton.positionMenu();
    -  var menuNode = goog.dom.getElement('demoMenu');
    -  assertRoughlyEquals(menuNode.offsetTop, node.offsetTop + node.offsetHeight,
    -      20);
    -  assertRoughlyEquals(menuNode.offsetLeft, node.offsetLeft, 20);
    -}
    -
    -
    -/**
    - * Tests that calling positionMenu when the menu is not in the document does not
    - * throw an exception.
    - */
    -function testPositionMenuNotInDocument() {
    -  var menu = new goog.ui.Menu();
    -  menu.createDom();
    -  menuButton.setMenu(menu);
    -  menuButton.positionMenu();
    -}
    -
    -
    -/**
    - * Shows the menu and moves the menu button, a timer correct the menu position.
    - */
    -function testOpenedMenuPositionCorrection() {
    -  var iframe = goog.dom.getElement('iframe1');
    -  var iframeDoc = goog.dom.getFrameContentDocument(iframe);
    -  var iframeDom = goog.dom.getDomHelper(iframeDoc);
    -  var iframeWindow = goog.dom.getWindow(iframeDoc);
    -
    -  var button = new goog.ui.MenuButton();
    -  iframeWindow.scrollTo(0, 0);
    -  var node = iframeDom.getElement('demoMenuButton');
    -  button.decorate(node);
    -  var mockTimer = new goog.Timer();
    -  // Don't start the timer.  We manually dispatch the Tick event.
    -  mockTimer.start = goog.nullFunction;
    -  button.timer_ = mockTimer;
    -
    -  var replacer = new goog.testing.PropertyReplacer();
    -  var positionMenuCalled;
    -  var origPositionMenu = goog.bind(button.positionMenu, button);
    -  replacer.set(button, 'positionMenu', function() {
    -    positionMenuCalled = true;
    -    origPositionMenu();
    -  });
    -
    -  // Show the menu.
    -  button.setOpen(true);
    -
    -  // Confirm the menu position
    -  var menuNode = iframeDom.getElement('demoMenu');
    -  assertRoughlyEquals(menuNode.offsetTop, node.offsetTop + node.offsetHeight,
    -      20);
    -  assertRoughlyEquals(menuNode.offsetLeft, node.offsetLeft, 20);
    -
    -  positionMenuCalled = false;
    -  // A Tick event is dispatched.
    -  mockTimer.dispatchEvent(goog.Timer.TICK);
    -  assertFalse('positionMenu() shouldn\'t be called.', positionMenuCalled);
    -
    -  // Move the menu button by DOM structure change
    -  var p1 = iframeDom.createDom('p', null, iframeDom.createTextNode('foo'));
    -  var p2 = iframeDom.createDom('p', null, iframeDom.createTextNode('foo'));
    -  var p3 = iframeDom.createDom('p', null, iframeDom.createTextNode('foo'));
    -  iframeDom.insertSiblingBefore(p1, node);
    -  iframeDom.insertSiblingBefore(p2, node);
    -  iframeDom.insertSiblingBefore(p3, node);
    -
    -  // Confirm the menu is detached from the button.
    -  assertTrue(Math.abs(node.offsetTop + node.offsetHeight -
    -      menuNode.offsetTop) > 20);
    -
    -  positionMenuCalled = false;
    -  // A Tick event is dispatched.
    -  mockTimer.dispatchEvent(goog.Timer.TICK);
    -  assertTrue('positionMenu() should be called.', positionMenuCalled);
    -
    -  // The menu is moved to appropriate position again.
    -  assertRoughlyEquals(menuNode.offsetTop, node.offsetTop + node.offsetHeight,
    -      20);
    -
    -  // Make the frame page scrollable.
    -  var viewportHeight = iframeDom.getViewportSize().height;
    -  var footer = iframeDom.getElement('footer');
    -  goog.style.setSize(footer, 1, viewportHeight * 2);
    -  // Change the viewport offset.
    -  iframeWindow.scrollTo(0, viewportHeight);
    -  // A Tick event is dispatched and positionMenu() should be called.
    -  positionMenuCalled = false;
    -  mockTimer.dispatchEvent(goog.Timer.TICK);
    -  assertTrue('positionMenu() should be called.', positionMenuCalled);
    -  goog.style.setSize(footer, 1, 1);
    -
    -  // Tear down.
    -  iframeDom.removeNode(p1);
    -  iframeDom.removeNode(p2);
    -  iframeDom.removeNode(p3);
    -  replacer.reset();
    -  button.dispose();
    -}
    -
    -
    -/**
    - * Use a different button to position the menu and make sure it does so
    - * correctly.
    - */
    -function testAlternatePositioningElement() {
    -  var node = goog.dom.getElement('demoMenuButton');
    -  menuButton.decorate(node);
    -
    -  var posElement = goog.dom.getElement('positionElement');
    -  menuButton.setPositionElement(posElement);
    -
    -  // Show the menu.
    -  menuButton.setOpen(true);
    -
    -  // Confirm the menu position
    -  var menuNode = menuButton.getMenu().getElement();
    -  assertRoughlyEquals(menuNode.offsetTop, posElement.offsetTop +
    -      posElement.offsetHeight, 20);
    -  assertRoughlyEquals(menuNode.offsetLeft, posElement.offsetLeft, 20);
    -}
    -
    -
    -/**
    - * Test forced positioning above the button.
    - */
    -function testPositioningAboveAnchor() {
    -  var node = goog.dom.getElement('demoMenuButton');
    -  menuButton.decorate(node);
    -
    -  // Show the menu.
    -  menuButton.setAlignMenuToStart(true);  // Should get overridden below
    -  menuButton.setScrollOnOverflow(true);  // Should get overridden below
    -
    -  var position = new goog.positioning.MenuAnchoredPosition(
    -      menuButton.getElement(),
    -      goog.positioning.Corner.TOP_START,
    -      /* opt_adjust */ false, /* opt_resize */ false);
    -  menuButton.setMenuPosition(position);
    -  menuButton.setOpen(true);
    -
    -  // Confirm the menu position
    -  var buttonBounds = goog.style.getBounds(node);
    -  var menuNode = menuButton.getMenu().getElement();
    -  var menuBounds = goog.style.getBounds(menuNode);
    -
    -  assertRoughlyEquals(menuBounds.top + menuBounds.height,
    -      buttonBounds.top, 3);
    -  assertRoughlyEquals(menuBounds.left, buttonBounds.left, 3);
    -  // For this test to be valid, the node must have non-trival height.
    -  assertRoughlyEquals(node.offsetHeight, 19, 3);
    -}
    -
    -
    -/**
    - * Test forced positioning below the button.
    - */
    -function testPositioningBelowAnchor() {
    -  var node = goog.dom.getElement('demoMenuButton');
    -  menuButton.decorate(node);
    -
    -  // Show the menu.
    -  menuButton.setAlignMenuToStart(true);  // Should get overridden below
    -  menuButton.setScrollOnOverflow(true);  // Should get overridden below
    -
    -  var position = new goog.positioning.MenuAnchoredPosition(
    -      menuButton.getElement(),
    -      goog.positioning.Corner.BOTTOM_START,
    -      /* opt_adjust */ false, /* opt_resize */ false);
    -  menuButton.setMenuPosition(position);
    -  menuButton.setOpen(true);
    -
    -  // Confirm the menu position
    -  var buttonBounds = goog.style.getBounds(node);
    -  var menuNode = menuButton.getMenu().getElement();
    -  var menuBounds = goog.style.getBounds(menuNode);
    -
    -  expectedFailures.expectFailureFor(isWinSafariBefore5());
    -  try {
    -    assertRoughlyEquals(menuBounds.top,
    -        buttonBounds.top + buttonBounds.height, 3);
    -    assertRoughlyEquals(menuBounds.left, buttonBounds.left, 3);
    -  } catch (e) {
    -    expectedFailures.handleException(e);
    -  }
    -  // For this test to be valid, the node must have non-trival height.
    -  assertRoughlyEquals(node.offsetHeight, 19, 3);
    -}
    -
    -function isWinSafariBefore5() {
    -  return goog.userAgent.WINDOWS && goog.userAgent.product.SAFARI &&
    -      goog.userAgent.product.isVersion(4) &&
    -      !goog.userAgent.product.isVersion(5);
    -}
    -
    -
    -/**
    - * Tests that space, and only space, fire on key up.
    - */
    -function testSpaceFireOnKeyUp() {
    -  var node = goog.dom.getElement('demoMenuButton');
    -  menuButton.decorate(node);
    -
    -  e = new goog.events.Event(goog.events.KeyHandler.EventType.KEY, menuButton);
    -  e.preventDefault = goog.testing.recordFunction();
    -  e.keyCode = goog.events.KeyCodes.SPACE;
    -  menuButton.handleKeyEvent(e);
    -  assertFalse('Menu must not have been triggered by Space keypress',
    -      menuButton.isOpen());
    -  assertNotNull('Page scrolling is prevented', e.preventDefault.getLastCall());
    -
    -  e = new goog.events.Event(goog.events.EventType.KEYUP, menuButton);
    -  e.keyCode = goog.events.KeyCodes.SPACE;
    -  menuButton.handleKeyEvent(e);
    -  assertTrue('Menu must have been triggered by Space keyup',
    -      menuButton.isOpen());
    -  menuButton.getMenu().setHighlightedIndex(0);
    -  e = new goog.events.Event(goog.events.KeyHandler.EventType.KEY, menuButton);
    -  e.keyCode = goog.events.KeyCodes.DOWN;
    -  menuButton.handleKeyEvent(e);
    -  assertEquals('Highlighted menu item must have hanged by Down keypress',
    -      1,
    -      menuButton.getMenu().getHighlightedIndex());
    -
    -  menuButton.getMenu().setHighlightedIndex(0);
    -  e = new goog.events.Event(goog.events.EventType.KEYUP, menuButton);
    -  e.keyCode = goog.events.KeyCodes.DOWN;
    -  menuButton.handleKeyEvent(e);
    -  assertEquals('Highlighted menu item must not have changed by Down keyup',
    -      0,
    -      menuButton.getMenu().getHighlightedIndex());
    -}
    -
    -
    -/**
    - * Tests that preventing the button from closing also prevents the menu from
    - * being hidden.
    - */
    -function testPreventHide() {
    -  var node = goog.dom.getElement('demoMenuButton');
    -  menuButton.decorate(node);
    -  menuButton.setDispatchTransitionEvents(goog.ui.Component.State.OPENED, true);
    -
    -  // Show the menu.
    -  menuButton.setOpen(true);
    -  assertTrue('Menu button should be open.', menuButton.isOpen());
    -  assertTrue('Menu should be visible.', menuButton.getMenu().isVisible());
    -
    -  var key = goog.events.listen(menuButton,
    -                               goog.ui.Component.EventType.CLOSE,
    -                               function(event) { event.preventDefault(); });
    -
    -  // Try to hide the menu.
    -  menuButton.setOpen(false);
    -  assertTrue('Menu button should still be open.', menuButton.isOpen());
    -  assertTrue('Menu should still be visible.', menuButton.getMenu().isVisible());
    -
    -  // Remove listener and try again.
    -  goog.events.unlistenByKey(key);
    -  menuButton.setOpen(false);
    -  assertFalse('Menu button should not be open.', menuButton.isOpen());
    -  assertFalse('Menu should not be visible.', menuButton.getMenu().isVisible());
    -}
    -
    -
    -/**
    - * Tests that opening and closing the menu does not affect how adding or
    - * removing menu items changes the size of the menu.
    - */
    -function testResizeOnItemAddOrRemove() {
    -  var node = goog.dom.getElement('demoMenuButton');
    -  menuButton.decorate(node);
    -  var menu = menuButton.getMenu();
    -
    -  // Show the menu.
    -  menuButton.setOpen(true);
    -  var originalSize = goog.style.getSize(menu.getElement());
    -
    -  // Check that removing an item while the menu is left open correctly changes
    -  // the size of the menu.
    -  // Remove an item using a method on Menu.
    -  var item = menu.removeChildAt(0, true);
    -  // Confirm size of menu changed.
    -  var afterRemoveSize = goog.style.getSize(menu.getElement());
    -  assertTrue('Height of menu must decrease after removing a menu item.',
    -      afterRemoveSize.height < originalSize.height);
    -
    -  // Check that removing an item while the menu is closed, then opened
    -  // (so that reposition is called) correctly changes the size of the menu.
    -  // Hide menu.
    -  menuButton.setOpen(false);
    -  var item2 = menu.removeChildAt(0, true);
    -  menuButton.setOpen(true);
    -  // Confirm size of menu changed.
    -  var afterRemoveAgainSize = goog.style.getSize(menu.getElement());
    -  assertTrue('Height of menu must decrease after removing a second menu item.',
    -      afterRemoveAgainSize.height < afterRemoveSize.height);
    -
    -  // Check that adding an item while the menu is opened, then closed, then
    -  // opened, correctly changes the size of the menu.
    -  // Add an item, this time using a MenuButton method.
    -  menuButton.setOpen(true);
    -  menuButton.addItem(item2);
    -  menuButton.setOpen(false);
    -  menuButton.setOpen(true);
    -  // Confirm size of menu changed.
    -  var afterAddSize = goog.style.getSize(menu.getElement());
    -  assertTrue('Height of menu must increase after adding a menu item.',
    -      afterRemoveAgainSize.height < afterAddSize.height);
    -  assertEquals(
    -      'Removing and adding back items must not change the height of a menu.',
    -      afterRemoveSize.height, afterAddSize.height);
    -
    -  // Add back the last item to keep state consistent.
    -  menuButton.addItem(item);
    -}
    -
    -
    -/**
    - * Tests that adding and removing items from a menu with scrollOnOverflow is on
    - * correctly resizes the menu.
    - */
    -function testResizeOnItemAddOrRemoveWithScrollOnOverflow() {
    -  var node = goog.dom.getElement('demoMenuButton');
    -  menuButton.decorate(node);
    -  var menu = menuButton.getMenu();
    -
    -  // Show the menu.
    -  menuButton.setScrollOnOverflow(true);
    -  menuButton.setOpen(true);
    -  var originalSize = goog.style.getSize(menu.getElement());
    -
    -  // Check that removing an item while the menu is left open correctly changes
    -  // the size of the menu.
    -  // Remove an item using a method on Menu.
    -  var item = menu.removeChildAt(0, true);
    -  menuButton.invalidateMenuSize();
    -  menuButton.positionMenu();
    -
    -  // Confirm size of menu changed.
    -  var afterRemoveSize = goog.style.getSize(menu.getElement());
    -  assertTrue('Height of menu must decrease after removing a menu item.',
    -      afterRemoveSize.height < originalSize.height);
    -
    -  var item2 = menu.removeChildAt(0, true);
    -  menuButton.invalidateMenuSize();
    -  menuButton.positionMenu();
    -
    -  // Confirm size of menu changed.
    -  var afterRemoveAgainSize = goog.style.getSize(menu.getElement());
    -  assertTrue('Height of menu must decrease after removing a second menu item.',
    -      afterRemoveAgainSize.height < afterRemoveSize.height);
    -
    -  // Check that adding an item while the menu is opened correctly changes the
    -  // size of the menu.
    -  menuButton.addItem(item2);
    -  menuButton.invalidateMenuSize();
    -  menuButton.positionMenu();
    -
    -  // Confirm size of menu changed.
    -  var afterAddSize = goog.style.getSize(menu.getElement());
    -  assertTrue('Height of menu must increase after adding a menu item.',
    -      afterRemoveAgainSize.height < afterAddSize.height);
    -  assertEquals(
    -      'Removing and adding back items must not change the height of a menu.',
    -      afterRemoveSize.height, afterAddSize.height);
    -}
    -
    -
    -/**
    - * Try rendering the menu as a sibling rather than as a child of the dom. This
    - * tests the case when the button is rendered, rather than decorated.
    - */
    -function testRenderMenuAsSibling() {
    -  menuButton.setRenderMenuAsSibling(true);
    -  menuButton.addItem(new goog.ui.MenuItem('Menu item 1'));
    -  menuButton.addItem(new goog.ui.MenuItem('Menu item 2'));
    -  // By default the menu is rendered into the top level dom and the button
    -  // is rendered into whatever parent we provide.  If we don't provide a
    -  // parent then we aren't really testing anything, since both would be, by
    -  // default, rendered into the top level dom, and therefore siblings.
    -  menuButton.render(goog.dom.getElement('siblingTest'));
    -  menuButton.setOpen(true);
    -  assertEquals(
    -      menuButton.getElement().parentNode,
    -      menuButton.getMenu().getElement().parentNode);
    -}
    -
    -
    -/**
    - * Check that we render the menu as a sibling of the menu button, immediately
    - * after the menu button.
    - */
    -function testRenderMenuAsSiblingForDecoratedButton() {
    -  var menu = new goog.ui.Menu();
    -  menu.addChild(new goog.ui.MenuItem('Menu item 1'), true /* render */);
    -  menu.addChild(new goog.ui.MenuItem('Menu item 2'), true /* render */);
    -  menu.addChild(new goog.ui.MenuItem('Menu item 3'), true /* render */);
    -
    -  var menuButton = new goog.ui.MenuButton();
    -  menuButton.setMenu(menu);
    -  menuButton.setRenderMenuAsSibling(true);
    -  var node = goog.dom.getElement('button1');
    -  menuButton.decorate(node);
    -
    -  menuButton.setOpen(true);
    -
    -  assertEquals('The menu should be rendered immediately after the menu button',
    -      goog.dom.getNextElementSibling(menuButton.getElement()),
    -      menu.getElement());
    -
    -  assertEquals('The menu should be rendered immediately before the next button',
    -      goog.dom.getNextElementSibling(menu.getElement()),
    -      goog.dom.getElement('button2'));
    -}
    -
    -function testAlignToStartSetter() {
    -  assertTrue(menuButton.isAlignMenuToStart());
    -
    -  menuButton.setAlignMenuToStart(false);
    -  assertFalse(menuButton.isAlignMenuToStart());
    -
    -  menuButton.setAlignMenuToStart(true);
    -  assertTrue(menuButton.isAlignMenuToStart());
    -}
    -
    -function testScrollOnOverflowSetter() {
    -  assertFalse(menuButton.isScrollOnOverflow());
    -
    -  menuButton.setScrollOnOverflow(true);
    -  assertTrue(menuButton.isScrollOnOverflow());
    -
    -  menuButton.setScrollOnOverflow(false);
    -  assertFalse(menuButton.isScrollOnOverflow());
    -}
    -
    -
    -/**
    - * Tests that the attached menu has been set to aria-hidden=false explicitly
    - * when the menu is opened.
    - */
    -function testSetOpenUnsetsAriaHidden() {
    -  var node = goog.dom.getElement('demoMenuButton');
    -  menuButton.decorate(node);
    -  var menuElem = menuButton.getMenu().getElementStrict();
    -  goog.a11y.aria.setState(menuElem, goog.a11y.aria.State.HIDDEN, true);
    -  menuButton.setOpen(true);
    -  assertEquals(
    -      '', goog.a11y.aria.getState(menuElem, goog.a11y.aria.State.HIDDEN));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/menubutton_test_frame.html b/src/database/third_party/closure-library/closure/goog/ui/menubutton_test_frame.html
    deleted file mode 100644
    index b918890d3e7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/menubutton_test_frame.html
    +++ /dev/null
    @@ -1,41 +0,0 @@
    -<!DOCTYPE html>
    -<!--
    -
    -  @author tkent@google.com (TAMURA Kent)
    --->
    -<html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<style type='text/css'>
    -#demoMenuButton {
    -  /*
    -   * Set a fixed width because the button size can be changed by a scroll bar
    -   * without it.
    -   */
    -  width: 64px;
    -}
    -.goog-menu {
    -  position: absolute;
    -  color: #aaa;
    -}
    -</style>
    -</head>
    -<body>
    -<div id="demoMenuButton" class="goog-menu-button">
    -  Button
    -  <div id="demoMenu" class="goog-menu">
    -    <div id='menuItem1' class="goog-menuitem">Annual Report.pdf</div>
    -    <div id='menuItem2' class="goog-menuitem">Quarterly Update.pdf</div>
    -    <div id='menuItem3' class="goog-menuitem">Enemies List.txt</div>
    -  </div>
    -</div>
    -
    -<div id="footer"></div>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/menubuttonrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/menubuttonrenderer.js
    deleted file mode 100644
    index b9560974043..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/menubuttonrenderer.js
    +++ /dev/null
    @@ -1,191 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Renderer for {@link goog.ui.MenuButton}s and subclasses.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.MenuButtonRenderer');
    -
    -goog.require('goog.dom');
    -goog.require('goog.style');
    -goog.require('goog.ui.CustomButtonRenderer');
    -goog.require('goog.ui.INLINE_BLOCK_CLASSNAME');
    -goog.require('goog.ui.Menu');
    -goog.require('goog.ui.MenuRenderer');
    -
    -
    -
    -/**
    - * Renderer for {@link goog.ui.MenuButton}s.  This implementation overrides
    - * {@link goog.ui.CustomButtonRenderer#createButton} to create a separate
    - * caption and dropdown element.
    - * @constructor
    - * @extends {goog.ui.CustomButtonRenderer}
    - */
    -goog.ui.MenuButtonRenderer = function() {
    -  goog.ui.CustomButtonRenderer.call(this);
    -};
    -goog.inherits(goog.ui.MenuButtonRenderer, goog.ui.CustomButtonRenderer);
    -goog.addSingletonGetter(goog.ui.MenuButtonRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.MenuButtonRenderer.CSS_CLASS = goog.getCssName('goog-menu-button');
    -
    -
    -/**
    - * Takes the button's root element and returns the parent element of the
    - * button's contents.  Overrides the superclass implementation by taking
    - * the nested DIV structure of menu buttons into account.
    - * @param {Element} element Root element of the button whose content element
    - *     is to be returned.
    - * @return {Element} The button's content element.
    - * @override
    - */
    -goog.ui.MenuButtonRenderer.prototype.getContentElement = function(element) {
    -  return goog.ui.MenuButtonRenderer.superClass_.getContentElement.call(this,
    -      /** @type {Element} */ (element && element.firstChild));
    -};
    -
    -
    -/**
    - * Takes an element, decorates it with the menu button control, and returns
    - * the element.  Overrides {@link goog.ui.CustomButtonRenderer#decorate} by
    - * looking for a child element that can be decorated by a menu, and if it
    - * finds one, decorates it and attaches it to the menu button.
    - * @param {goog.ui.Control} control goog.ui.MenuButton to decorate the element.
    - * @param {Element} element Element to decorate.
    - * @return {Element} Decorated element.
    - * @override
    - */
    -goog.ui.MenuButtonRenderer.prototype.decorate = function(control, element) {
    -  var button = /** @type {goog.ui.MenuButton} */ (control);
    -  // TODO(attila):  Add more robust support for subclasses of goog.ui.Menu.
    -  var menuElem = goog.dom.getElementsByTagNameAndClass(
    -      '*', goog.ui.MenuRenderer.CSS_CLASS, element)[0];
    -  if (menuElem) {
    -    // Move the menu element directly under the body (but hide it first to
    -    // prevent flicker; see bug 1089244).
    -    goog.style.setElementShown(menuElem, false);
    -    goog.dom.appendChild(goog.dom.getOwnerDocument(menuElem).body, menuElem);
    -
    -    // Decorate the menu and attach it to the button.
    -    var menu = new goog.ui.Menu();
    -    menu.decorate(menuElem);
    -    button.setMenu(menu);
    -  }
    -
    -  // Let the superclass do the rest.
    -  return goog.ui.MenuButtonRenderer.superClass_.decorate.call(this, button,
    -      element);
    -};
    -
    -
    -/**
    - * Takes a text caption or existing DOM structure, and returns the content and
    - * a dropdown arrow element wrapped in a pseudo-rounded-corner box.  Creates
    - * the following DOM structure:
    - *    <div class="goog-inline-block goog-menu-button-outer-box">
    - *      <div class="goog-inline-block goog-menu-button-inner-box">
    - *        <div class="goog-inline-block goog-menu-button-caption">
    - *          Contents...
    - *        </div>
    - *        <div class="goog-inline-block goog-menu-button-dropdown">
    - *          &nbsp;
    - *        </div>
    - *      </div>
    - *    </div>
    - * @param {goog.ui.ControlContent} content Text caption or DOM structure
    - *     to wrap in a box.
    - * @param {goog.dom.DomHelper} dom DOM helper, used for document interaction.
    - * @return {Element} Pseudo-rounded-corner box containing the content.
    - * @override
    - */
    -goog.ui.MenuButtonRenderer.prototype.createButton = function(content, dom) {
    -  return goog.ui.MenuButtonRenderer.superClass_.createButton.call(this,
    -      [this.createCaption(content, dom), this.createDropdown(dom)], dom);
    -};
    -
    -
    -/**
    - * Takes a text caption or existing DOM structure, and returns it wrapped in
    - * an appropriately-styled DIV.  Creates the following DOM structure:
    - *    <div class="goog-inline-block goog-menu-button-caption">
    - *      Contents...
    - *    </div>
    - * @param {goog.ui.ControlContent} content Text caption or DOM structure
    - *     to wrap in a box.
    - * @param {goog.dom.DomHelper} dom DOM helper, used for document interaction.
    - * @return {Element} Caption element.
    - */
    -goog.ui.MenuButtonRenderer.prototype.createCaption = function(content, dom) {
    -  return goog.ui.MenuButtonRenderer.wrapCaption(
    -      content, this.getCssClass(), dom);
    -};
    -
    -
    -/**
    - * Takes a text caption or existing DOM structure, and returns it wrapped in
    - * an appropriately-styled DIV.  Creates the following DOM structure:
    - *    <div class="goog-inline-block goog-menu-button-caption">
    - *      Contents...
    - *    </div>
    - * @param {goog.ui.ControlContent} content Text caption or DOM structure
    - *     to wrap in a box.
    - * @param {string} cssClass The CSS class for the renderer.
    - * @param {goog.dom.DomHelper} dom DOM helper, used for document interaction.
    - * @return {!Element} Caption element.
    - */
    -goog.ui.MenuButtonRenderer.wrapCaption = function(content, cssClass, dom) {
    -  return dom.createDom(
    -      'div',
    -      goog.ui.INLINE_BLOCK_CLASSNAME + ' ' +
    -          goog.getCssName(cssClass, 'caption'),
    -      content);
    -};
    -
    -
    -/**
    - * Returns an appropriately-styled DIV containing a dropdown arrow element.
    - * Creates the following DOM structure:
    - *    <div class="goog-inline-block goog-menu-button-dropdown">
    - *      &nbsp;
    - *    </div>
    - * @param {goog.dom.DomHelper} dom DOM helper, used for document interaction.
    - * @return {Element} Dropdown element.
    - */
    -goog.ui.MenuButtonRenderer.prototype.createDropdown = function(dom) {
    -  // 00A0 is &nbsp;
    -  return dom.createDom('div',
    -      goog.ui.INLINE_BLOCK_CLASSNAME + ' ' +
    -      goog.getCssName(this.getCssClass(), 'dropdown'), '\u00A0');
    -};
    -
    -
    -/**
    - * Returns the CSS class to be applied to the root element of components
    - * rendered using this renderer.
    - * @return {string} Renderer-specific CSS class.
    - * @override
    - */
    -goog.ui.MenuButtonRenderer.prototype.getCssClass = function() {
    -  return goog.ui.MenuButtonRenderer.CSS_CLASS;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/menubuttonrenderer_test.html b/src/database/third_party/closure-library/closure/goog/ui/menubuttonrenderer_test.html
    deleted file mode 100644
    index 82de5295ea8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/menubuttonrenderer_test.html
    +++ /dev/null
    @@ -1,35 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -
    -  @author nicksantos@google.com (Nick Santos)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests for MenuButtonRenderer
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.MenuButtonRendererTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="root">
    -   <!-- A parent to attach rendered buttons to -->
    -   <div id="parent">
    -   </div>
    -   <!-- A button to decorate -->
    -   <div id="decoratedButton">
    -    Foo
    -   </div>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/menubuttonrenderer_test.js b/src/database/third_party/closure-library/closure/goog/ui/menubuttonrenderer_test.js
    deleted file mode 100644
    index 657026d5679..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/menubuttonrenderer_test.js
    +++ /dev/null
    @@ -1,168 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.MenuButtonRendererTest');
    -goog.setTestOnly('goog.ui.MenuButtonRendererTest');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.ui.rendererasserts');
    -goog.require('goog.ui.MenuButton');
    -goog.require('goog.ui.MenuButtonRenderer');
    -goog.require('goog.userAgent');
    -
    -var decoratedButton;
    -var renderedButton;
    -var savedRootTree;
    -
    -function setUp() {
    -  savedRootTree = goog.dom.getElement('root').cloneNode(true);
    -  decoratedButton = null;
    -  renderedButton = null;
    -}
    -
    -function tearDown() {
    -  if (decoratedButton) {
    -    decoratedButton.dispose();
    -  }
    -
    -  if (renderedButton) {
    -    renderedButton.dispose();
    -  }
    -
    -  var root = goog.dom.getElement('root');
    -  root.parentNode.replaceChild(savedRootTree, root);
    -}
    -
    -function testRendererWithTextContent() {
    -  renderedButton = new goog.ui.MenuButton('Foo');
    -  renderOnParent(renderedButton);
    -  checkButtonCaption(renderedButton);
    -  checkAriaState(renderedButton);
    -
    -  decoratedButton = new goog.ui.MenuButton();
    -  decorateDemoButton(decoratedButton);
    -  checkButtonCaption(decoratedButton);
    -  checkAriaState(decoratedButton);
    -
    -  assertButtonsEqual();
    -}
    -
    -function testRendererWithNodeContent() {
    -  renderedButton = new goog.ui.MenuButton(
    -      goog.dom.createDom('div', null, 'Foo'));
    -  renderOnParent(renderedButton);
    -
    -  var contentEl = renderedButton.getContentElement();
    -  if (goog.userAgent.IE || goog.userAgent.OPERA) {
    -    assertHTMLEquals('<div unselectable="on">Foo</div>', contentEl.innerHTML);
    -  } else {
    -    assertHTMLEquals('<div>Foo</div>', contentEl.innerHTML);
    -  }
    -  assertTrue(hasInlineBlock(contentEl));
    -}
    -
    -function testSetContent() {
    -  renderedButton = new goog.ui.MenuButton();
    -  renderOnParent(renderedButton);
    -
    -  var contentEl = renderedButton.getContentElement();
    -  assertHTMLEquals('', contentEl.innerHTML);
    -
    -  renderedButton.setContent('Foo');
    -  contentEl = renderedButton.getContentElement();
    -  assertHTMLEquals('Foo', contentEl.innerHTML);
    -  assertTrue(hasInlineBlock(contentEl));
    -
    -  renderedButton.setContent(goog.dom.createDom('div', null, 'Bar'));
    -  contentEl = renderedButton.getContentElement();
    -  assertHTMLEquals('<div>Bar</div>', contentEl.innerHTML);
    -
    -  renderedButton.setContent('Foo');
    -  contentEl = renderedButton.getContentElement();
    -  assertHTMLEquals('Foo', contentEl.innerHTML);
    -}
    -
    -function assertButtonsEqual() {
    -  assertHTMLEquals(
    -      'Rendered button and decorated button produced different HTML!',
    -      renderedButton.getElement().innerHTML,
    -      decoratedButton.getElement().innerHTML);
    -}
    -
    -
    -/**
    - * Render the given button as a child of 'parent'.
    - * @param {goog.ui.Button} button A button with content 'Foo'.
    - */
    -function renderOnParent(button) {
    -  button.render(goog.dom.getElement('parent'));
    -}
    -
    -
    -/**
    - * Decaorate the button with id 'button'.
    - * @param {goog.ui.Button} button A button with no content.
    - */
    -function decorateDemoButton(button) {
    -  button.decorate(goog.dom.getElement('decoratedButton'));
    -}
    -
    -
    -/**
    - * Verify that the button's caption is never the direct
    - * child of an inline-block element.
    - * @param {goog.ui.Button} button A button.
    - */
    -function checkButtonCaption(button) {
    -  var contentElement = button.getContentElement();
    -  assertEquals('Foo', contentElement.innerHTML);
    -  assertTrue(hasInlineBlock(contentElement));
    -  assert(hasInlineBlock(contentElement.parentNode));
    -
    -  button.setContent('Bar');
    -  contentElement = button.getContentElement();
    -  assertEquals('Bar', contentElement.innerHTML);
    -  assertTrue(hasInlineBlock(contentElement));
    -  assert(hasInlineBlock(contentElement.parentNode));
    -}
    -
    -
    -/**
    - * Verify that the menu button has the correct ARIA attributes
    - * @param {goog.ui.Button} button A button.
    - */
    -function checkAriaState(button) {
    -  assertEquals(
    -      'menu buttons should have default aria-expanded == false', 'false',
    -      goog.a11y.aria.getState(
    -          button.getElement(), goog.a11y.aria.State.EXPANDED));
    -  button.setOpen(true);
    -  assertEquals('menu buttons should not aria-expanded == true after ' +
    -      'opening', 'true',
    -      goog.a11y.aria.getState(
    -          button.getElement(), goog.a11y.aria.State.EXPANDED));
    -}
    -
    -function hasInlineBlock(el) {
    -  return goog.dom.classlist.contains(el, 'goog-inline-block');
    -}
    -
    -function testDoesntCallGetCssClassInConstructor() {
    -  goog.testing.ui.rendererasserts.
    -      assertNoGetCssClassCallsInConstructor(goog.ui.MenuButtonRenderer);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/menuheader.js b/src/database/third_party/closure-library/closure/goog/ui/menuheader.js
    deleted file mode 100644
    index 1e04f32e78b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/menuheader.js
    +++ /dev/null
    @@ -1,62 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A class for representing menu headers.
    - * @see goog.ui.Menu
    - *
    - */
    -
    -goog.provide('goog.ui.MenuHeader');
    -
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.Control');
    -goog.require('goog.ui.MenuHeaderRenderer');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * Class representing a menu header.
    - * @param {goog.ui.ControlContent} content Text caption or DOM structure to
    - *     display as the content of the item (use to add icons or styling to
    - *     menus).
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper used for
    - *     document interactions.
    - * @param {goog.ui.MenuHeaderRenderer=} opt_renderer Optional renderer.
    - * @constructor
    - * @extends {goog.ui.Control}
    - */
    -goog.ui.MenuHeader = function(content, opt_domHelper, opt_renderer) {
    -  goog.ui.Control.call(this, content, opt_renderer ||
    -      goog.ui.MenuHeaderRenderer.getInstance(), opt_domHelper);
    -
    -  this.setSupportedState(goog.ui.Component.State.DISABLED, false);
    -  this.setSupportedState(goog.ui.Component.State.HOVER, false);
    -  this.setSupportedState(goog.ui.Component.State.ACTIVE, false);
    -  this.setSupportedState(goog.ui.Component.State.FOCUSED, false);
    -
    -  // Headers are always considered disabled.
    -  this.setStateInternal(goog.ui.Component.State.DISABLED);
    -};
    -goog.inherits(goog.ui.MenuHeader, goog.ui.Control);
    -
    -
    -// Register a decorator factory function for goog.ui.MenuHeaders.
    -goog.ui.registry.setDecoratorByClassName(
    -    goog.ui.MenuHeaderRenderer.CSS_CLASS,
    -    function() {
    -      // MenuHeader defaults to using MenuHeaderRenderer.
    -      return new goog.ui.MenuHeader(null);
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/menuheaderrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/menuheaderrenderer.js
    deleted file mode 100644
    index fd2360d5c5c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/menuheaderrenderer.js
    +++ /dev/null
    @@ -1,54 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Renderer for {@link goog.ui.MenuHeader}s.
    - *
    - */
    -
    -goog.provide('goog.ui.MenuHeaderRenderer');
    -
    -goog.require('goog.ui.ControlRenderer');
    -
    -
    -
    -/**
    - * Renderer for menu headers.
    - * @constructor
    - * @extends {goog.ui.ControlRenderer}
    - */
    -goog.ui.MenuHeaderRenderer = function() {
    -  goog.ui.ControlRenderer.call(this);
    -};
    -goog.inherits(goog.ui.MenuHeaderRenderer, goog.ui.ControlRenderer);
    -goog.addSingletonGetter(goog.ui.MenuHeaderRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.MenuHeaderRenderer.CSS_CLASS = goog.getCssName('goog-menuheader');
    -
    -
    -/**
    - * Returns the CSS class to be applied to the root element of components
    - * rendered using this renderer.
    - * @return {string} Renderer-specific CSS class.
    - * @override
    - */
    -goog.ui.MenuHeaderRenderer.prototype.getCssClass = function() {
    -  return goog.ui.MenuHeaderRenderer.CSS_CLASS;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/menuitem.js b/src/database/third_party/closure-library/closure/goog/ui/menuitem.js
    deleted file mode 100644
    index 9db7b884507..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/menuitem.js
    +++ /dev/null
    @@ -1,322 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A class for representing items in menus.
    - * @see goog.ui.Menu
    - *
    - * @author attila@google.com (Attila Bodis)
    - * @see ../demos/menuitem.html
    - */
    -
    -goog.provide('goog.ui.MenuItem');
    -
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.string');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.Control');
    -goog.require('goog.ui.MenuItemRenderer');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * Class representing an item in a menu.
    - *
    - * @param {goog.ui.ControlContent} content Text caption or DOM structure to
    - *     display as the content of the item (use to add icons or styling to
    - *     menus).
    - * @param {*=} opt_model Data/model associated with the menu item.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper used for
    - *     document interactions.
    - * @param {goog.ui.MenuItemRenderer=} opt_renderer Optional renderer.
    - * @constructor
    - * @extends {goog.ui.Control}
    - */
    -goog.ui.MenuItem = function(content, opt_model, opt_domHelper, opt_renderer) {
    -  goog.ui.Control.call(this, content, opt_renderer ||
    -      goog.ui.MenuItemRenderer.getInstance(), opt_domHelper);
    -  this.setValue(opt_model);
    -};
    -goog.inherits(goog.ui.MenuItem, goog.ui.Control);
    -goog.tagUnsealableClass(goog.ui.MenuItem);
    -
    -
    -/**
    - * The access key for this menu item. This key allows the user to quickly
    - * trigger this item's action with they keyboard. For example, setting the
    - * mnenomic key to 70 (F), when the user opens the menu and hits "F," the
    - * menu item is triggered.
    - *
    - * @type {goog.events.KeyCodes}
    - * @private
    - */
    -goog.ui.MenuItem.prototype.mnemonicKey_;
    -
    -
    -/**
    - * The class set on an element that contains a parenthetical mnemonic key hint.
    - * Parenthetical hints are added to items in which the mnemonic key is not found
    - * within the menu item's caption itself. For example, if you have a menu item
    - * with the caption "Record," but its mnemonic key is "I", the caption displayed
    - * in the menu will appear as "Record (I)".
    - *
    - * @type {string}
    - * @private
    - */
    -goog.ui.MenuItem.MNEMONIC_WRAPPER_CLASS_ =
    -    goog.getCssName('goog-menuitem-mnemonic-separator');
    -
    -
    -/**
    - * The class set on an element that contains a keyboard accelerator hint.
    - * @type {string}
    - */
    -goog.ui.MenuItem.ACCELERATOR_CLASS = goog.getCssName('goog-menuitem-accel');
    -
    -
    -// goog.ui.Component and goog.ui.Control implementation.
    -
    -
    -/**
    - * Returns the value associated with the menu item.  The default implementation
    - * returns the model object associated with the item (if any), or its caption.
    - * @return {*} Value associated with the menu item, if any, or its caption.
    - */
    -goog.ui.MenuItem.prototype.getValue = function() {
    -  var model = this.getModel();
    -  return model != null ? model : this.getCaption();
    -};
    -
    -
    -/**
    - * Sets the value associated with the menu item.  The default implementation
    - * stores the value as the model of the menu item.
    - * @param {*} value Value to be associated with the menu item.
    - */
    -goog.ui.MenuItem.prototype.setValue = function(value) {
    -  this.setModel(value);
    -};
    -
    -
    -/** @override */
    -goog.ui.MenuItem.prototype.setSupportedState = function(state, support) {
    -  goog.ui.MenuItem.base(this, 'setSupportedState', state, support);
    -  switch (state) {
    -    case goog.ui.Component.State.SELECTED:
    -      this.setSelectableInternal_(support);
    -      break;
    -    case goog.ui.Component.State.CHECKED:
    -      this.setCheckableInternal_(support);
    -      break;
    -  }
    -};
    -
    -
    -/**
    - * Sets the menu item to be selectable or not.  Set to true for menu items
    - * that represent selectable options.
    - * @param {boolean} selectable Whether the menu item is selectable.
    - */
    -goog.ui.MenuItem.prototype.setSelectable = function(selectable) {
    -  this.setSupportedState(goog.ui.Component.State.SELECTED, selectable);
    -};
    -
    -
    -/**
    - * Sets the menu item to be selectable or not.
    - * @param {boolean} selectable  Whether the menu item is selectable.
    - * @private
    - */
    -goog.ui.MenuItem.prototype.setSelectableInternal_ = function(selectable) {
    -  if (this.isChecked() && !selectable) {
    -    this.setChecked(false);
    -  }
    -
    -  var element = this.getElement();
    -  if (element) {
    -    this.getRenderer().setSelectable(this, element, selectable);
    -  }
    -};
    -
    -
    -/**
    - * Sets the menu item to be checkable or not.  Set to true for menu items
    - * that represent checkable options.
    - * @param {boolean} checkable Whether the menu item is checkable.
    - */
    -goog.ui.MenuItem.prototype.setCheckable = function(checkable) {
    -  this.setSupportedState(goog.ui.Component.State.CHECKED, checkable);
    -};
    -
    -
    -/**
    - * Sets the menu item to be checkable or not.
    - * @param {boolean} checkable Whether the menu item is checkable.
    - * @private
    - */
    -goog.ui.MenuItem.prototype.setCheckableInternal_ = function(checkable) {
    -  var element = this.getElement();
    -  if (element) {
    -    this.getRenderer().setCheckable(this, element, checkable);
    -  }
    -};
    -
    -
    -/**
    - * Returns the text caption of the component while ignoring accelerators.
    - * @override
    - */
    -goog.ui.MenuItem.prototype.getCaption = function() {
    -  var content = this.getContent();
    -  if (goog.isArray(content)) {
    -    var acceleratorClass = goog.ui.MenuItem.ACCELERATOR_CLASS;
    -    var mnemonicWrapClass = goog.ui.MenuItem.MNEMONIC_WRAPPER_CLASS_;
    -    var caption = goog.array.map(content, function(node) {
    -      if (goog.dom.isElement(node) &&
    -          (goog.dom.classlist.contains(/** @type {!Element} */ (node),
    -              acceleratorClass) ||
    -          goog.dom.classlist.contains(/** @type {!Element} */ (node),
    -              mnemonicWrapClass))) {
    -        return '';
    -      } else {
    -        return goog.dom.getRawTextContent(node);
    -      }
    -    }).join('');
    -    return goog.string.collapseBreakingSpaces(caption);
    -  }
    -  return goog.ui.MenuItem.superClass_.getCaption.call(this);
    -};
    -
    -
    -/**
    - * @return {?string} The keyboard accelerator text, or null if the menu item
    - *     doesn't have one.
    - */
    -goog.ui.MenuItem.prototype.getAccelerator = function() {
    -  var dom = this.getDomHelper();
    -  var content = this.getContent();
    -  if (goog.isArray(content)) {
    -    var acceleratorEl = goog.array.find(content, function(e) {
    -      return goog.dom.classlist.contains(/** @type {!Element} */ (e),
    -          goog.ui.MenuItem.ACCELERATOR_CLASS);
    -    });
    -    if (acceleratorEl) {
    -      return dom.getTextContent(acceleratorEl);
    -    }
    -  }
    -  return null;
    -};
    -
    -
    -/** @override */
    -goog.ui.MenuItem.prototype.handleMouseUp = function(e) {
    -  var parentMenu = /** @type {goog.ui.Menu} */ (this.getParent());
    -
    -  if (parentMenu) {
    -    var oldCoords = parentMenu.openingCoords;
    -    // Clear out the saved opening coords immediately so they're not used twice.
    -    parentMenu.openingCoords = null;
    -
    -    if (oldCoords && goog.isNumber(e.clientX)) {
    -      var newCoords = new goog.math.Coordinate(e.clientX, e.clientY);
    -      if (goog.math.Coordinate.equals(oldCoords, newCoords)) {
    -        // This menu was opened by a mousedown and we're handling the consequent
    -        // mouseup. The coords haven't changed, meaning this was a simple click,
    -        // not a click and drag. Don't do the usual behavior because the menu
    -        // just popped up under the mouse and the user didn't mean to activate
    -        // this item.
    -        return;
    -      }
    -    }
    -  }
    -
    -  goog.ui.MenuItem.base(this, 'handleMouseUp', e);
    -};
    -
    -
    -/** @override */
    -goog.ui.MenuItem.prototype.handleKeyEventInternal = function(e) {
    -  if (e.keyCode == this.getMnemonic() && this.performActionInternal(e)) {
    -    return true;
    -  } else {
    -    return goog.ui.MenuItem.base(this, 'handleKeyEventInternal', e);
    -  }
    -};
    -
    -
    -/**
    - * Sets the mnemonic key code. The mnemonic is the key associated with this
    - * action.
    - * @param {goog.events.KeyCodes} key The key code.
    - */
    -goog.ui.MenuItem.prototype.setMnemonic = function(key) {
    -  this.mnemonicKey_ = key;
    -};
    -
    -
    -/**
    - * Gets the mnemonic key code. The mnemonic is the key associated with this
    - * action.
    - * @return {goog.events.KeyCodes} The key code of the mnemonic key.
    - */
    -goog.ui.MenuItem.prototype.getMnemonic = function() {
    -  return this.mnemonicKey_;
    -};
    -
    -
    -// Register a decorator factory function for goog.ui.MenuItems.
    -goog.ui.registry.setDecoratorByClassName(goog.ui.MenuItemRenderer.CSS_CLASS,
    -    function() {
    -      // MenuItem defaults to using MenuItemRenderer.
    -      return new goog.ui.MenuItem(null);
    -    });
    -
    -
    -/**
    - * @override
    - */
    -goog.ui.MenuItem.prototype.getPreferredAriaRole = function() {
    -  if (this.isSupportedState(goog.ui.Component.State.CHECKED)) {
    -    return goog.a11y.aria.Role.MENU_ITEM_CHECKBOX;
    -  }
    -  if (this.isSupportedState(goog.ui.Component.State.SELECTED)) {
    -    return goog.a11y.aria.Role.MENU_ITEM_RADIO;
    -  }
    -  return goog.ui.MenuItem.base(this, 'getPreferredAriaRole');
    -};
    -
    -
    -/**
    - * @override
    - * @return {goog.ui.Menu}
    - */
    -goog.ui.MenuItem.prototype.getParent = function() {
    -  return /** @type {goog.ui.Menu} */ (
    -      goog.ui.Control.prototype.getParent.call(this));
    -};
    -
    -
    -/**
    - * @override
    - * @return {goog.ui.Menu}
    - */
    -goog.ui.MenuItem.prototype.getParentEventTarget = function() {
    -  return /** @type {goog.ui.Menu} */ (
    -      goog.ui.Control.prototype.getParentEventTarget.call(this));
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/menuitem_test.html b/src/database/third_party/closure-library/closure/goog/ui/menuitem_test.html
    deleted file mode 100644
    index c56b9bae2d8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/menuitem_test.html
    +++ /dev/null
    @@ -1,29 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -Author: attila@google.com (Attila Bodis)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.MenuItem
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.MenuItemTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="sandbox">
    -  </div>
    -  <div id="parentComponent">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/menuitem_test.js b/src/database/third_party/closure-library/closure/goog/ui/menuitem_test.js
    deleted file mode 100644
    index 4ceda5dfe26..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/menuitem_test.js
    +++ /dev/null
    @@ -1,583 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.MenuItemTest');
    -goog.setTestOnly('goog.ui.MenuItemTest');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.dom.NodeType');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.MenuItem');
    -goog.require('goog.ui.MenuItemRenderer');
    -
    -var sandbox;
    -var item;
    -
    -function setUp() {
    -  sandbox = goog.dom.getElement('sandbox');
    -  item = new goog.ui.MenuItem('Item');
    -}
    -
    -function tearDown() {
    -  item.dispose();
    -  goog.dom.removeChildren(sandbox);
    -}
    -
    -function testMenuItem() {
    -  assertNotNull('Instance must not be null', item);
    -  assertEquals('Renderer must default to MenuItemRenderer singleton',
    -      goog.ui.MenuItemRenderer.getInstance(), item.getRenderer());
    -  assertEquals('Content must have expected value', 'Item',
    -      item.getContent());
    -  assertEquals('Caption must default to the content', item.getContent(),
    -      item.getCaption());
    -  assertEquals('Value must default to the caption', item.getCaption(),
    -      item.getValue());
    -}
    -
    -function testMenuItemConstructor() {
    -  var model = 'Hello';
    -  var fakeDom = {};
    -  var fakeRenderer = {};
    -
    -  var menuItem = new goog.ui.MenuItem('Item', model, fakeDom, fakeRenderer);
    -  assertEquals('Content must have expected value', 'Item',
    -      menuItem.getContent());
    -  assertEquals('Caption must default to the content', menuItem.getContent(),
    -      menuItem.getCaption());
    -  assertEquals('Model must be set', model, menuItem.getModel());
    -  assertNotEquals('Value must not equal the caption', menuItem.getCaption(),
    -      menuItem.getValue());
    -  assertEquals('Value must equal the model', model, menuItem.getValue());
    -  assertEquals('DomHelper must be set', fakeDom, menuItem.getDomHelper());
    -  assertEquals('Renderer must be set', fakeRenderer,
    -      menuItem.getRenderer());
    -}
    -
    -function testGetValue() {
    -  assertUndefined('Model must be undefined by default', item.getModel());
    -  assertEquals('Without a model, value must default to the caption',
    -      item.getCaption(), item.getValue());
    -  item.setModel('Foo');
    -  assertEquals('With a model, value must default to the model',
    -      item.getModel(), item.getValue());
    -}
    -
    -function testSetValue() {
    -  assertUndefined('Model must be undefined by default', item.getModel());
    -  assertEquals('Without a model, value must default to the caption',
    -      item.getCaption(), item.getValue());
    -  item.setValue(17);
    -  assertEquals('Value must be set', 17, item.getValue());
    -  assertEquals('Value and model must be the same', item.getValue(),
    -      item.getModel());
    -}
    -
    -function testGetSetContent() {
    -  assertEquals('Content must have expected value', 'Item',
    -      item.getContent());
    -  item.setContent(goog.dom.createDom('div', 'foo', 'Foo'));
    -  assertEquals('Content must be an element', goog.dom.NodeType.ELEMENT,
    -      item.getContent().nodeType);
    -  assertHTMLEquals('Content must be the expected element',
    -      '<div class="foo">Foo</div>',
    -      goog.dom.getOuterHtml(item.getContent()));
    -}
    -
    -function testGetSetCaption() {
    -  assertEquals('Caption must have expected value', 'Item',
    -      item.getCaption());
    -  item.setCaption('Hello, world!');
    -  assertTrue('Caption must be a string', goog.isString(item.getCaption()));
    -  assertEquals('Caption must have expected value', 'Hello, world!',
    -      item.getCaption());
    -  item.setContent(goog.dom.createDom('div', 'foo', 'Foo'));
    -  assertTrue('Caption must be a string', goog.isString(item.getCaption()));
    -  assertEquals('Caption must have expected value', 'Foo',
    -      item.getCaption());
    -}
    -
    -function testGetSetContentAfterCreateDom() {
    -  item.createDom();
    -  assertEquals('Content must have expected value', 'Item',
    -      item.getContent());
    -  item.setContent(goog.dom.createDom('div', 'foo', 'Foo'));
    -  assertEquals('Content must be an element', goog.dom.NodeType.ELEMENT,
    -      item.getContent().nodeType);
    -  assertHTMLEquals('Content must be the expected element',
    -      '<div class="foo">Foo</div>',
    -      goog.dom.getOuterHtml(item.getContent()));
    -}
    -
    -function testGetSetCaptionAfterCreateDom() {
    -  item.createDom();
    -  assertEquals('Caption must have expected value', 'Item',
    -      item.getCaption());
    -  item.setCaption('Hello, world!');
    -  assertTrue('Caption must be a string', goog.isString(item.getCaption()));
    -  assertEquals('Caption must have expected value', 'Hello, world!',
    -      item.getCaption());
    -  item.setContent(goog.dom.createDom('div', 'foo', 'Foo'));
    -  assertTrue('Caption must be a string', goog.isString(item.getCaption()));
    -  assertEquals('Caption must have expected value', 'Foo',
    -      item.getCaption());
    -
    -  var arrayContent = goog.array.clone(goog.dom.htmlToDocumentFragment(
    -      ' <b> \xa0foo</b><i>  bar</i> ').childNodes);
    -  item.setContent(arrayContent);
    -  assertEquals('whitespaces must be normalized in the caption',
    -      '\xa0foo bar', item.getCaption());
    -}
    -
    -function testSetSelectable() {
    -  assertFalse('Item must not be selectable by default',
    -      item.isSupportedState(goog.ui.Component.State.SELECTED));
    -  item.setSelectable(true);
    -  assertTrue('Item must be selectable',
    -      item.isSupportedState(goog.ui.Component.State.SELECTED));
    -  item.setSelected(true);
    -  assertTrue('Item must be selected', item.isSelected());
    -  assertFalse('Item must not be checked', item.isChecked());
    -  item.setSelectable(false);
    -  assertFalse('Item must not no longer be selectable',
    -      item.isSupportedState(goog.ui.Component.State.SELECTED));
    -  assertFalse('Item must no longer be selected', item.isSelected());
    -  assertFalse('Item must not be checked', item.isChecked());
    -}
    -
    -function testSetCheckable() {
    -  assertFalse('Item must not be checkable by default',
    -      item.isSupportedState(goog.ui.Component.State.CHECKED));
    -  item.setCheckable(true);
    -  assertTrue('Item must be checkable',
    -      item.isSupportedState(goog.ui.Component.State.CHECKED));
    -  item.setChecked(true);
    -  assertTrue('Item must be checked', item.isChecked());
    -  assertFalse('Item must not be selected', item.isSelected());
    -  item.setCheckable(false);
    -  assertFalse('Item must not no longer be checkable',
    -      item.isSupportedState(goog.ui.Component.State.CHECKED));
    -  assertFalse('Item must no longer be checked', item.isChecked());
    -  assertFalse('Item must not be selected', item.isSelected());
    -}
    -
    -function testSetSelectableBeforeCreateDom() {
    -  item.setSelectable(true);
    -  item.createDom();
    -  assertTrue('Item must have checkbox structure',
    -      item.getRenderer().hasCheckBoxStructure(item.getElement()));
    -  item.setSelectable(false);
    -  assertFalse('Item must no longer have checkbox structure',
    -      item.getRenderer().hasCheckBoxStructure(item.getElement()));
    -}
    -
    -function testSetCheckableBeforeCreateDom() {
    -  item.setCheckable(true);
    -  item.createDom();
    -  assertTrue('Item must have checkbox structure',
    -      item.getRenderer().hasCheckBoxStructure(item.getElement()));
    -  assertEquals('Element must have ARIA role menuitemcheckbox',
    -      goog.a11y.aria.Role.MENU_ITEM_CHECKBOX,
    -      goog.a11y.aria.getRole(item.getElement()));
    -  item.setCheckable(false);
    -  assertFalse('Item must no longer have checkbox structure',
    -      item.getRenderer().hasCheckBoxStructure(item.getElement()));
    -}
    -
    -function testSetSelectableAfterCreateDom() {
    -  item.createDom();
    -  item.setSelectable(true);
    -  assertTrue('Item must have checkbox structure',
    -      item.getRenderer().hasCheckBoxStructure(item.getElement()));
    -  assertEquals('Element must have ARIA role menuitemradio',
    -      goog.a11y.aria.Role.MENU_ITEM_RADIO,
    -      goog.a11y.aria.getRole(item.getElement()));
    -  item.setSelectable(false);
    -  assertFalse('Item must no longer have checkbox structure',
    -      item.getRenderer().hasCheckBoxStructure(item.getElement()));
    -}
    -
    -function testSetCheckableAfterCreateDom() {
    -  item.createDom();
    -  item.setCheckable(true);
    -  assertTrue('Item must have checkbox structure',
    -      item.getRenderer().hasCheckBoxStructure(item.getElement()));
    -  item.setCheckable(false);
    -  assertFalse('Item must no longer have checkbox structure',
    -      item.getRenderer().hasCheckBoxStructure(item.getElement()));
    -}
    -
    -function testSelectableBehavior() {
    -  item.setSelectable(true);
    -  item.render(sandbox);
    -  assertFalse('Item must not be selected by default', item.isSelected());
    -  item.performActionInternal();
    -  assertTrue('Item must be selected', item.isSelected());
    -  item.performActionInternal();
    -  assertTrue('Item must still be selected', item.isSelected());
    -}
    -
    -function testCheckableBehavior() {
    -  item.setCheckable(true);
    -  item.render(sandbox);
    -  assertFalse('Item must not be checked by default', item.isChecked());
    -  item.performActionInternal();
    -  assertTrue('Item must be checked', item.isChecked());
    -  item.performActionInternal();
    -  assertFalse('Item must no longer be checked', item.isChecked());
    -}
    -
    -function testGetSetContentForItemWithCheckBox() {
    -  item.setSelectable(true);
    -  item.createDom();
    -
    -  assertTrue('Item must have checkbox structure',
    -      item.getRenderer().hasCheckBoxStructure(item.getElement()));
    -  assertEquals('getContent() must not return the checkbox structure',
    -      'Item', item.getContent());
    -
    -  item.setContent('Hello');
    -  assertEquals('getContent() must not return the checkbox structure',
    -      'Hello', item.getContent());
    -  assertTrue('Item must still have checkbox structure',
    -      item.getRenderer().hasCheckBoxStructure(item.getElement()));
    -
    -  item.setContent(goog.dom.createDom('span', 'foo', 'Foo'));
    -  assertEquals('getContent() must return element',
    -      goog.dom.NodeType.ELEMENT, item.getContent().nodeType);
    -  assertTrue('Item must still have checkbox structure',
    -      item.getRenderer().hasCheckBoxStructure(item.getElement()));
    -
    -  item.setContent(null);
    -  assertNull('getContent() must return null', item.getContent());
    -  assertTrue('Item must still have checkbox structure',
    -      item.getRenderer().hasCheckBoxStructure(item.getElement()));
    -}
    -
    -function testGetSetCaptionForItemWithCheckBox() {
    -  item.setCheckable(true);
    -  item.createDom();
    -
    -  assertTrue('Item must have checkbox structure',
    -      item.getRenderer().hasCheckBoxStructure(item.getElement()));
    -  assertEquals('getCaption() must not return the checkbox structure',
    -      'Item', item.getCaption());
    -
    -  item.setCaption('Hello');
    -  assertEquals('getCaption() must not return the checkbox structure',
    -      'Hello', item.getCaption());
    -  assertTrue('Item must still have checkbox structure',
    -      item.getRenderer().hasCheckBoxStructure(item.getElement()));
    -
    -  item.setContent(goog.dom.createDom('span', 'foo', 'Foo'));
    -  assertEquals('getCaption() must return text content', 'Foo',
    -      item.getCaption());
    -  assertTrue('Item must still have checkbox structure',
    -      item.getRenderer().hasCheckBoxStructure(item.getElement()));
    -
    -  item.setCaption('');
    -  assertEquals('getCaption() must return empty string', '',
    -      item.getCaption());
    -  assertTrue('Item must still have checkbox structure',
    -      item.getRenderer().hasCheckBoxStructure(item.getElement()));
    -}
    -
    -function testGetSetCaptionForItemWithAccelerators() {
    -  var contentArr = [];
    -  contentArr.push(goog.dom.createDom('span',
    -      goog.getCssName('goog-menuitem-accel'), 'Ctrl+1'));
    -  contentArr.push(goog.dom.createTextNode('Hello'));
    -  item.setCaption(contentArr);
    -  assertEquals('getCaption() must not return the accelerator', 'Hello',
    -      item.getCaption());
    -
    -  item.setCaption([
    -    goog.dom.createDom('span', goog.getCssName('goog-menuitem-accel'), 'Ctrl+1')
    -  ]);
    -  assertEquals('getCaption() must return empty string', '',
    -      item.getCaption());
    -
    -  assertEquals('getAccelerator() should return the accelerator', 'Ctrl+1',
    -      item.getAccelerator());
    -}
    -
    -function testGetSetCaptionForItemWithMnemonics() {
    -  var contentArr = [];
    -  contentArr.push(goog.dom.createDom('span',
    -      goog.getCssName('goog-menuitem-mnemonic-hint'), 'H'));
    -  contentArr.push(goog.dom.createTextNode('ello'));
    -  item.setCaption(contentArr);
    -  assertEquals('getCaption() must not return hint markup', 'Hello',
    -      item.getCaption());
    -
    -  contentArr = [];
    -  contentArr.push(goog.dom.createTextNode('Hello'));
    -  contentArr.push(goog.dom.createDom('span',
    -      goog.getCssName('goog-menuitem-mnemonic-separator'), '(',
    -      goog.dom.createDom('span',
    -          goog.getCssName('goog-menuitem-mnemonic-hint'), 'J'), ')'));
    -  item.setCaption(contentArr);
    -  assertEquals('getCaption() must not return the paranethetical mnemonic',
    -      'Hello', item.getCaption());
    -
    -  item.setCaption('');
    -  assertEquals('getCaption() must return the empty string', '',
    -      item.getCaption());
    -}
    -
    -function testHandleKeyEventInternalWithMnemonic() {
    -  item.performActionInternal =
    -      goog.testing.recordFunction(item.performActionInternal);
    -  item.setMnemonic(goog.events.KeyCodes.F);
    -  item.handleKeyEventInternal({'keyCode': goog.events.KeyCodes.F});
    -  assertEquals('performActionInternal must be called', 1,
    -      item.performActionInternal.getCallCount());
    -}
    -
    -function testHandleKeyEventInternalWithoutMnemonic() {
    -  item.performActionInternal = goog.testing.recordFunction(
    -      item.performActionInternal);
    -  item.handleKeyEventInternal({'keyCode': goog.events.KeyCodes.F});
    -  assertEquals('performActionInternal must not be called without a' +
    -      ' mnemonic', 0, item.performActionInternal.getCallCount());
    -}
    -
    -function testRender() {
    -  item.render(sandbox);
    -  var contentElement = item.getContentElement();
    -  assertNotNull('Content element must exist', contentElement);
    -  assertTrue('Content element must have expected class name',
    -      goog.dom.classlist.contains(contentElement,
    -          item.getRenderer().getStructuralCssClass() + '-content'));
    -  assertHTMLEquals('Content element must have expected structure',
    -      'Item', contentElement.innerHTML);
    -}
    -
    -function testRenderSelectableItem() {
    -  item.setSelectable(true);
    -  item.render(sandbox);
    -  assertTrue('Item must have checkbox structure',
    -      item.getRenderer().hasCheckBoxStructure(item.getElement()));
    -  assertEquals('getCaption() return expected value', 'Item',
    -      item.getCaption());
    -}
    -
    -function testRenderSelectedItem() {
    -  item.setSelectable(true);
    -  item.setSelected(true);
    -  item.render(sandbox);
    -  assertTrue('Item must have checkbox structure',
    -      item.getRenderer().hasCheckBoxStructure(item.getElement()));
    -  assertTrue('Item must have selected style',
    -      goog.dom.classlist.contains(item.getElement(),
    -          item.getRenderer().getClassForState(
    -              goog.ui.Component.State.SELECTED)));
    -}
    -
    -function testRenderCheckableItem() {
    -  item.setCheckable(true);
    -  item.render(sandbox);
    -  assertTrue('Item must have checkbox structure',
    -      item.getRenderer().hasCheckBoxStructure(item.getElement()));
    -  assertEquals('getCaption() return expected value', 'Item',
    -      item.getCaption());
    -}
    -
    -function testRenderCheckedItem() {
    -  item.setCheckable(true);
    -  item.setChecked(true);
    -  item.render(sandbox);
    -  assertTrue('Item must have checkbox structure',
    -      item.getRenderer().hasCheckBoxStructure(item.getElement()));
    -  assertTrue('Item must have checked style',
    -      goog.dom.classlist.contains(item.getElement(),
    -          item.getRenderer().getClassForState(
    -              goog.ui.Component.State.CHECKED)));
    -}
    -
    -function testDecorate() {
    -  sandbox.innerHTML = '<div id="foo">Foo</div>';
    -  var foo = goog.dom.getElement('foo');
    -  item.decorate(foo);
    -  assertEquals('Decorated element must be as expected', foo,
    -      item.getElement());
    -  assertTrue('Decorated element must have expected class name',
    -      goog.dom.classlist.contains(item.getElement(),
    -          item.getRenderer().getCssClass()));
    -  assertEquals('Content element must be the decorated element\'s child',
    -      item.getContentElement(), item.getElement().firstChild);
    -  assertHTMLEquals('Content must have expected structure', 'Foo',
    -      item.getContentElement().innerHTML);
    -}
    -
    -function testDecorateCheckableItem() {
    -  sandbox.innerHTML = '<div id="foo" class="goog-option">Foo</div>';
    -  var foo = goog.dom.getElement('foo');
    -  item.decorate(foo);
    -  assertEquals('Decorated element must be as expected', foo,
    -      item.getElement());
    -  assertTrue('Decorated element must have expected class name',
    -      goog.dom.classlist.contains(item.getElement(),
    -          item.getRenderer().getCssClass()));
    -  assertEquals('Content element must be the decorated element\'s child',
    -      item.getContentElement(), item.getElement().firstChild);
    -  assertTrue('Item must have checkbox structure',
    -      item.getRenderer().hasCheckBoxStructure(item.getElement()));
    -  assertFalse('Item must not be checked', item.isChecked());
    -}
    -
    -function testDecorateCheckedItem() {
    -  sandbox.innerHTML =
    -      '<div id="foo" class="goog-option goog-option-selected">Foo</div>';
    -  var foo = goog.dom.getElement('foo');
    -  item.decorate(foo);
    -  assertEquals('Decorated element must be as expected', foo,
    -      item.getElement());
    -  assertSameElements('Decorated element must have expected class names',
    -      ['goog-menuitem', 'goog-option', 'goog-option-selected'],
    -      goog.dom.classlist.get(item.getElement()));
    -  assertEquals('Content element must be the decorated element\'s child',
    -      item.getContentElement(), item.getElement().firstChild);
    -  assertTrue('Item must have checkbox structure',
    -      item.getRenderer().hasCheckBoxStructure(item.getElement()));
    -  assertTrue('Item must be checked', item.isChecked());
    -}
    -
    -function testDecorateTemplate() {
    -  sandbox.innerHTML = '<div id="foo" class="goog-menuitem">' +
    -      '<div class="goog-menuitem-content">Foo</div></div>';
    -  var foo = goog.dom.getElement('foo');
    -  item.decorate(foo);
    -  assertEquals('Decorated element must be as expected', foo,
    -      item.getElement());
    -  assertTrue('Decorated element must have expected class name',
    -      goog.dom.classlist.contains(item.getElement(),
    -          item.getRenderer().getCssClass()));
    -  assertEquals('Content element must be the decorated element\'s child',
    -      item.getContentElement(), item.getElement().firstChild);
    -  assertHTMLEquals('Content must have expected structure', 'Foo',
    -      item.getContentElement().innerHTML);
    -}
    -
    -function testDecorateCheckableItemTemplate() {
    -  sandbox.innerHTML = '<div id="foo" class="goog-menuitem goog-option">' +
    -      '<div class="goog-menuitem-content">' +
    -      '<div class="goog-menuitem-checkbox"></div>' +
    -      'Foo</div></div>';
    -  var foo = goog.dom.getElement('foo');
    -  item.decorate(foo);
    -  assertEquals('Decorated element must be as expected', foo,
    -      item.getElement());
    -  assertTrue('Decorated element must have expected class name',
    -      goog.dom.classlist.contains(item.getElement(),
    -          item.getRenderer().getCssClass()));
    -  assertEquals('Content element must be the decorated element\'s child',
    -      item.getContentElement(), item.getElement().firstChild);
    -  assertTrue('Item must have checkbox structure',
    -      item.getRenderer().hasCheckBoxStructure(item.getElement()));
    -  assertEquals('Item must have exactly one checkbox structure', 1,
    -      goog.dom.getElementsByTagNameAndClass('div', 'goog-menuitem-checkbox',
    -          item.getElement()).length);
    -  assertFalse('Item must not be checked', item.isChecked());
    -}
    -
    -function testDecorateCheckedItemTemplate() {
    -  sandbox.innerHTML = '<div id="foo" ' +
    -      'class="goog-menuitem goog-option goog-option-selected">' +
    -      '<div class="goog-menuitem-content">' +
    -      '<div class="goog-menuitem-checkbox"></div>' +
    -      'Foo</div></div>';
    -  var foo = goog.dom.getElement('foo');
    -  item.decorate(foo);
    -  assertEquals('Decorated element must be as expected', foo,
    -      item.getElement());
    -  assertSameElements('Decorated element must have expected class names',
    -      ['goog-menuitem', 'goog-option', 'goog-option-selected'],
    -      goog.dom.classlist.get(item.getElement()));
    -  assertEquals('Content element must be the decorated element\'s child',
    -      item.getContentElement(), item.getElement().firstChild);
    -  assertTrue('Item must have checkbox structure',
    -      item.getRenderer().hasCheckBoxStructure(item.getElement()));
    -  assertEquals('Item must have exactly one checkbox structure', 1,
    -      goog.dom.getElementsByTagNameAndClass('div', 'goog-menuitem-checkbox',
    -          item.getElement()).length);
    -  assertTrue('Item must be checked', item.isChecked());
    -}
    -
    -
    -/** @bug 1463524 */
    -function testHandleMouseUp() {
    -  var COORDS_1 = new goog.math.Coordinate(1, 1);
    -  var COORDS_2 = new goog.math.Coordinate(2, 2);
    -  item.setActive(true);
    -  // Override performActionInternal() for testing purposes.
    -  var actionPerformed;
    -  item.performActionInternal = function() {
    -    actionPerformed = true;
    -    return true;
    -  };
    -  item.render(sandbox);
    -
    -  // Scenario 1: item has no parent.
    -  actionPerformed = false;
    -  item.setActive(true);
    -  goog.testing.events.fireMouseUpEvent(item.getElement());
    -  assertTrue('Action should be performed on mouseup', actionPerformed);
    -
    -  // Scenario 2: item has a parent.
    -  actionPerformed = false;
    -  item.setActive(true);
    -  var parent = new goog.ui.Component();
    -  var parentElem = goog.dom.getElement('parentComponent');
    -  parent.render(parentElem);
    -  parent.addChild(item);
    -  parent.openingCoords = COORDS_1;
    -  goog.testing.events.fireMouseUpEvent(
    -      item.getElement(), undefined, COORDS_2);
    -  assertTrue('Action should be performed on mouseup', actionPerformed);
    -
    -  // Scenario 3: item has a parent which was opened during mousedown, and
    -  // item, and now the mouseup fires at the same coords.
    -  actionPerformed = false;
    -  item.setActive(true);
    -  parent.openingCoords = COORDS_2;
    -  goog.testing.events.fireMouseUpEvent(
    -      item.getElement(), undefined, COORDS_2);
    -  assertFalse('Action should not be performed on mouseup', actionPerformed);
    -}
    -
    -function testSetAriaLabel() {
    -  assertNull('Item must not have aria label by default', item.getAriaLabel());
    -  item.setAriaLabel('Item 1');
    -  item.render(sandbox);
    -  var el = item.getElementStrict();
    -  assertEquals('Item element must have expected aria-label', 'Item 1',
    -      el.getAttribute('aria-label'));
    -  assertEquals('Item element must have expected aria-role', 'menuitem',
    -      el.getAttribute('role'));
    -  item.setAriaLabel('Item 2');
    -  assertEquals('Item element must have updated aria-label', 'Item 2',
    -      el.getAttribute('aria-label'));
    -  assertEquals('Item element must have expected aria-role', 'menuitem',
    -      el.getAttribute('role'));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/menuitemrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/menuitemrenderer.js
    deleted file mode 100644
    index 76e9765fab0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/menuitemrenderer.js
    +++ /dev/null
    @@ -1,354 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Renderer for {@link goog.ui.MenuItem}s.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.MenuItemRenderer');
    -
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.ControlRenderer');
    -
    -
    -
    -/**
    - * Default renderer for {@link goog.ui.MenuItem}s.  Each item has the following
    - * structure:
    - * <pre>
    - *   <div class="goog-menuitem">
    - *     <div class="goog-menuitem-content">
    - *       ...(menu item contents)...
    - *     </div>
    - *   </div>
    - * </pre>
    - * @constructor
    - * @extends {goog.ui.ControlRenderer}
    - */
    -goog.ui.MenuItemRenderer = function() {
    -  goog.ui.ControlRenderer.call(this);
    -
    -  /**
    -   * Commonly used CSS class names, cached here for convenience (and to avoid
    -   * unnecessary string concatenation).
    -   * @type {!Array<string>}
    -   * @private
    -   */
    -  this.classNameCache_ = [];
    -};
    -goog.inherits(goog.ui.MenuItemRenderer, goog.ui.ControlRenderer);
    -goog.addSingletonGetter(goog.ui.MenuItemRenderer);
    -
    -
    -/**
    - * CSS class name the renderer applies to menu item elements.
    - * @type {string}
    - */
    -goog.ui.MenuItemRenderer.CSS_CLASS = goog.getCssName('goog-menuitem');
    -
    -
    -/**
    - * Constants for referencing composite CSS classes.
    - * @enum {number}
    - * @private
    - */
    -goog.ui.MenuItemRenderer.CompositeCssClassIndex_ = {
    -  HOVER: 0,
    -  CHECKBOX: 1,
    -  CONTENT: 2
    -};
    -
    -
    -/**
    - * Returns the composite CSS class by using the cached value or by constructing
    - * the value from the base CSS class and the passed index.
    - * @param {goog.ui.MenuItemRenderer.CompositeCssClassIndex_} index Index for the
    - *     CSS class - could be highlight, checkbox or content in usual cases.
    - * @return {string} The composite CSS class.
    - * @private
    - */
    -goog.ui.MenuItemRenderer.prototype.getCompositeCssClass_ = function(index) {
    -  var result = this.classNameCache_[index];
    -  if (!result) {
    -    switch (index) {
    -      case goog.ui.MenuItemRenderer.CompositeCssClassIndex_.HOVER:
    -        result = goog.getCssName(this.getStructuralCssClass(), 'highlight');
    -        break;
    -      case goog.ui.MenuItemRenderer.CompositeCssClassIndex_.CHECKBOX:
    -        result = goog.getCssName(this.getStructuralCssClass(), 'checkbox');
    -        break;
    -      case goog.ui.MenuItemRenderer.CompositeCssClassIndex_.CONTENT:
    -        result = goog.getCssName(this.getStructuralCssClass(), 'content');
    -        break;
    -    }
    -    this.classNameCache_[index] = result;
    -  }
    -
    -  return result;
    -};
    -
    -
    -/** @override */
    -goog.ui.MenuItemRenderer.prototype.getAriaRole = function() {
    -  return goog.a11y.aria.Role.MENU_ITEM;
    -};
    -
    -
    -/**
    - * Overrides {@link goog.ui.ControlRenderer#createDom} by adding extra markup
    - * and stying to the menu item's element if it is selectable or checkable.
    - * @param {goog.ui.Control} item Menu item to render.
    - * @return {Element} Root element for the item.
    - * @override
    - */
    -goog.ui.MenuItemRenderer.prototype.createDom = function(item) {
    -  var element = item.getDomHelper().createDom(
    -      'div', this.getClassNames(item).join(' '),
    -      this.createContent(item.getContent(), item.getDomHelper()));
    -  this.setEnableCheckBoxStructure(item, element,
    -      item.isSupportedState(goog.ui.Component.State.SELECTED) ||
    -      item.isSupportedState(goog.ui.Component.State.CHECKED));
    -  return element;
    -};
    -
    -
    -/** @override */
    -goog.ui.MenuItemRenderer.prototype.getContentElement = function(element) {
    -  return /** @type {Element} */ (element && element.firstChild);
    -};
    -
    -
    -/**
    - * Overrides {@link goog.ui.ControlRenderer#decorate} by initializing the
    - * menu item to checkable based on whether the element to be decorated has
    - * extra stying indicating that it should be.
    - * @param {goog.ui.Control} item Menu item instance to decorate the element.
    - * @param {Element} element Element to decorate.
    - * @return {Element} Decorated element.
    - * @override
    - */
    -goog.ui.MenuItemRenderer.prototype.decorate = function(item, element) {
    -  goog.asserts.assert(element);
    -  if (!this.hasContentStructure(element)) {
    -    element.appendChild(
    -        this.createContent(element.childNodes, item.getDomHelper()));
    -  }
    -  if (goog.dom.classlist.contains(element, goog.getCssName('goog-option'))) {
    -    (/** @type {goog.ui.MenuItem} */ (item)).setCheckable(true);
    -    this.setCheckable(item, element, true);
    -  }
    -  return goog.ui.MenuItemRenderer.superClass_.decorate.call(this, item,
    -      element);
    -};
    -
    -
    -/**
    - * Takes a menu item's root element, and sets its content to the given text
    - * caption or DOM structure.  Overrides the superclass immplementation by
    - * making sure that the checkbox structure (for selectable/checkable menu
    - * items) is preserved.
    - * @param {Element} element The item's root element.
    - * @param {goog.ui.ControlContent} content Text caption or DOM structure to be
    - *     set as the item's content.
    - * @override
    - */
    -goog.ui.MenuItemRenderer.prototype.setContent = function(element, content) {
    -  // Save the checkbox element, if present.
    -  var contentElement = this.getContentElement(element);
    -  var checkBoxElement = this.hasCheckBoxStructure(element) ?
    -      contentElement.firstChild : null;
    -  goog.ui.MenuItemRenderer.superClass_.setContent.call(this, element, content);
    -  if (checkBoxElement && !this.hasCheckBoxStructure(element)) {
    -    // The call to setContent() blew away the checkbox element; reattach it.
    -    contentElement.insertBefore(checkBoxElement,
    -        contentElement.firstChild || null);
    -  }
    -};
    -
    -
    -/**
    - * Returns true if the element appears to have a proper menu item structure by
    - * checking whether its first child has the appropriate structural class name.
    - * @param {Element} element Element to check.
    - * @return {boolean} Whether the element appears to have a proper menu item DOM.
    - * @protected
    - */
    -goog.ui.MenuItemRenderer.prototype.hasContentStructure = function(element) {
    -  var child = goog.dom.getFirstElementChild(element);
    -  var contentClassName = this.getCompositeCssClass_(
    -      goog.ui.MenuItemRenderer.CompositeCssClassIndex_.CONTENT);
    -  return !!child && goog.dom.classlist.contains(child, contentClassName);
    -};
    -
    -
    -/**
    - * Wraps the given text caption or existing DOM node(s) in a structural element
    - * containing the menu item's contents.
    - * @param {goog.ui.ControlContent} content Menu item contents.
    - * @param {goog.dom.DomHelper} dom DOM helper for document interaction.
    - * @return {Element} Menu item content element.
    - * @protected
    - */
    -goog.ui.MenuItemRenderer.prototype.createContent = function(content, dom) {
    -  var contentClassName = this.getCompositeCssClass_(
    -      goog.ui.MenuItemRenderer.CompositeCssClassIndex_.CONTENT);
    -  return dom.createDom('div', contentClassName, content);
    -};
    -
    -
    -/**
    - * Enables/disables radio button semantics on the menu item.
    - * @param {goog.ui.Control} item Menu item to update.
    - * @param {Element} element Menu item element to update (may be null if the
    - *     item hasn't been rendered yet).
    - * @param {boolean} selectable Whether the item should be selectable.
    - */
    -goog.ui.MenuItemRenderer.prototype.setSelectable = function(item, element,
    -    selectable) {
    -  if (item && element) {
    -    this.setEnableCheckBoxStructure(item, element, selectable);
    -  }
    -};
    -
    -
    -/**
    - * Enables/disables checkbox semantics on the menu item.
    - * @param {goog.ui.Control} item Menu item to update.
    - * @param {Element} element Menu item element to update (may be null if the
    - *     item hasn't been rendered yet).
    - * @param {boolean} checkable Whether the item should be checkable.
    - */
    -goog.ui.MenuItemRenderer.prototype.setCheckable = function(item, element,
    -    checkable) {
    -  if (item && element) {
    -    this.setEnableCheckBoxStructure(item, element, checkable);
    -  }
    -};
    -
    -
    -/**
    - * Determines whether the item contains a checkbox element.
    - * @param {Element} element Menu item root element.
    - * @return {boolean} Whether the element contains a checkbox element.
    - * @protected
    - */
    -goog.ui.MenuItemRenderer.prototype.hasCheckBoxStructure = function(element) {
    -  var contentElement = this.getContentElement(element);
    -  if (contentElement) {
    -    var child = contentElement.firstChild;
    -    var checkboxClassName = this.getCompositeCssClass_(
    -        goog.ui.MenuItemRenderer.CompositeCssClassIndex_.CHECKBOX);
    -    return !!child && goog.dom.isElement(child) &&
    -        goog.dom.classlist.contains(/** @type {!Element} */ (child),
    -            checkboxClassName);
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Adds or removes extra markup and CSS styling to the menu item to make it
    - * selectable or non-selectable, depending on the value of the
    - * {@code selectable} argument.
    - * @param {!goog.ui.Control} item Menu item to update.
    - * @param {!Element} element Menu item element to update.
    - * @param {boolean} enable Whether to add or remove the checkbox structure.
    - * @protected
    - */
    -goog.ui.MenuItemRenderer.prototype.setEnableCheckBoxStructure = function(item,
    -    element, enable) {
    -  this.setAriaRole(element, item.getPreferredAriaRole());
    -  this.setAriaStates(item, element);
    -  if (enable != this.hasCheckBoxStructure(element)) {
    -    goog.dom.classlist.enable(element, goog.getCssName('goog-option'), enable);
    -    var contentElement = this.getContentElement(element);
    -    if (enable) {
    -      // Insert checkbox structure.
    -      var checkboxClassName = this.getCompositeCssClass_(
    -          goog.ui.MenuItemRenderer.CompositeCssClassIndex_.CHECKBOX);
    -      contentElement.insertBefore(
    -          item.getDomHelper().createDom('div', checkboxClassName),
    -          contentElement.firstChild || null);
    -    } else {
    -      // Remove checkbox structure.
    -      contentElement.removeChild(contentElement.firstChild);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Takes a single {@link goog.ui.Component.State}, and returns the
    - * corresponding CSS class name (null if none).  Overrides the superclass
    - * implementation by using 'highlight' as opposed to 'hover' as the CSS
    - * class name suffix for the HOVER state, for backwards compatibility.
    - * @param {goog.ui.Component.State} state Component state.
    - * @return {string|undefined} CSS class representing the given state
    - *     (undefined if none).
    - * @override
    - */
    -goog.ui.MenuItemRenderer.prototype.getClassForState = function(state) {
    -  switch (state) {
    -    case goog.ui.Component.State.HOVER:
    -      // We use 'highlight' as the suffix, for backwards compatibility.
    -      return this.getCompositeCssClass_(
    -          goog.ui.MenuItemRenderer.CompositeCssClassIndex_.HOVER);
    -    case goog.ui.Component.State.CHECKED:
    -    case goog.ui.Component.State.SELECTED:
    -      // We use 'goog-option-selected' as the class, for backwards
    -      // compatibility.
    -      return goog.getCssName('goog-option-selected');
    -    default:
    -      return goog.ui.MenuItemRenderer.superClass_.getClassForState.call(this,
    -          state);
    -  }
    -};
    -
    -
    -/**
    - * Takes a single CSS class name which may represent a component state, and
    - * returns the corresponding component state (0x00 if none).  Overrides the
    - * superclass implementation by treating 'goog-option-selected' as special,
    - * for backwards compatibility.
    - * @param {string} className CSS class name, possibly representing a component
    - *     state.
    - * @return {goog.ui.Component.State} state Component state corresponding
    - *     to the given CSS class (0x00 if none).
    - * @override
    - */
    -goog.ui.MenuItemRenderer.prototype.getStateFromClass = function(className) {
    -  var hoverClassName = this.getCompositeCssClass_(
    -      goog.ui.MenuItemRenderer.CompositeCssClassIndex_.HOVER);
    -  switch (className) {
    -    case goog.getCssName('goog-option-selected'):
    -      return goog.ui.Component.State.CHECKED;
    -    case hoverClassName:
    -      return goog.ui.Component.State.HOVER;
    -    default:
    -      return goog.ui.MenuItemRenderer.superClass_.getStateFromClass.call(this,
    -          className);
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.MenuItemRenderer.prototype.getCssClass = function() {
    -  return goog.ui.MenuItemRenderer.CSS_CLASS;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/menuitemrenderer_test.html b/src/database/third_party/closure-library/closure/goog/ui/menuitemrenderer_test.html
    deleted file mode 100644
    index 0bad9140229..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/menuitemrenderer_test.html
    +++ /dev/null
    @@ -1,27 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -Author: attila@google.com (Attila Bodis)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.MenuItemRenderer
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.MenuItemRendererTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="sandbox">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/menuitemrenderer_test.js b/src/database/third_party/closure-library/closure/goog/ui/menuitemrenderer_test.js
    deleted file mode 100644
    index 58b638d97e9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/menuitemrenderer_test.js
    +++ /dev/null
    @@ -1,243 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.MenuItemRendererTest');
    -goog.setTestOnly('goog.ui.MenuItemRendererTest');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.ui.rendererasserts');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.MenuItem');
    -goog.require('goog.ui.MenuItemRenderer');
    -
    -var sandbox;
    -var item, renderer;
    -
    -function setUp() {
    -  sandbox = goog.dom.getElement('sandbox');
    -  item = new goog.ui.MenuItem('Hello');
    -  renderer = goog.ui.MenuItemRenderer.getInstance();
    -}
    -
    -function tearDown() {
    -  item.dispose();
    -  goog.dom.removeChildren(sandbox);
    -}
    -
    -function testMenuItemRenderer() {
    -  assertNotNull('Instance must not be null', renderer);
    -  assertEquals('Singleton getter must always return same instance',
    -      renderer, goog.ui.MenuItemRenderer.getInstance());
    -}
    -
    -function testCreateDom() {
    -  var element = renderer.createDom(item);
    -  assertNotNull('Element must not be null', element);
    -  assertSameElements('Element must have the expected class names',
    -      ['goog-menuitem'], goog.dom.classlist.get(element));
    -  assertEquals('Element must have exactly one child element', 1,
    -      element.childNodes.length);
    -  assertHTMLEquals('Child element must have the expected structure',
    -      '<div class="goog-menuitem-content">Hello</div>',
    -      element.innerHTML);
    -}
    -
    -function testCreateDomWithHoverState() {
    -  item.setHighlighted(true);
    -  var element = renderer.createDom(item);
    -  assertSameElements('Element must have the expected class names',
    -      ['goog-menuitem', 'goog-menuitem-highlight'],
    -      goog.dom.classlist.get(element));
    -}
    -
    -function testCreateDomForCheckableItem() {
    -  item.setSupportedState(goog.ui.Component.State.CHECKED, true);
    -  item.render();
    -  var element = item.getElement();
    -  assertNotNull(element);
    -  assertSameElements('Element must have the expected class names',
    -      ['goog-menuitem', 'goog-option'],
    -      goog.dom.classlist.get(element));
    -  assertEquals('Element must have ARIA role menuitemcheckbox',
    -      goog.a11y.aria.Role.MENU_ITEM_CHECKBOX,
    -      goog.a11y.aria.getRole(element));
    -
    -  item.setChecked(true);
    -  assertTrue('Item must be checked', item.isChecked());
    -  assertSameElements('Checked item must have the expected class names',
    -      ['goog-menuitem', 'goog-option', 'goog-option-selected'],
    -      goog.dom.classlist.get(element));
    -  assertEquals('Item must have checked ARIA state', 'true',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.CHECKED));
    -}
    -
    -function testCreateUpdateDomForCheckableItem() {
    -  // Render the item first, then update its supported states to include CHECKED.
    -  item.render();
    -  var element = item.getElement();
    -  item.setSupportedState(goog.ui.Component.State.CHECKED, true);
    -  assertNotNull(element);
    -  assertSameElements('Element must have the expected class names',
    -      ['goog-menuitem', 'goog-option'],
    -      goog.dom.classlist.get(element));
    -  assertEquals('Element must have ARIA role menuitemcheckbox',
    -      goog.a11y.aria.Role.MENU_ITEM_CHECKBOX,
    -      goog.a11y.aria.getRole(element));
    -
    -  // Now actually check the item.
    -  item.setChecked(true);
    -  assertTrue('Item must be checked', item.isChecked());
    -  assertSameElements('Checked item must have the expected class names',
    -      ['goog-menuitem', 'goog-option', 'goog-option-selected'],
    -      goog.dom.classlist.get(element));
    -  assertEquals('Item must have checked ARIA state', 'true',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.CHECKED));
    -}
    -
    -function testCreateDomForSelectableItem() {
    -  item.setSupportedState(goog.ui.Component.State.SELECTED, true);
    -  item.render();
    -  var element = item.getElement();
    -  assertNotNull(element);
    -  assertSameElements('Element must have the expected class names',
    -      ['goog-menuitem', 'goog-option'],
    -      goog.dom.classlist.get(element));
    -  assertEquals('Element must have ARIA role menuitemradio',
    -      goog.a11y.aria.Role.MENU_ITEM_RADIO,
    -      goog.a11y.aria.getRole(element));
    -
    -  item.setSelected(true);
    -  assertTrue('Item must be selected', item.isSelected());
    -  assertSameElements('Selected item must have the expected class names',
    -      ['goog-menuitem', 'goog-option', 'goog-option-selected'],
    -      goog.dom.classlist.get(element));
    -  assertEquals('Item must have selected ARIA state', 'true',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.CHECKED));
    -}
    -
    -function testCreateUpdateDomForSelectableItem() {
    -  // Render the item first, then update its supported states to include
    -  // SELECTED.
    -  item.render();
    -  var element = item.getElement();
    -  item.setSupportedState(goog.ui.Component.State.SELECTED, true);
    -  assertNotNull(element);
    -  assertSameElements('Element must have the expected class names',
    -      ['goog-menuitem', 'goog-option'],
    -      goog.dom.classlist.get(element));
    -  assertEquals('Element must have ARIA role menuitemradio',
    -      goog.a11y.aria.Role.MENU_ITEM_RADIO,
    -      goog.a11y.aria.getRole(element));
    -
    -  // Now actually select the item.
    -  item.setSelected(true);
    -  assertTrue('Item must be selected', item.isSelected());
    -  assertSameElements('Selected item must have the expected class names',
    -      ['goog-menuitem', 'goog-option', 'goog-option-selected'],
    -      goog.dom.classlist.get(element));
    -  assertEquals('Item must have selected ARIA state', 'true',
    -      goog.a11y.aria.getState(element, goog.a11y.aria.State.CHECKED));
    -}
    -
    -function testGetContentElement() {
    -  assertNull('Content element must be the null initially',
    -      item.getContentElement());
    -  item.createDom();
    -  assertEquals('Content element must be the element\'s first child',
    -      item.getElement().firstChild, item.getContentElement());
    -}
    -
    -function testDecorate() {
    -  sandbox.innerHTML = '<div id="foo">Hello</div>';
    -  var foo = goog.dom.getElement('foo');
    -
    -  var element = renderer.decorate(item, foo);
    -  assertSameElements('Element must have the expected class names',
    -      ['goog-menuitem'], goog.dom.classlist.get(element));
    -  assertEquals('Element must have exactly one child element', 1,
    -      element.childNodes.length);
    -  assertHTMLEquals('Child element must have the expected structure',
    -      '<div class="goog-menuitem-content">Hello</div>',
    -      element.innerHTML);
    -}
    -
    -function testDecorateWithContentStructure() {
    -  sandbox.innerHTML =
    -      '<div id="foo"><div class="goog-menuitem-content">Hello</div></div>';
    -  var foo = goog.dom.getElement('foo');
    -
    -  var element = renderer.decorate(item, foo);
    -  assertSameElements('Element must have the expected class names',
    -      ['goog-menuitem'], goog.dom.classlist.get(element));
    -  assertEquals('Element must have exactly one child element', 1,
    -      element.childNodes.length);
    -  assertHTMLEquals('Child element must have the expected structure',
    -      '<div class="goog-menuitem-content">Hello</div>',
    -      element.innerHTML);
    -}
    -
    -function testDecorateWithHoverState() {
    -  sandbox.innerHTML =
    -      '<div id="foo" class="goog-menuitem-highlight">Hello</div>';
    -  var foo = goog.dom.getElement('foo');
    -
    -  assertFalse('Item must not be highlighted', item.isHighlighted());
    -  var element = renderer.decorate(item, foo);
    -  assertSameElements('Element must have the expected class names',
    -      ['goog-menuitem', 'goog-menuitem-highlight'],
    -      goog.dom.classlist.get(element));
    -  assertTrue('Item must be highlighted', item.isHighlighted());
    -}
    -
    -function testDecorateCheckableItem() {
    -  sandbox.innerHTML = '<div id="foo" class="goog-option">Hello</div>';
    -  var foo = goog.dom.getElement('foo');
    -
    -  assertFalse('Item must not be checkable',
    -      item.isSupportedState(goog.ui.Component.State.CHECKED));
    -  var element = renderer.decorate(item, foo);
    -  assertSameElements('Element must have the expected class names',
    -      ['goog-menuitem', 'goog-option'], goog.dom.classlist.get(element));
    -  assertTrue('Item must be checkable',
    -      item.isSupportedState(goog.ui.Component.State.CHECKED));
    -  assertHTMLEquals('Child element must have the expected structure',
    -      '<div class="goog-menuitem-content">' +
    -          '<div class="goog-menuitem-checkbox"></div>Hello</div>',
    -      element.innerHTML);
    -}
    -
    -function testSetContent() {
    -  item.setSupportedState(goog.ui.Component.State.CHECKED, true);
    -  var element = renderer.createDom(item);
    -  assertHTMLEquals('Child element must have the expected structure',
    -      '<div class="goog-menuitem-content">' +
    -          '<div class="goog-menuitem-checkbox"></div>Hello</div>',
    -      element.innerHTML);
    -
    -  renderer.setContent(element, 'Goodbye');
    -  assertHTMLEquals('Child element must have the expected structure',
    -      '<div class="goog-menuitem-content">' +
    -          '<div class="goog-menuitem-checkbox"></div>Goodbye</div>',
    -      element.innerHTML);
    -}
    -
    -function testDoesntCallGetCssClassInConstructor() {
    -  goog.testing.ui.rendererasserts.
    -      assertNoGetCssClassCallsInConstructor(goog.ui.MenuItemRenderer);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/menurenderer.js b/src/database/third_party/closure-library/closure/goog/ui/menurenderer.js
    deleted file mode 100644
    index f39134d91f6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/menurenderer.js
    +++ /dev/null
    @@ -1,114 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Renderer for {@link goog.ui.Menu}s.
    - *
    - * @author robbyw@google.com (Robby Walker)
    - */
    -
    -goog.provide('goog.ui.MenuRenderer');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.ui.ContainerRenderer');
    -goog.require('goog.ui.Separator');
    -
    -
    -
    -/**
    - * Default renderer for {@link goog.ui.Menu}s, based on {@link
    - * goog.ui.ContainerRenderer}.
    - * @param {string=} opt_ariaRole Optional ARIA role used for the element.
    - * @constructor
    - * @extends {goog.ui.ContainerRenderer}
    - */
    -goog.ui.MenuRenderer = function(opt_ariaRole) {
    -  goog.ui.ContainerRenderer.call(this,
    -      opt_ariaRole || goog.a11y.aria.Role.MENU);
    -};
    -goog.inherits(goog.ui.MenuRenderer, goog.ui.ContainerRenderer);
    -goog.addSingletonGetter(goog.ui.MenuRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of toolbars rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.MenuRenderer.CSS_CLASS = goog.getCssName('goog-menu');
    -
    -
    -/**
    - * Returns whether the element is a UL or acceptable to our superclass.
    - * @param {Element} element Element to decorate.
    - * @return {boolean} Whether the renderer can decorate the element.
    - * @override
    - */
    -goog.ui.MenuRenderer.prototype.canDecorate = function(element) {
    -  return element.tagName == 'UL' ||
    -      goog.ui.MenuRenderer.superClass_.canDecorate.call(this, element);
    -};
    -
    -
    -/**
    - * Inspects the element, and creates an instance of {@link goog.ui.Control} or
    - * an appropriate subclass best suited to decorate it.  Overrides the superclass
    - * implementation by recognizing HR elements as separators.
    - * @param {Element} element Element to decorate.
    - * @return {goog.ui.Control?} A new control suitable to decorate the element
    - *     (null if none).
    - * @override
    - */
    -goog.ui.MenuRenderer.prototype.getDecoratorForChild = function(element) {
    -  return element.tagName == 'HR' ?
    -      new goog.ui.Separator() :
    -      goog.ui.MenuRenderer.superClass_.getDecoratorForChild.call(this,
    -          element);
    -};
    -
    -
    -/**
    - * Returns whether the given element is contained in the menu's DOM.
    - * @param {goog.ui.Menu} menu The menu to test.
    - * @param {Element} element The element to test.
    - * @return {boolean} Whether the given element is contained in the menu.
    - */
    -goog.ui.MenuRenderer.prototype.containsElement = function(menu, element) {
    -  return goog.dom.contains(menu.getElement(), element);
    -};
    -
    -
    -/**
    - * Returns the CSS class to be applied to the root element of containers
    - * rendered using this renderer.
    - * @return {string} Renderer-specific CSS class.
    - * @override
    - */
    -goog.ui.MenuRenderer.prototype.getCssClass = function() {
    -  return goog.ui.MenuRenderer.CSS_CLASS;
    -};
    -
    -
    -/** @override */
    -goog.ui.MenuRenderer.prototype.initializeDom = function(container) {
    -  goog.ui.MenuRenderer.superClass_.initializeDom.call(this, container);
    -
    -  var element = container.getElement();
    -  goog.asserts.assert(element, 'The menu DOM element cannot be null.');
    -  goog.a11y.aria.setState(element, goog.a11y.aria.State.HASPOPUP, 'true');
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/menuseparator.js b/src/database/third_party/closure-library/closure/goog/ui/menuseparator.js
    deleted file mode 100644
    index 67365f58f03..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/menuseparator.js
    +++ /dev/null
    @@ -1,52 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A class for representing menu separators.
    - * @see goog.ui.Menu
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.MenuSeparator');
    -
    -goog.require('goog.ui.MenuSeparatorRenderer');
    -goog.require('goog.ui.Separator');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * Class representing a menu separator.  A menu separator extends {@link
    - * goog.ui.Separator} by always setting its renderer to {@link
    - * goog.ui.MenuSeparatorRenderer}.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper used for
    - *     document interactions.
    - * @constructor
    - * @extends {goog.ui.Separator}
    - */
    -goog.ui.MenuSeparator = function(opt_domHelper) {
    -  goog.ui.Separator.call(this, goog.ui.MenuSeparatorRenderer.getInstance(),
    -      opt_domHelper);
    -};
    -goog.inherits(goog.ui.MenuSeparator, goog.ui.Separator);
    -
    -
    -// Register a decorator factory function for goog.ui.MenuSeparators.
    -goog.ui.registry.setDecoratorByClassName(
    -    goog.ui.MenuSeparatorRenderer.CSS_CLASS,
    -    function() {
    -      // Separator defaults to using MenuSeparatorRenderer.
    -      return new goog.ui.Separator();
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/menuseparatorrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/menuseparatorrenderer.js
    deleted file mode 100644
    index c2e139ba8e0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/menuseparatorrenderer.js
    +++ /dev/null
    @@ -1,112 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Renderer for {@link goog.ui.MenuSeparator}s.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.MenuSeparatorRenderer');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.ui.ControlRenderer');
    -
    -
    -
    -/**
    - * Renderer for menu separators.
    - * @constructor
    - * @extends {goog.ui.ControlRenderer}
    - */
    -goog.ui.MenuSeparatorRenderer = function() {
    -  goog.ui.ControlRenderer.call(this);
    -};
    -goog.inherits(goog.ui.MenuSeparatorRenderer, goog.ui.ControlRenderer);
    -goog.addSingletonGetter(goog.ui.MenuSeparatorRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.MenuSeparatorRenderer.CSS_CLASS = goog.getCssName('goog-menuseparator');
    -
    -
    -/**
    - * Returns an empty, styled menu separator DIV.  Overrides {@link
    - * goog.ui.ControlRenderer#createDom}.
    - * @param {goog.ui.Control} separator goog.ui.Separator to render.
    - * @return {!Element} Root element for the separator.
    - * @override
    - */
    -goog.ui.MenuSeparatorRenderer.prototype.createDom = function(separator) {
    -  return separator.getDomHelper().createDom('div', this.getCssClass());
    -};
    -
    -
    -/**
    - * Takes an existing element, and decorates it with the separator.  Overrides
    - * {@link goog.ui.ControlRenderer#decorate}.
    - * @param {goog.ui.Control} separator goog.ui.MenuSeparator to decorate the
    - *     element.
    - * @param {Element} element Element to decorate.
    - * @return {!Element} Decorated element.
    - * @override
    - */
    -goog.ui.MenuSeparatorRenderer.prototype.decorate = function(separator,
    -                                                            element) {
    -  // Normally handled in the superclass. But we don't call the superclass.
    -  if (element.id) {
    -    separator.setId(element.id);
    -  }
    -
    -  if (element.tagName == 'HR') {
    -    // Replace HR with separator.
    -    var hr = element;
    -    element = this.createDom(separator);
    -    goog.dom.insertSiblingBefore(element, hr);
    -    goog.dom.removeNode(hr);
    -  } else {
    -    goog.dom.classlist.add(element, this.getCssClass());
    -  }
    -  return element;
    -};
    -
    -
    -/**
    - * Overrides {@link goog.ui.ControlRenderer#setContent} to do nothing, since
    - * separators are empty.
    - * @param {Element} separator The separator's root element.
    - * @param {goog.ui.ControlContent} content Text caption or DOM structure to be
    - *    set as the separators's content (ignored).
    - * @override
    - */
    -goog.ui.MenuSeparatorRenderer.prototype.setContent = function(separator,
    -                                                              content) {
    -  // Do nothing.  Separators are empty.
    -};
    -
    -
    -/**
    - * Returns the CSS class to be applied to the root element of components
    - * rendered using this renderer.
    - * @return {string} Renderer-specific CSS class.
    - * @override
    - */
    -goog.ui.MenuSeparatorRenderer.prototype.getCssClass = function() {
    -  return goog.ui.MenuSeparatorRenderer.CSS_CLASS;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/menuseparatorrenderer_test.html b/src/database/third_party/closure-library/closure/goog/ui/menuseparatorrenderer_test.html
    deleted file mode 100644
    index 4a3947d273e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/menuseparatorrenderer_test.html
    +++ /dev/null
    @@ -1,31 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -
    -  @author mfrederick@google.com (Michael Frederick)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests for MenuSeparatorRenderer
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.MenuSeparatorRendererTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="sandbox">
    -   <!-- A menu separator to decorate -->
    -   <div id="separator" class="goog-menuseparator">
    -   </div>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/menuseparatorrenderer_test.js b/src/database/third_party/closure-library/closure/goog/ui/menuseparatorrenderer_test.js
    deleted file mode 100644
    index 8caaf03408d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/menuseparatorrenderer_test.js
    +++ /dev/null
    @@ -1,43 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.MenuSeparatorRendererTest');
    -goog.setTestOnly('goog.ui.MenuSeparatorRendererTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.MenuSeparator');
    -goog.require('goog.ui.MenuSeparatorRenderer');
    -
    -var sandbox;
    -var originalSandbox;
    -
    -function setUp() {
    -  sandbox = goog.dom.getElement('sandbox');
    -  originalSandbox = sandbox.cloneNode(true);
    -}
    -
    -function tearDown() {
    -  sandbox.parentNode.replaceChild(originalSandbox, sandbox);
    -}
    -
    -function testDecorate() {
    -  var separator = new goog.ui.MenuSeparator();
    -  var dummyId = 'foo';
    -  separator.setId(dummyId);
    -  assertEquals(dummyId, separator.getId());
    -  var renderer = new goog.ui.MenuSeparatorRenderer();
    -  renderer.decorate(separator, goog.dom.getElement('separator'));
    -  assertEquals('separator', separator.getId());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/mockactivitymonitor.js b/src/database/third_party/closure-library/closure/goog/ui/mockactivitymonitor.js
    deleted file mode 100644
    index 10c1737991e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/mockactivitymonitor.js
    +++ /dev/null
    @@ -1,72 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Definition of goog.ui.MockActivityMonitor.
    - */
    -
    -goog.provide('goog.ui.MockActivityMonitor');
    -
    -goog.require('goog.events.EventType');
    -goog.require('goog.ui.ActivityMonitor');
    -
    -
    -
    -/**
    - * A mock implementation of goog.ui.ActivityMonitor for unit testing. Clients
    - * of this class should override goog.now to return a synthetic time from
    - * the unit test.
    - * @constructor
    - * @extends {goog.ui.ActivityMonitor}
    - * @final
    - */
    -goog.ui.MockActivityMonitor = function() {
    -  goog.ui.MockActivityMonitor.base(this, 'constructor');
    -
    -  /**
    -   * Tracks whether an event has been fired. Used by simulateEvent.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.eventFired_ = false;
    -};
    -goog.inherits(goog.ui.MockActivityMonitor, goog.ui.ActivityMonitor);
    -
    -
    -/**
    - * Simulates an event that updates the user to being non-idle.
    - * @param {goog.events.EventType=} opt_type The type of event that made the user
    - *     not idle. If not specified, defaults to MOUSEMOVE.
    - */
    -goog.ui.MockActivityMonitor.prototype.simulateEvent = function(opt_type) {
    -  var eventTime = goog.now();
    -  var eventType = opt_type || goog.events.EventType.MOUSEMOVE;
    -
    -  this.eventFired_ = false;
    -  this.updateIdleTime(eventTime, eventType);
    -
    -  if (!this.eventFired_) {
    -    this.dispatchEvent(goog.ui.ActivityMonitor.Event.ACTIVITY);
    -  }
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.ui.MockActivityMonitor.prototype.dispatchEvent = function(e) {
    -  var rv = goog.ui.MockActivityMonitor.base(this, 'dispatchEvent', e);
    -  this.eventFired_ = true;
    -  return rv;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/mockactivitymonitor_test.html b/src/database/third_party/closure-library/closure/goog/ui/mockactivitymonitor_test.html
    deleted file mode 100644
    index 2b3eccbcda5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/mockactivitymonitor_test.html
    +++ /dev/null
    @@ -1,19 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.ui.MockActivityMonitor</title>
    -<script src="../base.js"></script>
    -<script>
    -goog.require('goog.ui.MockActivityMonitorTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/mockactivitymonitor_test.js b/src/database/third_party/closure-library/closure/goog/ui/mockactivitymonitor_test.js
    deleted file mode 100644
    index b0405ec3870..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/mockactivitymonitor_test.js
    +++ /dev/null
    @@ -1,94 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Tests for goog.ui.MockActivityMonitorTest.
    - * @author nnaze@google.com (Nathan Naze)
    - */
    -
    -/** @suppress {extraProvide} */
    -goog.provide('goog.ui.MockActivityMonitorTest');
    -
    -goog.require('goog.events');
    -goog.require('goog.functions');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -goog.require('goog.ui.ActivityMonitor');
    -goog.require('goog.ui.MockActivityMonitor');
    -
    -goog.setTestOnly('goog.ui.MockActivityMonitorTest');
    -
    -var googNow = goog.now;
    -var monitor;
    -var recordedFunction;
    -var replacer;
    -
    -function setUp() {
    -  monitor = new goog.ui.MockActivityMonitor();
    -  recordedFunction = goog.testing.recordFunction();
    -
    -  goog.events.listen(
    -      monitor,
    -      goog.ui.ActivityMonitor.Event.ACTIVITY,
    -      recordedFunction);
    -}
    -
    -function tearDown() {
    -  goog.dispose(monitor);
    -  goog.now = googNow;
    -}
    -
    -function testEventFireSameTime() {
    -  goog.now = goog.functions.constant(1000);
    -
    -  monitor.simulateEvent();
    -  assertEquals(1, recordedFunction.getCallCount());
    -
    -  monitor.simulateEvent();
    -  assertEquals(2, recordedFunction.getCallCount());
    -}
    -
    -function testEventFireDifferingTime() {
    -  goog.now = goog.functions.constant(1000);
    -  monitor.simulateEvent();
    -  assertEquals(1, recordedFunction.getCallCount());
    -
    -  goog.now = goog.functions.constant(1001);
    -  monitor.simulateEvent();
    -  assertEquals(2, recordedFunction.getCallCount());
    -}
    -
    -function testDispatchEventReturnValue() {
    -  assertTrue(monitor.dispatchEvent(goog.ui.ActivityMonitor.Event.ACTIVITY));
    -  assertEquals(1, recordedFunction.getCallCount());
    -}
    -
    -function testDispatchEventPreventDefault() {
    -  // Undo the listen call in setUp.
    -  goog.events.unlisten(
    -      monitor,
    -      goog.ui.ActivityMonitor.Event.ACTIVITY,
    -      recordedFunction);
    -
    -  // Listen with a function that cancels the event.
    -  goog.events.listen(
    -      monitor,
    -      goog.ui.ActivityMonitor.Event.ACTIVITY,
    -      function(e) {
    -        e.preventDefault();
    -      });
    -
    -  assertFalse(monitor.dispatchEvent(goog.ui.ActivityMonitor.Event.ACTIVITY));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/modalpopup.js b/src/database/third_party/closure-library/closure/goog/ui/modalpopup.js
    deleted file mode 100644
    index 615840a8500..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/modalpopup.js
    +++ /dev/null
    @@ -1,748 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Class for showing simple modal popup.
    - * @author chrishenry@google.com (Chris Henry)
    - */
    -
    -goog.provide('goog.ui.ModalPopup');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.dom.iframe');
    -goog.require('goog.events');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.FocusHandler');
    -goog.require('goog.fx.Transition');
    -goog.require('goog.string');
    -goog.require('goog.style');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.PopupBase');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Base class for modal popup UI components. This can also be used as
    - * a standalone component to render a modal popup with an empty div.
    - *
    - * WARNING: goog.ui.ModalPopup is only guaranteed to work when it is rendered
    - * directly in the 'body' element.
    - *
    - * The Html structure of the modal popup is:
    - * <pre>
    - *  Element         Function              Class-name, goog-modalpopup = default
    - * ----------------------------------------------------------------------------
    - * - iframe         Iframe mask           goog-modalpopup-bg
    - * - div            Background mask       goog-modalpopup-bg
    - * - div            Modal popup area      goog-modalpopup
    - * - span           Tab catcher
    - * </pre>
    - * @constructor
    - * @param {boolean=} opt_useIframeMask Work around windowed controls z-index
    - *     issue by using an iframe instead of a div for bg element.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper; see {@link
    - *     goog.ui.Component} for semantics.
    - * @extends {goog.ui.Component}
    - */
    -goog.ui.ModalPopup = function(opt_useIframeMask, opt_domHelper) {
    -  goog.ui.ModalPopup.base(this, 'constructor', opt_domHelper);
    -
    -  /**
    -   * Whether the modal popup should use an iframe as the background
    -   * element to work around z-order issues.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.useIframeMask_ = !!opt_useIframeMask;
    -
    -  /**
    -   * The element that had focus before the popup was displayed.
    -   * @type {Element}
    -   * @private
    -   */
    -  this.lastFocus_ = null;
    -};
    -goog.inherits(goog.ui.ModalPopup, goog.ui.Component);
    -goog.tagUnsealableClass(goog.ui.ModalPopup);
    -
    -
    -/**
    - * Focus handler. It will be initialized in enterDocument.
    - * @type {goog.events.FocusHandler}
    - * @private
    - */
    -goog.ui.ModalPopup.prototype.focusHandler_ = null;
    -
    -
    -/**
    - * Whether the modal popup is visible.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.ModalPopup.prototype.visible_ = false;
    -
    -
    -/**
    - * Element for the background which obscures the UI and blocks events.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.ModalPopup.prototype.bgEl_ = null;
    -
    -
    -/**
    - * Iframe element that is only used for IE as a workaround to keep select-type
    - * elements from burning through background.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.ModalPopup.prototype.bgIframeEl_ = null;
    -
    -
    -/**
    - * Element used to catch focus and prevent the user from tabbing out
    - * of the popup.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.ModalPopup.prototype.tabCatcherElement_ = null;
    -
    -
    -/**
    - * Whether the modal popup is in the process of wrapping focus from the top of
    - * the popup to the last tabbable element.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.ModalPopup.prototype.backwardTabWrapInProgress_ = false;
    -
    -
    -/**
    - * Transition to show the popup.
    - * @type {goog.fx.Transition}
    - * @private
    - */
    -goog.ui.ModalPopup.prototype.popupShowTransition_;
    -
    -
    -/**
    - * Transition to hide the popup.
    - * @type {goog.fx.Transition}
    - * @private
    - */
    -goog.ui.ModalPopup.prototype.popupHideTransition_;
    -
    -
    -/**
    - * Transition to show the background.
    - * @type {goog.fx.Transition}
    - * @private
    - */
    -goog.ui.ModalPopup.prototype.bgShowTransition_;
    -
    -
    -/**
    - * Transition to hide the background.
    - * @type {goog.fx.Transition}
    - * @private
    - */
    -goog.ui.ModalPopup.prototype.bgHideTransition_;
    -
    -
    -/**
    - * The elements set to aria-hidden when the popup was made visible.
    - * @type {Array<!Element>}
    - * @private
    - */
    -goog.ui.ModalPopup.prototype.hiddenElements_;
    -
    -
    -/**
    - * @return {string} Base CSS class for this component.
    - * @protected
    - */
    -goog.ui.ModalPopup.prototype.getCssClass = function() {
    -  return goog.getCssName('goog-modalpopup');
    -};
    -
    -
    -/**
    - * Returns the background iframe mask element, if any.
    - * @return {Element} The background iframe mask element, may return
    - *     null/undefined if the modal popup does not use iframe mask.
    - */
    -goog.ui.ModalPopup.prototype.getBackgroundIframe = function() {
    -  return this.bgIframeEl_;
    -};
    -
    -
    -/**
    - * Returns the background mask element.
    - * @return {Element} The background mask element.
    - */
    -goog.ui.ModalPopup.prototype.getBackgroundElement = function() {
    -  return this.bgEl_;
    -};
    -
    -
    -/**
    - * Creates the initial DOM representation for the modal popup.
    - * @override
    - */
    -goog.ui.ModalPopup.prototype.createDom = function() {
    -  // Create the modal popup element, and make sure it's hidden.
    -  goog.ui.ModalPopup.base(this, 'createDom');
    -
    -  var element = this.getElement();
    -  goog.asserts.assert(element);
    -  var allClasses = goog.string.trim(this.getCssClass()).split(' ');
    -  goog.dom.classlist.addAll(element, allClasses);
    -  goog.dom.setFocusableTabIndex(element, true);
    -  goog.style.setElementShown(element, false);
    -
    -  // Manages the DOM for background mask elements.
    -  this.manageBackgroundDom_();
    -  this.createTabCatcher_();
    -};
    -
    -
    -/**
    - * Creates and disposes of the DOM for background mask elements.
    - * @private
    - */
    -goog.ui.ModalPopup.prototype.manageBackgroundDom_ = function() {
    -  if (this.useIframeMask_ && !this.bgIframeEl_) {
    -    // IE renders the iframe on top of the select elements while still
    -    // respecting the z-index of the other elements on the page.  See
    -    // http://support.microsoft.com/kb/177378 for more information.
    -    // Flash and other controls behave in similar ways for other browsers
    -    this.bgIframeEl_ = goog.dom.iframe.createBlank(this.getDomHelper());
    -    this.bgIframeEl_.className = goog.getCssName(this.getCssClass(), 'bg');
    -    goog.style.setElementShown(this.bgIframeEl_, false);
    -    goog.style.setOpacity(this.bgIframeEl_, 0);
    -  }
    -
    -  // Create the backgound mask, initialize its opacity, and make sure it's
    -  // hidden.
    -  if (!this.bgEl_) {
    -    this.bgEl_ = this.getDomHelper().createDom(
    -        'div', goog.getCssName(this.getCssClass(), 'bg'));
    -    goog.style.setElementShown(this.bgEl_, false);
    -  }
    -};
    -
    -
    -/**
    - * Creates the tab catcher element.
    - * @private
    - */
    -goog.ui.ModalPopup.prototype.createTabCatcher_ = function() {
    -  // Creates tab catcher element.
    -  if (!this.tabCatcherElement_) {
    -    this.tabCatcherElement_ = this.getDomHelper().createElement('span');
    -    goog.style.setElementShown(this.tabCatcherElement_, false);
    -    goog.dom.setFocusableTabIndex(this.tabCatcherElement_, true);
    -    this.tabCatcherElement_.style.position = 'absolute';
    -  }
    -};
    -
    -
    -/**
    - * Allow a shift-tab from the top of the modal popup to the last tabbable
    - * element by moving focus to the tab catcher. This should be called after
    - * catching a wrapping shift-tab event and before allowing it to propagate, so
    - * that focus will land on the last tabbable element before the tab catcher.
    - * @protected
    - */
    -goog.ui.ModalPopup.prototype.setupBackwardTabWrap = function() {
    -  this.backwardTabWrapInProgress_ = true;
    -  try {
    -    this.tabCatcherElement_.focus();
    -  } catch (e) {
    -    // Swallow this. IE can throw an error if the element can not be focused.
    -  }
    -  // Reset the flag on a timer in case anything goes wrong with the followup
    -  // event.
    -  goog.Timer.callOnce(this.resetBackwardTabWrap_, 0, this);
    -};
    -
    -
    -/**
    - * Resets the backward tab wrap flag.
    - * @private
    - */
    -goog.ui.ModalPopup.prototype.resetBackwardTabWrap_ = function() {
    -  this.backwardTabWrapInProgress_ = false;
    -};
    -
    -
    -/**
    - * Renders the background mask.
    - * @private
    - */
    -goog.ui.ModalPopup.prototype.renderBackground_ = function() {
    -  goog.asserts.assert(!!this.bgEl_, 'Background element must not be null.');
    -  if (this.bgIframeEl_) {
    -    goog.dom.insertSiblingBefore(this.bgIframeEl_, this.getElement());
    -  }
    -  goog.dom.insertSiblingBefore(this.bgEl_, this.getElement());
    -};
    -
    -
    -/** @override */
    -goog.ui.ModalPopup.prototype.canDecorate = function(element) {
    -  // Assume we can decorate any DIV.
    -  return !!element && element.tagName == goog.dom.TagName.DIV;
    -};
    -
    -
    -/** @override */
    -goog.ui.ModalPopup.prototype.decorateInternal = function(element) {
    -  // Decorate the modal popup area element.
    -  goog.ui.ModalPopup.base(this, 'decorateInternal', element);
    -  var allClasses = goog.string.trim(this.getCssClass()).split(' ');
    -
    -  goog.dom.classlist.addAll(
    -      goog.asserts.assert(this.getElement()),
    -      allClasses);
    -
    -  // Create the background mask...
    -  this.manageBackgroundDom_();
    -  this.createTabCatcher_();
    -
    -  // Make sure the decorated modal popup is focusable and hidden.
    -  goog.dom.setFocusableTabIndex(this.getElement(), true);
    -  goog.style.setElementShown(this.getElement(), false);
    -};
    -
    -
    -/** @override */
    -goog.ui.ModalPopup.prototype.enterDocument = function() {
    -  this.renderBackground_();
    -  goog.ui.ModalPopup.base(this, 'enterDocument');
    -
    -  goog.dom.insertSiblingAfter(this.tabCatcherElement_, this.getElement());
    -
    -  this.focusHandler_ = new goog.events.FocusHandler(
    -      this.getDomHelper().getDocument());
    -
    -  // We need to watch the entire document so that we can detect when the
    -  // focus is moved out of this modal popup.
    -  this.getHandler().listen(
    -      this.focusHandler_, goog.events.FocusHandler.EventType.FOCUSIN,
    -      this.onFocus);
    -  this.setA11YDetectBackground(false);
    -};
    -
    -
    -/** @override */
    -goog.ui.ModalPopup.prototype.exitDocument = function() {
    -  if (this.isVisible()) {
    -    this.setVisible(false);
    -  }
    -
    -  goog.dispose(this.focusHandler_);
    -
    -  goog.ui.ModalPopup.base(this, 'exitDocument');
    -  goog.dom.removeNode(this.bgIframeEl_);
    -  goog.dom.removeNode(this.bgEl_);
    -  goog.dom.removeNode(this.tabCatcherElement_);
    -};
    -
    -
    -/**
    - * Sets the visibility of the modal popup box and focus to the popup.
    - * @param {boolean} visible Whether the modal popup should be visible.
    - */
    -goog.ui.ModalPopup.prototype.setVisible = function(visible) {
    -  goog.asserts.assert(
    -      this.isInDocument(), 'ModalPopup must be rendered first.');
    -
    -  if (visible == this.visible_) {
    -    return;
    -  }
    -
    -  if (this.popupShowTransition_) this.popupShowTransition_.stop();
    -  if (this.bgShowTransition_) this.bgShowTransition_.stop();
    -  if (this.popupHideTransition_) this.popupHideTransition_.stop();
    -  if (this.bgHideTransition_) this.bgHideTransition_.stop();
    -
    -  if (this.isInDocument()) {
    -    this.setA11YDetectBackground(visible);
    -  }
    -  if (visible) {
    -    this.show_();
    -  } else {
    -    this.hide_();
    -  }
    -};
    -
    -
    -/**
    - * Sets aria-hidden on the rest of the page to restrict screen reader focus.
    - * Top-level elements with an explicit aria-hidden state are not altered.
    - * @param {boolean} hide Whether to hide or show the rest of the page.
    - * @protected
    - */
    -goog.ui.ModalPopup.prototype.setA11YDetectBackground = function(hide) {
    -  if (hide) {
    -    if (!this.hiddenElements_) {
    -      this.hiddenElements_ = [];
    -    }
    -    var dom = this.getDomHelper();
    -    var topLevelChildren = dom.getChildren(dom.getDocument().body);
    -    for (var i = 0; i < topLevelChildren.length; i++) {
    -      var child = topLevelChildren[i];
    -      if (child != this.getElementStrict() &&
    -          !goog.a11y.aria.getState(child, goog.a11y.aria.State.HIDDEN)) {
    -        goog.a11y.aria.setState(child, goog.a11y.aria.State.HIDDEN, true);
    -        this.hiddenElements_.push(child);
    -      }
    -    }
    -  } else if (this.hiddenElements_) {
    -    for (var i = 0; i < this.hiddenElements_.length; i++) {
    -      goog.a11y.aria.removeState(
    -          this.hiddenElements_[i], goog.a11y.aria.State.HIDDEN);
    -    }
    -    this.hiddenElements_ = null;
    -  }
    -};
    -
    -
    -/**
    - * Sets the transitions to show and hide the popup and background.
    - * @param {!goog.fx.Transition} popupShowTransition Transition to show the
    - *     popup.
    - * @param {!goog.fx.Transition} popupHideTransition Transition to hide the
    - *     popup.
    - * @param {!goog.fx.Transition} bgShowTransition Transition to show
    - *     the background.
    - * @param {!goog.fx.Transition} bgHideTransition Transition to hide
    - *     the background.
    - */
    -goog.ui.ModalPopup.prototype.setTransition = function(popupShowTransition,
    -    popupHideTransition, bgShowTransition, bgHideTransition) {
    -  this.popupShowTransition_ = popupShowTransition;
    -  this.popupHideTransition_ = popupHideTransition;
    -  this.bgShowTransition_ = bgShowTransition;
    -  this.bgHideTransition_ = bgHideTransition;
    -};
    -
    -
    -/**
    - * Shows the popup.
    - * @private
    - */
    -goog.ui.ModalPopup.prototype.show_ = function() {
    -  if (!this.dispatchEvent(goog.ui.PopupBase.EventType.BEFORE_SHOW)) {
    -    return;
    -  }
    -
    -  try {
    -    this.lastFocus_ = this.getDomHelper().getDocument().activeElement;
    -  } catch (e) {
    -    // Focus-related actions often throw exceptions.
    -    // Sample past issue: https://bugzilla.mozilla.org/show_bug.cgi?id=656283
    -  }
    -  this.resizeBackground_();
    -  this.reposition();
    -
    -  // Listen for keyboard and resize events while the modal popup is visible.
    -  this.getHandler().listen(
    -      this.getDomHelper().getWindow(), goog.events.EventType.RESIZE,
    -      this.resizeBackground_);
    -
    -  this.showPopupElement_(true);
    -  this.focus();
    -  this.visible_ = true;
    -
    -  if (this.popupShowTransition_ && this.bgShowTransition_) {
    -    goog.events.listenOnce(
    -        /** @type {!goog.events.EventTarget} */ (this.popupShowTransition_),
    -        goog.fx.Transition.EventType.END, this.onShow, false, this);
    -    this.bgShowTransition_.play();
    -    this.popupShowTransition_.play();
    -  } else {
    -    this.onShow();
    -  }
    -};
    -
    -
    -/**
    - * Hides the popup.
    - * @private
    - */
    -goog.ui.ModalPopup.prototype.hide_ = function() {
    -  if (!this.dispatchEvent(goog.ui.PopupBase.EventType.BEFORE_HIDE)) {
    -    return;
    -  }
    -
    -  // Stop listening for keyboard and resize events while the modal
    -  // popup is hidden.
    -  this.getHandler().unlisten(
    -      this.getDomHelper().getWindow(), goog.events.EventType.RESIZE,
    -      this.resizeBackground_);
    -
    -  // Set visibility to hidden even if there is a transition. This
    -  // reduces complexity in subclasses who may want to override
    -  // setVisible (such as goog.ui.Dialog).
    -  this.visible_ = false;
    -
    -  if (this.popupHideTransition_ && this.bgHideTransition_) {
    -    goog.events.listenOnce(
    -        /** @type {!goog.events.EventTarget} */ (this.popupHideTransition_),
    -        goog.fx.Transition.EventType.END, this.onHide, false, this);
    -    this.bgHideTransition_.play();
    -    // The transition whose END event you are listening to must be played last
    -    // to prevent errors when disposing on hide event, which occur on browsers
    -    // that do not support CSS3 transitions.
    -    this.popupHideTransition_.play();
    -  } else {
    -    this.onHide();
    -  }
    -
    -  this.returnFocus_();
    -};
    -
    -
    -/**
    - * Attempts to return the focus back to the element that had it before the popup
    - * was opened.
    - * @private
    - */
    -goog.ui.ModalPopup.prototype.returnFocus_ = function() {
    -  try {
    -    var dom = this.getDomHelper();
    -    var body = dom.getDocument().body;
    -    var active = dom.getDocument().activeElement || body;
    -    if (!this.lastFocus_ || this.lastFocus_ == body) {
    -      this.lastFocus_ = null;
    -      return;
    -    }
    -    // We only want to move the focus if we actually have it, i.e.:
    -    //  - if we immediately hid the popup the focus should have moved to the
    -    // body element
    -    //  - if there is a hiding transition in progress the focus would still be
    -    // within the dialog and it is safe to move it if the current focused
    -    // element is a child of the dialog
    -    if (active == body || dom.contains(this.getElement(), active)) {
    -      this.lastFocus_.focus();
    -    }
    -  } catch (e) {
    -    // Swallow this. IE can throw an error if the element can not be focused.
    -  }
    -  // Explicitly want to null this out even if there was an error focusing to
    -  // avoid bleed over between dialog invocations.
    -  this.lastFocus_ = null;
    -};
    -
    -
    -/**
    - * Shows or hides the popup element.
    - * @param {boolean} visible Shows the popup element if true, hides if false.
    - * @private
    - */
    -goog.ui.ModalPopup.prototype.showPopupElement_ = function(visible) {
    -  if (this.bgIframeEl_) {
    -    goog.style.setElementShown(this.bgIframeEl_, visible);
    -  }
    -  if (this.bgEl_) {
    -    goog.style.setElementShown(this.bgEl_, visible);
    -  }
    -  goog.style.setElementShown(this.getElement(), visible);
    -  goog.style.setElementShown(this.tabCatcherElement_, visible);
    -};
    -
    -
    -/**
    - * Called after the popup is shown. If there is a transition, this
    - * will be called after the transition completed or stopped.
    - * @protected
    - */
    -goog.ui.ModalPopup.prototype.onShow = function() {
    -  this.dispatchEvent(goog.ui.PopupBase.EventType.SHOW);
    -};
    -
    -
    -/**
    - * Called after the popup is hidden. If there is a transition, this
    - * will be called after the transition completed or stopped.
    - * @protected
    - */
    -goog.ui.ModalPopup.prototype.onHide = function() {
    -  this.showPopupElement_(false);
    -  this.dispatchEvent(goog.ui.PopupBase.EventType.HIDE);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the modal popup is visible.
    - */
    -goog.ui.ModalPopup.prototype.isVisible = function() {
    -  return this.visible_;
    -};
    -
    -
    -/**
    - * Focuses on the modal popup.
    - */
    -goog.ui.ModalPopup.prototype.focus = function() {
    -  this.focusElement_();
    -};
    -
    -
    -/**
    - * Make the background element the size of the document.
    - *
    - * NOTE(user): We must hide the background element before measuring the
    - * document, otherwise the size of the background will stop the document from
    - * shrinking to fit a smaller window.  This does cause a slight flicker in Linux
    - * browsers, but should not be a common scenario.
    - * @private
    - */
    -goog.ui.ModalPopup.prototype.resizeBackground_ = function() {
    -  if (this.bgIframeEl_) {
    -    goog.style.setElementShown(this.bgIframeEl_, false);
    -  }
    -  if (this.bgEl_) {
    -    goog.style.setElementShown(this.bgEl_, false);
    -  }
    -
    -  var doc = this.getDomHelper().getDocument();
    -  var win = goog.dom.getWindow(doc) || window;
    -
    -  // Take the max of document height and view height, in case the document does
    -  // not fill the viewport. Read from both the body element and the html element
    -  // to account for browser differences in treatment of absolutely-positioned
    -  // content.
    -  var viewSize = goog.dom.getViewportSize(win);
    -  var w = Math.max(viewSize.width,
    -      Math.max(doc.body.scrollWidth, doc.documentElement.scrollWidth));
    -  var h = Math.max(viewSize.height,
    -      Math.max(doc.body.scrollHeight, doc.documentElement.scrollHeight));
    -
    -  if (this.bgIframeEl_) {
    -    goog.style.setElementShown(this.bgIframeEl_, true);
    -    goog.style.setSize(this.bgIframeEl_, w, h);
    -  }
    -  if (this.bgEl_) {
    -    goog.style.setElementShown(this.bgEl_, true);
    -    goog.style.setSize(this.bgEl_, w, h);
    -  }
    -};
    -
    -
    -/**
    - * Centers the modal popup in the viewport, taking scrolling into account.
    - */
    -goog.ui.ModalPopup.prototype.reposition = function() {
    -  // TODO(chrishenry): Make this use goog.positioning as in goog.ui.PopupBase?
    -
    -  // Get the current viewport to obtain the scroll offset.
    -  var doc = this.getDomHelper().getDocument();
    -  var win = goog.dom.getWindow(doc) || window;
    -  if (goog.style.getComputedPosition(this.getElement()) == 'fixed') {
    -    var x = 0;
    -    var y = 0;
    -  } else {
    -    var scroll = this.getDomHelper().getDocumentScroll();
    -    var x = scroll.x;
    -    var y = scroll.y;
    -  }
    -
    -  var popupSize = goog.style.getSize(this.getElement());
    -  var viewSize = goog.dom.getViewportSize(win);
    -
    -  // Make sure left and top are non-negatives.
    -  var left = Math.max(x + viewSize.width / 2 - popupSize.width / 2, 0);
    -  var top = Math.max(y + viewSize.height / 2 - popupSize.height / 2, 0);
    -  goog.style.setPosition(this.getElement(), left, top);
    -
    -  // We place the tab catcher at the same position as the dialog to
    -  // prevent IE from scrolling when users try to tab out of the dialog.
    -  goog.style.setPosition(this.tabCatcherElement_, left, top);
    -};
    -
    -
    -/**
    - * Handles focus events.  Makes sure that if the user tabs past the
    - * elements in the modal popup, the focus wraps back to the beginning, and that
    - * if the user shift-tabs past the front of the modal popup, focus wraps around
    - * to the end.
    - * @param {goog.events.BrowserEvent} e Browser's event object.
    - * @protected
    - */
    -goog.ui.ModalPopup.prototype.onFocus = function(e) {
    -  if (this.backwardTabWrapInProgress_) {
    -    this.resetBackwardTabWrap_();
    -  } else if (e.target == this.tabCatcherElement_) {
    -    goog.Timer.callOnce(this.focusElement_, 0, this);
    -  }
    -};
    -
    -
    -/**
    - * Returns the magic tab catcher element used to detect when the user has
    - * rolled focus off of the popup content.  It is automatically created during
    - * the createDom method() and can be used by subclasses to implement custom
    - * tab-loop behavior.
    - * @return {Element} The tab catcher element.
    - * @protected
    - */
    -goog.ui.ModalPopup.prototype.getTabCatcherElement = function() {
    -  return this.tabCatcherElement_;
    -};
    -
    -
    -/**
    - * Moves the focus to the modal popup.
    - * @private
    - */
    -goog.ui.ModalPopup.prototype.focusElement_ = function() {
    -  try {
    -    if (goog.userAgent.IE) {
    -      // In IE, we must first focus on the body or else focussing on a
    -      // sub-element will not work.
    -      this.getDomHelper().getDocument().body.focus();
    -    }
    -    this.getElement().focus();
    -  } catch (e) {
    -    // Swallow this. IE can throw an error if the element can not be focused.
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.ModalPopup.prototype.disposeInternal = function() {
    -  goog.dispose(this.popupShowTransition_);
    -  this.popupShowTransition_ = null;
    -
    -  goog.dispose(this.popupHideTransition_);
    -  this.popupHideTransition_ = null;
    -
    -  goog.dispose(this.bgShowTransition_);
    -  this.bgShowTransition_ = null;
    -
    -  goog.dispose(this.bgHideTransition_);
    -  this.bgHideTransition_ = null;
    -
    -  goog.ui.ModalPopup.base(this, 'disposeInternal');
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/modalpopup_test.html b/src/database/third_party/closure-library/closure/goog/ui/modalpopup_test.html
    deleted file mode 100644
    index e1817ce8369..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/modalpopup_test.html
    +++ /dev/null
    @@ -1,27 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -  Author: chrishenry@google.com (Chris Henry)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.ModalPopup
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.ModalPopupTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="main">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/modalpopup_test.js b/src/database/third_party/closure-library/closure/goog/ui/modalpopup_test.js
    deleted file mode 100644
    index 4b273a3fdbd..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/modalpopup_test.js
    +++ /dev/null
    @@ -1,463 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.ModalPopupTest');
    -goog.setTestOnly('goog.ui.ModalPopupTest');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.dispose');
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.fx.Transition');
    -goog.require('goog.fx.css3');
    -goog.require('goog.string');
    -goog.require('goog.style');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.ModalPopup');
    -goog.require('goog.ui.PopupBase');
    -
    -var popup;
    -var main;
    -var mockClock;
    -
    -
    -function setUp() {
    -  main = /** @type {!Element}*/ (goog.dom.getElement('main'));
    -  mockClock = new goog.testing.MockClock(true);
    -}
    -
    -
    -function tearDown() {
    -  goog.dispose(popup);
    -  mockClock.dispose();
    -  goog.a11y.aria.removeState(main, goog.a11y.aria.State.HIDDEN);
    -}
    -
    -
    -function testDispose() {
    -  popup = new goog.ui.ModalPopup();
    -  popup.render();
    -
    -  goog.dispose(popup);
    -  assertNull(goog.dom.getElementByClass('goog-modalpopup-bg'));
    -  assertNull(goog.dom.getElementByClass('goog-modalpopup'));
    -  assertEquals(0, goog.dom.getElementsByTagNameAndClass('span').length);
    -}
    -
    -
    -function testRenderWithoutIframeMask() {
    -  popup = new goog.ui.ModalPopup();
    -  popup.render();
    -
    -  assertEquals(0, goog.dom.getElementsByTagNameAndClass(
    -      'iframe', 'goog-modalpopup-bg').length);
    -
    -  var bg = goog.dom.getElementsByTagNameAndClass('div', 'goog-modalpopup-bg');
    -  assertEquals(1, bg.length);
    -  var content = goog.dom.getElementByClass('goog-modalpopup');
    -  assertNotNull(content);
    -  var tabCatcher = goog.dom.getElementsByTagNameAndClass('span');
    -  assertEquals(1, tabCatcher.length);
    -
    -  assertTrue(goog.dom.compareNodeOrder(bg[0], content) < 0);
    -  assertTrue(goog.dom.compareNodeOrder(content, tabCatcher[0]) < 0);
    -  assertTrue(goog.string.isEmptyOrWhitespace(goog.string.makeSafe(
    -      goog.a11y.aria.getState(main, goog.a11y.aria.State.HIDDEN))));
    -  popup.setVisible(true);
    -  assertTrue(goog.string.isEmptyOrWhitespace(goog.string.makeSafe(
    -      goog.a11y.aria.getState(
    -          popup.getElementStrict(), goog.a11y.aria.State.HIDDEN))));
    -  assertEquals('true',
    -      goog.a11y.aria.getState(main, goog.a11y.aria.State.HIDDEN));
    -  popup.setVisible(false);
    -  assertTrue(goog.string.isEmptyOrWhitespace(goog.string.makeSafe(
    -      goog.a11y.aria.getState(main, goog.a11y.aria.State.HIDDEN))));
    -}
    -
    -
    -function testRenderWithIframeMask() {
    -  popup = new goog.ui.ModalPopup(true);
    -  popup.render();
    -
    -  var iframe = goog.dom.getElementsByTagNameAndClass(
    -      'iframe', 'goog-modalpopup-bg');
    -  assertEquals(1, iframe.length);
    -  var bg = goog.dom.getElementsByTagNameAndClass('div', 'goog-modalpopup-bg');
    -  assertEquals(1, bg.length);
    -  var content = goog.dom.getElementByClass('goog-modalpopup');
    -  assertNotNull(content);
    -  var tabCatcher = goog.dom.getElementsByTagNameAndClass('span');
    -  assertEquals(1, tabCatcher.length);
    -
    -  assertTrue(goog.dom.compareNodeOrder(iframe[0], bg[0]) < 0);
    -  assertTrue(goog.dom.compareNodeOrder(bg[0], content) < 0);
    -  assertTrue(goog.dom.compareNodeOrder(content, tabCatcher[0]) < 0);
    -  assertTrue(goog.string.isEmptyOrWhitespace(goog.string.makeSafe(
    -      goog.a11y.aria.getState(main, goog.a11y.aria.State.HIDDEN))));
    -  popup.setVisible(true);
    -  assertTrue(goog.string.isEmptyOrWhitespace(goog.string.makeSafe(
    -      goog.a11y.aria.getState(
    -          popup.getElementStrict(), goog.a11y.aria.State.HIDDEN))));
    -  assertEquals('true',
    -      goog.a11y.aria.getState(main, goog.a11y.aria.State.HIDDEN));
    -  popup.setVisible(false);
    -  assertTrue(goog.string.isEmptyOrWhitespace(
    -      goog.string.makeSafe(
    -          goog.a11y.aria.getState(main, goog.a11y.aria.State.HIDDEN))));
    -}
    -
    -
    -function testRenderWithAriaState() {
    -  popup = new goog.ui.ModalPopup();
    -  popup.render();
    -
    -  goog.a11y.aria.setState(main, goog.a11y.aria.State.HIDDEN, true);
    -  popup.setVisible(true);
    -  assertEquals(
    -      'true', goog.a11y.aria.getState(main, goog.a11y.aria.State.HIDDEN));
    -  popup.setVisible(false);
    -  assertEquals(
    -      'true', goog.a11y.aria.getState(main, goog.a11y.aria.State.HIDDEN));
    -
    -  goog.a11y.aria.setState(main, goog.a11y.aria.State.HIDDEN, false);
    -  popup.setVisible(true);
    -  assertEquals(
    -      'false', goog.a11y.aria.getState(main, goog.a11y.aria.State.HIDDEN));
    -  popup.setVisible(false);
    -  assertEquals(
    -      'false', goog.a11y.aria.getState(main, goog.a11y.aria.State.HIDDEN));
    -}
    -
    -
    -function testRenderDoesNotShowAnyElement() {
    -  popup = new goog.ui.ModalPopup(true);
    -  popup.render();
    -
    -  var iframe = goog.dom.getElementsByTagNameAndClass(
    -      'iframe', 'goog-modalpopup-bg');
    -  assertFalse(goog.style.isElementShown(iframe[0]));
    -  var bg = goog.dom.getElementsByTagNameAndClass('div', 'goog-modalpopup-bg');
    -  assertFalse(goog.style.isElementShown(bg[0]));
    -  assertFalse(goog.style.isElementShown(
    -      goog.dom.getElementByClass('goog-modalpopup')));
    -  var tabCatcher = goog.dom.getElementsByTagNameAndClass('span');
    -  assertFalse(goog.style.isElementShown(tabCatcher[0]));
    -}
    -
    -
    -function testIframeOpacityIsSetToZero() {
    -  popup = new goog.ui.ModalPopup(true);
    -  popup.render();
    -
    -  var iframe = goog.dom.getElementsByTagNameAndClass(
    -      'iframe', 'goog-modalpopup-bg')[0];
    -  assertEquals(0, goog.style.getOpacity(iframe));
    -}
    -
    -
    -function testEventFiredOnShow() {
    -  popup = new goog.ui.ModalPopup(true);
    -  popup.render();
    -
    -  var beforeShowCallCount = 0;
    -  var beforeShowHandler = function() {
    -    beforeShowCallCount++;
    -  };
    -  var showCallCount = false;
    -  var showHandler = function() {
    -    assertEquals('BEFORE_SHOW is not dispatched before SHOW',
    -        1, beforeShowCallCount);
    -    showCallCount++;
    -  };
    -
    -  goog.events.listen(
    -      popup, goog.ui.PopupBase.EventType.BEFORE_SHOW, beforeShowHandler);
    -  goog.events.listen(popup, goog.ui.PopupBase.EventType.SHOW, showHandler);
    -
    -  popup.setVisible(true);
    -
    -  assertEquals(1, beforeShowCallCount);
    -  assertEquals(1, showCallCount);
    -}
    -
    -
    -function testEventFiredOnHide() {
    -  popup = new goog.ui.ModalPopup(true);
    -  popup.render();
    -  popup.setVisible(true);
    -
    -  var beforeHideCallCount = 0;
    -  var beforeHideHandler = function() {
    -    beforeHideCallCount++;
    -  };
    -  var hideCallCount = false;
    -  var hideHandler = function() {
    -    assertEquals('BEFORE_HIDE is not dispatched before HIDE',
    -        1, beforeHideCallCount);
    -    hideCallCount++;
    -  };
    -
    -  goog.events.listen(
    -      popup, goog.ui.PopupBase.EventType.BEFORE_HIDE, beforeHideHandler);
    -  goog.events.listen(popup, goog.ui.PopupBase.EventType.HIDE, hideHandler);
    -
    -  popup.setVisible(false);
    -
    -  assertEquals(1, beforeHideCallCount);
    -  assertEquals(1, hideCallCount);
    -}
    -
    -
    -function testShowEventFiredWithNoTransition() {
    -  popup = new goog.ui.ModalPopup();
    -  popup.render();
    -
    -  var showHandlerCalled = false;
    -  goog.events.listen(popup, goog.ui.PopupBase.EventType.SHOW, function() {
    -    showHandlerCalled = true;
    -  });
    -
    -  popup.setVisible(true);
    -  assertTrue(showHandlerCalled);
    -}
    -
    -function testHideEventFiredWithNoTransition() {
    -  popup = new goog.ui.ModalPopup();
    -  popup.render();
    -
    -  var hideHandlerCalled = false;
    -  goog.events.listen(popup, goog.ui.PopupBase.EventType.HIDE, function() {
    -    hideHandlerCalled = true;
    -  });
    -
    -  popup.setVisible(true);
    -  popup.setVisible(false);
    -  assertTrue(hideHandlerCalled);
    -}
    -
    -function testTransitionsPlayedOnShow() {
    -  popup = new goog.ui.ModalPopup();
    -  popup.render();
    -
    -  var mockPopupShowTransition = new MockTransition();
    -  var mockPopupHideTransition = new MockTransition();
    -  var mockBgShowTransition = new MockTransition();
    -  var mockBgHideTransition = new MockTransition();
    -
    -  var showHandlerCalled = false;
    -  goog.events.listen(popup, goog.ui.PopupBase.EventType.SHOW, function() {
    -    showHandlerCalled = true;
    -  });
    -
    -  popup.setTransition(mockPopupShowTransition, mockPopupHideTransition,
    -      mockBgShowTransition, mockBgHideTransition);
    -  assertFalse(mockPopupShowTransition.wasPlayed);
    -  assertFalse(mockBgShowTransition.wasPlayed);
    -
    -  popup.setVisible(true);
    -  assertTrue(mockPopupShowTransition.wasPlayed);
    -  assertTrue(mockBgShowTransition.wasPlayed);
    -
    -  assertFalse(showHandlerCalled);
    -  mockPopupShowTransition.dispatchEvent(goog.fx.Transition.EventType.END);
    -  assertTrue(showHandlerCalled);
    -}
    -
    -
    -function testTransitionsPlayedOnHide() {
    -  popup = new goog.ui.ModalPopup();
    -  popup.render();
    -
    -  var mockPopupShowTransition = new MockTransition();
    -  var mockPopupHideTransition = new MockTransition();
    -  var mockBgShowTransition = new MockTransition();
    -  var mockBgHideTransition = new MockTransition();
    -
    -  var hideHandlerCalled = false;
    -  goog.events.listen(popup, goog.ui.PopupBase.EventType.HIDE, function() {
    -    hideHandlerCalled = true;
    -  });
    -
    -  popup.setTransition(mockPopupShowTransition, mockPopupHideTransition,
    -      mockBgShowTransition, mockBgHideTransition);
    -  popup.setVisible(true);
    -  assertFalse(mockPopupHideTransition.wasPlayed);
    -  assertFalse(mockBgHideTransition.wasPlayed);
    -
    -  popup.setVisible(false);
    -  assertTrue(mockPopupHideTransition.wasPlayed);
    -  assertTrue(mockBgHideTransition.wasPlayed);
    -
    -  assertFalse(hideHandlerCalled);
    -  mockPopupHideTransition.dispatchEvent(goog.fx.Transition.EventType.END);
    -  assertTrue(hideHandlerCalled);
    -}
    -
    -
    -function testTransitionsAndDisposingOnHideWorks() {
    -  popup = new goog.ui.ModalPopup();
    -  popup.render();
    -
    -  goog.events.listen(popup, goog.ui.PopupBase.EventType.HIDE, function() {
    -    popup.dispose();
    -  });
    -
    -  var popupShowTransition = goog.fx.css3.fadeIn(popup.getElement(),
    -      0.1 /* duration */);
    -  var popupHideTransition = goog.fx.css3.fadeOut(popup.getElement(),
    -      0.1 /* duration */);
    -  var bgShowTransition = goog.fx.css3.fadeIn(popup.getElement(),
    -      0.1 /* duration */);
    -  var bgHideTransition = goog.fx.css3.fadeOut(popup.getElement(),
    -      0.1 /* duration */);
    -
    -  popup.setTransition(popupShowTransition, popupHideTransition,
    -      bgShowTransition, bgHideTransition);
    -  popup.setVisible(true);
    -  popup.setVisible(false);
    -  // Nothing to assert. We only want to ensure that there is no error.
    -}
    -
    -
    -function testSetVisibleWorksCorrectlyWithTransitions() {
    -  popup = new goog.ui.ModalPopup();
    -  popup.render();
    -  popup.setTransition(
    -      goog.fx.css3.fadeIn(popup.getElement(), 1),
    -      goog.fx.css3.fadeIn(popup.getBackgroundElement(), 1),
    -      goog.fx.css3.fadeOut(popup.getElement(), 1),
    -      goog.fx.css3.fadeOut(popup.getBackgroundElement(), 1));
    -
    -  // Consecutive calls to setVisible works without needing to wait for
    -  // transition to finish.
    -  popup.setVisible(true);
    -  assertTrue(popup.isVisible());
    -  popup.setVisible(false);
    -  assertFalse(popup.isVisible());
    -  mockClock.tick(1100);
    -
    -  // Calling setVisible(true) immediately changed the state to visible.
    -  popup.setVisible(true);
    -  assertTrue(popup.isVisible());
    -  mockClock.tick(1100);
    -
    -  // Consecutive calls to setVisible, in opposite order.
    -  popup.setVisible(false);
    -  popup.setVisible(true);
    -  assertTrue(popup.isVisible());
    -  mockClock.tick(1100);
    -
    -  // Calling setVisible(false) immediately changed the state to not visible.
    -  popup.setVisible(false);
    -  assertFalse(popup.isVisible());
    -  mockClock.tick(1100);
    -}
    -
    -
    -function testTransitionsDisposed() {
    -  popup = new goog.ui.ModalPopup();
    -  popup.render();
    -
    -  var transition = goog.fx.css3.fadeIn(popup.getElement(), 0.1 /* duration */);
    -
    -  var hideHandlerCalled = false;
    -  goog.events.listen(popup, goog.ui.PopupBase.EventType.HIDE, function() {
    -    hideHandlerCalled = true;
    -  });
    -
    -  popup.setTransition(transition, transition, transition, transition);
    -  popup.dispose();
    -
    -  transition.dispatchEvent(goog.fx.Transition.EventType.END);
    -  assertFalse(hideHandlerCalled);
    -}
    -
    -
    -function testBackgroundHeight() {
    -  // Insert an absolutely-positioned element larger than the viewport.
    -  var viewportSize = goog.dom.getViewportSize();
    -  var w = viewportSize.width * 2;
    -  var h = viewportSize.height * 2;
    -  var dummy = goog.dom.createElement('div');
    -  dummy.style.position = 'absolute';
    -  goog.style.setSize(dummy, w, h);
    -  document.body.appendChild(dummy);
    -
    -  try {
    -    popup = new goog.ui.ModalPopup();
    -    popup.render();
    -    popup.setVisible(true);
    -
    -    var size = goog.style.getSize(popup.getBackgroundElement());
    -    assertTrue('Background element must cover the size of the content',
    -        size.width >= w && size.height >= h);
    -  } finally {
    -    goog.dom.removeNode(dummy);
    -  }
    -}
    -
    -
    -function testSetupBackwardTabWrapResetsFlagAfterTimeout() {
    -  popup.setupBackwardTabWrap();
    -  assertTrue('Backward tab wrap should be in progress',
    -      popup.backwardTabWrapInProgress_);
    -  mockClock.tick(1);
    -  assertFalse('Backward tab wrap flag should be reset after delay',
    -      popup.backwardTabWrapInProgress_);
    -}
    -
    -
    -function testPopupGetsFocus() {
    -  popup = new goog.ui.ModalPopup();
    -  popup.render();
    -  popup.setVisible(true);
    -  assertTrue('Dialog must receive initial focus',
    -      goog.dom.getActiveElement(document) == popup.getElement());
    -}
    -
    -
    -function testDecoratedPopupGetsFocus() {
    -  var dialogElem = goog.dom.createElement('div');
    -  document.body.appendChild(dialogElem);
    -  popup = new goog.ui.ModalPopup();
    -  popup.decorate(dialogElem);
    -  popup.setVisible(true);
    -  assertTrue('Dialog must receive initial focus',
    -      goog.dom.getActiveElement(document) == popup.getElement());
    -  goog.dom.removeNode(dialogElem);
    -}
    -
    -
    -
    -/**
    - * @implements {goog.fx.Transition}
    - * @extends {goog.events.EventTarget}
    - * @constructor
    - */
    -var MockTransition = function() {
    -  MockTransition.base(this, 'constructor');
    -  this.wasPlayed = false;
    -};
    -goog.inherits(MockTransition, goog.events.EventTarget);
    -
    -
    -MockTransition.prototype.play = function() {
    -  this.wasPlayed = true;
    -};
    -
    -
    -MockTransition.prototype.stop = goog.nullFunction;
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/nativebuttonrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/nativebuttonrenderer.js
    deleted file mode 100644
    index 8129c789b7e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/nativebuttonrenderer.js
    +++ /dev/null
    @@ -1,209 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Native browser button renderer for {@link goog.ui.Button}s.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.NativeButtonRenderer');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events.EventType');
    -goog.require('goog.ui.ButtonRenderer');
    -goog.require('goog.ui.Component');
    -
    -
    -
    -/**
    - * Renderer for {@link goog.ui.Button}s.  Renders and decorates native HTML
    - * button elements.  Since native HTML buttons have built-in support for many
    - * features, overrides many expensive (and redundant) superclass methods to
    - * be no-ops.
    - * @constructor
    - * @extends {goog.ui.ButtonRenderer}
    - */
    -goog.ui.NativeButtonRenderer = function() {
    -  goog.ui.ButtonRenderer.call(this);
    -};
    -goog.inherits(goog.ui.NativeButtonRenderer, goog.ui.ButtonRenderer);
    -goog.addSingletonGetter(goog.ui.NativeButtonRenderer);
    -
    -
    -/** @override */
    -goog.ui.NativeButtonRenderer.prototype.getAriaRole = function() {
    -  // Native buttons don't need ARIA roles to be recognized by screen readers.
    -  return undefined;
    -};
    -
    -
    -/**
    - * Returns the button's contents wrapped in a native HTML button element.  Sets
    - * the button's disabled attribute as needed.
    - * @param {goog.ui.Control} button Button to render.
    - * @return {Element} Root element for the button (a native HTML button element).
    - * @override
    - */
    -goog.ui.NativeButtonRenderer.prototype.createDom = function(button) {
    -  this.setUpNativeButton_(button);
    -  return button.getDomHelper().createDom('button', {
    -    'class': this.getClassNames(button).join(' '),
    -    'disabled': !button.isEnabled(),
    -    'title': button.getTooltip() || '',
    -    'value': button.getValue() || ''
    -  }, button.getCaption() || '');
    -};
    -
    -
    -/**
    - * Overrides {@link goog.ui.ButtonRenderer#canDecorate} by returning true only
    - * if the element is an HTML button.
    - * @param {Element} element Element to decorate.
    - * @return {boolean} Whether the renderer can decorate the element.
    - * @override
    - */
    -goog.ui.NativeButtonRenderer.prototype.canDecorate = function(element) {
    -  return element.tagName == 'BUTTON' ||
    -      (element.tagName == 'INPUT' && (element.type == 'button' ||
    -          element.type == 'submit' || element.type == 'reset'));
    -};
    -
    -
    -/** @override */
    -goog.ui.NativeButtonRenderer.prototype.decorate = function(button, element) {
    -  this.setUpNativeButton_(button);
    -  if (element.disabled) {
    -    // Add the marker class for the DISABLED state before letting the superclass
    -    // implementation decorate the element, so its state will be correct.
    -    var disabledClassName = goog.asserts.assertString(
    -        this.getClassForState(goog.ui.Component.State.DISABLED));
    -    goog.dom.classlist.add(element, disabledClassName);
    -  }
    -  return goog.ui.NativeButtonRenderer.superClass_.decorate.call(this, button,
    -      element);
    -};
    -
    -
    -/**
    - * Native buttons natively support BiDi and keyboard focus.
    - * @suppress {visibility} getHandler and performActionInternal
    - * @override
    - */
    -goog.ui.NativeButtonRenderer.prototype.initializeDom = function(button) {
    -  // WARNING:  This is a hack, and it is only applicable to native buttons,
    -  // which are special because they do natively what most goog.ui.Controls
    -  // do programmatically.  Do not use your renderer's initializeDom method
    -  // to hook up event handlers!
    -  button.getHandler().listen(button.getElement(), goog.events.EventType.CLICK,
    -      button.performActionInternal);
    -};
    -
    -
    -/**
    - * @override
    - * Native buttons don't support text selection.
    - */
    -goog.ui.NativeButtonRenderer.prototype.setAllowTextSelection =
    -    goog.nullFunction;
    -
    -
    -/**
    - * @override
    - * Native buttons natively support right-to-left rendering.
    - */
    -goog.ui.NativeButtonRenderer.prototype.setRightToLeft = goog.nullFunction;
    -
    -
    -/**
    - * @override
    - * Native buttons are always focusable as long as they are enabled.
    - */
    -goog.ui.NativeButtonRenderer.prototype.isFocusable = function(button) {
    -  return button.isEnabled();
    -};
    -
    -
    -/**
    - * @override
    - * Native buttons natively support keyboard focus.
    - */
    -goog.ui.NativeButtonRenderer.prototype.setFocusable = goog.nullFunction;
    -
    -
    -/**
    - * @override
    - * Native buttons also expose the DISABLED state in the HTML button's
    - * {@code disabled} attribute.
    - */
    -goog.ui.NativeButtonRenderer.prototype.setState = function(button, state,
    -    enable) {
    -  goog.ui.NativeButtonRenderer.superClass_.setState.call(this, button, state,
    -      enable);
    -  var element = button.getElement();
    -  if (element && state == goog.ui.Component.State.DISABLED) {
    -    element.disabled = enable;
    -  }
    -};
    -
    -
    -/**
    - * @override
    - * Native buttons store their value in the HTML button's {@code value}
    - * attribute.
    - */
    -goog.ui.NativeButtonRenderer.prototype.getValue = function(element) {
    -  // TODO(attila): Make this work on IE!  This never worked...
    -  // See http://www.fourmilab.ch/fourmilog/archives/2007-03/000824.html
    -  // for a description of the problem.
    -  return element.value;
    -};
    -
    -
    -/**
    - * @override
    - * Native buttons also expose their value in the HTML button's {@code value}
    - * attribute.
    - */
    -goog.ui.NativeButtonRenderer.prototype.setValue = function(element, value) {
    -  if (element) {
    -    // TODO(attila): Make this work on IE!  This never worked...
    -    // See http://www.fourmilab.ch/fourmilog/archives/2007-03/000824.html
    -    // for a description of the problem.
    -    element.value = value;
    -  }
    -};
    -
    -
    -/**
    - * @override
    - * Native buttons don't need ARIA states to support accessibility, so this is
    - * a no-op.
    - */
    -goog.ui.NativeButtonRenderer.prototype.updateAriaState = goog.nullFunction;
    -
    -
    -/**
    - * Sets up the button control such that it doesn't waste time adding
    - * functionality that is already natively supported by native browser
    - * buttons.
    - * @param {goog.ui.Control} button Button control to configure.
    - * @private
    - */
    -goog.ui.NativeButtonRenderer.prototype.setUpNativeButton_ = function(button) {
    -  button.setHandleMouseEvents(false);
    -  button.setAutoStates(goog.ui.Component.State.ALL, false);
    -  button.setSupportedState(goog.ui.Component.State.FOCUSED, false);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/nativebuttonrenderer_test.html b/src/database/third_party/closure-library/closure/goog/ui/nativebuttonrenderer_test.html
    deleted file mode 100644
    index 5344c6f598e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/nativebuttonrenderer_test.html
    +++ /dev/null
    @@ -1,27 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -Author: attila@google.com (Attila Bodis)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.NativeButtonRenderer
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.NativeButtonRendererTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="sandbox">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/nativebuttonrenderer_test.js b/src/database/third_party/closure-library/closure/goog/ui/nativebuttonrenderer_test.js
    deleted file mode 100644
    index 8b4ff07cdf9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/nativebuttonrenderer_test.js
    +++ /dev/null
    @@ -1,217 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.NativeButtonRendererTest');
    -goog.setTestOnly('goog.ui.NativeButtonRendererTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events');
    -goog.require('goog.testing.ExpectedFailures');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.ui.rendererasserts');
    -goog.require('goog.ui.Button');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.NativeButtonRenderer');
    -goog.require('goog.userAgent');
    -
    -var sandbox;
    -var renderer;
    -var expectedFailures;
    -var button;
    -
    -function setUpPage() {
    -  sandbox = goog.dom.getElement('sandbox');
    -  renderer = goog.ui.NativeButtonRenderer.getInstance();
    -  expectedFailures = new goog.testing.ExpectedFailures();
    -}
    -
    -function setUp() {
    -  button = new goog.ui.Button('Hello', renderer);
    -}
    -
    -function tearDown() {
    -  button.dispose();
    -  goog.dom.removeChildren(sandbox);
    -  expectedFailures.handleTearDown();
    -}
    -
    -function testConstructor() {
    -  assertNotNull('Renderer must not be null', renderer);
    -}
    -
    -function testGetAriaRole() {
    -  assertUndefined('ARIA role must be undefined', renderer.getAriaRole());
    -}
    -
    -function testCreateDom() {
    -  button.setTooltip('Hello, world!');
    -  button.setValue('foo');
    -  var element = renderer.createDom(button);
    -  assertNotNull('Element must not be null', element);
    -  assertEquals('Element must be a button', 'BUTTON', element.tagName);
    -  assertSameElements('Button element must have expected class name',
    -      ['goog-button'], goog.dom.classlist.get(element));
    -  assertFalse('Button element must be enabled', element.disabled);
    -  assertEquals('Button element must have expected title', 'Hello, world!',
    -      element.title);
    -  // Expected to fail on IE.
    -  expectedFailures.expectFailureFor(goog.userAgent.IE);
    -  try {
    -    // See http://www.fourmilab.ch/fourmilog/archives/2007-03/000824.html
    -    // for a description of the problem.
    -    assertEquals('Button element must have expected value', 'foo',
    -        element.value);
    -    assertEquals('Button element must have expected contents', 'Hello',
    -        element.innerHTML);
    -  } catch (e) {
    -    expectedFailures.handleException(e);
    -  }
    -  assertFalse('Button must not handle its own mouse events',
    -      button.isHandleMouseEvents());
    -  assertFalse('Button must not support the custom FOCUSED state',
    -      button.isSupportedState(goog.ui.Component.State.FOCUSED));
    -}
    -
    -function testCanDecorate() {
    -  sandbox.innerHTML =
    -      '<button id="buttonElement">Button</button>\n' +
    -      '<input id="inputButton" type="button" value="Input Button">\n' +
    -      '<input id="inputSubmit" type="submit" value="Input Submit">\n' +
    -      '<input id="inputReset" type="reset" value="Input Reset">\n' +
    -      '<input id="inputText" type="text" size="10">\n' +
    -      '<div id="divButton" class="goog-button">Hello</div>';
    -
    -  assertTrue('Must be able to decorate <button>',
    -      renderer.canDecorate(goog.dom.getElement('buttonElement')));
    -  assertTrue('Must be able to decorate <input type="button">',
    -      renderer.canDecorate(goog.dom.getElement('inputButton')));
    -  assertTrue('Must be able to decorate <input type="submit">',
    -      renderer.canDecorate(goog.dom.getElement('inputSubmit')));
    -  assertTrue('Must be able to decorate <input type="reset">',
    -      renderer.canDecorate(goog.dom.getElement('inputReset')));
    -  assertFalse('Must not be able to decorate <input type="text">',
    -      renderer.canDecorate(goog.dom.getElement('inputText')));
    -  assertFalse('Must not be able to decorate <div class="goog-button">',
    -      renderer.canDecorate(goog.dom.getElement('divButton')));
    -}
    -
    -function testDecorate() {
    -  sandbox.innerHTML =
    -      '<button id="foo" title="Hello!" value="bar">Foo Button</button>\n' +
    -      '<button id="disabledButton" value="bah" disabled="disabled">Disabled' +
    -      '</button>';
    -
    -  var element = renderer.decorate(button, goog.dom.getElement('foo'));
    -  assertEquals('Decorated element must be as expected',
    -      goog.dom.getElement('foo'), element);
    -  assertEquals('Decorated button title must have expected value', 'Hello!',
    -      button.getTooltip());
    -  // Expected to fail on IE.
    -  expectedFailures.expectFailureFor(goog.userAgent.IE);
    -  try {
    -    // See http://www.fourmilab.ch/fourmilog/archives/2007-03/000824.html
    -    // for a description of the problem.
    -    assertEquals('Decorated button value must have expected value', 'bar',
    -        button.getValue());
    -  } catch (e) {
    -    expectedFailures.handleException(e);
    -  }
    -  assertFalse('Button must not handle its own mouse events',
    -      button.isHandleMouseEvents());
    -  assertFalse('Button must not support the custom FOCUSED state',
    -      button.isSupportedState(goog.ui.Component.State.FOCUSED));
    -
    -  element = renderer.decorate(button,
    -      goog.dom.getElement('disabledButton'));
    -  assertFalse('Decorated button must be disabled', button.isEnabled());
    -  assertSameElements('Decorated button must have expected class names',
    -      ['goog-button', 'goog-button-disabled'],
    -      goog.dom.classlist.get(element));
    -  // Expected to fail on IE.
    -  expectedFailures.expectFailureFor(goog.userAgent.IE);
    -  try {
    -    // See http://www.fourmilab.ch/fourmilog/archives/2007-03/000824.html
    -    // for a description of the problem.
    -    assertEquals('Decorated button value must have expected value', 'bah',
    -        button.getValue());
    -  } catch (e) {
    -    expectedFailures.handleException(e);
    -  }
    -  assertFalse('Button must not handle its own mouse events',
    -      button.isHandleMouseEvents());
    -  assertFalse('Button must not support the custom FOCUSED state',
    -      button.isSupportedState(goog.ui.Component.State.FOCUSED));
    -}
    -
    -function testInitializeDom() {
    -  var dispatchedActionCount = 0;
    -  var handleAction = function() {
    -    dispatchedActionCount++;
    -  };
    -  goog.events.listen(button, goog.ui.Component.EventType.ACTION,
    -      handleAction);
    -
    -  button.render(sandbox);
    -  goog.testing.events.fireClickSequence(button.getElement());
    -  assertEquals('Button must have dispatched ACTION on click', 1,
    -      dispatchedActionCount);
    -
    -  goog.events.unlisten(button, goog.ui.Component.EventType.ACTION,
    -      handleAction);
    -}
    -
    -function testIsFocusable() {
    -  assertTrue('Enabled button must be focusable',
    -      renderer.isFocusable(button));
    -  button.setEnabled(false);
    -  assertFalse('Disabled button must not be focusable',
    -      renderer.isFocusable(button));
    -}
    -
    -function testSetState() {
    -  button.render(sandbox);
    -  assertFalse('Button element must not be disabled',
    -      button.getElement().disabled);
    -  renderer.setState(button, goog.ui.Component.State.DISABLED, true);
    -  assertTrue('Button element must be disabled',
    -      button.getElement().disabled);
    -}
    -
    -function testGetValue() {
    -  sandbox.innerHTML = '<button id="foo" value="blah">Hello</button>';
    -  // Expected to fail on IE.
    -  expectedFailures.expectFailureFor(goog.userAgent.IE);
    -  try {
    -    // See http://www.fourmilab.ch/fourmilog/archives/2007-03/000824.html
    -    // for a description of the problem.
    -    assertEquals('Value must be as expected', 'blah',
    -        renderer.getValue(goog.dom.getElement('foo')));
    -  } catch (e) {
    -    expectedFailures.handleException(e);
    -  }
    -}
    -
    -function testSetValue() {
    -  button.render(sandbox);
    -  renderer.setValue(button.getElement(), 'What?');
    -  assertEquals('Button must have expected value', 'What?',
    -      renderer.getValue(button.getElement()));
    -}
    -
    -function testDoesntCallGetCssClassInConstructor() {
    -  goog.testing.ui.rendererasserts.
    -      assertNoGetCssClassCallsInConstructor(goog.ui.NativeButtonRenderer);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/option.js b/src/database/third_party/closure-library/closure/goog/ui/option.js
    deleted file mode 100644
    index 3b7f001735f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/option.js
    +++ /dev/null
    @@ -1,68 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A menu item class that supports selection state.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.Option');
    -
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.MenuItem');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * Class representing a menu option.  This is just a convenience class that
    - * extends {@link goog.ui.MenuItem} by making it selectable.
    - *
    - * @param {goog.ui.ControlContent} content Text caption or DOM structure to
    - *     display as the content of the item (use to add icons or styling to
    - *     menus).
    - * @param {*=} opt_model Data/model associated with the menu item.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper used for
    - *     document interactions.
    - * @constructor
    - * @extends {goog.ui.MenuItem}
    - */
    -goog.ui.Option = function(content, opt_model, opt_domHelper) {
    -  goog.ui.MenuItem.call(this, content, opt_model, opt_domHelper);
    -  this.setSelectable(true);
    -};
    -goog.inherits(goog.ui.Option, goog.ui.MenuItem);
    -
    -
    -/**
    - * Performs the appropriate action when the option is activated by the user.
    - * Overrides the superclass implementation by not changing the selection state
    - * of the option and not dispatching any SELECTED events, for backwards
    - * compatibility with existing uses of this class.
    - * @param {goog.events.Event} e Mouse or key event that triggered the action.
    - * @return {boolean} True if the action was allowed to proceed, false otherwise.
    - * @override
    - */
    -goog.ui.Option.prototype.performActionInternal = function(e) {
    -  return this.dispatchEvent(goog.ui.Component.EventType.ACTION);
    -};
    -
    -
    -// Register a decorator factory function for goog.ui.Options.
    -goog.ui.registry.setDecoratorByClassName(
    -    goog.getCssName('goog-option'), function() {
    -      // Option defaults to using MenuItemRenderer.
    -      return new goog.ui.Option(null);
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/palette.js b/src/database/third_party/closure-library/closure/goog/ui/palette.js
    deleted file mode 100644
    index 8aeed61f0d5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/palette.js
    +++ /dev/null
    @@ -1,604 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A palette control.  A palette is a grid that the user can
    - * highlight or select via the keyboard or the mouse.
    - *
    - * @author attila@google.com (Attila Bodis)
    - * @see ../demos/palette.html
    - */
    -
    -goog.provide('goog.ui.Palette');
    -
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.math.Size');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.Control');
    -goog.require('goog.ui.PaletteRenderer');
    -goog.require('goog.ui.SelectionModel');
    -
    -
    -
    -/**
    - * A palette is a grid of DOM nodes that the user can highlight or select via
    - * the keyboard or the mouse.  The selection state of the palette is controlled
    - * an ACTION event.  Event listeners may retrieve the selected item using the
    - * {@link #getSelectedItem} or {@link #getSelectedIndex} method.
    - *
    - * Use this class as the base for components like color palettes or emoticon
    - * pickers.  Use {@link #setContent} to set/change the items in the palette
    - * after construction.  See palette.html demo for example usage.
    - *
    - * @param {Array<Node>} items Array of DOM nodes to be displayed as items
    - *     in the palette grid (limited to one per cell).
    - * @param {goog.ui.PaletteRenderer=} opt_renderer Renderer used to render or
    - *     decorate the palette; defaults to {@link goog.ui.PaletteRenderer}.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @constructor
    - * @extends {goog.ui.Control}
    - */
    -goog.ui.Palette = function(items, opt_renderer, opt_domHelper) {
    -  goog.ui.Palette.base(this, 'constructor', items,
    -      opt_renderer || goog.ui.PaletteRenderer.getInstance(), opt_domHelper);
    -  this.setAutoStates(goog.ui.Component.State.CHECKED |
    -      goog.ui.Component.State.SELECTED | goog.ui.Component.State.OPENED, false);
    -
    -  /**
    -   * A fake component for dispatching events on palette cell changes.
    -   * @type {!goog.ui.Palette.CurrentCell_}
    -   * @private
    -   */
    -  this.currentCellControl_ = new goog.ui.Palette.CurrentCell_();
    -  this.currentCellControl_.setParentEventTarget(this);
    -
    -  /**
    -   * @private {number} The last highlighted index, or -1 if it never had one.
    -   */
    -  this.lastHighlightedIndex_ = -1;
    -};
    -goog.inherits(goog.ui.Palette, goog.ui.Control);
    -goog.tagUnsealableClass(goog.ui.Palette);
    -
    -
    -/**
    - * Events fired by the palette object
    - * @enum {string}
    - */
    -goog.ui.Palette.EventType = {
    -  AFTER_HIGHLIGHT: goog.events.getUniqueId('afterhighlight')
    -};
    -
    -
    -/**
    - * Palette dimensions (columns x rows).  If the number of rows is undefined,
    - * it is calculated on first use.
    - * @type {goog.math.Size}
    - * @private
    - */
    -goog.ui.Palette.prototype.size_ = null;
    -
    -
    -/**
    - * Index of the currently highlighted item (-1 if none).
    - * @type {number}
    - * @private
    - */
    -goog.ui.Palette.prototype.highlightedIndex_ = -1;
    -
    -
    -/**
    - * Selection model controlling the palette's selection state.
    - * @type {goog.ui.SelectionModel}
    - * @private
    - */
    -goog.ui.Palette.prototype.selectionModel_ = null;
    -
    -
    -// goog.ui.Component / goog.ui.Control implementation.
    -
    -
    -/** @override */
    -goog.ui.Palette.prototype.disposeInternal = function() {
    -  goog.ui.Palette.superClass_.disposeInternal.call(this);
    -
    -  if (this.selectionModel_) {
    -    this.selectionModel_.dispose();
    -    this.selectionModel_ = null;
    -  }
    -
    -  this.size_ = null;
    -
    -  this.currentCellControl_.dispose();
    -};
    -
    -
    -/**
    - * Overrides {@link goog.ui.Control#setContentInternal} by also updating the
    - * grid size and the selection model.  Considered protected.
    - * @param {goog.ui.ControlContent} content Array of DOM nodes to be displayed
    - *     as items in the palette grid (one item per cell).
    - * @protected
    - * @override
    - */
    -goog.ui.Palette.prototype.setContentInternal = function(content) {
    -  var items = /** @type {Array<Node>} */ (content);
    -  goog.ui.Palette.superClass_.setContentInternal.call(this, items);
    -
    -  // Adjust the palette size.
    -  this.adjustSize_();
    -
    -  // Add the items to the selection model, replacing previous items (if any).
    -  if (this.selectionModel_) {
    -    // We already have a selection model; just replace the items.
    -    this.selectionModel_.clear();
    -    this.selectionModel_.addItems(items);
    -  } else {
    -    // Create a selection model, initialize the items, and hook up handlers.
    -    this.selectionModel_ = new goog.ui.SelectionModel(items);
    -    this.selectionModel_.setSelectionHandler(goog.bind(this.selectItem_,
    -        this));
    -    this.getHandler().listen(this.selectionModel_,
    -        goog.events.EventType.SELECT, this.handleSelectionChange);
    -  }
    -
    -  // In all cases, clear the highlight.
    -  this.highlightedIndex_ = -1;
    -};
    -
    -
    -/**
    - * Overrides {@link goog.ui.Control#getCaption} to return the empty string,
    - * since palettes don't have text captions.
    - * @return {string} The empty string.
    - * @override
    - */
    -goog.ui.Palette.prototype.getCaption = function() {
    -  return '';
    -};
    -
    -
    -/**
    - * Overrides {@link goog.ui.Control#setCaption} to be a no-op, since palettes
    - * don't have text captions.
    - * @param {string} caption Ignored.
    - * @override
    - */
    -goog.ui.Palette.prototype.setCaption = function(caption) {
    -  // Do nothing.
    -};
    -
    -
    -// Palette event handling.
    -
    -
    -/**
    - * Handles mouseover events.  Overrides {@link goog.ui.Control#handleMouseOver}
    - * by determining which palette item (if any) was moused over, highlighting it,
    - * and un-highlighting any previously-highlighted item.
    - * @param {goog.events.BrowserEvent} e Mouse event to handle.
    - * @override
    - */
    -goog.ui.Palette.prototype.handleMouseOver = function(e) {
    -  goog.ui.Palette.superClass_.handleMouseOver.call(this, e);
    -
    -  var item = this.getRenderer().getContainingItem(this, e.target);
    -  if (item && e.relatedTarget && goog.dom.contains(item, e.relatedTarget)) {
    -    // Ignore internal mouse moves.
    -    return;
    -  }
    -
    -  if (item != this.getHighlightedItem()) {
    -    this.setHighlightedItem(item);
    -  }
    -};
    -
    -
    -/**
    - * Handles mousedown events.  Overrides {@link goog.ui.Control#handleMouseDown}
    - * by ensuring that the item on which the user moused down is highlighted.
    - * @param {goog.events.Event} e Mouse event to handle.
    - * @override
    - */
    -goog.ui.Palette.prototype.handleMouseDown = function(e) {
    -  goog.ui.Palette.superClass_.handleMouseDown.call(this, e);
    -
    -  if (this.isActive()) {
    -    // Make sure we move the highlight to the cell on which the user moused
    -    // down.
    -    var item = this.getRenderer().getContainingItem(this, e.target);
    -    if (item != this.getHighlightedItem()) {
    -      this.setHighlightedItem(item);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Selects the currently highlighted palette item (triggered by mouseup or by
    - * keyboard action).  Overrides {@link goog.ui.Control#performActionInternal}
    - * by selecting the highlighted item and dispatching an ACTION event.
    - * @param {goog.events.Event} e Mouse or key event that triggered the action.
    - * @return {boolean} True if the action was allowed to proceed, false otherwise.
    - * @override
    - */
    -goog.ui.Palette.prototype.performActionInternal = function(e) {
    -  var item = this.getHighlightedItem();
    -  if (item) {
    -    this.setSelectedItem(item);
    -    return goog.ui.Palette.base(this, 'performActionInternal', e);
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Handles keyboard events dispatched while the palette has focus.  Moves the
    - * highlight on arrow keys, and selects the highlighted item on Enter or Space.
    - * Returns true if the event was handled, false otherwise.  In particular, if
    - * the user attempts to navigate out of the grid, the highlight isn't changed,
    - * and this method returns false; it is then up to the parent component to
    - * handle the event (e.g. by wrapping the highlight around).  Overrides {@link
    - * goog.ui.Control#handleKeyEvent}.
    - * @param {goog.events.KeyEvent} e Key event to handle.
    - * @return {boolean} True iff the key event was handled by the component.
    - * @override
    - */
    -goog.ui.Palette.prototype.handleKeyEvent = function(e) {
    -  var items = this.getContent();
    -  var numItems = items ? items.length : 0;
    -  var numColumns = this.size_.width;
    -
    -  // If the component is disabled or the palette is empty, bail.
    -  if (numItems == 0 || !this.isEnabled()) {
    -    return false;
    -  }
    -
    -  // User hit ENTER or SPACE; trigger action.
    -  if (e.keyCode == goog.events.KeyCodes.ENTER ||
    -      e.keyCode == goog.events.KeyCodes.SPACE) {
    -    return this.performActionInternal(e);
    -  }
    -
    -  // User hit HOME or END; move highlight.
    -  if (e.keyCode == goog.events.KeyCodes.HOME) {
    -    this.setHighlightedIndex(0);
    -    return true;
    -  } else if (e.keyCode == goog.events.KeyCodes.END) {
    -    this.setHighlightedIndex(numItems - 1);
    -    return true;
    -  }
    -
    -  // If nothing is highlighted, start from the selected index.  If nothing is
    -  // selected either, highlightedIndex is -1.
    -  var highlightedIndex = this.highlightedIndex_ < 0 ? this.getSelectedIndex() :
    -      this.highlightedIndex_;
    -
    -  switch (e.keyCode) {
    -    case goog.events.KeyCodes.LEFT:
    -      // If the highlighted index is uninitialized, or is at the beginning, move
    -      // it to the end.
    -      if (highlightedIndex == -1 ||
    -          highlightedIndex == 0) {
    -        highlightedIndex = numItems;
    -      }
    -      this.setHighlightedIndex(highlightedIndex - 1);
    -      e.preventDefault();
    -      return true;
    -      break;
    -
    -    case goog.events.KeyCodes.RIGHT:
    -      // If the highlighted index at the end, move it to the beginning.
    -      if (highlightedIndex == numItems - 1) {
    -        highlightedIndex = -1;
    -      }
    -      this.setHighlightedIndex(highlightedIndex + 1);
    -      e.preventDefault();
    -      return true;
    -      break;
    -
    -    case goog.events.KeyCodes.UP:
    -      if (highlightedIndex == -1) {
    -        highlightedIndex = numItems + numColumns - 1;
    -      }
    -      if (highlightedIndex >= numColumns) {
    -        this.setHighlightedIndex(highlightedIndex - numColumns);
    -        e.preventDefault();
    -        return true;
    -      }
    -      break;
    -
    -    case goog.events.KeyCodes.DOWN:
    -      if (highlightedIndex == -1) {
    -        highlightedIndex = -numColumns;
    -      }
    -      if (highlightedIndex < numItems - numColumns) {
    -        this.setHighlightedIndex(highlightedIndex + numColumns);
    -        e.preventDefault();
    -        return true;
    -      }
    -      break;
    -  }
    -
    -  return false;
    -};
    -
    -
    -/**
    - * Handles selection change events dispatched by the selection model.
    - * @param {goog.events.Event} e Selection event to handle.
    - */
    -goog.ui.Palette.prototype.handleSelectionChange = function(e) {
    -  // No-op in the base class.
    -};
    -
    -
    -// Palette management.
    -
    -
    -/**
    - * Returns the size of the palette grid.
    - * @return {goog.math.Size} Palette size (columns x rows).
    - */
    -goog.ui.Palette.prototype.getSize = function() {
    -  return this.size_;
    -};
    -
    -
    -/**
    - * Sets the size of the palette grid to the given size.  Callers can either
    - * pass a single {@link goog.math.Size} or a pair of numbers (first the number
    - * of columns, then the number of rows) to this method.  In both cases, the
    - * number of rows is optional and will be calculated automatically if needed.
    - * It is an error to attempt to change the size of the palette after it has
    - * been rendered.
    - * @param {goog.math.Size|number} size Either a size object or the number of
    - *     columns.
    - * @param {number=} opt_rows The number of rows (optional).
    - */
    -goog.ui.Palette.prototype.setSize = function(size, opt_rows) {
    -  if (this.getElement()) {
    -    throw Error(goog.ui.Component.Error.ALREADY_RENDERED);
    -  }
    -
    -  this.size_ = goog.isNumber(size) ?
    -      new goog.math.Size(size, /** @type {number} */ (opt_rows)) : size;
    -
    -  // Adjust size, if needed.
    -  this.adjustSize_();
    -};
    -
    -
    -/**
    - * Returns the 0-based index of the currently highlighted palette item, or -1
    - * if no item is highlighted.
    - * @return {number} Index of the highlighted item (-1 if none).
    - */
    -goog.ui.Palette.prototype.getHighlightedIndex = function() {
    -  return this.highlightedIndex_;
    -};
    -
    -
    -/**
    - * Returns the currently highlighted palette item, or null if no item is
    - * highlighted.
    - * @return {Node} The highlighted item (undefined if none).
    - */
    -goog.ui.Palette.prototype.getHighlightedItem = function() {
    -  var items = this.getContent();
    -  return items && items[this.highlightedIndex_];
    -};
    -
    -
    -/**
    - * @return {Element} The highlighted cell.
    - * @private
    - */
    -goog.ui.Palette.prototype.getHighlightedCellElement_ = function() {
    -  return this.getRenderer().getCellForItem(this.getHighlightedItem());
    -};
    -
    -
    -/**
    - * Highlights the item at the given 0-based index, or removes the highlight
    - * if the argument is -1 or out of range.  Any previously-highlighted item
    - * will be un-highlighted.
    - * @param {number} index 0-based index of the item to highlight.
    - */
    -goog.ui.Palette.prototype.setHighlightedIndex = function(index) {
    -  if (index != this.highlightedIndex_) {
    -    this.highlightIndex_(this.highlightedIndex_, false);
    -    this.lastHighlightedIndex_ = this.highlightedIndex_;
    -    this.highlightedIndex_ = index;
    -    this.highlightIndex_(index, true);
    -    this.dispatchEvent(goog.ui.Palette.EventType.AFTER_HIGHLIGHT);
    -  }
    -};
    -
    -
    -/**
    - * Highlights the given item, or removes the highlight if the argument is null
    - * or invalid.  Any previously-highlighted item will be un-highlighted.
    - * @param {Node|undefined} item Item to highlight.
    - */
    -goog.ui.Palette.prototype.setHighlightedItem = function(item) {
    -  var items = /** @type {Array<Node>} */ (this.getContent());
    -  this.setHighlightedIndex(items ? goog.array.indexOf(items, item) : -1);
    -};
    -
    -
    -/**
    - * Returns the 0-based index of the currently selected palette item, or -1
    - * if no item is selected.
    - * @return {number} Index of the selected item (-1 if none).
    - */
    -goog.ui.Palette.prototype.getSelectedIndex = function() {
    -  return this.selectionModel_ ? this.selectionModel_.getSelectedIndex() : -1;
    -};
    -
    -
    -/**
    - * Returns the currently selected palette item, or null if no item is selected.
    - * @return {Node} The selected item (null if none).
    - */
    -goog.ui.Palette.prototype.getSelectedItem = function() {
    -  return this.selectionModel_ ?
    -      /** @type {Node} */ (this.selectionModel_.getSelectedItem()) : null;
    -};
    -
    -
    -/**
    - * Selects the item at the given 0-based index, or clears the selection
    - * if the argument is -1 or out of range.  Any previously-selected item
    - * will be deselected.
    - * @param {number} index 0-based index of the item to select.
    - */
    -goog.ui.Palette.prototype.setSelectedIndex = function(index) {
    -  if (this.selectionModel_) {
    -    this.selectionModel_.setSelectedIndex(index);
    -  }
    -};
    -
    -
    -/**
    - * Selects the given item, or clears the selection if the argument is null or
    - * invalid.  Any previously-selected item will be deselected.
    - * @param {Node} item Item to select.
    - */
    -goog.ui.Palette.prototype.setSelectedItem = function(item) {
    -  if (this.selectionModel_) {
    -    this.selectionModel_.setSelectedItem(item);
    -  }
    -};
    -
    -
    -/**
    - * Private helper; highlights or un-highlights the item at the given index
    - * based on the value of the Boolean argument.  This implementation simply
    - * applies highlight styling to the cell containing the item to be highighted.
    - * Does nothing if the palette hasn't been rendered yet.
    - * @param {number} index 0-based index of item to highlight or un-highlight.
    - * @param {boolean} highlight If true, the item is highlighted; otherwise it
    - *     is un-highlighted.
    - * @private
    - */
    -goog.ui.Palette.prototype.highlightIndex_ = function(index, highlight) {
    -  if (this.getElement()) {
    -    var items = this.getContent();
    -    if (items && index >= 0 && index < items.length) {
    -      var cellEl = this.getHighlightedCellElement_();
    -      if (this.currentCellControl_.getElement() != cellEl) {
    -        this.currentCellControl_.setElementInternal(cellEl);
    -      }
    -      if (this.currentCellControl_.tryHighlight(highlight)) {
    -        this.getRenderer().highlightCell(this, items[index], highlight);
    -      }
    -    }
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.Palette.prototype.setHighlighted = function(highlight) {
    -  if (highlight && this.highlightedIndex_ == -1) {
    -    // If there was a last highlighted index, use that. Otherwise, highlight the
    -    // first cell.
    -    this.setHighlightedIndex(
    -        this.lastHighlightedIndex_ > -1 ?
    -        this.lastHighlightedIndex_ :
    -        0);
    -  } else if (!highlight) {
    -    this.setHighlightedIndex(-1);
    -  }
    -  // The highlight event should be fired once the component has updated its own
    -  // state.
    -  goog.ui.Palette.base(this, 'setHighlighted', highlight);
    -};
    -
    -
    -/**
    - * Private helper; selects or deselects the given item based on the value of
    - * the Boolean argument.  This implementation simply applies selection styling
    - * to the cell containing the item to be selected.  Does nothing if the palette
    - * hasn't been rendered yet.
    - * @param {Node} item Item to select or deselect.
    - * @param {boolean} select If true, the item is selected; otherwise it is
    - *     deselected.
    - * @private
    - */
    -goog.ui.Palette.prototype.selectItem_ = function(item, select) {
    -  if (this.getElement()) {
    -    this.getRenderer().selectCell(this, item, select);
    -  }
    -};
    -
    -
    -/**
    - * Calculates and updates the size of the palette based on any preset values
    - * and the number of palette items.  If there is no preset size, sets the
    - * palette size to the smallest square big enough to contain all items.  If
    - * there is a preset number of columns, increases the number of rows to hold
    - * all items if needed.  (If there are too many rows, does nothing.)
    - * @private
    - */
    -goog.ui.Palette.prototype.adjustSize_ = function() {
    -  var items = this.getContent();
    -  if (items) {
    -    if (this.size_ && this.size_.width) {
    -      // There is already a size set; honor the number of columns (if >0), but
    -      // increase the number of rows if needed.
    -      var minRows = Math.ceil(items.length / this.size_.width);
    -      if (!goog.isNumber(this.size_.height) || this.size_.height < minRows) {
    -        this.size_.height = minRows;
    -      }
    -    } else {
    -      // No size has been set; size the grid to the smallest square big enough
    -      // to hold all items (hey, why not?).
    -      var length = Math.ceil(Math.sqrt(items.length));
    -      this.size_ = new goog.math.Size(length, length);
    -    }
    -  } else {
    -    // No items; set size to 0x0.
    -    this.size_ = new goog.math.Size(0, 0);
    -  }
    -};
    -
    -
    -
    -/**
    - * A component to represent the currently highlighted cell.
    - * @constructor
    - * @extends {goog.ui.Control}
    - * @private
    - */
    -goog.ui.Palette.CurrentCell_ = function() {
    -  goog.ui.Palette.CurrentCell_.base(this, 'constructor', null);
    -  this.setDispatchTransitionEvents(goog.ui.Component.State.HOVER, true);
    -};
    -goog.inherits(goog.ui.Palette.CurrentCell_, goog.ui.Control);
    -
    -
    -/**
    - * @param {boolean} highlight Whether to highlight or unhighlight the component.
    - * @return {boolean} Whether it was successful.
    - */
    -goog.ui.Palette.CurrentCell_.prototype.tryHighlight = function(highlight) {
    -  this.setHighlighted(highlight);
    -  return this.isHighlighted() == highlight;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/palette_test.html b/src/database/third_party/closure-library/closure/goog/ui/palette_test.html
    deleted file mode 100644
    index 799cd8fd157..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/palette_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.Palette
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.PaletteTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="sandbox">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/palette_test.js b/src/database/third_party/closure-library/closure/goog/ui/palette_test.js
    deleted file mode 100644
    index 889be2cbf01..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/palette_test.js
    +++ /dev/null
    @@ -1,188 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.PaletteTest');
    -goog.setTestOnly('goog.ui.PaletteTest');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.events.KeyEvent');
    -goog.require('goog.testing.events.Event');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.Container');
    -goog.require('goog.ui.Palette');
    -
    -var palette;
    -var nodes;
    -
    -function setUp() {
    -  nodes = [];
    -  for (var i = 0; i < 23; i++) {
    -    var node = goog.dom.createTextNode('node[' + i + ']');
    -    nodes.push(node);
    -  }
    -  palette = new goog.ui.Palette(nodes);
    -}
    -
    -function tearDown() {
    -  palette.dispose();
    -  document.getElementById('sandbox').innerHTML = '';
    -}
    -
    -function testAfterHighlightListener() {
    -  palette.setHighlightedIndex(0);
    -  var handler = new goog.testing.recordFunction();
    -  goog.events.listen(palette,
    -      goog.ui.Palette.EventType.AFTER_HIGHLIGHT, handler);
    -  palette.setHighlightedIndex(2);
    -  assertEquals(1, handler.getCallCount());
    -  palette.setHighlightedIndex(-1);
    -  assertEquals(2, handler.getCallCount());
    -}
    -
    -function testHighlightItemUpdatesParentA11yActiveDescendant() {
    -  var container = new goog.ui.Container();
    -  container.render(document.getElementById('sandbox'));
    -  container.addChild(palette, true);
    -
    -  palette.setHighlightedItem(nodes[0]);
    -  assertEquals('Node 0 cell should be the container\'s active descendant',
    -      palette.getRenderer().getCellForItem(nodes[0]),
    -      goog.a11y.aria.getActiveDescendant(container.getElement()));
    -
    -  palette.setHighlightedItem(nodes[1]);
    -  assertEquals('Node 1 cell should be the container\'s active descendant',
    -      palette.getRenderer().getCellForItem(nodes[1]),
    -      goog.a11y.aria.getActiveDescendant(container.getElement()));
    -
    -  palette.setHighlightedItem();
    -  assertNull('Container should have no active descendant',
    -      goog.a11y.aria.getActiveDescendant(container.getElement()));
    -
    -  container.dispose();
    -}
    -
    -function testHighlightCellEvents() {
    -  var container = new goog.ui.Container();
    -  container.render(document.getElementById('sandbox'));
    -  container.addChild(palette, true);
    -  var renderer = palette.getRenderer();
    -
    -  var events = [];
    -  var targetElements = [];
    -  var handleEvent = function(e) {
    -    events.push(e);
    -    targetElements.push(e.target.getElement());
    -  };
    -  palette.getHandler().listen(palette, [
    -    this, goog.ui.Component.EventType.HIGHLIGHT,
    -    this, goog.ui.Component.EventType.UNHIGHLIGHT
    -  ], handleEvent);
    -
    -  // Test highlight events on first selection
    -  palette.setHighlightedItem(nodes[0]);
    -  assertEquals('Should have fired 1 event', 1, events.length);
    -  assertEquals('HIGHLIGHT event should be fired',
    -      goog.ui.Component.EventType.HIGHLIGHT, events[0].type);
    -  assertEquals('Event should be fired for node[0] cell',
    -      renderer.getCellForItem(nodes[0]), targetElements[0]);
    -
    -  events = [];
    -  targetElements = [];
    -
    -  // Only fire highlight events when there is a selection change
    -  palette.setHighlightedItem(nodes[0]);
    -  assertEquals('Should have fired 0 events', 0, events.length);
    -
    -  // Test highlight events on cell change
    -  palette.setHighlightedItem(nodes[1]);
    -  assertEquals('Should have fired 2 events', 2, events.length);
    -  var unhighlightEvent = events.shift();
    -  var highlightEvent = events.shift();
    -  assertEquals('UNHIGHLIGHT should be fired first',
    -      goog.ui.Component.EventType.UNHIGHLIGHT, unhighlightEvent.type);
    -  assertEquals('UNHIGHLIGHT should be fired for node[0] cell',
    -      renderer.getCellForItem(nodes[0]), targetElements[0]);
    -  assertEquals('HIGHLIGHT should be fired after UNHIGHLIGHT',
    -      goog.ui.Component.EventType.HIGHLIGHT, highlightEvent.type);
    -  assertEquals('HIGHLIGHT should be fired for node[1] cell',
    -      renderer.getCellForItem(nodes[1]), targetElements[1]);
    -
    -  events = [];
    -  targetElements = [];
    -
    -  // Test highlight events when a cell is unselected
    -  palette.setHighlightedItem();
    -
    -  assertEquals('Should have fired 1 event', 1, events.length);
    -  assertEquals('UNHIGHLIGHT event should be fired',
    -      goog.ui.Component.EventType.UNHIGHLIGHT, events[0].type);
    -  assertEquals('Event should be fired for node[1] cell',
    -      renderer.getCellForItem(nodes[1]), targetElements[0]);
    -}
    -
    -function testHandleKeyEventLoops() {
    -  palette.setHighlightedIndex(0);
    -  var createKeyEvent = function(keyCode) {
    -    return new goog.events.KeyEvent(keyCode,
    -        0 /* charCode */,
    -        false /* repeat */,
    -        new goog.testing.events.Event(goog.events.EventType.KEYDOWN));
    -  };
    -  palette.handleKeyEvent(createKeyEvent(goog.events.KeyCodes.LEFT));
    -  assertEquals(nodes.length - 1, palette.getHighlightedIndex());
    -
    -  palette.handleKeyEvent(createKeyEvent(goog.events.KeyCodes.RIGHT));
    -  assertEquals(0, palette.getHighlightedIndex());
    -}
    -
    -function testSetHighlight() {
    -  assertEquals(-1, palette.getHighlightedIndex());
    -  palette.setHighlighted(true);
    -  assertEquals(0, palette.getHighlightedIndex());
    -
    -  palette.setHighlightedIndex(3);
    -  palette.setHighlighted(false);
    -  assertEquals(-1, palette.getHighlightedIndex());
    -  palette.setHighlighted(true);
    -  assertEquals(3, palette.getHighlightedIndex());
    -
    -  palette.setHighlighted(false);
    -  palette.setHighlightedIndex(5);
    -  palette.setHighlighted(true);
    -  assertEquals(5, palette.getHighlightedIndex());
    -  palette.setHighlighted(true);
    -  assertEquals(5, palette.getHighlightedIndex());
    -}
    -
    -function testSetAriaLabel() {
    -  assertNull('Palette must not have aria label by default',
    -      palette.getAriaLabel());
    -  palette.setAriaLabel('My Palette');
    -  palette.render();
    -  var element = palette.getElementStrict();
    -  assertNotNull('Element must not be null', element);
    -  assertEquals('Palette element must have expected aria-label', 'My Palette',
    -      element.getAttribute('aria-label'));
    -  assertEquals('Palette element must have expected aria role', 'grid',
    -      element.getAttribute('role'));
    -  palette.setAriaLabel('My new Palette');
    -  assertEquals('Palette element must have updated aria-label', 'My new Palette',
    -      element.getAttribute('aria-label'));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/paletterenderer.js b/src/database/third_party/closure-library/closure/goog/ui/paletterenderer.js
    deleted file mode 100644
    index f1b2aa5c2eb..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/paletterenderer.js
    +++ /dev/null
    @@ -1,383 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Renderer for {@link goog.ui.Palette}s.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.PaletteRenderer');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.NodeIterator');
    -goog.require('goog.dom.NodeType');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.iter');
    -goog.require('goog.style');
    -goog.require('goog.ui.ControlRenderer');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Default renderer for {@link goog.ui.Palette}s.  Renders the palette as an
    - * HTML table wrapped in a DIV, with one palette item per cell:
    - *
    - *    <div class="goog-palette">
    - *      <table class="goog-palette-table">
    - *        <tbody class="goog-palette-body">
    - *          <tr class="goog-palette-row">
    - *            <td class="goog-palette-cell">...Item 0...</td>
    - *            <td class="goog-palette-cell">...Item 1...</td>
    - *            ...
    - *          </tr>
    - *          <tr class="goog-palette-row">
    - *            ...
    - *          </tr>
    - *        </tbody>
    - *      </table>
    - *    </div>
    - *
    - * @constructor
    - * @extends {goog.ui.ControlRenderer}
    - */
    -goog.ui.PaletteRenderer = function() {
    -  goog.ui.ControlRenderer.call(this);
    -};
    -goog.inherits(goog.ui.PaletteRenderer, goog.ui.ControlRenderer);
    -goog.addSingletonGetter(goog.ui.PaletteRenderer);
    -
    -
    -/**
    - * Globally unique ID sequence for cells rendered by this renderer class.
    - * @type {number}
    - * @private
    - */
    -goog.ui.PaletteRenderer.cellId_ = 0;
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.PaletteRenderer.CSS_CLASS = goog.getCssName('goog-palette');
    -
    -
    -/**
    - * Returns the palette items arranged in a table wrapped in a DIV, with the
    - * renderer's own CSS class and additional state-specific classes applied to
    - * it.
    - * @param {goog.ui.Control} palette goog.ui.Palette to render.
    - * @return {!Element} Root element for the palette.
    - * @override
    - */
    -goog.ui.PaletteRenderer.prototype.createDom = function(palette) {
    -  var classNames = this.getClassNames(palette);
    -  var element = palette.getDomHelper().createDom(
    -      goog.dom.TagName.DIV, classNames ? classNames.join(' ') : null,
    -      this.createGrid(/** @type {Array<Node>} */(palette.getContent()),
    -          palette.getSize(), palette.getDomHelper()));
    -  goog.a11y.aria.setRole(element, goog.a11y.aria.Role.GRID);
    -  return element;
    -};
    -
    -
    -/**
    - * Returns the given items in a table with {@code size.width} columns and
    - * {@code size.height} rows.  If the table is too big, empty cells will be
    - * created as needed.  If the table is too small, the items that don't fit
    - * will not be rendered.
    - * @param {Array<Node>} items Palette items.
    - * @param {goog.math.Size} size Palette size (columns x rows); both dimensions
    - *     must be specified as numbers.
    - * @param {goog.dom.DomHelper} dom DOM helper for document interaction.
    - * @return {!Element} Palette table element.
    - */
    -goog.ui.PaletteRenderer.prototype.createGrid = function(items, size, dom) {
    -  var rows = [];
    -  for (var row = 0, index = 0; row < size.height; row++) {
    -    var cells = [];
    -    for (var column = 0; column < size.width; column++) {
    -      var item = items && items[index++];
    -      cells.push(this.createCell(item, dom));
    -    }
    -    rows.push(this.createRow(cells, dom));
    -  }
    -
    -  return this.createTable(rows, dom);
    -};
    -
    -
    -/**
    - * Returns a table element (or equivalent) that wraps the given rows.
    - * @param {Array<Element>} rows Array of row elements.
    - * @param {goog.dom.DomHelper} dom DOM helper for document interaction.
    - * @return {!Element} Palette table element.
    - */
    -goog.ui.PaletteRenderer.prototype.createTable = function(rows, dom) {
    -  var table = dom.createDom(goog.dom.TagName.TABLE,
    -      goog.getCssName(this.getCssClass(), 'table'),
    -      dom.createDom(goog.dom.TagName.TBODY,
    -          goog.getCssName(this.getCssClass(), 'body'), rows));
    -  table.cellSpacing = 0;
    -  table.cellPadding = 0;
    -  return table;
    -};
    -
    -
    -/**
    - * Returns a table row element (or equivalent) that wraps the given cells.
    - * @param {Array<Element>} cells Array of cell elements.
    - * @param {goog.dom.DomHelper} dom DOM helper for document interaction.
    - * @return {!Element} Row element.
    - */
    -goog.ui.PaletteRenderer.prototype.createRow = function(cells, dom) {
    -  var row = dom.createDom(goog.dom.TagName.TR,
    -      goog.getCssName(this.getCssClass(), 'row'), cells);
    -  goog.a11y.aria.setRole(row, goog.a11y.aria.Role.ROW);
    -  return row;
    -};
    -
    -
    -/**
    - * Returns a table cell element (or equivalent) that wraps the given palette
    - * item (which must be a DOM node).
    - * @param {Node|string} node Palette item.
    - * @param {goog.dom.DomHelper} dom DOM helper for document interaction.
    - * @return {!Element} Cell element.
    - */
    -goog.ui.PaletteRenderer.prototype.createCell = function(node, dom) {
    -  var cell = dom.createDom(goog.dom.TagName.TD, {
    -    'class': goog.getCssName(this.getCssClass(), 'cell'),
    -    // Cells must have an ID, for accessibility, so we generate one here.
    -    'id': goog.getCssName(this.getCssClass(), 'cell-') +
    -        goog.ui.PaletteRenderer.cellId_++
    -  }, node);
    -  goog.a11y.aria.setRole(cell, goog.a11y.aria.Role.GRIDCELL);
    -  // Initialize to an unselected state.
    -  goog.a11y.aria.setState(cell, goog.a11y.aria.State.SELECTED, false);
    -
    -  if (!goog.dom.getTextContent(cell) && !goog.a11y.aria.getLabel(cell)) {
    -    var ariaLabelForCell = this.findAriaLabelForCell_(cell);
    -    if (ariaLabelForCell) {
    -      goog.a11y.aria.setLabel(cell, ariaLabelForCell);
    -    }
    -  }
    -  return cell;
    -};
    -
    -
    -/**
    - * Descends the DOM and tries to find an aria label for a grid cell
    - * from the first child with a label or title.
    - * @param {!Element} cell The cell.
    - * @return {string} The label to use.
    - * @private
    - */
    -goog.ui.PaletteRenderer.prototype.findAriaLabelForCell_ = function(cell) {
    -  var iter = new goog.dom.NodeIterator(cell);
    -  var label = '';
    -  var node;
    -  while (!label && (node = goog.iter.nextOrValue(iter, null))) {
    -    if (node.nodeType == goog.dom.NodeType.ELEMENT) {
    -      label = goog.a11y.aria.getLabel(/** @type {!Element} */ (node)) ||
    -          node.title;
    -    }
    -  }
    -  return label;
    -};
    -
    -
    -/**
    - * Overrides {@link goog.ui.ControlRenderer#canDecorate} to always return false.
    - * @param {Element} element Ignored.
    - * @return {boolean} False, since palettes don't support the decorate flow (for
    - *     now).
    - * @override
    - */
    -goog.ui.PaletteRenderer.prototype.canDecorate = function(element) {
    -  return false;
    -};
    -
    -
    -/**
    - * Overrides {@link goog.ui.ControlRenderer#decorate} to be a no-op, since
    - * palettes don't support the decorate flow (for now).
    - * @param {goog.ui.Control} palette Ignored.
    - * @param {Element} element Ignored.
    - * @return {null} Always null.
    - * @override
    - */
    -goog.ui.PaletteRenderer.prototype.decorate = function(palette, element) {
    -  return null;
    -};
    -
    -
    -/**
    - * Overrides {@link goog.ui.ControlRenderer#setContent} for palettes.  Locates
    - * the HTML table representing the palette grid, and replaces the contents of
    - * each cell with a new element from the array of nodes passed as the second
    - * argument.  If the new content has too many items the table will have more
    - * rows added to fit, if there are less items than the table has cells, then the
    - * left over cells will be empty.
    - * @param {Element} element Root element of the palette control.
    - * @param {goog.ui.ControlContent} content Array of items to replace existing
    - *     palette items.
    - * @override
    - */
    -goog.ui.PaletteRenderer.prototype.setContent = function(element, content) {
    -  var items = /** @type {Array<Node>} */ (content);
    -  if (element) {
    -    var tbody = goog.dom.getElementsByTagNameAndClass(goog.dom.TagName.TBODY,
    -        goog.getCssName(this.getCssClass(), 'body'), element)[0];
    -    if (tbody) {
    -      var index = 0;
    -      goog.array.forEach(tbody.rows, function(row) {
    -        goog.array.forEach(row.cells, function(cell) {
    -          goog.dom.removeChildren(cell);
    -          if (items) {
    -            var item = items[index++];
    -            if (item) {
    -              goog.dom.appendChild(cell, item);
    -            }
    -          }
    -        });
    -      });
    -
    -      // Make space for any additional items.
    -      if (index < items.length) {
    -        var cells = [];
    -        var dom = goog.dom.getDomHelper(element);
    -        var width = tbody.rows[0].cells.length;
    -        while (index < items.length) {
    -          var item = items[index++];
    -          cells.push(this.createCell(item, dom));
    -          if (cells.length == width) {
    -            var row = this.createRow(cells, dom);
    -            goog.dom.appendChild(tbody, row);
    -            cells.length = 0;
    -          }
    -        }
    -        if (cells.length > 0) {
    -          while (cells.length < width) {
    -            cells.push(this.createCell('', dom));
    -          }
    -          var row = this.createRow(cells, dom);
    -          goog.dom.appendChild(tbody, row);
    -        }
    -      }
    -    }
    -    // Make sure the new contents are still unselectable.
    -    goog.style.setUnselectable(element, true, goog.userAgent.GECKO);
    -  }
    -};
    -
    -
    -/**
    - * Returns the item corresponding to the given node, or null if the node is
    - * neither a palette cell nor part of a palette item.
    - * @param {goog.ui.Palette} palette Palette in which to look for the item.
    - * @param {Node} node Node to look for.
    - * @return {Node} The corresponding palette item (null if not found).
    - */
    -goog.ui.PaletteRenderer.prototype.getContainingItem = function(palette, node) {
    -  var root = palette.getElement();
    -  while (node && node.nodeType == goog.dom.NodeType.ELEMENT && node != root) {
    -    if (node.tagName == goog.dom.TagName.TD && goog.dom.classlist.contains(
    -        /** @type {!Element} */ (node),
    -        goog.getCssName(this.getCssClass(), 'cell'))) {
    -      return node.firstChild;
    -    }
    -    node = node.parentNode;
    -  }
    -
    -  return null;
    -};
    -
    -
    -/**
    - * Updates the highlight styling of the palette cell containing the given node
    - * based on the value of the Boolean argument.
    - * @param {goog.ui.Palette} palette Palette containing the item.
    - * @param {Node} node Item whose cell is to be highlighted or un-highlighted.
    - * @param {boolean} highlight If true, the cell is highlighted; otherwise it is
    - *     un-highlighted.
    - */
    -goog.ui.PaletteRenderer.prototype.highlightCell = function(palette,
    -                                                           node,
    -                                                           highlight) {
    -  if (node) {
    -    var cell = this.getCellForItem(node);
    -    goog.asserts.assert(cell);
    -    goog.dom.classlist.enable(cell,
    -        goog.getCssName(this.getCssClass(), 'cell-hover'), highlight);
    -    // See http://www.w3.org/TR/2006/WD-aria-state-20061220/#activedescendent
    -    // for an explanation of the activedescendent.
    -    if (highlight) {
    -      goog.a11y.aria.setState(palette.getElementStrict(),
    -          goog.a11y.aria.State.ACTIVEDESCENDANT, cell.id);
    -    } else if (cell.id == goog.a11y.aria.getState(palette.getElementStrict(),
    -        goog.a11y.aria.State.ACTIVEDESCENDANT)) {
    -      goog.a11y.aria.removeState(palette.getElementStrict(),
    -          goog.a11y.aria.State.ACTIVEDESCENDANT);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * @param {Node} node Item whose cell is to be returned.
    - * @return {Element} The grid cell for the palette item.
    - */
    -goog.ui.PaletteRenderer.prototype.getCellForItem = function(node) {
    -  return /** @type {Element} */ (node ? node.parentNode : null);
    -};
    -
    -
    -/**
    - * Updates the selection styling of the palette cell containing the given node
    - * based on the value of the Boolean argument.
    - * @param {goog.ui.Palette} palette Palette containing the item.
    - * @param {Node} node Item whose cell is to be selected or deselected.
    - * @param {boolean} select If true, the cell is selected; otherwise it is
    - *     deselected.
    - */
    -goog.ui.PaletteRenderer.prototype.selectCell = function(palette, node, select) {
    -  if (node) {
    -    var cell = /** @type {!Element} */ (node.parentNode);
    -    goog.dom.classlist.enable(cell,
    -        goog.getCssName(this.getCssClass(), 'cell-selected'),
    -        select);
    -    goog.a11y.aria.setState(cell, goog.a11y.aria.State.SELECTED, select);
    -  }
    -};
    -
    -
    -/**
    - * Returns the CSS class to be applied to the root element of components
    - * rendered using this renderer.
    - * @return {string} Renderer-specific CSS class.
    - * @override
    - */
    -goog.ui.PaletteRenderer.prototype.getCssClass = function() {
    -  return goog.ui.PaletteRenderer.CSS_CLASS;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/paletterenderer_test.html b/src/database/third_party/closure-library/closure/goog/ui/paletterenderer_test.html
    deleted file mode 100644
    index 4c18fb8032c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/paletterenderer_test.html
    +++ /dev/null
    @@ -1,29 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -  @author erickj@google.com (Erick Johnson)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests for PaletteRenderer
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.PaletteRendererTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="root">
    -   <div id="sandbox">
    -   </div>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/paletterenderer_test.js b/src/database/third_party/closure-library/closure/goog/ui/paletterenderer_test.js
    deleted file mode 100644
    index f6cfec9aba0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/paletterenderer_test.js
    +++ /dev/null
    @@ -1,91 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.PaletteRendererTest');
    -goog.setTestOnly('goog.ui.PaletteRendererTest');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.Palette');
    -goog.require('goog.ui.PaletteRenderer');
    -
    -var sandbox;
    -var items = [
    -  '<div aria-label="label-0"></div>',
    -  '<div title="title-1"></div>',
    -  '<div aria-label="label-2" title="title-2"></div>',
    -  '<div><span title="child-title-3"></span></div>'
    -];
    -var itemEls;
    -var renderer;
    -var palette;
    -
    -function setUp() {
    -  sandbox = goog.dom.getElement('sandbox');
    -  itemEls = goog.array.map(items, function(item, index, a) {
    -    return goog.dom.htmlToDocumentFragment(item);
    -  });
    -  renderer = new goog.ui.PaletteRenderer();
    -  palette = new goog.ui.Palette(itemEls, renderer);
    -  palette.setSize(4, 1);
    -}
    -
    -function tearDown() {
    -  palette.dispose();
    -}
    -
    -function testGridA11yRoles() {
    -  var grid = renderer.createDom(palette);
    -  assertEquals(goog.a11y.aria.Role.GRID, goog.a11y.aria.getRole(grid));
    -  var table = grid.getElementsByTagName('table')[0];
    -  var row = table.getElementsByTagName('tr')[0];
    -  assertEquals(goog.a11y.aria.Role.ROW, goog.a11y.aria.getRole(row));
    -  var cell = row.getElementsByTagName('td')[0];
    -  assertEquals(goog.a11y.aria.Role.GRIDCELL, goog.a11y.aria.getRole(cell));
    -}
    -
    -function testCellA11yLabels() {
    -  var grid = renderer.createDom(palette);
    -  var cells = grid.getElementsByTagName('td');
    -
    -  assertEquals('An aria-label is used as a label',
    -      'label-0', goog.a11y.aria.getLabel(cells[0]));
    -  assertEquals('A title is used as a label',
    -      'title-1', goog.a11y.aria.getLabel(cells[1]));
    -  assertEquals('An aria-label takes precedence over a title',
    -      'label-2', goog.a11y.aria.getLabel(cells[2]));
    -  assertEquals('Children are traversed to find labels',
    -      'child-title-3', goog.a11y.aria.getLabel(cells[3]));
    -}
    -
    -function testA11yActiveDescendant() {
    -  palette.render();
    -  var cells = palette.getElementStrict().getElementsByTagName('td');
    -
    -  renderer.highlightCell(palette, cells[1].firstChild, true);
    -  assertEquals(cells[1].id, goog.a11y.aria.getState(
    -      palette.getElementStrict(), goog.a11y.aria.State.ACTIVEDESCENDANT));
    -
    -  renderer.highlightCell(palette, cells[0].firstChild, false);
    -  assertEquals(cells[1].id, goog.a11y.aria.getState(
    -      palette.getElementStrict(), goog.a11y.aria.State.ACTIVEDESCENDANT));
    -
    -  renderer.highlightCell(palette, cells[1].firstChild, false);
    -  assertNotEquals(cells[1].id, goog.a11y.aria.getState(
    -      palette.getElementStrict(), goog.a11y.aria.State.ACTIVEDESCENDANT));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/plaintextspellchecker.js b/src/database/third_party/closure-library/closure/goog/ui/plaintextspellchecker.js
    deleted file mode 100644
    index 5f65cca0352..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/plaintextspellchecker.js
    +++ /dev/null
    @@ -1,641 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Plain text spell checker implementation.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - * @see ../demos/plaintextspellchecker.html
    - */
    -
    -goog.provide('goog.ui.PlainTextSpellChecker');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.a11y.aria');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.events.KeyHandler');
    -goog.require('goog.spell.SpellCheck');
    -goog.require('goog.style');
    -goog.require('goog.ui.AbstractSpellChecker');
    -goog.require('goog.ui.Component');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Plain text spell checker implementation.
    - *
    - * @param {goog.spell.SpellCheck} handler Instance of the SpellCheckHandler
    - *     support object to use. A single instance can be shared by multiple
    - *     editor components.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @constructor
    - * @extends {goog.ui.AbstractSpellChecker}
    - * @final
    - */
    -goog.ui.PlainTextSpellChecker = function(handler, opt_domHelper) {
    -  goog.ui.AbstractSpellChecker.call(this, handler, opt_domHelper);
    -
    -  /**
    -   * Correction UI container.
    -   * @private {!HTMLDivElement}
    -   */
    -  this.overlay_ = /** @type {!HTMLDivElement} */
    -      (this.getDomHelper().createDom('div'));
    -  goog.style.setPreWrap(this.overlay_);
    -
    -  /**
    -   * Bound async function (to avoid rebinding it on every call).
    -   * @type {Function}
    -   * @private
    -   */
    -  this.boundContinueAsyncFn_ = goog.bind(this.continueAsync_, this);
    -
    -  /**
    -   * Regular expression for matching line breaks.
    -   * @type {RegExp}
    -   * @private
    -   */
    -  this.endOfLineMatcher_ = new RegExp('(.*)(\n|\r\n){0,1}', 'g');
    -};
    -goog.inherits(goog.ui.PlainTextSpellChecker, goog.ui.AbstractSpellChecker);
    -
    -
    -/**
    - * Class name for invalid words.
    - * @type {string}
    - */
    -goog.ui.PlainTextSpellChecker.prototype.invalidWordClassName =
    -    goog.getCssName('goog-spellcheck-invalidword');
    -
    -
    -/**
    - * Class name for corrected words.
    - * @type {string}
    - */
    -goog.ui.PlainTextSpellChecker.prototype.correctedWordClassName =
    -    goog.getCssName('goog-spellcheck-correctedword');
    -
    -
    -/**
    - * Class name for correction pane.
    - * @type {string}
    - */
    -goog.ui.PlainTextSpellChecker.prototype.correctionPaneClassName =
    -    goog.getCssName('goog-spellcheck-correctionpane');
    -
    -
    -/**
    - * Number of words to scan to precharge the dictionary.
    - * @type {number}
    - * @private
    - */
    -goog.ui.PlainTextSpellChecker.prototype.dictionaryPreScanSize_ = 1000;
    -
    -
    -/**
    - * Size of window. Used to check if a resize operation actually changed the size
    - * of the window.
    - * @type {goog.math.Size|undefined}
    - * @private
    - */
    -goog.ui.PlainTextSpellChecker.prototype.winSize_;
    -
    -
    -/**
    - * Event handler for listening to events without leaking.
    - * @type {goog.events.EventHandler|undefined}
    - * @private
    - */
    -goog.ui.PlainTextSpellChecker.prototype.eventHandler_;
    -
    -
    -/**
    - * The object handling keyboard events.
    - * @type {goog.events.KeyHandler|undefined}
    - * @private
    - */
    -goog.ui.PlainTextSpellChecker.prototype.keyHandler_;
    -
    -
    -/** @private {number} */
    -goog.ui.PlainTextSpellChecker.prototype.textArrayIndex_;
    -
    -
    -/** @private {!Array<string>} */
    -goog.ui.PlainTextSpellChecker.prototype.textArray_;
    -
    -
    -/** @private {!Array<boolean>} */
    -goog.ui.PlainTextSpellChecker.prototype.textArrayProcess_;
    -
    -
    -/**
    - * Creates the initial DOM representation for the component.
    - * @override
    - */
    -goog.ui.PlainTextSpellChecker.prototype.createDom = function() {
    -  this.setElementInternal(this.getDomHelper().createElement('textarea'));
    -};
    -
    -
    -/** @override */
    -goog.ui.PlainTextSpellChecker.prototype.enterDocument = function() {
    -  goog.ui.PlainTextSpellChecker.superClass_.enterDocument.call(this);
    -
    -  this.eventHandler_ = new goog.events.EventHandler(this);
    -  this.keyHandler_ = new goog.events.KeyHandler(this.overlay_);
    -
    -  this.initSuggestionsMenu();
    -  this.initAccessibility_();
    -};
    -
    -
    -/** @override */
    -goog.ui.PlainTextSpellChecker.prototype.exitDocument = function() {
    -  goog.ui.PlainTextSpellChecker.superClass_.exitDocument.call(this);
    -
    -  if (this.eventHandler_) {
    -    this.eventHandler_.dispose();
    -    this.eventHandler_ = undefined;
    -  }
    -  if (this.keyHandler_) {
    -    this.keyHandler_.dispose();
    -    this.keyHandler_ = undefined;
    -  }
    -};
    -
    -
    -/**
    - * Initializes suggestions menu. Populates menu with separator and ignore option
    - * that are always valid. Suggestions are later added above the separator.
    - * @override
    - */
    -goog.ui.PlainTextSpellChecker.prototype.initSuggestionsMenu = function() {
    -  goog.ui.PlainTextSpellChecker.superClass_.initSuggestionsMenu.call(this);
    -  this.eventHandler_.listen(/** @type {goog.ui.PopupMenu} */ (this.getMenu()),
    -      goog.ui.Component.EventType.HIDE, this.onCorrectionHide_);
    -};
    -
    -
    -/**
    - * Checks spelling for all text and displays correction UI.
    - * @override
    - */
    -goog.ui.PlainTextSpellChecker.prototype.check = function() {
    -  var text = this.getElement().value;
    -  this.getElement().readOnly = true;
    -
    -  // Prepare and position correction UI.
    -  goog.dom.removeChildren(this.overlay_);
    -  this.overlay_.className = this.correctionPaneClassName;
    -  if (this.getElement().parentNode != this.overlay_.parentNode) {
    -    this.getElement().parentNode.appendChild(this.overlay_);
    -  }
    -  goog.style.setElementShown(this.overlay_, false);
    -
    -  this.preChargeDictionary_(text);
    -};
    -
    -
    -/**
    - * Final stage of spell checking - displays the correction UI.
    - * @private
    - */
    -goog.ui.PlainTextSpellChecker.prototype.finishCheck_ = function() {
    -  // Show correction UI.
    -  this.positionOverlay_();
    -  goog.style.setElementShown(this.getElement(), false);
    -  goog.style.setElementShown(this.overlay_, true);
    -
    -  var eh = this.eventHandler_;
    -  eh.listen(this.overlay_, goog.events.EventType.CLICK, this.onWordClick_);
    -  eh.listen(/** @type {goog.events.KeyHandler} */ (this.keyHandler_),
    -      goog.events.KeyHandler.EventType.KEY, this.handleOverlayKeyEvent);
    -
    -  // The position and size of the overlay element needs to be recalculated if
    -  // the browser window is resized.
    -  var win = goog.dom.getWindow(this.getDomHelper().getDocument()) || window;
    -  this.winSize_ = goog.dom.getViewportSize(win);
    -  eh.listen(win, goog.events.EventType.RESIZE, this.onWindowResize_);
    -
    -  goog.ui.PlainTextSpellChecker.superClass_.check.call(this);
    -};
    -
    -
    -/**
    - * Start the scan after the dictionary was loaded.
    - *
    - * @param {string} text text to process.
    - * @private
    - */
    -goog.ui.PlainTextSpellChecker.prototype.preChargeDictionary_ = function(text) {
    -  this.eventHandler_.listen(this.spellCheck,
    -      goog.spell.SpellCheck.EventType.READY, this.onDictionaryCharged_, true);
    -
    -  this.populateDictionary(text, this.dictionaryPreScanSize_);
    -};
    -
    -
    -/**
    - * Loads few initial dictionary words into the cache.
    - *
    - * @param {goog.events.Event} e goog.spell.SpellCheck.EventType.READY event.
    - * @private
    - */
    -goog.ui.PlainTextSpellChecker.prototype.onDictionaryCharged_ = function(e) {
    -  e.stopPropagation();
    -  this.eventHandler_.unlisten(this.spellCheck,
    -      goog.spell.SpellCheck.EventType.READY, this.onDictionaryCharged_, true);
    -  this.checkAsync_(this.getElement().value);
    -};
    -
    -
    -/**
    - * Processes the included and skips the excluded text ranges.
    - * @return {goog.ui.AbstractSpellChecker.AsyncResult} Whether the spell
    - *     checking is pending or done.
    - * @private
    - */
    -goog.ui.PlainTextSpellChecker.prototype.spellCheckLoop_ = function() {
    -  for (var i = this.textArrayIndex_; i < this.textArray_.length; ++i) {
    -    var text = this.textArray_[i];
    -    if (this.textArrayProcess_[i]) {
    -      var result = this.processTextAsync(this.overlay_, text);
    -      if (result == goog.ui.AbstractSpellChecker.AsyncResult.PENDING) {
    -        this.textArrayIndex_ = i + 1;
    -        goog.Timer.callOnce(this.boundContinueAsyncFn_);
    -        return result;
    -      }
    -    } else {
    -      this.processRange(this.overlay_, text);
    -    }
    -  }
    -
    -  this.textArray_ = [];
    -  this.textArrayProcess_ = [];
    -
    -  return goog.ui.AbstractSpellChecker.AsyncResult.DONE;
    -};
    -
    -
    -/**
    - * Breaks text into included and excluded ranges using the marker RegExp
    - * supplied by the caller.
    - *
    - * @param {string} text text to process.
    - * @private
    - */
    -goog.ui.PlainTextSpellChecker.prototype.initTextArray_ = function(text) {
    -  if (!this.excludeMarker) {
    -    this.textArray_ = [text];
    -    this.textArrayProcess_ = [true];
    -    return;
    -  }
    -
    -  this.textArray_ = [];
    -  this.textArrayProcess_ = [];
    -  this.excludeMarker.lastIndex = 0;
    -  var stringSegmentStart = 0;
    -  var result;
    -  while (result = this.excludeMarker.exec(text)) {
    -    if (result[0].length == 0) {
    -      break;
    -    }
    -    var excludedRange = result[0];
    -    var includedRange = text.substr(stringSegmentStart, result.index -
    -        stringSegmentStart);
    -    if (includedRange) {
    -      this.textArray_.push(includedRange);
    -      this.textArrayProcess_.push(true);
    -    }
    -    this.textArray_.push(excludedRange);
    -    this.textArrayProcess_.push(false);
    -    stringSegmentStart = this.excludeMarker.lastIndex;
    -  }
    -
    -  var leftoverText = text.substr(stringSegmentStart);
    -  if (leftoverText) {
    -    this.textArray_.push(leftoverText);
    -    this.textArrayProcess_.push(true);
    -  }
    -};
    -
    -
    -/**
    - * Starts asynchrnonous spell checking.
    - *
    - * @param {string} text text to process.
    - * @private
    - */
    -goog.ui.PlainTextSpellChecker.prototype.checkAsync_ = function(text) {
    -  this.initializeAsyncMode();
    -  this.initTextArray_(text);
    -  this.textArrayIndex_ = 0;
    -  if (this.spellCheckLoop_() ==
    -      goog.ui.AbstractSpellChecker.AsyncResult.PENDING) {
    -    return;
    -  }
    -  this.finishAsyncProcessing();
    -  this.finishCheck_();
    -};
    -
    -
    -/**
    - * Continues asynchrnonous spell checking.
    - * @private
    - */
    -goog.ui.PlainTextSpellChecker.prototype.continueAsync_ = function() {
    -  // First finish with the current segment.
    -  var result = this.continueAsyncProcessing();
    -  if (result == goog.ui.AbstractSpellChecker.AsyncResult.PENDING) {
    -    goog.Timer.callOnce(this.boundContinueAsyncFn_);
    -    return;
    -  }
    -  if (this.spellCheckLoop_() ==
    -      goog.ui.AbstractSpellChecker.AsyncResult.PENDING) {
    -    return;
    -  }
    -  this.finishAsyncProcessing();
    -  this.finishCheck_();
    -};
    -
    -
    -/**
    - * Processes word.
    - *
    - * @param {Node} node Node containing word.
    - * @param {string} word Word to process.
    - * @param {goog.spell.SpellCheck.WordStatus} status Status of word.
    - * @override
    - */
    -goog.ui.PlainTextSpellChecker.prototype.processWord = function(node, word,
    -    status) {
    -  node.appendChild(this.createWordElement(word, status));
    -};
    -
    -
    -/**
    - * Processes range of text - recognized words and separators.
    - *
    - * @param {Node} node Node containing separator.
    - * @param {string} text text to process.
    - * @override
    - */
    -goog.ui.PlainTextSpellChecker.prototype.processRange = function(node, text) {
    -  this.endOfLineMatcher_.lastIndex = 0;
    -  var result;
    -  while (result = this.endOfLineMatcher_.exec(text)) {
    -    if (result[0].length == 0) {
    -      break;
    -    }
    -    node.appendChild(this.getDomHelper().createTextNode(result[1]));
    -    if (result[2]) {
    -      node.appendChild(this.getDomHelper().createElement('br'));
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Hides correction UI.
    - * @override
    - */
    -goog.ui.PlainTextSpellChecker.prototype.resume = function() {
    -  var wasVisible = this.isVisible();
    -
    -  goog.ui.PlainTextSpellChecker.superClass_.resume.call(this);
    -
    -  goog.style.setElementShown(this.overlay_, false);
    -  goog.style.setElementShown(this.getElement(), true);
    -  this.getElement().readOnly = false;
    -
    -  if (wasVisible) {
    -    this.getElement().value = goog.dom.getRawTextContent(this.overlay_);
    -    goog.dom.removeChildren(this.overlay_);
    -
    -    var eh = this.eventHandler_;
    -    eh.unlisten(this.overlay_, goog.events.EventType.CLICK, this.onWordClick_);
    -    eh.unlisten(/** @type {goog.events.KeyHandler} */ (this.keyHandler_),
    -        goog.events.KeyHandler.EventType.KEY, this.handleOverlayKeyEvent);
    -
    -    var win = goog.dom.getWindow(this.getDomHelper().getDocument()) || window;
    -    eh.unlisten(win, goog.events.EventType.RESIZE, this.onWindowResize_);
    -  }
    -};
    -
    -
    -/**
    - * Returns desired element properties for the specified status.
    - *
    - * @param {goog.spell.SpellCheck.WordStatus} status Status of word.
    - * @return {!Object} Properties to apply to word element.
    - * @override
    - */
    -goog.ui.PlainTextSpellChecker.prototype.getElementProperties =
    -    function(status) {
    -  if (status == goog.spell.SpellCheck.WordStatus.INVALID) {
    -    return {'class': this.invalidWordClassName};
    -  } else if (status == goog.spell.SpellCheck.WordStatus.CORRECTED) {
    -    return {'class': this.correctedWordClassName};
    -  }
    -  return {'class': ''};
    -};
    -
    -
    -/**
    - * Handles the click events.
    - *
    - * @param {goog.events.BrowserEvent} event Event object.
    - * @private
    - */
    -goog.ui.PlainTextSpellChecker.prototype.onWordClick_ = function(event) {
    -  if (event.target.className == this.invalidWordClassName ||
    -      event.target.className == this.correctedWordClassName) {
    -    this.showSuggestionsMenu(/** @type {!Element} */ (event.target), event);
    -
    -    // Prevent document click handler from closing the menu.
    -    event.stopPropagation();
    -  }
    -};
    -
    -
    -/**
    - * Handles window resize events.
    - *
    - * @param {goog.events.BrowserEvent} event Event object.
    - * @private
    - */
    -goog.ui.PlainTextSpellChecker.prototype.onWindowResize_ = function(event) {
    -  var win = goog.dom.getWindow(this.getDomHelper().getDocument()) || window;
    -  var size = goog.dom.getViewportSize(win);
    -
    -  if (size.width != this.winSize_.width ||
    -      size.height != this.winSize_.height) {
    -    goog.style.setElementShown(this.overlay_, false);
    -    goog.style.setElementShown(this.getElement(), true);
    -
    -    // IE requires a slight delay, allowing the resize operation to take effect.
    -    if (goog.userAgent.IE) {
    -      goog.Timer.callOnce(this.resizeOverlay_, 100, this);
    -    } else {
    -      this.resizeOverlay_();
    -    }
    -    this.winSize_ = size;
    -  }
    -};
    -
    -
    -/**
    - * Resizes overlay to match the size of the bound element then displays the
    - * overlay. Helper for {@link #onWindowResize_}.
    - *
    - * @private
    - */
    -goog.ui.PlainTextSpellChecker.prototype.resizeOverlay_ = function() {
    -  this.positionOverlay_();
    -  goog.style.setElementShown(this.getElement(), false);
    -  goog.style.setElementShown(this.overlay_, true);
    -};
    -
    -
    -/**
    - * Updates the position and size of the overlay to match the original element.
    - *
    - * @private
    - */
    -goog.ui.PlainTextSpellChecker.prototype.positionOverlay_ = function() {
    -  goog.style.setPosition(
    -      this.overlay_, goog.style.getPosition(this.getElement()));
    -  goog.style.setSize(this.overlay_, goog.style.getSize(this.getElement()));
    -};
    -
    -
    -/** @override */
    -goog.ui.PlainTextSpellChecker.prototype.disposeInternal = function() {
    -  this.getDomHelper().removeNode(this.overlay_);
    -  delete this.overlay_;
    -  delete this.boundContinueAsyncFn_;
    -  delete this.endOfLineMatcher_;
    -  goog.ui.PlainTextSpellChecker.superClass_.disposeInternal.call(this);
    -};
    -
    -
    -/**
    - * Specify ARIA roles and states as appropriate.
    - * @private
    - */
    -goog.ui.PlainTextSpellChecker.prototype.initAccessibility_ = function() {
    -  goog.asserts.assert(this.overlay_,
    -      'The plain text spell checker DOM element cannot be null.');
    -  goog.a11y.aria.setRole(this.overlay_, 'region');
    -  goog.a11y.aria.setState(this.overlay_, 'live', 'assertive');
    -  this.overlay_.tabIndex = 0;
    -
    -  /** @desc Title for Spell Checker's overlay.*/
    -  var MSG_SPELLCHECKER_OVERLAY_TITLE = goog.getMsg('Spell Checker');
    -  this.overlay_.title = MSG_SPELLCHECKER_OVERLAY_TITLE;
    -};
    -
    -
    -/**
    - * Handles key down for overlay.
    - * @param {goog.events.BrowserEvent} e The browser event.
    - * @return {boolean} The handled value.
    - */
    -goog.ui.PlainTextSpellChecker.prototype.handleOverlayKeyEvent = function(e) {
    -  var handled = false;
    -  switch (e.keyCode) {
    -    case goog.events.KeyCodes.RIGHT:
    -      if (e.ctrlKey) {
    -        handled = this.navigate(goog.ui.AbstractSpellChecker.Direction.NEXT);
    -      }
    -      break;
    -
    -    case goog.events.KeyCodes.LEFT:
    -      if (e.ctrlKey) {
    -        handled = this.navigate(
    -            goog.ui.AbstractSpellChecker.Direction.PREVIOUS);
    -      }
    -      break;
    -
    -    case goog.events.KeyCodes.DOWN:
    -      if (this.getFocusedElementIndex()) {
    -        var el = this.getDomHelper().getElement(this.makeElementId(
    -            this.getFocusedElementIndex()));
    -        if (el) {
    -          var position = goog.style.getPosition(el);
    -          var size = goog.style.getSize(el);
    -          position.x += size.width / 2;
    -          position.y += size.height / 2;
    -          this.showSuggestionsMenu(el, position);
    -          handled = true;
    -        }
    -      }
    -      break;
    -  }
    -
    -  if (handled) {
    -    e.preventDefault();
    -  }
    -
    -  return handled;
    -};
    -
    -
    -/**
    - * Handles correction menu actions.
    - *
    - * @param {goog.events.Event} event Action event.
    - * @override
    - */
    -goog.ui.PlainTextSpellChecker.prototype.onCorrectionAction = function(event) {
    -  goog.ui.PlainTextSpellChecker.superClass_.onCorrectionAction.call(this,
    -      event);
    -
    -  // In case of editWord base class has already set the focus (on the input),
    -  // otherwise set the focus back on the word.
    -  if (event.target != this.getMenuEdit()) {
    -    this.reFocus_();
    -  }
    -};
    -
    -
    -/**
    - * Restores focus when the suggestion menu is hidden.
    - *
    - * @param {goog.events.BrowserEvent} event Blur event.
    - * @private
    - */
    -goog.ui.PlainTextSpellChecker.prototype.onCorrectionHide_ = function(event) {
    -  this.reFocus_();
    -};
    -
    -
    -/**
    - * Sets the focus back on the previously focused word element.
    - * @private
    - */
    -goog.ui.PlainTextSpellChecker.prototype.reFocus_ = function() {
    -  var el = this.getElementByIndex(this.getFocusedElementIndex());
    -  if (el) {
    -    el.focus();
    -  } else {
    -    this.overlay_.focus();
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/plaintextspellchecker_test.html b/src/database/third_party/closure-library/closure/goog/ui/plaintextspellchecker_test.html
    deleted file mode 100644
    index cd5521a12d1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/plaintextspellchecker_test.html
    +++ /dev/null
    @@ -1,42 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <!--
    -This test has not yet been updated to run on IE8. See http://b/hotlist?id=36311
    --->
    -  <!--meta http-equiv="X-UA-Compatible" content="IE=edge"-->
    -  <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
    -  <title>
    -   Closure Unit Tests - goog.ui.PlainTextSpellChecker
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.PlainTextSpellCheckerTest');
    -  </script>
    - </head>
    - <body>
    -  <textarea id="test1" style="width: 50ex; height: 15em;">
    -  </textarea>
    -  <textarea id="test2" style="width: 50ex; height: 15em;">
    -  </textarea>
    -  <textarea id="test3" style="width: 50ex; height: 15em;">
    -  </textarea>
    -  <textarea id="test4" style="width: 50ex; height: 15em;">
    -  </textarea>
    -  <textarea id="test5" style="width: 50ex; height: 15em;">
    -  </textarea>
    -  <textarea id="test6" style="width: 50ex; height: 15em;">
    -  </textarea>
    -  <textarea id="test7" style="width: 50ex; height: 15em;">
    -  </textarea>
    -  <textarea id="test8" style="width: 50ex; height: 15em;">
    -  </textarea>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/plaintextspellchecker_test.js b/src/database/third_party/closure-library/closure/goog/ui/plaintextspellchecker_test.js
    deleted file mode 100644
    index 5697f2037b7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/plaintextspellchecker_test.js
    +++ /dev/null
    @@ -1,439 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.PlainTextSpellCheckerTest');
    -goog.setTestOnly('goog.ui.PlainTextSpellCheckerTest');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.dom');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.spell.SpellCheck');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.PlainTextSpellChecker');
    -
    -var missspelling = 'missspelling';
    -var iggnore = 'iggnore';
    -var vocabulary = ['test', 'words', 'a', 'few', missspelling, iggnore];
    -
    -// We don't use Math.random() to make test predictable. Math.random is not
    -// repeatable, so a success on the dev machine != success in the lab (or on
    -// other dev machines). This is the same pseudorandom logic that CRT rand()
    -// uses.
    -var rseed = 1;
    -function random(range) {
    -  rseed = (rseed * 1103515245 + 12345) & 0xffffffff;
    -  return ((rseed >> 16) & 0x7fff) % range;
    -}
    -
    -function localSpellCheckingFunction(words, spellChecker, callback) {
    -  var len = words.length;
    -  var results = [];
    -  for (var i = 0; i < len; i++) {
    -    var word = words[i];
    -    var found = false;
    -    // Last two words are considered misspellings
    -    for (var j = 0; j < vocabulary.length - 2; ++j) {
    -      if (vocabulary[j] == word) {
    -        found = true;
    -        break;
    -      }
    -    }
    -    if (found) {
    -      results.push([word, goog.spell.SpellCheck.WordStatus.VALID]);
    -    } else {
    -      results.push([word, goog.spell.SpellCheck.WordStatus.INVALID,
    -        ['foo', 'bar']]);
    -    }
    -  }
    -  callback.call(spellChecker, results);
    -}
    -
    -function generateRandomSpace() {
    -  var string = '';
    -  var nSpace = 1 + random(4);
    -  for (var i = 0; i < nSpace; ++i) {
    -    string += ' ';
    -  }
    -  return string;
    -}
    -
    -function generateRandomString(maxWords, doQuotes) {
    -  var x = random(10);
    -  var string = '';
    -  if (doQuotes) {
    -    if (x == 0) {
    -      string = 'On xxxxx yyyy wrote:\n> ';
    -    } else if (x < 3) {
    -      string = '> ';
    -    }
    -  }
    -
    -  var nWords = 1 + random(maxWords);
    -  for (var i = 0; i < nWords; ++i) {
    -    string += vocabulary[random(vocabulary.length)];
    -    string += generateRandomSpace();
    -  }
    -  return string;
    -}
    -
    -var timerQueue = [];
    -function processTimerQueue() {
    -  while (timerQueue.length > 0) {
    -    var fn = timerQueue.shift();
    -    fn();
    -  }
    -}
    -
    -function localTimer(fn, delay, obj) {
    -  if (obj) {
    -    fn = goog.bind(fn, obj);
    -  }
    -  timerQueue.push(fn);
    -  return timerQueue.length;
    -}
    -
    -function testPlainTextSpellCheckerNoQuotes() {
    -  var handler = new goog.spell.SpellCheck(localSpellCheckingFunction);
    -  var s = new goog.ui.PlainTextSpellChecker(handler);
    -  s.asyncWordsPerBatch_ = 100;
    -  var el = document.getElementById('test1');
    -  s.decorate(el);
    -  var text = '';
    -  for (var i = 0; i < 10; ++i) {
    -    text += generateRandomString(10, false) + '\n';
    -  }
    -  el.value = text;
    -  // Yes this looks bizzare. This is for '\n' processing.
    -  // They get converted to CRLF as part of the above statement.
    -  text = el.value;
    -
    -  var timerSav = goog.Timer.callOnce;
    -  goog.Timer.callOnce = localTimer;
    -
    -  s.check();
    -  processTimerQueue();
    -  s.ignoreWord(iggnore);
    -  processTimerQueue();
    -  s.check();
    -  processTimerQueue();
    -  s.resume();
    -  processTimerQueue();
    -
    -  goog.Timer.callOnce = timerSav;
    -
    -  assertEquals('Spell checker run should not change the underlying element.',
    -               text, el.value);
    -  s.dispose();
    -}
    -
    -function testPlainTextSpellCheckerWithQuotes() {
    -  var handler = new goog.spell.SpellCheck(localSpellCheckingFunction);
    -  var s = new goog.ui.PlainTextSpellChecker(handler);
    -  s.asyncWordsPerBatch_ = 100;
    -  var el = document.getElementById('test2');
    -  s.decorate(el);
    -  var text = '';
    -  for (var i = 0; i < 10; ++i) {
    -    text += generateRandomString(10, true) + '\n';
    -  }
    -  el.value = text;
    -  // Yes this looks bizzare. This is for '\n' processing.
    -  // They get converted to CRLF as part of the above statement.
    -  text = el.value;
    -
    -  var timerSav = goog.Timer.callOnce;
    -  goog.Timer.callOnce = localTimer;
    -
    -  s.setExcludeMarker(new RegExp('\nOn .* wrote:\n(> .*\n)+|\n(> .*\n)', 'g'));
    -  s.check();
    -  processTimerQueue();
    -  s.ignoreWord(iggnore);
    -  processTimerQueue();
    -  s.check();
    -  processTimerQueue();
    -  s.resume();
    -  processTimerQueue();
    -
    -  goog.Timer.callOnce = timerSav;
    -
    -  assertEquals('Spell checker run should not change the underlying element.',
    -               text, el.value);
    -  s.dispose();
    -}
    -
    -function testPlainTextSpellCheckerWordReplacement() {
    -  var handler = new goog.spell.SpellCheck(localSpellCheckingFunction);
    -  var s = new goog.ui.PlainTextSpellChecker(handler);
    -  s.asyncWordsPerBatch_ = 100;
    -  var el = document.getElementById('test3');
    -  s.decorate(el);
    -  var text = '';
    -  for (var i = 0; i < 10; ++i) {
    -    text += generateRandomString(10, false) + '\n';
    -  }
    -  el.value = text;
    -
    -  var timerSav = goog.Timer.callOnce;
    -  goog.Timer.callOnce = localTimer;
    -
    -  s.check();
    -  processTimerQueue();
    -
    -  var container = s.overlay_;
    -  var wordEl = container.firstChild;
    -  while (wordEl) {
    -    if (goog.dom.getTextContent(wordEl) == missspelling) {
    -      break;
    -    }
    -    wordEl = wordEl.nextSibling;
    -  }
    -
    -  if (!wordEl) {
    -    assertTrue('Cannot find the world that should have been here.' +
    -               'Please revise the test', false);
    -    return;
    -  }
    -
    -  s.activeWord_ = missspelling;
    -  s.activeElement_ = wordEl;
    -  var suggestions = s.getSuggestions_();
    -  s.replaceWord(wordEl, missspelling, 'foo');
    -  assertEquals('Should have set the original word attribute!',
    -      wordEl.getAttribute(goog.ui.AbstractSpellChecker.ORIGINAL_),
    -      missspelling);
    -
    -  s.activeWord_ = goog.dom.getTextContent(wordEl);
    -  s.activeElement_ = wordEl;
    -  var newSuggestions = s.getSuggestions_();
    -  assertEquals('Suggestion list should still be present even if the word ' +
    -      'is now correct!', suggestions, newSuggestions);
    -
    -  s.resume();
    -  processTimerQueue();
    -
    -  goog.Timer.callOnce = timerSav;
    -  s.dispose();
    -}
    -
    -
    -function testPlainTextSpellCheckerKeyboardNavigateNext() {
    -  var handler = new goog.spell.SpellCheck(localSpellCheckingFunction);
    -  var s = new goog.ui.PlainTextSpellChecker(handler);
    -  var el = document.getElementById('test4');
    -  s.decorate(el);
    -  var text = 'a unit test for keyboard test';
    -  el.value = text;
    -  var keyEventProperties = {};
    -  keyEventProperties.ctrlKey = true;
    -  keyEventProperties.shiftKey = false;
    -
    -  var timerSav = goog.Timer.callOnce;
    -  goog.Timer.callOnce = localTimer;
    -
    -  s.check();
    -  processTimerQueue();
    -
    -  var container = s.overlay_;
    -
    -  // First call just moves focus to first misspelled word.
    -  goog.testing.events.fireKeySequence(container, goog.events.KeyCodes.RIGHT,
    -      keyEventProperties);
    -
    -  // Test moving from first to second mispelled word.
    -  var defaultExecuted = goog.testing.events.fireKeySequence(container,
    -      goog.events.KeyCodes.RIGHT, keyEventProperties);
    -
    -  assertFalse('The default action should be prevented for the key event',
    -      defaultExecuted);
    -  assertEquals('The second misspelled word should have focus.',
    -      document.activeElement, container.children[1]);
    -
    -  s.resume();
    -  processTimerQueue();
    -
    -  goog.Timer.callOnce = timerSav;
    -  s.dispose();
    -}
    -
    -
    -function testPlainTextSpellCheckerKeyboardNavigateNextOnLastWord() {
    -  var handler = new goog.spell.SpellCheck(localSpellCheckingFunction);
    -  var s = new goog.ui.PlainTextSpellChecker(handler);
    -  var el = document.getElementById('test5');
    -  s.decorate(el);
    -  var text = 'a unit test for keyboard test';
    -  el.value = text;
    -  var keyEventProperties = {};
    -  keyEventProperties.ctrlKey = true;
    -  keyEventProperties.shiftKey = false;
    -
    -  var timerSav = goog.Timer.callOnce;
    -  goog.Timer.callOnce = localTimer;
    -
    -  s.check();
    -  processTimerQueue();
    -
    -  var container = s.overlay_;
    -
    -  // First call just moves focus to first misspelled word.
    -  goog.testing.events.fireKeySequence(container, goog.events.KeyCodes.RIGHT,
    -      keyEventProperties);
    -  goog.testing.events.fireKeySequence(container, goog.events.KeyCodes.RIGHT,
    -      keyEventProperties);
    -  goog.testing.events.fireKeySequence(container, goog.events.KeyCodes.RIGHT,
    -      keyEventProperties);
    -
    -  // Test moving to the next invalid word.
    -  var defaultExecuted = goog.testing.events.fireKeySequence(container,
    -      goog.events.KeyCodes.RIGHT, keyEventProperties);
    -
    -  assertFalse('The default action should be prevented for the key event',
    -      defaultExecuted);
    -  assertEquals('The third/last misspelled word should have focus.',
    -      document.activeElement, container.children[2]);
    -
    -  s.resume();
    -  processTimerQueue();
    -
    -  goog.Timer.callOnce = timerSav;
    -  s.dispose();
    -}
    -
    -
    -function testPlainTextSpellCheckerKeyboardNavigateOpenSuggestions() {
    -  var handler = new goog.spell.SpellCheck(localSpellCheckingFunction);
    -  var s = new goog.ui.PlainTextSpellChecker(handler);
    -  var el = document.getElementById('test6');
    -  s.decorate(el);
    -  var text = 'unit';
    -  el.value = text;
    -  var keyEventProperties = {};
    -  keyEventProperties.ctrlKey = true;
    -  keyEventProperties.shiftKey = false;
    -
    -  var timerSav = goog.Timer.callOnce;
    -  goog.Timer.callOnce = localTimer;
    -
    -  s.check();
    -  processTimerQueue();
    -
    -  var container = s.overlay_;
    -  var suggestionMenu = s.getMenu();
    -
    -  goog.testing.events.fireKeySequence(container, goog.events.KeyCodes.RIGHT,
    -      keyEventProperties);
    -
    -  assertFalse('The suggestion menu should not be visible yet.',
    -      suggestionMenu.isVisible());
    -
    -  keyEventProperties.ctrlKey = false;
    -  var defaultExecuted = goog.testing.events.fireKeySequence(container,
    -      goog.events.KeyCodes.DOWN, keyEventProperties);
    -
    -  assertFalse('The default action should be prevented for the key event',
    -      defaultExecuted);
    -  assertTrue('The suggestion menu should be visible after the key event.',
    -      suggestionMenu.isVisible());
    -
    -  s.resume();
    -  processTimerQueue();
    -
    -  goog.Timer.callOnce = timerSav;
    -  s.dispose();
    -}
    -
    -
    -function testPlainTextSpellCheckerKeyboardNavigatePrevious() {
    -  var handler = new goog.spell.SpellCheck(localSpellCheckingFunction);
    -  var s = new goog.ui.PlainTextSpellChecker(handler);
    -  var el = document.getElementById('test7');
    -  s.decorate(el);
    -  var text = 'a unit test for keyboard test';
    -  el.value = text;
    -  var keyEventProperties = {};
    -  keyEventProperties.ctrlKey = true;
    -  keyEventProperties.shiftKey = false;
    -
    -  var timerSav = goog.Timer.callOnce;
    -  goog.Timer.callOnce = localTimer;
    -
    -  s.check();
    -  processTimerQueue();
    -
    -  var container = s.overlay_;
    -
    -  // Move to the third element, so we can test the move back to the second.
    -  goog.testing.events.fireKeySequence(container, goog.events.KeyCodes.RIGHT,
    -      keyEventProperties);
    -  goog.testing.events.fireKeySequence(container, goog.events.KeyCodes.RIGHT,
    -      keyEventProperties);
    -  goog.testing.events.fireKeySequence(container, goog.events.KeyCodes.RIGHT,
    -      keyEventProperties);
    -
    -  // Test moving from third to second mispelled word.
    -  var defaultExecuted = goog.testing.events.fireKeySequence(container,
    -      goog.events.KeyCodes.LEFT, keyEventProperties);
    -
    -  assertFalse('The default action should be prevented for the key event',
    -      defaultExecuted);
    -  assertEquals('The second misspelled word should have focus.',
    -      document.activeElement, container.children[1]);
    -
    -  s.resume();
    -  processTimerQueue();
    -
    -  goog.Timer.callOnce = timerSav;
    -  s.dispose();
    -}
    -
    -
    -function testPlainTextSpellCheckerKeyboardNavigatePreviousOnFirstWord() {
    -  var handler = new goog.spell.SpellCheck(localSpellCheckingFunction);
    -  var s = new goog.ui.PlainTextSpellChecker(handler);
    -  var el = document.getElementById('test8');
    -  s.decorate(el);
    -  var text = 'a unit test for keyboard test';
    -  el.value = text;
    -  var keyEventProperties = {};
    -  keyEventProperties.ctrlKey = true;
    -  keyEventProperties.shiftKey = false;
    -
    -  var timerSav = goog.Timer.callOnce;
    -  goog.Timer.callOnce = localTimer;
    -
    -  s.check();
    -  processTimerQueue();
    -
    -  var container = s.overlay_;
    -
    -  // Move to the first invalid word.
    -  goog.testing.events.fireKeySequence(container, goog.events.KeyCodes.RIGHT,
    -      keyEventProperties);
    -
    -  // Test moving to the previous invalid word.
    -  var defaultExecuted = goog.testing.events.fireKeySequence(container,
    -      goog.events.KeyCodes.LEFT, keyEventProperties);
    -
    -  assertFalse('The default action should be prevented for the key event',
    -      defaultExecuted);
    -  assertEquals('The first misspelled word should have focus.',
    -      document.activeElement, container.children[0]);
    -
    -  s.resume();
    -  processTimerQueue();
    -
    -  goog.Timer.callOnce = timerSav;
    -  s.dispose();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/popup.js b/src/database/third_party/closure-library/closure/goog/ui/popup.js
    deleted file mode 100644
    index 6cb03ec25bd..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/popup.js
    +++ /dev/null
    @@ -1,337 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Definition of the Popup class.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - * @see ../demos/popup.html
    - */
    -
    -goog.provide('goog.ui.Popup');
    -goog.provide('goog.ui.Popup.AbsolutePosition');
    -goog.provide('goog.ui.Popup.AnchoredPosition');
    -goog.provide('goog.ui.Popup.AnchoredViewPortPosition');
    -goog.provide('goog.ui.Popup.ClientPosition');
    -goog.provide('goog.ui.Popup.Overflow');
    -goog.provide('goog.ui.Popup.ViewPortClientPosition');
    -goog.provide('goog.ui.Popup.ViewPortPosition');
    -
    -goog.require('goog.math.Box');
    -goog.require('goog.positioning.AbsolutePosition');
    -goog.require('goog.positioning.AnchoredPosition');
    -goog.require('goog.positioning.AnchoredViewportPosition');
    -goog.require('goog.positioning.ClientPosition');
    -goog.require('goog.positioning.Corner');
    -goog.require('goog.positioning.Overflow');
    -goog.require('goog.positioning.ViewportClientPosition');
    -goog.require('goog.positioning.ViewportPosition');
    -goog.require('goog.style');
    -goog.require('goog.ui.PopupBase');
    -
    -
    -
    -/**
    - * The Popup class provides functionality for displaying an absolutely
    - * positioned element at a particular location in the window. It's designed to
    - * be used as the foundation for building controls like a menu or tooltip. The
    - * Popup class includes functionality for displaying a Popup near adjacent to
    - * an anchor element.
    - *
    - * This works cross browser and thus does not use IE's createPopup feature
    - * which supports extending outside the edge of the brower window.
    - *
    - * @param {Element=} opt_element A DOM element for the popup.
    - * @param {goog.positioning.AbstractPosition=} opt_position A positioning helper
    - *     object.
    - * @constructor
    - * @extends {goog.ui.PopupBase}
    - */
    -goog.ui.Popup = function(opt_element, opt_position) {
    -  /**
    -   * Corner of the popup to used in the positioning algorithm.
    -   *
    -   * @type {goog.positioning.Corner}
    -   * @private
    -   */
    -  this.popupCorner_ = goog.positioning.Corner.TOP_START;
    -
    -  /**
    -   * Positioning helper object.
    -   *
    -   * @type {goog.positioning.AbstractPosition|undefined}
    -   * @protected
    -   * @suppress {underscore|visibility}
    -   */
    -  this.position_ = opt_position || undefined;
    -  goog.ui.PopupBase.call(this, opt_element);
    -};
    -goog.inherits(goog.ui.Popup, goog.ui.PopupBase);
    -goog.tagUnsealableClass(goog.ui.Popup);
    -
    -
    -/**
    - * Enum for representing position handling in cases where the element would be
    - * positioned outside the viewport.
    - *
    - * @enum {number}
    - *
    - * @deprecated Use {@link goog.positioning.Overflow} instead, this alias will be
    - *     removed at the end of Q1 2009.
    - */
    -goog.ui.Popup.Overflow = goog.positioning.Overflow;
    -
    -
    -/**
    - * Margin for the popup used in positioning algorithms.
    - *
    - * @type {goog.math.Box|undefined}
    - * @private
    - */
    -goog.ui.Popup.prototype.margin_;
    -
    -
    -/**
    - * Returns the corner of the popup to used in the positioning algorithm.
    - *
    - * @return {goog.positioning.Corner} The popup corner used for positioning.
    - */
    -goog.ui.Popup.prototype.getPinnedCorner = function() {
    -  return this.popupCorner_;
    -};
    -
    -
    -/**
    - * Sets the corner of the popup to used in the positioning algorithm.
    - *
    - * @param {goog.positioning.Corner} corner The popup corner used for
    - *     positioning.
    - */
    -goog.ui.Popup.prototype.setPinnedCorner = function(corner) {
    -  this.popupCorner_ = corner;
    -  if (this.isVisible()) {
    -    this.reposition();
    -  }
    -};
    -
    -
    -/**
    - * @return {goog.positioning.AbstractPosition} The position helper object
    - *     associated with the popup.
    - */
    -goog.ui.Popup.prototype.getPosition = function() {
    -  return this.position_ || null;
    -};
    -
    -
    -/**
    - * Sets the position helper object associated with the popup.
    - *
    - * @param {goog.positioning.AbstractPosition} position A position helper object.
    - */
    -goog.ui.Popup.prototype.setPosition = function(position) {
    -  this.position_ = position || undefined;
    -  if (this.isVisible()) {
    -    this.reposition();
    -  }
    -};
    -
    -
    -/**
    - * Returns the margin to place around the popup.
    - *
    - * @return {goog.math.Box?} The margin.
    - */
    -goog.ui.Popup.prototype.getMargin = function() {
    -  return this.margin_ || null;
    -};
    -
    -
    -/**
    - * Sets the margin to place around the popup.
    - *
    - * @param {goog.math.Box|number|null} arg1 Top value or Box.
    - * @param {number=} opt_arg2 Right value.
    - * @param {number=} opt_arg3 Bottom value.
    - * @param {number=} opt_arg4 Left value.
    - */
    -goog.ui.Popup.prototype.setMargin = function(arg1, opt_arg2, opt_arg3,
    -                                             opt_arg4) {
    -  if (arg1 == null || arg1 instanceof goog.math.Box) {
    -    this.margin_ = arg1;
    -  } else {
    -    this.margin_ = new goog.math.Box(arg1,
    -        /** @type {number} */ (opt_arg2),
    -        /** @type {number} */ (opt_arg3),
    -        /** @type {number} */ (opt_arg4));
    -  }
    -  if (this.isVisible()) {
    -    this.reposition();
    -  }
    -};
    -
    -
    -/**
    - * Repositions the popup according to the current state.
    - * @override
    - */
    -goog.ui.Popup.prototype.reposition = function() {
    -  if (!this.position_) {
    -    return;
    -  }
    -
    -  var hideForPositioning = !this.isVisible() &&
    -      this.getType() != goog.ui.PopupBase.Type.MOVE_OFFSCREEN;
    -  var el = this.getElement();
    -  if (hideForPositioning) {
    -    el.style.visibility = 'hidden';
    -    goog.style.setElementShown(el, true);
    -  }
    -
    -  this.position_.reposition(el, this.popupCorner_, this.margin_);
    -
    -  if (hideForPositioning) {
    -    // NOTE(eae): The visibility property is reset to 'visible' by the show_
    -    // method in PopupBase. Resetting it here causes flickering in some
    -    // situations, even if set to visible after the display property has been
    -    // set to none by the call below.
    -    goog.style.setElementShown(el, false);
    -  }
    -};
    -
    -
    -
    -/**
    - * Encapsulates a popup position where the popup is anchored at a corner of
    - * an element.
    - *
    - * When using AnchoredPosition, it is recommended that the popup element
    - * specified in the Popup constructor or Popup.setElement be absolutely
    - * positioned.
    - *
    - * @param {Element} element The element to anchor the popup at.
    - * @param {goog.positioning.Corner} corner The corner of the element to anchor
    - *     the popup at.
    - * @constructor
    - * @extends {goog.positioning.AbstractPosition}
    - *
    - * @deprecated Use {@link goog.positioning.AnchoredPosition} instead, this
    - *     alias will be removed at the end of Q1 2009.
    - * @final
    - */
    -goog.ui.Popup.AnchoredPosition = goog.positioning.AnchoredPosition;
    -
    -
    -
    -/**
    - * Encapsulates a popup position where the popup is anchored at a corner of
    - * an element. The corners are swapped if dictated by the viewport. For instance
    - * if a popup is anchored with its top left corner to the bottom left corner of
    - * the anchor the popup is either displayed below the anchor (as specified) or
    - * above it if there's not enough room to display it below.
    - *
    - * When using AnchoredPosition, it is recommended that the popup element
    - * specified in the Popup constructor or Popup.setElement be absolutely
    - * positioned.
    - *
    - * @param {Element} element The element to anchor the popup at.
    - * @param {goog.positioning.Corner} corner The corner of the element to anchor
    - *    the popup at.
    - * @param {boolean=} opt_adjust Whether the positioning should be adjusted until
    - *    the element fits inside the viewport even if that means that the anchored
    - *    corners are ignored.
    - * @constructor
    - * @extends {goog.ui.Popup.AnchoredPosition}
    - *
    - * @deprecated Use {@link goog.positioning.AnchoredViewportPosition} instead,
    - *     this alias will be removed at the end of Q1 2009.
    - */
    -goog.ui.Popup.AnchoredViewPortPosition =
    -    goog.positioning.AnchoredViewportPosition;
    -
    -
    -
    -/**
    - * Encapsulates a popup position where the popup absolutely positioned by
    - * setting the left/top style elements directly to the specified values.
    - * The position is generally relative to the element's offsetParent. Normally,
    - * this is the document body, but can be another element if the popup element
    - * is scoped by an element with relative position.
    - *
    - * @param {number|!goog.math.Coordinate} arg1 Left position or coordinate.
    - * @param {number=} opt_arg2 Top position.
    - * @constructor
    - * @extends {goog.positioning.AbstractPosition}
    - *
    - * @deprecated Use {@link goog.positioning.AbsolutePosition} instead, this alias
    - *     will be removed at the end of Q1 2009.
    - * @final
    - */
    -goog.ui.Popup.AbsolutePosition = goog.positioning.AbsolutePosition;
    -
    -
    -
    -/**
    - * Encapsulates a popup position where the popup is positioned according to
    - * coordinates relative to the  element's view port (page). This calculates the
    - * correct position to use even if the element is relatively positioned to some
    - * other element.
    - *
    - * @param {number|!goog.math.Coordinate} arg1 Left position or coordinate.
    - * @param {number=} opt_arg2 Top position.
    - * @constructor
    - * @extends {goog.ui.Popup.AbsolutePosition}
    - *
    - * @deprecated Use {@link goog.positioning.ViewPortPosition} instead, this alias
    - *     will be removed at the end of Q1 2009.
    - */
    -goog.ui.Popup.ViewPortPosition = goog.positioning.ViewportPosition;
    -
    -
    -
    -/**
    - * Encapsulates a popup position where the popup is positioned relative to the
    - * window (client) coordinates. This calculates the correct position to
    - * use even if the element is relatively positioned to some other element. This
    - * is for trying to position an element at the spot of the mouse cursor in
    - * a MOUSEMOVE event. Just use the event.clientX and event.clientY as the
    - * parameters.
    - *
    - * @param {number|!goog.math.Coordinate} arg1 Left position or coordinate.
    - * @param {number=} opt_arg2 Top position.
    - * @constructor
    - * @extends {goog.ui.Popup.AbsolutePosition}
    - *
    - * @deprecated Use {@link goog.positioning.ClientPosition} instead, this alias
    - *     will be removed at the end of Q1 2009.
    - * @final
    - */
    -goog.ui.Popup.ClientPosition = goog.positioning.ClientPosition;
    -
    -
    -
    -/**
    - * Encapsulates a popup position where the popup is positioned relative to the
    - * window (client) coordinates, and made to stay within the viewport.
    - *
    - * @param {number|!goog.math.Coordinate} arg1 Left position or coordinate.
    - * @param {number=} opt_arg2 Top position if arg1 is a number representing the
    - *     left position, ignored otherwise.
    - * @constructor
    - * @extends {goog.ui.Popup.ClientPosition}
    - *
    - * @deprecated Use {@link goog.positioning.ViewPortClientPosition} instead, this
    - *     alias will be removed at the end of Q1 2009.
    - */
    -goog.ui.Popup.ViewPortClientPosition = goog.positioning.ViewportClientPosition;
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/popup_test.html b/src/database/third_party/closure-library/closure/goog/ui/popup_test.html
    deleted file mode 100644
    index 6c21c55bfa2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/popup_test.html
    +++ /dev/null
    @@ -1,36 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.Popup
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.PopupTest');
    -  </script>
    -  <style>
    -   #popup {
    -  position: absolute;
    -}
    -#anchor {
    -  margin-left: 100px;
    -}
    -  </style>
    - </head>
    - <body>
    -  <span id="anchor">
    -   anchor
    -  </span>
    -  <div id="popup">
    -   Popup.
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/popup_test.js b/src/database/third_party/closure-library/closure/goog/ui/popup_test.js
    deleted file mode 100644
    index aaf95d280ae..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/popup_test.js
    +++ /dev/null
    @@ -1,120 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.PopupTest');
    -goog.setTestOnly('goog.ui.PopupTest');
    -
    -goog.require('goog.positioning.AnchoredPosition');
    -goog.require('goog.positioning.Corner');
    -goog.require('goog.style');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.Popup');
    -goog.require('goog.userAgent');
    -
    -
    -/**
    - * This is used to round pixel values on FF3 Mac.
    - */
    -function assertRoundedEquals(a, b, c) {
    -  function round(x) {
    -    return goog.userAgent.GECKO && (goog.userAgent.MAC || goog.userAgent.X11) &&
    -        goog.userAgent.isVersionOrHigher('1.9') ? Math.round(x) : x;
    -  }
    -  if (arguments.length == 3) {
    -    assertEquals(a, round(b), round(c));
    -  } else {
    -    assertEquals(round(a), round(b));
    -  }
    -}
    -
    -function testCreateAndReposition() {
    -  var anchorEl = document.getElementById('anchor');
    -  var popupEl = document.getElementById('popup');
    -  var corner = goog.positioning.Corner;
    -
    -  var pos = new goog.positioning.AnchoredPosition(anchorEl,
    -                                                  corner.BOTTOM_START);
    -  var popup = new goog.ui.Popup(popupEl, pos);
    -  popup.setVisible(true);
    -
    -  var anchorRect = goog.style.getBounds(anchorEl);
    -  var popupRect = goog.style.getBounds(popupEl);
    -  assertRoundedEquals('Left edge of popup should line up with left edge ' +
    -                      'of anchor.',
    -                      anchorRect.left,
    -                      popupRect.left);
    -  assertRoundedEquals('Popup should be positioned just below the anchor.',
    -                      anchorRect.top + anchorRect.height,
    -                      popupRect.top);
    -
    -  // Reposition.
    -  anchorEl.style.marginTop = '7px';
    -  popup.reposition();
    -
    -  anchorRect = goog.style.getBounds(anchorEl);
    -  popupRect = goog.style.getBounds(popupEl);
    -  assertRoundedEquals('Popup should be positioned just below the anchor.',
    -                      anchorRect.top + anchorRect.height,
    -                      popupRect.top);
    -}
    -
    -
    -function testSetPinnedCorner() {
    -  var anchorEl = document.getElementById('anchor');
    -  var popupEl = document.getElementById('popup');
    -  var corner = goog.positioning.Corner;
    -
    -  var pos = new goog.positioning.AnchoredPosition(anchorEl,
    -                                                  corner.BOTTOM_START);
    -  var popup = new goog.ui.Popup(popupEl, pos);
    -  popup.setVisible(true);
    -
    -  var anchorRect = goog.style.getBounds(anchorEl);
    -  var popupRect = goog.style.getBounds(popupEl);
    -  assertRoundedEquals('Left edge of popup should line up with left edge ' +
    -                      'of anchor.',
    -                      anchorRect.left,
    -                      popupRect.left);
    -  assertRoundedEquals('Popup should be positioned just below the anchor.',
    -                      anchorRect.top + anchorRect.height,
    -                      popupRect.top);
    -
    -  // Change pinned corner.
    -  popup.setPinnedCorner(corner.BOTTOM_END);
    -
    -  anchorRect = goog.style.getBounds(anchorEl);
    -  popupRect = goog.style.getBounds(popupEl);
    -  assertRoundedEquals('Right edge of popup should line up with left edge ' +
    -                      'of anchor.',
    -                      anchorRect.left,
    -                      popupRect.left + popupRect.width);
    -  assertRoundedEquals('Bottom edge of popup should line up with bottom ' +
    -                      'of anchor.',
    -                      anchorRect.top + anchorRect.height,
    -                      popupRect.top + popupRect.height);
    -
    -  // Position outside the viewport.
    -  anchorEl.style.marginLeft = '0';
    -  popup.reposition();
    -
    -  anchorRect = goog.style.getBounds(anchorEl);
    -  popupRect = goog.style.getBounds(popupEl);
    -
    -  assertRoundedEquals('Right edge of popup should line up with left edge ' +
    -                      'of anchor.',
    -                      anchorRect.left,
    -                      popupRect.left + popupRect.width);
    -
    -  anchorEl.style.marginLeft = '';
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/popupbase.js b/src/database/third_party/closure-library/closure/goog/ui/popupbase.js
    deleted file mode 100644
    index 8b986221ca4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/popupbase.js
    +++ /dev/null
    @@ -1,892 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Definition of the PopupBase class.
    - *
    - */
    -
    -goog.provide('goog.ui.PopupBase');
    -goog.provide('goog.ui.PopupBase.EventType');
    -goog.provide('goog.ui.PopupBase.Type');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.fx.Transition');
    -goog.require('goog.style');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * The PopupBase class provides functionality for showing and hiding a generic
    - * container element. It also provides the option for hiding the popup element
    - * if the user clicks outside the popup or the popup loses focus.
    - *
    - * @constructor
    - * @extends {goog.events.EventTarget}
    - * @param {Element=} opt_element A DOM element for the popup.
    - * @param {goog.ui.PopupBase.Type=} opt_type Type of popup.
    - */
    -goog.ui.PopupBase = function(opt_element, opt_type) {
    -  goog.events.EventTarget.call(this);
    -
    -  /**
    -   * An event handler to manage the events easily
    -   * @type {goog.events.EventHandler<!goog.ui.PopupBase>}
    -   * @private
    -   */
    -  this.handler_ = new goog.events.EventHandler(this);
    -
    -  this.setElement(opt_element || null);
    -  if (opt_type) {
    -    this.setType(opt_type);
    -  }
    -};
    -goog.inherits(goog.ui.PopupBase, goog.events.EventTarget);
    -goog.tagUnsealableClass(goog.ui.PopupBase);
    -
    -
    -/**
    - * Constants for type of Popup
    - * @enum {string}
    - */
    -goog.ui.PopupBase.Type = {
    -  TOGGLE_DISPLAY: 'toggle_display',
    -  MOVE_OFFSCREEN: 'move_offscreen'
    -};
    -
    -
    -/**
    - * The popup dom element that this Popup wraps.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.PopupBase.prototype.element_ = null;
    -
    -
    -/**
    - * Whether the Popup dismisses itself it the user clicks outside of it or the
    - * popup loses focus
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.PopupBase.prototype.autoHide_ = true;
    -
    -
    -/**
    - * Mouse events without auto hide partner elements will not dismiss the popup.
    - * @type {Array<Element>}
    - * @private
    - */
    -goog.ui.PopupBase.prototype.autoHidePartners_ = null;
    -
    -
    -/**
    - * Clicks outside the popup but inside this element will cause the popup to
    - * hide if autoHide_ is true. If this is null, then the entire document is used.
    - * For example, you can use a body-size div so that clicks on the browser
    - * scrollbar do not dismiss the popup.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.PopupBase.prototype.autoHideRegion_ = null;
    -
    -
    -/**
    - * Whether the popup is currently being shown.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.PopupBase.prototype.isVisible_ = false;
    -
    -
    -/**
    - * Whether the popup should hide itself asynchrously. This was added because
    - * there are cases where hiding the element in mouse down handler in IE can
    - * cause textinputs to get into a bad state if the element that had focus is
    - * hidden.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.PopupBase.prototype.shouldHideAsync_ = false;
    -
    -
    -/**
    - * The time when the popup was last shown.
    - * @type {number}
    - * @private
    - */
    -goog.ui.PopupBase.prototype.lastShowTime_ = -1;
    -
    -
    -/**
    - * The time when the popup was last hidden.
    - * @type {number}
    - * @private
    - */
    -goog.ui.PopupBase.prototype.lastHideTime_ = -1;
    -
    -
    -/**
    - * Whether to hide when the escape key is pressed.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.PopupBase.prototype.hideOnEscape_ = false;
    -
    -
    -/**
    - * Whether to enable cross-iframe dismissal.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.PopupBase.prototype.enableCrossIframeDismissal_ = true;
    -
    -
    -/**
    - * The type of popup
    - * @type {goog.ui.PopupBase.Type}
    - * @private
    - */
    -goog.ui.PopupBase.prototype.type_ = goog.ui.PopupBase.Type.TOGGLE_DISPLAY;
    -
    -
    -/**
    - * Transition to play on showing the popup.
    - * @type {goog.fx.Transition|undefined}
    - * @private
    - */
    -goog.ui.PopupBase.prototype.showTransition_;
    -
    -
    -/**
    - * Transition to play on hiding the popup.
    - * @type {goog.fx.Transition|undefined}
    - * @private
    - */
    -goog.ui.PopupBase.prototype.hideTransition_;
    -
    -
    -/**
    - * Constants for event type fired by Popup
    - *
    - * @enum {string}
    - */
    -goog.ui.PopupBase.EventType = {
    -  BEFORE_SHOW: 'beforeshow',
    -  SHOW: 'show',
    -  BEFORE_HIDE: 'beforehide',
    -  HIDE: 'hide'
    -};
    -
    -
    -/**
    - * A time in ms used to debounce events that happen right after each other.
    - *
    - * A note about why this is necessary. There are two cases to consider.
    - * First case, a popup will usually see a focus event right after it's launched
    - * because it's typical for it to be launched in a mouse-down event which will
    - * then move focus to the launching button. We don't want to think this is a
    - * separate user action moving focus. Second case, a user clicks on the
    - * launcher button to close the menu. In that case, we'll close the menu in the
    - * focus event and then show it again because of the mouse down event, even
    - * though the intention is to just close the menu. This workaround appears to
    - * be the least intrusive fix.
    - *
    - * @type {number}
    - */
    -goog.ui.PopupBase.DEBOUNCE_DELAY_MS = 150;
    -
    -
    -/**
    - * @return {goog.ui.PopupBase.Type} The type of popup this is.
    - */
    -goog.ui.PopupBase.prototype.getType = function() {
    -  return this.type_;
    -};
    -
    -
    -/**
    - * Specifies the type of popup to use.
    - *
    - * @param {goog.ui.PopupBase.Type} type Type of popup.
    - */
    -goog.ui.PopupBase.prototype.setType = function(type) {
    -  this.type_ = type;
    -};
    -
    -
    -/**
    - * Returns whether the popup should hide itself asynchronously using a timeout
    - * instead of synchronously.
    - * @return {boolean} Whether to hide async.
    - */
    -goog.ui.PopupBase.prototype.shouldHideAsync = function() {
    -  return this.shouldHideAsync_;
    -};
    -
    -
    -/**
    - * Sets whether the popup should hide itself asynchronously using a timeout
    - * instead of synchronously.
    - * @param {boolean} b Whether to hide async.
    - */
    -goog.ui.PopupBase.prototype.setShouldHideAsync = function(b) {
    -  this.shouldHideAsync_ = b;
    -};
    -
    -
    -/**
    - * Returns the dom element that should be used for the popup.
    - *
    - * @return {Element} The popup element.
    - */
    -goog.ui.PopupBase.prototype.getElement = function() {
    -  return this.element_;
    -};
    -
    -
    -/**
    - * Specifies the dom element that should be used for the popup.
    - *
    - * @param {Element} elt A DOM element for the popup.
    - */
    -goog.ui.PopupBase.prototype.setElement = function(elt) {
    -  this.ensureNotVisible_();
    -  this.element_ = elt;
    -};
    -
    -
    -/**
    - * Returns whether the Popup dismisses itself when the user clicks outside of
    - * it.
    - * @return {boolean} Whether the Popup autohides on an external click.
    - */
    -goog.ui.PopupBase.prototype.getAutoHide = function() {
    -  return this.autoHide_;
    -};
    -
    -
    -/**
    - * Sets whether the Popup dismisses itself when the user clicks outside of it.
    - * @param {boolean} autoHide Whether to autohide on an external click.
    - */
    -goog.ui.PopupBase.prototype.setAutoHide = function(autoHide) {
    -  this.ensureNotVisible_();
    -  this.autoHide_ = autoHide;
    -};
    -
    -
    -/**
    - * Mouse events that occur within an autoHide partner will not hide a popup
    - * set to autoHide.
    - * @param {!Element} partner The auto hide partner element.
    - */
    -goog.ui.PopupBase.prototype.addAutoHidePartner = function(partner) {
    -  if (!this.autoHidePartners_) {
    -    this.autoHidePartners_ = [];
    -  }
    -
    -  goog.array.insert(this.autoHidePartners_, partner);
    -};
    -
    -
    -/**
    - * Removes a previously registered auto hide partner.
    - * @param {!Element} partner The auto hide partner element.
    - */
    -goog.ui.PopupBase.prototype.removeAutoHidePartner = function(partner) {
    -  if (this.autoHidePartners_) {
    -    goog.array.remove(this.autoHidePartners_, partner);
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the Popup autohides on the escape key.
    - */
    -goog.ui.PopupBase.prototype.getHideOnEscape = function() {
    -  return this.hideOnEscape_;
    -};
    -
    -
    -/**
    - * Sets whether the Popup dismisses itself on the escape key.
    - * @param {boolean} hideOnEscape Whether to autohide on the escape key.
    - */
    -goog.ui.PopupBase.prototype.setHideOnEscape = function(hideOnEscape) {
    -  this.ensureNotVisible_();
    -  this.hideOnEscape_ = hideOnEscape;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether cross iframe dismissal is enabled.
    - */
    -goog.ui.PopupBase.prototype.getEnableCrossIframeDismissal = function() {
    -  return this.enableCrossIframeDismissal_;
    -};
    -
    -
    -/**
    - * Sets whether clicks in other iframes should dismiss this popup.  In some
    - * cases it should be disabled, because it can cause spurious
    - * @param {boolean} enable Whether to enable cross iframe dismissal.
    - */
    -goog.ui.PopupBase.prototype.setEnableCrossIframeDismissal = function(enable) {
    -  this.enableCrossIframeDismissal_ = enable;
    -};
    -
    -
    -/**
    - * Returns the region inside which the Popup dismisses itself when the user
    - * clicks, or null if it's the entire document.
    - * @return {Element} The DOM element for autohide, or null if it hasn't been
    - *     set.
    - */
    -goog.ui.PopupBase.prototype.getAutoHideRegion = function() {
    -  return this.autoHideRegion_;
    -};
    -
    -
    -/**
    - * Sets the region inside which the Popup dismisses itself when the user
    - * clicks.
    - * @param {Element} element The DOM element for autohide.
    - */
    -goog.ui.PopupBase.prototype.setAutoHideRegion = function(element) {
    -  this.autoHideRegion_ = element;
    -};
    -
    -
    -/**
    - * Sets transition animation on showing and hiding the popup.
    - * @param {goog.fx.Transition=} opt_showTransition Transition to play on
    - *     showing the popup.
    - * @param {goog.fx.Transition=} opt_hideTransition Transition to play on
    - *     hiding the popup.
    - */
    -goog.ui.PopupBase.prototype.setTransition = function(
    -    opt_showTransition, opt_hideTransition) {
    -  this.showTransition_ = opt_showTransition;
    -  this.hideTransition_ = opt_hideTransition;
    -};
    -
    -
    -/**
    - * Returns the time when the popup was last shown.
    - *
    - * @return {number} time in ms since epoch when the popup was last shown, or
    - * -1 if the popup was never shown.
    - */
    -goog.ui.PopupBase.prototype.getLastShowTime = function() {
    -  return this.lastShowTime_;
    -};
    -
    -
    -/**
    - * Returns the time when the popup was last hidden.
    - *
    - * @return {number} time in ms since epoch when the popup was last hidden, or
    - * -1 if the popup was never hidden or is currently showing.
    - */
    -goog.ui.PopupBase.prototype.getLastHideTime = function() {
    -  return this.lastHideTime_;
    -};
    -
    -
    -/**
    - * Returns the event handler for the popup. All event listeners belonging to
    - * this handler are removed when the tooltip is hidden. Therefore,
    - * the recommended usage of this handler is to listen on events in
    - * {@link #onShow_}.
    - * @return {goog.events.EventHandler<T>} Event handler for this popup.
    - * @protected
    - * @this T
    - * @template T
    - */
    -goog.ui.PopupBase.prototype.getHandler = function() {
    -  // As the template type is unbounded, narrow the "this" type
    -  var self = /** @type {!goog.ui.PopupBase} */ (this);
    -
    -  return self.handler_;
    -};
    -
    -
    -/**
    - * Helper to throw exception if the popup is showing.
    - * @private
    - */
    -goog.ui.PopupBase.prototype.ensureNotVisible_ = function() {
    -  if (this.isVisible_) {
    -    throw Error('Can not change this state of the popup while showing.');
    -  }
    -};
    -
    -
    -/**
    - * Returns whether the popup is currently visible.
    - *
    - * @return {boolean} whether the popup is currently visible.
    - */
    -goog.ui.PopupBase.prototype.isVisible = function() {
    -  return this.isVisible_;
    -};
    -
    -
    -/**
    - * Returns whether the popup is currently visible or was visible within about
    - * 150 ms ago. This is used by clients to handle a very specific, but common,
    - * popup scenario. The button that launches the popup should close the popup
    - * on mouse down if the popup is alrady open. The problem is that the popup
    - * closes itself during the capture phase of the mouse down and thus the button
    - * thinks it's hidden and this should show it again. This method provides a
    - * good heuristic for clients. Typically in their event handler they will have
    - * code that is:
    - *
    - * if (menu.isOrWasRecentlyVisible()) {
    - *   menu.setVisible(false);
    - * } else {
    - *   ... // code to position menu and initialize other state
    - *   menu.setVisible(true);
    - * }
    - * @return {boolean} Whether the popup is currently visible or was visible
    - *     within about 150 ms ago.
    - */
    -goog.ui.PopupBase.prototype.isOrWasRecentlyVisible = function() {
    -  return this.isVisible_ ||
    -         (goog.now() - this.lastHideTime_ <
    -          goog.ui.PopupBase.DEBOUNCE_DELAY_MS);
    -};
    -
    -
    -/**
    - * Sets whether the popup should be visible. After this method
    - * returns, isVisible() will always return the new state, even if
    - * there is a transition.
    - *
    - * @param {boolean} visible Desired visibility state.
    - */
    -goog.ui.PopupBase.prototype.setVisible = function(visible) {
    -  // Make sure that any currently running transition is stopped.
    -  if (this.showTransition_) this.showTransition_.stop();
    -  if (this.hideTransition_) this.hideTransition_.stop();
    -
    -  if (visible) {
    -    this.show_();
    -  } else {
    -    this.hide_();
    -  }
    -};
    -
    -
    -/**
    - * Repositions the popup according to the current state.
    - * Should be overriden by subclases.
    - */
    -goog.ui.PopupBase.prototype.reposition = goog.nullFunction;
    -
    -
    -/**
    - * Does the work to show the popup.
    - * @private
    - */
    -goog.ui.PopupBase.prototype.show_ = function() {
    -  // Ignore call if we are already showing.
    -  if (this.isVisible_) {
    -    return;
    -  }
    -
    -  // Give derived classes and handlers a chance to customize popup.
    -  if (!this.onBeforeShow()) {
    -    return;
    -  }
    -
    -  // Allow callers to set the element in the BEFORE_SHOW event.
    -  if (!this.element_) {
    -    throw Error('Caller must call setElement before trying to show the popup');
    -  }
    -
    -  // Call reposition after onBeforeShow, as it may change the style and/or
    -  // content of the popup and thereby affecting the size which is used for the
    -  // viewport calculation.
    -  this.reposition();
    -
    -  var doc = goog.dom.getOwnerDocument(this.element_);
    -
    -  if (this.hideOnEscape_) {
    -
    -    // Handle the escape keys.  Listen in the capture phase so that we can
    -    // stop the escape key from propagating to other elements.  For example,
    -    // if there is a popup within a dialog box, we want the popup to be
    -    // dismissed first, rather than the dialog.
    -    this.handler_.listen(doc, goog.events.EventType.KEYDOWN,
    -        this.onDocumentKeyDown_, true);
    -  }
    -
    -  // Set up event handlers.
    -  if (this.autoHide_) {
    -
    -    // Even if the popup is not in the focused document, we want to
    -    // close it on mousedowns in the document it's in.
    -    this.handler_.listen(doc, goog.events.EventType.MOUSEDOWN,
    -        this.onDocumentMouseDown_, true);
    -
    -    if (goog.userAgent.IE) {
    -      // We want to know about deactivates/mousedowns on the document with focus
    -      // The top-level document won't get a deactivate event if the focus is
    -      // in an iframe and the deactivate fires within that iframe.
    -      // The active element in the top-level document will remain the iframe
    -      // itself.
    -      var activeElement;
    -      /** @preserveTry */
    -      try {
    -        activeElement = doc.activeElement;
    -      } catch (e) {
    -        // There is an IE browser bug which can cause just the reading of
    -        // document.activeElement to throw an Unspecified Error.  This
    -        // may have to do with loading a popup within a hidden iframe.
    -      }
    -      while (activeElement && activeElement.nodeName == 'IFRAME') {
    -        /** @preserveTry */
    -        try {
    -          var tempDoc = goog.dom.getFrameContentDocument(activeElement);
    -        } catch (e) {
    -          // The frame is on a different domain that its parent document
    -          // This way, we grab the lowest-level document object we can get
    -          // a handle on given cross-domain security.
    -          break;
    -        }
    -        doc = tempDoc;
    -        activeElement = doc.activeElement;
    -      }
    -
    -      // Handle mousedowns in the focused document in case the user clicks
    -      // on the activeElement (in which case the popup should hide).
    -      this.handler_.listen(doc, goog.events.EventType.MOUSEDOWN,
    -          this.onDocumentMouseDown_, true);
    -
    -      // If the active element inside the focused document changes, then
    -      // we probably need to hide the popup.
    -      this.handler_.listen(doc, goog.events.EventType.DEACTIVATE,
    -          this.onDocumentBlur_);
    -
    -    } else {
    -      this.handler_.listen(doc, goog.events.EventType.BLUR,
    -          this.onDocumentBlur_);
    -    }
    -  }
    -
    -  // Make the popup visible.
    -  if (this.type_ == goog.ui.PopupBase.Type.TOGGLE_DISPLAY) {
    -    this.showPopupElement();
    -  } else if (this.type_ == goog.ui.PopupBase.Type.MOVE_OFFSCREEN) {
    -    this.reposition();
    -  }
    -  this.isVisible_ = true;
    -
    -  this.lastShowTime_ = goog.now();
    -  this.lastHideTime_ = -1;
    -
    -  // If there is transition to play, we play it and fire SHOW event after
    -  // the transition is over.
    -  if (this.showTransition_) {
    -    goog.events.listenOnce(
    -        /** @type {!goog.events.EventTarget} */ (this.showTransition_),
    -        goog.fx.Transition.EventType.END, this.onShow_, false, this);
    -    this.showTransition_.play();
    -  } else {
    -    // Notify derived classes and handlers.
    -    this.onShow_();
    -  }
    -};
    -
    -
    -/**
    - * Hides the popup. This call is idempotent.
    - *
    - * @param {Object=} opt_target Target of the event causing the hide.
    - * @return {boolean} Whether the popup was hidden and not cancelled.
    - * @private
    - */
    -goog.ui.PopupBase.prototype.hide_ = function(opt_target) {
    -  // Give derived classes and handlers a chance to cancel hiding.
    -  if (!this.isVisible_ || !this.onBeforeHide_(opt_target)) {
    -    return false;
    -  }
    -
    -  // Remove any listeners we attached when showing the popup.
    -  if (this.handler_) {
    -    this.handler_.removeAll();
    -  }
    -
    -  // Set visibility to hidden even if there is a transition.
    -  this.isVisible_ = false;
    -  this.lastHideTime_ = goog.now();
    -
    -  // If there is transition to play, we play it and only hide the element
    -  // (and fire HIDE event) after the transition is over.
    -  if (this.hideTransition_) {
    -    goog.events.listenOnce(
    -        /** @type {!goog.events.EventTarget} */ (this.hideTransition_),
    -        goog.fx.Transition.EventType.END,
    -        goog.partial(this.continueHidingPopup_, opt_target), false, this);
    -    this.hideTransition_.play();
    -  } else {
    -    this.continueHidingPopup_(opt_target);
    -  }
    -
    -  return true;
    -};
    -
    -
    -/**
    - * Continues hiding the popup. This is a continuation from hide_. It is
    - * a separate method so that we can add a transition before hiding.
    - * @param {Object=} opt_target Target of the event causing the hide.
    - * @private
    - */
    -goog.ui.PopupBase.prototype.continueHidingPopup_ = function(opt_target) {
    -  // Hide the popup.
    -  if (this.type_ == goog.ui.PopupBase.Type.TOGGLE_DISPLAY) {
    -    if (this.shouldHideAsync_) {
    -      goog.Timer.callOnce(this.hidePopupElement, 0, this);
    -    } else {
    -      this.hidePopupElement();
    -    }
    -  } else if (this.type_ == goog.ui.PopupBase.Type.MOVE_OFFSCREEN) {
    -    this.moveOffscreen_();
    -  }
    -
    -  // Notify derived classes and handlers.
    -  this.onHide_(opt_target);
    -};
    -
    -
    -/**
    - * Shows the popup element.
    - * @protected
    - */
    -goog.ui.PopupBase.prototype.showPopupElement = function() {
    -  this.element_.style.visibility = 'visible';
    -  goog.style.setElementShown(this.element_, true);
    -};
    -
    -
    -/**
    - * Hides the popup element.
    - * @protected
    - */
    -goog.ui.PopupBase.prototype.hidePopupElement = function() {
    -  this.element_.style.visibility = 'hidden';
    -  goog.style.setElementShown(this.element_, false);
    -};
    -
    -
    -/**
    - * Hides the popup by moving it offscreen.
    - *
    - * @private
    - */
    -goog.ui.PopupBase.prototype.moveOffscreen_ = function() {
    -  this.element_.style.top = '-10000px';
    -};
    -
    -
    -/**
    - * Called before the popup is shown. Derived classes can override to hook this
    - * event but should make sure to call the parent class method.
    - *
    - * @return {boolean} If anyone called preventDefault on the event object (or
    - *     if any of the handlers returns false this will also return false.
    - * @protected
    - */
    -goog.ui.PopupBase.prototype.onBeforeShow = function() {
    -  return this.dispatchEvent(goog.ui.PopupBase.EventType.BEFORE_SHOW);
    -};
    -
    -
    -/**
    - * Called after the popup is shown. Derived classes can override to hook this
    - * event but should make sure to call the parent class method.
    - * @protected
    - * @suppress {underscore|visibility}
    - */
    -goog.ui.PopupBase.prototype.onShow_ = function() {
    -  this.dispatchEvent(goog.ui.PopupBase.EventType.SHOW);
    -};
    -
    -
    -/**
    - * Called before the popup is hidden. Derived classes can override to hook this
    - * event but should make sure to call the parent class method.
    - *
    - * @param {Object=} opt_target Target of the event causing the hide.
    - * @return {boolean} If anyone called preventDefault on the event object (or
    - *     if any of the handlers returns false this will also return false.
    - * @protected
    - * @suppress {underscore|visibility}
    - */
    -goog.ui.PopupBase.prototype.onBeforeHide_ = function(opt_target) {
    -  return this.dispatchEvent({
    -    type: goog.ui.PopupBase.EventType.BEFORE_HIDE,
    -    target: opt_target
    -  });
    -};
    -
    -
    -/**
    - * Called after the popup is hidden. Derived classes can override to hook this
    - * event but should make sure to call the parent class method.
    - * @param {Object=} opt_target Target of the event causing the hide.
    - * @protected
    - * @suppress {underscore|visibility}
    - */
    -goog.ui.PopupBase.prototype.onHide_ = function(opt_target) {
    -  this.dispatchEvent({
    -    type: goog.ui.PopupBase.EventType.HIDE,
    -    target: opt_target
    -  });
    -};
    -
    -
    -/**
    - * Mouse down handler for the document on capture phase. Used to hide the
    - * popup for auto-hide mode.
    - *
    - * @param {goog.events.BrowserEvent} e The event object.
    - * @private
    - */
    -goog.ui.PopupBase.prototype.onDocumentMouseDown_ = function(e) {
    -  var target = /** @type {Node} */ (e.target);
    -
    -  if (!goog.dom.contains(this.element_, target) &&
    -      !this.isOrWithinAutoHidePartner_(target) &&
    -      this.isWithinAutoHideRegion_(target) &&
    -      !this.shouldDebounce_()) {
    -
    -    // Mouse click was outside popup and partners, so hide.
    -    this.hide_(target);
    -  }
    -};
    -
    -
    -/**
    - * Handles key-downs on the document to handle the escape key.
    - *
    - * @param {goog.events.BrowserEvent} e The event object.
    - * @private
    - */
    -goog.ui.PopupBase.prototype.onDocumentKeyDown_ = function(e) {
    -  if (e.keyCode == goog.events.KeyCodes.ESC) {
    -    if (this.hide_(e.target)) {
    -      // Eat the escape key, but only if this popup was actually closed.
    -      e.preventDefault();
    -      e.stopPropagation();
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Deactivate handler(IE) and blur handler (other browsers) for document.
    - * Used to hide the popup for auto-hide mode.
    - *
    - * @param {goog.events.BrowserEvent} e The event object.
    - * @private
    - */
    -goog.ui.PopupBase.prototype.onDocumentBlur_ = function(e) {
    -  if (!this.enableCrossIframeDismissal_) {
    -    return;
    -  }
    -
    -  var doc = goog.dom.getOwnerDocument(this.element_);
    -
    -  // Ignore blur events if the active element is still inside the popup or if
    -  // there is no longer an active element.  For example, a widget like a
    -  // goog.ui.Button might programatically blur itself before losing tabIndex.
    -  if (typeof document.activeElement != 'undefined') {
    -    var activeElement = doc.activeElement;
    -    if (!activeElement || goog.dom.contains(this.element_,
    -        activeElement) || activeElement.tagName == 'BODY') {
    -      return;
    -    }
    -
    -  // Ignore blur events not for the document itself in non-IE browsers.
    -  } else if (e.target != doc) {
    -    return;
    -  }
    -
    -  // Debounce the initial focus move.
    -  if (this.shouldDebounce_()) {
    -    return;
    -  }
    -
    -  this.hide_();
    -};
    -
    -
    -/**
    - * @param {Node} element The element to inspect.
    - * @return {boolean} Returns true if the given element is one of the auto hide
    - *     partners or is a child of an auto hide partner.
    - * @private
    - */
    -goog.ui.PopupBase.prototype.isOrWithinAutoHidePartner_ = function(element) {
    -  return goog.array.some(this.autoHidePartners_ || [], function(partner) {
    -    return element === partner || goog.dom.contains(partner, element);
    -  });
    -};
    -
    -
    -/**
    - * @param {Node} element The element to inspect.
    - * @return {boolean} Returns true if the element is contained within
    - *     the autohide region. If unset, the autohide region is the entire
    - *     entire document.
    - * @private
    - */
    -goog.ui.PopupBase.prototype.isWithinAutoHideRegion_ = function(element) {
    -  return this.autoHideRegion_ ?
    -      goog.dom.contains(this.autoHideRegion_, element) : true;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the time since last show is less than the debounce
    - *     delay.
    - * @private
    - */
    -goog.ui.PopupBase.prototype.shouldDebounce_ = function() {
    -  return goog.now() - this.lastShowTime_ < goog.ui.PopupBase.DEBOUNCE_DELAY_MS;
    -};
    -
    -
    -/** @override */
    -goog.ui.PopupBase.prototype.disposeInternal = function() {
    -  goog.ui.PopupBase.base(this, 'disposeInternal');
    -  this.handler_.dispose();
    -  goog.dispose(this.showTransition_);
    -  goog.dispose(this.hideTransition_);
    -  delete this.element_;
    -  delete this.handler_;
    -  delete this.autoHidePartners_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/popupbase_test.html b/src/database/third_party/closure-library/closure/goog/ui/popupbase_test.html
    deleted file mode 100644
    index 4967a37f89e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/popupbase_test.html
    +++ /dev/null
    @@ -1,47 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -  Author: gboyer@google.com (Garrett Boyer)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.PopupBase
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.PopupBaseTest');
    -  </script>
    -  <style>
    -   #moveOffscreenPopupDiv {
    -  position: absolute;
    -  width: 300px;
    -  height: 300px;
    -  top: -1000px;
    -}
    -  </style>
    - </head>
    - <body>
    -  <div id="commonAncestor">
    -   <div id="targetDiv">
    -    Mouse and key target
    -   </div>
    -   <div id="partnerDiv">
    -    Auto-hide partner
    -   </div>
    -   <div id="popupDiv" style="visibility:hidden">
    -    Popup Contents Here.
    -   </div>
    -   <div id="moveOffscreenPopupDiv">
    -    Move offscreen popup contents here.
    -   </div>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/popupbase_test.js b/src/database/third_party/closure-library/closure/goog/ui/popupbase_test.js
    deleted file mode 100644
    index d96e4f372c7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/popupbase_test.js
    +++ /dev/null
    @@ -1,485 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.PopupBaseTest');
    -goog.setTestOnly('goog.ui.PopupBaseTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.fx.Transition');
    -goog.require('goog.fx.css3');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.events.Event');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.PopupBase');
    -
    -var targetDiv;
    -var popupDiv;
    -var partnerDiv;
    -var clock;
    -var popup;
    -
    -function setUpPage() {
    -  targetDiv = goog.dom.getElement('targetDiv');
    -  popupDiv = goog.dom.getElement('popupDiv');
    -  partnerDiv = goog.dom.getElement('partnerDiv');
    -}
    -
    -function setUp() {
    -  popup = new goog.ui.PopupBase(popupDiv);
    -  clock = new goog.testing.MockClock(true);
    -}
    -
    -function tearDown() {
    -  popup.dispose();
    -  clock.uninstall();
    -  document.body.setAttribute('dir', 'ltr');
    -}
    -
    -function testSetVisible() {
    -  popup.setVisible(true);
    -  assertEquals('visible', popupDiv.style.visibility);
    -  assertEquals('', popupDiv.style.display);
    -  popup.setVisible(false);
    -  assertEquals('hidden', popupDiv.style.visibility);
    -  assertEquals('none', popupDiv.style.display);
    -}
    -
    -function testEscapeDismissal() {
    -  popup.setHideOnEscape(true);
    -  assertTrue('Sanity check that getHideOnEscape is true when set to true.',
    -      popup.getHideOnEscape());
    -  popup.setVisible(true);
    -  assertFalse('Escape key should be cancelled',
    -      goog.testing.events.fireKeySequence(
    -          targetDiv, goog.events.KeyCodes.ESC));
    -  assertFalse(popup.isVisible());
    -}
    -
    -function testEscapeDismissalCanBeDisabled() {
    -  popup.setHideOnEscape(false);
    -  popup.setVisible(true);
    -  assertTrue('Escape key should be cancelled',
    -      goog.testing.events.fireKeySequence(
    -          targetDiv, goog.events.KeyCodes.ESC));
    -  assertTrue(popup.isVisible());
    -}
    -
    -function testEscapeDismissalIsDisabledByDefault() {
    -  assertFalse(popup.getHideOnEscape());
    -}
    -
    -function testEscapeDismissalDoesNotRecognizeOtherKeys() {
    -  popup.setHideOnEscape(true);
    -  popup.setVisible(true);
    -  var eventsPropagated = 0;
    -  goog.events.listenOnce(goog.dom.getElement('commonAncestor'),
    -      [goog.events.EventType.KEYDOWN,
    -       goog.events.EventType.KEYUP,
    -       goog.events.EventType.KEYPRESS],
    -      function() {
    -        ++eventsPropagated;
    -      });
    -  assertTrue('Popup should remain visible', popup.isVisible());
    -  assertTrue('The key event default action should not be prevented',
    -      goog.testing.events.fireKeySequence(
    -          targetDiv, goog.events.KeyCodes.A));
    -  assertEquals('Keydown, keyup, and keypress should have all propagated',
    -      3, eventsPropagated);
    -}
    -
    -function testEscapeDismissalCanBeCancelledByBeforeHideEvent() {
    -  popup.setHideOnEscape(true);
    -  popup.setVisible(true);
    -  var eventsPropagated = 0;
    -  goog.events.listenOnce(goog.dom.getElement('commonAncestor'),
    -      goog.events.EventType.KEYDOWN,
    -      function() {
    -        ++eventsPropagated;
    -      });
    -  // Make a listener so that we stop hiding with an event handler.
    -  goog.events.listenOnce(popup, goog.ui.PopupBase.EventType.BEFORE_HIDE,
    -      function(e) {
    -        e.preventDefault();
    -      });
    -  assertEquals('The hide should have been cancelled',
    -      true, popup.isVisible());
    -  assertTrue('The key event default action should not be prevented',
    -      goog.testing.events.fireKeySequence(
    -          targetDiv, goog.events.KeyCodes.ESC));
    -  assertEquals('Keydown should have all propagated',
    -      1, eventsPropagated);
    -}
    -
    -function testEscapeDismissalProvidesKeyTargetAsTargetForHideEvents() {
    -  popup.setHideOnEscape(true);
    -  popup.setVisible(true);
    -  var calls = 0;
    -  goog.events.listenOnce(popup,
    -      [goog.ui.PopupBase.EventType.BEFORE_HIDE,
    -       goog.ui.PopupBase.EventType.HIDE],
    -      function(e) {
    -        calls++;
    -        assertEquals('The key target should be the hide event target',
    -            'targetDiv', e.target.id);
    -      });
    -  goog.testing.events.fireKeySequence(
    -      targetDiv, goog.events.KeyCodes.ESC);
    -}
    -
    -function testAutoHide() {
    -  popup.setAutoHide(true);
    -  popup.setVisible(true);
    -  clock.tick(1000); // avoid bouncing
    -  goog.testing.events.fireClickSequence(targetDiv);
    -  assertFalse(popup.isVisible());
    -}
    -
    -function testAutoHideCanBeDisabled() {
    -  popup.setAutoHide(false);
    -  popup.setVisible(true);
    -  clock.tick(1000); // avoid bouncing
    -  goog.testing.events.fireClickSequence(targetDiv);
    -  assertTrue(
    -      'Should not be hidden if auto hide is disabled', popup.isVisible());
    -}
    -
    -function testAutoHideEnabledByDefault() {
    -  assertTrue(popup.getAutoHide());
    -}
    -
    -function testAutoHideWithPartners() {
    -  popup.setAutoHide(true);
    -  popup.setVisible(true);
    -  popup.addAutoHidePartner(targetDiv);
    -  popup.addAutoHidePartner(partnerDiv);
    -  clock.tick(1000); // avoid bouncing
    -
    -  goog.testing.events.fireClickSequence(targetDiv);
    -  assertTrue(popup.isVisible());
    -  goog.testing.events.fireClickSequence(partnerDiv);
    -  assertTrue(popup.isVisible());
    -
    -  popup.removeAutoHidePartner(partnerDiv);
    -  goog.testing.events.fireClickSequence(partnerDiv);
    -  assertFalse(popup.isVisible());
    -}
    -
    -function testCanAddElementDuringBeforeShow() {
    -  popup.setElement(null);
    -  goog.events.listenOnce(popup, goog.ui.PopupBase.EventType.BEFORE_SHOW,
    -      function() {
    -        popup.setElement(popupDiv);
    -      });
    -  popup.setVisible(true);
    -  assertTrue('Popup should be shown', popup.isVisible());
    -}
    -
    -function testShowWithNoElementThrowsException() {
    -  popup.setElement(null);
    -  var e = assertThrows(function() {
    -    popup.setVisible(true);
    -  });
    -  assertEquals('Caller must call setElement before trying to show the popup',
    -      e.message);
    -}
    -
    -function testShowEventFiredWithNoTransition() {
    -  var showHandlerCalled = false;
    -  goog.events.listen(popup, goog.ui.PopupBase.EventType.SHOW, function() {
    -    showHandlerCalled = true;
    -  });
    -
    -  popup.setVisible(true);
    -  assertTrue(showHandlerCalled);
    -}
    -
    -function testHideEventFiredWithNoTransition() {
    -  var hideHandlerCalled = false;
    -  goog.events.listen(popup, goog.ui.PopupBase.EventType.HIDE, function() {
    -    hideHandlerCalled = true;
    -  });
    -
    -  popup.setVisible(true);
    -  popup.setVisible(false);
    -  assertTrue(hideHandlerCalled);
    -}
    -
    -function testOnShowTransition() {
    -  var mockTransition = new MockTransition();
    -
    -  var showHandlerCalled = false;
    -  goog.events.listen(popup, goog.ui.PopupBase.EventType.SHOW, function() {
    -    showHandlerCalled = true;
    -  });
    -
    -  popup.setTransition(mockTransition);
    -  popup.setVisible(true);
    -  assertTrue(mockTransition.wasPlayed);
    -
    -  assertFalse(showHandlerCalled);
    -  mockTransition.dispatchEvent(goog.fx.Transition.EventType.END);
    -  assertTrue(showHandlerCalled);
    -}
    -
    -function testOnHideTransition() {
    -  var mockTransition = new MockTransition();
    -
    -  var hideHandlerCalled = false;
    -  goog.events.listen(popup, goog.ui.PopupBase.EventType.HIDE, function() {
    -    hideHandlerCalled = true;
    -  });
    -
    -  popup.setTransition(undefined, mockTransition);
    -  popup.setVisible(true);
    -  assertFalse(mockTransition.wasPlayed);
    -
    -  popup.setVisible(false);
    -  assertTrue(mockTransition.wasPlayed);
    -
    -  assertFalse(hideHandlerCalled);
    -  mockTransition.dispatchEvent(goog.fx.Transition.EventType.END);
    -  assertTrue(hideHandlerCalled);
    -}
    -
    -function testSetVisibleWorksCorrectlyWithTransitions() {
    -  popup.setTransition(
    -      goog.fx.css3.fadeIn(popup.getElement(), 1),
    -      goog.fx.css3.fadeOut(popup.getElement(), 1));
    -
    -  // Consecutive calls to setVisible works without needing to wait for
    -  // transition to finish.
    -  popup.setVisible(true);
    -  assertTrue(popup.isVisible());
    -  popup.setVisible(false);
    -  assertFalse(popup.isVisible());
    -  clock.tick(1100);
    -
    -  // Calling setVisible(true) immediately changed the state to visible.
    -  popup.setVisible(true);
    -  assertTrue(popup.isVisible());
    -  clock.tick(1100);
    -
    -  // Consecutive calls to setVisible, in opposite order.
    -  popup.setVisible(false);
    -  popup.setVisible(true);
    -  assertTrue(popup.isVisible());
    -  clock.tick(1100);
    -
    -  // Calling setVisible(false) immediately changed the state to not visible.
    -  popup.setVisible(false);
    -  assertFalse(popup.isVisible());
    -  clock.tick(1100);
    -}
    -
    -function testWasRecentlyVisibleWorksCorrectlyWithTransitions() {
    -  popup.setTransition(
    -      goog.fx.css3.fadeIn(popup.getElement(), 1),
    -      goog.fx.css3.fadeOut(popup.getElement(), 1));
    -
    -  popup.setVisible(true);
    -  clock.tick(1100);
    -  popup.setVisible(false);
    -  assertTrue(popup.isOrWasRecentlyVisible());
    -  clock.tick(goog.ui.PopupBase.DEBOUNCE_DELAY_MS);
    -  assertFalse(popup.isOrWasRecentlyVisible());
    -}
    -
    -function testMoveOffscreenRTL() {
    -  document.body.setAttribute('dir', 'rtl');
    -  popup.reposition = function() {
    -    this.element_.style.left = '100px';
    -    this.element_.style.top = '100px';
    -  };
    -  popup.setType(goog.ui.PopupBase.Type.MOVE_OFFSCREEN);
    -  popup.setElement(goog.dom.getElement('moveOffscreenPopupDiv'));
    -  originalScrollWidth = goog.dom.getDocumentScrollElement().scrollWidth;
    -  popup.setVisible(true);
    -  popup.setVisible(false);
    -  assertFalse('Moving a popup offscreen should not cause scrollbars',
    -      goog.dom.getDocumentScrollElement().scrollWidth != originalScrollWidth);
    -}
    -
    -function testOnDocumentBlurDisabledCrossIframeDismissalWithoutDelay() {
    -  popup.setEnableCrossIframeDismissal(false);
    -  popup.setVisible(true);
    -  var e = new goog.testing.events.Event(
    -      goog.events.EventType.BLUR, document);
    -  goog.testing.events.fireBrowserEvent(e);
    -  assertTrue('Popup should remain visible', popup.isVisible());
    -}
    -
    -function testOnDocumentBlurDisabledCrossIframeDismissalWithDelay() {
    -  popup.setEnableCrossIframeDismissal(false);
    -  popup.setVisible(true);
    -  var e = new goog.testing.events.Event(
    -      goog.events.EventType.BLUR, document);
    -  clock.tick(goog.ui.PopupBase.DEBOUNCE_DELAY_MS);
    -  goog.testing.events.fireBrowserEvent(e);
    -  assertTrue('Popup should remain visible', popup.isVisible());
    -}
    -
    -function testOnDocumentBlurActiveElementInsidePopupWithoutDelay() {
    -  popup.setVisible(true);
    -  var elementInsidePopup = goog.dom.createDom('div');
    -  goog.dom.append(popupDiv, elementInsidePopup);
    -  elementInsidePopup.setAttribute('tabIndex', 0);
    -  elementInsidePopup.focus();
    -  var e = new goog.testing.events.Event(
    -      goog.events.EventType.BLUR, document);
    -  goog.testing.events.fireBrowserEvent(e);
    -  assertTrue('Popup should remain visible', popup.isVisible());
    -}
    -
    -function testOnDocumentBlurActiveElementInsidePopupWithDelay() {
    -  popup.setVisible(true);
    -  var elementInsidePopup = goog.dom.createDom('div');
    -  goog.dom.append(popupDiv, elementInsidePopup);
    -  elementInsidePopup.setAttribute('tabIndex', 0);
    -  elementInsidePopup.focus();
    -  var e = new goog.testing.events.Event(
    -      goog.events.EventType.BLUR, document);
    -  clock.tick(goog.ui.PopupBase.DEBOUNCE_DELAY_MS);
    -  goog.testing.events.fireBrowserEvent(e);
    -  assertTrue('Popup should remain visible', popup.isVisible());
    -}
    -
    -function testOnDocumentBlurActiveElementIsBodyWithoutDelay() {
    -  popup.setVisible(true);
    -  var bodyElement = goog.dom.getDomHelper().
    -      getElementsByTagNameAndClass('body')[0];
    -  bodyElement.setAttribute('tabIndex', 0);
    -  bodyElement.focus();
    -  var e = new goog.testing.events.Event(
    -      goog.events.EventType.BLUR, document);
    -  goog.testing.events.fireBrowserEvent(e);
    -  assertTrue('Popup should remain visible', popup.isVisible());
    -}
    -
    -function testOnDocumentBlurActiveElementIsBodyWithDelay() {
    -  popup.setVisible(true);
    -  var bodyElement = goog.dom.getDomHelper().
    -      getElementsByTagNameAndClass('body')[0];
    -  bodyElement.setAttribute('tabIndex', 0);
    -  bodyElement.focus();
    -  var e = new goog.testing.events.Event(
    -      goog.events.EventType.BLUR, document);
    -  clock.tick(goog.ui.PopupBase.DEBOUNCE_DELAY_MS);
    -  goog.testing.events.fireBrowserEvent(e);
    -  assertTrue('Popup should remain visible', popup.isVisible());
    -}
    -
    -function testOnDocumentBlurEventTargetNotDocumentWithoutDelay() {
    -  popup.setVisible(true);
    -  var e = new goog.testing.events.Event(
    -      goog.events.EventType.BLUR, targetDiv);
    -  goog.testing.events.fireBrowserEvent(e);
    -  assertTrue('Popup should remain visible', popup.isVisible());
    -}
    -
    -function testOnDocumentBlurEventTargetNotDocumentWithDelay() {
    -  popup.setVisible(true);
    -  var e = new goog.testing.events.Event(
    -      goog.events.EventType.BLUR, targetDiv);
    -  clock.tick(goog.ui.PopupBase.DEBOUNCE_DELAY_MS);
    -  goog.testing.events.fireBrowserEvent(e);
    -  assertTrue('Popup should remain visible', popup.isVisible());
    -}
    -
    -function testOnDocumentBlurShouldDebounceWithoutDelay() {
    -  popup.setVisible(true);
    -  var commonAncestor = goog.dom.getElement('commonAncestor');
    -  var focusDiv = goog.dom.createDom('div', 'tabIndex');
    -  focusDiv.setAttribute('tabIndex', 0);
    -  goog.dom.appendChild(commonAncestor, focusDiv);
    -  focusDiv.focus();
    -  var e = new goog.testing.events.Event(
    -      goog.events.EventType.BLUR, document);
    -  goog.testing.events.fireBrowserEvent(e);
    -  assertTrue('Popup should be visible', popup.isVisible());
    -  goog.dom.removeNode(focusDiv);
    -}
    -
    -function testOnDocumentBlurShouldNotDebounceWithDelay() {
    -  popup.setVisible(true);
    -  clock.tick(goog.ui.PopupBase.DEBOUNCE_DELAY_MS);
    -  var commonAncestor = goog.dom.getElement('commonAncestor');
    -  var focusDiv = goog.dom.createDom('div', 'tabIndex');
    -  focusDiv.setAttribute('tabIndex', 0);
    -  goog.dom.appendChild(commonAncestor, focusDiv);
    -  focusDiv.focus();
    -  var e = new goog.testing.events.Event(
    -      goog.events.EventType.BLUR, document);
    -  goog.testing.events.fireBrowserEvent(e);
    -  assertFalse('Popup should be invisible', popup.isVisible());
    -  goog.dom.removeNode(focusDiv);
    -}
    -
    -
    -function testOnDocumentBlurShouldNotHideBubbleWithoutDelay() {
    -  popup.setVisible(true);
    -  var commonAncestor = goog.dom.getElement('commonAncestor');
    -  var focusDiv = goog.dom.createDom('div', 'tabIndex');
    -  focusDiv.setAttribute('tabIndex', 0);
    -  goog.dom.appendChild(commonAncestor, focusDiv);
    -  focusDiv.focus();
    -  var e = new goog.testing.events.Event(
    -      goog.events.EventType.BLUR, document);
    -  goog.testing.events.fireBrowserEvent(e);
    -  assertTrue('Popup should be visible', popup.isVisible());
    -  goog.dom.removeNode(focusDiv);
    -}
    -
    -function testOnDocumentBlurShouldHideBubbleWithDelay() {
    -  popup.setVisible(true);
    -  clock.tick(goog.ui.PopupBase.DEBOUNCE_DELAY_MS);
    -  var commonAncestor = goog.dom.getElement('commonAncestor');
    -  var focusDiv = goog.dom.createDom('div', 'tabIndex');
    -  focusDiv.setAttribute('tabIndex', 0);
    -  goog.dom.appendChild(commonAncestor, focusDiv);
    -  focusDiv.focus();
    -  var e = new goog.testing.events.Event(
    -      goog.events.EventType.BLUR, document);
    -  goog.testing.events.fireBrowserEvent(e);
    -  assertFalse('Popup should be invisible', popup.isVisible());
    -  goog.dom.removeNode(focusDiv);
    -}
    -
    -
    -
    -/**
    - * @implements {goog.fx.Transition}
    - * @extends {goog.events.EventTarget}
    - * @constructor
    - */
    -var MockTransition = function() {
    -  MockTransition.base(this, 'constructor');
    -  this.wasPlayed = false;
    -};
    -goog.inherits(MockTransition, goog.events.EventTarget);
    -
    -
    -MockTransition.prototype.play = function() {
    -  this.wasPlayed = true;
    -};
    -
    -
    -MockTransition.prototype.stop = goog.nullFunction;
    -
    -
    -// TODO(gboyer): Write better unit tests for click and cross-iframe dismissal.
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/popupcolorpicker.js b/src/database/third_party/closure-library/closure/goog/ui/popupcolorpicker.js
    deleted file mode 100644
    index cb0373918ae..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/popupcolorpicker.js
    +++ /dev/null
    @@ -1,475 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Popup Color Picker implementation.  This is intended to be
    - * less general than goog.ui.ColorPicker and presents a default set of colors
    - * that CCC apps currently use in their color pickers.
    - *
    - * @see ../demos/popupcolorpicker.html
    - */
    -
    -goog.provide('goog.ui.PopupColorPicker');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events.EventType');
    -goog.require('goog.positioning.AnchoredPosition');
    -goog.require('goog.positioning.Corner');
    -goog.require('goog.ui.ColorPicker');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.Popup');
    -
    -
    -
    -/**
    - * Popup color picker widget.
    - *
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @param {goog.ui.ColorPicker=} opt_colorPicker Optional color picker to use
    - *     for this popup.
    - * @extends {goog.ui.Component}
    - * @constructor
    - */
    -goog.ui.PopupColorPicker = function(opt_domHelper, opt_colorPicker) {
    -  goog.ui.Component.call(this, opt_domHelper);
    -
    -  if (opt_colorPicker) {
    -    this.colorPicker_ = opt_colorPicker;
    -  }
    -};
    -goog.inherits(goog.ui.PopupColorPicker, goog.ui.Component);
    -goog.tagUnsealableClass(goog.ui.PopupColorPicker);
    -
    -
    -/**
    - * Whether the color picker is initialized.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.PopupColorPicker.prototype.initialized_ = false;
    -
    -
    -/**
    - * Instance of a color picker control.
    - * @type {goog.ui.ColorPicker}
    - * @private
    - */
    -goog.ui.PopupColorPicker.prototype.colorPicker_ = null;
    -
    -
    -/**
    - * Instance of goog.ui.Popup used to manage the behavior of the color picker.
    - * @type {goog.ui.Popup}
    - * @private
    - */
    -goog.ui.PopupColorPicker.prototype.popup_ = null;
    -
    -
    -/**
    - * Corner of the popup which is pinned to the attaching element.
    - * @type {goog.positioning.Corner}
    - * @private
    - */
    -goog.ui.PopupColorPicker.prototype.pinnedCorner_ =
    -    goog.positioning.Corner.TOP_START;
    -
    -
    -/**
    - * Corner of the attaching element where the popup shows.
    - * @type {goog.positioning.Corner}
    - * @private
    - */
    -goog.ui.PopupColorPicker.prototype.popupCorner_ =
    -    goog.positioning.Corner.BOTTOM_START;
    -
    -
    -/**
    - * Reference to the element that triggered the last popup.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.PopupColorPicker.prototype.lastTarget_ = null;
    -
    -
    -/** @private {boolean} */
    -goog.ui.PopupColorPicker.prototype.rememberSelection_;
    -
    -
    -/**
    - * Whether the color picker can move the focus to its key event target when it
    - * is shown.  The default is true.  Setting to false can break keyboard
    - * navigation, but this is needed for certain scenarios, for example the
    - * toolbar menu in trogedit which can't have the selection changed.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.PopupColorPicker.prototype.allowAutoFocus_ = true;
    -
    -
    -/**
    - * Whether the color picker can accept focus.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.PopupColorPicker.prototype.focusable_ = true;
    -
    -
    -/**
    - * If true, then the colorpicker will toggle off if it is already visible.
    - *
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.PopupColorPicker.prototype.toggleMode_ = true;
    -
    -
    -/**
    - * If true, the colorpicker will appear on hover.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.PopupColorPicker.prototype.showOnHover_ = false;
    -
    -
    -/** @override */
    -goog.ui.PopupColorPicker.prototype.createDom = function() {
    -  goog.ui.PopupColorPicker.superClass_.createDom.call(this);
    -  this.popup_ = new goog.ui.Popup(this.getElement());
    -  this.popup_.setPinnedCorner(this.pinnedCorner_);
    -  goog.dom.classlist.set(
    -      goog.asserts.assert(this.getElement()),
    -      goog.getCssName('goog-popupcolorpicker'));
    -  this.getElement().unselectable = 'on';
    -};
    -
    -
    -/** @override */
    -goog.ui.PopupColorPicker.prototype.disposeInternal = function() {
    -  goog.ui.PopupColorPicker.superClass_.disposeInternal.call(this);
    -  this.colorPicker_ = null;
    -  this.lastTarget_ = null;
    -  this.initialized_ = false;
    -  if (this.popup_) {
    -    this.popup_.dispose();
    -    this.popup_ = null;
    -  }
    -};
    -
    -
    -/**
    - * ColorPickers cannot be used to decorate pre-existing html, since the
    - * structure they build is fairly complicated.
    - * @param {Element} element Element to decorate.
    - * @return {boolean} Returns always false.
    - * @override
    - */
    -goog.ui.PopupColorPicker.prototype.canDecorate = function(element) {
    -  return false;
    -};
    -
    -
    -/**
    - * @return {goog.ui.ColorPicker} The color picker instance.
    - */
    -goog.ui.PopupColorPicker.prototype.getColorPicker = function() {
    -  return this.colorPicker_;
    -};
    -
    -
    -/**
    - * Returns whether the Popup dismisses itself when the user clicks outside of
    - * it.
    - * @return {boolean} Whether the Popup autohides on an external click.
    - */
    -goog.ui.PopupColorPicker.prototype.getAutoHide = function() {
    -  return !!this.popup_ && this.popup_.getAutoHide();
    -};
    -
    -
    -/**
    - * Sets whether the Popup dismisses itself when the user clicks outside of it -
    - * must be called after the Popup has been created (in createDom()),
    - * otherwise it does nothing.
    - *
    - * @param {boolean} autoHide Whether to autohide on an external click.
    - */
    -goog.ui.PopupColorPicker.prototype.setAutoHide = function(autoHide) {
    -  if (this.popup_) {
    -    this.popup_.setAutoHide(autoHide);
    -  }
    -};
    -
    -
    -/**
    - * Returns the region inside which the Popup dismisses itself when the user
    - * clicks, or null if it was not set. Null indicates the entire document is
    - * the autohide region.
    - * @return {Element} The DOM element for autohide, or null if it hasn't been
    - *     set.
    - */
    -goog.ui.PopupColorPicker.prototype.getAutoHideRegion = function() {
    -  return this.popup_ && this.popup_.getAutoHideRegion();
    -};
    -
    -
    -/**
    - * Sets the region inside which the Popup dismisses itself when the user
    - * clicks - must be called after the Popup has been created (in createDom()),
    - * otherwise it does nothing.
    - *
    - * @param {Element} element The DOM element for autohide.
    - */
    -goog.ui.PopupColorPicker.prototype.setAutoHideRegion = function(element) {
    -  if (this.popup_) {
    -    this.popup_.setAutoHideRegion(element);
    -  }
    -};
    -
    -
    -/**
    - * Returns the {@link goog.ui.PopupBase} from this picker. Returns null if the
    - * popup has not yet been created.
    - *
    - * NOTE: This should *ONLY* be called from tests. If called before createDom(),
    - * this should return null.
    - *
    - * @return {goog.ui.PopupBase?} The popup or null if it hasn't been created.
    - */
    -goog.ui.PopupColorPicker.prototype.getPopup = function() {
    -  return this.popup_;
    -};
    -
    -
    -/**
    - * @return {Element} The last element that triggered the popup.
    - */
    -goog.ui.PopupColorPicker.prototype.getLastTarget = function() {
    -  return this.lastTarget_;
    -};
    -
    -
    -/**
    - * Attaches the popup color picker to an element.
    - * @param {Element} element The element to attach to.
    - */
    -goog.ui.PopupColorPicker.prototype.attach = function(element) {
    -  if (this.showOnHover_) {
    -    this.getHandler().listen(element, goog.events.EventType.MOUSEOVER,
    -                             this.show_);
    -  } else {
    -    this.getHandler().listen(element, goog.events.EventType.MOUSEDOWN,
    -                             this.show_);
    -  }
    -};
    -
    -
    -/**
    - * Detatches the popup color picker from an element.
    - * @param {Element} element The element to detach from.
    - */
    -goog.ui.PopupColorPicker.prototype.detach = function(element) {
    -  if (this.showOnHover_) {
    -    this.getHandler().unlisten(element, goog.events.EventType.MOUSEOVER,
    -                               this.show_);
    -  } else {
    -    this.getHandler().unlisten(element, goog.events.EventType.MOUSEOVER,
    -                               this.show_);
    -  }
    -};
    -
    -
    -/**
    - * Gets the color that is currently selected in this color picker.
    - * @return {?string} The hex string of the color selected, or null if no
    - *     color is selected.
    - */
    -goog.ui.PopupColorPicker.prototype.getSelectedColor = function() {
    -  return this.colorPicker_.getSelectedColor();
    -};
    -
    -
    -/**
    - * Sets whether the color picker can accept focus.
    - * @param {boolean} focusable True iff the color picker can accept focus.
    - */
    -goog.ui.PopupColorPicker.prototype.setFocusable = function(focusable) {
    -  this.focusable_ = focusable;
    -  if (this.colorPicker_) {
    -    // TODO(user): In next revision sort the behavior of passing state to
    -    // children correctly
    -    this.colorPicker_.setFocusable(focusable);
    -  }
    -};
    -
    -
    -/**
    - * Sets whether the color picker can automatically move focus to its key event
    - * target when it is set to visible.
    - * @param {boolean} allow Whether to allow auto focus.
    - */
    -goog.ui.PopupColorPicker.prototype.setAllowAutoFocus = function(allow) {
    -  this.allowAutoFocus_ = allow;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the color picker can automatically move focus to
    - *     its key event target when it is set to visible.
    - */
    -goog.ui.PopupColorPicker.prototype.getAllowAutoFocus = function() {
    -  return this.allowAutoFocus_;
    -};
    -
    -
    -/**
    - * Sets whether the color picker should toggle off if it is already open.
    - * @param {boolean} toggle The new toggle mode.
    - */
    -goog.ui.PopupColorPicker.prototype.setToggleMode = function(toggle) {
    -  this.toggleMode_ = toggle;
    -};
    -
    -
    -/**
    - * Gets whether the colorpicker is in toggle mode
    - * @return {boolean} toggle.
    - */
    -goog.ui.PopupColorPicker.prototype.getToggleMode = function() {
    -  return this.toggleMode_;
    -};
    -
    -
    -/**
    - * Sets whether the picker remembers the last selected color between popups.
    - *
    - * @param {boolean} remember Whether to remember the selection.
    - */
    -goog.ui.PopupColorPicker.prototype.setRememberSelection = function(remember) {
    -  this.rememberSelection_ = remember;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the picker remembers the last selected color
    - *     between popups.
    - */
    -goog.ui.PopupColorPicker.prototype.getRememberSelection = function() {
    -  return this.rememberSelection_;
    -};
    -
    -
    -/**
    - * Add an array of colors to the colors displayed by the color picker.
    - * Does not add duplicated colors.
    - * @param {Array<string>} colors The array of colors to be added.
    - */
    -goog.ui.PopupColorPicker.prototype.addColors = function(colors) {
    -
    -};
    -
    -
    -/**
    - * Clear the colors displayed by the color picker.
    - */
    -goog.ui.PopupColorPicker.prototype.clearColors = function() {
    -
    -};
    -
    -
    -/**
    - * Set the pinned corner of the popup.
    - * @param {goog.positioning.Corner} corner The corner of the popup which is
    - *     pinned to the attaching element.
    - */
    -goog.ui.PopupColorPicker.prototype.setPinnedCorner = function(corner) {
    -  this.pinnedCorner_ = corner;
    -  if (this.popup_) {
    -    this.popup_.setPinnedCorner(this.pinnedCorner_);
    -  }
    -};
    -
    -
    -/**
    - * Sets which corner of the attaching element this popup shows up.
    - * @param {goog.positioning.Corner} corner The corner of the attaching element
    - *     where to show the popup.
    - */
    -goog.ui.PopupColorPicker.prototype.setPopupCorner = function(corner) {
    -  this.popupCorner_ = corner;
    -};
    -
    -
    -/**
    - * Sets whether the popup shows up on hover. By default, appears on click.
    - * @param {boolean} showOnHover True if popup should appear on hover.
    - */
    -goog.ui.PopupColorPicker.prototype.setShowOnHover = function(showOnHover) {
    -  this.showOnHover_ = showOnHover;
    -};
    -
    -
    -/**
    - * Handles click events on the targets and shows the color picker.
    - * @param {goog.events.BrowserEvent} e The browser event.
    - * @private
    - */
    -goog.ui.PopupColorPicker.prototype.show_ = function(e) {
    -  if (!this.initialized_) {
    -    this.colorPicker_ = this.colorPicker_ ||
    -        goog.ui.ColorPicker.createSimpleColorGrid(this.getDomHelper());
    -    this.colorPicker_.setFocusable(this.focusable_);
    -    this.addChild(this.colorPicker_, true);
    -    this.getHandler().listen(this.colorPicker_,
    -        goog.ui.ColorPicker.EventType.CHANGE, this.onColorPicked_);
    -    this.initialized_ = true;
    -  }
    -
    -  if (this.popup_.isOrWasRecentlyVisible() && this.toggleMode_ &&
    -      this.lastTarget_ == e.currentTarget) {
    -    this.popup_.setVisible(false);
    -    return;
    -  }
    -
    -  this.lastTarget_ = /** @type {Element} */ (e.currentTarget);
    -  this.popup_.setPosition(new goog.positioning.AnchoredPosition(
    -      this.lastTarget_, this.popupCorner_));
    -  if (!this.rememberSelection_) {
    -    this.colorPicker_.setSelectedIndex(-1);
    -  }
    -  this.popup_.setVisible(true);
    -  if (this.allowAutoFocus_) {
    -    this.colorPicker_.focus();
    -  }
    -};
    -
    -
    -/**
    - * Handles the color change event.
    - * @param {goog.events.Event} e The event.
    - * @private
    - */
    -goog.ui.PopupColorPicker.prototype.onColorPicked_ = function(e) {
    -  // When we show the color picker we reset the color, which triggers an event.
    -  // Here we block that event so that it doesn't dismiss the popup
    -  // TODO(user): Update the colorpicker to allow selection to be cleared
    -  if (this.colorPicker_.getSelectedIndex() == -1) {
    -    e.stopPropagation();
    -    return;
    -  }
    -  this.popup_.setVisible(false);
    -  if (this.allowAutoFocus_) {
    -    this.lastTarget_.focus();
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/popupcolorpicker_test.html b/src/database/third_party/closure-library/closure/goog/ui/popupcolorpicker_test.html
    deleted file mode 100644
    index 08d4efeee82..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/popupcolorpicker_test.html
    +++ /dev/null
    @@ -1,27 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.Popup
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.PopupColorPickerTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="containingDiv">
    -   <a href="javascript:void(0)" id="button1">
    -    color picker
    -   </a>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/popupcolorpicker_test.js b/src/database/third_party/closure-library/closure/goog/ui/popupcolorpicker_test.js
    deleted file mode 100644
    index 3ab408674c1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/popupcolorpicker_test.js
    +++ /dev/null
    @@ -1,66 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.PopupColorPickerTest');
    -goog.setTestOnly('goog.ui.PopupColorPickerTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.ColorPicker');
    -goog.require('goog.ui.PopupColorPicker');
    -
    -// Unittest to ensure that the popup gets created in createDom().
    -function testPopupCreation() {
    -  var picker = new goog.ui.PopupColorPicker();
    -  picker.createDom();
    -  assertNotNull(picker.getPopup());
    -}
    -
    -function testAutoHideIsSetProperly() {
    -  var picker = new goog.ui.PopupColorPicker();
    -  picker.createDom();
    -  picker.setAutoHide(true);
    -  var containingDiv = goog.dom.getElement('containingDiv');
    -  picker.setAutoHideRegion(containingDiv);
    -  assertTrue(picker.getAutoHide());
    -  assertEquals(containingDiv, picker.getAutoHideRegion());
    -}
    -
    -// Unittest to ensure the popup opens with a custom color picker.
    -function testCustomColorPicker() {
    -  var button1 = document.getElementById('button1');
    -  var domHelper = goog.dom.getDomHelper();
    -  var colorPicker = new goog.ui.ColorPicker();
    -  colorPicker.setColors(['#ffffff', '#000000']);
    -  var picker = new goog.ui.PopupColorPicker(domHelper, colorPicker);
    -  picker.render();
    -  picker.attach(button1);
    -  assertNotNull(picker.getColorPicker());
    -  assertNotNull(picker.getPopup().getElement());
    -  assertNull(picker.getSelectedColor());
    -
    -  var changeEvents = 0;
    -  goog.events.listen(picker, goog.ui.ColorPicker.EventType.CHANGE, function(e) {
    -    changeEvents++;
    -  });
    -
    -  // Select the first color.
    -  goog.testing.events.fireClickSequence(button1);
    -  goog.testing.events.fireClickSequence(
    -      document.getElementById('goog-palette-cell-0').firstChild);
    -  assertEquals('#ffffff', picker.getSelectedColor());
    -  assertEquals(1, changeEvents);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/popupdatepicker.js b/src/database/third_party/closure-library/closure/goog/ui/popupdatepicker.js
    deleted file mode 100644
    index e5158ed1992..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/popupdatepicker.js
    +++ /dev/null
    @@ -1,288 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Popup Date Picker implementation.  Pairs a goog.ui.DatePicker
    - * with a goog.ui.Popup allowing the DatePicker to be attached to elements.
    - *
    - * @see ../demos/popupdatepicker.html
    - */
    -
    -goog.provide('goog.ui.PopupDatePicker');
    -
    -goog.require('goog.events.EventType');
    -goog.require('goog.positioning.AnchoredPosition');
    -goog.require('goog.positioning.Corner');
    -goog.require('goog.positioning.Overflow');
    -goog.require('goog.style');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.DatePicker');
    -goog.require('goog.ui.Popup');
    -goog.require('goog.ui.PopupBase');
    -
    -
    -
    -/**
    - * Popup date picker widget. Fires goog.ui.PopupBase.EventType.SHOW or HIDE
    - * events when its visibility changes.
    - *
    - * @param {goog.ui.DatePicker=} opt_datePicker Optional DatePicker.  This
    - *     enables the use of a custom date-picker instance.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @extends {goog.ui.Component}
    - * @constructor
    - */
    -goog.ui.PopupDatePicker = function(opt_datePicker, opt_domHelper) {
    -  goog.ui.Component.call(this, opt_domHelper);
    -
    -  this.datePicker_ = opt_datePicker || new goog.ui.DatePicker();
    -};
    -goog.inherits(goog.ui.PopupDatePicker, goog.ui.Component);
    -goog.tagUnsealableClass(goog.ui.PopupDatePicker);
    -
    -
    -/**
    - * Instance of a date picker control.
    - * @type {goog.ui.DatePicker?}
    - * @private
    - */
    -goog.ui.PopupDatePicker.prototype.datePicker_ = null;
    -
    -
    -/**
    - * Instance of goog.ui.Popup used to manage the behavior of the date picker.
    - * @type {goog.ui.Popup?}
    - * @private
    - */
    -goog.ui.PopupDatePicker.prototype.popup_ = null;
    -
    -
    -/**
    - * Reference to the element that triggered the last popup.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.PopupDatePicker.prototype.lastTarget_ = null;
    -
    -
    -/**
    - * Whether the date picker can move the focus to its key event target when it
    - * is shown.  The default is true.  Setting to false can break keyboard
    - * navigation, but this is needed for certain scenarios, for example the
    - * toolbar menu in trogedit which can't have the selection changed.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.PopupDatePicker.prototype.allowAutoFocus_ = true;
    -
    -
    -/** @override */
    -goog.ui.PopupDatePicker.prototype.createDom = function() {
    -  goog.ui.PopupDatePicker.superClass_.createDom.call(this);
    -  this.getElement().className = goog.getCssName('goog-popupdatepicker');
    -  this.popup_ = new goog.ui.Popup(this.getElement());
    -  this.popup_.setParentEventTarget(this);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the date picker is visible.
    - */
    -goog.ui.PopupDatePicker.prototype.isVisible = function() {
    -  return this.popup_ ? this.popup_.isVisible() : false;
    -};
    -
    -
    -/** @override */
    -goog.ui.PopupDatePicker.prototype.enterDocument = function() {
    -  goog.ui.PopupDatePicker.superClass_.enterDocument.call(this);
    -  // Create the DatePicker, if it isn't already.
    -  // Done here as DatePicker assumes that the element passed to it is attached
    -  // to a document.
    -  if (!this.datePicker_.isInDocument()) {
    -    var el = this.getElement();
    -    // Make it initially invisible
    -    el.style.visibility = 'hidden';
    -    goog.style.setElementShown(el, false);
    -    this.datePicker_.decorate(el);
    -  }
    -  this.getHandler().listen(this.datePicker_, goog.ui.DatePicker.Events.CHANGE,
    -                           this.onDateChanged_);
    -};
    -
    -
    -/** @override */
    -goog.ui.PopupDatePicker.prototype.disposeInternal = function() {
    -  goog.ui.PopupDatePicker.superClass_.disposeInternal.call(this);
    -  if (this.popup_) {
    -    this.popup_.dispose();
    -    this.popup_ = null;
    -  }
    -  this.datePicker_.dispose();
    -  this.datePicker_ = null;
    -  this.lastTarget_ = null;
    -};
    -
    -
    -/**
    - * DatePicker cannot be used to decorate pre-existing html, since they're
    - * not based on Components.
    - * @param {Element} element Element to decorate.
    - * @return {boolean} Returns always false.
    - * @override
    - */
    -goog.ui.PopupDatePicker.prototype.canDecorate = function(element) {
    -  return false;
    -};
    -
    -
    -/**
    - * @return {goog.ui.DatePicker} The date picker instance.
    - */
    -goog.ui.PopupDatePicker.prototype.getDatePicker = function() {
    -  return this.datePicker_;
    -};
    -
    -
    -/**
    - * @return {goog.date.Date?} The selected date, if any.  See
    - *     goog.ui.DatePicker.getDate().
    - */
    -goog.ui.PopupDatePicker.prototype.getDate = function() {
    -  return this.datePicker_.getDate();
    -};
    -
    -
    -/**
    - * Sets the selected date.  See goog.ui.DatePicker.setDate().
    - * @param {goog.date.Date?} date The date to select.
    - */
    -goog.ui.PopupDatePicker.prototype.setDate = function(date) {
    -  this.datePicker_.setDate(date);
    -};
    -
    -
    -/**
    - * @return {Element} The last element that triggered the popup.
    - */
    -goog.ui.PopupDatePicker.prototype.getLastTarget = function() {
    -  return this.lastTarget_;
    -};
    -
    -
    -/**
    - * Attaches the popup date picker to an element.
    - * @param {Element} element The element to attach to.
    - */
    -goog.ui.PopupDatePicker.prototype.attach = function(element) {
    -  this.getHandler().listen(element, goog.events.EventType.MOUSEDOWN,
    -                           this.showPopup_);
    -};
    -
    -
    -/**
    - * Detatches the popup date picker from an element.
    - * @param {Element} element The element to detach from.
    - */
    -goog.ui.PopupDatePicker.prototype.detach = function(element) {
    -  this.getHandler().unlisten(element, goog.events.EventType.MOUSEDOWN,
    -                             this.showPopup_);
    -};
    -
    -
    -/**
    - * Sets whether the date picker can automatically move focus to its key event
    - * target when it is set to visible.
    - * @param {boolean} allow Whether to allow auto focus.
    - */
    -goog.ui.PopupDatePicker.prototype.setAllowAutoFocus = function(allow) {
    -  this.allowAutoFocus_ = allow;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the date picker can automatically move focus to
    - * its key event target when it is set to visible.
    - */
    -goog.ui.PopupDatePicker.prototype.getAllowAutoFocus = function() {
    -  return this.allowAutoFocus_;
    -};
    -
    -
    -/**
    - * Show the popup at the bottom-left corner of the specified element.
    - * @param {Element} element Reference element for displaying the popup -- popup
    - *     will appear at the bottom-left corner of this element.
    - */
    -goog.ui.PopupDatePicker.prototype.showPopup = function(element) {
    -  this.lastTarget_ = element;
    -  this.popup_.setPosition(new goog.positioning.AnchoredPosition(
    -      element,
    -      goog.positioning.Corner.BOTTOM_START,
    -      (goog.positioning.Overflow.ADJUST_X_EXCEPT_OFFSCREEN |
    -      goog.positioning.Overflow.ADJUST_Y_EXCEPT_OFFSCREEN)));
    -
    -  // Don't listen to date changes while we're setting up the popup so we don't
    -  // have to worry about change events when we call setDate().
    -  this.getHandler().unlisten(this.datePicker_, goog.ui.DatePicker.Events.CHANGE,
    -                             this.onDateChanged_);
    -  this.datePicker_.setDate(null);
    -
    -  // Forward the change event onto our listeners.  Done before we start
    -  // listening to date changes again, so that listeners can change the date
    -  // without firing more events.
    -  this.dispatchEvent(goog.ui.PopupBase.EventType.SHOW);
    -
    -  this.getHandler().listen(this.datePicker_, goog.ui.DatePicker.Events.CHANGE,
    -                           this.onDateChanged_);
    -  this.popup_.setVisible(true);
    -  if (this.allowAutoFocus_) {
    -    this.getElement().focus();  // Our element contains the date picker.
    -  }
    -};
    -
    -
    -/**
    - * Handles click events on the targets and shows the date picker.
    - * @param {goog.events.Event} event The click event.
    - * @private
    - */
    -goog.ui.PopupDatePicker.prototype.showPopup_ = function(event) {
    -  this.showPopup(/** @type {Element} */ (event.currentTarget));
    -};
    -
    -
    -/**
    - * Hides this popup.
    - */
    -goog.ui.PopupDatePicker.prototype.hidePopup = function() {
    -  this.popup_.setVisible(false);
    -  if (this.allowAutoFocus_ && this.lastTarget_) {
    -    this.lastTarget_.focus();
    -  }
    -};
    -
    -
    -/**
    - * Called when the date is changed.
    - *
    - * @param {goog.events.Event} event The date change event.
    - * @private
    - */
    -goog.ui.PopupDatePicker.prototype.onDateChanged_ = function(event) {
    -  this.hidePopup();
    -
    -  // Forward the change event onto our listeners.
    -  this.dispatchEvent(event);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/popupdatepicker_test.html b/src/database/third_party/closure-library/closure/goog/ui/popupdatepicker_test.html
    deleted file mode 100644
    index b38237aa727..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/popupdatepicker_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.PopupDatePicker
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.PopupDatePickerTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/popupdatepicker_test.js b/src/database/third_party/closure-library/closure/goog/ui/popupdatepicker_test.js
    deleted file mode 100644
    index 83d477a1f74..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/popupdatepicker_test.js
    +++ /dev/null
    @@ -1,67 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.PopupDatePickerTest');
    -goog.setTestOnly('goog.ui.PopupDatePickerTest');
    -
    -goog.require('goog.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -goog.require('goog.ui.PopupBase');
    -goog.require('goog.ui.PopupDatePicker');
    -
    -var popupDatePicker;
    -
    -function setUp() {
    -  popupDatePicker = new goog.ui.PopupDatePicker();
    -}
    -
    -function tearDown() {
    -  popupDatePicker.dispose();
    -}
    -
    -function testIsVisible() {
    -  assertFalse(popupDatePicker.isVisible());
    -  popupDatePicker.createDom();
    -  assertFalse(popupDatePicker.isVisible());
    -  popupDatePicker.render();
    -  assertFalse(popupDatePicker.isVisible());
    -  popupDatePicker.showPopup(document.body);
    -  assertTrue(popupDatePicker.isVisible());
    -  popupDatePicker.hidePopup();
    -  assertFalse(popupDatePicker.isVisible());
    -}
    -
    -function testFiresShowAndHideEvents() {
    -  var showHandler = goog.testing.recordFunction();
    -  var hideHandler = goog.testing.recordFunction();
    -  goog.events.listen(popupDatePicker, goog.ui.PopupBase.EventType.SHOW,
    -      showHandler);
    -  goog.events.listen(popupDatePicker, goog.ui.PopupBase.EventType.HIDE,
    -      hideHandler);
    -  popupDatePicker.createDom();
    -  popupDatePicker.render();
    -  assertEquals(0, showHandler.getCallCount());
    -  assertEquals(0, hideHandler.getCallCount());
    -
    -  popupDatePicker.showPopup(document.body);
    -  // Bug in goog.ui.Popup: the SHOW event is fired twice.
    -  assertEquals(2, showHandler.getCallCount());
    -  assertEquals(0, hideHandler.getCallCount());
    -  showHandler.reset();
    -
    -  popupDatePicker.hidePopup();
    -  assertEquals(0, showHandler.getCallCount());
    -  assertEquals(1, hideHandler.getCallCount());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/popupmenu.js b/src/database/third_party/closure-library/closure/goog/ui/popupmenu.js
    deleted file mode 100644
    index f33fdfc50c2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/popupmenu.js
    +++ /dev/null
    @@ -1,558 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A menu class for showing popups.  A single popup can be
    - * attached to multiple anchor points.  The menu will try to reposition itself
    - * if it goes outside the viewport.
    - *
    - * Decoration is the same as goog.ui.Menu except that the outer DIV can have a
    - * 'for' property, which is the ID of the element which triggers the popup.
    - *
    - * Decorate Example:
    - * <button id="dButton">Decorated Popup</button>
    - * <div id="dMenu" for="dButton" class="goog-menu">
    - *   <div class="goog-menuitem">A a</div>
    - *   <div class="goog-menuitem">B b</div>
    - *   <div class="goog-menuitem">C c</div>
    - *   <div class="goog-menuitem">D d</div>
    - *   <div class="goog-menuitem">E e</div>
    - *   <div class="goog-menuitem">F f</div>
    - * </div>
    - *
    - * TESTED=FireFox 2.0, IE6, Opera 9, Chrome.
    - * TODO(user): Key handling is flakey in Opera and Chrome
    - *
    - * @see ../demos/popupmenu.html
    - */
    -
    -goog.provide('goog.ui.PopupMenu');
    -
    -goog.require('goog.events.EventType');
    -goog.require('goog.positioning.AnchoredViewportPosition');
    -goog.require('goog.positioning.Corner');
    -goog.require('goog.positioning.MenuAnchoredPosition');
    -goog.require('goog.positioning.Overflow');
    -goog.require('goog.positioning.ViewportClientPosition');
    -goog.require('goog.structs.Map');
    -goog.require('goog.style');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.Menu');
    -goog.require('goog.ui.PopupBase');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * A basic menu class.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @param {goog.ui.MenuRenderer=} opt_renderer Renderer used to render or
    - *     decorate the container; defaults to {@link goog.ui.MenuRenderer}.
    - * @extends {goog.ui.Menu}
    - * @constructor
    - */
    -goog.ui.PopupMenu = function(opt_domHelper, opt_renderer) {
    -  goog.ui.Menu.call(this, opt_domHelper, opt_renderer);
    -
    -  this.setAllowAutoFocus(true);
    -
    -  // Popup menus are hidden by default.
    -  this.setVisible(false, true);
    -
    -  /**
    -   * Map of attachment points for the menu.  Key -> Object
    -   * @type {!goog.structs.Map}
    -   * @private
    -   */
    -  this.targets_ = new goog.structs.Map();
    -};
    -goog.inherits(goog.ui.PopupMenu, goog.ui.Menu);
    -goog.tagUnsealableClass(goog.ui.PopupMenu);
    -
    -
    -/**
    - * If true, then if the menu will toggle off if it is already visible.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.PopupMenu.prototype.toggleMode_ = false;
    -
    -
    -/**
    - * Time that the menu was last shown.
    - * @type {number}
    - * @private
    - */
    -goog.ui.PopupMenu.prototype.lastHide_ = 0;
    -
    -
    -/**
    - * Current element where the popup menu is anchored.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.PopupMenu.prototype.currentAnchor_ = null;
    -
    -
    -/**
    - * Decorate an existing HTML structure with the menu. Menu items will be
    - * constructed from elements with classname 'goog-menuitem', separators will be
    - * made from HR elements.
    - * @param {Element} element Element to decorate.
    - * @override
    - */
    -goog.ui.PopupMenu.prototype.decorateInternal = function(element) {
    -  goog.ui.PopupMenu.superClass_.decorateInternal.call(this, element);
    -  // 'for' is a custom attribute for attaching the menu to a click target
    -  var htmlFor = element.getAttribute('for') || element.htmlFor;
    -  if (htmlFor) {
    -    this.attach(
    -        this.getDomHelper().getElement(htmlFor),
    -        goog.positioning.Corner.BOTTOM_LEFT);
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.PopupMenu.prototype.enterDocument = function() {
    -  goog.ui.PopupMenu.superClass_.enterDocument.call(this);
    -
    -  this.targets_.forEach(this.attachEvent_, this);
    -
    -  var handler = this.getHandler();
    -  handler.listen(
    -      this, goog.ui.Component.EventType.ACTION, this.onAction_);
    -  handler.listen(this.getDomHelper().getDocument(),
    -      goog.events.EventType.MOUSEDOWN, this.onDocClick, true);
    -
    -  // Webkit doesn't fire a mousedown event when opening the context menu,
    -  // but we need one to update menu visibility properly. So in Safari handle
    -  // contextmenu mouse events like mousedown.
    -  // {@link http://bugs.webkit.org/show_bug.cgi?id=6595}
    -  if (goog.userAgent.WEBKIT) {
    -    handler.listen(this.getDomHelper().getDocument(),
    -        goog.events.EventType.CONTEXTMENU, this.onDocClick, true);
    -  }
    -};
    -
    -
    -/**
    - * Attaches the menu to a new popup position and anchor element.  A menu can
    - * only be attached to an element once, since attaching the same menu for
    - * multiple positions doesn't make sense.
    - *
    - * @param {Element} element Element whose click event should trigger the menu.
    - * @param {goog.positioning.Corner=} opt_targetCorner Corner of the target that
    - *     the menu should be anchored to.
    - * @param {goog.positioning.Corner=} opt_menuCorner Corner of the menu that
    - *     should be anchored.
    - * @param {boolean=} opt_contextMenu Whether the menu should show on
    - *     {@link goog.events.EventType.CONTEXTMENU} events, false if it should
    - *     show on {@link goog.events.EventType.MOUSEDOWN} events. Default is
    - *     MOUSEDOWN.
    - * @param {goog.math.Box=} opt_margin Margin for the popup used in positioning
    - *     algorithms.
    - */
    -goog.ui.PopupMenu.prototype.attach = function(
    -    element, opt_targetCorner, opt_menuCorner, opt_contextMenu, opt_margin) {
    -
    -  if (this.isAttachTarget(element)) {
    -    // Already in the popup, so just return.
    -    return;
    -  }
    -
    -  var target = this.createAttachTarget(element, opt_targetCorner,
    -      opt_menuCorner, opt_contextMenu, opt_margin);
    -
    -  if (this.isInDocument()) {
    -    this.attachEvent_(target);
    -  }
    -};
    -
    -
    -/**
    - * Creates an object describing how the popup menu should be attached to the
    - * anchoring element based on the given parameters. The created object is
    - * stored, keyed by {@code element} and is retrievable later by invoking
    - * {@link #getAttachTarget(element)} at a later point.
    - *
    - * Subclass may add more properties to the returned object, as needed.
    - *
    - * @param {Element} element Element whose click event should trigger the menu.
    - * @param {goog.positioning.Corner=} opt_targetCorner Corner of the target that
    - *     the menu should be anchored to.
    - * @param {goog.positioning.Corner=} opt_menuCorner Corner of the menu that
    - *     should be anchored.
    - * @param {boolean=} opt_contextMenu Whether the menu should show on
    - *     {@link goog.events.EventType.CONTEXTMENU} events, false if it should
    - *     show on {@link goog.events.EventType.MOUSEDOWN} events. Default is
    - *     MOUSEDOWN.
    - * @param {goog.math.Box=} opt_margin Margin for the popup used in positioning
    - *     algorithms.
    - *
    - * @return {Object} An object that describes how the popup menu should be
    - *     attached to the anchoring element.
    - *
    - * @protected
    - */
    -goog.ui.PopupMenu.prototype.createAttachTarget = function(
    -    element, opt_targetCorner, opt_menuCorner, opt_contextMenu, opt_margin) {
    -  if (!element) {
    -    return null;
    -  }
    -
    -  var target = {
    -    element_: element,
    -    targetCorner_: opt_targetCorner,
    -    menuCorner_: opt_menuCorner,
    -    eventType_: opt_contextMenu ? goog.events.EventType.CONTEXTMENU :
    -        goog.events.EventType.MOUSEDOWN,
    -    margin_: opt_margin
    -  };
    -
    -  this.targets_.set(goog.getUid(element), target);
    -
    -  return target;
    -};
    -
    -
    -/**
    - * Returns the object describing how the popup menu should be attach to given
    - * element or {@code null}. The object is created and the association is formed
    - * when {@link #attach} is invoked.
    - *
    - * @param {Element} element DOM element.
    - * @return {Object} The object created when {@link attach} is invoked on
    - *     {@code element}. Returns {@code null} if the element does not trigger
    - *     the menu (i.e. {@link attach} has never been invoked on
    - *     {@code element}).
    - * @protected
    - */
    -goog.ui.PopupMenu.prototype.getAttachTarget = function(element) {
    -  return element ?
    -      /** @type {Object} */(this.targets_.get(goog.getUid(element))) :
    -      null;
    -};
    -
    -
    -/**
    - * @param {Element} element Any DOM element.
    - * @return {boolean} Whether clicking on the given element will trigger the
    - *     menu.
    - *
    - * @protected
    - */
    -goog.ui.PopupMenu.prototype.isAttachTarget = function(element) {
    -  return element ? this.targets_.containsKey(goog.getUid(element)) : false;
    -};
    -
    -
    -/**
    - * @return {Element} The current element where the popup is anchored, if it's
    - *     visible.
    - */
    -goog.ui.PopupMenu.prototype.getAttachedElement = function() {
    -  return this.currentAnchor_;
    -};
    -
    -
    -/**
    - * Attaches an event listener to a target
    - * @param {Object} target The target to attach an event to.
    - * @private
    - */
    -goog.ui.PopupMenu.prototype.attachEvent_ = function(target) {
    -  this.getHandler().listen(
    -      target.element_, target.eventType_, this.onTargetClick_);
    -};
    -
    -
    -/**
    - * Detaches all listeners
    - */
    -goog.ui.PopupMenu.prototype.detachAll = function() {
    -  if (this.isInDocument()) {
    -    var keys = this.targets_.getKeys();
    -    for (var i = 0; i < keys.length; i++) {
    -      this.detachEvent_(/** @type {Object} */ (this.targets_.get(keys[i])));
    -    }
    -  }
    -
    -  this.targets_.clear();
    -};
    -
    -
    -/**
    - * Detaches a menu from a given element.
    - * @param {Element} element Element whose click event should trigger the menu.
    - */
    -goog.ui.PopupMenu.prototype.detach = function(element) {
    -  if (!this.isAttachTarget(element)) {
    -    throw Error('Menu not attached to provided element, unable to detach.');
    -  }
    -
    -  var key = goog.getUid(element);
    -  if (this.isInDocument()) {
    -    this.detachEvent_(/** @type {Object} */ (this.targets_.get(key)));
    -  }
    -
    -  this.targets_.remove(key);
    -};
    -
    -
    -/**
    - * Detaches an event listener to a target
    - * @param {Object} target The target to detach events from.
    - * @private
    - */
    -goog.ui.PopupMenu.prototype.detachEvent_ = function(target) {
    -  this.getHandler().unlisten(
    -      target.element_, target.eventType_, this.onTargetClick_);
    -};
    -
    -
    -/**
    - * Sets whether the menu should toggle if it is already open.  For context
    - * menus this should be false, for toolbar menus it makes more sense to be true.
    - * @param {boolean} toggle The new toggle mode.
    - */
    -goog.ui.PopupMenu.prototype.setToggleMode = function(toggle) {
    -  this.toggleMode_ = toggle;
    -};
    -
    -
    -/**
    - * Gets whether the menu is in toggle mode
    - * @return {boolean} toggle.
    - */
    -goog.ui.PopupMenu.prototype.getToggleMode = function() {
    -  return this.toggleMode_;
    -};
    -
    -
    -/**
    - * Show the menu using given positioning object.
    - * @param {goog.positioning.AbstractPosition} position The positioning instance.
    - * @param {goog.positioning.Corner=} opt_menuCorner The corner of the menu to be
    - *     positioned.
    - * @param {goog.math.Box=} opt_margin A margin specified in pixels.
    - * @param {Element=} opt_anchor The element which acts as visual anchor for this
    - *     menu.
    - */
    -goog.ui.PopupMenu.prototype.showWithPosition = function(position,
    -    opt_menuCorner, opt_margin, opt_anchor) {
    -  var isVisible = this.isVisible();
    -  if (this.isOrWasRecentlyVisible() && this.toggleMode_) {
    -    this.hide();
    -    return;
    -  }
    -
    -  // Set current anchor before dispatching BEFORE_SHOW. This is typically useful
    -  // when we would need to make modifications based on the current anchor to the
    -  // menu just before displaying it.
    -  this.currentAnchor_ = opt_anchor || null;
    -
    -  // Notify event handlers that the menu is about to be shown.
    -  if (!this.dispatchEvent(goog.ui.Component.EventType.BEFORE_SHOW)) {
    -    return;
    -  }
    -
    -  var menuCorner = typeof opt_menuCorner != 'undefined' ?
    -                   opt_menuCorner :
    -                   goog.positioning.Corner.TOP_START;
    -
    -  // This is a little hacky so that we can position the menu with minimal
    -  // flicker.
    -
    -  if (!isVisible) {
    -    // On IE, setting visibility = 'hidden' on a visible menu
    -    // will cause a blur, forcing the menu to close immediately.
    -    this.getElement().style.visibility = 'hidden';
    -  }
    -
    -  goog.style.setElementShown(this.getElement(), true);
    -  position.reposition(this.getElement(), menuCorner, opt_margin);
    -
    -  if (!isVisible) {
    -    this.getElement().style.visibility = 'visible';
    -  }
    -
    -  this.setHighlightedIndex(-1);
    -
    -  // setVisible dispatches a goog.ui.Component.EventType.SHOW event, which may
    -  // be canceled to prevent the menu from being shown.
    -  this.setVisible(true);
    -};
    -
    -
    -/**
    - * Show the menu at a given attached target.
    - * @param {Object} target Popup target.
    - * @param {number} x The client-X associated with the show event.
    - * @param {number} y The client-Y associated with the show event.
    - * @protected
    - */
    -goog.ui.PopupMenu.prototype.showMenu = function(target, x, y) {
    -  var position = goog.isDef(target.targetCorner_) ?
    -      new goog.positioning.AnchoredViewportPosition(target.element_,
    -          target.targetCorner_, true) :
    -      new goog.positioning.ViewportClientPosition(x, y);
    -  if (position.setLastResortOverflow) {
    -    // This is a ViewportClientPosition, so we can set the overflow policy.
    -    // Allow the menu to slide from the corner rather than clipping if it is
    -    // completely impossible to fit it otherwise.
    -    position.setLastResortOverflow(goog.positioning.Overflow.ADJUST_X |
    -                                   goog.positioning.Overflow.ADJUST_Y);
    -  }
    -  this.showWithPosition(position, target.menuCorner_, target.margin_,
    -                        target.element_);
    -};
    -
    -
    -/**
    - * Shows the menu immediately at the given client coordinates.
    - * @param {number} x The client-X associated with the show event.
    - * @param {number} y The client-Y associated with the show event.
    - * @param {goog.positioning.Corner=} opt_menuCorner Corner of the menu that
    - *     should be anchored.
    - */
    -goog.ui.PopupMenu.prototype.showAt = function(x, y, opt_menuCorner) {
    -  this.showWithPosition(
    -      new goog.positioning.ViewportClientPosition(x, y), opt_menuCorner);
    -};
    -
    -
    -/**
    - * Shows the menu immediately attached to the given element
    - * @param {Element} element The element to show at.
    - * @param {goog.positioning.Corner} targetCorner The corner of the target to
    - *     anchor to.
    - * @param {goog.positioning.Corner=} opt_menuCorner Corner of the menu that
    - *     should be anchored.
    - */
    -goog.ui.PopupMenu.prototype.showAtElement = function(element, targetCorner,
    -    opt_menuCorner) {
    -  this.showWithPosition(
    -      new goog.positioning.MenuAnchoredPosition(element, targetCorner, true),
    -      opt_menuCorner, null, element);
    -};
    -
    -
    -/**
    - * Hides the menu.
    - */
    -goog.ui.PopupMenu.prototype.hide = function() {
    -  if (!this.isVisible()) {
    -    return;
    -  }
    -
    -  // setVisible dispatches a goog.ui.Component.EventType.HIDE event, which may
    -  // be canceled to prevent the menu from being hidden.
    -  this.setVisible(false);
    -  if (!this.isVisible()) {
    -    // HIDE event wasn't canceled; the menu is now hidden.
    -    this.lastHide_ = goog.now();
    -    this.currentAnchor_ = null;
    -  }
    -};
    -
    -
    -/**
    - * Returns whether the menu is currently visible or was visible within about
    - * 150 ms ago.  This stops the menu toggling back on if the toggleMode == false.
    - * @return {boolean} Whether the popup is currently visible or was visible
    - *     within about 150 ms ago.
    - */
    -goog.ui.PopupMenu.prototype.isOrWasRecentlyVisible = function() {
    -  return this.isVisible() || this.wasRecentlyHidden();
    -};
    -
    -
    -/**
    - * Used to stop the menu toggling back on if the toggleMode == false.
    - * @return {boolean} Whether the menu was recently hidden.
    - * @protected
    - */
    -goog.ui.PopupMenu.prototype.wasRecentlyHidden = function() {
    -  return goog.now() - this.lastHide_ < goog.ui.PopupBase.DEBOUNCE_DELAY_MS;
    -};
    -
    -
    -/**
    - * Dismiss the popup menu when an action fires.
    - * @param {goog.events.Event=} opt_e The optional event.
    - * @private
    - */
    -goog.ui.PopupMenu.prototype.onAction_ = function(opt_e) {
    -  this.hide();
    -};
    -
    -
    -/**
    - * Handles a browser event on one of the popup targets
    - * @param {goog.events.BrowserEvent} e The browser event.
    - * @private
    - */
    -goog.ui.PopupMenu.prototype.onTargetClick_ = function(e) {
    -  var keys = this.targets_.getKeys();
    -  for (var i = 0; i < keys.length; i++) {
    -    var target = /** @type {Object} */(this.targets_.get(keys[i]));
    -    if (target.element_ == e.currentTarget) {
    -      this.showMenu(target,
    -                    /** @type {number} */ (e.clientX),
    -                    /** @type {number} */ (e.clientY));
    -      e.preventDefault();
    -      e.stopPropagation();
    -      return;
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Handles click events that propagate to the document.
    - * @param {goog.events.BrowserEvent} e The browser event.
    - * @protected
    - */
    -goog.ui.PopupMenu.prototype.onDocClick = function(e) {
    -  if (this.isVisible() &&
    -      !this.containsElement(/** @type {Element} */ (e.target))) {
    -    this.hide();
    -  }
    -};
    -
    -
    -/**
    - * Handles the key event target loosing focus.
    - * @param {goog.events.BrowserEvent} e The browser event.
    - * @protected
    - * @override
    - */
    -goog.ui.PopupMenu.prototype.handleBlur = function(e) {
    -  goog.ui.PopupMenu.superClass_.handleBlur.call(this, e);
    -  this.hide();
    -};
    -
    -
    -/** @override */
    -goog.ui.PopupMenu.prototype.disposeInternal = function() {
    -  // Always call the superclass' disposeInternal() first (Bug 715885).
    -  goog.ui.PopupMenu.superClass_.disposeInternal.call(this);
    -
    -  // Disposes of the attachment target map.
    -  if (this.targets_) {
    -    this.targets_.clear();
    -    delete this.targets_;
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/popupmenu_test.html b/src/database/third_party/closure-library/closure/goog/ui/popupmenu_test.html
    deleted file mode 100644
    index 28567275da9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/popupmenu_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.PopupMenu
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.PopupMenuTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="popup-anchor">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/popupmenu_test.js b/src/database/third_party/closure-library/closure/goog/ui/popupmenu_test.js
    deleted file mode 100644
    index dc2d2246812..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/popupmenu_test.js
    +++ /dev/null
    @@ -1,313 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.PopupMenuTest');
    -goog.setTestOnly('goog.ui.PopupMenuTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventType');
    -goog.require('goog.math.Box');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.positioning.Corner');
    -goog.require('goog.style');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.Menu');
    -goog.require('goog.ui.MenuItem');
    -goog.require('goog.ui.PopupMenu');
    -
    -var anchor;
    -
    -// Event handler
    -var handler;
    -var showPopup;
    -var beforeShowPopupCalled;
    -var popup;
    -
    -function setUp() {
    -  anchor = goog.dom.getElement('popup-anchor');
    -  handler = new goog.events.EventHandler();
    -  popup = new goog.ui.PopupMenu();
    -  popup.render();
    -}
    -
    -function tearDown() {
    -  handler.dispose();
    -  popup.dispose();
    -}
    -
    -
    -/**
    - * Asserts properties of {@code target} matches the expected value.
    - *
    - * @param {Object} target The target specifying how the popup menu should be
    - *     attached to an anchor.
    - * @param {Element} expectedElement The expected anchoring element.
    - * @param {goog.positioning.Corner} expectedTargetCorner The expected value of
    - *     the {@code target.targetCorner_} property.
    - * @param {goog.positioning.Corner} expectedMenuCorner The expected value of
    - *     the {@code target.menuCorner_} property.
    - * @param {goog.events.EventType} expectedEventType The expected value of the
    - *     {@code target.eventType_} property.
    - * @param {goog.math.Box} expectedMargin The expected value of the
    - *     {@code target.margin_} property.
    - */
    -function assertTarget(target, expectedElement, expectedTargetCorner,
    -    expectedMenuCorner, expectedEventType, expectedMargin) {
    -  var expectedTarget = {
    -    element_: expectedElement,
    -    targetCorner_: expectedTargetCorner,
    -    menuCorner_: expectedMenuCorner,
    -    eventType_: expectedEventType,
    -    margin_: expectedMargin
    -  };
    -
    -  assertObjectEquals('Target does not match.', expectedTarget, target);
    -}
    -
    -
    -/**
    - * Test menu receives BEFORE_SHOW event before it's displayed.
    - */
    -function testBeforeShowEvent() {
    -  var target = popup.createAttachTarget(anchor);
    -  popup.attach(anchor);
    -
    -  function beforeShowPopup(e) {
    -    // Ensure that the element is not yet visible.
    -    assertFalse('The element should not be shown when BEFORE_SHOW event is ' +
    -        'being handled',
    -        goog.style.isElementShown(popup.getElement()));
    -    // Verify that current anchor is set before dispatching BEFORE_SHOW.
    -    assertNotNullNorUndefined(popup.getAttachedElement());
    -    assertEquals('The attached anchor element is incorrect',
    -        target.element_, popup.getAttachedElement());
    -    beforeShowPopupCalled = true;
    -    return showPopup;
    -
    -  };
    -  function onShowPopup(e) {
    -    assertEquals('The attached anchor element is incorrect',
    -        target.element_, popup.getAttachedElement());
    -  };
    -
    -  handler.listen(popup,
    -                 goog.ui.Menu.EventType.BEFORE_SHOW,
    -                 beforeShowPopup);
    -  handler.listen(popup,
    -                 goog.ui.Menu.EventType.SHOW,
    -                 onShowPopup);
    -
    -  beforeShowPopupCalled = false;
    -  showPopup = false;
    -  popup.showMenu(target, 0, 0);
    -  assertTrue('BEFORE_SHOW event handler should be called on #showMenu',
    -      beforeShowPopupCalled);
    -  assertFalse('The element should not be shown when BEFORE_SHOW handler ' +
    -      'returned false',
    -      goog.style.isElementShown(popup.getElement()));
    -
    -  beforeShowPopupCalled = false;
    -  showPopup = true;
    -  popup.showMenu(target, 0, 0);
    -  assertTrue('The element should be shown when BEFORE_SHOW handler ' +
    -      'returned true',
    -      goog.style.isElementShown(popup.getElement()));
    -}
    -
    -
    -/**
    - * Test the behavior of {@link PopupMenu.isAttachTarget}.
    - */
    -function testIsAttachTarget() {
    -  // Before 'attach' is called.
    -  assertFalse('Menu should not be attached to the element',
    -      popup.isAttachTarget(anchor));
    -
    -  popup.attach(anchor);
    -  assertTrue('Menu should be attached to the anchor',
    -      popup.isAttachTarget(anchor));
    -
    -  popup.detach(anchor);
    -  assertFalse('Menu is expected to be detached from the element',
    -      popup.isAttachTarget(anchor));
    -}
    -
    -
    -/**
    - * Tests the behavior of {@link PopupMenu.createAttachTarget}.
    - */
    -function testCreateAttachTarget() {
    -  // Randomly picking parameters.
    -  var targetCorner = goog.positioning.Corner.TOP_END;
    -  var menuCorner = goog.positioning.Corner.BOTTOM_LEFT;
    -  var contextMenu = false;   // Show menu on mouse down event.
    -  var margin = new goog.math.Box(0, 10, 5, 25);
    -
    -  // Simply setting the required parameters.
    -  var target = popup.createAttachTarget(anchor);
    -  assertTrue(popup.isAttachTarget(anchor));
    -  assertTarget(target, anchor, undefined, undefined,
    -      goog.events.EventType.MOUSEDOWN, undefined);
    -
    -  // Creating another target with all the parameters.
    -  target = popup.createAttachTarget(anchor, targetCorner, menuCorner,
    -      contextMenu, margin);
    -  assertTrue(popup.isAttachTarget(anchor));
    -  assertTarget(target, anchor, targetCorner, menuCorner,
    -      goog.events.EventType.MOUSEDOWN, margin);
    -
    -  // Finally, switch up the 'contextMenu'
    -  target = popup.createAttachTarget(anchor, undefined, undefined,
    -      true /*opt_contextMenu*/, undefined);
    -  assertTarget(target, anchor, undefined, undefined,
    -      goog.events.EventType.CONTEXTMENU, undefined);
    -}
    -
    -
    -/**
    - * Tests the behavior of {@link PopupMenu.getAttachTarget}.
    - */
    -function testGetAttachTarget() {
    -  // Before the menu is attached to the anchor.
    -  var target = popup.getAttachTarget(anchor);
    -  assertTrue('Not expecting a target before the element is attach to the menu',
    -      target == null);
    -
    -  // Randomly picking parameters.
    -  var targetCorner = goog.positioning.Corner.TOP_END;
    -  var menuCorner = goog.positioning.Corner.BOTTOM_LEFT;
    -  var contextMenu = false;   // Show menu on mouse down event.
    -  var margin = new goog.math.Box(0, 10, 5, 25);
    -
    -  popup.attach(anchor, targetCorner, menuCorner, contextMenu, margin);
    -  target = popup.getAttachTarget(anchor);
    -  assertTrue('Failed to get target after attaching element to menu',
    -      target != null);
    -
    -  // Make sure we got the right target back.
    -  assertTarget(target, anchor, targetCorner, menuCorner,
    -      goog.events.EventType.MOUSEDOWN, margin);
    -}
    -
    -function testSmallViewportSliding() {
    -  popup.getElement().style.position = 'absolute';
    -  popup.getElement().style.outline = '1px solid blue';
    -  var item = new goog.ui.MenuItem('Test Item');
    -  popup.addChild(item, true);
    -  item.getElement().style.overflow = 'hidden';
    -
    -  var viewport = goog.style.getClientViewportElement();
    -  var viewportRect = goog.style.getVisibleRectForElement(viewport);
    -
    -  var middlePos = Math.floor((viewportRect.right - viewportRect.left) / 2);
    -  var leftwardPos = Math.floor((viewportRect.right - viewportRect.left) / 3);
    -  var rightwardPos =
    -      Math.floor((viewportRect.right - viewportRect.left) / 3 * 2);
    -
    -  // Can interpret these positions as widths relative to the viewport as well.
    -  var smallWidth = leftwardPos;
    -  var mediumWidth = middlePos;
    -  var largeWidth = rightwardPos;
    -
    -  // Test small menu first.  This should be small enough that it will display
    -  // its upper left corner where we tell it to in all three positions.
    -  popup.getElement().style.width = smallWidth + 'px';
    -
    -  var target = popup.createAttachTarget(anchor);
    -  popup.attach(anchor);
    -
    -  popup.showMenu(target, leftwardPos, 0);
    -  assertObjectEquals(
    -      'Popup in wrong position: small size, leftward pos',
    -      new goog.math.Coordinate(leftwardPos, 0),
    -      goog.style.getPosition(popup.getElement()));
    -
    -  popup.showMenu(target, middlePos, 0);
    -  assertObjectEquals(
    -      'Popup in wrong position: small size, middle pos',
    -      new goog.math.Coordinate(middlePos, 0),
    -      goog.style.getPosition(popup.getElement()));
    -
    -  popup.showMenu(target, rightwardPos, 0);
    -  assertObjectEquals(
    -      'Popup in wrong position: small size, rightward pos',
    -      new goog.math.Coordinate(rightwardPos, 0),
    -      goog.style.getPosition(popup.getElement()));
    -
    -  // Test medium menu next.  This should display with its upper left corner
    -  // at the target when leftward and middle, but on the right it should
    -  // position its upper right corner at the target instead.
    -  popup.getElement().style.width = mediumWidth + 'px';
    -
    -  popup.showMenu(target, leftwardPos, 0);
    -  assertObjectEquals(
    -      'Popup in wrong position: medium size, leftward pos',
    -      new goog.math.Coordinate(leftwardPos, 0),
    -      goog.style.getPosition(popup.getElement()));
    -
    -  popup.showMenu(target, middlePos, 0);
    -  assertObjectEquals(
    -      'Popup in wrong position: medium size, middle pos',
    -      new goog.math.Coordinate(middlePos, 0),
    -      goog.style.getPosition(popup.getElement()));
    -
    -  popup.showMenu(target, rightwardPos, 0);
    -  assertObjectEquals(
    -      'Popup in wrong position: medium size, rightward pos',
    -      new goog.math.Coordinate(rightwardPos - mediumWidth, 0),
    -      goog.style.getPosition(popup.getElement()));
    -
    -  // Test large menu next.  This should display with its upper left corner at
    -  // the target when leftward, and its upper right corner at the target when
    -  // rightward, but right in the middle neither corner can be at the target and
    -  // keep the entire menu onscreen, so it should place its upper right corner
    -  // at the very right edge of the viewport.
    -  popup.getElement().style.width = largeWidth + 'px';
    -  popup.showMenu(target, leftwardPos, 0);
    -  assertObjectEquals(
    -      'Popup in wrong position: large size, leftward pos',
    -      new goog.math.Coordinate(leftwardPos, 0),
    -      goog.style.getPosition(popup.getElement()));
    -
    -  popup.showMenu(target, middlePos, 0);
    -  assertObjectEquals(
    -      'Popup in wrong position: large size, middle pos',
    -      new goog.math.Coordinate(
    -          viewportRect.right - viewportRect.left - largeWidth, 0),
    -      goog.style.getPosition(popup.getElement()));
    -
    -  popup.showMenu(target, rightwardPos, 0);
    -  assertObjectEquals(
    -      'Popup in wrong position: large size, rightward pos',
    -      new goog.math.Coordinate(rightwardPos - largeWidth, 0),
    -      goog.style.getPosition(popup.getElement()));
    -
    -  // Make sure that the menu still displays correctly if we give the target
    -  // a target corner.  We can't set the overflow policy in that case, but it
    -  // should still display.
    -  popup.detach(anchor);
    -  anchor.style.position = 'absolute';
    -  anchor.style.left = '24px';
    -  anchor.style.top = '24px';
    -  var targetCorner = goog.positioning.Corner.TOP_END;
    -  target = popup.createAttachTarget(anchor, targetCorner);
    -  popup.attach(anchor, targetCorner);
    -  popup.getElement().style.width = smallWidth + 'px';
    -  popup.showMenu(target, leftwardPos, 0);
    -  assertObjectEquals(
    -      'Popup in wrong position: small size, leftward pos, with target corner',
    -      new goog.math.Coordinate(24, 24),
    -      goog.style.getPosition(popup.getElement()));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/progressbar.js b/src/database/third_party/closure-library/closure/goog/ui/progressbar.js
    deleted file mode 100644
    index f3a53b8a9e1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/progressbar.js
    +++ /dev/null
    @@ -1,407 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Implementation of a progress bar.
    - *
    - * @author arv@google.com (Erik Arvidsson)
    - * @see ../demos/progressbar.html
    - */
    -
    -
    -goog.provide('goog.ui.ProgressBar');
    -goog.provide('goog.ui.ProgressBar.Orientation');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events');
    -goog.require('goog.events.EventType');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.RangeModel');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * This creates a progress bar object.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @constructor
    - * @extends {goog.ui.Component}
    - */
    -goog.ui.ProgressBar = function(opt_domHelper) {
    -  goog.ui.Component.call(this, opt_domHelper);
    -
    -  /** @type {?HTMLDivElement} */
    -  this.thumbElement_;
    -
    -  /**
    -   * The underlying data model for the progress bar.
    -   * @type {goog.ui.RangeModel}
    -   * @private
    -   */
    -  this.rangeModel_ = new goog.ui.RangeModel;
    -  goog.events.listen(this.rangeModel_, goog.ui.Component.EventType.CHANGE,
    -                     this.handleChange_, false, this);
    -};
    -goog.inherits(goog.ui.ProgressBar, goog.ui.Component);
    -goog.tagUnsealableClass(goog.ui.ProgressBar);
    -
    -
    -/**
    - * Enum for representing the orientation of the progress bar.
    - *
    - * @enum {string}
    - */
    -goog.ui.ProgressBar.Orientation = {
    -  VERTICAL: 'vertical',
    -  HORIZONTAL: 'horizontal'
    -};
    -
    -
    -/**
    - * Map from progress bar orientation to CSS class names.
    - * @type {Object}
    - * @private
    - */
    -goog.ui.ProgressBar.ORIENTATION_TO_CSS_NAME_ = {};
    -goog.ui.ProgressBar.ORIENTATION_TO_CSS_NAME_[
    -    goog.ui.ProgressBar.Orientation.VERTICAL] =
    -    goog.getCssName('progress-bar-vertical');
    -goog.ui.ProgressBar.ORIENTATION_TO_CSS_NAME_[
    -    goog.ui.ProgressBar.Orientation.HORIZONTAL] =
    -    goog.getCssName('progress-bar-horizontal');
    -
    -
    -/**
    - * Creates the DOM nodes needed for the progress bar
    - * @override
    - */
    -goog.ui.ProgressBar.prototype.createDom = function() {
    -  this.thumbElement_ = this.createThumb_();
    -  var cs = goog.ui.ProgressBar.ORIENTATION_TO_CSS_NAME_[this.orientation_];
    -  this.setElementInternal(
    -      this.getDomHelper().createDom('div', cs, this.thumbElement_));
    -  this.setValueState_();
    -  this.setMinimumState_();
    -  this.setMaximumState_();
    -};
    -
    -
    -/** @override */
    -goog.ui.ProgressBar.prototype.enterDocument = function() {
    -  goog.ui.ProgressBar.superClass_.enterDocument.call(this);
    -  this.attachEvents_();
    -  this.updateUi_();
    -
    -  var element = this.getElement();
    -  goog.asserts.assert(element,
    -      'The progress bar DOM element cannot be null.');
    -  // state live = polite will notify the user of updates,
    -  // but will not interrupt ongoing feedback
    -  goog.a11y.aria.setRole(element, 'progressbar');
    -  goog.a11y.aria.setState(element, 'live', 'polite');
    -};
    -
    -
    -/** @override */
    -goog.ui.ProgressBar.prototype.exitDocument = function() {
    -  goog.ui.ProgressBar.superClass_.exitDocument.call(this);
    -  this.detachEvents_();
    -};
    -
    -
    -/**
    - * This creates the thumb element.
    - * @private
    - * @return {HTMLDivElement} The created thumb element.
    - */
    -goog.ui.ProgressBar.prototype.createThumb_ = function() {
    -  return /** @type {!HTMLDivElement} */ (this.getDomHelper().createDom('div',
    -      goog.getCssName('progress-bar-thumb')));
    -};
    -
    -
    -/**
    - * Adds the initial event listeners to the element.
    - * @private
    - */
    -goog.ui.ProgressBar.prototype.attachEvents_ = function() {
    -  if (goog.userAgent.IE && goog.userAgent.VERSION < 7) {
    -    goog.events.listen(this.getElement(), goog.events.EventType.RESIZE,
    -                       this.updateUi_, false, this);
    -  }
    -};
    -
    -
    -/**
    - * Removes the event listeners added by attachEvents_.
    - * @private
    - */
    -goog.ui.ProgressBar.prototype.detachEvents_ = function() {
    -  if (goog.userAgent.IE && goog.userAgent.VERSION < 7) {
    -    goog.events.unlisten(this.getElement(), goog.events.EventType.RESIZE,
    -                         this.updateUi_, false, this);
    -  }
    -};
    -
    -
    -/**
    - * Decorates an existing HTML DIV element as a progress bar input. If the
    - * element contains a child with a class name of 'progress-bar-thumb' that will
    - * be used as the thumb.
    - * @param {Element} element  The HTML element to decorate.
    - * @override
    - */
    -goog.ui.ProgressBar.prototype.decorateInternal = function(element) {
    -  goog.ui.ProgressBar.superClass_.decorateInternal.call(this, element);
    -  goog.dom.classlist.add(
    -      goog.asserts.assert(this.getElement()),
    -      goog.ui.ProgressBar.ORIENTATION_TO_CSS_NAME_[this.orientation_]);
    -
    -  // find thumb
    -  var thumb = goog.dom.getElementsByTagNameAndClass(
    -      null, goog.getCssName('progress-bar-thumb'), this.getElement())[0];
    -  if (!thumb) {
    -    thumb = this.createThumb_();
    -    this.getElement().appendChild(thumb);
    -  }
    -  this.thumbElement_ = thumb;
    -};
    -
    -
    -/**
    - * @return {number} The value.
    - */
    -goog.ui.ProgressBar.prototype.getValue = function() {
    -  return this.rangeModel_.getValue();
    -};
    -
    -
    -/**
    - * Sets the value
    - * @param {number} v The value.
    - */
    -goog.ui.ProgressBar.prototype.setValue = function(v) {
    -  this.rangeModel_.setValue(v);
    -  if (this.getElement()) {
    -    this.setValueState_();
    -  }
    -};
    -
    -
    -/**
    - * Sets the state for a11y of the current value.
    - * @private
    - */
    -goog.ui.ProgressBar.prototype.setValueState_ = function() {
    -  var element = this.getElement();
    -  goog.asserts.assert(element,
    -      'The progress bar DOM element cannot be null.');
    -  goog.a11y.aria.setState(element, 'valuenow', this.getValue());
    -};
    -
    -
    -/**
    - * @return {number} The minimum value.
    - */
    -goog.ui.ProgressBar.prototype.getMinimum = function() {
    -  return this.rangeModel_.getMinimum();
    -};
    -
    -
    -/**
    - * Sets the minimum number
    - * @param {number} v The minimum value.
    - */
    -goog.ui.ProgressBar.prototype.setMinimum = function(v) {
    -  this.rangeModel_.setMinimum(v);
    -  if (this.getElement()) {
    -    this.setMinimumState_();
    -  }
    -};
    -
    -
    -/**
    - * Sets the state for a11y of the minimum value.
    - * @private
    - */
    -goog.ui.ProgressBar.prototype.setMinimumState_ = function() {
    -  var element = this.getElement();
    -  goog.asserts.assert(element,
    -      'The progress bar DOM element cannot be null.');
    -  goog.a11y.aria.setState(element, 'valuemin', this.getMinimum());
    -};
    -
    -
    -/**
    - * @return {number} The maximum value.
    - */
    -goog.ui.ProgressBar.prototype.getMaximum = function() {
    -  return this.rangeModel_.getMaximum();
    -};
    -
    -
    -/**
    - * Sets the maximum number
    - * @param {number} v The maximum value.
    - */
    -goog.ui.ProgressBar.prototype.setMaximum = function(v) {
    -  this.rangeModel_.setMaximum(v);
    -  if (this.getElement()) {
    -    this.setMaximumState_();
    -  }
    -};
    -
    -
    -/**
    - * Sets the state for a11y of the maximum valiue.
    - * @private
    - */
    -goog.ui.ProgressBar.prototype.setMaximumState_ = function() {
    -  var element = this.getElement();
    -  goog.asserts.assert(element,
    -      'The progress bar DOM element cannot be null.');
    -  goog.a11y.aria.setState(element, 'valuemax', this.getMaximum());
    -};
    -
    -
    -/**
    - *
    - * @type {goog.ui.ProgressBar.Orientation}
    - * @private
    - */
    -goog.ui.ProgressBar.prototype.orientation_ =
    -    goog.ui.ProgressBar.Orientation.HORIZONTAL;
    -
    -
    -/**
    - * Call back when the internal range model changes
    - * @param {goog.events.Event} e The event object.
    - * @private
    - */
    -goog.ui.ProgressBar.prototype.handleChange_ = function(e) {
    -  this.updateUi_();
    -  this.dispatchEvent(goog.ui.Component.EventType.CHANGE);
    -};
    -
    -
    -/**
    - * This is called when we need to update the size of the thumb. This happens
    - * when first created as well as when the value and the orientation changes.
    - * @private
    - */
    -goog.ui.ProgressBar.prototype.updateUi_ = function() {
    -  if (this.thumbElement_) {
    -    var min = this.getMinimum();
    -    var max = this.getMaximum();
    -    var val = this.getValue();
    -    var ratio = (val - min) / (max - min);
    -    var size = Math.round(ratio * 100);
    -    if (this.orientation_ == goog.ui.ProgressBar.Orientation.VERTICAL) {
    -      // Note(arv): IE up to version 6 has some serious computation bugs when
    -      // using percentages or bottom. We therefore first set the height to
    -      // 100% and measure that and base the top and height on that size instead.
    -      if (goog.userAgent.IE && goog.userAgent.VERSION < 7) {
    -        this.thumbElement_.style.top = 0;
    -        this.thumbElement_.style.height = '100%';
    -        var h = this.thumbElement_.offsetHeight;
    -        var bottom = Math.round(ratio * h);
    -        this.thumbElement_.style.top = h - bottom + 'px';
    -        this.thumbElement_.style.height = bottom + 'px';
    -      } else {
    -        this.thumbElement_.style.top = (100 - size) + '%';
    -        this.thumbElement_.style.height = size + '%';
    -      }
    -    } else {
    -      this.thumbElement_.style.width = size + '%';
    -    }
    -  }
    -};
    -
    -
    -/**
    - * This is called when we need to setup the UI sizes and positions. This
    - * happens when we create the element and when we change the orientation.
    - * @private
    - */
    -goog.ui.ProgressBar.prototype.initializeUi_ = function() {
    -  var tStyle = this.thumbElement_.style;
    -  if (this.orientation_ == goog.ui.ProgressBar.Orientation.VERTICAL) {
    -    tStyle.left = 0;
    -    tStyle.width = '100%';
    -  } else {
    -    tStyle.top = tStyle.left = 0;
    -    tStyle.height = '100%';
    -  }
    -};
    -
    -
    -/**
    - * Changes the orientation
    - * @param {goog.ui.ProgressBar.Orientation} orient The orientation.
    - */
    -goog.ui.ProgressBar.prototype.setOrientation = function(orient) {
    -  if (this.orientation_ != orient) {
    -    var oldCss =
    -        goog.ui.ProgressBar.ORIENTATION_TO_CSS_NAME_[this.orientation_];
    -    var newCss = goog.ui.ProgressBar.ORIENTATION_TO_CSS_NAME_[orient];
    -    this.orientation_ = orient;
    -
    -    // Update the DOM
    -    var element = this.getElement();
    -    if (element) {
    -      goog.dom.classlist.swap(element, oldCss, newCss);
    -      this.initializeUi_();
    -      this.updateUi_();
    -    }
    -  }
    -};
    -
    -
    -/**
    - * @return {goog.ui.ProgressBar.Orientation} The orientation of the
    - *     progress bar.
    - */
    -goog.ui.ProgressBar.prototype.getOrientation = function() {
    -  return this.orientation_;
    -};
    -
    -
    -/** @override */
    -goog.ui.ProgressBar.prototype.disposeInternal = function() {
    -  this.detachEvents_();
    -  goog.ui.ProgressBar.superClass_.disposeInternal.call(this);
    -  this.thumbElement_ = null;
    -  this.rangeModel_.dispose();
    -};
    -
    -
    -/**
    - * @return {?number} The step value used to determine how to round the value.
    - */
    -goog.ui.ProgressBar.prototype.getStep = function() {
    -  return this.rangeModel_.getStep();
    -};
    -
    -
    -/**
    - * Sets the step value. The step value is used to determine how to round the
    - * value.
    - * @param {?number} step  The step size.
    - */
    -goog.ui.ProgressBar.prototype.setStep = function(step) {
    -  this.rangeModel_.setStep(step);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/prompt.js b/src/database/third_party/closure-library/closure/goog/ui/prompt.js
    deleted file mode 100644
    index 752f49ca8db..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/prompt.js
    +++ /dev/null
    @@ -1,409 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview DHTML prompt to replace javascript's prompt().
    - *
    - * @see ../demos/prompt.html
    - */
    -
    -
    -goog.provide('goog.ui.Prompt');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.EventType');
    -goog.require('goog.functions');
    -goog.require('goog.html.SafeHtml');
    -goog.require('goog.html.legacyconversions');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.Dialog');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Creates an object that represents a prompt (used in place of javascript's
    - * prompt). The html structure of the prompt is the same as the layout for
    - * dialog.js except for the addition of a text box which is placed inside the
    - * "Content area" and has the default class-name 'modal-dialog-userInput'
    - *
    - * @param {string} promptTitle The title of the prompt.
    - * @param {string|!goog.html.SafeHtml} promptHtml The HTML body of the prompt.
    - *     The variable is trusted and it should be already properly escaped.
    - * @param {Function} callback The function to call when the user selects Ok or
    - *     Cancel. The function should expect a single argument which represents
    - *     what the user entered into the prompt. If the user presses cancel, the
    - *     value of the argument will be null.
    - * @param {string=} opt_defaultValue Optional default value that should be in
    - *     the text box when the prompt appears.
    - * @param {string=} opt_class Optional prefix for the classes.
    - * @param {boolean=} opt_useIframeForIE For IE, workaround windowed controls
    - *     z-index issue by using a an iframe instead of a div for bg element.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper; see {@link
    - *    goog.ui.Component} for semantics.
    - * @constructor
    - * @extends {goog.ui.Dialog}
    - */
    -goog.ui.Prompt = function(promptTitle, promptHtml, callback, opt_defaultValue,
    -    opt_class, opt_useIframeForIE, opt_domHelper) {
    -  goog.ui.Prompt.base(this, 'constructor',
    -      opt_class, opt_useIframeForIE, opt_domHelper);
    -
    -  /**
    -   * The id of the input element.
    -   * @type {string}
    -   * @private
    -   */
    -  this.inputElementId_ = this.makeId('ie');
    -
    -  this.setTitle(promptTitle);
    -
    -  var label = goog.html.SafeHtml.create('label', {'for': this.inputElementId_},
    -      promptHtml instanceof goog.html.SafeHtml ? promptHtml :
    -          goog.html.legacyconversions.safeHtmlFromString(promptHtml));
    -  var br = goog.html.SafeHtml.create('br');
    -  this.setSafeHtmlContent(goog.html.SafeHtml.concat(label, br, br));
    -
    -  this.callback_ = callback;
    -  this.defaultValue_ = goog.isDef(opt_defaultValue) ? opt_defaultValue : '';
    -
    -  /** @desc label for a dialog button. */
    -  var MSG_PROMPT_OK = goog.getMsg('OK');
    -  /** @desc label for a dialog button. */
    -  var MSG_PROMPT_CANCEL = goog.getMsg('Cancel');
    -  var buttonSet = new goog.ui.Dialog.ButtonSet(opt_domHelper);
    -  buttonSet.set(goog.ui.Dialog.DefaultButtonKeys.OK, MSG_PROMPT_OK, true);
    -  buttonSet.set(goog.ui.Dialog.DefaultButtonKeys.CANCEL,
    -      MSG_PROMPT_CANCEL, false, true);
    -  this.setButtonSet(buttonSet);
    -};
    -goog.inherits(goog.ui.Prompt, goog.ui.Dialog);
    -goog.tagUnsealableClass(goog.ui.Prompt);
    -
    -
    -/**
    - * Callback function which is invoked with the response to the prompt
    - * @type {Function}
    - * @private
    - */
    -goog.ui.Prompt.prototype.callback_ = goog.nullFunction;
    -
    -
    -/**
    - * Default value to display in prompt window
    - * @type {string}
    - * @private
    - */
    -goog.ui.Prompt.prototype.defaultValue_ = '';
    -
    -
    -/**
    - * Element in which user enters response (HTML <input> text box)
    - * @type {HTMLInputElement}
    - * @private
    - */
    -goog.ui.Prompt.prototype.userInputEl_ = null;
    -
    -
    -/**
    - * Tracks whether the prompt is in the process of closing to prevent multiple
    - * calls to the callback when the user presses enter.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.Prompt.prototype.isClosing_ = false;
    -
    -
    -/**
    - * Number of rows in the user input element.
    - * The default is 1 which means use an <input> element.
    - * @type {number}
    - * @private
    - */
    -goog.ui.Prompt.prototype.rows_ = 1;
    -
    -
    -/**
    - * Number of cols in the user input element.
    - * The default is 0 which means use browser default.
    - * @type {number}
    - * @private
    - */
    -goog.ui.Prompt.prototype.cols_ = 0;
    -
    -
    -/**
    - * The input decorator function.
    - * @type {function(Element)?}
    - * @private
    - */
    -goog.ui.Prompt.prototype.inputDecoratorFn_ = null;
    -
    -
    -/**
    - * A validation function that takes a string and returns true if the string is
    - * accepted, false otherwise.
    - * @type {function(string):boolean}
    - * @private
    - */
    -goog.ui.Prompt.prototype.validationFn_ = goog.functions.TRUE;
    -
    -
    -/**
    - * Sets the validation function that takes a string and returns true if the
    - * string is accepted, false otherwise.
    - * @param {function(string): boolean} fn The validation function to use on user
    - *     input.
    - */
    -goog.ui.Prompt.prototype.setValidationFunction = function(fn) {
    -  this.validationFn_ = fn;
    -};
    -
    -
    -/** @override */
    -goog.ui.Prompt.prototype.enterDocument = function() {
    -  if (this.inputDecoratorFn_) {
    -    this.inputDecoratorFn_(this.userInputEl_);
    -  }
    -  goog.ui.Prompt.superClass_.enterDocument.call(this);
    -  this.getHandler().listen(this,
    -      goog.ui.Dialog.EventType.SELECT, this.onPromptExit_);
    -
    -  this.getHandler().listen(this.userInputEl_,
    -      [goog.events.EventType.KEYUP, goog.events.EventType.CHANGE],
    -      this.handleInputChanged_);
    -};
    -
    -
    -/**
    - * @return {HTMLInputElement} The user input element. May be null if the Prompt
    - *     has not been rendered.
    - */
    -goog.ui.Prompt.prototype.getInputElement = function() {
    -  return this.userInputEl_;
    -};
    -
    -
    -/**
    - * Sets an input decorator function.  This function will be called in
    - * #enterDocument and will be passed the input element.  This is useful for
    - * attaching handlers to the input element for specific change events,
    - * for example.
    - * @param {function(Element)} inputDecoratorFn A function to call on the input
    - *     element on #enterDocument.
    - */
    -goog.ui.Prompt.prototype.setInputDecoratorFn = function(inputDecoratorFn) {
    -  this.inputDecoratorFn_ = inputDecoratorFn;
    -};
    -
    -
    -/**
    - * Set the number of rows in the user input element.
    - * A values of 1 means use an <input> element.  If the prompt is already
    - * rendered then you cannot change from <input> to <textarea> or vice versa.
    - * @param {number} rows Number of rows for user input element.
    - * @throws {goog.ui.Component.Error.ALREADY_RENDERED} If the component is
    - *    already rendered and an attempt to change between <input> and <textarea>
    - *    is made.
    - */
    -goog.ui.Prompt.prototype.setRows = function(rows) {
    -  if (this.isInDocument()) {
    -    if (this.userInputEl_.tagName.toLowerCase() == 'input') {
    -      if (rows > 1) {
    -        throw Error(goog.ui.Component.Error.ALREADY_RENDERED);
    -      }
    -    } else {
    -      if (rows <= 1) {
    -        throw Error(goog.ui.Component.Error.ALREADY_RENDERED);
    -      }
    -      this.userInputEl_.rows = rows;
    -    }
    -  }
    -  this.rows_ = rows;
    -};
    -
    -
    -/**
    - * @return {number} The number of rows in the user input element.
    - */
    -goog.ui.Prompt.prototype.getRows = function() {
    -  return this.rows_;
    -};
    -
    -
    -/**
    - * Set the number of cols in the user input element.
    - * @param {number} cols Number of cols for user input element.
    - */
    -goog.ui.Prompt.prototype.setCols = function(cols) {
    -  this.cols_ = cols;
    -  if (this.userInputEl_) {
    -    if (this.userInputEl_.tagName.toLowerCase() == 'input') {
    -      this.userInputEl_.size = cols;
    -    } else {
    -      this.userInputEl_.cols = cols;
    -    }
    -  }
    -};
    -
    -
    -/**
    - * @return {number} The number of cols in the user input element.
    - */
    -goog.ui.Prompt.prototype.getCols = function() {
    -  return this.cols_;
    -};
    -
    -
    -/**
    - * Create the initial DOM representation for the prompt.
    - * @override
    - */
    -goog.ui.Prompt.prototype.createDom = function() {
    -  goog.ui.Prompt.superClass_.createDom.call(this);
    -
    -  var cls = this.getClass();
    -
    -  // add input box to the content
    -  var attrs = {
    -    'className': goog.getCssName(cls, 'userInput'),
    -    'value': this.defaultValue_};
    -  if (this.rows_ == 1) {
    -    // If rows == 1 then use an input element.
    -    this.userInputEl_ = /** @type {!HTMLInputElement} */
    -        (this.getDomHelper().createDom('input', attrs));
    -    this.userInputEl_.type = 'text';
    -    if (this.cols_) {
    -      this.userInputEl_.size = this.cols_;
    -    }
    -  } else {
    -    // If rows > 1 then use a textarea.
    -    this.userInputEl_ = /** @type {!HTMLInputElement} */
    -        (this.getDomHelper().createDom('textarea', attrs));
    -    this.userInputEl_.rows = this.rows_;
    -    if (this.cols_) {
    -      this.userInputEl_.cols = this.cols_;
    -    }
    -  }
    -
    -  this.userInputEl_.id = this.inputElementId_;
    -  var contentEl = this.getContentElement();
    -  contentEl.appendChild(this.getDomHelper().createDom(
    -      'div', {'style': 'overflow: auto'}, this.userInputEl_));
    -};
    -
    -
    -/**
    - * Handles input change events on the input field.  Disables the OK button if
    - * validation fails on the new input value.
    - * @private
    - */
    -goog.ui.Prompt.prototype.handleInputChanged_ = function() {
    -  this.updateOkButtonState_();
    -};
    -
    -
    -/**
    - * Set OK button enabled/disabled state based on input.
    - * @private
    - */
    -goog.ui.Prompt.prototype.updateOkButtonState_ = function() {
    -  var enableOkButton = this.validationFn_(this.userInputEl_.value);
    -  var buttonSet = this.getButtonSet();
    -  buttonSet.setButtonEnabled(goog.ui.Dialog.DefaultButtonKeys.OK,
    -      enableOkButton);
    -};
    -
    -
    -/**
    - * Causes the prompt to appear, centered on the screen, gives focus
    - * to the text box, and selects the text
    - * @param {boolean} visible Whether the dialog should be visible.
    - * @override
    - */
    -goog.ui.Prompt.prototype.setVisible = function(visible) {
    -  goog.ui.Prompt.base(this, 'setVisible', visible);
    -
    -  if (visible) {
    -    this.isClosing_ = false;
    -    this.userInputEl_.value = this.defaultValue_;
    -    this.focus();
    -    this.updateOkButtonState_();
    -  }
    -};
    -
    -
    -/**
    - * Overrides setFocus to put focus on the input element.
    - * @override
    - */
    -goog.ui.Prompt.prototype.focus = function() {
    -  goog.ui.Prompt.base(this, 'focus');
    -
    -  if (goog.userAgent.OPERA) {
    -    // select() doesn't focus <input> elements in Opera.
    -    this.userInputEl_.focus();
    -  }
    -  this.userInputEl_.select();
    -};
    -
    -
    -/**
    - * Sets the default value of the prompt when it is displayed.
    - * @param {string} defaultValue The default value to display.
    - */
    -goog.ui.Prompt.prototype.setDefaultValue = function(defaultValue) {
    -  this.defaultValue_ = defaultValue;
    -};
    -
    -
    -/**
    - * Handles the closing of the prompt, invoking the callback function that was
    - * registered to handle the value returned by the prompt.
    - * @param {goog.ui.Dialog.Event} e The dialog's selection event.
    - * @private
    - */
    -goog.ui.Prompt.prototype.onPromptExit_ = function(e) {
    -  /*
    -   * The timeouts below are required for one edge case. If after the dialog
    -   * hides, suppose validation of the input fails which displays an alert. If
    -   * the user pressed the Enter key to dismiss the alert that was displayed it
    -   * can trigger the event handler a second time. This timeout ensures that the
    -   * alert is displayed only after the prompt is able to clean itself up.
    -   */
    -  if (!this.isClosing_) {
    -    this.isClosing_ = true;
    -    if (e.key == 'ok') {
    -      goog.Timer.callOnce(
    -          goog.bind(this.callback_, this, this.userInputEl_.value), 1);
    -    } else {
    -      goog.Timer.callOnce(goog.bind(this.callback_, this, null), 1);
    -    }
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.Prompt.prototype.disposeInternal = function() {
    -  goog.dom.removeNode(this.userInputEl_);
    -
    -  goog.events.unlisten(this, goog.ui.Dialog.EventType.SELECT,
    -      this.onPromptExit_, true, this);
    -
    -  goog.ui.Prompt.superClass_.disposeInternal.call(this);
    -
    -  this.userInputEl_ = null;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/prompt_test.html b/src/database/third_party/closure-library/closure/goog/ui/prompt_test.html
    deleted file mode 100644
    index 079b198bd72..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/prompt_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.Prompt
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.PromptTest');
    -  </script>
    -  <link rel="stylesheet" type="text/css" href="../css/common.css" />
    -  <link rel="stylesheet" type="text/css" href="../css/dialog.css" />
    - </head>
    - <body>
    -  <input type="button" value="Prompt" onclick="newPrompt();" />
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/prompt_test.js b/src/database/third_party/closure-library/closure/goog/ui/prompt_test.js
    deleted file mode 100644
    index df289a54a58..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/prompt_test.js
    +++ /dev/null
    @@ -1,139 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.PromptTest');
    -goog.setTestOnly('goog.ui.PromptTest');
    -
    -goog.require('goog.dom.selection');
    -goog.require('goog.events.InputHandler');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.functions');
    -goog.require('goog.string');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.BidiInput');
    -goog.require('goog.ui.Dialog');
    -goog.require('goog.ui.Prompt');
    -goog.require('goog.userAgent');
    -goog.require('goog.userAgent.product');
    -
    -var prompt;
    -
    -function setUp() {
    -  document.body.focus();
    -}
    -
    -function tearDown() {
    -  goog.dispose(prompt);
    -}
    -
    -function testFocusOnInputElement() {
    -  // FF does not perform focus if the window is not active in the first place.
    -  if (goog.userAgent.GECKO && document.hasFocus && !document.hasFocus()) {
    -    return;
    -  }
    -
    -  var promptResult = undefined;
    -  prompt = new goog.ui.Prompt('title', 'Prompt:', function(result) {
    -    promptResult = result;
    -  }, 'defaultValue');
    -  prompt.setVisible(true);
    -
    -  if (goog.userAgent.product.CHROME) {
    -    // For some reason, this test fails non-deterministically on Chrome,
    -    // but only on the test farm.
    -    return;
    -  }
    -  assertEquals('defaultValue',
    -      goog.dom.selection.getText(prompt.userInputEl_));
    -}
    -
    -
    -function testValidationFunction() {
    -  var promptResult = undefined;
    -  prompt = new goog.ui.Prompt('title', 'Prompt:', function(result) {
    -    promptResult = result;
    -  }, '');
    -  prompt.setValidationFunction(goog.functions.not(goog.string.isEmptyOrWhitespace));
    -  prompt.setVisible(true);
    -
    -  var buttonSet = prompt.getButtonSet();
    -  var okButton = buttonSet.getButton(goog.ui.Dialog.DefaultButtonKeys.OK);
    -  assertTrue(okButton.disabled);
    -
    -  prompt.userInputEl_.value = '';
    -  goog.testing.events.fireKeySequence(prompt.userInputEl_,
    -      goog.events.KeyCodes.SPACE);
    -  assertTrue(okButton.disabled);
    -  prompt.userInputEl_.value = 'foo';
    -  goog.testing.events.fireKeySequence(prompt.userInputEl_,
    -      goog.events.KeyCodes.X);
    -  assertFalse(okButton.disabled);
    -}
    -
    -function testBidiInput() {
    -  var shalomInHebrew = '\u05e9\u05dc\u05d5\u05dd';
    -  var promptResult = undefined;
    -  prompt = new goog.ui.Prompt('title', 'Prompt:', goog.functions.NULL, '');
    -  var bidiInput = new goog.ui.BidiInput();
    -  prompt.setInputDecoratorFn(goog.bind(bidiInput.decorate, bidiInput));
    -  prompt.setVisible(true);
    -
    -  prompt.userInputEl_.value = shalomInHebrew;
    -  goog.testing.events.fireKeySequence(prompt.userInputEl_,
    -      goog.events.KeyCodes.SPACE);
    -  goog.testing.events.fireBrowserEvent(
    -      {'target' : prompt.userInputEl_, 'type' : 'input'});
    -  bidiInput.inputHandler_.dispatchEvent(
    -      goog.events.InputHandler.EventType.INPUT);
    -  assertEquals('rtl', prompt.userInputEl_.dir);
    -
    -  prompt.userInputEl_.value = 'shalomInEnglish';
    -  goog.testing.events.fireKeySequence(prompt.userInputEl_,
    -      goog.events.KeyCodes.SPACE);
    -  goog.testing.events.fireBrowserEvent(
    -      {'target' : prompt.userInputEl_, 'type' : 'input'});
    -  bidiInput.inputHandler_.dispatchEvent(
    -      goog.events.InputHandler.EventType.INPUT);
    -  assertEquals('ltr', prompt.userInputEl_.dir);
    -  goog.dispose(bidiInput);
    -}
    -
    -function testBidiInput_off() {
    -  var shalomInHebrew = '\u05e9\u05dc\u05d5\u05dd';
    -  var promptResult = undefined;
    -  prompt = new goog.ui.Prompt('title', 'Prompt:', goog.functions.NULL, '');
    -  prompt.setVisible(true);
    -
    -  prompt.userInputEl_.value = shalomInHebrew;
    -  goog.testing.events.fireKeySequence(prompt.userInputEl_,
    -      goog.events.KeyCodes.SPACE);
    -  goog.testing.events.fireBrowserEvent(
    -      {'target' : prompt.userInputEl_, 'type' : 'input'});
    -  assertEquals('', prompt.userInputEl_.dir);
    -
    -  prompt.userInputEl_.value = 'shalomInEnglish';
    -  goog.testing.events.fireKeySequence(prompt.userInputEl_,
    -      goog.events.KeyCodes.SPACE);
    -  assertEquals('', prompt.userInputEl_.dir);
    -}
    -
    -// An interactive test so we can manually see what it looks like.
    -function newPrompt() {
    -  prompt = new goog.ui.Prompt('title', 'Prompt:', function(result) {
    -    alert('Result: ' + result);
    -    goog.dispose(prompt);
    -  }, 'defaultValue');
    -  prompt.setVisible(true);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/rangemodel.js b/src/database/third_party/closure-library/closure/goog/ui/rangemodel.js
    deleted file mode 100644
    index 0a8afac6d8c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/rangemodel.js
    +++ /dev/null
    @@ -1,303 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Implementation of a range model. This is an implementation of
    - * the BoundedRangeModel as described by Java at
    - * http://java.sun.com/javase/6/docs/api/javax/swing/BoundedRangeModel.html.
    - *
    - * One good way to understand the range model is to think of a scroll bar for
    - * a scrollable element. In that case minimum is 0, maximum is scrollHeight,
    - * value is scrollTop and extent is clientHeight.
    - *
    - * Based on http://webfx.eae.net/dhtml/slider/js/range.js
    - *
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -goog.provide('goog.ui.RangeModel');
    -
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.ui.Component');
    -
    -
    -
    -/**
    - * Creates a range model
    - * @extends {goog.events.EventTarget}
    - * @constructor
    - */
    -goog.ui.RangeModel = function() {
    -  goog.events.EventTarget.call(this);
    -};
    -goog.inherits(goog.ui.RangeModel, goog.events.EventTarget);
    -goog.tagUnsealableClass(goog.ui.RangeModel);
    -
    -
    -/**
    - * @type {number}
    - * @private
    - */
    -goog.ui.RangeModel.prototype.value_ = 0;
    -
    -
    -/**
    - * @type {number}
    - * @private
    - */
    -goog.ui.RangeModel.prototype.minimum_ = 0;
    -
    -
    -/**
    - * @type {number}
    - * @private
    - */
    -goog.ui.RangeModel.prototype.maximum_ = 100;
    -
    -
    -/**
    - * @type {number}
    - * @private
    - */
    -goog.ui.RangeModel.prototype.extent_ = 0;
    -
    -
    -/**
    - * @type {?number}
    - * @private
    - */
    -goog.ui.RangeModel.prototype.step_ = 1;
    -
    -
    -/**
    - * This is true if something is changed as a side effect. This happens when for
    - * example we set the maximum below the current value.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.RangeModel.prototype.isChanging_ = false;
    -
    -
    -/**
    - * If set to true, we do not fire any change events.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.RangeModel.prototype.mute_ = false;
    -
    -
    -/**
    - * Sets the model to mute / unmute.
    - * @param {boolean} muteValue Whether or not to mute the range, i.e.,
    - *     suppress any CHANGE events.
    - */
    -goog.ui.RangeModel.prototype.setMute = function(muteValue) {
    -  this.mute_ = muteValue;
    -};
    -
    -
    -/**
    - * Sets the value.
    - * @param {number} value The new value.
    - */
    -goog.ui.RangeModel.prototype.setValue = function(value) {
    -  value = this.roundToStepWithMin(value);
    -  if (this.value_ != value) {
    -    if (value + this.extent_ > this.maximum_) {
    -      this.value_ = this.maximum_ - this.extent_;
    -    } else if (value < this.minimum_) {
    -      this.value_ = this.minimum_;
    -    } else {
    -      this.value_ = value;
    -    }
    -    if (!this.isChanging_ && !this.mute_) {
    -      this.dispatchEvent(goog.ui.Component.EventType.CHANGE);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * @return {number} the current value.
    - */
    -goog.ui.RangeModel.prototype.getValue = function() {
    -  return this.roundToStepWithMin(this.value_);
    -};
    -
    -
    -/**
    - * Sets the extent. The extent is the 'size' of the value.
    - * @param {number} extent The new extent.
    - */
    -goog.ui.RangeModel.prototype.setExtent = function(extent) {
    -  extent = this.roundToStepWithMin(extent);
    -  if (this.extent_ != extent) {
    -    if (extent < 0) {
    -      this.extent_ = 0;
    -    } else if (this.value_ + extent > this.maximum_) {
    -      this.extent_ = this.maximum_ - this.value_;
    -    } else {
    -      this.extent_ = extent;
    -    }
    -    if (!this.isChanging_ && !this.mute_) {
    -      this.dispatchEvent(goog.ui.Component.EventType.CHANGE);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * @return {number} The extent for the range model.
    - */
    -goog.ui.RangeModel.prototype.getExtent = function() {
    -  return this.roundToStep(this.extent_);
    -};
    -
    -
    -/**
    - * Sets the minimum
    - * @param {number} minimum The new minimum.
    - */
    -goog.ui.RangeModel.prototype.setMinimum = function(minimum) {
    -  // Don't round minimum because it is the base
    -  if (this.minimum_ != minimum) {
    -    var oldIsChanging = this.isChanging_;
    -    this.isChanging_ = true;
    -
    -    this.minimum_ = minimum;
    -
    -    if (minimum + this.extent_ > this.maximum_) {
    -      this.extent_ = this.maximum_ - this.minimum_;
    -    }
    -    if (minimum > this.value_) {
    -      this.setValue(minimum);
    -    }
    -    if (minimum > this.maximum_) {
    -      this.extent_ = 0;
    -      this.setMaximum(minimum);
    -      this.setValue(minimum);
    -    }
    -
    -
    -    this.isChanging_ = oldIsChanging;
    -    if (!this.isChanging_ && !this.mute_) {
    -      this.dispatchEvent(goog.ui.Component.EventType.CHANGE);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * @return {number} The minimum value for the range model.
    - */
    -goog.ui.RangeModel.prototype.getMinimum = function() {
    -  return this.roundToStepWithMin(this.minimum_);
    -};
    -
    -
    -/**
    - * Sets the maximum
    - * @param {number} maximum The new maximum.
    - */
    -goog.ui.RangeModel.prototype.setMaximum = function(maximum) {
    -  maximum = this.roundToStepWithMin(maximum);
    -  if (this.maximum_ != maximum) {
    -    var oldIsChanging = this.isChanging_;
    -    this.isChanging_ = true;
    -
    -    this.maximum_ = maximum;
    -
    -    if (maximum < this.value_ + this.extent_) {
    -      this.setValue(maximum - this.extent_);
    -    }
    -    if (maximum < this.minimum_) {
    -      this.extent_ = 0;
    -      this.setMinimum(maximum);
    -      this.setValue(this.maximum_);
    -    }
    -    if (maximum < this.minimum_ + this.extent_) {
    -      this.extent_ = this.maximum_ - this.minimum_;
    -    }
    -
    -    this.isChanging_ = oldIsChanging;
    -    if (!this.isChanging_ && !this.mute_) {
    -      this.dispatchEvent(goog.ui.Component.EventType.CHANGE);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * @return {number} The maximimum value for the range model.
    - */
    -goog.ui.RangeModel.prototype.getMaximum = function() {
    -  return this.roundToStepWithMin(this.maximum_);
    -};
    -
    -
    -/**
    - * Returns the step value. The step value is used to determine how to round the
    - * value.
    - * @return {?number} The maximimum value for the range model.
    - */
    -goog.ui.RangeModel.prototype.getStep = function() {
    -  return this.step_;
    -};
    -
    -
    -/**
    - * Sets the step. The step value is used to determine how to round the value.
    - * @param {?number} step  The step size.
    - */
    -goog.ui.RangeModel.prototype.setStep = function(step) {
    -  if (this.step_ != step) {
    -    this.step_ = step;
    -
    -    // adjust value, extent and maximum
    -    var oldIsChanging = this.isChanging_;
    -    this.isChanging_ = true;
    -
    -    this.setMaximum(this.getMaximum());
    -    this.setExtent(this.getExtent());
    -    this.setValue(this.getValue());
    -
    -    this.isChanging_ = oldIsChanging;
    -    if (!this.isChanging_ && !this.mute_) {
    -      this.dispatchEvent(goog.ui.Component.EventType.CHANGE);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Rounds to the closest step using the minimum value as the base.
    - * @param {number} value  The number to round.
    - * @return {number} The number rounded to the closest step.
    - */
    -goog.ui.RangeModel.prototype.roundToStepWithMin = function(value) {
    -  if (this.step_ == null) return value;
    -  return this.minimum_ +
    -      Math.round((value - this.minimum_) / this.step_) * this.step_;
    -};
    -
    -
    -/**
    - * Rounds to the closest step.
    - * @param {number} value  The number to round.
    - * @return {number} The number rounded to the closest step.
    - */
    -goog.ui.RangeModel.prototype.roundToStep = function(value) {
    -  if (this.step_ == null) return value;
    -  return Math.round(value / this.step_) * this.step_;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/rangemodel_test.html b/src/database/third_party/closure-library/closure/goog/ui/rangemodel_test.html
    deleted file mode 100644
    index 1dcfa4e37c4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/rangemodel_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.RangeModel
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.RangeModelTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/rangemodel_test.js b/src/database/third_party/closure-library/closure/goog/ui/rangemodel_test.js
    deleted file mode 100644
    index e4901df726c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/rangemodel_test.js
    +++ /dev/null
    @@ -1,266 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.RangeModelTest');
    -goog.setTestOnly('goog.ui.RangeModelTest');
    -
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.RangeModel');
    -
    -function reset(rm, step) {
    -  rm.setStep(step || 1);
    -  rm.setExtent(0);
    -  rm.setMinimum(0);
    -  rm.setMaximum(100);
    -  rm.setValue(0);
    -}
    -
    -function getDescriptiveString(rm) {
    -  return rm.getMinimum() + ' < ' + rm.getValue() + '[' + rm.getExtent() +
    -      '] < ' + rm.getMaximum();
    -}
    -
    -function testValue() {
    -  var rm = new goog.ui.RangeModel;
    -
    -  assertEquals(0, rm.getValue());
    -  rm.setValue(50);
    -  assertEquals(50, rm.getValue());
    -
    -  // setting smaller than min should keep min
    -  rm.setValue(-1);
    -  assertEquals(0, rm.getValue());
    -
    -  // setting larger than max should keep max - extent
    -  rm.setValue(101);
    -  assertEquals(100, rm.getValue());
    -  rm.setValue(0);
    -  rm.setExtent(10);
    -  rm.setValue(100);
    -  assertEquals(90, rm.getValue());
    -
    -  ////////////////
    -  // Change step
    -  reset(rm, 3);
    -
    -  assertEquals(0, rm.getValue());
    -  rm.setValue(50);
    -  assertEquals(51, rm.getValue());
    -
    -  // setting smaller than min should keep min
    -  rm.setValue(-1);
    -  assertEquals(0, rm.getValue());
    -
    -  // setting larger than max should keep max - extent
    -  rm.setValue(101);
    -  assertEquals(99, rm.getValue());
    -  rm.setValue(0);
    -  rm.setExtent(10);
    -  rm.setValue(100);
    -  assertEquals(90, rm.getValue());
    -
    -}
    -
    -function testMinium() {
    -  var rm = new goog.ui.RangeModel;
    -
    -  rm.setValue(50);
    -  rm.setMinimum(10);
    -  assertEquals(10, rm.getMinimum());
    -
    -  reset(rm);
    -
    -  // setting larger than value should change value
    -  rm.setMinimum(10);
    -  assertEquals(10, rm.getMinimum());
    -  assertEquals(10, rm.getValue());
    -
    -  // setting larger than max should set max = min
    -  rm.setMinimum(200);
    -  assertEquals(200, rm.getMinimum());
    -  assertEquals(200, rm.getValue());
    -  assertEquals(200, rm.getMaximum());
    -  assertEquals(0, rm.getExtent());
    -
    -  reset(rm);
    -
    -  // should change extent
    -  rm.setExtent(10);
    -  rm.setMinimum(95);
    -  assertEquals(95, rm.getMinimum());
    -  assertEquals(95, rm.getValue());
    -  assertEquals(100, rm.getMaximum());
    -  assertEquals(5, rm.getExtent());
    -
    -  ////////////////
    -  // Change step
    -  reset(rm, 3);
    -
    -  rm.setValue(50);
    -  rm.setMinimum(10);
    -  assertEquals(10, rm.getMinimum());
    -
    -  reset(rm, 3);
    -
    -  // setting larger than value should change value
    -  rm.setMinimum(10);
    -  assertEquals(10, rm.getMinimum());
    -  assertEquals(10, rm.getValue());
    -
    -  // setting larger than max should set max = min
    -  rm.setMinimum(200);
    -  assertEquals(200, rm.getMinimum());
    -  assertEquals(200, rm.getValue());
    -  assertEquals(200, rm.getMaximum());
    -  assertEquals(0, rm.getExtent());
    -
    -  reset(rm, 3);
    -
    -  // should change extent
    -  rm.setExtent(10); // 0 < 0[9] < 99
    -  rm.setMinimum(95); // 95 < 95[3] < 98
    -  assertEquals(95, rm.getMinimum());
    -  assertEquals(95, rm.getValue());
    -  assertEquals(98, rm.getMaximum());
    -  assertEquals(3, rm.getExtent());
    -}
    -
    -function testMaximum() {
    -  var rm = new goog.ui.RangeModel;
    -
    -  rm.setMaximum(50);
    -  assertEquals(50, rm.getMaximum());
    -
    -  reset(rm);
    -
    -  // setting to smaller than minimum should change minimum, value and extent
    -  rm.setValue(5);
    -  rm.setExtent(10);
    -  rm.setMinimum(50);
    -  rm.setMaximum(40);
    -  assertEquals(40, rm.getMaximum());
    -  assertEquals(0, rm.getExtent());
    -  assertEquals(40, rm.getValue());
    -  assertEquals(40, rm.getMinimum());
    -
    -  reset(rm);
    -
    -  // setting smaller than value should change value to max - extent
    -  rm.setExtent(10);
    -  rm.setValue(50);
    -  rm.setMaximum(40);
    -  assertEquals(40, rm.getMaximum());
    -  assertEquals(30, rm.getValue());
    -
    -  reset(rm);
    -
    -  // should change value, and keep extent constant,
    -  // unless extent is > max - min.
    -  rm.setExtent(10);
    -  rm.setValue(90);
    -  rm.setMaximum(95);
    -  assertEquals(95, rm.getMaximum());
    -  assertEquals(10, rm.getExtent());
    -  assertEquals(85, rm.getValue());
    -
    -  ////////////////
    -  // Change step
    -  reset(rm, 3);
    -
    -  rm.setMaximum(50); // 0 < 0[0] < 51
    -  assertEquals(51, rm.getMaximum());
    -
    -  reset(rm, 3);
    -
    -  // setting to smaller than minimum should change minimum, value and extent
    -  rm.setValue(5); // 0 < 6[0] < 99
    -  rm.setExtent(10); // 0 < 6[9] < 99
    -  rm.setMinimum(50); // 50 < 50[9] < 98
    -  rm.setMaximum(40); // 41 < 41[0] < 41
    -  assertEquals(41, rm.getMaximum());
    -  assertEquals(0, rm.getExtent());
    -  assertEquals(41, rm.getValue());
    -  assertEquals(41, rm.getMinimum());
    -
    -  reset(rm, 3);
    -
    -  // setting smaller than value should change value to max - extent
    -  rm.setExtent(10); // 0 < 0[9] < 99
    -  rm.setValue(50); // 0 < 51[9] < 99
    -  rm.setMaximum(40); // 0 < 30[9] < 39
    -  assertEquals(39, rm.getMaximum());
    -  assertEquals(30, rm.getValue());
    -
    -  reset(rm, 3);
    -
    -  // should change value, and keep extent constant,
    -  // unless extent is > max - min.
    -  rm.setExtent(10); // 0 < 0[9] < 99
    -  rm.setValue(90); // 0 < 90[9] < 99
    -  rm.setMaximum(95); // 0 < 90[6] < 96
    -  assertEquals(96, rm.getMaximum());
    -  assertEquals(87, rm.getValue());
    -  assertEquals(9, rm.getExtent());
    -}
    -
    -function testExtent() {
    -  var rm = new goog.ui.RangeModel;
    -
    -  rm.setExtent(10);
    -  assertEquals(10, rm.getExtent());
    -
    -  rm.setExtent(-10);
    -  assertEquals(0, rm.getExtent());
    -
    -  rm.setValue(50);
    -  rm.setExtent(100);
    -  assertEquals(50, rm.getExtent());
    -  assertEquals(50, rm.getValue());
    -
    -  ////////////////
    -  // Change step
    -  reset(rm, 3);
    -
    -  rm.setExtent(10); // 0 < 0[9] < 99
    -  assertEquals(9, rm.getExtent());
    -
    -  rm.setExtent(-10);
    -  assertEquals(0, rm.getExtent());
    -
    -  rm.setValue(50);  // 0 < 51[9] < 99
    -  rm.setExtent(100); // 0 < 51[48] < 99
    -  assertEquals(48, rm.getExtent());
    -  assertEquals(51, rm.getValue());
    -}
    -
    -function testRoundToStep() {
    -  var rm = new goog.ui.RangeModel;
    -  rm.setStep(0.5);
    -
    -  assertEquals(1, rm.roundToStep(1));
    -  assertEquals(0.5, rm.roundToStep(0.5));
    -  assertEquals(1, rm.roundToStep(0.75));
    -  assertEquals(0.5, rm.roundToStep(0.74));
    -}
    -
    -function testRoundToStepWithMin() {
    -  var rm = new goog.ui.RangeModel;
    -  rm.setStep(0.5);
    -  rm.setMinimum(0.25);
    -
    -  assertEquals(1.25, rm.roundToStepWithMin(1));
    -  assertEquals(0.75, rm.roundToStepWithMin(0.5));
    -  assertEquals(0.75, rm.roundToStepWithMin(0.75));
    -  assertEquals(0.75, rm.roundToStepWithMin(0.74));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/ratings.js b/src/database/third_party/closure-library/closure/goog/ui/ratings.js
    deleted file mode 100644
    index 94591faaf41..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/ratings.js
    +++ /dev/null
    @@ -1,508 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A base ratings widget that allows the user to select a rating,
    - * like "star video" in Google Video. This fires a "change" event when the user
    - * selects a rating.
    - *
    - * Keyboard:
    - * ESC = Clear (if supported)
    - * Home = 1 star
    - * End = Full rating
    - * Left arrow = Decrease rating
    - * Right arrow = Increase rating
    - * 0 = Clear (if supported)
    - * 1 - 9 = nth star
    - *
    - * @see ../demos/ratings.html
    - */
    -
    -goog.provide('goog.ui.Ratings');
    -goog.provide('goog.ui.Ratings.EventType');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.asserts');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events.EventType');
    -goog.require('goog.ui.Component');
    -
    -
    -
    -/**
    - * A UI Control used for rating things, i.e. videos on Google Video.
    - * @param {Array<string>=} opt_ratings Ratings. Default: [1,2,3,4,5].
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @constructor
    - * @extends {goog.ui.Component}
    - */
    -goog.ui.Ratings = function(opt_ratings, opt_domHelper) {
    -  goog.ui.Component.call(this, opt_domHelper);
    -
    -  /**
    -   * Ordered ratings that can be picked, Default: [1,2,3,4,5]
    -   * @type {Array<string>}
    -   * @private
    -   */
    -  this.ratings_ = opt_ratings || ['1', '2', '3', '4', '5'];
    -
    -  /**
    -   * Array containing references to the star elements
    -   * @type {Array<Element>}
    -   * @private
    -   */
    -  this.stars_ = [];
    -
    -
    -  // Awkward name because the obvious name is taken by subclasses already.
    -  /**
    -   * Whether the control is enabled.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.isEnabled_ = true;
    -
    -
    -  /**
    -   * The last index to be highlighted
    -   * @type {number}
    -   * @private
    -   */
    -  this.highlightedIndex_ = -1;
    -
    -
    -  /**
    -   * The currently selected index
    -   * @type {number}
    -   * @private
    -   */
    -  this.selectedIndex_ = -1;
    -
    -
    -  /**
    -   * An attached form field to set the value to
    -   * @type {HTMLInputElement|HTMLSelectElement|null}
    -   * @private
    -   */
    -  this.attachedFormField_ = null;
    -};
    -goog.inherits(goog.ui.Ratings, goog.ui.Component);
    -goog.tagUnsealableClass(goog.ui.Ratings);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.Ratings.CSS_CLASS = goog.getCssName('goog-ratings');
    -
    -
    -/**
    - * Enums for Ratings event type.
    - * @enum {string}
    - */
    -goog.ui.Ratings.EventType = {
    -  CHANGE: 'change',
    -  HIGHLIGHT_CHANGE: 'highlightchange',
    -  HIGHLIGHT: 'highlight',
    -  UNHIGHLIGHT: 'unhighlight'
    -};
    -
    -
    -/**
    - * Decorate a HTML structure already in the document.  Expects the structure:
    - * <pre>
    - * - div
    - *   - select
    - *       - option 1 #text = 1 star
    - *       - option 2 #text = 2 stars
    - *       - option 3 #text = 3 stars
    - *       - option N (where N is max number of ratings)
    - * </pre>
    - *
    - * The div can contain other elements for graceful degredation, but they will be
    - * hidden when the decoration occurs.
    - *
    - * @param {Element} el Div element to decorate.
    - * @override
    - */
    -goog.ui.Ratings.prototype.decorateInternal = function(el) {
    -  var select = el.getElementsByTagName('select')[0];
    -  if (!select) {
    -    throw Error('Can not decorate ' + el + ', with Ratings. Must ' +
    -                'contain select box');
    -  }
    -  this.ratings_.length = 0;
    -  for (var i = 0, n = select.options.length; i < n; i++) {
    -    var option = select.options[i];
    -    this.ratings_.push(option.text);
    -  }
    -  this.setSelectedIndex(select.selectedIndex);
    -  select.style.display = 'none';
    -  this.attachedFormField_ = select;
    -  this.createDom();
    -  el.insertBefore(this.getElement(), select);
    -};
    -
    -
    -/**
    - * Render the rating widget inside the provided element. This will override the
    - * current content of the element.
    - * @override
    - */
    -goog.ui.Ratings.prototype.enterDocument = function() {
    -  var el = this.getElement();
    -  goog.asserts.assert(el, 'The DOM element for ratings cannot be null.');
    -  el.tabIndex = 0;
    -  goog.dom.classlist.add(el, this.getCssClass());
    -  goog.a11y.aria.setRole(el, goog.a11y.aria.Role.SLIDER);
    -  goog.a11y.aria.setState(el, goog.a11y.aria.State.VALUEMIN, 0);
    -  var max = this.ratings_.length - 1;
    -  goog.a11y.aria.setState(el, goog.a11y.aria.State.VALUEMAX, max);
    -  var handler = this.getHandler();
    -  handler.listen(el, 'keydown', this.onKeyDown_);
    -
    -  // Create the elements for the stars
    -  for (var i = 0; i < this.ratings_.length; i++) {
    -    var star = this.getDomHelper().createDom('span', {
    -      'title': this.ratings_[i],
    -      'class': this.getClassName_(i, false),
    -      'index': i});
    -    this.stars_.push(star);
    -    el.appendChild(star);
    -  }
    -
    -  handler.listen(el, goog.events.EventType.CLICK, this.onClick_);
    -  handler.listen(el, goog.events.EventType.MOUSEOUT, this.onMouseOut_);
    -  handler.listen(el, goog.events.EventType.MOUSEOVER, this.onMouseOver_);
    -
    -  this.highlightIndex_(this.selectedIndex_);
    -};
    -
    -
    -/**
    - * Should be called when the widget is removed from the document but may be
    - * reused.  This removes all the listeners the widget has attached and destroys
    - * the DOM nodes it uses.
    - * @override
    - */
    -goog.ui.Ratings.prototype.exitDocument = function() {
    -  goog.ui.Ratings.superClass_.exitDocument.call(this);
    -  for (var i = 0; i < this.stars_.length; i++) {
    -    this.getDomHelper().removeNode(this.stars_[i]);
    -  }
    -  this.stars_.length = 0;
    -};
    -
    -
    -/** @override */
    -goog.ui.Ratings.prototype.disposeInternal = function() {
    -  goog.ui.Ratings.superClass_.disposeInternal.call(this);
    -  this.ratings_.length = 0;
    -};
    -
    -
    -/**
    - * Returns the base CSS class used by subcomponents of this component.
    - * @return {string} Component-specific CSS class.
    - */
    -goog.ui.Ratings.prototype.getCssClass = function() {
    -  return goog.ui.Ratings.CSS_CLASS;
    -};
    -
    -
    -/**
    - * Sets the selected index. If the provided index is greater than the number of
    - * ratings then the max is set.  0 is the first item, -1 is no selection.
    - * @param {number} index The index of the rating to select.
    - */
    -goog.ui.Ratings.prototype.setSelectedIndex = function(index) {
    -  index = Math.max(-1, Math.min(index, this.ratings_.length - 1));
    -  if (index != this.selectedIndex_) {
    -    this.selectedIndex_ = index;
    -    this.highlightIndex_(this.selectedIndex_);
    -    if (this.attachedFormField_) {
    -      if (this.attachedFormField_.tagName == 'SELECT') {
    -        this.attachedFormField_.selectedIndex = index;
    -      } else {
    -        this.attachedFormField_.value =
    -            /** @type {string} */ (this.getValue());
    -      }
    -      var ratingsElement = this.getElement();
    -      goog.asserts.assert(ratingsElement,
    -          'The DOM ratings element cannot be null.');
    -      goog.a11y.aria.setState(ratingsElement,
    -          goog.a11y.aria.State.VALUENOW,
    -          this.ratings_[index]);
    -    }
    -    this.dispatchEvent(goog.ui.Ratings.EventType.CHANGE);
    -  }
    -};
    -
    -
    -/**
    - * @return {number} The index of the currently selected rating.
    - */
    -goog.ui.Ratings.prototype.getSelectedIndex = function() {
    -  return this.selectedIndex_;
    -};
    -
    -
    -/**
    - * Returns the rating value of the currently selected rating
    - * @return {?string} The value of the currently selected rating (or null).
    - */
    -goog.ui.Ratings.prototype.getValue = function() {
    -  return this.selectedIndex_ == -1 ? null : this.ratings_[this.selectedIndex_];
    -};
    -
    -
    -/**
    - * Returns the index of the currently highlighted rating, -1 if the mouse isn't
    - * currently over the widget
    - * @return {number} The index of the currently highlighted rating.
    - */
    -goog.ui.Ratings.prototype.getHighlightedIndex = function() {
    -  return this.highlightedIndex_;
    -};
    -
    -
    -/**
    - * Returns the value of the currently highlighted rating, null if the mouse
    - * isn't currently over the widget
    - * @return {?string} The value of the currently highlighted rating, or null.
    - */
    -goog.ui.Ratings.prototype.getHighlightedValue = function() {
    -  return this.highlightedIndex_ == -1 ? null :
    -      this.ratings_[this.highlightedIndex_];
    -};
    -
    -
    -/**
    - * Sets the array of ratings that the comonent
    - * @param {Array<string>} ratings Array of value to use as ratings.
    - */
    -goog.ui.Ratings.prototype.setRatings = function(ratings) {
    -  this.ratings_ = ratings;
    -  // TODO(user): If rendered update stars
    -};
    -
    -
    -/**
    - * Gets the array of ratings that the component
    - * @return {Array<string>} Array of ratings.
    - */
    -goog.ui.Ratings.prototype.getRatings = function() {
    -  return this.ratings_;
    -};
    -
    -
    -/**
    - * Attaches an input or select element to the ratings widget. The value or
    - * index of the field will be updated along with the ratings widget.
    - * @param {HTMLSelectElement|HTMLInputElement} field The field to attach to.
    - */
    -goog.ui.Ratings.prototype.setAttachedFormField = function(field) {
    -  this.attachedFormField_ = field;
    -};
    -
    -
    -/**
    - * Returns the attached input or select element to the ratings widget.
    - * @return {HTMLSelectElement|HTMLInputElement|null} The attached form field.
    - */
    -goog.ui.Ratings.prototype.getAttachedFormField = function() {
    -  return this.attachedFormField_;
    -};
    -
    -
    -/**
    - * Enables or disables the ratings control.
    - * @param {boolean} enable Whether to enable or disable the control.
    - */
    -goog.ui.Ratings.prototype.setEnabled = function(enable) {
    -  this.isEnabled_ = enable;
    -  if (!enable) {
    -    // Undo any highlighting done during mouseover when disabling the control
    -    // and highlight the last selected rating.
    -    this.resetHighlights_();
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the ratings control is enabled.
    - */
    -goog.ui.Ratings.prototype.isEnabled = function() {
    -  return this.isEnabled_;
    -};
    -
    -
    -/**
    - * Handle the mouse moving over a star.
    - * @param {goog.events.BrowserEvent} e The browser event.
    - * @private
    - */
    -goog.ui.Ratings.prototype.onMouseOver_ = function(e) {
    -  if (!this.isEnabled()) {
    -    return;
    -  }
    -  if (goog.isDef(e.target.index)) {
    -    var n = e.target.index;
    -    if (this.highlightedIndex_ != n) {
    -      this.highlightIndex_(n);
    -      this.highlightedIndex_ = n;
    -      this.dispatchEvent(goog.ui.Ratings.EventType.HIGHLIGHT_CHANGE);
    -      this.dispatchEvent(goog.ui.Ratings.EventType.HIGHLIGHT);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Handle the mouse moving over a star.
    - * @param {goog.events.BrowserEvent} e The browser event.
    - * @private
    - */
    -goog.ui.Ratings.prototype.onMouseOut_ = function(e) {
    -  // Only remove the highlight if the mouse is not moving to another star
    -  if (e.relatedTarget && !goog.isDef(e.relatedTarget.index)) {
    -    this.resetHighlights_();
    -  }
    -};
    -
    -
    -/**
    - * Handle the mouse moving over a star.
    - * @param {goog.events.BrowserEvent} e The browser event.
    - * @private
    - */
    -goog.ui.Ratings.prototype.onClick_ = function(e) {
    -  if (!this.isEnabled()) {
    -    return;
    -  }
    -
    -  if (goog.isDef(e.target.index)) {
    -    this.setSelectedIndex(e.target.index);
    -  }
    -};
    -
    -
    -/**
    - * Handle the key down event. 0 = unselected in this case, 1 = the first rating
    - * @param {goog.events.BrowserEvent} e The browser event.
    - * @private
    - */
    -goog.ui.Ratings.prototype.onKeyDown_ = function(e) {
    -  if (!this.isEnabled()) {
    -    return;
    -  }
    -  switch (e.keyCode) {
    -    case 27: // esc
    -      this.setSelectedIndex(-1);
    -      break;
    -    case 36: // home
    -      this.setSelectedIndex(0);
    -      break;
    -    case 35: // end
    -      this.setSelectedIndex(this.ratings_.length);
    -      break;
    -    case 37: // left arrow
    -      this.setSelectedIndex(this.getSelectedIndex() - 1);
    -      break;
    -    case 39: // right arrow
    -      this.setSelectedIndex(this.getSelectedIndex() + 1);
    -      break;
    -    default:
    -      // Detected a numeric key stroke, such as 0 - 9.  0 clears, 1 is first
    -      // star, 9 is 9th star or last if there are less than 9 stars.
    -      var num = parseInt(String.fromCharCode(e.keyCode), 10);
    -      if (!isNaN(num)) {
    -        this.setSelectedIndex(num - 1);
    -      }
    -  }
    -};
    -
    -
    -/**
    - * Resets the highlights to the selected rating to undo highlights due to hover
    - * effects.
    - * @private
    - */
    -goog.ui.Ratings.prototype.resetHighlights_ = function() {
    -  this.highlightIndex_(this.selectedIndex_);
    -  this.highlightedIndex_ = -1;
    -  this.dispatchEvent(goog.ui.Ratings.EventType.HIGHLIGHT_CHANGE);
    -  this.dispatchEvent(goog.ui.Ratings.EventType.UNHIGHLIGHT);
    -};
    -
    -
    -/**
    - * Highlights the ratings up to a specific index
    - * @param {number} n Index to highlight.
    - * @private
    - */
    -goog.ui.Ratings.prototype.highlightIndex_ = function(n) {
    -  for (var i = 0, star; star = this.stars_[i]; i++) {
    -    goog.dom.classlist.set(star, this.getClassName_(i, i <= n));
    -  }
    -};
    -
    -
    -/**
    - * Get the class name for a given rating.  All stars have the class:
    - * goog-ratings-star.
    - * Other possible classnames dependent on position and state are:
    - * goog-ratings-firststar-on
    - * goog-ratings-firststar-off
    - * goog-ratings-midstar-on
    - * goog-ratings-midstar-off
    - * goog-ratings-laststar-on
    - * goog-ratings-laststar-off
    - * @param {number} i Index to get class name for.
    - * @param {boolean} on Whether it should be on.
    - * @return {string} The class name.
    - * @private
    - */
    -goog.ui.Ratings.prototype.getClassName_ = function(i, on) {
    -  var className;
    -  var enabledClassName;
    -  var baseClass = this.getCssClass();
    -
    -  if (i === 0) {
    -    className = goog.getCssName(baseClass, 'firststar');
    -  } else if (i == this.ratings_.length - 1) {
    -    className = goog.getCssName(baseClass, 'laststar');
    -  } else {
    -    className = goog.getCssName(baseClass, 'midstar');
    -  }
    -
    -  if (on) {
    -    className = goog.getCssName(className, 'on');
    -  } else {
    -    className = goog.getCssName(className, 'off');
    -  }
    -
    -  if (this.isEnabled_) {
    -    enabledClassName = goog.getCssName(baseClass, 'enabled');
    -  } else {
    -    enabledClassName = goog.getCssName(baseClass, 'disabled');
    -  }
    -
    -  return goog.getCssName(baseClass, 'star') + ' ' + className +
    -      ' ' + enabledClassName;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/registry.js b/src/database/third_party/closure-library/closure/goog/ui/registry.js
    deleted file mode 100644
    index 91257dc42a7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/registry.js
    +++ /dev/null
    @@ -1,172 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Global renderer and decorator registry.
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.registry');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.dom.classlist');
    -
    -
    -/**
    - * Given a {@link goog.ui.Component} constructor, returns an instance of its
    - * default renderer.  If the default renderer is a singleton, returns the
    - * singleton instance; otherwise returns a new instance of the renderer class.
    - * @param {Function} componentCtor Component constructor function (for example
    - *     {@code goog.ui.Button}).
    - * @return {goog.ui.ControlRenderer?} Renderer instance (for example the
    - *     singleton instance of {@code goog.ui.ButtonRenderer}), or null if
    - *     no default renderer was found.
    - */
    -goog.ui.registry.getDefaultRenderer = function(componentCtor) {
    -  // Locate the default renderer based on the constructor's unique ID.  If no
    -  // renderer is registered for this class, walk up the superClass_ chain.
    -  var key;
    -  /** @type {Function|undefined} */ var rendererCtor;
    -  while (componentCtor) {
    -    key = goog.getUid(componentCtor);
    -    if ((rendererCtor = goog.ui.registry.defaultRenderers_[key])) {
    -      break;
    -    }
    -    componentCtor = componentCtor.superClass_ ?
    -        componentCtor.superClass_.constructor : null;
    -  }
    -
    -  // If the renderer has a static getInstance method, return the singleton
    -  // instance; otherwise create and return a new instance.
    -  if (rendererCtor) {
    -    return goog.isFunction(rendererCtor.getInstance) ?
    -        rendererCtor.getInstance() : new rendererCtor();
    -  }
    -
    -  return null;
    -};
    -
    -
    -/**
    - * Sets the default renderer for the given {@link goog.ui.Component}
    - * constructor.
    - * @param {Function} componentCtor Component constructor function (for example
    - *     {@code goog.ui.Button}).
    - * @param {Function} rendererCtor Renderer constructor function (for example
    - *     {@code goog.ui.ButtonRenderer}).
    - * @throws {Error} If the arguments aren't functions.
    - */
    -goog.ui.registry.setDefaultRenderer = function(componentCtor, rendererCtor) {
    -  // In this case, explicit validation has negligible overhead (since each
    -  // renderer is only registered once), and helps catch subtle bugs.
    -  if (!goog.isFunction(componentCtor)) {
    -    throw Error('Invalid component class ' + componentCtor);
    -  }
    -  if (!goog.isFunction(rendererCtor)) {
    -    throw Error('Invalid renderer class ' + rendererCtor);
    -  }
    -
    -  // Map the component constructor's unique ID to the renderer constructor.
    -  var key = goog.getUid(componentCtor);
    -  goog.ui.registry.defaultRenderers_[key] = rendererCtor;
    -};
    -
    -
    -/**
    - * Returns the {@link goog.ui.Component} instance created by the decorator
    - * factory function registered for the given CSS class name, or null if no
    - * decorator factory function was found.
    - * @param {string} className CSS class name.
    - * @return {goog.ui.Component?} Component instance.
    - */
    -goog.ui.registry.getDecoratorByClassName = function(className) {
    -  return className in goog.ui.registry.decoratorFunctions_ ?
    -      goog.ui.registry.decoratorFunctions_[className]() : null;
    -};
    -
    -
    -/**
    - * Maps a CSS class name to a function that returns a new instance of
    - * {@link goog.ui.Component} or a subclass, suitable to decorate an element
    - * that has the specified CSS class.
    - * @param {string} className CSS class name.
    - * @param {Function} decoratorFn No-argument function that returns a new
    - *     instance of a {@link goog.ui.Component} to decorate an element.
    - * @throws {Error} If the class name or the decorator function is invalid.
    - */
    -goog.ui.registry.setDecoratorByClassName = function(className, decoratorFn) {
    -  // In this case, explicit validation has negligible overhead (since each
    -  // decorator  is only registered once), and helps catch subtle bugs.
    -  if (!className) {
    -    throw Error('Invalid class name ' + className);
    -  }
    -  if (!goog.isFunction(decoratorFn)) {
    -    throw Error('Invalid decorator function ' + decoratorFn);
    -  }
    -
    -  goog.ui.registry.decoratorFunctions_[className] = decoratorFn;
    -};
    -
    -
    -/**
    - * Returns an instance of {@link goog.ui.Component} or a subclass suitable to
    - * decorate the given element, based on its CSS class.
    - *
    - * TODO(nnaze): Type of element should be {!Element}.
    - *
    - * @param {Element} element Element to decorate.
    - * @return {goog.ui.Component?} Component to decorate the element (null if
    - *     none).
    - */
    -goog.ui.registry.getDecorator = function(element) {
    -  var decorator;
    -  goog.asserts.assert(element);
    -  var classNames = goog.dom.classlist.get(element);
    -  for (var i = 0, len = classNames.length; i < len; i++) {
    -    if ((decorator = goog.ui.registry.getDecoratorByClassName(classNames[i]))) {
    -      return decorator;
    -    }
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * Resets the global renderer and decorator registry.
    - */
    -goog.ui.registry.reset = function() {
    -  goog.ui.registry.defaultRenderers_ = {};
    -  goog.ui.registry.decoratorFunctions_ = {};
    -};
    -
    -
    -/**
    - * Map of {@link goog.ui.Component} constructor unique IDs to the constructors
    - * of their default {@link goog.ui.Renderer}s.
    - * @type {Object}
    - * @private
    - */
    -goog.ui.registry.defaultRenderers_ = {};
    -
    -
    -/**
    - * Map of CSS class names to registry factory functions.  The keys are
    - * class names.  The values are function objects that return new instances
    - * of {@link goog.ui.registry} or one of its subclasses, suitable to
    - * decorate elements marked with the corresponding CSS class.  Used by
    - * containers while decorating their children.
    - * @type {Object}
    - * @private
    - */
    -goog.ui.registry.decoratorFunctions_ = {};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/registry_test.html b/src/database/third_party/closure-library/closure/goog/ui/registry_test.html
    deleted file mode 100644
    index b8f37643591..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/registry_test.html
    +++ /dev/null
    @@ -1,31 +0,0 @@
    -<!DOCTYPE html>
    -<!-- Author: attila@google.com (Attila Bodis) -->
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.registry
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.ui.registryTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="x" class="fake-component-x">
    -  </div>
    -  <div id="y" class="fake-component-y fake-component-x">
    -  </div>
    -  <div id="z" class="fake-component-z">
    -  </div>
    -  <div id="u">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/registry_test.js b/src/database/third_party/closure-library/closure/goog/ui/registry_test.js
    deleted file mode 100644
    index 80fa5bb5d28..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/registry_test.js
    +++ /dev/null
    @@ -1,230 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.registryTest');
    -goog.setTestOnly('goog.ui.registryTest');
    -
    -goog.require('goog.object');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.registry');
    -
    -// Fake component and renderer implementations, for testing only.
    -
    -// UnknownComponent has no default renderer or decorator registered.
    -function UnknownComponent() {
    -}
    -
    -// FakeComponentX's default renderer is FakeRenderer.  It also has a
    -// decorator.
    -function FakeComponentX() {
    -  this.element = null;
    -}
    -
    -FakeComponentX.prototype.decorate = function(element) {
    -  this.element = element;
    -};
    -
    -// FakeComponentY doesn't have an explicitly registered default
    -// renderer; it should inherit the default renderer from its superclass.
    -// It does have a decorator registered.
    -function FakeComponentY() {
    -  FakeComponentX.call(this);
    -}
    -goog.inherits(FakeComponentY, FakeComponentX);
    -
    -// FakeComponentZ is just another component.  Its default renderer is
    -// FakeSingletonRenderer, but it has no decorator registered.
    -function FakeComponentZ() {
    -}
    -
    -// FakeRenderer is a stateful renderer.
    -function FakeRenderer() {
    -}
    -
    -// FakeSingletonRenderer is a stateless renderer that can be used as a
    -// singleton.
    -function FakeSingletonRenderer() {
    -}
    -
    -FakeSingletonRenderer.instance_ = new FakeSingletonRenderer();
    -
    -FakeSingletonRenderer.getInstance = function() {
    -  return FakeSingletonRenderer.instance_;
    -};
    -
    -function setUp() {
    -  goog.ui.registry.setDefaultRenderer(FakeComponentX, FakeRenderer);
    -  goog.ui.registry.setDefaultRenderer(FakeComponentZ,
    -      FakeSingletonRenderer);
    -
    -  goog.ui.registry.setDecoratorByClassName('fake-component-x',
    -      function() {
    -        return new FakeComponentX();
    -      });
    -  goog.ui.registry.setDecoratorByClassName('fake-component-y',
    -      function() {
    -        return new FakeComponentY();
    -      });
    -}
    -
    -function tearDown() {
    -  goog.ui.registry.reset();
    -}
    -
    -function testGetDefaultRenderer() {
    -  var rx1 = goog.ui.registry.getDefaultRenderer(FakeComponentX);
    -  var rx2 = goog.ui.registry.getDefaultRenderer(FakeComponentX);
    -  assertTrue('FakeComponentX\'s default renderer must be a FakeRenderer',
    -      rx1 instanceof FakeRenderer);
    -  assertNotEquals('Each call to getDefaultRenderer must create a new ' +
    -      'FakeRenderer', rx1, rx2);
    -
    -  var ry = goog.ui.registry.getDefaultRenderer(FakeComponentY);
    -  assertTrue('FakeComponentY must inherit its default renderer from ' +
    -      'its superclass', ry instanceof FakeRenderer);
    -
    -  var rz1 = goog.ui.registry.getDefaultRenderer(FakeComponentZ);
    -  var rz2 = goog.ui.registry.getDefaultRenderer(FakeComponentZ);
    -  assertTrue('FakeComponentZ\' default renderer must be a ' +
    -      'FakeSingletonRenderer', rz1 instanceof FakeSingletonRenderer);
    -  assertEquals('Each call to getDefaultRenderer must return the ' +
    -      'singleton instance of FakeSingletonRenderer', rz1, rz2);
    -
    -  assertNull('getDefaultRenderer must return null for unknown component',
    -      goog.ui.registry.getDefaultRenderer(UnknownComponent));
    -}
    -
    -function testSetDefaultRenderer() {
    -  var rx1 = goog.ui.registry.getDefaultRenderer(FakeComponentX);
    -  assertTrue('FakeComponentX\'s renderer must be FakeRenderer',
    -      rx1 instanceof FakeRenderer);
    -
    -  var ry1 = goog.ui.registry.getDefaultRenderer(FakeComponentY);
    -  assertTrue('FakeComponentY must inherit its default renderer from ' +
    -      'its superclass', ry1 instanceof FakeRenderer);
    -
    -  goog.ui.registry.setDefaultRenderer(FakeComponentX,
    -      FakeSingletonRenderer);
    -
    -  var rx2 = goog.ui.registry.getDefaultRenderer(FakeComponentX);
    -  assertEquals('FakeComponentX\'s renderer must be FakeSingletonRenderer',
    -      FakeSingletonRenderer.getInstance(), rx2);
    -
    -  var ry2 = goog.ui.registry.getDefaultRenderer(FakeComponentY);
    -  assertEquals('FakeComponentY must inherit the new default renderer ' +
    -      'from its superclass', FakeSingletonRenderer.getInstance(), ry2);
    -
    -  goog.ui.registry.setDefaultRenderer(FakeComponentY, FakeRenderer);
    -
    -  var rx3 = goog.ui.registry.getDefaultRenderer(FakeComponentX);
    -  assertEquals('FakeComponentX\'s renderer must be unchanged',
    -      FakeSingletonRenderer.getInstance(), rx3);
    -
    -  var ry3 = goog.ui.registry.getDefaultRenderer(FakeComponentY);
    -  assertTrue('FakeComponentY must now have its own default renderer',
    -      ry3 instanceof FakeRenderer);
    -
    -  assertThrows('Calling setDefaultRenderer with non-function component ' +
    -      'must throw error',
    -      function() {
    -        goog.ui.registry.setDefaultRenderer('Not function', FakeRenderer);
    -      });
    -
    -  assertThrows('Calling setDefaultRenderer with non-function renderer ' +
    -      'must throw error',
    -      function() {
    -        goog.ui.registry.setDefaultRenderer(FakeComponentX, 'Not function');
    -      });
    -}
    -
    -function testGetDecoratorByClassName() {
    -  var dx1 = goog.ui.registry.getDecoratorByClassName('fake-component-x');
    -  var dx2 = goog.ui.registry.getDecoratorByClassName('fake-component-x');
    -  assertTrue('fake-component-x must be decorated by a FakeComponentX',
    -      dx1 instanceof FakeComponentX);
    -  assertNotEquals('Each call to getDecoratorByClassName must return a ' +
    -      'new FakeComponentX instance', dx1, dx2);
    -
    -  var dy1 = goog.ui.registry.getDecoratorByClassName('fake-component-y');
    -  var dy2 = goog.ui.registry.getDecoratorByClassName('fake-component-y');
    -  assertTrue('fake-component-y must be decorated by a FakeComponentY',
    -      dy1 instanceof FakeComponentY);
    -  assertNotEquals('Each call to getDecoratorByClassName must return a ' +
    -      'new FakeComponentY instance', dy1, dy2);
    -
    -  assertNull('getDecoratorByClassName must return null for unknown class',
    -      goog.ui.registry.getDecoratorByClassName('fake-component-z'));
    -  assertNull('getDecoratorByClassName must return null for empty string',
    -      goog.ui.registry.getDecoratorByClassName(''));
    -}
    -
    -function testSetDecoratorByClassName() {
    -  var dx1, dx2;
    -
    -  dx1 = goog.ui.registry.getDecoratorByClassName('fake-component-x');
    -  assertTrue('fake-component-x must be decorated by a FakeComponentX',
    -      dx1 instanceof FakeComponentX);
    -  goog.ui.registry.setDecoratorByClassName('fake-component-x',
    -      function() {
    -        return new UnknownComponent();
    -      });
    -  dx2 = goog.ui.registry.getDecoratorByClassName('fake-component-x');
    -  assertTrue('fake-component-x must now be decorated by UnknownComponent',
    -      dx2 instanceof UnknownComponent);
    -
    -  assertThrows('Calling setDecoratorByClassName with invalid class name ' +
    -      'must throw error',
    -      function() {
    -        goog.ui.registry.setDecoratorByClassName('', function() {
    -          return new UnknownComponent();
    -        });
    -      });
    -
    -  assertThrows('Calling setDecoratorByClassName with non-function ' +
    -      'decorator must throw error',
    -      function() {
    -        goog.ui.registry.setDecoratorByClassName('fake-component-x',
    -            'Not function');
    -      });
    -}
    -
    -function testGetDecorator() {
    -  var dx = goog.ui.registry.getDecorator(document.getElementById('x'));
    -  assertTrue('Decorator for element with fake-component-x class must be ' +
    -      'a FakeComponentX', dx instanceof FakeComponentX);
    -
    -  var dy = goog.ui.registry.getDecorator(document.getElementById('y'));
    -  assertTrue('Decorator for element with fake-component-y class must be ' +
    -      'a FakeComponentY', dy instanceof FakeComponentY);
    -
    -  var dz = goog.ui.registry.getDecorator(document.getElementById('z'));
    -  assertNull('Decorator for element with unknown class must be null', dz);
    -
    -  var du = goog.ui.registry.getDecorator(document.getElementById('u'));
    -  assertNull('Decorator for element without CSS class must be null', du);
    -}
    -
    -function testReset() {
    -  assertNotEquals('Some renderers must be registered', 0,
    -      goog.object.getCount(goog.ui.registry.defaultRenderers_));
    -  assertNotEquals('Some decorators must be registered', 0,
    -      goog.object.getCount(goog.ui.registry.decoratorFunctions_));
    -
    -  goog.ui.registry.reset();
    -
    -  assertTrue('No renderers must be registered',
    -      goog.object.isEmpty(goog.ui.registry.defaultRenderers_));
    -  assertTrue('No decorators must be registered',
    -      goog.object.isEmpty(goog.ui.registry.decoratorFunctions_));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/richtextspellchecker.js b/src/database/third_party/closure-library/closure/goog/ui/richtextspellchecker.js
    deleted file mode 100644
    index c20143bf3f3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/richtextspellchecker.js
    +++ /dev/null
    @@ -1,780 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Rich text spell checker implementation.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - * @see ../demos/richtextspellchecker.html
    - */
    -
    -goog.provide('goog.ui.RichTextSpellChecker');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.NodeType');
    -goog.require('goog.dom.Range');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.events.KeyHandler');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.spell.SpellCheck');
    -goog.require('goog.string.StringBuffer');
    -goog.require('goog.style');
    -goog.require('goog.ui.AbstractSpellChecker');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.PopupMenu');
    -
    -
    -
    -/**
    - * Rich text spell checker implementation.
    - *
    - * @param {goog.spell.SpellCheck} handler Instance of the SpellCheckHandler
    - *     support object to use. A single instance can be shared by multiple editor
    - *     components.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @constructor
    - * @extends {goog.ui.AbstractSpellChecker}
    - */
    -goog.ui.RichTextSpellChecker = function(handler, opt_domHelper) {
    -  goog.ui.AbstractSpellChecker.call(this, handler, opt_domHelper);
    -
    -  /**
    -   * String buffer for use in reassembly of the original text.
    -   * @type {goog.string.StringBuffer}
    -   * @private
    -   */
    -  this.workBuffer_ = new goog.string.StringBuffer();
    -
    -  /**
    -   * Bound async function (to avoid rebinding it on every call).
    -   * @type {Function}
    -   * @private
    -   */
    -  this.boundContinueAsyncFn_ = goog.bind(this.continueAsync_, this);
    -
    -  /**
    -   * Event handler for listening to events without leaking.
    -   * @private {!goog.events.EventHandler}
    -   */
    -  this.eventHandler_ = new goog.events.EventHandler(this);
    -  this.registerDisposable(this.eventHandler_);
    -
    -  /**
    -   * The object handling keyboard events.
    -   * @private {!goog.events.KeyHandler}
    -   */
    -  this.keyHandler_ = new goog.events.KeyHandler();
    -  this.registerDisposable(this.keyHandler_);
    -};
    -goog.inherits(goog.ui.RichTextSpellChecker, goog.ui.AbstractSpellChecker);
    -goog.tagUnsealableClass(goog.ui.RichTextSpellChecker);
    -
    -
    -/**
    - * Root node for rich editor.
    - * @type {Node}
    - * @private
    - */
    -goog.ui.RichTextSpellChecker.prototype.rootNode_;
    -
    -
    -/**
    - * Indicates whether the root node for the rich editor is an iframe.
    - * @private {boolean}
    - */
    -goog.ui.RichTextSpellChecker.prototype.rootNodeIframe_ = false;
    -
    -
    -/**
    - * Current node where spell checker has interrupted to go to the next stack
    - * frame.
    - * @type {Node}
    - * @private
    - */
    -goog.ui.RichTextSpellChecker.prototype.currentNode_;
    -
    -
    -/**
    - * Counter of inserted elements. Used in processing loop to attempt to preserve
    - * existing nodes if they contain no misspellings.
    - * @type {number}
    - * @private
    - */
    -goog.ui.RichTextSpellChecker.prototype.elementsInserted_ = 0;
    -
    -
    -/**
    - * Number of words to scan to precharge the dictionary.
    - * @type {number}
    - * @private
    - */
    -goog.ui.RichTextSpellChecker.prototype.dictionaryPreScanSize_ = 1000;
    -
    -
    -/**
    - * Class name for word spans.
    - * @type {string}
    - */
    -goog.ui.RichTextSpellChecker.prototype.wordClassName =
    -    goog.getCssName('goog-spellcheck-word');
    -
    -
    -/**
    - * DomHelper to be used for interacting with the editable document/element.
    - *
    - * @type {goog.dom.DomHelper|undefined}
    - * @private
    - */
    -goog.ui.RichTextSpellChecker.prototype.editorDom_;
    -
    -
    -/**
    - * Tag name portion of the marker for the text that does not need to be checked
    - * for spelling.
    - *
    - * @type {Array<string|undefined>}
    - */
    -goog.ui.RichTextSpellChecker.prototype.excludeTags;
    -
    -
    -/**
    - * CSS Style text for invalid words. As it's set inside the rich edit iframe
    - * classes defined in the parent document are not availble, thus the style is
    - * set inline.
    - * @type {string}
    - */
    -goog.ui.RichTextSpellChecker.prototype.invalidWordCssText =
    -    'background: yellow;';
    -
    -
    -/**
    - * Creates the initial DOM representation for the component.
    - *
    - * @throws {Error} Not supported. Use decorate.
    - * @see #decorate
    - * @override
    - */
    -goog.ui.RichTextSpellChecker.prototype.createDom = function() {
    -  throw Error('Render not supported for goog.ui.RichTextSpellChecker.');
    -};
    -
    -
    -/**
    - * Decorates the element for the UI component.
    - *
    - * @param {Element} element Element to decorate.
    - * @override
    - */
    -goog.ui.RichTextSpellChecker.prototype.decorateInternal = function(element) {
    -  this.setElementInternal(element);
    -  this.rootNodeIframe_ = element.contentDocument || element.contentWindow;
    -  if (this.rootNodeIframe_) {
    -    var doc = element.contentDocument || element.contentWindow.document;
    -    this.rootNode_ = doc.body;
    -    this.editorDom_ = goog.dom.getDomHelper(doc);
    -  } else {
    -    this.rootNode_ = element;
    -    this.editorDom_ = goog.dom.getDomHelper(element);
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.RichTextSpellChecker.prototype.enterDocument = function() {
    -  goog.ui.RichTextSpellChecker.superClass_.enterDocument.call(this);
    -
    -  var rootElement = goog.asserts.assertElement(this.rootNode_,
    -      'The rootNode_ of a richtextspellchecker must be an Element.');
    -  this.keyHandler_.attach(rootElement);
    -
    -  this.initSuggestionsMenu();
    -};
    -
    -
    -/** @override */
    -goog.ui.RichTextSpellChecker.prototype.initSuggestionsMenu = function() {
    -  goog.ui.RichTextSpellChecker.base(this, 'initSuggestionsMenu');
    -
    -  var menu = goog.asserts.assertInstanceof(this.getMenu(), goog.ui.PopupMenu,
    -      'The menu of a richtextspellchecker must be a PopupMenu.');
    -  this.eventHandler_.listen(menu,
    -      goog.ui.Component.EventType.HIDE, this.onCorrectionHide_);
    -};
    -
    -
    -/**
    - * Checks spelling for all text and displays correction UI.
    - * @override
    - */
    -goog.ui.RichTextSpellChecker.prototype.check = function() {
    -  this.blockReadyEvents();
    -  this.preChargeDictionary_(this.rootNode_, this.dictionaryPreScanSize_);
    -  this.unblockReadyEvents();
    -
    -  this.eventHandler_.listen(this.spellCheck,
    -      goog.spell.SpellCheck.EventType.READY, this.onDictionaryCharged_, true);
    -  this.spellCheck.processPending();
    -};
    -
    -
    -/**
    - * Processes nodes recursively.
    - *
    - * @param {Node} node Node to start with.
    - * @param {number} words Max number of words to process.
    - * @private
    - */
    -goog.ui.RichTextSpellChecker.prototype.preChargeDictionary_ = function(node,
    -                                                                       words) {
    -  while (node) {
    -    var next = this.nextNode_(node);
    -    if (this.isExcluded_(node)) {
    -      node = next;
    -      continue;
    -    }
    -    if (node.nodeType == goog.dom.NodeType.TEXT) {
    -      if (node.nodeValue) {
    -        words -= this.populateDictionary(node.nodeValue, words);
    -        if (words <= 0) {
    -          return;
    -        }
    -      }
    -    } else if (node.nodeType == goog.dom.NodeType.ELEMENT) {
    -      if (node.firstChild) {
    -        next = node.firstChild;
    -      }
    -    }
    -    node = next;
    -  }
    -};
    -
    -
    -/**
    - * Starts actual processing after the dictionary is charged.
    - * @param {goog.events.Event} e goog.spell.SpellCheck.EventType.READY event.
    - * @private
    - */
    -goog.ui.RichTextSpellChecker.prototype.onDictionaryCharged_ = function(e) {
    -  e.stopPropagation();
    -  this.eventHandler_.unlisten(this.spellCheck,
    -      goog.spell.SpellCheck.EventType.READY, this.onDictionaryCharged_, true);
    -
    -  // Now actually do the spell checking.
    -  this.clearWordElements();
    -  this.initializeAsyncMode();
    -  this.elementsInserted_ = 0;
    -  var result = this.processNode_(this.rootNode_);
    -  if (result == goog.ui.AbstractSpellChecker.AsyncResult.PENDING) {
    -    goog.Timer.callOnce(this.boundContinueAsyncFn_);
    -    return;
    -  }
    -  this.finishAsyncProcessing();
    -  this.finishCheck_();
    -};
    -
    -
    -/**
    - * Continues asynchrnonous spell checking.
    - * @private
    - */
    -goog.ui.RichTextSpellChecker.prototype.continueAsync_ = function() {
    -  var result = this.continueAsyncProcessing();
    -  if (result == goog.ui.AbstractSpellChecker.AsyncResult.PENDING) {
    -    goog.Timer.callOnce(this.boundContinueAsyncFn_);
    -    return;
    -  }
    -  result = this.processNode_(this.currentNode_);
    -  if (result == goog.ui.AbstractSpellChecker.AsyncResult.PENDING) {
    -    goog.Timer.callOnce(this.boundContinueAsyncFn_);
    -    return;
    -  }
    -  this.finishAsyncProcessing();
    -  this.finishCheck_();
    -};
    -
    -
    -/**
    - * Finalizes spelling check.
    - * @private
    - */
    -goog.ui.RichTextSpellChecker.prototype.finishCheck_ = function() {
    -  delete this.currentNode_;
    -  this.spellCheck.processPending();
    -
    -  if (!this.isVisible()) {
    -    this.eventHandler_.
    -        listen(this.rootNode_, goog.events.EventType.CLICK, this.onWordClick_).
    -        listen(this.keyHandler_, goog.events.KeyHandler.EventType.KEY,
    -            this.handleRootNodeKeyEvent);
    -  }
    -  goog.ui.RichTextSpellChecker.superClass_.check.call(this);
    -};
    -
    -
    -/**
    - * Finds next node in our enumeration of the tree.
    - *
    - * @param {Node} node The node to which we're computing the next node for.
    - * @return {Node} The next node or null if none was found.
    - * @private
    - */
    -goog.ui.RichTextSpellChecker.prototype.nextNode_ = function(node) {
    -  while (node != this.rootNode_) {
    -    if (node.nextSibling) {
    -      return node.nextSibling;
    -    }
    -    node = node.parentNode;
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * Determines if the node is text node without any children.
    - *
    - * @param {Node} node The node to check.
    - * @return {boolean} Whether the node is a text leaf node.
    - * @private
    - */
    -goog.ui.RichTextSpellChecker.prototype.isTextLeaf_ = function(node) {
    -  return node != null &&
    -         node.nodeType == goog.dom.NodeType.TEXT &&
    -         !node.firstChild;
    -};
    -
    -
    -/** @override */
    -goog.ui.RichTextSpellChecker.prototype.setExcludeMarker = function(marker) {
    -  if (marker) {
    -    if (typeof marker == 'string') {
    -      marker = [marker];
    -    }
    -
    -    this.excludeTags = [];
    -    this.excludeMarker = [];
    -    for (var i = 0; i < marker.length; i++) {
    -      var parts = marker[i].split('.');
    -      if (parts.length == 2) {
    -        this.excludeTags.push(parts[0]);
    -        this.excludeMarker.push(parts[1]);
    -      } else {
    -        this.excludeMarker.push(parts[0]);
    -        this.excludeTags.push(undefined);
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Determines if the node is excluded from checking.
    - *
    - * @param {Node} node The node to check.
    - * @return {boolean} Whether the node is excluded.
    - * @private
    - */
    -goog.ui.RichTextSpellChecker.prototype.isExcluded_ = function(node) {
    -  if (this.excludeMarker && node.className) {
    -    for (var i = 0; i < this.excludeMarker.length; i++) {
    -      var excludeTag = this.excludeTags[i];
    -      var excludeClass = this.excludeMarker[i];
    -      var isExcluded = !!(excludeClass &&
    -          node.className.indexOf(excludeClass) != -1 &&
    -          (!excludeTag || node.tagName == excludeTag));
    -      if (isExcluded) {
    -        return true;
    -      }
    -    }
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Processes nodes recursively.
    - *
    - * @param {Node} node Node where to start.
    - * @return {goog.ui.AbstractSpellChecker.AsyncResult|undefined} Result code.
    - * @private
    - */
    -goog.ui.RichTextSpellChecker.prototype.processNode_ = function(node) {
    -  delete this.currentNode_;
    -  while (node) {
    -    var next = this.nextNode_(node);
    -    if (this.isExcluded_(node)) {
    -      node = next;
    -      continue;
    -    }
    -    if (node.nodeType == goog.dom.NodeType.TEXT) {
    -      var deleteNode = true;
    -      if (node.nodeValue) {
    -        var currentElements = this.elementsInserted_;
    -        var result = this.processTextAsync(node, node.nodeValue);
    -        if (result == goog.ui.AbstractSpellChecker.AsyncResult.PENDING) {
    -          // This markes node for deletion (empty nodes get deleted couple
    -          // of lines down this function). This is so our algorithm terminates.
    -          // In this case the node may be needlessly recreated, but it
    -          // happens rather infrequently and saves a lot of code.
    -          node.nodeValue = '';
    -          this.currentNode_ = node;
    -          return result;
    -        }
    -        // If we did not add nodes in processing, the current element is still
    -        // valid. Let's preserve it!
    -        if (currentElements == this.elementsInserted_) {
    -          deleteNode = false;
    -        }
    -      }
    -      if (deleteNode) {
    -        goog.dom.removeNode(node);
    -      }
    -    } else if (node.nodeType == goog.dom.NodeType.ELEMENT) {
    -      // If this is a spell checker element...
    -      if (node.className == this.wordClassName) {
    -        // First, reconsolidate the text nodes inside the element - editing
    -        // in IE splits them up.
    -        var runner = node.firstChild;
    -        while (runner) {
    -          if (this.isTextLeaf_(runner)) {
    -            while (this.isTextLeaf_(runner.nextSibling)) {
    -              // Yes, this is not super efficient in IE, but it will almost
    -              // never happen.
    -              runner.nodeValue += runner.nextSibling.nodeValue;
    -              goog.dom.removeNode(runner.nextSibling);
    -            }
    -          }
    -          runner = runner.nextSibling;
    -        }
    -        // Move its contents out and reprocess it on the next iteration.
    -        if (node.firstChild) {
    -          next = node.firstChild;
    -          while (node.firstChild) {
    -            node.parentNode.insertBefore(node.firstChild, node);
    -          }
    -        }
    -        // get rid of the empty shell.
    -        goog.dom.removeNode(node);
    -      } else {
    -        if (node.firstChild) {
    -          next = node.firstChild;
    -        }
    -      }
    -    }
    -    node = next;
    -  }
    -};
    -
    -
    -/**
    - * Processes word.
    - *
    - * @param {Node} node Node containing word.
    - * @param {string} word Word to process.
    - * @param {goog.spell.SpellCheck.WordStatus} status Status of the word.
    - * @protected
    - * @override
    - */
    -goog.ui.RichTextSpellChecker.prototype.processWord = function(node, word,
    -                                                              status) {
    -  node.parentNode.insertBefore(this.createWordElement(word, status), node);
    -  this.elementsInserted_++;
    -};
    -
    -
    -/**
    - * Processes recognized text and separators.
    - *
    - * @param {Node} node Node containing separator.
    - * @param {string} text Text to process.
    - * @protected
    - * @override
    - */
    -goog.ui.RichTextSpellChecker.prototype.processRange = function(node, text) {
    -  // The text does not change, it only gets split, so if the lengths are the
    -  // same, the text is the same, so keep the existing node.
    -  if (node.nodeType == goog.dom.NodeType.TEXT && node.nodeValue.length ==
    -      text.length) {
    -    return;
    -  }
    -
    -  node.parentNode.insertBefore(this.editorDom_.createTextNode(text), node);
    -  this.elementsInserted_++;
    -};
    -
    -
    -/** @override */
    -goog.ui.RichTextSpellChecker.prototype.getElementByIndex = function(id) {
    -  return this.editorDom_.getElement(this.makeElementId(id));
    -};
    -
    -
    -/**
    - * Updates or replaces element based on word status.
    - * @see goog.ui.AbstractSpellChecker.prototype.updateElement_
    - *
    - * Overridden from AbstractSpellChecker because we need to be mindful of
    - * deleting the currentNode_ - this can break our pending processing.
    - *
    - * @param {Element} el Word element.
    - * @param {string} word Word to update status for.
    - * @param {goog.spell.SpellCheck.WordStatus} status Status of word.
    - * @protected
    - * @override
    - */
    -goog.ui.RichTextSpellChecker.prototype.updateElement = function(el, word,
    -    status) {
    -  if (status == goog.spell.SpellCheck.WordStatus.VALID && el !=
    -      this.currentNode_ && el.nextSibling != this.currentNode_) {
    -    this.removeMarkup(el);
    -  } else {
    -    goog.dom.setProperties(el, this.getElementProperties(status));
    -  }
    -};
    -
    -
    -/**
    - * Hides correction UI.
    - * @override
    - */
    -goog.ui.RichTextSpellChecker.prototype.resume = function() {
    -  goog.ui.RichTextSpellChecker.superClass_.resume.call(this);
    -
    -  this.restoreNode_(this.rootNode_);
    -
    -  this.eventHandler_.
    -      unlisten(this.rootNode_, goog.events.EventType.CLICK, this.onWordClick_).
    -      unlisten(this.keyHandler_, goog.events.KeyHandler.EventType.KEY,
    -          this.handleRootNodeKeyEvent);
    -};
    -
    -
    -/**
    - * Processes nodes recursively, removes all spell checker markup, and
    - * consolidates text nodes.
    - *
    - * @param {Node} node node on which to recurse.
    - * @private
    - */
    -goog.ui.RichTextSpellChecker.prototype.restoreNode_ = function(node) {
    -  while (node) {
    -    if (this.isExcluded_(node)) {
    -      node = node.nextSibling;
    -      continue;
    -    }
    -    // Contents of the child of the element is usually 1 text element, but the
    -    // user can actually add multiple nodes in it during editing. So we move
    -    // all the children out, prepend, and reprocess (pointer is set back to
    -    // the first node that's been moved out, and the loop repeats).
    -    if (node.nodeType == goog.dom.NodeType.ELEMENT && node.className ==
    -        this.wordClassName) {
    -      var firstElement = node.firstChild;
    -      var next;
    -      for (var child = firstElement; child; child = next) {
    -        next = child.nextSibling;
    -        node.parentNode.insertBefore(child, node);
    -      }
    -      next = firstElement || node.nextSibling;
    -      goog.dom.removeNode(node);
    -      node = next;
    -      continue;
    -    }
    -    // If this is a chain of text elements, we're trying to consolidate it.
    -    var textLeaf = this.isTextLeaf_(node);
    -    if (textLeaf) {
    -      var textNodes = 1;
    -      var next = node.nextSibling;
    -      while (this.isTextLeaf_(node.previousSibling)) {
    -        node = node.previousSibling;
    -        ++textNodes;
    -      }
    -      while (this.isTextLeaf_(next)) {
    -        next = next.nextSibling;
    -        ++textNodes;
    -      }
    -      if (textNodes > 1) {
    -        this.workBuffer_.append(node.nodeValue);
    -        while (this.isTextLeaf_(node.nextSibling)) {
    -          this.workBuffer_.append(node.nextSibling.nodeValue);
    -          goog.dom.removeNode(node.nextSibling);
    -        }
    -        node.nodeValue = this.workBuffer_.toString();
    -        this.workBuffer_.clear();
    -      }
    -    }
    -    // Process child nodes, if any.
    -    if (node.firstChild) {
    -      this.restoreNode_(node.firstChild);
    -    }
    -    node = node.nextSibling;
    -  }
    -};
    -
    -
    -/**
    - * Returns desired element properties for the specified status.
    - *
    - * @param {goog.spell.SpellCheck.WordStatus} status Status of the word.
    - * @return {!Object} Properties to apply to word element.
    - * @protected
    - * @override
    - */
    -goog.ui.RichTextSpellChecker.prototype.getElementProperties =
    -    function(status) {
    -  return {
    -    'class': this.wordClassName,
    -    'style': (status == goog.spell.SpellCheck.WordStatus.INVALID) ?
    -        this.invalidWordCssText : ''
    -  };
    -};
    -
    -
    -/**
    - * Handler for click events.
    - *
    - * @param {goog.events.BrowserEvent} event Event object.
    - * @private
    - */
    -goog.ui.RichTextSpellChecker.prototype.onWordClick_ = function(event) {
    -  var target = /** @type {Element} */ (event.target);
    -  if (event.target.className == this.wordClassName &&
    -      this.spellCheck.checkWord(goog.dom.getTextContent(target)) ==
    -      goog.spell.SpellCheck.WordStatus.INVALID) {
    -
    -    this.showSuggestionsMenu(target, event);
    -
    -    // Prevent document click handler from closing the menu.
    -    event.stopPropagation();
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.RichTextSpellChecker.prototype.disposeInternal = function() {
    -  goog.ui.RichTextSpellChecker.superClass_.disposeInternal.call(this);
    -  this.rootNode_ = null;
    -  this.editorDom_ = null;
    -};
    -
    -
    -/**
    - * Returns whether the editor node is an iframe.
    - *
    - * @return {boolean} true the editor node is an iframe, otherwise false.
    - * @protected
    - */
    -goog.ui.RichTextSpellChecker.prototype.isEditorIframe = function() {
    -  return this.rootNodeIframe_;
    -};
    -
    -
    -/**
    - * Handles keyboard events inside the editor to allow keyboard navigation
    - * between misspelled words and activation of the suggestion menu.
    - *
    - * @param {goog.events.BrowserEvent} e the key event.
    - * @return {boolean} The handled value.
    - * @protected
    - */
    -goog.ui.RichTextSpellChecker.prototype.handleRootNodeKeyEvent = function(e) {
    -  var handled = false;
    -  switch (e.keyCode) {
    -    case goog.events.KeyCodes.RIGHT:
    -      if (e.ctrlKey) {
    -        handled = this.navigate(goog.ui.AbstractSpellChecker.Direction.NEXT);
    -      }
    -      break;
    -
    -    case goog.events.KeyCodes.LEFT:
    -      if (e.ctrlKey) {
    -        handled = this.navigate(
    -            goog.ui.AbstractSpellChecker.Direction.PREVIOUS);
    -      }
    -      break;
    -
    -    case goog.events.KeyCodes.DOWN:
    -      if (this.getFocusedElementIndex()) {
    -        var el = this.editorDom_.getElement(this.makeElementId(
    -            this.getFocusedElementIndex()));
    -        if (el) {
    -          var position = goog.style.getClientPosition(el);
    -
    -          if (this.isEditorIframe()) {
    -            var iframePosition = goog.style.getClientPosition(
    -                this.getElementStrict());
    -            position = goog.math.Coordinate.sum(iframePosition, position);
    -          }
    -
    -          var size = goog.style.getSize(el);
    -          position.x += size.width / 2;
    -          position.y += size.height / 2;
    -          this.showSuggestionsMenu(el, position);
    -          handled = true;
    -        }
    -      }
    -      break;
    -  }
    -
    -  if (handled) {
    -    e.preventDefault();
    -  }
    -
    -  return handled;
    -};
    -
    -
    -/** @override */
    -goog.ui.RichTextSpellChecker.prototype.onCorrectionAction = function(event) {
    -  goog.ui.RichTextSpellChecker.base(this, 'onCorrectionAction', event);
    -
    -  // In case of editWord base class has already set the focus (on the input),
    -  // otherwise set the focus back on the word.
    -  if (event.target != this.getMenuEdit()) {
    -    this.reFocus_();
    -  }
    -};
    -
    -
    -/**
    - * Restores focus when the suggestion menu is hidden.
    - *
    - * @param {goog.events.BrowserEvent} event Blur event.
    - * @private
    - */
    -goog.ui.RichTextSpellChecker.prototype.onCorrectionHide_ = function(event) {
    -  this.reFocus_();
    -};
    -
    -
    -/**
    - * Sets the focus back on the previously focused word element.
    - * @private
    - */
    -goog.ui.RichTextSpellChecker.prototype.reFocus_ = function() {
    -  this.getElementStrict().focus();
    -
    -  var el = this.getElementByIndex(this.getFocusedElementIndex());
    -  if (el) {
    -    this.focusOnElement(el);
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.RichTextSpellChecker.prototype.focusOnElement = function(element) {
    -  goog.dom.Range.createCaret(element, 0).select();
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/richtextspellchecker_test.html b/src/database/third_party/closure-library/closure/goog/ui/richtextspellchecker_test.html
    deleted file mode 100644
    index 2528646d1ee..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/richtextspellchecker_test.html
    +++ /dev/null
    @@ -1,38 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.RichTextSpellChecker
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.RichTextSpellCheckerTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="test1">
    -  </div>
    -  <div id="test2">
    -  </div>
    -  <div id="test3">
    -  </div>
    -  <div id="test4" contenteditable="true">
    -  </div>
    -  <div id="test5" contenteditable="true">
    -  </div>
    -  <div id="test6" contenteditable="true">
    -  </div>
    -  <div id="test7" contenteditable="true">
    -  </div>
    -  <div id="test8" contenteditable="true">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/richtextspellchecker_test.js b/src/database/third_party/closure-library/closure/goog/ui/richtextspellchecker_test.js
    deleted file mode 100644
    index 143a55a3c5e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/richtextspellchecker_test.js
    +++ /dev/null
    @@ -1,367 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.RichTextSpellCheckerTest');
    -goog.setTestOnly('goog.ui.RichTextSpellCheckerTest');
    -
    -goog.require('goog.dom.Range');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.object');
    -goog.require('goog.spell.SpellCheck');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.RichTextSpellChecker');
    -
    -var VOCABULARY = ['test', 'words', 'a', 'few'];
    -var SUGGESTIONS = ['foo', 'bar'];
    -var EXCLUDED_DATA = ['DIV.goog-quote', 'goog-comment', 'SPAN.goog-note'];
    -
    -
    -/**
    - * Delay in ms needed for the spell check word lookup to finish. Finishing the
    - * lookup also finishes the spell checking.
    - * @see goog.spell.SpellCheck.LOOKUP_DELAY_
    - */
    -var SPELL_CHECK_LOOKUP_DELAY = 100;
    -
    -var TEST_TEXT1 = 'this test is longer than a few words now';
    -var TEST_TEXT2 = 'test another simple text with misspelled words';
    -var TEST_TEXT3 = 'test another simple text with misspelled words' +
    -    '<b class="goog-quote">test another simple text with misspelled words<u> ' +
    -    'test another simple text with misspelled words<del class="goog-quote"> ' +
    -    'test another simple text with misspelled words<i>this test is longer ' +
    -    'than a few words now</i>test another simple text with misspelled words ' +
    -    '<i>this test is longer than a few words now</i></del>test another ' +
    -    'simple text with misspelled words<del class="goog-quote">test another ' +
    -    'simple text with misspelled words<i>this test is longer than a few ' +
    -    'words now</i>test another simple text with misspelled words<i>this test ' +
    -    'is longer than a few words now</i></del></u>test another simple text ' +
    -    'with misspelled words<u>test another simple text with misspelled words' +
    -    '<del class="goog-quote">test another simple text with misspelled words' +
    -    '<i> thistest is longer than a few words now</i>test another simple text ' +
    -    'with misspelled words<i>this test is longer than a few words ' +
    -    'now</i></del>test another simple text with misspelled words' +
    -    '<del class="goog-quote">test another simple text with misspelled words' +
    -    '<i>this test is longer than a few words now</i>test another simple text ' +
    -    'with misspelled words<i>this test is longer than a few words ' +
    -    'now</i></del></u></b>';
    -
    -var spellChecker;
    -var handler;
    -var mockClock;
    -
    -function setUp() {
    -  mockClock = new goog.testing.MockClock(true /* install */);
    -  handler = new goog.spell.SpellCheck(localSpellCheckingFunction);
    -  spellChecker = new goog.ui.RichTextSpellChecker(handler);
    -}
    -
    -function tearDown() {
    -  spellChecker.dispose();
    -  handler.dispose();
    -  mockClock.dispose();
    -}
    -
    -function waitForSpellCheckToFinish() {
    -  mockClock.tick(SPELL_CHECK_LOOKUP_DELAY);
    -}
    -
    -
    -/**
    - * @typedef {!Array<string><string>>}
    - * @suppress {missingProvide}
    - */
    -var lookupWordEntry;
    -
    -
    -/**
    - * Function to use for word lookup by the spell check handler. This function is
    - * supplied as a constructor parameter for the spell check handler.
    - * @param {!Array<string>} words Unknown words that need to be looked up.
    - * @param {!goog.spell.SpellCheck} spellChecker The spell check handler.
    - * @param {function(!Array.)} callback The lookup callback
    - *     function.
    - */
    -function localSpellCheckingFunction(words, spellChecker, callback) {
    -  var len = words.length;
    -  var results = [];
    -  for (var i = 0; i < len; i++) {
    -    var word = words[i];
    -    var found = false;
    -    for (var j = 0; j < VOCABULARY.length; ++j) {
    -      if (VOCABULARY[j] == word) {
    -        found = true;
    -        break;
    -      }
    -    }
    -    if (found) {
    -      results.push([word, goog.spell.SpellCheck.WordStatus.VALID]);
    -    } else {
    -      results.push([word, goog.spell.SpellCheck.WordStatus.INVALID,
    -        SUGGESTIONS]);
    -    }
    -  }
    -  callback.call(spellChecker, results);
    -}
    -
    -function testDocumentIntegrity() {
    -  var el = document.getElementById('test1');
    -  spellChecker.decorate(el);
    -  el.appendChild(document.createTextNode(TEST_TEXT3));
    -  var el2 = el.cloneNode(true);
    -
    -  spellChecker.setExcludeMarker('goog-quote');
    -  spellChecker.check();
    -  waitForSpellCheckToFinish();
    -  spellChecker.ignoreWord('iggnore');
    -  waitForSpellCheckToFinish();
    -  spellChecker.check();
    -  waitForSpellCheckToFinish();
    -  spellChecker.resume();
    -  waitForSpellCheckToFinish();
    -
    -  assertEquals('Spell checker run should not change the underlying element.',
    -               el2.innerHTML, el.innerHTML);
    -}
    -
    -function testExcludeMarkers() {
    -  var el = document.getElementById('test1');
    -  spellChecker.decorate(el);
    -  spellChecker.setExcludeMarker(
    -      ['DIV.goog-quote', 'goog-comment', 'SPAN.goog-note']);
    -  assertArrayEquals(['goog-quote', 'goog-comment', 'goog-note'],
    -      spellChecker.excludeMarker);
    -  assertArrayEquals(['DIV', undefined, 'SPAN'],
    -      spellChecker.excludeTags);
    -  el.innerHTML = '<div class="goog-quote">misspelling</div>' +
    -      '<div class="goog-yes">misspelling</div>' +
    -      '<div class="goog-note">misspelling</div>' +
    -      '<div class="goog-comment">misspelling</div>' +
    -      '<span>misspelling<span>';
    -
    -  spellChecker.check();
    -  waitForSpellCheckToFinish();
    -  assertEquals(3, spellChecker.getLastIndex());
    -}
    -
    -function testBiggerDocument() {
    -  var el = document.getElementById('test2');
    -  spellChecker.decorate(el);
    -  el.appendChild(document.createTextNode(TEST_TEXT3));
    -  var el2 = el.cloneNode(true);
    -
    -  spellChecker.check();
    -  waitForSpellCheckToFinish();
    -  spellChecker.resume();
    -  waitForSpellCheckToFinish();
    -
    -  assertEquals('Spell checker run should not change the underlying element.',
    -               el2.innerHTML, el.innerHTML);
    -}
    -
    -function testElementOverflow() {
    -  var el = document.getElementById('test3');
    -  spellChecker.decorate(el);
    -  el.appendChild(document.createTextNode(TEST_TEXT3));
    -
    -  var el2 = el.cloneNode(true);
    -
    -  spellChecker.check();
    -  waitForSpellCheckToFinish();
    -  spellChecker.check();
    -  waitForSpellCheckToFinish();
    -  spellChecker.resume();
    -  waitForSpellCheckToFinish();
    -
    -  assertEquals('Spell checker run should not change the underlying element.',
    -               el2.innerHTML, el.innerHTML);
    -}
    -
    -function testKeyboardNavigateNext() {
    -  var el = document.getElementById('test4');
    -  spellChecker.decorate(el);
    -  var text = 'a unit test for keyboard test';
    -  el.appendChild(document.createTextNode(text));
    -  var keyEventProperties =
    -      goog.object.create('ctrlKey', true, 'shiftKey', false);
    -
    -  spellChecker.check();
    -  waitForSpellCheckToFinish();
    -
    -  // First call just moves focus to first misspelled word.
    -  goog.testing.events.fireKeySequence(el, goog.events.KeyCodes.RIGHT,
    -      keyEventProperties);
    -
    -  // Test moving from first to second mispelled word.
    -  var defaultExecuted = goog.testing.events.fireKeySequence(el,
    -      goog.events.KeyCodes.RIGHT, keyEventProperties);
    -
    -  assertFalse('The default action should be prevented for the key event',
    -      defaultExecuted);
    -  assertCursorAtElement(spellChecker.makeElementId(2));
    -
    -  spellChecker.resume();
    -}
    -
    -function testKeyboardNavigateNextOnLastWord() {
    -  var el = document.getElementById('test5');
    -  spellChecker.decorate(el);
    -  var text = 'a unit test for keyboard test';
    -  el.appendChild(document.createTextNode(text));
    -  var keyEventProperties =
    -      goog.object.create('ctrlKey', true, 'shiftKey', false);
    -
    -  spellChecker.check();
    -  waitForSpellCheckToFinish();
    -
    -  // Move to the last invalid word.
    -  goog.testing.events.fireKeySequence(el, goog.events.KeyCodes.RIGHT,
    -      keyEventProperties);
    -  goog.testing.events.fireKeySequence(el, goog.events.KeyCodes.RIGHT,
    -      keyEventProperties);
    -  goog.testing.events.fireKeySequence(el, goog.events.KeyCodes.RIGHT,
    -      keyEventProperties);
    -
    -  // Test moving to the next invalid word. Should have no effect.
    -  var defaultExecuted = goog.testing.events.fireKeySequence(el,
    -      goog.events.KeyCodes.RIGHT, keyEventProperties);
    -
    -  assertFalse('The default action should be prevented for the key event',
    -      defaultExecuted);
    -  assertCursorAtElement(spellChecker.makeElementId(3));
    -
    -  spellChecker.resume();
    -}
    -
    -function testKeyboardNavigateOpenSuggestions() {
    -  var el = document.getElementById('test6');
    -  spellChecker.decorate(el);
    -  var text = 'unit';
    -  el.appendChild(document.createTextNode(text));
    -  var keyEventProperties =
    -      goog.object.create('ctrlKey', true, 'shiftKey', false);
    -
    -  spellChecker.check();
    -  waitForSpellCheckToFinish();
    -
    -  var suggestionMenu = spellChecker.getMenu();
    -
    -  goog.testing.events.fireKeySequence(el, goog.events.KeyCodes.RIGHT,
    -      keyEventProperties);
    -
    -  assertFalse('The suggestion menu should not be visible yet.',
    -      suggestionMenu.isVisible());
    -
    -  keyEventProperties.ctrlKey = false;
    -  var defaultExecuted = goog.testing.events.fireKeySequence(el,
    -      goog.events.KeyCodes.DOWN, keyEventProperties);
    -
    -  assertFalse('The default action should be prevented for the key event',
    -      defaultExecuted);
    -  assertTrue('The suggestion menu should be visible after the key event.',
    -      suggestionMenu.isVisible());
    -
    -  spellChecker.resume();
    -}
    -
    -function testKeyboardNavigatePrevious() {
    -  var el = document.getElementById('test7');
    -  spellChecker.decorate(el);
    -  var text = 'a unit test for keyboard test';
    -  el.appendChild(document.createTextNode(text));
    -  var keyEventProperties =
    -      goog.object.create('ctrlKey', true, 'shiftKey', false);
    -
    -  spellChecker.check();
    -  waitForSpellCheckToFinish();
    -
    -  // Move to the third element, so we can test the move back to the second.
    -  goog.testing.events.fireKeySequence(el, goog.events.KeyCodes.RIGHT,
    -      keyEventProperties);
    -  goog.testing.events.fireKeySequence(el, goog.events.KeyCodes.RIGHT,
    -      keyEventProperties);
    -  goog.testing.events.fireKeySequence(el, goog.events.KeyCodes.RIGHT,
    -      keyEventProperties);
    -
    -  var defaultExecuted = goog.testing.events.fireKeySequence(el,
    -      goog.events.KeyCodes.LEFT, keyEventProperties);
    -
    -  assertFalse('The default action should be prevented for the key event',
    -      defaultExecuted);
    -  assertCursorAtElement(spellChecker.makeElementId(2));
    -
    -  spellChecker.resume();
    -}
    -
    -function testKeyboardNavigatePreviousOnLastWord() {
    -  var el = document.getElementById('test8');
    -  spellChecker.decorate(el);
    -  var text = 'a unit test for keyboard test';
    -  el.appendChild(document.createTextNode(text));
    -  var keyEventProperties =
    -      goog.object.create('ctrlKey', true, 'shiftKey', false);
    -
    -  spellChecker.check();
    -  waitForSpellCheckToFinish();
    -
    -  // Move to the first invalid word.
    -  goog.testing.events.fireKeySequence(el, goog.events.KeyCodes.RIGHT,
    -      keyEventProperties);
    -
    -  // Test moving to the previous invalid word. Should have no effect.
    -  var defaultExecuted = goog.testing.events.fireKeySequence(el,
    -      goog.events.KeyCodes.LEFT, keyEventProperties);
    -
    -  assertFalse('The default action should be prevented for the key event',
    -      defaultExecuted);
    -  assertCursorAtElement(spellChecker.makeElementId(1));
    -
    -  spellChecker.resume();
    -}
    -
    -function assertCursorAtElement(expectedId) {
    -  var range = goog.dom.Range.createFromWindow();
    -
    -  if (isCaret(range)) {
    -    if (isMisspelledWordElement(range.getStartNode())) {
    -      var focusedElementId = range.getStartNode().id;
    -    }
    -
    -    // In Chrome a cursor at the start of a misspelled word will appear to be at
    -    // the end of the text node preceding it.
    -    if (isCursorAtEndOfStartNode(range) &&
    -        range.getStartNode().nextSibling != null &&
    -        isMisspelledWordElement(range.getStartNode().nextSibling)) {
    -      var focusedElementId = range.getStartNode().nextSibling.id;
    -    }
    -  }
    -
    -  assertEquals('The cursor is not at the expected misspelled word.',
    -      expectedId, focusedElementId);
    -}
    -
    -function isCaret(range) {
    -  return range.getStartNode() == range.getEndNode();
    -}
    -
    -function isMisspelledWordElement(element) {
    -  return goog.dom.classlist.contains(
    -      element, 'goog-spellcheck-word');
    -}
    -
    -function isCursorAtEndOfStartNode(range) {
    -  return range.getStartNode().length == range.getStartOffset();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/roundedpanel.js b/src/database/third_party/closure-library/closure/goog/ui/roundedpanel.js
    deleted file mode 100644
    index cbddddbdaaf..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/roundedpanel.js
    +++ /dev/null
    @@ -1,630 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Class definition for a rounded corner panel.
    - * @supported IE 6.0+, Safari 2.0+, Firefox 1.5+, Opera 9.2+.
    - * @see ../demos/roundedpanel.html
    - */
    -
    -goog.provide('goog.ui.BaseRoundedPanel');
    -goog.provide('goog.ui.CssRoundedPanel');
    -goog.provide('goog.ui.GraphicsRoundedPanel');
    -goog.provide('goog.ui.RoundedPanel');
    -goog.provide('goog.ui.RoundedPanel.Corner');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.graphics');
    -goog.require('goog.graphics.Path');
    -goog.require('goog.graphics.SolidFill');
    -goog.require('goog.graphics.Stroke');
    -goog.require('goog.math');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.style');
    -goog.require('goog.ui.Component');
    -goog.require('goog.userAgent');
    -
    -
    -/**
    - * Factory method that returns an instance of a BaseRoundedPanel.
    - * @param {number} radius The radius of the rounded corner(s), in pixels.
    - * @param {number} borderWidth The thickness of the border, in pixels.
    - * @param {string} borderColor The border color of the panel.
    - * @param {string=} opt_backgroundColor The background color of the panel.
    - * @param {number=} opt_corners The corners of the panel to be rounded. Any
    - *     corners not specified will be rendered as square corners. Will default
    - *     to all square corners if not specified.
    - * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper object for the
    - *     document we want to render in.
    - * @return {!goog.ui.BaseRoundedPanel} An instance of a
    - *     goog.ui.BaseRoundedPanel subclass.
    - */
    -goog.ui.RoundedPanel.create = function(radius,
    -                                       borderWidth,
    -                                       borderColor,
    -                                       opt_backgroundColor,
    -                                       opt_corners,
    -                                       opt_domHelper) {
    -  // This variable checks for the presence of Safari 3.0+ or Gecko 1.9+,
    -  // which can leverage special CSS styles to create rounded corners.
    -  var isCssReady = goog.userAgent.WEBKIT &&
    -      goog.userAgent.isVersionOrHigher('500') ||
    -      goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.9a');
    -
    -  if (isCssReady) {
    -    // Safari 3.0+ and Firefox 3.0+ support this instance.
    -    return new goog.ui.CssRoundedPanel(
    -        radius,
    -        borderWidth,
    -        borderColor,
    -        opt_backgroundColor,
    -        opt_corners,
    -        opt_domHelper);
    -  } else {
    -    return new goog.ui.GraphicsRoundedPanel(
    -        radius,
    -        borderWidth,
    -        borderColor,
    -        opt_backgroundColor,
    -        opt_corners,
    -        opt_domHelper);
    -  }
    -};
    -
    -
    -/**
    - * Enum for specifying which corners to render.
    - * @enum {number}
    - */
    -goog.ui.RoundedPanel.Corner = {
    -  NONE: 0,
    -  BOTTOM_LEFT: 2,
    -  TOP_LEFT: 4,
    -  LEFT: 6, // BOTTOM_LEFT | TOP_LEFT
    -  TOP_RIGHT: 8,
    -  TOP: 12, // TOP_LEFT | TOP_RIGHT
    -  BOTTOM_RIGHT: 1,
    -  BOTTOM: 3, // BOTTOM_LEFT | BOTTOM_RIGHT
    -  RIGHT: 9, // TOP_RIGHT | BOTTOM_RIGHT
    -  ALL: 15 // TOP | BOTTOM
    -};
    -
    -
    -/**
    - * CSS class name suffixes for the elements comprising the RoundedPanel.
    - * @enum {string}
    - * @private
    - */
    -goog.ui.RoundedPanel.Classes_ = {
    -  BACKGROUND: goog.getCssName('goog-roundedpanel-background'),
    -  PANEL: goog.getCssName('goog-roundedpanel'),
    -  CONTENT: goog.getCssName('goog-roundedpanel-content')
    -};
    -
    -
    -
    -/**
    - * Base class for the hierarchy of RoundedPanel classes. Do not
    - * instantiate directly. Instead, call goog.ui.RoundedPanel.create().
    - * The HTML structure for the RoundedPanel is:
    - * <pre>
    - * - div (Contains the background and content. Class name: goog-roundedpanel)
    - *   - div (Contains the background/rounded corners. Class name:
    - *       goog-roundedpanel-bg)
    - *   - div (Contains the content. Class name: goog-roundedpanel-content)
    - * </pre>
    - * @param {number} radius The radius of the rounded corner(s), in pixels.
    - * @param {number} borderWidth The thickness of the border, in pixels.
    - * @param {string} borderColor The border color of the panel.
    - * @param {string=} opt_backgroundColor The background color of the panel.
    - * @param {number=} opt_corners The corners of the panel to be rounded. Any
    - *     corners not specified will be rendered as square corners. Will default
    - *     to all square corners if not specified.
    - * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper object for the
    - *     document we want to render in.
    - * @extends {goog.ui.Component}
    - * @constructor
    - */
    -goog.ui.BaseRoundedPanel = function(radius,
    -                                    borderWidth,
    -                                    borderColor,
    -                                    opt_backgroundColor,
    -                                    opt_corners,
    -                                    opt_domHelper) {
    -  goog.ui.Component.call(this, opt_domHelper);
    -
    -  /**
    -   * The radius of the rounded corner(s), in pixels.
    -   * @type {number}
    -   * @private
    -   */
    -  this.radius_ = radius;
    -
    -  /**
    -   * The thickness of the border, in pixels.
    -   * @type {number}
    -   * @private
    -   */
    -  this.borderWidth_ = borderWidth;
    -
    -  /**
    -   * The border color of the panel.
    -   * @type {string}
    -   * @private
    -   */
    -  this.borderColor_ = borderColor;
    -
    -  /**
    -   * The background color of the panel.
    -   * @type {?string}
    -   * @private
    -   */
    -  this.backgroundColor_ = opt_backgroundColor || null;
    -
    -  /**
    -   * The corners of the panel to be rounded; defaults to
    -   * goog.ui.RoundedPanel.Corner.NONE
    -   * @type {number}
    -   * @private
    -   */
    -  this.corners_ = opt_corners || goog.ui.RoundedPanel.Corner.NONE;
    -};
    -goog.inherits(goog.ui.BaseRoundedPanel, goog.ui.Component);
    -goog.tagUnsealableClass(goog.ui.BaseRoundedPanel);
    -
    -
    -/**
    - * The element containing the rounded corners and background.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.BaseRoundedPanel.prototype.backgroundElement_;
    -
    -
    -/**
    - * The element containing the actual content.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.BaseRoundedPanel.prototype.contentElement_;
    -
    -
    -/**
    - * This method performs all the necessary DOM manipulation to create the panel.
    - * Overrides {@link goog.ui.Component#decorateInternal}.
    - * @param {Element} element The element to decorate.
    - * @protected
    - * @override
    - */
    -goog.ui.BaseRoundedPanel.prototype.decorateInternal = function(element) {
    -  goog.ui.BaseRoundedPanel.superClass_.decorateInternal.call(this, element);
    -  goog.dom.classlist.add(goog.asserts.assert(this.getElement()),
    -      goog.ui.RoundedPanel.Classes_.PANEL);
    -
    -  // Create backgroundElement_, and add it to the DOM.
    -  this.backgroundElement_ = this.getDomHelper().createElement('div');
    -  this.backgroundElement_.className = goog.ui.RoundedPanel.Classes_.BACKGROUND;
    -  this.getElement().appendChild(this.backgroundElement_);
    -
    -  // Set contentElement_ by finding a child node within element_ with the
    -  // proper class name. If none exists, create it and add it to the DOM.
    -  this.contentElement_ = goog.dom.getElementsByTagNameAndClass(
    -      null, goog.ui.RoundedPanel.Classes_.CONTENT, this.getElement())[0];
    -  if (!this.contentElement_) {
    -    this.contentElement_ = this.getDomHelper().createDom('div');
    -    this.contentElement_.className = goog.ui.RoundedPanel.Classes_.CONTENT;
    -    this.getElement().appendChild(this.contentElement_);
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.BaseRoundedPanel.prototype.disposeInternal = function() {
    -  if (this.backgroundElement_) {
    -    this.getDomHelper().removeNode(this.backgroundElement_);
    -    this.backgroundElement_ = null;
    -  }
    -  this.contentElement_ = null;
    -  goog.ui.BaseRoundedPanel.superClass_.disposeInternal.call(this);
    -};
    -
    -
    -/**
    - * Returns the DOM element containing the actual content.
    - * @return {Element} The element containing the actual content (null if none).
    - * @override
    - */
    -goog.ui.BaseRoundedPanel.prototype.getContentElement = function() {
    -  return this.contentElement_;
    -};
    -
    -
    -
    -/**
    - * RoundedPanel class specifically for browsers that support CSS attributes
    - * for elements with rounded borders (ex. Safari 3.0+, Firefox 3.0+). Do not
    - * instantiate directly. Instead, call goog.ui.RoundedPanel.create().
    - * @param {number} radius The radius of the rounded corner(s), in pixels.
    - * @param {number} borderWidth The thickness of the border, in pixels.
    - * @param {string} borderColor The border color of the panel.
    - * @param {string=} opt_backgroundColor The background color of the panel.
    - * @param {number=} opt_corners The corners of the panel to be rounded. Any
    - *     corners not specified will be rendered as square corners. Will
    - *     default to all square corners if not specified.
    - * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper object for the
    - *     document we want to render in.
    - * @extends {goog.ui.BaseRoundedPanel}
    - * @constructor
    - * @final
    - */
    -goog.ui.CssRoundedPanel = function(radius,
    -                                   borderWidth,
    -                                   borderColor,
    -                                   opt_backgroundColor,
    -                                   opt_corners,
    -                                   opt_domHelper) {
    -  goog.ui.BaseRoundedPanel.call(this,
    -                                radius,
    -                                borderWidth,
    -                                borderColor,
    -                                opt_backgroundColor,
    -                                opt_corners,
    -                                opt_domHelper);
    -};
    -goog.inherits(goog.ui.CssRoundedPanel, goog.ui.BaseRoundedPanel);
    -
    -
    -/**
    - * This method performs all the necessary DOM manipulation to create the panel.
    - * Overrides {@link goog.ui.Component#decorateInternal}.
    - * @param {Element} element The element to decorate.
    - * @protected
    - * @override
    - */
    -goog.ui.CssRoundedPanel.prototype.decorateInternal = function(element) {
    -  goog.ui.CssRoundedPanel.superClass_.decorateInternal.call(this, element);
    -
    -  // Set the border width and background color, if needed.
    -  this.backgroundElement_.style.border = this.borderWidth_ +
    -      'px solid ' +
    -      this.borderColor_;
    -  if (this.backgroundColor_) {
    -    this.backgroundElement_.style.backgroundColor = this.backgroundColor_;
    -  }
    -
    -  // Set radii of the appropriate rounded corners.
    -  if (this.corners_ == goog.ui.RoundedPanel.Corner.ALL) {
    -    var styleName = this.getStyle_(goog.ui.RoundedPanel.Corner.ALL);
    -    this.backgroundElement_.style[styleName] = this.radius_ + 'px';
    -  } else {
    -    var topLeftRadius =
    -        this.corners_ & goog.ui.RoundedPanel.Corner.TOP_LEFT ?
    -        this.radius_ :
    -        0;
    -    var cornerStyle = this.getStyle_(goog.ui.RoundedPanel.Corner.TOP_LEFT);
    -    this.backgroundElement_.style[cornerStyle] = topLeftRadius + 'px';
    -    var topRightRadius =
    -        this.corners_ & goog.ui.RoundedPanel.Corner.TOP_RIGHT ?
    -        this.radius_ :
    -        0;
    -    cornerStyle = this.getStyle_(goog.ui.RoundedPanel.Corner.TOP_RIGHT);
    -    this.backgroundElement_.style[cornerStyle] = topRightRadius + 'px';
    -    var bottomRightRadius =
    -        this.corners_ & goog.ui.RoundedPanel.Corner.BOTTOM_RIGHT ?
    -        this.radius_ :
    -        0;
    -    cornerStyle = this.getStyle_(goog.ui.RoundedPanel.Corner.BOTTOM_RIGHT);
    -    this.backgroundElement_.style[cornerStyle] = bottomRightRadius + 'px';
    -    var bottomLeftRadius =
    -        this.corners_ & goog.ui.RoundedPanel.Corner.BOTTOM_LEFT ?
    -        this.radius_ :
    -        0;
    -    cornerStyle = this.getStyle_(goog.ui.RoundedPanel.Corner.BOTTOM_LEFT);
    -    this.backgroundElement_.style[cornerStyle] = bottomLeftRadius + 'px';
    -  }
    -};
    -
    -
    -/**
    - * This method returns the CSS style based on the corner of the panel, and the
    - * user-agent.
    - * @param {number} corner The corner whose style name to retrieve.
    - * @private
    - * @return {string} The CSS style based on the specified corner.
    - */
    -goog.ui.CssRoundedPanel.prototype.getStyle_ = function(corner) {
    -  // Determine the proper corner to work with.
    -  var cssCorner, suffixLeft, suffixRight;
    -  if (goog.userAgent.WEBKIT) {
    -    suffixLeft = 'Left';
    -    suffixRight = 'Right';
    -  } else {
    -    suffixLeft = 'left';
    -    suffixRight = 'right';
    -  }
    -  switch (corner) {
    -    case goog.ui.RoundedPanel.Corner.ALL:
    -      cssCorner = '';
    -      break;
    -    case goog.ui.RoundedPanel.Corner.TOP_LEFT:
    -      cssCorner = 'Top' + suffixLeft;
    -      break;
    -    case goog.ui.RoundedPanel.Corner.TOP_RIGHT:
    -      cssCorner = 'Top' + suffixRight;
    -      break;
    -    case goog.ui.RoundedPanel.Corner.BOTTOM_LEFT:
    -      cssCorner = 'Bottom' + suffixLeft;
    -      break;
    -    case goog.ui.RoundedPanel.Corner.BOTTOM_RIGHT:
    -      cssCorner = 'Bottom' + suffixRight;
    -      break;
    -  }
    -
    -  return goog.userAgent.WEBKIT ?
    -      'WebkitBorder' + cssCorner + 'Radius' :
    -      'MozBorderRadius' + cssCorner;
    -};
    -
    -
    -
    -/**
    - * RoundedPanel class that uses goog.graphics to create the rounded corners.
    - * Do not instantiate directly. Instead, call goog.ui.RoundedPanel.create().
    - * @param {number} radius The radius of the rounded corner(s), in pixels.
    - * @param {number} borderWidth The thickness of the border, in pixels.
    - * @param {string} borderColor The border color of the panel.
    - * @param {string=} opt_backgroundColor The background color of the panel.
    - * @param {number=} opt_corners The corners of the panel to be rounded. Any
    - *     corners not specified will be rendered as square corners. Will
    - *     default to all square corners if not specified.
    - * @param {goog.dom.DomHelper=} opt_domHelper The DOM helper object for the
    - *     document we want to render in.
    - * @extends {goog.ui.BaseRoundedPanel}
    - * @constructor
    - * @final
    - */
    -goog.ui.GraphicsRoundedPanel = function(radius,
    -                                        borderWidth,
    -                                        borderColor,
    -                                        opt_backgroundColor,
    -                                        opt_corners,
    -                                        opt_domHelper) {
    -  goog.ui.BaseRoundedPanel.call(this,
    -                                radius,
    -                                borderWidth,
    -                                borderColor,
    -                                opt_backgroundColor,
    -                                opt_corners,
    -                                opt_domHelper);
    -};
    -goog.inherits(goog.ui.GraphicsRoundedPanel, goog.ui.BaseRoundedPanel);
    -
    -
    -/**
    - * A 4-element array containing the circle centers for the arcs in the
    - * bottom-left, top-left, top-right, and bottom-right corners, respectively.
    - * @type {Array<goog.math.Coordinate>}
    - * @private
    - */
    -goog.ui.GraphicsRoundedPanel.prototype.arcCenters_;
    -
    -
    -/**
    - * A 4-element array containing the start coordinates for rendering the arcs
    - * in the bottom-left, top-left, top-right, and bottom-right corners,
    - * respectively.
    - * @type {Array<goog.math.Coordinate>}
    - * @private
    - */
    -goog.ui.GraphicsRoundedPanel.prototype.cornerStarts_;
    -
    -
    -/**
    - * A 4-element array containing the arc end angles for the bottom-left,
    - * top-left, top-right, and bottom-right corners, respectively.
    - * @type {Array<number>}
    - * @private
    - */
    -goog.ui.GraphicsRoundedPanel.prototype.endAngles_;
    -
    -
    -/**
    - * Graphics object for rendering the background.
    - * @type {goog.graphics.AbstractGraphics}
    - * @private
    - */
    -goog.ui.GraphicsRoundedPanel.prototype.graphics_;
    -
    -
    -/**
    - * A 4-element array containing the rounded corner radii for the bottom-left,
    - * top-left, top-right, and bottom-right corners, respectively.
    - * @type {Array<number>}
    - * @private
    - */
    -goog.ui.GraphicsRoundedPanel.prototype.radii_;
    -
    -
    -/**
    - * A 4-element array containing the arc start angles for the bottom-left,
    - * top-left, top-right, and bottom-right corners, respectively.
    - * @type {Array<number>}
    - * @private
    - */
    -goog.ui.GraphicsRoundedPanel.prototype.startAngles_;
    -
    -
    -/**
    - * Thickness constant used as an offset to help determine where to start
    - * rendering.
    - * @type {number}
    - * @private
    - */
    -goog.ui.GraphicsRoundedPanel.BORDER_WIDTH_FACTOR_ = 1 / 2;
    -
    -
    -/**
    - * This method performs all the necessary DOM manipulation to create the panel.
    - * Overrides {@link goog.ui.Component#decorateInternal}.
    - * @param {Element} element The element to decorate.
    - * @protected
    - * @override
    - */
    -goog.ui.GraphicsRoundedPanel.prototype.decorateInternal =
    -    function(element) {
    -  goog.ui.GraphicsRoundedPanel.superClass_.decorateInternal.call(this,
    -                                                                 element);
    -
    -  // Calculate the points and angles for creating the rounded corners. Then
    -  // instantiate a Graphics object for drawing purposes.
    -  var elementSize = goog.style.getSize(this.getElement());
    -  this.calculateArcParameters_(elementSize);
    -  this.graphics_ = goog.graphics.createGraphics(
    -      /** @type {number} */ (elementSize.width),
    -      /** @type {number} */ (elementSize.height),
    -      /** @type {number} */ (elementSize.width),
    -      /** @type {number} */ (elementSize.height),
    -      this.getDomHelper());
    -  this.graphics_.createDom();
    -
    -  // Create the path, starting from the bottom-right corner, moving clockwise.
    -  // End with the top-right corner.
    -  var path = new goog.graphics.Path();
    -  for (var i = 0; i < 4; i++) {
    -    if (this.radii_[i]) {
    -      // If radius > 0, draw an arc, moving to the first point and drawing
    -      // a line to the others.
    -      var cx = this.arcCenters_[i].x;
    -      var cy = this.arcCenters_[i].y;
    -      var rx = this.radii_[i];
    -      var ry = rx;
    -      var fromAngle = this.startAngles_[i];
    -      var extent = this.endAngles_[i] - fromAngle;
    -      var startX = cx + goog.math.angleDx(fromAngle, rx);
    -      var startY = cy + goog.math.angleDy(fromAngle, ry);
    -      if (i > 0) {
    -        var currentPoint = path.getCurrentPoint();
    -        if (!currentPoint || startX != currentPoint[0] ||
    -            startY != currentPoint[1]) {
    -          path.lineTo(startX, startY);
    -        }
    -      } else {
    -        path.moveTo(startX, startY);
    -      }
    -      path.arcTo(rx, ry, fromAngle, extent);
    -    } else if (i == 0) {
    -      // If we're just starting out (ie. i == 0), move to the starting point.
    -      path.moveTo(this.cornerStarts_[i].x,
    -                  this.cornerStarts_[i].y);
    -    } else {
    -      // Otherwise, draw a line to the starting point.
    -      path.lineTo(this.cornerStarts_[i].x,
    -                  this.cornerStarts_[i].y);
    -    }
    -  }
    -
    -  // Close the path, create a stroke object, and fill the enclosed area, if
    -  // needed. Then render the path.
    -  path.close();
    -  var stroke = this.borderWidth_ ?
    -      new goog.graphics.Stroke(this.borderWidth_, this.borderColor_) :
    -      null;
    -  var fill = this.backgroundColor_ ?
    -      new goog.graphics.SolidFill(this.backgroundColor_, 1) :
    -      null;
    -  this.graphics_.drawPath(path, stroke, fill);
    -  this.graphics_.render(this.backgroundElement_);
    -};
    -
    -
    -/** @override */
    -goog.ui.GraphicsRoundedPanel.prototype.disposeInternal = function() {
    -  goog.ui.GraphicsRoundedPanel.superClass_.disposeInternal.call(this);
    -  this.graphics_.dispose();
    -  delete this.graphics_;
    -  delete this.radii_;
    -  delete this.cornerStarts_;
    -  delete this.arcCenters_;
    -  delete this.startAngles_;
    -  delete this.endAngles_;
    -};
    -
    -
    -/**
    - * Calculates the start coordinates, circle centers, and angles, for the rounded
    - * corners at each corner of the panel.
    - * @param {goog.math.Size} elementSize The size of element_.
    - * @private
    - */
    -goog.ui.GraphicsRoundedPanel.prototype.calculateArcParameters_ =
    -    function(elementSize) {
    -  // Initialize the arrays containing the key points and angles.
    -  this.radii_ = [];
    -  this.cornerStarts_ = [];
    -  this.arcCenters_ = [];
    -  this.startAngles_ = [];
    -  this.endAngles_ = [];
    -
    -  // Set the start points, circle centers, and angles for the bottom-right,
    -  // bottom-left, top-left and top-right corners, in that order.
    -  var angleInterval = 90;
    -  var borderWidthOffset = this.borderWidth_ *
    -      goog.ui.GraphicsRoundedPanel.BORDER_WIDTH_FACTOR_;
    -  var radius, xStart, yStart, xCenter, yCenter, startAngle, endAngle;
    -  for (var i = 0; i < 4; i++) {
    -    var corner = Math.pow(2, i);  // Determines which corner we're dealing with.
    -    var isLeft = corner & goog.ui.RoundedPanel.Corner.LEFT;
    -    var isTop = corner & goog.ui.RoundedPanel.Corner.TOP;
    -
    -    // Calculate the radius and the start coordinates.
    -    radius = corner & this.corners_ ? this.radius_ : 0;
    -    switch (corner) {
    -      case goog.ui.RoundedPanel.Corner.BOTTOM_LEFT:
    -        xStart = borderWidthOffset + radius;
    -        yStart = elementSize.height - borderWidthOffset;
    -        break;
    -      case goog.ui.RoundedPanel.Corner.TOP_LEFT:
    -        xStart = borderWidthOffset;
    -        yStart = radius + borderWidthOffset;
    -        break;
    -      case goog.ui.RoundedPanel.Corner.TOP_RIGHT:
    -        xStart = elementSize.width - radius - borderWidthOffset;
    -        yStart = borderWidthOffset;
    -        break;
    -      case goog.ui.RoundedPanel.Corner.BOTTOM_RIGHT:
    -        xStart = elementSize.width - borderWidthOffset;
    -        yStart = elementSize.height - radius - borderWidthOffset;
    -        break;
    -    }
    -
    -    // Calculate the circle centers and start/end angles.
    -    xCenter = isLeft ?
    -        radius + borderWidthOffset :
    -        elementSize.width - radius - borderWidthOffset;
    -    yCenter = isTop ?
    -        radius + borderWidthOffset :
    -        elementSize.height - radius - borderWidthOffset;
    -    startAngle = angleInterval * i;
    -    endAngle = startAngle + angleInterval;
    -
    -    // Append the radius, angles, and coordinates to their arrays.
    -    this.radii_[i] = radius;
    -    this.cornerStarts_[i] = new goog.math.Coordinate(xStart, yStart);
    -    this.arcCenters_[i] = new goog.math.Coordinate(xCenter, yCenter);
    -    this.startAngles_[i] = startAngle;
    -    this.endAngles_[i] = endAngle;
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/roundedpanel_test.html b/src/database/third_party/closure-library/closure/goog/ui/roundedpanel_test.html
    deleted file mode 100644
    index daa69801226..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/roundedpanel_test.html
    +++ /dev/null
    @@ -1,26 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -
    -  Unit test file for goog.ui.RoundedPanel component
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.RoundedPanel
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.RoundedPanelTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/roundedpanel_test.js b/src/database/third_party/closure-library/closure/goog/ui/roundedpanel_test.js
    deleted file mode 100644
    index ae415478826..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/roundedpanel_test.js
    +++ /dev/null
    @@ -1,54 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.RoundedPanelTest');
    -goog.setTestOnly('goog.ui.RoundedPanelTest');
    -
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.CssRoundedPanel');
    -goog.require('goog.ui.GraphicsRoundedPanel');
    -goog.require('goog.ui.RoundedPanel');
    -goog.require('goog.userAgent');
    -
    -
    -/**
    - * Tests goog.ui.RoundedPanel.create(), ensuring that the proper instance is
    - * created based on user-agent
    - */
    -function testRoundedPanelCreate() {
    -  var rcp = goog.ui.RoundedPanel.create(15,
    -                                        5,
    -                                        '#cccccc',
    -                                        '#cccccc',
    -                                        goog.ui.RoundedPanel.Corner.ALL);
    -
    -  if (goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher('1.9a')) {
    -    assertTrue('For Firefox 3.0+ (uses Gecko 1.9+), an instance of ' +
    -        'goog.ui.CssRoundedPanel should be returned.',
    -        rcp instanceof goog.ui.CssRoundedPanel);
    -  } else if (goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher('500')) {
    -    assertTrue('For Safari 3.0+, an instance of goog.ui.CssRoundedPanel ' +
    -        'should be returned.', rcp instanceof goog.ui.CssRoundedPanel);
    -  } else if (goog.userAgent.GECKO ||
    -             goog.userAgent.IE ||
    -             goog.userAgent.OPERA ||
    -             goog.userAgent.WEBKIT) {
    -    assertTrue('For Gecko 1.8- (ex. Firefox 2.0-, Camino 1.5-, etc.), ' +
    -        'IE, Opera, and Safari 2.0-, an instance of ' +
    -        'goog.ui.GraphicsRoundedPanel should be returned.',
    -        rcp instanceof goog.ui.GraphicsRoundedPanel);
    -  } else {
    -    assertNull('For non-supported user-agents, null is returned.', rcp);
    -  }
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/roundedtabrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/roundedtabrenderer.js
    deleted file mode 100644
    index c270cd418b2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/roundedtabrenderer.js
    +++ /dev/null
    @@ -1,198 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Rounded corner tab renderer for {@link goog.ui.Tab}s.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.RoundedTabRenderer');
    -
    -goog.require('goog.dom');
    -goog.require('goog.ui.Tab');
    -goog.require('goog.ui.TabBar');
    -goog.require('goog.ui.TabRenderer');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * Rounded corner tab renderer for {@link goog.ui.Tab}s.
    - * @constructor
    - * @extends {goog.ui.TabRenderer}
    - * @final
    - */
    -goog.ui.RoundedTabRenderer = function() {
    -  goog.ui.TabRenderer.call(this);
    -};
    -goog.inherits(goog.ui.RoundedTabRenderer, goog.ui.TabRenderer);
    -goog.addSingletonGetter(goog.ui.RoundedTabRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.RoundedTabRenderer.CSS_CLASS = goog.getCssName('goog-rounded-tab');
    -
    -
    -/**
    - * Returns the CSS class name to be applied to the root element of all tabs
    - * rendered or decorated using this renderer.
    - * @return {string} Renderer-specific CSS class name.
    - * @override
    - */
    -goog.ui.RoundedTabRenderer.prototype.getCssClass = function() {
    -  return goog.ui.RoundedTabRenderer.CSS_CLASS;
    -};
    -
    -
    -/**
    - * Creates the tab's DOM structure, based on the containing tab bar's location
    - * relative to tab contents.  For example, the DOM for a tab in a tab bar
    - * located above tab contents would look like this:
    - * <pre>
    - *   <div class="goog-rounded-tab" title="...">
    - *     <table class="goog-rounded-tab-table">
    - *       <tbody>
    - *         <tr>
    - *           <td nowrap>
    - *             <div class="goog-rounded-tab-outer-edge"></div>
    - *             <div class="goog-rounded-tab-inner-edge"></div>
    - *           </td>
    - *         </tr>
    - *         <tr>
    - *           <td nowrap>
    - *             <div class="goog-rounded-tab-caption">Hello, world</div>
    - *           </td>
    - *         </tr>
    - *       </tbody>
    - *     </table>
    - *   </div>
    - * </pre>
    - * @param {goog.ui.Control} tab Tab to render.
    - * @return {Element} Root element for the tab.
    - * @override
    - */
    -goog.ui.RoundedTabRenderer.prototype.createDom = function(tab) {
    -  return this.decorate(tab,
    -      goog.ui.RoundedTabRenderer.superClass_.createDom.call(this, tab));
    -};
    -
    -
    -/**
    - * Decorates the element with the tab.  Overrides the superclass implementation
    - * by wrapping the tab's content in a table that implements rounded corners.
    - * @param {goog.ui.Control} tab Tab to decorate the element.
    - * @param {Element} element Element to decorate.
    - * @return {Element} Decorated element.
    - * @override
    - */
    -goog.ui.RoundedTabRenderer.prototype.decorate = function(tab, element) {
    -  var tabBar = tab.getParent();
    -
    -  if (!this.getContentElement(element)) {
    -    // The element to be decorated doesn't appear to have the full tab DOM,
    -    // so we have to create it.
    -    element.appendChild(this.createTab(tab.getDomHelper(), element.childNodes,
    -        tabBar.getLocation()));
    -  }
    -
    -  return goog.ui.RoundedTabRenderer.superClass_.decorate.call(this, tab,
    -      element);
    -};
    -
    -
    -/**
    - * Creates a table implementing a rounded corner tab.
    - * @param {goog.dom.DomHelper} dom DOM helper to use for element construction.
    - * @param {goog.ui.ControlContent} caption Text caption or DOM structure
    - *     to display as the tab's caption.
    - * @param {goog.ui.TabBar.Location} location Tab bar location relative to the
    - *     tab contents.
    - * @return {!Element} Table implementing a rounded corner tab.
    - * @protected
    - */
    -goog.ui.RoundedTabRenderer.prototype.createTab = function(dom, caption,
    -    location) {
    -  var rows = [];
    -
    -  if (location != goog.ui.TabBar.Location.BOTTOM) {
    -    // This is a left, right, or top tab, so it needs a rounded top edge.
    -    rows.push(this.createEdge(dom, /* isTopEdge */ true));
    -  }
    -  rows.push(this.createCaption(dom, caption));
    -  if (location != goog.ui.TabBar.Location.TOP) {
    -    // This is a left, right, or bottom tab, so it needs a rounded bottom edge.
    -    rows.push(this.createEdge(dom, /* isTopEdge */ false));
    -  }
    -
    -  return dom.createDom('table', {
    -    'cellPadding': 0,
    -    'cellSpacing': 0,
    -    'className': goog.getCssName(this.getStructuralCssClass(), 'table')
    -  }, dom.createDom('tbody', null, rows));
    -};
    -
    -
    -/**
    - * Creates a table row implementing the tab caption.
    - * @param {goog.dom.DomHelper} dom DOM helper to use for element construction.
    - * @param {goog.ui.ControlContent} caption Text caption or DOM structure
    - *     to display as the tab's caption.
    - * @return {!Element} Tab caption table row.
    - * @protected
    - */
    -goog.ui.RoundedTabRenderer.prototype.createCaption = function(dom, caption) {
    -  var baseClass = this.getStructuralCssClass();
    -  return dom.createDom('tr', null,
    -      dom.createDom('td', {'noWrap': true},
    -          dom.createDom('div', goog.getCssName(baseClass, 'caption'),
    -              caption)));
    -};
    -
    -
    -/**
    - * Creates a table row implementing a rounded tab edge.
    - * @param {goog.dom.DomHelper} dom DOM helper to use for element construction.
    - * @param {boolean} isTopEdge Whether to create a top or bottom edge.
    - * @return {!Element} Rounded tab edge table row.
    - * @protected
    - */
    -goog.ui.RoundedTabRenderer.prototype.createEdge = function(dom, isTopEdge) {
    -  var baseClass = this.getStructuralCssClass();
    -  var inner = dom.createDom('div', goog.getCssName(baseClass, 'inner-edge'));
    -  var outer = dom.createDom('div', goog.getCssName(baseClass, 'outer-edge'));
    -  return dom.createDom('tr', null,
    -      dom.createDom('td', {'noWrap': true},
    -          isTopEdge ? [outer, inner] : [inner, outer]));
    -};
    -
    -
    -/** @override */
    -goog.ui.RoundedTabRenderer.prototype.getContentElement = function(element) {
    -  var baseClass = this.getStructuralCssClass();
    -  return element && goog.dom.getElementsByTagNameAndClass(
    -      'div', goog.getCssName(baseClass, 'caption'), element)[0];
    -};
    -
    -
    -// Register a decorator factory function for goog.ui.Tabs using the rounded
    -// tab renderer.
    -goog.ui.registry.setDecoratorByClassName(goog.ui.RoundedTabRenderer.CSS_CLASS,
    -    function() {
    -      return new goog.ui.Tab(null, goog.ui.RoundedTabRenderer.getInstance());
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/scrollfloater.js b/src/database/third_party/closure-library/closure/goog/ui/scrollfloater.js
    deleted file mode 100644
    index 3e7cafa4177..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/scrollfloater.js
    +++ /dev/null
    @@ -1,636 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview  Class for making an element detach and float to remain visible
    - * even when the viewport has been scrolled.
    - * <p>
    - * The element remains at its normal position in the layout until scrolling
    - * would cause its top edge to scroll off the top of the viewport; at that
    - * point, the element is replaced with an invisible placeholder (to keep the
    - * layout stable), reattached in the dom tree to a new parent (the body element
    - * by default), and set to "fixed" positioning (emulated for IE < 7) so that it
    - * remains at its original X position while staying fixed to the top of the
    - * viewport in the Y dimension.
    - * <p>
    - * When the window is scrolled up past the point where the original element
    - * would be fully visible again, the element snaps back into place, replacing
    - * the placeholder.
    - *
    - * @see ../demos/scrollfloater.html
    - *
    - * Adapted from http://go/elementfloater.js
    - */
    -
    -
    -goog.provide('goog.ui.ScrollFloater');
    -goog.provide('goog.ui.ScrollFloater.EventType');
    -
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events.EventType');
    -goog.require('goog.style');
    -goog.require('goog.ui.Component');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * Creates a ScrollFloater; see file overview for details.
    - *
    - * @param {Element=} opt_parentElement Where to attach the element when it's
    - *     floating.  Default is the document body.  If the floating element
    - *     contains form inputs, it will be necessary to attach it to the
    - *     corresponding form element, or to an element in the DOM subtree under
    - *     the form element.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @constructor
    - * @extends {goog.ui.Component}
    - */
    -goog.ui.ScrollFloater = function(opt_parentElement, opt_domHelper) {
    -  // If a parentElement is supplied, we want to use its domHelper,
    -  // ignoring the caller-supplied one.
    -  var domHelper = opt_parentElement ?
    -      goog.dom.getDomHelper(opt_parentElement) : opt_domHelper;
    -
    -  goog.ui.ScrollFloater.base(this, 'constructor', domHelper);
    -
    -  /**
    -   * The element to which the scroll-floated element will be attached
    -   * when it is floating.
    -   * @type {Element}
    -   * @private
    -   */
    -  this.parentElement_ =
    -      opt_parentElement || this.getDomHelper().getDocument().body;
    -
    -  /**
    -   * The original styles applied to the element before it began floating;
    -   * used to restore those styles when the element stops floating.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.originalStyles_ = {};
    -
    -  /**
    -   * A vertical offset from which to start floating the element.  This is
    -   * useful in cases when there are 'position:fixed' elements covering up
    -   * part of the viewport.
    -   * @type {number}
    -   * @private
    -   */
    -  this.viewportTopOffset_ = 0;
    -
    -  /**
    -   * An element used to define the boundaries within which the floater can
    -   * be positioned.
    -   * @type {Element}
    -   * @private
    -   */
    -  this.containerElement_ = null;
    -
    -  /**
    -   * Container element's bounding rectangle.
    -   * @type {goog.math.Rect}
    -   * @private
    -   */
    -  this.containerBounds_ = null;
    -
    -  /**
    -   * Element's original bounding rectangle.
    -   * @type {goog.math.Rect}
    -   * @private
    -   */
    -  this.originalBounds_ = null;
    -
    -  /**
    -   * Element's top offset when it's not floated or pinned.
    -   * @type {number}
    -   * @private
    -   */
    -  this.originalTopOffset_ = 0;
    -
    -  /**
    -   * The placeholder element dropped in to hold the layout for
    -   * the floated element.
    -   * @type {Element}
    -   * @private
    -   */
    -  this.placeholder_ = null;
    -
    -  /**
    -   * Whether scrolling is enabled for this element; true by default.
    -   * The {@link #setScrollingEnabled} method can be used to change this value.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.scrollingEnabled_ = true;
    -
    -  /**
    -   * A flag indicating whether this instance is currently pinned to the bottom
    -   * of the container element.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.pinned_ = false;
    -
    -  /**
    -   * A flag indicating whether this instance is currently floating.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.floating_ = false;
    -};
    -goog.inherits(goog.ui.ScrollFloater, goog.ui.Component);
    -
    -
    -/**
    - * Events dispatched by this component.
    - * @enum {string}
    - */
    -goog.ui.ScrollFloater.EventType = {
    -  /**
    -   * Dispatched when the component starts floating. The event is
    -   * cancellable.
    -   */
    -  FLOAT: 'float',
    -
    -  /**
    -   * Dispatched when the component returns to its original state.
    -   * The event is cancellable.
    -   */
    -  DOCK: 'dock',
    -
    -  /**
    -   * Dispatched when the component gets pinned to the bottom of the
    -   * container element.  This event is cancellable.
    -   */
    -  PIN: 'pin'
    -};
    -
    -
    -/**
    - * The element can float at different positions on the page.
    - * @enum {number}
    - * @private
    - */
    -goog.ui.ScrollFloater.FloatMode_ = {
    -  TOP: 0,
    -  BOTTOM: 1
    -};
    -
    -
    -/**
    - * The style properties which are stored when we float an element, so they
    - * can be restored when it 'docks' again.
    - * @type {Array<string>}
    - * @private
    - */
    -goog.ui.ScrollFloater.STORED_STYLE_PROPS_ = [
    -  'position', 'top', 'left', 'width', 'cssFloat'];
    -
    -
    -/**
    - * The style elements managed for the placeholder object.
    - * @type {Array<string>}
    - * @private
    - */
    -goog.ui.ScrollFloater.PLACEHOLDER_STYLE_PROPS_ = [
    -  'position', 'top', 'left', 'display', 'cssFloat',
    -  'marginTop', 'marginLeft', 'marginRight', 'marginBottom'];
    -
    -
    -/**
    - * The class name applied to the floating element.
    - * @type {string}
    - * @private
    - */
    -goog.ui.ScrollFloater.CSS_CLASS_ = goog.getCssName('goog-scrollfloater');
    -
    -
    -/**
    - * Delegates dom creation to superclass, then constructs and
    - * decorates required DOM elements.
    - * @override
    - */
    -goog.ui.ScrollFloater.prototype.createDom = function() {
    -  goog.ui.ScrollFloater.base(this, 'createDom');
    -
    -  this.decorateInternal(this.getElement());
    -};
    -
    -
    -/**
    - * Decorates the floated element with the standard ScrollFloater CSS class.
    - * @param {Element} element The element to decorate.
    - * @override
    - */
    -goog.ui.ScrollFloater.prototype.decorateInternal = function(element) {
    -  goog.ui.ScrollFloater.base(this, 'decorateInternal', element);
    -  goog.asserts.assert(element);
    -  goog.dom.classlist.add(element, goog.ui.ScrollFloater.CSS_CLASS_);
    -};
    -
    -
    -/** @override */
    -goog.ui.ScrollFloater.prototype.enterDocument = function() {
    -  goog.ui.ScrollFloater.base(this, 'enterDocument');
    -
    -  if (!this.placeholder_) {
    -    this.placeholder_ =
    -        this.getDomHelper().createDom('div', {'style': 'visibility:hidden'});
    -  }
    -
    -  this.update();
    -
    -  this.setScrollingEnabled(this.scrollingEnabled_);
    -  var win = this.getDomHelper().getWindow();
    -  this.getHandler().
    -      listen(win, goog.events.EventType.SCROLL, this.handleScroll_).
    -      listen(win, goog.events.EventType.RESIZE, this.update);
    -};
    -
    -
    -/**
    - * Forces the component to update the cached element positions and sizes and
    - * to re-evaluate whether the the component should be docked, floated or
    - * pinned.
    - */
    -goog.ui.ScrollFloater.prototype.update = function() {
    -  if (!this.isInDocument()) {
    -    return;
    -  }
    -
    -  // These values can only be calculated when the element is in its original
    -  // state, so we dock first, and then re-evaluate.
    -  this.dock_();
    -  if (this.containerElement_) {
    -    this.containerBounds_ = goog.style.getBounds(this.containerElement_);
    -  }
    -  this.originalBounds_ = goog.style.getBounds(this.getElement());
    -  this.originalTopOffset_ = goog.style.getPageOffset(this.getElement()).y;
    -  this.handleScroll_();
    -};
    -
    -
    -/** @override */
    -goog.ui.ScrollFloater.prototype.disposeInternal = function() {
    -  goog.ui.ScrollFloater.base(this, 'disposeInternal');
    -
    -  this.placeholder_ = null;
    -};
    -
    -
    -/**
    - * Sets whether the element should be floated if it scrolls out of view.
    - * @param {boolean} enable Whether floating is enabled for this element.
    - */
    -goog.ui.ScrollFloater.prototype.setScrollingEnabled = function(enable) {
    -  this.scrollingEnabled_ = enable;
    -
    -  if (enable) {
    -    this.applyIeBgHack_();
    -    this.handleScroll_();
    -  } else {
    -    this.dock_();
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the component is enabled for scroll-floating.
    - */
    -goog.ui.ScrollFloater.prototype.isScrollingEnabled = function() {
    -  return this.scrollingEnabled_;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the component is currently scroll-floating.
    - */
    -goog.ui.ScrollFloater.prototype.isFloating = function() {
    -  return this.floating_;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the component is currently pinned to the bottom
    - *     of the container.
    - */
    -goog.ui.ScrollFloater.prototype.isPinned = function() {
    -  return this.pinned_;
    -};
    -
    -
    -/**
    - * @param {number} offset A vertical offset from the top of the viewport, from
    - *    which to start floating the element. Default is 0. This is useful in cases
    - *    when there are 'position:fixed' elements covering up part of the viewport.
    - */
    -goog.ui.ScrollFloater.prototype.setViewportTopOffset = function(offset) {
    -  this.viewportTopOffset_ = offset;
    -  this.update();
    -};
    -
    -
    -/**
    - * @param {Element} container An element used to define the boundaries within
    - *     which the floater can be positioned. If not specified, scrolling the page
    - *     down far enough may result in the floated element extending past the
    - *     containing element as it is being scrolled out of the viewport. In some
    - *     cases, such as a list with a sticky header, this may be undesirable. If
    - *     the container element is specified and the floated element extends past
    - *     the bottom of the container, the element will be pinned to the bottom of
    - *     the container.
    - */
    -goog.ui.ScrollFloater.prototype.setContainerElement = function(container) {
    -  this.containerElement_ = container;
    -  this.update();
    -};
    -
    -
    -/**
    - * When a scroll event occurs, compares the element's position to the current
    - * document scroll position, and stops or starts floating behavior if needed.
    - * @param {goog.events.Event=} opt_e The event, which is ignored.
    - * @private
    - */
    -goog.ui.ScrollFloater.prototype.handleScroll_ = function(opt_e) {
    -  if (this.scrollingEnabled_) {
    -    var scrollTop = this.getDomHelper().getDocumentScroll().y;
    -
    -    if (this.originalBounds_.top - scrollTop >= this.viewportTopOffset_) {
    -      this.dock_();
    -      return;
    -    }
    -
    -    var effectiveElementHeight = this.originalBounds_.height +
    -        this.viewportTopOffset_;
    -
    -    // If the element extends past the container, we need to pin it instead.
    -    if (this.containerElement_) {
    -      var containerBottom = this.containerBounds_.top +
    -          this.containerBounds_.height;
    -
    -      if (scrollTop > containerBottom - effectiveElementHeight) {
    -        this.pin_();
    -        return;
    -      }
    -    }
    -
    -    var windowHeight = this.getDomHelper().getViewportSize().height;
    -
    -    // If the element is shorter than the window or the user uses IE < 7,
    -    // float it at the top.
    -    if (this.needsIePositionHack_() || effectiveElementHeight < windowHeight) {
    -      this.float_(goog.ui.ScrollFloater.FloatMode_.TOP);
    -      return;
    -    }
    -
    -    // If the element is taller than the window and is extending past the
    -    // bottom, allow it scroll with the page until the bottom of the element is
    -    // fully visible.
    -    if (this.originalBounds_.height + this.originalTopOffset_ >
    -        windowHeight + scrollTop) {
    -      this.dock_();
    -    } else {
    -      // Pin the element to the bottom of the page since the user has scrolled
    -      // past it.
    -      this.float_(goog.ui.ScrollFloater.FloatMode_.BOTTOM);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Pins the element to the bottom of the container, making as much of the
    - * element visible as possible without extending past it.
    - * @private
    - */
    -goog.ui.ScrollFloater.prototype.pin_ = function() {
    -  if (this.floating_ && !this.dock_()) {
    -    return;
    -  }
    -
    -  // Ignore if the component is pinned or the PIN event is cancelled.
    -  if (this.pinned_ ||
    -      !this.dispatchEvent(goog.ui.ScrollFloater.EventType.PIN)) {
    -    return;
    -  }
    -
    -  var elem = this.getElement();
    -
    -  this.storeOriginalStyles_();
    -
    -  elem.style.position = 'relative';
    -  elem.style.top = this.containerBounds_.height - this.originalBounds_.height -
    -      this.originalBounds_.top + this.containerBounds_.top + 'px';
    -
    -  this.pinned_ = true;
    -};
    -
    -
    -/**
    - * Begins floating behavior, making the element position:fixed (or IE hacked
    - * equivalent) and inserting a placeholder where it used to be to keep the
    - * layout from shifting around. For IE < 7 users, we only support floating at
    - * the top.
    - * @param {goog.ui.ScrollFloater.FloatMode_} floatMode The position at which we
    - *     should float.
    - * @private
    - */
    -goog.ui.ScrollFloater.prototype.float_ = function(floatMode) {
    -  var isTop = floatMode == goog.ui.ScrollFloater.FloatMode_.TOP;
    -  if (this.pinned_ && !this.dock_()) {
    -    return;
    -  }
    -
    -  // Ignore if the component is floating or the FLOAT event is cancelled.
    -  if (this.floating_ ||
    -      !this.dispatchEvent(goog.ui.ScrollFloater.EventType.FLOAT)) {
    -    return;
    -  }
    -
    -  var elem = this.getElement();
    -  var doc = this.getDomHelper().getDocument();
    -
    -  // Read properties of element before modifying it.
    -  var originalLeft_ = goog.style.getPageOffsetLeft(elem);
    -  var originalWidth_ = goog.style.getContentBoxSize(elem).width;
    -
    -  this.storeOriginalStyles_();
    -
    -  goog.style.setSize(this.placeholder_, elem.offsetWidth, elem.offsetHeight);
    -
    -  // Make element float.
    -  goog.style.setStyle(elem, {
    -    'left': originalLeft_ + 'px',
    -    'width': originalWidth_ + 'px',
    -    'cssFloat': 'none'
    -  });
    -
    -  // If parents are the same, avoid detaching and reattaching elem.
    -  // This prevents Flash embeds from being reloaded, for example.
    -  if (elem.parentNode == this.parentElement_) {
    -    elem.parentNode.insertBefore(this.placeholder_, elem);
    -  } else {
    -    elem.parentNode.replaceChild(this.placeholder_, elem);
    -    this.parentElement_.appendChild(elem);
    -  }
    -
    -  // Versions of IE below 7-in-standards-mode don't handle 'position: fixed',
    -  // so we must emulate it using an IE-specific idiom for JS-based calculated
    -  // style values. These users will only ever float at the top (bottom floating
    -  // not supported.) Also checked in handleScroll_.
    -  if (this.needsIePositionHack_()) {
    -    elem.style.position = 'absolute';
    -    elem.style.setExpression('top',
    -        'document.compatMode=="CSS1Compat"?' +
    -        'documentElement.scrollTop:document.body.scrollTop');
    -  } else {
    -    elem.style.position = 'fixed';
    -    if (isTop) {
    -      elem.style.top = this.viewportTopOffset_ + 'px';
    -      elem.style.bottom = 'auto';
    -    } else {
    -      elem.style.top = 'auto';
    -      elem.style.bottom = 0;
    -    }
    -  }
    -
    -  this.floating_ = true;
    -};
    -
    -
    -/**
    - * Stops floating behavior, returning element to its original state.
    - * @return {boolean} True if the the element has been docked.  False if the
    - *     element is already docked or the event was cancelled.
    - * @private
    - */
    -goog.ui.ScrollFloater.prototype.dock_ = function() {
    -  // Ignore if the component is docked or the DOCK event is cancelled.
    -  if (!(this.floating_ || this.pinned_) ||
    -      !this.dispatchEvent(goog.ui.ScrollFloater.EventType.DOCK)) {
    -    return false;
    -  }
    -
    -  var elem = this.getElement();
    -
    -  if (this.floating_) {
    -    this.restoreOriginalStyles_();
    -
    -    if (this.needsIePositionHack_()) {
    -      elem.style.removeExpression('top');
    -    }
    -
    -    // If placeholder_ was inserted and didn't replace elem then elem has
    -    // the right parent already, no need to replace (which removes elem before
    -    // inserting it).
    -    if (this.placeholder_.parentNode == this.parentElement_) {
    -      this.placeholder_.parentNode.removeChild(this.placeholder_);
    -    } else {
    -      this.placeholder_.parentNode.replaceChild(elem, this.placeholder_);
    -    }
    -  }
    -
    -  if (this.pinned_) {
    -    this.restoreOriginalStyles_();
    -  }
    -
    -  this.floating_ = this.pinned_ = false;
    -
    -  return true;
    -};
    -
    -
    -/**
    - * @private
    - */
    -goog.ui.ScrollFloater.prototype.storeOriginalStyles_ = function() {
    -  var elem = this.getElement();
    -  this.originalStyles_ = {};
    -
    -  // Store styles while not floating so we can restore them when the
    -  // element stops floating.
    -  goog.array.forEach(goog.ui.ScrollFloater.STORED_STYLE_PROPS_,
    -                     function(property) {
    -                       this.originalStyles_[property] = elem.style[property];
    -                     },
    -                     this);
    -
    -  // Copy relevant styles to placeholder so it will be layed out the same
    -  // as the element that's about to be floated.
    -  goog.array.forEach(goog.ui.ScrollFloater.PLACEHOLDER_STYLE_PROPS_,
    -                     function(property) {
    -                       this.placeholder_.style[property] =
    -                           elem.style[property] ||
    -                               goog.style.getCascadedStyle(elem, property) ||
    -                               goog.style.getComputedStyle(elem, property);
    -                     },
    -                     this);
    -};
    -
    -
    -/**
    - * @private
    - */
    -goog.ui.ScrollFloater.prototype.restoreOriginalStyles_ = function() {
    -  var elem = this.getElement();
    -  for (var prop in this.originalStyles_) {
    -    elem.style[prop] = this.originalStyles_[prop];
    -  }
    -};
    -
    -
    -/**
    - * Determines whether we need to apply the position hack to emulated position:
    - * fixed on this browser.
    - * @return {boolean} Whether the current browser needs the position hack.
    - * @private
    - */
    -goog.ui.ScrollFloater.prototype.needsIePositionHack_ = function() {
    -  return goog.userAgent.IE &&
    -      !(goog.userAgent.isVersionOrHigher('7') &&
    -          this.getDomHelper().isCss1CompatMode());
    -};
    -
    -
    -/**
    - * Sets some magic CSS properties that make float-scrolling work smoothly
    - * in IE6 (and IE7 in quirks mode). Without this hack, the floating element
    - * will appear jumpy when you scroll the document. This involves modifying
    - * the background of the HTML element (or BODY in quirks mode). If there's
    - * already a background image in use this is not required.
    - * For further reading, see
    - * http://annevankesteren.nl/2005/01/position-fixed-in-ie
    - * @private
    - */
    -goog.ui.ScrollFloater.prototype.applyIeBgHack_ = function() {
    -  if (this.needsIePositionHack_()) {
    -    var doc = this.getDomHelper().getDocument();
    -    var topLevelElement = goog.style.getClientViewportElement(doc);
    -
    -    if (topLevelElement.currentStyle.backgroundImage == 'none') {
    -      // Using an https URL if the current windowbp is https avoids an IE
    -      // "This page contains a mix of secure and nonsecure items" warning.
    -      topLevelElement.style.backgroundImage =
    -          this.getDomHelper().getWindow().location.protocol == 'https:' ?
    -              'url(https:///)' : 'url(about:blank)';
    -      topLevelElement.style.backgroundAttachment = 'fixed';
    -    }
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/scrollfloater_test.html b/src/database/third_party/closure-library/closure/goog/ui/scrollfloater_test.html
    deleted file mode 100644
    index c87036f925a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/scrollfloater_test.html
    +++ /dev/null
    @@ -1,29 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.ScrollFloater
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.ScrollFloaterTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="container">
    -   <div id="floater">
    -    Content to be scroll-floated.
    -   </div>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/scrollfloater_test.js b/src/database/third_party/closure-library/closure/goog/ui/scrollfloater_test.js
    deleted file mode 100644
    index f1ff6b84314..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/scrollfloater_test.js
    +++ /dev/null
    @@ -1,136 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.ScrollFloaterTest');
    -goog.setTestOnly('goog.ui.ScrollFloaterTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.style');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.ScrollFloater');
    -
    -function testScrollFloater() {
    -  var scrollFloater = new goog.ui.ScrollFloater();
    -  var floater = goog.dom.getElement('floater');
    -  scrollFloater.decorate(floater);
    -
    -  assertTrue('Default state is enabled', scrollFloater.isScrollingEnabled());
    -  assertFalse('On unscrolled page should not be floating',
    -              scrollFloater.isFloating());
    -
    -  scrollFloater.setScrollingEnabled(false);
    -
    -  assertFalse('We can disable the floater',
    -              scrollFloater.isScrollingEnabled());
    -  scrollFloater.dispose();
    -}
    -
    -function testScrollFloaterEvents() {
    -  var scrollFloater = new goog.ui.ScrollFloater();
    -  var floater = goog.dom.getElement('floater');
    -  scrollFloater.setContainerElement(goog.dom.getElement('container'));
    -  scrollFloater.decorate(floater);
    -
    -  var floatWasCalled = false;
    -  var callRecorder = function() { floatWasCalled = true; };
    -  goog.events.listen(
    -      scrollFloater, goog.ui.ScrollFloater.EventType.FLOAT, callRecorder);
    -  scrollFloater.float_(goog.ui.ScrollFloater.FloatMode_.TOP);
    -  assertTrue('FLOAT event was called', floatWasCalled);
    -  assertTrue('Should be floating', scrollFloater.isFloating());
    -  assertFalse('Should not be pinned', scrollFloater.isPinned());
    -
    -  var dockWasCalled = false;
    -  callRecorder = function() { dockWasCalled = true; };
    -  goog.events.listen(
    -      scrollFloater, goog.ui.ScrollFloater.EventType.DOCK, callRecorder);
    -  scrollFloater.dock_();
    -  assertTrue('DOCK event was called', dockWasCalled);
    -  assertFalse('Should not be floating', scrollFloater.isFloating());
    -  assertFalse('Should not be pinned', scrollFloater.isPinned());
    -
    -  var pinWasCalled = false;
    -  callRecorder = function() { pinWasCalled = true; };
    -  goog.events.listen(
    -      scrollFloater, goog.ui.ScrollFloater.EventType.PIN, callRecorder);
    -  scrollFloater.pin_();
    -  assertTrue('PIN event was called', pinWasCalled);
    -  assertFalse('Should not be floating', scrollFloater.isFloating());
    -  assertTrue('Should be pinned', scrollFloater.isPinned());
    -
    -  scrollFloater.dispose();
    -}
    -
    -function testScrollFloaterEventCancellation() {
    -  var scrollFloater = new goog.ui.ScrollFloater();
    -  var floater = goog.dom.getElement('floater');
    -  scrollFloater.decorate(floater);
    -
    -  // Event handler that returns false to cancel the event.
    -  var eventCanceller = function() { return false; };
    -
    -  // Have eventCanceller handle the FLOAT event and verify cancellation.
    -  goog.events.listen(
    -      scrollFloater, goog.ui.ScrollFloater.EventType.FLOAT, eventCanceller);
    -  scrollFloater.float_(goog.ui.ScrollFloater.FloatMode_.TOP);
    -  assertFalse('Should not be floating', scrollFloater.isFloating());
    -
    -  // Have eventCanceller handle the PIN event and verify cancellation.
    -  goog.events.listen(
    -      scrollFloater, goog.ui.ScrollFloater.EventType.PIN, eventCanceller);
    -  scrollFloater.dock_();
    -  assertFalse('Should not be pinned', scrollFloater.isPinned());
    -
    -  // Detach eventCanceller and enable floating.
    -  goog.events.unlisten(
    -      scrollFloater, goog.ui.ScrollFloater.EventType.FLOAT, eventCanceller);
    -  scrollFloater.float_(goog.ui.ScrollFloater.FloatMode_.TOP);
    -
    -  // Have eventCanceller handle the DOCK event and verify cancellation.
    -  goog.events.listen(
    -      scrollFloater, goog.ui.ScrollFloater.EventType.DOCK, eventCanceller);
    -  scrollFloater.dock_();
    -  assertTrue('Should still be floating', scrollFloater.isFloating());
    -
    -  scrollFloater.dispose();
    -}
    -
    -function testScrollFloaterUpdateStyleOnFloatEvent() {
    -  var scrollFloater = new goog.ui.ScrollFloater();
    -  var floater = goog.dom.getElement('floater');
    -  scrollFloater.decorate(floater);
    -
    -  // Event handler that sets the font size of the scrollfloater to 20px.
    -  var updateStyle = function(e) {
    -    goog.style.setStyle(e.target.getElement(), 'font-size', '20px');
    -  };
    -
    -  // Set the current font size to 10px.
    -  goog.style.setStyle(scrollFloater.getElement(), 'font-size', '10px');
    -  goog.events.listen(
    -      scrollFloater, goog.ui.ScrollFloater.EventType.FLOAT, updateStyle);
    -  scrollFloater.float_(goog.ui.ScrollFloater.FloatMode_.BOTTOM);
    -
    -  // Ensure event handler got called and updated the font size.
    -  assertEquals('Font size should be 20px',
    -      '20px', goog.style.getStyle(scrollFloater.getElement(), 'font-size'));
    -
    -  assertEquals('Top should be auto',
    -      'auto', goog.style.getStyle(scrollFloater.getElement(), 'top'));
    -  assertEquals('Bottom should be 0px',
    -      0, parseInt(goog.style.getStyle(scrollFloater.getElement(), 'bottom')));
    -
    -  scrollFloater.dispose();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/select.js b/src/database/third_party/closure-library/closure/goog/ui/select.js
    deleted file mode 100644
    index 6afa9e250be..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/select.js
    +++ /dev/null
    @@ -1,526 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A class that supports single selection from a dropdown menu,
    - * with semantics similar to the native HTML <code>&lt;select&gt;</code>
    - * element.
    - *
    - * @author attila@google.com (Attila Bodis)
    - * @see ../demos/select.html
    - */
    -
    -goog.provide('goog.ui.Select');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.array');
    -goog.require('goog.events.EventType');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.IdGenerator');
    -goog.require('goog.ui.MenuButton');
    -goog.require('goog.ui.MenuItem');
    -goog.require('goog.ui.MenuRenderer');
    -goog.require('goog.ui.SelectionModel');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * A selection control.  Extends {@link goog.ui.MenuButton} by composing a
    - * menu with a selection model, and automatically updating the button's caption
    - * based on the current selection.
    - *
    - * Select fires the following events:
    - *   CHANGE - after selection changes.
    - *
    - * @param {goog.ui.ControlContent=} opt_caption Default caption or existing DOM
    - *     structure to display as the button's caption when nothing is selected.
    - *     Defaults to no caption.
    - * @param {goog.ui.Menu=} opt_menu Menu containing selection options.
    - * @param {goog.ui.ButtonRenderer=} opt_renderer Renderer used to render or
    - *     decorate the control; defaults to {@link goog.ui.MenuButtonRenderer}.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @param {!goog.ui.MenuRenderer=} opt_menuRenderer Renderer used to render or
    - *     decorate the menu; defaults to {@link goog.ui.MenuRenderer}.
    - * @constructor
    - * @extends {goog.ui.MenuButton}
    - */
    -goog.ui.Select = function(opt_caption, opt_menu, opt_renderer, opt_domHelper,
    -    opt_menuRenderer) {
    -  goog.ui.Select.base(this, 'constructor',
    -      opt_caption, opt_menu, opt_renderer, opt_domHelper,
    -      opt_menuRenderer ||
    -          new goog.ui.MenuRenderer(goog.a11y.aria.Role.LISTBOX));
    -  /**
    -   * Default caption to show when no option is selected.
    -   * @private {goog.ui.ControlContent}
    -   */
    -  this.defaultCaption_ = this.getContent();
    -
    -  /**
    -   * The initial value of the aria label of the content element. This will be
    -   * null until the caption is first populated and will be non-null thereafter.
    -   * @private {?string}
    -   */
    -  this.initialAriaLabel_ = null;
    -
    -  this.setPreferredAriaRole(goog.a11y.aria.Role.LISTBOX);
    -};
    -goog.inherits(goog.ui.Select, goog.ui.MenuButton);
    -goog.tagUnsealableClass(goog.ui.Select);
    -
    -
    -/**
    - * The selection model controlling the items in the menu.
    - * @type {goog.ui.SelectionModel}
    - * @private
    - */
    -goog.ui.Select.prototype.selectionModel_ = null;
    -
    -
    -/** @override */
    -goog.ui.Select.prototype.enterDocument = function() {
    -  goog.ui.Select.superClass_.enterDocument.call(this);
    -  this.updateCaption();
    -  this.listenToSelectionModelEvents_();
    -};
    -
    -
    -/**
    - * Decorates the given element with this control.  Overrides the superclass
    - * implementation by initializing the default caption on the select button.
    - * @param {Element} element Element to decorate.
    - * @override
    - */
    -goog.ui.Select.prototype.decorateInternal = function(element) {
    -  goog.ui.Select.superClass_.decorateInternal.call(this, element);
    -  var caption = this.getCaption();
    -  if (caption) {
    -    // Initialize the default caption.
    -    this.setDefaultCaption(caption);
    -  } else if (!this.getSelectedItem()) {
    -    // If there is no default caption and no selected item, select the first
    -    // option (this is technically an arbitrary choice, but what most people
    -    // would expect to happen).
    -    this.setSelectedIndex(0);
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.Select.prototype.disposeInternal = function() {
    -  goog.ui.Select.superClass_.disposeInternal.call(this);
    -
    -  if (this.selectionModel_) {
    -    this.selectionModel_.dispose();
    -    this.selectionModel_ = null;
    -  }
    -
    -  this.defaultCaption_ = null;
    -};
    -
    -
    -/**
    - * Handles {@link goog.ui.Component.EventType.ACTION} events dispatched by
    - * the menu item clicked by the user.  Updates the selection model, calls
    - * the superclass implementation to hide the menu, stops the propagation of
    - * the event, and dispatches an ACTION event on behalf of the select control
    - * itself.  Overrides {@link goog.ui.MenuButton#handleMenuAction}.
    - * @param {goog.events.Event} e Action event to handle.
    - * @override
    - */
    -goog.ui.Select.prototype.handleMenuAction = function(e) {
    -  this.setSelectedItem(/** @type {goog.ui.MenuItem} */ (e.target));
    -  goog.ui.Select.base(this, 'handleMenuAction', e);
    -
    -  // NOTE(chrishenry): We should not stop propagation and then fire
    -  // our own ACTION event. Fixing this without breaking anyone
    -  // relying on this event is hard though.
    -  e.stopPropagation();
    -  this.dispatchEvent(goog.ui.Component.EventType.ACTION);
    -};
    -
    -
    -/**
    - * Handles {@link goog.events.EventType.SELECT} events raised by the
    - * selection model when the selection changes.  Updates the contents of the
    - * select button.
    - * @param {goog.events.Event} e Selection event to handle.
    - */
    -goog.ui.Select.prototype.handleSelectionChange = function(e) {
    -  var item = this.getSelectedItem();
    -  goog.ui.Select.superClass_.setValue.call(this, item && item.getValue());
    -  this.updateCaption();
    -};
    -
    -
    -/**
    - * Replaces the menu currently attached to the control (if any) with the given
    - * argument, and updates the selection model.  Does nothing if the new menu is
    - * the same as the old one.  Overrides {@link goog.ui.MenuButton#setMenu}.
    - * @param {goog.ui.Menu} menu New menu to be attached to the menu button.
    - * @return {goog.ui.Menu|undefined} Previous menu (undefined if none).
    - * @override
    - */
    -goog.ui.Select.prototype.setMenu = function(menu) {
    -  // Call superclass implementation to replace the menu.
    -  var oldMenu = goog.ui.Select.superClass_.setMenu.call(this, menu);
    -
    -  // Do nothing unless the new menu is different from the current one.
    -  if (menu != oldMenu) {
    -    // Clear the old selection model (if any).
    -    if (this.selectionModel_) {
    -      this.selectionModel_.clear();
    -    }
    -
    -    // Initialize new selection model (unless the new menu is null).
    -    if (menu) {
    -      if (this.selectionModel_) {
    -        menu.forEachChild(function(child, index) {
    -          this.setCorrectAriaRole_(
    -              /** @type {goog.ui.MenuItem|goog.ui.MenuSeparator} */ (child));
    -          this.selectionModel_.addItem(child);
    -        }, this);
    -      } else {
    -        this.createSelectionModel_(menu);
    -      }
    -    }
    -  }
    -
    -  return oldMenu;
    -};
    -
    -
    -/**
    - * Returns the default caption to be shown when no option is selected.
    - * @return {goog.ui.ControlContent} Default caption.
    - */
    -goog.ui.Select.prototype.getDefaultCaption = function() {
    -  return this.defaultCaption_;
    -};
    -
    -
    -/**
    - * Sets the default caption to the given string or DOM structure.
    - * @param {goog.ui.ControlContent} caption Default caption to be shown
    - *    when no option is selected.
    - */
    -goog.ui.Select.prototype.setDefaultCaption = function(caption) {
    -  this.defaultCaption_ = caption;
    -  this.updateCaption();
    -};
    -
    -
    -/**
    - * Adds a new menu item at the end of the menu.
    - * @param {goog.ui.Control} item Menu item to add to the menu.
    - * @override
    - */
    -goog.ui.Select.prototype.addItem = function(item) {
    -  this.setCorrectAriaRole_(
    -      /** @type {goog.ui.MenuItem|goog.ui.MenuSeparator} */ (item));
    -  goog.ui.Select.superClass_.addItem.call(this, item);
    -
    -  if (this.selectionModel_) {
    -    this.selectionModel_.addItem(item);
    -  } else {
    -    this.createSelectionModel_(this.getMenu());
    -  }
    -  this.updateAriaActiveDescendant_();
    -};
    -
    -
    -/**
    - * Adds a new menu item at a specific index in the menu.
    - * @param {goog.ui.MenuItem|goog.ui.MenuSeparator} item Menu item to add to the
    - *     menu.
    - * @param {number} index Index at which to insert the menu item.
    - * @override
    - */
    -goog.ui.Select.prototype.addItemAt = function(item, index) {
    -  this.setCorrectAriaRole_(
    -      /** @type {goog.ui.MenuItem|goog.ui.MenuSeparator} */ (item));
    -  goog.ui.Select.superClass_.addItemAt.call(this, item, index);
    -
    -  if (this.selectionModel_) {
    -    this.selectionModel_.addItemAt(item, index);
    -  } else {
    -    this.createSelectionModel_(this.getMenu());
    -  }
    -};
    -
    -
    -/**
    - * Removes an item from the menu and disposes it.
    - * @param {goog.ui.MenuItem|goog.ui.MenuSeparator} item The menu item to remove.
    - * @override
    - */
    -goog.ui.Select.prototype.removeItem = function(item) {
    -  goog.ui.Select.superClass_.removeItem.call(this, item);
    -  if (this.selectionModel_) {
    -    this.selectionModel_.removeItem(item);
    -  }
    -};
    -
    -
    -/**
    - * Removes a menu item at a given index in the menu and disposes it.
    - * @param {number} index Index of item.
    - * @override
    - */
    -goog.ui.Select.prototype.removeItemAt = function(index) {
    -  goog.ui.Select.superClass_.removeItemAt.call(this, index);
    -  if (this.selectionModel_) {
    -    this.selectionModel_.removeItemAt(index);
    -  }
    -};
    -
    -
    -/**
    - * Selects the specified option (assumed to be in the select menu), and
    - * deselects the previously selected option, if any.  A null argument clears
    - * the selection.
    - * @param {goog.ui.MenuItem} item Option to be selected (null to clear
    - *     the selection).
    - */
    -goog.ui.Select.prototype.setSelectedItem = function(item) {
    -  if (this.selectionModel_) {
    -    var prevItem = this.getSelectedItem();
    -    this.selectionModel_.setSelectedItem(item);
    -
    -    if (item != prevItem) {
    -      this.dispatchEvent(goog.ui.Component.EventType.CHANGE);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Selects the option at the specified index, or clears the selection if the
    - * index is out of bounds.
    - * @param {number} index Index of the option to be selected.
    - */
    -goog.ui.Select.prototype.setSelectedIndex = function(index) {
    -  if (this.selectionModel_) {
    -    this.setSelectedItem(/** @type {goog.ui.MenuItem} */
    -        (this.selectionModel_.getItemAt(index)));
    -  }
    -};
    -
    -
    -/**
    - * Selects the first option found with an associated value equal to the
    - * argument, or clears the selection if no such option is found.  A null
    - * argument also clears the selection.  Overrides {@link
    - * goog.ui.Button#setValue}.
    - * @param {*} value Value of the option to be selected (null to clear
    - *     the selection).
    - * @override
    - */
    -goog.ui.Select.prototype.setValue = function(value) {
    -  if (goog.isDefAndNotNull(value) && this.selectionModel_) {
    -    for (var i = 0, item; item = this.selectionModel_.getItemAt(i); i++) {
    -      if (item && typeof item.getValue == 'function' &&
    -          item.getValue() == value) {
    -        this.setSelectedItem(/** @type {!goog.ui.MenuItem} */ (item));
    -        return;
    -      }
    -    }
    -  }
    -
    -  this.setSelectedItem(null);
    -};
    -
    -
    -/**
    - * Gets the value associated with the currently selected option (null if none).
    - *
    - * Note that unlike {@link goog.ui.Button#getValue} which this method overrides,
    - * the "value" of a Select instance is the value of its selected menu item, not
    - * its own value. This makes a difference because the "value" of a Button is
    - * reset to the value of the element it decorates when it's added to the DOM
    - * (via ButtonRenderer), whereas the value of the selected item is unaffected.
    - * So while setValue() has no effect on a Button before it is added to the DOM,
    - * it will make a persistent change to a Select instance (which is consistent
    - * with any changes made by {@link goog.ui.Select#setSelectedItem} and
    - * {@link goog.ui.Select#setSelectedIndex}).
    - *
    - * @override
    - */
    -goog.ui.Select.prototype.getValue = function() {
    -  var selectedItem = this.getSelectedItem();
    -  return selectedItem ? selectedItem.getValue() : null;
    -};
    -
    -
    -/**
    - * Returns the currently selected option.
    - * @return {goog.ui.MenuItem} The currently selected option (null if none).
    - */
    -goog.ui.Select.prototype.getSelectedItem = function() {
    -  return this.selectionModel_ ?
    -      /** @type {goog.ui.MenuItem} */ (this.selectionModel_.getSelectedItem()) :
    -      null;
    -};
    -
    -
    -/**
    - * Returns the index of the currently selected option.
    - * @return {number} 0-based index of the currently selected option (-1 if none).
    - */
    -goog.ui.Select.prototype.getSelectedIndex = function() {
    -  return this.selectionModel_ ? this.selectionModel_.getSelectedIndex() : -1;
    -};
    -
    -
    -/**
    - * @return {goog.ui.SelectionModel} The selection model.
    - * @protected
    - */
    -goog.ui.Select.prototype.getSelectionModel = function() {
    -  return this.selectionModel_;
    -};
    -
    -
    -/**
    - * Creates a new selection model and sets up an event listener to handle
    - * {@link goog.events.EventType.SELECT} events dispatched by it.
    - * @param {goog.ui.Component=} opt_component If provided, will add the
    - *     component's children as items to the selection model.
    - * @private
    - */
    -goog.ui.Select.prototype.createSelectionModel_ = function(opt_component) {
    -  this.selectionModel_ = new goog.ui.SelectionModel();
    -  if (opt_component) {
    -    opt_component.forEachChild(function(child, index) {
    -      this.setCorrectAriaRole_(
    -          /** @type {goog.ui.MenuItem|goog.ui.MenuSeparator} */ (child));
    -      this.selectionModel_.addItem(child);
    -    }, this);
    -  }
    -  this.listenToSelectionModelEvents_();
    -};
    -
    -
    -/**
    - * Subscribes to events dispatched by the selection model.
    - * @private
    - */
    -goog.ui.Select.prototype.listenToSelectionModelEvents_ = function() {
    -  if (this.selectionModel_) {
    -    this.getHandler().listen(this.selectionModel_, goog.events.EventType.SELECT,
    -        this.handleSelectionChange);
    -  }
    -};
    -
    -
    -/**
    - * Updates the caption to be shown in the select button.  If no option is
    - * selected and a default caption is set, sets the caption to the default
    - * caption; otherwise to the empty string.
    - * @protected
    - */
    -goog.ui.Select.prototype.updateCaption = function() {
    -  var item = this.getSelectedItem();
    -  this.setContent(item ? item.getCaption() : this.defaultCaption_);
    -
    -  var contentElement = this.getRenderer().getContentElement(this.getElement());
    -  // Despite the ControlRenderer interface indicating the return value is
    -  // {Element}, many renderers cast element.firstChild to {Element} when it is
    -  // really {Node}. Checking tagName verifies this is an {!Element}.
    -  if (contentElement && this.getDomHelper().isElement(contentElement)) {
    -    if (this.initialAriaLabel_ == null) {
    -      this.initialAriaLabel_ = goog.a11y.aria.getLabel(contentElement);
    -    }
    -    var itemElement = item ? item.getElement() : null;
    -    goog.a11y.aria.setLabel(contentElement, itemElement ?
    -        goog.a11y.aria.getLabel(itemElement) : this.initialAriaLabel_);
    -    this.updateAriaActiveDescendant_();
    -  }
    -};
    -
    -
    -/**
    - * Updates the aria active descendant attribute.
    - * @private
    - */
    -goog.ui.Select.prototype.updateAriaActiveDescendant_ = function() {
    -  var renderer = this.getRenderer();
    -  if (renderer) {
    -    var contentElement = renderer.getContentElement(this.getElement());
    -    if (contentElement) {
    -      var buttonElement = this.getElementStrict();
    -      if (!contentElement.id) {
    -        contentElement.id = goog.ui.IdGenerator.getInstance().getNextUniqueId();
    -      }
    -      goog.a11y.aria.setRole(contentElement, goog.a11y.aria.Role.OPTION);
    -      goog.a11y.aria.setState(buttonElement,
    -          goog.a11y.aria.State.ACTIVEDESCENDANT, contentElement.id);
    -      if (this.selectionModel_) {
    -        // We can't use selectionmodel's getItemCount here because we need to
    -        // skip separators.
    -        var items = this.selectionModel_.getItems();
    -        var menuItemCount = goog.array.count(items, function(item) {
    -          return item instanceof goog.ui.MenuItem;
    -        });
    -        goog.a11y.aria.setState(contentElement, goog.a11y.aria.State.SETSIZE,
    -            menuItemCount);
    -        // Set a human-readable selection index.
    -        goog.a11y.aria.setState(contentElement, goog.a11y.aria.State.POSINSET,
    -            1 + this.selectionModel_.getSelectedIndex());
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Sets the correct ARIA role for the menu item or separator.
    - * @param {goog.ui.MenuItem|goog.ui.MenuSeparator} item The item to set.
    - * @private
    - */
    -goog.ui.Select.prototype.setCorrectAriaRole_ = function(item) {
    -  item.setPreferredAriaRole(item instanceof goog.ui.MenuItem ?
    -      goog.a11y.aria.Role.OPTION : goog.a11y.aria.Role.SEPARATOR);
    -};
    -
    -
    -/**
    - * Opens or closes the menu.  Overrides {@link goog.ui.MenuButton#setOpen} by
    - * highlighting the currently selected option on open.
    - * @param {boolean} open Whether to open or close the menu.
    - * @param {goog.events.Event=} opt_e Mousedown event that caused the menu to
    - *     be opened.
    - * @override
    - */
    -goog.ui.Select.prototype.setOpen = function(open, opt_e) {
    -  goog.ui.Select.superClass_.setOpen.call(this, open, opt_e);
    -
    -  if (this.isOpen()) {
    -    this.getMenu().setHighlightedIndex(this.getSelectedIndex());
    -  } else {
    -    this.updateAriaActiveDescendant_();
    -  }
    -};
    -
    -
    -// Register a decorator factory function for goog.ui.Selects.
    -goog.ui.registry.setDecoratorByClassName(
    -    goog.getCssName('goog-select'), function() {
    -      // Select defaults to using MenuButtonRenderer, since it shares its L&F.
    -      return new goog.ui.Select(null);
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/select_test.html b/src/database/third_party/closure-library/closure/goog/ui/select_test.html
    deleted file mode 100644
    index d9f9683e9ea..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/select_test.html
    +++ /dev/null
    @@ -1,26 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.Select
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.SelectTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="sandbox">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/select_test.js b/src/database/third_party/closure-library/closure/goog/ui/select_test.js
    deleted file mode 100644
    index 5f42d6cff8a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/select_test.js
    +++ /dev/null
    @@ -1,329 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.SelectTest');
    -goog.setTestOnly('goog.ui.SelectTest');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.CustomButtonRenderer');
    -goog.require('goog.ui.Menu');
    -goog.require('goog.ui.MenuItem');
    -goog.require('goog.ui.Select');
    -goog.require('goog.ui.Separator');
    -
    -var defaultCaption = 'initial caption';
    -var sandboxEl;
    -var select;
    -
    -function setUp() {
    -  sandboxEl = goog.dom.getElement('sandbox');
    -  select = new goog.ui.Select(defaultCaption);
    -}
    -
    -function tearDown() {
    -  select.dispose();
    -  goog.dom.removeChildren(sandboxEl);
    -}
    -
    -
    -/**
    - * Checks that the default caption passed in the constructor and in the setter
    - * is returned by getDefaultCaption, and acts as a default caption, i.e. is
    - * shown as a caption when no items are selected.
    - */
    -function testDefaultCaption() {
    -  select.render(sandboxEl);
    -  var item1 = new goog.ui.MenuItem('item 1');
    -  select.addItem(item1);
    -  select.addItem(new goog.ui.MenuItem('item 2'));
    -  assertEquals(defaultCaption, select.getDefaultCaption());
    -  assertEquals(defaultCaption, select.getCaption());
    -
    -  var newCaption = 'new caption';
    -  select.setDefaultCaption(newCaption);
    -  assertEquals(newCaption, select.getDefaultCaption());
    -  assertEquals(newCaption, select.getCaption());
    -
    -  select.setSelectedItem(item1);
    -  assertNotEquals(newCaption, select.getCaption());
    -
    -  select.setSelectedItem(null);
    -  assertEquals(newCaption, select.getCaption());
    -}
    -
    -function testNoDefaultCaption() {
    -  assertNull(new goog.ui.Select().getDefaultCaption());
    -  assertEquals('', new goog.ui.Select('').getDefaultCaption());
    -}
    -
    -// Confirms that aria roles for select conform to spec:
    -// http://www.w3.org/TR/wai-aria/roles#listbox
    -// Basically the select should have a role of LISTBOX and all the items should
    -// have a role of OPTION.
    -function testAriaRoles() {
    -  select.render(sandboxEl);
    -  var item1 = new goog.ui.MenuItem('item 1');
    -  select.addItem(item1);
    -  // Added a separator to make sure that the SETSIZE ignores the separator
    -  // items.
    -  var separator = new goog.ui.Separator();
    -  select.addItem(separator);
    -  var item2 = new goog.ui.MenuItem('item 2');
    -  select.addItem(item2);
    -  assertNotNull(select.getElement());
    -  assertNotNull(item1.getElement());
    -  assertNotNull(item2.getElement());
    -  assertEquals(goog.a11y.aria.Role.LISTBOX,
    -      goog.a11y.aria.getRole(select.getElement()));
    -  assertEquals(goog.a11y.aria.Role.OPTION,
    -      goog.a11y.aria.getRole(item1.getElement()));
    -  assertEquals(goog.a11y.aria.Role.OPTION,
    -      goog.a11y.aria.getRole(item2.getElement()));
    -  assertNotNull(goog.a11y.aria.getState(select.getElement(),
    -      goog.a11y.aria.State.ACTIVEDESCENDANT));
    -  var contentElement = select.getRenderer().
    -      getContentElement(select.getElement());
    -  assertEquals('2', goog.a11y.aria.getState(contentElement,
    -      goog.a11y.aria.State.SETSIZE));
    -  assertEquals('0', goog.a11y.aria.getState(contentElement,
    -      goog.a11y.aria.State.POSINSET));
    -}
    -
    -
    -/**
    - * Checks that the select control handles ACTION events from its items.
    - */
    -function testHandlesItemActions() {
    -  select.render(sandboxEl);
    -  var item1 = new goog.ui.MenuItem('item 1');
    -  var item2 = new goog.ui.MenuItem('item 2');
    -  select.addItem(item1);
    -  select.addItem(item2);
    -
    -  item1.dispatchEvent(goog.ui.Component.EventType.ACTION);
    -  assertEquals(item1, select.getSelectedItem());
    -  assertEquals(item1.getCaption(), select.getCaption());
    -
    -  item2.dispatchEvent(goog.ui.Component.EventType.ACTION);
    -  assertEquals(item2, select.getSelectedItem());
    -  assertEquals(item2.getCaption(), select.getCaption());
    -}
    -
    -
    -/**
    - * Tests goog.ui.Select.prototype.setValue.
    - */
    -function testSetValue() {
    -  select.render(sandboxEl);
    -  var item1 = new goog.ui.MenuItem('item 1', 1);
    -  var item2 = new goog.ui.MenuItem('item 2', 2);
    -  select.addItem(item1);
    -  select.addItem(item2);
    -
    -  select.setValue(1);
    -  assertEquals(item1, select.getSelectedItem());
    -
    -  select.setValue(2);
    -  assertEquals(item2, select.getSelectedItem());
    -
    -  select.setValue(3);
    -  assertNull(select.getSelectedItem());
    -}
    -
    -
    -/**
    - * Checks that the current selection is cleared when the selected item is
    - * removed.
    - */
    -function testSelectionIsClearedWhenSelectedItemIsRemoved() {
    -  select.render(sandboxEl);
    -  var item1 = new goog.ui.MenuItem('item 1');
    -  select.addItem(item1);
    -  select.addItem(new goog.ui.MenuItem('item 2'));
    -
    -  select.setSelectedItem(item1);
    -  select.removeItem(item1);
    -  assertNull(select.getSelectedItem());
    -}
    -
    -
    -/**
    - * Check that the select control is subscribed to its selection model events
    - * after being added, removed and added back again into the document.
    - */
    -function testExitAndEnterDocument() {
    -  var component = new goog.ui.Component();
    -  component.render(sandboxEl);
    -
    -  var item1 = new goog.ui.MenuItem('item 1');
    -  var item2 = new goog.ui.MenuItem('item 2');
    -  var item3 = new goog.ui.MenuItem('item 3');
    -
    -  select.addItem(item1);
    -  select.addItem(item2);
    -  select.addItem(item3);
    -
    -  component.addChild(select, true);
    -  item2.dispatchEvent(goog.ui.Component.EventType.ACTION);
    -  assertEquals(item2.getCaption(), select.getCaption());
    -
    -  component.removeChild(select, true);
    -  item1.dispatchEvent(goog.ui.Component.EventType.ACTION);
    -  assertEquals(item2.getCaption(), select.getCaption());
    -
    -  component.addChild(select, true);
    -  item3.dispatchEvent(goog.ui.Component.EventType.ACTION);
    -  assertEquals(item3.getCaption(), select.getCaption());
    -}
    -
    -function testSelectEventFiresForProgrammaticChange() {
    -  select.render();
    -  var item1 = new goog.ui.MenuItem('item 1');
    -  var item2 = new goog.ui.MenuItem('item 2');
    -  select.addItem(item1);
    -  select.addItem(item2);
    -
    -  var recordingHandler = new goog.testing.recordFunction();
    -  goog.events.listen(
    -      select, goog.ui.Component.EventType.CHANGE, recordingHandler);
    -
    -  select.setSelectedItem(item2);
    -  assertEquals('Selecting new item should fire CHANGE event.',
    -      1, recordingHandler.getCallCount());
    -
    -  select.setSelectedItem(item2);
    -  assertEquals('Selecting the same item should not fire CHANGE event.',
    -      1, recordingHandler.getCallCount());
    -
    -  select.setSelectedIndex(0);
    -  assertEquals('Selecting new item should fire CHANGE event.',
    -      2, recordingHandler.getCallCount());
    -
    -  select.setSelectedIndex(0);
    -  assertEquals('Selecting the same item should not fire CHANGE event.',
    -      2, recordingHandler.getCallCount());
    -}
    -
    -function testSelectEventFiresForUserInitiatedAction() {
    -  select.render();
    -  var item1 = new goog.ui.MenuItem('item 1');
    -  var item2 = new goog.ui.MenuItem('item 2');
    -  select.addItem(item1);
    -  select.addItem(item2);
    -
    -  var recordingHandler = new goog.testing.recordFunction();
    -  goog.events.listen(
    -      select, goog.ui.Component.EventType.CHANGE, recordingHandler);
    -
    -  select.setOpen(true);
    -
    -  item2.dispatchEvent(goog.ui.Component.EventType.ACTION);
    -  assertEquals('Selecting new item should fire CHANGE event.',
    -      1, recordingHandler.getCallCount());
    -  assertFalse(select.isOpen());
    -
    -  select.setOpen(true);
    -
    -  item2.dispatchEvent(goog.ui.Component.EventType.ACTION);
    -  assertEquals('Selecting the same item should not fire CHANGE event.',
    -      1, recordingHandler.getCallCount());
    -  assertFalse(select.isOpen());
    -}
    -
    -
    -/**
    - * Checks that if an item is selected before decorate is called, the selection
    - * is preserved after decorate.
    - */
    -function testSetSelectedItemBeforeRender() {
    -  select.addItem(new goog.ui.MenuItem('item 1'));
    -  select.addItem(new goog.ui.MenuItem('item 2'));
    -  var item3 = new goog.ui.MenuItem('item 3');
    -  select.addItem(item3);
    -  select.setSelectedItem(item3);
    -  assertEquals(2, select.getSelectedIndex());
    -
    -  select.decorate(sandboxEl);
    -  assertEquals(2, select.getSelectedIndex());
    -}
    -
    -
    -/**
    - * Checks that if a value is set before decorate is called, the value is
    - * preserved after decorate.
    - */
    -function testSetValueBeforeRender() {
    -  select.addItem(new goog.ui.MenuItem('item 1', 1));
    -  select.addItem(new goog.ui.MenuItem('item 2', 2));
    -  select.setValue(2);
    -  assertEquals(2, select.getValue());
    -
    -  select.decorate(sandboxEl);
    -  assertEquals(2, select.getValue());
    -}
    -
    -
    -function testUpdateCaption_aria() {
    -  select.render(sandboxEl);
    -
    -  // Verify default state.
    -  assertEquals(defaultCaption, select.getCaption());
    -  assertFalse(
    -      !!goog.a11y.aria.getLabel(
    -          select.getRenderer().getContentElement(select.getElement())));
    -
    -  // Add and select an item with aria-label.
    -  var item1 = new goog.ui.MenuItem();
    -  select.addItem(item1);
    -  item1.getElement().setAttribute('aria-label', 'item1');
    -  select.setSelectedIndex(0);
    -  assertEquals(
    -      'item1',
    -      goog.a11y.aria.getLabel(
    -          select.getRenderer().getContentElement(select.getElement())));
    -
    -  // Add and select an item without a label.
    -  var item2 = new goog.ui.MenuItem();
    -  select.addItem(item2);
    -  select.setSelectedIndex(1);
    -  assertFalse(
    -      !!goog.a11y.aria.getLabel(
    -          select.getRenderer().getContentElement(select.getElement())));
    -}
    -
    -function testDisposeWhenInnerHTMLHasBeenClearedInIE10() {
    -  assertNotThrows(function() {
    -    var customSelect = new goog.ui.Select(null /* label */, new goog.ui.Menu(),
    -        new goog.ui.CustomButtonRenderer());
    -    customSelect.render(sandboxEl);
    -
    -    // In IE10 setting the innerHTML of a node invalidates the parent child
    -    // relation of all its child nodes (unlike removeNode).
    -    sandboxEl.innerHTML = '';
    -
    -    // goog.ui.Select's disposeInternal trigger's goog.ui.Component's
    -    // disposeInternal, which triggers goog.ui.MenuButton's exitDocument,
    -    // which closes the associated menu and updates the activeDescendent.
    -    // In the case of a CustomMenuButton the contentElement is referenced by
    -    // element.firstChild.firstChild, an invalid relation in IE 10.
    -    customSelect.dispose();
    -  });
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/selectionmenubutton.js b/src/database/third_party/closure-library/closure/goog/ui/selectionmenubutton.js
    deleted file mode 100644
    index 98445ff2024..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/selectionmenubutton.js
    +++ /dev/null
    @@ -1,300 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A customized MenuButton for selection of items among lists.
    - * Menu contains 'select all' and 'select none' MenuItems for selecting all and
    - * no items by default. Other MenuItems can be added by user.
    - *
    - * The checkbox content fires the action events associated with the 'select all'
    - * and 'select none' menu items.
    - *
    - * @see ../demos/selectionmenubutton.html
    - */
    -
    -goog.provide('goog.ui.SelectionMenuButton');
    -goog.provide('goog.ui.SelectionMenuButton.SelectionState');
    -
    -goog.require('goog.events.EventType');
    -goog.require('goog.style');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.MenuButton');
    -goog.require('goog.ui.MenuItem');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * A selection menu button control.  Extends {@link goog.ui.MenuButton}.
    - * Menu contains 'select all' and 'select none' MenuItems for selecting all and
    - * no items by default. Other MenuItems can be added by user.
    - *
    - * The checkbox content fires the action events associated with the 'select all'
    - * and 'select none' menu items.
    - *
    - * @param {goog.ui.ButtonRenderer=} opt_renderer Renderer used to render or
    - *     decorate the menu button; defaults to {@link goog.ui.MenuButtonRenderer}.
    - * @param {goog.ui.MenuItemRenderer=} opt_itemRenderer Optional menu item
    - *     renderer.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @constructor
    - * @extends {goog.ui.MenuButton}
    - */
    -goog.ui.SelectionMenuButton = function(opt_renderer,
    -                                       opt_itemRenderer,
    -                                       opt_domHelper) {
    -  goog.ui.MenuButton.call(this,
    -                          null,
    -                          null,
    -                          opt_renderer,
    -                          opt_domHelper);
    -  this.initialItemRenderer_ = opt_itemRenderer || null;
    -};
    -goog.inherits(goog.ui.SelectionMenuButton, goog.ui.MenuButton);
    -goog.tagUnsealableClass(goog.ui.SelectionMenuButton);
    -
    -
    -/**
    - * Constants for menu action types.
    - * @enum {number}
    - */
    -goog.ui.SelectionMenuButton.SelectionState = {
    -  ALL: 0,
    -  SOME: 1,
    -  NONE: 2
    -};
    -
    -
    -/**
    - * Select button state
    - * @type {goog.ui.SelectionMenuButton.SelectionState}
    - * @protected
    - */
    -goog.ui.SelectionMenuButton.prototype.selectionState =
    -    goog.ui.SelectionMenuButton.SelectionState.NONE;
    -
    -
    -/**
    - * Item renderer used for the first 2 items, 'select all' and 'select none'.
    - * @type {goog.ui.MenuItemRenderer}
    - * @private
    - */
    -goog.ui.SelectionMenuButton.prototype.initialItemRenderer_;
    -
    -
    -/**
    - * Enables button and embedded checkbox.
    - * @param {boolean} enable Whether to enable or disable the button.
    - * @override
    - */
    -goog.ui.SelectionMenuButton.prototype.setEnabled = function(enable) {
    -  goog.ui.SelectionMenuButton.base(this, 'setEnabled', enable);
    -  this.setCheckboxEnabled(enable);
    -};
    -
    -
    -/**
    - * Enables the embedded checkbox.
    - * @param {boolean} enable Whether to enable or disable the checkbox.
    - * @protected
    - */
    -goog.ui.SelectionMenuButton.prototype.setCheckboxEnabled = function(enable) {
    -  this.getCheckboxElement().disabled = !enable;
    -};
    -
    -
    -/** @override */
    -goog.ui.SelectionMenuButton.prototype.handleMouseDown = function(e) {
    -  if (!this.getDomHelper().contains(this.getCheckboxElement(),
    -      /** @type {Element} */ (e.target))) {
    -    goog.ui.SelectionMenuButton.superClass_.handleMouseDown.call(this, e);
    -  }
    -};
    -
    -
    -/**
    - * Gets the checkbox element. Needed because if decorating html, getContent()
    - * may include and comment/text elements in addition to the input element.
    - * @return {Element} Checkbox.
    - * @protected
    - */
    -goog.ui.SelectionMenuButton.prototype.getCheckboxElement = function() {
    -  var elements = this.getDomHelper().getElementsByTagNameAndClass(
    -      'input',
    -      goog.getCssName('goog-selectionmenubutton-checkbox'),
    -      this.getContentElement());
    -  return elements[0];
    -};
    -
    -
    -/**
    - * Checkbox click handler.
    - * @param {goog.events.BrowserEvent} e Checkbox click event.
    - * @protected
    - */
    -goog.ui.SelectionMenuButton.prototype.handleCheckboxClick = function(e) {
    -  if (this.selectionState == goog.ui.SelectionMenuButton.SelectionState.NONE) {
    -    this.setSelectionState(goog.ui.SelectionMenuButton.SelectionState.ALL);
    -    if (this.getItemAt(0)) {
    -      this.getItemAt(0).dispatchEvent(  // 'All' item
    -          goog.ui.Component.EventType.ACTION);
    -    }
    -  } else {
    -    this.setSelectionState(goog.ui.SelectionMenuButton.SelectionState.NONE);
    -    if (this.getItemAt(1)) {
    -      this.getItemAt(1).dispatchEvent(  // 'None' item
    -          goog.ui.Component.EventType.ACTION);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Menu action handler to update checkbox checked state.
    - * @param {goog.events.Event} e Menu action event.
    - * @private
    - */
    -goog.ui.SelectionMenuButton.prototype.handleMenuAction_ = function(e) {
    -  if (e.target.getModel() == goog.ui.SelectionMenuButton.SelectionState.ALL) {
    -    this.setSelectionState(goog.ui.SelectionMenuButton.SelectionState.ALL);
    -  } else {
    -    this.setSelectionState(goog.ui.SelectionMenuButton.SelectionState.NONE);
    -  }
    -};
    -
    -
    -/**
    - * Set up events related to the menu items.
    - * @private
    - */
    -goog.ui.SelectionMenuButton.prototype.addMenuEvent_ = function() {
    -  if (this.getItemAt(0) && this.getItemAt(1)) {
    -    this.getHandler().listen(this.getMenu(),
    -                             goog.ui.Component.EventType.ACTION,
    -                             this.handleMenuAction_);
    -    this.getItemAt(0).setModel(goog.ui.SelectionMenuButton.SelectionState.ALL);
    -    this.getItemAt(1).setModel(goog.ui.SelectionMenuButton.SelectionState.NONE);
    -  }
    -};
    -
    -
    -/**
    - * Set up events related to the checkbox.
    - * @protected
    - */
    -goog.ui.SelectionMenuButton.prototype.addCheckboxEvent = function() {
    -  this.getHandler().listen(this.getCheckboxElement(),
    -                           goog.events.EventType.CLICK,
    -                           this.handleCheckboxClick);
    -};
    -
    -
    -/**
    - * Adds the checkbox to the button, and adds 2 items to the menu corresponding
    - * to 'select all' and 'select none'.
    - * @override
    - * @protected
    - */
    -goog.ui.SelectionMenuButton.prototype.createDom = function() {
    -  goog.ui.SelectionMenuButton.superClass_.createDom.call(this);
    -
    -  this.createCheckbox();
    -
    -  /** @desc Text for 'All' button, used to select all items in a list. */
    -  var MSG_SELECTIONMENUITEM_ALL = goog.getMsg('All');
    -  /** @desc Text for 'None' button, used to unselect all items in a list. */
    -  var MSG_SELECTIONMENUITEM_NONE = goog.getMsg('None');
    -
    -  var itemAll = new goog.ui.MenuItem(MSG_SELECTIONMENUITEM_ALL,
    -                                     null,
    -                                     this.getDomHelper(),
    -                                     this.initialItemRenderer_);
    -  var itemNone = new goog.ui.MenuItem(MSG_SELECTIONMENUITEM_NONE,
    -                                      null,
    -                                      this.getDomHelper(),
    -                                      this.initialItemRenderer_);
    -  this.addItem(itemAll);
    -  this.addItem(itemNone);
    -
    -  this.addCheckboxEvent();
    -  this.addMenuEvent_();
    -};
    -
    -
    -/**
    - * Creates and adds the checkbox to the button.
    - * @protected
    - */
    -goog.ui.SelectionMenuButton.prototype.createCheckbox = function() {
    -  var checkbox = this.getDomHelper().createElement('input');
    -  checkbox.type = 'checkbox';
    -  checkbox.className = goog.getCssName('goog-selectionmenubutton-checkbox');
    -  this.setContent(checkbox);
    -};
    -
    -
    -/** @override */
    -goog.ui.SelectionMenuButton.prototype.decorateInternal = function(element) {
    -  goog.ui.SelectionMenuButton.superClass_.decorateInternal.call(this, element);
    -  this.addCheckboxEvent();
    -  this.addMenuEvent_();
    -};
    -
    -
    -/** @override */
    -goog.ui.SelectionMenuButton.prototype.setMenu = function(menu) {
    -  goog.ui.SelectionMenuButton.superClass_.setMenu.call(this, menu);
    -  this.addMenuEvent_();
    -};
    -
    -
    -/**
    - * Set selection state and update checkbox.
    - * @param {goog.ui.SelectionMenuButton.SelectionState} state Selection state.
    - */
    -goog.ui.SelectionMenuButton.prototype.setSelectionState = function(state) {
    -  if (this.selectionState != state) {
    -    var checkbox = this.getCheckboxElement();
    -    if (state == goog.ui.SelectionMenuButton.SelectionState.ALL) {
    -      checkbox.checked = true;
    -      goog.style.setOpacity(checkbox, 1);
    -    } else if (state == goog.ui.SelectionMenuButton.SelectionState.SOME) {
    -      checkbox.checked = true;
    -      // TODO(user): Get UX help to style this
    -      goog.style.setOpacity(checkbox, 0.5);
    -    } else { // NONE
    -      checkbox.checked = false;
    -      goog.style.setOpacity(checkbox, 1);
    -    }
    -    this.selectionState = state;
    -  }
    -};
    -
    -
    -/**
    -* Get selection state.
    -* @return {goog.ui.SelectionMenuButton.SelectionState} Selection state.
    -*/
    -goog.ui.SelectionMenuButton.prototype.getSelectionState = function() {
    -  return this.selectionState;
    -};
    -
    -
    -// Register a decorator factory function for goog.ui.SelectionMenuButton.
    -goog.ui.registry.setDecoratorByClassName(
    -    goog.getCssName('goog-selectionmenubutton-button'),
    -    function() {
    -      return new goog.ui.SelectionMenuButton();
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/selectionmenubutton_test.html b/src/database/third_party/closure-library/closure/goog/ui/selectionmenubutton_test.html
    deleted file mode 100644
    index 065236acfff..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/selectionmenubutton_test.html
    +++ /dev/null
    @@ -1,54 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -
    -  @author zhyder@google.com (Zohair Hyder)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.SelectionMenuButton
    -  </title>
    -  <style type="text/css">
    -   .goog-menu {
    -  position: absolute;
    -  color: #aaa;
    -}
    -  </style>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.SelectionMenuButtonTest');
    -  </script>
    - </head>
    - <body>
    -  <p>
    -   Here's a selectionmenu defined in markup:
    -  </p>
    -  <div id="demoSelectionMenuButton" class="goog-selectionmenubutton-button">
    -   <input id="demoCheckbox" class="goog-selectionmenubutton-checkbox" type="checkbox" />
    -   <div id="demoMenu" class="goog-menu">
    -    <div id="menuItem1" class="goog-menuitem">
    -     All
    -    </div>
    -    <div id="menuItem2" class="goog-menuitem">
    -     None
    -    </div>
    -    <div id="menuItem3" class="goog-menuitem">
    -     Read
    -    </div>
    -    <div id="menuItem4" class="goog-menuitem">
    -     Unread
    -    </div>
    -   </div>
    -  </div>
    -  <div id="footer">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/selectionmenubutton_test.js b/src/database/third_party/closure-library/closure/goog/ui/selectionmenubutton_test.js
    deleted file mode 100644
    index e7af08a2c1a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/selectionmenubutton_test.js
    +++ /dev/null
    @@ -1,201 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.SelectionMenuButtonTest');
    -goog.setTestOnly('goog.ui.SelectionMenuButtonTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.SelectionMenuButton');
    -
    -var selectionMenuButton;
    -var clonedSelectionMenuButtonDom;
    -
    -
    -function setUp() {
    -  clonedSelectionMenuButtonDom =
    -      goog.dom.getElement('demoSelectionMenuButton').cloneNode(true);
    -
    -  selectionMenuButton = new goog.ui.SelectionMenuButton();
    -}
    -
    -function tearDown() {
    -  selectionMenuButton.dispose();
    -
    -  var element = goog.dom.getElement('demoSelectionMenuButton');
    -  element.parentNode.replaceChild(clonedSelectionMenuButtonDom, element);
    -}
    -
    -
    -/**
    - * Open the menu and click on the menu item inside.
    - */
    -function testBasicButtonBehavior() {
    -  var node = goog.dom.getElement('demoSelectionMenuButton');
    -  selectionMenuButton.decorate(node);
    -  goog.testing.events.fireClickSequence(node);
    -
    -  assertTrue('Menu must open after click', selectionMenuButton.isOpen());
    -
    -  var menuItemClicked = 0;
    -  var lastMenuItemClicked = null;
    -  goog.events.listen(selectionMenuButton.getMenu(),
    -      goog.ui.Component.EventType.ACTION,
    -      function(e) {
    -        menuItemClicked++;
    -        lastMenuItemClicked = e.target;
    -      });
    -
    -  var menuItem2 = goog.dom.getElement('menuItem2');
    -  goog.testing.events.fireClickSequence(menuItem2);
    -  assertFalse('Menu must close on clicking when open',
    -      selectionMenuButton.isOpen());
    -  assertEquals('Number of menu items clicked should be 1', 1, menuItemClicked);
    -  assertEquals('menuItem2 should be the last menuitem clicked', menuItem2,
    -      lastMenuItemClicked.getElement());
    -}
    -
    -
    -/**
    - * Tests that the checkbox fires the same events as the first 2 items.
    - */
    -function testCheckboxFireEvents() {
    -  var node = goog.dom.getElement('demoSelectionMenuButton');
    -  selectionMenuButton.decorate(node);
    -
    -  var menuItemClicked = 0;
    -  var lastMenuItemClicked = null;
    -  goog.events.listen(selectionMenuButton.getMenu(),
    -      goog.ui.Component.EventType.ACTION,
    -      function(e) {
    -        menuItemClicked++;
    -        lastMenuItemClicked = e.target;
    -      });
    -
    -  var checkbox = goog.dom.getElement('demoCheckbox');
    -  assertFalse('Checkbox must be unchecked (i.e. unselected)', checkbox.checked);
    -
    -  checkbox.checked = true;
    -  goog.testing.events.fireClickSequence(checkbox);
    -  assertFalse('Menu must be closed when clicking checkbox',
    -      selectionMenuButton.isOpen());
    -  assertEquals('Number of menu items clicked should be 1', 1, menuItemClicked);
    -  assertEquals('menuItem1 should be the last menuitem clicked',
    -      goog.dom.getElement('menuItem1'),
    -      lastMenuItemClicked.getElement());
    -
    -  checkbox.checked = false;
    -  goog.testing.events.fireClickSequence(checkbox);
    -  assertFalse('Menu must be closed when clicking checkbox',
    -      selectionMenuButton.isOpen());
    -  assertEquals('Number of menu items clicked should be 2', 2, menuItemClicked);
    -  assertEquals('menuItem2 should be the last menuitem clicked',
    -      goog.dom.getElement('menuItem2'), lastMenuItemClicked.getElement());
    -}
    -
    -
    -/**
    - * Tests that the checkbox state gets updated when the first 2 events fire
    - */
    -function testCheckboxReceiveEvents() {
    -  var node = goog.dom.getElement('demoSelectionMenuButton');
    -  selectionMenuButton.decorate(node);
    -
    -  var checkbox = goog.dom.getElement('demoCheckbox');
    -  assertFalse('Checkbox must be unchecked (i.e. unselected)', checkbox.checked);
    -
    -  goog.testing.events.fireClickSequence(goog.dom.getElement('menuItem1'));
    -  assertTrue('Checkbox must be checked (i.e. selected)', checkbox.checked);
    -
    -  goog.testing.events.fireClickSequence(goog.dom.getElement('menuItem2'));
    -  assertFalse('Checkbox must be unchecked (i.e. unselected)', checkbox.checked);
    -}
    -
    -
    -/**
    - * Tests that set/getSelectionState correctly changes the state
    - */
    -function testSelectionState() {
    -  var node = goog.dom.getElement('demoSelectionMenuButton');
    -  selectionMenuButton.decorate(node);
    -
    -  var checkbox = goog.dom.getElement('demoCheckbox');
    -  assertFalse('Checkbox must be unchecked (i.e. unselected)', checkbox.checked);
    -
    -  selectionMenuButton.setSelectionState(
    -      goog.ui.SelectionMenuButton.SelectionState.ALL);
    -  assertTrue('Checkbox should be checked when selecting all', checkbox.checked);
    -  assertEquals('selectionState should be ALL',
    -      selectionMenuButton.getSelectionState(),
    -      goog.ui.SelectionMenuButton.SelectionState.ALL);
    -
    -  selectionMenuButton.setSelectionState(
    -      goog.ui.SelectionMenuButton.SelectionState.NONE);
    -  assertFalse('Checkbox should be checked when selecting all',
    -      checkbox.checked);
    -  assertEquals('selectionState should be NONE',
    -      selectionMenuButton.getSelectionState(),
    -      goog.ui.SelectionMenuButton.SelectionState.NONE);
    -
    -  selectionMenuButton.setSelectionState(
    -      goog.ui.SelectionMenuButton.SelectionState.SOME);
    -  assertTrue('Checkbox should be checked when selecting all', checkbox.checked);
    -  assertEquals('selectionState should be SOME',
    -      selectionMenuButton.getSelectionState(),
    -      goog.ui.SelectionMenuButton.SelectionState.SOME);
    -}
    -
    -
    -/**
    - * Tests that the checkbox gets disabled when the button is disabled
    - */
    -function testCheckboxDisabled() {
    -  var node = goog.dom.getElement('demoSelectionMenuButton');
    -  selectionMenuButton.decorate(node);
    -
    -  var checkbox = goog.dom.getElement('demoCheckbox');
    -  assertFalse('Checkbox must be enabled', checkbox.disabled);
    -
    -  selectionMenuButton.setEnabled(false);
    -  assertTrue('Checkbox must be disabled', checkbox.disabled);
    -
    -  selectionMenuButton.setEnabled(true);
    -  assertFalse('Checkbox must be enabled', checkbox.disabled);
    -}
    -
    -
    -/**
    - * Tests that clicking the checkbox does not open the menu
    - */
    -function testCheckboxClickMenuClosed() {
    -  var node = goog.dom.getElement('demoSelectionMenuButton');
    -  selectionMenuButton.decorate(node);
    -
    -  var checkbox = goog.dom.getElement('demoCheckbox');
    -  goog.testing.events.fireMouseDownEvent(checkbox);
    -  assertFalse('Menu must be closed when mousedown checkbox',
    -      selectionMenuButton.isOpen());
    -  goog.testing.events.fireMouseUpEvent(checkbox);
    -  assertFalse('Menu must remain closed when mouseup checkbox',
    -      selectionMenuButton.isOpen());
    -
    -  selectionMenuButton.setOpen(true);
    -  goog.testing.events.fireClickSequence(checkbox);
    -  assertFalse('Menu must close when clickin checkbox',
    -      selectionMenuButton.isOpen());
    -
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/selectionmodel.js b/src/database/third_party/closure-library/closure/goog/ui/selectionmodel.js
    deleted file mode 100644
    index 4cde31bd822..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/selectionmodel.js
    +++ /dev/null
    @@ -1,301 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Single-selection model implemenation.
    - *
    - * TODO(attila): Add keyboard & mouse event hooks?
    - * TODO(attila): Add multiple selection?
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -
    -goog.provide('goog.ui.SelectionModel');
    -
    -goog.require('goog.array');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -
    -
    -
    -/**
    - * Single-selection model.  Dispatches a {@link goog.events.EventType.SELECT}
    - * event when a selection is made.
    - * @param {Array<Object>=} opt_items Array of items; defaults to empty.
    - * @extends {goog.events.EventTarget}
    - * @constructor
    - */
    -goog.ui.SelectionModel = function(opt_items) {
    -  goog.events.EventTarget.call(this);
    -
    -  /**
    -   * Array of items controlled by the selection model.  If the items support
    -   * the {@code setSelected(Boolean)} interface, they will be (de)selected
    -   * as needed.
    -   * @type {!Array<Object>}
    -   * @private
    -   */
    -  this.items_ = [];
    -  this.addItems(opt_items);
    -};
    -goog.inherits(goog.ui.SelectionModel, goog.events.EventTarget);
    -goog.tagUnsealableClass(goog.ui.SelectionModel);
    -
    -
    -/**
    - * The currently selected item (null if none).
    - * @type {Object}
    - * @private
    - */
    -goog.ui.SelectionModel.prototype.selectedItem_ = null;
    -
    -
    -/**
    - * Selection handler function.  Called with two arguments (the item to be
    - * selected or deselected, and a Boolean indicating whether the item is to
    - * be selected or deselected).
    - * @type {Function}
    - * @private
    - */
    -goog.ui.SelectionModel.prototype.selectionHandler_ = null;
    -
    -
    -/**
    - * Returns the selection handler function used by the selection model to change
    - * the internal selection state of items under its control.
    - * @return {Function} Selection handler function (null if none).
    - */
    -goog.ui.SelectionModel.prototype.getSelectionHandler = function() {
    -  return this.selectionHandler_;
    -};
    -
    -
    -/**
    - * Sets the selection handler function to be used by the selection model to
    - * change the internal selection state of items under its control.  The
    - * function must take two arguments:  an item and a Boolean to indicate whether
    - * the item is to be selected or deselected.  Selection handler functions are
    - * only needed if the items in the selection model don't natively support the
    - * {@code setSelected(Boolean)} interface.
    - * @param {Function} handler Selection handler function.
    - */
    -goog.ui.SelectionModel.prototype.setSelectionHandler = function(handler) {
    -  this.selectionHandler_ = handler;
    -};
    -
    -
    -/**
    - * Returns the number of items controlled by the selection model.
    - * @return {number} Number of items.
    - */
    -goog.ui.SelectionModel.prototype.getItemCount = function() {
    -  return this.items_.length;
    -};
    -
    -
    -/**
    - * Returns the 0-based index of the given item within the selection model, or
    - * -1 if no such item is found.
    - * @param {Object|undefined} item Item to look for.
    - * @return {number} Index of the given item (-1 if none).
    - */
    -goog.ui.SelectionModel.prototype.indexOfItem = function(item) {
    -  return item ? goog.array.indexOf(this.items_, item) : -1;
    -};
    -
    -
    -/**
    - * @return {Object|undefined} The first item, or undefined if there are no items
    - *     in the model.
    - */
    -goog.ui.SelectionModel.prototype.getFirst = function() {
    -  return this.items_[0];
    -};
    -
    -
    -/**
    - * @return {Object|undefined} The last item, or undefined if there are no items
    - *     in the model.
    - */
    -goog.ui.SelectionModel.prototype.getLast = function() {
    -  return this.items_[this.items_.length - 1];
    -};
    -
    -
    -/**
    - * Returns the item at the given 0-based index.
    - * @param {number} index Index of the item to return.
    - * @return {Object} Item at the given index (null if none).
    - */
    -goog.ui.SelectionModel.prototype.getItemAt = function(index) {
    -  return this.items_[index] || null;
    -};
    -
    -
    -/**
    - * Bulk-adds items to the selection model.  This is more efficient than calling
    - * {@link #addItem} for each new item.
    - * @param {Array<Object>|undefined} items New items to add.
    - */
    -goog.ui.SelectionModel.prototype.addItems = function(items) {
    -  if (items) {
    -    // New items shouldn't be selected.
    -    goog.array.forEach(items, function(item) {
    -      this.selectItem_(item, false);
    -    }, this);
    -    goog.array.extend(this.items_, items);
    -  }
    -};
    -
    -
    -/**
    - * Adds an item at the end of the list.
    - * @param {Object} item Item to add.
    - */
    -goog.ui.SelectionModel.prototype.addItem = function(item) {
    -  this.addItemAt(item, this.getItemCount());
    -};
    -
    -
    -/**
    - * Adds an item at the given index.
    - * @param {Object} item Item to add.
    - * @param {number} index Index at which to add the new item.
    - */
    -goog.ui.SelectionModel.prototype.addItemAt = function(item, index) {
    -  if (item) {
    -    // New items must not be selected.
    -    this.selectItem_(item, false);
    -    goog.array.insertAt(this.items_, item, index);
    -  }
    -};
    -
    -
    -/**
    - * Removes the given item (if it exists).  Dispatches a {@code SELECT} event if
    - * the removed item was the currently selected item.
    - * @param {Object} item Item to remove.
    - */
    -goog.ui.SelectionModel.prototype.removeItem = function(item) {
    -  if (item && goog.array.remove(this.items_, item)) {
    -    if (item == this.selectedItem_) {
    -      this.selectedItem_ = null;
    -      this.dispatchEvent(goog.events.EventType.SELECT);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Removes the item at the given index.
    - * @param {number} index Index of the item to remove.
    - */
    -goog.ui.SelectionModel.prototype.removeItemAt = function(index) {
    -  this.removeItem(this.getItemAt(index));
    -};
    -
    -
    -/**
    - * @return {Object} The currently selected item, or null if none.
    - */
    -goog.ui.SelectionModel.prototype.getSelectedItem = function() {
    -  return this.selectedItem_;
    -};
    -
    -
    -/**
    - * @return {!Array<Object>} All items in the selection model.
    - */
    -goog.ui.SelectionModel.prototype.getItems = function() {
    -  return goog.array.clone(this.items_);
    -};
    -
    -
    -/**
    - * Selects the given item, deselecting any previously selected item, and
    - * dispatches a {@code SELECT} event.
    - * @param {Object} item Item to select (null to clear the selection).
    - */
    -goog.ui.SelectionModel.prototype.setSelectedItem = function(item) {
    -  if (item != this.selectedItem_) {
    -    this.selectItem_(this.selectedItem_, false);
    -    this.selectedItem_ = item;
    -    this.selectItem_(item, true);
    -  }
    -
    -  // Always dispatch a SELECT event; let listeners decide what to do if the
    -  // selected item hasn't changed.
    -  this.dispatchEvent(goog.events.EventType.SELECT);
    -};
    -
    -
    -/**
    - * @return {number} The 0-based index of the currently selected item, or -1
    - *     if none.
    - */
    -goog.ui.SelectionModel.prototype.getSelectedIndex = function() {
    -  return this.indexOfItem(this.selectedItem_);
    -};
    -
    -
    -/**
    - * Selects the item at the given index, deselecting any previously selected
    - * item, and dispatches a {@code SELECT} event.
    - * @param {number} index Index to select (-1 to clear the selection).
    - */
    -goog.ui.SelectionModel.prototype.setSelectedIndex = function(index) {
    -  this.setSelectedItem(this.getItemAt(index));
    -};
    -
    -
    -/**
    - * Clears the selection model by removing all items from the selection.
    - */
    -goog.ui.SelectionModel.prototype.clear = function() {
    -  goog.array.clear(this.items_);
    -  this.selectedItem_ = null;
    -};
    -
    -
    -/** @override */
    -goog.ui.SelectionModel.prototype.disposeInternal = function() {
    -  goog.ui.SelectionModel.superClass_.disposeInternal.call(this);
    -  delete this.items_;
    -  this.selectedItem_ = null;
    -};
    -
    -
    -/**
    - * Private helper; selects or deselects the given item based on the value of
    - * the {@code select} argument.  If a selection handler has been registered
    - * (via {@link #setSelectionHandler}, calls it to update the internal selection
    - * state of the item.  Otherwise, attempts to call {@code setSelected(Boolean)}
    - * on the item itself, provided the object supports that interface.
    - * @param {Object} item Item to select or deselect.
    - * @param {boolean} select If true, the object will be selected; if false, it
    - *     will be deselected.
    - * @private
    - */
    -goog.ui.SelectionModel.prototype.selectItem_ = function(item, select) {
    -  if (item) {
    -    if (typeof this.selectionHandler_ == 'function') {
    -      // Use the registered selection handler function.
    -      this.selectionHandler_(item, select);
    -    } else if (typeof item.setSelected == 'function') {
    -      // Call setSelected() on the item, if it supports it.
    -      item.setSelected(select);
    -    }
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/selectionmodel_test.html b/src/database/third_party/closure-library/closure/goog/ui/selectionmodel_test.html
    deleted file mode 100644
    index 72c9681eca4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/selectionmodel_test.html
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.ui.SelectionModel
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.ui.SelectionModelTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/selectionmodel_test.js b/src/database/third_party/closure-library/closure/goog/ui/selectionmodel_test.js
    deleted file mode 100644
    index 7481b5d26e0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/selectionmodel_test.js
    +++ /dev/null
    @@ -1,220 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.SelectionModelTest');
    -goog.setTestOnly('goog.ui.SelectionModelTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -goog.require('goog.ui.SelectionModel');
    -
    -var selectionModel, items, addedItem, addedItems;
    -
    -function setUp() {
    -  items = [1, 2, 3, 4];
    -  addedItem = 5;
    -  addedItems = [6, 7, 8];
    -  selectionModel = new goog.ui.SelectionModel(items);
    -}
    -
    -function tearDown() {
    -  goog.dispose(selectionModel);
    -}
    -
    -/*
    - * Checks that the selection model returns the correct item count.
    - */
    -function testGetItemCount() {
    -  assertEquals(items.length, selectionModel.getItemCount());
    -}
    -
    -/*
    - * Checks that the correct first element is returned by the selection model.
    - */
    -function testGetFirst() {
    -  assertEquals(items[0], selectionModel.getFirst());
    -}
    -
    -/*
    - * Checks that the correct last element is returned by the selection model.
    - */
    -function testGetLast() {
    -  assertEquals(items[items.length - 1], selectionModel.getLast());
    -}
    -
    -/*
    - * Tests the behavior of goog.ui.SelectionModel.getItemAt(index).
    - */
    -function testGetItemAt() {
    -  goog.array.forEach(items,
    -      function(item, i) {
    -        assertEquals(item, selectionModel.getItemAt(i));
    -      });
    -}
    -
    -/*
    - * Checks that an item can be correctly added to the selection model.
    - */
    -function testAddItem() {
    -  assertEquals(items.length, selectionModel.getItemCount());
    -
    -  selectionModel.addItem(addedItem);
    -
    -  assertEquals(items.length + 1, selectionModel.getItemCount());
    -  assertEquals(addedItem, selectionModel.getLast());
    -}
    -
    -/*
    - * Checks that an item can be added to the selection model at a specific index.
    - */
    -function testAddItemAt() {
    -  assertEquals(items.length, selectionModel.getItemCount());
    -
    -  var insertIndex = 2;
    -  assertEquals(items[insertIndex], selectionModel.getItemAt(insertIndex));
    -
    -  selectionModel.addItemAt(addedItem, insertIndex);
    -
    -  var resultArray = goog.array.clone(items);
    -  goog.array.insertAt(resultArray, addedItem, insertIndex);
    -
    -  assertEquals(items.length + 1, selectionModel.getItemCount());
    -  assertEquals(addedItem, selectionModel.getItemAt(insertIndex));
    -  assertArrayEquals(resultArray, selectionModel.getItems());
    -}
    -
    -/*
    - * Checks that multiple items can be correctly added to the selection model.
    - */
    -function testAddItems() {
    -  assertEquals(items.length, selectionModel.getItemCount());
    -
    -  selectionModel.addItems(addedItems);
    -
    -  assertEquals(items.length + addedItems.length, selectionModel.getItemCount());
    -
    -  var resultArray = goog.array.concat(items, addedItems);
    -  assertArrayEquals(resultArray, selectionModel.getItems());
    -}
    -
    -/*
    - * Checks that all elements can be removed from the selection model.
    - */
    -function testClear() {
    -  assertArrayEquals(items, selectionModel.getItems());
    -
    -  selectionModel.clear();
    -
    -  assertArrayEquals([], selectionModel.getItems());
    -}
    -
    -/*
    - * Checks that all items can be obtained from the selection model.
    - */
    -function testGetItems() {
    -  assertArrayEquals(items, selectionModel.getItems());
    -}
    -
    -/*
    - * Checks that an item's index can be found in the selection model.
    - */
    -function testIndexOfItem() {
    -  goog.array.forEach(items,
    -      function(item, i) {
    -        assertEquals(i, selectionModel.indexOfItem(item));
    -      });
    -}
    -
    -/*
    - * Checks that an item can be removed from the selection model.
    - */
    -function testRemoveItem() {
    -  assertEquals(items.length, selectionModel.getItemCount());
    -
    -  var resultArray = goog.array.clone(items);
    -  goog.array.removeAt(resultArray, 2);
    -
    -  selectionModel.removeItem(items[2]);
    -
    -  assertEquals(items.length - 1, selectionModel.getItemCount());
    -  assertArrayEquals(resultArray, selectionModel.getItems());
    -}
    -
    -/*
    - * Checks that an item at a particular index can be removed from the selection
    - * model.
    - */
    -function testRemoveItemAt() {
    -  assertEquals(items.length, selectionModel.getItemCount());
    -
    -  var resultArray = goog.array.clone(items);
    -  var removeIndex = 2;
    -
    -  goog.array.removeAt(resultArray, removeIndex);
    -
    -  selectionModel.removeItemAt(removeIndex);
    -
    -  assertEquals(items.length - 1, selectionModel.getItemCount());
    -  assertNotEquals(items[removeIndex], selectionModel.getItemAt(removeIndex));
    -  assertArrayEquals(resultArray, selectionModel.getItems());
    -}
    -
    -/*
    - * Checks that item selection at a particular index works.
    - */
    -function testSelectedIndex() {
    -  // Default selected index is -1
    -  assertEquals(-1, selectionModel.getSelectedIndex());
    -
    -  selectionModel.setSelectedIndex(2);
    -
    -  assertEquals(2, selectionModel.getSelectedIndex());
    -  assertEquals(items[2], selectionModel.getSelectedItem());
    -}
    -
    -/*
    - * Checks that items can be selected in the selection model.
    - */
    -function testSelectedItem() {
    -  assertNull(selectionModel.getSelectedItem());
    -
    -  selectionModel.setSelectedItem(items[1]);
    -
    -  assertNotNull(selectionModel.getSelectedItem());
    -  assertEquals(items[1], selectionModel.getSelectedItem());
    -  assertEquals(1, selectionModel.getSelectedIndex());
    -}
    -
    -/*
    - * Checks that an installed handler is called on selection change.
    - */
    -function testSelectionHandler() {
    -  var myRecordFunction = new goog.testing.recordFunction();
    -
    -  selectionModel.setSelectionHandler(myRecordFunction);
    -
    -  // Select index 2
    -  selectionModel.setSelectedIndex(2);
    -  // De-select 2 and select 3
    -  selectionModel.setSelectedIndex(3);
    -
    -  var recordCalls = myRecordFunction.getCalls();
    -
    -  assertEquals(3, recordCalls.length);
    -  // Calls: Select items[2], de-select items[2], select items[3]
    -  assertArrayEquals([items[2], true], recordCalls[0].getArguments());
    -  assertArrayEquals([items[2], false], recordCalls[1].getArguments());
    -  assertArrayEquals([items[3], true], recordCalls[2].getArguments());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/separator.js b/src/database/third_party/closure-library/closure/goog/ui/separator.js
    deleted file mode 100644
    index 303d9d3c2bf..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/separator.js
    +++ /dev/null
    @@ -1,80 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A class for representing a separator, with renderers for both
    - * horizontal (menu) and vertical (toolbar) separators.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.Separator');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.asserts');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.Control');
    -goog.require('goog.ui.MenuSeparatorRenderer');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * Class representing a separator.  Although it extends {@link goog.ui.Control},
    - * the Separator class doesn't allocate any event handlers, nor does it change
    - * its appearance on mouseover, etc.
    - * @param {goog.ui.MenuSeparatorRenderer=} opt_renderer Renderer to render or
    - *    decorate the separator; defaults to {@link goog.ui.MenuSeparatorRenderer}.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *    document interaction.
    - * @constructor
    - * @extends {goog.ui.Control}
    - */
    -goog.ui.Separator = function(opt_renderer, opt_domHelper) {
    -  goog.ui.Control.call(this, null, opt_renderer ||
    -      goog.ui.MenuSeparatorRenderer.getInstance(), opt_domHelper);
    -
    -  this.setSupportedState(goog.ui.Component.State.DISABLED, false);
    -  this.setSupportedState(goog.ui.Component.State.HOVER, false);
    -  this.setSupportedState(goog.ui.Component.State.ACTIVE, false);
    -  this.setSupportedState(goog.ui.Component.State.FOCUSED, false);
    -
    -  // Separators are always considered disabled.
    -  this.setStateInternal(goog.ui.Component.State.DISABLED);
    -};
    -goog.inherits(goog.ui.Separator, goog.ui.Control);
    -
    -
    -/**
    - * Configures the component after its DOM has been rendered.  Overrides
    - * {@link goog.ui.Control#enterDocument} by making sure no event handler
    - * is allocated.
    - * @override
    - */
    -goog.ui.Separator.prototype.enterDocument = function() {
    -  goog.ui.Separator.superClass_.enterDocument.call(this);
    -  var element = this.getElement();
    -  goog.asserts.assert(element,
    -      'The DOM element for the separator cannot be null.');
    -  goog.a11y.aria.setRole(element, 'separator');
    -};
    -
    -
    -// Register a decorator factory function for goog.ui.MenuSeparators.
    -goog.ui.registry.setDecoratorByClassName(
    -    goog.ui.MenuSeparatorRenderer.CSS_CLASS,
    -    function() {
    -      // Separator defaults to using MenuSeparatorRenderer.
    -      return new goog.ui.Separator();
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/serverchart.js b/src/database/third_party/closure-library/closure/goog/ui/serverchart.js
    deleted file mode 100644
    index 1735c90bef2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/serverchart.js
    +++ /dev/null
    @@ -1,1839 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Component for generating chart PNGs using Google Chart Server.
    - *
    - * @deprecated Google Chart Images service (the server-side component of this
    - *     class) has been deprecated. See
    - *     https://developers.google.com/chart/ for alternatives.
    - *
    - * @see ../demos/serverchart.html
    - */
    -
    -
    -/**
    - * Namespace for chart functions
    - */
    -goog.provide('goog.ui.ServerChart');
    -goog.provide('goog.ui.ServerChart.AxisDisplayType');
    -goog.provide('goog.ui.ServerChart.ChartType');
    -goog.provide('goog.ui.ServerChart.EncodingType');
    -goog.provide('goog.ui.ServerChart.Event');
    -goog.provide('goog.ui.ServerChart.LegendPosition');
    -goog.provide('goog.ui.ServerChart.MaximumValue');
    -goog.provide('goog.ui.ServerChart.MultiAxisAlignment');
    -goog.provide('goog.ui.ServerChart.MultiAxisType');
    -goog.provide('goog.ui.ServerChart.UriParam');
    -goog.provide('goog.ui.ServerChart.UriTooLongEvent');
    -
    -goog.require('goog.Uri');
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.events.Event');
    -goog.require('goog.string');
    -goog.require('goog.ui.Component');
    -
    -
    -
    -/**
    - * Will construct a chart using Google's chartserver.
    - *
    - * @param {goog.ui.ServerChart.ChartType} type The chart type.
    - * @param {number=} opt_width The width of the chart.
    - * @param {number=} opt_height The height of the chart.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM Helper.
    - * @param {string=} opt_uri Optional uri used to connect to the chart server, if
    - *     different than goog.ui.ServerChart.CHART_SERVER_SCHEME_INDEPENDENT_URI.
    - * @constructor
    - * @extends {goog.ui.Component}
    - *
    - * @deprecated Google Chart Server has been deprecated. See
    - *     https://developers.google.com/chart/image/ for details.
    - * @final
    - */
    -goog.ui.ServerChart = function(type, opt_width, opt_height, opt_domHelper,
    -    opt_uri) {
    -  goog.ui.Component.call(this, opt_domHelper);
    -
    -  /**
    -   * Image URI.
    -   * @type {goog.Uri}
    -   * @private
    -   */
    -  this.uri_ = new goog.Uri(
    -      opt_uri || goog.ui.ServerChart.CHART_SERVER_SCHEME_INDEPENDENT_URI);
    -
    -  /**
    -   * Encoding method for the URI data format.
    -   * @type {goog.ui.ServerChart.EncodingType}
    -   * @private
    -   */
    -  this.encodingType_ = goog.ui.ServerChart.EncodingType.AUTOMATIC;
    -
    -  /**
    -   * Two-dimensional array of the data sets on the chart.
    -   * @type {Array<Array<number>>}
    -   * @private
    -   */
    -  this.dataSets_ = [];
    -
    -  /**
    -   * Colors for each data set.
    -   * @type {Array<string>}
    -   * @private
    -   */
    -  this.setColors_ = [];
    -
    -  /**
    -   * Legend texts for each data set.
    -   * @type {Array<string>}
    -   * @private
    -   */
    -  this.setLegendTexts_ = [];
    -
    -  /**
    -   * Labels on the X-axis.
    -   * @type {Array<string>}
    -   * @private
    -   */
    -  this.xLabels_ = [];
    -
    -  /**
    -   * Labels on the left along the Y-axis.
    -   * @type {Array<string>}
    -   * @private
    -   */
    -  this.leftLabels_ = [];
    -
    -  /**
    -   * Labels on the right along the Y-axis.
    -   * @type {Array<string>}
    -   * @private
    -   */
    -  this.rightLabels_ = [];
    -
    -  /**
    -   * Axis type for each multi-axis in the chart. The indices into this array
    -   * also work as the reference index for all other multi-axis properties.
    -   * @type {Array<goog.ui.ServerChart.MultiAxisType>}
    -   * @private
    -   */
    -  this.multiAxisType_ = [];
    -
    -  /**
    -   * Axis text for each multi-axis in the chart, indexed by the indices from
    -   * multiAxisType_ in a sparse array.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.multiAxisLabelText_ = {};
    -
    -
    -  /**
    -   * Axis position for each multi-axis in the chart, indexed by the indices
    -   * from multiAxisType_ in a sparse array.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.multiAxisLabelPosition_ = {};
    -
    -  /**
    -   * Axis range for each multi-axis in the chart, indexed by the indices from
    -   * multiAxisType_ in a sparse array.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.multiAxisRange_ = {};
    -
    -  /**
    -   * Axis style for each multi-axis in the chart, indexed by the indices from
    -   * multiAxisType_ in a sparse array.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.multiAxisLabelStyle_ = {};
    -
    -  this.setType(type);
    -  this.setSize(opt_width, opt_height);
    -
    -  /**
    -   * Minimum value for the chart (used for normalization). By default,
    -   * this is set to infinity, and is eventually updated to the lowest given
    -   * value in the data. The minimum value is then subtracted from all other
    -   * values. For a pie chart, subtracting the minimum value does not make
    -   * sense, so minValue_ is set to zero because 0 is the additive identity.
    -   * @type {number}
    -   * @private
    -   */
    -  this.minValue_ = this.isPieChart() ? 0 : Infinity;
    -};
    -goog.inherits(goog.ui.ServerChart, goog.ui.Component);
    -
    -
    -/**
    - * Base scheme-independent URI for the chart renderer.
    - * @type {string}
    - */
    -goog.ui.ServerChart.CHART_SERVER_SCHEME_INDEPENDENT_URI =
    -    '//chart.googleapis.com/chart';
    -
    -
    -/**
    - * Base HTTP URI for the chart renderer.
    - * @type {string}
    - */
    -goog.ui.ServerChart.CHART_SERVER_HTTP_URI =
    -    'http://chart.googleapis.com/chart';
    -
    -
    -/**
    - * Base HTTPS URI for the chart renderer.
    - * @type {string}
    - */
    -goog.ui.ServerChart.CHART_SERVER_HTTPS_URI =
    -    'https://chart.googleapis.com/chart';
    -
    -
    -/**
    - * Base URI for the chart renderer.
    - * @type {string}
    - * @deprecated Use
    - *     {@link goog.ui.ServerChart.CHART_SERVER_SCHEME_INDEPENDENT_URI},
    - *     {@link goog.ui.ServerChart.CHART_SERVER_HTTP_URI} or
    - *     {@link goog.ui.ServerChart.CHART_SERVER_HTTPS_URI} instead.
    - */
    -goog.ui.ServerChart.CHART_SERVER_URI =
    -    goog.ui.ServerChart.CHART_SERVER_HTTP_URI;
    -
    -
    -/**
    - * The 0 - 1.0 ("fraction of the range") value to use when getMinValue() ==
    - * getMaxValue(). This determines, for example, the vertical position
    - * of the line in a flat line-chart.
    - * @type {number}
    - */
    -goog.ui.ServerChart.DEFAULT_NORMALIZATION = 0.5;
    -
    -
    -/**
    - * The upper limit on the length of the chart image URI, after encoding.
    - * If the URI's length equals or exceeds it, goog.ui.ServerChart.UriTooLongEvent
    - * is dispatched on the goog.ui.ServerChart object.
    - * @type {number}
    - * @private
    - */
    -goog.ui.ServerChart.prototype.uriLengthLimit_ = 2048;
    -
    -
    -/**
    - * Number of gridlines along the X-axis.
    - * @type {number}
    - * @private
    - */
    -goog.ui.ServerChart.prototype.gridX_ = 0;
    -
    -
    -/**
    - * Number of gridlines along the Y-axis.
    - * @type {number}
    - * @private
    - */
    -goog.ui.ServerChart.prototype.gridY_ = 0;
    -
    -
    -/**
    - * Maximum value for the chart (used for normalization). The minimum is
    - * declared in the constructor.
    - * @type {number}
    - * @private
    - */
    -goog.ui.ServerChart.prototype.maxValue_ = -Infinity;
    -
    -
    -/**
    - * Chart title.
    - * @type {?string}
    - * @private
    - */
    -goog.ui.ServerChart.prototype.title_ = null;
    -
    -
    -/**
    - * Chart title size.
    - * @type {number}
    - * @private
    - */
    -goog.ui.ServerChart.prototype.titleSize_ = 13.5;
    -
    -
    -/**
    - * Chart title color.
    - * @type {string}
    - * @private
    - */
    -goog.ui.ServerChart.prototype.titleColor_ = '333333';
    -
    -
    -/**
    - * Chart legend.
    - * @type {Array<string>?}
    - * @private
    - */
    -goog.ui.ServerChart.prototype.legend_ = null;
    -
    -
    -/**
    - * ChartServer supports using data sets to position markers. A data set
    - * that is being used for positioning only can be made "invisible", in other
    - * words, the caller can indicate to ChartServer that ordinary chart elements
    - * (e.g. bars in a bar chart) should not be drawn on the data points of the
    - * invisible data set. Such data sets must be provided at the end of the
    - * chd parameter, and if invisible data sets are being used, the chd
    - * parameter must indicate the number of visible data sets.
    - * @type {?number}
    - * @private
    - */
    -goog.ui.ServerChart.prototype.numVisibleDataSets_ = null;
    -
    -
    -/**
    - * Creates the DOM node (image) needed for the Chart
    - * @override
    - */
    -goog.ui.ServerChart.prototype.createDom = function() {
    -  var size = this.getSize();
    -  this.setElementInternal(this.getDomHelper().createDom(
    -      'img', {'src': this.getUri(),
    -        'class': goog.getCssName('goog-serverchart-image'),
    -        'width': size[0], 'height': size[1]}));
    -};
    -
    -
    -/**
    - * Decorate an image already in the DOM.
    - * Expects the following structure:
    - * <pre>
    - *   - img
    - * </pre>
    - *
    - * @param {Element} img Image to decorate.
    - * @override
    - */
    -goog.ui.ServerChart.prototype.decorateInternal = function(img) {
    -  img.src = this.getUri();
    -  this.setElementInternal(img);
    -};
    -
    -
    -/**
    - * Updates the image if any of the data or settings have changed.
    - */
    -goog.ui.ServerChart.prototype.updateChart = function() {
    -  if (this.getElement()) {
    -    this.getElement().src = this.getUri();
    -  }
    -};
    -
    -
    -/**
    - * Sets the URI of the chart.
    - *
    - * @param {goog.Uri} uri The chart URI.
    - */
    -goog.ui.ServerChart.prototype.setUri = function(uri) {
    -  this.uri_ = uri;
    -};
    -
    -
    -/**
    - * Returns the URI of the chart.
    - *
    - * @return {goog.Uri} The chart URI.
    - */
    -goog.ui.ServerChart.prototype.getUri = function() {
    -  this.computeDataString_();
    -  return this.uri_;
    -};
    -
    -
    -/**
    - * Returns the upper limit on the length of the chart image URI, after encoding.
    - * If the URI's length equals or exceeds it, goog.ui.ServerChart.UriTooLongEvent
    - * is dispatched on the goog.ui.ServerChart object.
    - *
    - * @return {number} The chart URI length limit.
    - */
    -goog.ui.ServerChart.prototype.getUriLengthLimit = function() {
    -  return this.uriLengthLimit_;
    -};
    -
    -
    -/**
    - * Sets the upper limit on the length of the chart image URI, after encoding.
    - * If the URI's length equals or exceeds it, goog.ui.ServerChart.UriTooLongEvent
    - * is dispatched on the goog.ui.ServerChart object.
    - *
    - * @param {number} uriLengthLimit The chart URI length limit.
    - */
    -goog.ui.ServerChart.prototype.setUriLengthLimit = function(uriLengthLimit) {
    -  this.uriLengthLimit_ = uriLengthLimit;
    -};
    -
    -
    -/**
    - * Sets the 'chg' parameter of the chart Uri.
    - * This is used by various types of charts to specify Grids.
    - *
    - * @param {string} value Value for the 'chg' parameter in the chart Uri.
    - */
    -goog.ui.ServerChart.prototype.setGridParameter = function(value) {
    -  this.uri_.setParameterValue(goog.ui.ServerChart.UriParam.GRID, value);
    -};
    -
    -
    -/**
    - * Returns the 'chg' parameter of the chart Uri.
    - * This is used by various types of charts to specify Grids.
    - *
    - * @return {string|undefined} The 'chg' parameter of the chart Uri.
    - */
    -goog.ui.ServerChart.prototype.getGridParameter = function() {
    -  return /** @type {string} */ (
    -      this.uri_.getParameterValue(goog.ui.ServerChart.UriParam.GRID));
    -};
    -
    -
    -/**
    - * Sets the 'chm' parameter of the chart Uri.
    - * This is used by various types of charts to specify Markers.
    - *
    - * @param {string} value Value for the 'chm' parameter in the chart Uri.
    - */
    -goog.ui.ServerChart.prototype.setMarkerParameter = function(value) {
    -  this.uri_.setParameterValue(goog.ui.ServerChart.UriParam.MARKERS, value);
    -};
    -
    -
    -/**
    - * Returns the 'chm' parameter of the chart Uri.
    - * This is used by various types of charts to specify Markers.
    - *
    - * @return {string|undefined} The 'chm' parameter of the chart Uri.
    - */
    -goog.ui.ServerChart.prototype.getMarkerParameter = function() {
    -  return /** @type {string} */ (
    -      this.uri_.getParameterValue(goog.ui.ServerChart.UriParam.MARKERS));
    -};
    -
    -
    -/**
    - * Sets the 'chp' parameter of the chart Uri.
    - * This is used by various types of charts to specify certain options.
    - * e.g., finance charts use this to designate which line is the 0 axis.
    - *
    - * @param {string|number} value Value for the 'chp' parameter in the chart Uri.
    - */
    -goog.ui.ServerChart.prototype.setMiscParameter = function(value) {
    -  this.uri_.setParameterValue(goog.ui.ServerChart.UriParam.MISC_PARAMS,
    -                              String(value));
    -};
    -
    -
    -/**
    - * Returns the 'chp' parameter of the chart Uri.
    - * This is used by various types of charts to specify certain options.
    - * e.g., finance charts use this to designate which line is the 0 axis.
    - *
    - * @return {string|undefined} The 'chp' parameter of the chart Uri.
    - */
    -goog.ui.ServerChart.prototype.getMiscParameter = function() {
    -  return /** @type {string} */ (
    -      this.uri_.getParameterValue(goog.ui.ServerChart.UriParam.MISC_PARAMS));
    -};
    -
    -
    -/**
    - * Enum of chart data encoding types
    - *
    - * @enum {string}
    - */
    -goog.ui.ServerChart.EncodingType = {
    -  AUTOMATIC: '',
    -  EXTENDED: 'e',
    -  SIMPLE: 's',
    -  TEXT: 't'
    -};
    -
    -
    -/**
    - * Enum of chart types with their short names used by the chartserver.
    - *
    - * @enum {string}
    - */
    -goog.ui.ServerChart.ChartType = {
    -  BAR: 'br',
    -  CLOCK: 'cf',
    -  CONCENTRIC_PIE: 'pc',
    -  FILLEDLINE: 'lr',
    -  FINANCE: 'lfi',
    -  GOOGLEOMETER: 'gom',
    -  HORIZONTAL_GROUPED_BAR: 'bhg',
    -  HORIZONTAL_STACKED_BAR: 'bhs',
    -  LINE: 'lc',
    -  MAP: 't',
    -  MAPUSA: 'tuss',
    -  MAPWORLD: 'twoc',
    -  PIE: 'p',
    -  PIE3D: 'p3',
    -  RADAR: 'rs',
    -  SCATTER: 's',
    -  SPARKLINE: 'ls',
    -  VENN: 'v',
    -  VERTICAL_GROUPED_BAR: 'bvg',
    -  VERTICAL_STACKED_BAR: 'bvs',
    -  XYLINE: 'lxy'
    -};
    -
    -
    -/**
    - * Enum of multi-axis types.
    - *
    - * @enum {string}
    - */
    -goog.ui.ServerChart.MultiAxisType = {
    -  X_AXIS: 'x',
    -  LEFT_Y_AXIS: 'y',
    -  RIGHT_Y_AXIS: 'r',
    -  TOP_AXIS: 't'
    -};
    -
    -
    -/**
    - * Enum of multi-axis alignments.
    - *
    - * @enum {number}
    - */
    -goog.ui.ServerChart.MultiAxisAlignment = {
    -  ALIGN_LEFT: -1,
    -  ALIGN_CENTER: 0,
    -  ALIGN_RIGHT: 1
    -};
    -
    -
    -/**
    - * Enum of legend positions.
    - *
    - * @enum {string}
    - */
    -goog.ui.ServerChart.LegendPosition = {
    -  TOP: 't',
    -  BOTTOM: 'b',
    -  LEFT: 'l',
    -  RIGHT: 'r'
    -};
    -
    -
    -/**
    - * Enum of line and tick options for an axis.
    - *
    - * @enum {string}
    - */
    -goog.ui.ServerChart.AxisDisplayType = {
    -  LINE_AND_TICKS: 'lt',
    -  LINE: 'l',
    -  TICKS: 't'
    -};
    -
    -
    -/**
    - * Enum of chart maximum values in pixels, as listed at:
    - * http://code.google.com/apis/chart/basics.html
    - *
    - * @enum {number}
    - */
    -goog.ui.ServerChart.MaximumValue = {
    -  WIDTH: 1000,
    -  HEIGHT: 1000,
    -  MAP_WIDTH: 440,
    -  MAP_HEIGHT: 220,
    -  TOTAL_AREA: 300000
    -};
    -
    -
    -/**
    - * Enum of ChartServer URI parameters.
    - *
    - * @enum {string}
    - */
    -goog.ui.ServerChart.UriParam = {
    -  BACKGROUND_FILL: 'chf',
    -  BAR_HEIGHT: 'chbh',
    -  DATA: 'chd',
    -  DATA_COLORS: 'chco',
    -  DATA_LABELS: 'chld',
    -  DATA_SCALING: 'chds',
    -  DIGITAL_SIGNATURE: 'sig',
    -  GEOGRAPHICAL_REGION: 'chtm',
    -  GRID: 'chg',
    -  LABEL_COLORS: 'chlc',
    -  LEFT_Y_LABELS: 'chly',
    -  LEGEND: 'chdl',
    -  LEGEND_POSITION: 'chdlp',
    -  LEGEND_TEXTS: 'chdl',
    -  LINE_STYLES: 'chls',
    -  MARGINS: 'chma',
    -  MARKERS: 'chm',
    -  MISC_PARAMS: 'chp',
    -  MULTI_AXIS_LABEL_POSITION: 'chxp',
    -  MULTI_AXIS_LABEL_TEXT: 'chxl',
    -  MULTI_AXIS_RANGE: 'chxr',
    -  MULTI_AXIS_STYLE: 'chxs',
    -  MULTI_AXIS_TYPES: 'chxt',
    -  RIGHT_LABELS: 'chlr',
    -  RIGHT_LABEL_POSITIONS: 'chlrp',
    -  SIZE: 'chs',
    -  TITLE: 'chtt',
    -  TITLE_FORMAT: 'chts',
    -  TYPE: 'cht',
    -  X_AXIS_STYLE: 'chx',
    -  X_LABELS: 'chl'
    -};
    -
    -
    -/**
    - * Sets the background fill.
    - *
    - * @param {Array<Object>} fill An array of background fill specification
    - *     objects. Each object may have the following properties:
    - *     {string} area The area to fill, either 'bg' for background or 'c' for
    - *         chart area.  The default is 'bg'.
    - *     {string} color (required) The color of the background fill.
    - *     // TODO(user): Add support for gradient/stripes, which requires
    - *     // a different object structure.
    - */
    -goog.ui.ServerChart.prototype.setBackgroundFill = function(fill) {
    -  var value = [];
    -  goog.array.forEach(fill, function(spec) {
    -    spec.area = spec.area || 'bg';
    -    spec.effect = spec.effect || 's';
    -    value.push([spec.area, spec.effect, spec.color].join(','));
    -  });
    -  value = value.join('|');
    -  this.setParameterValue(goog.ui.ServerChart.UriParam.BACKGROUND_FILL, value);
    -};
    -
    -
    -/**
    - * Returns the background fill.
    - *
    - * @return {!Array<Object>} An array of background fill specifications.
    - *     If the fill specification string is in an unsupported format, the method
    - *    returns an empty array.
    - */
    -goog.ui.ServerChart.prototype.getBackgroundFill = function() {
    -  var value =
    -      this.uri_.getParameterValue(goog.ui.ServerChart.UriParam.BACKGROUND_FILL);
    -  var result = [];
    -  if (goog.isDefAndNotNull(value)) {
    -    var fillSpecifications = value.split('|');
    -    var valid = true;
    -    goog.array.forEach(fillSpecifications, function(spec) {
    -      var parts = spec.split(',');
    -      if (valid && parts[1] == 's') {
    -        result.push({area: parts[0], effect: parts[1], color: parts[2]});
    -      } else {
    -        // If the format is unsupported, return an empty array.
    -        result = [];
    -        valid = false;
    -      }
    -    });
    -  }
    -  return result;
    -};
    -
    -
    -/**
    - * Sets the encoding type.
    - *
    - * @param {goog.ui.ServerChart.EncodingType} type Desired data encoding type.
    - */
    -goog.ui.ServerChart.prototype.setEncodingType = function(type) {
    -  this.encodingType_ = type;
    -};
    -
    -
    -/**
    - * Gets the encoding type.
    - *
    - * @return {goog.ui.ServerChart.EncodingType} The encoding type.
    - */
    -goog.ui.ServerChart.prototype.getEncodingType = function() {
    -  return this.encodingType_;
    -};
    -
    -
    -/**
    - * Sets the chart type.
    - *
    - * @param {goog.ui.ServerChart.ChartType} type The desired chart type.
    - */
    -goog.ui.ServerChart.prototype.setType = function(type) {
    -  this.uri_.setParameterValue(goog.ui.ServerChart.UriParam.TYPE, type);
    -};
    -
    -
    -/**
    - * Returns the chart type.
    - *
    - * @return {goog.ui.ServerChart.ChartType} The chart type.
    - */
    -goog.ui.ServerChart.prototype.getType = function() {
    -  return /** @type {goog.ui.ServerChart.ChartType} */ (
    -      this.uri_.getParameterValue(goog.ui.ServerChart.UriParam.TYPE));
    -};
    -
    -
    -/**
    - * Sets the chart size.
    - *
    - * @param {number=} opt_width Optional chart width, defaults to 300.
    - * @param {number=} opt_height Optional chart height, defaults to 150.
    - */
    -goog.ui.ServerChart.prototype.setSize = function(opt_width, opt_height) {
    -  var sizeString = [opt_width || 300, opt_height || 150].join('x');
    -  this.uri_.setParameterValue(goog.ui.ServerChart.UriParam.SIZE, sizeString);
    -};
    -
    -
    -/**
    - * Returns the chart size.
    - *
    - * @return {!Array<string>} [Width, Height].
    - */
    -goog.ui.ServerChart.prototype.getSize = function() {
    -  var sizeStr = this.uri_.getParameterValue(goog.ui.ServerChart.UriParam.SIZE);
    -  return sizeStr.split('x');
    -};
    -
    -
    -/**
    - * Sets the minimum value of the chart.
    - *
    - * @param {number} minValue The minimum value of the chart.
    - */
    -goog.ui.ServerChart.prototype.setMinValue = function(minValue) {
    -  this.minValue_ = minValue;
    -};
    -
    -
    -/**
    - * @return {number} The minimum value of the chart.
    - */
    -goog.ui.ServerChart.prototype.getMinValue = function() {
    -  return this.minValue_;
    -};
    -
    -
    -/**
    - * Sets the maximum value of the chart.
    - *
    - * @param {number} maxValue The maximum value of the chart.
    - */
    -goog.ui.ServerChart.prototype.setMaxValue = function(maxValue) {
    -  this.maxValue_ = maxValue;
    -};
    -
    -
    -/**
    - * @return {number} The maximum value of the chart.
    - */
    -goog.ui.ServerChart.prototype.getMaxValue = function() {
    -  return this.maxValue_;
    -};
    -
    -
    -/**
    - * Sets the chart margins.
    - *
    - * @param {number} leftMargin The size in pixels of the left margin.
    - * @param {number} rightMargin The size in pixels of the right margin.
    - * @param {number} topMargin The size in pixels of the top margin.
    - * @param {number} bottomMargin The size in pixels of the bottom margin.
    - */
    -goog.ui.ServerChart.prototype.setMargins = function(leftMargin, rightMargin,
    -    topMargin, bottomMargin) {
    -  var margins = [leftMargin, rightMargin, topMargin, bottomMargin].join(',');
    -  var UriParam = goog.ui.ServerChart.UriParam;
    -  this.uri_.setParameterValue(UriParam.MARGINS, margins);
    -};
    -
    -
    -/**
    - * Sets the number of grid lines along the X-axis.
    - *
    - * @param {number} gridlines The number of X-axis grid lines.
    - */
    -goog.ui.ServerChart.prototype.setGridX = function(gridlines) {
    -  // Need data for this to work.
    -  this.gridX_ = gridlines;
    -  this.setGrids_(this.gridX_, this.gridY_);
    -};
    -
    -
    -/**
    - * @return {number} The number of gridlines along the X-axis.
    - */
    -goog.ui.ServerChart.prototype.getGridX = function() {
    -  return this.gridX_;
    -};
    -
    -
    -/**
    - * Sets the number of grid lines along the Y-axis.
    - *
    - * @param {number} gridlines The number of Y-axis grid lines.
    - */
    -goog.ui.ServerChart.prototype.setGridY = function(gridlines) {
    -  // Need data for this to work.
    -  this.gridY_ = gridlines;
    -  this.setGrids_(this.gridX_, this.gridY_);
    -};
    -
    -
    -/**
    - * @return {number} The number of gridlines along the Y-axis.
    - */
    -goog.ui.ServerChart.prototype.getGridY = function() {
    -  return this.gridY_;
    -};
    -
    -
    -/**
    - * Sets the grids for the chart
    - *
    - * @private
    - * @param {number} x The number of grid lines along the x-axis.
    - * @param {number} y The number of grid lines along the y-axis.
    - */
    -goog.ui.ServerChart.prototype.setGrids_ = function(x, y) {
    -  var gridArray = [x == 0 ? 0 : 100 / x,
    -                   y == 0 ? 0 : 100 / y];
    -  this.uri_.setParameterValue(goog.ui.ServerChart.UriParam.GRID,
    -                              gridArray.join(','));
    -};
    -
    -
    -/**
    - * Sets the X Labels for the chart.
    - *
    - * @param {Array<string>} labels The X Labels for the chart.
    - */
    -goog.ui.ServerChart.prototype.setXLabels = function(labels) {
    -  this.xLabels_ = labels;
    -  this.uri_.setParameterValue(goog.ui.ServerChart.UriParam.X_LABELS,
    -                              this.xLabels_.join('|'));
    -};
    -
    -
    -/**
    - * @return {Array<string>} The X Labels for the chart.
    - */
    -goog.ui.ServerChart.prototype.getXLabels = function() {
    -  return this.xLabels_;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the chart is a bar chart.
    - */
    -goog.ui.ServerChart.prototype.isBarChart = function() {
    -  var type = this.getType();
    -  return type == goog.ui.ServerChart.ChartType.BAR ||
    -      type == goog.ui.ServerChart.ChartType.HORIZONTAL_GROUPED_BAR ||
    -      type == goog.ui.ServerChart.ChartType.HORIZONTAL_STACKED_BAR ||
    -      type == goog.ui.ServerChart.ChartType.VERTICAL_GROUPED_BAR ||
    -      type == goog.ui.ServerChart.ChartType.VERTICAL_STACKED_BAR;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the chart is a pie chart.
    - */
    -goog.ui.ServerChart.prototype.isPieChart = function() {
    -  var type = this.getType();
    -  return type == goog.ui.ServerChart.ChartType.PIE ||
    -      type == goog.ui.ServerChart.ChartType.PIE3D ||
    -      type == goog.ui.ServerChart.ChartType.CONCENTRIC_PIE;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the chart is a grouped bar chart.
    - */
    -goog.ui.ServerChart.prototype.isGroupedBarChart = function() {
    -  var type = this.getType();
    -  return type == goog.ui.ServerChart.ChartType.HORIZONTAL_GROUPED_BAR ||
    -      type == goog.ui.ServerChart.ChartType.VERTICAL_GROUPED_BAR;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the chart is a horizontal bar chart.
    - */
    -goog.ui.ServerChart.prototype.isHorizontalBarChart = function() {
    -  var type = this.getType();
    -  return type == goog.ui.ServerChart.ChartType.BAR ||
    -      type == goog.ui.ServerChart.ChartType.HORIZONTAL_GROUPED_BAR ||
    -      type == goog.ui.ServerChart.ChartType.HORIZONTAL_STACKED_BAR;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the chart is a line chart.
    - */
    -goog.ui.ServerChart.prototype.isLineChart = function() {
    -  var type = this.getType();
    -  return type == goog.ui.ServerChart.ChartType.FILLEDLINE ||
    -      type == goog.ui.ServerChart.ChartType.LINE ||
    -      type == goog.ui.ServerChart.ChartType.SPARKLINE ||
    -      type == goog.ui.ServerChart.ChartType.XYLINE;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the chart is a map.
    - */
    -goog.ui.ServerChart.prototype.isMap = function() {
    -  var type = this.getType();
    -  return type == goog.ui.ServerChart.ChartType.MAP ||
    -      type == goog.ui.ServerChart.ChartType.MAPUSA ||
    -      type == goog.ui.ServerChart.ChartType.MAPWORLD;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the chart is a stacked bar chart.
    - */
    -goog.ui.ServerChart.prototype.isStackedBarChart = function() {
    -  var type = this.getType();
    -  return type == goog.ui.ServerChart.ChartType.BAR ||
    -      type == goog.ui.ServerChart.ChartType.HORIZONTAL_STACKED_BAR ||
    -      type == goog.ui.ServerChart.ChartType.VERTICAL_STACKED_BAR;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the chart is a vertical bar chart.
    - */
    -goog.ui.ServerChart.prototype.isVerticalBarChart = function() {
    -  var type = this.getType();
    -  return type == goog.ui.ServerChart.ChartType.VERTICAL_GROUPED_BAR ||
    -      type == goog.ui.ServerChart.ChartType.VERTICAL_STACKED_BAR;
    -};
    -
    -
    -/**
    - * Sets the Left Labels for the chart.
    - * NOTE: The array should start with the lowest value, and then
    - *       move progessively up the axis. So if you want labels
    - *       from 0 to 100 with 0 at bottom of the graph, then you would
    - *       want to pass something like [0,25,50,75,100].
    - *
    - * @param {Array<string>} labels The Left Labels for the chart.
    - */
    -goog.ui.ServerChart.prototype.setLeftLabels = function(labels) {
    -  this.leftLabels_ = labels;
    -  this.uri_.setParameterValue(goog.ui.ServerChart.UriParam.LEFT_Y_LABELS,
    -                              this.leftLabels_.reverse().join('|'));
    -};
    -
    -
    -/**
    - * @return {Array<string>} The Left Labels for the chart.
    - */
    -goog.ui.ServerChart.prototype.getLeftLabels = function() {
    -  return this.leftLabels_;
    -};
    -
    -
    -/**
    - * Sets the given ChartServer parameter.
    - *
    - * @param {goog.ui.ServerChart.UriParam} key The ChartServer parameter to set.
    - * @param {string} value The value to set for the ChartServer parameter.
    - */
    -goog.ui.ServerChart.prototype.setParameterValue = function(key, value) {
    -  this.uri_.setParameterValue(key, value);
    -};
    -
    -
    -/**
    - * Removes the given ChartServer parameter.
    - *
    - * @param {goog.ui.ServerChart.UriParam} key The ChartServer parameter to
    - *     remove.
    - */
    -goog.ui.ServerChart.prototype.removeParameter = function(key) {
    -  this.uri_.removeParameter(key);
    -};
    -
    -
    -/**
    - * Sets the Right Labels for the chart.
    - * NOTE: The array should start with the lowest value, and then
    - *       move progessively up the axis. So if you want labels
    - *       from 0 to 100 with 0 at bottom of the graph, then you would
    - *       want to pass something like [0,25,50,75,100].
    - *
    - * @param {Array<string>} labels The Right Labels for the chart.
    - */
    -goog.ui.ServerChart.prototype.setRightLabels = function(labels) {
    -  this.rightLabels_ = labels;
    -  this.uri_.setParameterValue(goog.ui.ServerChart.UriParam.RIGHT_LABELS,
    -                              this.rightLabels_.reverse().join('|'));
    -};
    -
    -
    -/**
    - * @return {Array<string>} The Right Labels for the chart.
    - */
    -goog.ui.ServerChart.prototype.getRightLabels = function() {
    -  return this.rightLabels_;
    -};
    -
    -
    -/**
    - * Sets the position relative to the chart where the legend is to be displayed.
    - *
    - * @param {goog.ui.ServerChart.LegendPosition} value Legend position.
    - */
    -goog.ui.ServerChart.prototype.setLegendPosition = function(value) {
    -  this.uri_.setParameterValue(
    -      goog.ui.ServerChart.UriParam.LEGEND_POSITION, value);
    -};
    -
    -
    -/**
    - * Returns the position relative to the chart where the legend is to be
    - * displayed.
    - *
    - * @return {goog.ui.ServerChart.LegendPosition} Legend position.
    - */
    -goog.ui.ServerChart.prototype.getLegendPosition = function() {
    -  return /** @type {goog.ui.ServerChart.LegendPosition} */ (
    -      this.uri_.getParameterValue(
    -          goog.ui.ServerChart.UriParam.LEGEND_POSITION));
    -};
    -
    -
    -/**
    - * Sets the number of "visible" data sets. All data sets that come after
    - * the visible data set are not drawn as part of the chart. Instead, they
    - * are available for positioning markers.
    -
    - * @param {?number} n The number of visible data sets, or null if all data
    - * sets are to be visible.
    - */
    -goog.ui.ServerChart.prototype.setNumVisibleDataSets = function(n) {
    -  this.numVisibleDataSets_ = n;
    -};
    -
    -
    -/**
    - * Returns the number of "visible" data sets. All data sets that come after
    - * the visible data set are not drawn as part of the chart. Instead, they
    - * are available for positioning markers.
    - *
    - * @return {?number} The number of visible data sets, or null if all data
    - * sets are visible.
    - */
    -goog.ui.ServerChart.prototype.getNumVisibleDataSets = function() {
    -  return this.numVisibleDataSets_;
    -};
    -
    -
    -/**
    - * Sets the weight function for a Venn Diagram along with the associated
    - *     colors and legend text. Weights are assigned as follows:
    - *     weights[0] is relative area of circle A.
    - *     weights[1] is relative area of circle B.
    - *     weights[2] is relative area of circle C.
    - *     weights[3] is relative area of overlap of circles A and B.
    - *     weights[4] is relative area of overlap of circles A and C.
    - *     weights[5] is relative area of overlap of circles B and C.
    - *     weights[6] is relative area of overlap of circles A, B and C.
    - * For a two circle Venn Diagram the weights are assigned as follows:
    - *     weights[0] is relative area of circle A.
    - *     weights[1] is relative area of circle B.
    - *     weights[2] is relative area of overlap of circles A and B.
    - *
    - * @param {Array<number>} weights The relative weights of the circles.
    - * @param {Array<string>=} opt_legendText The legend labels for the circles.
    - * @param {Array<string>=} opt_colors The colors for the circles.
    - */
    -goog.ui.ServerChart.prototype.setVennSeries = function(
    -    weights, opt_legendText, opt_colors) {
    -  if (this.getType() != goog.ui.ServerChart.ChartType.VENN) {
    -    throw Error('Can only set a weight function for a Venn diagram.');
    -  }
    -  var dataMin = this.arrayMin_(weights);
    -  if (dataMin < this.minValue_) {
    -    this.minValue_ = dataMin;
    -  }
    -  var dataMax = this.arrayMax_(weights);
    -  if (dataMax > this.maxValue_) {
    -    this.maxValue_ = dataMax;
    -  }
    -  if (goog.isDef(opt_legendText)) {
    -    goog.array.forEach(
    -        opt_legendText,
    -        goog.bind(function(legend) {
    -          this.setLegendTexts_.push(legend);
    -        }, this));
    -    this.uri_.setParameterValue(goog.ui.ServerChart.UriParam.LEGEND_TEXTS,
    -                                this.setLegendTexts_.join('|'));
    -  }
    -  // If the caller only gave three weights, then they wanted a two circle
    -  // Venn Diagram. Create a 3 circle weight function where circle C has
    -  // area zero.
    -  if (weights.length == 3) {
    -    weights[3] = weights[2];
    -    weights[2] = 0.0;
    -  }
    -  this.dataSets_.push(weights);
    -  if (goog.isDef(opt_colors)) {
    -    goog.array.forEach(opt_colors, goog.bind(function(color) {
    -      this.setColors_.push(color);
    -    }, this));
    -    this.uri_.setParameterValue(goog.ui.ServerChart.UriParam.DATA_COLORS,
    -                                this.setColors_.join(','));
    -  }
    -};
    -
    -
    -/**
    - * Sets the title of the chart.
    - *
    - * @param {string} title The chart title.
    - */
    -goog.ui.ServerChart.prototype.setTitle = function(title) {
    -  this.title_ = title;
    -  this.uri_.setParameterValue(goog.ui.ServerChart.UriParam.TITLE,
    -                              this.title_.replace(/\n/g, '|'));
    -};
    -
    -
    -/**
    - * Sets the size of the chart title.
    - *
    - * @param {number} size The title size, in points.
    - */
    -goog.ui.ServerChart.prototype.setTitleSize = function(size) {
    -  this.titleSize_ = size;
    -  this.uri_.setParameterValue(goog.ui.ServerChart.UriParam.TITLE_FORMAT,
    -                              this.titleColor_ + ',' + this.titleSize_);
    -};
    -
    -
    -/**
    - * @return {number} size The title size, in points.
    - */
    -goog.ui.ServerChart.prototype.getTitleSize = function() {
    -  return this.titleSize_;
    -};
    -
    -
    -/**
    - * Sets the color of the chart title.
    - *
    - * NOTE: The color string should NOT have a '#' at the beginning of it.
    - *
    - * @param {string} color The hex value for the title color.
    - */
    -goog.ui.ServerChart.prototype.setTitleColor = function(color) {
    -  this.titleColor_ = color;
    -  this.uri_.setParameterValue(goog.ui.ServerChart.UriParam.TITLE_FORMAT,
    -                              this.titleColor_ + ',' + this.titleSize_);
    -};
    -
    -
    -/**
    - * @return {string} color The hex value for the title color.
    - */
    -goog.ui.ServerChart.prototype.getTitleColor = function() {
    -  return this.titleColor_;
    -};
    -
    -
    -/**
    - * Adds a legend to the chart.
    - *
    - * @param {Array<string>} legend The legend to add.
    - */
    -goog.ui.ServerChart.prototype.setLegend = function(legend) {
    -  this.legend_ = legend;
    -  this.uri_.setParameterValue(goog.ui.ServerChart.UriParam.LEGEND,
    -                              this.legend_.join('|'));
    -};
    -
    -
    -/**
    - * Sets the data scaling.
    - * NOTE: This also changes the encoding type because data scaling will
    - *     only work with {@code goog.ui.ServerChart.EncodingType.TEXT}
    - *     encoding.
    - * @param {number} minimum The lowest number to apply to the data.
    - * @param {number} maximum The highest number to apply to the data.
    - */
    -goog.ui.ServerChart.prototype.setDataScaling = function(minimum, maximum) {
    -  this.encodingType_ = goog.ui.ServerChart.EncodingType.TEXT;
    -  this.uri_.setParameterValue(goog.ui.ServerChart.UriParam.DATA_SCALING,
    -                              minimum + ',' + maximum);
    -};
    -
    -
    -/**
    - * Sets the widths of the bars and the spaces between the bars in a bar
    - * chart.
    - * NOTE: If the space between groups is specified but the space between
    - *     bars is left undefined, the space between groups will be interpreted
    - *     as the space between bars because this is the behavior exposed
    - *     in the external developers guide.
    - * @param {number} barWidth The width of a bar in pixels.
    - * @param {number=} opt_spaceBars The width of the space between
    - *     bars in a group in pixels.
    - * @param {number=} opt_spaceGroups The width of the space between
    - *     groups.
    - */
    -goog.ui.ServerChart.prototype.setBarSpaceWidths = function(barWidth,
    -                                                           opt_spaceBars,
    -                                                           opt_spaceGroups) {
    -  var widths = [barWidth];
    -  if (goog.isDef(opt_spaceBars)) {
    -    widths.push(opt_spaceBars);
    -  }
    -  if (goog.isDef(opt_spaceGroups)) {
    -    widths.push(opt_spaceGroups);
    -  }
    -  this.uri_.setParameterValue(goog.ui.ServerChart.UriParam.BAR_HEIGHT,
    -                              widths.join(','));
    -};
    -
    -
    -/**
    - * Specifies that the bar width in a bar chart should be calculated
    - * automatically given the space available in the chart, while optionally
    - * setting the spaces between the bars.
    - * NOTE: If the space between groups is specified but the space between
    - *     bars is left undefined, the space between groups will be interpreted
    - *     as the space between bars because this is the behavior exposed
    - *     in the external developers guide.
    - * @param {number=} opt_spaceBars The width of the space between
    - *     bars in a group in pixels.
    - * @param {number=} opt_spaceGroups The width of the space between
    - *     groups.
    - */
    -goog.ui.ServerChart.prototype.setAutomaticBarWidth = function(opt_spaceBars,
    -                                                              opt_spaceGroups) {
    -  var widths = ['a'];
    -  if (goog.isDef(opt_spaceBars)) {
    -    widths.push(opt_spaceBars);
    -  }
    -  if (goog.isDef(opt_spaceGroups)) {
    -    widths.push(opt_spaceGroups);
    -  }
    -  this.uri_.setParameterValue(goog.ui.ServerChart.UriParam.BAR_HEIGHT,
    -                              widths.join(','));
    -};
    -
    -
    -/**
    - * Adds a multi-axis to the chart, and sets its type. Multiple axes of the same
    - * type can be added.
    - *
    - * @param {goog.ui.ServerChart.MultiAxisType} axisType The desired axis type.
    - * @return {number} The index of the newly inserted axis, suitable for feeding
    - *     to the setMultiAxis*() functions.
    - */
    -goog.ui.ServerChart.prototype.addMultiAxis = function(axisType) {
    -  this.multiAxisType_.push(axisType);
    -  this.uri_.setParameterValue(goog.ui.ServerChart.UriParam.MULTI_AXIS_TYPES,
    -                              this.multiAxisType_.join(','));
    -  return this.multiAxisType_.length - 1;
    -};
    -
    -
    -/**
    - * Returns the axis type for the given axis, or all of them in an array if the
    - * axis number is not given.
    - *
    - * @param {number=} opt_axisNumber The axis index, as returned by addMultiAxis.
    - * @return {goog.ui.ServerChart.MultiAxisType|
    - *     Array<goog.ui.ServerChart.MultiAxisType>}
    - *     The axis type for the given axis, or all of them in an array if the
    - *     axis number is not given.
    - */
    -goog.ui.ServerChart.prototype.getMultiAxisType = function(opt_axisNumber) {
    -  if (goog.isDef(opt_axisNumber)) {
    -    return this.multiAxisType_[opt_axisNumber];
    -  }
    -  return this.multiAxisType_;
    -};
    -
    -
    -/**
    - * Sets the label text (usually multiple values) for a given axis, overwriting
    - * any existing values.
    - *
    - * @param {number} axisNumber The axis index, as returned by addMultiAxis.
    - * @param {Array<string>} labelText The actual label text to be added.
    - */
    -goog.ui.ServerChart.prototype.setMultiAxisLabelText = function(axisNumber,
    -                                                               labelText) {
    -  this.multiAxisLabelText_[axisNumber] = labelText;
    -
    -  var axisString = this.computeMultiAxisDataString_(this.multiAxisLabelText_,
    -                                                    ':|',
    -                                                    '|',
    -                                                    '|');
    -  this.uri_.setParameterValue(
    -      goog.ui.ServerChart.UriParam.MULTI_AXIS_LABEL_TEXT,
    -      axisString);
    -};
    -
    -
    -/**
    - * Returns the label text, or all of them in a two-dimensional array if the
    - * axis number is not given.
    - *
    - * @param {number=} opt_axisNumber The axis index, as returned by addMultiAxis.
    - * @return {Object|Array<string>} The label text, or all of them in a
    - *     two-dimensional array if the axis number is not given.
    - */
    -goog.ui.ServerChart.prototype.getMultiAxisLabelText = function(opt_axisNumber) {
    -  if (goog.isDef(opt_axisNumber)) {
    -    return this.multiAxisLabelText_[opt_axisNumber];
    -  }
    -  return this.multiAxisLabelText_;
    -};
    -
    -
    -/**
    - * Sets the label positions for a given axis, overwriting any existing values.
    - * The label positions are assumed to be floating-point numbers within the
    - * range of the axis.
    - *
    - * @param {number} axisNumber The axis index, as returned by addMultiAxis.
    - * @param {Array<number>} labelPosition The actual label positions to be added.
    - */
    -goog.ui.ServerChart.prototype.setMultiAxisLabelPosition = function(
    -    axisNumber, labelPosition) {
    -  this.multiAxisLabelPosition_[axisNumber] = labelPosition;
    -
    -  var positionString = this.computeMultiAxisDataString_(
    -      this.multiAxisLabelPosition_,
    -      ',',
    -      ',',
    -      '|');
    -  this.uri_.setParameterValue(
    -      goog.ui.ServerChart.UriParam.MULTI_AXIS_LABEL_POSITION,
    -      positionString);
    -};
    -
    -
    -/**
    - * Returns the label positions for a given axis number, or all of them in a
    - * two-dimensional array if the axis number is not given.
    - *
    - * @param {number=} opt_axisNumber The axis index, as returned by addMultiAxis.
    - * @return {Object|Array<number>} The label positions for a given axis number,
    - *     or all of them in a two-dimensional array if the axis number is not
    - *     given.
    - */
    -goog.ui.ServerChart.prototype.getMultiAxisLabelPosition =
    -    function(opt_axisNumber) {
    -  if (goog.isDef(opt_axisNumber)) {
    -    return this.multiAxisLabelPosition_[opt_axisNumber];
    -  }
    -  return this.multiAxisLabelPosition_;
    -};
    -
    -
    -/**
    - * Sets the label range for a given axis, overwriting any existing range.
    - * The default range is from 0 to 100. If the start value is larger than the
    - * end value, the axis direction is reversed.  rangeStart and rangeEnd must
    - * be two different finite numbers.
    - *
    - * @param {number} axisNumber The axis index, as returned by addMultiAxis.
    - * @param {number} rangeStart The new start of the range.
    - * @param {number} rangeEnd The new end of the range.
    - * @param {number=} opt_interval The interval between axis labels.
    - */
    -goog.ui.ServerChart.prototype.setMultiAxisRange = function(axisNumber,
    -                                                           rangeStart,
    -                                                           rangeEnd,
    -                                                           opt_interval) {
    -  goog.asserts.assert(rangeStart != rangeEnd,
    -      'Range start and end cannot be the same value.');
    -  goog.asserts.assert(isFinite(rangeStart) && isFinite(rangeEnd),
    -      'Range start and end must be finite numbers.');
    -  this.multiAxisRange_[axisNumber] = [rangeStart, rangeEnd];
    -  if (goog.isDef(opt_interval)) {
    -    this.multiAxisRange_[axisNumber].push(opt_interval);
    -  }
    -  var rangeString = this.computeMultiAxisDataString_(this.multiAxisRange_,
    -      ',', ',', '|');
    -  this.uri_.setParameterValue(goog.ui.ServerChart.UriParam.MULTI_AXIS_RANGE,
    -      rangeString);
    -};
    -
    -
    -/**
    - * Returns the label range for a given axis number as a two-element array of
    - * (range start, range end), or all of them in a two-dimensional array if the
    - * axis number is not given.
    - *
    - * @param {number=} opt_axisNumber The axis index, as returned by addMultiAxis.
    - * @return {Object|Array<number>} The label range for a given axis number as a
    - *     two-element array of (range start, range end), or all of them in a
    - *     two-dimensional array if the axis number is not given.
    - */
    -goog.ui.ServerChart.prototype.getMultiAxisRange = function(opt_axisNumber) {
    -  if (goog.isDef(opt_axisNumber)) {
    -    return this.multiAxisRange_[opt_axisNumber];
    -  }
    -  return this.multiAxisRange_;
    -};
    -
    -
    -/**
    - * Sets the label style for a given axis, overwriting any existing style.
    - * The default style is as follows: Default is x-axis labels are centered, left
    - * hand y-axis labels are right aligned, right hand y-axis labels are left
    - * aligned. The font size and alignment are optional parameters.
    - *
    - * NOTE: The color string should NOT have a '#' at the beginning of it.
    - *
    - * @param {number} axisNumber The axis index, as returned by addMultiAxis.
    - * @param {string} color The hex value for this label's color.
    - * @param {number=} opt_fontSize The label font size, in pixels.
    - * @param {goog.ui.ServerChart.MultiAxisAlignment=} opt_alignment The label
    - *     alignment.
    - * @param {goog.ui.ServerChart.AxisDisplayType=} opt_axisDisplay The axis
    - *     line and ticks.
    - */
    -goog.ui.ServerChart.prototype.setMultiAxisLabelStyle = function(
    -    axisNumber, color, opt_fontSize, opt_alignment, opt_axisDisplay) {
    -  var style = [color];
    -  if (goog.isDef(opt_fontSize) || goog.isDef(opt_alignment)) {
    -    style.push(opt_fontSize || '');
    -  }
    -  if (goog.isDef(opt_alignment)) {
    -    style.push(opt_alignment);
    -  }
    -  if (opt_axisDisplay) {
    -    style.push(opt_axisDisplay);
    -  }
    -  this.multiAxisLabelStyle_[axisNumber] = style;
    -  var styleString = this.computeMultiAxisDataString_(this.multiAxisLabelStyle_,
    -                                                     ',',
    -                                                     ',',
    -                                                     '|');
    -  this.uri_.setParameterValue(
    -      goog.ui.ServerChart.UriParam.MULTI_AXIS_STYLE,
    -      styleString);
    -};
    -
    -
    -/**
    - * Returns the label style for a given axis number as a one- to three-element
    - * array, or all of them in a two-dimensional array if the axis number is not
    - * given.
    - *
    - * @param {number=} opt_axisNumber The axis index, as returned by addMultiAxis.
    - * @return {Object|Array<number>} The label style for a given axis number as a
    - *     one- to three-element array, or all of them in a two-dimensional array if
    - *     the axis number is not given.
    - */
    -goog.ui.ServerChart.prototype.getMultiAxisLabelStyle =
    -    function(opt_axisNumber) {
    -  if (goog.isDef(opt_axisNumber)) {
    -    return this.multiAxisLabelStyle_[opt_axisNumber];
    -  }
    -  return this.multiAxisLabelStyle_;
    -};
    -
    -
    -/**
    - * Adds a data set.
    - * NOTE: The color string should NOT have a '#' at the beginning of it.
    - *
    - * @param {Array<number|null>} data An array of numbers (values can be
    - *     NaN or null).
    - * @param {string} color The hex value for this data set's color.
    - * @param {string=} opt_legendText The legend text, if any, for this data
    - *     series. NOTE: If specified, all previously added data sets must also
    - *     have a legend text.
    - */
    -goog.ui.ServerChart.prototype.addDataSet = function(data,
    -                                                    color,
    -                                                    opt_legendText) {
    -  var dataMin = this.arrayMin_(data);
    -  if (dataMin < this.minValue_) {
    -    this.minValue_ = dataMin;
    -  }
    -
    -  var dataMax = this.arrayMax_(data);
    -  if (dataMax > this.maxValue_) {
    -    this.maxValue_ = dataMax;
    -  }
    -
    -  if (goog.isDef(opt_legendText)) {
    -    if (this.setLegendTexts_.length < this.dataSets_.length) {
    -      throw Error('Cannot start adding legends text after first element.');
    -    }
    -    this.setLegendTexts_.push(opt_legendText);
    -    this.uri_.setParameterValue(goog.ui.ServerChart.UriParam.LEGEND_TEXTS,
    -                                this.setLegendTexts_.join('|'));
    -  }
    -
    -  this.dataSets_.push(data);
    -  this.setColors_.push(color);
    -
    -  this.uri_.setParameterValue(goog.ui.ServerChart.UriParam.DATA_COLORS,
    -                              this.setColors_.join(','));
    -};
    -
    -
    -/**
    - * Clears the data sets from the graph. All data, including the colors and
    - * legend text, is cleared.
    - */
    -goog.ui.ServerChart.prototype.clearDataSets = function() {
    -  var queryData = this.uri_.getQueryData();
    -  queryData.remove(goog.ui.ServerChart.UriParam.LEGEND_TEXTS);
    -  queryData.remove(goog.ui.ServerChart.UriParam.DATA_COLORS);
    -  queryData.remove(goog.ui.ServerChart.UriParam.DATA);
    -  this.setLegendTexts_.length = 0;
    -  this.setColors_.length = 0;
    -  this.dataSets_.length = 0;
    -};
    -
    -
    -/**
    - * Returns the given data set or all of them in a two-dimensional array if
    - * the set number is not given.
    - *
    - * @param {number=} opt_setNumber Optional data set number to get.
    - * @return {Array<?>} The given data set or all of them in a two-dimensional
    - *     array if the set number is not given.
    - */
    -goog.ui.ServerChart.prototype.getData = function(opt_setNumber) {
    -  if (goog.isDef(opt_setNumber)) {
    -    return this.dataSets_[opt_setNumber];
    -  }
    -  return this.dataSets_;
    -};
    -
    -
    -/**
    - * Computes the data string using the data in this.dataSets_ and sets
    - * the object's URI accordingly. If the URI's length equals or exceeds the
    - * limit, goog.ui.ServerChart.UriTooLongEvent is dispatched on the
    - * goog.ui.ServerChart object.
    - * @private
    - */
    -goog.ui.ServerChart.prototype.computeDataString_ = function() {
    -  var ok;
    -  if (this.encodingType_ != goog.ui.ServerChart.EncodingType.AUTOMATIC) {
    -    ok = this.computeDataStringForEncoding_(this.encodingType_);
    -  } else {
    -    ok = this.computeDataStringForEncoding_(
    -        goog.ui.ServerChart.EncodingType.EXTENDED);
    -    if (!ok) {
    -      ok = this.computeDataStringForEncoding_(
    -          goog.ui.ServerChart.EncodingType.SIMPLE);
    -    }
    -  }
    -  if (!ok) {
    -    this.dispatchEvent(
    -        new goog.ui.ServerChart.UriTooLongEvent(this.uri_.toString()));
    -  }
    -};
    -
    -
    -/**
    - * Computes the data string using the data in this.dataSets_ and the encoding
    - * specified by the encoding parameter, which must not be AUTOMATIC, and sets
    - * the object's URI accordingly.
    - * @param {goog.ui.ServerChart.EncodingType} encoding The data encoding to use;
    - *     must not be AUTOMATIC.
    - * @return {boolean} False if the resulting URI is too long.
    - * @private
    - */
    -goog.ui.ServerChart.prototype.computeDataStringForEncoding_ = function(
    -    encoding) {
    -  var dataStrings = [];
    -  for (var i = 0, setLen = this.dataSets_.length; i < setLen; ++i) {
    -    dataStrings[i] = this.getChartServerValues_(this.dataSets_[i],
    -                                                this.minValue_,
    -                                                this.maxValue_,
    -                                                encoding);
    -  }
    -  var delimiter = encoding == goog.ui.ServerChart.EncodingType.TEXT ? '|' : ',';
    -  dataStrings = dataStrings.join(delimiter);
    -  var data;
    -  if (this.numVisibleDataSets_ == null) {
    -    data = goog.string.buildString(encoding, ':', dataStrings);
    -  } else {
    -    data = goog.string.buildString(encoding, this.numVisibleDataSets_, ':',
    -        dataStrings);
    -  }
    -  this.uri_.setParameterValue(goog.ui.ServerChart.UriParam.DATA, data);
    -  return this.uri_.toString().length < this.uriLengthLimit_;
    -};
    -
    -
    -/**
    - * Computes a multi-axis data string from the given data and separators. The
    - * general data format for each index/element in the array will be
    - * "<arrayIndex><indexSeparator><arrayElement.join(elementSeparator)>", with
    - * axisSeparator used between multiple elements.
    - * @param {Object} data The data to compute the data string for, as a
    - *     sparse array of arrays. NOTE: The function uses the length of
    - *     multiAxisType_ to determine the upper bound for the outer array.
    - * @param {string} indexSeparator The separator string inserted between each
    - *     index and the data itself, commonly a comma (,).
    - * @param {string} elementSeparator The separator string inserted between each
    - *     element inside each sub-array in the data, if there are more than one;
    - *     commonly a comma (,).
    - * @param {string} axisSeparator The separator string inserted between each
    - *     axis specification, if there are more than one; usually a pipe sign (|).
    - * @return {string} The multi-axis data string.
    - * @private
    - */
    -goog.ui.ServerChart.prototype.computeMultiAxisDataString_ = function(
    -    data,
    -    indexSeparator,
    -    elementSeparator,
    -    axisSeparator) {
    -  var elementStrings = [];
    -  for (var i = 0, setLen = this.multiAxisType_.length; i < setLen; ++i) {
    -    if (data[i]) {
    -      elementStrings.push(i + indexSeparator + data[i].join(elementSeparator));
    -    }
    -  }
    -  return elementStrings.join(axisSeparator);
    -};
    -
    -
    -/**
    - * Array of possible ChartServer data values
    - * @type {string}
    - */
    -goog.ui.ServerChart.CHART_VALUES = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
    -                                   'abcdefghijklmnopqrstuvwxyz' +
    -                                   '0123456789';
    -
    -
    -/**
    - * Array of extended ChartServer data values
    - * @type {string}
    - */
    -goog.ui.ServerChart.CHART_VALUES_EXTENDED = goog.ui.ServerChart.CHART_VALUES +
    -                                            '-.';
    -
    -
    -/**
    - * Upper bound for extended values
    - */
    -goog.ui.ServerChart.EXTENDED_UPPER_BOUND =
    -    Math.pow(goog.ui.ServerChart.CHART_VALUES_EXTENDED.length, 2) - 1;
    -
    -
    -/**
    - * Converts a single number to an encoded data value suitable for ChartServer.
    - * The TEXT encoding is the number in decimal; the SIMPLE encoding is a single
    - * character, and the EXTENDED encoding is two characters.  See
    - * https://developers.google.com/chart/image/docs/data_formats for the detailed
    - * specification of these encoding formats.
    - *
    - * @private
    - * @param {?number} value The value to convert (null for a missing data point).
    - * @param {number} minValue The minimum value (used for normalization).
    - * @param {number} maxValue The maximum value (used for normalization).
    - * @param {goog.ui.ServerChart.EncodingType} encoding The data encoding to use;
    - *     must not be AUTOMATIC.
    - * @return {string} The encoded data value.
    - */
    -goog.ui.ServerChart.prototype.getConvertedValue_ = function(value,
    -                                                            minValue,
    -                                                            maxValue,
    -                                                            encoding) {
    -  goog.asserts.assert(minValue <= maxValue,
    -      'minValue should be less than or equal to maxValue');
    -  var isExtended = (encoding == goog.ui.ServerChart.EncodingType.EXTENDED);
    -
    -  if (goog.isNull(value) || !goog.isDef(value) || isNaN(value) ||
    -      value < minValue || value > maxValue) {
    -    return isExtended ? '__' : '_';
    -  }
    -
    -  if (encoding == goog.ui.ServerChart.EncodingType.TEXT) {
    -    return String(value);
    -  }
    -
    -  var frac = goog.ui.ServerChart.DEFAULT_NORMALIZATION;
    -  if (maxValue > minValue) {
    -    frac = (value - minValue) / (maxValue - minValue);
    -    // Previous checks of value ensure that 0 <= frac <= 1 at this point.
    -  }
    -
    -  if (isExtended) {
    -    var maxIndex = goog.ui.ServerChart.CHART_VALUES_EXTENDED.length;
    -    var upperBound = goog.ui.ServerChart.EXTENDED_UPPER_BOUND;
    -    var index1 = Math.floor(frac * upperBound / maxIndex);
    -    var index2 = Math.floor((frac * upperBound) % maxIndex);
    -    var extendedVals = goog.ui.ServerChart.CHART_VALUES_EXTENDED;
    -    return extendedVals.charAt(index1) + extendedVals.charAt(index2);
    -  }
    -
    -  var index = Math.round(frac * (goog.ui.ServerChart.CHART_VALUES.length - 1));
    -  return goog.ui.ServerChart.CHART_VALUES.charAt(index);
    -};
    -
    -
    -/**
    - * Creates the chd string for chartserver.
    - *
    - * @private
    - * @param {Array<number>} values An array of numbers to graph.
    - * @param {number} minValue The minimum value (used for normalization).
    - * @param {number} maxValue The maximum value (used for normalization).
    - * @param {goog.ui.ServerChart.EncodingType} encoding The data encoding to use;
    - *     must not be AUTOMATIC.
    - * @return {string} The chd string for chartserver.
    - */
    -goog.ui.ServerChart.prototype.getChartServerValues_ = function(values,
    -                                                               minValue,
    -                                                               maxValue,
    -                                                               encoding) {
    -  var s = [];
    -  for (var i = 0, valuesLen = values.length; i < valuesLen; ++i) {
    -    s.push(this.getConvertedValue_(values[i], minValue,
    -                                   maxValue, encoding));
    -  }
    -  return s.join(
    -      this.encodingType_ == goog.ui.ServerChart.EncodingType.TEXT ? ',' : '');
    -};
    -
    -
    -/**
    - * Finds the minimum value in an array and returns it.
    - * Needed because Math.min does not handle sparse arrays the way we want.
    - *
    - * @param {Array<number?>} ary An array of values.
    - * @return {number} The minimum value.
    - * @private
    - */
    -goog.ui.ServerChart.prototype.arrayMin_ = function(ary) {
    -  var min = Infinity;
    -  for (var i = 0, aryLen = ary.length; i < aryLen; ++i) {
    -    var value = ary[i];
    -    if (value != null && value < min) {
    -      min = value;
    -    }
    -  }
    -  return min;
    -};
    -
    -
    -/**
    - * Finds the maximum value in an array and returns it.
    - * Needed because Math.max does not handle sparse arrays the way we want.
    - *
    - * @param {Array<number?>} ary An array of values.
    - * @return {number} The maximum value.
    - * @private
    - */
    -goog.ui.ServerChart.prototype.arrayMax_ = function(ary) {
    -  var max = -Infinity;
    -  for (var i = 0, aryLen = ary.length; i < aryLen; ++i) {
    -    var value = ary[i];
    -    if (value != null && value > max) {
    -      max = value;
    -    }
    -  }
    -  return max;
    -};
    -
    -
    -/** @override */
    -goog.ui.ServerChart.prototype.disposeInternal = function() {
    -  goog.ui.ServerChart.superClass_.disposeInternal.call(this);
    -  delete this.xLabels_;
    -  delete this.leftLabels_;
    -  delete this.rightLabels_;
    -  delete this.gridX_;
    -  delete this.gridY_;
    -  delete this.setColors_;
    -  delete this.setLegendTexts_;
    -  delete this.dataSets_;
    -  this.uri_ = null;
    -  delete this.minValue_;
    -  delete this.maxValue_;
    -  this.title_ = null;
    -  delete this.multiAxisType_;
    -  delete this.multiAxisLabelText_;
    -  delete this.multiAxisLabelPosition_;
    -  delete this.multiAxisRange_;
    -  delete this.multiAxisLabelStyle_;
    -  this.legend_ = null;
    -};
    -
    -
    -/**
    - * Event types dispatched by the ServerChart object
    - * @enum {string}
    - */
    -goog.ui.ServerChart.Event = {
    -  /**
    -   * Dispatched when the resulting URI reaches or exceeds the URI length limit.
    -   */
    -  URI_TOO_LONG: 'uritoolong'
    -};
    -
    -
    -
    -/**
    - * Class for the event dispatched on the ServerChart when the resulting URI
    - * exceeds the URI length limit.
    - * @constructor
    - * @param {string} uri The overly-long URI string.
    - * @extends {goog.events.Event}
    - * @final
    - */
    -goog.ui.ServerChart.UriTooLongEvent = function(uri) {
    -  goog.events.Event.call(this, goog.ui.ServerChart.Event.URI_TOO_LONG);
    -
    -  /**
    -   * The overly-long URI string.
    -   * @type {string}
    -   */
    -  this.uri = uri;
    -};
    -goog.inherits(goog.ui.ServerChart.UriTooLongEvent, goog.events.Event);
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/serverchart_test.html b/src/database/third_party/closure-library/closure/goog/ui/serverchart_test.html
    deleted file mode 100644
    index 09ca81494cf..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/serverchart_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.serverchart
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.ServerChartTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/serverchart_test.js b/src/database/third_party/closure-library/closure/goog/ui/serverchart_test.js
    deleted file mode 100644
    index ef75fa93193..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/serverchart_test.js
    +++ /dev/null
    @@ -1,635 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.ServerChartTest');
    -goog.setTestOnly('goog.ui.ServerChartTest');
    -
    -goog.require('goog.Uri');
    -goog.require('goog.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.ServerChart');
    -
    -function testSchemeIndependentBarChartRequest() {
    -  var bar = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.BAR,
    -      180,
    -      104,
    -      null);
    -  tryToCreateBarChart(bar);
    -  var uri = bar.getUri();
    -  var schemeIndependentUri = new goog.Uri(
    -      goog.ui.ServerChart.CHART_SERVER_SCHEME_INDEPENDENT_URI);
    -  assertEquals('', uri.getScheme());
    -  assertEquals(schemeIndependentUri.getDomain(), uri.getDomain());
    -}
    -
    -function testHttpBarChartRequest() {
    -  var bar = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.BAR,
    -      180,
    -      104,
    -      null,
    -      goog.ui.ServerChart.CHART_SERVER_HTTP_URI);
    -  tryToCreateBarChart(bar);
    -  var uri = bar.getUri();
    -  var httpUri = new goog.Uri(goog.ui.ServerChart.CHART_SERVER_HTTP_URI);
    -  assertEquals('http', uri.getScheme());
    -  assertEquals(httpUri.getDomain(), uri.getDomain());
    -}
    -
    -function testHttpsBarChartRequest() {
    -  var bar = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.BAR,
    -      180,
    -      104,
    -      null,
    -      goog.ui.ServerChart.CHART_SERVER_HTTPS_URI);
    -  tryToCreateBarChart(bar);
    -  var uri = bar.getUri();
    -  var httpsUri = new goog.Uri(goog.ui.ServerChart.CHART_SERVER_HTTPS_URI);
    -  assertEquals('https', uri.getScheme());
    -  assertEquals(httpsUri.getDomain(), uri.getDomain());
    -}
    -
    -function testMinValue() {
    -  var pie = new goog.ui.ServerChart(goog.ui.ServerChart.ChartType.PIE3D,
    -      180, 104);
    -  pie.addDataSet([1, 2, 3], '000000');
    -  assertEquals(pie.getMinValue(), 0);
    -
    -  var line = new goog.ui.ServerChart(goog.ui.ServerChart.ChartType.LINE,
    -      180, 104);
    -  line.addDataSet([1, 2, 3], '000000');
    -  assertEquals(line.getMinValue(), 1);
    -}
    -
    -function testMargins() {
    -  var pie = new goog.ui.ServerChart(goog.ui.ServerChart.ChartType.PIE3D,
    -      180, 104);
    -  pie.setMargins(1, 2, 3, 4);
    -  assertEquals('1,2,3,4',
    -      pie.getUri().getParameterValue(goog.ui.ServerChart.UriParam.MARGINS));
    -}
    -
    -function testSetParameterValue() {
    -  var scatter = new goog.ui.ServerChart(goog.ui.ServerChart.ChartType.SCATTER,
    -      180, 104);
    -  var key = goog.ui.ServerChart.UriParam.DATA_COLORS;
    -  var value = '000000,FF0000|00FF00|0000FF';
    -  scatter.setParameterValue(key, value);
    -
    -  assertEquals('unexpected parameter value', value,
    -      scatter.getUri().getParameterValue(key));
    -
    -  scatter.removeParameter(key);
    -
    -  assertUndefined('parameter not removed',
    -      scatter.getUri().getParameterValue(key));
    -}
    -
    -function testTypes() {
    -  var chart;
    -
    -  chart = new goog.ui.ServerChart(goog.ui.ServerChart.ChartType.CONCENTRIC_PIE,
    -      180, 104);
    -
    -  assertTrue(chart.isPieChart());
    -  assertFalse(chart.isBarChart());
    -  assertFalse(chart.isMap());
    -  assertFalse(chart.isLineChart());
    -
    -  chart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.HORIZONTAL_GROUPED_BAR, 180, 104);
    -
    -  assertFalse(chart.isPieChart());
    -  assertTrue(chart.isBarChart());
    -  assertTrue(chart.isHorizontalBarChart());
    -  assertTrue(chart.isGroupedBarChart());
    -  assertFalse(chart.isVerticalBarChart());
    -  assertFalse(chart.isStackedBarChart());
    -
    -  chart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.BAR, 180, 104);
    -  assertTrue(chart.isBarChart());
    -  assertTrue(chart.isStackedBarChart());
    -  assertFalse(chart.isGroupedBarChart());
    -
    -  chart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.XYLINE, 180, 104);
    -  assertTrue('I thought lxy was a line chart', chart.isLineChart());
    -  assertFalse('lxy is definitely not a pie chart', chart.isPieChart());
    -}
    -
    -function testBarChartRequest() {
    -  var bar = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.BAR, 180, 104);
    -  tryToCreateBarChart(bar);
    -  var httpUri = new goog.Uri(goog.ui.ServerChart.CHART_SERVER_URI);
    -  var uri = bar.getUri();
    -  assertEquals(httpUri.getDomain(), uri.getDomain());
    -}
    -
    -function tryToCreateBarChart(bar) {
    -  bar.addDataSet([8, 23, 7], '008000');
    -  bar.addDataSet([31, 11, 7], 'ffcc33');
    -  bar.addDataSet([2, 43, 70, 3, 43, 74], '3072f3');
    -  bar.setLeftLabels(['', '20K', '', '60K', '', '100K']);
    -  bar.setXLabels(['O', 'N', 'D']);
    -  bar.setMaxValue(100);
    -  var uri = bar.getUri();
    -  assertEquals(
    -      'br',
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.TYPE));
    -  assertEquals(
    -      '180x104',
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.SIZE));
    -  assertEquals(
    -      'e:D6NtDQ,S7F4DQ,AAaxsZApaxvA',
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.DATA));
    -  assertEquals(
    -      '008000,ffcc33,3072f3',
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.DATA_COLORS));
    -  assertEquals(
    -      '100K||60K||20K|',
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.LEFT_Y_LABELS));
    -  assertEquals(
    -      'O|N|D',
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.X_LABELS));
    -}
    -
    -function testClearDataSets() {
    -  var chart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.BAR, 180, 104);
    -  tryToCreateBarChart(chart);
    -  var uriBefore = chart.getUri();
    -  chart.clearDataSets();
    -  var chart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.BAR, 180, 104);
    -  tryToCreateBarChart(chart);
    -  var uriAfter = chart.getUri();
    -  assertEquals(uriBefore.getScheme(), uriAfter.getScheme());
    -  assertEquals(uriBefore.getDomain(), uriAfter.getDomain());
    -  assertEquals(uriBefore.getPath(), uriAfter.getPath());
    -}
    -
    -function testMultipleDatasetsTextEncoding() {
    -  var chart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.BAR, 180, 104);
    -  chart.setEncodingType(goog.ui.ServerChart.EncodingType.TEXT);
    -  chart.addDataSet([0, 25, 100], '008000');
    -  chart.addDataSet([12, 2, 7.1], '112233');
    -  chart.addDataSet([82, 16, 2], '3072f3');
    -  var uri = chart.getUri();
    -  assertEquals(
    -      't:0,25,100|12,2,7.1|82,16,2',
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.DATA));
    -}
    -
    -function testVennDiagramRequest() {
    -  var venn = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.VENN, 300, 200);
    -  venn.setTitle('Google Employees');
    -  var weights = [80,  // Size of circle A
    -                 60,  // Size of circle B
    -                 40,  // Size of circle C
    -                 20,  // Overlap of A and B
    -                 20,  // Overlap of A and C
    -                 20,  // Overlap of B and C
    -                 5];  // Overlap of A, B and C
    -  var labels = [
    -    'C Hackers',      // Label for A
    -    'LISP Gurus',     // Label for B
    -    'Java Jockeys'];  // Label for C
    -  venn.setVennSeries(weights, labels);
    -  var uri = venn.getUri();
    -  var httpUri = new goog.Uri(goog.ui.ServerChart.CHART_SERVER_URI);
    -  assertEquals(httpUri.getDomain(), uri.getDomain());
    -  assertEquals(
    -      'v',
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.TYPE));
    -  assertEquals(
    -      '300x200',
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.SIZE));
    -  assertEquals(
    -      'e:..u7d3MzMzMzAA',
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.DATA));
    -  assertEquals(
    -      'Google Employees',
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.TITLE));
    -  assertEquals(
    -      labels.join('|'),
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.LEGEND_TEXTS));
    -}
    -
    -
    -function testSparklineChartRequest() {
    -  var chart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.SPARKLINE, 300, 200);
    -  chart.addDataSet([8, 23, 7], '008000');
    -  chart.addDataSet([31, 11, 7], 'ffcc33');
    -  chart.addDataSet([2, 43, 70, 3, 43, 74], '3072f3');
    -  chart.setLeftLabels(['', '20K', '', '60K', '', '100K']);
    -  chart.setXLabels(['O', 'N', 'D']);
    -  chart.setMaxValue(100);
    -  var uri = chart.getUri();
    -  assertEquals(
    -      'ls',
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.TYPE));
    -  assertEquals(
    -      '300x200',
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.SIZE));
    -  assertEquals(
    -      'e:D6NtDQ,S7F4DQ,AAaxsZApaxvA',
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.DATA));
    -  assertEquals(
    -      '008000,ffcc33,3072f3',
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.DATA_COLORS));
    -  assertEquals(
    -      '100K||60K||20K|',
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.LEFT_Y_LABELS));
    -  assertEquals(
    -      'O|N|D',
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.X_LABELS));
    -}
    -
    -function testLegendPositionRequest() {
    -  var chart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.SPARKLINE, 300, 200);
    -  chart.addDataSet([0, 100], '008000', 'foo');
    -  chart.setLegendPosition(goog.ui.ServerChart.LegendPosition.TOP);
    -  assertEquals('t', chart.getLegendPosition());
    -  var uri = chart.getUri();
    -  assertEquals(
    -      't',
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.LEGEND_POSITION));
    -}
    -
    -function testSetGridParameter() {
    -  var gridArg = '20,20,4,4';
    -  var chart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.SPARKLINE, 300, 200);
    -  chart.addDataSet([0, 100], '008000', 'foo');
    -  chart.setGridParameter(gridArg);
    -  assertEquals(gridArg, chart.getGridParameter());
    -  var uri = chart.getUri();
    -  assertEquals(
    -      gridArg,
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.GRID));
    -}
    -
    -function testSetMarkerParameter() {
    -  var markerArg = 's,FF0000,0,-1,5';
    -  var chart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.SPARKLINE, 300, 200);
    -  chart.addDataSet([0, 100], '008000', 'foo');
    -  chart.setMarkerParameter(markerArg);
    -  assertEquals(markerArg, chart.getMarkerParameter());
    -  var uri = chart.getUri();
    -  assertEquals(
    -      markerArg,
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.MARKERS));
    -}
    -
    -function testNullDataPointRequest() {
    -  var chart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.SPARKLINE, 300, 200);
    -  chart.addDataSet([40, null, 10], '008000');
    -  assertEquals(10, chart.getMinValue());
    -  assertEquals(40, chart.getMaxValue());
    -  var uri = chart.getUri();
    -  assertEquals(
    -      'e:..__AA',
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.DATA));
    -
    -  chart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.SPARKLINE, 300, 200);
    -  chart.addDataSet([-5, null, -1], '008000');
    -  assertEquals(-5, chart.getMinValue());
    -  assertEquals(-1, chart.getMaxValue());
    -  uri = chart.getUri();
    -  assertEquals(
    -      'e:AA__..',
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.DATA));
    -}
    -
    -function testSetBarSpaceWidths() {
    -  var noSpaceBetweenBarsSpecified = '20';
    -  var noSpaceBetweenBarsChart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.VERTICAL_STACKED_BAR);
    -  noSpaceBetweenBarsChart.setBarSpaceWidths(20);
    -  var uri = noSpaceBetweenBarsChart.getUri();
    -  assertEquals(noSpaceBetweenBarsSpecified,
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.BAR_HEIGHT));
    -
    -  var spaceBetweenBarsSpecified = '20,5';
    -  var spaceBetweenBarsChart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.HORIZONTAL_STACKED_BAR);
    -  spaceBetweenBarsChart.setBarSpaceWidths(20, 5);
    -  var uri = spaceBetweenBarsChart.getUri();
    -  assertEquals(spaceBetweenBarsSpecified,
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.BAR_HEIGHT));
    -
    -  var spaceBetweenGroupsSpecified = '20,5,6';
    -  var spaceBetweenGroupsChart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.HORIZONTAL_STACKED_BAR);
    -  spaceBetweenGroupsChart.setBarSpaceWidths(20, 5, 6);
    -  var uri = spaceBetweenGroupsChart.getUri();
    -  assertEquals(spaceBetweenGroupsSpecified,
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.BAR_HEIGHT));
    -
    -  var groupsButNotBarsSpecified = '20,6';
    -  var groupsButNotBarsChart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.HORIZONTAL_STACKED_BAR);
    -  groupsButNotBarsChart.setBarSpaceWidths(20, undefined, 6);
    -  var uri = groupsButNotBarsChart.getUri();
    -  assertEquals(groupsButNotBarsSpecified,
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.BAR_HEIGHT));
    -}
    -
    -function testSetAutomaticBarWidth() {
    -  var noSpaceBetweenBarsSpecified = 'a';
    -  var noSpaceBetweenBarsChart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.VERTICAL_STACKED_BAR);
    -  noSpaceBetweenBarsChart.setAutomaticBarWidth();
    -  var uri = noSpaceBetweenBarsChart.getUri();
    -  assertEquals(noSpaceBetweenBarsSpecified,
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.BAR_HEIGHT));
    -
    -  var spaceBetweenBarsSpecified = 'a,5';
    -  var spaceBetweenBarsChart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.HORIZONTAL_STACKED_BAR);
    -  spaceBetweenBarsChart.setAutomaticBarWidth(5);
    -  uri = spaceBetweenBarsChart.getUri();
    -  assertEquals(spaceBetweenBarsSpecified,
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.BAR_HEIGHT));
    -
    -  var spaceBetweenGroupsSpecified = 'a,5,6';
    -  var spaceBetweenGroupsChart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.HORIZONTAL_STACKED_BAR);
    -  spaceBetweenGroupsChart.setAutomaticBarWidth(5, 6);
    -  uri = spaceBetweenGroupsChart.getUri();
    -  assertEquals(spaceBetweenGroupsSpecified,
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.BAR_HEIGHT));
    -
    -  var groupsButNotBarsSpecified = 'a,6';
    -  var groupsButNotBarsChart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.HORIZONTAL_STACKED_BAR);
    -  groupsButNotBarsChart.setAutomaticBarWidth(undefined, 6);
    -  uri = groupsButNotBarsChart.getUri();
    -  assertEquals(groupsButNotBarsSpecified,
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.BAR_HEIGHT));
    -}
    -
    -function testSetDataScaling() {
    -  var dataScalingArg = '0,160';
    -  var dataArg = 't:0,50,100,130';
    -  var chart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.VERTICAL_STACKED_BAR, 300, 200);
    -  chart.addDataSet([0, 50, 100, 130], '008000');
    -  chart.setDataScaling(0, 160);
    -  var uri = chart.getUri();
    -  assertEquals(dataScalingArg,
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.DATA_SCALING));
    -  assertEquals(
    -      dataArg,
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.DATA));
    -}
    -
    -function testSetMultiAxisLabelStyle() {
    -  var noFontSizeChart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.HORIZONTAL_STACKED_BAR, 300, 200);
    -  noFontSizeChart.addDataSet([0, 50, 100, 130], '008000');
    -  var axisNumber = noFontSizeChart.addMultiAxis(
    -      goog.ui.ServerChart.MultiAxisType.LEFT_Y_AXIS);
    -  var noFontSizeArgs = axisNumber + ',009000';
    -  noFontSizeChart.setMultiAxisLabelStyle(axisNumber, '009000');
    -  var noFontSizeUri = noFontSizeChart.getUri();
    -  assertEquals(noFontSizeArgs,
    -      noFontSizeUri.getParameterValue(
    -          goog.ui.ServerChart.UriParam.MULTI_AXIS_STYLE));
    -
    -  var noAlignChart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.HORIZONTAL_STACKED_BAR, 300, 200);
    -  noAlignChart.addDataSet([0, 50, 100, 130], '008000');
    -  var xAxisNumber = noAlignChart.addMultiAxis(
    -      goog.ui.ServerChart.MultiAxisType.X_AXIS);
    -  var yAxisNumber = noAlignChart.addMultiAxis(
    -      goog.ui.ServerChart.MultiAxisType.LEFT_Y_AXIS);
    -  var noAlignArgs = xAxisNumber + ',009000,12|' + yAxisNumber + ',007000,14';
    -  noAlignChart.setMultiAxisLabelStyle(xAxisNumber, '009000', 12);
    -  noAlignChart.setMultiAxisLabelStyle(yAxisNumber, '007000', 14);
    -  var noAlignUri = noAlignChart.getUri();
    -  assertEquals(noAlignArgs,
    -      noAlignUri.getParameterValue(
    -          goog.ui.ServerChart.UriParam.MULTI_AXIS_STYLE));
    -
    -  var noLineTicksChart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.HORIZONTAL_STACKED_BAR, 300, 200);
    -  noLineTicksChart.addDataSet([0, 50, 100, 130], '008000');
    -  axisNumber = noLineTicksChart.addMultiAxis(
    -      goog.ui.ServerChart.MultiAxisType.LEFT_Y_AXIS);
    -  var noLineTicksArgs = axisNumber + ',009000,12,0';
    -  noLineTicksChart.setMultiAxisLabelStyle(axisNumber, '009000', 12,
    -      goog.ui.ServerChart.MultiAxisAlignment.ALIGN_CENTER);
    -  var noLineTicksUri = noLineTicksChart.getUri();
    -  assertEquals(noLineTicksArgs,
    -      noLineTicksUri.getParameterValue(
    -          goog.ui.ServerChart.UriParam.MULTI_AXIS_STYLE));
    -
    -
    -  var allParamsChart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.HORIZONTAL_STACKED_BAR, 300, 200);
    -  allParamsChart.addDataSet([0, 50, 100, 130], '008000');
    -  axisNumber = allParamsChart.addMultiAxis(
    -      goog.ui.ServerChart.MultiAxisType.LEFT_Y_AXIS);
    -  var allParamsArgs = axisNumber + ',009000,12,0,lt';
    -  allParamsChart.setMultiAxisLabelStyle(axisNumber, '009000', 12,
    -      goog.ui.ServerChart.MultiAxisAlignment.ALIGN_CENTER,
    -      goog.ui.ServerChart.AxisDisplayType.LINE_AND_TICKS);
    -  var allParamsUri = allParamsChart.getUri();
    -  assertEquals(allParamsArgs,
    -      allParamsUri.getParameterValue(
    -          goog.ui.ServerChart.UriParam.MULTI_AXIS_STYLE));
    -}
    -
    -function testSetBackgroundFill() {
    -  var chart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.HORIZONTAL_STACKED_BAR, 300, 200);
    -  assertEquals(0, chart.getBackgroundFill().length);
    -  chart.setBackgroundFill([{color: '00ff00'}]);
    -  assertObjectEquals({
    -    area: 'bg',
    -    effect: 's',
    -    color: '00ff00'}, chart.getBackgroundFill()[0]);
    -  chart.setBackgroundFill([
    -    {color: '00ff00'},
    -    {area: 'c', color: '00ff00'}
    -  ]);
    -  assertObjectEquals({
    -    area: 'bg',
    -    effect: 's',
    -    color: '00ff00'}, chart.getBackgroundFill()[0]);
    -  assertObjectEquals({
    -    area: 'c',
    -    effect: 's',
    -    color: '00ff00'}, chart.getBackgroundFill()[1]);
    -
    -  chart.setParameterValue(goog.ui.ServerChart.UriParam.BACKGROUND_FILL,
    -      'bg,s,00ff00|c,lg,45,ff00ff|bg,s,ff00ff');
    -  assertEquals(0, chart.getBackgroundFill().length);
    -}
    -
    -function testSetMultiAxisRange() {
    -  var chart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.HORIZONTAL_STACKED_BAR, 300, 200);
    -  var x = chart.addMultiAxis(goog.ui.ServerChart.MultiAxisType.X_AXIS);
    -  var top = chart.addMultiAxis(goog.ui.ServerChart.MultiAxisType.TOP_AXIS);
    -  chart.setMultiAxisRange(x, -500, 500, 100);
    -  chart.setMultiAxisRange(top, 0, 10);
    -  var range = chart.getMultiAxisRange();
    -
    -  assertArrayEquals(range[x], [-500, 500, 100]);
    -  assertArrayEquals(range[top], [0, 10]);
    -}
    -
    -function testGetConvertedValue() {
    -  var chart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.VERTICAL_STACKED_BAR);
    -
    -  assertThrows('No exception thrown when minValue > maxValue', function() {
    -    var result = chart.getConvertedValue_(
    -        90, 24, 3, goog.ui.ServerChart.EncodingType.SIMPLE);
    -  });
    -
    -  assertEquals('_', chart.getConvertedValue_(90, 100, 101,
    -      goog.ui.ServerChart.EncodingType.SIMPLE));
    -
    -  assertEquals('_', chart.getConvertedValue_(
    -      null, 0, 5, goog.ui.ServerChart.EncodingType.SIMPLE));
    -  assertEquals('__', chart.getConvertedValue_(
    -      null, 0, 150, goog.ui.ServerChart.EncodingType.EXTENDED));
    -  assertEquals('24', chart.getConvertedValue_(
    -      24, 1, 200, goog.ui.ServerChart.EncodingType.TEXT));
    -  assertEquals('H', chart.getConvertedValue_(
    -      24, 1, 200, goog.ui.ServerChart.EncodingType.SIMPLE));
    -  assertEquals('HZ', chart.getConvertedValue_(
    -      24, 1, 200, goog.ui.ServerChart.EncodingType.EXTENDED));
    -
    -  // Out-of-range values should give a missing data point, not an empty string.
    -  assertEquals('__', chart.getConvertedValue_(
    -      0, 1, 200, goog.ui.ServerChart.EncodingType.EXTENDED));
    -  assertEquals('__', chart.getConvertedValue_(
    -      201, 1, 200, goog.ui.ServerChart.EncodingType.EXTENDED));
    -  assertEquals('_', chart.getConvertedValue_(
    -      0, 1, 200, goog.ui.ServerChart.EncodingType.SIMPLE));
    -  assertEquals('_', chart.getConvertedValue_(
    -      201, 1, 200, goog.ui.ServerChart.EncodingType.SIMPLE));
    -  assertEquals('_', chart.getConvertedValue_(
    -      0, 1, 200, goog.ui.ServerChart.EncodingType.TEXT));
    -  assertEquals('_', chart.getConvertedValue_(
    -      201, 1, 200, goog.ui.ServerChart.EncodingType.TEXT));
    -}
    -
    -function testGetChartServerValues() {
    -  var chart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.HORIZONTAL_STACKED_BAR);
    -  var values = [0, 1, 2, 56, 90, 120];
    -  var minValue = 0;
    -  var maxValue = 140;
    -  var expectedSimple = 'AABYn0';
    -  assertEquals(expectedSimple,
    -      chart.getChartServerValues_(values, minValue, maxValue));
    -  var expectedText = '0,1,2,56,90,120';
    -  assertEquals(expectedSimple,
    -      chart.getChartServerValues_(values, minValue, maxValue));
    -}
    -
    -function testUriLengthLimit() {
    -  var chart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.SPARKLINE, 300, 200);
    -  var longUri = null;
    -  goog.events.listen(chart, goog.ui.ServerChart.Event.URI_TOO_LONG,
    -                     function(e) {longUri = e.uri;});
    -  assertEquals(goog.ui.ServerChart.EncodingType.AUTOMATIC,
    -      chart.getEncodingType());
    -  chart.addDataSet([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
    -      '008000');
    -  assertEquals(
    -      'e:AAHHOOVVccjjqqxx44..AAHHOOVVccjjqqxx44..',
    -      chart.getUri().getParameterValue(goog.ui.ServerChart.UriParam.DATA));
    -  chart.setUriLengthLimit(100);
    -  assertEquals(
    -      's:AHOUbipv29AHOUbipv29',
    -      chart.getUri().getParameterValue(goog.ui.ServerChart.UriParam.DATA));
    -  chart.setUriLengthLimit(80);
    -  assertEquals(null, longUri);
    -  chart.getUri();
    -  assertNotEquals(null, longUri);
    -}
    -
    -function testVisibleDataSets() {
    -  var uri;
    -
    -  var bar = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.BAR, 180, 104);
    -  bar.addDataSet([8, 23, 7], '008000');
    -  bar.addDataSet([31, 11, 7], 'ffcc33');
    -  bar.addDataSet([2, 43, 70, 3, 43, 74], '3072f3');
    -  bar.setMaxValue(100);
    -
    -  bar.setNumVisibleDataSets(0);
    -  uri = bar.getUri();
    -  assertEquals(
    -      'e0:D6NtDQ,S7F4DQ,AAaxsZApaxvA',
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.DATA));
    -
    -  bar.setNumVisibleDataSets(1);
    -  uri = bar.getUri();
    -  assertEquals(
    -      'e1:D6NtDQ,S7F4DQ,AAaxsZApaxvA',
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.DATA));
    -
    -  bar.setNumVisibleDataSets(2);
    -  uri = bar.getUri();
    -  assertEquals(
    -      'e2:D6NtDQ,S7F4DQ,AAaxsZApaxvA',
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.DATA));
    -
    -  bar.setNumVisibleDataSets(null);
    -  uri = bar.getUri();
    -  assertEquals(
    -      'e:D6NtDQ,S7F4DQ,AAaxsZApaxvA',
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.DATA));
    -}
    -
    -function testTitle() {
    -  var chart = new goog.ui.ServerChart(
    -      goog.ui.ServerChart.ChartType.BAR, 180, 104);
    -  assertEquals('Default title size', 13.5, chart.getTitleSize());
    -  assertEquals('Default title color', '333333', chart.getTitleColor());
    -  chart.setTitle('Test title');
    -  chart.setTitleSize(7);
    -  chart.setTitleColor('ff0000');
    -  var uri = chart.getUri();
    -  assertEquals(
    -      'Changing chart title failed',
    -      'Test title',
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.TITLE));
    -  assertEquals(
    -      'Changing title size and color failed',
    -      'ff0000,7',
    -      uri.getParameterValue(goog.ui.ServerChart.UriParam.TITLE_FORMAT));
    -  assertEquals('New title size', 7, chart.getTitleSize());
    -  assertEquals('New title color', 'ff0000', chart.getTitleColor());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/slider.js b/src/database/third_party/closure-library/closure/goog/ui/slider.js
    deleted file mode 100644
    index bb243716c23..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/slider.js
    +++ /dev/null
    @@ -1,136 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A slider implementation that allows to select a value within a
    - * range by dragging a thumb. The selected value is exposed through getValue().
    - *
    - * To decorate, the slider should be bound to an element with the class name
    - * 'goog-slider' containing a child with the class name 'goog-slider-thumb',
    - * whose position is set to relative.
    - * Note that you won't be able to see these elements unless they are styled.
    - *
    - * Slider orientation is horizontal by default.
    - * Use setOrientation(goog.ui.Slider.Orientation.VERTICAL) for a vertical
    - * slider.
    - *
    - * Decorate Example:
    - * <div id="slider" class="goog-slider">
    - *   <div class="goog-slider-thumb"></div>
    - * </div>
    - *
    - * JavaScript code:
    - * <code>
    - *   var slider = new goog.ui.Slider;
    - *   slider.decorate(document.getElementById('slider'));
    - * </code>
    - *
    - * @author arv@google.com (Erik Arvidsson)
    - * @see ../demos/slider.html
    - */
    -
    -// Implementation note: We implement slider by inheriting from baseslider,
    -// which allows to select sub-ranges within a range using two thumbs. All we do
    -// is we co-locate the two thumbs into one.
    -
    -goog.provide('goog.ui.Slider');
    -goog.provide('goog.ui.Slider.Orientation');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.dom');
    -goog.require('goog.ui.SliderBase');
    -
    -
    -
    -/**
    - * This creates a slider object.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @param {(function(number):?string)=} opt_labelFn An optional function mapping
    - *     slider values to a description of the value.
    - * @constructor
    - * @extends {goog.ui.SliderBase}
    - */
    -goog.ui.Slider = function(opt_domHelper, opt_labelFn) {
    -  goog.ui.SliderBase.call(this, opt_domHelper, opt_labelFn);
    -  this.rangeModel.setExtent(0);
    -};
    -goog.inherits(goog.ui.Slider, goog.ui.SliderBase);
    -goog.tagUnsealableClass(goog.ui.Slider);
    -
    -
    -/**
    - * Expose Enum of superclass (representing the orientation of the slider) within
    - * Slider namespace.
    - *
    - * @enum {string}
    - */
    -goog.ui.Slider.Orientation = goog.ui.SliderBase.Orientation;
    -
    -
    -/**
    - * The prefix we use for the CSS class names for the slider and its elements.
    - * @type {string}
    - */
    -goog.ui.Slider.CSS_CLASS_PREFIX = goog.getCssName('goog-slider');
    -
    -
    -/**
    - * CSS class name for the single thumb element.
    - * @type {string}
    - */
    -goog.ui.Slider.THUMB_CSS_CLASS =
    -    goog.getCssName(goog.ui.Slider.CSS_CLASS_PREFIX, 'thumb');
    -
    -
    -/**
    - * Returns CSS class applied to the slider element.
    - * @param {goog.ui.SliderBase.Orientation} orient Orientation of the slider.
    - * @return {string} The CSS class applied to the slider element.
    - * @protected
    - * @override
    - */
    -goog.ui.Slider.prototype.getCssClass = function(orient) {
    -  return orient == goog.ui.SliderBase.Orientation.VERTICAL ?
    -      goog.getCssName(goog.ui.Slider.CSS_CLASS_PREFIX, 'vertical') :
    -      goog.getCssName(goog.ui.Slider.CSS_CLASS_PREFIX, 'horizontal');
    -};
    -
    -
    -/** @override */
    -goog.ui.Slider.prototype.createThumbs = function() {
    -  // find thumb
    -  var element = this.getElement();
    -  var thumb = goog.dom.getElementsByTagNameAndClass(
    -      null, goog.ui.Slider.THUMB_CSS_CLASS, element)[0];
    -  if (!thumb) {
    -    thumb = this.createThumb_();
    -    element.appendChild(thumb);
    -  }
    -  this.valueThumb = this.extentThumb = thumb;
    -};
    -
    -
    -/**
    - * Creates the thumb element.
    - * @return {!HTMLDivElement} The created thumb element.
    - * @private
    - */
    -goog.ui.Slider.prototype.createThumb_ = function() {
    -  var thumb =
    -      this.getDomHelper().createDom('div', goog.ui.Slider.THUMB_CSS_CLASS);
    -  goog.a11y.aria.setRole(thumb, goog.a11y.aria.Role.BUTTON);
    -  return /** @type {!HTMLDivElement} */ (thumb);
    -};
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/sliderbase.js b/src/database/third_party/closure-library/closure/goog/ui/sliderbase.js
    deleted file mode 100644
    index 1f1a7ea7abf..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/sliderbase.js
    +++ /dev/null
    @@ -1,1657 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Implementation of a basic slider control.
    - *
    - * Models a control that allows to select a sub-range within a given
    - * range of values using two thumbs.  The underlying range is modeled
    - * as a range model, where the min thumb points to value of the
    - * rangemodel, and the max thumb points to value + extent of the range
    - * model.
    - *
    - * The currently selected range is exposed through methods
    - * getValue() and getExtent().
    - *
    - * The reason for modelling the basic slider state as value + extent is
    - * to be able to capture both, a two-thumb slider to select a range, and
    - * a single-thumb slider to just select a value (in the latter case, extent
    - * is always zero). We provide subclasses (twothumbslider.js and slider.js)
    - * that model those special cases of this control.
    - *
    - * All rendering logic is left out, so that the subclasses can define
    - * their own rendering. To do so, the subclasses overwrite:
    - * - createDom
    - * - decorateInternal
    - * - getCssClass
    - *
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -goog.provide('goog.ui.SliderBase');
    -goog.provide('goog.ui.SliderBase.AnimationFactory');
    -goog.provide('goog.ui.SliderBase.Orientation');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.events.KeyHandler');
    -goog.require('goog.events.MouseWheelHandler');
    -goog.require('goog.functions');
    -goog.require('goog.fx.AnimationParallelQueue');
    -goog.require('goog.fx.Dragger');
    -goog.require('goog.fx.Transition');
    -goog.require('goog.fx.dom.ResizeHeight');
    -goog.require('goog.fx.dom.ResizeWidth');
    -goog.require('goog.fx.dom.Slide');
    -goog.require('goog.math');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.style');
    -goog.require('goog.style.bidi');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.RangeModel');
    -
    -
    -
    -/**
    - * This creates a SliderBase object.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @param {(function(number):?string)=} opt_labelFn An optional function mapping
    - *     slider values to a description of the value.
    - * @constructor
    - * @extends {goog.ui.Component}
    - */
    -goog.ui.SliderBase = function(opt_domHelper, opt_labelFn) {
    -  goog.ui.Component.call(this, opt_domHelper);
    -
    -  /**
    -   * The factory to use to generate additional animations when animating to a
    -   * new value.
    -   * @type {goog.ui.SliderBase.AnimationFactory}
    -   * @private
    -   */
    -  this.additionalAnimations_ = null;
    -
    -  /**
    -   * The model for the range of the slider.
    -   * @type {!goog.ui.RangeModel}
    -   */
    -  this.rangeModel = new goog.ui.RangeModel;
    -
    -  /**
    -   * A function mapping slider values to text description.
    -   * @private {function(number):?string}
    -   */
    -  this.labelFn_ = opt_labelFn || goog.functions.NULL;
    -
    -  // Don't use getHandler because it gets cleared in exitDocument.
    -  goog.events.listen(this.rangeModel, goog.ui.Component.EventType.CHANGE,
    -      this.handleRangeModelChange, false, this);
    -};
    -goog.inherits(goog.ui.SliderBase, goog.ui.Component);
    -goog.tagUnsealableClass(goog.ui.SliderBase);
    -
    -
    -/**
    - * Event types used to listen for dragging events. Note that extent drag events
    - * are also sent for single-thumb sliders, since the one thumb controls both
    - * value and extent together; in this case, they can simply be ignored.
    - * @enum {string}
    - */
    -goog.ui.SliderBase.EventType = {
    -  /** User started dragging the value thumb */
    -  DRAG_VALUE_START: goog.events.getUniqueId('dragvaluestart'),
    -  /** User is done dragging the value thumb */
    -  DRAG_VALUE_END: goog.events.getUniqueId('dragvalueend'),
    -  /** User started dragging the extent thumb */
    -  DRAG_EXTENT_START: goog.events.getUniqueId('dragextentstart'),
    -  /** User is done dragging the extent thumb */
    -  DRAG_EXTENT_END: goog.events.getUniqueId('dragextentend'),
    -  // Note that the following two events are sent twice, once for the value
    -  // dragger, and once of the extent dragger. If you need to differentiate
    -  // between the two, or if your code relies on receiving a single event per
    -  // START/END event, it should listen to one of the VALUE/EXTENT-specific
    -  // events.
    -  /** User started dragging a thumb */
    -  DRAG_START: goog.events.getUniqueId('dragstart'),
    -  /** User is done dragging a thumb */
    -  DRAG_END: goog.events.getUniqueId('dragend')
    -};
    -
    -
    -/**
    - * Enum for representing the orientation of the slider.
    - *
    - * @enum {string}
    - */
    -goog.ui.SliderBase.Orientation = {
    -  VERTICAL: 'vertical',
    -  HORIZONTAL: 'horizontal'
    -};
    -
    -
    -/**
    - * Orientation of the slider.
    - * @type {goog.ui.SliderBase.Orientation}
    - * @private
    - */
    -goog.ui.SliderBase.prototype.orientation_ =
    -    goog.ui.SliderBase.Orientation.HORIZONTAL;
    -
    -
    -/** @private {goog.fx.AnimationParallelQueue} */
    -goog.ui.SliderBase.prototype.currentAnimation_;
    -
    -
    -/** @private {!goog.Timer} */
    -goog.ui.SliderBase.prototype.incTimer_;
    -
    -
    -/** @private {boolean} */
    -goog.ui.SliderBase.prototype.incrementing_;
    -
    -
    -/** @private {number} */
    -goog.ui.SliderBase.prototype.lastMousePosition_;
    -
    -
    -/**
    - * When the user holds down the mouse on the slider background, the closest
    - * thumb will move in "lock-step" towards the mouse. This number indicates how
    - * long each step should take (in milliseconds).
    - * @type {number}
    - * @private
    - */
    -goog.ui.SliderBase.MOUSE_DOWN_INCREMENT_INTERVAL_ = 200;
    -
    -
    -/**
    - * How long the animations should take (in milliseconds).
    - * @type {number}
    - * @private
    - */
    -goog.ui.SliderBase.ANIMATION_INTERVAL_ = 100;
    -
    -
    -/**
    - * The underlying range model
    - * @type {goog.ui.RangeModel}
    - * @protected
    - */
    -goog.ui.SliderBase.prototype.rangeModel;
    -
    -
    -/**
    - * The minThumb dom-element, pointing to the start of the selected range.
    - * @type {HTMLDivElement}
    - * @protected
    - */
    -goog.ui.SliderBase.prototype.valueThumb;
    -
    -
    -/**
    - * The maxThumb dom-element, pointing to the end of the selected range.
    - * @type {HTMLDivElement}
    - * @protected
    - */
    -goog.ui.SliderBase.prototype.extentThumb;
    -
    -
    -/**
    - * The dom-element highlighting the selected range.
    - * @type {HTMLDivElement}
    - * @protected
    - */
    -goog.ui.SliderBase.prototype.rangeHighlight;
    -
    -
    -/**
    - * The thumb that we should be moving (only relevant when timed move is active).
    - * @type {HTMLDivElement}
    - * @private
    - */
    -goog.ui.SliderBase.prototype.thumbToMove_;
    -
    -
    -/**
    - * The object handling keyboard events.
    - * @type {goog.events.KeyHandler}
    - * @private
    - */
    -goog.ui.SliderBase.prototype.keyHandler_;
    -
    -
    -/**
    - * The object handling mouse wheel events.
    - * @type {goog.events.MouseWheelHandler}
    - * @private
    - */
    -goog.ui.SliderBase.prototype.mouseWheelHandler_;
    -
    -
    -/**
    - * The Dragger for dragging the valueThumb.
    - * @type {goog.fx.Dragger}
    - * @private
    - */
    -goog.ui.SliderBase.prototype.valueDragger_;
    -
    -
    -/**
    - * The Dragger for dragging the extentThumb.
    - * @type {goog.fx.Dragger}
    - * @private
    - */
    -goog.ui.SliderBase.prototype.extentDragger_;
    -
    -
    -/**
    - * If we are currently animating the thumb.
    - * @private
    - * @type {boolean}
    - */
    -goog.ui.SliderBase.prototype.isAnimating_ = false;
    -
    -
    -/**
    - * Whether clicking on the backgtround should move directly to that point.
    - * @private
    - * @type {boolean}
    - */
    -goog.ui.SliderBase.prototype.moveToPointEnabled_ = false;
    -
    -
    -/**
    - * The amount to increment/decrement for page up/down as well as when holding
    - * down the mouse button on the background.
    - * @private
    - * @type {number}
    - */
    -goog.ui.SliderBase.prototype.blockIncrement_ = 10;
    -
    -
    -/**
    - * The minimal extent. The class will ensure that the extent cannot shrink
    - * to a value smaller than minExtent.
    - * @private
    - * @type {number}
    - */
    -goog.ui.SliderBase.prototype.minExtent_ = 0;
    -
    -
    -/**
    - * Whether the slider should handle mouse wheel events.
    - * @private
    - * @type {boolean}
    - */
    -goog.ui.SliderBase.prototype.isHandleMouseWheel_ = true;
    -
    -
    -/**
    - * The time the last mousedown event was received.
    - * @private
    - * @type {number}
    - */
    -goog.ui.SliderBase.prototype.mouseDownTime_ = 0;
    -
    -
    -/**
    - * The delay after mouseDownTime_ during which a click event is ignored.
    - * @private
    - * @type {number}
    - * @const
    - */
    -goog.ui.SliderBase.prototype.MOUSE_DOWN_DELAY_ = 1000;
    -
    -
    -/**
    - * Whether the slider is enabled or not.
    - * @private
    - * @type {boolean}
    - */
    -goog.ui.SliderBase.prototype.enabled_ = true;
    -
    -
    -/**
    - * Whether the slider implements the changes described in http://b/6324964,
    - * making it truly RTL.  This is a temporary flag to allow clients to transition
    - * to the new behavior at their convenience.  At some point it will be the
    - * default.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.SliderBase.prototype.flipForRtl_ = false;
    -
    -
    -/**
    - * Enables/disables true RTL behavior.  This should be called immediately after
    - * construction.  This is a temporary flag to allow clients to transition
    - * to the new behavior at their convenience.  At some point it will be the
    - * default.
    - * @param {boolean} flipForRtl True if the slider should be flipped for RTL,
    - *     false otherwise.
    - */
    -goog.ui.SliderBase.prototype.enableFlipForRtl = function(flipForRtl) {
    -  this.flipForRtl_ = flipForRtl;
    -};
    -
    -
    -// TODO: Make this return a base CSS class (without orientation), in subclasses.
    -/**
    - * Returns the CSS class applied to the slider element for the given
    - * orientation. Subclasses must override this method.
    - * @param {goog.ui.SliderBase.Orientation} orient The orientation.
    - * @return {string} The CSS class applied to slider elements.
    - * @protected
    - */
    -goog.ui.SliderBase.prototype.getCssClass = goog.abstractMethod;
    -
    -
    -/** @override */
    -goog.ui.SliderBase.prototype.createDom = function() {
    -  goog.ui.SliderBase.superClass_.createDom.call(this);
    -  var element =
    -      this.getDomHelper().createDom('div', this.getCssClass(this.orientation_));
    -  this.decorateInternal(element);
    -};
    -
    -
    -/**
    - * Subclasses must implement this method and set the valueThumb and
    - * extentThumb to non-null values. They can also set the rangeHighlight
    - * element if a range highlight is desired.
    - * @type {function() : void}
    - * @protected
    - */
    -goog.ui.SliderBase.prototype.createThumbs = goog.abstractMethod;
    -
    -
    -/**
    - * CSS class name applied to the slider while its thumbs are being dragged.
    - * @type {string}
    - * @private
    - */
    -goog.ui.SliderBase.SLIDER_DRAGGING_CSS_CLASS_ =
    -    goog.getCssName('goog-slider-dragging');
    -
    -
    -/**
    - * CSS class name applied to a thumb while it's being dragged.
    - * @type {string}
    - * @private
    - */
    -goog.ui.SliderBase.THUMB_DRAGGING_CSS_CLASS_ =
    -    goog.getCssName('goog-slider-thumb-dragging');
    -
    -
    -/**
    - * CSS class name applied when the slider is disabled.
    - * @type {string}
    - * @private
    - */
    -goog.ui.SliderBase.DISABLED_CSS_CLASS_ =
    -    goog.getCssName('goog-slider-disabled');
    -
    -
    -/** @override */
    -goog.ui.SliderBase.prototype.decorateInternal = function(element) {
    -  goog.ui.SliderBase.superClass_.decorateInternal.call(this, element);
    -  goog.asserts.assert(element);
    -  goog.dom.classlist.add(element, this.getCssClass(this.orientation_));
    -  this.createThumbs();
    -  this.setAriaRoles();
    -};
    -
    -
    -/**
    - * Called when the DOM for the component is for sure in the document.
    - * Subclasses should override this method to set this element's role.
    - * @override
    - */
    -goog.ui.SliderBase.prototype.enterDocument = function() {
    -  goog.ui.SliderBase.superClass_.enterDocument.call(this);
    -
    -  // Attach the events
    -  this.valueDragger_ = new goog.fx.Dragger(this.valueThumb);
    -  this.extentDragger_ = new goog.fx.Dragger(this.extentThumb);
    -  this.valueDragger_.enableRightPositioningForRtl(this.flipForRtl_);
    -  this.extentDragger_.enableRightPositioningForRtl(this.flipForRtl_);
    -
    -  // The slider is handling the positioning so make the defaultActions empty.
    -  this.valueDragger_.defaultAction = this.extentDragger_.defaultAction =
    -      goog.nullFunction;
    -  this.keyHandler_ = new goog.events.KeyHandler(this.getElement());
    -  this.enableEventHandlers_(true);
    -
    -  this.getElement().tabIndex = 0;
    -  this.updateUi_();
    -};
    -
    -
    -/**
    - * Attaches/Detaches the event handlers on the slider.
    - * @param {boolean} enable Whether to attach or detach the event handlers.
    - * @private
    - */
    -goog.ui.SliderBase.prototype.enableEventHandlers_ = function(enable) {
    -  if (enable) {
    -    this.getHandler().
    -        listen(this.valueDragger_, goog.fx.Dragger.EventType.BEFOREDRAG,
    -            this.handleBeforeDrag_).
    -        listen(this.extentDragger_, goog.fx.Dragger.EventType.BEFOREDRAG,
    -            this.handleBeforeDrag_).
    -        listen(this.valueDragger_,
    -            [goog.fx.Dragger.EventType.START, goog.fx.Dragger.EventType.END],
    -            this.handleThumbDragStartEnd_).
    -        listen(this.extentDragger_,
    -            [goog.fx.Dragger.EventType.START, goog.fx.Dragger.EventType.END],
    -            this.handleThumbDragStartEnd_).
    -        listen(this.keyHandler_, goog.events.KeyHandler.EventType.KEY,
    -            this.handleKeyDown_).
    -        listen(this.getElement(), goog.events.EventType.CLICK,
    -            this.handleMouseDownAndClick_).
    -        listen(this.getElement(), goog.events.EventType.MOUSEDOWN,
    -            this.handleMouseDownAndClick_);
    -    if (this.isHandleMouseWheel()) {
    -      this.enableMouseWheelHandling_(true);
    -    }
    -  } else {
    -    this.getHandler().
    -        unlisten(this.valueDragger_, goog.fx.Dragger.EventType.BEFOREDRAG,
    -            this.handleBeforeDrag_).
    -        unlisten(this.extentDragger_, goog.fx.Dragger.EventType.BEFOREDRAG,
    -            this.handleBeforeDrag_).
    -        unlisten(this.valueDragger_,
    -            [goog.fx.Dragger.EventType.START, goog.fx.Dragger.EventType.END],
    -            this.handleThumbDragStartEnd_).
    -        unlisten(this.extentDragger_,
    -            [goog.fx.Dragger.EventType.START, goog.fx.Dragger.EventType.END],
    -            this.handleThumbDragStartEnd_).
    -        unlisten(this.keyHandler_, goog.events.KeyHandler.EventType.KEY,
    -            this.handleKeyDown_).
    -        unlisten(this.getElement(), goog.events.EventType.CLICK,
    -            this.handleMouseDownAndClick_).
    -        unlisten(this.getElement(), goog.events.EventType.MOUSEDOWN,
    -            this.handleMouseDownAndClick_);
    -    if (this.isHandleMouseWheel()) {
    -      this.enableMouseWheelHandling_(false);
    -    }
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.SliderBase.prototype.exitDocument = function() {
    -  goog.ui.SliderBase.base(this, 'exitDocument');
    -  goog.disposeAll(this.valueDragger_, this.extentDragger_, this.keyHandler_,
    -                  this.mouseWheelHandler_);
    -};
    -
    -
    -/**
    - * Handler for the before drag event. We use the event properties to determine
    - * the new value.
    - * @param {goog.fx.DragEvent} e  The drag event used to drag the thumb.
    - * @private
    - */
    -goog.ui.SliderBase.prototype.handleBeforeDrag_ = function(e) {
    -  var thumbToDrag = e.dragger == this.valueDragger_ ?
    -      this.valueThumb : this.extentThumb;
    -  var value;
    -  if (this.orientation_ == goog.ui.SliderBase.Orientation.VERTICAL) {
    -    var availHeight = this.getElement().clientHeight - thumbToDrag.offsetHeight;
    -    value = (availHeight - e.top) / availHeight *
    -        (this.getMaximum() - this.getMinimum()) + this.getMinimum();
    -  } else {
    -    var availWidth = this.getElement().clientWidth - thumbToDrag.offsetWidth;
    -    value = (e.left / availWidth) * (this.getMaximum() - this.getMinimum()) +
    -        this.getMinimum();
    -  }
    -  // Bind the value within valid range before calling setThumbPosition_.
    -  // This is necessary because setThumbPosition_ is a no-op for values outside
    -  // of the legal range. For drag operations, we want the handle to snap to the
    -  // last valid value instead of remaining at the previous position.
    -  if (e.dragger == this.valueDragger_) {
    -    value = Math.min(Math.max(value, this.getMinimum()),
    -        this.getValue() + this.getExtent());
    -  } else {
    -    value = Math.min(Math.max(value, this.getValue()), this.getMaximum());
    -  }
    -  this.setThumbPosition_(thumbToDrag, value);
    -};
    -
    -
    -/**
    - * Handler for the start/end drag event on the thumgs. Adds/removes
    - * the "-dragging" CSS classes on the slider and thumb.
    - * @param {goog.fx.DragEvent} e The drag event used to drag the thumb.
    - * @private
    - */
    -goog.ui.SliderBase.prototype.handleThumbDragStartEnd_ = function(e) {
    -  var isDragStart = e.type == goog.fx.Dragger.EventType.START;
    -  goog.dom.classlist.enable(goog.asserts.assertElement(this.getElement()),
    -      goog.ui.SliderBase.SLIDER_DRAGGING_CSS_CLASS_, isDragStart);
    -  goog.dom.classlist.enable(goog.asserts.assertElement(e.target.handle),
    -      goog.ui.SliderBase.THUMB_DRAGGING_CSS_CLASS_, isDragStart);
    -  var isValueDragger = e.dragger == this.valueDragger_;
    -  if (isDragStart) {
    -    this.dispatchEvent(goog.ui.SliderBase.EventType.DRAG_START);
    -    this.dispatchEvent(isValueDragger ?
    -        goog.ui.SliderBase.EventType.DRAG_VALUE_START :
    -        goog.ui.SliderBase.EventType.DRAG_EXTENT_START);
    -  } else {
    -    this.dispatchEvent(goog.ui.SliderBase.EventType.DRAG_END);
    -    this.dispatchEvent(isValueDragger ?
    -        goog.ui.SliderBase.EventType.DRAG_VALUE_END :
    -        goog.ui.SliderBase.EventType.DRAG_EXTENT_END);
    -  }
    -};
    -
    -
    -/**
    - * Event handler for the key down event. This is used to update the value
    - * based on the key pressed.
    - * @param {goog.events.KeyEvent} e  The keyboard event object.
    - * @private
    - */
    -goog.ui.SliderBase.prototype.handleKeyDown_ = function(e) {
    -  var handled = true;
    -  switch (e.keyCode) {
    -    case goog.events.KeyCodes.HOME:
    -      this.animatedSetValue(this.getMinimum());
    -      break;
    -    case goog.events.KeyCodes.END:
    -      this.animatedSetValue(this.getMaximum());
    -      break;
    -    case goog.events.KeyCodes.PAGE_UP:
    -      this.moveThumbs(this.getBlockIncrement());
    -      break;
    -    case goog.events.KeyCodes.PAGE_DOWN:
    -      this.moveThumbs(-this.getBlockIncrement());
    -      break;
    -    case goog.events.KeyCodes.LEFT:
    -      var sign = this.flipForRtl_ && this.isRightToLeft() ? 1 : -1;
    -      this.moveThumbs(e.shiftKey ?
    -          sign * this.getBlockIncrement() : sign * this.getUnitIncrement());
    -      break;
    -    case goog.events.KeyCodes.DOWN:
    -      this.moveThumbs(e.shiftKey ?
    -          -this.getBlockIncrement() : -this.getUnitIncrement());
    -      break;
    -    case goog.events.KeyCodes.RIGHT:
    -      var sign = this.flipForRtl_ && this.isRightToLeft() ? -1 : 1;
    -      this.moveThumbs(e.shiftKey ?
    -          sign * this.getBlockIncrement() : sign * this.getUnitIncrement());
    -      break;
    -    case goog.events.KeyCodes.UP:
    -      this.moveThumbs(e.shiftKey ?
    -          this.getBlockIncrement() : this.getUnitIncrement());
    -      break;
    -
    -    default:
    -      handled = false;
    -  }
    -
    -  if (handled) {
    -    e.preventDefault();
    -  }
    -};
    -
    -
    -/**
    - * Handler for the mouse down event and click event.
    - * @param {goog.events.Event} e  The mouse event object.
    - * @private
    - */
    -goog.ui.SliderBase.prototype.handleMouseDownAndClick_ = function(e) {
    -  if (this.getElement().focus) {
    -    this.getElement().focus();
    -  }
    -
    -  // Known Element.
    -  var target = /** @type {Element} */ (e.target);
    -
    -  if (!goog.dom.contains(this.valueThumb, target) &&
    -      !goog.dom.contains(this.extentThumb, target)) {
    -    var isClick = e.type == goog.events.EventType.CLICK;
    -    if (isClick && goog.now() < this.mouseDownTime_ + this.MOUSE_DOWN_DELAY_) {
    -      // Ignore a click event that comes a short moment after a mousedown
    -      // event.  This happens for desktop.  For devices with both a touch
    -      // screen and a mouse pad we do not get a mousedown event from the mouse
    -      // pad and do get a click event.
    -      return;
    -    }
    -    if (!isClick) {
    -      this.mouseDownTime_ = goog.now();
    -    }
    -
    -    if (this.moveToPointEnabled_) {
    -      // just set the value directly based on the position of the click
    -      this.animatedSetValue(this.getValueFromMousePosition(e));
    -    } else {
    -      // start a timer that incrementally moves the handle
    -      this.startBlockIncrementing_(e);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Handler for the mouse wheel event.
    - * @param {goog.events.MouseWheelEvent} e  The mouse wheel event object.
    - * @private
    - */
    -goog.ui.SliderBase.prototype.handleMouseWheel_ = function(e) {
    -  // Just move one unit increment per mouse wheel event
    -  var direction = e.detail > 0 ? -1 : 1;
    -  this.moveThumbs(direction * this.getUnitIncrement());
    -  e.preventDefault();
    -};
    -
    -
    -/**
    - * Starts the animation that causes the thumb to increment/decrement by the
    - * block increment when the user presses down on the background.
    - * @param {goog.events.Event} e  The mouse event object.
    - * @private
    - */
    -goog.ui.SliderBase.prototype.startBlockIncrementing_ = function(e) {
    -  this.storeMousePos_(e);
    -  this.thumbToMove_ = this.getClosestThumb_(this.getValueFromMousePosition(e));
    -  if (this.orientation_ == goog.ui.SliderBase.Orientation.VERTICAL) {
    -    this.incrementing_ = this.lastMousePosition_ < this.thumbToMove_.offsetTop;
    -  } else {
    -    this.incrementing_ = this.lastMousePosition_ >
    -                         this.getOffsetStart_(this.thumbToMove_) +
    -                         this.thumbToMove_.offsetWidth;
    -  }
    -
    -  var doc = goog.dom.getOwnerDocument(this.getElement());
    -  this.getHandler().
    -      listen(doc, goog.events.EventType.MOUSEUP,
    -          this.stopBlockIncrementing_, true).
    -      listen(this.getElement(), goog.events.EventType.MOUSEMOVE,
    -          this.storeMousePos_);
    -
    -  if (!this.incTimer_) {
    -    this.incTimer_ = new goog.Timer(
    -        goog.ui.SliderBase.MOUSE_DOWN_INCREMENT_INTERVAL_);
    -    this.getHandler().listen(this.incTimer_, goog.Timer.TICK,
    -        this.handleTimerTick_);
    -  }
    -  this.handleTimerTick_();
    -  this.incTimer_.start();
    -};
    -
    -
    -/**
    - * Handler for the tick event dispatched by the timer used to update the value
    - * in a block increment. This is also called directly from
    - * startBlockIncrementing_.
    - * @private
    - */
    -goog.ui.SliderBase.prototype.handleTimerTick_ = function() {
    -  var value;
    -  if (this.orientation_ == goog.ui.SliderBase.Orientation.VERTICAL) {
    -    var mouseY = this.lastMousePosition_;
    -    var thumbY = this.thumbToMove_.offsetTop;
    -    if (this.incrementing_) {
    -      if (mouseY < thumbY) {
    -        value = this.getThumbPosition_(this.thumbToMove_) +
    -            this.getBlockIncrement();
    -      }
    -    } else {
    -      var thumbH = this.thumbToMove_.offsetHeight;
    -      if (mouseY > thumbY + thumbH) {
    -        value = this.getThumbPosition_(this.thumbToMove_) -
    -            this.getBlockIncrement();
    -      }
    -    }
    -  } else {
    -    var mouseX = this.lastMousePosition_;
    -    var thumbX = this.getOffsetStart_(this.thumbToMove_);
    -    if (this.incrementing_) {
    -      var thumbW = this.thumbToMove_.offsetWidth;
    -      if (mouseX > thumbX + thumbW) {
    -        value = this.getThumbPosition_(this.thumbToMove_) +
    -            this.getBlockIncrement();
    -      }
    -    } else {
    -      if (mouseX < thumbX) {
    -        value = this.getThumbPosition_(this.thumbToMove_) -
    -            this.getBlockIncrement();
    -      }
    -    }
    -  }
    -
    -  if (goog.isDef(value)) { // not all code paths sets the value variable
    -    this.setThumbPosition_(this.thumbToMove_, value);
    -  }
    -};
    -
    -
    -/**
    - * Stops the block incrementing animation and unlistens the necessary
    - * event handlers.
    - * @private
    - */
    -goog.ui.SliderBase.prototype.stopBlockIncrementing_ = function() {
    -  if (this.incTimer_) {
    -    this.incTimer_.stop();
    -  }
    -
    -  var doc = goog.dom.getOwnerDocument(this.getElement());
    -  this.getHandler().
    -      unlisten(doc, goog.events.EventType.MOUSEUP,
    -          this.stopBlockIncrementing_, true).
    -      unlisten(this.getElement(), goog.events.EventType.MOUSEMOVE,
    -          this.storeMousePos_);
    -};
    -
    -
    -/**
    - * Returns the relative mouse position to the slider.
    - * @param {goog.events.Event} e  The mouse event object.
    - * @return {number} The relative mouse position to the slider.
    - * @private
    - */
    -goog.ui.SliderBase.prototype.getRelativeMousePos_ = function(e) {
    -  var coord = goog.style.getRelativePosition(e, this.getElement());
    -  if (this.orientation_ == goog.ui.SliderBase.Orientation.VERTICAL) {
    -    return coord.y;
    -  } else {
    -    if (this.flipForRtl_ && this.isRightToLeft()) {
    -      return this.getElement().clientWidth - coord.x;
    -    } else {
    -      return coord.x;
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Stores the current mouse position so that it can be used in the timer.
    - * @param {goog.events.Event} e  The mouse event object.
    - * @private
    - */
    -goog.ui.SliderBase.prototype.storeMousePos_ = function(e) {
    -  this.lastMousePosition_ = this.getRelativeMousePos_(e);
    -};
    -
    -
    -/**
    - * Returns the value to use for the current mouse position
    - * @param {goog.events.Event} e  The mouse event object.
    - * @return {number} The value that this mouse position represents.
    - */
    -goog.ui.SliderBase.prototype.getValueFromMousePosition = function(e) {
    -  var min = this.getMinimum();
    -  var max = this.getMaximum();
    -  if (this.orientation_ == goog.ui.SliderBase.Orientation.VERTICAL) {
    -    var thumbH = this.valueThumb.offsetHeight;
    -    var availH = this.getElement().clientHeight - thumbH;
    -    var y = this.getRelativeMousePos_(e) - thumbH / 2;
    -    return (max - min) * (availH - y) / availH + min;
    -  } else {
    -    var thumbW = this.valueThumb.offsetWidth;
    -    var availW = this.getElement().clientWidth - thumbW;
    -    var x = this.getRelativeMousePos_(e) - thumbW / 2;
    -    return (max - min) * x / availW + min;
    -  }
    -};
    -
    -
    -
    -/**
    - * @param {HTMLDivElement} thumb  The thumb object.
    - * @return {number} The position of the specified thumb.
    - * @private
    - */
    -goog.ui.SliderBase.prototype.getThumbPosition_ = function(thumb) {
    -  if (thumb == this.valueThumb) {
    -    return this.rangeModel.getValue();
    -  } else if (thumb == this.extentThumb) {
    -    return this.rangeModel.getValue() + this.rangeModel.getExtent();
    -  } else {
    -    throw Error('Illegal thumb element. Neither minThumb nor maxThumb');
    -  }
    -};
    -
    -
    -/**
    - * Returns whether a thumb is currently being dragged with the mouse (or via
    - * touch). Note that changing the value with keyboard, mouswheel, or via
    - * move-to-point click immediately sends a CHANGE event without going through a
    - * dragged state.
    - * @return {boolean} Whether a dragger is currently being dragged.
    - */
    -goog.ui.SliderBase.prototype.isDragging = function() {
    -  return this.valueDragger_.isDragging() || this.extentDragger_.isDragging();
    -};
    -
    -
    -/**
    - * Moves the thumbs by the specified delta as follows
    - * - as long as both thumbs stay within [min,max], both thumbs are moved
    - * - once a thumb reaches or exceeds min (or max, respectively), it stays
    - * - at min (or max, respectively).
    - * In case both thumbs have reached min (or max), no change event will fire.
    - * If the specified delta is smaller than the step size, it will be rounded
    - * to the step size.
    - * @param {number} delta The delta by which to move the selected range.
    - */
    -goog.ui.SliderBase.prototype.moveThumbs = function(delta) {
    -  // Assume that a small delta is supposed to be at least a step.
    -  if (Math.abs(delta) < this.getStep()) {
    -    delta = goog.math.sign(delta) * this.getStep();
    -  }
    -  var newMinPos = this.getThumbPosition_(this.valueThumb) + delta;
    -  var newMaxPos = this.getThumbPosition_(this.extentThumb) + delta;
    -  // correct min / max positions to be within bounds
    -  newMinPos = goog.math.clamp(
    -      newMinPos, this.getMinimum(), this.getMaximum() - this.minExtent_);
    -  newMaxPos = goog.math.clamp(
    -      newMaxPos, this.getMinimum() + this.minExtent_, this.getMaximum());
    -  // Set value and extent atomically
    -  this.setValueAndExtent(newMinPos, newMaxPos - newMinPos);
    -};
    -
    -
    -/**
    - * Sets the position of the given thumb. The set is ignored and no CHANGE event
    - * fires if it violates the constraint minimum <= value (valueThumb position) <=
    - * value + extent (extentThumb position) <= maximum.
    - *
    - * Note: To keep things simple, the setThumbPosition_ function does not have the
    - * side-effect of "correcting" value or extent to fit the above constraint as it
    - * is the case in the underlying range model. Instead, we simply ignore the
    - * call. Callers must make these adjustements explicitly if they wish.
    - * @param {Element} thumb The thumb whose position to set.
    - * @param {number} position The position to move the thumb to.
    - * @private
    - */
    -goog.ui.SliderBase.prototype.setThumbPosition_ = function(thumb, position) {
    -  // Round first so that all computations and checks are consistent.
    -  var roundedPosition = this.rangeModel.roundToStepWithMin(position);
    -  var value = thumb == this.valueThumb ? roundedPosition :
    -      this.rangeModel.getValue();
    -  var end = thumb == this.extentThumb ? roundedPosition :
    -      this.rangeModel.getValue() + this.rangeModel.getExtent();
    -  if (value >= this.getMinimum() && end >= value + this.minExtent_ &&
    -      this.getMaximum() >= end) {
    -    this.setValueAndExtent(value, end - value);
    -  }
    -};
    -
    -
    -/**
    - * Sets the value and extent of the underlying range model. We enforce that
    - * getMinimum() <= value <= getMaximum() - extent and
    - * getMinExtent <= extent <= getMaximum() - getValue()
    - * If this is not satisfied for the given extent, the call is ignored and no
    - * CHANGE event fires. This is a utility method to allow setting the thumbs
    - * simultaneously and ensuring that only one event fires.
    - * @param {number} value The value to which to set the value.
    - * @param {number} extent The value to which to set the extent.
    - */
    -goog.ui.SliderBase.prototype.setValueAndExtent = function(value, extent) {
    -  if (this.getMinimum() <= value &&
    -      value <= this.getMaximum() - extent &&
    -      this.minExtent_ <= extent &&
    -      extent <= this.getMaximum() - value) {
    -
    -    if (value == this.getValue() && extent == this.getExtent()) {
    -      return;
    -    }
    -    // because the underlying range model applies adjustements of value
    -    // and extent to fit within bounds, we need to reset the extent
    -    // first so these adjustements don't kick in.
    -    this.rangeModel.setMute(true);
    -    this.rangeModel.setExtent(0);
    -    this.rangeModel.setValue(value);
    -    this.rangeModel.setExtent(extent);
    -    this.rangeModel.setMute(false);
    -    this.handleRangeModelChange(null);
    -  }
    -};
    -
    -
    -/**
    - * @return {number} The minimum value.
    - */
    -goog.ui.SliderBase.prototype.getMinimum = function() {
    -  return this.rangeModel.getMinimum();
    -};
    -
    -
    -/**
    - * Sets the minimum number.
    - * @param {number} min The minimum value.
    - */
    -goog.ui.SliderBase.prototype.setMinimum = function(min) {
    -  this.rangeModel.setMinimum(min);
    -};
    -
    -
    -/**
    - * @return {number} The maximum value.
    - */
    -goog.ui.SliderBase.prototype.getMaximum = function() {
    -  return this.rangeModel.getMaximum();
    -};
    -
    -
    -/**
    - * Sets the maximum number.
    - * @param {number} max The maximum value.
    - */
    -goog.ui.SliderBase.prototype.setMaximum = function(max) {
    -  this.rangeModel.setMaximum(max);
    -};
    -
    -
    -/**
    - * @return {HTMLDivElement} The value thumb element.
    - */
    -goog.ui.SliderBase.prototype.getValueThumb = function() {
    -  return this.valueThumb;
    -};
    -
    -
    -/**
    - * @return {HTMLDivElement} The extent thumb element.
    - */
    -goog.ui.SliderBase.prototype.getExtentThumb = function() {
    -  return this.extentThumb;
    -};
    -
    -
    -/**
    - * @param {number} position The position to get the closest thumb to.
    - * @return {HTMLDivElement} The thumb that is closest to the given position.
    - * @private
    - */
    -goog.ui.SliderBase.prototype.getClosestThumb_ = function(position) {
    -  if (position <= (this.rangeModel.getValue() +
    -                   this.rangeModel.getExtent() / 2)) {
    -    return this.valueThumb;
    -  } else {
    -    return this.extentThumb;
    -  }
    -};
    -
    -
    -/**
    - * Call back when the internal range model changes. Sub-classes may override
    - * and re-enter this method to update a11y state. Consider protected.
    - * @param {goog.events.Event} e The event object.
    - * @protected
    - */
    -goog.ui.SliderBase.prototype.handleRangeModelChange = function(e) {
    -  this.updateUi_();
    -  this.updateAriaStates();
    -  this.dispatchEvent(goog.ui.Component.EventType.CHANGE);
    -};
    -
    -
    -/**
    - * This is called when we need to update the size of the thumb. This happens
    - * when first created as well as when the value and the orientation changes.
    - * @private
    - */
    -goog.ui.SliderBase.prototype.updateUi_ = function() {
    -  if (this.valueThumb && !this.isAnimating_) {
    -    var minCoord = this.getThumbCoordinateForValue(
    -        this.getThumbPosition_(this.valueThumb));
    -    var maxCoord = this.getThumbCoordinateForValue(
    -        this.getThumbPosition_(this.extentThumb));
    -
    -    if (this.orientation_ == goog.ui.SliderBase.Orientation.VERTICAL) {
    -      this.valueThumb.style.top = minCoord.y + 'px';
    -      this.extentThumb.style.top = maxCoord.y + 'px';
    -      if (this.rangeHighlight) {
    -        var highlightPositioning = this.calculateRangeHighlightPositioning_(
    -            maxCoord.y, minCoord.y, this.valueThumb.offsetHeight);
    -        this.rangeHighlight.style.top = highlightPositioning.offset + 'px';
    -        this.rangeHighlight.style.height = highlightPositioning.size + 'px';
    -      }
    -    } else {
    -      var pos = (this.flipForRtl_ && this.isRightToLeft()) ? 'right' : 'left';
    -      this.valueThumb.style[pos] = minCoord.x + 'px';
    -      this.extentThumb.style[pos] = maxCoord.x + 'px';
    -      if (this.rangeHighlight) {
    -        var highlightPositioning = this.calculateRangeHighlightPositioning_(
    -            minCoord.x, maxCoord.x, this.valueThumb.offsetWidth);
    -        this.rangeHighlight.style[pos] = highlightPositioning.offset + 'px';
    -        this.rangeHighlight.style.width = highlightPositioning.size + 'px';
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Calculates the start position (offset) and size of the range highlight, e.g.
    - * for a horizontal slider, this will return [left, width] for the highlight.
    - * @param {number} firstThumbPos The position of the first thumb along the
    - *     slider axis.
    - * @param {number} secondThumbPos The position of the second thumb along the
    - *     slider axis, must be >= firstThumbPos.
    - * @param {number} thumbSize The size of the thumb, along the slider axis.
    - * @return {{offset: number, size: number}} The positioning parameters for the
    - *     range highlight.
    - * @private
    - */
    -goog.ui.SliderBase.prototype.calculateRangeHighlightPositioning_ = function(
    -    firstThumbPos, secondThumbPos, thumbSize) {
    -  // Highlight is inset by half the thumb size, from the edges of the thumb.
    -  var highlightInset = Math.ceil(thumbSize / 2);
    -  var size = secondThumbPos - firstThumbPos + thumbSize - 2 * highlightInset;
    -  // Don't return negative size since it causes an error. IE sometimes attempts
    -  // to position the thumbs while slider size is 0, resulting in size < 0 here.
    -  return {
    -    offset: firstThumbPos + highlightInset,
    -    size: Math.max(size, 0)
    -  };
    -};
    -
    -
    -/**
    - * Returns the position to move the handle to for a given value
    - * @param {number} val  The value to get the coordinate for.
    - * @return {!goog.math.Coordinate} Coordinate with either x or y set.
    - */
    -goog.ui.SliderBase.prototype.getThumbCoordinateForValue = function(val) {
    -  var coord = new goog.math.Coordinate;
    -  if (this.valueThumb) {
    -    var min = this.getMinimum();
    -    var max = this.getMaximum();
    -
    -    // This check ensures the ratio never take NaN value, which is possible when
    -    // the slider min & max are same numbers (i.e. 1).
    -    var ratio = (val == min && min == max) ? 0 : (val - min) / (max - min);
    -
    -    if (this.orientation_ == goog.ui.SliderBase.Orientation.VERTICAL) {
    -      var thumbHeight = this.valueThumb.offsetHeight;
    -      var h = this.getElement().clientHeight - thumbHeight;
    -      var bottom = Math.round(ratio * h);
    -      coord.x = this.getOffsetStart_(this.valueThumb); // Keep x the same.
    -      coord.y = h - bottom;
    -    } else {
    -      var w = this.getElement().clientWidth - this.valueThumb.offsetWidth;
    -      var left = Math.round(ratio * w);
    -      coord.x = left;
    -      coord.y = this.valueThumb.offsetTop; // Keep y the same.
    -    }
    -  }
    -  return coord;
    -};
    -
    -
    -
    -/**
    - * Sets the value and starts animating the handle towards that position.
    - * @param {number} v Value to set and animate to.
    - */
    -goog.ui.SliderBase.prototype.animatedSetValue = function(v) {
    -  // the value might be out of bounds
    -  v = goog.math.clamp(v, this.getMinimum(), this.getMaximum());
    -
    -  if (this.isAnimating_) {
    -    this.currentAnimation_.stop(true);
    -  }
    -  var animations = new goog.fx.AnimationParallelQueue();
    -  var end;
    -
    -  var thumb = this.getClosestThumb_(v);
    -  var previousValue = this.getValue();
    -  var previousExtent = this.getExtent();
    -  var previousThumbValue = this.getThumbPosition_(thumb);
    -  var previousCoord = this.getThumbCoordinateForValue(previousThumbValue);
    -  var stepSize = this.getStep();
    -
    -  // If the delta is less than a single step, increase it to a step, else the
    -  // range model will reduce it to zero.
    -  if (Math.abs(v - previousThumbValue) < stepSize) {
    -    var delta = v > previousThumbValue ? stepSize : -stepSize;
    -    v = previousThumbValue + delta;
    -
    -    // The resulting value may be out of bounds, sanitize.
    -    v = goog.math.clamp(v, this.getMinimum(), this.getMaximum());
    -  }
    -
    -  this.setThumbPosition_(thumb, v);
    -  var coord = this.getThumbCoordinateForValue(this.getThumbPosition_(thumb));
    -
    -  if (this.orientation_ == goog.ui.SliderBase.Orientation.VERTICAL) {
    -    end = [this.getOffsetStart_(thumb), coord.y];
    -  } else {
    -    end = [coord.x, thumb.offsetTop];
    -  }
    -
    -  var slide = new goog.fx.dom.Slide(thumb,
    -      [previousCoord.x, previousCoord.y],
    -      end,
    -      goog.ui.SliderBase.ANIMATION_INTERVAL_);
    -  slide.enableRightPositioningForRtl(this.flipForRtl_);
    -  animations.add(slide);
    -  if (this.rangeHighlight) {
    -    this.addRangeHighlightAnimations_(thumb, previousValue, previousExtent,
    -        coord, animations);
    -  }
    -
    -  // Create additional animations to play if a factory has been set.
    -  if (this.additionalAnimations_) {
    -    var additionalAnimations = this.additionalAnimations_.createAnimations(
    -        previousValue, v, goog.ui.SliderBase.ANIMATION_INTERVAL_);
    -    goog.array.forEach(additionalAnimations, function(animation) {
    -      animations.add(animation);
    -    });
    -  }
    -
    -  this.currentAnimation_ = animations;
    -  this.getHandler().listen(animations, goog.fx.Transition.EventType.END,
    -      this.endAnimation_);
    -
    -  this.isAnimating_ = true;
    -  animations.play(false);
    -};
    -
    -
    -/**
    - * @return {boolean} True if the slider is animating, false otherwise.
    - */
    -goog.ui.SliderBase.prototype.isAnimating = function() {
    -  return this.isAnimating_;
    -};
    -
    -
    -/**
    - * Sets the factory that will be used to create additional animations to be
    - * played when animating to a new value.  These animations can be for any
    - * element and the animations will be played in addition to the default
    - * animation(s).  The animations will also be played in the same parallel queue
    - * ensuring that all animations are played at the same time.
    - * @see #animatedSetValue
    - *
    - * @param {goog.ui.SliderBase.AnimationFactory} factory The animation factory to
    - *     use.  This will not change the default animations played by the slider.
    - *     It will only allow for additional animations.
    - */
    -goog.ui.SliderBase.prototype.setAdditionalAnimations = function(factory) {
    -  this.additionalAnimations_ = factory;
    -};
    -
    -
    -/**
    - * Adds animations for the range highlight element to the animation queue.
    - *
    - * @param {Element} thumb The thumb that's moving, must be
    - *     either valueThumb or extentThumb.
    - * @param {number} previousValue The previous value of the slider.
    - * @param {number} previousExtent The previous extent of the
    - *     slider.
    - * @param {goog.math.Coordinate} newCoord The new pixel coordinate of the
    - *     thumb that's moving.
    - * @param {goog.fx.AnimationParallelQueue} animations The animation queue.
    - * @private
    - */
    -goog.ui.SliderBase.prototype.addRangeHighlightAnimations_ = function(thumb,
    -    previousValue, previousExtent, newCoord, animations) {
    -  var previousMinCoord = this.getThumbCoordinateForValue(previousValue);
    -  var previousMaxCoord = this.getThumbCoordinateForValue(
    -      previousValue + previousExtent);
    -  var minCoord = previousMinCoord;
    -  var maxCoord = previousMaxCoord;
    -  if (thumb == this.valueThumb) {
    -    minCoord = newCoord;
    -  } else {
    -    maxCoord = newCoord;
    -  }
    -
    -  if (this.orientation_ == goog.ui.SliderBase.Orientation.VERTICAL) {
    -    var previousHighlightPositioning = this.calculateRangeHighlightPositioning_(
    -        previousMaxCoord.y, previousMinCoord.y, this.valueThumb.offsetHeight);
    -    var highlightPositioning = this.calculateRangeHighlightPositioning_(
    -        maxCoord.y, minCoord.y, this.valueThumb.offsetHeight);
    -    var slide = new goog.fx.dom.Slide(this.rangeHighlight,
    -        [this.getOffsetStart_(this.rangeHighlight),
    -          previousHighlightPositioning.offset],
    -        [this.getOffsetStart_(this.rangeHighlight),
    -          highlightPositioning.offset],
    -        goog.ui.SliderBase.ANIMATION_INTERVAL_);
    -    var resizeHeight = new goog.fx.dom.ResizeHeight(this.rangeHighlight,
    -        previousHighlightPositioning.size, highlightPositioning.size,
    -        goog.ui.SliderBase.ANIMATION_INTERVAL_);
    -    slide.enableRightPositioningForRtl(this.flipForRtl_);
    -    resizeHeight.enableRightPositioningForRtl(this.flipForRtl_);
    -    animations.add(slide);
    -    animations.add(resizeHeight);
    -  } else {
    -    var previousHighlightPositioning = this.calculateRangeHighlightPositioning_(
    -        previousMinCoord.x, previousMaxCoord.x, this.valueThumb.offsetWidth);
    -    var highlightPositioning = this.calculateRangeHighlightPositioning_(
    -        minCoord.x, maxCoord.x, this.valueThumb.offsetWidth);
    -    var slide = new goog.fx.dom.Slide(this.rangeHighlight,
    -        [previousHighlightPositioning.offset, this.rangeHighlight.offsetTop],
    -        [highlightPositioning.offset, this.rangeHighlight.offsetTop],
    -        goog.ui.SliderBase.ANIMATION_INTERVAL_);
    -    var resizeWidth = new goog.fx.dom.ResizeWidth(this.rangeHighlight,
    -        previousHighlightPositioning.size, highlightPositioning.size,
    -        goog.ui.SliderBase.ANIMATION_INTERVAL_);
    -    slide.enableRightPositioningForRtl(this.flipForRtl_);
    -    resizeWidth.enableRightPositioningForRtl(this.flipForRtl_);
    -    animations.add(slide);
    -    animations.add(resizeWidth);
    -  }
    -};
    -
    -
    -/**
    - * Sets the isAnimating_ field to false once the animation is done.
    - * @param {goog.fx.AnimationEvent} e Event object passed by the animation
    - *     object.
    - * @private
    - */
    -goog.ui.SliderBase.prototype.endAnimation_ = function(e) {
    -  this.isAnimating_ = false;
    -};
    -
    -
    -/**
    - * Changes the orientation.
    - * @param {goog.ui.SliderBase.Orientation} orient The orientation.
    - */
    -goog.ui.SliderBase.prototype.setOrientation = function(orient) {
    -  if (this.orientation_ != orient) {
    -    var oldCss = this.getCssClass(this.orientation_);
    -    var newCss = this.getCssClass(orient);
    -    this.orientation_ = orient;
    -
    -    // Update the DOM
    -    if (this.getElement()) {
    -      goog.dom.classlist.swap(goog.asserts.assert(this.getElement()),
    -                              oldCss, newCss);
    -      // we need to reset the left and top, plus range highlight
    -      var pos = (this.flipForRtl_ && this.isRightToLeft()) ? 'right' : 'left';
    -      this.valueThumb.style[pos] = this.valueThumb.style.top = '';
    -      this.extentThumb.style[pos] = this.extentThumb.style.top = '';
    -      if (this.rangeHighlight) {
    -        this.rangeHighlight.style[pos] = this.rangeHighlight.style.top = '';
    -        this.rangeHighlight.style.width = this.rangeHighlight.style.height = '';
    -      }
    -      this.updateUi_();
    -    }
    -  }
    -};
    -
    -
    -/**
    - * @return {goog.ui.SliderBase.Orientation} the orientation of the slider.
    - */
    -goog.ui.SliderBase.prototype.getOrientation = function() {
    -  return this.orientation_;
    -};
    -
    -
    -/** @override */
    -goog.ui.SliderBase.prototype.disposeInternal = function() {
    -  goog.ui.SliderBase.superClass_.disposeInternal.call(this);
    -  if (this.incTimer_) {
    -    this.incTimer_.dispose();
    -  }
    -  delete this.incTimer_;
    -  if (this.currentAnimation_) {
    -    this.currentAnimation_.dispose();
    -  }
    -  delete this.currentAnimation_;
    -  delete this.valueThumb;
    -  delete this.extentThumb;
    -  if (this.rangeHighlight) {
    -    delete this.rangeHighlight;
    -  }
    -  this.rangeModel.dispose();
    -  delete this.rangeModel;
    -  if (this.keyHandler_) {
    -    this.keyHandler_.dispose();
    -    delete this.keyHandler_;
    -  }
    -  if (this.mouseWheelHandler_) {
    -    this.mouseWheelHandler_.dispose();
    -    delete this.mouseWheelHandler_;
    -  }
    -  if (this.valueDragger_) {
    -    this.valueDragger_.dispose();
    -    delete this.valueDragger_;
    -  }
    -  if (this.extentDragger_) {
    -    this.extentDragger_.dispose();
    -    delete this.extentDragger_;
    -  }
    -};
    -
    -
    -/**
    - * @return {number} The amount to increment/decrement for page up/down as well
    - *     as when holding down the mouse button on the background.
    - */
    -goog.ui.SliderBase.prototype.getBlockIncrement = function() {
    -  return this.blockIncrement_;
    -};
    -
    -
    -/**
    - * Sets the amount to increment/decrement for page up/down as well as when
    - * holding down the mouse button on the background.
    - *
    - * @param {number} value The value to set the block increment to.
    - */
    -goog.ui.SliderBase.prototype.setBlockIncrement = function(value) {
    -  this.blockIncrement_ = value;
    -};
    -
    -
    -/**
    - * Sets the minimal value that the extent may have.
    - *
    - * @param {number} value The minimal value for the extent.
    - */
    -goog.ui.SliderBase.prototype.setMinExtent = function(value) {
    -  this.minExtent_ = value;
    -};
    -
    -
    -/**
    - * The amount to increment/decrement for up, down, left and right arrow keys
    - * and mouse wheel events.
    - * @private
    - * @type {number}
    - */
    -goog.ui.SliderBase.prototype.unitIncrement_ = 1;
    -
    -
    -/**
    - * @return {number} The amount to increment/decrement for up, down, left and
    - *     right arrow keys and mouse wheel events.
    - */
    -goog.ui.SliderBase.prototype.getUnitIncrement = function() {
    -  return this.unitIncrement_;
    -};
    -
    -
    -/**
    - * Sets the amount to increment/decrement for up, down, left and right arrow
    - * keys and mouse wheel events.
    - * @param {number} value  The value to set the unit increment to.
    - */
    -goog.ui.SliderBase.prototype.setUnitIncrement = function(value) {
    -  this.unitIncrement_ = value;
    -};
    -
    -
    -/**
    - * @return {?number} The step value used to determine how to round the value.
    - */
    -goog.ui.SliderBase.prototype.getStep = function() {
    -  return this.rangeModel.getStep();
    -};
    -
    -
    -/**
    - * Sets the step value. The step value is used to determine how to round the
    - * value.
    - * @param {?number} step  The step size.
    - */
    -goog.ui.SliderBase.prototype.setStep = function(step) {
    -  this.rangeModel.setStep(step);
    -};
    -
    -
    -/**
    - * @return {boolean} Whether clicking on the backgtround should move directly to
    - *     that point.
    - */
    -goog.ui.SliderBase.prototype.getMoveToPointEnabled = function() {
    -  return this.moveToPointEnabled_;
    -};
    -
    -
    -/**
    - * Sets whether clicking on the background should move directly to that point.
    - * @param {boolean} val Whether clicking on the background should move directly
    - *     to that point.
    - */
    -goog.ui.SliderBase.prototype.setMoveToPointEnabled = function(val) {
    -  this.moveToPointEnabled_ = val;
    -};
    -
    -
    -/**
    - * @return {number} The value of the underlying range model.
    - */
    -goog.ui.SliderBase.prototype.getValue = function() {
    -  return this.rangeModel.getValue();
    -};
    -
    -
    -/**
    - * Sets the value of the underlying range model. We enforce that
    - * getMinimum() <= value <= getMaximum() - getExtent()
    - * If this is not satisifed for the given value, the call is ignored and no
    - * CHANGE event fires.
    - * @param {number} value The value.
    - */
    -goog.ui.SliderBase.prototype.setValue = function(value) {
    -  // Set the position through the thumb method to enforce constraints.
    -  this.setThumbPosition_(this.valueThumb, value);
    -};
    -
    -
    -/**
    - * @return {number} The value of the extent of the underlying range model.
    - */
    -goog.ui.SliderBase.prototype.getExtent = function() {
    -  return this.rangeModel.getExtent();
    -};
    -
    -
    -/**
    - * Sets the extent of the underlying range model. We enforce that
    - * getMinExtent() <= extent <= getMaximum() - getValue()
    - * If this is not satisifed for the given extent, the call is ignored and no
    - * CHANGE event fires.
    - * @param {number} extent The value to which to set the extent.
    - */
    -goog.ui.SliderBase.prototype.setExtent = function(extent) {
    -  // Set the position through the thumb method to enforce constraints.
    -  this.setThumbPosition_(this.extentThumb, (this.rangeModel.getValue() +
    -                                            extent));
    -};
    -
    -
    -/**
    - * Change the visibility of the slider.
    - * You must call this if you had set the slider's value when it was invisible.
    - * @param {boolean} visible Whether to show the slider.
    - */
    -goog.ui.SliderBase.prototype.setVisible = function(visible) {
    -  goog.style.setElementShown(this.getElement(), visible);
    -  if (visible) {
    -    this.updateUi_();
    -  }
    -};
    -
    -
    -/**
    - * Set a11y roles and state.
    - * @protected
    - */
    -goog.ui.SliderBase.prototype.setAriaRoles = function() {
    -  var el = this.getElement();
    -  goog.asserts.assert(el,
    -      'The DOM element for the slider base cannot be null.');
    -  goog.a11y.aria.setRole(el, goog.a11y.aria.Role.SLIDER);
    -  this.updateAriaStates();
    -};
    -
    -
    -/**
    - * Set a11y roles and state when values change.
    - * @protected
    - */
    -goog.ui.SliderBase.prototype.updateAriaStates = function() {
    -  var element = this.getElement();
    -  if (element) {
    -    goog.a11y.aria.setState(element, goog.a11y.aria.State.VALUEMIN,
    -        this.getMinimum());
    -    goog.a11y.aria.setState(element, goog.a11y.aria.State.VALUEMAX,
    -        this.getMaximum());
    -    goog.a11y.aria.setState(element, goog.a11y.aria.State.VALUENOW,
    -        this.getValue());
    -    // Passing an empty value to setState will restore the default.
    -    goog.a11y.aria.setState(element, goog.a11y.aria.State.VALUETEXT,
    -        this.getTextValue() || '');
    -  }
    -};
    -
    -
    -/**
    - * Enables or disables mouse wheel handling for the slider. The mouse wheel
    - * handler enables the user to change the value of slider using a mouse wheel.
    - *
    - * @param {boolean} enable Whether to enable mouse wheel handling.
    - */
    -goog.ui.SliderBase.prototype.setHandleMouseWheel = function(enable) {
    -  if (this.isInDocument() && enable != this.isHandleMouseWheel()) {
    -    this.enableMouseWheelHandling_(enable);
    -  }
    -
    -  this.isHandleMouseWheel_ = enable;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the slider handles mousewheel.
    - */
    -goog.ui.SliderBase.prototype.isHandleMouseWheel = function() {
    -  return this.isHandleMouseWheel_;
    -};
    -
    -
    -/**
    - * Enable/Disable mouse wheel handling.
    - * @param {boolean} enable Whether to enable mouse wheel handling.
    - * @private
    - */
    -goog.ui.SliderBase.prototype.enableMouseWheelHandling_ = function(enable) {
    -  if (enable) {
    -    if (!this.mouseWheelHandler_) {
    -      this.mouseWheelHandler_ = new goog.events.MouseWheelHandler(
    -          this.getElement());
    -    }
    -    this.getHandler().listen(this.mouseWheelHandler_,
    -        goog.events.MouseWheelHandler.EventType.MOUSEWHEEL,
    -        this.handleMouseWheel_);
    -  } else {
    -    this.getHandler().unlisten(this.mouseWheelHandler_,
    -        goog.events.MouseWheelHandler.EventType.MOUSEWHEEL,
    -        this.handleMouseWheel_);
    -  }
    -};
    -
    -
    -/**
    - * Enables or disables the slider. A disabled slider will ignore all
    - * user-initiated events. Also fires goog.ui.Component.EventType.ENABLE/DISABLE
    - * event as appropriate.
    - * @param {boolean} enable Whether to enable the slider or not.
    - */
    -goog.ui.SliderBase.prototype.setEnabled = function(enable) {
    -  if (this.enabled_ == enable) {
    -    return;
    -  }
    -
    -  var eventType = enable ?
    -      goog.ui.Component.EventType.ENABLE : goog.ui.Component.EventType.DISABLE;
    -  if (this.dispatchEvent(eventType)) {
    -    this.enabled_ = enable;
    -    this.enableEventHandlers_(enable);
    -    if (!enable) {
    -      // Disabling a slider is equivalent to a mouse up event when the block
    -      // increment (if happening) should be halted and any possible event
    -      // handlers be appropriately unlistened.
    -      this.stopBlockIncrementing_();
    -    }
    -    goog.dom.classlist.enable(
    -        goog.asserts.assert(this.getElement()),
    -        goog.ui.SliderBase.DISABLED_CSS_CLASS_, !enable);
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the slider is enabled or not.
    - */
    -goog.ui.SliderBase.prototype.isEnabled = function() {
    -  return this.enabled_;
    -};
    -
    -
    -/**
    - * @param {Element} element An element for which we want offsetLeft.
    - * @return {number} Returns the element's offsetLeft, accounting for RTL if
    - *     flipForRtl_ is true.
    - * @private
    - */
    -goog.ui.SliderBase.prototype.getOffsetStart_ = function(element) {
    -  return this.flipForRtl_ ?
    -      goog.style.bidi.getOffsetStart(element) : element.offsetLeft;
    -};
    -
    -
    -/**
    - * @return {?string} The text value for the slider's current value, or null if
    - *     unavailable.
    - */
    -goog.ui.SliderBase.prototype.getTextValue = function() {
    -  return this.labelFn_(this.getValue());
    -};
    -
    -
    -
    -/**
    - * The factory for creating additional animations to be played when animating to
    - * a new value.
    - * @interface
    - */
    -goog.ui.SliderBase.AnimationFactory = function() {};
    -
    -
    -/**
    - * Creates an additonal animation to play when animating to a new value.
    - *
    - * @param {number} previousValue The previous value (before animation).
    - * @param {number} newValue The new value (after animation).
    - * @param {number} interval The animation interval.
    - * @return {!Array<!goog.fx.TransitionBase>} The additional animations to play.
    - */
    -goog.ui.SliderBase.AnimationFactory.prototype.createAnimations;
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/sliderbase_test.html b/src/database/third_party/closure-library/closure/goog/ui/sliderbase_test.html
    deleted file mode 100644
    index 4875a6be45b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/sliderbase_test.html
    +++ /dev/null
    @@ -1,67 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.SliderBase
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script type="text/javascript">
    -   goog.require('goog.ui.SliderBaseTest');
    -  </script>
    -  <style type="text/css">
    -   #oneThumbSlider {
    -  position: relative;
    -  width: 1000px;
    -  background: grey;
    -  height: 20px;
    -}
    -
    -#oneThumbSlider.test-slider-vertical {
    -  height: 1000px;
    -  width: 20px;
    -}
    -
    -#twoThumbSlider {
    -  position: relative;
    -  /* Extra 20px is so distance between thumb centers is 1000px */
    -  width: 1020px;
    -}
    -
    -#valueThumb, #extentThumb {
    -  position: absolute;
    -  width: 20px;
    -}
    -
    -#thumb {
    -  position: absolute;
    -  width: 20px;
    -  height: 20px;
    -  background: black;
    -  top: 5px;
    -}
    -
    -.test-slider-vertical > #thumb {
    -  left: 5px;
    -  top: auto;
    -}
    -
    -#rangeHighlight {
    -  position: absolute;
    -}
    -  </style>
    - </head>
    - <body>
    -  <div id="sandbox">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/sliderbase_test.js b/src/database/third_party/closure-library/closure/goog/ui/sliderbase_test.js
    deleted file mode 100644
    index d9a6a924333..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/sliderbase_test.js
    +++ /dev/null
    @@ -1,948 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.SliderBaseTest');
    -goog.setTestOnly('goog.ui.SliderBaseTest');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.fx.Animation');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.style');
    -goog.require('goog.style.bidi');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.MockControl');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.mockmatchers');
    -goog.require('goog.testing.recordFunction');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.SliderBase');
    -goog.require('goog.userAgent');
    -
    -var oneThumbSlider;
    -var oneThumbSliderRtl;
    -var oneChangeEventCount;
    -
    -var twoThumbSlider;
    -var twoThumbSliderRtl;
    -var twoChangeEventCount;
    -
    -var mockClock;
    -var mockAnimation;
    -
    -
    -
    -/**
    - * A basic class to implement the abstract goog.ui.SliderBase for testing.
    - * @constructor
    - * @extends {goog.ui.SliderBase}
    - */
    -function OneThumbSlider() {
    -  goog.ui.SliderBase.call(this, undefined /* domHelper */, function(value) {
    -    return value > 5 ? 'A big value.' : 'A small value.';
    -  });
    -}
    -goog.inherits(OneThumbSlider, goog.ui.SliderBase);
    -
    -
    -/** @override */
    -OneThumbSlider.prototype.createThumbs = function() {
    -  this.valueThumb = this.extentThumb = goog.dom.getElement('thumb');
    -};
    -
    -
    -/** @override */
    -OneThumbSlider.prototype.getCssClass = function(orientation) {
    -  return goog.getCssName('test-slider', orientation);
    -};
    -
    -
    -
    -/**
    - * A basic class to implement the abstract goog.ui.SliderBase for testing.
    - * @constructor
    - * @extends {goog.ui.SliderBase}
    - */
    -function TwoThumbSlider() {
    -  goog.ui.SliderBase.call(this);
    -}
    -goog.inherits(TwoThumbSlider, goog.ui.SliderBase);
    -
    -
    -/** @override */
    -TwoThumbSlider.prototype.createThumbs = function() {
    -  this.valueThumb = goog.dom.getElement('valueThumb');
    -  this.extentThumb = goog.dom.getElement('extentThumb');
    -  this.rangeHighlight = goog.dom.getElement('rangeHighlight');
    -};
    -
    -
    -/** @override */
    -TwoThumbSlider.prototype.getCssClass = function(orientation) {
    -  return goog.getCssName('test-slider', orientation);
    -};
    -
    -
    -
    -/**
    - * Basic class that implements the AnimationFactory interface for testing.
    - * @param {!goog.fx.Animation|!Array<!goog.fx.Animation>} testAnimations The
    - *     test animations to use.
    - * @constructor
    - * @implements {goog.ui.SliderBase.AnimationFactory}
    - */
    -function AnimationFactory(testAnimations) {
    -  this.testAnimations = testAnimations;
    -}
    -
    -
    -/** @override */
    -AnimationFactory.prototype.createAnimations = function() {
    -  return this.testAnimations;
    -};
    -
    -
    -function setUp() {
    -  var sandBox = goog.dom.getElement('sandbox');
    -  mockClock = new goog.testing.MockClock(true);
    -
    -  var oneThumbElem = goog.dom.createDom(
    -      'div', {'id': 'oneThumbSlider'},
    -      goog.dom.createDom('span', {'id': 'thumb'}));
    -  sandBox.appendChild(oneThumbElem);
    -  oneThumbSlider = new OneThumbSlider();
    -  oneThumbSlider.decorate(oneThumbElem);
    -  oneChangeEventCount = 0;
    -  goog.events.listen(oneThumbSlider, goog.ui.Component.EventType.CHANGE,
    -      function() {
    -        oneChangeEventCount++;
    -      });
    -
    -  var twoThumbElem = goog.dom.createDom(
    -      'div', {'id': 'twoThumbSlider'},
    -      goog.dom.createDom('div', {'id': 'rangeHighlight'}),
    -      goog.dom.createDom('span', {'id': 'valueThumb'}),
    -      goog.dom.createDom('span', {'id': 'extentThumb'}));
    -  sandBox.appendChild(twoThumbElem);
    -  twoThumbSlider = new TwoThumbSlider();
    -  twoThumbSlider.decorate(twoThumbElem);
    -  twoChangeEventCount = 0;
    -  goog.events.listen(twoThumbSlider, goog.ui.Component.EventType.CHANGE,
    -      function() {
    -        twoChangeEventCount++;
    -      });
    -
    -  var sandBoxRtl = goog.dom.createDom('div',
    -      {'dir': 'rtl', 'style': 'position:absolute;'});
    -  sandBox.appendChild(sandBoxRtl);
    -
    -  var oneThumbElemRtl = goog.dom.createDom(
    -      'div', {'id': 'oneThumbSliderRtl'},
    -      goog.dom.createDom('span', {'id': 'thumbRtl'}));
    -  sandBoxRtl.appendChild(oneThumbElemRtl);
    -  oneThumbSliderRtl = new OneThumbSlider();
    -  oneThumbSliderRtl.enableFlipForRtl(true);
    -  oneThumbSliderRtl.decorate(oneThumbElemRtl);
    -  goog.events.listen(oneThumbSliderRtl, goog.ui.Component.EventType.CHANGE,
    -      function() {
    -        oneChangeEventCount++;
    -      });
    -
    -  var twoThumbElemRtl = goog.dom.createDom(
    -      'div', {'id': 'twoThumbSliderRtl'},
    -      goog.dom.createDom('div', {'id': 'rangeHighlightRtl'}),
    -      goog.dom.createDom('span', {'id': 'valueThumbRtl'}),
    -      goog.dom.createDom('span', {'id': 'extentThumbRtl'}));
    -  sandBoxRtl.appendChild(twoThumbElemRtl);
    -  twoThumbSliderRtl = new TwoThumbSlider();
    -  twoThumbSliderRtl.enableFlipForRtl(true);
    -  twoThumbSliderRtl.decorate(twoThumbElemRtl);
    -  twoChangeEventCount = 0;
    -  goog.events.listen(twoThumbSliderRtl, goog.ui.Component.EventType.CHANGE,
    -      function() {
    -        twoChangeEventCount++;
    -      });
    -}
    -
    -function tearDown() {
    -  oneThumbSlider.dispose();
    -  twoThumbSlider.dispose();
    -  oneThumbSliderRtl.dispose();
    -  twoThumbSliderRtl.dispose();
    -  mockClock.dispose();
    -  goog.dom.getElement('sandbox').innerHTML = '';
    -}
    -
    -function testGetAndSetValue() {
    -  oneThumbSlider.setValue(30);
    -  assertEquals(30, oneThumbSlider.getValue());
    -  assertEquals('Setting valid value must dispatch only a single change event.',
    -      1, oneChangeEventCount);
    -
    -  oneThumbSlider.setValue(30);
    -  assertEquals(30, oneThumbSlider.getValue());
    -  assertEquals('Setting to same value must not dispatch change event.',
    -      1, oneChangeEventCount);
    -
    -  oneThumbSlider.setValue(-30);
    -  assertEquals('Setting invalid value must not change value.',
    -      30, oneThumbSlider.getValue());
    -  assertEquals('Setting invalid value must not dispatch change event.',
    -      1, oneChangeEventCount);
    -
    -
    -  // Value thumb can't go past extent thumb, so we must move that first to
    -  // allow setting value.
    -  twoThumbSlider.setExtent(70);
    -  twoChangeEventCount = 0;
    -  twoThumbSlider.setValue(60);
    -  assertEquals(60, twoThumbSlider.getValue());
    -  assertEquals('Setting valid value must dispatch only a single change event.',
    -      1, twoChangeEventCount);
    -
    -  twoThumbSlider.setValue(60);
    -  assertEquals(60, twoThumbSlider.getValue());
    -  assertEquals('Setting to same value must not dispatch change event.',
    -      1, twoChangeEventCount);
    -
    -  twoThumbSlider.setValue(-60);
    -  assertEquals('Setting invalid value must not change value.',
    -      60, twoThumbSlider.getValue());
    -  assertEquals('Setting invalid value must not dispatch change event.',
    -      1, twoChangeEventCount);
    -}
    -
    -function testGetAndSetValueRtl() {
    -  var thumbElement = goog.dom.getElement('thumbRtl');
    -  assertEquals(0, goog.style.bidi.getOffsetStart(thumbElement));
    -  assertEquals('', thumbElement.style.left);
    -  assertTrue(thumbElement.style.right >= 0);
    -
    -  oneThumbSliderRtl.setValue(30);
    -  assertEquals(30, oneThumbSliderRtl.getValue());
    -  assertEquals('Setting valid value must dispatch only a single change event.',
    -      1, oneChangeEventCount);
    -
    -  assertEquals('', thumbElement.style.left);
    -  assertTrue(thumbElement.style.right >= 0);
    -
    -  oneThumbSliderRtl.setValue(30);
    -  assertEquals(30, oneThumbSliderRtl.getValue());
    -  assertEquals('Setting to same value must not dispatch change event.',
    -      1, oneChangeEventCount);
    -
    -  oneThumbSliderRtl.setValue(-30);
    -  assertEquals('Setting invalid value must not change value.',
    -      30, oneThumbSliderRtl.getValue());
    -  assertEquals('Setting invalid value must not dispatch change event.',
    -      1, oneChangeEventCount);
    -
    -
    -  // Value thumb can't go past extent thumb, so we must move that first to
    -  // allow setting value.
    -  var valueThumbElement = goog.dom.getElement('valueThumbRtl');
    -  var extentThumbElement = goog.dom.getElement('extentThumbRtl');
    -  assertEquals(0, goog.style.bidi.getOffsetStart(valueThumbElement));
    -  assertEquals(0, goog.style.bidi.getOffsetStart(extentThumbElement));
    -  assertEquals('', valueThumbElement.style.left);
    -  assertTrue(valueThumbElement.style.right >= 0);
    -  assertEquals('', extentThumbElement.style.left);
    -  assertTrue(extentThumbElement.style.right >= 0);
    -
    -  twoThumbSliderRtl.setExtent(70);
    -  twoChangeEventCount = 0;
    -  twoThumbSliderRtl.setValue(60);
    -  assertEquals(60, twoThumbSliderRtl.getValue());
    -  assertEquals('Setting valid value must dispatch only a single change event.',
    -      1, twoChangeEventCount);
    -
    -  twoThumbSliderRtl.setValue(60);
    -  assertEquals(60, twoThumbSliderRtl.getValue());
    -  assertEquals('Setting to same value must not dispatch change event.',
    -      1, twoChangeEventCount);
    -
    -  assertEquals('', valueThumbElement.style.left);
    -  assertTrue(valueThumbElement.style.right >= 0);
    -  assertEquals('', extentThumbElement.style.left);
    -  assertTrue(extentThumbElement.style.right >= 0);
    -
    -  twoThumbSliderRtl.setValue(-60);
    -  assertEquals('Setting invalid value must not change value.',
    -      60, twoThumbSliderRtl.getValue());
    -  assertEquals('Setting invalid value must not dispatch change event.',
    -      1, twoChangeEventCount);
    -}
    -
    -function testGetAndSetExtent() {
    -  // Note(user): With a one thumb slider the API only really makes sense if you
    -  // always use setValue since there is no extent.
    -
    -  twoThumbSlider.setExtent(7);
    -  assertEquals(7, twoThumbSlider.getExtent());
    -  assertEquals('Setting valid value must dispatch only a single change event.',
    -      1, twoChangeEventCount);
    -
    -  twoThumbSlider.setExtent(7);
    -  assertEquals(7, twoThumbSlider.getExtent());
    -  assertEquals('Setting to same value must not dispatch change event.',
    -      1, twoChangeEventCount);
    -
    -  twoThumbSlider.setExtent(-7);
    -  assertEquals('Setting invalid value must not change value.',
    -      7, twoThumbSlider.getExtent());
    -  assertEquals('Setting invalid value must not dispatch change event.',
    -      1, twoChangeEventCount);
    -}
    -
    -function testUpdateValueExtent() {
    -  twoThumbSlider.setValueAndExtent(30, 50);
    -
    -  assertNotNull(twoThumbSlider.getElement());
    -  assertEquals('Setting value results in updating aria-valuenow',
    -      '30',
    -      goog.a11y.aria.getState(twoThumbSlider.getElement(),
    -          goog.a11y.aria.State.VALUENOW));
    -  assertEquals(30, twoThumbSlider.getValue());
    -  assertEquals(50, twoThumbSlider.getExtent());
    -}
    -
    -function testValueText() {
    -  oneThumbSlider.setValue(10);
    -  assertEquals('Setting value results in correct aria-valuetext',
    -      'A big value.', goog.a11y.aria.getState(oneThumbSlider.getElement(),
    -          goog.a11y.aria.State.VALUETEXT));
    -  oneThumbSlider.setValue(2);
    -  assertEquals('Updating value results in updated aria-valuetext',
    -      'A small value.', goog.a11y.aria.getState(oneThumbSlider.getElement(),
    -          goog.a11y.aria.State.VALUETEXT));
    -}
    -
    -function testGetValueText() {
    -  oneThumbSlider.setValue(10);
    -  assertEquals('Getting the text value gets the correct description',
    -      'A big value.', oneThumbSlider.getTextValue());
    -  oneThumbSlider.setValue(2);
    -  assertEquals(
    -      'Getting the updated text value gets the correct updated description',
    -      'A small value.', oneThumbSlider.getTextValue());
    -}
    -
    -function testRangeListener() {
    -  var slider = new goog.ui.SliderBase;
    -  slider.updateUi_ = slider.updateAriaStates = function() {};
    -  slider.rangeModel.setValue(0);
    -
    -  var f = goog.testing.recordFunction();
    -  goog.events.listen(slider, goog.ui.Component.EventType.CHANGE, f);
    -
    -  slider.rangeModel.setValue(50);
    -  assertEquals(1, f.getCallCount());
    -
    -  slider.exitDocument();
    -  slider.rangeModel.setValue(0);
    -  assertEquals('The range model listener should not have been removed so we ' +
    -               'should have gotten a second event dispatch',
    -               2, f.getCallCount());
    -}
    -
    -
    -/**
    - * Verifies that rangeHighlight position and size are correct for the given
    - * startValue and endValue. Assumes slider has default min/max values [0, 100],
    - * width of 1020px, and thumb widths of 20px, with rangeHighlight drawn from
    - * the centers of the thumbs.
    - * @param {number} rangeHighlight The range highlight.
    - * @param {number} startValue The start value.
    - * @param {number} endValue The end value.
    - */
    -function assertHighlightedRange(rangeHighlight, startValue, endValue) {
    -  var rangeStr = '[' + startValue + ', ' + endValue + ']';
    -  var rangeStart = 10 + 10 * startValue;
    -  assertEquals('Range highlight for ' + rangeStr + ' should start at ' +
    -      rangeStart + 'px.', rangeStart, rangeHighlight.offsetLeft);
    -  var rangeSize = 10 * (endValue - startValue);
    -  assertEquals('Range highlight for ' + rangeStr + ' should have size ' +
    -      rangeSize + 'px.', rangeSize, rangeHighlight.offsetWidth);
    -}
    -
    -function testKeyHandlingTests() {
    -  twoThumbSlider.setValue(0);
    -  twoThumbSlider.setExtent(100);
    -  assertEquals(0, twoThumbSlider.getValue());
    -  assertEquals(100, twoThumbSlider.getExtent());
    -
    -  goog.testing.events.fireKeySequence(
    -      twoThumbSlider.getElement(), goog.events.KeyCodes.RIGHT);
    -  assertEquals(1, twoThumbSlider.getValue());
    -  assertEquals(99, twoThumbSlider.getExtent());
    -
    -  goog.testing.events.fireKeySequence(
    -      twoThumbSlider.getElement(), goog.events.KeyCodes.RIGHT);
    -  assertEquals(2, twoThumbSlider.getValue());
    -  assertEquals(98, twoThumbSlider.getExtent());
    -
    -  goog.testing.events.fireKeySequence(
    -      twoThumbSlider.getElement(), goog.events.KeyCodes.LEFT);
    -  assertEquals(1, twoThumbSlider.getValue());
    -  assertEquals(98, twoThumbSlider.getExtent());
    -
    -  goog.testing.events.fireKeySequence(
    -      twoThumbSlider.getElement(), goog.events.KeyCodes.LEFT);
    -  assertEquals(0, twoThumbSlider.getValue());
    -  assertEquals(98, twoThumbSlider.getExtent());
    -
    -  goog.testing.events.fireKeySequence(
    -      twoThumbSlider.getElement(), goog.events.KeyCodes.RIGHT,
    -      { shiftKey: true });
    -  assertEquals(10, twoThumbSlider.getValue());
    -  assertEquals(90, twoThumbSlider.getExtent());
    -
    -  goog.testing.events.fireKeySequence(
    -      twoThumbSlider.getElement(), goog.events.KeyCodes.RIGHT,
    -      { shiftKey: true });
    -  assertEquals(20, twoThumbSlider.getValue());
    -  assertEquals(80, twoThumbSlider.getExtent());
    -
    -  goog.testing.events.fireKeySequence(
    -      twoThumbSlider.getElement(), goog.events.KeyCodes.LEFT,
    -      { shiftKey: true });
    -  assertEquals(10, twoThumbSlider.getValue());
    -  assertEquals(80, twoThumbSlider.getExtent());
    -
    -  goog.testing.events.fireKeySequence(
    -      twoThumbSlider.getElement(), goog.events.KeyCodes.LEFT,
    -      { shiftKey: true });
    -  assertEquals(0, twoThumbSlider.getValue());
    -  assertEquals(80, twoThumbSlider.getExtent());
    -}
    -
    -function testKeyHandlingLargeStepSize() {
    -  twoThumbSlider.setValue(0);
    -  twoThumbSlider.setExtent(100);
    -  twoThumbSlider.setStep(5);
    -  assertEquals(0, twoThumbSlider.getValue());
    -  assertEquals(100, twoThumbSlider.getExtent());
    -
    -  goog.testing.events.fireKeySequence(
    -      twoThumbSlider.getElement(), goog.events.KeyCodes.RIGHT);
    -  assertEquals(5, twoThumbSlider.getValue());
    -  assertEquals(95, twoThumbSlider.getExtent());
    -
    -  goog.testing.events.fireKeySequence(
    -      twoThumbSlider.getElement(), goog.events.KeyCodes.RIGHT);
    -  assertEquals(10, twoThumbSlider.getValue());
    -  assertEquals(90, twoThumbSlider.getExtent());
    -
    -  goog.testing.events.fireKeySequence(
    -      twoThumbSlider.getElement(), goog.events.KeyCodes.LEFT);
    -  assertEquals(5, twoThumbSlider.getValue());
    -  assertEquals(90, twoThumbSlider.getExtent());
    -
    -  goog.testing.events.fireKeySequence(
    -      twoThumbSlider.getElement(), goog.events.KeyCodes.LEFT);
    -  assertEquals(0, twoThumbSlider.getValue());
    -  assertEquals(90, twoThumbSlider.getExtent());
    -}
    -
    -function testKeyHandlingRtl() {
    -  twoThumbSliderRtl.setValue(0);
    -  twoThumbSliderRtl.setExtent(100);
    -  assertEquals(0, twoThumbSliderRtl.getValue());
    -  assertEquals(100, twoThumbSliderRtl.getExtent());
    -
    -  goog.testing.events.fireKeySequence(
    -      twoThumbSliderRtl.getElement(), goog.events.KeyCodes.RIGHT);
    -  assertEquals(0, twoThumbSliderRtl.getValue());
    -  assertEquals(99, twoThumbSliderRtl.getExtent());
    -
    -  goog.testing.events.fireKeySequence(
    -      twoThumbSliderRtl.getElement(), goog.events.KeyCodes.RIGHT);
    -  assertEquals(0, twoThumbSliderRtl.getValue());
    -  assertEquals(98, twoThumbSliderRtl.getExtent());
    -
    -  goog.testing.events.fireKeySequence(
    -      twoThumbSliderRtl.getElement(), goog.events.KeyCodes.LEFT);
    -  assertEquals(1, twoThumbSliderRtl.getValue());
    -  assertEquals(98, twoThumbSliderRtl.getExtent());
    -
    -  goog.testing.events.fireKeySequence(
    -      twoThumbSliderRtl.getElement(), goog.events.KeyCodes.LEFT);
    -  assertEquals(2, twoThumbSliderRtl.getValue());
    -  assertEquals(98, twoThumbSliderRtl.getExtent());
    -
    -  goog.testing.events.fireKeySequence(
    -      twoThumbSliderRtl.getElement(), goog.events.KeyCodes.RIGHT,
    -      { shiftKey: true });
    -  assertEquals(0, twoThumbSliderRtl.getValue());
    -  assertEquals(90, twoThumbSliderRtl.getExtent());
    -
    -  goog.testing.events.fireKeySequence(
    -      twoThumbSliderRtl.getElement(), goog.events.KeyCodes.RIGHT,
    -      { shiftKey: true });
    -  assertEquals(0, twoThumbSliderRtl.getValue());
    -  assertEquals(80, twoThumbSliderRtl.getExtent());
    -
    -  goog.testing.events.fireKeySequence(
    -      twoThumbSliderRtl.getElement(), goog.events.KeyCodes.LEFT,
    -      { shiftKey: true });
    -  assertEquals(10, twoThumbSliderRtl.getValue());
    -  assertEquals(80, twoThumbSliderRtl.getExtent());
    -
    -  goog.testing.events.fireKeySequence(
    -      twoThumbSliderRtl.getElement(), goog.events.KeyCodes.LEFT,
    -      { shiftKey: true });
    -  assertEquals(20, twoThumbSliderRtl.getValue());
    -  assertEquals(80, twoThumbSliderRtl.getExtent());
    -}
    -
    -function testRangeHighlight() {
    -  var rangeHighlight = goog.dom.getElement('rangeHighlight');
    -
    -  // Test [0, 100]
    -  twoThumbSlider.setValue(0);
    -  twoThumbSlider.setExtent(100);
    -  assertHighlightedRange(rangeHighlight, 0, 100);
    -
    -  // Test [25, 75]
    -  twoThumbSlider.setValue(25);
    -  twoThumbSlider.setExtent(50);
    -  assertHighlightedRange(rangeHighlight, 25, 75);
    -
    -  // Test [50, 50]
    -  twoThumbSlider.setValue(50);
    -  twoThumbSlider.setExtent(0);
    -  assertHighlightedRange(rangeHighlight, 50, 50);
    -}
    -
    -function testRangeHighlightAnimation() {
    -  var animationDelay = 160; // Delay in ms, is a bit higher than actual delay.
    -  if (goog.userAgent.IE) {
    -    // For some reason, (probably due to how timing works), IE7 and IE8 will not
    -    // stop if we don't wait for it.
    -    animationDelay = 250;
    -  }
    -
    -  var rangeHighlight = goog.dom.getElement('rangeHighlight');
    -  twoThumbSlider.setValue(0);
    -  twoThumbSlider.setExtent(100);
    -
    -  // Animate right thumb, final range is [0, 75]
    -  twoThumbSlider.animatedSetValue(75);
    -  assertHighlightedRange(rangeHighlight, 0, 100);
    -  mockClock.tick(animationDelay);
    -  assertHighlightedRange(rangeHighlight, 0, 75);
    -
    -  // Animate left thumb, final range is [25, 75]
    -  twoThumbSlider.animatedSetValue(25);
    -  assertHighlightedRange(rangeHighlight, 0, 75);
    -  mockClock.tick(animationDelay);
    -  assertHighlightedRange(rangeHighlight, 25, 75);
    -}
    -
    -
    -/**
    - * Verifies that no error occurs and that the range highlight is sized correctly
    - * for a zero-size slider (i.e. doesn't attempt to set a negative size). The
    - * test tries to resize the slider from its original size to 0, then checks
    - * that the range highlight's size is correctly set to 0.
    - *
    - * The size verification is needed because Webkit/Gecko outright ignore calls
    - * to set negative sizes on an element, leaving it at its former size. IE
    - * throws an error in the same situation.
    - */
    -function testRangeHighlightForZeroSizeSlider() {
    -  // Make sure range highlight spans whole slider before zeroing width.
    -  twoThumbSlider.setExtent(100);
    -  twoThumbSlider.getElement().style.width = 0;
    -
    -  // The setVisible call is used to force a UI update.
    -  twoThumbSlider.setVisible(true);
    -  assertEquals('Range highlight size should be 0 when slider size is 0',
    -      0, goog.dom.getElement('rangeHighlight').offsetWidth);
    -}
    -
    -function testAnimatedSetValueAnimatesFactoryCreatedAnimations() {
    -  // Create and set the factory.
    -  var ignore = goog.testing.mockmatchers.ignoreArgument;
    -  var mockControl = new goog.testing.MockControl();
    -  var mockAnimation1 = mockControl.createLooseMock(goog.fx.Animation);
    -  var mockAnimation2 = mockControl.createLooseMock(goog.fx.Animation);
    -  var testAnimations = [mockAnimation1, mockAnimation2];
    -  oneThumbSlider.setAdditionalAnimations(new AnimationFactory(testAnimations));
    -
    -  // Expect the animations to be played.
    -  mockAnimation1.play(false);
    -  mockAnimation2.play(false);
    -  mockAnimation1.addEventListener(ignore, ignore, ignore);
    -  mockAnimation2.addEventListener(ignore, ignore, ignore);
    -
    -  // Animate and verify.
    -  mockControl.$replayAll();
    -  oneThumbSlider.animatedSetValue(50);
    -  mockControl.$verifyAll();
    -  mockControl.$resetAll();
    -  mockControl.$tearDown();
    -}
    -
    -function testMouseWheelEventHandlerEnable() {
    -  // Mouse wheel handling should be enabled by default.
    -  assertTrue(oneThumbSlider.isHandleMouseWheel());
    -
    -  // Test disabling the mouse wheel handler
    -  oneThumbSlider.setHandleMouseWheel(false);
    -  assertFalse(oneThumbSlider.isHandleMouseWheel());
    -
    -  // Test that enabling again works fine.
    -  oneThumbSlider.setHandleMouseWheel(true);
    -  assertTrue(oneThumbSlider.isHandleMouseWheel());
    -
    -  // Test that mouse wheel handling can be disabled before rendering a slider.
    -  var wheelDisabledElem = goog.dom.createDom(
    -      'div', {}, goog.dom.createDom('span'));
    -  var wheelDisabledSlider = new OneThumbSlider();
    -  wheelDisabledSlider.setHandleMouseWheel(false);
    -  wheelDisabledSlider.decorate(wheelDisabledElem);
    -  assertFalse(wheelDisabledSlider.isHandleMouseWheel());
    -}
    -
    -function testDisabledAndEnabledSlider() {
    -  // Check that a slider is enabled by default
    -  assertTrue(oneThumbSlider.isEnabled());
    -
    -  var listenerCount = oneThumbSlider.getHandler().getListenerCount();
    -  // Disable the slider and check its state
    -  oneThumbSlider.setEnabled(false);
    -  assertFalse(oneThumbSlider.isEnabled());
    -  assertTrue(goog.dom.classlist.contains(
    -      oneThumbSlider.getElement(), 'goog-slider-disabled'));
    -  assertEquals(0, oneThumbSlider.getHandler().getListenerCount());
    -
    -  // setValue should work unaffected even when the slider is disabled.
    -  oneThumbSlider.setValue(30);
    -  assertEquals(30, oneThumbSlider.getValue());
    -  assertEquals('Setting valid value must dispatch a change event ' +
    -      'even when slider is disabled.', 1, oneChangeEventCount);
    -
    -  // Test the transition from disabled to enabled
    -  oneThumbSlider.setEnabled(true);
    -  assertTrue(oneThumbSlider.isEnabled());
    -  assertFalse(goog.dom.classlist.contains(
    -      oneThumbSlider.getElement(), 'goog-slider-disabled'));
    -  assertTrue(listenerCount == oneThumbSlider.getHandler().getListenerCount());
    -}
    -
    -function testBlockIncrementingWithEnableAndDisabled() {
    -  var doc = goog.dom.getOwnerDocument(oneThumbSlider.getElement());
    -  // Case when slider is not disabled between the mouse down and up events.
    -  goog.testing.events.fireMouseDownEvent(oneThumbSlider.getElement());
    -  assertEquals(1, goog.events.getListeners(
    -      oneThumbSlider.getElement(),
    -      goog.events.EventType.MOUSEMOVE, false).length);
    -  assertEquals(1, goog.events.getListeners(
    -      doc, goog.events.EventType.MOUSEUP, true).length);
    -
    -  goog.testing.events.fireMouseUpEvent(oneThumbSlider.getElement());
    -
    -  assertEquals(0, goog.events.getListeners(
    -      oneThumbSlider.getElement(),
    -      goog.events.EventType.MOUSEMOVE, false).length);
    -  assertEquals(0, goog.events.getListeners(
    -      doc, goog.events.EventType.MOUSEUP, true).length);
    -
    -  // Case when the slider is disabled between the mouse down and up events.
    -  goog.testing.events.fireMouseDownEvent(oneThumbSlider.getElement());
    -  assertEquals(1, goog.events.getListeners(
    -      oneThumbSlider.getElement(),
    -      goog.events.EventType.MOUSEMOVE, false).length);
    -  assertEquals(1,
    -      goog.events.getListeners(doc,
    -      goog.events.EventType.MOUSEUP, true).length);
    -
    -  oneThumbSlider.setEnabled(false);
    -
    -  assertEquals(0, goog.events.getListeners(
    -      oneThumbSlider.getElement(),
    -      goog.events.EventType.MOUSEMOVE, false).length);
    -  assertEquals(0, goog.events.getListeners(
    -      doc, goog.events.EventType.MOUSEUP, true).length);
    -  assertEquals(1, oneThumbSlider.getHandler().getListenerCount());
    -
    -  goog.testing.events.fireMouseUpEvent(oneThumbSlider.getElement());
    -  assertEquals(0, goog.events.getListeners(
    -      oneThumbSlider.getElement(),
    -      goog.events.EventType.MOUSEMOVE, false).length);
    -  assertEquals(0, goog.events.getListeners(
    -      doc, goog.events.EventType.MOUSEUP, true).length);
    -}
    -
    -function testMouseClickWithMoveToPointEnabled() {
    -  var stepSize = 20;
    -  oneThumbSlider.setStep(stepSize);
    -  oneThumbSlider.setMoveToPointEnabled(true);
    -  var initialValue = oneThumbSlider.getValue();
    -
    -  // Figure out the number of pixels per step.
    -  var numSteps = Math.round(
    -      (oneThumbSlider.getMaximum() - oneThumbSlider.getMinimum()) / stepSize);
    -  var size = goog.style.getSize(oneThumbSlider.getElement());
    -  var pixelsPerStep = Math.round(size.width / numSteps);
    -
    -  var coords = goog.style.getClientPosition(oneThumbSlider.getElement());
    -  coords.x += pixelsPerStep / 2;
    -
    -  // Case when value is increased
    -  goog.testing.events.fireClickSequence(oneThumbSlider.getElement(),
    -      /* opt_button */ undefined, coords);
    -  assertEquals(oneThumbSlider.getValue(), initialValue + stepSize);
    -
    -  // Case when value is decreased
    -  goog.testing.events.fireClickSequence(oneThumbSlider.getElement(),
    -      /* opt_button */ undefined, coords);
    -  assertEquals(oneThumbSlider.getValue(), initialValue);
    -
    -  // Case when thumb is clicked
    -  goog.testing.events.fireClickSequence(oneThumbSlider.getElement());
    -  assertEquals(oneThumbSlider.getValue(), initialValue);
    -}
    -
    -function testNonIntegerStepSize() {
    -  var stepSize = 0.02;
    -  oneThumbSlider.setStep(stepSize);
    -  oneThumbSlider.setMinimum(-1);
    -  oneThumbSlider.setMaximum(1);
    -  oneThumbSlider.setValue(0.7);
    -  assertRoughlyEquals(0.7, oneThumbSlider.getValue(), 0.000001);
    -  oneThumbSlider.setValue(0.3);
    -  assertRoughlyEquals(0.3, oneThumbSlider.getValue(), 0.000001);
    -}
    -
    -function testSingleThumbSliderHasZeroExtent() {
    -  var stepSize = 0.02;
    -  oneThumbSlider.setStep(stepSize);
    -  oneThumbSlider.setMinimum(-1);
    -  oneThumbSlider.setMaximum(1);
    -  oneThumbSlider.setValue(0.7);
    -  assertEquals(0, oneThumbSlider.getExtent());
    -  oneThumbSlider.setValue(0.3);
    -  assertEquals(0, oneThumbSlider.getExtent());
    -}
    -
    -
    -/**
    - * Tests getThumbCoordinateForValue method.
    - */
    -function testThumbCoordinateForValueWithHorizontalSlider() {
    -  // Make sure the y-coordinate stays the same for the horizontal slider.
    -  var originalY = goog.style.getPosition(oneThumbSlider.valueThumb).y;
    -  var width = oneThumbSlider.getElement().clientWidth -
    -      oneThumbSlider.valueThumb.offsetWidth;
    -  var range = oneThumbSlider.getMaximum() - oneThumbSlider.getMinimum();
    -
    -  // Verify coordinate for a particular value.
    -  var value = 20;
    -  var expectedX = Math.round(value / range * width);
    -  var expectedCoord = new goog.math.Coordinate(expectedX, originalY);
    -  var coord = oneThumbSlider.getThumbCoordinateForValue(value);
    -  assertObjectEquals(expectedCoord, coord);
    -
    -  // Verify this works regardless of current position.
    -  oneThumbSlider.setValue(value / 2);
    -  coord = oneThumbSlider.getThumbCoordinateForValue(value);
    -  assertObjectEquals(expectedCoord, coord);
    -}
    -
    -function testThumbCoordinateForValueWithVerticalSlider() {
    -  // Make sure the x-coordinate stays the same for the vertical slider.
    -  oneThumbSlider.setOrientation(goog.ui.SliderBase.Orientation.VERTICAL);
    -  var originalX = goog.style.getPosition(oneThumbSlider.valueThumb).x;
    -  var height = oneThumbSlider.getElement().clientHeight -
    -      oneThumbSlider.valueThumb.offsetHeight;
    -  var range = oneThumbSlider.getMaximum() - oneThumbSlider.getMinimum();
    -
    -  // Verify coordinate for a particular value.
    -  var value = 20;
    -  var expectedY = height - Math.round(value / range * height);
    -  var expectedCoord = new goog.math.Coordinate(originalX, expectedY);
    -  var coord = oneThumbSlider.getThumbCoordinateForValue(value);
    -  assertObjectEquals(expectedCoord, coord);
    -
    -  // Verify this works regardless of current position.
    -  oneThumbSlider.setValue(value / 2);
    -  coord = oneThumbSlider.getThumbCoordinateForValue(value);
    -  assertObjectEquals(expectedCoord, coord);
    -}
    -
    -
    -/**
    - * Tests getValueFromMousePosition method.
    - */
    -function testValueFromMousePosition() {
    -  var value = 30;
    -  oneThumbSlider.setValue(value);
    -  var offset = goog.style.getPageOffset(oneThumbSlider.valueThumb);
    -  var size = goog.style.getSize(oneThumbSlider.valueThumb);
    -  offset.x += size.width / 2;
    -  offset.y += size.height / 2;
    -  var e = null;
    -  goog.events.listen(oneThumbSlider, goog.events.EventType.MOUSEMOVE,
    -      function(evt) {
    -        e = evt;
    -      });
    -  goog.testing.events.fireMouseMoveEvent(oneThumbSlider, offset);
    -  assertNotEquals(e, null);
    -  assertEquals(
    -      value, Math.round(oneThumbSlider.getValueFromMousePosition(e)));
    -  // Verify this works regardless of current position.
    -  oneThumbSlider.setValue(value / 2);
    -  assertEquals(
    -      value, Math.round(oneThumbSlider.getValueFromMousePosition(e)));
    -}
    -
    -
    -/**
    - * Tests ignoring click event after mousedown event.
    - */
    -function testClickAfterMousedown() {
    -  // Get the center of the thumb at value zero.
    -  oneThumbSlider.setValue(0);
    -  var offset = goog.style.getPageOffset(oneThumbSlider.valueThumb);
    -  var size = goog.style.getSize(oneThumbSlider.valueThumb);
    -  offset.x += size.width / 2;
    -  offset.y += size.height / 2;
    -
    -  var sliderElement = oneThumbSlider.getElement();
    -  var width = sliderElement.clientWidth - size.width;
    -  var range = oneThumbSlider.getMaximum() - oneThumbSlider.getMinimum();
    -  var offsetXAtZero = offset.x;
    -
    -  // Temporarily control time.
    -  var theTime = goog.now();
    -  var saveGoogNow = goog.now;
    -  goog.now = function() { return theTime; };
    -
    -  // set coordinate for a particular value.
    -  var valueOne = 10;
    -  offset.x = offsetXAtZero + Math.round(valueOne / range * width);
    -  goog.testing.events.fireMouseDownEvent(sliderElement, null, offset);
    -  assertEquals(valueOne, oneThumbSlider.getValue());
    -
    -  // Verify a click event with another value that follows quickly is ignored.
    -  theTime += oneThumbSlider.MOUSE_DOWN_DELAY_ / 2;
    -  var valueTwo = 20;
    -  offset.x = offsetXAtZero + Math.round(valueTwo / range * width);
    -  goog.testing.events.fireClickEvent(sliderElement, null, offset);
    -  assertEquals(valueOne, oneThumbSlider.getValue());
    -
    -  // Verify a click later in time does move the thumb.
    -  theTime += oneThumbSlider.MOUSE_DOWN_DELAY_;
    -  goog.testing.events.fireClickEvent(sliderElement, null, offset);
    -  assertEquals(valueTwo, oneThumbSlider.getValue());
    -
    -  goog.now = saveGoogNow;
    -}
    -
    -
    -/**
    - * Tests dragging events.
    - */
    -function testDragEvents() {
    -  var offset = goog.style.getPageOffset(oneThumbSlider.valueThumb);
    -  var size = goog.style.getSize(oneThumbSlider.valueThumb);
    -  offset.x += size.width / 2;
    -  offset.y += size.height / 2;
    -  var event_types = [];
    -  var handler = function(evt) {
    -    event_types.push(evt.type);
    -  };
    -
    -  goog.events.listen(oneThumbSlider,
    -      [goog.ui.SliderBase.EventType.DRAG_START,
    -       goog.ui.SliderBase.EventType.DRAG_END,
    -       goog.ui.SliderBase.EventType.DRAG_VALUE_START,
    -       goog.ui.SliderBase.EventType.DRAG_VALUE_END,
    -       goog.ui.SliderBase.EventType.DRAG_EXTENT_START,
    -       goog.ui.SliderBase.EventType.DRAG_EXTENT_END,
    -       goog.ui.Component.EventType.CHANGE],
    -      handler);
    -
    -  // Since the order of the events between value and extent is not guaranteed
    -  // accross browsers, we need to allow for both here and once we have
    -  // them all, make sure that they were different.
    -  function isValueOrExtentDragStart(type) {
    -    return type == goog.ui.SliderBase.EventType.DRAG_VALUE_START ||
    -        type == goog.ui.SliderBase.EventType.DRAG_EXTENT_START;
    -  };
    -  function isValueOrExtentDragEnd(type) {
    -    return type == goog.ui.SliderBase.EventType.DRAG_VALUE_END ||
    -        type == goog.ui.SliderBase.EventType.DRAG_EXTENT_END;
    -  };
    -
    -  // Test that dragging the thumb calls all the correct events.
    -  goog.testing.events.fireMouseDownEvent(oneThumbSlider.valueThumb);
    -  offset.x += 100;
    -  goog.testing.events.fireMouseMoveEvent(oneThumbSlider.valueThumb, offset);
    -  goog.testing.events.fireMouseUpEvent(oneThumbSlider.valueThumb);
    -
    -  assertEquals(9, event_types.length);
    -
    -  assertEquals(goog.ui.SliderBase.EventType.DRAG_START, event_types[0]);
    -  assertTrue(isValueOrExtentDragStart(event_types[1]));
    -
    -  assertEquals(goog.ui.SliderBase.EventType.DRAG_START, event_types[2]);
    -  assertTrue(isValueOrExtentDragStart(event_types[3]));
    -
    -  assertEquals(goog.ui.Component.EventType.CHANGE, event_types[4]);
    -
    -  assertEquals(goog.ui.SliderBase.EventType.DRAG_END, event_types[5]);
    -  assertTrue(isValueOrExtentDragEnd(event_types[6]));
    -
    -  assertEquals(goog.ui.SliderBase.EventType.DRAG_END, event_types[7]);
    -  assertTrue(isValueOrExtentDragEnd(event_types[8]));
    -
    -  assertFalse(event_types[1] == event_types[3]);
    -  assertFalse(event_types[6] == event_types[8]);
    -
    -  // Test that clicking the thumb without moving the mouse does not cause a
    -  // CHANGE event between DRAG_START/DRAG_END.
    -  event_types = [];
    -  goog.testing.events.fireMouseDownEvent(oneThumbSlider.valueThumb);
    -  goog.testing.events.fireMouseUpEvent(oneThumbSlider.valueThumb);
    -
    -  assertEquals(8, event_types.length);
    -
    -  assertEquals(goog.ui.SliderBase.EventType.DRAG_START, event_types[0]);
    -  assertTrue(isValueOrExtentDragStart(event_types[1]));
    -
    -  assertEquals(goog.ui.SliderBase.EventType.DRAG_START, event_types[2]);
    -  assertTrue(isValueOrExtentDragStart(event_types[3]));
    -
    -  assertEquals(goog.ui.SliderBase.EventType.DRAG_END, event_types[4]);
    -  assertTrue(isValueOrExtentDragEnd(event_types[5]));
    -
    -  assertEquals(goog.ui.SliderBase.EventType.DRAG_END, event_types[6]);
    -  assertTrue(isValueOrExtentDragEnd(event_types[7]));
    -
    -  assertFalse(event_types[1] == event_types[3]);
    -  assertFalse(event_types[5] == event_types[7]);
    -
    -  // Early listener removal, do not wait for tearDown, to avoid building up
    -  // arrays of events unnecessarilly in further tests.
    -  goog.events.removeAll(oneThumbSlider);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/splitbehavior.js b/src/database/third_party/closure-library/closure/goog/ui/splitbehavior.js
    deleted file mode 100644
    index 4320d901a57..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/splitbehavior.js
    +++ /dev/null
    @@ -1,336 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Behavior for combining two controls.
    - *
    - * @see ../demos/split.html
    - */
    -
    -goog.provide('goog.ui.SplitBehavior');
    -goog.provide('goog.ui.SplitBehavior.DefaultHandlers');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.asserts');
    -goog.require('goog.dispose');
    -goog.require('goog.dom');
    -goog.require('goog.dom.NodeType');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.ui.ButtonSide');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.decorate');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * Creates a behavior for combining two controls. The behavior is triggered
    - * by a given event type which applies the behavior handler.
    - * Can be used to also render or decorate  the controls.
    - * For a usage example see {@link goog.ui.ColorSplitBehavior}
    - *
    - * @param {goog.ui.Control} first A ui control.
    - * @param {goog.ui.Control} second A ui control.
    - * @param {function(goog.ui.Control,Event)=} opt_behaviorHandler A handler
    - *     to apply for the behavior.
    - * @param {string=} opt_eventType The event type triggering the
    - *     handler.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @constructor
    - * @extends {goog.Disposable}
    - */
    -goog.ui.SplitBehavior = function(first, second, opt_behaviorHandler,
    -    opt_eventType, opt_domHelper) {
    -  goog.Disposable.call(this);
    -
    -  /**
    -   * @type {goog.ui.Control}
    -   * @private
    -   */
    -  this.first_ = first;
    -
    -  /**
    -   * @type {goog.ui.Control}
    -   * @private
    -   */
    -  this.second_ = second;
    -
    -  /**
    -   * Handler for this behavior.
    -   * @type {function(goog.ui.Control,Event)}
    -   * @private
    -   */
    -  this.behaviorHandler_ = opt_behaviorHandler ||
    -                          goog.ui.SplitBehavior.DefaultHandlers.CAPTION;
    -
    -  /**
    -   * Event type triggering the behavior.
    -   * @type {string}
    -   * @private
    -   */
    -  this.eventType_ = opt_eventType || goog.ui.Component.EventType.ACTION;
    -
    -  /**
    -   * True iff the behavior is active.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.isActive_ = false;
    -
    -  /**
    -   * Event handler.
    -   * @type {goog.events.EventHandler}
    -   * @private
    -   */
    -  this.eventHandler_ = new goog.events.EventHandler();
    -
    -  /**
    -   * Whether to dispose the first control when dispose is called.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.disposeFirst_ = true;
    -
    -  /**
    -   * Whether to dispose the second control when dispose is called.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.disposeSecond_ = true;
    -};
    -goog.inherits(goog.ui.SplitBehavior, goog.Disposable);
    -goog.tagUnsealableClass(goog.ui.SplitBehavior);
    -
    -
    -/**
    - * Css class for elements rendered by this behavior.
    - * @type {string}
    - */
    -goog.ui.SplitBehavior.CSS_CLASS = goog.getCssName('goog-split-behavior');
    -
    -
    -/**
    - * An emum of split behavior handlers.
    - * @enum {function(goog.ui.Control,Event)}
    - */
    -goog.ui.SplitBehavior.DefaultHandlers = {
    -  NONE: goog.nullFunction,
    -  CAPTION: function(targetControl, e) {
    -    var item = /** @type {goog.ui.MenuItem} */ (e.target);
    -    var value = (/** @type {string} */((item && item.getValue()) || ''));
    -    var button = /** @type {goog.ui.Button} */ (targetControl);
    -    button.setCaption && button.setCaption(value);
    -    button.setValue && button.setValue(value);
    -  },
    -  VALUE: function(targetControl, e) {
    -    var item = /** @type {goog.ui.MenuItem} */ (e.target);
    -    var value = (/** @type {string} */(item && item.getValue()) || '');
    -    var button = /** @type {goog.ui.Button} */ (targetControl);
    -    button.setValue && button.setValue(value);
    -  }
    -};
    -
    -
    -/**
    - * The element containing the controls.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.SplitBehavior.prototype.element_ = null;
    -
    -
    -/**
    - * @return {Element} The element containing the controls.
    - */
    -goog.ui.SplitBehavior.prototype.getElement = function() {
    -  return this.element_;
    -};
    -
    -
    -/**
    - * @return {function(goog.ui.Control,Event)} The behavior handler.
    - */
    -goog.ui.SplitBehavior.prototype.getBehaviorHandler = function() {
    -  return this.behaviorHandler_;
    -};
    -
    -
    -/**
    - * @return {string} The behavior event type.
    - */
    -goog.ui.SplitBehavior.prototype.getEventType = function() {
    -  return this.eventType_;
    -};
    -
    -
    -/**
    - * Sets the disposeControls flags.
    - * @param {boolean} disposeFirst Whether to dispose the first control
    - *     when dispose is called.
    - * @param {boolean} disposeSecond Whether to dispose the second control
    - *     when dispose is called.
    - */
    -goog.ui.SplitBehavior.prototype.setDisposeControls = function(disposeFirst,
    -    disposeSecond) {
    -  this.disposeFirst_ = !!disposeFirst;
    -  this.disposeSecond_ = !!disposeSecond;
    -};
    -
    -
    -/**
    - * Sets the behavior handler.
    - * @param {function(goog.ui.Control,Event)} behaviorHandler The behavior
    - *     handler.
    - */
    -goog.ui.SplitBehavior.prototype.setHandler = function(behaviorHandler) {
    -  this.behaviorHandler_ = behaviorHandler;
    -  if (this.isActive_) {
    -    this.setActive(false);
    -    this.setActive(true);
    -  }
    -};
    -
    -
    -/**
    - * Sets the behavior event type.
    - * @param {string} eventType The behavior event type.
    - */
    -goog.ui.SplitBehavior.prototype.setEventType = function(eventType) {
    -  this.eventType_ = eventType;
    -  if (this.isActive_) {
    -    this.setActive(false);
    -    this.setActive(true);
    -  }
    -};
    -
    -
    -/**
    - * Decorates an element and returns the behavior.
    - * @param {Element} element An element to decorate.
    - * @param {boolean=} opt_activate Whether to activate the behavior
    - *     (default=true).
    - * @return {!goog.ui.SplitBehavior} A split behavior.
    - */
    -goog.ui.SplitBehavior.prototype.decorate = function(element, opt_activate) {
    -  if (this.first_ || this.second_) {
    -    throw Error('Cannot decorate controls are already set');
    -  }
    -  this.decorateChildren_(element);
    -  var activate = goog.isDefAndNotNull(opt_activate) ? !!opt_activate : true;
    -  this.element_ = element;
    -  this.setActive(activate);
    -  return this;
    -};
    -
    -
    -/**
    - * Renders an element and returns the behavior.
    - * @param {Element} element An element to decorate.
    - * @param {boolean=} opt_activate Whether to activate the behavior
    - *     (default=true).
    - * @return {!goog.ui.SplitBehavior} A split behavior.
    - */
    -goog.ui.SplitBehavior.prototype.render = function(element, opt_activate) {
    -  goog.asserts.assert(element);
    -  goog.dom.classlist.add(element, goog.ui.SplitBehavior.CSS_CLASS);
    -  this.first_.render(element);
    -  this.second_.render(element);
    -  this.collapseSides_(this.first_, this.second_);
    -  var activate = goog.isDefAndNotNull(opt_activate) ? !!opt_activate : true;
    -  this.element_ = element;
    -  this.setActive(activate);
    -  return this;
    -};
    -
    -
    -/**
    - * Activate or deactivate the behavior.
    - * @param {boolean} activate Whether to activate or deactivate the behavior.
    - */
    -goog.ui.SplitBehavior.prototype.setActive = function(activate) {
    -  if (this.isActive_ == activate) {
    -    return;
    -  }
    -  this.isActive_ = activate;
    -  if (activate) {
    -    this.eventHandler_.listen(this.second_, this.eventType_,
    -        goog.bind(this.behaviorHandler_, this, this.first_));
    -    // TODO(user): should we call the handler here to sync between
    -    // first_ and second_.
    -  } else {
    -    this.eventHandler_.removeAll();
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.SplitBehavior.prototype.disposeInternal = function() {
    -  this.setActive(false);
    -  goog.dispose(this.eventHandler_);
    -  if (this.disposeFirst_) {
    -    goog.dispose(this.first_);
    -  }
    -  if (this.disposeSecond_) {
    -    goog.dispose(this.second_);
    -  }
    -  goog.ui.SplitBehavior.superClass_.disposeInternal.call(this);
    -};
    -
    -
    -/**
    - * Decorates two child nodes of the given element.
    - * @param {Element} element An element to render two of it's child nodes.
    - * @private
    - */
    -goog.ui.SplitBehavior.prototype.decorateChildren_ = function(
    -    element) {
    -  var childNodes = element.childNodes;
    -  var len = childNodes.length;
    -  var finished = false;
    -  for (var i = 0; i < len && !finished; i++) {
    -    var child = childNodes[i];
    -    if (child.nodeType == goog.dom.NodeType.ELEMENT) {
    -      if (!this.first_) {
    -        this.first_ = /** @type {goog.ui.Control} */ (goog.ui.decorate(child));
    -      } else if (!this.second_) {
    -        this.second_ = /** @type {goog.ui.Control} */ (goog.ui.decorate(child));
    -        finished = true;
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Collapse the the controls together.
    - * @param {goog.ui.Control} first The first element.
    - * @param {goog.ui.Control} second The second element.
    - * @private
    - */
    -goog.ui.SplitBehavior.prototype.collapseSides_ = function(first, second) {
    -  if (goog.isFunction(first.setCollapsed) &&
    -      goog.isFunction(second.setCollapsed)) {
    -    first.setCollapsed(goog.ui.ButtonSide.END);
    -    second.setCollapsed(goog.ui.ButtonSide.START);
    -  }
    -};
    -
    -
    -// Register a decorator factory function for goog.ui.Buttons.
    -goog.ui.registry.setDecoratorByClassName(goog.ui.SplitBehavior.CSS_CLASS,
    -    function() {
    -      return new goog.ui.SplitBehavior(null, null);
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/splitbehavior_test.html b/src/database/third_party/closure-library/closure/goog/ui/splitbehavior_test.html
    deleted file mode 100644
    index b6e352441ef..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/splitbehavior_test.html
    +++ /dev/null
    @@ -1,26 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.SplitBehavior
    -  </title>
    -  <script type="text/javascript" src="../base.js">
    -  </script>
    -  <script type="text/javascript">
    -   goog.require('goog.ui.SplitBehaviorTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="split">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/splitbehavior_test.js b/src/database/third_party/closure-library/closure/goog/ui/splitbehavior_test.js
    deleted file mode 100644
    index 11040564427..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/splitbehavior_test.js
    +++ /dev/null
    @@ -1,154 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.SplitBehaviorTest');
    -goog.setTestOnly('goog.ui.SplitBehaviorTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.Event');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.CustomButton');
    -goog.require('goog.ui.Menu');
    -goog.require('goog.ui.MenuButton');
    -goog.require('goog.ui.MenuItem');
    -goog.require('goog.ui.SplitBehavior');
    -goog.require('goog.ui.decorate');
    -
    -var splitbehavior;
    -var button;
    -var menuValues;
    -var menu;
    -var menuButton;
    -var splitDiv;
    -
    -function setUp() {
    -  splitDiv = document.getElementById('split');
    -  button = new goog.ui.CustomButton('text');
    -  menu = new goog.ui.Menu();
    -  menuValues = ['a', 'b', 'c'];
    -  goog.array.forEach(menuValues, function(val) {
    -    menu.addItem(new goog.ui.MenuItem(val));
    -  });
    -  menuButton = new goog.ui.MenuButton('text', menu);
    -  splitbehavior = new goog.ui.SplitBehavior(button, menuButton);
    -}
    -
    -function tearDown() {
    -  button.dispose();
    -  menu.dispose();
    -  menuButton.dispose();
    -  splitbehavior.dispose();
    -  splitDiv.innerHTML = '';
    -  splitDiv.className = '';
    -}
    -
    -function testRender() {
    -  assertEquals('no elements in doc with goog-split-behavior class',
    -      0, goog.dom.getElementsByTagNameAndClass('div',
    -      'goog-split-behavior').length);
    -  splitbehavior.render(splitDiv);
    -  assertEquals('two childs are rendered', 2, splitDiv.childNodes.length);
    -  assertEquals('one element in doc with goog-split-behavior class',
    -      1, goog.dom.getElementsByTagNameAndClass('div',
    -      'goog-split-behavior').length);
    -  assertEquals('one goog-custom-button',
    -      1, goog.dom.getElementsByTagNameAndClass('div',
    -      'goog-custom-button', splitDiv).length);
    -  assertEquals('one goog-menu-button',
    -      1, goog.dom.getElementsByTagNameAndClass('div',
    -      'goog-menu-button', splitDiv).length);
    -}
    -
    -function testDecorate() {
    -  var decorateDiv = goog.dom.createDom('div', 'goog-split-behavior',
    -      goog.dom.createDom('div', 'goog-custom-button'),
    -      goog.dom.createDom('div', 'goog-menu-button'));
    -  goog.dom.appendChild(splitDiv, decorateDiv);
    -  var split = goog.ui.decorate(decorateDiv);
    -  assertNotNull(split);
    -  assertTrue('instance of SplitBehavior',
    -      split.constructor == goog.ui.SplitBehavior);
    -  assertNotNull(split.first_);
    -  assertTrue('instance of CustomButton',
    -      split.first_.constructor == goog.ui.CustomButton);
    -  assertNotNull(split.second_);
    -  assertTrue('instance of MenuButton',
    -      split.second_.constructor == goog.ui.MenuButton);
    -}
    -
    -function testBehaviorDefault() {
    -  splitbehavior.render(splitDiv);
    -  assertEquals('original caption is "text"', 'text', button.getCaption());
    -  var menuItem = menuButton.getMenu().getChildAt(0);
    -  var type = goog.ui.Component.EventType.ACTION;
    -  goog.events.dispatchEvent(menuButton, new goog.events.Event(type, menuItem));
    -  assertEquals('caption is updated to "a"', 'a', button.getCaption());
    -}
    -
    -function testBehaviorCustomEvent() {
    -  splitbehavior.render(splitDiv);
    -  assertEquals('original caption is "text"', 'text', button.getCaption());
    -  var type = goog.ui.Component.EventType.ENTER;
    -  splitbehavior.setEventType(type);
    -  var menuItem = menuButton.getMenu().getChildAt(0);
    -  goog.events.dispatchEvent(menuButton, new goog.events.Event(type, menuItem));
    -  assertEquals('caption is updated to "a"', 'a', button.getCaption());
    -}
    -
    -function testBehaviorCustomHandler() {
    -  splitbehavior.render(splitDiv);
    -  var called = false;
    -  splitbehavior.setHandler(function() { called = true; });
    -  goog.events.dispatchEvent(menuButton, goog.ui.Component.EventType.ACTION);
    -  assertTrue('custom handler is called', called);
    -}
    -
    -function testSetActive() {
    -  splitbehavior.render(splitDiv, false);
    -  assertEquals('original caption is "text"', 'text', button.getCaption());
    -  var menuItem = menuButton.getMenu().getChildAt(0);
    -  var type = goog.ui.Component.EventType.ACTION;
    -  goog.events.dispatchEvent(menuButton, new goog.events.Event(type, menuItem));
    -  assertEquals('caption remains "text"', 'text', button.getCaption());
    -
    -  splitbehavior.setActive(true);
    -  goog.events.dispatchEvent(menuButton, new goog.events.Event(type, menuItem));
    -  assertEquals('caption is updated to "a"', 'a', button.getCaption());
    -}
    -
    -function testDispose() {
    -  goog.dispose(splitbehavior);
    -  assertTrue(splitbehavior.isDisposed());
    -  assertTrue(splitbehavior.first_.isDisposed());
    -  assertTrue(splitbehavior.second_.isDisposed());
    -}
    -
    -function testDisposeNoControls() {
    -  splitbehavior.setDisposeControls(false);
    -  goog.dispose(splitbehavior);
    -  assertTrue(splitbehavior.isDisposed());
    -  assertFalse(splitbehavior.first_.isDisposed());
    -  assertFalse(splitbehavior.second_.isDisposed());
    -}
    -
    -function testDisposeFirstAndNotSecondControl() {
    -  splitbehavior.setDisposeControls(true, false);
    -  goog.dispose(splitbehavior);
    -  assertTrue(splitbehavior.isDisposed());
    -  assertTrue(splitbehavior.first_.isDisposed());
    -  assertFalse(splitbehavior.second_.isDisposed());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/splitpane.js b/src/database/third_party/closure-library/closure/goog/ui/splitpane.js
    deleted file mode 100644
    index 5a8975a103f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/splitpane.js
    +++ /dev/null
    @@ -1,909 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview  Class for splitting two areas with draggable control for
    - * changing size.
    - *
    - * The DOM that is created (or that can be decorated) looks like this:
    - * <div class='goog-splitpane'>
    - *   <div class='goog-splitpane-first-container'></div>
    - *   <div class='goog-splitpane-second-container'></div>
    - *   <div class='goog-splitpane-handle'></div>
    - * </div>
    - *
    - * The content to be split goes in the first and second DIVs, the third one
    - * is for managing (and styling) the splitter handle.
    - *
    - * @see ../demos/splitpane.html
    - */
    -
    -
    -goog.provide('goog.ui.SplitPane');
    -goog.provide('goog.ui.SplitPane.Orientation');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events.EventType');
    -goog.require('goog.fx.Dragger');
    -goog.require('goog.math.Rect');
    -goog.require('goog.math.Size');
    -goog.require('goog.style');
    -goog.require('goog.ui.Component');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * A left/right up/down Container SplitPane.
    - * Create SplitPane with two goog.ui.Component opjects to split.
    - * TODO(user): Support minimum splitpane size.
    - * TODO(user): Allow component change/orientation after init.
    - * TODO(user): Support hiding either side of handle (plus handle).
    - * TODO(user): Look at setBorderBoxSize fixes and revist borderwidth code.
    - *
    - * @param {goog.ui.Component} firstComponent Left or Top component.
    - * @param {goog.ui.Component} secondComponent Right or Bottom component.
    - * @param {goog.ui.SplitPane.Orientation} orientation SplitPane orientation.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @extends {goog.ui.Component}
    - * @constructor
    - */
    -goog.ui.SplitPane = function(firstComponent, secondComponent, orientation,
    -    opt_domHelper) {
    -  goog.ui.SplitPane.base(this, 'constructor', opt_domHelper);
    -
    -  /**
    -   * The orientation of the containers.
    -   * @type {goog.ui.SplitPane.Orientation}
    -   * @private
    -   */
    -  this.orientation_ = orientation;
    -
    -  /**
    -   * The left/top component.
    -   * @type {goog.ui.Component}
    -   * @private
    -   */
    -  this.firstComponent_ = firstComponent;
    -  this.addChild(firstComponent);
    -
    -  /**
    -   * The right/bottom component.
    -   * @type {goog.ui.Component}
    -   * @private
    -   */
    -  this.secondComponent_ = secondComponent;
    -  this.addChild(secondComponent);
    -
    -  /** @private {Element} */
    -  this.splitpaneHandle_ = null;
    -};
    -goog.inherits(goog.ui.SplitPane, goog.ui.Component);
    -goog.tagUnsealableClass(goog.ui.SplitPane);
    -
    -
    -/**
    - * Events.
    - * @enum {string}
    - */
    -goog.ui.SplitPane.EventType = {
    -
    -  /**
    -   * Dispatched after handle drag.
    -   */
    -  HANDLE_DRAG: 'handle_drag',
    -
    -  /**
    -   * Dispatched after handle drag end.
    -   */
    -  HANDLE_DRAG_END: 'handle_drag_end',
    -
    -  /**
    -   * Dispatched after handle snap (double-click splitter).
    -   */
    -  HANDLE_SNAP: 'handle_snap'
    -};
    -
    -
    -/**
    - * CSS class names for splitpane outer container.
    - * @type {string}
    - * @private
    - */
    -goog.ui.SplitPane.CLASS_NAME_ = goog.getCssName('goog-splitpane');
    -
    -
    -/**
    - * CSS class name for first splitpane container.
    - * @type {string}
    - * @private
    - */
    -goog.ui.SplitPane.FIRST_CONTAINER_CLASS_NAME_ =
    -    goog.getCssName('goog-splitpane-first-container');
    -
    -
    -/**
    - * CSS class name for second splitpane container.
    - * @type {string}
    - * @private
    - */
    -goog.ui.SplitPane.SECOND_CONTAINER_CLASS_NAME_ =
    -    goog.getCssName('goog-splitpane-second-container');
    -
    -
    -/**
    - * CSS class name for the splitpane handle.
    - * @type {string}
    - * @private
    - */
    -goog.ui.SplitPane.HANDLE_CLASS_NAME_ = goog.getCssName('goog-splitpane-handle');
    -
    -
    -/**
    - * CSS class name for the splitpane handle in horizontal orientation.
    - * @type {string}
    - * @private
    - */
    -goog.ui.SplitPane.HANDLE_CLASS_NAME_HORIZONTAL_ =
    -    goog.getCssName('goog-splitpane-handle-horizontal');
    -
    -
    -/**
    - * CSS class name for the splitpane handle in horizontal orientation.
    - * @type {string}
    - * @private
    - */
    -goog.ui.SplitPane.HANDLE_CLASS_NAME_VERTICAL_ =
    -    goog.getCssName('goog-splitpane-handle-vertical');
    -
    -
    -/**
    -  * The dragger to move the drag handle.
    -  * @type {goog.fx.Dragger?}
    -  * @private
    -  */
    -goog.ui.SplitPane.prototype.splitDragger_ = null;
    -
    -
    -/**
    - * The left/top component dom container.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.SplitPane.prototype.firstComponentContainer_ = null;
    -
    -
    -/**
    - * The right/bottom component dom container.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.SplitPane.prototype.secondComponentContainer_ = null;
    -
    -
    -/**
    - * The size (width or height) of the splitpane handle, default = 5.
    - * @type {number}
    - * @private
    - */
    -goog.ui.SplitPane.prototype.handleSize_ = 5;
    -
    -
    -/**
    - * The initial size (width or height) of the left or top component.
    - * @type {?number}
    - * @private
    - */
    -goog.ui.SplitPane.prototype.initialSize_ = null;
    -
    -
    -/**
    - * The saved size (width or height) of the left or top component on a
    - * double-click (snap).
    - * This needs to be saved so it can be restored after another double-click.
    - * @type {?number}
    - * @private
    - */
    -goog.ui.SplitPane.prototype.savedSnapSize_ = null;
    -
    -
    -/**
    - * The first component size, so we don't change it on a window resize.
    - * @type {?number}
    - * @private
    - */
    -goog.ui.SplitPane.prototype.firstComponentSize_ = null;
    -
    -
    -/**
    - * If we resize as they user moves the handle (default = true).
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.SplitPane.prototype.continuousResize_ = true;
    -
    -
    -/**
    - * Iframe overlay to prevent iframes from grabbing events.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.SplitPane.prototype.iframeOverlay_ = null;
    -
    -
    -/**
    - * Z indices for iframe overlay and splitter handle.
    - * @enum {number}
    - * @private
    - */
    -goog.ui.SplitPane.IframeOverlayIndex_ = {
    -  HIDDEN: -1,
    -  OVERLAY: 1,
    -  SPLITTER_HANDLE: 2
    -};
    -
    -
    -/**
    -* Orientation values for the splitpane.
    -* @enum {string}
    -*/
    -goog.ui.SplitPane.Orientation = {
    -
    -  /**
    -   * Horizontal orientation means splitter moves right-left.
    -   */
    -  HORIZONTAL: 'horizontal',
    -
    -  /**
    -   * Vertical orientation means splitter moves up-down.
    -   */
    -  VERTICAL: 'vertical'
    -};
    -
    -
    -/**
    - * Create the DOM node & text node needed for the splitpane.
    - * @override
    - */
    -goog.ui.SplitPane.prototype.createDom = function() {
    -  var dom = this.getDomHelper();
    -
    -  // Create the components.
    -  var firstContainer = dom.createDom('div',
    -      goog.ui.SplitPane.FIRST_CONTAINER_CLASS_NAME_);
    -  var secondContainer = dom.createDom('div',
    -      goog.ui.SplitPane.SECOND_CONTAINER_CLASS_NAME_);
    -  var splitterHandle = dom.createDom('div',
    -      goog.ui.SplitPane.HANDLE_CLASS_NAME_);
    -
    -  // Create the primary element, a DIV that holds the two containers and handle.
    -  this.setElementInternal(dom.createDom('div', goog.ui.SplitPane.CLASS_NAME_,
    -      firstContainer, secondContainer, splitterHandle));
    -
    -  this.firstComponentContainer_ = firstContainer;
    -  this.secondComponentContainer_ = secondContainer;
    -  this.splitpaneHandle_ = splitterHandle;
    -  this.setUpHandle_();
    -
    -  this.finishSetup_();
    -};
    -
    -
    -/**
    - * Determines if a given element can be decorated by this type of component.
    - * @param {Element} element Element to decorate.
    - * @return {boolean} True if the element can be decorated, false otherwise.
    - * @override
    - */
    -goog.ui.SplitPane.prototype.canDecorate = function(element) {
    -  var className = goog.ui.SplitPane.FIRST_CONTAINER_CLASS_NAME_;
    -  var firstContainer = this.getElementToDecorate_(element, className);
    -  if (!firstContainer) {
    -    return false;
    -  }
    -  // Since we have this component, save it so we don't have to get it
    -  // again in decorateInternal.  Same w/other components.
    -  this.firstComponentContainer_ = firstContainer;
    -
    -  className = goog.ui.SplitPane.SECOND_CONTAINER_CLASS_NAME_;
    -  var secondContainer = this.getElementToDecorate_(element, className);
    -
    -  if (!secondContainer) {
    -    return false;
    -  }
    -  this.secondComponentContainer_ = secondContainer;
    -
    -  className = goog.ui.SplitPane.HANDLE_CLASS_NAME_;
    -  var splitpaneHandle = this.getElementToDecorate_(element, className);
    -  if (!splitpaneHandle) {
    -    return false;
    -  }
    -  this.splitpaneHandle_ = splitpaneHandle;
    -
    -  // We found all the components we're looking for, so return true.
    -  return true;
    -};
    -
    -
    -/**
    - * Obtains the element to be decorated by class name. If multiple such elements
    - * are found, preference is given to those directly attached to the specified
    - * root element.
    - * @param {Element} rootElement The root element from which to retrieve the
    - *     element to be decorated.
    - * @param {!string} className The target class name.
    - * @return {Element} The element to decorate.
    - * @private
    - */
    -goog.ui.SplitPane.prototype.getElementToDecorate_ = function(rootElement,
    -    className) {
    -
    -  // Decorate the root element's children, if available.
    -  var childElements = goog.dom.getChildren(rootElement);
    -  for (var i = 0; i < childElements.length; i++) {
    -    var childElement = goog.asserts.assertElement(childElements[i]);
    -    if (goog.dom.classlist.contains(childElement, className)) {
    -      return childElement;
    -    }
    -  }
    -
    -  // Default to the first descendent element with the correct class.
    -  return goog.dom.getElementsByTagNameAndClass(
    -      null, className, rootElement)[0];
    -};
    -
    -
    -/**
    - * Decorates the given HTML element as a SplitPane.  Overrides {@link
    - * goog.ui.Component#decorateInternal}.  Considered protected.
    - * @param {Element} element Element (SplitPane div) to decorate.
    - * @protected
    - * @override
    - */
    -goog.ui.SplitPane.prototype.decorateInternal = function(element) {
    -  goog.ui.SplitPane.base(this, 'decorateInternal', element);
    -
    -  this.setUpHandle_();
    -
    -  var elSize = goog.style.getBorderBoxSize(element);
    -  this.setSize(new goog.math.Size(elSize.width, elSize.height));
    -
    -  this.finishSetup_();
    -};
    -
    -
    -/**
    - * Parent the passed in components to the split containers.  Call their
    - * createDom methods if necessary.
    - * @private
    - */
    -goog.ui.SplitPane.prototype.finishSetup_ = function() {
    -  var dom = this.getDomHelper();
    -
    -  if (!this.firstComponent_.getElement()) {
    -    this.firstComponent_.createDom();
    -  }
    -
    -  dom.appendChild(this.firstComponentContainer_,
    -      this.firstComponent_.getElement());
    -
    -  if (!this.secondComponent_.getElement()) {
    -    this.secondComponent_.createDom();
    -  }
    -
    -  dom.appendChild(this.secondComponentContainer_,
    -      this.secondComponent_.getElement());
    -
    -  this.splitDragger_ = new goog.fx.Dragger(this.splitpaneHandle_,
    -      this.splitpaneHandle_);
    -
    -  this.firstComponentContainer_.style.position = 'absolute';
    -  this.secondComponentContainer_.style.position = 'absolute';
    -  var handleStyle = this.splitpaneHandle_.style;
    -  handleStyle.position = 'absolute';
    -  handleStyle.overflow = 'hidden';
    -  handleStyle.zIndex =
    -      goog.ui.SplitPane.IframeOverlayIndex_.SPLITTER_HANDLE;
    -};
    -
    -
    -/**
    - * Setup all events and do an initial resize.
    - * @override
    - */
    -goog.ui.SplitPane.prototype.enterDocument = function() {
    -  goog.ui.SplitPane.base(this, 'enterDocument');
    -
    -  // If position is not set in the inline style of the element, it is not
    -  // possible to get the element's real CSS position until the element is in
    -  // the document.
    -  // When position:relative is set in the CSS and the element is not in the
    -  // document, Safari, Chrome, and Opera always return the empty string; while
    -  // IE always return "static".
    -  // Do the final check to see if element's position is set as "relative",
    -  // "absolute" or "fixed".
    -  var element = this.getElement();
    -  if (goog.style.getComputedPosition(element) == 'static') {
    -    element.style.position = 'relative';
    -  }
    -
    -  this.getHandler().
    -      listen(this.splitpaneHandle_, goog.events.EventType.DBLCLICK,
    -          this.handleDoubleClick_).
    -      listen(this.splitDragger_, goog.fx.Dragger.EventType.START,
    -          this.handleDragStart_).
    -      listen(this.splitDragger_, goog.fx.Dragger.EventType.DRAG,
    -          this.handleDrag_).
    -      listen(this.splitDragger_, goog.fx.Dragger.EventType.END,
    -          this.handleDragEnd_);
    -
    -  this.setFirstComponentSize(this.initialSize_);
    -};
    -
    -
    -/**
    - * Sets the initial size of the left or top component.
    - * @param {number} size The size in Pixels of the container.
    - */
    -goog.ui.SplitPane.prototype.setInitialSize = function(size) {
    -  this.initialSize_ = size;
    -};
    -
    -
    -/**
    - * Sets the SplitPane handle size.
    - * TODO(user): Make sure this works after initialization.
    - * @param {number} size The size of the handle in pixels.
    - */
    -goog.ui.SplitPane.prototype.setHandleSize = function(size) {
    -  this.handleSize_ = size;
    -};
    -
    -
    -/**
    - * Sets whether we resize on handle drag.
    - * @param {boolean} continuous The continuous resize value.
    - */
    -goog.ui.SplitPane.prototype.setContinuousResize = function(continuous) {
    -  this.continuousResize_ = continuous;
    -};
    -
    -
    -/**
    - * Returns whether the orientation for the split pane is vertical
    - * or not.
    - * @return {boolean} True if the orientation is vertical, false otherwise.
    - */
    -goog.ui.SplitPane.prototype.isVertical = function() {
    -  return this.orientation_ == goog.ui.SplitPane.Orientation.VERTICAL;
    -};
    -
    -
    -/**
    - * Initializes the handle by assigning the correct height/width and adding
    - * the correct class as per the orientation.
    - * @private
    - */
    -goog.ui.SplitPane.prototype.setUpHandle_ = function() {
    -  if (this.isVertical()) {
    -    this.splitpaneHandle_.style.height = this.handleSize_ + 'px';
    -    goog.dom.classlist.add(this.splitpaneHandle_,
    -        goog.ui.SplitPane.HANDLE_CLASS_NAME_VERTICAL_);
    -  } else {
    -    this.splitpaneHandle_.style.width = this.handleSize_ + 'px';
    -    goog.dom.classlist.add(this.splitpaneHandle_,
    -        goog.ui.SplitPane.HANDLE_CLASS_NAME_HORIZONTAL_);
    -  }
    -};
    -
    -
    -/**
    - * Sets the orientation class for the split pane handle.
    - * @protected
    - */
    -goog.ui.SplitPane.prototype.setOrientationClassForHandle = function() {
    -  goog.asserts.assert(this.splitpaneHandle_);
    -  if (this.isVertical()) {
    -    goog.dom.classlist.swap(this.splitpaneHandle_,
    -        goog.ui.SplitPane.HANDLE_CLASS_NAME_HORIZONTAL_,
    -        goog.ui.SplitPane.HANDLE_CLASS_NAME_VERTICAL_);
    -  } else {
    -    goog.dom.classlist.swap(this.splitpaneHandle_,
    -        goog.ui.SplitPane.HANDLE_CLASS_NAME_VERTICAL_,
    -        goog.ui.SplitPane.HANDLE_CLASS_NAME_HORIZONTAL_);
    -  }
    -};
    -
    -
    -/**
    - * Sets the orientation of the split pane.
    - * @param {goog.ui.SplitPane.Orientation} orientation SplitPane orientation.
    - */
    -goog.ui.SplitPane.prototype.setOrientation = function(orientation) {
    -  if (this.orientation_ != orientation) {
    -    this.orientation_ = orientation;
    -    var isVertical = this.isVertical();
    -
    -    // If the split pane is already in document, then the positions and sizes
    -    // need to be adjusted.
    -    if (this.isInDocument()) {
    -      this.setOrientationClassForHandle();
    -      // TODO(user): Should handleSize_ and initialSize_ also be adjusted ?
    -      if (goog.isNumber(this.firstComponentSize_)) {
    -        var splitpaneSize = goog.style.getBorderBoxSize(this.getElement());
    -        var ratio = isVertical ? splitpaneSize.height / splitpaneSize.width :
    -            splitpaneSize.width / splitpaneSize.height;
    -        // TODO(user): Fix the behaviour for the case when the handle is
    -        // placed on either of  the edges of the split pane. Also, similar
    -        // behaviour is present in {@link #setSize}. Probably need to modify
    -        // {@link #setFirstComponentSize}.
    -        this.setFirstComponentSize(this.firstComponentSize_ * ratio);
    -      } else {
    -        this.setFirstComponentSize();
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Gets the orientation of the split pane.
    - * @return {goog.ui.SplitPane.Orientation} The orientation.
    - */
    -goog.ui.SplitPane.prototype.getOrientation = function() {
    -  return this.orientation_;
    -};
    -
    -
    -/**
    - * Move and resize a container.  The sizing changes the BorderBoxSize.
    - * @param {Element} element The element to move and size.
    - * @param {goog.math.Rect} rect The top, left, width and height to change to.
    - * @private
    - */
    -goog.ui.SplitPane.prototype.moveAndSize_ = function(element, rect) {
    -  goog.style.setPosition(element, rect.left, rect.top);
    -  // TODO(user): Add a goog.math.Size.max call for below.
    -  goog.style.setBorderBoxSize(element,
    -      new goog.math.Size(Math.max(rect.width, 0), Math.max(rect.height, 0)));
    -};
    -
    -
    -/**
    - * @return {?number} The size of the left/top component.
    - */
    -goog.ui.SplitPane.prototype.getFirstComponentSize = function() {
    -  return this.firstComponentSize_;
    -};
    -
    -
    -/**
    - * Set the size of the left/top component, and resize the other component based
    - * on that size and handle size.
    - * @param {?number=} opt_size The size of the top or left, in pixels. If
    - *     unspecified, leaves the size of the first component unchanged but adjusts
    - *     the size of the second component to fit the split pane size.
    - */
    -goog.ui.SplitPane.prototype.setFirstComponentSize = function(opt_size) {
    -  this.setFirstComponentSize_(
    -      goog.style.getBorderBoxSize(this.getElement()), opt_size);
    -};
    -
    -
    -/**
    - * Set the size of the left/top component, and resize the other component based
    - * on that size and handle size. Unlike the public method, this takes the
    - * current pane size which avoids the expensive getBorderBoxSize() call
    - * when we have the size available.
    - *
    - * @param {!goog.math.Size} splitpaneSize The current size of the splitpane.
    - * @param {?number=} opt_size The size of the top or left, in pixels.
    - * @private
    - */
    -goog.ui.SplitPane.prototype.setFirstComponentSize_ = function(
    -    splitpaneSize, opt_size) {
    -  var top = 0, left = 0;
    -
    -  var isVertical = this.isVertical();
    -  // Figure out first component size; it's either passed in, taken from the
    -  // saved size, or is half of the total size.
    -  var firstComponentSize = goog.isNumber(opt_size) ? opt_size :
    -      goog.isNumber(this.firstComponentSize_) ? this.firstComponentSize_ :
    -      Math.floor((isVertical ? splitpaneSize.height : splitpaneSize.width) / 2);
    -  this.firstComponentSize_ = firstComponentSize;
    -
    -  var firstComponentWidth;
    -  var firstComponentHeight;
    -  var secondComponentWidth;
    -  var secondComponentHeight;
    -  var handleWidth;
    -  var handleHeight;
    -  var secondComponentLeft;
    -  var secondComponentTop;
    -  var handleLeft;
    -  var handleTop;
    -
    -  if (isVertical) {
    -
    -    // Width for the handle and the first and second components will be the
    -    // width of the split pane. The height for the first component will be
    -    // the calculated first component size. The height for the second component
    -    // will be the  total height minus the heights of the first component and
    -    // the handle.
    -    firstComponentHeight = firstComponentSize;
    -    firstComponentWidth = splitpaneSize.width;
    -    handleWidth = splitpaneSize.width;
    -    handleHeight = this.handleSize_;
    -    secondComponentHeight = splitpaneSize.height - firstComponentHeight -
    -        handleHeight;
    -    secondComponentWidth = splitpaneSize.width;
    -    handleTop = top + firstComponentHeight;
    -    handleLeft = left;
    -    secondComponentTop = handleTop + handleHeight;
    -    secondComponentLeft = left;
    -  } else {
    -
    -    // Height for the handle and the first and second components will be the
    -    // height of the split pane. The width for the first component will be
    -    // the calculated first component size. The width for the second component
    -    // will be the  total width minus the widths of the first component and
    -    // the handle.
    -    firstComponentWidth = firstComponentSize;
    -    firstComponentHeight = splitpaneSize.height;
    -    handleWidth = this.handleSize_;
    -    handleHeight = splitpaneSize.height;
    -    secondComponentWidth = splitpaneSize.width - firstComponentWidth -
    -        handleWidth;
    -    secondComponentHeight = splitpaneSize.height;
    -    handleLeft = left + firstComponentWidth;
    -    handleTop = top;
    -    secondComponentLeft = handleLeft + handleWidth;
    -    secondComponentTop = top;
    -  }
    -
    -  // Now move and size the containers.
    -  this.moveAndSize_(this.firstComponentContainer_,
    -      new goog.math.Rect(left, top, firstComponentWidth, firstComponentHeight));
    -
    -  if (typeof this.firstComponent_.resize == 'function') {
    -    this.firstComponent_.resize(new goog.math.Size(
    -        firstComponentWidth, firstComponentHeight));
    -  }
    -
    -  this.moveAndSize_(this.splitpaneHandle_, new goog.math.Rect(handleLeft,
    -      handleTop, handleWidth, handleHeight));
    -
    -  this.moveAndSize_(this.secondComponentContainer_,
    -      new goog.math.Rect(secondComponentLeft, secondComponentTop,
    -          secondComponentWidth, secondComponentHeight));
    -
    -  if (typeof this.secondComponent_.resize == 'function') {
    -    this.secondComponent_.resize(new goog.math.Size(secondComponentWidth,
    -        secondComponentHeight));
    -  }
    -  // Fire a CHANGE event.
    -  this.dispatchEvent(goog.ui.Component.EventType.CHANGE);
    -};
    -
    -
    -/**
    - * Set the size of the splitpane.  This is usually called by the controlling
    - * application.  This will set the SplitPane BorderBoxSize.
    - * @param {!goog.math.Size} size The size to set the splitpane.
    - * @param {?number=} opt_firstComponentSize The size of the top or left
    - *     component, in pixels.
    - */
    -goog.ui.SplitPane.prototype.setSize = function(size, opt_firstComponentSize) {
    -  goog.style.setBorderBoxSize(this.getElement(), size);
    -  if (this.iframeOverlay_) {
    -    goog.style.setBorderBoxSize(this.iframeOverlay_, size);
    -  }
    -  this.setFirstComponentSize_(size, opt_firstComponentSize);
    -};
    -
    -
    -/**
    - * Snap the container to the left or top on a Double-click.
    - * @private
    - */
    -goog.ui.SplitPane.prototype.snapIt_ = function() {
    -  var handlePos = goog.style.getRelativePosition(this.splitpaneHandle_,
    -      this.firstComponentContainer_);
    -  var firstBorderBoxSize =
    -      goog.style.getBorderBoxSize(this.firstComponentContainer_);
    -  var firstContentBoxSize =
    -      goog.style.getContentBoxSize(this.firstComponentContainer_);
    -
    -  var isVertical = this.isVertical();
    -
    -  // Where do we snap the handle (what size to make the component) and what
    -  // is the current handle position.
    -  var snapSize;
    -  var handlePosition;
    -  if (isVertical) {
    -    snapSize = firstBorderBoxSize.height - firstContentBoxSize.height;
    -    handlePosition = handlePos.y;
    -  } else {
    -    snapSize = firstBorderBoxSize.width - firstContentBoxSize.width;
    -    handlePosition = handlePos.x;
    -  }
    -
    -  if (snapSize == handlePosition) {
    -    // This means we're 'unsnapping', set it back to where it was.
    -    this.setFirstComponentSize(this.savedSnapSize_);
    -  } else {
    -    // This means we're 'snapping', set the size to snapSize, and hide the
    -    // first component.
    -    if (isVertical) {
    -      this.savedSnapSize_ = goog.style.getBorderBoxSize(
    -          this.firstComponentContainer_).height;
    -    } else {
    -      this.savedSnapSize_ = goog.style.getBorderBoxSize(
    -          this.firstComponentContainer_).width;
    -    }
    -    this.setFirstComponentSize(snapSize);
    -  }
    -
    -  // Fire a SNAP event.
    -  this.dispatchEvent(goog.ui.SplitPane.EventType.HANDLE_SNAP);
    -};
    -
    -
    -/**
    - * Handle the start drag event - set up the dragger.
    - * @param {goog.events.Event} e The event.
    - * @private
    - */
    -goog.ui.SplitPane.prototype.handleDragStart_ = function(e) {
    -
    -  // Setup iframe overlay to prevent iframes from grabbing events.
    -  if (!this.iframeOverlay_) {
    -    // Create the overlay.
    -    var cssStyles = 'position: relative';
    -
    -    if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('10')) {
    -      // IE doesn't look at this div unless it has a background, so we'll
    -      // put one on, but make it opaque.
    -      cssStyles += ';background-color: #000;filter: Alpha(Opacity=0)';
    -    }
    -    this.iframeOverlay_ =
    -        this.getDomHelper().createDom('div', {'style': cssStyles});
    -
    -    this.getDomHelper().appendChild(this.getElement(), this.iframeOverlay_);
    -  }
    -  this.iframeOverlay_.style.zIndex =
    -      goog.ui.SplitPane.IframeOverlayIndex_.OVERLAY;
    -
    -  goog.style.setBorderBoxSize(this.iframeOverlay_,
    -      goog.style.getBorderBoxSize(this.getElement()));
    -
    -  var pos = goog.style.getPosition(this.firstComponentContainer_);
    -
    -  // For the size of the limiting box, we add the container content box sizes
    -  // so that if the handle is placed all the way to the end or the start, the
    -  // border doesn't exceed the total size. For position, we add the difference
    -  // between the border box and content box sizes of the first container to the
    -  // position of the first container. The start position should be such that
    -  // there is no overlap of borders.
    -  var limitWidth = 0;
    -  var limitHeight = 0;
    -  var limitx = pos.x;
    -  var limity = pos.y;
    -  var firstBorderBoxSize =
    -      goog.style.getBorderBoxSize(this.firstComponentContainer_);
    -  var firstContentBoxSize =
    -      goog.style.getContentBoxSize(this.firstComponentContainer_);
    -  var secondContentBoxSize =
    -      goog.style.getContentBoxSize(this.secondComponentContainer_);
    -  if (this.isVertical()) {
    -    limitHeight = firstContentBoxSize.height + secondContentBoxSize.height;
    -    limity += firstBorderBoxSize.height - firstContentBoxSize.height;
    -  } else {
    -    limitWidth = firstContentBoxSize.width + secondContentBoxSize.width;
    -    limitx += firstBorderBoxSize.width - firstContentBoxSize.width;
    -  }
    -  var limits = new goog.math.Rect(limitx, limity, limitWidth, limitHeight);
    -  this.splitDragger_.setLimits(limits);
    -};
    -
    -
    -/**
    - * Find the location relative to the splitpane.
    - * @param {number} left The x location relative to the window.
    - * @return {number} The relative x location.
    - * @private
    - */
    -goog.ui.SplitPane.prototype.getRelativeLeft_ = function(left) {
    -  return left - goog.style.getPosition(this.firstComponentContainer_).x;
    -};
    -
    -
    -/**
    - * Find the location relative to the splitpane.
    - * @param {number} top The y location relative to the window.
    - * @return {number} The relative y location.
    - * @private
    - */
    -goog.ui.SplitPane.prototype.getRelativeTop_ = function(top) {
    -  return top - goog.style.getPosition(this.firstComponentContainer_).y;
    -};
    -
    -
    -/**
    - * Handle the drag event. Move the containers.
    - * @param {!goog.fx.DragEvent} e The event.
    - * @private
    - */
    -goog.ui.SplitPane.prototype.handleDrag_ = function(e) {
    -  if (this.continuousResize_) {
    -    if (this.isVertical()) {
    -      var top = this.getRelativeTop_(e.top);
    -      this.setFirstComponentSize(top);
    -    } else {
    -      var left = this.getRelativeLeft_(e.left);
    -      this.setFirstComponentSize(left);
    -    }
    -    this.dispatchEvent(goog.ui.SplitPane.EventType.HANDLE_DRAG);
    -  }
    -};
    -
    -
    -/**
    - * Handle the drag end event. If we're not doing continuous resize,
    - * resize the component.  If we're doing continuous resize, the component
    - * is already the correct size.
    - * @param {!goog.fx.DragEvent} e The event.
    - * @private
    - */
    -goog.ui.SplitPane.prototype.handleDragEnd_ = function(e) {
    -  // Push iframe overlay down.
    -  this.iframeOverlay_.style.zIndex =
    -      goog.ui.SplitPane.IframeOverlayIndex_.HIDDEN;
    -  if (!this.continuousResize_) {
    -    if (this.isVertical()) {
    -      var top = this.getRelativeTop_(e.top);
    -      this.setFirstComponentSize(top);
    -    } else {
    -      var left = this.getRelativeLeft_(e.left);
    -      this.setFirstComponentSize(left);
    -    }
    -  }
    -
    -  this.dispatchEvent(goog.ui.SplitPane.EventType.HANDLE_DRAG_END);
    -};
    -
    -
    -/**
    - * Handle the Double-click. Call the snapIt method which snaps the container
    - * to the top or left.
    - * @param {goog.events.Event} e The event.
    - * @private
    - */
    -goog.ui.SplitPane.prototype.handleDoubleClick_ = function(e) {
    -  this.snapIt_();
    -};
    -
    -
    -/** @override */
    -goog.ui.SplitPane.prototype.disposeInternal = function() {
    -  goog.dispose(this.splitDragger_);
    -  this.splitDragger_ = null;
    -
    -  goog.dom.removeNode(this.iframeOverlay_);
    -  this.iframeOverlay_ = null;
    -
    -  goog.ui.SplitPane.base(this, 'disposeInternal');
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/splitpane_test.html b/src/database/third_party/closure-library/closure/goog/ui/splitpane_test.html
    deleted file mode 100644
    index ae2f2493763..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/splitpane_test.html
    +++ /dev/null
    @@ -1,26 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.SplitPane
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script type="text/javascript">
    -   goog.require('goog.ui.SplitPaneTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="sandbox">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/splitpane_test.js b/src/database/third_party/closure-library/closure/goog/ui/splitpane_test.js
    deleted file mode 100644
    index ab0851fb988..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/splitpane_test.js
    +++ /dev/null
    @@ -1,223 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.SplitPaneTest');
    -goog.setTestOnly('goog.ui.SplitPaneTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events');
    -goog.require('goog.math.Size');
    -goog.require('goog.style');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.recordFunction');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.SplitPane');
    -
    -var splitpane;
    -var leftComponent;
    -var rightComponent;
    -
    -function setUp() {
    -  leftComponent = new goog.ui.Component();
    -  rightComponent = new goog.ui.Component();
    -  splitpane = new goog.ui.SplitPane(leftComponent, rightComponent,
    -      goog.ui.SplitPane.Orientation.HORIZONTAL);
    -}
    -
    -function tearDown() {
    -  splitpane.dispose();
    -  leftComponent.dispose();
    -  rightComponent.dispose();
    -  goog.dom.getElement('sandbox').innerHTML = '';
    -}
    -
    -function testRender() {
    -  splitpane.render(goog.dom.getElement('sandbox'));
    -  assertEquals(1, goog.dom.getElementsByTagNameAndClass('div',
    -      'goog-splitpane').length);
    -  assertEquals(1, goog.dom.getElementsByTagNameAndClass('div',
    -      'goog-splitpane-first-container').length);
    -  assertEquals(1, goog.dom.getElementsByTagNameAndClass('div',
    -      'goog-splitpane-second-container').length);
    -  assertEquals(1, goog.dom.getElementsByTagNameAndClass('div',
    -      'goog-splitpane-handle').length);
    -}
    -
    -function testDecorate() {
    -  var mainDiv = goog.dom.createDom('div', 'goog-splitpane',
    -      goog.dom.createDom('div', 'goog-splitpane-first-container'),
    -      goog.dom.createDom('div', 'goog-splitpane-second-container'),
    -      goog.dom.createDom('div', 'goog-splitpane-handle'));
    -  var sandbox = goog.dom.getElement('sandbox');
    -  goog.dom.appendChild(sandbox, mainDiv);
    -
    -  splitpane.decorate(mainDiv);
    -}
    -
    -function testDecorateWithNestedSplitPane() {
    -
    -  // Create a standard split pane to be nested within another split pane.
    -  var innerSplitPaneDiv = goog.dom.createDom('div', 'goog-splitpane',
    -      goog.dom.createDom('div', 'goog-splitpane-first-container e1'),
    -      goog.dom.createDom('div', 'goog-splitpane-second-container e2'),
    -      goog.dom.createDom('div', 'goog-splitpane-handle e3'));
    -
    -  // Create a split pane containing a split pane instance.
    -  var outerSplitPaneDiv = goog.dom.createDom('div', 'goog-splitpane',
    -      goog.dom.createDom('div', 'goog-splitpane-first-container e4',
    -          innerSplitPaneDiv),
    -      goog.dom.createDom('div', 'goog-splitpane-second-container e5'),
    -      goog.dom.createDom('div', 'goog-splitpane-handle e6'));
    -
    -  var sandbox = goog.dom.getElement('sandbox');
    -  goog.dom.appendChild(sandbox, outerSplitPaneDiv);
    -
    -  // Decorate and check that the correct containers and handle are used.
    -  splitpane.decorate(outerSplitPaneDiv);
    -  assertTrue(goog.dom.classlist.contains(
    -      splitpane.firstComponentContainer_, 'e4'));
    -  assertTrue(goog.dom.classlist.contains(
    -      splitpane.secondComponentContainer_, 'e5'));
    -  assertTrue(goog.dom.classlist.contains(splitpane.splitpaneHandle_, 'e6'));
    -}
    -
    -function testSetSize() {
    -  splitpane.setInitialSize(200);
    -  splitpane.setHandleSize(10);
    -  splitpane.render(goog.dom.getElement('sandbox'));
    -
    -  splitpane.setSize(new goog.math.Size(500, 300));
    -  assertEquals(200, splitpane.getFirstComponentSize());
    -
    -  var splitpaneSize = goog.style.getBorderBoxSize(splitpane.getElement());
    -  assertEquals(500, splitpaneSize.width);
    -  assertEquals(300, splitpaneSize.height);
    -}
    -
    -function testOrientationChange() {
    -  splitpane.setInitialSize(200);
    -  splitpane.setHandleSize(10);
    -  splitpane.render(goog.dom.getElement('sandbox'));
    -  splitpane.setSize(new goog.math.Size(500, 300));
    -
    -  var first = goog.dom.getElementsByTagNameAndClass('div',
    -      'goog-splitpane-first-container')[0];
    -  var second = goog.dom.getElementsByTagNameAndClass('div',
    -      'goog-splitpane-second-container')[0];
    -  var handle = goog.dom.getElementsByTagNameAndClass('div',
    -      'goog-splitpane-handle')[0];
    -
    -  var handleSize = goog.style.getBorderBoxSize(handle);
    -  assertEquals(10, handleSize.width);
    -  assertEquals(300, handleSize.height);
    -
    -  var firstSize = goog.style.getBorderBoxSize(first);
    -  assertEquals(200, firstSize.width);
    -  assertEquals(300, firstSize.height);
    -
    -  var secondSize = goog.style.getBorderBoxSize(second);
    -  assertEquals(290, secondSize.width); // 500 - 200 - 10 = 290
    -  assertEquals(300, secondSize.height);
    -
    -  splitpane.setOrientation(goog.ui.SplitPane.Orientation.VERTICAL);
    -
    -  handleSize = goog.style.getBorderBoxSize(handle);
    -  assertEquals(10, handleSize.height);
    -  assertEquals(500, handleSize.width);
    -
    -  firstSize = goog.style.getBorderBoxSize(first);
    -  assertEquals(120, firstSize.height); // 200 * 300/500 = 120
    -  assertEquals(500, firstSize.width);
    -
    -  secondSize = goog.style.getBorderBoxSize(second);
    -  assertEquals(170, secondSize.height); // 300 - 120 - 10 = 170
    -  assertEquals(500, secondSize.width);
    -
    -  splitpane.setOrientation(goog.ui.SplitPane.Orientation.HORIZONTAL);
    -
    -  handleSize = goog.style.getBorderBoxSize(handle);
    -  assertEquals(10, handleSize.width);
    -  assertEquals(300, handleSize.height);
    -
    -  firstSize = goog.style.getBorderBoxSize(first);
    -  assertEquals(200, firstSize.width);
    -  assertEquals(300, firstSize.height);
    -
    -  secondSize = goog.style.getBorderBoxSize(second);
    -  assertEquals(290, secondSize.width);
    -  assertEquals(300, secondSize.height);
    -}
    -
    -function testDragEvent() {
    -  splitpane.setInitialSize(200);
    -  splitpane.setHandleSize(10);
    -  splitpane.render(goog.dom.getElement('sandbox'));
    -
    -  var handler = goog.testing.recordFunction();
    -  goog.events.listen(splitpane, goog.ui.SplitPane.EventType.HANDLE_DRAG,
    -      handler);
    -  var handle = goog.dom.getElementsByTagNameAndClass('div',
    -      'goog-splitpane-handle')[0];
    -
    -  goog.testing.events.fireMouseDownEvent(handle);
    -  goog.testing.events.fireMouseMoveEvent(handle);
    -  goog.testing.events.fireMouseUpEvent(handle);
    -  assertEquals('HANDLE_DRAG event expected', 1, handler.getCallCount());
    -
    -  splitpane.setContinuousResize(false);
    -  handler.reset();
    -  goog.testing.events.fireMouseDownEvent(handle);
    -  goog.testing.events.fireMouseMoveEvent(handle);
    -  goog.testing.events.fireMouseUpEvent(handle);
    -  assertEquals('HANDLE_DRAG event not expected', 0, handler.getCallCount());
    -}
    -
    -function testDragEndEvent() {
    -  splitpane.setInitialSize(200);
    -  splitpane.setHandleSize(10);
    -  splitpane.render(goog.dom.getElement('sandbox'));
    -  var handler = goog.testing.recordFunction();
    -  goog.events.listen(splitpane, goog.ui.SplitPane.EventType.HANDLE_DRAG_END,
    -      handler);
    -
    -  var handle = goog.dom.getElementsByTagNameAndClass('div',
    -      'goog-splitpane-handle')[0];
    -
    -  goog.testing.events.fireMouseDownEvent(handle);
    -  goog.testing.events.fireMouseMoveEvent(handle);
    -  goog.testing.events.fireMouseUpEvent(handle);
    -  assertEquals('HANDLE_DRAG_END event expected', 1, handler.getCallCount());
    -
    -  splitpane.setContinuousResize(false);
    -  handler.reset();
    -  goog.testing.events.fireMouseDownEvent(handle);
    -  goog.testing.events.fireMouseMoveEvent(handle);
    -  goog.testing.events.fireMouseUpEvent(handle);
    -  assertEquals('HANDLE_DRAG_END event expected', 1, handler.getCallCount());
    -}
    -
    -function testSnapEvent() {
    -  splitpane.setInitialSize(200);
    -  splitpane.setHandleSize(10);
    -  splitpane.render(goog.dom.getElement('sandbox'));
    -  var handler = goog.testing.recordFunction();
    -  goog.events.listen(splitpane, goog.ui.SplitPane.EventType.HANDLE_SNAP,
    -      handler);
    -  var handle = goog.dom.getElementsByTagNameAndClass('div',
    -      'goog-splitpane-handle')[0];
    -  goog.testing.events.fireDoubleClickSequence(handle);
    -  assertEquals('HANDLE_SNAP event expected', 1, handler.getCallCount());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/style/app/buttonrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/style/app/buttonrenderer.js
    deleted file mode 100644
    index 145fd578d28..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/style/app/buttonrenderer.js
    +++ /dev/null
    @@ -1,202 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Renderer for {@link goog.ui.Button}s in App style.
    - *
    - * Based on ImagelessButtonRender. Uses even more CSS voodoo than the default
    - * implementation to render custom buttons with fake rounded corners and
    - * dimensionality (via a subtle flat shadow on the bottom half of the button)
    - * without the use of images.
    - *
    - * Based on the Custom Buttons 3.1 visual specification, see
    - * http://go/custombuttons
    - *
    - * @author eae@google.com (Emil A Eklund)
    - */
    -
    -goog.provide('goog.ui.style.app.ButtonRenderer');
    -
    -goog.require('goog.dom.classlist');
    -goog.require('goog.ui.Button');
    -goog.require('goog.ui.CustomButtonRenderer');
    -goog.require('goog.ui.INLINE_BLOCK_CLASSNAME');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * Custom renderer for {@link goog.ui.Button}s. Imageless buttons can contain
    - * almost arbitrary HTML content, will flow like inline elements, but can be
    - * styled like block-level elements.
    - *
    - * @constructor
    - * @extends {goog.ui.CustomButtonRenderer}
    - */
    -goog.ui.style.app.ButtonRenderer = function() {
    -  goog.ui.CustomButtonRenderer.call(this);
    -};
    -goog.inherits(goog.ui.style.app.ButtonRenderer, goog.ui.CustomButtonRenderer);
    -goog.addSingletonGetter(goog.ui.style.app.ButtonRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.style.app.ButtonRenderer.CSS_CLASS = goog.getCssName('goog-button');
    -
    -
    -/**
    - * Array of arrays of CSS classes that we want composite classes added and
    - * removed for in IE6 and lower as a workaround for lack of multi-class CSS
    - * selector support.
    - * @type {Array<Array<string>>}
    - */
    -goog.ui.style.app.ButtonRenderer.IE6_CLASS_COMBINATIONS = [];
    -
    -
    -/**
    - * Returns the button's contents wrapped in the following DOM structure:
    - *    <div class="goog-inline-block goog-button-base goog-button">
    - *      <div class="goog-inline-block goog-button-base-outer-box">
    - *        <div class="goog-button-base-inner-box">
    - *          <div class="goog-button-base-pos">
    - *            <div class="goog-button-base-top-shadow">&nbsp;</div>
    - *            <div class="goog-button-base-content">Contents...</div>
    - *          </div>
    - *        </div>
    - *      </div>
    - *    </div>
    - * @override
    - */
    -goog.ui.style.app.ButtonRenderer.prototype.createDom;
    -
    -
    -/** @override */
    -goog.ui.style.app.ButtonRenderer.prototype.getContentElement = function(
    -    element) {
    -  return element && /** @type {Element} */(
    -      element.firstChild.firstChild.firstChild.lastChild);
    -};
    -
    -
    -/**
    - * Takes a text caption or existing DOM structure, and returns the content
    - * wrapped in a pseudo-rounded-corner box.  Creates the following DOM structure:
    - *  <div class="goog-inline-block goog-button-base-outer-box">
    - *    <div class="goog-inline-block goog-button-base-inner-box">
    - *      <div class="goog-button-base-pos">
    - *        <div class="goog-button-base-top-shadow">&nbsp;</div>
    - *        <div class="goog-button-base-content">Contents...</div>
    - *      </div>
    - *    </div>
    - *  </div>
    - * Used by both {@link #createDom} and {@link #decorate}.  To be overridden
    - * by subclasses.
    - * @param {goog.ui.ControlContent} content Text caption or DOM structure to wrap
    - *     in a box.
    - * @param {goog.dom.DomHelper} dom DOM helper, used for document interaction.
    - * @return {Element} Pseudo-rounded-corner box containing the content.
    - * @override
    - */
    -goog.ui.style.app.ButtonRenderer.prototype.createButton = function(content,
    -    dom) {
    -  var baseClass = this.getStructuralCssClass();
    -  var inlineBlock = goog.ui.INLINE_BLOCK_CLASSNAME + ' ';
    -  return dom.createDom(
    -      'div', inlineBlock + goog.getCssName(baseClass, 'outer-box'),
    -      dom.createDom(
    -          'div', inlineBlock + goog.getCssName(baseClass, 'inner-box'),
    -          dom.createDom('div', goog.getCssName(baseClass, 'pos'),
    -              dom.createDom(
    -                  'div', goog.getCssName(baseClass, 'top-shadow'), '\u00A0'),
    -              dom.createDom(
    -                  'div', goog.getCssName(baseClass, 'content'), content))));
    -};
    -
    -
    -/**
    - * Check if the button's element has a box structure.
    - * @param {goog.ui.Button} button Button instance whose structure is being
    - *     checked.
    - * @param {Element} element Element of the button.
    - * @return {boolean} Whether the element has a box structure.
    - * @protected
    - * @override
    - */
    -goog.ui.style.app.ButtonRenderer.prototype.hasBoxStructure = function(
    -    button, element) {
    -
    -  var baseClass = this.getStructuralCssClass();
    -  var outer = button.getDomHelper().getFirstElementChild(element);
    -  var outerClassName = goog.getCssName(baseClass, 'outer-box');
    -  if (outer && goog.dom.classlist.contains(outer, outerClassName)) {
    -
    -    var inner = button.getDomHelper().getFirstElementChild(outer);
    -    var innerClassName = goog.getCssName(baseClass, 'inner-box');
    -    if (inner && goog.dom.classlist.contains(inner, innerClassName)) {
    -
    -      var pos = button.getDomHelper().getFirstElementChild(inner);
    -      var posClassName = goog.getCssName(baseClass, 'pos');
    -      if (pos && goog.dom.classlist.contains(pos, posClassName)) {
    -
    -        var shadow = button.getDomHelper().getFirstElementChild(pos);
    -        var shadowClassName = goog.getCssName(baseClass, 'top-shadow');
    -        if (shadow && goog.dom.classlist.contains(shadow, shadowClassName)) {
    -
    -          var content = button.getDomHelper().getNextElementSibling(shadow);
    -          var contentClassName = goog.getCssName(baseClass, 'content');
    -          if (content &&
    -              goog.dom.classlist.contains(content, contentClassName)) {
    -            // We have a proper box structure.
    -            return true;
    -          }
    -        }
    -      }
    -    }
    -  }
    -  return false;
    -};
    -
    -
    -/** @override */
    -goog.ui.style.app.ButtonRenderer.prototype.getCssClass = function() {
    -  return goog.ui.style.app.ButtonRenderer.CSS_CLASS;
    -};
    -
    -
    -/** @override */
    -goog.ui.style.app.ButtonRenderer.prototype.getStructuralCssClass = function() {
    -  // TODO(user): extract to a constant.
    -  return goog.getCssName('goog-button-base');
    -};
    -
    -
    -/** @override */
    -goog.ui.style.app.ButtonRenderer.prototype.getIe6ClassCombinations =
    -    function() {
    -  return goog.ui.style.app.ButtonRenderer.IE6_CLASS_COMBINATIONS;
    -};
    -
    -
    -
    -// Register a decorator factory function for goog.ui.style.app.ButtonRenderer.
    -goog.ui.registry.setDecoratorByClassName(
    -    goog.ui.style.app.ButtonRenderer.CSS_CLASS,
    -    function() {
    -      return new goog.ui.Button(null,
    -          goog.ui.style.app.ButtonRenderer.getInstance());
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/style/app/buttonrenderer_test.html b/src/database/third_party/closure-library/closure/goog/ui/style/app/buttonrenderer_test.html
    deleted file mode 100644
    index 62305b0d312..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/style/app/buttonrenderer_test.html
    +++ /dev/null
    @@ -1,43 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.style.app.ButtonRenderer
    -  </title>
    -  <script src="../../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.ui.style.app.ButtonRendererTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="sandbox"></div>
    -
    -  <div id="button" title="Click for Decorated">
    -    Hello Decorated
    -  </div>
    -
    -  <!-- The component DOM must always be created without whitespace. -->
    -  <div id="button-box" title="Click for Decorated Box" class="goog-button goog-button-base"><div class="goog-inline-block goog-button-base-outer-box"><div class="goog-inline-block goog-button-base-inner-box"><div class="goog-button-base-pos"><div class="goog-button-base-top-shadow">&nbsp;</div><div class="goog-button-base-content">Hello Decorated Box</div></div></div></div></div>
    -
    -  <!-- The component DOM must always be created without whitespace. This
    -       demonstrates what happens when the content has whitespace.
    -   -->
    -  <div id="button-box-with-space-in-content" class="goog-button goog-button-base"><div class="goog-inline-block goog-button-base-outer-box"><div class="goog-inline-block goog-button-base-inner-box"><div class="goog-button-base-pos"><div class="goog-button-base-top-shadow">&nbsp;</div><div class="goog-button-base-content">
    -    Hello Decorated Box with space
    -  </div></div></div></div></div>
    -
    -  <div id="button-box-with-dom-content">
    -    <strong>Hello</strong> <em>Box</em>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/style/app/buttonrenderer_test.js b/src/database/third_party/closure-library/closure/goog/ui/style/app/buttonrenderer_test.js
    deleted file mode 100644
    index 6b481419b33..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/style/app/buttonrenderer_test.js
    +++ /dev/null
    @@ -1,130 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.style.app.ButtonRendererTest');
    -goog.setTestOnly('goog.ui.style.app.ButtonRendererTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.ui.style');
    -goog.require('goog.ui.Button');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.style.app.ButtonRenderer');
    -goog.require('goog.userAgent');
    -var renderer = goog.ui.style.app.ButtonRenderer.getInstance();
    -var button;
    -
    -// Write iFrame tag to load reference FastUI markup. Then, our tests will
    -// compare the generated markup to the reference markup.
    -var refPath = '../../../../../webutil/css/fastui/app/button_spec.html';
    -goog.testing.ui.style.writeReferenceFrame(refPath);
    -
    -function setUp() {
    -  button = new goog.ui.Button('Hello Generated', renderer);
    -  button.setTooltip('Click for Generated');
    -}
    -
    -function tearDown() {
    -  if (button) {
    -    button.dispose();
    -  }
    -  goog.dom.getElement('sandbox').innerHTML = '';
    -}
    -
    -function testGeneratedButton() {
    -  button.render(goog.dom.getElement('sandbox'));
    -  goog.testing.ui.style.assertStructureMatchesReference(button.getElement(),
    -      'normal-resting');
    -  assertEquals('Hello Generated', button.getContentElement().innerHTML);
    -  assertEquals('Click for Generated',
    -      button.getElement().getAttribute('title'));
    -}
    -
    -function testButtonStates() {
    -  button.render(goog.dom.getElement('sandbox'));
    -  goog.testing.ui.style.assertStructureMatchesReference(button.getElement(),
    -      'normal-resting');
    -  button.setState(goog.ui.Component.State.HOVER, true);
    -  goog.testing.ui.style.assertStructureMatchesReference(button.getElement(),
    -      'normal-hover');
    -  button.setState(goog.ui.Component.State.HOVER, false);
    -  button.setState(goog.ui.Component.State.FOCUSED, true);
    -  goog.testing.ui.style.assertStructureMatchesReference(button.getElement(),
    -      'normal-focused');
    -  button.setState(goog.ui.Component.State.FOCUSED, false);
    -  button.setState(goog.ui.Component.State.ACTIVE, true);
    -  goog.testing.ui.style.assertStructureMatchesReference(button.getElement(),
    -      'normal-active');
    -  button.setState(goog.ui.Component.State.ACTIVE, false);
    -  button.setState(goog.ui.Component.State.DISABLED, true);
    -  goog.testing.ui.style.assertStructureMatchesReference(button.getElement(),
    -      'normal-disabled');
    -}
    -
    -function testDecoratedButton() {
    -  button.decorate(goog.dom.getElement('button'));
    -  goog.testing.ui.style.assertStructureMatchesReference(button.getElement(),
    -      'normal-resting');
    -  assertEquals('Hello Decorated', button.getContentElement().innerHTML);
    -  assertEquals('Click for Decorated',
    -      button.getElement().getAttribute('title'));
    -}
    -
    -function testDecoratedButtonBox() {
    -  button.decorate(goog.dom.getElement('button-box'));
    -  goog.testing.ui.style.assertStructureMatchesReference(button.getElement(),
    -      'normal-resting');
    -  assertEquals('Hello Decorated Box',
    -      button.getContentElement().innerHTML);
    -  assertEquals('Click for Decorated Box',
    -      button.getElement().getAttribute('title'));
    -}
    -
    -/*
    - * This test demonstrates what happens when you put whitespace in a
    - * decorated button's content, and the decorated element 'hasBoxStructure'.
    - * Note that this behavior is different than when the element does not
    - * have box structure. Should this be fixed?
    - */
    -function testDecoratedButtonBoxWithSpaceInContent() {
    -  button.decorate(goog.dom.getElement('button-box-with-space-in-content'));
    -  goog.testing.ui.style.assertStructureMatchesReference(button.getElement(),
    -      'normal-resting');
    -  if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9)) {
    -    assertEquals('Hello Decorated Box with space ',
    -        button.getContentElement().innerHTML);
    -  } else {
    -    assertEquals('\n    Hello Decorated Box with space\n  ',
    -        button.getContentElement().innerHTML);
    -  }
    -}
    -
    -function testExistingContentIsUsed() {
    -  button.decorate(goog.dom.getElement('button-box-with-dom-content'));
    -  goog.testing.ui.style.assertStructureMatchesReference(button.getElement(),
    -      'normal-resting');
    -  // Safari 3 adds style="-webkit-user-select" to the strong tag, so we
    -  // can't simply look at the HTML.
    -  var content = button.getContentElement();
    -  assertEquals('Unexpected number of child nodes', 3,
    -      content.childNodes.length);
    -  assertEquals('Unexpected tag', 'STRONG',
    -      content.childNodes[0].tagName);
    -  assertEquals('Unexpected text content', 'Hello',
    -      content.childNodes[0].innerHTML);
    -  assertEquals('Unexpected tag', 'EM',
    -      content.childNodes[2].tagName);
    -  assertEquals('Unexpected text content', 'Box',
    -      content.childNodes[2].innerHTML);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/style/app/menubuttonrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/style/app/menubuttonrenderer.js
    deleted file mode 100644
    index c28febfaa72..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/style/app/menubuttonrenderer.js
    +++ /dev/null
    @@ -1,233 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Renderer for {@link goog.ui.style.app.MenuButton}s and
    - * subclasses.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.style.app.MenuButtonRenderer');
    -
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.style');
    -goog.require('goog.ui.Menu');
    -goog.require('goog.ui.MenuRenderer');
    -goog.require('goog.ui.style.app.ButtonRenderer');
    -
    -
    -
    -/**
    - * Renderer for {@link goog.ui.style.app.MenuButton}s.  This implementation
    - * overrides {@link goog.ui.style.app.ButtonRenderer#createButton} to insert a
    - * dropdown element into the content element after the specified content.
    - * @constructor
    - * @extends {goog.ui.style.app.ButtonRenderer}
    - * @final
    - */
    -goog.ui.style.app.MenuButtonRenderer = function() {
    -  goog.ui.style.app.ButtonRenderer.call(this);
    -};
    -goog.inherits(goog.ui.style.app.MenuButtonRenderer,
    -    goog.ui.style.app.ButtonRenderer);
    -goog.addSingletonGetter(goog.ui.style.app.MenuButtonRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.style.app.MenuButtonRenderer.CSS_CLASS =
    -    goog.getCssName('goog-menu-button');
    -
    -
    -/**
    - * Array of arrays of CSS classes that we want composite classes added and
    - * removed for in IE6 and lower as a workaround for lack of multi-class CSS
    - * selector support.
    - * @type {Array<Array<string>>}
    - */
    -goog.ui.style.app.MenuButtonRenderer.IE6_CLASS_COMBINATIONS = [
    -  [goog.getCssName('goog-button-base-rtl'),
    -   goog.getCssName('goog-menu-button')],
    -
    -  [goog.getCssName('goog-button-base-hover'),
    -   goog.getCssName('goog-menu-button')],
    -
    -  [goog.getCssName('goog-button-base-focused'),
    -   goog.getCssName('goog-menu-button')],
    -
    -  [goog.getCssName('goog-button-base-disabled'),
    -   goog.getCssName('goog-menu-button')],
    -
    -  [goog.getCssName('goog-button-base-active'),
    -   goog.getCssName('goog-menu-button')],
    -
    -  [goog.getCssName('goog-button-base-open'),
    -   goog.getCssName('goog-menu-button')],
    -
    -  [goog.getCssName('goog-button-base-active'),
    -   goog.getCssName('goog-button-base-open'),
    -   goog.getCssName('goog-menu-button')]
    -];
    -
    -
    -/**
    - * Returns the ARIA role to be applied to menu buttons, which
    - * have a menu attached to them.
    - * @return {goog.a11y.aria.Role} ARIA role.
    - * @override
    - */
    -goog.ui.style.app.MenuButtonRenderer.prototype.getAriaRole = function() {
    -  // If we apply the 'button' ARIA role to the menu button, the
    -  // screen reader keeps referring to menus as buttons, which
    -  // might be misleading for the users. Hence the ARIA role
    -  // 'menu' is assigned.
    -  return goog.a11y.aria.Role.MENU;
    -};
    -
    -
    -/**
    - * Takes the button's root element and returns the parent element of the
    - * button's contents.  Overrides the superclass implementation by taking
    - * the nested DIV structure of menu buttons into account.
    - * @param {Element} element Root element of the button whose content element
    - *     is to be returned.
    - * @return {Element} The button's content element.
    - * @override
    - */
    -goog.ui.style.app.MenuButtonRenderer.prototype.getContentElement =
    -    function(element) {
    -  return goog.ui.style.app.MenuButtonRenderer.superClass_.getContentElement
    -      .call(this, element);
    -};
    -
    -
    -/**
    - * Takes an element, decorates it with the menu button control, and returns
    - * the element.  Overrides {@link goog.ui.style.app.ButtonRenderer#decorate} by
    - * looking for a child element that can be decorated by a menu, and if it
    - * finds one, decorates it and attaches it to the menu button.
    - * @param {goog.ui.Control} control goog.ui.MenuButton to decorate the element.
    - * @param {Element} element Element to decorate.
    - * @return {Element} Decorated element.
    - * @override
    - */
    -goog.ui.style.app.MenuButtonRenderer.prototype.decorate =
    -    function(control, element) {
    -  var button = /** @type {goog.ui.MenuButton} */ (control);
    -  // TODO(attila):  Add more robust support for subclasses of goog.ui.Menu.
    -  var menuElem = goog.dom.getElementsByTagNameAndClass(
    -      '*', goog.ui.MenuRenderer.CSS_CLASS, element)[0];
    -  if (menuElem) {
    -    // Move the menu element directly under the body (but hide it first to
    -    // prevent flicker; see bug 1089244).
    -    goog.style.setElementShown(menuElem, false);
    -    goog.dom.appendChild(goog.dom.getOwnerDocument(menuElem).body, menuElem);
    -
    -    // Decorate the menu and attach it to the button.
    -    var menu = new goog.ui.Menu();
    -    menu.decorate(menuElem);
    -    button.setMenu(menu);
    -  }
    -
    -  // Let the superclass do the rest.
    -  return goog.ui.style.app.MenuButtonRenderer.superClass_.decorate.call(this,
    -      button, element);
    -};
    -
    -
    -/**
    - * Takes a text caption or existing DOM structure, and returns the content and
    - * a dropdown arrow element wrapped in a pseudo-rounded-corner box.  Creates
    - * the following DOM structure:
    - *  <div class="goog-inline-block goog-button-outer-box">
    - *    <div class="goog-inline-block goog-button-inner-box">
    - *      <div class="goog-button-pos">
    - *        <div class="goog-button-top-shadow">&nbsp;</div>
    - *        <div class="goog-button-content">
    - *          Contents...
    - *          <div class="goog-menu-button-dropdown"> </div>
    - *        </div>
    - *      </div>
    - *    </div>
    - *  </div>
    - * @param {goog.ui.ControlContent} content Text caption or DOM structure to wrap
    - *     in a box.
    - * @param {goog.dom.DomHelper} dom DOM helper, used for document interaction.
    - * @return {Element} Pseudo-rounded-corner box containing the content.
    - * @override
    - */
    -goog.ui.style.app.MenuButtonRenderer.prototype.createButton = function(content,
    -    dom) {
    -  var contentWithDropdown = this.createContentWithDropdown(content, dom);
    -  return goog.ui.style.app.MenuButtonRenderer.superClass_.createButton.call(
    -      this, contentWithDropdown, dom);
    -};
    -
    -
    -/** @override */
    -goog.ui.style.app.MenuButtonRenderer.prototype.setContent = function(element,
    -    content) {
    -  var dom = goog.dom.getDomHelper(this.getContentElement(element));
    -  goog.ui.style.app.MenuButtonRenderer.superClass_.setContent.call(
    -      this, element, this.createContentWithDropdown(content, dom));
    -};
    -
    -
    -/**
    - * Inserts dropdown element as last child of existing content.
    - * @param {goog.ui.ControlContent} content Text caption or DOM structure.
    - * @param {goog.dom.DomHelper} dom DOM helper, used for document ineraction.
    - * @return {Array<Node>} DOM structure to be set as the button's content.
    - */
    -goog.ui.style.app.MenuButtonRenderer.prototype.createContentWithDropdown =
    -    function(content, dom) {
    -  var caption = dom.createDom('div', null, content, this.createDropdown(dom));
    -  return goog.array.toArray(caption.childNodes);
    -};
    -
    -
    -/**
    - * Returns an appropriately-styled DIV containing a dropdown arrow.
    - * Creates the following DOM structure:
    - *    <div class="goog-menu-button-dropdown"> </div>
    - * @param {goog.dom.DomHelper} dom DOM helper, used for document interaction.
    - * @return {Element} Dropdown element.
    - */
    -goog.ui.style.app.MenuButtonRenderer.prototype.createDropdown = function(dom) {
    -  return dom.createDom('div', goog.getCssName(this.getCssClass(), 'dropdown'));
    -};
    -
    -
    -/**
    - * Returns the CSS class to be applied to the root element of components
    - * rendered using this renderer.
    - * @return {string} Renderer-specific CSS class.
    - * @override
    - */
    -goog.ui.style.app.MenuButtonRenderer.prototype.getCssClass = function() {
    -  return goog.ui.style.app.MenuButtonRenderer.CSS_CLASS;
    -};
    -
    -
    -/** @override */
    -goog.ui.style.app.MenuButtonRenderer.prototype.getIe6ClassCombinations =
    -    function() {
    -  return goog.ui.style.app.MenuButtonRenderer.IE6_CLASS_COMBINATIONS;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/style/app/menubuttonrenderer_test.html b/src/database/third_party/closure-library/closure/goog/ui/style/app/menubuttonrenderer_test.html
    deleted file mode 100644
    index 3f77a8ffc17..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/style/app/menubuttonrenderer_test.html
    +++ /dev/null
    @@ -1,48 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.style.app.MenuButtonRenderer
    -  </title>
    -  <script src="../../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.ui.style.app.MenuButtonRendererTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="sandbox"></div>
    -
    -  <div id="button" title="Click for Decorated">
    -    Hello Decorated
    -  </div>
    -
    -  <div id="button-2" title="Click for Decorated">
    -    Hello Decorated
    -  </div>
    -
    -  <!-- The component DOM must always be created without whitespace. -->
    -  <div id="button-box" title="Click for Decorated Box" class="goog-menu-button goog-button-base"><div class="goog-inline-block goog-button-base-outer-box"><div class="goog-inline-block goog-button-base-inner-box"><div class="goog-button-base-pos"><div class="goog-button-base-top-shadow">&nbsp;</div><div class="goog-button-base-content">Hello Decorated Box<div class="goog-menu-button-dropdown"> </div></div></div></div></div></div>
    -
    -  <div id="button-with-dom-content" class="goog-menu-button">
    -    <strong>Hello Strong</strong> <em>Box</em>
    -  </div>
    -
    -  <div id="button-with-menu" class="goog-menu-button">
    -    Button with Menu
    -    <div class="goog-menu">
    -      <div class="goog-menuitem">Item 1</div>
    -      <div class="goog-menuitem">Item 2</div>
    -    </div>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/style/app/menubuttonrenderer_test.js b/src/database/third_party/closure-library/closure/goog/ui/style/app/menubuttonrenderer_test.js
    deleted file mode 100644
    index f2c9194f6f0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/style/app/menubuttonrenderer_test.js
    +++ /dev/null
    @@ -1,136 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.style.app.MenuButtonRendererTest');
    -goog.setTestOnly('goog.ui.style.app.MenuButtonRendererTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.ui.style');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.MenuButton');
    -goog.require('goog.ui.style.app.MenuButtonRenderer');
    -var renderer = goog.ui.style.app.MenuButtonRenderer.getInstance();
    -var button;
    -
    -// Write iFrame tag to load reference FastUI markup. Then, our tests will
    -// compare the generated markup to the reference markup.
    -var refPath = '../../../../../webutil/css/fastui/app/menubutton_spec.html';
    -goog.testing.ui.style.writeReferenceFrame(refPath);
    -
    -function setUp() {
    -  button = new goog.ui.MenuButton('Hello Generated', null, renderer);
    -  button.setTooltip('Click for Generated');
    -}
    -
    -function tearDown() {
    -  if (button) {
    -    button.dispose();
    -  }
    -  goog.dom.getElement('sandbox').innerHTML = '';
    -}
    -
    -function testGeneratedButton() {
    -  button.render(goog.dom.getElement('sandbox'));
    -  goog.testing.ui.style.assertStructureMatchesReference(button.getElement(),
    -      'normal-resting');
    -  assertEquals('Hello Generated',
    -      button.getContentElement().firstChild.nodeValue);
    -  assertEquals('Click for Generated',
    -      button.getElement().getAttribute('title'));
    -}
    -
    -function testButtonStates() {
    -  button.render(goog.dom.getElement('sandbox'));
    -  goog.testing.ui.style.assertStructureMatchesReference(button.getElement(),
    -      'normal-resting');
    -  button.setState(goog.ui.Component.State.HOVER, true);
    -  goog.testing.ui.style.assertStructureMatchesReference(button.getElement(),
    -      'normal-hover');
    -  button.setState(goog.ui.Component.State.HOVER, false);
    -  button.setState(goog.ui.Component.State.FOCUSED, true);
    -  goog.testing.ui.style.assertStructureMatchesReference(button.getElement(),
    -      'normal-focused');
    -  button.setState(goog.ui.Component.State.FOCUSED, false);
    -  button.setState(goog.ui.Component.State.ACTIVE, true);
    -  goog.testing.ui.style.assertStructureMatchesReference(button.getElement(),
    -      'normal-active');
    -  button.setState(goog.ui.Component.State.ACTIVE, false);
    -  button.setState(goog.ui.Component.State.DISABLED, true);
    -  goog.testing.ui.style.assertStructureMatchesReference(button.getElement(),
    -      'normal-disabled');
    -}
    -
    -function testDecoratedButton() {
    -  button.decorate(goog.dom.getElement('button'));
    -  goog.testing.ui.style.assertStructureMatchesReference(button.getElement(),
    -      'normal-resting');
    -  assertEquals('Hello Decorated',
    -      button.getContentElement().firstChild.nodeValue);
    -  assertEquals('Click for Decorated',
    -      button.getElement().getAttribute('title'));
    -}
    -
    -function testDecoratedButtonBox() {
    -  button.decorate(goog.dom.getElement('button-box'));
    -  goog.testing.ui.style.assertStructureMatchesReference(button.getElement(),
    -      'normal-resting');
    -  assertEquals('Hello Decorated Box',
    -      button.getContentElement().firstChild.nodeValue);
    -  assertEquals('Click for Decorated Box',
    -      button.getElement().getAttribute('title'));
    -}
    -
    -function testExistingContentIsUsed() {
    -  button.decorate(goog.dom.getElement('button-with-dom-content'));
    -  goog.testing.ui.style.assertStructureMatchesReference(button.getElement(),
    -      'normal-resting');
    -  // Safari 3 adds style="-webkit-user-select" to the strong tag, so we
    -  // can't simply look at the HTML.
    -  var content = button.getContentElement();
    -  assertEquals('Unexpected number of child nodes; expected existing number ' +
    -      'plus one for the dropdown element', 4, content.childNodes.length);
    -  assertEquals('Unexpected tag', 'STRONG',
    -      content.childNodes[0].tagName);
    -  assertEquals('Unexpected text content', 'Hello Strong',
    -      content.childNodes[0].innerHTML);
    -  assertEquals('Unexpected tag', 'EM',
    -      content.childNodes[2].tagName);
    -  assertEquals('Unexpected text content', 'Box',
    -      content.childNodes[2].innerHTML);
    -}
    -
    -function testDecoratedButtonWithMenu() {
    -  button.decorate(goog.dom.getElement('button-with-menu'));
    -  assertEquals('Unexpected number of menu items', 2, button.getItemCount());
    -  goog.testing.ui.style.assertStructureMatchesReference(button.getElement(),
    -      'normal-resting');
    -  assertFalse('Expected menu element to not be contained by button',
    -      goog.dom.contains(button.getElement(),
    -          button.getMenu().getElement()));
    -}
    -
    -function testDropDownExistsAfterButtonRename() {
    -  button.decorate(goog.dom.getElement('button-2'));
    -  button.setContent('New title');
    -  goog.testing.ui.style.assertStructureMatchesReference(button.getElement(),
    -      'normal-resting');
    -  assertEquals('Unexpected number of child nodes; expected text element ' +
    -      'and the dropdown element',
    -      2, button.getContentElement().childNodes.length);
    -  assertEquals('New title',
    -      button.getContentElement().firstChild.nodeValue);
    -  assertEquals('Click for Decorated',
    -      button.getElement().getAttribute('title'));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/style/app/primaryactionbuttonrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/style/app/primaryactionbuttonrenderer.js
    deleted file mode 100644
    index e2fc1cf6a3a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/style/app/primaryactionbuttonrenderer.js
    +++ /dev/null
    @@ -1,89 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Renderer for {@link goog.ui.Button}s in App style. This
    - * type of button is typically used for an application's "primary action," eg
    - * in Gmail, it's "Compose," in Calendar, it's "Create Event".
    - *
    - */
    -
    -goog.provide('goog.ui.style.app.PrimaryActionButtonRenderer');
    -
    -goog.require('goog.ui.Button');
    -goog.require('goog.ui.registry');
    -goog.require('goog.ui.style.app.ButtonRenderer');
    -
    -
    -
    -/**
    - * Custom renderer for {@link goog.ui.Button}s. This renderer supports the
    - * "primary action" style for buttons.
    - *
    - * @constructor
    - * @extends {goog.ui.style.app.ButtonRenderer}
    - * @final
    - */
    -goog.ui.style.app.PrimaryActionButtonRenderer = function() {
    -  goog.ui.style.app.ButtonRenderer.call(this);
    -};
    -goog.inherits(goog.ui.style.app.PrimaryActionButtonRenderer,
    -    goog.ui.style.app.ButtonRenderer);
    -goog.addSingletonGetter(goog.ui.style.app.PrimaryActionButtonRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.style.app.PrimaryActionButtonRenderer.CSS_CLASS =
    -    'goog-primaryactionbutton';
    -
    -
    -/**
    - * Array of arrays of CSS classes that we want composite classes added and
    - * removed for in IE6 and lower as a workaround for lack of multi-class CSS
    - * selector support.
    - * @type {Array<Array<string>>}
    - */
    -goog.ui.style.app.PrimaryActionButtonRenderer.IE6_CLASS_COMBINATIONS = [
    -  ['goog-button-base-disabled', 'goog-primaryactionbutton'],
    -  ['goog-button-base-focused', 'goog-primaryactionbutton'],
    -  ['goog-button-base-hover', 'goog-primaryactionbutton']
    -];
    -
    -
    -/** @override */
    -goog.ui.style.app.PrimaryActionButtonRenderer.prototype.getCssClass =
    -    function() {
    -  return goog.ui.style.app.PrimaryActionButtonRenderer.CSS_CLASS;
    -};
    -
    -
    -/** @override */
    -goog.ui.style.app.PrimaryActionButtonRenderer.prototype.
    -    getIe6ClassCombinations = function() {
    -  return goog.ui.style.app.PrimaryActionButtonRenderer.IE6_CLASS_COMBINATIONS;
    -};
    -
    -
    -// Register a decorator factory function for
    -// goog.ui.style.app.PrimaryActionButtonRenderer.
    -goog.ui.registry.setDecoratorByClassName(
    -    goog.ui.style.app.PrimaryActionButtonRenderer.CSS_CLASS,
    -    function() {
    -      return new goog.ui.Button(null,
    -          goog.ui.style.app.PrimaryActionButtonRenderer.getInstance());
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/style/app/primaryactionbuttonrenderer_test.html b/src/database/third_party/closure-library/closure/goog/ui/style/app/primaryactionbuttonrenderer_test.html
    deleted file mode 100644
    index 320658d5af3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/style/app/primaryactionbuttonrenderer_test.html
    +++ /dev/null
    @@ -1,27 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests -
    -      goog.ui.style.app.PrimaryActionButtonRenderer
    -  </title>
    -  <script src="../../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.ui.style.app.PrimaryActionButtonRendererTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="sandbox">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/style/app/primaryactionbuttonrenderer_test.js b/src/database/third_party/closure-library/closure/goog/ui/style/app/primaryactionbuttonrenderer_test.js
    deleted file mode 100644
    index b66ec0dbc94..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/style/app/primaryactionbuttonrenderer_test.js
    +++ /dev/null
    @@ -1,69 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.style.app.PrimaryActionButtonRendererTest');
    -goog.setTestOnly('goog.ui.style.app.PrimaryActionButtonRendererTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.ui.style');
    -goog.require('goog.ui.Button');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.style.app.PrimaryActionButtonRenderer');
    -var renderer = goog.ui.style.app.PrimaryActionButtonRenderer.getInstance();
    -var button;
    -
    -// Write iFrame tag to load reference FastUI markup. Then, our tests will
    -// compare the generated markup to the reference markup.
    -var refPath = '../../../../../' +
    -    'webutil/css/fastui/app/primaryactionbutton_spec.html';
    -goog.testing.ui.style.writeReferenceFrame(refPath);
    -
    -function setUp() {
    -  button = new goog.ui.Button('Hello Generated', renderer);
    -}
    -
    -function tearDown() {
    -  if (button) {
    -    button.dispose();
    -  }
    -  goog.dom.getElement('sandbox').innerHTML = '';
    -}
    -
    -function testGeneratedButton() {
    -  button.render(goog.dom.getElement('sandbox'));
    -  goog.testing.ui.style.assertStructureMatchesReference(button.getElement(),
    -      'normal-resting');
    -}
    -
    -function testButtonStates() {
    -  button.render(goog.dom.getElement('sandbox'));
    -  goog.testing.ui.style.assertStructureMatchesReference(button.getElement(),
    -      'normal-resting');
    -  button.setState(goog.ui.Component.State.HOVER, true);
    -  goog.testing.ui.style.assertStructureMatchesReference(button.getElement(),
    -      'normal-hover');
    -  button.setState(goog.ui.Component.State.HOVER, false);
    -  button.setState(goog.ui.Component.State.FOCUSED, true);
    -  goog.testing.ui.style.assertStructureMatchesReference(button.getElement(),
    -      'normal-focused');
    -  button.setState(goog.ui.Component.State.FOCUSED, false);
    -  button.setState(goog.ui.Component.State.ACTIVE, true);
    -  goog.testing.ui.style.assertStructureMatchesReference(button.getElement(),
    -      'normal-active');
    -  button.setState(goog.ui.Component.State.ACTIVE, false);
    -  button.setState(goog.ui.Component.State.DISABLED, true);
    -  goog.testing.ui.style.assertStructureMatchesReference(button.getElement(),
    -      'normal-disabled');
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/submenu.js b/src/database/third_party/closure-library/closure/goog/ui/submenu.js
    deleted file mode 100644
    index 28869d3d3cc..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/submenu.js
    +++ /dev/null
    @@ -1,671 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A class representing menu items that open a submenu.
    - * @see goog.ui.Menu
    - *
    - * @see ../demos/submenus.html
    - * @see ../demos/submenus2.html
    - */
    -
    -goog.provide('goog.ui.SubMenu');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.positioning.AnchoredViewportPosition');
    -goog.require('goog.positioning.Corner');
    -goog.require('goog.style');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.Menu');
    -goog.require('goog.ui.MenuItem');
    -goog.require('goog.ui.SubMenuRenderer');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * Class representing a submenu that can be added as an item to other menus.
    - *
    - * @param {goog.ui.ControlContent} content Text caption or DOM structure to
    - *     display as the content of the submenu (use to add icons or styling to
    - *     menus).
    - * @param {*=} opt_model Data/model associated with the menu item.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional dom helper used for dom
    - *     interactions.
    - * @param {goog.ui.MenuItemRenderer=} opt_renderer Renderer used to render or
    - *     decorate the component; defaults to {@link goog.ui.SubMenuRenderer}.
    - * @constructor
    - * @extends {goog.ui.MenuItem}
    - */
    -goog.ui.SubMenu = function(content, opt_model, opt_domHelper, opt_renderer) {
    -  goog.ui.MenuItem.call(this, content, opt_model, opt_domHelper,
    -                        opt_renderer || goog.ui.SubMenuRenderer.getInstance());
    -};
    -goog.inherits(goog.ui.SubMenu, goog.ui.MenuItem);
    -goog.tagUnsealableClass(goog.ui.SubMenu);
    -
    -
    -/**
    - * The delay before opening the sub menu in milliseconds.
    - * @type {number}
    - */
    -goog.ui.SubMenu.MENU_DELAY_MS = 218;
    -
    -
    -/**
    - * Timer used to dismiss the submenu when the item becomes unhighlighted.
    - * @type {?number}
    - * @private
    - */
    -goog.ui.SubMenu.prototype.dismissTimer_ = null;
    -
    -
    -/**
    - * Timer used to show the submenu on mouseover.
    - * @type {?number}
    - * @private
    - */
    -goog.ui.SubMenu.prototype.showTimer_ = null;
    -
    -
    -/**
    - * Whether the submenu believes the menu is visible.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.SubMenu.prototype.menuIsVisible_ = false;
    -
    -
    -/**
    - * The lazily created sub menu.
    - * @type {goog.ui.Menu?}
    - * @private
    - */
    -goog.ui.SubMenu.prototype.subMenu_ = null;
    -
    -
    -/**
    - * Whether or not the sub-menu was set explicitly.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.SubMenu.prototype.externalSubMenu_ = false;
    -
    -
    -/**
    - * Whether or not to align the submenu at the end of the parent menu.
    - * If true, the menu expands to the right in LTR languages and to the left
    - * in RTL langauges.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.SubMenu.prototype.alignToEnd_ = true;
    -
    -
    -/**
    - * Whether the position of this submenu may be adjusted to fit
    - * the visible area, as in {@link goog.ui.Popup.positionAtCoordinate}.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.SubMenu.prototype.isPositionAdjustable_ = false;
    -
    -
    -/** @override */
    -goog.ui.SubMenu.prototype.enterDocument = function() {
    -  goog.ui.SubMenu.superClass_.enterDocument.call(this);
    -
    -  this.getHandler().listen(this.getParent(), goog.ui.Component.EventType.HIDE,
    -      this.onParentHidden_);
    -
    -  if (this.subMenu_) {
    -    this.setMenuListenersEnabled_(this.subMenu_, true);
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.SubMenu.prototype.exitDocument = function() {
    -  this.getHandler().unlisten(this.getParent(), goog.ui.Component.EventType.HIDE,
    -      this.onParentHidden_);
    -
    -  if (this.subMenu_) {
    -    this.setMenuListenersEnabled_(this.subMenu_, false);
    -    if (!this.externalSubMenu_) {
    -      this.subMenu_.exitDocument();
    -      goog.dom.removeNode(this.subMenu_.getElement());
    -    }
    -  }
    -
    -  goog.ui.SubMenu.superClass_.exitDocument.call(this);
    -};
    -
    -
    -/** @override */
    -goog.ui.SubMenu.prototype.disposeInternal = function() {
    -  if (this.subMenu_ && !this.externalSubMenu_) {
    -    this.subMenu_.dispose();
    -  }
    -  this.subMenu_ = null;
    -  goog.ui.SubMenu.superClass_.disposeInternal.call(this);
    -};
    -
    -
    -/**
    - * @override
    - * Dismisses the submenu on a delay, with the result that the user needs less
    - * accuracy when moving to submenus.  Alternate implementations could use
    - * geometry instead of a timer.
    - * @param {boolean} highlight Whether item should be highlighted.
    - * @param {boolean=} opt_btnPressed Whether the mouse button is held down.
    - */
    -goog.ui.SubMenu.prototype.setHighlighted = function(highlight,
    -                                                    opt_btnPressed) {
    -  goog.ui.SubMenu.superClass_.setHighlighted.call(this, highlight);
    -
    -  if (opt_btnPressed) {
    -    this.getMenu().setMouseButtonPressed(true);
    -  }
    -
    -  if (!highlight) {
    -    if (this.dismissTimer_) {
    -      goog.Timer.clear(this.dismissTimer_);
    -    }
    -    this.dismissTimer_ = goog.Timer.callOnce(
    -        this.dismissSubMenu, goog.ui.SubMenu.MENU_DELAY_MS, this);
    -  }
    -};
    -
    -
    -/**
    - * Show the submenu and ensure that all siblings are hidden.
    - */
    -goog.ui.SubMenu.prototype.showSubMenu = function() {
    -  // Only show the menu if this item is still selected. This is called on a
    -  // timeout, so make sure our parent still exists.
    -  var parent = this.getParent();
    -  if (parent && parent.getHighlighted() == this) {
    -    this.setSubMenuVisible_(true);
    -    this.dismissSiblings_();
    -  }
    -};
    -
    -
    -/**
    - * Dismisses the menu and all further submenus.
    - */
    -goog.ui.SubMenu.prototype.dismissSubMenu = function() {
    -  // Because setHighlighted calls this function on a timeout, we need to make
    -  // sure that the sub menu hasn't been disposed when we come back.
    -  var subMenu = this.subMenu_;
    -  if (subMenu && subMenu.getParent() == this) {
    -    this.setSubMenuVisible_(false);
    -    subMenu.forEachChild(function(child) {
    -      if (typeof child.dismissSubMenu == 'function') {
    -        child.dismissSubMenu();
    -      }
    -    });
    -  }
    -};
    -
    -
    -/**
    - * Clears the show and hide timers for the sub menu.
    - */
    -goog.ui.SubMenu.prototype.clearTimers = function() {
    -  if (this.dismissTimer_) {
    -    goog.Timer.clear(this.dismissTimer_);
    -  }
    -  if (this.showTimer_) {
    -    goog.Timer.clear(this.showTimer_);
    -  }
    -};
    -
    -
    -/**
    - * Sets the menu item to be visible or invisible.
    - * @param {boolean} visible Whether to show or hide the component.
    - * @param {boolean=} opt_force If true, doesn't check whether the component
    - *     already has the requested visibility, and doesn't dispatch any events.
    - * @return {boolean} Whether the visibility was changed.
    - * @override
    - */
    -goog.ui.SubMenu.prototype.setVisible = function(visible, opt_force) {
    -  var visibilityChanged = goog.ui.SubMenu.superClass_.setVisible.call(this,
    -      visible, opt_force);
    -  // For menus that allow menu items to be hidden (i.e. ComboBox) ensure that
    -  // the submenu is hidden.
    -  if (visibilityChanged && !this.isVisible()) {
    -    this.dismissSubMenu();
    -  }
    -  return visibilityChanged;
    -};
    -
    -
    -/**
    - * Dismiss all the sub menus of sibling menu items.
    - * @private
    - */
    -goog.ui.SubMenu.prototype.dismissSiblings_ = function() {
    -  this.getParent().forEachChild(function(child) {
    -    if (child != this && typeof child.dismissSubMenu == 'function') {
    -      child.dismissSubMenu();
    -      child.clearTimers();
    -    }
    -  }, this);
    -};
    -
    -
    -/**
    - * Handles a key event that is passed to the menu item from its parent because
    - * it is highlighted.  If the right key is pressed the sub menu takes control
    - * and delegates further key events to its menu until it is dismissed OR the
    - * left key is pressed.
    - * @param {goog.events.KeyEvent} e A key event.
    - * @return {boolean} Whether the event was handled.
    - * @override
    - */
    -goog.ui.SubMenu.prototype.handleKeyEvent = function(e) {
    -  var keyCode = e.keyCode;
    -  var openKeyCode = this.isRightToLeft() ? goog.events.KeyCodes.LEFT :
    -      goog.events.KeyCodes.RIGHT;
    -  var closeKeyCode = this.isRightToLeft() ? goog.events.KeyCodes.RIGHT :
    -      goog.events.KeyCodes.LEFT;
    -
    -  if (!this.menuIsVisible_) {
    -    // Menu item doesn't have keyboard control and the right key was pressed.
    -    // So open take keyboard control and open the sub menu.
    -    if (this.isEnabled() &&
    -        (keyCode == openKeyCode || keyCode == this.getMnemonic())) {
    -      this.showSubMenu();
    -      this.getMenu().highlightFirst();
    -      this.clearTimers();
    -
    -    // The menu item doesn't currently care about the key events so let the
    -    // parent menu handle them accordingly .
    -    } else {
    -      return false;
    -    }
    -
    -  // Menu item has control, so let its menu try to handle the keys (this may
    -  // in turn be handled by sub-sub menus).
    -  } else if (this.getMenu().handleKeyEvent(e)) {
    -    // Nothing to do
    -
    -  // The menu has control and the key hasn't yet been handled, on left arrow
    -  // we turn off key control.
    -  } else if (keyCode == closeKeyCode) {
    -    this.dismissSubMenu();
    -
    -  } else {
    -    // Submenu didn't handle the key so let the parent decide what to do.
    -    return false;
    -  }
    -
    -  e.preventDefault();
    -  return true;
    -};
    -
    -
    -/**
    - * Listens to the sub menus items and ensures that this menu item is selected
    - * while dismissing the others.  This handles the case when the user mouses
    - * over other items on their way to the sub menu.
    - * @param {goog.events.Event} e Enter event to handle.
    - * @private
    - */
    -goog.ui.SubMenu.prototype.onChildEnter_ = function(e) {
    -  if (this.subMenu_.getParent() == this) {
    -    this.clearTimers();
    -    this.getParentEventTarget().setHighlighted(this);
    -    this.dismissSiblings_();
    -  }
    -};
    -
    -
    -/**
    - * Listens to the parent menu's hide event and ensures that all submenus are
    - * hidden at the same time.
    - * @param {goog.events.Event} e The event.
    - * @private
    - */
    -goog.ui.SubMenu.prototype.onParentHidden_ = function(e) {
    -  // Ignore propagated events
    -  if (e.target == this.getParentEventTarget()) {
    -    // TODO(user): Using an event for this is expensive.  Consider having a
    -    // generalized interface that the parent menu calls on its children when
    -    // it is hidden.
    -    this.dismissSubMenu();
    -    this.clearTimers();
    -  }
    -};
    -
    -
    -/**
    - * @override
    - * Sets a timer to show the submenu and then dispatches an ENTER event to the
    - * parent menu.
    - * @param {goog.events.BrowserEvent} e Mouse event to handle.
    - * @protected
    - */
    -goog.ui.SubMenu.prototype.handleMouseOver = function(e) {
    -  if (this.isEnabled()) {
    -    this.clearTimers();
    -    this.showTimer_ = goog.Timer.callOnce(
    -        this.showSubMenu, goog.ui.SubMenu.MENU_DELAY_MS, this);
    -  }
    -  goog.ui.SubMenu.superClass_.handleMouseOver.call(this, e);
    -};
    -
    -
    -/**
    - * Overrides the default mouseup event handler, so that the ACTION isn't
    - * dispatched for the submenu itself, instead the submenu is shown instantly.
    - * @param {goog.events.Event} e The browser event.
    - * @return {boolean} True if the action was allowed to proceed, false otherwise.
    - * @override
    - */
    -goog.ui.SubMenu.prototype.performActionInternal = function(e) {
    -  this.clearTimers();
    -  var shouldHandleClick = this.isSupportedState(
    -      goog.ui.Component.State.SELECTED);
    -  if (shouldHandleClick) {
    -    return goog.ui.SubMenu.superClass_.performActionInternal.call(this, e);
    -  } else {
    -    this.showSubMenu();
    -    return true;
    -  }
    -};
    -
    -
    -/**
    - * Sets the visiblility of the sub menu.
    - * @param {boolean} visible Whether to show menu.
    - * @private
    - */
    -goog.ui.SubMenu.prototype.setSubMenuVisible_ = function(visible) {
    -  // Dispatch OPEN event before calling getMenu(), so we can create the menu
    -  // lazily on first access.
    -  this.dispatchEvent(goog.ui.Component.getStateTransitionEvent(
    -      goog.ui.Component.State.OPENED, visible));
    -  var subMenu = this.getMenu();
    -  if (visible != this.menuIsVisible_) {
    -    goog.dom.classlist.enable(
    -        goog.asserts.assert(this.getElement()),
    -        goog.getCssName('goog-submenu-open'), visible);
    -  }
    -  if (visible != subMenu.isVisible()) {
    -    if (visible) {
    -      // Lazy-render menu when first shown, if needed.
    -      if (!subMenu.isInDocument()) {
    -        subMenu.render();
    -      }
    -      subMenu.setHighlightedIndex(-1);
    -    }
    -    subMenu.setVisible(visible);
    -    // We must position after the menu is visible, otherwise positioning logic
    -    // breaks in RTL.
    -    if (visible) {
    -      this.positionSubMenu();
    -    }
    -  }
    -  this.menuIsVisible_ = visible;
    -};
    -
    -
    -/**
    - * Attaches or detaches menu event listeners to/from the given menu.  Called
    - * each time a menu is attached to or detached from the submenu.
    - * @param {goog.ui.Menu} menu Menu on which to listen for events.
    - * @param {boolean} attach Whether to attach or detach event listeners.
    - * @private
    - */
    -goog.ui.SubMenu.prototype.setMenuListenersEnabled_ = function(menu, attach) {
    -  var handler = this.getHandler();
    -  var method = attach ? handler.listen : handler.unlisten;
    -  method.call(handler, menu, goog.ui.Component.EventType.ENTER,
    -      this.onChildEnter_);
    -};
    -
    -
    -/**
    - * Sets whether the submenu is aligned at the end of the parent menu.
    - * @param {boolean} alignToEnd True to align to end, false to align to start.
    - */
    -goog.ui.SubMenu.prototype.setAlignToEnd = function(alignToEnd) {
    -  if (alignToEnd != this.alignToEnd_) {
    -    this.alignToEnd_ = alignToEnd;
    -    if (this.isInDocument()) {
    -      // Completely re-render the widget.
    -      var oldElement = this.getElement();
    -      this.exitDocument();
    -
    -      if (oldElement.nextSibling) {
    -        this.renderBefore(/** @type {!Element} */ (oldElement.nextSibling));
    -      } else {
    -        this.render(/** @type {Element} */ (oldElement.parentNode));
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Determines whether the submenu is aligned at the end of the parent menu.
    - * @return {boolean} True if aligned to the end (the default), false if
    - *     aligned to the start.
    - */
    -goog.ui.SubMenu.prototype.isAlignedToEnd = function() {
    -  return this.alignToEnd_;
    -};
    -
    -
    -/**
    - * Positions the submenu. This method should be called if the sub menu is
    - * opened and the menu element's size changes (e.g., when adding/removing items
    - * to an opened sub menu).
    - */
    -goog.ui.SubMenu.prototype.positionSubMenu = function() {
    -  var position = new goog.positioning.AnchoredViewportPosition(
    -      this.getElement(), this.isAlignedToEnd() ?
    -      goog.positioning.Corner.TOP_END : goog.positioning.Corner.TOP_START,
    -      this.isPositionAdjustable_);
    -
    -  // TODO(user): Clean up popup code and have this be a one line call
    -  var subMenu = this.getMenu();
    -  var el = subMenu.getElement();
    -  if (!subMenu.isVisible()) {
    -    el.style.visibility = 'hidden';
    -    goog.style.setElementShown(el, true);
    -  }
    -
    -  position.reposition(
    -      el, this.isAlignedToEnd() ?
    -      goog.positioning.Corner.TOP_START : goog.positioning.Corner.TOP_END);
    -
    -  if (!subMenu.isVisible()) {
    -    goog.style.setElementShown(el, false);
    -    el.style.visibility = 'visible';
    -  }
    -};
    -
    -
    -// Methods delegated to sub-menu but accessible here for convinience
    -
    -
    -/**
    - * Adds a new menu item at the end of the menu.
    - * @param {goog.ui.MenuHeader|goog.ui.MenuItem|goog.ui.MenuSeparator} item Menu
    - *     item to add to the menu.
    - */
    -goog.ui.SubMenu.prototype.addItem = function(item) {
    -  this.getMenu().addChild(item, true);
    -};
    -
    -
    -/**
    - * Adds a new menu item at a specific index in the menu.
    - * @param {goog.ui.MenuHeader|goog.ui.MenuItem|goog.ui.MenuSeparator} item Menu
    - *     item to add to the menu.
    - * @param {number} n Index at which to insert the menu item.
    - */
    -goog.ui.SubMenu.prototype.addItemAt = function(item, n) {
    -  this.getMenu().addChildAt(item, n, true);
    -};
    -
    -
    -/**
    - * Removes an item from the menu and disposes it.
    - * @param {goog.ui.MenuItem} item The menu item to remove.
    - */
    -goog.ui.SubMenu.prototype.removeItem = function(item) {
    -  var child = this.getMenu().removeChild(item, true);
    -  if (child) {
    -    child.dispose();
    -  }
    -};
    -
    -
    -/**
    - * Removes a menu item at a given index in the menu and disposes it.
    - * @param {number} n Index of item.
    - */
    -goog.ui.SubMenu.prototype.removeItemAt = function(n) {
    -  var child = this.getMenu().removeChildAt(n, true);
    -  if (child) {
    -    child.dispose();
    -  }
    -};
    -
    -
    -/**
    - * Returns a reference to the menu item at a given index.
    - * @param {number} n Index of menu item.
    - * @return {goog.ui.Component} Reference to the menu item.
    - */
    -goog.ui.SubMenu.prototype.getItemAt = function(n) {
    -  return this.getMenu().getChildAt(n);
    -};
    -
    -
    -/**
    - * Returns the number of items in the sub menu (including separators).
    - * @return {number} The number of items in the menu.
    - */
    -goog.ui.SubMenu.prototype.getItemCount = function() {
    -  return this.getMenu().getChildCount();
    -};
    -
    -
    -/**
    - * Returns the menu items contained in the sub menu.
    - * @return {!Array<!goog.ui.MenuItem>} An array of menu items.
    - * @deprecated Use getItemAt/getItemCount instead.
    - */
    -goog.ui.SubMenu.prototype.getItems = function() {
    -  return this.getMenu().getItems();
    -};
    -
    -
    -/**
    - * Gets a reference to the submenu's actual menu.
    - * @return {!goog.ui.Menu} Reference to the object representing the sub menu.
    - */
    -goog.ui.SubMenu.prototype.getMenu = function() {
    -  if (!this.subMenu_) {
    -    this.setMenu(
    -        new goog.ui.Menu(this.getDomHelper()), /* opt_internal */ true);
    -  } else if (this.externalSubMenu_ && this.subMenu_.getParent() != this) {
    -    // Since it is possible for the same popup menu to be attached to multiple
    -    // submenus, we need to ensure that it has the correct parent event target.
    -    this.subMenu_.setParent(this);
    -  }
    -  // Always create the menu DOM, for backward compatibility.
    -  if (!this.subMenu_.getElement()) {
    -    this.subMenu_.createDom();
    -  }
    -  return this.subMenu_;
    -};
    -
    -
    -/**
    - * Sets the submenu to a specific menu.
    - * @param {goog.ui.Menu} menu The menu to show when this item is selected.
    - * @param {boolean=} opt_internal Whether this menu is an "internal" menu, and
    - *     should be disposed of when this object is disposed of.
    - */
    -goog.ui.SubMenu.prototype.setMenu = function(menu, opt_internal) {
    -  var oldMenu = this.subMenu_;
    -  if (menu != oldMenu) {
    -    if (oldMenu) {
    -      this.dismissSubMenu();
    -      if (this.isInDocument()) {
    -        this.setMenuListenersEnabled_(oldMenu, false);
    -      }
    -    }
    -
    -    this.subMenu_ = menu;
    -    this.externalSubMenu_ = !opt_internal;
    -
    -    if (menu) {
    -      menu.setParent(this);
    -      // There's no need to dispatch a HIDE event during submenu construction.
    -      menu.setVisible(false, /* opt_force */ true);
    -      menu.setAllowAutoFocus(false);
    -      menu.setFocusable(false);
    -      if (this.isInDocument()) {
    -        this.setMenuListenersEnabled_(menu, true);
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Returns true if the provided element is to be considered inside the menu for
    - * purposes such as dismissing the menu on an event.  This is so submenus can
    - * make use of elements outside their own DOM.
    - * @param {Element} element The element to test for.
    - * @return {boolean} Whether or not the provided element is contained.
    - */
    -goog.ui.SubMenu.prototype.containsElement = function(element) {
    -  return this.getMenu().containsElement(element);
    -};
    -
    -
    -/**
    - * @param {boolean} isAdjustable Whether this submenu is adjustable.
    - */
    -goog.ui.SubMenu.prototype.setPositionAdjustable = function(isAdjustable) {
    -  this.isPositionAdjustable_ = !!isAdjustable;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether this submenu is adjustable.
    - */
    -goog.ui.SubMenu.prototype.isPositionAdjustable = function() {
    -  return this.isPositionAdjustable_;
    -};
    -
    -
    -// Register a decorator factory function for goog.ui.SubMenus.
    -goog.ui.registry.setDecoratorByClassName(goog.getCssName('goog-submenu'),
    -    function() {
    -      return new goog.ui.SubMenu(null);
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/submenu_test.html b/src/database/third_party/closure-library/closure/goog/ui/submenu_test.html
    deleted file mode 100644
    index f7b4cf4433a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/submenu_test.html
    +++ /dev/null
    @@ -1,102 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -
    -  @author nicksantos@google.com (Nick Santos)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.SubMenu
    -  </title>
    -  <style type="text/css">
    -   .goog-menu {
    -  position: absolute;
    -  color: #000;
    -  border: 1px solid #B5B6B5;
    -  background-color: #F3F3F7;
    -  cursor: default;
    -  font: normal small arial, helvetica, sans-serif;
    -  margin: 0;
    -  padding: 0;
    -  outline: none;
    -}
    -
    -.goog-menuitem {
    -  padding: 2px 1.5em 2px 5px;
    -  margin: 0;
    -  list-style: none;
    -}
    -
    -.goog-menuitem-rtl {
    -  padding: 2px 5px 2px 1.5em;
    -}
    -
    -.goog-submenu-arrow {
    -  text-align: right;
    -  position: absolute;
    -  right: 0;
    -  left: auto;
    -}
    -
    -.goog-menuitem-rtl .goog-submenu-arrow {
    -  text-align: left;
    -  position: absolute;
    -  left: 0;
    -  right: auto;
    -}
    -
    -.goog-menuitem-disabled .goog-submenu-arrow {
    -  display: none;
    -}
    -  </style>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.SubMenuTest');
    -  </script>
    - </head>
    - <body>
    -  <p>
    -   Here's a menu (with submenus) defined in markup:
    -  </p>
    -  <div id="demoMenu" class="goog-menu">
    -   <div class="goog-menuitem">
    -    Open...
    -   </div>
    -   <div class="goog-submenu">
    -    Open Recent
    -    <div class="goog-menu">
    -     <div class="goog-menuitem">
    -      Annual Report.pdf
    -     </div>
    -     <div class="goog-menuitem">
    -      Quarterly Update.pdf
    -     </div>
    -     <div class="goog-menuitem">
    -      Enemies List.txt
    -     </div>
    -     <div class="goog-submenu">
    -      More
    -      <div class="goog-menu">
    -       <div class="goog-menuitem">
    -        Foo.txt
    -       </div>
    -       <div class="goog-menuitem">
    -        Bar.txt
    -       </div>
    -      </div>
    -     </div>
    -    </div>
    -   </div>
    -  </div>
    -  <div id="sandbox">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/submenu_test.js b/src/database/third_party/closure-library/closure/goog/ui/submenu_test.js
    deleted file mode 100644
    index b2022d0dc61..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/submenu_test.js
    +++ /dev/null
    @@ -1,547 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.SubMenuTest');
    -goog.setTestOnly('goog.ui.SubMenuTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.functions');
    -goog.require('goog.positioning');
    -goog.require('goog.positioning.Overflow');
    -goog.require('goog.style');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.Menu');
    -goog.require('goog.ui.MenuItem');
    -goog.require('goog.ui.SubMenu');
    -goog.require('goog.ui.SubMenuRenderer');
    -
    -var menu;
    -var clonedMenuDom;
    -
    -var mockClock;
    -
    -// mock out goog.positioning.positionAtCoordinate so that
    -// the menu always fits. (we don't care about testing the
    -// dynamic menu positioning if the menu doesn't fit in the window.)
    -var oldPositionFn = goog.positioning.positionAtCoordinate;
    -goog.positioning.positionAtCoordinate = function(absolutePos, movableElement,
    -                                                 movableElementCorner,
    -                                                 opt_margin, opt_overflow) {
    -  return oldPositionFn.call(null, absolutePos, movableElement,
    -      movableElementCorner, opt_margin, goog.positioning.Overflow.IGNORE);
    -};
    -
    -function setUp() {
    -  clonedMenuDom = goog.dom.getElement('demoMenu').cloneNode(true);
    -
    -  menu = new goog.ui.Menu();
    -}
    -
    -function tearDown() {
    -  document.body.style.direction = 'ltr';
    -  menu.dispose();
    -
    -  var element = goog.dom.getElement('demoMenu');
    -  element.parentNode.replaceChild(clonedMenuDom, element);
    -
    -  goog.dom.getElement('sandbox').innerHTML = '';
    -
    -  if (mockClock) {
    -    mockClock.uninstall();
    -    mockClock = null;
    -  }
    -}
    -
    -function assertKeyHandlingIsCorrect(keyToOpenSubMenu, keyToCloseSubMenu) {
    -  menu.setFocusable(true);
    -  menu.decorate(goog.dom.getElement('demoMenu'));
    -
    -  var KeyCodes = goog.events.KeyCodes;
    -  var plainItem = menu.getChildAt(0);
    -  plainItem.setMnemonic(KeyCodes.F);
    -
    -  var subMenuItem1 = menu.getChildAt(1);
    -  subMenuItem1.setMnemonic(KeyCodes.S);
    -  var subMenuItem1Menu = subMenuItem1.getMenu();
    -  menu.setHighlighted(plainItem);
    -
    -  var fireKeySequence = goog.testing.events.fireKeySequence;
    -
    -  assertTrue(
    -      'Expected OpenSubMenu key to not be handled',
    -      fireKeySequence(plainItem.getElement(), keyToOpenSubMenu));
    -  assertFalse(subMenuItem1Menu.isVisible());
    -
    -  assertFalse(
    -      'Expected F key to be handled',
    -      fireKeySequence(plainItem.getElement(), KeyCodes.F));
    -
    -  assertFalse(
    -      'Expected DOWN key to be handled',
    -      fireKeySequence(plainItem.getElement(), KeyCodes.DOWN));
    -  assertEquals(subMenuItem1, menu.getChildAt(1));
    -
    -  assertFalse(
    -      'Expected OpenSubMenu key to be handled',
    -      fireKeySequence(subMenuItem1.getElement(), keyToOpenSubMenu));
    -  assertTrue(subMenuItem1Menu.isVisible());
    -
    -  assertFalse(
    -      'Expected CloseSubMenu key to be handled',
    -      fireKeySequence(subMenuItem1.getElement(), keyToCloseSubMenu));
    -  assertFalse(subMenuItem1Menu.isVisible());
    -
    -  assertFalse(
    -      'Expected UP key to be handled',
    -      fireKeySequence(subMenuItem1.getElement(), KeyCodes.UP));
    -
    -  assertFalse(
    -      'Expected S key to be handled',
    -      fireKeySequence(plainItem.getElement(), KeyCodes.S));
    -  assertTrue(subMenuItem1Menu.isVisible());
    -}
    -
    -function testKeyHandling_ltr() {
    -  assertKeyHandlingIsCorrect(goog.events.KeyCodes.RIGHT,
    -      goog.events.KeyCodes.LEFT);
    -}
    -
    -function testKeyHandling_rtl() {
    -  document.body.style.direction = 'rtl';
    -  assertKeyHandlingIsCorrect(goog.events.KeyCodes.LEFT,
    -      goog.events.KeyCodes.RIGHT);
    -}
    -
    -function testNormalLtrSubMenu() {
    -  menu.decorate(goog.dom.getElement('demoMenu'));
    -  var subMenu = menu.getChildAt(1);
    -  assertArrowDirection(subMenu, false);
    -  assertRenderDirection(subMenu, false);
    -  assertArrowPosition(subMenu, false);
    -}
    -
    -function testNormalRtlSubMenu() {
    -  document.body.style.direction = 'rtl';
    -  menu.decorate(goog.dom.getElement('demoMenu'));
    -  var subMenu = menu.getChildAt(1);
    -  assertArrowDirection(subMenu, true);
    -  assertRenderDirection(subMenu, true);
    -  assertArrowPosition(subMenu, true);
    -}
    -
    -function testLtrSubMenuAlignedToStart() {
    -  menu.decorate(goog.dom.getElement('demoMenu'));
    -  var subMenu = menu.getChildAt(1);
    -  subMenu.setAlignToEnd(false);
    -  assertArrowDirection(subMenu, true);
    -  assertRenderDirection(subMenu, true);
    -  assertArrowPosition(subMenu, false);
    -}
    -
    -function testNullContentElement() {
    -  var subMenu = new goog.ui.SubMenu();
    -  subMenu.setContent('demo');
    -}
    -
    -function testRtlSubMenuAlignedToStart() {
    -  document.body.style.direction = 'rtl';
    -  menu.decorate(goog.dom.getElement('demoMenu'));
    -  var subMenu = menu.getChildAt(1);
    -  subMenu.setAlignToEnd(false);
    -  assertArrowDirection(subMenu, false);
    -  assertRenderDirection(subMenu, false);
    -  assertArrowPosition(subMenu, true);
    -}
    -
    -function testSetContentKeepsArrow_ltr() {
    -  document.body.style.direction = 'ltr';
    -  menu.decorate(goog.dom.getElement('demoMenu'));
    -  var subMenu = menu.getChildAt(1);
    -  subMenu.setAlignToEnd(false);
    -  subMenu.setContent('test');
    -  assertArrowDirection(subMenu, true);
    -  assertRenderDirection(subMenu, true);
    -  assertArrowPosition(subMenu, false);
    -}
    -
    -function testSetContentKeepsArrow_rtl() {
    -  document.body.style.direction = 'rtl';
    -  menu.decorate(goog.dom.getElement('demoMenu'));
    -  var subMenu = menu.getChildAt(1);
    -  subMenu.setAlignToEnd(false);
    -  subMenu.setContent('test');
    -  assertArrowDirection(subMenu, false);
    -  assertRenderDirection(subMenu, false);
    -  assertArrowPosition(subMenu, true);
    -}
    -
    -function testExitDocument() {
    -  menu.decorate(goog.dom.getElement('demoMenu'));
    -  var subMenu = menu.getChildAt(1);
    -  var innerMenu = subMenu.getMenu();
    -
    -  assertTrue('Top-level menu was not in document', menu.isInDocument());
    -  assertTrue('Submenu was not in document', subMenu.isInDocument());
    -  assertTrue('Inner menu was not in document', innerMenu.isInDocument());
    -
    -  menu.exitDocument();
    -
    -  assertFalse('Top-level menu was in document', menu.isInDocument());
    -  assertFalse('Submenu was in document', subMenu.isInDocument());
    -  assertFalse('Inner menu was in document', innerMenu.isInDocument());
    -}
    -
    -function testDisposal() {
    -  menu.decorate(goog.dom.getElement('demoMenu'));
    -  var subMenu = menu.getChildAt(1);
    -  var innerMenu = subMenu.getMenu();
    -  menu.dispose();
    -
    -  assert('Top-level menu was not disposed', menu.getDisposed());
    -  assert('Submenu was not disposed', subMenu.getDisposed());
    -  assert('Inner menu was not disposed', innerMenu.getDisposed());
    -}
    -
    -function testShowAndDismissSubMenu() {
    -  var openEventDispatched = false;
    -  var closeEventDispatched = false;
    -
    -  function handleEvent(e) {
    -    switch (e.type) {
    -      case goog.ui.Component.EventType.OPEN:
    -        openEventDispatched = true;
    -        break;
    -      case goog.ui.Component.EventType.CLOSE:
    -        closeEventDispatched = true;
    -        break;
    -      default:
    -        fail('Invalid event type: ' + e.type);
    -    }
    -  }
    -
    -  menu.decorate(goog.dom.getElement('demoMenu'));
    -  var subMenu = menu.getChildAt(1);
    -  subMenu.setHighlighted(true);
    -
    -  goog.events.listen(subMenu, [
    -    goog.ui.Component.EventType.OPEN,
    -    goog.ui.Component.EventType.CLOSE
    -  ], handleEvent);
    -
    -  assertFalse('Submenu must not have "-open" CSS class',
    -      goog.dom.classlist.contains(subMenu.getElement(), 'goog-submenu-open'));
    -  assertFalse('Popup menu must not be visible',
    -      subMenu.getMenu().isVisible());
    -  assertFalse('No OPEN event must have been dispatched', openEventDispatched);
    -  assertFalse('No CLOSE event must have been dispatched', closeEventDispatched);
    -
    -  subMenu.showSubMenu();
    -  assertTrue('Submenu must have "-open" CSS class',
    -      goog.dom.classlist.contains(subMenu.getElement(), 'goog-submenu-open'));
    -  assertTrue('Popup menu must be visible',
    -      subMenu.getMenu().isVisible());
    -  assertTrue('OPEN event must have been dispatched', openEventDispatched);
    -  assertFalse('No CLOSE event must have been dispatched', closeEventDispatched);
    -
    -  subMenu.dismissSubMenu();
    -  assertFalse('Submenu must not have "-open" CSS class',
    -      goog.dom.classlist.contains(subMenu.getElement(), 'goog-submenu-open'));
    -  assertFalse('Popup menu must not be visible',
    -      subMenu.getMenu().isVisible());
    -  assertTrue('CLOSE event must have been dispatched', closeEventDispatched);
    -
    -  goog.events.unlisten(subMenu, [
    -    goog.ui.Component.EventType.OPEN,
    -    goog.ui.Component.EventType.CLOSE
    -  ], handleEvent);
    -}
    -
    -function testDismissWhenSubMenuNotVisible() {
    -  var openEventDispatched = false;
    -  var closeEventDispatched = false;
    -
    -  function handleEvent(e) {
    -    switch (e.type) {
    -      case goog.ui.Component.EventType.OPEN:
    -        openEventDispatched = true;
    -        break;
    -      case goog.ui.Component.EventType.CLOSE:
    -        closeEventDispatched = true;
    -        break;
    -      default:
    -        fail('Invalid event type: ' + e.type);
    -    }
    -  }
    -
    -  menu.decorate(goog.dom.getElement('demoMenu'));
    -  var subMenu = menu.getChildAt(1);
    -  subMenu.setHighlighted(true);
    -
    -  goog.events.listen(subMenu, [
    -    goog.ui.Component.EventType.OPEN,
    -    goog.ui.Component.EventType.CLOSE
    -  ], handleEvent);
    -
    -  assertFalse('Submenu must not have "-open" CSS class',
    -      goog.dom.classlist.contains(subMenu.getElement(), 'goog-submenu-open'));
    -  assertFalse('Popup menu must not be visible',
    -      subMenu.getMenu().isVisible());
    -  assertFalse('No OPEN event must have been dispatched', openEventDispatched);
    -  assertFalse('No CLOSE event must have been dispatched', closeEventDispatched);
    -
    -  subMenu.showSubMenu();
    -  subMenu.getMenu().setVisible(false);
    -
    -  subMenu.dismissSubMenu();
    -  assertFalse('Submenu must not have "-open" CSS class',
    -      goog.dom.classlist.contains(subMenu.getElement(), 'goog-submenu-open'));
    -  assertFalse(subMenu.menuIsVisible_);
    -  assertFalse('Popup menu must not be visible',
    -      subMenu.getMenu().isVisible());
    -  assertTrue('CLOSE event must have been dispatched', closeEventDispatched);
    -
    -  goog.events.unlisten(subMenu, [
    -    goog.ui.Component.EventType.OPEN,
    -    goog.ui.Component.EventType.CLOSE
    -  ], handleEvent);
    -}
    -
    -function testLazyInstantiateSubMenu() {
    -  menu.decorate(goog.dom.getElement('demoMenu'));
    -  var subMenu = menu.getChildAt(1);
    -  subMenu.setHighlighted(true);
    -
    -  var lazyMenu;
    -
    -  var key = goog.events.listen(subMenu, goog.ui.Component.EventType.OPEN,
    -      function(e) {
    -        lazyMenu = new goog.ui.Menu();
    -        lazyMenu.addItem(new goog.ui.MenuItem('foo'));
    -        lazyMenu.addItem(new goog.ui.MenuItem('bar'));
    -        subMenu.setMenu(lazyMenu, /* opt_internal */ false);
    -      });
    -
    -  subMenu.showSubMenu();
    -  assertNotNull('Popup menu must have been created', lazyMenu);
    -  assertEquals('Popup menu must be a child of the submenu', subMenu,
    -      lazyMenu.getParent());
    -  assertTrue('Popup menu must have been rendered', lazyMenu.isInDocument());
    -  assertTrue('Popup menu must be visible', lazyMenu.isVisible());
    -
    -  menu.dispose();
    -  assertTrue('Submenu must have been disposed of', subMenu.isDisposed());
    -  assertFalse('Popup menu must not have been disposed of',
    -      lazyMenu.isDisposed());
    -
    -  lazyMenu.dispose();
    -
    -  goog.events.unlistenByKey(key);
    -}
    -
    -function testReusableMenu() {
    -  var subMenuOne = new goog.ui.SubMenu('SubMenu One');
    -  var subMenuTwo = new goog.ui.SubMenu('SubMenu Two');
    -  menu.addItem(subMenuOne);
    -  menu.addItem(subMenuTwo);
    -  menu.render(goog.dom.getElement('sandbox'));
    -
    -  // It is possible for the same popup menu to be shared between different
    -  // submenus.
    -  var sharedMenu = new goog.ui.Menu();
    -  sharedMenu.addItem(new goog.ui.MenuItem('Hello'));
    -  sharedMenu.addItem(new goog.ui.MenuItem('World'));
    -
    -  assertNull('Shared menu must not have a parent', sharedMenu.getParent());
    -
    -  subMenuOne.setMenu(sharedMenu);
    -  assertEquals('SubMenuOne must point to the shared menu', sharedMenu,
    -      subMenuOne.getMenu());
    -  assertEquals('SubMenuOne must be the shared menu\'s parent', subMenuOne,
    -      sharedMenu.getParent());
    -
    -  subMenuTwo.setMenu(sharedMenu);
    -  assertEquals('SubMenuTwo must point to the shared menu', sharedMenu,
    -      subMenuTwo.getMenu());
    -  assertEquals('SubMenuTwo must be the shared menu\'s parent', subMenuTwo,
    -      sharedMenu.getParent());
    -  assertEquals('SubMenuOne must still point to the shared menu', sharedMenu,
    -      subMenuOne.getMenu());
    -
    -  menu.setHighlighted(subMenuOne);
    -  subMenuOne.showSubMenu();
    -  assertEquals('SubMenuOne must point to the shared menu', sharedMenu,
    -      subMenuOne.getMenu());
    -  assertEquals('SubMenuOne must be the shared menu\'s parent', subMenuOne,
    -      sharedMenu.getParent());
    -  assertEquals('SubMenuTwo must still point to the shared menu', sharedMenu,
    -      subMenuTwo.getMenu());
    -  assertTrue('Shared menu must be visible', sharedMenu.isVisible());
    -
    -  menu.setHighlighted(subMenuTwo);
    -  subMenuTwo.showSubMenu();
    -  assertEquals('SubMenuTwo must point to the shared menu', sharedMenu,
    -      subMenuTwo.getMenu());
    -  assertEquals('SubMenuTwo must be the shared menu\'s parent', subMenuTwo,
    -      sharedMenu.getParent());
    -  assertEquals('SubMenuOne must still point to the shared menu', sharedMenu,
    -      subMenuOne.getMenu());
    -  assertTrue('Shared menu must be visible', sharedMenu.isVisible());
    -}
    -
    -
    -/**
    - * If you remove a submenu in the interval between when a mouseover event
    - * is fired on it, and showSubMenu() is called, showSubMenu causes a null
    - * value to be dereferenced. This test validates that the fix for this works.
    - * (See bug 1823144).
    - */
    -function testDeleteItemDuringSubmenuDisplayInterval() {
    -  mockClock = new goog.testing.MockClock(true);
    -
    -  var submenu = new goog.ui.SubMenu('submenu');
    -  submenu.addItem(new goog.ui.MenuItem('submenu item 1'));
    -  menu.addItem(submenu);
    -
    -  // Trigger mouseover, and remove item before showSubMenu can be called.
    -  var e = new goog.events.Event();
    -  submenu.handleMouseOver(e);
    -  menu.removeItem(submenu);
    -  mockClock.tick(goog.ui.SubMenu.MENU_DELAY_MS);
    -  // (No JS error should occur.)
    -}
    -
    -function testShowSubMenuAfterRemoval() {
    -  var submenu = new goog.ui.SubMenu('submenu');
    -  menu.addItem(submenu);
    -  menu.removeItem(submenu);
    -  submenu.showSubMenu();
    -  // (No JS error should occur.)
    -}
    -
    -function testSubmenuSelectable() {
    -  var submenu = new goog.ui.SubMenu('submenu');
    -  submenu.addItem(new goog.ui.MenuItem('submenu item 1'));
    -  menu.addItem(submenu);
    -  submenu.setSelectable(true);
    -
    -  var numClicks = 0;
    -  var menuClickedFn = function(e) {
    -    numClicks++;
    -  };
    -
    -  goog.events.listen(submenu, goog.ui.Component.EventType.ACTION,
    -      menuClickedFn);
    -  submenu.performActionInternal(null);
    -  submenu.performActionInternal(null);
    -
    -  assertEquals('The submenu should have fired an event', 2, numClicks);
    -
    -  submenu.setSelectable(false);
    -  submenu.performActionInternal(null);
    -
    -  assertEquals('The submenu should not have fired any further events', 2,
    -      numClicks);
    -}
    -
    -
    -/**
    - * Tests that entering a child menu cancels the dismiss timer for the submenu.
    - */
    -function testEnteringChildCancelsDismiss() {
    -  var submenu = new goog.ui.SubMenu('submenu');
    -  submenu.isInDocument = goog.functions.TRUE;
    -  submenu.addItem(new goog.ui.MenuItem('submenu item 1'));
    -  menu.addItem(submenu);
    -
    -  mockClock = new goog.testing.MockClock(true);
    -  submenu.getMenu().setVisible(true);
    -
    -  // This starts the dismiss timer.
    -  submenu.setHighlighted(false);
    -
    -  // This should cancel the dismiss timer.
    -  submenu.getMenu().dispatchEvent(goog.ui.Component.EventType.ENTER);
    -
    -  // Tick the length of the dismiss timer.
    -  mockClock.tick(goog.ui.SubMenu.MENU_DELAY_MS);
    -
    -  // Check that the menu is now highlighted and still visible.
    -  assertTrue(submenu.getMenu().isVisible());
    -  assertTrue(submenu.isHighlighted());
    -}
    -
    -
    -/**
    - * Asserts that this sub menu renders in the right direction relative to
    - * the parent menu.
    - * @param {goog.ui.SubMenu} subMenu The sub menu.
    - * @param {boolean} left True for left-pointing, false for right-pointing.
    - */
    -function assertRenderDirection(subMenu, left) {
    -  subMenu.getParent().setHighlighted(subMenu);
    -  subMenu.showSubMenu();
    -  var menuItemPosition = goog.style.getPageOffset(subMenu.getElement());
    -  var menuPosition = goog.style.getPageOffset(subMenu.getMenu().getElement());
    -  assert(Math.abs(menuItemPosition.y - menuPosition.y) < 5);
    -  assertEquals(
    -      'Menu at: ' + menuPosition.x +
    -      ', submenu item at: ' + menuItemPosition.x,
    -      left, menuPosition.x < menuItemPosition.x);
    -}
    -
    -
    -/**
    - * Asserts that this sub menu has a properly-oriented arrow.
    - * @param {goog.ui.SubMenu} subMenu The sub menu.
    - * @param {boolean} left True for left-pointing, false for right-pointing.
    - */
    -function assertArrowDirection(subMenu, left) {
    -  assertEquals(
    -      left ? goog.ui.SubMenuRenderer.LEFT_ARROW_ :
    -      goog.ui.SubMenuRenderer.RIGHT_ARROW_,
    -      getArrowElement(subMenu).innerHTML);
    -}
    -
    -
    -/**
    - * Asserts that the arrow position is correct.
    - * @param {goog.ui.SubMenu} subMenu The sub menu.
    - * @param {boolean} leftAlign True for left-aligned, false for right-aligned.
    - */
    -function assertArrowPosition(subMenu, left) {
    -  var arrow = getArrowElement(subMenu);
    -  var expectedLeft =
    -      left ? 0 : arrow.offsetParent.offsetWidth - arrow.offsetWidth;
    -  var actualLeft = arrow.offsetLeft;
    -  assertTrue('Expected left offset: ' + expectedLeft + '\n' +
    -             'Actual left offset: ' + actualLeft + '\n',
    -             Math.abs(expectedLeft - actualLeft) < 5);
    -}
    -
    -
    -/**
    - * Gets the arrow element of a sub menu.
    - * @param {goog.ui.SubMenu} subMenu The sub menu.
    - * @return {Element} The arrow.
    - */
    -function getArrowElement(subMenu) {
    -  return subMenu.getContentElement().lastChild;
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/submenurenderer.js b/src/database/third_party/closure-library/closure/goog/ui/submenurenderer.js
    deleted file mode 100644
    index 3ae99590446..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/submenurenderer.js
    +++ /dev/null
    @@ -1,239 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Renderer for {@link goog.ui.SubMenu}s.
    - *
    - */
    -
    -goog.provide('goog.ui.SubMenuRenderer');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.style');
    -goog.require('goog.ui.Menu');
    -goog.require('goog.ui.MenuItemRenderer');
    -
    -
    -
    -/**
    - * Default renderer for {@link goog.ui.SubMenu}s.  Each item has the following
    - * structure:
    - *    <div class="goog-submenu">
    - *      ...(menuitem content)...
    - *      <div class="goog-menu">
    - *        ... (submenu content) ...
    - *      </div>
    - *    </div>
    - * @constructor
    - * @extends {goog.ui.MenuItemRenderer}
    - * @final
    - */
    -goog.ui.SubMenuRenderer = function() {
    -  goog.ui.MenuItemRenderer.call(this);
    -};
    -goog.inherits(goog.ui.SubMenuRenderer, goog.ui.MenuItemRenderer);
    -goog.addSingletonGetter(goog.ui.SubMenuRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.SubMenuRenderer.CSS_CLASS = goog.getCssName('goog-submenu');
    -
    -
    -/**
    - * The CSS class for submenus that displays the submenu arrow.
    - * @type {string}
    - * @private
    - */
    -goog.ui.SubMenuRenderer.CSS_CLASS_SUBMENU_ =
    -    goog.getCssName('goog-submenu-arrow');
    -
    -
    -/**
    - * Overrides {@link goog.ui.MenuItemRenderer#createDom} by adding
    - * the additional class 'goog-submenu' to the created element,
    - * and passes the element to {@link goog.ui.SubMenuItemRenderer#addArrow_}
    - * to add an child element that can be styled to show an arrow.
    - * @param {goog.ui.Control} control goog.ui.SubMenu to render.
    - * @return {!Element} Root element for the item.
    - * @override
    - */
    -goog.ui.SubMenuRenderer.prototype.createDom = function(control) {
    -  var subMenu = /** @type {goog.ui.SubMenu} */ (control);
    -  var element = goog.ui.SubMenuRenderer.superClass_.createDom.call(this,
    -                                                                   subMenu);
    -  goog.asserts.assert(element);
    -  goog.dom.classlist.add(element, goog.ui.SubMenuRenderer.CSS_CLASS);
    -  this.addArrow_(subMenu, element);
    -  return element;
    -};
    -
    -
    -/**
    - * Overrides {@link goog.ui.MenuItemRenderer#decorate} by adding
    - * the additional class 'goog-submenu' to the decorated element,
    - * and passing the element to {@link goog.ui.SubMenuItemRenderer#addArrow_}
    - * to add a child element that can be styled to show an arrow.
    - * Also searches the element for a child with the class goog-menu. If a
    - * matching child element is found, creates a goog.ui.Menu, uses it to
    - * decorate the child element, and passes that menu to subMenu.setMenu.
    - * @param {goog.ui.Control} control goog.ui.SubMenu to render.
    - * @param {Element} element Element to decorate.
    - * @return {!Element} Root element for the item.
    - * @override
    - */
    -goog.ui.SubMenuRenderer.prototype.decorate = function(control, element) {
    -  var subMenu = /** @type {goog.ui.SubMenu} */ (control);
    -  element = goog.ui.SubMenuRenderer.superClass_.decorate.call(
    -      this, subMenu, element);
    -  goog.asserts.assert(element);
    -  goog.dom.classlist.add(element, goog.ui.SubMenuRenderer.CSS_CLASS);
    -  this.addArrow_(subMenu, element);
    -
    -  // Search for a child menu and decorate it.
    -  var childMenuEls = goog.dom.getElementsByTagNameAndClass(
    -      'div', goog.getCssName('goog-menu'), element);
    -  if (childMenuEls.length) {
    -    var childMenu = new goog.ui.Menu(subMenu.getDomHelper());
    -    var childMenuEl = childMenuEls[0];
    -    // Hide the menu element before attaching it to the document body; see
    -    // bug 1089244.
    -    goog.style.setElementShown(childMenuEl, false);
    -    subMenu.getDomHelper().getDocument().body.appendChild(childMenuEl);
    -    childMenu.decorate(childMenuEl);
    -    subMenu.setMenu(childMenu, true);
    -  }
    -  return element;
    -};
    -
    -
    -/**
    - * Takes a menu item's root element, and sets its content to the given text
    - * caption or DOM structure.  Overrides the superclass immplementation by
    - * making sure that the submenu arrow structure is preserved.
    - * @param {Element} element The item's root element.
    - * @param {goog.ui.ControlContent} content Text caption or DOM structure to be
    - *     set as the item's content.
    - * @override
    - */
    -goog.ui.SubMenuRenderer.prototype.setContent = function(element, content) {
    -  // Save the submenu arrow element, if present.
    -  var contentElement = this.getContentElement(element);
    -  var arrowElement = contentElement && contentElement.lastChild;
    -  goog.ui.SubMenuRenderer.superClass_.setContent.call(this, element, content);
    -  // If the arrowElement was there, is no longer there, and really was an arrow,
    -  // reappend it.
    -  if (arrowElement &&
    -      contentElement.lastChild != arrowElement &&
    -      goog.dom.classlist.contains(/** @type {!Element} */ (arrowElement),
    -          goog.ui.SubMenuRenderer.CSS_CLASS_SUBMENU_)) {
    -    contentElement.appendChild(arrowElement);
    -  }
    -};
    -
    -
    -/**
    - * Overrides {@link goog.ui.MenuItemRenderer#initializeDom} to tweak
    - * the DOM structure for the span.goog-submenu-arrow element
    - * depending on the text direction (LTR or RTL). When the SubMenu is RTL
    - * the arrow will be given the additional class of goog-submenu-arrow-rtl,
    - * and the arrow will be moved up to be the first child in the SubMenu's
    - * element. Otherwise the arrow will have the class goog-submenu-arrow-ltr,
    - * and be kept as the last child of the SubMenu's element.
    - * @param {goog.ui.Control} control goog.ui.SubMenu whose DOM is to be
    - *     initialized as it enters the document.
    - * @override
    - */
    -goog.ui.SubMenuRenderer.prototype.initializeDom = function(control) {
    -  var subMenu = /** @type {goog.ui.SubMenu} */ (control);
    -  goog.ui.SubMenuRenderer.superClass_.initializeDom.call(this, subMenu);
    -  var element = subMenu.getContentElement();
    -  var arrow = subMenu.getDomHelper().getElementsByTagNameAndClass(
    -      'span', goog.ui.SubMenuRenderer.CSS_CLASS_SUBMENU_, element)[0];
    -  goog.ui.SubMenuRenderer.setArrowTextContent_(subMenu, arrow);
    -  if (arrow != element.lastChild) {
    -    element.appendChild(arrow);
    -  }
    -  var subMenuElement = subMenu.getElement();
    -  goog.asserts.assert(subMenuElement,
    -      'The sub menu DOM element cannot be null.');
    -  goog.a11y.aria.setState(subMenuElement,
    -      goog.a11y.aria.State.HASPOPUP,
    -      'true');
    -};
    -
    -
    -/**
    - * Appends a child node with the class goog.getCssName('goog-submenu-arrow') or
    - * 'goog-submenu-arrow-rtl' which can be styled to show an arrow.
    - * @param {goog.ui.SubMenu} subMenu SubMenu to render.
    - * @param {Element} element Element to decorate.
    - * @private
    - */
    -goog.ui.SubMenuRenderer.prototype.addArrow_ = function(subMenu, element) {
    -  var arrow = subMenu.getDomHelper().createDom('span');
    -  arrow.className = goog.ui.SubMenuRenderer.CSS_CLASS_SUBMENU_;
    -  goog.ui.SubMenuRenderer.setArrowTextContent_(subMenu, arrow);
    -  this.getContentElement(element).appendChild(arrow);
    -};
    -
    -
    -/**
    - * The unicode char for a left arrow.
    - * @type {string}
    - * @private
    - */
    -goog.ui.SubMenuRenderer.LEFT_ARROW_ = '\u25C4';
    -
    -
    -/**
    - * The unicode char for a right arrow.
    - * @type {string}
    - * @private
    - */
    -goog.ui.SubMenuRenderer.RIGHT_ARROW_ = '\u25BA';
    -
    -
    -/**
    - * Set the text content of an arrow.
    - * @param {goog.ui.SubMenu} subMenu The sub menu that owns the arrow.
    - * @param {Element} arrow The arrow element.
    - * @private
    - */
    -goog.ui.SubMenuRenderer.setArrowTextContent_ = function(subMenu, arrow) {
    -  // Fix arrow rtl
    -  var leftArrow = goog.ui.SubMenuRenderer.LEFT_ARROW_;
    -  var rightArrow = goog.ui.SubMenuRenderer.RIGHT_ARROW_;
    -
    -  goog.asserts.assert(arrow);
    -
    -  if (subMenu.isRightToLeft()) {
    -    goog.dom.classlist.add(arrow, goog.getCssName('goog-submenu-arrow-rtl'));
    -    // Unicode character - Black left-pointing pointer iff aligned to end.
    -    goog.dom.setTextContent(arrow, subMenu.isAlignedToEnd() ?
    -        leftArrow : rightArrow);
    -  } else {
    -    goog.dom.classlist.remove(arrow, goog.getCssName('goog-submenu-arrow-rtl'));
    -    // Unicode character - Black right-pointing pointer iff aligned to end.
    -    goog.dom.setTextContent(arrow, subMenu.isAlignedToEnd() ?
    -        rightArrow : leftArrow);
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tab.js b/src/database/third_party/closure-library/closure/goog/ui/tab.js
    deleted file mode 100644
    index d589df2702f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tab.js
    +++ /dev/null
    @@ -1,103 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A tab control, designed to be used in {@link goog.ui.TabBar}s.
    - *
    - * @author attila@google.com (Attila Bodis)
    - * @see ../demos/tabbar.html
    - */
    -
    -goog.provide('goog.ui.Tab');
    -
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.Control');
    -goog.require('goog.ui.TabRenderer');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * Tab control, designed to be hosted in a {@link goog.ui.TabBar}.  The tab's
    - * DOM may be different based on the configuration of the containing tab bar,
    - * so tabs should only be rendered or decorated as children of a tab bar.
    - * @param {goog.ui.ControlContent} content Text caption or DOM structure to
    - *     display as the tab's caption (if any).
    - * @param {goog.ui.TabRenderer=} opt_renderer Optional renderer used to render
    - *     or decorate the tab.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @constructor
    - * @extends {goog.ui.Control}
    - */
    -goog.ui.Tab = function(content, opt_renderer, opt_domHelper) {
    -  goog.ui.Control.call(this, content,
    -      opt_renderer || goog.ui.TabRenderer.getInstance(), opt_domHelper);
    -
    -  // Tabs support the SELECTED state.
    -  this.setSupportedState(goog.ui.Component.State.SELECTED, true);
    -
    -  // Tabs must dispatch state transition events for the DISABLED and SELECTED
    -  // states in order for the tab bar to function properly.
    -  this.setDispatchTransitionEvents(
    -      goog.ui.Component.State.DISABLED | goog.ui.Component.State.SELECTED,
    -      true);
    -};
    -goog.inherits(goog.ui.Tab, goog.ui.Control);
    -goog.tagUnsealableClass(goog.ui.Tab);
    -
    -
    -/**
    - * Tooltip text for the tab, displayed on hover (if any).
    - * @type {string|undefined}
    - * @private
    - */
    -goog.ui.Tab.prototype.tooltip_;
    -
    -
    -/**
    - * @return {string|undefined} Tab tooltip text (if any).
    - */
    -goog.ui.Tab.prototype.getTooltip = function() {
    -  return this.tooltip_;
    -};
    -
    -
    -/**
    - * Sets the tab tooltip text.  If the tab has already been rendered, updates
    - * its tooltip.
    - * @param {string} tooltip New tooltip text.
    - */
    -goog.ui.Tab.prototype.setTooltip = function(tooltip) {
    -  this.getRenderer().setTooltip(this.getElement(), tooltip);
    -  this.setTooltipInternal(tooltip);
    -};
    -
    -
    -/**
    - * Sets the tab tooltip text.  Considered protected; to be called only by the
    - * renderer during element decoration.
    - * @param {string} tooltip New tooltip text.
    - * @protected
    - */
    -goog.ui.Tab.prototype.setTooltipInternal = function(tooltip) {
    -  this.tooltip_ = tooltip;
    -};
    -
    -
    -// Register a decorator factory function for goog.ui.Tabs.
    -goog.ui.registry.setDecoratorByClassName(goog.ui.TabRenderer.CSS_CLASS,
    -    function() {
    -      return new goog.ui.Tab(null);
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tab_test.html b/src/database/third_party/closure-library/closure/goog/ui/tab_test.html
    deleted file mode 100644
    index e8c7f00b9a7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tab_test.html
    +++ /dev/null
    @@ -1,27 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -Author: attila@google.com (Attila Bodis)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.Tab
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.TabTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="sandbox">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tab_test.js b/src/database/third_party/closure-library/closure/goog/ui/tab_test.js
    deleted file mode 100644
    index 04fd881d844..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tab_test.js
    +++ /dev/null
    @@ -1,74 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.TabTest');
    -goog.setTestOnly('goog.ui.TabTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.Tab');
    -goog.require('goog.ui.TabRenderer');
    -
    -var sandbox;
    -var tab;
    -
    -function setUp() {
    -  sandbox = goog.dom.getElement('sandbox');
    -  tab = new goog.ui.Tab('Hello');
    -}
    -
    -function tearDown() {
    -  tab.dispose();
    -  goog.dom.removeChildren(sandbox);
    -}
    -
    -function testConstructor() {
    -  assertNotNull('Tab must not be null', tab);
    -  assertEquals('Tab must have expected content', 'Hello', tab.getContent());
    -  assertEquals('Tab\'s renderer must default to TabRenderer',
    -      goog.ui.TabRenderer.getInstance(), tab.getRenderer());
    -  assertTrue('Tab must support the SELECTED state',
    -      tab.isSupportedState(goog.ui.Component.State.SELECTED));
    -  assertTrue('SELECTED must be an auto-state',
    -      tab.isAutoState(goog.ui.Component.State.SELECTED));
    -  assertTrue('Tab must dispatch transition events for the DISABLED state',
    -      tab.isDispatchTransitionEvents(goog.ui.Component.State.DISABLED));
    -  assertTrue('Tab must dispatch transition events for the SELECTED state',
    -      tab.isDispatchTransitionEvents(goog.ui.Component.State.SELECTED));
    -}
    -
    -function testGetSetTooltip() {
    -  assertUndefined('Tooltip must be undefined by default', tab.getTooltip());
    -  tab.setTooltip('Hello, world!');
    -  assertEquals('Tooltip must have expected value', 'Hello, world!',
    -      tab.getTooltip());
    -}
    -
    -function testSetAriaLabel() {
    -  assertNull('Tab must not have aria label by default', tab.getAriaLabel());
    -  tab.setAriaLabel('My tab');
    -  tab.render();
    -  var element = tab.getElementStrict();
    -  assertNotNull('Element must not be null', element);
    -  assertEquals('Tab element must have expected aria-label', 'My tab',
    -      element.getAttribute('aria-label'));
    -  assertEquals('Tab element must have expected aria role', 'tab',
    -      element.getAttribute('role'));
    -  tab.setAriaLabel('My new tab');
    -  assertEquals('Tab element must have updated aria-label', 'My new tab',
    -      element.getAttribute('aria-label'));
    -  assertEquals('Tab element must have expected aria role', 'tab',
    -      element.getAttribute('role'));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tabbar.js b/src/database/third_party/closure-library/closure/goog/ui/tabbar.js
    deleted file mode 100644
    index a6fae436375..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tabbar.js
    +++ /dev/null
    @@ -1,395 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Tab bar UI component.
    - *
    - * @author attila@google.com (Attila Bodis)
    - * @see ../demos/tabbar.html
    - */
    -
    -goog.provide('goog.ui.TabBar');
    -goog.provide('goog.ui.TabBar.Location');
    -
    -goog.require('goog.ui.Component.EventType');
    -goog.require('goog.ui.Container');
    -goog.require('goog.ui.Container.Orientation');
    -// We need to include following dependency because of the magic with
    -// goog.ui.registry.setDecoratorByClassName
    -goog.require('goog.ui.Tab');
    -goog.require('goog.ui.TabBarRenderer');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * Tab bar UI component.  A tab bar contains tabs, rendered above, below,
    - * before, or after tab contents.  Tabs in tab bars dispatch the following
    - * events:
    - * <ul>
    - *   <li>{@link goog.ui.Component.EventType.ACTION} when activated via the
    - *       keyboard or the mouse,
    - *   <li>{@link goog.ui.Component.EventType.SELECT} when selected, and
    - *   <li>{@link goog.ui.Component.EventType.UNSELECT} when deselected.
    - * </ul>
    - * Clients may listen for all of the above events on the tab bar itself, and
    - * refer to the event target to identify the tab that dispatched the event.
    - * When an unselected tab is clicked for the first time, it dispatches both a
    - * {@code SELECT} event and an {@code ACTION} event; subsequent clicks on an
    - * already selected tab only result in {@code ACTION} events.
    - *
    - * @param {goog.ui.TabBar.Location=} opt_location Tab bar location; defaults to
    - *     {@link goog.ui.TabBar.Location.TOP}.
    - * @param {goog.ui.TabBarRenderer=} opt_renderer Renderer used to render or
    - *     decorate the container; defaults to {@link goog.ui.TabBarRenderer}.
    - * @param {goog.dom.DomHelper=} opt_domHelper DOM helper, used for document
    - *     interaction.
    - * @constructor
    - * @extends {goog.ui.Container}
    - */
    -goog.ui.TabBar = function(opt_location, opt_renderer, opt_domHelper) {
    -  this.setLocation(opt_location || goog.ui.TabBar.Location.TOP);
    -
    -  goog.ui.Container.call(this, this.getOrientation(),
    -      opt_renderer || goog.ui.TabBarRenderer.getInstance(),
    -      opt_domHelper);
    -
    -  this.listenToTabEvents_();
    -};
    -goog.inherits(goog.ui.TabBar, goog.ui.Container);
    -goog.tagUnsealableClass(goog.ui.TabBar);
    -
    -
    -/**
    - * Tab bar location relative to tab contents.
    - * @enum {string}
    - */
    -goog.ui.TabBar.Location = {
    -  // Above tab contents.
    -  TOP: 'top',
    -  // Below tab contents.
    -  BOTTOM: 'bottom',
    -  // To the left of tab contents (to the right if the page is right-to-left).
    -  START: 'start',
    -  // To the right of tab contents (to the left if the page is right-to-left).
    -  END: 'end'
    -};
    -
    -
    -/**
    - * Tab bar location; defaults to {@link goog.ui.TabBar.Location.TOP}.
    - * @type {goog.ui.TabBar.Location}
    - * @private
    - */
    -goog.ui.TabBar.prototype.location_;
    -
    -
    -/**
    - * Whether keyboard navigation should change the selected tab, or just move
    - * the highlight.  Defaults to true.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.TabBar.prototype.autoSelectTabs_ = true;
    -
    -
    -/**
    - * The currently selected tab (null if none).
    - * @type {goog.ui.Control?}
    - * @private
    - */
    -goog.ui.TabBar.prototype.selectedTab_ = null;
    -
    -
    -/**
    - * @override
    - */
    -goog.ui.TabBar.prototype.enterDocument = function() {
    -  goog.ui.TabBar.superClass_.enterDocument.call(this);
    -
    -  this.listenToTabEvents_();
    -};
    -
    -
    -/** @override */
    -goog.ui.TabBar.prototype.disposeInternal = function() {
    -  goog.ui.TabBar.superClass_.disposeInternal.call(this);
    -  this.selectedTab_ = null;
    -};
    -
    -
    -/**
    - * Removes the tab from the tab bar.  Overrides the superclass implementation
    - * by deselecting the tab being removed.  Since {@link #removeChildAt} uses
    - * {@link #removeChild} internally, we only need to override this method.
    - * @param {string|goog.ui.Component} tab Tab to remove.
    - * @param {boolean=} opt_unrender Whether to call {@code exitDocument} on the
    - *     removed tab, and detach its DOM from the document (defaults to false).
    - * @return {goog.ui.Control} The removed tab, if any.
    - * @override
    - */
    -goog.ui.TabBar.prototype.removeChild = function(tab, opt_unrender) {
    -  // This actually only accepts goog.ui.Controls. There's a TODO
    -  // on the superclass method to fix this.
    -  this.deselectIfSelected(/** @type {goog.ui.Control} */ (tab));
    -  return goog.ui.TabBar.superClass_.removeChild.call(this, tab, opt_unrender);
    -};
    -
    -
    -/**
    - * @return {goog.ui.TabBar.Location} Tab bar location relative to tab contents.
    - */
    -goog.ui.TabBar.prototype.getLocation = function() {
    -  return this.location_;
    -};
    -
    -
    -/**
    - * Sets the location of the tab bar relative to tab contents.
    - * @param {goog.ui.TabBar.Location} location Tab bar location relative to tab
    - *     contents.
    - * @throws {Error} If the tab bar has already been rendered.
    - */
    -goog.ui.TabBar.prototype.setLocation = function(location) {
    -  // setOrientation() will take care of throwing an error if already rendered.
    -  this.setOrientation(goog.ui.TabBar.getOrientationFromLocation(location));
    -  this.location_ = location;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether keyboard navigation should change the selected tab,
    - *     or just move the highlight.
    - */
    -goog.ui.TabBar.prototype.isAutoSelectTabs = function() {
    -  return this.autoSelectTabs_;
    -};
    -
    -
    -/**
    - * Enables or disables auto-selecting tabs using the keyboard.  If auto-select
    - * is enabled, keyboard navigation switches tabs immediately, otherwise it just
    - * moves the highlight.
    - * @param {boolean} enable Whether keyboard navigation should change the
    - *     selected tab, or just move the highlight.
    - */
    -goog.ui.TabBar.prototype.setAutoSelectTabs = function(enable) {
    -  this.autoSelectTabs_ = enable;
    -};
    -
    -
    -/**
    - * Highlights the tab at the given index in response to a keyboard event.
    - * Overrides the superclass implementation by also selecting the tab if
    - * {@link #isAutoSelectTabs} returns true.
    - * @param {number} index Index of tab to highlight.
    - * @protected
    - * @override
    - */
    -goog.ui.TabBar.prototype.setHighlightedIndexFromKeyEvent = function(index) {
    -  goog.ui.TabBar.superClass_.setHighlightedIndexFromKeyEvent.call(this, index);
    -  if (this.autoSelectTabs_) {
    -    // Immediately select the tab.
    -    this.setSelectedTabIndex(index);
    -  }
    -};
    -
    -
    -/**
    - * @return {goog.ui.Control?} The currently selected tab (null if none).
    - */
    -goog.ui.TabBar.prototype.getSelectedTab = function() {
    -  return this.selectedTab_;
    -};
    -
    -
    -/**
    - * Selects the given tab.
    - * @param {goog.ui.Control?} tab Tab to select (null to select none).
    - */
    -goog.ui.TabBar.prototype.setSelectedTab = function(tab) {
    -  if (tab) {
    -    // Select the tab and have it dispatch a SELECT event, to be handled in
    -    // handleTabSelect() below.
    -    tab.setSelected(true);
    -  } else if (this.getSelectedTab()) {
    -    // De-select the currently selected tab and have it dispatch an UNSELECT
    -    // event, to be handled in handleTabUnselect() below.
    -    this.getSelectedTab().setSelected(false);
    -  }
    -};
    -
    -
    -/**
    - * @return {number} Index of the currently selected tab (-1 if none).
    - */
    -goog.ui.TabBar.prototype.getSelectedTabIndex = function() {
    -  return this.indexOfChild(this.getSelectedTab());
    -};
    -
    -
    -/**
    - * Selects the tab at the given index.
    - * @param {number} index Index of the tab to select (-1 to select none).
    - */
    -goog.ui.TabBar.prototype.setSelectedTabIndex = function(index) {
    -  this.setSelectedTab(/** @type {goog.ui.Tab} */ (this.getChildAt(index)));
    -};
    -
    -
    -/**
    - * If the specified tab is the currently selected tab, deselects it, and
    - * selects the closest selectable tab in the tab bar (first looking before,
    - * then after the deselected tab).  Does nothing if the argument is not the
    - * currently selected tab.  Called internally when a tab is removed, hidden,
    - * or disabled, to ensure that another tab is selected instead.
    - * @param {goog.ui.Control?} tab Tab to deselect (if any).
    - * @protected
    - */
    -goog.ui.TabBar.prototype.deselectIfSelected = function(tab) {
    -  if (tab && tab == this.getSelectedTab()) {
    -    var index = this.indexOfChild(tab);
    -    // First look for the closest selectable tab before this one.
    -    for (var i = index - 1;
    -         tab = /** @type {goog.ui.Tab} */ (this.getChildAt(i));
    -         i--) {
    -      if (this.isSelectableTab(tab)) {
    -        this.setSelectedTab(tab);
    -        return;
    -      }
    -    }
    -    // Next, look for the closest selectable tab after this one.
    -    for (var j = index + 1;
    -         tab = /** @type {goog.ui.Tab} */ (this.getChildAt(j));
    -         j++) {
    -      if (this.isSelectableTab(tab)) {
    -        this.setSelectedTab(tab);
    -        return;
    -      }
    -    }
    -    // If all else fails, just set the selection to null.
    -    this.setSelectedTab(null);
    -  }
    -};
    -
    -
    -/**
    - * Returns true if the tab is selectable, false otherwise.  Only visible and
    - * enabled tabs are selectable.
    - * @param {goog.ui.Control} tab Tab to check.
    - * @return {boolean} Whether the tab is selectable.
    - * @protected
    - */
    -goog.ui.TabBar.prototype.isSelectableTab = function(tab) {
    -  return tab.isVisible() && tab.isEnabled();
    -};
    -
    -
    -/**
    - * Handles {@code SELECT} events dispatched by tabs as they become selected.
    - * @param {goog.events.Event} e Select event to handle.
    - * @protected
    - */
    -goog.ui.TabBar.prototype.handleTabSelect = function(e) {
    -  if (this.selectedTab_ && this.selectedTab_ != e.target) {
    -    // Deselect currently selected tab.
    -    this.selectedTab_.setSelected(false);
    -  }
    -  this.selectedTab_ = /** @type {goog.ui.Tab} */ (e.target);
    -};
    -
    -
    -/**
    - * Handles {@code UNSELECT} events dispatched by tabs as they become deselected.
    - * @param {goog.events.Event} e Unselect event to handle.
    - * @protected
    - */
    -goog.ui.TabBar.prototype.handleTabUnselect = function(e) {
    -  if (e.target == this.selectedTab_) {
    -    this.selectedTab_ = null;
    -  }
    -};
    -
    -
    -/**
    - * Handles {@code DISABLE} events displayed by tabs.
    - * @param {goog.events.Event} e Disable event to handle.
    - * @protected
    - */
    -goog.ui.TabBar.prototype.handleTabDisable = function(e) {
    -  this.deselectIfSelected(/** @type {goog.ui.Tab} */ (e.target));
    -};
    -
    -
    -/**
    - * Handles {@code HIDE} events displayed by tabs.
    - * @param {goog.events.Event} e Hide event to handle.
    - * @protected
    - */
    -goog.ui.TabBar.prototype.handleTabHide = function(e) {
    -  this.deselectIfSelected(/** @type {goog.ui.Tab} */ (e.target));
    -};
    -
    -
    -/**
    - * Handles focus events dispatched by the tab bar's key event target.  If no tab
    - * is currently highlighted, highlights the selected tab or the first tab if no
    - * tab is selected either.
    - * @param {goog.events.Event} e Focus event to handle.
    - * @protected
    - * @override
    - */
    -goog.ui.TabBar.prototype.handleFocus = function(e) {
    -  if (!this.getHighlighted()) {
    -    this.setHighlighted(this.getSelectedTab() ||
    -        /** @type {goog.ui.Tab} */ (this.getChildAt(0)));
    -  }
    -};
    -
    -
    -/**
    - * Subscribes to events dispatched by tabs.
    - * @private
    - */
    -goog.ui.TabBar.prototype.listenToTabEvents_ = function() {
    -  // Listen for SELECT, UNSELECT, DISABLE, and HIDE events dispatched by tabs.
    -  this.getHandler().
    -      listen(this, goog.ui.Component.EventType.SELECT, this.handleTabSelect).
    -      listen(this,
    -             goog.ui.Component.EventType.UNSELECT,
    -             this.handleTabUnselect).
    -      listen(this, goog.ui.Component.EventType.DISABLE, this.handleTabDisable).
    -      listen(this, goog.ui.Component.EventType.HIDE, this.handleTabHide);
    -};
    -
    -
    -/**
    - * Returns the {@link goog.ui.Container.Orientation} that is implied by the
    - * given {@link goog.ui.TabBar.Location}.
    - * @param {goog.ui.TabBar.Location} location Tab bar location.
    - * @return {goog.ui.Container.Orientation} Corresponding orientation.
    - */
    -goog.ui.TabBar.getOrientationFromLocation = function(location) {
    -  return location == goog.ui.TabBar.Location.START ||
    -         location == goog.ui.TabBar.Location.END ?
    -             goog.ui.Container.Orientation.VERTICAL :
    -             goog.ui.Container.Orientation.HORIZONTAL;
    -};
    -
    -
    -// Register a decorator factory function for goog.ui.TabBars.
    -goog.ui.registry.setDecoratorByClassName(goog.ui.TabBarRenderer.CSS_CLASS,
    -    function() {
    -      return new goog.ui.TabBar();
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tabbar_test.html b/src/database/third_party/closure-library/closure/goog/ui/tabbar_test.html
    deleted file mode 100644
    index 9d8fb203bf7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tabbar_test.html
    +++ /dev/null
    @@ -1,27 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -Author: attila@google.com (Attila Bodis)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.TabBar
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.TabBarTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="sandbox">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tabbar_test.js b/src/database/third_party/closure-library/closure/goog/ui/tabbar_test.js
    deleted file mode 100644
    index 8475a51bb30..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tabbar_test.js
    +++ /dev/null
    @@ -1,606 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.TabBarTest');
    -goog.setTestOnly('goog.ui.TabBarTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.Container');
    -goog.require('goog.ui.Tab');
    -goog.require('goog.ui.TabBar');
    -goog.require('goog.ui.TabBarRenderer');
    -
    -var sandbox;
    -var tabBar;
    -
    -// Fake keyboard event object.
    -function FakeKeyEvent(keyCode) {
    -  this.keyCode = keyCode;
    -  this.defaultPrevented = false;
    -  this.propagationStopped = false;
    -}
    -FakeKeyEvent.prototype.preventDefault = function() {
    -  this.defaultPrevented = true;
    -};
    -FakeKeyEvent.prototype.stopPropagation = function() {
    -  this.propagationStopped = true;
    -};
    -
    -function setUp() {
    -  sandbox = goog.dom.getElement('sandbox');
    -  tabBar = new goog.ui.TabBar();
    -}
    -
    -function tearDown() {
    -  tabBar.dispose();
    -  goog.dom.removeChildren(sandbox);
    -}
    -
    -function testConstructor() {
    -  assertNotNull('Tab bar must not be null', tabBar);
    -  assertEquals('Tab bar renderer must default to expected value',
    -      goog.ui.TabBarRenderer.getInstance(), tabBar.getRenderer());
    -  assertEquals('Tab bar location must default to expected value',
    -      goog.ui.TabBar.Location.TOP, tabBar.getLocation());
    -  assertEquals('Tab bar orientation must default to expected value',
    -      goog.ui.Container.Orientation.HORIZONTAL, tabBar.getOrientation());
    -
    -  var fakeRenderer = {};
    -  var fakeDomHelper = {};
    -  var bar = new goog.ui.TabBar(goog.ui.TabBar.Location.START, fakeRenderer,
    -      fakeDomHelper);
    -  assertNotNull('Tab bar must not be null', bar);
    -  assertEquals('Tab bar renderer must have expected value',
    -      fakeRenderer, bar.getRenderer());
    -  assertEquals('Tab bar DOM helper must have expected value',
    -      fakeDomHelper, bar.getDomHelper());
    -  assertEquals('Tab bar location must have expected value',
    -      goog.ui.TabBar.Location.START, bar.getLocation());
    -  assertEquals('Tab bar orientation must have expected value',
    -      goog.ui.Container.Orientation.VERTICAL, bar.getOrientation());
    -  bar.dispose();
    -}
    -
    -function testDispose() {
    -  // Set tabBar.selectedTab_ to something non-null, just to test dispose().
    -  tabBar.selectedTab_ = {};
    -  assertNotNull('Selected tab must be non-null', tabBar.getSelectedTab());
    -  assertFalse('Tab bar must not have been disposed of',
    -      tabBar.isDisposed());
    -  tabBar.dispose();
    -  assertNull('Selected tab must be null', tabBar.getSelectedTab());
    -  assertTrue('Tab bar must have been disposed of', tabBar.isDisposed());
    -}
    -
    -function testAddRemoveChild() {
    -  assertNull('No tab must be selected', tabBar.getSelectedTab());
    -
    -  var first = new goog.ui.Tab('First');
    -  tabBar.addChild(first);
    -  assertEquals('First tab must have been added at the expected index', 0,
    -      tabBar.indexOfChild(first));
    -  first.setSelected(true);
    -  assertEquals('First tab must be selected', 0,
    -      tabBar.getSelectedTabIndex());
    -
    -  var second = new goog.ui.Tab('Second');
    -  tabBar.addChild(second);
    -  assertEquals('Second tab must have been added at the expected index', 1,
    -      tabBar.indexOfChild(second));
    -  assertEquals('First tab must remain selected', 0,
    -      tabBar.getSelectedTabIndex());
    -
    -  var firstRemoved = tabBar.removeChild(first);
    -  assertEquals('removeChild() must return the removed tab', first,
    -      firstRemoved);
    -  assertEquals('First tab must no longer be in the tab bar', -1,
    -      tabBar.indexOfChild(first));
    -  assertEquals('Second tab must be at the expected index', 0,
    -      tabBar.indexOfChild(second));
    -  assertFalse('First tab must no longer be selected', first.isSelected());
    -  assertTrue('Remaining tab must be selected', second.isSelected());
    -
    -  var secondRemoved = tabBar.removeChild(second);
    -  assertEquals('removeChild() must return the removed tab', second,
    -      secondRemoved);
    -  assertFalse('Tab must no longer be selected', second.isSelected());
    -  assertNull('No tab must be selected', tabBar.getSelectedTab());
    -}
    -
    -function testGetSetLocation() {
    -  assertEquals('Location must default to TOP', goog.ui.TabBar.Location.TOP,
    -      tabBar.getLocation());
    -  tabBar.setLocation(goog.ui.TabBar.Location.START);
    -  assertEquals('Location must have expected value',
    -      goog.ui.TabBar.Location.START, tabBar.getLocation());
    -  tabBar.createDom();
    -  assertThrows('Attempting to change the location after the tab bar has ' +
    -      'been rendered must throw error',
    -      function() {
    -        tabBar.setLocation(goog.ui.TabBar.Location.BOTTOM);
    -      });
    -}
    -
    -function testIsSetAutoSelectTabs() {
    -  assertTrue('Tab bar must auto-select tabs by default',
    -      tabBar.isAutoSelectTabs());
    -  tabBar.setAutoSelectTabs(false);
    -  assertFalse('Tab bar must no longer auto-select tabs by default',
    -      tabBar.isAutoSelectTabs());
    -  tabBar.render(sandbox);
    -  assertFalse('Rendering must not change auto-select setting',
    -      tabBar.isAutoSelectTabs());
    -  tabBar.setAutoSelectTabs(true);
    -  assertTrue('Tab bar must once again auto-select tabs',
    -      tabBar.isAutoSelectTabs());
    -}
    -
    -function setHighlightedIndexFromKeyEvent() {
    -  var foo, bar, baz;
    -
    -  // Create a tab bar with some tabs.
    -  tabBar.addChild(foo = new goog.ui.Tab('foo'));
    -  tabBar.addChild(bar = new goog.ui.Tab('bar'));
    -  tabBar.addChild(baz = new goog.ui.Tab('baz'));
    -
    -  // Verify baseline assumptions.
    -  assertNull('No tab must be highlighted', tabBar.getHighlighted());
    -  assertNull('No tab must be selected', tabBar.getSelectedTab());
    -  assertTrue('Tab bar must auto-select tabs on keyboard highlight',
    -      tabBar.isAutoSelectTabs());
    -
    -  // Highlight and selection must move together.
    -  tabBar.setHighlightedIndexFromKeyEvent(0);
    -  assertTrue('Foo must be highlighted', foo.isHighlighted());
    -  assertTrue('Foo must be selected', foo.isSelected());
    -
    -  // Highlight and selection must move together.
    -  tabBar.setHighlightedIndexFromKeyEvent(1);
    -  assertFalse('Foo must no longer be highlighted', foo.isHighlighted());
    -  assertFalse('Foo must no longer be selected', foo.isSelected());
    -  assertTrue('Bar must be highlighted', bar.isHighlighted());
    -  assertTrue('Bar must be selected', bar.isSelected());
    -
    -  // Turn off auto-select-on-keyboard-highlight.
    -  tabBar.setAutoSelectTabs(false);
    -
    -  // Selection must not change; only highlight should move.
    -  tabBar.setHighlightedIndexFromKeyEvent(2);
    -  assertFalse('Bar must no longer be highlighted', bar.isHighlighted());
    -  assertTrue('Bar must remain selected', bar.isSelected());
    -  assertTrue('Baz must be highlighted', baz.isHighlighted());
    -  assertFalse('Baz must not be selected', baz.isSelected());
    -}
    -
    -function testGetSetSelectedTab() {
    -  var foo, bar, baz;
    -
    -  // Create a tab bar with some tabs.
    -  tabBar.addChild(foo = new goog.ui.Tab('foo'));
    -  tabBar.addChild(bar = new goog.ui.Tab('bar'));
    -  tabBar.addChild(baz = new goog.ui.Tab('baz'));
    -
    -  assertNull('No tab must be selected', tabBar.getSelectedTab());
    -
    -  tabBar.setSelectedTab(baz);
    -  assertTrue('Baz must be selected', baz.isSelected());
    -  assertEquals('Baz must be the selected tab', baz,
    -      tabBar.getSelectedTab());
    -
    -  tabBar.setSelectedTab(foo);
    -  assertFalse('Baz must no longer be selected', baz.isSelected());
    -  assertTrue('Foo must be selected', foo.isSelected());
    -  assertEquals('Foo must be the selected tab', foo,
    -      tabBar.getSelectedTab());
    -
    -  tabBar.setSelectedTab(foo);
    -  assertTrue('Foo must remain selected', foo.isSelected());
    -  assertEquals('Foo must remain the selected tab', foo,
    -      tabBar.getSelectedTab());
    -
    -  tabBar.setSelectedTab(null);
    -  assertFalse('Foo must no longer be selected', foo.isSelected());
    -  assertNull('No tab must be selected', tabBar.getSelectedTab());
    -}
    -
    -function testGetSetSelectedTabIndex() {
    -  var foo, bar, baz;
    -
    -  // Create a tab bar with some tabs.
    -  tabBar.addChildAt(foo = new goog.ui.Tab('foo'), 0);
    -  tabBar.addChildAt(bar = new goog.ui.Tab('bar'), 1);
    -  tabBar.addChildAt(baz = new goog.ui.Tab('baz'), 2);
    -
    -  assertEquals('No tab must be selected', -1, tabBar.getSelectedTabIndex());
    -
    -  tabBar.setSelectedTabIndex(2);
    -  assertTrue('Baz must be selected', baz.isSelected());
    -  assertEquals('Baz must be the selected tab', 2,
    -      tabBar.getSelectedTabIndex());
    -
    -  tabBar.setSelectedTabIndex(0);
    -  assertFalse('Baz must no longer be selected', baz.isSelected());
    -  assertTrue('Foo must be selected', foo.isSelected());
    -  assertEquals('Foo must be the selected tab', 0,
    -      tabBar.getSelectedTabIndex());
    -
    -  tabBar.setSelectedTabIndex(0);
    -  assertTrue('Foo must remain selected', foo.isSelected());
    -  assertEquals('Foo must remain the selected tab', 0,
    -      tabBar.getSelectedTabIndex());
    -
    -  tabBar.setSelectedTabIndex(-1);
    -  assertFalse('Foo must no longer be selected', foo.isSelected());
    -  assertEquals('No tab must be selected', -1, tabBar.getSelectedTabIndex());
    -}
    -
    -function testDeselectIfSelected() {
    -  var foo, bar, baz;
    -
    -  // Create a tab bar with some tabs.
    -  tabBar.addChild(foo = new goog.ui.Tab('foo'));
    -  tabBar.addChild(bar = new goog.ui.Tab('bar'));
    -  tabBar.addChild(baz = new goog.ui.Tab('baz'));
    -
    -  // Start with the middle tab selected.
    -  bar.setSelected(true);
    -  assertTrue('Bar must be selected', bar.isSelected());
    -  assertEquals('Bar must be the selected tab', bar,
    -      tabBar.getSelectedTab());
    -
    -  // Should be a no-op.
    -  tabBar.deselectIfSelected(null);
    -  assertTrue('Bar must remain selected', bar.isSelected());
    -  assertEquals('Bar must remain the selected tab', bar,
    -      tabBar.getSelectedTab());
    -
    -  // Should be a no-op.
    -  tabBar.deselectIfSelected(foo);
    -  assertTrue('Bar must remain selected', bar.isSelected());
    -  assertEquals('Bar must remain the selected tab', bar,
    -      tabBar.getSelectedTab());
    -
    -  // Should deselect bar and select the previous tab (foo).
    -  tabBar.deselectIfSelected(bar);
    -  assertFalse('Bar must no longer be selected', bar.isSelected());
    -  assertTrue('Foo must be selected', foo.isSelected());
    -  assertEquals('Foo must be the selected tab', foo,
    -      tabBar.getSelectedTab());
    -
    -  // Should deselect foo and select the next tab (bar).
    -  tabBar.deselectIfSelected(foo);
    -  assertFalse('Foo must no longer be selected', foo.isSelected());
    -  assertTrue('Bar must be selected', bar.isSelected());
    -  assertEquals('Bar must be the selected tab', bar,
    -      tabBar.getSelectedTab());
    -}
    -
    -function testHandleTabSelect() {
    -  var foo, bar, baz;
    -
    -  // Create a tab bar with some tabs.
    -  tabBar.addChild(foo = new goog.ui.Tab('foo'));
    -  tabBar.addChild(bar = new goog.ui.Tab('bar'));
    -  tabBar.addChild(baz = new goog.ui.Tab('baz'));
    -
    -  assertNull('No tab must be selected', tabBar.getSelectedTab());
    -
    -  tabBar.handleTabSelect(new goog.events.Event(
    -      goog.ui.Component.EventType.SELECT, bar));
    -  assertEquals('Bar must be the selected tab', bar,
    -      tabBar.getSelectedTab());
    -
    -  tabBar.handleTabSelect(new goog.events.Event(
    -      goog.ui.Component.EventType.SELECT, bar));
    -  assertEquals('Bar must remain selected tab', bar,
    -      tabBar.getSelectedTab());
    -
    -  tabBar.handleTabSelect(new goog.events.Event(
    -      goog.ui.Component.EventType.SELECT, foo));
    -  assertEquals('Foo must now be the selected tab', foo,
    -      tabBar.getSelectedTab());
    -}
    -
    -function testHandleTabUnselect() {
    -  var foo, bar, baz;
    -
    -  // Create a tab bar with some tabs.
    -  tabBar.addChild(foo = new goog.ui.Tab('foo'));
    -  tabBar.addChild(bar = new goog.ui.Tab('bar'));
    -  tabBar.addChild(baz = new goog.ui.Tab('baz'));
    -
    -  bar.setSelected(true);
    -  assertEquals('Bar must be the selected tab', bar,
    -      tabBar.getSelectedTab());
    -
    -  tabBar.handleTabUnselect(new goog.events.Event(
    -      goog.ui.Component.EventType.UNSELECT, foo));
    -  assertEquals('Bar must remain the selected tab', bar,
    -      tabBar.getSelectedTab());
    -
    -  tabBar.handleTabUnselect(new goog.events.Event(
    -      goog.ui.Component.EventType.SELECT, bar));
    -  assertNull('No tab must be selected', tabBar.getSelectedTab());
    -}
    -
    -function testHandleTabDisable() {
    -  var foo, bar, baz;
    -
    -  // Create a tab bar with some tabs.
    -  tabBar.addChild(foo = new goog.ui.Tab('foo'));
    -  tabBar.addChild(bar = new goog.ui.Tab('bar'));
    -  tabBar.addChild(baz = new goog.ui.Tab('baz'));
    -
    -  // Start with the middle tab selected.
    -  bar.setSelected(true);
    -  assertTrue('Bar must be selected', bar.isSelected());
    -  assertEquals('Bar must be the selected tab', bar,
    -      tabBar.getSelectedTab());
    -
    -  // Should deselect bar and select the previous enabled, visible tab (foo).
    -  bar.setEnabled(false);
    -  assertFalse('Bar must no longer be selected', bar.isSelected());
    -  assertTrue('Foo must be selected', foo.isSelected());
    -  assertEquals('Foo must be the selected tab', foo,
    -      tabBar.getSelectedTab());
    -
    -  // Should deselect foo and select the next enabled, visible tab (baz).
    -  foo.setEnabled(false);
    -  assertFalse('Foo must no longer be selected', foo.isSelected());
    -  assertTrue('Baz must be selected', baz.isSelected());
    -  assertEquals('Baz must be the selected tab', baz,
    -      tabBar.getSelectedTab());
    -
    -  // Should deselect baz.  Since there are no enabled, visible tabs left,
    -  // the tab bar should have no selected tab.
    -  baz.setEnabled(false);
    -  assertFalse('Baz must no longer be selected', baz.isSelected());
    -  assertNull('No tab must be selected', tabBar.getSelectedTab());
    -}
    -
    -function testHandleTabHide() {
    -  var foo, bar, baz;
    -
    -  // Create a tab bar with some tabs.
    -  tabBar.addChild(foo = new goog.ui.Tab('foo'));
    -  tabBar.addChild(bar = new goog.ui.Tab('bar'));
    -  tabBar.addChild(baz = new goog.ui.Tab('baz'));
    -
    -  // Start with the middle tab selected.
    -  bar.setSelected(true);
    -  assertTrue('Bar must be selected', bar.isSelected());
    -  assertEquals('Bar must be the selected tab', bar,
    -      tabBar.getSelectedTab());
    -
    -  // Should deselect bar and select the previous enabled, visible tab (foo).
    -  bar.setVisible(false);
    -  assertFalse('Bar must no longer be selected', bar.isSelected());
    -  assertTrue('Foo must be selected', foo.isSelected());
    -  assertEquals('Foo must be the selected tab', foo,
    -      tabBar.getSelectedTab());
    -
    -  // Should deselect foo and select the next enabled, visible tab (baz).
    -  foo.setVisible(false);
    -  assertFalse('Foo must no longer be selected', foo.isSelected());
    -  assertTrue('Baz must be selected', baz.isSelected());
    -  assertEquals('Baz must be the selected tab', baz,
    -      tabBar.getSelectedTab());
    -
    -  // Should deselect baz.  Since there are no enabled, visible tabs left,
    -  // the tab bar should have no selected tab.
    -  baz.setVisible(false);
    -  assertFalse('Baz must no longer be selected', baz.isSelected());
    -  assertNull('No tab must be selected', tabBar.getSelectedTab());
    -}
    -
    -function testHandleFocus() {
    -  var foo, bar, baz;
    -
    -  // Create a tab bar with some tabs.
    -  tabBar.addChild(foo = new goog.ui.Tab('foo'), true);
    -  tabBar.addChild(bar = new goog.ui.Tab('bar'), true);
    -  tabBar.addChild(baz = new goog.ui.Tab('baz'), true);
    -
    -  // Render the tab bar into the document, so highlight handling works as
    -  // expected.
    -  tabBar.render(sandbox);
    -
    -  // Start with the middle tab selected.
    -  bar.setSelected(true);
    -  assertTrue('Bar must be selected', bar.isSelected());
    -  assertEquals('Bar must be the selected tab', bar,
    -      tabBar.getSelectedTab());
    -
    -  assertNull('No tab must be highlighted', tabBar.getHighlighted());
    -  tabBar.handleFocus(new goog.events.Event(goog.events.EventType.FOCUS,
    -      tabBar.getElement()));
    -  assertTrue('Bar must be highlighted', bar.isHighlighted());
    -  assertEquals('Bar must be the highlighted tab', bar,
    -      tabBar.getHighlighted());
    -}
    -
    -function testHandleFocusWithoutSelectedTab() {
    -  var foo, bar, baz;
    -
    -  // Create a tab bar with some tabs.
    -  tabBar.addChild(foo = new goog.ui.Tab('foo'), true);
    -  tabBar.addChild(bar = new goog.ui.Tab('bar'), true);
    -  tabBar.addChild(baz = new goog.ui.Tab('baz'), true);
    -
    -  // Render the tab bar into the document, so highlight handling works as
    -  // expected.
    -  tabBar.render(sandbox);
    -
    -  // Start with no tab selected.
    -  assertNull('No tab must be selected', tabBar.getSelectedTab());
    -
    -  assertNull('No tab must be highlighted', tabBar.getHighlighted());
    -  tabBar.handleFocus(new goog.events.Event(goog.events.EventType.FOCUS,
    -      tabBar.getElement()));
    -  assertTrue('Foo must be highlighted', foo.isHighlighted());
    -  assertEquals('Foo must be the highlighted tab', foo,
    -      tabBar.getHighlighted());
    -}
    -
    -function testGetOrientationFromLocation() {
    -  assertEquals(goog.ui.Container.Orientation.HORIZONTAL,
    -      goog.ui.TabBar.getOrientationFromLocation(
    -          goog.ui.TabBar.Location.TOP));
    -  assertEquals(goog.ui.Container.Orientation.HORIZONTAL,
    -      goog.ui.TabBar.getOrientationFromLocation(
    -          goog.ui.TabBar.Location.BOTTOM));
    -  assertEquals(goog.ui.Container.Orientation.VERTICAL,
    -      goog.ui.TabBar.getOrientationFromLocation(
    -          goog.ui.TabBar.Location.START));
    -  assertEquals(goog.ui.Container.Orientation.VERTICAL,
    -      goog.ui.TabBar.getOrientationFromLocation(
    -          goog.ui.TabBar.Location.END));
    -}
    -
    -function testKeyboardNavigation() {
    -  var foo, bar, baz;
    -
    -  // Create a tab bar with some tabs.
    -  tabBar.addChild(foo = new goog.ui.Tab('foo'), true);
    -  tabBar.addChild(bar = new goog.ui.Tab('bar'), true);
    -  tabBar.addChild(baz = new goog.ui.Tab('baz'), true);
    -  tabBar.render(sandbox);
    -
    -  // Highlight the selected tab (this happens automatically when the tab
    -  // bar receives keyboard focus).
    -  tabBar.setSelectedTabIndex(0);
    -  tabBar.getSelectedTab().setHighlighted(true);
    -
    -  // Count events dispatched by each tab.
    -  var eventCount = {
    -    'foo': {'select': 0, 'unselect': 0},
    -    'bar': {'select': 0, 'unselect': 0},
    -    'baz': {'select': 0, 'unselect': 0}
    -  };
    -
    -  function countEvent(e) {
    -    var tabId = e.target.getContent();
    -    var type = e.type;
    -    eventCount[tabId][type]++;
    -  }
    -
    -  function getEventCount(tabId, type) {
    -    return eventCount[tabId][type];
    -  }
    -
    -  // Listen for SELECT and UNSELECT events on the tab bar.
    -  goog.events.listen(tabBar, [
    -    goog.ui.Component.EventType.SELECT,
    -    goog.ui.Component.EventType.UNSELECT
    -  ], countEvent);
    -
    -  // Verify baseline assumptions.
    -  assertTrue('Tab bar must auto-select tabs',
    -      tabBar.isAutoSelectTabs());
    -  assertEquals('First tab must be selected', 0,
    -      tabBar.getSelectedTabIndex());
    -
    -  // Simulate a right arrow key event.
    -  var rightEvent = new FakeKeyEvent(goog.events.KeyCodes.RIGHT);
    -  assertTrue('Key event must have beeen handled',
    -      tabBar.handleKeyEvent(rightEvent));
    -  assertTrue('Key event propagation must have been stopped',
    -      rightEvent.propagationStopped);
    -  assertTrue('Default key event must have been prevented',
    -      rightEvent.defaultPrevented);
    -  assertEquals('Foo must have dispatched UNSELECT', 1,
    -      getEventCount('foo', goog.ui.Component.EventType.UNSELECT));
    -  assertEquals('Bar must have dispatched SELECT', 1,
    -      getEventCount('bar', goog.ui.Component.EventType.SELECT));
    -  assertEquals('Bar must have been selected', bar, tabBar.getSelectedTab());
    -
    -  // Simulate a left arrow key event.
    -  var leftEvent = new FakeKeyEvent(goog.events.KeyCodes.LEFT);
    -  assertTrue('Key event must have beeen handled',
    -      tabBar.handleKeyEvent(leftEvent));
    -  assertTrue('Key event propagation must have been stopped',
    -      leftEvent.propagationStopped);
    -  assertTrue('Default key event must have been prevented',
    -      leftEvent.defaultPrevented);
    -  assertEquals('Bar must have dispatched UNSELECT', 1,
    -      getEventCount('bar', goog.ui.Component.EventType.UNSELECT));
    -  assertEquals('Foo must have dispatched SELECT', 1,
    -      getEventCount('foo', goog.ui.Component.EventType.SELECT));
    -  assertEquals('Foo must have been selected', foo, tabBar.getSelectedTab());
    -
    -  // Disable tab auto-selection.
    -  tabBar.setAutoSelectTabs(false);
    -
    -  // Simulate another left arrow key event.
    -  var anotherLeftEvent = new FakeKeyEvent(goog.events.KeyCodes.LEFT);
    -  assertTrue('Key event must have beeen handled',
    -      tabBar.handleKeyEvent(anotherLeftEvent));
    -  assertTrue('Key event propagation must have been stopped',
    -      anotherLeftEvent.propagationStopped);
    -  assertTrue('Default key event must have been prevented',
    -      anotherLeftEvent.defaultPrevented);
    -  assertEquals('Foo must remain selected', foo, tabBar.getSelectedTab());
    -  assertEquals('Foo must not have dispatched another UNSELECT event', 1,
    -      getEventCount('foo', goog.ui.Component.EventType.UNSELECT));
    -  assertEquals('Baz must not have dispatched a SELECT event', 0,
    -      getEventCount('baz', goog.ui.Component.EventType.SELECT));
    -  assertFalse('Baz must not be selected', baz.isSelected());
    -  assertTrue('Baz must be highlighted', baz.isHighlighted());
    -
    -  // Simulate 'g' key event.
    -  var gEvent = new FakeKeyEvent(goog.events.KeyCodes.G);
    -  assertFalse('Key event must not have beeen handled',
    -      tabBar.handleKeyEvent(gEvent));
    -  assertFalse('Key event propagation must not have been stopped',
    -      gEvent.propagationStopped);
    -  assertFalse('Default key event must not have been prevented',
    -      gEvent.defaultPrevented);
    -  assertEquals('Foo must remain selected', foo, tabBar.getSelectedTab());
    -
    -  // Clean up.
    -  goog.events.unlisten(tabBar, [
    -    goog.ui.Component.EventType.SELECT,
    -    goog.ui.Component.EventType.UNSELECT
    -  ], countEvent);
    -}
    -
    -function testExitAndEnterDocument() {
    -  var component = new goog.ui.Component();
    -  component.render(sandbox);
    -
    -  var tab1 = new goog.ui.Tab('tab1');
    -  var tab2 = new goog.ui.Tab('tab2');
    -  var tab3 = new goog.ui.Tab('tab3');
    -  tabBar.addChild(tab1, true);
    -  tabBar.addChild(tab2, true);
    -  tabBar.addChild(tab3, true);
    -
    -  component.addChild(tabBar, true);
    -  tab2.setSelected(true);
    -  assertEquals(tabBar.getSelectedTab(), tab2);
    -
    -  component.removeChild(tabBar, true);
    -  tab1.setSelected(true);
    -  assertEquals(tabBar.getSelectedTab(), tab2);
    -
    -  component.addChild(tabBar, true);
    -  tab3.setSelected(true);
    -  assertEquals(tabBar.getSelectedTab(), tab3);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tabbarrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/tabbarrenderer.js
    deleted file mode 100644
    index 2d93929827b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tabbarrenderer.js
    +++ /dev/null
    @@ -1,165 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Default renderer for {@link goog.ui.TabBar}s.  Based on the
    - * original {@code TabPane} code.
    - *
    - * @author attila@google.com (Attila Bodis)
    - * @author eae@google.com (Emil A. Eklund)
    - */
    -
    -goog.provide('goog.ui.TabBarRenderer');
    -
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.object');
    -goog.require('goog.ui.ContainerRenderer');
    -
    -
    -
    -/**
    - * Default renderer for {@link goog.ui.TabBar}s, based on the {@code TabPane}
    - * code.  The tab bar's DOM structure is determined by its orientation and
    - * location relative to tab contents.  For example, a horizontal tab bar
    - * located above tab contents looks like this:
    - * <pre>
    - *   <div class="goog-tab-bar goog-tab-bar-horizontal goog-tab-bar-top">
    - *     ...(tabs here)...
    - *   </div>
    - * </pre>
    - * @constructor
    - * @extends {goog.ui.ContainerRenderer}
    - */
    -goog.ui.TabBarRenderer = function() {
    -  goog.ui.ContainerRenderer.call(this, goog.a11y.aria.Role.TAB_LIST);
    -};
    -goog.inherits(goog.ui.TabBarRenderer, goog.ui.ContainerRenderer);
    -goog.addSingletonGetter(goog.ui.TabBarRenderer);
    -goog.tagUnsealableClass(goog.ui.TabBarRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.TabBarRenderer.CSS_CLASS = goog.getCssName('goog-tab-bar');
    -
    -
    -/**
    - * Returns the CSS class name to be applied to the root element of all tab bars
    - * rendered or decorated using this renderer.
    - * @return {string} Renderer-specific CSS class name.
    - * @override
    - */
    -goog.ui.TabBarRenderer.prototype.getCssClass = function() {
    -  return goog.ui.TabBarRenderer.CSS_CLASS;
    -};
    -
    -
    -/**
    - * Sets the tab bar's state based on the given CSS class name, encountered
    - * during decoration.  Overrides the superclass implementation by recognizing
    - * class names representing tab bar orientation and location.
    - * @param {goog.ui.Container} tabBar Tab bar to configure.
    - * @param {string} className CSS class name.
    - * @param {string} baseClass Base class name used as the root of state-specific
    - *     class names (typically the renderer's own class name).
    - * @protected
    - * @override
    - */
    -goog.ui.TabBarRenderer.prototype.setStateFromClassName = function(tabBar,
    -    className, baseClass) {
    -  // Create the class-to-location lookup table on first access.
    -  if (!this.locationByClass_) {
    -    this.createLocationByClassMap_();
    -  }
    -
    -  // If the class name corresponds to a location, update the tab bar's location;
    -  // otherwise let the superclass handle it.
    -  var location = this.locationByClass_[className];
    -  if (location) {
    -    tabBar.setLocation(location);
    -  } else {
    -    goog.ui.TabBarRenderer.superClass_.setStateFromClassName.call(this, tabBar,
    -        className, baseClass);
    -  }
    -};
    -
    -
    -/**
    - * Returns all CSS class names applicable to the tab bar, based on its state.
    - * Overrides the superclass implementation by appending the location-specific
    - * class name to the list.
    - * @param {goog.ui.Container} tabBar Tab bar whose CSS classes are to be
    - *     returned.
    - * @return {!Array<string>} Array of CSS class names applicable to the tab bar.
    - * @override
    - */
    -goog.ui.TabBarRenderer.prototype.getClassNames = function(tabBar) {
    -  var classNames = goog.ui.TabBarRenderer.superClass_.getClassNames.call(this,
    -      tabBar);
    -
    -  // Create the location-to-class lookup table on first access.
    -  if (!this.classByLocation_) {
    -    this.createClassByLocationMap_();
    -  }
    -
    -  // Apped the class name corresponding to the tab bar's location to the list.
    -  classNames.push(this.classByLocation_[tabBar.getLocation()]);
    -  return classNames;
    -};
    -
    -
    -/**
    - * Creates the location-to-class lookup table.
    - * @private
    - */
    -goog.ui.TabBarRenderer.prototype.createClassByLocationMap_ = function() {
    -  var baseClass = this.getCssClass();
    -
    -  /**
    -   * Map of locations to location-specific structural class names,
    -   * precomputed and cached on first use to minimize object allocations
    -   * and string concatenation.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.classByLocation_ = goog.object.create(
    -      goog.ui.TabBar.Location.TOP, goog.getCssName(baseClass, 'top'),
    -      goog.ui.TabBar.Location.BOTTOM, goog.getCssName(baseClass, 'bottom'),
    -      goog.ui.TabBar.Location.START, goog.getCssName(baseClass, 'start'),
    -      goog.ui.TabBar.Location.END, goog.getCssName(baseClass, 'end'));
    -};
    -
    -
    -/**
    - * Creates the class-to-location lookup table, used during decoration.
    - * @private
    - */
    -goog.ui.TabBarRenderer.prototype.createLocationByClassMap_ = function() {
    -  // We need the classByLocation_ map so we can transpose it.
    -  if (!this.classByLocation_) {
    -    this.createClassByLocationMap_();
    -  }
    -
    -  /**
    -   * Map of location-specific structural class names to locations, used during
    -   * element decoration.  Precomputed and cached on first use to minimize object
    -   * allocations and string concatenation.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.locationByClass_ = goog.object.transpose(this.classByLocation_);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tabbarrenderer_test.html b/src/database/third_party/closure-library/closure/goog/ui/tabbarrenderer_test.html
    deleted file mode 100644
    index 71d010d5c44..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tabbarrenderer_test.html
    +++ /dev/null
    @@ -1,27 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -Author: attila@google.com (Attila Bodis)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.TabBarRenderer
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.TabBarRendererTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="sandbox">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tabbarrenderer_test.js b/src/database/third_party/closure-library/closure/goog/ui/tabbarrenderer_test.js
    deleted file mode 100644
    index 436b4c1e781..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tabbarrenderer_test.js
    +++ /dev/null
    @@ -1,132 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.TabBarRendererTest');
    -goog.setTestOnly('goog.ui.TabBarRendererTest');
    -
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.ui.rendererasserts');
    -goog.require('goog.ui.Container');
    -goog.require('goog.ui.TabBar');
    -goog.require('goog.ui.TabBarRenderer');
    -
    -var sandbox;
    -var renderer;
    -var tabBar;
    -
    -function setUp() {
    -  sandbox = goog.dom.getElement('sandbox');
    -  renderer = goog.ui.TabBarRenderer.getInstance();
    -  tabBar = new goog.ui.TabBar();
    -}
    -
    -function tearDown() {
    -  tabBar.dispose();
    -  goog.dom.removeChildren(sandbox);
    -}
    -
    -function testConstructor() {
    -  assertNotNull('Renderer must not be null', renderer);
    -}
    -
    -function testGetCssClass() {
    -  assertEquals('getCssClass() must return expected value',
    -      goog.ui.TabBarRenderer.CSS_CLASS, renderer.getCssClass());
    -}
    -
    -function testGetAriaRole() {
    -  assertEquals('getAriaRole() must return expected value',
    -      goog.a11y.aria.Role.TAB_LIST, renderer.getAriaRole());
    -}
    -
    -function testCreateDom() {
    -  var element = renderer.createDom(tabBar);
    -  assertNotNull('Created element must not be null', element);
    -  assertEquals('Created element must be a DIV', 'DIV', element.tagName);
    -  assertSameElements('Created element must have expected class names',
    -      ['goog-tab-bar', 'goog-tab-bar-horizontal', 'goog-tab-bar-top'],
    -      goog.dom.classlist.get(element));
    -}
    -
    -function testDecorate() {
    -  sandbox.innerHTML = '<div id="start" class="goog-tab-bar-start"></div>';
    -  var element = renderer.decorate(tabBar, goog.dom.getElement('start'));
    -  assertNotNull('Decorated element must not be null', element);
    -  assertEquals('Decorated element must be as expected',
    -      goog.dom.getElement('start'), element);
    -  // Due to a bug in ContainerRenderer, the "-vertical" class isn't applied.
    -  // TODO(attila): Fix this!
    -  assertSameElements('Decorated element must have expected class names',
    -      ['goog-tab-bar', 'goog-tab-bar-start'],
    -      goog.dom.classlist.get(element));
    -}
    -
    -function testSetStateFromClassName() {
    -  renderer.setStateFromClassName(tabBar, 'goog-tab-bar-bottom',
    -      renderer.getCssClass());
    -  assertEquals('Location must be BOTTOM', goog.ui.TabBar.Location.BOTTOM,
    -      tabBar.getLocation());
    -  assertEquals('Orientation must be HORIZONTAL',
    -      goog.ui.Container.Orientation.HORIZONTAL, tabBar.getOrientation());
    -
    -  renderer.setStateFromClassName(tabBar, 'goog-tab-bar-end',
    -      renderer.getCssClass());
    -  assertEquals('Location must be END', goog.ui.TabBar.Location.END,
    -      tabBar.getLocation());
    -  assertEquals('Orientation must be VERTICAL',
    -      goog.ui.Container.Orientation.VERTICAL, tabBar.getOrientation());
    -
    -  renderer.setStateFromClassName(tabBar, 'goog-tab-bar-top',
    -      renderer.getCssClass());
    -  assertEquals('Location must be TOP', goog.ui.TabBar.Location.TOP,
    -      tabBar.getLocation());
    -  assertEquals('Orientation must be HORIZONTAL',
    -      goog.ui.Container.Orientation.HORIZONTAL, tabBar.getOrientation());
    -
    -  renderer.setStateFromClassName(tabBar, 'goog-tab-bar-start',
    -      renderer.getCssClass());
    -  assertEquals('Location must be START', goog.ui.TabBar.Location.START,
    -      tabBar.getLocation());
    -  assertEquals('Orientation must be VERTICAL',
    -      goog.ui.Container.Orientation.VERTICAL, tabBar.getOrientation());
    -}
    -
    -function testGetClassNames() {
    -  assertSameElements('Class names for TOP location must be as expected',
    -      ['goog-tab-bar', 'goog-tab-bar-horizontal', 'goog-tab-bar-top'],
    -      renderer.getClassNames(tabBar));
    -
    -  tabBar.setLocation(goog.ui.TabBar.Location.START);
    -  assertSameElements('Class names for START location must be as expected',
    -      ['goog-tab-bar', 'goog-tab-bar-vertical', 'goog-tab-bar-start'],
    -      renderer.getClassNames(tabBar));
    -
    -  tabBar.setLocation(goog.ui.TabBar.Location.BOTTOM);
    -  assertSameElements('Class names for BOTTOM location must be as expected',
    -      ['goog-tab-bar', 'goog-tab-bar-horizontal', 'goog-tab-bar-bottom'],
    -      renderer.getClassNames(tabBar));
    -
    -  tabBar.setLocation(goog.ui.TabBar.Location.END);
    -  assertSameElements('Class names for END location must be as expected',
    -      ['goog-tab-bar', 'goog-tab-bar-vertical', 'goog-tab-bar-end'],
    -      renderer.getClassNames(tabBar));
    -}
    -
    -function testDoesntCallGetCssClassInConstructor() {
    -  goog.testing.ui.rendererasserts.
    -      assertNoGetCssClassCallsInConstructor(goog.ui.TabBarRenderer);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tablesorter.js b/src/database/third_party/closure-library/closure/goog/ui/tablesorter.js
    deleted file mode 100644
    index 03750500239..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tablesorter.js
    +++ /dev/null
    @@ -1,324 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A table sorting decorator.
    - *
    - * @author robbyw@google.com (Robby Walker)
    - * @see ../demos/tablesorter.html
    - */
    -
    -goog.provide('goog.ui.TableSorter');
    -goog.provide('goog.ui.TableSorter.EventType');
    -
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.dom.TagName');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events.EventType');
    -goog.require('goog.functions');
    -goog.require('goog.ui.Component');
    -
    -
    -
    -/**
    - * A table sorter allows for sorting of a table by column.  This component can
    - * be used to decorate an already existing TABLE element with sorting
    - * features.
    - *
    - * The TABLE should use a THEAD containing TH elements for the table column
    - * headers.
    - *
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @constructor
    - * @extends {goog.ui.Component}
    - */
    -goog.ui.TableSorter = function(opt_domHelper) {
    -  goog.ui.Component.call(this, opt_domHelper);
    -
    -  /**
    -   * The current sort header of the table, or null if none.
    -   * @type {HTMLTableCellElement}
    -   * @private
    -   */
    -  this.header_ = null;
    -
    -  /**
    -   * Whether the last sort was in reverse.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.reversed_ = false;
    -
    -  /**
    -   * The default sorting function.
    -   * @type {function(*, *) : number}
    -   * @private
    -   */
    -  this.defaultSortFunction_ = goog.ui.TableSorter.numericSort;
    -
    -  /**
    -   * Array of custom sorting functions per colun.
    -   * @type {Array<function(*, *) : number>}
    -   * @private
    -   */
    -  this.sortFunctions_ = [];
    -};
    -goog.inherits(goog.ui.TableSorter, goog.ui.Component);
    -goog.tagUnsealableClass(goog.ui.TableSorter);
    -
    -
    -/**
    - * Row number (in <thead>) to use for sorting.
    - * @type {number}
    - * @private
    - */
    -goog.ui.TableSorter.prototype.sortableHeaderRowIndex_ = 0;
    -
    -
    -/**
    - * Sets the row index (in <thead>) to be used for sorting.
    - * By default, the first row (index 0) is used.
    - * Must be called before decorate() is called.
    - * @param {number} index The row index.
    - */
    -goog.ui.TableSorter.prototype.setSortableHeaderRowIndex = function(index) {
    -  if (this.isInDocument()) {
    -    throw Error(goog.ui.Component.Error.ALREADY_RENDERED);
    -  }
    -  this.sortableHeaderRowIndex_ = index;
    -};
    -
    -
    -/**
    - * Table sorter events.
    - * @enum {string}
    - */
    -goog.ui.TableSorter.EventType = {
    -  BEFORESORT: 'beforesort',
    -  SORT: 'sort'
    -};
    -
    -
    -/** @override */
    -goog.ui.TableSorter.prototype.canDecorate = function(element) {
    -  return element.tagName == goog.dom.TagName.TABLE;
    -};
    -
    -
    -/** @override */
    -goog.ui.TableSorter.prototype.enterDocument = function() {
    -  goog.ui.TableSorter.superClass_.enterDocument.call(this);
    -
    -  var table = this.getElement();
    -  var headerRow = table.tHead.rows[this.sortableHeaderRowIndex_];
    -
    -  this.getHandler().listen(headerRow, goog.events.EventType.CLICK, this.sort_);
    -};
    -
    -
    -/**
    - * @return {number} The current sort column of the table, or -1 if none.
    - */
    -goog.ui.TableSorter.prototype.getSortColumn = function() {
    -  return this.header_ ? this.header_.cellIndex : -1;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the last sort was in reverse.
    - */
    -goog.ui.TableSorter.prototype.isSortReversed = function() {
    -  return this.reversed_;
    -};
    -
    -
    -/**
    - * @return {function(*, *) : number} The default sort function to be used by
    - *     all columns.
    - */
    -goog.ui.TableSorter.prototype.getDefaultSortFunction = function() {
    -  return this.defaultSortFunction_;
    -};
    -
    -
    -/**
    - * Sets the default sort function to be used by all columns.  If not set
    - * explicitly, this defaults to numeric sorting.
    - * @param {function(*, *) : number} sortFunction The new default sort function.
    - */
    -goog.ui.TableSorter.prototype.setDefaultSortFunction = function(sortFunction) {
    -  this.defaultSortFunction_ = sortFunction;
    -};
    -
    -
    -/**
    - * Gets the sort function to be used by the given column.  Returns the default
    - * sort function if no sort function is explicitly set for this column.
    - * @param {number} column The column index.
    - * @return {function(*, *) : number} The sort function used by the column.
    - */
    -goog.ui.TableSorter.prototype.getSortFunction = function(column) {
    -  return this.sortFunctions_[column] || this.defaultSortFunction_;
    -};
    -
    -
    -/**
    - * Set the sort function for the given column, overriding the default sort
    - * function.
    - * @param {number} column The column index.
    - * @param {function(*, *) : number} sortFunction The new sort function.
    - */
    -goog.ui.TableSorter.prototype.setSortFunction = function(column, sortFunction) {
    -  this.sortFunctions_[column] = sortFunction;
    -};
    -
    -
    -/**
    - * Sort the table contents by the values in the given column.
    - * @param {goog.events.BrowserEvent} e The click event.
    - * @private
    - */
    -goog.ui.TableSorter.prototype.sort_ = function(e) {
    -  // Determine what column was clicked.
    -  // TODO(robbyw): If this table cell contains another table, this could break.
    -  var target = /** @type {Node} */ (e.target);
    -  var th = goog.dom.getAncestorByTagNameAndClass(target,
    -      goog.dom.TagName.TH);
    -
    -  // If the user clicks on the same column, sort it in reverse of what it is
    -  // now.  Otherwise, sort forward.
    -  var reverse = th == this.header_ ? !this.reversed_ : false;
    -
    -  // Perform the sort.
    -  if (this.dispatchEvent(goog.ui.TableSorter.EventType.BEFORESORT)) {
    -    if (this.sort(th.cellIndex, reverse)) {
    -      this.dispatchEvent(goog.ui.TableSorter.EventType.SORT);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Sort the table contents by the values in the given column.
    - * @param {number} column The column to sort by.
    - * @param {boolean=} opt_reverse Whether to sort in reverse.
    - * @return {boolean} Whether the sort was executed.
    - */
    -goog.ui.TableSorter.prototype.sort = function(column, opt_reverse) {
    -  var sortFunction = this.getSortFunction(column);
    -  if (sortFunction === goog.ui.TableSorter.noSort) {
    -    return false;
    -  }
    -
    -  // Remove old header classes.
    -  if (this.header_) {
    -    goog.dom.classlist.remove(this.header_, this.reversed_ ?
    -        goog.getCssName('goog-tablesorter-sorted-reverse') :
    -        goog.getCssName('goog-tablesorter-sorted'));
    -  }
    -
    -  // If the user clicks on the same column, sort it in reverse of what it is
    -  // now.  Otherwise, sort forward.
    -  this.reversed_ = !!opt_reverse;
    -  var multiplier = this.reversed_ ? -1 : 1;
    -  var cmpFn = function(a, b) {
    -    return multiplier * sortFunction(a[0], b[0]) || a[1] - b[1];
    -  };
    -
    -  // Sort all tBodies
    -  var table = this.getElement();
    -  goog.array.forEach(table.tBodies, function(tBody) {
    -    // Collect all of the rows into an array.
    -    var values = goog.array.map(tBody.rows, function(row, rowIndex) {
    -      return [goog.dom.getTextContent(row.cells[column]), rowIndex, row];
    -    });
    -
    -    goog.array.sort(values, cmpFn);
    -
    -    // Remove the tBody temporarily since this speeds up the sort on some
    -    // browsers.
    -    var nextSibling = tBody.nextSibling;
    -    table.removeChild(tBody);
    -
    -    // Sort the rows, using the resulting array.
    -    goog.array.forEach(values, function(row) {
    -      tBody.appendChild(row[2]);
    -    });
    -
    -    // Reinstate the tBody.
    -    table.insertBefore(tBody, nextSibling);
    -  });
    -
    -  // Mark this as the last sorted column.
    -  this.header_ = table.tHead.rows[this.sortableHeaderRowIndex_].cells[column];
    -
    -  // Update the header class.
    -  goog.dom.classlist.add(this.header_, this.reversed_ ?
    -      goog.getCssName('goog-tablesorter-sorted-reverse') :
    -      goog.getCssName('goog-tablesorter-sorted'));
    -
    -  return true;
    -};
    -
    -
    -/**
    - * Disables sorting on the specified column
    - * @param {*} a First sort value.
    - * @param {*} b Second sort value.
    - * @return {number} Negative if a < b, 0 if a = b, and positive if a > b.
    - */
    -goog.ui.TableSorter.noSort = goog.functions.error('no sort');
    -
    -
    -/**
    - * A numeric sort function.  NaN values (or values that do not parse as float
    - * numbers) compare equal to each other and greater to any other number.
    - * @param {*} a First sort value.
    - * @param {*} b Second sort value.
    - * @return {number} Negative if a < b, 0 if a = b, and positive if a > b.
    - */
    -goog.ui.TableSorter.numericSort = function(a, b) {
    -  a = parseFloat(a);
    -  b = parseFloat(b);
    -  // foo == foo is false if and only if foo is NaN.
    -  if (a == a) {
    -    return b == b ? a - b : -1;
    -  } else {
    -    return b == b ? 1 : 0;
    -  }
    -};
    -
    -
    -/**
    - * Alphabetic sort function.
    - * @param {*} a First sort value.
    - * @param {*} b Second sort value.
    - * @return {number} Negative if a < b, 0 if a = b, and positive if a > b.
    - */
    -goog.ui.TableSorter.alphaSort = goog.array.defaultCompare;
    -
    -
    -/**
    - * Returns a function that is the given sort function in reverse.
    - * @param {function(*, *) : number} sortFunction The original sort function.
    - * @return {function(*, *) : number} A new sort function that reverses the
    - *     given sort function.
    - */
    -goog.ui.TableSorter.createReverseSort = function(sortFunction) {
    -  return function(a, b) {
    -    return -1 * sortFunction(a, b);
    -  };
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tablesorter_test.html b/src/database/third_party/closure-library/closure/goog/ui/tablesorter_test.html
    deleted file mode 100644
    index 14e9fd00301..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tablesorter_test.html
    +++ /dev/null
    @@ -1,80 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!-- Author:  robbyw@google.com (Robby Walker) -->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.TableSorter
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.TableSorterTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="content">
    -    <table id="sortable">
    -      <thead>
    -        <tr><th>alpha</th><th>number</th><th>not sortable</th></tr>
    -        <tr><th id="not-sortable" colspan="3">cannot sort</th></tr>
    -      </thead>
    -      <tbody>
    -        <tr><td>C</td><td>10</td><td></td></tr>
    -        <tr><td>A</td><td>10</td><td></td></tr>
    -        <tr><td>C</td><td>17</td><td></td></tr>
    -        <tr><td>B</td><td>0</td><td></td></tr>
    -        <tr><td>C</td><td>3</td><td></td></tr>
    -      </tbody>
    -    </table>
    -    <table id="sortable-2">
    -      <thead>
    -        <tr><th>not sortable 1</th><th colspan="2">not sortable 2</th></tr>
    -        <tr>
    -          <th id="sorttable-2-col-1">Col 1</th>
    -          <th id="sorttable-2-col-2">Col 2</th>
    -          <th id="sorttable-2-col-3">Col 3</th>
    -        </tr>
    -      </thead>
    -      <tbody>
    -        <tr><td>4</td><td>5</td><td>6</td></tr>
    -        <tr><td>1</td><td>2</td><td>3</td></tr>
    -        <tr><td>3</td><td>1</td><td>9</td></tr>
    -      </tbody>
    -    </table>
    -    <table id="sortable-3">
    -      <thead>
    -        <tr><th id="sortable-3-col">Sortable</th></tr>
    -      </thead>
    -      <tbody>
    -        <tr><td>B</td></tr>
    -        <tr><td>C</td></tr>
    -        <tr><td>A</td></tr>
    -      </tbody>
    -      <tbody>
    -        <tr><td>B</td></tr>
    -        <tr><td>A</td></tr>
    -        <tr><td>C</td></tr>
    -      </tbody>
    -    </table>
    -    <table id="sortable-4">
    -      <thead>
    -        <tr><th id="sortable-4-col">Sortable</th></tr>
    -      </thead>
    -      <tbody>
    -        <tr><td>11</td></tr>
    -        <tr><td>Bar</td></tr>
    -        <tr><td>3</td></tr>
    -        <tr><td>Foo</td></tr>
    -        <tr><td>2</td></tr>
    -      </tbody>
    -    </table>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tablesorter_test.js b/src/database/third_party/closure-library/closure/goog/ui/tablesorter_test.js
    deleted file mode 100644
    index a2cb1b84a66..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tablesorter_test.js
    +++ /dev/null
    @@ -1,229 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.TableSorterTest');
    -goog.setTestOnly('goog.ui.TableSorterTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.TableSorter');
    -
    -var oldHtml;
    -var alphaHeader, numberHeader, notSortableHeader, table, tableSorter;
    -
    -function setUpPage() {
    -  oldHtml = goog.dom.getElement('content').innerHTML;
    -}
    -
    -function setUp() {
    -  goog.dom.getElement('content').innerHTML = oldHtml;
    -  table = goog.dom.getElement('sortable');
    -  alphaHeader = table.getElementsByTagName('TH')[0];
    -  numberHeader = table.getElementsByTagName('TH')[1];
    -  notSortableHeader = table.getElementsByTagName('TH')[2];
    -
    -  tableSorter = new goog.ui.TableSorter();
    -  tableSorter.setSortFunction(0, goog.ui.TableSorter.alphaSort);
    -  tableSorter.setSortFunction(2, goog.ui.TableSorter.noSort);
    -  tableSorter.decorate(table);
    -}
    -
    -function tearDown() {
    -  tableSorter.dispose();
    -  table = null;
    -}
    -
    -function testConstructor() {
    -  assertNotNull('Should have successful construction', tableSorter);
    -  assertNotNull('Should be in document', tableSorter);
    -}
    -
    -function testForwardAlpha() {
    -  goog.testing.events.fireClickEvent(alphaHeader);
    -  assertOrder(['A', '10', 'B', '0', 'C', '10', 'C', '17', 'C', '3']);
    -  assertTrue(goog.dom.classlist.contains(alphaHeader,
    -      'goog-tablesorter-sorted'));
    -  assertEquals(0, tableSorter.getSortColumn());
    -  assertFalse(tableSorter.isSortReversed());
    -}
    -
    -function testBackwardAlpha() {
    -  goog.testing.events.fireClickEvent(alphaHeader);
    -  goog.testing.events.fireClickEvent(alphaHeader);
    -  assertOrder(['C', '10', 'C', '17', 'C', '3', 'B', '0', 'A', '10']);
    -  assertFalse(goog.dom.classlist.contains(alphaHeader,
    -      'goog-tablesorter-sorted'));
    -  assertTrue(goog.dom.classlist.contains(alphaHeader,
    -      'goog-tablesorter-sorted-reverse'));
    -  assertEquals(0, tableSorter.getSortColumn());
    -  assertTrue(tableSorter.isSortReversed());
    -}
    -
    -function testForwardNumeric() {
    -  goog.testing.events.fireClickEvent(numberHeader);
    -  assertOrder(['B', '0', 'C', '3', 'C', '10', 'A', '10', 'C', '17']);
    -  assertTrue(goog.dom.classlist.contains(numberHeader,
    -      'goog-tablesorter-sorted'));
    -  assertEquals(1, tableSorter.getSortColumn());
    -  assertFalse(tableSorter.isSortReversed());
    -}
    -
    -function testBackwardNumeric() {
    -  goog.testing.events.fireClickEvent(numberHeader);
    -  goog.testing.events.fireClickEvent(numberHeader);
    -  assertOrder(['C', '17', 'C', '10', 'A', '10', 'C', '3', 'B', '0']);
    -  assertTrue(goog.dom.classlist.contains(numberHeader,
    -      'goog-tablesorter-sorted-reverse'));
    -  assertEquals(1, tableSorter.getSortColumn());
    -  assertTrue(tableSorter.isSortReversed());
    -}
    -
    -function testAlphaThenNumeric() {
    -  testForwardAlpha();
    -  goog.testing.events.fireClickEvent(numberHeader);
    -  assertOrder(['B', '0', 'C', '3', 'A', '10', 'C', '10', 'C', '17']);
    -  assertFalse(goog.dom.classlist.contains(alphaHeader,
    -      'goog-tablesorter-sorted'));
    -  assertEquals(1, tableSorter.getSortColumn());
    -  assertFalse(tableSorter.isSortReversed());
    -}
    -
    -function testNotSortableUnchanged() {
    -  goog.testing.events.fireClickEvent(notSortableHeader);
    -  assertEquals(0, goog.dom.classlist.get(notSortableHeader).length);
    -  assertEquals(-1, tableSorter.getSortColumn());
    -}
    -
    -function testSortWithNonDefaultSortableHeaderRowIndex() {
    -  // Check that clicking on non-sortable header doesn't trigger any sorting.
    -  assertOrder(['C', '10', 'A', '10', 'C', '17', 'B', '0', 'C', '3']);
    -  goog.testing.events.fireClickEvent(goog.dom.getElement('not-sortable'));
    -  assertOrder(['C', '10', 'A', '10', 'C', '17', 'B', '0', 'C', '3']);
    -}
    -
    -function testsetSortableHeaderRowIndexAfterDecorateThrows() {
    -  var func = function() { tableSorter.setSortableHeaderRowIndex(0); };
    -  var msg = assertThrows('failFunc should throw.', func)['message'];
    -  assertEquals('Component already rendered', msg);
    -}
    -
    -function testSortOnSecondHeaderRow() {
    -  // Test a table with multiple table headers.
    -  // Using setSortableHeaderRowIndex one can specify table header columns to use
    -  // in sorting.
    -  var tableSorter2 = new goog.ui.TableSorter();
    -  tableSorter2.setSortableHeaderRowIndex(1);
    -  tableSorter2.decorate(goog.dom.getElement('sortable-2'));
    -
    -  // Initial order.
    -  assertOrder(['4', '5', '6', '1', '2', '3', '3', '1', '9'],
    -              goog.dom.getElement('sortable-2'));
    -
    -  // Sort on first column.
    -  goog.testing.events.fireClickEvent(
    -      goog.dom.getElement('sorttable-2-col-1'));
    -  assertOrder(['1', '2', '3', '3', '1', '9', '4', '5', '6'],
    -              goog.dom.getElement('sortable-2'));
    -
    -  // Sort on second column.
    -  goog.testing.events.fireClickEvent(
    -      goog.dom.getElement('sorttable-2-col-2'));
    -  assertOrder(['3', '1', '9', '1', '2', '3', '4', '5', '6'],
    -              goog.dom.getElement('sortable-2'));
    -
    -  // Sort on third column.
    -  goog.testing.events.fireClickEvent(
    -      goog.dom.getElement('sorttable-2-col-3'));
    -  assertOrder(['1', '2', '3', '4', '5', '6', '3', '1', '9'],
    -              goog.dom.getElement('sortable-2'));
    -
    -  // Reverse sort on third column.
    -  goog.testing.events.fireClickEvent(
    -      goog.dom.getElement('sorttable-2-col-3'));
    -  assertOrder(['3', '1', '9', '4', '5', '6', '1', '2', '3'],
    -              goog.dom.getElement('sortable-2'));
    -
    -  tableSorter2.dispose();
    -}
    -
    -function testSortAfterSwapping() {
    -  // First click
    -  goog.testing.events.fireClickEvent(alphaHeader);
    -  assertOrder(['A', '10', 'B', '0', 'C', '10', 'C', '17', 'C', '3']);
    -  assertEquals(0, tableSorter.getSortColumn());
    -
    -  // Move first column to the end
    -  for (var i = 0, r; (r = table.rows[i]); i++) {
    -    var cell = r.cells[0];
    -    cell.parentNode.appendChild(cell);
    -  }
    -  // Make sure the above worked as expected
    -  assertOrder(['10', 'A', '0', 'B', '10', 'C', '17', 'C', '3', 'C']);
    -
    -  // Our column is now the second one
    -  assertEquals(2, tableSorter.getSortColumn());
    -
    -  // Second click, should reverse
    -  tableSorter.setSortFunction(2, goog.ui.TableSorter.alphaSort);
    -  goog.testing.events.fireClickEvent(alphaHeader);
    -  assertOrder(['10', 'C', '17', 'C', '3', 'C', '0', 'B', '10', 'A']);
    -}
    -
    -function testTwoBodies() {
    -  var table3 = goog.dom.getElement('sortable-3');
    -  var header = goog.dom.getElement('sortable-3-col');
    -  var sorter3 = new goog.ui.TableSorter();
    -  sorter3.setSortFunction(0, goog.ui.TableSorter.alphaSort);
    -  try {
    -    sorter3.decorate(table3);
    -    goog.testing.events.fireClickEvent(header);
    -    assertOrder(['A', 'B', 'C', 'A', 'B', 'C'], table3);
    -    goog.testing.events.fireClickEvent(header);
    -    assertOrder(['C', 'B', 'A', 'C', 'B', 'A'], table3);
    -  } finally {
    -    sorter3.dispose();
    -  }
    -}
    -
    -function testNaNs() {
    -  var table = goog.dom.getElement('sortable-4');
    -  var header = goog.dom.getElement('sortable-4-col');
    -  var sorter = new goog.ui.TableSorter();
    -  try {
    -    // All non-numbers compare equal, i.e. Bar == Foo, so order of those
    -    // elements should not change (since we are using stable sort).
    -    sorter.decorate(table);
    -    goog.testing.events.fireClickEvent(header);
    -    assertOrder(['2', '3', '11', 'Bar', 'Foo'], table);
    -    goog.testing.events.fireClickEvent(header);
    -    assertOrder(['Bar', 'Foo', '11', '3', '2'], table);
    -  } finally {
    -    sorter.dispose();
    -  }
    -}
    -
    -function assertOrder(arr, opt_table) {
    -  var tbl = opt_table || table;
    -  var actual = [];
    -  goog.array.forEach(tbl.getElementsByTagName('TD'), function(td, idx) {
    -    var txt = goog.dom.getTextContent(td);
    -    if (txt) {
    -      actual.push(txt);
    -    }
    -  });
    -  assertArrayEquals(arr, actual);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tabpane.js b/src/database/third_party/closure-library/closure/goog/ui/tabpane.js
    deleted file mode 100644
    index 9847774c247..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tabpane.js
    +++ /dev/null
    @@ -1,680 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview TabPane widget implementation.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - */
    -
    -goog.provide('goog.ui.TabPane');
    -goog.provide('goog.ui.TabPane.Events');
    -goog.provide('goog.ui.TabPane.TabLocation');
    -goog.provide('goog.ui.TabPane.TabPage');
    -goog.provide('goog.ui.TabPaneEvent');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.style');
    -
    -
    -
    -/**
    - * TabPane widget. All children already inside the tab pane container element
    - * will be be converted to tabs. Each tab is represented by a goog.ui.TabPane.
    - * TabPage object. Further pages can be constructed either from an existing
    - * container or created from scratch.
    - *
    - * @param {Element} el Container element to create the tab pane out of.
    - * @param {goog.ui.TabPane.TabLocation=} opt_tabLocation Location of the tabs
    - *     in relation to the content container. Default is top.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @param {boolean=} opt_useMouseDown Whether to use MOUSEDOWN instead of CLICK
    - *     for tab changes.
    - * @extends {goog.events.EventTarget}
    - * @constructor
    - * @see ../demos/tabpane.html
    - * @deprecated Use goog.ui.TabBar instead.
    - */
    -goog.ui.TabPane = function(el, opt_tabLocation, opt_domHelper,
    -                           opt_useMouseDown) {
    -  goog.events.EventTarget.call(this);
    -
    -  /**
    -   * DomHelper used to interact with the document, allowing components to be
    -   * created in a different window.  This property is considered protected;
    -   * subclasses of Component may refer to it directly.
    -   * @type {goog.dom.DomHelper}
    -   * @protected
    -   * @suppress {underscore|visibility}
    -   */
    -  this.dom_ = opt_domHelper || goog.dom.getDomHelper();
    -
    -  /**
    -   * Tab pane element.
    -   * @type {Element}
    -   * @private
    -   */
    -  this.el_ = el;
    -
    -  /**
    -   * Collection of tab panes.
    -   * @type {Array<goog.ui.TabPane.TabPage>}
    -   * @private
    -   */
    -  this.pages_ = [];
    -
    -  /**
    -   * Location of the tabs with respect to the content box.
    -   * @type {goog.ui.TabPane.TabLocation}
    -   * @private
    -   */
    -  this.tabLocation_ =
    -      opt_tabLocation ? opt_tabLocation : goog.ui.TabPane.TabLocation.TOP;
    -
    -  /**
    -   * Whether to use MOUSEDOWN instead of CLICK for tab change events. This
    -   * fixes some focus problems on Safari/Chrome.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.useMouseDown_ = !!opt_useMouseDown;
    -
    -  this.create_();
    -};
    -goog.inherits(goog.ui.TabPane, goog.events.EventTarget);
    -goog.tagUnsealableClass(goog.ui.TabPane);
    -
    -
    -/**
    - * Element containing the tab buttons.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.TabPane.prototype.elButtonBar_;
    -
    -
    -/**
    - * Element containing the tab pages.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.TabPane.prototype.elContent_;
    -
    -
    -/**
    - * Selected page.
    - * @type {goog.ui.TabPane.TabPage?}
    - * @private
    - */
    -goog.ui.TabPane.prototype.selected_;
    -
    -
    -/**
    - * Constants for event names
    - *
    - * @const
    - */
    -goog.ui.TabPane.Events = {
    -  CHANGE: 'change'
    -};
    -
    -
    -/**
    - * Enum for representing the location of the tabs in relation to the content.
    - *
    - * @enum {number}
    - */
    -goog.ui.TabPane.TabLocation = {
    -  TOP: 0,
    -  BOTTOM: 1,
    -  LEFT: 2,
    -  RIGHT: 3
    -};
    -
    -
    -/**
    - * Creates HTML nodes for tab pane.
    - *
    - * @private
    - */
    -goog.ui.TabPane.prototype.create_ = function() {
    -  this.el_.className = goog.getCssName('goog-tabpane');
    -
    -  var nodes = this.getChildNodes_();
    -
    -  // Create tab strip
    -  this.elButtonBar_ = this.dom_.createDom('ul',
    -      {'className': goog.getCssName('goog-tabpane-tabs'), 'tabIndex': '0'});
    -
    -  // Create content area
    -  this.elContent_ =
    -      this.dom_.createDom('div', goog.getCssName('goog-tabpane-cont'));
    -  this.el_.appendChild(this.elContent_);
    -
    -  var element = goog.asserts.assertElement(this.el_);
    -
    -  switch (this.tabLocation_) {
    -    case goog.ui.TabPane.TabLocation.TOP:
    -      element.insertBefore(this.elButtonBar_, this.elContent_);
    -      element.insertBefore(this.createClear_(), this.elContent_);
    -      goog.dom.classlist.add(element, goog.getCssName('goog-tabpane-top'));
    -      break;
    -    case goog.ui.TabPane.TabLocation.BOTTOM:
    -      element.appendChild(this.elButtonBar_);
    -      element.appendChild(this.createClear_());
    -      goog.dom.classlist.add(element, goog.getCssName('goog-tabpane-bottom'));
    -      break;
    -    case goog.ui.TabPane.TabLocation.LEFT:
    -      element.insertBefore(this.elButtonBar_, this.elContent_);
    -      goog.dom.classlist.add(element, goog.getCssName('goog-tabpane-left'));
    -      break;
    -    case goog.ui.TabPane.TabLocation.RIGHT:
    -      element.insertBefore(this.elButtonBar_, this.elContent_);
    -      goog.dom.classlist.add(element, goog.getCssName('goog-tabpane-right'));
    -      break;
    -    default:
    -      throw Error('Invalid tab location');
    -  }
    -
    -  // Listen for click and keydown events on header
    -  this.elButtonBar_.tabIndex = 0;
    -  goog.events.listen(this.elButtonBar_,
    -      this.useMouseDown_ ?
    -      goog.events.EventType.MOUSEDOWN :
    -      goog.events.EventType.CLICK,
    -      this.onHeaderClick_, false, this);
    -  goog.events.listen(this.elButtonBar_, goog.events.EventType.KEYDOWN,
    -      this.onHeaderKeyDown_, false, this);
    -
    -  this.createPages_(nodes);
    -};
    -
    -
    -/**
    - * Creates the HTML node for the clearing div, and associated style in
    - * the <HEAD>.
    - *
    - * @return {!Element} Reference to a DOM div node.
    - * @private
    - */
    -goog.ui.TabPane.prototype.createClear_ = function() {
    -  var clearFloatStyle = '.' + goog.getCssName('goog-tabpane-clear') +
    -      ' { clear: both; height: 0px; overflow: hidden }';
    -  goog.style.installStyles(clearFloatStyle);
    -  return this.dom_.createDom('div', goog.getCssName('goog-tabpane-clear'));
    -};
    -
    -
    -/** @override */
    -goog.ui.TabPane.prototype.disposeInternal = function() {
    -  goog.ui.TabPane.superClass_.disposeInternal.call(this);
    -  goog.events.unlisten(this.elButtonBar_,
    -      this.useMouseDown_ ?
    -      goog.events.EventType.MOUSEDOWN :
    -      goog.events.EventType.CLICK,
    -      this.onHeaderClick_, false, this);
    -  goog.events.unlisten(this.elButtonBar_, goog.events.EventType.KEYDOWN,
    -      this.onHeaderKeyDown_, false, this);
    -  delete this.el_;
    -  this.elButtonBar_ = null;
    -  this.elContent_ = null;
    -};
    -
    -
    -/**
    - * @return {!Array<Element>} The element child nodes of tab pane container.
    - * @private
    - */
    -goog.ui.TabPane.prototype.getChildNodes_ = function() {
    -  var nodes = [];
    -
    -  var child = goog.dom.getFirstElementChild(this.el_);
    -  while (child) {
    -    nodes.push(child);
    -    child = goog.dom.getNextElementSibling(child);
    -  }
    -
    -  return nodes;
    -};
    -
    -
    -/**
    - * Creates pages out of a collection of elements.
    - *
    - * @param {Array<Element>} nodes Array of elements to create pages out of.
    - * @private
    - */
    -goog.ui.TabPane.prototype.createPages_ = function(nodes) {
    -  for (var node, i = 0; node = nodes[i]; i++) {
    -    this.addPage(new goog.ui.TabPane.TabPage(node));
    -  }
    -};
    -
    -
    -/**
    - * Adds a page to the tab pane.
    - *
    - * @param {goog.ui.TabPane.TabPage} page Tab page to add.
    - * @param {number=} opt_index Zero based index to insert tab at. Inserted at the
    - *                           end if not specified.
    - */
    -goog.ui.TabPane.prototype.addPage = function(page, opt_index) {
    -  // If page is already in another tab pane it's removed from that one before it
    -  // can be added to this one.
    -  if (page.parent_ && page.parent_ != this &&
    -      page.parent_ instanceof goog.ui.TabPane) {
    -    page.parent_.removePage(page);
    -  }
    -
    -  // Insert page at specified position
    -  var index = this.pages_.length;
    -  if (goog.isDef(opt_index) && opt_index != index) {
    -    index = opt_index;
    -    this.pages_.splice(index, 0, page);
    -    this.elButtonBar_.insertBefore(page.elTitle_,
    -                                   this.elButtonBar_.childNodes[index]);
    -  }
    -
    -  // Append page to end
    -  else {
    -    this.pages_.push(page);
    -    this.elButtonBar_.appendChild(page.elTitle_);
    -  }
    -
    -  page.setParent_(this, index);
    -
    -  // Select first page and fire change event
    -  if (!this.selected_) {
    -    this.selected_ = page;
    -    this.dispatchEvent(new goog.ui.TabPaneEvent(goog.ui.TabPane.Events.CHANGE,
    -                                                this, this.selected_));
    -  }
    -
    -  // Move page content to the tab pane and update visibility.
    -  this.elContent_.appendChild(page.elContent_);
    -  page.setVisible_(page == this.selected_);
    -
    -  // Update index for following pages
    -  for (var pg, i = index + 1; pg = this.pages_[i]; i++) {
    -    pg.index_ = i;
    -  }
    -};
    -
    -
    -/**
    - * Removes the specified page from the tab pane.
    - *
    - * @param {goog.ui.TabPane.TabPage|number} page Reference to tab page or zero
    - *     based index.
    - */
    -goog.ui.TabPane.prototype.removePage = function(page) {
    -  if (goog.isNumber(page)) {
    -    page = this.pages_[page];
    -  }
    -  this.pages_.splice(page.index_, 1);
    -  page.setParent_(null);
    -
    -  goog.dom.removeNode(page.elTitle_);
    -  goog.dom.removeNode(page.elContent_);
    -
    -  for (var pg, i = 0; pg = this.pages_[i]; i++) {
    -    pg.setParent_(this, i);
    -  }
    -};
    -
    -
    -/**
    - * Gets the tab page by zero based index.
    - *
    - * @param {number} index Index of page to return.
    - * @return {goog.ui.TabPane.TabPage?} page The tab page.
    - */
    -goog.ui.TabPane.prototype.getPage = function(index) {
    -  return this.pages_[index];
    -};
    -
    -
    -/**
    - * Sets the selected tab page by object reference.
    - *
    - * @param {goog.ui.TabPane.TabPage} page Tab page to select.
    - */
    -goog.ui.TabPane.prototype.setSelectedPage = function(page) {
    -  if (page.isEnabled() &&
    -      (!this.selected_ || page != this.selected_)) {
    -    this.selected_.setVisible_(false);
    -    page.setVisible_(true);
    -    this.selected_ = page;
    -
    -    // Fire changed event
    -    this.dispatchEvent(new goog.ui.TabPaneEvent(goog.ui.TabPane.Events.CHANGE,
    -                                                this, this.selected_));
    -  }
    -};
    -
    -
    -/**
    - * Sets the selected tab page by zero based index.
    - *
    - * @param {number} index Index of page to select.
    - */
    -goog.ui.TabPane.prototype.setSelectedIndex = function(index) {
    -  if (index >= 0 && index < this.pages_.length) {
    -    this.setSelectedPage(this.pages_[index]);
    -  }
    -};
    -
    -
    -/**
    - * @return {number} The index for the selected tab page or -1 if no page is
    - *     selected.
    - */
    -goog.ui.TabPane.prototype.getSelectedIndex = function() {
    -  return this.selected_ ? /** @type {number} */ (this.selected_.index_) : -1;
    -};
    -
    -
    -/**
    - * @return {goog.ui.TabPane.TabPage?} The selected tab page.
    - */
    -goog.ui.TabPane.prototype.getSelectedPage = function() {
    -  return this.selected_ || null;
    -};
    -
    -
    -/**
    - * @return {Element} The element that contains the tab pages.
    - */
    -goog.ui.TabPane.prototype.getContentElement = function() {
    -  return this.elContent_ || null;
    -};
    -
    -
    -/**
    - * @return {Element} The main element for the tabpane.
    - */
    -goog.ui.TabPane.prototype.getElement = function() {
    -  return this.el_ || null;
    -};
    -
    -
    -/**
    - * Click event handler for header element, handles clicks on tabs.
    - *
    - * @param {goog.events.BrowserEvent} event Click event.
    - * @private
    - */
    -goog.ui.TabPane.prototype.onHeaderClick_ = function(event) {
    -  var el = event.target;
    -
    -  // Determine index if a tab (li element) was clicked.
    -  while (el != this.elButtonBar_) {
    -    if (el.tagName == 'LI') {
    -      var i;
    -      // {} prevents compiler warning
    -      for (i = 0; el = el.previousSibling; i++) {}
    -      this.setSelectedIndex(i);
    -      break;
    -    }
    -    el = el.parentNode;
    -  }
    -  event.preventDefault();
    -};
    -
    -
    -/**
    - * KeyDown event handler for header element. Arrow keys moves between pages.
    - * Home and end selects the first/last page.
    - *
    - * @param {goog.events.BrowserEvent} event KeyDown event.
    - * @private
    - */
    -goog.ui.TabPane.prototype.onHeaderKeyDown_ = function(event) {
    -  if (event.altKey || event.metaKey || event.ctrlKey) {
    -    return;
    -  }
    -
    -  switch (event.keyCode) {
    -    case goog.events.KeyCodes.LEFT:
    -      var index = this.selected_.getIndex() - 1;
    -      this.setSelectedIndex(index < 0 ? this.pages_.length - 1 : index);
    -      break;
    -    case goog.events.KeyCodes.RIGHT:
    -      var index = this.selected_.getIndex() + 1;
    -      this.setSelectedIndex(index >= this.pages_.length ? 0 : index);
    -      break;
    -    case goog.events.KeyCodes.HOME:
    -      this.setSelectedIndex(0);
    -      break;
    -    case goog.events.KeyCodes.END:
    -      this.setSelectedIndex(this.pages_.length - 1);
    -      break;
    -  }
    -};
    -
    -
    -
    -/**
    - * Object representing an individual tab pane.
    - *
    - * @param {Element=} opt_el Container element to create the pane out of.
    - * @param {(Element|string)=} opt_title Pane title or element to use as the
    - *     title. If not specified the first element in the container is used as
    - *     the title.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper
    - * The first parameter can be omitted.
    - * @constructor
    - */
    -goog.ui.TabPane.TabPage = function(opt_el, opt_title, opt_domHelper) {
    -  var title, el;
    -  if (goog.isString(opt_el) && !goog.isDef(opt_title)) {
    -    title = opt_el;
    -  } else if (opt_title) {
    -    title = opt_title;
    -    el = opt_el;
    -  } else if (opt_el) {
    -    var child = goog.dom.getFirstElementChild(opt_el);
    -    if (child) {
    -      title = goog.dom.getTextContent(child);
    -      child.parentNode.removeChild(child);
    -    }
    -    el = opt_el;
    -  }
    -
    -  /**
    -   * DomHelper used to interact with the document, allowing components to be
    -   * created in a different window.  This property is considered protected;
    -   * subclasses of Component may refer to it directly.
    -   * @type {goog.dom.DomHelper}
    -   * @protected
    -   * @suppress {underscore|visibility}
    -   */
    -  this.dom_ = opt_domHelper || goog.dom.getDomHelper();
    -
    -  /**
    -   * Content element
    -   * @type {Element}
    -   * @private
    -   */
    -  this.elContent_ = el || this.dom_.createDom('div');
    -
    -  /**
    -   * Title element
    -   * @type {Element}
    -   * @private
    -   */
    -  this.elTitle_ = this.dom_.createDom('li', null, title);
    -
    -  /**
    -   * Parent TabPane reference.
    -   * @type {goog.ui.TabPane?}
    -   * @private
    -   */
    -  this.parent_ = null;
    -
    -  /**
    -   * Index for page in tab pane.
    -   * @type {?number}
    -   * @private
    -   */
    -  this.index_ = null;
    -
    -  /**
    -   * Flags if this page is enabled and can be selected.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.enabled_ = true;
    -};
    -
    -
    -/**
    - * @return {string} The title for tab page.
    - */
    -goog.ui.TabPane.TabPage.prototype.getTitle = function() {
    -  return goog.dom.getTextContent(this.elTitle_);
    -};
    -
    -
    -/**
    - * Sets title for tab page.
    - *
    - * @param {string} title Title for tab page.
    - */
    -goog.ui.TabPane.TabPage.prototype.setTitle = function(title) {
    -  goog.dom.setTextContent(this.elTitle_, title);
    -};
    -
    -
    -/**
    - * @return {Element} The title element.
    - */
    -goog.ui.TabPane.TabPage.prototype.getTitleElement = function() {
    -  return this.elTitle_;
    -};
    -
    -
    -/**
    - * @return {Element} The content element.
    - */
    -goog.ui.TabPane.TabPage.prototype.getContentElement = function() {
    -  return this.elContent_;
    -};
    -
    -
    -/**
    - * @return {?number} The index of page in tab pane.
    - */
    -goog.ui.TabPane.TabPage.prototype.getIndex = function() {
    -  return this.index_;
    -};
    -
    -
    -/**
    - * @return {goog.ui.TabPane?} The parent tab pane for page.
    - */
    -goog.ui.TabPane.TabPage.prototype.getParent = function() {
    -  return this.parent_;
    -};
    -
    -
    -/**
    - * Selects page in the associated tab pane.
    - */
    -goog.ui.TabPane.TabPage.prototype.select = function() {
    -  if (this.parent_) {
    -    this.parent_.setSelectedPage(this);
    -  }
    -};
    -
    -
    -/**
    - * Sets the enabled state.
    - *
    - * @param {boolean} enabled Enabled state.
    - */
    -goog.ui.TabPane.TabPage.prototype.setEnabled = function(enabled) {
    -  this.enabled_ = enabled;
    -  this.elTitle_.className = enabled ?
    -      goog.getCssName('goog-tabpane-tab') :
    -      goog.getCssName('goog-tabpane-tab-disabled');
    -};
    -
    -
    -/**
    - * Returns if the page is enabled.
    - * @return {boolean} Whether the page is enabled or not.
    - */
    -goog.ui.TabPane.TabPage.prototype.isEnabled = function() {
    -  return this.enabled_;
    -};
    -
    -
    -/**
    - * Sets visible state for page content and updates style of tab.
    - *
    - * @param {boolean} visible Visible state.
    - * @private
    - */
    -goog.ui.TabPane.TabPage.prototype.setVisible_ = function(visible) {
    -  if (this.isEnabled()) {
    -    this.elContent_.style.display = visible ? '' : 'none';
    -    this.elTitle_.className = visible ?
    -        goog.getCssName('goog-tabpane-tab-selected') :
    -        goog.getCssName('goog-tabpane-tab');
    -  }
    -};
    -
    -
    -/**
    - * Sets parent tab pane for tab page.
    - *
    - * @param {goog.ui.TabPane?} tabPane Tab strip object.
    - * @param {number=} opt_index Index of page in pane.
    - * @private
    - */
    -goog.ui.TabPane.TabPage.prototype.setParent_ = function(tabPane, opt_index) {
    -  this.parent_ = tabPane;
    -  this.index_ = goog.isDef(opt_index) ? opt_index : null;
    -};
    -
    -
    -
    -/**
    - * Object representing a tab pane page changed event.
    - *
    - * @param {string} type Event type.
    - * @param {goog.ui.TabPane} target Tab widget initiating event.
    - * @param {goog.ui.TabPane.TabPage} page Selected page in tab pane.
    - * @extends {goog.events.Event}
    - * @constructor
    - * @final
    - */
    -goog.ui.TabPaneEvent = function(type, target, page) {
    -  goog.events.Event.call(this, type, target);
    -
    -  /**
    -   * The selected page.
    -   * @type {goog.ui.TabPane.TabPage}
    -   */
    -  this.page = page;
    -};
    -goog.inherits(goog.ui.TabPaneEvent, goog.events.Event);
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tabpane_test.html b/src/database/third_party/closure-library/closure/goog/ui/tabpane_test.html
    deleted file mode 100644
    index e31edd5ba75..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tabpane_test.html
    +++ /dev/null
    @@ -1,24 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.TabPane
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.TabPaneTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="testBody">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tabpane_test.js b/src/database/third_party/closure-library/closure/goog/ui/tabpane_test.js
    deleted file mode 100644
    index 0023479764d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tabpane_test.js
    +++ /dev/null
    @@ -1,100 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.TabPaneTest');
    -goog.setTestOnly('goog.ui.TabPaneTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.TabPane');
    -
    -var tabPane;
    -var page1;
    -var page2;
    -var page3;
    -
    -function setUp() {
    -  goog.dom.getElement('testBody').innerHTML =
    -      '<div id="tabpane"></div>' +
    -      '<div id="page1Content">' +
    -      '  Content for page 1' +
    -      '</div>' +
    -      '<div id="page2Content">' +
    -      '  Content for page 2' +
    -      '</div>' +
    -      '<div id="page3Content">' +
    -      '  Content for page 3' +
    -      '</div>';
    -
    -  tabPane = new goog.ui.TabPane(goog.dom.getElement('tabpane'));
    -  page1 = new goog.ui.TabPane.TabPage(goog.dom.getElement('page1Content'),
    -      'page1');
    -  page2 = new goog.ui.TabPane.TabPage(goog.dom.getElement('page2Content'),
    -      'page2');
    -  page3 = new goog.ui.TabPane.TabPage(goog.dom.getElement('page3Content'),
    -      'page3');
    -
    -  tabPane.addPage(page1);
    -  tabPane.addPage(page2);
    -  tabPane.addPage(page3);
    -}
    -
    -function tearDown() {
    -  tabPane.dispose();
    -}
    -
    -function testAllPagesEnabledAndSelectable() {
    -  tabPane.setSelectedIndex(0);
    -  var selected = tabPane.getSelectedPage();
    -  assertEquals('page1 should be selected', 'page1', selected.getTitle());
    -  assertEquals('goog-tabpane-tab-selected',
    -               selected.getTitleElement().className);
    -
    -  tabPane.setSelectedIndex(1);
    -  selected = tabPane.getSelectedPage();
    -  assertEquals('page2 should be selected', 'page2', selected.getTitle());
    -  assertEquals('goog-tabpane-tab-selected',
    -               selected.getTitleElement().className);
    -
    -  tabPane.setSelectedIndex(2);
    -  selected = tabPane.getSelectedPage();
    -  assertEquals('page3 should be selected', 'page3', selected.getTitle());
    -  assertEquals('goog-tabpane-tab-selected',
    -               selected.getTitleElement().className);
    -}
    -
    -function testDisabledPageIsNotSelectable() {
    -  page2.setEnabled(false);
    -  assertEquals('goog-tabpane-tab-disabled',
    -               page2.getTitleElement().className);
    -
    -  tabPane.setSelectedIndex(0);
    -  var selected = tabPane.getSelectedPage();
    -  assertEquals('page1 should be selected', 'page1', selected.getTitle());
    -  assertEquals('goog-tabpane-tab-selected',
    -               selected.getTitleElement().className);
    -
    -  tabPane.setSelectedIndex(1);
    -  selected = tabPane.getSelectedPage();
    -  assertEquals('page1 should remain selected, as page2 is disabled',
    -               'page1', selected.getTitle());
    -  assertEquals('goog-tabpane-tab-selected',
    -               selected.getTitleElement().className);
    -
    -  tabPane.setSelectedIndex(2);
    -  selected = tabPane.getSelectedPage();
    -  assertEquals('page3 should be selected', 'page3', selected.getTitle());
    -  assertEquals('goog-tabpane-tab-selected',
    -               selected.getTitleElement().className);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tabrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/tabrenderer.js
    deleted file mode 100644
    index 8c15644c658..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tabrenderer.js
    +++ /dev/null
    @@ -1,153 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Default renderer for {@link goog.ui.Tab}s.  Based on the
    - * original {@code TabPane} code.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.TabRenderer');
    -
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.ControlRenderer');
    -
    -
    -
    -/**
    - * Default renderer for {@link goog.ui.Tab}s, based on the {@code TabPane} code.
    - * @constructor
    - * @extends {goog.ui.ControlRenderer}
    - */
    -goog.ui.TabRenderer = function() {
    -  goog.ui.ControlRenderer.call(this);
    -};
    -goog.inherits(goog.ui.TabRenderer, goog.ui.ControlRenderer);
    -goog.addSingletonGetter(goog.ui.TabRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.TabRenderer.CSS_CLASS = goog.getCssName('goog-tab');
    -
    -
    -/**
    - * Returns the CSS class name to be applied to the root element of all tabs
    - * rendered or decorated using this renderer.
    - * @return {string} Renderer-specific CSS class name.
    - * @override
    - */
    -goog.ui.TabRenderer.prototype.getCssClass = function() {
    -  return goog.ui.TabRenderer.CSS_CLASS;
    -};
    -
    -
    -/**
    - * Returns the ARIA role to be applied to the tab element.
    - * See http://wiki/Main/ARIA for more info.
    - * @return {goog.a11y.aria.Role} ARIA role.
    - * @override
    - */
    -goog.ui.TabRenderer.prototype.getAriaRole = function() {
    -  return goog.a11y.aria.Role.TAB;
    -};
    -
    -
    -/**
    - * Returns the tab's contents wrapped in a DIV, with the renderer's own CSS
    - * class and additional state-specific classes applied to it.  Creates the
    - * following DOM structure:
    - * <pre>
    - *   <div class="goog-tab" title="Title">Content</div>
    - * </pre>
    - * @param {goog.ui.Control} tab Tab to render.
    - * @return {Element} Root element for the tab.
    - * @override
    - */
    -goog.ui.TabRenderer.prototype.createDom = function(tab) {
    -  var element = goog.ui.TabRenderer.superClass_.createDom.call(this, tab);
    -
    -  var tooltip = tab.getTooltip();
    -  if (tooltip) {
    -    // Only update the element if the tab has a tooltip.
    -    this.setTooltip(element, tooltip);
    -  }
    -
    -  return element;
    -};
    -
    -
    -/**
    - * Decorates the element with the tab.  Initializes the tab's ID, content,
    - * tooltip, and state based on the ID of the element, its title, child nodes,
    - * and CSS classes, respectively.  Returns the element.
    - * @param {goog.ui.Control} tab Tab to decorate the element.
    - * @param {Element} element Element to decorate.
    - * @return {Element} Decorated element.
    - * @override
    - */
    -goog.ui.TabRenderer.prototype.decorate = function(tab, element) {
    -  element = goog.ui.TabRenderer.superClass_.decorate.call(this, tab, element);
    -
    -  var tooltip = this.getTooltip(element);
    -  if (tooltip) {
    -    // Only update the tab if the element has a tooltip.
    -    tab.setTooltipInternal(tooltip);
    -  }
    -
    -  // If the tab is selected and hosted in a tab bar, update the tab bar's
    -  // selection model.
    -  if (tab.isSelected()) {
    -    var tabBar = tab.getParent();
    -    if (tabBar && goog.isFunction(tabBar.setSelectedTab)) {
    -      // We need to temporarily deselect the tab, so the tab bar can re-select
    -      // it and thereby correctly initialize its state.  We use the protected
    -      // setState() method to avoid dispatching useless events.
    -      tab.setState(goog.ui.Component.State.SELECTED, false);
    -      tabBar.setSelectedTab(tab);
    -    }
    -  }
    -
    -  return element;
    -};
    -
    -
    -/**
    - * Takes a tab's root element, and returns its tooltip text, or the empty
    - * string if the element has no tooltip.
    - * @param {Element} element The tab's root element.
    - * @return {string} The tooltip text (empty string if none).
    - */
    -goog.ui.TabRenderer.prototype.getTooltip = function(element) {
    -  return element.title || '';
    -};
    -
    -
    -/**
    - * Takes a tab's root element and a tooltip string, and updates the element
    - * with the new tooltip.  If the new tooltip is null or undefined, sets the
    - * element's title to the empty string.
    - * @param {Element} element The tab's root element.
    - * @param {string|null|undefined} tooltip New tooltip text (if any).
    - */
    -goog.ui.TabRenderer.prototype.setTooltip = function(element, tooltip) {
    -  if (element) {
    -    element.title = tooltip || '';
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tabrenderer_test.html b/src/database/third_party/closure-library/closure/goog/ui/tabrenderer_test.html
    deleted file mode 100644
    index 6dc3f9a77c1..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tabrenderer_test.html
    +++ /dev/null
    @@ -1,27 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -Author: attila@google.com (Attila Bodis)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.TabRenderer
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.TabRendererTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="sandbox">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tabrenderer_test.js b/src/database/third_party/closure-library/closure/goog/ui/tabrenderer_test.js
    deleted file mode 100644
    index d9070e4941e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tabrenderer_test.js
    +++ /dev/null
    @@ -1,140 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.TabRendererTest');
    -goog.setTestOnly('goog.ui.TabRendererTest');
    -
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.testing.dom');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.ui.rendererasserts');
    -goog.require('goog.ui.Tab');
    -goog.require('goog.ui.TabRenderer');
    -
    -var sandbox;
    -var renderer;
    -var tab;
    -
    -function setUp() {
    -  sandbox = goog.dom.getElement('sandbox');
    -  renderer = goog.ui.TabRenderer.getInstance();
    -  tab = new goog.ui.Tab('Hello');
    -}
    -
    -function tearDown() {
    -  tab.dispose();
    -  goog.dom.removeChildren(sandbox);
    -}
    -
    -function testConstructor() {
    -  assertNotNull('Renderer must not be null', renderer);
    -}
    -
    -function testGetCssClass() {
    -  assertEquals('CSS class must have expected value',
    -      goog.ui.TabRenderer.CSS_CLASS, renderer.getCssClass());
    -}
    -
    -function testGetAriaRole() {
    -  assertEquals('ARIA role must have expected value',
    -      goog.a11y.aria.Role.TAB, renderer.getAriaRole());
    -}
    -
    -function testCreateDom() {
    -  var element = renderer.createDom(tab);
    -  assertNotNull('Element must not be null', element);
    -  goog.testing.dom.assertHtmlMatches(
    -      '<div class="goog-tab">Hello</div>',
    -      goog.dom.getOuterHtml(element));
    -}
    -
    -function testCreateDomWithTooltip() {
    -  tab.setTooltip('Hello, world!');
    -  var element = renderer.createDom(tab);
    -  assertNotNull('Element must not be null', element);
    -  assertEquals('Element must have expected tooltip', 'Hello, world!',
    -      renderer.getTooltip(element));
    -}
    -
    -function testRender() {
    -  tab.setRenderer(renderer);
    -  tab.render();
    -  var element = tab.getElementStrict();
    -  assertNotNull('Element must not be null', element);
    -  assertEquals('aria-selected should be false',
    -      'false', element.getAttribute('aria-selected'));
    -}
    -
    -function testDecorate() {
    -  sandbox.innerHTML =
    -      '<div id="foo">Foo</div>\n' +
    -      '<div id="bar" title="Yes">Bar</div>';
    -
    -  var foo = renderer.decorate(tab, goog.dom.getElement('foo'));
    -  assertNotNull('Decorated element must not be null', foo);
    -  assertSameElements('Decorated element must have expected class',
    -      ['goog-tab'], goog.dom.classlist.get(foo));
    -  assertEquals('Decorated tab must have expected content', 'Foo',
    -      tab.getContent().nodeValue);
    -  assertUndefined('Decorated tab must not have tooltip', tab.getTooltip());
    -  assertEquals('Decorated element must not have title', '',
    -      renderer.getTooltip(foo));
    -
    -  var bar = renderer.decorate(tab, goog.dom.getElement('bar'));
    -  assertNotNull('Decorated element must not be null', bar);
    -  assertSameElements('Decorated element must have expected class',
    -      ['goog-tab'], goog.dom.classlist.get(bar));
    -  assertEquals('Decorated tab must have expected content', 'Bar',
    -      tab.getContent().nodeValue);
    -  assertEquals('Decorated tab must have expected tooltip', 'Yes',
    -      tab.getTooltip());
    -  assertEquals('Decorated element must have expected title', 'Yes',
    -      renderer.getTooltip(bar));
    -}
    -
    -function testGetTooltip() {
    -  sandbox.innerHTML =
    -      '<div id="foo">Foo</div>\n' +
    -      '<div id="bar" title="">Bar</div>\n' +
    -      '<div id="baz" title="BazTitle">Baz</div>';
    -  assertEquals('getTooltip() must return empty string for no title', '',
    -      renderer.getTooltip(goog.dom.getElement('foo')));
    -  assertEquals('getTooltip() must return empty string for empty title', '',
    -      renderer.getTooltip(goog.dom.getElement('bar')));
    -  assertEquals('Tooltip must have expected value', 'BazTitle',
    -      renderer.getTooltip(goog.dom.getElement('baz')));
    -}
    -
    -function testSetTooltip() {
    -  sandbox.innerHTML = '<div id="foo">Foo</div>';
    -  var element = goog.dom.getElement('foo');
    -
    -  renderer.setTooltip(null, null); // Must not error.
    -
    -  renderer.setTooltip(element, null);
    -  assertEquals('Tooltip must be the empty string', '', element.title);
    -
    -  renderer.setTooltip(element, '');
    -  assertEquals('Tooltip must be the empty string', '', element.title);
    -
    -  renderer.setTooltip(element, 'Foo');
    -  assertEquals('Tooltip must have expected value', 'Foo', element.title);
    -}
    -
    -function testDoesntCallGetCssClassInConstructor() {
    -  goog.testing.ui.rendererasserts.
    -      assertNoGetCssClassCallsInConstructor(goog.ui.TabRenderer);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/textarea.js b/src/database/third_party/closure-library/closure/goog/ui/textarea.js
    deleted file mode 100644
    index 3b4d19bb279..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/textarea.js
    +++ /dev/null
    @@ -1,736 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A content-aware textarea control that grows and shrinks
    - * automatically. This implementation extends {@link goog.ui.Control}.
    - * This code is inspired by Dojo Dijit's Textarea implementation with
    - * modifications to support native (when available) textarea resizing and
    - * minHeight and maxHeight enforcement.
    - *
    - * @see ../demos/textarea.html
    - */
    -
    -goog.provide('goog.ui.Textarea');
    -goog.provide('goog.ui.Textarea.EventType');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events.EventType');
    -goog.require('goog.style');
    -goog.require('goog.ui.Control');
    -goog.require('goog.ui.TextareaRenderer');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * A textarea control to handle growing/shrinking with textarea.value.
    - *
    - * @param {string} content Text to set as the textarea's value.
    - * @param {goog.ui.TextareaRenderer=} opt_renderer Renderer used to render or
    - *     decorate the textarea. Defaults to {@link goog.ui.TextareaRenderer}.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @constructor
    - * @extends {goog.ui.Control}
    - */
    -goog.ui.Textarea = function(content, opt_renderer, opt_domHelper) {
    -  goog.ui.Control.call(this, content, opt_renderer ||
    -      goog.ui.TextareaRenderer.getInstance(), opt_domHelper);
    -
    -  this.setHandleMouseEvents(false);
    -  this.setAllowTextSelection(true);
    -  this.hasUserInput_ = (content != '');
    -  if (!content) {
    -    this.setContentInternal('');
    -  }
    -};
    -goog.inherits(goog.ui.Textarea, goog.ui.Control);
    -goog.tagUnsealableClass(goog.ui.Textarea);
    -
    -
    -/**
    - * Some UAs will shrink the textarea automatically, some won't.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.Textarea.NEEDS_HELP_SHRINKING_ = goog.userAgent.GECKO ||
    -    goog.userAgent.WEBKIT ||
    -    (goog.userAgent.IE && goog.userAgent.isDocumentModeOrHigher(11));
    -
    -
    -/**
    - * True if the resizing function is executing, false otherwise.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.Textarea.prototype.isResizing_ = false;
    -
    -
    -/**
    - * Represents if we have focus on the textarea element, used only
    - * to render the placeholder if we don't have native placeholder
    - * support.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.Textarea.prototype.hasFocusForPlaceholder_ = false;
    -
    -
    -/**
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.Textarea.prototype.hasUserInput_ = false;
    -
    -
    -/**
    - * The height of the textarea as last measured.
    - * @type {number}
    - * @private
    - */
    -goog.ui.Textarea.prototype.height_ = 0;
    -
    -
    -/**
    - * A maximum height for the textarea. When set to 0, the default, there is no
    - * enforcement of this value during resize.
    - * @type {number}
    - * @private
    - */
    -goog.ui.Textarea.prototype.maxHeight_ = 0;
    -
    -
    -/**
    - * A minimum height for the textarea. When set to 0, the default, there is no
    - * enforcement of this value during resize.
    - * @type {number}
    - * @private
    - */
    -goog.ui.Textarea.prototype.minHeight_ = 0;
    -
    -
    -/**
    - * Whether or not textarea rendering characteristics have been discovered.
    - * Specifically we determine, at runtime:
    - *    If the padding and border box is included in offsetHeight.
    - *    @see {goog.ui.Textarea.prototype.needsPaddingBorderFix_}
    - *    If the padding and border box is included in scrollHeight.
    - *    @see {goog.ui.Textarea.prototype.scrollHeightIncludesPadding_} and
    - *    @see {goog.ui.Textarea.prototype.scrollHeightIncludesBorder_}
    - * TODO(user): See if we can determine goog.ui.Textarea.NEEDS_HELP_SHRINKING_.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.Textarea.prototype.hasDiscoveredTextareaCharacteristics_ = false;
    -
    -
    -/**
    - * If a user agent doesn't correctly support the box-sizing:border-box CSS
    - * value then we'll need to adjust our height calculations.
    - * @see {goog.ui.Textarea.prototype.discoverTextareaCharacteristics_}
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.Textarea.prototype.needsPaddingBorderFix_ = false;
    -
    -
    -/**
    - * Whether or not scrollHeight of a textarea includes the padding box.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.Textarea.prototype.scrollHeightIncludesPadding_ = false;
    -
    -
    -/**
    - * Whether or not scrollHeight of a textarea includes the border box.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.Textarea.prototype.scrollHeightIncludesBorder_ = false;
    -
    -
    -/**
    - * For storing the padding box size during enterDocument, to prevent possible
    - * measurement differences that can happen after text zooming.
    - * Note: runtime padding changes will cause problems with this.
    - * @type {goog.math.Box}
    - * @private
    - */
    -goog.ui.Textarea.prototype.paddingBox_;
    -
    -
    -/**
    - * For storing the border box size during enterDocument, to prevent possible
    - * measurement differences that can happen after text zooming.
    - * Note: runtime border width changes will cause problems with this.
    - * @type {goog.math.Box}
    - * @private
    - */
    -goog.ui.Textarea.prototype.borderBox_;
    -
    -
    -/**
    - * Default text content for the textarea when it is unchanged and unfocussed.
    - * We use the placeholder attribute for all browsers that have support for
    - * it (new in HTML5 for the following browsers:
    - *
    - *   Internet Explorer 10.0
    - *   Firefox 4.0
    - *   Opera 11.6
    - *   Chrome 4.0
    - *   Safari 5.0
    - *
    - * For older browsers, we save the placeholderText_ and set it as the element's
    - * value and add the TEXTAREA_PLACEHOLDER_CLASS to indicate that it's a
    - * placeholder string.
    - * @type {string}
    - * @private
    - */
    -goog.ui.Textarea.prototype.placeholderText_ = '';
    -
    -
    -/**
    - * Constants for event names.
    - * @enum {string}
    - */
    -goog.ui.Textarea.EventType = {
    -  RESIZE: 'resize'
    -};
    -
    -
    -/**
    - * Sets the default text for the textarea.
    - * @param {string} text The default text for the textarea.
    - */
    -goog.ui.Textarea.prototype.setPlaceholder = function(text) {
    -  this.placeholderText_ = text;
    -  if (this.getElement()) {
    -    this.restorePlaceholder_();
    -  }
    -};
    -
    -
    -/**
    - * @return {number} The padding plus the border box height.
    - * @private
    - */
    -goog.ui.Textarea.prototype.getPaddingBorderBoxHeight_ = function() {
    -  var paddingBorderBoxHeight = this.paddingBox_.top + this.paddingBox_.bottom +
    -      this.borderBox_.top + this.borderBox_.bottom;
    -  return paddingBorderBoxHeight;
    -};
    -
    -
    -/**
    - * @return {number} The minHeight value.
    - */
    -goog.ui.Textarea.prototype.getMinHeight = function() {
    -  return this.minHeight_;
    -};
    -
    -
    -/**
    - * @return {number} The minHeight value with a potential padding fix.
    - * @private
    - */
    -goog.ui.Textarea.prototype.getMinHeight_ = function() {
    -  var minHeight = this.minHeight_;
    -  var textarea = this.getElement();
    -  if (minHeight && textarea && this.needsPaddingBorderFix_) {
    -    minHeight -= this.getPaddingBorderBoxHeight_();
    -  }
    -  return minHeight;
    -};
    -
    -
    -/**
    - * Sets a minimum height for the textarea, and calls resize if rendered.
    - * @param {number} height New minHeight value.
    - */
    -goog.ui.Textarea.prototype.setMinHeight = function(height) {
    -  this.minHeight_ = height;
    -  this.resize();
    -};
    -
    -
    -/**
    - * @return {number} The maxHeight value.
    - */
    -goog.ui.Textarea.prototype.getMaxHeight = function() {
    -  return this.maxHeight_;
    -};
    -
    -
    -/**
    - * @return {number} The maxHeight value with a potential padding fix.
    - * @private
    - */
    -goog.ui.Textarea.prototype.getMaxHeight_ = function() {
    -  var maxHeight = this.maxHeight_;
    -  var textarea = this.getElement();
    -  if (maxHeight && textarea && this.needsPaddingBorderFix_) {
    -    maxHeight -= this.getPaddingBorderBoxHeight_();
    -  }
    -  return maxHeight;
    -};
    -
    -
    -/**
    - * Sets a maximum height for the textarea, and calls resize if rendered.
    - * @param {number} height New maxHeight value.
    - */
    -goog.ui.Textarea.prototype.setMaxHeight = function(height) {
    -  this.maxHeight_ = height;
    -  this.resize();
    -};
    -
    -
    -/**
    - * Sets the textarea's value.
    - * @param {*} value The value property for the textarea, will be cast to a
    - *     string by the browser when setting textarea.value.
    - */
    -goog.ui.Textarea.prototype.setValue = function(value) {
    -  this.setContent(String(value));
    -};
    -
    -
    -/**
    - * Gets the textarea's value.
    - * @return {string} value The value of the textarea.
    - */
    -goog.ui.Textarea.prototype.getValue = function() {
    -  // We potentially have the placeholder stored in the value.
    -  // If a client of this class sets this.getElement().value directly
    -  // we don't set the this.hasUserInput_ boolean. Thus, we need to
    -  // explicitly check if the value != the placeholder text. This has
    -  // the unfortunate edge case of:
    -  //   If the client sets this.getElement().value to the placeholder
    -  //   text, we'll return the empty string.
    -  // The normal use case shouldn't be an issue, however, since the
    -  // default placeholderText is the empty string. Also, if the end user
    -  // inputs text, then this.hasUserInput_ will always be true.
    -  if (this.getElement().value != this.placeholderText_ ||
    -      this.supportsNativePlaceholder_() || this.hasUserInput_) {
    -    // We don't do anything fancy here.
    -    return this.getElement().value;
    -  }
    -  return '';
    -};
    -
    -
    -/** @override */
    -goog.ui.Textarea.prototype.setContent = function(content) {
    -  goog.ui.Textarea.superClass_.setContent.call(this, content);
    -  this.hasUserInput_ = (content != '');
    -  this.resize();
    -};
    -
    -
    -/** @override **/
    -goog.ui.Textarea.prototype.setEnabled = function(enable) {
    -  goog.ui.Textarea.superClass_.setEnabled.call(this, enable);
    -  this.getElement().disabled = !enable;
    -};
    -
    -
    -/**
    - * Resizes the textarea vertically.
    - */
    -goog.ui.Textarea.prototype.resize = function() {
    -  if (this.getElement()) {
    -    this.grow_();
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} True if the element supports the placeholder attribute.
    - * @private
    - */
    -goog.ui.Textarea.prototype.supportsNativePlaceholder_ = function() {
    -  goog.asserts.assert(this.getElement());
    -  return 'placeholder' in this.getElement();
    -};
    -
    -
    -/**
    - * Sets the value of the textarea element to the default text.
    - * @private
    - */
    -goog.ui.Textarea.prototype.restorePlaceholder_ = function() {
    -  if (!this.placeholderText_) {
    -    // Return early if there is no placeholder to mess with.
    -    return;
    -  }
    -  // Check again in case something changed since this was scheduled.
    -  // We check that the element is still there since this is called by a timer
    -  // and the dispose method may have been called prior to this.
    -  if (this.supportsNativePlaceholder_()) {
    -    this.getElement().placeholder = this.placeholderText_;
    -  } else if (this.getElement() && !this.hasUserInput_ &&
    -      !this.hasFocusForPlaceholder_) {
    -    // We only want to set the value + placeholder CSS if we actually have
    -    // some placeholder text to show.
    -    goog.dom.classlist.add(
    -        goog.asserts.assert(this.getElement()),
    -        goog.ui.Textarea.TEXTAREA_PLACEHOLDER_CLASS);
    -    this.getElement().value = this.placeholderText_;
    -  }
    -};
    -
    -
    -/** @override **/
    -goog.ui.Textarea.prototype.enterDocument = function() {
    -  goog.ui.Textarea.base(this, 'enterDocument');
    -  var textarea = this.getElement();
    -
    -  // Eliminates the vertical scrollbar and changes the box-sizing mode for the
    -  // textarea to the border-box (aka quirksmode) paradigm.
    -  goog.style.setStyle(textarea, {
    -    'overflowY': 'hidden',
    -    'overflowX': 'auto',
    -    'boxSizing': 'border-box',
    -    'MsBoxSizing': 'border-box',
    -    'WebkitBoxSizing': 'border-box',
    -    'MozBoxSizing': 'border-box'});
    -
    -  this.paddingBox_ = goog.style.getPaddingBox(textarea);
    -  this.borderBox_ = goog.style.getBorderBox(textarea);
    -
    -  this.getHandler().
    -      listen(textarea, goog.events.EventType.SCROLL, this.grow_).
    -      listen(textarea, goog.events.EventType.FOCUS, this.grow_).
    -      listen(textarea, goog.events.EventType.KEYUP, this.grow_).
    -      listen(textarea, goog.events.EventType.MOUSEUP, this.mouseUpListener_).
    -      listen(textarea, goog.events.EventType.BLUR, this.blur_);
    -
    -  this.restorePlaceholder_();
    -  this.resize();
    -};
    -
    -
    -/**
    - * Gets the textarea's content height + padding height + border height.
    - * This is done by getting the scrollHeight and adjusting from there.
    - * In the end this result is what we want the new offsetHeight to equal.
    - * @return {number} The height of the textarea.
    - * @private
    - */
    -goog.ui.Textarea.prototype.getHeight_ = function() {
    -  this.discoverTextareaCharacteristics_();
    -  var textarea = this.getElement();
    -  // Because enterDocument can be called even when the component is rendered
    -  // without being in a document, we may not have cached the correct paddingBox
    -  // data on render(). We try to make up for this here.
    -  if (isNaN(this.paddingBox_.top)) {
    -    this.paddingBox_ = goog.style.getPaddingBox(textarea);
    -    this.borderBox_ = goog.style.getBorderBox(textarea);
    -  }
    -  // Accounts for a possible (though unlikely) horizontal scrollbar.
    -  var height = this.getElement().scrollHeight +
    -      this.getHorizontalScrollBarHeight_();
    -  if (this.needsPaddingBorderFix_) {
    -    height -= this.getPaddingBorderBoxHeight_();
    -  } else {
    -    if (!this.scrollHeightIncludesPadding_) {
    -      var paddingBox = this.paddingBox_;
    -      var paddingBoxHeight = paddingBox.top + paddingBox.bottom;
    -      height += paddingBoxHeight;
    -    }
    -    if (!this.scrollHeightIncludesBorder_) {
    -      var borderBox = goog.style.getBorderBox(textarea);
    -      var borderBoxHeight = borderBox.top + borderBox.bottom;
    -      height += borderBoxHeight;
    -    }
    -  }
    -  return height;
    -};
    -
    -
    -/**
    - * Sets the textarea's height.
    - * @param {number} height The height to set.
    - * @private
    - */
    -goog.ui.Textarea.prototype.setHeight_ = function(height) {
    -  if (this.height_ != height) {
    -    this.height_ = height;
    -    this.getElement().style.height = height + 'px';
    -  }
    -};
    -
    -
    -/**
    - * Sets the textarea's rows attribute to be the number of newlines + 1.
    - * This is necessary when the textarea is hidden, in which case scrollHeight
    - * is not available.
    - * @private
    - */
    -goog.ui.Textarea.prototype.setHeightToEstimate_ = function() {
    -  var textarea = this.getElement();
    -  textarea.style.height = 'auto';
    -  var newlines = textarea.value.match(/\n/g) || [];
    -  textarea.rows = newlines.length + 1;
    -  this.height_ = 0;
    -};
    -
    -
    -/**
    - * Gets the the height of (possibly present) horizontal scrollbar.
    - * @return {number} The height of the horizontal scrollbar.
    - * @private
    - */
    -goog.ui.Textarea.prototype.getHorizontalScrollBarHeight_ =
    -    function() {
    -  var textarea = this.getElement();
    -  var height = textarea.offsetHeight - textarea.clientHeight;
    -  if (!this.scrollHeightIncludesPadding_) {
    -    var paddingBox = this.paddingBox_;
    -    var paddingBoxHeight = paddingBox.top + paddingBox.bottom;
    -    height -= paddingBoxHeight;
    -  }
    -  if (!this.scrollHeightIncludesBorder_) {
    -    var borderBox = goog.style.getBorderBox(textarea);
    -    var borderBoxHeight = borderBox.top + borderBox.bottom;
    -    height -= borderBoxHeight;
    -  }
    -  // Prevent negative number results, which sometimes show up.
    -  return height > 0 ? height : 0;
    -};
    -
    -
    -/**
    - * In order to assess the correct height for a textarea, we need to know
    - * whether the scrollHeight (the full height of the text) property includes
    - * the values for padding and borders. We can also test whether the
    - * box-sizing: border-box setting is working and then tweak accordingly.
    - * Instead of hardcoding a list of currently known behaviors and testing
    - * for quirksmode, we do a runtime check out of the flow. The performance
    - * impact should be very small.
    - * @private
    - */
    -goog.ui.Textarea.prototype.discoverTextareaCharacteristics_ = function() {
    -  if (!this.hasDiscoveredTextareaCharacteristics_) {
    -    var textarea = /** @type {!Element} */ (this.getElement().cloneNode(false));
    -    // We need to overwrite/write box model specific styles that might
    -    // affect height.
    -    goog.style.setStyle(textarea, {
    -      'position': 'absolute',
    -      'height': 'auto',
    -      'top': '-9999px',
    -      'margin': '0',
    -      'padding': '1px',
    -      'border': '1px solid #000',
    -      'overflow': 'hidden'
    -    });
    -    goog.dom.appendChild(this.getDomHelper().getDocument().body, textarea);
    -    var initialScrollHeight = textarea.scrollHeight;
    -
    -    textarea.style.padding = '10px';
    -    var paddingScrollHeight = textarea.scrollHeight;
    -    this.scrollHeightIncludesPadding_ = paddingScrollHeight >
    -        initialScrollHeight;
    -
    -    initialScrollHeight = paddingScrollHeight;
    -    textarea.style.borderWidth = '10px';
    -    var borderScrollHeight = textarea.scrollHeight;
    -    this.scrollHeightIncludesBorder_ = borderScrollHeight > initialScrollHeight;
    -
    -    // Tests if border-box sizing is working or not.
    -    textarea.style.height = '100px';
    -    var offsetHeightAtHeight100 = textarea.offsetHeight;
    -    if (offsetHeightAtHeight100 != 100) {
    -      this.needsPaddingBorderFix_ = true;
    -    }
    -
    -    goog.dom.removeNode(textarea);
    -    this.hasDiscoveredTextareaCharacteristics_ = true;
    -  }
    -};
    -
    -
    -/**
    - * The CSS class name to add to the input when the user has not entered a
    - * value.
    - */
    -goog.ui.Textarea.TEXTAREA_PLACEHOLDER_CLASS =
    -    goog.getCssName('textarea-placeholder-input');
    -
    -
    -/**
    - * Called when the element goes out of focus.
    - * @param {goog.events.Event=} opt_e The browser event.
    - * @private
    - */
    -goog.ui.Textarea.prototype.blur_ = function(opt_e) {
    -  if (!this.supportsNativePlaceholder_()) {
    -    this.hasFocusForPlaceholder_ = false;
    -    if (this.getElement().value == '') {
    -      // Only transition to the default text if we have
    -      // no user input.
    -      this.hasUserInput_ = false;
    -      this.restorePlaceholder_();
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Resizes the textarea to grow/shrink to match its contents.
    - * @param {goog.events.Event=} opt_e The browser event.
    - * @private
    - */
    -goog.ui.Textarea.prototype.grow_ = function(opt_e) {
    -  if (this.isResizing_) {
    -    return;
    -  }
    -  var textarea = this.getElement();
    -  // If the element is getting focus and we don't support placeholders
    -  // natively, then remove the placeholder class.
    -  if (!this.supportsNativePlaceholder_() && opt_e &&
    -      opt_e.type == goog.events.EventType.FOCUS) {
    -    // We must have a textarea element, since we're growing it.
    -    // Remove the placeholder CSS + set the value to empty if we're currently
    -    // showing the placeholderText_ value if this is the first time we're
    -    // getting focus.
    -    if (textarea.value == this.placeholderText_ &&
    -        this.placeholderText_ &&
    -        !this.hasFocusForPlaceholder_) {
    -      goog.dom.classlist.remove(
    -          textarea, goog.ui.Textarea.TEXTAREA_PLACEHOLDER_CLASS);
    -      textarea.value = '';
    -    }
    -    this.hasFocusForPlaceholder_ = true;
    -    this.hasUserInput_ = (textarea.value != '');
    -  }
    -  var shouldCallShrink = false;
    -  this.isResizing_ = true;
    -  var oldHeight = this.height_;
    -  if (textarea.scrollHeight) {
    -    var setMinHeight = false;
    -    var setMaxHeight = false;
    -    var newHeight = this.getHeight_();
    -    var currentHeight = textarea.offsetHeight;
    -    var minHeight = this.getMinHeight_();
    -    var maxHeight = this.getMaxHeight_();
    -    if (minHeight && newHeight < minHeight) {
    -      this.setHeight_(minHeight);
    -      setMinHeight = true;
    -    } else if (maxHeight && newHeight > maxHeight) {
    -      this.setHeight_(maxHeight);
    -      // If the content is greater than the height, we'll want the vertical
    -      // scrollbar back.
    -      textarea.style.overflowY = '';
    -      setMaxHeight = true;
    -    } else if (currentHeight != newHeight) {
    -      this.setHeight_(newHeight);
    -    // Makes sure that height_ is at least set.
    -    } else if (!this.height_) {
    -      this.height_ = newHeight;
    -    }
    -    if (!setMinHeight && !setMaxHeight &&
    -        goog.ui.Textarea.NEEDS_HELP_SHRINKING_) {
    -      shouldCallShrink = true;
    -    }
    -  } else {
    -    this.setHeightToEstimate_();
    -  }
    -  this.isResizing_ = false;
    -
    -  if (shouldCallShrink) {
    -    this.shrink_();
    -  }
    -  if (oldHeight != this.height_) {
    -    this.dispatchEvent(goog.ui.Textarea.EventType.RESIZE);
    -  }
    -};
    -
    -
    -/**
    - * Resizes the textarea to shrink to fit its contents. The way this works is
    - * by increasing the padding of the textarea by 1px (it's important here that
    - * we're in box-sizing: border-box mode). If the size of the textarea grows,
    - * then the box is filled up to the padding box with text.
    - * If it doesn't change, then we can shrink.
    - * @private
    - */
    -goog.ui.Textarea.prototype.shrink_ = function() {
    -  var textarea = this.getElement();
    -  if (!this.isResizing_) {
    -    this.isResizing_ = true;
    -    var scrollHeight = textarea.scrollHeight;
    -    if (!scrollHeight) {
    -      this.setHeightToEstimate_();
    -    } else {
    -      var currentHeight = this.getHeight_();
    -      var minHeight = this.getMinHeight_();
    -      var maxHeight = this.getMaxHeight_();
    -      if (!(minHeight && currentHeight <= minHeight)) {
    -        // Nudge the padding by 1px.
    -        var paddingBox = this.paddingBox_;
    -        textarea.style.paddingBottom = paddingBox.bottom + 1 + 'px';
    -        var heightAfterNudge = this.getHeight_();
    -        // If the one px of padding had no effect, then we can shrink.
    -        if (heightAfterNudge == currentHeight) {
    -          textarea.style.paddingBottom = paddingBox.bottom + scrollHeight +
    -              'px';
    -          textarea.scrollTop = 0;
    -          var shrinkToHeight = this.getHeight_() - scrollHeight;
    -          if (shrinkToHeight >= minHeight) {
    -            this.setHeight_(shrinkToHeight);
    -          } else {
    -            this.setHeight_(minHeight);
    -          }
    -        }
    -        textarea.style.paddingBottom = paddingBox.bottom + 'px';
    -      }
    -    }
    -    this.isResizing_ = false;
    -  }
    -};
    -
    -
    -/**
    - * We use this listener to check if the textarea has been natively resized
    - * and if so we reset minHeight so that we don't ever shrink smaller than
    - * the user's manually set height. Note that we cannot check size on mousedown
    - * and then just compare here because we cannot capture mousedown on
    - * the textarea resizer, while mouseup fires reliably.
    - * @param {goog.events.BrowserEvent} e The mousedown event.
    - * @private
    - */
    -goog.ui.Textarea.prototype.mouseUpListener_ = function(e) {
    -  var textarea = this.getElement();
    -  var height = textarea.offsetHeight;
    -
    -  // This solves for when the MSIE DropShadow filter is enabled,
    -  // as it affects the offsetHeight value, even with MsBoxSizing:border-box.
    -  if (textarea['filters'] && textarea['filters'].length) {
    -    var dropShadow =
    -        textarea['filters']['item']('DXImageTransform.Microsoft.DropShadow');
    -    if (dropShadow) {
    -      height -= dropShadow['offX'];
    -    }
    -  }
    -
    -  if (height != this.height_) {
    -    this.minHeight_ = height;
    -    this.height_ = height;
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/textarea_test.html b/src/database/third_party/closure-library/closure/goog/ui/textarea_test.html
    deleted file mode 100644
    index 15a87cc6033..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/textarea_test.html
    +++ /dev/null
    @@ -1,44 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.Textarea
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.TextareaTest');
    -  </script>
    -  <style>
    -   textarea {
    -      /* Some of the height tests are based on font size px values. */
    -      font-size: 1em;
    -      height: 25px; /* Need to force an initial height < our minHeight. */
    -      width: 150px;
    -      padding: 2px;
    -      margin: 0;
    -      border: 1px solid #000;
    -    }
    -    .drop-shadowed {
    -      filter:progid:DXImageTransform.Microsoft.DropShadow(color='#e7e7e7',
    -          offX='5',offY='5');
    -      box-shadow: 5px 5px 0 #e7e7e7;
    -      -moz-box-shadow: 5px 5px 0 #e7e7e7;
    -      -webkit-box-shadow: 5px 5px 0 #e7e7e7;
    -    }
    -  </style>
    - </head>
    - <body>
    -  <h1>goog.ui.Textarea tests</h1>
    -  <p>Here's a textarea defined in markup:</p>
    -  <textarea id="demo-textarea">Foo</textarea>
    -  <div id="sandbox"></div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/textarea_test.js b/src/database/third_party/closure-library/closure/goog/ui/textarea_test.js
    deleted file mode 100644
    index 9a4aef0d7b9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/textarea_test.js
    +++ /dev/null
    @@ -1,348 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.TextareaTest');
    -goog.setTestOnly('goog.ui.TextareaTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events');
    -goog.require('goog.style');
    -goog.require('goog.testing.ExpectedFailures');
    -goog.require('goog.testing.events.EventObserver');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.Textarea');
    -goog.require('goog.ui.TextareaRenderer');
    -goog.require('goog.userAgent');
    -goog.require('goog.userAgent.product');
    -
    -var sandbox;
    -var textarea;
    -var demoTextareaElement;
    -var expectedFailures;
    -
    -function setUp() {
    -  sandbox = goog.dom.getElement('sandbox');
    -  textarea = new goog.ui.Textarea();
    -  demoTextareaElement = goog.dom.getElement('demo-textarea');
    -  expectedFailures = new goog.testing.ExpectedFailures();
    -}
    -
    -function tearDown() {
    -  expectedFailures.handleTearDown();
    -  textarea.dispose();
    -  goog.dom.removeChildren(sandbox);
    -}
    -
    -
    -/**
    - * @return {boolean} Whether we're on Mac Safari 3.x.
    - */
    -function isMacSafari3() {
    -  return goog.userAgent.WEBKIT && goog.userAgent.MAC &&
    -      !goog.userAgent.isVersionOrHigher('527');
    -}
    -
    -
    -/**
    - * @return {boolean} Whether we're on Linux Firefox 3.6.3.
    - */
    -function isLinuxFirefox() {
    -  return goog.userAgent.product.FIREFOX && goog.userAgent.LINUX;
    -}
    -
    -
    -/**
    - * @return {boolean} Whether we're on Firefox 3.0.
    - */
    -function isFirefox3() {
    -  return goog.userAgent.GECKO &&
    -      !goog.userAgent.isVersionOrHigher('1.9.1');
    -}
    -
    -function testConstructor() {
    -  assertNotNull('Textarea must not be null', textarea);
    -  assertEquals('Renderer must default to expected value',
    -      goog.ui.TextareaRenderer.getInstance(), textarea.getRenderer());
    -
    -  var fakeDomHelper = {
    -    'getDocument': function() { return true; }
    -  };
    -  var testTextarea = new goog.ui.Textarea('Hello',
    -      goog.ui.TextareaRenderer.getInstance(), fakeDomHelper);
    -  assertEquals('Content must have expected content', 'Hello',
    -      testTextarea.getContent());
    -  assertEquals('Renderer must have expected value',
    -      goog.ui.TextareaRenderer.getInstance(), testTextarea.getRenderer());
    -  assertEquals('DOM helper must have expected value', fakeDomHelper,
    -      testTextarea.getDomHelper());
    -  testTextarea.dispose();
    -}
    -
    -function testConstructorWithDecorator() {
    -  var decoratedTextarea = new goog.ui.Textarea();
    -  decoratedTextarea.decorate(demoTextareaElement);
    -  assertEquals('Textarea should have current content after decoration',
    -      'Foo', decoratedTextarea.getContent());
    -  var initialHeight = decoratedTextarea.getHeight_();
    -  var initialOffsetHeight = decoratedTextarea.getElement().offsetHeight;
    -  // focus() will trigger the grow/shrink flow.
    -  decoratedTextarea.getElement().focus();
    -  assertEquals('Height should not have changed without content change',
    -      initialHeight, decoratedTextarea.getHeight_());
    -  assertEquals('offsetHeight should not have changed without content ' +
    -      'change', initialOffsetHeight,
    -      decoratedTextarea.getElement().offsetHeight);
    -  decoratedTextarea.dispose();
    -}
    -
    -function testGetSetContent() {
    -  textarea.render(sandbox);
    -  assertEquals('Textarea\'s content must default to an empty string',
    -      '', textarea.getContent());
    -  textarea.setContent(17);
    -  assertEquals('Textarea element must have expected content', '17',
    -      textarea.getElement().value);
    -  textarea.setContent('foo');
    -  assertEquals('Textarea element must have updated content', 'foo',
    -      textarea.getElement().value);
    -}
    -
    -function testGetSetValue() {
    -  textarea.render(sandbox);
    -  assertEquals('Textarea\'s content must default to an empty string',
    -      '', textarea.getValue());
    -  textarea.setValue(17);
    -  assertEquals('Textarea element must have expected content', '17',
    -      textarea.getValue());
    -  textarea.setValue('17');
    -  assertEquals('Textarea element must have expected content', '17',
    -      textarea.getValue());
    -}
    -
    -function testBasicTextareaBehavior() {
    -  var observer = new goog.testing.events.EventObserver();
    -  goog.events.listen(textarea, goog.ui.Textarea.EventType.RESIZE, observer);
    -  textarea.render(sandbox);
    -  var el = textarea.getElement();
    -  var heightBefore = textarea.getHeight_();
    -  assertTrue('One resize event should be fired during render',
    -      observer.getEvents().length == 1);
    -  textarea.setContent('Lorem ipsum dolor sit amet, consectetuer ' +
    -      'elit. Aenean sollicitudin ultrices urna. Proin vehicula mauris ac ' +
    -      'est. Ut scelerisque, risus ut facilisis dictum, est massa lacinia ' +
    -      'lorem, in fermentum purus ligula quis nunc.');
    -  var heightAfter = textarea.getHeight_();
    -  assertTrue('With this much content, height should have grown.',
    -      heightAfter > heightBefore);
    -  assertTrue('With a height change, a resize event should have fired.',
    -      observer.getEvents().length == 2);
    -  textarea.setContent('');
    -  heightAfter = textarea.getHeight_();
    -  assertTrue('Textarea should shrink with no content.',
    -      heightAfter <= heightBefore);
    -  assertTrue('With a height change, a resize event should have fired.',
    -      observer.getEvents().length == 3);
    -  goog.events.unlisten(textarea, goog.ui.Textarea.EventType.RESIZE,
    -      observer);
    -}
    -
    -function testMinHeight() {
    -  textarea.render(sandbox);
    -  textarea.setMinHeight(50);
    -  assertEquals('offsetHeight should be 50 initially', 50,
    -      textarea.getElement().offsetHeight);
    -  textarea.setContent('Lorem ipsum dolor sit amet, consectetuer  ' +
    -      'elit. Aenean sollicitudin ultrices urna. Proin vehicula mauris ac ' +
    -      'est. Ut scelerisque, risus ut facilisis dictum, est massa lacinia ' +
    -      'lorem, in fermentum purus ligula quis nunc.');
    -  assertTrue('getHeight_() should be > 50',
    -      textarea.getHeight_() > 50);
    -
    -  textarea.setContent('');
    -  assertEquals('With no content, offsetHeight should go back to 50, ' +
    -      'the minHeight.', 50, textarea.getElement().offsetHeight);
    -
    -  expectedFailures.expectFailureFor(isMacSafari3());
    -  try {
    -    textarea.setMinHeight(0);
    -    assertTrue('After setting minHeight to 0, offsetHeight should ' +
    -        'now be < 50, but it is ' + textarea.getElement().offsetHeight,
    -        textarea.getElement().offsetHeight < 50);
    -  } catch (e) {
    -    expectedFailures.handleException(e);
    -  }
    -}
    -
    -function testMouseUpListener() {
    -  textarea.render(sandbox);
    -  textarea.setMinHeight(100);
    -  textarea.setMaxHeight(200);
    -  textarea.mouseUpListener_({});
    -  assertEquals('After a mouseup which is not a resize, minHeight should ' +
    -      'still be 100', 100, textarea.minHeight_);
    -
    -  // We need to test how CSS drop shadows effect this too.
    -  goog.dom.classlist.add(textarea.getElement(), 'drop-shadowed');
    -  textarea.mouseUpListener_({});
    -  assertEquals('After a mouseup which is not a resize, minHeight should ' +
    -      'still be 100 even with a shadow', 100, textarea.minHeight_);
    -
    -}
    -
    -function testMaxHeight() {
    -  textarea.render(sandbox);
    -  textarea.setMaxHeight(50);
    -  assertTrue('Initial offsetHeight should be less than 50',
    -      textarea.getElement().offsetHeight < 50);
    -  var newContent = 'Lorem ipsum dolor sit amet, consectetuer adipiscing ' +
    -      'elit. Aenean sollicitudin ultrices urna. Proin vehicula mauris ac ' +
    -      'est. Ut scelerisque, risus ut facilisis dictum, est massa lacinia ' +
    -      'lorem, in fermentum purus ligula quis nunc.';
    -  textarea.setContent(newContent);
    -
    -  assertTrue('With lots of content, getHeight_() should be > 50',
    -      textarea.getHeight_() > 50);
    -  assertEquals('Even with lots of content, offsetHeight should be 50 ' +
    -      'with maxHeight set', 50, textarea.getElement().offsetHeight);
    -  textarea.setMaxHeight(0);
    -  assertTrue('After setting maxHeight to 0, offsetHeight should now ' +
    -      'be > 50', textarea.getElement().offsetHeight > 50);
    -}
    -
    -function testMaxHeight_canShrink() {
    -  textarea.render(sandbox);
    -  textarea.setMaxHeight(50);
    -  assertTrue('Initial offsetHeight should be less than 50',
    -      textarea.getElement().offsetHeight < 50);
    -  var newContent = 'Lorem ipsum dolor sit amet, consectetuer adipiscing ' +
    -      'elit. Aenean sollicitudin ultrices urna. Proin vehicula mauris ac ' +
    -      'est. Ut scelerisque, risus ut facilisis dictum, est massa lacinia ' +
    -      'lorem, in fermentum purus ligula quis nunc.';
    -  textarea.setContent(newContent);
    -
    -  assertEquals('Even with lots of content, offsetHeight should be 50 ' +
    -      'with maxHeight set', 50, textarea.getElement().offsetHeight);
    -  textarea.setContent('');
    -  assertTrue('With no content, offsetHeight should be back to < 50',
    -      textarea.getElement().offsetHeight < 50);
    -}
    -
    -function testSetPlaceholder() {
    -  textarea.setPlaceholder('Some default text here.');
    -  textarea.setPlaceholder('new default text...');
    -  textarea.render(sandbox);
    -  if (textarea.supportsNativePlaceholder_()) {
    -    assertEquals('new default text...', textarea.getElement().placeholder);
    -  }
    -  assertEquals('', textarea.getValue());
    -  textarea.setValue('some value');
    -  assertEquals('some value', textarea.getValue());
    -  // ensure setting a new placeholder doesn't replace the value.
    -  textarea.setPlaceholder('some new placeholder');
    -  assertEquals('some value', textarea.getValue());
    -}
    -
    -function testSetPlaceholderForInitialContent() {
    -  var testTextarea = new goog.ui.Textarea('initial content');
    -  testTextarea.render(sandbox);
    -  assertEquals('initial content', testTextarea.getValue());
    -  testTextarea.setPlaceholder('new default text...');
    -  assertEquals('initial content', testTextarea.getValue());
    -  testTextarea.setValue('new content');
    -  assertEquals('new content', testTextarea.getValue());
    -  testTextarea.setValue('');
    -  assertEquals('', testTextarea.getValue());
    -  if (!testTextarea.supportsNativePlaceholder_()) {
    -    // Pretend we leave the textarea. When that happens, the
    -    // placeholder text should appear.
    -    assertEquals('', testTextarea.getElement().value);
    -    testTextarea.blur_();
    -    assertEquals('new default text...', testTextarea.getElement().value);
    -  }
    -}
    -
    -function testMinAndMaxHeight() {
    -  textarea.render(sandbox);
    -  textarea.setMinHeight(50);
    -  textarea.setMaxHeight(150);
    -  assertEquals('offsetHeight should be 50 initially', 50,
    -      textarea.getElement().offsetHeight);
    -
    -  textarea.setContent('Lorem ipsum dolor sit amet, consectetuer  ' +
    -      'elit. Aenean sollicitudin ultrices urna. Proin vehicula mauris ac ' +
    -      'est. Ut scelerisque, risus ut facilisis dictum, est massa lacinia ' +
    -      'lorem, in fermentum purus ligula quis nunc.');
    -
    -  var height = textarea.getHeight_();
    -  // For some reason Mac Safari 3 has 136 and Linux FF has 146 here.
    -  expectedFailures.expectFailureFor(isMacSafari3() || isLinuxFirefox());
    -  try {
    -    assertTrue('With lots of content, getHeight_() should be > 150 ' +
    -        '(it is ' + height + ')', height > 150);
    -    assertEquals('Even with lots of content, offsetHeight should be 150 ' +
    -        'with maxHeight set', 150,
    -        textarea.getElement().offsetHeight);
    -
    -    textarea.setMaxHeight(0);
    -    assertTrue('After setting maxHeight to 0, offsetHeight should now ' +
    -        'be > 150 (it is ' + textarea.getElement().offsetHeight + ')',
    -        textarea.getElement().offsetHeight > 150);
    -
    -    textarea.setContent('');
    -    textarea.setMinHeight(0);
    -    assertTrue('After setting minHeight to 0, with no contents, ' +
    -        'offsetHeight should now be < 50',
    -        textarea.getElement().offsetHeight < 50);
    -  } catch (e) {
    -    expectedFailures.handleException(e);
    -  }
    -}
    -
    -function testSetValueWhenInvisible() {
    -  textarea.render(sandbox);
    -  var content = 'Lorem ipsum dolor sit amet, consectetuer  ' +
    -      'elit. Aenean sollicitudin ultrices urna. Proin vehicula mauris ac ' +
    -      'est. Ut scelerisque, risus ut facilisis dictum, est massa lacinia ' +
    -      'lorem, in fermentum purus ligula quis nunc.';
    -  textarea.setValue(content);
    -  var height = textarea.getHeight_();
    -  var elementHeight = goog.style.getStyle(textarea.getElement(), 'height');
    -  assertEquals(height + 'px', elementHeight);
    -
    -  // Hide the element, height_ should be invalidate when setValue().
    -  goog.style.setElementShown(textarea.getElement(), false);
    -  textarea.setValue(content);
    -
    -  // Show the element again.
    -  goog.style.setElementShown(textarea.getElement(), true);
    -  textarea.setValue(content);
    -  height = textarea.getHeight_();
    -  elementHeight = goog.style.getStyle(textarea.getElement(), 'height');
    -  assertEquals(height + 'px', elementHeight);
    -}
    -
    -function testSetAriaLabel() {
    -  assertNull('Textarea must not have aria label by default',
    -      textarea.getAriaLabel());
    -  textarea.setAriaLabel('My textarea');
    -  textarea.render(sandbox);
    -  var element = textarea.getElementStrict();
    -  assertNotNull('Element must not be null', element);
    -  assertEquals('Item element must have expected aria-label', 'My textarea',
    -      element.getAttribute('aria-label'));
    -  textarea.setAriaLabel('My new textarea');
    -  assertEquals('Item element must have updated aria-label', 'My new textarea',
    -      element.getAttribute('aria-label'));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/textarearenderer.js b/src/database/third_party/closure-library/closure/goog/ui/textarearenderer.js
    deleted file mode 100644
    index a888e5da1d2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/textarearenderer.js
    +++ /dev/null
    @@ -1,170 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//     http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Native browser textarea renderer for {@link goog.ui.Textarea}s.
    - */
    -
    -goog.provide('goog.ui.TextareaRenderer');
    -
    -goog.require('goog.dom.TagName');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.ControlRenderer');
    -
    -
    -
    -/**
    - * Renderer for {@link goog.ui.Textarea}s.  Renders and decorates native HTML
    - * textarea elements.  Since native HTML textareas have built-in support for
    - * many features, overrides many expensive (and redundant) superclass methods to
    - * be no-ops.
    - * @constructor
    - * @extends {goog.ui.ControlRenderer}
    - * @final
    - */
    -goog.ui.TextareaRenderer = function() {
    -  goog.ui.ControlRenderer.call(this);
    -};
    -goog.inherits(goog.ui.TextareaRenderer, goog.ui.ControlRenderer);
    -goog.addSingletonGetter(goog.ui.TextareaRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.TextareaRenderer.CSS_CLASS = goog.getCssName('goog-textarea');
    -
    -
    -/** @override */
    -goog.ui.TextareaRenderer.prototype.getAriaRole = function() {
    -  // textareas don't need ARIA roles to be recognized by screen readers.
    -  return undefined;
    -};
    -
    -
    -/** @override */
    -goog.ui.TextareaRenderer.prototype.decorate = function(control, element) {
    -  this.setUpTextarea_(control);
    -  goog.ui.TextareaRenderer.superClass_.decorate.call(this, control,
    -      element);
    -  control.setContent(element.value);
    -  return element;
    -};
    -
    -
    -/**
    - * Returns the textarea's contents wrapped in an HTML textarea element.  Sets
    - * the textarea's disabled attribute as needed.
    - * @param {goog.ui.Control} textarea Textarea to render.
    - * @return {!Element} Root element for the Textarea control (an HTML textarea
    - *     element).
    - * @override
    - */
    -goog.ui.TextareaRenderer.prototype.createDom = function(textarea) {
    -  this.setUpTextarea_(textarea);
    -  var element = textarea.getDomHelper().createDom('textarea', {
    -    'class': this.getClassNames(textarea).join(' '),
    -    'disabled': !textarea.isEnabled()
    -  }, textarea.getContent() || '');
    -  return element;
    -};
    -
    -
    -/**
    - * Overrides {@link goog.ui.TextareaRenderer#canDecorate} by returning true only
    - * if the element is an HTML textarea.
    - * @param {Element} element Element to decorate.
    - * @return {boolean} Whether the renderer can decorate the element.
    - * @override
    - */
    -goog.ui.TextareaRenderer.prototype.canDecorate = function(element) {
    -  return element.tagName == goog.dom.TagName.TEXTAREA;
    -};
    -
    -
    -/**
    - * Textareas natively support right-to-left rendering.
    - * @override
    - */
    -goog.ui.TextareaRenderer.prototype.setRightToLeft = goog.nullFunction;
    -
    -
    -/**
    - * Textareas are always focusable as long as they are enabled.
    - * @override
    - */
    -goog.ui.TextareaRenderer.prototype.isFocusable = function(textarea) {
    -  return textarea.isEnabled();
    -};
    -
    -
    -/**
    - * Textareas natively support keyboard focus.
    - * @override
    - */
    -goog.ui.TextareaRenderer.prototype.setFocusable = goog.nullFunction;
    -
    -
    -/**
    - * Textareas also expose the DISABLED state in the HTML textarea's
    - * {@code disabled} attribute.
    - * @override
    - */
    -goog.ui.TextareaRenderer.prototype.setState = function(textarea, state,
    -    enable) {
    -  goog.ui.TextareaRenderer.superClass_.setState.call(this, textarea, state,
    -      enable);
    -  var element = textarea.getElement();
    -  if (element && state == goog.ui.Component.State.DISABLED) {
    -    element.disabled = enable;
    -  }
    -};
    -
    -
    -/**
    - * Textareas don't need ARIA states to support accessibility, so this is
    - * a no-op.
    - * @override
    - */
    -goog.ui.TextareaRenderer.prototype.updateAriaState = goog.nullFunction;
    -
    -
    -/**
    - * Sets up the textarea control such that it doesn't waste time adding
    - * functionality that is already natively supported by browser
    - * textareas.
    - * @param {goog.ui.Control} textarea Textarea control to configure.
    - * @private
    - */
    -goog.ui.TextareaRenderer.prototype.setUpTextarea_ = function(textarea) {
    -  textarea.setHandleMouseEvents(false);
    -  textarea.setAutoStates(goog.ui.Component.State.ALL, false);
    -  textarea.setSupportedState(goog.ui.Component.State.FOCUSED, false);
    -};
    -
    -
    -/** @override **/
    -goog.ui.TextareaRenderer.prototype.setContent = function(element, value) {
    -  if (element) {
    -    element.value = value;
    -  }
    -};
    -
    -
    -/** @override **/
    -goog.ui.TextareaRenderer.prototype.getCssClass = function() {
    -  return goog.ui.TextareaRenderer.CSS_CLASS;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/togglebutton.js b/src/database/third_party/closure-library/closure/goog/ui/togglebutton.js
    deleted file mode 100644
    index 3e9bdb01c73..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/togglebutton.js
    +++ /dev/null
    @@ -1,58 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A toggle button control.  Extends {@link goog.ui.Button} by
    - * providing checkbox-like semantics.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.ToggleButton');
    -
    -goog.require('goog.ui.Button');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.CustomButtonRenderer');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * A toggle button, with checkbox-like semantics.  Rendered using
    - * {@link goog.ui.CustomButtonRenderer} by default, though any
    - * {@link goog.ui.ButtonRenderer} would work.
    - *
    - * @param {goog.ui.ControlContent} content Text caption or existing DOM
    - *     structure to display as the button's caption.
    - * @param {goog.ui.ButtonRenderer=} opt_renderer Renderer used to render or
    - *     decorate the button; defaults to {@link goog.ui.CustomButtonRenderer}.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @constructor
    - * @extends {goog.ui.Button}
    - */
    -goog.ui.ToggleButton = function(content, opt_renderer, opt_domHelper) {
    -  goog.ui.Button.call(this, content, opt_renderer ||
    -      goog.ui.CustomButtonRenderer.getInstance(), opt_domHelper);
    -  this.setSupportedState(goog.ui.Component.State.CHECKED, true);
    -};
    -goog.inherits(goog.ui.ToggleButton, goog.ui.Button);
    -
    -
    -// Register a decorator factory function for goog.ui.ToggleButtons.
    -goog.ui.registry.setDecoratorByClassName(
    -    goog.getCssName('goog-toggle-button'), function() {
    -      // ToggleButton defaults to using CustomButtonRenderer.
    -      return new goog.ui.ToggleButton(null);
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/toolbar.js b/src/database/third_party/closure-library/closure/goog/ui/toolbar.js
    deleted file mode 100644
    index 45c25fb5caa..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/toolbar.js
    +++ /dev/null
    @@ -1,59 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A toolbar class that hosts {@link goog.ui.Control}s such as
    - * buttons and menus, along with toolbar-specific renderers of those controls.
    - *
    - * @author attila@google.com (Attila Bodis)
    - * @see ../demos/toolbar.html
    - */
    -
    -goog.provide('goog.ui.Toolbar');
    -
    -goog.require('goog.ui.Container');
    -goog.require('goog.ui.ToolbarRenderer');
    -
    -
    -
    -/**
    - * A toolbar class, implemented as a {@link goog.ui.Container} that defaults to
    - * having a horizontal orientation and {@link goog.ui.ToolbarRenderer} as its
    - * renderer.
    - * @param {goog.ui.ToolbarRenderer=} opt_renderer Renderer used to render or
    - *     decorate the toolbar; defaults to {@link goog.ui.ToolbarRenderer}.
    - * @param {?goog.ui.Container.Orientation=} opt_orientation Toolbar orientation;
    - *     defaults to {@code HORIZONTAL}.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @constructor
    - * @extends {goog.ui.Container}
    - */
    -goog.ui.Toolbar = function(opt_renderer, opt_orientation, opt_domHelper) {
    -  goog.ui.Container.call(this, opt_orientation, opt_renderer ||
    -      goog.ui.ToolbarRenderer.getInstance(), opt_domHelper);
    -};
    -goog.inherits(goog.ui.Toolbar, goog.ui.Container);
    -
    -
    -/** @override */
    -goog.ui.Toolbar.prototype.handleFocus = function(e) {
    -  goog.ui.Toolbar.base(this, 'handleFocus', e);
    -  // Highlight the first highlightable item on focus via the keyboard for ARIA
    -  // spec compliance. Do not highlight the item if the mouse button is pressed,
    -  // since this method is also called from handleMouseDown when a toolbar button
    -  // is clicked.
    -  if (!this.isMouseButtonPressed()) {
    -    this.highlightFirst();
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/toolbar_test.html b/src/database/third_party/closure-library/closure/goog/ui/toolbar_test.html
    deleted file mode 100644
    index e44f32bc683..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/toolbar_test.html
    +++ /dev/null
    @@ -1,26 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.Toolbar
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.ToolbarTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="toolbar-wrapper">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/toolbar_test.js b/src/database/third_party/closure-library/closure/goog/ui/toolbar_test.js
    deleted file mode 100644
    index e8b8cbe0843..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/toolbar_test.js
    +++ /dev/null
    @@ -1,92 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.ToolbarTest');
    -goog.setTestOnly('goog.ui.ToolbarTest');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.dom');
    -goog.require('goog.events.EventType');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.events.Event');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.Toolbar');
    -goog.require('goog.ui.ToolbarMenuButton');
    -
    -var toolbar;
    -var toolbarWrapper;
    -var buttons;
    -
    -function setUp() {
    -  toolbar = new goog.ui.Toolbar();
    -  toolbarWrapper = goog.dom.getElement('toolbar-wrapper');
    -
    -  // Render and populate the toolbar.
    -  toolbar.render(toolbarWrapper);
    -  var toolbarElem = toolbar.getElement();
    -  var button1 = new goog.ui.ToolbarMenuButton('button 1');
    -  var button2 = new goog.ui.ToolbarMenuButton('button 2');
    -  var button3 = new goog.ui.ToolbarMenuButton('button 3');
    -  button1.render(toolbarElem);
    -  button2.render(toolbarElem);
    -  button3.render(toolbarElem);
    -  toolbar.addChild(button1);
    -  toolbar.addChild(button2);
    -  toolbar.addChild(button3);
    -  buttons = [button1, button2, button3];
    -}
    -
    -function tearDown() {
    -  toolbar.dispose();
    -}
    -
    -function testHighlightFirstOnFocus() {
    -  var firstButton = buttons[0];
    -
    -  // Verify that focusing the toolbar via the keyboard (i.e. no click event)
    -  // highlights the first item and sets it as the active descendant.
    -  goog.testing.events.fireFocusEvent(toolbar.getElement());
    -  assertEquals(0, toolbar.getHighlightedIndex());
    -  assertTrue(firstButton.isHighlighted());
    -  assertEquals(
    -      firstButton.getElement(),
    -      goog.a11y.aria.getActiveDescendant(toolbar.getElement()));
    -
    -  // Verify that removing focus unhighlights the first item and removes it as
    -  // the active descendant.
    -  goog.testing.events.fireBlurEvent(toolbar.getElement());
    -  assertEquals(-1, toolbar.getHighlightedIndex());
    -  assertNull(goog.a11y.aria.getActiveDescendant(toolbar.getElement()));
    -  assertFalse(firstButton.isHighlighted());
    -}
    -
    -function testHighlightSelectedOnClick() {
    -  var firstButton = buttons[0];
    -  var secondButton = buttons[1];
    -
    -  // Verify that mousing over and clicking on a toolbar button selects only the
    -  // correct item.
    -  var mouseover = new goog.testing.events.Event(
    -      goog.events.EventType.MOUSEOVER, secondButton.getElement());
    -  goog.testing.events.fireBrowserEvent(mouseover);
    -  var mousedown = new goog.testing.events.Event(
    -      goog.events.EventType.MOUSEDOWN, toolbar.getElement());
    -  goog.testing.events.fireBrowserEvent(mousedown);
    -  assertEquals(1, toolbar.getHighlightedIndex());
    -  assertTrue(secondButton.isHighlighted());
    -  assertFalse(firstButton.isHighlighted());
    -  assertEquals(
    -      secondButton.getElement(),
    -      goog.a11y.aria.getActiveDescendant(toolbar.getElement()));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/toolbarbutton.js b/src/database/third_party/closure-library/closure/goog/ui/toolbarbutton.js
    deleted file mode 100644
    index 1582b62f957..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/toolbarbutton.js
    +++ /dev/null
    @@ -1,54 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A toolbar button control.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.ToolbarButton');
    -
    -goog.require('goog.ui.Button');
    -goog.require('goog.ui.ToolbarButtonRenderer');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * A button control for a toolbar.
    - *
    - * @param {goog.ui.ControlContent} content Text caption or existing DOM
    - *     structure to display as the button's caption.
    - * @param {goog.ui.ButtonRenderer=} opt_renderer Optional renderer used to
    - *     render or decorate the button; defaults to
    - *     {@link goog.ui.ToolbarButtonRenderer}.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @constructor
    - * @extends {goog.ui.Button}
    - */
    -goog.ui.ToolbarButton = function(content, opt_renderer, opt_domHelper) {
    -  goog.ui.Button.call(this, content, opt_renderer ||
    -      goog.ui.ToolbarButtonRenderer.getInstance(), opt_domHelper);
    -};
    -goog.inherits(goog.ui.ToolbarButton, goog.ui.Button);
    -
    -
    -// Registers a decorator factory function for toolbar buttons.
    -goog.ui.registry.setDecoratorByClassName(
    -    goog.ui.ToolbarButtonRenderer.CSS_CLASS,
    -    function() {
    -      return new goog.ui.ToolbarButton(null);
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/toolbarbuttonrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/toolbarbuttonrenderer.js
    deleted file mode 100644
    index 155727b6575..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/toolbarbuttonrenderer.js
    +++ /dev/null
    @@ -1,57 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Renderer for toolbar buttons.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.ToolbarButtonRenderer');
    -
    -goog.require('goog.ui.CustomButtonRenderer');
    -
    -
    -
    -/**
    - * Toolbar-specific renderer for {@link goog.ui.Button}s, based on {@link
    - * goog.ui.CustomButtonRenderer}.
    - * @constructor
    - * @extends {goog.ui.CustomButtonRenderer}
    - */
    -goog.ui.ToolbarButtonRenderer = function() {
    -  goog.ui.CustomButtonRenderer.call(this);
    -};
    -goog.inherits(goog.ui.ToolbarButtonRenderer, goog.ui.CustomButtonRenderer);
    -goog.addSingletonGetter(goog.ui.ToolbarButtonRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of buttons rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.ToolbarButtonRenderer.CSS_CLASS =
    -    goog.getCssName('goog-toolbar-button');
    -
    -
    -/**
    - * Returns the CSS class to be applied to the root element of buttons rendered
    - * using this renderer.
    - * @return {string} Renderer-specific CSS class.
    - * @override
    - */
    -goog.ui.ToolbarButtonRenderer.prototype.getCssClass = function() {
    -  return goog.ui.ToolbarButtonRenderer.CSS_CLASS;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/toolbarcolormenubutton.js b/src/database/third_party/closure-library/closure/goog/ui/toolbarcolormenubutton.js
    deleted file mode 100644
    index 3df6918056a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/toolbarcolormenubutton.js
    +++ /dev/null
    @@ -1,57 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A toolbar color menu button control.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.ToolbarColorMenuButton');
    -
    -goog.require('goog.ui.ColorMenuButton');
    -goog.require('goog.ui.ToolbarColorMenuButtonRenderer');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * A color menu button control for a toolbar.
    - *
    - * @param {goog.ui.ControlContent} content Text caption or existing DOM
    - *     structure to display as the button's caption.
    - * @param {goog.ui.Menu=} opt_menu Menu to render under the button when clicked;
    - *     should contain at least one {@link goog.ui.ColorPalette} if present.
    - * @param {goog.ui.ColorMenuButtonRenderer=} opt_renderer Optional
    - *     renderer used to render or decorate the button; defaults to
    - *     {@link goog.ui.ToolbarColorMenuButtonRenderer}.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @constructor
    - * @extends {goog.ui.ColorMenuButton}
    - */
    -goog.ui.ToolbarColorMenuButton = function(
    -    content, opt_menu, opt_renderer, opt_domHelper) {
    -  goog.ui.ColorMenuButton.call(this, content, opt_menu, opt_renderer ||
    -      goog.ui.ToolbarColorMenuButtonRenderer.getInstance(), opt_domHelper);
    -};
    -goog.inherits(goog.ui.ToolbarColorMenuButton, goog.ui.ColorMenuButton);
    -
    -
    -// Registers a decorator factory function for toolbar color menu buttons.
    -goog.ui.registry.setDecoratorByClassName(
    -    goog.getCssName('goog-toolbar-color-menu-button'),
    -    function() {
    -      return new goog.ui.ToolbarColorMenuButton(null);
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/toolbarcolormenubuttonrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/toolbarcolormenubuttonrenderer.js
    deleted file mode 100644
    index 23954b4054b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/toolbarcolormenubuttonrenderer.js
    +++ /dev/null
    @@ -1,101 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A toolbar-style renderer for {@link goog.ui.ColorMenuButton}.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.ToolbarColorMenuButtonRenderer');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.ui.ColorMenuButtonRenderer');
    -goog.require('goog.ui.MenuButtonRenderer');
    -goog.require('goog.ui.ToolbarMenuButtonRenderer');
    -
    -
    -
    -/**
    - * Toolbar-style renderer for {@link goog.ui.ColorMenuButton}s.
    - * @constructor
    - * @extends {goog.ui.ToolbarMenuButtonRenderer}
    - * @final
    - */
    -goog.ui.ToolbarColorMenuButtonRenderer = function() {
    -  goog.ui.ToolbarMenuButtonRenderer.call(this);
    -};
    -goog.inherits(goog.ui.ToolbarColorMenuButtonRenderer,
    -              goog.ui.ToolbarMenuButtonRenderer);
    -goog.addSingletonGetter(goog.ui.ToolbarColorMenuButtonRenderer);
    -
    -
    -/**
    - * Overrides the superclass implementation by wrapping the caption text or DOM
    - * structure in a color indicator element.  Creates the following DOM structure:
    - *   <div class="goog-inline-block goog-toolbar-menu-button-caption">
    - *     <div class="goog-color-menu-button-indicator">
    - *       Contents...
    - *     </div>
    - *   </div>
    - * @param {goog.ui.ControlContent} content Text caption or DOM structure.
    - * @param {goog.dom.DomHelper} dom DOM helper, used for document interaction.
    - * @return {!Element} Caption element.
    - * @see goog.ui.ToolbarColorMenuButtonRenderer#createColorIndicator
    - * @override
    - */
    -goog.ui.ToolbarColorMenuButtonRenderer.prototype.createCaption = function(
    -    content, dom) {
    -  return goog.ui.MenuButtonRenderer.wrapCaption(
    -      goog.ui.ColorMenuButtonRenderer.wrapCaption(content, dom),
    -      this.getCssClass(),
    -      dom);
    -};
    -
    -
    -/**
    - * Takes a color menu button control's root element and a value object
    - * (which is assumed to be a color), and updates the button's DOM to reflect
    - * the new color.  Overrides {@link goog.ui.ButtonRenderer#setValue}.
    - * @param {Element} element The button control's root element (if rendered).
    - * @param {*} value New value; assumed to be a color spec string.
    - * @override
    - */
    -goog.ui.ToolbarColorMenuButtonRenderer.prototype.setValue = function(element,
    -    value) {
    -  if (element) {
    -    goog.ui.ColorMenuButtonRenderer.setCaptionValue(
    -        this.getContentElement(element), value);
    -  }
    -};
    -
    -
    -/**
    - * Initializes the button's DOM when it enters the document.  Overrides the
    - * superclass implementation by making sure the button's color indicator is
    - * initialized.
    - * @param {goog.ui.Control} button goog.ui.ColorMenuButton whose DOM is to be
    - *     initialized as it enters the document.
    - * @override
    - */
    -goog.ui.ToolbarColorMenuButtonRenderer.prototype.initializeDom = function(
    -    button) {
    -  this.setValue(button.getElement(), button.getValue());
    -  goog.dom.classlist.add(
    -      goog.asserts.assert(button.getElement()),
    -      goog.getCssName('goog-toolbar-color-menu-button'));
    -  goog.ui.ToolbarColorMenuButtonRenderer.superClass_.initializeDom.call(this,
    -      button);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/toolbarcolormenubuttonrenderer_test.html b/src/database/third_party/closure-library/closure/goog/ui/toolbarcolormenubuttonrenderer_test.html
    deleted file mode 100644
    index b1c289c0e4e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/toolbarcolormenubuttonrenderer_test.html
    +++ /dev/null
    @@ -1,33 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -
    -  @author nicksantos@google.com (Nick Santos)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests for ToolbarColorMenuButtonRenderer
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.ToolbarColorMenuButtonRendererTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="root">
    -   <!-- A parent to attach rendered buttons to -->
    -   <div id="parent">
    -   </div>
    -   <!-- A button to decorate -->
    -   <div id="decoratedButton"><div>Foo</div></div>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/toolbarcolormenubuttonrenderer_test.js b/src/database/third_party/closure-library/closure/goog/ui/toolbarcolormenubuttonrenderer_test.js
    deleted file mode 100644
    index 7f444f40336..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/toolbarcolormenubuttonrenderer_test.js
    +++ /dev/null
    @@ -1,50 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.ToolbarColorMenuButtonRendererTest');
    -goog.setTestOnly('goog.ui.ToolbarColorMenuButtonRendererTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.testing.ui.RendererHarness');
    -goog.require('goog.testing.ui.rendererasserts');
    -goog.require('goog.ui.ToolbarColorMenuButton');
    -goog.require('goog.ui.ToolbarColorMenuButtonRenderer');
    -
    -var harness;
    -
    -function setUp() {
    -  harness = new goog.testing.ui.RendererHarness(
    -      goog.ui.ToolbarColorMenuButtonRenderer.getInstance(),
    -      goog.dom.getElement('parent'),
    -      goog.dom.getElement('decoratedButton'));
    -}
    -
    -function tearDown() {
    -  harness.dispose();
    -}
    -
    -function testEquality() {
    -  harness.attachControlAndRender(
    -      new goog.ui.ToolbarColorMenuButton('Foo'));
    -  harness.attachControlAndDecorate(
    -      new goog.ui.ToolbarColorMenuButton());
    -  harness.assertDomMatches();
    -}
    -
    -function testDoesntCallGetCssClassInConstructor() {
    -  goog.testing.ui.rendererasserts.
    -      assertNoGetCssClassCallsInConstructor(
    -          goog.ui.ToolbarColorMenuButtonRenderer);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/toolbarmenubutton.js b/src/database/third_party/closure-library/closure/goog/ui/toolbarmenubutton.js
    deleted file mode 100644
    index e3ecee2fdc4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/toolbarmenubutton.js
    +++ /dev/null
    @@ -1,56 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A toolbar menu button control.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.ToolbarMenuButton');
    -
    -goog.require('goog.ui.MenuButton');
    -goog.require('goog.ui.ToolbarMenuButtonRenderer');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * A menu button control for a toolbar.
    - *
    - * @param {goog.ui.ControlContent} content Text caption or existing DOM
    - *     structure to display as the button's caption.
    - * @param {goog.ui.Menu=} opt_menu Menu to render under the button when clicked.
    - * @param {goog.ui.ButtonRenderer=} opt_renderer Optional renderer used to
    - *     render or decorate the button; defaults to
    - *     {@link goog.ui.ToolbarMenuButtonRenderer}.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @constructor
    - * @extends {goog.ui.MenuButton}
    - */
    -goog.ui.ToolbarMenuButton = function(
    -    content, opt_menu, opt_renderer, opt_domHelper) {
    -  goog.ui.MenuButton.call(this, content, opt_menu, opt_renderer ||
    -      goog.ui.ToolbarMenuButtonRenderer.getInstance(), opt_domHelper);
    -};
    -goog.inherits(goog.ui.ToolbarMenuButton, goog.ui.MenuButton);
    -
    -
    -// Registers a decorator factory function for toolbar menu buttons.
    -goog.ui.registry.setDecoratorByClassName(
    -    goog.ui.ToolbarMenuButtonRenderer.CSS_CLASS,
    -    function() {
    -      return new goog.ui.ToolbarMenuButton(null);
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/toolbarmenubuttonrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/toolbarmenubuttonrenderer.js
    deleted file mode 100644
    index 3c5ffe017f3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/toolbarmenubuttonrenderer.js
    +++ /dev/null
    @@ -1,57 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A toolbar menu button renderer.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.ToolbarMenuButtonRenderer');
    -
    -goog.require('goog.ui.MenuButtonRenderer');
    -
    -
    -
    -/**
    - * Toolbar-specific renderer for {@link goog.ui.MenuButton}s, based on {@link
    - * goog.ui.MenuButtonRenderer}.
    - * @constructor
    - * @extends {goog.ui.MenuButtonRenderer}
    - */
    -goog.ui.ToolbarMenuButtonRenderer = function() {
    -  goog.ui.MenuButtonRenderer.call(this);
    -};
    -goog.inherits(goog.ui.ToolbarMenuButtonRenderer, goog.ui.MenuButtonRenderer);
    -goog.addSingletonGetter(goog.ui.ToolbarMenuButtonRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of menu buttons rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.ToolbarMenuButtonRenderer.CSS_CLASS =
    -    goog.getCssName('goog-toolbar-menu-button');
    -
    -
    -/**
    - * Returns the CSS class to be applied to the root element of menu buttons
    - * rendered using this renderer.
    - * @return {string} Renderer-specific CSS class.
    - * @override
    - */
    -goog.ui.ToolbarMenuButtonRenderer.prototype.getCssClass = function() {
    -  return goog.ui.ToolbarMenuButtonRenderer.CSS_CLASS;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/toolbarrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/toolbarrenderer.js
    deleted file mode 100644
    index 316814c266b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/toolbarrenderer.js
    +++ /dev/null
    @@ -1,89 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Renderer for {@link goog.ui.Toolbar}s.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.ToolbarRenderer');
    -
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.ui.Container');
    -goog.require('goog.ui.ContainerRenderer');
    -goog.require('goog.ui.Separator');
    -goog.require('goog.ui.ToolbarSeparatorRenderer');
    -
    -
    -
    -/**
    - * Default renderer for {@link goog.ui.Toolbar}s, based on {@link
    - * goog.ui.ContainerRenderer}.
    - * @constructor
    - * @extends {goog.ui.ContainerRenderer}
    - */
    -goog.ui.ToolbarRenderer = function() {
    -  goog.ui.ContainerRenderer.call(this, goog.a11y.aria.Role.TOOLBAR);
    -};
    -goog.inherits(goog.ui.ToolbarRenderer, goog.ui.ContainerRenderer);
    -goog.addSingletonGetter(goog.ui.ToolbarRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of toolbars rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.ToolbarRenderer.CSS_CLASS = goog.getCssName('goog-toolbar');
    -
    -
    -/**
    - * Inspects the element, and creates an instance of {@link goog.ui.Control} or
    - * an appropriate subclass best suited to decorate it.  Overrides the superclass
    - * implementation by recognizing HR elements as separators.
    - * @param {Element} element Element to decorate.
    - * @return {goog.ui.Control?} A new control suitable to decorate the element
    - *     (null if none).
    - * @override
    - */
    -goog.ui.ToolbarRenderer.prototype.getDecoratorForChild = function(element) {
    -  return element.tagName == 'HR' ?
    -      new goog.ui.Separator(goog.ui.ToolbarSeparatorRenderer.getInstance()) :
    -      goog.ui.ToolbarRenderer.superClass_.getDecoratorForChild.call(this,
    -          element);
    -};
    -
    -
    -/**
    - * Returns the CSS class to be applied to the root element of containers
    - * rendered using this renderer.
    - * @return {string} Renderer-specific CSS class.
    - * @override
    - */
    -goog.ui.ToolbarRenderer.prototype.getCssClass = function() {
    -  return goog.ui.ToolbarRenderer.CSS_CLASS;
    -};
    -
    -
    -/**
    - * Returns the default orientation of containers rendered or decorated by this
    - * renderer.  This implementation returns {@code HORIZONTAL}.
    - * @return {goog.ui.Container.Orientation} Default orientation for containers
    - *     created or decorated by this renderer.
    - * @override
    - */
    -goog.ui.ToolbarRenderer.prototype.getDefaultOrientation = function() {
    -  return goog.ui.Container.Orientation.HORIZONTAL;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/toolbarselect.js b/src/database/third_party/closure-library/closure/goog/ui/toolbarselect.js
    deleted file mode 100644
    index 008fe9fad1d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/toolbarselect.js
    +++ /dev/null
    @@ -1,55 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A toolbar select control.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.ToolbarSelect');
    -
    -goog.require('goog.ui.Select');
    -goog.require('goog.ui.ToolbarMenuButtonRenderer');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * A select control for a toolbar.
    - *
    - * @param {goog.ui.ControlContent} caption Default caption or existing DOM
    - *     structure to display as the button's caption when nothing is selected.
    - * @param {goog.ui.Menu=} opt_menu Menu containing selection options.
    - * @param {goog.ui.MenuButtonRenderer=} opt_renderer Renderer used to
    - *     render or decorate the control; defaults to
    - *     {@link goog.ui.ToolbarMenuButtonRenderer}.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @constructor
    - * @extends {goog.ui.Select}
    - */
    -goog.ui.ToolbarSelect = function(
    -    caption, opt_menu, opt_renderer, opt_domHelper) {
    -  goog.ui.Select.call(this, caption, opt_menu, opt_renderer ||
    -      goog.ui.ToolbarMenuButtonRenderer.getInstance(), opt_domHelper);
    -};
    -goog.inherits(goog.ui.ToolbarSelect, goog.ui.Select);
    -
    -
    -// Registers a decorator factory function for select controls used in toolbars.
    -goog.ui.registry.setDecoratorByClassName(goog.getCssName('goog-toolbar-select'),
    -    function() {
    -      return new goog.ui.ToolbarSelect(null);
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/toolbarseparator.js b/src/database/third_party/closure-library/closure/goog/ui/toolbarseparator.js
    deleted file mode 100644
    index 8bca9587de3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/toolbarseparator.js
    +++ /dev/null
    @@ -1,53 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A toolbar separator control.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.ToolbarSeparator');
    -
    -goog.require('goog.ui.Separator');
    -goog.require('goog.ui.ToolbarSeparatorRenderer');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * A separator control for a toolbar.
    - *
    - * @param {goog.ui.ToolbarSeparatorRenderer=} opt_renderer Renderer to render or
    - *    decorate the separator; defaults to
    - *     {@link goog.ui.ToolbarSeparatorRenderer}.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *    document interaction.
    - * @constructor
    - * @extends {goog.ui.Separator}
    - * @final
    - */
    -goog.ui.ToolbarSeparator = function(opt_renderer, opt_domHelper) {
    -  goog.ui.Separator.call(this, opt_renderer ||
    -      goog.ui.ToolbarSeparatorRenderer.getInstance(), opt_domHelper);
    -};
    -goog.inherits(goog.ui.ToolbarSeparator, goog.ui.Separator);
    -
    -
    -// Registers a decorator factory function for toolbar separators.
    -goog.ui.registry.setDecoratorByClassName(
    -    goog.ui.ToolbarSeparatorRenderer.CSS_CLASS,
    -    function() {
    -      return new goog.ui.ToolbarSeparator();
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/toolbarseparatorrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/toolbarseparatorrenderer.js
    deleted file mode 100644
    index 6c3e9757f59..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/toolbarseparatorrenderer.js
    +++ /dev/null
    @@ -1,94 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Renderer for toolbar separators.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.ToolbarSeparatorRenderer');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.ui.INLINE_BLOCK_CLASSNAME');
    -goog.require('goog.ui.MenuSeparatorRenderer');
    -
    -
    -
    -/**
    - * Renderer for toolbar separators.
    - * @constructor
    - * @extends {goog.ui.MenuSeparatorRenderer}
    - */
    -goog.ui.ToolbarSeparatorRenderer = function() {
    -  goog.ui.MenuSeparatorRenderer.call(this);
    -};
    -goog.inherits(goog.ui.ToolbarSeparatorRenderer, goog.ui.MenuSeparatorRenderer);
    -goog.addSingletonGetter(goog.ui.ToolbarSeparatorRenderer);
    -
    -
    -/**
    - * Default CSS class to be applied to the root element of components rendered
    - * by this renderer.
    - * @type {string}
    - */
    -goog.ui.ToolbarSeparatorRenderer.CSS_CLASS =
    -    goog.getCssName('goog-toolbar-separator');
    -
    -
    -/**
    - * Returns a styled toolbar separator implemented by the following DOM:
    - * <div class="goog-toolbar-separator goog-inline-block">&nbsp;</div>
    - * Overrides {@link goog.ui.MenuSeparatorRenderer#createDom}.
    - * @param {goog.ui.Control} separator goog.ui.Separator to render.
    - * @return {!Element} Root element for the separator.
    - * @override
    - */
    -goog.ui.ToolbarSeparatorRenderer.prototype.createDom = function(separator) {
    -  // 00A0 is &nbsp;
    -  return separator.getDomHelper().createDom('div',
    -      this.getClassNames(separator).join(' ') +
    -          ' ' + goog.ui.INLINE_BLOCK_CLASSNAME,
    -      '\u00A0');
    -};
    -
    -
    -/**
    - * Takes an existing element, and decorates it with the separator.  Overrides
    - * {@link goog.ui.MenuSeparatorRenderer#decorate}.
    - * @param {goog.ui.Control} separator goog.ui.Separator to decorate the element.
    - * @param {Element} element Element to decorate.
    - * @return {!Element} Decorated element.
    - * @override
    - */
    -goog.ui.ToolbarSeparatorRenderer.prototype.decorate = function(separator,
    -                                                               element) {
    -  element = goog.ui.ToolbarSeparatorRenderer.superClass_.decorate.call(this,
    -      separator, element);
    -  goog.asserts.assert(element);
    -  goog.dom.classlist.add(element, goog.ui.INLINE_BLOCK_CLASSNAME);
    -  return element;
    -};
    -
    -
    -/**
    - * Returns the CSS class to be applied to the root element of components
    - * rendered using this renderer.
    - * @return {string} Renderer-specific CSS class.
    - * @override
    - */
    -goog.ui.ToolbarSeparatorRenderer.prototype.getCssClass = function() {
    -  return goog.ui.ToolbarSeparatorRenderer.CSS_CLASS;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/toolbarseparatorrenderer_test.html b/src/database/third_party/closure-library/closure/goog/ui/toolbarseparatorrenderer_test.html
    deleted file mode 100644
    index dfd2938fb6d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/toolbarseparatorrenderer_test.html
    +++ /dev/null
    @@ -1,31 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -
    -  @author nicksantos@google.com (Nick Santos)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests for ToolbarSeparatorRenderer
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.ToolbarSeparatorRendererTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="root">
    -   <!-- A parent to attach rendered buttons to -->
    -   <div id="parent">
    -   </div>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/toolbarseparatorrenderer_test.js b/src/database/third_party/closure-library/closure/goog/ui/toolbarseparatorrenderer_test.js
    deleted file mode 100644
    index a263d09efc9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/toolbarseparatorrenderer_test.js
    +++ /dev/null
    @@ -1,67 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.ToolbarSeparatorRendererTest');
    -goog.setTestOnly('goog.ui.ToolbarSeparatorRendererTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.INLINE_BLOCK_CLASSNAME');
    -goog.require('goog.ui.ToolbarSeparator');
    -goog.require('goog.ui.ToolbarSeparatorRenderer');
    -
    -var parent;
    -var renderer;
    -var separator;
    -
    -function setUp() {
    -  parent = goog.dom.getElement('parent');
    -  renderer = goog.ui.ToolbarSeparatorRenderer.getInstance();
    -  separator = new goog.ui.ToolbarSeparator(renderer);
    -}
    -
    -function tearDown() {
    -  separator.dispose();
    -  goog.dom.removeChildren(parent);
    -}
    -
    -function testConstructor() {
    -  assertNotNull('Renderer must not be null', renderer);
    -}
    -
    -function testGetCssClass() {
    -  assertEquals('getCssClass() must return expected value',
    -      goog.ui.ToolbarSeparatorRenderer.CSS_CLASS, renderer.getCssClass());
    -}
    -
    -function testCreateDom() {
    -  var element = renderer.createDom(separator);
    -  assertNotNull('Created element must not be null', element);
    -  assertEquals('Created element must be a DIV', 'DIV', element.tagName);
    -  assertSameElements('Created element must have expected class names',
    -      [goog.ui.ToolbarSeparatorRenderer.CSS_CLASS,
    -       // Separators are always in a disabled state.
    -       renderer.getClassForState(goog.ui.Component.State.DISABLED),
    -       goog.ui.INLINE_BLOCK_CLASSNAME],
    -      goog.dom.classlist.get(element));
    -}
    -
    -function testCreateDomWithExtraCssClass() {
    -  separator.addClassName('another-class');
    -  var element = renderer.createDom(separator);
    -  assertContains('Created element must contain extra CSS classes',
    -                 'another-class', goog.dom.classlist.get(element));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/toolbartogglebutton.js b/src/database/third_party/closure-library/closure/goog/ui/toolbartogglebutton.js
    deleted file mode 100644
    index 54c914be325..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/toolbartogglebutton.js
    +++ /dev/null
    @@ -1,53 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A toolbar toggle button control.
    - *
    - * @author attila@google.com (Attila Bodis)
    - */
    -
    -goog.provide('goog.ui.ToolbarToggleButton');
    -
    -goog.require('goog.ui.ToggleButton');
    -goog.require('goog.ui.ToolbarButtonRenderer');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * A toggle button control for a toolbar.
    - *
    - * @param {goog.ui.ControlContent} content Text caption or existing DOM
    - *     structure to display as the button's caption.
    - * @param {goog.ui.ToolbarButtonRenderer=} opt_renderer Optional renderer used
    - *     to render or decorate the button; defaults to
    - *     {@link goog.ui.ToolbarButtonRenderer}.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
    - *     document interaction.
    - * @constructor
    - * @extends {goog.ui.ToggleButton}
    - */
    -goog.ui.ToolbarToggleButton = function(content, opt_renderer, opt_domHelper) {
    -  goog.ui.ToggleButton.call(this, content, opt_renderer ||
    -      goog.ui.ToolbarButtonRenderer.getInstance(), opt_domHelper);
    -};
    -goog.inherits(goog.ui.ToolbarToggleButton, goog.ui.ToggleButton);
    -
    -
    -// Registers a decorator factory function for toggle buttons in toolbars.
    -goog.ui.registry.setDecoratorByClassName(
    -    goog.getCssName('goog-toolbar-toggle-button'), function() {
    -      return new goog.ui.ToolbarToggleButton(null);
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tooltip.js b/src/database/third_party/closure-library/closure/goog/ui/tooltip.js
    deleted file mode 100644
    index 18040a18622..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tooltip.js
    +++ /dev/null
    @@ -1,1017 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Tooltip widget implementation.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - * @see ../demos/tooltip.html
    - */
    -
    -goog.provide('goog.ui.Tooltip');
    -goog.provide('goog.ui.Tooltip.CursorTooltipPosition');
    -goog.provide('goog.ui.Tooltip.ElementTooltipPosition');
    -goog.provide('goog.ui.Tooltip.State');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.dom.safe');
    -goog.require('goog.events');
    -goog.require('goog.events.EventType');
    -goog.require('goog.html.legacyconversions');
    -goog.require('goog.math.Box');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.positioning');
    -goog.require('goog.positioning.AnchoredPosition');
    -goog.require('goog.positioning.Corner');
    -goog.require('goog.positioning.Overflow');
    -goog.require('goog.positioning.OverflowStatus');
    -goog.require('goog.positioning.ViewportPosition');
    -goog.require('goog.structs.Set');
    -goog.require('goog.style');
    -goog.require('goog.ui.Popup');
    -goog.require('goog.ui.PopupBase');
    -
    -
    -
    -/**
    - * Tooltip widget. Can be attached to one or more elements and is shown, with a
    - * slight delay, when the the cursor is over the element or the element gains
    - * focus.
    - *
    - * @param {Element|string=} opt_el Element to display tooltip for, either
    - *     element reference or string id.
    - * @param {?string=} opt_str Text message to display in tooltip.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @constructor
    - * @extends {goog.ui.Popup}
    - */
    -goog.ui.Tooltip = function(opt_el, opt_str, opt_domHelper) {
    -  /**
    -   * Dom Helper
    -   * @type {goog.dom.DomHelper}
    -   * @private
    -   */
    -  this.dom_ = opt_domHelper || (opt_el ?
    -      goog.dom.getDomHelper(goog.dom.getElement(opt_el)) :
    -      goog.dom.getDomHelper());
    -
    -  goog.ui.Popup.call(this, this.dom_.createDom(
    -      'div', {'style': 'position:absolute;display:none;'}));
    -
    -  /**
    -   * Cursor position relative to the page.
    -   * @type {!goog.math.Coordinate}
    -   * @protected
    -   */
    -  this.cursorPosition = new goog.math.Coordinate(1, 1);
    -
    -  /**
    -   * Elements this widget is attached to.
    -   * @type {goog.structs.Set}
    -   * @private
    -   */
    -  this.elements_ = new goog.structs.Set();
    -
    -  // Attach to element, if specified
    -  if (opt_el) {
    -    this.attach(opt_el);
    -  }
    -
    -  // Set message, if specified.
    -  if (opt_str != null) {
    -    this.setText(opt_str);
    -  }
    -};
    -goog.inherits(goog.ui.Tooltip, goog.ui.Popup);
    -goog.tagUnsealableClass(goog.ui.Tooltip);
    -
    -
    -/**
    - * List of active (open) tooltip widgets. Used to prevent multiple tooltips
    - * from appearing at once.
    - *
    - * @type {!Array<goog.ui.Tooltip>}
    - * @private
    - */
    -goog.ui.Tooltip.activeInstances_ = [];
    -
    -
    -/**
    - * Active element reference. Used by the delayed show functionality to keep
    - * track of the element the mouse is over or the element with focus.
    - * @type {Element}
    - * @private
    - */
    -goog.ui.Tooltip.prototype.activeEl_ = null;
    -
    -
    -/**
    - * CSS class name for tooltip.
    - *
    - * @type {string}
    - */
    -goog.ui.Tooltip.prototype.className = goog.getCssName('goog-tooltip');
    -
    -
    -/**
    - * Delay in milliseconds since the last mouseover or mousemove before the
    - * tooltip is displayed for an element.
    - *
    - * @type {number}
    - * @private
    - */
    -goog.ui.Tooltip.prototype.showDelayMs_ = 500;
    -
    -
    -/**
    - * Timer for when to show.
    - *
    - * @type {number|undefined}
    - * @protected
    - */
    -goog.ui.Tooltip.prototype.showTimer;
    -
    -
    -/**
    - * Delay in milliseconds before tooltips are hidden.
    - *
    - * @type {number}
    - * @private
    - */
    -goog.ui.Tooltip.prototype.hideDelayMs_ = 0;
    -
    -
    -/**
    - * Timer for when to hide.
    - *
    - * @type {number|undefined}
    - * @protected
    - */
    -goog.ui.Tooltip.prototype.hideTimer;
    -
    -
    -/**
    - * Element that triggered the tooltip.  Note that if a second element triggers
    - * this tooltip, anchor becomes that second element, even if its show is
    - * cancelled and the original tooltip survives.
    - *
    - * @type {Element|undefined}
    - * @protected
    - */
    -goog.ui.Tooltip.prototype.anchor;
    -
    -
    -/**
    - * Possible states for the tooltip to be in.
    - * @enum {number}
    - */
    -goog.ui.Tooltip.State = {
    -  INACTIVE: 0,
    -  WAITING_TO_SHOW: 1,
    -  SHOWING: 2,
    -  WAITING_TO_HIDE: 3,
    -  UPDATING: 4 // waiting to show new hovercard while old one still showing.
    -};
    -
    -
    -/**
    - * Popup activation types. Used to select a positioning strategy.
    - * @enum {number}
    - */
    -goog.ui.Tooltip.Activation = {
    -  CURSOR: 0,
    -  FOCUS: 1
    -};
    -
    -
    -/**
    - * Whether the anchor has seen the cursor move or has received focus since the
    - * tooltip was last shown. Used to ignore mouse over events triggered by view
    - * changes and UI updates.
    - * @type {boolean|undefined}
    - * @private
    - */
    -goog.ui.Tooltip.prototype.seenInteraction_;
    -
    -
    -/**
    - * Whether the cursor must have moved before the tooltip will be shown.
    - * @type {boolean|undefined}
    - * @private
    - */
    -goog.ui.Tooltip.prototype.requireInteraction_;
    -
    -
    -/**
    - * If this tooltip's element contains another tooltip that becomes active, this
    - * property identifies that tooltip so that we can check if this tooltip should
    - * not be hidden because the nested tooltip is active.
    - * @type {goog.ui.Tooltip}
    - * @private
    - */
    -goog.ui.Tooltip.prototype.childTooltip_;
    -
    -
    -/**
    - * If this tooltip is inside another tooltip's element, then it may have
    - * prevented that tooltip from hiding.  When this tooltip hides, we'll need
    - * to check if the parent should be hidden as well.
    - * @type {goog.ui.Tooltip}
    - * @private
    - */
    -goog.ui.Tooltip.prototype.parentTooltip_;
    -
    -
    -/**
    - * Returns the dom helper that is being used on this component.
    - * @return {goog.dom.DomHelper} The dom helper used on this component.
    - */
    -goog.ui.Tooltip.prototype.getDomHelper = function() {
    -  return this.dom_;
    -};
    -
    -
    -/**
    - * @return {goog.ui.Tooltip} Active tooltip in a child element, or null if none.
    - * @protected
    - */
    -goog.ui.Tooltip.prototype.getChildTooltip = function() {
    -  return this.childTooltip_;
    -};
    -
    -
    -/**
    - * Attach to element. Tooltip will be displayed when the cursor is over the
    - * element or when the element has been active for a few milliseconds.
    - *
    - * @param {Element|string} el Element to display tooltip for, either element
    - *                            reference or string id.
    - */
    -goog.ui.Tooltip.prototype.attach = function(el) {
    -  el = goog.dom.getElement(el);
    -
    -  this.elements_.add(el);
    -  goog.events.listen(el, goog.events.EventType.MOUSEOVER,
    -                     this.handleMouseOver, false, this);
    -  goog.events.listen(el, goog.events.EventType.MOUSEOUT,
    -                     this.handleMouseOutAndBlur, false, this);
    -  goog.events.listen(el, goog.events.EventType.MOUSEMOVE,
    -                     this.handleMouseMove, false, this);
    -  goog.events.listen(el, goog.events.EventType.FOCUS,
    -                     this.handleFocus, false, this);
    -  goog.events.listen(el, goog.events.EventType.BLUR,
    -                     this.handleMouseOutAndBlur, false, this);
    -};
    -
    -
    -/**
    - * Detach from element(s).
    - *
    - * @param {Element|string=} opt_el Element to detach from, either element
    - *                                reference or string id. If no element is
    - *                                specified all are detached.
    - */
    -goog.ui.Tooltip.prototype.detach = function(opt_el) {
    -  if (opt_el) {
    -    var el = goog.dom.getElement(opt_el);
    -    this.detachElement_(el);
    -    this.elements_.remove(el);
    -  } else {
    -    var a = this.elements_.getValues();
    -    for (var el, i = 0; el = a[i]; i++) {
    -      this.detachElement_(el);
    -    }
    -    this.elements_.clear();
    -  }
    -};
    -
    -
    -/**
    - * Detach from element.
    - *
    - * @param {Element} el Element to detach from.
    - * @private
    - */
    -goog.ui.Tooltip.prototype.detachElement_ = function(el) {
    -  goog.events.unlisten(el, goog.events.EventType.MOUSEOVER,
    -                       this.handleMouseOver, false, this);
    -  goog.events.unlisten(el, goog.events.EventType.MOUSEOUT,
    -                       this.handleMouseOutAndBlur, false, this);
    -  goog.events.unlisten(el, goog.events.EventType.MOUSEMOVE,
    -                       this.handleMouseMove, false, this);
    -  goog.events.unlisten(el, goog.events.EventType.FOCUS,
    -                       this.handleFocus, false, this);
    -  goog.events.unlisten(el, goog.events.EventType.BLUR,
    -                       this.handleMouseOutAndBlur, false, this);
    -};
    -
    -
    -/**
    - * Sets delay in milliseconds before tooltip is displayed for an element.
    - *
    - * @param {number} delay The delay in milliseconds.
    - */
    -goog.ui.Tooltip.prototype.setShowDelayMs = function(delay) {
    -  this.showDelayMs_ = delay;
    -};
    -
    -
    -/**
    - * @return {number} The delay in milliseconds before tooltip is displayed for an
    - *     element.
    - */
    -goog.ui.Tooltip.prototype.getShowDelayMs = function() {
    -  return this.showDelayMs_;
    -};
    -
    -
    -/**
    - * Sets delay in milliseconds before tooltip is hidden once the cursor leavs
    - * the element.
    - *
    - * @param {number} delay The delay in milliseconds.
    - */
    -goog.ui.Tooltip.prototype.setHideDelayMs = function(delay) {
    -  this.hideDelayMs_ = delay;
    -};
    -
    -
    -/**
    - * @return {number} The delay in milliseconds before tooltip is hidden once the
    - *     cursor leaves the element.
    - */
    -goog.ui.Tooltip.prototype.getHideDelayMs = function() {
    -  return this.hideDelayMs_;
    -};
    -
    -
    -/**
    - * Sets tooltip message as plain text.
    - *
    - * @param {string} str Text message to display in tooltip.
    - */
    -goog.ui.Tooltip.prototype.setText = function(str) {
    -  goog.dom.setTextContent(this.getElement(), str);
    -};
    -
    -
    -// TODO(user): Deprecate in favor of setSafeHtml, once developer docs on.
    -/**
    - * Sets tooltip message as HTML markup.
    - * using goog.html.SafeHtml are in place.
    - *
    - * @param {string} str HTML message to display in tooltip.
    - */
    -goog.ui.Tooltip.prototype.setHtml = function(str) {
    -  this.setSafeHtml(goog.html.legacyconversions.safeHtmlFromString(str));
    -};
    -
    -
    -/**
    - * Sets tooltip message as HTML markup.
    - * @param {!goog.html.SafeHtml} html HTML message to display in tooltip.
    - */
    -goog.ui.Tooltip.prototype.setSafeHtml = function(html) {
    -  var element = this.getElement();
    -  if (element) {
    -    goog.dom.safe.setInnerHtml(element, html);
    -  }
    -};
    -
    -
    -/**
    - * Sets tooltip element.
    - *
    - * @param {Element} el HTML element to use as the tooltip.
    - * @override
    - */
    -goog.ui.Tooltip.prototype.setElement = function(el) {
    -  var oldElement = this.getElement();
    -  if (oldElement) {
    -    goog.dom.removeNode(oldElement);
    -  }
    -  goog.ui.Tooltip.superClass_.setElement.call(this, el);
    -  if (el) {
    -    var body = this.dom_.getDocument().body;
    -    body.insertBefore(el, body.lastChild);
    -  }
    -};
    -
    -
    -/**
    - * @return {string} The tooltip message as plain text.
    - */
    -goog.ui.Tooltip.prototype.getText = function() {
    -  return goog.dom.getTextContent(this.getElement());
    -};
    -
    -
    -/**
    - * @return {string} The tooltip message as HTML as plain string.
    - */
    -goog.ui.Tooltip.prototype.getHtml = function() {
    -  return this.getElement().innerHTML;
    -};
    -
    -
    -/**
    - * @return {goog.ui.Tooltip.State} Current state of tooltip.
    - */
    -goog.ui.Tooltip.prototype.getState = function() {
    -  return this.showTimer ?
    -             (this.isVisible() ? goog.ui.Tooltip.State.UPDATING :
    -                                 goog.ui.Tooltip.State.WAITING_TO_SHOW) :
    -         this.hideTimer ? goog.ui.Tooltip.State.WAITING_TO_HIDE :
    -         this.isVisible() ? goog.ui.Tooltip.State.SHOWING :
    -         goog.ui.Tooltip.State.INACTIVE;
    -};
    -
    -
    -/**
    - * Sets whether tooltip requires the mouse to have moved or the anchor receive
    - * focus before the tooltip will be shown.
    - * @param {boolean} requireInteraction Whether tooltip should require some user
    - *     interaction before showing tooltip.
    - */
    -goog.ui.Tooltip.prototype.setRequireInteraction = function(requireInteraction) {
    -  this.requireInteraction_ = requireInteraction;
    -};
    -
    -
    -/**
    - * Returns true if the coord is in the tooltip.
    - * @param {goog.math.Coordinate} coord Coordinate being tested.
    - * @return {boolean} Whether the coord is in the tooltip.
    - */
    -goog.ui.Tooltip.prototype.isCoordinateInTooltip = function(coord) {
    -  // Check if coord is inside the the tooltip
    -  if (!this.isVisible()) {
    -    return false;
    -  }
    -
    -  var offset = goog.style.getPageOffset(this.getElement());
    -  var size = goog.style.getSize(this.getElement());
    -  return offset.x <= coord.x && coord.x <= offset.x + size.width &&
    -         offset.y <= coord.y && coord.y <= offset.y + size.height;
    -};
    -
    -
    -/**
    - * Called before the popup is shown.
    - *
    - * @return {boolean} Whether tooltip should be shown.
    - * @protected
    - * @override
    - */
    -goog.ui.Tooltip.prototype.onBeforeShow = function() {
    -  if (!goog.ui.PopupBase.prototype.onBeforeShow.call(this)) {
    -    return false;
    -  }
    -
    -  // Hide all open tooltips except if this tooltip is triggered by an element
    -  // inside another tooltip.
    -  if (this.anchor) {
    -    for (var tt, i = 0; tt = goog.ui.Tooltip.activeInstances_[i]; i++) {
    -      if (!goog.dom.contains(tt.getElement(), this.anchor)) {
    -        tt.setVisible(false);
    -      }
    -    }
    -  }
    -  goog.array.insert(goog.ui.Tooltip.activeInstances_, this);
    -
    -  var element = this.getElement();
    -  element.className = this.className;
    -  this.clearHideTimer();
    -
    -  // Register event handlers for tooltip. Used to prevent the tooltip from
    -  // closing if the cursor is over the tooltip rather then the element that
    -  // triggered it.
    -  goog.events.listen(element, goog.events.EventType.MOUSEOVER,
    -                     this.handleTooltipMouseOver, false, this);
    -  goog.events.listen(element, goog.events.EventType.MOUSEOUT,
    -                     this.handleTooltipMouseOut, false, this);
    -
    -  this.clearShowTimer();
    -  return true;
    -};
    -
    -
    -/**
    - * Called after the popup is hidden.
    - *
    - * @protected
    - * @suppress {underscore|visibility}
    - * @override
    - */
    -goog.ui.Tooltip.prototype.onHide_ = function() {
    -  goog.array.remove(goog.ui.Tooltip.activeInstances_, this);
    -
    -  // Hide all open tooltips triggered by an element inside this tooltip.
    -  var element = this.getElement();
    -  for (var tt, i = 0; tt = goog.ui.Tooltip.activeInstances_[i]; i++) {
    -    if (tt.anchor && goog.dom.contains(element, tt.anchor)) {
    -      tt.setVisible(false);
    -    }
    -  }
    -
    -  // If this tooltip is inside another tooltip, start hide timer for that
    -  // tooltip in case this tooltip was the only reason it was still showing.
    -  if (this.parentTooltip_) {
    -    this.parentTooltip_.startHideTimer();
    -  }
    -
    -  goog.events.unlisten(element, goog.events.EventType.MOUSEOVER,
    -                       this.handleTooltipMouseOver, false, this);
    -  goog.events.unlisten(element, goog.events.EventType.MOUSEOUT,
    -                       this.handleTooltipMouseOut, false, this);
    -
    -  this.anchor = undefined;
    -  // If we are still waiting to show a different hovercard, don't abort it
    -  // because you think you haven't seen a mouse move:
    -  if (this.getState() == goog.ui.Tooltip.State.INACTIVE) {
    -    this.seenInteraction_ = false;
    -  }
    -
    -  goog.ui.PopupBase.prototype.onHide_.call(this);
    -};
    -
    -
    -/**
    - * Called by timer from mouse over handler. Shows tooltip if cursor is still
    - * over the same element.
    - *
    - * @param {Element} el Element to show tooltip for.
    - * @param {goog.positioning.AbstractPosition=} opt_pos Position to display popup
    - *     at.
    - */
    -goog.ui.Tooltip.prototype.maybeShow = function(el, opt_pos) {
    -  // Assert that the mouse is still over the same element, and that we have not
    -  // detached from the anchor in the meantime.
    -  if (this.anchor == el && this.elements_.contains(this.anchor)) {
    -    if (this.seenInteraction_ || !this.requireInteraction_) {
    -      // If it is currently showing, then hide it, and abort if it doesn't hide.
    -      this.setVisible(false);
    -      if (!this.isVisible()) {
    -        this.positionAndShow_(el, opt_pos);
    -      }
    -    } else {
    -      this.anchor = undefined;
    -    }
    -  }
    -  this.showTimer = undefined;
    -};
    -
    -
    -/**
    - * @return {goog.structs.Set} Elements this widget is attached to.
    - * @protected
    - */
    -goog.ui.Tooltip.prototype.getElements = function() {
    -  return this.elements_;
    -};
    -
    -
    -/**
    - * @return {Element} Active element reference.
    - */
    -goog.ui.Tooltip.prototype.getActiveElement = function() {
    -  return this.activeEl_;
    -};
    -
    -
    -/**
    - * @param {Element} activeEl Active element reference.
    - * @protected
    - */
    -goog.ui.Tooltip.prototype.setActiveElement = function(activeEl) {
    -  this.activeEl_ = activeEl;
    -};
    -
    -
    -/**
    - * Shows tooltip for a specific element.
    - *
    - * @param {Element} el Element to show tooltip for.
    - * @param {goog.positioning.AbstractPosition=} opt_pos Position to display popup
    - *     at.
    - */
    -goog.ui.Tooltip.prototype.showForElement = function(el, opt_pos) {
    -  this.attach(el);
    -  this.activeEl_ = el;
    -
    -  this.positionAndShow_(el, opt_pos);
    -};
    -
    -
    -/**
    - * Sets tooltip position and shows it.
    - *
    - * @param {Element} el Element to show tooltip for.
    - * @param {goog.positioning.AbstractPosition=} opt_pos Position to display popup
    - *     at.
    - * @private
    - */
    -goog.ui.Tooltip.prototype.positionAndShow_ = function(el, opt_pos) {
    -  this.anchor = el;
    -  this.setPosition(opt_pos ||
    -      this.getPositioningStrategy(goog.ui.Tooltip.Activation.CURSOR));
    -  this.setVisible(true);
    -};
    -
    -
    -/**
    - * Called by timer from mouse out handler. Hides tooltip if cursor is still
    - * outside element and tooltip, or if a child of tooltip has the focus.
    - * @param {Element} el Tooltip's anchor when hide timer was started.
    - */
    -goog.ui.Tooltip.prototype.maybeHide = function(el) {
    -  this.hideTimer = undefined;
    -  if (el == this.anchor) {
    -    if ((this.activeEl_ == null || (this.activeEl_ != this.getElement() &&
    -        !this.elements_.contains(this.activeEl_))) &&
    -        !this.hasActiveChild()) {
    -      this.setVisible(false);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} Whether tooltip element contains an active child tooltip,
    - *     and should thus not be hidden.  When the child tooltip is hidden, it
    - *     will check if the parent should be hidden, too.
    - * @protected
    - */
    -goog.ui.Tooltip.prototype.hasActiveChild = function() {
    -  return !!(this.childTooltip_ && this.childTooltip_.activeEl_);
    -};
    -
    -
    -/**
    - * Saves the current mouse cursor position to {@code this.cursorPosition}.
    - * @param {goog.events.BrowserEvent} event MOUSEOVER or MOUSEMOVE event.
    - * @private
    - */
    -goog.ui.Tooltip.prototype.saveCursorPosition_ = function(event) {
    -  var scroll = this.dom_.getDocumentScroll();
    -  this.cursorPosition.x = event.clientX + scroll.x;
    -  this.cursorPosition.y = event.clientY + scroll.y;
    -};
    -
    -
    -/**
    - * Handler for mouse over events.
    - *
    - * @param {goog.events.BrowserEvent} event Event object.
    - * @protected
    - */
    -goog.ui.Tooltip.prototype.handleMouseOver = function(event) {
    -  var el = this.getAnchorFromElement(/** @type {Element} */ (event.target));
    -  this.activeEl_ = /** @type {Element} */ (el);
    -  this.clearHideTimer();
    -  if (el != this.anchor) {
    -    this.anchor = el;
    -    this.startShowTimer(/** @type {Element} */ (el));
    -    this.checkForParentTooltip_();
    -    this.saveCursorPosition_(event);
    -  }
    -};
    -
    -
    -/**
    - * Find anchor containing the given element, if any.
    - *
    - * @param {Element} el Element that triggered event.
    - * @return {Element} Element in elements_ array that contains given element,
    - *     or null if not found.
    - * @protected
    - */
    -goog.ui.Tooltip.prototype.getAnchorFromElement = function(el) {
    -  // FireFox has a bug where mouse events relating to <input> elements are
    -  // sometimes duplicated (often in FF2, rarely in FF3): once for the
    -  // <input> element and once for a magic hidden <div> element.  Javascript
    -  // code does not have sufficient permissions to read properties on that
    -  // magic element and thus will throw an error in this call to
    -  // getAnchorFromElement_().  In that case we swallow the error.
    -  // See https://bugzilla.mozilla.org/show_bug.cgi?id=330961
    -  try {
    -    while (el && !this.elements_.contains(el)) {
    -      el = /** @type {Element} */ (el.parentNode);
    -    }
    -    return el;
    -  } catch (e) {
    -    return null;
    -  }
    -};
    -
    -
    -/**
    - * Handler for mouse move events.
    - *
    - * @param {goog.events.BrowserEvent} event MOUSEMOVE event.
    - * @protected
    - */
    -goog.ui.Tooltip.prototype.handleMouseMove = function(event) {
    -  this.saveCursorPosition_(event);
    -  this.seenInteraction_ = true;
    -};
    -
    -
    -/**
    - * Handler for focus events.
    - *
    - * @param {goog.events.BrowserEvent} event Event object.
    - * @protected
    - */
    -goog.ui.Tooltip.prototype.handleFocus = function(event) {
    -  var el = this.getAnchorFromElement(/** @type {Element} */ (event.target));
    -  this.activeEl_ = el;
    -  this.seenInteraction_ = true;
    -
    -  if (this.anchor != el) {
    -    this.anchor = el;
    -    var pos = this.getPositioningStrategy(goog.ui.Tooltip.Activation.FOCUS);
    -    this.clearHideTimer();
    -    this.startShowTimer(/** @type {Element} */ (el), pos);
    -
    -    this.checkForParentTooltip_();
    -  }
    -};
    -
    -
    -/**
    - * Return a Position instance for repositioning the tooltip. Override in
    - * subclasses to customize the way repositioning is done.
    - *
    - * @param {goog.ui.Tooltip.Activation} activationType Information about what
    - *    kind of event caused the popup to be shown.
    - * @return {!goog.positioning.AbstractPosition} The position object used
    - *    to position the tooltip.
    - * @protected
    - */
    -goog.ui.Tooltip.prototype.getPositioningStrategy = function(activationType) {
    -  if (activationType == goog.ui.Tooltip.Activation.CURSOR) {
    -    var coord = this.cursorPosition.clone();
    -    return new goog.ui.Tooltip.CursorTooltipPosition(coord);
    -  }
    -  return new goog.ui.Tooltip.ElementTooltipPosition(this.activeEl_);
    -};
    -
    -
    -/**
    - * Looks for an active tooltip whose element contains this tooltip's anchor.
    - * This allows us to prevent hides until they are really necessary.
    - *
    - * @private
    - */
    -goog.ui.Tooltip.prototype.checkForParentTooltip_ = function() {
    -  if (this.anchor) {
    -    for (var tt, i = 0; tt = goog.ui.Tooltip.activeInstances_[i]; i++) {
    -      if (goog.dom.contains(tt.getElement(), this.anchor)) {
    -        tt.childTooltip_ = this;
    -        this.parentTooltip_ = tt;
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Handler for mouse out and blur events.
    - *
    - * @param {goog.events.BrowserEvent} event Event object.
    - * @protected
    - */
    -goog.ui.Tooltip.prototype.handleMouseOutAndBlur = function(event) {
    -  var el = this.getAnchorFromElement(/** @type {Element} */ (event.target));
    -  var elTo = this.getAnchorFromElement(
    -      /** @type {Element} */ (event.relatedTarget));
    -  if (el == elTo) {
    -    // We haven't really left the anchor, just moved from one child to
    -    // another.
    -    return;
    -  }
    -
    -  if (el == this.activeEl_) {
    -    this.activeEl_ = null;
    -  }
    -
    -  this.clearShowTimer();
    -  this.seenInteraction_ = false;
    -  if (this.isVisible() && (!event.relatedTarget ||
    -      !goog.dom.contains(this.getElement(), event.relatedTarget))) {
    -    this.startHideTimer();
    -  } else {
    -    this.anchor = undefined;
    -  }
    -};
    -
    -
    -/**
    - * Handler for mouse over events for the tooltip element.
    - *
    - * @param {goog.events.BrowserEvent} event Event object.
    - * @protected
    - */
    -goog.ui.Tooltip.prototype.handleTooltipMouseOver = function(event) {
    -  var element = this.getElement();
    -  if (this.activeEl_ != element) {
    -    this.clearHideTimer();
    -    this.activeEl_ = element;
    -  }
    -};
    -
    -
    -/**
    - * Handler for mouse out events for the tooltip element.
    - *
    - * @param {goog.events.BrowserEvent} event Event object.
    - * @protected
    - */
    -goog.ui.Tooltip.prototype.handleTooltipMouseOut = function(event) {
    -  var element = this.getElement();
    -  if (this.activeEl_ == element && (!event.relatedTarget ||
    -      !goog.dom.contains(element, event.relatedTarget))) {
    -    this.activeEl_ = null;
    -    this.startHideTimer();
    -  }
    -};
    -
    -
    -/**
    - * Helper method, starts timer that calls maybeShow. Parameters are passed to
    - * the maybeShow method.
    - *
    - * @param {Element} el Element to show tooltip for.
    - * @param {goog.positioning.AbstractPosition=} opt_pos Position to display popup
    - *     at.
    - * @protected
    - */
    -goog.ui.Tooltip.prototype.startShowTimer = function(el, opt_pos) {
    -  if (!this.showTimer) {
    -    this.showTimer = goog.Timer.callOnce(
    -        goog.bind(this.maybeShow, this, el, opt_pos), this.showDelayMs_);
    -  }
    -};
    -
    -
    -/**
    - * Helper method called to clear the show timer.
    - *
    - * @protected
    - */
    -goog.ui.Tooltip.prototype.clearShowTimer = function() {
    -  if (this.showTimer) {
    -    goog.Timer.clear(this.showTimer);
    -    this.showTimer = undefined;
    -  }
    -};
    -
    -
    -/**
    - * Helper method called to start the close timer.
    - * @protected
    - */
    -goog.ui.Tooltip.prototype.startHideTimer = function() {
    -  if (this.getState() == goog.ui.Tooltip.State.SHOWING) {
    -    this.hideTimer = goog.Timer.callOnce(
    -        goog.bind(this.maybeHide, this, this.anchor), this.getHideDelayMs());
    -  }
    -};
    -
    -
    -/**
    - * Helper method called to clear the close timer.
    - * @protected
    - */
    -goog.ui.Tooltip.prototype.clearHideTimer = function() {
    -  if (this.hideTimer) {
    -    goog.Timer.clear(this.hideTimer);
    -    this.hideTimer = undefined;
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.Tooltip.prototype.disposeInternal = function() {
    -  this.setVisible(false);
    -  this.clearShowTimer();
    -  this.detach();
    -  if (this.getElement()) {
    -    goog.dom.removeNode(this.getElement());
    -  }
    -  this.activeEl_ = null;
    -  delete this.dom_;
    -  goog.ui.Tooltip.superClass_.disposeInternal.call(this);
    -};
    -
    -
    -
    -/**
    - * Popup position implementation that positions the popup (the tooltip in this
    - * case) based on the cursor position. It's positioned below the cursor to the
    - * right if there's enough room to fit all of it inside the Viewport. Otherwise
    - * it's displayed as far right as possible either above or below the element.
    - *
    - * Used to position tooltips triggered by the cursor.
    - *
    - * @param {number|!goog.math.Coordinate} arg1 Left position or coordinate.
    - * @param {number=} opt_arg2 Top position.
    - * @constructor
    - * @extends {goog.positioning.ViewportPosition}
    - * @final
    - */
    -goog.ui.Tooltip.CursorTooltipPosition = function(arg1, opt_arg2) {
    -  goog.positioning.ViewportPosition.call(this, arg1, opt_arg2);
    -};
    -goog.inherits(goog.ui.Tooltip.CursorTooltipPosition,
    -              goog.positioning.ViewportPosition);
    -
    -
    -/**
    - * Repositions the popup based on cursor position.
    - *
    - * @param {Element} element The DOM element of the popup.
    - * @param {goog.positioning.Corner} popupCorner The corner of the popup element
    - *     that that should be positioned adjacent to the anchorElement.
    - * @param {goog.math.Box=} opt_margin A margin specified in pixels.
    - * @override
    - */
    -goog.ui.Tooltip.CursorTooltipPosition.prototype.reposition = function(
    -    element, popupCorner, opt_margin) {
    -  var viewportElt = goog.style.getClientViewportElement(element);
    -  var viewport = goog.style.getVisibleRectForElement(viewportElt);
    -  var margin = opt_margin ? new goog.math.Box(opt_margin.top + 10,
    -      opt_margin.right, opt_margin.bottom, opt_margin.left + 10) :
    -      new goog.math.Box(10, 0, 0, 10);
    -
    -  if (goog.positioning.positionAtCoordinate(this.coordinate, element,
    -      goog.positioning.Corner.TOP_START, margin, viewport,
    -      goog.positioning.Overflow.ADJUST_X | goog.positioning.Overflow.FAIL_Y
    -      ) & goog.positioning.OverflowStatus.FAILED) {
    -    goog.positioning.positionAtCoordinate(this.coordinate, element,
    -        goog.positioning.Corner.TOP_START, margin, viewport,
    -        goog.positioning.Overflow.ADJUST_X |
    -            goog.positioning.Overflow.ADJUST_Y);
    -  }
    -};
    -
    -
    -
    -/**
    - * Popup position implementation that positions the popup (the tooltip in this
    - * case) based on the element position. It's positioned below the element to the
    - * right if there's enough room to fit all of it inside the Viewport. Otherwise
    - * it's displayed as far right as possible either above or below the element.
    - *
    - * Used to position tooltips triggered by focus changes.
    - *
    - * @param {Element} element The element to anchor the popup at.
    - * @constructor
    - * @extends {goog.positioning.AnchoredPosition}
    - */
    -goog.ui.Tooltip.ElementTooltipPosition = function(element) {
    -  goog.positioning.AnchoredPosition.call(this, element,
    -      goog.positioning.Corner.BOTTOM_RIGHT);
    -};
    -goog.inherits(goog.ui.Tooltip.ElementTooltipPosition,
    -              goog.positioning.AnchoredPosition);
    -
    -
    -/**
    - * Repositions the popup based on element position.
    - *
    - * @param {Element} element The DOM element of the popup.
    - * @param {goog.positioning.Corner} popupCorner The corner of the popup element
    - *     that should be positioned adjacent to the anchorElement.
    - * @param {goog.math.Box=} opt_margin A margin specified in pixels.
    - * @override
    - */
    -goog.ui.Tooltip.ElementTooltipPosition.prototype.reposition = function(
    -    element, popupCorner, opt_margin) {
    -  var offset = new goog.math.Coordinate(10, 0);
    -
    -  if (goog.positioning.positionAtAnchor(this.element, this.corner, element,
    -      popupCorner, offset, opt_margin,
    -      goog.positioning.Overflow.ADJUST_X | goog.positioning.Overflow.FAIL_Y
    -      ) & goog.positioning.OverflowStatus.FAILED) {
    -    goog.positioning.positionAtAnchor(this.element,
    -        goog.positioning.Corner.TOP_RIGHT, element,
    -        goog.positioning.Corner.BOTTOM_LEFT, offset, opt_margin,
    -        goog.positioning.Overflow.ADJUST_X |
    -            goog.positioning.Overflow.ADJUST_Y);
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tooltip_test.html b/src/database/third_party/closure-library/closure/goog/ui/tooltip_test.html
    deleted file mode 100644
    index fe616e2cfd2..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tooltip_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!-- Author:  attila@google.com (Attila Bodis) -->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.Tooltip
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.TooltipTest');
    -  </script>
    - </head>
    - <body>
    -  <iframe id="testframe" style="width: 200px; height: 200px;" src="blank_test_helper.html">
    -  </iframe>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tooltip_test.js b/src/database/third_party/closure-library/closure/goog/ui/tooltip_test.js
    deleted file mode 100644
    index 4aa462a067d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tooltip_test.js
    +++ /dev/null
    @@ -1,394 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.TooltipTest');
    -goog.setTestOnly('goog.ui.TooltipTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventType');
    -goog.require('goog.html.testing');
    -goog.require('goog.math.Coordinate');
    -goog.require('goog.positioning.AbsolutePosition');
    -goog.require('goog.style');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.TestQueue');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.PopupBase');
    -goog.require('goog.ui.Tooltip');
    -goog.require('goog.userAgent');
    -
    -var stubs = new goog.testing.PropertyReplacer();
    -
    -
    -
    -/**
    - * A subclass of Tooltip that overrides {@code getPositioningStrategy}
    - * for testing purposes.
    - * @constructor
    - */
    -function TestTooltip(el, text, dom) {
    -  goog.ui.Tooltip.call(this, el, text, dom);
    -}
    -goog.inherits(TestTooltip, goog.ui.Tooltip);
    -
    -
    -/** @override */
    -TestTooltip.prototype.getPositioningStrategy = function() {
    -  return new goog.positioning.AbsolutePosition(13, 17);
    -};
    -
    -
    -var tt, clock, handler, eventQueue, dom;
    -
    -// Allow positions to be off by one in gecko as it reports scrolling
    -// offsets in steps of 2.
    -var ALLOWED_OFFSET = goog.userAgent.GECKO ? 1 : 0;
    -
    -function setUp() {
    -  // We get access denied error when accessing the iframe in IE on the farm
    -  // as IE doesn't have the same window size issues as firefox on the farm
    -  // we bypass the iframe and use the current document instead.
    -  if (goog.userAgent.IE) {
    -    dom = goog.dom.getDomHelper(document);
    -  } else {
    -    var frame = document.getElementById('testframe');
    -    var doc = goog.dom.getFrameContentDocument(frame);
    -    dom = goog.dom.getDomHelper(doc);
    -  }
    -
    -  // Host elements in fixed size iframe to avoid window size problems when
    -  // running under Selenium.
    -  dom.getDocument().body.innerHTML =
    -      '<p id="notpopup">Content</p>' +
    -      '<p id="hovertarget">Hover Here For Popup</p>' +
    -      '<p id="second">Secondary target</p>';
    -
    -  tt = new goog.ui.Tooltip(undefined, undefined, dom);
    -  tt.setElement(dom.createDom('div', {id: 'popup',
    -    style: 'visibility:hidden'},
    -  'Hello'));
    -  clock = new goog.testing.MockClock(true);
    -  eventQueue = new goog.testing.TestQueue();
    -  handler = new goog.events.EventHandler(eventQueue);
    -  handler.listen(tt, goog.ui.PopupBase.EventType.SHOW, eventQueue.enqueue);
    -  handler.listen(tt, goog.ui.PopupBase.EventType.HIDE, eventQueue.enqueue);
    -
    -  // Reset global flags to their defaults.
    -  /** @suppress {missingRequire} */
    -  stubs.set(goog.html.legacyconversions, 'ALLOW_LEGACY_CONVERSIONS', true);
    -}
    -
    -function tearDown() {
    -  // tooltip needs to be hidden as well as disposed of so that it doesn't
    -  // leave global state hanging around to trip up other tests.
    -  tt.onHide_();
    -  tt.dispose();
    -  clock.uninstall();
    -  handler.removeAll();
    -}
    -
    -function testConstructor() {
    -  var element = tt.getElement();
    -  assertNotNull('Tooltip should have non-null element', element);
    -  assertEquals('Tooltip element should be the DIV we created',
    -      dom.getElement('popup'), element);
    -  assertEquals('Tooltip element should be a child of the document body',
    -      dom.getDocument().body, element.parentNode);
    -}
    -
    -function testTooltipShowsAndHides() {
    -  var hoverTarget = dom.getElement('hovertarget');
    -  var elsewhere = dom.getElement('notpopup');
    -  var element = tt.getElement();
    -  var position = new goog.math.Coordinate(5, 5);
    -  assertNotNull('Tooltip should have non-null element', element);
    -  assertEquals('Initial state should be inactive',
    -               goog.ui.Tooltip.State.INACTIVE, tt.getState());
    -  tt.attach(hoverTarget);
    -  tt.setShowDelayMs(100);
    -  tt.setHideDelayMs(50);
    -  goog.testing.events.fireMouseOverEvent(hoverTarget, elsewhere, position);
    -  assertEquals(goog.ui.Tooltip.State.WAITING_TO_SHOW, tt.getState());
    -  clock.tick(101);
    -  assertEquals('visible', tt.getElement().style.visibility);
    -  assertEquals('tooltip y position (10px margin below the cursor)', '15px',
    -      tt.getElement().style.top);
    -  assertEquals(goog.ui.Tooltip.State.SHOWING, tt.getState());
    -  assertEquals(goog.ui.PopupBase.EventType.SHOW, eventQueue.dequeue().type);
    -  assertTrue(eventQueue.isEmpty());
    -
    -  goog.testing.events.fireMouseOutEvent(hoverTarget, elsewhere);
    -  assertEquals(goog.ui.Tooltip.State.WAITING_TO_HIDE, tt.getState());
    -  clock.tick(51);
    -  assertEquals('hidden', tt.getElement().style.visibility);
    -  assertEquals(goog.ui.Tooltip.State.INACTIVE, tt.getState());
    -  assertEquals(goog.ui.PopupBase.EventType.HIDE, eventQueue.dequeue().type);
    -  assertTrue(eventQueue.isEmpty());
    -}
    -
    -function testMultipleTargets() {
    -  var firstTarget = dom.getElement('hovertarget');
    -  var secondTarget = dom.getElement('second');
    -  var elsewhere = dom.getElement('notpopup');
    -  var element = tt.getElement();
    -
    -  tt.attach(firstTarget);
    -  tt.attach(secondTarget);
    -  tt.setShowDelayMs(100);
    -  tt.setHideDelayMs(50);
    -
    -  // Move over first target
    -  goog.testing.events.fireMouseOverEvent(firstTarget, elsewhere);
    -  clock.tick(101);
    -  assertEquals(goog.ui.PopupBase.EventType.SHOW, eventQueue.dequeue().type);
    -  assertTrue(eventQueue.isEmpty());
    -
    -  // Move from first to second
    -  goog.testing.events.fireMouseOutEvent(firstTarget, secondTarget);
    -  goog.testing.events.fireMouseOverEvent(secondTarget, firstTarget);
    -  assertEquals(goog.ui.Tooltip.State.UPDATING, tt.getState());
    -  assertTrue(eventQueue.isEmpty());
    -
    -  // Move from second to element (before second shows)
    -  goog.testing.events.fireMouseOutEvent(secondTarget, element);
    -  goog.testing.events.fireMouseOverEvent(element, secondTarget);
    -  assertEquals(goog.ui.Tooltip.State.SHOWING, tt.getState());
    -  assertTrue(eventQueue.isEmpty());
    -
    -  // Move from element to second, and let it show
    -  goog.testing.events.fireMouseOutEvent(element, secondTarget);
    -  goog.testing.events.fireMouseOverEvent(secondTarget, element);
    -  assertEquals(goog.ui.Tooltip.State.UPDATING, tt.getState());
    -  clock.tick(101);
    -  assertEquals(goog.ui.Tooltip.State.SHOWING, tt.getState());
    -  assertEquals('Anchor should be second target', secondTarget, tt.anchor);
    -  assertEquals(goog.ui.PopupBase.EventType.HIDE, eventQueue.dequeue().type);
    -  assertEquals(goog.ui.PopupBase.EventType.SHOW, eventQueue.dequeue().type);
    -  assertTrue(eventQueue.isEmpty());
    -
    -  // Move from second to first and then off without first showing
    -  goog.testing.events.fireMouseOutEvent(secondTarget, firstTarget);
    -  goog.testing.events.fireMouseOverEvent(firstTarget, secondTarget);
    -  assertEquals(goog.ui.Tooltip.State.UPDATING, tt.getState());
    -  goog.testing.events.fireMouseOutEvent(firstTarget, elsewhere);
    -  assertEquals(goog.ui.Tooltip.State.WAITING_TO_HIDE, tt.getState());
    -  clock.tick(51);
    -  assertEquals('hidden', tt.getElement().style.visibility);
    -  assertEquals(goog.ui.Tooltip.State.INACTIVE, tt.getState());
    -  assertEquals(goog.ui.PopupBase.EventType.HIDE, eventQueue.dequeue().type);
    -  assertTrue(eventQueue.isEmpty());
    -  clock.tick(200);
    -
    -  // Move from element to second, but detach second before it shows.
    -  goog.testing.events.fireMouseOutEvent(element, secondTarget);
    -  goog.testing.events.fireMouseOverEvent(secondTarget, element);
    -  assertEquals(goog.ui.Tooltip.State.WAITING_TO_SHOW, tt.getState());
    -  tt.detach(secondTarget);
    -  clock.tick(200);
    -  assertEquals(goog.ui.Tooltip.State.INACTIVE, tt.getState());
    -  assertEquals('Anchor should be second target', secondTarget, tt.anchor);
    -  assertTrue(eventQueue.isEmpty());
    -}
    -
    -function testRequireInteraction() {
    -  var hoverTarget = dom.getElement('hovertarget');
    -  var elsewhere = dom.getElement('notpopup');
    -
    -  tt.attach(hoverTarget);
    -  tt.setShowDelayMs(100);
    -  tt.setHideDelayMs(50);
    -  tt.setRequireInteraction(true);
    -
    -  goog.testing.events.fireMouseOverEvent(hoverTarget, elsewhere);
    -  clock.tick(101);
    -  assertEquals(
    -      'Tooltip should not show without mouse move event',
    -      'hidden', tt.getElement().style.visibility);
    -  goog.testing.events.fireMouseMoveEvent(hoverTarget);
    -  goog.testing.events.fireMouseOverEvent(hoverTarget, elsewhere);
    -  clock.tick(101);
    -  assertEquals(
    -      'Tooltip should show because we had mouse move event',
    -      'visible', tt.getElement().style.visibility);
    -
    -  goog.testing.events.fireMouseOutEvent(hoverTarget, elsewhere);
    -  clock.tick(51);
    -  assertEquals('hidden', tt.getElement().style.visibility);
    -  goog.testing.events.fireBrowserEvent(new goog.events.Event(
    -      goog.events.EventType.FOCUS, hoverTarget));
    -  clock.tick(101);
    -  assertEquals(
    -      'Tooltip should show because we had focus event',
    -      'visible', tt.getElement().style.visibility);
    -  goog.testing.events.fireBrowserEvent(new goog.events.Event(
    -      goog.events.EventType.BLUR, hoverTarget));
    -  clock.tick(51);
    -  assertEquals('hidden', tt.getElement().style.visibility);
    -
    -  goog.testing.events.fireMouseMoveEvent(hoverTarget);
    -  goog.testing.events.fireMouseOverEvent(hoverTarget, elsewhere);
    -  goog.testing.events.fireMouseOutEvent(hoverTarget, elsewhere);
    -  goog.testing.events.fireMouseOverEvent(hoverTarget, elsewhere);
    -  clock.tick(101);
    -  assertEquals(
    -      'A cancelled trigger should also cancel the seen interaction',
    -      'hidden', tt.getElement().style.visibility);
    -}
    -
    -function testDispose() {
    -  var element = tt.getElement();
    -  tt.dispose();
    -  assertTrue('Tooltip should have been disposed of', tt.isDisposed());
    -  assertNull('Tooltip element reference should have been nulled out',
    -      tt.getElement());
    -  assertNotEquals('Tooltip element should not be a child of the body',
    -      document.body, element.parentNode);
    -}
    -
    -function testNested() {
    -  var ttNested;
    -  tt.getElement().appendChild(dom.createDom(
    -      'span', {id: 'nested'}, 'Goodbye'));
    -  ttNested = new goog.ui.Tooltip(undefined, undefined, dom);
    -  ttNested.setElement(dom.createDom('div', {id: 'nestedPopup'}, 'hi'));
    -  tt.setShowDelayMs(100);
    -  tt.setHideDelayMs(50);
    -  ttNested.setShowDelayMs(75);
    -  ttNested.setHideDelayMs(25);
    -  var nestedAnchor = dom.getElement('nested');
    -  var hoverTarget = dom.getElement('hovertarget');
    -  var outerTooltip = dom.getElement('popup');
    -  var innerTooltip = dom.getElement('nestedPopup');
    -  var elsewhere = dom.getElement('notpopup');
    -
    -  ttNested.attach(nestedAnchor);
    -  tt.attach(hoverTarget);
    -
    -  // Test mouse into, out of nested tooltip
    -  goog.testing.events.fireMouseOverEvent(hoverTarget, elsewhere);
    -  clock.tick(101);
    -  goog.testing.events.fireMouseOutEvent(hoverTarget, outerTooltip);
    -  goog.testing.events.fireMouseOverEvent(outerTooltip, hoverTarget);
    -  clock.tick(51);
    -  assertEquals('visible', tt.getElement().style.visibility);
    -  goog.testing.events.fireMouseOutEvent(outerTooltip, nestedAnchor);
    -  goog.testing.events.fireMouseOverEvent(nestedAnchor, outerTooltip);
    -  clock.tick(76);
    -  assertEquals('visible', tt.getElement().style.visibility);
    -  assertEquals('visible', ttNested.getElement().style.visibility);
    -  goog.testing.events.fireMouseOutEvent(nestedAnchor, outerTooltip);
    -  goog.testing.events.fireMouseOverEvent(outerTooltip, nestedAnchor);
    -  clock.tick(100);
    -  assertEquals('visible', tt.getElement().style.visibility);
    -  assertEquals('hidden', ttNested.getElement().style.visibility);
    -
    -  // Go back in nested tooltip and then out through tooltip element.
    -  goog.testing.events.fireMouseOutEvent(outerTooltip, nestedAnchor);
    -  goog.testing.events.fireMouseOverEvent(nestedAnchor, outerTooltip);
    -  clock.tick(76);
    -  goog.testing.events.fireMouseOutEvent(nestedAnchor, innerTooltip);
    -  goog.testing.events.fireMouseOverEvent(innerTooltip, nestedAnchor);
    -  clock.tick(15);
    -  assertEquals('visible', tt.getElement().style.visibility);
    -  assertEquals('visible', ttNested.getElement().style.visibility);
    -  goog.testing.events.fireMouseOutEvent(innerTooltip, elsewhere);
    -  clock.tick(26);
    -  assertEquals('hidden', ttNested.getElement().style.visibility);
    -  clock.tick(51);
    -  assertEquals('hidden', tt.getElement().style.visibility);
    -
    -  // Test with focus
    -  goog.testing.events.fireBrowserEvent(new goog.events.Event(
    -      goog.events.EventType.FOCUS, hoverTarget));
    -  clock.tick(101);
    -  goog.testing.events.fireBrowserEvent(new goog.events.Event(
    -      goog.events.EventType.BLUR, hoverTarget));
    -  goog.testing.events.fireBrowserEvent(new goog.events.Event(
    -      goog.events.EventType.FOCUS, nestedAnchor));
    -  clock.tick(76);
    -  assertEquals('visible', tt.getElement().style.visibility);
    -  assertEquals('visible', ttNested.getElement().style.visibility);
    -  goog.testing.events.fireBrowserEvent(new goog.events.Event(
    -      goog.events.EventType.BLUR, nestedAnchor));
    -  goog.testing.events.fireBrowserEvent(new goog.events.Event(
    -      goog.events.EventType.FOCUS, hoverTarget));
    -  clock.tick(26);
    -  assertEquals('visible', tt.getElement().style.visibility);
    -  assertEquals('hidden', ttNested.getElement().style.visibility);
    -
    -  ttNested.onHide_();
    -  ttNested.dispose();
    -}
    -
    -function testPosition() {
    -  dom.getDocument().body.style.paddingBottom = '150%'; // force scrollbar
    -  var scrollEl = dom.getDocumentScrollElement();
    -
    -  var anchor = dom.getElement('hovertarget');
    -  var tooltip = new goog.ui.Tooltip(anchor, 'foo');
    -  tooltip.getElement().style.position = 'absolute';
    -
    -  tooltip.cursorPosition.x = 100;
    -  tooltip.cursorPosition.y = 100;
    -  tooltip.showForElement(anchor);
    -
    -  assertEquals('Tooltip should be at cursor position',
    -      '(110, 110)', // (100, 100) + padding (10, 10)
    -      goog.style.getPageOffset(tooltip.getElement()).toString());
    -
    -  scrollEl.scrollTop = 50;
    -
    -  var offset = goog.style.getPageOffset(tooltip.getElement());
    -  assertTrue('Tooltip should be at cursor position when scrolled',
    -      Math.abs(offset.x - 110) <= ALLOWED_OFFSET); // 100 + padding 10
    -  assertTrue('Tooltip should be at cursor position when scrolled',
    -      Math.abs(offset.y - 110) <= ALLOWED_OFFSET); // 100 + padding 10
    -
    -  tooltip.dispose();
    -  dom.getDocument().body.style.paddingTop = '';
    -  scrollEl.scrollTop = 0;
    -}
    -
    -function testPositionOverride() {
    -  var anchor = dom.getElement('hovertarget');
    -  var tooltip = new TestTooltip(anchor, 'foo', dom);
    -
    -  tooltip.showForElement(anchor);
    -
    -  assertEquals('Tooltip should be at absolute position', '(13, 17)',
    -      goog.style.getPageOffset(tooltip.getElement()).toString());
    -  tooltip.dispose();
    -}
    -
    -function testHtmlContent() {
    -  tt.setSafeHtml(goog.html.testing.newSafeHtmlForTest(
    -      '<span class="theSpan">Hello</span>'));
    -  var spanEl =
    -      goog.dom.getElementByClass('theSpan', tt.getElement());
    -  assertEquals('Hello', goog.dom.getTextContent(spanEl));
    -}
    -
    -function testSetContent_guardedByGlobalFlag() {
    -  /** @suppress {missingRequire} */
    -  stubs.set(goog.html.legacyconversions, 'ALLOW_LEGACY_CONVERSIONS', false);
    -  assertEquals(
    -      'Error: Legacy conversion from string to goog.html types is disabled',
    -      assertThrows(function() {
    -        tt.setHtml('<img src="blag" onerror="evil();">');
    -      }).message);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tree/basenode.js b/src/database/third_party/closure-library/closure/goog/ui/tree/basenode.js
    deleted file mode 100644
    index 964310a5cff..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tree/basenode.js
    +++ /dev/null
    @@ -1,1569 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Definition of the goog.ui.tree.BaseNode class.
    - *
    - * @author arv@google.com (Erik Arvidsson)
    - * @author eae@google.com (Emil A Eklund)
    - *
    - * This is a based on the webfx tree control. It since been updated to add
    - * typeahead support, as well as accessibility support using ARIA framework.
    - * See file comment in treecontrol.js.
    - */
    -
    -goog.provide('goog.ui.tree.BaseNode');
    -goog.provide('goog.ui.tree.BaseNode.EventType');
    -
    -goog.require('goog.Timer');
    -goog.require('goog.a11y.aria');
    -goog.require('goog.asserts');
    -goog.require('goog.dom.safe');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.html.SafeHtml');
    -goog.require('goog.html.SafeStyle');
    -goog.require('goog.html.legacyconversions');
    -goog.require('goog.string');
    -goog.require('goog.string.StringBuffer');
    -goog.require('goog.style');
    -goog.require('goog.ui.Component');
    -
    -
    -
    -/**
    - * An abstract base class for a node in the tree.
    - *
    - * @param {string|!goog.html.SafeHtml} html The html content of the node label.
    - * @param {Object=} opt_config The configuration for the tree. See
    - *    {@link goog.ui.tree.BaseNode.defaultConfig}. If not specified the
    - *    default config will be used.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @constructor
    - * @extends {goog.ui.Component}
    - */
    -goog.ui.tree.BaseNode = function(html, opt_config, opt_domHelper) {
    -  goog.ui.Component.call(this, opt_domHelper);
    -
    -  /**
    -   * The configuration for the tree.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.config_ = opt_config || goog.ui.tree.BaseNode.defaultConfig;
    -
    -  /**
    -   * HTML content of the node label.
    -   * @type {!goog.html.SafeHtml}
    -   * @private
    -   */
    -  this.html_ = (html instanceof goog.html.SafeHtml ? html :
    -      goog.html.legacyconversions.safeHtmlFromString(html));
    -
    -  /** @private {string} */
    -  this.iconClass_;
    -
    -  /** @private {string} */
    -  this.expandedIconClass_;
    -
    -  /** @protected {goog.ui.tree.TreeControl} */
    -  this.tree;
    -
    -  /** @private {goog.ui.tree.BaseNode} */
    -  this.previousSibling_;
    -
    -  /** @private {goog.ui.tree.BaseNode} */
    -  this.nextSibling_;
    -
    -  /** @private {goog.ui.tree.BaseNode} */
    -  this.firstChild_;
    -
    -  /** @private {goog.ui.tree.BaseNode} */
    -  this.lastChild_;
    -};
    -goog.inherits(goog.ui.tree.BaseNode, goog.ui.Component);
    -
    -
    -/**
    - * The event types dispatched by this class.
    - * @enum {string}
    - */
    -goog.ui.tree.BaseNode.EventType = {
    -  BEFORE_EXPAND: 'beforeexpand',
    -  EXPAND: 'expand',
    -  BEFORE_COLLAPSE: 'beforecollapse',
    -  COLLAPSE: 'collapse'
    -};
    -
    -
    -/**
    - * Map of nodes in existence. Needed to route events to the appropriate nodes.
    - * Nodes are added to the map at {@link #enterDocument} time and removed at
    - * {@link #exitDocument} time.
    - * @type {Object}
    - * @protected
    - */
    -goog.ui.tree.BaseNode.allNodes = {};
    -
    -
    -/**
    - * Whether the tree item is selected.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.tree.BaseNode.prototype.selected_ = false;
    -
    -
    -/**
    - * Whether the tree node is expanded.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.tree.BaseNode.prototype.expanded_ = false;
    -
    -
    -/**
    - * Tooltip for the tree item
    - * @type {?string}
    - * @private
    - */
    -goog.ui.tree.BaseNode.prototype.toolTip_ = null;
    -
    -
    -/**
    - * HTML that can appear after the label (so not inside the anchor).
    - * @type {!goog.html.SafeHtml}
    - * @private
    - */
    -goog.ui.tree.BaseNode.prototype.afterLabelHtml_ = goog.html.SafeHtml.EMPTY;
    -
    -
    -/**
    - * Whether to allow user to collapse this node.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.tree.BaseNode.prototype.isUserCollapsible_ = true;
    -
    -
    -/**
    - * Nesting depth of this node; cached result of computeDepth_.
    - * -1 if value has not been cached.
    - * @type {number}
    - * @private
    - */
    -goog.ui.tree.BaseNode.prototype.depth_ = -1;
    -
    -
    -/** @override */
    -goog.ui.tree.BaseNode.prototype.disposeInternal = function() {
    -  goog.ui.tree.BaseNode.superClass_.disposeInternal.call(this);
    -  if (this.tree) {
    -    this.tree.removeNode(this);
    -    this.tree = null;
    -  }
    -  this.setElementInternal(null);
    -};
    -
    -
    -/**
    - * Adds roles and states.
    - * @protected
    - */
    -goog.ui.tree.BaseNode.prototype.initAccessibility = function() {
    -  var el = this.getElement();
    -  if (el) {
    -    // Set an id for the label
    -    var label = this.getLabelElement();
    -    if (label && !label.id) {
    -      label.id = this.getId() + '.label';
    -    }
    -
    -    goog.a11y.aria.setRole(el, 'treeitem');
    -    goog.a11y.aria.setState(el, 'selected', false);
    -    goog.a11y.aria.setState(el, 'expanded', false);
    -    goog.a11y.aria.setState(el, 'level', this.getDepth());
    -    if (label) {
    -      goog.a11y.aria.setState(el, 'labelledby', label.id);
    -    }
    -
    -    var img = this.getIconElement();
    -    if (img) {
    -      goog.a11y.aria.setRole(img, 'presentation');
    -    }
    -    var ei = this.getExpandIconElement();
    -    if (ei) {
    -      goog.a11y.aria.setRole(ei, 'presentation');
    -    }
    -
    -    var ce = this.getChildrenElement();
    -    if (ce) {
    -      goog.a11y.aria.setRole(ce, 'group');
    -
    -      // In case the children will be created lazily.
    -      if (ce.hasChildNodes()) {
    -        // do setsize for each child
    -        var count = this.getChildCount();
    -        for (var i = 1; i <= count; i++) {
    -          var child = this.getChildAt(i - 1).getElement();
    -          goog.asserts.assert(child, 'The child element cannot be null');
    -          goog.a11y.aria.setState(child, 'setsize', count);
    -          goog.a11y.aria.setState(child, 'posinset', i);
    -        }
    -      }
    -    }
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.tree.BaseNode.prototype.createDom = function() {
    -  var element = this.getDomHelper().safeHtmlToNode(this.toSafeHtml());
    -  this.setElementInternal(/** @type {!Element} */ (element));
    -};
    -
    -
    -/** @override */
    -goog.ui.tree.BaseNode.prototype.enterDocument = function() {
    -  goog.ui.tree.BaseNode.superClass_.enterDocument.call(this);
    -  goog.ui.tree.BaseNode.allNodes[this.getId()] = this;
    -  this.initAccessibility();
    -};
    -
    -
    -/** @override */
    -goog.ui.tree.BaseNode.prototype.exitDocument = function() {
    -  goog.ui.tree.BaseNode.superClass_.exitDocument.call(this);
    -  delete goog.ui.tree.BaseNode.allNodes[this.getId()];
    -};
    -
    -
    -/**
    - * The method assumes that the child doesn't have parent node yet.
    - * The {@code opt_render} argument is not used. If the parent node is expanded,
    - * the child node's state will be the same as the parent's. Otherwise the
    - * child's DOM tree won't be created.
    - * @override
    - */
    -goog.ui.tree.BaseNode.prototype.addChildAt = function(child, index,
    -    opt_render) {
    -  goog.asserts.assert(!child.getParent());
    -  goog.asserts.assertInstanceof(child, goog.ui.tree.BaseNode);
    -  var prevNode = this.getChildAt(index - 1);
    -  var nextNode = this.getChildAt(index);
    -
    -  goog.ui.tree.BaseNode.superClass_.addChildAt.call(this, child, index);
    -
    -  child.previousSibling_ = prevNode;
    -  child.nextSibling_ = nextNode;
    -
    -  if (prevNode) {
    -    prevNode.nextSibling_ = child;
    -  } else {
    -    this.firstChild_ = child;
    -  }
    -  if (nextNode) {
    -    nextNode.previousSibling_ = child;
    -  } else {
    -    this.lastChild_ = child;
    -  }
    -
    -  var tree = this.getTree();
    -  if (tree) {
    -    child.setTreeInternal(tree);
    -  }
    -
    -  child.setDepth_(this.getDepth() + 1);
    -
    -  if (this.getElement()) {
    -    this.updateExpandIcon();
    -    if (this.getExpanded()) {
    -      var el = this.getChildrenElement();
    -      if (!child.getElement()) {
    -        child.createDom();
    -      }
    -      var childElement = child.getElement();
    -      var nextElement = nextNode && nextNode.getElement();
    -      el.insertBefore(childElement, nextElement);
    -
    -      if (this.isInDocument()) {
    -        child.enterDocument();
    -      }
    -
    -      if (!nextNode) {
    -        if (prevNode) {
    -          prevNode.updateExpandIcon();
    -        } else {
    -          goog.style.setElementShown(el, true);
    -          this.setExpanded(this.getExpanded());
    -        }
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Adds a node as a child to the current node.
    - * @param {goog.ui.tree.BaseNode} child The child to add.
    - * @param {goog.ui.tree.BaseNode=} opt_before If specified, the new child is
    - *    added as a child before this one. If not specified, it's appended to the
    - *    end.
    - * @return {!goog.ui.tree.BaseNode} The added child.
    - */
    -goog.ui.tree.BaseNode.prototype.add = function(child, opt_before) {
    -  goog.asserts.assert(!opt_before || opt_before.getParent() == this,
    -      'Can only add nodes before siblings');
    -  if (child.getParent()) {
    -    child.getParent().removeChild(child);
    -  }
    -  this.addChildAt(child,
    -      opt_before ? this.indexOfChild(opt_before) : this.getChildCount());
    -  return child;
    -};
    -
    -
    -/**
    - * Removes a child. The caller is responsible for disposing the node.
    - * @param {goog.ui.Component|string} childNode The child to remove. Must be a
    - *     {@link goog.ui.tree.BaseNode}.
    - * @param {boolean=} opt_unrender Unused. The child will always be unrendered.
    - * @return {!goog.ui.tree.BaseNode} The child that was removed.
    - * @override
    - */
    -goog.ui.tree.BaseNode.prototype.removeChild =
    -    function(childNode, opt_unrender) {
    -  // In reality, this only accepts BaseNodes.
    -  var child = /** @type {goog.ui.tree.BaseNode} */ (childNode);
    -
    -  // if we remove selected or tree with the selected we should select this
    -  var tree = this.getTree();
    -  var selectedNode = tree ? tree.getSelectedItem() : null;
    -  if (selectedNode == child || child.contains(selectedNode)) {
    -    if (tree.hasFocus()) {
    -      this.select();
    -      goog.Timer.callOnce(this.onTimeoutSelect_, 10, this);
    -    } else {
    -      this.select();
    -    }
    -  }
    -
    -  goog.ui.tree.BaseNode.superClass_.removeChild.call(this, child);
    -
    -  if (this.lastChild_ == child) {
    -    this.lastChild_ = child.previousSibling_;
    -  }
    -  if (this.firstChild_ == child) {
    -    this.firstChild_ = child.nextSibling_;
    -  }
    -  if (child.previousSibling_) {
    -    child.previousSibling_.nextSibling_ = child.nextSibling_;
    -  }
    -  if (child.nextSibling_) {
    -    child.nextSibling_.previousSibling_ = child.previousSibling_;
    -  }
    -
    -  var wasLast = child.isLastSibling();
    -
    -  child.tree = null;
    -  child.depth_ = -1;
    -
    -  if (tree) {
    -    // Tell the tree control that this node is now removed.
    -    tree.removeNode(this);
    -
    -    if (this.isInDocument()) {
    -      var el = this.getChildrenElement();
    -
    -      if (child.isInDocument()) {
    -        var childEl = child.getElement();
    -        el.removeChild(childEl);
    -
    -        child.exitDocument();
    -      }
    -
    -      if (wasLast) {
    -        var newLast = this.getLastChild();
    -        if (newLast) {
    -          newLast.updateExpandIcon();
    -        }
    -      }
    -      if (!this.hasChildren()) {
    -        el.style.display = 'none';
    -        this.updateExpandIcon();
    -        this.updateIcon_();
    -      }
    -    }
    -  }
    -
    -  return child;
    -};
    -
    -
    -/**
    - * @deprecated Use {@link #removeChild}.
    - */
    -goog.ui.tree.BaseNode.prototype.remove =
    -    goog.ui.tree.BaseNode.prototype.removeChild;
    -
    -
    -/**
    - * Handler for setting focus asynchronously.
    - * @private
    - */
    -goog.ui.tree.BaseNode.prototype.onTimeoutSelect_ = function() {
    -  this.select();
    -};
    -
    -
    -/**
    - * Returns the tree.
    - */
    -goog.ui.tree.BaseNode.prototype.getTree = goog.abstractMethod;
    -
    -
    -/**
    - * Returns the depth of the node in the tree. Should not be overridden.
    - * @return {number} The non-negative depth of this node (the root is zero).
    - */
    -goog.ui.tree.BaseNode.prototype.getDepth = function() {
    -  var depth = this.depth_;
    -  if (depth < 0) {
    -    depth = this.computeDepth_();
    -    this.setDepth_(depth);
    -  }
    -  return depth;
    -};
    -
    -
    -/**
    - * Computes the depth of the node in the tree.
    - * Called only by getDepth, when the depth hasn't already been cached.
    - * @return {number} The non-negative depth of this node (the root is zero).
    - * @private
    - */
    -goog.ui.tree.BaseNode.prototype.computeDepth_ = function() {
    -  var parent = this.getParent();
    -  if (parent) {
    -    return parent.getDepth() + 1;
    -  } else {
    -    return 0;
    -  }
    -};
    -
    -
    -/**
    - * Changes the depth of a node (and all its descendants).
    - * @param {number} depth The new nesting depth; must be non-negative.
    - * @private
    - */
    -goog.ui.tree.BaseNode.prototype.setDepth_ = function(depth) {
    -  if (depth != this.depth_) {
    -    this.depth_ = depth;
    -    var row = this.getRowElement();
    -    if (row) {
    -      var indent = this.getPixelIndent_() + 'px';
    -      if (this.isRightToLeft()) {
    -        row.style.paddingRight = indent;
    -      } else {
    -        row.style.paddingLeft = indent;
    -      }
    -    }
    -    this.forEachChild(function(child) {
    -      child.setDepth_(depth + 1);
    -    });
    -  }
    -};
    -
    -
    -/**
    - * Returns true if the node is a descendant of this node
    - * @param {goog.ui.tree.BaseNode} node The node to check.
    - * @return {boolean} True if the node is a descendant of this node, false
    - *    otherwise.
    - */
    -goog.ui.tree.BaseNode.prototype.contains = function(node) {
    -  var current = node;
    -  while (current) {
    -    if (current == this) {
    -      return true;
    -    }
    -    current = current.getParent();
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * An array of empty children to return for nodes that have no children.
    - * @type {!Array<!goog.ui.tree.BaseNode>}
    - * @private
    - */
    -goog.ui.tree.BaseNode.EMPTY_CHILDREN_ = [];
    -
    -
    -/**
    - * @param {number} index 0-based index.
    - * @return {goog.ui.tree.BaseNode} The child at the given index; null if none.
    - */
    -goog.ui.tree.BaseNode.prototype.getChildAt;
    -
    -
    -/**
    - * Returns the children of this node.
    - * @return {!Array<!goog.ui.tree.BaseNode>} The children.
    - */
    -goog.ui.tree.BaseNode.prototype.getChildren = function() {
    -  var children = [];
    -  this.forEachChild(function(child) {
    -    children.push(child);
    -  });
    -  return children;
    -};
    -
    -
    -/**
    - * @return {goog.ui.tree.BaseNode} The first child of this node.
    - */
    -goog.ui.tree.BaseNode.prototype.getFirstChild = function() {
    -  return this.getChildAt(0);
    -};
    -
    -
    -/**
    - * @return {goog.ui.tree.BaseNode} The last child of this node.
    - */
    -goog.ui.tree.BaseNode.prototype.getLastChild = function() {
    -  return this.getChildAt(this.getChildCount() - 1);
    -};
    -
    -
    -/**
    - * @return {goog.ui.tree.BaseNode} The previous sibling of this node.
    - */
    -goog.ui.tree.BaseNode.prototype.getPreviousSibling = function() {
    -  return this.previousSibling_;
    -};
    -
    -
    -/**
    - * @return {goog.ui.tree.BaseNode} The next sibling of this node.
    - */
    -goog.ui.tree.BaseNode.prototype.getNextSibling = function() {
    -  return this.nextSibling_;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the node is the last sibling.
    - */
    -goog.ui.tree.BaseNode.prototype.isLastSibling = function() {
    -  return !this.nextSibling_;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the node is selected.
    - */
    -goog.ui.tree.BaseNode.prototype.isSelected = function() {
    -  return this.selected_;
    -};
    -
    -
    -/**
    - * Selects the node.
    - */
    -goog.ui.tree.BaseNode.prototype.select = function() {
    -  var tree = this.getTree();
    -  if (tree) {
    -    tree.setSelectedItem(this);
    -  }
    -};
    -
    -
    -/**
    - * Originally it was intended to deselect the node but never worked.
    - * @deprecated Use {@code tree.setSelectedItem(null)}.
    - */
    -goog.ui.tree.BaseNode.prototype.deselect = goog.nullFunction;
    -
    -
    -/**
    - * Called from the tree to instruct the node change its selection state.
    - * @param {boolean} selected The new selection state.
    - * @protected
    - */
    -goog.ui.tree.BaseNode.prototype.setSelectedInternal = function(selected) {
    -  if (this.selected_ == selected) {
    -    return;
    -  }
    -  this.selected_ = selected;
    -
    -  this.updateRow();
    -
    -  var el = this.getElement();
    -  if (el) {
    -    goog.a11y.aria.setState(el, 'selected', selected);
    -    if (selected) {
    -      var treeElement = this.getTree().getElement();
    -      goog.asserts.assert(treeElement,
    -          'The DOM element for the tree cannot be null');
    -      goog.a11y.aria.setState(treeElement,
    -          'activedescendant',
    -          this.getId());
    -    }
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the node is expanded.
    - */
    -goog.ui.tree.BaseNode.prototype.getExpanded = function() {
    -  return this.expanded_;
    -};
    -
    -
    -/**
    - * Sets the node to be expanded internally, without state change events.
    - * @param {boolean} expanded Whether to expand or close the node.
    - */
    -goog.ui.tree.BaseNode.prototype.setExpandedInternal = function(expanded) {
    -  this.expanded_ = expanded;
    -};
    -
    -
    -/**
    - * Sets the node to be expanded.
    - * @param {boolean} expanded Whether to expand or close the node.
    - */
    -goog.ui.tree.BaseNode.prototype.setExpanded = function(expanded) {
    -  var isStateChange = expanded != this.expanded_;
    -  if (isStateChange) {
    -    // Only fire events if the expanded state has actually changed.
    -    var prevented = !this.dispatchEvent(
    -        expanded ? goog.ui.tree.BaseNode.EventType.BEFORE_EXPAND :
    -        goog.ui.tree.BaseNode.EventType.BEFORE_COLLAPSE);
    -    if (prevented) return;
    -  }
    -  var ce;
    -  this.expanded_ = expanded;
    -  var tree = this.getTree();
    -  var el = this.getElement();
    -
    -  if (this.hasChildren()) {
    -    if (!expanded && tree && this.contains(tree.getSelectedItem())) {
    -      this.select();
    -    }
    -
    -    if (el) {
    -      ce = this.getChildrenElement();
    -      if (ce) {
    -        goog.style.setElementShown(ce, expanded);
    -
    -        // Make sure we have the HTML for the children here.
    -        if (expanded && this.isInDocument() && !ce.hasChildNodes()) {
    -          var children = [];
    -          this.forEachChild(function(child) {
    -            children.push(child.toSafeHtml());
    -          });
    -          goog.dom.safe.setInnerHtml(ce, goog.html.SafeHtml.concat(children));
    -          this.forEachChild(function(child) {
    -            child.enterDocument();
    -          });
    -        }
    -      }
    -      this.updateExpandIcon();
    -    }
    -  } else {
    -    ce = this.getChildrenElement();
    -    if (ce) {
    -      goog.style.setElementShown(ce, false);
    -    }
    -  }
    -  if (el) {
    -    this.updateIcon_();
    -    goog.a11y.aria.setState(el, 'expanded', expanded);
    -  }
    -
    -  if (isStateChange) {
    -    this.dispatchEvent(expanded ? goog.ui.tree.BaseNode.EventType.EXPAND :
    -                       goog.ui.tree.BaseNode.EventType.COLLAPSE);
    -  }
    -};
    -
    -
    -/**
    - * Toggles the expanded state of the node.
    - */
    -goog.ui.tree.BaseNode.prototype.toggle = function() {
    -  this.setExpanded(!this.getExpanded());
    -};
    -
    -
    -/**
    - * Expands the node.
    - */
    -goog.ui.tree.BaseNode.prototype.expand = function() {
    -  this.setExpanded(true);
    -};
    -
    -
    -/**
    - * Collapses the node.
    - */
    -goog.ui.tree.BaseNode.prototype.collapse = function() {
    -  this.setExpanded(false);
    -};
    -
    -
    -/**
    - * Collapses the children of the node.
    - */
    -goog.ui.tree.BaseNode.prototype.collapseChildren = function() {
    -  this.forEachChild(function(child) {
    -    child.collapseAll();
    -  });
    -};
    -
    -
    -/**
    - * Collapses the children and the node.
    - */
    -goog.ui.tree.BaseNode.prototype.collapseAll = function() {
    -  this.collapseChildren();
    -  this.collapse();
    -};
    -
    -
    -/**
    - * Expands the children of the node.
    - */
    -goog.ui.tree.BaseNode.prototype.expandChildren = function() {
    -  this.forEachChild(function(child) {
    -    child.expandAll();
    -  });
    -};
    -
    -
    -/**
    - * Expands the children and the node.
    - */
    -goog.ui.tree.BaseNode.prototype.expandAll = function() {
    -  this.expandChildren();
    -  this.expand();
    -};
    -
    -
    -/**
    - * Expands the parent chain of this node so that it is visible.
    - */
    -goog.ui.tree.BaseNode.prototype.reveal = function() {
    -  var parent = this.getParent();
    -  if (parent) {
    -    parent.setExpanded(true);
    -    parent.reveal();
    -  }
    -};
    -
    -
    -/**
    - * Sets whether the node will allow the user to collapse it.
    - * @param {boolean} isCollapsible Whether to allow node collapse.
    - */
    -goog.ui.tree.BaseNode.prototype.setIsUserCollapsible = function(isCollapsible) {
    -  this.isUserCollapsible_ = isCollapsible;
    -  if (!this.isUserCollapsible_) {
    -    this.expand();
    -  }
    -  if (this.getElement()) {
    -    this.updateExpandIcon();
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the node is collapsible by user actions.
    - */
    -goog.ui.tree.BaseNode.prototype.isUserCollapsible = function() {
    -  return this.isUserCollapsible_;
    -};
    -
    -
    -/**
    - * Creates HTML for the node.
    - * @return {!goog.html.SafeHtml}
    - * @protected
    - */
    -goog.ui.tree.BaseNode.prototype.toSafeHtml = function() {
    -  var tree = this.getTree();
    -  var hideLines = !tree.getShowLines() ||
    -      tree == this.getParent() && !tree.getShowRootLines();
    -
    -  var childClass = hideLines ? this.config_.cssChildrenNoLines :
    -      this.config_.cssChildren;
    -
    -  var nonEmptyAndExpanded = this.getExpanded() && this.hasChildren();
    -
    -  var attributes = {
    -    'class': childClass,
    -    'style': this.getLineStyle()
    -  };
    -
    -  var content = [];
    -  if (nonEmptyAndExpanded) {
    -    // children
    -    this.forEachChild(function(child) {
    -      content.push(child.toSafeHtml());
    -    });
    -  }
    -
    -  var children = goog.html.SafeHtml.create('div', attributes, content);
    -
    -  return goog.html.SafeHtml.create('div',
    -      {'class': this.config_.cssItem, 'id': this.getId()},
    -      [this.getRowSafeHtml(), children]);
    -};
    -
    -
    -/**
    - * @return {number} The pixel indent of the row.
    - * @private
    - */
    -goog.ui.tree.BaseNode.prototype.getPixelIndent_ = function() {
    -  return Math.max(0, (this.getDepth() - 1) * this.config_.indentWidth);
    -};
    -
    -
    -/**
    - * @return {!goog.html.SafeHtml} The html for the row.
    - * @protected
    - */
    -goog.ui.tree.BaseNode.prototype.getRowSafeHtml = function() {
    -  var style = {};
    -  style['padding-' + (this.isRightToLeft() ? 'right' : 'left')] =
    -      this.getPixelIndent_() + 'px';
    -  var attributes = {
    -    'class': this.getRowClassName(),
    -    'style': style
    -  };
    -  var content = [
    -    this.getExpandIconSafeHtml(),
    -    this.getIconSafeHtml(),
    -    this.getLabelSafeHtml()
    -  ];
    -  return goog.html.SafeHtml.create('div', attributes, content);
    -};
    -
    -
    -/**
    - * @return {string} The class name for the row.
    - * @protected
    - */
    -goog.ui.tree.BaseNode.prototype.getRowClassName = function() {
    -  var selectedClass;
    -  if (this.isSelected()) {
    -    selectedClass = ' ' + this.config_.cssSelectedRow;
    -  } else {
    -    selectedClass = '';
    -  }
    -  return this.config_.cssTreeRow + selectedClass;
    -};
    -
    -
    -/**
    - * @return {!goog.html.SafeHtml} The html for the label.
    - * @protected
    - */
    -goog.ui.tree.BaseNode.prototype.getLabelSafeHtml = function() {
    -  var html = goog.html.SafeHtml.create('span',
    -      {
    -        'class': this.config_.cssItemLabel,
    -        'title': this.getToolTip() || null
    -      },
    -      this.getSafeHtml());
    -  return goog.html.SafeHtml.concat(html,
    -      goog.html.SafeHtml.create('span', {}, this.getAfterLabelSafeHtml()));
    -};
    -
    -
    -/**
    - * Returns the html that appears after the label. This is useful if you want to
    - * put extra UI on the row of the label but not inside the anchor tag.
    - * @return {string} The html.
    - * @final
    - */
    -goog.ui.tree.BaseNode.prototype.getAfterLabelHtml = function() {
    -  return goog.html.SafeHtml.unwrap(this.getAfterLabelSafeHtml());
    -};
    -
    -
    -/**
    - * Returns the html that appears after the label. This is useful if you want to
    - * put extra UI on the row of the label but not inside the anchor tag.
    - * @return {!goog.html.SafeHtml} The html.
    - */
    -goog.ui.tree.BaseNode.prototype.getAfterLabelSafeHtml = function() {
    -  return this.afterLabelHtml_;
    -};
    -
    -
    -// TODO(jakubvrana): Deprecate in favor of setSafeHtml, once developer docs on
    -// using goog.html.SafeHtml are in place.
    -/**
    - * Sets the html that appears after the label. This is useful if you want to
    - * put extra UI on the row of the label but not inside the anchor tag.
    - * @param {string} html The html.
    - */
    -goog.ui.tree.BaseNode.prototype.setAfterLabelHtml = function(html) {
    -  this.setAfterLabelSafeHtml(goog.html.legacyconversions.safeHtmlFromString(
    -      html));
    -};
    -
    -
    -/**
    - * Sets the html that appears after the label. This is useful if you want to
    - * put extra UI on the row of the label but not inside the anchor tag.
    - * @param {!goog.html.SafeHtml} html The html.
    - */
    -goog.ui.tree.BaseNode.prototype.setAfterLabelSafeHtml = function(html) {
    -  this.afterLabelHtml_ = html;
    -  var el = this.getAfterLabelElement();
    -  if (el) {
    -    goog.dom.safe.setInnerHtml(el, html);
    -  }
    -};
    -
    -
    -/**
    - * @return {!goog.html.SafeHtml} The html for the icon.
    - * @protected
    - */
    -goog.ui.tree.BaseNode.prototype.getIconSafeHtml = function() {
    -  return goog.html.SafeHtml.create('span', {
    -    'style': {'display': 'inline-block'},
    -    'class': this.getCalculatedIconClass()
    -  });
    -};
    -
    -
    -/**
    - * Gets the calculated icon class.
    - * @protected
    - */
    -goog.ui.tree.BaseNode.prototype.getCalculatedIconClass = goog.abstractMethod;
    -
    -
    -/**
    - * @return {!goog.html.SafeHtml} The source for the icon.
    - * @protected
    - */
    -goog.ui.tree.BaseNode.prototype.getExpandIconSafeHtml = function() {
    -  return goog.html.SafeHtml.create('span', {
    -    'type': 'expand',
    -    'style': {'display': 'inline-block'},
    -    'class': this.getExpandIconClass()
    -  });
    -};
    -
    -
    -/**
    - * @return {string} The class names of the icon used for expanding the node.
    - * @protected
    - */
    -goog.ui.tree.BaseNode.prototype.getExpandIconClass = function() {
    -  var tree = this.getTree();
    -  var hideLines = !tree.getShowLines() ||
    -      tree == this.getParent() && !tree.getShowRootLines();
    -
    -  var config = this.config_;
    -  var sb = new goog.string.StringBuffer();
    -  sb.append(config.cssTreeIcon, ' ', config.cssExpandTreeIcon, ' ');
    -
    -  if (this.hasChildren()) {
    -    var bits = 0;
    -    /*
    -      Bitmap used to determine which icon to use
    -      1  Plus
    -      2  Minus
    -      4  T Line
    -      8  L Line
    -    */
    -
    -    if (tree.getShowExpandIcons() && this.isUserCollapsible_) {
    -      if (this.getExpanded()) {
    -        bits = 2;
    -      } else {
    -        bits = 1;
    -      }
    -    }
    -
    -    if (!hideLines) {
    -      if (this.isLastSibling()) {
    -        bits += 4;
    -      } else {
    -        bits += 8;
    -      }
    -    }
    -
    -    switch (bits) {
    -      case 1:
    -        sb.append(config.cssExpandTreeIconPlus);
    -        break;
    -      case 2:
    -        sb.append(config.cssExpandTreeIconMinus);
    -        break;
    -      case 4:
    -        sb.append(config.cssExpandTreeIconL);
    -        break;
    -      case 5:
    -        sb.append(config.cssExpandTreeIconLPlus);
    -        break;
    -      case 6:
    -        sb.append(config.cssExpandTreeIconLMinus);
    -        break;
    -      case 8:
    -        sb.append(config.cssExpandTreeIconT);
    -        break;
    -      case 9:
    -        sb.append(config.cssExpandTreeIconTPlus);
    -        break;
    -      case 10:
    -        sb.append(config.cssExpandTreeIconTMinus);
    -        break;
    -      default:  // 0
    -        sb.append(config.cssExpandTreeIconBlank);
    -    }
    -  } else {
    -    if (hideLines) {
    -      sb.append(config.cssExpandTreeIconBlank);
    -    } else if (this.isLastSibling()) {
    -      sb.append(config.cssExpandTreeIconL);
    -    } else {
    -      sb.append(config.cssExpandTreeIconT);
    -    }
    -  }
    -  return sb.toString();
    -};
    -
    -
    -/**
    - * @return {!goog.html.SafeStyle} The line style.
    - */
    -goog.ui.tree.BaseNode.prototype.getLineStyle = function() {
    -  var nonEmptyAndExpanded = this.getExpanded() && this.hasChildren();
    -  return goog.html.SafeStyle.create({
    -    'background-position': this.getBackgroundPosition(),
    -    'display': nonEmptyAndExpanded ? null : 'none'
    -  });
    -};
    -
    -
    -/**
    - * @return {string} The background position style value.
    - */
    -goog.ui.tree.BaseNode.prototype.getBackgroundPosition = function() {
    -  return (this.isLastSibling() ? '-100' :
    -          (this.getDepth() - 1) * this.config_.indentWidth) + 'px 0';
    -};
    -
    -
    -/**
    - * @return {Element} The element for the tree node.
    - * @override
    - */
    -goog.ui.tree.BaseNode.prototype.getElement = function() {
    -  var el = goog.ui.tree.BaseNode.superClass_.getElement.call(this);
    -  if (!el) {
    -    el = this.getDomHelper().getElement(this.getId());
    -    this.setElementInternal(el);
    -  }
    -  return el;
    -};
    -
    -
    -/**
    - * @return {Element} The row is the div that is used to draw the node without
    - *     the children.
    - */
    -goog.ui.tree.BaseNode.prototype.getRowElement = function() {
    -  var el = this.getElement();
    -  return el ? /** @type {Element} */ (el.firstChild) : null;
    -};
    -
    -
    -/**
    - * @return {Element} The expanded icon element.
    - * @protected
    - */
    -goog.ui.tree.BaseNode.prototype.getExpandIconElement = function() {
    -  var el = this.getRowElement();
    -  return el ? /** @type {Element} */ (el.firstChild) : null;
    -};
    -
    -
    -/**
    - * @return {Element} The icon element.
    - * @protected
    - */
    -goog.ui.tree.BaseNode.prototype.getIconElement = function() {
    -  var el = this.getRowElement();
    -  return el ? /** @type {Element} */ (el.childNodes[1]) : null;
    -};
    -
    -
    -/**
    - * @return {Element} The label element.
    - */
    -goog.ui.tree.BaseNode.prototype.getLabelElement = function() {
    -  var el = this.getRowElement();
    -  // TODO: find/fix race condition that requires us to add
    -  // the lastChild check
    -  return el && el.lastChild ?
    -      /** @type {Element} */ (el.lastChild.previousSibling) : null;
    -};
    -
    -
    -/**
    - * @return {Element} The element after the label.
    - */
    -goog.ui.tree.BaseNode.prototype.getAfterLabelElement = function() {
    -  var el = this.getRowElement();
    -  return el ? /** @type {Element} */ (el.lastChild) : null;
    -};
    -
    -
    -/**
    - * @return {Element} The div containing the children.
    - * @protected
    - */
    -goog.ui.tree.BaseNode.prototype.getChildrenElement = function() {
    -  var el = this.getElement();
    -  return el ? /** @type {Element} */ (el.lastChild) : null;
    -};
    -
    -
    -/**
    - * Sets the icon class for the node.
    - * @param {string} s The icon class.
    - */
    -goog.ui.tree.BaseNode.prototype.setIconClass = function(s) {
    -  this.iconClass_ = s;
    -  if (this.isInDocument()) {
    -    this.updateIcon_();
    -  }
    -};
    -
    -
    -/**
    - * Gets the icon class for the node.
    - * @return {string} s The icon source.
    - */
    -goog.ui.tree.BaseNode.prototype.getIconClass = function() {
    -  return this.iconClass_;
    -};
    -
    -
    -/**
    - * Sets the icon class for when the node is expanded.
    - * @param {string} s The expanded icon class.
    - */
    -goog.ui.tree.BaseNode.prototype.setExpandedIconClass = function(s) {
    -  this.expandedIconClass_ = s;
    -  if (this.isInDocument()) {
    -    this.updateIcon_();
    -  }
    -};
    -
    -
    -/**
    - * Gets the icon class for when the node is expanded.
    - * @return {string} The class.
    - */
    -goog.ui.tree.BaseNode.prototype.getExpandedIconClass = function() {
    -  return this.expandedIconClass_;
    -};
    -
    -
    -/**
    - * Sets the text of the label.
    - * @param {string} s The plain text of the label.
    - */
    -goog.ui.tree.BaseNode.prototype.setText = function(s) {
    -  this.setSafeHtml(goog.html.SafeHtml.htmlEscape(s));
    -};
    -
    -
    -/**
    - * Returns the text of the label. If the text was originally set as HTML, the
    - * return value is unspecified.
    - * @return {string} The plain text of the label.
    - */
    -goog.ui.tree.BaseNode.prototype.getText = function() {
    -  return goog.string.unescapeEntities(goog.html.SafeHtml.unwrap(this.html_));
    -};
    -
    -
    -// TODO(jakubvrana): Deprecate in favor of setSafeHtml, once developer docs on
    -// using goog.html.SafeHtml are in place.
    -/**
    - * Sets the html of the label.
    - * @param {string} s The html string for the label.
    - */
    -goog.ui.tree.BaseNode.prototype.setHtml = function(s) {
    -  this.setSafeHtml(goog.html.legacyconversions.safeHtmlFromString(s));
    -};
    -
    -
    -/**
    - * Sets the HTML of the label.
    - * @param {!goog.html.SafeHtml} html The HTML object for the label.
    - */
    -goog.ui.tree.BaseNode.prototype.setSafeHtml = function(html) {
    -  this.html_ = html;
    -  var el = this.getLabelElement();
    -  if (el) {
    -    goog.dom.safe.setInnerHtml(el, html);
    -  }
    -  var tree = this.getTree();
    -  if (tree) {
    -    // Tell the tree control about the updated label text.
    -    tree.setNode(this);
    -  }
    -};
    -
    -
    -/**
    - * Returns the html of the label.
    - * @return {string} The html string of the label.
    - * @final
    - */
    -goog.ui.tree.BaseNode.prototype.getHtml = function() {
    -  return goog.html.SafeHtml.unwrap(this.getSafeHtml());
    -};
    -
    -
    -/**
    - * Returns the html of the label.
    - * @return {!goog.html.SafeHtml} The html string of the label.
    - */
    -goog.ui.tree.BaseNode.prototype.getSafeHtml = function() {
    -  return this.html_;
    -};
    -
    -
    -/**
    - * Sets the text of the tooltip.
    - * @param {string} s The tooltip text to set.
    - */
    -goog.ui.tree.BaseNode.prototype.setToolTip = function(s) {
    -  this.toolTip_ = s;
    -  var el = this.getLabelElement();
    -  if (el) {
    -    el.title = s;
    -  }
    -};
    -
    -
    -/**
    - * Returns the text of the tooltip.
    - * @return {?string} The tooltip text.
    - */
    -goog.ui.tree.BaseNode.prototype.getToolTip = function() {
    -  return this.toolTip_;
    -};
    -
    -
    -/**
    - * Updates the row styles.
    - */
    -goog.ui.tree.BaseNode.prototype.updateRow = function() {
    -  var rowEl = this.getRowElement();
    -  if (rowEl) {
    -    rowEl.className = this.getRowClassName();
    -  }
    -};
    -
    -
    -/**
    - * Updates the expand icon of the node.
    - */
    -goog.ui.tree.BaseNode.prototype.updateExpandIcon = function() {
    -  var img = this.getExpandIconElement();
    -  if (img) {
    -    img.className = this.getExpandIconClass();
    -  }
    -  var cel = this.getChildrenElement();
    -  if (cel) {
    -    cel.style.backgroundPosition = this.getBackgroundPosition();
    -  }
    -};
    -
    -
    -/**
    - * Updates the icon of the node. Assumes that this.getElement() is created.
    - * @private
    - */
    -goog.ui.tree.BaseNode.prototype.updateIcon_ = function() {
    -  this.getIconElement().className = this.getCalculatedIconClass();
    -};
    -
    -
    -/**
    - * Handles mouse down event.
    - * @param {!goog.events.BrowserEvent} e The browser event.
    - * @protected
    - */
    -goog.ui.tree.BaseNode.prototype.onMouseDown = function(e) {
    -  var el = e.target;
    -  // expand icon
    -  var type = el.getAttribute('type');
    -  if (type == 'expand' && this.hasChildren()) {
    -    if (this.isUserCollapsible_) {
    -      this.toggle();
    -    }
    -    return;
    -  }
    -
    -  this.select();
    -  this.updateRow();
    -};
    -
    -
    -/**
    - * Handles a click event.
    - * @param {!goog.events.BrowserEvent} e The browser event.
    - * @protected
    - * @suppress {underscore|visibility}
    - */
    -goog.ui.tree.BaseNode.prototype.onClick_ = goog.events.Event.preventDefault;
    -
    -
    -/**
    - * Handles a double click event.
    - * @param {!goog.events.BrowserEvent} e The browser event.
    - * @protected
    - * @suppress {underscore|visibility}
    - */
    -goog.ui.tree.BaseNode.prototype.onDoubleClick_ = function(e) {
    -  var el = e.target;
    -  // expand icon
    -  var type = el.getAttribute('type');
    -  if (type == 'expand' && this.hasChildren()) {
    -    return;
    -  }
    -
    -  if (this.isUserCollapsible_) {
    -    this.toggle();
    -  }
    -};
    -
    -
    -/**
    - * Handles a key down event.
    - * @param {!goog.events.BrowserEvent} e The browser event.
    - * @return {boolean} The handled value.
    - * @protected
    - */
    -goog.ui.tree.BaseNode.prototype.onKeyDown = function(e) {
    -  var handled = true;
    -  switch (e.keyCode) {
    -    case goog.events.KeyCodes.RIGHT:
    -      if (e.altKey) {
    -        break;
    -      }
    -      if (this.hasChildren()) {
    -        if (!this.getExpanded()) {
    -          this.setExpanded(true);
    -        } else {
    -          this.getFirstChild().select();
    -        }
    -      }
    -      break;
    -
    -    case goog.events.KeyCodes.LEFT:
    -      if (e.altKey) {
    -        break;
    -      }
    -      if (this.hasChildren() && this.getExpanded() && this.isUserCollapsible_) {
    -        this.setExpanded(false);
    -      } else {
    -        var parent = this.getParent();
    -        var tree = this.getTree();
    -        // don't go to root if hidden
    -        if (parent && (tree.getShowRootNode() || parent != tree)) {
    -          parent.select();
    -        }
    -      }
    -      break;
    -
    -    case goog.events.KeyCodes.DOWN:
    -      var nextNode = this.getNextShownNode();
    -      if (nextNode) {
    -        nextNode.select();
    -      }
    -      break;
    -
    -    case goog.events.KeyCodes.UP:
    -      var previousNode = this.getPreviousShownNode();
    -      if (previousNode) {
    -        previousNode.select();
    -      }
    -      break;
    -
    -    default:
    -      handled = false;
    -  }
    -
    -  if (handled) {
    -    e.preventDefault();
    -    var tree = this.getTree();
    -    if (tree) {
    -      // clear type ahead buffer as user navigates with arrow keys
    -      tree.clearTypeAhead();
    -    }
    -  }
    -
    -  return handled;
    -};
    -
    -
    -
    -/**
    - * @return {goog.ui.tree.BaseNode} The last shown descendant.
    - */
    -goog.ui.tree.BaseNode.prototype.getLastShownDescendant = function() {
    -  if (!this.getExpanded() || !this.hasChildren()) {
    -    return this;
    -  }
    -  // we know there is at least 1 child
    -  return this.getLastChild().getLastShownDescendant();
    -};
    -
    -
    -/**
    - * @return {goog.ui.tree.BaseNode} The next node to show or null if there isn't
    - *     a next node to show.
    - */
    -goog.ui.tree.BaseNode.prototype.getNextShownNode = function() {
    -  if (this.hasChildren() && this.getExpanded()) {
    -    return this.getFirstChild();
    -  } else {
    -    var parent = this;
    -    var next;
    -    while (parent != this.getTree()) {
    -      next = parent.getNextSibling();
    -      if (next != null) {
    -        return next;
    -      }
    -      parent = parent.getParent();
    -    }
    -    return null;
    -  }
    -};
    -
    -
    -/**
    - * @return {goog.ui.tree.BaseNode} The previous node to show.
    - */
    -goog.ui.tree.BaseNode.prototype.getPreviousShownNode = function() {
    -  var ps = this.getPreviousSibling();
    -  if (ps != null) {
    -    return ps.getLastShownDescendant();
    -  }
    -  var parent = this.getParent();
    -  var tree = this.getTree();
    -  if (!tree.getShowRootNode() && parent == tree) {
    -    return null;
    -  }
    -  // The root is the first node.
    -  if (this == tree) {
    -    return null;
    -  }
    -  return /** @type {goog.ui.tree.BaseNode} */ (parent);
    -};
    -
    -
    -/**
    - * @return {*} Data set by the client.
    - * @deprecated Use {@link #getModel} instead.
    - */
    -goog.ui.tree.BaseNode.prototype.getClientData =
    -    goog.ui.tree.BaseNode.prototype.getModel;
    -
    -
    -/**
    - * Sets client data to associate with the node.
    - * @param {*} data The client data to associate with the node.
    - * @deprecated Use {@link #setModel} instead.
    - */
    -goog.ui.tree.BaseNode.prototype.setClientData =
    -    goog.ui.tree.BaseNode.prototype.setModel;
    -
    -
    -/**
    - * @return {Object} The configuration for the tree.
    - */
    -goog.ui.tree.BaseNode.prototype.getConfig = function() {
    -  return this.config_;
    -};
    -
    -
    -/**
    - * Internal method that is used to set the tree control on the node.
    - * @param {goog.ui.tree.TreeControl} tree The tree control.
    - */
    -goog.ui.tree.BaseNode.prototype.setTreeInternal = function(tree) {
    -  if (this.tree != tree) {
    -    this.tree = tree;
    -    // Add new node to the type ahead node map.
    -    tree.setNode(this);
    -    this.forEachChild(function(child) {
    -      child.setTreeInternal(tree);
    -    });
    -  }
    -};
    -
    -
    -/**
    - * A default configuration for the tree.
    - */
    -goog.ui.tree.BaseNode.defaultConfig = {
    -  indentWidth: 19,
    -  cssRoot: goog.getCssName('goog-tree-root') + ' ' +
    -      goog.getCssName('goog-tree-item'),
    -  cssHideRoot: goog.getCssName('goog-tree-hide-root'),
    -  cssItem: goog.getCssName('goog-tree-item'),
    -  cssChildren: goog.getCssName('goog-tree-children'),
    -  cssChildrenNoLines: goog.getCssName('goog-tree-children-nolines'),
    -  cssTreeRow: goog.getCssName('goog-tree-row'),
    -  cssItemLabel: goog.getCssName('goog-tree-item-label'),
    -  cssTreeIcon: goog.getCssName('goog-tree-icon'),
    -  cssExpandTreeIcon: goog.getCssName('goog-tree-expand-icon'),
    -  cssExpandTreeIconPlus: goog.getCssName('goog-tree-expand-icon-plus'),
    -  cssExpandTreeIconMinus: goog.getCssName('goog-tree-expand-icon-minus'),
    -  cssExpandTreeIconTPlus: goog.getCssName('goog-tree-expand-icon-tplus'),
    -  cssExpandTreeIconTMinus: goog.getCssName('goog-tree-expand-icon-tminus'),
    -  cssExpandTreeIconLPlus: goog.getCssName('goog-tree-expand-icon-lplus'),
    -  cssExpandTreeIconLMinus: goog.getCssName('goog-tree-expand-icon-lminus'),
    -  cssExpandTreeIconT: goog.getCssName('goog-tree-expand-icon-t'),
    -  cssExpandTreeIconL: goog.getCssName('goog-tree-expand-icon-l'),
    -  cssExpandTreeIconBlank: goog.getCssName('goog-tree-expand-icon-blank'),
    -  cssExpandedFolderIcon: goog.getCssName('goog-tree-expanded-folder-icon'),
    -  cssCollapsedFolderIcon: goog.getCssName('goog-tree-collapsed-folder-icon'),
    -  cssFileIcon: goog.getCssName('goog-tree-file-icon'),
    -  cssExpandedRootIcon: goog.getCssName('goog-tree-expanded-folder-icon'),
    -  cssCollapsedRootIcon: goog.getCssName('goog-tree-collapsed-folder-icon'),
    -  cssSelectedRow: goog.getCssName('selected')
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tree/basenode_test.html b/src/database/third_party/closure-library/closure/goog/ui/tree/basenode_test.html
    deleted file mode 100644
    index cc89e9bf6fe..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tree/basenode_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -  Author: arv@google.com (Erik Arvidsson)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.tree.BaseNode
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.tree.BaseNodeTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tree/basenode_test.js b/src/database/third_party/closure-library/closure/goog/ui/tree/basenode_test.js
    deleted file mode 100644
    index 6642ac8a49d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tree/basenode_test.js
    +++ /dev/null
    @@ -1,290 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.tree.BaseNodeTest');
    -goog.setTestOnly('goog.ui.tree.BaseNodeTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.html.legacyconversions');
    -goog.require('goog.html.testing');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.tree.BaseNode');
    -goog.require('goog.ui.tree.TreeControl');
    -goog.require('goog.ui.tree.TreeNode');
    -var stubs = new goog.testing.PropertyReplacer();
    -
    -function setUp() {
    -  // Reset global flags to their defaults.
    -  stubs.set(goog.html.legacyconversions, 'ALLOW_LEGACY_CONVERSIONS', true);
    -}
    -
    -function testAdd() {
    -  var node1 = new goog.ui.tree.TreeNode('node1');
    -  var node2 = new goog.ui.tree.TreeNode('node2');
    -  var node3 = new goog.ui.tree.TreeNode('node3');
    -  var node4 = new goog.ui.tree.TreeNode('node4');
    -
    -  assertEquals('node2 added', node2, node1.add(node2));
    -  assertEquals('node3 added', node3, node1.add(node3));
    -  assertEquals('node4 added', node4, node1.add(node4, node3));
    -
    -  assertEquals('node1 has 3 children', 3, node1.getChildCount());
    -  assertEquals('first child', node2, node1.getChildAt(0));
    -  assertEquals('second child', node4, node1.getChildAt(1));
    -  assertEquals('third child', node3, node1.getChildAt(2));
    -  assertNull('node1 has no parent', node1.getParent());
    -  assertEquals('the parent of node2 is node1', node1, node2.getParent());
    -
    -  assertEquals('node4 moved under node2', node4, node2.add(node4));
    -  assertEquals('node1 has 2 children', 2, node1.getChildCount());
    -  assertEquals('node2 has 1 child', 1, node2.getChildCount());
    -  assertEquals('the child of node2 is node4', node4, node2.getChildAt(0));
    -  assertEquals('the parent of node4 is node2', node2, node4.getParent());
    -}
    -
    -function testExpandIconAfterAddChild() {
    -  var tree = new goog.ui.tree.TreeControl('root');
    -  var node1 = new goog.ui.tree.TreeNode('node1');
    -  var node2 = new goog.ui.tree.TreeNode('node2');
    -  tree.render(goog.dom.createDom('div'));
    -  tree.addChild(node1);
    -
    -  node1.addChild(node2);
    -  assertTrue('expand icon of node1 changed to L+', goog.dom.classlist.contains(
    -      node1.getExpandIconElement(), 'goog-tree-expand-icon-lplus'));
    -
    -  node1.removeChild(node2);
    -  assertFalse('expand icon of node1 changed back to L',
    -      goog.dom.classlist.contains(
    -          node1.getExpandIconElement(), 'goog-tree-expand-icon-lplus'));
    -}
    -
    -function testExpandEvents() {
    -  var n = new goog.ui.tree.BaseNode('');
    -  n.getTree = function() {};
    -  var expanded = false;
    -  n.setExpanded(expanded);
    -  assertEquals(expanded, n.getExpanded());
    -  var callCount = 0;
    -  n.addEventListener(goog.ui.tree.BaseNode.EventType.BEFORE_EXPAND,
    -      function(e) {
    -        assertEquals(expanded, n.getExpanded());
    -        callCount++;
    -      });
    -  n.addEventListener(goog.ui.tree.BaseNode.EventType.EXPAND,
    -      function(e) {
    -        assertEquals(!expanded, n.getExpanded());
    -        callCount++;
    -      });
    -  n.setExpanded(!expanded);
    -  assertEquals(2, callCount);
    -}
    -
    -function testExpandEvents2() {
    -  var n = new goog.ui.tree.BaseNode('');
    -  n.getTree = function() {};
    -  var expanded = true;
    -  n.setExpanded(expanded);
    -  assertEquals(expanded, n.getExpanded());
    -  var callCount = 0;
    -  n.addEventListener(goog.ui.tree.BaseNode.EventType.BEFORE_COLLAPSE,
    -      function(e) {
    -        assertEquals(expanded, n.getExpanded());
    -        callCount++;
    -      });
    -  n.addEventListener(goog.ui.tree.BaseNode.EventType.COLLAPSE,
    -      function(e) {
    -        assertEquals(!expanded, n.getExpanded());
    -        callCount++;
    -      });
    -  n.setExpanded(!expanded);
    -  assertEquals(2, callCount);
    -}
    -
    -function testExpandEventsPreventDefault() {
    -  var n = new goog.ui.tree.BaseNode('');
    -  n.getTree = function() {};
    -  var expanded = true;
    -  n.setExpanded(expanded);
    -  assertEquals(expanded, n.getExpanded());
    -  var callCount = 0;
    -  n.addEventListener(goog.ui.tree.BaseNode.EventType.BEFORE_COLLAPSE,
    -      function(e) {
    -        assertEquals(expanded, n.getExpanded());
    -        e.preventDefault();
    -        callCount++;
    -      });
    -  n.addEventListener(goog.ui.tree.BaseNode.EventType.COLLAPSE,
    -      function(e) {
    -        fail('Should not fire COLLAPSE');
    -      });
    -  n.setExpanded(!expanded);
    -  assertEquals(1, callCount);
    -}
    -
    -function testExpandEventsPreventDefault2() {
    -  var n = new goog.ui.tree.BaseNode('');
    -  n.getTree = function() {};
    -  var expanded = false;
    -  n.setExpanded(expanded);
    -  assertEquals(expanded, n.getExpanded());
    -  var callCount = 0;
    -  n.addEventListener(goog.ui.tree.BaseNode.EventType.BEFORE_EXPAND,
    -      function(e) {
    -        assertEquals(expanded, n.getExpanded());
    -        e.preventDefault();
    -        callCount++;
    -      });
    -  n.addEventListener(goog.ui.tree.BaseNode.EventType.EXPAND,
    -      function(e) {
    -        fail('Should not fire EXPAND');
    -      });
    -  n.setExpanded(!expanded);
    -  assertEquals(1, callCount);
    -}
    -
    -function testGetNextShownNode() {
    -  var tree = new goog.ui.tree.TreeControl('tree');
    -  assertNull('next node for unpopulated tree', tree.getNextShownNode());
    -
    -  var node1 = new goog.ui.tree.TreeNode('node1');
    -  var node2 = new goog.ui.tree.TreeNode('node2');
    -  var node3 = new goog.ui.tree.TreeNode('node3');
    -  node1.add(node2);
    -  node1.add(node3);
    -
    -  assertNull('next node for unexpanded node1', node1.getNextShownNode());
    -  node1.expand();
    -  assertEquals('next node for expanded node1', node2, node1.getNextShownNode());
    -  assertEquals('next node for node2', node3, node2.getNextShownNode());
    -  assertNull('next node for node3', node3.getNextShownNode());
    -
    -  tree.add(node1);
    -  assertEquals('next node for populated tree', node1, tree.getNextShownNode());
    -  assertNull('next node for node3 inside the tree', node3.getNextShownNode());
    -
    -  var component = new goog.ui.Component();
    -  component.addChild(tree);
    -  assertNull('next node for node3 inside the tree if the tree has parent',
    -      node3.getNextShownNode());
    -}
    -
    -function testGetPreviousShownNode() {
    -  var tree = new goog.ui.tree.TreeControl('tree');
    -  assertNull('next node for unpopulated tree', tree.getPreviousShownNode());
    -
    -  var node1 = new goog.ui.tree.TreeNode('node1');
    -  var node2 = new goog.ui.tree.TreeNode('node2');
    -  var node3 = new goog.ui.tree.TreeNode('node3');
    -  tree.add(node1);
    -  node1.add(node2);
    -  tree.add(node3);
    -
    -  assertEquals('prev node for node3 when node1 is unexpanded',
    -               node1, node3.getPreviousShownNode());
    -  node1.expand();
    -  assertEquals('prev node for node3 when node1 is expanded',
    -               node2, node3.getPreviousShownNode());
    -  assertEquals('prev node for node2 when node1 is expanded',
    -               node1, node2.getPreviousShownNode());
    -  assertEquals('prev node for node1 when root is shown', tree,
    -               node1.getPreviousShownNode());
    -  tree.setShowRootNode(false);
    -  assertNull('next node for node1 when root is not shown',
    -             node1.getPreviousShownNode());
    -
    -  var component = new goog.ui.Component();
    -  component.addChild(tree);
    -  assertNull('prev node for root if the tree has parent',
    -             tree.getPreviousShownNode());
    -}
    -
    -function testInvisibleNodesInUnrenderedTree() {
    -  var tree = new goog.ui.tree.TreeControl('tree');
    -  var a = new goog.ui.tree.TreeNode('a');
    -  var b = new goog.ui.tree.TreeNode('b');
    -  tree.add(a);
    -  a.add(b);
    -  tree.render();
    -
    -  var textContent =
    -      tree.getElement().textContent || tree.getElement().innerText;
    -  assertContains('Node should be rendered.', 'tree', textContent);
    -  assertContains('Node should be rendered.', 'a', textContent);
    -  assertNotContains('Unexpanded node child should not be rendered.',
    -      'b', textContent);
    -
    -  a.expand();
    -  var textContent =
    -      tree.getElement().textContent || tree.getElement().innerText;
    -  assertContains('Node should be rendered.', 'tree', textContent);
    -  assertContains('Node should be rendered.', 'a', textContent);
    -  assertContains('Expanded node child should be rendered.', 'b', textContent);
    -  tree.dispose();
    -}
    -
    -function testInvisibleNodesInRenderedTree() {
    -  var tree = new goog.ui.tree.TreeControl('tree');
    -  tree.render();
    -  var a = new goog.ui.tree.TreeNode('a');
    -  var b = new goog.ui.tree.TreeNode('b');
    -  tree.add(a);
    -  a.add(b);
    -
    -  var textContent =
    -      tree.getElement().textContent || tree.getElement().innerText;
    -  assertContains('Node should be rendered.', 'tree', textContent);
    -  assertContains('Node should be rendered.', 'a', textContent);
    -  assertNotContains('Unexpanded node child should not be rendered.',
    -      'b', textContent);
    -
    -  a.expand();
    -  var textContent =
    -      tree.getElement().textContent || tree.getElement().innerText;
    -  assertContains('Node should be rendered.', 'tree', textContent);
    -  assertContains('Node should be rendered.', 'a', textContent);
    -  assertContains('Expanded node child should be rendered.', 'b', textContent);
    -  tree.dispose();
    -}
    -
    -function testConstructor() {
    -  var tree = new goog.ui.tree.TreeControl('tree');
    -  assertEquals('tree', tree.getHtml());
    -
    -  tree = new goog.ui.tree.TreeControl(
    -      goog.html.testing.newSafeHtmlForTest('tree'));
    -  assertEquals('tree', tree.getHtml());
    -}
    -
    -function testSetHtml() {
    -  var tree = new goog.ui.tree.TreeControl('');
    -  tree.setHtml('<b>tree</b>');
    -  assertEquals('<b>tree</b>', tree.getHtml());
    -
    -  tree = new goog.ui.tree.TreeControl('');
    -  tree.setSafeHtml(goog.html.testing.newSafeHtmlForTest('<b>tree</b>'));
    -  assertEquals('<b>tree</b>', tree.getHtml());
    -}
    -
    -function testSetHtml_guardedByGlobalFlag() {
    -  stubs.set(goog.html.legacyconversions, 'ALLOW_LEGACY_CONVERSIONS', false);
    -  assertEquals(
    -      'Error: Legacy conversion from string to goog.html types is disabled',
    -      assertThrows(function() {
    -        new goog.ui.tree.TreeControl('<img src="blag" onerror="evil();">');
    -      }).message);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tree/treecontrol.js b/src/database/third_party/closure-library/closure/goog/ui/tree/treecontrol.js
    deleted file mode 100644
    index b61a8fc88e7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tree/treecontrol.js
    +++ /dev/null
    @@ -1,642 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Definition of the goog.ui.tree.TreeControl class, which
    - * provides a way to view a hierarchical set of data.
    - *
    - * @author arv@google.com (Erik Arvidsson)
    - * @author eae@google.com (Emil A Eklund)
    - *
    - * This is a based on the webfx tree control. It since been updated to add
    - * typeahead support, as well as accessibility support using ARIA framework.
    - *
    - * @see ../../demos/tree/demo.html
    - */
    -
    -goog.provide('goog.ui.tree.TreeControl');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.asserts');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.FocusHandler');
    -goog.require('goog.events.KeyHandler');
    -goog.require('goog.html.SafeHtml');
    -goog.require('goog.log');
    -goog.require('goog.ui.tree.BaseNode');
    -goog.require('goog.ui.tree.TreeNode');
    -goog.require('goog.ui.tree.TypeAhead');
    -goog.require('goog.userAgent');
    -
    -
    -
    -/**
    - * This creates a TreeControl object. A tree control provides a way to
    - * view a hierarchical set of data.
    - * @param {string|!goog.html.SafeHtml} html The HTML content of the node label.
    - * @param {Object=} opt_config The configuration for the tree. See
    - *    goog.ui.tree.TreeControl.defaultConfig. If not specified, a default config
    - *    will be used.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @constructor
    - * @extends {goog.ui.tree.BaseNode}
    - */
    -goog.ui.tree.TreeControl = function(html, opt_config, opt_domHelper) {
    -  goog.ui.tree.BaseNode.call(this, html, opt_config, opt_domHelper);
    -
    -  // The root is open and selected by default.
    -  this.setExpandedInternal(true);
    -  this.setSelectedInternal(true);
    -
    -  this.selectedItem_ = this;
    -
    -  /**
    -   * Used for typeahead support.
    -   * @type {!goog.ui.tree.TypeAhead}
    -   * @private
    -   */
    -  this.typeAhead_ = new goog.ui.tree.TypeAhead();
    -
    -  if (goog.userAgent.IE) {
    -    /** @preserveTry */
    -    try {
    -      // works since IE6SP1
    -      document.execCommand('BackgroundImageCache', false, true);
    -    } catch (e) {
    -      goog.log.warning(this.logger_, 'Failed to enable background image cache');
    -    }
    -  }
    -};
    -goog.inherits(goog.ui.tree.TreeControl, goog.ui.tree.BaseNode);
    -
    -
    -/**
    - * The object handling keyboard events.
    - * @type {goog.events.KeyHandler}
    - * @private
    - */
    -goog.ui.tree.TreeControl.prototype.keyHandler_ = null;
    -
    -
    -/**
    - * The object handling focus events.
    - * @type {goog.events.FocusHandler}
    - * @private
    - */
    -goog.ui.tree.TreeControl.prototype.focusHandler_ = null;
    -
    -
    -/**
    - * Logger
    - * @type {goog.log.Logger}
    - * @private
    - */
    -goog.ui.tree.TreeControl.prototype.logger_ =
    -    goog.log.getLogger('goog.ui.tree.TreeControl');
    -
    -
    -/**
    - * Whether the tree is focused.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.tree.TreeControl.prototype.focused_ = false;
    -
    -
    -/**
    - * Child node that currently has focus.
    - * @type {goog.ui.tree.BaseNode}
    - * @private
    - */
    -goog.ui.tree.TreeControl.prototype.focusedNode_ = null;
    -
    -
    -/**
    - * Whether to show lines.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.tree.TreeControl.prototype.showLines_ = true;
    -
    -
    -/**
    - * Whether to show expanded lines.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.tree.TreeControl.prototype.showExpandIcons_ = true;
    -
    -
    -/**
    - * Whether to show the root node.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.tree.TreeControl.prototype.showRootNode_ = true;
    -
    -
    -/**
    - * Whether to show the root lines.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.tree.TreeControl.prototype.showRootLines_ = true;
    -
    -
    -/** @override */
    -goog.ui.tree.TreeControl.prototype.getTree = function() {
    -  return this;
    -};
    -
    -
    -/** @override */
    -goog.ui.tree.TreeControl.prototype.getDepth = function() {
    -  return 0;
    -};
    -
    -
    -/**
    - * Expands the parent chain of this node so that it is visible.
    - * @override
    - */
    -goog.ui.tree.TreeControl.prototype.reveal = function() {
    -  // always expanded by default
    -  // needs to be overriden so that we don't try to reveal our parent
    -  // which is a generic component
    -};
    -
    -
    -/**
    - * Handles focus on the tree.
    - * @param {!goog.events.BrowserEvent} e The browser event.
    - * @private
    - */
    -goog.ui.tree.TreeControl.prototype.handleFocus_ = function(e) {
    -  this.focused_ = true;
    -  goog.dom.classlist.add(
    -      goog.asserts.assert(this.getElement()),
    -      goog.getCssName('focused'));
    -
    -  if (this.selectedItem_) {
    -    this.selectedItem_.select();
    -  }
    -};
    -
    -
    -/**
    - * Handles blur on the tree.
    - * @param {!goog.events.BrowserEvent} e The browser event.
    - * @private
    - */
    -goog.ui.tree.TreeControl.prototype.handleBlur_ = function(e) {
    -  this.focused_ = false;
    -  goog.dom.classlist.remove(
    -      goog.asserts.assert(this.getElement()),
    -      goog.getCssName('focused'));
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the tree has keyboard focus.
    - */
    -goog.ui.tree.TreeControl.prototype.hasFocus = function() {
    -  return this.focused_;
    -};
    -
    -
    -/** @override */
    -goog.ui.tree.TreeControl.prototype.getExpanded = function() {
    -  return !this.showRootNode_ ||
    -      goog.ui.tree.TreeControl.superClass_.getExpanded.call(this);
    -};
    -
    -
    -/** @override */
    -goog.ui.tree.TreeControl.prototype.setExpanded = function(expanded) {
    -  if (!this.showRootNode_) {
    -    this.setExpandedInternal(expanded);
    -  } else {
    -    goog.ui.tree.TreeControl.superClass_.setExpanded.call(this, expanded);
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.tree.TreeControl.prototype.getExpandIconSafeHtml = function() {
    -  // no expand icon for root element
    -  return goog.html.SafeHtml.EMPTY;
    -};
    -
    -
    -/** @override */
    -goog.ui.tree.TreeControl.prototype.getIconElement = function() {
    -  var el = this.getRowElement();
    -  return el ? /** @type {Element} */ (el.firstChild) : null;
    -};
    -
    -
    -/** @override */
    -goog.ui.tree.TreeControl.prototype.getExpandIconElement = function() {
    -  // no expand icon for root element
    -  return null;
    -};
    -
    -
    -/** @override */
    -goog.ui.tree.TreeControl.prototype.updateExpandIcon = function() {
    -  // no expand icon
    -};
    -
    -
    -/** @override */
    -goog.ui.tree.TreeControl.prototype.getRowClassName = function() {
    -  return goog.ui.tree.TreeControl.superClass_.getRowClassName.call(this) +
    -      (this.showRootNode_ ? '' : ' ' + this.getConfig().cssHideRoot);
    -};
    -
    -
    -/**
    - * Returns the source for the icon.
    - * @return {string} Src for the icon.
    - * @override
    - */
    -goog.ui.tree.TreeControl.prototype.getCalculatedIconClass = function() {
    -  var expanded = this.getExpanded();
    -  var expandedIconClass = this.getExpandedIconClass();
    -  if (expanded && expandedIconClass) {
    -    return expandedIconClass;
    -  }
    -  var iconClass = this.getIconClass();
    -  if (!expanded && iconClass) {
    -    return iconClass;
    -  }
    -
    -  // fall back on default icons
    -  var config = this.getConfig();
    -  if (expanded && config.cssExpandedRootIcon) {
    -    return config.cssTreeIcon + ' ' + config.cssExpandedRootIcon;
    -  } else if (!expanded && config.cssCollapsedRootIcon) {
    -    return config.cssTreeIcon + ' ' + config.cssCollapsedRootIcon;
    -  }
    -  return '';
    -};
    -
    -
    -/**
    - * Sets the selected item.
    - * @param {goog.ui.tree.BaseNode} node The item to select.
    - */
    -goog.ui.tree.TreeControl.prototype.setSelectedItem = function(node) {
    -  if (this.selectedItem_ == node) {
    -    return;
    -  }
    -
    -  var hadFocus = false;
    -  if (this.selectedItem_) {
    -    hadFocus = this.selectedItem_ == this.focusedNode_;
    -    this.selectedItem_.setSelectedInternal(false);
    -  }
    -
    -  this.selectedItem_ = node;
    -
    -  if (node) {
    -    node.setSelectedInternal(true);
    -    if (hadFocus) {
    -      node.select();
    -    }
    -  }
    -
    -  this.dispatchEvent(goog.events.EventType.CHANGE);
    -};
    -
    -
    -/**
    - * Returns the selected item.
    - * @return {goog.ui.tree.BaseNode} The currently selected item.
    - */
    -goog.ui.tree.TreeControl.prototype.getSelectedItem = function() {
    -  return this.selectedItem_;
    -};
    -
    -
    -/**
    - * Sets whether to show lines.
    - * @param {boolean} b Whether to show lines.
    - */
    -goog.ui.tree.TreeControl.prototype.setShowLines = function(b) {
    -  if (this.showLines_ != b) {
    -    this.showLines_ = b;
    -    if (this.isInDocument()) {
    -      this.updateLinesAndExpandIcons_();
    -    }
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} Whether to show lines.
    - */
    -goog.ui.tree.TreeControl.prototype.getShowLines = function() {
    -  return this.showLines_;
    -};
    -
    -
    -/**
    - * Updates the lines after the tree has been drawn.
    - * @private
    - */
    -goog.ui.tree.TreeControl.prototype.updateLinesAndExpandIcons_ = function() {
    -  var tree = this;
    -  var showLines = tree.getShowLines();
    -  var showRootLines = tree.getShowRootLines();
    -
    -  /**
    -   * Recursively walk through all nodes and update the class names of the
    -   * expand icon and the children element.
    -   * @param {!goog.ui.tree.BaseNode} node
    -   */
    -  function updateShowLines(node) {
    -    var childrenEl = node.getChildrenElement();
    -    if (childrenEl) {
    -      var hideLines = !showLines || tree == node.getParent() && !showRootLines;
    -      var childClass = hideLines ? node.getConfig().cssChildrenNoLines :
    -          node.getConfig().cssChildren;
    -      childrenEl.className = childClass;
    -
    -      var expandIconEl = node.getExpandIconElement();
    -      if (expandIconEl) {
    -        expandIconEl.className = node.getExpandIconClass();
    -      }
    -    }
    -    node.forEachChild(updateShowLines);
    -  }
    -  updateShowLines(this);
    -};
    -
    -
    -/**
    - * Sets whether to show root lines.
    - * @param {boolean} b Whether to show root lines.
    - */
    -goog.ui.tree.TreeControl.prototype.setShowRootLines = function(b) {
    -  if (this.showRootLines_ != b) {
    -    this.showRootLines_ = b;
    -    if (this.isInDocument()) {
    -      this.updateLinesAndExpandIcons_();
    -    }
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} Whether to show root lines.
    - */
    -goog.ui.tree.TreeControl.prototype.getShowRootLines = function() {
    -  return this.showRootLines_;
    -};
    -
    -
    -/**
    - * Sets whether to show expand icons.
    - * @param {boolean} b Whether to show expand icons.
    - */
    -goog.ui.tree.TreeControl.prototype.setShowExpandIcons = function(b) {
    -  if (this.showExpandIcons_ != b) {
    -    this.showExpandIcons_ = b;
    -    if (this.isInDocument()) {
    -      this.updateLinesAndExpandIcons_();
    -    }
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} Whether to show expand icons.
    - */
    -goog.ui.tree.TreeControl.prototype.getShowExpandIcons = function() {
    -  return this.showExpandIcons_;
    -};
    -
    -
    -/**
    - * Sets whether to show the root node.
    - * @param {boolean} b Whether to show the root node.
    - */
    -goog.ui.tree.TreeControl.prototype.setShowRootNode = function(b) {
    -  if (this.showRootNode_ != b) {
    -    this.showRootNode_ = b;
    -    if (this.isInDocument()) {
    -      var el = this.getRowElement();
    -      if (el) {
    -        el.className = this.getRowClassName();
    -      }
    -    }
    -    // Ensure that we do not hide the selected item.
    -    if (!b && this.getSelectedItem() == this && this.getFirstChild()) {
    -      this.setSelectedItem(this.getFirstChild());
    -    }
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} Whether to show the root node.
    - */
    -goog.ui.tree.TreeControl.prototype.getShowRootNode = function() {
    -  return this.showRootNode_;
    -};
    -
    -
    -/**
    - * Add roles and states.
    - * @protected
    - * @override
    - */
    -goog.ui.tree.TreeControl.prototype.initAccessibility = function() {
    -  goog.ui.tree.TreeControl.superClass_.initAccessibility.call(this);
    -
    -  var elt = this.getElement();
    -  goog.asserts.assert(elt, 'The DOM element for the tree cannot be null.');
    -  goog.a11y.aria.setRole(elt, 'tree');
    -  goog.a11y.aria.setState(elt, 'labelledby', this.getLabelElement().id);
    -};
    -
    -
    -/** @override */
    -goog.ui.tree.TreeControl.prototype.enterDocument = function() {
    -  goog.ui.tree.TreeControl.superClass_.enterDocument.call(this);
    -  var el = this.getElement();
    -  el.className = this.getConfig().cssRoot;
    -  el.setAttribute('hideFocus', 'true');
    -  this.attachEvents_();
    -  this.initAccessibility();
    -};
    -
    -
    -/** @override */
    -goog.ui.tree.TreeControl.prototype.exitDocument = function() {
    -  goog.ui.tree.TreeControl.superClass_.exitDocument.call(this);
    -  this.detachEvents_();
    -};
    -
    -
    -/**
    - * Adds the event listeners to the tree.
    - * @private
    - */
    -goog.ui.tree.TreeControl.prototype.attachEvents_ = function() {
    -  var el = this.getElement();
    -  el.tabIndex = 0;
    -
    -  var kh = this.keyHandler_ = new goog.events.KeyHandler(el);
    -  var fh = this.focusHandler_ = new goog.events.FocusHandler(el);
    -
    -  this.getHandler().
    -      listen(fh, goog.events.FocusHandler.EventType.FOCUSOUT, this.handleBlur_).
    -      listen(fh, goog.events.FocusHandler.EventType.FOCUSIN, this.handleFocus_).
    -      listen(kh, goog.events.KeyHandler.EventType.KEY, this.handleKeyEvent).
    -      listen(el, goog.events.EventType.MOUSEDOWN, this.handleMouseEvent_).
    -      listen(el, goog.events.EventType.CLICK, this.handleMouseEvent_).
    -      listen(el, goog.events.EventType.DBLCLICK, this.handleMouseEvent_);
    -};
    -
    -
    -/**
    - * Removes the event listeners from the tree.
    - * @private
    - */
    -goog.ui.tree.TreeControl.prototype.detachEvents_ = function() {
    -  this.keyHandler_.dispose();
    -  this.keyHandler_ = null;
    -  this.focusHandler_.dispose();
    -  this.focusHandler_ = null;
    -};
    -
    -
    -/**
    - * Handles mouse events.
    - * @param {!goog.events.BrowserEvent} e The browser event.
    - * @private
    - */
    -goog.ui.tree.TreeControl.prototype.handleMouseEvent_ = function(e) {
    -  goog.log.fine(this.logger_, 'Received event ' + e.type);
    -  var node = this.getNodeFromEvent_(e);
    -  if (node) {
    -    switch (e.type) {
    -      case goog.events.EventType.MOUSEDOWN:
    -        node.onMouseDown(e);
    -        break;
    -      case goog.events.EventType.CLICK:
    -        node.onClick_(e);
    -        break;
    -      case goog.events.EventType.DBLCLICK:
    -        node.onDoubleClick_(e);
    -        break;
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Handles key down on the tree.
    - * @param {!goog.events.BrowserEvent} e The browser event.
    - * @return {boolean} The handled value.
    - */
    -goog.ui.tree.TreeControl.prototype.handleKeyEvent = function(e) {
    -  var handled = false;
    -
    -  // Handle typeahead and navigation keystrokes.
    -  handled = this.typeAhead_.handleNavigation(e) ||
    -            (this.selectedItem_ && this.selectedItem_.onKeyDown(e)) ||
    -            this.typeAhead_.handleTypeAheadChar(e);
    -
    -  if (handled) {
    -    e.preventDefault();
    -  }
    -
    -  return handled;
    -};
    -
    -
    -/**
    - * Finds the containing node given an event.
    - * @param {!goog.events.BrowserEvent} e The browser event.
    - * @return {goog.ui.tree.BaseNode} The containing node or null if no node is
    - *     found.
    - * @private
    - */
    -goog.ui.tree.TreeControl.prototype.getNodeFromEvent_ = function(e) {
    -  // find the right node
    -  var node = null;
    -  var target = e.target;
    -  while (target != null) {
    -    var id = target.id;
    -    node = goog.ui.tree.BaseNode.allNodes[id];
    -    if (node) {
    -      return node;
    -    }
    -    if (target == this.getElement()) {
    -      break;
    -    }
    -    target = target.parentNode;
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * Creates a new tree node using the same config as the root.
    - * @param {string=} opt_html The HTML content of the node label.
    - * @return {!goog.ui.tree.TreeNode} The new item.
    - */
    -goog.ui.tree.TreeControl.prototype.createNode = function(opt_html) {
    -  return new goog.ui.tree.TreeNode(opt_html || goog.html.SafeHtml.EMPTY,
    -      this.getConfig(), this.getDomHelper());
    -};
    -
    -
    -/**
    - * Allows the caller to notify that the given node has been added or just had
    - * been updated in the tree.
    - * @param {goog.ui.tree.BaseNode} node New node being added or existing node
    - *    that just had been updated.
    - */
    -goog.ui.tree.TreeControl.prototype.setNode = function(node) {
    -  this.typeAhead_.setNodeInMap(node);
    -};
    -
    -
    -/**
    - * Allows the caller to notify that the given node is being removed from the
    - * tree.
    - * @param {goog.ui.tree.BaseNode} node Node being removed.
    - */
    -goog.ui.tree.TreeControl.prototype.removeNode = function(node) {
    -  this.typeAhead_.removeNodeFromMap(node);
    -};
    -
    -
    -/**
    - * Clear the typeahead buffer.
    - */
    -goog.ui.tree.TreeControl.prototype.clearTypeAhead = function() {
    -  this.typeAhead_.clear();
    -};
    -
    -
    -/**
    - * A default configuration for the tree.
    - */
    -goog.ui.tree.TreeControl.defaultConfig = goog.ui.tree.BaseNode.defaultConfig;
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tree/treecontrol_test.html b/src/database/third_party/closure-library/closure/goog/ui/tree/treecontrol_test.html
    deleted file mode 100644
    index fb7569eb791..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tree/treecontrol_test.html
    +++ /dev/null
    @@ -1,26 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.tree.TreeControl
    -  </title>
    -  <script type="text/javascript" src="../../base.js">
    -  </script>
    -  <script type="text/javascript">
    -    goog.require('goog.ui.tree.TreeControlTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="treeContainer" style="width:400px">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tree/treecontrol_test.js b/src/database/third_party/closure-library/closure/goog/ui/tree/treecontrol_test.js
    deleted file mode 100644
    index 325f76adb1a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tree/treecontrol_test.js
    +++ /dev/null
    @@ -1,106 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.tree.TreeControlTest');
    -goog.setTestOnly('goog.ui.tree.TreeControlTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.tree.TreeControl');
    -function makeATree() {
    -  var tree = new goog.ui.tree.TreeControl('root');
    -  var testData = ['A', [
    -    ['AA', [
    -      ['AAA', []],
    -      ['AAB', []]
    -    ]],
    -    ['AB', [
    -      ['ABA', []],
    -      ['ABB', []]
    -    ]]
    -  ]];
    -
    -  createTreeFromTestData(tree, testData, 3);
    -  tree.render(goog.dom.getElement('treeContainer'));
    -  return tree;
    -}
    -
    -function createTreeFromTestData(node, data, maxLevels) {
    -  node.setHtml(data[0]);
    -  if (maxLevels < 0) {
    -    return;
    -  }
    -
    -  var children = data[1];
    -  for (var i = 0; i < children.length; i++) {
    -    var child = children[i];
    -    var childNode = node.getTree().createNode('');
    -    node.add(childNode);
    -    createTreeFromTestData(childNode, child, maxLevels - 1);
    -  }
    -}
    -
    -
    -/**
    - * Test moving a node to a greater depth.
    - */
    -function testIndent() {
    -  var tree = makeATree();
    -  tree.expandAll();
    -
    -  var node = tree.getChildren()[0].getChildren()[0];
    -  assertEquals('AAA', node.getHtml());
    -  assertNotNull(node.getElement());
    -  assertEquals('19px', node.getRowElement().style.paddingLeft);
    -
    -  assertEquals(2, node.getDepth());
    -
    -  var newParent = node.getNextSibling();
    -  assertEquals('AAB', newParent.getHtml());
    -  assertEquals(2, newParent.getDepth());
    -
    -  newParent.add(node);
    -
    -  assertEquals(newParent, node.getParent());
    -  assertEquals(node, newParent.getChildren()[0]);
    -  assertEquals(3, node.getDepth());
    -  assertEquals('38px', node.getRowElement().style.paddingLeft);
    -}
    -
    -
    -/**
    - * Test moving a node to a lesser depth.
    - */
    -function testOutdent() {
    -  var tree = makeATree();
    -  tree.expandAll();
    -
    -  var node = tree.getChildren()[0].getChildren()[0];
    -  assertEquals('AAA', node.getHtml());
    -  assertNotNull(node.getElement());
    -  assertEquals('19px', node.getRowElement().style.paddingLeft);
    -
    -  assertEquals(2, node.getDepth());
    -
    -  var newParent = tree;
    -  assertEquals('A', newParent.getHtml());
    -  assertEquals(0, newParent.getDepth());
    -
    -  newParent.add(node);
    -
    -  assertEquals(newParent, node.getParent());
    -  assertEquals(node, newParent.getChildren()[2]);
    -  assertEquals(1, node.getDepth());
    -  assertEquals('0px', node.getRowElement().style.paddingLeft);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tree/treenode.js b/src/database/third_party/closure-library/closure/goog/ui/tree/treenode.js
    deleted file mode 100644
    index 4f7aa96c215..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tree/treenode.js
    +++ /dev/null
    @@ -1,100 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Definition of the goog.ui.tree.TreeNode class.
    - *
    - * @author arv@google.com (Erik Arvidsson)
    - * @author eae@google.com (Emil A Eklund)
    - *
    - * This is a based on the webfx tree control. See file comment in
    - * treecontrol.js.
    - */
    -
    -goog.provide('goog.ui.tree.TreeNode');
    -
    -goog.require('goog.ui.tree.BaseNode');
    -
    -
    -
    -/**
    - * A single node in the tree.
    - * @param {string|!goog.html.SafeHtml} html The html content of the node label.
    - * @param {Object=} opt_config The configuration for the tree. See
    - *    goog.ui.tree.TreeControl.defaultConfig. If not specified, a default config
    - *    will be used.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @constructor
    - * @extends {goog.ui.tree.BaseNode}
    - */
    -goog.ui.tree.TreeNode = function(html, opt_config, opt_domHelper) {
    -  goog.ui.tree.BaseNode.call(this, html, opt_config, opt_domHelper);
    -};
    -goog.inherits(goog.ui.tree.TreeNode, goog.ui.tree.BaseNode);
    -
    -
    -/**
    - * Returns the tree.
    - * @return {?goog.ui.tree.TreeControl} The tree.
    - * @override
    - */
    -goog.ui.tree.TreeNode.prototype.getTree = function() {
    -  if (this.tree) {
    -    return this.tree;
    -  }
    -  var parent = this.getParent();
    -  if (parent) {
    -    var tree = parent.getTree();
    -    if (tree) {
    -      this.setTreeInternal(tree);
    -      return tree;
    -    }
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * Returns the source for the icon.
    - * @return {string} Src for the icon.
    - * @override
    - */
    -goog.ui.tree.TreeNode.prototype.getCalculatedIconClass = function() {
    -  var expanded = this.getExpanded();
    -  var expandedIconClass = this.getExpandedIconClass();
    -  if (expanded && expandedIconClass) {
    -    return expandedIconClass;
    -  }
    -  var iconClass = this.getIconClass();
    -  if (!expanded && iconClass) {
    -    return iconClass;
    -  }
    -
    -  // fall back on default icons
    -  var config = this.getConfig();
    -  if (this.hasChildren()) {
    -    if (expanded && config.cssExpandedFolderIcon) {
    -      return config.cssTreeIcon + ' ' +
    -             config.cssExpandedFolderIcon;
    -    } else if (!expanded && config.cssCollapsedFolderIcon) {
    -      return config.cssTreeIcon + ' ' +
    -             config.cssCollapsedFolderIcon;
    -    }
    -  } else {
    -    if (config.cssFileIcon) {
    -      return config.cssTreeIcon + ' ' + config.cssFileIcon;
    -    }
    -  }
    -  return '';
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tree/typeahead.js b/src/database/third_party/closure-library/closure/goog/ui/tree/typeahead.js
    deleted file mode 100644
    index 777c453a805..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tree/typeahead.js
    +++ /dev/null
    @@ -1,332 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Provides the typeahead functionality for the tree class.
    - *
    - */
    -
    -goog.provide('goog.ui.tree.TypeAhead');
    -goog.provide('goog.ui.tree.TypeAhead.Offset');
    -
    -goog.require('goog.array');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.string');
    -goog.require('goog.structs.Trie');
    -
    -
    -
    -/**
    - * Constructs a TypeAhead object.
    - * @constructor
    - * @final
    - */
    -goog.ui.tree.TypeAhead = function() {
    -  this.nodeMap_ = new goog.structs.Trie();
    -};
    -
    -
    -/**
    - * Map of tree nodes to allow for quick access by characters in the label text.
    - * @type {goog.structs.Trie<Array<goog.ui.tree.BaseNode>>}
    - * @private
    - */
    -goog.ui.tree.TypeAhead.prototype.nodeMap_;
    -
    -
    -/**
    - * Buffer for storing typeahead characters.
    - * @type {string}
    - * @private
    - */
    -goog.ui.tree.TypeAhead.prototype.buffer_ = '';
    -
    -
    -/**
    - * Matching labels from the latest typeahead search.
    - * @type {?Array<string>}
    - * @private
    - */
    -goog.ui.tree.TypeAhead.prototype.matchingLabels_ = null;
    -
    -
    -/**
    - * Matching nodes from the latest typeahead search. Used when more than
    - * one node is present with the same label text.
    - * @type {?Array<goog.ui.tree.BaseNode>}
    - * @private
    - */
    -goog.ui.tree.TypeAhead.prototype.matchingNodes_ = null;
    -
    -
    -/**
    - * Specifies the current index of the label from the latest typeahead search.
    - * @type {number}
    - * @private
    - */
    -goog.ui.tree.TypeAhead.prototype.matchingLabelIndex_ = 0;
    -
    -
    -/**
    - * Specifies the index into matching nodes when more than one node is found
    - * with the same label.
    - * @type {number}
    - * @private
    - */
    -goog.ui.tree.TypeAhead.prototype.matchingNodeIndex_ = 0;
    -
    -
    -/**
    - * Enum for offset values that are used for ctrl-key navigation among the
    - * multiple matches of a given typeahead buffer.
    - *
    - * @enum {number}
    - */
    -goog.ui.tree.TypeAhead.Offset = {
    -  DOWN: 1,
    -  UP: -1
    -};
    -
    -
    -/**
    - * Handles navigation keys.
    - * @param {goog.events.BrowserEvent} e The browser event.
    - * @return {boolean} The handled value.
    - */
    -goog.ui.tree.TypeAhead.prototype.handleNavigation = function(e) {
    -  var handled = false;
    -
    -  switch (e.keyCode) {
    -    // Handle ctrl+down, ctrl+up to navigate within typeahead results.
    -    case goog.events.KeyCodes.DOWN:
    -    case goog.events.KeyCodes.UP:
    -      if (e.ctrlKey) {
    -        this.jumpTo_(e.keyCode == goog.events.KeyCodes.DOWN ?
    -                     goog.ui.tree.TypeAhead.Offset.DOWN :
    -                     goog.ui.tree.TypeAhead.Offset.UP);
    -        handled = true;
    -      }
    -      break;
    -
    -    // Remove the last typeahead char.
    -    case goog.events.KeyCodes.BACKSPACE:
    -      var length = this.buffer_.length - 1;
    -      handled = true;
    -      if (length > 0) {
    -        this.buffer_ = this.buffer_.substring(0, length);
    -        this.jumpToLabel_(this.buffer_);
    -      } else if (length == 0) {
    -        // Clear the last character in typeahead.
    -        this.buffer_ = '';
    -      } else {
    -        handled = false;
    -      }
    -      break;
    -
    -    // Clear typeahead buffer.
    -    case goog.events.KeyCodes.ESC:
    -      this.buffer_ = '';
    -      handled = true;
    -      break;
    -  }
    -
    -  return handled;
    -};
    -
    -
    -/**
    - * Handles the character presses.
    - * @param {goog.events.BrowserEvent} e The browser event.
    - *    Expected event type is goog.events.KeyHandler.EventType.KEY.
    - * @return {boolean} The handled value.
    - */
    -goog.ui.tree.TypeAhead.prototype.handleTypeAheadChar = function(e) {
    -  var handled = false;
    -
    -  if (!e.ctrlKey && !e.altKey) {
    -    // Since goog.structs.Trie.getKeys compares characters during
    -    // lookup, we should use charCode instead of keyCode where possible.
    -    // Convert to lowercase, typeahead is case insensitive.
    -    var ch = String.fromCharCode(e.charCode || e.keyCode).toLowerCase();
    -    if (goog.string.isUnicodeChar(ch) && (ch != ' ' || this.buffer_)) {
    -      this.buffer_ += ch;
    -      handled = this.jumpToLabel_(this.buffer_);
    -    }
    -  }
    -
    -  return handled;
    -};
    -
    -
    -/**
    - * Adds or updates the given node in the nodemap. The label text is used as a
    - * key and the node id is used as a value. In the case that the key already
    - * exists, such as when more than one node exists with the same label, then this
    - * function creates an array to hold the multiple nodes.
    - * @param {goog.ui.tree.BaseNode} node Node to be added or updated.
    - */
    -goog.ui.tree.TypeAhead.prototype.setNodeInMap = function(node) {
    -  var labelText = node.getText();
    -  if (labelText && !goog.string.isEmptyOrWhitespace(goog.string.makeSafe(labelText))) {
    -    // Typeahead is case insensitive, convert to lowercase.
    -    labelText = labelText.toLowerCase();
    -
    -    var previousValue = this.nodeMap_.get(labelText);
    -    if (previousValue) {
    -      // Found a previously created array, add the given node.
    -      previousValue.push(node);
    -    } else {
    -      // Create a new array and set the array as value.
    -      var nodeList = [node];
    -      this.nodeMap_.set(labelText, nodeList);
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Removes the given node from the nodemap.
    - * @param {goog.ui.tree.BaseNode} node Node to be removed.
    - */
    -goog.ui.tree.TypeAhead.prototype.removeNodeFromMap = function(node) {
    -  var labelText = node.getText();
    -  if (labelText && !goog.string.isEmptyOrWhitespace(goog.string.makeSafe(labelText))) {
    -    labelText = labelText.toLowerCase();
    -
    -    var nodeList = this.nodeMap_.get(labelText);
    -    if (nodeList) {
    -      // Remove the node from the array.
    -      goog.array.remove(nodeList, node);
    -      if (!!nodeList.length) {
    -        this.nodeMap_.remove(labelText);
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Select the first matching node for the given typeahead.
    - * @param {string} typeAhead Typeahead characters to match.
    - * @return {boolean} True iff a node is found.
    - * @private
    - */
    -goog.ui.tree.TypeAhead.prototype.jumpToLabel_ = function(typeAhead) {
    -  var handled = false;
    -  var labels = this.nodeMap_.getKeys(typeAhead);
    -
    -  // Make sure we have at least one matching label.
    -  if (labels && labels.length) {
    -    this.matchingNodeIndex_ = 0;
    -    this.matchingLabelIndex_ = 0;
    -
    -    var nodes = this.nodeMap_.get(labels[0]);
    -    if ((handled = this.selectMatchingNode_(nodes))) {
    -      this.matchingLabels_ = labels;
    -    }
    -  }
    -
    -  // TODO(user): beep when no node is found
    -  return handled;
    -};
    -
    -
    -/**
    - * Select the next or previous node based on the offset.
    - * @param {goog.ui.tree.TypeAhead.Offset} offset DOWN or UP.
    - * @return {boolean} Whether a node is found.
    - * @private
    - */
    -goog.ui.tree.TypeAhead.prototype.jumpTo_ = function(offset) {
    -  var handled = false;
    -  var labels = this.matchingLabels_;
    -
    -  if (labels) {
    -    var nodes = null;
    -    var nodeIndexOutOfRange = false;
    -
    -    // Navigate within the nodes array.
    -    if (this.matchingNodes_) {
    -      var newNodeIndex = this.matchingNodeIndex_ + offset;
    -      if (newNodeIndex >= 0 && newNodeIndex < this.matchingNodes_.length) {
    -        this.matchingNodeIndex_ = newNodeIndex;
    -        nodes = this.matchingNodes_;
    -      } else {
    -        nodeIndexOutOfRange = true;
    -      }
    -    }
    -
    -    // Navigate to the next or previous label.
    -    if (!nodes) {
    -      var newLabelIndex = this.matchingLabelIndex_ + offset;
    -      if (newLabelIndex >= 0 && newLabelIndex < labels.length) {
    -        this.matchingLabelIndex_ = newLabelIndex;
    -      }
    -
    -      if (labels.length > this.matchingLabelIndex_) {
    -        nodes = this.nodeMap_.get(labels[this.matchingLabelIndex_]);
    -      }
    -
    -      // Handle the case where we are moving beyond the available nodes,
    -      // while going UP select the last item of multiple nodes with same label
    -      // and while going DOWN select the first item of next set of nodes
    -      if (nodes && nodes.length && nodeIndexOutOfRange) {
    -        this.matchingNodeIndex_ = (offset == goog.ui.tree.TypeAhead.Offset.UP) ?
    -                                  nodes.length - 1 : 0;
    -      }
    -    }
    -
    -    if ((handled = this.selectMatchingNode_(nodes))) {
    -      this.matchingLabels_ = labels;
    -    }
    -  }
    -
    -  // TODO(user): beep when no node is found
    -  return handled;
    -};
    -
    -
    -/**
    - * Given a nodes array reveals and selects the node while using node index.
    - * @param {Array<goog.ui.tree.BaseNode>|undefined} nodes Nodes array to select
    - *     the node from.
    - * @return {boolean} Whether a matching node was found.
    - * @private
    - */
    -goog.ui.tree.TypeAhead.prototype.selectMatchingNode_ = function(nodes) {
    -  var node;
    -
    -  if (nodes) {
    -    // Find the matching node.
    -    if (this.matchingNodeIndex_ < nodes.length) {
    -      node = nodes[this.matchingNodeIndex_];
    -      this.matchingNodes_ = nodes;
    -    }
    -
    -    if (node) {
    -      node.reveal();
    -      node.select();
    -    }
    -  }
    -
    -  return !!node;
    -};
    -
    -
    -/**
    - * Clears the typeahead buffer.
    - */
    -goog.ui.tree.TypeAhead.prototype.clear = function() {
    -  this.buffer_ = '';
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tree/typeahead_test.html b/src/database/third_party/closure-library/closure/goog/ui/tree/typeahead_test.html
    deleted file mode 100644
    index 9194cd11fa7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tree/typeahead_test.html
    +++ /dev/null
    @@ -1,26 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.tree.TypeAhead
    -  </title>
    -  <script src="../../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.ui.tree.TypeAheadTest');
    -  </script>
    - </head>
    - <body>
    -  <div id="treeContainer" style="width:400px">
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tree/typeahead_test.js b/src/database/third_party/closure-library/closure/goog/ui/tree/typeahead_test.js
    deleted file mode 100644
    index b70e40ae54e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tree/typeahead_test.js
    +++ /dev/null
    @@ -1,127 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.tree.TypeAheadTest');
    -goog.setTestOnly('goog.ui.tree.TypeAheadTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.tree.TreeControl');
    -goog.require('goog.ui.tree.TypeAhead');
    -function makeATree() {
    -  var tree = new goog.ui.tree.TreeControl('root');
    -  var testData = ['level1',
    -    [['level2', [['eve', []], ['eve2', []]], []],
    -     ['level22', [['eve', []], ['eve3', []]], []]],
    -    []];
    -
    -  createTreeFromTestData(tree, testData, 3);
    -
    -  tree.createDom();
    -  goog.dom.getElement('treeContainer').appendChild(tree.getElement());
    -  tree.enterDocument();
    -
    -  return tree;
    -}
    -
    -function createTreeFromTestData(node, data, maxLevels) {
    -  node.setHtml(data[0]);
    -  if (maxLevels < 0) {
    -    return;
    -  }
    -
    -  var children = data[1];
    -  for (var i = 0; i < children.length; i++) {
    -    var child = children[i];
    -    var childNode = node.getTree().createNode('');
    -    node.add(childNode);
    -    createTreeFromTestData(childNode, child, maxLevels - 1);
    -  }
    -}
    -
    -
    -/**
    - * Test jumpToLabel_ functionality.
    - */
    -function testJumpToLabel() {
    -  var tree = makeATree();
    -  var typeAhead = tree.typeAhead_;
    -
    -  // Test the case when only one matching entry exists.
    -  var handled = typeAhead.jumpToLabel_('level1');
    -  var selectedItem = tree.getSelectedItem();
    -  assertTrue(handled && selectedItem.getHtml() == 'level1');
    -
    -  // Test the case when more than one matching entry exists.
    -  handled = typeAhead.jumpToLabel_('eve');
    -  selectedItem = tree.getSelectedItem();
    -  assertTrue(handled && selectedItem.getHtml() == 'eve');
    -
    -  // Test the case when the matching entry is at a deeper level.
    -  handled = typeAhead.jumpToLabel_('eve3');
    -  selectedItem = tree.getSelectedItem();
    -  assertTrue(handled && selectedItem.getHtml() == 'eve3');
    -}
    -
    -
    -/**
    - * Test jumpTo_ functionality.
    - */
    -function testJumpTo() {
    -  var tree = makeATree();
    -  var typeAhead = tree.typeAhead_;
    -
    -  // Jump to the first matching 'eve', followed by Ctrl+DOWN to jump to
    -  // second matching 'eve'
    -  var handled = typeAhead.jumpToLabel_('eve') &&
    -                typeAhead.jumpTo_(goog.ui.tree.TypeAhead.Offset.DOWN);
    -  var selectedItem = tree.getSelectedItem();
    -  assertTrue(handled && selectedItem.getHtml() == 'eve');
    -
    -  // Simulate a DOWN key on the tree, now the selection should be on 'eve3'
    -  var e = new Object();
    -  e.keyCode = goog.events.KeyCodes.DOWN;
    -  e.preventDefault = function() {};
    -  handled = tree.handleKeyEvent(e);
    -  selectedItem = tree.getSelectedItem();
    -  assertTrue(handled && selectedItem.getHtml() == 'eve3');
    -}
    -
    -
    -/**
    - * Test handleTypeAheadChar functionality.
    - */
    -function testHandleTypeAheadChar() {
    -  var tree = makeATree();
    -  var typeAhead = tree.typeAhead_;
    -  var e = new Object();
    -
    -  // Period character('.'): keyCode = 190, charCode = 46
    -  // String.fromCharCode(190) = '3/4'  <-- incorrect
    -  // String.fromCharCode(46) = '.'  <-- correct
    -  e.keyCode = goog.events.KeyCodes.PERIOD;
    -  e.charCode = 46;
    -  e.preventDefault = function() {};
    -  typeAhead.handleTypeAheadChar(e);
    -  assertEquals('.', typeAhead.buffer_);
    -
    -  // charCode not supplied.
    -  // This is expected to work only for alpha-num characters.
    -  e.keyCode = goog.events.KeyCodes.A;
    -  e.charCode = undefined;
    -  typeAhead.buffer_ = '';
    -  typeAhead.handleTypeAheadChar(e);
    -  assertEquals('a', typeAhead.buffer_);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tristatemenuitem.js b/src/database/third_party/closure-library/closure/goog/ui/tristatemenuitem.js
    deleted file mode 100644
    index b4f59a6a589..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tristatemenuitem.js
    +++ /dev/null
    @@ -1,196 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview A menu item class that supports three state checkbox semantics.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - */
    -
    -goog.provide('goog.ui.TriStateMenuItem');
    -goog.provide('goog.ui.TriStateMenuItem.State');
    -
    -goog.require('goog.dom.classlist');
    -goog.require('goog.ui.Component');
    -goog.require('goog.ui.MenuItem');
    -goog.require('goog.ui.TriStateMenuItemRenderer');
    -goog.require('goog.ui.registry');
    -
    -
    -
    -/**
    - * Class representing a three state checkbox menu item.
    - *
    - * @param {goog.ui.ControlContent} content Text caption or DOM structure
    - *     to display as the content of the item (use to add icons or styling to
    - *     menus).
    - * @param {Object=} opt_model Data/model associated with the menu item.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper used for
    - *     document interactions.
    - * @param {goog.ui.MenuItemRenderer=} opt_renderer Optional renderer.
    - * @param {boolean=} opt_alwaysAllowPartial  If true, always allow partial
    - *     state.
    - * @constructor
    - * @extends {goog.ui.MenuItem}
    - * TODO(attila): Figure out how to better integrate this into the
    - * goog.ui.Control state management framework.
    - * @final
    - */
    -goog.ui.TriStateMenuItem = function(content, opt_model, opt_domHelper,
    -    opt_renderer, opt_alwaysAllowPartial) {
    -  goog.ui.MenuItem.call(this, content, opt_model, opt_domHelper,
    -      opt_renderer || new goog.ui.TriStateMenuItemRenderer());
    -  this.setCheckable(true);
    -  this.alwaysAllowPartial_ = opt_alwaysAllowPartial || false;
    -};
    -goog.inherits(goog.ui.TriStateMenuItem, goog.ui.MenuItem);
    -
    -
    -/**
    - * Checked states for component.
    - * @enum {number}
    - */
    -goog.ui.TriStateMenuItem.State = {
    -  /**
    -   * Component is not checked.
    -   */
    -  NOT_CHECKED: 0,
    -
    -  /**
    -   * Component is partially checked.
    -   */
    -  PARTIALLY_CHECKED: 1,
    -
    -  /**
    -   * Component is fully checked.
    -   */
    -  FULLY_CHECKED: 2
    -};
    -
    -
    -/**
    - * Menu item's checked state.
    - * @type {goog.ui.TriStateMenuItem.State}
    - * @private
    - */
    -goog.ui.TriStateMenuItem.prototype.checkState_ =
    -    goog.ui.TriStateMenuItem.State.NOT_CHECKED;
    -
    -
    -/**
    - * Whether the partial state can be toggled.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.TriStateMenuItem.prototype.allowPartial_ = false;
    -
    -
    -/**
    - * Used to override allowPartial_ to force the third state to always be
    - * permitted.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.TriStateMenuItem.prototype.alwaysAllowPartial_ = false;
    -
    -
    -/**
    - * @return {goog.ui.TriStateMenuItem.State} The menu item's check state.
    - */
    -goog.ui.TriStateMenuItem.prototype.getCheckedState = function() {
    -  return this.checkState_;
    -};
    -
    -
    -/**
    - * Sets the checked state.
    - * @param {goog.ui.TriStateMenuItem.State} state The checked state.
    - */
    -goog.ui.TriStateMenuItem.prototype.setCheckedState = function(state) {
    -  this.setCheckedState_(state);
    -  this.allowPartial_ =
    -      state == goog.ui.TriStateMenuItem.State.PARTIALLY_CHECKED;
    -};
    -
    -
    -/**
    - * Sets the checked state and updates the CSS styling. Dispatches a
    - * {@code CHECK} or {@code UNCHECK} event prior to changing the component's
    - * state, which may be caught and canceled to prevent the component from
    - * changing state.
    - * @param {goog.ui.TriStateMenuItem.State} state The checked state.
    - * @private
    - */
    -goog.ui.TriStateMenuItem.prototype.setCheckedState_ = function(state) {
    -  if (this.dispatchEvent(state != goog.ui.TriStateMenuItem.State.NOT_CHECKED ?
    -                             goog.ui.Component.EventType.CHECK :
    -                             goog.ui.Component.EventType.UNCHECK)) {
    -    this.setState(goog.ui.Component.State.CHECKED,
    -        state != goog.ui.TriStateMenuItem.State.NOT_CHECKED);
    -    this.checkState_ = state;
    -    this.updatedCheckedStateClassNames_();
    -  }
    -};
    -
    -
    -/** @override */
    -goog.ui.TriStateMenuItem.prototype.performActionInternal = function(e) {
    -  switch (this.getCheckedState()) {
    -    case goog.ui.TriStateMenuItem.State.NOT_CHECKED:
    -      this.setCheckedState_(this.alwaysAllowPartial_ || this.allowPartial_ ?
    -          goog.ui.TriStateMenuItem.State.PARTIALLY_CHECKED :
    -          goog.ui.TriStateMenuItem.State.FULLY_CHECKED);
    -      break;
    -    case goog.ui.TriStateMenuItem.State.PARTIALLY_CHECKED:
    -      this.setCheckedState_(goog.ui.TriStateMenuItem.State.FULLY_CHECKED);
    -      break;
    -    case goog.ui.TriStateMenuItem.State.FULLY_CHECKED:
    -      this.setCheckedState_(goog.ui.TriStateMenuItem.State.NOT_CHECKED);
    -      break;
    -  }
    -
    -  var checkboxClass = goog.getCssName(
    -      this.getRenderer().getCssClass(), 'checkbox');
    -  var clickOnCheckbox = e.target && goog.dom.classlist.contains(
    -      /** @type {!Element} */ (e.target), checkboxClass);
    -
    -  return this.dispatchEvent(clickOnCheckbox || this.allowPartial_ ?
    -      goog.ui.Component.EventType.CHANGE :
    -      goog.ui.Component.EventType.ACTION);
    -};
    -
    -
    -/**
    - * Updates the extra class names applied to the menu item element.
    - * @private
    - */
    -goog.ui.TriStateMenuItem.prototype.updatedCheckedStateClassNames_ = function() {
    -  var renderer = this.getRenderer();
    -  renderer.enableExtraClassName(
    -      this, goog.getCssName(renderer.getCssClass(), 'partially-checked'),
    -      this.getCheckedState() ==
    -      goog.ui.TriStateMenuItem.State.PARTIALLY_CHECKED);
    -  renderer.enableExtraClassName(
    -      this, goog.getCssName(renderer.getCssClass(), 'fully-checked'),
    -      this.getCheckedState() == goog.ui.TriStateMenuItem.State.FULLY_CHECKED);
    -};
    -
    -
    -// Register a decorator factory function for goog.ui.TriStateMenuItemRenderer.
    -goog.ui.registry.setDecoratorByClassName(
    -    goog.ui.TriStateMenuItemRenderer.CSS_CLASS,
    -    function() {
    -      // TriStateMenuItem defaults to using TriStateMenuItemRenderer.
    -      return new goog.ui.TriStateMenuItem(null);
    -    });
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/tristatemenuitemrenderer.js b/src/database/third_party/closure-library/closure/goog/ui/tristatemenuitemrenderer.js
    deleted file mode 100644
    index 961511f4fbf..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/tristatemenuitemrenderer.js
    +++ /dev/null
    @@ -1,92 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Renderer for {@link goog.ui.TriStateMenuItem}s.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - */
    -
    -goog.provide('goog.ui.TriStateMenuItemRenderer');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.ui.MenuItemRenderer');
    -
    -
    -
    -/**
    - * Default renderer for {@link goog.ui.TriStateMenuItemRenderer}s. Each item has
    - * the following structure:
    - *    <div class="goog-tristatemenuitem">
    - *        <div class="goog-tristatemenuitem-checkbox"></div>
    - *        <div>...(content)...</div>
    - *    </div>
    - * @constructor
    - * @extends {goog.ui.MenuItemRenderer}
    - * @final
    - */
    -goog.ui.TriStateMenuItemRenderer = function() {
    -  goog.ui.MenuItemRenderer.call(this);
    -};
    -goog.inherits(goog.ui.TriStateMenuItemRenderer, goog.ui.MenuItemRenderer);
    -goog.addSingletonGetter(goog.ui.TriStateMenuItemRenderer);
    -
    -
    -/**
    - * CSS class name the renderer applies to menu item elements.
    - * @type {string}
    - */
    -goog.ui.TriStateMenuItemRenderer.CSS_CLASS =
    -    goog.getCssName('goog-tristatemenuitem');
    -
    -
    -/**
    - * Overrides {@link goog.ui.ControlRenderer#decorate} by initializing the
    - * menu item to checkable based on whether the element to be decorated has
    - * extra styling indicating that it should be.
    - * @param {goog.ui.Control} item goog.ui.TriStateMenuItem to decorate
    - *     the element.
    - * @param {Element} element Element to decorate.
    - * @return {!Element} Decorated element.
    - * @override
    - */
    -goog.ui.TriStateMenuItemRenderer.prototype.decorate = function(item, element) {
    -  element = goog.ui.TriStateMenuItemRenderer.superClass_.decorate.call(this,
    -      item, element);
    -  this.setCheckable(item, element, true);
    -
    -  goog.asserts.assert(element);
    -
    -  if (goog.dom.classlist.contains(element,
    -      goog.getCssName(this.getCssClass(), 'fully-checked'))) {
    -    item.setCheckedState(/** @suppress {missingRequire} */
    -        goog.ui.TriStateMenuItem.State.FULLY_CHECKED);
    -  } else if (goog.dom.classlist.contains(element,
    -      goog.getCssName(this.getCssClass(), 'partially-checked'))) {
    -    item.setCheckedState(/** @suppress {missingRequire} */
    -        goog.ui.TriStateMenuItem.State.PARTIALLY_CHECKED);
    -  } else {
    -    item.setCheckedState(/** @suppress {missingRequire} */
    -        goog.ui.TriStateMenuItem.State.NOT_CHECKED);
    -  }
    -
    -  return element;
    -};
    -
    -
    -/** @override */
    -goog.ui.TriStateMenuItemRenderer.prototype.getCssClass = function() {
    -  return goog.ui.TriStateMenuItemRenderer.CSS_CLASS;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/twothumbslider.js b/src/database/third_party/closure-library/closure/goog/ui/twothumbslider.js
    deleted file mode 100644
    index 79485112f61..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/twothumbslider.js
    +++ /dev/null
    @@ -1,158 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Twothumbslider is a slider that allows to select a subrange
    - * within a range by dragging two thumbs. The selected sub-range is exposed
    - * through getValue() and getExtent().
    - *
    - * To decorate, the twothumbslider should be bound to an element with the class
    - * name 'goog-twothumbslider-[vertical / horizontal]' containing children with
    - * the classname 'goog-twothumbslider-value-thumb' and
    - * 'goog-twothumbslider-extent-thumb', respectively.
    - *
    - * Decorate Example:
    - * <div id="twothumbslider" class="goog-twothumbslider-horizontal">
    - *   <div class="goog-twothumbslider-value-thumb">
    - *   <div class="goog-twothumbslider-extent-thumb">
    - * </div>
    - * <script>
    - *
    - * var slider = new goog.ui.TwoThumbSlider;
    - * slider.decorate(document.getElementById('twothumbslider'));
    - *
    - * TODO(user): add a11y once we know what this element is
    - *
    - * @see ../demos/twothumbslider.html
    - */
    -
    -goog.provide('goog.ui.TwoThumbSlider');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.dom');
    -goog.require('goog.ui.SliderBase');
    -
    -
    -
    -/**
    - * This creates a TwoThumbSlider object.
    - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
    - * @constructor
    - * @extends {goog.ui.SliderBase}
    - */
    -goog.ui.TwoThumbSlider = function(opt_domHelper) {
    -  goog.ui.SliderBase.call(this, opt_domHelper);
    -  this.rangeModel.setValue(this.getMinimum());
    -  this.rangeModel.setExtent(this.getMaximum() - this.getMinimum());
    -};
    -goog.inherits(goog.ui.TwoThumbSlider, goog.ui.SliderBase);
    -goog.tagUnsealableClass(goog.ui.TwoThumbSlider);
    -
    -
    -/**
    - * The prefix we use for the CSS class names for the slider and its elements.
    - * @type {string}
    - */
    -goog.ui.TwoThumbSlider.CSS_CLASS_PREFIX =
    -    goog.getCssName('goog-twothumbslider');
    -
    -
    -/**
    - * CSS class name for the value thumb element.
    - * @type {string}
    - */
    -goog.ui.TwoThumbSlider.VALUE_THUMB_CSS_CLASS =
    -    goog.getCssName(goog.ui.TwoThumbSlider.CSS_CLASS_PREFIX, 'value-thumb');
    -
    -
    -/**
    - * CSS class name for the extent thumb element.
    - * @type {string}
    - */
    -goog.ui.TwoThumbSlider.EXTENT_THUMB_CSS_CLASS =
    -    goog.getCssName(goog.ui.TwoThumbSlider.CSS_CLASS_PREFIX, 'extent-thumb');
    -
    -
    -/**
    - * CSS class name for the range highlight element.
    - * @type {string}
    - */
    -goog.ui.TwoThumbSlider.RANGE_HIGHLIGHT_CSS_CLASS =
    -    goog.getCssName(goog.ui.TwoThumbSlider.CSS_CLASS_PREFIX, 'rangehighlight');
    -
    -
    -/**
    - * @param {goog.ui.SliderBase.Orientation} orient orientation of the slider.
    - * @return {string} The CSS class applied to the twothumbslider element.
    - * @protected
    - * @override
    - */
    -goog.ui.TwoThumbSlider.prototype.getCssClass = function(orient) {
    -  return orient == goog.ui.SliderBase.Orientation.VERTICAL ?
    -      goog.getCssName(goog.ui.TwoThumbSlider.CSS_CLASS_PREFIX, 'vertical') :
    -      goog.getCssName(goog.ui.TwoThumbSlider.CSS_CLASS_PREFIX, 'horizontal');
    -};
    -
    -
    -/**
    - * This creates a thumb element with the specified CSS class name.
    - * @param {string} cs  CSS class name of the thumb to be created.
    - * @return {!HTMLDivElement} The created thumb element.
    - * @private
    - */
    -goog.ui.TwoThumbSlider.prototype.createThumb_ = function(cs) {
    -  var thumb = this.getDomHelper().createDom('div', cs);
    -  goog.a11y.aria.setRole(thumb, goog.a11y.aria.Role.BUTTON);
    -  return /** @type {!HTMLDivElement} */ (thumb);
    -};
    -
    -
    -/**
    - * Creates the thumb members for a twothumbslider. If the
    - * element contains a child with a class name 'goog-twothumbslider-value-thumb'
    - * (or 'goog-twothumbslider-extent-thumb', respectively), then that will be used
    - * as the valueThumb (or as the extentThumb, respectively). If the element
    - * contains a child with a class name 'goog-twothumbslider-rangehighlight',
    - * then that will be used as the range highlight.
    - * @override
    - */
    -goog.ui.TwoThumbSlider.prototype.createThumbs = function() {
    -  // find range highlight and thumbs
    -  var valueThumb = goog.dom.getElementsByTagNameAndClass(
    -      null, goog.ui.TwoThumbSlider.VALUE_THUMB_CSS_CLASS, this.getElement())[0];
    -  var extentThumb = goog.dom.getElementsByTagNameAndClass(null,
    -      goog.ui.TwoThumbSlider.EXTENT_THUMB_CSS_CLASS, this.getElement())[0];
    -  var rangeHighlight = goog.dom.getElementsByTagNameAndClass(null,
    -      goog.ui.TwoThumbSlider.RANGE_HIGHLIGHT_CSS_CLASS, this.getElement())[0];
    -  if (!valueThumb) {
    -    valueThumb =
    -        this.createThumb_(goog.ui.TwoThumbSlider.VALUE_THUMB_CSS_CLASS);
    -    this.getElement().appendChild(valueThumb);
    -  }
    -  if (!extentThumb) {
    -    extentThumb =
    -        this.createThumb_(goog.ui.TwoThumbSlider.EXTENT_THUMB_CSS_CLASS);
    -    this.getElement().appendChild(extentThumb);
    -  }
    -  if (!rangeHighlight) {
    -    rangeHighlight = this.getDomHelper().createDom('div',
    -        goog.ui.TwoThumbSlider.RANGE_HIGHLIGHT_CSS_CLASS);
    -    // Insert highlight before value thumb so that it renders under the thumbs.
    -    this.getDomHelper().insertSiblingBefore(rangeHighlight, valueThumb);
    -  }
    -  this.valueThumb = valueThumb;
    -  this.extentThumb = extentThumb;
    -  this.rangeHighlight = rangeHighlight;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/twothumbslider_test.html b/src/database/third_party/closure-library/closure/goog/ui/twothumbslider_test.html
    deleted file mode 100644
    index 00aa71b21bf..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/twothumbslider_test.html
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -  Author: chrishenry@google.com (Chris Henry)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.TwoThumbSlider
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.TwoThumbSliderTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/twothumbslider_test.js b/src/database/third_party/closure-library/closure/goog/ui/twothumbslider_test.js
    deleted file mode 100644
    index 8cd168f856a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/twothumbslider_test.js
    +++ /dev/null
    @@ -1,34 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.TwoThumbSliderTest');
    -goog.setTestOnly('goog.ui.TwoThumbSliderTest');
    -
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.SliderBase');
    -goog.require('goog.ui.TwoThumbSlider');
    -
    -var slider;
    -
    -function tearDown() {
    -  goog.dispose(slider);
    -}
    -
    -function testGetCssClass() {
    -  slider = new goog.ui.TwoThumbSlider();
    -  assertEquals('goog-twothumbslider-horizontal',
    -      slider.getCssClass(goog.ui.SliderBase.Orientation.HORIZONTAL));
    -  assertEquals('goog-twothumbslider-vertical',
    -      slider.getCssClass(goog.ui.SliderBase.Orientation.VERTICAL));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/zippy.js b/src/database/third_party/closure-library/closure/goog/ui/zippy.js
    deleted file mode 100644
    index f48b8db115f..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/zippy.js
    +++ /dev/null
    @@ -1,461 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Zippy widget implementation.
    - *
    - * @author eae@google.com (Emil A Eklund)
    - * @see ../demos/zippy.html
    - */
    -
    -goog.provide('goog.ui.Zippy');
    -goog.provide('goog.ui.Zippy.Events');
    -goog.provide('goog.ui.ZippyEvent');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.a11y.aria.Role');
    -goog.require('goog.a11y.aria.State');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events.Event');
    -goog.require('goog.events.EventHandler');
    -goog.require('goog.events.EventTarget');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.KeyCodes');
    -goog.require('goog.style');
    -
    -
    -
    -/**
    - * Zippy widget. Expandable/collapsible container, clicking the header toggles
    - * the visibility of the content.
    - *
    - * @extends {goog.events.EventTarget}
    - * @param {Element|string|null} header Header element, either element
    - *     reference, string id or null if no header exists.
    - * @param {Element|string|function():Element=} opt_content Content element
    - *     (if any), either element reference or string id.  If skipped, the caller
    - *     should handle the TOGGLE event in its own way. If a function is passed,
    - *     then if will be called to create the content element the first time the
    - *     zippy is expanded.
    - * @param {boolean=} opt_expanded Initial expanded/visibility state. If
    - *     undefined, attempts to infer the state from the DOM. Setting visibility
    - *     using one of the standard Soy templates guarantees correct inference.
    - * @param {Element|string=} opt_expandedHeader Element to use as the header when
    - *     the zippy is expanded.
    - * @param {goog.dom.DomHelper=} opt_domHelper An optional DOM helper.
    - * @constructor
    - */
    -goog.ui.Zippy = function(header, opt_content, opt_expanded,
    -    opt_expandedHeader, opt_domHelper) {
    -  goog.ui.Zippy.base(this, 'constructor');
    -
    -  /**
    -   * DomHelper used to interact with the document, allowing components to be
    -   * created in a different window.
    -   * @type {!goog.dom.DomHelper}
    -   * @private
    -   */
    -  this.dom_ = opt_domHelper || goog.dom.getDomHelper();
    -
    -  /**
    -   * Header element or null if no header exists.
    -   * @type {Element}
    -   * @private
    -   */
    -  this.elHeader_ = this.dom_.getElement(header) || null;
    -
    -  /**
    -   * When present, the header to use when the zippy is expanded.
    -   * @type {Element}
    -   * @private
    -   */
    -  this.elExpandedHeader_ = this.dom_.getElement(opt_expandedHeader || null);
    -
    -  /**
    -   * Function that will create the content element, or false if there is no such
    -   * function.
    -   * @type {?function():Element}
    -   * @private
    -   */
    -  this.lazyCreateFunc_ = goog.isFunction(opt_content) ? opt_content : null;
    -
    -  /**
    -   * Content element.
    -   * @type {Element}
    -   * @private
    -   */
    -  this.elContent_ = this.lazyCreateFunc_ || !opt_content ? null :
    -      this.dom_.getElement(/** @type {!Element} */ (opt_content));
    -
    -  /**
    -   * Expanded state.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.expanded_ = opt_expanded == true;
    -  if (!goog.isDef(opt_expanded) && !this.lazyCreateFunc_) {
    -    // For the dual caption case, we can get expanded_ from the visibility of
    -    // the expandedHeader. For the single-caption case, we use the
    -    // presence/absence of the relevant class. Using one of the standard Soy
    -    // templates guarantees that this will work.
    -    if (this.elExpandedHeader_) {
    -      this.expanded_ = goog.style.isElementShown(this.elExpandedHeader_);
    -    } else if (this.elHeader_) {
    -      this.expanded_ = goog.dom.classlist.contains(
    -          this.elHeader_, goog.getCssName('goog-zippy-expanded'));
    -    }
    -  }
    -
    -
    -  /**
    -   * A keyboard events handler. If there are two headers it is shared for both.
    -   * @type {goog.events.EventHandler<!goog.ui.Zippy>}
    -   * @private
    -   */
    -  this.keyboardEventHandler_ = new goog.events.EventHandler(this);
    -
    -  /**
    -   * A mouse events handler. If there are two headers it is shared for both.
    -   * @type {goog.events.EventHandler<!goog.ui.Zippy>}
    -   * @private
    -   */
    -  this.mouseEventHandler_ = new goog.events.EventHandler(this);
    -
    -  var self = this;
    -  function addHeaderEvents(el) {
    -    if (el) {
    -      el.tabIndex = 0;
    -      goog.a11y.aria.setRole(el, self.getAriaRole());
    -      goog.dom.classlist.add(el, goog.getCssName('goog-zippy-header'));
    -      self.enableMouseEventsHandling_(el);
    -      self.enableKeyboardEventsHandling_(el);
    -    }
    -  }
    -  addHeaderEvents(this.elHeader_);
    -  addHeaderEvents(this.elExpandedHeader_);
    -
    -  // initialize based on expanded state
    -  this.setExpanded(this.expanded_);
    -};
    -goog.inherits(goog.ui.Zippy, goog.events.EventTarget);
    -goog.tagUnsealableClass(goog.ui.Zippy);
    -
    -
    -/**
    - * Constants for event names
    - *
    - * @const
    - */
    -goog.ui.Zippy.Events = {
    -  // Zippy will dispatch an ACTION event for user interaction. Mimics
    -  // {@code goog.ui.Controls#performActionInternal} by first changing
    -  // the toggle state and then dispatching an ACTION event.
    -  ACTION: 'action',
    -  // Zippy state is toggled from collapsed to expanded or vice versa.
    -  TOGGLE: 'toggle'
    -};
    -
    -
    -/**
    - * Whether to listen for and handle mouse events; defaults to true.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.Zippy.prototype.handleMouseEvents_ = true;
    -
    -
    -/**
    - * Whether to listen for and handle key events; defaults to true.
    - * @type {boolean}
    - * @private
    - */
    -goog.ui.Zippy.prototype.handleKeyEvents_ = true;
    -
    -
    -/** @override */
    -goog.ui.Zippy.prototype.disposeInternal = function() {
    -  goog.ui.Zippy.base(this, 'disposeInternal');
    -  goog.dispose(this.keyboardEventHandler_);
    -  goog.dispose(this.mouseEventHandler_);
    -};
    -
    -
    -/**
    - * @return {goog.a11y.aria.Role} The ARIA role to be applied to Zippy element.
    - */
    -goog.ui.Zippy.prototype.getAriaRole = function() {
    -  return goog.a11y.aria.Role.TAB;
    -};
    -
    -
    -/**
    - * @return {Element} The content element.
    - */
    -goog.ui.Zippy.prototype.getContentElement = function() {
    -  return this.elContent_;
    -};
    -
    -
    -/**
    - * @return {Element} The visible header element.
    - */
    -goog.ui.Zippy.prototype.getVisibleHeaderElement = function() {
    -  var expandedHeader = this.elExpandedHeader_;
    -  return expandedHeader && goog.style.isElementShown(expandedHeader) ?
    -      expandedHeader : this.elHeader_;
    -};
    -
    -
    -/**
    - * Expands content pane.
    - */
    -goog.ui.Zippy.prototype.expand = function() {
    -  this.setExpanded(true);
    -};
    -
    -
    -/**
    - * Collapses content pane.
    - */
    -goog.ui.Zippy.prototype.collapse = function() {
    -  this.setExpanded(false);
    -};
    -
    -
    -/**
    - * Toggles expanded state.
    - */
    -goog.ui.Zippy.prototype.toggle = function() {
    -  this.setExpanded(!this.expanded_);
    -};
    -
    -
    -/**
    - * Sets expanded state.
    - *
    - * @param {boolean} expanded Expanded/visibility state.
    - */
    -goog.ui.Zippy.prototype.setExpanded = function(expanded) {
    -  if (this.elContent_) {
    -    // Hide the element, if one is provided.
    -    goog.style.setElementShown(this.elContent_, expanded);
    -  } else if (expanded && this.lazyCreateFunc_) {
    -    // Assume that when the element is not hidden upon creation.
    -    this.elContent_ = this.lazyCreateFunc_();
    -  }
    -  if (this.elContent_) {
    -    goog.dom.classlist.add(this.elContent_,
    -        goog.getCssName('goog-zippy-content'));
    -  }
    -
    -  if (this.elExpandedHeader_) {
    -    // Hide the show header and show the hide one.
    -    goog.style.setElementShown(this.elHeader_, !expanded);
    -    goog.style.setElementShown(this.elExpandedHeader_, expanded);
    -  } else {
    -    // Update header image, if any.
    -    this.updateHeaderClassName(expanded);
    -  }
    -
    -  this.setExpandedInternal(expanded);
    -
    -  // Fire toggle event
    -  this.dispatchEvent(new goog.ui.ZippyEvent(goog.ui.Zippy.Events.TOGGLE,
    -                                            this, this.expanded_));
    -};
    -
    -
    -/**
    - * Sets expanded internal state.
    - *
    - * @param {boolean} expanded Expanded/visibility state.
    - * @protected
    - */
    -goog.ui.Zippy.prototype.setExpandedInternal = function(expanded) {
    -  this.expanded_ = expanded;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the zippy is expanded.
    - */
    -goog.ui.Zippy.prototype.isExpanded = function() {
    -  return this.expanded_;
    -};
    -
    -
    -/**
    - * Updates the header element's className and ARIA (accessibility) EXPANDED
    - * state.
    - *
    - * @param {boolean} expanded Expanded/visibility state.
    - * @protected
    - */
    -goog.ui.Zippy.prototype.updateHeaderClassName = function(expanded) {
    -  if (this.elHeader_) {
    -    goog.dom.classlist.enable(this.elHeader_,
    -        goog.getCssName('goog-zippy-expanded'), expanded);
    -    goog.dom.classlist.enable(this.elHeader_,
    -        goog.getCssName('goog-zippy-collapsed'), !expanded);
    -    goog.a11y.aria.setState(this.elHeader_,
    -        goog.a11y.aria.State.EXPANDED,
    -        expanded);
    -  }
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the Zippy handles its own key events.
    - */
    -goog.ui.Zippy.prototype.isHandleKeyEvents = function() {
    -  return this.handleKeyEvents_;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the Zippy handles its own mouse events.
    - */
    -goog.ui.Zippy.prototype.isHandleMouseEvents = function() {
    -  return this.handleMouseEvents_;
    -};
    -
    -
    -/**
    - * Sets whether the Zippy handles it's own keyboard events.
    - * @param {boolean} enable Whether the Zippy handles keyboard events.
    - */
    -goog.ui.Zippy.prototype.setHandleKeyboardEvents = function(enable) {
    -  if (this.handleKeyEvents_ != enable) {
    -    this.handleKeyEvents_ = enable;
    -    if (enable) {
    -      this.enableKeyboardEventsHandling_(this.elHeader_);
    -      this.enableKeyboardEventsHandling_(this.elExpandedHeader_);
    -    } else {
    -      this.keyboardEventHandler_.removeAll();
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Sets whether the Zippy handles it's own mouse events.
    - * @param {boolean} enable Whether the Zippy handles mouse events.
    - */
    -goog.ui.Zippy.prototype.setHandleMouseEvents = function(enable) {
    -  if (this.handleMouseEvents_ != enable) {
    -    this.handleMouseEvents_ = enable;
    -    if (enable) {
    -      this.enableMouseEventsHandling_(this.elHeader_);
    -      this.enableMouseEventsHandling_(this.elExpandedHeader_);
    -    } else {
    -      this.mouseEventHandler_.removeAll();
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Enables keyboard events handling for the passed header element.
    - * @param {Element} header The header element.
    - * @private
    - */
    -goog.ui.Zippy.prototype.enableKeyboardEventsHandling_ = function(header) {
    -  if (header) {
    -    this.keyboardEventHandler_.listen(header, goog.events.EventType.KEYDOWN,
    -        this.onHeaderKeyDown_);
    -  }
    -};
    -
    -
    -/**
    - * Enables mouse events handling for the passed header element.
    - * @param {Element} header The header element.
    - * @private
    - */
    -goog.ui.Zippy.prototype.enableMouseEventsHandling_ = function(header) {
    -  if (header) {
    -    this.mouseEventHandler_.listen(header, goog.events.EventType.CLICK,
    -        this.onHeaderClick_);
    -  }
    -};
    -
    -
    -/**
    - * KeyDown event handler for header element. Enter and space toggles expanded
    - * state.
    - *
    - * @param {goog.events.BrowserEvent} event KeyDown event.
    - * @private
    - */
    -goog.ui.Zippy.prototype.onHeaderKeyDown_ = function(event) {
    -  if (event.keyCode == goog.events.KeyCodes.ENTER ||
    -      event.keyCode == goog.events.KeyCodes.SPACE) {
    -
    -    this.toggle();
    -    this.dispatchActionEvent_();
    -
    -    // Prevent enter key from submitting form.
    -    event.preventDefault();
    -
    -    event.stopPropagation();
    -  }
    -};
    -
    -
    -/**
    - * Click event handler for header element.
    - *
    - * @param {goog.events.BrowserEvent} event Click event.
    - * @private
    - */
    -goog.ui.Zippy.prototype.onHeaderClick_ = function(event) {
    -  this.toggle();
    -  this.dispatchActionEvent_();
    -};
    -
    -
    -/**
    - * Dispatch an ACTION event whenever there is user interaction with the header.
    - * Please note that after the zippy state change is completed a TOGGLE event
    - * will be dispatched. However, the TOGGLE event is dispatch on every toggle,
    - * including programmatic call to {@code #toggle}.
    - * @private
    - */
    -goog.ui.Zippy.prototype.dispatchActionEvent_ = function() {
    -  this.dispatchEvent(new goog.events.Event(goog.ui.Zippy.Events.ACTION, this));
    -};
    -
    -
    -
    -/**
    - * Object representing a zippy toggle event.
    - *
    - * @param {string} type Event type.
    - * @param {goog.ui.Zippy} target Zippy widget initiating event.
    - * @param {boolean} expanded Expanded state.
    - * @extends {goog.events.Event}
    - * @constructor
    - * @final
    - */
    -goog.ui.ZippyEvent = function(type, target, expanded) {
    -  goog.ui.ZippyEvent.base(this, 'constructor', type, target);
    -
    -  /**
    -   * The expanded state.
    -   * @type {boolean}
    -   */
    -  this.expanded = expanded;
    -};
    -goog.inherits(goog.ui.ZippyEvent, goog.events.Event);
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/zippy_test.html b/src/database/third_party/closure-library/closure/goog/ui/zippy_test.html
    deleted file mode 100644
    index 0ec9fe299ef..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/zippy_test.html
    +++ /dev/null
    @@ -1,57 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    - <!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.ui.Zippy
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -   goog.require('goog.ui.ZippyTest');
    -  </script>
    -  <style type="text/css">
    -   .demo {
    -      border: solid 1px red;
    -      margin: 0 0 20px 0;
    -    }
    -
    -    .demo h2 {
    -      background-color: yellow;
    -      border: solid 1px #ccc;
    -      padding: 2px;
    -      margin: 0;
    -      font-size: 100%;
    -    }
    -
    -    .demo div {
    -      border: solid 1px #ccc;
    -      padding: 2px;
    -    }
    -  </style>
    - </head>
    - <body>
    -  <div class="demo" id="d1">
    -   <h2 id="t1">
    -    handler
    -   </h2>
    -   <div id="c1">
    -    sem. Suspendisse porta felis ac ipsum. Sed tincidunt dui vitae nulla. Ut
    -    blandit. Nunc non neque. Mauris placerat. Vestibulum mollis tellus id dolor.
    -    Phasellus ac dolor molestie nunc euismod aliquam. Mauris tellus ipsum,
    -    fringilla id, tincidunt eu, vestibulum sit amet, metus. Quisque congue
    -    varius
    -    ligula. Quisque ornare mollis enim. Aliquam erat volutpat. Nulla mattis
    -    venenatis magna.
    -   </div>
    -  </div>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/ui/zippy_test.js b/src/database/third_party/closure-library/closure/goog/ui/zippy_test.js
    deleted file mode 100644
    index 22f461fa0c7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/ui/zippy_test.js
    +++ /dev/null
    @@ -1,267 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.ui.ZippyTest');
    -goog.setTestOnly('goog.ui.ZippyTest');
    -
    -goog.require('goog.a11y.aria');
    -goog.require('goog.dom');
    -goog.require('goog.dom.classlist');
    -goog.require('goog.events');
    -goog.require('goog.object');
    -goog.require('goog.testing.events');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.ui.Zippy');
    -
    -var zippy, fakeZippy1, fakeZippy2, contentlessZippy, headerlessZippy;
    -var lazyZippy;
    -var lazyZippyCallCount;
    -var lazyZippyContentEl;
    -var dualHeaderZippy;
    -var dualHeaderZippyCollapsedHeaderEl;
    -var dualHeaderZippyExpandedHeaderEl;
    -
    -function setUp() {
    -  zippy = new goog.ui.Zippy(goog.dom.getElement('t1'),
    -      goog.dom.getElement('c1'));
    -
    -  var fakeControlEl = document.createElement('button');
    -  var fakeContentEl = document.createElement('div');
    -
    -  fakeZippy1 = new goog.ui.Zippy(fakeControlEl.cloneNode(true),
    -      fakeContentEl.cloneNode(true), true);
    -  fakeZippy2 = new goog.ui.Zippy(fakeControlEl.cloneNode(true),
    -      fakeContentEl.cloneNode(true), false);
    -  contentlessZippy = new goog.ui.Zippy(fakeControlEl.cloneNode(true),
    -      undefined, true);
    -  headerlessZippy = new goog.ui.Zippy(null, fakeContentEl.cloneNode(true),
    -      true);
    -
    -  lazyZippyCallCount = 0;
    -  lazyZippyContentEl = fakeContentEl.cloneNode(true);
    -  lazyZippy = new goog.ui.Zippy(goog.dom.getElement('t1'), function() {
    -    lazyZippyCallCount++;
    -    return lazyZippyContentEl;
    -  });
    -  dualHeaderZippyCollapsedHeaderEl = fakeControlEl.cloneNode(true);
    -  dualHeaderZippyExpandedHeaderEl = fakeControlEl.cloneNode(true);
    -  dualHeaderZippy = new goog.ui.Zippy(dualHeaderZippyCollapsedHeaderEl,
    -      fakeContentEl.cloneNode(true), false, dualHeaderZippyExpandedHeaderEl);
    -}
    -
    -function testConstructor() {
    -  assertNotNull('must not be null', zippy);
    -}
    -
    -function testIsExpanded() {
    -  assertEquals('Default expanded must be false', false, zippy.isExpanded());
    -  assertEquals('Expanded must be true', true, fakeZippy1.isExpanded());
    -  assertEquals('Expanded must be false', false, fakeZippy2.isExpanded());
    -  assertEquals('Expanded must be true', true, headerlessZippy.isExpanded());
    -  assertEquals('Expanded must be false', false, lazyZippy.isExpanded());
    -  assertEquals('Expanded must be false', false, dualHeaderZippy.isExpanded());
    -}
    -
    -function tearDown() {
    -  zippy.dispose();
    -  fakeZippy1.dispose();
    -  fakeZippy2.dispose();
    -  contentlessZippy.dispose();
    -  headerlessZippy.dispose();
    -  lazyZippy.dispose();
    -  dualHeaderZippy.dispose();
    -}
    -
    -function testExpandCollapse() {
    -  zippy.expand();
    -  headerlessZippy.expand();
    -  assertEquals('expanded must be true', true, zippy.isExpanded());
    -  assertEquals('expanded must be true', true, headerlessZippy.isExpanded());
    -
    -  zippy.collapse();
    -  headerlessZippy.collapse();
    -  assertEquals('expanded must be false', false, zippy.isExpanded());
    -  assertEquals('expanded must be false', false, headerlessZippy.isExpanded());
    -}
    -
    -function testExpandCollapse_lazyZippy() {
    -  assertEquals('callback should not be called #1.', 0, lazyZippyCallCount);
    -  lazyZippy.collapse();
    -  assertEquals('callback should not be called #2.', 0, lazyZippyCallCount);
    -
    -  lazyZippy.expand();
    -  assertEquals('callback should be called once #1.', 1, lazyZippyCallCount);
    -  assertEquals('expanded must be true', true, lazyZippy.isExpanded());
    -  assertEquals('contentEl should be visible', '',
    -      lazyZippyContentEl.style.display);
    -
    -  lazyZippy.collapse();
    -  assertEquals('callback should be called once #2.', 1, lazyZippyCallCount);
    -  assertEquals('expanded must be false', false, lazyZippy.isExpanded());
    -  assertEquals('contentEl should not be visible', 'none',
    -      lazyZippyContentEl.style.display);
    -
    -  lazyZippy.expand();
    -  assertEquals('callback should be called once #3.', 1, lazyZippyCallCount);
    -  assertEquals('expanded must be true #2', true, lazyZippy.isExpanded());
    -  assertEquals('contentEl should be visible #2', '',
    -      lazyZippyContentEl.style.display);
    -}
    -
    -function testExpandCollapse_dualHeaderZippy() {
    -  dualHeaderZippy.expand();
    -  assertEquals('expanded must be true', true, dualHeaderZippy.isExpanded());
    -  assertFalse('collapsed header should not have state class name #1',
    -      hasCollapseOrExpandClasses(dualHeaderZippyCollapsedHeaderEl));
    -  assertFalse('expanded header should not have state class name #1',
    -      hasCollapseOrExpandClasses(dualHeaderZippyExpandedHeaderEl));
    -
    -  dualHeaderZippy.collapse();
    -  assertEquals('expanded must be false', false, dualHeaderZippy.isExpanded());
    -  assertFalse('collapsed header should not have state class name #2',
    -      hasCollapseOrExpandClasses(dualHeaderZippyCollapsedHeaderEl));
    -  assertFalse('expanded header should not have state class name #2',
    -      hasCollapseOrExpandClasses(dualHeaderZippyExpandedHeaderEl));
    -}
    -
    -function testSetExpand() {
    -  var expanded = !zippy.isExpanded();
    -  zippy.setExpanded(expanded);
    -  assertEquals('expanded must be ' + expanded, expanded, zippy.isExpanded());
    -}
    -
    -function testCssClassesAndAria() {
    -  assertTrue('goog-zippy-header is enabled',
    -      goog.dom.classlist.contains(zippy.elHeader_, 'goog-zippy-header'));
    -  assertNotNull(zippy.elHeader_);
    -  assertEquals('header aria-expanded is false', 'false',
    -      goog.a11y.aria.getState(zippy.elHeader_, 'expanded'));
    -  zippy.setExpanded(true);
    -  assertTrue('goog-zippy-content is enabled',
    -      goog.dom.classlist.contains(zippy.getContentElement(),
    -      'goog-zippy-content'));
    -  assertEquals('header aria role is TAB', 'tab',
    -      goog.a11y.aria.getRole(zippy.elHeader_));
    -  assertEquals('header aria-expanded is true', 'true',
    -      goog.a11y.aria.getState(zippy.elHeader_, 'expanded'));
    -}
    -
    -function testHeaderTabIndex() {
    -  assertEquals('Header tabIndex is 0', 0, zippy.elHeader_.tabIndex);
    -}
    -
    -function testGetVisibleHeaderElement() {
    -  dualHeaderZippy.setExpanded(false);
    -  assertEquals(dualHeaderZippyCollapsedHeaderEl,
    -      dualHeaderZippy.getVisibleHeaderElement());
    -  dualHeaderZippy.setExpanded(true);
    -  assertEquals(dualHeaderZippyExpandedHeaderEl,
    -      dualHeaderZippy.getVisibleHeaderElement());
    -}
    -
    -function testToggle() {
    -  var expanded = !zippy.isExpanded();
    -  zippy.toggle();
    -  assertEquals('expanded must be ' + expanded, expanded, zippy.isExpanded());
    -}
    -
    -function testCustomEventTOGGLE() {
    -  var dispatchedActionCount;
    -  var handleAction = function() {
    -    dispatchedActionCount++;
    -  };
    -
    -  var doTest = function(zippyObj) {
    -    dispatchedActionCount = 0;
    -    goog.events.listen(zippyObj, goog.ui.Zippy.Events.TOGGLE, handleAction);
    -    zippy.toggle();
    -    assertEquals('Custom Event must be called ', 1, dispatchedActionCount);
    -  };
    -
    -  doTest(zippy);
    -  doTest(fakeZippy1);
    -  doTest(contentlessZippy);
    -  doTest(headerlessZippy);
    -}
    -
    -function testActionEvent() {
    -  var actionEventCount = 0;
    -  var toggleEventCount = 0;
    -  var handleEvent = function(e) {
    -    if (e.type == goog.ui.Zippy.Events.TOGGLE) {
    -      toggleEventCount++;
    -    } else if (e.type == goog.ui.Zippy.Events.ACTION) {
    -      actionEventCount++;
    -      assertTrue('toggle must have been called first',
    -          toggleEventCount >= actionEventCount);
    -    }
    -  };
    -  goog.events.listen(zippy, goog.object.getValues(goog.ui.Zippy.Events),
    -      handleEvent);
    -  goog.testing.events.fireClickSequence(zippy.elHeader_);
    -  assertEquals('Zippy ACTION event fired', 1, actionEventCount);
    -  assertEquals('Zippy TOGGLE event fired', 1, toggleEventCount);
    -
    -  zippy.toggle();
    -  assertEquals('Zippy ACTION event NOT fired', 1, actionEventCount);
    -  assertEquals('Zippy TOGGLE event fired', 2, toggleEventCount);
    -}
    -
    -function testBasicZippyBehavior() {
    -  var dispatchedActionCount = 0;
    -  var handleAction = function() {
    -    dispatchedActionCount++;
    -  };
    -
    -  goog.events.listen(zippy, goog.ui.Zippy.Events.TOGGLE, handleAction);
    -  goog.testing.events.fireClickSequence(zippy.elHeader_);
    -  assertEquals('Zippy  must have dispatched TOGGLE on click', 1,
    -      dispatchedActionCount);
    -
    -}
    -
    -function hasCollapseOrExpandClasses(el) {
    -  var isCollapsed = goog.dom.classlist.contains(el, 'goog-zippy-collapsed');
    -  var isExpanded = goog.dom.classlist.contains(el, 'goog-zippy-expanded');
    -  return isCollapsed || isExpanded;
    -}
    -
    -function testIsHandleKeyEvent() {
    -  zippy.setHandleKeyboardEvents(false);
    -  assertFalse('Zippy is not handling key events', zippy.isHandleKeyEvents());
    -  assertTrue('Zippy setHandleKeyEvents does not affect handling mouse events',
    -      zippy.isHandleMouseEvents());
    -  assertEquals(0, zippy.keyboardEventHandler_.getListenerCount());
    -
    -  zippy.setHandleKeyboardEvents(true);
    -  assertTrue('Zippy is handling key events', zippy.isHandleKeyEvents());
    -  assertTrue('Zippy setHandleKeyEvents does not affect handling mouse events',
    -      zippy.isHandleMouseEvents());
    -  assertNotEquals(0, zippy.keyboardEventHandler_.getListenerCount());
    -}
    -
    -function testIsHandleMouseEvent() {
    -  zippy.setHandleMouseEvents(false);
    -  assertFalse('Zippy is not handling mouse events',
    -      zippy.isHandleMouseEvents());
    -  assertTrue('Zippy setHandleMouseEvents does not affect handling key events',
    -      zippy.isHandleKeyEvents());
    -  assertEquals(0, zippy.mouseEventHandler_.getListenerCount());
    -
    -  zippy.setHandleMouseEvents(true);
    -  assertTrue('Zippy is handling mouse events', zippy.isHandleMouseEvents());
    -  assertTrue('Zippy setHandleMouseEvents does not affect handling key events',
    -      zippy.isHandleKeyEvents());
    -  assertNotEquals(0, zippy.mouseEventHandler_.getListenerCount());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/uri/uri.js b/src/database/third_party/closure-library/closure/goog/uri/uri.js
    deleted file mode 100644
    index 86b9d47a43b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/uri/uri.js
    +++ /dev/null
    @@ -1,1526 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Class for parsing and formatting URIs.
    - *
    - * Use goog.Uri(string) to parse a URI string.  Use goog.Uri.create(...) to
    - * create a new instance of the goog.Uri object from Uri parts.
    - *
    - * e.g: <code>var myUri = new goog.Uri(window.location);</code>
    - *
    - * Implements RFC 3986 for parsing/formatting URIs.
    - * http://www.ietf.org/rfc/rfc3986.txt
    - *
    - * Some changes have been made to the interface (more like .NETs), though the
    - * internal representation is now of un-encoded parts, this will change the
    - * behavior slightly.
    - *
    - */
    -
    -goog.provide('goog.Uri');
    -goog.provide('goog.Uri.QueryData');
    -
    -goog.require('goog.array');
    -goog.require('goog.string');
    -goog.require('goog.structs');
    -goog.require('goog.structs.Map');
    -goog.require('goog.uri.utils');
    -goog.require('goog.uri.utils.ComponentIndex');
    -goog.require('goog.uri.utils.StandardQueryParam');
    -
    -
    -
    -/**
    - * This class contains setters and getters for the parts of the URI.
    - * The <code>getXyz</code>/<code>setXyz</code> methods return the decoded part
    - * -- so<code>goog.Uri.parse('/foo%20bar').getPath()</code> will return the
    - * decoded path, <code>/foo bar</code>.
    - *
    - * Reserved characters (see RFC 3986 section 2.2) can be present in
    - * their percent-encoded form in scheme, domain, and path URI components and
    - * will not be auto-decoded. For example:
    - * <code>goog.Uri.parse('rel%61tive/path%2fto/resource').getPath()</code> will
    - * return <code>relative/path%2fto/resource</code>.
    - *
    - * The constructor accepts an optional unparsed, raw URI string.  The parser
    - * is relaxed, so special characters that aren't escaped but don't cause
    - * ambiguities will not cause parse failures.
    - *
    - * All setters return <code>this</code> and so may be chained, a la
    - * <code>goog.Uri.parse('/foo').setFragment('part').toString()</code>.
    - *
    - * @param {*=} opt_uri Optional string URI to parse
    - *        (use goog.Uri.create() to create a URI from parts), or if
    - *        a goog.Uri is passed, a clone is created.
    - * @param {boolean=} opt_ignoreCase If true, #getParameterValue will ignore
    - * the case of the parameter name.
    - *
    - * @constructor
    - * @struct
    - */
    -goog.Uri = function(opt_uri, opt_ignoreCase) {
    -  // Parse in the uri string
    -  var m;
    -  if (opt_uri instanceof goog.Uri) {
    -    this.ignoreCase_ = goog.isDef(opt_ignoreCase) ?
    -        opt_ignoreCase : opt_uri.getIgnoreCase();
    -    this.setScheme(opt_uri.getScheme());
    -    this.setUserInfo(opt_uri.getUserInfo());
    -    this.setDomain(opt_uri.getDomain());
    -    this.setPort(opt_uri.getPort());
    -    this.setPath(opt_uri.getPath());
    -    this.setQueryData(opt_uri.getQueryData().clone());
    -    this.setFragment(opt_uri.getFragment());
    -  } else if (opt_uri && (m = goog.uri.utils.split(String(opt_uri)))) {
    -    this.ignoreCase_ = !!opt_ignoreCase;
    -
    -    // Set the parts -- decoding as we do so.
    -    // COMPATABILITY NOTE - In IE, unmatched fields may be empty strings,
    -    // whereas in other browsers they will be undefined.
    -    this.setScheme(m[goog.uri.utils.ComponentIndex.SCHEME] || '', true);
    -    this.setUserInfo(m[goog.uri.utils.ComponentIndex.USER_INFO] || '', true);
    -    this.setDomain(m[goog.uri.utils.ComponentIndex.DOMAIN] || '', true);
    -    this.setPort(m[goog.uri.utils.ComponentIndex.PORT]);
    -    this.setPath(m[goog.uri.utils.ComponentIndex.PATH] || '', true);
    -    this.setQueryData(m[goog.uri.utils.ComponentIndex.QUERY_DATA] || '', true);
    -    this.setFragment(m[goog.uri.utils.ComponentIndex.FRAGMENT] || '', true);
    -
    -  } else {
    -    this.ignoreCase_ = !!opt_ignoreCase;
    -    this.queryData_ = new goog.Uri.QueryData(null, null, this.ignoreCase_);
    -  }
    -};
    -
    -
    -/**
    - * If true, we preserve the type of query parameters set programmatically.
    - *
    - * This means that if you set a parameter to a boolean, and then call
    - * getParameterValue, you will get a boolean back.
    - *
    - * If false, we will coerce parameters to strings, just as they would
    - * appear in real URIs.
    - *
    - * TODO(nicksantos): Remove this once people have time to fix all tests.
    - *
    - * @type {boolean}
    - */
    -goog.Uri.preserveParameterTypesCompatibilityFlag = false;
    -
    -
    -/**
    - * Parameter name added to stop caching.
    - * @type {string}
    - */
    -goog.Uri.RANDOM_PARAM = goog.uri.utils.StandardQueryParam.RANDOM;
    -
    -
    -/**
    - * Scheme such as "http".
    - * @type {string}
    - * @private
    - */
    -goog.Uri.prototype.scheme_ = '';
    -
    -
    -/**
    - * User credentials in the form "username:password".
    - * @type {string}
    - * @private
    - */
    -goog.Uri.prototype.userInfo_ = '';
    -
    -
    -/**
    - * Domain part, e.g. "www.google.com".
    - * @type {string}
    - * @private
    - */
    -goog.Uri.prototype.domain_ = '';
    -
    -
    -/**
    - * Port, e.g. 8080.
    - * @type {?number}
    - * @private
    - */
    -goog.Uri.prototype.port_ = null;
    -
    -
    -/**
    - * Path, e.g. "/tests/img.png".
    - * @type {string}
    - * @private
    - */
    -goog.Uri.prototype.path_ = '';
    -
    -
    -/**
    - * Object representing query data.
    - * @type {!goog.Uri.QueryData}
    - * @private
    - */
    -goog.Uri.prototype.queryData_;
    -
    -
    -/**
    - * The fragment without the #.
    - * @type {string}
    - * @private
    - */
    -goog.Uri.prototype.fragment_ = '';
    -
    -
    -/**
    - * Whether or not this Uri should be treated as Read Only.
    - * @type {boolean}
    - * @private
    - */
    -goog.Uri.prototype.isReadOnly_ = false;
    -
    -
    -/**
    - * Whether or not to ignore case when comparing query params.
    - * @type {boolean}
    - * @private
    - */
    -goog.Uri.prototype.ignoreCase_ = false;
    -
    -
    -/**
    - * @return {string} The string form of the url.
    - * @override
    - */
    -goog.Uri.prototype.toString = function() {
    -  var out = [];
    -
    -  var scheme = this.getScheme();
    -  if (scheme) {
    -    out.push(goog.Uri.encodeSpecialChars_(
    -        scheme, goog.Uri.reDisallowedInSchemeOrUserInfo_, true), ':');
    -  }
    -
    -  var domain = this.getDomain();
    -  if (domain) {
    -    out.push('//');
    -
    -    var userInfo = this.getUserInfo();
    -    if (userInfo) {
    -      out.push(goog.Uri.encodeSpecialChars_(
    -          userInfo, goog.Uri.reDisallowedInSchemeOrUserInfo_, true), '@');
    -    }
    -
    -    out.push(goog.Uri.removeDoubleEncoding_(goog.string.urlEncode(domain)));
    -
    -    var port = this.getPort();
    -    if (port != null) {
    -      out.push(':', String(port));
    -    }
    -  }
    -
    -  var path = this.getPath();
    -  if (path) {
    -    if (this.hasDomain() && path.charAt(0) != '/') {
    -      out.push('/');
    -    }
    -    out.push(goog.Uri.encodeSpecialChars_(
    -        path,
    -        path.charAt(0) == '/' ?
    -            goog.Uri.reDisallowedInAbsolutePath_ :
    -            goog.Uri.reDisallowedInRelativePath_,
    -        true));
    -  }
    -
    -  var query = this.getEncodedQuery();
    -  if (query) {
    -    out.push('?', query);
    -  }
    -
    -  var fragment = this.getFragment();
    -  if (fragment) {
    -    out.push('#', goog.Uri.encodeSpecialChars_(
    -        fragment, goog.Uri.reDisallowedInFragment_));
    -  }
    -  return out.join('');
    -};
    -
    -
    -/**
    - * Resolves the given relative URI (a goog.Uri object), using the URI
    - * represented by this instance as the base URI.
    - *
    - * There are several kinds of relative URIs:<br>
    - * 1. foo - replaces the last part of the path, the whole query and fragment<br>
    - * 2. /foo - replaces the the path, the query and fragment<br>
    - * 3. //foo - replaces everything from the domain on.  foo is a domain name<br>
    - * 4. ?foo - replace the query and fragment<br>
    - * 5. #foo - replace the fragment only
    - *
    - * Additionally, if relative URI has a non-empty path, all ".." and "."
    - * segments will be resolved, as described in RFC 3986.
    - *
    - * @param {!goog.Uri} relativeUri The relative URI to resolve.
    - * @return {!goog.Uri} The resolved URI.
    - */
    -goog.Uri.prototype.resolve = function(relativeUri) {
    -
    -  var absoluteUri = this.clone();
    -
    -  // we satisfy these conditions by looking for the first part of relativeUri
    -  // that is not blank and applying defaults to the rest
    -
    -  var overridden = relativeUri.hasScheme();
    -
    -  if (overridden) {
    -    absoluteUri.setScheme(relativeUri.getScheme());
    -  } else {
    -    overridden = relativeUri.hasUserInfo();
    -  }
    -
    -  if (overridden) {
    -    absoluteUri.setUserInfo(relativeUri.getUserInfo());
    -  } else {
    -    overridden = relativeUri.hasDomain();
    -  }
    -
    -  if (overridden) {
    -    absoluteUri.setDomain(relativeUri.getDomain());
    -  } else {
    -    overridden = relativeUri.hasPort();
    -  }
    -
    -  var path = relativeUri.getPath();
    -  if (overridden) {
    -    absoluteUri.setPort(relativeUri.getPort());
    -  } else {
    -    overridden = relativeUri.hasPath();
    -    if (overridden) {
    -      // resolve path properly
    -      if (path.charAt(0) != '/') {
    -        // path is relative
    -        if (this.hasDomain() && !this.hasPath()) {
    -          // RFC 3986, section 5.2.3, case 1
    -          path = '/' + path;
    -        } else {
    -          // RFC 3986, section 5.2.3, case 2
    -          var lastSlashIndex = absoluteUri.getPath().lastIndexOf('/');
    -          if (lastSlashIndex != -1) {
    -            path = absoluteUri.getPath().substr(0, lastSlashIndex + 1) + path;
    -          }
    -        }
    -      }
    -      path = goog.Uri.removeDotSegments(path);
    -    }
    -  }
    -
    -  if (overridden) {
    -    absoluteUri.setPath(path);
    -  } else {
    -    overridden = relativeUri.hasQuery();
    -  }
    -
    -  if (overridden) {
    -    absoluteUri.setQueryData(relativeUri.getDecodedQuery());
    -  } else {
    -    overridden = relativeUri.hasFragment();
    -  }
    -
    -  if (overridden) {
    -    absoluteUri.setFragment(relativeUri.getFragment());
    -  }
    -
    -  return absoluteUri;
    -};
    -
    -
    -/**
    - * Clones the URI instance.
    - * @return {!goog.Uri} New instance of the URI object.
    - */
    -goog.Uri.prototype.clone = function() {
    -  return new goog.Uri(this);
    -};
    -
    -
    -/**
    - * @return {string} The encoded scheme/protocol for the URI.
    - */
    -goog.Uri.prototype.getScheme = function() {
    -  return this.scheme_;
    -};
    -
    -
    -/**
    - * Sets the scheme/protocol.
    - * @param {string} newScheme New scheme value.
    - * @param {boolean=} opt_decode Optional param for whether to decode new value.
    - * @return {!goog.Uri} Reference to this URI object.
    - */
    -goog.Uri.prototype.setScheme = function(newScheme, opt_decode) {
    -  this.enforceReadOnly();
    -  this.scheme_ = opt_decode ? goog.Uri.decodeOrEmpty_(newScheme, true) :
    -      newScheme;
    -
    -  // remove an : at the end of the scheme so somebody can pass in
    -  // window.location.protocol
    -  if (this.scheme_) {
    -    this.scheme_ = this.scheme_.replace(/:$/, '');
    -  }
    -  return this;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the scheme has been set.
    - */
    -goog.Uri.prototype.hasScheme = function() {
    -  return !!this.scheme_;
    -};
    -
    -
    -/**
    - * @return {string} The decoded user info.
    - */
    -goog.Uri.prototype.getUserInfo = function() {
    -  return this.userInfo_;
    -};
    -
    -
    -/**
    - * Sets the userInfo.
    - * @param {string} newUserInfo New userInfo value.
    - * @param {boolean=} opt_decode Optional param for whether to decode new value.
    - * @return {!goog.Uri} Reference to this URI object.
    - */
    -goog.Uri.prototype.setUserInfo = function(newUserInfo, opt_decode) {
    -  this.enforceReadOnly();
    -  this.userInfo_ = opt_decode ? goog.Uri.decodeOrEmpty_(newUserInfo) :
    -                   newUserInfo;
    -  return this;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the user info has been set.
    - */
    -goog.Uri.prototype.hasUserInfo = function() {
    -  return !!this.userInfo_;
    -};
    -
    -
    -/**
    - * @return {string} The decoded domain.
    - */
    -goog.Uri.prototype.getDomain = function() {
    -  return this.domain_;
    -};
    -
    -
    -/**
    - * Sets the domain.
    - * @param {string} newDomain New domain value.
    - * @param {boolean=} opt_decode Optional param for whether to decode new value.
    - * @return {!goog.Uri} Reference to this URI object.
    - */
    -goog.Uri.prototype.setDomain = function(newDomain, opt_decode) {
    -  this.enforceReadOnly();
    -  this.domain_ = opt_decode ? goog.Uri.decodeOrEmpty_(newDomain, true) :
    -      newDomain;
    -  return this;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the domain has been set.
    - */
    -goog.Uri.prototype.hasDomain = function() {
    -  return !!this.domain_;
    -};
    -
    -
    -/**
    - * @return {?number} The port number.
    - */
    -goog.Uri.prototype.getPort = function() {
    -  return this.port_;
    -};
    -
    -
    -/**
    - * Sets the port number.
    - * @param {*} newPort Port number. Will be explicitly casted to a number.
    - * @return {!goog.Uri} Reference to this URI object.
    - */
    -goog.Uri.prototype.setPort = function(newPort) {
    -  this.enforceReadOnly();
    -
    -  if (newPort) {
    -    newPort = Number(newPort);
    -    if (isNaN(newPort) || newPort < 0) {
    -      throw Error('Bad port number ' + newPort);
    -    }
    -    this.port_ = newPort;
    -  } else {
    -    this.port_ = null;
    -  }
    -
    -  return this;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the port has been set.
    - */
    -goog.Uri.prototype.hasPort = function() {
    -  return this.port_ != null;
    -};
    -
    -
    -/**
    -  * @return {string} The decoded path.
    - */
    -goog.Uri.prototype.getPath = function() {
    -  return this.path_;
    -};
    -
    -
    -/**
    - * Sets the path.
    - * @param {string} newPath New path value.
    - * @param {boolean=} opt_decode Optional param for whether to decode new value.
    - * @return {!goog.Uri} Reference to this URI object.
    - */
    -goog.Uri.prototype.setPath = function(newPath, opt_decode) {
    -  this.enforceReadOnly();
    -  this.path_ = opt_decode ? goog.Uri.decodeOrEmpty_(newPath, true) : newPath;
    -  return this;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the path has been set.
    - */
    -goog.Uri.prototype.hasPath = function() {
    -  return !!this.path_;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the query string has been set.
    - */
    -goog.Uri.prototype.hasQuery = function() {
    -  return this.queryData_.toString() !== '';
    -};
    -
    -
    -/**
    - * Sets the query data.
    - * @param {goog.Uri.QueryData|string|undefined} queryData QueryData object.
    - * @param {boolean=} opt_decode Optional param for whether to decode new value.
    - *     Applies only if queryData is a string.
    - * @return {!goog.Uri} Reference to this URI object.
    - */
    -goog.Uri.prototype.setQueryData = function(queryData, opt_decode) {
    -  this.enforceReadOnly();
    -
    -  if (queryData instanceof goog.Uri.QueryData) {
    -    this.queryData_ = queryData;
    -    this.queryData_.setIgnoreCase(this.ignoreCase_);
    -  } else {
    -    if (!opt_decode) {
    -      // QueryData accepts encoded query string, so encode it if
    -      // opt_decode flag is not true.
    -      queryData = goog.Uri.encodeSpecialChars_(queryData,
    -                                               goog.Uri.reDisallowedInQuery_);
    -    }
    -    this.queryData_ = new goog.Uri.QueryData(queryData, null, this.ignoreCase_);
    -  }
    -
    -  return this;
    -};
    -
    -
    -/**
    - * Sets the URI query.
    - * @param {string} newQuery New query value.
    - * @param {boolean=} opt_decode Optional param for whether to decode new value.
    - * @return {!goog.Uri} Reference to this URI object.
    - */
    -goog.Uri.prototype.setQuery = function(newQuery, opt_decode) {
    -  return this.setQueryData(newQuery, opt_decode);
    -};
    -
    -
    -/**
    - * @return {string} The encoded URI query, not including the ?.
    - */
    -goog.Uri.prototype.getEncodedQuery = function() {
    -  return this.queryData_.toString();
    -};
    -
    -
    -/**
    - * @return {string} The decoded URI query, not including the ?.
    - */
    -goog.Uri.prototype.getDecodedQuery = function() {
    -  return this.queryData_.toDecodedString();
    -};
    -
    -
    -/**
    - * Returns the query data.
    - * @return {!goog.Uri.QueryData} QueryData object.
    - */
    -goog.Uri.prototype.getQueryData = function() {
    -  return this.queryData_;
    -};
    -
    -
    -/**
    - * @return {string} The encoded URI query, not including the ?.
    - *
    - * Warning: This method, unlike other getter methods, returns encoded
    - * value, instead of decoded one.
    - */
    -goog.Uri.prototype.getQuery = function() {
    -  return this.getEncodedQuery();
    -};
    -
    -
    -/**
    - * Sets the value of the named query parameters, clearing previous values for
    - * that key.
    - *
    - * @param {string} key The parameter to set.
    - * @param {*} value The new value.
    - * @return {!goog.Uri} Reference to this URI object.
    - */
    -goog.Uri.prototype.setParameterValue = function(key, value) {
    -  this.enforceReadOnly();
    -  this.queryData_.set(key, value);
    -  return this;
    -};
    -
    -
    -/**
    - * Sets the values of the named query parameters, clearing previous values for
    - * that key.  Not new values will currently be moved to the end of the query
    - * string.
    - *
    - * So, <code>goog.Uri.parse('foo?a=b&c=d&e=f').setParameterValues('c', ['new'])
    - * </code> yields <tt>foo?a=b&e=f&c=new</tt>.</p>
    - *
    - * @param {string} key The parameter to set.
    - * @param {*} values The new values. If values is a single
    - *     string then it will be treated as the sole value.
    - * @return {!goog.Uri} Reference to this URI object.
    - */
    -goog.Uri.prototype.setParameterValues = function(key, values) {
    -  this.enforceReadOnly();
    -
    -  if (!goog.isArray(values)) {
    -    values = [String(values)];
    -  }
    -
    -  this.queryData_.setValues(key, values);
    -
    -  return this;
    -};
    -
    -
    -/**
    - * Returns the value<b>s</b> for a given cgi parameter as a list of decoded
    - * query parameter values.
    - * @param {string} name The parameter to get values for.
    - * @return {!Array<?>} The values for a given cgi parameter as a list of
    - *     decoded query parameter values.
    - */
    -goog.Uri.prototype.getParameterValues = function(name) {
    -  return this.queryData_.getValues(name);
    -};
    -
    -
    -/**
    - * Returns the first value for a given cgi parameter or undefined if the given
    - * parameter name does not appear in the query string.
    - * @param {string} paramName Unescaped parameter name.
    - * @return {string|undefined} The first value for a given cgi parameter or
    - *     undefined if the given parameter name does not appear in the query
    - *     string.
    - */
    -goog.Uri.prototype.getParameterValue = function(paramName) {
    -  // NOTE(nicksantos): This type-cast is a lie when
    -  // preserveParameterTypesCompatibilityFlag is set to true.
    -  // But this should only be set to true in tests.
    -  return /** @type {string|undefined} */ (this.queryData_.get(paramName));
    -};
    -
    -
    -/**
    - * @return {string} The URI fragment, not including the #.
    - */
    -goog.Uri.prototype.getFragment = function() {
    -  return this.fragment_;
    -};
    -
    -
    -/**
    - * Sets the URI fragment.
    - * @param {string} newFragment New fragment value.
    - * @param {boolean=} opt_decode Optional param for whether to decode new value.
    - * @return {!goog.Uri} Reference to this URI object.
    - */
    -goog.Uri.prototype.setFragment = function(newFragment, opt_decode) {
    -  this.enforceReadOnly();
    -  this.fragment_ = opt_decode ? goog.Uri.decodeOrEmpty_(newFragment) :
    -                   newFragment;
    -  return this;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the URI has a fragment set.
    - */
    -goog.Uri.prototype.hasFragment = function() {
    -  return !!this.fragment_;
    -};
    -
    -
    -/**
    - * Returns true if this has the same domain as that of uri2.
    - * @param {!goog.Uri} uri2 The URI object to compare to.
    - * @return {boolean} true if same domain; false otherwise.
    - */
    -goog.Uri.prototype.hasSameDomainAs = function(uri2) {
    -  return ((!this.hasDomain() && !uri2.hasDomain()) ||
    -          this.getDomain() == uri2.getDomain()) &&
    -      ((!this.hasPort() && !uri2.hasPort()) ||
    -          this.getPort() == uri2.getPort());
    -};
    -
    -
    -/**
    - * Adds a random parameter to the Uri.
    - * @return {!goog.Uri} Reference to this Uri object.
    - */
    -goog.Uri.prototype.makeUnique = function() {
    -  this.enforceReadOnly();
    -  this.setParameterValue(goog.Uri.RANDOM_PARAM, goog.string.getRandomString());
    -
    -  return this;
    -};
    -
    -
    -/**
    - * Removes the named query parameter.
    - *
    - * @param {string} key The parameter to remove.
    - * @return {!goog.Uri} Reference to this URI object.
    - */
    -goog.Uri.prototype.removeParameter = function(key) {
    -  this.enforceReadOnly();
    -  this.queryData_.remove(key);
    -  return this;
    -};
    -
    -
    -/**
    - * Sets whether Uri is read only. If this goog.Uri is read-only,
    - * enforceReadOnly_ will be called at the start of any function that may modify
    - * this Uri.
    - * @param {boolean} isReadOnly whether this goog.Uri should be read only.
    - * @return {!goog.Uri} Reference to this Uri object.
    - */
    -goog.Uri.prototype.setReadOnly = function(isReadOnly) {
    -  this.isReadOnly_ = isReadOnly;
    -  return this;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the URI is read only.
    - */
    -goog.Uri.prototype.isReadOnly = function() {
    -  return this.isReadOnly_;
    -};
    -
    -
    -/**
    - * Checks if this Uri has been marked as read only, and if so, throws an error.
    - * This should be called whenever any modifying function is called.
    - */
    -goog.Uri.prototype.enforceReadOnly = function() {
    -  if (this.isReadOnly_) {
    -    throw Error('Tried to modify a read-only Uri');
    -  }
    -};
    -
    -
    -/**
    - * Sets whether to ignore case.
    - * NOTE: If there are already key/value pairs in the QueryData, and
    - * ignoreCase_ is set to false, the keys will all be lower-cased.
    - * @param {boolean} ignoreCase whether this goog.Uri should ignore case.
    - * @return {!goog.Uri} Reference to this Uri object.
    - */
    -goog.Uri.prototype.setIgnoreCase = function(ignoreCase) {
    -  this.ignoreCase_ = ignoreCase;
    -  if (this.queryData_) {
    -    this.queryData_.setIgnoreCase(ignoreCase);
    -  }
    -  return this;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether to ignore case.
    - */
    -goog.Uri.prototype.getIgnoreCase = function() {
    -  return this.ignoreCase_;
    -};
    -
    -
    -//==============================================================================
    -// Static members
    -//==============================================================================
    -
    -
    -/**
    - * Creates a uri from the string form.  Basically an alias of new goog.Uri().
    - * If a Uri object is passed to parse then it will return a clone of the object.
    - *
    - * @param {*} uri Raw URI string or instance of Uri
    - *     object.
    - * @param {boolean=} opt_ignoreCase Whether to ignore the case of parameter
    - * names in #getParameterValue.
    - * @return {!goog.Uri} The new URI object.
    - */
    -goog.Uri.parse = function(uri, opt_ignoreCase) {
    -  return uri instanceof goog.Uri ?
    -         uri.clone() : new goog.Uri(uri, opt_ignoreCase);
    -};
    -
    -
    -/**
    - * Creates a new goog.Uri object from unencoded parts.
    - *
    - * @param {?string=} opt_scheme Scheme/protocol or full URI to parse.
    - * @param {?string=} opt_userInfo username:password.
    - * @param {?string=} opt_domain www.google.com.
    - * @param {?number=} opt_port 9830.
    - * @param {?string=} opt_path /some/path/to/a/file.html.
    - * @param {string|goog.Uri.QueryData=} opt_query a=1&b=2.
    - * @param {?string=} opt_fragment The fragment without the #.
    - * @param {boolean=} opt_ignoreCase Whether to ignore parameter name case in
    - *     #getParameterValue.
    - *
    - * @return {!goog.Uri} The new URI object.
    - */
    -goog.Uri.create = function(opt_scheme, opt_userInfo, opt_domain, opt_port,
    -                           opt_path, opt_query, opt_fragment, opt_ignoreCase) {
    -
    -  var uri = new goog.Uri(null, opt_ignoreCase);
    -
    -  // Only set the parts if they are defined and not empty strings.
    -  opt_scheme && uri.setScheme(opt_scheme);
    -  opt_userInfo && uri.setUserInfo(opt_userInfo);
    -  opt_domain && uri.setDomain(opt_domain);
    -  opt_port && uri.setPort(opt_port);
    -  opt_path && uri.setPath(opt_path);
    -  opt_query && uri.setQueryData(opt_query);
    -  opt_fragment && uri.setFragment(opt_fragment);
    -
    -  return uri;
    -};
    -
    -
    -/**
    - * Resolves a relative Uri against a base Uri, accepting both strings and
    - * Uri objects.
    - *
    - * @param {*} base Base Uri.
    - * @param {*} rel Relative Uri.
    - * @return {!goog.Uri} Resolved uri.
    - */
    -goog.Uri.resolve = function(base, rel) {
    -  if (!(base instanceof goog.Uri)) {
    -    base = goog.Uri.parse(base);
    -  }
    -
    -  if (!(rel instanceof goog.Uri)) {
    -    rel = goog.Uri.parse(rel);
    -  }
    -
    -  return base.resolve(rel);
    -};
    -
    -
    -/**
    - * Removes dot segments in given path component, as described in
    - * RFC 3986, section 5.2.4.
    - *
    - * @param {string} path A non-empty path component.
    - * @return {string} Path component with removed dot segments.
    - */
    -goog.Uri.removeDotSegments = function(path) {
    -  if (path == '..' || path == '.') {
    -    return '';
    -
    -  } else if (!goog.string.contains(path, './') &&
    -             !goog.string.contains(path, '/.')) {
    -    // This optimization detects uris which do not contain dot-segments,
    -    // and as a consequence do not require any processing.
    -    return path;
    -
    -  } else {
    -    var leadingSlash = goog.string.startsWith(path, '/');
    -    var segments = path.split('/');
    -    var out = [];
    -
    -    for (var pos = 0; pos < segments.length; ) {
    -      var segment = segments[pos++];
    -
    -      if (segment == '.') {
    -        if (leadingSlash && pos == segments.length) {
    -          out.push('');
    -        }
    -      } else if (segment == '..') {
    -        if (out.length > 1 || out.length == 1 && out[0] != '') {
    -          out.pop();
    -        }
    -        if (leadingSlash && pos == segments.length) {
    -          out.push('');
    -        }
    -      } else {
    -        out.push(segment);
    -        leadingSlash = true;
    -      }
    -    }
    -
    -    return out.join('/');
    -  }
    -};
    -
    -
    -/**
    - * Decodes a value or returns the empty string if it isn't defined or empty.
    - * @param {string|undefined} val Value to decode.
    - * @param {boolean=} opt_preserveReserved If true, restricted characters will
    - *     not be decoded.
    - * @return {string} Decoded value.
    - * @private
    - */
    -goog.Uri.decodeOrEmpty_ = function(val, opt_preserveReserved) {
    -  // Don't use UrlDecode() here because val is not a query parameter.
    -  if (!val) {
    -    return '';
    -  }
    -
    -  return opt_preserveReserved ? decodeURI(val) : decodeURIComponent(val);
    -};
    -
    -
    -/**
    - * If unescapedPart is non null, then escapes any characters in it that aren't
    - * valid characters in a url and also escapes any special characters that
    - * appear in extra.
    - *
    - * @param {*} unescapedPart The string to encode.
    - * @param {RegExp} extra A character set of characters in [\01-\177].
    - * @param {boolean=} opt_removeDoubleEncoding If true, remove double percent
    - *     encoding.
    - * @return {?string} null iff unescapedPart == null.
    - * @private
    - */
    -goog.Uri.encodeSpecialChars_ = function(unescapedPart, extra,
    -    opt_removeDoubleEncoding) {
    -  if (goog.isString(unescapedPart)) {
    -    var encoded = encodeURI(unescapedPart).
    -        replace(extra, goog.Uri.encodeChar_);
    -    if (opt_removeDoubleEncoding) {
    -      // encodeURI double-escapes %XX sequences used to represent restricted
    -      // characters in some URI components, remove the double escaping here.
    -      encoded = goog.Uri.removeDoubleEncoding_(encoded);
    -    }
    -    return encoded;
    -  }
    -  return null;
    -};
    -
    -
    -/**
    - * Converts a character in [\01-\177] to its unicode character equivalent.
    - * @param {string} ch One character string.
    - * @return {string} Encoded string.
    - * @private
    - */
    -goog.Uri.encodeChar_ = function(ch) {
    -  var n = ch.charCodeAt(0);
    -  return '%' + ((n >> 4) & 0xf).toString(16) + (n & 0xf).toString(16);
    -};
    -
    -
    -/**
    - * Removes double percent-encoding from a string.
    - * @param  {string} doubleEncodedString String
    - * @return {string} String with double encoding removed.
    - * @private
    - */
    -goog.Uri.removeDoubleEncoding_ = function(doubleEncodedString) {
    -  return doubleEncodedString.replace(/%25([0-9a-fA-F]{2})/g, '%$1');
    -};
    -
    -
    -/**
    - * Regular expression for characters that are disallowed in the scheme or
    - * userInfo part of the URI.
    - * @type {RegExp}
    - * @private
    - */
    -goog.Uri.reDisallowedInSchemeOrUserInfo_ = /[#\/\?@]/g;
    -
    -
    -/**
    - * Regular expression for characters that are disallowed in a relative path.
    - * Colon is included due to RFC 3986 3.3.
    - * @type {RegExp}
    - * @private
    - */
    -goog.Uri.reDisallowedInRelativePath_ = /[\#\?:]/g;
    -
    -
    -/**
    - * Regular expression for characters that are disallowed in an absolute path.
    - * @type {RegExp}
    - * @private
    - */
    -goog.Uri.reDisallowedInAbsolutePath_ = /[\#\?]/g;
    -
    -
    -/**
    - * Regular expression for characters that are disallowed in the query.
    - * @type {RegExp}
    - * @private
    - */
    -goog.Uri.reDisallowedInQuery_ = /[\#\?@]/g;
    -
    -
    -/**
    - * Regular expression for characters that are disallowed in the fragment.
    - * @type {RegExp}
    - * @private
    - */
    -goog.Uri.reDisallowedInFragment_ = /#/g;
    -
    -
    -/**
    - * Checks whether two URIs have the same domain.
    - * @param {string} uri1String First URI string.
    - * @param {string} uri2String Second URI string.
    - * @return {boolean} true if the two URIs have the same domain; false otherwise.
    - */
    -goog.Uri.haveSameDomain = function(uri1String, uri2String) {
    -  // Differs from goog.uri.utils.haveSameDomain, since this ignores scheme.
    -  // TODO(gboyer): Have this just call goog.uri.util.haveSameDomain.
    -  var pieces1 = goog.uri.utils.split(uri1String);
    -  var pieces2 = goog.uri.utils.split(uri2String);
    -  return pieces1[goog.uri.utils.ComponentIndex.DOMAIN] ==
    -             pieces2[goog.uri.utils.ComponentIndex.DOMAIN] &&
    -         pieces1[goog.uri.utils.ComponentIndex.PORT] ==
    -             pieces2[goog.uri.utils.ComponentIndex.PORT];
    -};
    -
    -
    -
    -/**
    - * Class used to represent URI query parameters.  It is essentially a hash of
    - * name-value pairs, though a name can be present more than once.
    - *
    - * Has the same interface as the collections in goog.structs.
    - *
    - * @param {?string=} opt_query Optional encoded query string to parse into
    - *     the object.
    - * @param {goog.Uri=} opt_uri Optional uri object that should have its
    - *     cache invalidated when this object updates. Deprecated -- this
    - *     is no longer required.
    - * @param {boolean=} opt_ignoreCase If true, ignore the case of the parameter
    - *     name in #get.
    - * @constructor
    - * @struct
    - * @final
    - */
    -goog.Uri.QueryData = function(opt_query, opt_uri, opt_ignoreCase) {
    -  /**
    -   * Encoded query string, or null if it requires computing from the key map.
    -   * @type {?string}
    -   * @private
    -   */
    -  this.encodedQuery_ = opt_query || null;
    -
    -  /**
    -   * If true, ignore the case of the parameter name in #get.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.ignoreCase_ = !!opt_ignoreCase;
    -};
    -
    -
    -/**
    - * If the underlying key map is not yet initialized, it parses the
    - * query string and fills the map with parsed data.
    - * @private
    - */
    -goog.Uri.QueryData.prototype.ensureKeyMapInitialized_ = function() {
    -  if (!this.keyMap_) {
    -    this.keyMap_ = new goog.structs.Map();
    -    this.count_ = 0;
    -    if (this.encodedQuery_) {
    -      var self = this;
    -      goog.uri.utils.parseQueryData(this.encodedQuery_, function(name, value) {
    -        self.add(goog.string.urlDecode(name), value);
    -      });
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Creates a new query data instance from a map of names and values.
    - *
    - * @param {!goog.structs.Map<string, ?>|!Object} map Map of string parameter
    - *     names to parameter value. If parameter value is an array, it is
    - *     treated as if the key maps to each individual value in the
    - *     array.
    - * @param {goog.Uri=} opt_uri URI object that should have its cache
    - *     invalidated when this object updates.
    - * @param {boolean=} opt_ignoreCase If true, ignore the case of the parameter
    - *     name in #get.
    - * @return {!goog.Uri.QueryData} The populated query data instance.
    - */
    -goog.Uri.QueryData.createFromMap = function(map, opt_uri, opt_ignoreCase) {
    -  var keys = goog.structs.getKeys(map);
    -  if (typeof keys == 'undefined') {
    -    throw Error('Keys are undefined');
    -  }
    -
    -  var queryData = new goog.Uri.QueryData(null, null, opt_ignoreCase);
    -  var values = goog.structs.getValues(map);
    -  for (var i = 0; i < keys.length; i++) {
    -    var key = keys[i];
    -    var value = values[i];
    -    if (!goog.isArray(value)) {
    -      queryData.add(key, value);
    -    } else {
    -      queryData.setValues(key, value);
    -    }
    -  }
    -  return queryData;
    -};
    -
    -
    -/**
    - * Creates a new query data instance from parallel arrays of parameter names
    - * and values. Allows for duplicate parameter names. Throws an error if the
    - * lengths of the arrays differ.
    - *
    - * @param {!Array<string>} keys Parameter names.
    - * @param {!Array<?>} values Parameter values.
    - * @param {goog.Uri=} opt_uri URI object that should have its cache
    - *     invalidated when this object updates.
    - * @param {boolean=} opt_ignoreCase If true, ignore the case of the parameter
    - *     name in #get.
    - * @return {!goog.Uri.QueryData} The populated query data instance.
    - */
    -goog.Uri.QueryData.createFromKeysValues = function(
    -    keys, values, opt_uri, opt_ignoreCase) {
    -  if (keys.length != values.length) {
    -    throw Error('Mismatched lengths for keys/values');
    -  }
    -  var queryData = new goog.Uri.QueryData(null, null, opt_ignoreCase);
    -  for (var i = 0; i < keys.length; i++) {
    -    queryData.add(keys[i], values[i]);
    -  }
    -  return queryData;
    -};
    -
    -
    -/**
    - * The map containing name/value or name/array-of-values pairs.
    - * May be null if it requires parsing from the query string.
    - *
    - * We need to use a Map because we cannot guarantee that the key names will
    - * not be problematic for IE.
    - *
    - * @private {goog.structs.Map<string, !Array<*>>}
    - */
    -goog.Uri.QueryData.prototype.keyMap_ = null;
    -
    -
    -/**
    - * The number of params, or null if it requires computing.
    - * @type {?number}
    - * @private
    - */
    -goog.Uri.QueryData.prototype.count_ = null;
    -
    -
    -/**
    - * @return {?number} The number of parameters.
    - */
    -goog.Uri.QueryData.prototype.getCount = function() {
    -  this.ensureKeyMapInitialized_();
    -  return this.count_;
    -};
    -
    -
    -/**
    - * Adds a key value pair.
    - * @param {string} key Name.
    - * @param {*} value Value.
    - * @return {!goog.Uri.QueryData} Instance of this object.
    - */
    -goog.Uri.QueryData.prototype.add = function(key, value) {
    -  this.ensureKeyMapInitialized_();
    -  this.invalidateCache_();
    -
    -  key = this.getKeyName_(key);
    -  var values = this.keyMap_.get(key);
    -  if (!values) {
    -    this.keyMap_.set(key, (values = []));
    -  }
    -  values.push(value);
    -  this.count_++;
    -  return this;
    -};
    -
    -
    -/**
    - * Removes all the params with the given key.
    - * @param {string} key Name.
    - * @return {boolean} Whether any parameter was removed.
    - */
    -goog.Uri.QueryData.prototype.remove = function(key) {
    -  this.ensureKeyMapInitialized_();
    -
    -  key = this.getKeyName_(key);
    -  if (this.keyMap_.containsKey(key)) {
    -    this.invalidateCache_();
    -
    -    // Decrement parameter count.
    -    this.count_ -= this.keyMap_.get(key).length;
    -    return this.keyMap_.remove(key);
    -  }
    -  return false;
    -};
    -
    -
    -/**
    - * Clears the parameters.
    - */
    -goog.Uri.QueryData.prototype.clear = function() {
    -  this.invalidateCache_();
    -  this.keyMap_ = null;
    -  this.count_ = 0;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether we have any parameters.
    - */
    -goog.Uri.QueryData.prototype.isEmpty = function() {
    -  this.ensureKeyMapInitialized_();
    -  return this.count_ == 0;
    -};
    -
    -
    -/**
    - * Whether there is a parameter with the given name
    - * @param {string} key The parameter name to check for.
    - * @return {boolean} Whether there is a parameter with the given name.
    - */
    -goog.Uri.QueryData.prototype.containsKey = function(key) {
    -  this.ensureKeyMapInitialized_();
    -  key = this.getKeyName_(key);
    -  return this.keyMap_.containsKey(key);
    -};
    -
    -
    -/**
    - * Whether there is a parameter with the given value.
    - * @param {*} value The value to check for.
    - * @return {boolean} Whether there is a parameter with the given value.
    - */
    -goog.Uri.QueryData.prototype.containsValue = function(value) {
    -  // NOTE(arv): This solution goes through all the params even if it was the
    -  // first param. We can get around this by not reusing code or by switching to
    -  // iterators.
    -  var vals = this.getValues();
    -  return goog.array.contains(vals, value);
    -};
    -
    -
    -/**
    - * Returns all the keys of the parameters. If a key is used multiple times
    - * it will be included multiple times in the returned array
    - * @return {!Array<string>} All the keys of the parameters.
    - */
    -goog.Uri.QueryData.prototype.getKeys = function() {
    -  this.ensureKeyMapInitialized_();
    -  // We need to get the values to know how many keys to add.
    -  var vals = /** @type {!Array<*>} */ (this.keyMap_.getValues());
    -  var keys = this.keyMap_.getKeys();
    -  var rv = [];
    -  for (var i = 0; i < keys.length; i++) {
    -    var val = vals[i];
    -    for (var j = 0; j < val.length; j++) {
    -      rv.push(keys[i]);
    -    }
    -  }
    -  return rv;
    -};
    -
    -
    -/**
    - * Returns all the values of the parameters with the given name. If the query
    - * data has no such key this will return an empty array. If no key is given
    - * all values wil be returned.
    - * @param {string=} opt_key The name of the parameter to get the values for.
    - * @return {!Array<?>} All the values of the parameters with the given name.
    - */
    -goog.Uri.QueryData.prototype.getValues = function(opt_key) {
    -  this.ensureKeyMapInitialized_();
    -  var rv = [];
    -  if (goog.isString(opt_key)) {
    -    if (this.containsKey(opt_key)) {
    -      rv = goog.array.concat(rv, this.keyMap_.get(this.getKeyName_(opt_key)));
    -    }
    -  } else {
    -    // Return all values.
    -    var values = this.keyMap_.getValues();
    -    for (var i = 0; i < values.length; i++) {
    -      rv = goog.array.concat(rv, values[i]);
    -    }
    -  }
    -  return rv;
    -};
    -
    -
    -/**
    - * Sets a key value pair and removes all other keys with the same value.
    - *
    - * @param {string} key Name.
    - * @param {*} value Value.
    - * @return {!goog.Uri.QueryData} Instance of this object.
    - */
    -goog.Uri.QueryData.prototype.set = function(key, value) {
    -  this.ensureKeyMapInitialized_();
    -  this.invalidateCache_();
    -
    -  // TODO(chrishenry): This could be better written as
    -  // this.remove(key), this.add(key, value), but that would reorder
    -  // the key (since the key is first removed and then added at the
    -  // end) and we would have to fix unit tests that depend on key
    -  // ordering.
    -  key = this.getKeyName_(key);
    -  if (this.containsKey(key)) {
    -    this.count_ -= this.keyMap_.get(key).length;
    -  }
    -  this.keyMap_.set(key, [value]);
    -  this.count_++;
    -  return this;
    -};
    -
    -
    -/**
    - * Returns the first value associated with the key. If the query data has no
    - * such key this will return undefined or the optional default.
    - * @param {string} key The name of the parameter to get the value for.
    - * @param {*=} opt_default The default value to return if the query data
    - *     has no such key.
    - * @return {*} The first string value associated with the key, or opt_default
    - *     if there's no value.
    - */
    -goog.Uri.QueryData.prototype.get = function(key, opt_default) {
    -  var values = key ? this.getValues(key) : [];
    -  if (goog.Uri.preserveParameterTypesCompatibilityFlag) {
    -    return values.length > 0 ? values[0] : opt_default;
    -  } else {
    -    return values.length > 0 ? String(values[0]) : opt_default;
    -  }
    -};
    -
    -
    -/**
    - * Sets the values for a key. If the key already exists, this will
    - * override all of the existing values that correspond to the key.
    - * @param {string} key The key to set values for.
    - * @param {!Array<?>} values The values to set.
    - */
    -goog.Uri.QueryData.prototype.setValues = function(key, values) {
    -  this.remove(key);
    -
    -  if (values.length > 0) {
    -    this.invalidateCache_();
    -    this.keyMap_.set(this.getKeyName_(key), goog.array.clone(values));
    -    this.count_ += values.length;
    -  }
    -};
    -
    -
    -/**
    - * @return {string} Encoded query string.
    - * @override
    - */
    -goog.Uri.QueryData.prototype.toString = function() {
    -  if (this.encodedQuery_) {
    -    return this.encodedQuery_;
    -  }
    -
    -  if (!this.keyMap_) {
    -    return '';
    -  }
    -
    -  var sb = [];
    -
    -  // In the past, we use this.getKeys() and this.getVals(), but that
    -  // generates a lot of allocations as compared to simply iterating
    -  // over the keys.
    -  var keys = this.keyMap_.getKeys();
    -  for (var i = 0; i < keys.length; i++) {
    -    var key = keys[i];
    -    var encodedKey = goog.string.urlEncode(key);
    -    var val = this.getValues(key);
    -    for (var j = 0; j < val.length; j++) {
    -      var param = encodedKey;
    -      // Ensure that null and undefined are encoded into the url as
    -      // literal strings.
    -      if (val[j] !== '') {
    -        param += '=' + goog.string.urlEncode(val[j]);
    -      }
    -      sb.push(param);
    -    }
    -  }
    -
    -  return this.encodedQuery_ = sb.join('&');
    -};
    -
    -
    -/**
    - * @return {string} Decoded query string.
    - */
    -goog.Uri.QueryData.prototype.toDecodedString = function() {
    -  return goog.Uri.decodeOrEmpty_(this.toString());
    -};
    -
    -
    -/**
    - * Invalidate the cache.
    - * @private
    - */
    -goog.Uri.QueryData.prototype.invalidateCache_ = function() {
    -  this.encodedQuery_ = null;
    -};
    -
    -
    -/**
    - * Removes all keys that are not in the provided list. (Modifies this object.)
    - * @param {Array<string>} keys The desired keys.
    - * @return {!goog.Uri.QueryData} a reference to this object.
    - */
    -goog.Uri.QueryData.prototype.filterKeys = function(keys) {
    -  this.ensureKeyMapInitialized_();
    -  this.keyMap_.forEach(
    -      function(value, key) {
    -        if (!goog.array.contains(keys, key)) {
    -          this.remove(key);
    -        }
    -      }, this);
    -  return this;
    -};
    -
    -
    -/**
    - * Clone the query data instance.
    - * @return {!goog.Uri.QueryData} New instance of the QueryData object.
    - */
    -goog.Uri.QueryData.prototype.clone = function() {
    -  var rv = new goog.Uri.QueryData();
    -  rv.encodedQuery_ = this.encodedQuery_;
    -  if (this.keyMap_) {
    -    rv.keyMap_ = this.keyMap_.clone();
    -    rv.count_ = this.count_;
    -  }
    -  return rv;
    -};
    -
    -
    -/**
    - * Helper function to get the key name from a JavaScript object. Converts
    - * the object to a string, and to lower case if necessary.
    - * @private
    - * @param {*} arg The object to get a key name from.
    - * @return {string} valid key name which can be looked up in #keyMap_.
    - */
    -goog.Uri.QueryData.prototype.getKeyName_ = function(arg) {
    -  var keyName = String(arg);
    -  if (this.ignoreCase_) {
    -    keyName = keyName.toLowerCase();
    -  }
    -  return keyName;
    -};
    -
    -
    -/**
    - * Ignore case in parameter names.
    - * NOTE: If there are already key/value pairs in the QueryData, and
    - * ignoreCase_ is set to false, the keys will all be lower-cased.
    - * @param {boolean} ignoreCase whether this goog.Uri should ignore case.
    - */
    -goog.Uri.QueryData.prototype.setIgnoreCase = function(ignoreCase) {
    -  var resetKeys = ignoreCase && !this.ignoreCase_;
    -  if (resetKeys) {
    -    this.ensureKeyMapInitialized_();
    -    this.invalidateCache_();
    -    this.keyMap_.forEach(
    -        function(value, key) {
    -          var lowerCase = key.toLowerCase();
    -          if (key != lowerCase) {
    -            this.remove(key);
    -            this.setValues(lowerCase, value);
    -          }
    -        }, this);
    -  }
    -  this.ignoreCase_ = ignoreCase;
    -};
    -
    -
    -/**
    - * Extends a query data object with another query data or map like object. This
    - * operates 'in-place', it does not create a new QueryData object.
    - *
    - * @param {...(goog.Uri.QueryData|goog.structs.Map<?, ?>|Object)} var_args
    - *     The object from which key value pairs will be copied.
    - */
    -goog.Uri.QueryData.prototype.extend = function(var_args) {
    -  for (var i = 0; i < arguments.length; i++) {
    -    var data = arguments[i];
    -    goog.structs.forEach(data,
    -        /** @this {goog.Uri.QueryData} */
    -        function(value, key) {
    -          this.add(key, value);
    -        }, this);
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/uri/uri_test.html b/src/database/third_party/closure-library/closure/goog/uri/uri_test.html
    deleted file mode 100644
    index 8366d291dae..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/uri/uri_test.html
    +++ /dev/null
    @@ -1,21 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.Uri</title>
    -<script src="../base.js"></script>
    -<script>
    -goog.require('goog.UriTest');
    -</script>
    -</head>
    -<body>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/uri/uri_test.js b/src/database/third_party/closure-library/closure/goog/uri/uri_test.js
    deleted file mode 100644
    index 793c0e9b52c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/uri/uri_test.js
    +++ /dev/null
    @@ -1,1096 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Unit tests for goog.Uri.
    - *
    - */
    -
    -goog.provide('goog.UriTest');
    -
    -goog.require('goog.Uri');
    -goog.require('goog.testing.jsunit');
    -
    -goog.setTestOnly('goog.UriTest');
    -
    -function testUriParse() {
    -  var uri = new goog.Uri('http://www.google.com:80/path?q=query#fragmento');
    -  assertEquals('http', uri.getScheme());
    -  assertEquals('', uri.getUserInfo());
    -  assertEquals('www.google.com', uri.getDomain());
    -  assertEquals(80, uri.getPort());
    -  assertEquals('/path', uri.getPath());
    -  assertEquals('q=query', uri.getQuery());
    -  assertEquals('fragmento', uri.getFragment());
    -
    -  assertEquals('terer258+foo@gmail.com',
    -               goog.Uri.parse('mailto:terer258+foo@gmail.com').getPath());
    -}
    -
    -function testUriParseAcceptsThingsWithToString() {
    -  // Ensure that the goog.Uri constructor coerces random types to strings.
    -  var uriStr = 'http://www.google.com:80/path?q=query#fragmento';
    -  var uri = new goog.Uri({toString: function() { return uriStr; }});
    -  assertEquals('http://www.google.com:80/path?q=query#fragmento',
    -      uri.toString());
    -}
    -
    -function testUriCreate() {
    -  assertEquals(
    -      'http://www.google.com:81/search%20path?q=what%20to%20eat%2Bdrink%3F',
    -      goog.Uri.create('http', null, 'www.google.com', 81, '/search path',
    -          (new goog.Uri.QueryData).set('q', 'what to eat+drink?'), null)
    -      .toString());
    -
    -  assertEquals(
    -      'http://www.google.com:80/search%20path?q=what%20to%20eat%2Bdrink%3F',
    -      goog.Uri.create('http', null, 'www.google.com', 80, '/search path',
    -          (new goog.Uri.QueryData).set('q', 'what to eat+drink?'), null)
    -      .toString());
    -
    -  assertEquals(
    -      'http://www.google.com/search%20path?q=what%20to%20eat%2Bdrink%3F',
    -      goog.Uri.create('http', null, 'www.google.com', null, '/search path',
    -          (new goog.Uri.QueryData).set('q', 'what to eat+drink?'), null)
    -      .toString());
    -
    -  var createdUri = goog.Uri.create(
    -      'http', null, 'www.google.com', null, '/search path',
    -      new goog.Uri.QueryData(null, null, true).set('Q', 'what to eat+drink?'),
    -      null);
    -
    -  assertEquals('http://www.google.com/search%20path?q=what%20to%20eat%2Bdrink%3F',
    -               createdUri.toString());
    -}
    -
    -function testClone() {
    -  var uri1 = new goog.Uri(
    -      'http://user:pass@www.google.com:8080/foo?a=1&b=2#c=3');
    -  // getCount forces instantiation of internal data structures to more
    -  // thoroughly test clone.
    -  uri1.getQueryData().getCount();
    -  var uri2 = uri1.clone();
    -
    -  assertNotEquals(uri1, uri2);
    -  assertEquals(uri1.toString(), uri2.toString());
    -  assertEquals(2, uri2.getQueryData().getCount());
    -
    -  uri2.setParameterValues('q', 'bar');
    -  assertFalse(uri1.getParameterValue('q') == 'bar');
    -}
    -
    -function testRelativeUris() {
    -  assertFalse(new goog.Uri('?hello').hasPath());
    -}
    -
    -function testAbsolutePathResolution() {
    -  var uri1 = new goog.Uri('http://www.google.com:8080/path?q=query#fragmento');
    -
    -  assertEquals('http://www.google.com:8080/foo',
    -               uri1.resolve(new goog.Uri('/foo')).toString());
    -
    -  assertEquals('http://www.google.com:8080/foo/bar',
    -               goog.Uri.resolve('http://www.google.com:8080/search/',
    -                                '/foo/bar').toString());
    -}
    -
    -function testRelativePathResolution() {
    -  var uri1 = new goog.Uri('http://www.google.com:8080/path?q=query#fragmento');
    -  assertEquals('http://www.google.com:8080/foo',
    -               uri1.resolve(goog.Uri.parse('foo')).toString());
    -
    -  var uri2 = new goog.Uri('http://www.google.com:8080/search');
    -  assertEquals('http://www.google.com:8080/foo/bar',
    -               uri2.resolve(new goog.Uri('foo/bar')).toString());
    -
    -  var uri3 = new goog.Uri('http://www.google.com:8080/search/');
    -  assertEquals('http://www.google.com:8080/search/foo/bar',
    -               uri3.resolve(new goog.Uri('foo/bar')).toString());
    -
    -  var uri4 = new goog.Uri('foo');
    -  assertEquals('bar',
    -               uri4.resolve(new goog.Uri('bar')).toString());
    -
    -  var uri5 = new goog.Uri('http://www.google.com:8080/search/');
    -  assertEquals('http://www.google.com:8080/search/..%2ffoo/bar',
    -               uri3.resolve(new goog.Uri('..%2ffoo/bar')).toString());
    -
    -}
    -
    -function testDomainResolution() {
    -  assertEquals('https://www.google.com/foo/bar',
    -               new goog.Uri('https://www.fark.com:443/search/').resolve(
    -                   new goog.Uri('//www.google.com/foo/bar')
    -               ).toString());
    -
    -  assertEquals('http://www.google.com/',
    -               goog.Uri.resolve('http://www.fark.com/search/',
    -                                '//www.google.com/').toString());
    -}
    -
    -function testQueryResolution() {
    -  assertEquals('http://www.google.com/search?q=new%20search',
    -               goog.Uri.parse('http://www.google.com/search?q=old+search').
    -                   resolve(goog.Uri.parse('?q=new%20search')).toString());
    -
    -  assertEquals('http://www.google.com/search?q=new%20search',
    -               goog.Uri.parse('http://www.google.com/search?q=old+search#hi').
    -                   resolve(goog.Uri.parse('?q=new%20search')).toString());
    -}
    -
    -function testFragmentResolution() {
    -  assertEquals('http://www.google.com/foo/bar?q=hi#there',
    -               goog.Uri.resolve('http://www.google.com/foo/bar?q=hi',
    -                                '#there').toString());
    -
    -  assertEquals('http://www.google.com/foo/bar?q=hi#there',
    -               goog.Uri.resolve('http://www.google.com/foo/bar?q=hi#you',
    -                                '#there').toString());
    -}
    -
    -function testBogusResolution() {
    -  var uri = goog.Uri.parse('some:base/url').resolve(
    -      goog.Uri.parse('a://completely.different/url'));
    -  assertEquals('a://completely.different/url', uri.toString());
    -}
    -
    -function testDotSegmentsRemovalRemoveLeadingDots() {
    -  // Test removing leading "../" and "./"
    -  assertEquals('bar', goog.Uri.removeDotSegments('../bar'));
    -  assertEquals('bar', goog.Uri.removeDotSegments('./bar'));
    -  assertEquals('bar', goog.Uri.removeDotSegments('.././bar'));
    -  assertEquals('bar', goog.Uri.removeDotSegments('.././bar'));
    -}
    -
    -function testDotSegmentRemovalRemoveSingleDot() {
    -  // Tests replacing "/./" with "/"
    -  assertEquals('/foo/bar', goog.Uri.removeDotSegments('/foo/./bar'));
    -  assertEquals('/bar/', goog.Uri.removeDotSegments('/bar/./'));
    -
    -  // Test replacing trailing "/." with "/"
    -  assertEquals('/', goog.Uri.removeDotSegments('/.'));
    -  assertEquals('/bar/', goog.Uri.removeDotSegments('/bar/.'));
    -}
    -
    -function testDotSegmentRemovalRemoveDoubleDot() {
    -  // Test resolving "/../"
    -  assertEquals('/bar', goog.Uri.removeDotSegments('/foo/../bar'));
    -  assertEquals('/', goog.Uri.removeDotSegments('/bar/../'));
    -
    -  // Test resolving trailing "/.."
    -  assertEquals('/', goog.Uri.removeDotSegments('/..'));
    -  assertEquals('/', goog.Uri.removeDotSegments('/bar/..'));
    -  assertEquals('/foo/', goog.Uri.removeDotSegments('/foo/bar/..'));
    -}
    -
    -function testDotSegmentRemovalRemovePlainDots() {
    -  // RFC 3986, section 5.2.4, point 2.D.
    -  // Test resolving plain ".." or "."
    -  assertEquals('', goog.Uri.removeDotSegments('.'));
    -  assertEquals('', goog.Uri.removeDotSegments('..'));
    -}
    -
    -function testPathConcatenation() {
    -  // Check accordenance with RFC 3986, section 5.2.4
    -  assertResolvedEquals('bar', '', 'bar');
    -  assertResolvedEquals('/bar', '/', 'bar');
    -  assertResolvedEquals('/bar', '/foo', '/bar');
    -  assertResolvedEquals('/foo/foo', '/foo/bar', 'foo');
    -}
    -
    -function testPathConcatenationDontRemoveForEmptyUri() {
    -  // Resolving URIs with empty path should not result in dot segments removal.
    -  // See: algorithm in section 5.2.2: code inside 'if (R.path == "")' clause.
    -  assertResolvedEquals('/search/../foo', '/search/../foo', '');
    -  assertResolvedEquals('/search/./foo', '/search/./foo', '');
    -}
    -
    -
    -function testParameterGetters() {
    -  function assertArraysEqual(l1, l2) {
    -    if (!l1 || !l2) {
    -      assertEquals(l1, l2);
    -      return;
    -    }
    -    var l1s = l1.toString(), l2s = l2.toString();
    -    assertEquals(l1s, l2s);
    -    assertEquals(l1s, l1.length, l2.length);
    -    for (var i = 0; i < l1.length; ++i) {
    -      assertEquals('part ' + i + ' of ' + l1.length + ' in ' + l1s,
    -                   l1[i], l2[i]);
    -    }
    -  }
    -
    -  assertArraysEqual(['v1', 'v2'],
    -      goog.Uri.parse('/path?a=b&key=v1&c=d&key=v2&keywithsuffix=v3').
    -          getParameterValues('key'));
    -
    -  assertArraysEqual(['v1', 'v2'],
    -      goog.Uri.parse('/path?a=b&keY=v1&c=d&KEy=v2&keywithsuffix=v3', true).
    -          getParameterValues('kEy'));
    -
    -  assertEquals('v1',
    -      goog.Uri.parse('/path?key=v1&c=d&keywithsuffix=v3&key=v2').
    -          getParameterValue('key'));
    -
    -  assertEquals('v1',
    -      goog.Uri.parse('/path?kEY=v1&c=d&keywithsuffix=v3&key=v2', true).
    -          getParameterValue('Key'));
    -
    -  assertEquals('v1=v2',
    -      goog.Uri.parse('/path?key=v1=v2', true).getParameterValue('key'));
    -
    -  assertEquals('v1=v2=v3',
    -      goog.Uri.parse('/path?key=v1=v2=v3', true).getParameterValue('key'));
    -
    -  assertArraysEqual(undefined,
    -                    goog.Uri.parse('/path?key=v1&c=d&keywithsuffix=v3&key=v2').
    -                    getParameterValue('nosuchkey'));
    -
    -  // test boundary conditions
    -  assertArraysEqual(['v1', 'v2'],
    -      goog.Uri.parse('/path?key=v1&c=d&key=v2&keywithsuffix=v3').
    -          getParameterValues('key'));
    -  assertArraysEqual(['v1', 'v2'],
    -      goog.Uri.parse('/path?key=v1&c=d&keywithsuffix=v3&key=v2').
    -          getParameterValues('key'));
    -
    -  // test no =
    -  assertArraysEqual([''],
    -      goog.Uri.parse('/path?key').getParameterValues('key'));
    -  assertArraysEqual([''],
    -      goog.Uri.parse('/path?key', true).getParameterValues('key'));
    -
    -  assertArraysEqual([''],
    -                    goog.Uri.parse('/path?foo=bar&key').
    -                    getParameterValues('key'));
    -  assertArraysEqual([''],
    -                    goog.Uri.parse('/path?foo=bar&key', true).
    -                    getParameterValues('key'));
    -
    -  assertEquals('',
    -               goog.Uri.parse('/path?key').getParameterValue('key'));
    -  assertEquals('',
    -               goog.Uri.parse('/path?key', true).getParameterValue('key'));
    -
    -  assertEquals('',
    -               goog.Uri.parse('/path?foo=bar&key').getParameterValue('key'));
    -  assertEquals('',
    -               goog.Uri.parse('/path?foo=bar&key', true).
    -               getParameterValue('key'));
    -
    -  var u = new goog.Uri('/path?a=b&key=v1&c=d&key=v2&keywithsuffix=v3');
    -  assertArraysEqual(u.getParameterValues('a'), ['b']);
    -  assertArraysEqual(u.getParameterValues('key'), ['v1', 'v2']);
    -  assertArraysEqual(u.getParameterValues('c'), ['d']);
    -  assertArraysEqual(u.getParameterValues('keywithsuffix'), ['v3']);
    -  assertArraysEqual(u.getParameterValues('KeyWITHSuffix'), []);
    -
    -  // Make sure constructing from another URI preserves case-sensitivity
    -  var u2 = new goog.Uri(u);
    -  assertArraysEqual(u2.getParameterValues('a'), ['b']);
    -  assertArraysEqual(u2.getParameterValues('key'), ['v1', 'v2']);
    -  assertArraysEqual(u2.getParameterValues('c'), ['d']);
    -  assertArraysEqual(u2.getParameterValues('keywithsuffix'), ['v3']);
    -  assertArraysEqual(u2.getParameterValues('KeyWITHSuffix'), []);
    -
    -  u = new goog.Uri('/path?a=b&key=v1&c=d&kEy=v2&keywithsuffix=v3', true);
    -  assertArraysEqual(u.getParameterValues('A'), ['b']);
    -  assertArraysEqual(u.getParameterValues('keY'), ['v1', 'v2']);
    -  assertArraysEqual(u.getParameterValues('c'), ['d']);
    -  assertArraysEqual(u.getParameterValues('keyWITHsuffix'), ['v3']);
    -
    -  // Make sure constructing from another URI preserves case-insensitivity
    -  u2 = new goog.Uri(u);
    -  assertArraysEqual(u2.getParameterValues('A'), ['b']);
    -  assertArraysEqual(u2.getParameterValues('keY'), ['v1', 'v2']);
    -  assertArraysEqual(u2.getParameterValues('c'), ['d']);
    -  assertArraysEqual(u2.getParameterValues('keyWITHsuffix'), ['v3']);
    -}
    -
    -function testRemoveParameter() {
    -  assertEquals('/path?a=b&c=d&keywithsuffix=v3',
    -               goog.Uri.parse('/path?a=b&key=v1&c=d&key=v2&keywithsuffix=v3')
    -               .removeParameter('key').toString());
    -}
    -
    -function testParameterSetters() {
    -  assertEquals('/path?a=b&key=newval&c=d&keywithsuffix=v3',
    -               goog.Uri.parse('/path?a=b&key=v1&c=d&key=v2&keywithsuffix=v3')
    -               .setParameterValue('key', 'newval').toString());
    -
    -  assertEquals('/path?a=b&key=1&key=2&key=3&c=d&keywithsuffix=v3',
    -               goog.Uri.parse('/path?a=b&key=v1&c=d&key=v2&keywithsuffix=v3')
    -               .setParameterValues('key', ['1', '2', '3']).toString());
    -
    -  assertEquals('/path',
    -      goog.Uri.parse('/path?key=v1&key=v2')
    -          .setParameterValues('key', []).toString());
    -
    -  // Test case-insensitive setters
    -  assertEquals('/path?a=b&key=newval&c=d&keywithsuffix=v3',
    -      goog.Uri.parse('/path?a=b&key=v1&c=d&key=v2&keywithsuffix=v3', true)
    -               .setParameterValue('KEY', 'newval').toString());
    -
    -  assertEquals(
    -      '/path?a=b&key=1&key=2&key=3&c=d&keywithsuffix=v3',
    -      goog.Uri.parse('/path?a=b&key=v1&c=d&key=v2&keywithsuffix=v3', true)
    -          .setParameterValues('kEY', ['1', '2', '3']).toString());
    -}
    -
    -function testEncoding() {
    -  assertEquals('/foo bar baz',
    -               goog.Uri.parse('/foo%20bar%20baz').getPath());
    -  assertEquals('/foo+bar+baz',
    -               goog.Uri.parse('/foo+bar+baz').getPath());
    -}
    -
    -function testSetScheme() {
    -  var uri = new goog.Uri('http://www.google.com:80/path?q=query#fragmento');
    -
    -  uri.setScheme('https');
    -  assertTrue(uri.hasScheme());
    -  assertEquals('https', uri.getScheme());
    -  assertEquals('https://www.google.com:80/path?q=query#fragmento',
    -               uri.toString());
    -
    -  uri.setScheme(encodeURIComponent('ab cd'), true);
    -  assertTrue(uri.hasScheme());
    -  assertEquals('ab cd', uri.getScheme());
    -  assertEquals('ab%20cd://www.google.com:80/path?q=query#fragmento',
    -               uri.toString());
    -
    -  uri.setScheme('http:');
    -  assertTrue(uri.hasScheme());
    -  assertEquals('http', uri.getScheme());
    -  assertEquals('http://www.google.com:80/path?q=query#fragmento',
    -               uri.toString());
    -
    -  uri.setScheme('');
    -  assertFalse(uri.hasScheme());
    -  assertEquals('', uri.getScheme());
    -  assertEquals('//www.google.com:80/path?q=query#fragmento',
    -               uri.toString());
    -}
    -
    -function testSetDomain() {
    -  var uri = new goog.Uri('http://www.google.com:80/path?q=query#fragmento');
    -
    -  uri.setDomain('\u1e21oogle.com');
    -  assertTrue(uri.hasDomain());
    -  assertEquals('\u1e21oogle.com', uri.getDomain());
    -  assertEquals('http://%E1%B8%A1oogle.com:80/path?q=query#fragmento',
    -               uri.toString());
    -
    -  uri.setDomain(encodeURIComponent('\u1e21oogle.com'), true);
    -  assertTrue(uri.hasDomain());
    -  assertEquals('\u1e21oogle.com', uri.getDomain());
    -  assertEquals('http://%E1%B8%A1oogle.com:80/path?q=query#fragmento',
    -               uri.toString());
    -
    -  uri.setDomain('');
    -  assertFalse(uri.hasDomain());
    -  assertEquals('', uri.getDomain());
    -  assertEquals('http:/path?q=query#fragmento',
    -               uri.toString());
    -}
    -
    -function testSetPort() {
    -  var uri = new goog.Uri('http://www.google.com:80/path?q=query#fragmento');
    -
    -  assertThrows(function() {
    -    uri.setPort(-1);
    -  });
    -  assertEquals(80, uri.getPort());
    -
    -  assertThrows(function() {
    -    uri.setPort('a');
    -  });
    -  assertEquals(80, uri.getPort());
    -
    -  uri.setPort(443);
    -  assertTrue(uri.hasPort());
    -  assertEquals(443, uri.getPort());
    -  assertEquals('http://www.google.com:443/path?q=query#fragmento',
    -               uri.toString());
    -
    -  // TODO(chrishenry): This is undocumented, but exist in previous unit
    -  // test. We should clarify whether this is intended (alternatively,
    -  // setPort(0) also works).
    -  uri.setPort(null);
    -  assertFalse(uri.hasPort());
    -  assertEquals(null, uri.getPort());
    -  assertEquals('http://www.google.com/path?q=query#fragmento',
    -               uri.toString());
    -}
    -
    -function testSetPath() {
    -  var uri = new goog.Uri('http://www.google.com:80/path?q=query#fragmento');
    -
    -  uri.setPath('/search path/');
    -  assertTrue(uri.hasPath());
    -  assertEquals('/search path/', uri.getPath());
    -  assertEquals(
    -      'http://www.google.com:80/search%20path/?q=query#fragmento',
    -      uri.toString());
    -
    -  uri.setPath(encodeURIComponent('search path 2/'), true);
    -  assertTrue(uri.hasPath());
    -  assertEquals('search path 2%2F', uri.getPath());
    -  assertEquals(
    -      'http://www.google.com:80/search%20path%202%2F?q=query#fragmento',
    -      uri.toString());
    -
    -  uri.setPath('');
    -  assertFalse(uri.hasPath());
    -  assertEquals('', uri.getPath());
    -  assertEquals(
    -      'http://www.google.com:80?q=query#fragmento',
    -      uri.toString());
    -}
    -
    -function testSetFragment() {
    -  var uri = new goog.Uri('http://www.google.com:80/path?q=query#fragmento');
    -
    -  uri.setFragment('foo?bar=a b&baz=2');
    -  assertTrue(uri.hasFragment());
    -  assertEquals('foo?bar=a b&baz=2', uri.getFragment());
    -  assertEquals(
    -      'http://www.google.com:80/path?q=query#foo?bar=a%20b&baz=2',
    -      uri.toString());
    -
    -  uri.setFragment(encodeURIComponent('foo?bar=a b&baz=3'), true);
    -  assertTrue(uri.hasFragment());
    -  assertEquals('foo?bar=a b&baz=3', uri.getFragment());
    -  assertEquals(
    -      'http://www.google.com:80/path?q=query#foo?bar=a%20b&baz=3',
    -      uri.toString());
    -
    -  uri.setFragment('');
    -  assertFalse(uri.hasFragment());
    -  assertEquals('', uri.getFragment());
    -  assertEquals(
    -      'http://www.google.com:80/path?q=query',
    -      uri.toString());
    -}
    -
    -function testSetUserInfo() {
    -  var uri = new goog.Uri('http://www.google.com:80/path?q=query#fragmento');
    -
    -  uri.setUserInfo('user:pw d');
    -  assertTrue(uri.hasUserInfo());
    -  assertEquals('user:pw d', uri.getUserInfo());
    -  assertEquals('http://user:pw%20d@www.google.com:80/path?q=query#fragmento',
    -      uri.toString());
    -
    -  uri.setUserInfo(encodeURIComponent('user:pw d2'), true);
    -  assertTrue(uri.hasUserInfo());
    -  assertEquals('user:pw d2', uri.getUserInfo());
    -  assertEquals('http://user:pw%20d2@www.google.com:80/path?q=query#fragmento',
    -      uri.toString());
    -
    -  uri.setUserInfo('user');
    -  assertTrue(uri.hasUserInfo());
    -  assertEquals('user', uri.getUserInfo());
    -  assertEquals('http://user@www.google.com:80/path?q=query#fragmento',
    -      uri.toString());
    -
    -  uri.setUserInfo('');
    -  assertFalse(uri.hasUserInfo());
    -  assertEquals('', uri.getUserInfo());
    -  assertEquals('http://www.google.com:80/path?q=query#fragmento',
    -      uri.toString());
    -}
    -
    -function testSetParameterValues() {
    -  var uri = new goog.Uri('http://www.google.com:80/path?q=query#fragmento');
    -
    -  uri.setParameterValues('q', ['foo', 'other query']);
    -  assertEquals('http://www.google.com:80/path?q=foo&q=other%20query#fragmento',
    -      uri.toString());
    -
    -  uri.setParameterValues('lang', 'en');
    -  assertEquals(
    -      'http://www.google.com:80/path?q=foo&q=other%20query&lang=en#fragmento',
    -      uri.toString());
    -}
    -
    -function testTreatmentOfAt1() {
    -  var uri = new goog.Uri('http://www.google.com?q=johndoe@gmail.com');
    -  assertEquals('http', uri.getScheme());
    -  assertEquals('www.google.com', uri.getDomain());
    -  assertEquals('johndoe@gmail.com', uri.getParameterValue('q'));
    -
    -  uri = goog.Uri.create('http', null, 'www.google.com', null, null,
    -                        'q=johndoe@gmail.com', null);
    -  assertEquals('http://www.google.com?q=johndoe%40gmail.com', uri.toString());
    -}
    -
    -function testTreatmentOfAt2() {
    -  var uri = new goog.Uri('http://www/~johndoe@gmail.com/foo');
    -  assertEquals('http', uri.getScheme());
    -  assertEquals('www', uri.getDomain());
    -  assertEquals('/~johndoe@gmail.com/foo', uri.getPath());
    -
    -  assertEquals('http://www/~johndoe@gmail.com/foo',
    -               goog.Uri.create('http', null, 'www', null,
    -                               '/~johndoe@gmail.com/foo', null, null).
    -               toString());
    -}
    -
    -function testTreatmentOfAt3() {
    -  var uri = new goog.Uri('ftp://skroob:1234@teleport/~skroob@vacuum');
    -  assertEquals('ftp', uri.getScheme());
    -  assertEquals('skroob:1234', uri.getUserInfo());
    -  assertEquals('teleport', uri.getDomain());
    -  assertEquals('/~skroob@vacuum', uri.getPath());
    -
    -  assertEquals('ftp://skroob:1234@teleport/~skroob@vacuum',
    -               goog.Uri.create('ftp', 'skroob:1234', 'teleport', null,
    -                               '/~skroob@vacuum', null, null).toString());
    -}
    -
    -function testTreatmentOfAt4() {
    -  assertEquals('ftp://darkhelmet:45%4078@teleport/~dhelmet@vacuum',
    -               goog.Uri.create('ftp', 'darkhelmet:45@78', 'teleport', null,
    -                               '/~dhelmet@vacuum', null, null).toString());
    -}
    -
    -function testSameDomain1() {
    -  var uri1 = 'http://www.google.com/a';
    -  var uri2 = 'http://www.google.com/b';
    -  assertTrue(goog.Uri.haveSameDomain(uri1, uri2));
    -  assertTrue(goog.Uri.haveSameDomain(uri2, uri1));
    -}
    -
    -function testSameDomain2() {
    -  var uri1 = 'http://www.google.com:1234/a';
    -  var uri2 = 'http://www.google.com/b';
    -  assertFalse(goog.Uri.haveSameDomain(uri1, uri2));
    -  assertFalse(goog.Uri.haveSameDomain(uri2, uri1));
    -}
    -
    -function testSameDomain3() {
    -  var uri1 = 'www.google.com/a';
    -  var uri2 = 'http://www.google.com/b';
    -  assertFalse(goog.Uri.haveSameDomain(uri1, uri2));
    -  assertFalse(goog.Uri.haveSameDomain(uri2, uri1));
    -}
    -
    -function testSameDomain4() {
    -  var uri1 = '/a';
    -  var uri2 = 'http://www.google.com/b';
    -  assertFalse(goog.Uri.haveSameDomain(uri1, uri2));
    -  assertFalse(goog.Uri.haveSameDomain(uri2, uri1));
    -}
    -
    -function testSameDomain5() {
    -  var uri1 = 'http://www.google.com/a';
    -  var uri2 = 'http://mail.google.com/b';
    -  assertFalse(goog.Uri.haveSameDomain(uri1, uri2));
    -  assertFalse(goog.Uri.haveSameDomain(uri2, uri1));
    -}
    -
    -function testSameDomain6() {
    -  var uri1 = '/a';
    -  var uri2 = '/b';
    -  assertTrue(goog.Uri.haveSameDomain(uri1, uri2));
    -  assertTrue(goog.Uri.haveSameDomain(uri2, uri1));
    -}
    -
    -function testMakeUnique() {
    -  var uri1 = new goog.Uri('http://www.google.com/setgmail');
    -  uri1.makeUnique();
    -  var uri2 = new goog.Uri('http://www.google.com/setgmail');
    -  uri2.makeUnique();
    -  assertTrue(uri1.getQueryData().containsKey(goog.Uri.RANDOM_PARAM));
    -  assertTrue(uri1.toString() != uri2.toString());
    -}
    -
    -function testSetReadOnly() {
    -  var uri = new goog.Uri('http://www.google.com/setgmail');
    -  uri.setReadOnly(true);
    -  assertThrows(function() {
    -    uri.setParameterValue('cant', 'dothis');
    -  });
    -}
    -
    -function testSetReadOnlyChained() {
    -  var uri = new goog.Uri('http://www.google.com/setgmail').setReadOnly(true);
    -  assertThrows(function() {
    -    uri.setParameterValue('cant', 'dothis');
    -  });
    -}
    -
    -function testQueryDataCount() {
    -  var qd = new goog.Uri.QueryData('a=A&b=B&a=A2&b=B2&c=C');
    -  assertEquals(5, qd.getCount());
    -}
    -
    -function testQueryDataRemove() {
    -  var qd = new goog.Uri.QueryData('a=A&b=B&a=A2&b=B2&c=C');
    -  qd.remove('c');
    -  assertEquals(4, qd.getCount());
    -  assertEquals('a=A&a=A2&b=B&b=B2', String(qd));
    -  qd.remove('a');
    -  assertEquals(2, qd.getCount());
    -  assertEquals('b=B&b=B2', String(qd));
    -}
    -
    -function testQueryDataClear() {
    -  var qd = new goog.Uri.QueryData('a=A&b=B&a=A2&b=B2&c=C');
    -  qd.clear();
    -  assertEquals(0, qd.getCount());
    -  assertEquals('', String(qd));
    -}
    -
    -function testQueryDataIsEmpty() {
    -  var qd = new goog.Uri.QueryData('a=A&b=B&a=A2&b=B2&c=C');
    -  qd.remove('a');
    -  assertFalse(qd.isEmpty());
    -  qd.remove('b');
    -  assertFalse(qd.isEmpty());
    -  qd.remove('c');
    -  assertTrue(qd.isEmpty());
    -
    -  qd = new goog.Uri.QueryData('a=A&b=B&a=A2&b=B2&c=C');
    -  qd.clear();
    -  assertTrue(qd.isEmpty());
    -
    -  qd = new goog.Uri.QueryData('');
    -  assertTrue(qd.isEmpty());
    -}
    -
    -function testQueryDataContainsKey() {
    -  var qd = new goog.Uri.QueryData('a=A&b=B&a=A2&b=B2&c=C');
    -  assertTrue(qd.containsKey('a'));
    -  assertTrue(qd.containsKey('b'));
    -  assertTrue(qd.containsKey('c'));
    -  qd.remove('a');
    -  assertFalse(qd.containsKey('a'));
    -  assertTrue(qd.containsKey('b'));
    -  assertTrue(qd.containsKey('c'));
    -  qd.remove('b');
    -  assertFalse(qd.containsKey('a'));
    -  assertFalse(qd.containsKey('b'));
    -  assertTrue(qd.containsKey('c'));
    -  qd.remove('c');
    -  assertFalse(qd.containsKey('a'));
    -  assertFalse(qd.containsKey('b'));
    -  assertFalse(qd.containsKey('c'));
    -
    -  qd = new goog.Uri.QueryData('a=A&b=B&a=A2&b=B2&c=C');
    -  qd.clear();
    -  assertFalse(qd.containsKey('a'));
    -  assertFalse(qd.containsKey('b'));
    -  assertFalse(qd.containsKey('c'));
    -
    -  // Test case-insensitive
    -  qd = new goog.Uri.QueryData('aaa=A&bbb=B&aaa=A2&bbbb=B2&ccc=C', null, true);
    -  assertTrue(qd.containsKey('aaa'));
    -  assertTrue(qd.containsKey('bBb'));
    -  assertTrue(qd.containsKey('CCC'));
    -
    -  qd = new goog.Uri.QueryData('a=b=c');
    -  assertTrue(qd.containsKey('a'));
    -  assertFalse(qd.containsKey('b'));
    -}
    -
    -function testQueryDataContainsValue() {
    -  var qd = new goog.Uri.QueryData('a=A&b=B&a=A2&b=B2&c=C');
    -
    -  assertTrue(qd.containsValue('A'));
    -  assertTrue(qd.containsValue('B'));
    -  assertTrue(qd.containsValue('A2'));
    -  assertTrue(qd.containsValue('B2'));
    -  assertTrue(qd.containsValue('C'));
    -  qd.remove('a');
    -  assertFalse(qd.containsValue('A'));
    -  assertTrue(qd.containsValue('B'));
    -  assertFalse(qd.containsValue('A2'));
    -  assertTrue(qd.containsValue('B2'));
    -  assertTrue(qd.containsValue('C'));
    -  qd.remove('b');
    -  assertFalse(qd.containsValue('A'));
    -  assertFalse(qd.containsValue('B'));
    -  assertFalse(qd.containsValue('A2'));
    -  assertFalse(qd.containsValue('B2'));
    -  assertTrue(qd.containsValue('C'));
    -  qd.remove('c');
    -  assertFalse(qd.containsValue('A'));
    -  assertFalse(qd.containsValue('B'));
    -  assertFalse(qd.containsValue('A2'));
    -  assertFalse(qd.containsValue('B2'));
    -  assertFalse(qd.containsValue('C'));
    -
    -  qd = new goog.Uri.QueryData('a=A&b=B&a=A2&b=B2&c=C');
    -  qd.clear();
    -  assertFalse(qd.containsValue('A'));
    -  assertFalse(qd.containsValue('B'));
    -  assertFalse(qd.containsValue('A2'));
    -  assertFalse(qd.containsValue('B2'));
    -  assertFalse(qd.containsValue('C'));
    -
    -  qd = new goog.Uri.QueryData('a=b=c');
    -  assertTrue(qd.containsValue('b=c'));
    -  assertFalse(qd.containsValue('b'));
    -  assertFalse(qd.containsValue('c'));
    -}
    -
    -function testQueryDataGetKeys() {
    -  var qd = new goog.Uri.QueryData('a=A&b=B&a=A2&b=B2&c=C=extra');
    -
    -  assertEquals('aabbc', qd.getKeys().join(''));
    -  qd.remove('a');
    -  assertEquals('bbc', qd.getKeys().join(''));
    -  qd.add('d', 'D');
    -  qd.add('d', 'D');
    -  assertEquals('bbcdd', qd.getKeys().join(''));
    -
    -  // Test case-insensitive
    -  qd = new goog.Uri.QueryData('A=A&B=B&a=A2&b=B2&C=C=extra', null, true);
    -
    -  assertEquals('aabbc', qd.getKeys().join(''));
    -  qd.remove('a');
    -  assertEquals('bbc', qd.getKeys().join(''));
    -  qd.add('d', 'D');
    -  qd.add('D', 'D');
    -  assertEquals('bbcdd', qd.getKeys().join(''));
    -}
    -
    -function testQueryDataGetValues() {
    -  var qd = new goog.Uri.QueryData('a=A&b=B&a=A2&b=B2&c=C=extra');
    -
    -  assertArrayEquals(['A', 'A2', 'B', 'B2', 'C=extra'], qd.getValues());
    -  qd.remove('a');
    -  assertArrayEquals(['B', 'B2', 'C=extra'], qd.getValues());
    -  qd.add('d', 'D');
    -  qd.add('d', 'D');
    -  assertArrayEquals(['B', 'B2', 'C=extra', 'D', 'D'], qd.getValues());
    -
    -  qd.add('e', new String('Eee'));
    -  assertArrayEquals(['B', 'B2', 'C=extra', 'D', 'D', 'Eee'], qd.getValues());
    -
    -  assertArrayEquals(['Eee'], qd.getValues('e'));
    -}
    -
    -function testQueryDataSet() {
    -  var qd = new goog.Uri.QueryData('a=A&b=B&a=A2&b=B2&c=C');
    -
    -  qd.set('d', 'D');
    -  assertEquals('a=A&a=A2&b=B&b=B2&c=C&d=D', String(qd));
    -  qd.set('d', 'D2');
    -  assertEquals('a=A&a=A2&b=B&b=B2&c=C&d=D2', String(qd));
    -  qd.set('a', 'A3');
    -  assertEquals('a=A3&b=B&b=B2&c=C&d=D2', String(qd));
    -  qd.remove('a');
    -  qd.set('a', 'A4');
    -  // this is different in IE and Mozilla so we cannot use the toString to test
    -  assertEquals('A4', qd.get('a'));
    -}
    -
    -function testQueryDataGet() {
    -  var qd = new goog.Uri.QueryData('a=A&b=B&a=A2&b=B2&c=C=extra');
    -
    -  assertEquals('A', qd.get('a'));
    -  assertEquals('B', qd.get('b'));
    -  assertEquals('C=extra', qd.get('c'));
    -  assertEquals('Default', qd.get('d', 'Default'));
    -
    -  qd = new goog.Uri.QueryData('a=A&b=B&a=A2&b=B2&c=C=extra', null, true);
    -
    -  assertEquals('A', qd.get('A'));
    -  assertEquals('B', qd.get('b'));
    -  assertEquals('C=extra', qd.get('C'));
    -  assertEquals('Default', qd.get('D', 'Default'));
    -
    -  // Some unit tests pass undefined to get method (even though the type
    -  // for key is {string}). This is not caught by JsCompiler as
    -  // tests aren't typically compiled.
    -  assertUndefined(qd.get(undefined));
    -}
    -
    -
    -function testQueryDataSetValues() {
    -  var qd = new goog.Uri.QueryData('a=A&b=B&a=A2&b=B2&c=C');
    -
    -  qd.setValues('a', ['A3', 'A4', 'A5']);
    -  assertEquals('a=A3&a=A4&a=A5&b=B&b=B2&c=C', String(qd));
    -  qd.setValues('d', ['D']);
    -  assertEquals('a=A3&a=A4&a=A5&b=B&b=B2&c=C&d=D', String(qd));
    -  qd.setValues('e', []);
    -  assertEquals('a=A3&a=A4&a=A5&b=B&b=B2&c=C&d=D', String(qd));
    -}
    -
    -function testQueryDataSetIgnoreCase() {
    -  var qd = new goog.Uri.QueryData('aaA=one&BBb=two&cCc=three');
    -  assertEquals('one', qd.get('aaA'));
    -  assertEquals(undefined, qd.get('aaa'));
    -  qd.setIgnoreCase(true);
    -  assertEquals('one', qd.get('aaA'));
    -  assertEquals('one', qd.get('aaa'));
    -  qd.setIgnoreCase(false);
    -  assertEquals(undefined, qd.get('aaA'));
    -  assertEquals('one', qd.get('aaa'));
    -  qd.add('DdD', 'four');
    -  assertEquals('four', qd.get('DdD'));
    -  assertEquals(undefined, qd.get('ddd'));
    -}
    -
    -function testQueryDataSetIgnoreCaseWithMultipleValues() {
    -  var qd = new goog.Uri.QueryData('aaA=one&aaA=two');
    -  qd.setIgnoreCase(true);
    -  assertArrayEquals(['one', 'two'], qd.getValues('aaA'));
    -  assertArrayEquals(['one', 'two'], qd.getValues('aaa'));
    -}
    -
    -function testQueryDataExtend() {
    -  var qd1 = new goog.Uri.QueryData('a=A&b=B&c=C');
    -  var qd2 = new goog.Uri.QueryData('d=D&e=E');
    -  qd1.extend(qd2);
    -  assertEquals('a=A&b=B&c=C&d=D&e=E', String(qd1));
    -
    -  qd1 = new goog.Uri.QueryData('a=A&b=B&c=C');
    -  qd2 = new goog.Uri.QueryData('d=D&e=E');
    -  var qd3 = new goog.Uri.QueryData('f=F&g=G');
    -  qd1.extend(qd2, qd3);
    -  assertEquals('a=A&b=B&c=C&d=D&e=E&f=F&g=G', String(qd1));
    -
    -  qd1 = new goog.Uri.QueryData('a=A&b=B&c=C');
    -  qd2 = new goog.Uri.QueryData('a=A&c=C');
    -  qd1.extend(qd2);
    -  assertEquals('a=A&a=A&b=B&c=C&c=C', String(qd1));
    -}
    -
    -function testQueryDataCreateFromMap() {
    -  assertEquals('', String(goog.Uri.QueryData.createFromMap({})));
    -  assertEquals('a=A&b=B&c=C',
    -      String(goog.Uri.QueryData.createFromMap({a: 'A', b: 'B', c: 'C'})));
    -  assertEquals('a=foo%26bar',
    -      String(goog.Uri.QueryData.createFromMap({a: 'foo&bar'})));
    -}
    -
    -function testQueryDataCreateFromMapWithArrayValues() {
    -  var obj = {'key': ['1', '2', '3']};
    -  var qd = goog.Uri.QueryData.createFromMap(obj);
    -  assertEquals('key=1&key=2&key=3', qd.toString());
    -  qd.add('breakCache', 1);
    -  obj.key.push('4');
    -  assertEquals('key=1&key=2&key=3&breakCache=1', qd.toString());
    -
    -}
    -
    -function testQueryDataCreateFromKeysValues() {
    -  assertEquals('', String(goog.Uri.QueryData.createFromKeysValues([], [])));
    -  assertEquals('a=A&b=B&c=C', String(goog.Uri.QueryData.createFromKeysValues(
    -      ['a', 'b', 'c'], ['A', 'B', 'C'])));
    -  assertEquals('a=A&a=B&a=C', String(goog.Uri.QueryData.createFromKeysValues(
    -      ['a', 'a', 'a'], ['A', 'B', 'C'])));
    -}
    -
    -function testQueryDataAddMultipleValuesWithSameKey() {
    -  var qd = new goog.Uri.QueryData();
    -  qd.add('abc', 'v');
    -  qd.add('abc', 'v2');
    -  qd.add('abc', 'v3');
    -  assertEquals('abc=v&abc=v2&abc=v3', qd.toString());
    -}
    -
    -function testQueryDataAddWithArray() {
    -  var qd = new goog.Uri.QueryData();
    -  qd.add('abc', ['v', 'v2']);
    -  assertEquals('abc=v%2Cv2', qd.toString());
    -}
    -
    -function testFragmentEncoding() {
    -  var allowedInFragment = /[A-Za-z0-9\-\._~!$&'()*+,;=:@/?]/g;
    -
    -  var sb = [];
    -  for (var i = 33; i < 500; i++) {  // arbitrarily use first 500 chars.
    -    sb.push(String.fromCharCode(i));
    -  }
    -  var testString = sb.join('');
    -
    -  var fragment = new goog.Uri().setFragment(testString).toString();
    -
    -  // Remove first '#' character.
    -  fragment = fragment.substr(1);
    -
    -  // Strip all percent encoded characters, as they're ok.
    -  fragment = fragment.replace(/%[0-9A-F][0-9A-F]/g, '');
    -
    -  // Remove allowed characters.
    -  fragment = fragment.replace(allowedInFragment, '');
    -
    -  // Only illegal characters should remain, which is a fail.
    -  assertEquals('String should be empty', 0, fragment.length);
    -
    -}
    -
    -function testStrictDoubleEncodingRemoval() {
    -  var url = goog.Uri.parse('dummy/a%25invalid');
    -  assertEquals('dummy/a%25invalid', url.toString());
    -  url = goog.Uri.parse('dummy/a%252fdouble-encoded-slash');
    -  assertEquals('dummy/a%2fdouble-encoded-slash', url.toString());
    -}
    -
    -
    -// Tests, that creating URI from components and then
    -// getting the components back yields equal results.
    -// The special attention is payed to test proper encoding
    -// and decoding of URI components.
    -function testComponentsAfterUriCreate() {
    -  var createdUri = new goog.Uri.create('%40',  // scheme
    -                                       '%41',  // user info
    -                                       '%42',  // domain
    -                                       43,     // port
    -                                       '%44',  // path
    -                                       '%45',  // query
    -                                       '%46'); // fragment
    -
    -  assertEquals('%40', createdUri.getScheme());
    -  assertEquals('%41', createdUri.getUserInfo());
    -  assertEquals('%42', createdUri.getDomain());
    -  assertEquals(43, createdUri.getPort());
    -  assertEquals('%44', createdUri.getPath());
    -  assertEquals('%2545', createdUri.getQuery()); // returns encoded value
    -  assertEquals('%45', createdUri.getDecodedQuery());
    -  assertEquals('%2545', createdUri.getEncodedQuery());
    -  assertEquals('%46', createdUri.getFragment());
    -}
    -
    -// Tests setting the query string and then reading back
    -// query parameter values.
    -function testSetQueryAndGetParameterValue() {
    -  var uri = new goog.Uri();
    -
    -  // Sets query as decoded string.
    -  uri.setQuery('i=j&k');
    -  assertEquals('?i=j&k', uri.toString());
    -  assertEquals('i=j&k', uri.getDecodedQuery());
    -  assertEquals('i=j&k', uri.getEncodedQuery());
    -  assertEquals('i=j&k', uri.getQuery()); // returns encoded value
    -  assertEquals('j', uri.getParameterValue('i'));
    -  assertEquals('', uri.getParameterValue('k'));
    -
    -  // Sets query as encoded string.
    -  uri.setQuery('i=j&k', true);
    -  assertEquals('?i=j&k', uri.toString());
    -  assertEquals('i=j&k', uri.getDecodedQuery());
    -  assertEquals('i=j&k', uri.getEncodedQuery());
    -  assertEquals('i=j&k', uri.getQuery()); // returns encoded value
    -  assertEquals('j', uri.getParameterValue('i'));
    -  assertEquals('', uri.getParameterValue('k'));
    -
    -  // Sets query as decoded string.
    -  uri.setQuery('i=j%26k');
    -  assertEquals('?i=j%2526k', uri.toString());
    -  assertEquals('i=j%26k', uri.getDecodedQuery());
    -  assertEquals('i=j%2526k', uri.getEncodedQuery());
    -  assertEquals('i=j%2526k', uri.getQuery()); // returns encoded value
    -  assertEquals('j%26k', uri.getParameterValue('i'));
    -  assertUndefined(uri.getParameterValue('k'));
    -
    -  // Sets query as encoded string.
    -  uri.setQuery('i=j%26k', true);
    -  assertEquals('?i=j%26k', uri.toString());
    -  assertEquals('i=j&k', uri.getDecodedQuery());
    -  assertEquals('i=j%26k', uri.getEncodedQuery());
    -  assertEquals('i=j%26k', uri.getQuery()); // returns encoded value
    -  assertEquals('j&k', uri.getParameterValue('i'));
    -  assertUndefined(uri.getParameterValue('k'));
    -}
    -
    -// Tests setting query parameter values and the reading back the query string.
    -function testSetParameterValueAndGetQuery() {
    -  var uri = new goog.Uri();
    -
    -  uri.setParameterValue('a', 'b&c');
    -  assertEquals('?a=b%26c', uri.toString());
    -  assertEquals('a=b&c', uri.getDecodedQuery());
    -  assertEquals('a=b%26c', uri.getEncodedQuery());
    -  assertEquals('a=b%26c', uri.getQuery()); // returns encoded value
    -
    -  uri.setParameterValue('a', 'b%26c');
    -  assertEquals('?a=b%2526c', uri.toString());
    -  assertEquals('a=b%26c', uri.getDecodedQuery());
    -  assertEquals('a=b%2526c', uri.getEncodedQuery());
    -  assertEquals('a=b%2526c', uri.getQuery()); // returns encoded value
    -}
    -
    -
    -// Tests that building a URI with a query string and then reading it back
    -// gives the same result.
    -function testQueryNotModified() {
    -  assertEquals('?foo', new goog.Uri('?foo').toString());
    -  assertEquals('?foo=', new goog.Uri('?foo=').toString());
    -  assertEquals('?foo=bar', new goog.Uri('?foo=bar').toString());
    -  assertEquals('?&=&=&', new goog.Uri('?&=&=&').toString());
    -}
    -
    -
    -function testRelativePathEscapesColon() {
    -  assertEquals('javascript%3aalert(1)',
    -               new goog.Uri().setPath('javascript:alert(1)').toString());
    -}
    -
    -
    -function testAbsolutePathDoesNotEscapeColon() {
    -  assertEquals('/javascript:alert(1)',
    -               new goog.Uri('/javascript:alert(1)').toString());
    -}
    -
    -
    -function testColonInPathNotUnescaped() {
    -  assertEquals('/javascript%3aalert(1)',
    -               new goog.Uri('/javascript%3aalert(1)').toString());
    -  assertEquals('javascript%3aalert(1)',
    -               new goog.Uri('javascript%3aalert(1)').toString());
    -  assertEquals('javascript:alert(1)',
    -               new goog.Uri('javascript:alert(1)').toString());
    -  assertEquals('http://www.foo.bar/path:with:colon/x',
    -               new goog.Uri('http://www.foo.bar/path:with:colon/x').toString());
    -  assertEquals('//www.foo.bar/path:with:colon/x',
    -               new goog.Uri('//www.foo.bar/path:with:colon/x').toString());
    -}
    -
    -
    -// verifies bug http://b/9821952
    -function testGetQueryForEmptyString() {
    -  var queryData = new goog.Uri.QueryData('a=b&c=d');
    -  assertArrayEquals(['b', 'd'], queryData.getValues());
    -  assertArrayEquals([], queryData.getValues(''));
    -
    -  queryData = new goog.Uri.QueryData('a=b&c=d&=e');
    -  assertArrayEquals(['e'], queryData.getValues(''));
    -}
    -
    -
    -function testRestrictedCharactersArePreserved() {
    -  var uri = new goog.Uri(
    -      'ht%74p://hos%74.example.%2f.com/pa%74h%2f-with-embedded-slash/');
    -  assertEquals('http', uri.getScheme());
    -  assertEquals('host.example.%2f.com', uri.getDomain());
    -  assertEquals('/path%2f-with-embedded-slash/', uri.getPath());
    -  assertEquals('http://host.example.%2f.com/path%2f-with-embedded-slash/',
    -      uri.toString());
    -}
    -
    -function assertDotRemovedEquals(expected, path) {
    -  assertEquals(expected, goog.Uri.removeDotSegments(path));
    -}
    -
    -function assertResolvedEquals(expected, base, other) {
    -  assertEquals(expected, goog.Uri.resolve(base, other).toString());
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/uri/utils.js b/src/database/third_party/closure-library/closure/goog/uri/utils.js
    deleted file mode 100644
    index 28a6ee32a39..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/uri/utils.js
    +++ /dev/null
    @@ -1,1116 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Simple utilities for dealing with URI strings.
    - *
    - * This is intended to be a lightweight alternative to constructing goog.Uri
    - * objects.  Whereas goog.Uri adds several kilobytes to the binary regardless
    - * of how much of its functionality you use, this is designed to be a set of
    - * mostly-independent utilities so that the compiler includes only what is
    - * necessary for the task.  Estimated savings of porting is 5k pre-gzip and
    - * 1.5k post-gzip.  To ensure the savings remain, future developers should
    - * avoid adding new functionality to existing functions, but instead create
    - * new ones and factor out shared code.
    - *
    - * Many of these utilities have limited functionality, tailored to common
    - * cases.  The query parameter utilities assume that the parameter keys are
    - * already encoded, since most keys are compile-time alphanumeric strings.  The
    - * query parameter mutation utilities also do not tolerate fragment identifiers.
    - *
    - * By design, these functions can be slower than goog.Uri equivalents.
    - * Repeated calls to some of functions may be quadratic in behavior for IE,
    - * although the effect is somewhat limited given the 2kb limit.
    - *
    - * One advantage of the limited functionality here is that this approach is
    - * less sensitive to differences in URI encodings than goog.Uri, since these
    - * functions operate on strings directly, rather than decoding them and
    - * then re-encoding.
    - *
    - * Uses features of RFC 3986 for parsing/formatting URIs:
    - *   http://www.ietf.org/rfc/rfc3986.txt
    - *
    - * @author gboyer@google.com (Garrett Boyer) - The "lightened" design.
    - */
    -
    -goog.provide('goog.uri.utils');
    -goog.provide('goog.uri.utils.ComponentIndex');
    -goog.provide('goog.uri.utils.QueryArray');
    -goog.provide('goog.uri.utils.QueryValue');
    -goog.provide('goog.uri.utils.StandardQueryParam');
    -
    -goog.require('goog.asserts');
    -goog.require('goog.string');
    -goog.require('goog.userAgent');
    -
    -
    -/**
    - * Character codes inlined to avoid object allocations due to charCode.
    - * @enum {number}
    - * @private
    - */
    -goog.uri.utils.CharCode_ = {
    -  AMPERSAND: 38,
    -  EQUAL: 61,
    -  HASH: 35,
    -  QUESTION: 63
    -};
    -
    -
    -/**
    - * Builds a URI string from already-encoded parts.
    - *
    - * No encoding is performed.  Any component may be omitted as either null or
    - * undefined.
    - *
    - * @param {?string=} opt_scheme The scheme such as 'http'.
    - * @param {?string=} opt_userInfo The user name before the '@'.
    - * @param {?string=} opt_domain The domain such as 'www.google.com', already
    - *     URI-encoded.
    - * @param {(string|number|null)=} opt_port The port number.
    - * @param {?string=} opt_path The path, already URI-encoded.  If it is not
    - *     empty, it must begin with a slash.
    - * @param {?string=} opt_queryData The URI-encoded query data.
    - * @param {?string=} opt_fragment The URI-encoded fragment identifier.
    - * @return {string} The fully combined URI.
    - */
    -goog.uri.utils.buildFromEncodedParts = function(opt_scheme, opt_userInfo,
    -    opt_domain, opt_port, opt_path, opt_queryData, opt_fragment) {
    -  var out = '';
    -
    -  if (opt_scheme) {
    -    out += opt_scheme + ':';
    -  }
    -
    -  if (opt_domain) {
    -    out += '//';
    -
    -    if (opt_userInfo) {
    -      out += opt_userInfo + '@';
    -    }
    -
    -    out += opt_domain;
    -
    -    if (opt_port) {
    -      out += ':' + opt_port;
    -    }
    -  }
    -
    -  if (opt_path) {
    -    out += opt_path;
    -  }
    -
    -  if (opt_queryData) {
    -    out += '?' + opt_queryData;
    -  }
    -
    -  if (opt_fragment) {
    -    out += '#' + opt_fragment;
    -  }
    -
    -  return out;
    -};
    -
    -
    -/**
    - * A regular expression for breaking a URI into its component parts.
    - *
    - * {@link http://www.ietf.org/rfc/rfc3986.txt} says in Appendix B
    - * As the "first-match-wins" algorithm is identical to the "greedy"
    - * disambiguation method used by POSIX regular expressions, it is natural and
    - * commonplace to use a regular expression for parsing the potential five
    - * components of a URI reference.
    - *
    - * The following line is the regular expression for breaking-down a
    - * well-formed URI reference into its components.
    - *
    - * <pre>
    - * ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
    - *  12            3  4          5       6  7        8 9
    - * </pre>
    - *
    - * The numbers in the second line above are only to assist readability; they
    - * indicate the reference points for each subexpression (i.e., each paired
    - * parenthesis). We refer to the value matched for subexpression <n> as $<n>.
    - * For example, matching the above expression to
    - * <pre>
    - *     http://www.ics.uci.edu/pub/ietf/uri/#Related
    - * </pre>
    - * results in the following subexpression matches:
    - * <pre>
    - *    $1 = http:
    - *    $2 = http
    - *    $3 = //www.ics.uci.edu
    - *    $4 = www.ics.uci.edu
    - *    $5 = /pub/ietf/uri/
    - *    $6 = <undefined>
    - *    $7 = <undefined>
    - *    $8 = #Related
    - *    $9 = Related
    - * </pre>
    - * where <undefined> indicates that the component is not present, as is the
    - * case for the query component in the above example. Therefore, we can
    - * determine the value of the five components as
    - * <pre>
    - *    scheme    = $2
    - *    authority = $4
    - *    path      = $5
    - *    query     = $7
    - *    fragment  = $9
    - * </pre>
    - *
    - * The regular expression has been modified slightly to expose the
    - * userInfo, domain, and port separately from the authority.
    - * The modified version yields
    - * <pre>
    - *    $1 = http              scheme
    - *    $2 = <undefined>       userInfo -\
    - *    $3 = www.ics.uci.edu   domain     | authority
    - *    $4 = <undefined>       port     -/
    - *    $5 = /pub/ietf/uri/    path
    - *    $6 = <undefined>       query without ?
    - *    $7 = Related           fragment without #
    - * </pre>
    - * @type {!RegExp}
    - * @private
    - */
    -goog.uri.utils.splitRe_ = new RegExp(
    -    '^' +
    -    '(?:' +
    -        '([^:/?#.]+)' +                  // scheme - ignore special characters
    -                                         // used by other URL parts such as :,
    -                                         // ?, /, #, and .
    -    ':)?' +
    -    '(?://' +
    -        '(?:([^/?#]*)@)?' +              // userInfo
    -        '([^/#?]*?)' +                   // domain
    -        '(?::([0-9]+))?' +               // port
    -        '(?=[/#?]|$)' +                  // authority-terminating character
    -    ')?' +
    -    '([^?#]+)?' +                        // path
    -    '(?:\\?([^#]*))?' +                  // query
    -    '(?:#(.*))?' +                       // fragment
    -    '$');
    -
    -
    -/**
    - * The index of each URI component in the return value of goog.uri.utils.split.
    - * @enum {number}
    - */
    -goog.uri.utils.ComponentIndex = {
    -  SCHEME: 1,
    -  USER_INFO: 2,
    -  DOMAIN: 3,
    -  PORT: 4,
    -  PATH: 5,
    -  QUERY_DATA: 6,
    -  FRAGMENT: 7
    -};
    -
    -
    -/**
    - * Splits a URI into its component parts.
    - *
    - * Each component can be accessed via the component indices; for example:
    - * <pre>
    - * goog.uri.utils.split(someStr)[goog.uri.utils.CompontentIndex.QUERY_DATA];
    - * </pre>
    - *
    - * @param {string} uri The URI string to examine.
    - * @return {!Array<string|undefined>} Each component still URI-encoded.
    - *     Each component that is present will contain the encoded value, whereas
    - *     components that are not present will be undefined or empty, depending
    - *     on the browser's regular expression implementation.  Never null, since
    - *     arbitrary strings may still look like path names.
    - */
    -goog.uri.utils.split = function(uri) {
    -  goog.uri.utils.phishingProtection_();
    -
    -  // See @return comment -- never null.
    -  return /** @type {!Array<string|undefined>} */ (
    -      uri.match(goog.uri.utils.splitRe_));
    -};
    -
    -
    -/**
    - * Safari has a nasty bug where if you have an http URL with a username, e.g.,
    - * http://evil.com%2F@google.com/
    - * Safari will report that window.location.href is
    - * http://evil.com/google.com/
    - * so that anyone who tries to parse the domain of that URL will get
    - * the wrong domain. We've seen exploits where people use this to trick
    - * Safari into loading resources from evil domains.
    - *
    - * To work around this, we run a little "Safari phishing check", and throw
    - * an exception if we see this happening.
    - *
    - * There is no convenient place to put this check. We apply it to
    - * anyone doing URI parsing on Webkit. We're not happy about this, but
    - * it fixes the problem.
    - *
    - * This should be removed once Safari fixes their bug.
    - *
    - * Exploit reported by Masato Kinugawa.
    - *
    - * @type {boolean}
    - * @private
    - */
    -goog.uri.utils.needsPhishingProtection_ = goog.userAgent.WEBKIT;
    -
    -
    -/**
    - * Check to see if the user is being phished.
    - * @private
    - */
    -goog.uri.utils.phishingProtection_ = function() {
    -  if (goog.uri.utils.needsPhishingProtection_) {
    -    // Turn protection off, so that we don't recurse.
    -    goog.uri.utils.needsPhishingProtection_ = false;
    -
    -    // Use quoted access, just in case the user isn't using location externs.
    -    var location = goog.global['location'];
    -    if (location) {
    -      var href = location['href'];
    -      if (href) {
    -        var domain = goog.uri.utils.getDomain(href);
    -        if (domain && domain != location['hostname']) {
    -          // Phishing attack
    -          goog.uri.utils.needsPhishingProtection_ = true;
    -          throw Error();
    -        }
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * @param {?string} uri A possibly null string.
    - * @param {boolean=} opt_preserveReserved If true, percent-encoding of RFC-3986
    - *     reserved characters will not be removed.
    - * @return {?string} The string URI-decoded, or null if uri is null.
    - * @private
    - */
    -goog.uri.utils.decodeIfPossible_ = function(uri, opt_preserveReserved) {
    -  if (!uri) {
    -    return uri;
    -  }
    -
    -  return opt_preserveReserved ? decodeURI(uri) : decodeURIComponent(uri);
    -};
    -
    -
    -/**
    - * Gets a URI component by index.
    - *
    - * It is preferred to use the getPathEncoded() variety of functions ahead,
    - * since they are more readable.
    - *
    - * @param {goog.uri.utils.ComponentIndex} componentIndex The component index.
    - * @param {string} uri The URI to examine.
    - * @return {?string} The still-encoded component, or null if the component
    - *     is not present.
    - * @private
    - */
    -goog.uri.utils.getComponentByIndex_ = function(componentIndex, uri) {
    -  // Convert undefined, null, and empty string into null.
    -  return goog.uri.utils.split(uri)[componentIndex] || null;
    -};
    -
    -
    -/**
    - * @param {string} uri The URI to examine.
    - * @return {?string} The protocol or scheme, or null if none.  Does not
    - *     include trailing colons or slashes.
    - */
    -goog.uri.utils.getScheme = function(uri) {
    -  return goog.uri.utils.getComponentByIndex_(
    -      goog.uri.utils.ComponentIndex.SCHEME, uri);
    -};
    -
    -
    -/**
    - * Gets the effective scheme for the URL.  If the URL is relative then the
    - * scheme is derived from the page's location.
    - * @param {string} uri The URI to examine.
    - * @return {string} The protocol or scheme, always lower case.
    - */
    -goog.uri.utils.getEffectiveScheme = function(uri) {
    -  var scheme = goog.uri.utils.getScheme(uri);
    -  if (!scheme && self.location) {
    -    var protocol = self.location.protocol;
    -    scheme = protocol.substr(0, protocol.length - 1);
    -  }
    -  // NOTE: When called from a web worker in Firefox 3.5, location maybe null.
    -  // All other browsers with web workers support self.location from the worker.
    -  return scheme ? scheme.toLowerCase() : '';
    -};
    -
    -
    -/**
    - * @param {string} uri The URI to examine.
    - * @return {?string} The user name still encoded, or null if none.
    - */
    -goog.uri.utils.getUserInfoEncoded = function(uri) {
    -  return goog.uri.utils.getComponentByIndex_(
    -      goog.uri.utils.ComponentIndex.USER_INFO, uri);
    -};
    -
    -
    -/**
    - * @param {string} uri The URI to examine.
    - * @return {?string} The decoded user info, or null if none.
    - */
    -goog.uri.utils.getUserInfo = function(uri) {
    -  return goog.uri.utils.decodeIfPossible_(
    -      goog.uri.utils.getUserInfoEncoded(uri));
    -};
    -
    -
    -/**
    - * @param {string} uri The URI to examine.
    - * @return {?string} The domain name still encoded, or null if none.
    - */
    -goog.uri.utils.getDomainEncoded = function(uri) {
    -  return goog.uri.utils.getComponentByIndex_(
    -      goog.uri.utils.ComponentIndex.DOMAIN, uri);
    -};
    -
    -
    -/**
    - * @param {string} uri The URI to examine.
    - * @return {?string} The decoded domain, or null if none.
    - */
    -goog.uri.utils.getDomain = function(uri) {
    -  return goog.uri.utils.decodeIfPossible_(
    -      goog.uri.utils.getDomainEncoded(uri), true /* opt_preserveReserved */);
    -};
    -
    -
    -/**
    - * @param {string} uri The URI to examine.
    - * @return {?number} The port number, or null if none.
    - */
    -goog.uri.utils.getPort = function(uri) {
    -  // Coerce to a number.  If the result of getComponentByIndex_ is null or
    -  // non-numeric, the number coersion yields NaN.  This will then return
    -  // null for all non-numeric cases (though also zero, which isn't a relevant
    -  // port number).
    -  return Number(goog.uri.utils.getComponentByIndex_(
    -      goog.uri.utils.ComponentIndex.PORT, uri)) || null;
    -};
    -
    -
    -/**
    - * @param {string} uri The URI to examine.
    - * @return {?string} The path still encoded, or null if none. Includes the
    - *     leading slash, if any.
    - */
    -goog.uri.utils.getPathEncoded = function(uri) {
    -  return goog.uri.utils.getComponentByIndex_(
    -      goog.uri.utils.ComponentIndex.PATH, uri);
    -};
    -
    -
    -/**
    - * @param {string} uri The URI to examine.
    - * @return {?string} The decoded path, or null if none.  Includes the leading
    - *     slash, if any.
    - */
    -goog.uri.utils.getPath = function(uri) {
    -  return goog.uri.utils.decodeIfPossible_(
    -      goog.uri.utils.getPathEncoded(uri), true /* opt_preserveReserved */);
    -};
    -
    -
    -/**
    - * @param {string} uri The URI to examine.
    - * @return {?string} The query data still encoded, or null if none.  Does not
    - *     include the question mark itself.
    - */
    -goog.uri.utils.getQueryData = function(uri) {
    -  return goog.uri.utils.getComponentByIndex_(
    -      goog.uri.utils.ComponentIndex.QUERY_DATA, uri);
    -};
    -
    -
    -/**
    - * @param {string} uri The URI to examine.
    - * @return {?string} The fragment identifier, or null if none.  Does not
    - *     include the hash mark itself.
    - */
    -goog.uri.utils.getFragmentEncoded = function(uri) {
    -  // The hash mark may not appear in any other part of the URL.
    -  var hashIndex = uri.indexOf('#');
    -  return hashIndex < 0 ? null : uri.substr(hashIndex + 1);
    -};
    -
    -
    -/**
    - * @param {string} uri The URI to examine.
    - * @param {?string} fragment The encoded fragment identifier, or null if none.
    - *     Does not include the hash mark itself.
    - * @return {string} The URI with the fragment set.
    - */
    -goog.uri.utils.setFragmentEncoded = function(uri, fragment) {
    -  return goog.uri.utils.removeFragment(uri) + (fragment ? '#' + fragment : '');
    -};
    -
    -
    -/**
    - * @param {string} uri The URI to examine.
    - * @return {?string} The decoded fragment identifier, or null if none.  Does
    - *     not include the hash mark.
    - */
    -goog.uri.utils.getFragment = function(uri) {
    -  return goog.uri.utils.decodeIfPossible_(
    -      goog.uri.utils.getFragmentEncoded(uri));
    -};
    -
    -
    -/**
    - * Extracts everything up to the port of the URI.
    - * @param {string} uri The URI string.
    - * @return {string} Everything up to and including the port.
    - */
    -goog.uri.utils.getHost = function(uri) {
    -  var pieces = goog.uri.utils.split(uri);
    -  return goog.uri.utils.buildFromEncodedParts(
    -      pieces[goog.uri.utils.ComponentIndex.SCHEME],
    -      pieces[goog.uri.utils.ComponentIndex.USER_INFO],
    -      pieces[goog.uri.utils.ComponentIndex.DOMAIN],
    -      pieces[goog.uri.utils.ComponentIndex.PORT]);
    -};
    -
    -
    -/**
    - * Extracts the path of the URL and everything after.
    - * @param {string} uri The URI string.
    - * @return {string} The URI, starting at the path and including the query
    - *     parameters and fragment identifier.
    - */
    -goog.uri.utils.getPathAndAfter = function(uri) {
    -  var pieces = goog.uri.utils.split(uri);
    -  return goog.uri.utils.buildFromEncodedParts(null, null, null, null,
    -      pieces[goog.uri.utils.ComponentIndex.PATH],
    -      pieces[goog.uri.utils.ComponentIndex.QUERY_DATA],
    -      pieces[goog.uri.utils.ComponentIndex.FRAGMENT]);
    -};
    -
    -
    -/**
    - * Gets the URI with the fragment identifier removed.
    - * @param {string} uri The URI to examine.
    - * @return {string} Everything preceding the hash mark.
    - */
    -goog.uri.utils.removeFragment = function(uri) {
    -  // The hash mark may not appear in any other part of the URL.
    -  var hashIndex = uri.indexOf('#');
    -  return hashIndex < 0 ? uri : uri.substr(0, hashIndex);
    -};
    -
    -
    -/**
    - * Ensures that two URI's have the exact same domain, scheme, and port.
    - *
    - * Unlike the version in goog.Uri, this checks protocol, and therefore is
    - * suitable for checking against the browser's same-origin policy.
    - *
    - * @param {string} uri1 The first URI.
    - * @param {string} uri2 The second URI.
    - * @return {boolean} Whether they have the same scheme, domain and port.
    - */
    -goog.uri.utils.haveSameDomain = function(uri1, uri2) {
    -  var pieces1 = goog.uri.utils.split(uri1);
    -  var pieces2 = goog.uri.utils.split(uri2);
    -  return pieces1[goog.uri.utils.ComponentIndex.DOMAIN] ==
    -             pieces2[goog.uri.utils.ComponentIndex.DOMAIN] &&
    -         pieces1[goog.uri.utils.ComponentIndex.SCHEME] ==
    -             pieces2[goog.uri.utils.ComponentIndex.SCHEME] &&
    -         pieces1[goog.uri.utils.ComponentIndex.PORT] ==
    -             pieces2[goog.uri.utils.ComponentIndex.PORT];
    -};
    -
    -
    -/**
    - * Asserts that there are no fragment or query identifiers, only in uncompiled
    - * mode.
    - * @param {string} uri The URI to examine.
    - * @private
    - */
    -goog.uri.utils.assertNoFragmentsOrQueries_ = function(uri) {
    -  // NOTE: would use goog.asserts here, but jscompiler doesn't know that
    -  // indexOf has no side effects.
    -  if (goog.DEBUG && (uri.indexOf('#') >= 0 || uri.indexOf('?') >= 0)) {
    -    throw Error('goog.uri.utils: Fragment or query identifiers are not ' +
    -        'supported: [' + uri + ']');
    -  }
    -};
    -
    -
    -/**
    - * Supported query parameter values by the parameter serializing utilities.
    - *
    - * If a value is null or undefined, the key-value pair is skipped, as an easy
    - * way to omit parameters conditionally.  Non-array parameters are converted
    - * to a string and URI encoded.  Array values are expanded into multiple
    - * &key=value pairs, with each element stringized and URI-encoded.
    - *
    - * @typedef {*}
    - */
    -goog.uri.utils.QueryValue;
    -
    -
    -/**
    - * An array representing a set of query parameters with alternating keys
    - * and values.
    - *
    - * Keys are assumed to be URI encoded already and live at even indices.  See
    - * goog.uri.utils.QueryValue for details on how parameter values are encoded.
    - *
    - * Example:
    - * <pre>
    - * var data = [
    - *   // Simple param: ?name=BobBarker
    - *   'name', 'BobBarker',
    - *   // Conditional param -- may be omitted entirely.
    - *   'specialDietaryNeeds', hasDietaryNeeds() ? getDietaryNeeds() : null,
    - *   // Multi-valued param: &house=LosAngeles&house=NewYork&house=null
    - *   'house', ['LosAngeles', 'NewYork', null]
    - * ];
    - * </pre>
    - *
    - * @typedef {!Array<string|goog.uri.utils.QueryValue>}
    - */
    -goog.uri.utils.QueryArray;
    -
    -
    -/**
    - * Parses encoded query parameters and calls callback function for every
    - * parameter found in the string.
    - *
    - * Missing value of parameter (e.g. “…&key&…”) is treated as if the value was an
    - * empty string.  Keys may be empty strings (e.g. “…&=value&…”) which also means
    - * that “…&=&…” and “…&&…” will result in an empty key and value.
    - *
    - * @param {string} encodedQuery Encoded query string excluding question mark at
    - *     the beginning.
    - * @param {function(string, string)} callback Function called for every
    - *     parameter found in query string.  The first argument (name) will not be
    - *     urldecoded (so the function is consistent with buildQueryData), but the
    - *     second will.  If the parameter has no value (i.e. “=” was not present)
    - *     the second argument (value) will be an empty string.
    - */
    -goog.uri.utils.parseQueryData = function(encodedQuery, callback) {
    -  var pairs = encodedQuery.split('&');
    -  for (var i = 0; i < pairs.length; i++) {
    -    var indexOfEquals = pairs[i].indexOf('=');
    -    var name = null;
    -    var value = null;
    -    if (indexOfEquals >= 0) {
    -      name = pairs[i].substring(0, indexOfEquals);
    -      value = pairs[i].substring(indexOfEquals + 1);
    -    } else {
    -      name = pairs[i];
    -    }
    -    callback(name, value ? goog.string.urlDecode(value) : '');
    -  }
    -};
    -
    -
    -/**
    - * Appends a URI and query data in a string buffer with special preconditions.
    - *
    - * Internal implementation utility, performing very few object allocations.
    - *
    - * @param {!Array<string|undefined>} buffer A string buffer.  The first element
    - *     must be the base URI, and may have a fragment identifier.  If the array
    - *     contains more than one element, the second element must be an ampersand,
    - *     and may be overwritten, depending on the base URI.  Undefined elements
    - *     are treated as empty-string.
    - * @return {string} The concatenated URI and query data.
    - * @private
    - */
    -goog.uri.utils.appendQueryData_ = function(buffer) {
    -  if (buffer[1]) {
    -    // At least one query parameter was added.  We need to check the
    -    // punctuation mark, which is currently an ampersand, and also make sure
    -    // there aren't any interfering fragment identifiers.
    -    var baseUri = /** @type {string} */ (buffer[0]);
    -    var hashIndex = baseUri.indexOf('#');
    -    if (hashIndex >= 0) {
    -      // Move the fragment off the base part of the URI into the end.
    -      buffer.push(baseUri.substr(hashIndex));
    -      buffer[0] = baseUri = baseUri.substr(0, hashIndex);
    -    }
    -    var questionIndex = baseUri.indexOf('?');
    -    if (questionIndex < 0) {
    -      // No question mark, so we need a question mark instead of an ampersand.
    -      buffer[1] = '?';
    -    } else if (questionIndex == baseUri.length - 1) {
    -      // Question mark is the very last character of the existing URI, so don't
    -      // append an additional delimiter.
    -      buffer[1] = undefined;
    -    }
    -  }
    -
    -  return buffer.join('');
    -};
    -
    -
    -/**
    - * Appends key=value pairs to an array, supporting multi-valued objects.
    - * @param {string} key The key prefix.
    - * @param {goog.uri.utils.QueryValue} value The value to serialize.
    - * @param {!Array<string>} pairs The array to which the 'key=value' strings
    - *     should be appended.
    - * @private
    - */
    -goog.uri.utils.appendKeyValuePairs_ = function(key, value, pairs) {
    -  if (goog.isArray(value)) {
    -    // Convince the compiler it's an array.
    -    goog.asserts.assertArray(value);
    -    for (var j = 0; j < value.length; j++) {
    -      // Convert to string explicitly, to short circuit the null and array
    -      // logic in this function -- this ensures that null and undefined get
    -      // written as literal 'null' and 'undefined', and arrays don't get
    -      // expanded out but instead encoded in the default way.
    -      goog.uri.utils.appendKeyValuePairs_(key, String(value[j]), pairs);
    -    }
    -  } else if (value != null) {
    -    // Skip a top-level null or undefined entirely.
    -    pairs.push('&', key,
    -        // Check for empty string. Zero gets encoded into the url as literal
    -        // strings.  For empty string, skip the equal sign, to be consistent
    -        // with UriBuilder.java.
    -        value === '' ? '' : '=',
    -        goog.string.urlEncode(value));
    -  }
    -};
    -
    -
    -/**
    - * Builds a buffer of query data from a sequence of alternating keys and values.
    - *
    - * @param {!Array<string|undefined>} buffer A string buffer to append to.  The
    - *     first element appended will be an '&', and may be replaced by the caller.
    - * @param {!goog.uri.utils.QueryArray|!Arguments} keysAndValues An array with
    - *     alternating keys and values -- see the typedef.
    - * @param {number=} opt_startIndex A start offset into the arary, defaults to 0.
    - * @return {!Array<string|undefined>} The buffer argument.
    - * @private
    - */
    -goog.uri.utils.buildQueryDataBuffer_ = function(
    -    buffer, keysAndValues, opt_startIndex) {
    -  goog.asserts.assert(Math.max(keysAndValues.length - (opt_startIndex || 0),
    -      0) % 2 == 0, 'goog.uri.utils: Key/value lists must be even in length.');
    -
    -  for (var i = opt_startIndex || 0; i < keysAndValues.length; i += 2) {
    -    goog.uri.utils.appendKeyValuePairs_(
    -        keysAndValues[i], keysAndValues[i + 1], buffer);
    -  }
    -
    -  return buffer;
    -};
    -
    -
    -/**
    - * Builds a query data string from a sequence of alternating keys and values.
    - * Currently generates "&key&" for empty args.
    - *
    - * @param {goog.uri.utils.QueryArray} keysAndValues Alternating keys and
    - *     values.  See the typedef.
    - * @param {number=} opt_startIndex A start offset into the arary, defaults to 0.
    - * @return {string} The encoded query string, in the form 'a=1&b=2'.
    - */
    -goog.uri.utils.buildQueryData = function(keysAndValues, opt_startIndex) {
    -  var buffer = goog.uri.utils.buildQueryDataBuffer_(
    -      [], keysAndValues, opt_startIndex);
    -  buffer[0] = ''; // Remove the leading ampersand.
    -  return buffer.join('');
    -};
    -
    -
    -/**
    - * Builds a buffer of query data from a map.
    - *
    - * @param {!Array<string|undefined>} buffer A string buffer to append to.  The
    - *     first element appended will be an '&', and may be replaced by the caller.
    - * @param {!Object<string, goog.uri.utils.QueryValue>} map An object where keys
    - *     are URI-encoded parameter keys, and the values conform to the contract
    - *     specified in the goog.uri.utils.QueryValue typedef.
    - * @return {!Array<string|undefined>} The buffer argument.
    - * @private
    - */
    -goog.uri.utils.buildQueryDataBufferFromMap_ = function(buffer, map) {
    -  for (var key in map) {
    -    goog.uri.utils.appendKeyValuePairs_(key, map[key], buffer);
    -  }
    -
    -  return buffer;
    -};
    -
    -
    -/**
    - * Builds a query data string from a map.
    - * Currently generates "&key&" for empty args.
    - *
    - * @param {!Object<string, goog.uri.utils.QueryValue>} map An object where keys
    - *     are URI-encoded parameter keys, and the values are arbitrary types
    - *     or arrays. Keys with a null value are dropped.
    - * @return {string} The encoded query string, in the form 'a=1&b=2'.
    - */
    -goog.uri.utils.buildQueryDataFromMap = function(map) {
    -  var buffer = goog.uri.utils.buildQueryDataBufferFromMap_([], map);
    -  buffer[0] = '';
    -  return buffer.join('');
    -};
    -
    -
    -/**
    - * Appends URI parameters to an existing URI.
    - *
    - * The variable arguments may contain alternating keys and values.  Keys are
    - * assumed to be already URI encoded.  The values should not be URI-encoded,
    - * and will instead be encoded by this function.
    - * <pre>
    - * appendParams('http://www.foo.com?existing=true',
    - *     'key1', 'value1',
    - *     'key2', 'value?willBeEncoded',
    - *     'key3', ['valueA', 'valueB', 'valueC'],
    - *     'key4', null);
    - * result: 'http://www.foo.com?existing=true&' +
    - *     'key1=value1&' +
    - *     'key2=value%3FwillBeEncoded&' +
    - *     'key3=valueA&key3=valueB&key3=valueC'
    - * </pre>
    - *
    - * A single call to this function will not exhibit quadratic behavior in IE,
    - * whereas multiple repeated calls may, although the effect is limited by
    - * fact that URL's generally can't exceed 2kb.
    - *
    - * @param {string} uri The original URI, which may already have query data.
    - * @param {...(goog.uri.utils.QueryArray|string|goog.uri.utils.QueryValue)} var_args
    - *     An array or argument list conforming to goog.uri.utils.QueryArray.
    - * @return {string} The URI with all query parameters added.
    - */
    -goog.uri.utils.appendParams = function(uri, var_args) {
    -  return goog.uri.utils.appendQueryData_(
    -      arguments.length == 2 ?
    -      goog.uri.utils.buildQueryDataBuffer_([uri], arguments[1], 0) :
    -      goog.uri.utils.buildQueryDataBuffer_([uri], arguments, 1));
    -};
    -
    -
    -/**
    - * Appends query parameters from a map.
    - *
    - * @param {string} uri The original URI, which may already have query data.
    - * @param {!Object<goog.uri.utils.QueryValue>} map An object where keys are
    - *     URI-encoded parameter keys, and the values are arbitrary types or arrays.
    - *     Keys with a null value are dropped.
    - * @return {string} The new parameters.
    - */
    -goog.uri.utils.appendParamsFromMap = function(uri, map) {
    -  return goog.uri.utils.appendQueryData_(
    -      goog.uri.utils.buildQueryDataBufferFromMap_([uri], map));
    -};
    -
    -
    -/**
    - * Appends a single URI parameter.
    - *
    - * Repeated calls to this can exhibit quadratic behavior in IE6 due to the
    - * way string append works, though it should be limited given the 2kb limit.
    - *
    - * @param {string} uri The original URI, which may already have query data.
    - * @param {string} key The key, which must already be URI encoded.
    - * @param {*=} opt_value The value, which will be stringized and encoded
    - *     (assumed not already to be encoded).  If omitted, undefined, or null, the
    - *     key will be added as a valueless parameter.
    - * @return {string} The URI with the query parameter added.
    - */
    -goog.uri.utils.appendParam = function(uri, key, opt_value) {
    -  var paramArr = [uri, '&', key];
    -  if (goog.isDefAndNotNull(opt_value)) {
    -    paramArr.push('=', goog.string.urlEncode(opt_value));
    -  }
    -  return goog.uri.utils.appendQueryData_(paramArr);
    -};
    -
    -
    -/**
    - * Finds the next instance of a query parameter with the specified name.
    - *
    - * Does not instantiate any objects.
    - *
    - * @param {string} uri The URI to search.  May contain a fragment identifier
    - *     if opt_hashIndex is specified.
    - * @param {number} startIndex The index to begin searching for the key at.  A
    - *     match may be found even if this is one character after the ampersand.
    - * @param {string} keyEncoded The URI-encoded key.
    - * @param {number} hashOrEndIndex Index to stop looking at.  If a hash
    - *     mark is present, it should be its index, otherwise it should be the
    - *     length of the string.
    - * @return {number} The position of the first character in the key's name,
    - *     immediately after either a question mark or a dot.
    - * @private
    - */
    -goog.uri.utils.findParam_ = function(
    -    uri, startIndex, keyEncoded, hashOrEndIndex) {
    -  var index = startIndex;
    -  var keyLength = keyEncoded.length;
    -
    -  // Search for the key itself and post-filter for surronuding punctuation,
    -  // rather than expensively building a regexp.
    -  while ((index = uri.indexOf(keyEncoded, index)) >= 0 &&
    -      index < hashOrEndIndex) {
    -    var precedingChar = uri.charCodeAt(index - 1);
    -    // Ensure that the preceding character is '&' or '?'.
    -    if (precedingChar == goog.uri.utils.CharCode_.AMPERSAND ||
    -        precedingChar == goog.uri.utils.CharCode_.QUESTION) {
    -      // Ensure the following character is '&', '=', '#', or NaN
    -      // (end of string).
    -      var followingChar = uri.charCodeAt(index + keyLength);
    -      if (!followingChar ||
    -          followingChar == goog.uri.utils.CharCode_.EQUAL ||
    -          followingChar == goog.uri.utils.CharCode_.AMPERSAND ||
    -          followingChar == goog.uri.utils.CharCode_.HASH) {
    -        return index;
    -      }
    -    }
    -    index += keyLength + 1;
    -  }
    -
    -  return -1;
    -};
    -
    -
    -/**
    - * Regular expression for finding a hash mark or end of string.
    - * @type {RegExp}
    - * @private
    - */
    -goog.uri.utils.hashOrEndRe_ = /#|$/;
    -
    -
    -/**
    - * Determines if the URI contains a specific key.
    - *
    - * Performs no object instantiations.
    - *
    - * @param {string} uri The URI to process.  May contain a fragment
    - *     identifier.
    - * @param {string} keyEncoded The URI-encoded key.  Case-sensitive.
    - * @return {boolean} Whether the key is present.
    - */
    -goog.uri.utils.hasParam = function(uri, keyEncoded) {
    -  return goog.uri.utils.findParam_(uri, 0, keyEncoded,
    -      uri.search(goog.uri.utils.hashOrEndRe_)) >= 0;
    -};
    -
    -
    -/**
    - * Gets the first value of a query parameter.
    - * @param {string} uri The URI to process.  May contain a fragment.
    - * @param {string} keyEncoded The URI-encoded key.  Case-sensitive.
    - * @return {?string} The first value of the parameter (URI-decoded), or null
    - *     if the parameter is not found.
    - */
    -goog.uri.utils.getParamValue = function(uri, keyEncoded) {
    -  var hashOrEndIndex = uri.search(goog.uri.utils.hashOrEndRe_);
    -  var foundIndex = goog.uri.utils.findParam_(
    -      uri, 0, keyEncoded, hashOrEndIndex);
    -
    -  if (foundIndex < 0) {
    -    return null;
    -  } else {
    -    var endPosition = uri.indexOf('&', foundIndex);
    -    if (endPosition < 0 || endPosition > hashOrEndIndex) {
    -      endPosition = hashOrEndIndex;
    -    }
    -    // Progress forth to the end of the "key=" or "key&" substring.
    -    foundIndex += keyEncoded.length + 1;
    -    // Use substr, because it (unlike substring) will return empty string
    -    // if foundIndex > endPosition.
    -    return goog.string.urlDecode(
    -        uri.substr(foundIndex, endPosition - foundIndex));
    -  }
    -};
    -
    -
    -/**
    - * Gets all values of a query parameter.
    - * @param {string} uri The URI to process.  May contain a framgnet.
    - * @param {string} keyEncoded The URI-encoded key.  Case-snsitive.
    - * @return {!Array<string>} All URI-decoded values with the given key.
    - *     If the key is not found, this will have length 0, but never be null.
    - */
    -goog.uri.utils.getParamValues = function(uri, keyEncoded) {
    -  var hashOrEndIndex = uri.search(goog.uri.utils.hashOrEndRe_);
    -  var position = 0;
    -  var foundIndex;
    -  var result = [];
    -
    -  while ((foundIndex = goog.uri.utils.findParam_(
    -      uri, position, keyEncoded, hashOrEndIndex)) >= 0) {
    -    // Find where this parameter ends, either the '&' or the end of the
    -    // query parameters.
    -    position = uri.indexOf('&', foundIndex);
    -    if (position < 0 || position > hashOrEndIndex) {
    -      position = hashOrEndIndex;
    -    }
    -
    -    // Progress forth to the end of the "key=" or "key&" substring.
    -    foundIndex += keyEncoded.length + 1;
    -    // Use substr, because it (unlike substring) will return empty string
    -    // if foundIndex > position.
    -    result.push(goog.string.urlDecode(uri.substr(
    -        foundIndex, position - foundIndex)));
    -  }
    -
    -  return result;
    -};
    -
    -
    -/**
    - * Regexp to find trailing question marks and ampersands.
    - * @type {RegExp}
    - * @private
    - */
    -goog.uri.utils.trailingQueryPunctuationRe_ = /[?&]($|#)/;
    -
    -
    -/**
    - * Removes all instances of a query parameter.
    - * @param {string} uri The URI to process.  Must not contain a fragment.
    - * @param {string} keyEncoded The URI-encoded key.
    - * @return {string} The URI with all instances of the parameter removed.
    - */
    -goog.uri.utils.removeParam = function(uri, keyEncoded) {
    -  var hashOrEndIndex = uri.search(goog.uri.utils.hashOrEndRe_);
    -  var position = 0;
    -  var foundIndex;
    -  var buffer = [];
    -
    -  // Look for a query parameter.
    -  while ((foundIndex = goog.uri.utils.findParam_(
    -      uri, position, keyEncoded, hashOrEndIndex)) >= 0) {
    -    // Get the portion of the query string up to, but not including, the ?
    -    // or & starting the parameter.
    -    buffer.push(uri.substring(position, foundIndex));
    -    // Progress to immediately after the '&'.  If not found, go to the end.
    -    // Avoid including the hash mark.
    -    position = Math.min((uri.indexOf('&', foundIndex) + 1) || hashOrEndIndex,
    -        hashOrEndIndex);
    -  }
    -
    -  // Append everything that is remaining.
    -  buffer.push(uri.substr(position));
    -
    -  // Join the buffer, and remove trailing punctuation that remains.
    -  return buffer.join('').replace(
    -      goog.uri.utils.trailingQueryPunctuationRe_, '$1');
    -};
    -
    -
    -/**
    - * Replaces all existing definitions of a parameter with a single definition.
    - *
    - * Repeated calls to this can exhibit quadratic behavior due to the need to
    - * find existing instances and reconstruct the string, though it should be
    - * limited given the 2kb limit.  Consider using appendParams to append multiple
    - * parameters in bulk.
    - *
    - * @param {string} uri The original URI, which may already have query data.
    - * @param {string} keyEncoded The key, which must already be URI encoded.
    - * @param {*} value The value, which will be stringized and encoded (assumed
    - *     not already to be encoded).
    - * @return {string} The URI with the query parameter added.
    - */
    -goog.uri.utils.setParam = function(uri, keyEncoded, value) {
    -  return goog.uri.utils.appendParam(
    -      goog.uri.utils.removeParam(uri, keyEncoded), keyEncoded, value);
    -};
    -
    -
    -/**
    - * Generates a URI path using a given URI and a path with checks to
    - * prevent consecutive "//". The baseUri passed in must not contain
    - * query or fragment identifiers. The path to append may not contain query or
    - * fragment identifiers.
    - *
    - * @param {string} baseUri URI to use as the base.
    - * @param {string} path Path to append.
    - * @return {string} Updated URI.
    - */
    -goog.uri.utils.appendPath = function(baseUri, path) {
    -  goog.uri.utils.assertNoFragmentsOrQueries_(baseUri);
    -
    -  // Remove any trailing '/'
    -  if (goog.string.endsWith(baseUri, '/')) {
    -    baseUri = baseUri.substr(0, baseUri.length - 1);
    -  }
    -  // Remove any leading '/'
    -  if (goog.string.startsWith(path, '/')) {
    -    path = path.substr(1);
    -  }
    -  return goog.string.buildString(baseUri, '/', path);
    -};
    -
    -
    -/**
    - * Replaces the path.
    - * @param {string} uri URI to use as the base.
    - * @param {string} path New path.
    - * @return {string} Updated URI.
    - */
    -goog.uri.utils.setPath = function(uri, path) {
    -  // Add any missing '/'.
    -  if (!goog.string.startsWith(path, '/')) {
    -    path = '/' + path;
    -  }
    -  var parts = goog.uri.utils.split(uri);
    -  return goog.uri.utils.buildFromEncodedParts(
    -      parts[goog.uri.utils.ComponentIndex.SCHEME],
    -      parts[goog.uri.utils.ComponentIndex.USER_INFO],
    -      parts[goog.uri.utils.ComponentIndex.DOMAIN],
    -      parts[goog.uri.utils.ComponentIndex.PORT],
    -      path,
    -      parts[goog.uri.utils.ComponentIndex.QUERY_DATA],
    -      parts[goog.uri.utils.ComponentIndex.FRAGMENT]);
    -};
    -
    -
    -/**
    - * Standard supported query parameters.
    - * @enum {string}
    - */
    -goog.uri.utils.StandardQueryParam = {
    -
    -  /** Unused parameter for unique-ifying. */
    -  RANDOM: 'zx'
    -};
    -
    -
    -/**
    - * Sets the zx parameter of a URI to a random value.
    - * @param {string} uri Any URI.
    - * @return {string} That URI with the "zx" parameter added or replaced to
    - *     contain a random string.
    - */
    -goog.uri.utils.makeUnique = function(uri) {
    -  return goog.uri.utils.setParam(uri,
    -      goog.uri.utils.StandardQueryParam.RANDOM, goog.string.getRandomString());
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/uri/utils_test.html b/src/database/third_party/closure-library/closure/goog/uri/utils_test.html
    deleted file mode 100644
    index f11b40df8f6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/uri/utils_test.html
    +++ /dev/null
    @@ -1,28 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -
    -  Most of these tests were stolen from the original goog.Uri tests.
    -
    -  Author: gboyer@google.com (Garrett Boyer)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.uri.utils
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.uri.utilsTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/uri/utils_test.js b/src/database/third_party/closure-library/closure/goog/uri/utils_test.js
    deleted file mode 100644
    index c46be3d4710..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/uri/utils_test.js
    +++ /dev/null
    @@ -1,601 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.uri.utilsTest');
    -goog.setTestOnly('goog.uri.utilsTest');
    -
    -goog.require('goog.functions');
    -goog.require('goog.string');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.uri.utils');
    -
    -var utils = goog.uri.utils;
    -var stubs = new goog.testing.PropertyReplacer();
    -
    -
    -function setUpPage() {
    -  goog.string.getRandomString = goog.functions.constant('RANDOM');
    -}
    -
    -function tearDown() {
    -  stubs.reset();
    -}
    -
    -function testSplit() {
    -  var uri = 'http://www.google.com:80/path%20path+path?q=query&hl=en#fragment';
    -  assertEquals('http', utils.getScheme(uri));
    -  assertNull(utils.getUserInfoEncoded(uri));
    -  assertNull(utils.getUserInfo(uri));
    -  assertEquals('www.google.com', utils.getDomainEncoded(uri));
    -  assertEquals('www.google.com', utils.getDomain(uri));
    -  assertEquals(80, utils.getPort(uri));
    -  assertEquals('/path%20path+path', utils.getPathEncoded(uri));
    -  assertEquals('/path path+path', utils.getPath(uri));
    -  assertEquals('q=query&hl=en', utils.getQueryData(uri));
    -  assertEquals('fragment', utils.getFragmentEncoded(uri));
    -  assertEquals('fragment', utils.getFragment(uri));
    -
    -  assertEquals(utils.getDomain('http://[2607:f8b0:4006:802::1006]'),
    -      '[2607:f8b0:4006:802::1006]');
    -  assertEquals(utils.getDomain('http://[2607:f8b0:4006:802::1006]:80'),
    -      '[2607:f8b0:4006:802::1006]');
    -  assertEquals(utils.getPort('http://[2607:f8b0:4006:802::1006]:80'), 80);
    -  assertEquals(utils.getDomain('http://[2607]:80/?q=]'), '[2607]');
    -  assertEquals(utils.getDomain('http://!!!'), '!!!');
    -  assertNull(utils.getPath('http://!!!'));
    -  assertNull(utils.getScheme('www.x.com:80'));
    -  assertEquals('Query data with no fragment identifier', 'foo=bar&baz=bin',
    -      utils.getQueryData('http://google.com?foo=bar&baz=bin'));
    -}
    -
    -function testMailtoUri() {
    -  var uri = 'mailto:joe+random@hominid.com';
    -  assertNull(utils.getDomain(uri));
    -  assertEquals('mailto', utils.getScheme(uri));
    -  assertEquals('joe+random@hominid.com', utils.getPath(uri));
    -}
    -
    -function testSplitRelativeUri() {
    -  var uri = '/path%20path+path?q=query&hl=en#fragment';
    -  assertNull(utils.getScheme(uri));
    -  assertNull(utils.getDomain(uri));
    -  assertNull(utils.getDomainEncoded(uri));
    -  assertNull(utils.getPort(uri));
    -  assertEquals('/path%20path+path', utils.getPathEncoded(uri));
    -  assertEquals('/path path+path', utils.getPath(uri));
    -  assertEquals('q=query&hl=en', utils.getQueryData(uri));
    -  assertEquals('fragment', utils.getFragmentEncoded(uri));
    -  assertEquals('fragment', utils.getFragment(uri));
    -}
    -
    -function testSplitBadAuthority() {
    -  // This URL has a syntax error per the RFC (port number must be digits, and
    -  // host cannot contain a colon except in [...]). This test is solely to
    -  // 'document' the current behavior, which may affect application handling
    -  // of erroneous URLs.
    -  assertEquals(utils.getDomain('http://host:port/'), 'host:port');
    -  assertNull(utils.getPort('http://host:port/'));
    -}
    -
    -function testSplitIntoHostAndPath() {
    -  // Splitting into host and path takes care of one of the major use cases
    -  // of resolve, without implementing a generic algorithm that undoubtedly
    -  // requires a huge footprint.
    -  var uri = 'http://www.google.com:80/path%20path+path?q=query&hl=en#fragment';
    -  assertEquals('http://www.google.com:80',
    -      goog.uri.utils.getHost(uri));
    -  assertEquals('/path%20path+path?q=query&hl=en#fragment',
    -      goog.uri.utils.getPathAndAfter(uri));
    -
    -  var uri2 = 'http://www.google.com/calendar';
    -  assertEquals('should handle missing fields', 'http://www.google.com',
    -      goog.uri.utils.getHost(uri2));
    -  assertEquals('should handle missing fields', '/calendar',
    -      goog.uri.utils.getPathAndAfter(uri2));
    -}
    -
    -
    -function testRelativeUrisHaveNoPath() {
    -  assertNull(utils.getPathEncoded('?hello'));
    -}
    -
    -
    -function testReservedCharacters() {
    -  var o = '%6F';
    -  var uri = 'http://www.g' + o + 'ogle.com%40/xxx%2feee/ccc';
    -  assertEquals('Should not decode reserved characters in path',
    -      '/xxx%2feee/ccc', goog.uri.utils.getPath(uri));
    -  assertEquals('Should not decode reserved characters in domain',
    -      'www.google.com%40', goog.uri.utils.getDomain(uri));
    -}
    -
    -function testSetFragmentEncoded() {
    -  var expected = 'http://www.google.com/path#bar';
    -  assertEquals(expected,
    -      utils.setFragmentEncoded('http://www.google.com/path#foo', 'bar'));
    -
    -  assertEquals(expected,
    -      utils.setFragmentEncoded('http://www.google.com/path', 'bar'));
    -
    -  assertEquals('http://www.google.com/path',
    -      utils.setFragmentEncoded('http://www.google.com/path', ''));
    -
    -  assertEquals('http://www.google.com/path',
    -      utils.setFragmentEncoded('http://www.google.com/path', null));
    -}
    -
    -
    -function testGetParamValue() {
    -  assertEquals('v1',
    -      utils.getParamValue('/path?key=v1&c=d&keywithsuffix=v3&key=v2', 'key'));
    -
    -  assertEquals('v1',
    -      utils.getParamValue('/path?kEY=v1&c=d&keywithsuffix=v3&key=v2', 'kEY'));
    -}
    -
    -
    -function testGetParamValues() {
    -  assertArrayEquals('should ignore confusing suffixes', ['v1', 'v2'],
    -      utils.getParamValues(
    -          '/path?a=b&key=v1&c=d&key=v2&keywithsuffix=v3', 'key'));
    -  assertArrayEquals('should be case sensitive', ['v2'],
    -      utils.getParamValues('/path?a=b&keY=v1&c=d&KEy=v2&keywithsuffix=v3',
    -          'KEy'));
    -  assertArrayEquals('should work for the first parameter', ['v1', 'v2'],
    -      utils.getParamValues('/path?key=v1&c=d&key=v2&keywithsuffix=v3', 'key'));
    -  assertArrayEquals('should work for the last parameter', ['v1', 'v2'],
    -      utils.getParamValues('/path?key=v1&c=d&keywithsuffix=v3&key=v2', 'key'));
    -  assertArrayEquals(['1'],
    -      utils.getParamValues('http://foo.com?q=1#?q=2&q=3', 'q'));
    -}
    -
    -
    -function testGetParamValueAllowsEqualInValues() {
    -  assertEquals('equals signs can appear unencoded', 'v1=v2',
    -      utils.getParamValue('/path?key=v1=v2', 'key'));
    -  assertArrayEquals(['v1=v2=v3'],
    -      utils.getParamValues('/path?key=v1=v2=v3', 'key'));
    -}
    -
    -
    -function testGetParamValueNoSuchKey() {
    -  var uri = '/path?key=v1&c=d&keywithsuffix=v3&key=v2';
    -  assertNull(utils.getParamValue(uri, 'nosuchkey'));
    -  assertArrayEquals([], utils.getParamValues(uri, 'nosuchkey'));
    -  assertFalse(utils.hasParam(uri, 'nosuchkey'));
    -  assertNull(utils.getParamValue('q=1', 'q'));
    -  assertEquals('1', utils.getParamValue('?q=1', 'q'));
    -}
    -
    -
    -function testGetParamValueEmptyAndMissingValueStrings() {
    -  assertEquals('', utils.getParamValue('/path?key&bar', 'key'));
    -  assertEquals('', utils.getParamValue('/path?foo=bar&key', 'key'));
    -  assertEquals('', utils.getParamValue('/path?key', 'key'));
    -  assertEquals('', utils.getParamValue('/path?key=', 'key'));
    -  assertArrayEquals([''], utils.getParamValues('/path?key', 'key'));
    -  assertArrayEquals([''], utils.getParamValues('/path?key&bar', 'key'));
    -  assertArrayEquals([''], utils.getParamValues('/path?foo=bar&key', 'key'));
    -  assertArrayEquals([''], utils.getParamValues('/path?foo=bar&key=', 'key'));
    -  assertArrayEquals(['', '', '', 'j', ''],
    -      utils.getParamValues('/path?key&key&key=&key=j&key', 'key'));
    -  assertArrayEquals(['', '', '', '', ''],
    -      utils.getParamValues('/pathqqq?q&qq&q&q=&q&q', 'q'));
    -  assertTrue(utils.hasParam('/path?key=', 'key'));
    -}
    -
    -
    -function testGetParamValueDecoding() {
    -  assertEquals('plus should be supported as alias of space', 'foo bar baz',
    -      utils.getParamValue('/path?key=foo+bar%20baz', 'key'));
    -  assertArrayEquals(['foo bar baz'],
    -      utils.getParamValues('/path?key=foo%20bar%20baz', 'key'));
    -}
    -
    -
    -function testGetParamIgnoresParamsInFragmentIdentifiers() {
    -  assertFalse(utils.hasParam('/path?bah#a&key=foo', 'key'));
    -  assertEquals(null, utils.getParamValue('/path?bah#a&key=bar', 'key'));
    -  assertArrayEquals([], utils.getParamValues('/path?bah#a&key=bar', 'key'));
    -}
    -
    -
    -function testGetParamIgnoresExcludesFragmentFromParameterValue() {
    -  // Make sure the '#' doesn't get included anywhere, for parameter values
    -  // of different lengths.
    -  assertEquals('foo',
    -      utils.getParamValue('/path?key=foo#key=bar&key=baz', 'key'));
    -  assertArrayEquals(['foo'],
    -      utils.getParamValues('/path?key=foo#key=bar&key=baz', 'key'));
    -  assertEquals('',
    -      utils.getParamValue('/path?key#key=bar&key=baz', 'key'));
    -  assertArrayEquals([''],
    -      utils.getParamValues('/path?key#key=bar&key=baz', 'key'));
    -  assertEquals('x',
    -      utils.getParamValue('/path?key=x#key=bar&key=baz', 'key'));
    -  assertArrayEquals(['x'],
    -      utils.getParamValues('/path?key=x#key=bar&key=baz', 'key'));
    -
    -  // Simply make sure hasParam doesn't die in this case.
    -  assertTrue(utils.hasParam('/path?key=foo#key=bar&key=baz', 'key'));
    -  assertTrue(utils.hasParam('/path?key=foo#key&key=baz', 'key'));
    -}
    -
    -
    -function testSameDomainPathsDiffer() {
    -  var uri1 = 'http://www.google.com/a';
    -  var uri2 = 'http://www.google.com/b';
    -  assertTrue(goog.uri.utils.haveSameDomain(uri1, uri2));
    -  assertTrue(goog.uri.utils.haveSameDomain(uri2, uri1));
    -}
    -
    -
    -function testSameDomainSchemesDiffer() {
    -  var uri1 = 'http://www.google.com';
    -  var uri2 = 'https://www.google.com';
    -  assertFalse(goog.uri.utils.haveSameDomain(uri1, uri2));
    -  assertFalse(goog.uri.utils.haveSameDomain(uri2, uri1));
    -}
    -
    -
    -function testSameDomainPortsDiffer() {
    -  var uri1 = 'http://www.google.com:1234/a';
    -  var uri2 = 'http://www.google.com/b';
    -  var uri3 = 'http://www.google.com:2345/b';
    -  assertFalse(goog.uri.utils.haveSameDomain(uri1, uri2));
    -  assertFalse(goog.uri.utils.haveSameDomain(uri2, uri1));
    -  assertFalse(goog.uri.utils.haveSameDomain(uri1, uri3));
    -}
    -
    -
    -function testSameDomainDomainsDiffer() {
    -  var uri1 = '/a';
    -  var uri2 = 'http://www.google.com/b';
    -  assertFalse(goog.uri.utils.haveSameDomain(uri1, uri2));
    -  assertFalse(goog.uri.utils.haveSameDomain(uri2, uri1));
    -}
    -
    -
    -function testSameDomainSubDomainDiffers() {
    -  var uri1 = 'http://www.google.com/a';
    -  var uri2 = 'http://mail.google.com/b';
    -  assertFalse(goog.uri.utils.haveSameDomain(uri1, uri2));
    -  assertFalse(goog.uri.utils.haveSameDomain(uri2, uri1));
    -}
    -
    -
    -function testSameDomainNoDomain() {
    -  var uri1 = '/a';
    -  var uri2 = '/b';
    -  assertTrue(goog.uri.utils.haveSameDomain(uri1, uri2));
    -  assertTrue(goog.uri.utils.haveSameDomain(uri2, uri1));
    -}
    -
    -
    -
    -/**
    - * Simple class with a constant toString.
    - * @param {string} stringValue The result of toString.
    - * @constructor
    - */
    -function HasString(stringValue) {
    -  this.value_ = stringValue;
    -}
    -
    -
    -/** @override */
    -HasString.prototype.toString = function() {
    -  return this.value_;
    -};
    -
    -
    -function testBuildFromEncodedParts() {
    -  assertEquals('should handle full URL',
    -      'http://foo@www.google.com:80/path?q=query#fragment',
    -      utils.buildFromEncodedParts('http', 'foo', 'www.google.com',
    -          80, '/path', 'q=query', 'fragment'));
    -  assertEquals('should handle unspecified parameters', '/search',
    -      utils.buildFromEncodedParts(null, null, undefined, null, '/search'));
    -  assertEquals('should handle params of non-primitive types',
    -      'http://foo@www.google.com:80/path?q=query#fragment',
    -      utils.buildFromEncodedParts(new HasString('http'), new HasString('foo'),
    -          new HasString('www.google.com'), new HasString('80'),
    -          new HasString('/path'), new HasString('q=query'),
    -          new HasString('fragment')));
    -}
    -
    -
    -function testAppendParam() {
    -  assertEquals('http://foo.com?q=1',
    -      utils.appendParam('http://foo.com', 'q', 1));
    -  assertEquals('http://foo.com?q=1#preserve',
    -      utils.appendParam('http://foo.com#preserve', 'q', 1));
    -  assertEquals('should tolerate a lone question mark',
    -      'http://foo.com?q=1',
    -      utils.appendParam('http://foo.com?', 'q', 1));
    -  assertEquals('http://foo.com?q=1&r=2',
    -      utils.appendParam('http://foo.com?q=1', 'r', 2));
    -  assertEquals('http://foo.com?q=1&r=2&s=3#preserve',
    -      utils.appendParam('http://foo.com?q=1&r=2#preserve', 's', 3));
    -  assertEquals('q=1&r=2&s=3&s=4',
    -      utils.buildQueryData(['q', 1, 'r', 2, 's', [3, 4]]));
    -  assertEquals('',
    -      utils.buildQueryData([]));
    -  assertEquals('?q=1#preserve',
    -      utils.appendParam('#preserve', 'q', 1));
    -}
    -
    -function testAppendParams() {
    -  assertEquals('http://foo.com',
    -      utils.appendParams('http://foo.com'));
    -  assertEquals('http://foo.com?q=1&r=2&s=3&s=4#preserve',
    -      utils.appendParams('http://foo.com#preserve',
    -          'q', 1, 'r', 2, 's', [3, 4]));
    -  assertEquals('http://foo.com?a=1&q=1&r=2&s=3&s=4#preserve',
    -      utils.appendParams('http://foo.com?a=1#preserve',
    -          'q', 1, 'r', 2, 's', [3, 4]));
    -  assertEquals('http://foo.com?q=1&r=2&s=3&s=4#preserve',
    -      utils.appendParams('http://foo.com?#preserve',
    -          'q', 1, 'r', 2, 's', [3, 4]));
    -  assertEquals('?q=1&r=2&s=3&s=4#preserve',
    -      utils.appendParams('#preserve',
    -          'q', 1, 'r', 2, 's', [3, 4]));
    -  assertEquals('A question mark must not be appended if there are no ' +
    -      'parameters, otherwise repeated appends will be broken.',
    -      'http://foo.com#test', utils.appendParams('http://foo.com#test'));
    -  assertEquals('should handle objects with to-string',
    -      'http://foo.com?q=a&r=b',
    -      utils.appendParams('http://foo.com',
    -          'q', new HasString('a'), 'r', [new HasString('b')]));
    -
    -  assertThrows('appendParams should fail with an odd number of arguments.',
    -      function() {
    -        utils.appendParams('http://foo.com', 'a', 1, 'b');
    -      });
    -}
    -
    -
    -function testValuelessParam() {
    -  assertEquals('http://foo.com?q',
    -      utils.appendParam('http://foo.com', 'q'));
    -  assertEquals('http://foo.com?q',
    -      utils.appendParam('http://foo.com', 'q', null /* opt_value */));
    -  assertEquals('http://foo.com?q#preserve',
    -      utils.appendParam('http://foo.com#preserve', 'q'));
    -  assertEquals('should tolerate a lone question mark',
    -      'http://foo.com?q',
    -      utils.appendParam('http://foo.com?', 'q'));
    -  assertEquals('http://foo.com?q=1&r',
    -      utils.appendParam('http://foo.com?q=1', 'r'));
    -  assertEquals('http://foo.com?q=1&r=2&s#preserve',
    -      utils.appendParam('http://foo.com?q=1&r=2#preserve', 's'));
    -  assertTrue(utils.hasParam('http://foo.com?q=1&r=2&s#preserve', 's'));
    -}
    -
    -
    -function testAppendParamsAsArray() {
    -  assertEquals('http://foo.com?q=1&r=2&s=3&s=4#preserve',
    -      utils.appendParams('http://foo.com#preserve',
    -          ['q', 1, 'r', 2, 's', [3, 4]]));
    -  assertEquals('http://foo.com?q=1&s=3&s=4#preserve',
    -      utils.appendParams('http://foo.com#preserve',
    -          ['q', 1, 'r', null, 's', [3, 4]]));
    -  assertEquals('http://foo.com?q=1&s=3&s=4#preserve',
    -      utils.appendParams('http://foo.com#preserve',
    -          ['q', 1, 'r', undefined, 's', [3, 4]]));
    -  assertEquals('http://foo.com?q=1&r=2&s=3&s=4&s=null&s=undefined#preserve',
    -      utils.appendParams('http://foo.com#preserve',
    -          ['q', 1, 'r', 2, 's', [3, new HasString('4'), null, undefined]]));
    -}
    -
    -
    -function testAppendParamEscapes() {
    -  assertEquals('http://foo.com?h=a%20b',
    -      utils.appendParams('http://foo.com', 'h', 'a b'));
    -  assertEquals('h=a%20b', utils.buildQueryData(['h', 'a b']));
    -  assertEquals('h=a%20b', utils.buildQueryDataFromMap({'h': 'a b'}));
    -}
    -
    -
    -function testAppendParamsFromMap() {
    -  var uri = utils.appendParamsFromMap('http://www.foo.com',
    -      {'a': 1, 'b': 'bob', 'c': [1, 2, new HasString('3')]});
    -  assertArrayEquals(['1'], utils.getParamValues(uri, 'a'));
    -  assertArrayEquals(['bob'], utils.getParamValues(uri, 'b'));
    -  assertArrayEquals(['1', '2', '3'], utils.getParamValues(uri, 'c'));
    -}
    -
    -function testBuildQueryDataFromMap() {
    -  assertEquals('a=1', utils.buildQueryDataFromMap({'a': 1}));
    -  var uri = 'foo.com?' + utils.buildQueryDataFromMap(
    -      {'a': 1, 'b': 'bob', 'c': [1, 2, new HasString('3')]});
    -  assertArrayEquals(['1'], utils.getParamValues(uri, 'a'));
    -  assertArrayEquals(['bob'], utils.getParamValues(uri, 'b'));
    -  assertArrayEquals(['1', '2', '3'], utils.getParamValues(uri, 'c'));
    -}
    -
    -
    -function testMultiParamSkipsNullParams() {
    -  // For the multi-param functions, null and undefined keys should be
    -  // skipped, but null within a parameter array should still be appended.
    -  assertEquals('buildQueryDataFromMap', 'a=null',
    -      utils.buildQueryDataFromMap({'a': [null], 'b': null, 'c': undefined}));
    -  assertEquals('buildQueryData', 'a=null',
    -      utils.buildQueryData(['a', [null], 'b', null, 'c', undefined]));
    -  assertEquals('appendParams', 'foo.com?a=null',
    -      utils.appendParams('foo.com', 'a', [null], 'b', null, 'c', undefined));
    -  assertEquals('empty strings should NOT be skipped', 'foo.com?a&b',
    -      utils.appendParams('foo.com', 'a', [''], 'b', ''));
    -}
    -
    -
    -function testRemoveParam() {
    -  assertEquals('remove middle', 'http://foo.com?q=1&s=3',
    -      utils.removeParam('http://foo.com?q=1&r=2&s=3', 'r'));
    -  assertEquals('remove first', 'http://foo.com?r=2&s=3',
    -      utils.removeParam('http://foo.com?q=1&r=2&s=3', 'q'));
    -  assertEquals('remove last', 'http://foo.com?q=1&r=2',
    -      utils.removeParam('http://foo.com?q=1&r=2&s=3', 's'));
    -  assertEquals('remove only param', 'http://foo.com',
    -      utils.removeParam('http://foo.com?q=1', 'q'));
    -}
    -
    -
    -function testRemoveParamWithFragment() {
    -  assertEquals('remove middle', 'http://foo.com?q=1&s=3#?r=1&r=1',
    -      utils.removeParam('http://foo.com?q=1&r=2&s=3#?r=1&r=1', 'r'));
    -  assertEquals('remove first', 'http://foo.com?r=2&s=3#?q=1&q=1',
    -      utils.removeParam('http://foo.com?q=1&r=2&s=3#?q=1&q=1', 'q'));
    -  assertEquals('remove only param', 'http://foo.com#?q=1&q=1',
    -      utils.removeParam('http://foo.com?q=1#?q=1&q=1', 'q'));
    -  assertEquals('remove last', 'http://foo.com?q=1&r=2#?s=1&s=1',
    -      utils.removeParam('http://foo.com?q=1&r=2&s=3#?s=1&s=1', 's'));
    -}
    -
    -
    -function testRemoveNonExistent() {
    -  assertEquals('remove key not present', 'http://foo.com?q=1',
    -      utils.removeParam('http://foo.com?q=1', 'nosuchkey'));
    -  assertEquals('remove key not present', 'http://foo.com#q=1',
    -      utils.removeParam('http://foo.com#q=1', 'q'));
    -  assertEquals('remove key from empty string', '',
    -      utils.removeParam('', 'nosuchkey'));
    -}
    -
    -
    -function testRemoveMultiple() {
    -  assertEquals('remove four of the same', 'http://foo.com',
    -      utils.removeParam('http://foo.com?q=1&q=2&q=3&q=4', 'q'));
    -  assertEquals('remove four of the same with another one in the middle',
    -      'http://foo.com?a=99',
    -      utils.removeParam('http://foo.com?q=1&q=2&a=99&q=3&q=4', 'q'));
    -}
    -
    -
    -function testSetParam() {
    -  assertEquals('middle, no fragment', 'http://foo.com?q=1&s=3&r=999',
    -      utils.setParam('http://foo.com?q=1&r=2&s=3', 'r', 999));
    -  assertEquals('middle', 'http://foo.com?q=1&s=3&r=999#?r=1&r=1',
    -      utils.setParam('http://foo.com?q=1&r=2&s=3#?r=1&r=1', 'r', 999));
    -  assertEquals('first', 'http://foo.com?r=2&s=3&q=999#?q=1&q=1',
    -      utils.setParam('http://foo.com?q=1&r=2&s=3#?q=1&q=1', 'q', 999));
    -  assertEquals('only param', 'http://foo.com?q=999#?q=1&q=1',
    -      utils.setParam('http://foo.com?q=1#?q=1&q=1', 'q', 999));
    -  assertEquals('last', 'http://foo.com?q=1&r=2&s=999#?s=1&s=1',
    -      utils.setParam('http://foo.com?q=1&r=2&s=3#?s=1&s=1', 's', 999));
    -  assertEquals('multiple', 'http://foo.com?s=999#?s=1&s=1',
    -      utils.setParam('http://foo.com?s=1&s=2&s=3#?s=1&s=1', 's', 999));
    -  assertEquals('none', 'http://foo.com?r=1&s=999#?s=1&s=1',
    -      utils.setParam('http://foo.com?r=1#?s=1&s=1', 's', 999));
    -}
    -
    -
    -function testModifyQueryParams() {
    -  var uri = 'http://foo.com?a=A&a=A2&b=B&b=B2&c=C';
    -
    -  uri = utils.appendParam(uri, 'd', 'D');
    -  assertEquals('http://foo.com?a=A&a=A2&b=B&b=B2&c=C&d=D', uri);
    -
    -  uri = utils.removeParam(uri, 'd');
    -  uri = utils.appendParam(uri, 'd', 'D2');
    -  assertEquals('http://foo.com?a=A&a=A2&b=B&b=B2&c=C&d=D2', uri);
    -
    -  uri = utils.removeParam(uri, 'a');
    -  uri = utils.appendParam(uri, 'a', 'A3');
    -  assertEquals('http://foo.com?b=B&b=B2&c=C&d=D2&a=A3', uri);
    -
    -  uri = utils.removeParam(uri, 'a');
    -  uri = utils.appendParam(uri, 'a', 'A4');
    -  assertEquals('A4', utils.getParamValue(uri, 'a'));
    -}
    -
    -
    -function testBrowserEncoding() {
    -  // Sanity check borrowed from old code to ensure that encodeURIComponent
    -  // is good enough.  Entire test should be safe to delete.
    -  var allowedInFragment = /[A-Za-z0-9\-\._~!$&'()*+,;=:@/?]/g;
    -
    -  var sb = [];
    -  for (var i = 33; i < 500; i++) {  // arbitrarily use first 500 chars.
    -    sb.push(String.fromCharCode(i));
    -  }
    -  var testString = sb.join('');
    -
    -  var encodedStr = encodeURIComponent(testString);
    -
    -  // Strip all percent encoded characters, as they're ok.
    -  encodedStr = encodedStr.replace(/%[0-9A-F][0-9A-F]/g, '');
    -
    -  // Remove allowed characters.
    -  encodedStr = encodedStr.replace(allowedInFragment, '');
    -
    -  // Only illegal characters should remain, which is a fail.
    -  assertEquals('String should be empty', 0, encodedStr.length);
    -}
    -
    -
    -function testAppendPath() {
    -  var uri = 'http://www.foo.com';
    -  var expected = uri + '/dummy';
    -  assertEquals('Path has no trailing "/", adding with leading "/" failed',
    -      expected,
    -      goog.uri.utils.appendPath(uri, '/dummy'));
    -  assertEquals('Path has no trailing "/", adding with no leading "/" failed',
    -      expected,
    -      goog.uri.utils.appendPath(uri, 'dummy'));
    -  uri = uri + '/';
    -  assertEquals('Path has trailing "/", adding with leading "/" failed',
    -      expected,
    -      goog.uri.utils.appendPath(uri, '/dummy'));
    -
    -  assertEquals('Path has trailing "/", adding with no leading "/" failed',
    -      expected,
    -      goog.uri.utils.appendPath(uri, 'dummy'));
    -}
    -
    -
    -function testMakeUnique() {
    -  assertEquals('http://www.google.com?zx=RANDOM#blob',
    -      goog.uri.utils.makeUnique('http://www.google.com#blob'));
    -  assertEquals('http://www.google.com?a=1&b=2&zx=RANDOM#blob',
    -      goog.uri.utils.makeUnique('http://www.google.com?zx=9&a=1&b=2#blob'));
    -}
    -
    -
    -function testParseQuery() {
    -  var result = [];
    -  goog.uri.utils.parseQueryData(
    -      'foo=bar&no&empty=&tricky%3D%26=%3D%26&=nothing&=&',
    -      function(name, value) { result.push(name, value); });
    -  assertArrayEquals(
    -      ['foo', 'bar',
    -       'no', '',
    -       'empty', '',
    -       'tricky%3D%26', '=&',
    -       '', 'nothing',
    -       '', '',
    -       '', ''],
    -      result);
    -
    -  // Go thought buildQueryData and parseQueryData and see if we get the same
    -  // result.
    -  var result2 = [];
    -  goog.uri.utils.parseQueryData(
    -      goog.uri.utils.buildQueryData(result),
    -      function(name, value) { result2.push(name, value); });
    -  assertArrayEquals(result, result2);
    -}
    -
    -
    diff --git a/src/database/third_party/closure-library/closure/goog/useragent/adobereader.js b/src/database/third_party/closure-library/closure/goog/useragent/adobereader.js
    deleted file mode 100644
    index 72ad22f8ad6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/useragent/adobereader.js
    +++ /dev/null
    @@ -1,90 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Detects the Adobe Reader PDF browser plugin.
    - *
    - * @author chrisn@google.com (Chris Nokleberg)
    - * @see ../demos/useragent.html
    - */
    -
    -/** @suppress {extraProvide} */
    -goog.provide('goog.userAgent.adobeReader');
    -
    -goog.require('goog.string');
    -goog.require('goog.userAgent');
    -
    -
    -(function() {
    -  var version = '';
    -  if (goog.userAgent.IE) {
    -    var detectOnIe = function(classId) {
    -      /** @preserveTry */
    -      try {
    -        new ActiveXObject(classId);
    -        return true;
    -      } catch (ex) {
    -        return false;
    -      }
    -    };
    -    if (detectOnIe('AcroPDF.PDF.1')) {
    -      version = '7';
    -    } else if (detectOnIe('PDF.PdfCtrl.6')) {
    -      version = '6';
    -    }
    -    // TODO(chrisn): Add detection for previous versions if anyone needs them.
    -  } else {
    -    if (navigator.mimeTypes && navigator.mimeTypes.length > 0) {
    -      var mimeType = navigator.mimeTypes['application/pdf'];
    -      if (mimeType && mimeType.enabledPlugin) {
    -        var description = mimeType.enabledPlugin.description;
    -        if (description && description.indexOf('Adobe') != -1) {
    -          // Newer plugins do not include the version in the description, so we
    -          // default to 7.
    -          version = description.indexOf('Version') != -1 ?
    -              description.split('Version')[1] : '7';
    -        }
    -      }
    -    }
    -  }
    -
    -  /**
    -   * Whether we detect the user has the Adobe Reader browser plugin installed.
    -   * @type {boolean}
    -   */
    -  goog.userAgent.adobeReader.HAS_READER = !!version;
    -
    -
    -  /**
    -   * The version of the installed Adobe Reader plugin. Versions after 7
    -   * will all be reported as '7'.
    -   * @type {string}
    -   */
    -  goog.userAgent.adobeReader.VERSION = version;
    -
    -
    -  /**
    -   * On certain combinations of platform/browser/plugin, a print dialog
    -   * can be shown for PDF files without a download dialog or making the
    -   * PDF visible to the user, by loading the PDF into a hidden iframe.
    -   *
    -   * Currently this variable is true if Adobe Reader version 6 or later
    -   * is detected on Windows.
    -   *
    -   * @type {boolean}
    -   */
    -  goog.userAgent.adobeReader.SILENT_PRINT = goog.userAgent.WINDOWS &&
    -      goog.string.compareVersions(version, '6') >= 0;
    -
    -})();
    diff --git a/src/database/third_party/closure-library/closure/goog/useragent/adobereader_test.html b/src/database/third_party/closure-library/closure/goog/useragent/adobereader_test.html
    deleted file mode 100644
    index 0e29db5ecd4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/useragent/adobereader_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.userAgent.adobeReader
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.userAgent.adobeReaderTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/useragent/adobereader_test.js b/src/database/third_party/closure-library/closure/goog/useragent/adobereader_test.js
    deleted file mode 100644
    index c5b8d7ac55b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/useragent/adobereader_test.js
    +++ /dev/null
    @@ -1,29 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.userAgent.adobeReaderTest');
    -goog.setTestOnly('goog.userAgent.adobeReaderTest');
    -
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent.adobeReader');
    -
    -// For now, just test that the variables exist, the test runner will
    -// pick up any runtime errors.
    -// TODO(chrisn): Mock out each browser implementation and test the code path
    -// correctly detects the version for each case.
    -function testAdobeReader() {
    -  assertNotUndefined(goog.userAgent.adobeReader.HAS_READER);
    -  assertNotUndefined(goog.userAgent.adobeReader.VERSION);
    -  assertNotUndefined(goog.userAgent.adobeReader.SILENT_PRINT);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/useragent/flash.js b/src/database/third_party/closure-library/closure/goog/useragent/flash.js
    deleted file mode 100644
    index 69d8f1e0946..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/useragent/flash.js
    +++ /dev/null
    @@ -1,156 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Flash detection.
    - * @see ../demos/useragent.html
    - */
    -
    -goog.provide('goog.userAgent.flash');
    -
    -goog.require('goog.string');
    -
    -
    -/**
    - * @define {boolean} Whether we know at compile-time that the browser doesn't
    - * have flash.
    - */
    -goog.define('goog.userAgent.flash.ASSUME_NO_FLASH', false);
    -
    -
    -/**
    - * Whether we can detect that the browser has flash
    - * @type {boolean}
    - * @private
    - */
    -goog.userAgent.flash.detectedFlash_ = false;
    -
    -
    -/**
    - * Full version information of flash installed, in form 7.0.61
    - * @type {string}
    - * @private
    - */
    -goog.userAgent.flash.detectedFlashVersion_ = '';
    -
    -
    -/**
    - * Initializer for goog.userAgent.flash
    - *
    - * This is a named function so that it can be stripped via the jscompiler if
    - * goog.userAgent.flash.ASSUME_NO_FLASH is true.
    - * @private
    - */
    -goog.userAgent.flash.init_ = function() {
    -  if (navigator.plugins && navigator.plugins.length) {
    -    var plugin = navigator.plugins['Shockwave Flash'];
    -    if (plugin) {
    -      goog.userAgent.flash.detectedFlash_ = true;
    -      if (plugin.description) {
    -        goog.userAgent.flash.detectedFlashVersion_ =
    -            goog.userAgent.flash.getVersion_(plugin.description);
    -      }
    -    }
    -
    -    if (navigator.plugins['Shockwave Flash 2.0']) {
    -      goog.userAgent.flash.detectedFlash_ = true;
    -      goog.userAgent.flash.detectedFlashVersion_ = '2.0.0.11';
    -    }
    -
    -  } else if (navigator.mimeTypes && navigator.mimeTypes.length) {
    -    var mimeType = navigator.mimeTypes['application/x-shockwave-flash'];
    -    goog.userAgent.flash.detectedFlash_ = mimeType && mimeType.enabledPlugin;
    -    if (goog.userAgent.flash.detectedFlash_) {
    -      goog.userAgent.flash.detectedFlashVersion_ =
    -          goog.userAgent.flash.getVersion_(mimeType.enabledPlugin.description);
    -    }
    -
    -  } else {
    -    /** @preserveTry */
    -    try {
    -      // Try 7 first, since we know we can use GetVariable with it
    -      var ax = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.7');
    -      goog.userAgent.flash.detectedFlash_ = true;
    -      goog.userAgent.flash.detectedFlashVersion_ =
    -          goog.userAgent.flash.getVersion_(ax.GetVariable('$version'));
    -    } catch (e) {
    -      // Try 6 next, some versions are known to crash with GetVariable calls
    -      /** @preserveTry */
    -      try {
    -        var ax = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.6');
    -        goog.userAgent.flash.detectedFlash_ = true;
    -        // First public version of Flash 6
    -        goog.userAgent.flash.detectedFlashVersion_ = '6.0.21';
    -      } catch (e2) {
    -        /** @preserveTry */
    -        try {
    -          // Try the default activeX
    -          var ax = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');
    -          goog.userAgent.flash.detectedFlash_ = true;
    -          goog.userAgent.flash.detectedFlashVersion_ =
    -              goog.userAgent.flash.getVersion_(ax.GetVariable('$version'));
    -        } catch (e3) {
    -          // No flash
    -        }
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * Derived from Apple's suggested sniffer.
    - * @param {string} desc e.g. Shockwave Flash 7.0 r61.
    - * @return {string} 7.0.61.
    - * @private
    - */
    -goog.userAgent.flash.getVersion_ = function(desc) {
    -  var matches = desc.match(/[\d]+/g);
    -  if (!matches) {
    -    return '';
    -  }
    -  matches.length = 3;  // To standardize IE vs FF
    -  return matches.join('.');
    -};
    -
    -
    -if (!goog.userAgent.flash.ASSUME_NO_FLASH) {
    -  goog.userAgent.flash.init_();
    -}
    -
    -
    -/**
    - * Whether we can detect that the browser has flash
    - * @type {boolean}
    - */
    -goog.userAgent.flash.HAS_FLASH = goog.userAgent.flash.detectedFlash_;
    -
    -
    -/**
    - * Full version information of flash installed, in form 7.0.61
    - * @type {string}
    - */
    -goog.userAgent.flash.VERSION = goog.userAgent.flash.detectedFlashVersion_;
    -
    -
    -/**
    - * Whether the installed flash version is as new or newer than a given version.
    - * @param {string} version The version to check.
    - * @return {boolean} Whether the installed flash version is as new or newer
    - *     than a given version.
    - */
    -goog.userAgent.flash.isVersion = function(version) {
    -  return goog.string.compareVersions(goog.userAgent.flash.VERSION,
    -                                     version) >= 0;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/useragent/flash_test.html b/src/database/third_party/closure-library/closure/goog/useragent/flash_test.html
    deleted file mode 100644
    index 699559a9003..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/useragent/flash_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.userAgent.flash
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.userAgent.flashTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/useragent/flash_test.js b/src/database/third_party/closure-library/closure/goog/useragent/flash_test.js
    deleted file mode 100644
    index ea719f585a0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/useragent/flash_test.js
    +++ /dev/null
    @@ -1,29 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.userAgent.flashTest');
    -goog.setTestOnly('goog.userAgent.flashTest');
    -
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent.flash');
    -
    -// For now, just test that the flash variables exist, the test runner will
    -// pick up any runtime errors.
    -// TODO(user): Mock out each browser implementation and test the code path
    -// correctly detects the flash version for each case.
    -function testFlash() {
    -  assertNotUndefined(goog.userAgent.flash.HAS_FLASH);
    -  assertNotUndefined(goog.userAgent.flash.VERSION);
    -  assertEquals(typeof goog.userAgent.flash.isVersion('5'), 'boolean');
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/useragent/iphoto.js b/src/database/third_party/closure-library/closure/goog/useragent/iphoto.js
    deleted file mode 100644
    index 7b315c9cc99..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/useragent/iphoto.js
    +++ /dev/null
    @@ -1,87 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Newer versions of iPhoto include a Safari plugin which allows
    - * the browser to detect if iPhoto is installed. Adapted from detection code
    - * built into the Mac.com Gallery RSS feeds.
    - * @author brenneman@google.com (Shawn Brenneman)
    - * @see ../demos/useragent.html
    - */
    -
    -
    -goog.provide('goog.userAgent.iphoto');
    -
    -goog.require('goog.string');
    -goog.require('goog.userAgent');
    -
    -
    -(function() {
    -  var hasIphoto = false;
    -  var version = '';
    -
    -  /**
    -   * The plugin description string contains the version number as in the form
    -   * 'iPhoto 700'. This returns just the version number as a dotted string,
    -   * e.g., '7.0.0', compatible with {@code goog.string.compareVersions}.
    -   * @param {string} desc The version string.
    -   * @return {string} The dotted version.
    -   */
    -  function getIphotoVersion(desc) {
    -    var matches = desc.match(/\d/g);
    -    return matches.join('.');
    -  }
    -
    -  if (goog.userAgent.WEBKIT &&
    -      navigator.mimeTypes &&
    -      navigator.mimeTypes.length > 0) {
    -    var iphoto = navigator.mimeTypes['application/photo'];
    -
    -    if (iphoto) {
    -      hasIphoto = true;
    -      var description = iphoto['description'];
    -
    -      if (description) {
    -        version = getIphotoVersion(description);
    -      }
    -    }
    -  }
    -
    -  /**
    -   * Whether we can detect that the user has iPhoto installed.
    -   * @type {boolean}
    -   */
    -  goog.userAgent.iphoto.HAS_IPHOTO = hasIphoto;
    -
    -
    -  /**
    -   * The version of iPhoto installed if found.
    -   * @type {string}
    -   */
    -  goog.userAgent.iphoto.VERSION = version;
    -
    -})();
    -
    -
    -/**
    - * Whether the installed version of iPhoto is as new or newer than a given
    - * version.
    - * @param {string} version The version to check.
    - * @return {boolean} Whether the installed version of iPhoto is as new or newer
    - *     than a given version.
    - */
    -goog.userAgent.iphoto.isVersion = function(version) {
    -  return goog.string.compareVersions(
    -      goog.userAgent.iphoto.VERSION, version) >= 0;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/useragent/jscript.js b/src/database/third_party/closure-library/closure/goog/useragent/jscript.js
    deleted file mode 100644
    index b1a9ca99b43..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/useragent/jscript.js
    +++ /dev/null
    @@ -1,95 +0,0 @@
    -// Copyright 2007 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Detection of JScript version.
    - *
    - * @author arv@google.com (Erik Arvidsson)
    - */
    -
    -
    -goog.provide('goog.userAgent.jscript');
    -
    -goog.require('goog.string');
    -
    -
    -/**
    - * @define {boolean} True if it is known at compile time that the runtime
    - *     environment will not be using JScript.
    - */
    -goog.define('goog.userAgent.jscript.ASSUME_NO_JSCRIPT', false);
    -
    -
    -/**
    - * Initializer for goog.userAgent.jscript.  Detects if the user agent is using
    - * Microsoft JScript and which version of it.
    - *
    - * This is a named function so that it can be stripped via the jscompiler
    - * option for stripping types.
    - * @private
    - */
    -goog.userAgent.jscript.init_ = function() {
    -  var hasScriptEngine = 'ScriptEngine' in goog.global;
    -
    -  /**
    -   * @type {boolean}
    -   * @private
    -   */
    -  goog.userAgent.jscript.DETECTED_HAS_JSCRIPT_ =
    -      hasScriptEngine && goog.global['ScriptEngine']() == 'JScript';
    -
    -  /**
    -   * @type {string}
    -   * @private
    -   */
    -  goog.userAgent.jscript.DETECTED_VERSION_ =
    -      goog.userAgent.jscript.DETECTED_HAS_JSCRIPT_ ?
    -      (goog.global['ScriptEngineMajorVersion']() + '.' +
    -       goog.global['ScriptEngineMinorVersion']() + '.' +
    -       goog.global['ScriptEngineBuildVersion']()) :
    -      '0';
    -};
    -
    -if (!goog.userAgent.jscript.ASSUME_NO_JSCRIPT) {
    -  goog.userAgent.jscript.init_();
    -}
    -
    -
    -/**
    - * Whether we detect that the user agent is using Microsoft JScript.
    - * @type {boolean}
    - */
    -goog.userAgent.jscript.HAS_JSCRIPT = goog.userAgent.jscript.ASSUME_NO_JSCRIPT ?
    -    false : goog.userAgent.jscript.DETECTED_HAS_JSCRIPT_;
    -
    -
    -/**
    - * The installed version of JScript.
    - * @type {string}
    - */
    -goog.userAgent.jscript.VERSION = goog.userAgent.jscript.ASSUME_NO_JSCRIPT ?
    -    '0' : goog.userAgent.jscript.DETECTED_VERSION_;
    -
    -
    -/**
    - * Whether the installed version of JScript is as new or newer than a given
    - * version.
    - * @param {string} version The version to check.
    - * @return {boolean} Whether the installed version of JScript is as new or
    - *     newer than the given version.
    - */
    -goog.userAgent.jscript.isVersion = function(version) {
    -  return goog.string.compareVersions(goog.userAgent.jscript.VERSION,
    -                                     version) >= 0;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/useragent/jscript_test.html b/src/database/third_party/closure-library/closure/goog/useragent/jscript_test.html
    deleted file mode 100644
    index 529b198d741..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/useragent/jscript_test.html
    +++ /dev/null
    @@ -1,41 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.userAgent.jscript
    -  </title>
    -  <script>
    -// Mock JScript functions
    -
    -function ScriptEngine() {
    -  return 'JScript';
    -}
    -
    -function ScriptEngineMajorVersion() {
    -  return 1;
    -}
    -
    -function ScriptEngineMinorVersion() {
    -  return 2;
    -}
    -
    -function ScriptEngineBuildVersion() {
    -  return 3456;
    -}
    -  </script>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.userAgent.jscriptTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/useragent/jscript_test.js b/src/database/third_party/closure-library/closure/goog/useragent/jscript_test.js
    deleted file mode 100644
    index e92ff4b7d43..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/useragent/jscript_test.js
    +++ /dev/null
    @@ -1,54 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -// Mock JScript functions
    -goog.provide('goog.userAgent.jscriptTest');
    -goog.setTestOnly('goog.userAgent.jscriptTest');
    -
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent.jscript');
    -
    -function ScriptEngine() {
    -  return 'JScript';
    -}
    -
    -function ScriptEngineMajorVersion() {
    -  return 1;
    -}
    -
    -function ScriptEngineMinorVersion() {
    -  return 2;
    -}
    -
    -function ScriptEngineBuildVersion() {
    -  return 3456;
    -}
    -
    -function testHasJscript() {
    -  assertTrue('Should have jscript', goog.userAgent.jscript.HAS_JSCRIPT);
    -}
    -
    -function testVersion() {
    -  assertEquals('Version should be 1.2.3456', '1.2.3456',
    -               goog.userAgent.jscript.VERSION);
    -}
    -
    -function testIsVersion() {
    -  assertTrue('Should be version 1.2.3456 or larger',
    -             goog.userAgent.jscript.isVersion('1.2.3456'));
    -  assertTrue('Should be version 1.2 or larger',
    -             goog.userAgent.jscript.isVersion('1.2'));
    -  assertFalse('Should not be version 8.9 or larger',
    -      goog.userAgent.jscript.isVersion('8.9'));
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/useragent/keyboard.js b/src/database/third_party/closure-library/closure/goog/useragent/keyboard.js
    deleted file mode 100644
    index b062b55bee9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/useragent/keyboard.js
    +++ /dev/null
    @@ -1,49 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Constants for determining keyboard support.
    - */
    -
    -goog.provide('goog.userAgent.keyboard');
    -
    -goog.require('goog.labs.userAgent.platform');
    -
    -
    -/**
    - * @define {boolean} Whether the user agent is running with in an environment
    - * that should use Mac-based keyboard shortcuts (Meta instead of Ctrl, etc.).
    - */
    -goog.define('goog.userAgent.keyboard.ASSUME_MAC_KEYBOARD', false);
    -
    -
    -/**
    - * Determines whether Mac-based keyboard shortcuts should be used.
    - * @return {boolean}
    - * @private
    - */
    -goog.userAgent.keyboard.determineMacKeyboard_ = function() {
    -  return goog.labs.userAgent.platform.isMacintosh() ||
    -      goog.labs.userAgent.platform.isIos();
    -};
    -
    -
    -/**
    - * Whether the user agent is running in an environment that uses Mac-based
    - * keyboard shortcuts.
    - * @type {boolean}
    - */
    -goog.userAgent.keyboard.MAC_KEYBOARD =
    -    goog.userAgent.keyboard.ASSUME_MAC_KEYBOARD ||
    -    goog.userAgent.keyboard.determineMacKeyboard_();
    diff --git a/src/database/third_party/closure-library/closure/goog/useragent/keyboard_test.js b/src/database/third_party/closure-library/closure/goog/useragent/keyboard_test.js
    deleted file mode 100644
    index e017d6a3cbb..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/useragent/keyboard_test.js
    +++ /dev/null
    @@ -1,225 +0,0 @@
    -// Copyright 2014 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.userAgent.keyboardTest');
    -goog.setTestOnly('goog.userAgent.keyboardTest');
    -
    -goog.require('goog.labs.userAgent.testAgents');
    -goog.require('goog.labs.userAgent.util');
    -goog.require('goog.testing.MockUserAgent');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent.keyboard');
    -goog.require('goog.userAgentTestUtil');
    -
    -
    -var mockAgent;
    -
    -function setUp() {
    -  mockAgent = new goog.testing.MockUserAgent();
    -  mockAgent.install();
    -}
    -
    -function tearDown() {
    -  mockAgent.dispose();
    -  goog.labs.userAgent.util.setUserAgent(null);
    -  goog.userAgentTestUtil.reinitializeUserAgent();
    -}
    -
    -function testAndroid() {
    -  mockAgent.setNavigator({platform: 'Linux'});
    -
    -  setUserAgent(goog.labs.userAgent.testAgents.ANDROID_BROWSER_235);
    -  assertFalse(goog.userAgent.keyboard.MAC_KEYBOARD);
    -
    -  setUserAgent(goog.labs.userAgent.testAgents.ANDROID_BROWSER_221);
    -  assertFalse(goog.userAgent.keyboard.MAC_KEYBOARD);
    -
    -  setUserAgent(goog.labs.userAgent.testAgents.ANDROID_BROWSER_233);
    -  assertFalse(goog.userAgent.keyboard.MAC_KEYBOARD);
    -
    -  setUserAgent(goog.labs.userAgent.testAgents.ANDROID_BROWSER_403);
    -  assertFalse(goog.userAgent.keyboard.MAC_KEYBOARD);
    -
    -  setUserAgent(goog.labs.userAgent.testAgents.ANDROID_BROWSER_403_ALT);
    -  assertFalse(goog.userAgent.keyboard.MAC_KEYBOARD);
    -}
    -
    -function testIe() {
    -  mockAgent.setNavigator({platform: 'Windows'});
    -
    -  setUserAgent(goog.labs.userAgent.testAgents.IE_6);
    -  assertFalse(goog.userAgent.keyboard.MAC_KEYBOARD);
    -
    -  setUserAgent(goog.labs.userAgent.testAgents.IE_7);
    -  assertFalse(goog.userAgent.keyboard.MAC_KEYBOARD);
    -
    -  setUserAgent(goog.labs.userAgent.testAgents.IE_8);
    -  assertFalse(goog.userAgent.keyboard.MAC_KEYBOARD);
    -
    -  setUserAgent(
    -      goog.labs.userAgent.testAgents.IE_8_COMPATIBILITY);
    -  assertFalse(goog.userAgent.keyboard.MAC_KEYBOARD);
    -
    -  setUserAgent(goog.labs.userAgent.testAgents.IE_9);
    -  assertFalse(goog.userAgent.keyboard.MAC_KEYBOARD);
    -
    -  setUserAgent(goog.labs.userAgent.testAgents.IE_10);
    -  assertFalse(goog.userAgent.keyboard.MAC_KEYBOARD);
    -
    -  setUserAgent(
    -      goog.labs.userAgent.testAgents.IE_10_COMPATIBILITY);
    -  assertFalse(goog.userAgent.keyboard.MAC_KEYBOARD);
    -
    -  setUserAgent(goog.labs.userAgent.testAgents.IE_11);
    -  assertFalse(goog.userAgent.keyboard.MAC_KEYBOARD);
    -
    -  setUserAgent(
    -      goog.labs.userAgent.testAgents.IE_11_COMPATIBILITY_MSIE_7);
    -  assertFalse(goog.userAgent.keyboard.MAC_KEYBOARD);
    -
    -  setUserAgent(
    -      goog.labs.userAgent.testAgents.IE_11_COMPATIBILITY_MSIE_9);
    -  assertFalse(goog.userAgent.keyboard.MAC_KEYBOARD);
    -}
    -
    -function testFirefoxMac() {
    -  mockAgent.setNavigator({platform: 'Macintosh'});
    -  setUserAgent(
    -      goog.labs.userAgent.testAgents.FIREFOX_MAC);
    -  assertTrue(goog.userAgent.keyboard.MAC_KEYBOARD);
    -}
    -
    -function testFirefoxNotMac() {
    -  mockAgent.setNavigator({platform: 'X11'});
    -  setUserAgent(
    -      goog.labs.userAgent.testAgents.FIREFOX_LINUX);
    -  assertFalse(goog.userAgent.keyboard.MAC_KEYBOARD);
    -
    -  mockAgent.setNavigator({platform: 'Windows'});
    -  setUserAgent(
    -      goog.labs.userAgent.testAgents.FIREFOX_WINDOWS);
    -  assertFalse(goog.userAgent.keyboard.MAC_KEYBOARD);
    -}
    -
    -function testSafari() {
    -  mockAgent.setNavigator({platform: 'Macintosh'});
    -  setUserAgent(
    -      goog.labs.userAgent.testAgents.SAFARI_6);
    -  assertTrue(goog.userAgent.keyboard.MAC_KEYBOARD);
    -
    -  setUserAgent(
    -      goog.labs.userAgent.testAgents.SAFARI_MAC);
    -  assertTrue(goog.userAgent.keyboard.MAC_KEYBOARD);
    -
    -  mockAgent.setNavigator({platform: 'iPhone'});
    -  setUserAgent(
    -      goog.labs.userAgent.testAgents.SAFARI_IPHONE_32);
    -  assertTrue(goog.userAgent.keyboard.MAC_KEYBOARD);
    -
    -  setUserAgent(
    -      goog.labs.userAgent.testAgents.SAFARI_IPHONE_421);
    -  assertTrue(goog.userAgent.keyboard.MAC_KEYBOARD);
    -
    -  setUserAgent(
    -      goog.labs.userAgent.testAgents.SAFARI_IPHONE_431);
    -  assertTrue(goog.userAgent.keyboard.MAC_KEYBOARD);
    -
    -  setUserAgent(
    -      goog.labs.userAgent.testAgents.SAFARI_IPHONE_6);
    -  assertTrue(goog.userAgent.keyboard.MAC_KEYBOARD);
    -
    -  mockAgent.setNavigator({platform: 'iPod'});
    -  setUserAgent(
    -      goog.labs.userAgent.testAgents.SAFARI_IPOD);
    -  assertTrue(goog.userAgent.keyboard.MAC_KEYBOARD);
    -}
    -
    -function testSafariWndows() {
    -  mockAgent.setNavigator({platform: 'Macintosh'});
    -  setUserAgent(
    -      goog.labs.userAgent.testAgents.SAFARI_WINDOWS);
    -  assertFalse(goog.userAgent.keyboard.MAC_KEYBOARD);
    -}
    -
    -function testOperaMac() {
    -  mockAgent.setNavigator({platform: 'Macintosh'});
    -  setUserAgent(
    -      goog.labs.userAgent.testAgents.OPERA_MAC);
    -  assertTrue(goog.userAgent.keyboard.MAC_KEYBOARD);
    -}
    -
    -function testOperaNonMac() {
    -  mockAgent.setNavigator({platform: 'X11'});
    -  setUserAgent(
    -      goog.labs.userAgent.testAgents.OPERA_LINUX);
    -  assertFalse(goog.userAgent.keyboard.MAC_KEYBOARD);
    -
    -  mockAgent.setNavigator({platform: 'Windows'});
    -  setUserAgent(
    -      goog.labs.userAgent.testAgents.OPERA_15);
    -  assertFalse(goog.userAgent.keyboard.MAC_KEYBOARD);
    -}
    -
    -function testIPad() {
    -  mockAgent.setNavigator({platform: 'iPad'});
    -  setUserAgent(goog.labs.userAgent.testAgents.IPAD_4);
    -  assertTrue(goog.userAgent.keyboard.MAC_KEYBOARD);
    -
    -  setUserAgent(goog.labs.userAgent.testAgents.IPAD_5);
    -  assertTrue(goog.userAgent.keyboard.MAC_KEYBOARD);
    -
    -  setUserAgent(goog.labs.userAgent.testAgents.IPAD_6);
    -  assertTrue(goog.userAgent.keyboard.MAC_KEYBOARD);
    -}
    -
    -function testChromeMac() {
    -  mockAgent.setNavigator({platform: 'Macintosh'});
    -  setUserAgent(
    -      goog.labs.userAgent.testAgents.CHROME_MAC);
    -  assertTrue(goog.userAgent.keyboard.MAC_KEYBOARD);
    -
    -  mockAgent.setNavigator({platform: 'iPhone'});
    -  setUserAgent(
    -      goog.labs.userAgent.testAgents.CHROME_IPHONE);
    -  assertTrue(goog.userAgent.keyboard.MAC_KEYBOARD);
    -}
    -
    -function testChromeNonMac() {
    -  mockAgent.setNavigator({platform: 'Linux'});
    -  setUserAgent(
    -      goog.labs.userAgent.testAgents.CHROME_ANDROID);
    -  assertFalse(goog.userAgent.keyboard.MAC_KEYBOARD);
    -
    -  mockAgent.setNavigator({platform: 'X11'});
    -  setUserAgent(
    -      goog.labs.userAgent.testAgents.CHROME_OS);
    -  assertFalse(goog.userAgent.keyboard.MAC_KEYBOARD);
    -
    -  mockAgent.setNavigator({platform: 'X11'});
    -  setUserAgent(
    -      goog.labs.userAgent.testAgents.CHROME_LINUX);
    -  assertFalse(goog.userAgent.keyboard.MAC_KEYBOARD);
    -
    -  mockAgent.setNavigator({platform: 'Windows'});
    -  setUserAgent(
    -      goog.labs.userAgent.testAgents.CHROME_25);
    -
    -  assertFalse(goog.userAgent.keyboard.MAC_KEYBOARD);
    -}
    -
    -function setUserAgent(ua) {
    -  mockAgent.setUserAgentString(ua);
    -  goog.labs.userAgent.util.setUserAgent(ua);
    -  goog.userAgentTestUtil.reinitializeUserAgent();
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/useragent/platform.js b/src/database/third_party/closure-library/closure/goog/useragent/platform.js
    deleted file mode 100644
    index 50212b3fdca..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/useragent/platform.js
    +++ /dev/null
    @@ -1,83 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Utilities for getting details about the user's platform.
    - */
    -
    -goog.provide('goog.userAgent.platform');
    -
    -goog.require('goog.string');
    -goog.require('goog.userAgent');
    -
    -
    -/**
    - * Detects the version of Windows or Mac OS that is running.
    - *
    - * @private
    - * @return {string} The platform version.
    - */
    -goog.userAgent.platform.determineVersion_ = function() {
    -  var re;
    -  if (goog.userAgent.WINDOWS) {
    -    re = /Windows NT ([0-9.]+)/;
    -    var match = re.exec(goog.userAgent.getUserAgentString());
    -    if (match) {
    -      return match[1];
    -    } else {
    -      return '0';
    -    }
    -  } else if (goog.userAgent.MAC) {
    -    re = /10[_.][0-9_.]+/;
    -    var match = re.exec(goog.userAgent.getUserAgentString());
    -    // Note: some old versions of Camino do not report an OSX version.
    -    // Default to 10.
    -    return match ? match[0].replace(/_/g, '.') : '10';
    -  } else if (goog.userAgent.ANDROID) {
    -    re = /Android\s+([^\);]+)(\)|;)/;
    -    var match = re.exec(goog.userAgent.getUserAgentString());
    -    return match ? match[1] : '';
    -  } else if (goog.userAgent.IPHONE || goog.userAgent.IPAD) {
    -    re = /(?:iPhone|CPU)\s+OS\s+(\S+)/;
    -    var match = re.exec(goog.userAgent.getUserAgentString());
    -    // Report the version as x.y.z and not x_y_z
    -    return match ? match[1].replace(/_/g, '.') : '';
    -  }
    -
    -  return '';
    -};
    -
    -
    -/**
    - * The version of the platform. We only determine the version for Windows and
    - * Mac, since it doesn't make much sense on Linux. For Windows, we only look at
    - * the NT version. Non-NT-based versions (e.g. 95, 98, etc.) are given version
    - * 0.0
    - * @type {string}
    - */
    -goog.userAgent.platform.VERSION = goog.userAgent.platform.determineVersion_();
    -
    -
    -/**
    - * Whether the user agent platform version is higher or the same as the given
    - * version.
    - *
    - * @param {string|number} version The version to check.
    - * @return {boolean} Whether the user agent platform version is higher or the
    - *     same as the given version.
    - */
    -goog.userAgent.platform.isVersion = function(version) {
    -  return goog.string.compareVersions(
    -      goog.userAgent.platform.VERSION, version) >= 0;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/useragent/platform_test.html b/src/database/third_party/closure-library/closure/goog/useragent/platform_test.html
    deleted file mode 100644
    index c020b46f3b5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/useragent/platform_test.html
    +++ /dev/null
    @@ -1,26 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -
    -  @author mpd@google.com (Michael Davidson)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.userAgent.platform
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.userAgent.platformTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/useragent/platform_test.js b/src/database/third_party/closure-library/closure/goog/useragent/platform_test.js
    deleted file mode 100644
    index 30fcf9cfa1d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/useragent/platform_test.js
    +++ /dev/null
    @@ -1,151 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.userAgent.platformTest');
    -goog.setTestOnly('goog.userAgent.platformTest');
    -
    -goog.require('goog.testing.MockUserAgent');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -goog.require('goog.userAgent.platform');
    -goog.require('goog.userAgentTestUtil');
    -
    -var mockAgent;
    -
    -function setUp() {
    -  mockAgent = new goog.testing.MockUserAgent();
    -  mockAgent.install();
    -}
    -
    -function tearDown() {
    -  mockAgent.dispose();
    -  updateUserAgentUtils();
    -}
    -
    -function updateUserAgentUtils() {
    -  goog.userAgentTestUtil.reinitializeUserAgent();
    -}
    -
    -function testWindows() {
    -  mockAgent.setNavigator({platform: 'Win32'});
    -
    -  var win98 = 'Mozilla/4.0 (compatible; MSIE 6.0b; Windows 98; Win 9x 4.90)';
    -  var win2k = 'Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 5.0; en-US)';
    -  var xp = 'Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 5.1; en-US)';
    -  var vista = 'Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 6.0; en-US)';
    -  var win7 = 'Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 6.1; en-US)';
    -  var win81 = 'Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko';
    -
    -  mockAgent.setUserAgentString(win98);
    -  updateUserAgentUtils();
    -  assertEquals('0', goog.userAgent.platform.VERSION);
    -
    -  mockAgent.setUserAgentString(win2k);
    -  updateUserAgentUtils();
    -  assertEquals('5.0', goog.userAgent.platform.VERSION);
    -
    -  mockAgent.setUserAgentString(xp);
    -  updateUserAgentUtils();
    -  assertEquals('5.1', goog.userAgent.platform.VERSION);
    -
    -  mockAgent.setUserAgentString(vista);
    -  updateUserAgentUtils();
    -  assertEquals('6.0', goog.userAgent.platform.VERSION);
    -
    -  mockAgent.setUserAgentString(win7);
    -  updateUserAgentUtils();
    -  assertEquals('6.1', goog.userAgent.platform.VERSION);
    -
    -  mockAgent.setUserAgentString(win81);
    -  updateUserAgentUtils();
    -  assertEquals('6.3', goog.userAgent.platform.VERSION);
    -}
    -
    -function testMac() {
    -  // For some reason Chrome substitutes _ for . in the OS version.
    -  var chrome = 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; en-US)' +
    -      'AppleWebKit/532.5 (KHTML, like Gecko) Chrome/4.0.249.49 Safari/532.5';
    -
    -  var ff = 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US;' +
    -      'rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6';
    -
    -  mockAgent.setNavigator({platform: 'IntelMac'});
    -
    -  mockAgent.setUserAgentString(chrome);
    -  updateUserAgentUtils();
    -  assertEquals('10.5.8', goog.userAgent.platform.VERSION);
    -
    -  mockAgent.setUserAgentString(ff);
    -  updateUserAgentUtils();
    -  assertEquals('10.5', goog.userAgent.platform.VERSION);
    -}
    -
    -function testChromeOnAndroid() {
    -  // Borrowing search's test user agent string for android.
    -  var uaString = 'Mozilla/5.0 (Linux; U; Android 4.0.2; en-us; Galaxy Nexus' +
    -      ' Build/ICL53F) AppleWebKit/535.7 (KHTML, like Gecko) ' +
    -      'Chrome/18.0.1025.133 Mobile Safari/535.7';
    -
    -  // Need to set this lest the testing platform be used for detection.
    -  mockAgent.setNavigator({platform: 'Android'});
    -
    -  mockAgent.setUserAgentString(uaString);
    -  updateUserAgentUtils();
    -  assertTrue(goog.userAgent.ANDROID);
    -  assertEquals('4.0.2', goog.userAgent.platform.VERSION);
    -}
    -
    -function testAndroidBrowser() {
    -  var uaString = 'Mozilla/5.0 (Linux; U; Android 2.3.4; fr-fr;' +
    -      'HTC Desire Build/GRJ22) AppleWebKit/533.1 (KHTML, like Gecko)' +
    -      'Version/4.0 Mobile Safari/533.1';
    -
    -  // Need to set this lest the testing platform be used for detection.
    -  mockAgent.setNavigator({platform: 'Android'});
    -
    -  mockAgent.setUserAgentString(uaString);
    -  updateUserAgentUtils();
    -  assertTrue(goog.userAgent.ANDROID);
    -  assertEquals('2.3.4', goog.userAgent.platform.VERSION);
    -}
    -
    -function testIPhone() {
    -  // Borrowing search's test user agent string for the iPhone.
    -  var uaString = 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; ' +
    -      'en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 ' +
    -      'Mobile/8A293 Safari/6531.22.7';
    -
    -  // Need to set this lest the testing platform be used for detection.
    -  mockAgent.setNavigator({platform: 'iPhone'});
    -
    -  mockAgent.setUserAgentString(uaString);
    -  updateUserAgentUtils();
    -  assertTrue(goog.userAgent.IPHONE);
    -  assertEquals('4.0', goog.userAgent.platform.VERSION);
    -}
    -
    -function testIPad() {
    -  // Borrowing search's test user agent string for the iPad.
    -  var uaString = 'Mozilla/5.0 (iPad; U; CPU OS 4_2_1 like Mac OS X; ja-jp) ' +
    -      'AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 ' +
    -      'Safari/6533.18.5';
    -
    -  // Need to set this lest the testing platform be used for detection.
    -  mockAgent.setNavigator({platform: 'iPad'});
    -
    -  mockAgent.setUserAgentString(uaString);
    -  updateUserAgentUtils();
    -  assertTrue(goog.userAgent.IPAD);
    -  assertEquals('4.2.1', goog.userAgent.platform.VERSION);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/useragent/product.js b/src/database/third_party/closure-library/closure/goog/useragent/product.js
    deleted file mode 100644
    index f9b07e56168..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/useragent/product.js
    +++ /dev/null
    @@ -1,175 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Detects the specific browser and not just the rendering engine.
    - *
    - */
    -
    -goog.provide('goog.userAgent.product');
    -
    -goog.require('goog.labs.userAgent.browser');
    -goog.require('goog.labs.userAgent.platform');
    -goog.require('goog.userAgent');
    -
    -
    -/**
    - * @define {boolean} Whether the code is running on the Firefox web browser.
    - */
    -goog.define('goog.userAgent.product.ASSUME_FIREFOX', false);
    -
    -
    -/**
    - * @define {boolean} Whether we know at compile-time that the product is an
    - *     iPhone.
    - */
    -goog.define('goog.userAgent.product.ASSUME_IPHONE', false);
    -
    -
    -/**
    - * @define {boolean} Whether we know at compile-time that the product is an
    - *     iPad.
    - */
    -goog.define('goog.userAgent.product.ASSUME_IPAD', false);
    -
    -
    -/**
    - * @define {boolean} Whether we know at compile-time that the product is an
    - *     AOSP browser or WebView inside a pre KitKat Android phone or tablet.
    - */
    -goog.define('goog.userAgent.product.ASSUME_ANDROID', false);
    -
    -
    -/**
    - * @define {boolean} Whether the code is running on the Chrome web browser on
    - * any platform or AOSP browser or WebView in a KitKat+ Android phone or tablet.
    - */
    -goog.define('goog.userAgent.product.ASSUME_CHROME', false);
    -
    -
    -/**
    - * @define {boolean} Whether the code is running on the Safari web browser.
    - */
    -goog.define('goog.userAgent.product.ASSUME_SAFARI', false);
    -
    -
    -/**
    - * Whether we know the product type at compile-time.
    - * @type {boolean}
    - * @private
    - */
    -goog.userAgent.product.PRODUCT_KNOWN_ =
    -    goog.userAgent.ASSUME_IE ||
    -    goog.userAgent.ASSUME_OPERA ||
    -    goog.userAgent.product.ASSUME_FIREFOX ||
    -    goog.userAgent.product.ASSUME_IPHONE ||
    -    goog.userAgent.product.ASSUME_IPAD ||
    -    goog.userAgent.product.ASSUME_ANDROID ||
    -    goog.userAgent.product.ASSUME_CHROME ||
    -    goog.userAgent.product.ASSUME_SAFARI;
    -
    -
    -/**
    - * Whether the code is running on the Opera web browser.
    - * @type {boolean}
    - */
    -goog.userAgent.product.OPERA = goog.userAgent.OPERA;
    -
    -
    -/**
    - * Whether the code is running on an IE web browser.
    - * @type {boolean}
    - */
    -goog.userAgent.product.IE = goog.userAgent.IE;
    -
    -
    -/**
    - * Whether the code is running on the Firefox web browser.
    - * @type {boolean}
    - */
    -goog.userAgent.product.FIREFOX = goog.userAgent.product.PRODUCT_KNOWN_ ?
    -    goog.userAgent.product.ASSUME_FIREFOX :
    -    goog.labs.userAgent.browser.isFirefox();
    -
    -
    -/**
    - * Whether the user agent is an iPhone or iPod (as in iPod touch).
    - * @return {boolean}
    - * @private
    - */
    -goog.userAgent.product.isIphoneOrIpod_ = function() {
    -  return goog.labs.userAgent.platform.isIphone() ||
    -      goog.labs.userAgent.platform.isIpod();
    -};
    -
    -
    -/**
    - * Whether the code is running on an iPhone or iPod touch.
    - *
    - * iPod touch is considered an iPhone for legacy reasons.
    - * @type {boolean}
    - */
    -goog.userAgent.product.IPHONE = goog.userAgent.product.PRODUCT_KNOWN_ ?
    -    goog.userAgent.product.ASSUME_IPHONE :
    -    goog.userAgent.product.isIphoneOrIpod_();
    -
    -
    -/**
    - * Whether the code is running on an iPad.
    - * @type {boolean}
    - */
    -goog.userAgent.product.IPAD = goog.userAgent.product.PRODUCT_KNOWN_ ?
    -    goog.userAgent.product.ASSUME_IPAD :
    -    goog.labs.userAgent.platform.isIpad();
    -
    -
    -/**
    - * Whether the code is running on AOSP browser or WebView inside
    - * a pre KitKat Android phone or tablet.
    - * @type {boolean}
    - */
    -goog.userAgent.product.ANDROID = goog.userAgent.product.PRODUCT_KNOWN_ ?
    -    goog.userAgent.product.ASSUME_ANDROID :
    -    goog.labs.userAgent.browser.isAndroidBrowser();
    -
    -
    -/**
    - * Whether the code is running on the Chrome web browser on any platform
    - * or AOSP browser or WebView in a KitKat+ Android phone or tablet.
    - * @type {boolean}
    - */
    -goog.userAgent.product.CHROME = goog.userAgent.product.PRODUCT_KNOWN_ ?
    -    goog.userAgent.product.ASSUME_CHROME :
    -    goog.labs.userAgent.browser.isChrome();
    -
    -
    -/**
    - * @return {boolean} Whether the browser is Safari on desktop.
    - * @private
    - */
    -goog.userAgent.product.isSafariDesktop_ = function() {
    -  return goog.labs.userAgent.browser.isSafari() &&
    -      !goog.labs.userAgent.platform.isIos();
    -};
    -
    -
    -/**
    - * Whether the code is running on the desktop Safari web browser.
    - * Note: the legacy behavior here is only true for Safari not running
    - * on iOS.
    - * @type {boolean}
    - */
    -goog.userAgent.product.SAFARI = goog.userAgent.product.PRODUCT_KNOWN_ ?
    -    goog.userAgent.product.ASSUME_SAFARI :
    -    goog.userAgent.product.isSafariDesktop_();
    diff --git a/src/database/third_party/closure-library/closure/goog/useragent/product_isversion.js b/src/database/third_party/closure-library/closure/goog/useragent/product_isversion.js
    deleted file mode 100644
    index bbe497f9ce5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/useragent/product_isversion.js
    +++ /dev/null
    @@ -1,143 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Functions for understanding the version of the browser.
    - * This is pulled out of product.js to ensure that only builds that need
    - * this functionality actually get it, without having to rely on the compiler
    - * to strip out unneeded pieces.
    - *
    - * TODO(nnaze): Move to more appropriate filename/namespace.
    - *
    - */
    -
    -
    -goog.provide('goog.userAgent.product.isVersion');
    -
    -
    -goog.require('goog.labs.userAgent.platform');
    -goog.require('goog.string');
    -goog.require('goog.userAgent');
    -goog.require('goog.userAgent.product');
    -
    -
    -/**
    - * @return {string} The string that describes the version number of the user
    - *     agent product.  This is a string rather than a number because it may
    - *     contain 'b', 'a', and so on.
    - * @private
    - */
    -goog.userAgent.product.determineVersion_ = function() {
    -  // All browsers have different ways to detect the version and they all have
    -  // different naming schemes.
    -
    -  if (goog.userAgent.product.FIREFOX) {
    -    // Firefox/2.0.0.1 or Firefox/3.5.3
    -    return goog.userAgent.product.getFirstRegExpGroup_(/Firefox\/([0-9.]+)/);
    -  }
    -
    -  if (goog.userAgent.product.IE || goog.userAgent.product.OPERA) {
    -    return goog.userAgent.VERSION;
    -  }
    -
    -  if (goog.userAgent.product.CHROME) {
    -    // Chrome/4.0.223.1
    -    return goog.userAgent.product.getFirstRegExpGroup_(/Chrome\/([0-9.]+)/);
    -  }
    -
    -  // This replicates legacy logic, which considered Safari and iOS to be
    -  // different products.
    -  if (goog.userAgent.product.SAFARI && !goog.labs.userAgent.platform.isIos()) {
    -    // Version/5.0.3
    -    //
    -    // NOTE: Before version 3, Safari did not report a product version number.
    -    // The product version number for these browsers will be the empty string.
    -    // They may be differentiated by WebKit version number in goog.userAgent.
    -    return goog.userAgent.product.getFirstRegExpGroup_(/Version\/([0-9.]+)/);
    -  }
    -
    -  if (goog.userAgent.product.IPHONE || goog.userAgent.product.IPAD) {
    -    // Mozilla/5.0 (iPod; U; CPU like Mac OS X; en) AppleWebKit/420.1
    -    // (KHTML, like Gecko) Version/3.0 Mobile/3A100a Safari/419.3
    -    // Version is the browser version, Mobile is the build number. We combine
    -    // the version string with the build number: 3.0.3A100a for the example.
    -    var arr = goog.userAgent.product.execRegExp_(
    -        /Version\/(\S+).*Mobile\/(\S+)/);
    -    if (arr) {
    -      return arr[1] + '.' + arr[2];
    -    }
    -  } else if (goog.userAgent.product.ANDROID) {
    -    // Mozilla/5.0 (Linux; U; Android 0.5; en-us) AppleWebKit/522+
    -    // (KHTML, like Gecko) Safari/419.3
    -    //
    -    // Mozilla/5.0 (Linux; U; Android 1.0; en-us; dream) AppleWebKit/525.10+
    -    // (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2
    -    //
    -    // Prefer Version number if present, else make do with the OS number
    -    var version = goog.userAgent.product.getFirstRegExpGroup_(
    -        /Android\s+([0-9.]+)/);
    -    if (version) {
    -      return version;
    -    }
    -
    -    return goog.userAgent.product.getFirstRegExpGroup_(/Version\/([0-9.]+)/);
    -  }
    -
    -  return '';
    -};
    -
    -
    -/**
    - * Return the first group of the given regex.
    - * @param {!RegExp} re Regular expression with at least one group.
    - * @return {string} Contents of the first group or an empty string if no match.
    - * @private
    - */
    -goog.userAgent.product.getFirstRegExpGroup_ = function(re) {
    -  var arr = goog.userAgent.product.execRegExp_(re);
    -  return arr ? arr[1] : '';
    -};
    -
    -
    -/**
    - * Run regexp's exec() on the userAgent string.
    - * @param {!RegExp} re Regular expression.
    - * @return {Array<?>} A result array, or null for no match.
    - * @private
    - */
    -goog.userAgent.product.execRegExp_ = function(re) {
    -  return re.exec(goog.userAgent.getUserAgentString());
    -};
    -
    -
    -/**
    - * The version of the user agent. This is a string because it might contain
    - * 'b' (as in beta) as well as multiple dots.
    - * @type {string}
    - */
    -goog.userAgent.product.VERSION = goog.userAgent.product.determineVersion_();
    -
    -
    -/**
    - * Whether the user agent product version is higher or the same as the given
    - * version.
    - *
    - * @param {string|number} version The version to check.
    - * @return {boolean} Whether the user agent product version is higher or the
    - *     same as the given version.
    - */
    -goog.userAgent.product.isVersion = function(version) {
    -  return goog.string.compareVersions(
    -      goog.userAgent.product.VERSION, version) >= 0;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/useragent/product_test.html b/src/database/third_party/closure-library/closure/goog/useragent/product_test.html
    deleted file mode 100644
    index a37d52266ff..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/useragent/product_test.html
    +++ /dev/null
    @@ -1,30 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <!--
    -
    -  @author andybons@google.com (Andrew Boneventre)
    --->
    - <head>
    -  <!--
    -This test has not yet been updated to run on IE8. See http://b/hotlist?id=36311
    --->
    -  <!--meta http-equiv="X-UA-Compatible" content="IE=edge"-->
    -  <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
    -  <title>
    -   Closure Unit Tests - goog.userAgent.product
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.userAgent.productTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/useragent/product_test.js b/src/database/third_party/closure-library/closure/goog/useragent/product_test.js
    deleted file mode 100644
    index c694d12b9ac..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/useragent/product_test.js
    +++ /dev/null
    @@ -1,371 +0,0 @@
    -// Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.userAgent.productTest');
    -goog.setTestOnly('goog.userAgent.productTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.labs.userAgent.testAgents');
    -goog.require('goog.labs.userAgent.util');
    -goog.require('goog.testing.MockUserAgent');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -goog.require('goog.userAgent.product');
    -goog.require('goog.userAgent.product.isVersion');
    -goog.require('goog.userAgentTestUtil');
    -
    -var mockAgent;
    -var replacer;
    -
    -function setUp() {
    -  mockAgent = new goog.testing.MockUserAgent();
    -  mockAgent.install();
    -  replacer = new goog.testing.PropertyReplacer();
    -}
    -
    -function tearDown() {
    -  replacer.reset();
    -  mockAgent.dispose();
    -  updateUserAgentUtils();
    -}
    -
    -function updateUserAgentUtils() {
    -  goog.labs.userAgent.util.setUserAgent(null);
    -  goog.userAgentTestUtil.reinitializeUserAgent();
    -}
    -
    -// The set of products whose corresponding goog.userAgent.product value is set
    -// in goog.userAgent.product.init_().
    -var DETECTED_BROWSER_KEYS =
    -    ['FIREFOX', 'IPHONE', 'IPAD', 'ANDROID', 'CHROME', 'SAFARI'];
    -
    -
    -// browserKey should be the constant name, as a string
    -// 'FIREFOX', 'CHROME', 'ANDROID', etc.
    -function assertIsBrowser(currentBrowser) {
    -  assertTrue('Current browser key into goog.userAgent.product' +
    -      'should be true',
    -      goog.userAgent.product[currentBrowser]);
    -
    -  // Make sure we don't have any false positives for other browsers.
    -  goog.array.forEach(DETECTED_BROWSER_KEYS, function(browserKey) {
    -    // Ignore the iPad/Safari case, as the new code correctly
    -    // identifies the test useragent as both iPad and Safari.
    -    if (currentBrowser == 'IPAD' && browserKey == 'SAFARI') {
    -      return;
    -    }
    -
    -    if (currentBrowser == 'IPHONE' && browserKey == 'SAFARI') {
    -      return;
    -    }
    -
    -    if (currentBrowser != browserKey) {
    -      assertFalse(
    -          'Current browser key is ' + currentBrowser +
    -          ' but different key into goog.userAgent.product is true: ' +
    -          browserKey,
    -          goog.userAgent.product[browserKey]);
    -    }
    -  });
    -}
    -
    -function assertBrowserAndVersion(userAgent, browser, version) {
    -  mockAgent.setUserAgentString(userAgent);
    -  updateUserAgentUtils();
    -  assertIsBrowser(browser);
    -  assertEquals('User agent should have this version',
    -               version, goog.userAgent.VERSION);
    -}
    -
    -
    -/**
    - * @param {Array<{
    - *           ua: string,
    - *           versions: Array<{
    - *             num: {string|number}, truth: boolean}>}>} userAgents
    - * @param {string} browser
    - */
    -function checkEachUserAgentDetected(userAgents, browser) {
    -  goog.array.forEach(userAgents, function(ua) {
    -    mockAgent.setUserAgentString(ua.ua);
    -    updateUserAgentUtils();
    -
    -    assertIsBrowser(browser);
    -
    -    // Check versions
    -    goog.array.forEach(ua.versions, function(v) {
    -      mockAgent.setUserAgentString(ua.ua);
    -      updateUserAgentUtils();
    -      assertEquals(
    -          'Expected version ' + v.num + ' from ' + ua.ua + ' but got ' +
    -              goog.userAgent.product.VERSION,
    -          v.truth, goog.userAgent.product.isVersion(v.num));
    -    });
    -  });
    -}
    -
    -function testInternetExplorer() {
    -  var userAgents = [
    -    {ua: 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; GTB6; ' +
    -          'chromeframe; .NET CLR 1.1.4322; InfoPath.1; ' +
    -          '.NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648; ' +
    -          '.NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 2.0.50727)',
    -      versions: [
    -        {num: 6, truth: true},
    -        {num: '7.0', truth: true},
    -        {num: 7.1, truth: false},
    -        {num: 8, truth: false}
    -      ]
    -    },
    -    {ua: 'Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko',
    -      versions: [
    -        {num: 10, truth: true},
    -        {num: 11, truth: true},
    -        {num: '11.0', truth: true},
    -        {num: '12', truth: false}
    -      ]
    -    }
    -  ];
    -  // hide any navigator.product value by putting in a navigator with no
    -  // properties.
    -  mockAgent.setNavigator({});
    -  checkEachUserAgentDetected(userAgents, 'IE');
    -}
    -
    -function testOpera() {
    -  var opera = {};
    -  var userAgents = [
    -    {ua: 'Opera/9.80 (Windows NT 5.1; U; en) Presto/2.2.15 Version/10.01',
    -      versions: [
    -        {num: 9, truth: true},
    -        {num: '10.1', truth: true},
    -        {num: 11, truth: false}
    -      ]}
    -  ];
    -  replacer.set(goog.global, 'opera', opera);
    -  opera.version = '10.01';
    -  checkEachUserAgentDetected(userAgents, 'OPERA');
    -  userAgents = [
    -    {ua: 'Opera/9.63 (Windows NT 5.1; U; en) Presto/2.1.1',
    -      versions: [
    -        {num: 9, truth: true},
    -        {num: '10.1', truth: false},
    -        {num: '9.80', truth: false},
    -        {num: '9.60', truth: true}
    -      ]}
    -  ];
    -  opera.version = '9.63';
    -  checkEachUserAgentDetected(userAgents, 'OPERA');
    -}
    -
    -function testFirefox() {
    -  var userAgents = [
    -    {ua: 'Mozilla/6.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; ' +
    -          'rv:2.0.0.0) Gecko/20061028 Firefox/3.0',
    -      versions: [
    -        {num: 2, truth: true},
    -        {num: '3.0', truth: true},
    -        {num: '3.5.3', truth: false}
    -      ]},
    -    {ua: 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; ' +
    -          'rv:1.8.1.4) Gecko/20070515 Firefox/2.0.4',
    -      versions: [
    -        {num: 2, truth: true},
    -        {num: '2.0.4', truth: true},
    -        {num: 3, truth: false},
    -        {num: '3.5.3', truth: false}
    -      ]},
    -    {ua: 'Mozilla/5.0 (X11; Linux i686; rv:6.0) Gecko/6.0 Firefox/6.0',
    -      versions: [
    -        {num: 6, truth: true},
    -        {num: '6.0', truth: true},
    -        {num: 7, truth: false},
    -        {num: '7.0', truth: false}
    -      ]}
    -  ];
    -
    -  checkEachUserAgentDetected(userAgents, 'FIREFOX');
    -
    -  // Mozilla reported to us that they plan this UA format starting
    -  // in Firefox 13.
    -  // See bug at https://bugzilla.mozilla.org/show_bug.cgi?id=588909
    -  // and thread at http://goto.google.com/pfltz
    -  mockAgent.setNavigator({product: 'Gecko'});
    -  assertBrowserAndVersion(
    -      'Mozilla/5.0 (X11; Linux i686; rv:6.0) Gecko/6.0 Firefox/6.0',
    -      'FIREFOX', '6.0');
    -}
    -
    -function testChrome() {
    -  var userAgents = [
    -    {ua: 'Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) ' +
    -          'AppleWebKit/525.19 (KHTML, like Gecko) Chrome/0.2.153.0 ' +
    -          'Safari/525.19',
    -      versions: [
    -        {num: '0.2.153', truth: true},
    -        {num: 1, truth: false}
    -      ]},
    -    {ua: 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) ' +
    -          'AppleWebKit/532.3 (KHTML, like Gecko) Chrome/4.0.223.11 ' +
    -          'Safari/532.3',
    -      versions: [
    -        {num: 4, truth: true},
    -        {num: '0.2.153', truth: true},
    -        {num: '4.1.223.13', truth: false},
    -        {num: '4.0.223.10', truth: true}
    -      ]},
    -    {ua: 'Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B)' +
    -          'AppleWebKit/535.19 (KHTML, like Gecko) ' +
    -          'Chrome/18.0.1025.133 Mobile' +
    -          'Safari/535.19',
    -      versions: [
    -        {num: 18, truth: true},
    -        {num: '0.2.153', truth: true},
    -        {num: 29, truth: false},
    -        {num: '18.0.1025.133', truth: true}
    -      ]}
    -  ];
    -  checkEachUserAgentDetected(userAgents, 'CHROME');
    -}
    -
    -function testSafari() {
    -  var userAgents = [
    -    {ua: 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; de-de) ' +
    -          'AppleWebKit/534.16+ (KHTML, like Gecko) Version/5.0.3 ' +
    -          'Safari/533.19.4',
    -      versions: [
    -        {num: 5, truth: true},
    -        {num: '5.0.3', truth: true},
    -        {num: '5.0.4', truth: false},
    -        {num: '533', truth: false}
    -      ]},
    -    {ua: 'Mozilla/5.0 (Windows; U; Windows NT 6.0; pl-PL) ' +
    -          'AppleWebKit/525.19 (KHTML, like Gecko) Version/3.1.2 Safari/525.21',
    -      versions: [
    -        {num: 3, truth: true},
    -        {num: '3.0', truth: true},
    -        {num: '3.1.2', truth: true}
    -      ]},
    -    {ua: 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_5_3; en-us) ' +
    -          'AppleWebKit/525.18 (KHTML, like Gecko) Version/3.1.1 Safari/525.20',
    -      versions: [
    -        {num: 3, truth: true},
    -        {num: '3.1.1', truth: true},
    -        {num: '3.1.2', truth: false},
    -        {num: '525.21', truth: false}
    -      ]},
    -
    -    // Safari 1 and 2 do not report product version numbers in their
    -    // user-agent strings. VERSION for these browsers will be set to ''.
    -    {ua: 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; ja-jp) ' +
    -          'AppleWebKit/418.9.1 (KHTML, like Gecko) Safari/419.3',
    -      versions: [
    -        {num: 3, truth: false},
    -        {num: 2, truth: false},
    -        {num: 1, truth: false},
    -        {num: 0, truth: true},
    -        {num: '0', truth: true},
    -        {num: '', truth: true}
    -      ]}
    -  ];
    -  checkEachUserAgentDetected(userAgents, 'SAFARI');
    -}
    -
    -function testIphone() {
    -  var userAgents = [
    -    {ua: 'Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ ' +
    -          '(KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3',
    -      versions: [
    -        {num: '3.0.1A543a', truth: true},
    -        {num: '3.0', truth: true},
    -        {num: '3.0.1B543a', truth: false},
    -        {num: '3.1.1A543a', truth: false},
    -        {num: '3.0.1A320c', truth: true},
    -        {num: '3.0.3A100a', truth: false}
    -      ]},
    -    {ua: 'Mozilla/5.0 (iPod; U; CPU like Mac OS X; en) AppleWebKit/420.1 ' +
    -          '(KHTML, like Gecko) Version/3.0 Mobile/3A100a Safari/419.3',
    -      versions: [
    -        {num: '3.0.1A543a', truth: true},
    -        {num: '3.0.3A100a', truth: true}
    -      ]}
    -  ];
    -  checkEachUserAgentDetected(userAgents, 'IPHONE');
    -}
    -
    -function testIpad() {
    -  var userAgents = [
    -    {ua: 'Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) ' +
    -          'AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 ' +
    -          'Mobile/7B334b Safari/531.21.10',
    -      versions: [
    -        {num: '4.0.4.7B334b', truth: true},
    -        {num: '4.0', truth: true},
    -        {num: '4.0.4.7C334b', truth: false},
    -        {num: '4.1.7B334b', truth: false},
    -        {num: '4.0.4.7B320c', truth: true},
    -        {num: '4.0.4.8B334b', truth: false}
    -      ]},
    -    // Webview in the Facebook iOS app
    -    {ua: 'Mozilla/5.0 (iPad; CPU OS 8_1 like Mac OS X) AppleWebKit/600.1.4' +
    -          '(KHTML, like Gecko) Mobile/12B410 [FBAN/FBIOS;FBAV/16.0.0.13.22;' +
    -          'FBBV/4697910;FBDV/iPad3,4;FBMD/iPad;FBSN/iPhone OS;FBSV/8.1;' +
    -          'FBSS/2; FBCR/;FBID/tablet;FBLC/ja_JP;FBOP/1]',
    -      versions: [
    -        {num: '', truth: true}
    -      ]}
    -  ];
    -  checkEachUserAgentDetected(userAgents, 'IPAD');
    -}
    -
    -function testAndroid() {
    -  var userAgents = [
    -    {ua: 'Mozilla/5.0 (Linux; U; Android 0.5; en-us) AppleWebKit/522+ ' +
    -          '(KHTML, like Gecko) Safari/419.3',
    -      versions: [
    -        {num: 0.5, truth: true},
    -        {num: '1.0', truth: false}
    -      ]},
    -    {ua: 'Mozilla/5.0 (Linux; U; Android 1.0; en-us; dream) ' +
    -          'AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile ' +
    -          'Safari/523.12.2',
    -      versions: [
    -        {num: 0.5, truth: true},
    -        {num: 1, truth: true},
    -        {num: '1.0', truth: true},
    -        {num: '3.0.12', truth: false}
    -      ]}
    -  ];
    -  checkEachUserAgentDetected(userAgents, 'ANDROID');
    -}
    -
    -function testAndroidLegacyBehavior() {
    -  mockAgent.setUserAgentString(
    -      goog.labs.userAgent.testAgents.FIREFOX_ANDROID_TABLET);
    -  updateUserAgentUtils();
    -  // Historically, goog.userAgent.product.ANDROID has referred to the
    -  // Android browser, not the platform. Firefox on Android should
    -  // be false.
    -  assertFalse(goog.userAgent.product.ANDROID);
    -}
    -
    -function testSafariIosLegacyBehavior() {
    -  mockAgent.setUserAgentString(
    -      goog.labs.userAgent.testAgents.SAFARI_IPHONE_6);
    -  updateUserAgentUtils();
    -  // Historically, goog.userAgent.product.SAFARI has referred to the
    -  // Safari desktop browser, not the mobile browser.
    -  assertFalse(goog.userAgent.product.SAFARI);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/useragent/useragent.js b/src/database/third_party/closure-library/closure/goog/useragent/useragent.js
    deleted file mode 100644
    index c8999024c1b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/useragent/useragent.js
    +++ /dev/null
    @@ -1,519 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Rendering engine detection.
    - * @see <a href="http://www.useragentstring.com/">User agent strings</a>
    - * For information on the browser brand (such as Safari versus Chrome), see
    - * goog.userAgent.product.
    - * @author arv@google.com (Erik Arvidsson)
    - * @see ../demos/useragent.html
    - */
    -
    -goog.provide('goog.userAgent');
    -
    -goog.require('goog.labs.userAgent.browser');
    -goog.require('goog.labs.userAgent.engine');
    -goog.require('goog.labs.userAgent.platform');
    -goog.require('goog.labs.userAgent.util');
    -goog.require('goog.string');
    -
    -
    -/**
    - * @define {boolean} Whether we know at compile-time that the browser is IE.
    - */
    -goog.define('goog.userAgent.ASSUME_IE', false);
    -
    -
    -/**
    - * @define {boolean} Whether we know at compile-time that the browser is GECKO.
    - */
    -goog.define('goog.userAgent.ASSUME_GECKO', false);
    -
    -
    -/**
    - * @define {boolean} Whether we know at compile-time that the browser is WEBKIT.
    - */
    -goog.define('goog.userAgent.ASSUME_WEBKIT', false);
    -
    -
    -/**
    - * @define {boolean} Whether we know at compile-time that the browser is a
    - *     mobile device running WebKit e.g. iPhone or Android.
    - */
    -goog.define('goog.userAgent.ASSUME_MOBILE_WEBKIT', false);
    -
    -
    -/**
    - * @define {boolean} Whether we know at compile-time that the browser is OPERA.
    - */
    -goog.define('goog.userAgent.ASSUME_OPERA', false);
    -
    -
    -/**
    - * @define {boolean} Whether the
    - *     {@code goog.userAgent.isVersionOrHigher}
    - *     function will return true for any version.
    - */
    -goog.define('goog.userAgent.ASSUME_ANY_VERSION', false);
    -
    -
    -/**
    - * Whether we know the browser engine at compile-time.
    - * @type {boolean}
    - * @private
    - */
    -goog.userAgent.BROWSER_KNOWN_ =
    -    goog.userAgent.ASSUME_IE ||
    -    goog.userAgent.ASSUME_GECKO ||
    -    goog.userAgent.ASSUME_MOBILE_WEBKIT ||
    -    goog.userAgent.ASSUME_WEBKIT ||
    -    goog.userAgent.ASSUME_OPERA;
    -
    -
    -/**
    - * Returns the userAgent string for the current browser.
    - *
    - * @return {string} The userAgent string.
    - */
    -goog.userAgent.getUserAgentString = function() {
    -  return goog.labs.userAgent.util.getUserAgent();
    -};
    -
    -
    -/**
    - * TODO(nnaze): Change type to "Navigator" and update compilation targets.
    - * @return {Object} The native navigator object.
    - */
    -goog.userAgent.getNavigator = function() {
    -  // Need a local navigator reference instead of using the global one,
    -  // to avoid the rare case where they reference different objects.
    -  // (in a WorkerPool, for example).
    -  return goog.global['navigator'] || null;
    -};
    -
    -
    -/**
    - * Whether the user agent is Opera.
    - * @type {boolean}
    - */
    -goog.userAgent.OPERA = goog.userAgent.BROWSER_KNOWN_ ?
    -    goog.userAgent.ASSUME_OPERA :
    -    goog.labs.userAgent.browser.isOpera();
    -
    -
    -/**
    - * Whether the user agent is Internet Explorer.
    - * @type {boolean}
    - */
    -goog.userAgent.IE = goog.userAgent.BROWSER_KNOWN_ ?
    -    goog.userAgent.ASSUME_IE :
    -    goog.labs.userAgent.browser.isIE();
    -
    -
    -/**
    - * Whether the user agent is Gecko. Gecko is the rendering engine used by
    - * Mozilla, Firefox, and others.
    - * @type {boolean}
    - */
    -goog.userAgent.GECKO = goog.userAgent.BROWSER_KNOWN_ ?
    -    goog.userAgent.ASSUME_GECKO :
    -    goog.labs.userAgent.engine.isGecko();
    -
    -
    -/**
    - * Whether the user agent is WebKit. WebKit is the rendering engine that
    - * Safari, Android and others use.
    - * @type {boolean}
    - */
    -goog.userAgent.WEBKIT = goog.userAgent.BROWSER_KNOWN_ ?
    -    goog.userAgent.ASSUME_WEBKIT || goog.userAgent.ASSUME_MOBILE_WEBKIT :
    -    goog.labs.userAgent.engine.isWebKit();
    -
    -
    -/**
    - * Whether the user agent is running on a mobile device.
    - *
    - * This is a separate function so that the logic can be tested.
    - *
    - * TODO(nnaze): Investigate swapping in goog.labs.userAgent.device.isMobile().
    - *
    - * @return {boolean} Whether the user agent is running on a mobile device.
    - * @private
    - */
    -goog.userAgent.isMobile_ = function() {
    -  return goog.userAgent.WEBKIT &&
    -         goog.labs.userAgent.util.matchUserAgent('Mobile');
    -};
    -
    -
    -/**
    - * Whether the user agent is running on a mobile device.
    - *
    - * TODO(nnaze): Consider deprecating MOBILE when labs.userAgent
    - *   is promoted as the gecko/webkit logic is likely inaccurate.
    - *
    - * @type {boolean}
    - */
    -goog.userAgent.MOBILE = goog.userAgent.ASSUME_MOBILE_WEBKIT ||
    -                        goog.userAgent.isMobile_();
    -
    -
    -/**
    - * Used while transitioning code to use WEBKIT instead.
    - * @type {boolean}
    - * @deprecated Use {@link goog.userAgent.product.SAFARI} instead.
    - * TODO(nicksantos): Delete this from goog.userAgent.
    - */
    -goog.userAgent.SAFARI = goog.userAgent.WEBKIT;
    -
    -
    -/**
    - * @return {string} the platform (operating system) the user agent is running
    - *     on. Default to empty string because navigator.platform may not be defined
    - *     (on Rhino, for example).
    - * @private
    - */
    -goog.userAgent.determinePlatform_ = function() {
    -  var navigator = goog.userAgent.getNavigator();
    -  return navigator && navigator.platform || '';
    -};
    -
    -
    -/**
    - * The platform (operating system) the user agent is running on. Default to
    - * empty string because navigator.platform may not be defined (on Rhino, for
    - * example).
    - * @type {string}
    - */
    -goog.userAgent.PLATFORM = goog.userAgent.determinePlatform_();
    -
    -
    -/**
    - * @define {boolean} Whether the user agent is running on a Macintosh operating
    - *     system.
    - */
    -goog.define('goog.userAgent.ASSUME_MAC', false);
    -
    -
    -/**
    - * @define {boolean} Whether the user agent is running on a Windows operating
    - *     system.
    - */
    -goog.define('goog.userAgent.ASSUME_WINDOWS', false);
    -
    -
    -/**
    - * @define {boolean} Whether the user agent is running on a Linux operating
    - *     system.
    - */
    -goog.define('goog.userAgent.ASSUME_LINUX', false);
    -
    -
    -/**
    - * @define {boolean} Whether the user agent is running on a X11 windowing
    - *     system.
    - */
    -goog.define('goog.userAgent.ASSUME_X11', false);
    -
    -
    -/**
    - * @define {boolean} Whether the user agent is running on Android.
    - */
    -goog.define('goog.userAgent.ASSUME_ANDROID', false);
    -
    -
    -/**
    - * @define {boolean} Whether the user agent is running on an iPhone.
    - */
    -goog.define('goog.userAgent.ASSUME_IPHONE', false);
    -
    -
    -/**
    - * @define {boolean} Whether the user agent is running on an iPad.
    - */
    -goog.define('goog.userAgent.ASSUME_IPAD', false);
    -
    -
    -/**
    - * @type {boolean}
    - * @private
    - */
    -goog.userAgent.PLATFORM_KNOWN_ =
    -    goog.userAgent.ASSUME_MAC ||
    -    goog.userAgent.ASSUME_WINDOWS ||
    -    goog.userAgent.ASSUME_LINUX ||
    -    goog.userAgent.ASSUME_X11 ||
    -    goog.userAgent.ASSUME_ANDROID ||
    -    goog.userAgent.ASSUME_IPHONE ||
    -    goog.userAgent.ASSUME_IPAD;
    -
    -
    -/**
    - * Whether the user agent is running on a Macintosh operating system.
    - * @type {boolean}
    - */
    -goog.userAgent.MAC = goog.userAgent.PLATFORM_KNOWN_ ?
    -    goog.userAgent.ASSUME_MAC : goog.labs.userAgent.platform.isMacintosh();
    -
    -
    -/**
    - * Whether the user agent is running on a Windows operating system.
    - * @type {boolean}
    - */
    -goog.userAgent.WINDOWS = goog.userAgent.PLATFORM_KNOWN_ ?
    -    goog.userAgent.ASSUME_WINDOWS :
    -    goog.labs.userAgent.platform.isWindows();
    -
    -
    -/**
    - * Whether the user agent is Linux per the legacy behavior of
    - * goog.userAgent.LINUX, which considered ChromeOS to also be
    - * Linux.
    - * @return {boolean}
    - * @private
    - */
    -goog.userAgent.isLegacyLinux_ = function() {
    -  return goog.labs.userAgent.platform.isLinux() ||
    -      goog.labs.userAgent.platform.isChromeOS();
    -};
    -
    -
    -/**
    - * Whether the user agent is running on a Linux operating system.
    - *
    - * Note that goog.userAgent.LINUX considers ChromeOS to be Linux,
    - * while goog.labs.userAgent.platform considers ChromeOS and
    - * Linux to be different OSes.
    - *
    - * @type {boolean}
    - */
    -goog.userAgent.LINUX = goog.userAgent.PLATFORM_KNOWN_ ?
    -    goog.userAgent.ASSUME_LINUX :
    -    goog.userAgent.isLegacyLinux_();
    -
    -
    -/**
    - * @return {boolean} Whether the user agent is an X11 windowing system.
    - * @private
    - */
    -goog.userAgent.isX11_ = function() {
    -  var navigator = goog.userAgent.getNavigator();
    -  return !!navigator &&
    -      goog.string.contains(navigator['appVersion'] || '', 'X11');
    -};
    -
    -
    -/**
    - * Whether the user agent is running on a X11 windowing system.
    - * @type {boolean}
    - */
    -goog.userAgent.X11 = goog.userAgent.PLATFORM_KNOWN_ ?
    -    goog.userAgent.ASSUME_X11 :
    -    goog.userAgent.isX11_();
    -
    -
    -/**
    - * Whether the user agent is running on Android.
    - * @type {boolean}
    - */
    -goog.userAgent.ANDROID = goog.userAgent.PLATFORM_KNOWN_ ?
    -    goog.userAgent.ASSUME_ANDROID :
    -    goog.labs.userAgent.platform.isAndroid();
    -
    -
    -/**
    - * Whether the user agent is running on an iPhone.
    - * @type {boolean}
    - */
    -goog.userAgent.IPHONE = goog.userAgent.PLATFORM_KNOWN_ ?
    -    goog.userAgent.ASSUME_IPHONE :
    -    goog.labs.userAgent.platform.isIphone();
    -
    -
    -/**
    - * Whether the user agent is running on an iPad.
    - * @type {boolean}
    - */
    -goog.userAgent.IPAD = goog.userAgent.PLATFORM_KNOWN_ ?
    -    goog.userAgent.ASSUME_IPAD :
    -    goog.labs.userAgent.platform.isIpad();
    -
    -
    -/**
    - * @return {string} The string that describes the version number of the user
    - *     agent.
    - * @private
    - */
    -goog.userAgent.determineVersion_ = function() {
    -  // All browsers have different ways to detect the version and they all have
    -  // different naming schemes.
    -
    -  // version is a string rather than a number because it may contain 'b', 'a',
    -  // and so on.
    -  var version = '', re;
    -
    -  if (goog.userAgent.OPERA && goog.global['opera']) {
    -    var operaVersion = goog.global['opera'].version;
    -    return goog.isFunction(operaVersion) ? operaVersion() : operaVersion;
    -  }
    -
    -  if (goog.userAgent.GECKO) {
    -    re = /rv\:([^\);]+)(\)|;)/;
    -  } else if (goog.userAgent.IE) {
    -    re = /\b(?:MSIE|rv)[: ]([^\);]+)(\)|;)/;
    -  } else if (goog.userAgent.WEBKIT) {
    -    // WebKit/125.4
    -    re = /WebKit\/(\S+)/;
    -  }
    -
    -  if (re) {
    -    var arr = re.exec(goog.userAgent.getUserAgentString());
    -    version = arr ? arr[1] : '';
    -  }
    -
    -  if (goog.userAgent.IE) {
    -    // IE9 can be in document mode 9 but be reporting an inconsistent user agent
    -    // version.  If it is identifying as a version lower than 9 we take the
    -    // documentMode as the version instead.  IE8 has similar behavior.
    -    // It is recommended to set the X-UA-Compatible header to ensure that IE9
    -    // uses documentMode 9.
    -    var docMode = goog.userAgent.getDocumentMode_();
    -    if (docMode > parseFloat(version)) {
    -      return String(docMode);
    -    }
    -  }
    -
    -  return version;
    -};
    -
    -
    -/**
    - * @return {number|undefined} Returns the document mode (for testing).
    - * @private
    - */
    -goog.userAgent.getDocumentMode_ = function() {
    -  // NOTE(user): goog.userAgent may be used in context where there is no DOM.
    -  var doc = goog.global['document'];
    -  return doc ? doc['documentMode'] : undefined;
    -};
    -
    -
    -/**
    - * The version of the user agent. This is a string because it might contain
    - * 'b' (as in beta) as well as multiple dots.
    - * @type {string}
    - */
    -goog.userAgent.VERSION = goog.userAgent.determineVersion_();
    -
    -
    -/**
    - * Compares two version numbers.
    - *
    - * @param {string} v1 Version of first item.
    - * @param {string} v2 Version of second item.
    - *
    - * @return {number}  1 if first argument is higher
    - *                   0 if arguments are equal
    - *                  -1 if second argument is higher.
    - * @deprecated Use goog.string.compareVersions.
    - */
    -goog.userAgent.compare = function(v1, v2) {
    -  return goog.string.compareVersions(v1, v2);
    -};
    -
    -
    -/**
    - * Cache for {@link goog.userAgent.isVersionOrHigher}.
    - * Calls to compareVersions are surprisingly expensive and, as a browser's
    - * version number is unlikely to change during a session, we cache the results.
    - * @const
    - * @private
    - */
    -goog.userAgent.isVersionOrHigherCache_ = {};
    -
    -
    -/**
    - * Whether the user agent version is higher or the same as the given version.
    - * NOTE: When checking the version numbers for Firefox and Safari, be sure to
    - * use the engine's version, not the browser's version number.  For example,
    - * Firefox 3.0 corresponds to Gecko 1.9 and Safari 3.0 to Webkit 522.11.
    - * Opera and Internet Explorer versions match the product release number.<br>
    - * @see <a href="http://en.wikipedia.org/wiki/Safari_version_history">
    - *     Webkit</a>
    - * @see <a href="http://en.wikipedia.org/wiki/Gecko_engine">Gecko</a>
    - *
    - * @param {string|number} version The version to check.
    - * @return {boolean} Whether the user agent version is higher or the same as
    - *     the given version.
    - */
    -goog.userAgent.isVersionOrHigher = function(version) {
    -  return goog.userAgent.ASSUME_ANY_VERSION ||
    -      goog.userAgent.isVersionOrHigherCache_[version] ||
    -      (goog.userAgent.isVersionOrHigherCache_[version] =
    -          goog.string.compareVersions(goog.userAgent.VERSION, version) >= 0);
    -};
    -
    -
    -/**
    - * Deprecated alias to {@code goog.userAgent.isVersionOrHigher}.
    - * @param {string|number} version The version to check.
    - * @return {boolean} Whether the user agent version is higher or the same as
    - *     the given version.
    - * @deprecated Use goog.userAgent.isVersionOrHigher().
    - */
    -goog.userAgent.isVersion = goog.userAgent.isVersionOrHigher;
    -
    -
    -/**
    - * Whether the IE effective document mode is higher or the same as the given
    - * document mode version.
    - * NOTE: Only for IE, return false for another browser.
    - *
    - * @param {number} documentMode The document mode version to check.
    - * @return {boolean} Whether the IE effective document mode is higher or the
    - *     same as the given version.
    - */
    -goog.userAgent.isDocumentModeOrHigher = function(documentMode) {
    -  return goog.userAgent.IE && goog.userAgent.DOCUMENT_MODE >= documentMode;
    -};
    -
    -
    -/**
    - * Deprecated alias to {@code goog.userAgent.isDocumentModeOrHigher}.
    - * @param {number} version The version to check.
    - * @return {boolean} Whether the IE effective document mode is higher or the
    - *      same as the given version.
    - * @deprecated Use goog.userAgent.isDocumentModeOrHigher().
    - */
    -goog.userAgent.isDocumentMode = goog.userAgent.isDocumentModeOrHigher;
    -
    -
    -/**
    - * For IE version < 7, documentMode is undefined, so attempt to use the
    - * CSS1Compat property to see if we are in standards mode. If we are in
    - * standards mode, treat the browser version as the document mode. Otherwise,
    - * IE is emulating version 5.
    - * @type {number|undefined}
    - * @const
    - */
    -goog.userAgent.DOCUMENT_MODE = (function() {
    -  var doc = goog.global['document'];
    -  if (!doc || !goog.userAgent.IE) {
    -    return undefined;
    -  }
    -  var mode = goog.userAgent.getDocumentMode_();
    -  return mode || (doc['compatMode'] == 'CSS1Compat' ?
    -      parseInt(goog.userAgent.VERSION, 10) : 5);
    -})();
    diff --git a/src/database/third_party/closure-library/closure/goog/useragent/useragent_quirks_test.html b/src/database/third_party/closure-library/closure/goog/useragent/useragent_quirks_test.html
    deleted file mode 100644
    index 35d5db10e9e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/useragent/useragent_quirks_test.html
    +++ /dev/null
    @@ -1,21 +0,0 @@
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <title>
    -   Closure Unit Tests - goog.userAgent quirks
    -  </title>
    -  <meta http-equiv="X-UA-Compatible" content="IE=5">
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.userAgentQuirksTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/useragent/useragent_quirks_test.js b/src/database/third_party/closure-library/closure/goog/useragent/useragent_quirks_test.js
    deleted file mode 100644
    index 960d0be432d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/useragent/useragent_quirks_test.js
    +++ /dev/null
    @@ -1,25 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.userAgentQuirksTest');
    -goog.setTestOnly('goog.userAgentQuirksTest');
    -
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -
    -function testGetDocumentModeInQuirksMode() {
    -  // This test file is forcing quirks mode.
    -  var expected = goog.userAgent.IE ? 5 : undefined;
    -  assertEquals(expected, goog.userAgent.DOCUMENT_MODE);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/useragent/useragent_test.html b/src/database/third_party/closure-library/closure/goog/useragent/useragent_test.html
    deleted file mode 100644
    index 72429ee2329..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/useragent/useragent_test.html
    +++ /dev/null
    @@ -1,22 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.userAgent
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.userAgentTest');
    -  </script>
    - </head>
    - <body>
    - </body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/useragent/useragent_test.js b/src/database/third_party/closure-library/closure/goog/useragent/useragent_test.js
    deleted file mode 100644
    index c2245a620e0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/useragent/useragent_test.js
    +++ /dev/null
    @@ -1,290 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.userAgentTest');
    -goog.setTestOnly('goog.userAgentTest');
    -
    -goog.require('goog.array');
    -goog.require('goog.labs.userAgent.platform');
    -goog.require('goog.labs.userAgent.testAgents');
    -goog.require('goog.labs.userAgent.util');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.userAgent');
    -goog.require('goog.userAgentTestUtil');
    -
    -
    -var documentMode;
    -goog.userAgent.getDocumentMode_ = function() {
    -  return documentMode;
    -};
    -
    -
    -var propertyReplacer = new goog.testing.PropertyReplacer();
    -
    -var UserAgents = {
    -  GECKO: 'GECKO',
    -  IE: 'IE',
    -  OPERA: 'OPERA',
    -  WEBKIT: 'WEBKIT'
    -};
    -
    -
    -function tearDown() {
    -  goog.labs.userAgent.util.setUserAgent(null);
    -  documentMode = undefined;
    -  propertyReplacer.reset();
    -}
    -
    -
    -/**
    - * Test browser detection for a user agent configuration.
    - * @param {Array<number>} expectedAgents Array of expected userAgents.
    - * @param {string} uaString User agent string.
    - * @param {string=} opt_product Navigator product string.
    - * @param {string=} opt_vendor Navigator vendor string.
    - */
    -function assertUserAgent(expectedAgents, uaString, opt_product, opt_vendor) {
    -  var mockGlobal = {
    -    'navigator': {
    -      'userAgent': uaString,
    -      'product': opt_product,
    -      'vendor': opt_vendor
    -    }
    -  };
    -  propertyReplacer.set(goog, 'global', mockGlobal);
    -
    -  goog.labs.userAgent.util.setUserAgent(null);
    -
    -  goog.userAgentTestUtil.reinitializeUserAgent();
    -  for (var ua in UserAgents) {
    -    var isExpected = goog.array.contains(expectedAgents, UserAgents[ua]);
    -    assertEquals(isExpected,
    -        goog.userAgentTestUtil.getUserAgentDetected(UserAgents[ua]));
    -  }
    -}
    -
    -function testOperaInit() {
    -  var mockOpera = {
    -    'version': function() {
    -      return '9.20';
    -    }
    -  };
    -
    -  var mockGlobal = {
    -    'navigator': {
    -      'userAgent': 'Opera/9.20 (Windows NT 5.1; U; de),gzip(gfe)'
    -    },
    -    'opera': mockOpera
    -  };
    -  propertyReplacer.set(goog, 'global', mockGlobal);
    -
    -  propertyReplacer.set(goog.userAgent, 'getUserAgentString', function() {
    -    return 'Opera/9.20 (Windows NT 5.1; U; de),gzip(gfe)';
    -  });
    -
    -  goog.labs.userAgent.util.setUserAgent(null);
    -  goog.userAgentTestUtil.reinitializeUserAgent();
    -  assertTrue(goog.userAgent.OPERA);
    -  assertEquals('9.20', goog.userAgent.VERSION);
    -
    -  // What if 'opera' global has been overwritten?
    -  // We must degrade gracefully (rather than throwing JS errors).
    -  propertyReplacer.set(goog.global, 'opera', 'bobloblaw');
    -
    -  // NOTE(nnaze): window.opera is now ignored with the migration to
    -  // goog.labs.userAgent.*. Version is expected to should stay the same.
    -  goog.labs.userAgent.util.setUserAgent(null);
    -  goog.userAgentTestUtil.reinitializeUserAgent();
    -  assertUndefined(goog.userAgent.VERSION);
    -}
    -
    -function testCompare() {
    -  assertTrue('exact equality broken',
    -             goog.userAgent.compare('1.0', '1.0') == 0);
    -  assertTrue('mutlidot equality broken',
    -             goog.userAgent.compare('1.0.0.0', '1.0') == 0);
    -  assertTrue('less than broken',
    -             goog.userAgent.compare('1.0.2.1', '1.1') < 0);
    -  assertTrue('greater than broken',
    -             goog.userAgent.compare('1.1', '1.0.2.1') > 0);
    -
    -  assertTrue('b broken', goog.userAgent.compare('1.1', '1.1b') > 0);
    -  assertTrue('b broken', goog.userAgent.compare('1.1b', '1.1') < 0);
    -  assertTrue('b broken', goog.userAgent.compare('1.1b', '1.1b') == 0);
    -
    -  assertTrue('b>a broken', goog.userAgent.compare('1.1b', '1.1a') > 0);
    -  assertTrue('a<b broken', goog.userAgent.compare('1.1a', '1.1b') < 0);
    -}
    -
    -function testGecko() {
    -
    -  assertGecko('Mozilla/5.0 (Windows; U; Windows NT 5.1; nl-NL; rv:1.7.5)' +
    -      'Gecko/20041202 Gecko/1.0', '1.7.5');
    -  assertGecko('Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.7.6)' +
    -      'Gecko/20050512 Gecko', '1.7.6');
    -  assertGecko('Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.8)' +
    -      'Gecko/20050609 Gecko/1.0.4', '1.7.8');
    -  assertGecko('Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.9)' +
    -      'Gecko/20050711 Gecko/1.0.5', '1.7.9');
    -  assertGecko('Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.10)' +
    -      'Gecko/20050716 Gecko/1.0.6', '1.7.10');
    -  assertGecko('Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-GB;' +
    -      'rv:1.7.10) Gecko/20050717 Gecko/1.0.6', '1.7.10');
    -  assertGecko('Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.12)' +
    -      'Gecko/20050915 Gecko/1.0.7', '1.7.12');
    -  assertGecko('Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US;' +
    -      'rv:1.7.12) Gecko/20050915 Gecko/1.0.7', '1.7.12');
    -  assertGecko('Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b4)' +
    -      'Gecko/20050908 Gecko/1.4', '1.8b4');
    -  assertGecko('Mozilla/5.0 (Windows; U; Windows NT 5.1; nl; rv:1.8)' +
    -      'Gecko/20051107 Gecko/1.5', '1.8');
    -  assertGecko('Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.0.1)' +
    -      'Gecko/20060111 Gecko/1.5.0.1', '1.8.0.1');
    -  assertGecko('Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.8.0.1)' +
    -      'Gecko/20060111 Gecko/1.5.0.1', '1.8.0.1');
    -  assertGecko('Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.2)' +
    -      'Gecko/20060308 Gecko/1.5.0.2', '1.8.0.2');
    -  assertGecko('Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US;' +
    -      'rv:1.8.0.3) Gecko/20060426 Gecko/1.5.0.3', '1.8.0.3');
    -  assertGecko('Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.3)' +
    -      'Gecko/20060426 Gecko/1.5.0.3', '1.8.0.3');
    -  assertGecko('Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.4)' +
    -      'Gecko/20060508 Gecko/1.5.0.4', '1.8.0.4');
    -  assertGecko('Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.4)' +
    -      'Gecko/20060508 Gecko/1.5.0.4', '1.8.0.4');
    -  assertGecko('Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.8.0.4)' +
    -      'Gecko/20060508 Gecko/1.5.0.4', '1.8.0.4');
    -  assertGecko('Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.8.0.6)' +
    -      'Gecko/20060728 Gecko/1.5.0.6', '1.8.0.6');
    -  assertGecko('Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.6)' +
    -      'Gecko/20060808 Fedora/1.5.0.6-2.fc5 Gecko/1.5.0.6 pango-text',
    -      '1.8.0.6');
    -  assertGecko('Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8)' +
    -      'Gecko/20060321 Gecko/2.0a1', '1.8');
    -  assertGecko('Mozilla/5.0 (X11; Linux i686; rv:6.0) Gecko/6.0 Firefox/6.0',
    -      '6.0');
    -}
    -
    -function testIe() {
    -  assertIe('Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)', '5.01');
    -  assertIe('Mozilla/4.0 (compatible; MSIE 5.17; Mac_PowerPC)', '5.17');
    -  assertIe('Mozilla/4.0 (compatible; MSIE 5.23; Mac_PowerPC)', '5.23');
    -  assertIe('Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)', '5.5');
    -  assertIe('Mozilla/4.0 (compatible; MSIE 6.0; MSN 2.5; Windows 98)', '6.0');
    -  assertIe('Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)', '6.0');
    -  assertIe('Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; ' +
    -      '.NET CLR 1.1.4322)', '6.0');
    -  assertIe('Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; ' +
    -      '.NET CLR 2.0.50727)', '6.0');
    -  assertIe('Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.1)', '7.0b');
    -  assertIe('Mozilla/4.0 (compatible; MSIE 7.0b; Win32)', '7.0b');
    -  assertIe('Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 6.0)', '7.0b');
    -  assertIe('Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; SV1;' +
    -      'Arcor 5.005; .NET CLR 1.0.3705; .NET CLR 1.1.4322)', '7.0');
    -  assertIe(
    -      'Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko', '11.0');
    -}
    -
    -function testIeDocumentModeOverride() {
    -  documentMode = 9;
    -  assertIe('Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/5.0',
    -           '9');
    -  assertIe('Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/5.0',
    -           '9');
    -
    -  documentMode = 8;
    -  assertIe('Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/5.0',
    -           '8.0');
    -}
    -
    -function testDocumentModeInStandardsMode() {
    -  goog.userAgentTestUtil.reinitializeUserAgent();
    -  var expectedMode = goog.userAgent.IE ? parseInt(goog.userAgent.VERSION) :
    -                                         undefined;
    -  assertEquals(expectedMode, goog.userAgent.DOCUMENT_MODE);
    -}
    -
    -function testOpera() {
    -  var assertOpera = function(uaString) {
    -    assertUserAgent([UserAgents.OPERA], uaString);
    -  };
    -  assertOpera('Opera/7.23 (Windows 98; U) [en]');
    -  assertOpera('Opera/8.00 (Windows NT 5.1; U; en)');
    -  assertOpera('Opera/8.0 (X11; Linux i686; U; cs)');
    -  assertOpera('Opera/8.02 (Windows NT 5.1; U; en)');
    -  assertOpera('Opera/8.50 (Windows NT 5.1; U; en)');
    -  assertOpera('Opera/8.5 (X11; Linux i686; U; cs)');
    -  assertOpera('Opera/8.51 (Windows NT 5.1; U; en)');
    -  assertOpera('Opera/9.0 (Windows NT 5.0; U; en)');
    -  assertOpera('Opera/9.00 (Macintosh; PPC Mac OS X; U; en)');
    -  assertOpera('Opera/9.00 (Windows NT 5.1; U; en)');
    -  assertOpera('Opera/9.00 (Windows NT 5.2; U; en)');
    -  assertOpera('Opera/9.00 (Windows NT 6.0; U; en)');
    -}
    -
    -function testWebkit() {
    -  var testAgents = goog.labs.userAgent.testAgents;
    -  assertWebkit(testAgents.ANDROID_BROWSER_403);
    -  assertWebkit(testAgents.ANDROID_BROWSER_403_ALT);
    -}
    -
    -function testUnknownBrowser() {
    -  assertUserAgent([], 'MyWebBrowser');
    -  assertUserAgent([], undefined);
    -}
    -
    -function testNoNavigator() {
    -  // global object has no "navigator" property.
    -  var mockGlobal = {};
    -  propertyReplacer.set(goog, 'global', mockGlobal);
    -  goog.labs.userAgent.util.setUserAgent(null);
    -  goog.userAgentTestUtil.reinitializeUserAgent();
    -
    -  assertEquals('Platform should be the empty string', '',
    -      goog.userAgent.PLATFORM);
    -  assertEquals('Version should be the empty string', '',
    -      goog.userAgent.VERSION);
    -}
    -
    -function testLegacyChromeOsAndLinux() {
    -  // As a legacy behavior, goog.userAgent.LINUX considers
    -  // ChromeOS to be Linux.
    -  // goog.labs.userAgent.platform.isLinux() does not.
    -  goog.labs.userAgent.util.setUserAgent(
    -      goog.labs.userAgent.testAgents.CHROME_OS);
    -  goog.userAgentTestUtil.reinitializeUserAgent();
    -  assertTrue(goog.userAgent.LINUX);
    -  assertFalse(goog.labs.userAgent.platform.isLinux());
    -}
    -
    -function assertIe(uaString, expectedVersion) {
    -  assertUserAgent([UserAgents.IE], uaString);
    -  assertEquals('User agent ' + uaString + ' should have had version ' +
    -      expectedVersion + ' but had ' + goog.userAgent.VERSION,
    -      expectedVersion,
    -      goog.userAgent.VERSION);
    -}
    -
    -function assertGecko(uaString, expectedVersion) {
    -  assertUserAgent([UserAgents.GECKO], uaString, 'Gecko');
    -  assertEquals('User agent ' + uaString + ' should have had version ' +
    -      expectedVersion + ' but had ' + goog.userAgent.VERSION,
    -      expectedVersion,
    -      goog.userAgent.VERSION);
    -}
    -
    -function assertWebkit(uaString) {
    -  assertUserAgent([UserAgents.WEBKIT], uaString, 'WebKit');
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/useragent/useragenttestutil.js b/src/database/third_party/closure-library/closure/goog/useragent/useragenttestutil.js
    deleted file mode 100644
    index a95173f5e29..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/useragent/useragenttestutil.js
    +++ /dev/null
    @@ -1,120 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Shared test function to reset the constants in
    - * goog.userAgent.*
    - */
    -
    -goog.provide('goog.userAgentTestUtil');
    -goog.provide('goog.userAgentTestUtil.UserAgents');
    -
    -goog.require('goog.labs.userAgent.browser');
    -goog.require('goog.labs.userAgent.engine');
    -goog.require('goog.labs.userAgent.platform');
    -goog.require('goog.userAgent');
    -goog.require('goog.userAgent.keyboard');
    -goog.require('goog.userAgent.platform');
    -goog.require('goog.userAgent.product');
    -/** @suppress {extraRequire} */
    -goog.require('goog.userAgent.product.isVersion');
    -
    -goog.setTestOnly('goog.userAgentTestUtil');
    -
    -
    -/**
    - * Rerun the initialization code to set all of the goog.userAgent constants.
    - * @suppress {accessControls}
    - */
    -goog.userAgentTestUtil.reinitializeUserAgent = function() {
    -  // Unfortunately we can't isolate the useragent setting in a function
    -  // we can call, because things rely on it compiling to nothing when
    -  // one of the ASSUME flags is set, and the compiler isn't smart enough
    -  // to do that when the setting is done inside a function that's inlined.
    -  goog.userAgent.OPERA = goog.labs.userAgent.browser.isOpera();
    -  goog.userAgent.IE = goog.labs.userAgent.browser.isIE();
    -  goog.userAgent.GECKO = goog.labs.userAgent.engine.isGecko();
    -  goog.userAgent.WEBKIT = goog.labs.userAgent.engine.isWebKit();
    -  goog.userAgent.MOBILE = goog.userAgent.isMobile_();
    -  goog.userAgent.SAFARI = goog.userAgent.WEBKIT;
    -
    -  // Platform in goog.userAgent.
    -  goog.userAgent.PLATFORM = goog.userAgent.determinePlatform_();
    -
    -  goog.userAgent.MAC = goog.labs.userAgent.platform.isMacintosh();
    -  goog.userAgent.WINDOWS = goog.labs.userAgent.platform.isWindows();
    -  goog.userAgent.LINUX = goog.userAgent.isLegacyLinux_();
    -  goog.userAgent.X11 = goog.userAgent.isX11_();
    -  goog.userAgent.ANDROID = goog.labs.userAgent.platform.isAndroid();
    -  goog.userAgent.IPAD = goog.labs.userAgent.platform.isIpad();
    -  goog.userAgent.IPHONE = goog.labs.userAgent.platform.isIphone();
    -  goog.userAgent.VERSION = goog.userAgent.determineVersion_();
    -
    -  // Platform in goog.userAgent.platform.
    -  goog.userAgent.platform.VERSION = goog.userAgent.platform.determineVersion_();
    -
    -  // Update goog.userAgent.product
    -  goog.userAgent.product.ANDROID =
    -      goog.labs.userAgent.browser.isAndroidBrowser();
    -  goog.userAgent.product.CHROME =
    -      goog.labs.userAgent.browser.isChrome();
    -  goog.userAgent.product.FIREFOX =
    -      goog.labs.userAgent.browser.isFirefox();
    -  goog.userAgent.product.IE =
    -      goog.labs.userAgent.browser.isIE();
    -  goog.userAgent.product.IPAD = goog.labs.userAgent.platform.isIpad();
    -  goog.userAgent.product.IPHONE = goog.userAgent.product.isIphoneOrIpod_();
    -  goog.userAgent.product.OPERA = goog.labs.userAgent.browser.isOpera();
    -  goog.userAgent.product.SAFARI = goog.userAgent.product.isSafariDesktop_();
    -
    -  // Still uses its own implementation.
    -  goog.userAgent.product.VERSION = goog.userAgent.product.determineVersion_();
    -
    -  // goog.userAgent.keyboard
    -  goog.userAgent.keyboard.MAC_KEYBOARD =
    -      goog.userAgent.keyboard.determineMacKeyboard_();
    -};
    -
    -
    -/**
    - * Browser definitions.
    - * @enum {string}
    - */
    -goog.userAgentTestUtil.UserAgents = {
    -  GECKO: 'GECKO',
    -  IE: 'IE',
    -  OPERA: 'OPERA',
    -  WEBKIT: 'WEBKIT'
    -};
    -
    -
    -/**
    - * Return whether a given user agent has been detected.
    - * @param {string} agent Value in UserAgents.
    - * @return {boolean} Whether the user agent has been detected.
    - */
    -goog.userAgentTestUtil.getUserAgentDetected = function(agent) {
    -  switch (agent) {
    -    case goog.userAgentTestUtil.UserAgents.GECKO:
    -      return goog.userAgent.GECKO;
    -    case goog.userAgentTestUtil.UserAgents.IE:
    -      return goog.userAgent.IE;
    -    case goog.userAgentTestUtil.UserAgents.OPERA:
    -      return goog.userAgent.OPERA;
    -    case goog.userAgentTestUtil.UserAgents.WEBKIT:
    -      return goog.userAgent.WEBKIT;
    -  }
    -
    -  throw Error('Unrecognized user agent');
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/float32array.js b/src/database/third_party/closure-library/closure/goog/vec/float32array.js
    deleted file mode 100644
    index 87e37ecba4c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/float32array.js
    +++ /dev/null
    @@ -1,111 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Supplies a Float32Array implementation that implements
    - *     most of the Float32Array spec and that can be used when a built-in
    - *     implementation is not available.
    - *
    - *     Note that if no existing Float32Array implementation is found then
    - *     this class and all its public properties are exported as Float32Array.
    - *
    - *     Adding support for the other TypedArray classes here does not make sense
    - *     since this vector math library only needs Float32Array.
    - *
    - */
    -goog.provide('goog.vec.Float32Array');
    -
    -
    -
    -/**
    - * Constructs a new Float32Array. The new array is initialized to all zeros.
    - *
    - * @param {goog.vec.Float32Array|Array|ArrayBuffer|number} p0
    - *     The length of the array, or an array to initialize the contents of the
    - *     new Float32Array.
    - * @constructor
    - * @final
    - */
    -goog.vec.Float32Array = function(p0) {
    -  this.length = /** @type {number} */ (p0.length || p0);
    -  for (var i = 0; i < this.length; i++) {
    -    this[i] = p0[i] || 0;
    -  }
    -};
    -
    -
    -/**
    - * The number of bytes in an element (as defined by the Typed Array
    - * specification).
    - *
    - * @type {number}
    - */
    -goog.vec.Float32Array.BYTES_PER_ELEMENT = 4;
    -
    -
    -/**
    - * The number of bytes in an element (as defined by the Typed Array
    - * specification).
    - *
    - * @type {number}
    - */
    -goog.vec.Float32Array.prototype.BYTES_PER_ELEMENT = 4;
    -
    -
    -/**
    - * Sets elements of the array.
    - * @param {Array<number>|Float32Array} values The array of values.
    - * @param {number=} opt_offset The offset in this array to start.
    - */
    -goog.vec.Float32Array.prototype.set = function(values, opt_offset) {
    -  opt_offset = opt_offset || 0;
    -  for (var i = 0; i < values.length && opt_offset + i < this.length; i++) {
    -    this[opt_offset + i] = values[i];
    -  }
    -};
    -
    -
    -/**
    - * Creates a string representation of this array.
    - * @return {string} The string version of this array.
    - * @override
    - */
    -goog.vec.Float32Array.prototype.toString = Array.prototype.join;
    -
    -
    -/**
    - * Note that we cannot implement the subarray() or (deprecated) slice()
    - * methods properly since doing so would require being able to overload
    - * the [] operator which is not possible in javascript.  So we leave
    - * them unimplemented.  Any attempt to call these methods will just result
    - * in a javascript error since we leave them undefined.
    - */
    -
    -
    -/**
    - * If no existing Float32Array implementation is found then we export
    - * goog.vec.Float32Array as Float32Array.
    - */
    -if (typeof Float32Array == 'undefined') {
    -  goog.exportProperty(goog.vec.Float32Array, 'BYTES_PER_ELEMENT',
    -                      goog.vec.Float32Array.BYTES_PER_ELEMENT);
    -  goog.exportProperty(goog.vec.Float32Array.prototype, 'BYTES_PER_ELEMENT',
    -                      goog.vec.Float32Array.prototype.BYTES_PER_ELEMENT);
    -  goog.exportProperty(goog.vec.Float32Array.prototype, 'set',
    -                      goog.vec.Float32Array.prototype.set);
    -  goog.exportProperty(goog.vec.Float32Array.prototype, 'toString',
    -                      goog.vec.Float32Array.prototype.toString);
    -  goog.exportSymbol('Float32Array', goog.vec.Float32Array);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/float32array_test.html b/src/database/third_party/closure-library/closure/goog/vec/float32array_test.html
    deleted file mode 100644
    index 227797d47a0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/float32array_test.html
    +++ /dev/null
    @@ -1,69 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.vec.Float32Array</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.vec.Float32Array');
    -  goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -  function testConstructorInitializesElementsToZero() {
    -    var f = new goog.vec.Float32Array(3);
    -    assertEquals(3, f.length);
    -    assertEquals(0, f[0]);
    -    assertEquals(0, f[1]);
    -    assertEquals(0, f[2]);
    -    assertEquals(4, f.BYTES_PER_ELEMENT);
    -    assertEquals(4, goog.vec.Float32Array.BYTES_PER_ELEMENT);
    -  }
    -
    -  function testConstructorWithArrayAsArgument() {
    -    var f0 = new goog.vec.Float32Array([0, 0, 1, 0]);
    -    var f1 = new goog.vec.Float32Array(4);
    -    f1[0] = 0;
    -    f1[1] = 0;
    -    f1[2] = 1;
    -    f1[3] = 0;
    -    assertObjectEquals(f0, f1);
    -  }
    -
    -  function testSet() {
    -    var f0 = new goog.vec.Float32Array(4);
    -    var f1 = new goog.vec.Float32Array(4);
    -    f0.set([1, 2, 3, 4]);
    -    f1[0] = 1;
    -    f1[1] = 2;
    -    f1[2] = 3;
    -    f1[3] = 4;
    -    assertObjectEquals(f0, f1);
    -  }
    -
    -  function testSetWithOffset() {
    -    var f0 = new goog.vec.Float32Array(4);
    -    var f1 = new goog.vec.Float32Array(4);
    -    f0.set([5], 1);
    -    f1[0] = 0;
    -    f1[1] = 5;
    -    f1[2] = 0;
    -    f1[3] = 0;
    -    assertObjectEquals(f0, f1);
    -  }
    -
    -  function testToString() {
    -    var f = new goog.vec.Float32Array([4, 3, 2, 1]);
    -    assertEquals('4,3,2,1', f.toString());
    -  }
    -
    -</script>
    -</body>
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/float64array.js b/src/database/third_party/closure-library/closure/goog/vec/float64array.js
    deleted file mode 100644
    index a71c97d1013..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/float64array.js
    +++ /dev/null
    @@ -1,118 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Supplies a Float64Array implementation that implements
    - * most of the Float64Array spec and that can be used when a built-in
    - * implementation is not available.
    - *
    - * Note that if no existing Float64Array implementation is found then this
    - * class and all its public properties are exported as Float64Array.
    - *
    - * Adding support for the other TypedArray classes here does not make sense
    - * since this vector math library only needs Float32Array and Float64Array.
    - *
    - */
    -goog.provide('goog.vec.Float64Array');
    -
    -
    -
    -/**
    - * Constructs a new Float64Array. The new array is initialized to all zeros.
    - *
    - * @param {goog.vec.Float64Array|Array|ArrayBuffer|number} p0
    - *     The length of the array, or an array to initialize the contents of the
    - *     new Float64Array.
    - * @constructor
    - * @final
    - */
    -goog.vec.Float64Array = function(p0) {
    -  this.length = /** @type {number} */ (p0.length || p0);
    -  for (var i = 0; i < this.length; i++) {
    -    this[i] = p0[i] || 0;
    -  }
    -};
    -
    -
    -/**
    - * The number of bytes in an element (as defined by the Typed Array
    - * specification).
    - *
    - * @type {number}
    - */
    -goog.vec.Float64Array.BYTES_PER_ELEMENT = 8;
    -
    -
    -/**
    - * The number of bytes in an element (as defined by the Typed Array
    - * specification).
    - *
    - * @type {number}
    - */
    -goog.vec.Float64Array.prototype.BYTES_PER_ELEMENT = 8;
    -
    -
    -/**
    - * Sets elements of the array.
    - * @param {Array<number>|Float64Array} values The array of values.
    - * @param {number=} opt_offset The offset in this array to start.
    - */
    -goog.vec.Float64Array.prototype.set = function(values, opt_offset) {
    -  opt_offset = opt_offset || 0;
    -  for (var i = 0; i < values.length && opt_offset + i < this.length; i++) {
    -    this[opt_offset + i] = values[i];
    -  }
    -};
    -
    -
    -/**
    - * Creates a string representation of this array.
    - * @return {string} The string version of this array.
    - * @override
    - */
    -goog.vec.Float64Array.prototype.toString = Array.prototype.join;
    -
    -
    -/**
    - * Note that we cannot implement the subarray() or (deprecated) slice()
    - * methods properly since doing so would require being able to overload
    - * the [] operator which is not possible in javascript.  So we leave
    - * them unimplemented.  Any attempt to call these methods will just result
    - * in a javascript error since we leave them undefined.
    - */
    -
    -
    -/**
    - * If no existing Float64Array implementation is found then we export
    - * goog.vec.Float64Array as Float64Array.
    - */
    -if (typeof Float64Array == 'undefined') {
    -  try {
    -    goog.exportProperty(goog.vec.Float64Array, 'BYTES_PER_ELEMENT',
    -                        goog.vec.Float64Array.BYTES_PER_ELEMENT);
    -  } catch (float64ArrayError) {
    -    // Do nothing.  This code is in place to fix b/7225850, in which an error
    -    // is incorrectly thrown for Google TV on an old Chrome.
    -    // TODO(user): remove after that version is retired.
    -  }
    -
    -  goog.exportProperty(goog.vec.Float64Array.prototype, 'BYTES_PER_ELEMENT',
    -                      goog.vec.Float64Array.prototype.BYTES_PER_ELEMENT);
    -  goog.exportProperty(goog.vec.Float64Array.prototype, 'set',
    -                      goog.vec.Float64Array.prototype.set);
    -  goog.exportProperty(goog.vec.Float64Array.prototype, 'toString',
    -                      goog.vec.Float64Array.prototype.toString);
    -  goog.exportSymbol('Float64Array', goog.vec.Float64Array);
    -}
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/float64array_test.html b/src/database/third_party/closure-library/closure/goog/vec/float64array_test.html
    deleted file mode 100644
    index 0e72e00924e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/float64array_test.html
    +++ /dev/null
    @@ -1,69 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.vec.Float64Array</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.vec.Float64Array');
    -  goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -  function testConstructorInitializesElementsToZero() {
    -    var f = new goog.vec.Float64Array(3);
    -    assertEquals(3, f.length);
    -    assertEquals(0, f[0]);
    -    assertEquals(0, f[1]);
    -    assertEquals(0, f[2]);
    -    assertEquals(8, f.BYTES_PER_ELEMENT);
    -    assertEquals(8, goog.vec.Float64Array.BYTES_PER_ELEMENT);
    -  }
    -
    -  function testConstructorWithArrayAsArgument() {
    -    var f0 = new goog.vec.Float64Array([0, 0, 1, 0]);
    -    var f1 = new goog.vec.Float64Array(4);
    -    f1[0] = 0;
    -    f1[1] = 0;
    -    f1[2] = 1;
    -    f1[3] = 0;
    -    assertObjectEquals(f0, f1);
    -  }
    -
    -  function testSet() {
    -    var f0 = new goog.vec.Float64Array(4);
    -    var f1 = new goog.vec.Float64Array(4);
    -    f0.set([1, 2, 3, 4]);
    -    f1[0] = 1;
    -    f1[1] = 2;
    -    f1[2] = 3;
    -    f1[3] = 4;
    -    assertObjectEquals(f0, f1);
    -  }
    -
    -  function testSetWithOffset() {
    -    var f0 = new goog.vec.Float64Array(4);
    -    var f1 = new goog.vec.Float64Array(4);
    -    f0.set([5], 1);
    -    f1[0] = 0;
    -    f1[1] = 5;
    -    f1[2] = 0;
    -    f1[3] = 0;
    -    assertObjectEquals(f0, f1);
    -  }
    -
    -  function testToString() {
    -    var f = new goog.vec.Float64Array([4, 3, 2, 1]);
    -    assertEquals('4,3,2,1', f.toString());
    -  }
    -
    -</script>
    -</body>
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/mat3.js b/src/database/third_party/closure-library/closure/goog/vec/mat3.js
    deleted file mode 100644
    index cb747e344f6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/mat3.js
    +++ /dev/null
    @@ -1,1211 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Implements 3x3 matrices and their related functions which are
    - * compatible with WebGL. The API is structured to avoid unnecessary memory
    - * allocations.  The last parameter will typically be the output vector and
    - * an object can be both an input and output parameter to all methods except
    - * where noted. Matrix operations follow the mathematical form when multiplying
    - * vectors as follows: resultVec = matrix * vec.
    - *
    - * The matrices are stored in column-major order.
    - *
    - */
    -goog.provide('goog.vec.Mat3');
    -
    -goog.require('goog.vec');
    -
    -
    -/** @typedef {goog.vec.Float32} */ goog.vec.Mat3.Float32;
    -/** @typedef {goog.vec.Float64} */ goog.vec.Mat3.Float64;
    -/** @typedef {goog.vec.Number} */ goog.vec.Mat3.Number;
    -/** @typedef {goog.vec.AnyType} */ goog.vec.Mat3.AnyType;
    -
    -// The following two types are deprecated - use the above types instead.
    -/** @typedef {Float32Array} */ goog.vec.Mat3.Type;
    -/** @typedef {goog.vec.ArrayType} */ goog.vec.Mat3.Mat3Like;
    -
    -
    -/**
    - * Creates the array representation of a 3x3 matrix of Float32.
    - * The use of the array directly instead of a class reduces overhead.
    - * The returned matrix is cleared to all zeros.
    - *
    - * @return {!goog.vec.Mat3.Float32} The new matrix.
    - */
    -goog.vec.Mat3.createFloat32 = function() {
    -  return new Float32Array(9);
    -};
    -
    -
    -/**
    - * Creates the array representation of a 3x3 matrix of Float64.
    - * The returned matrix is cleared to all zeros.
    - *
    - * @return {!goog.vec.Mat3.Float64} The new matrix.
    - */
    -goog.vec.Mat3.createFloat64 = function() {
    -  return new Float64Array(9);
    -};
    -
    -
    -/**
    - * Creates the array representation of a 3x3 matrix of Number.
    - * The returned matrix is cleared to all zeros.
    - *
    - * @return {!goog.vec.Mat3.Number} The new matrix.
    - */
    -goog.vec.Mat3.createNumber = function() {
    -  var a = new Array(9);
    -  goog.vec.Mat3.setFromValues(a,
    -                              0, 0, 0,
    -                              0, 0, 0,
    -                              0, 0, 0);
    -  return a;
    -};
    -
    -
    -/**
    - * Creates the array representation of a 3x3 matrix of Float32.
    - * The returned matrix is cleared to all zeros.
    - *
    - * @deprecated Use createFloat32.
    - * @return {!goog.vec.Mat3.Type} The new matrix.
    - */
    -goog.vec.Mat3.create = function() {
    -  return goog.vec.Mat3.createFloat32();
    -};
    -
    -
    -/**
    - * Creates a 3x3 identity matrix of Float32.
    - *
    - * @return {!goog.vec.Mat3.Float32} The new 9 element array.
    - */
    -goog.vec.Mat3.createFloat32Identity = function() {
    -  var mat = goog.vec.Mat3.createFloat32();
    -  mat[0] = mat[4] = mat[8] = 1;
    -  return mat;
    -};
    -
    -
    -/**
    - * Creates a 3x3 identity matrix of Float64.
    - *
    - * @return {!goog.vec.Mat3.Float64} The new 9 element array.
    - */
    -goog.vec.Mat3.createFloat64Identity = function() {
    -  var mat = goog.vec.Mat3.createFloat64();
    -  mat[0] = mat[4] = mat[8] = 1;
    -  return mat;
    -};
    -
    -
    -/**
    - * Creates a 3x3 identity matrix of Number.
    - * The returned matrix is cleared to all zeros.
    - *
    - * @return {!goog.vec.Mat3.Number} The new 9 element array.
    - */
    -goog.vec.Mat3.createNumberIdentity = function() {
    -  var a = new Array(9);
    -  goog.vec.Mat3.setFromValues(a,
    -                              1, 0, 0,
    -                              0, 1, 0,
    -                              0, 0, 1);
    -  return a;
    -};
    -
    -
    -/**
    - * Creates the array representation of a 3x3 matrix of Float32.
    - * The returned matrix is cleared to all zeros.
    - *
    - * @deprecated Use createFloat32Identity.
    - * @return {!goog.vec.Mat3.Type} The new 9 element array.
    - */
    -goog.vec.Mat3.createIdentity = function() {
    -  return goog.vec.Mat3.createFloat32Identity();
    -};
    -
    -
    -/**
    - * Creates a 3x3 matrix of Float32 initialized from the given array.
    - *
    - * @param {goog.vec.Mat3.AnyType} matrix The array containing the
    - *     matrix values in column major order.
    - * @return {!goog.vec.Mat3.Float32} The new, nine element array.
    - */
    -goog.vec.Mat3.createFloat32FromArray = function(matrix) {
    -  var newMatrix = goog.vec.Mat3.createFloat32();
    -  goog.vec.Mat3.setFromArray(newMatrix, matrix);
    -  return newMatrix;
    -};
    -
    -
    -/**
    - * Creates a 3x3 matrix of Float32 initialized from the given values.
    - *
    - * @param {number} v00 The values at (0, 0).
    - * @param {number} v10 The values at (1, 0).
    - * @param {number} v20 The values at (2, 0).
    - * @param {number} v01 The values at (0, 1).
    - * @param {number} v11 The values at (1, 1).
    - * @param {number} v21 The values at (2, 1).
    - * @param {number} v02 The values at (0, 2).
    - * @param {number} v12 The values at (1, 2).
    - * @param {number} v22 The values at (2, 2).
    - * @return {!goog.vec.Mat3.Float32} The new, nine element array.
    - */
    -goog.vec.Mat3.createFloat32FromValues = function(
    -    v00, v10, v20, v01, v11, v21, v02, v12, v22) {
    -  var newMatrix = goog.vec.Mat3.createFloat32();
    -  goog.vec.Mat3.setFromValues(
    -      newMatrix, v00, v10, v20, v01, v11, v21, v02, v12, v22);
    -  return newMatrix;
    -};
    -
    -
    -/**
    - * Creates a clone of a 3x3 matrix of Float32.
    - *
    - * @param {goog.vec.Mat3.Float32} matrix The source 3x3 matrix.
    - * @return {!goog.vec.Mat3.Float32} The new 3x3 element matrix.
    - */
    -goog.vec.Mat3.cloneFloat32 = goog.vec.Mat3.createFloat32FromArray;
    -
    -
    -/**
    - * Creates a 3x3 matrix of Float64 initialized from the given array.
    - *
    - * @param {goog.vec.Mat3.AnyType} matrix The array containing the
    - *     matrix values in column major order.
    - * @return {!goog.vec.Mat3.Float64} The new, nine element array.
    - */
    -goog.vec.Mat3.createFloat64FromArray = function(matrix) {
    -  var newMatrix = goog.vec.Mat3.createFloat64();
    -  goog.vec.Mat3.setFromArray(newMatrix, matrix);
    -  return newMatrix;
    -};
    -
    -
    -/**
    - * Creates a 3x3 matrix of Float64 initialized from the given values.
    - *
    - * @param {number} v00 The values at (0, 0).
    - * @param {number} v10 The values at (1, 0).
    - * @param {number} v20 The values at (2, 0).
    - * @param {number} v01 The values at (0, 1).
    - * @param {number} v11 The values at (1, 1).
    - * @param {number} v21 The values at (2, 1).
    - * @param {number} v02 The values at (0, 2).
    - * @param {number} v12 The values at (1, 2).
    - * @param {number} v22 The values at (2, 2).
    - * @return {!goog.vec.Mat3.Float64} The new, nine element array.
    - */
    -goog.vec.Mat3.createFloat64FromValues = function(
    -    v00, v10, v20, v01, v11, v21, v02, v12, v22) {
    -  var newMatrix = goog.vec.Mat3.createFloat64();
    -  goog.vec.Mat3.setFromValues(
    -      newMatrix, v00, v10, v20, v01, v11, v21, v02, v12, v22);
    -  return newMatrix;
    -};
    -
    -
    -/**
    - * Creates a clone of a 3x3 matrix of Float64.
    - *
    - * @param {goog.vec.Mat3.Float64} matrix The source 3x3 matrix.
    - * @return {!goog.vec.Mat3.Float64} The new 3x3 element matrix.
    - */
    -goog.vec.Mat3.cloneFloat64 = goog.vec.Mat3.createFloat64FromArray;
    -
    -
    -/**
    - * Creates a 3x3 matrix of Float32 initialized from the given array.
    - *
    - * @deprecated Use createFloat32FromArray.
    - * @param {goog.vec.Mat3.Mat3Like} matrix The array containing the
    - *     matrix values in column major order.
    - * @return {!goog.vec.Mat3.Type} The new, nine element array.
    - */
    -goog.vec.Mat3.createFromArray = function(matrix) {
    -  var newMatrix = goog.vec.Mat3.createFloat32();
    -  goog.vec.Mat3.setFromArray(newMatrix, matrix);
    -  return newMatrix;
    -};
    -
    -
    -/**
    - * Creates a 3x3 matrix of Float32 initialized from the given values.
    - *
    - * @deprecated Use createFloat32FromValues.
    - * @param {number} v00 The values at (0, 0).
    - * @param {number} v10 The values at (1, 0).
    - * @param {number} v20 The values at (2, 0).
    - * @param {number} v01 The values at (0, 1).
    - * @param {number} v11 The values at (1, 1).
    - * @param {number} v21 The values at (2, 1).
    - * @param {number} v02 The values at (0, 2).
    - * @param {number} v12 The values at (1, 2).
    - * @param {number} v22 The values at (2, 2).
    - * @return {!goog.vec.Mat3.Type} The new, nine element array.
    - */
    -goog.vec.Mat3.createFromValues = function(
    -    v00, v10, v20, v01, v11, v21, v02, v12, v22) {
    -  var newMatrix = goog.vec.Mat3.create();
    -  goog.vec.Mat3.setFromValues(
    -      newMatrix, v00, v10, v20, v01, v11, v21, v02, v12, v22);
    -  return newMatrix;
    -};
    -
    -
    -/**
    - * Creates a clone of a 3x3 matrix of Float32.
    - *
    - * @deprecated Use cloneFloat32.
    - * @param {goog.vec.Mat3.Mat3Like} matrix The source 3x3 matrix.
    - * @return {!goog.vec.Mat3.Type} The new 3x3 element matrix.
    - */
    -goog.vec.Mat3.clone = goog.vec.Mat3.createFromArray;
    -
    -
    -/**
    - * Retrieves the element at the requested row and column.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix containing the value to
    - *     retrieve.
    - * @param {number} row The row index.
    - * @param {number} column The column index.
    - * @return {number} The element value at the requested row, column indices.
    - */
    -goog.vec.Mat3.getElement = function(mat, row, column) {
    -  return mat[row + column * 3];
    -};
    -
    -
    -/**
    - * Sets the element at the requested row and column.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix containing the value to
    - *     retrieve.
    - * @param {number} row The row index.
    - * @param {number} column The column index.
    - * @param {number} value The value to set at the requested row, column.
    - * @return {goog.vec.Mat3.AnyType} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat3.setElement = function(mat, row, column, value) {
    -  mat[row + column * 3] = value;
    -  return mat;
    -};
    -
    -
    -/**
    - * Initializes the matrix from the set of values. Note the values supplied are
    - * in column major order.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix to receive the
    - *     values.
    - * @param {number} v00 The values at (0, 0).
    - * @param {number} v10 The values at (1, 0).
    - * @param {number} v20 The values at (2, 0).
    - * @param {number} v01 The values at (0, 1).
    - * @param {number} v11 The values at (1, 1).
    - * @param {number} v21 The values at (2, 1).
    - * @param {number} v02 The values at (0, 2).
    - * @param {number} v12 The values at (1, 2).
    - * @param {number} v22 The values at (2, 2).
    - * @return {goog.vec.Mat3.AnyType} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat3.setFromValues = function(
    -    mat, v00, v10, v20, v01, v11, v21, v02, v12, v22) {
    -  mat[0] = v00;
    -  mat[1] = v10;
    -  mat[2] = v20;
    -  mat[3] = v01;
    -  mat[4] = v11;
    -  mat[5] = v21;
    -  mat[6] = v02;
    -  mat[7] = v12;
    -  mat[8] = v22;
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the matrix from the array of values stored in column major order.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix to receive the values.
    - * @param {goog.vec.Mat3.AnyType} values The column major ordered
    - *     array of values to store in the matrix.
    - * @return {goog.vec.Mat3.AnyType} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat3.setFromArray = function(mat, values) {
    -  mat[0] = values[0];
    -  mat[1] = values[1];
    -  mat[2] = values[2];
    -  mat[3] = values[3];
    -  mat[4] = values[4];
    -  mat[5] = values[5];
    -  mat[6] = values[6];
    -  mat[7] = values[7];
    -  mat[8] = values[8];
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the matrix from the array of values stored in row major order.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix to receive the values.
    - * @param {goog.vec.Mat3.AnyType} values The row major ordered array
    - *     of values to store in the matrix.
    - * @return {goog.vec.Mat3.AnyType} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat3.setFromRowMajorArray = function(mat, values) {
    -  mat[0] = values[0];
    -  mat[1] = values[3];
    -  mat[2] = values[6];
    -  mat[3] = values[1];
    -  mat[4] = values[4];
    -  mat[5] = values[7];
    -  mat[6] = values[2];
    -  mat[7] = values[5];
    -  mat[8] = values[8];
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the diagonal values of the matrix from the given values.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix to receive the values.
    - * @param {number} v00 The values for (0, 0).
    - * @param {number} v11 The values for (1, 1).
    - * @param {number} v22 The values for (2, 2).
    - * @return {goog.vec.Mat3.AnyType} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat3.setDiagonalValues = function(mat, v00, v11, v22) {
    -  mat[0] = v00;
    -  mat[4] = v11;
    -  mat[8] = v22;
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the diagonal values of the matrix from the given vector.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix to receive the values.
    - * @param {goog.vec.Vec3.AnyType} vec The vector containing the values.
    - * @return {goog.vec.Mat3.AnyType} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat3.setDiagonal = function(mat, vec) {
    -  mat[0] = vec[0];
    -  mat[4] = vec[1];
    -  mat[8] = vec[2];
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the specified column with the supplied values.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix to recieve the values.
    - * @param {number} column The column index to set the values on.
    - * @param {number} v0 The value for row 0.
    - * @param {number} v1 The value for row 1.
    - * @param {number} v2 The value for row 2.
    - * @return {goog.vec.Mat3.AnyType} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat3.setColumnValues = function(mat, column, v0, v1, v2) {
    -  var i = column * 3;
    -  mat[i] = v0;
    -  mat[i + 1] = v1;
    -  mat[i + 2] = v2;
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the specified column with the value from the supplied array.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix to receive the values.
    - * @param {number} column The column index to set the values on.
    - * @param {goog.vec.Vec3.AnyType} vec The vector elements for the column.
    - * @return {goog.vec.Mat3.AnyType} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat3.setColumn = function(mat, column, vec) {
    -  var i = column * 3;
    -  mat[i] = vec[0];
    -  mat[i + 1] = vec[1];
    -  mat[i + 2] = vec[2];
    -  return mat;
    -};
    -
    -
    -/**
    - * Retrieves the specified column from the matrix into the given vector
    - * array.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix supplying the values.
    - * @param {number} column The column to get the values from.
    - * @param {goog.vec.Vec3.AnyType} vec The vector elements to receive the
    - *     column.
    - * @return {goog.vec.Vec3.AnyType} return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat3.getColumn = function(mat, column, vec) {
    -  var i = column * 3;
    -  vec[0] = mat[i];
    -  vec[1] = mat[i + 1];
    -  vec[2] = mat[i + 2];
    -  return vec;
    -};
    -
    -
    -/**
    - * Sets the columns of the matrix from the set of vector elements.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix to receive the values.
    - * @param {goog.vec.Vec3.AnyType} vec0 The values for column 0.
    - * @param {goog.vec.Vec3.AnyType} vec1 The values for column 1.
    - * @param {goog.vec.Vec3.AnyType} vec2 The values for column 2.
    - * @return {goog.vec.Mat3.AnyType} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat3.setColumns = function(mat, vec0, vec1, vec2) {
    -  goog.vec.Mat3.setColumn(mat, 0, vec0);
    -  goog.vec.Mat3.setColumn(mat, 1, vec1);
    -  goog.vec.Mat3.setColumn(mat, 2, vec2);
    -  return mat;
    -};
    -
    -
    -/**
    - * Retrieves the column values from the given matrix into the given vector
    - * elements.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix supplying the columns.
    - * @param {goog.vec.Vec3.AnyType} vec0 The vector to receive column 0.
    - * @param {goog.vec.Vec3.AnyType} vec1 The vector to receive column 1.
    - * @param {goog.vec.Vec3.AnyType} vec2 The vector to receive column 2.
    - */
    -goog.vec.Mat3.getColumns = function(mat, vec0, vec1, vec2) {
    -  goog.vec.Mat3.getColumn(mat, 0, vec0);
    -  goog.vec.Mat3.getColumn(mat, 1, vec1);
    -  goog.vec.Mat3.getColumn(mat, 2, vec2);
    -};
    -
    -
    -/**
    - * Sets the row values from the supplied values.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix to receive the values.
    - * @param {number} row The index of the row to receive the values.
    - * @param {number} v0 The value for column 0.
    - * @param {number} v1 The value for column 1.
    - * @param {number} v2 The value for column 2.
    - * @return {goog.vec.Mat3.AnyType} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat3.setRowValues = function(mat, row, v0, v1, v2) {
    -  mat[row] = v0;
    -  mat[row + 3] = v1;
    -  mat[row + 6] = v2;
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the row values from the supplied vector.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix to receive the row values.
    - * @param {number} row The index of the row.
    - * @param {goog.vec.Vec3.AnyType} vec The vector containing the values.
    - * @return {goog.vec.Mat3.AnyType} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat3.setRow = function(mat, row, vec) {
    -  mat[row] = vec[0];
    -  mat[row + 3] = vec[1];
    -  mat[row + 6] = vec[2];
    -  return mat;
    -};
    -
    -
    -/**
    - * Retrieves the row values into the given vector.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix supplying the values.
    - * @param {number} row The index of the row supplying the values.
    - * @param {goog.vec.Vec3.AnyType} vec The vector to receive the row.
    - * @return {goog.vec.Vec3.AnyType} return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat3.getRow = function(mat, row, vec) {
    -  vec[0] = mat[row];
    -  vec[1] = mat[row + 3];
    -  vec[2] = mat[row + 6];
    -  return vec;
    -};
    -
    -
    -/**
    - * Sets the rows of the matrix from the supplied vectors.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix to receive the values.
    - * @param {goog.vec.Vec3.AnyType} vec0 The values for row 0.
    - * @param {goog.vec.Vec3.AnyType} vec1 The values for row 1.
    - * @param {goog.vec.Vec3.AnyType} vec2 The values for row 2.
    - * @return {goog.vec.Mat3.AnyType} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat3.setRows = function(mat, vec0, vec1, vec2) {
    -  goog.vec.Mat3.setRow(mat, 0, vec0);
    -  goog.vec.Mat3.setRow(mat, 1, vec1);
    -  goog.vec.Mat3.setRow(mat, 2, vec2);
    -  return mat;
    -};
    -
    -
    -/**
    - * Retrieves the rows of the matrix into the supplied vectors.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix to supplying the values.
    - * @param {goog.vec.Vec3.AnyType} vec0 The vector to receive row 0.
    - * @param {goog.vec.Vec3.AnyType} vec1 The vector to receive row 1.
    - * @param {goog.vec.Vec3.AnyType} vec2 The vector to receive row 2.
    - */
    -goog.vec.Mat3.getRows = function(mat, vec0, vec1, vec2) {
    -  goog.vec.Mat3.getRow(mat, 0, vec0);
    -  goog.vec.Mat3.getRow(mat, 1, vec1);
    -  goog.vec.Mat3.getRow(mat, 2, vec2);
    -};
    -
    -
    -/**
    - * Makes the given 3x3 matrix the zero matrix.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix.
    - * @return {goog.vec.Mat3.AnyType} return mat so operations can be chained.
    - */
    -goog.vec.Mat3.makeZero = function(mat) {
    -  mat[0] = 0;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 0;
    -  mat[5] = 0;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = 0;
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 3x3 matrix the identity matrix.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix.
    - * @return {goog.vec.Mat3.AnyType} return mat so operations can be chained.
    - */
    -goog.vec.Mat3.makeIdentity = function(mat) {
    -  mat[0] = 1;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 1;
    -  mat[5] = 0;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = 1;
    -  return mat;
    -};
    -
    -
    -/**
    - * Performs a per-component addition of the matrices mat0 and mat1, storing
    - * the result into resultMat.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat0 The first addend.
    - * @param {goog.vec.Mat3.AnyType} mat1 The second addend.
    - * @param {goog.vec.Mat3.AnyType} resultMat The matrix to
    - *     receive the results (may be either mat0 or mat1).
    - * @return {goog.vec.Mat3.AnyType} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat3.addMat = function(mat0, mat1, resultMat) {
    -  resultMat[0] = mat0[0] + mat1[0];
    -  resultMat[1] = mat0[1] + mat1[1];
    -  resultMat[2] = mat0[2] + mat1[2];
    -  resultMat[3] = mat0[3] + mat1[3];
    -  resultMat[4] = mat0[4] + mat1[4];
    -  resultMat[5] = mat0[5] + mat1[5];
    -  resultMat[6] = mat0[6] + mat1[6];
    -  resultMat[7] = mat0[7] + mat1[7];
    -  resultMat[8] = mat0[8] + mat1[8];
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Performs a per-component subtraction of the matrices mat0 and mat1,
    - * storing the result into resultMat.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat0 The minuend.
    - * @param {goog.vec.Mat3.AnyType} mat1 The subtrahend.
    - * @param {goog.vec.Mat3.AnyType} resultMat The matrix to receive
    - *     the results (may be either mat0 or mat1).
    - * @return {goog.vec.Mat3.AnyType} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat3.subMat = function(mat0, mat1, resultMat) {
    -  resultMat[0] = mat0[0] - mat1[0];
    -  resultMat[1] = mat0[1] - mat1[1];
    -  resultMat[2] = mat0[2] - mat1[2];
    -  resultMat[3] = mat0[3] - mat1[3];
    -  resultMat[4] = mat0[4] - mat1[4];
    -  resultMat[5] = mat0[5] - mat1[5];
    -  resultMat[6] = mat0[6] - mat1[6];
    -  resultMat[7] = mat0[7] - mat1[7];
    -  resultMat[8] = mat0[8] - mat1[8];
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Multiplies matrix mat0 with the given scalar, storing the result
    - * into resultMat.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix.
    - * @param {number} scalar The scalar value to multiple to each element of mat.
    - * @param {goog.vec.Mat3.AnyType} resultMat The matrix to receive
    - *     the results (may be mat).
    - * @return {goog.vec.Mat3.AnyType} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat3.multScalar = function(mat, scalar, resultMat) {
    -  resultMat[0] = mat[0] * scalar;
    -  resultMat[1] = mat[1] * scalar;
    -  resultMat[2] = mat[2] * scalar;
    -  resultMat[3] = mat[3] * scalar;
    -  resultMat[4] = mat[4] * scalar;
    -  resultMat[5] = mat[5] * scalar;
    -  resultMat[6] = mat[6] * scalar;
    -  resultMat[7] = mat[7] * scalar;
    -  resultMat[8] = mat[8] * scalar;
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Multiplies the two matrices mat0 and mat1 using matrix multiplication,
    - * storing the result into resultMat.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat0 The first (left hand) matrix.
    - * @param {goog.vec.Mat3.AnyType} mat1 The second (right hand) matrix.
    - * @param {goog.vec.Mat3.AnyType} resultMat The matrix to receive
    - *     the results (may be either mat0 or mat1).
    - * @return {goog.vec.Mat3.AnyType} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat3.multMat = function(mat0, mat1, resultMat) {
    -  var a00 = mat0[0], a10 = mat0[1], a20 = mat0[2];
    -  var a01 = mat0[3], a11 = mat0[4], a21 = mat0[5];
    -  var a02 = mat0[6], a12 = mat0[7], a22 = mat0[8];
    -
    -  var b00 = mat1[0], b10 = mat1[1], b20 = mat1[2];
    -  var b01 = mat1[3], b11 = mat1[4], b21 = mat1[5];
    -  var b02 = mat1[6], b12 = mat1[7], b22 = mat1[8];
    -
    -  resultMat[0] = a00 * b00 + a01 * b10 + a02 * b20;
    -  resultMat[1] = a10 * b00 + a11 * b10 + a12 * b20;
    -  resultMat[2] = a20 * b00 + a21 * b10 + a22 * b20;
    -  resultMat[3] = a00 * b01 + a01 * b11 + a02 * b21;
    -  resultMat[4] = a10 * b01 + a11 * b11 + a12 * b21;
    -  resultMat[5] = a20 * b01 + a21 * b11 + a22 * b21;
    -  resultMat[6] = a00 * b02 + a01 * b12 + a02 * b22;
    -  resultMat[7] = a10 * b02 + a11 * b12 + a12 * b22;
    -  resultMat[8] = a20 * b02 + a21 * b12 + a22 * b22;
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Transposes the given matrix mat storing the result into resultMat.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix to transpose.
    - * @param {goog.vec.Mat3.AnyType} resultMat The matrix to receive
    - *     the results (may be mat).
    - * @return {goog.vec.Mat3.AnyType} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat3.transpose = function(mat, resultMat) {
    -  if (resultMat == mat) {
    -    var a10 = mat[1], a20 = mat[2], a21 = mat[5];
    -    resultMat[1] = mat[3];
    -    resultMat[2] = mat[6];
    -    resultMat[3] = a10;
    -    resultMat[5] = mat[7];
    -    resultMat[6] = a20;
    -    resultMat[7] = a21;
    -  } else {
    -    resultMat[0] = mat[0];
    -    resultMat[1] = mat[3];
    -    resultMat[2] = mat[6];
    -    resultMat[3] = mat[1];
    -    resultMat[4] = mat[4];
    -    resultMat[5] = mat[7];
    -    resultMat[6] = mat[2];
    -    resultMat[7] = mat[5];
    -    resultMat[8] = mat[8];
    -  }
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Computes the inverse of mat0 storing the result into resultMat. If the
    - * inverse is defined, this function returns true, false otherwise.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat0 The matrix to invert.
    - * @param {goog.vec.Mat3.AnyType} resultMat The matrix to receive
    - *     the result (may be mat0).
    - * @return {boolean} True if the inverse is defined. If false is returned,
    - *     resultMat is not modified.
    - */
    -goog.vec.Mat3.invert = function(mat0, resultMat) {
    -  var a00 = mat0[0], a10 = mat0[1], a20 = mat0[2];
    -  var a01 = mat0[3], a11 = mat0[4], a21 = mat0[5];
    -  var a02 = mat0[6], a12 = mat0[7], a22 = mat0[8];
    -
    -  var t00 = a11 * a22 - a12 * a21;
    -  var t10 = a12 * a20 - a10 * a22;
    -  var t20 = a10 * a21 - a11 * a20;
    -  var det = a00 * t00 + a01 * t10 + a02 * t20;
    -  if (det == 0) {
    -    return false;
    -  }
    -
    -  var idet = 1 / det;
    -  resultMat[0] = t00 * idet;
    -  resultMat[3] = (a02 * a21 - a01 * a22) * idet;
    -  resultMat[6] = (a01 * a12 - a02 * a11) * idet;
    -
    -  resultMat[1] = t10 * idet;
    -  resultMat[4] = (a00 * a22 - a02 * a20) * idet;
    -  resultMat[7] = (a02 * a10 - a00 * a12) * idet;
    -
    -  resultMat[2] = t20 * idet;
    -  resultMat[5] = (a01 * a20 - a00 * a21) * idet;
    -  resultMat[8] = (a00 * a11 - a01 * a10) * idet;
    -  return true;
    -};
    -
    -
    -/**
    - * Returns true if the components of mat0 are equal to the components of mat1.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat0 The first matrix.
    - * @param {goog.vec.Mat3.AnyType} mat1 The second matrix.
    - * @return {boolean} True if the the two matrices are equivalent.
    - */
    -goog.vec.Mat3.equals = function(mat0, mat1) {
    -  return mat0.length == mat1.length &&
    -      mat0[0] == mat1[0] && mat0[1] == mat1[1] && mat0[2] == mat1[2] &&
    -      mat0[3] == mat1[3] && mat0[4] == mat1[4] && mat0[5] == mat1[5] &&
    -      mat0[6] == mat1[6] && mat0[7] == mat1[7] && mat0[8] == mat1[8];
    -};
    -
    -
    -/**
    - * Transforms the given vector with the given matrix storing the resulting,
    - * transformed matrix into resultVec.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix supplying the transformation.
    - * @param {goog.vec.Vec3.AnyType} vec The vector to transform.
    - * @param {goog.vec.Vec3.AnyType} resultVec The vector to
    - *     receive the results (may be vec).
    - * @return {goog.vec.Vec3.AnyType} return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat3.multVec3 = function(mat, vec, resultVec) {
    -  var x = vec[0], y = vec[1], z = vec[2];
    -  resultVec[0] = x * mat[0] + y * mat[3] + z * mat[6];
    -  resultVec[1] = x * mat[1] + y * mat[4] + z * mat[7];
    -  resultVec[2] = x * mat[2] + y * mat[5] + z * mat[8];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Makes the given 3x3 matrix a translation matrix with x and y
    - * translation values.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix.
    - * @param {number} x The translation along the x axis.
    - * @param {number} y The translation along the y axis.
    - * @return {goog.vec.Mat3.AnyType} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.Mat3.makeTranslate = function(mat, x, y) {
    -  goog.vec.Mat3.makeIdentity(mat);
    -  return goog.vec.Mat3.setColumnValues(mat, 2, x, y, 1);
    -};
    -
    -
    -/**
    - * Makes the given 3x3 matrix a scale matrix with x, y, and z scale factors.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The 3x3 (9-element) matrix
    - *     array to receive the new scale matrix.
    - * @param {number} x The scale along the x axis.
    - * @param {number} y The scale along the y axis.
    - * @param {number} z The scale along the z axis.
    - * @return {goog.vec.Mat3.AnyType} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.Mat3.makeScale = function(mat, x, y, z) {
    -  goog.vec.Mat3.makeIdentity(mat);
    -  return goog.vec.Mat3.setDiagonalValues(mat, x, y, z);
    -};
    -
    -
    -/**
    - * Makes the given 3x3 matrix a rotation matrix with the given rotation
    - * angle about the axis defined by the vector (ax, ay, az).
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix.
    - * @param {number} angle The rotation angle in radians.
    - * @param {number} ax The x component of the rotation axis.
    - * @param {number} ay The y component of the rotation axis.
    - * @param {number} az The z component of the rotation axis.
    - * @return {goog.vec.Mat3.AnyType} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.Mat3.makeRotate = function(mat, angle, ax, ay, az) {
    -  var c = Math.cos(angle);
    -  var d = 1 - c;
    -  var s = Math.sin(angle);
    -
    -  return goog.vec.Mat3.setFromValues(mat,
    -      ax * ax * d + c,
    -      ax * ay * d + az * s,
    -      ax * az * d - ay * s,
    -
    -      ax * ay * d - az * s,
    -      ay * ay * d + c,
    -      ay * az * d + ax * s,
    -
    -      ax * az * d + ay * s,
    -      ay * az * d - ax * s,
    -      az * az * d + c);
    -};
    -
    -
    -/**
    - * Makes the given 3x3 matrix a rotation matrix with the given rotation
    - * angle about the X axis.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix.
    - * @param {number} angle The rotation angle in radians.
    - * @return {goog.vec.Mat3.AnyType} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.Mat3.makeRotateX = function(mat, angle) {
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -  return goog.vec.Mat3.setFromValues(mat,
    -                                     1, 0, 0,
    -                                     0, c, s,
    -                                     0, -s, c);
    -};
    -
    -
    -/**
    - * Makes the given 3x3 matrix a rotation matrix with the given rotation
    - * angle about the Y axis.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix.
    - * @param {number} angle The rotation angle in radians.
    - * @return {goog.vec.Mat3.AnyType} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.Mat3.makeRotateY = function(mat, angle) {
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -  return goog.vec.Mat3.setFromValues(mat,
    -                                     c, 0, -s,
    -                                     0, 1, 0,
    -                                     s, 0, c);
    -};
    -
    -
    -/**
    - * Makes the given 3x3 matrix a rotation matrix with the given rotation
    - * angle about the Z axis.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix.
    - * @param {number} angle The rotation angle in radians.
    - * @return {goog.vec.Mat3.AnyType} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.Mat3.makeRotateZ = function(mat, angle) {
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -  return goog.vec.Mat3.setFromValues(mat,
    -                                     c, s, 0,
    -                                     -s, c, 0,
    -                                     0, 0, 1);
    -};
    -
    -
    -/**
    - * Rotate the given matrix by angle about the x,y,z axis.  Equivalent to:
    - * goog.vec.Mat3.multMat(
    - *     mat,
    - *     goog.vec.Mat3.makeRotate(goog.vec.Mat3.create(), angle, x, y, z),
    - *     mat);
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix.
    - * @param {number} angle The angle in radians.
    - * @param {number} x The x component of the rotation axis.
    - * @param {number} y The y component of the rotation axis.
    - * @param {number} z The z component of the rotation axis.
    - * @return {goog.vec.Mat3.AnyType} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.Mat3.rotate = function(mat, angle, x, y, z) {
    -  var m00 = mat[0], m10 = mat[1], m20 = mat[2];
    -  var m01 = mat[3], m11 = mat[4], m21 = mat[5];
    -  var m02 = mat[6], m12 = mat[7], m22 = mat[8];
    -
    -  var cosAngle = Math.cos(angle);
    -  var sinAngle = Math.sin(angle);
    -  var diffCosAngle = 1 - cosAngle;
    -  var r00 = x * x * diffCosAngle + cosAngle;
    -  var r10 = x * y * diffCosAngle + z * sinAngle;
    -  var r20 = x * z * diffCosAngle - y * sinAngle;
    -
    -  var r01 = x * y * diffCosAngle - z * sinAngle;
    -  var r11 = y * y * diffCosAngle + cosAngle;
    -  var r21 = y * z * diffCosAngle + x * sinAngle;
    -
    -  var r02 = x * z * diffCosAngle + y * sinAngle;
    -  var r12 = y * z * diffCosAngle - x * sinAngle;
    -  var r22 = z * z * diffCosAngle + cosAngle;
    -
    -  return goog.vec.Mat3.setFromValues(
    -      mat,
    -      m00 * r00 + m01 * r10 + m02 * r20,
    -      m10 * r00 + m11 * r10 + m12 * r20,
    -      m20 * r00 + m21 * r10 + m22 * r20,
    -
    -      m00 * r01 + m01 * r11 + m02 * r21,
    -      m10 * r01 + m11 * r11 + m12 * r21,
    -      m20 * r01 + m21 * r11 + m22 * r21,
    -
    -      m00 * r02 + m01 * r12 + m02 * r22,
    -      m10 * r02 + m11 * r12 + m12 * r22,
    -      m20 * r02 + m21 * r12 + m22 * r22);
    -};
    -
    -
    -/**
    - * Rotate the given matrix by angle about the x axis.  Equivalent to:
    - * goog.vec.Mat3.multMat(
    - *     mat,
    - *     goog.vec.Mat3.makeRotateX(goog.vec.Mat3.create(), angle),
    - *     mat);
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix.
    - * @param {number} angle The angle in radians.
    - * @return {goog.vec.Mat3.AnyType} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.Mat3.rotateX = function(mat, angle) {
    -  var m01 = mat[3], m11 = mat[4], m21 = mat[5];
    -  var m02 = mat[6], m12 = mat[7], m22 = mat[8];
    -
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[3] = m01 * c + m02 * s;
    -  mat[4] = m11 * c + m12 * s;
    -  mat[5] = m21 * c + m22 * s;
    -  mat[6] = m01 * -s + m02 * c;
    -  mat[7] = m11 * -s + m12 * c;
    -  mat[8] = m21 * -s + m22 * c;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Rotate the given matrix by angle about the y axis.  Equivalent to:
    - * goog.vec.Mat3.multMat(
    - *     mat,
    - *     goog.vec.Mat3.makeRotateY(goog.vec.Mat3.create(), angle),
    - *     mat);
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix.
    - * @param {number} angle The angle in radians.
    - * @return {goog.vec.Mat3.AnyType} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.Mat3.rotateY = function(mat, angle) {
    -  var m00 = mat[0], m10 = mat[1], m20 = mat[2];
    -  var m02 = mat[6], m12 = mat[7], m22 = mat[8];
    -
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[0] = m00 * c + m02 * -s;
    -  mat[1] = m10 * c + m12 * -s;
    -  mat[2] = m20 * c + m22 * -s;
    -  mat[6] = m00 * s + m02 * c;
    -  mat[7] = m10 * s + m12 * c;
    -  mat[8] = m20 * s + m22 * c;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Rotate the given matrix by angle about the z axis.  Equivalent to:
    - * goog.vec.Mat3.multMat(
    - *     mat,
    - *     goog.vec.Mat3.makeRotateZ(goog.vec.Mat3.create(), angle),
    - *     mat);
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix.
    - * @param {number} angle The angle in radians.
    - * @return {goog.vec.Mat3.AnyType} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.Mat3.rotateZ = function(mat, angle) {
    -  var m00 = mat[0], m10 = mat[1], m20 = mat[2];
    -  var m01 = mat[3], m11 = mat[4], m21 = mat[5];
    -
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[0] = m00 * c + m01 * s;
    -  mat[1] = m10 * c + m11 * s;
    -  mat[2] = m20 * c + m21 * s;
    -  mat[3] = m00 * -s + m01 * c;
    -  mat[4] = m10 * -s + m11 * c;
    -  mat[5] = m20 * -s + m21 * c;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 3x3 matrix a rotation matrix given Euler angles using
    - * the ZXZ convention.
    - * Given the euler angles [theta1, theta2, theta3], the rotation is defined as
    - * rotation = rotation_z(theta1) * rotation_x(theta2) * rotation_z(theta3),
    - * with theta1 in [0, 2 * pi], theta2 in [0, pi] and theta3 in [0, 2 * pi].
    - * rotation_x(theta) means rotation around the X axis of theta radians.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix.
    - * @param {number} theta1 The angle of rotation around the Z axis in radians.
    - * @param {number} theta2 The angle of rotation around the X axis in radians.
    - * @param {number} theta3 The angle of rotation around the Z axis in radians.
    - * @return {goog.vec.Mat3.AnyType} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.Mat3.makeEulerZXZ = function(mat, theta1, theta2, theta3) {
    -  var c1 = Math.cos(theta1);
    -  var s1 = Math.sin(theta1);
    -
    -  var c2 = Math.cos(theta2);
    -  var s2 = Math.sin(theta2);
    -
    -  var c3 = Math.cos(theta3);
    -  var s3 = Math.sin(theta3);
    -
    -  mat[0] = c1 * c3 - c2 * s1 * s3;
    -  mat[1] = c2 * c1 * s3 + c3 * s1;
    -  mat[2] = s3 * s2;
    -
    -  mat[3] = -c1 * s3 - c3 * c2 * s1;
    -  mat[4] = c1 * c2 * c3 - s1 * s3;
    -  mat[5] = c3 * s2;
    -
    -  mat[6] = s2 * s1;
    -  mat[7] = -c1 * s2;
    -  mat[8] = c2;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Decomposes a rotation matrix into Euler angles using the ZXZ convention so
    - * that rotation = rotation_z(theta1) * rotation_x(theta2) * rotation_z(theta3),
    - * with theta1 in [0, 2 * pi], theta2 in [0, pi] and theta3 in [0, 2 * pi].
    - * rotation_x(theta) means rotation around the X axis of theta radians.
    - *
    - * @param {goog.vec.Mat3.AnyType} mat The matrix.
    - * @param {goog.vec.Vec3.AnyType} euler The ZXZ Euler angles in
    - *     radians as [theta1, theta2, theta3].
    - * @param {boolean=} opt_theta2IsNegative Whether theta2 is in [-pi, 0] instead
    - *     of the default [0, pi].
    - * @return {goog.vec.Vec3.AnyType} return euler so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat3.toEulerZXZ = function(mat, euler, opt_theta2IsNegative) {
    -  // There is an ambiguity in the sign of sinTheta2 because of the sqrt.
    -  var sinTheta2 = Math.sqrt(mat[2] * mat[2] + mat[5] * mat[5]);
    -
    -  // By default we explicitely constrain theta2 to be in [0, pi],
    -  // so sinTheta2 is always positive. We can change the behavior and specify
    -  // theta2 to be negative in [-pi, 0] with opt_Theta2IsNegative.
    -  var signTheta2 = opt_theta2IsNegative ? -1 : 1;
    -
    -  if (sinTheta2 > goog.vec.EPSILON) {
    -    euler[2] = Math.atan2(mat[2] * signTheta2, mat[5] * signTheta2);
    -    euler[1] = Math.atan2(sinTheta2 * signTheta2, mat[8]);
    -    euler[0] = Math.atan2(mat[6] * signTheta2, -mat[7] * signTheta2);
    -  } else {
    -    // There is also an arbitrary choice for theta1 = 0 or theta2 = 0 here.
    -    // We assume theta1 = 0 as some applications do not allow the camera to roll
    -    // (i.e. have theta1 != 0).
    -    euler[0] = 0;
    -    euler[1] = Math.atan2(sinTheta2 * signTheta2, mat[8]);
    -    euler[2] = Math.atan2(mat[1], mat[0]);
    -  }
    -
    -  // Atan2 outputs angles in [-pi, pi] so we bring them back to [0, 2 * pi].
    -  euler[0] = (euler[0] + Math.PI * 2) % (Math.PI * 2);
    -  euler[2] = (euler[2] + Math.PI * 2) % (Math.PI * 2);
    -  // For theta2 we want the angle to be in [0, pi] or [-pi, 0] depending on
    -  // signTheta2.
    -  euler[1] = ((euler[1] * signTheta2 + Math.PI * 2) % (Math.PI * 2)) *
    -      signTheta2;
    -
    -  return euler;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/mat3_test.html b/src/database/third_party/closure-library/closure/goog/vec/mat3_test.html
    deleted file mode 100644
    index 55dbc86e6fc..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/mat3_test.html
    +++ /dev/null
    @@ -1,465 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.vec.Mat3</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.vec.Mat3');
    -  goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -  var randomMat3 = goog.vec.Mat3.createFloat32FromValues(
    -      0.8025078773498535,
    -      0.7559120655059814,
    -      0.15274643898010254,
    -      0.19196106493473053,
    -      0.0890120416879654,
    -      0.15422114729881287,
    -      0.09754583984613419,
    -      0.44862601161003113,
    -      0.9196512699127197);
    -
    -  function testDeprecatedConstructor() {
    -    var m0 = goog.vec.Mat3.create();
    -    assertElementsEquals([0, 0, 0, 0, 0, 0, 0, 0, 0], m0);
    -
    -    var m1 = goog.vec.Mat3.createFromArray([1, 2, 3, 4, 5, 6, 7, 8, 9]);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m1);
    -
    -    var m2 = goog.vec.Mat3.createFromArray(m1);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m1);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m2);
    -
    -    var m3 = goog.vec.Mat3.createFromValues(1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m3);
    -
    -    var m4 = goog.vec.Mat3.createIdentity();
    -    assertElementsEquals([1, 0, 0, 0, 1, 0, 0, 0, 1], m4);
    -  }
    -
    -  function testConstructor() {
    -    var m0 = goog.vec.Mat3.createFloat32();
    -    assertElementsEquals([0, 0, 0, 0, 0, 0, 0, 0, 0], m0);
    -
    -    var m1 = goog.vec.Mat3.createFloat32FromArray([1, 2, 3, 4, 5, 6, 7, 8, 9]);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m1);
    -
    -    var m2 = goog.vec.Mat3.createFloat32FromArray(m1);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m1);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m2);
    -
    -    var m3 = goog.vec.Mat3.createFloat32FromValues(1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m3);
    -
    -    var m4 = goog.vec.Mat3.createFloat32Identity();
    -    assertElementsEquals([1, 0, 0, 0, 1, 0, 0, 0, 1], m4);
    -
    -    var n0 = goog.vec.Mat3.createFloat64();
    -    assertElementsEquals([0, 0, 0, 0, 0, 0, 0, 0, 0], n0);
    -
    -    var n1 = goog.vec.Mat3.createFloat64FromArray([1, 2, 3, 4, 5, 6, 7, 8, 9]);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], n1);
    -
    -    var n2 = goog.vec.Mat3.createFloat64FromArray(n1);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], n1);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], n2);
    -
    -    var n3 = goog.vec.Mat3.createFloat64FromValues(1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], n3);
    -
    -    var n4 = goog.vec.Mat3.createFloat64Identity();
    -    assertElementsEquals([1, 0, 0, 0, 1, 0, 0, 0, 1], n4);
    -  }
    -
    -  function testSet() {
    -    var m0 = goog.vec.Mat3.createFloat32();
    -    var m1 = goog.vec.Mat3.createFromArray([1, 2, 3, 4, 5, 6, 7, 8, 9]);
    -    goog.vec.Mat3.setFromArray(m0, m1);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -
    -    goog.vec.Mat3.setFromValues(m0, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    -    assertElementsEquals([2, 3, 4, 5, 6, 7, 8, 9, 10], m0);
    -  }
    -
    -  function testSetDiagonal() {
    -    var m0 = goog.vec.Mat3.createFloat32();
    -    goog.vec.Mat3.setDiagonalValues(m0, 1, 2, 3);
    -    assertElementsEquals([1, 0, 0, 0, 2, 0, 0, 0, 3], m0);
    -
    -    goog.vec.Mat3.setDiagonal(m0, [4, 5, 6]);
    -    assertElementsEquals([4, 0, 0, 0, 5, 0, 0, 0, 6], m0);
    -  }
    -
    -  function testSetGetColumn() {
    -    var m0 = goog.vec.Mat3.createFloat32();
    -    goog.vec.Mat3.setColumn(m0, 0, [1, 2, 3]);
    -    goog.vec.Mat3.setColumn(m0, 1, [4, 5, 6]);
    -    goog.vec.Mat3.setColumn(m0, 2, [7, 8, 9]);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -
    -    var v0 = [0, 0, 0];
    -    goog.vec.Mat3.getColumn(m0, 0, v0);
    -    assertElementsEquals([1, 2, 3], v0);
    -    goog.vec.Mat3.getColumn(m0, 1, v0);
    -    assertElementsEquals([4, 5, 6], v0);
    -    goog.vec.Mat3.getColumn(m0, 2, v0);
    -    assertElementsEquals([7, 8, 9], v0);
    -  }
    -
    -  function testSetGetColumns() {
    -    var m0 = goog.vec.Mat3.createFloat32();
    -    goog.vec.Mat3.setColumns(m0, [1, 2, 3], [4, 5, 6], [7, 8, 9]);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -
    -    var v0 = [0, 0, 0], v1 = [0, 0, 0], v2 = [0, 0, 0];
    -    goog.vec.Mat3.getColumns(m0, v0, v1, v2);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals([4, 5, 6], v1);
    -    assertElementsEquals([7, 8, 9], v2);
    -  }
    -
    -  function testSetGetRow() {
    -    var m0 = goog.vec.Mat3.createFloat32();
    -    goog.vec.Mat3.setRow(m0, 0, [1, 2, 3]);
    -    goog.vec.Mat3.setRow(m0, 1, [4, 5, 6]);
    -    goog.vec.Mat3.setRow(m0, 2, [7, 8, 9]);
    -    assertElementsEquals([1, 4, 7, 2, 5, 8, 3, 6, 9], m0);
    -
    -    var v0 = [0, 0, 0];
    -    goog.vec.Mat3.getRow(m0, 0, v0);
    -    assertElementsEquals([1, 2, 3], v0);
    -    goog.vec.Mat3.getRow(m0, 1, v0);
    -    assertElementsEquals([4, 5, 6], v0);
    -    goog.vec.Mat3.getRow(m0, 2, v0);
    -    assertElementsEquals([7, 8, 9], v0);
    -  }
    -
    -  function testSetGetRows() {
    -    var m0 = goog.vec.Mat3.createFloat32();
    -    goog.vec.Mat3.setRows(m0, [1, 2, 3], [4, 5, 6], [7, 8, 9]);
    -    assertElementsEquals([1, 4, 7, 2, 5, 8, 3, 6, 9], m0);
    -
    -    var v0 = [0, 0, 0], v1 = [0, 0, 0], v2 = [0, 0, 0];
    -    goog.vec.Mat3.getRows(m0, v0, v1, v2);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals([4, 5, 6], v1);
    -    assertElementsEquals([7, 8, 9], v2);
    -  }
    -
    -  function testSetRowMajorArray() {
    -    var m0 = goog.vec.Mat3.createFloat32();
    -    goog.vec.Mat3.setFromRowMajorArray(
    -        m0, [1, 2, 3, 4, 5, 6, 7, 8, 9]);
    -    assertElementsEquals([1, 4, 7, 2, 5, 8, 3, 6, 9], m0);
    -  }
    -
    -  function testMakeZero() {
    -    var m0 = goog.vec.Mat3.createFromArray([1, 2, 3, 4, 5, 6, 7, 8, 9]);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -    goog.vec.Mat3.makeZero(m0);
    -    assertElementsEquals([0, 0, 0, 0, 0, 0, 0, 0, 0], m0);
    -  }
    -
    -  function testMakeIdentity() {
    -    var m0 = goog.vec.Mat3.createFloat32();
    -    goog.vec.Mat3.makeIdentity(m0);
    -    assertElementsEquals([1, 0, 0, 0, 1, 0, 0, 0, 1], m0);
    -  }
    -
    -  function testSetGetElement() {
    -    var m0 = goog.vec.Mat3.createFloat32();
    -    for (var r = 0; r < 3; r++) {
    -      for (var c = 0; c < 3; c++) {
    -        var value = c * 3 + r + 1;
    -        goog.vec.Mat3.setElement(m0, r, c, value);
    -        assertEquals(value, goog.vec.Mat3.getElement(m0, r, c));
    -      }
    -    }
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -  }
    -
    -  function testAddMat() {
    -    var m0 = goog.vec.Mat3.createFloat32FromValues(1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var m1 = goog.vec.Mat3.createFloat32FromValues(3, 4, 5, 6, 7, 8, 9, 1, 2);
    -    var m2 = goog.vec.Mat3.create();
    -    goog.vec.Mat3.addMat(m0, m1, m2);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -    assertElementsEquals([3, 4, 5, 6, 7, 8, 9, 1, 2], m1);
    -    assertElementsEquals([4, 6, 8, 10, 12, 14, 16, 9, 11], m2);
    -
    -    goog.vec.Mat3.addMat(m0, m1, m0);
    -    assertElementsEquals([3, 4, 5, 6, 7, 8, 9, 1, 2], m1);
    -    assertElementsEquals([4, 6, 8, 10, 12, 14, 16, 9, 11], m0);
    -  }
    -
    -  function testSubMat() {
    -    var m0 = goog.vec.Mat3.createFloat32FromValues(1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var m1 = goog.vec.Mat3.createFloat32FromValues(3, 4, 5, 6, 7, 8, 9, 1, 2);
    -    var m2 = goog.vec.Mat3.create();
    -
    -    goog.vec.Mat3.subMat(m0, m1, m2);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -    assertElementsEquals([3, 4, 5, 6, 7, 8, 9, 1, 2], m1);
    -    assertElementsEquals([-2, -2, -2, -2, -2, -2, -2, 7, 7], m2);
    -
    -    goog.vec.Mat3.subMat(m1, m0, m1);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -    assertElementsEquals([2, 2, 2, 2, 2, 2, 2, -7, -7], m1);
    -  }
    -
    -  function testMultScalar() {
    -    var m0 = goog.vec.Mat3.createFloat32FromValues(1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var m1 = goog.vec.Mat3.createFloat32();
    -
    -    goog.vec.Mat3.multScalar(m0, 5, m1);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -    assertElementsEquals([5, 10, 15, 20, 25, 30, 35, 40, 45], m1);
    -
    -    goog.vec.Mat3.multScalar(m0, 5, m0);
    -    assertElementsEquals([5, 10, 15, 20, 25, 30, 35, 40, 45], m0);
    -  }
    -
    -  function testMultMat() {
    -    var m0 = goog.vec.Mat3.createFloat32FromValues(1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var m1 = goog.vec.Mat3.createFloat32FromValues(1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var m2 = goog.vec.Mat3.create();
    -
    -    goog.vec.Mat3.multMat(m0, m1, m2);
    -    assertElementsEquals([30, 36, 42, 66, 81, 96, 102, 126, 150], m2);
    -
    -    goog.vec.Mat3.addMat(m0, m1, m1);
    -    goog.vec.Mat3.multMat(m0, m1, m1);
    -    assertElementsEquals([60, 72, 84, 132, 162, 192, 204, 252, 300], m1);
    -  }
    -
    -  function testTranspose() {
    -    var m0 = goog.vec.Mat3.createFloat32FromValues(1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var m1 = goog.vec.Mat3.createFloat32();
    -    goog.vec.Mat3.transpose(m0, m1);
    -    assertElementsEquals([1, 4, 7, 2, 5, 8, 3, 6, 9], m1);
    -    goog.vec.Mat3.transpose(m1, m1);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m1);
    -  }
    -
    -  function testInvert() {
    -    var m0 = goog.vec.Mat3.createFloat32FromValues(1, 1, 1, 1, 1, 1, 1, 1, 1);
    -    assertFalse(goog.vec.Mat3.invert(m0, m0));
    -    assertElementsEquals([1, 1, 1, 1, 1, 1, 1, 1, 1], m0);
    -
    -    goog.vec.Mat3.setFromValues(m0, 1, 2, 3, 1, 3, 4, 3, 4, 5);
    -    assertTrue(goog.vec.Mat3.invert(m0, m0));
    -    assertElementsEquals([0.5, -1.0, 0.5, -3.5, 2.0, 0.5, 2.5, -1.0, -0.5], m0);
    -
    -    goog.vec.Mat3.makeScale(m0, .01, .01, .01);
    -    assertTrue(goog.vec.Mat3.invert(m0, m0));
    -    var m1 = goog.vec.Mat3.create();
    -    goog.vec.Mat3.makeScale(m1, 100, 100, 100);
    -    assertElementsEquals(m1, m0);
    -  }
    -
    -  function testEquals() {
    -    var m0 = goog.vec.Mat3.createFloat32FromValues(1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var m1 = goog.vec.Mat3.createFromArray(m0);
    -    assertTrue(goog.vec.Mat3.equals(m0, m1));
    -    assertTrue(goog.vec.Mat3.equals(m1, m0));
    -    for (var i = 0; i < 9; i++) {
    -      m1[i] = 15;
    -      assertFalse(goog.vec.Mat3.equals(m0, m1));
    -      assertFalse(goog.vec.Mat3.equals(m1, m0));
    -      m1[i] = i + 1;
    -    }
    -  }
    -
    -  function testMultVec3() {
    -    var m0 = goog.vec.Mat3.createFloat32FromValues(1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var v0 = [1, 2, 3];
    -    var v1 = [0, 0, 0];
    -
    -    goog.vec.Mat3.multVec3(m0, v0, v1);
    -    assertElementsEquals([30, 36, 42], v1);
    -    goog.vec.Mat3.multVec3(m0, v0, v0);
    -    assertElementsEquals([30, 36, 42], v0);
    -  }
    -
    -  function testSetValues() {
    -    var a0 = goog.vec.Mat3.createFloat32();
    -    assertElementsEquals([0, 0, 0, 0, 0, 0, 0, 0, 0], a0);
    -    goog.vec.Mat3.setFromValues(a0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], a0);
    -
    -    var a1 = goog.vec.Mat3.createFloat32();
    -    goog.vec.Mat3.setDiagonalValues(a1, 1, 2, 3);
    -    assertElementsEquals([1, 0, 0, 0, 2, 0, 0, 0, 3], a1);
    -
    -    goog.vec.Mat3.setColumnValues(a1, 0, 2, 3, 4);
    -    goog.vec.Mat3.setColumnValues(a1, 1, 5, 6, 7);
    -    goog.vec.Mat3.setColumnValues(a1, 2, 8, 9, 1);
    -    assertElementsEquals([2, 3, 4, 5, 6, 7, 8, 9, 1], a1);
    -
    -    goog.vec.Mat3.setRowValues(a1, 0, 1, 4, 7);
    -    goog.vec.Mat3.setRowValues(a1, 1, 2, 5, 8);
    -    goog.vec.Mat3.setRowValues(a1, 2, 3, 6, 9);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], a1);
    -  }
    -
    -  function testMakeTranslate() {
    -    var m0 = goog.vec.Mat3.createFloat32();
    -    goog.vec.Mat3.makeTranslate(m0, 3, 4);
    -    assertElementsEquals([1, 0, 0, 0, 1, 0, 3, 4, 1], m0);
    -  }
    -
    -  function testMakeScale() {
    -    var m0 = goog.vec.Mat3.createFloat32();
    -    goog.vec.Mat3.makeScale(m0, 3, 4, 5);
    -    assertElementsEquals([3, 0, 0, 0, 4, 0, 0, 0, 5], m0);
    -  }
    -
    -  function testMakeRotate() {
    -    var m0 = goog.vec.Mat3.createFloat32();
    -    goog.vec.Mat3.makeRotate(m0, Math.PI / 2, 0, 0, 1);
    -    var v0 = [0, 1, 0, -1, 0, 0, 0, 0, 1];
    -    assertElementsRoughlyEqual(m0, v0, goog.vec.EPSILON);
    -
    -    var m1 = goog.vec.Mat3.createFloat32();
    -    goog.vec.Mat3.makeRotate(m1, -Math.PI / 4, 0, 0, 1);
    -    goog.vec.Mat3.multMat(m0, m1, m1);
    -    var v1 = [0.7071068, 0.7071068, 0, -0.7071068, 0.7071068, 0, 0, 0, 1];
    -    assertElementsRoughlyEqual(m1, v1, goog.vec.EPSILON);
    -  }
    -
    -  function testMakeRotateX() {
    -    var m0 = goog.vec.Mat3.createFloat32();
    -    var m1 = goog.vec.Mat3.createFloat32()
    -
    -    goog.vec.Mat3.makeRotateX(m0, Math.PI / 7);
    -    goog.vec.Mat3.makeRotate(m1, Math.PI / 7, 1, 0, 0);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testMakeRotateY() {
    -    var m0 = goog.vec.Mat3.createFloat32();
    -    var m1 = goog.vec.Mat3.createFloat32()
    -
    -    goog.vec.Mat3.makeRotateY(m0, Math.PI / 7);
    -    goog.vec.Mat3.makeRotate(m1, Math.PI / 7, 0, 1, 0);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testMakeRotateZ() {
    -    var m0 = goog.vec.Mat3.createFloat32();
    -    var m1 = goog.vec.Mat3.createFloat32()
    -
    -    goog.vec.Mat3.makeRotateZ(m0, Math.PI / 7);
    -    goog.vec.Mat3.makeRotate(m1, Math.PI / 7, 0, 0, 1);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testRotate() {
    -    var m0 = goog.vec.Mat3.createIdentity();
    -    goog.vec.Mat3.rotate(m0, Math.PI / 2, 0, 0, 1);
    -    assertElementsRoughlyEqual(
    -        [0, 1, 0, -1, 0, 0, 0, 0, 1],
    -        m0, goog.vec.EPSILON);
    -
    -    goog.vec.Mat3.rotate(m0, -Math.PI / 4, 0, 0, 1);
    -    assertElementsRoughlyEqual(
    -        [0.7071068, 0.7071068, 0,
    -         -0.7071068, 0.7071068, 0,
    -         0, 0, 1],
    -        m0, goog.vec.EPSILON);
    -  }
    -
    -  function testRotateX() {
    -    var m0 = goog.vec.Mat3.createFloat32();
    -    var m1 = goog.vec.Mat3.createFloat32FromArray(randomMat3)
    -
    -    goog.vec.Mat3.makeRotateX(m0, Math.PI / 7);
    -    goog.vec.Mat3.multMat(m1, m0, m0);
    -    goog.vec.Mat3.rotateX(m1, Math.PI / 7);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testRotateY() {
    -    var m0 = goog.vec.Mat3.createFloat32();
    -    var m1 = goog.vec.Mat3.createFloat32FromArray(randomMat3)
    -
    -    goog.vec.Mat3.makeRotateY(m0, Math.PI / 7);
    -    goog.vec.Mat3.multMat(m1, m0, m0);
    -    goog.vec.Mat3.rotateY(m1, Math.PI / 7);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testRotateZ() {
    -    var m0 = goog.vec.Mat3.createFloat32();
    -    var m1 = goog.vec.Mat3.createFloat32FromArray(randomMat3)
    -
    -    goog.vec.Mat3.makeRotateZ(m0, Math.PI / 7);
    -    goog.vec.Mat3.multMat(m1, m0, m0);
    -    goog.vec.Mat3.rotateZ(m1, Math.PI / 7);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testMakeEulerZXZ() {
    -    var m0 = goog.vec.Mat3.createFloat32();
    -    var roll = 0.200982 * 2 * Math.PI;
    -    var tilt = 0.915833 * Math.PI;
    -    var yaw = 0.839392 * 2 * Math.PI;
    -
    -    goog.vec.Mat3.makeRotate(m0, roll, 0, 0, 1);
    -    goog.vec.Mat3.rotate(m0, tilt, 1, 0, 0);
    -    goog.vec.Mat3.rotate(m0, yaw, 0, 0, 1);
    -
    -    var m1 = goog.vec.Mat3.createFloat32();
    -    goog.vec.Mat3.makeEulerZXZ(m1, roll, tilt, yaw);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -
    -
    -    var euler = [0, 0, 0];
    -    goog.vec.Mat3.toEulerZXZ(m0, euler);
    -
    -    assertRoughlyEquals(roll, euler[0], goog.vec.EPSILON);
    -    assertRoughlyEquals(tilt, euler[1], goog.vec.EPSILON);
    -    assertRoughlyEquals(yaw, euler[2], goog.vec.EPSILON);
    -
    -    // Test negative tilt now.
    -    goog.vec.Mat3.makeRotate(m0, roll, 0, 0, 1);
    -    goog.vec.Mat3.rotate(m0, -tilt, 1, 0, 0);
    -    goog.vec.Mat3.rotate(m0, yaw, 0, 0, 1);
    -
    -    goog.vec.Mat3.makeEulerZXZ(m1, roll, -tilt, yaw);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -
    -    var euler = [0, 0, 0];
    -    goog.vec.Mat3.toEulerZXZ(m0, euler, true);
    -
    -    assertRoughlyEquals(roll, euler[0], goog.vec.EPSILON);
    -    assertRoughlyEquals(-tilt, euler[1], goog.vec.EPSILON);
    -    assertRoughlyEquals(yaw, euler[2], goog.vec.EPSILON);
    -  }
    -
    -  function testEulerZXZExtrema() {
    -    var m0 = goog.vec.Mat3.createFloat32FromArray(
    -        [1, 0, 0, 0, 0, -1, 0, 1, 0]);
    -    var m1 = goog.vec.Mat3.createFloat32FromArray(
    -        [0, 0, 0, 0, 0, 0, 0, 0, 0]);
    -
    -    var euler = [0, 0, 0];
    -    goog.vec.Mat3.toEulerZXZ(m0, euler);
    -    assertElementsRoughlyEqual(
    -        [Math.PI, Math.PI / 2, Math.PI], euler, goog.vec.EPSILON);
    -    goog.vec.Mat3.makeEulerZXZ(m1, euler[0], euler[1], euler[2]);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -</script>
    -</body>
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/mat3d.js b/src/database/third_party/closure-library/closure/goog/vec/mat3d.js
    deleted file mode 100644
    index 1ebddc65f69..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/mat3d.js
    +++ /dev/null
    @@ -1,1039 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -//                                                                           //
    -// Any edits to this file must be applied to mat3f.js by running:            //
    -//   swap_type.sh mat3d.js > mat3f.js                                        //
    -//                                                                           //
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -
    -
    -/**
    - * @fileoverview Provides functions for operating on 3x3 double (64bit)
    - * matrices.  The matrices are stored in column-major order.
    - *
    - * The last parameter will typically be the output object and an object
    - * can be both an input and output parameter to all methods except where
    - * noted.
    - *
    - * See the README for notes about the design and structure of the API
    - * (especially related to performance).
    - *
    - */
    -goog.provide('goog.vec.mat3d');
    -goog.provide('goog.vec.mat3d.Type');
    -
    -goog.require('goog.vec');
    -
    -
    -/** @typedef {goog.vec.Float64} */ goog.vec.mat3d.Type;
    -
    -
    -/**
    - * Creates a mat3d with all elements initialized to zero.
    - *
    - * @return {!goog.vec.mat3d.Type} The new mat3d.
    - */
    -goog.vec.mat3d.create = function() {
    -  return new Float64Array(9);
    -};
    -
    -
    -/**
    - * Initializes the matrix from the set of values. Note the values supplied are
    - * in column major order.
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix to receive the
    - *     values.
    - * @param {number} v00 The values at (0, 0).
    - * @param {number} v10 The values at (1, 0).
    - * @param {number} v20 The values at (2, 0).
    - * @param {number} v01 The values at (0, 1).
    - * @param {number} v11 The values at (1, 1).
    - * @param {number} v21 The values at (2, 1).
    - * @param {number} v02 The values at (0, 2).
    - * @param {number} v12 The values at (1, 2).
    - * @param {number} v22 The values at (2, 2).
    - * @return {!goog.vec.mat3d.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3d.setFromValues = function(
    -    mat, v00, v10, v20, v01, v11, v21, v02, v12, v22) {
    -  mat[0] = v00;
    -  mat[1] = v10;
    -  mat[2] = v20;
    -  mat[3] = v01;
    -  mat[4] = v11;
    -  mat[5] = v21;
    -  mat[6] = v02;
    -  mat[7] = v12;
    -  mat[8] = v22;
    -  return mat;
    -};
    -
    -
    -/**
    - * Initializes mat3d mat from mat3d src.
    - *
    - * @param {goog.vec.mat3d.Type} mat The destination matrix.
    - * @param {goog.vec.mat3d.Type} src The source matrix.
    - * @return {!goog.vec.mat3d.Type} Return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3d.setFromMat3d = function(mat, src) {
    -  mat[0] = src[0];
    -  mat[1] = src[1];
    -  mat[2] = src[2];
    -  mat[3] = src[3];
    -  mat[4] = src[4];
    -  mat[5] = src[5];
    -  mat[6] = src[6];
    -  mat[7] = src[7];
    -  mat[8] = src[8];
    -  return mat;
    -};
    -
    -
    -/**
    - * Initializes mat3d mat from mat3f src (typed as a Float32Array to
    - * avoid circular goog.requires).
    - *
    - * @param {goog.vec.mat3d.Type} mat The destination matrix.
    - * @param {Float32Array} src The source matrix.
    - * @return {!goog.vec.mat3d.Type} Return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3d.setFromMat3f = function(mat, src) {
    -  mat[0] = src[0];
    -  mat[1] = src[1];
    -  mat[2] = src[2];
    -  mat[3] = src[3];
    -  mat[4] = src[4];
    -  mat[5] = src[5];
    -  mat[6] = src[6];
    -  mat[7] = src[7];
    -  mat[8] = src[8];
    -  return mat;
    -};
    -
    -
    -/**
    - * Initializes mat3d mat from Array src.
    - *
    - * @param {goog.vec.mat3d.Type} mat The destination matrix.
    - * @param {Array<number>} src The source matrix.
    - * @return {!goog.vec.mat3d.Type} Return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3d.setFromArray = function(mat, src) {
    -  mat[0] = src[0];
    -  mat[1] = src[1];
    -  mat[2] = src[2];
    -  mat[3] = src[3];
    -  mat[4] = src[4];
    -  mat[5] = src[5];
    -  mat[6] = src[6];
    -  mat[7] = src[7];
    -  mat[8] = src[8];
    -  return mat;
    -};
    -
    -
    -/**
    - * Retrieves the element at the requested row and column.
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix containing the value to
    - *     retrieve.
    - * @param {number} row The row index.
    - * @param {number} column The column index.
    - * @return {number} The element value at the requested row, column indices.
    - */
    -goog.vec.mat3d.getElement = function(mat, row, column) {
    -  return mat[row + column * 3];
    -};
    -
    -
    -/**
    - * Sets the element at the requested row and column.
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix containing the value to
    - *     retrieve.
    - * @param {number} row The row index.
    - * @param {number} column The column index.
    - * @param {number} value The value to set at the requested row, column.
    - * @return {!goog.vec.mat3d.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3d.setElement = function(mat, row, column, value) {
    -  mat[row + column * 3] = value;
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the diagonal values of the matrix from the given values.
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix to receive the values.
    - * @param {number} v00 The values for (0, 0).
    - * @param {number} v11 The values for (1, 1).
    - * @param {number} v22 The values for (2, 2).
    - * @return {!goog.vec.mat3d.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3d.setDiagonalValues = function(mat, v00, v11, v22) {
    -  mat[0] = v00;
    -  mat[4] = v11;
    -  mat[8] = v22;
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the diagonal values of the matrix from the given vector.
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix to receive the values.
    - * @param {goog.vec.vec3d.Type} vec The vector containing the values.
    - * @return {!goog.vec.mat3d.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3d.setDiagonal = function(mat, vec) {
    -  mat[0] = vec[0];
    -  mat[4] = vec[1];
    -  mat[8] = vec[2];
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the specified column with the supplied values.
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix to recieve the values.
    - * @param {number} column The column index to set the values on.
    - * @param {number} v0 The value for row 0.
    - * @param {number} v1 The value for row 1.
    - * @param {number} v2 The value for row 2.
    - * @return {!goog.vec.mat3d.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3d.setColumnValues = function(mat, column, v0, v1, v2) {
    -  var i = column * 3;
    -  mat[i] = v0;
    -  mat[i + 1] = v1;
    -  mat[i + 2] = v2;
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the specified column with the value from the supplied array.
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix to receive the values.
    - * @param {number} column The column index to set the values on.
    - * @param {goog.vec.vec3d.Type} vec The vector elements for the column.
    - * @return {!goog.vec.mat3d.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3d.setColumn = function(mat, column, vec) {
    -  var i = column * 3;
    -  mat[i] = vec[0];
    -  mat[i + 1] = vec[1];
    -  mat[i + 2] = vec[2];
    -  return mat;
    -};
    -
    -
    -/**
    - * Retrieves the specified column from the matrix into the given vector
    - * array.
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix supplying the values.
    - * @param {number} column The column to get the values from.
    - * @param {goog.vec.vec3d.Type} vec The vector elements to receive the
    - *     column.
    - * @return {!goog.vec.vec3d.Type} return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3d.getColumn = function(mat, column, vec) {
    -  var i = column * 3;
    -  vec[0] = mat[i];
    -  vec[1] = mat[i + 1];
    -  vec[2] = mat[i + 2];
    -  return vec;
    -};
    -
    -
    -/**
    - * Sets the columns of the matrix from the set of vector elements.
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix to receive the values.
    - * @param {goog.vec.vec3d.Type} vec0 The values for column 0.
    - * @param {goog.vec.vec3d.Type} vec1 The values for column 1.
    - * @param {goog.vec.vec3d.Type} vec2 The values for column 2.
    - * @return {!goog.vec.mat3d.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3d.setColumns = function(mat, vec0, vec1, vec2) {
    -  goog.vec.mat3d.setColumn(mat, 0, vec0);
    -  goog.vec.mat3d.setColumn(mat, 1, vec1);
    -  goog.vec.mat3d.setColumn(mat, 2, vec2);
    -  return /** @type {!goog.vec.mat3d.Type} */(mat);
    -};
    -
    -
    -/**
    - * Retrieves the column values from the given matrix into the given vector
    - * elements.
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix supplying the columns.
    - * @param {goog.vec.vec3d.Type} vec0 The vector to receive column 0.
    - * @param {goog.vec.vec3d.Type} vec1 The vector to receive column 1.
    - * @param {goog.vec.vec3d.Type} vec2 The vector to receive column 2.
    - */
    -goog.vec.mat3d.getColumns = function(mat, vec0, vec1, vec2) {
    -  goog.vec.mat3d.getColumn(mat, 0, vec0);
    -  goog.vec.mat3d.getColumn(mat, 1, vec1);
    -  goog.vec.mat3d.getColumn(mat, 2, vec2);
    -};
    -
    -
    -/**
    - * Sets the row values from the supplied values.
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix to receive the values.
    - * @param {number} row The index of the row to receive the values.
    - * @param {number} v0 The value for column 0.
    - * @param {number} v1 The value for column 1.
    - * @param {number} v2 The value for column 2.
    - * @return {!goog.vec.mat3d.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3d.setRowValues = function(mat, row, v0, v1, v2) {
    -  mat[row] = v0;
    -  mat[row + 3] = v1;
    -  mat[row + 6] = v2;
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the row values from the supplied vector.
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix to receive the row values.
    - * @param {number} row The index of the row.
    - * @param {goog.vec.vec3d.Type} vec The vector containing the values.
    - * @return {!goog.vec.mat3d.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3d.setRow = function(mat, row, vec) {
    -  mat[row] = vec[0];
    -  mat[row + 3] = vec[1];
    -  mat[row + 6] = vec[2];
    -  return mat;
    -};
    -
    -
    -/**
    - * Retrieves the row values into the given vector.
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix supplying the values.
    - * @param {number} row The index of the row supplying the values.
    - * @param {goog.vec.vec3d.Type} vec The vector to receive the row.
    - * @return {!goog.vec.vec3d.Type} return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3d.getRow = function(mat, row, vec) {
    -  vec[0] = mat[row];
    -  vec[1] = mat[row + 3];
    -  vec[2] = mat[row + 6];
    -  return vec;
    -};
    -
    -
    -/**
    - * Sets the rows of the matrix from the supplied vectors.
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix to receive the values.
    - * @param {goog.vec.vec3d.Type} vec0 The values for row 0.
    - * @param {goog.vec.vec3d.Type} vec1 The values for row 1.
    - * @param {goog.vec.vec3d.Type} vec2 The values for row 2.
    - * @return {!goog.vec.mat3d.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3d.setRows = function(mat, vec0, vec1, vec2) {
    -  goog.vec.mat3d.setRow(mat, 0, vec0);
    -  goog.vec.mat3d.setRow(mat, 1, vec1);
    -  goog.vec.mat3d.setRow(mat, 2, vec2);
    -  return /** @type {!goog.vec.mat3d.Type} */(mat);
    -};
    -
    -
    -/**
    - * Retrieves the rows of the matrix into the supplied vectors.
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix to supplying the values.
    - * @param {goog.vec.vec3d.Type} vec0 The vector to receive row 0.
    - * @param {goog.vec.vec3d.Type} vec1 The vector to receive row 1.
    - * @param {goog.vec.vec3d.Type} vec2 The vector to receive row 2.
    - */
    -goog.vec.mat3d.getRows = function(mat, vec0, vec1, vec2) {
    -  goog.vec.mat3d.getRow(mat, 0, vec0);
    -  goog.vec.mat3d.getRow(mat, 1, vec1);
    -  goog.vec.mat3d.getRow(mat, 2, vec2);
    -};
    -
    -
    -/**
    - * Makes the given 3x3 matrix the zero matrix.
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix.
    - * @return {!goog.vec.mat3d.Type} return mat so operations can be chained.
    - */
    -goog.vec.mat3d.makeZero = function(mat) {
    -  mat[0] = 0;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 0;
    -  mat[5] = 0;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = 0;
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 3x3 matrix the identity matrix.
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix.
    - * @return {!goog.vec.mat3d.Type} return mat so operations can be chained.
    - */
    -goog.vec.mat3d.makeIdentity = function(mat) {
    -  mat[0] = 1;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 1;
    -  mat[5] = 0;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = 1;
    -  return mat;
    -};
    -
    -
    -/**
    - * Performs a per-component addition of the matrices mat0 and mat1, storing
    - * the result into resultMat.
    - *
    - * @param {goog.vec.mat3d.Type} mat0 The first addend.
    - * @param {goog.vec.mat3d.Type} mat1 The second addend.
    - * @param {goog.vec.mat3d.Type} resultMat The matrix to
    - *     receive the results (may be either mat0 or mat1).
    - * @return {!goog.vec.mat3d.Type} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3d.addMat = function(mat0, mat1, resultMat) {
    -  resultMat[0] = mat0[0] + mat1[0];
    -  resultMat[1] = mat0[1] + mat1[1];
    -  resultMat[2] = mat0[2] + mat1[2];
    -  resultMat[3] = mat0[3] + mat1[3];
    -  resultMat[4] = mat0[4] + mat1[4];
    -  resultMat[5] = mat0[5] + mat1[5];
    -  resultMat[6] = mat0[6] + mat1[6];
    -  resultMat[7] = mat0[7] + mat1[7];
    -  resultMat[8] = mat0[8] + mat1[8];
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Performs a per-component subtraction of the matrices mat0 and mat1,
    - * storing the result into resultMat.
    - *
    - * @param {goog.vec.mat3d.Type} mat0 The minuend.
    - * @param {goog.vec.mat3d.Type} mat1 The subtrahend.
    - * @param {goog.vec.mat3d.Type} resultMat The matrix to receive
    - *     the results (may be either mat0 or mat1).
    - * @return {!goog.vec.mat3d.Type} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3d.subMat = function(mat0, mat1, resultMat) {
    -  resultMat[0] = mat0[0] - mat1[0];
    -  resultMat[1] = mat0[1] - mat1[1];
    -  resultMat[2] = mat0[2] - mat1[2];
    -  resultMat[3] = mat0[3] - mat1[3];
    -  resultMat[4] = mat0[4] - mat1[4];
    -  resultMat[5] = mat0[5] - mat1[5];
    -  resultMat[6] = mat0[6] - mat1[6];
    -  resultMat[7] = mat0[7] - mat1[7];
    -  resultMat[8] = mat0[8] - mat1[8];
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Multiplies matrix mat0 with the given scalar, storing the result
    - * into resultMat.
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix.
    - * @param {number} scalar The scalar value to multiple to each element of mat.
    - * @param {goog.vec.mat3d.Type} resultMat The matrix to receive
    - *     the results (may be mat).
    - * @return {!goog.vec.mat3d.Type} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3d.multScalar = function(mat, scalar, resultMat) {
    -  resultMat[0] = mat[0] * scalar;
    -  resultMat[1] = mat[1] * scalar;
    -  resultMat[2] = mat[2] * scalar;
    -  resultMat[3] = mat[3] * scalar;
    -  resultMat[4] = mat[4] * scalar;
    -  resultMat[5] = mat[5] * scalar;
    -  resultMat[6] = mat[6] * scalar;
    -  resultMat[7] = mat[7] * scalar;
    -  resultMat[8] = mat[8] * scalar;
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Multiplies the two matrices mat0 and mat1 using matrix multiplication,
    - * storing the result into resultMat.
    - *
    - * @param {goog.vec.mat3d.Type} mat0 The first (left hand) matrix.
    - * @param {goog.vec.mat3d.Type} mat1 The second (right hand) matrix.
    - * @param {goog.vec.mat3d.Type} resultMat The matrix to receive
    - *     the results (may be either mat0 or mat1).
    - * @return {!goog.vec.mat3d.Type} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3d.multMat = function(mat0, mat1, resultMat) {
    -  var a00 = mat0[0], a10 = mat0[1], a20 = mat0[2];
    -  var a01 = mat0[3], a11 = mat0[4], a21 = mat0[5];
    -  var a02 = mat0[6], a12 = mat0[7], a22 = mat0[8];
    -
    -  var b00 = mat1[0], b10 = mat1[1], b20 = mat1[2];
    -  var b01 = mat1[3], b11 = mat1[4], b21 = mat1[5];
    -  var b02 = mat1[6], b12 = mat1[7], b22 = mat1[8];
    -
    -  resultMat[0] = a00 * b00 + a01 * b10 + a02 * b20;
    -  resultMat[1] = a10 * b00 + a11 * b10 + a12 * b20;
    -  resultMat[2] = a20 * b00 + a21 * b10 + a22 * b20;
    -  resultMat[3] = a00 * b01 + a01 * b11 + a02 * b21;
    -  resultMat[4] = a10 * b01 + a11 * b11 + a12 * b21;
    -  resultMat[5] = a20 * b01 + a21 * b11 + a22 * b21;
    -  resultMat[6] = a00 * b02 + a01 * b12 + a02 * b22;
    -  resultMat[7] = a10 * b02 + a11 * b12 + a12 * b22;
    -  resultMat[8] = a20 * b02 + a21 * b12 + a22 * b22;
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Transposes the given matrix mat storing the result into resultMat.
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix to transpose.
    - * @param {goog.vec.mat3d.Type} resultMat The matrix to receive
    - *     the results (may be mat).
    - * @return {!goog.vec.mat3d.Type} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3d.transpose = function(mat, resultMat) {
    -  if (resultMat == mat) {
    -    var a10 = mat[1], a20 = mat[2], a21 = mat[5];
    -    resultMat[1] = mat[3];
    -    resultMat[2] = mat[6];
    -    resultMat[3] = a10;
    -    resultMat[5] = mat[7];
    -    resultMat[6] = a20;
    -    resultMat[7] = a21;
    -  } else {
    -    resultMat[0] = mat[0];
    -    resultMat[1] = mat[3];
    -    resultMat[2] = mat[6];
    -    resultMat[3] = mat[1];
    -    resultMat[4] = mat[4];
    -    resultMat[5] = mat[7];
    -    resultMat[6] = mat[2];
    -    resultMat[7] = mat[5];
    -    resultMat[8] = mat[8];
    -  }
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Computes the inverse of mat0 storing the result into resultMat. If the
    - * inverse is defined, this function returns true, false otherwise.
    - *
    - * @param {goog.vec.mat3d.Type} mat0 The matrix to invert.
    - * @param {goog.vec.mat3d.Type} resultMat The matrix to receive
    - *     the result (may be mat0).
    - * @return {boolean} True if the inverse is defined. If false is returned,
    - *     resultMat is not modified.
    - */
    -goog.vec.mat3d.invert = function(mat0, resultMat) {
    -  var a00 = mat0[0], a10 = mat0[1], a20 = mat0[2];
    -  var a01 = mat0[3], a11 = mat0[4], a21 = mat0[5];
    -  var a02 = mat0[6], a12 = mat0[7], a22 = mat0[8];
    -
    -  var t00 = a11 * a22 - a12 * a21;
    -  var t10 = a12 * a20 - a10 * a22;
    -  var t20 = a10 * a21 - a11 * a20;
    -  var det = a00 * t00 + a01 * t10 + a02 * t20;
    -  if (det == 0) {
    -    return false;
    -  }
    -
    -  var idet = 1 / det;
    -  resultMat[0] = t00 * idet;
    -  resultMat[3] = (a02 * a21 - a01 * a22) * idet;
    -  resultMat[6] = (a01 * a12 - a02 * a11) * idet;
    -
    -  resultMat[1] = t10 * idet;
    -  resultMat[4] = (a00 * a22 - a02 * a20) * idet;
    -  resultMat[7] = (a02 * a10 - a00 * a12) * idet;
    -
    -  resultMat[2] = t20 * idet;
    -  resultMat[5] = (a01 * a20 - a00 * a21) * idet;
    -  resultMat[8] = (a00 * a11 - a01 * a10) * idet;
    -  return true;
    -};
    -
    -
    -/**
    - * Returns true if the components of mat0 are equal to the components of mat1.
    - *
    - * @param {goog.vec.mat3d.Type} mat0 The first matrix.
    - * @param {goog.vec.mat3d.Type} mat1 The second matrix.
    - * @return {boolean} True if the the two matrices are equivalent.
    - */
    -goog.vec.mat3d.equals = function(mat0, mat1) {
    -  return mat0.length == mat1.length &&
    -      mat0[0] == mat1[0] && mat0[1] == mat1[1] && mat0[2] == mat1[2] &&
    -      mat0[3] == mat1[3] && mat0[4] == mat1[4] && mat0[5] == mat1[5] &&
    -      mat0[6] == mat1[6] && mat0[7] == mat1[7] && mat0[8] == mat1[8];
    -};
    -
    -
    -/**
    - * Transforms the given vector with the given matrix storing the resulting,
    - * transformed matrix into resultVec.
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix supplying the transformation.
    - * @param {goog.vec.vec3d.Type} vec The vector to transform.
    - * @param {goog.vec.vec3d.Type} resultVec The vector to
    - *     receive the results (may be vec).
    - * @return {!goog.vec.vec3d.Type} return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3d.multVec3 = function(mat, vec, resultVec) {
    -  var x = vec[0], y = vec[1], z = vec[2];
    -  resultVec[0] = x * mat[0] + y * mat[3] + z * mat[6];
    -  resultVec[1] = x * mat[1] + y * mat[4] + z * mat[7];
    -  resultVec[2] = x * mat[2] + y * mat[5] + z * mat[8];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Makes the given 3x3 matrix a translation matrix with x and y
    - * translation values.
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix.
    - * @param {number} x The translation along the x axis.
    - * @param {number} y The translation along the y axis.
    - * @return {!goog.vec.mat3d.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat3d.makeTranslate = function(mat, x, y) {
    -  mat[0] = 1;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 1;
    -  mat[5] = 0;
    -  mat[6] = x;
    -  mat[7] = y;
    -  mat[8] = 1;
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 3x3 matrix a scale matrix with x, y, and z scale factors.
    - *
    - * @param {goog.vec.mat3d.Type} mat The 3x3 (9-element) matrix
    - *     array to receive the new scale matrix.
    - * @param {number} x The scale along the x axis.
    - * @param {number} y The scale along the y axis.
    - * @param {number} z The scale along the z axis.
    - * @return {!goog.vec.mat3d.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat3d.makeScale = function(mat, x, y, z) {
    -  mat[0] = x;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = y;
    -  mat[5] = 0;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = z;
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 3x3 matrix a rotation matrix with the given rotation
    - * angle about the axis defined by the vector (ax, ay, az).
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix.
    - * @param {number} angle The rotation angle in radians.
    - * @param {number} ax The x component of the rotation axis.
    - * @param {number} ay The y component of the rotation axis.
    - * @param {number} az The z component of the rotation axis.
    - * @return {!goog.vec.mat3d.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat3d.makeRotate = function(mat, angle, ax, ay, az) {
    -  var c = Math.cos(angle);
    -  var d = 1 - c;
    -  var s = Math.sin(angle);
    -
    -  mat[0] = ax * ax * d + c;
    -  mat[1] = ax * ay * d + az * s;
    -  mat[2] = ax * az * d - ay * s;
    -  mat[3] = ax * ay * d - az * s;
    -  mat[4] = ay * ay * d + c;
    -  mat[5] = ay * az * d + ax * s;
    -  mat[6] = ax * az * d + ay * s;
    -  mat[7] = ay * az * d - ax * s;
    -  mat[8] = az * az * d + c;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 3x3 matrix a rotation matrix with the given rotation
    - * angle about the X axis.
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix.
    - * @param {number} angle The rotation angle in radians.
    - * @return {!goog.vec.mat3d.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat3d.makeRotateX = function(mat, angle) {
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[0] = 1;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = c;
    -  mat[5] = s;
    -  mat[6] = 0;
    -  mat[7] = -s;
    -  mat[8] = c;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 3x3 matrix a rotation matrix with the given rotation
    - * angle about the Y axis.
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix.
    - * @param {number} angle The rotation angle in radians.
    - * @return {!goog.vec.mat3d.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat3d.makeRotateY = function(mat, angle) {
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[0] = c;
    -  mat[1] = 0;
    -  mat[2] = -s;
    -  mat[3] = 0;
    -  mat[4] = 1;
    -  mat[5] = 0;
    -  mat[6] = s;
    -  mat[7] = 0;
    -  mat[8] = c;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 3x3 matrix a rotation matrix with the given rotation
    - * angle about the Z axis.
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix.
    - * @param {number} angle The rotation angle in radians.
    - * @return {!goog.vec.mat3d.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat3d.makeRotateZ = function(mat, angle) {
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[0] = c;
    -  mat[1] = s;
    -  mat[2] = 0;
    -  mat[3] = -s;
    -  mat[4] = c;
    -  mat[5] = 0;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = 1;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Rotate the given matrix by angle about the x,y,z axis.  Equivalent to:
    - * goog.vec.mat3d.multMat(
    - *     mat,
    - *     goog.vec.mat3d.makeRotate(goog.vec.mat3d.create(), angle, x, y, z),
    - *     mat);
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix.
    - * @param {number} angle The angle in radians.
    - * @param {number} x The x component of the rotation axis.
    - * @param {number} y The y component of the rotation axis.
    - * @param {number} z The z component of the rotation axis.
    - * @return {!goog.vec.mat3d.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat3d.rotate = function(mat, angle, x, y, z) {
    -  var m00 = mat[0], m10 = mat[1], m20 = mat[2];
    -  var m01 = mat[3], m11 = mat[4], m21 = mat[5];
    -  var m02 = mat[6], m12 = mat[7], m22 = mat[8];
    -
    -  var cosAngle = Math.cos(angle);
    -  var sinAngle = Math.sin(angle);
    -  var diffCosAngle = 1 - cosAngle;
    -  var r00 = x * x * diffCosAngle + cosAngle;
    -  var r10 = x * y * diffCosAngle + z * sinAngle;
    -  var r20 = x * z * diffCosAngle - y * sinAngle;
    -
    -  var r01 = x * y * diffCosAngle - z * sinAngle;
    -  var r11 = y * y * diffCosAngle + cosAngle;
    -  var r21 = y * z * diffCosAngle + x * sinAngle;
    -
    -  var r02 = x * z * diffCosAngle + y * sinAngle;
    -  var r12 = y * z * diffCosAngle - x * sinAngle;
    -  var r22 = z * z * diffCosAngle + cosAngle;
    -
    -  mat[0] = m00 * r00 + m01 * r10 + m02 * r20;
    -  mat[1] = m10 * r00 + m11 * r10 + m12 * r20;
    -  mat[2] = m20 * r00 + m21 * r10 + m22 * r20;
    -  mat[3] = m00 * r01 + m01 * r11 + m02 * r21;
    -  mat[4] = m10 * r01 + m11 * r11 + m12 * r21;
    -  mat[5] = m20 * r01 + m21 * r11 + m22 * r21;
    -  mat[6] = m00 * r02 + m01 * r12 + m02 * r22;
    -  mat[7] = m10 * r02 + m11 * r12 + m12 * r22;
    -  mat[8] = m20 * r02 + m21 * r12 + m22 * r22;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Rotate the given matrix by angle about the x axis.  Equivalent to:
    - * goog.vec.mat3d.multMat(
    - *     mat,
    - *     goog.vec.mat3d.makeRotateX(goog.vec.mat3d.create(), angle),
    - *     mat);
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix.
    - * @param {number} angle The angle in radians.
    - * @return {!goog.vec.mat3d.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat3d.rotateX = function(mat, angle) {
    -  var m01 = mat[3], m11 = mat[4], m21 = mat[5];
    -  var m02 = mat[6], m12 = mat[7], m22 = mat[8];
    -
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[3] = m01 * c + m02 * s;
    -  mat[4] = m11 * c + m12 * s;
    -  mat[5] = m21 * c + m22 * s;
    -  mat[6] = m01 * -s + m02 * c;
    -  mat[7] = m11 * -s + m12 * c;
    -  mat[8] = m21 * -s + m22 * c;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Rotate the given matrix by angle about the y axis.  Equivalent to:
    - * goog.vec.mat3d.multMat(
    - *     mat,
    - *     goog.vec.mat3d.makeRotateY(goog.vec.mat3d.create(), angle),
    - *     mat);
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix.
    - * @param {number} angle The angle in radians.
    - * @return {!goog.vec.mat3d.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat3d.rotateY = function(mat, angle) {
    -  var m00 = mat[0], m10 = mat[1], m20 = mat[2];
    -  var m02 = mat[6], m12 = mat[7], m22 = mat[8];
    -
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[0] = m00 * c + m02 * -s;
    -  mat[1] = m10 * c + m12 * -s;
    -  mat[2] = m20 * c + m22 * -s;
    -  mat[6] = m00 * s + m02 * c;
    -  mat[7] = m10 * s + m12 * c;
    -  mat[8] = m20 * s + m22 * c;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Rotate the given matrix by angle about the z axis.  Equivalent to:
    - * goog.vec.mat3d.multMat(
    - *     mat,
    - *     goog.vec.mat3d.makeRotateZ(goog.vec.mat3d.create(), angle),
    - *     mat);
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix.
    - * @param {number} angle The angle in radians.
    - * @return {!goog.vec.mat3d.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat3d.rotateZ = function(mat, angle) {
    -  var m00 = mat[0], m10 = mat[1], m20 = mat[2];
    -  var m01 = mat[3], m11 = mat[4], m21 = mat[5];
    -
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[0] = m00 * c + m01 * s;
    -  mat[1] = m10 * c + m11 * s;
    -  mat[2] = m20 * c + m21 * s;
    -  mat[3] = m00 * -s + m01 * c;
    -  mat[4] = m10 * -s + m11 * c;
    -  mat[5] = m20 * -s + m21 * c;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 3x3 matrix a rotation matrix given Euler angles using
    - * the ZXZ convention.
    - * Given the euler angles [theta1, theta2, theta3], the rotation is defined as
    - * rotation = rotation_z(theta1) * rotation_x(theta2) * rotation_z(theta3),
    - * with theta1 in [0, 2 * pi], theta2 in [0, pi] and theta3 in [0, 2 * pi].
    - * rotation_x(theta) means rotation around the X axis of theta radians.
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix.
    - * @param {number} theta1 The angle of rotation around the Z axis in radians.
    - * @param {number} theta2 The angle of rotation around the X axis in radians.
    - * @param {number} theta3 The angle of rotation around the Z axis in radians.
    - * @return {!goog.vec.mat3d.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat3d.makeEulerZXZ = function(mat, theta1, theta2, theta3) {
    -  var c1 = Math.cos(theta1);
    -  var s1 = Math.sin(theta1);
    -
    -  var c2 = Math.cos(theta2);
    -  var s2 = Math.sin(theta2);
    -
    -  var c3 = Math.cos(theta3);
    -  var s3 = Math.sin(theta3);
    -
    -  mat[0] = c1 * c3 - c2 * s1 * s3;
    -  mat[1] = c2 * c1 * s3 + c3 * s1;
    -  mat[2] = s3 * s2;
    -
    -  mat[3] = -c1 * s3 - c3 * c2 * s1;
    -  mat[4] = c1 * c2 * c3 - s1 * s3;
    -  mat[5] = c3 * s2;
    -
    -  mat[6] = s2 * s1;
    -  mat[7] = -c1 * s2;
    -  mat[8] = c2;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Decomposes a rotation matrix into Euler angles using the ZXZ convention so
    - * that rotation = rotation_z(theta1) * rotation_x(theta2) * rotation_z(theta3),
    - * with theta1 in [0, 2 * pi], theta2 in [0, pi] and theta3 in [0, 2 * pi].
    - * rotation_x(theta) means rotation around the X axis of theta radians.
    - *
    - * @param {goog.vec.mat3d.Type} mat The matrix.
    - * @param {goog.vec.vec3d.Type} euler The ZXZ Euler angles in
    - *     radians as [theta1, theta2, theta3].
    - * @param {boolean=} opt_theta2IsNegative Whether theta2 is in [-pi, 0] instead
    - *     of the default [0, pi].
    - * @return {!goog.vec.vec3d.Type} return euler so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3d.toEulerZXZ = function(mat, euler, opt_theta2IsNegative) {
    -  // There is an ambiguity in the sign of sinTheta2 because of the sqrt.
    -  var sinTheta2 = Math.sqrt(mat[2] * mat[2] + mat[5] * mat[5]);
    -
    -  // By default we explicitely constrain theta2 to be in [0, pi],
    -  // so sinTheta2 is always positive. We can change the behavior and specify
    -  // theta2 to be negative in [-pi, 0] with opt_Theta2IsNegative.
    -  var signTheta2 = opt_theta2IsNegative ? -1 : 1;
    -
    -  if (sinTheta2 > goog.vec.EPSILON) {
    -    euler[2] = Math.atan2(mat[2] * signTheta2, mat[5] * signTheta2);
    -    euler[1] = Math.atan2(sinTheta2 * signTheta2, mat[8]);
    -    euler[0] = Math.atan2(mat[6] * signTheta2, -mat[7] * signTheta2);
    -  } else {
    -    // There is also an arbitrary choice for theta1 = 0 or theta2 = 0 here.
    -    // We assume theta1 = 0 as some applications do not allow the camera to roll
    -    // (i.e. have theta1 != 0).
    -    euler[0] = 0;
    -    euler[1] = Math.atan2(sinTheta2 * signTheta2, mat[8]);
    -    euler[2] = Math.atan2(mat[1], mat[0]);
    -  }
    -
    -  // Atan2 outputs angles in [-pi, pi] so we bring them back to [0, 2 * pi].
    -  euler[0] = (euler[0] + Math.PI * 2) % (Math.PI * 2);
    -  euler[2] = (euler[2] + Math.PI * 2) % (Math.PI * 2);
    -  // For theta2 we want the angle to be in [0, pi] or [-pi, 0] depending on
    -  // signTheta2.
    -  euler[1] = ((euler[1] * signTheta2 + Math.PI * 2) % (Math.PI * 2)) *
    -      signTheta2;
    -
    -  return euler;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/mat3d_test.html b/src/database/third_party/closure-library/closure/goog/vec/mat3d_test.html
    deleted file mode 100644
    index 8bf68c6b3aa..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/mat3d_test.html
    +++ /dev/null
    @@ -1,432 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -//                                                                           //
    -// Any edits to this file must be applied to mat3f_test.html by running:     //
    -//   swap_type.sh mat3d_test.html > mat3f_test.html                          //
    -//                                                                           //
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.vec.mat3d</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.vec.mat3d');
    -  goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -  var randommat3d = goog.vec.mat3d.setFromValues(goog.vec.mat3d.create(),
    -      0.8025078773498535,
    -      0.7559120655059814,
    -      0.15274643898010254,
    -      0.19196106493473053,
    -      0.0890120416879654,
    -      0.15422114729881287,
    -      0.09754583984613419,
    -      0.44862601161003113,
    -      0.9196512699127197);
    -
    -  function testCreate() {
    -    var m = goog.vec.mat3d.create();
    -    assertElementsEquals([0, 0, 0, 0, 0, 0, 0, 0, 0], m);
    -  }
    -
    -  function testSet() {
    -    var m0 = goog.vec.mat3d.create();
    -    var m1 = goog.vec.mat3d.setFromArray(
    -        goog.vec.mat3d.create(), [1, 2, 3, 4, 5, 6, 7, 8, 9]);
    -    goog.vec.mat3d.setFromArray(m0, m1);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -
    -    goog.vec.mat3d.setFromValues(m0, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    -    assertElementsEquals([2, 3, 4, 5, 6, 7, 8, 9, 10], m0);
    -  }
    -
    -  function testSetDiagonal() {
    -    var m0 = goog.vec.mat3d.create();
    -    goog.vec.mat3d.setDiagonalValues(m0, 1, 2, 3);
    -    assertElementsEquals([1, 0, 0, 0, 2, 0, 0, 0, 3], m0);
    -
    -    goog.vec.mat3d.setDiagonal(m0, [4, 5, 6]);
    -    assertElementsEquals([4, 0, 0, 0, 5, 0, 0, 0, 6], m0);
    -  }
    -
    -  function testSetGetColumn() {
    -    var m0 = goog.vec.mat3d.create();
    -    goog.vec.mat3d.setColumn(m0, 0, [1, 2, 3]);
    -    goog.vec.mat3d.setColumn(m0, 1, [4, 5, 6]);
    -    goog.vec.mat3d.setColumn(m0, 2, [7, 8, 9]);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -
    -    var v0 = [0, 0, 0];
    -    goog.vec.mat3d.getColumn(m0, 0, v0);
    -    assertElementsEquals([1, 2, 3], v0);
    -    goog.vec.mat3d.getColumn(m0, 1, v0);
    -    assertElementsEquals([4, 5, 6], v0);
    -    goog.vec.mat3d.getColumn(m0, 2, v0);
    -    assertElementsEquals([7, 8, 9], v0);
    -  }
    -
    -  function testSetGetColumns() {
    -    var m0 = goog.vec.mat3d.create();
    -    goog.vec.mat3d.setColumns(m0, [1, 2, 3], [4, 5, 6], [7, 8, 9]);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -
    -    var v0 = [0, 0, 0], v1 = [0, 0, 0], v2 = [0, 0, 0];
    -    goog.vec.mat3d.getColumns(m0, v0, v1, v2);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals([4, 5, 6], v1);
    -    assertElementsEquals([7, 8, 9], v2);
    -  }
    -
    -  function testSetGetRow() {
    -    var m0 = goog.vec.mat3d.create();
    -    goog.vec.mat3d.setRow(m0, 0, [1, 2, 3]);
    -    goog.vec.mat3d.setRow(m0, 1, [4, 5, 6]);
    -    goog.vec.mat3d.setRow(m0, 2, [7, 8, 9]);
    -    assertElementsEquals([1, 4, 7, 2, 5, 8, 3, 6, 9], m0);
    -
    -    var v0 = [0, 0, 0];
    -    goog.vec.mat3d.getRow(m0, 0, v0);
    -    assertElementsEquals([1, 2, 3], v0);
    -    goog.vec.mat3d.getRow(m0, 1, v0);
    -    assertElementsEquals([4, 5, 6], v0);
    -    goog.vec.mat3d.getRow(m0, 2, v0);
    -    assertElementsEquals([7, 8, 9], v0);
    -  }
    -
    -  function testSetGetRows() {
    -    var m0 = goog.vec.mat3d.create();
    -    goog.vec.mat3d.setRows(m0, [1, 2, 3], [4, 5, 6], [7, 8, 9]);
    -    assertElementsEquals([1, 4, 7, 2, 5, 8, 3, 6, 9], m0);
    -
    -    var v0 = [0, 0, 0], v1 = [0, 0, 0], v2 = [0, 0, 0];
    -    goog.vec.mat3d.getRows(m0, v0, v1, v2);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals([4, 5, 6], v1);
    -    assertElementsEquals([7, 8, 9], v2);
    -  }
    -
    -  function testMakeZero() {
    -    var m0 = goog.vec.mat3d.setFromArray(
    -        goog.vec.mat3d.create(), [1, 2, 3, 4, 5, 6, 7, 8, 9]);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -    goog.vec.mat3d.makeZero(m0);
    -    assertElementsEquals([0, 0, 0, 0, 0, 0, 0, 0, 0], m0);
    -  }
    -
    -  function testMakeIdentity() {
    -    var m0 = goog.vec.mat3d.create();
    -    goog.vec.mat3d.makeIdentity(m0);
    -    assertElementsEquals([1, 0, 0, 0, 1, 0, 0, 0, 1], m0);
    -  }
    -
    -  function testSetGetElement() {
    -    var m0 = goog.vec.mat3d.create();
    -    for (var r = 0; r < 3; r++) {
    -      for (var c = 0; c < 3; c++) {
    -        var value = c * 3 + r + 1;
    -        goog.vec.mat3d.setElement(m0, r, c, value);
    -        assertEquals(value, goog.vec.mat3d.getElement(m0, r, c));
    -      }
    -    }
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -  }
    -
    -  function testAddMat() {
    -    var m0 = goog.vec.mat3d.setFromValues(
    -        goog.vec.mat3d.create(), 1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var m1 = goog.vec.mat3d.setFromValues(
    -        goog.vec.mat3d.create(), 3, 4, 5, 6, 7, 8, 9, 1, 2);
    -    var m2 = goog.vec.mat3d.create();
    -    goog.vec.mat3d.addMat(m0, m1, m2);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -    assertElementsEquals([3, 4, 5, 6, 7, 8, 9, 1, 2], m1);
    -    assertElementsEquals([4, 6, 8, 10, 12, 14, 16, 9, 11], m2);
    -
    -    goog.vec.mat3d.addMat(m0, m1, m0);
    -    assertElementsEquals([3, 4, 5, 6, 7, 8, 9, 1, 2], m1);
    -    assertElementsEquals([4, 6, 8, 10, 12, 14, 16, 9, 11], m0);
    -  }
    -
    -  function testSubMat() {
    -    var m0 = goog.vec.mat3d.setFromValues(
    -        goog.vec.mat3d.create(), 1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var m1 = goog.vec.mat3d.setFromValues(
    -        goog.vec.mat3d.create(), 3, 4, 5, 6, 7, 8, 9, 1, 2);
    -    var m2 = goog.vec.mat3d.create();
    -
    -    goog.vec.mat3d.subMat(m0, m1, m2);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -    assertElementsEquals([3, 4, 5, 6, 7, 8, 9, 1, 2], m1);
    -    assertElementsEquals([-2, -2, -2, -2, -2, -2, -2, 7, 7], m2);
    -
    -    goog.vec.mat3d.subMat(m1, m0, m1);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -    assertElementsEquals([2, 2, 2, 2, 2, 2, 2, -7, -7], m1);
    -  }
    -
    -  function testMultScalar() {
    -    var m0 = goog.vec.mat3d.setFromValues(
    -        goog.vec.mat3d.create(), 1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var m1 = goog.vec.mat3d.create();
    -
    -    goog.vec.mat3d.multScalar(m0, 5, m1);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -    assertElementsEquals([5, 10, 15, 20, 25, 30, 35, 40, 45], m1);
    -
    -    goog.vec.mat3d.multScalar(m0, 5, m0);
    -    assertElementsEquals([5, 10, 15, 20, 25, 30, 35, 40, 45], m0);
    -  }
    -
    -  function testMultMat() {
    -    var m0 = goog.vec.mat3d.setFromValues(
    -        goog.vec.mat3d.create(), 1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var m1 = goog.vec.mat3d.setFromValues(
    -        goog.vec.mat3d.create(), 1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var m2 = goog.vec.mat3d.create();
    -
    -    goog.vec.mat3d.multMat(m0, m1, m2);
    -    assertElementsEquals([30, 36, 42, 66, 81, 96, 102, 126, 150], m2);
    -
    -    goog.vec.mat3d.addMat(m0, m1, m1);
    -    goog.vec.mat3d.multMat(m0, m1, m1);
    -    assertElementsEquals([60, 72, 84, 132, 162, 192, 204, 252, 300], m1);
    -  }
    -
    -  function testTranspose() {
    -    var m0 = goog.vec.mat3d.setFromValues(
    -        goog.vec.mat3d.create(), 1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var m1 = goog.vec.mat3d.create();
    -    goog.vec.mat3d.transpose(m0, m1);
    -    assertElementsEquals([1, 4, 7, 2, 5, 8, 3, 6, 9], m1);
    -    goog.vec.mat3d.transpose(m1, m1);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m1);
    -  }
    -
    -  function testInvert() {
    -    var m0 = goog.vec.mat3d.setFromValues(
    -        goog.vec.mat3d.create(), 1, 1, 1, 1, 1, 1, 1, 1, 1);
    -    assertFalse(goog.vec.mat3d.invert(m0, m0));
    -    assertElementsEquals([1, 1, 1, 1, 1, 1, 1, 1, 1], m0);
    -
    -    goog.vec.mat3d.setFromValues(m0, 1, 2, 3, 1, 3, 4, 3, 4, 5);
    -    assertTrue(goog.vec.mat3d.invert(m0, m0));
    -    assertElementsEquals([0.5, -1.0, 0.5, -3.5, 2.0, 0.5, 2.5, -1.0, -0.5], m0);
    -
    -    goog.vec.mat3d.makeScale(m0, .01, .01, .01);
    -    assertTrue(goog.vec.mat3d.invert(m0, m0));
    -    var m1 = goog.vec.mat3d.create();
    -    goog.vec.mat3d.makeScale(m1, 100, 100, 100);
    -    assertElementsEquals(m1, m0);
    -  }
    -
    -  function testEquals() {
    -    var m0 = goog.vec.mat3d.setFromValues(
    -        goog.vec.mat3d.create(), 1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var m1 = goog.vec.mat3d.setFromArray(goog.vec.mat3d.create(), m0);
    -    assertTrue(goog.vec.mat3d.equals(m0, m1));
    -    assertTrue(goog.vec.mat3d.equals(m1, m0));
    -    for (var i = 0; i < 9; i++) {
    -      m1[i] = 15;
    -      assertFalse(goog.vec.mat3d.equals(m0, m1));
    -      assertFalse(goog.vec.mat3d.equals(m1, m0));
    -      m1[i] = i + 1;
    -    }
    -  }
    -
    -  function testMultVec3() {
    -    var m0 = goog.vec.mat3d.setFromValues(
    -        goog.vec.mat3d.create(), 1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var v0 = [1, 2, 3];
    -    var v1 = [0, 0, 0];
    -
    -    goog.vec.mat3d.multVec3(m0, v0, v1);
    -    assertElementsEquals([30, 36, 42], v1);
    -    goog.vec.mat3d.multVec3(m0, v0, v0);
    -    assertElementsEquals([30, 36, 42], v0);
    -  }
    -
    -  function testSetValues() {
    -    var a0 = goog.vec.mat3d.create();
    -    assertElementsEquals([0, 0, 0, 0, 0, 0, 0, 0, 0], a0);
    -    goog.vec.mat3d.setFromValues(a0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], a0);
    -
    -    var a1 = goog.vec.mat3d.create();
    -    goog.vec.mat3d.setDiagonalValues(a1, 1, 2, 3);
    -    assertElementsEquals([1, 0, 0, 0, 2, 0, 0, 0, 3], a1);
    -
    -    goog.vec.mat3d.setColumnValues(a1, 0, 2, 3, 4);
    -    goog.vec.mat3d.setColumnValues(a1, 1, 5, 6, 7);
    -    goog.vec.mat3d.setColumnValues(a1, 2, 8, 9, 1);
    -    assertElementsEquals([2, 3, 4, 5, 6, 7, 8, 9, 1], a1);
    -
    -    goog.vec.mat3d.setRowValues(a1, 0, 1, 4, 7);
    -    goog.vec.mat3d.setRowValues(a1, 1, 2, 5, 8);
    -    goog.vec.mat3d.setRowValues(a1, 2, 3, 6, 9);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], a1);
    -  }
    -
    -  function testMakeTranslate() {
    -    var m0 = goog.vec.mat3d.create();
    -    goog.vec.mat3d.makeTranslate(m0, 3, 4);
    -    assertElementsEquals([1, 0, 0, 0, 1, 0, 3, 4, 1], m0);
    -  }
    -
    -  function testMakeScale() {
    -    var m0 = goog.vec.mat3d.create();
    -    goog.vec.mat3d.makeScale(m0, 3, 4, 5);
    -    assertElementsEquals([3, 0, 0, 0, 4, 0, 0, 0, 5], m0);
    -  }
    -
    -  function testMakeRotate() {
    -    var m0 = goog.vec.mat3d.create();
    -    goog.vec.mat3d.makeRotate(m0, Math.PI / 2, 0, 0, 1);
    -    var v0 = [0, 1, 0, -1, 0, 0, 0, 0, 1];
    -    assertElementsRoughlyEqual(m0, v0, goog.vec.EPSILON);
    -
    -    var m1 = goog.vec.mat3d.create();
    -    goog.vec.mat3d.makeRotate(m1, -Math.PI / 4, 0, 0, 1);
    -    goog.vec.mat3d.multMat(m0, m1, m1);
    -    var v1 = [0.7071068, 0.7071068, 0, -0.7071068, 0.7071068, 0, 0, 0, 1];
    -    assertElementsRoughlyEqual(m1, v1, goog.vec.EPSILON);
    -  }
    -
    -  function testMakeRotateX() {
    -    var m0 = goog.vec.mat3d.create();
    -    var m1 = goog.vec.mat3d.create()
    -
    -    goog.vec.mat3d.makeRotateX(m0, Math.PI / 7);
    -    goog.vec.mat3d.makeRotate(m1, Math.PI / 7, 1, 0, 0);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testMakeRotateY() {
    -    var m0 = goog.vec.mat3d.create();
    -    var m1 = goog.vec.mat3d.create()
    -
    -    goog.vec.mat3d.makeRotateY(m0, Math.PI / 7);
    -    goog.vec.mat3d.makeRotate(m1, Math.PI / 7, 0, 1, 0);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testMakeRotateZ() {
    -    var m0 = goog.vec.mat3d.create();
    -    var m1 = goog.vec.mat3d.create()
    -
    -    goog.vec.mat3d.makeRotateZ(m0, Math.PI / 7);
    -    goog.vec.mat3d.makeRotate(m1, Math.PI / 7, 0, 0, 1);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testRotate() {
    -    var m0 = goog.vec.mat3d.makeIdentity(goog.vec.mat3d.create());
    -    goog.vec.mat3d.rotate(m0, Math.PI / 2, 0, 0, 1);
    -    assertElementsRoughlyEqual(
    -        [0, 1, 0, -1, 0, 0, 0, 0, 1],
    -        m0, goog.vec.EPSILON);
    -
    -    goog.vec.mat3d.rotate(m0, -Math.PI / 4, 0, 0, 1);
    -    assertElementsRoughlyEqual(
    -        [0.7071068, 0.7071068, 0,
    -         -0.7071068, 0.7071068, 0,
    -         0, 0, 1],
    -        m0, goog.vec.EPSILON);
    -  }
    -
    -  function testRotateX() {
    -    var m0 = goog.vec.mat3d.create();
    -    var m1 = goog.vec.mat3d.setFromArray(goog.vec.mat3d.create(), randommat3d);
    -
    -    goog.vec.mat3d.makeRotateX(m0, Math.PI / 7);
    -    goog.vec.mat3d.multMat(m1, m0, m0);
    -    goog.vec.mat3d.rotateX(m1, Math.PI / 7);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testRotateY() {
    -    var m0 = goog.vec.mat3d.create();
    -    var m1 = goog.vec.mat3d.setFromArray(goog.vec.mat3d.create(), randommat3d);
    -
    -    goog.vec.mat3d.makeRotateY(m0, Math.PI / 7);
    -    goog.vec.mat3d.multMat(m1, m0, m0);
    -    goog.vec.mat3d.rotateY(m1, Math.PI / 7);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testRotateZ() {
    -    var m0 = goog.vec.mat3d.create();
    -    var m1 = goog.vec.mat3d.setFromArray(goog.vec.mat3d.create(), randommat3d);
    -
    -    goog.vec.mat3d.makeRotateZ(m0, Math.PI / 7);
    -    goog.vec.mat3d.multMat(m1, m0, m0);
    -    goog.vec.mat3d.rotateZ(m1, Math.PI / 7);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testMakeEulerZXZ() {
    -    var m0 = goog.vec.mat3d.create();
    -    var roll = 0.200982 * 2 * Math.PI;
    -    var tilt = 0.915833 * Math.PI;
    -    var yaw = 0.839392 * 2 * Math.PI;
    -
    -    goog.vec.mat3d.makeRotate(m0, roll, 0, 0, 1);
    -    goog.vec.mat3d.rotate(m0, tilt, 1, 0, 0);
    -    goog.vec.mat3d.rotate(m0, yaw, 0, 0, 1);
    -
    -    var m1 = goog.vec.mat3d.create();
    -    goog.vec.mat3d.makeEulerZXZ(m1, roll, tilt, yaw);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -
    -
    -    var euler = [0, 0, 0];
    -    goog.vec.mat3d.toEulerZXZ(m0, euler);
    -
    -    assertRoughlyEquals(roll, euler[0], goog.vec.EPSILON);
    -    assertRoughlyEquals(tilt, euler[1], goog.vec.EPSILON);
    -    assertRoughlyEquals(yaw, euler[2], goog.vec.EPSILON);
    -
    -    // Test negative tilt now.
    -    goog.vec.mat3d.makeRotate(m0, roll, 0, 0, 1);
    -    goog.vec.mat3d.rotate(m0, -tilt, 1, 0, 0);
    -    goog.vec.mat3d.rotate(m0, yaw, 0, 0, 1);
    -
    -    goog.vec.mat3d.makeEulerZXZ(m1, roll, -tilt, yaw);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -
    -    var euler = [0, 0, 0];
    -    goog.vec.mat3d.toEulerZXZ(m0, euler, true);
    -
    -    assertRoughlyEquals(roll, euler[0], goog.vec.EPSILON);
    -    assertRoughlyEquals(-tilt, euler[1], goog.vec.EPSILON);
    -    assertRoughlyEquals(yaw, euler[2], goog.vec.EPSILON);
    -  }
    -
    -  function testEulerZXZExtrema() {
    -    var m0 = goog.vec.mat3d.setFromArray(goog.vec.mat3d.create(), 
    -        [1, 0, 0, 0, 0, -1, 0, 1, 0]);
    -    var m1 = goog.vec.mat3d.setFromArray(goog.vec.mat3d.create(), 
    -        [0, 0, 0, 0, 0, 0, 0, 0, 0]);
    -
    -    var euler = [0, 0, 0];
    -    goog.vec.mat3d.toEulerZXZ(m0, euler);
    -    assertElementsRoughlyEqual(
    -        [Math.PI, Math.PI / 2, Math.PI], euler, goog.vec.EPSILON);
    -    goog.vec.mat3d.makeEulerZXZ(m1, euler[0], euler[1], euler[2]);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -</script>
    -</body>
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/mat3f.js b/src/database/third_party/closure-library/closure/goog/vec/mat3f.js
    deleted file mode 100644
    index 28b04970879..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/mat3f.js
    +++ /dev/null
    @@ -1,1039 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -//                                                                           //
    -// Any edits to this file must be applied to mat3d.js by running:            //
    -//   swap_type.sh mat3f.js > mat3d.js                                        //
    -//                                                                           //
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -
    -
    -/**
    - * @fileoverview Provides functions for operating on 3x3 float (32bit)
    - * matrices.  The matrices are stored in column-major order.
    - *
    - * The last parameter will typically be the output object and an object
    - * can be both an input and output parameter to all methods except where
    - * noted.
    - *
    - * See the README for notes about the design and structure of the API
    - * (especially related to performance).
    - *
    - */
    -goog.provide('goog.vec.mat3f');
    -goog.provide('goog.vec.mat3f.Type');
    -
    -goog.require('goog.vec');
    -
    -
    -/** @typedef {goog.vec.Float32} */ goog.vec.mat3f.Type;
    -
    -
    -/**
    - * Creates a mat3f with all elements initialized to zero.
    - *
    - * @return {!goog.vec.mat3f.Type} The new mat3f.
    - */
    -goog.vec.mat3f.create = function() {
    -  return new Float32Array(9);
    -};
    -
    -
    -/**
    - * Initializes the matrix from the set of values. Note the values supplied are
    - * in column major order.
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix to receive the
    - *     values.
    - * @param {number} v00 The values at (0, 0).
    - * @param {number} v10 The values at (1, 0).
    - * @param {number} v20 The values at (2, 0).
    - * @param {number} v01 The values at (0, 1).
    - * @param {number} v11 The values at (1, 1).
    - * @param {number} v21 The values at (2, 1).
    - * @param {number} v02 The values at (0, 2).
    - * @param {number} v12 The values at (1, 2).
    - * @param {number} v22 The values at (2, 2).
    - * @return {!goog.vec.mat3f.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3f.setFromValues = function(
    -    mat, v00, v10, v20, v01, v11, v21, v02, v12, v22) {
    -  mat[0] = v00;
    -  mat[1] = v10;
    -  mat[2] = v20;
    -  mat[3] = v01;
    -  mat[4] = v11;
    -  mat[5] = v21;
    -  mat[6] = v02;
    -  mat[7] = v12;
    -  mat[8] = v22;
    -  return mat;
    -};
    -
    -
    -/**
    - * Initializes mat3f mat from mat3f src.
    - *
    - * @param {goog.vec.mat3f.Type} mat The destination matrix.
    - * @param {goog.vec.mat3f.Type} src The source matrix.
    - * @return {!goog.vec.mat3f.Type} Return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3f.setFromMat3f = function(mat, src) {
    -  mat[0] = src[0];
    -  mat[1] = src[1];
    -  mat[2] = src[2];
    -  mat[3] = src[3];
    -  mat[4] = src[4];
    -  mat[5] = src[5];
    -  mat[6] = src[6];
    -  mat[7] = src[7];
    -  mat[8] = src[8];
    -  return mat;
    -};
    -
    -
    -/**
    - * Initializes mat3f mat from mat3d src (typed as a Float64Array to
    - * avoid circular goog.requires).
    - *
    - * @param {goog.vec.mat3f.Type} mat The destination matrix.
    - * @param {Float64Array} src The source matrix.
    - * @return {!goog.vec.mat3f.Type} Return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3f.setFromMat3d = function(mat, src) {
    -  mat[0] = src[0];
    -  mat[1] = src[1];
    -  mat[2] = src[2];
    -  mat[3] = src[3];
    -  mat[4] = src[4];
    -  mat[5] = src[5];
    -  mat[6] = src[6];
    -  mat[7] = src[7];
    -  mat[8] = src[8];
    -  return mat;
    -};
    -
    -
    -/**
    - * Initializes mat3f mat from Array src.
    - *
    - * @param {goog.vec.mat3f.Type} mat The destination matrix.
    - * @param {Array<number>} src The source matrix.
    - * @return {!goog.vec.mat3f.Type} Return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3f.setFromArray = function(mat, src) {
    -  mat[0] = src[0];
    -  mat[1] = src[1];
    -  mat[2] = src[2];
    -  mat[3] = src[3];
    -  mat[4] = src[4];
    -  mat[5] = src[5];
    -  mat[6] = src[6];
    -  mat[7] = src[7];
    -  mat[8] = src[8];
    -  return mat;
    -};
    -
    -
    -/**
    - * Retrieves the element at the requested row and column.
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix containing the value to
    - *     retrieve.
    - * @param {number} row The row index.
    - * @param {number} column The column index.
    - * @return {number} The element value at the requested row, column indices.
    - */
    -goog.vec.mat3f.getElement = function(mat, row, column) {
    -  return mat[row + column * 3];
    -};
    -
    -
    -/**
    - * Sets the element at the requested row and column.
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix containing the value to
    - *     retrieve.
    - * @param {number} row The row index.
    - * @param {number} column The column index.
    - * @param {number} value The value to set at the requested row, column.
    - * @return {!goog.vec.mat3f.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3f.setElement = function(mat, row, column, value) {
    -  mat[row + column * 3] = value;
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the diagonal values of the matrix from the given values.
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix to receive the values.
    - * @param {number} v00 The values for (0, 0).
    - * @param {number} v11 The values for (1, 1).
    - * @param {number} v22 The values for (2, 2).
    - * @return {!goog.vec.mat3f.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3f.setDiagonalValues = function(mat, v00, v11, v22) {
    -  mat[0] = v00;
    -  mat[4] = v11;
    -  mat[8] = v22;
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the diagonal values of the matrix from the given vector.
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix to receive the values.
    - * @param {goog.vec.vec3f.Type} vec The vector containing the values.
    - * @return {!goog.vec.mat3f.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3f.setDiagonal = function(mat, vec) {
    -  mat[0] = vec[0];
    -  mat[4] = vec[1];
    -  mat[8] = vec[2];
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the specified column with the supplied values.
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix to recieve the values.
    - * @param {number} column The column index to set the values on.
    - * @param {number} v0 The value for row 0.
    - * @param {number} v1 The value for row 1.
    - * @param {number} v2 The value for row 2.
    - * @return {!goog.vec.mat3f.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3f.setColumnValues = function(mat, column, v0, v1, v2) {
    -  var i = column * 3;
    -  mat[i] = v0;
    -  mat[i + 1] = v1;
    -  mat[i + 2] = v2;
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the specified column with the value from the supplied array.
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix to receive the values.
    - * @param {number} column The column index to set the values on.
    - * @param {goog.vec.vec3f.Type} vec The vector elements for the column.
    - * @return {!goog.vec.mat3f.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3f.setColumn = function(mat, column, vec) {
    -  var i = column * 3;
    -  mat[i] = vec[0];
    -  mat[i + 1] = vec[1];
    -  mat[i + 2] = vec[2];
    -  return mat;
    -};
    -
    -
    -/**
    - * Retrieves the specified column from the matrix into the given vector
    - * array.
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix supplying the values.
    - * @param {number} column The column to get the values from.
    - * @param {goog.vec.vec3f.Type} vec The vector elements to receive the
    - *     column.
    - * @return {!goog.vec.vec3f.Type} return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3f.getColumn = function(mat, column, vec) {
    -  var i = column * 3;
    -  vec[0] = mat[i];
    -  vec[1] = mat[i + 1];
    -  vec[2] = mat[i + 2];
    -  return vec;
    -};
    -
    -
    -/**
    - * Sets the columns of the matrix from the set of vector elements.
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix to receive the values.
    - * @param {goog.vec.vec3f.Type} vec0 The values for column 0.
    - * @param {goog.vec.vec3f.Type} vec1 The values for column 1.
    - * @param {goog.vec.vec3f.Type} vec2 The values for column 2.
    - * @return {!goog.vec.mat3f.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3f.setColumns = function(mat, vec0, vec1, vec2) {
    -  goog.vec.mat3f.setColumn(mat, 0, vec0);
    -  goog.vec.mat3f.setColumn(mat, 1, vec1);
    -  goog.vec.mat3f.setColumn(mat, 2, vec2);
    -  return /** @type {!goog.vec.mat3f.Type} */(mat);
    -};
    -
    -
    -/**
    - * Retrieves the column values from the given matrix into the given vector
    - * elements.
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix supplying the columns.
    - * @param {goog.vec.vec3f.Type} vec0 The vector to receive column 0.
    - * @param {goog.vec.vec3f.Type} vec1 The vector to receive column 1.
    - * @param {goog.vec.vec3f.Type} vec2 The vector to receive column 2.
    - */
    -goog.vec.mat3f.getColumns = function(mat, vec0, vec1, vec2) {
    -  goog.vec.mat3f.getColumn(mat, 0, vec0);
    -  goog.vec.mat3f.getColumn(mat, 1, vec1);
    -  goog.vec.mat3f.getColumn(mat, 2, vec2);
    -};
    -
    -
    -/**
    - * Sets the row values from the supplied values.
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix to receive the values.
    - * @param {number} row The index of the row to receive the values.
    - * @param {number} v0 The value for column 0.
    - * @param {number} v1 The value for column 1.
    - * @param {number} v2 The value for column 2.
    - * @return {!goog.vec.mat3f.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3f.setRowValues = function(mat, row, v0, v1, v2) {
    -  mat[row] = v0;
    -  mat[row + 3] = v1;
    -  mat[row + 6] = v2;
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the row values from the supplied vector.
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix to receive the row values.
    - * @param {number} row The index of the row.
    - * @param {goog.vec.vec3f.Type} vec The vector containing the values.
    - * @return {!goog.vec.mat3f.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3f.setRow = function(mat, row, vec) {
    -  mat[row] = vec[0];
    -  mat[row + 3] = vec[1];
    -  mat[row + 6] = vec[2];
    -  return mat;
    -};
    -
    -
    -/**
    - * Retrieves the row values into the given vector.
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix supplying the values.
    - * @param {number} row The index of the row supplying the values.
    - * @param {goog.vec.vec3f.Type} vec The vector to receive the row.
    - * @return {!goog.vec.vec3f.Type} return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3f.getRow = function(mat, row, vec) {
    -  vec[0] = mat[row];
    -  vec[1] = mat[row + 3];
    -  vec[2] = mat[row + 6];
    -  return vec;
    -};
    -
    -
    -/**
    - * Sets the rows of the matrix from the supplied vectors.
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix to receive the values.
    - * @param {goog.vec.vec3f.Type} vec0 The values for row 0.
    - * @param {goog.vec.vec3f.Type} vec1 The values for row 1.
    - * @param {goog.vec.vec3f.Type} vec2 The values for row 2.
    - * @return {!goog.vec.mat3f.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3f.setRows = function(mat, vec0, vec1, vec2) {
    -  goog.vec.mat3f.setRow(mat, 0, vec0);
    -  goog.vec.mat3f.setRow(mat, 1, vec1);
    -  goog.vec.mat3f.setRow(mat, 2, vec2);
    -  return /** @type {!goog.vec.mat3f.Type} */(mat);
    -};
    -
    -
    -/**
    - * Retrieves the rows of the matrix into the supplied vectors.
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix to supplying the values.
    - * @param {goog.vec.vec3f.Type} vec0 The vector to receive row 0.
    - * @param {goog.vec.vec3f.Type} vec1 The vector to receive row 1.
    - * @param {goog.vec.vec3f.Type} vec2 The vector to receive row 2.
    - */
    -goog.vec.mat3f.getRows = function(mat, vec0, vec1, vec2) {
    -  goog.vec.mat3f.getRow(mat, 0, vec0);
    -  goog.vec.mat3f.getRow(mat, 1, vec1);
    -  goog.vec.mat3f.getRow(mat, 2, vec2);
    -};
    -
    -
    -/**
    - * Makes the given 3x3 matrix the zero matrix.
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix.
    - * @return {!goog.vec.mat3f.Type} return mat so operations can be chained.
    - */
    -goog.vec.mat3f.makeZero = function(mat) {
    -  mat[0] = 0;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 0;
    -  mat[5] = 0;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = 0;
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 3x3 matrix the identity matrix.
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix.
    - * @return {!goog.vec.mat3f.Type} return mat so operations can be chained.
    - */
    -goog.vec.mat3f.makeIdentity = function(mat) {
    -  mat[0] = 1;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 1;
    -  mat[5] = 0;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = 1;
    -  return mat;
    -};
    -
    -
    -/**
    - * Performs a per-component addition of the matrices mat0 and mat1, storing
    - * the result into resultMat.
    - *
    - * @param {goog.vec.mat3f.Type} mat0 The first addend.
    - * @param {goog.vec.mat3f.Type} mat1 The second addend.
    - * @param {goog.vec.mat3f.Type} resultMat The matrix to
    - *     receive the results (may be either mat0 or mat1).
    - * @return {!goog.vec.mat3f.Type} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3f.addMat = function(mat0, mat1, resultMat) {
    -  resultMat[0] = mat0[0] + mat1[0];
    -  resultMat[1] = mat0[1] + mat1[1];
    -  resultMat[2] = mat0[2] + mat1[2];
    -  resultMat[3] = mat0[3] + mat1[3];
    -  resultMat[4] = mat0[4] + mat1[4];
    -  resultMat[5] = mat0[5] + mat1[5];
    -  resultMat[6] = mat0[6] + mat1[6];
    -  resultMat[7] = mat0[7] + mat1[7];
    -  resultMat[8] = mat0[8] + mat1[8];
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Performs a per-component subtraction of the matrices mat0 and mat1,
    - * storing the result into resultMat.
    - *
    - * @param {goog.vec.mat3f.Type} mat0 The minuend.
    - * @param {goog.vec.mat3f.Type} mat1 The subtrahend.
    - * @param {goog.vec.mat3f.Type} resultMat The matrix to receive
    - *     the results (may be either mat0 or mat1).
    - * @return {!goog.vec.mat3f.Type} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3f.subMat = function(mat0, mat1, resultMat) {
    -  resultMat[0] = mat0[0] - mat1[0];
    -  resultMat[1] = mat0[1] - mat1[1];
    -  resultMat[2] = mat0[2] - mat1[2];
    -  resultMat[3] = mat0[3] - mat1[3];
    -  resultMat[4] = mat0[4] - mat1[4];
    -  resultMat[5] = mat0[5] - mat1[5];
    -  resultMat[6] = mat0[6] - mat1[6];
    -  resultMat[7] = mat0[7] - mat1[7];
    -  resultMat[8] = mat0[8] - mat1[8];
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Multiplies matrix mat0 with the given scalar, storing the result
    - * into resultMat.
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix.
    - * @param {number} scalar The scalar value to multiple to each element of mat.
    - * @param {goog.vec.mat3f.Type} resultMat The matrix to receive
    - *     the results (may be mat).
    - * @return {!goog.vec.mat3f.Type} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3f.multScalar = function(mat, scalar, resultMat) {
    -  resultMat[0] = mat[0] * scalar;
    -  resultMat[1] = mat[1] * scalar;
    -  resultMat[2] = mat[2] * scalar;
    -  resultMat[3] = mat[3] * scalar;
    -  resultMat[4] = mat[4] * scalar;
    -  resultMat[5] = mat[5] * scalar;
    -  resultMat[6] = mat[6] * scalar;
    -  resultMat[7] = mat[7] * scalar;
    -  resultMat[8] = mat[8] * scalar;
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Multiplies the two matrices mat0 and mat1 using matrix multiplication,
    - * storing the result into resultMat.
    - *
    - * @param {goog.vec.mat3f.Type} mat0 The first (left hand) matrix.
    - * @param {goog.vec.mat3f.Type} mat1 The second (right hand) matrix.
    - * @param {goog.vec.mat3f.Type} resultMat The matrix to receive
    - *     the results (may be either mat0 or mat1).
    - * @return {!goog.vec.mat3f.Type} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3f.multMat = function(mat0, mat1, resultMat) {
    -  var a00 = mat0[0], a10 = mat0[1], a20 = mat0[2];
    -  var a01 = mat0[3], a11 = mat0[4], a21 = mat0[5];
    -  var a02 = mat0[6], a12 = mat0[7], a22 = mat0[8];
    -
    -  var b00 = mat1[0], b10 = mat1[1], b20 = mat1[2];
    -  var b01 = mat1[3], b11 = mat1[4], b21 = mat1[5];
    -  var b02 = mat1[6], b12 = mat1[7], b22 = mat1[8];
    -
    -  resultMat[0] = a00 * b00 + a01 * b10 + a02 * b20;
    -  resultMat[1] = a10 * b00 + a11 * b10 + a12 * b20;
    -  resultMat[2] = a20 * b00 + a21 * b10 + a22 * b20;
    -  resultMat[3] = a00 * b01 + a01 * b11 + a02 * b21;
    -  resultMat[4] = a10 * b01 + a11 * b11 + a12 * b21;
    -  resultMat[5] = a20 * b01 + a21 * b11 + a22 * b21;
    -  resultMat[6] = a00 * b02 + a01 * b12 + a02 * b22;
    -  resultMat[7] = a10 * b02 + a11 * b12 + a12 * b22;
    -  resultMat[8] = a20 * b02 + a21 * b12 + a22 * b22;
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Transposes the given matrix mat storing the result into resultMat.
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix to transpose.
    - * @param {goog.vec.mat3f.Type} resultMat The matrix to receive
    - *     the results (may be mat).
    - * @return {!goog.vec.mat3f.Type} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3f.transpose = function(mat, resultMat) {
    -  if (resultMat == mat) {
    -    var a10 = mat[1], a20 = mat[2], a21 = mat[5];
    -    resultMat[1] = mat[3];
    -    resultMat[2] = mat[6];
    -    resultMat[3] = a10;
    -    resultMat[5] = mat[7];
    -    resultMat[6] = a20;
    -    resultMat[7] = a21;
    -  } else {
    -    resultMat[0] = mat[0];
    -    resultMat[1] = mat[3];
    -    resultMat[2] = mat[6];
    -    resultMat[3] = mat[1];
    -    resultMat[4] = mat[4];
    -    resultMat[5] = mat[7];
    -    resultMat[6] = mat[2];
    -    resultMat[7] = mat[5];
    -    resultMat[8] = mat[8];
    -  }
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Computes the inverse of mat0 storing the result into resultMat. If the
    - * inverse is defined, this function returns true, false otherwise.
    - *
    - * @param {goog.vec.mat3f.Type} mat0 The matrix to invert.
    - * @param {goog.vec.mat3f.Type} resultMat The matrix to receive
    - *     the result (may be mat0).
    - * @return {boolean} True if the inverse is defined. If false is returned,
    - *     resultMat is not modified.
    - */
    -goog.vec.mat3f.invert = function(mat0, resultMat) {
    -  var a00 = mat0[0], a10 = mat0[1], a20 = mat0[2];
    -  var a01 = mat0[3], a11 = mat0[4], a21 = mat0[5];
    -  var a02 = mat0[6], a12 = mat0[7], a22 = mat0[8];
    -
    -  var t00 = a11 * a22 - a12 * a21;
    -  var t10 = a12 * a20 - a10 * a22;
    -  var t20 = a10 * a21 - a11 * a20;
    -  var det = a00 * t00 + a01 * t10 + a02 * t20;
    -  if (det == 0) {
    -    return false;
    -  }
    -
    -  var idet = 1 / det;
    -  resultMat[0] = t00 * idet;
    -  resultMat[3] = (a02 * a21 - a01 * a22) * idet;
    -  resultMat[6] = (a01 * a12 - a02 * a11) * idet;
    -
    -  resultMat[1] = t10 * idet;
    -  resultMat[4] = (a00 * a22 - a02 * a20) * idet;
    -  resultMat[7] = (a02 * a10 - a00 * a12) * idet;
    -
    -  resultMat[2] = t20 * idet;
    -  resultMat[5] = (a01 * a20 - a00 * a21) * idet;
    -  resultMat[8] = (a00 * a11 - a01 * a10) * idet;
    -  return true;
    -};
    -
    -
    -/**
    - * Returns true if the components of mat0 are equal to the components of mat1.
    - *
    - * @param {goog.vec.mat3f.Type} mat0 The first matrix.
    - * @param {goog.vec.mat3f.Type} mat1 The second matrix.
    - * @return {boolean} True if the the two matrices are equivalent.
    - */
    -goog.vec.mat3f.equals = function(mat0, mat1) {
    -  return mat0.length == mat1.length &&
    -      mat0[0] == mat1[0] && mat0[1] == mat1[1] && mat0[2] == mat1[2] &&
    -      mat0[3] == mat1[3] && mat0[4] == mat1[4] && mat0[5] == mat1[5] &&
    -      mat0[6] == mat1[6] && mat0[7] == mat1[7] && mat0[8] == mat1[8];
    -};
    -
    -
    -/**
    - * Transforms the given vector with the given matrix storing the resulting,
    - * transformed matrix into resultVec.
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix supplying the transformation.
    - * @param {goog.vec.vec3f.Type} vec The vector to transform.
    - * @param {goog.vec.vec3f.Type} resultVec The vector to
    - *     receive the results (may be vec).
    - * @return {!goog.vec.vec3f.Type} return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3f.multVec3 = function(mat, vec, resultVec) {
    -  var x = vec[0], y = vec[1], z = vec[2];
    -  resultVec[0] = x * mat[0] + y * mat[3] + z * mat[6];
    -  resultVec[1] = x * mat[1] + y * mat[4] + z * mat[7];
    -  resultVec[2] = x * mat[2] + y * mat[5] + z * mat[8];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Makes the given 3x3 matrix a translation matrix with x and y
    - * translation values.
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix.
    - * @param {number} x The translation along the x axis.
    - * @param {number} y The translation along the y axis.
    - * @return {!goog.vec.mat3f.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat3f.makeTranslate = function(mat, x, y) {
    -  mat[0] = 1;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 1;
    -  mat[5] = 0;
    -  mat[6] = x;
    -  mat[7] = y;
    -  mat[8] = 1;
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 3x3 matrix a scale matrix with x, y, and z scale factors.
    - *
    - * @param {goog.vec.mat3f.Type} mat The 3x3 (9-element) matrix
    - *     array to receive the new scale matrix.
    - * @param {number} x The scale along the x axis.
    - * @param {number} y The scale along the y axis.
    - * @param {number} z The scale along the z axis.
    - * @return {!goog.vec.mat3f.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat3f.makeScale = function(mat, x, y, z) {
    -  mat[0] = x;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = y;
    -  mat[5] = 0;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = z;
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 3x3 matrix a rotation matrix with the given rotation
    - * angle about the axis defined by the vector (ax, ay, az).
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix.
    - * @param {number} angle The rotation angle in radians.
    - * @param {number} ax The x component of the rotation axis.
    - * @param {number} ay The y component of the rotation axis.
    - * @param {number} az The z component of the rotation axis.
    - * @return {!goog.vec.mat3f.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat3f.makeRotate = function(mat, angle, ax, ay, az) {
    -  var c = Math.cos(angle);
    -  var d = 1 - c;
    -  var s = Math.sin(angle);
    -
    -  mat[0] = ax * ax * d + c;
    -  mat[1] = ax * ay * d + az * s;
    -  mat[2] = ax * az * d - ay * s;
    -  mat[3] = ax * ay * d - az * s;
    -  mat[4] = ay * ay * d + c;
    -  mat[5] = ay * az * d + ax * s;
    -  mat[6] = ax * az * d + ay * s;
    -  mat[7] = ay * az * d - ax * s;
    -  mat[8] = az * az * d + c;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 3x3 matrix a rotation matrix with the given rotation
    - * angle about the X axis.
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix.
    - * @param {number} angle The rotation angle in radians.
    - * @return {!goog.vec.mat3f.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat3f.makeRotateX = function(mat, angle) {
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[0] = 1;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = c;
    -  mat[5] = s;
    -  mat[6] = 0;
    -  mat[7] = -s;
    -  mat[8] = c;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 3x3 matrix a rotation matrix with the given rotation
    - * angle about the Y axis.
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix.
    - * @param {number} angle The rotation angle in radians.
    - * @return {!goog.vec.mat3f.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat3f.makeRotateY = function(mat, angle) {
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[0] = c;
    -  mat[1] = 0;
    -  mat[2] = -s;
    -  mat[3] = 0;
    -  mat[4] = 1;
    -  mat[5] = 0;
    -  mat[6] = s;
    -  mat[7] = 0;
    -  mat[8] = c;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 3x3 matrix a rotation matrix with the given rotation
    - * angle about the Z axis.
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix.
    - * @param {number} angle The rotation angle in radians.
    - * @return {!goog.vec.mat3f.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat3f.makeRotateZ = function(mat, angle) {
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[0] = c;
    -  mat[1] = s;
    -  mat[2] = 0;
    -  mat[3] = -s;
    -  mat[4] = c;
    -  mat[5] = 0;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = 1;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Rotate the given matrix by angle about the x,y,z axis.  Equivalent to:
    - * goog.vec.mat3f.multMat(
    - *     mat,
    - *     goog.vec.mat3f.makeRotate(goog.vec.mat3f.create(), angle, x, y, z),
    - *     mat);
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix.
    - * @param {number} angle The angle in radians.
    - * @param {number} x The x component of the rotation axis.
    - * @param {number} y The y component of the rotation axis.
    - * @param {number} z The z component of the rotation axis.
    - * @return {!goog.vec.mat3f.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat3f.rotate = function(mat, angle, x, y, z) {
    -  var m00 = mat[0], m10 = mat[1], m20 = mat[2];
    -  var m01 = mat[3], m11 = mat[4], m21 = mat[5];
    -  var m02 = mat[6], m12 = mat[7], m22 = mat[8];
    -
    -  var cosAngle = Math.cos(angle);
    -  var sinAngle = Math.sin(angle);
    -  var diffCosAngle = 1 - cosAngle;
    -  var r00 = x * x * diffCosAngle + cosAngle;
    -  var r10 = x * y * diffCosAngle + z * sinAngle;
    -  var r20 = x * z * diffCosAngle - y * sinAngle;
    -
    -  var r01 = x * y * diffCosAngle - z * sinAngle;
    -  var r11 = y * y * diffCosAngle + cosAngle;
    -  var r21 = y * z * diffCosAngle + x * sinAngle;
    -
    -  var r02 = x * z * diffCosAngle + y * sinAngle;
    -  var r12 = y * z * diffCosAngle - x * sinAngle;
    -  var r22 = z * z * diffCosAngle + cosAngle;
    -
    -  mat[0] = m00 * r00 + m01 * r10 + m02 * r20;
    -  mat[1] = m10 * r00 + m11 * r10 + m12 * r20;
    -  mat[2] = m20 * r00 + m21 * r10 + m22 * r20;
    -  mat[3] = m00 * r01 + m01 * r11 + m02 * r21;
    -  mat[4] = m10 * r01 + m11 * r11 + m12 * r21;
    -  mat[5] = m20 * r01 + m21 * r11 + m22 * r21;
    -  mat[6] = m00 * r02 + m01 * r12 + m02 * r22;
    -  mat[7] = m10 * r02 + m11 * r12 + m12 * r22;
    -  mat[8] = m20 * r02 + m21 * r12 + m22 * r22;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Rotate the given matrix by angle about the x axis.  Equivalent to:
    - * goog.vec.mat3f.multMat(
    - *     mat,
    - *     goog.vec.mat3f.makeRotateX(goog.vec.mat3f.create(), angle),
    - *     mat);
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix.
    - * @param {number} angle The angle in radians.
    - * @return {!goog.vec.mat3f.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat3f.rotateX = function(mat, angle) {
    -  var m01 = mat[3], m11 = mat[4], m21 = mat[5];
    -  var m02 = mat[6], m12 = mat[7], m22 = mat[8];
    -
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[3] = m01 * c + m02 * s;
    -  mat[4] = m11 * c + m12 * s;
    -  mat[5] = m21 * c + m22 * s;
    -  mat[6] = m01 * -s + m02 * c;
    -  mat[7] = m11 * -s + m12 * c;
    -  mat[8] = m21 * -s + m22 * c;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Rotate the given matrix by angle about the y axis.  Equivalent to:
    - * goog.vec.mat3f.multMat(
    - *     mat,
    - *     goog.vec.mat3f.makeRotateY(goog.vec.mat3f.create(), angle),
    - *     mat);
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix.
    - * @param {number} angle The angle in radians.
    - * @return {!goog.vec.mat3f.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat3f.rotateY = function(mat, angle) {
    -  var m00 = mat[0], m10 = mat[1], m20 = mat[2];
    -  var m02 = mat[6], m12 = mat[7], m22 = mat[8];
    -
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[0] = m00 * c + m02 * -s;
    -  mat[1] = m10 * c + m12 * -s;
    -  mat[2] = m20 * c + m22 * -s;
    -  mat[6] = m00 * s + m02 * c;
    -  mat[7] = m10 * s + m12 * c;
    -  mat[8] = m20 * s + m22 * c;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Rotate the given matrix by angle about the z axis.  Equivalent to:
    - * goog.vec.mat3f.multMat(
    - *     mat,
    - *     goog.vec.mat3f.makeRotateZ(goog.vec.mat3f.create(), angle),
    - *     mat);
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix.
    - * @param {number} angle The angle in radians.
    - * @return {!goog.vec.mat3f.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat3f.rotateZ = function(mat, angle) {
    -  var m00 = mat[0], m10 = mat[1], m20 = mat[2];
    -  var m01 = mat[3], m11 = mat[4], m21 = mat[5];
    -
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[0] = m00 * c + m01 * s;
    -  mat[1] = m10 * c + m11 * s;
    -  mat[2] = m20 * c + m21 * s;
    -  mat[3] = m00 * -s + m01 * c;
    -  mat[4] = m10 * -s + m11 * c;
    -  mat[5] = m20 * -s + m21 * c;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 3x3 matrix a rotation matrix given Euler angles using
    - * the ZXZ convention.
    - * Given the euler angles [theta1, theta2, theta3], the rotation is defined as
    - * rotation = rotation_z(theta1) * rotation_x(theta2) * rotation_z(theta3),
    - * with theta1 in [0, 2 * pi], theta2 in [0, pi] and theta3 in [0, 2 * pi].
    - * rotation_x(theta) means rotation around the X axis of theta radians.
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix.
    - * @param {number} theta1 The angle of rotation around the Z axis in radians.
    - * @param {number} theta2 The angle of rotation around the X axis in radians.
    - * @param {number} theta3 The angle of rotation around the Z axis in radians.
    - * @return {!goog.vec.mat3f.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat3f.makeEulerZXZ = function(mat, theta1, theta2, theta3) {
    -  var c1 = Math.cos(theta1);
    -  var s1 = Math.sin(theta1);
    -
    -  var c2 = Math.cos(theta2);
    -  var s2 = Math.sin(theta2);
    -
    -  var c3 = Math.cos(theta3);
    -  var s3 = Math.sin(theta3);
    -
    -  mat[0] = c1 * c3 - c2 * s1 * s3;
    -  mat[1] = c2 * c1 * s3 + c3 * s1;
    -  mat[2] = s3 * s2;
    -
    -  mat[3] = -c1 * s3 - c3 * c2 * s1;
    -  mat[4] = c1 * c2 * c3 - s1 * s3;
    -  mat[5] = c3 * s2;
    -
    -  mat[6] = s2 * s1;
    -  mat[7] = -c1 * s2;
    -  mat[8] = c2;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Decomposes a rotation matrix into Euler angles using the ZXZ convention so
    - * that rotation = rotation_z(theta1) * rotation_x(theta2) * rotation_z(theta3),
    - * with theta1 in [0, 2 * pi], theta2 in [0, pi] and theta3 in [0, 2 * pi].
    - * rotation_x(theta) means rotation around the X axis of theta radians.
    - *
    - * @param {goog.vec.mat3f.Type} mat The matrix.
    - * @param {goog.vec.vec3f.Type} euler The ZXZ Euler angles in
    - *     radians as [theta1, theta2, theta3].
    - * @param {boolean=} opt_theta2IsNegative Whether theta2 is in [-pi, 0] instead
    - *     of the default [0, pi].
    - * @return {!goog.vec.vec3f.Type} return euler so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat3f.toEulerZXZ = function(mat, euler, opt_theta2IsNegative) {
    -  // There is an ambiguity in the sign of sinTheta2 because of the sqrt.
    -  var sinTheta2 = Math.sqrt(mat[2] * mat[2] + mat[5] * mat[5]);
    -
    -  // By default we explicitely constrain theta2 to be in [0, pi],
    -  // so sinTheta2 is always positive. We can change the behavior and specify
    -  // theta2 to be negative in [-pi, 0] with opt_Theta2IsNegative.
    -  var signTheta2 = opt_theta2IsNegative ? -1 : 1;
    -
    -  if (sinTheta2 > goog.vec.EPSILON) {
    -    euler[2] = Math.atan2(mat[2] * signTheta2, mat[5] * signTheta2);
    -    euler[1] = Math.atan2(sinTheta2 * signTheta2, mat[8]);
    -    euler[0] = Math.atan2(mat[6] * signTheta2, -mat[7] * signTheta2);
    -  } else {
    -    // There is also an arbitrary choice for theta1 = 0 or theta2 = 0 here.
    -    // We assume theta1 = 0 as some applications do not allow the camera to roll
    -    // (i.e. have theta1 != 0).
    -    euler[0] = 0;
    -    euler[1] = Math.atan2(sinTheta2 * signTheta2, mat[8]);
    -    euler[2] = Math.atan2(mat[1], mat[0]);
    -  }
    -
    -  // Atan2 outputs angles in [-pi, pi] so we bring them back to [0, 2 * pi].
    -  euler[0] = (euler[0] + Math.PI * 2) % (Math.PI * 2);
    -  euler[2] = (euler[2] + Math.PI * 2) % (Math.PI * 2);
    -  // For theta2 we want the angle to be in [0, pi] or [-pi, 0] depending on
    -  // signTheta2.
    -  euler[1] = ((euler[1] * signTheta2 + Math.PI * 2) % (Math.PI * 2)) *
    -      signTheta2;
    -
    -  return euler;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/mat3f_test.html b/src/database/third_party/closure-library/closure/goog/vec/mat3f_test.html
    deleted file mode 100644
    index 0f6633aef46..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/mat3f_test.html
    +++ /dev/null
    @@ -1,432 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -//                                                                           //
    -// Any edits to this file must be applied to mat3d_test.html by running:     //
    -//   swap_type.sh mat3f_test.html > mat3d_test.html                          //
    -//                                                                           //
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.vec.mat3f</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.vec.mat3f');
    -  goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -  var randommat3f = goog.vec.mat3f.setFromValues(goog.vec.mat3f.create(),
    -      0.8025078773498535,
    -      0.7559120655059814,
    -      0.15274643898010254,
    -      0.19196106493473053,
    -      0.0890120416879654,
    -      0.15422114729881287,
    -      0.09754583984613419,
    -      0.44862601161003113,
    -      0.9196512699127197);
    -
    -  function testCreate() {
    -    var m = goog.vec.mat3f.create();
    -    assertElementsEquals([0, 0, 0, 0, 0, 0, 0, 0, 0], m);
    -  }
    -
    -  function testSet() {
    -    var m0 = goog.vec.mat3f.create();
    -    var m1 = goog.vec.mat3f.setFromArray(
    -        goog.vec.mat3f.create(), [1, 2, 3, 4, 5, 6, 7, 8, 9]);
    -    goog.vec.mat3f.setFromArray(m0, m1);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -
    -    goog.vec.mat3f.setFromValues(m0, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    -    assertElementsEquals([2, 3, 4, 5, 6, 7, 8, 9, 10], m0);
    -  }
    -
    -  function testSetDiagonal() {
    -    var m0 = goog.vec.mat3f.create();
    -    goog.vec.mat3f.setDiagonalValues(m0, 1, 2, 3);
    -    assertElementsEquals([1, 0, 0, 0, 2, 0, 0, 0, 3], m0);
    -
    -    goog.vec.mat3f.setDiagonal(m0, [4, 5, 6]);
    -    assertElementsEquals([4, 0, 0, 0, 5, 0, 0, 0, 6], m0);
    -  }
    -
    -  function testSetGetColumn() {
    -    var m0 = goog.vec.mat3f.create();
    -    goog.vec.mat3f.setColumn(m0, 0, [1, 2, 3]);
    -    goog.vec.mat3f.setColumn(m0, 1, [4, 5, 6]);
    -    goog.vec.mat3f.setColumn(m0, 2, [7, 8, 9]);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -
    -    var v0 = [0, 0, 0];
    -    goog.vec.mat3f.getColumn(m0, 0, v0);
    -    assertElementsEquals([1, 2, 3], v0);
    -    goog.vec.mat3f.getColumn(m0, 1, v0);
    -    assertElementsEquals([4, 5, 6], v0);
    -    goog.vec.mat3f.getColumn(m0, 2, v0);
    -    assertElementsEquals([7, 8, 9], v0);
    -  }
    -
    -  function testSetGetColumns() {
    -    var m0 = goog.vec.mat3f.create();
    -    goog.vec.mat3f.setColumns(m0, [1, 2, 3], [4, 5, 6], [7, 8, 9]);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -
    -    var v0 = [0, 0, 0], v1 = [0, 0, 0], v2 = [0, 0, 0];
    -    goog.vec.mat3f.getColumns(m0, v0, v1, v2);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals([4, 5, 6], v1);
    -    assertElementsEquals([7, 8, 9], v2);
    -  }
    -
    -  function testSetGetRow() {
    -    var m0 = goog.vec.mat3f.create();
    -    goog.vec.mat3f.setRow(m0, 0, [1, 2, 3]);
    -    goog.vec.mat3f.setRow(m0, 1, [4, 5, 6]);
    -    goog.vec.mat3f.setRow(m0, 2, [7, 8, 9]);
    -    assertElementsEquals([1, 4, 7, 2, 5, 8, 3, 6, 9], m0);
    -
    -    var v0 = [0, 0, 0];
    -    goog.vec.mat3f.getRow(m0, 0, v0);
    -    assertElementsEquals([1, 2, 3], v0);
    -    goog.vec.mat3f.getRow(m0, 1, v0);
    -    assertElementsEquals([4, 5, 6], v0);
    -    goog.vec.mat3f.getRow(m0, 2, v0);
    -    assertElementsEquals([7, 8, 9], v0);
    -  }
    -
    -  function testSetGetRows() {
    -    var m0 = goog.vec.mat3f.create();
    -    goog.vec.mat3f.setRows(m0, [1, 2, 3], [4, 5, 6], [7, 8, 9]);
    -    assertElementsEquals([1, 4, 7, 2, 5, 8, 3, 6, 9], m0);
    -
    -    var v0 = [0, 0, 0], v1 = [0, 0, 0], v2 = [0, 0, 0];
    -    goog.vec.mat3f.getRows(m0, v0, v1, v2);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals([4, 5, 6], v1);
    -    assertElementsEquals([7, 8, 9], v2);
    -  }
    -
    -  function testMakeZero() {
    -    var m0 = goog.vec.mat3f.setFromArray(
    -        goog.vec.mat3f.create(), [1, 2, 3, 4, 5, 6, 7, 8, 9]);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -    goog.vec.mat3f.makeZero(m0);
    -    assertElementsEquals([0, 0, 0, 0, 0, 0, 0, 0, 0], m0);
    -  }
    -
    -  function testMakeIdentity() {
    -    var m0 = goog.vec.mat3f.create();
    -    goog.vec.mat3f.makeIdentity(m0);
    -    assertElementsEquals([1, 0, 0, 0, 1, 0, 0, 0, 1], m0);
    -  }
    -
    -  function testSetGetElement() {
    -    var m0 = goog.vec.mat3f.create();
    -    for (var r = 0; r < 3; r++) {
    -      for (var c = 0; c < 3; c++) {
    -        var value = c * 3 + r + 1;
    -        goog.vec.mat3f.setElement(m0, r, c, value);
    -        assertEquals(value, goog.vec.mat3f.getElement(m0, r, c));
    -      }
    -    }
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -  }
    -
    -  function testAddMat() {
    -    var m0 = goog.vec.mat3f.setFromValues(
    -        goog.vec.mat3f.create(), 1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var m1 = goog.vec.mat3f.setFromValues(
    -        goog.vec.mat3f.create(), 3, 4, 5, 6, 7, 8, 9, 1, 2);
    -    var m2 = goog.vec.mat3f.create();
    -    goog.vec.mat3f.addMat(m0, m1, m2);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -    assertElementsEquals([3, 4, 5, 6, 7, 8, 9, 1, 2], m1);
    -    assertElementsEquals([4, 6, 8, 10, 12, 14, 16, 9, 11], m2);
    -
    -    goog.vec.mat3f.addMat(m0, m1, m0);
    -    assertElementsEquals([3, 4, 5, 6, 7, 8, 9, 1, 2], m1);
    -    assertElementsEquals([4, 6, 8, 10, 12, 14, 16, 9, 11], m0);
    -  }
    -
    -  function testSubMat() {
    -    var m0 = goog.vec.mat3f.setFromValues(
    -        goog.vec.mat3f.create(), 1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var m1 = goog.vec.mat3f.setFromValues(
    -        goog.vec.mat3f.create(), 3, 4, 5, 6, 7, 8, 9, 1, 2);
    -    var m2 = goog.vec.mat3f.create();
    -
    -    goog.vec.mat3f.subMat(m0, m1, m2);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -    assertElementsEquals([3, 4, 5, 6, 7, 8, 9, 1, 2], m1);
    -    assertElementsEquals([-2, -2, -2, -2, -2, -2, -2, 7, 7], m2);
    -
    -    goog.vec.mat3f.subMat(m1, m0, m1);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -    assertElementsEquals([2, 2, 2, 2, 2, 2, 2, -7, -7], m1);
    -  }
    -
    -  function testMultScalar() {
    -    var m0 = goog.vec.mat3f.setFromValues(
    -        goog.vec.mat3f.create(), 1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var m1 = goog.vec.mat3f.create();
    -
    -    goog.vec.mat3f.multScalar(m0, 5, m1);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -    assertElementsEquals([5, 10, 15, 20, 25, 30, 35, 40, 45], m1);
    -
    -    goog.vec.mat3f.multScalar(m0, 5, m0);
    -    assertElementsEquals([5, 10, 15, 20, 25, 30, 35, 40, 45], m0);
    -  }
    -
    -  function testMultMat() {
    -    var m0 = goog.vec.mat3f.setFromValues(
    -        goog.vec.mat3f.create(), 1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var m1 = goog.vec.mat3f.setFromValues(
    -        goog.vec.mat3f.create(), 1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var m2 = goog.vec.mat3f.create();
    -
    -    goog.vec.mat3f.multMat(m0, m1, m2);
    -    assertElementsEquals([30, 36, 42, 66, 81, 96, 102, 126, 150], m2);
    -
    -    goog.vec.mat3f.addMat(m0, m1, m1);
    -    goog.vec.mat3f.multMat(m0, m1, m1);
    -    assertElementsEquals([60, 72, 84, 132, 162, 192, 204, 252, 300], m1);
    -  }
    -
    -  function testTranspose() {
    -    var m0 = goog.vec.mat3f.setFromValues(
    -        goog.vec.mat3f.create(), 1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var m1 = goog.vec.mat3f.create();
    -    goog.vec.mat3f.transpose(m0, m1);
    -    assertElementsEquals([1, 4, 7, 2, 5, 8, 3, 6, 9], m1);
    -    goog.vec.mat3f.transpose(m1, m1);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m1);
    -  }
    -
    -  function testInvert() {
    -    var m0 = goog.vec.mat3f.setFromValues(
    -        goog.vec.mat3f.create(), 1, 1, 1, 1, 1, 1, 1, 1, 1);
    -    assertFalse(goog.vec.mat3f.invert(m0, m0));
    -    assertElementsEquals([1, 1, 1, 1, 1, 1, 1, 1, 1], m0);
    -
    -    goog.vec.mat3f.setFromValues(m0, 1, 2, 3, 1, 3, 4, 3, 4, 5);
    -    assertTrue(goog.vec.mat3f.invert(m0, m0));
    -    assertElementsEquals([0.5, -1.0, 0.5, -3.5, 2.0, 0.5, 2.5, -1.0, -0.5], m0);
    -
    -    goog.vec.mat3f.makeScale(m0, .01, .01, .01);
    -    assertTrue(goog.vec.mat3f.invert(m0, m0));
    -    var m1 = goog.vec.mat3f.create();
    -    goog.vec.mat3f.makeScale(m1, 100, 100, 100);
    -    assertElementsEquals(m1, m0);
    -  }
    -
    -  function testEquals() {
    -    var m0 = goog.vec.mat3f.setFromValues(
    -        goog.vec.mat3f.create(), 1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var m1 = goog.vec.mat3f.setFromArray(goog.vec.mat3f.create(), m0);
    -    assertTrue(goog.vec.mat3f.equals(m0, m1));
    -    assertTrue(goog.vec.mat3f.equals(m1, m0));
    -    for (var i = 0; i < 9; i++) {
    -      m1[i] = 15;
    -      assertFalse(goog.vec.mat3f.equals(m0, m1));
    -      assertFalse(goog.vec.mat3f.equals(m1, m0));
    -      m1[i] = i + 1;
    -    }
    -  }
    -
    -  function testMultVec3() {
    -    var m0 = goog.vec.mat3f.setFromValues(
    -        goog.vec.mat3f.create(), 1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var v0 = [1, 2, 3];
    -    var v1 = [0, 0, 0];
    -
    -    goog.vec.mat3f.multVec3(m0, v0, v1);
    -    assertElementsEquals([30, 36, 42], v1);
    -    goog.vec.mat3f.multVec3(m0, v0, v0);
    -    assertElementsEquals([30, 36, 42], v0);
    -  }
    -
    -  function testSetValues() {
    -    var a0 = goog.vec.mat3f.create();
    -    assertElementsEquals([0, 0, 0, 0, 0, 0, 0, 0, 0], a0);
    -    goog.vec.mat3f.setFromValues(a0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], a0);
    -
    -    var a1 = goog.vec.mat3f.create();
    -    goog.vec.mat3f.setDiagonalValues(a1, 1, 2, 3);
    -    assertElementsEquals([1, 0, 0, 0, 2, 0, 0, 0, 3], a1);
    -
    -    goog.vec.mat3f.setColumnValues(a1, 0, 2, 3, 4);
    -    goog.vec.mat3f.setColumnValues(a1, 1, 5, 6, 7);
    -    goog.vec.mat3f.setColumnValues(a1, 2, 8, 9, 1);
    -    assertElementsEquals([2, 3, 4, 5, 6, 7, 8, 9, 1], a1);
    -
    -    goog.vec.mat3f.setRowValues(a1, 0, 1, 4, 7);
    -    goog.vec.mat3f.setRowValues(a1, 1, 2, 5, 8);
    -    goog.vec.mat3f.setRowValues(a1, 2, 3, 6, 9);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], a1);
    -  }
    -
    -  function testMakeTranslate() {
    -    var m0 = goog.vec.mat3f.create();
    -    goog.vec.mat3f.makeTranslate(m0, 3, 4);
    -    assertElementsEquals([1, 0, 0, 0, 1, 0, 3, 4, 1], m0);
    -  }
    -
    -  function testMakeScale() {
    -    var m0 = goog.vec.mat3f.create();
    -    goog.vec.mat3f.makeScale(m0, 3, 4, 5);
    -    assertElementsEquals([3, 0, 0, 0, 4, 0, 0, 0, 5], m0);
    -  }
    -
    -  function testMakeRotate() {
    -    var m0 = goog.vec.mat3f.create();
    -    goog.vec.mat3f.makeRotate(m0, Math.PI / 2, 0, 0, 1);
    -    var v0 = [0, 1, 0, -1, 0, 0, 0, 0, 1];
    -    assertElementsRoughlyEqual(m0, v0, goog.vec.EPSILON);
    -
    -    var m1 = goog.vec.mat3f.create();
    -    goog.vec.mat3f.makeRotate(m1, -Math.PI / 4, 0, 0, 1);
    -    goog.vec.mat3f.multMat(m0, m1, m1);
    -    var v1 = [0.7071068, 0.7071068, 0, -0.7071068, 0.7071068, 0, 0, 0, 1];
    -    assertElementsRoughlyEqual(m1, v1, goog.vec.EPSILON);
    -  }
    -
    -  function testMakeRotateX() {
    -    var m0 = goog.vec.mat3f.create();
    -    var m1 = goog.vec.mat3f.create()
    -
    -    goog.vec.mat3f.makeRotateX(m0, Math.PI / 7);
    -    goog.vec.mat3f.makeRotate(m1, Math.PI / 7, 1, 0, 0);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testMakeRotateY() {
    -    var m0 = goog.vec.mat3f.create();
    -    var m1 = goog.vec.mat3f.create()
    -
    -    goog.vec.mat3f.makeRotateY(m0, Math.PI / 7);
    -    goog.vec.mat3f.makeRotate(m1, Math.PI / 7, 0, 1, 0);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testMakeRotateZ() {
    -    var m0 = goog.vec.mat3f.create();
    -    var m1 = goog.vec.mat3f.create()
    -
    -    goog.vec.mat3f.makeRotateZ(m0, Math.PI / 7);
    -    goog.vec.mat3f.makeRotate(m1, Math.PI / 7, 0, 0, 1);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testRotate() {
    -    var m0 = goog.vec.mat3f.makeIdentity(goog.vec.mat3f.create());
    -    goog.vec.mat3f.rotate(m0, Math.PI / 2, 0, 0, 1);
    -    assertElementsRoughlyEqual(
    -        [0, 1, 0, -1, 0, 0, 0, 0, 1],
    -        m0, goog.vec.EPSILON);
    -
    -    goog.vec.mat3f.rotate(m0, -Math.PI / 4, 0, 0, 1);
    -    assertElementsRoughlyEqual(
    -        [0.7071068, 0.7071068, 0,
    -         -0.7071068, 0.7071068, 0,
    -         0, 0, 1],
    -        m0, goog.vec.EPSILON);
    -  }
    -
    -  function testRotateX() {
    -    var m0 = goog.vec.mat3f.create();
    -    var m1 = goog.vec.mat3f.setFromArray(goog.vec.mat3f.create(), randommat3f);
    -
    -    goog.vec.mat3f.makeRotateX(m0, Math.PI / 7);
    -    goog.vec.mat3f.multMat(m1, m0, m0);
    -    goog.vec.mat3f.rotateX(m1, Math.PI / 7);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testRotateY() {
    -    var m0 = goog.vec.mat3f.create();
    -    var m1 = goog.vec.mat3f.setFromArray(goog.vec.mat3f.create(), randommat3f);
    -
    -    goog.vec.mat3f.makeRotateY(m0, Math.PI / 7);
    -    goog.vec.mat3f.multMat(m1, m0, m0);
    -    goog.vec.mat3f.rotateY(m1, Math.PI / 7);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testRotateZ() {
    -    var m0 = goog.vec.mat3f.create();
    -    var m1 = goog.vec.mat3f.setFromArray(goog.vec.mat3f.create(), randommat3f);
    -
    -    goog.vec.mat3f.makeRotateZ(m0, Math.PI / 7);
    -    goog.vec.mat3f.multMat(m1, m0, m0);
    -    goog.vec.mat3f.rotateZ(m1, Math.PI / 7);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testMakeEulerZXZ() {
    -    var m0 = goog.vec.mat3f.create();
    -    var roll = 0.200982 * 2 * Math.PI;
    -    var tilt = 0.915833 * Math.PI;
    -    var yaw = 0.839392 * 2 * Math.PI;
    -
    -    goog.vec.mat3f.makeRotate(m0, roll, 0, 0, 1);
    -    goog.vec.mat3f.rotate(m0, tilt, 1, 0, 0);
    -    goog.vec.mat3f.rotate(m0, yaw, 0, 0, 1);
    -
    -    var m1 = goog.vec.mat3f.create();
    -    goog.vec.mat3f.makeEulerZXZ(m1, roll, tilt, yaw);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -
    -
    -    var euler = [0, 0, 0];
    -    goog.vec.mat3f.toEulerZXZ(m0, euler);
    -
    -    assertRoughlyEquals(roll, euler[0], goog.vec.EPSILON);
    -    assertRoughlyEquals(tilt, euler[1], goog.vec.EPSILON);
    -    assertRoughlyEquals(yaw, euler[2], goog.vec.EPSILON);
    -
    -    // Test negative tilt now.
    -    goog.vec.mat3f.makeRotate(m0, roll, 0, 0, 1);
    -    goog.vec.mat3f.rotate(m0, -tilt, 1, 0, 0);
    -    goog.vec.mat3f.rotate(m0, yaw, 0, 0, 1);
    -
    -    goog.vec.mat3f.makeEulerZXZ(m1, roll, -tilt, yaw);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -
    -    var euler = [0, 0, 0];
    -    goog.vec.mat3f.toEulerZXZ(m0, euler, true);
    -
    -    assertRoughlyEquals(roll, euler[0], goog.vec.EPSILON);
    -    assertRoughlyEquals(-tilt, euler[1], goog.vec.EPSILON);
    -    assertRoughlyEquals(yaw, euler[2], goog.vec.EPSILON);
    -  }
    -
    -  function testEulerZXZExtrema() {
    -    var m0 = goog.vec.mat3f.setFromArray(goog.vec.mat3f.create(), 
    -        [1, 0, 0, 0, 0, -1, 0, 1, 0]);
    -    var m1 = goog.vec.mat3f.setFromArray(goog.vec.mat3f.create(), 
    -        [0, 0, 0, 0, 0, 0, 0, 0, 0]);
    -
    -    var euler = [0, 0, 0];
    -    goog.vec.mat3f.toEulerZXZ(m0, euler);
    -    assertElementsRoughlyEqual(
    -        [Math.PI, Math.PI / 2, Math.PI], euler, goog.vec.EPSILON);
    -    goog.vec.mat3f.makeEulerZXZ(m1, euler[0], euler[1], euler[2]);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -</script>
    -</body>
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/mat4.js b/src/database/third_party/closure-library/closure/goog/vec/mat4.js
    deleted file mode 100644
    index d047b7a79d9..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/mat4.js
    +++ /dev/null
    @@ -1,1822 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Implements 4x4 matrices and their related functions which are
    - * compatible with WebGL. The API is structured to avoid unnecessary memory
    - * allocations.  The last parameter will typically be the output vector and
    - * an object can be both an input and output parameter to all methods except
    - * where noted. Matrix operations follow the mathematical form when multiplying
    - * vectors as follows: resultVec = matrix * vec.
    - *
    - * The matrices are stored in column-major order.
    - *
    - */
    -goog.provide('goog.vec.Mat4');
    -
    -goog.require('goog.vec');
    -goog.require('goog.vec.Vec3');
    -goog.require('goog.vec.Vec4');
    -
    -
    -/** @typedef {goog.vec.Float32} */ goog.vec.Mat4.Float32;
    -/** @typedef {goog.vec.Float64} */ goog.vec.Mat4.Float64;
    -/** @typedef {goog.vec.Number} */ goog.vec.Mat4.Number;
    -/** @typedef {goog.vec.AnyType} */ goog.vec.Mat4.AnyType;
    -
    -// The following two types are deprecated - use the above types instead.
    -/** @typedef {!Float32Array} */ goog.vec.Mat4.Type;
    -/** @typedef {goog.vec.ArrayType} */ goog.vec.Mat4.Mat4Like;
    -
    -
    -/**
    - * Creates the array representation of a 4x4 matrix of Float32.
    - * The use of the array directly instead of a class reduces overhead.
    - * The returned matrix is cleared to all zeros.
    - *
    - * @return {!goog.vec.Mat4.Float32} The new matrix.
    - */
    -goog.vec.Mat4.createFloat32 = function() {
    -  return new Float32Array(16);
    -};
    -
    -
    -/**
    - * Creates the array representation of a 4x4 matrix of Float64.
    - * The returned matrix is cleared to all zeros.
    - *
    - * @return {!goog.vec.Mat4.Float64} The new matrix.
    - */
    -goog.vec.Mat4.createFloat64 = function() {
    -  return new Float64Array(16);
    -};
    -
    -
    -/**
    - * Creates the array representation of a 4x4 matrix of Number.
    - * The returned matrix is cleared to all zeros.
    - *
    - * @return {!goog.vec.Mat4.Number} The new matrix.
    - */
    -goog.vec.Mat4.createNumber = function() {
    -  var a = new Array(16);
    -  goog.vec.Mat4.setFromValues(a,
    -                              0, 0, 0, 0,
    -                              0, 0, 0, 0,
    -                              0, 0, 0, 0,
    -                              0, 0, 0, 0);
    -  return a;
    -};
    -
    -
    -/**
    - * Creates the array representation of a 4x4 matrix of Float32.
    - * The returned matrix is cleared to all zeros.
    - *
    - * @deprecated Use createFloat32.
    - * @return {!goog.vec.Mat4.Type} The new matrix.
    - */
    -goog.vec.Mat4.create = function() {
    -  return goog.vec.Mat4.createFloat32();
    -};
    -
    -
    -/**
    - * Creates a 4x4 identity matrix of Float32.
    - *
    - * @return {!goog.vec.Mat4.Float32} The new 16 element array.
    - */
    -goog.vec.Mat4.createFloat32Identity = function() {
    -  var mat = goog.vec.Mat4.createFloat32();
    -  mat[0] = mat[5] = mat[10] = mat[15] = 1;
    -  return mat;
    -};
    -
    -
    -/**
    - * Creates a 4x4 identity matrix of Float64.
    - *
    - * @return {!goog.vec.Mat4.Float64} The new 16 element array.
    - */
    -goog.vec.Mat4.createFloat64Identity = function() {
    -  var mat = goog.vec.Mat4.createFloat64();
    -  mat[0] = mat[5] = mat[10] = mat[15] = 1;
    -  return mat;
    -};
    -
    -
    -/**
    - * Creates a 4x4 identity matrix of Number.
    - * The returned matrix is cleared to all zeros.
    - *
    - * @return {!goog.vec.Mat4.Number} The new 16 element array.
    - */
    -goog.vec.Mat4.createNumberIdentity = function() {
    -  var a = new Array(16);
    -  goog.vec.Mat4.setFromValues(a,
    -                              1, 0, 0, 0,
    -                              0, 1, 0, 0,
    -                              0, 0, 1, 0,
    -                              0, 0, 0, 1);
    -  return a;
    -};
    -
    -
    -/**
    - * Creates the array representation of a 4x4 matrix of Float32.
    - * The returned matrix is cleared to all zeros.
    - *
    - * @deprecated Use createFloat32Identity.
    - * @return {!goog.vec.Mat4.Type} The new 16 element array.
    - */
    -goog.vec.Mat4.createIdentity = function() {
    -  return goog.vec.Mat4.createFloat32Identity();
    -};
    -
    -
    -/**
    - * Creates a 4x4 matrix of Float32 initialized from the given array.
    - *
    - * @param {goog.vec.Mat4.AnyType} matrix The array containing the
    - *     matrix values in column major order.
    - * @return {!goog.vec.Mat4.Float32} The new, 16 element array.
    - */
    -goog.vec.Mat4.createFloat32FromArray = function(matrix) {
    -  var newMatrix = goog.vec.Mat4.createFloat32();
    -  goog.vec.Mat4.setFromArray(newMatrix, matrix);
    -  return newMatrix;
    -};
    -
    -
    -/**
    - * Creates a 4x4 matrix of Float32 initialized from the given values.
    - *
    - * @param {number} v00 The values at (0, 0).
    - * @param {number} v10 The values at (1, 0).
    - * @param {number} v20 The values at (2, 0).
    - * @param {number} v30 The values at (3, 0).
    - * @param {number} v01 The values at (0, 1).
    - * @param {number} v11 The values at (1, 1).
    - * @param {number} v21 The values at (2, 1).
    - * @param {number} v31 The values at (3, 1).
    - * @param {number} v02 The values at (0, 2).
    - * @param {number} v12 The values at (1, 2).
    - * @param {number} v22 The values at (2, 2).
    - * @param {number} v32 The values at (3, 2).
    - * @param {number} v03 The values at (0, 3).
    - * @param {number} v13 The values at (1, 3).
    - * @param {number} v23 The values at (2, 3).
    - * @param {number} v33 The values at (3, 3).
    - * @return {!goog.vec.Mat4.Float32} The new, 16 element array.
    - */
    -goog.vec.Mat4.createFloat32FromValues = function(
    -    v00, v10, v20, v30,
    -    v01, v11, v21, v31,
    -    v02, v12, v22, v32,
    -    v03, v13, v23, v33) {
    -  var newMatrix = goog.vec.Mat4.createFloat32();
    -  goog.vec.Mat4.setFromValues(
    -      newMatrix, v00, v10, v20, v30, v01, v11, v21, v31, v02, v12, v22, v32,
    -      v03, v13, v23, v33);
    -  return newMatrix;
    -};
    -
    -
    -/**
    - * Creates a clone of a 4x4 matrix of Float32.
    - *
    - * @param {goog.vec.Mat4.Float32} matrix The source 4x4 matrix.
    - * @return {!goog.vec.Mat4.Float32} The new 4x4 element matrix.
    - */
    -goog.vec.Mat4.cloneFloat32 = goog.vec.Mat4.createFloat32FromArray;
    -
    -
    -/**
    - * Creates a 4x4 matrix of Float64 initialized from the given array.
    - *
    - * @param {goog.vec.Mat4.AnyType} matrix The array containing the
    - *     matrix values in column major order.
    - * @return {!goog.vec.Mat4.Float64} The new, nine element array.
    - */
    -goog.vec.Mat4.createFloat64FromArray = function(matrix) {
    -  var newMatrix = goog.vec.Mat4.createFloat64();
    -  goog.vec.Mat4.setFromArray(newMatrix, matrix);
    -  return newMatrix;
    -};
    -
    -
    -/**
    - * Creates a 4x4 matrix of Float64 initialized from the given values.
    - *
    - * @param {number} v00 The values at (0, 0).
    - * @param {number} v10 The values at (1, 0).
    - * @param {number} v20 The values at (2, 0).
    - * @param {number} v30 The values at (3, 0).
    - * @param {number} v01 The values at (0, 1).
    - * @param {number} v11 The values at (1, 1).
    - * @param {number} v21 The values at (2, 1).
    - * @param {number} v31 The values at (3, 1).
    - * @param {number} v02 The values at (0, 2).
    - * @param {number} v12 The values at (1, 2).
    - * @param {number} v22 The values at (2, 2).
    - * @param {number} v32 The values at (3, 2).
    - * @param {number} v03 The values at (0, 3).
    - * @param {number} v13 The values at (1, 3).
    - * @param {number} v23 The values at (2, 3).
    - * @param {number} v33 The values at (3, 3).
    - * @return {!goog.vec.Mat4.Float64} The new, 16 element array.
    - */
    -goog.vec.Mat4.createFloat64FromValues = function(
    -    v00, v10, v20, v30,
    -    v01, v11, v21, v31,
    -    v02, v12, v22, v32,
    -    v03, v13, v23, v33) {
    -  var newMatrix = goog.vec.Mat4.createFloat64();
    -  goog.vec.Mat4.setFromValues(
    -      newMatrix, v00, v10, v20, v30, v01, v11, v21, v31, v02, v12, v22, v32,
    -      v03, v13, v23, v33);
    -  return newMatrix;
    -};
    -
    -
    -/**
    - * Creates a clone of a 4x4 matrix of Float64.
    - *
    - * @param {goog.vec.Mat4.Float64} matrix The source 4x4 matrix.
    - * @return {!goog.vec.Mat4.Float64} The new 4x4 element matrix.
    - */
    -goog.vec.Mat4.cloneFloat64 = goog.vec.Mat4.createFloat64FromArray;
    -
    -
    -/**
    - * Creates a 4x4 matrix of Float32 initialized from the given array.
    - *
    - * @deprecated Use createFloat32FromArray.
    - * @param {goog.vec.Mat4.Mat4Like} matrix The array containing the
    - *     matrix values in column major order.
    - * @return {!goog.vec.Mat4.Type} The new, nine element array.
    - */
    -goog.vec.Mat4.createFromArray = function(matrix) {
    -  var newMatrix = goog.vec.Mat4.createFloat32();
    -  goog.vec.Mat4.setFromArray(newMatrix, matrix);
    -  return newMatrix;
    -};
    -
    -
    -/**
    - * Creates a 4x4 matrix of Float32 initialized from the given values.
    - *
    - * @deprecated Use createFloat32FromValues.
    - * @param {number} v00 The values at (0, 0).
    - * @param {number} v10 The values at (1, 0).
    - * @param {number} v20 The values at (2, 0).
    - * @param {number} v30 The values at (3, 0).
    - * @param {number} v01 The values at (0, 1).
    - * @param {number} v11 The values at (1, 1).
    - * @param {number} v21 The values at (2, 1).
    - * @param {number} v31 The values at (3, 1).
    - * @param {number} v02 The values at (0, 2).
    - * @param {number} v12 The values at (1, 2).
    - * @param {number} v22 The values at (2, 2).
    - * @param {number} v32 The values at (3, 2).
    - * @param {number} v03 The values at (0, 3).
    - * @param {number} v13 The values at (1, 3).
    - * @param {number} v23 The values at (2, 3).
    - * @param {number} v33 The values at (3, 3).
    - * @return {!goog.vec.Mat4.Type} The new, 16 element array.
    - */
    -goog.vec.Mat4.createFromValues = function(
    -    v00, v10, v20, v30,
    -    v01, v11, v21, v31,
    -    v02, v12, v22, v32,
    -    v03, v13, v23, v33) {
    -  return goog.vec.Mat4.createFloat32FromValues(
    -      v00, v10, v20, v30, v01, v11, v21, v31, v02, v12, v22, v32,
    -      v03, v13, v23, v33);
    -};
    -
    -
    -/**
    - * Creates a clone of a 4x4 matrix of Float32.
    - *
    - * @deprecated Use cloneFloat32.
    - * @param {goog.vec.Mat4.Mat4Like} matrix The source 4x4 matrix.
    - * @return {!goog.vec.Mat4.Type} The new 4x4 element matrix.
    - */
    -goog.vec.Mat4.clone = goog.vec.Mat4.createFromArray;
    -
    -
    -/**
    - * Retrieves the element at the requested row and column.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix containing the
    - *     value to retrieve.
    - * @param {number} row The row index.
    - * @param {number} column The column index.
    - * @return {number} The element value at the requested row, column indices.
    - */
    -goog.vec.Mat4.getElement = function(mat, row, column) {
    -  return mat[row + column * 4];
    -};
    -
    -
    -/**
    - * Sets the element at the requested row and column.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix to set the value on.
    - * @param {number} row The row index.
    - * @param {number} column The column index.
    - * @param {number} value The value to set at the requested row, column.
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat4.setElement = function(mat, row, column, value) {
    -  mat[row + column * 4] = value;
    -  return mat;
    -};
    -
    -
    -/**
    - * Initializes the matrix from the set of values. Note the values supplied are
    - * in column major order.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix to receive the
    - *     values.
    - * @param {number} v00 The values at (0, 0).
    - * @param {number} v10 The values at (1, 0).
    - * @param {number} v20 The values at (2, 0).
    - * @param {number} v30 The values at (3, 0).
    - * @param {number} v01 The values at (0, 1).
    - * @param {number} v11 The values at (1, 1).
    - * @param {number} v21 The values at (2, 1).
    - * @param {number} v31 The values at (3, 1).
    - * @param {number} v02 The values at (0, 2).
    - * @param {number} v12 The values at (1, 2).
    - * @param {number} v22 The values at (2, 2).
    - * @param {number} v32 The values at (3, 2).
    - * @param {number} v03 The values at (0, 3).
    - * @param {number} v13 The values at (1, 3).
    - * @param {number} v23 The values at (2, 3).
    - * @param {number} v33 The values at (3, 3).
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat4.setFromValues = function(
    -    mat, v00, v10, v20, v30, v01, v11, v21, v31, v02, v12, v22, v32,
    -    v03, v13, v23, v33) {
    -  mat[0] = v00;
    -  mat[1] = v10;
    -  mat[2] = v20;
    -  mat[3] = v30;
    -  mat[4] = v01;
    -  mat[5] = v11;
    -  mat[6] = v21;
    -  mat[7] = v31;
    -  mat[8] = v02;
    -  mat[9] = v12;
    -  mat[10] = v22;
    -  mat[11] = v32;
    -  mat[12] = v03;
    -  mat[13] = v13;
    -  mat[14] = v23;
    -  mat[15] = v33;
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the matrix from the array of values stored in column major order.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix to receive the values.
    - * @param {goog.vec.Mat4.AnyType} values The column major ordered
    - *     array of values to store in the matrix.
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat4.setFromArray = function(mat, values) {
    -  mat[0] = values[0];
    -  mat[1] = values[1];
    -  mat[2] = values[2];
    -  mat[3] = values[3];
    -  mat[4] = values[4];
    -  mat[5] = values[5];
    -  mat[6] = values[6];
    -  mat[7] = values[7];
    -  mat[8] = values[8];
    -  mat[9] = values[9];
    -  mat[10] = values[10];
    -  mat[11] = values[11];
    -  mat[12] = values[12];
    -  mat[13] = values[13];
    -  mat[14] = values[14];
    -  mat[15] = values[15];
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the matrix from the array of values stored in row major order.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix to receive the values.
    - * @param {goog.vec.Mat4.AnyType} values The row major ordered array of
    - *     values to store in the matrix.
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat4.setFromRowMajorArray = function(mat, values) {
    -  mat[0] = values[0];
    -  mat[1] = values[4];
    -  mat[2] = values[8];
    -  mat[3] = values[12];
    -
    -  mat[4] = values[1];
    -  mat[5] = values[5];
    -  mat[6] = values[9];
    -  mat[7] = values[13];
    -
    -  mat[8] = values[2];
    -  mat[9] = values[6];
    -  mat[10] = values[10];
    -  mat[11] = values[14];
    -
    -  mat[12] = values[3];
    -  mat[13] = values[7];
    -  mat[14] = values[11];
    -  mat[15] = values[15];
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the diagonal values of the matrix from the given values.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix to receive the values.
    - * @param {number} v00 The values for (0, 0).
    - * @param {number} v11 The values for (1, 1).
    - * @param {number} v22 The values for (2, 2).
    - * @param {number} v33 The values for (3, 3).
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat4.setDiagonalValues = function(mat, v00, v11, v22, v33) {
    -  mat[0] = v00;
    -  mat[5] = v11;
    -  mat[10] = v22;
    -  mat[15] = v33;
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the diagonal values of the matrix from the given vector.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix to receive the values.
    - * @param {goog.vec.Vec4.AnyType} vec The vector containing the values.
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat4.setDiagonal = function(mat, vec) {
    -  mat[0] = vec[0];
    -  mat[5] = vec[1];
    -  mat[10] = vec[2];
    -  mat[15] = vec[3];
    -  return mat;
    -};
    -
    -
    -/**
    - * Gets the diagonal values of the matrix into the given vector.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix containing the values.
    - * @param {goog.vec.Vec4.AnyType} vec The vector to receive the values.
    - * @param {number=} opt_diagonal Which diagonal to get. A value of 0 selects the
    - *     main diagonal, a positive number selects a super diagonal and a negative
    - *     number selects a sub diagonal.
    - * @return {goog.vec.Vec4.AnyType} return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat4.getDiagonal = function(mat, vec, opt_diagonal) {
    -  if (!opt_diagonal) {
    -    // This is the most common case, so we avoid the for loop.
    -    vec[0] = mat[0];
    -    vec[1] = mat[5];
    -    vec[2] = mat[10];
    -    vec[3] = mat[15];
    -  } else {
    -    var offset = opt_diagonal > 0 ? 4 * opt_diagonal : -opt_diagonal;
    -    for (var i = 0; i < 4 - Math.abs(opt_diagonal); i++) {
    -      vec[i] = mat[offset + 5 * i];
    -    }
    -  }
    -  return vec;
    -};
    -
    -
    -/**
    - * Sets the specified column with the supplied values.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix to recieve the values.
    - * @param {number} column The column index to set the values on.
    - * @param {number} v0 The value for row 0.
    - * @param {number} v1 The value for row 1.
    - * @param {number} v2 The value for row 2.
    - * @param {number} v3 The value for row 3.
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat4.setColumnValues = function(mat, column, v0, v1, v2, v3) {
    -  var i = column * 4;
    -  mat[i] = v0;
    -  mat[i + 1] = v1;
    -  mat[i + 2] = v2;
    -  mat[i + 3] = v3;
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the specified column with the value from the supplied vector.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix to receive the values.
    - * @param {number} column The column index to set the values on.
    - * @param {goog.vec.Vec4.AnyType} vec The vector of elements for the column.
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat4.setColumn = function(mat, column, vec) {
    -  var i = column * 4;
    -  mat[i] = vec[0];
    -  mat[i + 1] = vec[1];
    -  mat[i + 2] = vec[2];
    -  mat[i + 3] = vec[3];
    -  return mat;
    -};
    -
    -
    -/**
    - * Retrieves the specified column from the matrix into the given vector.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix supplying the values.
    - * @param {number} column The column to get the values from.
    - * @param {goog.vec.Vec4.AnyType} vec The vector of elements to
    - *     receive the column.
    - * @return {goog.vec.Vec4.AnyType} return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat4.getColumn = function(mat, column, vec) {
    -  var i = column * 4;
    -  vec[0] = mat[i];
    -  vec[1] = mat[i + 1];
    -  vec[2] = mat[i + 2];
    -  vec[3] = mat[i + 3];
    -  return vec;
    -};
    -
    -
    -/**
    - * Sets the columns of the matrix from the given vectors.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix to receive the values.
    - * @param {goog.vec.Vec4.AnyType} vec0 The values for column 0.
    - * @param {goog.vec.Vec4.AnyType} vec1 The values for column 1.
    - * @param {goog.vec.Vec4.AnyType} vec2 The values for column 2.
    - * @param {goog.vec.Vec4.AnyType} vec3 The values for column 3.
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat4.setColumns = function(mat, vec0, vec1, vec2, vec3) {
    -  goog.vec.Mat4.setColumn(mat, 0, vec0);
    -  goog.vec.Mat4.setColumn(mat, 1, vec1);
    -  goog.vec.Mat4.setColumn(mat, 2, vec2);
    -  goog.vec.Mat4.setColumn(mat, 3, vec3);
    -  return mat;
    -};
    -
    -
    -/**
    - * Retrieves the column values from the given matrix into the given vectors.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix supplying the columns.
    - * @param {goog.vec.Vec4.AnyType} vec0 The vector to receive column 0.
    - * @param {goog.vec.Vec4.AnyType} vec1 The vector to receive column 1.
    - * @param {goog.vec.Vec4.AnyType} vec2 The vector to receive column 2.
    - * @param {goog.vec.Vec4.AnyType} vec3 The vector to receive column 3.
    - */
    -goog.vec.Mat4.getColumns = function(mat, vec0, vec1, vec2, vec3) {
    -  goog.vec.Mat4.getColumn(mat, 0, vec0);
    -  goog.vec.Mat4.getColumn(mat, 1, vec1);
    -  goog.vec.Mat4.getColumn(mat, 2, vec2);
    -  goog.vec.Mat4.getColumn(mat, 3, vec3);
    -};
    -
    -
    -/**
    - * Sets the row values from the supplied values.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix to receive the values.
    - * @param {number} row The index of the row to receive the values.
    - * @param {number} v0 The value for column 0.
    - * @param {number} v1 The value for column 1.
    - * @param {number} v2 The value for column 2.
    - * @param {number} v3 The value for column 3.
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat4.setRowValues = function(mat, row, v0, v1, v2, v3) {
    -  mat[row] = v0;
    -  mat[row + 4] = v1;
    -  mat[row + 8] = v2;
    -  mat[row + 12] = v3;
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the row values from the supplied vector.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix to receive the row values.
    - * @param {number} row The index of the row.
    - * @param {goog.vec.Vec4.AnyType} vec The vector containing the values.
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat4.setRow = function(mat, row, vec) {
    -  mat[row] = vec[0];
    -  mat[row + 4] = vec[1];
    -  mat[row + 8] = vec[2];
    -  mat[row + 12] = vec[3];
    -  return mat;
    -};
    -
    -
    -/**
    - * Retrieves the row values into the given vector.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix supplying the values.
    - * @param {number} row The index of the row supplying the values.
    - * @param {goog.vec.Vec4.AnyType} vec The vector to receive the row.
    - * @return {goog.vec.Vec4.AnyType} return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat4.getRow = function(mat, row, vec) {
    -  vec[0] = mat[row];
    -  vec[1] = mat[row + 4];
    -  vec[2] = mat[row + 8];
    -  vec[3] = mat[row + 12];
    -  return vec;
    -};
    -
    -
    -/**
    - * Sets the rows of the matrix from the supplied vectors.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix to receive the values.
    - * @param {goog.vec.Vec4.AnyType} vec0 The values for row 0.
    - * @param {goog.vec.Vec4.AnyType} vec1 The values for row 1.
    - * @param {goog.vec.Vec4.AnyType} vec2 The values for row 2.
    - * @param {goog.vec.Vec4.AnyType} vec3 The values for row 3.
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat4.setRows = function(mat, vec0, vec1, vec2, vec3) {
    -  goog.vec.Mat4.setRow(mat, 0, vec0);
    -  goog.vec.Mat4.setRow(mat, 1, vec1);
    -  goog.vec.Mat4.setRow(mat, 2, vec2);
    -  goog.vec.Mat4.setRow(mat, 3, vec3);
    -  return mat;
    -};
    -
    -
    -/**
    - * Retrieves the rows of the matrix into the supplied vectors.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix to supply the values.
    - * @param {goog.vec.Vec4.AnyType} vec0 The vector to receive row 0.
    - * @param {goog.vec.Vec4.AnyType} vec1 The vector to receive row 1.
    - * @param {goog.vec.Vec4.AnyType} vec2 The vector to receive row 2.
    - * @param {goog.vec.Vec4.AnyType} vec3 The vector to receive row 3.
    - */
    -goog.vec.Mat4.getRows = function(mat, vec0, vec1, vec2, vec3) {
    -  goog.vec.Mat4.getRow(mat, 0, vec0);
    -  goog.vec.Mat4.getRow(mat, 1, vec1);
    -  goog.vec.Mat4.getRow(mat, 2, vec2);
    -  goog.vec.Mat4.getRow(mat, 3, vec3);
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix the zero matrix.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix.
    - * @return {!goog.vec.Mat4.AnyType} return mat so operations can be chained.
    - */
    -goog.vec.Mat4.makeZero = function(mat) {
    -  mat[0] = 0;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 0;
    -  mat[5] = 0;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = 0;
    -  mat[9] = 0;
    -  mat[10] = 0;
    -  mat[11] = 0;
    -  mat[12] = 0;
    -  mat[13] = 0;
    -  mat[14] = 0;
    -  mat[15] = 0;
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix the identity matrix.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix.
    - * @return {goog.vec.Mat4.AnyType} return mat so operations can be chained.
    - */
    -goog.vec.Mat4.makeIdentity = function(mat) {
    -  mat[0] = 1;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 0;
    -  mat[5] = 1;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = 0;
    -  mat[9] = 0;
    -  mat[10] = 1;
    -  mat[11] = 0;
    -  mat[12] = 0;
    -  mat[13] = 0;
    -  mat[14] = 0;
    -  mat[15] = 1;
    -  return mat;
    -};
    -
    -
    -/**
    - * Performs a per-component addition of the matrix mat0 and mat1, storing
    - * the result into resultMat.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat0 The first addend.
    - * @param {goog.vec.Mat4.AnyType} mat1 The second addend.
    - * @param {goog.vec.Mat4.AnyType} resultMat The matrix to
    - *     receive the results (may be either mat0 or mat1).
    - * @return {goog.vec.Mat4.AnyType} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat4.addMat = function(mat0, mat1, resultMat) {
    -  resultMat[0] = mat0[0] + mat1[0];
    -  resultMat[1] = mat0[1] + mat1[1];
    -  resultMat[2] = mat0[2] + mat1[2];
    -  resultMat[3] = mat0[3] + mat1[3];
    -  resultMat[4] = mat0[4] + mat1[4];
    -  resultMat[5] = mat0[5] + mat1[5];
    -  resultMat[6] = mat0[6] + mat1[6];
    -  resultMat[7] = mat0[7] + mat1[7];
    -  resultMat[8] = mat0[8] + mat1[8];
    -  resultMat[9] = mat0[9] + mat1[9];
    -  resultMat[10] = mat0[10] + mat1[10];
    -  resultMat[11] = mat0[11] + mat1[11];
    -  resultMat[12] = mat0[12] + mat1[12];
    -  resultMat[13] = mat0[13] + mat1[13];
    -  resultMat[14] = mat0[14] + mat1[14];
    -  resultMat[15] = mat0[15] + mat1[15];
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Performs a per-component subtraction of the matrix mat0 and mat1,
    - * storing the result into resultMat.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat0 The minuend.
    - * @param {goog.vec.Mat4.AnyType} mat1 The subtrahend.
    - * @param {goog.vec.Mat4.AnyType} resultMat The matrix to receive
    - *     the results (may be either mat0 or mat1).
    - * @return {goog.vec.Mat4.AnyType} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat4.subMat = function(mat0, mat1, resultMat) {
    -  resultMat[0] = mat0[0] - mat1[0];
    -  resultMat[1] = mat0[1] - mat1[1];
    -  resultMat[2] = mat0[2] - mat1[2];
    -  resultMat[3] = mat0[3] - mat1[3];
    -  resultMat[4] = mat0[4] - mat1[4];
    -  resultMat[5] = mat0[5] - mat1[5];
    -  resultMat[6] = mat0[6] - mat1[6];
    -  resultMat[7] = mat0[7] - mat1[7];
    -  resultMat[8] = mat0[8] - mat1[8];
    -  resultMat[9] = mat0[9] - mat1[9];
    -  resultMat[10] = mat0[10] - mat1[10];
    -  resultMat[11] = mat0[11] - mat1[11];
    -  resultMat[12] = mat0[12] - mat1[12];
    -  resultMat[13] = mat0[13] - mat1[13];
    -  resultMat[14] = mat0[14] - mat1[14];
    -  resultMat[15] = mat0[15] - mat1[15];
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Multiplies matrix mat with the given scalar, storing the result
    - * into resultMat.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix.
    - * @param {number} scalar The scalar value to multiply to each element of mat.
    - * @param {goog.vec.Mat4.AnyType} resultMat The matrix to receive
    - *     the results (may be mat).
    - * @return {goog.vec.Mat4.AnyType} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat4.multScalar = function(mat, scalar, resultMat) {
    -  resultMat[0] = mat[0] * scalar;
    -  resultMat[1] = mat[1] * scalar;
    -  resultMat[2] = mat[2] * scalar;
    -  resultMat[3] = mat[3] * scalar;
    -  resultMat[4] = mat[4] * scalar;
    -  resultMat[5] = mat[5] * scalar;
    -  resultMat[6] = mat[6] * scalar;
    -  resultMat[7] = mat[7] * scalar;
    -  resultMat[8] = mat[8] * scalar;
    -  resultMat[9] = mat[9] * scalar;
    -  resultMat[10] = mat[10] * scalar;
    -  resultMat[11] = mat[11] * scalar;
    -  resultMat[12] = mat[12] * scalar;
    -  resultMat[13] = mat[13] * scalar;
    -  resultMat[14] = mat[14] * scalar;
    -  resultMat[15] = mat[15] * scalar;
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Multiplies the two matrices mat0 and mat1 using matrix multiplication,
    - * storing the result into resultMat.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat0 The first (left hand) matrix.
    - * @param {goog.vec.Mat4.AnyType} mat1 The second (right hand) matrix.
    - * @param {goog.vec.Mat4.AnyType} resultMat The matrix to receive
    - *     the results (may be either mat0 or mat1).
    - * @return {goog.vec.Mat4.AnyType} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat4.multMat = function(mat0, mat1, resultMat) {
    -  var a00 = mat0[0], a10 = mat0[1], a20 = mat0[2], a30 = mat0[3];
    -  var a01 = mat0[4], a11 = mat0[5], a21 = mat0[6], a31 = mat0[7];
    -  var a02 = mat0[8], a12 = mat0[9], a22 = mat0[10], a32 = mat0[11];
    -  var a03 = mat0[12], a13 = mat0[13], a23 = mat0[14], a33 = mat0[15];
    -
    -  var b00 = mat1[0], b10 = mat1[1], b20 = mat1[2], b30 = mat1[3];
    -  var b01 = mat1[4], b11 = mat1[5], b21 = mat1[6], b31 = mat1[7];
    -  var b02 = mat1[8], b12 = mat1[9], b22 = mat1[10], b32 = mat1[11];
    -  var b03 = mat1[12], b13 = mat1[13], b23 = mat1[14], b33 = mat1[15];
    -
    -  resultMat[0] = a00 * b00 + a01 * b10 + a02 * b20 + a03 * b30;
    -  resultMat[1] = a10 * b00 + a11 * b10 + a12 * b20 + a13 * b30;
    -  resultMat[2] = a20 * b00 + a21 * b10 + a22 * b20 + a23 * b30;
    -  resultMat[3] = a30 * b00 + a31 * b10 + a32 * b20 + a33 * b30;
    -
    -  resultMat[4] = a00 * b01 + a01 * b11 + a02 * b21 + a03 * b31;
    -  resultMat[5] = a10 * b01 + a11 * b11 + a12 * b21 + a13 * b31;
    -  resultMat[6] = a20 * b01 + a21 * b11 + a22 * b21 + a23 * b31;
    -  resultMat[7] = a30 * b01 + a31 * b11 + a32 * b21 + a33 * b31;
    -
    -  resultMat[8] = a00 * b02 + a01 * b12 + a02 * b22 + a03 * b32;
    -  resultMat[9] = a10 * b02 + a11 * b12 + a12 * b22 + a13 * b32;
    -  resultMat[10] = a20 * b02 + a21 * b12 + a22 * b22 + a23 * b32;
    -  resultMat[11] = a30 * b02 + a31 * b12 + a32 * b22 + a33 * b32;
    -
    -  resultMat[12] = a00 * b03 + a01 * b13 + a02 * b23 + a03 * b33;
    -  resultMat[13] = a10 * b03 + a11 * b13 + a12 * b23 + a13 * b33;
    -  resultMat[14] = a20 * b03 + a21 * b13 + a22 * b23 + a23 * b33;
    -  resultMat[15] = a30 * b03 + a31 * b13 + a32 * b23 + a33 * b33;
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Transposes the given matrix mat storing the result into resultMat.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix to transpose.
    - * @param {goog.vec.Mat4.AnyType} resultMat The matrix to receive
    - *     the results (may be mat).
    - * @return {goog.vec.Mat4.AnyType} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat4.transpose = function(mat, resultMat) {
    -  if (resultMat == mat) {
    -    var a10 = mat[1], a20 = mat[2], a30 = mat[3];
    -    var a21 = mat[6], a31 = mat[7];
    -    var a32 = mat[11];
    -    resultMat[1] = mat[4];
    -    resultMat[2] = mat[8];
    -    resultMat[3] = mat[12];
    -    resultMat[4] = a10;
    -    resultMat[6] = mat[9];
    -    resultMat[7] = mat[13];
    -    resultMat[8] = a20;
    -    resultMat[9] = a21;
    -    resultMat[11] = mat[14];
    -    resultMat[12] = a30;
    -    resultMat[13] = a31;
    -    resultMat[14] = a32;
    -  } else {
    -    resultMat[0] = mat[0];
    -    resultMat[1] = mat[4];
    -    resultMat[2] = mat[8];
    -    resultMat[3] = mat[12];
    -
    -    resultMat[4] = mat[1];
    -    resultMat[5] = mat[5];
    -    resultMat[6] = mat[9];
    -    resultMat[7] = mat[13];
    -
    -    resultMat[8] = mat[2];
    -    resultMat[9] = mat[6];
    -    resultMat[10] = mat[10];
    -    resultMat[11] = mat[14];
    -
    -    resultMat[12] = mat[3];
    -    resultMat[13] = mat[7];
    -    resultMat[14] = mat[11];
    -    resultMat[15] = mat[15];
    -  }
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Computes the determinant of the matrix.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix to compute the matrix for.
    - * @return {number} The determinant of the matrix.
    - */
    -goog.vec.Mat4.determinant = function(mat) {
    -  var m00 = mat[0], m10 = mat[1], m20 = mat[2], m30 = mat[3];
    -  var m01 = mat[4], m11 = mat[5], m21 = mat[6], m31 = mat[7];
    -  var m02 = mat[8], m12 = mat[9], m22 = mat[10], m32 = mat[11];
    -  var m03 = mat[12], m13 = mat[13], m23 = mat[14], m33 = mat[15];
    -
    -  var a0 = m00 * m11 - m10 * m01;
    -  var a1 = m00 * m21 - m20 * m01;
    -  var a2 = m00 * m31 - m30 * m01;
    -  var a3 = m10 * m21 - m20 * m11;
    -  var a4 = m10 * m31 - m30 * m11;
    -  var a5 = m20 * m31 - m30 * m21;
    -  var b0 = m02 * m13 - m12 * m03;
    -  var b1 = m02 * m23 - m22 * m03;
    -  var b2 = m02 * m33 - m32 * m03;
    -  var b3 = m12 * m23 - m22 * m13;
    -  var b4 = m12 * m33 - m32 * m13;
    -  var b5 = m22 * m33 - m32 * m23;
    -
    -  return a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0;
    -};
    -
    -
    -/**
    - * Computes the inverse of mat storing the result into resultMat. If the
    - * inverse is defined, this function returns true, false otherwise.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix to invert.
    - * @param {goog.vec.Mat4.AnyType} resultMat The matrix to receive
    - *     the result (may be mat).
    - * @return {boolean} True if the inverse is defined. If false is returned,
    - *     resultMat is not modified.
    - */
    -goog.vec.Mat4.invert = function(mat, resultMat) {
    -  var m00 = mat[0], m10 = mat[1], m20 = mat[2], m30 = mat[3];
    -  var m01 = mat[4], m11 = mat[5], m21 = mat[6], m31 = mat[7];
    -  var m02 = mat[8], m12 = mat[9], m22 = mat[10], m32 = mat[11];
    -  var m03 = mat[12], m13 = mat[13], m23 = mat[14], m33 = mat[15];
    -
    -  var a0 = m00 * m11 - m10 * m01;
    -  var a1 = m00 * m21 - m20 * m01;
    -  var a2 = m00 * m31 - m30 * m01;
    -  var a3 = m10 * m21 - m20 * m11;
    -  var a4 = m10 * m31 - m30 * m11;
    -  var a5 = m20 * m31 - m30 * m21;
    -  var b0 = m02 * m13 - m12 * m03;
    -  var b1 = m02 * m23 - m22 * m03;
    -  var b2 = m02 * m33 - m32 * m03;
    -  var b3 = m12 * m23 - m22 * m13;
    -  var b4 = m12 * m33 - m32 * m13;
    -  var b5 = m22 * m33 - m32 * m23;
    -
    -  var det = a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0;
    -  if (det == 0) {
    -    return false;
    -  }
    -
    -  var idet = 1.0 / det;
    -  resultMat[0] = (m11 * b5 - m21 * b4 + m31 * b3) * idet;
    -  resultMat[1] = (-m10 * b5 + m20 * b4 - m30 * b3) * idet;
    -  resultMat[2] = (m13 * a5 - m23 * a4 + m33 * a3) * idet;
    -  resultMat[3] = (-m12 * a5 + m22 * a4 - m32 * a3) * idet;
    -  resultMat[4] = (-m01 * b5 + m21 * b2 - m31 * b1) * idet;
    -  resultMat[5] = (m00 * b5 - m20 * b2 + m30 * b1) * idet;
    -  resultMat[6] = (-m03 * a5 + m23 * a2 - m33 * a1) * idet;
    -  resultMat[7] = (m02 * a5 - m22 * a2 + m32 * a1) * idet;
    -  resultMat[8] = (m01 * b4 - m11 * b2 + m31 * b0) * idet;
    -  resultMat[9] = (-m00 * b4 + m10 * b2 - m30 * b0) * idet;
    -  resultMat[10] = (m03 * a4 - m13 * a2 + m33 * a0) * idet;
    -  resultMat[11] = (-m02 * a4 + m12 * a2 - m32 * a0) * idet;
    -  resultMat[12] = (-m01 * b3 + m11 * b1 - m21 * b0) * idet;
    -  resultMat[13] = (m00 * b3 - m10 * b1 + m20 * b0) * idet;
    -  resultMat[14] = (-m03 * a3 + m13 * a1 - m23 * a0) * idet;
    -  resultMat[15] = (m02 * a3 - m12 * a1 + m22 * a0) * idet;
    -  return true;
    -};
    -
    -
    -/**
    - * Returns true if the components of mat0 are equal to the components of mat1.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat0 The first matrix.
    - * @param {goog.vec.Mat4.AnyType} mat1 The second matrix.
    - * @return {boolean} True if the the two matrices are equivalent.
    - */
    -goog.vec.Mat4.equals = function(mat0, mat1) {
    -  return mat0.length == mat1.length &&
    -      mat0[0] == mat1[0] &&
    -      mat0[1] == mat1[1] &&
    -      mat0[2] == mat1[2] &&
    -      mat0[3] == mat1[3] &&
    -      mat0[4] == mat1[4] &&
    -      mat0[5] == mat1[5] &&
    -      mat0[6] == mat1[6] &&
    -      mat0[7] == mat1[7] &&
    -      mat0[8] == mat1[8] &&
    -      mat0[9] == mat1[9] &&
    -      mat0[10] == mat1[10] &&
    -      mat0[11] == mat1[11] &&
    -      mat0[12] == mat1[12] &&
    -      mat0[13] == mat1[13] &&
    -      mat0[14] == mat1[14] &&
    -      mat0[15] == mat1[15];
    -};
    -
    -
    -/**
    - * Transforms the given vector with the given matrix storing the resulting,
    - * transformed vector into resultVec. The input vector is multiplied against the
    - * upper 3x4 matrix omitting the projective component.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix supplying the transformation.
    - * @param {goog.vec.Vec3.AnyType} vec The 3 element vector to transform.
    - * @param {goog.vec.Vec3.AnyType} resultVec The 3 element vector to
    - *     receive the results (may be vec).
    - * @return {goog.vec.Vec3.AnyType} return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat4.multVec3 = function(mat, vec, resultVec) {
    -  var x = vec[0], y = vec[1], z = vec[2];
    -  resultVec[0] = x * mat[0] + y * mat[4] + z * mat[8] + mat[12];
    -  resultVec[1] = x * mat[1] + y * mat[5] + z * mat[9] + mat[13];
    -  resultVec[2] = x * mat[2] + y * mat[6] + z * mat[10] + mat[14];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Transforms the given vector with the given matrix storing the resulting,
    - * transformed vector into resultVec. The input vector is multiplied against the
    - * upper 3x3 matrix omitting the projective component and translation
    - * components.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix supplying the transformation.
    - * @param {goog.vec.Vec3.AnyType} vec The 3 element vector to transform.
    - * @param {goog.vec.Vec3.AnyType} resultVec The 3 element vector to
    - *     receive the results (may be vec).
    - * @return {goog.vec.Vec3.AnyType} return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat4.multVec3NoTranslate = function(mat, vec, resultVec) {
    -  var x = vec[0], y = vec[1], z = vec[2];
    -  resultVec[0] = x * mat[0] + y * mat[4] + z * mat[8];
    -  resultVec[1] = x * mat[1] + y * mat[5] + z * mat[9];
    -  resultVec[2] = x * mat[2] + y * mat[6] + z * mat[10];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Transforms the given vector with the given matrix storing the resulting,
    - * transformed vector into resultVec. The input vector is multiplied against the
    - * full 4x4 matrix with the homogeneous divide applied to reduce the 4 element
    - * vector to a 3 element vector.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix supplying the transformation.
    - * @param {goog.vec.Vec3.AnyType} vec The 3 element vector to transform.
    - * @param {goog.vec.Vec3.AnyType} resultVec The 3 element vector
    - *     to receive the results (may be vec).
    - * @return {goog.vec.Vec3.AnyType} return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat4.multVec3Projective = function(mat, vec, resultVec) {
    -  var x = vec[0], y = vec[1], z = vec[2];
    -  var invw = 1 / (x * mat[3] + y * mat[7] + z * mat[11] + mat[15]);
    -  resultVec[0] = (x * mat[0] + y * mat[4] + z * mat[8] + mat[12]) * invw;
    -  resultVec[1] = (x * mat[1] + y * mat[5] + z * mat[9] + mat[13]) * invw;
    -  resultVec[2] = (x * mat[2] + y * mat[6] + z * mat[10] + mat[14]) * invw;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Transforms the given vector with the given matrix storing the resulting,
    - * transformed vector into resultVec.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix supplying the transformation.
    - * @param {goog.vec.Vec4.AnyType} vec The vector to transform.
    - * @param {goog.vec.Vec4.AnyType} resultVec The vector to
    - *     receive the results (may be vec).
    - * @return {goog.vec.Vec4.AnyType} return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat4.multVec4 = function(mat, vec, resultVec) {
    -  var x = vec[0], y = vec[1], z = vec[2], w = vec[3];
    -  resultVec[0] = x * mat[0] + y * mat[4] + z * mat[8] + w * mat[12];
    -  resultVec[1] = x * mat[1] + y * mat[5] + z * mat[9] + w * mat[13];
    -  resultVec[2] = x * mat[2] + y * mat[6] + z * mat[10] + w * mat[14];
    -  resultVec[3] = x * mat[3] + y * mat[7] + z * mat[11] + w * mat[15];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix a translation matrix with x, y and z
    - * translation factors.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix.
    - * @param {number} x The translation along the x axis.
    - * @param {number} y The translation along the y axis.
    - * @param {number} z The translation along the z axis.
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.Mat4.makeTranslate = function(mat, x, y, z) {
    -  goog.vec.Mat4.makeIdentity(mat);
    -  return goog.vec.Mat4.setColumnValues(mat, 3, x, y, z, 1);
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix as a scale matrix with x, y and z scale factors.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix.
    - * @param {number} x The scale along the x axis.
    - * @param {number} y The scale along the y axis.
    - * @param {number} z The scale along the z axis.
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.Mat4.makeScale = function(mat, x, y, z) {
    -  goog.vec.Mat4.makeIdentity(mat);
    -  return goog.vec.Mat4.setDiagonalValues(mat, x, y, z, 1);
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix a rotation matrix with the given rotation
    - * angle about the axis defined by the vector (ax, ay, az).
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix.
    - * @param {number} angle The rotation angle in radians.
    - * @param {number} ax The x component of the rotation axis.
    - * @param {number} ay The y component of the rotation axis.
    - * @param {number} az The z component of the rotation axis.
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.Mat4.makeRotate = function(mat, angle, ax, ay, az) {
    -  var c = Math.cos(angle);
    -  var d = 1 - c;
    -  var s = Math.sin(angle);
    -
    -  return goog.vec.Mat4.setFromValues(mat,
    -      ax * ax * d + c,
    -      ax * ay * d + az * s,
    -      ax * az * d - ay * s,
    -      0,
    -
    -      ax * ay * d - az * s,
    -      ay * ay * d + c,
    -      ay * az * d + ax * s,
    -      0,
    -
    -      ax * az * d + ay * s,
    -      ay * az * d - ax * s,
    -      az * az * d + c,
    -      0,
    -
    -      0, 0, 0, 1);
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix a rotation matrix with the given rotation
    - * angle about the X axis.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix.
    - * @param {number} angle The rotation angle in radians.
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.Mat4.makeRotateX = function(mat, angle) {
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -  return goog.vec.Mat4.setFromValues(
    -      mat, 1, 0, 0, 0, 0, c, s, 0, 0, -s, c, 0, 0, 0, 0, 1);
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix a rotation matrix with the given rotation
    - * angle about the Y axis.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix.
    - * @param {number} angle The rotation angle in radians.
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.Mat4.makeRotateY = function(mat, angle) {
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -  return goog.vec.Mat4.setFromValues(
    -      mat, c, 0, -s, 0, 0, 1, 0, 0, s, 0, c, 0, 0, 0, 0, 1);
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix a rotation matrix with the given rotation
    - * angle about the Z axis.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix.
    - * @param {number} angle The rotation angle in radians.
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.Mat4.makeRotateZ = function(mat, angle) {
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -  return goog.vec.Mat4.setFromValues(
    -      mat, c, s, 0, 0, -s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix a perspective projection matrix.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix.
    - * @param {number} left The coordinate of the left clipping plane.
    - * @param {number} right The coordinate of the right clipping plane.
    - * @param {number} bottom The coordinate of the bottom clipping plane.
    - * @param {number} top The coordinate of the top clipping plane.
    - * @param {number} near The distance to the near clipping plane.
    - * @param {number} far The distance to the far clipping plane.
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.Mat4.makeFrustum = function(mat, left, right, bottom, top, near, far) {
    -  var x = (2 * near) / (right - left);
    -  var y = (2 * near) / (top - bottom);
    -  var a = (right + left) / (right - left);
    -  var b = (top + bottom) / (top - bottom);
    -  var c = -(far + near) / (far - near);
    -  var d = -(2 * far * near) / (far - near);
    -
    -  return goog.vec.Mat4.setFromValues(mat,
    -      x, 0, 0, 0,
    -      0, y, 0, 0,
    -      a, b, c, -1,
    -      0, 0, d, 0
    -  );
    -};
    -
    -
    -/**
    - * Makse the given 4x4 matrix  perspective projection matrix given a
    - * field of view and aspect ratio.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix.
    - * @param {number} fovy The field of view along the y (vertical) axis in
    - *     radians.
    - * @param {number} aspect The x (width) to y (height) aspect ratio.
    - * @param {number} near The distance to the near clipping plane.
    - * @param {number} far The distance to the far clipping plane.
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.Mat4.makePerspective = function(mat, fovy, aspect, near, far) {
    -  var angle = fovy / 2;
    -  var dz = far - near;
    -  var sinAngle = Math.sin(angle);
    -  if (dz == 0 || sinAngle == 0 || aspect == 0) {
    -    return mat;
    -  }
    -
    -  var cot = Math.cos(angle) / sinAngle;
    -  return goog.vec.Mat4.setFromValues(mat,
    -      cot / aspect, 0, 0, 0,
    -      0, cot, 0, 0,
    -      0, 0, -(far + near) / dz, -1,
    -      0, 0, -(2 * near * far) / dz, 0
    -  );
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix an orthographic projection matrix.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix.
    - * @param {number} left The coordinate of the left clipping plane.
    - * @param {number} right The coordinate of the right clipping plane.
    - * @param {number} bottom The coordinate of the bottom clipping plane.
    - * @param {number} top The coordinate of the top clipping plane.
    - * @param {number} near The distance to the near clipping plane.
    - * @param {number} far The distance to the far clipping plane.
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.Mat4.makeOrtho = function(mat, left, right, bottom, top, near, far) {
    -  var x = 2 / (right - left);
    -  var y = 2 / (top - bottom);
    -  var z = -2 / (far - near);
    -  var a = -(right + left) / (right - left);
    -  var b = -(top + bottom) / (top - bottom);
    -  var c = -(far + near) / (far - near);
    -
    -  return goog.vec.Mat4.setFromValues(mat,
    -      x, 0, 0, 0,
    -      0, y, 0, 0,
    -      0, 0, z, 0,
    -      a, b, c, 1
    -  );
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix a modelview matrix of a camera so that
    - * the camera is 'looking at' the given center point.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix.
    - * @param {goog.vec.Vec3.AnyType} eyePt The position of the eye point
    - *     (camera origin).
    - * @param {goog.vec.Vec3.AnyType} centerPt The point to aim the camera at.
    - * @param {goog.vec.Vec3.AnyType} worldUpVec The vector that identifies
    - *     the up direction for the camera.
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.Mat4.makeLookAt = function(mat, eyePt, centerPt, worldUpVec) {
    -  // Compute the direction vector from the eye point to the center point and
    -  // normalize.
    -  var fwdVec = goog.vec.Mat4.tmpVec4_[0];
    -  goog.vec.Vec3.subtract(centerPt, eyePt, fwdVec);
    -  goog.vec.Vec3.normalize(fwdVec, fwdVec);
    -  fwdVec[3] = 0;
    -
    -  // Compute the side vector from the forward vector and the input up vector.
    -  var sideVec = goog.vec.Mat4.tmpVec4_[1];
    -  goog.vec.Vec3.cross(fwdVec, worldUpVec, sideVec);
    -  goog.vec.Vec3.normalize(sideVec, sideVec);
    -  sideVec[3] = 0;
    -
    -  // Now the up vector to form the orthonormal basis.
    -  var upVec = goog.vec.Mat4.tmpVec4_[2];
    -  goog.vec.Vec3.cross(sideVec, fwdVec, upVec);
    -  goog.vec.Vec3.normalize(upVec, upVec);
    -  upVec[3] = 0;
    -
    -  // Update the view matrix with the new orthonormal basis and position the
    -  // camera at the given eye point.
    -  goog.vec.Vec3.negate(fwdVec, fwdVec);
    -  goog.vec.Mat4.setRow(mat, 0, sideVec);
    -  goog.vec.Mat4.setRow(mat, 1, upVec);
    -  goog.vec.Mat4.setRow(mat, 2, fwdVec);
    -  goog.vec.Mat4.setRowValues(mat, 3, 0, 0, 0, 1);
    -  goog.vec.Mat4.translate(
    -      mat, -eyePt[0], -eyePt[1], -eyePt[2]);
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Decomposes a matrix into the lookAt vectors eyePt, fwdVec and worldUpVec.
    - * The matrix represents the modelview matrix of a camera. It is the inverse
    - * of lookAt except for the output of the fwdVec instead of centerPt.
    - * The centerPt itself cannot be recovered from a modelview matrix.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix.
    - * @param {goog.vec.Vec3.AnyType} eyePt The position of the eye point
    - *     (camera origin).
    - * @param {goog.vec.Vec3.AnyType} fwdVec The vector describing where
    - *     the camera points to.
    - * @param {goog.vec.Vec3.AnyType} worldUpVec The vector that
    - *     identifies the up direction for the camera.
    - * @return {boolean} True if the method succeeds, false otherwise.
    - *     The method can only fail if the inverse of viewMatrix is not defined.
    - */
    -goog.vec.Mat4.toLookAt = function(mat, eyePt, fwdVec, worldUpVec) {
    -  // Get eye of the camera.
    -  var matInverse = goog.vec.Mat4.tmpMat4_[0];
    -  if (!goog.vec.Mat4.invert(mat, matInverse)) {
    -    // The input matrix does not have a valid inverse.
    -    return false;
    -  }
    -
    -  if (eyePt) {
    -    eyePt[0] = matInverse[12];
    -    eyePt[1] = matInverse[13];
    -    eyePt[2] = matInverse[14];
    -  }
    -
    -  // Get forward vector from the definition of lookAt.
    -  if (fwdVec || worldUpVec) {
    -    if (!fwdVec) {
    -      fwdVec = goog.vec.Mat4.tmpVec3_[0];
    -    }
    -    fwdVec[0] = -mat[2];
    -    fwdVec[1] = -mat[6];
    -    fwdVec[2] = -mat[10];
    -    // Normalize forward vector.
    -    goog.vec.Vec3.normalize(fwdVec, fwdVec);
    -  }
    -
    -  if (worldUpVec) {
    -    // Get side vector from the definition of gluLookAt.
    -    var side = goog.vec.Mat4.tmpVec3_[1];
    -    side[0] = mat[0];
    -    side[1] = mat[4];
    -    side[2] = mat[8];
    -    // Compute up vector as a up = side x forward.
    -    goog.vec.Vec3.cross(side, fwdVec, worldUpVec);
    -    // Normalize up vector.
    -    goog.vec.Vec3.normalize(worldUpVec, worldUpVec);
    -  }
    -  return true;
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix a rotation matrix given Euler angles using
    - * the ZXZ convention.
    - * Given the euler angles [theta1, theta2, theta3], the rotation is defined as
    - * rotation = rotation_z(theta1) * rotation_x(theta2) * rotation_z(theta3),
    - * with theta1 in [0, 2 * pi], theta2 in [0, pi] and theta3 in [0, 2 * pi].
    - * rotation_x(theta) means rotation around the X axis of theta radians,
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix.
    - * @param {number} theta1 The angle of rotation around the Z axis in radians.
    - * @param {number} theta2 The angle of rotation around the X axis in radians.
    - * @param {number} theta3 The angle of rotation around the Z axis in radians.
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.Mat4.makeEulerZXZ = function(mat, theta1, theta2, theta3) {
    -  var c1 = Math.cos(theta1);
    -  var s1 = Math.sin(theta1);
    -
    -  var c2 = Math.cos(theta2);
    -  var s2 = Math.sin(theta2);
    -
    -  var c3 = Math.cos(theta3);
    -  var s3 = Math.sin(theta3);
    -
    -  mat[0] = c1 * c3 - c2 * s1 * s3;
    -  mat[1] = c2 * c1 * s3 + c3 * s1;
    -  mat[2] = s3 * s2;
    -  mat[3] = 0;
    -
    -  mat[4] = -c1 * s3 - c3 * c2 * s1;
    -  mat[5] = c1 * c2 * c3 - s1 * s3;
    -  mat[6] = c3 * s2;
    -  mat[7] = 0;
    -
    -  mat[8] = s2 * s1;
    -  mat[9] = -c1 * s2;
    -  mat[10] = c2;
    -  mat[11] = 0;
    -
    -  mat[12] = 0;
    -  mat[13] = 0;
    -  mat[14] = 0;
    -  mat[15] = 1;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Decomposes a rotation matrix into Euler angles using the ZXZ convention so
    - * that rotation = rotation_z(theta1) * rotation_x(theta2) * rotation_z(theta3),
    - * with theta1 in [0, 2 * pi], theta2 in [0, pi] and theta3 in [0, 2 * pi].
    - * rotation_x(theta) means rotation around the X axis of theta radians.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix.
    - * @param {goog.vec.Vec3.AnyType} euler The ZXZ Euler angles in
    - *     radians as [theta1, theta2, theta3].
    - * @param {boolean=} opt_theta2IsNegative Whether theta2 is in [-pi, 0] instead
    - *     of the default [0, pi].
    - * @return {goog.vec.Vec4.AnyType} return euler so that operations can be
    - *     chained together.
    - */
    -goog.vec.Mat4.toEulerZXZ = function(mat, euler, opt_theta2IsNegative) {
    -  // There is an ambiguity in the sign of sinTheta2 because of the sqrt.
    -  var sinTheta2 = Math.sqrt(mat[2] * mat[2] + mat[6] * mat[6]);
    -
    -  // By default we explicitely constrain theta2 to be in [0, pi],
    -  // so sinTheta2 is always positive. We can change the behavior and specify
    -  // theta2 to be negative in [-pi, 0] with opt_Theta2IsNegative.
    -  var signTheta2 = opt_theta2IsNegative ? -1 : 1;
    -
    -  if (sinTheta2 > goog.vec.EPSILON) {
    -    euler[2] = Math.atan2(mat[2] * signTheta2, mat[6] * signTheta2);
    -    euler[1] = Math.atan2(sinTheta2 * signTheta2, mat[10]);
    -    euler[0] = Math.atan2(mat[8] * signTheta2, -mat[9] * signTheta2);
    -  } else {
    -    // There is also an arbitrary choice for theta1 = 0 or theta2 = 0 here.
    -    // We assume theta1 = 0 as some applications do not allow the camera to roll
    -    // (i.e. have theta1 != 0).
    -    euler[0] = 0;
    -    euler[1] = Math.atan2(sinTheta2 * signTheta2, mat[10]);
    -    euler[2] = Math.atan2(mat[1], mat[0]);
    -  }
    -
    -  // Atan2 outputs angles in [-pi, pi] so we bring them back to [0, 2 * pi].
    -  euler[0] = (euler[0] + Math.PI * 2) % (Math.PI * 2);
    -  euler[2] = (euler[2] + Math.PI * 2) % (Math.PI * 2);
    -  // For theta2 we want the angle to be in [0, pi] or [-pi, 0] depending on
    -  // signTheta2.
    -  euler[1] = ((euler[1] * signTheta2 + Math.PI * 2) % (Math.PI * 2)) *
    -      signTheta2;
    -
    -  return euler;
    -};
    -
    -
    -/**
    - * Translates the given matrix by x,y,z.  Equvialent to:
    - * goog.vec.Mat4.multMat(
    - *     mat,
    - *     goog.vec.Mat4.makeTranslate(goog.vec.Mat4.create(), x, y, z),
    - *     mat);
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix.
    - * @param {number} x The translation along the x axis.
    - * @param {number} y The translation along the y axis.
    - * @param {number} z The translation along the z axis.
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.Mat4.translate = function(mat, x, y, z) {
    -  return goog.vec.Mat4.setColumnValues(
    -      mat, 3,
    -      mat[0] * x + mat[4] * y + mat[8] * z + mat[12],
    -      mat[1] * x + mat[5] * y + mat[9] * z + mat[13],
    -      mat[2] * x + mat[6] * y + mat[10] * z + mat[14],
    -      mat[3] * x + mat[7] * y + mat[11] * z + mat[15]);
    -};
    -
    -
    -/**
    - * Scales the given matrix by x,y,z.  Equivalent to:
    - * goog.vec.Mat4.multMat(
    - *     mat,
    - *     goog.vec.Mat4.makeScale(goog.vec.Mat4.create(), x, y, z),
    - *     mat);
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix.
    - * @param {number} x The x scale factor.
    - * @param {number} y The y scale factor.
    - * @param {number} z The z scale factor.
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.Mat4.scale = function(mat, x, y, z) {
    -  return goog.vec.Mat4.setFromValues(
    -      mat,
    -      mat[0] * x, mat[1] * x, mat[2] * x, mat[3] * x,
    -      mat[4] * y, mat[5] * y, mat[6] * y, mat[7] * y,
    -      mat[8] * z, mat[9] * z, mat[10] * z, mat[11] * z,
    -      mat[12], mat[13], mat[14], mat[15]);
    -};
    -
    -
    -/**
    - * Rotate the given matrix by angle about the x,y,z axis.  Equivalent to:
    - * goog.vec.Mat4.multMat(
    - *     mat,
    - *     goog.vec.Mat4.makeRotate(goog.vec.Mat4.create(), angle, x, y, z),
    - *     mat);
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix.
    - * @param {number} angle The angle in radians.
    - * @param {number} x The x component of the rotation axis.
    - * @param {number} y The y component of the rotation axis.
    - * @param {number} z The z component of the rotation axis.
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.Mat4.rotate = function(mat, angle, x, y, z) {
    -  var m00 = mat[0], m10 = mat[1], m20 = mat[2], m30 = mat[3];
    -  var m01 = mat[4], m11 = mat[5], m21 = mat[6], m31 = mat[7];
    -  var m02 = mat[8], m12 = mat[9], m22 = mat[10], m32 = mat[11];
    -  var m03 = mat[12], m13 = mat[13], m23 = mat[14], m33 = mat[15];
    -
    -  var cosAngle = Math.cos(angle);
    -  var sinAngle = Math.sin(angle);
    -  var diffCosAngle = 1 - cosAngle;
    -  var r00 = x * x * diffCosAngle + cosAngle;
    -  var r10 = x * y * diffCosAngle + z * sinAngle;
    -  var r20 = x * z * diffCosAngle - y * sinAngle;
    -
    -  var r01 = x * y * diffCosAngle - z * sinAngle;
    -  var r11 = y * y * diffCosAngle + cosAngle;
    -  var r21 = y * z * diffCosAngle + x * sinAngle;
    -
    -  var r02 = x * z * diffCosAngle + y * sinAngle;
    -  var r12 = y * z * diffCosAngle - x * sinAngle;
    -  var r22 = z * z * diffCosAngle + cosAngle;
    -
    -  return goog.vec.Mat4.setFromValues(
    -      mat,
    -      m00 * r00 + m01 * r10 + m02 * r20,
    -      m10 * r00 + m11 * r10 + m12 * r20,
    -      m20 * r00 + m21 * r10 + m22 * r20,
    -      m30 * r00 + m31 * r10 + m32 * r20,
    -
    -      m00 * r01 + m01 * r11 + m02 * r21,
    -      m10 * r01 + m11 * r11 + m12 * r21,
    -      m20 * r01 + m21 * r11 + m22 * r21,
    -      m30 * r01 + m31 * r11 + m32 * r21,
    -
    -      m00 * r02 + m01 * r12 + m02 * r22,
    -      m10 * r02 + m11 * r12 + m12 * r22,
    -      m20 * r02 + m21 * r12 + m22 * r22,
    -      m30 * r02 + m31 * r12 + m32 * r22,
    -
    -      m03, m13, m23, m33);
    -};
    -
    -
    -/**
    - * Rotate the given matrix by angle about the x axis.  Equivalent to:
    - * goog.vec.Mat4.multMat(
    - *     mat,
    - *     goog.vec.Mat4.makeRotateX(goog.vec.Mat4.create(), angle),
    - *     mat);
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix.
    - * @param {number} angle The angle in radians.
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.Mat4.rotateX = function(mat, angle) {
    -  var m01 = mat[4], m11 = mat[5], m21 = mat[6], m31 = mat[7];
    -  var m02 = mat[8], m12 = mat[9], m22 = mat[10], m32 = mat[11];
    -
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[4] = m01 * c + m02 * s;
    -  mat[5] = m11 * c + m12 * s;
    -  mat[6] = m21 * c + m22 * s;
    -  mat[7] = m31 * c + m32 * s;
    -  mat[8] = m01 * -s + m02 * c;
    -  mat[9] = m11 * -s + m12 * c;
    -  mat[10] = m21 * -s + m22 * c;
    -  mat[11] = m31 * -s + m32 * c;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Rotate the given matrix by angle about the y axis.  Equivalent to:
    - * goog.vec.Mat4.multMat(
    - *     mat,
    - *     goog.vec.Mat4.makeRotateY(goog.vec.Mat4.create(), angle),
    - *     mat);
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix.
    - * @param {number} angle The angle in radians.
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.Mat4.rotateY = function(mat, angle) {
    -  var m00 = mat[0], m10 = mat[1], m20 = mat[2], m30 = mat[3];
    -  var m02 = mat[8], m12 = mat[9], m22 = mat[10], m32 = mat[11];
    -
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[0] = m00 * c + m02 * -s;
    -  mat[1] = m10 * c + m12 * -s;
    -  mat[2] = m20 * c + m22 * -s;
    -  mat[3] = m30 * c + m32 * -s;
    -  mat[8] = m00 * s + m02 * c;
    -  mat[9] = m10 * s + m12 * c;
    -  mat[10] = m20 * s + m22 * c;
    -  mat[11] = m30 * s + m32 * c;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Rotate the given matrix by angle about the z axis.  Equivalent to:
    - * goog.vec.Mat4.multMat(
    - *     mat,
    - *     goog.vec.Mat4.makeRotateZ(goog.vec.Mat4.create(), angle),
    - *     mat);
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The matrix.
    - * @param {number} angle The angle in radians.
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.Mat4.rotateZ = function(mat, angle) {
    -  var m00 = mat[0], m10 = mat[1], m20 = mat[2], m30 = mat[3];
    -  var m01 = mat[4], m11 = mat[5], m21 = mat[6], m31 = mat[7];
    -
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[0] = m00 * c + m01 * s;
    -  mat[1] = m10 * c + m11 * s;
    -  mat[2] = m20 * c + m21 * s;
    -  mat[3] = m30 * c + m31 * s;
    -  mat[4] = m00 * -s + m01 * c;
    -  mat[5] = m10 * -s + m11 * c;
    -  mat[6] = m20 * -s + m21 * c;
    -  mat[7] = m30 * -s + m31 * c;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Retrieves the translation component of the transformation matrix.
    - *
    - * @param {goog.vec.Mat4.AnyType} mat The transformation matrix.
    - * @param {goog.vec.Vec3.AnyType} translation The vector for storing the
    - *     result.
    - * @return {goog.vec.Mat4.AnyType} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.Mat4.getTranslation = function(mat, translation) {
    -  translation[0] = mat[12];
    -  translation[1] = mat[13];
    -  translation[2] = mat[14];
    -  return translation;
    -};
    -
    -
    -/**
    - * @type {!Array<!goog.vec.Vec3.Type>}
    - * @private
    - */
    -goog.vec.Mat4.tmpVec3_ = [
    -  goog.vec.Vec3.createFloat64(),
    -  goog.vec.Vec3.createFloat64()
    -];
    -
    -
    -/**
    - * @type {!Array<!goog.vec.Vec4.Type>}
    - * @private
    - */
    -goog.vec.Mat4.tmpVec4_ = [
    -  goog.vec.Vec4.createFloat64(),
    -  goog.vec.Vec4.createFloat64(),
    -  goog.vec.Vec4.createFloat64()
    -];
    -
    -
    -/**
    - * @type {!Array<!goog.vec.Mat4.Type>}
    - * @private
    - */
    -goog.vec.Mat4.tmpMat4_ = [
    -  goog.vec.Mat4.createFloat64()
    -];
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/mat4_test.html b/src/database/third_party/closure-library/closure/goog/vec/mat4_test.html
    deleted file mode 100644
    index 3f8c6c20244..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/mat4_test.html
    +++ /dev/null
    @@ -1,781 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.vec.Mat4</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.vec.Mat4');
    -  goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -  var randomMat4 = goog.vec.Mat4.createFloat32FromValues(
    -      0.8025078773498535,
    -      0.7559120655059814,
    -      0.15274643898010254,
    -      0.19196106493473053,
    -      0.0890120416879654,
    -      0.15422114729881287,
    -      0.09754583984613419,
    -      0.44862601161003113,
    -      0.9196512699127197,
    -      0.5310639142990112,
    -      0.8962187170982361,
    -      0.280601441860199,
    -      0.594650387763977,
    -      0.4134795069694519,
    -      0.06632178276777267,
    -      0.8837796449661255);
    -
    -  function testDeprecatedConstructor() {
    -    var m0 = goog.vec.Mat4.create();
    -    assertElementsEquals([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], m0);
    -
    -    var m1 = goog.vec.Mat4.createFromArray(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m1);
    -
    -    var m2 = goog.vec.Mat4.clone(m1);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m1);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m2);
    -
    -    var m3 = goog.vec.Mat4.createFromValues(
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m3);
    -
    -    var m4 = goog.vec.Mat4.createIdentity();
    -    assertElementsEquals([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], m4);
    -  }
    -
    -  function testConstructor() {
    -    var m0 = goog.vec.Mat4.createFloat32();
    -    assertElementsEquals([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], m0);
    -
    -    var m1 = goog.vec.Mat4.createFloat32FromArray(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m1);
    -
    -    var m2 = goog.vec.Mat4.clone(m1);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m1);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m2);
    -
    -    var m3 = goog.vec.Mat4.createFloat32FromValues(
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m3);
    -
    -    var m4 = goog.vec.Mat4.createIdentity();
    -    assertElementsEquals([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], m4);
    -  }
    -
    -  function testSet() {
    -    var m0 = goog.vec.Mat4.createFloat32();
    -    var m1 = goog.vec.Mat4.createFloat32FromArray(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
    -    goog.vec.Mat4.setFromArray(m0, m1);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -
    -    goog.vec.Mat4.setFromValues(
    -        m0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17);
    -    assertElementsEquals(
    -        [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17], m0);
    -  }
    -
    -  function testSetDiagonal() {
    -    var m0 = goog.vec.Mat4.createFloat32();
    -    goog.vec.Mat4.setDiagonalValues(m0, 1, 2, 3, 4);
    -    assertElementsEquals(
    -        [1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 4], m0);
    -
    -    goog.vec.Mat4.setDiagonal(m0, [4, 5, 6, 7]);
    -    assertElementsEquals(
    -        [4, 0, 0, 0, 0, 5, 0, 0, 0, 0, 6, 0, 0, 0, 0, 7], m0);
    -  }
    -
    -  function testGetDiagonal() {
    -    var v0 = goog.vec.Vec4.create();
    -    var m0 = goog.vec.Mat4.createFloat32();
    -    goog.vec.Mat4.setFromArray(
    -        m0, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
    -
    -    goog.vec.Mat4.getDiagonal(m0, v0);
    -    assertElementsEquals([0, 5, 10, 15], v0);
    -
    -    goog.vec.Vec4.setFromArray(v0, [0, 0, 0, 0]);
    -    goog.vec.Mat4.getDiagonal(m0, v0, 1);
    -    assertElementsEquals([4, 9, 14, 0], v0);
    -
    -    goog.vec.Vec4.setFromArray(v0, [0, 0, 0, 0]);
    -    goog.vec.Mat4.getDiagonal(m0, v0, 2);
    -    assertElementsEquals([8, 13, 0, 0], v0);
    -
    -    goog.vec.Vec4.setFromArray(v0, [0, 0, 0, 0]);
    -    goog.vec.Mat4.getDiagonal(m0, v0, 3);
    -    assertElementsEquals([12, 0, 0, 0], v0);
    -
    -    goog.vec.Vec4.setFromArray(v0, [0, 0, 0, 0]);
    -    goog.vec.Mat4.getDiagonal(m0, v0, 4);
    -    assertElementsEquals([0, 0, 0, 0], v0);
    -
    -    goog.vec.Vec4.setFromArray(v0, [0, 0, 0, 0]);
    -    goog.vec.Mat4.getDiagonal(m0, v0, -1);
    -    assertElementsEquals([1, 6, 11, 0], v0);
    -
    -    goog.vec.Vec4.setFromArray(v0, [0, 0, 0, 0]);
    -    goog.vec.Mat4.getDiagonal(m0, v0, -2);
    -    assertElementsEquals([2, 7, 0, 0], v0);
    -
    -    goog.vec.Vec4.setFromArray(v0, [0, 0, 0, 0]);
    -    goog.vec.Mat4.getDiagonal(m0, v0, -3);
    -    assertElementsEquals([3, 0, 0, 0], v0);
    -
    -    goog.vec.Vec4.setFromArray(v0, [0, 0, 0, 0]);
    -    goog.vec.Mat4.getDiagonal(m0, v0, -4);
    -    assertElementsEquals([0, 0, 0, 0], v0);
    -  }
    -
    -  function testSetGetColumn() {
    -    var m0 = goog.vec.Mat4.createFloat32();
    -    goog.vec.Mat4.setColumn(m0, 0, [1, 2, 3, 4]);
    -    goog.vec.Mat4.setColumn(m0, 1, [5, 6, 7, 8]);
    -    goog.vec.Mat4.setColumn(m0, 2, [9, 10, 11, 12]);
    -    goog.vec.Mat4.setColumn(m0, 3, [13, 14, 15, 16]);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -
    -    var v0 = [0, 0, 0, 0];
    -    goog.vec.Mat4.getColumn(m0, 0, v0);
    -    assertElementsEquals([1, 2, 3, 4], v0);
    -    goog.vec.Mat4.getColumn(m0, 1, v0);
    -    assertElementsEquals([5, 6, 7, 8], v0);
    -    goog.vec.Mat4.getColumn(m0, 2, v0);
    -    assertElementsEquals([9, 10, 11, 12], v0);
    -    goog.vec.Mat4.getColumn(m0, 3, v0);
    -    assertElementsEquals([13, 14, 15, 16], v0);
    -  }
    -
    -  function testSetGetColumns() {
    -    var m0 = goog.vec.Mat4.createFloat32();
    -    goog.vec.Mat4.setColumns(
    -        m0, [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -
    -    var v0 = [0, 0, 0, 0], v1 = [0, 0, 0, 0];
    -    var v2 = [0, 0, 0, 0], v3 = [0, 0, 0, 0];
    -    goog.vec.Mat4.getColumns(m0, v0, v1, v2, v3);
    -    assertElementsEquals([1, 2, 3, 4], v0);
    -    assertElementsEquals([5, 6, 7, 8], v1);
    -    assertElementsEquals([9, 10, 11, 12], v2);
    -    assertElementsEquals([13, 14, 15, 16], v3);
    -  }
    -
    -  function testSetGetRow() {
    -    var m0 = goog.vec.Mat4.createFloat32();
    -    goog.vec.Mat4.setRow(m0, 0, [1, 2, 3, 4]);
    -    goog.vec.Mat4.setRow(m0, 1, [5, 6, 7, 8]);
    -    goog.vec.Mat4.setRow(m0, 2, [9, 10, 11, 12]);
    -    goog.vec.Mat4.setRow(m0, 3, [13, 14, 15, 16]);
    -    assertElementsEquals(
    -        [1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16], m0);
    -
    -    var v0 = [0, 0, 0, 0];
    -    goog.vec.Mat4.getRow(m0, 0, v0);
    -    assertElementsEquals([1, 2, 3, 4], v0);
    -    goog.vec.Mat4.getRow(m0, 1, v0);
    -    assertElementsEquals([5, 6, 7, 8], v0);
    -    goog.vec.Mat4.getRow(m0, 2, v0);
    -    assertElementsEquals([9, 10, 11, 12], v0);
    -    goog.vec.Mat4.getRow(m0, 3, v0);
    -    assertElementsEquals([13, 14, 15, 16], v0);
    -  }
    -
    -  function testSetGetRows() {
    -    var m0 = goog.vec.Mat4.createFloat32();
    -    goog.vec.Mat4.setRows(
    -        m0, [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]);
    -    assertElementsEquals(
    -        [1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16], m0);
    -
    -    var v0 = [0, 0, 0, 0], v1 = [0, 0, 0, 0];
    -    var v2 = [0, 0, 0, 0], v3 = [0, 0, 0, 0];
    -    goog.vec.Mat4.getRows(m0, v0, v1, v2, v3);
    -    assertElementsEquals([1, 2, 3, 4], v0);
    -    assertElementsEquals([5, 6, 7, 8], v1);
    -    assertElementsEquals([9, 10, 11, 12], v2);
    -    assertElementsEquals([13, 14, 15, 16], v3);
    -  }
    -
    -  function testSetRowMajorArray() {
    -    var m0 = goog.vec.Mat4.createFloat32();
    -    goog.vec.Mat4.setFromRowMajorArray(
    -        m0, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
    -    assertElementsEquals(
    -        [1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16], m0);
    -  }
    -
    -  function testMakeZero() {
    -    var m0 = goog.vec.Mat4.createFloat32FromArray(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -    goog.vec.Mat4.makeZero(m0);
    -    assertElementsEquals(
    -        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], m0);
    -  }
    -
    -  function testMakeIdentity() {
    -    var m0 = goog.vec.Mat4.createFloat32();
    -    goog.vec.Mat4.makeIdentity(m0);
    -    assertElementsEquals(
    -        [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], m0);
    -  }
    -
    -  function testSetGetElement() {
    -    var m0 = goog.vec.Mat4.createFloat32();
    -    for (var r = 0; r < 4; r++) {
    -      for (var c = 0; c < 4; c++) {
    -        var value = c * 4 + r + 1;
    -        goog.vec.Mat4.setElement(m0, r, c, value);
    -        assertEquals(value, goog.vec.Mat4.getElement(m0, r, c));
    -      }
    -    }
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -  }
    -
    -  function testAddMat() {
    -    var m0 = goog.vec.Mat4.createFloat32FromValues(
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var m1 = goog.vec.Mat4.createFloat32FromValues(
    -        9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8);
    -    var m2 = goog.vec.Mat4.createFloat32();
    -    goog.vec.Mat4.addMat(m0, m1, m2);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -    assertElementsEquals(
    -        [9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8], m1);
    -    assertElementsEquals(
    -        [10, 12, 14, 16, 18, 20, 22, 24, 10, 12, 14, 16, 18, 20, 22, 24], m2);
    -
    -    goog.vec.Mat4.addMat(m0, m1, m0);
    -    assertElementsEquals(
    -        [9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8], m1);
    -    assertElementsEquals(
    -        [10, 12, 14, 16, 18, 20, 22, 24, 10, 12, 14, 16, 18, 20, 22, 24], m0);
    -  }
    -
    -  function testSubMat() {
    -    var m0 = goog.vec.Mat4.createFloat32FromValues(
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var m1 = goog.vec.Mat4.createFloat32FromValues(
    -        9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8);
    -    var m2 = goog.vec.Mat4.createFloat32();
    -
    -    goog.vec.Mat4.subMat(m0, m1, m2);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -    assertElementsEquals(
    -        [9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8], m1);
    -    assertElementsEquals(
    -        [-8, -8, -8, -8, -8, -8, -8, -8, 8, 8, 8, 8, 8, 8, 8, 8], m2);
    -
    -    goog.vec.Mat4.subMat(m1, m0, m1);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -    assertElementsEquals(
    -        [8, 8, 8, 8, 8, 8, 8, 8, -8, -8, -8, -8, -8, -8, -8, -8], m1);
    -  }
    -
    -  function testMultScalar() {
    -    var m0 = goog.vec.Mat4.createFloat32FromValues(
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var m1 = goog.vec.Mat4.createFloat32();
    -
    -    goog.vec.Mat4.multScalar(m0, 2, m1);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -    assertElementsEquals(
    -        [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32], m1);
    -
    -    goog.vec.Mat4.multScalar(m0, 5, m0);
    -    assertElementsEquals(
    -        [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80], m0);
    -  }
    -
    -  function testMultMat() {
    -    var m0 = goog.vec.Mat4.createFloat32FromValues(
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var m1 = goog.vec.Mat4.createFloat32FromValues(
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var m2 = goog.vec.Mat4.createFloat32();
    -
    -    goog.vec.Mat4.multMat(m0, m1, m2);
    -    assertElementsEquals(
    -        [90, 100, 110, 120, 202, 228, 254, 280,
    -         314, 356, 398, 440, 426, 484, 542, 600], m2);
    -
    -    goog.vec.Mat4.multScalar(m1, 2, m1);
    -    goog.vec.Mat4.multMat(m1, m0, m1);
    -    assertElementsEquals(
    -        [180, 200, 220, 240, 404, 456, 508, 560,
    -         628, 712, 796, 880, 852, 968, 1084, 1200], m1);
    -  }
    -
    -  function testTranspose() {
    -    var m0 = goog.vec.Mat4.createFloat32FromValues(
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var m1 = goog.vec.Mat4.createFloat32();
    -    goog.vec.Mat4.transpose(m0, m1);
    -    assertElementsEquals(
    -        [1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16], m1);
    -
    -    goog.vec.Mat4.transpose(m1, m1);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m1);
    -  }
    -
    -  function testDeterminant() {
    -    var m0 = goog.vec.Mat4.createFloat32FromValues(
    -        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
    -    assertEquals(0, goog.vec.Mat4.determinant(m0));
    -    assertElementsEquals(
    -        [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], m0);
    -
    -    goog.vec.Mat4.setFromValues(
    -        m0, 1, 2, 3, 4, 2, 3, 4, 1, 3, 4, 1, 2, 4, 1, 2, 3);
    -    assertEquals(160, goog.vec.Mat4.determinant(m0));
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 2, 3, 4, 1, 3, 4, 1, 2, 4, 1, 2, 3], m0);
    -  }
    -
    -  function testInvert() {
    -    var m0 = goog.vec.Mat4.createFloat32FromValues(
    -        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
    -    assertFalse(goog.vec.Mat4.invert(m0, m0));
    -    assertElementsEquals(
    -        [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], m0);
    -
    -    goog.vec.Mat4.setFromValues(
    -        m0, 1, 2, 3, 4, 2, 3, 4, 1, 3, 4, 1, 2, 4, 1, 2, 3);
    -    assertTrue(goog.vec.Mat4.invert(m0, m0));
    -    assertElementsRoughlyEqual(
    -        [-0.225, 0.025, 0.025, 0.275, 0.025, 0.025, 0.275, -0.225,
    -         0.025, 0.275, -0.225, 0.025, 0.275, -0.225, 0.025, 0.025], m0,
    -         goog.vec.EPSILON);
    -
    -    goog.vec.Mat4.makeScale(m0, .01, .01, .01);
    -    assertTrue(goog.vec.Mat4.invert(m0, m0));
    -    var m1 = goog.vec.Mat4.createFloat32();
    -    goog.vec.Mat4.makeScale(m1, 100, 100, 100);
    -    assertElementsEquals(m1, m0);
    -  }
    -
    -  function testEquals() {
    -    var m0 = goog.vec.Mat4.createFloat32FromValues(
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var m1 = goog.vec.Mat4.clone(m0);
    -    assertTrue(goog.vec.Mat4.equals(m0, m1));
    -    assertTrue(goog.vec.Mat4.equals(m1, m0));
    -    for (var i = 0; i < 16; i++) {
    -      m1[i] = 18;
    -      assertFalse(goog.vec.Mat4.equals(m0, m1));
    -      assertFalse(goog.vec.Mat4.equals(m1, m0));
    -      m1[i] = i + 1;
    -    }
    -  }
    -
    -  function testMultVec3() {
    -    var m0 = goog.vec.Mat4.createFloat32FromValues(
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var v0 = [1, 2, 3];
    -    var v1 = [0, 0, 0];
    -
    -    goog.vec.Mat4.multVec3(m0, v0, v1);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals([51, 58, 65], v1);
    -
    -    goog.vec.Mat4.multVec3(m0, v0, v0);
    -    assertElementsEquals([51, 58, 65], v0);
    -  }
    -
    -  function testMultVec3NoTranslate() {
    -    var m0 = goog.vec.Mat4.createFloat32FromValues(
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var v0 = [1, 2, 3];
    -    var v1 = [0, 0, 0];
    -
    -    goog.vec.Mat4.multVec3NoTranslate(m0, v0, v1);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals([38, 44, 50], v1);
    -
    -    goog.vec.Mat4.multVec3NoTranslate(m0, v0, v0);
    -    assertElementsEquals([38, 44, 50], v0);
    -  }
    -
    -  function testMultVec3Projective() {
    -    var m0 = goog.vec.Mat4.createFloat32FromValues(
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var v0 = [1, 2, 3];
    -    var v1 = [0, 0, 0];
    -    var invw = 1 / 72;
    -
    -    goog.vec.Mat4.multVec3Projective(m0, v0, v1);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals(
    -        [51 * invw, 58 * invw, 65 * invw], v1);
    -
    -    goog.vec.Mat4.multVec3Projective(m0, v0, v0);
    -    assertElementsEquals(
    -        [51 * invw, 58 * invw, 65 * invw], v0);
    -  }
    -
    -  function testMultVec4() {
    -    var m0 = goog.vec.Mat4.createFloat32FromValues(
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var v0 = [1, 2, 3, 4];
    -    var v1 = [0, 0, 0, 0];
    -
    -    goog.vec.Mat4.multVec4(m0, v0, v1);
    -    assertElementsEquals([90, 100, 110, 120], v1);
    -    goog.vec.Mat4.multVec4(m0, v0, v0);
    -    assertElementsEquals([90, 100, 110, 120], v0);
    -  }
    -
    -  function testSetValues() {
    -    var a0 = goog.vec.Mat4.createFloat32();
    -    assertElementsEquals(
    -        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], a0);
    -    a0 = goog.vec.Mat4.createFloat32FromArray(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], a0);
    -
    -    var a1 = goog.vec.Mat4.createFloat32();
    -    goog.vec.Mat4.setDiagonalValues(a1, 1, 2, 3, 4);
    -    assertElementsEquals(
    -        [1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 4], a1);
    -
    -    goog.vec.Mat4.setColumnValues(a1, 0, 2, 3, 4, 5);
    -    goog.vec.Mat4.setColumnValues(a1, 1, 6, 7, 8, 9);
    -    goog.vec.Mat4.setColumnValues(a1, 2, 10, 11, 12, 13);
    -    goog.vec.Mat4.setColumnValues(a1, 3, 14, 15, 16, 1);
    -    assertElementsEquals(
    -        [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1], a1);
    -
    -    goog.vec.Mat4.setRowValues(a1, 0, 1, 5, 9, 13);
    -    goog.vec.Mat4.setRowValues(a1, 1, 2, 6, 10, 14);
    -    goog.vec.Mat4.setRowValues(a1, 2, 3, 7, 11, 15);
    -    goog.vec.Mat4.setRowValues(a1, 3, 4, 8, 12, 16);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], a1);
    -  }
    -
    -  function testMakeTranslate() {
    -    var m0 = goog.vec.Mat4.createFloat32();
    -    goog.vec.Mat4.makeTranslate(m0, 3, 4, 5);
    -    assertElementsEquals(
    -        [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 3, 4, 5, 1], m0);
    -  }
    -
    -  function testMakeScale() {
    -    var m0 = goog.vec.Mat4.createFloat32();
    -    goog.vec.Mat4.makeScale(m0, 3, 4, 5);
    -    assertElementsEquals(
    -        [3, 0, 0, 0, 0, 4, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1], m0);
    -  }
    -
    -  function testMakeRotate() {
    -    var m0 = goog.vec.Mat4.createFloat32();
    -    goog.vec.Mat4.makeRotate(m0, Math.PI / 2, 0, 0, 1);
    -    assertElementsRoughlyEqual(
    -        [0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
    -        m0, goog.vec.EPSILON);
    -
    -    var m1 = goog.vec.Mat4.createFloat32();
    -    goog.vec.Mat4.makeRotate(m1, -Math.PI / 4, 0, 0, 1);
    -    goog.vec.Mat4.multMat(m0, m1, m1);
    -    assertElementsRoughlyEqual(
    -        [0.7071068, 0.7071068, 0, 0,
    -         -0.7071068, 0.7071068, 0, 0,
    -         0, 0, 1, 0,
    -         0, 0, 0, 1],
    -        m1, goog.vec.EPSILON);
    -  }
    -
    -  function testMakeRotateX() {
    -    var m0 = goog.vec.Mat4.createFloat32();
    -    var m1 = goog.vec.Mat4.createFloat32()
    -
    -    goog.vec.Mat4.makeRotateX(m0, Math.PI / 7);
    -    goog.vec.Mat4.makeRotate(m1, Math.PI / 7, 1, 0, 0);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testMakeRotateY() {
    -    var m0 = goog.vec.Mat4.createFloat32();
    -    var m1 = goog.vec.Mat4.createFloat32()
    -
    -    goog.vec.Mat4.makeRotateY(m0, Math.PI / 7);
    -    goog.vec.Mat4.makeRotate(m1, Math.PI / 7, 0, 1, 0);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testMakeRotateZ() {
    -    var m0 = goog.vec.Mat4.createFloat32();
    -    var m1 = goog.vec.Mat4.createFloat32()
    -
    -    goog.vec.Mat4.makeRotateZ(m0, Math.PI / 7);
    -    goog.vec.Mat4.makeRotate(m1, Math.PI / 7, 0, 0, 1);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -
    -  function testTranslate() {
    -    var m0 = goog.vec.Mat4.createIdentity();
    -    goog.vec.Mat4.translate(m0, 3, 4, 5);
    -    assertElementsEquals(
    -        [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 3, 4, 5, 1], m0);
    -
    -    goog.vec.Mat4.setFromValues(
    -        m0, 1, 2, 3, 4, 2, 3, 4, 1, 3, 4, 1, 2, 4, 1, 2, 3);
    -
    -    var m1 = goog.vec.Mat4.createFloat32();
    -    goog.vec.Mat4.makeTranslate(m1, 5, 6, 7);
    -    var m2 = goog.vec.Mat4.createFloat32();
    -    goog.vec.Mat4.multMat(m0, m1, m2);
    -    goog.vec.Mat4.translate(m0, 5, 6, 7);
    -    assertElementsEquals(m2, m0);
    -  }
    -
    -  function testScale() {
    -    var m0 = goog.vec.Mat4.createIdentity();
    -    goog.vec.Mat4.scale(m0, 3, 4, 5);
    -    assertElementsEquals([3, 0, 0, 0, 0, 4, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1], m0);
    -  }
    -
    -  function testRotate() {
    -    var m0 = goog.vec.Mat4.createIdentity();
    -    goog.vec.Mat4.rotate(m0, Math.PI / 2, 0, 0, 1);
    -    assertElementsRoughlyEqual(
    -        [0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
    -        m0, goog.vec.EPSILON);
    -
    -    goog.vec.Mat4.rotate(m0, -Math.PI / 4, 0, 0, 1);
    -    assertElementsRoughlyEqual(
    -        [0.7071068, 0.7071068, 0, 0,
    -         -0.7071068, 0.7071068, 0, 0,
    -         0, 0, 1, 0,
    -         0, 0, 0, 1],
    -        m0, goog.vec.EPSILON);
    -  }
    -
    -  function testRotateX() {
    -    var m0 = goog.vec.Mat4.createFloat32();
    -    var m1 = goog.vec.Mat4.createFloat32FromArray(randomMat4)
    -
    -    goog.vec.Mat4.makeRotateX(m0, Math.PI / 7);
    -    goog.vec.Mat4.multMat(m1, m0, m0);
    -    goog.vec.Mat4.rotateX(m1, Math.PI / 7);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testRotateY() {
    -    var m0 = goog.vec.Mat4.createFloat32();
    -    var m1 = goog.vec.Mat4.createFloat32FromArray(randomMat4)
    -
    -    goog.vec.Mat4.makeRotateY(m0, Math.PI / 7);
    -    goog.vec.Mat4.multMat(m1, m0, m0);
    -    goog.vec.Mat4.rotateY(m1, Math.PI / 7);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testRotateZ() {
    -    var m0 = goog.vec.Mat4.createFloat32();
    -    var m1 = goog.vec.Mat4.createFloat32FromArray(randomMat4)
    -
    -    goog.vec.Mat4.makeRotateZ(m0, Math.PI / 7);
    -    goog.vec.Mat4.multMat(m1, m0, m0);
    -    goog.vec.Mat4.rotateZ(m1, Math.PI / 7);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testGetTranslation() {
    -    var mat = goog.vec.Mat4.createFloat32FromArray(randomMat4);
    -    var translation = goog.vec.Vec3.createFloat32();
    -    goog.vec.Mat4.getTranslation(mat, translation);
    -    assertElementsRoughlyEqual(
    -        [0.59465038776, 0.413479506969, 0.0663217827677],
    -        translation, goog.vec.EPSILON);
    -  }
    -
    -  function testMakeFrustum() {
    -    var m0 = goog.vec.Mat4.createFloat32();
    -    goog.vec.Mat4.makeFrustum(m0, -1, 2, -2, 1, .1, 1.1);
    -    assertElementsRoughlyEqual(
    -        [0.06666666, 0, 0, 0,
    -         0, 0.06666666, 0, 0,
    -         0.33333333, -0.33333333, -1.2, -1,
    -         0, 0, -0.22, 0], m0, goog.vec.EPSILON);
    -  }
    -
    -  function testMakePerspective() {
    -    var m0 = goog.vec.Mat4.createFloat32();
    -    goog.vec.Mat4.makePerspective(m0, 90 * Math.PI / 180, 2, 0.1, 1.1);
    -    assertElementsRoughlyEqual(
    -        [0.5, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1.2, -1, 0, 0, -0.22, 0],
    -        m0, goog.vec.EPSILON);
    -  }
    -
    -  function testMakeOrtho() {
    -    var m0 = goog.vec.Mat4.createFloat32();
    -    goog.vec.Mat4.makeOrtho(m0, -1, 2, -2, 1, 0.1, 1.1);
    -    assertElementsRoughlyEqual(
    -        [0.6666666, 0, 0, 0,
    -         0, 0.6666666, 0, 0,
    -         0, 0, -2, 0,
    -         -0.333333, 0.3333333, -1.2, 1], m0, goog.vec.EPSILON);
    -
    -  }
    -
    -  function testMakeEulerZXZ() {
    -    var m0 = goog.vec.Mat4.createFloat32();
    -    var roll = 0.200982 * 2 * Math.PI;
    -    var tilt = 0.915833 * Math.PI;
    -    var yaw = 0.839392 * 2 * Math.PI;
    -
    -    goog.vec.Mat4.makeRotate(m0, roll, 0, 0, 1);
    -    goog.vec.Mat4.rotate(m0, tilt, 1, 0, 0);
    -    goog.vec.Mat4.rotate(m0, yaw, 0, 0, 1);
    -
    -    var m1 = goog.vec.Mat4.createFloat32();
    -    goog.vec.Mat4.makeEulerZXZ(m1, roll, tilt, yaw);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -
    -
    -    var euler = [0, 0, 0];
    -    goog.vec.Mat4.toEulerZXZ(m0, euler);
    -
    -    assertRoughlyEquals(roll, euler[0], goog.vec.EPSILON);
    -    assertRoughlyEquals(tilt, euler[1], goog.vec.EPSILON);
    -    assertRoughlyEquals(yaw, euler[2], goog.vec.EPSILON);
    -
    -    // Test negative tilt now.
    -    goog.vec.Mat4.makeRotate(m0, roll, 0, 0, 1);
    -    goog.vec.Mat4.rotate(m0, -tilt, 1, 0, 0);
    -    goog.vec.Mat4.rotate(m0, yaw, 0, 0, 1);
    -
    -    goog.vec.Mat4.makeEulerZXZ(m1, roll, -tilt, yaw);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -
    -    var euler = [0, 0, 0];
    -    goog.vec.Mat4.toEulerZXZ(m0, euler, true);
    -
    -    assertRoughlyEquals(roll, euler[0], goog.vec.EPSILON);
    -    assertRoughlyEquals(-tilt, euler[1], goog.vec.EPSILON);
    -    assertRoughlyEquals(yaw, euler[2], goog.vec.EPSILON);
    -  }
    -
    -  function testEulerZXZExtrema() {
    -    var m0 = goog.vec.Mat4.createFloat32FromArray(
    -    [1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1]);
    -    var m1 = goog.vec.Mat4.createFloat32FromArray(
    -    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
    -
    -    var euler = [0, 0, 0];
    -    goog.vec.Mat4.toEulerZXZ(m0, euler);
    -    assertElementsRoughlyEqual(
    -        [Math.PI, Math.PI / 2, Math.PI], euler, goog.vec.EPSILON);
    -    goog.vec.Mat4.makeEulerZXZ(m1, euler[0], euler[1], euler[2]);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testLookAt() {
    -    var viewMatrix = goog.vec.Mat4.createFloat32();
    -    goog.vec.Mat4.makeLookAt(
    -      viewMatrix, [0, 0, 0], [1, 0, 0], [0, 1, 0]);
    -    assertElementsRoughlyEqual(
    -      [0, 0, -1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1], viewMatrix,
    -      goog.vec.EPSILON);
    -  }
    -
    -  function testToLookAt() {
    -    // This test does not use the default precision goog.vec.EPSILON due to
    -    // precision issues in some browsers leading to flaky tests.
    -    var EPSILON = 1e-4;
    -
    -    var eyeExp = [0, 0, 0];
    -    var fwdExp = [1, 0, 0];
    -    var upExp = [0, 1, 0];
    -
    -    var centerExp = [0, 0, 0];
    -    goog.vec.Vec3.add(eyeExp, fwdExp, centerExp);
    -
    -    var view = goog.vec.Mat4.createFloat32();
    -    goog.vec.Mat4.makeLookAt(view, eyeExp, centerExp, upExp);
    -
    -    var eyeRes = [0, 0, 0];
    -    var fwdRes = [0, 0, 0];
    -    var upRes = [0, 0, 0];
    -    goog.vec.Mat4.toLookAt(view, eyeRes, fwdRes, upRes);
    -    assertElementsRoughlyEqual(eyeExp, eyeRes, EPSILON);
    -    assertElementsRoughlyEqual(fwdExp, fwdRes, EPSILON);
    -    assertElementsRoughlyEqual(upExp, upRes, EPSILON);
    -  }
    -
    -  function testLookAtDecomposition() {
    -    // This test does not use the default precision goog.vec.EPSILON due to
    -    // precision issues in some browsers leading to flaky tests.
    -    var EPSILON = 1e-4;
    -
    -    var viewExp = goog.vec.Mat4.createFloat32();
    -    var viewRes = goog.vec.Mat4.createFloat32();
    -
    -    // Get a valid set of random vectors eye, forward, up by decomposing
    -    // a random matrix into a set of lookAt vectors.
    -    var tmp = goog.vec.Mat4.createFloat32FromArray(randomMat4);
    -    var eyeExp = [0, 0, 0];
    -    var fwdExp = [0, 0, 0];
    -    var upExp = [0, 0, 0];
    -    var centerExp = [0, 0, 0];
    -    // Project the random matrix into a real modelview matrix.
    -    goog.vec.Mat4.toLookAt(tmp, eyeExp, fwdExp, upExp);
    -    goog.vec.Vec3.add(eyeExp, fwdExp, centerExp);
    -
    -    // Compute the expected modelview matrix from a set of valid random vectors.
    -    goog.vec.Mat4.makeLookAt(viewExp, eyeExp, centerExp, upExp);
    -
    -    var eyeRes = [0, 0, 0];
    -    var fwdRes = [0, 0, 0];
    -    var upRes = [0, 0, 0];
    -    var centerRes = [0, 0, 0];
    -    goog.vec.Mat4.toLookAt(viewExp, eyeRes, fwdRes, upRes);
    -    goog.vec.Vec3.add(eyeRes, fwdRes, centerRes);
    -
    -    goog.vec.Mat4.makeLookAt(viewRes, eyeRes, centerRes, upRes);
    -
    -    assertElementsRoughlyEqual(eyeExp, eyeRes, EPSILON);
    -    assertElementsRoughlyEqual(fwdExp, fwdRes, EPSILON);
    -    assertElementsRoughlyEqual(upExp, upRes, EPSILON);
    -    assertElementsRoughlyEqual(viewExp, viewRes, EPSILON);
    -  }
    -
    -</script>
    -</body>
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/mat4d.js b/src/database/third_party/closure-library/closure/goog/vec/mat4d.js
    deleted file mode 100644
    index ad0a83171c5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/mat4d.js
    +++ /dev/null
    @@ -1,1769 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -//                                                                           //
    -// Any edits to this file must be applied to mat4f.js by running:            //
    -//   swap_type.sh mat4d.js > mat4f.js                                        //
    -//                                                                           //
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -
    -
    -/**
    - * @fileoverview Provides functions for operating on 4x4 double (64bit)
    - * matrices.  The matrices are stored in column-major order.
    - *
    - * The last parameter will typically be the output matrix and an
    - * object can be both an input and output parameter to all methods except
    - * where noted.
    - *
    - * See the README for notes about the design and structure of the API
    - * (especially related to performance).
    - *
    - */
    -goog.provide('goog.vec.mat4d');
    -goog.provide('goog.vec.mat4d.Type');
    -
    -goog.require('goog.vec');
    -goog.require('goog.vec.vec3d');
    -goog.require('goog.vec.vec4d');
    -
    -
    -/** @typedef {goog.vec.Float64} */ goog.vec.mat4d.Type;
    -
    -
    -/**
    - * Creates a mat4d with all elements initialized to zero.
    - *
    - * @return {!goog.vec.mat4d.Type} The new mat4d.
    - */
    -goog.vec.mat4d.create = function() {
    -  return new Float64Array(16);
    -};
    -
    -
    -/**
    - * Initializes the matrix from the set of values. Note the values supplied are
    - * in column major order.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix to receive the
    - *     values.
    - * @param {number} v00 The values at (0, 0).
    - * @param {number} v10 The values at (1, 0).
    - * @param {number} v20 The values at (2, 0).
    - * @param {number} v30 The values at (3, 0).
    - * @param {number} v01 The values at (0, 1).
    - * @param {number} v11 The values at (1, 1).
    - * @param {number} v21 The values at (2, 1).
    - * @param {number} v31 The values at (3, 1).
    - * @param {number} v02 The values at (0, 2).
    - * @param {number} v12 The values at (1, 2).
    - * @param {number} v22 The values at (2, 2).
    - * @param {number} v32 The values at (3, 2).
    - * @param {number} v03 The values at (0, 3).
    - * @param {number} v13 The values at (1, 3).
    - * @param {number} v23 The values at (2, 3).
    - * @param {number} v33 The values at (3, 3).
    - * @return {!goog.vec.mat4d.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4d.setFromValues = function(
    -    mat, v00, v10, v20, v30, v01, v11, v21, v31, v02, v12, v22, v32,
    -    v03, v13, v23, v33) {
    -  mat[0] = v00;
    -  mat[1] = v10;
    -  mat[2] = v20;
    -  mat[3] = v30;
    -  mat[4] = v01;
    -  mat[5] = v11;
    -  mat[6] = v21;
    -  mat[7] = v31;
    -  mat[8] = v02;
    -  mat[9] = v12;
    -  mat[10] = v22;
    -  mat[11] = v32;
    -  mat[12] = v03;
    -  mat[13] = v13;
    -  mat[14] = v23;
    -  mat[15] = v33;
    -  return mat;
    -};
    -
    -
    -/**
    - * Initializes mat4d mat from mat4d src.
    - *
    - * @param {goog.vec.mat4d.Type} mat The destination matrix.
    - * @param {goog.vec.mat4d.Type} src The source matrix.
    - * @return {!goog.vec.mat4d.Type} Return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4d.setFromMat4d = function(mat, src) {
    -  mat[0] = src[0];
    -  mat[1] = src[1];
    -  mat[2] = src[2];
    -  mat[3] = src[3];
    -  mat[4] = src[4];
    -  mat[5] = src[5];
    -  mat[6] = src[6];
    -  mat[7] = src[7];
    -  mat[8] = src[8];
    -  mat[9] = src[9];
    -  mat[10] = src[10];
    -  mat[11] = src[11];
    -  mat[12] = src[12];
    -  mat[13] = src[13];
    -  mat[14] = src[14];
    -  mat[15] = src[15];
    -  return mat;
    -};
    -
    -
    -/**
    - * Initializes mat4d mat from mat4f src (typed as a Float32Array to
    - * avoid circular goog.requires).
    - *
    - * @param {goog.vec.mat4d.Type} mat The destination matrix.
    - * @param {Float32Array} src The source matrix.
    - * @return {!goog.vec.mat4d.Type} Return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4d.setFromMat4f = function(mat, src) {
    -  mat[0] = src[0];
    -  mat[1] = src[1];
    -  mat[2] = src[2];
    -  mat[3] = src[3];
    -  mat[4] = src[4];
    -  mat[5] = src[5];
    -  mat[6] = src[6];
    -  mat[7] = src[7];
    -  mat[8] = src[8];
    -  mat[9] = src[9];
    -  mat[10] = src[10];
    -  mat[11] = src[11];
    -  mat[12] = src[12];
    -  mat[13] = src[13];
    -  mat[14] = src[14];
    -  mat[15] = src[15];
    -  return mat;
    -};
    -
    -
    -/**
    - * Initializes mat4d mat from Array src.
    - *
    - * @param {goog.vec.mat4d.Type} mat The destination matrix.
    - * @param {Array<number>} src The source matrix.
    - * @return {!goog.vec.mat4d.Type} Return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4d.setFromArray = function(mat, src) {
    -  mat[0] = src[0];
    -  mat[1] = src[1];
    -  mat[2] = src[2];
    -  mat[3] = src[3];
    -  mat[4] = src[4];
    -  mat[5] = src[5];
    -  mat[6] = src[6];
    -  mat[7] = src[7];
    -  mat[8] = src[8];
    -  mat[9] = src[9];
    -  mat[10] = src[10];
    -  mat[11] = src[11];
    -  mat[12] = src[12];
    -  mat[13] = src[13];
    -  mat[14] = src[14];
    -  mat[15] = src[15];
    -  return mat;
    -};
    -
    -
    -/**
    - * Retrieves the element at the requested row and column.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix containing the value to
    - *     retrieve.
    - * @param {number} row The row index.
    - * @param {number} column The column index.
    - * @return {number} The element value at the requested row, column indices.
    - */
    -goog.vec.mat4d.getElement = function(mat, row, column) {
    -  return mat[row + column * 4];
    -};
    -
    -
    -/**
    - * Sets the element at the requested row and column.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix containing the value to
    - *     retrieve.
    - * @param {number} row The row index.
    - * @param {number} column The column index.
    - * @param {number} value The value to set at the requested row, column.
    - * @return {!goog.vec.mat4d.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4d.setElement = function(mat, row, column, value) {
    -  mat[row + column * 4] = value;
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the diagonal values of the matrix from the given values.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix to receive the values.
    - * @param {number} v00 The values for (0, 0).
    - * @param {number} v11 The values for (1, 1).
    - * @param {number} v22 The values for (2, 2).
    - * @param {number} v33 The values for (3, 3).
    - * @return {!goog.vec.mat4d.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4d.setDiagonalValues = function(mat, v00, v11, v22, v33) {
    -  mat[0] = v00;
    -  mat[5] = v11;
    -  mat[10] = v22;
    -  mat[15] = v33;
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the diagonal values of the matrix from the given vector.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix to receive the values.
    - * @param {goog.vec.vec4d.Type} vec The vector containing the values.
    - * @return {!goog.vec.mat4d.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4d.setDiagonal = function(mat, vec) {
    -  mat[0] = vec[0];
    -  mat[5] = vec[1];
    -  mat[10] = vec[2];
    -  mat[15] = vec[3];
    -  return mat;
    -};
    -
    -
    -/**
    - * Gets the diagonal values of the matrix into the given vector.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix containing the values.
    - * @param {goog.vec.vec4d.Type} vec The vector to receive the values.
    - * @param {number=} opt_diagonal Which diagonal to get. A value of 0 selects the
    - *     main diagonal, a positive number selects a super diagonal and a negative
    - *     number selects a sub diagonal.
    - * @return {goog.vec.vec4d.Type} return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4d.getDiagonal = function(mat, vec, opt_diagonal) {
    -  if (!opt_diagonal) {
    -    // This is the most common case, so we avoid the for loop.
    -    vec[0] = mat[0];
    -    vec[1] = mat[5];
    -    vec[2] = mat[10];
    -    vec[3] = mat[15];
    -  } else {
    -    var offset = opt_diagonal > 0 ? 4 * opt_diagonal : -opt_diagonal;
    -    for (var i = 0; i < 4 - Math.abs(opt_diagonal); i++) {
    -      vec[i] = mat[offset + 5 * i];
    -    }
    -  }
    -  return vec;
    -};
    -
    -
    -/**
    - * Sets the specified column with the supplied values.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix to recieve the values.
    - * @param {number} column The column index to set the values on.
    - * @param {number} v0 The value for row 0.
    - * @param {number} v1 The value for row 1.
    - * @param {number} v2 The value for row 2.
    - * @param {number} v3 The value for row 3.
    - * @return {!goog.vec.mat4d.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4d.setColumnValues = function(mat, column, v0, v1, v2, v3) {
    -  var i = column * 4;
    -  mat[i] = v0;
    -  mat[i + 1] = v1;
    -  mat[i + 2] = v2;
    -  mat[i + 3] = v3;
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the specified column with the value from the supplied vector.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix to receive the values.
    - * @param {number} column The column index to set the values on.
    - * @param {goog.vec.vec4d.Type} vec The vector of elements for the column.
    - * @return {!goog.vec.mat4d.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4d.setColumn = function(mat, column, vec) {
    -  var i = column * 4;
    -  mat[i] = vec[0];
    -  mat[i + 1] = vec[1];
    -  mat[i + 2] = vec[2];
    -  mat[i + 3] = vec[3];
    -  return mat;
    -};
    -
    -
    -/**
    - * Retrieves the specified column from the matrix into the given vector.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix supplying the values.
    - * @param {number} column The column to get the values from.
    - * @param {goog.vec.vec4d.Type} vec The vector of elements to
    - *     receive the column.
    - * @return {!goog.vec.vec4d.Type} return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4d.getColumn = function(mat, column, vec) {
    -  var i = column * 4;
    -  vec[0] = mat[i];
    -  vec[1] = mat[i + 1];
    -  vec[2] = mat[i + 2];
    -  vec[3] = mat[i + 3];
    -  return vec;
    -};
    -
    -
    -/**
    - * Sets the columns of the matrix from the given vectors.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix to receive the values.
    - * @param {goog.vec.vec4d.Type} vec0 The values for column 0.
    - * @param {goog.vec.vec4d.Type} vec1 The values for column 1.
    - * @param {goog.vec.vec4d.Type} vec2 The values for column 2.
    - * @param {goog.vec.vec4d.Type} vec3 The values for column 3.
    - * @return {!goog.vec.mat4d.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4d.setColumns = function(mat, vec0, vec1, vec2, vec3) {
    -  mat[0] = vec0[0];
    -  mat[1] = vec0[1];
    -  mat[2] = vec0[2];
    -  mat[3] = vec0[3];
    -  mat[4] = vec1[0];
    -  mat[5] = vec1[1];
    -  mat[6] = vec1[2];
    -  mat[7] = vec1[3];
    -  mat[8] = vec2[0];
    -  mat[9] = vec2[1];
    -  mat[10] = vec2[2];
    -  mat[11] = vec2[3];
    -  mat[12] = vec3[0];
    -  mat[13] = vec3[1];
    -  mat[14] = vec3[2];
    -  mat[15] = vec3[3];
    -  return mat;
    -};
    -
    -
    -/**
    - * Retrieves the column values from the given matrix into the given vectors.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix supplying the columns.
    - * @param {goog.vec.vec4d.Type} vec0 The vector to receive column 0.
    - * @param {goog.vec.vec4d.Type} vec1 The vector to receive column 1.
    - * @param {goog.vec.vec4d.Type} vec2 The vector to receive column 2.
    - * @param {goog.vec.vec4d.Type} vec3 The vector to receive column 3.
    - */
    -goog.vec.mat4d.getColumns = function(mat, vec0, vec1, vec2, vec3) {
    -  vec0[0] = mat[0];
    -  vec0[1] = mat[1];
    -  vec0[2] = mat[2];
    -  vec0[3] = mat[3];
    -  vec1[0] = mat[4];
    -  vec1[1] = mat[5];
    -  vec1[2] = mat[6];
    -  vec1[3] = mat[7];
    -  vec2[0] = mat[8];
    -  vec2[1] = mat[9];
    -  vec2[2] = mat[10];
    -  vec2[3] = mat[11];
    -  vec3[0] = mat[12];
    -  vec3[1] = mat[13];
    -  vec3[2] = mat[14];
    -  vec3[3] = mat[15];
    -};
    -
    -
    -/**
    - * Sets the row values from the supplied values.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix to receive the values.
    - * @param {number} row The index of the row to receive the values.
    - * @param {number} v0 The value for column 0.
    - * @param {number} v1 The value for column 1.
    - * @param {number} v2 The value for column 2.
    - * @param {number} v3 The value for column 3.
    - * @return {!goog.vec.mat4d.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4d.setRowValues = function(mat, row, v0, v1, v2, v3) {
    -  mat[row] = v0;
    -  mat[row + 4] = v1;
    -  mat[row + 8] = v2;
    -  mat[row + 12] = v3;
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the row values from the supplied vector.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix to receive the row values.
    - * @param {number} row The index of the row.
    - * @param {goog.vec.vec4d.Type} vec The vector containing the values.
    - * @return {!goog.vec.mat4d.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4d.setRow = function(mat, row, vec) {
    -  mat[row] = vec[0];
    -  mat[row + 4] = vec[1];
    -  mat[row + 8] = vec[2];
    -  mat[row + 12] = vec[3];
    -  return mat;
    -};
    -
    -
    -/**
    - * Retrieves the row values into the given vector.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix supplying the values.
    - * @param {number} row The index of the row supplying the values.
    - * @param {goog.vec.vec4d.Type} vec The vector to receive the row.
    - * @return {!goog.vec.vec4d.Type} return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4d.getRow = function(mat, row, vec) {
    -  vec[0] = mat[row];
    -  vec[1] = mat[row + 4];
    -  vec[2] = mat[row + 8];
    -  vec[3] = mat[row + 12];
    -  return vec;
    -};
    -
    -
    -/**
    - * Sets the rows of the matrix from the supplied vectors.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix to receive the values.
    - * @param {goog.vec.vec4d.Type} vec0 The values for row 0.
    - * @param {goog.vec.vec4d.Type} vec1 The values for row 1.
    - * @param {goog.vec.vec4d.Type} vec2 The values for row 2.
    - * @param {goog.vec.vec4d.Type} vec3 The values for row 3.
    - * @return {!goog.vec.mat4d.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4d.setRows = function(mat, vec0, vec1, vec2, vec3) {
    -  mat[0] = vec0[0];
    -  mat[1] = vec1[0];
    -  mat[2] = vec2[0];
    -  mat[3] = vec3[0];
    -  mat[4] = vec0[1];
    -  mat[5] = vec1[1];
    -  mat[6] = vec2[1];
    -  mat[7] = vec3[1];
    -  mat[8] = vec0[2];
    -  mat[9] = vec1[2];
    -  mat[10] = vec2[2];
    -  mat[11] = vec3[2];
    -  mat[12] = vec0[3];
    -  mat[13] = vec1[3];
    -  mat[14] = vec2[3];
    -  mat[15] = vec3[3];
    -  return mat;
    -};
    -
    -
    -/**
    - * Retrieves the rows of the matrix into the supplied vectors.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix to supply the values.
    - * @param {goog.vec.vec4d.Type} vec0 The vector to receive row 0.
    - * @param {goog.vec.vec4d.Type} vec1 The vector to receive row 1.
    - * @param {goog.vec.vec4d.Type} vec2 The vector to receive row 2.
    - * @param {goog.vec.vec4d.Type} vec3 The vector to receive row 3.
    - */
    -goog.vec.mat4d.getRows = function(mat, vec0, vec1, vec2, vec3) {
    -  vec0[0] = mat[0];
    -  vec1[0] = mat[1];
    -  vec2[0] = mat[2];
    -  vec3[0] = mat[3];
    -  vec0[1] = mat[4];
    -  vec1[1] = mat[5];
    -  vec2[1] = mat[6];
    -  vec3[1] = mat[7];
    -  vec0[2] = mat[8];
    -  vec1[2] = mat[9];
    -  vec2[2] = mat[10];
    -  vec3[2] = mat[11];
    -  vec0[3] = mat[12];
    -  vec1[3] = mat[13];
    -  vec2[3] = mat[14];
    -  vec3[3] = mat[15];
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix the zero matrix.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix.
    - * @return {!goog.vec.mat4d.Type} return mat so operations can be chained.
    - */
    -goog.vec.mat4d.makeZero = function(mat) {
    -  mat[0] = 0;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 0;
    -  mat[5] = 0;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = 0;
    -  mat[9] = 0;
    -  mat[10] = 0;
    -  mat[11] = 0;
    -  mat[12] = 0;
    -  mat[13] = 0;
    -  mat[14] = 0;
    -  mat[15] = 0;
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix the identity matrix.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix.
    - * @return {!goog.vec.mat4d.Type} return mat so operations can be chained.
    - */
    -goog.vec.mat4d.makeIdentity = function(mat) {
    -  mat[0] = 1;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 0;
    -  mat[5] = 1;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = 0;
    -  mat[9] = 0;
    -  mat[10] = 1;
    -  mat[11] = 0;
    -  mat[12] = 0;
    -  mat[13] = 0;
    -  mat[14] = 0;
    -  mat[15] = 1;
    -  return mat;
    -};
    -
    -
    -/**
    - * Performs a per-component addition of the matrix mat0 and mat1, storing
    - * the result into resultMat.
    - *
    - * @param {goog.vec.mat4d.Type} mat0 The first addend.
    - * @param {goog.vec.mat4d.Type} mat1 The second addend.
    - * @param {goog.vec.mat4d.Type} resultMat The matrix to
    - *     receive the results (may be either mat0 or mat1).
    - * @return {!goog.vec.mat4d.Type} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4d.addMat = function(mat0, mat1, resultMat) {
    -  resultMat[0] = mat0[0] + mat1[0];
    -  resultMat[1] = mat0[1] + mat1[1];
    -  resultMat[2] = mat0[2] + mat1[2];
    -  resultMat[3] = mat0[3] + mat1[3];
    -  resultMat[4] = mat0[4] + mat1[4];
    -  resultMat[5] = mat0[5] + mat1[5];
    -  resultMat[6] = mat0[6] + mat1[6];
    -  resultMat[7] = mat0[7] + mat1[7];
    -  resultMat[8] = mat0[8] + mat1[8];
    -  resultMat[9] = mat0[9] + mat1[9];
    -  resultMat[10] = mat0[10] + mat1[10];
    -  resultMat[11] = mat0[11] + mat1[11];
    -  resultMat[12] = mat0[12] + mat1[12];
    -  resultMat[13] = mat0[13] + mat1[13];
    -  resultMat[14] = mat0[14] + mat1[14];
    -  resultMat[15] = mat0[15] + mat1[15];
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Performs a per-component subtraction of the matrix mat0 and mat1,
    - * storing the result into resultMat.
    - *
    - * @param {goog.vec.mat4d.Type} mat0 The minuend.
    - * @param {goog.vec.mat4d.Type} mat1 The subtrahend.
    - * @param {goog.vec.mat4d.Type} resultMat The matrix to receive
    - *     the results (may be either mat0 or mat1).
    - * @return {!goog.vec.mat4d.Type} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4d.subMat = function(mat0, mat1, resultMat) {
    -  resultMat[0] = mat0[0] - mat1[0];
    -  resultMat[1] = mat0[1] - mat1[1];
    -  resultMat[2] = mat0[2] - mat1[2];
    -  resultMat[3] = mat0[3] - mat1[3];
    -  resultMat[4] = mat0[4] - mat1[4];
    -  resultMat[5] = mat0[5] - mat1[5];
    -  resultMat[6] = mat0[6] - mat1[6];
    -  resultMat[7] = mat0[7] - mat1[7];
    -  resultMat[8] = mat0[8] - mat1[8];
    -  resultMat[9] = mat0[9] - mat1[9];
    -  resultMat[10] = mat0[10] - mat1[10];
    -  resultMat[11] = mat0[11] - mat1[11];
    -  resultMat[12] = mat0[12] - mat1[12];
    -  resultMat[13] = mat0[13] - mat1[13];
    -  resultMat[14] = mat0[14] - mat1[14];
    -  resultMat[15] = mat0[15] - mat1[15];
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Multiplies matrix mat with the given scalar, storing the result
    - * into resultMat.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix.
    - * @param {number} scalar The scalar value to multiply to each element of mat.
    - * @param {goog.vec.mat4d.Type} resultMat The matrix to receive
    - *     the results (may be mat).
    - * @return {!goog.vec.mat4d.Type} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4d.multScalar = function(mat, scalar, resultMat) {
    -  resultMat[0] = mat[0] * scalar;
    -  resultMat[1] = mat[1] * scalar;
    -  resultMat[2] = mat[2] * scalar;
    -  resultMat[3] = mat[3] * scalar;
    -  resultMat[4] = mat[4] * scalar;
    -  resultMat[5] = mat[5] * scalar;
    -  resultMat[6] = mat[6] * scalar;
    -  resultMat[7] = mat[7] * scalar;
    -  resultMat[8] = mat[8] * scalar;
    -  resultMat[9] = mat[9] * scalar;
    -  resultMat[10] = mat[10] * scalar;
    -  resultMat[11] = mat[11] * scalar;
    -  resultMat[12] = mat[12] * scalar;
    -  resultMat[13] = mat[13] * scalar;
    -  resultMat[14] = mat[14] * scalar;
    -  resultMat[15] = mat[15] * scalar;
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Multiplies the two matrices mat0 and mat1 using matrix multiplication,
    - * storing the result into resultMat.
    - *
    - * @param {goog.vec.mat4d.Type} mat0 The first (left hand) matrix.
    - * @param {goog.vec.mat4d.Type} mat1 The second (right hand) matrix.
    - * @param {goog.vec.mat4d.Type} resultMat The matrix to receive
    - *     the results (may be either mat0 or mat1).
    - * @return {!goog.vec.mat4d.Type} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4d.multMat = function(mat0, mat1, resultMat) {
    -  var a00 = mat0[0], a10 = mat0[1], a20 = mat0[2], a30 = mat0[3];
    -  var a01 = mat0[4], a11 = mat0[5], a21 = mat0[6], a31 = mat0[7];
    -  var a02 = mat0[8], a12 = mat0[9], a22 = mat0[10], a32 = mat0[11];
    -  var a03 = mat0[12], a13 = mat0[13], a23 = mat0[14], a33 = mat0[15];
    -
    -  var b00 = mat1[0], b10 = mat1[1], b20 = mat1[2], b30 = mat1[3];
    -  var b01 = mat1[4], b11 = mat1[5], b21 = mat1[6], b31 = mat1[7];
    -  var b02 = mat1[8], b12 = mat1[9], b22 = mat1[10], b32 = mat1[11];
    -  var b03 = mat1[12], b13 = mat1[13], b23 = mat1[14], b33 = mat1[15];
    -
    -  resultMat[0] = a00 * b00 + a01 * b10 + a02 * b20 + a03 * b30;
    -  resultMat[1] = a10 * b00 + a11 * b10 + a12 * b20 + a13 * b30;
    -  resultMat[2] = a20 * b00 + a21 * b10 + a22 * b20 + a23 * b30;
    -  resultMat[3] = a30 * b00 + a31 * b10 + a32 * b20 + a33 * b30;
    -
    -  resultMat[4] = a00 * b01 + a01 * b11 + a02 * b21 + a03 * b31;
    -  resultMat[5] = a10 * b01 + a11 * b11 + a12 * b21 + a13 * b31;
    -  resultMat[6] = a20 * b01 + a21 * b11 + a22 * b21 + a23 * b31;
    -  resultMat[7] = a30 * b01 + a31 * b11 + a32 * b21 + a33 * b31;
    -
    -  resultMat[8] = a00 * b02 + a01 * b12 + a02 * b22 + a03 * b32;
    -  resultMat[9] = a10 * b02 + a11 * b12 + a12 * b22 + a13 * b32;
    -  resultMat[10] = a20 * b02 + a21 * b12 + a22 * b22 + a23 * b32;
    -  resultMat[11] = a30 * b02 + a31 * b12 + a32 * b22 + a33 * b32;
    -
    -  resultMat[12] = a00 * b03 + a01 * b13 + a02 * b23 + a03 * b33;
    -  resultMat[13] = a10 * b03 + a11 * b13 + a12 * b23 + a13 * b33;
    -  resultMat[14] = a20 * b03 + a21 * b13 + a22 * b23 + a23 * b33;
    -  resultMat[15] = a30 * b03 + a31 * b13 + a32 * b23 + a33 * b33;
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Transposes the given matrix mat storing the result into resultMat.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix to transpose.
    - * @param {goog.vec.mat4d.Type} resultMat The matrix to receive
    - *     the results (may be mat).
    - * @return {!goog.vec.mat4d.Type} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4d.transpose = function(mat, resultMat) {
    -  if (resultMat == mat) {
    -    var a10 = mat[1], a20 = mat[2], a30 = mat[3];
    -    var a21 = mat[6], a31 = mat[7];
    -    var a32 = mat[11];
    -    resultMat[1] = mat[4];
    -    resultMat[2] = mat[8];
    -    resultMat[3] = mat[12];
    -    resultMat[4] = a10;
    -    resultMat[6] = mat[9];
    -    resultMat[7] = mat[13];
    -    resultMat[8] = a20;
    -    resultMat[9] = a21;
    -    resultMat[11] = mat[14];
    -    resultMat[12] = a30;
    -    resultMat[13] = a31;
    -    resultMat[14] = a32;
    -  } else {
    -    resultMat[0] = mat[0];
    -    resultMat[1] = mat[4];
    -    resultMat[2] = mat[8];
    -    resultMat[3] = mat[12];
    -
    -    resultMat[4] = mat[1];
    -    resultMat[5] = mat[5];
    -    resultMat[6] = mat[9];
    -    resultMat[7] = mat[13];
    -
    -    resultMat[8] = mat[2];
    -    resultMat[9] = mat[6];
    -    resultMat[10] = mat[10];
    -    resultMat[11] = mat[14];
    -
    -    resultMat[12] = mat[3];
    -    resultMat[13] = mat[7];
    -    resultMat[14] = mat[11];
    -    resultMat[15] = mat[15];
    -  }
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Computes the determinant of the matrix.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix to compute the matrix for.
    - * @return {number} The determinant of the matrix.
    - */
    -goog.vec.mat4d.determinant = function(mat) {
    -  var m00 = mat[0], m10 = mat[1], m20 = mat[2], m30 = mat[3];
    -  var m01 = mat[4], m11 = mat[5], m21 = mat[6], m31 = mat[7];
    -  var m02 = mat[8], m12 = mat[9], m22 = mat[10], m32 = mat[11];
    -  var m03 = mat[12], m13 = mat[13], m23 = mat[14], m33 = mat[15];
    -
    -  var a0 = m00 * m11 - m10 * m01;
    -  var a1 = m00 * m21 - m20 * m01;
    -  var a2 = m00 * m31 - m30 * m01;
    -  var a3 = m10 * m21 - m20 * m11;
    -  var a4 = m10 * m31 - m30 * m11;
    -  var a5 = m20 * m31 - m30 * m21;
    -  var b0 = m02 * m13 - m12 * m03;
    -  var b1 = m02 * m23 - m22 * m03;
    -  var b2 = m02 * m33 - m32 * m03;
    -  var b3 = m12 * m23 - m22 * m13;
    -  var b4 = m12 * m33 - m32 * m13;
    -  var b5 = m22 * m33 - m32 * m23;
    -
    -  return a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0;
    -};
    -
    -
    -/**
    - * Computes the inverse of mat storing the result into resultMat. If the
    - * inverse is defined, this function returns true, false otherwise.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix to invert.
    - * @param {goog.vec.mat4d.Type} resultMat The matrix to receive
    - *     the result (may be mat).
    - * @return {boolean} True if the inverse is defined. If false is returned,
    - *     resultMat is not modified.
    - */
    -goog.vec.mat4d.invert = function(mat, resultMat) {
    -  var m00 = mat[0], m10 = mat[1], m20 = mat[2], m30 = mat[3];
    -  var m01 = mat[4], m11 = mat[5], m21 = mat[6], m31 = mat[7];
    -  var m02 = mat[8], m12 = mat[9], m22 = mat[10], m32 = mat[11];
    -  var m03 = mat[12], m13 = mat[13], m23 = mat[14], m33 = mat[15];
    -
    -  var a0 = m00 * m11 - m10 * m01;
    -  var a1 = m00 * m21 - m20 * m01;
    -  var a2 = m00 * m31 - m30 * m01;
    -  var a3 = m10 * m21 - m20 * m11;
    -  var a4 = m10 * m31 - m30 * m11;
    -  var a5 = m20 * m31 - m30 * m21;
    -  var b0 = m02 * m13 - m12 * m03;
    -  var b1 = m02 * m23 - m22 * m03;
    -  var b2 = m02 * m33 - m32 * m03;
    -  var b3 = m12 * m23 - m22 * m13;
    -  var b4 = m12 * m33 - m32 * m13;
    -  var b5 = m22 * m33 - m32 * m23;
    -
    -  var det = a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0;
    -  if (det == 0) {
    -    return false;
    -  }
    -
    -  var idet = 1.0 / det;
    -  resultMat[0] = (m11 * b5 - m21 * b4 + m31 * b3) * idet;
    -  resultMat[1] = (-m10 * b5 + m20 * b4 - m30 * b3) * idet;
    -  resultMat[2] = (m13 * a5 - m23 * a4 + m33 * a3) * idet;
    -  resultMat[3] = (-m12 * a5 + m22 * a4 - m32 * a3) * idet;
    -  resultMat[4] = (-m01 * b5 + m21 * b2 - m31 * b1) * idet;
    -  resultMat[5] = (m00 * b5 - m20 * b2 + m30 * b1) * idet;
    -  resultMat[6] = (-m03 * a5 + m23 * a2 - m33 * a1) * idet;
    -  resultMat[7] = (m02 * a5 - m22 * a2 + m32 * a1) * idet;
    -  resultMat[8] = (m01 * b4 - m11 * b2 + m31 * b0) * idet;
    -  resultMat[9] = (-m00 * b4 + m10 * b2 - m30 * b0) * idet;
    -  resultMat[10] = (m03 * a4 - m13 * a2 + m33 * a0) * idet;
    -  resultMat[11] = (-m02 * a4 + m12 * a2 - m32 * a0) * idet;
    -  resultMat[12] = (-m01 * b3 + m11 * b1 - m21 * b0) * idet;
    -  resultMat[13] = (m00 * b3 - m10 * b1 + m20 * b0) * idet;
    -  resultMat[14] = (-m03 * a3 + m13 * a1 - m23 * a0) * idet;
    -  resultMat[15] = (m02 * a3 - m12 * a1 + m22 * a0) * idet;
    -  return true;
    -};
    -
    -
    -/**
    - * Returns true if the components of mat0 are equal to the components of mat1.
    - *
    - * @param {goog.vec.mat4d.Type} mat0 The first matrix.
    - * @param {goog.vec.mat4d.Type} mat1 The second matrix.
    - * @return {boolean} True if the the two matrices are equivalent.
    - */
    -goog.vec.mat4d.equals = function(mat0, mat1) {
    -  return mat0.length == mat1.length &&
    -      mat0[0] == mat1[0] &&
    -      mat0[1] == mat1[1] &&
    -      mat0[2] == mat1[2] &&
    -      mat0[3] == mat1[3] &&
    -      mat0[4] == mat1[4] &&
    -      mat0[5] == mat1[5] &&
    -      mat0[6] == mat1[6] &&
    -      mat0[7] == mat1[7] &&
    -      mat0[8] == mat1[8] &&
    -      mat0[9] == mat1[9] &&
    -      mat0[10] == mat1[10] &&
    -      mat0[11] == mat1[11] &&
    -      mat0[12] == mat1[12] &&
    -      mat0[13] == mat1[13] &&
    -      mat0[14] == mat1[14] &&
    -      mat0[15] == mat1[15];
    -};
    -
    -
    -/**
    - * Transforms the given vector with the given matrix storing the resulting,
    - * transformed vector into resultVec. The input vector is multiplied against the
    - * upper 3x4 matrix omitting the projective component.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix supplying the transformation.
    - * @param {goog.vec.vec3d.Type} vec The 3 element vector to transform.
    - * @param {goog.vec.vec3d.Type} resultVec The 3 element vector to
    - *     receive the results (may be vec).
    - * @return {!goog.vec.vec3d.Type} return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4d.multVec3 = function(mat, vec, resultVec) {
    -  var x = vec[0], y = vec[1], z = vec[2];
    -  resultVec[0] = x * mat[0] + y * mat[4] + z * mat[8] + mat[12];
    -  resultVec[1] = x * mat[1] + y * mat[5] + z * mat[9] + mat[13];
    -  resultVec[2] = x * mat[2] + y * mat[6] + z * mat[10] + mat[14];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Transforms the given vector with the given matrix storing the resulting,
    - * transformed vector into resultVec. The input vector is multiplied against the
    - * upper 3x3 matrix omitting the projective component and translation
    - * components.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix supplying the transformation.
    - * @param {goog.vec.vec3d.Type} vec The 3 element vector to transform.
    - * @param {goog.vec.vec3d.Type} resultVec The 3 element vector to
    - *     receive the results (may be vec).
    - * @return {!goog.vec.vec3d.Type} return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4d.multVec3NoTranslate = function(mat, vec, resultVec) {
    -  var x = vec[0], y = vec[1], z = vec[2];
    -  resultVec[0] = x * mat[0] + y * mat[4] + z * mat[8];
    -  resultVec[1] = x * mat[1] + y * mat[5] + z * mat[9];
    -  resultVec[2] = x * mat[2] + y * mat[6] + z * mat[10];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Transforms the given vector with the given matrix storing the resulting,
    - * transformed vector into resultVec. The input vector is multiplied against the
    - * full 4x4 matrix with the homogeneous divide applied to reduce the 4 element
    - * vector to a 3 element vector.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix supplying the transformation.
    - * @param {goog.vec.vec3d.Type} vec The 3 element vector to transform.
    - * @param {goog.vec.vec3d.Type} resultVec The 3 element vector
    - *     to receive the results (may be vec).
    - * @return {!goog.vec.vec3d.Type} return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4d.multVec3Projective = function(mat, vec, resultVec) {
    -  var x = vec[0], y = vec[1], z = vec[2];
    -  var invw = 1 / (x * mat[3] + y * mat[7] + z * mat[11] + mat[15]);
    -  resultVec[0] = (x * mat[0] + y * mat[4] + z * mat[8] + mat[12]) * invw;
    -  resultVec[1] = (x * mat[1] + y * mat[5] + z * mat[9] + mat[13]) * invw;
    -  resultVec[2] = (x * mat[2] + y * mat[6] + z * mat[10] + mat[14]) * invw;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Transforms the given vector with the given matrix storing the resulting,
    - * transformed vector into resultVec.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix supplying the transformation.
    - * @param {goog.vec.vec4d.Type} vec The vector to transform.
    - * @param {goog.vec.vec4d.Type} resultVec The vector to
    - *     receive the results (may be vec).
    - * @return {!goog.vec.vec4d.Type} return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4d.multVec4 = function(mat, vec, resultVec) {
    -  var x = vec[0], y = vec[1], z = vec[2], w = vec[3];
    -  resultVec[0] = x * mat[0] + y * mat[4] + z * mat[8] + w * mat[12];
    -  resultVec[1] = x * mat[1] + y * mat[5] + z * mat[9] + w * mat[13];
    -  resultVec[2] = x * mat[2] + y * mat[6] + z * mat[10] + w * mat[14];
    -  resultVec[3] = x * mat[3] + y * mat[7] + z * mat[11] + w * mat[15];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix a translation matrix with x, y and z
    - * translation factors.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix.
    - * @param {number} x The translation along the x axis.
    - * @param {number} y The translation along the y axis.
    - * @param {number} z The translation along the z axis.
    - * @return {!goog.vec.mat4d.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4d.makeTranslate = function(mat, x, y, z) {
    -  mat[0] = 1;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 0;
    -  mat[5] = 1;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = 0;
    -  mat[9] = 0;
    -  mat[10] = 1;
    -  mat[11] = 0;
    -  mat[12] = x;
    -  mat[13] = y;
    -  mat[14] = z;
    -  mat[15] = 1;
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix as a scale matrix with x, y and z scale factors.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix.
    - * @param {number} x The scale along the x axis.
    - * @param {number} y The scale along the y axis.
    - * @param {number} z The scale along the z axis.
    - * @return {!goog.vec.mat4d.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4d.makeScale = function(mat, x, y, z) {
    -  mat[0] = x;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 0;
    -  mat[5] = y;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = 0;
    -  mat[9] = 0;
    -  mat[10] = z;
    -  mat[11] = 0;
    -  mat[12] = 0;
    -  mat[13] = 0;
    -  mat[14] = 0;
    -  mat[15] = 1;
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix a rotation matrix with the given rotation
    - * angle about the axis defined by the vector (ax, ay, az).
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix.
    - * @param {number} angle The rotation angle in radians.
    - * @param {number} ax The x component of the rotation axis.
    - * @param {number} ay The y component of the rotation axis.
    - * @param {number} az The z component of the rotation axis.
    - * @return {!goog.vec.mat4d.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4d.makeRotate = function(mat, angle, ax, ay, az) {
    -  var c = Math.cos(angle);
    -  var d = 1 - c;
    -  var s = Math.sin(angle);
    -
    -  mat[0] = ax * ax * d + c;
    -  mat[1] = ax * ay * d + az * s;
    -  mat[2] = ax * az * d - ay * s;
    -  mat[3] = 0;
    -  mat[4] = ax * ay * d - az * s;
    -  mat[5] = ay * ay * d + c;
    -  mat[6] = ay * az * d + ax * s;
    -  mat[7] = 0;
    -  mat[8] = ax * az * d + ay * s;
    -  mat[9] = ay * az * d - ax * s;
    -  mat[10] = az * az * d + c;
    -  mat[11] = 0;
    -  mat[12] = 0;
    -  mat[13] = 0;
    -  mat[14] = 0;
    -  mat[15] = 1;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix a rotation matrix with the given rotation
    - * angle about the X axis.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix.
    - * @param {number} angle The rotation angle in radians.
    - * @return {!goog.vec.mat4d.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4d.makeRotateX = function(mat, angle) {
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[0] = 1;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 0;
    -  mat[5] = c;
    -  mat[6] = s;
    -  mat[7] = 0;
    -  mat[8] = 0;
    -  mat[9] = -s;
    -  mat[10] = c;
    -  mat[11] = 0;
    -  mat[12] = 0;
    -  mat[13] = 0;
    -  mat[14] = 0;
    -  mat[15] = 1;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix a rotation matrix with the given rotation
    - * angle about the Y axis.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix.
    - * @param {number} angle The rotation angle in radians.
    - * @return {!goog.vec.mat4d.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4d.makeRotateY = function(mat, angle) {
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[0] = c;
    -  mat[1] = 0;
    -  mat[2] = -s;
    -  mat[3] = 0;
    -  mat[4] = 0;
    -  mat[5] = 1;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = s;
    -  mat[9] = 0;
    -  mat[10] = c;
    -  mat[11] = 0;
    -  mat[12] = 0;
    -  mat[13] = 0;
    -  mat[14] = 0;
    -  mat[15] = 1;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix a rotation matrix with the given rotation
    - * angle about the Z axis.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix.
    - * @param {number} angle The rotation angle in radians.
    - * @return {!goog.vec.mat4d.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4d.makeRotateZ = function(mat, angle) {
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[0] = c;
    -  mat[1] = s;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = -s;
    -  mat[5] = c;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = 0;
    -  mat[9] = 0;
    -  mat[10] = 1;
    -  mat[11] = 0;
    -  mat[12] = 0;
    -  mat[13] = 0;
    -  mat[14] = 0;
    -  mat[15] = 1;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix a perspective projection matrix.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix.
    - * @param {number} left The coordinate of the left clipping plane.
    - * @param {number} right The coordinate of the right clipping plane.
    - * @param {number} bottom The coordinate of the bottom clipping plane.
    - * @param {number} top The coordinate of the top clipping plane.
    - * @param {number} near The distance to the near clipping plane.
    - * @param {number} far The distance to the far clipping plane.
    - * @return {!goog.vec.mat4d.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4d.makeFrustum = function(
    -    mat, left, right, bottom, top, near, far) {
    -  var x = (2 * near) / (right - left);
    -  var y = (2 * near) / (top - bottom);
    -  var a = (right + left) / (right - left);
    -  var b = (top + bottom) / (top - bottom);
    -  var c = -(far + near) / (far - near);
    -  var d = -(2 * far * near) / (far - near);
    -
    -  mat[0] = x;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 0;
    -  mat[5] = y;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = a;
    -  mat[9] = b;
    -  mat[10] = c;
    -  mat[11] = -1;
    -  mat[12] = 0;
    -  mat[13] = 0;
    -  mat[14] = d;
    -  mat[15] = 0;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Makse the given 4x4 matrix  perspective projection matrix given a
    - * field of view and aspect ratio.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix.
    - * @param {number} fovy The field of view along the y (vertical) axis in
    - *     radians.
    - * @param {number} aspect The x (width) to y (height) aspect ratio.
    - * @param {number} near The distance to the near clipping plane.
    - * @param {number} far The distance to the far clipping plane.
    - * @return {goog.vec.mat4d.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4d.makePerspective = function(mat, fovy, aspect, near, far) {
    -  var angle = fovy / 2;
    -  var dz = far - near;
    -  var sinAngle = Math.sin(angle);
    -  if (dz == 0 || sinAngle == 0 || aspect == 0) {
    -    return mat;
    -  }
    -
    -  var cot = Math.cos(angle) / sinAngle;
    -
    -  mat[0] = cot / aspect;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 0;
    -  mat[5] = cot;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = 0;
    -  mat[9] = 0;
    -  mat[10] = -(far + near) / dz;
    -  mat[11] = -1;
    -  mat[12] = 0;
    -  mat[13] = 0;
    -  mat[14] = -(2 * near * far) / dz;
    -  mat[15] = 0;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix an orthographic projection matrix.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix.
    - * @param {number} left The coordinate of the left clipping plane.
    - * @param {number} right The coordinate of the right clipping plane.
    - * @param {number} bottom The coordinate of the bottom clipping plane.
    - * @param {number} top The coordinate of the top clipping plane.
    - * @param {number} near The distance to the near clipping plane.
    - * @param {number} far The distance to the far clipping plane.
    - * @return {!goog.vec.mat4d.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4d.makeOrtho = function(mat, left, right, bottom, top, near, far) {
    -  var x = 2 / (right - left);
    -  var y = 2 / (top - bottom);
    -  var z = -2 / (far - near);
    -  var a = -(right + left) / (right - left);
    -  var b = -(top + bottom) / (top - bottom);
    -  var c = -(far + near) / (far - near);
    -
    -  mat[0] = x;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 0;
    -  mat[5] = y;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = 0;
    -  mat[9] = 0;
    -  mat[10] = z;
    -  mat[11] = 0;
    -  mat[12] = a;
    -  mat[13] = b;
    -  mat[14] = c;
    -  mat[15] = 1;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix a modelview matrix of a camera so that
    - * the camera is 'looking at' the given center point.
    - *
    - * Note that unlike most other goog.vec functions where we inline
    - * everything, this function does not inline various goog.vec
    - * functions.  This makes the code more readable, but somewhat
    - * less efficient.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix.
    - * @param {goog.vec.vec3d.Type} eyePt The position of the eye point
    - *     (camera origin).
    - * @param {goog.vec.vec3d.Type} centerPt The point to aim the camera at.
    - * @param {goog.vec.vec3d.Type} worldUpVec The vector that identifies
    - *     the up direction for the camera.
    - * @return {goog.vec.mat4d.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4d.makeLookAt = function(mat, eyePt, centerPt, worldUpVec) {
    -  // Compute the direction vector from the eye point to the center point and
    -  // normalize.
    -  var fwdVec = goog.vec.mat4d.tmpvec4d_[0];
    -  goog.vec.vec3d.subtract(centerPt, eyePt, fwdVec);
    -  goog.vec.vec3d.normalize(fwdVec, fwdVec);
    -  fwdVec[3] = 0;
    -
    -  // Compute the side vector from the forward vector and the input up vector.
    -  var sideVec = goog.vec.mat4d.tmpvec4d_[1];
    -  goog.vec.vec3d.cross(fwdVec, worldUpVec, sideVec);
    -  goog.vec.vec3d.normalize(sideVec, sideVec);
    -  sideVec[3] = 0;
    -
    -  // Now the up vector to form the orthonormal basis.
    -  var upVec = goog.vec.mat4d.tmpvec4d_[2];
    -  goog.vec.vec3d.cross(sideVec, fwdVec, upVec);
    -  goog.vec.vec3d.normalize(upVec, upVec);
    -  upVec[3] = 0;
    -
    -  // Update the view matrix with the new orthonormal basis and position the
    -  // camera at the given eye point.
    -  goog.vec.vec3d.negate(fwdVec, fwdVec);
    -  goog.vec.mat4d.setRow(mat, 0, sideVec);
    -  goog.vec.mat4d.setRow(mat, 1, upVec);
    -  goog.vec.mat4d.setRow(mat, 2, fwdVec);
    -  goog.vec.mat4d.setRowValues(mat, 3, 0, 0, 0, 1);
    -  goog.vec.mat4d.translate(
    -      mat, -eyePt[0], -eyePt[1], -eyePt[2]);
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Decomposes a matrix into the lookAt vectors eyePt, fwdVec and worldUpVec.
    - * The matrix represents the modelview matrix of a camera. It is the inverse
    - * of lookAt except for the output of the fwdVec instead of centerPt.
    - * The centerPt itself cannot be recovered from a modelview matrix.
    - *
    - * Note that unlike most other goog.vec functions where we inline
    - * everything, this function does not inline various goog.vec
    - * functions.  This makes the code more readable, but somewhat
    - * less efficient.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix.
    - * @param {goog.vec.vec3d.Type} eyePt The position of the eye point
    - *     (camera origin).
    - * @param {goog.vec.vec3d.Type} fwdVec The vector describing where
    - *     the camera points to.
    - * @param {goog.vec.vec3d.Type} worldUpVec The vector that
    - *     identifies the up direction for the camera.
    - * @return {boolean} True if the method succeeds, false otherwise.
    - *     The method can only fail if the inverse of viewMatrix is not defined.
    - */
    -goog.vec.mat4d.toLookAt = function(mat, eyePt, fwdVec, worldUpVec) {
    -  // Get eye of the camera.
    -  var matInverse = goog.vec.mat4d.tmpmat4d_[0];
    -  if (!goog.vec.mat4d.invert(mat, matInverse)) {
    -    // The input matrix does not have a valid inverse.
    -    return false;
    -  }
    -
    -  if (eyePt) {
    -    eyePt[0] = matInverse[12];
    -    eyePt[1] = matInverse[13];
    -    eyePt[2] = matInverse[14];
    -  }
    -
    -  // Get forward vector from the definition of lookAt.
    -  if (fwdVec || worldUpVec) {
    -    if (!fwdVec) {
    -      fwdVec = goog.vec.mat4d.tmpvec3d_[0];
    -    }
    -    fwdVec[0] = -mat[2];
    -    fwdVec[1] = -mat[6];
    -    fwdVec[2] = -mat[10];
    -    // Normalize forward vector.
    -    goog.vec.vec3d.normalize(fwdVec, fwdVec);
    -  }
    -
    -  if (worldUpVec) {
    -    // Get side vector from the definition of gluLookAt.
    -    var side = goog.vec.mat4d.tmpvec3d_[1];
    -    side[0] = mat[0];
    -    side[1] = mat[4];
    -    side[2] = mat[8];
    -    // Compute up vector as a up = side x forward.
    -    goog.vec.vec3d.cross(side, fwdVec, worldUpVec);
    -    // Normalize up vector.
    -    goog.vec.vec3d.normalize(worldUpVec, worldUpVec);
    -  }
    -  return true;
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix a rotation matrix given Euler angles using
    - * the ZXZ convention.
    - * Given the euler angles [theta1, theta2, theta3], the rotation is defined as
    - * rotation = rotation_z(theta1) * rotation_x(theta2) * rotation_z(theta3),
    - * with theta1 in [0, 2 * pi], theta2 in [0, pi] and theta3 in [0, 2 * pi].
    - * rotation_x(theta) means rotation around the X axis of theta radians,
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix.
    - * @param {number} theta1 The angle of rotation around the Z axis in radians.
    - * @param {number} theta2 The angle of rotation around the X axis in radians.
    - * @param {number} theta3 The angle of rotation around the Z axis in radians.
    - * @return {!goog.vec.mat4d.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4d.makeEulerZXZ = function(mat, theta1, theta2, theta3) {
    -  var c1 = Math.cos(theta1);
    -  var s1 = Math.sin(theta1);
    -
    -  var c2 = Math.cos(theta2);
    -  var s2 = Math.sin(theta2);
    -
    -  var c3 = Math.cos(theta3);
    -  var s3 = Math.sin(theta3);
    -
    -  mat[0] = c1 * c3 - c2 * s1 * s3;
    -  mat[1] = c2 * c1 * s3 + c3 * s1;
    -  mat[2] = s3 * s2;
    -  mat[3] = 0;
    -
    -  mat[4] = -c1 * s3 - c3 * c2 * s1;
    -  mat[5] = c1 * c2 * c3 - s1 * s3;
    -  mat[6] = c3 * s2;
    -  mat[7] = 0;
    -
    -  mat[8] = s2 * s1;
    -  mat[9] = -c1 * s2;
    -  mat[10] = c2;
    -  mat[11] = 0;
    -
    -  mat[12] = 0;
    -  mat[13] = 0;
    -  mat[14] = 0;
    -  mat[15] = 1;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Decomposes a rotation matrix into Euler angles using the ZXZ convention so
    - * that rotation = rotation_z(theta1) * rotation_x(theta2) * rotation_z(theta3),
    - * with theta1 in [0, 2 * pi], theta2 in [0, pi] and theta3 in [0, 2 * pi].
    - * rotation_x(theta) means rotation around the X axis of theta radians.
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix.
    - * @param {goog.vec.vec3d.Type} euler The ZXZ Euler angles in
    - *     radians as [theta1, theta2, theta3].
    - * @param {boolean=} opt_theta2IsNegative Whether theta2 is in [-pi, 0] instead
    - *     of the default [0, pi].
    - * @return {!goog.vec.vec4d.Type} return euler so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4d.toEulerZXZ = function(mat, euler, opt_theta2IsNegative) {
    -  // There is an ambiguity in the sign of sinTheta2 because of the sqrt.
    -  var sinTheta2 = Math.sqrt(mat[2] * mat[2] + mat[6] * mat[6]);
    -
    -  // By default we explicitely constrain theta2 to be in [0, pi],
    -  // so sinTheta2 is always positive. We can change the behavior and specify
    -  // theta2 to be negative in [-pi, 0] with opt_Theta2IsNegative.
    -  var signTheta2 = opt_theta2IsNegative ? -1 : 1;
    -
    -  if (sinTheta2 > goog.vec.EPSILON) {
    -    euler[2] = Math.atan2(mat[2] * signTheta2, mat[6] * signTheta2);
    -    euler[1] = Math.atan2(sinTheta2 * signTheta2, mat[10]);
    -    euler[0] = Math.atan2(mat[8] * signTheta2, -mat[9] * signTheta2);
    -  } else {
    -    // There is also an arbitrary choice for theta1 = 0 or theta2 = 0 here.
    -    // We assume theta1 = 0 as some applications do not allow the camera to roll
    -    // (i.e. have theta1 != 0).
    -    euler[0] = 0;
    -    euler[1] = Math.atan2(sinTheta2 * signTheta2, mat[10]);
    -    euler[2] = Math.atan2(mat[1], mat[0]);
    -  }
    -
    -  // Atan2 outputs angles in [-pi, pi] so we bring them back to [0, 2 * pi].
    -  euler[0] = (euler[0] + Math.PI * 2) % (Math.PI * 2);
    -  euler[2] = (euler[2] + Math.PI * 2) % (Math.PI * 2);
    -  // For theta2 we want the angle to be in [0, pi] or [-pi, 0] depending on
    -  // signTheta2.
    -  euler[1] = ((euler[1] * signTheta2 + Math.PI * 2) % (Math.PI * 2)) *
    -      signTheta2;
    -
    -  return euler;
    -};
    -
    -
    -/**
    - * Translates the given matrix by x,y,z.  Equvialent to:
    - * goog.vec.mat4d.multMat(
    - *     mat,
    - *     goog.vec.mat4d.makeTranslate(goog.vec.mat4d.create(), x, y, z),
    - *     mat);
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix.
    - * @param {number} x The translation along the x axis.
    - * @param {number} y The translation along the y axis.
    - * @param {number} z The translation along the z axis.
    - * @return {!goog.vec.mat4d.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4d.translate = function(mat, x, y, z) {
    -  mat[12] += mat[0] * x + mat[4] * y + mat[8] * z;
    -  mat[13] += mat[1] * x + mat[5] * y + mat[9] * z;
    -  mat[14] += mat[2] * x + mat[6] * y + mat[10] * z;
    -  mat[15] += mat[3] * x + mat[7] * y + mat[11] * z;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Scales the given matrix by x,y,z.  Equivalent to:
    - * goog.vec.mat4d.multMat(
    - *     mat,
    - *     goog.vec.mat4d.makeScale(goog.vec.mat4d.create(), x, y, z),
    - *     mat);
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix.
    - * @param {number} x The x scale factor.
    - * @param {number} y The y scale factor.
    - * @param {number} z The z scale factor.
    - * @return {!goog.vec.mat4d.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4d.scale = function(mat, x, y, z) {
    -  mat[0] = mat[0] * x;
    -  mat[1] = mat[1] * x;
    -  mat[2] = mat[2] * x;
    -  mat[3] = mat[3] * x;
    -  mat[4] = mat[4] * y;
    -  mat[5] = mat[5] * y;
    -  mat[6] = mat[6] * y;
    -  mat[7] = mat[7] * y;
    -  mat[8] = mat[8] * z;
    -  mat[9] = mat[9] * z;
    -  mat[10] = mat[10] * z;
    -  mat[11] = mat[11] * z;
    -  mat[12] = mat[12];
    -  mat[13] = mat[13];
    -  mat[14] = mat[14];
    -  mat[15] = mat[15];
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Rotate the given matrix by angle about the x,y,z axis.  Equivalent to:
    - * goog.vec.mat4d.multMat(
    - *     mat,
    - *     goog.vec.mat4d.makeRotate(goog.vec.mat4d.create(), angle, x, y, z),
    - *     mat);
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix.
    - * @param {number} angle The angle in radians.
    - * @param {number} x The x component of the rotation axis.
    - * @param {number} y The y component of the rotation axis.
    - * @param {number} z The z component of the rotation axis.
    - * @return {!goog.vec.mat4d.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4d.rotate = function(mat, angle, x, y, z) {
    -  var m00 = mat[0], m10 = mat[1], m20 = mat[2], m30 = mat[3];
    -  var m01 = mat[4], m11 = mat[5], m21 = mat[6], m31 = mat[7];
    -  var m02 = mat[8], m12 = mat[9], m22 = mat[10], m32 = mat[11];
    -
    -  var cosAngle = Math.cos(angle);
    -  var sinAngle = Math.sin(angle);
    -  var diffCosAngle = 1 - cosAngle;
    -  var r00 = x * x * diffCosAngle + cosAngle;
    -  var r10 = x * y * diffCosAngle + z * sinAngle;
    -  var r20 = x * z * diffCosAngle - y * sinAngle;
    -
    -  var r01 = x * y * diffCosAngle - z * sinAngle;
    -  var r11 = y * y * diffCosAngle + cosAngle;
    -  var r21 = y * z * diffCosAngle + x * sinAngle;
    -
    -  var r02 = x * z * diffCosAngle + y * sinAngle;
    -  var r12 = y * z * diffCosAngle - x * sinAngle;
    -  var r22 = z * z * diffCosAngle + cosAngle;
    -
    -  mat[0] = m00 * r00 + m01 * r10 + m02 * r20;
    -  mat[1] = m10 * r00 + m11 * r10 + m12 * r20;
    -  mat[2] = m20 * r00 + m21 * r10 + m22 * r20;
    -  mat[3] = m30 * r00 + m31 * r10 + m32 * r20;
    -  mat[4] = m00 * r01 + m01 * r11 + m02 * r21;
    -  mat[5] = m10 * r01 + m11 * r11 + m12 * r21;
    -  mat[6] = m20 * r01 + m21 * r11 + m22 * r21;
    -  mat[7] = m30 * r01 + m31 * r11 + m32 * r21;
    -  mat[8] = m00 * r02 + m01 * r12 + m02 * r22;
    -  mat[9] = m10 * r02 + m11 * r12 + m12 * r22;
    -  mat[10] = m20 * r02 + m21 * r12 + m22 * r22;
    -  mat[11] = m30 * r02 + m31 * r12 + m32 * r22;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Rotate the given matrix by angle about the x axis.  Equivalent to:
    - * goog.vec.mat4d.multMat(
    - *     mat,
    - *     goog.vec.mat4d.makeRotateX(goog.vec.mat4d.create(), angle),
    - *     mat);
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix.
    - * @param {number} angle The angle in radians.
    - * @return {!goog.vec.mat4d.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4d.rotateX = function(mat, angle) {
    -  var m01 = mat[4], m11 = mat[5], m21 = mat[6], m31 = mat[7];
    -  var m02 = mat[8], m12 = mat[9], m22 = mat[10], m32 = mat[11];
    -
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[4] = m01 * c + m02 * s;
    -  mat[5] = m11 * c + m12 * s;
    -  mat[6] = m21 * c + m22 * s;
    -  mat[7] = m31 * c + m32 * s;
    -  mat[8] = m01 * -s + m02 * c;
    -  mat[9] = m11 * -s + m12 * c;
    -  mat[10] = m21 * -s + m22 * c;
    -  mat[11] = m31 * -s + m32 * c;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Rotate the given matrix by angle about the y axis.  Equivalent to:
    - * goog.vec.mat4d.multMat(
    - *     mat,
    - *     goog.vec.mat4d.makeRotateY(goog.vec.mat4d.create(), angle),
    - *     mat);
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix.
    - * @param {number} angle The angle in radians.
    - * @return {!goog.vec.mat4d.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4d.rotateY = function(mat, angle) {
    -  var m00 = mat[0], m10 = mat[1], m20 = mat[2], m30 = mat[3];
    -  var m02 = mat[8], m12 = mat[9], m22 = mat[10], m32 = mat[11];
    -
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[0] = m00 * c + m02 * -s;
    -  mat[1] = m10 * c + m12 * -s;
    -  mat[2] = m20 * c + m22 * -s;
    -  mat[3] = m30 * c + m32 * -s;
    -  mat[8] = m00 * s + m02 * c;
    -  mat[9] = m10 * s + m12 * c;
    -  mat[10] = m20 * s + m22 * c;
    -  mat[11] = m30 * s + m32 * c;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Rotate the given matrix by angle about the z axis.  Equivalent to:
    - * goog.vec.mat4d.multMat(
    - *     mat,
    - *     goog.vec.mat4d.makeRotateZ(goog.vec.mat4d.create(), angle),
    - *     mat);
    - *
    - * @param {goog.vec.mat4d.Type} mat The matrix.
    - * @param {number} angle The angle in radians.
    - * @return {!goog.vec.mat4d.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4d.rotateZ = function(mat, angle) {
    -  var m00 = mat[0], m10 = mat[1], m20 = mat[2], m30 = mat[3];
    -  var m01 = mat[4], m11 = mat[5], m21 = mat[6], m31 = mat[7];
    -
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[0] = m00 * c + m01 * s;
    -  mat[1] = m10 * c + m11 * s;
    -  mat[2] = m20 * c + m21 * s;
    -  mat[3] = m30 * c + m31 * s;
    -  mat[4] = m00 * -s + m01 * c;
    -  mat[5] = m10 * -s + m11 * c;
    -  mat[6] = m20 * -s + m21 * c;
    -  mat[7] = m30 * -s + m31 * c;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Retrieves the translation component of the transformation matrix.
    - *
    - * @param {goog.vec.mat4d.Type} mat The transformation matrix.
    - * @param {goog.vec.vec3d.Type} translation The vector for storing the
    - *     result.
    - * @return {!goog.vec.vec3d.Type} return translation so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4d.getTranslation = function(mat, translation) {
    -  translation[0] = mat[12];
    -  translation[1] = mat[13];
    -  translation[2] = mat[14];
    -  return translation;
    -};
    -
    -
    -/**
    - * @type {Array<goog.vec.vec3d.Type>}
    - * @private
    - */
    -goog.vec.mat4d.tmpvec3d_ = [
    -  goog.vec.vec3d.create(),
    -  goog.vec.vec3d.create()
    -];
    -
    -
    -/**
    - * @type {Array<goog.vec.vec4d.Type>}
    - * @private
    - */
    -goog.vec.mat4d.tmpvec4d_ = [
    -  goog.vec.vec4d.create(),
    -  goog.vec.vec4d.create(),
    -  goog.vec.vec4d.create()
    -];
    -
    -
    -/**
    - * @type {Array<goog.vec.mat4d.Type>}
    - * @private
    - */
    -goog.vec.mat4d.tmpmat4d_ = [
    -  goog.vec.mat4d.create()
    -];
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/mat4d_test.html b/src/database/third_party/closure-library/closure/goog/vec/mat4d_test.html
    deleted file mode 100644
    index 7ec7e7489f0..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/mat4d_test.html
    +++ /dev/null
    @@ -1,738 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -//                                                                           //
    -// Any edits to this file must be applied to mat4f_test.html by running:     //
    -//   swap_type.sh mat4d_test.html > mat4f_test.html                          //
    -//                                                                           //
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.vec.mat4d</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.vec.mat4d');
    -  goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -  var randommat4d = goog.vec.mat4d.setFromValues(goog.vec.mat4d.create(),
    -      0.8025078773498535,
    -      0.7559120655059814,
    -      0.15274643898010254,
    -      0.19196106493473053,
    -      0.0890120416879654,
    -      0.15422114729881287,
    -      0.09754583984613419,
    -      0.44862601161003113,
    -      0.9196512699127197,
    -      0.5310639142990112,
    -      0.8962187170982361,
    -      0.280601441860199,
    -      0.594650387763977,
    -      0.4134795069694519,
    -      0.06632178276777267,
    -      0.8837796449661255);
    -
    -  function testCreate() {
    -    var m = goog.vec.mat4d.create();
    -    assertElementsEquals([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], m);
    -  }
    -
    -  function testSet() {
    -    var m0 = goog.vec.mat4d.create();
    -    var m1 = goog.vec.mat4d.setFromArray(goog.vec.mat4d.create(), 
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
    -    goog.vec.mat4d.setFromArray(m0, m1);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -
    -    goog.vec.mat4d.setFromValues(
    -        m0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17);
    -    assertElementsEquals(
    -        [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17], m0);
    -  }
    -
    -  function testSetDiagonal() {
    -    var m0 = goog.vec.mat4d.create();
    -    goog.vec.mat4d.setDiagonalValues(m0, 1, 2, 3, 4);
    -    assertElementsEquals(
    -        [1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 4], m0);
    -
    -    goog.vec.mat4d.setDiagonal(m0, [4, 5, 6, 7]);
    -    assertElementsEquals(
    -        [4, 0, 0, 0, 0, 5, 0, 0, 0, 0, 6, 0, 0, 0, 0, 7], m0);
    -  }
    -
    -  function testGetDiagonal() {
    -    var v0 = goog.vec.vec4d.create();
    -    var m0 = goog.vec.mat4d.create();
    -    goog.vec.mat4d.setFromArray(
    -        m0, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
    -
    -    goog.vec.mat4d.getDiagonal(m0, v0);
    -    assertElementsEquals([0, 5, 10, 15], v0);
    -
    -    goog.vec.vec4d.setFromArray(v0, [0, 0, 0, 0]);
    -    goog.vec.mat4d.getDiagonal(m0, v0, 1);
    -    assertElementsEquals([4, 9, 14, 0], v0);
    -
    -    goog.vec.vec4d.setFromArray(v0, [0, 0, 0, 0]);
    -    goog.vec.mat4d.getDiagonal(m0, v0, 2);
    -    assertElementsEquals([8, 13, 0, 0], v0);
    -
    -    goog.vec.vec4d.setFromArray(v0, [0, 0, 0, 0]);
    -    goog.vec.mat4d.getDiagonal(m0, v0, 3);
    -    assertElementsEquals([12, 0, 0, 0], v0);
    -
    -    goog.vec.vec4d.setFromArray(v0, [0, 0, 0, 0]);
    -    goog.vec.mat4d.getDiagonal(m0, v0, 4);
    -    assertElementsEquals([0, 0, 0, 0], v0);
    -
    -    goog.vec.vec4d.setFromArray(v0, [0, 0, 0, 0]);
    -    goog.vec.mat4d.getDiagonal(m0, v0, -1);
    -    assertElementsEquals([1, 6, 11, 0], v0);
    -
    -    goog.vec.vec4d.setFromArray(v0, [0, 0, 0, 0]);
    -    goog.vec.mat4d.getDiagonal(m0, v0, -2);
    -    assertElementsEquals([2, 7, 0, 0], v0);
    -
    -    goog.vec.vec4d.setFromArray(v0, [0, 0, 0, 0]);
    -    goog.vec.mat4d.getDiagonal(m0, v0, -3);
    -    assertElementsEquals([3, 0, 0, 0], v0);
    -
    -    goog.vec.vec4d.setFromArray(v0, [0, 0, 0, 0]);
    -    goog.vec.mat4d.getDiagonal(m0, v0, -4);
    -    assertElementsEquals([0, 0, 0, 0], v0);
    -  }
    -
    -  function testSetGetColumn() {
    -    var m0 = goog.vec.mat4d.create();
    -    goog.vec.mat4d.setColumn(m0, 0, [1, 2, 3, 4]);
    -    goog.vec.mat4d.setColumn(m0, 1, [5, 6, 7, 8]);
    -    goog.vec.mat4d.setColumn(m0, 2, [9, 10, 11, 12]);
    -    goog.vec.mat4d.setColumn(m0, 3, [13, 14, 15, 16]);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -
    -    var v0 = [0, 0, 0, 0];
    -    goog.vec.mat4d.getColumn(m0, 0, v0);
    -    assertElementsEquals([1, 2, 3, 4], v0);
    -    goog.vec.mat4d.getColumn(m0, 1, v0);
    -    assertElementsEquals([5, 6, 7, 8], v0);
    -    goog.vec.mat4d.getColumn(m0, 2, v0);
    -    assertElementsEquals([9, 10, 11, 12], v0);
    -    goog.vec.mat4d.getColumn(m0, 3, v0);
    -    assertElementsEquals([13, 14, 15, 16], v0);
    -  }
    -
    -  function testSetGetColumns() {
    -    var m0 = goog.vec.mat4d.create();
    -    goog.vec.mat4d.setColumns(
    -        m0, [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -
    -    var v0 = [0, 0, 0, 0], v1 = [0, 0, 0, 0];
    -    var v2 = [0, 0, 0, 0], v3 = [0, 0, 0, 0];
    -    goog.vec.mat4d.getColumns(m0, v0, v1, v2, v3);
    -    assertElementsEquals([1, 2, 3, 4], v0);
    -    assertElementsEquals([5, 6, 7, 8], v1);
    -    assertElementsEquals([9, 10, 11, 12], v2);
    -    assertElementsEquals([13, 14, 15, 16], v3);
    -  }
    -
    -  function testSetGetRow() {
    -    var m0 = goog.vec.mat4d.create();
    -    goog.vec.mat4d.setRow(m0, 0, [1, 2, 3, 4]);
    -    goog.vec.mat4d.setRow(m0, 1, [5, 6, 7, 8]);
    -    goog.vec.mat4d.setRow(m0, 2, [9, 10, 11, 12]);
    -    goog.vec.mat4d.setRow(m0, 3, [13, 14, 15, 16]);
    -    assertElementsEquals(
    -        [1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16], m0);
    -
    -    var v0 = [0, 0, 0, 0];
    -    goog.vec.mat4d.getRow(m0, 0, v0);
    -    assertElementsEquals([1, 2, 3, 4], v0);
    -    goog.vec.mat4d.getRow(m0, 1, v0);
    -    assertElementsEquals([5, 6, 7, 8], v0);
    -    goog.vec.mat4d.getRow(m0, 2, v0);
    -    assertElementsEquals([9, 10, 11, 12], v0);
    -    goog.vec.mat4d.getRow(m0, 3, v0);
    -    assertElementsEquals([13, 14, 15, 16], v0);
    -  }
    -
    -  function testSetGetRows() {
    -    var m0 = goog.vec.mat4d.create();
    -    goog.vec.mat4d.setRows(
    -        m0, [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]);
    -    assertElementsEquals(
    -        [1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16], m0);
    -
    -    var v0 = [0, 0, 0, 0], v1 = [0, 0, 0, 0];
    -    var v2 = [0, 0, 0, 0], v3 = [0, 0, 0, 0];
    -    goog.vec.mat4d.getRows(m0, v0, v1, v2, v3);
    -    assertElementsEquals([1, 2, 3, 4], v0);
    -    assertElementsEquals([5, 6, 7, 8], v1);
    -    assertElementsEquals([9, 10, 11, 12], v2);
    -    assertElementsEquals([13, 14, 15, 16], v3);
    -  }
    -
    -  function testMakeZero() {
    -    var m0 = goog.vec.mat4d.setFromArray(goog.vec.mat4d.create(), 
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -    goog.vec.mat4d.makeZero(m0);
    -    assertElementsEquals(
    -        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], m0);
    -  }
    -
    -  function testMakeIdentity() {
    -    var m0 = goog.vec.mat4d.create();
    -    goog.vec.mat4d.makeIdentity(m0);
    -    assertElementsEquals(
    -        [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], m0);
    -  }
    -
    -  function testSetGetElement() {
    -    var m0 = goog.vec.mat4d.create();
    -    for (var r = 0; r < 4; r++) {
    -      for (var c = 0; c < 4; c++) {
    -        var value = c * 4 + r + 1;
    -        goog.vec.mat4d.setElement(m0, r, c, value);
    -        assertEquals(value, goog.vec.mat4d.getElement(m0, r, c));
    -      }
    -    }
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -  }
    -
    -  function testAddMat() {
    -    var m0 = goog.vec.mat4d.setFromValues(goog.vec.mat4d.create(), 
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var m1 = goog.vec.mat4d.setFromValues(goog.vec.mat4d.create(), 
    -        9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8);
    -    var m2 = goog.vec.mat4d.create();
    -    goog.vec.mat4d.addMat(m0, m1, m2);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -    assertElementsEquals(
    -        [9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8], m1);
    -    assertElementsEquals(
    -        [10, 12, 14, 16, 18, 20, 22, 24, 10, 12, 14, 16, 18, 20, 22, 24], m2);
    -
    -    goog.vec.mat4d.addMat(m0, m1, m0);
    -    assertElementsEquals(
    -        [9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8], m1);
    -    assertElementsEquals(
    -        [10, 12, 14, 16, 18, 20, 22, 24, 10, 12, 14, 16, 18, 20, 22, 24], m0);
    -  }
    -
    -  function testSubMat() {
    -    var m0 = goog.vec.mat4d.setFromValues(goog.vec.mat4d.create(), 
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var m1 = goog.vec.mat4d.setFromValues(goog.vec.mat4d.create(), 
    -        9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8);
    -    var m2 = goog.vec.mat4d.create();
    -
    -    goog.vec.mat4d.subMat(m0, m1, m2);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -    assertElementsEquals(
    -        [9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8], m1);
    -    assertElementsEquals(
    -        [-8, -8, -8, -8, -8, -8, -8, -8, 8, 8, 8, 8, 8, 8, 8, 8], m2);
    -
    -    goog.vec.mat4d.subMat(m1, m0, m1);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -    assertElementsEquals(
    -        [8, 8, 8, 8, 8, 8, 8, 8, -8, -8, -8, -8, -8, -8, -8, -8], m1);
    -  }
    -
    -  function testMultScalar() {
    -    var m0 = goog.vec.mat4d.setFromValues(goog.vec.mat4d.create(), 
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var m1 = goog.vec.mat4d.create();
    -
    -    goog.vec.mat4d.multScalar(m0, 2, m1);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -    assertElementsEquals(
    -        [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32], m1);
    -
    -    goog.vec.mat4d.multScalar(m0, 5, m0);
    -    assertElementsEquals(
    -        [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80], m0);
    -  }
    -
    -  function testMultMat() {
    -    var m0 = goog.vec.mat4d.setFromValues(goog.vec.mat4d.create(), 
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var m1 = goog.vec.mat4d.setFromValues(goog.vec.mat4d.create(), 
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var m2 = goog.vec.mat4d.create();
    -
    -    goog.vec.mat4d.multMat(m0, m1, m2);
    -    assertElementsEquals(
    -        [90, 100, 110, 120, 202, 228, 254, 280,
    -         314, 356, 398, 440, 426, 484, 542, 600], m2);
    -
    -    goog.vec.mat4d.multScalar(m1, 2, m1);
    -    goog.vec.mat4d.multMat(m1, m0, m1);
    -    assertElementsEquals(
    -        [180, 200, 220, 240, 404, 456, 508, 560,
    -         628, 712, 796, 880, 852, 968, 1084, 1200], m1);
    -  }
    -
    -  function testTranspose() {
    -    var m0 = goog.vec.mat4d.setFromValues(goog.vec.mat4d.create(), 
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var m1 = goog.vec.mat4d.create();
    -    goog.vec.mat4d.transpose(m0, m1);
    -    assertElementsEquals(
    -        [1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16], m1);
    -
    -    goog.vec.mat4d.transpose(m1, m1);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m1);
    -  }
    -
    -  function testDeterminant() {
    -    var m0 = goog.vec.mat4d.setFromValues(goog.vec.mat4d.create(), 
    -        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
    -    assertEquals(0, goog.vec.mat4d.determinant(m0));
    -    assertElementsEquals(
    -        [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], m0);
    -
    -    goog.vec.mat4d.setFromValues(
    -        m0, 1, 2, 3, 4, 2, 3, 4, 1, 3, 4, 1, 2, 4, 1, 2, 3);
    -    assertEquals(160, goog.vec.mat4d.determinant(m0));
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 2, 3, 4, 1, 3, 4, 1, 2, 4, 1, 2, 3], m0);
    -  }
    -
    -  function testInvert() {
    -    var m0 = goog.vec.mat4d.setFromValues(goog.vec.mat4d.create(), 
    -        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
    -    assertFalse(goog.vec.mat4d.invert(m0, m0));
    -    assertElementsEquals(
    -        [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], m0);
    -
    -    goog.vec.mat4d.setFromValues(
    -        m0, 1, 2, 3, 4, 2, 3, 4, 1, 3, 4, 1, 2, 4, 1, 2, 3);
    -    assertTrue(goog.vec.mat4d.invert(m0, m0));
    -    assertElementsRoughlyEqual(
    -        [-0.225, 0.025, 0.025, 0.275, 0.025, 0.025, 0.275, -0.225,
    -         0.025, 0.275, -0.225, 0.025, 0.275, -0.225, 0.025, 0.025], m0,
    -         goog.vec.EPSILON);
    -
    -    goog.vec.mat4d.makeScale(m0, .01, .01, .01);
    -    assertTrue(goog.vec.mat4d.invert(m0, m0));
    -    var m1 = goog.vec.mat4d.create();
    -    goog.vec.mat4d.makeScale(m1, 100, 100, 100);
    -    assertElementsEquals(m1, m0);
    -  }
    -
    -  function testEquals() {
    -    var m0 = goog.vec.mat4d.setFromValues(goog.vec.mat4d.create(), 
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var m1 = goog.vec.mat4d.setFromMat4d(goog.vec.mat4d.create(), m0);
    -    assertTrue(goog.vec.mat4d.equals(m0, m1));
    -    assertTrue(goog.vec.mat4d.equals(m1, m0));
    -    for (var i = 0; i < 16; i++) {
    -      m1[i] = 18;
    -      assertFalse(goog.vec.mat4d.equals(m0, m1));
    -      assertFalse(goog.vec.mat4d.equals(m1, m0));
    -      m1[i] = i + 1;
    -    }
    -  }
    -
    -  function testMultVec3() {
    -    var m0 = goog.vec.mat4d.setFromValues(goog.vec.mat4d.create(), 
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var v0 = [1, 2, 3];
    -    var v1 = [0, 0, 0];
    -
    -    goog.vec.mat4d.multVec3(m0, v0, v1);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals([51, 58, 65], v1);
    -
    -    goog.vec.mat4d.multVec3(m0, v0, v0);
    -    assertElementsEquals([51, 58, 65], v0);
    -  }
    -
    -  function testMultVec3NoTranslate() {
    -    var m0 = goog.vec.mat4d.setFromValues(goog.vec.mat4d.create(), 
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var v0 = [1, 2, 3];
    -    var v1 = [0, 0, 0];
    -
    -    goog.vec.mat4d.multVec3NoTranslate(m0, v0, v1);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals([38, 44, 50], v1);
    -
    -    goog.vec.mat4d.multVec3NoTranslate(m0, v0, v0);
    -    assertElementsEquals([38, 44, 50], v0);
    -  }
    -
    -  function testMultVec3Projective() {
    -    var m0 = goog.vec.mat4d.setFromValues(goog.vec.mat4d.create(), 
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var v0 = [1, 2, 3];
    -    var v1 = [0, 0, 0];
    -    var invw = 1 / 72;
    -
    -    goog.vec.mat4d.multVec3Projective(m0, v0, v1);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals(
    -        [51 * invw, 58 * invw, 65 * invw], v1);
    -
    -    goog.vec.mat4d.multVec3Projective(m0, v0, v0);
    -    assertElementsEquals(
    -        [51 * invw, 58 * invw, 65 * invw], v0);
    -  }
    -
    -  function testMultVec4() {
    -    var m0 = goog.vec.mat4d.setFromValues(goog.vec.mat4d.create(), 
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var v0 = [1, 2, 3, 4];
    -    var v1 = [0, 0, 0, 0];
    -
    -    goog.vec.mat4d.multVec4(m0, v0, v1);
    -    assertElementsEquals([90, 100, 110, 120], v1);
    -    goog.vec.mat4d.multVec4(m0, v0, v0);
    -    assertElementsEquals([90, 100, 110, 120], v0);
    -  }
    -
    -  function testSetValues() {
    -    var a0 = goog.vec.mat4d.create();
    -    assertElementsEquals(
    -        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], a0);
    -    a0 = goog.vec.mat4d.setFromArray(goog.vec.mat4d.create(), 
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], a0);
    -
    -    var a1 = goog.vec.mat4d.create();
    -    goog.vec.mat4d.setDiagonalValues(a1, 1, 2, 3, 4);
    -    assertElementsEquals(
    -        [1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 4], a1);
    -
    -    goog.vec.mat4d.setColumnValues(a1, 0, 2, 3, 4, 5);
    -    goog.vec.mat4d.setColumnValues(a1, 1, 6, 7, 8, 9);
    -    goog.vec.mat4d.setColumnValues(a1, 2, 10, 11, 12, 13);
    -    goog.vec.mat4d.setColumnValues(a1, 3, 14, 15, 16, 1);
    -    assertElementsEquals(
    -        [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1], a1);
    -
    -    goog.vec.mat4d.setRowValues(a1, 0, 1, 5, 9, 13);
    -    goog.vec.mat4d.setRowValues(a1, 1, 2, 6, 10, 14);
    -    goog.vec.mat4d.setRowValues(a1, 2, 3, 7, 11, 15);
    -    goog.vec.mat4d.setRowValues(a1, 3, 4, 8, 12, 16);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], a1);
    -  }
    -
    -  function testMakeTranslate() {
    -    var m0 = goog.vec.mat4d.create();
    -    goog.vec.mat4d.makeTranslate(m0, 3, 4, 5);
    -    assertElementsEquals(
    -        [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 3, 4, 5, 1], m0);
    -  }
    -
    -  function testMakeScale() {
    -    var m0 = goog.vec.mat4d.create();
    -    goog.vec.mat4d.makeScale(m0, 3, 4, 5);
    -    assertElementsEquals(
    -        [3, 0, 0, 0, 0, 4, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1], m0);
    -  }
    -
    -  function testMakeRotate() {
    -    var m0 = goog.vec.mat4d.create();
    -    goog.vec.mat4d.makeRotate(m0, Math.PI / 2, 0, 0, 1);
    -    assertElementsRoughlyEqual(
    -        [0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
    -        m0, goog.vec.EPSILON);
    -
    -    var m1 = goog.vec.mat4d.create();
    -    goog.vec.mat4d.makeRotate(m1, -Math.PI / 4, 0, 0, 1);
    -    goog.vec.mat4d.multMat(m0, m1, m1);
    -    assertElementsRoughlyEqual(
    -        [0.7071068, 0.7071068, 0, 0,
    -         -0.7071068, 0.7071068, 0, 0,
    -         0, 0, 1, 0,
    -         0, 0, 0, 1],
    -        m1, goog.vec.EPSILON);
    -  }
    -
    -  function testMakeRotateX() {
    -    var m0 = goog.vec.mat4d.create();
    -    var m1 = goog.vec.mat4d.create()
    -
    -    goog.vec.mat4d.makeRotateX(m0, Math.PI / 7);
    -    goog.vec.mat4d.makeRotate(m1, Math.PI / 7, 1, 0, 0);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testMakeRotateY() {
    -    var m0 = goog.vec.mat4d.create();
    -    var m1 = goog.vec.mat4d.create()
    -
    -    goog.vec.mat4d.makeRotateY(m0, Math.PI / 7);
    -    goog.vec.mat4d.makeRotate(m1, Math.PI / 7, 0, 1, 0);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testMakeRotateZ() {
    -    var m0 = goog.vec.mat4d.create();
    -    var m1 = goog.vec.mat4d.create()
    -
    -    goog.vec.mat4d.makeRotateZ(m0, Math.PI / 7);
    -    goog.vec.mat4d.makeRotate(m1, Math.PI / 7, 0, 0, 1);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -
    -  function testTranslate() {
    -    var m0 = goog.vec.mat4d.makeIdentity(goog.vec.mat4d.create());
    -    goog.vec.mat4d.translate(m0, 3, 4, 5);
    -    assertElementsEquals(
    -        [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 3, 4, 5, 1], m0);
    -
    -    goog.vec.mat4d.setFromValues(
    -        m0, 1, 2, 3, 4, 2, 3, 4, 1, 3, 4, 1, 2, 4, 1, 2, 3);
    -
    -    var m1 = goog.vec.mat4d.create();
    -    goog.vec.mat4d.makeTranslate(m1, 5, 6, 7);
    -    var m2 = goog.vec.mat4d.create();
    -    goog.vec.mat4d.multMat(m0, m1, m2);
    -    goog.vec.mat4d.translate(m0, 5, 6, 7);
    -    assertElementsEquals(m2, m0);
    -  }
    -
    -  function testScale() {
    -    var m0 = goog.vec.mat4d.makeIdentity(goog.vec.mat4d.create());
    -    goog.vec.mat4d.scale(m0, 3, 4, 5);
    -    assertElementsEquals([3, 0, 0, 0, 0, 4, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1], m0);
    -  }
    -
    -  function testRotate() {
    -    var m0 = goog.vec.mat4d.makeIdentity(goog.vec.mat4d.create());
    -    goog.vec.mat4d.rotate(m0, Math.PI / 2, 0, 0, 1);
    -    assertElementsRoughlyEqual(
    -        [0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
    -        m0, goog.vec.EPSILON);
    -
    -    goog.vec.mat4d.rotate(m0, -Math.PI / 4, 0, 0, 1);
    -    assertElementsRoughlyEqual(
    -        [0.7071068, 0.7071068, 0, 0,
    -         -0.7071068, 0.7071068, 0, 0,
    -         0, 0, 1, 0,
    -         0, 0, 0, 1],
    -        m0, goog.vec.EPSILON);
    -  }
    -
    -  function testRotateX() {
    -    var m0 = goog.vec.mat4d.create();
    -    var m1 = goog.vec.mat4d.setFromArray(goog.vec.mat4d.create(), randommat4d)
    -
    -    goog.vec.mat4d.makeRotateX(m0, Math.PI / 7);
    -    goog.vec.mat4d.multMat(m1, m0, m0);
    -    goog.vec.mat4d.rotateX(m1, Math.PI / 7);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testRotateY() {
    -    var m0 = goog.vec.mat4d.create();
    -    var m1 = goog.vec.mat4d.setFromArray(goog.vec.mat4d.create(), randommat4d)
    -
    -    goog.vec.mat4d.makeRotateY(m0, Math.PI / 7);
    -    goog.vec.mat4d.multMat(m1, m0, m0);
    -    goog.vec.mat4d.rotateY(m1, Math.PI / 7);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testRotateZ() {
    -    var m0 = goog.vec.mat4d.create();
    -    var m1 = goog.vec.mat4d.setFromArray(goog.vec.mat4d.create(), randommat4d)
    -
    -    goog.vec.mat4d.makeRotateZ(m0, Math.PI / 7);
    -    goog.vec.mat4d.multMat(m1, m0, m0);
    -    goog.vec.mat4d.rotateZ(m1, Math.PI / 7);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testGetTranslation() {
    -    var mat = goog.vec.mat4d.setFromArray(goog.vec.mat4d.create(), randommat4d);
    -    var translation = goog.vec.vec3d.create();
    -    goog.vec.mat4d.getTranslation(mat, translation);
    -    assertElementsRoughlyEqual(
    -        [0.59465038776, 0.413479506969, 0.0663217827677],
    -        translation, goog.vec.EPSILON);
    -  }
    -
    -  function testMakeFrustum() {
    -    var m0 = goog.vec.mat4d.create();
    -    goog.vec.mat4d.makeFrustum(m0, -1, 2, -2, 1, .1, 1.1);
    -    assertElementsRoughlyEqual(
    -        [0.06666666, 0, 0, 0,
    -         0, 0.06666666, 0, 0,
    -         0.33333333, -0.33333333, -1.2, -1,
    -         0, 0, -0.22, 0], m0, goog.vec.EPSILON);
    -  }
    -
    -  function testMakePerspective() {
    -    var m0 = goog.vec.mat4d.create();
    -    goog.vec.mat4d.makePerspective(m0, 90 * Math.PI / 180, 2, 0.1, 1.1);
    -    assertElementsRoughlyEqual(
    -        [0.5, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1.2, -1, 0, 0, -0.22, 0],
    -        m0, goog.vec.EPSILON);
    -  }
    -
    -  function testMakeOrtho() {
    -    var m0 = goog.vec.mat4d.create();
    -    goog.vec.mat4d.makeOrtho(m0, -1, 2, -2, 1, 0.1, 1.1);
    -    assertElementsRoughlyEqual(
    -        [0.6666666, 0, 0, 0,
    -         0, 0.6666666, 0, 0,
    -         0, 0, -2, 0,
    -         -0.333333, 0.3333333, -1.2, 1], m0, goog.vec.EPSILON);
    -
    -  }
    -
    -  function testMakeEulerZXZ() {
    -    var m0 = goog.vec.mat4d.create();
    -    var roll = 0.200982 * 2 * Math.PI;
    -    var tilt = 0.915833 * Math.PI;
    -    var yaw = 0.839392 * 2 * Math.PI;
    -
    -    goog.vec.mat4d.makeRotate(m0, roll, 0, 0, 1);
    -    goog.vec.mat4d.rotate(m0, tilt, 1, 0, 0);
    -    goog.vec.mat4d.rotate(m0, yaw, 0, 0, 1);
    -
    -    var m1 = goog.vec.mat4d.create();
    -    goog.vec.mat4d.makeEulerZXZ(m1, roll, tilt, yaw);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -
    -
    -    var euler = [0, 0, 0];
    -    goog.vec.mat4d.toEulerZXZ(m0, euler);
    -
    -    assertRoughlyEquals(roll, euler[0], goog.vec.EPSILON);
    -    assertRoughlyEquals(tilt, euler[1], goog.vec.EPSILON);
    -    assertRoughlyEquals(yaw, euler[2], goog.vec.EPSILON);
    -
    -    // Test negative tilt now.
    -    goog.vec.mat4d.makeRotate(m0, roll, 0, 0, 1);
    -    goog.vec.mat4d.rotate(m0, -tilt, 1, 0, 0);
    -    goog.vec.mat4d.rotate(m0, yaw, 0, 0, 1);
    -
    -    goog.vec.mat4d.makeEulerZXZ(m1, roll, -tilt, yaw);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -
    -    var euler = [0, 0, 0];
    -    goog.vec.mat4d.toEulerZXZ(m0, euler, true);
    -
    -    assertRoughlyEquals(roll, euler[0], goog.vec.EPSILON);
    -    assertRoughlyEquals(-tilt, euler[1], goog.vec.EPSILON);
    -    assertRoughlyEquals(yaw, euler[2], goog.vec.EPSILON);
    -  }
    -
    -  function testEulerZXZExtrema() {
    -    var m0 = goog.vec.mat4d.setFromArray(goog.vec.mat4d.create(), 
    -    [1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1]);
    -    var m1 = goog.vec.mat4d.setFromArray(goog.vec.mat4d.create(), 
    -    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
    -
    -    var euler = [0, 0, 0];
    -    goog.vec.mat4d.toEulerZXZ(m0, euler);
    -    assertElementsRoughlyEqual(
    -        [Math.PI, Math.PI / 2, Math.PI], euler, goog.vec.EPSILON);
    -    goog.vec.mat4d.makeEulerZXZ(m1, euler[0], euler[1], euler[2]);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testLookAt() {
    -    var viewMatrix = goog.vec.mat4d.create();
    -    goog.vec.mat4d.makeLookAt(
    -      viewMatrix, [0, 0, 0], [1, 0, 0], [0, 1, 0]);
    -    assertElementsRoughlyEqual(
    -      [0, 0, -1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1], viewMatrix,
    -      goog.vec.EPSILON);
    -  }
    -
    -  function testToLookAt() {
    -    // This test does not use the default precision goog.vec.EPSILON due to
    -    // precision issues in some browsers leading to flaky tests.
    -    var EPSILON = 1e-4;
    -
    -    var eyeExp = [0, 0, 0];
    -    var fwdExp = [1, 0, 0];
    -    var upExp = [0, 1, 0];
    -
    -    var centerExp = [0, 0, 0];
    -    goog.vec.vec3d.add(eyeExp, fwdExp, centerExp);
    -
    -    var view = goog.vec.mat4d.create();
    -    goog.vec.mat4d.makeLookAt(view, eyeExp, centerExp, upExp);
    -
    -    var eyeRes = [0, 0, 0];
    -    var fwdRes = [0, 0, 0];
    -    var upRes = [0, 0, 0];
    -    goog.vec.mat4d.toLookAt(view, eyeRes, fwdRes, upRes);
    -    assertElementsRoughlyEqual(eyeExp, eyeRes, EPSILON);
    -    assertElementsRoughlyEqual(fwdExp, fwdRes, EPSILON);
    -    assertElementsRoughlyEqual(upExp, upRes, EPSILON);
    -  }
    -
    -  function testLookAtDecomposition() {
    -    // This test does not use the default precision goog.vec.EPSILON due to
    -    // precision issues in some browsers leading to flaky tests.
    -    var EPSILON = 1e-4;
    -
    -    var viewExp = goog.vec.mat4d.create();
    -    var viewRes = goog.vec.mat4d.create();
    -
    -    // Get a valid set of random vectors eye, forward, up by decomposing
    -    // a random matrix into a set of lookAt vectors.
    -    var tmp = goog.vec.mat4d.setFromArray(goog.vec.mat4d.create(), randommat4d);
    -    var eyeExp = [0, 0, 0];
    -    var fwdExp = [0, 0, 0];
    -    var upExp = [0, 0, 0];
    -    var centerExp = [0, 0, 0];
    -    // Project the random matrix into a real modelview matrix.
    -    goog.vec.mat4d.toLookAt(tmp, eyeExp, fwdExp, upExp);
    -    goog.vec.vec3d.add(eyeExp, fwdExp, centerExp);
    -
    -    // Compute the expected modelview matrix from a set of valid random vectors.
    -    goog.vec.mat4d.makeLookAt(viewExp, eyeExp, centerExp, upExp);
    -
    -    var eyeRes = [0, 0, 0];
    -    var fwdRes = [0, 0, 0];
    -    var upRes = [0, 0, 0];
    -    var centerRes = [0, 0, 0];
    -    goog.vec.mat4d.toLookAt(viewExp, eyeRes, fwdRes, upRes);
    -    goog.vec.vec3d.add(eyeRes, fwdRes, centerRes);
    -
    -    goog.vec.mat4d.makeLookAt(viewRes, eyeRes, centerRes, upRes);
    -
    -    assertElementsRoughlyEqual(eyeExp, eyeRes, EPSILON);
    -    assertElementsRoughlyEqual(fwdExp, fwdRes, EPSILON);
    -    assertElementsRoughlyEqual(upExp, upRes, EPSILON);
    -    assertElementsRoughlyEqual(viewExp, viewRes, EPSILON);
    -  }
    -
    -</script>
    -</body>
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/mat4f.js b/src/database/third_party/closure-library/closure/goog/vec/mat4f.js
    deleted file mode 100644
    index 666438f589c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/mat4f.js
    +++ /dev/null
    @@ -1,1769 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -//                                                                           //
    -// Any edits to this file must be applied to mat4d.js by running:            //
    -//   swap_type.sh mat4f.js > mat4d.js                                        //
    -//                                                                           //
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -
    -
    -/**
    - * @fileoverview Provides functions for operating on 4x4 float (32bit)
    - * matrices.  The matrices are stored in column-major order.
    - *
    - * The last parameter will typically be the output matrix and an
    - * object can be both an input and output parameter to all methods except
    - * where noted.
    - *
    - * See the README for notes about the design and structure of the API
    - * (especially related to performance).
    - *
    - */
    -goog.provide('goog.vec.mat4f');
    -goog.provide('goog.vec.mat4f.Type');
    -
    -goog.require('goog.vec');
    -goog.require('goog.vec.vec3f');
    -goog.require('goog.vec.vec4f');
    -
    -
    -/** @typedef {goog.vec.Float32} */ goog.vec.mat4f.Type;
    -
    -
    -/**
    - * Creates a mat4f with all elements initialized to zero.
    - *
    - * @return {!goog.vec.mat4f.Type} The new mat4f.
    - */
    -goog.vec.mat4f.create = function() {
    -  return new Float32Array(16);
    -};
    -
    -
    -/**
    - * Initializes the matrix from the set of values. Note the values supplied are
    - * in column major order.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix to receive the
    - *     values.
    - * @param {number} v00 The values at (0, 0).
    - * @param {number} v10 The values at (1, 0).
    - * @param {number} v20 The values at (2, 0).
    - * @param {number} v30 The values at (3, 0).
    - * @param {number} v01 The values at (0, 1).
    - * @param {number} v11 The values at (1, 1).
    - * @param {number} v21 The values at (2, 1).
    - * @param {number} v31 The values at (3, 1).
    - * @param {number} v02 The values at (0, 2).
    - * @param {number} v12 The values at (1, 2).
    - * @param {number} v22 The values at (2, 2).
    - * @param {number} v32 The values at (3, 2).
    - * @param {number} v03 The values at (0, 3).
    - * @param {number} v13 The values at (1, 3).
    - * @param {number} v23 The values at (2, 3).
    - * @param {number} v33 The values at (3, 3).
    - * @return {!goog.vec.mat4f.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4f.setFromValues = function(
    -    mat, v00, v10, v20, v30, v01, v11, v21, v31, v02, v12, v22, v32,
    -    v03, v13, v23, v33) {
    -  mat[0] = v00;
    -  mat[1] = v10;
    -  mat[2] = v20;
    -  mat[3] = v30;
    -  mat[4] = v01;
    -  mat[5] = v11;
    -  mat[6] = v21;
    -  mat[7] = v31;
    -  mat[8] = v02;
    -  mat[9] = v12;
    -  mat[10] = v22;
    -  mat[11] = v32;
    -  mat[12] = v03;
    -  mat[13] = v13;
    -  mat[14] = v23;
    -  mat[15] = v33;
    -  return mat;
    -};
    -
    -
    -/**
    - * Initializes mat4f mat from mat4f src.
    - *
    - * @param {goog.vec.mat4f.Type} mat The destination matrix.
    - * @param {goog.vec.mat4f.Type} src The source matrix.
    - * @return {!goog.vec.mat4f.Type} Return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4f.setFromMat4f = function(mat, src) {
    -  mat[0] = src[0];
    -  mat[1] = src[1];
    -  mat[2] = src[2];
    -  mat[3] = src[3];
    -  mat[4] = src[4];
    -  mat[5] = src[5];
    -  mat[6] = src[6];
    -  mat[7] = src[7];
    -  mat[8] = src[8];
    -  mat[9] = src[9];
    -  mat[10] = src[10];
    -  mat[11] = src[11];
    -  mat[12] = src[12];
    -  mat[13] = src[13];
    -  mat[14] = src[14];
    -  mat[15] = src[15];
    -  return mat;
    -};
    -
    -
    -/**
    - * Initializes mat4f mat from mat4d src (typed as a Float64Array to
    - * avoid circular goog.requires).
    - *
    - * @param {goog.vec.mat4f.Type} mat The destination matrix.
    - * @param {Float64Array} src The source matrix.
    - * @return {!goog.vec.mat4f.Type} Return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4f.setFromMat4d = function(mat, src) {
    -  mat[0] = src[0];
    -  mat[1] = src[1];
    -  mat[2] = src[2];
    -  mat[3] = src[3];
    -  mat[4] = src[4];
    -  mat[5] = src[5];
    -  mat[6] = src[6];
    -  mat[7] = src[7];
    -  mat[8] = src[8];
    -  mat[9] = src[9];
    -  mat[10] = src[10];
    -  mat[11] = src[11];
    -  mat[12] = src[12];
    -  mat[13] = src[13];
    -  mat[14] = src[14];
    -  mat[15] = src[15];
    -  return mat;
    -};
    -
    -
    -/**
    - * Initializes mat4f mat from Array src.
    - *
    - * @param {goog.vec.mat4f.Type} mat The destination matrix.
    - * @param {Array<number>} src The source matrix.
    - * @return {!goog.vec.mat4f.Type} Return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4f.setFromArray = function(mat, src) {
    -  mat[0] = src[0];
    -  mat[1] = src[1];
    -  mat[2] = src[2];
    -  mat[3] = src[3];
    -  mat[4] = src[4];
    -  mat[5] = src[5];
    -  mat[6] = src[6];
    -  mat[7] = src[7];
    -  mat[8] = src[8];
    -  mat[9] = src[9];
    -  mat[10] = src[10];
    -  mat[11] = src[11];
    -  mat[12] = src[12];
    -  mat[13] = src[13];
    -  mat[14] = src[14];
    -  mat[15] = src[15];
    -  return mat;
    -};
    -
    -
    -/**
    - * Retrieves the element at the requested row and column.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix containing the value to
    - *     retrieve.
    - * @param {number} row The row index.
    - * @param {number} column The column index.
    - * @return {number} The element value at the requested row, column indices.
    - */
    -goog.vec.mat4f.getElement = function(mat, row, column) {
    -  return mat[row + column * 4];
    -};
    -
    -
    -/**
    - * Sets the element at the requested row and column.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix containing the value to
    - *     retrieve.
    - * @param {number} row The row index.
    - * @param {number} column The column index.
    - * @param {number} value The value to set at the requested row, column.
    - * @return {!goog.vec.mat4f.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4f.setElement = function(mat, row, column, value) {
    -  mat[row + column * 4] = value;
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the diagonal values of the matrix from the given values.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix to receive the values.
    - * @param {number} v00 The values for (0, 0).
    - * @param {number} v11 The values for (1, 1).
    - * @param {number} v22 The values for (2, 2).
    - * @param {number} v33 The values for (3, 3).
    - * @return {!goog.vec.mat4f.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4f.setDiagonalValues = function(mat, v00, v11, v22, v33) {
    -  mat[0] = v00;
    -  mat[5] = v11;
    -  mat[10] = v22;
    -  mat[15] = v33;
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the diagonal values of the matrix from the given vector.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix to receive the values.
    - * @param {goog.vec.vec4f.Type} vec The vector containing the values.
    - * @return {!goog.vec.mat4f.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4f.setDiagonal = function(mat, vec) {
    -  mat[0] = vec[0];
    -  mat[5] = vec[1];
    -  mat[10] = vec[2];
    -  mat[15] = vec[3];
    -  return mat;
    -};
    -
    -
    -/**
    - * Gets the diagonal values of the matrix into the given vector.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix containing the values.
    - * @param {goog.vec.vec4f.Type} vec The vector to receive the values.
    - * @param {number=} opt_diagonal Which diagonal to get. A value of 0 selects the
    - *     main diagonal, a positive number selects a super diagonal and a negative
    - *     number selects a sub diagonal.
    - * @return {goog.vec.vec4f.Type} return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4f.getDiagonal = function(mat, vec, opt_diagonal) {
    -  if (!opt_diagonal) {
    -    // This is the most common case, so we avoid the for loop.
    -    vec[0] = mat[0];
    -    vec[1] = mat[5];
    -    vec[2] = mat[10];
    -    vec[3] = mat[15];
    -  } else {
    -    var offset = opt_diagonal > 0 ? 4 * opt_diagonal : -opt_diagonal;
    -    for (var i = 0; i < 4 - Math.abs(opt_diagonal); i++) {
    -      vec[i] = mat[offset + 5 * i];
    -    }
    -  }
    -  return vec;
    -};
    -
    -
    -/**
    - * Sets the specified column with the supplied values.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix to recieve the values.
    - * @param {number} column The column index to set the values on.
    - * @param {number} v0 The value for row 0.
    - * @param {number} v1 The value for row 1.
    - * @param {number} v2 The value for row 2.
    - * @param {number} v3 The value for row 3.
    - * @return {!goog.vec.mat4f.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4f.setColumnValues = function(mat, column, v0, v1, v2, v3) {
    -  var i = column * 4;
    -  mat[i] = v0;
    -  mat[i + 1] = v1;
    -  mat[i + 2] = v2;
    -  mat[i + 3] = v3;
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the specified column with the value from the supplied vector.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix to receive the values.
    - * @param {number} column The column index to set the values on.
    - * @param {goog.vec.vec4f.Type} vec The vector of elements for the column.
    - * @return {!goog.vec.mat4f.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4f.setColumn = function(mat, column, vec) {
    -  var i = column * 4;
    -  mat[i] = vec[0];
    -  mat[i + 1] = vec[1];
    -  mat[i + 2] = vec[2];
    -  mat[i + 3] = vec[3];
    -  return mat;
    -};
    -
    -
    -/**
    - * Retrieves the specified column from the matrix into the given vector.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix supplying the values.
    - * @param {number} column The column to get the values from.
    - * @param {goog.vec.vec4f.Type} vec The vector of elements to
    - *     receive the column.
    - * @return {!goog.vec.vec4f.Type} return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4f.getColumn = function(mat, column, vec) {
    -  var i = column * 4;
    -  vec[0] = mat[i];
    -  vec[1] = mat[i + 1];
    -  vec[2] = mat[i + 2];
    -  vec[3] = mat[i + 3];
    -  return vec;
    -};
    -
    -
    -/**
    - * Sets the columns of the matrix from the given vectors.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix to receive the values.
    - * @param {goog.vec.vec4f.Type} vec0 The values for column 0.
    - * @param {goog.vec.vec4f.Type} vec1 The values for column 1.
    - * @param {goog.vec.vec4f.Type} vec2 The values for column 2.
    - * @param {goog.vec.vec4f.Type} vec3 The values for column 3.
    - * @return {!goog.vec.mat4f.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4f.setColumns = function(mat, vec0, vec1, vec2, vec3) {
    -  mat[0] = vec0[0];
    -  mat[1] = vec0[1];
    -  mat[2] = vec0[2];
    -  mat[3] = vec0[3];
    -  mat[4] = vec1[0];
    -  mat[5] = vec1[1];
    -  mat[6] = vec1[2];
    -  mat[7] = vec1[3];
    -  mat[8] = vec2[0];
    -  mat[9] = vec2[1];
    -  mat[10] = vec2[2];
    -  mat[11] = vec2[3];
    -  mat[12] = vec3[0];
    -  mat[13] = vec3[1];
    -  mat[14] = vec3[2];
    -  mat[15] = vec3[3];
    -  return mat;
    -};
    -
    -
    -/**
    - * Retrieves the column values from the given matrix into the given vectors.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix supplying the columns.
    - * @param {goog.vec.vec4f.Type} vec0 The vector to receive column 0.
    - * @param {goog.vec.vec4f.Type} vec1 The vector to receive column 1.
    - * @param {goog.vec.vec4f.Type} vec2 The vector to receive column 2.
    - * @param {goog.vec.vec4f.Type} vec3 The vector to receive column 3.
    - */
    -goog.vec.mat4f.getColumns = function(mat, vec0, vec1, vec2, vec3) {
    -  vec0[0] = mat[0];
    -  vec0[1] = mat[1];
    -  vec0[2] = mat[2];
    -  vec0[3] = mat[3];
    -  vec1[0] = mat[4];
    -  vec1[1] = mat[5];
    -  vec1[2] = mat[6];
    -  vec1[3] = mat[7];
    -  vec2[0] = mat[8];
    -  vec2[1] = mat[9];
    -  vec2[2] = mat[10];
    -  vec2[3] = mat[11];
    -  vec3[0] = mat[12];
    -  vec3[1] = mat[13];
    -  vec3[2] = mat[14];
    -  vec3[3] = mat[15];
    -};
    -
    -
    -/**
    - * Sets the row values from the supplied values.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix to receive the values.
    - * @param {number} row The index of the row to receive the values.
    - * @param {number} v0 The value for column 0.
    - * @param {number} v1 The value for column 1.
    - * @param {number} v2 The value for column 2.
    - * @param {number} v3 The value for column 3.
    - * @return {!goog.vec.mat4f.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4f.setRowValues = function(mat, row, v0, v1, v2, v3) {
    -  mat[row] = v0;
    -  mat[row + 4] = v1;
    -  mat[row + 8] = v2;
    -  mat[row + 12] = v3;
    -  return mat;
    -};
    -
    -
    -/**
    - * Sets the row values from the supplied vector.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix to receive the row values.
    - * @param {number} row The index of the row.
    - * @param {goog.vec.vec4f.Type} vec The vector containing the values.
    - * @return {!goog.vec.mat4f.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4f.setRow = function(mat, row, vec) {
    -  mat[row] = vec[0];
    -  mat[row + 4] = vec[1];
    -  mat[row + 8] = vec[2];
    -  mat[row + 12] = vec[3];
    -  return mat;
    -};
    -
    -
    -/**
    - * Retrieves the row values into the given vector.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix supplying the values.
    - * @param {number} row The index of the row supplying the values.
    - * @param {goog.vec.vec4f.Type} vec The vector to receive the row.
    - * @return {!goog.vec.vec4f.Type} return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4f.getRow = function(mat, row, vec) {
    -  vec[0] = mat[row];
    -  vec[1] = mat[row + 4];
    -  vec[2] = mat[row + 8];
    -  vec[3] = mat[row + 12];
    -  return vec;
    -};
    -
    -
    -/**
    - * Sets the rows of the matrix from the supplied vectors.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix to receive the values.
    - * @param {goog.vec.vec4f.Type} vec0 The values for row 0.
    - * @param {goog.vec.vec4f.Type} vec1 The values for row 1.
    - * @param {goog.vec.vec4f.Type} vec2 The values for row 2.
    - * @param {goog.vec.vec4f.Type} vec3 The values for row 3.
    - * @return {!goog.vec.mat4f.Type} return mat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4f.setRows = function(mat, vec0, vec1, vec2, vec3) {
    -  mat[0] = vec0[0];
    -  mat[1] = vec1[0];
    -  mat[2] = vec2[0];
    -  mat[3] = vec3[0];
    -  mat[4] = vec0[1];
    -  mat[5] = vec1[1];
    -  mat[6] = vec2[1];
    -  mat[7] = vec3[1];
    -  mat[8] = vec0[2];
    -  mat[9] = vec1[2];
    -  mat[10] = vec2[2];
    -  mat[11] = vec3[2];
    -  mat[12] = vec0[3];
    -  mat[13] = vec1[3];
    -  mat[14] = vec2[3];
    -  mat[15] = vec3[3];
    -  return mat;
    -};
    -
    -
    -/**
    - * Retrieves the rows of the matrix into the supplied vectors.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix to supply the values.
    - * @param {goog.vec.vec4f.Type} vec0 The vector to receive row 0.
    - * @param {goog.vec.vec4f.Type} vec1 The vector to receive row 1.
    - * @param {goog.vec.vec4f.Type} vec2 The vector to receive row 2.
    - * @param {goog.vec.vec4f.Type} vec3 The vector to receive row 3.
    - */
    -goog.vec.mat4f.getRows = function(mat, vec0, vec1, vec2, vec3) {
    -  vec0[0] = mat[0];
    -  vec1[0] = mat[1];
    -  vec2[0] = mat[2];
    -  vec3[0] = mat[3];
    -  vec0[1] = mat[4];
    -  vec1[1] = mat[5];
    -  vec2[1] = mat[6];
    -  vec3[1] = mat[7];
    -  vec0[2] = mat[8];
    -  vec1[2] = mat[9];
    -  vec2[2] = mat[10];
    -  vec3[2] = mat[11];
    -  vec0[3] = mat[12];
    -  vec1[3] = mat[13];
    -  vec2[3] = mat[14];
    -  vec3[3] = mat[15];
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix the zero matrix.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix.
    - * @return {!goog.vec.mat4f.Type} return mat so operations can be chained.
    - */
    -goog.vec.mat4f.makeZero = function(mat) {
    -  mat[0] = 0;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 0;
    -  mat[5] = 0;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = 0;
    -  mat[9] = 0;
    -  mat[10] = 0;
    -  mat[11] = 0;
    -  mat[12] = 0;
    -  mat[13] = 0;
    -  mat[14] = 0;
    -  mat[15] = 0;
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix the identity matrix.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix.
    - * @return {!goog.vec.mat4f.Type} return mat so operations can be chained.
    - */
    -goog.vec.mat4f.makeIdentity = function(mat) {
    -  mat[0] = 1;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 0;
    -  mat[5] = 1;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = 0;
    -  mat[9] = 0;
    -  mat[10] = 1;
    -  mat[11] = 0;
    -  mat[12] = 0;
    -  mat[13] = 0;
    -  mat[14] = 0;
    -  mat[15] = 1;
    -  return mat;
    -};
    -
    -
    -/**
    - * Performs a per-component addition of the matrix mat0 and mat1, storing
    - * the result into resultMat.
    - *
    - * @param {goog.vec.mat4f.Type} mat0 The first addend.
    - * @param {goog.vec.mat4f.Type} mat1 The second addend.
    - * @param {goog.vec.mat4f.Type} resultMat The matrix to
    - *     receive the results (may be either mat0 or mat1).
    - * @return {!goog.vec.mat4f.Type} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4f.addMat = function(mat0, mat1, resultMat) {
    -  resultMat[0] = mat0[0] + mat1[0];
    -  resultMat[1] = mat0[1] + mat1[1];
    -  resultMat[2] = mat0[2] + mat1[2];
    -  resultMat[3] = mat0[3] + mat1[3];
    -  resultMat[4] = mat0[4] + mat1[4];
    -  resultMat[5] = mat0[5] + mat1[5];
    -  resultMat[6] = mat0[6] + mat1[6];
    -  resultMat[7] = mat0[7] + mat1[7];
    -  resultMat[8] = mat0[8] + mat1[8];
    -  resultMat[9] = mat0[9] + mat1[9];
    -  resultMat[10] = mat0[10] + mat1[10];
    -  resultMat[11] = mat0[11] + mat1[11];
    -  resultMat[12] = mat0[12] + mat1[12];
    -  resultMat[13] = mat0[13] + mat1[13];
    -  resultMat[14] = mat0[14] + mat1[14];
    -  resultMat[15] = mat0[15] + mat1[15];
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Performs a per-component subtraction of the matrix mat0 and mat1,
    - * storing the result into resultMat.
    - *
    - * @param {goog.vec.mat4f.Type} mat0 The minuend.
    - * @param {goog.vec.mat4f.Type} mat1 The subtrahend.
    - * @param {goog.vec.mat4f.Type} resultMat The matrix to receive
    - *     the results (may be either mat0 or mat1).
    - * @return {!goog.vec.mat4f.Type} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4f.subMat = function(mat0, mat1, resultMat) {
    -  resultMat[0] = mat0[0] - mat1[0];
    -  resultMat[1] = mat0[1] - mat1[1];
    -  resultMat[2] = mat0[2] - mat1[2];
    -  resultMat[3] = mat0[3] - mat1[3];
    -  resultMat[4] = mat0[4] - mat1[4];
    -  resultMat[5] = mat0[5] - mat1[5];
    -  resultMat[6] = mat0[6] - mat1[6];
    -  resultMat[7] = mat0[7] - mat1[7];
    -  resultMat[8] = mat0[8] - mat1[8];
    -  resultMat[9] = mat0[9] - mat1[9];
    -  resultMat[10] = mat0[10] - mat1[10];
    -  resultMat[11] = mat0[11] - mat1[11];
    -  resultMat[12] = mat0[12] - mat1[12];
    -  resultMat[13] = mat0[13] - mat1[13];
    -  resultMat[14] = mat0[14] - mat1[14];
    -  resultMat[15] = mat0[15] - mat1[15];
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Multiplies matrix mat with the given scalar, storing the result
    - * into resultMat.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix.
    - * @param {number} scalar The scalar value to multiply to each element of mat.
    - * @param {goog.vec.mat4f.Type} resultMat The matrix to receive
    - *     the results (may be mat).
    - * @return {!goog.vec.mat4f.Type} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4f.multScalar = function(mat, scalar, resultMat) {
    -  resultMat[0] = mat[0] * scalar;
    -  resultMat[1] = mat[1] * scalar;
    -  resultMat[2] = mat[2] * scalar;
    -  resultMat[3] = mat[3] * scalar;
    -  resultMat[4] = mat[4] * scalar;
    -  resultMat[5] = mat[5] * scalar;
    -  resultMat[6] = mat[6] * scalar;
    -  resultMat[7] = mat[7] * scalar;
    -  resultMat[8] = mat[8] * scalar;
    -  resultMat[9] = mat[9] * scalar;
    -  resultMat[10] = mat[10] * scalar;
    -  resultMat[11] = mat[11] * scalar;
    -  resultMat[12] = mat[12] * scalar;
    -  resultMat[13] = mat[13] * scalar;
    -  resultMat[14] = mat[14] * scalar;
    -  resultMat[15] = mat[15] * scalar;
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Multiplies the two matrices mat0 and mat1 using matrix multiplication,
    - * storing the result into resultMat.
    - *
    - * @param {goog.vec.mat4f.Type} mat0 The first (left hand) matrix.
    - * @param {goog.vec.mat4f.Type} mat1 The second (right hand) matrix.
    - * @param {goog.vec.mat4f.Type} resultMat The matrix to receive
    - *     the results (may be either mat0 or mat1).
    - * @return {!goog.vec.mat4f.Type} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4f.multMat = function(mat0, mat1, resultMat) {
    -  var a00 = mat0[0], a10 = mat0[1], a20 = mat0[2], a30 = mat0[3];
    -  var a01 = mat0[4], a11 = mat0[5], a21 = mat0[6], a31 = mat0[7];
    -  var a02 = mat0[8], a12 = mat0[9], a22 = mat0[10], a32 = mat0[11];
    -  var a03 = mat0[12], a13 = mat0[13], a23 = mat0[14], a33 = mat0[15];
    -
    -  var b00 = mat1[0], b10 = mat1[1], b20 = mat1[2], b30 = mat1[3];
    -  var b01 = mat1[4], b11 = mat1[5], b21 = mat1[6], b31 = mat1[7];
    -  var b02 = mat1[8], b12 = mat1[9], b22 = mat1[10], b32 = mat1[11];
    -  var b03 = mat1[12], b13 = mat1[13], b23 = mat1[14], b33 = mat1[15];
    -
    -  resultMat[0] = a00 * b00 + a01 * b10 + a02 * b20 + a03 * b30;
    -  resultMat[1] = a10 * b00 + a11 * b10 + a12 * b20 + a13 * b30;
    -  resultMat[2] = a20 * b00 + a21 * b10 + a22 * b20 + a23 * b30;
    -  resultMat[3] = a30 * b00 + a31 * b10 + a32 * b20 + a33 * b30;
    -
    -  resultMat[4] = a00 * b01 + a01 * b11 + a02 * b21 + a03 * b31;
    -  resultMat[5] = a10 * b01 + a11 * b11 + a12 * b21 + a13 * b31;
    -  resultMat[6] = a20 * b01 + a21 * b11 + a22 * b21 + a23 * b31;
    -  resultMat[7] = a30 * b01 + a31 * b11 + a32 * b21 + a33 * b31;
    -
    -  resultMat[8] = a00 * b02 + a01 * b12 + a02 * b22 + a03 * b32;
    -  resultMat[9] = a10 * b02 + a11 * b12 + a12 * b22 + a13 * b32;
    -  resultMat[10] = a20 * b02 + a21 * b12 + a22 * b22 + a23 * b32;
    -  resultMat[11] = a30 * b02 + a31 * b12 + a32 * b22 + a33 * b32;
    -
    -  resultMat[12] = a00 * b03 + a01 * b13 + a02 * b23 + a03 * b33;
    -  resultMat[13] = a10 * b03 + a11 * b13 + a12 * b23 + a13 * b33;
    -  resultMat[14] = a20 * b03 + a21 * b13 + a22 * b23 + a23 * b33;
    -  resultMat[15] = a30 * b03 + a31 * b13 + a32 * b23 + a33 * b33;
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Transposes the given matrix mat storing the result into resultMat.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix to transpose.
    - * @param {goog.vec.mat4f.Type} resultMat The matrix to receive
    - *     the results (may be mat).
    - * @return {!goog.vec.mat4f.Type} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4f.transpose = function(mat, resultMat) {
    -  if (resultMat == mat) {
    -    var a10 = mat[1], a20 = mat[2], a30 = mat[3];
    -    var a21 = mat[6], a31 = mat[7];
    -    var a32 = mat[11];
    -    resultMat[1] = mat[4];
    -    resultMat[2] = mat[8];
    -    resultMat[3] = mat[12];
    -    resultMat[4] = a10;
    -    resultMat[6] = mat[9];
    -    resultMat[7] = mat[13];
    -    resultMat[8] = a20;
    -    resultMat[9] = a21;
    -    resultMat[11] = mat[14];
    -    resultMat[12] = a30;
    -    resultMat[13] = a31;
    -    resultMat[14] = a32;
    -  } else {
    -    resultMat[0] = mat[0];
    -    resultMat[1] = mat[4];
    -    resultMat[2] = mat[8];
    -    resultMat[3] = mat[12];
    -
    -    resultMat[4] = mat[1];
    -    resultMat[5] = mat[5];
    -    resultMat[6] = mat[9];
    -    resultMat[7] = mat[13];
    -
    -    resultMat[8] = mat[2];
    -    resultMat[9] = mat[6];
    -    resultMat[10] = mat[10];
    -    resultMat[11] = mat[14];
    -
    -    resultMat[12] = mat[3];
    -    resultMat[13] = mat[7];
    -    resultMat[14] = mat[11];
    -    resultMat[15] = mat[15];
    -  }
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Computes the determinant of the matrix.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix to compute the matrix for.
    - * @return {number} The determinant of the matrix.
    - */
    -goog.vec.mat4f.determinant = function(mat) {
    -  var m00 = mat[0], m10 = mat[1], m20 = mat[2], m30 = mat[3];
    -  var m01 = mat[4], m11 = mat[5], m21 = mat[6], m31 = mat[7];
    -  var m02 = mat[8], m12 = mat[9], m22 = mat[10], m32 = mat[11];
    -  var m03 = mat[12], m13 = mat[13], m23 = mat[14], m33 = mat[15];
    -
    -  var a0 = m00 * m11 - m10 * m01;
    -  var a1 = m00 * m21 - m20 * m01;
    -  var a2 = m00 * m31 - m30 * m01;
    -  var a3 = m10 * m21 - m20 * m11;
    -  var a4 = m10 * m31 - m30 * m11;
    -  var a5 = m20 * m31 - m30 * m21;
    -  var b0 = m02 * m13 - m12 * m03;
    -  var b1 = m02 * m23 - m22 * m03;
    -  var b2 = m02 * m33 - m32 * m03;
    -  var b3 = m12 * m23 - m22 * m13;
    -  var b4 = m12 * m33 - m32 * m13;
    -  var b5 = m22 * m33 - m32 * m23;
    -
    -  return a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0;
    -};
    -
    -
    -/**
    - * Computes the inverse of mat storing the result into resultMat. If the
    - * inverse is defined, this function returns true, false otherwise.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix to invert.
    - * @param {goog.vec.mat4f.Type} resultMat The matrix to receive
    - *     the result (may be mat).
    - * @return {boolean} True if the inverse is defined. If false is returned,
    - *     resultMat is not modified.
    - */
    -goog.vec.mat4f.invert = function(mat, resultMat) {
    -  var m00 = mat[0], m10 = mat[1], m20 = mat[2], m30 = mat[3];
    -  var m01 = mat[4], m11 = mat[5], m21 = mat[6], m31 = mat[7];
    -  var m02 = mat[8], m12 = mat[9], m22 = mat[10], m32 = mat[11];
    -  var m03 = mat[12], m13 = mat[13], m23 = mat[14], m33 = mat[15];
    -
    -  var a0 = m00 * m11 - m10 * m01;
    -  var a1 = m00 * m21 - m20 * m01;
    -  var a2 = m00 * m31 - m30 * m01;
    -  var a3 = m10 * m21 - m20 * m11;
    -  var a4 = m10 * m31 - m30 * m11;
    -  var a5 = m20 * m31 - m30 * m21;
    -  var b0 = m02 * m13 - m12 * m03;
    -  var b1 = m02 * m23 - m22 * m03;
    -  var b2 = m02 * m33 - m32 * m03;
    -  var b3 = m12 * m23 - m22 * m13;
    -  var b4 = m12 * m33 - m32 * m13;
    -  var b5 = m22 * m33 - m32 * m23;
    -
    -  var det = a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0;
    -  if (det == 0) {
    -    return false;
    -  }
    -
    -  var idet = 1.0 / det;
    -  resultMat[0] = (m11 * b5 - m21 * b4 + m31 * b3) * idet;
    -  resultMat[1] = (-m10 * b5 + m20 * b4 - m30 * b3) * idet;
    -  resultMat[2] = (m13 * a5 - m23 * a4 + m33 * a3) * idet;
    -  resultMat[3] = (-m12 * a5 + m22 * a4 - m32 * a3) * idet;
    -  resultMat[4] = (-m01 * b5 + m21 * b2 - m31 * b1) * idet;
    -  resultMat[5] = (m00 * b5 - m20 * b2 + m30 * b1) * idet;
    -  resultMat[6] = (-m03 * a5 + m23 * a2 - m33 * a1) * idet;
    -  resultMat[7] = (m02 * a5 - m22 * a2 + m32 * a1) * idet;
    -  resultMat[8] = (m01 * b4 - m11 * b2 + m31 * b0) * idet;
    -  resultMat[9] = (-m00 * b4 + m10 * b2 - m30 * b0) * idet;
    -  resultMat[10] = (m03 * a4 - m13 * a2 + m33 * a0) * idet;
    -  resultMat[11] = (-m02 * a4 + m12 * a2 - m32 * a0) * idet;
    -  resultMat[12] = (-m01 * b3 + m11 * b1 - m21 * b0) * idet;
    -  resultMat[13] = (m00 * b3 - m10 * b1 + m20 * b0) * idet;
    -  resultMat[14] = (-m03 * a3 + m13 * a1 - m23 * a0) * idet;
    -  resultMat[15] = (m02 * a3 - m12 * a1 + m22 * a0) * idet;
    -  return true;
    -};
    -
    -
    -/**
    - * Returns true if the components of mat0 are equal to the components of mat1.
    - *
    - * @param {goog.vec.mat4f.Type} mat0 The first matrix.
    - * @param {goog.vec.mat4f.Type} mat1 The second matrix.
    - * @return {boolean} True if the the two matrices are equivalent.
    - */
    -goog.vec.mat4f.equals = function(mat0, mat1) {
    -  return mat0.length == mat1.length &&
    -      mat0[0] == mat1[0] &&
    -      mat0[1] == mat1[1] &&
    -      mat0[2] == mat1[2] &&
    -      mat0[3] == mat1[3] &&
    -      mat0[4] == mat1[4] &&
    -      mat0[5] == mat1[5] &&
    -      mat0[6] == mat1[6] &&
    -      mat0[7] == mat1[7] &&
    -      mat0[8] == mat1[8] &&
    -      mat0[9] == mat1[9] &&
    -      mat0[10] == mat1[10] &&
    -      mat0[11] == mat1[11] &&
    -      mat0[12] == mat1[12] &&
    -      mat0[13] == mat1[13] &&
    -      mat0[14] == mat1[14] &&
    -      mat0[15] == mat1[15];
    -};
    -
    -
    -/**
    - * Transforms the given vector with the given matrix storing the resulting,
    - * transformed vector into resultVec. The input vector is multiplied against the
    - * upper 3x4 matrix omitting the projective component.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix supplying the transformation.
    - * @param {goog.vec.vec3f.Type} vec The 3 element vector to transform.
    - * @param {goog.vec.vec3f.Type} resultVec The 3 element vector to
    - *     receive the results (may be vec).
    - * @return {!goog.vec.vec3f.Type} return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4f.multVec3 = function(mat, vec, resultVec) {
    -  var x = vec[0], y = vec[1], z = vec[2];
    -  resultVec[0] = x * mat[0] + y * mat[4] + z * mat[8] + mat[12];
    -  resultVec[1] = x * mat[1] + y * mat[5] + z * mat[9] + mat[13];
    -  resultVec[2] = x * mat[2] + y * mat[6] + z * mat[10] + mat[14];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Transforms the given vector with the given matrix storing the resulting,
    - * transformed vector into resultVec. The input vector is multiplied against the
    - * upper 3x3 matrix omitting the projective component and translation
    - * components.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix supplying the transformation.
    - * @param {goog.vec.vec3f.Type} vec The 3 element vector to transform.
    - * @param {goog.vec.vec3f.Type} resultVec The 3 element vector to
    - *     receive the results (may be vec).
    - * @return {!goog.vec.vec3f.Type} return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4f.multVec3NoTranslate = function(mat, vec, resultVec) {
    -  var x = vec[0], y = vec[1], z = vec[2];
    -  resultVec[0] = x * mat[0] + y * mat[4] + z * mat[8];
    -  resultVec[1] = x * mat[1] + y * mat[5] + z * mat[9];
    -  resultVec[2] = x * mat[2] + y * mat[6] + z * mat[10];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Transforms the given vector with the given matrix storing the resulting,
    - * transformed vector into resultVec. The input vector is multiplied against the
    - * full 4x4 matrix with the homogeneous divide applied to reduce the 4 element
    - * vector to a 3 element vector.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix supplying the transformation.
    - * @param {goog.vec.vec3f.Type} vec The 3 element vector to transform.
    - * @param {goog.vec.vec3f.Type} resultVec The 3 element vector
    - *     to receive the results (may be vec).
    - * @return {!goog.vec.vec3f.Type} return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4f.multVec3Projective = function(mat, vec, resultVec) {
    -  var x = vec[0], y = vec[1], z = vec[2];
    -  var invw = 1 / (x * mat[3] + y * mat[7] + z * mat[11] + mat[15]);
    -  resultVec[0] = (x * mat[0] + y * mat[4] + z * mat[8] + mat[12]) * invw;
    -  resultVec[1] = (x * mat[1] + y * mat[5] + z * mat[9] + mat[13]) * invw;
    -  resultVec[2] = (x * mat[2] + y * mat[6] + z * mat[10] + mat[14]) * invw;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Transforms the given vector with the given matrix storing the resulting,
    - * transformed vector into resultVec.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix supplying the transformation.
    - * @param {goog.vec.vec4f.Type} vec The vector to transform.
    - * @param {goog.vec.vec4f.Type} resultVec The vector to
    - *     receive the results (may be vec).
    - * @return {!goog.vec.vec4f.Type} return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4f.multVec4 = function(mat, vec, resultVec) {
    -  var x = vec[0], y = vec[1], z = vec[2], w = vec[3];
    -  resultVec[0] = x * mat[0] + y * mat[4] + z * mat[8] + w * mat[12];
    -  resultVec[1] = x * mat[1] + y * mat[5] + z * mat[9] + w * mat[13];
    -  resultVec[2] = x * mat[2] + y * mat[6] + z * mat[10] + w * mat[14];
    -  resultVec[3] = x * mat[3] + y * mat[7] + z * mat[11] + w * mat[15];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix a translation matrix with x, y and z
    - * translation factors.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix.
    - * @param {number} x The translation along the x axis.
    - * @param {number} y The translation along the y axis.
    - * @param {number} z The translation along the z axis.
    - * @return {!goog.vec.mat4f.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4f.makeTranslate = function(mat, x, y, z) {
    -  mat[0] = 1;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 0;
    -  mat[5] = 1;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = 0;
    -  mat[9] = 0;
    -  mat[10] = 1;
    -  mat[11] = 0;
    -  mat[12] = x;
    -  mat[13] = y;
    -  mat[14] = z;
    -  mat[15] = 1;
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix as a scale matrix with x, y and z scale factors.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix.
    - * @param {number} x The scale along the x axis.
    - * @param {number} y The scale along the y axis.
    - * @param {number} z The scale along the z axis.
    - * @return {!goog.vec.mat4f.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4f.makeScale = function(mat, x, y, z) {
    -  mat[0] = x;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 0;
    -  mat[5] = y;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = 0;
    -  mat[9] = 0;
    -  mat[10] = z;
    -  mat[11] = 0;
    -  mat[12] = 0;
    -  mat[13] = 0;
    -  mat[14] = 0;
    -  mat[15] = 1;
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix a rotation matrix with the given rotation
    - * angle about the axis defined by the vector (ax, ay, az).
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix.
    - * @param {number} angle The rotation angle in radians.
    - * @param {number} ax The x component of the rotation axis.
    - * @param {number} ay The y component of the rotation axis.
    - * @param {number} az The z component of the rotation axis.
    - * @return {!goog.vec.mat4f.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4f.makeRotate = function(mat, angle, ax, ay, az) {
    -  var c = Math.cos(angle);
    -  var d = 1 - c;
    -  var s = Math.sin(angle);
    -
    -  mat[0] = ax * ax * d + c;
    -  mat[1] = ax * ay * d + az * s;
    -  mat[2] = ax * az * d - ay * s;
    -  mat[3] = 0;
    -  mat[4] = ax * ay * d - az * s;
    -  mat[5] = ay * ay * d + c;
    -  mat[6] = ay * az * d + ax * s;
    -  mat[7] = 0;
    -  mat[8] = ax * az * d + ay * s;
    -  mat[9] = ay * az * d - ax * s;
    -  mat[10] = az * az * d + c;
    -  mat[11] = 0;
    -  mat[12] = 0;
    -  mat[13] = 0;
    -  mat[14] = 0;
    -  mat[15] = 1;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix a rotation matrix with the given rotation
    - * angle about the X axis.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix.
    - * @param {number} angle The rotation angle in radians.
    - * @return {!goog.vec.mat4f.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4f.makeRotateX = function(mat, angle) {
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[0] = 1;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 0;
    -  mat[5] = c;
    -  mat[6] = s;
    -  mat[7] = 0;
    -  mat[8] = 0;
    -  mat[9] = -s;
    -  mat[10] = c;
    -  mat[11] = 0;
    -  mat[12] = 0;
    -  mat[13] = 0;
    -  mat[14] = 0;
    -  mat[15] = 1;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix a rotation matrix with the given rotation
    - * angle about the Y axis.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix.
    - * @param {number} angle The rotation angle in radians.
    - * @return {!goog.vec.mat4f.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4f.makeRotateY = function(mat, angle) {
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[0] = c;
    -  mat[1] = 0;
    -  mat[2] = -s;
    -  mat[3] = 0;
    -  mat[4] = 0;
    -  mat[5] = 1;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = s;
    -  mat[9] = 0;
    -  mat[10] = c;
    -  mat[11] = 0;
    -  mat[12] = 0;
    -  mat[13] = 0;
    -  mat[14] = 0;
    -  mat[15] = 1;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix a rotation matrix with the given rotation
    - * angle about the Z axis.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix.
    - * @param {number} angle The rotation angle in radians.
    - * @return {!goog.vec.mat4f.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4f.makeRotateZ = function(mat, angle) {
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[0] = c;
    -  mat[1] = s;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = -s;
    -  mat[5] = c;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = 0;
    -  mat[9] = 0;
    -  mat[10] = 1;
    -  mat[11] = 0;
    -  mat[12] = 0;
    -  mat[13] = 0;
    -  mat[14] = 0;
    -  mat[15] = 1;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix a perspective projection matrix.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix.
    - * @param {number} left The coordinate of the left clipping plane.
    - * @param {number} right The coordinate of the right clipping plane.
    - * @param {number} bottom The coordinate of the bottom clipping plane.
    - * @param {number} top The coordinate of the top clipping plane.
    - * @param {number} near The distance to the near clipping plane.
    - * @param {number} far The distance to the far clipping plane.
    - * @return {!goog.vec.mat4f.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4f.makeFrustum = function(
    -    mat, left, right, bottom, top, near, far) {
    -  var x = (2 * near) / (right - left);
    -  var y = (2 * near) / (top - bottom);
    -  var a = (right + left) / (right - left);
    -  var b = (top + bottom) / (top - bottom);
    -  var c = -(far + near) / (far - near);
    -  var d = -(2 * far * near) / (far - near);
    -
    -  mat[0] = x;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 0;
    -  mat[5] = y;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = a;
    -  mat[9] = b;
    -  mat[10] = c;
    -  mat[11] = -1;
    -  mat[12] = 0;
    -  mat[13] = 0;
    -  mat[14] = d;
    -  mat[15] = 0;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Makse the given 4x4 matrix  perspective projection matrix given a
    - * field of view and aspect ratio.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix.
    - * @param {number} fovy The field of view along the y (vertical) axis in
    - *     radians.
    - * @param {number} aspect The x (width) to y (height) aspect ratio.
    - * @param {number} near The distance to the near clipping plane.
    - * @param {number} far The distance to the far clipping plane.
    - * @return {goog.vec.mat4f.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4f.makePerspective = function(mat, fovy, aspect, near, far) {
    -  var angle = fovy / 2;
    -  var dz = far - near;
    -  var sinAngle = Math.sin(angle);
    -  if (dz == 0 || sinAngle == 0 || aspect == 0) {
    -    return mat;
    -  }
    -
    -  var cot = Math.cos(angle) / sinAngle;
    -
    -  mat[0] = cot / aspect;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 0;
    -  mat[5] = cot;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = 0;
    -  mat[9] = 0;
    -  mat[10] = -(far + near) / dz;
    -  mat[11] = -1;
    -  mat[12] = 0;
    -  mat[13] = 0;
    -  mat[14] = -(2 * near * far) / dz;
    -  mat[15] = 0;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix an orthographic projection matrix.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix.
    - * @param {number} left The coordinate of the left clipping plane.
    - * @param {number} right The coordinate of the right clipping plane.
    - * @param {number} bottom The coordinate of the bottom clipping plane.
    - * @param {number} top The coordinate of the top clipping plane.
    - * @param {number} near The distance to the near clipping plane.
    - * @param {number} far The distance to the far clipping plane.
    - * @return {!goog.vec.mat4f.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4f.makeOrtho = function(mat, left, right, bottom, top, near, far) {
    -  var x = 2 / (right - left);
    -  var y = 2 / (top - bottom);
    -  var z = -2 / (far - near);
    -  var a = -(right + left) / (right - left);
    -  var b = -(top + bottom) / (top - bottom);
    -  var c = -(far + near) / (far - near);
    -
    -  mat[0] = x;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 0;
    -  mat[5] = y;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = 0;
    -  mat[9] = 0;
    -  mat[10] = z;
    -  mat[11] = 0;
    -  mat[12] = a;
    -  mat[13] = b;
    -  mat[14] = c;
    -  mat[15] = 1;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix a modelview matrix of a camera so that
    - * the camera is 'looking at' the given center point.
    - *
    - * Note that unlike most other goog.vec functions where we inline
    - * everything, this function does not inline various goog.vec
    - * functions.  This makes the code more readable, but somewhat
    - * less efficient.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix.
    - * @param {goog.vec.vec3f.Type} eyePt The position of the eye point
    - *     (camera origin).
    - * @param {goog.vec.vec3f.Type} centerPt The point to aim the camera at.
    - * @param {goog.vec.vec3f.Type} worldUpVec The vector that identifies
    - *     the up direction for the camera.
    - * @return {goog.vec.mat4f.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4f.makeLookAt = function(mat, eyePt, centerPt, worldUpVec) {
    -  // Compute the direction vector from the eye point to the center point and
    -  // normalize.
    -  var fwdVec = goog.vec.mat4f.tmpvec4f_[0];
    -  goog.vec.vec3f.subtract(centerPt, eyePt, fwdVec);
    -  goog.vec.vec3f.normalize(fwdVec, fwdVec);
    -  fwdVec[3] = 0;
    -
    -  // Compute the side vector from the forward vector and the input up vector.
    -  var sideVec = goog.vec.mat4f.tmpvec4f_[1];
    -  goog.vec.vec3f.cross(fwdVec, worldUpVec, sideVec);
    -  goog.vec.vec3f.normalize(sideVec, sideVec);
    -  sideVec[3] = 0;
    -
    -  // Now the up vector to form the orthonormal basis.
    -  var upVec = goog.vec.mat4f.tmpvec4f_[2];
    -  goog.vec.vec3f.cross(sideVec, fwdVec, upVec);
    -  goog.vec.vec3f.normalize(upVec, upVec);
    -  upVec[3] = 0;
    -
    -  // Update the view matrix with the new orthonormal basis and position the
    -  // camera at the given eye point.
    -  goog.vec.vec3f.negate(fwdVec, fwdVec);
    -  goog.vec.mat4f.setRow(mat, 0, sideVec);
    -  goog.vec.mat4f.setRow(mat, 1, upVec);
    -  goog.vec.mat4f.setRow(mat, 2, fwdVec);
    -  goog.vec.mat4f.setRowValues(mat, 3, 0, 0, 0, 1);
    -  goog.vec.mat4f.translate(
    -      mat, -eyePt[0], -eyePt[1], -eyePt[2]);
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Decomposes a matrix into the lookAt vectors eyePt, fwdVec and worldUpVec.
    - * The matrix represents the modelview matrix of a camera. It is the inverse
    - * of lookAt except for the output of the fwdVec instead of centerPt.
    - * The centerPt itself cannot be recovered from a modelview matrix.
    - *
    - * Note that unlike most other goog.vec functions where we inline
    - * everything, this function does not inline various goog.vec
    - * functions.  This makes the code more readable, but somewhat
    - * less efficient.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix.
    - * @param {goog.vec.vec3f.Type} eyePt The position of the eye point
    - *     (camera origin).
    - * @param {goog.vec.vec3f.Type} fwdVec The vector describing where
    - *     the camera points to.
    - * @param {goog.vec.vec3f.Type} worldUpVec The vector that
    - *     identifies the up direction for the camera.
    - * @return {boolean} True if the method succeeds, false otherwise.
    - *     The method can only fail if the inverse of viewMatrix is not defined.
    - */
    -goog.vec.mat4f.toLookAt = function(mat, eyePt, fwdVec, worldUpVec) {
    -  // Get eye of the camera.
    -  var matInverse = goog.vec.mat4f.tmpmat4f_[0];
    -  if (!goog.vec.mat4f.invert(mat, matInverse)) {
    -    // The input matrix does not have a valid inverse.
    -    return false;
    -  }
    -
    -  if (eyePt) {
    -    eyePt[0] = matInverse[12];
    -    eyePt[1] = matInverse[13];
    -    eyePt[2] = matInverse[14];
    -  }
    -
    -  // Get forward vector from the definition of lookAt.
    -  if (fwdVec || worldUpVec) {
    -    if (!fwdVec) {
    -      fwdVec = goog.vec.mat4f.tmpvec3f_[0];
    -    }
    -    fwdVec[0] = -mat[2];
    -    fwdVec[1] = -mat[6];
    -    fwdVec[2] = -mat[10];
    -    // Normalize forward vector.
    -    goog.vec.vec3f.normalize(fwdVec, fwdVec);
    -  }
    -
    -  if (worldUpVec) {
    -    // Get side vector from the definition of gluLookAt.
    -    var side = goog.vec.mat4f.tmpvec3f_[1];
    -    side[0] = mat[0];
    -    side[1] = mat[4];
    -    side[2] = mat[8];
    -    // Compute up vector as a up = side x forward.
    -    goog.vec.vec3f.cross(side, fwdVec, worldUpVec);
    -    // Normalize up vector.
    -    goog.vec.vec3f.normalize(worldUpVec, worldUpVec);
    -  }
    -  return true;
    -};
    -
    -
    -/**
    - * Makes the given 4x4 matrix a rotation matrix given Euler angles using
    - * the ZXZ convention.
    - * Given the euler angles [theta1, theta2, theta3], the rotation is defined as
    - * rotation = rotation_z(theta1) * rotation_x(theta2) * rotation_z(theta3),
    - * with theta1 in [0, 2 * pi], theta2 in [0, pi] and theta3 in [0, 2 * pi].
    - * rotation_x(theta) means rotation around the X axis of theta radians,
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix.
    - * @param {number} theta1 The angle of rotation around the Z axis in radians.
    - * @param {number} theta2 The angle of rotation around the X axis in radians.
    - * @param {number} theta3 The angle of rotation around the Z axis in radians.
    - * @return {!goog.vec.mat4f.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4f.makeEulerZXZ = function(mat, theta1, theta2, theta3) {
    -  var c1 = Math.cos(theta1);
    -  var s1 = Math.sin(theta1);
    -
    -  var c2 = Math.cos(theta2);
    -  var s2 = Math.sin(theta2);
    -
    -  var c3 = Math.cos(theta3);
    -  var s3 = Math.sin(theta3);
    -
    -  mat[0] = c1 * c3 - c2 * s1 * s3;
    -  mat[1] = c2 * c1 * s3 + c3 * s1;
    -  mat[2] = s3 * s2;
    -  mat[3] = 0;
    -
    -  mat[4] = -c1 * s3 - c3 * c2 * s1;
    -  mat[5] = c1 * c2 * c3 - s1 * s3;
    -  mat[6] = c3 * s2;
    -  mat[7] = 0;
    -
    -  mat[8] = s2 * s1;
    -  mat[9] = -c1 * s2;
    -  mat[10] = c2;
    -  mat[11] = 0;
    -
    -  mat[12] = 0;
    -  mat[13] = 0;
    -  mat[14] = 0;
    -  mat[15] = 1;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Decomposes a rotation matrix into Euler angles using the ZXZ convention so
    - * that rotation = rotation_z(theta1) * rotation_x(theta2) * rotation_z(theta3),
    - * with theta1 in [0, 2 * pi], theta2 in [0, pi] and theta3 in [0, 2 * pi].
    - * rotation_x(theta) means rotation around the X axis of theta radians.
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix.
    - * @param {goog.vec.vec3f.Type} euler The ZXZ Euler angles in
    - *     radians as [theta1, theta2, theta3].
    - * @param {boolean=} opt_theta2IsNegative Whether theta2 is in [-pi, 0] instead
    - *     of the default [0, pi].
    - * @return {!goog.vec.vec4f.Type} return euler so that operations can be
    - *     chained together.
    - */
    -goog.vec.mat4f.toEulerZXZ = function(mat, euler, opt_theta2IsNegative) {
    -  // There is an ambiguity in the sign of sinTheta2 because of the sqrt.
    -  var sinTheta2 = Math.sqrt(mat[2] * mat[2] + mat[6] * mat[6]);
    -
    -  // By default we explicitely constrain theta2 to be in [0, pi],
    -  // so sinTheta2 is always positive. We can change the behavior and specify
    -  // theta2 to be negative in [-pi, 0] with opt_Theta2IsNegative.
    -  var signTheta2 = opt_theta2IsNegative ? -1 : 1;
    -
    -  if (sinTheta2 > goog.vec.EPSILON) {
    -    euler[2] = Math.atan2(mat[2] * signTheta2, mat[6] * signTheta2);
    -    euler[1] = Math.atan2(sinTheta2 * signTheta2, mat[10]);
    -    euler[0] = Math.atan2(mat[8] * signTheta2, -mat[9] * signTheta2);
    -  } else {
    -    // There is also an arbitrary choice for theta1 = 0 or theta2 = 0 here.
    -    // We assume theta1 = 0 as some applications do not allow the camera to roll
    -    // (i.e. have theta1 != 0).
    -    euler[0] = 0;
    -    euler[1] = Math.atan2(sinTheta2 * signTheta2, mat[10]);
    -    euler[2] = Math.atan2(mat[1], mat[0]);
    -  }
    -
    -  // Atan2 outputs angles in [-pi, pi] so we bring them back to [0, 2 * pi].
    -  euler[0] = (euler[0] + Math.PI * 2) % (Math.PI * 2);
    -  euler[2] = (euler[2] + Math.PI * 2) % (Math.PI * 2);
    -  // For theta2 we want the angle to be in [0, pi] or [-pi, 0] depending on
    -  // signTheta2.
    -  euler[1] = ((euler[1] * signTheta2 + Math.PI * 2) % (Math.PI * 2)) *
    -      signTheta2;
    -
    -  return euler;
    -};
    -
    -
    -/**
    - * Translates the given matrix by x,y,z.  Equvialent to:
    - * goog.vec.mat4f.multMat(
    - *     mat,
    - *     goog.vec.mat4f.makeTranslate(goog.vec.mat4f.create(), x, y, z),
    - *     mat);
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix.
    - * @param {number} x The translation along the x axis.
    - * @param {number} y The translation along the y axis.
    - * @param {number} z The translation along the z axis.
    - * @return {!goog.vec.mat4f.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4f.translate = function(mat, x, y, z) {
    -  mat[12] += mat[0] * x + mat[4] * y + mat[8] * z;
    -  mat[13] += mat[1] * x + mat[5] * y + mat[9] * z;
    -  mat[14] += mat[2] * x + mat[6] * y + mat[10] * z;
    -  mat[15] += mat[3] * x + mat[7] * y + mat[11] * z;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Scales the given matrix by x,y,z.  Equivalent to:
    - * goog.vec.mat4f.multMat(
    - *     mat,
    - *     goog.vec.mat4f.makeScale(goog.vec.mat4f.create(), x, y, z),
    - *     mat);
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix.
    - * @param {number} x The x scale factor.
    - * @param {number} y The y scale factor.
    - * @param {number} z The z scale factor.
    - * @return {!goog.vec.mat4f.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4f.scale = function(mat, x, y, z) {
    -  mat[0] = mat[0] * x;
    -  mat[1] = mat[1] * x;
    -  mat[2] = mat[2] * x;
    -  mat[3] = mat[3] * x;
    -  mat[4] = mat[4] * y;
    -  mat[5] = mat[5] * y;
    -  mat[6] = mat[6] * y;
    -  mat[7] = mat[7] * y;
    -  mat[8] = mat[8] * z;
    -  mat[9] = mat[9] * z;
    -  mat[10] = mat[10] * z;
    -  mat[11] = mat[11] * z;
    -  mat[12] = mat[12];
    -  mat[13] = mat[13];
    -  mat[14] = mat[14];
    -  mat[15] = mat[15];
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Rotate the given matrix by angle about the x,y,z axis.  Equivalent to:
    - * goog.vec.mat4f.multMat(
    - *     mat,
    - *     goog.vec.mat4f.makeRotate(goog.vec.mat4f.create(), angle, x, y, z),
    - *     mat);
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix.
    - * @param {number} angle The angle in radians.
    - * @param {number} x The x component of the rotation axis.
    - * @param {number} y The y component of the rotation axis.
    - * @param {number} z The z component of the rotation axis.
    - * @return {!goog.vec.mat4f.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4f.rotate = function(mat, angle, x, y, z) {
    -  var m00 = mat[0], m10 = mat[1], m20 = mat[2], m30 = mat[3];
    -  var m01 = mat[4], m11 = mat[5], m21 = mat[6], m31 = mat[7];
    -  var m02 = mat[8], m12 = mat[9], m22 = mat[10], m32 = mat[11];
    -
    -  var cosAngle = Math.cos(angle);
    -  var sinAngle = Math.sin(angle);
    -  var diffCosAngle = 1 - cosAngle;
    -  var r00 = x * x * diffCosAngle + cosAngle;
    -  var r10 = x * y * diffCosAngle + z * sinAngle;
    -  var r20 = x * z * diffCosAngle - y * sinAngle;
    -
    -  var r01 = x * y * diffCosAngle - z * sinAngle;
    -  var r11 = y * y * diffCosAngle + cosAngle;
    -  var r21 = y * z * diffCosAngle + x * sinAngle;
    -
    -  var r02 = x * z * diffCosAngle + y * sinAngle;
    -  var r12 = y * z * diffCosAngle - x * sinAngle;
    -  var r22 = z * z * diffCosAngle + cosAngle;
    -
    -  mat[0] = m00 * r00 + m01 * r10 + m02 * r20;
    -  mat[1] = m10 * r00 + m11 * r10 + m12 * r20;
    -  mat[2] = m20 * r00 + m21 * r10 + m22 * r20;
    -  mat[3] = m30 * r00 + m31 * r10 + m32 * r20;
    -  mat[4] = m00 * r01 + m01 * r11 + m02 * r21;
    -  mat[5] = m10 * r01 + m11 * r11 + m12 * r21;
    -  mat[6] = m20 * r01 + m21 * r11 + m22 * r21;
    -  mat[7] = m30 * r01 + m31 * r11 + m32 * r21;
    -  mat[8] = m00 * r02 + m01 * r12 + m02 * r22;
    -  mat[9] = m10 * r02 + m11 * r12 + m12 * r22;
    -  mat[10] = m20 * r02 + m21 * r12 + m22 * r22;
    -  mat[11] = m30 * r02 + m31 * r12 + m32 * r22;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Rotate the given matrix by angle about the x axis.  Equivalent to:
    - * goog.vec.mat4f.multMat(
    - *     mat,
    - *     goog.vec.mat4f.makeRotateX(goog.vec.mat4f.create(), angle),
    - *     mat);
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix.
    - * @param {number} angle The angle in radians.
    - * @return {!goog.vec.mat4f.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4f.rotateX = function(mat, angle) {
    -  var m01 = mat[4], m11 = mat[5], m21 = mat[6], m31 = mat[7];
    -  var m02 = mat[8], m12 = mat[9], m22 = mat[10], m32 = mat[11];
    -
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[4] = m01 * c + m02 * s;
    -  mat[5] = m11 * c + m12 * s;
    -  mat[6] = m21 * c + m22 * s;
    -  mat[7] = m31 * c + m32 * s;
    -  mat[8] = m01 * -s + m02 * c;
    -  mat[9] = m11 * -s + m12 * c;
    -  mat[10] = m21 * -s + m22 * c;
    -  mat[11] = m31 * -s + m32 * c;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Rotate the given matrix by angle about the y axis.  Equivalent to:
    - * goog.vec.mat4f.multMat(
    - *     mat,
    - *     goog.vec.mat4f.makeRotateY(goog.vec.mat4f.create(), angle),
    - *     mat);
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix.
    - * @param {number} angle The angle in radians.
    - * @return {!goog.vec.mat4f.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4f.rotateY = function(mat, angle) {
    -  var m00 = mat[0], m10 = mat[1], m20 = mat[2], m30 = mat[3];
    -  var m02 = mat[8], m12 = mat[9], m22 = mat[10], m32 = mat[11];
    -
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[0] = m00 * c + m02 * -s;
    -  mat[1] = m10 * c + m12 * -s;
    -  mat[2] = m20 * c + m22 * -s;
    -  mat[3] = m30 * c + m32 * -s;
    -  mat[8] = m00 * s + m02 * c;
    -  mat[9] = m10 * s + m12 * c;
    -  mat[10] = m20 * s + m22 * c;
    -  mat[11] = m30 * s + m32 * c;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Rotate the given matrix by angle about the z axis.  Equivalent to:
    - * goog.vec.mat4f.multMat(
    - *     mat,
    - *     goog.vec.mat4f.makeRotateZ(goog.vec.mat4f.create(), angle),
    - *     mat);
    - *
    - * @param {goog.vec.mat4f.Type} mat The matrix.
    - * @param {number} angle The angle in radians.
    - * @return {!goog.vec.mat4f.Type} return mat so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4f.rotateZ = function(mat, angle) {
    -  var m00 = mat[0], m10 = mat[1], m20 = mat[2], m30 = mat[3];
    -  var m01 = mat[4], m11 = mat[5], m21 = mat[6], m31 = mat[7];
    -
    -  var c = Math.cos(angle);
    -  var s = Math.sin(angle);
    -
    -  mat[0] = m00 * c + m01 * s;
    -  mat[1] = m10 * c + m11 * s;
    -  mat[2] = m20 * c + m21 * s;
    -  mat[3] = m30 * c + m31 * s;
    -  mat[4] = m00 * -s + m01 * c;
    -  mat[5] = m10 * -s + m11 * c;
    -  mat[6] = m20 * -s + m21 * c;
    -  mat[7] = m30 * -s + m31 * c;
    -
    -  return mat;
    -};
    -
    -
    -/**
    - * Retrieves the translation component of the transformation matrix.
    - *
    - * @param {goog.vec.mat4f.Type} mat The transformation matrix.
    - * @param {goog.vec.vec3f.Type} translation The vector for storing the
    - *     result.
    - * @return {!goog.vec.vec3f.Type} return translation so that operations can be
    - *     chained.
    - */
    -goog.vec.mat4f.getTranslation = function(mat, translation) {
    -  translation[0] = mat[12];
    -  translation[1] = mat[13];
    -  translation[2] = mat[14];
    -  return translation;
    -};
    -
    -
    -/**
    - * @type {Array<goog.vec.vec3f.Type>}
    - * @private
    - */
    -goog.vec.mat4f.tmpvec3f_ = [
    -  goog.vec.vec3f.create(),
    -  goog.vec.vec3f.create()
    -];
    -
    -
    -/**
    - * @type {Array<goog.vec.vec4f.Type>}
    - * @private
    - */
    -goog.vec.mat4f.tmpvec4f_ = [
    -  goog.vec.vec4f.create(),
    -  goog.vec.vec4f.create(),
    -  goog.vec.vec4f.create()
    -];
    -
    -
    -/**
    - * @type {Array<goog.vec.mat4f.Type>}
    - * @private
    - */
    -goog.vec.mat4f.tmpmat4f_ = [
    -  goog.vec.mat4f.create()
    -];
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/mat4f_test.html b/src/database/third_party/closure-library/closure/goog/vec/mat4f_test.html
    deleted file mode 100644
    index 67c8b68b983..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/mat4f_test.html
    +++ /dev/null
    @@ -1,738 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -//                                                                           //
    -// Any edits to this file must be applied to mat4d_test.html by running:     //
    -//   swap_type.sh mat4f_test.html > mat4d_test.html                          //
    -//                                                                           //
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.vec.mat4f</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.vec.mat4f');
    -  goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -  var randommat4f = goog.vec.mat4f.setFromValues(goog.vec.mat4f.create(),
    -      0.8025078773498535,
    -      0.7559120655059814,
    -      0.15274643898010254,
    -      0.19196106493473053,
    -      0.0890120416879654,
    -      0.15422114729881287,
    -      0.09754583984613419,
    -      0.44862601161003113,
    -      0.9196512699127197,
    -      0.5310639142990112,
    -      0.8962187170982361,
    -      0.280601441860199,
    -      0.594650387763977,
    -      0.4134795069694519,
    -      0.06632178276777267,
    -      0.8837796449661255);
    -
    -  function testCreate() {
    -    var m = goog.vec.mat4f.create();
    -    assertElementsEquals([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], m);
    -  }
    -
    -  function testSet() {
    -    var m0 = goog.vec.mat4f.create();
    -    var m1 = goog.vec.mat4f.setFromArray(goog.vec.mat4f.create(), 
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
    -    goog.vec.mat4f.setFromArray(m0, m1);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -
    -    goog.vec.mat4f.setFromValues(
    -        m0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17);
    -    assertElementsEquals(
    -        [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17], m0);
    -  }
    -
    -  function testSetDiagonal() {
    -    var m0 = goog.vec.mat4f.create();
    -    goog.vec.mat4f.setDiagonalValues(m0, 1, 2, 3, 4);
    -    assertElementsEquals(
    -        [1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 4], m0);
    -
    -    goog.vec.mat4f.setDiagonal(m0, [4, 5, 6, 7]);
    -    assertElementsEquals(
    -        [4, 0, 0, 0, 0, 5, 0, 0, 0, 0, 6, 0, 0, 0, 0, 7], m0);
    -  }
    -
    -  function testGetDiagonal() {
    -    var v0 = goog.vec.vec4f.create();
    -    var m0 = goog.vec.mat4f.create();
    -    goog.vec.mat4f.setFromArray(
    -        m0, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
    -
    -    goog.vec.mat4f.getDiagonal(m0, v0);
    -    assertElementsEquals([0, 5, 10, 15], v0);
    -
    -    goog.vec.vec4f.setFromArray(v0, [0, 0, 0, 0]);
    -    goog.vec.mat4f.getDiagonal(m0, v0, 1);
    -    assertElementsEquals([4, 9, 14, 0], v0);
    -
    -    goog.vec.vec4f.setFromArray(v0, [0, 0, 0, 0]);
    -    goog.vec.mat4f.getDiagonal(m0, v0, 2);
    -    assertElementsEquals([8, 13, 0, 0], v0);
    -
    -    goog.vec.vec4f.setFromArray(v0, [0, 0, 0, 0]);
    -    goog.vec.mat4f.getDiagonal(m0, v0, 3);
    -    assertElementsEquals([12, 0, 0, 0], v0);
    -
    -    goog.vec.vec4f.setFromArray(v0, [0, 0, 0, 0]);
    -    goog.vec.mat4f.getDiagonal(m0, v0, 4);
    -    assertElementsEquals([0, 0, 0, 0], v0);
    -
    -    goog.vec.vec4f.setFromArray(v0, [0, 0, 0, 0]);
    -    goog.vec.mat4f.getDiagonal(m0, v0, -1);
    -    assertElementsEquals([1, 6, 11, 0], v0);
    -
    -    goog.vec.vec4f.setFromArray(v0, [0, 0, 0, 0]);
    -    goog.vec.mat4f.getDiagonal(m0, v0, -2);
    -    assertElementsEquals([2, 7, 0, 0], v0);
    -
    -    goog.vec.vec4f.setFromArray(v0, [0, 0, 0, 0]);
    -    goog.vec.mat4f.getDiagonal(m0, v0, -3);
    -    assertElementsEquals([3, 0, 0, 0], v0);
    -
    -    goog.vec.vec4f.setFromArray(v0, [0, 0, 0, 0]);
    -    goog.vec.mat4f.getDiagonal(m0, v0, -4);
    -    assertElementsEquals([0, 0, 0, 0], v0);
    -  }
    -
    -  function testSetGetColumn() {
    -    var m0 = goog.vec.mat4f.create();
    -    goog.vec.mat4f.setColumn(m0, 0, [1, 2, 3, 4]);
    -    goog.vec.mat4f.setColumn(m0, 1, [5, 6, 7, 8]);
    -    goog.vec.mat4f.setColumn(m0, 2, [9, 10, 11, 12]);
    -    goog.vec.mat4f.setColumn(m0, 3, [13, 14, 15, 16]);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -
    -    var v0 = [0, 0, 0, 0];
    -    goog.vec.mat4f.getColumn(m0, 0, v0);
    -    assertElementsEquals([1, 2, 3, 4], v0);
    -    goog.vec.mat4f.getColumn(m0, 1, v0);
    -    assertElementsEquals([5, 6, 7, 8], v0);
    -    goog.vec.mat4f.getColumn(m0, 2, v0);
    -    assertElementsEquals([9, 10, 11, 12], v0);
    -    goog.vec.mat4f.getColumn(m0, 3, v0);
    -    assertElementsEquals([13, 14, 15, 16], v0);
    -  }
    -
    -  function testSetGetColumns() {
    -    var m0 = goog.vec.mat4f.create();
    -    goog.vec.mat4f.setColumns(
    -        m0, [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -
    -    var v0 = [0, 0, 0, 0], v1 = [0, 0, 0, 0];
    -    var v2 = [0, 0, 0, 0], v3 = [0, 0, 0, 0];
    -    goog.vec.mat4f.getColumns(m0, v0, v1, v2, v3);
    -    assertElementsEquals([1, 2, 3, 4], v0);
    -    assertElementsEquals([5, 6, 7, 8], v1);
    -    assertElementsEquals([9, 10, 11, 12], v2);
    -    assertElementsEquals([13, 14, 15, 16], v3);
    -  }
    -
    -  function testSetGetRow() {
    -    var m0 = goog.vec.mat4f.create();
    -    goog.vec.mat4f.setRow(m0, 0, [1, 2, 3, 4]);
    -    goog.vec.mat4f.setRow(m0, 1, [5, 6, 7, 8]);
    -    goog.vec.mat4f.setRow(m0, 2, [9, 10, 11, 12]);
    -    goog.vec.mat4f.setRow(m0, 3, [13, 14, 15, 16]);
    -    assertElementsEquals(
    -        [1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16], m0);
    -
    -    var v0 = [0, 0, 0, 0];
    -    goog.vec.mat4f.getRow(m0, 0, v0);
    -    assertElementsEquals([1, 2, 3, 4], v0);
    -    goog.vec.mat4f.getRow(m0, 1, v0);
    -    assertElementsEquals([5, 6, 7, 8], v0);
    -    goog.vec.mat4f.getRow(m0, 2, v0);
    -    assertElementsEquals([9, 10, 11, 12], v0);
    -    goog.vec.mat4f.getRow(m0, 3, v0);
    -    assertElementsEquals([13, 14, 15, 16], v0);
    -  }
    -
    -  function testSetGetRows() {
    -    var m0 = goog.vec.mat4f.create();
    -    goog.vec.mat4f.setRows(
    -        m0, [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]);
    -    assertElementsEquals(
    -        [1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16], m0);
    -
    -    var v0 = [0, 0, 0, 0], v1 = [0, 0, 0, 0];
    -    var v2 = [0, 0, 0, 0], v3 = [0, 0, 0, 0];
    -    goog.vec.mat4f.getRows(m0, v0, v1, v2, v3);
    -    assertElementsEquals([1, 2, 3, 4], v0);
    -    assertElementsEquals([5, 6, 7, 8], v1);
    -    assertElementsEquals([9, 10, 11, 12], v2);
    -    assertElementsEquals([13, 14, 15, 16], v3);
    -  }
    -
    -  function testMakeZero() {
    -    var m0 = goog.vec.mat4f.setFromArray(goog.vec.mat4f.create(), 
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -    goog.vec.mat4f.makeZero(m0);
    -    assertElementsEquals(
    -        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], m0);
    -  }
    -
    -  function testMakeIdentity() {
    -    var m0 = goog.vec.mat4f.create();
    -    goog.vec.mat4f.makeIdentity(m0);
    -    assertElementsEquals(
    -        [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], m0);
    -  }
    -
    -  function testSetGetElement() {
    -    var m0 = goog.vec.mat4f.create();
    -    for (var r = 0; r < 4; r++) {
    -      for (var c = 0; c < 4; c++) {
    -        var value = c * 4 + r + 1;
    -        goog.vec.mat4f.setElement(m0, r, c, value);
    -        assertEquals(value, goog.vec.mat4f.getElement(m0, r, c));
    -      }
    -    }
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -  }
    -
    -  function testAddMat() {
    -    var m0 = goog.vec.mat4f.setFromValues(goog.vec.mat4f.create(), 
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var m1 = goog.vec.mat4f.setFromValues(goog.vec.mat4f.create(), 
    -        9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8);
    -    var m2 = goog.vec.mat4f.create();
    -    goog.vec.mat4f.addMat(m0, m1, m2);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -    assertElementsEquals(
    -        [9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8], m1);
    -    assertElementsEquals(
    -        [10, 12, 14, 16, 18, 20, 22, 24, 10, 12, 14, 16, 18, 20, 22, 24], m2);
    -
    -    goog.vec.mat4f.addMat(m0, m1, m0);
    -    assertElementsEquals(
    -        [9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8], m1);
    -    assertElementsEquals(
    -        [10, 12, 14, 16, 18, 20, 22, 24, 10, 12, 14, 16, 18, 20, 22, 24], m0);
    -  }
    -
    -  function testSubMat() {
    -    var m0 = goog.vec.mat4f.setFromValues(goog.vec.mat4f.create(), 
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var m1 = goog.vec.mat4f.setFromValues(goog.vec.mat4f.create(), 
    -        9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8);
    -    var m2 = goog.vec.mat4f.create();
    -
    -    goog.vec.mat4f.subMat(m0, m1, m2);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -    assertElementsEquals(
    -        [9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8], m1);
    -    assertElementsEquals(
    -        [-8, -8, -8, -8, -8, -8, -8, -8, 8, 8, 8, 8, 8, 8, 8, 8], m2);
    -
    -    goog.vec.mat4f.subMat(m1, m0, m1);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -    assertElementsEquals(
    -        [8, 8, 8, 8, 8, 8, 8, 8, -8, -8, -8, -8, -8, -8, -8, -8], m1);
    -  }
    -
    -  function testMultScalar() {
    -    var m0 = goog.vec.mat4f.setFromValues(goog.vec.mat4f.create(), 
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var m1 = goog.vec.mat4f.create();
    -
    -    goog.vec.mat4f.multScalar(m0, 2, m1);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -    assertElementsEquals(
    -        [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32], m1);
    -
    -    goog.vec.mat4f.multScalar(m0, 5, m0);
    -    assertElementsEquals(
    -        [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80], m0);
    -  }
    -
    -  function testMultMat() {
    -    var m0 = goog.vec.mat4f.setFromValues(goog.vec.mat4f.create(), 
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var m1 = goog.vec.mat4f.setFromValues(goog.vec.mat4f.create(), 
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var m2 = goog.vec.mat4f.create();
    -
    -    goog.vec.mat4f.multMat(m0, m1, m2);
    -    assertElementsEquals(
    -        [90, 100, 110, 120, 202, 228, 254, 280,
    -         314, 356, 398, 440, 426, 484, 542, 600], m2);
    -
    -    goog.vec.mat4f.multScalar(m1, 2, m1);
    -    goog.vec.mat4f.multMat(m1, m0, m1);
    -    assertElementsEquals(
    -        [180, 200, 220, 240, 404, 456, 508, 560,
    -         628, 712, 796, 880, 852, 968, 1084, 1200], m1);
    -  }
    -
    -  function testTranspose() {
    -    var m0 = goog.vec.mat4f.setFromValues(goog.vec.mat4f.create(), 
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var m1 = goog.vec.mat4f.create();
    -    goog.vec.mat4f.transpose(m0, m1);
    -    assertElementsEquals(
    -        [1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16], m1);
    -
    -    goog.vec.mat4f.transpose(m1, m1);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m1);
    -  }
    -
    -  function testDeterminant() {
    -    var m0 = goog.vec.mat4f.setFromValues(goog.vec.mat4f.create(), 
    -        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
    -    assertEquals(0, goog.vec.mat4f.determinant(m0));
    -    assertElementsEquals(
    -        [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], m0);
    -
    -    goog.vec.mat4f.setFromValues(
    -        m0, 1, 2, 3, 4, 2, 3, 4, 1, 3, 4, 1, 2, 4, 1, 2, 3);
    -    assertEquals(160, goog.vec.mat4f.determinant(m0));
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 2, 3, 4, 1, 3, 4, 1, 2, 4, 1, 2, 3], m0);
    -  }
    -
    -  function testInvert() {
    -    var m0 = goog.vec.mat4f.setFromValues(goog.vec.mat4f.create(), 
    -        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
    -    assertFalse(goog.vec.mat4f.invert(m0, m0));
    -    assertElementsEquals(
    -        [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], m0);
    -
    -    goog.vec.mat4f.setFromValues(
    -        m0, 1, 2, 3, 4, 2, 3, 4, 1, 3, 4, 1, 2, 4, 1, 2, 3);
    -    assertTrue(goog.vec.mat4f.invert(m0, m0));
    -    assertElementsRoughlyEqual(
    -        [-0.225, 0.025, 0.025, 0.275, 0.025, 0.025, 0.275, -0.225,
    -         0.025, 0.275, -0.225, 0.025, 0.275, -0.225, 0.025, 0.025], m0,
    -         goog.vec.EPSILON);
    -
    -    goog.vec.mat4f.makeScale(m0, .01, .01, .01);
    -    assertTrue(goog.vec.mat4f.invert(m0, m0));
    -    var m1 = goog.vec.mat4f.create();
    -    goog.vec.mat4f.makeScale(m1, 100, 100, 100);
    -    assertElementsEquals(m1, m0);
    -  }
    -
    -  function testEquals() {
    -    var m0 = goog.vec.mat4f.setFromValues(goog.vec.mat4f.create(), 
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var m1 = goog.vec.mat4f.setFromMat4f(goog.vec.mat4f.create(), m0);
    -    assertTrue(goog.vec.mat4f.equals(m0, m1));
    -    assertTrue(goog.vec.mat4f.equals(m1, m0));
    -    for (var i = 0; i < 16; i++) {
    -      m1[i] = 18;
    -      assertFalse(goog.vec.mat4f.equals(m0, m1));
    -      assertFalse(goog.vec.mat4f.equals(m1, m0));
    -      m1[i] = i + 1;
    -    }
    -  }
    -
    -  function testMultVec3() {
    -    var m0 = goog.vec.mat4f.setFromValues(goog.vec.mat4f.create(), 
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var v0 = [1, 2, 3];
    -    var v1 = [0, 0, 0];
    -
    -    goog.vec.mat4f.multVec3(m0, v0, v1);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals([51, 58, 65], v1);
    -
    -    goog.vec.mat4f.multVec3(m0, v0, v0);
    -    assertElementsEquals([51, 58, 65], v0);
    -  }
    -
    -  function testMultVec3NoTranslate() {
    -    var m0 = goog.vec.mat4f.setFromValues(goog.vec.mat4f.create(), 
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var v0 = [1, 2, 3];
    -    var v1 = [0, 0, 0];
    -
    -    goog.vec.mat4f.multVec3NoTranslate(m0, v0, v1);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals([38, 44, 50], v1);
    -
    -    goog.vec.mat4f.multVec3NoTranslate(m0, v0, v0);
    -    assertElementsEquals([38, 44, 50], v0);
    -  }
    -
    -  function testMultVec3Projective() {
    -    var m0 = goog.vec.mat4f.setFromValues(goog.vec.mat4f.create(), 
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var v0 = [1, 2, 3];
    -    var v1 = [0, 0, 0];
    -    var invw = 1 / 72;
    -
    -    goog.vec.mat4f.multVec3Projective(m0, v0, v1);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals(
    -        [51 * invw, 58 * invw, 65 * invw], v1);
    -
    -    goog.vec.mat4f.multVec3Projective(m0, v0, v0);
    -    assertElementsEquals(
    -        [51 * invw, 58 * invw, 65 * invw], v0);
    -  }
    -
    -  function testMultVec4() {
    -    var m0 = goog.vec.mat4f.setFromValues(goog.vec.mat4f.create(), 
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var v0 = [1, 2, 3, 4];
    -    var v1 = [0, 0, 0, 0];
    -
    -    goog.vec.mat4f.multVec4(m0, v0, v1);
    -    assertElementsEquals([90, 100, 110, 120], v1);
    -    goog.vec.mat4f.multVec4(m0, v0, v0);
    -    assertElementsEquals([90, 100, 110, 120], v0);
    -  }
    -
    -  function testSetValues() {
    -    var a0 = goog.vec.mat4f.create();
    -    assertElementsEquals(
    -        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], a0);
    -    a0 = goog.vec.mat4f.setFromArray(goog.vec.mat4f.create(), 
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], a0);
    -
    -    var a1 = goog.vec.mat4f.create();
    -    goog.vec.mat4f.setDiagonalValues(a1, 1, 2, 3, 4);
    -    assertElementsEquals(
    -        [1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 4], a1);
    -
    -    goog.vec.mat4f.setColumnValues(a1, 0, 2, 3, 4, 5);
    -    goog.vec.mat4f.setColumnValues(a1, 1, 6, 7, 8, 9);
    -    goog.vec.mat4f.setColumnValues(a1, 2, 10, 11, 12, 13);
    -    goog.vec.mat4f.setColumnValues(a1, 3, 14, 15, 16, 1);
    -    assertElementsEquals(
    -        [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1], a1);
    -
    -    goog.vec.mat4f.setRowValues(a1, 0, 1, 5, 9, 13);
    -    goog.vec.mat4f.setRowValues(a1, 1, 2, 6, 10, 14);
    -    goog.vec.mat4f.setRowValues(a1, 2, 3, 7, 11, 15);
    -    goog.vec.mat4f.setRowValues(a1, 3, 4, 8, 12, 16);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], a1);
    -  }
    -
    -  function testMakeTranslate() {
    -    var m0 = goog.vec.mat4f.create();
    -    goog.vec.mat4f.makeTranslate(m0, 3, 4, 5);
    -    assertElementsEquals(
    -        [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 3, 4, 5, 1], m0);
    -  }
    -
    -  function testMakeScale() {
    -    var m0 = goog.vec.mat4f.create();
    -    goog.vec.mat4f.makeScale(m0, 3, 4, 5);
    -    assertElementsEquals(
    -        [3, 0, 0, 0, 0, 4, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1], m0);
    -  }
    -
    -  function testMakeRotate() {
    -    var m0 = goog.vec.mat4f.create();
    -    goog.vec.mat4f.makeRotate(m0, Math.PI / 2, 0, 0, 1);
    -    assertElementsRoughlyEqual(
    -        [0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
    -        m0, goog.vec.EPSILON);
    -
    -    var m1 = goog.vec.mat4f.create();
    -    goog.vec.mat4f.makeRotate(m1, -Math.PI / 4, 0, 0, 1);
    -    goog.vec.mat4f.multMat(m0, m1, m1);
    -    assertElementsRoughlyEqual(
    -        [0.7071068, 0.7071068, 0, 0,
    -         -0.7071068, 0.7071068, 0, 0,
    -         0, 0, 1, 0,
    -         0, 0, 0, 1],
    -        m1, goog.vec.EPSILON);
    -  }
    -
    -  function testMakeRotateX() {
    -    var m0 = goog.vec.mat4f.create();
    -    var m1 = goog.vec.mat4f.create()
    -
    -    goog.vec.mat4f.makeRotateX(m0, Math.PI / 7);
    -    goog.vec.mat4f.makeRotate(m1, Math.PI / 7, 1, 0, 0);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testMakeRotateY() {
    -    var m0 = goog.vec.mat4f.create();
    -    var m1 = goog.vec.mat4f.create()
    -
    -    goog.vec.mat4f.makeRotateY(m0, Math.PI / 7);
    -    goog.vec.mat4f.makeRotate(m1, Math.PI / 7, 0, 1, 0);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testMakeRotateZ() {
    -    var m0 = goog.vec.mat4f.create();
    -    var m1 = goog.vec.mat4f.create()
    -
    -    goog.vec.mat4f.makeRotateZ(m0, Math.PI / 7);
    -    goog.vec.mat4f.makeRotate(m1, Math.PI / 7, 0, 0, 1);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -
    -  function testTranslate() {
    -    var m0 = goog.vec.mat4f.makeIdentity(goog.vec.mat4f.create());
    -    goog.vec.mat4f.translate(m0, 3, 4, 5);
    -    assertElementsEquals(
    -        [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 3, 4, 5, 1], m0);
    -
    -    goog.vec.mat4f.setFromValues(
    -        m0, 1, 2, 3, 4, 2, 3, 4, 1, 3, 4, 1, 2, 4, 1, 2, 3);
    -
    -    var m1 = goog.vec.mat4f.create();
    -    goog.vec.mat4f.makeTranslate(m1, 5, 6, 7);
    -    var m2 = goog.vec.mat4f.create();
    -    goog.vec.mat4f.multMat(m0, m1, m2);
    -    goog.vec.mat4f.translate(m0, 5, 6, 7);
    -    assertElementsEquals(m2, m0);
    -  }
    -
    -  function testScale() {
    -    var m0 = goog.vec.mat4f.makeIdentity(goog.vec.mat4f.create());
    -    goog.vec.mat4f.scale(m0, 3, 4, 5);
    -    assertElementsEquals([3, 0, 0, 0, 0, 4, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1], m0);
    -  }
    -
    -  function testRotate() {
    -    var m0 = goog.vec.mat4f.makeIdentity(goog.vec.mat4f.create());
    -    goog.vec.mat4f.rotate(m0, Math.PI / 2, 0, 0, 1);
    -    assertElementsRoughlyEqual(
    -        [0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
    -        m0, goog.vec.EPSILON);
    -
    -    goog.vec.mat4f.rotate(m0, -Math.PI / 4, 0, 0, 1);
    -    assertElementsRoughlyEqual(
    -        [0.7071068, 0.7071068, 0, 0,
    -         -0.7071068, 0.7071068, 0, 0,
    -         0, 0, 1, 0,
    -         0, 0, 0, 1],
    -        m0, goog.vec.EPSILON);
    -  }
    -
    -  function testRotateX() {
    -    var m0 = goog.vec.mat4f.create();
    -    var m1 = goog.vec.mat4f.setFromArray(goog.vec.mat4f.create(), randommat4f)
    -
    -    goog.vec.mat4f.makeRotateX(m0, Math.PI / 7);
    -    goog.vec.mat4f.multMat(m1, m0, m0);
    -    goog.vec.mat4f.rotateX(m1, Math.PI / 7);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testRotateY() {
    -    var m0 = goog.vec.mat4f.create();
    -    var m1 = goog.vec.mat4f.setFromArray(goog.vec.mat4f.create(), randommat4f)
    -
    -    goog.vec.mat4f.makeRotateY(m0, Math.PI / 7);
    -    goog.vec.mat4f.multMat(m1, m0, m0);
    -    goog.vec.mat4f.rotateY(m1, Math.PI / 7);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testRotateZ() {
    -    var m0 = goog.vec.mat4f.create();
    -    var m1 = goog.vec.mat4f.setFromArray(goog.vec.mat4f.create(), randommat4f)
    -
    -    goog.vec.mat4f.makeRotateZ(m0, Math.PI / 7);
    -    goog.vec.mat4f.multMat(m1, m0, m0);
    -    goog.vec.mat4f.rotateZ(m1, Math.PI / 7);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testGetTranslation() {
    -    var mat = goog.vec.mat4f.setFromArray(goog.vec.mat4f.create(), randommat4f);
    -    var translation = goog.vec.vec3f.create();
    -    goog.vec.mat4f.getTranslation(mat, translation);
    -    assertElementsRoughlyEqual(
    -        [0.59465038776, 0.413479506969, 0.0663217827677],
    -        translation, goog.vec.EPSILON);
    -  }
    -
    -  function testMakeFrustum() {
    -    var m0 = goog.vec.mat4f.create();
    -    goog.vec.mat4f.makeFrustum(m0, -1, 2, -2, 1, .1, 1.1);
    -    assertElementsRoughlyEqual(
    -        [0.06666666, 0, 0, 0,
    -         0, 0.06666666, 0, 0,
    -         0.33333333, -0.33333333, -1.2, -1,
    -         0, 0, -0.22, 0], m0, goog.vec.EPSILON);
    -  }
    -
    -  function testMakePerspective() {
    -    var m0 = goog.vec.mat4f.create();
    -    goog.vec.mat4f.makePerspective(m0, 90 * Math.PI / 180, 2, 0.1, 1.1);
    -    assertElementsRoughlyEqual(
    -        [0.5, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1.2, -1, 0, 0, -0.22, 0],
    -        m0, goog.vec.EPSILON);
    -  }
    -
    -  function testMakeOrtho() {
    -    var m0 = goog.vec.mat4f.create();
    -    goog.vec.mat4f.makeOrtho(m0, -1, 2, -2, 1, 0.1, 1.1);
    -    assertElementsRoughlyEqual(
    -        [0.6666666, 0, 0, 0,
    -         0, 0.6666666, 0, 0,
    -         0, 0, -2, 0,
    -         -0.333333, 0.3333333, -1.2, 1], m0, goog.vec.EPSILON);
    -
    -  }
    -
    -  function testMakeEulerZXZ() {
    -    var m0 = goog.vec.mat4f.create();
    -    var roll = 0.200982 * 2 * Math.PI;
    -    var tilt = 0.915833 * Math.PI;
    -    var yaw = 0.839392 * 2 * Math.PI;
    -
    -    goog.vec.mat4f.makeRotate(m0, roll, 0, 0, 1);
    -    goog.vec.mat4f.rotate(m0, tilt, 1, 0, 0);
    -    goog.vec.mat4f.rotate(m0, yaw, 0, 0, 1);
    -
    -    var m1 = goog.vec.mat4f.create();
    -    goog.vec.mat4f.makeEulerZXZ(m1, roll, tilt, yaw);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -
    -
    -    var euler = [0, 0, 0];
    -    goog.vec.mat4f.toEulerZXZ(m0, euler);
    -
    -    assertRoughlyEquals(roll, euler[0], goog.vec.EPSILON);
    -    assertRoughlyEquals(tilt, euler[1], goog.vec.EPSILON);
    -    assertRoughlyEquals(yaw, euler[2], goog.vec.EPSILON);
    -
    -    // Test negative tilt now.
    -    goog.vec.mat4f.makeRotate(m0, roll, 0, 0, 1);
    -    goog.vec.mat4f.rotate(m0, -tilt, 1, 0, 0);
    -    goog.vec.mat4f.rotate(m0, yaw, 0, 0, 1);
    -
    -    goog.vec.mat4f.makeEulerZXZ(m1, roll, -tilt, yaw);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -
    -    var euler = [0, 0, 0];
    -    goog.vec.mat4f.toEulerZXZ(m0, euler, true);
    -
    -    assertRoughlyEquals(roll, euler[0], goog.vec.EPSILON);
    -    assertRoughlyEquals(-tilt, euler[1], goog.vec.EPSILON);
    -    assertRoughlyEquals(yaw, euler[2], goog.vec.EPSILON);
    -  }
    -
    -  function testEulerZXZExtrema() {
    -    var m0 = goog.vec.mat4f.setFromArray(goog.vec.mat4f.create(), 
    -    [1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1]);
    -    var m1 = goog.vec.mat4f.setFromArray(goog.vec.mat4f.create(), 
    -    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
    -
    -    var euler = [0, 0, 0];
    -    goog.vec.mat4f.toEulerZXZ(m0, euler);
    -    assertElementsRoughlyEqual(
    -        [Math.PI, Math.PI / 2, Math.PI], euler, goog.vec.EPSILON);
    -    goog.vec.mat4f.makeEulerZXZ(m1, euler[0], euler[1], euler[2]);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testLookAt() {
    -    var viewMatrix = goog.vec.mat4f.create();
    -    goog.vec.mat4f.makeLookAt(
    -      viewMatrix, [0, 0, 0], [1, 0, 0], [0, 1, 0]);
    -    assertElementsRoughlyEqual(
    -      [0, 0, -1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1], viewMatrix,
    -      goog.vec.EPSILON);
    -  }
    -
    -  function testToLookAt() {
    -    // This test does not use the default precision goog.vec.EPSILON due to
    -    // precision issues in some browsers leading to flaky tests.
    -    var EPSILON = 1e-4;
    -
    -    var eyeExp = [0, 0, 0];
    -    var fwdExp = [1, 0, 0];
    -    var upExp = [0, 1, 0];
    -
    -    var centerExp = [0, 0, 0];
    -    goog.vec.vec3f.add(eyeExp, fwdExp, centerExp);
    -
    -    var view = goog.vec.mat4f.create();
    -    goog.vec.mat4f.makeLookAt(view, eyeExp, centerExp, upExp);
    -
    -    var eyeRes = [0, 0, 0];
    -    var fwdRes = [0, 0, 0];
    -    var upRes = [0, 0, 0];
    -    goog.vec.mat4f.toLookAt(view, eyeRes, fwdRes, upRes);
    -    assertElementsRoughlyEqual(eyeExp, eyeRes, EPSILON);
    -    assertElementsRoughlyEqual(fwdExp, fwdRes, EPSILON);
    -    assertElementsRoughlyEqual(upExp, upRes, EPSILON);
    -  }
    -
    -  function testLookAtDecomposition() {
    -    // This test does not use the default precision goog.vec.EPSILON due to
    -    // precision issues in some browsers leading to flaky tests.
    -    var EPSILON = 1e-4;
    -
    -    var viewExp = goog.vec.mat4f.create();
    -    var viewRes = goog.vec.mat4f.create();
    -
    -    // Get a valid set of random vectors eye, forward, up by decomposing
    -    // a random matrix into a set of lookAt vectors.
    -    var tmp = goog.vec.mat4f.setFromArray(goog.vec.mat4f.create(), randommat4f);
    -    var eyeExp = [0, 0, 0];
    -    var fwdExp = [0, 0, 0];
    -    var upExp = [0, 0, 0];
    -    var centerExp = [0, 0, 0];
    -    // Project the random matrix into a real modelview matrix.
    -    goog.vec.mat4f.toLookAt(tmp, eyeExp, fwdExp, upExp);
    -    goog.vec.vec3f.add(eyeExp, fwdExp, centerExp);
    -
    -    // Compute the expected modelview matrix from a set of valid random vectors.
    -    goog.vec.mat4f.makeLookAt(viewExp, eyeExp, centerExp, upExp);
    -
    -    var eyeRes = [0, 0, 0];
    -    var fwdRes = [0, 0, 0];
    -    var upRes = [0, 0, 0];
    -    var centerRes = [0, 0, 0];
    -    goog.vec.mat4f.toLookAt(viewExp, eyeRes, fwdRes, upRes);
    -    goog.vec.vec3f.add(eyeRes, fwdRes, centerRes);
    -
    -    goog.vec.mat4f.makeLookAt(viewRes, eyeRes, centerRes, upRes);
    -
    -    assertElementsRoughlyEqual(eyeExp, eyeRes, EPSILON);
    -    assertElementsRoughlyEqual(fwdExp, fwdRes, EPSILON);
    -    assertElementsRoughlyEqual(upExp, upRes, EPSILON);
    -    assertElementsRoughlyEqual(viewExp, viewRes, EPSILON);
    -  }
    -
    -</script>
    -</body>
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/matrix3.js b/src/database/third_party/closure-library/closure/goog/vec/matrix3.js
    deleted file mode 100644
    index 71f554ac838..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/matrix3.js
    +++ /dev/null
    @@ -1,720 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview WARNING: DEPRECATED.  Use Mat3 instead.
    - * Implements 3x3 matrices and their related functions which are
    - * compatible with WebGL. The API is structured to avoid unnecessary memory
    - * allocations.  The last parameter will typically be the output vector and
    - * an object can be both an input and output parameter to all methods except
    - * where noted. Matrix operations follow the mathematical form when multiplying
    - * vectors as follows: resultVec = matrix * vec.
    - *
    - */
    -goog.provide('goog.vec.Matrix3');
    -
    -
    -/**
    - * @typedef {goog.vec.ArrayType}
    - */
    -goog.vec.Matrix3.Type;
    -
    -
    -/**
    - * Creates the array representation of a 3x3 matrix. The use of the array
    - * directly eliminates any overhead associated with the class representation
    - * defined above. The returned matrix is cleared to all zeros.
    - *
    - * @return {goog.vec.Matrix3.Type} The new, nine element array.
    - */
    -goog.vec.Matrix3.create = function() {
    -  return new Float32Array(9);
    -};
    -
    -
    -/**
    - * Creates the array representation of a 3x3 matrix. The use of the array
    - * directly eliminates any overhead associated with the class representation
    - * defined above. The returned matrix is initialized with the identity.
    - *
    - * @return {goog.vec.Matrix3.Type} The new, nine element array.
    - */
    -goog.vec.Matrix3.createIdentity = function() {
    -  var mat = goog.vec.Matrix3.create();
    -  mat[0] = mat[4] = mat[8] = 1;
    -  return mat;
    -};
    -
    -
    -/**
    - * Creates a 3x3 matrix initialized from the given array.
    - *
    - * @param {goog.vec.ArrayType} matrix The array containing the
    - *     matrix values in column major order.
    - * @return {goog.vec.Matrix3.Type} The new, nine element array.
    - */
    -goog.vec.Matrix3.createFromArray = function(matrix) {
    -  var newMatrix = goog.vec.Matrix3.create();
    -  goog.vec.Matrix3.setFromArray(newMatrix, matrix);
    -  return newMatrix;
    -};
    -
    -
    -/**
    - * Creates a 3x3 matrix initialized from the given values.
    - *
    - * @param {number} v00 The values at (0, 0).
    - * @param {number} v10 The values at (1, 0).
    - * @param {number} v20 The values at (2, 0).
    - * @param {number} v01 The values at (0, 1).
    - * @param {number} v11 The values at (1, 1).
    - * @param {number} v21 The values at (2, 1).
    - * @param {number} v02 The values at (0, 2).
    - * @param {number} v12 The values at (1, 2).
    - * @param {number} v22 The values at (2, 2).
    - * @return {goog.vec.Matrix3.Type} The new, nine element array.
    - */
    -goog.vec.Matrix3.createFromValues = function(
    -    v00, v10, v20, v01, v11, v21, v02, v12, v22) {
    -  var newMatrix = goog.vec.Matrix3.create();
    -  goog.vec.Matrix3.setFromValues(
    -      newMatrix, v00, v10, v20, v01, v11, v21, v02, v12, v22);
    -  return newMatrix;
    -};
    -
    -
    -/**
    - * Creates a clone of a 3x3 matrix.
    - *
    - * @param {goog.vec.Matrix3.Type} matrix The source 3x3 matrix.
    - * @return {goog.vec.Matrix3.Type} The new 3x3 element matrix.
    - */
    -goog.vec.Matrix3.clone =
    -    goog.vec.Matrix3.createFromArray;
    -
    -
    -/**
    - * Retrieves the element at the requested row and column.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix containing the
    - *     value to retrieve.
    - * @param {number} row The row index.
    - * @param {number} column The column index.
    - * @return {number} The element value at the requested row, column indices.
    - */
    -goog.vec.Matrix3.getElement = function(mat, row, column) {
    -  return mat[row + column * 3];
    -};
    -
    -
    -/**
    - * Sets the element at the requested row and column.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix containing the
    - *     value to retrieve.
    - * @param {number} row The row index.
    - * @param {number} column The column index.
    - * @param {number} value The value to set at the requested row, column.
    - */
    -goog.vec.Matrix3.setElement = function(mat, row, column, value) {
    -  mat[row + column * 3] = value;
    -};
    -
    -
    -/**
    - * Initializes the matrix from the set of values. Note the values supplied are
    - * in column major order.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to receive the
    - *     values.
    - * @param {number} v00 The values at (0, 0).
    - * @param {number} v10 The values at (1, 0).
    - * @param {number} v20 The values at (2, 0).
    - * @param {number} v01 The values at (0, 1).
    - * @param {number} v11 The values at (1, 1).
    - * @param {number} v21 The values at (2, 1).
    - * @param {number} v02 The values at (0, 2).
    - * @param {number} v12 The values at (1, 2).
    - * @param {number} v22 The values at (2, 2).
    - */
    -goog.vec.Matrix3.setFromValues = function(
    -    mat, v00, v10, v20, v01, v11, v21, v02, v12, v22) {
    -  mat[0] = v00;
    -  mat[1] = v10;
    -  mat[2] = v20;
    -  mat[3] = v01;
    -  mat[4] = v11;
    -  mat[5] = v21;
    -  mat[6] = v02;
    -  mat[7] = v12;
    -  mat[8] = v22;
    -};
    -
    -
    -/**
    - * Sets the matrix from the array of values stored in column major order.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to receive the
    - *     values.
    - * @param {goog.vec.ArrayType} values The column major ordered
    - *     array of values to store in the matrix.
    - */
    -goog.vec.Matrix3.setFromArray = function(mat, values) {
    -  mat[0] = values[0];
    -  mat[1] = values[1];
    -  mat[2] = values[2];
    -  mat[3] = values[3];
    -  mat[4] = values[4];
    -  mat[5] = values[5];
    -  mat[6] = values[6];
    -  mat[7] = values[7];
    -  mat[8] = values[8];
    -};
    -
    -
    -/**
    - * Sets the matrix from the array of values stored in row major order.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to receive the
    - *     values.
    - * @param {goog.vec.ArrayType} values The row major ordered array
    - *     of values to store in the matrix.
    - */
    -goog.vec.Matrix3.setFromRowMajorArray = function(mat, values) {
    -  mat[0] = values[0];
    -  mat[1] = values[3];
    -  mat[2] = values[6];
    -  mat[3] = values[1];
    -  mat[4] = values[4];
    -  mat[5] = values[7];
    -  mat[6] = values[2];
    -  mat[7] = values[5];
    -  mat[8] = values[8];
    -};
    -
    -
    -/**
    - * Sets the diagonal values of the matrix from the given values.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to receive the
    - *     values.
    - * @param {number} v00 The values for (0, 0).
    - * @param {number} v11 The values for (1, 1).
    - * @param {number} v22 The values for (2, 2).
    - */
    -goog.vec.Matrix3.setDiagonalValues = function(mat, v00, v11, v22) {
    -  mat[0] = v00;
    -  mat[4] = v11;
    -  mat[8] = v22;
    -};
    -
    -
    -/**
    - * Sets the diagonal values of the matrix from the given vector.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to receive the
    - *     values.
    - * @param {goog.vec.ArrayType} vec The vector containing the
    - *     values.
    - */
    -goog.vec.Matrix3.setDiagonal = function(mat, vec) {
    -  mat[0] = vec[0];
    -  mat[4] = vec[1];
    -  mat[8] = vec[2];
    -};
    -
    -
    -/**
    - * Sets the specified column with the supplied values.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to recieve the
    - *     values.
    - * @param {number} column The column index to set the values on.
    - * @param {number} v0 The value for row 0.
    - * @param {number} v1 The value for row 1.
    - * @param {number} v2 The value for row 2.
    - */
    -goog.vec.Matrix3.setColumnValues = function(
    -    mat, column, v0, v1, v2) {
    -  var i = column * 3;
    -  mat[i] = v0;
    -  mat[i + 1] = v1;
    -  mat[i + 2] = v2;
    -};
    -
    -
    -/**
    - * Sets the specified column with the value from the supplied array.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to receive the
    - *     values.
    - * @param {number} column The column index to set the values on.
    - * @param {goog.vec.ArrayType} vec The vector elements for the
    - *     column.
    - */
    -goog.vec.Matrix3.setColumn = function(mat, column, vec) {
    -  var i = column * 3;
    -  mat[i] = vec[0];
    -  mat[i + 1] = vec[1];
    -  mat[i + 2] = vec[2];
    -};
    -
    -
    -/**
    - * Retrieves the specified column from the matrix into the given vector
    - * array.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix supplying the
    - *     values.
    - * @param {number} column The column to get the values from.
    - * @param {goog.vec.ArrayType} vec The vector elements to receive
    - *     the column.
    - */
    -goog.vec.Matrix3.getColumn = function(mat, column, vec) {
    -  var i = column * 3;
    -  vec[0] = mat[i];
    -  vec[1] = mat[i + 1];
    -  vec[2] = mat[i + 2];
    -};
    -
    -
    -/**
    - * Sets the columns of the matrix from the set of vector elements.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to receive the
    - *     values.
    - * @param {goog.vec.ArrayType} vec0 The values for column 0.
    - * @param {goog.vec.ArrayType} vec1 The values for column 1.
    - * @param {goog.vec.ArrayType} vec2 The values for column 2.
    - */
    -goog.vec.Matrix3.setColumns = function(
    -    mat, vec0, vec1, vec2) {
    -  goog.vec.Matrix3.setColumn(mat, 0, vec0);
    -  goog.vec.Matrix3.setColumn(mat, 1, vec1);
    -  goog.vec.Matrix3.setColumn(mat, 2, vec2);
    -};
    -
    -
    -/**
    - * Retrieves the column values from the given matrix into the given vector
    - * elements.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix containing the
    - *     columns to retrieve.
    - * @param {goog.vec.ArrayType} vec0 The vector elements to receive
    - *     column 0.
    - * @param {goog.vec.ArrayType} vec1 The vector elements to receive
    - *     column 1.
    - * @param {goog.vec.ArrayType} vec2 The vector elements to receive
    - *     column 2.
    - */
    -goog.vec.Matrix3.getColumns = function(
    -    mat, vec0, vec1, vec2) {
    -  goog.vec.Matrix3.getColumn(mat, 0, vec0);
    -  goog.vec.Matrix3.getColumn(mat, 1, vec1);
    -  goog.vec.Matrix3.getColumn(mat, 2, vec2);
    -};
    -
    -
    -/**
    - * Sets the row values from the supplied values.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to receive the
    - *     values.
    - * @param {number} row The index of the row to receive the values.
    - * @param {number} v0 The value for column 0.
    - * @param {number} v1 The value for column 1.
    - * @param {number} v2 The value for column 2.
    - */
    -goog.vec.Matrix3.setRowValues = function(mat, row, v0, v1, v2) {
    -  mat[row] = v0;
    -  mat[row + 3] = v1;
    -  mat[row + 6] = v2;
    -};
    -
    -
    -/**
    - * Sets the row values from the supplied vector.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to receive the
    - *     row values.
    - * @param {number} row The index of the row.
    - * @param {goog.vec.ArrayType} vec The vector containing the values.
    - */
    -goog.vec.Matrix3.setRow = function(mat, row, vec) {
    -  mat[row] = vec[0];
    -  mat[row + 3] = vec[1];
    -  mat[row + 6] = vec[2];
    -};
    -
    -
    -/**
    - * Retrieves the row values into the given vector.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix supplying the
    - *     values.
    - * @param {number} row The index of the row supplying the values.
    - * @param {goog.vec.ArrayType} vec The vector to receive the row.
    - */
    -goog.vec.Matrix3.getRow = function(mat, row, vec) {
    -  vec[0] = mat[row];
    -  vec[1] = mat[row + 3];
    -  vec[2] = mat[row + 6];
    -};
    -
    -
    -/**
    - * Sets the rows of the matrix from the supplied vectors.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to receive the
    - *     values.
    - * @param {goog.vec.ArrayType} vec0 The values for row 0.
    - * @param {goog.vec.ArrayType} vec1 The values for row 1.
    - * @param {goog.vec.ArrayType} vec2 The values for row 2.
    - */
    -goog.vec.Matrix3.setRows = function(
    -    mat, vec0, vec1, vec2) {
    -  goog.vec.Matrix3.setRow(mat, 0, vec0);
    -  goog.vec.Matrix3.setRow(mat, 1, vec1);
    -  goog.vec.Matrix3.setRow(mat, 2, vec2);
    -};
    -
    -
    -/**
    - * Retrieves the rows of the matrix into the supplied vectors.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to supplying
    - *     the values.
    - * @param {goog.vec.ArrayType} vec0 The vector to receive row 0.
    - * @param {goog.vec.ArrayType} vec1 The vector to receive row 1.
    - * @param {goog.vec.ArrayType} vec2 The vector to receive row 2.
    - */
    -goog.vec.Matrix3.getRows = function(
    -    mat, vec0, vec1, vec2) {
    -  goog.vec.Matrix3.getRow(mat, 0, vec0);
    -  goog.vec.Matrix3.getRow(mat, 1, vec1);
    -  goog.vec.Matrix3.getRow(mat, 2, vec2);
    -};
    -
    -
    -/**
    - * Clears the given matrix to zero.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to clear.
    - */
    -goog.vec.Matrix3.setZero = function(mat) {
    -  mat[0] = 0;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 0;
    -  mat[5] = 0;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = 0;
    -};
    -
    -
    -/**
    - * Sets the given matrix to the identity matrix.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to set.
    - */
    -goog.vec.Matrix3.setIdentity = function(mat) {
    -  mat[0] = 1;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 1;
    -  mat[5] = 0;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = 1;
    -};
    -
    -
    -/**
    - * Performs a per-component addition of the matrices mat0 and mat1, storing
    - * the result into resultMat.
    - *
    - * @param {goog.vec.ArrayType} mat0 The first addend.
    - * @param {goog.vec.ArrayType} mat1 The second addend.
    - * @param {goog.vec.ArrayType} resultMat The matrix to
    - *     receive the results (may be either mat0 or mat1).
    - * @return {goog.vec.ArrayType} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Matrix3.add = function(mat0, mat1, resultMat) {
    -  resultMat[0] = mat0[0] + mat1[0];
    -  resultMat[1] = mat0[1] + mat1[1];
    -  resultMat[2] = mat0[2] + mat1[2];
    -  resultMat[3] = mat0[3] + mat1[3];
    -  resultMat[4] = mat0[4] + mat1[4];
    -  resultMat[5] = mat0[5] + mat1[5];
    -  resultMat[6] = mat0[6] + mat1[6];
    -  resultMat[7] = mat0[7] + mat1[7];
    -  resultMat[8] = mat0[8] + mat1[8];
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Performs a per-component subtraction of the matrices mat0 and mat1,
    - * storing the result into resultMat.
    - *
    - * @param {goog.vec.ArrayType} mat0 The minuend.
    - * @param {goog.vec.ArrayType} mat1 The subtrahend.
    - * @param {goog.vec.ArrayType} resultMat The matrix to receive
    - *     the results (may be either mat0 or mat1).
    - * @return {goog.vec.ArrayType} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Matrix3.subtract = function(mat0, mat1, resultMat) {
    -  resultMat[0] = mat0[0] - mat1[0];
    -  resultMat[1] = mat0[1] - mat1[1];
    -  resultMat[2] = mat0[2] - mat1[2];
    -  resultMat[3] = mat0[3] - mat1[3];
    -  resultMat[4] = mat0[4] - mat1[4];
    -  resultMat[5] = mat0[5] - mat1[5];
    -  resultMat[6] = mat0[6] - mat1[6];
    -  resultMat[7] = mat0[7] - mat1[7];
    -  resultMat[8] = mat0[8] - mat1[8];
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Performs a component-wise multiplication of mat0 with the given scalar
    - * storing the result into resultMat.
    - *
    - * @param {goog.vec.ArrayType} mat0 The matrix to scale.
    - * @param {number} scalar The scalar value to multiple to each element of mat0.
    - * @param {goog.vec.ArrayType} resultMat The matrix to receive
    - *     the results (may be mat0).
    - * @return {goog.vec.ArrayType} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Matrix3.scale = function(mat0, scalar, resultMat) {
    -  resultMat[0] = mat0[0] * scalar;
    -  resultMat[1] = mat0[1] * scalar;
    -  resultMat[2] = mat0[2] * scalar;
    -  resultMat[3] = mat0[3] * scalar;
    -  resultMat[4] = mat0[4] * scalar;
    -  resultMat[5] = mat0[5] * scalar;
    -  resultMat[6] = mat0[6] * scalar;
    -  resultMat[7] = mat0[7] * scalar;
    -  resultMat[8] = mat0[8] * scalar;
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Multiplies the two matrices mat0 and mat1 using matrix multiplication,
    - * storing the result into resultMat.
    - *
    - * @param {goog.vec.ArrayType} mat0 The first (left hand) matrix.
    - * @param {goog.vec.ArrayType} mat1 The second (right hand)
    - *     matrix.
    - * @param {goog.vec.ArrayType} resultMat The matrix to receive
    - *     the results (may be either mat0 or mat1).
    - * @return {goog.vec.ArrayType} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Matrix3.multMat = function(mat0, mat1, resultMat) {
    -  var a00 = mat0[0], a10 = mat0[1], a20 = mat0[2];
    -  var a01 = mat0[3], a11 = mat0[4], a21 = mat0[5];
    -  var a02 = mat0[6], a12 = mat0[7], a22 = mat0[8];
    -
    -  var b00 = mat1[0], b10 = mat1[1], b20 = mat1[2];
    -  var b01 = mat1[3], b11 = mat1[4], b21 = mat1[5];
    -  var b02 = mat1[6], b12 = mat1[7], b22 = mat1[8];
    -
    -  resultMat[0] = a00 * b00 + a01 * b10 + a02 * b20;
    -  resultMat[1] = a10 * b00 + a11 * b10 + a12 * b20;
    -  resultMat[2] = a20 * b00 + a21 * b10 + a22 * b20;
    -  resultMat[3] = a00 * b01 + a01 * b11 + a02 * b21;
    -  resultMat[4] = a10 * b01 + a11 * b11 + a12 * b21;
    -  resultMat[5] = a20 * b01 + a21 * b11 + a22 * b21;
    -  resultMat[6] = a00 * b02 + a01 * b12 + a02 * b22;
    -  resultMat[7] = a10 * b02 + a11 * b12 + a12 * b22;
    -  resultMat[8] = a20 * b02 + a21 * b12 + a22 * b22;
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Transposes the given matrix mat storing the result into resultMat.
    - * @param {goog.vec.ArrayType} mat The matrix to transpose.
    - * @param {goog.vec.ArrayType} resultMat The matrix to receive
    - *     the results (may be mat).
    - * @return {goog.vec.ArrayType} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Matrix3.transpose = function(mat, resultMat) {
    -  if (resultMat == mat) {
    -    var a10 = mat[1], a20 = mat[2], a21 = mat[5];
    -    resultMat[1] = mat[3];
    -    resultMat[2] = mat[6];
    -    resultMat[3] = a10;
    -    resultMat[5] = mat[7];
    -    resultMat[6] = a20;
    -    resultMat[7] = a21;
    -  } else {
    -    resultMat[0] = mat[0];
    -    resultMat[1] = mat[3];
    -    resultMat[2] = mat[6];
    -    resultMat[3] = mat[1];
    -    resultMat[4] = mat[4];
    -    resultMat[5] = mat[7];
    -    resultMat[6] = mat[2];
    -    resultMat[7] = mat[5];
    -    resultMat[8] = mat[8];
    -  }
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Computes the inverse of mat0 storing the result into resultMat. If the
    - * inverse is defined, this function returns true, false otherwise.
    - * @param {goog.vec.ArrayType} mat0 The matrix to invert.
    - * @param {goog.vec.ArrayType} resultMat The matrix to receive
    - *     the result (may be mat0).
    - * @return {boolean} True if the inverse is defined. If false is returned,
    - *     resultMat is not modified.
    - */
    -goog.vec.Matrix3.invert = function(mat0, resultMat) {
    -  var a00 = mat0[0], a10 = mat0[1], a20 = mat0[2];
    -  var a01 = mat0[3], a11 = mat0[4], a21 = mat0[5];
    -  var a02 = mat0[6], a12 = mat0[7], a22 = mat0[8];
    -
    -  var t00 = a11 * a22 - a12 * a21;
    -  var t10 = a12 * a20 - a10 * a22;
    -  var t20 = a10 * a21 - a11 * a20;
    -  var det = a00 * t00 + a01 * t10 + a02 * t20;
    -  if (det == 0) {
    -    return false;
    -  }
    -
    -  var idet = 1 / det;
    -  resultMat[0] = t00 * idet;
    -  resultMat[3] = (a02 * a21 - a01 * a22) * idet;
    -  resultMat[6] = (a01 * a12 - a02 * a11) * idet;
    -
    -  resultMat[1] = t10 * idet;
    -  resultMat[4] = (a00 * a22 - a02 * a20) * idet;
    -  resultMat[7] = (a02 * a10 - a00 * a12) * idet;
    -
    -  resultMat[2] = t20 * idet;
    -  resultMat[5] = (a01 * a20 - a00 * a21) * idet;
    -  resultMat[8] = (a00 * a11 - a01 * a10) * idet;
    -  return true;
    -};
    -
    -
    -/**
    - * Returns true if the components of mat0 are equal to the components of mat1.
    - *
    - * @param {goog.vec.ArrayType} mat0 The first matrix.
    - * @param {goog.vec.ArrayType} mat1 The second matrix.
    - * @return {boolean} True if the the two matrices are equivalent.
    - */
    -goog.vec.Matrix3.equals = function(mat0, mat1) {
    -  return mat0.length == mat1.length &&
    -      mat0[0] == mat1[0] && mat0[1] == mat1[1] && mat0[2] == mat1[2] &&
    -      mat0[3] == mat1[3] && mat0[4] == mat1[4] && mat0[5] == mat1[5] &&
    -      mat0[6] == mat1[6] && mat0[7] == mat1[7] && mat0[8] == mat1[8];
    -};
    -
    -
    -/**
    - * Transforms the given vector with the given matrix storing the resulting,
    - * transformed matrix into resultVec.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix supplying the
    - *     transformation.
    - * @param {goog.vec.ArrayType} vec The vector to transform.
    - * @param {goog.vec.ArrayType} resultVec The vector to
    - *     receive the results (may be vec).
    - * @return {goog.vec.ArrayType} return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Matrix3.multVec3 = function(mat, vec, resultVec) {
    -  var x = vec[0], y = vec[1], z = vec[2];
    -  resultVec[0] = x * mat[0] + y * mat[3] + z * mat[6];
    -  resultVec[1] = x * mat[1] + y * mat[4] + z * mat[7];
    -  resultVec[2] = x * mat[2] + y * mat[5] + z * mat[8];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Initializes the given 3x3 matrix as a translation matrix with x and y
    - * translation values.
    - *
    - * @param {goog.vec.ArrayType} mat The 3x3 (9-element) matrix
    - *     array to receive the new translation matrix.
    - * @param {number} x The translation along the x axis.
    - * @param {number} y The translation along the y axis.
    - */
    -goog.vec.Matrix3.makeTranslate = function(mat, x, y) {
    -  goog.vec.Matrix3.setIdentity(mat);
    -  goog.vec.Matrix3.setColumnValues(mat, 2, x, y, 1);
    -};
    -
    -
    -/**
    - * Initializes the given 3x3 matrix as a scale matrix with x, y and z scale
    - * factors.
    - * @param {goog.vec.ArrayType} mat The 3x3 (9-element) matrix
    - *     array to receive the new scale matrix.
    - * @param {number} x The scale along the x axis.
    - * @param {number} y The scale along the y axis.
    - * @param {number} z The scale along the z axis.
    - */
    -goog.vec.Matrix3.makeScale = function(mat, x, y, z) {
    -  goog.vec.Matrix3.setIdentity(mat);
    -  goog.vec.Matrix3.setDiagonalValues(mat, x, y, z);
    -};
    -
    -
    -/**
    - * Initializes the given 3x3 matrix as a rotation matrix with the given rotation
    - * angle about the axis defined by the vector (ax, ay, az).
    - * @param {goog.vec.ArrayType} mat The 3x3 (9-element) matrix
    - *     array to receive the new scale matrix.
    - * @param {number} angle The rotation angle in radians.
    - * @param {number} ax The x component of the rotation axis.
    - * @param {number} ay The y component of the rotation axis.
    - * @param {number} az The z component of the rotation axis.
    - */
    -goog.vec.Matrix3.makeAxisAngleRotate = function(
    -    mat, angle, ax, ay, az) {
    -  var c = Math.cos(angle);
    -  var d = 1 - c;
    -  var s = Math.sin(angle);
    -
    -  goog.vec.Matrix3.setFromValues(mat,
    -      ax * ax * d + c,
    -      ax * ay * d + az * s,
    -      ax * az * d - ay * s,
    -
    -      ax * ay * d - az * s,
    -      ay * ay * d + c,
    -      ay * az * d + ax * s,
    -
    -      ax * az * d + ay * s,
    -      ay * az * d - ax * s,
    -      az * az * d + c);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/matrix3_test.html b/src/database/third_party/closure-library/closure/goog/vec/matrix3_test.html
    deleted file mode 100644
    index d66b04fae28..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/matrix3_test.html
    +++ /dev/null
    @@ -1,301 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.vec.Vec3</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.vec.Float32Array');
    -  goog.require('goog.vec.Matrix3');
    -  goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -  function testConstructor() {
    -    var m0 = goog.vec.Matrix3.create();
    -    assertElementsEquals([0, 0, 0, 0, 0, 0, 0, 0, 0], m0);
    -
    -    var m1 = goog.vec.Matrix3.createFromArray([1, 2, 3, 4, 5, 6, 7, 8, 9]);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m1);
    -
    -    var m2 = goog.vec.Matrix3.createFromArray(m1);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m1);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m2);
    -
    -    var m3 = goog.vec.Matrix3.createFromValues(1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m3);
    -
    -    var m4 = goog.vec.Matrix3.createIdentity();
    -    assertElementsEquals([1, 0, 0, 0, 1, 0, 0, 0, 1], m4);
    -  }
    -
    -  function testSet() {
    -    var m0 = goog.vec.Matrix3.create();
    -    var m1 = goog.vec.Matrix3.createFromArray([1, 2, 3, 4, 5, 6, 7, 8, 9]);
    -    goog.vec.Matrix3.setFromArray(m0, m1);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -
    -    goog.vec.Matrix3.setFromValues(m0, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    -    assertElementsEquals([2, 3, 4, 5, 6, 7, 8, 9, 10], m0);
    -  }
    -
    -  function testSetDiagonal() {
    -    var m0 = goog.vec.Matrix3.create();
    -    goog.vec.Matrix3.setDiagonalValues(m0, 1, 2, 3);
    -    assertElementsEquals([1, 0, 0, 0, 2, 0, 0, 0, 3], m0);
    -
    -    goog.vec.Matrix3.setDiagonal(m0, [4, 5, 6]);
    -    assertElementsEquals([4, 0, 0, 0, 5, 0, 0, 0, 6], m0);
    -  }
    -
    -  function testSetGetColumn() {
    -    var m0 = goog.vec.Matrix3.create();
    -    goog.vec.Matrix3.setColumn(m0, 0, [1, 2, 3]);
    -    goog.vec.Matrix3.setColumn(m0, 1, [4, 5, 6]);
    -    goog.vec.Matrix3.setColumn(m0, 2, [7, 8, 9]);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -
    -    var v0 = [0, 0, 0];
    -    goog.vec.Matrix3.getColumn(m0, 0, v0);
    -    assertElementsEquals([1, 2, 3], v0);
    -    goog.vec.Matrix3.getColumn(m0, 1, v0);
    -    assertElementsEquals([4, 5, 6], v0);
    -    goog.vec.Matrix3.getColumn(m0, 2, v0);
    -    assertElementsEquals([7, 8, 9], v0);
    -  }
    -
    -  function testSetGetColumns() {
    -    var m0 = goog.vec.Matrix3.create();
    -    goog.vec.Matrix3.setColumns(m0, [1, 2, 3], [4, 5, 6], [7, 8, 9]);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -
    -    var v0 = [0, 0, 0], v1 = [0, 0, 0], v2 = [0, 0, 0];
    -    goog.vec.Matrix3.getColumns(m0, v0, v1, v2);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals([4, 5, 6], v1);
    -    assertElementsEquals([7, 8, 9], v2);
    -  }
    -
    -  function testSetGetRow() {
    -    var m0 = goog.vec.Matrix3.create();
    -    goog.vec.Matrix3.setRow(m0, 0, [1, 2, 3]);
    -    goog.vec.Matrix3.setRow(m0, 1, [4, 5, 6]);
    -    goog.vec.Matrix3.setRow(m0, 2, [7, 8, 9]);
    -    assertElementsEquals([1, 4, 7, 2, 5, 8, 3, 6, 9], m0);
    -
    -    var v0 = [0, 0, 0];
    -    goog.vec.Matrix3.getRow(m0, 0, v0);
    -    assertElementsEquals([1, 2, 3], v0);
    -    goog.vec.Matrix3.getRow(m0, 1, v0);
    -    assertElementsEquals([4, 5, 6], v0);
    -    goog.vec.Matrix3.getRow(m0, 2, v0);
    -    assertElementsEquals([7, 8, 9], v0);
    -  }
    -
    -  function testSetGetRows() {
    -    var m0 = goog.vec.Matrix3.create();
    -    goog.vec.Matrix3.setRows(m0, [1, 2, 3], [4, 5, 6], [7, 8, 9]);
    -    assertElementsEquals([1, 4, 7, 2, 5, 8, 3, 6, 9], m0);
    -
    -    var v0 = [0, 0, 0], v1 = [0, 0, 0], v2 = [0, 0, 0];
    -    goog.vec.Matrix3.getRows(m0, v0, v1, v2);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals([4, 5, 6], v1);
    -    assertElementsEquals([7, 8, 9], v2);
    -  }
    -
    -  function testSetRowMajorArray() {
    -    var m0 = goog.vec.Matrix3.create();
    -    goog.vec.Matrix3.setFromRowMajorArray(
    -        m0, [1, 2, 3, 4, 5, 6, 7, 8, 9]);
    -    assertElementsEquals([1, 4, 7, 2, 5, 8, 3, 6, 9], m0);
    -  }
    -
    -  function testSetZero() {
    -    var m0 = goog.vec.Matrix3.createFromArray([1, 2, 3, 4, 5, 6, 7, 8, 9]);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -    goog.vec.Matrix3.setZero(m0);
    -    assertElementsEquals([0, 0, 0, 0, 0, 0, 0, 0, 0], m0);
    -  }
    -
    -  function testSetIdentity() {
    -    var m0 = goog.vec.Matrix3.create();
    -    goog.vec.Matrix3.setIdentity(m0);
    -    assertElementsEquals([1, 0, 0, 0, 1, 0, 0, 0, 1], m0);
    -  }
    -
    -  function testSetGetElement() {
    -    var m0 = goog.vec.Matrix3.create();
    -    for (var r = 0; r < 3; r++) {
    -      for (var c = 0; c < 3; c++) {
    -        var value = c * 3 + r + 1;
    -        goog.vec.Matrix3.setElement(m0, r, c, value);
    -        assertEquals(value, goog.vec.Matrix3.getElement(m0, r, c));
    -      }
    -    }
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -  }
    -
    -  function testAdd() {
    -    var m0 = goog.vec.Matrix3.createFromValues(1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var m1 = goog.vec.Matrix3.createFromValues(3, 4, 5, 6, 7, 8, 9, 1, 2);
    -    var m2 = goog.vec.Matrix3.create();
    -    goog.vec.Matrix3.add(m0, m1, m2);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -    assertElementsEquals([3, 4, 5, 6, 7, 8, 9, 1, 2], m1);
    -    assertElementsEquals([4, 6, 8, 10, 12, 14, 16, 9, 11], m2);
    -
    -    goog.vec.Matrix3.add(m0, m1, m0);
    -    assertElementsEquals([3, 4, 5, 6, 7, 8, 9, 1, 2], m1);
    -    assertElementsEquals([4, 6, 8, 10, 12, 14, 16, 9, 11], m0);
    -  }
    -
    -  function testSubtract() {
    -    var m0 = goog.vec.Matrix3.createFromValues(1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var m1 = goog.vec.Matrix3.createFromValues(3, 4, 5, 6, 7, 8, 9, 1, 2);
    -    var m2 = goog.vec.Matrix3.create();
    -
    -    goog.vec.Matrix3.subtract(m0, m1, m2);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -    assertElementsEquals([3, 4, 5, 6, 7, 8, 9, 1, 2], m1);
    -    assertElementsEquals([-2, -2, -2, -2, -2, -2, -2, 7, 7], m2);
    -
    -    goog.vec.Matrix3.subtract(m1, m0, m1);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -    assertElementsEquals([2, 2, 2, 2, 2, 2, 2, -7, -7], m1);
    -  }
    -
    -  function testScale() {
    -    var m0 = goog.vec.Matrix3.createFromValues(1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var m1 = goog.vec.Matrix3.create();
    -
    -    goog.vec.Matrix3.scale(m0, 5, m1);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m0);
    -    assertElementsEquals([5, 10, 15, 20, 25, 30, 35, 40, 45], m1);
    -
    -    goog.vec.Matrix3.scale(m0, 5, m0);
    -    assertElementsEquals([5, 10, 15, 20, 25, 30, 35, 40, 45], m0);
    -  }
    -
    -  function testMultMat() {
    -    var m0 = goog.vec.Matrix3.createFromValues(1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var m1 = goog.vec.Matrix3.createFromValues(1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var m2 = goog.vec.Matrix3.create();
    -
    -    goog.vec.Matrix3.multMat(m0, m1, m2);
    -    assertElementsEquals([30, 36, 42, 66, 81, 96, 102, 126, 150], m2);
    -
    -    goog.vec.Matrix3.add(m0, m1, m1);
    -    goog.vec.Matrix3.multMat(m0, m1, m1);
    -    assertElementsEquals([60, 72, 84, 132, 162, 192, 204, 252, 300], m1);
    -  }
    -
    -  function testTranspose() {
    -    var m0 = goog.vec.Matrix3.createFromValues(1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var m1 = goog.vec.Matrix3.create();
    -    goog.vec.Matrix3.transpose(m0, m1);
    -    assertElementsEquals([1, 4, 7, 2, 5, 8, 3, 6, 9], m1);
    -    goog.vec.Matrix3.transpose(m1, m1);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], m1);
    -  }
    -
    -  function testInvert() {
    -    var m0 = goog.vec.Matrix3.createFromValues(1, 1, 1, 1, 1, 1, 1, 1, 1);
    -    assertFalse(goog.vec.Matrix3.invert(m0, m0));
    -    assertElementsEquals([1, 1, 1, 1, 1, 1, 1, 1, 1], m0);
    -
    -    goog.vec.Matrix3.setFromValues(m0, 1, 2, 3, 1, 3, 4, 3, 4, 5);
    -    assertTrue(goog.vec.Matrix3.invert(m0, m0));
    -    assertElementsEquals([0.5, -1.0, 0.5, -3.5, 2.0, 0.5, 2.5, -1.0, -0.5], m0);
    -
    -    goog.vec.Matrix3.makeScale(m0, .01, .01, .01);
    -    assertTrue(goog.vec.Matrix3.invert(m0, m0));
    -    var m1 = goog.vec.Matrix3.create();
    -    goog.vec.Matrix3.makeScale(m1, 100, 100, 100);
    -    assertElementsEquals(m1, m0);
    -  }
    -
    -  function testEquals() {
    -    var m0 = goog.vec.Matrix3.createFromValues(1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var m1 = goog.vec.Matrix3.createFromArray(m0);
    -    assertTrue(goog.vec.Matrix3.equals(m0, m1));
    -    assertTrue(goog.vec.Matrix3.equals(m1, m0));
    -    for (var i = 0; i < 9; i++) {
    -      m1[i] = 15;
    -      assertFalse(goog.vec.Matrix3.equals(m0, m1));
    -      assertFalse(goog.vec.Matrix3.equals(m1, m0));
    -      m1[i] = i + 1;
    -    }
    -  }
    -
    -  function testMultVec3() {
    -    var m0 = goog.vec.Matrix3.createFromValues(1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    var v0 = [1, 2, 3];
    -    var v1 = [0, 0, 0];
    -
    -    goog.vec.Matrix3.multVec3(m0, v0, v1);
    -    assertElementsEquals([30, 36, 42], v1);
    -    goog.vec.Matrix3.multVec3(m0, v0, v0);
    -    assertElementsEquals([30, 36, 42], v0);
    -  }
    -
    -  function testSetValues() {
    -    var a0 = goog.vec.Matrix3.create();
    -    assertElementsEquals([0, 0, 0, 0, 0, 0, 0, 0, 0], a0);
    -    goog.vec.Matrix3.setFromValues(a0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], a0);
    -
    -    var a1 = goog.vec.Matrix3.create();
    -    goog.vec.Matrix3.setDiagonalValues(a1, 1, 2, 3);
    -    assertElementsEquals([1, 0, 0, 0, 2, 0, 0, 0, 3], a1);
    -
    -    goog.vec.Matrix3.setColumnValues(a1, 0, 2, 3, 4);
    -    goog.vec.Matrix3.setColumnValues(a1, 1, 5, 6, 7);
    -    goog.vec.Matrix3.setColumnValues(a1, 2, 8, 9, 1);
    -    assertElementsEquals([2, 3, 4, 5, 6, 7, 8, 9, 1], a1);
    -
    -    goog.vec.Matrix3.setRowValues(a1, 0, 1, 4, 7);
    -    goog.vec.Matrix3.setRowValues(a1, 1, 2, 5, 8);
    -    goog.vec.Matrix3.setRowValues(a1, 2, 3, 6, 9);
    -    assertElementsEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], a1);
    -  }
    -
    -  function testMakeTranslate() {
    -    var m0 = goog.vec.Matrix3.create();
    -    goog.vec.Matrix3.makeTranslate(m0, 3, 4);
    -    assertElementsEquals([1, 0, 0, 0, 1, 0, 3, 4, 1], m0);
    -  }
    -
    -  function testMakeScale() {
    -    var m0 = goog.vec.Matrix3.create();
    -    goog.vec.Matrix3.makeScale(m0, 3, 4, 5);
    -    assertElementsEquals([3, 0, 0, 0, 4, 0, 0, 0, 5], m0);
    -  }
    -
    -  function testMakeRotate() {
    -    var m0 = goog.vec.Matrix3.create();
    -    goog.vec.Matrix3.makeAxisAngleRotate(m0, Math.PI / 2, 0, 0, 1);
    -    var v0 = [0, 1, 0, -1, 0, 0, 0, 0, 1];
    -    for (var i = 0; i < 9; ++i) {
    -      assertTrue(Math.abs(m0[i] - v0[i]) < 1e-6);
    -    }
    -
    -    var m1 = goog.vec.Matrix3.create();
    -    goog.vec.Matrix3.makeAxisAngleRotate(m1, -Math.PI / 4, 0, 0, 1);
    -    goog.vec.Matrix3.multMat(m0, m1, m1);
    -    var v1 = [0.7071068, 0.7071068, 0, -0.7071068, 0.7071068, 0, 0, 0, 1];
    -    for (var i = 0; i < 9; ++i) {
    -      assertTrue(Math.abs(m1[i] - v1[i]) < 1e-6);
    -    }
    -  }
    -
    -</script>
    -</body>
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/matrix4.js b/src/database/third_party/closure-library/closure/goog/vec/matrix4.js
    deleted file mode 100644
    index c5a693f2cde..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/matrix4.js
    +++ /dev/null
    @@ -1,1405 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview WARNING: DEPRECATED.  Use Mat4 instead.
    - * Implements 4x4 matrices and their related functions which are
    - * compatible with WebGL. The API is structured to avoid unnecessary memory
    - * allocations.  The last parameter will typically be the output vector and
    - * an object can be both an input and output parameter to all methods except
    - * where noted. Matrix operations follow the mathematical form when multiplying
    - * vectors as follows: resultVec = matrix * vec.
    - *
    - */
    -goog.provide('goog.vec.Matrix4');
    -
    -goog.require('goog.vec');
    -goog.require('goog.vec.Vec3');
    -goog.require('goog.vec.Vec4');
    -
    -
    -/**
    - * @typedef {goog.vec.ArrayType}
    - */
    -goog.vec.Matrix4.Type;
    -
    -
    -/**
    - * Creates the array representation of a 4x4 matrix. The use of the array
    - * directly eliminates any overhead associated with the class representation
    - * defined above. The returned matrix is cleared to all zeros.
    - *
    - * @return {goog.vec.Matrix4.Type} The new, sixteen element array.
    - */
    -goog.vec.Matrix4.create = function() {
    -  return new Float32Array(16);
    -};
    -
    -
    -/**
    - * Creates the array representation of a 4x4 matrix. The use of the array
    - * directly eliminates any overhead associated with the class representation
    - * defined above. The returned matrix is initialized with the identity
    - *
    - * @return {goog.vec.Matrix4.Type} The new, sixteen element array.
    - */
    -goog.vec.Matrix4.createIdentity = function() {
    -  var mat = goog.vec.Matrix4.create();
    -  mat[0] = mat[5] = mat[10] = mat[15] = 1;
    -  return mat;
    -};
    -
    -
    -/**
    - * Creates a 4x4 matrix initialized from the given array.
    - *
    - * @param {goog.vec.ArrayType} matrix The array containing the
    - *     matrix values in column major order.
    - * @return {goog.vec.Matrix4.Type} The new, 16 element array.
    - */
    -goog.vec.Matrix4.createFromArray = function(matrix) {
    -  var newMatrix = goog.vec.Matrix4.create();
    -  goog.vec.Matrix4.setFromArray(newMatrix, matrix);
    -  return newMatrix;
    -};
    -
    -
    -/**
    - * Creates a 4x4 matrix initialized from the given values.
    - *
    - * @param {number} v00 The values at (0, 0).
    - * @param {number} v10 The values at (1, 0).
    - * @param {number} v20 The values at (2, 0).
    - * @param {number} v30 The values at (3, 0).
    - * @param {number} v01 The values at (0, 1).
    - * @param {number} v11 The values at (1, 1).
    - * @param {number} v21 The values at (2, 1).
    - * @param {number} v31 The values at (3, 1).
    - * @param {number} v02 The values at (0, 2).
    - * @param {number} v12 The values at (1, 2).
    - * @param {number} v22 The values at (2, 2).
    - * @param {number} v32 The values at (3, 2).
    - * @param {number} v03 The values at (0, 3).
    - * @param {number} v13 The values at (1, 3).
    - * @param {number} v23 The values at (2, 3).
    - * @param {number} v33 The values at (3, 3).
    - * @return {goog.vec.Matrix4.Type} The new, 16 element array.
    - */
    -goog.vec.Matrix4.createFromValues = function(
    -    v00, v10, v20, v30, v01, v11, v21, v31, v02, v12, v22, v32,
    -    v03, v13, v23, v33) {
    -  var newMatrix = goog.vec.Matrix4.create();
    -  goog.vec.Matrix4.setFromValues(
    -      newMatrix, v00, v10, v20, v30, v01, v11, v21, v31, v02, v12, v22, v32,
    -      v03, v13, v23, v33);
    -  return newMatrix;
    -};
    -
    -
    -/**
    - * Creates a clone of a 4x4 matrix.
    - *
    - * @param {goog.vec.Matrix4.Type} matrix The source 4x4 matrix.
    - * @return {goog.vec.Matrix4.Type} The new, 16 element matrix.
    - */
    -goog.vec.Matrix4.clone =
    -    goog.vec.Matrix4.createFromArray;
    -
    -
    -/**
    - * Retrieves the element at the requested row and column.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix containing the
    - *     value to retrieve.
    - * @param {number} row The row index.
    - * @param {number} column The column index.
    - * @return {number} The element value at the requested row, column indices.
    - */
    -goog.vec.Matrix4.getElement = function(mat, row, column) {
    -  return mat[row + column * 4];
    -};
    -
    -
    -/**
    - * Sets the element at the requested row and column.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix containing the
    - *     value to retrieve.
    - * @param {number} row The row index.
    - * @param {number} column The column index.
    - * @param {number} value The value to set at the requested row, column.
    - */
    -goog.vec.Matrix4.setElement = function(mat, row, column, value) {
    -  mat[row + column * 4] = value;
    -};
    -
    -
    -/**
    - * Initializes the matrix from the set of values. Note the values supplied are
    - * in column major order.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to receive the
    - *     values.
    - * @param {number} v00 The values at (0, 0).
    - * @param {number} v10 The values at (1, 0).
    - * @param {number} v20 The values at (2, 0).
    - * @param {number} v30 The values at (3, 0).
    - * @param {number} v01 The values at (0, 1).
    - * @param {number} v11 The values at (1, 1).
    - * @param {number} v21 The values at (2, 1).
    - * @param {number} v31 The values at (3, 1).
    - * @param {number} v02 The values at (0, 2).
    - * @param {number} v12 The values at (1, 2).
    - * @param {number} v22 The values at (2, 2).
    - * @param {number} v32 The values at (3, 2).
    - * @param {number} v03 The values at (0, 3).
    - * @param {number} v13 The values at (1, 3).
    - * @param {number} v23 The values at (2, 3).
    - * @param {number} v33 The values at (3, 3).
    - */
    -goog.vec.Matrix4.setFromValues = function(
    -    mat, v00, v10, v20, v30, v01, v11, v21, v31, v02, v12, v22, v32,
    -    v03, v13, v23, v33) {
    -  mat[0] = v00;
    -  mat[1] = v10;
    -  mat[2] = v20;
    -  mat[3] = v30;
    -  mat[4] = v01;
    -  mat[5] = v11;
    -  mat[6] = v21;
    -  mat[7] = v31;
    -  mat[8] = v02;
    -  mat[9] = v12;
    -  mat[10] = v22;
    -  mat[11] = v32;
    -  mat[12] = v03;
    -  mat[13] = v13;
    -  mat[14] = v23;
    -  mat[15] = v33;
    -};
    -
    -
    -/**
    - * Sets the matrix from the array of values stored in column major order.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to receive the
    - *     values.
    - * @param {goog.vec.ArrayType} values The column major ordered
    - *     array of values to store in the matrix.
    - */
    -goog.vec.Matrix4.setFromArray = function(mat, values) {
    -  mat[0] = values[0];
    -  mat[1] = values[1];
    -  mat[2] = values[2];
    -  mat[3] = values[3];
    -  mat[4] = values[4];
    -  mat[5] = values[5];
    -  mat[6] = values[6];
    -  mat[7] = values[7];
    -  mat[8] = values[8];
    -  mat[9] = values[9];
    -  mat[10] = values[10];
    -  mat[11] = values[11];
    -  mat[12] = values[12];
    -  mat[13] = values[13];
    -  mat[14] = values[14];
    -  mat[15] = values[15];
    -};
    -
    -
    -/**
    - * Sets the matrix from the array of values stored in row major order.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to receive the
    - *     values.
    - * @param {goog.vec.ArrayType} values The row major ordered array of
    - *     values to store in the matrix.
    - */
    -goog.vec.Matrix4.setFromRowMajorArray = function(mat, values) {
    -  mat[0] = values[0];
    -  mat[1] = values[4];
    -  mat[2] = values[8];
    -  mat[3] = values[12];
    -
    -  mat[4] = values[1];
    -  mat[5] = values[5];
    -  mat[6] = values[9];
    -  mat[7] = values[13];
    -
    -  mat[8] = values[2];
    -  mat[9] = values[6];
    -  mat[10] = values[10];
    -  mat[11] = values[14];
    -
    -  mat[12] = values[3];
    -  mat[13] = values[7];
    -  mat[14] = values[11];
    -  mat[15] = values[15];
    -};
    -
    -
    -/**
    - * Sets the diagonal values of the matrix from the given values.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to receive the
    - *     values.
    - * @param {number} v00 The values for (0, 0).
    - * @param {number} v11 The values for (1, 1).
    - * @param {number} v22 The values for (2, 2).
    - * @param {number} v33 The values for (3, 3).
    - */
    -goog.vec.Matrix4.setDiagonalValues = function(
    -    mat, v00, v11, v22, v33) {
    -  mat[0] = v00;
    -  mat[5] = v11;
    -  mat[10] = v22;
    -  mat[15] = v33;
    -};
    -
    -
    -/**
    - * Sets the diagonal values of the matrix from the given vector.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to receive the
    - *     values.
    - * @param {goog.vec.ArrayType} vec The vector containing the
    - *     values.
    - */
    -goog.vec.Matrix4.setDiagonal = function(mat, vec) {
    -  mat[0] = vec[0];
    -  mat[5] = vec[1];
    -  mat[10] = vec[2];
    -  mat[15] = vec[3];
    -};
    -
    -
    -/**
    - * Sets the specified column with the supplied values.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to recieve the
    - *     values.
    - * @param {number} column The column index to set the values on.
    - * @param {number} v0 The value for row 0.
    - * @param {number} v1 The value for row 1.
    - * @param {number} v2 The value for row 2.
    - * @param {number} v3 The value for row 3.
    - */
    -goog.vec.Matrix4.setColumnValues = function(
    -    mat, column, v0, v1, v2, v3) {
    -  var i = column * 4;
    -  mat[i] = v0;
    -  mat[i + 1] = v1;
    -  mat[i + 2] = v2;
    -  mat[i + 3] = v3;
    -};
    -
    -
    -/**
    - * Sets the specified column with the value from the supplied array.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to receive the
    - *     values.
    - * @param {number} column The column index to set the values on.
    - * @param {goog.vec.ArrayType} vec The vector of elements for the
    - *     column.
    - */
    -goog.vec.Matrix4.setColumn = function(mat, column, vec) {
    -  var i = column * 4;
    -  mat[i] = vec[0];
    -  mat[i + 1] = vec[1];
    -  mat[i + 2] = vec[2];
    -  mat[i + 3] = vec[3];
    -};
    -
    -
    -/**
    - * Retrieves the specified column from the matrix into the given vector
    - * array.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix supplying the
    - *     values.
    - * @param {number} column The column to get the values from.
    - * @param {goog.vec.ArrayType} vec The vector of elements to
    - *     receive the column.
    - */
    -goog.vec.Matrix4.getColumn = function(mat, column, vec) {
    -  var i = column * 4;
    -  vec[0] = mat[i];
    -  vec[1] = mat[i + 1];
    -  vec[2] = mat[i + 2];
    -  vec[3] = mat[i + 3];
    -};
    -
    -
    -/**
    - * Sets the columns of the matrix from the set of vector elements.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to receive the
    - *     values.
    - * @param {goog.vec.ArrayType} vec0 The values for column 0.
    - * @param {goog.vec.ArrayType} vec1 The values for column 1.
    - * @param {goog.vec.ArrayType} vec2 The values for column 2.
    - * @param {goog.vec.ArrayType} vec3 The values for column 3.
    - */
    -goog.vec.Matrix4.setColumns = function(
    -    mat, vec0, vec1, vec2, vec3) {
    -  goog.vec.Matrix4.setColumn(mat, 0, vec0);
    -  goog.vec.Matrix4.setColumn(mat, 1, vec1);
    -  goog.vec.Matrix4.setColumn(mat, 2, vec2);
    -  goog.vec.Matrix4.setColumn(mat, 3, vec3);
    -};
    -
    -
    -/**
    - * Retrieves the column values from the given matrix into the given vector
    - * elements.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix containing the
    - *     columns to retrieve.
    - * @param {goog.vec.ArrayType} vec0 The vector elements to receive
    - *     column 0.
    - * @param {goog.vec.ArrayType} vec1 The vector elements to receive
    - *     column 1.
    - * @param {goog.vec.ArrayType} vec2 The vector elements to receive
    - *     column 2.
    - * @param {goog.vec.ArrayType} vec3 The vector elements to receive
    - *     column 3.
    - */
    -goog.vec.Matrix4.getColumns = function(
    -    mat, vec0, vec1, vec2, vec3) {
    -  goog.vec.Matrix4.getColumn(mat, 0, vec0);
    -  goog.vec.Matrix4.getColumn(mat, 1, vec1);
    -  goog.vec.Matrix4.getColumn(mat, 2, vec2);
    -  goog.vec.Matrix4.getColumn(mat, 3, vec3);
    -};
    -
    -
    -/**
    - * Sets the row values from the supplied values.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to receive the
    - *     values.
    - * @param {number} row The index of the row to receive the values.
    - * @param {number} v0 The value for column 0.
    - * @param {number} v1 The value for column 1.
    - * @param {number} v2 The value for column 2.
    - * @param {number} v3 The value for column 3.
    - */
    -goog.vec.Matrix4.setRowValues = function(mat, row, v0, v1, v2, v3) {
    -  mat[row] = v0;
    -  mat[row + 4] = v1;
    -  mat[row + 8] = v2;
    -  mat[row + 12] = v3;
    -};
    -
    -
    -/**
    - * Sets the row values from the supplied vector.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to receive the
    - *     row values.
    - * @param {number} row The index of the row.
    - * @param {goog.vec.ArrayType} vec The vector containing the
    - *     values.
    - */
    -goog.vec.Matrix4.setRow = function(mat, row, vec) {
    -  mat[row] = vec[0];
    -  mat[row + 4] = vec[1];
    -  mat[row + 8] = vec[2];
    -  mat[row + 12] = vec[3];
    -};
    -
    -
    -/**
    - * Retrieves the row values into the given vector.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix supplying the
    - *     values.
    - * @param {number} row The index of the row supplying the values.
    - * @param {goog.vec.ArrayType} vec The vector to receive the
    - *     row.
    - */
    -goog.vec.Matrix4.getRow = function(mat, row, vec) {
    -  vec[0] = mat[row];
    -  vec[1] = mat[row + 4];
    -  vec[2] = mat[row + 8];
    -  vec[3] = mat[row + 12];
    -};
    -
    -
    -/**
    - * Sets the rows of the matrix from the supplied vectors.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to receive the
    - *     values.
    - * @param {goog.vec.ArrayType} vec0 The values for row 0.
    - * @param {goog.vec.ArrayType} vec1 The values for row 1.
    - * @param {goog.vec.ArrayType} vec2 The values for row 2.
    - * @param {goog.vec.ArrayType} vec3 The values for row 3.
    - */
    -goog.vec.Matrix4.setRows = function(
    -    mat, vec0, vec1, vec2, vec3) {
    -  goog.vec.Matrix4.setRow(mat, 0, vec0);
    -  goog.vec.Matrix4.setRow(mat, 1, vec1);
    -  goog.vec.Matrix4.setRow(mat, 2, vec2);
    -  goog.vec.Matrix4.setRow(mat, 3, vec3);
    -};
    -
    -
    -/**
    - * Retrieves the rows of the matrix into the supplied vectors.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to supply the
    - *     values.
    - * @param {goog.vec.ArrayType} vec0 The vector to receive row 0.
    - * @param {goog.vec.ArrayType} vec1 The vector to receive row 1.
    - * @param {goog.vec.ArrayType} vec2 The vector to receive row 2.
    - * @param {goog.vec.ArrayType} vec3 The vector to receive row 3.
    - */
    -goog.vec.Matrix4.getRows = function(
    -    mat, vec0, vec1, vec2, vec3) {
    -  goog.vec.Matrix4.getRow(mat, 0, vec0);
    -  goog.vec.Matrix4.getRow(mat, 1, vec1);
    -  goog.vec.Matrix4.getRow(mat, 2, vec2);
    -  goog.vec.Matrix4.getRow(mat, 3, vec3);
    -};
    -
    -
    -/**
    - * Clears the given matrix to zero.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to clear.
    - */
    -goog.vec.Matrix4.setZero = function(mat) {
    -  mat[0] = 0;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 0;
    -  mat[5] = 0;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = 0;
    -  mat[9] = 0;
    -  mat[10] = 0;
    -  mat[11] = 0;
    -  mat[12] = 0;
    -  mat[13] = 0;
    -  mat[14] = 0;
    -  mat[15] = 0;
    -};
    -
    -
    -/**
    - * Sets the given matrix to the identity matrix.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to set.
    - */
    -goog.vec.Matrix4.setIdentity = function(mat) {
    -  mat[0] = 1;
    -  mat[1] = 0;
    -  mat[2] = 0;
    -  mat[3] = 0;
    -  mat[4] = 0;
    -  mat[5] = 1;
    -  mat[6] = 0;
    -  mat[7] = 0;
    -  mat[8] = 0;
    -  mat[9] = 0;
    -  mat[10] = 1;
    -  mat[11] = 0;
    -  mat[12] = 0;
    -  mat[13] = 0;
    -  mat[14] = 0;
    -  mat[15] = 1;
    -};
    -
    -
    -/**
    - * Performs a per-component addition of the matrix mat0 and mat1, storing
    - * the result into resultMat.
    - *
    - * @param {goog.vec.ArrayType} mat0 The first addend.
    - * @param {goog.vec.ArrayType} mat1 The second addend.
    - * @param {goog.vec.ArrayType} resultMat The matrix to
    - *     receive the results (may be either mat0 or mat1).
    - * @return {goog.vec.ArrayType} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Matrix4.add = function(mat0, mat1, resultMat) {
    -  resultMat[0] = mat0[0] + mat1[0];
    -  resultMat[1] = mat0[1] + mat1[1];
    -  resultMat[2] = mat0[2] + mat1[2];
    -  resultMat[3] = mat0[3] + mat1[3];
    -  resultMat[4] = mat0[4] + mat1[4];
    -  resultMat[5] = mat0[5] + mat1[5];
    -  resultMat[6] = mat0[6] + mat1[6];
    -  resultMat[7] = mat0[7] + mat1[7];
    -  resultMat[8] = mat0[8] + mat1[8];
    -  resultMat[9] = mat0[9] + mat1[9];
    -  resultMat[10] = mat0[10] + mat1[10];
    -  resultMat[11] = mat0[11] + mat1[11];
    -  resultMat[12] = mat0[12] + mat1[12];
    -  resultMat[13] = mat0[13] + mat1[13];
    -  resultMat[14] = mat0[14] + mat1[14];
    -  resultMat[15] = mat0[15] + mat1[15];
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Performs a per-component subtraction of the matrix mat0 and mat1,
    - * storing the result into resultMat.
    - *
    - * @param {goog.vec.ArrayType} mat0 The minuend.
    - * @param {goog.vec.ArrayType} mat1 The subtrahend.
    - * @param {goog.vec.ArrayType} resultMat The matrix to receive
    - *     the results (may be either mat0 or mat1).
    - * @return {goog.vec.ArrayType} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Matrix4.subtract = function(mat0, mat1, resultMat) {
    -  resultMat[0] = mat0[0] - mat1[0];
    -  resultMat[1] = mat0[1] - mat1[1];
    -  resultMat[2] = mat0[2] - mat1[2];
    -  resultMat[3] = mat0[3] - mat1[3];
    -  resultMat[4] = mat0[4] - mat1[4];
    -  resultMat[5] = mat0[5] - mat1[5];
    -  resultMat[6] = mat0[6] - mat1[6];
    -  resultMat[7] = mat0[7] - mat1[7];
    -  resultMat[8] = mat0[8] - mat1[8];
    -  resultMat[9] = mat0[9] - mat1[9];
    -  resultMat[10] = mat0[10] - mat1[10];
    -  resultMat[11] = mat0[11] - mat1[11];
    -  resultMat[12] = mat0[12] - mat1[12];
    -  resultMat[13] = mat0[13] - mat1[13];
    -  resultMat[14] = mat0[14] - mat1[14];
    -  resultMat[15] = mat0[15] - mat1[15];
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Performs a component-wise multiplication of mat0 with the given scalar
    - * storing the result into resultMat.
    - *
    - * @param {goog.vec.ArrayType} mat0 The matrix to scale.
    - * @param {number} scalar The scalar value to multiple to each element of mat0.
    - * @param {goog.vec.ArrayType} resultMat The matrix to receive
    - *     the results (may be mat0).
    - * @return {goog.vec.ArrayType} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Matrix4.scale = function(mat0, scalar, resultMat) {
    -  resultMat[0] = mat0[0] * scalar;
    -  resultMat[1] = mat0[1] * scalar;
    -  resultMat[2] = mat0[2] * scalar;
    -  resultMat[3] = mat0[3] * scalar;
    -  resultMat[4] = mat0[4] * scalar;
    -  resultMat[5] = mat0[5] * scalar;
    -  resultMat[6] = mat0[6] * scalar;
    -  resultMat[7] = mat0[7] * scalar;
    -  resultMat[8] = mat0[8] * scalar;
    -  resultMat[9] = mat0[9] * scalar;
    -  resultMat[10] = mat0[10] * scalar;
    -  resultMat[11] = mat0[11] * scalar;
    -  resultMat[12] = mat0[12] * scalar;
    -  resultMat[13] = mat0[13] * scalar;
    -  resultMat[14] = mat0[14] * scalar;
    -  resultMat[15] = mat0[15] * scalar;
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Multiplies the two matrices mat0 and mat1 using matrix multiplication,
    - * storing the result into resultMat.
    - *
    - * @param {goog.vec.ArrayType} mat0 The first (left hand) matrix.
    - * @param {goog.vec.ArrayType} mat1 The second (right hand)
    - *     matrix.
    - * @param {goog.vec.ArrayType} resultMat The matrix to receive
    - *     the results (may be either mat0 or mat1).
    - * @return {goog.vec.ArrayType} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Matrix4.multMat = function(mat0, mat1, resultMat) {
    -  var a00 = mat0[0], a10 = mat0[1], a20 = mat0[2], a30 = mat0[3];
    -  var a01 = mat0[4], a11 = mat0[5], a21 = mat0[6], a31 = mat0[7];
    -  var a02 = mat0[8], a12 = mat0[9], a22 = mat0[10], a32 = mat0[11];
    -  var a03 = mat0[12], a13 = mat0[13], a23 = mat0[14], a33 = mat0[15];
    -
    -  var b00 = mat1[0], b10 = mat1[1], b20 = mat1[2], b30 = mat1[3];
    -  var b01 = mat1[4], b11 = mat1[5], b21 = mat1[6], b31 = mat1[7];
    -  var b02 = mat1[8], b12 = mat1[9], b22 = mat1[10], b32 = mat1[11];
    -  var b03 = mat1[12], b13 = mat1[13], b23 = mat1[14], b33 = mat1[15];
    -
    -  resultMat[0] = a00 * b00 + a01 * b10 + a02 * b20 + a03 * b30;
    -  resultMat[1] = a10 * b00 + a11 * b10 + a12 * b20 + a13 * b30;
    -  resultMat[2] = a20 * b00 + a21 * b10 + a22 * b20 + a23 * b30;
    -  resultMat[3] = a30 * b00 + a31 * b10 + a32 * b20 + a33 * b30;
    -
    -  resultMat[4] = a00 * b01 + a01 * b11 + a02 * b21 + a03 * b31;
    -  resultMat[5] = a10 * b01 + a11 * b11 + a12 * b21 + a13 * b31;
    -  resultMat[6] = a20 * b01 + a21 * b11 + a22 * b21 + a23 * b31;
    -  resultMat[7] = a30 * b01 + a31 * b11 + a32 * b21 + a33 * b31;
    -
    -  resultMat[8] = a00 * b02 + a01 * b12 + a02 * b22 + a03 * b32;
    -  resultMat[9] = a10 * b02 + a11 * b12 + a12 * b22 + a13 * b32;
    -  resultMat[10] = a20 * b02 + a21 * b12 + a22 * b22 + a23 * b32;
    -  resultMat[11] = a30 * b02 + a31 * b12 + a32 * b22 + a33 * b32;
    -
    -  resultMat[12] = a00 * b03 + a01 * b13 + a02 * b23 + a03 * b33;
    -  resultMat[13] = a10 * b03 + a11 * b13 + a12 * b23 + a13 * b33;
    -  resultMat[14] = a20 * b03 + a21 * b13 + a22 * b23 + a23 * b33;
    -  resultMat[15] = a30 * b03 + a31 * b13 + a32 * b23 + a33 * b33;
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Transposes the given matrix mat storing the result into resultMat.
    - * @param {goog.vec.ArrayType} mat The matrix to transpose.
    - * @param {goog.vec.ArrayType} resultMat The matrix to receive
    - *     the results (may be mat).
    - * @return {goog.vec.ArrayType} return resultMat so that operations can be
    - *     chained together.
    - */
    -goog.vec.Matrix4.transpose = function(mat, resultMat) {
    -  if (resultMat == mat) {
    -    var a10 = mat[1], a20 = mat[2], a30 = mat[3];
    -    var a21 = mat[6], a31 = mat[7];
    -    var a32 = mat[11];
    -    resultMat[1] = mat[4];
    -    resultMat[2] = mat[8];
    -    resultMat[3] = mat[12];
    -    resultMat[4] = a10;
    -    resultMat[6] = mat[9];
    -    resultMat[7] = mat[13];
    -    resultMat[8] = a20;
    -    resultMat[9] = a21;
    -    resultMat[11] = mat[14];
    -    resultMat[12] = a30;
    -    resultMat[13] = a31;
    -    resultMat[14] = a32;
    -  } else {
    -    resultMat[0] = mat[0];
    -    resultMat[1] = mat[4];
    -    resultMat[2] = mat[8];
    -    resultMat[3] = mat[12];
    -
    -    resultMat[4] = mat[1];
    -    resultMat[5] = mat[5];
    -    resultMat[6] = mat[9];
    -    resultMat[7] = mat[13];
    -
    -    resultMat[8] = mat[2];
    -    resultMat[9] = mat[6];
    -    resultMat[10] = mat[10];
    -    resultMat[11] = mat[14];
    -
    -    resultMat[12] = mat[3];
    -    resultMat[13] = mat[7];
    -    resultMat[14] = mat[11];
    -    resultMat[15] = mat[15];
    -  }
    -  return resultMat;
    -};
    -
    -
    -/**
    - * Computes the determinant of the matrix.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to compute the
    - *     matrix for.
    - * @return {number} The determinant of the matrix.
    - */
    -goog.vec.Matrix4.determinant = function(mat) {
    -  var m00 = mat[0], m10 = mat[1], m20 = mat[2], m30 = mat[3];
    -  var m01 = mat[4], m11 = mat[5], m21 = mat[6], m31 = mat[7];
    -  var m02 = mat[8], m12 = mat[9], m22 = mat[10], m32 = mat[11];
    -  var m03 = mat[12], m13 = mat[13], m23 = mat[14], m33 = mat[15];
    -
    -  var a0 = m00 * m11 - m10 * m01;
    -  var a1 = m00 * m21 - m20 * m01;
    -  var a2 = m00 * m31 - m30 * m01;
    -  var a3 = m10 * m21 - m20 * m11;
    -  var a4 = m10 * m31 - m30 * m11;
    -  var a5 = m20 * m31 - m30 * m21;
    -  var b0 = m02 * m13 - m12 * m03;
    -  var b1 = m02 * m23 - m22 * m03;
    -  var b2 = m02 * m33 - m32 * m03;
    -  var b3 = m12 * m23 - m22 * m13;
    -  var b4 = m12 * m33 - m32 * m13;
    -  var b5 = m22 * m33 - m32 * m23;
    -
    -  return a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0;
    -};
    -
    -
    -/**
    - * Computes the inverse of mat storing the result into resultMat. If the
    - * inverse is defined, this function returns true, false otherwise.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix to invert.
    - * @param {goog.vec.ArrayType} resultMat The matrix to receive
    - *     the result (may be mat).
    - * @return {boolean} True if the inverse is defined. If false is returned,
    - *     resultMat is not modified.
    - */
    -goog.vec.Matrix4.invert = function(mat, resultMat) {
    -  var m00 = mat[0], m10 = mat[1], m20 = mat[2], m30 = mat[3];
    -  var m01 = mat[4], m11 = mat[5], m21 = mat[6], m31 = mat[7];
    -  var m02 = mat[8], m12 = mat[9], m22 = mat[10], m32 = mat[11];
    -  var m03 = mat[12], m13 = mat[13], m23 = mat[14], m33 = mat[15];
    -
    -  var a0 = m00 * m11 - m10 * m01;
    -  var a1 = m00 * m21 - m20 * m01;
    -  var a2 = m00 * m31 - m30 * m01;
    -  var a3 = m10 * m21 - m20 * m11;
    -  var a4 = m10 * m31 - m30 * m11;
    -  var a5 = m20 * m31 - m30 * m21;
    -  var b0 = m02 * m13 - m12 * m03;
    -  var b1 = m02 * m23 - m22 * m03;
    -  var b2 = m02 * m33 - m32 * m03;
    -  var b3 = m12 * m23 - m22 * m13;
    -  var b4 = m12 * m33 - m32 * m13;
    -  var b5 = m22 * m33 - m32 * m23;
    -
    -  var det = a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0;
    -  if (det == 0) {
    -    return false;
    -  }
    -
    -  var idet = 1.0 / det;
    -  resultMat[0] = (m11 * b5 - m21 * b4 + m31 * b3) * idet;
    -  resultMat[1] = (-m10 * b5 + m20 * b4 - m30 * b3) * idet;
    -  resultMat[2] = (m13 * a5 - m23 * a4 + m33 * a3) * idet;
    -  resultMat[3] = (-m12 * a5 + m22 * a4 - m32 * a3) * idet;
    -  resultMat[4] = (-m01 * b5 + m21 * b2 - m31 * b1) * idet;
    -  resultMat[5] = (m00 * b5 - m20 * b2 + m30 * b1) * idet;
    -  resultMat[6] = (-m03 * a5 + m23 * a2 - m33 * a1) * idet;
    -  resultMat[7] = (m02 * a5 - m22 * a2 + m32 * a1) * idet;
    -  resultMat[8] = (m01 * b4 - m11 * b2 + m31 * b0) * idet;
    -  resultMat[9] = (-m00 * b4 + m10 * b2 - m30 * b0) * idet;
    -  resultMat[10] = (m03 * a4 - m13 * a2 + m33 * a0) * idet;
    -  resultMat[11] = (-m02 * a4 + m12 * a2 - m32 * a0) * idet;
    -  resultMat[12] = (-m01 * b3 + m11 * b1 - m21 * b0) * idet;
    -  resultMat[13] = (m00 * b3 - m10 * b1 + m20 * b0) * idet;
    -  resultMat[14] = (-m03 * a3 + m13 * a1 - m23 * a0) * idet;
    -  resultMat[15] = (m02 * a3 - m12 * a1 + m22 * a0) * idet;
    -  return true;
    -};
    -
    -
    -/**
    - * Returns true if the components of mat0 are equal to the components of mat1.
    - *
    - * @param {goog.vec.ArrayType} mat0 The first matrix.
    - * @param {goog.vec.ArrayType} mat1 The second matrix.
    - * @return {boolean} True if the the two matrices are equivalent.
    - */
    -goog.vec.Matrix4.equals = function(mat0, mat1) {
    -  return mat0.length == mat1.length &&
    -      mat0[0] == mat1[0] &&
    -      mat0[1] == mat1[1] &&
    -      mat0[2] == mat1[2] &&
    -      mat0[3] == mat1[3] &&
    -      mat0[4] == mat1[4] &&
    -      mat0[5] == mat1[5] &&
    -      mat0[6] == mat1[6] &&
    -      mat0[7] == mat1[7] &&
    -      mat0[8] == mat1[8] &&
    -      mat0[9] == mat1[9] &&
    -      mat0[10] == mat1[10] &&
    -      mat0[11] == mat1[11] &&
    -      mat0[12] == mat1[12] &&
    -      mat0[13] == mat1[13] &&
    -      mat0[14] == mat1[14] &&
    -      mat0[15] == mat1[15];
    -};
    -
    -
    -/**
    - * Transforms the given vector with the given matrix storing the resulting,
    - * transformed vector into resultVec. The input vector is multiplied against the
    - * upper 3x4 matrix omitting the projective component.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix supplying the
    - *     transformation.
    - * @param {goog.vec.ArrayType} vec The 3 element vector to
    - *     transform.
    - * @param {goog.vec.ArrayType} resultVec The 3 element vector to
    - *     receive the results (may be vec).
    - * @return {goog.vec.ArrayType} return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Matrix4.multVec3 = function(mat, vec, resultVec) {
    -  var x = vec[0], y = vec[1], z = vec[2];
    -  resultVec[0] = x * mat[0] + y * mat[4] + z * mat[8] + mat[12];
    -  resultVec[1] = x * mat[1] + y * mat[5] + z * mat[9] + mat[13];
    -  resultVec[2] = x * mat[2] + y * mat[6] + z * mat[10] + mat[14];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Transforms the given vector with the given matrix storing the resulting,
    - * transformed vector into resultVec. The input vector is multiplied against the
    - * upper 3x3 matrix omitting the projective component and translation
    - * components.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix supplying the
    - *     transformation.
    - * @param {goog.vec.ArrayType} vec The 3 element vector to
    - *     transform.
    - * @param {goog.vec.ArrayType} resultVec The 3 element vector to
    - *     receive the results (may be vec).
    - * @return {goog.vec.ArrayType} return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Matrix4.multVec3NoTranslate = function(
    -    mat, vec, resultVec) {
    -  var x = vec[0], y = vec[1], z = vec[2];
    -  resultVec[0] = x * mat[0] + y * mat[4] + z * mat[8];
    -  resultVec[1] = x * mat[1] + y * mat[5] + z * mat[9];
    -  resultVec[2] = x * mat[2] + y * mat[6] + z * mat[10];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Transforms the given vector with the given matrix storing the resulting,
    - * transformed vector into resultVec. The input vector is multiplied against the
    - * full 4x4 matrix with the homogeneous divide applied to reduce the 4 element
    - * vector to a 3 element vector.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix supplying the
    - *     transformation.
    - * @param {goog.vec.ArrayType} vec The 3 element vector to
    - *     transform.
    - * @param {goog.vec.ArrayType} resultVec The 3 element vector
    - *     to receive the results (may be vec).
    - * @return {goog.vec.ArrayType} return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Matrix4.multVec3Projective = function(
    -    mat, vec, resultVec) {
    -  var x = vec[0], y = vec[1], z = vec[2];
    -  var invw = 1 / (x * mat[3] + y * mat[7] + z * mat[11] + mat[15]);
    -  resultVec[0] = (x * mat[0] + y * mat[4] + z * mat[8] + mat[12]) * invw;
    -  resultVec[1] = (x * mat[1] + y * mat[5] + z * mat[9] + mat[13]) * invw;
    -  resultVec[2] = (x * mat[2] + y * mat[6] + z * mat[10] + mat[14]) * invw;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Transforms the given vector with the given matrix storing the resulting,
    - * transformed vector into resultVec.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix supplying the
    - *     transformation.
    - * @param {goog.vec.ArrayType} vec The vector to transform.
    - * @param {goog.vec.ArrayType} resultVec The vector to
    - *     receive the results (may be vec).
    - * @return {goog.vec.ArrayType} return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Matrix4.multVec4 = function(mat, vec, resultVec) {
    -  var x = vec[0], y = vec[1], z = vec[2], w = vec[3];
    -  resultVec[0] = x * mat[0] + y * mat[4] + z * mat[8] + w * mat[12];
    -  resultVec[1] = x * mat[1] + y * mat[5] + z * mat[9] + w * mat[13];
    -  resultVec[2] = x * mat[2] + y * mat[6] + z * mat[10] + w * mat[14];
    -  resultVec[3] = x * mat[3] + y * mat[7] + z * mat[11] + w * mat[15];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Transforms the given vector with the given matrix storing the resulting,
    - * transformed vector into resultVec. The input matrix is multiplied against the
    - * upper 3x4 matrix omitting the projective component.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix supplying the
    - *     transformation.
    - * @param {goog.vec.ArrayType} vec The 3 element vector to
    - *     transform.
    - * @param {goog.vec.ArrayType} resultVec The 3 element vector to
    - *     receive the results (may be vec).
    - * @return {goog.vec.ArrayType} return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Matrix4.multVec3ToArray = function(mat, vec, resultVec) {
    -  goog.vec.Matrix4.multVec3(
    -      mat, vec, /** @type {goog.vec.ArrayType} */ (resultVec));
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Transforms the given vector with the given matrix storing the resulting,
    - * transformed vector into resultVec.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix supplying the
    - *     transformation.
    - * @param {goog.vec.ArrayType} vec The vector to transform.
    - * @param {goog.vec.ArrayType} resultVec The vector to
    - *     receive the results (may be vec).
    - * @return {goog.vec.ArrayType} return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Matrix4.multVec4ToArray = function(mat, vec, resultVec) {
    -  goog.vec.Matrix4.multVec4(
    -      mat, vec, /** @type {goog.vec.ArrayType} */ (resultVec));
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Initializes the given 4x4 matrix as a translation matrix with x, y and z
    - * translation factors.
    - * @param {goog.vec.ArrayType} mat The 4x4 (16-element) matrix
    - *     array to receive the new translation matrix.
    - * @param {number} x The translation along the x axis.
    - * @param {number} y The translation along the y axis.
    - * @param {number} z The translation along the z axis.
    - */
    -goog.vec.Matrix4.makeTranslate = function(mat, x, y, z) {
    -  goog.vec.Matrix4.setIdentity(mat);
    -  goog.vec.Matrix4.setColumnValues(mat, 3, x, y, z, 1);
    -};
    -
    -
    -/**
    - * Initializes the given 4x4 matrix as a scale matrix with x, y and z scale
    - * factors.
    - * @param {goog.vec.ArrayType} mat The 4x4 (16-element) matrix
    - *     array to receive the new translation matrix.
    - * @param {number} x The scale along the x axis.
    - * @param {number} y The scale along the y axis.
    - * @param {number} z The scale along the z axis.
    - */
    -goog.vec.Matrix4.makeScale = function(mat, x, y, z) {
    -  goog.vec.Matrix4.setIdentity(mat);
    -  goog.vec.Matrix4.setDiagonalValues(mat, x, y, z, 1);
    -};
    -
    -
    -/**
    - * Initializes the given 4x4 matrix as a rotation matrix with the given rotation
    - * angle about the axis defined by the vector (ax, ay, az).
    - * @param {goog.vec.ArrayType} mat The 4x4 (16-element) matrix
    - *     array to receive the new translation matrix.
    - * @param {number} angle The rotation angle in radians.
    - * @param {number} ax The x component of the rotation axis.
    - * @param {number} ay The y component of the rotation axis.
    - * @param {number} az The z component of the rotation axis.
    - */
    -goog.vec.Matrix4.makeAxisAngleRotate = function(
    -    mat, angle, ax, ay, az) {
    -  var c = Math.cos(angle);
    -  var d = 1 - c;
    -  var s = Math.sin(angle);
    -
    -  goog.vec.Matrix4.setFromValues(mat,
    -      ax * ax * d + c,
    -      ax * ay * d + az * s,
    -      ax * az * d - ay * s,
    -      0,
    -
    -      ax * ay * d - az * s,
    -      ay * ay * d + c,
    -      ay * az * d + ax * s,
    -      0,
    -
    -      ax * az * d + ay * s,
    -      ay * az * d - ax * s,
    -      az * az * d + c,
    -      0,
    -
    -      0, 0, 0, 1);
    -};
    -
    -
    -/**
    - * Initializes the given 4x4 matrix as a perspective projection matrix.
    - * @param {goog.vec.ArrayType} mat The 4x4 (16-element) matrix
    - *     array to receive the new translation matrix.
    - * @param {number} left The coordinate of the left clipping plane.
    - * @param {number} right The coordinate of the right clipping plane.
    - * @param {number} bottom The coordinate of the bottom clipping plane.
    - * @param {number} top The coordinate of the top clipping plane.
    - * @param {number} near The distance to the near clipping plane.
    - * @param {number} far The distance to the far clipping plane.
    - */
    -goog.vec.Matrix4.makeFrustum = function(
    -    mat, left, right, bottom, top, near, far) {
    -  var x = (2 * near) / (right - left);
    -  var y = (2 * near) / (top - bottom);
    -  var a = (right + left) / (right - left);
    -  var b = (top + bottom) / (top - bottom);
    -  var c = -(far + near) / (far - near);
    -  var d = -(2 * far * near) / (far - near);
    -
    -  goog.vec.Matrix4.setFromValues(mat,
    -      x, 0, 0, 0,
    -      0, y, 0, 0,
    -      a, b, c, -1,
    -      0, 0, d, 0
    -  );
    -};
    -
    -
    -/**
    - * Initializes the given 4x4 matrix as a perspective projection matrix given a
    - * field of view and aspect ratio.
    - * @param {goog.vec.ArrayType} mat The 4x4 (16-element) matrix
    - *     array to receive the new translation matrix.
    - * @param {number} fovy The field of view along the y (vertical) axis in
    - *     radians.
    - * @param {number} aspect The x (width) to y (height) aspect ratio.
    - * @param {number} near The distance to the near clipping plane.
    - * @param {number} far The distance to the far clipping plane.
    - */
    -goog.vec.Matrix4.makePerspective = function(
    -    mat, fovy, aspect, near, far) {
    -  var angle = fovy / 2;
    -  var dz = far - near;
    -  var sinAngle = Math.sin(angle);
    -  if (dz == 0 || sinAngle == 0 || aspect == 0) return;
    -
    -  var cot = Math.cos(angle) / sinAngle;
    -  goog.vec.Matrix4.setFromValues(mat,
    -      cot / aspect, 0, 0, 0,
    -      0, cot, 0, 0,
    -      0, 0, -(far + near) / dz, -1,
    -      0, 0, -(2 * near * far) / dz, 0
    -  );
    -};
    -
    -
    -/**
    - * Initializes the given 4x4 matrix as an orthographic projection matrix.
    - * @param {goog.vec.ArrayType} mat The 4x4 (16-element) matrix
    - *     array to receive the new translation matrix.
    - * @param {number} left The coordinate of the left clipping plane.
    - * @param {number} right The coordinate of the right clipping plane.
    - * @param {number} bottom The coordinate of the bottom clipping plane.
    - * @param {number} top The coordinate of the top clipping plane.
    - * @param {number} near The distance to the near clipping plane.
    - * @param {number} far The distance to the far clipping plane.
    - */
    -goog.vec.Matrix4.makeOrtho = function(
    -    mat, left, right, bottom, top, near, far) {
    -  var x = 2 / (right - left);
    -  var y = 2 / (top - bottom);
    -  var z = -2 / (far - near);
    -  var a = -(right + left) / (right - left);
    -  var b = -(top + bottom) / (top - bottom);
    -  var c = -(far + near) / (far - near);
    -
    -  goog.vec.Matrix4.setFromValues(mat,
    -      x, 0, 0, 0,
    -      0, y, 0, 0,
    -      0, 0, z, 0,
    -      a, b, c, 1
    -  );
    -};
    -
    -
    -/**
    - * Updates a matrix representing the modelview matrix of a camera so that
    - * the camera is 'looking at' the given center point.
    - * @param {goog.vec.ArrayType} viewMatrix The matrix.
    - * @param {goog.vec.ArrayType} eyePt The position of the eye point
    - *     (camera origin).
    - * @param {goog.vec.ArrayType} centerPt The point to aim the camera
    - *     at.
    - * @param {goog.vec.ArrayType} worldUpVec The vector that
    - *     identifies the up direction for the camera.
    - */
    -goog.vec.Matrix4.lookAt = function(
    -    viewMatrix, eyePt, centerPt, worldUpVec) {
    -  // Compute the direction vector from the eye point to the center point and
    -  // normalize.
    -  var fwdVec = goog.vec.Matrix4.tmpVec4_[0];
    -  goog.vec.Vec3.subtract(centerPt, eyePt, fwdVec);
    -  goog.vec.Vec3.normalize(fwdVec, fwdVec);
    -  fwdVec[3] = 0;
    -
    -  // Compute the side vector from the forward vector and the input up vector.
    -  var sideVec = goog.vec.Matrix4.tmpVec4_[1];
    -  goog.vec.Vec3.cross(fwdVec, worldUpVec, sideVec);
    -  goog.vec.Vec3.normalize(sideVec, sideVec);
    -  sideVec[3] = 0;
    -
    -  // Now the up vector to form the orthonormal basis.
    -  var upVec = goog.vec.Matrix4.tmpVec4_[2];
    -  goog.vec.Vec3.cross(sideVec, fwdVec, upVec);
    -  goog.vec.Vec3.normalize(upVec, upVec);
    -  upVec[3] = 0;
    -
    -  // Update the view matrix with the new orthonormal basis and position the
    -  // camera at the given eye point.
    -  goog.vec.Vec3.negate(fwdVec, fwdVec);
    -  goog.vec.Matrix4.setRow(viewMatrix, 0, sideVec);
    -  goog.vec.Matrix4.setRow(viewMatrix, 1, upVec);
    -  goog.vec.Matrix4.setRow(viewMatrix, 2, fwdVec);
    -  goog.vec.Matrix4.setRowValues(viewMatrix, 3, 0, 0, 0, 1);
    -  goog.vec.Matrix4.applyTranslate(
    -      viewMatrix, -eyePt[0], -eyePt[1], -eyePt[2]);
    -};
    -
    -
    -/**
    - * Decomposes a matrix into the lookAt vectors eyePt, fwdVec and worldUpVec.
    - * The matrix represents the modelview matrix of a camera. It is the inverse
    - * of lookAt except for the output of the fwdVec instead of centerPt.
    - * The centerPt itself cannot be recovered from a modelview matrix.
    - * @param {goog.vec.ArrayType} viewMatrix The matrix.
    - * @param {goog.vec.ArrayType} eyePt The position of the eye point
    - *     (camera origin).
    - * @param {goog.vec.ArrayType} fwdVec The vector describing where
    - *     the camera points to.
    - * @param {goog.vec.ArrayType} worldUpVec The vector that
    - *     identifies the up direction for the camera.
    - * @return {boolean} True if the method succeeds, false otherwise.
    - *     The method can only fail if the inverse of viewMatrix is not defined.
    - */
    -goog.vec.Matrix4.toLookAt = function(
    -    viewMatrix, eyePt, fwdVec, worldUpVec) {
    -  // Get eye of the camera.
    -  var viewMatrixInverse = goog.vec.Matrix4.tmpMatrix4_[0];
    -  if (!goog.vec.Matrix4.invert(viewMatrix, viewMatrixInverse)) {
    -    // The input matrix does not have a valid inverse.
    -    return false;
    -  }
    -
    -  if (eyePt) {
    -    eyePt[0] = viewMatrixInverse[12];
    -    eyePt[1] = viewMatrixInverse[13];
    -    eyePt[2] = viewMatrixInverse[14];
    -  }
    -
    -  // Get forward vector from the definition of lookAt.
    -  if (fwdVec || worldUpVec) {
    -    if (!fwdVec) {
    -      fwdVec = goog.vec.Matrix4.tmpVec3_[0];
    -    }
    -    fwdVec[0] = -viewMatrix[2];
    -    fwdVec[1] = -viewMatrix[6];
    -    fwdVec[2] = -viewMatrix[10];
    -    // Normalize forward vector.
    -    goog.vec.Vec3.normalize(fwdVec, fwdVec);
    -  }
    -
    -  if (worldUpVec) {
    -    // Get side vector from the definition of gluLookAt.
    -    var side = goog.vec.Matrix4.tmpVec3_[1];
    -    side[0] = viewMatrix[0];
    -    side[1] = viewMatrix[4];
    -    side[2] = viewMatrix[8];
    -    // Compute up vector as a up = side x forward.
    -    goog.vec.Vec3.cross(side, fwdVec, worldUpVec);
    -    // Normalize up vector.
    -    goog.vec.Vec3.normalize(worldUpVec, worldUpVec);
    -  }
    -  return true;
    -};
    -
    -
    -/**
    - * Constructs a rotation matrix from its Euler angles using the ZXZ convention.
    - * Given the euler angles [theta1, theta2, theta3], the rotation is defined as
    - * rotation = rotation_z(theta1) * rotation_x(theta2) * rotation_z(theta3),
    - * where rotation_x(theta) means rotation around the X axis of theta radians.
    - * @param {goog.vec.ArrayType} matrix The rotation matrix.
    - * @param {number} theta1 The angle of rotation around the Z axis in radians.
    - * @param {number} theta2 The angle of rotation around the X axis in radians.
    - * @param {number} theta3 The angle of rotation around the Z axis in radians.
    - */
    -goog.vec.Matrix4.fromEulerZXZ = function(
    -    matrix, theta1, theta2, theta3) {
    -  var c1 = Math.cos(theta1);
    -  var s1 = Math.sin(theta1);
    -
    -  var c2 = Math.cos(theta2);
    -  var s2 = Math.sin(theta2);
    -
    -  var c3 = Math.cos(theta3);
    -  var s3 = Math.sin(theta3);
    -
    -  matrix[0] = c1 * c3 - c2 * s1 * s3;
    -  matrix[1] = c2 * c1 * s3 + c3 * s1;
    -  matrix[2] = s3 * s2;
    -  matrix[3] = 0;
    -
    -  matrix[4] = -c1 * s3 - c3 * c2 * s1;
    -  matrix[5] = c1 * c2 * c3 - s1 * s3;
    -  matrix[6] = c3 * s2;
    -  matrix[7] = 0;
    -
    -  matrix[8] = s2 * s1;
    -  matrix[9] = -c1 * s2;
    -  matrix[10] = c2;
    -  matrix[11] = 0;
    -
    -  matrix[12] = 0;
    -  matrix[13] = 0;
    -  matrix[14] = 0;
    -  matrix[15] = 1;
    -};
    -
    -
    -/**
    - * Decomposes a rotation matrix into Euler angles using the ZXZ convention.
    - * @param {goog.vec.ArrayType} matrix The rotation matrix.
    - * @param {goog.vec.ArrayType} euler The ZXZ Euler angles in
    - *     radians. euler = [roll, tilt, pan].
    - */
    -goog.vec.Matrix4.toEulerZXZ = function(matrix, euler) {
    -  var s2 = Math.sqrt(matrix[2] * matrix[2] + matrix[6] * matrix[6]);
    -
    -  // There is an ambiguity in the sign of s2. We assume the tilt value
    -  // is between [-pi/2, 0], so s2 is always negative.
    -  if (s2 > goog.vec.EPSILON) {
    -    euler[2] = Math.atan2(-matrix[2], -matrix[6]);
    -    euler[1] = Math.atan2(-s2, matrix[10]);
    -    euler[0] = Math.atan2(-matrix[8], matrix[9]);
    -  } else {
    -    // There is also an arbitrary choice for roll = 0 or pan = 0 in this case.
    -    // We assume roll = 0 as some applications do not allow the camera to roll.
    -    euler[0] = 0;
    -    euler[1] = Math.atan2(-s2, matrix[10]);
    -    euler[2] = Math.atan2(matrix[1], matrix[0]);
    -  }
    -};
    -
    -
    -/**
    - * Applies a translation by x,y,z to the given matrix.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix.
    - * @param {number} x The translation along the x axis.
    - * @param {number} y The translation along the y axis.
    - * @param {number} z The translation along the z axis.
    - */
    -goog.vec.Matrix4.applyTranslate = function(mat, x, y, z) {
    -  goog.vec.Matrix4.setColumnValues(
    -      mat, 3,
    -      mat[0] * x + mat[4] * y + mat[8] * z + mat[12],
    -      mat[1] * x + mat[5] * y + mat[9] * z + mat[13],
    -      mat[2] * x + mat[6] * y + mat[10] * z + mat[14],
    -      mat[3] * x + mat[7] * y + mat[11] * z + mat[15]);
    -};
    -
    -
    -/**
    - * Applies an x,y,z scale to the given matrix.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix.
    - * @param {number} x The x scale factor.
    - * @param {number} y The y scale factor.
    - * @param {number} z The z scale factor.
    - */
    -goog.vec.Matrix4.applyScale = function(mat, x, y, z) {
    -  goog.vec.Matrix4.setFromValues(
    -      mat,
    -      mat[0] * x, mat[1] * x, mat[2] * x, mat[3] * x,
    -      mat[4] * y, mat[5] * y, mat[6] * y, mat[7] * y,
    -      mat[8] * z, mat[9] * z, mat[10] * z, mat[11] * z,
    -      mat[12], mat[13], mat[14], mat[15]);
    -};
    -
    -
    -/**
    - * Applies a rotation by angle about the x,y,z axis to the given matrix.
    - *
    - * @param {goog.vec.ArrayType} mat The matrix.
    - * @param {number} angle The angle in radians.
    - * @param {number} x The x component of the rotation axis.
    - * @param {number} y The y component of the rotation axis.
    - * @param {number} z The z component of the rotation axis.
    - */
    -goog.vec.Matrix4.applyRotate = function(mat, angle, x, y, z) {
    -  var m00 = mat[0], m10 = mat[1], m20 = mat[2], m30 = mat[3];
    -  var m01 = mat[4], m11 = mat[5], m21 = mat[6], m31 = mat[7];
    -  var m02 = mat[8], m12 = mat[9], m22 = mat[10], m32 = mat[11];
    -  var m03 = mat[12], m13 = mat[13], m23 = mat[14], m33 = mat[15];
    -
    -  var cosAngle = Math.cos(angle);
    -  var sinAngle = Math.sin(angle);
    -  var diffCosAngle = 1 - cosAngle;
    -  var r00 = x * x * diffCosAngle + cosAngle;
    -  var r10 = x * y * diffCosAngle + z * sinAngle;
    -  var r20 = x * z * diffCosAngle - y * sinAngle;
    -
    -  var r01 = x * y * diffCosAngle - z * sinAngle;
    -  var r11 = y * y * diffCosAngle + cosAngle;
    -  var r21 = y * z * diffCosAngle + x * sinAngle;
    -
    -  var r02 = x * z * diffCosAngle + y * sinAngle;
    -  var r12 = y * z * diffCosAngle - x * sinAngle;
    -  var r22 = z * z * diffCosAngle + cosAngle;
    -
    -  goog.vec.Matrix4.setFromValues(
    -      mat,
    -      m00 * r00 + m01 * r10 + m02 * r20,
    -      m10 * r00 + m11 * r10 + m12 * r20,
    -      m20 * r00 + m21 * r10 + m22 * r20,
    -      m30 * r00 + m31 * r10 + m32 * r20,
    -
    -      m00 * r01 + m01 * r11 + m02 * r21,
    -      m10 * r01 + m11 * r11 + m12 * r21,
    -      m20 * r01 + m21 * r11 + m22 * r21,
    -      m30 * r01 + m31 * r11 + m32 * r21,
    -
    -      m00 * r02 + m01 * r12 + m02 * r22,
    -      m10 * r02 + m11 * r12 + m12 * r22,
    -      m20 * r02 + m21 * r12 + m22 * r22,
    -      m30 * r02 + m31 * r12 + m32 * r22,
    -
    -      m03, m13, m23, m33);
    -};
    -
    -
    -/**
    - * @type {!Array<!goog.vec.Vec3.Type>}
    - * @private
    - */
    -goog.vec.Matrix4.tmpVec3_ = [
    -  goog.vec.Vec3.createNumber(),
    -  goog.vec.Vec3.createNumber()
    -];
    -
    -
    -/**
    - * @type {!Array<!goog.vec.Vec4.Type>}
    - * @private
    - */
    -goog.vec.Matrix4.tmpVec4_ = [
    -  goog.vec.Vec4.createNumber(),
    -  goog.vec.Vec4.createNumber(),
    -  goog.vec.Vec4.createNumber()
    -];
    -
    -
    -/**
    - * @type {Array<goog.vec.Matrix4.Type>}
    - * @private
    - */
    -goog.vec.Matrix4.tmpMatrix4_ = [
    -  goog.vec.Matrix4.create()
    -];
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/matrix4_test.html b/src/database/third_party/closure-library/closure/goog/vec/matrix4_test.html
    deleted file mode 100644
    index 498a2f87398..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/matrix4_test.html
    +++ /dev/null
    @@ -1,626 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.vec.Matrix4</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.vec.Float32Array');
    -  goog.require('goog.vec.Matrix4');
    -  goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -  function testConstructor() {
    -    var m0 = goog.vec.Matrix4.create();
    -    assertElementsEquals([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], m0);
    -
    -    var m1 = goog.vec.Matrix4.createFromArray(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m1);
    -
    -    var m2 = goog.vec.Matrix4.clone(m1);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m1);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m2);
    -
    -    var m3 = goog.vec.Matrix4.createFromValues(
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m3);
    -
    -    var m4 = goog.vec.Matrix4.createIdentity();
    -    assertElementsEquals([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], m4);
    -  }
    -
    -  function testSet() {
    -    var m0 = goog.vec.Matrix4.create();
    -    var m1 = goog.vec.Matrix4.createFromArray(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
    -    goog.vec.Matrix4.setFromArray(m0, m1);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -
    -    goog.vec.Matrix4.setFromValues(
    -        m0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17);
    -    assertElementsEquals(
    -        [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17], m0);
    -  }
    -
    -  function testSetDiagonal() {
    -    var m0 = goog.vec.Matrix4.create();
    -    goog.vec.Matrix4.setDiagonalValues(m0, 1, 2, 3, 4);
    -    assertElementsEquals(
    -        [1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 4], m0);
    -
    -    goog.vec.Matrix4.setDiagonal(m0, [4, 5, 6, 7]);
    -    assertElementsEquals(
    -        [4, 0, 0, 0, 0, 5, 0, 0, 0, 0, 6, 0, 0, 0, 0, 7], m0);
    -  }
    -
    -  function testSetGetColumn() {
    -    var m0 = goog.vec.Matrix4.create();
    -    goog.vec.Matrix4.setColumn(m0, 0, [1, 2, 3, 4]);
    -    goog.vec.Matrix4.setColumn(m0, 1, [5, 6, 7, 8]);
    -    goog.vec.Matrix4.setColumn(m0, 2, [9, 10, 11, 12]);
    -    goog.vec.Matrix4.setColumn(m0, 3, [13, 14, 15, 16]);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -
    -    var v0 = [0, 0, 0, 0];
    -    goog.vec.Matrix4.getColumn(m0, 0, v0);
    -    assertElementsEquals([1, 2, 3, 4], v0);
    -    goog.vec.Matrix4.getColumn(m0, 1, v0);
    -    assertElementsEquals([5, 6, 7, 8], v0);
    -    goog.vec.Matrix4.getColumn(m0, 2, v0);
    -    assertElementsEquals([9, 10, 11, 12], v0);
    -    goog.vec.Matrix4.getColumn(m0, 3, v0);
    -    assertElementsEquals([13, 14, 15, 16], v0);
    -  }
    -
    -  function testSetGetColumns() {
    -    var m0 = goog.vec.Matrix4.create();
    -    goog.vec.Matrix4.setColumns(
    -        m0, [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -
    -    var v0 = [0, 0, 0, 0], v1 = [0, 0, 0, 0];
    -    var v2 = [0, 0, 0, 0], v3 = [0, 0, 0, 0];
    -    goog.vec.Matrix4.getColumns(m0, v0, v1, v2, v3);
    -    assertElementsEquals([1, 2, 3, 4], v0);
    -    assertElementsEquals([5, 6, 7, 8], v1);
    -    assertElementsEquals([9, 10, 11, 12], v2);
    -    assertElementsEquals([13, 14, 15, 16], v3);
    -  }
    -
    -  function testSetGetRow() {
    -    var m0 = goog.vec.Matrix4.create();
    -    goog.vec.Matrix4.setRow(m0, 0, [1, 2, 3, 4]);
    -    goog.vec.Matrix4.setRow(m0, 1, [5, 6, 7, 8]);
    -    goog.vec.Matrix4.setRow(m0, 2, [9, 10, 11, 12]);
    -    goog.vec.Matrix4.setRow(m0, 3, [13, 14, 15, 16]);
    -    assertElementsEquals(
    -        [1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16], m0);
    -
    -    var v0 = [0, 0, 0, 0];
    -    goog.vec.Matrix4.getRow(m0, 0, v0);
    -    assertElementsEquals([1, 2, 3, 4], v0);
    -    goog.vec.Matrix4.getRow(m0, 1, v0);
    -    assertElementsEquals([5, 6, 7, 8], v0);
    -    goog.vec.Matrix4.getRow(m0, 2, v0);
    -    assertElementsEquals([9, 10, 11, 12], v0);
    -    goog.vec.Matrix4.getRow(m0, 3, v0);
    -    assertElementsEquals([13, 14, 15, 16], v0);
    -  }
    -
    -  function testSetGetRows() {
    -    var m0 = goog.vec.Matrix4.create();
    -    goog.vec.Matrix4.setRows(
    -        m0, [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]);
    -    assertElementsEquals(
    -        [1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16], m0);
    -
    -    var v0 = [0, 0, 0, 0], v1 = [0, 0, 0, 0];
    -    var v2 = [0, 0, 0, 0], v3 = [0, 0, 0, 0];
    -    goog.vec.Matrix4.getRows(m0, v0, v1, v2, v3);
    -    assertElementsEquals([1, 2, 3, 4], v0);
    -    assertElementsEquals([5, 6, 7, 8], v1);
    -    assertElementsEquals([9, 10, 11, 12], v2);
    -    assertElementsEquals([13, 14, 15, 16], v3);
    -  }
    -
    -  function testSetRowMajorArray() {
    -    var m0 = goog.vec.Matrix4.create();
    -    goog.vec.Matrix4.setFromRowMajorArray(
    -        m0, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
    -    assertElementsEquals(
    -        [1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16], m0);
    -  }
    -
    -  function testSetZero() {
    -    var m0 = goog.vec.Matrix4.createFromArray(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -    goog.vec.Matrix4.setZero(m0);
    -    assertElementsEquals(
    -        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], m0);
    -  }
    -
    -  function testSetIdentity() {
    -    var m0 = goog.vec.Matrix4.create();
    -    goog.vec.Matrix4.setIdentity(m0);
    -    assertElementsEquals(
    -        [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], m0);
    -  }
    -
    -  function testSetGetElement() {
    -    var m0 = goog.vec.Matrix4.create();
    -    for (var r = 0; r < 4; r++) {
    -      for (var c = 0; c < 4; c++) {
    -        var value = c * 4 + r + 1;
    -        goog.vec.Matrix4.setElement(m0, r, c, value);
    -        assertEquals(value, goog.vec.Matrix4.getElement(m0, r, c));
    -      }
    -    }
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -  }
    -
    -  function testAdd() {
    -    var m0 = goog.vec.Matrix4.createFromValues(
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var m1 = goog.vec.Matrix4.createFromValues(
    -        9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8);
    -    var m2 = goog.vec.Matrix4.create();
    -    goog.vec.Matrix4.add(m0, m1, m2);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -    assertElementsEquals(
    -        [9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8], m1);
    -    assertElementsEquals(
    -        [10, 12, 14, 16, 18, 20, 22, 24, 10, 12, 14, 16, 18, 20, 22, 24], m2);
    -
    -    goog.vec.Matrix4.add(m0, m1, m0);
    -    assertElementsEquals(
    -        [9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8], m1);
    -    assertElementsEquals(
    -        [10, 12, 14, 16, 18, 20, 22, 24, 10, 12, 14, 16, 18, 20, 22, 24], m0);
    -  }
    -
    -  function testSubtract() {
    -    var m0 = goog.vec.Matrix4.createFromValues(
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var m1 = goog.vec.Matrix4.createFromValues(
    -        9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8);
    -    var m2 = goog.vec.Matrix4.create();
    -
    -    goog.vec.Matrix4.subtract(m0, m1, m2);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -    assertElementsEquals(
    -        [9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8], m1);
    -    assertElementsEquals(
    -        [-8, -8, -8, -8, -8, -8, -8, -8, 8, 8, 8, 8, 8, 8, 8, 8], m2);
    -
    -    goog.vec.Matrix4.subtract(m1, m0, m1);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -    assertElementsEquals(
    -        [8, 8, 8, 8, 8, 8, 8, 8, -8, -8, -8, -8, -8, -8, -8, -8], m1);
    -  }
    -
    -  function testScale() {
    -    var m0 = goog.vec.Matrix4.createFromValues(
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var m1 = goog.vec.Matrix4.create();
    -
    -    goog.vec.Matrix4.scale(m0, 2, m1);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
    -    assertElementsEquals(
    -        [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32], m1);
    -
    -    goog.vec.Matrix4.scale(m0, 5, m0);
    -    assertElementsEquals(
    -        [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80], m0);
    -  }
    -
    -  function testMultMat() {
    -    var m0 = goog.vec.Matrix4.createFromValues(
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var m1 = goog.vec.Matrix4.createFromValues(
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var m2 = goog.vec.Matrix4.create();
    -
    -    goog.vec.Matrix4.multMat(m0, m1, m2);
    -    assertElementsEquals(
    -        [90, 100, 110, 120, 202, 228, 254, 280,
    -         314, 356, 398, 440, 426, 484, 542, 600], m2);
    -
    -    goog.vec.Matrix4.scale(m1, 2, m1);
    -    goog.vec.Matrix4.multMat(m1, m0, m1);
    -    assertElementsEquals(
    -        [180, 200, 220, 240, 404, 456, 508, 560,
    -         628, 712, 796, 880, 852, 968, 1084, 1200], m1);
    -  }
    -
    -  function testTranspose() {
    -    var m0 = goog.vec.Matrix4.createFromValues(
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var m1 = goog.vec.Matrix4.create();
    -    goog.vec.Matrix4.transpose(m0, m1);
    -    assertElementsEquals(
    -        [1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16], m1);
    -
    -    goog.vec.Matrix4.transpose(m1, m1);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m1);
    -  }
    -
    -  function testDeterminant() {
    -    var m0 = goog.vec.Matrix4.createFromValues(
    -        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
    -    assertEquals(0, goog.vec.Matrix4.determinant(m0));
    -    assertElementsEquals(
    -        [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], m0);
    -
    -    goog.vec.Matrix4.setFromValues(
    -        m0, 1, 2, 3, 4, 2, 3, 4, 1, 3, 4, 1, 2, 4, 1, 2, 3);
    -    assertEquals(160, goog.vec.Matrix4.determinant(m0));
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 2, 3, 4, 1, 3, 4, 1, 2, 4, 1, 2, 3], m0);
    -  }
    -
    -  function testInvert() {
    -    var m0 = goog.vec.Matrix4.createFromValues(
    -        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
    -    assertFalse(goog.vec.Matrix4.invert(m0, m0));
    -    assertElementsEquals(
    -        [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], m0);
    -
    -    goog.vec.Matrix4.setFromValues(
    -        m0, 1, 2, 3, 4, 2, 3, 4, 1, 3, 4, 1, 2, 4, 1, 2, 3);
    -    assertTrue(goog.vec.Matrix4.invert(m0, m0));
    -    assertElementsRoughlyEqual(
    -        [-0.225, 0.025, 0.025, 0.275, 0.025, 0.025, 0.275, -0.225,
    -         0.025, 0.275, -0.225, 0.025, 0.275, -0.225, 0.025, 0.025], m0,
    -         goog.vec.EPSILON);
    -
    -    goog.vec.Matrix4.makeScale(m0, .01, .01, .01);
    -    assertTrue(goog.vec.Matrix4.invert(m0, m0));
    -    var m1 = goog.vec.Matrix4.create();
    -    goog.vec.Matrix4.makeScale(m1, 100, 100, 100);
    -    assertElementsEquals(m1, m0);
    -  }
    -
    -  function testEquals() {
    -    var m0 = goog.vec.Matrix4.createFromValues(
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var m1 = goog.vec.Matrix4.clone(m0);
    -    assertTrue(goog.vec.Matrix4.equals(m0, m1));
    -    assertTrue(goog.vec.Matrix4.equals(m1, m0));
    -    for (var i = 0; i < 16; i++) {
    -      m1[i] = 18;
    -      assertFalse(goog.vec.Matrix4.equals(m0, m1));
    -      assertFalse(goog.vec.Matrix4.equals(m1, m0));
    -      m1[i] = i + 1;
    -    }
    -  }
    -
    -  function testMultVec3() {
    -    var m0 = goog.vec.Matrix4.createFromValues(
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var v0 = [1, 2, 3];
    -    var v1 = [0, 0, 0];
    -
    -    goog.vec.Matrix4.multVec3(m0, v0, v1);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals([51, 58, 65], v1);
    -
    -    goog.vec.Matrix4.multVec3(m0, v0, v0);
    -    assertElementsEquals([51, 58, 65], v0);
    -
    -    v0 = [1, 2, 3];
    -    goog.vec.Matrix4.multVec3ToArray(m0, v0, v0);
    -    assertElementsEquals([51, 58, 65], v0);
    -  }
    -
    -  function testMultVec3NoTranslate() {
    -    var m0 = goog.vec.Matrix4.createFromValues(
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var v0 = [1, 2, 3];
    -    var v1 = [0, 0, 0];
    -
    -    goog.vec.Matrix4.multVec3NoTranslate(m0, v0, v1);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals([38, 44, 50], v1);
    -
    -    goog.vec.Matrix4.multVec3NoTranslate(m0, v0, v0);
    -    assertElementsEquals([38, 44, 50], v0);
    -  }
    -
    -  function testMultVec3Projective() {
    -    var m0 = goog.vec.Matrix4.createFromValues(
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var v0 = [1, 2, 3];
    -    var v1 = [0, 0, 0];
    -    var invw = 1 / 72;
    -
    -    goog.vec.Matrix4.multVec3Projective(m0, v0, v1);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals(
    -        [51 * invw, 58 * invw, 65 * invw], v1);
    -
    -    goog.vec.Matrix4.multVec3Projective(m0, v0, v0);
    -    assertElementsEquals(
    -        [51 * invw, 58 * invw, 65 * invw], v0);
    -  }
    -
    -  function testMultVec4() {
    -    var m0 = goog.vec.Matrix4.createFromValues(
    -        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    -    var v0 = [1, 2, 3, 4];
    -    var v1 = [0, 0, 0, 0];
    -
    -    goog.vec.Matrix4.multVec4(m0, v0, v1);
    -    assertElementsEquals([90, 100, 110, 120], v1);
    -    goog.vec.Matrix4.multVec4(m0, v0, v0);
    -    assertElementsEquals([90, 100, 110, 120], v0);
    -
    -    var v0 = [1, 2, 3, 4];
    -    goog.vec.Matrix4.multVec4ToArray(m0, v0, v0);
    -    assertElementsEquals([90, 100, 110, 120], v0);
    -  }
    -
    -  function testSetValues() {
    -    var a0 = goog.vec.Matrix4.create();
    -    assertElementsEquals(
    -        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], a0);
    -    a0 = goog.vec.Matrix4.createFromArray(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], a0);
    -
    -    var a1 = goog.vec.Matrix4.create();
    -    goog.vec.Matrix4.setDiagonalValues(a1, 1, 2, 3, 4);
    -    assertElementsEquals(
    -        [1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 4], a1);
    -
    -    goog.vec.Matrix4.setColumnValues(a1, 0, 2, 3, 4, 5);
    -    goog.vec.Matrix4.setColumnValues(a1, 1, 6, 7, 8, 9);
    -    goog.vec.Matrix4.setColumnValues(a1, 2, 10, 11, 12, 13);
    -    goog.vec.Matrix4.setColumnValues(a1, 3, 14, 15, 16, 1);
    -    assertElementsEquals(
    -        [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1], a1);
    -
    -    goog.vec.Matrix4.setRowValues(a1, 0, 1, 5, 9, 13);
    -    goog.vec.Matrix4.setRowValues(a1, 1, 2, 6, 10, 14);
    -    goog.vec.Matrix4.setRowValues(a1, 2, 3, 7, 11, 15);
    -    goog.vec.Matrix4.setRowValues(a1, 3, 4, 8, 12, 16);
    -    assertElementsEquals(
    -        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], a1);
    -  }
    -
    -  function testMakeTranslate() {
    -    var m0 = goog.vec.Matrix4.create();
    -    goog.vec.Matrix4.makeTranslate(m0, 3, 4, 5);
    -    assertElementsEquals(
    -        [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 3, 4, 5, 1], m0);
    -  }
    -
    -  function testMakeScale() {
    -    var m0 = goog.vec.Matrix4.create();
    -    goog.vec.Matrix4.makeScale(m0, 3, 4, 5);
    -    assertElementsEquals(
    -        [3, 0, 0, 0, 0, 4, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1], m0);
    -  }
    -
    -  function testMakeRotate() {
    -    var m0 = goog.vec.Matrix4.create();
    -    goog.vec.Matrix4.makeAxisAngleRotate(m0, Math.PI / 2, 0, 0, 1);
    -    assertElementsRoughlyEqual(
    -        [0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
    -        m0, goog.vec.EPSILON);
    -
    -    var m1 = goog.vec.Matrix4.create();
    -    goog.vec.Matrix4.makeAxisAngleRotate(m1, -Math.PI / 4, 0, 0, 1);
    -    goog.vec.Matrix4.multMat(m0, m1, m1);
    -    assertElementsRoughlyEqual(
    -        [0.7071068, 0.7071068, 0, 0,
    -         -0.7071068, 0.7071068, 0, 0,
    -         0, 0, 1, 0,
    -         0, 0, 0, 1],
    -        m1, goog.vec.EPSILON);
    -  }
    -
    -  function testApplyTranslate() {
    -    var m0 = goog.vec.Matrix4.createIdentity();
    -    goog.vec.Matrix4.applyTranslate(m0, 3, 4, 5);
    -    assertElementsEquals(
    -        [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 3, 4, 5, 1], m0);
    -
    -    goog.vec.Matrix4.setFromValues(
    -        m0, 1, 2, 3, 4, 2, 3, 4, 1, 3, 4, 1, 2, 4, 1, 2, 3);
    -
    -    var m1 = goog.vec.Matrix4.create();
    -    goog.vec.Matrix4.makeTranslate(m1, 5, 6, 7);
    -    var m2 = goog.vec.Matrix4.create();
    -    goog.vec.Matrix4.multMat(m0, m1, m2);
    -    goog.vec.Matrix4.applyTranslate(m0, 5, 6, 7);
    -    assertElementsEquals(m2, m0);
    -  }
    -
    -  function testApplyScale() {
    -    var m0 = goog.vec.Matrix4.createIdentity();
    -    goog.vec.Matrix4.applyScale(m0, 3, 4, 5);
    -    assertElementsEquals([3, 0, 0, 0, 0, 4, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1], m0);
    -  }
    -
    -  function testApplyRotate() {
    -    var m0 = goog.vec.Matrix4.createIdentity();
    -    goog.vec.Matrix4.applyRotate(m0, Math.PI / 2, 0, 0, 1);
    -    assertElementsRoughlyEqual(
    -        [0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
    -        m0, goog.vec.EPSILON);
    -
    -    goog.vec.Matrix4.applyRotate(m0, -Math.PI / 4, 0, 0, 1);
    -    assertElementsRoughlyEqual(
    -        [0.7071068, 0.7071068, 0, 0,
    -         -0.7071068, 0.7071068, 0, 0,
    -         0, 0, 1, 0,
    -         0, 0, 0, 1],
    -        m0, goog.vec.EPSILON);
    -  }
    -
    -  function testMakeFrustum() {
    -    var m0 = goog.vec.Matrix4.create();
    -    goog.vec.Matrix4.makeFrustum(m0, -1, 2, -2, 1, .1, 1.1);
    -    assertElementsRoughlyEqual(
    -        [0.06666666, 0, 0, 0,
    -         0, 0.06666666, 0, 0,
    -         0.33333333, -0.33333333, -1.2, -1,
    -         0, 0, -0.22, 0], m0, goog.vec.EPSILON);
    -  }
    -
    -  function testMakePerspective() {
    -    var m0 = goog.vec.Matrix4.create();
    -    goog.vec.Matrix4.makePerspective(m0, 90 * Math.PI / 180, 2, 0.1, 1.1);
    -    assertElementsRoughlyEqual(
    -        [0.5, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1.2, -1, 0, 0, -0.22, 0],
    -        m0, goog.vec.EPSILON);
    -  }
    -
    -  function testMakeOrtho() {
    -    var m0 = goog.vec.Matrix4.create();
    -    goog.vec.Matrix4.makeOrtho(m0, -1, 2, -2, 1, 0.1, 1.1);
    -    assertElementsRoughlyEqual(
    -        [0.6666666, 0, 0, 0,
    -         0, 0.6666666, 0, 0,
    -         0, 0, -2, 0,
    -         -0.333333, 0.3333333, -1.2, 1], m0, goog.vec.EPSILON);
    -
    -  }
    -
    -  function testEulerZXZ() {
    -    var m0 = goog.vec.Matrix4.create();
    -    var roll = Math.random() * 2 * Math.PI;
    -    var tilt = -Math.random() * Math.PI / 2;
    -    var pan = Math.random() * 2 * Math.PI;
    -
    -    goog.vec.Matrix4.makeAxisAngleRotate(m0, roll, 0, 0, 1);
    -    goog.vec.Matrix4.applyRotate(m0, tilt, 1, 0, 0);
    -    goog.vec.Matrix4.applyRotate(m0, pan, 0, 0, 1);
    -
    -    var m1 = goog.vec.Matrix4.create();
    -    goog.vec.Matrix4.fromEulerZXZ(m1, roll, tilt, pan);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -
    -
    -    var euler = [0, 0, 0];
    -    goog.vec.Matrix4.toEulerZXZ(m0, euler);
    -    // Bring them to their range.
    -    euler[0] = (euler[0] + Math.PI * 2) % (Math.PI * 2);
    -    euler[1] = (euler[1] - Math.PI * 2) % (Math.PI * 2);
    -    euler[2] = (euler[2] + Math.PI * 2) % (Math.PI * 2);
    -    assertElementsRoughlyEqual([roll, tilt, pan], euler, goog.vec.EPSILON);
    -  }
    -
    -  function testEulerZXZExtrema() {
    -    var m0 = goog.vec.Matrix4.createFromArray(
    -    [1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1]);
    -    var m1 = goog.vec.Matrix4.createFromArray(
    -    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
    -
    -    var euler = [0, 0, 0];
    -    goog.vec.Matrix4.toEulerZXZ(m0, euler);
    -    assertElementsRoughlyEqual([0, -Math.PI / 2, 0], euler, goog.vec.EPSILON);
    -    goog.vec.Matrix4.fromEulerZXZ(m1, euler[0], euler[1], euler[2]);
    -    assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
    -  }
    -
    -  function testLookAt() {
    -    var viewMatrix = goog.vec.Matrix4.create();
    -    goog.vec.Matrix4.lookAt(
    -      viewMatrix, [0, 0, 0], [1, 0, 0], [0, 1, 0]);
    -    assertElementsRoughlyEqual(
    -      [0, 0, -1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1], viewMatrix,
    -      goog.vec.EPSILON);
    -  }
    -
    -  function testToLookAt() {
    -    // This test does not use the default precision goog.vec.EPSILON due to
    -    // precision issues in some browsers leading to flaky tests.
    -    var EPSILON = 1e-4;
    -
    -    var eyeExp = [0, 0, 0];
    -    var fwdExp = [1, 0, 0];
    -    var upExp = [0, 1, 0];
    -
    -    var centerExp = [0, 0, 0];
    -    goog.vec.Vec3.add(eyeExp, fwdExp, centerExp);
    -
    -    var view = goog.vec.Matrix4.create();
    -    goog.vec.Matrix4.lookAt(view, eyeExp, centerExp, upExp);
    -
    -    var eyeRes = [0, 0, 0];
    -    var fwdRes = [0, 0, 0];
    -    var upRes = [0, 0, 0];
    -    goog.vec.Matrix4.toLookAt(view, eyeRes, fwdRes, upRes);
    -    assertElementsRoughlyEqual(eyeExp, eyeRes, EPSILON);
    -    assertElementsRoughlyEqual(fwdExp, fwdRes, EPSILON);
    -    assertElementsRoughlyEqual(upExp, upRes, EPSILON);
    -  }
    -
    -  function testLookAtDecomposition() {
    -    // This test does not use the default precision goog.vec.EPSILON due to
    -    // precision issues in some browsers, which leads to flaky tests.
    -    var EPSILON = 1e-4;
    -
    -    var viewExp = goog.vec.Matrix4.create();
    -    var viewRes = goog.vec.Matrix4.create();
    -    var tmp = goog.vec.Matrix4.create();
    -
    -    // Get a valid set of random vectors eye, forward, up by decomposing
    -    // a random matrix into a set of lookAt vectors.
    -    for (var i = 0; i < tmp.length; i++)
    -      tmp[i] = Math.random();
    -    var eyeExp = [0, 0, 0];
    -    var fwdExp = [0, 0, 0];
    -    var upExp = [0, 0, 0];
    -    var centerExp = [0, 0, 0];
    -    // Project the random matrix into a real modelview matrix.
    -    goog.vec.Matrix4.toLookAt(tmp, eyeExp, fwdExp, upExp);
    -    goog.vec.Vec3.add(eyeExp, fwdExp, centerExp);
    -
    -    // Compute the expected modelview matrix from a set of valid random vectors.
    -    goog.vec.Matrix4.lookAt(viewExp, eyeExp, centerExp, upExp);
    -
    -    var eyeRes = [0, 0, 0];
    -    var fwdRes = [0, 0, 0];
    -    var upRes = [0, 0, 0];
    -    var centerRes = [0, 0, 0];
    -    goog.vec.Matrix4.toLookAt(viewExp, eyeRes, fwdRes, upRes);
    -    goog.vec.Vec3.add(eyeRes, fwdRes, centerRes);
    -
    -    goog.vec.Matrix4.lookAt(viewRes, eyeRes, centerRes, upRes);
    -
    -    assertElementsRoughlyEqual(eyeExp, eyeRes, EPSILON);
    -    assertElementsRoughlyEqual(fwdExp, fwdRes, EPSILON);
    -    assertElementsRoughlyEqual(upExp, upRes, EPSILON);
    -    assertElementsRoughlyEqual(viewExp, viewRes, EPSILON);
    -  }
    -
    -</script>
    -</body>
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/quaternion.js b/src/database/third_party/closure-library/closure/goog/vec/quaternion.js
    deleted file mode 100644
    index 35d40b937e3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/quaternion.js
    +++ /dev/null
    @@ -1,458 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Implements quaternions and their conversion functions. In this
    - * implementation, quaternions are represented as 4 element vectors with the
    - * first 3 elements holding the imaginary components and the 4th element holding
    - * the real component.
    - *
    - */
    -goog.provide('goog.vec.Quaternion');
    -
    -goog.require('goog.vec');
    -goog.require('goog.vec.Vec3');
    -goog.require('goog.vec.Vec4');
    -
    -
    -/** @typedef {goog.vec.Float32} */ goog.vec.Quaternion.Float32;
    -/** @typedef {goog.vec.Float64} */ goog.vec.Quaternion.Float64;
    -/** @typedef {goog.vec.Number} */ goog.vec.Quaternion.Number;
    -/** @typedef {goog.vec.AnyType} */ goog.vec.Quaternion.AnyType;
    -
    -
    -/**
    - * Creates a Float32 quaternion, initialized to zero.
    - *
    - * @return {!goog.vec.Quaternion.Float32} The new quaternion.
    - */
    -goog.vec.Quaternion.createFloat32 = goog.vec.Vec4.createFloat32;
    -
    -
    -/**
    - * Creates a Float64 quaternion, initialized to zero.
    - *
    - * @return {goog.vec.Quaternion.Float64} The new quaternion.
    - */
    -goog.vec.Quaternion.createFloat64 = goog.vec.Vec4.createFloat64;
    -
    -
    -/**
    - * Creates a Number quaternion, initialized to zero.
    - *
    - * @return {goog.vec.Quaternion.Number} The new quaternion.
    - */
    -goog.vec.Quaternion.createNumber = goog.vec.Vec4.createNumber;
    -
    -
    -/**
    - * Creates a new Float32 quaternion initialized with the values from the
    - * supplied array.
    - *
    - * @param {goog.vec.AnyType} vec The source 4 element array.
    - * @return {!goog.vec.Quaternion.Float32} The new quaternion.
    - */
    -goog.vec.Quaternion.createFloat32FromArray =
    -    goog.vec.Vec4.createFloat32FromArray;
    -
    -
    -/**
    - * Creates a new Float64 quaternion initialized with the values from the
    - * supplied array.
    - *
    - * @param {goog.vec.AnyType} vec The source 4 element array.
    - * @return {!goog.vec.Quaternion.Float64} The new quaternion.
    - */
    -goog.vec.Quaternion.createFloat64FromArray =
    -    goog.vec.Vec4.createFloat64FromArray;
    -
    -
    -/**
    - * Creates a new Float32 quaternion initialized with the supplied values.
    - *
    - * @param {number} v0 The value for element at index 0.
    - * @param {number} v1 The value for element at index 1.
    - * @param {number} v2 The value for element at index 2.
    - * @param {number} v3 The value for element at index 3.
    - * @return {!goog.vec.Quaternion.Float32} The new quaternion.
    - */
    -goog.vec.Quaternion.createFloat32FromValues =
    -    goog.vec.Vec4.createFloat32FromValues;
    -
    -
    -/**
    - * Creates a new Float64 quaternion initialized with the supplied values.
    - *
    - * @param {number} v0 The value for element at index 0.
    - * @param {number} v1 The value for element at index 1.
    - * @param {number} v2 The value for element at index 2.
    - * @param {number} v3 The value for element at index 3.
    - * @return {!goog.vec.Quaternion.Float64} The new quaternion.
    - */
    -goog.vec.Quaternion.createFloat64FromValues =
    -    goog.vec.Vec4.createFloat64FromValues;
    -
    -
    -/**
    - * Creates a clone of the given Float32 quaternion.
    - *
    - * @param {goog.vec.Quaternion.Float32} q The source quaternion.
    - * @return {goog.vec.Quaternion.Float32} The new quaternion.
    - */
    -goog.vec.Quaternion.cloneFloat32 = goog.vec.Vec4.cloneFloat32;
    -
    -
    -/**
    - * Creates a clone of the given Float64 quaternion.
    - *
    - * @param {goog.vec.Quaternion.Float64} q The source quaternion.
    - * @return {goog.vec.Quaternion.Float64} The new quaternion.
    - */
    -goog.vec.Quaternion.cloneFloat64 = goog.vec.Vec4.cloneFloat64;
    -
    -
    -/**
    - * Initializes the quaternion with the given values.
    - *
    - * @param {goog.vec.Quaternion.AnyType} q The quaternion to receive
    - *     the values.
    - * @param {number} v0 The value for element at index 0.
    - * @param {number} v1 The value for element at index 1.
    - * @param {number} v2 The value for element at index 2.
    - * @param {number} v3 The value for element at index 3.
    - * @return {!goog.vec.Vec4.AnyType} return q so that operations can be
    - *     chained together.
    - */
    -goog.vec.Quaternion.setFromValues = goog.vec.Vec4.setFromValues;
    -
    -
    -/**
    - * Initializes the quaternion with the given array of values.
    - *
    - * @param {goog.vec.Quaternion.AnyType} q The quaternion to receive
    - *     the values.
    - * @param {goog.vec.AnyType} values The array of values.
    - * @return {!goog.vec.Quaternion.AnyType} return q so that operations can be
    - *     chained together.
    - */
    -goog.vec.Quaternion.setFromArray = goog.vec.Vec4.setFromArray;
    -
    -
    -/**
    - * Adds the two quaternions.
    - *
    - * @param {goog.vec.Quaternion.AnyType} quat0 The first addend.
    - * @param {goog.vec.Quaternion.AnyType} quat1 The second addend.
    - * @param {goog.vec.Quaternion.AnyType} resultQuat The quaternion to
    - *     receive the result. May be quat0 or quat1.
    - */
    -goog.vec.Quaternion.add = goog.vec.Vec4.add;
    -
    -
    -/**
    - * Negates a quaternion, storing the result into resultQuat.
    - *
    - * @param {goog.vec.Quaternion.AnyType} quat0 The quaternion to negate.
    - * @param {goog.vec.Quaternion.AnyType} resultQuat The quaternion to
    - *     receive the result. May be quat0.
    - */
    -goog.vec.Quaternion.negate = goog.vec.Vec4.negate;
    -
    -
    -/**
    - * Multiplies each component of quat0 with scalar storing the product into
    - * resultVec.
    - *
    - * @param {goog.vec.Quaternion.AnyType} quat0 The source quaternion.
    - * @param {number} scalar The value to multiply with each component of quat0.
    - * @param {goog.vec.Quaternion.AnyType} resultQuat The quaternion to
    - *     receive the result. May be quat0.
    - */
    -goog.vec.Quaternion.scale = goog.vec.Vec4.scale;
    -
    -
    -/**
    - * Returns the square magnitude of the given quaternion.
    - *
    - * @param {goog.vec.Quaternion.AnyType} quat0 The quaternion.
    - * @return {number} The magnitude of the quaternion.
    - */
    -goog.vec.Quaternion.magnitudeSquared =
    -    goog.vec.Vec4.magnitudeSquared;
    -
    -
    -/**
    - * Returns the magnitude of the given quaternion.
    - *
    - * @param {goog.vec.Quaternion.AnyType} quat0 The quaternion.
    - * @return {number} The magnitude of the quaternion.
    - */
    -goog.vec.Quaternion.magnitude =
    -    goog.vec.Vec4.magnitude;
    -
    -
    -/**
    - * Normalizes the given quaternion storing the result into resultVec.
    - *
    - * @param {goog.vec.Quaternion.AnyType} quat0 The quaternion to
    - *     normalize.
    - * @param {goog.vec.Quaternion.AnyType} resultQuat The quaternion to
    - *     receive the result. May be quat0.
    - */
    -goog.vec.Quaternion.normalize = goog.vec.Vec4.normalize;
    -
    -
    -/**
    - * Computes the dot (scalar) product of two quaternions.
    - *
    - * @param {goog.vec.Quaternion.AnyType} q0 The first quaternion.
    - * @param {goog.vec.Quaternion.AnyType} q1 The second quaternion.
    - * @return {number} The scalar product.
    - */
    -goog.vec.Quaternion.dot = goog.vec.Vec4.dot;
    -
    -
    -/**
    - * Computes the conjugate of the quaternion in quat storing the result into
    - * resultQuat.
    - *
    - * @param {goog.vec.Quaternion.AnyType} quat The source quaternion.
    - * @param {goog.vec.Quaternion.AnyType} resultQuat The quaternion to
    - *     receive the result.
    - * @return {!goog.vec.Quaternion.AnyType} Return q so that
    - *     operations can be chained together.
    - */
    -goog.vec.Quaternion.conjugate = function(quat, resultQuat) {
    -  resultQuat[0] = -quat[0];
    -  resultQuat[1] = -quat[1];
    -  resultQuat[2] = -quat[2];
    -  resultQuat[3] = quat[3];
    -  return resultQuat;
    -};
    -
    -
    -/**
    - * Concatenates the two quaternions storing the result into resultQuat.
    - *
    - * @param {goog.vec.Quaternion.AnyType} quat0 The first quaternion.
    - * @param {goog.vec.Quaternion.AnyType} quat1 The second quaternion.
    - * @param {goog.vec.Quaternion.AnyType} resultQuat The quaternion to
    - *     receive the result.
    - * @return {!goog.vec.Quaternion.AnyType} Return q so that
    - *     operations can be chained together.
    - */
    -goog.vec.Quaternion.concat = function(quat0, quat1, resultQuat) {
    -  var x0 = quat0[0], y0 = quat0[1], z0 = quat0[2], w0 = quat0[3];
    -  var x1 = quat1[0], y1 = quat1[1], z1 = quat1[2], w1 = quat1[3];
    -  resultQuat[0] = w0 * x1 + x0 * w1 + y0 * z1 - z0 * y1;
    -  resultQuat[1] = w0 * y1 - x0 * z1 + y0 * w1 + z0 * x1;
    -  resultQuat[2] = w0 * z1 + x0 * y1 - y0 * x1 + z0 * w1;
    -  resultQuat[3] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1;
    -  return resultQuat;
    -};
    -
    -
    -/**
    - * Generates a unit quaternion from the given angle-axis rotation pair.
    - * The rotation axis is not required to be a unit vector, but should
    - * have non-zero length.  The angle should be specified in radians.
    - *
    - * @param {number} angle The angle (in radians) to rotate about the axis.
    - * @param {goog.vec.Quaternion.AnyType} axis Unit vector specifying the
    - *     axis of rotation.
    - * @param {goog.vec.Quaternion.AnyType} quat Unit quaternion to store the
    - *     result.
    - * @return {goog.vec.Quaternion.AnyType} Return q so that
    - *     operations can be chained together.
    - */
    -goog.vec.Quaternion.fromAngleAxis = function(angle, axis, quat) {
    -  // Normalize the axis of rotation.
    -  goog.vec.Vec3.normalize(axis, axis);
    -
    -  var halfAngle = 0.5 * angle;
    -  var sin = Math.sin(halfAngle);
    -  goog.vec.Quaternion.setFromValues(
    -      quat, sin * axis[0], sin * axis[1], sin * axis[2], Math.cos(halfAngle));
    -
    -  // Normalize the resulting quaternion.
    -  goog.vec.Quaternion.normalize(quat, quat);
    -  return quat;
    -};
    -
    -
    -/**
    - * Generates an angle-axis rotation pair from a unit quaternion.
    - * The quaternion is assumed to be of unit length.  The calculated
    - * values are returned via the passed 'axis' object and the 'angle'
    - * number returned by the function itself. The returned rotation axis
    - * is a non-zero length unit vector, and the returned angle is in
    - * radians in the range of [-PI, +PI].
    - *
    - * @param {goog.vec.Quaternion.AnyType} quat Unit quaternion to convert.
    - * @param {goog.vec.Quaternion.AnyType} axis Vector to store the returned
    - *     rotation axis.
    - * @return {number} angle Angle (in radians) to rotate about 'axis'.
    - *     The range of the returned angle is [-PI, +PI].
    - */
    -goog.vec.Quaternion.toAngleAxis = function(quat, axis) {
    -  var angle = 2 * Math.acos(quat[3]);
    -  var magnitude = Math.min(Math.max(1 - quat[3] * quat[3], 0), 1);
    -  if (magnitude < goog.vec.EPSILON) {
    -    // This is nearly an identity rotation, so just use a fixed +X axis.
    -    goog.vec.Vec3.setFromValues(axis, 1, 0, 0);
    -  } else {
    -    // Compute the proper rotation axis.
    -    goog.vec.Vec3.setFromValues(axis, quat[0], quat[1], quat[2]);
    -    // Make sure the rotation axis is of unit length.
    -    goog.vec.Vec3.normalize(axis, axis);
    -  }
    -  // Adjust the range of the returned angle to [-PI, +PI].
    -  if (angle > Math.PI) {
    -    angle -= 2 * Math.PI;
    -  }
    -  return angle;
    -};
    -
    -
    -/**
    - * Generates the quaternion from the given rotation matrix.
    - *
    - * @param {goog.vec.Quaternion.AnyType} matrix The source matrix.
    - * @param {goog.vec.Quaternion.AnyType} quat The resulting quaternion.
    - * @return {!goog.vec.Quaternion.AnyType} Return q so that
    - *     operations can be chained together.
    - */
    -goog.vec.Quaternion.fromRotationMatrix4 = function(matrix, quat) {
    -  var sx = matrix[0], sy = matrix[5], sz = matrix[10];
    -  quat[3] = Math.sqrt(Math.max(0, 1 + sx + sy + sz)) / 2;
    -  quat[0] = Math.sqrt(Math.max(0, 1 + sx - sy - sz)) / 2;
    -  quat[1] = Math.sqrt(Math.max(0, 1 - sx + sy - sz)) / 2;
    -  quat[2] = Math.sqrt(Math.max(0, 1 - sx - sy + sz)) / 2;
    -
    -  quat[0] = (matrix[6] - matrix[9] < 0) != (quat[0] < 0) ? -quat[0] : quat[0];
    -  quat[1] = (matrix[8] - matrix[2] < 0) != (quat[1] < 0) ? -quat[1] : quat[1];
    -  quat[2] = (matrix[1] - matrix[4] < 0) != (quat[2] < 0) ? -quat[2] : quat[2];
    -  return quat;
    -};
    -
    -
    -/**
    - * Generates the rotation matrix from the given quaternion.
    - *
    - * @param {goog.vec.Quaternion.AnyType} quat The source quaternion.
    - * @param {goog.vec.AnyType} matrix The resulting matrix.
    - * @return {!goog.vec.AnyType} Return resulting matrix so that
    - *     operations can be chained together.
    - */
    -goog.vec.Quaternion.toRotationMatrix4 = function(quat, matrix) {
    -  var x = quat[0], y = quat[1], z = quat[2], w = quat[3];
    -  var x2 = 2 * x, y2 = 2 * y, z2 = 2 * z;
    -  var wx = x2 * w;
    -  var wy = y2 * w;
    -  var wz = z2 * w;
    -  var xx = x2 * x;
    -  var xy = y2 * x;
    -  var xz = z2 * x;
    -  var yy = y2 * y;
    -  var yz = z2 * y;
    -  var zz = z2 * z;
    -
    -  matrix[0] = 1 - (yy + zz);
    -  matrix[1] = xy + wz;
    -  matrix[2] = xz - wy;
    -  matrix[3] = 0;
    -  matrix[4] = xy - wz;
    -  matrix[5] = 1 - (xx + zz);
    -  matrix[6] = yz + wx;
    -  matrix[7] = 0;
    -  matrix[8] = xz + wy;
    -  matrix[9] = yz - wx;
    -  matrix[10] = 1 - (xx + yy);
    -  matrix[11] = 0;
    -  matrix[12] = 0;
    -  matrix[13] = 0;
    -  matrix[14] = 0;
    -  matrix[15] = 1;
    -  return matrix;
    -};
    -
    -
    -/**
    - * Computes the spherical linear interpolated value from the given quaternions
    - * q0 and q1 according to the coefficient t. The resulting quaternion is stored
    - * in resultQuat.
    - *
    - * @param {goog.vec.Quaternion.AnyType} q0 The first quaternion.
    - * @param {goog.vec.Quaternion.AnyType} q1 The second quaternion.
    - * @param {number} t The interpolating coefficient.
    - * @param {goog.vec.Quaternion.AnyType} resultQuat The quaternion to
    - *     receive the result.
    - * @return {goog.vec.Quaternion.AnyType} Return q so that
    - *     operations can be chained together.
    - */
    -goog.vec.Quaternion.slerp = function(q0, q1, t, resultQuat) {
    -  // Compute the dot product between q0 and q1 (cos of the angle between q0 and
    -  // q1). If it's outside the interval [-1,1], then the arccos is not defined.
    -  // The usual reason for this is that q0 and q1 are colinear. In this case
    -  // the angle between the two is zero, so just return q1.
    -  var cosVal = goog.vec.Quaternion.dot(q0, q1);
    -  if (cosVal > 1 || cosVal < -1) {
    -    goog.vec.Vec4.setFromArray(resultQuat, q1);
    -    return resultQuat;
    -  }
    -
    -  // Quaternions are a double cover on the space of rotations. That is, q and -q
    -  // represent the same rotation. Thus we have two possibilities when
    -  // interpolating between q0 and q1: going the short way or the long way. We
    -  // prefer the short way since that is the likely expectation from users.
    -  var factor = 1;
    -  if (cosVal < 0) {
    -    factor = -1;
    -    cosVal = -cosVal;
    -  }
    -
    -  // Compute the angle between q0 and q1. If it's very small, then just return
    -  // q1 to avoid a very large denominator below.
    -  var angle = Math.acos(cosVal);
    -  if (angle <= goog.vec.EPSILON) {
    -    goog.vec.Vec4.setFromArray(resultQuat, q1);
    -    return resultQuat;
    -  }
    -
    -  // Compute the coefficients and interpolate.
    -  var invSinVal = 1 / Math.sin(angle);
    -  var c0 = Math.sin((1 - t) * angle) * invSinVal;
    -  var c1 = factor * Math.sin(t * angle) * invSinVal;
    -
    -  resultQuat[0] = q0[0] * c0 + q1[0] * c1;
    -  resultQuat[1] = q0[1] * c0 + q1[1] * c1;
    -  resultQuat[2] = q0[2] * c0 + q1[2] * c1;
    -  resultQuat[3] = q0[3] * c0 + q1[3] * c1;
    -  return resultQuat;
    -};
    -
    -
    -/**
    - * Compute the simple linear interpolation of the two quaternions q0 and q1
    - * according to the coefficient t. The resulting quaternion is stored in
    - * resultVec.
    - *
    - * @param {goog.vec.Quaternion.AnyType} q0 The first quaternion.
    - * @param {goog.vec.Quaternion.AnyType} q1 The second quaternion.
    - * @param {number} t The interpolation factor.
    - * @param {goog.vec.Quaternion.AnyType} resultQuat The quaternion to
    - *     receive the results (may be q0 or q1).
    - */
    -goog.vec.Quaternion.nlerp = goog.vec.Vec4.lerp;
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/quaternion_test.html b/src/database/third_party/closure-library/closure/goog/vec/quaternion_test.html
    deleted file mode 100644
    index 4ca760045e5..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/quaternion_test.html
    +++ /dev/null
    @@ -1,195 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.vec.Quaternion</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.vec.Float32Array');
    -  goog.require('goog.vec.Mat4');
    -  goog.require('goog.vec.Quaternion');
    -  goog.require('goog.vec.Vec3');
    -  goog.require('goog.vec.Vec4');
    -  goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -  function testConjugate() {
    -    var q0 = goog.vec.Quaternion.createFloat32FromValues(1, 2, 3, 4);
    -    var q1 = goog.vec.Quaternion.createFloat32();
    -
    -    goog.vec.Quaternion.conjugate(q0, q1);
    -    assertElementsEquals([1, 2, 3, 4], q0);
    -    assertElementsEquals([-1, -2, -3, 4], q1);
    -
    -    goog.vec.Quaternion.conjugate(q1, q1);
    -    assertElementsEquals([1, 2, 3, 4], q1);
    -  }
    -
    -  function testConcat() {
    -    var q0 = goog.vec.Quaternion.createFloat32FromValues(1, 2, 3, 4);
    -    var q1 = goog.vec.Quaternion.createFloat32FromValues(2, 3, 4, 5);
    -    var q2 = goog.vec.Quaternion.createFloat32();
    -    goog.vec.Quaternion.concat(q0, q1, q2);
    -    assertElementsEquals([12, 24, 30, 0], q2);
    -
    -    goog.vec.Quaternion.concat(q0, q1, q0);
    -    assertElementsEquals([12, 24, 30, 0], q0);
    -  }
    -
    -  function testSlerp() {
    -    var q0 = goog.vec.Quaternion.createFloat32FromValues(1, 2, 3, 4);
    -    var q1 = goog.vec.Quaternion.createFloat32FromValues(5, -6, 7, -8);
    -    var q2 = goog.vec.Quaternion.createFloat32();
    -
    -    goog.vec.Quaternion.slerp(q0, q1, 0, q2);
    -    assertElementsEquals([5, -6, 7, -8], q2);
    -
    -    goog.vec.Quaternion.normalize(q0, q0);
    -    goog.vec.Quaternion.normalize(q1, q1);
    -
    -    goog.vec.Quaternion.slerp(q0, q0, .5, q2);
    -    assertElementsEquals(q0, q2);
    -
    -    goog.vec.Quaternion.slerp(q0, q1, 0, q2);
    -    assertElementsEquals(q0, q2);
    -
    -    goog.vec.Quaternion.slerp(q0, q1, 1, q2);
    -    if (q1[3] * q2[3] < 0) {
    -      goog.vec.Quaternion.negate(q2, q2);
    -    }
    -    assertElementsEquals(q1, q2);
    -
    -    goog.vec.Quaternion.slerp(q0, q1, .3, q2);
    -    assertElementsRoughlyEqual(
    -        [-0.000501537327541, 0.4817612034640, 0.2398775270769, 0.842831337398],
    -        q2, goog.vec.EPSILON);
    -
    -    goog.vec.Quaternion.slerp(q0, q1, .5, q2);
    -    assertElementsRoughlyEqual(
    -        [-0.1243045421171, 0.51879732466, 0.0107895780990, 0.845743047108],
    -        q2, goog.vec.EPSILON);
    -
    -    goog.vec.Quaternion.slerp(q0, q1, .8, q0);
    -    assertElementsRoughlyEqual(
    -        [-0.291353561485, 0.506925588797, -0.3292443285721, 0.741442999653],
    -        q0, goog.vec.EPSILON);
    -  }
    -
    -  function testToRotMatrix() {
    -    var q0 = goog.vec.Quaternion.createFloat32FromValues(
    -        0.22094256606638, 0.53340203646030,
    -        0.64777022739548, 0.497051689967954);
    -    var m0 = goog.vec.Mat4.createFloat32();
    -    goog.vec.Quaternion.toRotationMatrix4(q0, m0);
    -
    -    assertElementsRoughlyEqual(
    -        [-0.408248, 0.8796528, -0.244016935, 0,
    -         -0.4082482, 0.06315623, 0.9106836, 0,
    -         0.8164965, 0.47140452, 0.3333333, 0,
    -         0, 0, 0, 1],
    -        m0, goog.vec.EPSILON);
    -  }
    -
    -  function testFromRotMatrix() {
    -    var m0 = goog.vec.Mat4.createFloat32FromValues(
    -        -0.408248, 0.8796528, -0.244016935, 0,
    -        -0.4082482, 0.06315623, 0.9106836, 0,
    -        0.8164965, 0.47140452, 0.3333333, 0,
    -        0, 0, 0, 1);
    -    var q0 = goog.vec.Quaternion.createFloat32();
    -    goog.vec.Quaternion.fromRotationMatrix4(m0, q0);
    -    assertElementsRoughlyEqual(
    -        [0.22094256606638, 0.53340203646030,
    -         0.64777022739548, 0.497051689967954],
    -        q0, goog.vec.EPSILON);
    -  }
    -
    -  function testToAngleAxis() {
    -    // Test the identity rotation.
    -    var q0 = goog.vec.Quaternion.createFloat32FromValues(0, 0, 0, 1);
    -    var axis = goog.vec.Vec3.createFloat32();
    -    var angle = goog.vec.Quaternion.toAngleAxis(q0, axis);
    -    assertRoughlyEquals(0.0, angle, goog.vec.EPSILON);
    -    assertElementsRoughlyEqual([1, 0, 0], axis, goog.vec.EPSILON);
    -
    -    // Check equivalent representations of the same rotation.
    -    goog.vec.Quaternion.setFromValues(
    -        q0, -0.288675032, 0.622008682, -0.17254543, 0.70710678);
    -    angle = goog.vec.Quaternion.toAngleAxis(q0, axis);
    -    assertRoughlyEquals(Math.PI / 2, angle, goog.vec.EPSILON);
    -    assertElementsRoughlyEqual([-0.408248, 0.8796528, -0.244016],
    -                               axis, goog.vec.EPSILON);
    -    // The polar opposite unit quaternion is the same rotation, so we
    -    // check that the negated quaternion yields the negated angle and axis.
    -    goog.vec.Quaternion.negate(q0, q0);
    -    angle = goog.vec.Quaternion.toAngleAxis(q0, axis);
    -    assertRoughlyEquals(-Math.PI / 2, angle, goog.vec.EPSILON);
    -    assertElementsRoughlyEqual([0.408248, -0.8796528, 0.244016],
    -                               axis, goog.vec.EPSILON);
    -
    -    // Verify that the inverse rotation yields the inverse axis.
    -    goog.vec.Quaternion.conjugate(q0, q0);
    -    angle = goog.vec.Quaternion.toAngleAxis(q0, axis);
    -    assertRoughlyEquals(-Math.PI / 2, angle, goog.vec.EPSILON);
    -    assertElementsRoughlyEqual([-0.408248, 0.8796528, -0.244016],
    -                               axis, goog.vec.EPSILON);
    -  }
    -
    -  function testFromAngleAxis() {
    -    // Test identity rotation (zero angle or multiples of TWO_PI).
    -    var angle = 0.0;
    -    var axis = goog.vec.Vec3.createFloat32FromValues(-0.408248, 0.8796528,
    -                                                     -0.244016);
    -    var q0 = goog.vec.Quaternion.createFloat32();
    -    goog.vec.Quaternion.fromAngleAxis(angle, axis, q0);
    -    assertElementsRoughlyEqual([0, 0, 0, 1], q0, goog.vec.EPSILON);
    -    angle = 4 * Math.PI;
    -    goog.vec.Quaternion.fromAngleAxis(angle, axis, q0);
    -    assertElementsRoughlyEqual([0, 0, 0, 1], q0, goog.vec.EPSILON);
    -
    -    // General test of various rotations around axes of different lengths.
    -    angle = Math.PI / 2;
    -    goog.vec.Quaternion.fromAngleAxis(angle, axis, q0);
    -    assertElementsRoughlyEqual(
    -        [-0.288675032, 0.622008682, -0.17254543, 0.70710678],
    -        q0, goog.vec.EPSILON);
    -    // Angle multiples of TWO_PI with a scaled axis should be the same.
    -    angle += 4 * Math.PI;
    -    goog.vec.Vec3.scale(axis, 7.0, axis);
    -    goog.vec.Quaternion.fromAngleAxis(angle, axis, q0);
    -    assertElementsRoughlyEqual(
    -        [-0.288675032, 0.622008682, -0.17254543, 0.70710678],
    -        q0, goog.vec.EPSILON);
    -    goog.vec.Vec3.setFromValues(axis, 1, 5, 8);
    -    goog.vec.Quaternion.fromAngleAxis(angle, axis, q0);
    -    assertElementsRoughlyEqual(
    -        [0.074535599, 0.372677996, 0.596284794, 0.70710678],
    -        q0, goog.vec.EPSILON);
    -
    -    // Check equivalent representations of the same rotation.
    -    angle = Math.PI / 5;
    -    goog.vec.Vec3.setFromValues(axis, 5, -2, -10);
    -    goog.vec.Quaternion.fromAngleAxis(angle, axis, q0);
    -    assertElementsRoughlyEqual(
    -        [0.136037146, -0.0544148586, -0.27207429, 0.951056516],
    -        q0, goog.vec.EPSILON);
    -    // The negated angle and axis should yield the same rotation.
    -    angle = -Math.PI / 5;
    -    goog.vec.Vec3.negate(axis, axis);
    -    goog.vec.Quaternion.fromAngleAxis(angle, axis, q0);
    -    assertElementsRoughlyEqual(
    -        [0.136037146, -0.0544148586, -0.27207429, 0.951056516],
    -        q0, goog.vec.EPSILON);
    -  }
    -
    -</script>
    -</body>
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/ray.js b/src/database/third_party/closure-library/closure/goog/vec/ray.js
    deleted file mode 100644
    index 84ca1f7df92..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/ray.js
    +++ /dev/null
    @@ -1,95 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Implements a 3D ray that are compatible with WebGL.
    - * Each element is a float64 in case high precision is required.
    - * The API is structured to avoid unnecessary memory allocations.
    - * The last parameter will typically be the output vector and an
    - * object can be both an input and output parameter to all methods
    - * except where noted.
    - *
    - */
    -goog.provide('goog.vec.Ray');
    -
    -goog.require('goog.vec.Vec3');
    -
    -
    -
    -/**
    - * Constructs a new ray with an optional origin and direction. If not specified,
    - * the default is [0, 0, 0].
    - * @param {goog.vec.Vec3.AnyType=} opt_origin The optional origin.
    - * @param {goog.vec.Vec3.AnyType=} opt_dir The optional direction.
    - * @constructor
    - * @final
    - */
    -goog.vec.Ray = function(opt_origin, opt_dir) {
    -  /**
    -   * @type {goog.vec.Vec3.Float64}
    -   */
    -  this.origin = goog.vec.Vec3.createFloat64();
    -  if (opt_origin) {
    -    goog.vec.Vec3.setFromArray(this.origin, opt_origin);
    -  }
    -
    -  /**
    -   * @type {goog.vec.Vec3.Float64}
    -   */
    -  this.dir = goog.vec.Vec3.createFloat64();
    -  if (opt_dir) {
    -    goog.vec.Vec3.setFromArray(this.dir, opt_dir);
    -  }
    -};
    -
    -
    -/**
    - * Sets the origin and direction of the ray.
    - * @param {goog.vec.AnyType} origin The new origin.
    - * @param {goog.vec.AnyType} dir The new direction.
    - */
    -goog.vec.Ray.prototype.set = function(origin, dir) {
    -  goog.vec.Vec3.setFromArray(this.origin, origin);
    -  goog.vec.Vec3.setFromArray(this.dir, dir);
    -};
    -
    -
    -/**
    - * Sets the origin of the ray.
    - * @param {goog.vec.AnyType} origin the new origin.
    - */
    -goog.vec.Ray.prototype.setOrigin = function(origin) {
    -  goog.vec.Vec3.setFromArray(this.origin, origin);
    -};
    -
    -
    -/**
    - * Sets the direction of the ray.
    - * @param {goog.vec.AnyType} dir The new direction.
    - */
    -goog.vec.Ray.prototype.setDir = function(dir) {
    -  goog.vec.Vec3.setFromArray(this.dir, dir);
    -};
    -
    -
    -/**
    - * Returns true if this ray is equal to the other ray.
    - * @param {goog.vec.Ray} other The other ray.
    - * @return {boolean} True if this ray is equal to the other ray.
    - */
    -goog.vec.Ray.prototype.equals = function(other) {
    -  return other != null &&
    -      goog.vec.Vec3.equals(this.origin, other.origin) &&
    -      goog.vec.Vec3.equals(this.dir, other.dir);
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/ray_test.html b/src/database/third_party/closure-library/closure/goog/vec/ray_test.html
    deleted file mode 100644
    index 61d878736bb..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/ray_test.html
    +++ /dev/null
    @@ -1,66 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.vec.Ray</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.vec.Float32Array');
    -  goog.require('goog.vec.Ray');
    -  goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -  function testConstructor() {
    -    var new_ray = new goog.vec.Ray();
    -    assertElementsEquals([0, 0, 0], new_ray.origin);
    -    assertElementsEquals([0, 0, 0], new_ray.dir);
    -
    -    new_ray = new goog.vec.Ray([1, 2, 3], [4, 5, 6]);
    -    assertElementsEquals([1, 2, 3], new_ray.origin);
    -    assertElementsEquals([4, 5, 6], new_ray.dir);
    -  }
    -
    -  function testSet() {
    -    var new_ray = new goog.vec.Ray();
    -    new_ray.set([2, 3, 4], [5, 6, 7]);
    -    assertElementsEquals([2, 3, 4], new_ray.origin);
    -    assertElementsEquals([5, 6, 7], new_ray.dir);
    -  }
    -
    -  function testSetOrigin() {
    -    var new_ray = new goog.vec.Ray();
    -    new_ray.setOrigin([1, 2, 3]);
    -    assertElementsEquals([1, 2, 3], new_ray.origin);
    -    assertElementsEquals([0, 0, 0], new_ray.dir);
    -  }
    -
    -
    -  function testSetDir() {
    -    var new_ray = new goog.vec.Ray();
    -    new_ray.setDir([2, 3, 4]);
    -    assertElementsEquals([0, 0, 0], new_ray.origin);
    -    assertElementsEquals([2, 3, 4], new_ray.dir);
    -  }
    -
    -  function testEquals() {
    -    var r0 = new goog.vec.Ray([1, 2, 3], [4, 5, 6]);
    -    var r1 = new goog.vec.Ray([5, 2, 3], [4, 5, 6]);
    -    assertFalse(r0.equals(r1));
    -    assertFalse(r0.equals(null));
    -    assertTrue(r1.equals(r1));
    -    r1.setOrigin(r0.origin);
    -    assertTrue(r1.equals(r0));
    -    assertTrue(r0.equals(r1));
    -  }
    -
    -</script>
    -</body>
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/vec.js b/src/database/third_party/closure-library/closure/goog/vec/vec.js
    deleted file mode 100644
    index de493fee5b4..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/vec.js
    +++ /dev/null
    @@ -1,73 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Supplies global data types and constants for the vector math
    - *     library.
    - */
    -goog.provide('goog.vec');
    -goog.provide('goog.vec.AnyType');
    -goog.provide('goog.vec.ArrayType');
    -goog.provide('goog.vec.Float32');
    -goog.provide('goog.vec.Float64');
    -goog.provide('goog.vec.Number');
    -
    -
    -/**
    - * On platforms that don't have native Float32Array or Float64Array support we
    - * use a javascript implementation so that this math library can be used on all
    - * platforms.
    - * @suppress {extraRequire}
    - */
    -goog.require('goog.vec.Float32Array');
    -/** @suppress {extraRequire} */
    -goog.require('goog.vec.Float64Array');
    -
    -// All vector and matrix operations are based upon arrays of numbers using
    -// either Float32Array, Float64Array, or a standard Javascript Array of
    -// Numbers.
    -
    -
    -/** @typedef {!Float32Array} */
    -goog.vec.Float32;
    -
    -
    -/** @typedef {!Float64Array} */
    -goog.vec.Float64;
    -
    -
    -/** @typedef {!Array<number>} */
    -goog.vec.Number;
    -
    -
    -/** @typedef {!goog.vec.Float32|!goog.vec.Float64|!goog.vec.Number} */
    -goog.vec.AnyType;
    -
    -
    -/**
    - * @deprecated Use AnyType.
    - * @typedef {!Float32Array|!Array<number>}
    - */
    -goog.vec.ArrayType;
    -
    -
    -/**
    - * For graphics work, 6 decimal places of accuracy are typically all that is
    - * required.
    - *
    - * @type {number}
    - * @const
    - */
    -goog.vec.EPSILON = 1e-6;
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/vec2.js b/src/database/third_party/closure-library/closure/goog/vec/vec2.js
    deleted file mode 100644
    index daf789a160d..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/vec2.js
    +++ /dev/null
    @@ -1,439 +0,0 @@
    -// Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Definition of 2 element vectors.  This follows the same design
    - * patterns as Vec3 and Vec4.
    - *
    - */
    -
    -goog.provide('goog.vec.Vec2');
    -
    -/** @suppress {extraRequire} */
    -goog.require('goog.vec');
    -
    -
    -/** @typedef {goog.vec.Float32} */ goog.vec.Vec2.Float32;
    -/** @typedef {goog.vec.Float64} */ goog.vec.Vec2.Float64;
    -/** @typedef {goog.vec.Number} */ goog.vec.Vec2.Number;
    -/** @typedef {goog.vec.AnyType} */ goog.vec.Vec2.AnyType;
    -
    -
    -/**
    - * Creates a 2 element vector of Float32. The array is initialized to zero.
    - *
    - * @return {!goog.vec.Vec2.Float32} The new 2 element array.
    - */
    -goog.vec.Vec2.createFloat32 = function() {
    -  return new Float32Array(2);
    -};
    -
    -
    -/**
    - * Creates a 2 element vector of Float64. The array is initialized to zero.
    - *
    - * @return {!goog.vec.Vec2.Float64} The new 2 element array.
    - */
    -goog.vec.Vec2.createFloat64 = function() {
    -  return new Float64Array(2);
    -};
    -
    -
    -/**
    - * Creates a 2 element vector of Number. The array is initialized to zero.
    - *
    - * @return {!goog.vec.Vec2.Number} The new 2 element array.
    - */
    -goog.vec.Vec2.createNumber = function() {
    -  var a = new Array(2);
    -  goog.vec.Vec2.setFromValues(a, 0, 0);
    -  return a;
    -};
    -
    -
    -/**
    - * Creates a new 2 element FLoat32 vector initialized with the value from the
    - * given array.
    - *
    - * @param {goog.vec.Vec2.AnyType} vec The source 2 element array.
    - * @return {!goog.vec.Vec2.Float32} The new 2 element array.
    - */
    -goog.vec.Vec2.createFloat32FromArray = function(vec) {
    -  var newVec = goog.vec.Vec2.createFloat32();
    -  goog.vec.Vec2.setFromArray(newVec, vec);
    -  return newVec;
    -};
    -
    -
    -/**
    - * Creates a new 2 element Float32 vector initialized with the supplied values.
    - *
    - * @param {number} vec0 The value for element at index 0.
    - * @param {number} vec1 The value for element at index 1.
    - * @return {!goog.vec.Vec2.Float32} The new vector.
    - */
    -goog.vec.Vec2.createFloat32FromValues = function(vec0, vec1) {
    -  var a = goog.vec.Vec2.createFloat32();
    -  goog.vec.Vec2.setFromValues(a, vec0, vec1);
    -  return a;
    -};
    -
    -
    -/**
    - * Creates a clone of the given 2 element Float32 vector.
    - *
    - * @param {goog.vec.Vec2.Float32} vec The source 2 element vector.
    - * @return {!goog.vec.Vec2.Float32} The new cloned vector.
    - */
    -goog.vec.Vec2.cloneFloat32 = goog.vec.Vec2.createFloat32FromArray;
    -
    -
    -/**
    - * Creates a new 2 element Float64 vector initialized with the value from the
    - * given array.
    - *
    - * @param {goog.vec.Vec2.AnyType} vec The source 2 element array.
    - * @return {!goog.vec.Vec2.Float64} The new 2 element array.
    - */
    -goog.vec.Vec2.createFloat64FromArray = function(vec) {
    -  var newVec = goog.vec.Vec2.createFloat64();
    -  goog.vec.Vec2.setFromArray(newVec, vec);
    -  return newVec;
    -};
    -
    -
    -/**
    -* Creates a new 2 element Float64 vector initialized with the supplied values.
    -*
    -* @param {number} vec0 The value for element at index 0.
    -* @param {number} vec1 The value for element at index 1.
    -* @return {!goog.vec.Vec2.Float64} The new vector.
    -*/
    -goog.vec.Vec2.createFloat64FromValues = function(vec0, vec1) {
    -  var vec = goog.vec.Vec2.createFloat64();
    -  goog.vec.Vec2.setFromValues(vec, vec0, vec1);
    -  return vec;
    -};
    -
    -
    -/**
    - * Creates a clone of the given 2 element vector.
    - *
    - * @param {goog.vec.Vec2.Float64} vec The source 2 element vector.
    - * @return {!goog.vec.Vec2.Float64} The new cloned vector.
    - */
    -goog.vec.Vec2.cloneFloat64 = goog.vec.Vec2.createFloat64FromArray;
    -
    -
    -/**
    - * Initializes the vector with the given values.
    - *
    - * @param {goog.vec.Vec2.AnyType} vec The vector to receive the values.
    - * @param {number} vec0 The value for element at index 0.
    - * @param {number} vec1 The value for element at index 1.
    - * @return {!goog.vec.Vec2.AnyType} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec2.setFromValues = function(vec, vec0, vec1) {
    -  vec[0] = vec0;
    -  vec[1] = vec1;
    -  return vec;
    -};
    -
    -
    -/**
    - * Initializes the vector with the given array of values.
    - *
    - * @param {goog.vec.Vec2.AnyType} vec The vector to receive the
    - *     values.
    - * @param {goog.vec.Vec2.AnyType} values The array of values.
    - * @return {!goog.vec.Vec2.AnyType} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec2.setFromArray = function(vec, values) {
    -  vec[0] = values[0];
    -  vec[1] = values[1];
    -  return vec;
    -};
    -
    -
    -/**
    - * Performs a component-wise addition of vec0 and vec1 together storing the
    - * result into resultVec.
    - *
    - * @param {goog.vec.Vec2.AnyType} vec0 The first addend.
    - * @param {goog.vec.Vec2.AnyType} vec1 The second addend.
    - * @param {goog.vec.Vec2.AnyType} resultVec The vector to
    - *     receive the result. May be vec0 or vec1.
    - * @return {!goog.vec.Vec2.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec2.add = function(vec0, vec1, resultVec) {
    -  resultVec[0] = vec0[0] + vec1[0];
    -  resultVec[1] = vec0[1] + vec1[1];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Performs a component-wise subtraction of vec1 from vec0 storing the
    - * result into resultVec.
    - *
    - * @param {goog.vec.Vec2.AnyType} vec0 The minuend.
    - * @param {goog.vec.Vec2.AnyType} vec1 The subtrahend.
    - * @param {goog.vec.Vec2.AnyType} resultVec The vector to
    - *     receive the result. May be vec0 or vec1.
    - * @return {!goog.vec.Vec2.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec2.subtract = function(vec0, vec1, resultVec) {
    -  resultVec[0] = vec0[0] - vec1[0];
    -  resultVec[1] = vec0[1] - vec1[1];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Negates vec0, storing the result into resultVec.
    - *
    - * @param {goog.vec.Vec2.AnyType} vec0 The vector to negate.
    - * @param {goog.vec.Vec2.AnyType} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.Vec2.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec2.negate = function(vec0, resultVec) {
    -  resultVec[0] = -vec0[0];
    -  resultVec[1] = -vec0[1];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Takes the absolute value of each component of vec0 storing the result in
    - * resultVec.
    - *
    - * @param {goog.vec.Vec2.AnyType} vec0 The source vector.
    - * @param {goog.vec.Vec2.AnyType} resultVec The vector to receive the result.
    - *     May be vec0.
    - * @return {!goog.vec.Vec2.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec2.abs = function(vec0, resultVec) {
    -  resultVec[0] = Math.abs(vec0[0]);
    -  resultVec[1] = Math.abs(vec0[1]);
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Multiplies each component of vec0 with scalar storing the product into
    - * resultVec.
    - *
    - * @param {goog.vec.Vec2.AnyType} vec0 The source vector.
    - * @param {number} scalar The value to multiply with each component of vec0.
    - * @param {goog.vec.Vec2.AnyType} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.Vec2.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec2.scale = function(vec0, scalar, resultVec) {
    -  resultVec[0] = vec0[0] * scalar;
    -  resultVec[1] = vec0[1] * scalar;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns the magnitudeSquared of the given vector.
    - *
    - * @param {goog.vec.Vec2.AnyType} vec0 The vector.
    - * @return {number} The magnitude of the vector.
    - */
    -goog.vec.Vec2.magnitudeSquared = function(vec0) {
    -  var x = vec0[0], y = vec0[1];
    -  return x * x + y * y;
    -};
    -
    -
    -/**
    - * Returns the magnitude of the given vector.
    - *
    - * @param {goog.vec.Vec2.AnyType} vec0 The vector.
    - * @return {number} The magnitude of the vector.
    - */
    -goog.vec.Vec2.magnitude = function(vec0) {
    -  var x = vec0[0], y = vec0[1];
    -  return Math.sqrt(x * x + y * y);
    -};
    -
    -
    -/**
    - * Normalizes the given vector storing the result into resultVec.
    - *
    - * @param {goog.vec.Vec2.AnyType} vec0 The vector to normalize.
    - * @param {goog.vec.Vec2.AnyType} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.Vec2.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec2.normalize = function(vec0, resultVec) {
    -  var ilen = 1 / goog.vec.Vec2.magnitude(vec0);
    -  resultVec[0] = vec0[0] * ilen;
    -  resultVec[1] = vec0[1] * ilen;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns the scalar product of vectors vec0 and vec1.
    - *
    - * @param {goog.vec.Vec2.AnyType} vec0 The first vector.
    - * @param {goog.vec.Vec2.AnyType} vec1 The second vector.
    - * @return {number} The scalar product.
    - */
    -goog.vec.Vec2.dot = function(vec0, vec1) {
    -  return vec0[0] * vec1[0] + vec0[1] * vec1[1];
    -};
    -
    -
    -/**
    - * Returns the squared distance between two points.
    - *
    - * @param {goog.vec.Vec2.AnyType} vec0 First point.
    - * @param {goog.vec.Vec2.AnyType} vec1 Second point.
    - * @return {number} The squared distance between the points.
    - */
    -goog.vec.Vec2.distanceSquared = function(vec0, vec1) {
    -  var x = vec0[0] - vec1[0];
    -  var y = vec0[1] - vec1[1];
    -  return x * x + y * y;
    -};
    -
    -
    -/**
    - * Returns the distance between two points.
    - *
    - * @param {goog.vec.Vec2.AnyType} vec0 First point.
    - * @param {goog.vec.Vec2.AnyType} vec1 Second point.
    - * @return {number} The distance between the points.
    - */
    -goog.vec.Vec2.distance = function(vec0, vec1) {
    -  return Math.sqrt(goog.vec.Vec2.distanceSquared(vec0, vec1));
    -};
    -
    -
    -/**
    - * Returns a unit vector pointing from one point to another.
    - * If the input points are equal then the result will be all zeros.
    - *
    - * @param {goog.vec.Vec2.AnyType} vec0 Origin point.
    - * @param {goog.vec.Vec2.AnyType} vec1 Target point.
    - * @param {goog.vec.Vec2.AnyType} resultVec The vector to receive the
    - *     results (may be vec0 or vec1).
    - * @return {!goog.vec.Vec2.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec2.direction = function(vec0, vec1, resultVec) {
    -  var x = vec1[0] - vec0[0];
    -  var y = vec1[1] - vec0[1];
    -  var d = Math.sqrt(x * x + y * y);
    -  if (d) {
    -    d = 1 / d;
    -    resultVec[0] = x * d;
    -    resultVec[1] = y * d;
    -  } else {
    -    resultVec[0] = resultVec[1] = 0;
    -  }
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Linearly interpolate from vec0 to vec1 according to f. The value of f should
    - * be in the range [0..1] otherwise the results are undefined.
    - *
    - * @param {goog.vec.Vec2.AnyType} vec0 The first vector.
    - * @param {goog.vec.Vec2.AnyType} vec1 The second vector.
    - * @param {number} f The interpolation factor.
    - * @param {goog.vec.Vec2.AnyType} resultVec The vector to receive the
    - *     results (may be vec0 or vec1).
    - * @return {!goog.vec.Vec2.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec2.lerp = function(vec0, vec1, f, resultVec) {
    -  var x = vec0[0], y = vec0[1];
    -  resultVec[0] = (vec1[0] - x) * f + x;
    -  resultVec[1] = (vec1[1] - y) * f + y;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Compares the components of vec0 with the components of another vector or
    - * scalar, storing the larger values in resultVec.
    - *
    - * @param {goog.vec.Vec2.AnyType} vec0 The source vector.
    - * @param {goog.vec.Vec2.AnyType|number} limit The limit vector or scalar.
    - * @param {goog.vec.Vec2.AnyType} resultVec The vector to receive the
    - *     results (may be vec0 or limit).
    - * @return {!goog.vec.Vec2.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec2.max = function(vec0, limit, resultVec) {
    -  if (goog.isNumber(limit)) {
    -    resultVec[0] = Math.max(vec0[0], limit);
    -    resultVec[1] = Math.max(vec0[1], limit);
    -  } else {
    -    resultVec[0] = Math.max(vec0[0], limit[0]);
    -    resultVec[1] = Math.max(vec0[1], limit[1]);
    -  }
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Compares the components of vec0 with the components of another vector or
    - * scalar, storing the smaller values in resultVec.
    - *
    - * @param {goog.vec.Vec2.AnyType} vec0 The source vector.
    - * @param {goog.vec.Vec2.AnyType|number} limit The limit vector or scalar.
    - * @param {goog.vec.Vec2.AnyType} resultVec The vector to receive the
    - *     results (may be vec0 or limit).
    - * @return {!goog.vec.Vec2.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec2.min = function(vec0, limit, resultVec) {
    -  if (goog.isNumber(limit)) {
    -    resultVec[0] = Math.min(vec0[0], limit);
    -    resultVec[1] = Math.min(vec0[1], limit);
    -  } else {
    -    resultVec[0] = Math.min(vec0[0], limit[0]);
    -    resultVec[1] = Math.min(vec0[1], limit[1]);
    -  }
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns true if the components of vec0 are equal to the components of vec1.
    - *
    - * @param {goog.vec.Vec2.AnyType} vec0 The first vector.
    - * @param {goog.vec.Vec2.AnyType} vec1 The second vector.
    - * @return {boolean} True if the vectors are equal, false otherwise.
    - */
    -goog.vec.Vec2.equals = function(vec0, vec1) {
    -  return vec0.length == vec1.length &&
    -      vec0[0] == vec1[0] && vec0[1] == vec1[1];
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/vec2_test.html b/src/database/third_party/closure-library/closure/goog/vec/vec2_test.html
    deleted file mode 100644
    index 4ec7a17bf79..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/vec2_test.html
    +++ /dev/null
    @@ -1,254 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2012 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.vec.Vec2</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.vec.Float32Array');
    -  goog.require('goog.vec.Vec2');
    -  goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -  function testConstructor() {
    -    var v = goog.vec.Vec2.createFloat32();
    -    assertElementsEquals(0, v[0]);
    -    assertEquals(0, v[1]);
    -
    -    assertElementsEquals([0, 0], goog.vec.Vec2.createFloat32());
    -
    -    goog.vec.Vec2.setFromValues(v, 1, 2);
    -    assertElementsEquals([1, 2], v);
    -
    -    var w = goog.vec.Vec2.createFloat64();
    -    assertElementsEquals(0, w[0]);
    -    assertEquals(0, w[1]);
    -
    -    assertElementsEquals([0, 0], goog.vec.Vec2.createFloat64());
    -
    -    goog.vec.Vec2.setFromValues(w, 1, 2);
    -    assertElementsEquals([1, 2], w);
    -  }
    -
    -
    -  function testSet() {
    -    var v = goog.vec.Vec2.createFloat32();
    -    goog.vec.Vec2.setFromValues(v, 1, 2);
    -    assertElementsEquals([1, 2], v);
    -
    -    goog.vec.Vec2.setFromArray(v, [4, 5]);
    -    assertElementsEquals([4, 5], v);
    -
    -    var w = goog.vec.Vec2.createFloat32();
    -    goog.vec.Vec2.setFromValues(w, 1, 2);
    -    assertElementsEquals([1, 2], w);
    -
    -    goog.vec.Vec2.setFromArray(w, [4, 5]);
    -    assertElementsEquals([4, 5], w);
    -  }
    -
    -  function testAdd() {
    -    var v0 = goog.vec.Vec2.createFloat32FromArray([1, 2]);
    -    var v1 = goog.vec.Vec2.createFloat32FromArray([4, 5]);
    -    var v2 = goog.vec.Vec2.cloneFloat32(v0);
    -
    -    goog.vec.Vec2.add(v2, v1, v2);
    -    assertElementsEquals([1, 2], v0);
    -    assertElementsEquals([4, 5], v1);
    -    assertElementsEquals([5, 7], v2);
    -
    -    goog.vec.Vec2.add(goog.vec.Vec2.add(v0, v1, v2), v0, v2);
    -    assertElementsEquals([6, 9], v2);
    -  }
    -
    -  function testSubtract() {
    -    var v0 = goog.vec.Vec2.createFloat32FromArray([1, 2]);
    -    var v1 = goog.vec.Vec2.createFloat32FromArray([4, 5]);
    -    var v2 = goog.vec.Vec2.cloneFloat32(v0);
    -
    -    goog.vec.Vec2.subtract(v2, v1, v2);
    -    assertElementsEquals([1, 2], v0);
    -    assertElementsEquals([4, 5], v1);
    -    assertElementsEquals([-3, -3], v2);
    -
    -    goog.vec.Vec2.setFromValues(v2, 0, 0, 0);
    -    goog.vec.Vec2.subtract(v1, v0, v2);
    -    assertElementsEquals([3, 3], v2);
    -
    -    v2 = goog.vec.Vec2.cloneFloat32(v0);
    -    goog.vec.Vec2.subtract(v2, v1, v2);
    -    assertElementsEquals([-3, -3], v2);
    -
    -    goog.vec.Vec2.subtract(goog.vec.Vec2.subtract(v1, v0, v2), v0, v2);
    -    assertElementsEquals([2, 1], v2);
    -  }
    -
    -  function testNegate() {
    -    var v0 = goog.vec.Vec2.createFloat32FromArray([1, 2]);
    -    var v1 = goog.vec.Vec2.createFloat32();
    -
    -    goog.vec.Vec2.negate(v0, v1);
    -    assertElementsEquals([-1, -2], v1);
    -    assertElementsEquals([1, 2], v0);
    -
    -    goog.vec.Vec2.negate(v0, v0);
    -    assertElementsEquals([-1, -2], v0);
    -  }
    -
    -  function testAbs() {
    -    var v0 = goog.vec.Vec2.createFloat32FromValues(-1, -2);
    -    var v1 = goog.vec.Vec2.createFloat32();
    -
    -    goog.vec.Vec2.abs(v0, v1);
    -    assertElementsEquals([1, 2], v1);
    -    assertElementsEquals([-1, -2], v0);
    -
    -    goog.vec.Vec2.abs(v0, v0);
    -    assertElementsEquals([1, 2], v0);
    -  }
    -
    -  function testScale() {
    -    var v0 = goog.vec.Vec2.createFloat32FromArray([1, 2]);
    -    var v1 = goog.vec.Vec2.createFloat32();
    -
    -    goog.vec.Vec2.scale(v0, 4, v1);
    -    assertElementsEquals([4, 8], v1);
    -    assertElementsEquals([1, 2], v0);
    -
    -    goog.vec.Vec2.setFromArray(v1, v0);
    -    goog.vec.Vec2.scale(v1, 5, v1);
    -    assertElementsEquals([5, 10], v1);
    -  }
    -
    -  function testMagnitudeSquared() {
    -    var v0 = goog.vec.Vec2.createFloat32FromArray([1, 2]);
    -    assertEquals(5, goog.vec.Vec2.magnitudeSquared(v0));
    -  }
    -
    -  function testMagnitude() {
    -    var v0 = goog.vec.Vec2.createFloat32FromArray([1, 2]);
    -    assertEquals(Math.sqrt(5), goog.vec.Vec2.magnitude(v0));
    -  }
    -
    -  function testNormalize() {
    -    var v0 = goog.vec.Vec2.createFloat32FromArray([2, 3]);
    -    var v1 = goog.vec.Vec2.createFloat32();
    -    var v2 = goog.vec.Vec2.createFloat32();
    -    goog.vec.Vec2.scale(
    -        v0, 1 / goog.vec.Vec2.magnitude(v0), v2);
    -
    -    goog.vec.Vec2.normalize(v0, v1);
    -    assertElementsEquals(v2, v1);
    -    assertElementsEquals([2, 3], v0);
    -
    -    goog.vec.Vec2.setFromArray(v1, v0);
    -    goog.vec.Vec2.normalize(v1, v1);
    -    assertElementsEquals(v2, v1);
    -  }
    -
    -  function testDot() {
    -    var v0 = goog.vec.Vec2.createFloat32FromArray([1, 2]);
    -    var v1 = goog.vec.Vec2.createFloat32FromArray([4, 5]);
    -    assertEquals(14, goog.vec.Vec2.dot(v0, v1));
    -    assertEquals(14, goog.vec.Vec2.dot(v1, v0));
    -  }
    -
    -  function testDistanceSquared() {
    -    var v0 = goog.vec.Vec2.createFloat32FromValues(1, 2);
    -    var v1 = goog.vec.Vec2.createFloat32FromValues(1, 2);
    -    assertEquals(0, goog.vec.Vec2.distanceSquared(v0, v1));
    -    goog.vec.Vec2.setFromValues(v0, 1, 2);
    -    goog.vec.Vec2.setFromValues(v1, -1, -2);
    -    assertEquals(20, goog.vec.Vec2.distanceSquared(v0, v1));
    -  }
    -
    -  function testDistance() {
    -    var v0 = goog.vec.Vec2.createFloat32FromValues(1, 2);
    -    var v1 = goog.vec.Vec2.createFloat32FromValues(1, 2);
    -    assertEquals(0, goog.vec.Vec2.distance(v0, v1));
    -    goog.vec.Vec2.setFromValues(v0, 2, 3);
    -    goog.vec.Vec2.setFromValues(v1, -2, 0);
    -    assertEquals(5, goog.vec.Vec2.distance(v0, v1));
    -  }
    -
    -  function testDirection() {
    -    var v0 = goog.vec.Vec2.createFloat32FromValues(1, 2);
    -    var v1 = goog.vec.Vec2.createFloat32FromValues(1, 2);
    -    var dirVec = goog.vec.Vec2.createFloat32FromValues(4, 5);
    -    goog.vec.Vec2.direction(v0, v1, dirVec);
    -    assertElementsEquals([0, 0], dirVec);
    -    goog.vec.Vec2.setFromValues(v0, 0, 0);
    -    goog.vec.Vec2.setFromValues(v1, 1, 0);
    -    goog.vec.Vec2.direction(v0, v1, dirVec);
    -    assertElementsEquals([1, 0], dirVec);
    -    goog.vec.Vec2.setFromValues(v0, 1, 1);
    -    goog.vec.Vec2.setFromValues(v1, 0, 0);
    -    goog.vec.Vec2.direction(v0, v1, dirVec);
    -    assertElementsRoughlyEqual(
    -        [-0.707106781, -0.707106781],
    -        dirVec, goog.vec.EPSILON);
    -  }
    -
    -  function testLerp() {
    -    var v0 = goog.vec.Vec2.createFloat32FromValues(1, 2);
    -    var v1 = goog.vec.Vec2.createFloat32FromValues(10, 20);
    -    var v2 = goog.vec.Vec2.cloneFloat32(v0);
    -
    -    goog.vec.Vec2.lerp(v2, v1, 0, v2);
    -    assertElementsEquals([1, 2], v2);
    -    goog.vec.Vec2.lerp(v2, v1, 1, v2);
    -    assertElementsEquals([10, 20], v2);
    -    goog.vec.Vec2.lerp(v0, v1, .5, v2);
    -    assertElementsEquals([5.5, 11], v2);
    -  }
    -
    -  function testMax() {
    -    var v0 = goog.vec.Vec2.createFloat32FromValues(10, 20);
    -    var v1 = goog.vec.Vec2.createFloat32FromValues(5, 25);
    -    var v2 = goog.vec.Vec2.createFloat32();
    -
    -    goog.vec.Vec2.max(v0, v1, v2);
    -    assertElementsEquals([10, 25], v2);
    -    goog.vec.Vec2.max(v1, v0, v1);
    -    assertElementsEquals([10, 25], v1);
    -    goog.vec.Vec2.max(v2, 20, v2);
    -    assertElementsEquals([20, 25], v2);
    -  }
    -
    -  function testMin() {
    -    var v0 = goog.vec.Vec2.createFloat32FromValues(10, 20);
    -    var v1 = goog.vec.Vec2.createFloat32FromValues(5, 25);
    -    var v2 = goog.vec.Vec2.createFloat32();
    -
    -    goog.vec.Vec2.min(v0, v1, v2);
    -    assertElementsEquals([5, 20], v2);
    -    goog.vec.Vec2.min(v1, v0, v1);
    -    assertElementsEquals([5, 20], v1);
    -    goog.vec.Vec2.min(v2, 10, v2);
    -    assertElementsEquals([5, 10], v2);
    -  }
    -
    -  function testEquals() {
    -    var v0 = goog.vec.Vec2.createFloat32FromValues(1, 2);
    -    var v1 = goog.vec.Vec2.cloneFloat32(v0);
    -    assertElementsEquals(v0, v1);
    -
    -    v1[0] = 4;
    -    assertFalse(goog.vec.Vec2.equals(v0, v1));
    -
    -    v1 = goog.vec.Vec2.cloneFloat32(v0);
    -    v1[1] = 4;
    -    assertFalse(goog.vec.Vec2.equals(v0, v1));
    -  }
    -
    -</script>
    -</body>
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/vec2d.js b/src/database/third_party/closure-library/closure/goog/vec/vec2d.js
    deleted file mode 100644
    index ad07200923c..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/vec2d.js
    +++ /dev/null
    @@ -1,424 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -//                                                                           //
    -// Any edits to this file must be applied to vec2f.js by running:            //
    -//   swap_type.sh vec2d.js > vec2f.js                                        //
    -//                                                                           //
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -
    -
    -/**
    - * @fileoverview Provides functions for operating on 2 element double (64bit)
    - * vectors.
    - *
    - * The last parameter will typically be the output object and an object
    - * can be both an input and output parameter to all methods except where
    - * noted.
    - *
    - * See the README for notes about the design and structure of the API
    - * (especially related to performance).
    - *
    - */
    -
    -goog.provide('goog.vec.vec2d');
    -goog.provide('goog.vec.vec2d.Type');
    -
    -/** @suppress {extraRequire} */
    -goog.require('goog.vec');
    -
    -
    -/** @typedef {goog.vec.Float64} */ goog.vec.vec2d.Type;
    -
    -
    -/**
    - * Creates a vec2d with all elements initialized to zero.
    - *
    - * @return {!goog.vec.vec2d.Type} The new vec2d.
    - */
    -goog.vec.vec2d.create = function() {
    -  return new Float64Array(2);
    -};
    -
    -
    -/**
    - * Initializes the vector with the given values.
    - *
    - * @param {goog.vec.vec2d.Type} vec The vector to receive the values.
    - * @param {number} v0 The value for element at index 0.
    - * @param {number} v1 The value for element at index 1.
    - * @return {!goog.vec.vec2d.Type} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2d.setFromValues = function(vec, v0, v1) {
    -  vec[0] = v0;
    -  vec[1] = v1;
    -  return vec;
    -};
    -
    -
    -/**
    - * Initializes vec2d vec from vec2d src.
    - *
    - * @param {goog.vec.vec2d.Type} vec The destination vector.
    - * @param {goog.vec.vec2d.Type} src The source vector.
    - * @return {!goog.vec.vec2d.Type} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2d.setFromVec2d = function(vec, src) {
    -  vec[0] = src[0];
    -  vec[1] = src[1];
    -  return vec;
    -};
    -
    -
    -/**
    - * Initializes vec2d vec from vec2f src (typed as a Float32Array to
    - * avoid circular goog.requires).
    - *
    - * @param {goog.vec.vec2d.Type} vec The destination vector.
    - * @param {Float32Array} src The source vector.
    - * @return {!goog.vec.vec2d.Type} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2d.setFromVec2f = function(vec, src) {
    -  vec[0] = src[0];
    -  vec[1] = src[1];
    -  return vec;
    -};
    -
    -
    -/**
    - * Initializes vec2d vec from Array src.
    - *
    - * @param {goog.vec.vec2d.Type} vec The destination vector.
    - * @param {Array<number>} src The source vector.
    - * @return {!goog.vec.vec2d.Type} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2d.setFromArray = function(vec, src) {
    -  vec[0] = src[0];
    -  vec[1] = src[1];
    -  return vec;
    -};
    -
    -
    -/**
    - * Performs a component-wise addition of vec0 and vec1 together storing the
    - * result into resultVec.
    - *
    - * @param {goog.vec.vec2d.Type} vec0 The first addend.
    - * @param {goog.vec.vec2d.Type} vec1 The second addend.
    - * @param {goog.vec.vec2d.Type} resultVec The vector to
    - *     receive the result. May be vec0 or vec1.
    - * @return {!goog.vec.vec2d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2d.add = function(vec0, vec1, resultVec) {
    -  resultVec[0] = vec0[0] + vec1[0];
    -  resultVec[1] = vec0[1] + vec1[1];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Performs a component-wise subtraction of vec1 from vec0 storing the
    - * result into resultVec.
    - *
    - * @param {goog.vec.vec2d.Type} vec0 The minuend.
    - * @param {goog.vec.vec2d.Type} vec1 The subtrahend.
    - * @param {goog.vec.vec2d.Type} resultVec The vector to
    - *     receive the result. May be vec0 or vec1.
    - * @return {!goog.vec.vec2d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2d.subtract = function(vec0, vec1, resultVec) {
    -  resultVec[0] = vec0[0] - vec1[0];
    -  resultVec[1] = vec0[1] - vec1[1];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Multiplies each component of vec0 with the matching element of vec0
    - * storing the products into resultVec.
    - *
    - * @param {!goog.vec.vec2d.Type} vec0 The first vector.
    - * @param {!goog.vec.vec2d.Type} vec1 The second vector.
    - * @param {!goog.vec.vec2d.Type} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.vec2d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2d.componentMultiply = function(vec0, vec1, resultVec) {
    -  resultVec[0] = vec0[0] * vec1[0];
    -  resultVec[1] = vec0[1] * vec1[1];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Divides each component of vec0 with the matching element of vec0
    - * storing the divisor into resultVec.
    - *
    - * @param {!goog.vec.vec2d.Type} vec0 The first vector.
    - * @param {!goog.vec.vec2d.Type} vec1 The second vector.
    - * @param {!goog.vec.vec2d.Type} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.vec2d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2d.componentDivide = function(vec0, vec1, resultVec) {
    -  resultVec[0] = vec0[0] / vec1[0];
    -  resultVec[1] = vec0[1] / vec1[1];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Negates vec0, storing the result into resultVec.
    - *
    - * @param {goog.vec.vec2d.Type} vec0 The vector to negate.
    - * @param {goog.vec.vec2d.Type} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.vec2d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2d.negate = function(vec0, resultVec) {
    -  resultVec[0] = -vec0[0];
    -  resultVec[1] = -vec0[1];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Takes the absolute value of each component of vec0 storing the result in
    - * resultVec.
    - *
    - * @param {goog.vec.vec2d.Type} vec0 The source vector.
    - * @param {goog.vec.vec2d.Type} resultVec The vector to receive the result.
    - *     May be vec0.
    - * @return {!goog.vec.vec2d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2d.abs = function(vec0, resultVec) {
    -  resultVec[0] = Math.abs(vec0[0]);
    -  resultVec[1] = Math.abs(vec0[1]);
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Multiplies each component of vec0 with scalar storing the product into
    - * resultVec.
    - *
    - * @param {goog.vec.vec2d.Type} vec0 The source vector.
    - * @param {number} scalar The value to multiply with each component of vec0.
    - * @param {goog.vec.vec2d.Type} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.vec2d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2d.scale = function(vec0, scalar, resultVec) {
    -  resultVec[0] = vec0[0] * scalar;
    -  resultVec[1] = vec0[1] * scalar;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns the magnitudeSquared of the given vector.
    - *
    - * @param {goog.vec.vec2d.Type} vec0 The vector.
    - * @return {number} The magnitude of the vector.
    - */
    -goog.vec.vec2d.magnitudeSquared = function(vec0) {
    -  var x = vec0[0], y = vec0[1];
    -  return x * x + y * y;
    -};
    -
    -
    -/**
    - * Returns the magnitude of the given vector.
    - *
    - * @param {goog.vec.vec2d.Type} vec0 The vector.
    - * @return {number} The magnitude of the vector.
    - */
    -goog.vec.vec2d.magnitude = function(vec0) {
    -  var x = vec0[0], y = vec0[1];
    -  return Math.sqrt(x * x + y * y);
    -};
    -
    -
    -/**
    - * Normalizes the given vector storing the result into resultVec.
    - *
    - * @param {goog.vec.vec2d.Type} vec0 The vector to normalize.
    - * @param {goog.vec.vec2d.Type} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.vec2d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2d.normalize = function(vec0, resultVec) {
    -  var x = vec0[0], y = vec0[1];
    -  var ilen = 1 / Math.sqrt(x * x + y * y);
    -  resultVec[0] = x * ilen;
    -  resultVec[1] = y * ilen;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns the scalar product of vectors vec0 and vec1.
    - *
    - * @param {goog.vec.vec2d.Type} vec0 The first vector.
    - * @param {goog.vec.vec2d.Type} vec1 The second vector.
    - * @return {number} The scalar product.
    - */
    -goog.vec.vec2d.dot = function(vec0, vec1) {
    -  return vec0[0] * vec1[0] + vec0[1] * vec1[1];
    -};
    -
    -
    -/**
    - * Returns the squared distance between two points.
    - *
    - * @param {goog.vec.vec2d.Type} vec0 First point.
    - * @param {goog.vec.vec2d.Type} vec1 Second point.
    - * @return {number} The squared distance between the points.
    - */
    -goog.vec.vec2d.distanceSquared = function(vec0, vec1) {
    -  var x = vec0[0] - vec1[0];
    -  var y = vec0[1] - vec1[1];
    -  return x * x + y * y;
    -};
    -
    -
    -/**
    - * Returns the distance between two points.
    - *
    - * @param {goog.vec.vec2d.Type} vec0 First point.
    - * @param {goog.vec.vec2d.Type} vec1 Second point.
    - * @return {number} The distance between the points.
    - */
    -goog.vec.vec2d.distance = function(vec0, vec1) {
    -  return Math.sqrt(goog.vec.vec2d.distanceSquared(vec0, vec1));
    -};
    -
    -
    -/**
    - * Returns a unit vector pointing from one point to another.
    - * If the input points are equal then the result will be all zeros.
    - *
    - * @param {goog.vec.vec2d.Type} vec0 Origin point.
    - * @param {goog.vec.vec2d.Type} vec1 Target point.
    - * @param {goog.vec.vec2d.Type} resultVec The vector to receive the
    - *     results (may be vec0 or vec1).
    - * @return {!goog.vec.vec2d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2d.direction = function(vec0, vec1, resultVec) {
    -  var x = vec1[0] - vec0[0];
    -  var y = vec1[1] - vec0[1];
    -  var d = Math.sqrt(x * x + y * y);
    -  if (d) {
    -    d = 1 / d;
    -    resultVec[0] = x * d;
    -    resultVec[1] = y * d;
    -  } else {
    -    resultVec[0] = resultVec[1] = 0;
    -  }
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Linearly interpolate from vec0 to vec1 according to f. The value of f should
    - * be in the range [0..1] otherwise the results are undefined.
    - *
    - * @param {goog.vec.vec2d.Type} vec0 The first vector.
    - * @param {goog.vec.vec2d.Type} vec1 The second vector.
    - * @param {number} f The interpolation factor.
    - * @param {goog.vec.vec2d.Type} resultVec The vector to receive the
    - *     results (may be vec0 or vec1).
    - * @return {!goog.vec.vec2d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2d.lerp = function(vec0, vec1, f, resultVec) {
    -  var x = vec0[0], y = vec0[1];
    -  resultVec[0] = (vec1[0] - x) * f + x;
    -  resultVec[1] = (vec1[1] - y) * f + y;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Compares the components of vec0 with the components of another vector or
    - * scalar, storing the larger values in resultVec.
    - *
    - * @param {goog.vec.vec2d.Type} vec0 The source vector.
    - * @param {goog.vec.vec2d.Type|number} limit The limit vector or scalar.
    - * @param {goog.vec.vec2d.Type} resultVec The vector to receive the
    - *     results (may be vec0 or limit).
    - * @return {!goog.vec.vec2d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2d.max = function(vec0, limit, resultVec) {
    -  if (goog.isNumber(limit)) {
    -    resultVec[0] = Math.max(vec0[0], limit);
    -    resultVec[1] = Math.max(vec0[1], limit);
    -  } else {
    -    resultVec[0] = Math.max(vec0[0], limit[0]);
    -    resultVec[1] = Math.max(vec0[1], limit[1]);
    -  }
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Compares the components of vec0 with the components of another vector or
    - * scalar, storing the smaller values in resultVec.
    - *
    - * @param {goog.vec.vec2d.Type} vec0 The source vector.
    - * @param {goog.vec.vec2d.Type|number} limit The limit vector or scalar.
    - * @param {goog.vec.vec2d.Type} resultVec The vector to receive the
    - *     results (may be vec0 or limit).
    - * @return {!goog.vec.vec2d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2d.min = function(vec0, limit, resultVec) {
    -  if (goog.isNumber(limit)) {
    -    resultVec[0] = Math.min(vec0[0], limit);
    -    resultVec[1] = Math.min(vec0[1], limit);
    -  } else {
    -    resultVec[0] = Math.min(vec0[0], limit[0]);
    -    resultVec[1] = Math.min(vec0[1], limit[1]);
    -  }
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns true if the components of vec0 are equal to the components of vec1.
    - *
    - * @param {goog.vec.vec2d.Type} vec0 The first vector.
    - * @param {goog.vec.vec2d.Type} vec1 The second vector.
    - * @return {boolean} True if the vectors are equal, false otherwise.
    - */
    -goog.vec.vec2d.equals = function(vec0, vec1) {
    -  return vec0.length == vec1.length &&
    -      vec0[0] == vec1[0] && vec0[1] == vec1[1];
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/vec2d_test.html b/src/database/third_party/closure-library/closure/goog/vec/vec2d_test.html
    deleted file mode 100644
    index af74c8bbec7..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/vec2d_test.html
    +++ /dev/null
    @@ -1,282 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -//                                                                           //
    -// Any edits to this file must be applied to vec2f_test.html by running:     //
    -//   swap_type.sh vec2d_test.html > vec2f_test.html                          //
    -//                                                                           //
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.vec.vec2d</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.vec.Float64Array');
    -  goog.require('goog.vec.vec2d');
    -  goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -  function testCreate() {
    -    var v = goog.vec.vec2d.create();
    -    assertElementsEquals([0, 0], v);
    -  }
    -
    -  function testSet() {
    -    var v = goog.vec.vec2d.create();
    -    goog.vec.vec2d.setFromValues(v, 1, 2);
    -    assertElementsEquals([1, 2], v);
    -
    -    goog.vec.vec2d.setFromArray(v, [4, 5]);
    -    assertElementsEquals([4, 5], v);
    -
    -    var w = goog.vec.vec2d.create();
    -    goog.vec.vec2d.setFromValues(w, 1, 2);
    -    assertElementsEquals([1, 2], w);
    -
    -    goog.vec.vec2d.setFromArray(w, [4, 5]);
    -    assertElementsEquals([4, 5], w);
    -  }
    -
    -  function testAdd() {
    -    var v0 = goog.vec.vec2d.setFromArray(goog.vec.vec2d.create(), [1, 2]);
    -    var v1 = goog.vec.vec2d.setFromArray(goog.vec.vec2d.create(), [4, 5]);
    -    var v2 = goog.vec.vec2d.setFromVec2d(goog.vec.vec2d.create(), v0);
    -
    -    goog.vec.vec2d.add(v2, v1, v2);
    -    assertElementsEquals([1, 2], v0);
    -    assertElementsEquals([4, 5], v1);
    -    assertElementsEquals([5, 7], v2);
    -
    -    goog.vec.vec2d.add(goog.vec.vec2d.add(v0, v1, v2), v0, v2);
    -    assertElementsEquals([6, 9], v2);
    -  }
    -
    -  function testSubtract() {
    -    var v0 = goog.vec.vec2d.setFromArray(goog.vec.vec2d.create(), [1, 2]);
    -    var v1 = goog.vec.vec2d.setFromArray(goog.vec.vec2d.create(), [4, 5]);
    -    var v2 = goog.vec.vec2d.setFromVec2d(goog.vec.vec2d.create(), v0);
    -
    -    goog.vec.vec2d.subtract(v2, v1, v2);
    -    assertElementsEquals([1, 2], v0);
    -    assertElementsEquals([4, 5], v1);
    -    assertElementsEquals([-3, -3], v2);
    -
    -    goog.vec.vec2d.setFromValues(v2, 0, 0);
    -    goog.vec.vec2d.subtract(v1, v0, v2);
    -    assertElementsEquals([3, 3], v2);
    -
    -    v2 = goog.vec.vec2d.setFromVec2d(goog.vec.vec2d.create(), v0);
    -    goog.vec.vec2d.subtract(v2, v1, v2);
    -    assertElementsEquals([-3, -3], v2);
    -
    -    goog.vec.vec2d.subtract(goog.vec.vec2d.subtract(v1, v0, v2), v0, v2);
    -    assertElementsEquals([2, 1], v2);
    -  }
    -
    -  function testMultiply() {
    -    var v0 = goog.vec.vec2d.setFromArray(goog.vec.vec2d.create(), [1, 2]);
    -    var v1 = goog.vec.vec2d.setFromArray(goog.vec.vec2d.create(), [4, 5]);
    -    var v2 = goog.vec.vec2d.setFromVec2d(goog.vec.vec2d.create(), v0);
    -
    -    goog.vec.vec2d.componentMultiply(v2, v1, v2);
    -    assertElementsEquals([1, 2], v0);
    -    assertElementsEquals([4, 5], v1);
    -    assertElementsEquals([4, 10], v2);
    -
    -    goog.vec.vec2d.componentMultiply(goog.vec.vec2d.componentMultiply(v0, v1, v2), v0, v2);
    -    assertElementsEquals([4, 20], v2);
    -  }
    -
    -  function testDivide() {
    -    var v0 = goog.vec.vec2d.setFromArray(goog.vec.vec2d.create(), [1, 2]);
    -    var v1 = goog.vec.vec2d.setFromArray(goog.vec.vec2d.create(), [4, 5]);
    -    var v2 = goog.vec.vec2d.setFromVec2d(goog.vec.vec2d.create(), v0);
    -
    -    goog.vec.vec2d.componentDivide(v2, v1, v2);
    -    assertElementsRoughlyEqual([1, 2], v0, 10e-5);
    -    assertElementsRoughlyEqual([4, 5], v1, 10e-5);
    -    assertElementsRoughlyEqual([.25, .4], v2, 10e-5);
    -
    -    goog.vec.vec2d.setFromValues(v2, 0, 0);
    -    goog.vec.vec2d.componentDivide(v1, v0, v2);
    -    assertElementsRoughlyEqual([4, 2.5], v2, 10e-5);
    -
    -    v2 = goog.vec.vec2d.setFromVec2d(goog.vec.vec2d.create(), v0);
    -    goog.vec.vec2d.componentDivide(v2, v1, v2);
    -    assertElementsRoughlyEqual([.25, .4], v2, 10e-5);
    -
    -    goog.vec.vec2d.componentDivide(goog.vec.vec2d.componentDivide(v1, v0, v2), v0, v2);
    -    assertElementsRoughlyEqual([4, 1.25], v2, 10e-5);
    -  }
    -
    -  function testNegate() {
    -    var v0 = goog.vec.vec2d.setFromArray(goog.vec.vec2d.create(), [1, 2]);
    -    var v1 = goog.vec.vec2d.create();
    -
    -    goog.vec.vec2d.negate(v0, v1);
    -    assertElementsEquals([-1, -2], v1);
    -    assertElementsEquals([1, 2], v0);
    -
    -    goog.vec.vec2d.negate(v0, v0);
    -    assertElementsEquals([-1, -2], v0);
    -  }
    -
    -  function testAbs() {
    -    var v0 = goog.vec.vec2d.setFromArray(goog.vec.vec2d.create(), [-1, -2]);
    -    var v1 = goog.vec.vec2d.create();
    -
    -    goog.vec.vec2d.abs(v0, v1);
    -    assertElementsEquals([1, 2], v1);
    -    assertElementsEquals([-1, -2], v0);
    -
    -    goog.vec.vec2d.abs(v0, v0);
    -    assertElementsEquals([1, 2], v0);
    -  }
    -
    -  function testScale() {
    -    var v0 = goog.vec.vec2d.setFromArray(goog.vec.vec2d.create(), [1, 2]);
    -    var v1 = goog.vec.vec2d.create();
    -
    -    goog.vec.vec2d.scale(v0, 4, v1);
    -    assertElementsEquals([4, 8], v1);
    -    assertElementsEquals([1, 2], v0);
    -
    -    goog.vec.vec2d.setFromArray(v1, v0);
    -    goog.vec.vec2d.scale(v1, 5, v1);
    -    assertElementsEquals([5, 10], v1);
    -  }
    -
    -  function testMagnitudeSquared() {
    -    var v0 = goog.vec.vec2d.setFromArray(goog.vec.vec2d.create(), [1, 2]);
    -    assertEquals(5, goog.vec.vec2d.magnitudeSquared(v0));
    -  }
    -
    -  function testMagnitude() {
    -    var v0 = goog.vec.vec2d.setFromArray(goog.vec.vec2d.create(), [1, 2]);
    -    assertEquals(Math.sqrt(5), goog.vec.vec2d.magnitude(v0));
    -  }
    -
    -  function testNormalize() {
    -    var v0 = goog.vec.vec2d.setFromArray(goog.vec.vec2d.create(), [2, 3]);
    -    var v1 = goog.vec.vec2d.create();
    -    var v2 = goog.vec.vec2d.create();
    -    goog.vec.vec2d.scale(
    -        v0, 1 / goog.vec.vec2d.magnitude(v0), v2);
    -
    -    goog.vec.vec2d.normalize(v0, v1);
    -    assertElementsEquals(v2, v1);
    -    assertElementsEquals([2, 3], v0);
    -
    -    goog.vec.vec2d.setFromArray(v1, v0);
    -    goog.vec.vec2d.normalize(v1, v1);
    -    assertElementsEquals(v2, v1);
    -  }
    -
    -  function testDot() {
    -    var v0 = goog.vec.vec2d.setFromArray(goog.vec.vec2d.create(), [1, 2]);
    -    var v1 = goog.vec.vec2d.setFromArray(goog.vec.vec2d.create(), [4, 5]);
    -    assertEquals(14, goog.vec.vec2d.dot(v0, v1));
    -    assertEquals(14, goog.vec.vec2d.dot(v1, v0));
    -  }
    -
    -  function testDistanceSquared() {
    -    var v0 = goog.vec.vec2d.setFromValues(goog.vec.vec2d.create(), 1, 2);
    -    var v1 = goog.vec.vec2d.setFromValues(goog.vec.vec2d.create(), 1, 2);
    -    assertEquals(0, goog.vec.vec2d.distanceSquared(v0, v1));
    -    goog.vec.vec2d.setFromValues(v0, 1, 2);
    -    goog.vec.vec2d.setFromValues(v1, -1, -2);
    -    assertEquals(20, goog.vec.vec2d.distanceSquared(v0, v1));
    -  }
    -
    -  function testDistance() {
    -    var v0 = goog.vec.vec2d.setFromValues(goog.vec.vec2d.create(), 1, 2);
    -    var v1 = goog.vec.vec2d.setFromValues(goog.vec.vec2d.create(), 1, 2);
    -    assertEquals(0, goog.vec.vec2d.distance(v0, v1));
    -    goog.vec.vec2d.setFromValues(v0, 2, 3);
    -    goog.vec.vec2d.setFromValues(v1, -2, 0);
    -    assertEquals(5, goog.vec.vec2d.distance(v0, v1));
    -  }
    -
    -  function testDirection() {
    -    var v0 = goog.vec.vec2d.setFromValues(goog.vec.vec2d.create(), 1, 2);
    -    var v1 = goog.vec.vec2d.setFromValues(goog.vec.vec2d.create(), 1, 2);
    -    var dirVec = goog.vec.vec2d.setFromValues(goog.vec.vec2d.create(), 4, 5);
    -    goog.vec.vec2d.direction(v0, v1, dirVec);
    -    assertElementsEquals([0, 0], dirVec);
    -    goog.vec.vec2d.setFromValues(v0, 0, 0);
    -    goog.vec.vec2d.setFromValues(v1, 1, 0);
    -    goog.vec.vec2d.direction(v0, v1, dirVec);
    -    assertElementsEquals([1, 0], dirVec);
    -    goog.vec.vec2d.setFromValues(v0, 1, 1);
    -    goog.vec.vec2d.setFromValues(v1, 0, 0);
    -    goog.vec.vec2d.direction(v0, v1, dirVec);
    -    assertElementsRoughlyEqual(
    -        [-0.707106781, -0.707106781],
    -        dirVec, goog.vec.EPSILON);
    -  }
    -
    -  function testLerp() {
    -    var v0 = goog.vec.vec2d.setFromValues(goog.vec.vec2d.create(), 1, 2);
    -    var v1 = goog.vec.vec2d.setFromValues(goog.vec.vec2d.create(), 10, 20);
    -    var v2 = goog.vec.vec2d.setFromVec2d(goog.vec.vec2d.create(), v0);
    -
    -    goog.vec.vec2d.lerp(v2, v1, 0, v2);
    -    assertElementsEquals([1, 2], v2);
    -    goog.vec.vec2d.lerp(v2, v1, 1, v2);
    -    assertElementsEquals([10, 20], v2);
    -    goog.vec.vec2d.lerp(v0, v1, .5, v2);
    -    assertElementsEquals([5.5, 11], v2);
    -  }
    -
    -  function testMax() {
    -    var v0 = goog.vec.vec2d.setFromValues(goog.vec.vec2d.create(), 10, 20);
    -    var v1 = goog.vec.vec2d.setFromValues(goog.vec.vec2d.create(), 5, 25);
    -    var v2 = goog.vec.vec2d.create();
    -
    -    goog.vec.vec2d.max(v0, v1, v2);
    -    assertElementsEquals([10, 25], v2);
    -    goog.vec.vec2d.max(v1, v0, v1);
    -    assertElementsEquals([10, 25], v1);
    -    goog.vec.vec2d.max(v2, 20, v2);
    -    assertElementsEquals([20, 25], v2);
    -  }
    -
    -  function testMin() {
    -    var v0 = goog.vec.vec2d.setFromValues(goog.vec.vec2d.create(), 10, 20);
    -    var v1 = goog.vec.vec2d.setFromValues(goog.vec.vec2d.create(), 5, 25);
    -    var v2 = goog.vec.vec2d.create();
    -
    -    goog.vec.vec2d.min(v0, v1, v2);
    -    assertElementsEquals([5, 20], v2);
    -    goog.vec.vec2d.min(v1, v0, v1);
    -    assertElementsEquals([5, 20], v1);
    -    goog.vec.vec2d.min(v2, 10, v2);
    -    assertElementsEquals([5, 10], v2);
    -  }
    -
    -  function testEquals() {
    -    var v0 = goog.vec.vec2d.setFromValues(goog.vec.vec2d.create(), 1, 2);
    -    var v1 = goog.vec.vec2d.setFromVec2d(goog.vec.vec2d.create(), v0);
    -    assertElementsEquals(v0, v1);
    -
    -    v1[0] = 4;
    -    assertFalse(goog.vec.vec2d.equals(v0, v1));
    -
    -    v1 = goog.vec.vec2d.setFromVec2d(goog.vec.vec2d.create(), v0);
    -    v1[1] = 4;
    -    assertFalse(goog.vec.vec2d.equals(v0, v1));
    -  }
    -
    -</script>
    -</body>
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/vec2f.js b/src/database/third_party/closure-library/closure/goog/vec/vec2f.js
    deleted file mode 100644
    index 8ec5643a70b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/vec2f.js
    +++ /dev/null
    @@ -1,424 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -//                                                                           //
    -// Any edits to this file must be applied to vec2d.js by running:            //
    -//   swap_type.sh vec2f.js > vec2d.js                                        //
    -//                                                                           //
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -
    -
    -/**
    - * @fileoverview Provides functions for operating on 2 element float (32bit)
    - * vectors.
    - *
    - * The last parameter will typically be the output object and an object
    - * can be both an input and output parameter to all methods except where
    - * noted.
    - *
    - * See the README for notes about the design and structure of the API
    - * (especially related to performance).
    - *
    - */
    -
    -goog.provide('goog.vec.vec2f');
    -goog.provide('goog.vec.vec2f.Type');
    -
    -/** @suppress {extraRequire} */
    -goog.require('goog.vec');
    -
    -
    -/** @typedef {goog.vec.Float32} */ goog.vec.vec2f.Type;
    -
    -
    -/**
    - * Creates a vec2f with all elements initialized to zero.
    - *
    - * @return {!goog.vec.vec2f.Type} The new vec2f.
    - */
    -goog.vec.vec2f.create = function() {
    -  return new Float32Array(2);
    -};
    -
    -
    -/**
    - * Initializes the vector with the given values.
    - *
    - * @param {goog.vec.vec2f.Type} vec The vector to receive the values.
    - * @param {number} v0 The value for element at index 0.
    - * @param {number} v1 The value for element at index 1.
    - * @return {!goog.vec.vec2f.Type} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2f.setFromValues = function(vec, v0, v1) {
    -  vec[0] = v0;
    -  vec[1] = v1;
    -  return vec;
    -};
    -
    -
    -/**
    - * Initializes vec2f vec from vec2f src.
    - *
    - * @param {goog.vec.vec2f.Type} vec The destination vector.
    - * @param {goog.vec.vec2f.Type} src The source vector.
    - * @return {!goog.vec.vec2f.Type} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2f.setFromVec2f = function(vec, src) {
    -  vec[0] = src[0];
    -  vec[1] = src[1];
    -  return vec;
    -};
    -
    -
    -/**
    - * Initializes vec2f vec from vec2d src (typed as a Float64Array to
    - * avoid circular goog.requires).
    - *
    - * @param {goog.vec.vec2f.Type} vec The destination vector.
    - * @param {Float64Array} src The source vector.
    - * @return {!goog.vec.vec2f.Type} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2f.setFromVec2d = function(vec, src) {
    -  vec[0] = src[0];
    -  vec[1] = src[1];
    -  return vec;
    -};
    -
    -
    -/**
    - * Initializes vec2f vec from Array src.
    - *
    - * @param {goog.vec.vec2f.Type} vec The destination vector.
    - * @param {Array<number>} src The source vector.
    - * @return {!goog.vec.vec2f.Type} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2f.setFromArray = function(vec, src) {
    -  vec[0] = src[0];
    -  vec[1] = src[1];
    -  return vec;
    -};
    -
    -
    -/**
    - * Performs a component-wise addition of vec0 and vec1 together storing the
    - * result into resultVec.
    - *
    - * @param {goog.vec.vec2f.Type} vec0 The first addend.
    - * @param {goog.vec.vec2f.Type} vec1 The second addend.
    - * @param {goog.vec.vec2f.Type} resultVec The vector to
    - *     receive the result. May be vec0 or vec1.
    - * @return {!goog.vec.vec2f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2f.add = function(vec0, vec1, resultVec) {
    -  resultVec[0] = vec0[0] + vec1[0];
    -  resultVec[1] = vec0[1] + vec1[1];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Performs a component-wise subtraction of vec1 from vec0 storing the
    - * result into resultVec.
    - *
    - * @param {goog.vec.vec2f.Type} vec0 The minuend.
    - * @param {goog.vec.vec2f.Type} vec1 The subtrahend.
    - * @param {goog.vec.vec2f.Type} resultVec The vector to
    - *     receive the result. May be vec0 or vec1.
    - * @return {!goog.vec.vec2f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2f.subtract = function(vec0, vec1, resultVec) {
    -  resultVec[0] = vec0[0] - vec1[0];
    -  resultVec[1] = vec0[1] - vec1[1];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Multiplies each component of vec0 with the matching element of vec0
    - * storing the products into resultVec.
    - *
    - * @param {!goog.vec.vec2f.Type} vec0 The first vector.
    - * @param {!goog.vec.vec2f.Type} vec1 The second vector.
    - * @param {!goog.vec.vec2f.Type} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.vec2f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2f.componentMultiply = function(vec0, vec1, resultVec) {
    -  resultVec[0] = vec0[0] * vec1[0];
    -  resultVec[1] = vec0[1] * vec1[1];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Divides each component of vec0 with the matching element of vec0
    - * storing the divisor into resultVec.
    - *
    - * @param {!goog.vec.vec2f.Type} vec0 The first vector.
    - * @param {!goog.vec.vec2f.Type} vec1 The second vector.
    - * @param {!goog.vec.vec2f.Type} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.vec2f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2f.componentDivide = function(vec0, vec1, resultVec) {
    -  resultVec[0] = vec0[0] / vec1[0];
    -  resultVec[1] = vec0[1] / vec1[1];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Negates vec0, storing the result into resultVec.
    - *
    - * @param {goog.vec.vec2f.Type} vec0 The vector to negate.
    - * @param {goog.vec.vec2f.Type} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.vec2f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2f.negate = function(vec0, resultVec) {
    -  resultVec[0] = -vec0[0];
    -  resultVec[1] = -vec0[1];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Takes the absolute value of each component of vec0 storing the result in
    - * resultVec.
    - *
    - * @param {goog.vec.vec2f.Type} vec0 The source vector.
    - * @param {goog.vec.vec2f.Type} resultVec The vector to receive the result.
    - *     May be vec0.
    - * @return {!goog.vec.vec2f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2f.abs = function(vec0, resultVec) {
    -  resultVec[0] = Math.abs(vec0[0]);
    -  resultVec[1] = Math.abs(vec0[1]);
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Multiplies each component of vec0 with scalar storing the product into
    - * resultVec.
    - *
    - * @param {goog.vec.vec2f.Type} vec0 The source vector.
    - * @param {number} scalar The value to multiply with each component of vec0.
    - * @param {goog.vec.vec2f.Type} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.vec2f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2f.scale = function(vec0, scalar, resultVec) {
    -  resultVec[0] = vec0[0] * scalar;
    -  resultVec[1] = vec0[1] * scalar;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns the magnitudeSquared of the given vector.
    - *
    - * @param {goog.vec.vec2f.Type} vec0 The vector.
    - * @return {number} The magnitude of the vector.
    - */
    -goog.vec.vec2f.magnitudeSquared = function(vec0) {
    -  var x = vec0[0], y = vec0[1];
    -  return x * x + y * y;
    -};
    -
    -
    -/**
    - * Returns the magnitude of the given vector.
    - *
    - * @param {goog.vec.vec2f.Type} vec0 The vector.
    - * @return {number} The magnitude of the vector.
    - */
    -goog.vec.vec2f.magnitude = function(vec0) {
    -  var x = vec0[0], y = vec0[1];
    -  return Math.sqrt(x * x + y * y);
    -};
    -
    -
    -/**
    - * Normalizes the given vector storing the result into resultVec.
    - *
    - * @param {goog.vec.vec2f.Type} vec0 The vector to normalize.
    - * @param {goog.vec.vec2f.Type} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.vec2f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2f.normalize = function(vec0, resultVec) {
    -  var x = vec0[0], y = vec0[1];
    -  var ilen = 1 / Math.sqrt(x * x + y * y);
    -  resultVec[0] = x * ilen;
    -  resultVec[1] = y * ilen;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns the scalar product of vectors vec0 and vec1.
    - *
    - * @param {goog.vec.vec2f.Type} vec0 The first vector.
    - * @param {goog.vec.vec2f.Type} vec1 The second vector.
    - * @return {number} The scalar product.
    - */
    -goog.vec.vec2f.dot = function(vec0, vec1) {
    -  return vec0[0] * vec1[0] + vec0[1] * vec1[1];
    -};
    -
    -
    -/**
    - * Returns the squared distance between two points.
    - *
    - * @param {goog.vec.vec2f.Type} vec0 First point.
    - * @param {goog.vec.vec2f.Type} vec1 Second point.
    - * @return {number} The squared distance between the points.
    - */
    -goog.vec.vec2f.distanceSquared = function(vec0, vec1) {
    -  var x = vec0[0] - vec1[0];
    -  var y = vec0[1] - vec1[1];
    -  return x * x + y * y;
    -};
    -
    -
    -/**
    - * Returns the distance between two points.
    - *
    - * @param {goog.vec.vec2f.Type} vec0 First point.
    - * @param {goog.vec.vec2f.Type} vec1 Second point.
    - * @return {number} The distance between the points.
    - */
    -goog.vec.vec2f.distance = function(vec0, vec1) {
    -  return Math.sqrt(goog.vec.vec2f.distanceSquared(vec0, vec1));
    -};
    -
    -
    -/**
    - * Returns a unit vector pointing from one point to another.
    - * If the input points are equal then the result will be all zeros.
    - *
    - * @param {goog.vec.vec2f.Type} vec0 Origin point.
    - * @param {goog.vec.vec2f.Type} vec1 Target point.
    - * @param {goog.vec.vec2f.Type} resultVec The vector to receive the
    - *     results (may be vec0 or vec1).
    - * @return {!goog.vec.vec2f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2f.direction = function(vec0, vec1, resultVec) {
    -  var x = vec1[0] - vec0[0];
    -  var y = vec1[1] - vec0[1];
    -  var d = Math.sqrt(x * x + y * y);
    -  if (d) {
    -    d = 1 / d;
    -    resultVec[0] = x * d;
    -    resultVec[1] = y * d;
    -  } else {
    -    resultVec[0] = resultVec[1] = 0;
    -  }
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Linearly interpolate from vec0 to vec1 according to f. The value of f should
    - * be in the range [0..1] otherwise the results are undefined.
    - *
    - * @param {goog.vec.vec2f.Type} vec0 The first vector.
    - * @param {goog.vec.vec2f.Type} vec1 The second vector.
    - * @param {number} f The interpolation factor.
    - * @param {goog.vec.vec2f.Type} resultVec The vector to receive the
    - *     results (may be vec0 or vec1).
    - * @return {!goog.vec.vec2f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2f.lerp = function(vec0, vec1, f, resultVec) {
    -  var x = vec0[0], y = vec0[1];
    -  resultVec[0] = (vec1[0] - x) * f + x;
    -  resultVec[1] = (vec1[1] - y) * f + y;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Compares the components of vec0 with the components of another vector or
    - * scalar, storing the larger values in resultVec.
    - *
    - * @param {goog.vec.vec2f.Type} vec0 The source vector.
    - * @param {goog.vec.vec2f.Type|number} limit The limit vector or scalar.
    - * @param {goog.vec.vec2f.Type} resultVec The vector to receive the
    - *     results (may be vec0 or limit).
    - * @return {!goog.vec.vec2f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2f.max = function(vec0, limit, resultVec) {
    -  if (goog.isNumber(limit)) {
    -    resultVec[0] = Math.max(vec0[0], limit);
    -    resultVec[1] = Math.max(vec0[1], limit);
    -  } else {
    -    resultVec[0] = Math.max(vec0[0], limit[0]);
    -    resultVec[1] = Math.max(vec0[1], limit[1]);
    -  }
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Compares the components of vec0 with the components of another vector or
    - * scalar, storing the smaller values in resultVec.
    - *
    - * @param {goog.vec.vec2f.Type} vec0 The source vector.
    - * @param {goog.vec.vec2f.Type|number} limit The limit vector or scalar.
    - * @param {goog.vec.vec2f.Type} resultVec The vector to receive the
    - *     results (may be vec0 or limit).
    - * @return {!goog.vec.vec2f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec2f.min = function(vec0, limit, resultVec) {
    -  if (goog.isNumber(limit)) {
    -    resultVec[0] = Math.min(vec0[0], limit);
    -    resultVec[1] = Math.min(vec0[1], limit);
    -  } else {
    -    resultVec[0] = Math.min(vec0[0], limit[0]);
    -    resultVec[1] = Math.min(vec0[1], limit[1]);
    -  }
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns true if the components of vec0 are equal to the components of vec1.
    - *
    - * @param {goog.vec.vec2f.Type} vec0 The first vector.
    - * @param {goog.vec.vec2f.Type} vec1 The second vector.
    - * @return {boolean} True if the vectors are equal, false otherwise.
    - */
    -goog.vec.vec2f.equals = function(vec0, vec1) {
    -  return vec0.length == vec1.length &&
    -      vec0[0] == vec1[0] && vec0[1] == vec1[1];
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/vec2f_test.html b/src/database/third_party/closure-library/closure/goog/vec/vec2f_test.html
    deleted file mode 100644
    index ec6940dc398..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/vec2f_test.html
    +++ /dev/null
    @@ -1,282 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -//                                                                           //
    -// Any edits to this file must be applied to vec2d_test.html by running:     //
    -//   swap_type.sh vec2f_test.html > vec2d_test.html                          //
    -//                                                                           //
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.vec.vec2f</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.vec.Float32Array');
    -  goog.require('goog.vec.vec2f');
    -  goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -  function testCreate() {
    -    var v = goog.vec.vec2f.create();
    -    assertElementsEquals([0, 0], v);
    -  }
    -
    -  function testSet() {
    -    var v = goog.vec.vec2f.create();
    -    goog.vec.vec2f.setFromValues(v, 1, 2);
    -    assertElementsEquals([1, 2], v);
    -
    -    goog.vec.vec2f.setFromArray(v, [4, 5]);
    -    assertElementsEquals([4, 5], v);
    -
    -    var w = goog.vec.vec2f.create();
    -    goog.vec.vec2f.setFromValues(w, 1, 2);
    -    assertElementsEquals([1, 2], w);
    -
    -    goog.vec.vec2f.setFromArray(w, [4, 5]);
    -    assertElementsEquals([4, 5], w);
    -  }
    -
    -  function testAdd() {
    -    var v0 = goog.vec.vec2f.setFromArray(goog.vec.vec2f.create(), [1, 2]);
    -    var v1 = goog.vec.vec2f.setFromArray(goog.vec.vec2f.create(), [4, 5]);
    -    var v2 = goog.vec.vec2f.setFromVec2f(goog.vec.vec2f.create(), v0);
    -
    -    goog.vec.vec2f.add(v2, v1, v2);
    -    assertElementsEquals([1, 2], v0);
    -    assertElementsEquals([4, 5], v1);
    -    assertElementsEquals([5, 7], v2);
    -
    -    goog.vec.vec2f.add(goog.vec.vec2f.add(v0, v1, v2), v0, v2);
    -    assertElementsEquals([6, 9], v2);
    -  }
    -
    -  function testSubtract() {
    -    var v0 = goog.vec.vec2f.setFromArray(goog.vec.vec2f.create(), [1, 2]);
    -    var v1 = goog.vec.vec2f.setFromArray(goog.vec.vec2f.create(), [4, 5]);
    -    var v2 = goog.vec.vec2f.setFromVec2f(goog.vec.vec2f.create(), v0);
    -
    -    goog.vec.vec2f.subtract(v2, v1, v2);
    -    assertElementsEquals([1, 2], v0);
    -    assertElementsEquals([4, 5], v1);
    -    assertElementsEquals([-3, -3], v2);
    -
    -    goog.vec.vec2f.setFromValues(v2, 0, 0);
    -    goog.vec.vec2f.subtract(v1, v0, v2);
    -    assertElementsEquals([3, 3], v2);
    -
    -    v2 = goog.vec.vec2f.setFromVec2f(goog.vec.vec2f.create(), v0);
    -    goog.vec.vec2f.subtract(v2, v1, v2);
    -    assertElementsEquals([-3, -3], v2);
    -
    -    goog.vec.vec2f.subtract(goog.vec.vec2f.subtract(v1, v0, v2), v0, v2);
    -    assertElementsEquals([2, 1], v2);
    -  }
    -
    -  function testMultiply() {
    -    var v0 = goog.vec.vec2f.setFromArray(goog.vec.vec2f.create(), [1, 2]);
    -    var v1 = goog.vec.vec2f.setFromArray(goog.vec.vec2f.create(), [4, 5]);
    -    var v2 = goog.vec.vec2f.setFromVec2f(goog.vec.vec2f.create(), v0);
    -
    -    goog.vec.vec2f.componentMultiply(v2, v1, v2);
    -    assertElementsEquals([1, 2], v0);
    -    assertElementsEquals([4, 5], v1);
    -    assertElementsEquals([4, 10], v2);
    -
    -    goog.vec.vec2f.componentMultiply(goog.vec.vec2f.componentMultiply(v0, v1, v2), v0, v2);
    -    assertElementsEquals([4, 20], v2);
    -  }
    -
    -  function testDivide() {
    -    var v0 = goog.vec.vec2f.setFromArray(goog.vec.vec2f.create(), [1, 2]);
    -    var v1 = goog.vec.vec2f.setFromArray(goog.vec.vec2f.create(), [4, 5]);
    -    var v2 = goog.vec.vec2f.setFromVec2f(goog.vec.vec2f.create(), v0);
    -
    -    goog.vec.vec2f.componentDivide(v2, v1, v2);
    -    assertElementsRoughlyEqual([1, 2], v0, 10e-5);
    -    assertElementsRoughlyEqual([4, 5], v1, 10e-5);
    -    assertElementsRoughlyEqual([.25, .4], v2, 10e-5);
    -
    -    goog.vec.vec2f.setFromValues(v2, 0, 0);
    -    goog.vec.vec2f.componentDivide(v1, v0, v2);
    -    assertElementsRoughlyEqual([4, 2.5], v2, 10e-5);
    -
    -    v2 = goog.vec.vec2f.setFromVec2f(goog.vec.vec2f.create(), v0);
    -    goog.vec.vec2f.componentDivide(v2, v1, v2);
    -    assertElementsRoughlyEqual([.25, .4], v2, 10e-5);
    -
    -    goog.vec.vec2f.componentDivide(goog.vec.vec2f.componentDivide(v1, v0, v2), v0, v2);
    -    assertElementsRoughlyEqual([4, 1.25], v2, 10e-5);
    -  }
    -
    -  function testNegate() {
    -    var v0 = goog.vec.vec2f.setFromArray(goog.vec.vec2f.create(), [1, 2]);
    -    var v1 = goog.vec.vec2f.create();
    -
    -    goog.vec.vec2f.negate(v0, v1);
    -    assertElementsEquals([-1, -2], v1);
    -    assertElementsEquals([1, 2], v0);
    -
    -    goog.vec.vec2f.negate(v0, v0);
    -    assertElementsEquals([-1, -2], v0);
    -  }
    -
    -  function testAbs() {
    -    var v0 = goog.vec.vec2f.setFromArray(goog.vec.vec2f.create(), [-1, -2]);
    -    var v1 = goog.vec.vec2f.create();
    -
    -    goog.vec.vec2f.abs(v0, v1);
    -    assertElementsEquals([1, 2], v1);
    -    assertElementsEquals([-1, -2], v0);
    -
    -    goog.vec.vec2f.abs(v0, v0);
    -    assertElementsEquals([1, 2], v0);
    -  }
    -
    -  function testScale() {
    -    var v0 = goog.vec.vec2f.setFromArray(goog.vec.vec2f.create(), [1, 2]);
    -    var v1 = goog.vec.vec2f.create();
    -
    -    goog.vec.vec2f.scale(v0, 4, v1);
    -    assertElementsEquals([4, 8], v1);
    -    assertElementsEquals([1, 2], v0);
    -
    -    goog.vec.vec2f.setFromArray(v1, v0);
    -    goog.vec.vec2f.scale(v1, 5, v1);
    -    assertElementsEquals([5, 10], v1);
    -  }
    -
    -  function testMagnitudeSquared() {
    -    var v0 = goog.vec.vec2f.setFromArray(goog.vec.vec2f.create(), [1, 2]);
    -    assertEquals(5, goog.vec.vec2f.magnitudeSquared(v0));
    -  }
    -
    -  function testMagnitude() {
    -    var v0 = goog.vec.vec2f.setFromArray(goog.vec.vec2f.create(), [1, 2]);
    -    assertEquals(Math.sqrt(5), goog.vec.vec2f.magnitude(v0));
    -  }
    -
    -  function testNormalize() {
    -    var v0 = goog.vec.vec2f.setFromArray(goog.vec.vec2f.create(), [2, 3]);
    -    var v1 = goog.vec.vec2f.create();
    -    var v2 = goog.vec.vec2f.create();
    -    goog.vec.vec2f.scale(
    -        v0, 1 / goog.vec.vec2f.magnitude(v0), v2);
    -
    -    goog.vec.vec2f.normalize(v0, v1);
    -    assertElementsEquals(v2, v1);
    -    assertElementsEquals([2, 3], v0);
    -
    -    goog.vec.vec2f.setFromArray(v1, v0);
    -    goog.vec.vec2f.normalize(v1, v1);
    -    assertElementsEquals(v2, v1);
    -  }
    -
    -  function testDot() {
    -    var v0 = goog.vec.vec2f.setFromArray(goog.vec.vec2f.create(), [1, 2]);
    -    var v1 = goog.vec.vec2f.setFromArray(goog.vec.vec2f.create(), [4, 5]);
    -    assertEquals(14, goog.vec.vec2f.dot(v0, v1));
    -    assertEquals(14, goog.vec.vec2f.dot(v1, v0));
    -  }
    -
    -  function testDistanceSquared() {
    -    var v0 = goog.vec.vec2f.setFromValues(goog.vec.vec2f.create(), 1, 2);
    -    var v1 = goog.vec.vec2f.setFromValues(goog.vec.vec2f.create(), 1, 2);
    -    assertEquals(0, goog.vec.vec2f.distanceSquared(v0, v1));
    -    goog.vec.vec2f.setFromValues(v0, 1, 2);
    -    goog.vec.vec2f.setFromValues(v1, -1, -2);
    -    assertEquals(20, goog.vec.vec2f.distanceSquared(v0, v1));
    -  }
    -
    -  function testDistance() {
    -    var v0 = goog.vec.vec2f.setFromValues(goog.vec.vec2f.create(), 1, 2);
    -    var v1 = goog.vec.vec2f.setFromValues(goog.vec.vec2f.create(), 1, 2);
    -    assertEquals(0, goog.vec.vec2f.distance(v0, v1));
    -    goog.vec.vec2f.setFromValues(v0, 2, 3);
    -    goog.vec.vec2f.setFromValues(v1, -2, 0);
    -    assertEquals(5, goog.vec.vec2f.distance(v0, v1));
    -  }
    -
    -  function testDirection() {
    -    var v0 = goog.vec.vec2f.setFromValues(goog.vec.vec2f.create(), 1, 2);
    -    var v1 = goog.vec.vec2f.setFromValues(goog.vec.vec2f.create(), 1, 2);
    -    var dirVec = goog.vec.vec2f.setFromValues(goog.vec.vec2f.create(), 4, 5);
    -    goog.vec.vec2f.direction(v0, v1, dirVec);
    -    assertElementsEquals([0, 0], dirVec);
    -    goog.vec.vec2f.setFromValues(v0, 0, 0);
    -    goog.vec.vec2f.setFromValues(v1, 1, 0);
    -    goog.vec.vec2f.direction(v0, v1, dirVec);
    -    assertElementsEquals([1, 0], dirVec);
    -    goog.vec.vec2f.setFromValues(v0, 1, 1);
    -    goog.vec.vec2f.setFromValues(v1, 0, 0);
    -    goog.vec.vec2f.direction(v0, v1, dirVec);
    -    assertElementsRoughlyEqual(
    -        [-0.707106781, -0.707106781],
    -        dirVec, goog.vec.EPSILON);
    -  }
    -
    -  function testLerp() {
    -    var v0 = goog.vec.vec2f.setFromValues(goog.vec.vec2f.create(), 1, 2);
    -    var v1 = goog.vec.vec2f.setFromValues(goog.vec.vec2f.create(), 10, 20);
    -    var v2 = goog.vec.vec2f.setFromVec2f(goog.vec.vec2f.create(), v0);
    -
    -    goog.vec.vec2f.lerp(v2, v1, 0, v2);
    -    assertElementsEquals([1, 2], v2);
    -    goog.vec.vec2f.lerp(v2, v1, 1, v2);
    -    assertElementsEquals([10, 20], v2);
    -    goog.vec.vec2f.lerp(v0, v1, .5, v2);
    -    assertElementsEquals([5.5, 11], v2);
    -  }
    -
    -  function testMax() {
    -    var v0 = goog.vec.vec2f.setFromValues(goog.vec.vec2f.create(), 10, 20);
    -    var v1 = goog.vec.vec2f.setFromValues(goog.vec.vec2f.create(), 5, 25);
    -    var v2 = goog.vec.vec2f.create();
    -
    -    goog.vec.vec2f.max(v0, v1, v2);
    -    assertElementsEquals([10, 25], v2);
    -    goog.vec.vec2f.max(v1, v0, v1);
    -    assertElementsEquals([10, 25], v1);
    -    goog.vec.vec2f.max(v2, 20, v2);
    -    assertElementsEquals([20, 25], v2);
    -  }
    -
    -  function testMin() {
    -    var v0 = goog.vec.vec2f.setFromValues(goog.vec.vec2f.create(), 10, 20);
    -    var v1 = goog.vec.vec2f.setFromValues(goog.vec.vec2f.create(), 5, 25);
    -    var v2 = goog.vec.vec2f.create();
    -
    -    goog.vec.vec2f.min(v0, v1, v2);
    -    assertElementsEquals([5, 20], v2);
    -    goog.vec.vec2f.min(v1, v0, v1);
    -    assertElementsEquals([5, 20], v1);
    -    goog.vec.vec2f.min(v2, 10, v2);
    -    assertElementsEquals([5, 10], v2);
    -  }
    -
    -  function testEquals() {
    -    var v0 = goog.vec.vec2f.setFromValues(goog.vec.vec2f.create(), 1, 2);
    -    var v1 = goog.vec.vec2f.setFromVec2f(goog.vec.vec2f.create(), v0);
    -    assertElementsEquals(v0, v1);
    -
    -    v1[0] = 4;
    -    assertFalse(goog.vec.vec2f.equals(v0, v1));
    -
    -    v1 = goog.vec.vec2f.setFromVec2f(goog.vec.vec2f.create(), v0);
    -    v1[1] = 4;
    -    assertFalse(goog.vec.vec2f.equals(v0, v1));
    -  }
    -
    -</script>
    -</body>
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/vec3.js b/src/database/third_party/closure-library/closure/goog/vec/vec3.js
    deleted file mode 100644
    index 4528887c484..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/vec3.js
    +++ /dev/null
    @@ -1,542 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Supplies 3 element vectors that are compatible with WebGL.
    - * Each element is a float32 since that is typically the desired size of a
    - * 3-vector in the GPU.  The API is structured to avoid unnecessary memory
    - * allocations.  The last parameter will typically be the output vector and
    - * an object can be both an input and output parameter to all methods except
    - * where noted.
    - *
    - */
    -goog.provide('goog.vec.Vec3');
    -
    -/** @suppress {extraRequire} */
    -goog.require('goog.vec');
    -
    -/** @typedef {goog.vec.Float32} */ goog.vec.Vec3.Float32;
    -/** @typedef {goog.vec.Float64} */ goog.vec.Vec3.Float64;
    -/** @typedef {goog.vec.Number} */ goog.vec.Vec3.Number;
    -/** @typedef {goog.vec.AnyType} */ goog.vec.Vec3.AnyType;
    -
    -// The following two types are deprecated - use the above types instead.
    -/** @typedef {Float32Array} */ goog.vec.Vec3.Type;
    -/** @typedef {goog.vec.ArrayType} */ goog.vec.Vec3.Vec3Like;
    -
    -
    -/**
    - * Creates a 3 element vector of Float32. The array is initialized to zero.
    - *
    - * @return {!goog.vec.Vec3.Float32} The new 3 element array.
    - */
    -goog.vec.Vec3.createFloat32 = function() {
    -  return new Float32Array(3);
    -};
    -
    -
    -/**
    - * Creates a 3 element vector of Float64. The array is initialized to zero.
    - *
    - * @return {!goog.vec.Vec3.Float64} The new 3 element array.
    - */
    -goog.vec.Vec3.createFloat64 = function() {
    -  return new Float64Array(3);
    -};
    -
    -
    -/**
    - * Creates a 3 element vector of Number. The array is initialized to zero.
    - *
    - * @return {!goog.vec.Vec3.Number} The new 3 element array.
    - */
    -goog.vec.Vec3.createNumber = function() {
    -  var a = new Array(3);
    -  goog.vec.Vec3.setFromValues(a, 0, 0, 0);
    -  return a;
    -};
    -
    -
    -/**
    - * Creates a 3 element vector of Float32Array. The array is initialized to zero.
    - *
    - * @deprecated Use createFloat32.
    - * @return {!goog.vec.Vec3.Type} The new 3 element array.
    - */
    -goog.vec.Vec3.create = function() {
    -  return new Float32Array(3);
    -};
    -
    -
    -/**
    - * Creates a new 3 element FLoat32 vector initialized with the value from the
    - * given array.
    - *
    - * @param {goog.vec.Vec3.AnyType} vec The source 3 element array.
    - * @return {!goog.vec.Vec3.Float32} The new 3 element array.
    - */
    -goog.vec.Vec3.createFloat32FromArray = function(vec) {
    -  var newVec = goog.vec.Vec3.createFloat32();
    -  goog.vec.Vec3.setFromArray(newVec, vec);
    -  return newVec;
    -};
    -
    -
    -/**
    - * Creates a new 3 element Float32 vector initialized with the supplied values.
    - *
    - * @param {number} v0 The value for element at index 0.
    - * @param {number} v1 The value for element at index 1.
    - * @param {number} v2 The value for element at index 2.
    - * @return {!goog.vec.Vec3.Float32} The new vector.
    - */
    -goog.vec.Vec3.createFloat32FromValues = function(v0, v1, v2) {
    -  var a = goog.vec.Vec3.createFloat32();
    -  goog.vec.Vec3.setFromValues(a, v0, v1, v2);
    -  return a;
    -};
    -
    -
    -/**
    - * Creates a clone of the given 3 element Float32 vector.
    - *
    - * @param {goog.vec.Vec3.Float32} vec The source 3 element vector.
    - * @return {!goog.vec.Vec3.Float32} The new cloned vector.
    - */
    -goog.vec.Vec3.cloneFloat32 = goog.vec.Vec3.createFloat32FromArray;
    -
    -
    -/**
    - * Creates a new 3 element Float64 vector initialized with the value from the
    - * given array.
    - *
    - * @param {goog.vec.Vec3.AnyType} vec The source 3 element array.
    - * @return {!goog.vec.Vec3.Float64} The new 3 element array.
    - */
    -goog.vec.Vec3.createFloat64FromArray = function(vec) {
    -  var newVec = goog.vec.Vec3.createFloat64();
    -  goog.vec.Vec3.setFromArray(newVec, vec);
    -  return newVec;
    -};
    -
    -
    -/**
    -* Creates a new 3 element Float64 vector initialized with the supplied values.
    -*
    -* @param {number} v0 The value for element at index 0.
    -* @param {number} v1 The value for element at index 1.
    -* @param {number} v2 The value for element at index 2.
    -* @return {!goog.vec.Vec3.Float64} The new vector.
    -*/
    -goog.vec.Vec3.createFloat64FromValues = function(v0, v1, v2) {
    -  var vec = goog.vec.Vec3.createFloat64();
    -  goog.vec.Vec3.setFromValues(vec, v0, v1, v2);
    -  return vec;
    -};
    -
    -
    -/**
    - * Creates a clone of the given 3 element vector.
    - *
    - * @param {goog.vec.Vec3.Float64} vec The source 3 element vector.
    - * @return {!goog.vec.Vec3.Float64} The new cloned vector.
    - */
    -goog.vec.Vec3.cloneFloat64 = goog.vec.Vec3.createFloat64FromArray;
    -
    -
    -/**
    - * Creates a new 3 element vector initialized with the value from the given
    - * array.
    - *
    - * @deprecated Use createFloat32FromArray.
    - * @param {goog.vec.Vec3.Vec3Like} vec The source 3 element array.
    - * @return {!goog.vec.Vec3.Type} The new 3 element array.
    - */
    -goog.vec.Vec3.createFromArray = function(vec) {
    -  var newVec = goog.vec.Vec3.create();
    -  goog.vec.Vec3.setFromArray(newVec, vec);
    -  return newVec;
    -};
    -
    -
    -/**
    - * Creates a new 3 element vector initialized with the supplied values.
    - *
    - * @deprecated Use createFloat32FromValues.
    - * @param {number} v0 The value for element at index 0.
    - * @param {number} v1 The value for element at index 1.
    - * @param {number} v2 The value for element at index 2.
    - * @return {!goog.vec.Vec3.Type} The new vector.
    - */
    -goog.vec.Vec3.createFromValues = function(v0, v1, v2) {
    -  var vec = goog.vec.Vec3.create();
    -  goog.vec.Vec3.setFromValues(vec, v0, v1, v2);
    -  return vec;
    -};
    -
    -
    -/**
    - * Creates a clone of the given 3 element vector.
    - *
    - * @deprecated Use cloneFloat32.
    - * @param {goog.vec.Vec3.Vec3Like} vec The source 3 element vector.
    - * @return {!goog.vec.Vec3.Type} The new cloned vector.
    - */
    -goog.vec.Vec3.clone = function(vec) {
    -  var newVec = goog.vec.Vec3.create();
    -  goog.vec.Vec3.setFromArray(newVec, vec);
    -  return newVec;
    -};
    -
    -
    -/**
    - * Initializes the vector with the given values.
    - *
    - * @param {goog.vec.Vec3.AnyType} vec The vector to receive the values.
    - * @param {number} v0 The value for element at index 0.
    - * @param {number} v1 The value for element at index 1.
    - * @param {number} v2 The value for element at index 2.
    - * @return {!goog.vec.Vec3.AnyType} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec3.setFromValues = function(vec, v0, v1, v2) {
    -  vec[0] = v0;
    -  vec[1] = v1;
    -  vec[2] = v2;
    -  return vec;
    -};
    -
    -
    -/**
    - * Initializes the vector with the given array of values.
    - *
    - * @param {goog.vec.Vec3.AnyType} vec The vector to receive the
    - *     values.
    - * @param {goog.vec.Vec3.AnyType} values The array of values.
    - * @return {!goog.vec.Vec3.AnyType} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec3.setFromArray = function(vec, values) {
    -  vec[0] = values[0];
    -  vec[1] = values[1];
    -  vec[2] = values[2];
    -  return vec;
    -};
    -
    -
    -/**
    - * Performs a component-wise addition of vec0 and vec1 together storing the
    - * result into resultVec.
    - *
    - * @param {goog.vec.Vec3.AnyType} vec0 The first addend.
    - * @param {goog.vec.Vec3.AnyType} vec1 The second addend.
    - * @param {goog.vec.Vec3.AnyType} resultVec The vector to
    - *     receive the result. May be vec0 or vec1.
    - * @return {!goog.vec.Vec3.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec3.add = function(vec0, vec1, resultVec) {
    -  resultVec[0] = vec0[0] + vec1[0];
    -  resultVec[1] = vec0[1] + vec1[1];
    -  resultVec[2] = vec0[2] + vec1[2];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Performs a component-wise subtraction of vec1 from vec0 storing the
    - * result into resultVec.
    - *
    - * @param {goog.vec.Vec3.AnyType} vec0 The minuend.
    - * @param {goog.vec.Vec3.AnyType} vec1 The subtrahend.
    - * @param {goog.vec.Vec3.AnyType} resultVec The vector to
    - *     receive the result. May be vec0 or vec1.
    - * @return {!goog.vec.Vec3.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec3.subtract = function(vec0, vec1, resultVec) {
    -  resultVec[0] = vec0[0] - vec1[0];
    -  resultVec[1] = vec0[1] - vec1[1];
    -  resultVec[2] = vec0[2] - vec1[2];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Negates vec0, storing the result into resultVec.
    - *
    - * @param {goog.vec.Vec3.AnyType} vec0 The vector to negate.
    - * @param {goog.vec.Vec3.AnyType} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.Vec3.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec3.negate = function(vec0, resultVec) {
    -  resultVec[0] = -vec0[0];
    -  resultVec[1] = -vec0[1];
    -  resultVec[2] = -vec0[2];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Takes the absolute value of each component of vec0 storing the result in
    - * resultVec.
    - *
    - * @param {goog.vec.Vec3.AnyType} vec0 The source vector.
    - * @param {goog.vec.Vec3.AnyType} resultVec The vector to receive the result.
    - *     May be vec0.
    - * @return {!goog.vec.Vec3.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec3.abs = function(vec0, resultVec) {
    -  resultVec[0] = Math.abs(vec0[0]);
    -  resultVec[1] = Math.abs(vec0[1]);
    -  resultVec[2] = Math.abs(vec0[2]);
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Multiplies each component of vec0 with scalar storing the product into
    - * resultVec.
    - *
    - * @param {goog.vec.Vec3.AnyType} vec0 The source vector.
    - * @param {number} scalar The value to multiply with each component of vec0.
    - * @param {goog.vec.Vec3.AnyType} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.Vec3.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec3.scale = function(vec0, scalar, resultVec) {
    -  resultVec[0] = vec0[0] * scalar;
    -  resultVec[1] = vec0[1] * scalar;
    -  resultVec[2] = vec0[2] * scalar;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns the magnitudeSquared of the given vector.
    - *
    - * @param {goog.vec.Vec3.AnyType} vec0 The vector.
    - * @return {number} The magnitude of the vector.
    - */
    -goog.vec.Vec3.magnitudeSquared = function(vec0) {
    -  var x = vec0[0], y = vec0[1], z = vec0[2];
    -  return x * x + y * y + z * z;
    -};
    -
    -
    -/**
    - * Returns the magnitude of the given vector.
    - *
    - * @param {goog.vec.Vec3.AnyType} vec0 The vector.
    - * @return {number} The magnitude of the vector.
    - */
    -goog.vec.Vec3.magnitude = function(vec0) {
    -  var x = vec0[0], y = vec0[1], z = vec0[2];
    -  return Math.sqrt(x * x + y * y + z * z);
    -};
    -
    -
    -/**
    - * Normalizes the given vector storing the result into resultVec.
    - *
    - * @param {goog.vec.Vec3.AnyType} vec0 The vector to normalize.
    - * @param {goog.vec.Vec3.AnyType} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.Vec3.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec3.normalize = function(vec0, resultVec) {
    -  var ilen = 1 / goog.vec.Vec3.magnitude(vec0);
    -  resultVec[0] = vec0[0] * ilen;
    -  resultVec[1] = vec0[1] * ilen;
    -  resultVec[2] = vec0[2] * ilen;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns the scalar product of vectors v0 and v1.
    - *
    - * @param {goog.vec.Vec3.AnyType} v0 The first vector.
    - * @param {goog.vec.Vec3.AnyType} v1 The second vector.
    - * @return {number} The scalar product.
    - */
    -goog.vec.Vec3.dot = function(v0, v1) {
    -  return v0[0] * v1[0] + v0[1] * v1[1] + v0[2] * v1[2];
    -};
    -
    -
    -/**
    - * Computes the vector (cross) product of v0 and v1 storing the result into
    - * resultVec.
    - *
    - * @param {goog.vec.Vec3.AnyType} v0 The first vector.
    - * @param {goog.vec.Vec3.AnyType} v1 The second vector.
    - * @param {goog.vec.Vec3.AnyType} resultVec The vector to receive the
    - *     results. May be either v0 or v1.
    - * @return {!goog.vec.Vec3.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec3.cross = function(v0, v1, resultVec) {
    -  var x0 = v0[0], y0 = v0[1], z0 = v0[2];
    -  var x1 = v1[0], y1 = v1[1], z1 = v1[2];
    -  resultVec[0] = y0 * z1 - z0 * y1;
    -  resultVec[1] = z0 * x1 - x0 * z1;
    -  resultVec[2] = x0 * y1 - y0 * x1;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns the squared distance between two points.
    - *
    - * @param {goog.vec.Vec3.AnyType} vec0 First point.
    - * @param {goog.vec.Vec3.AnyType} vec1 Second point.
    - * @return {number} The squared distance between the points.
    - */
    -goog.vec.Vec3.distanceSquared = function(vec0, vec1) {
    -  var x = vec0[0] - vec1[0];
    -  var y = vec0[1] - vec1[1];
    -  var z = vec0[2] - vec1[2];
    -  return x * x + y * y + z * z;
    -};
    -
    -
    -/**
    - * Returns the distance between two points.
    - *
    - * @param {goog.vec.Vec3.AnyType} vec0 First point.
    - * @param {goog.vec.Vec3.AnyType} vec1 Second point.
    - * @return {number} The distance between the points.
    - */
    -goog.vec.Vec3.distance = function(vec0, vec1) {
    -  return Math.sqrt(goog.vec.Vec3.distanceSquared(vec0, vec1));
    -};
    -
    -
    -/**
    - * Returns a unit vector pointing from one point to another.
    - * If the input points are equal then the result will be all zeros.
    - *
    - * @param {goog.vec.Vec3.AnyType} vec0 Origin point.
    - * @param {goog.vec.Vec3.AnyType} vec1 Target point.
    - * @param {goog.vec.Vec3.AnyType} resultVec The vector to receive the
    - *     results (may be vec0 or vec1).
    - * @return {!goog.vec.Vec3.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec3.direction = function(vec0, vec1, resultVec) {
    -  var x = vec1[0] - vec0[0];
    -  var y = vec1[1] - vec0[1];
    -  var z = vec1[2] - vec0[2];
    -  var d = Math.sqrt(x * x + y * y + z * z);
    -  if (d) {
    -    d = 1 / d;
    -    resultVec[0] = x * d;
    -    resultVec[1] = y * d;
    -    resultVec[2] = z * d;
    -  } else {
    -    resultVec[0] = resultVec[1] = resultVec[2] = 0;
    -  }
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Linearly interpolate from vec0 to v1 according to f. The value of f should be
    - * in the range [0..1] otherwise the results are undefined.
    - *
    - * @param {goog.vec.Vec3.AnyType} v0 The first vector.
    - * @param {goog.vec.Vec3.AnyType} v1 The second vector.
    - * @param {number} f The interpolation factor.
    - * @param {goog.vec.Vec3.AnyType} resultVec The vector to receive the
    - *     results (may be v0 or v1).
    - * @return {!goog.vec.Vec3.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec3.lerp = function(v0, v1, f, resultVec) {
    -  var x = v0[0], y = v0[1], z = v0[2];
    -  resultVec[0] = (v1[0] - x) * f + x;
    -  resultVec[1] = (v1[1] - y) * f + y;
    -  resultVec[2] = (v1[2] - z) * f + z;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Compares the components of vec0 with the components of another vector or
    - * scalar, storing the larger values in resultVec.
    - *
    - * @param {goog.vec.Vec3.AnyType} vec0 The source vector.
    - * @param {goog.vec.Vec3.AnyType|number} limit The limit vector or scalar.
    - * @param {goog.vec.Vec3.AnyType} resultVec The vector to receive the
    - *     results (may be vec0 or limit).
    - * @return {!goog.vec.Vec3.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec3.max = function(vec0, limit, resultVec) {
    -  if (goog.isNumber(limit)) {
    -    resultVec[0] = Math.max(vec0[0], limit);
    -    resultVec[1] = Math.max(vec0[1], limit);
    -    resultVec[2] = Math.max(vec0[2], limit);
    -  } else {
    -    resultVec[0] = Math.max(vec0[0], limit[0]);
    -    resultVec[1] = Math.max(vec0[1], limit[1]);
    -    resultVec[2] = Math.max(vec0[2], limit[2]);
    -  }
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Compares the components of vec0 with the components of another vector or
    - * scalar, storing the smaller values in resultVec.
    - *
    - * @param {goog.vec.Vec3.AnyType} vec0 The source vector.
    - * @param {goog.vec.Vec3.AnyType|number} limit The limit vector or scalar.
    - * @param {goog.vec.Vec3.AnyType} resultVec The vector to receive the
    - *     results (may be vec0 or limit).
    - * @return {!goog.vec.Vec3.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec3.min = function(vec0, limit, resultVec) {
    -  if (goog.isNumber(limit)) {
    -    resultVec[0] = Math.min(vec0[0], limit);
    -    resultVec[1] = Math.min(vec0[1], limit);
    -    resultVec[2] = Math.min(vec0[2], limit);
    -  } else {
    -    resultVec[0] = Math.min(vec0[0], limit[0]);
    -    resultVec[1] = Math.min(vec0[1], limit[1]);
    -    resultVec[2] = Math.min(vec0[2], limit[2]);
    -  }
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns true if the components of v0 are equal to the components of v1.
    - *
    - * @param {goog.vec.Vec3.AnyType} v0 The first vector.
    - * @param {goog.vec.Vec3.AnyType} v1 The second vector.
    - * @return {boolean} True if the vectors are equal, false otherwise.
    - */
    -goog.vec.Vec3.equals = function(v0, v1) {
    -  return v0.length == v1.length &&
    -      v0[0] == v1[0] && v0[1] == v1[1] && v0[2] == v1[2];
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/vec3_test.html b/src/database/third_party/closure-library/closure/goog/vec/vec3_test.html
    deleted file mode 100644
    index c2e26aaef97..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/vec3_test.html
    +++ /dev/null
    @@ -1,296 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.vec.Vec3</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.vec.Float32Array');
    -  goog.require('goog.vec.Vec3');
    -  goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -  function testDeprecatedConstructor() {
    -    var v = goog.vec.Vec3.create();
    -    assertElementsEquals(0, v[0]);
    -    assertEquals(0, v[1]);
    -    assertEquals(0, v[2]);
    -
    -    assertElementsEquals([0, 0, 0], goog.vec.Vec3.create());
    -
    -    assertElementsEquals([1, 2, 3], goog.vec.Vec3.createFromValues(1, 2, 3));
    -
    -    assertElementsEquals([1, 2, 3], goog.vec.Vec3.createFromArray([1, 2, 3]));
    -
    -    v = goog.vec.Vec3.createFromValues(1, 2, 3);
    -    assertElementsEquals([1, 2, 3], goog.vec.Vec3.clone(v));
    -  }
    -
    -  function testConstructor() {
    -    var v = goog.vec.Vec3.createFloat32();
    -    assertElementsEquals(0, v[0]);
    -    assertEquals(0, v[1]);
    -    assertEquals(0, v[2]);
    -
    -    assertElementsEquals([0, 0, 0], goog.vec.Vec3.createFloat32());
    -
    -    goog.vec.Vec3.setFromValues(v, 1, 2, 3);
    -    assertElementsEquals([1, 2, 3], v);
    -
    -    var w = goog.vec.Vec3.createFloat64();
    -    assertElementsEquals(0, w[0]);
    -    assertEquals(0, w[1]);
    -    assertEquals(0, w[2]);
    -
    -    assertElementsEquals([0, 0, 0], goog.vec.Vec3.createFloat64());
    -
    -    goog.vec.Vec3.setFromValues(w, 1, 2, 3);
    -    assertElementsEquals([1, 2, 3], w);
    -  }
    -
    -
    -  function testSet() {
    -    var v = goog.vec.Vec3.createFloat32();
    -    goog.vec.Vec3.setFromValues(v, 1, 2, 3);
    -    assertElementsEquals([1, 2, 3], v);
    -
    -    goog.vec.Vec3.setFromArray(v, [4, 5, 6]);
    -    assertElementsEquals([4, 5, 6], v);
    -
    -    var w = goog.vec.Vec3.createFloat32();
    -    goog.vec.Vec3.setFromValues(w, 1, 2, 3);
    -    assertElementsEquals([1, 2, 3], w);
    -
    -    goog.vec.Vec3.setFromArray(w, [4, 5, 6]);
    -    assertElementsEquals([4, 5, 6], w);
    -  }
    -
    -  function testAdd() {
    -    var v0 = goog.vec.Vec3.createFloat32FromArray([1, 2, 3]);
    -    var v1 = goog.vec.Vec3.createFloat32FromArray([4, 5, 6]);
    -    var v2 = goog.vec.Vec3.cloneFloat32(v0);
    -
    -    goog.vec.Vec3.add(v2, v1, v2);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals([4, 5, 6], v1);
    -    assertElementsEquals([5, 7, 9], v2);
    -
    -    goog.vec.Vec3.add(goog.vec.Vec3.add(v0, v1, v2), v0, v2);
    -    assertElementsEquals([6, 9, 12], v2);
    -  }
    -
    -  function testSubtract() {
    -    var v0 = goog.vec.Vec3.createFloat32FromArray([1, 2, 3]);
    -    var v1 = goog.vec.Vec3.createFloat32FromArray([4, 5, 6]);
    -    var v2 = goog.vec.Vec3.cloneFloat32(v0);
    -
    -    goog.vec.Vec3.subtract(v2, v1, v2);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals([4, 5, 6], v1);
    -    assertElementsEquals([-3, -3, -3], v2);
    -
    -    goog.vec.Vec3.setFromValues(v2, 0, 0, 0);
    -    goog.vec.Vec3.subtract(v1, v0, v2);
    -    assertElementsEquals([3, 3, 3], v2);
    -
    -    v2 = goog.vec.Vec3.cloneFloat32(v0);
    -    goog.vec.Vec3.subtract(v2, v1, v2);
    -    assertElementsEquals([-3, -3, -3], v2);
    -
    -    goog.vec.Vec3.subtract(goog.vec.Vec3.subtract(v1, v0, v2), v0, v2);
    -    assertElementsEquals([2, 1, 0], v2);
    -  }
    -
    -  function testNegate() {
    -    var v0 = goog.vec.Vec3.createFloat32FromArray([1, 2, 3]);
    -    var v1 = goog.vec.Vec3.createFloat32();
    -
    -    goog.vec.Vec3.negate(v0, v1);
    -    assertElementsEquals([-1, -2, -3], v1);
    -    assertElementsEquals([1, 2, 3], v0);
    -
    -    goog.vec.Vec3.negate(v0, v0);
    -    assertElementsEquals([-1, -2, -3], v0);
    -  }
    -
    -  function testAbs() {
    -    var v0 = goog.vec.Vec3.createFloat32FromValues(-1, -2, -3);
    -    var v1 = goog.vec.Vec3.createFloat32();
    -
    -    goog.vec.Vec3.abs(v0, v1);
    -    assertElementsEquals([1, 2, 3], v1);
    -    assertElementsEquals([-1, -2, -3], v0);
    -
    -    goog.vec.Vec3.abs(v0, v0);
    -    assertElementsEquals([1, 2, 3], v0);
    -  }
    -
    -  function testScale() {
    -    var v0 = goog.vec.Vec3.createFloat32FromArray([1, 2, 3]);
    -    var v1 = goog.vec.Vec3.createFloat32();
    -
    -    goog.vec.Vec3.scale(v0, 4, v1);
    -    assertElementsEquals([4, 8, 12], v1);
    -    assertElementsEquals([1, 2, 3], v0);
    -
    -    goog.vec.Vec3.setFromArray(v1, v0);
    -    goog.vec.Vec3.scale(v1, 5, v1);
    -    assertElementsEquals([5, 10, 15], v1);
    -  }
    -
    -  function testMagnitudeSquared() {
    -    var v0 = goog.vec.Vec3.createFloat32FromArray([1, 2, 3]);
    -    assertEquals(14, goog.vec.Vec3.magnitudeSquared(v0));
    -  }
    -
    -  function testMagnitude() {
    -    var v0 = goog.vec.Vec3.createFloat32FromArray([1, 2, 3]);
    -    assertEquals(Math.sqrt(14), goog.vec.Vec3.magnitude(v0));
    -  }
    -
    -  function testNormalize() {
    -    var v0 = goog.vec.Vec3.createFloat32FromArray([2, 3, 4]);
    -    var v1 = goog.vec.Vec3.create();
    -    var v2 = goog.vec.Vec3.create();
    -    goog.vec.Vec3.scale(
    -        v0, 1 / goog.vec.Vec3.magnitude(v0), v2);
    -
    -    goog.vec.Vec3.normalize(v0, v1);
    -    assertElementsEquals(v2, v1);
    -    assertElementsEquals([2, 3, 4], v0);
    -
    -    goog.vec.Vec3.setFromArray(v1, v0);
    -    goog.vec.Vec3.normalize(v1, v1);
    -    assertElementsEquals(v2, v1);
    -  }
    -
    -  function testDot() {
    -    var v0 = goog.vec.Vec3.createFloat32FromArray([1, 2, 3]);
    -    var v1 = goog.vec.Vec3.createFloat32FromArray([4, 5, 6]);
    -    assertEquals(32, goog.vec.Vec3.dot(v0, v1));
    -    assertEquals(32, goog.vec.Vec3.dot(v1, v0));
    -  }
    -
    -  function testCross() {
    -    var v0 = goog.vec.Vec3.createFloat32FromArray([1, 2, 3]);
    -    var v1 = goog.vec.Vec3.createFloat32FromArray([4, 5, 6]);
    -    var crossVec = goog.vec.Vec3.create();
    -
    -    goog.vec.Vec3.cross(v0, v1, crossVec);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals([4, 5, 6], v1);
    -    assertElementsEquals([-3, 6, -3], crossVec);
    -
    -    goog.vec.Vec3.setFromArray(crossVec, v1);
    -    goog.vec.Vec3.cross(crossVec, v0, crossVec);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals([4, 5, 6], v1);
    -    assertElementsEquals([3, -6, 3], crossVec);
    -
    -    goog.vec.Vec3.cross(v0, v0, v0);
    -    assertElementsEquals([0, 0, 0], v0);
    -  }
    -
    -  function testDistanceSquared() {
    -    var v0 = goog.vec.Vec3.createFloat32FromValues(1, 2, 3);
    -    var v1 = goog.vec.Vec3.createFloat32FromValues(1, 2, 3);
    -    assertEquals(0, goog.vec.Vec3.distanceSquared(v0, v1));
    -    goog.vec.Vec3.setFromValues(v0, 1, 2, 3);
    -    goog.vec.Vec3.setFromValues(v1, -1, -2, -1);
    -    assertEquals(36, goog.vec.Vec3.distanceSquared(v0, v1));
    -  }
    -
    -  function testDistance() {
    -    var v0 = goog.vec.Vec3.createFloat32FromValues(1, 2, 3);
    -    var v1 = goog.vec.Vec3.createFloat32FromValues(1, 2, 3);
    -    assertEquals(0, goog.vec.Vec3.distance(v0, v1));
    -    goog.vec.Vec3.setFromValues(v0, 1, 2, 3);
    -    goog.vec.Vec3.setFromValues(v1, -1, -2, -1);
    -    assertEquals(6, goog.vec.Vec3.distance(v0, v1));
    -  }
    -
    -  function testDirection() {
    -    var v0 = goog.vec.Vec3.createFloat32FromValues(1, 2, 3);
    -    var v1 = goog.vec.Vec3.createFloat32FromValues(1, 2, 3);
    -    var dirVec = goog.vec.Vec3.createFloat32FromValues(4, 5, 6);
    -    goog.vec.Vec3.direction(v0, v1, dirVec);
    -    assertElementsEquals([0, 0, 0], dirVec);
    -    goog.vec.Vec3.setFromValues(v0, 0, 0, 0);
    -    goog.vec.Vec3.setFromValues(v1, 1, 0, 0);
    -    goog.vec.Vec3.direction(v0, v1, dirVec);
    -    assertElementsEquals([1, 0, 0], dirVec);
    -    goog.vec.Vec3.setFromValues(v0, 1, 1, 1);
    -    goog.vec.Vec3.setFromValues(v1, 0, 0, 0);
    -    goog.vec.Vec3.direction(v0, v1, dirVec);
    -    assertElementsRoughlyEqual(
    -        [-0.5773502588272095, -0.5773502588272095, -0.5773502588272095],
    -        dirVec, goog.vec.EPSILON);
    -  }
    -
    -  function testLerp() {
    -    var v0 = goog.vec.Vec3.createFloat32FromValues(1, 2, 3);
    -    var v1 = goog.vec.Vec3.createFloat32FromValues(10, 20, 30);
    -    var v2 = goog.vec.Vec3.cloneFloat32(v0);
    -
    -    goog.vec.Vec3.lerp(v2, v1, 0, v2);
    -    assertElementsEquals([1, 2, 3], v2);
    -    goog.vec.Vec3.lerp(v2, v1, 1, v2);
    -    assertElementsEquals([10, 20, 30], v2);
    -    goog.vec.Vec3.lerp(v0, v1, .5, v2);
    -    assertElementsEquals([5.5, 11, 16.5], v2);
    -  }
    -
    -  function testMax() {
    -    var v0 = goog.vec.Vec3.createFloat32FromValues(10, 20, 30);
    -    var v1 = goog.vec.Vec3.createFloat32FromValues(5, 25, 35);
    -    var v2 = goog.vec.Vec3.createFloat32();
    -
    -    goog.vec.Vec3.max(v0, v1, v2);
    -    assertElementsEquals([10, 25, 35], v2);
    -    goog.vec.Vec3.max(v1, v0, v1);
    -    assertElementsEquals([10, 25, 35], v1);
    -    goog.vec.Vec3.max(v2, 20, v2);
    -    assertElementsEquals([20, 25, 35], v2);
    -  }
    -
    -  function testMin() {
    -    var v0 = goog.vec.Vec3.createFloat32FromValues(10, 20, 30);
    -    var v1 = goog.vec.Vec3.createFloat32FromValues(5, 25, 35);
    -    var v2 = goog.vec.Vec3.createFloat32();
    -
    -    goog.vec.Vec3.min(v0, v1, v2);
    -    assertElementsEquals([5, 20, 30], v2);
    -    goog.vec.Vec3.min(v1, v0, v1);
    -    assertElementsEquals([5, 20, 30], v1);
    -    goog.vec.Vec3.min(v2, 20, v2);
    -    assertElementsEquals([5, 20, 20], v2);
    -  }
    -
    -  function testEquals() {
    -    var v0 = goog.vec.Vec3.createFloat32FromValues(1, 2, 3);
    -    var v1 = goog.vec.Vec3.cloneFloat32(v0);
    -    assertElementsEquals(v0, v1);
    -
    -    v1[0] = 4;
    -    assertFalse(goog.vec.Vec3.equals(v0, v1));
    -
    -    v1 = goog.vec.Vec3.cloneFloat32(v0);
    -    v1[1] = 4;
    -    assertFalse(goog.vec.Vec3.equals(v0, v1));
    -
    -    v1 = goog.vec.Vec3.cloneFloat32(v0);
    -    v1[2] = 4;
    -    assertFalse(goog.vec.Vec3.equals(v0, v1));
    -  }
    -
    -</script>
    -</body>
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/vec3d.js b/src/database/third_party/closure-library/closure/goog/vec/vec3d.js
    deleted file mode 100644
    index 97e8d770912..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/vec3d.js
    +++ /dev/null
    @@ -1,426 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -//                                                                           //
    -// Any edits to this file must be applied to vec3f.js by running:            //
    -//   swap_type.sh vec3d.js > vec3f.js                                        //
    -//                                                                           //
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -
    -
    -/**
    - * @fileoverview Provides functions for operating on 3 element double (64bit)
    - * vectors.
    - *
    - * The last parameter will typically be the output object and an object
    - * can be both an input and output parameter to all methods except where
    - * noted.
    - *
    - * See the README for notes about the design and structure of the API
    - * (especially related to performance).
    - *
    - */
    -goog.provide('goog.vec.vec3d');
    -goog.provide('goog.vec.vec3d.Type');
    -
    -/** @suppress {extraRequire} */
    -goog.require('goog.vec');
    -
    -/** @typedef {goog.vec.Float64} */ goog.vec.vec3d.Type;
    -
    -
    -/**
    - * Creates a vec3d with all elements initialized to zero.
    - *
    - * @return {!goog.vec.vec3d.Type} The new vec3d.
    - */
    -goog.vec.vec3d.create = function() {
    -  return new Float64Array(3);
    -};
    -
    -
    -/**
    - * Initializes the vector with the given values.
    - *
    - * @param {goog.vec.vec3d.Type} vec The vector to receive the values.
    - * @param {number} v0 The value for element at index 0.
    - * @param {number} v1 The value for element at index 1.
    - * @param {number} v2 The value for element at index 2.
    - * @return {!goog.vec.vec3d.Type} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3d.setFromValues = function(vec, v0, v1, v2) {
    -  vec[0] = v0;
    -  vec[1] = v1;
    -  vec[2] = v2;
    -  return vec;
    -};
    -
    -
    -/**
    - * Initializes vec3d vec from vec3d src.
    - *
    - * @param {goog.vec.vec3d.Type} vec The destination vector.
    - * @param {goog.vec.vec3d.Type} src The source vector.
    - * @return {!goog.vec.vec3d.Type} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3d.setFromVec3d = function(vec, src) {
    -  vec[0] = src[0];
    -  vec[1] = src[1];
    -  vec[2] = src[2];
    -  return vec;
    -};
    -
    -
    -/**
    - * Initializes vec3d vec from vec3f src (typed as a Float32Array to
    - * avoid circular goog.requires).
    - *
    - * @param {goog.vec.vec3d.Type} vec The destination vector.
    - * @param {Float32Array} src The source vector.
    - * @return {!goog.vec.vec3d.Type} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3d.setFromVec3f = function(vec, src) {
    -  vec[0] = src[0];
    -  vec[1] = src[1];
    -  vec[2] = src[2];
    -  return vec;
    -};
    -
    -
    -/**
    - * Initializes vec3d vec from Array src.
    - *
    - * @param {goog.vec.vec3d.Type} vec The destination vector.
    - * @param {Array<number>} src The source vector.
    - * @return {!goog.vec.vec3d.Type} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3d.setFromArray = function(vec, src) {
    -  vec[0] = src[0];
    -  vec[1] = src[1];
    -  vec[2] = src[2];
    -  return vec;
    -};
    -
    -
    -/**
    - * Performs a component-wise addition of vec0 and vec1 together storing the
    - * result into resultVec.
    - *
    - * @param {goog.vec.vec3d.Type} vec0 The first addend.
    - * @param {goog.vec.vec3d.Type} vec1 The second addend.
    - * @param {goog.vec.vec3d.Type} resultVec The vector to
    - *     receive the result. May be vec0 or vec1.
    - * @return {!goog.vec.vec3d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3d.add = function(vec0, vec1, resultVec) {
    -  resultVec[0] = vec0[0] + vec1[0];
    -  resultVec[1] = vec0[1] + vec1[1];
    -  resultVec[2] = vec0[2] + vec1[2];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Performs a component-wise subtraction of vec1 from vec0 storing the
    - * result into resultVec.
    - *
    - * @param {goog.vec.vec3d.Type} vec0 The minuend.
    - * @param {goog.vec.vec3d.Type} vec1 The subtrahend.
    - * @param {goog.vec.vec3d.Type} resultVec The vector to
    - *     receive the result. May be vec0 or vec1.
    - * @return {!goog.vec.vec3d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3d.subtract = function(vec0, vec1, resultVec) {
    -  resultVec[0] = vec0[0] - vec1[0];
    -  resultVec[1] = vec0[1] - vec1[1];
    -  resultVec[2] = vec0[2] - vec1[2];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Negates vec0, storing the result into resultVec.
    - *
    - * @param {goog.vec.vec3d.Type} vec0 The vector to negate.
    - * @param {goog.vec.vec3d.Type} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.vec3d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3d.negate = function(vec0, resultVec) {
    -  resultVec[0] = -vec0[0];
    -  resultVec[1] = -vec0[1];
    -  resultVec[2] = -vec0[2];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Takes the absolute value of each component of vec0 storing the result in
    - * resultVec.
    - *
    - * @param {goog.vec.vec3d.Type} vec0 The source vector.
    - * @param {goog.vec.vec3d.Type} resultVec The vector to receive the result.
    - *     May be vec0.
    - * @return {!goog.vec.vec3d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3d.abs = function(vec0, resultVec) {
    -  resultVec[0] = Math.abs(vec0[0]);
    -  resultVec[1] = Math.abs(vec0[1]);
    -  resultVec[2] = Math.abs(vec0[2]);
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Multiplies each component of vec0 with scalar storing the product into
    - * resultVec.
    - *
    - * @param {goog.vec.vec3d.Type} vec0 The source vector.
    - * @param {number} scalar The value to multiply with each component of vec0.
    - * @param {goog.vec.vec3d.Type} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.vec3d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3d.scale = function(vec0, scalar, resultVec) {
    -  resultVec[0] = vec0[0] * scalar;
    -  resultVec[1] = vec0[1] * scalar;
    -  resultVec[2] = vec0[2] * scalar;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns the magnitudeSquared of the given vector.
    - *
    - * @param {goog.vec.vec3d.Type} vec0 The vector.
    - * @return {number} The magnitude of the vector.
    - */
    -goog.vec.vec3d.magnitudeSquared = function(vec0) {
    -  var x = vec0[0], y = vec0[1], z = vec0[2];
    -  return x * x + y * y + z * z;
    -};
    -
    -
    -/**
    - * Returns the magnitude of the given vector.
    - *
    - * @param {goog.vec.vec3d.Type} vec0 The vector.
    - * @return {number} The magnitude of the vector.
    - */
    -goog.vec.vec3d.magnitude = function(vec0) {
    -  var x = vec0[0], y = vec0[1], z = vec0[2];
    -  return Math.sqrt(x * x + y * y + z * z);
    -};
    -
    -
    -/**
    - * Normalizes the given vector storing the result into resultVec.
    - *
    - * @param {goog.vec.vec3d.Type} vec0 The vector to normalize.
    - * @param {goog.vec.vec3d.Type} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.vec3d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3d.normalize = function(vec0, resultVec) {
    -  var x = vec0[0], y = vec0[1], z = vec0[2];
    -  var ilen = 1 / Math.sqrt(x * x + y * y + z * z);
    -  resultVec[0] = x * ilen;
    -  resultVec[1] = y * ilen;
    -  resultVec[2] = z * ilen;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns the scalar product of vectors v0 and v1.
    - *
    - * @param {goog.vec.vec3d.Type} v0 The first vector.
    - * @param {goog.vec.vec3d.Type} v1 The second vector.
    - * @return {number} The scalar product.
    - */
    -goog.vec.vec3d.dot = function(v0, v1) {
    -  return v0[0] * v1[0] + v0[1] * v1[1] + v0[2] * v1[2];
    -};
    -
    -
    -/**
    - * Computes the vector (cross) product of v0 and v1 storing the result into
    - * resultVec.
    - *
    - * @param {goog.vec.vec3d.Type} v0 The first vector.
    - * @param {goog.vec.vec3d.Type} v1 The second vector.
    - * @param {goog.vec.vec3d.Type} resultVec The vector to receive the
    - *     results. May be either v0 or v1.
    - * @return {!goog.vec.vec3d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3d.cross = function(v0, v1, resultVec) {
    -  var x0 = v0[0], y0 = v0[1], z0 = v0[2];
    -  var x1 = v1[0], y1 = v1[1], z1 = v1[2];
    -  resultVec[0] = y0 * z1 - z0 * y1;
    -  resultVec[1] = z0 * x1 - x0 * z1;
    -  resultVec[2] = x0 * y1 - y0 * x1;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns the squared distance between two points.
    - *
    - * @param {goog.vec.vec3d.Type} vec0 First point.
    - * @param {goog.vec.vec3d.Type} vec1 Second point.
    - * @return {number} The squared distance between the points.
    - */
    -goog.vec.vec3d.distanceSquared = function(vec0, vec1) {
    -  var x = vec0[0] - vec1[0];
    -  var y = vec0[1] - vec1[1];
    -  var z = vec0[2] - vec1[2];
    -  return x * x + y * y + z * z;
    -};
    -
    -
    -/**
    - * Returns the distance between two points.
    - *
    - * @param {goog.vec.vec3d.Type} vec0 First point.
    - * @param {goog.vec.vec3d.Type} vec1 Second point.
    - * @return {number} The distance between the points.
    - */
    -goog.vec.vec3d.distance = function(vec0, vec1) {
    -  return Math.sqrt(goog.vec.vec3d.distanceSquared(vec0, vec1));
    -};
    -
    -
    -/**
    - * Returns a unit vector pointing from one point to another.
    - * If the input points are equal then the result will be all zeros.
    - *
    - * @param {goog.vec.vec3d.Type} vec0 Origin point.
    - * @param {goog.vec.vec3d.Type} vec1 Target point.
    - * @param {goog.vec.vec3d.Type} resultVec The vector to receive the
    - *     results (may be vec0 or vec1).
    - * @return {!goog.vec.vec3d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3d.direction = function(vec0, vec1, resultVec) {
    -  var x = vec1[0] - vec0[0];
    -  var y = vec1[1] - vec0[1];
    -  var z = vec1[2] - vec0[2];
    -  var d = Math.sqrt(x * x + y * y + z * z);
    -  if (d) {
    -    d = 1 / d;
    -    resultVec[0] = x * d;
    -    resultVec[1] = y * d;
    -    resultVec[2] = z * d;
    -  } else {
    -    resultVec[0] = resultVec[1] = resultVec[2] = 0;
    -  }
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Linearly interpolate from vec0 to v1 according to f. The value of f should be
    - * in the range [0..1] otherwise the results are undefined.
    - *
    - * @param {goog.vec.vec3d.Type} v0 The first vector.
    - * @param {goog.vec.vec3d.Type} v1 The second vector.
    - * @param {number} f The interpolation factor.
    - * @param {goog.vec.vec3d.Type} resultVec The vector to receive the
    - *     results (may be v0 or v1).
    - * @return {!goog.vec.vec3d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3d.lerp = function(v0, v1, f, resultVec) {
    -  var x = v0[0], y = v0[1], z = v0[2];
    -  resultVec[0] = (v1[0] - x) * f + x;
    -  resultVec[1] = (v1[1] - y) * f + y;
    -  resultVec[2] = (v1[2] - z) * f + z;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Compares the components of vec0 with the components of another vector or
    - * scalar, storing the larger values in resultVec.
    - *
    - * @param {goog.vec.vec3d.Type} vec0 The source vector.
    - * @param {goog.vec.vec3d.Type|number} limit The limit vector or scalar.
    - * @param {goog.vec.vec3d.Type} resultVec The vector to receive the
    - *     results (may be vec0 or limit).
    - * @return {!goog.vec.vec3d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3d.max = function(vec0, limit, resultVec) {
    -  if (goog.isNumber(limit)) {
    -    resultVec[0] = Math.max(vec0[0], limit);
    -    resultVec[1] = Math.max(vec0[1], limit);
    -    resultVec[2] = Math.max(vec0[2], limit);
    -  } else {
    -    resultVec[0] = Math.max(vec0[0], limit[0]);
    -    resultVec[1] = Math.max(vec0[1], limit[1]);
    -    resultVec[2] = Math.max(vec0[2], limit[2]);
    -  }
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Compares the components of vec0 with the components of another vector or
    - * scalar, storing the smaller values in resultVec.
    - *
    - * @param {goog.vec.vec3d.Type} vec0 The source vector.
    - * @param {goog.vec.vec3d.Type|number} limit The limit vector or scalar.
    - * @param {goog.vec.vec3d.Type} resultVec The vector to receive the
    - *     results (may be vec0 or limit).
    - * @return {!goog.vec.vec3d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3d.min = function(vec0, limit, resultVec) {
    -  if (goog.isNumber(limit)) {
    -    resultVec[0] = Math.min(vec0[0], limit);
    -    resultVec[1] = Math.min(vec0[1], limit);
    -    resultVec[2] = Math.min(vec0[2], limit);
    -  } else {
    -    resultVec[0] = Math.min(vec0[0], limit[0]);
    -    resultVec[1] = Math.min(vec0[1], limit[1]);
    -    resultVec[2] = Math.min(vec0[2], limit[2]);
    -  }
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns true if the components of v0 are equal to the components of v1.
    - *
    - * @param {goog.vec.vec3d.Type} v0 The first vector.
    - * @param {goog.vec.vec3d.Type} v1 The second vector.
    - * @return {boolean} True if the vectors are equal, false otherwise.
    - */
    -goog.vec.vec3d.equals = function(v0, v1) {
    -  return v0.length == v1.length &&
    -      v0[0] == v1[0] && v0[1] == v1[1] && v0[2] == v1[2];
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/vec3d_test.html b/src/database/third_party/closure-library/closure/goog/vec/vec3d_test.html
    deleted file mode 100644
    index 305b485f802..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/vec3d_test.html
    +++ /dev/null
    @@ -1,270 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -//                                                                           //
    -// Any edits to this file must be applied to vec3f_test.html by running:     //
    -//   swap_type.sh vec3d_test.html > vec3f_test.html                          //
    -//                                                                           //
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.vec.vec3d</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.vec.Float64Array');
    -  goog.require('goog.vec.vec3d');
    -  goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -  function testCreate() {
    -    var v = goog.vec.vec3d.create();
    -    assertElementsEquals([0, 0, 0], v);
    -  }
    -
    -  function testSet() {
    -    var v = goog.vec.vec3d.create();
    -    goog.vec.vec3d.setFromValues(v, 1, 2, 3);
    -    assertElementsEquals([1, 2, 3], v);
    -
    -    goog.vec.vec3d.setFromArray(v, [4, 5, 6]);
    -    assertElementsEquals([4, 5, 6], v);
    -
    -    var w = goog.vec.vec3d.create();
    -    goog.vec.vec3d.setFromValues(w, 1, 2, 3);
    -    assertElementsEquals([1, 2, 3], w);
    -
    -    goog.vec.vec3d.setFromArray(w, [4, 5, 6]);
    -    assertElementsEquals([4, 5, 6], w);
    -  }
    -
    -  function testAdd() {
    -    var v0 = goog.vec.vec3d.setFromArray(goog.vec.vec3d.create(), [1, 2, 3]);
    -    var v1 = goog.vec.vec3d.setFromArray(goog.vec.vec3d.create(), [4, 5, 6]);
    -    var v2 = goog.vec.vec3d.setFromVec3d(goog.vec.vec3d.create(), v0);
    -
    -    goog.vec.vec3d.add(v2, v1, v2);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals([4, 5, 6], v1);
    -    assertElementsEquals([5, 7, 9], v2);
    -
    -    goog.vec.vec3d.add(goog.vec.vec3d.add(v0, v1, v2), v0, v2);
    -    assertElementsEquals([6, 9, 12], v2);
    -  }
    -
    -  function testSubtract() {
    -    var v0 = goog.vec.vec3d.setFromArray(goog.vec.vec3d.create(), [1, 2, 3]);
    -    var v1 = goog.vec.vec3d.setFromArray(goog.vec.vec3d.create(), [4, 5, 6]);
    -    var v2 = goog.vec.vec3d.setFromVec3d(goog.vec.vec3d.create(), v0);
    -
    -    goog.vec.vec3d.subtract(v2, v1, v2);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals([4, 5, 6], v1);
    -    assertElementsEquals([-3, -3, -3], v2);
    -
    -    goog.vec.vec3d.setFromValues(v2, 0, 0, 0);
    -    goog.vec.vec3d.subtract(v1, v0, v2);
    -    assertElementsEquals([3, 3, 3], v2);
    -
    -    v2 = goog.vec.vec3d.setFromVec3d(goog.vec.vec3d.create(), v0);
    -    goog.vec.vec3d.subtract(v2, v1, v2);
    -    assertElementsEquals([-3, -3, -3], v2);
    -
    -    goog.vec.vec3d.subtract(goog.vec.vec3d.subtract(v1, v0, v2), v0, v2);
    -    assertElementsEquals([2, 1, 0], v2);
    -  }
    -
    -  function testNegate() {
    -    var v0 = goog.vec.vec3d.setFromArray(goog.vec.vec3d.create(), [1, 2, 3]);
    -    var v1 = goog.vec.vec3d.create();
    -
    -    goog.vec.vec3d.negate(v0, v1);
    -    assertElementsEquals([-1, -2, -3], v1);
    -    assertElementsEquals([1, 2, 3], v0);
    -
    -    goog.vec.vec3d.negate(v0, v0);
    -    assertElementsEquals([-1, -2, -3], v0);
    -  }
    -
    -  function testAbs() {
    -    var v0 = goog.vec.vec3d.setFromArray(goog.vec.vec3d.create(), [-1, -2, -3]);
    -    var v1 = goog.vec.vec3d.create();
    -
    -    goog.vec.vec3d.abs(v0, v1);
    -    assertElementsEquals([1, 2, 3], v1);
    -    assertElementsEquals([-1, -2, -3], v0);
    -
    -    goog.vec.vec3d.abs(v0, v0);
    -    assertElementsEquals([1, 2, 3], v0);
    -  }
    -
    -  function testScale() {
    -    var v0 = goog.vec.vec3d.setFromArray(goog.vec.vec3d.create(), [1, 2, 3]);
    -    var v1 = goog.vec.vec3d.create();
    -
    -    goog.vec.vec3d.scale(v0, 4, v1);
    -    assertElementsEquals([4, 8, 12], v1);
    -    assertElementsEquals([1, 2, 3], v0);
    -
    -    goog.vec.vec3d.setFromArray(v1, v0);
    -    goog.vec.vec3d.scale(v1, 5, v1);
    -    assertElementsEquals([5, 10, 15], v1);
    -  }
    -
    -  function testMagnitudeSquared() {
    -    var v0 = goog.vec.vec3d.setFromArray(goog.vec.vec3d.create(), [1, 2, 3]);
    -    assertEquals(14, goog.vec.vec3d.magnitudeSquared(v0));
    -  }
    -
    -  function testMagnitude() {
    -    var v0 = goog.vec.vec3d.setFromArray(goog.vec.vec3d.create(), [1, 2, 3]);
    -    assertEquals(Math.sqrt(14), goog.vec.vec3d.magnitude(v0));
    -  }
    -
    -  function testNormalize() {
    -    var v0 = goog.vec.vec3d.setFromArray(goog.vec.vec3d.create(), [2, 3, 4]);
    -    var v1 = goog.vec.vec3d.create();
    -    var v2 = goog.vec.vec3d.create();
    -    goog.vec.vec3d.scale(
    -        v0, 1 / goog.vec.vec3d.magnitude(v0), v2);
    -
    -    goog.vec.vec3d.normalize(v0, v1);
    -    assertElementsEquals(v2, v1);
    -    assertElementsEquals([2, 3, 4], v0);
    -
    -    goog.vec.vec3d.setFromArray(v1, v0);
    -    goog.vec.vec3d.normalize(v1, v1);
    -    assertElementsEquals(v2, v1);
    -  }
    -
    -  function testDot() {
    -    var v0 = goog.vec.vec3d.setFromArray(goog.vec.vec3d.create(), [1, 2, 3]);
    -    var v1 = goog.vec.vec3d.setFromArray(goog.vec.vec3d.create(), [4, 5, 6]);
    -    assertEquals(32, goog.vec.vec3d.dot(v0, v1));
    -    assertEquals(32, goog.vec.vec3d.dot(v1, v0));
    -  }
    -
    -  function testCross() {
    -    var v0 = goog.vec.vec3d.setFromArray(goog.vec.vec3d.create(), [1, 2, 3]);
    -    var v1 = goog.vec.vec3d.setFromArray(goog.vec.vec3d.create(), [4, 5, 6]);
    -    var crossVec = goog.vec.vec3d.create();
    -
    -    goog.vec.vec3d.cross(v0, v1, crossVec);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals([4, 5, 6], v1);
    -    assertElementsEquals([-3, 6, -3], crossVec);
    -
    -    goog.vec.vec3d.setFromArray(crossVec, v1);
    -    goog.vec.vec3d.cross(crossVec, v0, crossVec);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals([4, 5, 6], v1);
    -    assertElementsEquals([3, -6, 3], crossVec);
    -
    -    goog.vec.vec3d.cross(v0, v0, v0);
    -    assertElementsEquals([0, 0, 0], v0);
    -  }
    -
    -  function testDistanceSquared() {
    -    var v0 = goog.vec.vec3d.setFromValues(goog.vec.vec3d.create(), 1, 2, 3);
    -    var v1 = goog.vec.vec3d.setFromValues(goog.vec.vec3d.create(), 1, 2, 3);
    -    assertEquals(0, goog.vec.vec3d.distanceSquared(v0, v1));
    -    goog.vec.vec3d.setFromValues(v0, 1, 2, 3);
    -    goog.vec.vec3d.setFromValues(v1, -1, -2, -1);
    -    assertEquals(36, goog.vec.vec3d.distanceSquared(v0, v1));
    -  }
    -
    -  function testDistance() {
    -    var v0 = goog.vec.vec3d.setFromValues(goog.vec.vec3d.create(), 1, 2, 3);
    -    var v1 = goog.vec.vec3d.setFromValues(goog.vec.vec3d.create(), 1, 2, 3);
    -    assertEquals(0, goog.vec.vec3d.distance(v0, v1));
    -    goog.vec.vec3d.setFromValues(v0, 1, 2, 3);
    -    goog.vec.vec3d.setFromValues(v1, -1, -2, -1);
    -    assertEquals(6, goog.vec.vec3d.distance(v0, v1));
    -  }
    -
    -  function testDirection() {
    -    var v0 = goog.vec.vec3d.setFromValues(goog.vec.vec3d.create(), 1, 2, 3);
    -    var v1 = goog.vec.vec3d.setFromValues(goog.vec.vec3d.create(), 1, 2, 3);
    -    var dirVec = goog.vec.vec3d.setFromValues(goog.vec.vec3d.create(), 4, 5, 6);
    -    goog.vec.vec3d.direction(v0, v1, dirVec);
    -    assertElementsEquals([0, 0, 0], dirVec);
    -    goog.vec.vec3d.setFromValues(v0, 0, 0, 0);
    -    goog.vec.vec3d.setFromValues(v1, 1, 0, 0);
    -    goog.vec.vec3d.direction(v0, v1, dirVec);
    -    assertElementsEquals([1, 0, 0], dirVec);
    -    goog.vec.vec3d.setFromValues(v0, 1, 1, 1);
    -    goog.vec.vec3d.setFromValues(v1, 0, 0, 0);
    -    goog.vec.vec3d.direction(v0, v1, dirVec);
    -    assertElementsRoughlyEqual(
    -        [-0.5773502588272095, -0.5773502588272095, -0.5773502588272095],
    -        dirVec, goog.vec.EPSILON);
    -  }
    -
    -  function testLerp() {
    -    var v0 = goog.vec.vec3d.setFromValues(goog.vec.vec3d.create(), 1, 2, 3);
    -    var v1 = goog.vec.vec3d.setFromValues(goog.vec.vec3d.create(), 10, 20, 30);
    -    var v2 = goog.vec.vec3d.setFromVec3d(goog.vec.vec3d.create(), v0);
    -
    -    goog.vec.vec3d.lerp(v2, v1, 0, v2);
    -    assertElementsEquals([1, 2, 3], v2);
    -    goog.vec.vec3d.lerp(v2, v1, 1, v2);
    -    assertElementsEquals([10, 20, 30], v2);
    -    goog.vec.vec3d.lerp(v0, v1, .5, v2);
    -    assertElementsEquals([5.5, 11, 16.5], v2);
    -  }
    -
    -  function testMax() {
    -    var v0 = goog.vec.vec3d.setFromValues(goog.vec.vec3d.create(), 10, 20, 30);
    -    var v1 = goog.vec.vec3d.setFromValues(goog.vec.vec3d.create(), 5, 25, 35);
    -    var v2 = goog.vec.vec3d.create();
    -
    -    goog.vec.vec3d.max(v0, v1, v2);
    -    assertElementsEquals([10, 25, 35], v2);
    -    goog.vec.vec3d.max(v1, v0, v1);
    -    assertElementsEquals([10, 25, 35], v1);
    -    goog.vec.vec3d.max(v2, 20, v2);
    -    assertElementsEquals([20, 25, 35], v2);
    -  }
    -
    -  function testMin() {
    -    var v0 = goog.vec.vec3d.setFromValues(goog.vec.vec3d.create(), 10, 20, 30);
    -    var v1 = goog.vec.vec3d.setFromValues(goog.vec.vec3d.create(), 5, 25, 35);
    -    var v2 = goog.vec.vec3d.create();
    -
    -    goog.vec.vec3d.min(v0, v1, v2);
    -    assertElementsEquals([5, 20, 30], v2);
    -    goog.vec.vec3d.min(v1, v0, v1);
    -    assertElementsEquals([5, 20, 30], v1);
    -    goog.vec.vec3d.min(v2, 20, v2);
    -    assertElementsEquals([5, 20, 20], v2);
    -  }
    -
    -  function testEquals() {
    -    var v0 = goog.vec.vec3d.setFromValues(goog.vec.vec3d.create(), 1, 2, 3);
    -    var v1 = goog.vec.vec3d.setFromVec3d(goog.vec.vec3d.create(), v0);
    -    assertElementsEquals(v0, v1);
    -
    -    v1[0] = 4;
    -    assertFalse(goog.vec.vec3d.equals(v0, v1));
    -
    -    v1 = goog.vec.vec3d.setFromVec3d(goog.vec.vec3d.create(), v0);
    -    v1[1] = 4;
    -    assertFalse(goog.vec.vec3d.equals(v0, v1));
    -
    -    v1 = goog.vec.vec3d.setFromVec3d(goog.vec.vec3d.create(), v0);
    -    v1[2] = 4;
    -    assertFalse(goog.vec.vec3d.equals(v0, v1));
    -  }
    -
    -</script>
    -</body>
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/vec3f.js b/src/database/third_party/closure-library/closure/goog/vec/vec3f.js
    deleted file mode 100644
    index 8048ec7ab4b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/vec3f.js
    +++ /dev/null
    @@ -1,426 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -//                                                                           //
    -// Any edits to this file must be applied to vec3d.js by running:            //
    -//   swap_type.sh vec3f.js > vec3d.js                                        //
    -//                                                                           //
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -
    -
    -/**
    - * @fileoverview Provides functions for operating on 3 element float (32bit)
    - * vectors.
    - *
    - * The last parameter will typically be the output object and an object
    - * can be both an input and output parameter to all methods except where
    - * noted.
    - *
    - * See the README for notes about the design and structure of the API
    - * (especially related to performance).
    - *
    - */
    -goog.provide('goog.vec.vec3f');
    -goog.provide('goog.vec.vec3f.Type');
    -
    -/** @suppress {extraRequire} */
    -goog.require('goog.vec');
    -
    -/** @typedef {goog.vec.Float32} */ goog.vec.vec3f.Type;
    -
    -
    -/**
    - * Creates a vec3f with all elements initialized to zero.
    - *
    - * @return {!goog.vec.vec3f.Type} The new vec3f.
    - */
    -goog.vec.vec3f.create = function() {
    -  return new Float32Array(3);
    -};
    -
    -
    -/**
    - * Initializes the vector with the given values.
    - *
    - * @param {goog.vec.vec3f.Type} vec The vector to receive the values.
    - * @param {number} v0 The value for element at index 0.
    - * @param {number} v1 The value for element at index 1.
    - * @param {number} v2 The value for element at index 2.
    - * @return {!goog.vec.vec3f.Type} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3f.setFromValues = function(vec, v0, v1, v2) {
    -  vec[0] = v0;
    -  vec[1] = v1;
    -  vec[2] = v2;
    -  return vec;
    -};
    -
    -
    -/**
    - * Initializes vec3f vec from vec3f src.
    - *
    - * @param {goog.vec.vec3f.Type} vec The destination vector.
    - * @param {goog.vec.vec3f.Type} src The source vector.
    - * @return {!goog.vec.vec3f.Type} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3f.setFromVec3f = function(vec, src) {
    -  vec[0] = src[0];
    -  vec[1] = src[1];
    -  vec[2] = src[2];
    -  return vec;
    -};
    -
    -
    -/**
    - * Initializes vec3f vec from vec3d src (typed as a Float64Array to
    - * avoid circular goog.requires).
    - *
    - * @param {goog.vec.vec3f.Type} vec The destination vector.
    - * @param {Float64Array} src The source vector.
    - * @return {!goog.vec.vec3f.Type} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3f.setFromVec3d = function(vec, src) {
    -  vec[0] = src[0];
    -  vec[1] = src[1];
    -  vec[2] = src[2];
    -  return vec;
    -};
    -
    -
    -/**
    - * Initializes vec3f vec from Array src.
    - *
    - * @param {goog.vec.vec3f.Type} vec The destination vector.
    - * @param {Array<number>} src The source vector.
    - * @return {!goog.vec.vec3f.Type} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3f.setFromArray = function(vec, src) {
    -  vec[0] = src[0];
    -  vec[1] = src[1];
    -  vec[2] = src[2];
    -  return vec;
    -};
    -
    -
    -/**
    - * Performs a component-wise addition of vec0 and vec1 together storing the
    - * result into resultVec.
    - *
    - * @param {goog.vec.vec3f.Type} vec0 The first addend.
    - * @param {goog.vec.vec3f.Type} vec1 The second addend.
    - * @param {goog.vec.vec3f.Type} resultVec The vector to
    - *     receive the result. May be vec0 or vec1.
    - * @return {!goog.vec.vec3f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3f.add = function(vec0, vec1, resultVec) {
    -  resultVec[0] = vec0[0] + vec1[0];
    -  resultVec[1] = vec0[1] + vec1[1];
    -  resultVec[2] = vec0[2] + vec1[2];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Performs a component-wise subtraction of vec1 from vec0 storing the
    - * result into resultVec.
    - *
    - * @param {goog.vec.vec3f.Type} vec0 The minuend.
    - * @param {goog.vec.vec3f.Type} vec1 The subtrahend.
    - * @param {goog.vec.vec3f.Type} resultVec The vector to
    - *     receive the result. May be vec0 or vec1.
    - * @return {!goog.vec.vec3f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3f.subtract = function(vec0, vec1, resultVec) {
    -  resultVec[0] = vec0[0] - vec1[0];
    -  resultVec[1] = vec0[1] - vec1[1];
    -  resultVec[2] = vec0[2] - vec1[2];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Negates vec0, storing the result into resultVec.
    - *
    - * @param {goog.vec.vec3f.Type} vec0 The vector to negate.
    - * @param {goog.vec.vec3f.Type} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.vec3f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3f.negate = function(vec0, resultVec) {
    -  resultVec[0] = -vec0[0];
    -  resultVec[1] = -vec0[1];
    -  resultVec[2] = -vec0[2];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Takes the absolute value of each component of vec0 storing the result in
    - * resultVec.
    - *
    - * @param {goog.vec.vec3f.Type} vec0 The source vector.
    - * @param {goog.vec.vec3f.Type} resultVec The vector to receive the result.
    - *     May be vec0.
    - * @return {!goog.vec.vec3f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3f.abs = function(vec0, resultVec) {
    -  resultVec[0] = Math.abs(vec0[0]);
    -  resultVec[1] = Math.abs(vec0[1]);
    -  resultVec[2] = Math.abs(vec0[2]);
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Multiplies each component of vec0 with scalar storing the product into
    - * resultVec.
    - *
    - * @param {goog.vec.vec3f.Type} vec0 The source vector.
    - * @param {number} scalar The value to multiply with each component of vec0.
    - * @param {goog.vec.vec3f.Type} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.vec3f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3f.scale = function(vec0, scalar, resultVec) {
    -  resultVec[0] = vec0[0] * scalar;
    -  resultVec[1] = vec0[1] * scalar;
    -  resultVec[2] = vec0[2] * scalar;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns the magnitudeSquared of the given vector.
    - *
    - * @param {goog.vec.vec3f.Type} vec0 The vector.
    - * @return {number} The magnitude of the vector.
    - */
    -goog.vec.vec3f.magnitudeSquared = function(vec0) {
    -  var x = vec0[0], y = vec0[1], z = vec0[2];
    -  return x * x + y * y + z * z;
    -};
    -
    -
    -/**
    - * Returns the magnitude of the given vector.
    - *
    - * @param {goog.vec.vec3f.Type} vec0 The vector.
    - * @return {number} The magnitude of the vector.
    - */
    -goog.vec.vec3f.magnitude = function(vec0) {
    -  var x = vec0[0], y = vec0[1], z = vec0[2];
    -  return Math.sqrt(x * x + y * y + z * z);
    -};
    -
    -
    -/**
    - * Normalizes the given vector storing the result into resultVec.
    - *
    - * @param {goog.vec.vec3f.Type} vec0 The vector to normalize.
    - * @param {goog.vec.vec3f.Type} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.vec3f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3f.normalize = function(vec0, resultVec) {
    -  var x = vec0[0], y = vec0[1], z = vec0[2];
    -  var ilen = 1 / Math.sqrt(x * x + y * y + z * z);
    -  resultVec[0] = x * ilen;
    -  resultVec[1] = y * ilen;
    -  resultVec[2] = z * ilen;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns the scalar product of vectors v0 and v1.
    - *
    - * @param {goog.vec.vec3f.Type} v0 The first vector.
    - * @param {goog.vec.vec3f.Type} v1 The second vector.
    - * @return {number} The scalar product.
    - */
    -goog.vec.vec3f.dot = function(v0, v1) {
    -  return v0[0] * v1[0] + v0[1] * v1[1] + v0[2] * v1[2];
    -};
    -
    -
    -/**
    - * Computes the vector (cross) product of v0 and v1 storing the result into
    - * resultVec.
    - *
    - * @param {goog.vec.vec3f.Type} v0 The first vector.
    - * @param {goog.vec.vec3f.Type} v1 The second vector.
    - * @param {goog.vec.vec3f.Type} resultVec The vector to receive the
    - *     results. May be either v0 or v1.
    - * @return {!goog.vec.vec3f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3f.cross = function(v0, v1, resultVec) {
    -  var x0 = v0[0], y0 = v0[1], z0 = v0[2];
    -  var x1 = v1[0], y1 = v1[1], z1 = v1[2];
    -  resultVec[0] = y0 * z1 - z0 * y1;
    -  resultVec[1] = z0 * x1 - x0 * z1;
    -  resultVec[2] = x0 * y1 - y0 * x1;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns the squared distance between two points.
    - *
    - * @param {goog.vec.vec3f.Type} vec0 First point.
    - * @param {goog.vec.vec3f.Type} vec1 Second point.
    - * @return {number} The squared distance between the points.
    - */
    -goog.vec.vec3f.distanceSquared = function(vec0, vec1) {
    -  var x = vec0[0] - vec1[0];
    -  var y = vec0[1] - vec1[1];
    -  var z = vec0[2] - vec1[2];
    -  return x * x + y * y + z * z;
    -};
    -
    -
    -/**
    - * Returns the distance between two points.
    - *
    - * @param {goog.vec.vec3f.Type} vec0 First point.
    - * @param {goog.vec.vec3f.Type} vec1 Second point.
    - * @return {number} The distance between the points.
    - */
    -goog.vec.vec3f.distance = function(vec0, vec1) {
    -  return Math.sqrt(goog.vec.vec3f.distanceSquared(vec0, vec1));
    -};
    -
    -
    -/**
    - * Returns a unit vector pointing from one point to another.
    - * If the input points are equal then the result will be all zeros.
    - *
    - * @param {goog.vec.vec3f.Type} vec0 Origin point.
    - * @param {goog.vec.vec3f.Type} vec1 Target point.
    - * @param {goog.vec.vec3f.Type} resultVec The vector to receive the
    - *     results (may be vec0 or vec1).
    - * @return {!goog.vec.vec3f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3f.direction = function(vec0, vec1, resultVec) {
    -  var x = vec1[0] - vec0[0];
    -  var y = vec1[1] - vec0[1];
    -  var z = vec1[2] - vec0[2];
    -  var d = Math.sqrt(x * x + y * y + z * z);
    -  if (d) {
    -    d = 1 / d;
    -    resultVec[0] = x * d;
    -    resultVec[1] = y * d;
    -    resultVec[2] = z * d;
    -  } else {
    -    resultVec[0] = resultVec[1] = resultVec[2] = 0;
    -  }
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Linearly interpolate from vec0 to v1 according to f. The value of f should be
    - * in the range [0..1] otherwise the results are undefined.
    - *
    - * @param {goog.vec.vec3f.Type} v0 The first vector.
    - * @param {goog.vec.vec3f.Type} v1 The second vector.
    - * @param {number} f The interpolation factor.
    - * @param {goog.vec.vec3f.Type} resultVec The vector to receive the
    - *     results (may be v0 or v1).
    - * @return {!goog.vec.vec3f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3f.lerp = function(v0, v1, f, resultVec) {
    -  var x = v0[0], y = v0[1], z = v0[2];
    -  resultVec[0] = (v1[0] - x) * f + x;
    -  resultVec[1] = (v1[1] - y) * f + y;
    -  resultVec[2] = (v1[2] - z) * f + z;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Compares the components of vec0 with the components of another vector or
    - * scalar, storing the larger values in resultVec.
    - *
    - * @param {goog.vec.vec3f.Type} vec0 The source vector.
    - * @param {goog.vec.vec3f.Type|number} limit The limit vector or scalar.
    - * @param {goog.vec.vec3f.Type} resultVec The vector to receive the
    - *     results (may be vec0 or limit).
    - * @return {!goog.vec.vec3f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3f.max = function(vec0, limit, resultVec) {
    -  if (goog.isNumber(limit)) {
    -    resultVec[0] = Math.max(vec0[0], limit);
    -    resultVec[1] = Math.max(vec0[1], limit);
    -    resultVec[2] = Math.max(vec0[2], limit);
    -  } else {
    -    resultVec[0] = Math.max(vec0[0], limit[0]);
    -    resultVec[1] = Math.max(vec0[1], limit[1]);
    -    resultVec[2] = Math.max(vec0[2], limit[2]);
    -  }
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Compares the components of vec0 with the components of another vector or
    - * scalar, storing the smaller values in resultVec.
    - *
    - * @param {goog.vec.vec3f.Type} vec0 The source vector.
    - * @param {goog.vec.vec3f.Type|number} limit The limit vector or scalar.
    - * @param {goog.vec.vec3f.Type} resultVec The vector to receive the
    - *     results (may be vec0 or limit).
    - * @return {!goog.vec.vec3f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec3f.min = function(vec0, limit, resultVec) {
    -  if (goog.isNumber(limit)) {
    -    resultVec[0] = Math.min(vec0[0], limit);
    -    resultVec[1] = Math.min(vec0[1], limit);
    -    resultVec[2] = Math.min(vec0[2], limit);
    -  } else {
    -    resultVec[0] = Math.min(vec0[0], limit[0]);
    -    resultVec[1] = Math.min(vec0[1], limit[1]);
    -    resultVec[2] = Math.min(vec0[2], limit[2]);
    -  }
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns true if the components of v0 are equal to the components of v1.
    - *
    - * @param {goog.vec.vec3f.Type} v0 The first vector.
    - * @param {goog.vec.vec3f.Type} v1 The second vector.
    - * @return {boolean} True if the vectors are equal, false otherwise.
    - */
    -goog.vec.vec3f.equals = function(v0, v1) {
    -  return v0.length == v1.length &&
    -      v0[0] == v1[0] && v0[1] == v1[1] && v0[2] == v1[2];
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/vec3f_test.html b/src/database/third_party/closure-library/closure/goog/vec/vec3f_test.html
    deleted file mode 100644
    index 32fe1dccb27..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/vec3f_test.html
    +++ /dev/null
    @@ -1,270 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -//                                                                           //
    -// Any edits to this file must be applied to vec3d_test.html by running:     //
    -//   swap_type.sh vec3f_test.html > vec3d_test.html                          //
    -//                                                                           //
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.vec.vec3f</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.vec.Float32Array');
    -  goog.require('goog.vec.vec3f');
    -  goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -  function testCreate() {
    -    var v = goog.vec.vec3f.create();
    -    assertElementsEquals([0, 0, 0], v);
    -  }
    -
    -  function testSet() {
    -    var v = goog.vec.vec3f.create();
    -    goog.vec.vec3f.setFromValues(v, 1, 2, 3);
    -    assertElementsEquals([1, 2, 3], v);
    -
    -    goog.vec.vec3f.setFromArray(v, [4, 5, 6]);
    -    assertElementsEquals([4, 5, 6], v);
    -
    -    var w = goog.vec.vec3f.create();
    -    goog.vec.vec3f.setFromValues(w, 1, 2, 3);
    -    assertElementsEquals([1, 2, 3], w);
    -
    -    goog.vec.vec3f.setFromArray(w, [4, 5, 6]);
    -    assertElementsEquals([4, 5, 6], w);
    -  }
    -
    -  function testAdd() {
    -    var v0 = goog.vec.vec3f.setFromArray(goog.vec.vec3f.create(), [1, 2, 3]);
    -    var v1 = goog.vec.vec3f.setFromArray(goog.vec.vec3f.create(), [4, 5, 6]);
    -    var v2 = goog.vec.vec3f.setFromVec3f(goog.vec.vec3f.create(), v0);
    -
    -    goog.vec.vec3f.add(v2, v1, v2);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals([4, 5, 6], v1);
    -    assertElementsEquals([5, 7, 9], v2);
    -
    -    goog.vec.vec3f.add(goog.vec.vec3f.add(v0, v1, v2), v0, v2);
    -    assertElementsEquals([6, 9, 12], v2);
    -  }
    -
    -  function testSubtract() {
    -    var v0 = goog.vec.vec3f.setFromArray(goog.vec.vec3f.create(), [1, 2, 3]);
    -    var v1 = goog.vec.vec3f.setFromArray(goog.vec.vec3f.create(), [4, 5, 6]);
    -    var v2 = goog.vec.vec3f.setFromVec3f(goog.vec.vec3f.create(), v0);
    -
    -    goog.vec.vec3f.subtract(v2, v1, v2);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals([4, 5, 6], v1);
    -    assertElementsEquals([-3, -3, -3], v2);
    -
    -    goog.vec.vec3f.setFromValues(v2, 0, 0, 0);
    -    goog.vec.vec3f.subtract(v1, v0, v2);
    -    assertElementsEquals([3, 3, 3], v2);
    -
    -    v2 = goog.vec.vec3f.setFromVec3f(goog.vec.vec3f.create(), v0);
    -    goog.vec.vec3f.subtract(v2, v1, v2);
    -    assertElementsEquals([-3, -3, -3], v2);
    -
    -    goog.vec.vec3f.subtract(goog.vec.vec3f.subtract(v1, v0, v2), v0, v2);
    -    assertElementsEquals([2, 1, 0], v2);
    -  }
    -
    -  function testNegate() {
    -    var v0 = goog.vec.vec3f.setFromArray(goog.vec.vec3f.create(), [1, 2, 3]);
    -    var v1 = goog.vec.vec3f.create();
    -
    -    goog.vec.vec3f.negate(v0, v1);
    -    assertElementsEquals([-1, -2, -3], v1);
    -    assertElementsEquals([1, 2, 3], v0);
    -
    -    goog.vec.vec3f.negate(v0, v0);
    -    assertElementsEquals([-1, -2, -3], v0);
    -  }
    -
    -  function testAbs() {
    -    var v0 = goog.vec.vec3f.setFromArray(goog.vec.vec3f.create(), [-1, -2, -3]);
    -    var v1 = goog.vec.vec3f.create();
    -
    -    goog.vec.vec3f.abs(v0, v1);
    -    assertElementsEquals([1, 2, 3], v1);
    -    assertElementsEquals([-1, -2, -3], v0);
    -
    -    goog.vec.vec3f.abs(v0, v0);
    -    assertElementsEquals([1, 2, 3], v0);
    -  }
    -
    -  function testScale() {
    -    var v0 = goog.vec.vec3f.setFromArray(goog.vec.vec3f.create(), [1, 2, 3]);
    -    var v1 = goog.vec.vec3f.create();
    -
    -    goog.vec.vec3f.scale(v0, 4, v1);
    -    assertElementsEquals([4, 8, 12], v1);
    -    assertElementsEquals([1, 2, 3], v0);
    -
    -    goog.vec.vec3f.setFromArray(v1, v0);
    -    goog.vec.vec3f.scale(v1, 5, v1);
    -    assertElementsEquals([5, 10, 15], v1);
    -  }
    -
    -  function testMagnitudeSquared() {
    -    var v0 = goog.vec.vec3f.setFromArray(goog.vec.vec3f.create(), [1, 2, 3]);
    -    assertEquals(14, goog.vec.vec3f.magnitudeSquared(v0));
    -  }
    -
    -  function testMagnitude() {
    -    var v0 = goog.vec.vec3f.setFromArray(goog.vec.vec3f.create(), [1, 2, 3]);
    -    assertEquals(Math.sqrt(14), goog.vec.vec3f.magnitude(v0));
    -  }
    -
    -  function testNormalize() {
    -    var v0 = goog.vec.vec3f.setFromArray(goog.vec.vec3f.create(), [2, 3, 4]);
    -    var v1 = goog.vec.vec3f.create();
    -    var v2 = goog.vec.vec3f.create();
    -    goog.vec.vec3f.scale(
    -        v0, 1 / goog.vec.vec3f.magnitude(v0), v2);
    -
    -    goog.vec.vec3f.normalize(v0, v1);
    -    assertElementsEquals(v2, v1);
    -    assertElementsEquals([2, 3, 4], v0);
    -
    -    goog.vec.vec3f.setFromArray(v1, v0);
    -    goog.vec.vec3f.normalize(v1, v1);
    -    assertElementsEquals(v2, v1);
    -  }
    -
    -  function testDot() {
    -    var v0 = goog.vec.vec3f.setFromArray(goog.vec.vec3f.create(), [1, 2, 3]);
    -    var v1 = goog.vec.vec3f.setFromArray(goog.vec.vec3f.create(), [4, 5, 6]);
    -    assertEquals(32, goog.vec.vec3f.dot(v0, v1));
    -    assertEquals(32, goog.vec.vec3f.dot(v1, v0));
    -  }
    -
    -  function testCross() {
    -    var v0 = goog.vec.vec3f.setFromArray(goog.vec.vec3f.create(), [1, 2, 3]);
    -    var v1 = goog.vec.vec3f.setFromArray(goog.vec.vec3f.create(), [4, 5, 6]);
    -    var crossVec = goog.vec.vec3f.create();
    -
    -    goog.vec.vec3f.cross(v0, v1, crossVec);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals([4, 5, 6], v1);
    -    assertElementsEquals([-3, 6, -3], crossVec);
    -
    -    goog.vec.vec3f.setFromArray(crossVec, v1);
    -    goog.vec.vec3f.cross(crossVec, v0, crossVec);
    -    assertElementsEquals([1, 2, 3], v0);
    -    assertElementsEquals([4, 5, 6], v1);
    -    assertElementsEquals([3, -6, 3], crossVec);
    -
    -    goog.vec.vec3f.cross(v0, v0, v0);
    -    assertElementsEquals([0, 0, 0], v0);
    -  }
    -
    -  function testDistanceSquared() {
    -    var v0 = goog.vec.vec3f.setFromValues(goog.vec.vec3f.create(), 1, 2, 3);
    -    var v1 = goog.vec.vec3f.setFromValues(goog.vec.vec3f.create(), 1, 2, 3);
    -    assertEquals(0, goog.vec.vec3f.distanceSquared(v0, v1));
    -    goog.vec.vec3f.setFromValues(v0, 1, 2, 3);
    -    goog.vec.vec3f.setFromValues(v1, -1, -2, -1);
    -    assertEquals(36, goog.vec.vec3f.distanceSquared(v0, v1));
    -  }
    -
    -  function testDistance() {
    -    var v0 = goog.vec.vec3f.setFromValues(goog.vec.vec3f.create(), 1, 2, 3);
    -    var v1 = goog.vec.vec3f.setFromValues(goog.vec.vec3f.create(), 1, 2, 3);
    -    assertEquals(0, goog.vec.vec3f.distance(v0, v1));
    -    goog.vec.vec3f.setFromValues(v0, 1, 2, 3);
    -    goog.vec.vec3f.setFromValues(v1, -1, -2, -1);
    -    assertEquals(6, goog.vec.vec3f.distance(v0, v1));
    -  }
    -
    -  function testDirection() {
    -    var v0 = goog.vec.vec3f.setFromValues(goog.vec.vec3f.create(), 1, 2, 3);
    -    var v1 = goog.vec.vec3f.setFromValues(goog.vec.vec3f.create(), 1, 2, 3);
    -    var dirVec = goog.vec.vec3f.setFromValues(goog.vec.vec3f.create(), 4, 5, 6);
    -    goog.vec.vec3f.direction(v0, v1, dirVec);
    -    assertElementsEquals([0, 0, 0], dirVec);
    -    goog.vec.vec3f.setFromValues(v0, 0, 0, 0);
    -    goog.vec.vec3f.setFromValues(v1, 1, 0, 0);
    -    goog.vec.vec3f.direction(v0, v1, dirVec);
    -    assertElementsEquals([1, 0, 0], dirVec);
    -    goog.vec.vec3f.setFromValues(v0, 1, 1, 1);
    -    goog.vec.vec3f.setFromValues(v1, 0, 0, 0);
    -    goog.vec.vec3f.direction(v0, v1, dirVec);
    -    assertElementsRoughlyEqual(
    -        [-0.5773502588272095, -0.5773502588272095, -0.5773502588272095],
    -        dirVec, goog.vec.EPSILON);
    -  }
    -
    -  function testLerp() {
    -    var v0 = goog.vec.vec3f.setFromValues(goog.vec.vec3f.create(), 1, 2, 3);
    -    var v1 = goog.vec.vec3f.setFromValues(goog.vec.vec3f.create(), 10, 20, 30);
    -    var v2 = goog.vec.vec3f.setFromVec3f(goog.vec.vec3f.create(), v0);
    -
    -    goog.vec.vec3f.lerp(v2, v1, 0, v2);
    -    assertElementsEquals([1, 2, 3], v2);
    -    goog.vec.vec3f.lerp(v2, v1, 1, v2);
    -    assertElementsEquals([10, 20, 30], v2);
    -    goog.vec.vec3f.lerp(v0, v1, .5, v2);
    -    assertElementsEquals([5.5, 11, 16.5], v2);
    -  }
    -
    -  function testMax() {
    -    var v0 = goog.vec.vec3f.setFromValues(goog.vec.vec3f.create(), 10, 20, 30);
    -    var v1 = goog.vec.vec3f.setFromValues(goog.vec.vec3f.create(), 5, 25, 35);
    -    var v2 = goog.vec.vec3f.create();
    -
    -    goog.vec.vec3f.max(v0, v1, v2);
    -    assertElementsEquals([10, 25, 35], v2);
    -    goog.vec.vec3f.max(v1, v0, v1);
    -    assertElementsEquals([10, 25, 35], v1);
    -    goog.vec.vec3f.max(v2, 20, v2);
    -    assertElementsEquals([20, 25, 35], v2);
    -  }
    -
    -  function testMin() {
    -    var v0 = goog.vec.vec3f.setFromValues(goog.vec.vec3f.create(), 10, 20, 30);
    -    var v1 = goog.vec.vec3f.setFromValues(goog.vec.vec3f.create(), 5, 25, 35);
    -    var v2 = goog.vec.vec3f.create();
    -
    -    goog.vec.vec3f.min(v0, v1, v2);
    -    assertElementsEquals([5, 20, 30], v2);
    -    goog.vec.vec3f.min(v1, v0, v1);
    -    assertElementsEquals([5, 20, 30], v1);
    -    goog.vec.vec3f.min(v2, 20, v2);
    -    assertElementsEquals([5, 20, 20], v2);
    -  }
    -
    -  function testEquals() {
    -    var v0 = goog.vec.vec3f.setFromValues(goog.vec.vec3f.create(), 1, 2, 3);
    -    var v1 = goog.vec.vec3f.setFromVec3f(goog.vec.vec3f.create(), v0);
    -    assertElementsEquals(v0, v1);
    -
    -    v1[0] = 4;
    -    assertFalse(goog.vec.vec3f.equals(v0, v1));
    -
    -    v1 = goog.vec.vec3f.setFromVec3f(goog.vec.vec3f.create(), v0);
    -    v1[1] = 4;
    -    assertFalse(goog.vec.vec3f.equals(v0, v1));
    -
    -    v1 = goog.vec.vec3f.setFromVec3f(goog.vec.vec3f.create(), v0);
    -    v1[2] = 4;
    -    assertFalse(goog.vec.vec3f.equals(v0, v1));
    -  }
    -
    -</script>
    -</body>
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/vec4.js b/src/database/third_party/closure-library/closure/goog/vec/vec4.js
    deleted file mode 100644
    index 3936a08ff88..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/vec4.js
    +++ /dev/null
    @@ -1,479 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Supplies 4 element vectors that are compatible with WebGL.
    - * Each element is a float32 since that is typically the desired size of a
    - * 4-vector in the GPU.  The API is structured to avoid unnecessary memory
    - * allocations.  The last parameter will typically be the output vector and
    - * an object can be both an input and output parameter to all methods except
    - * where noted.
    - *
    - */
    -goog.provide('goog.vec.Vec4');
    -
    -/** @suppress {extraRequire} */
    -goog.require('goog.vec');
    -
    -/** @typedef {goog.vec.Float32} */ goog.vec.Vec4.Float32;
    -/** @typedef {goog.vec.Float64} */ goog.vec.Vec4.Float64;
    -/** @typedef {goog.vec.Number} */ goog.vec.Vec4.Number;
    -/** @typedef {goog.vec.AnyType} */ goog.vec.Vec4.AnyType;
    -
    -// The following two types are deprecated - use the above types instead.
    -/** @typedef {Float32Array} */ goog.vec.Vec4.Type;
    -/** @typedef {goog.vec.ArrayType} */ goog.vec.Vec4.Vec4Like;
    -
    -
    -/**
    - * Creates a 4 element vector of Float32. The array is initialized to zero.
    - *
    - * @return {!goog.vec.Vec4.Float32} The new 3 element array.
    - */
    -goog.vec.Vec4.createFloat32 = function() {
    -  return new Float32Array(4);
    -};
    -
    -
    -/**
    - * Creates a 4 element vector of Float64. The array is initialized to zero.
    - *
    - * @return {!goog.vec.Vec4.Float64} The new 4 element array.
    - */
    -goog.vec.Vec4.createFloat64 = function() {
    -  return new Float64Array(4);
    -};
    -
    -
    -/**
    - * Creates a 4 element vector of Number. The array is initialized to zero.
    - *
    - * @return {!goog.vec.Vec4.Number} The new 4 element array.
    - */
    -goog.vec.Vec4.createNumber = function() {
    -  var v = new Array(4);
    -  goog.vec.Vec4.setFromValues(v, 0, 0, 0, 0);
    -  return v;
    -};
    -
    -
    -/**
    - * Creates a 4 element vector of Float32Array. The array is initialized to zero.
    - *
    - * @deprecated Use createFloat32.
    - * @return {!goog.vec.Vec4.Type} The new 4 element array.
    - */
    -goog.vec.Vec4.create = function() {
    -  return new Float32Array(4);
    -};
    -
    -
    -/**
    - * Creates a new 4 element vector initialized with the value from the given
    - * array.
    - *
    - * @deprecated Use createFloat32FromArray.
    - * @param {goog.vec.Vec4.Vec4Like} vec The source 4 element array.
    - * @return {!goog.vec.Vec4.Type} The new 4 element array.
    - */
    -goog.vec.Vec4.createFromArray = function(vec) {
    -  var newVec = goog.vec.Vec4.create();
    -  goog.vec.Vec4.setFromArray(newVec, vec);
    -  return newVec;
    -};
    -
    -
    -/**
    - * Creates a new 4 element FLoat32 vector initialized with the value from the
    - * given array.
    - *
    - * @param {goog.vec.Vec4.AnyType} vec The source 3 element array.
    - * @return {!goog.vec.Vec4.Float32} The new 3 element array.
    - */
    -goog.vec.Vec4.createFloat32FromArray = function(vec) {
    -  var newVec = goog.vec.Vec4.createFloat32();
    -  goog.vec.Vec4.setFromArray(newVec, vec);
    -  return newVec;
    -};
    -
    -
    -/**
    - * Creates a new 4 element Float32 vector initialized with the supplied values.
    - *
    - * @param {number} v0 The value for element at index 0.
    - * @param {number} v1 The value for element at index 1.
    - * @param {number} v2 The value for element at index 2.
    - * @param {number} v3 The value for element at index 3.
    - * @return {!goog.vec.Vec4.Float32} The new vector.
    - */
    -goog.vec.Vec4.createFloat32FromValues = function(v0, v1, v2, v3) {
    -  var vec = goog.vec.Vec4.createFloat32();
    -  goog.vec.Vec4.setFromValues(vec, v0, v1, v2, v3);
    -  return vec;
    -};
    -
    -
    -/**
    - * Creates a clone of the given 4 element Float32 vector.
    - *
    - * @param {goog.vec.Vec4.Float32} vec The source 3 element vector.
    - * @return {!goog.vec.Vec4.Float32} The new cloned vector.
    - */
    -goog.vec.Vec4.cloneFloat32 = goog.vec.Vec4.createFloat32FromArray;
    -
    -
    -/**
    - * Creates a new 4 element Float64 vector initialized with the value from the
    - * given array.
    - *
    - * @param {goog.vec.Vec4.AnyType} vec The source 4 element array.
    - * @return {!goog.vec.Vec4.Float64} The new 4 element array.
    - */
    -goog.vec.Vec4.createFloat64FromArray = function(vec) {
    -  var newVec = goog.vec.Vec4.createFloat64();
    -  goog.vec.Vec4.setFromArray(newVec, vec);
    -  return newVec;
    -};
    -
    -
    -/**
    -* Creates a new 4 element Float64 vector initialized with the supplied values.
    -*
    -* @param {number} v0 The value for element at index 0.
    -* @param {number} v1 The value for element at index 1.
    -* @param {number} v2 The value for element at index 2.
    -* @param {number} v3 The value for element at index 3.
    -* @return {!goog.vec.Vec4.Float64} The new vector.
    -*/
    -goog.vec.Vec4.createFloat64FromValues = function(v0, v1, v2, v3) {
    -  var vec = goog.vec.Vec4.createFloat64();
    -  goog.vec.Vec4.setFromValues(vec, v0, v1, v2, v3);
    -  return vec;
    -};
    -
    -
    -/**
    - * Creates a clone of the given 4 element vector.
    - *
    - * @param {goog.vec.Vec4.Float64} vec The source 4 element vector.
    - * @return {!goog.vec.Vec4.Float64} The new cloned vector.
    - */
    -goog.vec.Vec4.cloneFloat64 = goog.vec.Vec4.createFloat64FromArray;
    -
    -
    -/**
    - * Creates a new 4 element vector initialized with the supplied values.
    - *
    - * @deprecated Use createFloat32FromValues.
    - * @param {number} v0 The value for element at index 0.
    - * @param {number} v1 The value for element at index 1.
    - * @param {number} v2 The value for element at index 2.
    - * @param {number} v3 The value for element at index 3.
    - * @return {!goog.vec.Vec4.Type} The new vector.
    - */
    -goog.vec.Vec4.createFromValues = function(v0, v1, v2, v3) {
    -  var vec = goog.vec.Vec4.create();
    -  goog.vec.Vec4.setFromValues(vec, v0, v1, v2, v3);
    -  return vec;
    -};
    -
    -
    -/**
    - * Creates a clone of the given 4 element vector.
    - *
    - * @deprecated Use cloneFloat32.
    - * @param {goog.vec.Vec4.Vec4Like} vec The source 4 element vector.
    - * @return {!goog.vec.Vec4.Type} The new cloned vector.
    - */
    -goog.vec.Vec4.clone = goog.vec.Vec4.createFromArray;
    -
    -
    -/**
    - * Initializes the vector with the given values.
    - *
    - * @param {goog.vec.Vec4.AnyType} vec The vector to receive the values.
    - * @param {number} v0 The value for element at index 0.
    - * @param {number} v1 The value for element at index 1.
    - * @param {number} v2 The value for element at index 2.
    - * @param {number} v3 The value for element at index 3.
    - * @return {!goog.vec.Vec4.AnyType} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec4.setFromValues = function(vec, v0, v1, v2, v3) {
    -  vec[0] = v0;
    -  vec[1] = v1;
    -  vec[2] = v2;
    -  vec[3] = v3;
    -  return vec;
    -};
    -
    -
    -/**
    - * Initializes the vector with the given array of values.
    - *
    - * @param {goog.vec.Vec4.AnyType} vec The vector to receive the
    - *     values.
    - * @param {goog.vec.Vec4.AnyType} values The array of values.
    - * @return {!goog.vec.Vec4.AnyType} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec4.setFromArray = function(vec, values) {
    -  vec[0] = values[0];
    -  vec[1] = values[1];
    -  vec[2] = values[2];
    -  vec[3] = values[3];
    -  return vec;
    -};
    -
    -
    -/**
    - * Performs a component-wise addition of vec0 and vec1 together storing the
    - * result into resultVec.
    - *
    - * @param {goog.vec.Vec4.AnyType} vec0 The first addend.
    - * @param {goog.vec.Vec4.AnyType} vec1 The second addend.
    - * @param {goog.vec.Vec4.AnyType} resultVec The vector to
    - *     receive the result. May be vec0 or vec1.
    - * @return {!goog.vec.Vec4.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec4.add = function(vec0, vec1, resultVec) {
    -  resultVec[0] = vec0[0] + vec1[0];
    -  resultVec[1] = vec0[1] + vec1[1];
    -  resultVec[2] = vec0[2] + vec1[2];
    -  resultVec[3] = vec0[3] + vec1[3];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Performs a component-wise subtraction of vec1 from vec0 storing the
    - * result into resultVec.
    - *
    - * @param {goog.vec.Vec4.AnyType} vec0 The minuend.
    - * @param {goog.vec.Vec4.AnyType} vec1 The subtrahend.
    - * @param {goog.vec.Vec4.AnyType} resultVec The vector to
    - *     receive the result. May be vec0 or vec1.
    - * @return {!goog.vec.Vec4.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec4.subtract = function(vec0, vec1, resultVec) {
    -  resultVec[0] = vec0[0] - vec1[0];
    -  resultVec[1] = vec0[1] - vec1[1];
    -  resultVec[2] = vec0[2] - vec1[2];
    -  resultVec[3] = vec0[3] - vec1[3];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Negates vec0, storing the result into resultVec.
    - *
    - * @param {goog.vec.Vec4.AnyType} vec0 The vector to negate.
    - * @param {goog.vec.Vec4.AnyType} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.Vec4.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec4.negate = function(vec0, resultVec) {
    -  resultVec[0] = -vec0[0];
    -  resultVec[1] = -vec0[1];
    -  resultVec[2] = -vec0[2];
    -  resultVec[3] = -vec0[3];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Takes the absolute value of each component of vec0 storing the result in
    - * resultVec.
    - *
    - * @param {goog.vec.Vec4.AnyType} vec0 The source vector.
    - * @param {goog.vec.Vec4.AnyType} resultVec The vector to receive the result.
    - *     May be vec0.
    - * @return {!goog.vec.Vec4.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec4.abs = function(vec0, resultVec) {
    -  resultVec[0] = Math.abs(vec0[0]);
    -  resultVec[1] = Math.abs(vec0[1]);
    -  resultVec[2] = Math.abs(vec0[2]);
    -  resultVec[3] = Math.abs(vec0[3]);
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Multiplies each component of vec0 with scalar storing the product into
    - * resultVec.
    - *
    - * @param {goog.vec.Vec4.AnyType} vec0 The source vector.
    - * @param {number} scalar The value to multiply with each component of vec0.
    - * @param {goog.vec.Vec4.AnyType} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.Vec4.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec4.scale = function(vec0, scalar, resultVec) {
    -  resultVec[0] = vec0[0] * scalar;
    -  resultVec[1] = vec0[1] * scalar;
    -  resultVec[2] = vec0[2] * scalar;
    -  resultVec[3] = vec0[3] * scalar;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns the magnitudeSquared of the given vector.
    - *
    - * @param {goog.vec.Vec4.AnyType} vec0 The vector.
    - * @return {number} The magnitude of the vector.
    - */
    -goog.vec.Vec4.magnitudeSquared = function(vec0) {
    -  var x = vec0[0], y = vec0[1], z = vec0[2], w = vec0[3];
    -  return x * x + y * y + z * z + w * w;
    -};
    -
    -
    -/**
    - * Returns the magnitude of the given vector.
    - *
    - * @param {goog.vec.Vec4.AnyType} vec0 The vector.
    - * @return {number} The magnitude of the vector.
    - */
    -goog.vec.Vec4.magnitude = function(vec0) {
    -  var x = vec0[0], y = vec0[1], z = vec0[2], w = vec0[3];
    -  return Math.sqrt(x * x + y * y + z * z + w * w);
    -};
    -
    -
    -/**
    - * Normalizes the given vector storing the result into resultVec.
    - *
    - * @param {goog.vec.Vec4.AnyType} vec0 The vector to normalize.
    - * @param {goog.vec.Vec4.AnyType} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.Vec4.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec4.normalize = function(vec0, resultVec) {
    -  var ilen = 1 / goog.vec.Vec4.magnitude(vec0);
    -  resultVec[0] = vec0[0] * ilen;
    -  resultVec[1] = vec0[1] * ilen;
    -  resultVec[2] = vec0[2] * ilen;
    -  resultVec[3] = vec0[3] * ilen;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns the scalar product of vectors v0 and v1.
    - *
    - * @param {goog.vec.Vec4.AnyType} v0 The first vector.
    - * @param {goog.vec.Vec4.AnyType} v1 The second vector.
    - * @return {number} The scalar product.
    - */
    -goog.vec.Vec4.dot = function(v0, v1) {
    -  return v0[0] * v1[0] + v0[1] * v1[1] + v0[2] * v1[2] + v0[3] * v1[3];
    -};
    -
    -
    -/**
    - * Linearly interpolate from v0 to v1 according to f. The value of f should be
    - * in the range [0..1] otherwise the results are undefined.
    - *
    - * @param {goog.vec.Vec4.AnyType} v0 The first vector.
    - * @param {goog.vec.Vec4.AnyType} v1 The second vector.
    - * @param {number} f The interpolation factor.
    - * @param {goog.vec.Vec4.AnyType} resultVec The vector to receive the
    - *     results (may be v0 or v1).
    - * @return {!goog.vec.Vec4.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec4.lerp = function(v0, v1, f, resultVec) {
    -  var x = v0[0], y = v0[1], z = v0[2], w = v0[3];
    -  resultVec[0] = (v1[0] - x) * f + x;
    -  resultVec[1] = (v1[1] - y) * f + y;
    -  resultVec[2] = (v1[2] - z) * f + z;
    -  resultVec[3] = (v1[3] - w) * f + w;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Compares the components of vec0 with the components of another vector or
    - * scalar, storing the larger values in resultVec.
    - *
    - * @param {goog.vec.Vec4.AnyType} vec0 The source vector.
    - * @param {goog.vec.Vec4.AnyType|number} limit The limit vector or scalar.
    - * @param {goog.vec.Vec4.AnyType} resultVec The vector to receive the
    - *     results (may be vec0 or limit).
    - * @return {!goog.vec.Vec4.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec4.max = function(vec0, limit, resultVec) {
    -  if (goog.isNumber(limit)) {
    -    resultVec[0] = Math.max(vec0[0], limit);
    -    resultVec[1] = Math.max(vec0[1], limit);
    -    resultVec[2] = Math.max(vec0[2], limit);
    -    resultVec[3] = Math.max(vec0[3], limit);
    -  } else {
    -    resultVec[0] = Math.max(vec0[0], limit[0]);
    -    resultVec[1] = Math.max(vec0[1], limit[1]);
    -    resultVec[2] = Math.max(vec0[2], limit[2]);
    -    resultVec[3] = Math.max(vec0[3], limit[3]);
    -  }
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Compares the components of vec0 with the components of another vector or
    - * scalar, storing the smaller values in resultVec.
    - *
    - * @param {goog.vec.Vec4.AnyType} vec0 The source vector.
    - * @param {goog.vec.Vec4.AnyType|number} limit The limit vector or scalar.
    - * @param {goog.vec.Vec4.AnyType} resultVec The vector to receive the
    - *     results (may be vec0 or limit).
    - * @return {!goog.vec.Vec4.AnyType} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.Vec4.min = function(vec0, limit, resultVec) {
    -  if (goog.isNumber(limit)) {
    -    resultVec[0] = Math.min(vec0[0], limit);
    -    resultVec[1] = Math.min(vec0[1], limit);
    -    resultVec[2] = Math.min(vec0[2], limit);
    -    resultVec[3] = Math.min(vec0[3], limit);
    -  } else {
    -    resultVec[0] = Math.min(vec0[0], limit[0]);
    -    resultVec[1] = Math.min(vec0[1], limit[1]);
    -    resultVec[2] = Math.min(vec0[2], limit[2]);
    -    resultVec[3] = Math.min(vec0[3], limit[3]);
    -  }
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns true if the components of v0 are equal to the components of v1.
    - *
    - * @param {goog.vec.Vec4.AnyType} v0 The first vector.
    - * @param {goog.vec.Vec4.AnyType} v1 The second vector.
    - * @return {boolean} True if the vectors are equal, false otherwise.
    - */
    -goog.vec.Vec4.equals = function(v0, v1) {
    -  return v0.length == v1.length &&
    -      v0[0] == v1[0] && v0[1] == v1[1] && v0[2] == v1[2] && v0[3] == v1[3];
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/vec4_test.html b/src/database/third_party/closure-library/closure/goog/vec/vec4_test.html
    deleted file mode 100644
    index e66ac6df1c3..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/vec4_test.html
    +++ /dev/null
    @@ -1,230 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.vec.Vec4</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.vec.Float32Array');
    -  goog.require('goog.vec.Vec4');
    -  goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -  function testDeprecatedConstructor() {
    -    assertElementsEquals([0, 0, 0, 0], goog.vec.Vec4.create());
    -
    -    assertElementsEquals([1, 2, 3, 4],
    -        goog.vec.Vec4.createFromValues(1, 2, 3, 4));
    -
    -    assertElementsEquals([1, 2, 3, 4],
    -        goog.vec.Vec4.createFromArray([1, 2, 3, 4]));
    -
    -    var v = goog.vec.Vec4.createFromValues(1, 2, 3, 4);
    -    assertElementsEquals([1, 2, 3, 4], goog.vec.Vec4.clone(v));
    -  }
    -
    -  function testConstructor() {
    -    assertElementsEquals([0, 0, 0, 0], goog.vec.Vec4.createFloat32());
    -
    -    assertElementsEquals([1, 2, 3, 4],
    -        goog.vec.Vec4.createFloat32FromValues(1, 2, 3, 4));
    -
    -    assertElementsEquals([1, 2, 3, 4],
    -        goog.vec.Vec4.createFloat32FromArray([1, 2, 3, 4]));
    -
    -    var v = goog.vec.Vec4.createFloat32FromValues(1, 2, 3, 4);
    -    assertElementsEquals([1, 2, 3, 4], goog.vec.Vec4.cloneFloat32(v));
    -
    -    assertElementsEquals([0, 0, 0, 0], goog.vec.Vec4.createFloat64());
    -
    -    assertElementsEquals([1, 2, 3, 4],
    -        goog.vec.Vec4.createFloat64FromValues(1, 2, 3, 4));
    -
    -    assertElementsEquals([1, 2, 3, 4],
    -        goog.vec.Vec4.createFloat64FromArray([1, 2, 3, 4]));
    -
    -    var w = goog.vec.Vec4.createFloat64FromValues(1, 2, 3, 4);
    -    assertElementsEquals([1, 2, 3, 4], goog.vec.Vec4.cloneFloat64(w));
    -  }
    -
    -  function testSet() {
    -    var v = goog.vec.Vec4.createFloat32();
    -    goog.vec.Vec4.setFromValues(v, 1, 2, 3, 4);
    -    assertElementsEquals([1, 2, 3, 4], v);
    -
    -    goog.vec.Vec4.setFromArray(v, [4, 5, 6, 7]);
    -    assertElementsEquals([4, 5, 6, 7], v);
    -  }
    -
    -  function testAdd() {
    -    var v0 = goog.vec.Vec4.createFloat32FromArray([1, 2, 3, 4]);
    -    var v1 = goog.vec.Vec4.createFloat32FromArray([5, 6, 7, 8]);
    -    var v2 = goog.vec.Vec4.cloneFloat32(v0);
    -
    -    goog.vec.Vec4.add(v2, v1, v2);
    -    assertElementsEquals([1, 2, 3, 4], v0);
    -    assertElementsEquals([5, 6, 7, 8], v1);
    -    assertElementsEquals([6, 8, 10, 12], v2);
    -
    -    goog.vec.Vec4.add(goog.vec.Vec4.add(v0, v1, v2), v0, v2);
    -    assertElementsEquals([7, 10, 13, 16], v2);
    -  }
    -
    -  function testSubtract() {
    -    var v0 = goog.vec.Vec4.createFloat32FromArray([4, 3, 2, 1]);
    -    var v1 = goog.vec.Vec4.createFloat32FromArray([5, 6, 7, 8]);
    -    var v2 = goog.vec.Vec4.cloneFloat32(v0);
    -
    -    goog.vec.Vec4.subtract(v2, v1, v2);
    -    assertElementsEquals([4, 3, 2, 1], v0);
    -    assertElementsEquals([5, 6, 7, 8], v1);
    -    assertElementsEquals([-1, -3, -5, -7], v2);
    -
    -    goog.vec.Vec4.setFromValues(v2, 0, 0, 0, 0);
    -    goog.vec.Vec4.subtract(v1, v0, v2);
    -    assertElementsEquals([1, 3, 5, 7], v2);
    -
    -    goog.vec.Vec4.subtract(goog.vec.Vec4.subtract(v1, v0, v2), v0, v2);
    -    assertElementsEquals([-3, 0, 3, 6], v2);
    -  }
    -
    -  function testNegate() {
    -    var v0 = goog.vec.Vec4.createFloat32FromArray([1, 2, 3, 4]);
    -    var v1 = goog.vec.Vec4.createFloat32();
    -
    -    goog.vec.Vec4.negate(v0, v1);
    -    assertElementsEquals([-1, -2, -3, -4], v1);
    -    assertElementsEquals([1, 2, 3, 4], v0);
    -
    -    goog.vec.Vec4.negate(v0, v0);
    -    assertElementsEquals([-1, -2, -3, -4], v0);
    -  }
    -
    -  function testAbs() {
    -    var v0 = goog.vec.Vec4.createFloat32FromValues(-1, -2, -3, -4);
    -    var v1 = goog.vec.Vec4.createFloat32();
    -
    -    goog.vec.Vec4.abs(v0, v1);
    -    assertElementsEquals([1, 2, 3, 4], v1);
    -    assertElementsEquals([-1, -2, -3, -4], v0);
    -
    -    goog.vec.Vec4.abs(v0, v0);
    -    assertElementsEquals([1, 2, 3, 4], v0);
    -  }
    -
    -  function testScale() {
    -    var v0 = goog.vec.Vec4.createFloat32FromArray([1, 2, 3, 4]);
    -    var v1 = goog.vec.Vec4.createFloat32();
    -
    -    goog.vec.Vec4.scale(v0, 4, v1);
    -    assertElementsEquals([4, 8, 12, 16], v1);
    -    assertElementsEquals([1, 2, 3, 4], v0);
    -
    -    goog.vec.Vec4.setFromArray(v1, v0);
    -    goog.vec.Vec4.scale(v1, 5, v1);
    -    assertElementsEquals([5, 10, 15, 20], v1);
    -  }
    -
    -  function testMagnitudeSquared() {
    -    var v0 = goog.vec.Vec4.createFloat32FromArray([1, 2, 3, 4]);
    -    assertEquals(30, goog.vec.Vec4.magnitudeSquared(v0));
    -  }
    -
    -  function testMagnitude() {
    -    var v0 = goog.vec.Vec4.createFloat32FromArray([1, 2, 3, 4]);
    -    assertEquals(Math.sqrt(30), goog.vec.Vec4.magnitude(v0));
    -  }
    -
    -  function testNormalize() {
    -    var v0 = goog.vec.Vec4.createFloat32FromArray([2, 3, 4, 5]);
    -    var v1 = goog.vec.Vec4.createFloat32();
    -    var v2 = goog.vec.Vec4.createFloat32();
    -    goog.vec.Vec4.scale(v0, 1 / goog.vec.Vec4.magnitude(v0), v2);
    -
    -    goog.vec.Vec4.normalize(v0, v1);
    -    assertElementsEquals(v2, v1);
    -    assertElementsEquals([2, 3, 4, 5], v0);
    -
    -    goog.vec.Vec4.setFromArray(v1, v0);
    -    goog.vec.Vec4.normalize(v1, v1);
    -    assertElementsEquals(v2, v1);
    -  }
    -
    -  function testDot() {
    -    var v0 = goog.vec.Vec4.createFloat32FromArray([1, 2, 3, 4]);
    -    var v1 = goog.vec.Vec4.createFloat32FromArray([5, 6, 7, 8]);
    -    assertEquals(70, goog.vec.Vec4.dot(v0, v1));
    -    assertEquals(70, goog.vec.Vec4.dot(v1, v0));
    -  }
    -
    -  function testLerp() {
    -    var v0 = goog.vec.Vec4.createFloat32FromValues(1, 2, 3, 4);
    -    var v1 = goog.vec.Vec4.createFloat32FromValues(10, 20, 30, 40);
    -    var v2 = goog.vec.Vec4.cloneFloat32(v0);
    -
    -    goog.vec.Vec4.lerp(v2, v1, 0, v2);
    -    assertElementsEquals([1, 2, 3, 4], v2);
    -    goog.vec.Vec4.lerp(v2, v1, 1, v2);
    -    assertElementsEquals([10, 20, 30, 40], v2);
    -    goog.vec.Vec4.lerp(v0, v1, .5, v2);
    -    assertElementsEquals([5.5, 11, 16.5, 22], v2);
    -  }
    -
    -  function testMax() {
    -    var v0 = goog.vec.Vec4.createFloat32FromValues(10, 20, 30, 40);
    -    var v1 = goog.vec.Vec4.createFloat32FromValues(5, 25, 35, 30);
    -    var v2 = goog.vec.Vec4.createFloat32();
    -
    -    goog.vec.Vec4.max(v0, v1, v2);
    -    assertElementsEquals([10, 25, 35, 40], v2);
    -    goog.vec.Vec4.max(v1, v0, v1);
    -    assertElementsEquals([10, 25, 35, 40], v1);
    -    goog.vec.Vec4.max(v2, 20, v2);
    -    assertElementsEquals([20, 25, 35, 40], v2);
    -  }
    -
    -  function testMin() {
    -    var v0 = goog.vec.Vec4.createFloat32FromValues(10, 20, 30, 40);
    -    var v1 = goog.vec.Vec4.createFloat32FromValues(5, 25, 35, 30);
    -    var v2 = goog.vec.Vec4.createFloat32();
    -
    -    goog.vec.Vec4.min(v0, v1, v2);
    -    assertElementsEquals([5, 20, 30, 30], v2);
    -    goog.vec.Vec4.min(v1, v0, v1);
    -    assertElementsEquals([5, 20, 30, 30], v1);
    -    goog.vec.Vec4.min(v2, 20, v2);
    -    assertElementsEquals([5, 20, 20, 20], v2);
    -  }
    -
    -  function testEquals() {
    -    var v0 = goog.vec.Vec4.createFloat32FromValues(1, 2, 3, 4);
    -    var v1 = goog.vec.Vec4.cloneFloat32(v0);
    -    assertElementsEquals(v0, v1);
    -
    -    v1[0] = 5;
    -    assertFalse(goog.vec.Vec4.equals(v0, v1));
    -
    -    v1 = goog.vec.Vec4.cloneFloat32(v0);
    -    v1[1] = 5;
    -    assertFalse(goog.vec.Vec4.equals(v0, v1));
    -
    -    v1 = goog.vec.Vec4.cloneFloat32(v0);
    -    v1[2] = 5;
    -    assertFalse(goog.vec.Vec4.equals(v0, v1));
    -
    -    v1 = goog.vec.Vec4.cloneFloat32(v0);
    -    v1[3] = 5;
    -    assertFalse(goog.vec.Vec4.equals(v0, v1));
    -  }
    -
    -</script>
    -</body>
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/vec4d.js b/src/database/third_party/closure-library/closure/goog/vec/vec4d.js
    deleted file mode 100644
    index b0baa41149b..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/vec4d.js
    +++ /dev/null
    @@ -1,366 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -//                                                                           //
    -// Any edits to this file must be applied to vec4f.js by running:            //
    -//   swap_type.sh vec4d.js > vec4f.js                                        //
    -//                                                                           //
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -
    -
    -/**
    - * @fileoverview Provides functions for operating on 4 element double (64bit)
    - * vectors.
    - *
    - * The last parameter will typically be the output object and an object
    - * can be both an input and output parameter to all methods except where
    - * noted.
    - *
    - * See the README for notes about the design and structure of the API
    - * (especially related to performance).
    - *
    - */
    -goog.provide('goog.vec.vec4d');
    -goog.provide('goog.vec.vec4d.Type');
    -
    -/** @suppress {extraRequire} */
    -goog.require('goog.vec');
    -
    -/** @typedef {goog.vec.Float64} */ goog.vec.vec4d.Type;
    -
    -
    -/**
    - * Creates a vec4d with all elements initialized to zero.
    - *
    - * @return {!goog.vec.vec4d.Type} The new vec4d.
    - */
    -goog.vec.vec4d.create = function() {
    -  return new Float64Array(4);
    -};
    -
    -
    -/**
    - * Initializes the vector with the given values.
    - *
    - * @param {goog.vec.vec4d.Type} vec The vector to receive the values.
    - * @param {number} v0 The value for element at index 0.
    - * @param {number} v1 The value for element at index 1.
    - * @param {number} v2 The value for element at index 2.
    - * @param {number} v3 The value for element at index 3.
    - * @return {!goog.vec.vec4d.Type} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec4d.setFromValues = function(vec, v0, v1, v2, v3) {
    -  vec[0] = v0;
    -  vec[1] = v1;
    -  vec[2] = v2;
    -  vec[3] = v3;
    -  return vec;
    -};
    -
    -
    -/**
    - * Initializes vec4d vec from vec4d src.
    - *
    - * @param {goog.vec.vec4d.Type} vec The destination vector.
    - * @param {goog.vec.vec4d.Type} src The source vector.
    - * @return {!goog.vec.vec4d.Type} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec4d.setFromVec4d = function(vec, src) {
    -  vec[0] = src[0];
    -  vec[1] = src[1];
    -  vec[2] = src[2];
    -  vec[3] = src[3];
    -  return vec;
    -};
    -
    -
    -/**
    - * Initializes vec4d vec from vec4f src (typed as a Float32Array to
    - * avoid circular goog.requires).
    - *
    - * @param {goog.vec.vec4d.Type} vec The destination vector.
    - * @param {Float32Array} src The source vector.
    - * @return {!goog.vec.vec4d.Type} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec4d.setFromVec4f = function(vec, src) {
    -  vec[0] = src[0];
    -  vec[1] = src[1];
    -  vec[2] = src[2];
    -  vec[3] = src[3];
    -  return vec;
    -};
    -
    -
    -/**
    - * Initializes vec4d vec from Array src.
    - *
    - * @param {goog.vec.vec4d.Type} vec The destination vector.
    - * @param {Array<number>} src The source vector.
    - * @return {!goog.vec.vec4d.Type} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec4d.setFromArray = function(vec, src) {
    -  vec[0] = src[0];
    -  vec[1] = src[1];
    -  vec[2] = src[2];
    -  vec[3] = src[3];
    -  return vec;
    -};
    -
    -
    -/**
    - * Performs a component-wise addition of vec0 and vec1 together storing the
    - * result into resultVec.
    - *
    - * @param {goog.vec.vec4d.Type} vec0 The first addend.
    - * @param {goog.vec.vec4d.Type} vec1 The second addend.
    - * @param {goog.vec.vec4d.Type} resultVec The vector to
    - *     receive the result. May be vec0 or vec1.
    - * @return {!goog.vec.vec4d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec4d.add = function(vec0, vec1, resultVec) {
    -  resultVec[0] = vec0[0] + vec1[0];
    -  resultVec[1] = vec0[1] + vec1[1];
    -  resultVec[2] = vec0[2] + vec1[2];
    -  resultVec[3] = vec0[3] + vec1[3];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Performs a component-wise subtraction of vec1 from vec0 storing the
    - * result into resultVec.
    - *
    - * @param {goog.vec.vec4d.Type} vec0 The minuend.
    - * @param {goog.vec.vec4d.Type} vec1 The subtrahend.
    - * @param {goog.vec.vec4d.Type} resultVec The vector to
    - *     receive the result. May be vec0 or vec1.
    - * @return {!goog.vec.vec4d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec4d.subtract = function(vec0, vec1, resultVec) {
    -  resultVec[0] = vec0[0] - vec1[0];
    -  resultVec[1] = vec0[1] - vec1[1];
    -  resultVec[2] = vec0[2] - vec1[2];
    -  resultVec[3] = vec0[3] - vec1[3];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Negates vec0, storing the result into resultVec.
    - *
    - * @param {goog.vec.vec4d.Type} vec0 The vector to negate.
    - * @param {goog.vec.vec4d.Type} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.vec4d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec4d.negate = function(vec0, resultVec) {
    -  resultVec[0] = -vec0[0];
    -  resultVec[1] = -vec0[1];
    -  resultVec[2] = -vec0[2];
    -  resultVec[3] = -vec0[3];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Takes the absolute value of each component of vec0 storing the result in
    - * resultVec.
    - *
    - * @param {goog.vec.vec4d.Type} vec0 The source vector.
    - * @param {goog.vec.vec4d.Type} resultVec The vector to receive the result.
    - *     May be vec0.
    - * @return {!goog.vec.vec4d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec4d.abs = function(vec0, resultVec) {
    -  resultVec[0] = Math.abs(vec0[0]);
    -  resultVec[1] = Math.abs(vec0[1]);
    -  resultVec[2] = Math.abs(vec0[2]);
    -  resultVec[3] = Math.abs(vec0[3]);
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Multiplies each component of vec0 with scalar storing the product into
    - * resultVec.
    - *
    - * @param {goog.vec.vec4d.Type} vec0 The source vector.
    - * @param {number} scalar The value to multiply with each component of vec0.
    - * @param {goog.vec.vec4d.Type} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.vec4d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec4d.scale = function(vec0, scalar, resultVec) {
    -  resultVec[0] = vec0[0] * scalar;
    -  resultVec[1] = vec0[1] * scalar;
    -  resultVec[2] = vec0[2] * scalar;
    -  resultVec[3] = vec0[3] * scalar;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns the magnitudeSquared of the given vector.
    - *
    - * @param {goog.vec.vec4d.Type} vec0 The vector.
    - * @return {number} The magnitude of the vector.
    - */
    -goog.vec.vec4d.magnitudeSquared = function(vec0) {
    -  var x = vec0[0], y = vec0[1], z = vec0[2], w = vec0[3];
    -  return x * x + y * y + z * z + w * w;
    -};
    -
    -
    -/**
    - * Returns the magnitude of the given vector.
    - *
    - * @param {goog.vec.vec4d.Type} vec0 The vector.
    - * @return {number} The magnitude of the vector.
    - */
    -goog.vec.vec4d.magnitude = function(vec0) {
    -  var x = vec0[0], y = vec0[1], z = vec0[2], w = vec0[3];
    -  return Math.sqrt(x * x + y * y + z * z + w * w);
    -};
    -
    -
    -/**
    - * Normalizes the given vector storing the result into resultVec.
    - *
    - * @param {goog.vec.vec4d.Type} vec0 The vector to normalize.
    - * @param {goog.vec.vec4d.Type} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.vec4d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec4d.normalize = function(vec0, resultVec) {
    -  var x = vec0[0], y = vec0[1], z = vec0[2], w = vec0[3];
    -  var ilen = 1 / Math.sqrt(x * x + y * y + z * z + w * w);
    -  resultVec[0] = x * ilen;
    -  resultVec[1] = y * ilen;
    -  resultVec[2] = z * ilen;
    -  resultVec[3] = w * ilen;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns the scalar product of vectors v0 and v1.
    - *
    - * @param {goog.vec.vec4d.Type} v0 The first vector.
    - * @param {goog.vec.vec4d.Type} v1 The second vector.
    - * @return {number} The scalar product.
    - */
    -goog.vec.vec4d.dot = function(v0, v1) {
    -  return v0[0] * v1[0] + v0[1] * v1[1] + v0[2] * v1[2] + v0[3] * v1[3];
    -};
    -
    -
    -/**
    - * Linearly interpolate from v0 to v1 according to f. The value of f should be
    - * in the range [0..1] otherwise the results are undefined.
    - *
    - * @param {goog.vec.vec4d.Type} v0 The first vector.
    - * @param {goog.vec.vec4d.Type} v1 The second vector.
    - * @param {number} f The interpolation factor.
    - * @param {goog.vec.vec4d.Type} resultVec The vector to receive the
    - *     results (may be v0 or v1).
    - * @return {!goog.vec.vec4d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec4d.lerp = function(v0, v1, f, resultVec) {
    -  var x = v0[0], y = v0[1], z = v0[2], w = v0[3];
    -  resultVec[0] = (v1[0] - x) * f + x;
    -  resultVec[1] = (v1[1] - y) * f + y;
    -  resultVec[2] = (v1[2] - z) * f + z;
    -  resultVec[3] = (v1[3] - w) * f + w;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Compares the components of vec0 with the components of another vector or
    - * scalar, storing the larger values in resultVec.
    - *
    - * @param {goog.vec.vec4d.Type} vec0 The source vector.
    - * @param {goog.vec.vec4d.Type|number} limit The limit vector or scalar.
    - * @param {goog.vec.vec4d.Type} resultVec The vector to receive the
    - *     results (may be vec0 or limit).
    - * @return {!goog.vec.vec4d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec4d.max = function(vec0, limit, resultVec) {
    -  if (goog.isNumber(limit)) {
    -    resultVec[0] = Math.max(vec0[0], limit);
    -    resultVec[1] = Math.max(vec0[1], limit);
    -    resultVec[2] = Math.max(vec0[2], limit);
    -    resultVec[3] = Math.max(vec0[3], limit);
    -  } else {
    -    resultVec[0] = Math.max(vec0[0], limit[0]);
    -    resultVec[1] = Math.max(vec0[1], limit[1]);
    -    resultVec[2] = Math.max(vec0[2], limit[2]);
    -    resultVec[3] = Math.max(vec0[3], limit[3]);
    -  }
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Compares the components of vec0 with the components of another vector or
    - * scalar, storing the smaller values in resultVec.
    - *
    - * @param {goog.vec.vec4d.Type} vec0 The source vector.
    - * @param {goog.vec.vec4d.Type|number} limit The limit vector or scalar.
    - * @param {goog.vec.vec4d.Type} resultVec The vector to receive the
    - *     results (may be vec0 or limit).
    - * @return {!goog.vec.vec4d.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec4d.min = function(vec0, limit, resultVec) {
    -  if (goog.isNumber(limit)) {
    -    resultVec[0] = Math.min(vec0[0], limit);
    -    resultVec[1] = Math.min(vec0[1], limit);
    -    resultVec[2] = Math.min(vec0[2], limit);
    -    resultVec[3] = Math.min(vec0[3], limit);
    -  } else {
    -    resultVec[0] = Math.min(vec0[0], limit[0]);
    -    resultVec[1] = Math.min(vec0[1], limit[1]);
    -    resultVec[2] = Math.min(vec0[2], limit[2]);
    -    resultVec[3] = Math.min(vec0[3], limit[3]);
    -  }
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns true if the components of v0 are equal to the components of v1.
    - *
    - * @param {goog.vec.vec4d.Type} v0 The first vector.
    - * @param {goog.vec.vec4d.Type} v1 The second vector.
    - * @return {boolean} True if the vectors are equal, false otherwise.
    - */
    -goog.vec.vec4d.equals = function(v0, v1) {
    -  return v0.length == v1.length &&
    -      v0[0] == v1[0] && v0[1] == v1[1] && v0[2] == v1[2] && v0[3] == v1[3];
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/vec4d_test.html b/src/database/third_party/closure-library/closure/goog/vec/vec4d_test.html
    deleted file mode 100644
    index 74a0382259a..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/vec4d_test.html
    +++ /dev/null
    @@ -1,206 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -//                                                                           //
    -// Any edits to this file must be applied to vec4f_test.html by running:     //
    -//   swap_type.sh vec4d_test.html > vec4f_test.html                          //
    -//                                                                           //
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.vec.vec4d</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.vec.Float64Array');
    -  goog.require('goog.vec.vec4d');
    -  goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -  function testCreate() {
    -    var v = goog.vec.vec4d.create();
    -    assertElementsEquals([0, 0, 0, 0], v);
    -  }
    -
    -  function testSet() {
    -    var v = goog.vec.vec4d.create();
    -    goog.vec.vec4d.setFromValues(v, 1, 2, 3, 4);
    -    assertElementsEquals([1, 2, 3, 4], v);
    -
    -    goog.vec.vec4d.setFromArray(v, [4, 5, 6, 7]);
    -    assertElementsEquals([4, 5, 6, 7], v);
    -  }
    -
    -  function testAdd() {
    -    var v0 = goog.vec.vec4d.setFromArray(goog.vec.vec4d.create(), [1, 2, 3, 4]);
    -    var v1 = goog.vec.vec4d.setFromArray(goog.vec.vec4d.create(), [5, 6, 7, 8]);
    -    var v2 = goog.vec.vec4d.setFromVec4d(goog.vec.vec4d.create(), v0);
    -
    -    goog.vec.vec4d.add(v2, v1, v2);
    -    assertElementsEquals([1, 2, 3, 4], v0);
    -    assertElementsEquals([5, 6, 7, 8], v1);
    -    assertElementsEquals([6, 8, 10, 12], v2);
    -
    -    goog.vec.vec4d.add(goog.vec.vec4d.add(v0, v1, v2), v0, v2);
    -    assertElementsEquals([7, 10, 13, 16], v2);
    -  }
    -
    -  function testSubtract() {
    -    var v0 = goog.vec.vec4d.setFromArray(goog.vec.vec4d.create(), [4, 3, 2, 1]);
    -    var v1 = goog.vec.vec4d.setFromArray(goog.vec.vec4d.create(), [5, 6, 7, 8]);
    -    var v2 = goog.vec.vec4d.setFromVec4d(goog.vec.vec4d.create(), v0);
    -
    -    goog.vec.vec4d.subtract(v2, v1, v2);
    -    assertElementsEquals([4, 3, 2, 1], v0);
    -    assertElementsEquals([5, 6, 7, 8], v1);
    -    assertElementsEquals([-1, -3, -5, -7], v2);
    -
    -    goog.vec.vec4d.setFromValues(v2, 0, 0, 0, 0);
    -    goog.vec.vec4d.subtract(v1, v0, v2);
    -    assertElementsEquals([1, 3, 5, 7], v2);
    -
    -    goog.vec.vec4d.subtract(goog.vec.vec4d.subtract(v1, v0, v2), v0, v2);
    -    assertElementsEquals([-3, 0, 3, 6], v2);
    -  }
    -
    -  function testNegate() {
    -    var v0 = goog.vec.vec4d.setFromArray(goog.vec.vec4d.create(), [1, 2, 3, 4]);
    -    var v1 = goog.vec.vec4d.create();
    -
    -    goog.vec.vec4d.negate(v0, v1);
    -    assertElementsEquals([-1, -2, -3, -4], v1);
    -    assertElementsEquals([1, 2, 3, 4], v0);
    -
    -    goog.vec.vec4d.negate(v0, v0);
    -    assertElementsEquals([-1, -2, -3, -4], v0);
    -  }
    -
    -  function testAbs() {
    -    var v0 = goog.vec.vec4d.setFromArray(goog.vec.vec4d.create(), [-1, -2, -3, -4]);
    -    var v1 = goog.vec.vec4d.create();
    -
    -    goog.vec.vec4d.abs(v0, v1);
    -    assertElementsEquals([1, 2, 3, 4], v1);
    -    assertElementsEquals([-1, -2, -3, -4], v0);
    -
    -    goog.vec.vec4d.abs(v0, v0);
    -    assertElementsEquals([1, 2, 3, 4], v0);
    -  }
    -
    -  function testScale() {
    -    var v0 = goog.vec.vec4d.setFromArray(goog.vec.vec4d.create(), [1, 2, 3, 4]);
    -    var v1 = goog.vec.vec4d.create();
    -
    -    goog.vec.vec4d.scale(v0, 4, v1);
    -    assertElementsEquals([4, 8, 12, 16], v1);
    -    assertElementsEquals([1, 2, 3, 4], v0);
    -
    -    goog.vec.vec4d.setFromArray(v1, v0);
    -    goog.vec.vec4d.scale(v1, 5, v1);
    -    assertElementsEquals([5, 10, 15, 20], v1);
    -  }
    -
    -  function testMagnitudeSquared() {
    -    var v0 = goog.vec.vec4d.setFromArray(goog.vec.vec4d.create(), [1, 2, 3, 4]);
    -    assertEquals(30, goog.vec.vec4d.magnitudeSquared(v0));
    -  }
    -
    -  function testMagnitude() {
    -    var v0 = goog.vec.vec4d.setFromArray(goog.vec.vec4d.create(), [1, 2, 3, 4]);
    -    assertEquals(Math.sqrt(30), goog.vec.vec4d.magnitude(v0));
    -  }
    -
    -  function testNormalize() {
    -    var v0 = goog.vec.vec4d.setFromArray(goog.vec.vec4d.create(), [2, 3, 4, 5]);
    -    var v1 = goog.vec.vec4d.create();
    -    var v2 = goog.vec.vec4d.create();
    -    goog.vec.vec4d.scale(v0, 1 / goog.vec.vec4d.magnitude(v0), v2);
    -
    -    goog.vec.vec4d.normalize(v0, v1);
    -    assertElementsEquals(v2, v1);
    -    assertElementsEquals([2, 3, 4, 5], v0);
    -
    -    goog.vec.vec4d.setFromArray(v1, v0);
    -    goog.vec.vec4d.normalize(v1, v1);
    -    assertElementsEquals(v2, v1);
    -  }
    -
    -  function testDot() {
    -    var v0 = goog.vec.vec4d.setFromArray(goog.vec.vec4d.create(), [1, 2, 3, 4]);
    -    var v1 = goog.vec.vec4d.setFromArray(goog.vec.vec4d.create(), [5, 6, 7, 8]);
    -    assertEquals(70, goog.vec.vec4d.dot(v0, v1));
    -    assertEquals(70, goog.vec.vec4d.dot(v1, v0));
    -  }
    -
    -  function testLerp() {
    -    var v0 = goog.vec.vec4d.setFromValues(goog.vec.vec4d.create(), 1, 2, 3, 4);
    -    var v1 = goog.vec.vec4d.setFromValues(goog.vec.vec4d.create(), 10, 20, 30, 40);
    -    var v2 = goog.vec.vec4d.setFromVec4d(goog.vec.vec4d.create(), v0);
    -
    -    goog.vec.vec4d.lerp(v2, v1, 0, v2);
    -    assertElementsEquals([1, 2, 3, 4], v2);
    -    goog.vec.vec4d.lerp(v2, v1, 1, v2);
    -    assertElementsEquals([10, 20, 30, 40], v2);
    -    goog.vec.vec4d.lerp(v0, v1, .5, v2);
    -    assertElementsEquals([5.5, 11, 16.5, 22], v2);
    -  }
    -
    -  function testMax() {
    -    var v0 = goog.vec.vec4d.setFromValues(goog.vec.vec4d.create(), 10, 20, 30, 40);
    -    var v1 = goog.vec.vec4d.setFromValues(goog.vec.vec4d.create(), 5, 25, 35, 30);
    -    var v2 = goog.vec.vec4d.create();
    -
    -    goog.vec.vec4d.max(v0, v1, v2);
    -    assertElementsEquals([10, 25, 35, 40], v2);
    -    goog.vec.vec4d.max(v1, v0, v1);
    -    assertElementsEquals([10, 25, 35, 40], v1);
    -    goog.vec.vec4d.max(v2, 20, v2);
    -    assertElementsEquals([20, 25, 35, 40], v2);
    -  }
    -
    -  function testMin() {
    -    var v0 = goog.vec.vec4d.setFromValues(goog.vec.vec4d.create(), 10, 20, 30, 40);
    -    var v1 = goog.vec.vec4d.setFromValues(goog.vec.vec4d.create(), 5, 25, 35, 30);
    -    var v2 = goog.vec.vec4d.create();
    -
    -    goog.vec.vec4d.min(v0, v1, v2);
    -    assertElementsEquals([5, 20, 30, 30], v2);
    -    goog.vec.vec4d.min(v1, v0, v1);
    -    assertElementsEquals([5, 20, 30, 30], v1);
    -    goog.vec.vec4d.min(v2, 20, v2);
    -    assertElementsEquals([5, 20, 20, 20], v2);
    -  }
    -
    -  function testEquals() {
    -    var v0 = goog.vec.vec4d.setFromValues(goog.vec.vec4d.create(), 1, 2, 3, 4);
    -    var v1 = goog.vec.vec4d.setFromVec4d(goog.vec.vec4d.create(), v0);
    -    assertElementsEquals(v0, v1);
    -
    -    v1[0] = 5;
    -    assertFalse(goog.vec.vec4d.equals(v0, v1));
    -
    -    v1 = goog.vec.vec4d.setFromVec4d(goog.vec.vec4d.create(), v0);
    -    v1[1] = 5;
    -    assertFalse(goog.vec.vec4d.equals(v0, v1));
    -
    -    v1 = goog.vec.vec4d.setFromVec4d(goog.vec.vec4d.create(), v0);
    -    v1[2] = 5;
    -    assertFalse(goog.vec.vec4d.equals(v0, v1));
    -
    -    v1 = goog.vec.vec4d.setFromVec4d(goog.vec.vec4d.create(), v0);
    -    v1[3] = 5;
    -    assertFalse(goog.vec.vec4d.equals(v0, v1));
    -  }
    -
    -</script>
    -</body>
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/vec4f.js b/src/database/third_party/closure-library/closure/goog/vec/vec4f.js
    deleted file mode 100644
    index 9b4f0bf6462..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/vec4f.js
    +++ /dev/null
    @@ -1,366 +0,0 @@
    -// Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -//                                                                           //
    -// Any edits to this file must be applied to vec4d.js by running:            //
    -//   swap_type.sh vec4f.js > vec4d.js                                        //
    -//                                                                           //
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -
    -
    -/**
    - * @fileoverview Provides functions for operating on 4 element float (32bit)
    - * vectors.
    - *
    - * The last parameter will typically be the output object and an object
    - * can be both an input and output parameter to all methods except where
    - * noted.
    - *
    - * See the README for notes about the design and structure of the API
    - * (especially related to performance).
    - *
    - */
    -goog.provide('goog.vec.vec4f');
    -goog.provide('goog.vec.vec4f.Type');
    -
    -/** @suppress {extraRequire} */
    -goog.require('goog.vec');
    -
    -/** @typedef {goog.vec.Float32} */ goog.vec.vec4f.Type;
    -
    -
    -/**
    - * Creates a vec4f with all elements initialized to zero.
    - *
    - * @return {!goog.vec.vec4f.Type} The new vec4f.
    - */
    -goog.vec.vec4f.create = function() {
    -  return new Float32Array(4);
    -};
    -
    -
    -/**
    - * Initializes the vector with the given values.
    - *
    - * @param {goog.vec.vec4f.Type} vec The vector to receive the values.
    - * @param {number} v0 The value for element at index 0.
    - * @param {number} v1 The value for element at index 1.
    - * @param {number} v2 The value for element at index 2.
    - * @param {number} v3 The value for element at index 3.
    - * @return {!goog.vec.vec4f.Type} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec4f.setFromValues = function(vec, v0, v1, v2, v3) {
    -  vec[0] = v0;
    -  vec[1] = v1;
    -  vec[2] = v2;
    -  vec[3] = v3;
    -  return vec;
    -};
    -
    -
    -/**
    - * Initializes vec4f vec from vec4f src.
    - *
    - * @param {goog.vec.vec4f.Type} vec The destination vector.
    - * @param {goog.vec.vec4f.Type} src The source vector.
    - * @return {!goog.vec.vec4f.Type} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec4f.setFromVec4f = function(vec, src) {
    -  vec[0] = src[0];
    -  vec[1] = src[1];
    -  vec[2] = src[2];
    -  vec[3] = src[3];
    -  return vec;
    -};
    -
    -
    -/**
    - * Initializes vec4f vec from vec4d src (typed as a Float64Array to
    - * avoid circular goog.requires).
    - *
    - * @param {goog.vec.vec4f.Type} vec The destination vector.
    - * @param {Float64Array} src The source vector.
    - * @return {!goog.vec.vec4f.Type} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec4f.setFromVec4d = function(vec, src) {
    -  vec[0] = src[0];
    -  vec[1] = src[1];
    -  vec[2] = src[2];
    -  vec[3] = src[3];
    -  return vec;
    -};
    -
    -
    -/**
    - * Initializes vec4f vec from Array src.
    - *
    - * @param {goog.vec.vec4f.Type} vec The destination vector.
    - * @param {Array<number>} src The source vector.
    - * @return {!goog.vec.vec4f.Type} Return vec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec4f.setFromArray = function(vec, src) {
    -  vec[0] = src[0];
    -  vec[1] = src[1];
    -  vec[2] = src[2];
    -  vec[3] = src[3];
    -  return vec;
    -};
    -
    -
    -/**
    - * Performs a component-wise addition of vec0 and vec1 together storing the
    - * result into resultVec.
    - *
    - * @param {goog.vec.vec4f.Type} vec0 The first addend.
    - * @param {goog.vec.vec4f.Type} vec1 The second addend.
    - * @param {goog.vec.vec4f.Type} resultVec The vector to
    - *     receive the result. May be vec0 or vec1.
    - * @return {!goog.vec.vec4f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec4f.add = function(vec0, vec1, resultVec) {
    -  resultVec[0] = vec0[0] + vec1[0];
    -  resultVec[1] = vec0[1] + vec1[1];
    -  resultVec[2] = vec0[2] + vec1[2];
    -  resultVec[3] = vec0[3] + vec1[3];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Performs a component-wise subtraction of vec1 from vec0 storing the
    - * result into resultVec.
    - *
    - * @param {goog.vec.vec4f.Type} vec0 The minuend.
    - * @param {goog.vec.vec4f.Type} vec1 The subtrahend.
    - * @param {goog.vec.vec4f.Type} resultVec The vector to
    - *     receive the result. May be vec0 or vec1.
    - * @return {!goog.vec.vec4f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec4f.subtract = function(vec0, vec1, resultVec) {
    -  resultVec[0] = vec0[0] - vec1[0];
    -  resultVec[1] = vec0[1] - vec1[1];
    -  resultVec[2] = vec0[2] - vec1[2];
    -  resultVec[3] = vec0[3] - vec1[3];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Negates vec0, storing the result into resultVec.
    - *
    - * @param {goog.vec.vec4f.Type} vec0 The vector to negate.
    - * @param {goog.vec.vec4f.Type} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.vec4f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec4f.negate = function(vec0, resultVec) {
    -  resultVec[0] = -vec0[0];
    -  resultVec[1] = -vec0[1];
    -  resultVec[2] = -vec0[2];
    -  resultVec[3] = -vec0[3];
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Takes the absolute value of each component of vec0 storing the result in
    - * resultVec.
    - *
    - * @param {goog.vec.vec4f.Type} vec0 The source vector.
    - * @param {goog.vec.vec4f.Type} resultVec The vector to receive the result.
    - *     May be vec0.
    - * @return {!goog.vec.vec4f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec4f.abs = function(vec0, resultVec) {
    -  resultVec[0] = Math.abs(vec0[0]);
    -  resultVec[1] = Math.abs(vec0[1]);
    -  resultVec[2] = Math.abs(vec0[2]);
    -  resultVec[3] = Math.abs(vec0[3]);
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Multiplies each component of vec0 with scalar storing the product into
    - * resultVec.
    - *
    - * @param {goog.vec.vec4f.Type} vec0 The source vector.
    - * @param {number} scalar The value to multiply with each component of vec0.
    - * @param {goog.vec.vec4f.Type} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.vec4f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec4f.scale = function(vec0, scalar, resultVec) {
    -  resultVec[0] = vec0[0] * scalar;
    -  resultVec[1] = vec0[1] * scalar;
    -  resultVec[2] = vec0[2] * scalar;
    -  resultVec[3] = vec0[3] * scalar;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns the magnitudeSquared of the given vector.
    - *
    - * @param {goog.vec.vec4f.Type} vec0 The vector.
    - * @return {number} The magnitude of the vector.
    - */
    -goog.vec.vec4f.magnitudeSquared = function(vec0) {
    -  var x = vec0[0], y = vec0[1], z = vec0[2], w = vec0[3];
    -  return x * x + y * y + z * z + w * w;
    -};
    -
    -
    -/**
    - * Returns the magnitude of the given vector.
    - *
    - * @param {goog.vec.vec4f.Type} vec0 The vector.
    - * @return {number} The magnitude of the vector.
    - */
    -goog.vec.vec4f.magnitude = function(vec0) {
    -  var x = vec0[0], y = vec0[1], z = vec0[2], w = vec0[3];
    -  return Math.sqrt(x * x + y * y + z * z + w * w);
    -};
    -
    -
    -/**
    - * Normalizes the given vector storing the result into resultVec.
    - *
    - * @param {goog.vec.vec4f.Type} vec0 The vector to normalize.
    - * @param {goog.vec.vec4f.Type} resultVec The vector to
    - *     receive the result. May be vec0.
    - * @return {!goog.vec.vec4f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec4f.normalize = function(vec0, resultVec) {
    -  var x = vec0[0], y = vec0[1], z = vec0[2], w = vec0[3];
    -  var ilen = 1 / Math.sqrt(x * x + y * y + z * z + w * w);
    -  resultVec[0] = x * ilen;
    -  resultVec[1] = y * ilen;
    -  resultVec[2] = z * ilen;
    -  resultVec[3] = w * ilen;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns the scalar product of vectors v0 and v1.
    - *
    - * @param {goog.vec.vec4f.Type} v0 The first vector.
    - * @param {goog.vec.vec4f.Type} v1 The second vector.
    - * @return {number} The scalar product.
    - */
    -goog.vec.vec4f.dot = function(v0, v1) {
    -  return v0[0] * v1[0] + v0[1] * v1[1] + v0[2] * v1[2] + v0[3] * v1[3];
    -};
    -
    -
    -/**
    - * Linearly interpolate from v0 to v1 according to f. The value of f should be
    - * in the range [0..1] otherwise the results are undefined.
    - *
    - * @param {goog.vec.vec4f.Type} v0 The first vector.
    - * @param {goog.vec.vec4f.Type} v1 The second vector.
    - * @param {number} f The interpolation factor.
    - * @param {goog.vec.vec4f.Type} resultVec The vector to receive the
    - *     results (may be v0 or v1).
    - * @return {!goog.vec.vec4f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec4f.lerp = function(v0, v1, f, resultVec) {
    -  var x = v0[0], y = v0[1], z = v0[2], w = v0[3];
    -  resultVec[0] = (v1[0] - x) * f + x;
    -  resultVec[1] = (v1[1] - y) * f + y;
    -  resultVec[2] = (v1[2] - z) * f + z;
    -  resultVec[3] = (v1[3] - w) * f + w;
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Compares the components of vec0 with the components of another vector or
    - * scalar, storing the larger values in resultVec.
    - *
    - * @param {goog.vec.vec4f.Type} vec0 The source vector.
    - * @param {goog.vec.vec4f.Type|number} limit The limit vector or scalar.
    - * @param {goog.vec.vec4f.Type} resultVec The vector to receive the
    - *     results (may be vec0 or limit).
    - * @return {!goog.vec.vec4f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec4f.max = function(vec0, limit, resultVec) {
    -  if (goog.isNumber(limit)) {
    -    resultVec[0] = Math.max(vec0[0], limit);
    -    resultVec[1] = Math.max(vec0[1], limit);
    -    resultVec[2] = Math.max(vec0[2], limit);
    -    resultVec[3] = Math.max(vec0[3], limit);
    -  } else {
    -    resultVec[0] = Math.max(vec0[0], limit[0]);
    -    resultVec[1] = Math.max(vec0[1], limit[1]);
    -    resultVec[2] = Math.max(vec0[2], limit[2]);
    -    resultVec[3] = Math.max(vec0[3], limit[3]);
    -  }
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Compares the components of vec0 with the components of another vector or
    - * scalar, storing the smaller values in resultVec.
    - *
    - * @param {goog.vec.vec4f.Type} vec0 The source vector.
    - * @param {goog.vec.vec4f.Type|number} limit The limit vector or scalar.
    - * @param {goog.vec.vec4f.Type} resultVec The vector to receive the
    - *     results (may be vec0 or limit).
    - * @return {!goog.vec.vec4f.Type} Return resultVec so that operations can be
    - *     chained together.
    - */
    -goog.vec.vec4f.min = function(vec0, limit, resultVec) {
    -  if (goog.isNumber(limit)) {
    -    resultVec[0] = Math.min(vec0[0], limit);
    -    resultVec[1] = Math.min(vec0[1], limit);
    -    resultVec[2] = Math.min(vec0[2], limit);
    -    resultVec[3] = Math.min(vec0[3], limit);
    -  } else {
    -    resultVec[0] = Math.min(vec0[0], limit[0]);
    -    resultVec[1] = Math.min(vec0[1], limit[1]);
    -    resultVec[2] = Math.min(vec0[2], limit[2]);
    -    resultVec[3] = Math.min(vec0[3], limit[3]);
    -  }
    -  return resultVec;
    -};
    -
    -
    -/**
    - * Returns true if the components of v0 are equal to the components of v1.
    - *
    - * @param {goog.vec.vec4f.Type} v0 The first vector.
    - * @param {goog.vec.vec4f.Type} v1 The second vector.
    - * @return {boolean} True if the vectors are equal, false otherwise.
    - */
    -goog.vec.vec4f.equals = function(v0, v1) {
    -  return v0.length == v1.length &&
    -      v0[0] == v1[0] && v0[1] == v1[1] && v0[2] == v1[2] && v0[3] == v1[3];
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/vec4f_test.html b/src/database/third_party/closure-library/closure/goog/vec/vec4f_test.html
    deleted file mode 100644
    index 12d138a7fda..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/vec4f_test.html
    +++ /dev/null
    @@ -1,206 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2013 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -//                                                                           //
    -// Any edits to this file must be applied to vec4d_test.html by running:     //
    -//   swap_type.sh vec4f_test.html > vec4d_test.html                          //
    -//                                                                           //
    -////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
    -
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -<title>Closure Unit Tests - goog.vec.vec4f</title>
    -<script src="../base.js"></script>
    -<script>
    -  goog.require('goog.vec.Float32Array');
    -  goog.require('goog.vec.vec4f');
    -  goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -  function testCreate() {
    -    var v = goog.vec.vec4f.create();
    -    assertElementsEquals([0, 0, 0, 0], v);
    -  }
    -
    -  function testSet() {
    -    var v = goog.vec.vec4f.create();
    -    goog.vec.vec4f.setFromValues(v, 1, 2, 3, 4);
    -    assertElementsEquals([1, 2, 3, 4], v);
    -
    -    goog.vec.vec4f.setFromArray(v, [4, 5, 6, 7]);
    -    assertElementsEquals([4, 5, 6, 7], v);
    -  }
    -
    -  function testAdd() {
    -    var v0 = goog.vec.vec4f.setFromArray(goog.vec.vec4f.create(), [1, 2, 3, 4]);
    -    var v1 = goog.vec.vec4f.setFromArray(goog.vec.vec4f.create(), [5, 6, 7, 8]);
    -    var v2 = goog.vec.vec4f.setFromVec4f(goog.vec.vec4f.create(), v0);
    -
    -    goog.vec.vec4f.add(v2, v1, v2);
    -    assertElementsEquals([1, 2, 3, 4], v0);
    -    assertElementsEquals([5, 6, 7, 8], v1);
    -    assertElementsEquals([6, 8, 10, 12], v2);
    -
    -    goog.vec.vec4f.add(goog.vec.vec4f.add(v0, v1, v2), v0, v2);
    -    assertElementsEquals([7, 10, 13, 16], v2);
    -  }
    -
    -  function testSubtract() {
    -    var v0 = goog.vec.vec4f.setFromArray(goog.vec.vec4f.create(), [4, 3, 2, 1]);
    -    var v1 = goog.vec.vec4f.setFromArray(goog.vec.vec4f.create(), [5, 6, 7, 8]);
    -    var v2 = goog.vec.vec4f.setFromVec4f(goog.vec.vec4f.create(), v0);
    -
    -    goog.vec.vec4f.subtract(v2, v1, v2);
    -    assertElementsEquals([4, 3, 2, 1], v0);
    -    assertElementsEquals([5, 6, 7, 8], v1);
    -    assertElementsEquals([-1, -3, -5, -7], v2);
    -
    -    goog.vec.vec4f.setFromValues(v2, 0, 0, 0, 0);
    -    goog.vec.vec4f.subtract(v1, v0, v2);
    -    assertElementsEquals([1, 3, 5, 7], v2);
    -
    -    goog.vec.vec4f.subtract(goog.vec.vec4f.subtract(v1, v0, v2), v0, v2);
    -    assertElementsEquals([-3, 0, 3, 6], v2);
    -  }
    -
    -  function testNegate() {
    -    var v0 = goog.vec.vec4f.setFromArray(goog.vec.vec4f.create(), [1, 2, 3, 4]);
    -    var v1 = goog.vec.vec4f.create();
    -
    -    goog.vec.vec4f.negate(v0, v1);
    -    assertElementsEquals([-1, -2, -3, -4], v1);
    -    assertElementsEquals([1, 2, 3, 4], v0);
    -
    -    goog.vec.vec4f.negate(v0, v0);
    -    assertElementsEquals([-1, -2, -3, -4], v0);
    -  }
    -
    -  function testAbs() {
    -    var v0 = goog.vec.vec4f.setFromArray(goog.vec.vec4f.create(), [-1, -2, -3, -4]);
    -    var v1 = goog.vec.vec4f.create();
    -
    -    goog.vec.vec4f.abs(v0, v1);
    -    assertElementsEquals([1, 2, 3, 4], v1);
    -    assertElementsEquals([-1, -2, -3, -4], v0);
    -
    -    goog.vec.vec4f.abs(v0, v0);
    -    assertElementsEquals([1, 2, 3, 4], v0);
    -  }
    -
    -  function testScale() {
    -    var v0 = goog.vec.vec4f.setFromArray(goog.vec.vec4f.create(), [1, 2, 3, 4]);
    -    var v1 = goog.vec.vec4f.create();
    -
    -    goog.vec.vec4f.scale(v0, 4, v1);
    -    assertElementsEquals([4, 8, 12, 16], v1);
    -    assertElementsEquals([1, 2, 3, 4], v0);
    -
    -    goog.vec.vec4f.setFromArray(v1, v0);
    -    goog.vec.vec4f.scale(v1, 5, v1);
    -    assertElementsEquals([5, 10, 15, 20], v1);
    -  }
    -
    -  function testMagnitudeSquared() {
    -    var v0 = goog.vec.vec4f.setFromArray(goog.vec.vec4f.create(), [1, 2, 3, 4]);
    -    assertEquals(30, goog.vec.vec4f.magnitudeSquared(v0));
    -  }
    -
    -  function testMagnitude() {
    -    var v0 = goog.vec.vec4f.setFromArray(goog.vec.vec4f.create(), [1, 2, 3, 4]);
    -    assertEquals(Math.sqrt(30), goog.vec.vec4f.magnitude(v0));
    -  }
    -
    -  function testNormalize() {
    -    var v0 = goog.vec.vec4f.setFromArray(goog.vec.vec4f.create(), [2, 3, 4, 5]);
    -    var v1 = goog.vec.vec4f.create();
    -    var v2 = goog.vec.vec4f.create();
    -    goog.vec.vec4f.scale(v0, 1 / goog.vec.vec4f.magnitude(v0), v2);
    -
    -    goog.vec.vec4f.normalize(v0, v1);
    -    assertElementsEquals(v2, v1);
    -    assertElementsEquals([2, 3, 4, 5], v0);
    -
    -    goog.vec.vec4f.setFromArray(v1, v0);
    -    goog.vec.vec4f.normalize(v1, v1);
    -    assertElementsEquals(v2, v1);
    -  }
    -
    -  function testDot() {
    -    var v0 = goog.vec.vec4f.setFromArray(goog.vec.vec4f.create(), [1, 2, 3, 4]);
    -    var v1 = goog.vec.vec4f.setFromArray(goog.vec.vec4f.create(), [5, 6, 7, 8]);
    -    assertEquals(70, goog.vec.vec4f.dot(v0, v1));
    -    assertEquals(70, goog.vec.vec4f.dot(v1, v0));
    -  }
    -
    -  function testLerp() {
    -    var v0 = goog.vec.vec4f.setFromValues(goog.vec.vec4f.create(), 1, 2, 3, 4);
    -    var v1 = goog.vec.vec4f.setFromValues(goog.vec.vec4f.create(), 10, 20, 30, 40);
    -    var v2 = goog.vec.vec4f.setFromVec4f(goog.vec.vec4f.create(), v0);
    -
    -    goog.vec.vec4f.lerp(v2, v1, 0, v2);
    -    assertElementsEquals([1, 2, 3, 4], v2);
    -    goog.vec.vec4f.lerp(v2, v1, 1, v2);
    -    assertElementsEquals([10, 20, 30, 40], v2);
    -    goog.vec.vec4f.lerp(v0, v1, .5, v2);
    -    assertElementsEquals([5.5, 11, 16.5, 22], v2);
    -  }
    -
    -  function testMax() {
    -    var v0 = goog.vec.vec4f.setFromValues(goog.vec.vec4f.create(), 10, 20, 30, 40);
    -    var v1 = goog.vec.vec4f.setFromValues(goog.vec.vec4f.create(), 5, 25, 35, 30);
    -    var v2 = goog.vec.vec4f.create();
    -
    -    goog.vec.vec4f.max(v0, v1, v2);
    -    assertElementsEquals([10, 25, 35, 40], v2);
    -    goog.vec.vec4f.max(v1, v0, v1);
    -    assertElementsEquals([10, 25, 35, 40], v1);
    -    goog.vec.vec4f.max(v2, 20, v2);
    -    assertElementsEquals([20, 25, 35, 40], v2);
    -  }
    -
    -  function testMin() {
    -    var v0 = goog.vec.vec4f.setFromValues(goog.vec.vec4f.create(), 10, 20, 30, 40);
    -    var v1 = goog.vec.vec4f.setFromValues(goog.vec.vec4f.create(), 5, 25, 35, 30);
    -    var v2 = goog.vec.vec4f.create();
    -
    -    goog.vec.vec4f.min(v0, v1, v2);
    -    assertElementsEquals([5, 20, 30, 30], v2);
    -    goog.vec.vec4f.min(v1, v0, v1);
    -    assertElementsEquals([5, 20, 30, 30], v1);
    -    goog.vec.vec4f.min(v2, 20, v2);
    -    assertElementsEquals([5, 20, 20, 20], v2);
    -  }
    -
    -  function testEquals() {
    -    var v0 = goog.vec.vec4f.setFromValues(goog.vec.vec4f.create(), 1, 2, 3, 4);
    -    var v1 = goog.vec.vec4f.setFromVec4f(goog.vec.vec4f.create(), v0);
    -    assertElementsEquals(v0, v1);
    -
    -    v1[0] = 5;
    -    assertFalse(goog.vec.vec4f.equals(v0, v1));
    -
    -    v1 = goog.vec.vec4f.setFromVec4f(goog.vec.vec4f.create(), v0);
    -    v1[1] = 5;
    -    assertFalse(goog.vec.vec4f.equals(v0, v1));
    -
    -    v1 = goog.vec.vec4f.setFromVec4f(goog.vec.vec4f.create(), v0);
    -    v1[2] = 5;
    -    assertFalse(goog.vec.vec4f.equals(v0, v1));
    -
    -    v1 = goog.vec.vec4f.setFromVec4f(goog.vec.vec4f.create(), v0);
    -    v1[3] = 5;
    -    assertFalse(goog.vec.vec4f.equals(v0, v1));
    -  }
    -
    -</script>
    -</body>
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/vec_array_perf.html b/src/database/third_party/closure-library/closure/goog/vec/vec_array_perf.html
    deleted file mode 100644
    index 67e5728615e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/vec_array_perf.html
    +++ /dev/null
    @@ -1,443 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -  <title>Closure Performance Tests - Vector Array math</title>
    -  <link rel="stylesheet" type="text/css"
    -        href="../testing/performancetable.css"/>
    -  <script type="text/javascript" src="../base.js"></script>
    -  <script type="text/javascript">
    -    goog.require('goog.testing.jsunit');
    -    goog.require('goog.testing.PerformanceTable');
    -    goog.require('goog.vec.Vec4');
    -    goog.require('goog.vec.Mat4');
    -  </script>
    -</head>
    -<body>
    -  <h1>Closure Performance Tests - Vector Array Math</h1>
    -  <p>
    -    <strong>User-agent:</strong>
    -    <script type="text/javascript">document.write(navigator.userAgent);</script>
    -  </p>
    -  <p>
    -    These tests compare various methods of performing vector operations on
    -    arrays of vectors.
    -  </p>
    -  <div id="perfTable"></div>
    -  <hr>
    - <script type="text/javascript">
    -
    -var table = new goog.testing.PerformanceTable(
    -    goog.dom.getElement('perfTable'));
    -
    -function createRandomFloat32Array(length) {
    -  var array = new Float32Array(length);
    -  for (var i = 0; i < length; i++) {
    -    array[i] = Math.random();
    -  }
    -  return array;
    -}
    -
    -function createRandomIndexArray(length) {
    -  var array = [];
    -  for (var i = 0; i < length; i++) {
    -    array[i] = Math.floor(Math.random() * length);
    -    array[i] = Math.min(length - 1, array[i]);
    -  }
    -  return array;
    -}
    -
    -function createRandomVec4Array(length) {
    -  var a = [];
    -  for (var i = 0; i < length; i++) {
    -    a[i] = goog.vec.Vec4.createFromValues(
    -        Math.random(), Math.random(), Math.random(), Math.random());
    -  }
    -  return a;
    -}
    -
    -function createRandomMat4() {
    -  var m = goog.vec.Mat4.createFromValues(
    -      Math.random(), Math.random(), Math.random(), Math.random(),
    -      Math.random(), Math.random(), Math.random(), Math.random(),
    -      Math.random(), Math.random(), Math.random(), Math.random(),
    -      Math.random(), Math.random(), Math.random(), Math.random());
    -  return m;
    -}
    -
    -function createRandomMat4Array(length) {
    -  var m = [];
    -  for (var i = 0; i < length; i++) {
    -    m[i] = createRandomMat4();
    -  }
    -  return m;
    -}
    -
    -/**
    - * Vec4Object is a 4-vector object with x,y,z,w components.
    - * @param {number} x The x component.
    - * @param {number} y The y component.
    - * @param {number} z The z component.
    - * @param {number} w The w component.
    - * @constructor
    - */
    -Vec4Object = function(x, y, z, w) {
    -  this.x = x;
    -  this.y = y;
    -  this.z = z;
    -  this.w = w;
    -};
    -
    -/**
    - * Add two vectors.
    - * @param {Vec4Object} v0 A vector.
    - * @param {Vec4Object} v1 Another vector.
    - * @param {Vec4Object} r The result.
    - */
    -Vec4Object.add = function(v0, v1, r) {
    -  r.x = v0.x + v1.x;
    -  r.y = v0.y + v1.y;
    -  r.z = v0.z + v1.z;
    -  r.w = v0.w + v1.w;
    -};
    -
    -function createRandomVec4ObjectArray(length) {
    -  var a = [];
    -  for (var i = 0; i < length; i++) {
    -    a[i] = new Vec4Object(
    -        Math.random(), Math.random(), Math.random(), Math.random());
    -  }
    -  return a;
    -}
    -
    -function setVec4FromArray(v, a, o) {
    -  v[0] = a[o + 0];
    -  v[1] = a[o + 1];
    -  v[2] = a[o + 2];
    -  v[3] = a[o + 3];
    -}
    -
    -function setArrayFromVec4(a, o, v) {
    -  a[o + 0] = v[0];
    -  a[o + 1] = v[1];
    -  a[o + 2] = v[2];
    -  a[o + 3] = v[3];
    -}
    -
    -/**
    - * This is the same as goog.vec.Vec4.add().  Use this to avoid namespace lookup
    - * overheads.
    - * @param {goog.vec.Vec4.Vec4Like} v0 A vector.
    - * @param {goog.vec.Vec4.Vec4Like} v1 Another vector.
    - * @param {goog.vec.Vec4.Vec4Like} r The result.
    - */
    -function addVec4(v0, v1, r) {
    -  r[0] = v0[0] + v1[0];
    -  r[1] = v0[1] + v1[1];
    -  r[2] = v0[2] + v1[2];
    -  r[3] = v0[3] + v1[3];
    -}
    -
    -function addVec4ByOffset(v0Buf, v0Off, v1Buf, v1Off, rBuf, rOff) {
    -  rBuf[rOff + 0] = v0Buf[v0Off + 0] + v1Buf[v1Off + 0];
    -  rBuf[rOff + 1] = v0Buf[v0Off + 1] + v1Buf[v1Off + 1];
    -  rBuf[rOff + 2] = v0Buf[v0Off + 2] + v1Buf[v1Off + 2];
    -  rBuf[rOff + 3] = v0Buf[v0Off + 3] + v1Buf[v1Off + 3];
    -}
    -
    -function addVec4ByOptionalOffset(v0, v1, r, opt_v0Off, opt_v1Off, opt_rOff) {
    -  if (opt_v0Off && opt_v1Off && opt_rOff) {
    -    r[opt_rOff + 0] = v0[opt_v0Off + 0] + v1[opt_v1Off + 0];
    -    r[opt_rOff + 1] = v0[opt_v0Off + 1] + v1[opt_v1Off + 1];
    -    r[opt_rOff + 2] = v0[opt_v0Off + 2] + v1[opt_v1Off + 2];
    -    r[opt_rOff + 3] = v0[opt_v0Off + 3] + v1[opt_v1Off + 3];
    -  } else {
    -    r[0] = v0[0] + v1[0];
    -    r[1] = v0[1] + v1[1];
    -    r[2] = v0[2] + v1[2];
    -    r[3] = v0[3] + v1[3];
    -  }
    -}
    -
    -function mat4MultVec4ByOffset(mBuf, mOff, vBuf, vOff, rBuf, rOff) {
    -  var x = vBuf[vOff + 0], y = vBuf[vOff + 1],
    -      z = vBuf[vOff + 2], w = vBuf[vOff + 3];
    -  rBuf[rOff + 0] = x * mBuf[mOff + 0] + y * mBuf[mOff + 4] +
    -      z * mBuf[mOff + 8] + w * mBuf[mOff + 12];
    -  rBuf[rOff + 1] = x * mBuf[mOff + 1] + y * mBuf[mOff + 5] +
    -      z * mBuf[mOff + 9] + w * mBuf[mOff + 13];
    -  rBuf[rOff + 2] = x * mBuf[mOff + 2] + y * mBuf[mOff + 6] +
    -      z * mBuf[mOff + 10] + w * mBuf[mOff + 14];
    -  rBuf[rOff + 3] = x * mBuf[mOff + 3] + y * mBuf[mOff + 7] +
    -      z * mBuf[mOff + 11] + w * mBuf[mOff + 15];
    -}
    -
    -var NUM_ITERATIONS = 200000;
    -
    -function testAddVec4ByOffset() {
    -  var nVecs = NUM_ITERATIONS;
    -  var nVals = nVecs * 4;
    -  var a0 = createRandomFloat32Array(nVals);
    -  var a1 = createRandomFloat32Array(nVals);
    -  var a2 = new Float32Array(nVals);
    -
    -  table.run(
    -      function() {
    -        for (var i = 0; i < nVecs; i++) {
    -          addVec4ByOffset(a0, i * 4, a1, i * 4, a2, i * 4);
    -        }
    -      },
    -      'Add vectors using offsets');
    -}
    -
    -function testAddVec4ByOptionalOffset() {
    -  var nVecs = NUM_ITERATIONS;
    -  var nVals = nVecs * 4;
    -  var a0 = createRandomFloat32Array(nVals);
    -  var a1 = createRandomFloat32Array(nVals);
    -  var a2 = new Float32Array(nVals);
    -
    -  table.run(
    -      function() {
    -        for (var i = 0; i < nVecs; i++) {
    -          addVec4ByOptionalOffset(a0, a1, a2, i * 4, i * 4, i * 4);
    -        }
    -      },
    -      'Add vectors with optional offsets (requires branch)');
    -}
    -
    -/**
    - * Check the overhead of using an array of individual
    - * Vec4s (Float32Arrays of length 4).
    - */
    -function testAddVec4ByVec4s() {
    -  var nVecs = NUM_ITERATIONS;
    -  var a0 = createRandomVec4Array(nVecs);
    -  var a1 = createRandomVec4Array(nVecs);
    -  var a2 = createRandomVec4Array(nVecs);
    -
    -  table.run(
    -      function() {
    -        for (var i = 0; i < nVecs; i++) {
    -          addVec4(a0[i], a1[i], a2[i]);
    -        }
    -      },
    -      'Add vectors using an array of Vec4s (Float32Arrays of length 4)');
    -}
    -
    -function testAddVec4ByTmp() {
    -  var nVecs = NUM_ITERATIONS;
    -  var nVals = nVecs * 4;
    -  var a0 = createRandomFloat32Array(nVals);
    -  var a1 = createRandomFloat32Array(nVals);
    -  var a2 = new Float32Array(nVals);
    -
    -  table.run(
    -      function() {
    -        var t0 = new Float32Array(4);
    -        var t1 = new Float32Array(4);
    -        for (var i = 0; i < nVecs; i++) {
    -          setVec4FromArray(t0, a0, i * 4);
    -          setVec4FromArray(t1, a1, i * 4);
    -          addVec4(t0, t1, t0);
    -          setArrayFromVec4(a2, i * 4, t0);
    -        }
    -      },
    -      'Add vectors using tmps');
    -}
    -
    -/**
    - * Check the overhead of using an array of Objects with the implicit hash
    - * lookups for the x,y,z,w components.
    - */
    -function testAddVec4ByObjects() {
    -  var nVecs = NUM_ITERATIONS;
    -  var a0 = createRandomVec4ObjectArray(nVecs);
    -  var a1 = createRandomVec4ObjectArray(nVecs);
    -  var a2 = createRandomVec4ObjectArray(nVecs);
    -
    -  table.run(
    -      function() {
    -        for (var i = 0; i < nVecs; i++) {
    -          Vec4Object.add(a0[i], a1[i], a2[i]);
    -        }
    -      },
    -      'Add vectors using an array of Objects ' +
    -      '(with implicit hash lookups for the x,y,z,w components)');
    -}
    -
    -function testAddVec4BySubarray() {
    -  var nVecs = NUM_ITERATIONS;
    -  var nVals = nVecs * 4;
    -  var a0 = createRandomFloat32Array(nVals);
    -  var a1 = createRandomFloat32Array(nVals);
    -  var a2 = new Float32Array(nVals);
    -
    -  table.run(
    -      function() {
    -        for (var i = 0; i < nVecs; i++) {
    -          var t0 = a0.subarray(i * 4 * 4);
    -          var t1 = a1.subarray(i * 4 * 4);
    -          var t2 = a2.subarray(i * 4 * 4);
    -          addVec4(t0, t1, t2);
    -        }
    -      },
    -      'Add vectors using Float32Array.subarray()');
    -}
    -
    -function testAddVec4ByView() {
    -  var nVecs = NUM_ITERATIONS;
    -  var nVals = nVecs * 4;
    -  var a0 = createRandomFloat32Array(nVals);
    -  var a1 = createRandomFloat32Array(nVals);
    -  var a2 = new Float32Array(nVals);
    -
    -  table.run(
    -      function() {
    -        for (var i = 0; i < nVecs; i++) {
    -          var t0 = new Float32Array(a0.buffer, i * 4 * 4);
    -          var t1 = new Float32Array(a1.buffer, i * 4 * 4);
    -          var t2 = new Float32Array(a2.buffer, i * 4 * 4);
    -          addVec4(t0, t1, t2);
    -        }
    -      },
    -      'Add vectors using Float32 view');
    -}
    -
    -function testMat4MultVec4ByOffset() {
    -  var nVecs = NUM_ITERATIONS;
    -  var nVecVals = nVecs * 4;
    -  var nMatVals = nVecs * 16;
    -  var m = createRandomFloat32Array(nMatVals);
    -  var a0 = createRandomFloat32Array(nVecVals);
    -  var a1 = new Float32Array(nVecVals);
    -
    -  table.run(
    -      function() {
    -        for (var i = 0; i < nVecs; i++) {
    -          mat4MultVec4ByOffset(m, i * 16, a0, i * 4, a1, i * 4);
    -        }
    -      },
    -      'vec4 = mat4 * vec4 using offsets.');
    -}
    -
    -/**
    - * Check the overhead of using an array of individual
    - * Vec4s (Float32Arrays of length 4).
    - */
    -function testMat4MultVec4ByVec4s() {
    -  var nVecs = NUM_ITERATIONS;
    -  var a0 = createRandomVec4Array(nVecs);
    -  var a1 = createRandomVec4Array(nVecs);
    -  var m = createRandomMat4Array(nVecs);
    -
    -  table.run(
    -      function() {
    -        for (var i = 0; i < nVecs; i++) {
    -          goog.vec.Mat4.multVec4(m[i], a0[i], a1[i]);
    -        }
    -      },
    -      'vec4 = mat4 * vec4  using arrays of Vec4s and Mat4s');
    -}
    -
    -/**
    - * Do 10x as many for the one vector tests.
    - * @type {number}
    - */
    -var NUM_ONE_ITERATIONS = NUM_ITERATIONS * 10;
    -
    -function testAddOneVec4ByOffset() {
    -  var a0 = createRandomFloat32Array(4);
    -  var a1 = createRandomFloat32Array(4);
    -  var a2 = new Float32Array(4);
    -
    -  table.run(
    -      function() {
    -        for (var i = 0; i < NUM_ONE_ITERATIONS; i++) {
    -          addVec4ByOffset(a0, 0, a1, 0, a2, 0);
    -        }
    -      },
    -      'Add one vector using offset of 0');
    -}
    -
    -function testAddOneVec4() {
    -  var a0 = createRandomFloat32Array(4);
    -  var a1 = createRandomFloat32Array(4);
    -  var a2 = new Float32Array(4);
    -
    -  table.run(
    -      function() {
    -        for (var i = 0; i < NUM_ONE_ITERATIONS; i++) {
    -          addVec4(a0, a1, a2);
    -        }
    -      },
    -      'Add one vector');
    -}
    -
    -function testAddOneVec4ByOptionalOffset() {
    -  var a0 = createRandomFloat32Array(4);
    -  var a1 = createRandomFloat32Array(4);
    -  var a2 = new Float32Array(4);
    -
    -  table.run(
    -      function() {
    -        for (var i = 0; i < NUM_ONE_ITERATIONS; i++) {
    -          addVec4ByOptionalOffset(a0, a1, a2);
    -        }
    -      },
    -      'Add one vector with optional offsets (requires branch)');
    -}
    -
    -function testAddRandomVec4ByOffset() {
    -  var nVecs = NUM_ITERATIONS;
    -  var nVals = nVecs * 4;
    -  var a0 = createRandomFloat32Array(nVals);
    -  var a1 = createRandomFloat32Array(nVals);
    -  var a2 = new Float32Array(nVals);
    -  var i0 = createRandomIndexArray(nVecs);
    -  var i1 = createRandomIndexArray(nVecs);
    -  var i2 = createRandomIndexArray(nVecs);
    -
    -  table.run(
    -      function() {
    -        for (var i = 0; i < nVecs; i++) {
    -          addVec4ByOffset(a0, i0[i] * 4, a1, i1[i] * 4, a2, i2[i] * 4);
    -        }
    -      },
    -      'Add random vectors using offsets');
    -}
    -
    -function testAddRandomVec4ByVec4s() {
    -  var nVecs = NUM_ITERATIONS;
    -  var a0 = createRandomVec4Array(nVecs);
    -  var a1 = createRandomVec4Array(nVecs);
    -  var a2 = createRandomVec4Array(nVecs);
    -  var i0 = createRandomIndexArray(nVecs);
    -  var i1 = createRandomIndexArray(nVecs);
    -  var i2 = createRandomIndexArray(nVecs);
    -
    -  table.run(
    -      function() {
    -        for (var i = 0; i < nVecs; i++) {
    -          addVec4(a0[i0[i]], a1[i1[i]], a2[i2[i]]);
    -        }
    -      },
    -      'Add random vectors using an array of Vec4s');
    -}
    -
    -// Make sure the tests are run in the order they are defined.
    -var testCase = new goog.testing.TestCase(document.title);
    -testCase.order = goog.testing.TestCase.Order.NATURAL;
    -testCase.autoDiscoverTests();
    -G_testRunner.initialize(testCase);
    -
    - </script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/vec/vec_perf.html b/src/database/third_party/closure-library/closure/goog/vec/vec_perf.html
    deleted file mode 100644
    index 1aacb5f676e..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/vec/vec_perf.html
    +++ /dev/null
    @@ -1,101 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    -
    -Author: nicksantos@google.com (Nick Santos)
    --->
    -<head>
    -<meta http-equiv="X-UA-Compatible" content="IE=edge">
    -  <title>Closure Performance Tests - Vector math</title>
    -  <link rel="stylesheet" type="text/css"
    -        href="../testing/performancetable.css"/>
    -  <script src="../base.js"></script>
    -  <script>
    -    goog.require('goog.crypt');
    -    goog.require('goog.string');
    -    goog.require('goog.testing.PerformanceTable');
    -    goog.require('goog.testing.jsunit');
    -    goog.require('goog.vec.Vec4');
    -  </script>
    -</head>
    -<body>
    -  <h1>Closure Performance Tests - Vector Math</h1>
    -  <p>
    -    <strong>User-agent:</strong>
    -    <script>document.write(navigator.userAgent);</script>
    -  </p>
    -  <div id="perfTable"></div>
    -  <hr>
    -
    -  <script>
    -    var table = new goog.testing.PerformanceTable(
    -        goog.dom.getElement('perfTable'));
    -    var createVec4FromValues = goog.vec.Vec4.createFromValues;
    -    var scaleVec4 = goog.vec.Vec4.scale;
    -
    -    var negateVec4ByScaling = function(v, result) {
    -      return scaleVec4(v, -1, result);
    -    };
    -
    -    var negateVec4ByNegation = function(v, result) {
    -      result[0] = -v[0];
    -      result[1] = -v[1];
    -      result[2] = -v[2];
    -      result[3] = -v[3];
    -      return result;
    -    };
    -
    -    var negateVec4ByMultiplication = function(v, result) {
    -      result[0] = -1 * v[0];
    -      result[1] = -1 * v[1];
    -      result[2] = -1 * v[2];
    -      result[3] = -1 * v[3];
    -      return result;
    -    };
    -
    -    function createRandomVec4() {
    -      return createVec4FromValues(
    -          Math.random(),
    -          Math.random(),
    -          Math.random(),
    -          Math.random());
    -    }
    -
    -    function testNegateVec4ByScaling() {
    -      var v = createRandomVec4();
    -      for (var i = 0; i < 2000000; i++) {
    -        // Warm the trace tree to see if that makes a difference.
    -        scaleVec4(v, 1, v);
    -      }
    -
    -      table.run(
    -          function() {
    -            for (var i = 0; i < 2000000; i++) {
    -              negateVec4ByScaling(v, v);
    -            }
    -          },
    -          'Negate vector by calling scale()');
    -    }
    -
    -    function testNegateVec4ByNegation() {
    -      var v = createRandomVec4();
    -      for (var i = 0; i < 2000000; i++) {
    -        // Warm the trace tree to see if that makes a difference.
    -        scaleVec4(v, 1, v);
    -      }
    -
    -      table.run(
    -          function() {
    -            for (var i = 0; i < 2000000; i++) {
    -              negateVec4ByNegation(v, v);
    -            }
    -          },
    -          'Negate vector by negating directly');
    -    }
    -  </script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/webgl/webgl.js b/src/database/third_party/closure-library/closure/goog/webgl/webgl.js
    deleted file mode 100644
    index 3c4235739b8..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/webgl/webgl.js
    +++ /dev/null
    @@ -1,2194 +0,0 @@
    -// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @fileoverview Constants used by the WebGL rendering, including all of the
    - * constants used from the WebGL context.  For example, instead of using
    - * context.ARRAY_BUFFER, your code can use
    - * goog.webgl.ARRAY_BUFFER. The benefits for doing this include allowing
    - * the compiler to optimize your code so that the compiled code does not have to
    - * contain large strings to reference these properties, and reducing runtime
    - * property access.
    - *
    - * Values are taken from the WebGL Spec:
    - * https://www.khronos.org/registry/webgl/specs/1.0/#WEBGLRENDERINGCONTEXT
    - */
    -
    -goog.provide('goog.webgl');
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.DEPTH_BUFFER_BIT = 0x00000100;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.STENCIL_BUFFER_BIT = 0x00000400;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.COLOR_BUFFER_BIT = 0x00004000;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.POINTS = 0x0000;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.LINES = 0x0001;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.LINE_LOOP = 0x0002;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.LINE_STRIP = 0x0003;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TRIANGLES = 0x0004;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TRIANGLE_STRIP = 0x0005;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TRIANGLE_FAN = 0x0006;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.ZERO = 0;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.ONE = 1;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.SRC_COLOR = 0x0300;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.ONE_MINUS_SRC_COLOR = 0x0301;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.SRC_ALPHA = 0x0302;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.ONE_MINUS_SRC_ALPHA = 0x0303;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.DST_ALPHA = 0x0304;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.ONE_MINUS_DST_ALPHA = 0x0305;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.DST_COLOR = 0x0306;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.ONE_MINUS_DST_COLOR = 0x0307;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.SRC_ALPHA_SATURATE = 0x0308;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.FUNC_ADD = 0x8006;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.BLEND_EQUATION = 0x8009;
    -
    -
    -/**
    - * Same as BLEND_EQUATION
    - * @const
    - * @type {number}
    - */
    -goog.webgl.BLEND_EQUATION_RGB = 0x8009;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.BLEND_EQUATION_ALPHA = 0x883D;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.FUNC_SUBTRACT = 0x800A;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.FUNC_REVERSE_SUBTRACT = 0x800B;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.BLEND_DST_RGB = 0x80C8;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.BLEND_SRC_RGB = 0x80C9;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.BLEND_DST_ALPHA = 0x80CA;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.BLEND_SRC_ALPHA = 0x80CB;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.CONSTANT_COLOR = 0x8001;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.ONE_MINUS_CONSTANT_COLOR = 0x8002;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.CONSTANT_ALPHA = 0x8003;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.ONE_MINUS_CONSTANT_ALPHA = 0x8004;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.BLEND_COLOR = 0x8005;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.ARRAY_BUFFER = 0x8892;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.ELEMENT_ARRAY_BUFFER = 0x8893;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.ARRAY_BUFFER_BINDING = 0x8894;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.ELEMENT_ARRAY_BUFFER_BINDING = 0x8895;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.STREAM_DRAW = 0x88E0;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.STATIC_DRAW = 0x88E4;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.DYNAMIC_DRAW = 0x88E8;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.BUFFER_SIZE = 0x8764;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.BUFFER_USAGE = 0x8765;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.CURRENT_VERTEX_ATTRIB = 0x8626;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.FRONT = 0x0404;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.BACK = 0x0405;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.FRONT_AND_BACK = 0x0408;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.CULL_FACE = 0x0B44;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.BLEND = 0x0BE2;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.DITHER = 0x0BD0;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.STENCIL_TEST = 0x0B90;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.DEPTH_TEST = 0x0B71;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.SCISSOR_TEST = 0x0C11;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.POLYGON_OFFSET_FILL = 0x8037;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.SAMPLE_ALPHA_TO_COVERAGE = 0x809E;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.SAMPLE_COVERAGE = 0x80A0;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.NO_ERROR = 0;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.INVALID_ENUM = 0x0500;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.INVALID_VALUE = 0x0501;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.INVALID_OPERATION = 0x0502;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.OUT_OF_MEMORY = 0x0505;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.CW = 0x0900;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.CCW = 0x0901;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.LINE_WIDTH = 0x0B21;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.ALIASED_POINT_SIZE_RANGE = 0x846D;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.ALIASED_LINE_WIDTH_RANGE = 0x846E;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.CULL_FACE_MODE = 0x0B45;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.FRONT_FACE = 0x0B46;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.DEPTH_RANGE = 0x0B70;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.DEPTH_WRITEMASK = 0x0B72;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.DEPTH_CLEAR_VALUE = 0x0B73;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.DEPTH_FUNC = 0x0B74;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.STENCIL_CLEAR_VALUE = 0x0B91;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.STENCIL_FUNC = 0x0B92;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.STENCIL_FAIL = 0x0B94;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.STENCIL_PASS_DEPTH_FAIL = 0x0B95;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.STENCIL_PASS_DEPTH_PASS = 0x0B96;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.STENCIL_REF = 0x0B97;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.STENCIL_VALUE_MASK = 0x0B93;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.STENCIL_WRITEMASK = 0x0B98;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.STENCIL_BACK_FUNC = 0x8800;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.STENCIL_BACK_FAIL = 0x8801;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.STENCIL_BACK_PASS_DEPTH_FAIL = 0x8802;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.STENCIL_BACK_PASS_DEPTH_PASS = 0x8803;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.STENCIL_BACK_REF = 0x8CA3;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.STENCIL_BACK_VALUE_MASK = 0x8CA4;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.STENCIL_BACK_WRITEMASK = 0x8CA5;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.VIEWPORT = 0x0BA2;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.SCISSOR_BOX = 0x0C10;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.COLOR_CLEAR_VALUE = 0x0C22;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.COLOR_WRITEMASK = 0x0C23;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.UNPACK_ALIGNMENT = 0x0CF5;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.PACK_ALIGNMENT = 0x0D05;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.MAX_TEXTURE_SIZE = 0x0D33;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.MAX_VIEWPORT_DIMS = 0x0D3A;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.SUBPIXEL_BITS = 0x0D50;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.RED_BITS = 0x0D52;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.GREEN_BITS = 0x0D53;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.BLUE_BITS = 0x0D54;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.ALPHA_BITS = 0x0D55;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.DEPTH_BITS = 0x0D56;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.STENCIL_BITS = 0x0D57;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.POLYGON_OFFSET_UNITS = 0x2A00;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.POLYGON_OFFSET_FACTOR = 0x8038;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE_BINDING_2D = 0x8069;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.SAMPLE_BUFFERS = 0x80A8;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.SAMPLES = 0x80A9;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.SAMPLE_COVERAGE_VALUE = 0x80AA;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.SAMPLE_COVERAGE_INVERT = 0x80AB;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.COMPRESSED_TEXTURE_FORMATS = 0x86A3;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.DONT_CARE = 0x1100;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.FASTEST = 0x1101;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.NICEST = 0x1102;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.GENERATE_MIPMAP_HINT = 0x8192;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.BYTE = 0x1400;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.UNSIGNED_BYTE = 0x1401;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.SHORT = 0x1402;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.UNSIGNED_SHORT = 0x1403;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.INT = 0x1404;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.UNSIGNED_INT = 0x1405;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.FLOAT = 0x1406;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.DEPTH_COMPONENT = 0x1902;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.ALPHA = 0x1906;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.RGB = 0x1907;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.RGBA = 0x1908;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.LUMINANCE = 0x1909;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.LUMINANCE_ALPHA = 0x190A;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.UNSIGNED_SHORT_4_4_4_4 = 0x8033;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.UNSIGNED_SHORT_5_5_5_1 = 0x8034;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.UNSIGNED_SHORT_5_6_5 = 0x8363;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.FRAGMENT_SHADER = 0x8B30;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.VERTEX_SHADER = 0x8B31;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.MAX_VERTEX_ATTRIBS = 0x8869;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.MAX_VARYING_VECTORS = 0x8DFC;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.MAX_COMBINED_TEXTURE_IMAGE_UNITS = 0x8B4D;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.MAX_TEXTURE_IMAGE_UNITS = 0x8872;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.SHADER_TYPE = 0x8B4F;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.DELETE_STATUS = 0x8B80;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.LINK_STATUS = 0x8B82;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.VALIDATE_STATUS = 0x8B83;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.ATTACHED_SHADERS = 0x8B85;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.ACTIVE_UNIFORMS = 0x8B86;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.ACTIVE_ATTRIBUTES = 0x8B89;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.SHADING_LANGUAGE_VERSION = 0x8B8C;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.CURRENT_PROGRAM = 0x8B8D;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.NEVER = 0x0200;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.LESS = 0x0201;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.EQUAL = 0x0202;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.LEQUAL = 0x0203;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.GREATER = 0x0204;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.NOTEQUAL = 0x0205;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.GEQUAL = 0x0206;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.ALWAYS = 0x0207;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.KEEP = 0x1E00;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.REPLACE = 0x1E01;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.INCR = 0x1E02;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.DECR = 0x1E03;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.INVERT = 0x150A;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.INCR_WRAP = 0x8507;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.DECR_WRAP = 0x8508;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.VENDOR = 0x1F00;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.RENDERER = 0x1F01;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.VERSION = 0x1F02;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.NEAREST = 0x2600;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.LINEAR = 0x2601;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.NEAREST_MIPMAP_NEAREST = 0x2700;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.LINEAR_MIPMAP_NEAREST = 0x2701;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.NEAREST_MIPMAP_LINEAR = 0x2702;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.LINEAR_MIPMAP_LINEAR = 0x2703;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE_MAG_FILTER = 0x2800;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE_MIN_FILTER = 0x2801;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE_WRAP_S = 0x2802;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE_WRAP_T = 0x2803;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE_2D = 0x0DE1;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE = 0x1702;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE_CUBE_MAP = 0x8513;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE_BINDING_CUBE_MAP = 0x8514;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE0 = 0x84C0;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE1 = 0x84C1;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE2 = 0x84C2;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE3 = 0x84C3;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE4 = 0x84C4;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE5 = 0x84C5;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE6 = 0x84C6;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE7 = 0x84C7;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE8 = 0x84C8;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE9 = 0x84C9;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE10 = 0x84CA;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE11 = 0x84CB;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE12 = 0x84CC;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE13 = 0x84CD;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE14 = 0x84CE;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE15 = 0x84CF;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE16 = 0x84D0;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE17 = 0x84D1;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE18 = 0x84D2;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE19 = 0x84D3;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE20 = 0x84D4;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE21 = 0x84D5;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE22 = 0x84D6;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE23 = 0x84D7;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE24 = 0x84D8;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE25 = 0x84D9;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE26 = 0x84DA;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE27 = 0x84DB;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE28 = 0x84DC;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE29 = 0x84DD;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE30 = 0x84DE;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE31 = 0x84DF;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.ACTIVE_TEXTURE = 0x84E0;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.REPEAT = 0x2901;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.CLAMP_TO_EDGE = 0x812F;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.MIRRORED_REPEAT = 0x8370;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.FLOAT_VEC2 = 0x8B50;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.FLOAT_VEC3 = 0x8B51;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.FLOAT_VEC4 = 0x8B52;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.INT_VEC2 = 0x8B53;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.INT_VEC3 = 0x8B54;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.INT_VEC4 = 0x8B55;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.BOOL = 0x8B56;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.BOOL_VEC2 = 0x8B57;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.BOOL_VEC3 = 0x8B58;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.BOOL_VEC4 = 0x8B59;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.FLOAT_MAT2 = 0x8B5A;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.FLOAT_MAT3 = 0x8B5B;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.FLOAT_MAT4 = 0x8B5C;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.SAMPLER_2D = 0x8B5E;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.SAMPLER_CUBE = 0x8B60;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.VERTEX_ATTRIB_ARRAY_ENABLED = 0x8622;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.VERTEX_ATTRIB_ARRAY_SIZE = 0x8623;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.VERTEX_ATTRIB_ARRAY_STRIDE = 0x8624;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.VERTEX_ATTRIB_ARRAY_TYPE = 0x8625;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.VERTEX_ATTRIB_ARRAY_NORMALIZED = 0x886A;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.VERTEX_ATTRIB_ARRAY_POINTER = 0x8645;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 0x889F;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.COMPILE_STATUS = 0x8B81;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.LOW_FLOAT = 0x8DF0;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.MEDIUM_FLOAT = 0x8DF1;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.HIGH_FLOAT = 0x8DF2;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.LOW_INT = 0x8DF3;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.MEDIUM_INT = 0x8DF4;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.HIGH_INT = 0x8DF5;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.FRAMEBUFFER = 0x8D40;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.RENDERBUFFER = 0x8D41;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.RGBA4 = 0x8056;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.RGB5_A1 = 0x8057;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.RGB565 = 0x8D62;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.DEPTH_COMPONENT16 = 0x81A5;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.STENCIL_INDEX = 0x1901;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.STENCIL_INDEX8 = 0x8D48;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.DEPTH_STENCIL = 0x84F9;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.RENDERBUFFER_WIDTH = 0x8D42;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.RENDERBUFFER_HEIGHT = 0x8D43;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.RENDERBUFFER_INTERNAL_FORMAT = 0x8D44;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.RENDERBUFFER_RED_SIZE = 0x8D50;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.RENDERBUFFER_GREEN_SIZE = 0x8D51;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.RENDERBUFFER_BLUE_SIZE = 0x8D52;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.RENDERBUFFER_ALPHA_SIZE = 0x8D53;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.RENDERBUFFER_DEPTH_SIZE = 0x8D54;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.RENDERBUFFER_STENCIL_SIZE = 0x8D55;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = 0x8CD0;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = 0x8CD1;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = 0x8CD2;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = 0x8CD3;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.COLOR_ATTACHMENT0 = 0x8CE0;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.DEPTH_ATTACHMENT = 0x8D00;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.STENCIL_ATTACHMENT = 0x8D20;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.DEPTH_STENCIL_ATTACHMENT = 0x821A;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.NONE = 0;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.FRAMEBUFFER_COMPLETE = 0x8CD5;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 0x8CD6;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 0x8CD7;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS = 0x8CD9;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.FRAMEBUFFER_UNSUPPORTED = 0x8CDD;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.FRAMEBUFFER_BINDING = 0x8CA6;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.RENDERBUFFER_BINDING = 0x8CA7;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.MAX_RENDERBUFFER_SIZE = 0x84E8;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.INVALID_FRAMEBUFFER_OPERATION = 0x0506;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.UNPACK_FLIP_Y_WEBGL = 0x9240;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.CONTEXT_LOST_WEBGL = 0x9242;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243;
    -
    -
    -/**
    - * @const
    - * @type {number}
    - */
    -goog.webgl.BROWSER_DEFAULT_WEBGL = 0x9244;
    -
    -
    -/**
    - * From the OES_texture_half_float extension.
    - * http://www.khronos.org/registry/webgl/extensions/OES_texture_half_float/
    - * @const
    - * @type {number}
    - */
    -goog.webgl.HALF_FLOAT_OES = 0x8D61;
    -
    -
    -/**
    - * From the OES_standard_derivatives extension.
    - * http://www.khronos.org/registry/webgl/extensions/OES_standard_derivatives/
    - * @const
    - * @type {number}
    - */
    -goog.webgl.FRAGMENT_SHADER_DERIVATIVE_HINT_OES = 0x8B8B;
    -
    -
    -/**
    - * From the OES_vertex_array_object extension.
    - * http://www.khronos.org/registry/webgl/extensions/OES_vertex_array_object/
    - * @const
    - * @type {number}
    - */
    -goog.webgl.VERTEX_ARRAY_BINDING_OES = 0x85B5;
    -
    -
    -/**
    - * From the WEBGL_debug_renderer_info extension.
    - * http://www.khronos.org/registry/webgl/extensions/WEBGL_debug_renderer_info/
    - * @const
    - * @type {number}
    - */
    -goog.webgl.UNMASKED_VENDOR_WEBGL = 0x9245;
    -
    -
    -/**
    - * From the WEBGL_debug_renderer_info extension.
    - * http://www.khronos.org/registry/webgl/extensions/WEBGL_debug_renderer_info/
    - * @const
    - * @type {number}
    - */
    -goog.webgl.UNMASKED_RENDERER_WEBGL = 0x9246;
    -
    -
    -/**
    - * From the WEBGL_compressed_texture_s3tc extension.
    - * http://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_s3tc/
    - * @const
    - * @type {number}
    - */
    -goog.webgl.COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0;
    -
    -
    -/**
    - * From the WEBGL_compressed_texture_s3tc extension.
    - * http://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_s3tc/
    - * @const
    - * @type {number}
    - */
    -goog.webgl.COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1;
    -
    -
    -/**
    - * From the WEBGL_compressed_texture_s3tc extension.
    - * http://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_s3tc/
    - * @const
    - * @type {number}
    - */
    -goog.webgl.COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2;
    -
    -
    -/**
    - * From the WEBGL_compressed_texture_s3tc extension.
    - * http://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_s3tc/
    - * @const
    - * @type {number}
    - */
    -goog.webgl.COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3;
    -
    -
    -/**
    - * From the EXT_texture_filter_anisotropic extension.
    - * http://www.khronos.org/registry/webgl/extensions/EXT_texture_filter_anisotropic/
    - * @const
    - * @type {number}
    - */
    -goog.webgl.TEXTURE_MAX_ANISOTROPY_EXT = 0x84FE;
    -
    -
    -/**
    - * From the EXT_texture_filter_anisotropic extension.
    - * http://www.khronos.org/registry/webgl/extensions/EXT_texture_filter_anisotropic/
    - * @const
    - * @type {number}
    - */
    -goog.webgl.MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF;
    diff --git a/src/database/third_party/closure-library/closure/goog/window/window.js b/src/database/third_party/closure-library/closure/goog/window/window.js
    deleted file mode 100644
    index a937727c853..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/window/window.js
    +++ /dev/null
    @@ -1,225 +0,0 @@
    -// Copyright 2006 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -/**
    - * @fileoverview Utilities for window manipulation.
    - */
    -
    -
    -goog.provide('goog.window');
    -
    -goog.require('goog.string');
    -goog.require('goog.userAgent');
    -
    -
    -/**
    - * Default height for popup windows
    - * @type {number}
    - */
    -goog.window.DEFAULT_POPUP_HEIGHT = 500;
    -
    -
    -/**
    - * Default width for popup windows
    - * @type {number}
    - */
    -goog.window.DEFAULT_POPUP_WIDTH = 690;
    -
    -
    -/**
    - * Default target for popup windows
    - * @type {string}
    - */
    -goog.window.DEFAULT_POPUP_TARGET = 'google_popup';
    -
    -
    -/**
    - * Opens a new window.
    - *
    - * @param {string|Object} linkRef A string or an object that supports toString,
    - *     for example goog.Uri.  If this is an object with a 'href' attribute, such
    - *     as HTMLAnchorElement, it will be used instead.
    - *
    - * @param {Object=} opt_options supports the following options:
    - *  'target': (string) target (window name). If null, linkRef.target will
    - *          be used.
    - *  'width': (number) window width.
    - *  'height': (number) window height.
    - *  'top': (number) distance from top of screen
    - *  'left': (number) distance from left of screen
    - *  'toolbar': (boolean) show toolbar
    - *  'scrollbars': (boolean) show scrollbars
    - *  'location': (boolean) show location
    - *  'statusbar': (boolean) show statusbar
    - *  'menubar': (boolean) show menubar
    - *  'resizable': (boolean) resizable
    - *  'noreferrer': (boolean) whether to attempt to remove the referrer header
    - *      from the request headers. Does this by opening a blank window that
    - *      then redirects to the target url, so users may see some flickering.
    - *
    - * @param {Window=} opt_parentWin Parent window that should be used to open the
    - *                 new window.
    - *
    - * @return {Window} Returns the window object that was opened. This returns
    - *                  null if a popup blocker prevented the window from being
    - *                  opened.
    - */
    -goog.window.open = function(linkRef, opt_options, opt_parentWin) {
    -  if (!opt_options) {
    -    opt_options = {};
    -  }
    -  var parentWin = opt_parentWin || window;
    -
    -  // HTMLAnchorElement has a toString() method with the same behavior as
    -  // goog.Uri in all browsers except for Safari, which returns
    -  // '[object HTMLAnchorElement]'.  We check for the href first, then
    -  // assume that it's a goog.Uri or String otherwise.
    -  var href = typeof linkRef.href != 'undefined' ? linkRef.href :
    -      String(linkRef);
    -  var target = opt_options.target || linkRef.target;
    -
    -  var sb = [];
    -  for (var option in opt_options) {
    -    switch (option) {
    -      case 'width':
    -      case 'height':
    -      case 'top':
    -      case 'left':
    -        sb.push(option + '=' + opt_options[option]);
    -        break;
    -      case 'target':
    -      case 'noreferrer':
    -        break;
    -      default:
    -        sb.push(option + '=' + (opt_options[option] ? 1 : 0));
    -    }
    -  }
    -  var optionString = sb.join(',');
    -
    -  var newWin;
    -  if (opt_options['noreferrer']) {
    -    // Use a meta-refresh to stop the referrer from being included in the
    -    // request headers.
    -    newWin = parentWin.open('', target, optionString);
    -    if (newWin) {
    -      if (goog.userAgent.IE) {
    -        // IE has problems parsing the content attribute if the url contains
    -        // a semicolon. We can fix this by adding quotes around the url, but
    -        // then we can't parse quotes in the URL correctly. We take a
    -        // best-effort approach.
    -        //
    -        // If the URL has semicolons, wrap it in single quotes to protect
    -        // the semicolons.
    -        // If the URL has semicolons and single quotes, url-encode the single
    -        // quotes as well.
    -        //
    -        // This is imperfect. Notice that both ' and ; are reserved characters
    -        // in URIs, so this could do the wrong thing, but at least it will
    -        // do the wrong thing in only rare cases.
    -        // ugh.
    -        if (href.indexOf(';') != -1) {
    -          href = "'" + href.replace(/'/g, '%27') + "'";
    -        }
    -      }
    -      newWin.opener = null;
    -      href = goog.string.htmlEscape(href);
    -      newWin.document.write('<META HTTP-EQUIV="refresh" content="0; url=' +
    -                            href + '">');
    -      newWin.document.close();
    -    }
    -  } else {
    -    newWin = parentWin.open(href, target, optionString);
    -  }
    -  // newWin is null if a popup blocker prevented the window open.
    -  return newWin;
    -};
    -
    -
    -/**
    - * Opens a new window without any real content in it.
    - *
    - * This can be used to get around popup blockers if you need to open a window
    - * in response to a user event, but need to do asynchronous work to determine
    - * the URL to open, and then set the URL later.
    - *
    - * Example usage:
    - *
    - * var newWin = goog.window.openBlank('Loading...');
    - * setTimeout(
    - *     function() {
    - *       newWin.location.href = 'http://www.google.com';
    - *     }, 100);
    - *
    - * @param {string=} opt_message String to show in the new window. This string
    - *     will be HTML-escaped to avoid XSS issues.
    - * @param {Object=} opt_options Options to open window with.
    - *     {@see goog.window.open for exact option semantics}.
    - * @param {Window=} opt_parentWin Parent window that should be used to open the
    - *                 new window.
    - * @return {Window} Returns the window object that was opened. This returns
    - *                  null if a popup blocker prevented the window from being
    - *                  opened.
    - */
    -goog.window.openBlank = function(opt_message, opt_options, opt_parentWin) {
    -
    -  // Open up a window with the loading message and nothing else.
    -  // This will be interpreted as HTML content type with a missing doctype
    -  // and html/body tags, but is otherwise acceptable.
    -  var loadingMessage = opt_message ? goog.string.htmlEscape(opt_message) : '';
    -  return /** @type {Window} */ (goog.window.open(
    -      'javascript:"' + encodeURI(loadingMessage) + '"',
    -      opt_options, opt_parentWin));
    -};
    -
    -
    -/**
    - * Raise a help popup window, defaulting to "Google standard" size and name.
    - *
    - * (If your project is using GXPs, consider using {@link PopUpLink.gxp}.)
    - *
    - * @param {string|Object} linkRef if this is a string, it will be used as the
    - * URL of the popped window; otherwise it's assumed to be an HTMLAnchorElement
    - * (or some other object with "target" and "href" properties).
    - *
    - * @param {Object=} opt_options Options to open window with.
    - *     {@see goog.window.open for exact option semantics}
    - *     Additional wrinkles to the options:
    - *     - if 'target' field is null, linkRef.target will be used. If *that's*
    - *     null, the default is "google_popup".
    - *     - if 'width' field is not specified, the default is 690.
    - *     - if 'height' field is not specified, the default is 500.
    - *
    - * @return {boolean} true if the window was not popped up, false if it was.
    - */
    -goog.window.popup = function(linkRef, opt_options) {
    -  if (!opt_options) {
    -    opt_options = {};
    -  }
    -
    -  // set default properties
    -  opt_options['target'] = opt_options['target'] ||
    -      linkRef['target'] || goog.window.DEFAULT_POPUP_TARGET;
    -  opt_options['width'] = opt_options['width'] ||
    -      goog.window.DEFAULT_POPUP_WIDTH;
    -  opt_options['height'] = opt_options['height'] ||
    -      goog.window.DEFAULT_POPUP_HEIGHT;
    -
    -  var newWin = goog.window.open(linkRef, opt_options);
    -  if (!newWin) {
    -    return true;
    -  }
    -  newWin.focus();
    -
    -  return false;
    -};
    diff --git a/src/database/third_party/closure-library/closure/goog/window/window_test.html b/src/database/third_party/closure-library/closure/goog/window/window_test.html
    deleted file mode 100644
    index 20f779386f6..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/window/window_test.html
    +++ /dev/null
    @@ -1,44 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -Use of this source code is governed by the Apache License, Version 2.0.
    -See the COPYING file for details.
    --->
    -<!--
    -
    -  @author marcosalmeida@google.com (Marcos Almeida)
    --->
    - <head>
    -  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    -  <title>
    -   Closure Unit Tests - goog.window
    -  </title>
    -  <script src="../base.js">
    -  </script>
    -  <script>
    -    goog.require('goog.windowTest');
    -  </script>
    -  <style type="text/css">
    -   .goog-like-link {
    -  color: blue;
    -  text-decoration: underline;
    -  cursor: pointer;
    -}
    -
    -</style>
    -</head>
    -<body>
    -
    -<h4>Some links for testing referrer stripping manually.</h4>
    -<div class='goog-like-link'>http://www.google.com/search?q=;</div>
    -<div class='goog-like-link'>http://www.google.com/search?q=x&amp;lang=en</div>
    -<div class='goog-like-link'>http://www.google.com/search?q=x;lang=en</div>
    -<div class='goog-like-link'>http://www.google.com/search?q="</div>
    -<div class='goog-like-link'>http://www.google.com/search?q='</div>
    -<div class='goog-like-link'>http://www.google.com/search?q=&lt;</div>
    -<div class='goog-like-link'>http://www.google.com/search?q=&gt;</div>
    -
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/closure/goog/window/window_test.js b/src/database/third_party/closure-library/closure/goog/window/window_test.js
    deleted file mode 100644
    index add715d0e73..00000000000
    --- a/src/database/third_party/closure-library/closure/goog/window/window_test.js
    +++ /dev/null
    @@ -1,217 +0,0 @@
    -// Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -goog.provide('goog.windowTest');
    -goog.setTestOnly('goog.windowTest');
    -
    -goog.require('goog.dom');
    -goog.require('goog.events');
    -goog.require('goog.string');
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.jsunit');
    -goog.require('goog.window');
    -
    -var newWin;
    -var REDIRECT_URL_PREFIX = 'window_test.html?runTests=';
    -var asyncTestCase =
    -    goog.testing.AsyncTestCase.createAndInstall(document.title);
    -asyncTestCase.stepTimeout = 5000;
    -
    -var WIN_LOAD_TRY_TIMEOUT = 100;
    -var MAX_WIN_LOAD_TRIES = 50; // 50x100ms = 5s waiting for window to load.
    -var winLoadCounter;
    -
    -function setUpPage() {
    -  var anchors = goog.dom.getElementsByTagNameAndClass(
    -      'div', 'goog-like-link');
    -  for (var i = 0; i < anchors.length; i++) {
    -    goog.events.listen(
    -        anchors[i], 'click',
    -        function(e) {
    -          goog.window.open(
    -              goog.dom.getTextContent(e.target), {'noreferrer': true});
    -        });
    -  }
    -}
    -
    -
    -/**
    - * Some tests should only run locally, because they will trigger
    - * popup blockers on http urls.
    - */
    -function canOpenPopups() {
    -  // TODO(nicksantos): Fix the test runner farm.
    -  return window.location.toString().indexOf('file://') == 0;
    -}
    -
    -if (canOpenPopups()) {
    -  // To test goog.window.open we open a new window with this file again. Once
    -  // the new window gets to this point in the file it notifies the opener that
    -  // it has loaded, so that the opener knows that the new window has been
    -  // populated with properties like referrer and location.
    -  var newWinLoaded = false;
    -  if (window.opener && window.opener.newWinLoaded === false) {
    -    window.opener.newWinLoaded = true;
    -  }
    -}
    -
    -function setUp() {
    -  newWinLoaded = false;
    -}
    -
    -function tearDown() {
    -  if (newWin) {
    -    newWin.close();
    -  }
    -}
    -
    -
    -/**
    - * Uses setTimeout to keep checking if a new window has been loaded, and once
    - * it has, calls the given continuation function and then calls
    - * asyncTestCase.continueTesting() to resume the flow of the test.
    - * @param {Function} continueFn Continuation function to be called when the
    - *     new window has loaded.
    - * @param {number=} opt_numTries Number of times this method has checked if
    - *     the window has loaded, to prevent getting in an endless setTimeout
    - *     loop. (Used internally, callers should omit.)
    - */
    -function continueAfterWindowLoaded(continueFn, opt_numTries) {
    -  opt_numTries = opt_numTries || 0;
    -  if (newWinLoaded) {
    -    continueFn();
    -    asyncTestCase.continueTesting();
    -  } else if (opt_numTries > MAX_WIN_LOAD_TRIES) {
    -    fail('Window did not load after maximum number of checks.');
    -    asyncTestCase.continueTesting();
    -  } else {
    -    setTimeout(goog.partial(continueAfterWindowLoaded,
    -                            continueFn, ++opt_numTries),
    -               WIN_LOAD_TRY_TIMEOUT);
    -  }
    -}
    -
    -
    -/**
    - * Helper to kick off a test that opens a window and checks that the referrer
    - * is hidden if requested and the url is properly encoded/decoded.
    - * @param {boolean} noreferrer Whether to test the noreferrer option.
    - * @param {string} urlParam Url param to append to the url being opened.
    - */
    -function doTestOpenWindow(noreferrer, urlParam) {
    -  if (!canOpenPopups()) {
    -    return;
    -  }
    -  newWin = goog.window.open(REDIRECT_URL_PREFIX + urlParam,
    -                            {'noreferrer': noreferrer});
    -  asyncTestCase.waitForAsync('Waiting for window to open and load.');
    -  continueAfterWindowLoaded(
    -      goog.partial(continueTestOpenWindow, noreferrer, urlParam));
    -}
    -
    -
    -/**
    - * Helper callback to do asserts after the window opens.
    - * @param {boolean} noreferrer Whether the noreferrer option is being tested.
    - * @param {string} urlParam Url param appended to the url being opened.
    - */
    -function continueTestOpenWindow(noreferrer, urlParam) {
    -  if (noreferrer) {
    -    assertEquals('Referrer should have been stripped',
    -                 '', newWin.document.referrer);
    -  }
    -
    -  var newWinUrl = decodeURI(newWin.location);
    -  var expectedUrlSuffix = decodeURI(urlParam);
    -  assertTrue('New window href should have ended with <' + expectedUrlSuffix +
    -      '> but was <' + newWinUrl + '>',
    -      goog.string.endsWith(newWinUrl, expectedUrlSuffix));
    -}
    -
    -
    -function testOpenNotEncoded() {
    -  doTestOpenWindow(false, '"bogus~"');
    -}
    -
    -function testOpenEncoded() {
    -  doTestOpenWindow(false, '"bogus%7E"');
    -}
    -
    -function testOpenEncodedPercent() {
    -  // Intent of url is to pass %7E to the server, so it was encoded to %257E .
    -  doTestOpenWindow(false, '"bogus%257E"');
    -}
    -
    -function testOpenNotEncodedHidingReferrer() {
    -  doTestOpenWindow(true, '"bogus~"');
    -}
    -
    -function testOpenEncodedHidingReferrer() {
    -  doTestOpenWindow(true, '"bogus%7E"');
    -}
    -
    -function testOpenEncodedPercentHidingReferrer() {
    -  // Intent of url is to pass %7E to the server, so it was encoded to %257E .
    -  doTestOpenWindow(true, '"bogus%257E"');
    -}
    -
    -function testOpenSemicolon() {
    -  doTestOpenWindow(true, 'beforesemi;aftersemi');
    -}
    -
    -function testTwoSemicolons() {
    -  doTestOpenWindow(true, 'a;b;c');
    -}
    -
    -function testOpenAmpersand() {
    -  doTestOpenWindow(true, 'this&that');
    -}
    -
    -function testOpenSingleQuote() {
    -  doTestOpenWindow(true, "'");
    -}
    -
    -function testOpenDoubleQuote() {
    -  doTestOpenWindow(true, '"');
    -}
    -
    -function testOpenDoubleQuote() {
    -  doTestOpenWindow(true, '<');
    -}
    -
    -function testOpenDoubleQuote() {
    -  doTestOpenWindow(true, '>');
    -}
    -
    -function testOpenBlank() {
    -  if (!canOpenPopups()) {
    -    return;
    -  }
    -  newWin = goog.window.openBlank('Loading...');
    -  asyncTestCase.waitForAsync('Waiting for temp window to open and load.');
    -  var urlParam = 'bogus~';
    -
    -  var continueFn = function() {
    -    newWin.location.href = REDIRECT_URL_PREFIX + urlParam;
    -    continueAfterWindowLoaded(
    -        goog.partial(continueTestOpenWindow, false, urlParam));
    -  };
    -  setTimeout(continueFn, 100);
    -}
    -
    -
    -/** @this {Element} */
    -function stripReferrer() {
    -  goog.window.open(this.href, {'noreferrer': true});
    -}
    diff --git a/src/database/third_party/closure-library/third_party/closure/goog/base.js b/src/database/third_party/closure-library/third_party/closure/goog/base.js
    deleted file mode 100644
    index c8890433f59..00000000000
    --- a/src/database/third_party/closure-library/third_party/closure/goog/base.js
    +++ /dev/null
    @@ -1,2 +0,0 @@
    -// This is a dummy file to trick genjsdeps into doing the right thing.
    -// TODO(nicksantos): fix this
    diff --git a/src/database/third_party/closure-library/third_party/closure/goog/caja/string/html/htmlparser.js b/src/database/third_party/closure-library/third_party/closure/goog/caja/string/html/htmlparser.js
    deleted file mode 100644
    index d241d4bb273..00000000000
    --- a/src/database/third_party/closure-library/third_party/closure/goog/caja/string/html/htmlparser.js
    +++ /dev/null
    @@ -1,611 +0,0 @@
    -// Copyright 2006-2008, The Google Caja project.
    -// Modifications Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -// All Rights Reserved
    -
    -/**
    - * @license Portions of this code are from the google-caja project, received by
    - * Google under the Apache license (http://code.google.com/p/google-caja/).
    - * All other code is Copyright 2009 Google, Inc. All Rights Reserved.
    -
    -// Copyright (C) 2006 Google Inc.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    - */
    -
    -/**
    - * @fileoverview A Html SAX parser.
    - *
    - * Examples of usage of the {@code goog.string.html.HtmlParser}:
    - * <pre>
    - *   var handler = new MyCustomHtmlVisitorHandlerThatExtendsHtmlSaxHandler();
    - *   var parser = new goog.string.html.HtmlParser();
    - *   parser.parse(handler, '<html><a href="google.com">link found!</a></html>');
    - * </pre>
    - *
    - * TODO(user, msamuel): validate sanitizer regex against the HTML5 grammar at
    - * http://www.whatwg.org/specs/web-apps/current-work/multipage/syntax.html
    - * http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html
    - * http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html
    - * http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html
    - *
    - * @supported IE6, IE7, IE8, FF1.5, FF2, FF3, Chrome 3.0, Safari and Opera 10.
    - */
    -
    -goog.provide('goog.string.html.HtmlParser');
    -goog.provide('goog.string.html.HtmlParser.EFlags');
    -goog.provide('goog.string.html.HtmlParser.Elements');
    -goog.provide('goog.string.html.HtmlParser.Entities');
    -goog.provide('goog.string.html.HtmlSaxHandler');
    -
    -
    -/**
    - * An Html parser: {@code parse} takes a string and calls methods on
    - * {@code goog.string.html.HtmlSaxHandler} while it is visiting it.
    - *
    - * @constructor
    - */
    -goog.string.html.HtmlParser = function() {
    -};
    -
    -
    -/**
    - * HTML entities that are encoded/decoded.
    - * TODO(user): use {@code goog.string.htmlEncode} instead.
    - * @enum {string}
    - */
    -goog.string.html.HtmlParser.Entities = {
    -  lt: '<',
    -  gt: '>',
    -  amp: '&',
    -  nbsp: '\240',
    -  quot: '"',
    -  apos: '\''
    -};
    -
    -
    -/**
    - * The html eflags, used internally on the parser.
    - * @enum {number}
    - */
    -goog.string.html.HtmlParser.EFlags = {
    -  OPTIONAL_ENDTAG: 1,
    -  EMPTY: 2,
    -  CDATA: 4,
    -  RCDATA: 8,
    -  UNSAFE: 16,
    -  FOLDABLE: 32
    -};
    -
    -
    -/**
    - * A map of element to a bitmap of flags it has, used internally on the parser.
    - * @type {Object}
    - */
    -goog.string.html.HtmlParser.Elements = {
    -  'a': 0,
    -  'abbr': 0,
    -  'acronym': 0,
    -  'address': 0,
    -  'applet': goog.string.html.HtmlParser.EFlags.UNSAFE,
    -  'area': goog.string.html.HtmlParser.EFlags.EMPTY,
    -  'b': 0,
    -  'base': goog.string.html.HtmlParser.EFlags.EMPTY |
    -      goog.string.html.HtmlParser.EFlags.UNSAFE,
    -  'basefont': goog.string.html.HtmlParser.EFlags.EMPTY |
    -      goog.string.html.HtmlParser.EFlags.UNSAFE,
    -  'bdo': 0,
    -  'big': 0,
    -  'blockquote': 0,
    -  'body': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG |
    -      goog.string.html.HtmlParser.EFlags.UNSAFE |
    -      goog.string.html.HtmlParser.EFlags.FOLDABLE,
    -  'br': goog.string.html.HtmlParser.EFlags.EMPTY,
    -  'button': 0,
    -  'caption': 0,
    -  'center': 0,
    -  'cite': 0,
    -  'code': 0,
    -  'col': goog.string.html.HtmlParser.EFlags.EMPTY,
    -  'colgroup': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,
    -  'dd': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,
    -  'del': 0,
    -  'dfn': 0,
    -  'dir': 0,
    -  'div': 0,
    -  'dl': 0,
    -  'dt': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,
    -  'em': 0,
    -  'fieldset': 0,
    -  'font': 0,
    -  'form': 0,
    -  'frame': goog.string.html.HtmlParser.EFlags.EMPTY |
    -      goog.string.html.HtmlParser.EFlags.UNSAFE,
    -  'frameset': goog.string.html.HtmlParser.EFlags.UNSAFE,
    -  'h1': 0,
    -  'h2': 0,
    -  'h3': 0,
    -  'h4': 0,
    -  'h5': 0,
    -  'h6': 0,
    -  'head': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG |
    -      goog.string.html.HtmlParser.EFlags.UNSAFE |
    -      goog.string.html.HtmlParser.EFlags.FOLDABLE,
    -  'hr': goog.string.html.HtmlParser.EFlags.EMPTY,
    -  'html': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG |
    -      goog.string.html.HtmlParser.EFlags.UNSAFE |
    -      goog.string.html.HtmlParser.EFlags.FOLDABLE,
    -  'i': 0,
    -  'iframe': goog.string.html.HtmlParser.EFlags.UNSAFE |
    -      goog.string.html.HtmlParser.EFlags.CDATA,
    -  'img': goog.string.html.HtmlParser.EFlags.EMPTY,
    -  'input': goog.string.html.HtmlParser.EFlags.EMPTY,
    -  'ins': 0,
    -  'isindex': goog.string.html.HtmlParser.EFlags.EMPTY |
    -      goog.string.html.HtmlParser.EFlags.UNSAFE,
    -  'kbd': 0,
    -  'label': 0,
    -  'legend': 0,
    -  'li': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,
    -  'link': goog.string.html.HtmlParser.EFlags.EMPTY |
    -      goog.string.html.HtmlParser.EFlags.UNSAFE,
    -  'map': 0,
    -  'menu': 0,
    -  'meta': goog.string.html.HtmlParser.EFlags.EMPTY |
    -      goog.string.html.HtmlParser.EFlags.UNSAFE,
    -  'noframes': goog.string.html.HtmlParser.EFlags.UNSAFE |
    -      goog.string.html.HtmlParser.EFlags.CDATA,
    -  'noscript': goog.string.html.HtmlParser.EFlags.UNSAFE |
    -      goog.string.html.HtmlParser.EFlags.CDATA,
    -  'object': goog.string.html.HtmlParser.EFlags.UNSAFE,
    -  'ol': 0,
    -  'optgroup': 0,
    -  'option': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,
    -  'p': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,
    -  'param': goog.string.html.HtmlParser.EFlags.EMPTY |
    -      goog.string.html.HtmlParser.EFlags.UNSAFE,
    -  'pre': 0,
    -  'q': 0,
    -  's': 0,
    -  'samp': 0,
    -  'script': goog.string.html.HtmlParser.EFlags.UNSAFE |
    -      goog.string.html.HtmlParser.EFlags.CDATA,
    -  'select': 0,
    -  'small': 0,
    -  'span': 0,
    -  'strike': 0,
    -  'strong': 0,
    -  'style': goog.string.html.HtmlParser.EFlags.UNSAFE |
    -      goog.string.html.HtmlParser.EFlags.CDATA,
    -  'sub': 0,
    -  'sup': 0,
    -  'table': 0,
    -  'tbody': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,
    -  'td': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,
    -  'textarea': goog.string.html.HtmlParser.EFlags.RCDATA,
    -  'tfoot': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,
    -  'th': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,
    -  'thead': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,
    -  'title': goog.string.html.HtmlParser.EFlags.RCDATA |
    -      goog.string.html.HtmlParser.EFlags.UNSAFE,
    -  'tr': goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG,
    -  'tt': 0,
    -  'u': 0,
    -  'ul': 0,
    -  'var': 0
    -};
    -
    -
    -/**
    - * Regular expression that matches &s.
    - * @type {RegExp}
    - * @private
    - */
    -goog.string.html.HtmlParser.AMP_RE_ = /&/g;
    -
    -
    -/**
    - * Regular expression that matches loose &s.
    - * @type {RegExp}
    - * @private
    - */
    -goog.string.html.HtmlParser.LOOSE_AMP_RE_ =
    -    /&([^a-z#]|#(?:[^0-9x]|x(?:[^0-9a-f]|$)|$)|$)/gi;
    -
    -
    -/**
    - * Regular expression that matches <.
    - * @type {RegExp}
    - * @private
    - */
    -goog.string.html.HtmlParser.LT_RE_ = /</g;
    -
    -
    -/**
    - * Regular expression that matches >.
    - * @type {RegExp}
    - * @private
    - */
    -goog.string.html.HtmlParser.GT_RE_ = />/g;
    -
    -
    -/**
    - * Regular expression that matches ".
    - * @type {RegExp}
    - * @private
    - */
    -goog.string.html.HtmlParser.QUOTE_RE_ = /\"/g;
    -
    -
    -/**
    - * Regular expression that matches =.
    - * @type {RegExp}
    - * @private
    - */
    -goog.string.html.HtmlParser.EQUALS_RE_ = /=/g;
    -
    -
    -/**
    - * Regular expression that matches null characters.
    - * @type {RegExp}
    - * @private
    - */
    -goog.string.html.HtmlParser.NULL_RE_ = /\0/g;
    -
    -
    -/**
    - * Regular expression that matches entities.
    - * @type {RegExp}
    - * @private
    - */
    -goog.string.html.HtmlParser.ENTITY_RE_ = /&(#\d+|#x[0-9A-Fa-f]+|\w+);/g;
    -
    -
    -/**
    - * Regular expression that matches decimal numbers.
    - * @type {RegExp}
    - * @private
    - */
    -goog.string.html.HtmlParser.DECIMAL_ESCAPE_RE_ = /^#(\d+)$/;
    -
    -
    -/**
    - * Regular expression that matches hexadecimal numbers.
    - * @type {RegExp}
    - * @private
    - */
    -goog.string.html.HtmlParser.HEX_ESCAPE_RE_ = /^#x([0-9A-Fa-f]+)$/;
    -
    -
    -/**
    - * Regular expression that matches the next token to be processed.
    - * @type {RegExp}
    - * @private
    - */
    -goog.string.html.HtmlParser.INSIDE_TAG_TOKEN_ = new RegExp(
    -    // Don't capture space.
    -    '^\\s*(?:' +
    -    // Capture an attribute name in group 1, and value in group 3.
    -    // We capture the fact that there was an attribute in group 2, since
    -    // interpreters are inconsistent in whether a group that matches nothing
    -    // is null, undefined, or the empty string.
    -    ('(?:' +
    -       '([a-z][a-z-]*)' +                   // attribute name
    -       ('(' +                               // optionally followed
    -          '\\s*=\\s*' +
    -          ('(' +
    -             // A double quoted string.
    -             '\"[^\"]*\"' +
    -             // A single quoted string.
    -             '|\'[^\']*\'' +
    -             // The positive lookahead is used to make sure that in
    -             // <foo bar= baz=boo>, the value for bar is blank, not "baz=boo".
    -             '|(?=[a-z][a-z-]*\\s*=)' +
    -             // An unquoted value that is not an attribute name.
    -             // We know it is not an attribute name because the previous
    -             // zero-width match would've eliminated that possibility.
    -             '|[^>\"\'\\s]*' +
    -             ')'
    -             ) +
    -          ')'
    -          ) + '?' +
    -       ')'
    -       ) +
    -    // End of tag captured in group 3.
    -    '|(/?>)' +
    -    // Don't capture cruft
    -    '|[^a-z\\s>]+)',
    -    'i');
    -
    -
    -/**
    - * Regular expression that matches the next token to be processed when we are
    - * outside a tag.
    - * @type {RegExp}
    - * @private
    - */
    -goog.string.html.HtmlParser.OUTSIDE_TAG_TOKEN_ = new RegExp(
    -    '^(?:' +
    -    // Entity captured in group 1.
    -    '&(\\#[0-9]+|\\#[x][0-9a-f]+|\\w+);' +
    -    // Comment, doctypes, and processing instructions not captured.
    -    '|<[!]--[\\s\\S]*?-->|<!\\w[^>]*>|<\\?[^>*]*>' +
    -    // '/' captured in group 2 for close tags, and name captured in group 3.
    -    '|<(/)?([a-z][a-z0-9]*)' +
    -    // Text captured in group 4.
    -    '|([^<&>]+)' +
    -    // Cruft captured in group 5.
    -    '|([<&>]))',
    -    'i');
    -
    -
    -/**
    - * Given a SAX-like {@code goog.string.html.HtmlSaxHandler} parses a
    - * {@code htmlText} and lets the {@code handler} know the structure while
    - * visiting the nodes.
    - *
    - * @param {goog.string.html.HtmlSaxHandler} handler The HtmlSaxHandler that will
    - *     receive the events.
    - * @param {string} htmlText The html text.
    - */
    -goog.string.html.HtmlParser.prototype.parse = function(handler, htmlText) {
    -  var htmlLower = null;
    -  var inTag = false;  // True iff we're currently processing a tag.
    -  var attribs = [];  // Accumulates attribute names and values.
    -  var tagName;  // The name of the tag currently being processed.
    -  var eflags;  // The element flags for the current tag.
    -  var openTag;  // True if the current tag is an open tag.
    -
    -  // Lets the handler know that we are starting to parse the document.
    -  handler.startDoc();
    -
    -  // Consumes tokens from the htmlText and stops once all tokens are processed.
    -  while (htmlText) {
    -    var regex = inTag ?
    -        goog.string.html.HtmlParser.INSIDE_TAG_TOKEN_ :
    -        goog.string.html.HtmlParser.OUTSIDE_TAG_TOKEN_;
    -    // Gets the next token
    -    var m = htmlText.match(regex);
    -    // And removes it from the string
    -    htmlText = htmlText.substring(m[0].length);
    -
    -    // TODO(goto): cleanup this code breaking it into separate methods.
    -    if (inTag) {
    -      if (m[1]) { // Attribute.
    -        // SetAttribute with uppercase names doesn't work on IE6.
    -        var attribName = goog.string.html.toLowerCase(m[1]);
    -        var decodedValue;
    -        if (m[2]) {
    -          var encodedValue = m[3];
    -          switch (encodedValue.charCodeAt(0)) {  // Strip quotes.
    -            case 34: case 39:
    -              encodedValue = encodedValue.substring(
    -                  1, encodedValue.length - 1);
    -              break;
    -          }
    -          decodedValue = this.unescapeEntities_(this.stripNULs_(encodedValue));
    -        } else {
    -          // Use name as value for valueless attribs, so
    -          //   <input type=checkbox checked>
    -          // gets attributes ['type', 'checkbox', 'checked', 'checked']
    -          decodedValue = attribName;
    -        }
    -        attribs.push(attribName, decodedValue);
    -      } else if (m[4]) {
    -        if (eflags !== void 0) {  // False if not in whitelist.
    -          if (openTag) {
    -            if (handler.startTag) {
    -              handler.startTag(/** @type {string} */ (tagName), attribs);
    -            }
    -          } else {
    -            if (handler.endTag) {
    -              handler.endTag(/** @type {string} */ (tagName));
    -            }
    -          }
    -        }
    -
    -        if (openTag && (eflags &
    -            (goog.string.html.HtmlParser.EFlags.CDATA |
    -             goog.string.html.HtmlParser.EFlags.RCDATA))) {
    -          if (htmlLower === null) {
    -            htmlLower = goog.string.html.toLowerCase (htmlText);
    -          } else {
    -           htmlLower = htmlLower.substring(
    -                htmlLower.length - htmlText.length);
    -          }
    -          var dataEnd = htmlLower.indexOf('</' + tagName);
    -          if (dataEnd < 0) {
    -            dataEnd = htmlText.length;
    -          }
    -          if (eflags & goog.string.html.HtmlParser.EFlags.CDATA) {
    -            if (handler.cdata) {
    -              handler.cdata(htmlText.substring(0, dataEnd));
    -            }
    -          } else if (handler.rcdata) {
    -            handler.rcdata(
    -                this.normalizeRCData_(htmlText.substring(0, dataEnd)));
    -          }
    -          htmlText = htmlText.substring(dataEnd);
    -        }
    -
    -        tagName = eflags = openTag = void 0;
    -        attribs.length = 0;
    -        inTag = false;
    -      }
    -    } else {
    -      if (m[1]) {  // Entity.
    -        handler.pcdata(m[0]);
    -      } else if (m[3]) {  // Tag.
    -        openTag = !m[2];
    -        inTag = true;
    -        tagName = goog.string.html.toLowerCase (m[3]);
    -        eflags = goog.string.html.HtmlParser.Elements.hasOwnProperty(tagName) ?
    -            goog.string.html.HtmlParser.Elements[tagName] : void 0;
    -      } else if (m[4]) {  // Text.
    -        handler.pcdata(m[4]);
    -      } else if (m[5]) {  // Cruft.
    -        switch (m[5]) {
    -          case '<': handler.pcdata('&lt;'); break;
    -          case '>': handler.pcdata('&gt;'); break;
    -          default: handler.pcdata('&amp;'); break;
    -        }
    -      }
    -    }
    -  }
    -
    -  // Lets the handler know that we are done parsing the document.
    -  handler.endDoc();
    -};
    -
    -
    -/**
    - * Decodes an HTML entity.
    - *
    - * @param {string} name The content between the '&' and the ';'.
    - * @return {string} A single unicode code-point as a string.
    - * @private
    - */
    -goog.string.html.HtmlParser.prototype.lookupEntity_ = function(name) {
    -  // TODO(goto): use {goog.string.htmlDecode} instead ?
    -  // TODO(goto): &pi; is different from &Pi;
    -  name = goog.string.html.toLowerCase(name);
    -  if (goog.string.html.HtmlParser.Entities.hasOwnProperty(name)) {
    -    return goog.string.html.HtmlParser.Entities[name];
    -  }
    -  var m = name.match(goog.string.html.HtmlParser.DECIMAL_ESCAPE_RE_);
    -  if (m) {
    -    return String.fromCharCode(parseInt(m[1], 10));
    -  } else if (
    -      !!(m = name.match(goog.string.html.HtmlParser.HEX_ESCAPE_RE_))) {
    -    return String.fromCharCode(parseInt(m[1], 16));
    -  }
    -  return '';
    -};
    -
    -
    -/**
    - * Removes null characters on the string.
    - * @param {string} s The string to have the null characters removed.
    - * @return {string} A string without null characters.
    - * @private
    - */
    -goog.string.html.HtmlParser.prototype.stripNULs_ = function(s) {
    -  return s.replace(goog.string.html.HtmlParser.NULL_RE_, '');
    -};
    -
    -
    -/**
    - * The plain text of a chunk of HTML CDATA which possibly containing.
    - *
    - * TODO(goto): use {@code goog.string.unescapeEntities} instead ?
    - * @param {string} s A chunk of HTML CDATA.  It must not start or end inside
    - *   an HTML entity.
    - * @return {string} The unescaped entities.
    - * @private
    - */
    -goog.string.html.HtmlParser.prototype.unescapeEntities_ = function(s) {
    -  return s.replace(
    -      goog.string.html.HtmlParser.ENTITY_RE_,
    -      goog.bind(this.lookupEntity_, this));
    -};
    -
    -
    -/**
    - * Escape entities in RCDATA that can be escaped without changing the meaning.
    - * @param {string} rcdata The RCDATA string we want to normalize.
    - * @return {string} A normalized version of RCDATA.
    - * @private
    - */
    -goog.string.html.HtmlParser.prototype.normalizeRCData_ = function(rcdata) {
    -  return rcdata.
    -      replace(goog.string.html.HtmlParser.LOOSE_AMP_RE_, '&amp;$1').
    -      replace(goog.string.html.HtmlParser.LT_RE_, '&lt;').
    -      replace(goog.string.html.HtmlParser.GT_RE_, '&gt;');
    -};
    -
    -
    -/**
    - * TODO(goto): why isn't this in the string package ? does this solves any
    - * real problem ? move it to the goog.string package if it does.
    - *
    - * @param {string} str The string to lower case.
    - * @return {string} The str in lower case format.
    - */
    -goog.string.html.toLowerCase = function(str) {
    -  // The below may not be true on browsers in the Turkish locale.
    -  if ('script' === 'SCRIPT'.toLowerCase()) {
    -    return str.toLowerCase();
    -  } else {
    -    return str.replace(/[A-Z]/g, function(ch) {
    -      return String.fromCharCode(ch.charCodeAt(0) | 32);
    -    });
    -  }
    -};
    -
    -
    -/**
    - * An interface to the {@code goog.string.html.HtmlParser} visitor, that gets
    - * called while the HTML is being parsed.
    - *
    - * @constructor
    - */
    -goog.string.html.HtmlSaxHandler = function() {
    -};
    -
    -
    -/**
    - * Handler called when the parser found a new tag.
    - * @param {string} name The name of the tag that is starting.
    - * @param {Array.<string>} attributes The attributes of the tag.
    - */
    -goog.string.html.HtmlSaxHandler.prototype.startTag = goog.abstractMethod;
    -
    -
    -/**
    - * Handler called when the parser found a closing tag.
    - * @param {string} name The name of the tag that is ending.
    - */
    -goog.string.html.HtmlSaxHandler.prototype.endTag = goog.abstractMethod;
    -
    -
    -/**
    - * Handler called when PCDATA is found.
    - * @param {string} text The PCDATA text found.
    - */
    -goog.string.html.HtmlSaxHandler.prototype.pcdata = goog.abstractMethod;
    -
    -
    -/**
    - * Handler called when RCDATA is found.
    - * @param {string} text The RCDATA text found.
    - */
    -goog.string.html.HtmlSaxHandler.prototype.rcdata = goog.abstractMethod;
    -
    -
    -/**
    - * Handler called when CDATA is found.
    - * @param {string} text The CDATA text found.
    - */
    -goog.string.html.HtmlSaxHandler.prototype.cdata = goog.abstractMethod;
    -
    -
    -/**
    - * Handler called when the parser is starting to parse the document.
    - */
    -goog.string.html.HtmlSaxHandler.prototype.startDoc = goog.abstractMethod;
    -
    -
    -/**
    - * Handler called when the parsing is done.
    - */
    -goog.string.html.HtmlSaxHandler.prototype.endDoc = goog.abstractMethod;
    diff --git a/src/database/third_party/closure-library/third_party/closure/goog/caja/string/html/htmlsanitizer.js b/src/database/third_party/closure-library/third_party/closure/goog/caja/string/html/htmlsanitizer.js
    deleted file mode 100644
    index c027bf09a7f..00000000000
    --- a/src/database/third_party/closure-library/third_party/closure/goog/caja/string/html/htmlsanitizer.js
    +++ /dev/null
    @@ -1,605 +0,0 @@
    -// Copyright 2006-2008, The Google Caja project.
    -// Modifications Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -// All Rights Reserved
    -
    -/**
    - * @license Portions of this code are from the google-caja project, received by
    - * Google under the Apache license (http://code.google.com/p/google-caja/).
    - * All other code is Copyright 2009 Google, Inc. All Rights Reserved.
    -
    -// Copyright (C) 2006 Google Inc.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    - */
    -
    -/**
    - * @fileoverview An HTML sanitizer that can satisfy a variety of security
    - * policies. The HTML sanitizer is built around a SAX parser and HTML element
    - * and attributes schemas.
    - *
    - * This package provides html sanitizing and parsing functions.
    - * {@code goog.string.htmlSanitize} is basically just using a custom written
    - * {@code goog.string.HtmlSaxHandler} that outputs safe html as the unsafe
    - * html content is parsed by {@code goog.string.HtmlParser}.
    - *
    - * Examples of usage of the static {@code goog.string.htmlSanitize}:
    - * <pre>
    - *   var safeHtml = goog.string.html.htmlSanitize('<script src="xss.js" />');
    - *   el.innerHTML = safeHtml;
    - * </pre>
    - *
    - * We use {@code goog.string.StringBuffer} for fast string concatenation, since
    - * htmlSanitize is relatively heavy considering that it is designed to parse
    - * large html files.
    - *
    - * @supported IE6, IE7, IE8, FF1.5, FF2, FF3, Chrome 4.0, Safari and Opera 10.
    - */
    -
    -goog.provide('goog.string.html.HtmlSanitizer');
    -goog.provide('goog.string.html.HtmlSanitizer.AttributeType');
    -goog.provide('goog.string.html.HtmlSanitizer.Attributes');
    -goog.provide('goog.string.html.htmlSanitize');
    -
    -goog.require('goog.string.StringBuffer');
    -goog.require('goog.string.html.HtmlParser');
    -goog.require('goog.string.html.HtmlParser.EFlags');
    -goog.require('goog.string.html.HtmlParser.Elements');
    -goog.require('goog.string.html.HtmlSaxHandler');
    -
    -
    -/**
    - * Strips unsafe tags and attributes from HTML.
    - *
    - * @param {string} htmlText The HTML text to sanitize.
    - * @param {function(string): string=} opt_urlPolicy A transform to apply to URL
    - *     attribute values.
    - * @param {function(string): string=} opt_nmTokenPolicy A transform to apply to
    - *     names, IDs, and classes.
    - * @return {string} A sanitized HTML, safe to be embedded on the page.
    - */
    -goog.string.html.htmlSanitize = function(
    -    htmlText, opt_urlPolicy, opt_nmTokenPolicy) {
    -  var stringBuffer = new goog.string.StringBuffer();
    -  var handler = new goog.string.html.HtmlSanitizer(
    -      stringBuffer, opt_urlPolicy, opt_nmTokenPolicy);
    -  var parser = new goog.string.html.HtmlParser();
    -  parser.parse(handler, htmlText);
    -  return stringBuffer.toString();
    -};
    -
    -
    -/**
    - * An implementation of the {@code goog.string.HtmlSaxHandler} interface that
    - * will take each of the html tags and sanitize it.
    - *
    - * @param {goog.string.StringBuffer} stringBuffer A string buffer, used to
    - *     output the html as we sanitize it.
    - * @param {?function(string):string} opt_urlPolicy An optional function to be
    - *     applied in URLs.
    - * @param {?function(string):string} opt_nmTokenPolicy An optional function to
    - *     be applied in names.
    - * @constructor
    - * @extends {goog.string.html.HtmlSaxHandler}
    - */
    -goog.string.html.HtmlSanitizer = function(
    -    stringBuffer, opt_urlPolicy, opt_nmTokenPolicy) {
    -  goog.string.html.HtmlSaxHandler.call(this);
    -
    -  /**
    -   * The string buffer that holds the sanitized version of the html. Used
    -   * during the parse time.
    -   * @type {goog.string.StringBuffer}
    -   * @private
    -   */
    -  this.stringBuffer_ = stringBuffer;
    -
    -  /**
    -   * A stack that holds how the handler is being called.
    -   * @type {Array}
    -   * @private
    -   */
    -  this.stack_ = [];
    -
    -  /**
    -   * Whether we are ignoring what is being processed or not.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.ignoring_ = false;
    -
    -  /**
    -   * A function to be applied to urls found on the parsing process.
    -   * @type {?function(string):string}
    -   * @private
    -   */
    -  this.urlPolicy_ = opt_urlPolicy;
    -
    -  /**
    -   * A function to be applied to names fround on the parsing process.
    -   * @type {?function(string):string}
    -   * @private
    -   */
    -  this.nmTokenPolicy_ = opt_nmTokenPolicy;
    -};
    -goog.inherits(
    -    goog.string.html.HtmlSanitizer,
    -    goog.string.html.HtmlSaxHandler);
    -
    -
    -
    -/**
    - * The HTML types the parser supports.
    - * @enum {number}
    - */
    -goog.string.html.HtmlSanitizer.AttributeType = {
    -  NONE: 0,
    -  URI: 1,
    -  URI_FRAGMENT: 11,
    -  SCRIPT: 2,
    -  STYLE: 3,
    -  ID: 4,
    -  IDREF: 5,
    -  IDREFS: 6,
    -  GLOBAL_NAME: 7,
    -  LOCAL_NAME: 8,
    -  CLASSES: 9,
    -  FRAME_TARGET: 10
    -};
    -
    -
    -/**
    - * A map of attributes to types it has.
    - * @enum {number}
    - */
    -goog.string.html.HtmlSanitizer.Attributes = {
    -  '*::class': goog.string.html.HtmlSanitizer.AttributeType.CLASSES,
    -  '*::dir': 0,
    -  '*::id': goog.string.html.HtmlSanitizer.AttributeType.ID,
    -  '*::lang': 0,
    -  '*::onclick': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  '*::ondblclick': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  '*::onkeydown': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  '*::onkeypress': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  '*::onkeyup': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  '*::onload': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  '*::onmousedown': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  '*::onmousemove': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  '*::onmouseout': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  '*::onmouseover': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  '*::onmouseup': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  '*::style': goog.string.html.HtmlSanitizer.AttributeType.STYLE,
    -  '*::title': 0,
    -  '*::accesskey': 0,
    -  '*::tabindex': 0,
    -  '*::onfocus': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  '*::onblur': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  'a::coords': 0,
    -  'a::href': goog.string.html.HtmlSanitizer.AttributeType.URI,
    -  'a::hreflang': 0,
    -  'a::name': goog.string.html.HtmlSanitizer.AttributeType.GLOBAL_NAME,
    -  'a::onblur': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  'a::rel': 0,
    -  'a::rev': 0,
    -  'a::shape': 0,
    -  'a::target': goog.string.html.HtmlSanitizer.AttributeType.FRAME_TARGET,
    -  'a::type': 0,
    -  'area::accesskey': 0,
    -  'area::alt': 0,
    -  'area::coords': 0,
    -  'area::href': goog.string.html.HtmlSanitizer.AttributeType.URI,
    -  'area::nohref': 0,
    -  'area::onfocus': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  'area::shape': 0,
    -  'area::tabindex': 0,
    -  'area::target': goog.string.html.HtmlSanitizer.AttributeType.FRAME_TARGET,
    -  'bdo::dir': 0,
    -  'blockquote::cite': goog.string.html.HtmlSanitizer.AttributeType.URI,
    -  'br::clear': 0,
    -  'button::accesskey': 0,
    -  'button::disabled': 0,
    -  'button::name': goog.string.html.HtmlSanitizer.AttributeType.LOCAL_NAME,
    -  'button::onblur': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  'button::onfocus': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  'button::tabindex': 0,
    -  'button::type': 0,
    -  'button::value': 0,
    -  'caption::align': 0,
    -  'col::align': 0,
    -  'col::char': 0,
    -  'col::charoff': 0,
    -  'col::span': 0,
    -  'col::valign': 0,
    -  'col::width': 0,
    -  'colgroup::align': 0,
    -  'colgroup::char': 0,
    -  'colgroup::charoff': 0,
    -  'colgroup::span': 0,
    -  'colgroup::valign': 0,
    -  'colgroup::width': 0,
    -  'del::cite': goog.string.html.HtmlSanitizer.AttributeType.URI,
    -  'del::datetime': 0,
    -  'dir::compact': 0,
    -  'div::align': 0,
    -  'dl::compact': 0,
    -  'font::color': 0,
    -  'font::face': 0,
    -  'font::size': 0,
    -  'form::accept': 0,
    -  'form::action': goog.string.html.HtmlSanitizer.AttributeType.URI,
    -  'form::autocomplete': 0,
    -  'form::enctype': 0,
    -  'form::method': 0,
    -  'form::name': goog.string.html.HtmlSanitizer.AttributeType.GLOBAL_NAME,
    -  'form::onreset': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  'form::onsubmit': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  'form::target': goog.string.html.HtmlSanitizer.AttributeType.FRAME_TARGET,
    -  'h1::align': 0,
    -  'h2::align': 0,
    -  'h3::align': 0,
    -  'h4::align': 0,
    -  'h5::align': 0,
    -  'h6::align': 0,
    -  'hr::align': 0,
    -  'hr::noshade': 0,
    -  'hr::size': 0,
    -  'hr::width': 0,
    -  'img::align': 0,
    -  'img::alt': 0,
    -  'img::border': 0,
    -  'img::height': 0,
    -  'img::hspace': 0,
    -  'img::ismap': 0,
    -  'img::longdesc': goog.string.html.HtmlSanitizer.AttributeType.URI,
    -  'img::name': goog.string.html.HtmlSanitizer.AttributeType.GLOBAL_NAME,
    -  'img::src': goog.string.html.HtmlSanitizer.AttributeType.URI,
    -  'img::usemap': goog.string.html.HtmlSanitizer.AttributeType.URI_FRAGMENT,
    -  'img::vspace': 0,
    -  'img::width': 0,
    -  'input::accept': 0,
    -  'input::accesskey': 0,
    -  'input::autocomplete': 0,
    -  'input::align': 0,
    -  'input::alt': 0,
    -  'input::checked': 0,
    -  'input::disabled': 0,
    -  'input::ismap': 0,
    -  'input::maxlength': 0,
    -  'input::name': goog.string.html.HtmlSanitizer.AttributeType.LOCAL_NAME,
    -  'input::onblur': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  'input::onchange': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  'input::onfocus': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  'input::onselect': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  'input::readonly': 0,
    -  'input::size': 0,
    -  'input::src': goog.string.html.HtmlSanitizer.AttributeType.URI,
    -  'input::tabindex': 0,
    -  'input::type': 0,
    -  'input::usemap': goog.string.html.HtmlSanitizer.AttributeType.URI_FRAGMENT,
    -  'input::value': 0,
    -  'ins::cite': goog.string.html.HtmlSanitizer.AttributeType.URI,
    -  'ins::datetime': 0,
    -  'label::accesskey': 0,
    -  'label::for': goog.string.html.HtmlSanitizer.AttributeType.IDREF,
    -  'label::onblur': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  'label::onfocus': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  'legend::accesskey': 0,
    -  'legend::align': 0,
    -  'li::type': 0,
    -  'li::value': 0,
    -  'map::name': goog.string.html.HtmlSanitizer.AttributeType.GLOBAL_NAME,
    -  'menu::compact': 0,
    -  'ol::compact': 0,
    -  'ol::start': 0,
    -  'ol::type': 0,
    -  'optgroup::disabled': 0,
    -  'optgroup::label': 0,
    -  'option::disabled': 0,
    -  'option::label': 0,
    -  'option::selected': 0,
    -  'option::value': 0,
    -  'p::align': 0,
    -  'pre::width': 0,
    -  'q::cite': goog.string.html.HtmlSanitizer.AttributeType.URI,
    -  'select::disabled': 0,
    -  'select::multiple': 0,
    -  'select::name': goog.string.html.HtmlSanitizer.AttributeType.LOCAL_NAME,
    -  'select::onblur': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  'select::onchange': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  'select::onfocus': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  'select::size': 0,
    -  'select::tabindex': 0,
    -  'table::align': 0,
    -  'table::bgcolor': 0,
    -  'table::border': 0,
    -  'table::cellpadding': 0,
    -  'table::cellspacing': 0,
    -  'table::frame': 0,
    -  'table::rules': 0,
    -  'table::summary': 0,
    -  'table::width': 0,
    -  'tbody::align': 0,
    -  'tbody::char': 0,
    -  'tbody::charoff': 0,
    -  'tbody::valign': 0,
    -  'td::abbr': 0,
    -  'td::align': 0,
    -  'td::axis': 0,
    -  'td::bgcolor': 0,
    -  'td::char': 0,
    -  'td::charoff': 0,
    -  'td::colspan': 0,
    -  'td::headers': goog.string.html.HtmlSanitizer.AttributeType.IDREFS,
    -  'td::height': 0,
    -  'td::nowrap': 0,
    -  'td::rowspan': 0,
    -  'td::scope': 0,
    -  'td::valign': 0,
    -  'td::width': 0,
    -  'textarea::accesskey': 0,
    -  'textarea::cols': 0,
    -  'textarea::disabled': 0,
    -  'textarea::name': goog.string.html.HtmlSanitizer.AttributeType.LOCAL_NAME,
    -  'textarea::onblur': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  'textarea::onchange': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  'textarea::onfocus': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  'textarea::onselect': goog.string.html.HtmlSanitizer.AttributeType.SCRIPT,
    -  'textarea::readonly': 0,
    -  'textarea::rows': 0,
    -  'textarea::tabindex': 0,
    -  'tfoot::align': 0,
    -  'tfoot::char': 0,
    -  'tfoot::charoff': 0,
    -  'tfoot::valign': 0,
    -  'th::abbr': 0,
    -  'th::align': 0,
    -  'th::axis': 0,
    -  'th::bgcolor': 0,
    -  'th::char': 0,
    -  'th::charoff': 0,
    -  'th::colspan': 0,
    -  'th::headers': goog.string.html.HtmlSanitizer.AttributeType.IDREFS,
    -  'th::height': 0,
    -  'th::nowrap': 0,
    -  'th::rowspan': 0,
    -  'th::scope': 0,
    -  'th::valign': 0,
    -  'th::width': 0,
    -  'thead::align': 0,
    -  'thead::char': 0,
    -  'thead::charoff': 0,
    -  'thead::valign': 0,
    -  'tr::align': 0,
    -  'tr::bgcolor': 0,
    -  'tr::char': 0,
    -  'tr::charoff': 0,
    -  'tr::valign': 0,
    -  'ul::compact': 0,
    -  'ul::type': 0
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.string.html.HtmlSanitizer.prototype.startTag =
    -    function(tagName, attribs) {
    -  if (this.ignoring_) {
    -    return;
    -  }
    -  if (!goog.string.html.HtmlParser.Elements.hasOwnProperty(tagName)) {
    -    return;
    -  }
    -  var eflags = goog.string.html.HtmlParser.Elements[tagName];
    -  if (eflags & goog.string.html.HtmlParser.EFlags.FOLDABLE) {
    -    return;
    -  } else if (eflags & goog.string.html.HtmlParser.EFlags.UNSAFE) {
    -    this.ignoring_ = !(eflags & goog.string.html.HtmlParser.EFlags.EMPTY);
    -    return;
    -  }
    -  attribs = this.sanitizeAttributes_(tagName, attribs);
    -  if (attribs) {
    -    if (!(eflags & goog.string.html.HtmlParser.EFlags.EMPTY)) {
    -      this.stack_.push(tagName);
    -    }
    -
    -    this.stringBuffer_.append('<', tagName);
    -    for (var i = 0, n = attribs.length; i < n; i += 2) {
    -      var attribName = attribs[i],
    -          value = attribs[i + 1];
    -      if (value !== null && value !== void 0) {
    -        this.stringBuffer_.append(' ', attribName, '="',
    -            this.escapeAttrib_(value), '"');
    -      }
    -    }
    -    this.stringBuffer_.append('>');
    -  }
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.string.html.HtmlSanitizer.prototype.endTag = function(tagName) {
    -  if (this.ignoring_) {
    -    this.ignoring_ = false;
    -    return;
    -  }
    -  if (!goog.string.html.HtmlParser.Elements.hasOwnProperty(tagName)) {
    -    return;
    -  }
    -  var eflags = goog.string.html.HtmlParser.Elements[tagName];
    -  if (!(eflags & (goog.string.html.HtmlParser.EFlags.UNSAFE |
    -      goog.string.html.HtmlParser.EFlags.EMPTY |
    -      goog.string.html.HtmlParser.EFlags.FOLDABLE))) {
    -    var index;
    -    if (eflags & goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG) {
    -      for (index = this.stack_.length; --index >= 0;) {
    -        var stackEl = this.stack_[index];
    -        if (stackEl === tagName) {
    -          break;
    -        }
    -        if (!(goog.string.html.HtmlParser.Elements[stackEl] &
    -            goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG)) {
    -          // Don't pop non optional end tags looking for a match.
    -          return;
    -        }
    -      }
    -    } else {
    -      for (index = this.stack_.length; --index >= 0;) {
    -        if (this.stack_[index] === tagName) {
    -          break;
    -        }
    -      }
    -    }
    -    if (index < 0) { return; }  // Not opened.
    -    for (var i = this.stack_.length; --i > index;) {
    -      var stackEl = this.stack_[i];
    -      if (!(goog.string.html.HtmlParser.Elements[stackEl] &
    -          goog.string.html.HtmlParser.EFlags.OPTIONAL_ENDTAG)) {
    -        this.stringBuffer_.append('</', stackEl, '>');
    -      }
    -    }
    -    this.stack_.length = index;
    -    this.stringBuffer_.append('</', tagName, '>');
    -  }
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.string.html.HtmlSanitizer.prototype.pcdata = function(text) {
    -  if (!this.ignoring_) {
    -    this.stringBuffer_.append(text);
    -  }
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.string.html.HtmlSanitizer.prototype.rcdata = function(text) {
    -  if (!this.ignoring_) {
    -    this.stringBuffer_.append(text);
    -  }
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.string.html.HtmlSanitizer.prototype.cdata = function(text) {
    -  if (!this.ignoring_) {
    -    this.stringBuffer_.append(text);
    -  }
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.string.html.HtmlSanitizer.prototype.startDoc = function() {
    -  this.stack_ = [];
    -  this.ignoring_ = false;
    -};
    -
    -
    -/**
    - * @override
    - */
    -goog.string.html.HtmlSanitizer.prototype.endDoc = function() {
    -  for (var i = this.stack_.length; --i >= 0;) {
    -    this.stringBuffer_.append('</', this.stack_[i], '>');
    -  }
    -  this.stack_.length = 0;
    -};
    -
    -
    -/**
    - * Escapes HTML special characters in attribute values as HTML entities.
    - *
    - * TODO(user): use {@code goog.string.htmlEscape} instead ?
    - * @param {string} s The string to be escaped.
    - * @return {string} An escaped version of {@code s}.
    - * @private
    - */
    -goog.string.html.HtmlSanitizer.prototype.escapeAttrib_ = function(s) {
    -  // Escaping '=' defangs many UTF-7 and SGML short-tag attacks.
    -  return s.replace(goog.string.html.HtmlParser.AMP_RE_, '&amp;').
    -      replace(goog.string.html.HtmlParser.LT_RE_, '&lt;').
    -      replace(goog.string.html.HtmlParser.GT_RE_, '&gt;').
    -      replace(goog.string.html.HtmlParser.QUOTE_RE_, '&#34;').
    -      replace(goog.string.html.HtmlParser.EQUALS_RE_, '&#61;');
    -};
    -
    -
    -/**
    - * Sanitizes attributes found on html entities.
    - * @param {string} tagName The name of the tag in which the {@code attribs} were
    - *     found.
    - * @param {Array.<?string>} attribs An array of attributes.
    - * @return {Array.<?string>} A sanitized version of the {@code attribs}.
    - * @private
    - */
    -goog.string.html.HtmlSanitizer.prototype.sanitizeAttributes_ =
    -    function(tagName, attribs) {
    -  for (var i = 0; i < attribs.length; i += 2) {
    -    var attribName = attribs[i];
    -    var value = attribs[i + 1];
    -    var atype = null, attribKey;
    -    if ((attribKey = tagName + '::' + attribName,
    -        goog.string.html.HtmlSanitizer.Attributes.hasOwnProperty(attribKey)) ||
    -        (attribKey = '*::' + attribName,
    -        goog.string.html.HtmlSanitizer.Attributes.hasOwnProperty(attribKey))) {
    -      atype = goog.string.html.HtmlSanitizer.Attributes[attribKey];
    -    }
    -    if (atype !== null) {
    -      switch (atype) {
    -        case 0: break;
    -        case goog.string.html.HtmlSanitizer.AttributeType.SCRIPT:
    -        case goog.string.html.HtmlSanitizer.AttributeType.STYLE:
    -          value = null;
    -          break;
    -        case goog.string.html.HtmlSanitizer.AttributeType.ID:
    -        case goog.string.html.HtmlSanitizer.AttributeType.IDREF:
    -        case goog.string.html.HtmlSanitizer.AttributeType.IDREFS:
    -        case goog.string.html.HtmlSanitizer.AttributeType.GLOBAL_NAME:
    -        case goog.string.html.HtmlSanitizer.AttributeType.LOCAL_NAME:
    -        case goog.string.html.HtmlSanitizer.AttributeType.CLASSES:
    -          value = this.nmTokenPolicy_ ?
    -            this.nmTokenPolicy_(/** @type {string} */ (value)) : value;
    -          break;
    -        case goog.string.html.HtmlSanitizer.AttributeType.URI:
    -          value = this.urlPolicy_ && this.urlPolicy_(
    -              /** @type {string} */ (value));
    -          break;
    -        case goog.string.html.HtmlSanitizer.AttributeType.URI_FRAGMENT:
    -          if (value && '#' === value.charAt(0)) {
    -            value = this.nmTokenPolicy_ ? this.nmTokenPolicy_(value) : value;
    -            if (value) { value = '#' + value; }
    -          } else {
    -            value = null;
    -          }
    -          break;
    -        default:
    -          value = null;
    -          break;
    -      }
    -    } else {
    -      value = null;
    -    }
    -    attribs[i + 1] = value;
    -  }
    -  return attribs;
    -};
    diff --git a/src/database/third_party/closure-library/third_party/closure/goog/deps.js b/src/database/third_party/closure-library/third_party/closure/goog/deps.js
    deleted file mode 100644
    index fa140dbec41..00000000000
    --- a/src/database/third_party/closure-library/third_party/closure/goog/deps.js
    +++ /dev/null
    @@ -1,20 +0,0 @@
    -// Copyright 2010 The Closure Library Authors. All Rights Reserved.
    -//
    -// Licensed under the Apache License, Version 2.0 (the "License");
    -// you may not use this file except in compliance with the License.
    -// You may obtain a copy of the License at
    -//
    -//      http://www.apache.org/licenses/LICENSE-2.0
    -//
    -// Unless required by applicable law or agreed to in writing, software
    -// distributed under the License is distributed on an "AS-IS" BASIS,
    -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -// See the License for the specific language governing permissions and
    -// limitations under the License.
    -
    -
    -/**
    - * @deprecated This file is deprecated. The contents have been
    - * migrated to the main deps.js instead (which is auto-included by
    - * base.js).  Please do not add new dependencies here.
    - */
    diff --git a/src/database/third_party/closure-library/third_party/closure/goog/dojo/dom/query.js b/src/database/third_party/closure-library/third_party/closure/goog/dojo/dom/query.js
    deleted file mode 100644
    index c4bbbb7ec78..00000000000
    --- a/src/database/third_party/closure-library/third_party/closure/goog/dojo/dom/query.js
    +++ /dev/null
    @@ -1,1545 +0,0 @@
    -// Copyright 2005-2009, The Dojo Foundation
    -// Modifications Copyright 2008 The Closure Library Authors.
    -// All Rights Reserved.
    -
    -/**
    - * @license Portions of this code are from the Dojo Toolkit, received by
    - * The Closure Library Authors under the BSD license. All other code is
    - * Copyright 2005-2009 The Closure Library Authors. All Rights Reserved.
    -
    -The "New" BSD License:
    -
    -Copyright (c) 2005-2009, The Dojo Foundation
    -All rights reserved.
    -
    -Redistribution and use in source and binary forms, with or without
    -modification, are permitted provided that the following conditions are met:
    -
    -  * Redistributions of source code must retain the above copyright notice, this
    -    list of conditions and the following disclaimer.
    -  * Redistributions in binary form must reproduce the above copyright notice,
    -    this list of conditions and the following disclaimer in the documentation
    -    and/or other materials provided with the distribution.
    -  * Neither the name of the Dojo Foundation nor the names of its contributors
    -    may be used to endorse or promote products derived from this software
    -    without specific prior written permission.
    -
    -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    -DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
    -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    -*/
    -
    -/**
    - * @fileoverview This code was ported from the Dojo Toolkit
    -   http://dojotoolkit.org and modified slightly for Closure.
    - *
    - *  goog.dom.query is a relatively full-featured CSS3 query function. It is
    - *  designed to take any valid CSS3 selector and return the nodes matching
    - *  the selector. To do this quickly, it processes queries in several
    - *  steps, applying caching where profitable.
    - *    The steps (roughly in reverse order of the way they appear in the code):
    - *    1.) check to see if we already have a "query dispatcher"
    - *      - if so, use that with the given parameterization. Skip to step 4.
    - *    2.) attempt to determine which branch to dispatch the query to:
    - *      - JS (optimized DOM iteration)
    - *      - native (FF3.1, Safari 3.2+, Chrome, some IE 8 doctypes). If native,
    - *        skip to step 4, using a stub dispatcher for QSA queries.
    - *    3.) tokenize and convert to executable "query dispatcher"
    - *        assembled as a chain of "yes/no" test functions pertaining to
    - *        a section of a simple query statement (".blah:nth-child(odd)"
    - *        but not "div div", which is 2 simple statements).
    - *    4.) the resulting query dispatcher is called in the passed scope
    - *        (by default the top-level document)
    - *      - for DOM queries, this results in a recursive, top-down
    - *        evaluation of nodes based on each simple query section
    - *      - querySelectorAll is used instead of DOM where possible. If a query
    - *        fails in this mode, it is re-run against the DOM evaluator and all
    - *        future queries using the same selector evaluate against the DOM branch
    - *        too.
    - *    5.) matched nodes are pruned to ensure they are unique
    - * @deprecated This is an all-software query selector. When developing for
    - *     recent browsers, use document.querySelector. See information at
    - *     http://caniuse.com/queryselector and
    - *     https://developer.mozilla.org/en-US/docs/DOM/Document.querySelector .
    - */
    -
    -goog.provide('goog.dom.query');
    -
    -goog.require('goog.array');
    -goog.require('goog.dom');
    -goog.require('goog.functions');
    -goog.require('goog.string');
    -goog.require('goog.userAgent');
    -
    -  /**
    -   * Returns nodes which match the given CSS3 selector, searching the
    -   * entire document by default but optionally taking a node to scope
    -   * the search by.
    -   *
    -   * dojo.query() is the swiss army knife of DOM node manipulation in
    -   * Dojo. Much like Prototype's "$$" (bling-bling) function or JQuery's
    -   * "$" function, dojo.query provides robust, high-performance
    -   * CSS-based node selector support with the option of scoping searches
    -   * to a particular sub-tree of a document.
    -   *
    -   * Supported Selectors:
    -   * --------------------
    -   *
    -   * dojo.query() supports a rich set of CSS3 selectors, including:
    -   *
    -   *   * class selectors (e.g., `.foo`)
    -   *   * node type selectors like `span`
    -   *   * ` ` descendant selectors
    -   *   * `>` child element selectors
    -   *   * `#foo` style ID selectors
    -   *   * `*` universal selector
    -   *   * `~`, the immediately preceded-by sibling selector
    -   *   * `+`, the preceded-by sibling selector
    -   *   * attribute queries:
    -   *   |  * `[foo]` attribute presence selector
    -   *   |  * `[foo='bar']` attribute value exact match
    -   *   |  * `[foo~='bar']` attribute value list item match
    -   *   |  * `[foo^='bar']` attribute start match
    -   *   |  * `[foo$='bar']` attribute end match
    -   *   |  * `[foo*='bar']` attribute substring match
    -   *   * `:first-child`, `:last-child` positional selectors
    -   *   * `:empty` content empty selector
    -   *   * `:empty` content empty selector
    -   *   * `:nth-child(n)`, `:nth-child(2n+1)` style positional calculations
    -   *   * `:nth-child(even)`, `:nth-child(odd)` positional selectors
    -   *   * `:not(...)` negation pseudo selectors
    -   *
    -   * Any legal combination of these selectors will work with
    -   * `dojo.query()`, including compound selectors ("," delimited).
    -   * Very complex and useful searches can be constructed with this
    -   * palette of selectors.
    -   *
    -   * Unsupported Selectors:
    -   * ----------------------
    -   *
    -   * While dojo.query handles many CSS3 selectors, some fall outside of
    -   * what's reasonable for a programmatic node querying engine to
    -   * handle. Currently unsupported selectors include:
    -   *
    -   *   * namespace-differentiated selectors of any form
    -   *   * all `::` pseudo-element selectors
    -   *   * certain pseudo-selectors which don't get a lot of day-to-day use:
    -   *   |  * `:root`, `:lang()`, `:target`, `:focus`
    -   *   * all visual and state selectors:
    -   *   |  * `:root`, `:active`, `:hover`, `:visited`, `:link`,
    -   *       `:enabled`, `:disabled`, `:checked`
    -   *   * `:*-of-type` pseudo selectors
    -   *
    -   * dojo.query and XML Documents:
    -   * -----------------------------
    -   *
    -   * `dojo.query` currently only supports searching XML documents
    -   * whose tags and attributes are 100% lower-case. This is a known
    -   * limitation and will [be addressed soon]
    -   * (http://trac.dojotoolkit.org/ticket/3866)
    -   *
    -   * Non-selector Queries:
    -   * ---------------------
    -   *
    -   * If something other than a String is passed for the query,
    -   * `dojo.query` will return a new array constructed from
    -   * that parameter alone and all further processing will stop. This
    -   * means that if you have a reference to a node or array or nodes, you
    -   * can quickly construct a new array of nodes from the original by
    -   * calling `dojo.query(node)` or `dojo.query(array)`.
    -   *
    -   * example:
    -   *   search the entire document for elements with the class "foo":
    -   * |  dojo.query(".foo");
    -   *   these elements will match:
    -   * |  <span class="foo"></span>
    -   * |  <span class="foo bar"></span>
    -   * |  <p class="thud foo"></p>
    -   * example:
    -   *   search the entire document for elements with the classes "foo" *and*
    -   *   "bar":
    -   * |  dojo.query(".foo.bar");
    -   *   these elements will match:
    -   * |  <span class="foo bar"></span>
    -   *   while these will not:
    -   * |  <span class="foo"></span>
    -   * |  <p class="thud foo"></p>
    -   * example:
    -   *   find `<span>` elements which are descendants of paragraphs and
    -   *   which have a "highlighted" class:
    -   * |  dojo.query("p span.highlighted");
    -   *   the innermost span in this fragment matches:
    -   * |  <p class="foo">
    -   * |    <span>...
    -   * |      <span class="highlighted foo bar">...</span>
    -   * |    </span>
    -   * |  </p>
    -   * example:
    -   *   find all odd table rows inside of the table
    -   *   `#tabular_data`, using the `>` (direct child) selector to avoid
    -   *   affecting any nested tables:
    -   * |  dojo.query("#tabular_data > tbody > tr:nth-child(odd)");
    -   *
    -   * @param {string|Array} query The CSS3 expression to match against.
    -   *     For details on the syntax of CSS3 selectors, see
    -   *     http://www.w3.org/TR/css3-selectors/#selectors.
    -   * @param {(string|Node)=} opt_root A Node (or node id) to scope the search
    -   *     from (optional).
    -   * @return { {length: number} } The elements that matched the query.
    -   *
    -   * @deprecated This is an all-software query selector. Use
    -   *     document.querySelector. See
    -   *     https://developer.mozilla.org/en-US/docs/DOM/Document.querySelector .
    -   */
    -goog.dom.query = (function() {
    -  ////////////////////////////////////////////////////////////////////////
    -  // Global utilities
    -  ////////////////////////////////////////////////////////////////////////
    -
    -  var cssCaseBug = (goog.userAgent.WEBKIT &&
    -                     ((goog.dom.getDocument().compatMode) == 'BackCompat')
    -                   );
    -
    -  var legacyIE = goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9');
    -
    -  // On browsers that support the "children" collection we can avoid a lot of
    -  // iteration on chaff (non-element) nodes.
    -  var childNodesName = !!goog.dom.getDocument().firstChild['children'] ?
    -                          'children' :
    -                          'childNodes';
    -
    -  var specials = '>~+';
    -
    -  // Global thunk to determine whether we should treat the current query as
    -  // case sensitive or not. This switch is flipped by the query evaluator based
    -  // on the document passed as the context to search.
    -  var caseSensitive = false;
    -
    -
    -  ////////////////////////////////////////////////////////////////////////
    -  // Tokenizer
    -  ////////////////////////////////////////////////////////////////////////
    -
    -  var getQueryParts = function(query) {
    -    //  summary:
    -    //    state machine for query tokenization
    -    //  description:
    -    //    instead of using a brittle and slow regex-based CSS parser,
    -    //    dojo.query implements an AST-style query representation. This
    -    //    representation is only generated once per query. For example,
    -    //    the same query run multiple times or under different root nodes
    -    //    does not re-parse the selector expression but instead uses the
    -    //    cached data structure. The state machine implemented here
    -    //    terminates on the last " " (space) character and returns an
    -    //    ordered array of query component structures (or "parts"). Each
    -    //    part represents an operator or a simple CSS filtering
    -    //    expression. The structure for parts is documented in the code
    -    //    below.
    -
    -
    -    // NOTE:
    -    //    this code is designed to run fast and compress well. Sacrifices
    -    //    to readability and maintainability have been made.
    -    if (specials.indexOf(query.slice(-1)) >= 0) {
    -      // If we end with a ">", "+", or "~", that means we're implicitly
    -      // searching all children, so make it explicit.
    -      query += ' * '
    -    } else {
    -      // if you have not provided a terminator, one will be provided for
    -      // you...
    -      query += ' ';
    -    }
    -
    -    var ts = function(/*Integer*/ s, /*Integer*/ e) {
    -      // trim and slice.
    -
    -      // take an index to start a string slice from and an end position
    -      // and return a trimmed copy of that sub-string
    -      return goog.string.trim(query.slice(s, e));
    -    };
    -
    -    // The overall data graph of the full query, as represented by queryPart
    -    // objects.
    -    var queryParts = [];
    -
    -
    -    // state keeping vars
    -    var inBrackets = -1,
    -        inParens = -1,
    -        inMatchFor = -1,
    -        inPseudo = -1,
    -        inClass = -1,
    -        inId = -1,
    -        inTag = -1,
    -        lc = '',
    -        cc = '',
    -        pStart;
    -
    -    // iteration vars
    -    var x = 0, // index in the query
    -        ql = query.length,
    -        currentPart = null, // data structure representing the entire clause
    -        cp = null; // the current pseudo or attr matcher
    -
    -    // several temporary variables are assigned to this structure during a
    -    // potential sub-expression match:
    -    //    attr:
    -    //      a string representing the current full attribute match in a
    -    //      bracket expression
    -    //    type:
    -    //      if there's an operator in a bracket expression, this is
    -    //      used to keep track of it
    -    //    value:
    -    //      the internals of parenthetical expression for a pseudo. for
    -    //      :nth-child(2n+1), value might be '2n+1'
    -
    -    var endTag = function() {
    -      // called when the tokenizer hits the end of a particular tag name.
    -      // Re-sets state variables for tag matching and sets up the matcher
    -      // to handle the next type of token (tag or operator).
    -      if (inTag >= 0) {
    -        var tv = (inTag == x) ? null : ts(inTag, x);
    -        if (specials.indexOf(tv) < 0) {
    -          currentPart.tag = tv;
    -        } else {
    -          currentPart.oper = tv;
    -        }
    -        inTag = -1;
    -      }
    -    };
    -
    -    var endId = function() {
    -      // Called when the tokenizer might be at the end of an ID portion of a
    -      // match.
    -      if (inId >= 0) {
    -        currentPart.id = ts(inId, x).replace(/\\/g, '');
    -        inId = -1;
    -      }
    -    };
    -
    -    var endClass = function() {
    -      // Called when the tokenizer might be at the end of a class name
    -      // match. CSS allows for multiple classes, so we augment the
    -      // current item with another class in its list.
    -      if (inClass >= 0) {
    -        currentPart.classes.push(ts(inClass + 1, x).replace(/\\/g, ''));
    -        inClass = -1;
    -      }
    -    };
    -
    -    var endAll = function() {
    -      // at the end of a simple fragment, so wall off the matches
    -      endId(); endTag(); endClass();
    -    };
    -
    -    var endPart = function() {
    -      endAll();
    -      if (inPseudo >= 0) {
    -        currentPart.pseudos.push({ name: ts(inPseudo + 1, x) });
    -      }
    -      // Hint to the selector engine to tell it whether or not it
    -      // needs to do any iteration. Many simple selectors don't, and
    -      // we can avoid significant construction-time work by advising
    -      // the system to skip them.
    -      currentPart.loops = currentPart.pseudos.length ||
    -                          currentPart.attrs.length ||
    -                          currentPart.classes.length;
    -
    -      // save the full expression as a string
    -      currentPart.oquery = currentPart.query = ts(pStart, x);
    -
    -
    -      // otag/tag are hints to suggest to the system whether or not
    -      // it's an operator or a tag. We save a copy of otag since the
    -      // tag name is cast to upper-case in regular HTML matches. The
    -      // system has a global switch to figure out if the current
    -      // expression needs to be case sensitive or not and it will use
    -      // otag or tag accordingly
    -      currentPart.otag = currentPart.tag = (currentPart.oper) ?
    -                                                     null :
    -                                                     (currentPart.tag || '*');
    -
    -      if (currentPart.tag) {
    -        // if we're in a case-insensitive HTML doc, we likely want
    -        // the toUpperCase when matching on element.tagName. If we
    -        // do it here, we can skip the string op per node
    -        // comparison
    -        currentPart.tag = currentPart.tag.toUpperCase();
    -      }
    -
    -      // add the part to the list
    -      if (queryParts.length && (queryParts[queryParts.length - 1].oper)) {
    -        // operators are always infix, so we remove them from the
    -        // list and attach them to the next match. The evaluator is
    -        // responsible for sorting out how to handle them.
    -        currentPart.infixOper = queryParts.pop();
    -        currentPart.query = currentPart.infixOper.query + ' ' +
    -            currentPart.query;
    -      }
    -      queryParts.push(currentPart);
    -
    -      currentPart = null;
    -    }
    -
    -    // iterate over the query, character by character, building up a
    -    // list of query part objects
    -    for (; lc = cc, cc = query.charAt(x), x < ql; x++) {
    -      //    cc: the current character in the match
    -      //    lc: the last character (if any)
    -
    -      // someone is trying to escape something, so don't try to match any
    -      // fragments. We assume we're inside a literal.
    -      if (lc == '\\') {
    -        continue;
    -      }
    -      if (!currentPart) { // a part was just ended or none has yet been created
    -        // NOTE: I hate all this alloc, but it's shorter than writing tons of
    -        // if's
    -        pStart = x;
    -        //  rules describe full CSS sub-expressions, like:
    -        //    #someId
    -        //    .className:first-child
    -        //  but not:
    -        //    thinger > div.howdy[type=thinger]
    -        //  the individual components of the previous query would be
    -        //  split into 3 parts that would be represented a structure
    -        //  like:
    -        //    [
    -        //      {
    -        //        query: 'thinger',
    -        //        tag: 'thinger',
    -        //      },
    -        //      {
    -        //        query: 'div.howdy[type=thinger]',
    -        //        classes: ['howdy'],
    -        //        infixOper: {
    -        //          query: '>',
    -        //          oper: '>',
    -        //        }
    -        //      },
    -        //    ]
    -        currentPart = {
    -          query: null, // the full text of the part's rule
    -          pseudos: [], // CSS supports multiple pseudo-class matches in a single
    -              // rule
    -          attrs: [],  // CSS supports multi-attribute match, so we need an array
    -          classes: [], // class matches may be additive,
    -              // e.g.: .thinger.blah.howdy
    -          tag: null,  // only one tag...
    -          oper: null, // ...or operator per component. Note that these wind up
    -              // being exclusive.
    -          id: null,   // the id component of a rule
    -          getTag: function() {
    -            return (caseSensitive) ? this.otag : this.tag;
    -          }
    -        };
    -
    -        // if we don't have a part, we assume we're going to start at
    -        // the beginning of a match, which should be a tag name. This
    -        // might fault a little later on, but we detect that and this
    -        // iteration will still be fine.
    -        inTag = x;
    -      }
    -
    -      if (inBrackets >= 0) {
    -        // look for a the close first
    -        if (cc == ']') { // if we're in a [...] clause and we end, do assignment
    -          if (!cp.attr) {
    -            // no attribute match was previously begun, so we
    -            // assume this is an attribute existence match in the
    -            // form of [someAttributeName]
    -            cp.attr = ts(inBrackets + 1, x);
    -          } else {
    -            // we had an attribute already, so we know that we're
    -            // matching some sort of value, as in [attrName=howdy]
    -            cp.matchFor = ts((inMatchFor || inBrackets + 1), x);
    -          }
    -          var cmf = cp.matchFor;
    -          if (cmf) {
    -            // try to strip quotes from the matchFor value. We want
    -            // [attrName=howdy] to match the same
    -            //  as [attrName = 'howdy' ]
    -            if ((cmf.charAt(0) == '"') || (cmf.charAt(0) == "'")) {
    -              cp.matchFor = cmf.slice(1, -1);
    -            }
    -          }
    -          // end the attribute by adding it to the list of attributes.
    -          currentPart.attrs.push(cp);
    -          cp = null; // necessary?
    -          inBrackets = inMatchFor = -1;
    -        } else if (cc == '=') {
    -          // if the last char was an operator prefix, make sure we
    -          // record it along with the '=' operator.
    -          var addToCc = ('|~^$*'.indexOf(lc) >= 0) ? lc : '';
    -          cp.type = addToCc + cc;
    -          cp.attr = ts(inBrackets + 1, x - addToCc.length);
    -          inMatchFor = x + 1;
    -        }
    -        // now look for other clause parts
    -      } else if (inParens >= 0) {
    -        // if we're in a parenthetical expression, we need to figure
    -        // out if it's attached to a pseudo-selector rule like
    -        // :nth-child(1)
    -        if (cc == ')') {
    -          if (inPseudo >= 0) {
    -            cp.value = ts(inParens + 1, x);
    -          }
    -          inPseudo = inParens = -1;
    -        }
    -      } else if (cc == '#') {
    -        // start of an ID match
    -        endAll();
    -        inId = x + 1;
    -      } else if (cc == '.') {
    -        // start of a class match
    -        endAll();
    -        inClass = x;
    -      } else if (cc == ':') {
    -        // start of a pseudo-selector match
    -        endAll();
    -        inPseudo = x;
    -      } else if (cc == '[') {
    -        // start of an attribute match.
    -        endAll();
    -        inBrackets = x;
    -        // provide a new structure for the attribute match to fill-in
    -        cp = {
    -          /*=====
    -          attr: null, type: null, matchFor: null
    -          =====*/
    -        };
    -      } else if (cc == '(') {
    -        // we really only care if we've entered a parenthetical
    -        // expression if we're already inside a pseudo-selector match
    -        if (inPseudo >= 0) {
    -          // provide a new structure for the pseudo match to fill-in
    -          cp = {
    -            name: ts(inPseudo + 1, x),
    -            value: null
    -          }
    -          currentPart.pseudos.push(cp);
    -        }
    -        inParens = x;
    -      } else if (
    -        (cc == ' ') &&
    -        // if it's a space char and the last char is too, consume the
    -        // current one without doing more work
    -        (lc != cc)
    -      ) {
    -        endPart();
    -      }
    -    }
    -    return queryParts;
    -  };
    -
    -
    -  ////////////////////////////////////////////////////////////////////////
    -  // DOM query infrastructure
    -  ////////////////////////////////////////////////////////////////////////
    -
    -  var agree = function(first, second) {
    -    // the basic building block of the yes/no chaining system. agree(f1,
    -    // f2) generates a new function which returns the boolean results of
    -    // both of the passed functions to a single logical-anded result. If
    -    // either are not passed, the other is used exclusively.
    -    if (!first) {
    -      return second;
    -    }
    -    if (!second) {
    -      return first;
    -    }
    -
    -    return function() {
    -      return first.apply(window, arguments) && second.apply(window, arguments);
    -    }
    -  };
    -
    -  /**
    -   * @param {Array=} opt_arr
    -   */
    -  function getArr(i, opt_arr) {
    -    // helps us avoid array alloc when we don't need it
    -    var r = opt_arr || [];
    -    if (i) {
    -      r.push(i);
    -    }
    -    return r;
    -  };
    -
    -  var isElement = function(n) {
    -    return (1 == n.nodeType);
    -  };
    -
    -  // FIXME: need to coalesce getAttr with defaultGetter
    -  var blank = '';
    -  var getAttr = function(elem, attr) {
    -    if (!elem) {
    -      return blank;
    -    }
    -    if (attr == 'class') {
    -      return elem.className || blank;
    -    }
    -    if (attr == 'for') {
    -      return elem.htmlFor || blank;
    -    }
    -    if (attr == 'style') {
    -      return elem.style.cssText || blank;
    -    }
    -    return (caseSensitive ? elem.getAttribute(attr) :
    -        elem.getAttribute(attr, 2)) || blank;
    -  };
    -
    -  var attrs = {
    -    '*=': function(attr, value) {
    -      return function(elem) {
    -        // E[foo*="bar"]
    -        //    an E element whose "foo" attribute value contains
    -        //    the substring "bar"
    -        return (getAttr(elem, attr).indexOf(value) >= 0);
    -      }
    -    },
    -    '^=': function(attr, value) {
    -      // E[foo^="bar"]
    -      //    an E element whose "foo" attribute value begins exactly
    -      //    with the string "bar"
    -      return function(elem) {
    -        return (getAttr(elem, attr).indexOf(value) == 0);
    -      }
    -    },
    -    '$=': function(attr, value) {
    -      // E[foo$="bar"]
    -      //    an E element whose "foo" attribute value ends exactly
    -      //    with the string "bar"
    -      var tval = ' ' + value;
    -      return function(elem) {
    -        var ea = ' ' + getAttr(elem, attr);
    -        return (ea.lastIndexOf(value) == (ea.length - value.length));
    -      }
    -    },
    -    '~=': function(attr, value) {
    -      // E[foo~="bar"]
    -      //    an E element whose "foo" attribute value is a list of
    -      //    space-separated values, one of which is exactly equal
    -      //    to "bar"
    -
    -      var tval = ' ' + value + ' ';
    -      return function(elem) {
    -        var ea = ' ' + getAttr(elem, attr) + ' ';
    -        return (ea.indexOf(tval) >= 0);
    -      }
    -    },
    -    '|=': function(attr, value) {
    -      // E[hreflang|="en"]
    -      //    an E element whose "hreflang" attribute has a
    -      //    hyphen-separated list of values beginning (from the
    -      //    left) with "en"
    -      value = ' ' + value;
    -      return function(elem) {
    -        var ea = ' ' + getAttr(elem, attr);
    -        return (
    -          (ea == value) ||
    -          (ea.indexOf(value + '-') == 0)
    -        );
    -      }
    -    },
    -    '=': function(attr, value) {
    -      return function(elem) {
    -        return (getAttr(elem, attr) == value);
    -      }
    -    }
    -  };
    -
    -  // avoid testing for node type if we can. Defining this in the negative
    -  // here to avoid negation in the fast path.
    -  var noNextElementSibling = (
    -    typeof goog.dom.getDocument().firstChild.nextElementSibling == 'undefined'
    -  );
    -  var nSibling = !noNextElementSibling ? 'nextElementSibling' : 'nextSibling';
    -  var pSibling = !noNextElementSibling ?
    -                    'previousElementSibling' :
    -                    'previousSibling';
    -  var simpleNodeTest = (noNextElementSibling ? isElement : goog.functions.TRUE);
    -
    -  var _lookLeft = function(node) {
    -    while (node = node[pSibling]) {
    -      if (simpleNodeTest(node)) {
    -        return false;
    -      }
    -    }
    -    return true;
    -  };
    -
    -  var _lookRight = function(node) {
    -    while (node = node[nSibling]) {
    -      if (simpleNodeTest(node)) {
    -        return false;
    -      }
    -    }
    -    return true;
    -  };
    -
    -  var getNodeIndex = function(node) {
    -    var root = node.parentNode;
    -    var i = 0,
    -        tret = root[childNodesName],
    -        ci = (node['_i'] || -1),
    -        cl = (root['_l'] || -1);
    -
    -    if (!tret) {
    -      return -1;
    -    }
    -    var l = tret.length;
    -
    -    // we calculate the parent length as a cheap way to invalidate the
    -    // cache. It's not 100% accurate, but it's much more honest than what
    -    // other libraries do
    -    if (cl == l && ci >= 0 && cl >= 0) {
    -      // if it's legit, tag and release
    -      return ci;
    -    }
    -
    -    // else re-key things
    -    root['_l'] = l;
    -    ci = -1;
    -    var te = root['firstElementChild'] || root['firstChild'];
    -    for (; te; te = te[nSibling]) {
    -      if (simpleNodeTest(te)) {
    -        te['_i'] = ++i;
    -        if (node === te) {
    -          // NOTE:
    -          //  shortcutting the return at this step in indexing works
    -          //  very well for benchmarking but we avoid it here since
    -          //  it leads to potential O(n^2) behavior in sequential
    -          //  getNodexIndex operations on a previously un-indexed
    -          //  parent. We may revisit this at a later time, but for
    -          //  now we just want to get the right answer more often
    -          //  than not.
    -          ci = i;
    -        }
    -      }
    -    }
    -    return ci;
    -  };
    -
    -  var isEven = function(elem) {
    -    return !((getNodeIndex(elem)) % 2);
    -  };
    -
    -  var isOdd = function(elem) {
    -    return (getNodeIndex(elem)) % 2;
    -  };
    -
    -  var pseudos = {
    -    'checked': function(name, condition) {
    -      return function(elem) {
    -        return elem.checked || elem.attributes['checked'];
    -      }
    -    },
    -    'first-child': function() {
    -      return _lookLeft;
    -    },
    -    'last-child': function() {
    -      return _lookRight;
    -    },
    -    'only-child': function(name, condition) {
    -      return function(node) {
    -        if (!_lookLeft(node)) {
    -          return false;
    -        }
    -        if (!_lookRight(node)) {
    -          return false;
    -        }
    -        return true;
    -      };
    -    },
    -    'empty': function(name, condition) {
    -      return function(elem) {
    -        // DomQuery and jQuery get this wrong, oddly enough.
    -        // The CSS 3 selectors spec is pretty explicit about it, too.
    -        var cn = elem.childNodes;
    -        var cnl = elem.childNodes.length;
    -        // if(!cnl) { return true; }
    -        for (var x = cnl - 1; x >= 0; x--) {
    -          var nt = cn[x].nodeType;
    -          if ((nt === 1) || (nt == 3)) {
    -            return false;
    -          }
    -        }
    -        return true;
    -      }
    -    },
    -    'contains': function(name, condition) {
    -      var cz = condition.charAt(0);
    -      if (cz == '"' || cz == "'") { // Remove quotes.
    -        condition = condition.slice(1, -1);
    -      }
    -      return function(elem) {
    -        return (elem.innerHTML.indexOf(condition) >= 0);
    -      }
    -    },
    -    'not': function(name, condition) {
    -      var p = getQueryParts(condition)[0];
    -      var ignores = { el: 1 };
    -      if (p.tag != '*') {
    -        ignores.tag = 1;
    -      }
    -      if (!p.classes.length) {
    -        ignores.classes = 1;
    -      }
    -      var ntf = getSimpleFilterFunc(p, ignores);
    -      return function(elem) {
    -        return !ntf(elem);
    -      }
    -    },
    -    'nth-child': function(name, condition) {
    -      function pi(n) {
    -        return parseInt(n, 10);
    -      }
    -      // avoid re-defining function objects if we can
    -      if (condition == 'odd') {
    -        return isOdd;
    -      } else if (condition == 'even') {
    -        return isEven;
    -      }
    -      // FIXME: can we shorten this?
    -      if (condition.indexOf('n') != -1) {
    -        var tparts = condition.split('n', 2);
    -        var pred = tparts[0] ? ((tparts[0] == '-') ? -1 : pi(tparts[0])) : 1;
    -        var idx = tparts[1] ? pi(tparts[1]) : 0;
    -        var lb = 0, ub = -1;
    -        if (pred > 0) {
    -          if (idx < 0) {
    -            idx = (idx % pred) && (pred + (idx % pred));
    -          } else if (idx > 0) {
    -            if (idx >= pred) {
    -              lb = idx - idx % pred;
    -            }
    -            idx = idx % pred;
    -          }
    -        } else if (pred < 0) {
    -          pred *= -1;
    -          // idx has to be greater than 0 when pred is negative;
    -          // shall we throw an error here?
    -          if (idx > 0) {
    -            ub = idx;
    -            idx = idx % pred;
    -          }
    -        }
    -        if (pred > 0) {
    -          return function(elem) {
    -            var i = getNodeIndex(elem);
    -            return (i >= lb) && (ub < 0 || i <= ub) && ((i % pred) == idx);
    -          }
    -        } else {
    -          condition = idx;
    -        }
    -      }
    -      var ncount = pi(condition);
    -      return function(elem) {
    -        return (getNodeIndex(elem) == ncount);
    -      }
    -    }
    -  };
    -
    -  var defaultGetter = (legacyIE) ? function(cond) {
    -    var clc = cond.toLowerCase();
    -    if (clc == 'class') {
    -      cond = 'className';
    -    }
    -    return function(elem) {
    -      return caseSensitive ? elem.getAttribute(cond) : elem[cond] || elem[clc];
    -    }
    -  } : function(cond) {
    -    return function(elem) {
    -      return elem && elem.getAttribute && elem.hasAttribute(cond);
    -    }
    -  };
    -
    -  var getSimpleFilterFunc = function(query, ignores) {
    -    // Generates a node tester function based on the passed query part. The
    -    // query part is one of the structures generated by the query parser when it
    -    // creates the query AST. The 'ignores' object specifies which (if any)
    -    // tests to skip, allowing the system to avoid duplicating work where it
    -    // may have already been taken into account by other factors such as how
    -    // the nodes to test were fetched in the first place.
    -    if (!query) {
    -      return goog.functions.TRUE;
    -    }
    -    ignores = ignores || {};
    -
    -    var ff = null;
    -
    -    if (!ignores.el) {
    -      ff = agree(ff, isElement);
    -    }
    -
    -    if (!ignores.tag) {
    -      if (query.tag != '*') {
    -        ff = agree(ff, function(elem) {
    -          return (elem && (elem.tagName == query.getTag()));
    -        });
    -      }
    -    }
    -
    -    if (!ignores.classes) {
    -      goog.array.forEach(query.classes, function(cname, idx, arr) {
    -        // Get the class name.
    -        var re = new RegExp('(?:^|\\s)' + cname + '(?:\\s|$)');
    -        ff = agree(ff, function(elem) {
    -          return re.test(elem.className);
    -        });
    -        ff.count = idx;
    -      });
    -    }
    -
    -    if (!ignores.pseudos) {
    -      goog.array.forEach(query.pseudos, function(pseudo) {
    -        var pn = pseudo.name;
    -        if (pseudos[pn]) {
    -          ff = agree(ff, pseudos[pn](pn, pseudo.value));
    -        }
    -      });
    -    }
    -
    -    if (!ignores.attrs) {
    -      goog.array.forEach(query.attrs, function(attr) {
    -        var matcher;
    -        var a = attr.attr;
    -        // type, attr, matchFor
    -        if (attr.type && attrs[attr.type]) {
    -          matcher = attrs[attr.type](a, attr.matchFor);
    -        } else if (a.length) {
    -          matcher = defaultGetter(a);
    -        }
    -        if (matcher) {
    -          ff = agree(ff, matcher);
    -        }
    -      });
    -    }
    -
    -    if (!ignores.id) {
    -      if (query.id) {
    -        ff = agree(ff, function(elem) {
    -          return (!!elem && (elem.id == query.id));
    -        });
    -      }
    -    }
    -
    -    if (!ff) {
    -      if (!('default' in ignores)) {
    -        ff = goog.functions.TRUE;
    -      }
    -    }
    -    return ff;
    -  };
    -
    -  var nextSiblingIterator = function(filterFunc) {
    -    return function(node, ret, bag) {
    -      while (node = node[nSibling]) {
    -        if (noNextElementSibling && (!isElement(node))) {
    -          continue;
    -        }
    -        if (
    -          (!bag || _isUnique(node, bag)) &&
    -          filterFunc(node)
    -        ) {
    -          ret.push(node);
    -        }
    -        break;
    -      }
    -      return ret;
    -    };
    -  };
    -
    -  var nextSiblingsIterator = function(filterFunc) {
    -    return function(root, ret, bag) {
    -      var te = root[nSibling];
    -      while (te) {
    -        if (simpleNodeTest(te)) {
    -          if (bag && !_isUnique(te, bag)) {
    -            break;
    -          }
    -          if (filterFunc(te)) {
    -            ret.push(te);
    -          }
    -        }
    -        te = te[nSibling];
    -      }
    -      return ret;
    -    };
    -  };
    -
    -  // Get an array of child *elements*, skipping text and comment nodes
    -  var _childElements = function(filterFunc) {
    -    filterFunc = filterFunc || goog.functions.TRUE;
    -    return function(root, ret, bag) {
    -      var te, x = 0, tret = root[childNodesName];
    -      while (te = tret[x++]) {
    -        if (
    -          simpleNodeTest(te) &&
    -          (!bag || _isUnique(te, bag)) &&
    -          (filterFunc(te, x))
    -        ) {
    -          ret.push(te);
    -        }
    -      }
    -      return ret;
    -    };
    -  };
    -
    -  // test to see if node is below root
    -  var _isDescendant = function(node, root) {
    -    var pn = node.parentNode;
    -    while (pn) {
    -      if (pn == root) {
    -        break;
    -      }
    -      pn = pn.parentNode;
    -    }
    -    return !!pn;
    -  };
    -
    -  var _getElementsFuncCache = {};
    -
    -  var getElementsFunc = function(query) {
    -    var retFunc = _getElementsFuncCache[query.query];
    -    // If we've got a cached dispatcher, just use that.
    -    if (retFunc) {
    -      return retFunc;
    -    }
    -    // Else, generate a new one.
    -
    -    // NOTE:
    -    //    This function returns a function that searches for nodes and
    -    //    filters them. The search may be specialized by infix operators
    -    //    (">", "~", or "+") else it will default to searching all
    -    //    descendants (the " " selector). Once a group of children is
    -    //    found, a test function is applied to weed out the ones we
    -    //    don't want. Many common cases can be fast-pathed. We spend a
    -    //    lot of cycles to create a dispatcher that doesn't do more work
    -    //    than necessary at any point since, unlike this function, the
    -    //    dispatchers will be called every time. The logic of generating
    -    //    efficient dispatchers looks like this in pseudo code:
    -    //
    -    //    # if it's a purely descendant query (no ">", "+", or "~" modifiers)
    -    //    if infixOperator == " ":
    -    //      if only(id):
    -    //        return def(root):
    -    //          return d.byId(id, root);
    -    //
    -    //      elif id:
    -    //        return def(root):
    -    //          return filter(d.byId(id, root));
    -    //
    -    //      elif cssClass && getElementsByClassName:
    -    //        return def(root):
    -    //          return filter(root.getElementsByClassName(cssClass));
    -    //
    -    //      elif only(tag):
    -    //        return def(root):
    -    //          return root.getElementsByTagName(tagName);
    -    //
    -    //      else:
    -    //        # search by tag name, then filter
    -    //        return def(root):
    -    //          return filter(root.getElementsByTagName(tagName||"*"));
    -    //
    -    //    elif infixOperator == ">":
    -    //      # search direct children
    -    //      return def(root):
    -    //        return filter(root.children);
    -    //
    -    //    elif infixOperator == "+":
    -    //      # search next sibling
    -    //      return def(root):
    -    //        return filter(root.nextElementSibling);
    -    //
    -    //    elif infixOperator == "~":
    -    //      # search rightward siblings
    -    //      return def(root):
    -    //        return filter(nextSiblings(root));
    -
    -    var io = query.infixOper;
    -    var oper = (io ? io.oper : '');
    -    // The default filter func which tests for all conditions in the query
    -    // part. This is potentially inefficient, so some optimized paths may
    -    // re-define it to test fewer things.
    -    var filterFunc = getSimpleFilterFunc(query, { el: 1 });
    -    var qt = query.tag;
    -    var wildcardTag = ('*' == qt);
    -    var ecs = goog.dom.getDocument()['getElementsByClassName'];
    -
    -    if (!oper) {
    -      // If there's no infix operator, then it's a descendant query. ID
    -      // and "elements by class name" variants can be accelerated so we
    -      // call them out explicitly:
    -      if (query.id) {
    -        // Testing shows that the overhead of goog.functions.TRUE() is
    -        // acceptable and can save us some bytes vs. re-defining the function
    -        // everywhere.
    -        filterFunc = (!query.loops && wildcardTag) ?
    -          goog.functions.TRUE :
    -          getSimpleFilterFunc(query, { el: 1, id: 1 });
    -
    -        retFunc = function(root, arr) {
    -          var te = goog.dom.getDomHelper(root).getElement(query.id);
    -          if (!te || !filterFunc(te)) {
    -            return;
    -          }
    -          if (9 == root.nodeType) { // If root's a doc, we just return directly.
    -            return getArr(te, arr);
    -          } else { // otherwise check ancestry
    -            if (_isDescendant(te, root)) {
    -              return getArr(te, arr);
    -            }
    -          }
    -        }
    -      } else if (
    -        ecs &&
    -        // isAlien check. Workaround for Prototype.js being totally evil/dumb.
    -        /\{\s*\[native code\]\s*\}/.test(String(ecs)) &&
    -        query.classes.length &&
    -        // WebKit bug where quirks-mode docs select by class w/o case
    -        // sensitivity.
    -        !cssCaseBug
    -      ) {
    -        // it's a class-based query and we've got a fast way to run it.
    -
    -        // ignore class and ID filters since we will have handled both
    -        filterFunc = getSimpleFilterFunc(query, { el: 1, classes: 1, id: 1 });
    -        var classesString = query.classes.join(' ');
    -        retFunc = function(root, arr) {
    -          var ret = getArr(0, arr), te, x = 0;
    -          var tret = root.getElementsByClassName(classesString);
    -          while ((te = tret[x++])) {
    -            if (filterFunc(te, root)) {
    -              ret.push(te);
    -            }
    -          }
    -          return ret;
    -        };
    -
    -      } else if (!wildcardTag && !query.loops) {
    -        // it's tag only. Fast-path it.
    -        retFunc = function(root, arr) {
    -          var ret = getArr(0, arr), te, x = 0;
    -          var tret = root.getElementsByTagName(query.getTag());
    -          while ((te = tret[x++])) {
    -            ret.push(te);
    -          }
    -          return ret;
    -        };
    -      } else {
    -        // the common case:
    -        //    a descendant selector without a fast path. By now it's got
    -        //    to have a tag selector, even if it's just "*" so we query
    -        //    by that and filter
    -        filterFunc = getSimpleFilterFunc(query, { el: 1, tag: 1, id: 1 });
    -        retFunc = function(root, arr) {
    -          var ret = getArr(0, arr), te, x = 0;
    -          // we use getTag() to avoid case sensitivity issues
    -          var tret = root.getElementsByTagName(query.getTag());
    -          while (te = tret[x++]) {
    -            if (filterFunc(te, root)) {
    -              ret.push(te);
    -            }
    -          }
    -          return ret;
    -        };
    -      }
    -    } else {
    -      // the query is scoped in some way. Instead of querying by tag we
    -      // use some other collection to find candidate nodes
    -      var skipFilters = { el: 1 };
    -      if (wildcardTag) {
    -        skipFilters.tag = 1;
    -      }
    -      filterFunc = getSimpleFilterFunc(query, skipFilters);
    -      if ('+' == oper) {
    -        retFunc = nextSiblingIterator(filterFunc);
    -      } else if ('~' == oper) {
    -        retFunc = nextSiblingsIterator(filterFunc);
    -      } else if ('>' == oper) {
    -        retFunc = _childElements(filterFunc);
    -      }
    -    }
    -    // cache it and return
    -    return _getElementsFuncCache[query.query] = retFunc;
    -  };
    -
    -  var filterDown = function(root, queryParts) {
    -    // NOTE:
    -    //    this is the guts of the DOM query system. It takes a list of
    -    //    parsed query parts and a root and finds children which match
    -    //    the selector represented by the parts
    -    var candidates = getArr(root), qp, x, te, qpl = queryParts.length, bag, ret;
    -
    -    for (var i = 0; i < qpl; i++) {
    -      ret = [];
    -      qp = queryParts[i];
    -      x = candidates.length - 1;
    -      if (x > 0) {
    -        // if we have more than one root at this level, provide a new
    -        // hash to use for checking group membership but tell the
    -        // system not to post-filter us since we will already have been
    -        // guaranteed to be unique
    -        bag = {};
    -        ret.nozip = true;
    -      }
    -      var gef = getElementsFunc(qp);
    -      for (var j = 0; te = candidates[j]; j++) {
    -        // for every root, get the elements that match the descendant
    -        // selector, adding them to the 'ret' array and filtering them
    -        // via membership in this level's bag. If there are more query
    -        // parts, then this level's return will be used as the next
    -        // level's candidates
    -        gef(te, ret, bag);
    -      }
    -      if (!ret.length) { break; }
    -      candidates = ret;
    -    }
    -    return ret;
    -  };
    -
    -  ////////////////////////////////////////////////////////////////////////
    -  // the query runner
    -  ////////////////////////////////////////////////////////////////////////
    -
    -  // these are the primary caches for full-query results. The query
    -  // dispatcher functions are generated then stored here for hash lookup in
    -  // the future
    -  var _queryFuncCacheDOM = {},
    -    _queryFuncCacheQSA = {};
    -
    -  // this is the second level of splitting, from full-length queries (e.g.,
    -  // 'div.foo .bar') into simple query expressions (e.g., ['div.foo',
    -  // '.bar'])
    -  var getStepQueryFunc = function(query) {
    -    var qparts = getQueryParts(goog.string.trim(query));
    -
    -    // if it's trivial, avoid iteration and zipping costs
    -    if (qparts.length == 1) {
    -      // We optimize this case here to prevent dispatch further down the
    -      // chain, potentially slowing things down. We could more elegantly
    -      // handle this in filterDown(), but it's slower for simple things
    -      // that need to be fast (e.g., '#someId').
    -      var tef = getElementsFunc(qparts[0]);
    -      return function(root) {
    -        var r = tef(root, []);
    -        if (r) { r.nozip = true; }
    -        return r;
    -      }
    -    }
    -
    -    // otherwise, break it up and return a runner that iterates over the parts
    -    // recursively
    -    return function(root) {
    -      return filterDown(root, qparts);
    -    }
    -  };
    -
    -  // NOTES:
    -  //  * we can't trust QSA for anything but document-rooted queries, so
    -  //    caching is split into DOM query evaluators and QSA query evaluators
    -  //  * caching query results is dirty and leak-prone (or, at a minimum,
    -  //    prone to unbounded growth). Other toolkits may go this route, but
    -  //    they totally destroy their own ability to manage their memory
    -  //    footprint. If we implement it, it should only ever be with a fixed
    -  //    total element reference # limit and an LRU-style algorithm since JS
    -  //    has no weakref support. Caching compiled query evaluators is also
    -  //    potentially problematic, but even on large documents the size of the
    -  //    query evaluators is often < 100 function objects per evaluator (and
    -  //    LRU can be applied if it's ever shown to be an issue).
    -  //  * since IE's QSA support is currently only for HTML documents and even
    -  //    then only in IE 8's 'standards mode', we have to detect our dispatch
    -  //    route at query time and keep 2 separate caches. Ugg.
    -
    -  var qsa = 'querySelectorAll';
    -
    -  // some versions of Safari provided QSA, but it was buggy and crash-prone.
    -  // We need to detect the right 'internal' webkit version to make this work.
    -  var qsaAvail = (
    -    !!goog.dom.getDocument()[qsa] &&
    -    // see #5832
    -    (!goog.userAgent.WEBKIT || goog.userAgent.isVersionOrHigher('526'))
    -  );
    -
    -  /** @param {boolean=} opt_forceDOM */
    -  var getQueryFunc = function(query, opt_forceDOM) {
    -
    -    if (qsaAvail) {
    -      // if we've got a cached variant and we think we can do it, run it!
    -      var qsaCached = _queryFuncCacheQSA[query];
    -      if (qsaCached && !opt_forceDOM) {
    -        return qsaCached;
    -      }
    -    }
    -
    -    // else if we've got a DOM cached variant, assume that we already know
    -    // all we need to and use it
    -    var domCached = _queryFuncCacheDOM[query];
    -    if (domCached) {
    -      return domCached;
    -    }
    -
    -    // TODO:
    -    //    today we're caching DOM and QSA branches separately so we
    -    //    recalc useQSA every time. If we had a way to tag root+query
    -    //    efficiently, we'd be in good shape to do a global cache.
    -
    -    var qcz = query.charAt(0);
    -    var nospace = (-1 == query.indexOf(' '));
    -
    -    // byId searches are wicked fast compared to QSA, even when filtering
    -    // is required
    -    if ((query.indexOf('#') >= 0) && (nospace)) {
    -      opt_forceDOM = true;
    -    }
    -
    -    var useQSA = (
    -      qsaAvail && (!opt_forceDOM) &&
    -      // as per CSS 3, we can't currently start w/ combinator:
    -      //    http://www.w3.org/TR/css3-selectors/#w3cselgrammar
    -      (specials.indexOf(qcz) == -1) &&
    -      // IE's QSA impl sucks on pseudos
    -      (!legacyIE || (query.indexOf(':') == -1)) &&
    -
    -      (!(cssCaseBug && (query.indexOf('.') >= 0))) &&
    -
    -      // FIXME:
    -      //    need to tighten up browser rules on ':contains' and '|=' to
    -      //    figure out which aren't good
    -      (query.indexOf(':contains') == -1) &&
    -      (query.indexOf('|=') == -1) // some browsers don't understand it
    -    );
    -
    -    // TODO:
    -    //    if we've got a descendant query (e.g., '> .thinger' instead of
    -    //    just '.thinger') in a QSA-able doc, but are passed a child as a
    -    //    root, it should be possible to give the item a synthetic ID and
    -    //    trivially rewrite the query to the form '#synid > .thinger' to
    -    //    use the QSA branch
    -
    -
    -    if (useQSA) {
    -      var tq = (specials.indexOf(query.charAt(query.length - 1)) >= 0) ?
    -            (query + ' *') : query;
    -      return _queryFuncCacheQSA[query] = function(root) {
    -        try {
    -          // the QSA system contains an egregious spec bug which
    -          // limits us, effectively, to only running QSA queries over
    -          // entire documents.  See:
    -          //    http://ejohn.org/blog/thoughts-on-queryselectorall/
    -          //  despite this, we can also handle QSA runs on simple
    -          //  selectors, but we don't want detection to be expensive
    -          //  so we're just checking for the presence of a space char
    -          //  right now. Not elegant, but it's cheaper than running
    -          //  the query parser when we might not need to
    -          if (!((9 == root.nodeType) || nospace)) {
    -            throw '';
    -          }
    -          var r = root[qsa](tq);
    -          // IE QSA queries may incorrectly include comment nodes, so we throw
    -          // the zipping function into 'remove' comments mode instead of the
    -          // normal 'skip it' which every other QSA-clued browser enjoys
    -          // skip expensive duplication checks and just wrap in an array.
    -          if (legacyIE) {
    -            r.commentStrip = true;
    -          } else {
    -            r.nozip = true;
    -          }
    -          return r;
    -        } catch (e) {
    -          // else run the DOM branch on this query, ensuring that we
    -          // default that way in the future
    -          return getQueryFunc(query, true)(root);
    -        }
    -      }
    -    } else {
    -      // DOM branch
    -      var parts = query.split(/\s*,\s*/);
    -      return _queryFuncCacheDOM[query] = ((parts.length < 2) ?
    -        // if not a compound query (e.g., '.foo, .bar'), cache and return a
    -        // dispatcher
    -        getStepQueryFunc(query) :
    -        // if it *is* a complex query, break it up into its
    -        // constituent parts and return a dispatcher that will
    -        // merge the parts when run
    -        function(root) {
    -          var pindex = 0, // avoid array alloc for every invocation
    -            ret = [],
    -            tp;
    -          while (tp = parts[pindex++]) {
    -            ret = ret.concat(getStepQueryFunc(tp)(root));
    -          }
    -          return ret;
    -        }
    -      );
    -    }
    -  };
    -
    -  var _zipIdx = 0;
    -
    -  // NOTE:
    -  //    this function is Moo inspired, but our own impl to deal correctly
    -  //    with XML in IE
    -  var _nodeUID = legacyIE ? function(node) {
    -    if (caseSensitive) {
    -      // XML docs don't have uniqueID on their nodes
    -      return node.getAttribute('_uid') ||
    -          node.setAttribute('_uid', ++_zipIdx) || _zipIdx;
    -
    -    } else {
    -      return node.uniqueID;
    -    }
    -  } :
    -  function(node) {
    -    return (node['_uid'] || (node['_uid'] = ++_zipIdx));
    -  };
    -
    -  // determine if a node in is unique in a 'bag'. In this case we don't want
    -  // to flatten a list of unique items, but rather just tell if the item in
    -  // question is already in the bag. Normally we'd just use hash lookup to do
    -  // this for us but IE's DOM is busted so we can't really count on that. On
    -  // the upside, it gives us a built in unique ID function.
    -  var _isUnique = function(node, bag) {
    -    if (!bag) {
    -      return 1;
    -    }
    -    var id = _nodeUID(node);
    -    if (!bag[id]) {
    -      return bag[id] = 1;
    -    }
    -    return 0;
    -  };
    -
    -  // attempt to efficiently determine if an item in a list is a dupe,
    -  // returning a list of 'uniques', hopefully in document order
    -  var _zipIdxName = '_zipIdx';
    -  var _zip = function(arr) {
    -    if (arr && arr.nozip) {
    -      return arr;
    -    }
    -    var ret = [];
    -    if (!arr || !arr.length) {
    -      return ret;
    -    }
    -    if (arr[0]) {
    -      ret.push(arr[0]);
    -    }
    -    if (arr.length < 2) {
    -      return ret;
    -    }
    -
    -    _zipIdx++;
    -
    -    // we have to fork here for IE and XML docs because we can't set
    -    // expandos on their nodes (apparently). *sigh*
    -    if (legacyIE && caseSensitive) {
    -      var szidx = _zipIdx + '';
    -      arr[0].setAttribute(_zipIdxName, szidx);
    -      for (var x = 1, te; te = arr[x]; x++) {
    -        if (arr[x].getAttribute(_zipIdxName) != szidx) {
    -          ret.push(te);
    -        }
    -        te.setAttribute(_zipIdxName, szidx);
    -      }
    -    } else if (legacyIE && arr.commentStrip) {
    -      try {
    -        for (var x = 1, te; te = arr[x]; x++) {
    -          if (isElement(te)) {
    -            ret.push(te);
    -          }
    -        }
    -      } catch (e) { /* squelch */ }
    -    } else {
    -      if (arr[0]) {
    -        arr[0][_zipIdxName] = _zipIdx;
    -      }
    -      for (var x = 1, te; te = arr[x]; x++) {
    -        if (arr[x][_zipIdxName] != _zipIdx) {
    -          ret.push(te);
    -        }
    -        te[_zipIdxName] = _zipIdx;
    -      }
    -    }
    -    return ret;
    -  };
    -
    -  /**
    -   * The main executor. Type specification from above.
    -   * @param {string|Array} query The query.
    -   * @param {(string|Node)=} root The root.
    -   * @return {!Array} The elements that matched the query.
    -   */
    -  var query = function(query, root) {
    -    // NOTE: elementsById is not currently supported
    -    // NOTE: ignores xpath-ish queries for now
    -
    -    //Set list constructor to desired value. This can change
    -    //between calls, so always re-assign here.
    -
    -    if (!query) {
    -      return [];
    -    }
    -
    -    if (query.constructor == Array) {
    -      return /** @type {!Array} */ (query);
    -    }
    -
    -    if (!goog.isString(query)) {
    -      return [query];
    -    }
    -
    -    if (goog.isString(root)) {
    -      root = goog.dom.getElement(root);
    -      if (!root) {
    -        return [];
    -      }
    -    }
    -
    -    root = root || goog.dom.getDocument();
    -    var od = root.ownerDocument || root.documentElement;
    -
    -    // throw the big case sensitivity switch
    -
    -    // NOTE:
    -    //    Opera in XHTML mode doesn't detect case-sensitivity correctly
    -    //    and it's not clear that there's any way to test for it
    -    caseSensitive =
    -        root.contentType && root.contentType == 'application/xml' ||
    -        goog.userAgent.OPERA &&
    -          (root.doctype || od.toString() == '[object XMLDocument]') ||
    -        !!od &&
    -        (legacyIE ? od.xml : (root.xmlVersion || od.xmlVersion));
    -
    -    // NOTE:
    -    //    adding 'true' as the 2nd argument to getQueryFunc is useful for
    -    //    testing the DOM branch without worrying about the
    -    //    behavior/performance of the QSA branch.
    -    var r = getQueryFunc(query)(root);
    -
    -    // FIXME(slightlyoff):
    -    //    need to investigate this branch WRT dojo:#8074 and dojo:#8075
    -    if (r && r.nozip) {
    -      return r;
    -    }
    -    return _zip(r);
    -  }
    -
    -  // FIXME: need to add infrastructure for post-filtering pseudos, ala :last
    -  query.pseudos = pseudos;
    -
    -  return query;
    -})();
    -
    -// TODO(arv): Please don't export here since it clobbers dead code elimination.
    -goog.exportSymbol('goog.dom.query', goog.dom.query);
    -goog.exportSymbol('goog.dom.query.pseudos', goog.dom.query.pseudos);
    diff --git a/src/database/third_party/closure-library/third_party/closure/goog/dojo/dom/query_test.html b/src/database/third_party/closure-library/third_party/closure/goog/dojo/dom/query_test.html
    deleted file mode 100644
    index 21dc81186dd..00000000000
    --- a/src/database/third_party/closure-library/third_party/closure/goog/dojo/dom/query_test.html
    +++ /dev/null
    @@ -1,64 +0,0 @@
    -<!DOCTYPE html>
    -<!--
    -Copyright 2005-2008, The Dojo Foundation
    -Modifications Copyright 2008 The Closure Library Authors. All Rights Reserved.
    -All Rights Reserved
    --->
    -<html>
    -<head>
    -  <title>Closure Unit Tests - goog.dom</title>
    -  <script src="../../../../../closure/goog/base.js"></script>
    -  <script>
    -    goog.require('goog.dom');
    -    goog.require('goog.dom.query');
    -    goog.require('goog.testing.asserts');
    -    goog.require('goog.testing.jsunit');
    -  </script>
    -  <script src="query_test.js"></script>
    -</head>
    -<body>
    -<h1>testing goog.dom.query()</h1>
    -<div id="t">
    -  <h3>h3 <span>span</span> endh3 </h3>
    -  <!-- comment to throw things off -->
    -  <div class="foo bar" id="_foo">
    -    <h3>h3</h3>
    -    <span id="foo"></span>
    -    <span></span>
    -  </div>
    -  <h3>h3</h3>
    -  <h3 class="baz" title="thud">h3</h3>
    -  <span class="foobar baz foo"></span>
    -  <span foo="bar"></span>
    -  <span foo="baz bar thud"></span>
    -  <!-- FIXME: should foo="bar-baz-thud" match? [foo$=thud] ??? -->
    -  <span foo="bar-baz-thudish" id="silly:id::with:colons"></span>
    -  <div id="container">
    -    <div id="child1" qux="true"></div>
    -    <div id="child2"></div>
    -    <div id="child3" qux="true"></div>
    -  </div>
    -  <div qux="true"></div>
    -  <input id="notbug" name="bug" type="hidden" value="failed">
    -  <input id="bug" type="hidden" value="passed">
    -</div>
    -
    -<div class="myupperclass">
    -  <span class="myclass">
    -    <input id="myid1">
    -  </span>
    -  <span class="myclass">
    -    <input id="myid2">
    -  </span>
    -</div>
    -
    -<iframe name=ifr></iframe>
    -<div id=iframe-test>
    -  <div id=if1>
    -    <div class=if2>
    -      <div id=if3></div>
    -    </div>
    -  </div>
    -</div>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/third_party/closure/goog/dojo/dom/query_test.js b/src/database/third_party/closure-library/third_party/closure/goog/dojo/dom/query_test.js
    deleted file mode 100644
    index 68f539a9e79..00000000000
    --- a/src/database/third_party/closure-library/third_party/closure/goog/dojo/dom/query_test.js
    +++ /dev/null
    @@ -1,173 +0,0 @@
    -goog.setTestOnly('query_test');
    -
    -goog.require('goog.dom');
    -goog.require('goog.userAgent');
    -
    -function testBasicSelectors() {
    -  assertQuery(4, 'h3');
    -  assertQuery(1, 'h1:first-child');
    -  assertQuery(2, 'h3:first-child');
    -  assertQuery(1, '#t');
    -  assertQuery(1, '#bug');
    -  assertQuery(4, '#t h3');
    -  assertQuery(1, 'div#t');
    -  assertQuery(4, 'div#t h3');
    -  assertQuery(0, 'span#t');
    -  assertQuery(1, '#t div > h3');
    -  assertQuery(2, '.foo');
    -  assertQuery(1, '.foo.bar');
    -  assertQuery(2, '.baz');
    -  assertQuery(3, '#t > h3');
    -}
    -
    -function testSyntacticEquivalents() {
    -  // syntactic equivalents
    -  assertQuery(12, '#t > *');
    -  assertQuery(12, '#t >');
    -  assertQuery(3, '.foo > *');
    -  assertQuery(3, '.foo >');
    -}
    -
    -function testWithARootById() {
    -  // Broken in latest chrome.
    -  if (goog.userAgent.WEBKIT) {
    -    return;
    -  }
    -
    -  // with a root, by ID
    -  assertQuery(3, '> *', 'container');
    -  assertQuery(3, '> h3', 't');
    -}
    -
    -function testCompoundQueries() {
    -  // compound queries
    -  assertQuery(2, '.foo, .bar');
    -  assertQuery(2, '.foo,.bar');
    -}
    -
    -function testMultipleClassAttributes() {
    -  // multiple class attribute
    -  assertQuery(1, '.foo.bar');
    -  assertQuery(2, '.foo');
    -  assertQuery(2, '.baz');
    -}
    -
    -function testCaseSensitivity() {
    -  // case sensitivity
    -  assertQuery(1, 'span.baz');
    -  assertQuery(1, 'sPaN.baz');
    -  assertQuery(1, 'SPAN.baz');
    -  assertQuery(1, '[class = \"foo bar\"]');
    -  assertQuery(2, '[foo~=\"bar\"]');
    -  assertQuery(2, '[ foo ~= \"bar\" ]');
    -}
    -
    -function testAttributes() {
    -  assertQuery(3, '[foo]');
    -  assertQuery(1, '[foo$=\"thud\"]');
    -  assertQuery(1, '[foo$=thud]');
    -  assertQuery(1, '[foo$=\"thudish\"]');
    -  assertQuery(1, '#t [foo$=thud]');
    -  assertQuery(1, '#t [ title $= thud ]');
    -  assertQuery(0, '#t span[ title $= thud ]');
    -  assertQuery(2, '[foo|=\"bar\"]');
    -  assertQuery(1, '[foo|=\"bar-baz\"]');
    -  assertQuery(0, '[foo|=\"baz\"]');
    -}
    -
    -function testDescendantSelectors() {
    -
    -  // Broken in latest chrome.
    -  if (goog.userAgent.WEBKIT) {
    -    return;
    -  }
    -
    -  assertQuery(3, '>', 'container');
    -  assertQuery(3, '> *', 'container');
    -  assertQuery(2, '> [qux]', 'container');
    -  assertEquals('child1', goog.dom.query('> [qux]', 'container')[0].id);
    -  assertEquals('child3', goog.dom.query('> [qux]', 'container')[1].id);
    -  assertQuery(3, '>', 'container');
    -  assertQuery(3, '> *', 'container');
    -}
    -
    -function testSiblingSelectors() {
    -  assertQuery(1, '+', 'container');
    -  assertQuery(3, '~', 'container');
    -  assertQuery(1, '.foo + span');
    -  assertQuery(4, '.foo ~ span');
    -  assertQuery(1, '#foo ~ *');
    -  assertQuery(1, '#foo ~');
    -}
    -
    -function testSubSelectors() {
    -  // sub-selector parsing
    -  assertQuery(1, '#t span.foo:not(span:first-child)');
    -  assertQuery(1, '#t span.foo:not(:first-child)');
    -}
    -
    -function testNthChild() {
    -  assertEquals(goog.dom.$('_foo'), goog.dom.query('.foo:nth-child(2)')[0]);
    -  assertQuery(2, '#t > h3:nth-child(odd)');
    -  assertQuery(3, '#t h3:nth-child(odd)');
    -  assertQuery(3, '#t h3:nth-child(2n+1)');
    -  assertQuery(1, '#t h3:nth-child(even)');
    -  assertQuery(1, '#t h3:nth-child(2n)');
    -  assertQuery(1, '#t h3:nth-child(2n+3)');
    -  assertQuery(2, '#t h3:nth-child(1)');
    -  assertQuery(1, '#t > h3:nth-child(1)');
    -  assertQuery(3, '#t :nth-child(3)');
    -  assertQuery(0, '#t > div:nth-child(1)');
    -  assertQuery(7, '#t span');
    -  assertQuery(3, '#t > *:nth-child(n+10)');
    -  assertQuery(1, '#t > *:nth-child(n+12)');
    -  assertQuery(10, '#t > *:nth-child(-n+10)');
    -  assertQuery(5, '#t > *:nth-child(-2n+10)');
    -  assertQuery(6, '#t > *:nth-child(2n+2)');
    -  assertQuery(5, '#t > *:nth-child(2n+4)');
    -  assertQuery(5, '#t > *:nth-child(2n+4)');
    -  assertQuery(12, '#t > *:nth-child(n-5)');
    -  assertQuery(6, '#t > *:nth-child(2n-5)');
    -}
    -
    -function testEmptyPseudoSelector() {
    -  assertQuery(4, '#t > span:empty');
    -  assertQuery(6, '#t span:empty');
    -  assertQuery(0, 'h3 span:empty');
    -  assertQuery(1, 'h3 :not(:empty)');
    -}
    -
    -function testIdsWithColons() {
    -  assertQuery(1, '#silly\\:id\\:\\:with\\:colons');
    -}
    -
    -function testOrder() {
    -  var els = goog.dom.query('.myupperclass .myclass input');
    -  assertEquals('myid1', els[0].id);
    -  assertEquals('myid2', els[1].id);
    -}
    -
    -function testCorrectDocumentInFrame() {
    -  var frameDocument = window.frames['ifr'].document;
    -  frameDocument.body.innerHTML =
    -      document.getElementById('iframe-test').innerHTML;
    -
    -  var els = goog.dom.query('#if1 .if2 div', document);
    -  var frameEls = goog.dom.query('#if1 .if2 div', frameDocument);
    -
    -  assertEquals(els.length, frameEls.length);
    -  assertEquals(1, frameEls.length);
    -  assertNotEquals(document.getElementById('if3'),
    -                  frameDocument.getElementById('if3'));
    -}
    -
    -
    -/**
    - * @param {number} expectedNumberOfNodes
    - * @param {...*} var_args
    - */
    -function assertQuery(expectedNumberOfNodes, var_args) {
    -  var args = Array.prototype.slice.call(arguments, 1);
    -  assertEquals(expectedNumberOfNodes,
    -               goog.dom.query.apply(null, args).length);
    -}
    diff --git a/src/database/third_party/closure-library/third_party/closure/goog/jpeg_encoder/jpeg_encoder_basic.js b/src/database/third_party/closure-library/third_party/closure/goog/jpeg_encoder/jpeg_encoder_basic.js
    deleted file mode 100644
    index aadccfb709d..00000000000
    --- a/src/database/third_party/closure-library/third_party/closure/goog/jpeg_encoder/jpeg_encoder_basic.js
    +++ /dev/null
    @@ -1,751 +0,0 @@
    -/**
    - * @license
    -  Copyright (c) 2008, Adobe Systems Incorporated
    -  All rights reserved.
    -
    -  Redistribution and use in source and binary forms, with or without
    -  modification, are permitted provided that the following conditions are
    -  met:
    -
    -  * Redistributions of source code must retain the above copyright notice,
    -    this list of conditions and the following disclaimer.
    -
    -  * Redistributions in binary form must reproduce the above copyright
    -    notice, this list of conditions and the following disclaimer in the
    -    documentation and/or other materials provided with the distribution.
    -
    -  * Neither the name of Adobe Systems Incorporated nor the names of its
    -    contributors may be used to endorse or promote products derived from
    -    this software without specific prior written permission.
    -
    -  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
    -  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    -  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    -  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    -  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    -  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    -  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    -  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    -  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
    -  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    -  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    -*/
    -/**
    - * @license
    -JPEG encoder ported to JavaScript and optimized by Andreas Ritter, www.bytestrom.eu, 11/2009
    -
    -Basic GUI blocking jpeg encoder
    -
    -v 0.9
    -*/
    -
    -/**
    - * @fileoverview This code was ported from
    - * http://www.bytestrom.eu/blog/2009/1120a_jpeg_encoder_for_javascript and
    - * modified slightly for Closure.
    - */
    -
    -goog.provide('goog.crypt.JpegEncoder');
    -
    -goog.require('goog.crypt.base64');
    -
    -/**
    - * Initializes the JpegEncoder.
    - *
    - * @constructor
    - * @param {number=} opt_quality The compression quality. Default 50.
    - */
    -goog.crypt.JpegEncoder = function(opt_quality) {
    -  var self = this;
    -  var fround = Math.round;
    -  var ffloor = Math.floor;
    -  var YTable = new Array(64);
    -  var UVTable = new Array(64);
    -  var fdtbl_Y = new Array(64);
    -  var fdtbl_UV = new Array(64);
    -  var YDC_HT;
    -  var UVDC_HT;
    -  var YAC_HT;
    -  var UVAC_HT;
    -
    -  var bitcode = new Array(65535);
    -  var category = new Array(65535);
    -  var outputfDCTQuant = new Array(64);
    -  var DU = new Array(64);
    -  var byteout = [];
    -  var bytenew = 0;
    -  var bytepos = 7;
    -
    -  var YDU = new Array(64);
    -  var UDU = new Array(64);
    -  var VDU = new Array(64);
    -  var clt = new Array(256);
    -  var RGB_YUV_TABLE = new Array(2048);
    -  var currentQuality;
    -
    -  var ZigZag = [
    -       0, 1, 5, 6,14,15,27,28,
    -       2, 4, 7,13,16,26,29,42,
    -       3, 8,12,17,25,30,41,43,
    -       9,11,18,24,31,40,44,53,
    -      10,19,23,32,39,45,52,54,
    -      20,22,33,38,46,51,55,60,
    -      21,34,37,47,50,56,59,61,
    -      35,36,48,49,57,58,62,63
    -    ];
    -
    -  var std_dc_luminance_nrcodes = [0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0];
    -  var std_dc_luminance_values = [0,1,2,3,4,5,6,7,8,9,10,11];
    -  var std_ac_luminance_nrcodes = [0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d];
    -  var std_ac_luminance_values = [
    -      0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,
    -      0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,
    -      0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,
    -      0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,
    -      0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,
    -      0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,
    -      0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,
    -      0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,
    -      0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,
    -      0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,
    -      0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,
    -      0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
    -      0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,
    -      0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,
    -      0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,
    -      0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,
    -      0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,
    -      0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,
    -      0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,
    -      0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,
    -      0xf9,0xfa
    -    ];
    -
    -  var std_dc_chrominance_nrcodes = [0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0];
    -  var std_dc_chrominance_values = [0,1,2,3,4,5,6,7,8,9,10,11];
    -  var std_ac_chrominance_nrcodes = [0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77];
    -  var std_ac_chrominance_values = [
    -      0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,
    -      0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,
    -      0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,
    -      0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,
    -      0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,
    -      0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,
    -      0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,
    -      0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,
    -      0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,
    -      0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,
    -      0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,
    -      0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,
    -      0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,
    -      0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,
    -      0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,
    -      0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,
    -      0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,
    -      0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,
    -      0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,
    -      0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,
    -      0xf9,0xfa
    -    ];
    -
    -  function initQuantTables(sf){
    -      var YQT = [
    -        16, 11, 10, 16, 24, 40, 51, 61,
    -        12, 12, 14, 19, 26, 58, 60, 55,
    -        14, 13, 16, 24, 40, 57, 69, 56,
    -        14, 17, 22, 29, 51, 87, 80, 62,
    -        18, 22, 37, 56, 68,109,103, 77,
    -        24, 35, 55, 64, 81,104,113, 92,
    -        49, 64, 78, 87,103,121,120,101,
    -        72, 92, 95, 98,112,100,103, 99
    -      ];
    -
    -      for (var i = 0; i < 64; i++) {
    -        var t = ffloor((YQT[i]*sf+50)/100);
    -        if (t < 1) {
    -          t = 1;
    -        } else if (t > 255) {
    -          t = 255;
    -        }
    -        YTable[ZigZag[i]] = t;
    -      }
    -      var UVQT = [
    -        17, 18, 24, 47, 99, 99, 99, 99,
    -        18, 21, 26, 66, 99, 99, 99, 99,
    -        24, 26, 56, 99, 99, 99, 99, 99,
    -        47, 66, 99, 99, 99, 99, 99, 99,
    -        99, 99, 99, 99, 99, 99, 99, 99,
    -        99, 99, 99, 99, 99, 99, 99, 99,
    -        99, 99, 99, 99, 99, 99, 99, 99,
    -        99, 99, 99, 99, 99, 99, 99, 99
    -      ];
    -      for (var j = 0; j < 64; j++) {
    -        var u = ffloor((UVQT[j]*sf+50)/100);
    -        if (u < 1) {
    -          u = 1;
    -        } else if (u > 255) {
    -          u = 255;
    -        }
    -        UVTable[ZigZag[j]] = u;
    -      }
    -      var aasf = [
    -        1.0, 1.387039845, 1.306562965, 1.175875602,
    -        1.0, 0.785694958, 0.541196100, 0.275899379
    -      ];
    -      var k = 0;
    -      for (var row = 0; row < 8; row++)
    -      {
    -        for (var col = 0; col < 8; col++)
    -        {
    -          fdtbl_Y[k]  = (1.0 / (YTable [ZigZag[k]] * aasf[row] * aasf[col] * 8.0));
    -          fdtbl_UV[k] = (1.0 / (UVTable[ZigZag[k]] * aasf[row] * aasf[col] * 8.0));
    -          k++;
    -        }
    -      }
    -    }
    -
    -    function computeHuffmanTbl(nrcodes, std_table){
    -      var codevalue = 0;
    -      var pos_in_table = 0;
    -      var HT = new Array();
    -      for (var k = 1; k <= 16; k++) {
    -        for (var j = 1; j <= nrcodes[k]; j++) {
    -          HT[std_table[pos_in_table]] = [];
    -          HT[std_table[pos_in_table]][0] = codevalue;
    -          HT[std_table[pos_in_table]][1] = k;
    -          pos_in_table++;
    -          codevalue++;
    -        }
    -        codevalue*=2;
    -      }
    -      return HT;
    -    }
    -
    -    function initHuffmanTbl()
    -    {
    -      YDC_HT = computeHuffmanTbl(std_dc_luminance_nrcodes,std_dc_luminance_values);
    -      UVDC_HT = computeHuffmanTbl(std_dc_chrominance_nrcodes,std_dc_chrominance_values);
    -      YAC_HT = computeHuffmanTbl(std_ac_luminance_nrcodes,std_ac_luminance_values);
    -      UVAC_HT = computeHuffmanTbl(std_ac_chrominance_nrcodes,std_ac_chrominance_values);
    -    }
    -
    -    function initCategoryNumber()
    -    {
    -      var nrlower = 1;
    -      var nrupper = 2;
    -      for (var cat = 1; cat <= 15; cat++) {
    -        //Positive numbers
    -        for (var nr = nrlower; nr<nrupper; nr++) {
    -          category[32767+nr] = cat;
    -          bitcode[32767+nr] = [];
    -          bitcode[32767+nr][1] = cat;
    -          bitcode[32767+nr][0] = nr;
    -        }
    -        //Negative numbers
    -        for (var nrneg =-(nrupper-1); nrneg<=-nrlower; nrneg++) {
    -          category[32767+nrneg] = cat;
    -          bitcode[32767+nrneg] = [];
    -          bitcode[32767+nrneg][1] = cat;
    -          bitcode[32767+nrneg][0] = nrupper-1+nrneg;
    -        }
    -        nrlower <<= 1;
    -        nrupper <<= 1;
    -      }
    -    }
    -
    -    function initRGBYUVTable() {
    -      for(var i = 0; i < 256;i++) {
    -        RGB_YUV_TABLE[i]          =  19595 * i;
    -        RGB_YUV_TABLE[(i+ 256)>>0]   =  38470 * i;
    -        RGB_YUV_TABLE[(i+ 512)>>0]   =   7471 * i + 0x8000;
    -        RGB_YUV_TABLE[(i+ 768)>>0]   = -11059 * i;
    -        RGB_YUV_TABLE[(i+1024)>>0]   = -21709 * i;
    -        RGB_YUV_TABLE[(i+1280)>>0]   =  32768 * i + 0x807FFF;
    -        RGB_YUV_TABLE[(i+1536)>>0]   = -27439 * i;
    -        RGB_YUV_TABLE[(i+1792)>>0]   = - 5329 * i;
    -      }
    -    }
    -
    -    // IO functions
    -    function writeBits(bs)
    -    {
    -      var value = bs[0];
    -      var posval = bs[1]-1;
    -      while ( posval >= 0 ) {
    -        if (value & (1 << posval) ) {
    -          bytenew |= (1 << bytepos);
    -        }
    -        posval--;
    -        bytepos--;
    -        if (bytepos < 0) {
    -          if (bytenew == 0xFF) {
    -            writeByte(0xFF);
    -            writeByte(0);
    -          }
    -          else {
    -            writeByte(bytenew);
    -          }
    -          bytepos=7;
    -          bytenew=0;
    -        }
    -      }
    -    }
    -
    -    function writeByte(value)
    -    {
    -      byteout.push(clt[value]); // write char directly instead of converting later
    -    }
    -
    -    function writeWord(value)
    -    {
    -      writeByte((value>>8)&0xFF);
    -      writeByte((value   )&0xFF);
    -    }
    -
    -    // DCT & quantization core
    -    function fDCTQuant(data, fdtbl)
    -    {
    -      var d0, d1, d2, d3, d4, d5, d6, d7;
    -      /* Pass 1: process rows. */
    -      var dataOff=0;
    -      var i;
    -      var I8 = 8;
    -      var I64 = 64;
    -      for (i=0; i<I8; ++i)
    -      {
    -        d0 = data[dataOff];
    -        d1 = data[dataOff+1];
    -        d2 = data[dataOff+2];
    -        d3 = data[dataOff+3];
    -        d4 = data[dataOff+4];
    -        d5 = data[dataOff+5];
    -        d6 = data[dataOff+6];
    -        d7 = data[dataOff+7];
    -
    -        var tmp0 = d0 + d7;
    -        var tmp7 = d0 - d7;
    -        var tmp1 = d1 + d6;
    -        var tmp6 = d1 - d6;
    -        var tmp2 = d2 + d5;
    -        var tmp5 = d2 - d5;
    -        var tmp3 = d3 + d4;
    -        var tmp4 = d3 - d4;
    -
    -        /* Even part */
    -        var tmp10 = tmp0 + tmp3;  /* phase 2 */
    -        var tmp13 = tmp0 - tmp3;
    -        var tmp11 = tmp1 + tmp2;
    -        var tmp12 = tmp1 - tmp2;
    -
    -        data[dataOff] = tmp10 + tmp11; /* phase 3 */
    -        data[dataOff+4] = tmp10 - tmp11;
    -
    -        var z1 = (tmp12 + tmp13) * 0.707106781; /* c4 */
    -        data[dataOff+2] = tmp13 + z1; /* phase 5 */
    -        data[dataOff+6] = tmp13 - z1;
    -
    -        /* Odd part */
    -        tmp10 = tmp4 + tmp5; /* phase 2 */
    -        tmp11 = tmp5 + tmp6;
    -        tmp12 = tmp6 + tmp7;
    -
    -        /* The rotator is modified from fig 4-8 to avoid extra negations. */
    -        var z5 = (tmp10 - tmp12) * 0.382683433; /* c6 */
    -        var z2 = 0.541196100 * tmp10 + z5; /* c2-c6 */
    -        var z4 = 1.306562965 * tmp12 + z5; /* c2+c6 */
    -        var z3 = tmp11 * 0.707106781; /* c4 */
    -
    -        var z11 = tmp7 + z3;  /* phase 5 */
    -        var z13 = tmp7 - z3;
    -
    -        data[dataOff+5] = z13 + z2;  /* phase 6 */
    -        data[dataOff+3] = z13 - z2;
    -        data[dataOff+1] = z11 + z4;
    -        data[dataOff+7] = z11 - z4;
    -
    -        dataOff += 8; /* advance pointer to next row */
    -      }
    -
    -      /* Pass 2: process columns. */
    -      dataOff = 0;
    -      for (i=0; i<I8; ++i)
    -      {
    -        d0 = data[dataOff];
    -        d1 = data[dataOff + 8];
    -        d2 = data[dataOff + 16];
    -        d3 = data[dataOff + 24];
    -        d4 = data[dataOff + 32];
    -        d5 = data[dataOff + 40];
    -        d6 = data[dataOff + 48];
    -        d7 = data[dataOff + 56];
    -
    -        var tmp0p2 = d0 + d7;
    -        var tmp7p2 = d0 - d7;
    -        var tmp1p2 = d1 + d6;
    -        var tmp6p2 = d1 - d6;
    -        var tmp2p2 = d2 + d5;
    -        var tmp5p2 = d2 - d5;
    -        var tmp3p2 = d3 + d4;
    -        var tmp4p2 = d3 - d4;
    -
    -        /* Even part */
    -        var tmp10p2 = tmp0p2 + tmp3p2;  /* phase 2 */
    -        var tmp13p2 = tmp0p2 - tmp3p2;
    -        var tmp11p2 = tmp1p2 + tmp2p2;
    -        var tmp12p2 = tmp1p2 - tmp2p2;
    -
    -        data[dataOff] = tmp10p2 + tmp11p2; /* phase 3 */
    -        data[dataOff+32] = tmp10p2 - tmp11p2;
    -
    -        var z1p2 = (tmp12p2 + tmp13p2) * 0.707106781; /* c4 */
    -        data[dataOff+16] = tmp13p2 + z1p2; /* phase 5 */
    -        data[dataOff+48] = tmp13p2 - z1p2;
    -
    -        /* Odd part */
    -        tmp10p2 = tmp4p2 + tmp5p2; /* phase 2 */
    -        tmp11p2 = tmp5p2 + tmp6p2;
    -        tmp12p2 = tmp6p2 + tmp7p2;
    -
    -        /* The rotator is modified from fig 4-8 to avoid extra negations. */
    -        var z5p2 = (tmp10p2 - tmp12p2) * 0.382683433; /* c6 */
    -        var z2p2 = 0.541196100 * tmp10p2 + z5p2; /* c2-c6 */
    -        var z4p2 = 1.306562965 * tmp12p2 + z5p2; /* c2+c6 */
    -        var z3p2 = tmp11p2 * 0.707106781; /* c4 */
    -
    -        var z11p2 = tmp7p2 + z3p2;  /* phase 5 */
    -        var z13p2 = tmp7p2 - z3p2;
    -
    -        data[dataOff+40] = z13p2 + z2p2; /* phase 6 */
    -        data[dataOff+24] = z13p2 - z2p2;
    -        data[dataOff+ 8] = z11p2 + z4p2;
    -        data[dataOff+56] = z11p2 - z4p2;
    -
    -        dataOff++; /* advance pointer to next column */
    -      }
    -
    -      // Quantize/descale the coefficients
    -      var fDCTQuant;
    -      for (i=0; i<I64; ++i)
    -      {
    -        // Apply the quantization and scaling factor & Round to nearest integer
    -        fDCTQuant = data[i]*fdtbl[i];
    -        outputfDCTQuant[i] = (fDCTQuant > 0.0) ? ((fDCTQuant + 0.5)|0) : ((fDCTQuant - 0.5)|0);
    -        //outputfDCTQuant[i] = fround(fDCTQuant);
    -
    -      }
    -      return outputfDCTQuant;
    -    }
    -
    -    function writeAPP0()
    -    {
    -      writeWord(0xFFE0); // marker
    -      writeWord(16); // length
    -      writeByte(0x4A); // J
    -      writeByte(0x46); // F
    -      writeByte(0x49); // I
    -      writeByte(0x46); // F
    -      writeByte(0); // = "JFIF",'\0'
    -      writeByte(1); // versionhi
    -      writeByte(1); // versionlo
    -      writeByte(0); // xyunits
    -      writeWord(1); // xdensity
    -      writeWord(1); // ydensity
    -      writeByte(0); // thumbnwidth
    -      writeByte(0); // thumbnheight
    -    }
    -
    -    function writeSOF0(width, height)
    -    {
    -      writeWord(0xFFC0); // marker
    -      writeWord(17);   // length, truecolor YUV JPG
    -      writeByte(8);    // precision
    -      writeWord(height);
    -      writeWord(width);
    -      writeByte(3);    // nrofcomponents
    -      writeByte(1);    // IdY
    -      writeByte(0x11); // HVY
    -      writeByte(0);    // QTY
    -      writeByte(2);    // IdU
    -      writeByte(0x11); // HVU
    -      writeByte(1);    // QTU
    -      writeByte(3);    // IdV
    -      writeByte(0x11); // HVV
    -      writeByte(1);    // QTV
    -    }
    -
    -    function writeDQT()
    -    {
    -      writeWord(0xFFDB); // marker
    -      writeWord(132);     // length
    -      writeByte(0);
    -      for (var i=0; i<64; i++) {
    -        writeByte(YTable[i]);
    -      }
    -      writeByte(1);
    -      for (var j=0; j<64; j++) {
    -        writeByte(UVTable[j]);
    -      }
    -    }
    -
    -    function writeDHT()
    -    {
    -      writeWord(0xFFC4); // marker
    -      writeWord(0x01A2); // length
    -
    -      writeByte(0); // HTYDCinfo
    -      for (var i=0; i<16; i++) {
    -        writeByte(std_dc_luminance_nrcodes[i+1]);
    -      }
    -      for (var j=0; j<=11; j++) {
    -        writeByte(std_dc_luminance_values[j]);
    -      }
    -
    -      writeByte(0x10); // HTYACinfo
    -      for (var k=0; k<16; k++) {
    -        writeByte(std_ac_luminance_nrcodes[k+1]);
    -      }
    -      for (var l=0; l<=161; l++) {
    -        writeByte(std_ac_luminance_values[l]);
    -      }
    -
    -      writeByte(1); // HTUDCinfo
    -      for (var m=0; m<16; m++) {
    -        writeByte(std_dc_chrominance_nrcodes[m+1]);
    -      }
    -      for (var n=0; n<=11; n++) {
    -        writeByte(std_dc_chrominance_values[n]);
    -      }
    -
    -      writeByte(0x11); // HTUACinfo
    -      for (var o=0; o<16; o++) {
    -        writeByte(std_ac_chrominance_nrcodes[o+1]);
    -      }
    -      for (var p=0; p<=161; p++) {
    -        writeByte(std_ac_chrominance_values[p]);
    -      }
    -    }
    -
    -    function writeSOS()
    -    {
    -      writeWord(0xFFDA); // marker
    -      writeWord(12); // length
    -      writeByte(3); // nrofcomponents
    -      writeByte(1); // IdY
    -      writeByte(0); // HTY
    -      writeByte(2); // IdU
    -      writeByte(0x11); // HTU
    -      writeByte(3); // IdV
    -      writeByte(0x11); // HTV
    -      writeByte(0); // Ss
    -      writeByte(0x3f); // Se
    -      writeByte(0); // Bf
    -    }
    -
    -    function processDU(CDU, fdtbl, DC, HTDC, HTAC){
    -      var EOB = HTAC[0x00];
    -      var M16zeroes = HTAC[0xF0];
    -      var pos;
    -      var I16 = 16;
    -      var I63 = 63;
    -      var I64 = 64;
    -      var DU_DCT = fDCTQuant(CDU, fdtbl);
    -      //ZigZag reorder
    -      for (var j=0;j<I64;++j) {
    -        DU[ZigZag[j]]=DU_DCT[j];
    -      }
    -      var Diff = DU[0] - DC; DC = DU[0];
    -      //Encode DC
    -      if (Diff==0) {
    -        writeBits(HTDC[0]); // Diff might be 0
    -      } else {
    -        pos = 32767+Diff;
    -        writeBits(HTDC[category[pos]]);
    -        writeBits(bitcode[pos]);
    -      }
    -      //Encode ACs
    -      var end0pos = 63; // was const... which is crazy
    -      for (; (end0pos>0)&&(DU[end0pos]==0); end0pos--) {};
    -      //end0pos = first element in reverse order !=0
    -      if ( end0pos == 0) {
    -        writeBits(EOB);
    -        return DC;
    -      }
    -      var i = 1;
    -      var lng;
    -      while ( i <= end0pos ) {
    -        var startpos = i;
    -        for (; (DU[i]==0) && (i<=end0pos); ++i) {}
    -        var nrzeroes = i-startpos;
    -        if ( nrzeroes >= I16 ) {
    -          lng = nrzeroes>>4;
    -          for (var nrmarker=1; nrmarker <= lng; ++nrmarker)
    -            writeBits(M16zeroes);
    -          nrzeroes = nrzeroes&0xF;
    -        }
    -        pos = 32767+DU[i];
    -        writeBits(HTAC[(nrzeroes<<4)+category[pos]]);
    -        writeBits(bitcode[pos]);
    -        i++;
    -      }
    -      if ( end0pos != I63 ) {
    -        writeBits(EOB);
    -      }
    -      return DC;
    -    }
    -
    -    function initCharLookupTable(){
    -      var sfcc = String.fromCharCode;
    -      for(var i=0; i < 256; i++){ ///// ACHTUNG // 255
    -        clt[i] = sfcc(i);
    -      }
    -    }
    -
    -/**
    - * Encodes ImageData to JPEG.
    - *
    - * @param {ImageData} image
    - * @param {number=} opt_quality The compression quality.
    - * @return {string} base64-encoded JPEG data.
    - */
    -    this.encode = function(image,opt_quality) // image data object
    -    {
    -      if(opt_quality) setQuality(opt_quality);
    -
    -      // Initialize bit writer
    -      byteout = new Array();
    -      bytenew=0;
    -      bytepos=7;
    -
    -      // Add JPEG headers
    -      writeWord(0xFFD8); // SOI
    -      writeAPP0();
    -      writeDQT();
    -      writeSOF0(image.width,image.height);
    -      writeDHT();
    -      writeSOS();
    -
    -
    -      // Encode 8x8 macroblocks
    -      var _DCY=0;
    -      var _DCU=0;
    -      var _DCV=0;
    -
    -      bytenew=0;
    -      bytepos=7;
    -
    -
    -      this.encode.displayName = "_encode_";
    -
    -      var imageData = image.data;
    -      var width = image.width;
    -      var height = image.height;
    -
    -      var quadWidth = width*4;
    -      var tripleWidth = width*3;
    -
    -      var x, y = 0;
    -      var r, g, b;
    -      var start,p, col,row,pos;
    -      while(y < height){
    -        x = 0;
    -        while(x < quadWidth){
    -        start = quadWidth * y + x;
    -        p = start;
    -        col = -1;
    -        row = 0;
    -
    -        for(pos=0; pos < 64; pos++){
    -          row = pos >> 3;// /8
    -          col = ( pos & 7 ) * 4; // %8
    -          p = start + ( row * quadWidth ) + col;
    -
    -          if(y+row >= height){ // padding bottom
    -            p-= (quadWidth*(y+1+row-height));
    -          }
    -
    -          if(x+col >= quadWidth){ // padding right
    -            p-= ((x+col) - quadWidth +4)
    -          }
    -
    -          r = imageData[ p++ ];
    -          g = imageData[ p++ ];
    -          b = imageData[ p++ ];
    -
    -
    -          /* // calculate YUV values dynamically
    -          YDU[pos]=((( 0.29900)*r+( 0.58700)*g+( 0.11400)*b))-128; //-0x80
    -          UDU[pos]=(((-0.16874)*r+(-0.33126)*g+( 0.50000)*b));
    -          VDU[pos]=((( 0.50000)*r+(-0.41869)*g+(-0.08131)*b));
    -          */
    -
    -          // use lookup table (slightly faster)
    -          YDU[pos] = ((RGB_YUV_TABLE[r]             + RGB_YUV_TABLE[(g +  256)>>0] + RGB_YUV_TABLE[(b +  512)>>0]) >> 16)-128;
    -          UDU[pos] = ((RGB_YUV_TABLE[(r +  768)>>0] + RGB_YUV_TABLE[(g + 1024)>>0] + RGB_YUV_TABLE[(b + 1280)>>0]) >> 16)-128;
    -          VDU[pos] = ((RGB_YUV_TABLE[(r + 1280)>>0] + RGB_YUV_TABLE[(g + 1536)>>0] + RGB_YUV_TABLE[(b + 1792)>>0]) >> 16)-128;
    -
    -        }
    -
    -        _DCY = processDU(YDU, fdtbl_Y, _DCY, YDC_HT, YAC_HT);
    -        _DCU = processDU(UDU, fdtbl_UV, _DCU, UVDC_HT, UVAC_HT);
    -        _DCV = processDU(VDU, fdtbl_UV, _DCV, UVDC_HT, UVAC_HT);
    -        x+=32;
    -        }
    -        y+=8;
    -      }
    -
    -
    -      ////////////////////////////////////////////////////////////////
    -
    -      // Do the bit alignment of the EOI marker
    -      if ( bytepos >= 0 ) {
    -        var fillbits = [];
    -        fillbits[1] = bytepos+1;
    -        fillbits[0] = (1<<(bytepos+1))-1;
    -        writeBits(fillbits);
    -      }
    -
    -      writeWord(0xFFD9); //EOI
    -
    -      var jpegDataUri = 'data:image/jpeg;base64,'
    -        + goog.crypt.base64.encodeString(byteout.join(''));
    -
    -      byteout = [];
    -
    -      return jpegDataUri
    -  }
    -
    -  function setQuality(quality){
    -    if (quality <= 0) {
    -      quality = 1;
    -    }
    -    if (quality > 100) {
    -      quality = 100;
    -    }
    -
    -    if(currentQuality == quality) return // don't recalc if unchanged
    -
    -    var sf = 0;
    -    if (quality < 50) {
    -      sf = Math.floor(5000 / quality);
    -    } else {
    -      sf = Math.floor(200 - quality*2);
    -    }
    -
    -    initQuantTables(sf);
    -    currentQuality = quality;
    -  }
    -
    -  function init(){
    -    if(!opt_quality) opt_quality = 50;
    -    // Create tables
    -    initCharLookupTable()
    -    initHuffmanTbl();
    -    initCategoryNumber();
    -    initRGBYUVTable();
    -
    -    setQuality(opt_quality);
    -  }
    -
    -  init();
    -
    -};
    diff --git a/src/database/third_party/closure-library/third_party/closure/goog/loremipsum/text/loremipsum.js b/src/database/third_party/closure-library/third_party/closure/goog/loremipsum/text/loremipsum.js
    deleted file mode 100644
    index 127f509f871..00000000000
    --- a/src/database/third_party/closure-library/third_party/closure/goog/loremipsum/text/loremipsum.js
    +++ /dev/null
    @@ -1,712 +0,0 @@
    -//   Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -
    -/**
    - * @fileoverview A generator of lorem ipsum text based on the python
    - * implementation at http://code.google.com/p/lorem-ipsum-generator/.
    - *
    - */
    -
    -goog.provide('goog.text.LoremIpsum');
    -
    -goog.require('goog.array');
    -goog.require('goog.math');
    -goog.require('goog.string');
    -goog.require('goog.structs.Map');
    -goog.require('goog.structs.Set');
    -
    -
    -/**
    - * Generates random strings of "lorem ipsum" text, based on the word
    - * distribution of a sample text, using the words in a dictionary.
    - * @constructor
    - */
    -goog.text.LoremIpsum = function() {
    -  this.generateChains_(this.sample_);
    -  this.generateStatistics_(this.sample_);
    -
    -  this.initializeDictionary_(this.dictionary_);
    -};
    -
    -
    -/**
    - * Delimiters that end sentences.
    - * @type {Array<string>}
    - * @private
    - */
    -goog.text.LoremIpsum.DELIMITERS_SENTENCES_ = ['.', '?', '!'];
    -
    -
    -/**
    - * Regular expression for spliting a text into sentences.
    - * @type {RegExp}
    - * @private
    - */
    -goog.text.LoremIpsum.SENTENCE_SPLIT_REGEX_ = /[\.\?\!]/;
    -
    -
    -/**
    - * Delimiters that end words.
    - * @type {Array<string>}
    - * @private
    - */
    -goog.text.LoremIpsum.DELIMITERS_WORDS_ = [',', '.', '?', '!'];
    -
    -
    -/**
    - * Regular expression for spliting text into words.
    - * @type {RegExp}
    - * @private
    - */
    -goog.text.LoremIpsum.WORD_SPLIT_REGEX_ = /\s/;
    -
    -
    -/**
    - * Words that can be used in the generated output.
    - * Maps a word-length to a list of words of that length.
    - * @type {goog.structs.Map}
    - * @private
    - */
    -goog.text.LoremIpsum.prototype.words_;
    -
    -
    -/**
    - * Chains of three words that appear in the sample text
    - * Maps a pair of word-lengths to a third word-length and an optional
    - * piece of trailing punctuation (for example, a period, comma, etc.).
    - * @type {goog.structs.Map}
    - * @private
    - */
    -goog.text.LoremIpsum.prototype.chains_;
    -
    -
    -/**
    - * Pairs of word-lengths that can appear at the beginning of sentences.
    - * @type {Array}
    - */
    -goog.text.LoremIpsum.prototype.starts_;
    -
    -
    -/**
    - * Averange sentence length in words.
    - * @type {number}
    - * @private
    - */
    -goog.text.LoremIpsum.prototype.sentenceMean_;
    -
    -
    -/**
    - * Sigma (sqrt of variance) for the sentence length in words.
    - * @type {number}
    - * @private
    - */
    -goog.text.LoremIpsum.prototype.sentenceSigma_;
    -
    -
    -/**
    - * Averange paragraph length in sentences.
    - * @type {number}
    - * @private
    - */
    -goog.text.LoremIpsum.prototype.paragraphMean_;
    -
    -
    -/**
    - * Sigma (sqrt of variance) for the paragraph length in sentences.
    - * @type {number}
    - * @private
    - */
    -goog.text.LoremIpsum.prototype.paragraphSigma_;
    -
    -
    -/**
    - * Generates the chains and starts values required for sentence generation.
    - * @param {string} sample The same text.
    - * @private
    - */
    -goog.text.LoremIpsum.prototype.generateChains_ = function(sample) {
    -  var words = goog.text.LoremIpsum.splitWords_(sample);
    -  var wordInfo = goog.array.map(words, goog.text.LoremIpsum.getWordInfo_);
    -
    -  var previous = [0, 0];
    -  var previousKey = previous.join('-');
    -  var chains = new goog.structs.Map();
    -  var starts = [previousKey];
    -  var chainKeys = {};
    -
    -  goog.array.forEach(wordInfo, function(pair) {
    -    var chain = chains.get(previousKey);
    -    if (chain) {
    -      chain.push(pair);
    -    } else {
    -      chain = [pair];
    -      chains.set(previousKey, chain);
    -    }
    -
    -    if (goog.array.contains(
    -        goog.text.LoremIpsum.DELIMITERS_SENTENCES_, pair[1])) {
    -      starts.push(previousKey);
    -    }
    -    chainKeys[previousKey] = previous;
    -    previous = [previous[1], pair[0]];
    -    previousKey = previous.join('-');
    -  });
    -
    -  if (chains.getCount() > 0) {
    -    this.chains_ = chains;
    -    this.starts_ = starts;
    -    this.chainKeys_ = chainKeys;
    -  } else {
    -    throw Error('Could not generate chains from sample text.');
    -  }
    -};
    -
    -
    -/**
    - * Calculates the mean and standard deviation of sentence and paragraph lengths.
    - * @param {string} sample The same text.
    - * @private
    - */
    -goog.text.LoremIpsum.prototype.generateStatistics_ = function(sample) {
    -  this.generateSentenceStatistics_(sample);
    -  this.generateParagraphStatistics_(sample);
    -};
    -
    -
    -/**
    - * Calculates the mean and standard deviation of the lengths of sentences
    - * (in words) in a sample text.
    - * @param {string} sample The same text.
    - * @private
    - */
    -goog.text.LoremIpsum.prototype.generateSentenceStatistics_ = function(sample) {
    -  var sentences = goog.array.filter(
    -      goog.text.LoremIpsum.splitSentences_(sample),
    -      goog.text.LoremIpsum.isNotEmptyOrWhitepace_);
    -
    -  var sentenceLengths = goog.array.map(
    -      goog.array.map(sentences, goog.text.LoremIpsum.splitWords_),
    -      goog.text.LoremIpsum.arrayLength_);
    -  this.sentenceMean_ = goog.math.average.apply(null, sentenceLengths);
    -  this.sentenceSigma_ = goog.math.standardDeviation.apply(
    -      null, sentenceLengths);
    -};
    -
    -
    -/**
    - * Calculates the mean and standard deviation of the lengths of paragraphs
    - * (in sentences) in a sample text.
    - * @param {string} sample The same text.
    - * @private
    - */
    -goog.text.LoremIpsum.prototype.generateParagraphStatistics_ = function(sample) {
    -  var paragraphs = goog.array.filter(
    -      goog.text.LoremIpsum.splitParagraphs_(sample),
    -      goog.text.LoremIpsum.isNotEmptyOrWhitepace_);
    -
    -  var paragraphLengths = goog.array.map(
    -    goog.array.map(paragraphs, goog.text.LoremIpsum.splitSentences_),
    -    goog.text.LoremIpsum.arrayLength_);
    -
    -  this.paragraphMean_ = goog.math.average.apply(null, paragraphLengths);
    -  this.paragraphSigma_ = goog.math.standardDeviation.apply(
    -      null, paragraphLengths);
    -};
    -
    -
    -/**
    - * Sets the generator to use a given selection of words for generating
    - * sentences with.
    - * @param {string} dictionary The dictionary to use.
    - */
    -goog.text.LoremIpsum.prototype.initializeDictionary_ = function(dictionary) {
    -  var dictionaryWords = goog.text.LoremIpsum.splitWords_(dictionary);
    -
    -  var words = new goog.structs.Map();
    -  goog.array.forEach(dictionaryWords, function(word) {
    -    var set = words.get(word.length);
    -    if (!set) {
    -      set = new goog.structs.Set();
    -      words.set(word.length, set);
    -    }
    -    set.add(word);
    -  });
    -
    -  this.words_ = words;
    -};
    -
    -
    -/**
    - * Picks a random starting chain.
    - * @return {Array<string>} The starting key.
    - * @private
    - */
    -goog.text.LoremIpsum.prototype.chooseRandomStart_ = function() {
    -  var key = goog.text.LoremIpsum.randomChoice_(this.starts_);
    -  return this.chainKeys_[key];
    -};
    -
    -
    -/**
    - * Generates a single sentence, of random length.
    - * @param {boolean} opt_startWithLorem Whether to start the setnence with the
    - *     standard "Lorem ipsum..." first sentence.
    - * @return {string} The generated sentence.
    - */
    -goog.text.LoremIpsum.prototype.generateSentence = function(opt_startWithLorem) {
    -  if (this.chains_.getCount() == 0 || this.starts_.length == 0) {
    -    throw Error('No chains created');
    -  }
    -
    -  if (this.words_.getCount() == 0) {
    -    throw Error('No dictionary');
    -  }
    -
    -  // The length of the sentence is a normally distributed random variable.
    -  var sentenceLength = goog.text.LoremIpsum.randomNormal_(
    -      this.sentenceMean_, this.sentenceSigma_)
    -  sentenceLength = Math.max(Math.floor(sentenceLength), 1);
    -
    -  var wordDelimiter = ''; // Defined here in case while loop doesn't run
    -
    -  // Start the sentence with "Lorem ipsum...", if desired
    -  var sentence;
    -  if (opt_startWithLorem) {
    -    var lorem = 'lorem ipsum dolor sit amet, consecteteur adipiscing elit';
    -    sentence = goog.text.LoremIpsum.splitWords_(lorem);
    -    if (sentence.length > sentenceLength) {
    -      sentence.length = sentenceLength;
    -    }
    -    var lastWord = sentence[sentence.length - 1];
    -    var lastChar = lastWord.substring(lastWord.length - 1);
    -    if (goog.array.contains(goog.text.LoremIpsum.DELIMITERS_WORDS_, lastChar)) {
    -      wordDelimiter = lastChar;
    -    }
    -  } else {
    -    sentence = [];
    -  }
    -
    -  var previous = [];
    -  var previousKey = '';
    -  // Generate a sentence from the "chains"
    -  while (sentence.length < sentenceLength) {
    -    // If the current starting point is invalid, choose another randomly
    -    if (!this.chains_.containsKey(previousKey)) {
    -      previous = this.chooseRandomStart_();
    -      previousKey = previous.join('-');
    -    }
    -
    -    // Choose the next "chain" to go to. This determines the next word
    -    // length we'll use, and whether there is e.g. a comma at the end of
    -    // the word.
    -    var chain = /** @type {Array} */ (goog.text.LoremIpsum.randomChoice_(
    -        /** @type {Array} */ (this.chains_.get(previousKey))));
    -    var wordLength = chain[0];
    -
    -    // If the word delimiter contained in the chain is also a sentence
    -    // delimiter, then we don't include it because we don't want the
    -    // sentence to end prematurely (we want the length to match the
    -    // sentence_length value).
    -    //debugger;
    -    if (goog.array.contains(goog.text.LoremIpsum.DELIMITERS_SENTENCES_,
    -        chain[1])) {
    -      wordDelimiter = '';
    -    } else {
    -      wordDelimiter = chain[1];
    -    }
    -
    -    // Choose a word randomly that matches (or closely matches) the
    -    // length we're after.
    -    var closestLength = goog.text.LoremIpsum.chooseClosest(
    -            this.words_.getKeys(), wordLength);
    -    var word = goog.text.LoremIpsum.randomChoice_(
    -        this.words_.get(closestLength).getValues());
    -
    -    sentence.push(word + wordDelimiter);
    -    previous = [previous[1], wordLength];
    -    previousKey = previous.join('-');
    -  }
    -
    -  // Finish the sentence off with capitalisation, a period and
    -  // form it into a string
    -  sentence = sentence.join(' ');
    -  sentence = sentence.slice(0, 1).toUpperCase() + sentence.slice(1);
    -  if (sentence.substring(sentence.length - 1) == wordDelimiter) {
    -    sentence = sentence.slice(0, sentence.length - 1);
    -  }
    -  return sentence + '.';
    -};
    -
    -/**
    - * Generates a single lorem ipsum paragraph, of random length.
    - * @param {boolean} opt_startWithLorem Whether to start the sentence with the
    - *     standard "Lorem ipsum..." first sentence.
    - * @return {string} The generated sentence.
    - */
    -goog.text.LoremIpsum.prototype.generateParagraph = function(
    -    opt_startWithLorem) {
    -  // The length of the paragraph is a normally distributed random variable.
    -  var paragraphLength = goog.text.LoremIpsum.randomNormal_(
    -      this.paragraphMean_, this.paragraphSigma_);
    -  paragraphLength = Math.max(Math.floor(paragraphLength), 1);
    -
    -  // Construct a paragraph from a number of sentences.
    -  var paragraph = []
    -  var startWithLorem = opt_startWithLorem;
    -  while (paragraph.length < paragraphLength) {
    -      var sentence = this.generateSentence(startWithLorem);
    -      paragraph.push(sentence);
    -      startWithLorem = false;
    -  }
    -
    -  // Form the paragraph into a string.
    -  paragraph = paragraph.join(' ')
    -  return paragraph
    -};
    -
    -
    -/**
    - * Splits a piece of text into paragraphs.
    - * @param {string} text The text to split.
    - * @return {Array<string>} An array of paragraphs.
    - * @private
    - */
    -goog.text.LoremIpsum.splitParagraphs_ = function(text) {
    -  return text.split('\n')
    -};
    -
    -
    -/**
    - * Splits a piece of text into sentences.
    - * @param {string} text The text to split.
    - * @return {Array<string>} An array of sentences.
    - * @private
    - */
    -goog.text.LoremIpsum.splitSentences_ = function(text) {
    -  return goog.array.filter(
    -      text.split(goog.text.LoremIpsum.SENTENCE_SPLIT_REGEX_),
    -      goog.text.LoremIpsum.isNotEmptyOrWhitepace_);
    -};
    -
    -
    -/**
    - * Splits a piece of text into words..
    - * @param {string} text The text to split.
    - * @return {Array<string>} An array of words.
    - * @private
    - */
    -goog.text.LoremIpsum.splitWords_ = function(text) {
    -  return goog.array.filter(
    -      text.split(goog.text.LoremIpsum.WORD_SPLIT_REGEX_),
    -      goog.text.LoremIpsum.isNotEmptyOrWhitepace_);
    -};
    -
    -
    -/**
    - * Returns the text is not empty or just whitespace.
    - * @param {string} text The text to check.
    - * @return {boolean} Whether the text is nether empty nor whitespace.
    - * @private
    - */
    -goog.text.LoremIpsum.isNotEmptyOrWhitepace_ = function(text) {
    -  return goog.string.trim(text).length > 0;
    -};
    -
    -
    -/**
    - * Returns the length of an array. Written as a function so it can be used
    - * as a function parameter.
    - * @param {Array} array The array to check.
    - * @return {number} The length of the array.
    - */
    -goog.text.LoremIpsum.arrayLength_ = function(array) {
    -  return array.length;
    -};
    -
    -
    -/**
    - * Find the number in the list of values that is closest to the target.
    - * @param {Array<number>} values The values.
    - * @param {number} target The target value.
    - * @return {number} The closest value.
    - */
    -goog.text.LoremIpsum.chooseClosest = function(values, target) {
    -  var closest = values[0];
    -  goog.array.forEach(values, function(value) {
    -    if (Math.abs(target - value) < Math.abs(target - closest)) {
    -      closest = value;
    -    }
    -  });
    -
    -  return closest;
    -};
    -
    -/**
    - * Gets info about a word used as part of the lorem ipsum algorithm.
    - * @param {string} word The word to check.
    - * @return {Array} A two element array. The first element is the size of the
    - *    word. The second element is the delimter used in the word.
    - * @private
    - */
    -goog.text.LoremIpsum.getWordInfo_ = function(word) {
    -  var ret;
    -  goog.array.some(goog.text.LoremIpsum.DELIMITERS_WORDS_,
    -      function (delimiter) {
    -        if (goog.string.endsWith(word, delimiter)) {
    -          ret = [word.length - delimiter.length, delimiter];
    -          return true;
    -        }
    -        return false;
    -      }
    -  );
    -  return ret || [word.length, ''];
    -};
    -
    -
    -/**
    - * Constant used for {@link #randomNormal_}.
    - * @type {number}
    - * @private
    - */
    -goog.text.LoremIpsum.NV_MAGICCONST_ = 4 * Math.exp(-0.5) / Math.sqrt(2.0);
    -
    -
    -/**
    - * Generates a random number for a normal distribution with the specified
    - * mean and sigma.
    - * @param {number} mu The mean of the distribution.
    - * @param {number} sigma The sigma of the distribution.
    - * @private
    - */
    -goog.text.LoremIpsum.randomNormal_ = function(mu, sigma) {
    -  while (true) {
    -    var u1 = Math.random();
    -    var u2 = 1.0 - Math.random();
    -    var z = goog.text.LoremIpsum.NV_MAGICCONST_ * (u1 - 0.5) / u2;
    -    var zz = z * z / 4.0;
    -    if (zz <= -Math.log(u2)) {
    -      break;
    -    }
    -  }
    -  return mu + z * sigma;
    -};
    -
    -
    -/**
    - * Picks a random element of the array.
    - * @param {Array} array The array to pick from.
    - * @return {*} An element from the array.
    - */
    -goog.text.LoremIpsum.randomChoice_ = function(array) {
    -  return array[goog.math.randomInt(array.length)];
    -};
    -
    -
    -/**
    - * Dictionary of words for lorem ipsum.
    - * @type {string}
    - * @private
    - */
    -goog.text.LoremIpsum.DICT_ =
    -    'a ac accumsan ad adipiscing aenean aliquam aliquet amet ante ' +
    -    'aptent arcu at auctor augue bibendum blandit class commodo ' +
    -    'condimentum congue consectetuer consequat conubia convallis cras ' +
    -    'cubilia cum curabitur curae cursus dapibus diam dictum dictumst ' +
    -    'dignissim dis dolor donec dui duis egestas eget eleifend elementum ' +
    -    'elit eni enim erat eros est et etiam eu euismod facilisi facilisis ' +
    -    'fames faucibus felis fermentum feugiat fringilla fusce gravida ' +
    -    'habitant habitasse hac hendrerit hymenaeos iaculis id imperdiet ' +
    -    'in inceptos integer interdum ipsum justo lacinia lacus laoreet ' +
    -    'lectus leo libero ligula litora lobortis lorem luctus maecenas ' +
    -    'magna magnis malesuada massa mattis mauris metus mi molestie ' +
    -    'mollis montes morbi mus nam nascetur natoque nec neque netus ' +
    -    'nibh nisi nisl non nonummy nostra nulla nullam nunc odio orci ' +
    -    'ornare parturient pede pellentesque penatibus per pharetra ' +
    -    'phasellus placerat platea porta porttitor posuere potenti praesent ' +
    -    'pretium primis proin pulvinar purus quam quis quisque rhoncus ' +
    -    'ridiculus risus rutrum sagittis sapien scelerisque sed sem semper ' +
    -    'senectus sit sociis sociosqu sodales sollicitudin suscipit ' +
    -    'suspendisse taciti tellus tempor tempus tincidunt torquent tortor ' +
    -    'tristique turpis ullamcorper ultrices ultricies urna ut varius ve ' +
    -    'vehicula vel velit venenatis vestibulum vitae vivamus viverra ' +
    -    'volutpat vulputate';
    -
    -
    -/**
    - * A sample to use for generating the distribution of word and sentence lengths
    - * in lorem ipsum.
    - * @type {string}
    - * @private
    - */
    -goog.text.LoremIpsum.SAMPLE_ =
    -    'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean ' +
    -    'commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus ' +
    -    'et magnis dis parturient montes, nascetur ridiculus mus. Donec quam ' +
    -    'felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla ' +
    -    'consequat massa quis enim. Donec pede justo, fringilla vel, aliquet ' +
    -    'nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, ' +
    -    'venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. ' +
    -    'Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean ' +
    -    'vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat ' +
    -    'vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra ' +
    -    'quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius ' +
    -    'laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel ' +
    -    'augue. Curabitur ullamcorper ultricies nisi. Nam eget dui.\n\n' +
    -
    -    'Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem ' +
    -    'quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam ' +
    -    'nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec ' +
    -    'odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis ' +
    -    'faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus ' +
    -    'tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales ' +
    -    'sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit ' +
    -    'cursus nunc, quis gravida magna mi a libero. Fusce vulputate eleifend ' +
    -    'sapien. Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, ' +
    -    'metus. Nullam accumsan lorem in dui. Cras ultricies mi eu turpis ' +
    -    'hendrerit fringilla. Vestibulum ante ipsum primis in faucibus orci ' +
    -    'luctus et ultrices posuere cubilia Curae; In ac dui quis mi ' +
    -    'consectetuer lacinia.\n\n' +
    -
    -    'Nam pretium turpis et arcu. Duis arcu tortor, suscipit eget, imperdiet ' +
    -    'nec, imperdiet iaculis, ipsum. Sed aliquam ultrices mauris. Integer ' +
    -    'ante arcu, accumsan a, consectetuer eget, posuere ut, mauris. Praesent ' +
    -    'adipiscing. Phasellus ullamcorper ipsum rutrum nunc. Nunc nonummy ' +
    -    'metus. Vestibulum volutpat pretium libero. Cras id dui. Aenean ut eros ' +
    -    'et nisl sagittis vestibulum. Nullam nulla eros, ultricies sit amet, ' +
    -    'nonummy id, imperdiet feugiat, pede. Sed lectus. Donec mollis hendrerit ' +
    -    'risus. Phasellus nec sem in justo pellentesque facilisis. Etiam ' +
    -    'imperdiet imperdiet orci. Nunc nec neque. Phasellus leo dolor, tempus ' +
    -    'non, auctor et, hendrerit quis, nisi.\n\n' +
    -
    -    'Curabitur ligula sapien, tincidunt non, euismod vitae, posuere ' +
    -    'imperdiet, leo. Maecenas malesuada. Praesent congue erat at massa. Sed ' +
    -    'cursus turpis vitae tortor. Donec posuere vulputate arcu. Phasellus ' +
    -    'accumsan cursus velit. Vestibulum ante ipsum primis in faucibus orci ' +
    -    'luctus et ultrices posuere cubilia Curae; Sed aliquam, nisi quis ' +
    -    'porttitor congue, elit erat euismod orci, ac placerat dolor lectus quis ' +
    -    'orci. Phasellus consectetuer vestibulum elit. Aenean tellus metus, ' +
    -    'bibendum sed, posuere ac, mattis non, nunc. Vestibulum fringilla pede ' +
    -    'sit amet augue. In turpis. Pellentesque posuere. Praesent turpis.\n\n' +
    -
    -    'Aenean posuere, tortor sed cursus feugiat, nunc augue blandit nunc, eu ' +
    -    'sollicitudin urna dolor sagittis lacus. Donec elit libero, sodales ' +
    -    'nec, volutpat a, suscipit non, turpis. Nullam sagittis. Suspendisse ' +
    -    'pulvinar, augue ac venenatis condimentum, sem libero volutpat nibh, ' +
    -    'nec pellentesque velit pede quis nunc. Vestibulum ante ipsum primis in ' +
    -    'faucibus orci luctus et ultrices posuere cubilia Curae; Fusce id ' +
    -    'purus. Ut varius tincidunt libero. Phasellus dolor. Maecenas vestibulum ' +
    -    'mollis diam. Pellentesque ut neque. Pellentesque habitant morbi ' +
    -    'tristique senectus et netus et malesuada fames ac turpis egestas.\n\n' +
    -
    -    'In dui magna, posuere eget, vestibulum et, tempor auctor, justo. In ac ' +
    -    'felis quis tortor malesuada pretium. Pellentesque auctor neque nec ' +
    -    'urna. Proin sapien ipsum, porta a, auctor quis, euismod ut, mi. Aenean ' +
    -    'viverra rhoncus pede. Pellentesque habitant morbi tristique senectus et ' +
    -    'netus et malesuada fames ac turpis egestas. Ut non enim eleifend felis ' +
    -    'pretium feugiat. Vivamus quis mi. Phasellus a est. Phasellus magna.\n\n' +
    -
    -    'In hac habitasse platea dictumst. Curabitur at lacus ac velit ornare ' +
    -    'lobortis. Curabitur a felis in nunc fringilla tristique. Morbi mattis ' +
    -    'ullamcorper velit. Phasellus gravida semper nisi. Nullam vel sem. ' +
    -    'Pellentesque libero tortor, tincidunt et, tincidunt eget, semper nec, ' +
    -    'quam. Sed hendrerit. Morbi ac felis. Nunc egestas, augue at ' +
    -    'pellentesque laoreet, felis eros vehicula leo, at malesuada velit leo ' +
    -    'quis pede. Donec interdum, metus et hendrerit aliquet, dolor diam ' +
    -    'sagittis ligula, eget egestas libero turpis vel mi. Nunc nulla. Fusce ' +
    -    'risus nisl, viverra et, tempor et, pretium in, sapien. Donec venenatis ' +
    -    'vulputate lorem.\n\n' +
    -
    -    'Morbi nec metus. Phasellus blandit leo ut odio. Maecenas ullamcorper, ' +
    -    'dui et placerat feugiat, eros pede varius nisi, condimentum viverra ' +
    -    'felis nunc et lorem. Sed magna purus, fermentum eu, tincidunt eu, ' +
    -    'varius ut, felis. In auctor lobortis lacus. Quisque libero metus, ' +
    -    'condimentum nec, tempor a, commodo mollis, magna. Vestibulum ' +
    -    'ullamcorper mauris at ligula. Fusce fermentum. Nullam cursus lacinia ' +
    -    'erat. Praesent blandit laoreet nibh.\n\n' +
    -
    -    'Fusce convallis metus id felis luctus adipiscing. Pellentesque egestas, ' +
    -    'neque sit amet convallis pulvinar, justo nulla eleifend augue, ac ' +
    -    'auctor orci leo non est. Quisque id mi. Ut tincidunt tincidunt erat. ' +
    -    'Etiam feugiat lorem non metus. Vestibulum dapibus nunc ac augue. ' +
    -    'Curabitur vestibulum aliquam leo. Praesent egestas neque eu enim. In ' +
    -    'hac habitasse platea dictumst. Fusce a quam. Etiam ut purus mattis ' +
    -    'mauris sodales aliquam. Curabitur nisi. Quisque malesuada placerat ' +
    -    'nisl. Nam ipsum risus, rutrum vitae, vestibulum eu, molestie vel, ' +
    -    'lacus.\n\n' +
    -
    -    'Sed augue ipsum, egestas nec, vestibulum et, malesuada adipiscing, ' +
    -    'dui. Vestibulum facilisis, purus nec pulvinar iaculis, ligula mi ' +
    -    'congue nunc, vitae euismod ligula urna in dolor. Mauris sollicitudin ' +
    -    'fermentum libero. Praesent nonummy mi in odio. Nunc interdum lacus sit ' +
    -    'amet orci. Vestibulum rutrum, mi nec elementum vehicula, eros quam ' +
    -    'gravida nisl, id fringilla neque ante vel mi. Morbi mollis tellus ac ' +
    -    'sapien. Phasellus volutpat, metus eget egestas mollis, lacus lacus ' +
    -    'blandit dui, id egestas quam mauris ut lacus. Fusce vel dui. Sed in ' +
    -    'libero ut nibh placerat accumsan. Proin faucibus arcu quis ante. In ' +
    -    'consectetuer turpis ut velit. Nulla sit amet est. Praesent metus ' +
    -    'tellus, elementum eu, semper a, adipiscing nec, purus. Cras risus ' +
    -    'ipsum, faucibus ut, ullamcorper id, varius ac, leo. Suspendisse ' +
    -    'feugiat. Suspendisse enim turpis, dictum sed, iaculis a, condimentum ' +
    -    'nec, nisi. Praesent nec nisl a purus blandit viverra. Praesent ac ' +
    -    'massa at ligula laoreet iaculis. Nulla neque dolor, sagittis eget, ' +
    -    'iaculis quis, molestie non, velit.\n\n' +
    -
    -    'Mauris turpis nunc, blandit et, volutpat molestie, porta ut, ligula. ' +
    -    'Fusce pharetra convallis urna. Quisque ut nisi. Donec mi odio, faucibus ' +
    -    'at, scelerisque quis, convallis in, nisi. Suspendisse non nisl sit amet ' +
    -    'velit hendrerit rutrum. Ut leo. Ut a nisl id ante tempus hendrerit. ' +
    -    'Proin pretium, leo ac pellentesque mollis, felis nunc ultrices eros, ' +
    -    'sed gravida augue augue mollis justo. Suspendisse eu ligula. Nulla ' +
    -    'facilisi. Donec id justo. Praesent porttitor, nulla vitae posuere ' +
    -    'iaculis, arcu nisl dignissim dolor, a pretium mi sem ut ipsum. ' +
    -    'Curabitur suscipit suscipit tellus.\n\n' +
    -
    -    'Praesent vestibulum dapibus nibh. Etiam iaculis nunc ac metus. Ut id ' +
    -    'nisl quis enim dignissim sagittis. Etiam sollicitudin, ipsum eu ' +
    -    'pulvinar rutrum, tellus ipsum laoreet sapien, quis venenatis ante ' +
    -    'odio sit amet eros. Proin magna. Duis vel nibh at velit scelerisque ' +
    -    'suscipit. Curabitur turpis. Vestibulum suscipit nulla quis orci. Fusce ' +
    -    'ac felis sit amet ligula pharetra condimentum. Maecenas egestas arcu ' +
    -    'quis ligula mattis placerat. Duis lobortis massa imperdiet quam. ' +
    -    'Suspendisse potenti.\n\n' +
    -
    -    'Pellentesque commodo eros a enim. Vestibulum turpis sem, aliquet eget, ' +
    -    'lobortis pellentesque, rutrum eu, nisl. Sed libero. Aliquam erat ' +
    -    'volutpat. Etiam vitae tortor. Morbi vestibulum volutpat enim. Aliquam ' +
    -    'eu nunc. Nunc sed turpis. Sed mollis, eros et ultrices tempus, mauris ' +
    -    'ipsum aliquam libero, non adipiscing dolor urna a orci. Nulla porta ' +
    -    'dolor. Class aptent taciti sociosqu ad litora torquent per conubia ' +
    -    'nostra, per inceptos hymenaeos.\n\n' +
    -
    -    'Pellentesque dapibus hendrerit tortor. Praesent egestas tristique nibh. ' +
    -    'Sed a libero. Cras varius. Donec vitae orci sed dolor rutrum auctor. ' +
    -    'Fusce egestas elit eget lorem. Suspendisse nisl elit, rhoncus eget, ' +
    -    'elementum ac, condimentum eget, diam. Nam at tortor in tellus interdum ' +
    -    'sagittis. Aliquam lobortis. Donec orci lectus, aliquam ut, faucibus ' +
    -    'non, euismod id, nulla. Curabitur blandit mollis lacus. Nam adipiscing. ' +
    -    'Vestibulum eu odio.\n\n' +
    -
    -    'Vivamus laoreet. Nullam tincidunt adipiscing enim. Phasellus tempus. ' +
    -    'Proin viverra, ligula sit amet ultrices semper, ligula arcu tristique ' +
    -    'sapien, a accumsan nisi mauris ac eros. Fusce neque. Suspendisse ' +
    -    'faucibus, nunc et pellentesque egestas, lacus ante convallis tellus, ' +
    -    'vitae iaculis lacus elit id tortor. Vivamus aliquet elit ac nisl. Fusce ' +
    -    'fermentum odio nec arcu. Vivamus euismod mauris. In ut quam vitae ' +
    -    'odio lacinia tincidunt. Praesent ut ligula non mi varius sagittis. ' +
    -    'Cras sagittis. Praesent ac sem eget est egestas volutpat. Vivamus ' +
    -    'consectetuer hendrerit lacus. Cras non dolor. Vivamus in erat ut urna ' +
    -    'cursus vestibulum. Fusce commodo aliquam arcu. Nam commodo suscipit ' +
    -    'quam. Quisque id odio. Praesent venenatis metus at tortor pulvinar ' +
    -    'varius.\n\n';
    -
    -/**
    - * Sample that the generated text is based on .
    - * @type {string}
    - */
    -goog.text.LoremIpsum.prototype.sample_ = goog.text.LoremIpsum.SAMPLE_;
    -
    -
    -/**
    - * Dictionary of words.
    - * @type {string}
    - */
    -goog.text.LoremIpsum.prototype.dictionary_ = goog.text.LoremIpsum.DICT_;
    diff --git a/src/database/third_party/closure-library/third_party/closure/goog/loremipsum/text/loremipsum_test.html b/src/database/third_party/closure-library/third_party/closure/goog/loremipsum/text/loremipsum_test.html
    deleted file mode 100644
    index edc0a168400..00000000000
    --- a/src/database/third_party/closure-library/third_party/closure/goog/loremipsum/text/loremipsum_test.html
    +++ /dev/null
    @@ -1,60 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -  Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -  Author: dgajda@google.com (Damian Gajda)
    --->
    -<head>
    -<title>Closure Unit Tests - goog.text.LorumIpsum</title>
    -  <script src="../../../../../closure/goog/base.js"></script>
    -<script>
    -  goog.require('goog.testing.jsunit');
    -  goog.require('goog.testing.PseudoRandom');
    -  goog.require('goog.text.LoremIpsum');
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -  var pseudoRandom;
    -
    -  function setUp() {
    -    pseudoRandom = new goog.testing.PseudoRandom(100);
    -    pseudoRandom.install();
    -  }
    -
    -  function tearDown() {
    -    pseudoRandom.uninstall();
    -  }
    -
    -  function testLoremIpsum() {
    -    var generator = new goog.text.LoremIpsum();
    -    assertEquals(
    -        'Lorem ipsum dolor sit amet, consecteteur. Elementum adipiscing ' +
    -        'nisl. Nisi egestas a, taciti enim, scelerisque. Vestibulum ' +
    -        'facilisis, quis vel faucibus a, pellentesque enim, nonummy vivamus ' +
    -        'sodales. Montes. Donec eu, risus luctus ligula ante tempor euismod. ' +
    -        'Porta nostra. Tincidunt in tincidunt eros, sit ante volutpat ' +
    -        'molestie semper parturient. Vestibulum. Nisi elit elit habitant ' +
    -        'torquent. A, pellentesque quis, aliquam a, varius enim, amet est ' +
    -        'hendrerit.',
    -        generator.generateParagraph(true));
    -
    -    assertEquals(
    -        'Non elit adipiscing libero quis rhoncus a, condimentum per, eget ' +
    -        'faucibus. Duis ac consectetuer sodales. Lectus euismod sed, in a ' +
    -        'nostra felis vitae molestie imperdiet. Interdum mi, aptent nonummy ' +
    -        'dui, ve. Quisque auctor ut torquent congue, torquent erat primis ' +
    -        'ornare. Nunc at. Risus leo integer mattis enim quis nisi laoreet ' +
    -        'quisque. Eleifend gravida lacinia varius quam ullamcorper iaculis. ' +
    -        'Vivamus. Suscipit suscipit, libero parturient justo feugiat sapien, ' +
    -        'ad pharetra. Rutrum, viverra potenti tempor nisi in amet dictumst ' +
    -        'vitae. Fermentum lacus venenatis parturient vel risus. Congue ac, ' +
    -        'pharetra diam cum massa curae, vel leo elementum tempus platea, sit ' +
    -        'aliquam ve, ac.',
    -        generator.generateParagraph(false));
    -  }
    -
    -</script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/third_party/closure/goog/mochikit/async/deferred.js b/src/database/third_party/closure-library/third_party/closure/goog/mochikit/async/deferred.js
    deleted file mode 100644
    index efc19a80818..00000000000
    --- a/src/database/third_party/closure-library/third_party/closure/goog/mochikit/async/deferred.js
    +++ /dev/null
    @@ -1,943 +0,0 @@
    -// Copyright 2007 Bob Ippolito. All Rights Reserved.
    -// Modifications Copyright 2009 The Closure Library Authors. All Rights
    -// Reserved.
    -
    -/**
    - * @license Portions of this code are from MochiKit, received by
    - * The Closure Authors under the MIT license. All other code is Copyright
    - * 2005-2009 The Closure Authors. All Rights Reserved.
    - */
    -
    -/**
    - * @fileoverview Classes for tracking asynchronous operations and handling the
    - * results. The Deferred object here is patterned after the Deferred object in
    - * the Twisted python networking framework.
    - *
    - * See: http://twistedmatrix.com/projects/core/documentation/howto/defer.html
    - *
    - * Based on the Dojo code which in turn is based on the MochiKit code.
    - *
    - * @author arv@google.com (Erik Arvidsson)
    - * @author brenneman@google.com (Shawn Brenneman)
    - */
    -
    -goog.provide('goog.async.Deferred');
    -goog.provide('goog.async.Deferred.AlreadyCalledError');
    -goog.provide('goog.async.Deferred.CanceledError');
    -
    -goog.require('goog.Promise');
    -goog.require('goog.Thenable');
    -goog.require('goog.array');
    -goog.require('goog.asserts');
    -goog.require('goog.debug.Error');
    -
    -
    -
    -/**
    - * A Deferred represents the result of an asynchronous operation. A Deferred
    - * instance has no result when it is created, and is "fired" (given an initial
    - * result) by calling {@code callback} or {@code errback}.
    - *
    - * Once fired, the result is passed through a sequence of callback functions
    - * registered with {@code addCallback} or {@code addErrback}. The functions may
    - * mutate the result before it is passed to the next function in the sequence.
    - *
    - * Callbacks and errbacks may be added at any time, including after the Deferred
    - * has been "fired". If there are no pending actions in the execution sequence
    - * of a fired Deferred, any new callback functions will be called with the last
    - * computed result. Adding a callback function is the only way to access the
    - * result of the Deferred.
    - *
    - * If a Deferred operation is canceled, an optional user-provided cancellation
    - * function is invoked which may perform any special cleanup, followed by firing
    - * the Deferred's errback sequence with a {@code CanceledError}. If the
    - * Deferred has already fired, cancellation is ignored.
    - *
    - * Deferreds may be templated to a specific type they produce using generics
    - * with syntax such as:
    - * <code>
    - *   /** @type {goog.async.Deferred<string>} *&#47;
    - *   var d = new goog.async.Deferred();
    - *   // Compiler can infer that foo is a string.
    - *   d.addCallback(function(foo) {...});
    - *   d.callback('string');  // Checked to be passed a string
    - * </code>
    - * Since deferreds are often used to produce different values across a chain,
    - * the type information is not propagated across chains, but rather only
    - * associated with specifically cast objects.
    - *
    - * @param {Function=} opt_onCancelFunction A function that will be called if the
    - *     Deferred is canceled. If provided, this function runs before the
    - *     Deferred is fired with a {@code CanceledError}.
    - * @param {Object=} opt_defaultScope The default object context to call
    - *     callbacks and errbacks in.
    - * @constructor
    - * @implements {goog.Thenable<VALUE>}
    - * @template VALUE
    - */
    -goog.async.Deferred = function(opt_onCancelFunction, opt_defaultScope) {
    -  /**
    -   * Entries in the sequence are arrays containing a callback, an errback, and
    -   * an optional scope. The callback or errback in an entry may be null.
    -   * @type {!Array<!Array>}
    -   * @private
    -   */
    -  this.sequence_ = [];
    -
    -  /**
    -   * Optional function that will be called if the Deferred is canceled.
    -   * @type {Function|undefined}
    -   * @private
    -   */
    -  this.onCancelFunction_ = opt_onCancelFunction;
    -
    -  /**
    -   * The default scope to execute callbacks and errbacks in.
    -   * @type {Object}
    -   * @private
    -   */
    -  this.defaultScope_ = opt_defaultScope || null;
    -
    -  /**
    -   * Whether the Deferred has been fired.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.fired_ = false;
    -
    -  /**
    -   * Whether the last result in the execution sequence was an error.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.hadError_ = false;
    -
    -  /**
    -   * The current Deferred result, updated as callbacks and errbacks are
    -   * executed.
    -   * @type {*}
    -   * @private
    -   */
    -  this.result_ = undefined;
    -
    -  /**
    -   * Whether the Deferred is blocked waiting on another Deferred to fire. If a
    -   * callback or errback returns a Deferred as a result, the execution sequence
    -   * is blocked until that Deferred result becomes available.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.blocked_ = false;
    -
    -  /**
    -   * Whether this Deferred is blocking execution of another Deferred. If this
    -   * instance was returned as a result in another Deferred's execution
    -   * sequence,that other Deferred becomes blocked until this instance's
    -   * execution sequence completes. No additional callbacks may be added to a
    -   * Deferred once it is blocking another instance.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.blocking_ = false;
    -
    -  /**
    -   * Whether the Deferred has been canceled without having a custom cancel
    -   * function.
    -   * @type {boolean}
    -   * @private
    -   */
    -  this.silentlyCanceled_ = false;
    -
    -  /**
    -   * If an error is thrown during Deferred execution with no errback to catch
    -   * it, the error is rethrown after a timeout. Reporting the error after a
    -   * timeout allows execution to continue in the calling context (empty when
    -   * no error is scheduled).
    -   * @type {number}
    -   * @private
    -   */
    -  this.unhandledErrorId_ = 0;
    -
    -  /**
    -   * If this Deferred was created by branch(), this will be the "parent"
    -   * Deferred.
    -   * @type {goog.async.Deferred}
    -   * @private
    -   */
    -  this.parent_ = null;
    -
    -  /**
    -   * The number of Deferred objects that have been branched off this one. This
    -   * will be decremented whenever a branch is fired or canceled.
    -   * @type {number}
    -   * @private
    -   */
    -  this.branches_ = 0;
    -
    -  if (goog.async.Deferred.LONG_STACK_TRACES) {
    -    /**
    -     * Holds the stack trace at time of deferred creation if the JS engine
    -     * provides the Error.captureStackTrace API.
    -     * @private {?string}
    -     */
    -    this.constructorStack_ = null;
    -    if (Error.captureStackTrace) {
    -      var target = { stack: '' };
    -      Error.captureStackTrace(target, goog.async.Deferred);
    -      // Check if Error.captureStackTrace worked. It fails in gjstest.
    -      if (typeof target.stack == 'string') {
    -        // Remove first line and force stringify to prevent memory leak due to
    -        // holding on to actual stack frames.
    -        this.constructorStack_ = target.stack.replace(/^[^\n]*\n/, '');
    -      }
    -    }
    -  }
    -};
    -
    -
    -/**
    - * @define {boolean} Whether unhandled errors should always get rethrown to the
    - * global scope. Defaults to the value of goog.DEBUG.
    - */
    -goog.define('goog.async.Deferred.STRICT_ERRORS', false);
    -
    -
    -/**
    - * @define {boolean} Whether to attempt to make stack traces long.  Defaults to
    - * the value of goog.DEBUG.
    - */
    -goog.define('goog.async.Deferred.LONG_STACK_TRACES', false);
    -
    -
    -/**
    - * Cancels a Deferred that has not yet been fired, or is blocked on another
    - * deferred operation. If this Deferred is waiting for a blocking Deferred to
    - * fire, the blocking Deferred will also be canceled.
    - *
    - * If this Deferred was created by calling branch() on a parent Deferred with
    - * opt_propagateCancel set to true, the parent may also be canceled. If
    - * opt_deepCancel is set, cancel() will be called on the parent (as well as any
    - * other ancestors if the parent is also a branch). If one or more branches were
    - * created with opt_propagateCancel set to true, the parent will be canceled if
    - * cancel() is called on all of those branches.
    - *
    - * @param {boolean=} opt_deepCancel If true, cancels this Deferred's parent even
    - *     if cancel() hasn't been called on some of the parent's branches. Has no
    - *     effect on a branch without opt_propagateCancel set to true.
    - */
    -goog.async.Deferred.prototype.cancel = function(opt_deepCancel) {
    -  if (!this.hasFired()) {
    -    if (this.parent_) {
    -      // Get rid of the parent reference before potentially running the parent's
    -      // canceler function to ensure that this cancellation isn't
    -      // double-counted.
    -      var parent = this.parent_;
    -      delete this.parent_;
    -      if (opt_deepCancel) {
    -        parent.cancel(opt_deepCancel);
    -      } else {
    -        parent.branchCancel_();
    -      }
    -    }
    -
    -    if (this.onCancelFunction_) {
    -      // Call in user-specified scope.
    -      this.onCancelFunction_.call(this.defaultScope_, this);
    -    } else {
    -      this.silentlyCanceled_ = true;
    -    }
    -    if (!this.hasFired()) {
    -      this.errback(new goog.async.Deferred.CanceledError(this));
    -    }
    -  } else if (this.result_ instanceof goog.async.Deferred) {
    -    this.result_.cancel();
    -  }
    -};
    -
    -
    -/**
    - * Handle a single branch being canceled. Once all branches are canceled, this
    - * Deferred will be canceled as well.
    - *
    - * @private
    - */
    -goog.async.Deferred.prototype.branchCancel_ = function() {
    -  this.branches_--;
    -  if (this.branches_ <= 0) {
    -    this.cancel();
    -  }
    -};
    -
    -
    -/**
    - * Called after a blocking Deferred fires. Unblocks this Deferred and resumes
    - * its execution sequence.
    - *
    - * @param {boolean} isSuccess Whether the result is a success or an error.
    - * @param {*} res The result of the blocking Deferred.
    - * @private
    - */
    -goog.async.Deferred.prototype.continue_ = function(isSuccess, res) {
    -  this.blocked_ = false;
    -  this.updateResult_(isSuccess, res);
    -};
    -
    -
    -/**
    - * Updates the current result based on the success or failure of the last action
    - * in the execution sequence.
    - *
    - * @param {boolean} isSuccess Whether the new result is a success or an error.
    - * @param {*} res The result.
    - * @private
    - */
    -goog.async.Deferred.prototype.updateResult_ = function(isSuccess, res) {
    -  this.fired_ = true;
    -  this.result_ = res;
    -  this.hadError_ = !isSuccess;
    -  this.fire_();
    -};
    -
    -
    -/**
    - * Verifies that the Deferred has not yet been fired.
    - *
    - * @private
    - * @throws {Error} If this has already been fired.
    - */
    -goog.async.Deferred.prototype.check_ = function() {
    -  if (this.hasFired()) {
    -    if (!this.silentlyCanceled_) {
    -      throw new goog.async.Deferred.AlreadyCalledError(this);
    -    }
    -    this.silentlyCanceled_ = false;
    -  }
    -};
    -
    -
    -/**
    - * Fire the execution sequence for this Deferred by passing the starting result
    - * to the first registered callback.
    - * @param {VALUE=} opt_result The starting result.
    - */
    -goog.async.Deferred.prototype.callback = function(opt_result) {
    -  this.check_();
    -  this.assertNotDeferred_(opt_result);
    -  this.updateResult_(true /* isSuccess */, opt_result);
    -};
    -
    -
    -/**
    - * Fire the execution sequence for this Deferred by passing the starting error
    - * result to the first registered errback.
    - * @param {*=} opt_result The starting error.
    - */
    -goog.async.Deferred.prototype.errback = function(opt_result) {
    -  this.check_();
    -  this.assertNotDeferred_(opt_result);
    -  this.makeStackTraceLong_(opt_result);
    -  this.updateResult_(false /* isSuccess */, opt_result);
    -};
    -
    -
    -/**
    - * Attempt to make the error's stack trace be long in that it contains the
    - * stack trace from the point where the deferred was created on top of the
    - * current stack trace to give additional context.
    - * @param {*} error
    - * @private
    - */
    -goog.async.Deferred.prototype.makeStackTraceLong_ = function(error) {
    -  if (!goog.async.Deferred.LONG_STACK_TRACES) {
    -    return;
    -  }
    -  if (this.constructorStack_ && goog.isObject(error) && error.stack &&
    -      // Stack looks like it was system generated. See
    -      // https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
    -      (/^[^\n]+(\n   [^\n]+)+/).test(error.stack)) {
    -    error.stack = error.stack + '\nDEFERRED OPERATION:\n' +
    -        this.constructorStack_;
    -  }
    -};
    -
    -
    -/**
    - * Asserts that an object is not a Deferred.
    - * @param {*} obj The object to test.
    - * @throws {Error} Throws an exception if the object is a Deferred.
    - * @private
    - */
    -goog.async.Deferred.prototype.assertNotDeferred_ = function(obj) {
    -  goog.asserts.assert(
    -      !(obj instanceof goog.async.Deferred),
    -      'An execution sequence may not be initiated with a blocking Deferred.');
    -};
    -
    -
    -/**
    - * Register a callback function to be called with a successful result. If no
    - * value is returned by the callback function, the result value is unchanged. If
    - * a new value is returned, it becomes the Deferred result and will be passed to
    - * the next callback in the execution sequence.
    - *
    - * If the function throws an error, the error becomes the new result and will be
    - * passed to the next errback in the execution chain.
    - *
    - * If the function returns a Deferred, the execution sequence will be blocked
    - * until that Deferred fires. Its result will be passed to the next callback (or
    - * errback if it is an error result) in this Deferred's execution sequence.
    - *
    - * @param {!function(this:T,VALUE):?} cb The function to be called with a
    - *     successful result.
    - * @param {T=} opt_scope An optional scope to call the callback in.
    - * @return {!goog.async.Deferred} This Deferred.
    - * @template T
    - */
    -goog.async.Deferred.prototype.addCallback = function(cb, opt_scope) {
    -  return this.addCallbacks(cb, null, opt_scope);
    -};
    -
    -
    -/**
    - * Register a callback function to be called with an error result. If no value
    - * is returned by the function, the error result is unchanged. If a new error
    - * value is returned or thrown, that error becomes the Deferred result and will
    - * be passed to the next errback in the execution sequence.
    - *
    - * If the errback function handles the error by returning a non-error value,
    - * that result will be passed to the next normal callback in the sequence.
    - *
    - * If the function returns a Deferred, the execution sequence will be blocked
    - * until that Deferred fires. Its result will be passed to the next callback (or
    - * errback if it is an error result) in this Deferred's execution sequence.
    - *
    - * @param {!function(this:T,?):?} eb The function to be called on an
    - *     unsuccessful result.
    - * @param {T=} opt_scope An optional scope to call the errback in.
    - * @return {!goog.async.Deferred<VALUE>} This Deferred.
    - * @template T
    - */
    -goog.async.Deferred.prototype.addErrback = function(eb, opt_scope) {
    -  return this.addCallbacks(null, eb, opt_scope);
    -};
    -
    -
    -/**
    - * Registers one function as both a callback and errback.
    - *
    - * @param {!function(this:T,?):?} f The function to be called on any result.
    - * @param {T=} opt_scope An optional scope to call the function in.
    - * @return {!goog.async.Deferred} This Deferred.
    - * @template T
    - */
    -goog.async.Deferred.prototype.addBoth = function(f, opt_scope) {
    -  return this.addCallbacks(f, f, opt_scope);
    -};
    -
    -
    -/**
    - * Like addBoth, but propagates uncaught exceptions in the errback.
    - *
    - * @param {!function(this:T,?):?} f The function to be called on any result.
    - * @param {T=} opt_scope An optional scope to call the function in.
    - * @return {!goog.async.Deferred.<VALUE>} This Deferred.
    - * @template T
    - */
    -goog.async.Deferred.prototype.addFinally = function (f, opt_scope) {
    -  return this.addCallbacks(f, function (err) {
    -    var result = f.call(this, err)
    -    if (!goog.isDef(result)) {
    -      throw err
    -    }
    -    return result
    -  }, opt_scope)
    -};
    -
    -
    -/**
    - * Registers a callback function and an errback function at the same position
    - * in the execution sequence. Only one of these functions will execute,
    - * depending on the error state during the execution sequence.
    - *
    - * NOTE: This is not equivalent to {@code def.addCallback().addErrback()}! If
    - * the callback is invoked, the errback will be skipped, and vice versa.
    - *
    - * @param {(function(this:T,VALUE):?)|null} cb The function to be called on a
    - *     successful result.
    - * @param {(function(this:T,?):?)|null} eb The function to be called on an
    - *     unsuccessful result.
    - * @param {T=} opt_scope An optional scope to call the functions in.
    - * @return {!goog.async.Deferred} This Deferred.
    - * @template T
    - */
    -goog.async.Deferred.prototype.addCallbacks = function(cb, eb, opt_scope) {
    -  goog.asserts.assert(!this.blocking_, 'Blocking Deferreds can not be re-used');
    -  this.sequence_.push([cb, eb, opt_scope]);
    -  if (this.hasFired()) {
    -    this.fire_();
    -  }
    -  return this;
    -};
    -
    -
    -/**
    - * Implements {@see goog.Thenable} for seamless integration with
    - * {@see goog.Promise}.
    - * Deferred results are mutable and may represent multiple values over
    - * their lifetime. Calling {@code then} on a Deferred returns a Promise
    - * with the result of the Deferred at that point in its callback chain.
    - * Note that if the Deferred result is never mutated, and only
    - * {@code then} calls are made, the Deferred will behave like a Promise.
    - *
    - * @override
    - */
    -goog.async.Deferred.prototype.then = function(opt_onFulfilled, opt_onRejected,
    -    opt_context) {
    -  var resolve, reject;
    -  var promise = new goog.Promise(function(res, rej) {
    -    // Copying resolvers to outer scope, so that they are available when the
    -    // deferred callback fires (which may be synchronous).
    -    resolve = res;
    -    reject = rej;
    -  });
    -  this.addCallbacks(resolve, function(reason) {
    -    if (reason instanceof goog.async.Deferred.CanceledError) {
    -      promise.cancel();
    -    } else {
    -      reject(reason);
    -    }
    -  });
    -  return promise.then(opt_onFulfilled, opt_onRejected, opt_context);
    -};
    -goog.Thenable.addImplementation(goog.async.Deferred);
    -
    -
    -/**
    - * Links another Deferred to the end of this Deferred's execution sequence. The
    - * result of this execution sequence will be passed as the starting result for
    - * the chained Deferred, invoking either its first callback or errback.
    - *
    - * @param {!goog.async.Deferred} otherDeferred The Deferred to chain.
    - * @return {!goog.async.Deferred} This Deferred.
    - */
    -goog.async.Deferred.prototype.chainDeferred = function(otherDeferred) {
    -  this.addCallbacks(
    -      otherDeferred.callback, otherDeferred.errback, otherDeferred);
    -  return this;
    -};
    -
    -
    -/**
    - * Makes this Deferred wait for another Deferred's execution sequence to
    - * complete before continuing.
    - *
    - * This is equivalent to adding a callback that returns {@code otherDeferred},
    - * but doesn't prevent additional callbacks from being added to
    - * {@code otherDeferred}.
    - *
    - * @param {!goog.async.Deferred|!goog.Thenable} otherDeferred The Deferred
    - *     to wait for.
    - * @return {!goog.async.Deferred} This Deferred.
    - */
    -goog.async.Deferred.prototype.awaitDeferred = function(otherDeferred) {
    -  if (!(otherDeferred instanceof goog.async.Deferred)) {
    -    // The Thenable case.
    -    return this.addCallback(function() {
    -      return otherDeferred;
    -    });
    -  }
    -  return this.addCallback(goog.bind(otherDeferred.branch, otherDeferred));
    -};
    -
    -
    -/**
    - * Creates a branch off this Deferred's execution sequence, and returns it as a
    - * new Deferred. The branched Deferred's starting result will be shared with the
    - * parent at the point of the branch, even if further callbacks are added to the
    - * parent.
    - *
    - * All branches at the same stage in the execution sequence will receive the
    - * same starting value.
    - *
    - * @param {boolean=} opt_propagateCancel If cancel() is called on every child
    - *     branch created with opt_propagateCancel, the parent will be canceled as
    - *     well.
    - * @return {!goog.async.Deferred<VALUE>} A Deferred that will be started with
    - *     the computed result from this stage in the execution sequence.
    - */
    -goog.async.Deferred.prototype.branch = function(opt_propagateCancel) {
    -  var d = new goog.async.Deferred();
    -  this.chainDeferred(d);
    -  if (opt_propagateCancel) {
    -    d.parent_ = this;
    -    this.branches_++;
    -  }
    -  return d;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether the execution sequence has been started on this
    - *     Deferred by invoking {@code callback} or {@code errback}.
    - */
    -goog.async.Deferred.prototype.hasFired = function() {
    -  return this.fired_;
    -};
    -
    -
    -/**
    - * @param {*} res The latest result in the execution sequence.
    - * @return {boolean} Whether the current result is an error that should cause
    - *     the next errback to fire. May be overridden by subclasses to handle
    - *     special error types.
    - * @protected
    - */
    -goog.async.Deferred.prototype.isError = function(res) {
    -  return res instanceof Error;
    -};
    -
    -
    -/**
    - * @return {boolean} Whether an errback exists in the remaining sequence.
    - * @private
    - */
    -goog.async.Deferred.prototype.hasErrback_ = function() {
    -  return goog.array.some(this.sequence_, function(sequenceRow) {
    -    // The errback is the second element in the array.
    -    return goog.isFunction(sequenceRow[1]);
    -  });
    -};
    -
    -
    -/**
    - * Exhausts the execution sequence while a result is available. The result may
    - * be modified by callbacks or errbacks, and execution will block if the
    - * returned result is an incomplete Deferred.
    - *
    - * @private
    - */
    -goog.async.Deferred.prototype.fire_ = function() {
    -  if (this.unhandledErrorId_ && this.hasFired() && this.hasErrback_()) {
    -    // It is possible to add errbacks after the Deferred has fired. If a new
    -    // errback is added immediately after the Deferred encountered an unhandled
    -    // error, but before that error is rethrown, the error is unscheduled.
    -    goog.async.Deferred.unscheduleError_(this.unhandledErrorId_);
    -    this.unhandledErrorId_ = 0;
    -  }
    -
    -  if (this.parent_) {
    -    this.parent_.branches_--;
    -    delete this.parent_;
    -  }
    -
    -  var res = this.result_;
    -  var unhandledException = false;
    -  var isNewlyBlocked = false;
    -
    -  while (this.sequence_.length && !this.blocked_) {
    -    var sequenceEntry = this.sequence_.shift();
    -
    -    var callback = sequenceEntry[0];
    -    var errback = sequenceEntry[1];
    -    var scope = sequenceEntry[2];
    -
    -    var f = this.hadError_ ? errback : callback;
    -    if (f) {
    -      /** @preserveTry */
    -      try {
    -        var ret = f.call(scope || this.defaultScope_, res);
    -
    -        // If no result, then use previous result.
    -        if (goog.isDef(ret)) {
    -          // Bubble up the error as long as the return value hasn't changed.
    -          this.hadError_ = this.hadError_ && (ret == res || this.isError(ret));
    -          this.result_ = res = ret;
    -        }
    -
    -        if (goog.Thenable.isImplementedBy(res)) {
    -          isNewlyBlocked = true;
    -          this.blocked_ = true;
    -        }
    -
    -      } catch (ex) {
    -        res = ex;
    -        this.hadError_ = true;
    -        this.makeStackTraceLong_(res);
    -
    -        if (!this.hasErrback_()) {
    -          // If an error is thrown with no additional errbacks in the queue,
    -          // prepare to rethrow the error.
    -          unhandledException = true;
    -        }
    -      }
    -    }
    -  }
    -
    -  this.result_ = res;
    -
    -  if (isNewlyBlocked) {
    -    var onCallback = goog.bind(this.continue_, this, true /* isSuccess */);
    -    var onErrback = goog.bind(this.continue_, this, false /* isSuccess */);
    -
    -    if (res instanceof goog.async.Deferred) {
    -      res.addCallbacks(onCallback, onErrback);
    -      res.blocking_ = true;
    -    } else {
    -      res.then(onCallback, onErrback);
    -    }
    -  } else if (goog.async.Deferred.STRICT_ERRORS && this.isError(res) &&
    -      !(res instanceof goog.async.Deferred.CanceledError)) {
    -    this.hadError_ = true;
    -    unhandledException = true;
    -  }
    -
    -  if (unhandledException) {
    -    // Rethrow the unhandled error after a timeout. Execution will continue, but
    -    // the error will be seen by global handlers and the user. The throw will
    -    // be canceled if another errback is appended before the timeout executes.
    -    // The error's original stack trace is preserved where available.
    -    this.unhandledErrorId_ = goog.async.Deferred.scheduleError_(res);
    -  }
    -};
    -
    -
    -/**
    - * Creates a Deferred that has an initial result.
    - *
    - * @param {*=} opt_result The result.
    - * @return {!goog.async.Deferred} The new Deferred.
    - */
    -goog.async.Deferred.succeed = function(opt_result) {
    -  var d = new goog.async.Deferred();
    -  d.callback(opt_result);
    -  return d;
    -};
    -
    -
    -/**
    - * Creates a Deferred that fires when the given promise resolves.
    - * Use only during migration to Promises.
    - *
    - * @param {!goog.Promise<T>} promise
    - * @return {!goog.async.Deferred<T>} The new Deferred.
    - * @template T
    - */
    -goog.async.Deferred.fromPromise = function(promise) {
    -  var d = new goog.async.Deferred();
    -  d.callback();
    -  d.addCallback(function() {
    -    return promise;
    -  });
    -  return d;
    -};
    -
    -
    -/**
    - * Creates a Deferred that has an initial error result.
    - *
    - * @param {*} res The error result.
    - * @return {!goog.async.Deferred} The new Deferred.
    - */
    -goog.async.Deferred.fail = function(res) {
    -  var d = new goog.async.Deferred();
    -  d.errback(res);
    -  return d;
    -};
    -
    -
    -/**
    - * Creates a Deferred that has already been canceled.
    - *
    - * @return {!goog.async.Deferred} The new Deferred.
    - */
    -goog.async.Deferred.canceled = function() {
    -  var d = new goog.async.Deferred();
    -  d.cancel();
    -  return d;
    -};
    -
    -
    -/**
    - * Normalizes values that may or may not be Deferreds.
    - *
    - * If the input value is a Deferred, the Deferred is branched (so the original
    - * execution sequence is not modified) and the input callback added to the new
    - * branch. The branch is returned to the caller.
    - *
    - * If the input value is not a Deferred, the callback will be executed
    - * immediately and an already firing Deferred will be returned to the caller.
    - *
    - * In the following (contrived) example, if <code>isImmediate</code> is true
    - * then 3 is alerted immediately, otherwise 6 is alerted after a 2-second delay.
    - *
    - * <pre>
    - * var value;
    - * if (isImmediate) {
    - *   value = 3;
    - * } else {
    - *   value = new goog.async.Deferred();
    - *   setTimeout(function() { value.callback(6); }, 2000);
    - * }
    - *
    - * var d = goog.async.Deferred.when(value, alert);
    - * </pre>
    - *
    - * @param {*} value Deferred or normal value to pass to the callback.
    - * @param {!function(this:T, ?):?} callback The callback to execute.
    - * @param {T=} opt_scope An optional scope to call the callback in.
    - * @return {!goog.async.Deferred} A new Deferred that will call the input
    - *     callback with the input value.
    - * @template T
    - */
    -goog.async.Deferred.when = function(value, callback, opt_scope) {
    -  if (value instanceof goog.async.Deferred) {
    -    return value.branch(true).addCallback(callback, opt_scope);
    -  } else {
    -    return goog.async.Deferred.succeed(value).addCallback(callback, opt_scope);
    -  }
    -};
    -
    -
    -
    -/**
    - * An error sub class that is used when a Deferred has already been called.
    - * @param {!goog.async.Deferred} deferred The Deferred.
    - *
    - * @constructor
    - * @extends {goog.debug.Error}
    - */
    -goog.async.Deferred.AlreadyCalledError = function(deferred) {
    -  goog.debug.Error.call(this);
    -
    -  /**
    -   * The Deferred that raised this error.
    -   * @type {goog.async.Deferred}
    -   */
    -  this.deferred = deferred;
    -};
    -goog.inherits(goog.async.Deferred.AlreadyCalledError, goog.debug.Error);
    -
    -
    -/** @override */
    -goog.async.Deferred.AlreadyCalledError.prototype.message =
    -    'Deferred has already fired';
    -
    -
    -/** @override */
    -goog.async.Deferred.AlreadyCalledError.prototype.name = 'AlreadyCalledError';
    -
    -
    -
    -/**
    - * An error sub class that is used when a Deferred is canceled.
    - *
    - * @param {!goog.async.Deferred} deferred The Deferred object.
    - * @constructor
    - * @extends {goog.debug.Error}
    - */
    -goog.async.Deferred.CanceledError = function(deferred) {
    -  goog.debug.Error.call(this);
    -
    -  /**
    -   * The Deferred that raised this error.
    -   * @type {goog.async.Deferred}
    -   */
    -  this.deferred = deferred;
    -};
    -goog.inherits(goog.async.Deferred.CanceledError, goog.debug.Error);
    -
    -
    -/** @override */
    -goog.async.Deferred.CanceledError.prototype.message = 'Deferred was canceled';
    -
    -
    -/** @override */
    -goog.async.Deferred.CanceledError.prototype.name = 'CanceledError';
    -
    -
    -
    -/**
    - * Wrapper around errors that are scheduled to be thrown by failing deferreds
    - * after a timeout.
    - *
    - * @param {*} error Error from a failing deferred.
    - * @constructor
    - * @final
    - * @private
    - * @struct
    - */
    -goog.async.Deferred.Error_ = function(error) {
    -  /** @const @private {number} */
    -  this.id_ = goog.global.setTimeout(goog.bind(this.throwError, this), 0);
    -
    -  /** @const @private {*} */
    -  this.error_ = error;
    -};
    -
    -
    -/**
    - * Actually throws the error and removes it from the list of pending
    - * deferred errors.
    - */
    -goog.async.Deferred.Error_.prototype.throwError = function() {
    -  goog.asserts.assert(goog.async.Deferred.errorMap_[this.id_],
    -      'Cannot throw an error that is not scheduled.');
    -  delete goog.async.Deferred.errorMap_[this.id_];
    -  throw this.error_;
    -};
    -
    -
    -/**
    - * Resets the error throw timer.
    - */
    -goog.async.Deferred.Error_.prototype.resetTimer = function() {
    -  goog.global.clearTimeout(this.id_);
    -};
    -
    -
    -/**
    - * Map of unhandled errors scheduled to be rethrown in a future timestep.
    - * @private {!Object<number|string, goog.async.Deferred.Error_>}
    - */
    -goog.async.Deferred.errorMap_ = {};
    -
    -
    -/**
    - * Schedules an error to be thrown after a delay.
    - * @param {*} error Error from a failing deferred.
    - * @return {number} Id of the error.
    - * @private
    - */
    -goog.async.Deferred.scheduleError_ = function(error) {
    -  var deferredError = new goog.async.Deferred.Error_(error);
    -  goog.async.Deferred.errorMap_[deferredError.id_] = deferredError;
    -  return deferredError.id_;
    -};
    -
    -
    -/**
    - * Unschedules an error from being thrown.
    - * @param {number} id Id of the deferred error to unschedule.
    - * @private
    - */
    -goog.async.Deferred.unscheduleError_ = function(id) {
    -  var error = goog.async.Deferred.errorMap_[id];
    -  if (error) {
    -    error.resetTimer();
    -    delete goog.async.Deferred.errorMap_[id];
    -  }
    -};
    -
    -
    -/**
    - * Asserts that there are no pending deferred errors. If there are any
    - * scheduled errors, one will be thrown immediately to make this function fail.
    - */
    -goog.async.Deferred.assertNoErrors = function() {
    -  var map = goog.async.Deferred.errorMap_;
    -  for (var key in map) {
    -    var error = map[key];
    -    error.resetTimer();
    -    error.throwError();
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/third_party/closure/goog/mochikit/async/deferred_async_test.html b/src/database/third_party/closure-library/third_party/closure/goog/mochikit/async/deferred_async_test.html
    deleted file mode 100644
    index a77c6d1c2aa..00000000000
    --- a/src/database/third_party/closure-library/third_party/closure/goog/mochikit/async/deferred_async_test.html
    +++ /dev/null
    @@ -1,145 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -  Copyright 2013 The Closure Library Authors. All Rights Reserved.
    --->
    -<head>
    -<title>Closure Unit Tests - goog.async.Deferred</title>
    -<script src="../../../../../closure/goog/base.js"></script>
    -<script>
    -
    -goog.require('goog.async.Deferred');
    -goog.require('goog.testing.AsyncTestCase');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.jsunit');
    -
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall();
    -var realSetTimeout = window.setTimeout;
    -var mockClock = new goog.testing.MockClock();
    -
    -function setUp() {
    -  mockClock.install();
    -  goog.async.Deferred.LONG_STACK_TRACES = true;
    -}
    -
    -function tearDown() {
    -  // Advance the mockClock to fire any unhandled exception timeouts.
    -  mockClock.tick();
    -  mockClock.uninstall();
    -}
    -
    -function testErrorStack() {
    -  if (!Error.captureStackTrace) {
    -    return;
    -  }
    -  var d;
    -  // Get the deferred from somewhere deep in the callstack.
    -  (function immediate() {
    -    (function immediate2() {
    -      d = new goog.async.Deferred();
    -      d.addCallback(function actuallyThrows() {
    -        throw new Error('Foo');
    -      });
    -    })();
    -  })();
    -  d.addCallback(function actuallyThrows() {
    -    throw new Error('Foo');
    -  });
    -  asyncTestCase.waitForAsync('Wait for timeout');
    -  realSetTimeout(function willThrow() {
    -    var error = assertThrows(function callbackCaller() {
    -      d.callback();
    -      mockClock.tick();
    -    });
    -    assertContains('Foo', error.stack);
    -    assertContains('testErrorStack', error.stack);
    -    assertContains('callbackCaller', error.stack);
    -    assertContains('willThrow', error.stack);
    -    assertContains('actuallyThrows', error.stack);
    -    assertContains('DEFERRED OPERATION', error.stack);
    -    assertContains('immediate', error.stack);
    -    assertContains('immediate2', error.stack);
    -
    -    asyncTestCase.continueTesting();
    -  }, 0);
    -}
    -
    -function testErrorStack_forErrback() {
    -  if (!Error.captureStackTrace) {
    -    return;
    -  }
    -  var d = new goog.async.Deferred();
    -  asyncTestCase.waitForAsync('Wait for timeout');
    -  realSetTimeout(function willThrow() {
    -    d.errback(new Error('Foo'));
    -    asyncTestCase.continueTesting();
    -  }, 0);
    -
    -  d.addErrback(function(error) {
    -    assertContains('Foo', error.stack);
    -    assertContains('testErrorStack_forErrback', error.stack);
    -    assertContains('willThrow', error.stack);
    -    assertContains('DEFERRED OPERATION', error.stack);
    -  });
    -}
    -
    -function testErrorStack_nested() {
    -  if (!Error.captureStackTrace) {
    -    return;
    -  }
    -  var d = new goog.async.Deferred();
    -  d.addErrback(function(error) {
    -    assertContains('Foo', error.stack);
    -    assertContains('testErrorStack_nested', error.stack);
    -    assertContains('async1', error.stack);
    -    assertContains('async2', error.stack);
    -    assertContains('immediate', error.stack);
    -    assertContains('DEFERRED OPERATION', error.stack);
    -  });
    -  asyncTestCase.waitForAsync('Wait for timeout');
    -  realSetTimeout(function async1() {
    -    var nested = new goog.async.Deferred();
    -    nested.addErrback(function nestedErrback(error) {
    -      d.errback(error);
    -      mockClock.tick();
    -    });
    -    realSetTimeout(function async2() {
    -      (function immediate() {
    -        nested.errback(new Error('Foo'));
    -        mockClock.tick();
    -      })();
    -
    -      asyncTestCase.continueTesting();
    -    });
    -  }, 0);
    -}
    -
    -function testErrorStack_doesNotTouchCustomStack() {
    -  if (!Error.captureStackTrace) {
    -    return;
    -  }
    -  var d = new goog.async.Deferred();
    -  d.addCallback(function actuallyThrows() {
    -    var e = new Error('Foo');
    -    e.stack = 'STACK';
    -    throw e;
    -  });
    -  asyncTestCase.waitForAsync('Wait for timeout');
    -  realSetTimeout(function willThrow() {
    -    var error = assertThrows(function callbackCaller() {
    -      d.callback();
    -      mockClock.tick();
    -    });
    -    assertContains('STACK', error.stack);
    -    asyncTestCase.continueTesting();
    -  }, 0);
    -}
    -
    -</script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/third_party/closure/goog/mochikit/async/deferred_test.html b/src/database/third_party/closure-library/third_party/closure/goog/mochikit/async/deferred_test.html
    deleted file mode 100644
    index 1945210c908..00000000000
    --- a/src/database/third_party/closure-library/third_party/closure/goog/mochikit/async/deferred_test.html
    +++ /dev/null
    @@ -1,1102 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -  Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -  Author: arv@google.com (Erik Arvidsson)
    --->
    -<head>
    -<title>Closure Unit Tests - goog.async.Deferred</title>
    -<script src="../../../../../closure/goog/base.js"></script>
    -<script>
    -
    -goog.require('goog.Promise');
    -goog.require('goog.Thenable');
    -goog.require('goog.array');
    -goog.require('goog.async.Deferred');
    -goog.require('goog.string');
    -goog.require('goog.testing.MockClock');
    -goog.require('goog.testing.PropertyReplacer');
    -goog.require('goog.testing.jsunit');
    -
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -var Deferred = goog.async.Deferred;
    -var AlreadyCalledError = Deferred.AlreadyCalledError;
    -var CanceledError = Deferred.CanceledError;
    -
    -// Unhandled errors may be sent to the browser on a timeout.
    -var mockClock = new goog.testing.MockClock();
    -var stubs = new goog.testing.PropertyReplacer();
    -
    -function setUp() {
    -  mockClock.install();
    -}
    -
    -function tearDown() {
    -  // Advance the mockClock to fire any unhandled exception timeouts.
    -  mockClock.tick();
    -  mockClock.uninstall();
    -  stubs.reset();
    -}
    -
    -function assertEqualsCallback(msg, expected) {
    -  return function(res) {
    -    assertEquals(msg, expected, res);
    -    // Since the assertion is an exception that will be caught inside the
    -    // Deferred object, we must advance the clock to see if it has failed.
    -    mockClock.tick();
    -    return res;
    -  };
    -}
    -
    -function increment(res) {
    -  return res + 1;
    -}
    -
    -function throwStuff(res) {
    -  throw res;
    -}
    -
    -function catchStuff(res) {
    -  return res;
    -}
    -
    -function returnError(res) {
    -  return Error(res);
    -}
    -
    -function neverHappen(res) {
    -  fail('This should not happen');
    -}
    -
    -function testNormal() {
    -  var d = new Deferred();
    -  d.addCallback(assertEqualsCallback('pre-deferred callback', 1));
    -  d.callback(1);
    -  d.addCallback(increment);
    -  d.addCallback(assertEqualsCallback('post-deferred callback', 2));
    -  d.addCallback(throwStuff);
    -  d.addCallback(neverHappen);
    -  d.addErrback(catchStuff);
    -  d.addCallback(assertEqualsCallback('throw -> err, catch -> success', 2));
    -  d.addCallback(returnError);
    -  d.addCallback(neverHappen);
    -  d.addErrback(catchStuff);
    -  d.addCallback(assertEqualsCallback('return -> err, catch -> succcess', 2));
    -}
    -
    -function testCancel() {
    -  var count = 0;
    -  function canceled(d) {
    -    count++;
    -  }
    -
    -  function canceledError(res) {
    -    assertTrue(res instanceof CanceledError);
    -  }
    -
    -  var d = new Deferred(canceled);
    -  d.addCallback(neverHappen);
    -  d.addErrback(canceledError);
    -  d.cancel();
    -
    -  assertEquals(1, count);
    -}
    -
    -function testSucceedFail() {
    -  var count = 0;
    -
    -  var d = Deferred.succeed(1).addCallback(assertEqualsCallback('succeed', 1));
    -
    -  // default error
    -  d = Deferred.fail().addCallback(neverHappen);
    -  d = d.addErrback(function(res) {
    -    count++;
    -    return res;
    -  });
    -
    -  // default wrapped error
    -  d = Deferred.fail('web taco').addCallback(neverHappen).addErrback(catchStuff);
    -  d = d.addCallback(assertEqualsCallback('wrapped fail', 'web taco'));
    -
    -  // default unwrapped error
    -  d = Deferred.fail(Error('ugh')).addCallback(neverHappen).addErrback(
    -      catchStuff);
    -  d = d.addCallback(assertEqualsCallback('unwrapped fail', 'ugh'));
    -
    -  assertEquals(1, count);
    -}
    -
    -function testDeferredDependencies() {
    -  function deferredIncrement(res) {
    -    var rval = Deferred.succeed(res);
    -    rval.addCallback(increment);
    -    return rval;
    -  }
    -
    -  var d = Deferred.succeed(1).addCallback(deferredIncrement);
    -  d = d.addCallback(assertEqualsCallback('dependent deferred succeed', 2));
    -
    -  function deferredFailure(res) {
    -    return Deferred.fail(res);
    -  }
    -
    -  d = Deferred.succeed('ugh').addCallback(deferredFailure).addErrback(
    -      catchStuff);
    -  d = d.addCallback(assertEqualsCallback('dependent deferred fail', 'ugh'));
    -}
    -
    -// Test double-calling, double-failing, etc.
    -function testDoubleCalling() {
    -  var ex = assertThrows(function() {
    -    Deferred.succeed(1).callback(2);
    -    neverHappen();
    -  });
    -  assertTrue('double call', ex instanceof AlreadyCalledError);
    -}
    -
    -function testDoubleCalling2() {
    -  var ex = assertThrows(function() {
    -    Deferred.fail(1).errback(2);
    -    neverHappen();
    -  });
    -  assertTrue('double-fail', ex instanceof AlreadyCalledError);
    -}
    -
    -function testDoubleCalling3() {
    -  var ex = assertThrows(function() {
    -    var d = Deferred.succeed(1);
    -    d.cancel();
    -    d = d.callback(2);
    -    assertTrue('swallowed one callback, no canceler', true);
    -    d.callback(3);
    -    neverHappen();
    -  });
    -  assertTrue('swallow cancel', ex instanceof AlreadyCalledError);
    -}
    -
    -function testDoubleCalling4() {
    -  var count = 0;
    -  function canceled(d) {
    -    count++;
    -  }
    -
    -  var ex = assertThrows(function() {
    -    var d = new Deferred(canceled);
    -    d.cancel();
    -    d = d.callback(1);
    -  });
    -
    -  assertTrue('non-swallowed cancel', ex instanceof AlreadyCalledError);
    -  assertEquals(1, count);
    -}
    -
    -// Test incorrect Deferred usage
    -function testIncorrectUsage() {
    -  var d = new Deferred();
    -
    -  var ex = assertThrows(function() {
    -    d.callback(new Deferred());
    -    neverHappen();
    -  });
    -  assertTrue('deferred not allowed for callback', ex instanceof Error);
    -}
    -
    -function testIncorrectUsage2() {
    -  var d = new Deferred();
    -
    -  var ex = assertThrows(function() {
    -    d.errback(new Deferred());
    -    neverHappen();
    -  });
    -  assertTrue('deferred not allowed for errback', ex instanceof Error);
    -}
    -
    -function testIncorrectUsage3() {
    -  var d = new Deferred();
    -  (new Deferred()).addCallback(function() {return d;}).callback(1);
    -
    -  var ex = assertThrows(function() {
    -    d.addCallback(function() {});
    -    neverHappen();
    -  });
    -  assertTrue('chained deferred not allowed to be re-used', ex instanceof Error);
    -}
    -
    -function testCallbackScope1() {
    -  var c1 = {}, c2 = {};
    -  var callbackScope = null;
    -  var errbackScope = null;
    -
    -  var d = new Deferred();
    -  d.addCallback(function() {
    -    callbackScope = this;
    -    throw Error('Foo');
    -  }, c1);
    -  d.addErrback(function() {
    -    errbackScope = this;
    -  }, c2);
    -  d.callback();
    -  assertEquals('Incorrect callback scope', c1, callbackScope);
    -  assertEquals('Incorrect errback scope', c2, errbackScope);
    -}
    -
    -function testCallbackScope2() {
    -  var callbackScope = null;
    -  var errbackScope = null;
    -
    -  var d = new Deferred();
    -  d.addCallback(function() {
    -    callbackScope = this;
    -    throw Error('Foo');
    -  });
    -  d.addErrback(function() {
    -    errbackScope = this;
    -  });
    -  d.callback();
    -  assertEquals('Incorrect callback scope', window, callbackScope);
    -  assertEquals('Incorrect errback scope', window, errbackScope);
    -}
    -
    -function testCallbackScope3() {
    -  var c = {};
    -  var callbackScope = null;
    -  var errbackScope = null;
    -
    -  var d = new Deferred(null, c);
    -  d.addCallback(function() {
    -    callbackScope = this;
    -    throw Error('Foo');
    -  });
    -  d.addErrback(function() {
    -    errbackScope = this;
    -  });
    -  d.callback();
    -  assertEquals('Incorrect callback scope', c, callbackScope);
    -  assertEquals('Incorrect errback scope', c, errbackScope);
    -}
    -
    -function testChainedDeferred1() {
    -  var calls = [];
    -
    -  var d2 = new Deferred();
    -  d2.addCallback(function() {calls.push('B1');});
    -  d2.addCallback(function() {calls.push('B2');});
    -
    -  var d1 = new Deferred();
    -  d1.addCallback(function() {calls.push('A1');});
    -  d1.addCallback(function() {calls.push('A2');});
    -  d1.chainDeferred(d2);
    -  d1.addCallback(function() {calls.push('A3');});
    -
    -  d1.callback();
    -  assertEquals('A1,A2,B1,B2,A3', calls.join(','));
    -}
    -
    -function testChainedDeferred2() {
    -  var calls = [];
    -
    -  var d2 = new Deferred();
    -  d2.addCallback(function() {calls.push('B1');});
    -  d2.addErrback(function(err) {calls.push('B2'); throw Error('x');});
    -
    -  var d1 = new Deferred();
    -  d1.addCallback(function(err) {throw Error('foo');});
    -  d1.chainDeferred(d2);
    -  d1.addCallback(function() {calls.push('A1');});
    -  d1.addErrback(function() {calls.push('A2');});
    -
    -  d1.callback();
    -  assertEquals('B2,A2', calls.join(','));
    -
    -  var ex = assertThrows(function() {
    -    mockClock.tick();
    -    neverHappen();
    -  });
    -  assertTrue('Should catch unhandled throw from d2.', ex.message == 'x');
    -}
    -
    -function testUndefinedResultAndCallbackSequence() {
    -  var results = [];
    -  var d = new Deferred();
    -  d.addCallback(function(res) {return 'foo';});
    -  d.addCallback(function(res) {results.push(res); return 'bar';});
    -  d.addCallback(function(res) {results.push(res);});
    -  d.addCallback(function(res) {results.push(res);});
    -  d.callback();
    -  assertEquals('foo,bar,bar', results.join(','));
    -}
    -
    -function testUndefinedResultAndErrbackSequence() {
    -  var results = [];
    -  var d = new Deferred();
    -  d.addCallback(function(res) {throw Error('uh oh');});
    -  d.addErrback(function(res) {results.push('A');});
    -  d.addCallback(function(res) {results.push('B');});
    -  d.addErrback(function(res) {results.push('C');});
    -  d.callback();
    -  assertEquals('A,C', results.join(','));
    -}
    -
    -function testHasFired() {
    -  var d1 = new Deferred();
    -  var d2 = new Deferred();
    -
    -  assertFalse(d1.hasFired());
    -  assertFalse(d2.hasFired());
    -
    -  d1.callback();
    -  d2.errback();
    -  assertTrue(d1.hasFired());
    -  assertTrue(d2.hasFired());
    -}
    -
    -function testUnhandledErrors() {
    -  var d = new Deferred();
    -  d.addCallback(throwStuff);
    -
    -  var ex = assertThrows(function() {
    -    d.callback(123);
    -    mockClock.tick();
    -    neverHappen();
    -  });
    -  assertEquals('Unhandled throws should hit the browser.', 123, ex);
    -
    -  assertNotThrows(
    -      'Errbacks added after a failure should resume.',
    -      function() {
    -        d.addErrback(catchStuff);
    -        mockClock.tick();
    -      });
    -
    -  d.addCallback(assertEqualsCallback('Should recover after throw.', 1));
    -  mockClock.tick();
    -}
    -
    -function testStrictUnhandledErrors() {
    -  stubs.replace(Deferred, 'STRICT_ERRORS', true);
    -  var err = Error('never handled');
    -
    -  // The registered errback exists, but doesn't modify the error value.
    -  var d = Deferred.succeed();
    -  d.addCallback(function(res) { throw err; });
    -  d.addErrback(function(unhandledErr) {});
    -
    -  var caught = assertThrows(
    -      'The error should be rethrown at the next clock tick.',
    -      function() { mockClock.tick(); });
    -  assertEquals(err, caught);
    -}
    -
    -function testStrictHandledErrors() {
    -  stubs.replace(Deferred, 'STRICT_ERRORS', true);
    -
    -  // The registered errback returns a non-error value.
    -  var d = Deferred.succeed();
    -  d.addCallback(function(res) { throw Error('eventually handled'); });
    -  d.addErrback(function(unhandledErr) { return true; });
    -
    -  assertNotThrows(
    -      'The error was handled and should not be rethrown',
    -      function() { mockClock.tick(); });
    -  d.addCallback(function(res) { assertTrue(res); });
    -}
    -
    -function testStrictBlockedErrors() {
    -  stubs.replace(Deferred, 'STRICT_ERRORS', true);
    -
    -  var d1 = Deferred.fail(Error('blocked failure'));
    -  var d2 = new Deferred();
    -
    -  d1.addBoth(function() { return d2; });
    -  assertNotThrows(
    -      'd1 should be blocked until d2 fires.',
    -      function() { mockClock.tick(); });
    -
    -  d2.callback('unblocked');
    -  d1.addCallback(assertEqualsCallback(
    -      'd1 should receive the fired result from d2.', 'unblocked'));
    -}
    -
    -function testStrictCanceledErrors() {
    -  stubs.replace(Deferred, 'STRICT_ERRORS', true);
    -
    -  var d = Deferred.canceled();
    -  assertNotThrows(
    -      'CanceledErrors should not be rethrown to the global scope.',
    -      function() { mockClock.tick(); });
    -}
    -
    -function testSynchronousErrorCanceling() {
    -  var d = new Deferred();
    -  d.addCallback(throwStuff);
    -
    -  assertNotThrows(
    -      'Adding an errback to the end of a failing Deferred should cancel the ' +
    -      'unhandled error timeout.',
    -      function() {
    -        d.callback(1);
    -        d.addErrback(catchStuff);
    -        mockClock.tick();
    -      });
    -
    -  d.addCallback(assertEqualsCallback('Callback should fire', 1));
    -}
    -
    -function testThrowNonError() {
    -  var results = [];
    -
    -  var d = new Deferred();
    -  d.addCallback(function(res) {
    -    throw res;
    -  });
    -  d.addErrback(function(res) {
    -    results.push(res);
    -    return 6;
    -  });
    -  d.addCallback(function(res) {
    -    results.push(res);
    -  });
    -
    -  d.callback(7);
    -  assertArrayEquals(
    -      'Errback should have been called with 7, followed by callback with 6.',
    -      [7, 6], results);
    -}
    -
    -function testThrownErrorWithNoErrbacks() {
    -  var d = new Deferred();
    -  d.addCallback(function() {
    -    throw Error('foo');
    -  });
    -  d.addCallback(goog.nullFunction);
    -
    -  function assertCallback() {
    -    d.callback(1);
    -    mockClock.tick(); // Should cause error because throwing is delayed.
    -  }
    -
    -  assertThrows('A thrown error should be rethrown if there is no ' +
    -               'errback to catch it.', assertCallback);
    -}
    -
    -function testThrownErrorCallbacksDoNotCancel() {
    -  var d = new Deferred();
    -  d.addCallback(function() {
    -    throw Error('foo');
    -  });
    -
    -  function assertCallback() {
    -    d.callback(1);
    -    // Add another callback after the fact.  Note this is not an errback!
    -    d.addCallback(neverHappen);
    -    mockClock.tick(); // Should cause error because throwing is delayed.
    -  }
    -
    -  assertThrows('A thrown error should be rethrown if there is no ' +
    -               'errback to catch it.', assertCallback);
    -}
    -
    -function testAwaitDeferred() {
    -
    -  var results = [];
    -
    -  function fn(x) {
    -    return function() {
    -      results.push(x);
    -    };
    -  }
    -
    -  var d2 = new Deferred();
    -  d2.addCallback(fn('b'));
    -
    -  // d1 -> a -> (wait for d2) -> c
    -  var d1 = new Deferred();
    -  d1.addCallback(fn('a'));
    -  d1.awaitDeferred(d2);
    -  d1.addCallback(fn('c'));
    -
    -  // calls 'a' then yields for d2.
    -  d1.callback(null);
    -
    -  // will get called after d2.
    -  d1.addCallback(fn('d'));
    -
    -  assertEquals('a', results.join(''));
    -
    -  // d3 -> w -> (wait for d2) -> x
    -  var d3 = new Deferred();
    -  d3.addCallback(fn('w'));
    -  d3.awaitDeferred(d2);
    -  d3.addCallback(fn('x'));
    -
    -  // calls 'w', then yields for d2.
    -  d3.callback();
    -
    -
    -  // will get called after d2.
    -  d3.addCallback(fn('y'));
    -
    -  assertEquals('aw', results.join(''));
    -
    -  // d1 calls 'd', d3 calls 'y'
    -  d2.callback(null);
    -
    -  assertEquals('awbcdxy', results.join(''));
    -
    -  // d3 and d2 already called, so 'z' called immediately.
    -  d3.addCallback(fn('z'));
    -
    -  assertEquals('awbcdxyz', results.join(''));
    -}
    -
    -function testAwaitDeferred_withPromise() {
    -
    -  var results = [];
    -
    -  function fn(x) {
    -    return function() {
    -      results.push(x);
    -    };
    -  }
    -
    -  var resolver = new goog.Promise.withResolver();
    -  resolver.promise.then(fn('b'));
    -
    -  // d1 -> a -> (wait for promise) -> c
    -  var d1 = new Deferred();
    -  d1.addCallback(fn('a'));
    -  d1.awaitDeferred(resolver.promise);
    -  d1.addCallback(fn('c'));
    -
    -  // calls 'a' then yields for promise.
    -  d1.callback(1);
    -
    -  // will get called after promise.
    -  d1.addCallback(fn('d'));
    -
    -  assertEquals('a', results.join(''));
    -
    -  // d3 -> w -> (wait for promise) -> x
    -  var d3 = new Deferred();
    -  d3.addCallback(fn('w'));
    -  d3.awaitDeferred(resolver.promise);
    -  d3.addCallback(fn('x'));
    -
    -  // calls 'w', then yields for promise.
    -  d3.callback(2);
    -
    -
    -  // will get called after promise.
    -  d3.addCallback(fn('y'));
    -
    -  assertEquals('aw', results.join(''));
    -
    -  // d1 calls 'd', d3 calls 'y'
    -  resolver.resolve();
    -  mockClock.tick();
    -
    -  assertEquals('awbcdxy', results.join(''));
    -
    -  // d3 and promise already called, so 'z' called immediately.
    -  d3.addCallback(fn('z'));
    -
    -  assertEquals('awbcdxyz', results.join(''));
    -}
    -
    -function testAwaitDeferredWithErrors() {
    -  var results = [];
    -
    -  function fn(x) {
    -    return function(e) {
    -      results.push(x);
    -    };
    -  }
    -
    -  var d2 = new Deferred();
    -  d2.addErrback(fn('a'));
    -
    -  var d1 = new Deferred();
    -  d1.awaitDeferred(d2);
    -  d1.addCallback(fn('x'));
    -  d1.addErrback(fn('b'));
    -  d1.callback(null);
    -
    -  assertEquals('', results.join(''));
    -
    -  d2.addCallback(fn('z'));
    -  d2.addErrback(fn('c'));
    -  d2.errback(null);
    -
    -  // First errback added to d2 prints 'a'.
    -  // Next 'd' was chained, so execute its err backs, printing 'b'.
    -  // Finally 'c' was added last by d2's errback.
    -  assertEquals('abc', results.join(''));
    -}
    -
    -function testNonErrorErrback() {
    -  var results = [];
    -
    -  function fn(x) {
    -    return function(e) {
    -      results.push(x);
    -    };
    -  }
    -
    -  var d = new Deferred();
    -  d.addCallback(fn('a'));
    -  d.addErrback(fn('b'));
    -
    -  d.addCallback(fn('c'));
    -  d.addErrback(fn('d'));
    -
    -  d.errback('foo');
    -
    -  assertEquals('bd', results.join(''));
    -}
    -
    -function testUnequalReturnValueForErrback() {
    -  var results = [];
    -
    -  function fn(x) {
    -    return function(e) {
    -      results.push(x);
    -    };
    -  }
    -
    -  var d = new Deferred();
    -  d.addCallback(fn('a'));
    -  d.addErrback(function() {
    -    results.push('b');
    -    return 'bar';
    -  });
    -
    -  d.addCallback(fn('c'));
    -  d.addErrback(fn('d'));
    -
    -  d.errback('foo');
    -
    -  assertEquals('bc', results.join(''));
    -}
    -
    -function testBranch() {
    -  function fn(x) {
    -    return function(arr) {
    -      return arr.concat(x);
    -    };
    -  }
    -
    -  var d = new Deferred();
    -  d.addCallback(fn(1));
    -  d.addCallback(fn(2));
    -  var d2 = d.branch();
    -  d.addCallback(fn(3));
    -  d2.addCallback(fn(4));
    -
    -  d.callback([]);
    -
    -  assertTrue('both deferreds should have fired', d.hasFired());
    -  assertTrue('both deferreds should have fired', d2.hasFired());
    -  d.addCallback(function(arr) { assertArrayEquals([1, 2, 3], arr); });
    -  d2.addCallback(function(arr) { assertArrayEquals([1, 2, 4], arr); });
    -}
    -
    -function testDiamondBranch() {
    -  function fn(x) {
    -    return function(arr) {
    -      return arr.concat(x);
    -    };
    -  }
    -
    -  var d = new Deferred();
    -  d.addCallback(fn(1));
    -
    -  var d2 = d.branch();
    -  d2.addCallback(fn(2));
    -
    -  // Chain the branch back to the original. There is no good reason to do this
    -  // cever.
    -  d.addCallback(function(ret) {return d2;});
    -  d.callback([]);
    -
    -  // But no reason it shouldn't work!
    -  d.addCallback(function(arr) { assertArrayEquals([1, 2], arr); });
    -}
    -
    -function testRepeatedBranch() {
    -  var d = new Deferred().addCallback(increment);
    -
    -  d.branch().
    -      addCallback(assertEqualsCallback('branch should be after increment', 2)).
    -      addCallback(function(res) {return d.branch();}).
    -      addCallback(assertEqualsCallback('second branch should be the same', 2));
    -  d.callback(1);
    -}
    -
    -function testCancelThroughBranch() {
    -  var wasCanceled = false;
    -  var d = new Deferred(function() { wasCanceled = true; });
    -  var branch1 = d.branch(true);
    -  var branch2 = d.branch(true);
    -
    -  branch1.cancel();
    -  assertFalse(wasCanceled);
    -  branch2.cancel();
    -  assertTrue(wasCanceled);
    -}
    -
    -function testCancelThroughSeveralBranches() {
    -  var wasCanceled = false;
    -  var d = new Deferred(function() { wasCanceled = true; });
    -  var branch = d.branch(true).branch(true).branch(true);
    -
    -  branch.cancel();
    -  assertTrue(wasCanceled);
    -}
    -
    -function testBranchCancelThenCallback() {
    -  var wasCanceled = false;
    -  var d = new Deferred(function() { wasCanceled = true; });
    -  var wasCalled = false;
    -  d.addCallback(function() { wasCalled = true; });
    -  var branch1 = d.branch();
    -  var branch2 = d.branch();
    -
    -  var branch1WasCalled = false;
    -  var branch2WasCalled = false;
    -  branch1.addCallback(function() { branch1WasCalled = true; });
    -  branch2.addCallback(function() { branch2WasCalled = true; });
    -
    -  var branch1HadErrback = false;
    -  var branch2HadErrback = false;
    -  branch1.addErrback(function() { branch1HadErrback = true; });
    -  branch2.addErrback(function() { branch2HadErrback = true; });
    -
    -  branch1.cancel();
    -  assertFalse(wasCanceled);
    -  assertTrue(branch1HadErrback);
    -  assertFalse(branch2HadErrback);
    -
    -  d.callback();
    -  assertTrue(wasCalled);
    -  assertFalse(branch1WasCalled);
    -  assertTrue(branch2WasCalled);
    -}
    -
    -function testDeepCancelOnBranch() {
    -  var wasCanceled = false;
    -  var d = new Deferred(function() { wasCanceled = true; });
    -  var branch1 = d.branch(true);
    -  var branch2 = d.branch(true).branch(true).branch(true);
    -
    -  var branch1HadErrback = false;
    -  var branch2HadErrback = false;
    -  branch1.addErrback(function() { branch1HadErrback = true; });
    -  branch2.addErrback(function() { branch2HadErrback = true; });
    -
    -  branch2.cancel(true /* opt_deepCancel */);
    -  assertTrue(wasCanceled);
    -  assertTrue(branch1HadErrback);
    -  assertTrue(branch2HadErrback);
    -}
    -
    -function testCancelOnRoot() {
    -  var wasCanceled = false;
    -  var d = new Deferred(function() { wasCanceled = true; });
    -  var branch = d.branch(true).branch(true).branch(true);
    -
    -  d.cancel();
    -  assertTrue(wasCanceled);
    -}
    -
    -function testCancelOnLeafBranch() {
    -  var wasCanceled = false;
    -  var branchWasCanceled = false;
    -  var d = new Deferred(function() { wasCanceled = true; });
    -  var branch = d.branch(true).branch(true).branch(true);
    -  branch.addErrback(function() { branchWasCanceled = true; });
    -
    -  branch.cancel();
    -  assertTrue(wasCanceled);
    -  assertTrue(branchWasCanceled);
    -}
    -
    -function testCancelOnIntermediateBranch() {
    -  var rootWasCanceled = false;
    -
    -  var d = new Deferred(function() { rootWasCanceled = true; });
    -  var branch = d.branch(true).branch(true).branch(true);
    -
    -  var deepBranch1 = branch.branch(true);
    -  var deepBranch2 = branch.branch(true);
    -
    -  branch.cancel();
    -  assertTrue(rootWasCanceled);
    -  assertTrue(deepBranch1.hasFired());
    -  assertTrue(deepBranch2.hasFired());
    -}
    -
    -function testCancelWithSomeCompletedBranches() {
    -  var d = new Deferred();
    -  var branch1 = d.branch(true);
    -
    -  var branch1HadCallback = false;
    -  var branch1HadErrback = false;
    -  branch1.
    -      addCallback(function() { branch1HadCallback = true; }).
    -      addErrback(function() { branch1HadErrback = true; });
    -  d.callback(true);
    -
    -  assertTrue(branch1HadCallback);
    -  assertFalse(branch1HadErrback);
    -
    -  var rootHadCallback = false;
    -  var rootHadErrback = false;
    -  // Block the root on a new Deferred indefinitely.
    -  d.
    -      addCallback(function() { rootHadCallback = true; }).
    -      addCallback(function() { return new Deferred(); }).
    -      addErrback(function() { rootHadErrback = true; });
    -  var branch2 = d.branch(true);
    -
    -  assertTrue(rootHadCallback);
    -  assertFalse(rootHadErrback);
    -
    -  branch2.cancel();
    -  assertFalse(branch1HadErrback);
    -  assertTrue('Canceling the last active branch should cancel the parent.',
    -             rootHadErrback);
    -}
    -
    -function testStaticCanceled() {
    -  var callbackCalled = false;
    -  var errbackResult = null;
    -
    -  var d = goog.async.Deferred.canceled();
    -  d.addCallback(function() { callbackCalled = true;} );
    -  d.addErrback(function(err) { errbackResult = err;} );
    -
    -  assertTrue('Errback should have been called with a canceled error',
    -      errbackResult instanceof goog.async.Deferred.CanceledError);
    -  assertFalse('Callback should not have been called', callbackCalled);
    -}
    -
    -function testWhenWithValues() {
    -  var called = false;
    -  Deferred.when(4, function(obj) {
    -    called = true;
    -    assertEquals(4, obj);
    -  });
    -  assertTrue('Fn should have been called', called);
    -}
    -
    -function testWhenWithDeferred() {
    -  var called = false;
    -
    -  var d = new Deferred();
    -  Deferred.when(d, function(obj) {
    -    called = true;
    -    assertEquals(6, obj);
    -  });
    -  assertFalse('Fn should not have been called yet', called);
    -  d.callback(6);
    -  assertTrue('Fn should have been called', called);
    -}
    -
    -function testWhenDoesntAlterOriginalChain() {
    -  var calls = 0;
    -
    -  var d1 = new Deferred();
    -  var d2 = Deferred.when(d1, function(obj) {
    -    calls++;
    -    return obj * 2;
    -  });
    -  d1.addCallback(function(obj) {
    -    assertEquals('Original chain should get original value', 5, obj);
    -    calls++;
    -  });
    -  d2.addCallback(function(obj) {
    -    assertEquals('Branched chain should get modified value', 10, obj);
    -    calls++;
    -  });
    -
    -  d1.callback(5);
    -
    -  assertEquals('There should have been 3 callbacks', 3, calls);
    -}
    -
    -function testAssertNoErrors() {
    -  var d = new Deferred();
    -  d.addCallback(function() {
    -    throw new Error('Foo');
    -  });
    -  d.callback(1);
    -
    -  var ex = assertThrows(function() {
    -    Deferred.assertNoErrors();
    -    neverHappen();
    -  });
    -  assertEquals('Expected to get thrown error', 'Foo', ex.message);
    -
    -  assertNotThrows(
    -      'Calling Deferred.assertNoErrors() a second time with only one ' +
    -          'scheduled error should pass.',
    -      function() {
    -        Deferred.assertNoErrors();
    -      });
    -}
    -
    -function testThen() {
    -  var result;
    -  var result2;
    -  var d = new Deferred();
    -  assertEquals(d.then, d['then']);
    -  d.then(function(r) {
    -    return result = r;
    -  }).then(function (r2) {
    -    result2 = r2;
    -  });
    -  d.callback('done');
    -  assertUndefined(result);
    -  mockClock.tick();
    -  assertEquals('done', result);
    -  assertEquals('done', result2);
    -}
    -
    -function testThen_reject() {
    -  var result, error, error2;
    -  var d = new Deferred();
    -  assertEquals(d.then, d['then']);
    -  d.then(function(r) {
    -    result = r;
    -  }, function(e) {
    -    error = e;
    -  });
    -  d.errback(new Error('boom'));
    -  assertUndefined(result);
    -  mockClock.tick();
    -  assertUndefined(result);
    -  assertEquals('boom', error.message);
    -}
    -
    -function testPromiseAll() {
    -  var d = new Deferred();
    -  var p = new goog.Promise(function(resolve) {
    -    resolve('promise');
    -  });
    -  goog.Promise.all([d, p]).then(function(values) {
    -    assertEquals(2, values.length);
    -    assertEquals('deferred', values[0]);
    -    assertEquals('promise', values[1]);
    -  });
    -  d.callback('deferred');
    -  mockClock.tick();
    -}
    -
    -function testPromiseBlocksDeferred() {
    -  var result;
    -  var d = new Deferred();
    -  var p = new goog.Promise(function(resolve) {
    -    resolve('promise');
    -  });
    -  d.callback();
    -  d.addCallback(function() {
    -    return p;
    -  });
    -  d.addCallback(function(r) {
    -    result = r;
    -  });
    -
    -  assertUndefined(result);
    -  mockClock.tick();
    -  assertEquals('promise', result);
    -}
    -
    -function testFromPromise() {
    -  var result;
    -  var p = new goog.Promise(function(resolve) {
    -    resolve('promise');
    -  });
    -  var d = Deferred.fromPromise(p);
    -  d.addCallback(function(value) {
    -    result = value;
    -  });
    -  assertUndefined(result);
    -  mockClock.tick();
    -  assertEquals('promise', result);
    -}
    -
    -function testPromiseBlocksDeferredAndRejects() {
    -  var result;
    -  var d = new Deferred();
    -  var p = new goog.Promise(function(resolve, reject) {
    -    reject(new Error('error'));
    -  });
    -  d.callback();
    -  d.addCallback(function(r) {
    -    return p;
    -  });
    -  d.addErrback(function(r) {
    -    result = r;
    -  });
    -
    -  assertUndefined(result);
    -  mockClock.tick();
    -  assertEquals('error', result.message);
    -}
    -
    -function testPromiseFromCanceledDeferred() {
    -  var result;
    -  var d = new Deferred();
    -  d.cancel();
    -
    -  var p = d.then(neverHappen, function(reason) {
    -    result = reason;
    -  });
    -
    -  mockClock.tick();
    -  assertTrue(result instanceof goog.Promise.CancellationError);
    -}
    -
    -function testThenableInterface() {
    -  var d = new Deferred();
    -  assertTrue(goog.Thenable.isImplementedBy(d));
    -}
    -
    -function testAddBothPropagatesToErrback() {
    -  var log = [];
    -  var deferred = new goog.async.Deferred();
    -  deferred.addBoth(goog.nullFunction);
    -  deferred.addErrback(function () {
    -    log.push('errback');
    -  });
    -  deferred.errback(new Error('my error'));
    -
    -  mockClock.tick(1);
    -  assertArrayEquals(['errback'], log);
    -}
    -
    -function testAddBothDoesNotPropagateUncaughtExceptions() {
    -  var deferred = new goog.async.Deferred();
    -  deferred.addBoth(goog.nullFunction);
    -  deferred.errback(new Error('my error'));
    -  mockClock.tick(1);
    -}
    -
    -function testAddFinally() {
    -  var deferred = new goog.async.Deferred();
    -  deferred.addFinally(goog.nullFunction);
    -  deferred.errback(new Error('my error'));
    -
    -  try {
    -    mockClock.tick(1);
    -  } catch (e) {
    -    assertEquals('my error', e.message);
    -  }
    -}
    -</script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/third_party/closure/goog/mochikit/async/deferredlist.js b/src/database/third_party/closure-library/third_party/closure/goog/mochikit/async/deferredlist.js
    deleted file mode 100644
    index 59a1587c106..00000000000
    --- a/src/database/third_party/closure-library/third_party/closure/goog/mochikit/async/deferredlist.js
    +++ /dev/null
    @@ -1,206 +0,0 @@
    -// Copyright 2005 Bob Ippolito. All Rights Reserved.
    -// Modifications Copyright 2009 The Closure Library Authors.
    -// All Rights Reserved.
    -
    -/**
    - * Portions of this code are from MochiKit, received by The Closure
    - * Library Authors under the MIT license. All other code is Copyright
    - * 2005-2009 The Closure Library Authors. All Rights Reserved.
    - */
    -
    -/**
    - * @fileoverview Class for tracking multiple asynchronous operations and
    - * handling the results. The DeferredList object here is patterned after the
    - * DeferredList object in the Twisted python networking framework.
    - *
    - * Based on the MochiKit code.
    - *
    - * See: http://twistedmatrix.com/projects/core/documentation/howto/defer.html
    - *
    - * @author brenneman@google.com (Shawn Brenneman)
    - */
    -
    -goog.provide('goog.async.DeferredList');
    -
    -goog.require('goog.async.Deferred');
    -
    -
    -
    -/**
    - * Constructs an object that waits on the results of multiple asynchronous
    - * operations and marshals the results. It is itself a <code>Deferred</code>,
    - * and may have an execution sequence of callback functions added to it. Each
    - * <code>DeferredList</code> instance is single use and may be fired only once.
    - *
    - * The default behavior of a <code>DeferredList</code> is to wait for a success
    - * or error result from every <code>Deferred</code> in its input list. Once
    - * every result is available, the <code>DeferredList</code>'s execution sequence
    - * is fired with a list of <code>[success, result]</code> array pairs, where
    - * <code>success</code> is a boolean indicating whether <code>result</code> was
    - * the product of a callback or errback. The list's completion criteria and
    - * result list may be modified by setting one or more of the boolean options
    - * documented below.
    - *
    - * <code>Deferred</code> instances passed into a <code>DeferredList</code> are
    - * independent, and may have additional callbacks and errbacks added to their
    - * execution sequences after they are passed as inputs to the list.
    - *
    - * @param {!Array<!goog.async.Deferred>} list An array of deferred results to
    - *     wait for.
    - * @param {boolean=} opt_fireOnOneCallback Whether to stop waiting as soon as
    - *     one input completes successfully. In this case, the
    - *     <code>DeferredList</code>'s callback chain will be called with a two
    - *     element array, <code>[index, result]</code>, where <code>index</code>
    - *     identifies which input <code>Deferred</code> produced the successful
    - *     <code>result</code>.
    - * @param {boolean=} opt_fireOnOneErrback Whether to stop waiting as soon as one
    - *     input reports an error. The failing result is passed to the
    - *     <code>DeferredList</code>'s errback sequence.
    - * @param {boolean=} opt_consumeErrors When true, any errors fired by a
    - *     <code>Deferred</code> in the input list will be captured and replaced
    - *     with a succeeding null result. Any callbacks added to the
    - *     <code>Deferred</code> after its use in the <code>DeferredList</code> will
    - *     receive null instead of the error.
    - * @param {Function=} opt_canceler A function that will be called if the
    - *     <code>DeferredList</code> is canceled. @see goog.async.Deferred#cancel
    - * @param {Object=} opt_defaultScope The default scope to invoke callbacks or
    - *     errbacks in.
    - * @constructor
    - * @extends {goog.async.Deferred}
    - */
    -goog.async.DeferredList = function(
    -    list, opt_fireOnOneCallback, opt_fireOnOneErrback, opt_consumeErrors,
    -    opt_canceler, opt_defaultScope) {
    -
    -  goog.async.DeferredList.base(this, 'constructor',
    -      opt_canceler, opt_defaultScope);
    -
    -  /**
    -   * The list of Deferred objects to wait for.
    -   * @const {!Array<!goog.async.Deferred>}
    -   * @private
    -   */
    -  this.list_ = list;
    -
    -  /**
    -   * The stored return values of the Deferred objects.
    -   * @const {!Array}
    -   * @private
    -   */
    -  this.deferredResults_ = [];
    -
    -  /**
    -   * Whether to fire on the first successful callback instead of waiting for
    -   * every Deferred to complete.
    -   * @const {boolean}
    -   * @private
    -   */
    -  this.fireOnOneCallback_ = !!opt_fireOnOneCallback;
    -
    -  /**
    -   * Whether to fire on the first error result received instead of waiting for
    -   * every Deferred to complete.
    -   * @const {boolean}
    -   * @private
    -   */
    -  this.fireOnOneErrback_ = !!opt_fireOnOneErrback;
    -
    -  /**
    -   * Whether to stop error propagation on the input Deferred objects. If the
    -   * DeferredList sees an error from one of the Deferred inputs, the error will
    -   * be captured, and the Deferred will be returned to success state with a null
    -   * return value.
    -   * @const {boolean}
    -   * @private
    -   */
    -  this.consumeErrors_ = !!opt_consumeErrors;
    -
    -  /**
    -   * The number of input deferred objects that have fired.
    -   * @private {number}
    -   */
    -  this.numFinished_ = 0;
    -
    -  for (var i = 0; i < list.length; i++) {
    -    var d = list[i];
    -    d.addCallbacks(goog.bind(this.handleCallback_, this, i, true),
    -                   goog.bind(this.handleCallback_, this, i, false));
    -  }
    -
    -  if (list.length == 0 && !this.fireOnOneCallback_) {
    -    this.callback(this.deferredResults_);
    -  }
    -};
    -goog.inherits(goog.async.DeferredList, goog.async.Deferred);
    -
    -
    -/**
    - * Registers the result from an input deferred callback or errback. The result
    - * is returned and may be passed to additional handlers in the callback chain.
    - *
    - * @param {number} index The index of the firing deferred object in the input
    - *     list.
    - * @param {boolean} success Whether the result is from a callback or errback.
    - * @param {*} result The result of the callback or errback.
    - * @return {*} The result, to be handled by the next handler in the deferred's
    - *     callback chain (if any). If consumeErrors is set, an error result is
    - *     replaced with null.
    - * @private
    - */
    -goog.async.DeferredList.prototype.handleCallback_ = function(
    -    index, success, result) {
    -
    -  this.numFinished_++;
    -  this.deferredResults_[index] = [success, result];
    -
    -  if (!this.hasFired()) {
    -    if (this.fireOnOneCallback_ && success) {
    -      this.callback([index, result]);
    -    } else if (this.fireOnOneErrback_ && !success) {
    -      this.errback(result);
    -    } else if (this.numFinished_ == this.list_.length) {
    -      this.callback(this.deferredResults_);
    -    }
    -  }
    -
    -  if (this.consumeErrors_ && !success) {
    -    result = null;
    -  }
    -
    -  return result;
    -};
    -
    -
    -/** @override */
    -goog.async.DeferredList.prototype.errback = function(res) {
    -  goog.async.DeferredList.base(this, 'errback', res);
    -
    -  // On error, cancel any pending requests.
    -  for (var i = 0; i < this.list_.length; i++) {
    -    this.list_[i].cancel();
    -  }
    -};
    -
    -
    -/**
    - * Creates a <code>DeferredList</code> that gathers results from multiple
    - * <code>Deferred</code> inputs. If all inputs succeed, the callback is fired
    - * with the list of results as a flat array. If any input fails, the list's
    - * errback is fired immediately with the offending error, and all other pending
    - * inputs are canceled.
    - *
    - * @param {!Array<!goog.async.Deferred>} list The list of <code>Deferred</code>
    - *     inputs to wait for.
    - * @return {!goog.async.Deferred} The deferred list of results from the inputs
    - *     if they all succeed, or the error result of the first input to fail.
    - */
    -goog.async.DeferredList.gatherResults = function(list) {
    -  return new goog.async.DeferredList(list, false, true).
    -      addCallback(function(results) {
    -        var output = [];
    -        for (var i = 0; i < results.length; i++) {
    -          output[i] = results[i][1];
    -        }
    -        return output;
    -      });
    -};
    diff --git a/src/database/third_party/closure-library/third_party/closure/goog/mochikit/async/deferredlist_test.html b/src/database/third_party/closure-library/third_party/closure/goog/mochikit/async/deferredlist_test.html
    deleted file mode 100644
    index bb8c63f485e..00000000000
    --- a/src/database/third_party/closure-library/third_party/closure/goog/mochikit/async/deferredlist_test.html
    +++ /dev/null
    @@ -1,504 +0,0 @@
    -<!DOCTYPE html>
    -<html>
    -<!--
    -  Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -  Author: brenneman@google.com (Shawn Brenneman)
    --->
    -<head>
    -<title>Closure Unit Tests - goog.async.DeferredList</title>
    -<script src="../../../../../closure/goog/base.js"></script>
    -<script>
    -goog.require('goog.array');
    -goog.require('goog.async.Deferred');
    -goog.require('goog.async.DeferredList');
    -goog.require('goog.testing.jsunit');
    -</script>
    -</head>
    -<body>
    -<script>
    -
    -var Deferred = goog.async.Deferred;
    -var DeferredList = goog.async.DeferredList;
    -
    -
    -// Re-throw (after a timeout) any errors not handled in an errback.
    -Deferred.STRICT_ERRORS = true;
    -
    -
    -/**
    - * A list of unhandled errors.
    - * @type {Array.<Error>}
    - */
    -var storedErrors = [];
    -
    -
    -/**
    - * Adds a catch-all error handler to deferred objects. Unhandled errors that
    - * reach the catch-all will be rethrown during tearDown.
    - *
    - * @param {...Deferred} var_args A list of deferred objects.
    - */
    -function addCatchAll(var_args) {
    -  for (var i = 0, d; d = arguments[i]; i++) {
    -    d.addErrback(function(res) {
    -      storedErrors.push(res);
    -    });
    -  }
    -}
    -
    -
    -/**
    - * Checks storedErrors for unhandled errors. If found, the error is rethrown.
    - */
    -function checkCatchAll() {
    -  var err = storedErrors.shift();
    -  goog.array.clear(storedErrors);
    -
    -  if (err) {
    -    throw err;
    -  }
    -}
    -
    -
    -function tearDown() {
    -  checkCatchAll();
    -}
    -
    -
    -function neverHappen(res) {
    -  fail('This should not happen');
    -}
    -
    -
    -function testNoInputs() {
    -  var count = 0;
    -  var d = new DeferredList([]);
    -
    -  d.addCallback(function(res) {
    -    assertArrayEquals([], res);
    -    count++;
    -  });
    -  addCatchAll(d);
    -
    -  assertEquals('An empty DeferredList should fire immediately with an empty ' +
    -               'list of results.',
    -               1, count);
    -}
    -
    -
    -function testNoInputsAndFireOnOneCallback() {
    -  var count = 0;
    -  var d = new DeferredList([], true);
    -
    -  d.addCallback(function(res) {
    -    assertArrayEquals([], res);
    -    count++;
    -  });
    -  addCatchAll(d);
    -
    -  assertEquals('An empty DeferredList with opt_fireOnOneCallback set should ' +
    -               'not fire unless callback is invoked explicitly.',
    -               0, count);
    -
    -  d.callback([]);
    -  assertEquals('Calling callback explicitly should still fire.', 1, count);
    -}
    -
    -
    -function testDeferredList() {
    -  var count = 0;
    -  var results;
    -
    -  var a = new Deferred();
    -  var b = new Deferred();
    -  var c = new Deferred();
    -
    -  var dl = new DeferredList([a, b, c]);
    -
    -  dl.addCallback(function(res) {
    -    assertEquals('Expected 3 Deferred results.', 3, res.length);
    -
    -    assertTrue('Deferred a should return success.', res[0][0]);
    -    assertFalse('Deferred b should return failure.', res[1][0]);
    -    assertTrue('Deferred c should return success.', res[2][0]);
    -
    -    assertEquals('Unexpected return value for a.', 'A', res[0][1]);
    -    assertEquals('Unexpected return value for c.', 'C', res[2][1]);
    -
    -    assertEquals('B', res[1][1]);
    -
    -    count++;
    -  });
    -
    -  addCatchAll(dl);
    -
    -  c.callback('C');
    -  assertEquals(0, count);
    -
    -  b.errback('B');
    -  assertEquals(0, count);
    -
    -  a.callback('A');
    -
    -  checkCatchAll();
    -  assertEquals('DeferredList should fire on last call or errback.', 1, count);
    -}
    -
    -
    -function testFireOnFirstCallback() {
    -  var a = new Deferred();
    -  var b = new Deferred();
    -  var c = new Deferred();
    -
    -  var dl = new DeferredList([a, b, c], true);
    -
    -  dl.addCallback(function(res) {
    -    assertEquals('Should be the deferred index in this mode.', 1, res[0]);
    -    assertEquals('B', res[1]);
    -  });
    -  dl.addErrback(neverHappen);
    -
    -  addCatchAll(dl);
    -
    -  a.errback('A');
    -  b.callback('B');
    -
    -  // Shouldn't cause any more callbacks on the DeferredList.
    -  c.callback('C');
    -}
    -
    -
    -function testFireOnFirstErrback() {
    -  var a = new Deferred();
    -  var b = new Deferred();
    -  var c = new Deferred();
    -
    -  var dl = new DeferredList([a, b, c], false, true);
    -
    -  dl.addCallback(neverHappen);
    -  dl.addErrback(function(res) {
    -    assertEquals('A', res);
    -
    -    // Return a non-error value to break out of the errback path.
    -    return null;
    -  });
    -  addCatchAll(dl);
    -
    -  b.callback('B');
    -  a.errback('A');
    -
    -  assertTrue(c.hasFired());
    -  c.addErrback(function(res) {
    -    assertTrue(
    -        'The DeferredList errback should have canceled all pending inputs.',
    -        res instanceof Deferred.CanceledError);
    -    return null;
    -  });
    -  addCatchAll(c);
    -
    -  // Shouldn't cause any more callbacks on the DeferredList.
    -  c.callback('C');
    -}
    -
    -
    -function testNoConsumeErrors() {
    -  var count = 0;
    -
    -  var a = new Deferred();
    -  var dl = new DeferredList([a]);
    -
    -  a.addErrback(function(res) {
    -    count++;
    -    return null;
    -  });
    -
    -  addCatchAll(a, dl);
    -
    -  a.errback('oh noes');
    -  assertEquals(1, count);
    -}
    -
    -
    -function testConsumeErrors() {
    -  var count = 0;
    -
    -  var a = new Deferred();
    -  var dl = new DeferredList([a], false, false, true);
    -
    -  a.addErrback(neverHappen);
    -
    -  addCatchAll(a, dl);
    -
    -  a.errback('oh noes');
    -  assertEquals(0, count);
    -}
    -
    -
    -function testNesting() {
    -
    -  function upperCase(res) {
    -    return res.toUpperCase();
    -  }
    -
    -  // Concatenates a list of callback or errback results into a single string.
    -  function combine(res) {
    -    return goog.array.map(res, function(result) {
    -      return result[1];
    -    }).join('');
    -  }
    -
    -  var a = new Deferred();
    -  var b = new Deferred();
    -  var c = new Deferred();
    -  var d = new Deferred();
    -
    -  a.addCallback(upperCase);
    -  b.addCallback(upperCase);
    -  c.addCallback(upperCase);
    -  d.addCallback(upperCase);
    -
    -  var dl1 = new DeferredList([a, b]);
    -  var dl2 = new DeferredList([c, d]);
    -
    -  dl1.addCallback(combine);
    -  dl2.addCallback(combine);
    -
    -  var dl3 = new DeferredList([dl1, dl2]);
    -  dl3.addCallback(combine);
    -  dl3.addCallback(function(res) {
    -    assertEquals('AbCd', res);
    -  });
    -
    -  addCatchAll(dl1, dl2, dl3);
    -
    -  a.callback('a');
    -  c.callback('c');
    -  b.errback('b');
    -  d.errback('d');
    -}
    -
    -
    -function testGatherResults() {
    -  var a = new Deferred();
    -  var b = new Deferred();
    -  var c = new Deferred();
    -
    -  var dl = DeferredList.gatherResults([a, b, c]);
    -
    -  dl.addCallback(function(res) {
    -    assertArrayEquals(['A', 'B', 'C'], res);
    -  });
    -
    -  addCatchAll(dl);
    -
    -  b.callback('B');
    -  a.callback('A');
    -  c.callback('C');
    -}
    -
    -
    -function testGatherResultsFailure() {
    -  var a = new Deferred();
    -  var b = new Deferred();
    -  var c = new Deferred();
    -
    -  var dl = DeferredList.gatherResults([a, b, c]);
    -
    -  var firedErrback = false;
    -  var firedCallback = false;
    -  dl.addCallback(function() {
    -    firedCallback = true;
    -  });
    -  dl.addErrback(function() {
    -    firedErrback = true;
    -    return null;
    -  });
    -
    -  addCatchAll(dl);
    -
    -  b.callback('B');
    -  a.callback('A');
    -  c.errback();
    -
    -  assertTrue('Errback should be called', firedErrback);
    -  assertFalse('Callback should not be called', firedCallback);
    -}
    -
    -
    -function testGatherResults_cancelCancelsChildren() {
    -  var canceled = [];
    -  var a = new Deferred(function() {
    -    canceled.push('a');
    -  });
    -  var b = new Deferred(function() {
    -    canceled.push('b');
    -  });
    -  var c = new Deferred(function() {
    -    canceled.push('c');
    -  });
    -
    -  var dl = new DeferredList([a, b, c]);
    -
    -  var firedErrback = false;
    -  var firedCallback = false;
    -  dl.addCallback(function() {
    -    firedCallback = true;
    -  });
    -  dl.addErrback(function() {
    -    firedErrback = true;
    -    return null;
    -  });
    -
    -  addCatchAll(dl);
    -
    -  b.callback('b');
    -  dl.cancel();
    -
    -  assertTrue('Errback should be called', firedErrback);
    -  assertFalse('Callback should not be called', firedCallback);
    -  assertArrayEquals(['a', 'c'], canceled);
    -}
    -
    -
    -function testErrorCancelsPendingChildrenWhenFireOnFirstError() {
    -  var canceled = [];
    -  var a = new Deferred(function() {
    -    canceled.push('a');
    -  });
    -  var b = new Deferred(function() {
    -    canceled.push('b');
    -  });
    -  var c = new Deferred(function() {
    -    canceled.push('c');
    -  });
    -
    -  var dl = new DeferredList([a, b, c], false, true);
    -
    -  var firedErrback = false;
    -  var firedCallback = false;
    -  dl.addCallback(function() {
    -    firedCallback = true;
    -  });
    -  dl.addErrback(function() {
    -    firedErrback = true;
    -    return null;
    -  });
    -
    -  addCatchAll(dl);
    -
    -  a.callback('a')
    -  b.errback();
    -
    -  assertTrue('Errback should be called', firedErrback);
    -  assertFalse('Callback should not be called', firedCallback);
    -  assertArrayEquals('Only C should be canceled since A and B fired.',
    -      ['c'], canceled);
    -}
    -
    -
    -function testErrorDoesNotCancelPendingChildrenForVanillaLists() {
    -  var canceled = [];
    -  var a = new Deferred(function() {
    -    canceled.push('a');
    -  });
    -  var b = new Deferred(function() {
    -    canceled.push('b');
    -  });
    -  var c = new Deferred(function() {
    -    canceled.push('c');
    -  });
    -
    -  var dl = new DeferredList([a, b, c]);
    -
    -  var firedErrback = false;
    -  var firedCallback = false;
    -  dl.addCallback(function() {
    -    firedCallback = true;
    -  });
    -  dl.addErrback(function() {
    -    firedErrback = true;
    -    return null;
    -  });
    -
    -  addCatchAll(dl);
    -
    -  a.callback('a')
    -  b.errback();
    -  c.callback('c')
    -
    -  assertFalse('Errback should not be called', firedErrback);
    -  assertTrue('Callback should be called', firedCallback);
    -  assertArrayEquals('No cancellations', [], canceled);
    -}
    -
    -
    -function testInputDeferredsStillUsable() {
    -  var increment = function(res) {
    -    return res + 1;
    -  };
    -  var incrementErrback = function(res) {
    -    throw res + 1;
    -  };
    -
    -  var aComplete = false;
    -  var bComplete = false;
    -  var hadListCallback = false;
    -
    -  var a = new Deferred().addCallback(increment);
    -  var b = new Deferred().addErrback(incrementErrback);
    -  var c = new Deferred();
    -
    -  var dl = new DeferredList([a, b, c]);
    -
    -  a.callback(0);
    -  a.addCallback(increment);
    -  a.addCallback(function(res) {
    -    aComplete = true;
    -    assertEquals(
    -        'The "a" Deferred should have had two increment callbacks.',
    -        2, res);
    -  });
    -  assertTrue('The "a" deferred should complete before the list.', aComplete);
    -
    -  b.errback(0);
    -  b.addErrback(incrementErrback);
    -  b.addErrback(function(res) {
    -    bComplete = true;
    -    assertEquals(
    -        'The "b" Deferred should have had two increment errbacks.',
    -        2, res);
    -  });
    -  assertTrue('The "b" deferred should complete before the list.', bComplete);
    -
    -  assertFalse('The list should not fire until every input has.', dl.hasFired());
    -  c.callback();
    -  assertTrue(dl.hasFired());
    -
    -  assertFalse(hadListCallback);
    -  dl.addCallback(function(results) {
    -    hadListCallback = true;
    -
    -    var aResult = results[0];
    -    var bResult = results[1];
    -    var cResult = results[2];
    -
    -    assertTrue(aResult[0]);
    -    assertEquals(
    -        'Should see the result from before the second callback was added.',
    -        1, aResult[1]);
    -
    -    assertFalse(bResult[0]);
    -    assertEquals(
    -        'Should see the result from before the second errback was added.',
    -        1, aResult[1]);
    -
    -    assertTrue(cResult[0]);
    -  });
    -  assertTrue(hadListCallback);
    -
    -  addCatchAll(dl);
    -}
    -
    -</script>
    -</body>
    -</html>
    diff --git a/src/database/third_party/closure-library/third_party/closure/goog/osapi/osapi.js b/src/database/third_party/closure-library/third_party/closure/goog/osapi/osapi.js
    deleted file mode 100644
    index 277a9ad62df..00000000000
    --- a/src/database/third_party/closure-library/third_party/closure/goog/osapi/osapi.js
    +++ /dev/null
    @@ -1,95 +0,0 @@
    -/**
    - * @license
    - * Licensed to the Apache Software Foundation (ASF) under one
    - * or more contributor license agreements. See the NOTICE file
    - * distributed with this work for additional information
    - * regarding copyright ownership. The ASF licenses this file
    - * to you under the Apache License, Version 2.0 (the
    - * "License"); you may not use this file except in compliance
    - * with the License. You may obtain a copy of the License at
    - * http://www.apache.org/licenses/LICENSE-2.0
    - * Unless required by applicable law or agreed to in writing,
    - * software distributed under the License is distributed on an
    - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    - * KIND, either express or implied. See the License for the
    - * specific language governing permissions and limitations under the License.
    - */
    -
    -/**
    - * @fileoverview Base OSAPI binding.
    - * This file was copied from
    - * http://svn.apache.org/repos/asf/shindig/trunk/features/src/main/javascript/features/shindig.container/osapi.js
    - * and it's slightly modified for Closure.
    - */
    -
    -goog.provide('goog.osapi');
    -
    -
    -// Expose osapi from container side.
    -var osapi = osapi || {};
    -goog.exportSymbol('osapi', osapi);
    -
    -
    -/** @type {Function} */
    -osapi.callback;
    -
    -
    -/**
    - * Dispatch a JSON-RPC batch request to services defined in the osapi namespace
    - * @param {Array<Object>} requests an array of rpc requests.
    - */
    -goog.osapi.handleGadgetRpcMethod = function(requests) {
    -  var responses = new Array(requests.length);
    -  var callCount = 0;
    -  var callback = osapi.callback;
    -  var dummy = function(params, apiCallback) {
    -    apiCallback({});
    -  };
    -  for (var i = 0; i < requests.length; i++) {
    -    // Don't allow underscores in any part of the method name as a
    -    // convention for restricted methods
    -    var current = osapi;
    -    if (requests[i]['method'].indexOf('_') == -1) {
    -      var path = requests[i]['method'].split('.');
    -      for (var j = 0; j < path.length; j++) {
    -        if (current.hasOwnProperty(path[j])) {
    -          current = current[path[j]];
    -        } else {
    -          // No matching api
    -          current = dummy;
    -          break;
    -        }
    -      }
    -    } else {
    -      current = dummy;
    -    }
    -
    -    // Execute the call and latch the rpc callback until all
    -    // complete
    -    current(requests[i]['params'], function(i) {
    -      return function(response) {
    -        // Put back in json-rpc format
    -        responses[i] = {'id': requests[i].id, 'data': response};
    -        callCount++;
    -        if (callCount == requests.length) {
    -          callback(responses);
    -        }
    -      };
    -    }(i));
    -  }
    -};
    -
    -
    -/**
    - * Initializes container side osapi binding.
    - */
    -goog.osapi.init = function() {
    -   // Container-side binding for the gadgetsrpctransport used by osapi.
    -   // Containers add services to the client-side osapi implementation by
    -   // defining them in the osapi namespace
    -  if (gadgets && gadgets.rpc) { // Only define if gadgets rpc exists.
    -    // Register the osapi RPC dispatcher.
    -    gadgets.rpc.register('osapi._handleGadgetRpcMethod',
    -        /** @type {!Function} */ (goog.osapi.handleGadgetRpcMethod));
    -  }
    -};
    diff --git a/src/database/third_party/closure-library/third_party/closure/goog/svgpan/svgpan.js b/src/database/third_party/closure-library/third_party/closure/goog/svgpan/svgpan.js
    deleted file mode 100644
    index 0a3682ffab6..00000000000
    --- a/src/database/third_party/closure-library/third_party/closure/goog/svgpan/svgpan.js
    +++ /dev/null
    @@ -1,425 +0,0 @@
    -/**
    - *  SVGPan library 1.2.2
    - * ======================
    - *
    - * Given an unique existing element with a given id (or by default, the first
    - * g-element), including the library into any SVG adds the following
    - * capabilities:
    - *
    - *  - Mouse panning
    - *  - Mouse zooming (using the wheel)
    - *  - Object dragging
    - *
    - * You can configure the behaviour of the pan/zoom/drag via setOptions().
    - *
    - * Known issues:
    - *
    - *  - Zooming (while panning) on Safari has still some issues
    - *
    - * Releases:
    - *
    - * 1.2.2, Tue Aug 30 17:21:56 CEST 2011, Andrea Leofreddi
    - *  - Fixed viewBox on root tag (#7)
    - *  - Improved zoom speed (#2)
    - *
    - * 1.2.1, Mon Jul  4 00:33:18 CEST 2011, Andrea Leofreddi
    - *  - Fixed a regression with mouse wheel (now working on Firefox 5)
    - *  - Working with viewBox attribute (#4)
    - *  - Added "use strict;" and fixed resulting warnings (#5)
    - *  - Added configuration variables, dragging is disabled by default (#3)
    - *
    - * 1.2, Sat Mar 20 08:42:50 GMT 2010, Zeng Xiaohui
    - *  Fixed a bug with browser mouse handler interaction
    - *
    - * 1.1, Wed Feb  3 17:39:33 GMT 2010, Zeng Xiaohui
    - *  Updated the zoom code to support the mouse wheel on Safari/Chrome
    - *
    - * 1.0, Andrea Leofreddi
    - *  First release
    - */
    -
    -/**
    - * @license
    - * This code is licensed under the following BSD license:
    - * Copyright 2009-2010 Andrea Leofreddi <a.leofreddi@itcharm.com>. All rights
    - * reserved.
    - *
    - * Redistribution and use in source and binary forms, with or without
    - * modification, are permitted provided that the following conditions are met:
    - *
    - *    1. Redistributions of source code must retain the above copyright notice,
    - *       this list of conditions and the following disclaimer.
    - *
    - *    2. Redistributions in binary form must reproduce the above copyright
    - *       notice, this list of conditions and the following disclaimer in the
    - *       documentation and/or other materials provided with the distribution.
    - *
    - * THIS SOFTWARE IS PROVIDED BY Andrea Leofreddi ``AS IS'' AND ANY EXPRESS OR
    - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
    - * EVENT SHALL Andrea Leofreddi OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
    - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    - *
    - * The views and conclusions contained in the software and documentation are
    - * those of the authors and should not be interpreted as representing official
    - * policies, either expressed or implied, of Andrea Leofreddi.
    - *
    - */
    -
    -goog.provide('svgpan.SvgPan');
    -
    -goog.require('goog.Disposable');
    -goog.require('goog.events');
    -goog.require('goog.events.EventType');
    -goog.require('goog.events.MouseWheelHandler');
    -
    -
    -
    -/**
    - * Instantiates an SvgPan object.
    - * @param {string=} opt_graphElementId The id of the graph element.
    - * @param {Element=} opt_root An optional document root.
    - * @constructor
    - * @extends {goog.Disposable}
    - */
    -svgpan.SvgPan = function(opt_graphElementId, opt_root) {
    -  svgpan.SvgPan.base(this, 'constructor');
    -
    -  /** @private {Element} */
    -  this.root_ = opt_root || document.documentElement;
    -
    -  /** @private {?string} */
    -  this.graphElementId_ = opt_graphElementId || null;
    -
    -  /** @private {boolean} */
    -  this.cancelNextClick_ = false;
    -
    -  /** @private {boolean} */
    -  this.enablePan_ = true;
    -
    -  /** @private {boolean} */
    -  this.enableZoom_ = true;
    -
    -  /** @private {boolean} */
    -  this.enableDrag_ = false;
    -
    -  /** @private {number} */
    -  this.zoomScale_ = 0.4;
    -
    -  /** @private {svgpan.SvgPan.State} */
    -  this.state_ = svgpan.SvgPan.State.NONE;
    -
    -  /** @private {Element} */
    -  this.svgRoot_ = null;
    -
    -  /** @private {Element} */
    -  this.stateTarget_ = null;
    -
    -  /** @private {SVGPoint} */
    -  this.stateOrigin_ = null;
    -
    -  /** @private {SVGMatrix} */
    -  this.stateTf_ = null;
    -
    -  /** @private {goog.events.MouseWheelHandler} */
    -  this.mouseWheelHandler_ = null;
    -
    -  this.setupHandlers_();
    -};
    -goog.inherits(svgpan.SvgPan, goog.Disposable);
    -
    -
    -/** @override */
    -svgpan.SvgPan.prototype.disposeInternal = function() {
    -  svgpan.SvgPan.base(this, 'disposeInternal');
    -  goog.events.removeAll(this.root_);
    -  this.mouseWheelHandler_.dispose();
    -};
    -
    -
    -/**
    - * @enum {string}
    - */
    -svgpan.SvgPan.State = {
    -  NONE: 'none',
    -  PAN: 'pan',
    -  DRAG: 'drag'
    -};
    -
    -
    -/**
    - * Enables/disables panning the entire SVG (default = true).
    - * @param {boolean} enabled Whether or not to allow panning.
    - */
    -svgpan.SvgPan.prototype.setPanEnabled = function(enabled) {
    -  this.enablePan_ = enabled;
    -};
    -
    -
    -/**
    - * Enables/disables zooming (default = true).
    - * @param {boolean} enabled Whether or not to allow zooming (default = true).
    - */
    -svgpan.SvgPan.prototype.setZoomEnabled = function(enabled) {
    -  this.enableZoom_ = enabled;
    -};
    -
    -
    -/**
    - * Enables/disables dragging individual SVG objects (default = false).
    - * @param {boolean} enabled Whether or not to allow dragging of objects.
    - */
    -svgpan.SvgPan.prototype.setDragEnabled = function(enabled) {
    -  this.enableDrag_ = enabled;
    -};
    -
    -
    -/**
    - * Sets the sensitivity of mousewheel zooming (default = 0.4).
    - * @param {number} scale The new zoom scale.
    - */
    -svgpan.SvgPan.prototype.setZoomScale = function(scale) {
    -  this.zoomScale_ = scale;
    -};
    -
    -
    -/**
    - * Registers mouse event handlers.
    - * @private
    - */
    -svgpan.SvgPan.prototype.setupHandlers_ = function() {
    -  goog.events.listen(this.root_, goog.events.EventType.CLICK,
    -      goog.bind(this.handleMouseClick_, this));
    -  goog.events.listen(this.root_, goog.events.EventType.MOUSEUP,
    -      goog.bind(this.handleMouseUp_, this));
    -  goog.events.listen(this.root_, goog.events.EventType.MOUSEDOWN,
    -      goog.bind(this.handleMouseDown_, this));
    -  goog.events.listen(this.root_, goog.events.EventType.MOUSEMOVE,
    -      goog.bind(this.handleMouseMove_, this));
    -  this.mouseWheelHandler_ = new goog.events.MouseWheelHandler(this.root_);
    -  goog.events.listen(this.mouseWheelHandler_,
    -      goog.events.MouseWheelHandler.EventType.MOUSEWHEEL,
    -      goog.bind(this.handleMouseWheel_, this));
    -};
    -
    -
    -/**
    - * Retrieves the root element for SVG manipulation. The element is then cached.
    - * @param {Document} svgDoc The document.
    - * @return {Element} The svg root.
    - * @private
    - */
    -svgpan.SvgPan.prototype.getRoot_ = function(svgDoc) {
    -  if (!this.svgRoot_) {
    -    var r = this.graphElementId_ ?
    -        svgDoc.getElementById(this.graphElementId_) : svgDoc.documentElement;
    -    var t = r;
    -    while (t != svgDoc) {
    -      if (t.getAttribute('viewBox')) {
    -        this.setCtm_(r, r.getCTM());
    -        t.removeAttribute('viewBox');
    -      }
    -      t = t.parentNode;
    -    }
    -    this.svgRoot_ = r;
    -  }
    -  return this.svgRoot_;
    -};
    -
    -
    -/**
    - * Instantiates an SVGPoint object with given event coordinates.
    - * @param {!goog.events.Event} evt The event with coordinates.
    - * @return {SVGPoint} The created point.
    - * @private
    - */
    -svgpan.SvgPan.prototype.getEventPoint_ = function(evt) {
    -  return this.newPoint_(evt.clientX, evt.clientY);
    -};
    -
    -
    -/**
    - * Instantiates an SVGPoint object with given coordinates.
    - * @param {number} x The x coordinate.
    - * @param {number} y The y coordinate.
    - * @return {SVGPoint} The created point.
    - * @private
    - */
    -svgpan.SvgPan.prototype.newPoint_ = function(x, y) {
    -  var p = this.root_.createSVGPoint();
    -  p.x = x;
    -  p.y = y;
    -  return p;
    -};
    -
    -
    -/**
    - * Sets the current transform matrix of an element.
    - * @param {Element} element The element.
    - * @param {SVGMatrix} matrix The transform matrix.
    - * @private
    - */
    -svgpan.SvgPan.prototype.setCtm_ = function(element, matrix) {
    -  var s = 'matrix(' + matrix.a + ',' + matrix.b + ',' + matrix.c + ',' +
    -      matrix.d + ',' + matrix.e + ',' + matrix.f + ')';
    -  element.setAttribute('transform', s);
    -};
    -
    -
    -/**
    - * Handle mouse wheel event.
    - * @param {!goog.events.Event} evt The event.
    - * @private
    - */
    -svgpan.SvgPan.prototype.handleMouseWheel_ = function(evt) {
    -  if (!this.enableZoom_)
    -    return;
    -
    -  // Prevents scrolling.
    -  evt.preventDefault();
    -
    -  var svgDoc = evt.target.ownerDocument;
    -
    -  var delta = evt.deltaY / -9;
    -  var z = Math.pow(1 + this.zoomScale_, delta);
    -  var g = this.getRoot_(svgDoc);
    -  var p = this.getEventPoint_(evt);
    -  p = p.matrixTransform(g.getCTM().inverse());
    -
    -  // Compute new scale matrix in current mouse position
    -  var k = this.root_.createSVGMatrix().translate(
    -      p.x, p.y).scale(z).translate(-p.x, -p.y);
    -  this.setCtm_(g, g.getCTM().multiply(k));
    -
    -  if (typeof(this.stateTf_) == 'undefined') {
    -    this.stateTf_ = g.getCTM().inverse();
    -  }
    -  this.stateTf_ =
    -      this.stateTf_ ? this.stateTf_.multiply(k.inverse()) : this.stateTf_;
    -};
    -
    -
    -/**
    - * Handle mouse move event.
    - * @param {!goog.events.Event} evt The event.
    - * @private
    - */
    -svgpan.SvgPan.prototype.handleMouseMove_ = function(evt) {
    -  if (evt.button != 0) {
    -    return;
    -  }
    -  this.handleMove(evt.clientX, evt.clientY, evt.target.ownerDocument);
    -};
    -
    -
    -/**
    - * Handles mouse motion for the given coordinates.
    - * @param {number} x The x coordinate.
    - * @param {number} y The y coordinate.
    - * @param {Document} svgDoc The svg document.
    - */
    -svgpan.SvgPan.prototype.handleMove = function(x, y, svgDoc) {
    -  var g = this.getRoot_(svgDoc);
    -  if (this.state_ == svgpan.SvgPan.State.PAN && this.enablePan_) {
    -    // Pan mode
    -    var p = this.newPoint_(x, y).matrixTransform(
    -        /** @type {!SVGMatrix} */ (this.stateTf_));
    -    this.setCtm_(g, this.stateTf_.inverse().translate(
    -        p.x - this.stateOrigin_.x, p.y - this.stateOrigin_.y));
    -    this.cancelNextClick_ = true;
    -  } else if (this.state_ == svgpan.SvgPan.State.DRAG && this.enableDrag_) {
    -    // Drag mode
    -    var p = this.newPoint_(x, y).matrixTransform(g.getCTM().inverse());
    -    this.setCtm_(this.stateTarget_, this.root_.createSVGMatrix().translate(
    -        p.x - this.stateOrigin_.x, p.y - this.stateOrigin_.y).multiply(
    -        g.getCTM().inverse()).multiply(this.stateTarget_.getCTM()));
    -    this.stateOrigin_ = p;
    -  }
    -};
    -
    -
    -/**
    - * Handle click event.
    - * @param {!goog.events.Event} evt The event.
    - * @private
    - */
    -svgpan.SvgPan.prototype.handleMouseDown_ = function(evt) {
    -  if (evt.button != 0) {
    -    return;
    -  }
    -  // Prevent selection while dragging.
    -  evt.preventDefault();
    -  var svgDoc = evt.target.ownerDocument;
    -
    -  var g = this.getRoot_(svgDoc);
    -
    -  if (evt.target.tagName == 'svg' || !this.enableDrag_) {
    -    // Pan mode
    -    this.state_ = svgpan.SvgPan.State.PAN;
    -    this.stateTf_ = g.getCTM().inverse();
    -    this.stateOrigin_ = this.getEventPoint_(evt).matrixTransform(this.stateTf_);
    -  } else {
    -    // Drag mode
    -    this.state_ = svgpan.SvgPan.State.DRAG;
    -    this.stateTarget_ = /** @type {Element} */ (evt.target);
    -    this.stateTf_ = g.getCTM().inverse();
    -    this.stateOrigin_ = this.getEventPoint_(evt).matrixTransform(this.stateTf_);
    -  }
    -};
    -
    -
    -/**
    - * Handle mouse button release event.
    - * @param {!goog.events.Event} evt The event.
    - * @private
    - */
    -svgpan.SvgPan.prototype.handleMouseUp_ = function(evt) {
    -  if (this.state_ != svgpan.SvgPan.State.NONE) {
    -    this.endPanOrDrag();
    -  }
    -};
    -
    -
    -/**
    - * Ends pan/drag mode.
    - */
    -svgpan.SvgPan.prototype.endPanOrDrag = function() {
    -  if (this.state_ != svgpan.SvgPan.State.NONE) {
    -    this.state_ = svgpan.SvgPan.State.NONE;
    -  }
    -};
    -
    -
    -/**
    - * Handle mouse clicks.
    - * @param {!goog.events.Event} evt The event.
    - * @private
    - */
    -svgpan.SvgPan.prototype.handleMouseClick_ = function(evt) {
    -  // We only set cancelNextClick_ after panning occurred, and use it to prevent
    -  // the default action that would otherwise take place when clicking on the
    -  // element (for instance, navigation on clickable links, but also any click
    -  // handler that may be set on an SVG element, in the case of active SVG
    -  // content)
    -  if (this.cancelNextClick_) {
    -    // Cancel potential click handler on active SVG content.
    -    evt.stopPropagation();
    -    // Cancel navigation when panning on clickable links.
    -    evt.preventDefault();
    -  }
    -  this.cancelNextClick_ = false;
    -};
    -
    -
    -/**
    - * Returns the current state.
    - * @return {!svgpan.SvgPan.State}
    - */
    -svgpan.SvgPan.prototype.getState = function() {
    -  return this.state_;
    -};
    diff --git a/src/firebase-browser.ts b/src/firebase-browser.ts
    new file mode 100644
    index 00000000000..ae744edee2b
    --- /dev/null
    +++ b/src/firebase-browser.ts
    @@ -0,0 +1,24 @@
    +/**
    +* Copyright 2017 Google Inc.
    +*
    +* Licensed under the Apache License, Version 2.0 (the "License");
    +* you may not use this file except in compliance with the License.
    +* You may obtain a copy of the License at
    +*
    +*   http://www.apache.org/licenses/LICENSE-2.0
    +*
    +* Unless required by applicable law or agreed to in writing, software
    +* distributed under the License is distributed on an "AS IS" BASIS,
    +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +* See the License for the specific language governing permissions and
    +* limitations under the License.
    +*/
    +
    +import firebase from "./app";
    +import './auth';
    +import './database';
    +import './storage';
    +import './messaging';
    +
    +// Export the single instance of firebase
    +export default firebase;
    diff --git a/src/firebase-node.ts b/src/firebase-node.ts
    new file mode 100644
    index 00000000000..c7150a533a0
    --- /dev/null
    +++ b/src/firebase-node.ts
    @@ -0,0 +1,37 @@
    +/**
    +* Copyright 2017 Google Inc.
    +*
    +* Licensed under the Apache License, Version 2.0 (the "License");
    +* you may not use this file except in compliance with the License.
    +* You may obtain a copy of the License at
    +*
    +*   http://www.apache.org/licenses/LICENSE-2.0
    +*
    +* Unless required by applicable law or agreed to in writing, software
    +* distributed under the License is distributed on an "AS IS" BASIS,
    +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +* See the License for the specific language governing permissions and
    +* limitations under the License.
    +*/
    +
    +import firebase from "./app";
    +import './auth';
    +import './database';
    +import './utils/nodePatches';
    +
    +
    +var Storage = require('dom-storage');
    +var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
    +
    +firebase.INTERNAL.extendNamespace({
    +  'INTERNAL': {
    +    'node': {
    +      'localStorage': new Storage(null, { strict: true }),
    +      'sessionStorage': new Storage(null, { strict: true }),
    +      'XMLHttpRequest': XMLHttpRequest
    +    }
    +  }
    +});
    +
    +// Export the single instance of firebase
    +export default firebase;
    diff --git a/src/firebase-react-native.ts b/src/firebase-react-native.ts
    new file mode 100644
    index 00000000000..0e3092ee86a
    --- /dev/null
    +++ b/src/firebase-react-native.ts
    @@ -0,0 +1,32 @@
    +/**
    +* Copyright 2017 Google Inc.
    +*
    +* Licensed under the Apache License, Version 2.0 (the "License");
    +* you may not use this file except in compliance with the License.
    +* You may obtain a copy of the License at
    +*
    +*   http://www.apache.org/licenses/LICENSE-2.0
    +*
    +* Unless required by applicable law or agreed to in writing, software
    +* distributed under the License is distributed on an "AS IS" BASIS,
    +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +* See the License for the specific language governing permissions and
    +* limitations under the License.
    +*/
    +
    +import firebase from "./app";
    +import './auth';
    +import './database';
    +import './storage';
    +
    +var AsyncStorage = require('react-native').AsyncStorage;
    +firebase.INTERNAL.extendNamespace({
    +  'INTERNAL': {
    +    'reactNative': {
    +      'AsyncStorage': AsyncStorage
    +    }
    +  }
    +});
    +
    +// Export the single instance of firebase
    +export default firebase;
    diff --git a/src/firebase.ts b/src/firebase.ts
    deleted file mode 100644
    index ca7d396b6b5..00000000000
    --- a/src/firebase.ts
    +++ /dev/null
    @@ -1,64 +0,0 @@
    -/**
    -* Copyright 2017 Google Inc.
    -*
    -* Licensed under the Apache License, Version 2.0 (the "License");
    -* you may not use this file except in compliance with the License.
    -* You may obtain a copy of the License at
    -*
    -*   http://www.apache.org/licenses/LICENSE-2.0
    -*
    -* Unless required by applicable law or agreed to in writing, software
    -* distributed under the License is distributed on an "AS IS" BASIS,
    -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -* See the License for the specific language governing permissions and
    -* limitations under the License.
    -*/
    -// Declare build time variable
    -declare const TARGET_ENVIRONMENT;
    -
    -import firebase from "./app";
    -import './auth';
    -// Import instance of FirebaseApp from ./app
    -
    -if (TARGET_ENVIRONMENT === 'node') {
    -  // TARGET_ENVIRONMENT is a build-time variable that is injected to create
    -  // all of the variable environment outputs
    -  require('./database-node');
    -
    -  var Storage = require('dom-storage');
    -  var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
    -
    -  firebase.INTERNAL.extendNamespace({
    -    'INTERNAL': {
    -      'node': {
    -        'localStorage': new Storage(null, { strict: true }),
    -        'sessionStorage': new Storage(null, { strict: true }),
    -        'XMLHttpRequest': XMLHttpRequest
    -      }
    -    }
    -  });
    -}
    -
    -if (TARGET_ENVIRONMENT !== 'node') {
    -  require('./database');
    -  require('./storage');
    -}
    -
    -if (TARGET_ENVIRONMENT === 'react-native') {
    -  var AsyncStorage = require('react-native').AsyncStorage;
    -  firebase.INTERNAL.extendNamespace({
    -    'INTERNAL': {
    -      'reactNative': {
    -        'AsyncStorage': AsyncStorage
    -      }
    -    }
    -  });
    -}
    -
    -
    -if (TARGET_ENVIRONMENT !== 'node' && TARGET_ENVIRONMENT !== 'react-native') {
    -  require('./messaging');
    -}
    -
    -// Export the single instance of firebase
    -export default firebase;
    diff --git a/src/storage/implementation/promise_external.ts b/src/storage/implementation/promise_external.ts
    index f83d96c9743..6acaf0a5354 100644
    --- a/src/storage/implementation/promise_external.ts
    +++ b/src/storage/implementation/promise_external.ts
    @@ -25,20 +25,20 @@
      *                  (function(!Error): void))} resolver
      */
     
    -import { local } from "../../app/shared_promise";
    +import { PromiseImpl } from "../../utils/promise";
     
     export function make<T>(resolver: (p1: (p1: T) => void, 
                             p2: (p1: Error) => void) => void): Promise<T> {
    -  return new local.Promise(resolver);
    +  return new PromiseImpl(resolver);
     }
     
     /**
      * @template T
      */
     export function resolve<T>(value: T): Promise<T> {
    -  return (local.Promise.resolve(value) as Promise<T>);
    +  return (PromiseImpl.resolve(value) as Promise<T>);
     }
     
     export function reject<T>(error: Error): Promise<T> {
    -  return (local.Promise.reject(error) as Promise<T>);
    +  return (PromiseImpl.reject(error) as Promise<T>);
     }
    diff --git a/src/utils/Sha1.ts b/src/utils/Sha1.ts
    new file mode 100644
    index 00000000000..969db1ed161
    --- /dev/null
    +++ b/src/utils/Sha1.ts
    @@ -0,0 +1,272 @@
    +import { Hash } from './hash';
    +
    +/**
    + * @fileoverview SHA-1 cryptographic hash.
    + * Variable names follow the notation in FIPS PUB 180-3:
    + * http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf.
    + *
    + * Usage:
    + *   var sha1 = new sha1();
    + *   sha1.update(bytes);
    + *   var hash = sha1.digest();
    + *
    + * Performance:
    + *   Chrome 23:   ~400 Mbit/s
    + *   Firefox 16:  ~250 Mbit/s
    + *
    + */
    + 
    +/**
    + * SHA-1 cryptographic hash constructor.
    + *
    + * The properties declared here are discussed in the above algorithm document.
    + * @constructor
    + * @extends {Hash}
    + * @final
    + * @struct
    + */
    +export class Sha1 extends Hash {
    +  /**
    +   * Holds the previous values of accumulated variables a-e in the compress_
    +   * function.
    +   * @type {!Array<number>}
    +   * @private
    +   */
    +  private chain_: Array<number> = [];
    +  
    +  /**
    +   * A buffer holding the partially computed hash result.
    +   * @type {!Array<number>}
    +   * @private
    +   */
    +  private buf_: Array<number> = [];
    +
    +  /**
    +   * An array of 80 bytes, each a part of the message to be hashed.  Referred to
    +   * as the message schedule in the docs.
    +   * @type {!Array<number>}
    +   * @private
    +   */
    +  private W_: Array<number> = [];
    +
    +  /**
    +   * Contains data needed to pad messages less than 64 bytes.
    +   * @type {!Array<number>}
    +   * @private
    +   */
    +  private pad_: Array<number> = [];
    +
    +  /**
    +   * @private {number}
    +   */
    +  private inbuf_: number = 0;
    +
    +  /**
    +   * @private {number}
    +   */
    +  private total_: number = 0;
    +
    +  constructor() {
    +    super();
    +  
    +    this.blockSize = 512 / 8;
    +  
    +    this.pad_[0] = 128;
    +    for (var i = 1; i < this.blockSize; ++i) {
    +      this.pad_[i] = 0;
    +    }
    +  
    +    this.reset();
    +  }
    +  
    +  reset() {
    +    this.chain_[0] = 0x67452301;
    +    this.chain_[1] = 0xefcdab89;
    +    this.chain_[2] = 0x98badcfe;
    +    this.chain_[3] = 0x10325476;
    +    this.chain_[4] = 0xc3d2e1f0;
    +  
    +    this.inbuf_ = 0;
    +    this.total_ = 0;
    +  }
    +  
    +  
    +  /**
    +   * Internal compress helper function.
    +   * @param {!Array<number>|!Uint8Array|string} buf Block to compress.
    +   * @param {number=} opt_offset Offset of the block in the buffer.
    +   * @private
    +   */
    +  compress_(buf, opt_offset?) {
    +    if (!opt_offset) {
    +      opt_offset = 0;
    +    }
    +  
    +    var W = this.W_;
    +  
    +    // get 16 big endian words
    +    if (typeof buf === 'string') {
    +      for (var i = 0; i < 16; i++) {
    +        // TODO(user): [bug 8140122] Recent versions of Safari for Mac OS and iOS
    +        // have a bug that turns the post-increment ++ operator into pre-increment
    +        // during JIT compilation.  We have code that depends heavily on SHA-1 for
    +        // correctness and which is affected by this bug, so I've removed all uses
    +        // of post-increment ++ in which the result value is used.  We can revert
    +        // this change once the Safari bug
    +        // (https://bugs.webkit.org/show_bug.cgi?id=109036) has been fixed and
    +        // most clients have been updated.
    +        W[i] = (buf.charCodeAt(opt_offset) << 24) |
    +              (buf.charCodeAt(opt_offset + 1) << 16) |
    +              (buf.charCodeAt(opt_offset + 2) << 8) |
    +              (buf.charCodeAt(opt_offset + 3));
    +        opt_offset += 4;
    +      }
    +    } else {
    +      for (var i = 0; i < 16; i++) {
    +        W[i] = (buf[opt_offset] << 24) |
    +              (buf[opt_offset + 1] << 16) |
    +              (buf[opt_offset + 2] << 8) |
    +              (buf[opt_offset + 3]);
    +        opt_offset += 4;
    +      }
    +    }
    +  
    +    // expand to 80 words
    +    for (var i = 16; i < 80; i++) {
    +      var t = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];
    +      W[i] = ((t << 1) | (t >>> 31)) & 0xffffffff;
    +    }
    +  
    +    var a = this.chain_[0];
    +    var b = this.chain_[1];
    +    var c = this.chain_[2];
    +    var d = this.chain_[3];
    +    var e = this.chain_[4];
    +    var f, k;
    +  
    +    // TODO(user): Try to unroll this loop to speed up the computation.
    +    for (var i = 0; i < 80; i++) {
    +      if (i < 40) {
    +        if (i < 20) {
    +          f = d ^ (b & (c ^ d));
    +          k = 0x5a827999;
    +        } else {
    +          f = b ^ c ^ d;
    +          k = 0x6ed9eba1;
    +        }
    +      } else {
    +        if (i < 60) {
    +          f = (b & c) | (d & (b | c));
    +          k = 0x8f1bbcdc;
    +        } else {
    +          f = b ^ c ^ d;
    +          k = 0xca62c1d6;
    +        }
    +      }
    +  
    +      var t = (((a << 5) | (a >>> 27)) + f + e + k + W[i]) & 0xffffffff;
    +      e = d;
    +      d = c;
    +      c = ((b << 30) | (b >>> 2)) & 0xffffffff;
    +      b = a;
    +      a = t;
    +    }
    +  
    +    this.chain_[0] = (this.chain_[0] + a) & 0xffffffff;
    +    this.chain_[1] = (this.chain_[1] + b) & 0xffffffff;
    +    this.chain_[2] = (this.chain_[2] + c) & 0xffffffff;
    +    this.chain_[3] = (this.chain_[3] + d) & 0xffffffff;
    +    this.chain_[4] = (this.chain_[4] + e) & 0xffffffff;
    +  }
    +  
    +  update(bytes, opt_length?) {
    +    // TODO(johnlenz): tighten the function signature and remove this check
    +    if (bytes == null) {
    +      return;
    +    }
    +  
    +    if (opt_length === undefined) {
    +      opt_length = bytes.length;
    +    }
    +  
    +    var lengthMinusBlock = opt_length - this.blockSize;
    +    var n = 0;
    +    // Using local instead of member variables gives ~5% speedup on Firefox 16.
    +    var buf = this.buf_;
    +    var inbuf = this.inbuf_;
    +  
    +    // The outer while loop should execute at most twice.
    +    while (n < opt_length) {
    +      // When we have no data in the block to top up, we can directly process the
    +      // input buffer (assuming it contains sufficient data). This gives ~25%
    +      // speedup on Chrome 23 and ~15% speedup on Firefox 16, but requires that
    +      // the data is provided in large chunks (or in multiples of 64 bytes).
    +      if (inbuf == 0) {
    +        while (n <= lengthMinusBlock) {
    +          this.compress_(bytes, n);
    +          n += this.blockSize;
    +        }
    +      }
    +  
    +      if (typeof bytes === 'string') {
    +        while (n < opt_length) {
    +          buf[inbuf] = bytes.charCodeAt(n);
    +          ++inbuf;
    +          ++n;
    +          if (inbuf == this.blockSize) {
    +            this.compress_(buf);
    +            inbuf = 0;
    +            // Jump to the outer loop so we use the full-block optimization.
    +            break;
    +          }
    +        }
    +      } else {
    +        while (n < opt_length) {
    +          buf[inbuf] = bytes[n];
    +          ++inbuf;
    +          ++n;
    +          if (inbuf == this.blockSize) {
    +            this.compress_(buf);
    +            inbuf = 0;
    +            // Jump to the outer loop so we use the full-block optimization.
    +            break;
    +          }
    +        }
    +      }
    +    }
    +  
    +    this.inbuf_ = inbuf;
    +    this.total_ += opt_length;
    +  }
    +  
    +  
    +  /** @override */
    +  digest() {
    +    var digest = [];
    +    var totalBits = this.total_ * 8;
    +  
    +    // Add pad 0x80 0x00*.
    +    if (this.inbuf_ < 56) {
    +      this.update(this.pad_, 56 - this.inbuf_);
    +    } else {
    +      this.update(this.pad_, this.blockSize - (this.inbuf_ - 56));
    +    }
    +  
    +    // Add # bits.
    +    for (var i = this.blockSize - 1; i >= 56; i--) {
    +      this.buf_[i] = totalBits & 255;
    +      totalBits /= 256; // Don't use bit-shifting here!
    +    }
    +  
    +    this.compress_(this.buf_);
    +  
    +    var n = 0;
    +    for (var i = 0; i < 5; i++) {
    +      for (var j = 24; j >= 0; j -= 8) {
    +        digest[n] = (this.chain_[i] >> j) & 255;
    +        ++n;
    +      }
    +    }
    +    return digest;
    +  }
    +}
    \ No newline at end of file
    diff --git a/src/utils/assert.ts b/src/utils/assert.ts
    new file mode 100644
    index 00000000000..367179993a9
    --- /dev/null
    +++ b/src/utils/assert.ts
    @@ -0,0 +1,21 @@
    +import { CONSTANTS } from "./constants";
    +
    +/**
    + * Throws an error if the provided assertion is falsy
    + * @param {*} assertion The assertion to be tested for falsiness
    + * @param {!string} message The message to display if the check fails
    + */
    +export const assert = function(assertion, message) {
    +  if (!assertion) {
    +    throw assertionError(message);
    +  }
    +};
    +
    +/**
    + * Returns an Error object suitable for throwing.
    + * @param {string} message
    + * @return {!Error}
    + */
    +export const assertionError = function(message) {
    +  return new Error('Firebase Database (' + CONSTANTS.SDK_VERSION + ') INTERNAL ASSERT FAILED: ' + message);
    +};
    diff --git a/src/utils/constants.ts b/src/utils/constants.ts
    new file mode 100644
    index 00000000000..00501d44760
    --- /dev/null
    +++ b/src/utils/constants.ts
    @@ -0,0 +1,19 @@
    +/**
    + * @fileoverview Firebase constants.  Some of these (@defines) can be overridden at compile-time.
    + */
    +
    +export const CONSTANTS = {
    +  /**
    +   * @define {boolean} Whether this is the client Node.js SDK.
    +   */
    +  NODE_CLIENT: false,
    +  /**
    +   * @define {boolean} Whether this is the Admin Node.js SDK.
    +   */
    +  NODE_ADMIN: false,
    +
    +  /**
    +   * Firebase SDK Version
    +   */
    +  SDK_VERSION: '${JSCORE_VERSION}'
    +}
    \ No newline at end of file
    diff --git a/src/utils/crypt.ts b/src/utils/crypt.ts
    new file mode 100644
    index 00000000000..7ec1148d074
    --- /dev/null
    +++ b/src/utils/crypt.ts
    @@ -0,0 +1,298 @@
    +import { globalScope } from './globalScope';
    +
    +const stringToByteArray = function(str) {
    +  var output = [], p = 0;
    +  for (var i = 0;i < str.length;i++) {
    +    var c = str.charCodeAt(i);
    +    while (c > 255) {
    +      output[p++] = c & 255;
    +      c >>= 8;
    +    }
    +    output[p++] = c;
    +  }
    +  return output;
    +};
    +
    +/**
    + * Turns an array of numbers into the string given by the concatenation of the
    + * characters to which the numbers correspond.
    + * @param {Array<number>} bytes Array of numbers representing characters.
    + * @return {string} Stringification of the array.
    + */
    +const byteArrayToString = function(bytes) {
    +  var CHUNK_SIZE = 8192;
    +
    +  // Special-case the simple case for speed's sake.
    +  if (bytes.length < CHUNK_SIZE) {
    +    return String.fromCharCode.apply(null, bytes);
    +  }
    +
    +  // The remaining logic splits conversion by chunks since
    +  // Function#apply() has a maximum parameter count.
    +  // See discussion: http://goo.gl/LrWmZ9
    +
    +  var str = '';
    +  for (var i = 0; i < bytes.length; i += CHUNK_SIZE) {
    +    var chunk = bytes.slice(i, i + CHUNK_SIZE);
    +    str += String.fromCharCode.apply(null, chunk);
    +  }
    +  return str;
    +};
    +
    +// Static lookup maps, lazily populated by init_()
    +export const base64 = {
    +  /**
    +   * Maps bytes to characters.
    +   * @type {Object}
    +   * @private
    +   */
    +  byteToCharMap_: null,
    +  
    +  /**
    +   * Maps characters to bytes.
    +   * @type {Object}
    +   * @private
    +   */
    +  charToByteMap_: null,
    +
    +  /**
    +   * Maps bytes to websafe characters.
    +   * @type {Object}
    +   * @private
    +   */
    +  byteToCharMapWebSafe_: null,
    +  
    +  
    +  /**
    +   * Maps websafe characters to bytes.
    +   * @type {Object}
    +   * @private
    +   */
    +  charToByteMapWebSafe_: null,
    +  
    +  
    +  /**
    +   * Our default alphabet, shared between
    +   * ENCODED_VALS and ENCODED_VALS_WEBSAFE
    +   * @type {string}
    +   */
    +  ENCODED_VALS_BASE:
    +      'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
    +      'abcdefghijklmnopqrstuvwxyz' +
    +      '0123456789',
    +
    +  /**
    +   * Our default alphabet. Value 64 (=) is special; it means "nothing."
    +   * @type {string}
    +   */
    +  get ENCODED_VALS() {
    +    return this.ENCODED_VALS_BASE + '+/=';
    +  },
    +  
    +  /**
    +   * Our websafe alphabet.
    +   * @type {string}
    +   */
    +  get ENCODED_VALS_WEBSAFE() {
    +    return this.ENCODED_VALS_BASE + '-_.'
    +  },
    +  
    +  /**
    +   * Whether this browser supports the atob and btoa functions. This extension
    +   * started at Mozilla but is now implemented by many browsers. We use the
    +   * ASSUME_* variables to avoid pulling in the full useragent detection library
    +   * but still allowing the standard per-browser compilations.
    +   *
    +   * @type {boolean}
    +   */
    +  HAS_NATIVE_SUPPORT: typeof globalScope.atob === 'function',
    +  
    +  /**
    +   * Base64-encode an array of bytes.
    +   *
    +   * @param {Array<number>|Uint8Array} input An array of bytes (numbers with
    +   *     value in [0, 255]) to encode.
    +   * @param {boolean=} opt_webSafe Boolean indicating we should use the
    +   *     alternative alphabet.
    +   * @return {string} The base64 encoded string.
    +   */
    +  encodeByteArray(input, opt_webSafe?) {
    +    if (!Array.isArray(input)) {
    +      throw Error('encodeByteArray takes an array as a parameter');
    +    }
    +  
    +    this.init_();
    +  
    +    var byteToCharMap = opt_webSafe ?
    +                        this.byteToCharMapWebSafe_ :
    +                        this.byteToCharMap_;
    +  
    +    var output = [];
    +  
    +    for (var i = 0; i < input.length; i += 3) {
    +      var byte1 = input[i];
    +      var haveByte2 = i + 1 < input.length;
    +      var byte2 = haveByte2 ? input[i + 1] : 0;
    +      var haveByte3 = i + 2 < input.length;
    +      var byte3 = haveByte3 ? input[i + 2] : 0;
    +  
    +      var outByte1 = byte1 >> 2;
    +      var outByte2 = ((byte1 & 0x03) << 4) | (byte2 >> 4);
    +      var outByte3 = ((byte2 & 0x0F) << 2) | (byte3 >> 6);
    +      var outByte4 = byte3 & 0x3F;
    +  
    +      if (!haveByte3) {
    +        outByte4 = 64;
    +  
    +        if (!haveByte2) {
    +          outByte3 = 64;
    +        }
    +      }
    +  
    +      output.push(byteToCharMap[outByte1],
    +                  byteToCharMap[outByte2],
    +                  byteToCharMap[outByte3],
    +                  byteToCharMap[outByte4]);
    +    }
    +  
    +    return output.join('');
    +  },
    +  
    +  
    +  /**
    +   * Base64-encode a string.
    +   *
    +   * @param {string} input A string to encode.
    +   * @param {boolean=} opt_webSafe If true, we should use the
    +   *     alternative alphabet.
    +   * @return {string} The base64 encoded string.
    +   */
    +  encodeString(input, opt_webSafe) {
    +    // Shortcut for Mozilla browsers that implement
    +    // a native base64 encoder in the form of "btoa/atob"
    +    if (this.HAS_NATIVE_SUPPORT && !opt_webSafe) {
    +      return btoa(input);
    +    }
    +    return this.encodeByteArray(
    +        stringToByteArray(input), opt_webSafe);
    +  },
    +  
    +  
    +  /**
    +   * Base64-decode a string.
    +   *
    +   * @param {string} input to decode.
    +   * @param {boolean=} opt_webSafe True if we should use the
    +   *     alternative alphabet.
    +   * @return {string} string representing the decoded value.
    +   */
    +  decodeString(input, opt_webSafe) {
    +    // Shortcut for Mozilla browsers that implement
    +    // a native base64 encoder in the form of "btoa/atob"
    +    if (this.HAS_NATIVE_SUPPORT && !opt_webSafe) {
    +      return atob(input);
    +    }
    +    return byteArrayToString(this.decodeStringToByteArray(input, opt_webSafe));
    +  },
    +  
    +  
    +  /**
    +   * Base64-decode a string.
    +   *
    +   * In base-64 decoding, groups of four characters are converted into three
    +   * bytes.  If the encoder did not apply padding, the input length may not
    +   * be a multiple of 4.
    +   *
    +   * In this case, the last group will have fewer than 4 characters, and
    +   * padding will be inferred.  If the group has one or two characters, it decodes
    +   * to one byte.  If the group has three characters, it decodes to two bytes.
    +   *
    +   * @param {string} input Input to decode.
    +   * @param {boolean=} opt_webSafe True if we should use the web-safe alphabet.
    +   * @return {!Array<number>} bytes representing the decoded value.
    +   */
    +  decodeStringToByteArray(input, opt_webSafe) {
    +    this.init_();
    +  
    +    var charToByteMap = opt_webSafe ?
    +                        this.charToByteMapWebSafe_ :
    +                        this.charToByteMap_;
    +  
    +    var output = [];
    +  
    +    for (var i = 0; i < input.length; ) {
    +      var byte1 = charToByteMap[input.charAt(i++)];
    +  
    +      var haveByte2 = i < input.length;
    +      var byte2 = haveByte2 ? charToByteMap[input.charAt(i)] : 0;
    +      ++i;
    +  
    +      var haveByte3 = i < input.length;
    +      var byte3 = haveByte3 ? charToByteMap[input.charAt(i)] : 64;
    +      ++i;
    +  
    +      var haveByte4 = i < input.length;
    +      var byte4 = haveByte4 ? charToByteMap[input.charAt(i)] : 64;
    +      ++i;
    +  
    +      if (byte1 == null || byte2 == null ||
    +          byte3 == null || byte4 == null) {
    +        throw Error();
    +      }
    +  
    +      var outByte1 = (byte1 << 2) | (byte2 >> 4);
    +      output.push(outByte1);
    +  
    +      if (byte3 != 64) {
    +        var outByte2 = ((byte2 << 4) & 0xF0) | (byte3 >> 2);
    +        output.push(outByte2);
    +  
    +        if (byte4 != 64) {
    +          var outByte3 = ((byte3 << 6) & 0xC0) | byte4;
    +          output.push(outByte3);
    +        }
    +      }
    +    }
    +  
    +    return output;
    +  },
    +  
    +  
    +  /**
    +   * Lazy static initialization function. Called before
    +   * accessing any of the static map variables.
    +   * @private
    +   */
    +  init_() {
    +    if (!this.byteToCharMap_) {
    +      this.byteToCharMap_ = {};
    +      this.charToByteMap_ = {};
    +      this.byteToCharMapWebSafe_ = {};
    +      this.charToByteMapWebSafe_ = {};
    +  
    +      // We want quick mappings back and forth, so we precompute two maps.
    +      for (var i = 0; i < this.ENCODED_VALS.length; i++) {
    +        this.byteToCharMap_[i] =
    +            this.ENCODED_VALS.charAt(i);
    +        this.charToByteMap_[this.byteToCharMap_[i]] = i;
    +        this.byteToCharMapWebSafe_[i] =
    +            this.ENCODED_VALS_WEBSAFE.charAt(i);
    +        this.charToByteMapWebSafe_[
    +            this.byteToCharMapWebSafe_[i]] = i;
    +  
    +        // Be forgiving when decoding and correctly decode both encodings.
    +        if (i >= this.ENCODED_VALS_BASE.length) {
    +          this.charToByteMap_[
    +              this.ENCODED_VALS_WEBSAFE.charAt(i)] = i;
    +          this.charToByteMapWebSafe_[
    +              this.ENCODED_VALS.charAt(i)] = i;
    +        }
    +      }
    +    }
    +  }
    +};
    +
    + 
    + 
    + 
    + 
    \ No newline at end of file
    diff --git a/src/utils/deep_copy.ts b/src/utils/deep_copy.ts
    new file mode 100644
    index 00000000000..85040385f26
    --- /dev/null
    +++ b/src/utils/deep_copy.ts
    @@ -0,0 +1,61 @@
    +/**
    + * Do a deep-copy of basic JavaScript Objects or Arrays.
    + */
    +export function deepCopy<T>(value: T): T {
    +  return deepExtend(undefined, value);
    +}
    +
    +/**
    + * Copy properties from source to target (recursively allows extension
    + * of Objects and Arrays).  Scalar values in the target are over-written.
    + * If target is undefined, an object of the appropriate type will be created
    + * (and returned).
    + *
    + * We recursively copy all child properties of plain Objects in the source- so
    + * that namespace- like dictionaries are merged.
    + *
    + * Note that the target can be a function, in which case the properties in
    + * the source Object are copied onto it as static properties of the Function.
    + */
    +export function deepExtend(target: any, source: any): any {
    +  if (!(source instanceof Object)) {
    +    return source;
    +  }
    +
    +  switch (source.constructor) {
    +  case Date:
    +    // Treat Dates like scalars; if the target date object had any child
    +    // properties - they will be lost!
    +    let dateValue = (source as any) as Date;
    +    return new Date(dateValue.getTime());
    +
    +  case Object:
    +    if (target === undefined) {
    +      target = {};
    +    }
    +    break;
    +
    +  case Array:
    +    // Always copy the array source and overwrite the target.
    +    target = [];
    +    break;
    +
    +  default:
    +    // Not a plain Object - treat it as a scalar.
    +    return source;
    +  }
    +
    +  for (let prop in source) {
    +    if (!source.hasOwnProperty(prop)) {
    +      continue;
    +    }
    +    target[prop] = deepExtend(target[prop], source[prop]);
    +  }
    +
    +  return target;
    +}
    +
    +// TODO: Really needed (for JSCompiler type checking)?
    +export function patchProperty(obj: any, prop: string, value: any) {
    +  obj[prop] = value;
    +}
    \ No newline at end of file
    diff --git a/src/utils/environment.ts b/src/utils/environment.ts
    new file mode 100644
    index 00000000000..c173ebaf00b
    --- /dev/null
    +++ b/src/utils/environment.ts
    @@ -0,0 +1,48 @@
    +import { CONSTANTS } from "./constants";
    +
    +/**
    + * Returns navigator.userAgent string or '' if it's not defined.
    + * @return {string} user agent string
    + */
    +export const getUA = function() {
    +  if (typeof navigator !== 'undefined' &&
    +      typeof navigator['userAgent'] === 'string') {
    +    return navigator['userAgent'];
    +  } else {
    +    return '';
    +  }
    +};
    +
    +/**
    + * Detect Cordova / PhoneGap / Ionic frameworks on a mobile device.
    + *
    + * Deliberately does not rely on checking `file://` URLs (as this fails PhoneGap in the Ripple emulator) nor
    + * Cordova `onDeviceReady`, which would normally wait for a callback.
    + *
    + * @return {boolean} isMobileCordova
    + */
    +export const isMobileCordova = function() {
    +  return typeof window !== 'undefined' &&
    +         !!(window['cordova'] || window['phonegap'] || window['PhoneGap']) &&
    +         /ios|iphone|ipod|ipad|android|blackberry|iemobile/i.test(getUA());
    +};
    +
    +
    +/**
    + * Detect React Native.
    + *
    + * @return {boolean} True if ReactNative environment is detected.
    + */
    +export const isReactNative = function() {
    +  return typeof navigator === 'object' && navigator['product'] === 'ReactNative';
    +};
    +
    +
    +/**
    + * Detect Node.js.
    + *
    + * @return {boolean} True if Node.js environment is detected.
    + */
    +export const isNodeSdk = function() {
    +  return CONSTANTS.NODE_CLIENT === true || CONSTANTS.NODE_ADMIN === true;
    +};
    diff --git a/src/utils/globalScope.ts b/src/utils/globalScope.ts
    new file mode 100644
    index 00000000000..4ea25c7f5bf
    --- /dev/null
    +++ b/src/utils/globalScope.ts
    @@ -0,0 +1,15 @@
    +let scope;
    +
    +if (typeof global !== 'undefined') {
    +    scope = global;
    +} else if (typeof self !== 'undefined') {
    +    scope = self;
    +} else {
    +    try {
    +        scope = Function('return this')();
    +    } catch (e) {
    +        throw new Error('polyfill failed because global object is unavailable in this environment');
    +    }
    +}
    +
    +export const globalScope = scope;
    \ No newline at end of file
    diff --git a/src/utils/hash.ts b/src/utils/hash.ts
    new file mode 100644
    index 00000000000..82261cfdda5
    --- /dev/null
    +++ b/src/utils/hash.ts
    @@ -0,0 +1,36 @@
    +// Copyright 2011 The Closure Library Authors. All Rights Reserved.
    +//
    +// Licensed under the Apache License, Version 2.0 (the "License");
    +// you may not use this file except in compliance with the License.
    +// You may obtain a copy of the License at
    +//
    +//      http://www.apache.org/licenses/LICENSE-2.0
    +//
    +// Unless required by applicable law or agreed to in writing, software
    +// distributed under the License is distributed on an "AS-IS" BASIS,
    +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +// See the License for the specific language governing permissions and
    +// limitations under the License.
    + 
    +/**
    + * @fileoverview Abstract cryptographic hash interface.
    + *
    + * See Sha1 and Md5 for sample implementations.
    + *
    + */
    + 
    +/**
    + * Create a cryptographic hash instance.
    + *
    + * @constructor
    + * @struct
    + */
    +export class Hash {
    +  /**
    +   * The block size for the hasher.
    +   * @type {number}
    +   */
    +  blockSize: number = -1;
    +  
    +  constructor() {}
    +}
    \ No newline at end of file
    diff --git a/src/utils/json.ts b/src/utils/json.ts
    new file mode 100644
    index 00000000000..da1917bd148
    --- /dev/null
    +++ b/src/utils/json.ts
    @@ -0,0 +1,19 @@
    +/**
    + * Evaluates a JSON string into a javascript object.
    + *
    + * @param {string} str A string containing JSON.
    + * @return {*} The javascript object representing the specified JSON.
    + */
    +export const jsonEval = function(str) {
    +  return JSON.parse(str);
    +};
    +
    +
    +/**
    + * Returns JSON representing a javascript object.
    + * @param {*} data Javascript object to be stringified.
    + * @return {string} The JSON contents of the object.
    + */
    +export const stringify = function(data) {
    +  return JSON.stringify(data);
    +};
    diff --git a/src/utils/jwt.ts b/src/utils/jwt.ts
    new file mode 100644
    index 00000000000..edb8cb2b827
    --- /dev/null
    +++ b/src/utils/jwt.ts
    @@ -0,0 +1,124 @@
    +import { base64Decode } from "../database/core/util/util";
    +import { jsonEval } from "./json";
    +
    +/**
    + * Decodes a Firebase auth. token into constituent parts.
    + *
    + * Notes:
    + * - May return with invalid / incomplete claims if there's no native base64 decoding support.
    + * - Doesn't check if the token is actually valid.
    + *
    + * @param {?string} token
    + * @return {{header: *, claims: *, data: *, signature: string}}
    + */
    +export const decode = function(token) {
    +  var header = {},
    +      claims = {},
    +      data = {},
    +      signature = '';
    +
    +  try {
    +    var parts = token.split('.');
    +    header = jsonEval(base64Decode(parts[0]) || '');
    +    claims = jsonEval(base64Decode(parts[1]) || '');
    +    signature = parts[2];
    +    data = claims['d'] || {};
    +    delete claims['d'];
    +  } catch (e) {}
    +
    +  return {
    +    header: header,
    +    claims: claims,
    +    data: data,
    +    signature: signature
    +  };
    +};
    +
    +/**
    + * Decodes a Firebase auth. token and checks the validity of its time-based claims. Will return true if the
    + * token is within the time window authorized by the 'nbf' (not-before) and 'iat' (issued-at) claims.
    + *
    + * Notes:
    + * - May return a false negative if there's no native base64 decoding support.
    + * - Doesn't check if the token is actually valid.
    + *
    + * @param {?string} token
    + * @return {boolean}
    + */
    +export const isValidTimestamp = function(token) {
    +  var claims = decode(token).claims,
    +      now = Math.floor(new Date().getTime() / 1000),
    +      validSince, validUntil;
    +
    +  if (typeof claims === 'object') {
    +    if (claims.hasOwnProperty('nbf')) {
    +      validSince = claims['nbf'];
    +    } else if (claims.hasOwnProperty('iat')) {
    +      validSince = claims['iat'];
    +    }
    +
    +    if (claims.hasOwnProperty('exp')) {
    +      validUntil = claims['exp'];
    +    } else {
    +      // token will expire after 24h by default
    +      validUntil = validSince + 86400;
    +    }
    +  }
    +
    +  return now && validSince && validUntil &&
    +        (now >= validSince) && (now <= validUntil);
    +};
    +
    +/**
    + * Decodes a Firebase auth. token and returns its issued at time if valid, null otherwise.
    + *
    + * Notes:
    + * - May return null if there's no native base64 decoding support.
    + * - Doesn't check if the token is actually valid.
    + *
    + * @param {?string} token
    + * @return {?number}
    + */
    +export const issuedAtTime = function(token) {
    +  var claims = decode(token).claims;
    +  if (typeof claims === 'object' && claims.hasOwnProperty('iat')) {
    +    return claims['iat'];
    +  }
    +  return null;
    +};
    +
    +/**
    + * Decodes a Firebase auth. token and checks the validity of its format. Expects a valid issued-at time and non-empty
    + * signature.
    + *
    + * Notes:
    + * - May return a false negative if there's no native base64 decoding support.
    + * - Doesn't check if the token is actually valid.
    + *
    + * @param {?string} token
    + * @return {boolean}
    + */
    +export const isValidFormat = function(token) {
    +  var decoded = decode(token),
    +      claims = decoded.claims;
    +
    +  return !!decoded.signature &&
    +    !!claims &&
    +    (typeof claims === 'object') &&
    +    claims.hasOwnProperty('iat');
    +};
    +
    +/**
    + * Attempts to peer into an auth token and determine if it's an admin auth token by looking at the claims portion.
    + *
    + * Notes:
    + * - May return a false negative if there's no native base64 decoding support.
    + * - Doesn't check if the token is actually valid.
    + *
    + * @param {?string} token
    + * @return {boolean}
    + */
    +export const isAdmin = function(token) {
    +  var claims = decode(token).claims;
    +  return (typeof claims === 'object' && claims['admin'] === true);
    +};
    diff --git a/src/utils/nodePatches.ts b/src/utils/nodePatches.ts
    new file mode 100644
    index 00000000000..7c9d94565bb
    --- /dev/null
    +++ b/src/utils/nodePatches.ts
    @@ -0,0 +1,182 @@
    +import { CONSTANTS } from "./constants";
    +import { setWebSocketImpl } from "../database/realtime/WebSocketConnection";
    +import { setBufferImpl } from "../database/core/util/util";
    +import { 
    +  FirebaseIFrameScriptHolder,
    +  FIREBASE_LONGPOLL_COMMAND_CB_NAME,
    +  FIREBASE_LONGPOLL_DATA_CB_NAME
    +} from "../database/realtime/BrowserPollConnection";
    +import { Client } from "faye-websocket";
    +
    +setBufferImpl(Buffer);
    +setWebSocketImpl(Client);
    +
    +// Overriding the constant (we should be the only ones doing this)
    +CONSTANTS.NODE_CLIENT = true;
    +
    +/**
    + * @suppress {es5Strict}
    + */
    +(function() {
    +  var version = process['version'];
    +  if (version !== 'v0.10.22' && version !== 'v0.10.23' && version !== 'v0.10.24') return;
    +  /**
    +   * The following duplicates much of `/lib/_stream_writable.js` at
    +   * b922b5e90d2c14dd332b95827c2533e083df7e55, applying the fix for
    +   * https://github.com/joyent/node/issues/6506. Note that this fix also
    +   * needs to be applied to `Duplex.prototype.write()` (in
    +   * `/lib/_stream_duplex.js`) as well.
    +   */
    +  var Writable = require('_stream_writable');
    +
    +  Writable['prototype']['write'] = function(chunk, encoding, cb) {
    +    var state = this['_writableState'];
    +    var ret = false;
    +
    +    if (typeof encoding === 'function') {
    +      cb = encoding;
    +      encoding = null;
    +    }
    +
    +    if (Buffer['isBuffer'](chunk))
    +      encoding = 'buffer';
    +    else if (!encoding)
    +      encoding = state['defaultEncoding'];
    +
    +    if (typeof cb !== 'function')
    +      cb = function() {};
    +
    +    if (state['ended'])
    +      writeAfterEnd(this, state, cb);
    +    else if (validChunk(this, state, chunk, cb))
    +      ret = writeOrBuffer(this, state, chunk, encoding, cb);
    +
    +    return ret;
    +  };
    +
    +  function writeAfterEnd(stream, state, cb) {
    +    var er = new Error('write after end');
    +    // TODO: defer error events consistently everywhere, not just the cb
    +    stream['emit']('error', er);
    +    process['nextTick'](function() {
    +      cb(er);
    +    });
    +  }
    +
    +  function validChunk(stream, state, chunk, cb) {
    +    var valid = true;
    +    if (!Buffer['isBuffer'](chunk) &&
    +        'string' !== typeof chunk &&
    +        chunk !== null &&
    +        chunk !== undefined &&
    +        !state['objectMode']) {
    +      var er = new TypeError('Invalid non-string/buffer chunk');
    +      stream['emit']('error', er);
    +      process['nextTick'](function() {
    +        cb(er);
    +      });
    +      valid = false;
    +    }
    +    return valid;
    +  }
    +
    +  function writeOrBuffer(stream, state, chunk, encoding, cb) {
    +    chunk = decodeChunk(state, chunk, encoding);
    +    if (Buffer['isBuffer'](chunk))
    +      encoding = 'buffer';
    +    var len = state['objectMode'] ? 1 : chunk['length'];
    +
    +    state['length'] += len;
    +
    +    var ret = state['length'] < state['highWaterMark'];
    +    // we must ensure that previous needDrain will not be reset to false.
    +    if (!ret)
    +      state['needDrain'] = true;
    +
    +    if (state['writing'])
    +      state['buffer']['push'](new WriteReq(chunk, encoding, cb));
    +    else
    +      doWrite(stream, state, len, chunk, encoding, cb);
    +
    +    return ret;
    +  }
    +
    +  function decodeChunk(state, chunk, encoding) {
    +    if (!state['objectMode'] &&
    +        state['decodeStrings'] !== false &&
    +        typeof chunk === 'string') {
    +      chunk = new Buffer(chunk, encoding);
    +    }
    +    return chunk;
    +  }
    +
    +  /**
    +   * @constructor
    +   */
    +  function WriteReq(chunk, encoding, cb) {
    +    this['chunk'] = chunk;
    +    this['encoding'] = encoding;
    +    this['callback'] = cb;
    +  }
    +
    +  function doWrite(stream, state, len, chunk, encoding, cb) {
    +    state['writelen'] = len;
    +    state['writecb'] = cb;
    +    state['writing'] = true;
    +    state['sync'] = true;
    +    stream['_write'](chunk, encoding, state['onwrite']);
    +    state['sync'] = false;
    +  }
    +
    +  var Duplex = require('_stream_duplex');
    +  Duplex['prototype']['write'] = Writable['prototype']['write'];
    +})();
    +
    +/**
    + * @type {?function({url: string, forever: boolean}, function(Error, number, string))}
    + */
    +(FirebaseIFrameScriptHolder as any).request = null;
    +
    +/**
    + * @param {{url: string, forever: boolean}} req
    + * @param {function(string)=} onComplete
    + */
    +(FirebaseIFrameScriptHolder as any).nodeRestRequest = function(req, onComplete) {
    +  if (!(FirebaseIFrameScriptHolder as any).request)
    +    (FirebaseIFrameScriptHolder as any).request =
    +      /** @type {function({url: string, forever: boolean}, function(Error, number, string))} */ (require('request'));
    +
    +  (FirebaseIFrameScriptHolder as any).request(req, function(error, response, body) {
    +    if (error)
    +      throw 'Rest request for ' + req.url + ' failed.';
    +
    +    if (onComplete)
    +      onComplete(body);
    +  });
    +};
    +
    +/**
    + * @param {!string} url
    + * @param {function()} loadCB
    + */
    +(<any>FirebaseIFrameScriptHolder.prototype).doNodeLongPoll = function(url, loadCB) {
    +  var self = this;
    +  (FirebaseIFrameScriptHolder as any).nodeRestRequest({ url: url, forever: true }, function(body) {
    +    self.evalBody(body);
    +    loadCB();
    +  });
    +};
    +
    +/**
    + * Evaluates the string contents of a jsonp response.
    + * @param {!string} body
    + */
    +(<any>FirebaseIFrameScriptHolder.prototype).evalBody = function(body) {
    +  var jsonpCB;
    +  //jsonpCB is externed in firebase-extern.js
    +  eval('jsonpCB = function(' + FIREBASE_LONGPOLL_COMMAND_CB_NAME + ', ' + FIREBASE_LONGPOLL_DATA_CB_NAME + ') {' +
    +    body +
    +    '}');
    +  jsonpCB(this.commandCB, this.onMessageCB);
    +};
    +
    diff --git a/src/utils/obj.ts b/src/utils/obj.ts
    new file mode 100644
    index 00000000000..3019cf945f5
    --- /dev/null
    +++ b/src/utils/obj.ts
    @@ -0,0 +1,132 @@
    +// See http://www.devthought.com/2012/01/18/an-object-is-not-a-hash/
    +
    +export const contains = function(obj, key) {
    +  return Object.prototype.hasOwnProperty.call(obj, key);
    +};
    +
    +export const safeGet = function(obj, key) {
    +  if (Object.prototype.hasOwnProperty.call(obj, key))
    +    return obj[key];
    +  // else return undefined.
    +};
    +
    +/**
    + * Enumerates the keys/values in an object, excluding keys defined on the prototype.
    + *
    + * @param {?Object.<K,V>} obj Object to enumerate.
    + * @param {!function(K, V)} fn Function to call for each key and value.
    + * @template K,V
    + */
    +export const forEach = function(obj, fn) {
    +  for (var key in obj) {
    +    if (Object.prototype.hasOwnProperty.call(obj, key)) {
    +      fn(key, obj[key]);
    +    }
    +  }
    +};
    +
    +/**
    + * Copies all the (own) properties from one object to another.
    + * @param {!Object} objTo
    + * @param {!Object} objFrom
    + * @return {!Object} objTo
    + */
    +export const extend = function(objTo, objFrom) {
    +  forEach(objFrom, function(key, value) {
    +    objTo[key] = value;
    +  });
    +  return objTo;
    +}
    +
    +
    +/**
    + * Returns a clone of the specified object.
    + * @param {!Object} obj
    + * @return {!Object} cloned obj.
    + */
    +export const clone = function(obj) {
    +  return extend({}, obj);
    +};
    +
    +
    +/**
    + * Returns true if obj has typeof "object" and is not null.  Unlike goog.isObject(), does not return true
    + * for functions.
    + *
    + * @param obj {*} A potential object.
    + * @returns {boolean} True if it's an object.
    + */
    +export const isNonNullObject = function(obj) {
    +  return typeof obj === 'object' && obj !== null;
    +};
    +
    +export const isEmpty = function(obj) {
    +  for (var key in obj) {
    +    return false;
    +  }
    +  return true;
    +}
    +
    +export const getCount = function(obj) {
    +  var rv = 0;
    +  for (var key in obj) {
    +    rv++;
    +  }
    +  return rv;
    +}
    +
    +export const map = function(obj, f, opt_obj?) {
    +  var res = {};
    +  for (var key in obj) {
    +    res[key] = f.call(opt_obj, obj[key], key, obj);
    +  }
    +  return res;
    +};
    +
    +export const findKey = function(obj, fn, opt_this?) {
    +  for (var key in obj) {
    +    if (fn.call(opt_this, obj[key], key, obj)) {
    +      return key;
    +    }
    +  }
    +  return undefined;
    +};
    +
    +export const findValue = function(obj, fn, opt_this?) {
    +  var key = findKey(obj, fn, opt_this);
    +  return key && obj[key];
    +};
    +
    +export const getAnyKey = function(obj) {
    +  for (var key in obj) {
    +    return key;
    +  }
    +};
    +
    +export const getValues = function(obj) {
    +  var res = [];
    +  var i = 0;
    +  for (var key in obj) {
    +    res[i++] = obj[key];
    +  }
    +  return res;
    +};
    +
    +/**
    + * Tests whether every key/value pair in an object pass the test implemented
    + * by the provided function
    + *
    + * @param {?Object.<K,V>} obj Object to test.
    + * @param {!function(K, V)} fn Function to call for each key and value.
    + * @template K,V
    + */
    +export const every = function<V>(obj: Object, fn: (k: string, v?: V) => boolean): boolean {
    +  for (let key in obj) {
    +    if (Object.prototype.hasOwnProperty.call(obj, key)) {
    +      if (!fn(key, obj[key])) {
    +        return false;
    +      }
    +    }
    +  }
    +  return true;
    +};
    diff --git a/src/utils/promise.ts b/src/utils/promise.ts
    new file mode 100644
    index 00000000000..db3477f4a1e
    --- /dev/null
    +++ b/src/utils/promise.ts
    @@ -0,0 +1,73 @@
    +import { globalScope } from '../utils/globalScope';
    +
    +export const PromiseImpl = globalScope.Promise || require('promise-polyfill');
    +
    +/**
    + * A deferred promise implementation.
    + */
    +export class Deferred {
    +  resolve;
    +  reject;
    +  promise;
    +  
    +  /** @constructor */
    +  constructor() {
    +    var self = this;
    +    this.resolve = null;
    +    this.reject = null;
    +    this.promise = new PromiseImpl(function(resolve, reject) {
    +      self.resolve = resolve;
    +      self.reject = reject;
    +    });
    +  }
    +
    +  /**
    +   * Our API internals are not promiseified and cannot because our callback APIs have subtle expectations around
    +   * invoking promises inline, which Promises are forbidden to do. This method accepts an optional node-style callback
    +   * and returns a node-style callback which will resolve or reject the Deferred's promise.
    +   * @param {((?function(?(Error)): (?|undefined))| (?function(?(Error),?=): (?|undefined)))=} opt_nodeCallback
    +   * @return {!function(?(Error), ?=)}
    +   */
    +  wrapCallback(opt_nodeCallback?) {
    +    var self = this;
    +    /**
    +       * @param {?Error} error
    +       * @param {?=} opt_value
    +       */
    +    function meta(error, opt_value) {
    +      if (error) {
    +        self.reject(error);
    +      } else {
    +        self.resolve(opt_value);
    +      }
    +      if (typeof opt_nodeCallback === 'function') {
    +        attachDummyErrorHandler(self.promise);
    +
    +        // Some of our callbacks don't expect a value and our own tests
    +        // assert that the parameter length is 1
    +        if (opt_nodeCallback.length === 1) {
    +          opt_nodeCallback(error);
    +        } else {
    +          opt_nodeCallback(error, opt_value);
    +        }
    +      }
    +    }
    +    return meta;
    +  }
    +};
    +
    +
    +/**
    + * Chrome (and maybe other browsers) report an Error in the console if you reject a promise
    + * and nobody handles the error. This is normally a good thing, but this will confuse devs who
    + * never intended to use promises in the first place. So in some cases (in particular, if the
    + * developer attached a callback), we should attach a dummy resolver to the promise to suppress
    + * this error.
    + *
    + * Note: We can't do this all the time, since it breaks the Promise spec (though in the obscure
    + * 3.3.3 section related to upgrading non-compliant promises).
    + * @param {!firebase.Promise} promise
    + */
    +export const attachDummyErrorHandler = function(promise) {
    +  promise.catch(() => {});
    +};
    \ No newline at end of file
    diff --git a/src/utils/utf8.ts b/src/utils/utf8.ts
    new file mode 100644
    index 00000000000..369bc14416b
    --- /dev/null
    +++ b/src/utils/utf8.ts
    @@ -0,0 +1,75 @@
    +import { assert } from "./assert";
    +
    +// Code originally came from goog.crypt.stringToUtf8ByteArray, but for some reason they
    +// automatically replaced '\r\n' with '\n', and they didn't handle surrogate pairs,
    +// so it's been modified.
    +
    +// Note that not all Unicode characters appear as single characters in JavaScript strings.
    +// fromCharCode returns the UTF-16 encoding of a character - so some Unicode characters
    +// use 2 characters in Javascript.  All 4-byte UTF-8 characters begin with a first
    +// character in the range 0xD800 - 0xDBFF (the first character of a so-called surrogate
    +// pair).
    +// See http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.3
    +
    +
    +/**
    + * @param {string} str
    + * @return {Array}
    + */
    +export const stringToByteArray = function(str) {
    +  var out = [], p = 0;
    +  for (var i = 0; i < str.length; i++) {
    +    var c = str.charCodeAt(i);
    +
    +    // Is this the lead surrogate in a surrogate pair?
    +    if (c >= 0xd800 && c <= 0xdbff) {
    +      var high = c - 0xd800; // the high 10 bits.
    +      i++;
    +      assert(i < str.length, 'Surrogate pair missing trail surrogate.');
    +      var low = str.charCodeAt(i) - 0xdc00; // the low 10 bits.
    +      c = 0x10000 + (high << 10) + low;
    +    }
    +
    +    if (c < 128) {
    +      out[p++] = c;
    +    } else if (c < 2048) {
    +      out[p++] = (c >> 6) | 192;
    +      out[p++] = (c & 63) | 128;
    +    } else if (c < 65536) {
    +      out[p++] = (c >> 12) | 224;
    +      out[p++] = ((c >> 6) & 63) | 128;
    +      out[p++] = (c & 63) | 128;
    +    } else {
    +      out[p++] = (c >> 18) | 240;
    +      out[p++] = ((c >> 12) & 63) | 128;
    +      out[p++] = ((c >> 6) & 63) | 128;
    +      out[p++] = (c & 63) | 128;
    +    }
    +  }
    +  return out;
    +};
    +
    +
    +/**
    + * Calculate length without actually converting; useful for doing cheaper validation.
    + * @param {string} str
    + * @return {number}
    + */
    +export const stringLength = function(str) {
    +  var p = 0;
    +  for (var i = 0; i < str.length; i++) {
    +    var c = str.charCodeAt(i);
    +    if (c < 128) {
    +      p++;
    +    } else if (c < 2048) {
    +      p += 2;
    +    } else if (c >= 0xd800 && c <= 0xdbff) {
    +      // Lead surrogate of a surrogate pair.  The pair together will take 4 bytes to represent.
    +      p += 4;
    +      i++; // skip trail surrogate.
    +    } else {
    +      p += 3;
    +    }
    +  }
    +  return p;
    +};
    diff --git a/src/utils/util.ts b/src/utils/util.ts
    new file mode 100644
    index 00000000000..edb896e49a5
    --- /dev/null
    +++ b/src/utils/util.ts
    @@ -0,0 +1,43 @@
    +import { forEach } from "./obj";
    +
    +/**
    + * Returns a querystring-formatted string (e.g. &arg=val&arg2=val2) from a params
    + * object (e.g. {arg: 'val', arg2: 'val2'})
    + * Note: You must prepend it with ? when adding it to a URL.
    + *
    + * @param {!Object} querystringParams
    + * @return {string}
    + */
    +export const querystring = function(querystringParams) {
    +  var params = [];
    +  forEach(querystringParams, function(key, value) {
    +    if (Array.isArray(value)) {
    +      value.forEach(function(arrayVal) {
    +        params.push(encodeURIComponent(key) + '=' + encodeURIComponent(arrayVal));
    +      });
    +    } else {
    +      params.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
    +    }
    +  });
    +  return (params.length) ? '&' + params.join('&') : '';
    +};
    +
    +
    +/**
    + * Decodes a querystring (e.g. ?arg=val&arg2=val2) into a params object (e.g. {arg: 'val', arg2: 'val2'})
    + *
    + * @param {string} querystring
    + * @return {!Object}
    + */
    +export const querystringDecode = function(querystring) {
    +  var obj = {};
    +  var tokens = querystring.replace(/^\?/, '').split('&');
    +
    +  tokens.forEach(function(token) {
    +    if (token) {
    +      var key = token.split('=');
    +      obj[key[0]] = key[1];
    +    }
    +  });
    +  return obj;
    +};
    \ No newline at end of file
    diff --git a/src/utils/validation.ts b/src/utils/validation.ts
    new file mode 100644
    index 00000000000..dd85f3196b0
    --- /dev/null
    +++ b/src/utils/validation.ts
    @@ -0,0 +1,87 @@
    +/**
    + * Check to make sure the appropriate number of arguments are provided for a public function.
    + * Throws an error if it fails.
    + *
    + * @param {!string} fnName The function name
    + * @param {!number} minCount The minimum number of arguments to allow for the function call
    + * @param {!number} maxCount The maximum number of argument to allow for the function call
    + * @param {!number} argCount The actual number of arguments provided.
    + */
    +export const validateArgCount = function(fnName, minCount, maxCount, argCount) {
    +  var argError;
    +  if (argCount < minCount) {
    +    argError = 'at least ' + minCount;
    +  } else if (argCount > maxCount) {
    +    argError = (maxCount === 0) ? 'none' : ('no more than ' + maxCount);
    +  }
    +  if (argError) {
    +    var error = fnName + ' failed: Was called with ' + argCount +
    +      ((argCount === 1) ? ' argument.' : ' arguments.') +
    +      ' Expects ' + argError + '.';
    +    throw new Error(error);
    +  }
    +};
    +
    +/**
    + * Generates a string to prefix an error message about failed argument validation
    + *
    + * @param {!string} fnName The function name
    + * @param {!number} argumentNumber The index of the argument
    + * @param {boolean} optional Whether or not the argument is optional
    + * @return {!string} The prefix to add to the error thrown for validation.
    + */
    +export function errorPrefix(fnName, argumentNumber, optional) {
    +  var argName = '';
    +  switch (argumentNumber) {
    +    case 1:
    +      argName = optional ? 'first' : 'First';
    +      break;
    +    case 2:
    +      argName = optional ? 'second' : 'Second';
    +      break;
    +    case 3:
    +      argName = optional ? 'third' : 'Third';
    +      break;
    +    case 4:
    +      argName = optional ? 'fourth' : 'Fourth';
    +      break;
    +    default:
    +      throw new Error('errorPrefix called with argumentNumber > 4.  Need to update it?');
    +  }
    +
    +  var error = fnName + ' failed: ';
    +
    +  error += argName + ' argument ';
    +  return error;
    +};
    +
    +/**
    + * @param {!string} fnName
    + * @param {!number} argumentNumber
    + * @param {!string} namespace
    + * @param {boolean} optional
    + */
    +export const validateNamespace = function(fnName, argumentNumber, namespace, optional) {
    +  if (optional && !(namespace))
    +    return;
    +  if (typeof namespace !== 'string') {
    +    //TODO: I should do more validation here. We only allow certain chars in namespaces.
    +    throw new Error(errorPrefix(fnName, argumentNumber, optional) +
    +      'must be a valid firebase namespace.');
    +  }
    +};
    +
    +export const validateCallback = function(fnName, argumentNumber, callback, optional) {
    +  if (optional && !(callback))
    +    return;
    +  if (typeof callback !== 'function')
    +    throw new Error(errorPrefix(fnName, argumentNumber, optional) + 'must be a valid function.');
    +};
    +
    +export const validateContextObject = function(fnName, argumentNumber, context, optional) {
    +  if (optional && !(context))
    +    return;
    +  if (typeof context !== 'object' || context === null)
    +    throw new Error(errorPrefix(fnName, argumentNumber, optional) +
    +      'must be a valid context object.');
    +};
    diff --git a/tests/app/unit/errors.test.ts b/tests/app/errors.test.ts
    similarity index 97%
    rename from tests/app/unit/errors.test.ts
    rename to tests/app/errors.test.ts
    index a332390af4b..560c6dbe88f 100644
    --- a/tests/app/unit/errors.test.ts
    +++ b/tests/app/errors.test.ts
    @@ -14,7 +14,7 @@
     * limitations under the License.
     */
     import {assert} from 'chai';
    -import {ErrorFactory, ErrorList, patchCapture} from '../../../src/app/errors';
    +import {ErrorFactory, ErrorList, patchCapture} from '../../src/app/errors';
     
     type Err =
       'generic-error' |
    diff --git a/tests/app/unit/firebase_app.test.ts b/tests/app/firebase_app.test.ts
    similarity index 99%
    rename from tests/app/unit/firebase_app.test.ts
    rename to tests/app/firebase_app.test.ts
    index f91751b12f3..fd8a7b137c9 100644
    --- a/tests/app/unit/firebase_app.test.ts
    +++ b/tests/app/firebase_app.test.ts
    @@ -18,7 +18,7 @@ import {
       FirebaseNamespace,
       FirebaseApp,
       FirebaseService
    -} from '../../../src/app/firebase_app';
    +} from '../../src/app/firebase_app';
     import {assert} from 'chai';
     
     describe("Firebase App Class", () => {
    diff --git a/tests/app/unit/subscribe.test.ts b/tests/app/subscribe.test.ts
    similarity index 99%
    rename from tests/app/unit/subscribe.test.ts
    rename to tests/app/subscribe.test.ts
    index 07bae4f843c..148479d2d29 100644
    --- a/tests/app/unit/subscribe.test.ts
    +++ b/tests/app/subscribe.test.ts
    @@ -23,7 +23,7 @@ import {
       Observer,
       Subscribe,
       Unsubscribe,
    -} from '../../../src/app/subscribe';
    +} from '../../src/app/subscribe';
     import {assert} from 'chai';
     import * as sinon from 'sinon';
     
    diff --git a/tests/config/project.json b/tests/config/project.json
    new file mode 100644
    index 00000000000..10dc41ebbbc
    --- /dev/null
    +++ b/tests/config/project.json
    @@ -0,0 +1 @@
    +{"apiKey":"AIzaSyBNHCyZ-bpv-WA-HpXTmigJm2aq3z1kaH8","authDomain":"jscore-sandbox-141b5.firebaseapp.com","databaseURL":"https://jscore-sandbox-141b5.firebaseio.com","projectId":"jscore-sandbox-141b5","storageBucket":"jscore-sandbox-141b5.appspot.com","messagingSenderId":"280127633210"}
    diff --git a/tests/database/browser/connection.test.ts b/tests/database/browser/connection.test.ts
    new file mode 100644
    index 00000000000..3f765a9bbf1
    --- /dev/null
    +++ b/tests/database/browser/connection.test.ts
    @@ -0,0 +1,40 @@
    +import { expect } from "chai";
    +import { TEST_PROJECT, testRepoInfo } from "../helpers/util";
    +import { Connection } from "../../../src/database/realtime/Connection";
    +
    +describe('Connection', function() {
    +  it('return the session id', function(done) {
    +    new Connection('1',
    +        testRepoInfo(TEST_PROJECT.databaseURL),
    +        message => {},
    +        (timestamp, sessionId) => {
    +          expect(sessionId).not.to.be.null;
    +          expect(sessionId).not.to.equal('');
    +          done();
    +        },
    +        () => {},
    +        reason => {});
    +  });
    +
    +  // TODO - Flakey Test.  When Dev Tools is closed on my Mac, this test
    +  // fails about 20% of the time (open - it never fails).  In the failing
    +  // case a long-poll is opened first.
    +  // https://app.asana.com/0/58926111402292/101921715724749
    +  it.skip('disconnect old session on new connection', function(done) {
    +    const info = testRepoInfo(TEST_PROJECT.databaseURL);
    +    new Connection('1', info,
    +        message => {},
    +        (timestamp, sessionId) => {
    +          new Connection('2', info,
    +              message => {},
    +              (timestamp, sessionId) => {},
    +              () => {},
    +              reason => {},
    +              sessionId);
    +        },
    +        () => {
    +          done(); // first connection was disconnected
    +        },
    +        reason => {});
    +  });
    +});
    diff --git a/tests/database/browser/crawler_support.test.ts b/tests/database/browser/crawler_support.test.ts
    new file mode 100644
    index 00000000000..d98b8ac40c6
    --- /dev/null
    +++ b/tests/database/browser/crawler_support.test.ts
    @@ -0,0 +1,181 @@
    +import { expect } from "chai";
    +import { forceRestClient } from "../../../src/database/api/test_access";
    +
    +import { 
    +  getRandomNode,
    +  testAuthTokenProvider,
    +  getFreshRepoFromReference
    +} from "../helpers/util";
    +
    +// Some sanity checks for the ReadonlyRestClient crawler support.
    +describe('Crawler Support', function() {
    +  var initialData;
    +  var normalRef;
    +  var restRef;
    +  var tokenProvider;
    +
    +  beforeEach(function(done) {
    +    normalRef = getRandomNode();
    +
    +    forceRestClient(true);
    +    restRef = getFreshRepoFromReference(normalRef);
    +    forceRestClient(false);
    +
    +    tokenProvider = testAuthTokenProvider(restRef.database.app);
    +
    +    setInitialData(done);
    +  });
    +
    +  afterEach(function() {
    +    tokenProvider.setToken(null);
    +  });
    +
    +  function setInitialData(done) {
    +    // Set some initial data.
    +    initialData = {
    +      leaf: 42,
    +      securedLeaf: 'secret',
    +      leafWithPriority: { '.value': 42, '.priority': 'pri' },
    +      obj: { a: 1, b: 2 },
    +      list: {
    +        10: { name: 'amy', age: 75, '.priority': 22 },
    +        20: { name: 'becky', age: 42, '.priority': 52 },
    +        30: { name: 'fred', age: 35, '.priority': 23 },
    +        40: { name: 'fred', age: 29, '.priority': 26 },
    +        50: { name: 'sally', age: 21, '.priority': 96 },
    +        60: { name: 'tom', age: 16, '.priority': 15 },
    +        70: { name: 'victor', age: 4, '.priority': 47 }
    +      },
    +      valueList: {
    +        10: 'c',
    +        20: 'b',
    +        30: 'e',
    +        40: 'f',
    +        50: 'a',
    +        60: 'd',
    +        70: 'e'
    +      }
    +    };
    +
    +    normalRef.set(initialData, function(error) {
    +      expect(error).to.equal(null);
    +      done();
    +    });
    +  }
    +
    +  it('set() is a no-op', function(done) {
    +    normalRef.child('leaf').on('value', function(s) {
    +      expect(s.val()).to.equal(42);
    +    });
    +
    +    restRef.child('leaf').set('hello');
    +
    +    // We need to wait long enough to be sure that our 'hello' didn't actually get set, but there's
    +    // no good way to do that.  So we just do a couple round-trips via the REST client and assume
    +    // that's good enough.
    +    restRef.child('obj').once('value', function(s) {
    +      expect(s.val()).to.deep.equal(initialData.obj);
    +
    +      restRef.child('obj').once('value', function(s) {
    +        expect(s.val()).to.deep.equal(initialData.obj);
    +
    +        normalRef.child('leaf').off();
    +        done();
    +      });
    +    });
    +  });
    +
    +  it('set() is a no-op (Promise)', function() {
    +    // This test mostly exists to make sure restRef really is using ReadonlyRestClient
    +    // and we're not accidentally testing a normal Firebase connection.
    +
    +    normalRef.child('leaf').on('value', function(s) {
    +      expect(s.val()).to.equal(42);
    +    });
    +
    +    restRef.child('leaf').set('hello');
    +
    +    // We need to wait long enough to be sure that our 'hello' didn't actually get set, but there's
    +    // no good way to do that.  So we just do a couple round-trips via the REST client and assume
    +    // that's good enough.
    +    return restRef.child('obj').once('value').then(function(s) {
    +      expect(s.val()).to.deep.equal(initialData.obj);
    +
    +      return restRef.child('obj').once('value');
    +    }).then(function(s) {
    +      expect(s.val()).to.deep.equal(initialData.obj);
    +      normalRef.child('leaf').off();
    +    }, function (reason) {
    +      normalRef.child('leaf').off();
    +      return Promise.reject(reason);
    +    });
    +  });
    +
    +  it('.info/connected fires with true', function(done) {
    +    restRef.root.child('.info/connected').on('value', function(s) {
    +      if (s.val() == true) {
    +        done();
    +      }
    +    });
    +  });
    +
    +  it('Leaf read works.', function(done) {
    +    restRef.child('leaf').once('value', function(s) {
    +      expect(s.val()).to.equal(initialData.leaf);
    +      done();
    +    });
    +  });
    +
    +  it('Leaf read works. (Promise)', function() {
    +    return restRef.child('leaf').once('value').then(function(s) {
    +      expect(s.val()).to.equal(initialData.leaf);
    +    });
    +  });
    +
    +  it('Object read works.', function(done) {
    +    restRef.child('obj').once('value', function(s) {
    +      expect(s.val()).to.deep.equal(initialData.obj);
    +      done();
    +    });
    +  });
    +
    +  it('Object read works. (Promise)', function() {
    +    return restRef.child('obj').once('value').then(function(s) {
    +      expect(s.val()).to.deep.equal(initialData.obj);
    +    });
    +  });
    +
    +  it('Leaf with priority read works.', function(done) {
    +    restRef.child('leafWithPriority').once('value', function(s) {
    +      expect(s.exportVal()).to.deep.equal(initialData.leafWithPriority);
    +      done();
    +    });
    +  });
    +
    +  it('Leaf with priority read works. (Promise)', function() {
    +    return restRef.child('leafWithPriority').once('value').then(function(s) {
    +      expect(s.exportVal()).to.deep.equal(initialData.leafWithPriority);
    +    });
    +  });
    +
    +  it('Null read works.', function(done) {
    +    restRef.child('nonexistent').once('value', function(s) {
    +      expect(s.val()).to.equal(null);
    +      done();
    +    });
    +  });
    +
    +  it('Null read works. (Promise)', function() {
    +    return restRef.child('nonexistent').once('value').then(function(s) {
    +      expect(s.val()).to.equal(null);
    +    });
    +  });
    +
    +  it('on works.', function(done) {
    +    restRef.child('leaf').on('value', function(s) {
    +      expect(s.val()).to.equal(initialData.leaf);
    +      restRef.child('leaf').off();
    +      done();
    +    });
    +  });
    +});
    diff --git a/tests/database/compound_write.test.ts b/tests/database/compound_write.test.ts
    new file mode 100644
    index 00000000000..df95f55e10d
    --- /dev/null
    +++ b/tests/database/compound_write.test.ts
    @@ -0,0 +1,438 @@
    +import { expect } from "chai";
    +import { ChildrenNode } from "../../src/database/core/snap/ChildrenNode";
    +import { CompoundWrite } from "../../src/database/core/CompoundWrite";
    +import { LeafNode } from "../../src/database/core/snap/LeafNode";
    +import { NamedNode } from "../../src/database/core/snap/Node";
    +import { nodeFromJSON } from "../../src/database/core/snap/nodeFromJSON";
    +import { Path } from "../../src/database/core/util/Path";
    +
    +describe('CompoundWrite Tests', function() {
    +  var LEAF_NODE = nodeFromJSON('leaf-node');
    +  var PRIO_NODE = nodeFromJSON('prio');
    +  var CHILDREN_NODE = nodeFromJSON({ 'child-1': 'value-1', 'child-2': 'value-2' });
    +  var EMPTY_NODE = ChildrenNode.EMPTY_NODE;
    +
    +  function assertNodeGetsCorrectPriority(compoundWrite, node, priority) {
    +    if (node.isEmpty()) {
    +      expect(compoundWrite.apply(node)).to.equal(EMPTY_NODE);
    +    } else {
    +      expect(compoundWrite.apply(node)).to.deep.equal(node.updatePriority(priority));
    +    }
    +  }
    +  
    +  function assertNodesEqual(expected, actual) {
    +    expect(actual.equals(expected)).to.be.true;
    +  }
    +
    +  it('Empty merge is empty', function() {
    +    expect(CompoundWrite.Empty.isEmpty()).to.be.true;
    +  });
    +
    +  it('CompoundWrite with priority update is not empty.', function() {
    +    expect(CompoundWrite.Empty.addWrite(new Path('.priority'), PRIO_NODE).isEmpty()).to.be.false;
    +  });
    +
    +  it('CompoundWrite with update is not empty.', function() {
    +    expect(CompoundWrite.Empty.addWrite(new Path('foo/bar'), LEAF_NODE).isEmpty()).to.be.false;
    +  });
    +
    +  it('CompoundWrite with root update is not empty.', function() {
    +    expect(CompoundWrite.Empty.addWrite(Path.Empty, LEAF_NODE).isEmpty()).to.be.false;
    +  });
    +
    +  it('CompoundWrite with empty root update is not empty.', function() {
    +    expect(CompoundWrite.Empty.addWrite(Path.Empty, EMPTY_NODE).isEmpty()).to.be.false;
    +  });
    +
    +  it('CompoundWrite with root priority update, child write is not empty.', function() {
    +    var compoundWrite = CompoundWrite.Empty.addWrite(new Path('.priority'), PRIO_NODE);
    +    expect(compoundWrite.childCompoundWrite(new Path('.priority')).isEmpty()).to.be.false;
    +  });
    +
    +  it('Applies leaf overwrite', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    compoundWrite = compoundWrite.addWrite(Path.Empty, LEAF_NODE);
    +    expect(compoundWrite.apply(EMPTY_NODE)).to.equal(LEAF_NODE);
    +  });
    +
    +  it('Applies children overwrite', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    var childNode = EMPTY_NODE.updateImmediateChild('child', LEAF_NODE);
    +    compoundWrite = compoundWrite.addWrite(Path.Empty, childNode);
    +    expect(compoundWrite.apply(EMPTY_NODE)).to.equal(childNode);
    +  });
    +
    +  it('Adds child node', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    var expected = EMPTY_NODE.updateImmediateChild('child', LEAF_NODE);
    +    compoundWrite = compoundWrite.addWrite(new Path('child'), LEAF_NODE);
    +    assertNodesEqual(expected, compoundWrite.apply(EMPTY_NODE));
    +  });
    +
    +  it('Adds deep child node', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    var path = new Path('deep/deep/node');
    +    var expected = EMPTY_NODE.updateChild(path, LEAF_NODE);
    +    compoundWrite = compoundWrite.addWrite(path, LEAF_NODE);
    +    expect(compoundWrite.apply(EMPTY_NODE)).to.deep.equal(expected);
    +  });
    +
    +  it('shallow update removes deep update', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    var updateOne = nodeFromJSON('new-foo-value');
    +    var updateTwo = nodeFromJSON('baz-value');
    +    var updateThree = nodeFromJSON({'foo': 'foo-value', 'bar': 'bar-value' });
    +    compoundWrite = compoundWrite.addWrite(new Path('child-1/foo'), updateOne);
    +    compoundWrite = compoundWrite.addWrite(new Path('child-1/baz'), updateTwo);
    +    compoundWrite = compoundWrite.addWrite(new Path('child-1'), updateThree);
    +    var expectedChildOne = {
    +        'foo': 'foo-value',
    +        'bar': 'bar-value'
    +    };
    +    var expected = CHILDREN_NODE.updateImmediateChild('child-1',
    +        nodeFromJSON(expectedChildOne));
    +    assertNodesEqual(expected, compoundWrite.apply(CHILDREN_NODE));
    +  });
    +
    +  it('child priority updates empty priority on child write', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    compoundWrite = compoundWrite.addWrite(new Path('child-1/.priority'), EMPTY_NODE);
    +    var node = new LeafNode('foo', PRIO_NODE);
    +    assertNodeGetsCorrectPriority(compoundWrite.childCompoundWrite(new Path('child-1')), node, EMPTY_NODE);
    +  });
    +
    +  it('deep priority set works on empty node when other set is available', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    compoundWrite = compoundWrite.addWrite(new Path('foo/.priority'), PRIO_NODE);
    +    compoundWrite = compoundWrite.addWrite(new Path('foo/child'), LEAF_NODE);
    +    var node = compoundWrite.apply(EMPTY_NODE);
    +    assertNodesEqual(PRIO_NODE, node.getChild(new Path('foo')).getPriority());
    +  });
    +
    +  it('child merge looks into update node', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    var update = nodeFromJSON({ 'foo': 'foo-value', 'bar': 'bar-value'});
    +    compoundWrite = compoundWrite.addWrite(Path.Empty, update);
    +    assertNodesEqual(nodeFromJSON('foo-value'),
    +        compoundWrite.childCompoundWrite(new Path('foo')).apply(EMPTY_NODE));
    +  });
    +
    +  it('child merge removes node on deeper paths', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    var update = nodeFromJSON({ 'foo': 'foo-value', 'bar': 'bar-value' });
    +    compoundWrite = compoundWrite.addWrite(Path.Empty, update);
    +    assertNodesEqual(EMPTY_NODE, compoundWrite.childCompoundWrite(new Path('foo/not/existing')).apply(LEAF_NODE));
    +  });
    +
    +  it('child merge with empty path is same merge', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    var update = nodeFromJSON({ 'foo': 'foo-value', 'bar': 'bar-value' });
    +    compoundWrite = compoundWrite.addWrite(Path.Empty, update);
    +    expect(compoundWrite.childCompoundWrite(Path.Empty)).to.equal(compoundWrite);
    +  });
    +
    +  it('root update removes root priority', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    compoundWrite = compoundWrite.addWrite(new Path('.priority'), PRIO_NODE);
    +    compoundWrite = compoundWrite.addWrite(Path.Empty, nodeFromJSON('foo'));
    +    assertNodesEqual(nodeFromJSON('foo'), compoundWrite.apply(EMPTY_NODE));
    +  });
    +
    +  it('deep update removes priority there', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    compoundWrite = compoundWrite.addWrite(new Path('foo/.priority'), PRIO_NODE);
    +    compoundWrite = compoundWrite.addWrite(new Path('foo'), nodeFromJSON('bar'));
    +    var expected = nodeFromJSON({ 'foo': 'bar' });
    +    assertNodesEqual(expected, compoundWrite.apply(EMPTY_NODE));
    +  });
    +
    +  it('adding updates at path works', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    var updates = {
    +      'foo': nodeFromJSON('foo-value'),
    +      'bar': nodeFromJSON('bar-value')
    +    };
    +    compoundWrite = compoundWrite.addWrites(new Path('child-1'), updates);
    +
    +    var expectedChildOne = {
    +        'foo': 'foo-value',
    +        'bar': 'bar-value'
    +    };
    +    var expected = CHILDREN_NODE.updateImmediateChild('child-1', nodeFromJSON(expectedChildOne));
    +    assertNodesEqual(expected, compoundWrite.apply(CHILDREN_NODE));
    +  });
    +
    +  it('adding updates at root works', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    var updates = {
    +      'child-1': nodeFromJSON('new-value-1'),
    +      'child-2': EMPTY_NODE,
    +      'child-3': nodeFromJSON('value-3')
    +    };
    +    compoundWrite = compoundWrite.addWrites(Path.Empty, updates);
    +
    +    var expected = {
    +        'child-1': 'new-value-1',
    +        'child-3': 'value-3'
    +    };
    +    assertNodesEqual(nodeFromJSON(expected), compoundWrite.apply(CHILDREN_NODE));
    +  });
    +
    +  it('child write of root priority works', function() {
    +    var compoundWrite = CompoundWrite.Empty.addWrite(new Path('.priority'), PRIO_NODE);
    +    assertNodesEqual(PRIO_NODE, compoundWrite.childCompoundWrite(new Path('.priority')).apply(EMPTY_NODE));
    +  });
    +
    +  it('complete children only returns complete overwrites', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    compoundWrite = compoundWrite.addWrite(new Path('child-1'), LEAF_NODE);
    +    expect(compoundWrite.getCompleteChildren()).to.deep.equal([new NamedNode('child-1', LEAF_NODE)]);
    +  });
    +
    +  it('complete children only returns empty overwrites', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    compoundWrite = compoundWrite.addWrite(new Path('child-1'), EMPTY_NODE);
    +    expect(compoundWrite.getCompleteChildren()).to.deep.equal([new NamedNode('child-1', EMPTY_NODE)]);
    +  });
    +
    +  it('complete children doesnt return deep overwrites', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    compoundWrite = compoundWrite.addWrite(new Path('child-1/deep/path'), LEAF_NODE);
    +    expect(compoundWrite.getCompleteChildren()).to.deep.equal([]);
    +  });
    +
    +  it('complete children return all complete children but no incomplete', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    compoundWrite = compoundWrite.addWrite(new Path('child-1/deep/path'), LEAF_NODE);
    +    compoundWrite = compoundWrite.addWrite(new Path('child-2'), LEAF_NODE);
    +    compoundWrite = compoundWrite.addWrite(new Path('child-3'), EMPTY_NODE);
    +    var expected = {
    +      'child-2': LEAF_NODE,
    +      'child-3': EMPTY_NODE
    +    };
    +    var actual = { };
    +    var completeChildren = compoundWrite.getCompleteChildren();
    +    for (var i = 0; i < completeChildren.length; i++) {
    +      actual[completeChildren[i].name] = completeChildren[i].node;
    +    }
    +    expect(actual).to.deep.equal(expected);
    +  });
    +
    +  it('complete children return all children for root set', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    compoundWrite = compoundWrite.addWrite(Path.Empty, CHILDREN_NODE);
    +
    +    var expected = {
    +      'child-1': nodeFromJSON('value-1'),
    +      'child-2': nodeFromJSON('value-2')
    +    };
    +
    +    var actual = { };
    +    var completeChildren = compoundWrite.getCompleteChildren();
    +    for (var i = 0; i < completeChildren.length; i++) {
    +      actual[completeChildren[i].name] = completeChildren[i].node;
    +    }
    +    expect(actual).to.deep.equal(expected);
    +  });
    +
    +  it('empty merge has no shadowing write', function() {
    +    expect(CompoundWrite.Empty.hasCompleteWrite(Path.Empty)).to.be.false;
    +  });
    +
    +  it('compound write with empty root has shadowing write', function() {
    +    var compoundWrite = CompoundWrite.Empty.addWrite(Path.Empty, EMPTY_NODE);
    +    expect(compoundWrite.hasCompleteWrite(Path.Empty)).to.be.true;
    +    expect(compoundWrite.hasCompleteWrite(new Path('child'))).to.be.true;
    +  });
    +
    +  it('compound write with  root has shadowing write', function() {
    +    var compoundWrite = CompoundWrite.Empty.addWrite(Path.Empty, LEAF_NODE);
    +    expect(compoundWrite.hasCompleteWrite(Path.Empty)).to.be.true;
    +    expect(compoundWrite.hasCompleteWrite(new Path('child'))).to.be.true;
    +  });
    +
    +  it('compound write with deep update has shadowing write', function() {
    +    var compoundWrite = CompoundWrite.Empty.addWrite(new Path('deep/update'), LEAF_NODE);
    +    expect(compoundWrite.hasCompleteWrite(Path.Empty)).to.be.false;
    +    expect(compoundWrite.hasCompleteWrite(new Path('deep'))).to.be.false;
    +    expect(compoundWrite.hasCompleteWrite(new Path('deep/update'))).to.be.true;
    +  });
    +
    +  it('compound write with priority update has shadowing write', function() {
    +    var compoundWrite = CompoundWrite.Empty.addWrite(new Path('.priority'), PRIO_NODE);
    +    expect(compoundWrite.hasCompleteWrite(Path.Empty)).to.be.false;
    +    expect(compoundWrite.hasCompleteWrite(new Path('.priority'))).to.be.true;
    +  });
    +
    +  it('updates can be removed', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    var update = nodeFromJSON({ 'foo': 'foo-value', 'bar': 'bar-value' });
    +    compoundWrite = compoundWrite.addWrite(new Path('child-1'), update);
    +    compoundWrite = compoundWrite.removeWrite(new Path('child-1'));
    +    assertNodesEqual(CHILDREN_NODE, compoundWrite.apply(CHILDREN_NODE));
    +  });
    +
    +  it('deep removes has no effect on overlaying set', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    var updateOne = nodeFromJSON({ 'foo': 'foo-value', 'bar': 'bar-value' });
    +    var updateTwo = nodeFromJSON('baz-value');
    +    var updateThree = nodeFromJSON('new-foo-value');
    +    compoundWrite = compoundWrite.addWrite(new Path('child-1'), updateOne);
    +    compoundWrite = compoundWrite.addWrite(new Path('child-1/baz'), updateTwo);
    +    compoundWrite = compoundWrite.addWrite(new Path('child-1/foo'), updateThree);
    +    compoundWrite = compoundWrite.removeWrite(new Path('child-1/foo'));
    +    var expectedChildOne = {
    +        'foo': 'new-foo-value',
    +        'bar': 'bar-value',
    +        'baz': 'baz-value'
    +    };
    +    var expected = CHILDREN_NODE.updateImmediateChild('child-1', nodeFromJSON(expectedChildOne));
    +    assertNodesEqual(expected, compoundWrite.apply(CHILDREN_NODE));
    +  });
    +
    +  it('remove at path without set is without effect', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    var updateOne = nodeFromJSON({ 'foo': 'foo-value', 'bar': 'bar-value' });
    +    var updateTwo = nodeFromJSON('baz-value');
    +    var updateThree = nodeFromJSON('new-foo-value');
    +    compoundWrite = compoundWrite.addWrite(new Path('child-1'), updateOne);
    +    compoundWrite = compoundWrite.addWrite(new Path('child-1/baz'), updateTwo);
    +    compoundWrite = compoundWrite.addWrite(new Path('child-1/foo'), updateThree);
    +    compoundWrite = compoundWrite.removeWrite(new Path('child-2'));
    +    var expectedChildOne = {
    +        'foo': 'new-foo-value',
    +        'bar': 'bar-value',
    +        'baz': 'baz-value'
    +    };
    +    var expected = CHILDREN_NODE.updateImmediateChild('child-1', nodeFromJSON(expectedChildOne));
    +    assertNodesEqual(expected, compoundWrite.apply(CHILDREN_NODE));
    +  });
    +
    +  it('can remove priority', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    compoundWrite = compoundWrite.addWrite(new Path('.priority'), PRIO_NODE);
    +    compoundWrite = compoundWrite.removeWrite(new Path('.priority'));
    +    assertNodeGetsCorrectPriority(compoundWrite, LEAF_NODE, EMPTY_NODE);
    +  });
    +
    +  it('removing only affects removed path', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    var updates = {
    +        'child-1': nodeFromJSON('new-value-1'),
    +        'child-2': EMPTY_NODE,
    +        'child-3': nodeFromJSON('value-3')
    +    };
    +    compoundWrite = compoundWrite.addWrites(Path.Empty, updates);
    +    compoundWrite = compoundWrite.removeWrite(new Path('child-2'));
    +
    +    var expected = {
    +        'child-1': 'new-value-1',
    +        'child-2': 'value-2',
    +        'child-3': 'value-3'
    +    };
    +    assertNodesEqual(nodeFromJSON(expected), compoundWrite.apply(CHILDREN_NODE));
    +  });
    +
    +  it('remove removes all deeper sets', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    var updateTwo = nodeFromJSON('baz-value');
    +    var updateThree = nodeFromJSON('new-foo-value');
    +    compoundWrite = compoundWrite.addWrite(new Path('child-1/baz'), updateTwo);
    +    compoundWrite = compoundWrite.addWrite(new Path('child-1/foo'), updateThree);
    +    compoundWrite = compoundWrite.removeWrite(new Path('child-1'));
    +    assertNodesEqual(CHILDREN_NODE, compoundWrite.apply(CHILDREN_NODE));
    +  });
    +
    +  it('remove at root also removes priority', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    compoundWrite = compoundWrite.addWrite(Path.Empty, new LeafNode('foo', PRIO_NODE));
    +    compoundWrite = compoundWrite.removeWrite(Path.Empty);
    +    var node = nodeFromJSON('value');
    +    assertNodeGetsCorrectPriority(compoundWrite, node, EMPTY_NODE);
    +  });
    +
    +  it('updating priority doesnt overwrite leaf node', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    compoundWrite = compoundWrite.addWrite(Path.Empty, LEAF_NODE);
    +    compoundWrite = compoundWrite.addWrite(new Path('child/.priority'), PRIO_NODE);
    +    assertNodesEqual(LEAF_NODE, compoundWrite.apply(EMPTY_NODE));
    +  });
    +
    +  it("updating empty node doesn't overwrite leaf node", function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    compoundWrite = compoundWrite.addWrite(Path.Empty, LEAF_NODE);
    +    compoundWrite = compoundWrite.addWrite(new Path('child'), EMPTY_NODE);
    +    assertNodesEqual(LEAF_NODE, compoundWrite.apply(EMPTY_NODE));
    +  });
    +
    +  it('Overwrites existing child', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    var path = new Path('child-1');
    +    compoundWrite = compoundWrite.addWrite(path, LEAF_NODE);
    +    expect(compoundWrite.apply(CHILDREN_NODE)).to.deep.equal(CHILDREN_NODE.updateImmediateChild(path.getFront(), LEAF_NODE));
    +  });
    +
    +  it('Updates existing child', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    var path = new Path('child-1/foo');
    +    compoundWrite = compoundWrite.addWrite(path, LEAF_NODE);
    +    expect(compoundWrite.apply(CHILDREN_NODE)).to.deep.equal(CHILDREN_NODE.updateChild(path, LEAF_NODE));
    +  });
    +
    +  it("Doesn't update priority on empty node.", function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    compoundWrite = compoundWrite.addWrite(new Path('.priority'), PRIO_NODE);
    +    assertNodeGetsCorrectPriority(compoundWrite, EMPTY_NODE, EMPTY_NODE);
    +  });
    +
    +  it('Updates priority on node', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    compoundWrite = compoundWrite.addWrite(new Path('.priority'), PRIO_NODE);
    +    var node = nodeFromJSON('value');
    +    assertNodeGetsCorrectPriority(compoundWrite, node, PRIO_NODE);
    +  });
    +
    +  it('Updates priority of child', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    var path = new Path('child-1/.priority');
    +    compoundWrite = compoundWrite.addWrite(path, PRIO_NODE);
    +    assertNodesEqual(CHILDREN_NODE.updateChild(path, PRIO_NODE), compoundWrite.apply(CHILDREN_NODE));
    +  });
    +
    +  it("Doesn't update priority of nonexistent child.", function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    var path = new Path('child-3/.priority');
    +    compoundWrite = compoundWrite.addWrite(path, PRIO_NODE);
    +    assertNodesEqual(CHILDREN_NODE, compoundWrite.apply(CHILDREN_NODE));
    +  });
    +
    +  it('Deep update existing updates', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    var updateOne = nodeFromJSON({ 'foo': 'foo-value', 'bar': 'bar-value' });
    +    var updateTwo = nodeFromJSON('baz-value');
    +    var updateThree = nodeFromJSON('new-foo-value');
    +    compoundWrite = compoundWrite.addWrite(new Path('child-1'), updateOne);
    +    compoundWrite = compoundWrite.addWrite(new Path('child-1/baz'), updateTwo);
    +    compoundWrite = compoundWrite.addWrite(new Path('child-1/foo'), updateThree);
    +    var expectedChildOne = {
    +        'foo': 'new-foo-value',
    +        'bar': 'bar-value',
    +        'baz': 'baz-value'
    +    };
    +    var expected = CHILDREN_NODE.updateImmediateChild('child-1', nodeFromJSON(expectedChildOne));
    +    assertNodesEqual(expected, compoundWrite.apply(CHILDREN_NODE));
    +  });
    +
    +  it("child priority doesn't update empty node priority on child merge", function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    compoundWrite = compoundWrite.addWrite(new Path('child-1/.priority'), PRIO_NODE);
    +    assertNodeGetsCorrectPriority(compoundWrite.childCompoundWrite(new Path('child-1')), EMPTY_NODE, EMPTY_NODE);
    +  });
    +
    +  it('Child priority updates priority on child write', function() {
    +    var compoundWrite = CompoundWrite.Empty;
    +    compoundWrite = compoundWrite.addWrite(new Path('child-1/.priority'), PRIO_NODE);
    +    var node = nodeFromJSON('value');
    +    assertNodeGetsCorrectPriority(compoundWrite.childCompoundWrite(new Path('child-1')), node, PRIO_NODE);
    +  });
    +});
    \ No newline at end of file
    diff --git a/tests/database/database.test.ts b/tests/database/database.test.ts
    new file mode 100644
    index 00000000000..3514be58b45
    --- /dev/null
    +++ b/tests/database/database.test.ts
    @@ -0,0 +1,92 @@
    +import { expect } from "chai";
    +import firebase from "../../src/app";
    +import { 
    +  TEST_PROJECT,
    +  patchFakeAuthFunctions,
    +} from "./helpers/util";
    +import "../../src/database";
    +
    +describe('Database Tests', function() {
    +  var defaultApp;
    +
    +  beforeEach(function() {
    +    defaultApp = firebase.initializeApp({databaseURL: TEST_PROJECT.databaseURL});
    +    patchFakeAuthFunctions(defaultApp);
    +  });
    +
    +  afterEach(function() {
    +    return defaultApp.delete();
    +  });
    +
    +  it('Can get database.', function() {
    +    var db = firebase.database();
    +    expect(db).to.not.be.undefined;
    +    expect(db).not.to.be.null;
    +  });
    +
    +  it('Illegal to call constructor', function() {
    +    expect(function() {
    +      var db = new firebase.database.Database('url');
    +    }).to.throw(/don't call new Database/i);
    +  });
    +
    +  it('Can get app', function() {
    +    var db = firebase.database();
    +    expect(db.app).to.not.be.undefined;
    +    expect((db.app as any) instanceof firebase.app.App);
    +  });
    +
    +  it('Can get root ref', function() {
    +    var db = firebase.database();
    +
    +    var ref = db.ref();
    +
    +    expect(ref instanceof firebase.database.Reference).to.be.true;
    +    expect(ref.key).to.be.null;
    +  });
    +
    +  it('Can get child ref', function() {
    +    var db = firebase.database();
    +
    +    var ref = db.ref('child');
    +
    +    expect(ref instanceof firebase.database.Reference).to.be.true;
    +    expect(ref.key).to.equal('child');
    +  });
    +
    +  it('Can get deep child ref', function() {
    +    var db = firebase.database();
    +
    +    var ref = db.ref('child/grand-child');
    +
    +    expect(ref instanceof firebase.database.Reference).to.be.true;
    +    expect(ref.key).to.equal('grand-child');
    +  });
    +
    +  it('ref() validates arguments', function() {
    +    var db = firebase.database();
    +    expect(function() {
    +      var ref = (db as any).ref('path', 'extra');
    +    }).to.throw(/Expects no more than 1/);
    +  });
    +
    +  it('Can get refFromURL()', function() {
    +    var db = firebase.database();
    +    var ref = db.refFromURL(TEST_PROJECT.databaseURL + '/path/to/data');
    +    expect(ref.key).to.equal('data');
    +  });
    +
    +  it('refFromURL() validates domain', function() {
    +    var db = firebase.database();
    +    expect(function() {
    +      var ref = db.refFromURL('https://thisisnotarealfirebase.firebaseio.com/path/to/data');
    +    }).to.throw(/does not match.*database/i);
    +  });
    +
    +  it('refFromURL() validates argument', function() {
    +    var db = firebase.database();
    +    expect(function() {
    +      var ref = (db as any).refFromURL();
    +    }).to.throw(/Expects at least 1/);
    +  });
    +});
    diff --git a/tests/database/datasnapshot.test.ts b/tests/database/datasnapshot.test.ts
    new file mode 100644
    index 00000000000..fbf6a1ba847
    --- /dev/null
    +++ b/tests/database/datasnapshot.test.ts
    @@ -0,0 +1,209 @@
    +import { expect } from "chai";
    +import { nodeFromJSON } from "../../src/database/core/snap/nodeFromJSON";
    +import { PRIORITY_INDEX } from "../../src/database/core/snap/indexes/PriorityIndex";
    +import { getRandomNode } from "./helpers/util";
    +import { DataSnapshot } from "../../src/database/api/DataSnapshot";
    +import { Reference } from "../../src/database/api/Reference";
    +
    +describe("DataSnapshot Tests", function () {
    +  /** @return {!DataSnapshot} */
    +  var snapshotForJSON = function(json) {
    +    var dummyRef = <Reference>getRandomNode();
    +    return new DataSnapshot(nodeFromJSON(json), dummyRef, PRIORITY_INDEX);
    +  };
    +
    +  it("DataSnapshot.hasChildren() works.", function() {
    +    var snap = snapshotForJSON({});
    +    expect(snap.hasChildren()).to.equal(false);
    +
    +    snap = snapshotForJSON(5);
    +    expect(snap.hasChildren()).to.equal(false);
    +
    +    snap = snapshotForJSON({'x': 5});
    +    expect(snap.hasChildren()).to.equal(true);
    +  });
    +
    +  it("DataSnapshot.exists() works.", function() {
    +    var snap = snapshotForJSON({});
    +    expect(snap.exists()).to.equal(false);
    +
    +    snap = snapshotForJSON({ '.priority':1 });
    +    expect(snap.exists()).to.equal(false);
    +
    +    snap = snapshotForJSON(null);
    +    expect(snap.exists()).to.equal(false);
    +
    +    snap = snapshotForJSON(true);
    +    expect(snap.exists()).to.equal(true);
    +
    +    snap = snapshotForJSON(5);
    +    expect(snap.exists()).to.equal(true);
    +
    +    snap = snapshotForJSON({'x': 5});
    +    expect(snap.exists()).to.equal(true);
    +  });
    +
    +  it("DataSnapshot.val() works.", function() {
    +    var snap = snapshotForJSON(5);
    +    expect(snap.val()).to.equal(5);
    +
    +    snap = snapshotForJSON({ });
    +    expect(snap.val()).to.equal(null);
    +
    +    var json =
    +    {
    +      x: 5,
    +      y: {
    +        ya: 1,
    +        yb: 2,
    +        yc: { yca: 3 }
    +      }
    +    };
    +    snap = snapshotForJSON(json);
    +    expect(snap.val()).to.deep.equal(json);
    +  });
    +
    +  it("DataSnapshot.child() works.", function() {
    +    var snap = snapshotForJSON({x: 5, y: { yy: 3, yz: 4}});
    +    expect(snap.child('x').val()).to.equal(5);
    +    expect(snap.child('y').val()).to.deep.equal({yy: 3, yz: 4});
    +    expect(snap.child('y').child('yy').val()).to.equal(3);
    +    expect(snap.child('y/yz').val()).to.equal(4);
    +    expect(snap.child('z').val()).to.equal(null);
    +    expect(snap.child('x/y').val()).to.equal(null);
    +    expect(snap.child('x').child('y').val()).to.equal(null)
    +  });
    +
    +  it("DataSnapshot.hasChild() works.", function() {
    +    var snap = snapshotForJSON({x: 5, y: { yy: 3, yz: 4}});
    +    expect(snap.hasChild('x')).to.equal(true);
    +    expect(snap.hasChild('y/yy')).to.equal(true);
    +    expect(snap.hasChild('dinosaur')).to.equal(false);
    +    expect(snap.child('x').hasChild('anything')).to.equal(false);
    +    expect(snap.hasChild('x/anything/at/all')).to.equal(false);
    +  });
    +
    +  it("DataSnapshot.key works.", function() {
    +    var snap = snapshotForJSON({a: { b: { c: 5 }}});
    +    expect(snap.child('a').key).to.equal('a');
    +    expect(snap.child('a/b/c').key).to.equal('c');
    +    expect(snap.child('/a/b/c/').key).to.equal('c');
    +    expect(snap.child('////a////b/c///').key).to.equal('c');
    +    expect(snap.child('///').key).to.equal(snap.key);
    +
    +    // Should also work for nonexistent paths.
    +    expect(snap.child('/z/q/r/v/m').key).to.equal('m');
    +  });
    +
    +  it("DataSnapshot.forEach() works: no priorities.", function() {
    +    var snap = snapshotForJSON({a: 1, z: 26, m: 13, n: 14, c: 3, b: 2, e: 5});
    +    var out = '';
    +    snap.forEach(function(child) {
    +      out = out + child.key + ':' + child.val() + ':';
    +    });
    +
    +    expect(out).to.equal('a:1:b:2:c:3:e:5:m:13:n:14:z:26:');
    +  });
    +
    +  it("DataSnapshot.forEach() works: numeric priorities.", function() {
    +    var snap = snapshotForJSON({
    +      a: {'.value': 1, '.priority': 26},
    +      z: {'.value': 26, '.priority': 1},
    +      m: {'.value': 13, '.priority': 14},
    +      n: {'.value': 14, '.priority': 12},
    +      c: {'.value': 3, '.priority': 24},
    +      b: {'.value': 2, '.priority': 25},
    +      e: {'.value': 5, '.priority': 22}});
    +
    +    var out = '';
    +    snap.forEach(function(child) {
    +      out = out + child.key + ':' + child.val() + ':';
    +    });
    +
    +    expect(out).to.equal('z:26:n:14:m:13:e:5:c:3:b:2:a:1:');
    +  });
    +
    +  it("DataSnapshot.forEach() works: numeric priorities as strings.", function() {
    +    var snap = snapshotForJSON({
    +      a: {'.value': 1, '.priority': '26'},
    +      z: {'.value': 26, '.priority': '1'},
    +      m: {'.value': 13, '.priority': '14'},
    +      n: {'.value': 14, '.priority': '12'},
    +      c: {'.value': 3, '.priority': '24'},
    +      b: {'.value': 2, '.priority': '25'},
    +      e: {'.value': 5, '.priority': '22'}});
    +
    +    var out = '';
    +    snap.forEach(function(child) {
    +      out = out + child.key + ':' + child.val() + ':';
    +    });
    +
    +    expect(out).to.equal('z:26:n:14:m:13:e:5:c:3:b:2:a:1:');
    +  });
    +
    +  it("DataSnapshot.forEach() works: alpha priorities.", function() {
    +    var snap = snapshotForJSON({
    +      a: {'.value': 1, '.priority': 'first'},
    +      z: {'.value': 26, '.priority': 'second'},
    +      m: {'.value': 13, '.priority': 'third'},
    +      n: {'.value': 14, '.priority': 'fourth'},
    +      c: {'.value': 3, '.priority': 'fifth'},
    +      b: {'.value': 2, '.priority': 'sixth'},
    +      e: {'.value': 5, '.priority': 'seventh'}});
    +
    +    var out = '';
    +    snap.forEach(function(child) {
    +      out = out + child.key + ':' + child.val() + ':';
    +    });
    +
    +    expect(out).to.equal('c:3:a:1:n:14:z:26:e:5:b:2:m:13:');
    +  });
    +
    +  it("DataSnapshot.foreach() works: mixed alpha and numeric priorities", function() {
    +    var json = {
    +      "alpha42": {'.value': 1, '.priority': "zed" },
    +      "noPriorityC": {'.value': 1, '.priority': null },
    +      "num41": {'.value': 1, '.priority': 500 },
    +      "noPriorityB": {'.value': 1, '.priority': null },
    +      "num80": {'.value': 1, '.priority': 4000.1 },
    +      "num50": {'.value': 1, '.priority': 4000 },
    +      "num10": {'.value': 1, '.priority': 24 },
    +      "alpha41": {'.value': 1, '.priority': "zed" },
    +      "alpha20": {'.value': 1, '.priority': "horse" },
    +      "num20": {'.value': 1, '.priority': 123 },
    +      "num70": {'.value': 1, '.priority': 4000.01 },
    +      "noPriorityA": {'.value': 1, '.priority': null },
    +      "alpha30": {'.value': 1, '.priority': "tree" },
    +      "num30": {'.value': 1, '.priority': 300 },
    +      "num60": {'.value': 1, '.priority': 4000.001 },
    +      "alpha10": {'.value': 1, '.priority': "0horse" },
    +      "num42": {'.value': 1, '.priority': 500 },
    +      "alpha40": {'.value': 1, '.priority': "zed" },
    +      "num40": {'.value': 1, '.priority': 500 } };
    +
    +    var snap = snapshotForJSON(json);
    +    var out = '';
    +    snap.forEach(function(child) {
    +      out = out + child.key + ', ';
    +    });
    +
    +    expect(out).to.equal("noPriorityA, noPriorityB, noPriorityC, num10, num20, num30, num40, num41, num42, num50, num60, num70, num80, alpha10, alpha20, alpha30, alpha40, alpha41, alpha42, ");
    +  });
    +
    +  it(".val() exports array-like data as arrays.", function() {
    +    var array = ['bob', 'and', 'becky', 'seem', 'really', 'nice', 'yeah?'];
    +    var snap = snapshotForJSON(array);
    +    var snapVal = snap.val();
    +    expect(snapVal).to.deep.equal(array);
    +    expect(snapVal instanceof Array).to.equal(true); // to.equal doesn't verify type.
    +  });
    +
    +  it("DataSnapshot can be JSON serialized", function() {
    +    var json = {
    +      "foo": "bar",
    +      ".priority": 1
    +    };
    +    var snap = snapshotForJSON(json);
    +    expect(JSON.parse(JSON.stringify(snap))).to.deep.equal(json);
    +  });
    +});
    diff --git a/tests/database/helpers/EventAccumulator.ts b/tests/database/helpers/EventAccumulator.ts
    new file mode 100644
    index 00000000000..8a2ad2ec635
    --- /dev/null
    +++ b/tests/database/helpers/EventAccumulator.ts
    @@ -0,0 +1,53 @@
    +export const EventAccumulatorFactory = {
    +  waitsForCount: maxCount => {
    +    let count = 0;
    +    const condition = () => ea.eventData.length >= count;
    +    const ea = new EventAccumulator(condition)
    +    ea.onReset(() => { count = 0; });
    +    ea.onEvent(() => { count++; });
    +    return ea;
    +  }
    +}
    +
    +export class EventAccumulator {
    +  public eventData = [];
    +  public promise;
    +  public resolve;
    +  public reject;
    +  private onResetFxn;
    +  private onEventFxn;
    +  constructor(public condition: Function) {
    +    this.promise = new Promise((resolve, reject) => {
    +      this.resolve = resolve;
    +      this.reject = reject;
    +    });
    +  }
    +  addEvent(eventData?: any) {
    +    this.eventData = [
    +      ...this.eventData,
    +      eventData
    +    ];
    +    if (typeof this.onEventFxn === 'function') this.onEventFxn();
    +    if (this._testCondition()) {
    +      this.resolve(this.eventData);
    +    }
    +  }
    +  reset(condition?: Function) {
    +    this.eventData = [];
    +    this.promise = new Promise((resolve, reject) => {
    +      this.resolve = resolve;
    +      this.reject = reject;
    +    });
    +    if (typeof this.onResetFxn === 'function') this.onResetFxn();
    +    if (typeof condition === 'function') this.condition = condition;
    +  }
    +  onEvent(cb: Function) {
    +    this.onEventFxn = cb;
    +  }
    +  onReset(cb: Function) {
    +    this.onResetFxn = cb;
    +  }
    +  _testCondition() {
    +    return this.condition();
    +  }
    +}
    \ No newline at end of file
    diff --git a/tests/database/helpers/events.ts b/tests/database/helpers/events.ts
    new file mode 100644
    index 00000000000..d5a8079840c
    --- /dev/null
    +++ b/tests/database/helpers/events.ts
    @@ -0,0 +1,215 @@
    +import { TEST_PROJECT } from "./util";
    +
    +/**
    + * A set of functions to clean up event handlers.
    + * @type {function()}
    + */
    +export let eventCleanupHandlers = [];
    +
    +
    +/** Clean up outstanding event handlers */
    +export function eventCleanup() {
    +  for (var i = 0; i < eventCleanupHandlers.length; ++i) {
    +    eventCleanupHandlers[i]();
    +  }
    +  eventCleanupHandlers = [];
    +};
    +
    +/**
    + * The path component of the firebaseRef url
    + * @param {Firebase} firebaseRef
    + * @return {string}
    + */
    +function rawPath(firebaseRef) {
    +  return firebaseRef.toString().replace(TEST_PROJECT.databaseURL, '');
    +};
    +
    +/**
    + * Creates a struct which waits for many events.
    + * @param {Array<Array>} pathAndEvents an array of tuples of [Firebase, [event type strings]]
    + * @param {string=} opt_helperName
    + * @return {{waiter: waiter, watchesInitializedWaiter: watchesInitializedWaiter, unregister: unregister, addExpectedEvents: addExpectedEvents}}
    + */
    +export function eventTestHelper(pathAndEvents, helperName?) {
    +  let resolve, reject;
    +  let promise = new Promise((pResolve, pReject) => {
    +    resolve = pResolve;
    +    reject = pReject;
    +  });
    +  let resolveInit, rejectInit;
    +  const initPromise = new Promise((pResolve, pReject) => {
    +    resolveInit = pResolve;
    +    rejectInit = pReject;
    +  });
    +  var expectedPathAndEvents = [];
    +  var actualPathAndEvents = [];
    +  var pathEventListeners = {};
    +  var initializationEvents = 0;
    +
    +  helperName = helperName ? helperName + ': ' : '';
    +
    +  // Listen on all of the required paths, with a callback function that just
    +  // appends to actualPathAndEvents.
    +  var make_eventCallback = function(type) {
    +    return function(snap) {
    +      // Get the ref of where the snapshot came from.
    +      var ref = type === 'value' ? snap.ref : snap.ref.parent;
    +
    +      actualPathAndEvents.push([rawPath(ref), [type, snap.key]]);
    +
    +      if (!pathEventListeners[ref].initialized) {
    +        initializationEvents++;
    +        if (type === 'value') {
    +          pathEventListeners[ref].initialized = true;
    +        }
    +      } else {
    +        // Call waiter here to trigger exceptions when the event is fired, rather than later when the
    +        // test framework is calling the waiter...  makes for easier debugging.
    +        waiter();
    +      }
    +
    +      // We want to trigger the promise resolution if valid, so try to call waiter as events
    +      // are coming back.
    +      try {
    +        if (waiter()) {
    +          resolve();
    +        }
    +      } catch(e) {}
    +    };
    +  };
    +
    +  // returns a function which indicates whether the events have been received
    +  // in the correct order.  If anything is wrong (too many events or
    +  // incorrect events, we throw).  Else we return false, indicating we should
    +  // keep waiting.
    +  var waiter = function() {
    +    var pathAndEventToString = function(pathAndEvent) {
    +      return '{path: ' + pathAndEvent[0] + ', event:[' + pathAndEvent[1][0] + ', ' + pathAndEvent[1][1] + ']}';
    +    };
    +
    +    var i = 0;
    +    while (i < expectedPathAndEvents.length && i < actualPathAndEvents.length) {
    +      var expected = expectedPathAndEvents[i];
    +      var actual = actualPathAndEvents[i];
    +
    +      if (expected[0] != actual[0] || expected[1][0] != actual[1][0] || expected[1][1] != actual[1][1]) {
    +        throw helperName + 'Event ' + i + ' incorrect. Expected: ' + pathAndEventToString(expected) +
    +            ' Actual: ' + pathAndEventToString(actual);
    +      }
    +      i++;
    +    }
    +
    +    if (expectedPathAndEvents.length < actualPathAndEvents.length) {
    +      throw helperName + "Extra event detected '" + pathAndEventToString(actualPathAndEvents[i]) + "'.";
    +    }
    +
    +    // If we haven't thrown and both arrays are the same length, then we're
    +    // done.
    +    return expectedPathAndEvents.length == actualPathAndEvents.length;
    +  };
    +
    +  var listenOnPath = function(path) {
    +    var valueCB = make_eventCallback('value');
    +    var addedCB = make_eventCallback('child_added');
    +    var removedCB = make_eventCallback('child_removed');
    +    var movedCB = make_eventCallback('child_moved');
    +    var changedCB = make_eventCallback('child_changed');
    +    path.on('child_removed', removedCB);
    +    path.on('child_added', addedCB);
    +    path.on('child_moved', movedCB);
    +    path.on('child_changed', changedCB);
    +    path.on('value', valueCB);
    +    return function() {
    +      path.off('child_removed', removedCB);
    +      path.off('child_added', addedCB);
    +      path.off('child_moved', movedCB);
    +      path.off('child_changed', changedCB);
    +      path.off('value', valueCB);
    +    }
    +  };
    +
    +
    +  var addExpectedEvents = function(pathAndEvents) {
    +    var pathsToListenOn = [];
    +    for (var i = 0; i < pathAndEvents.length; i++) {
    +
    +      var pathAndEvent = pathAndEvents[i];
    +
    +      var path = pathAndEvent[0];
    +      //var event = pathAndEvent[1];
    +
    +      pathsToListenOn.push(path);
    +
    +      pathAndEvent[0] = rawPath(path);
    +
    +      if (pathAndEvent[1][0] === 'value')
    +        pathAndEvent[1][1] = path.key;
    +
    +      expectedPathAndEvents.push(pathAndEvent);
    +    }
    +
    +    // There's some trickiness with event order depending on the order you attach event callbacks:
    +    //
    +    // When you listen on a/b/c, a/b, and a, we dedupe that to just listening on a.  But if you do it in that
    +    // order, we'll send "listen a/b/c, listen a/b, unlisten a/b/c, listen a, unlisten a/b" which will result in you
    +    // getting events something like "a/b/c: value, a/b: child_added c, a: child_added b, a/b: value, a: value"
    +    //
    +    // BUT, if all of the listens happen before you are connected to firebase (e.g. this is the first test you're
    +    // running), the dedupe will have taken affect and we'll just send "listen a", which results in:
    +    // "a/b/c: value, a/b: child_added c, a/b: value, a: child_added b, a: value"
    +    // Notice the 3rd and 4th events are swapped.
    +    // To mitigate this, we re-ordeer your event registrations and do them in order of shortest path to longest.
    +
    +    pathsToListenOn.sort(function(a, b) { return a.toString().length - b.toString().length; });
    +    for (i = 0; i < pathsToListenOn.length; i++) {
    +      path = pathsToListenOn[i];
    +      if (!pathEventListeners[path.toString()]) {
    +        pathEventListeners[path.toString()] = { };
    +        pathEventListeners[path.toString()].initialized = false;
    +        pathEventListeners[path.toString()].unlisten = listenOnPath(path);
    +      }
    +    }
    +
    +    promise = new Promise((pResolve, pReject) => {
    +      resolve = pResolve;
    +      reject = pReject;
    +    });
    +  };
    +
    +  addExpectedEvents(pathAndEvents);
    +
    +  var watchesInitializedWaiter = function() {
    +    for (var path in pathEventListeners) {
    +      if (!pathEventListeners[path].initialized)
    +        return false;
    +    }
    +
    +    // Remove any initialization events.
    +    actualPathAndEvents.splice(actualPathAndEvents.length - initializationEvents, initializationEvents);
    +    initializationEvents = 0;
    +
    +    resolveInit();
    +    return true;
    +  };
    +
    +  var unregister = function() {
    +    for (var path in pathEventListeners) {
    +      if (pathEventListeners.hasOwnProperty(path)) {
    +        pathEventListeners[path].unlisten();
    +      }
    +    }
    +  };
    +
    +  eventCleanupHandlers.push(unregister);
    +  return {
    +    promise,
    +    initPromise,
    +    waiter,
    +    watchesInitializedWaiter,
    +    unregister,
    +
    +    addExpectedEvents: function(moreEvents) {
    +      addExpectedEvents(moreEvents);
    +    }
    +  };
    +};
    \ No newline at end of file
    diff --git a/tests/database/helpers/util.ts b/tests/database/helpers/util.ts
    new file mode 100644
    index 00000000000..67ee1b1398c
    --- /dev/null
    +++ b/tests/database/helpers/util.ts
    @@ -0,0 +1,223 @@
    +import { globalScope } from "../../../src/utils/globalScope";
    +import firebase from "../../../src/app";
    +import '../../../src/database';
    +import { Reference } from "../../../src/database/api/Reference";
    +import { Query } from "../../../src/database/api/Query";
    +import { expect } from "chai";
    +import { ConnectionTarget } from "../../../src/database/api/test_access";
    +
    +
    +export const TEST_PROJECT = require('../../config/project.json');
    +
    +var qs = {};
    +if ('location' in this) {
    +  var search = (this.location.search.substr(1) || '').split('&');
    +  for (var i = 0; i < search.length; ++i) {
    +    var parts = search[i].split('=');
    +    qs[parts[0]] = parts[1] || true;  // support for foo=
    +  }
    +}
    +
    +let numDatabases = 0;
    +
    +/**
    + * Fake Firebase App Authentication functions for testing.
    + * @param {!FirebaseApp} app
    + * @return {!FirebaseApp}
    + */
    +export function patchFakeAuthFunctions(app) {
    +  var token_ = null;
    +
    +  app['INTERNAL'] = app['INTERNAL'] || {};
    +
    +  app['INTERNAL']['getToken'] = function(forceRefresh) {
    +    return Promise.resolve(token_);
    +  };
    +
    +  app['INTERNAL']['addAuthTokenListener'] = function(listener) {
    +  };
    +
    +  app['INTERNAL']['removeAuthTokenListener'] = function(listener) {
    +  };
    +
    +  return app;
    +};
    +
    +/**
    + * Gets or creates a root node to the test namespace. All calls sharing the
    + * value of opt_i will share an app context.
    + * @param {=} opt_i
    + * @param {string=} opt_ref
    + * @return {Firebase}
    + */
    +export function getRootNode(i?, ref?) {
    +  if (i === undefined) {
    +    i = 0;
    +  }
    +  if (i + 1 > numDatabases) {
    +    numDatabases = i + 1;
    +  }
    +  var app;
    +  var db;
    +  try {
    +    app = firebase.app("TEST-" + i);
    +  } catch(e) {
    +    app = firebase.initializeApp({ databaseURL: TEST_PROJECT.databaseURL }, "TEST-" + i);
    +    patchFakeAuthFunctions(app);
    +  }
    +  db = app.database();
    +  return db.ref(ref);
    +};
    +
    +/**
    + * Create multiple refs to the same top level
    + * push key - each on it's own Firebase.Context.
    + * @param {int=} opt_numNodes
    + * @return {Firebase|Array<Firebase>}
    + */
    +export function getRandomNode(numNodes?): Reference | Array<Reference> {
    +  if (numNodes === undefined) {
    +    return <Reference>getRandomNode(1)[0];
    +  }
    +
    +  var child;
    +  var nodeList = [];
    +  for (var i = 0; i < numNodes; i++) {
    +    var ref = getRootNode(i);
    +    if (child === undefined) {
    +      child = ref.push().key;
    +    }
    +
    +    nodeList[i] = ref.child(child);
    +  }
    +
    +  return <Array<Reference>>nodeList;
    +};
    +
    +export function getQueryValue(query: Query) {
    +  return query.once('value').then(snap => snap.val());
    +}
    +
    +export function pause(milliseconds: number) {
    +  return new Promise(resolve => {
    +    setTimeout(() => resolve(), milliseconds);
    +  });
    +}
    +
    +export function getPath(query: Query) {
    +  return query.toString().replace(TEST_PROJECT.databaseURL, '');
    +}
    +
    +export function shuffle(arr, randFn?) {
    +  var randFn = randFn || Math.random;
    +  for (var i = arr.length - 1;i > 0;i--) {
    +    var j = Math.floor(randFn() * (i + 1));
    +    var tmp = arr[i];
    +    arr[i] = arr[j];
    +    arr[j] = tmp;
    +  }
    +}
    +
    +export function testAuthTokenProvider(app) {
    +  var token_ = null;
    +  var nextToken_ = null;
    +  var hasNextToken_ = false;
    +  var listeners_  = [];
    +
    +  app['INTERNAL'] = app['INTERNAL'] || {};
    +
    +  app['INTERNAL']['getToken'] = function(forceRefresh) {
    +    if (forceRefresh && hasNextToken_) {
    +      token_ = nextToken_;
    +      hasNextToken_ = false;
    +    }
    +    return Promise.resolve({accessToken: token_});
    +  };
    +
    +  app['INTERNAL']['addAuthTokenListener'] = function(listener) {
    +    var token = token_;
    +    listeners_.push(listener);
    +    var async = Promise.resolve();
    +    async.then(function() {
    +      listener(token)
    +    });
    +  };
    +
    +  app['INTERNAL']['removeAuthTokenListener'] = function(listener) {
    +    throw Error('removeAuthTokenListener not supported in testing');
    +  };
    +
    +  return {
    +    setToken: function(token) {
    +      token_ = token;
    +      var async = Promise.resolve();
    +      for (var i = 0; i < listeners_.length; i++) {
    +        async.then((function(idx) {
    +          return function() {
    +            listeners_[idx](token);
    +          }
    +        }(i)));
    +      }
    +
    +      // Any future thens are guaranteed to be resolved after the listeners have been notified
    +      return async;
    +    },
    +    setNextToken: function(token) {
    +      nextToken_ = token;
    +      hasNextToken_ = true;
    +    }
    +  };
    +}
    +
    +let freshRepoId = 1;
    +const activeFreshApps = [];
    +
    +export function getFreshRepo(url, path?) {
    +  var app = firebase.initializeApp({databaseURL: url}, 'ISOLATED_REPO_' + freshRepoId++);
    +  patchFakeAuthFunctions(app);
    +  activeFreshApps.push(app);
    +  return app.database().ref(path);
    +}
    +
    +export function getFreshRepoFromReference(ref) {
    +  var host = ref.root.toString();
    +  var path = ref.toString().replace(host, '');
    +  return getFreshRepo(host, path);
    +}
    +
    +// Little helpers to get the currently cached snapshot / value.
    +export function getSnap(path) {
    +  var snap;
    +  var callback = function(snapshot) { snap = snapshot; };
    +  path.once('value', callback);
    +  return snap;
    +};
    +
    +export function getVal(path) {
    +  var snap = getSnap(path);
    +  return snap ? snap.val() : undefined;
    +};
    +
    +export function canCreateExtraConnections() {
    +  return globalScope.MozWebSocket || globalScope.WebSocket;
    +};
    +
    +export function buildObjFromKey(key) {
    +  var keys = key.split('.');
    +  var obj = {};
    +  var parent = obj;
    +  for (var i = 0; i < keys.length; i++) {
    +    var key = keys[i];
    +    parent[key] = i < keys.length - 1 ? {} : 'test_value';
    +    parent = parent[key];
    +  }
    +  return obj;
    +};
    +
    +export function testRepoInfo(url) {
    +  const regex = /https?:\/\/(.*).firebaseio.com/;
    +  const match = url.match(regex);
    +  if (!match) throw new Error('Couldnt get Namespace from passed URL');
    +  const [,ns] = match;
    +  return new ConnectionTarget(`${ns}.firebaseio.com`, true, ns, false);
    +}
    diff --git a/tests/database/info.test.ts b/tests/database/info.test.ts
    new file mode 100644
    index 00000000000..deece96dc98
    --- /dev/null
    +++ b/tests/database/info.test.ts
    @@ -0,0 +1,177 @@
    +import { expect } from "chai";
    +import { 
    +  getFreshRepo,
    +  getRootNode,
    +  getRandomNode,
    +  getPath
    +} from "./helpers/util";
    +import { Reference } from "../../src/database/api/Reference";
    +import { EventAccumulator } from "./helpers/EventAccumulator";
    +
    +/**
    + * We have a test that depends on leveraging two properly
    + * configured Firebase instances. we are skiping the test
    + * but I want to leave the test here for when we can refactor
    + * to remove the prod firebase dependency.
    + */
    +declare var runs;
    +declare var waitsFor;
    +declare var TEST_ALT_NAMESPACE;
    +declare var TEST_NAMESPACE;
    +
    +describe(".info Tests", function () {
    +  it("Can get a reference to .info nodes.", function() {
    +    var f = (getRootNode() as Reference);
    +    expect(getPath(f.child('.info'))).to.equal('/.info');
    +    expect(getPath(f.child('.info/foo'))).to.equal('/.info/foo');
    +  });
    +
    +  it("Can't write to .info", function() {
    +    var f = (getRootNode() as Reference).child('.info');
    +    expect(function() {f.set('hi');}).to.throw;
    +    expect(function() {f.setWithPriority('hi', 5);}).to.throw;
    +    expect(function() {f.setPriority('hi');}).to.throw;
    +    expect(function() {f.transaction(function() { });}).to.throw;
    +    expect(function() {f.push();}).to.throw;
    +    expect(function() {f.remove();}).to.throw;
    +
    +    expect(function() {f.child('test').set('hi');}).to.throw;
    +    var f2 = f.child('foo/baz');
    +    expect(function() {f2.set('hi');}).to.throw;
    +  });
    +
    +  it("Can watch .info/connected.", function() {
    +    return new Promise(resolve => {
    +      var f = (getRandomNode() as Reference).root;
    +      f.child('.info/connected').on('value', function(snap) {
    +        if (snap.val() === true) resolve();
    +      });
    +    })
    +  });
    +
    +
    +  it('.info/connected correctly goes to false when disconnected.', async function() {
    +    var f = (getRandomNode() as Reference).root;
    +    var everConnected = false;
    +    var connectHistory = '';
    +
    +    const ea = new EventAccumulator(() => everConnected);
    +    f.child('.info/connected').on('value', function(snap) {
    +      if (snap.val() === true)
    +        everConnected = true;
    +
    +      if (everConnected)
    +        connectHistory += snap.val() + ',';
    +      ea.addEvent();
    +    });
    +
    +    await ea.promise;
    +
    +    ea.reset(() => connectHistory);
    +    f.database.goOffline();
    +    f.database.goOnline();
    +
    +    return ea.promise;
    +  });
    +
    +  // Skipping this test as it is expecting a server time diff from a
    +  // local Firebase
    +  it.skip(".info/serverTimeOffset", async function() {
    +    var ref = (getRootNode() as Reference);
    +
    +    // make sure push works
    +    var child = ref.push();
    +
    +    var offsets = [];
    +
    +    const ea = new EventAccumulator(() => offsets.length === 1);
    +
    +    ref.child('.info/serverTimeOffset').on('value', function(snap) {
    +      offsets.push(snap.val());
    +      ea.addEvent();
    +    });
    +
    +    await ea.promise;
    +
    +    expect(typeof offsets[0]).to.equal('number');
    +    expect(offsets[0]).not.to.be.greaterThan(0);
    +
    +    // Make sure push still works
    +    ref.push();
    +    ref.child('.info/serverTimeOffset').off();
    +  });
    +
    +  it.skip("database.goOffline() / database.goOnline() connection management", function() {
    +    var ref = getFreshRepo(TEST_NAMESPACE);
    +    var refAlt = getFreshRepo(TEST_ALT_NAMESPACE);
    +    var ready;
    +
    +    // Wait until we're connected to both Firebases
    +    runs(function() {
    +      ready = 0;
    +      var eventHandler = function(snap) {
    +        if (snap.val() === true) {
    +          snap.ref.off();
    +          ready += 1;
    +        }
    +      };
    +      ref.child(".info/connected").on("value", eventHandler);
    +      refAlt.child(".info/connected").on("value", eventHandler);
    +    });
    +    waitsFor(function() { return (ready == 2); });
    +
    +    runs(function() {
    +      ref.database.goOffline();
    +      refAlt.database.goOffline();
    +    });
    +
    +    // Ensure we're disconnected from both Firebases
    +    runs(function() {
    +      ready = 0;
    +      var eventHandler = function(snap) {
    +        expect(snap.val() === false);
    +        ready += 1;
    +      }
    +      ref.child(".info/connected").once("value", eventHandler);
    +      refAlt.child(".info/connected").once("value", eventHandler);
    +    });
    +    waitsFor(function() { return (ready == 2); });
    +
    +    // Ensure that we don't automatically reconnect upon Reference creation
    +    runs(function() {
    +      ready = 0;
    +      var refDup = ref.database.ref();
    +      refDup.child(".info/connected").on("value", function(snap) {
    +        ready = (snap.val() === true) || ready;
    +      });
    +      setTimeout(function() {
    +        expect(ready).to.equal(0);
    +        refDup.child(".info/connected").off();
    +        ready = -1;
    +      }, 500);
    +    });
    +    waitsFor(function() { return ready == -1; });
    +
    +    runs(function() {
    +      ref.database.goOnline();
    +      refAlt.database.goOnline();
    +    });
    +
    +    // Ensure we're connected to both Firebases
    +    runs(function() {
    +      ready = 0;
    +      var eventHandler = function(snap) {
    +        if (snap.val() === true) {
    +          snap.ref.off();
    +          ready += 1;
    +        }
    +      };
    +      ref.child(".info/connected").on("value", eventHandler);
    +      refAlt.child(".info/connected").on("value", eventHandler);
    +    });
    +
    +    waitsFor(function() {
    +      return (ready == 2);
    +    });
    +  });
    +});
    diff --git a/tests/database/node.test.ts b/tests/database/node.test.ts
    new file mode 100644
    index 00000000000..6dc26e3e9f5
    --- /dev/null
    +++ b/tests/database/node.test.ts
    @@ -0,0 +1,255 @@
    +import { expect } from "chai";
    +import { PRIORITY_INDEX } from "../../src/database/core/snap/indexes/PriorityIndex";
    +import { LeafNode } from "../../src/database/core/snap/LeafNode";
    +import { IndexMap } from "../../src/database/core/snap/IndexMap";
    +import { Path } from "../../src/database/core/util/Path";
    +import { SortedMap } from "../../src/database/core/util/SortedMap";
    +import { ChildrenNode } from "../../src/database/core/snap/ChildrenNode";
    +import { NAME_COMPARATOR } from "../../src/database/core/snap/comparators";
    +import { nodeFromJSON } from "../../src/database/core/snap/nodeFromJSON";
    +
    +describe('Node Tests', function() {
    +  var DEFAULT_INDEX = PRIORITY_INDEX;
    +
    +  it('Create leaf nodes of various types.', function() {
    +    var x = new LeafNode(5, new LeafNode(42));
    +    expect(x.getValue()).to.equal(5);
    +    expect(x.getPriority().val()).to.equal(42);
    +    expect(x.isLeafNode()).to.equal(true);
    +
    +    x = new LeafNode('test');
    +    expect(x.getValue()).to.equal('test');
    +    x = new LeafNode(true);
    +    expect(x.getValue()).to.equal(true);
    +  });
    +
    +  it("LeafNode.updatePriority returns a new leaf node without changing the old.", function() {
    +    var x = new LeafNode("test", new LeafNode(42));
    +    var y = x.updatePriority(new LeafNode(187));
    +
    +    // old node is the same.
    +    expect(x.getValue()).to.equal("test");
    +    expect(x.getPriority().val()).to.equal(42);
    +
    +    // new node has the new priority but the old value.
    +    expect(y.getValue()).to.equal("test");
    +    expect(y.getPriority().val()).to.equal(187);
    +  });
    +
    +  it("LeafNode.updateImmediateChild returns a new children node.", function() {
    +    var x = new LeafNode("test", new LeafNode(42));
    +    var y = x.updateImmediateChild('test', new LeafNode("foo"));
    +
    +    expect(y.isLeafNode()).to.equal(false);
    +    expect(y.getPriority().val()).to.equal(42);
    +    expect(y.getImmediateChild('test').getValue()).to.equal('foo');
    +  });
    +
    +  it("LeafNode.getImmediateChild returns an empty node.", function() {
    +    var x = new LeafNode("test");
    +    expect(x.getImmediateChild('foo')).to.equal(ChildrenNode.EMPTY_NODE);
    +  });
    +
    +  it("LeafNode.getChild returns an empty node.", function() {
    +    var x = new LeafNode('test');
    +    expect(x.getChild(new Path('foo/bar'))).to.equal(ChildrenNode.EMPTY_NODE);
    +  });
    +
    +  it('ChildrenNode.updatePriority returns a new internal node without changing the old.', function() {
    +    var x = ChildrenNode.EMPTY_NODE.updateImmediateChild("child", new LeafNode(5));
    +    var children = x.children_;
    +    var y = x.updatePriority(new LeafNode(17));
    +    expect(y.children_).to.equal(x.children_);
    +    expect(x.children_).to.equal(children);
    +    expect(x.getPriority().val()).to.equal(null);
    +    expect(y.getPriority().val()).to.equal(17);
    +  });
    +
    +  it('ChildrenNode.updateImmediateChild returns a new internal node with the new child, without changing the old.',
    +      function() {
    +    var children = new SortedMap(NAME_COMPARATOR);
    +    var x = new ChildrenNode(children, ChildrenNode.EMPTY_NODE, IndexMap.Default);
    +    var newValue = new LeafNode('new value');
    +    var y = x.updateImmediateChild('test', newValue);
    +    expect(x.children_).to.equal(children);
    +    expect(y.children_.get('test')).to.equal(newValue);
    +  });
    +
    +  it("ChildrenNode.updateChild returns a new internal node with the new child, without changing the old.", function() {
    +    var children = new SortedMap(NAME_COMPARATOR);
    +    var x = new ChildrenNode(children, ChildrenNode.EMPTY_NODE, IndexMap.Default);
    +    var newValue = new LeafNode("new value");
    +    var y = x.updateChild(new Path('test/foo'), newValue);
    +    expect(x.children_).to.equal(children);
    +    expect(y.getChild(new Path('test/foo'))).to.equal(newValue);
    +  });
    +
    +  it("Node.hash() works correctly.", function() {
    +    var node = nodeFromJSON({
    +      intNode:4,
    +      doubleNode:4.5623,
    +      stringNode:"hey guys",
    +      boolNode:true
    +    });
    +
    +    // !!!NOTE!!! These hashes must match what the server generates.  If you change anything so these hashes change,
    +    // make sure you change the corresponding server code.
    +    expect(node.getImmediateChild("intNode").hash()).to.equal("eVih19a6ZDz3NL32uVBtg9KSgQY=");
    +    expect(node.getImmediateChild("doubleNode").hash()).to.equal("vf1CL0tIRwXXunHcG/irRECk3lY=");
    +    expect(node.getImmediateChild("stringNode").hash()).to.equal("CUNLXWpCVoJE6z7z1vE57lGaKAU=");
    +    expect(node.getImmediateChild("boolNode").hash()).to.equal("E5z61QM0lN/U2WsOnusszCTkR8M=");
    +
    +    expect(node.hash()).to.equal("6Mc4jFmNdrLVIlJJjz2/MakTK9I=");
    +  });
    +
    +  it("Node.hash() works correctly with priorities.", function() {
    +    var node = nodeFromJSON({
    +      root: {c: {'.value': 99, '.priority': 'abc'}, '.priority': 'def'}
    +    });
    +
    +    expect(node.hash()).to.equal("Fm6tzN4CVEu5WxFDZUdTtqbTVaA=");
    +  });
    +
    +  it("Node.hash() works correctly with number priorities.", function() {
    +    var node = nodeFromJSON({
    +      root: {c: {'.value': 99, '.priority': 42}, '.priority': 3.14}
    +    });
    +
    +    expect(node.hash()).to.equal("B15QCqrzCxrI5zz1y00arWqFRFg=");
    +  });
    +
    +  it("Node.hash() stress...", function() {
    +    var node = nodeFromJSON({
    +      a:-1.7976931348623157e+308,
    +      b:1.7976931348623157e+308,
    +      c:"unicode ✔ 🐵 🌴 x͢",
    +      d:3.14159265358979323846264338327950,
    +      e: {
    +        '.value': 12345678901234568,
    +        '.priority': "🐵"
    +      },
    +      "✔": "foo",
    +      '.priority':"✔"
    +    });
    +    expect(node.getImmediateChild('a').hash()).to.equal('7HxgOBDEC92uQwhCuuvKA2rbXDA=');
    +    expect(node.getImmediateChild('b').hash()).to.equal('8R+ekVQmxs6ZWP0fdzFHxVeGnWo=');
    +    expect(node.getImmediateChild('c').hash()).to.equal('JoKoFUnbmg3/DlY70KaDWslfYPk=');
    +    expect(node.getImmediateChild('d').hash()).to.equal('Y41iC5+92GIqXfabOm33EanRI8s=');
    +    expect(node.getImmediateChild('e').hash()).to.equal('+E+Mxlqh5MhT+On05bjsZ6JaaxI=');
    +    expect(node.getImmediateChild('✔').hash()).to.equal('MRRL/+aA/uibaL//jghUpxXS/uY=');
    +    expect(node.hash()).to.equal('CyC0OU8GSkOAKnsPjheWtWC0Yxo=');
    +  });
    +
    +  it("ChildrenNode.getPredecessorChild works correctly.", function() {
    +    var node = nodeFromJSON({
    +      d: true, a: true, g: true, c: true, e: true
    +    });
    +
    +    // HACK: Pass null instead of the actual childNode, since it's not actually needed.
    +    expect(node.getPredecessorChildName('a', null, DEFAULT_INDEX)).to.equal(null);
    +    expect(node.getPredecessorChildName('c', null, DEFAULT_INDEX)).to.equal('a');
    +    expect(node.getPredecessorChildName('d', null, DEFAULT_INDEX)).to.equal('c');
    +    expect(node.getPredecessorChildName('e', null, DEFAULT_INDEX)).to.equal('d');
    +    expect(node.getPredecessorChildName('g', null, DEFAULT_INDEX)).to.equal('e');
    +  });
    +
    +  it("SortedChildrenNode.getPredecessorChild works correctly.", function() {
    +    var node = nodeFromJSON({
    +      d: { '.value': true, '.priority' : 22 },
    +      a: { '.value': true, '.priority' : 25 },
    +      g: { '.value': true, '.priority' : 19 },
    +      c: { '.value': true, '.priority' : 23 },
    +      e: { '.value': true, '.priority' : 21 }
    +    });
    +
    +    expect(node.getPredecessorChildName('a', node.getImmediateChild('a'), DEFAULT_INDEX)).to.equal('c');
    +    expect(node.getPredecessorChildName('c', node.getImmediateChild('c'), DEFAULT_INDEX)).to.equal('d');
    +    expect(node.getPredecessorChildName('d', node.getImmediateChild('d'), DEFAULT_INDEX)).to.equal('e');
    +    expect(node.getPredecessorChildName('e', node.getImmediateChild('e'), DEFAULT_INDEX)).to.equal('g');
    +    expect(node.getPredecessorChildName('g', node.getImmediateChild('g'), DEFAULT_INDEX)).to.equal(null);
    +  });
    +
    +  it("SortedChildrenNode.updateImmediateChild works correctly.", function() {
    +    var node = nodeFromJSON({
    +      d: { '.value': true, '.priority' : 22 },
    +      a: { '.value': true, '.priority' : 25 },
    +      g: { '.value': true, '.priority' : 19 },
    +      c: { '.value': true, '.priority' : 23 },
    +      e: { '.value': true, '.priority' : 21 },
    +      '.priority' : 1000
    +    });
    +
    +    node = node.updateImmediateChild('c', nodeFromJSON(false));
    +    expect(node.getImmediateChild('c').getValue()).to.equal(false);
    +    expect(node.getImmediateChild('c').getPriority().val()).to.equal(null);
    +    expect(node.getPriority().val()).to.equal(1000);
    +  });
    +
    +  it("removing nodes correctly removes intermediate nodes with no remaining children", function() {
    +    var json = {a: {b: {c: 1}}};
    +    var node = nodeFromJSON(json);
    +    var newNode = node.updateChild(new Path('a/b/c'), ChildrenNode.EMPTY_NODE);
    +    expect(newNode.isEmpty()).to.equal(true);
    +  });
    +
    +  it("removing nodes leaves intermediate nodes with other children", function() {
    +    var json = {a: {b: {c: 1}, d: 2}};
    +    var node = nodeFromJSON(json);
    +    var newNode = node.updateChild(new Path('a/b/c'), ChildrenNode.EMPTY_NODE);
    +    expect(newNode.isEmpty()).to.equal(false);
    +    expect(newNode.getChild(new Path('a/b/c')).isEmpty()).to.equal(true);
    +    expect(newNode.getChild(new Path('a/d')).val()).to.equal(2);
    +  });
    +
    +  it("removing nodes leaves other leaf nodes", function() {
    +    var json = {a: {b: {c: 1, d: 2}}};
    +    var node = nodeFromJSON(json);
    +    var newNode = node.updateChild(new Path('a/b/c'), ChildrenNode.EMPTY_NODE);
    +    expect(newNode.isEmpty()).to.equal(false);
    +    expect(newNode.getChild(new Path('a/b/c')).isEmpty()).to.equal(true);
    +    expect(newNode.getChild(new Path('a/b/d')).val()).to.equal(2);
    +  });
    +
    +  it("removing nodes correctly removes the root", function() {
    +    var json = null;
    +    var node = nodeFromJSON(json);
    +    var newNode = node.updateChild(new Path(''), ChildrenNode.EMPTY_NODE);
    +    expect(newNode.isEmpty()).to.equal(true);
    +
    +    json = {a: 1};
    +    node = nodeFromJSON(json);
    +    newNode = node.updateChild(new Path('a'), ChildrenNode.EMPTY_NODE);
    +    expect(newNode.isEmpty()).to.equal(true);
    +  });
    +
    +  it("ignores null values", function() {
    +    var json = {a: 1, b: null};
    +    var node = nodeFromJSON(json);
    +    expect(node.children_.get('b')).to.equal(null);
    +  });
    +
    +  it("Leading zeroes in path are handled properly", function() {
    +    var json = {"1": 1, "01": 2, "001": 3};
    +    var tree = nodeFromJSON(json);
    +    expect(tree.getChild(new Path("1")).val()).to.equal(1);
    +    expect(tree.getChild(new Path("01")).val()).to.equal(2);
    +    expect(tree.getChild(new Path("001")).val()).to.equal(3);
    +  });
    +
    +  it("Treats leading zeroes as objects, not array", function() {
    +    var json = {"3": 1, "03": 2};
    +    var tree = nodeFromJSON(json);
    +    var val = tree.val();
    +    expect(val).to.deep.equal(json);
    +  });
    +
    +  it("Updating empty children doesn't overwrite leaf node", function() {
    +    var empty = ChildrenNode.EMPTY_NODE;
    +    var node = nodeFromJSON("value");
    +    expect(node).to.deep.equal(node.updateChild(new Path(".priority"), empty));
    +    expect(node).to.deep.equal(node.updateChild(new Path("child"), empty));
    +    expect(node).to.deep.equal(node.updateChild(new Path("child/.priority"), empty));
    +    expect(node).to.deep.equal(node.updateImmediateChild("child", empty));
    +    expect(node).to.deep.equal(node.updateImmediateChild(".priority", empty));
    +  });
    +});
    diff --git a/tests/database/node/connection.test.ts b/tests/database/node/connection.test.ts
    new file mode 100644
    index 00000000000..2683dce1c5b
    --- /dev/null
    +++ b/tests/database/node/connection.test.ts
    @@ -0,0 +1,40 @@
    +import { expect } from "chai";
    +import { TEST_PROJECT, testRepoInfo } from "../helpers/util";
    +import { Connection } from "../../../src/database/realtime/Connection";
    +import "../../../src/utils/nodePatches";
    +
    +describe('Connection', () => {
    +  it('return the session id', function(done) {
    +    new Connection('1',
    +        testRepoInfo(TEST_PROJECT.databaseURL),
    +        message => {},
    +        (timestamp, sessionId) => {
    +          expect(sessionId).not.to.be.null;
    +          expect(sessionId).not.to.equal('');
    +          done();
    +        },
    +        () => {},
    +        reason => {});
    +  });
    +
    +  // TODO(koss) - Flakey Test.  When Dev Tools is closed on my Mac, this test
    +  // fails about 20% of the time (open - it never fails).  In the failing
    +  // case a long-poll is opened first.
    +  it.skip('disconnect old session on new connection', function(done) {
    +    const info = testRepoInfo(TEST_PROJECT.databaseURL);
    +    new Connection('1', info,
    +        message => {},
    +        (timestamp, sessionId) => {
    +          new Connection('2', info,
    +              message => {},
    +              (timestamp, sessionId) => {},
    +              () => {},
    +              reason => {},
    +              sessionId);
    +        },
    +        () => {
    +          done(); // first connection was disconnected
    +        },
    +        reason => {});
    +  });
    +});
    diff --git a/tests/database/order.test.ts b/tests/database/order.test.ts
    new file mode 100644
    index 00000000000..1529b43fa6d
    --- /dev/null
    +++ b/tests/database/order.test.ts
    @@ -0,0 +1,543 @@
    +import { expect } from "chai";
    +import { getRandomNode } from './helpers/util';
    +import { Reference } from '../../src/database/api/Reference';
    +import { EventAccumulator } from './helpers/EventAccumulator';
    +import { 
    +  eventTestHelper,
    +} from "./helpers/events";
    +
    +describe('Order Tests', function () {
    +  // Kind of a hack, but a lot of these tests are written such that they'll fail if run before we're
    +  // connected to Firebase because they do a bunch of sets and then a listen and assume that they'll
    +  // arrive in that order.  But if we aren't connected yet, the "reconnection" code will send them
    +  // in the opposite order.
    +  beforeEach(function() {
    +    return new Promise(resolve => {
    +      var ref = (getRandomNode() as Reference), connected = false;
    +      ref.root.child('.info/connected').on('value', function(s) {
    +        connected = s.val() == true;
    +        if (connected) resolve();
    +      });
    +    })    
    +  });
    +
    +  it("Push a bunch of data, enumerate it back; ensure order is correct.", async function () {
    +    var node = (getRandomNode() as Reference);
    +    for (var i = 0; i < 10; i++) {
    +      node.push().set(i);
    +    }
    +
    +    const snap = await node.once('value');
    +
    +    var expected = 0;
    +    snap.forEach(function (child) {
    +      expect(child.val()).to.equal(expected);
    +      expected++;
    +    });
    +    expect(expected).to.equal(10);
    +  });
    +
    +  it("Push a bunch of paths, then write; ensure order is correct.", async function() {
    +    var node = (getRandomNode() as Reference);
    +    var paths = [];
    +    // Push them first to try to call push() multiple times in the same ms.
    +    for (var i = 0; i < 20; i++) {
    +      paths[i] = node.push();
    +    }
    +    for (i = 0; i < 20; i++) {
    +      paths[i].set(i);
    +    }
    +
    +    const snap = await node.once('value');
    +    
    +    var expected = 0;
    +    snap.forEach(function (child) {
    +      expect(child.val()).to.equal(expected);
    +      expected++;
    +    });
    +    expect(expected).to.equal(20);
    +  });
    +
    +  it("Push a bunch of data, reconnect, read it back; ensure order is chronological.", async function () {
    +    var nodePair = (getRandomNode(2) as Reference[]);
    +    var expected;
    +
    +    var node = nodePair[0];
    +    var nodesSet = 0;
    +    for (var i = 0; i < 10; i++) {
    +      node.push().set(i, function() { ++nodesSet });
    +    }
    +
    +    // read it back locally and make sure it's correct.
    +    const snap = await node.once('value');
    +
    +    expected = 0;
    +    snap.forEach(function (child) {
    +      expect(child.val()).to.equal(expected);
    +      expected++;
    +    });
    +    expect(expected).to.equal(10);
    +
    +    // read it back
    +    var readSnap;
    +    const ea = new EventAccumulator(() => readSnap);
    +    nodePair[1].on('value', function(snap) {
    +      readSnap = snap;
    +      ea.addEvent();
    +    });
    +
    +    await ea.promise;
    +
    +    expected = 0;
    +    readSnap.forEach(function (child) {
    +      expect(child.val()).to.equal(expected);
    +      expected++;
    +    });
    +    expect(expected).to.equal(10);
    +  });
    +
    +  it("Push a bunch of data with explicit priority, reconnect, read it back; ensure order is correct.", async function () {
    +    var nodePair = (getRandomNode(2) as Reference[]);
    +    var expected;
    +
    +    var node = nodePair[0];
    +    var nodesSet = 0;
    +    for (var i = 0; i < 10; i++) {
    +      var pushedNode = node.push();
    +      pushedNode.setWithPriority(i, 10 - i, function() { ++nodesSet });
    +    }
    +
    +      // read it back locally and make sure it's correct.
    +    const snap = await node.once('value');
    +    expected = 9;
    +    snap.forEach(function (child) {
    +      expect(child.val()).to.equal(expected);
    +      expected--;
    +    });
    +    expect(expected).to.equal(-1);
    +
    +    // local SETs are visible immediately, but the second node is in a separate repo, so it is considered remote.
    +    // We need confirmation that the server has gotten all the data before we can expect to receive it all
    +
    +    // read it back
    +    var readSnap;
    +    const ea = new EventAccumulator(() => readSnap);
    +    nodePair[1].on('value', function(snap) {
    +      readSnap = snap;
    +      ea.addEvent();
    +    });
    +    await ea.promise;
    +
    +    expected = 9;
    +    readSnap.forEach(function (child) {
    +      expect(child.val()).to.equal(expected);
    +      expected--;
    +    });
    +    expect(expected).to.equal(-1);
    +  });
    +
    +  it("Push data with exponential priority and ensure order is correct.", async function () {
    +    var nodePair = (getRandomNode(2) as Reference[]);
    +    var expected;
    +
    +    var node = nodePair[0];
    +    var nodesSet = 0;
    +    for (var i = 0; i < 10; i++) {
    +      var pushedNode = node.push();
    +      pushedNode.setWithPriority(i, 111111111111111111111111111111 / Math.pow(10, i), function() { ++nodesSet });
    +    }
    +
    +    // read it back locally and make sure it's correct.
    +    const snap = await node.once('value');
    +    expected = 9;
    +    snap.forEach(function (child) {
    +      expect(child.val()).to.equal(expected);
    +      expected--;
    +    });
    +    expect(expected).to.equal(-1);
    +
    +    // read it back
    +    var readSnap;
    +    const ea = new EventAccumulator(() => readSnap);
    +    nodePair[1].on('value', function(snap) {
    +      readSnap = snap;
    +      ea.addEvent();
    +    });
    +
    +    await ea.promise;
    +
    +    expected = 9;
    +    readSnap.forEach(function (child) {
    +      expect(child.val()).to.equal(expected);
    +      expected--;
    +    });
    +    expect(expected).to.equal(-1);
    +  });
    +
    +  it("Verify nodes without values aren't enumerated.", async function() {
    +    var node = (getRandomNode() as Reference);
    +    node.child('foo');
    +    node.child('bar').set('test');
    +
    +    var items = 0;
    +    const snap = await node.once('value');
    +    snap.forEach(function (child) {
    +      items++;
    +      expect(child.key).to.equal('bar');
    +    });
    +
    +    expect(items).to.equal(1);
    +  });
    +
    +  it.skip("Receive child_moved event when priority changes.", async function() {
    +    var node = (getRandomNode() as Reference);
    +
    +    // const ea = new EventAccumulator(() => eventHelper.watchesInitializedWaiter);
    +
    +    var eventHelper = eventTestHelper([
    +      [ node, ['child_added', 'a'] ],
    +      [ node, ['value', ''] ],
    +      [ node, ['child_added', 'b'] ],
    +      [ node, ['value', ''] ],
    +      [ node, ['child_added', 'c'] ],
    +      [ node, ['value', ''] ],
    +      [ node, ['child_moved', 'a'] ],
    +      [ node, ['child_changed', 'a'] ],
    +      [ node, ['value', ''] ]
    +    ]);
    +
    +    // await ea.promise;
    +
    +    node.child('a').setWithPriority('first', 1);
    +    node.child('b').setWithPriority('second', 5);
    +    node.child('c').setWithPriority('third', 10);
    +
    +    expect(eventHelper.waiter()).to.equal(false);
    +
    +    node.child('a').setPriority(15);
    +
    +    expect(eventHelper.waiter()).to.equal(true);
    +  });
    +
    +  it.skip("Can reset priority to null.", async function() {
    +    var node = (getRandomNode() as Reference);
    +
    +    node.child('a').setWithPriority('a', 1);
    +    node.child('b').setWithPriority('b', 2);
    +    var eventHelper;
    +
    +    // const ea = new EventAccumulator(() => eventHelper.waiter());
    +    eventHelper = eventTestHelper([
    +      [ node, ['child_added', 'a'] ],
    +      [ node, ['child_added', 'b'] ],
    +      [ node, ['value', ''] ]
    +    ]);
    +
    +    // await ea.promise;
    +    
    +    eventHelper.addExpectedEvents([
    +      [ node, ['child_moved', 'b'] ],
    +      [ node, ['child_changed', 'b'] ],
    +      [ node, ['value', '']]
    +    ]);
    +
    +    node.child('b').setPriority(null);
    +    expect(eventHelper.waiter()).to.equal(true);
    +
    +    expect((await node.once('value')).child('b').getPriority()).to.equal(null);
    +  });
    +
    +  it("Inserting a node under a leaf node preserves its priority.", function() {
    +    var node = (getRandomNode() as Reference);
    +
    +    var snap = null;
    +    node.on('value', function(s) {snap = s;});
    +
    +    node.setWithPriority('a', 10);
    +    node.child('deeper').set('deeper');
    +    expect(snap.getPriority()).to.equal(10);
    +  });
    +
    +  it("Verify order of mixed numbers / strings / no priorities.", async function () {
    +    var nodePair = (getRandomNode(2) as Reference[]);
    +    var nodeAndPriorities = [
    +      "alpha42", "zed",
    +      "noPriorityC", null,
    +      "num41", 500,
    +      "noPriorityB", null,
    +      "num80", 4000.1,
    +      "num50", 4000,
    +      "num10", 24,
    +      "alpha41", "zed",
    +      "alpha20", "horse",
    +      "num20", 123,
    +      "num70", 4000.01,
    +      "noPriorityA", null,
    +      "alpha30", "tree",
    +      "num30", 300,
    +      "num60", 4000.001,
    +      "alpha10", "0horse",
    +      "num42", 500,
    +      "alpha40", "zed",
    +      "num40", 500];
    +
    +    var setsCompleted = 0;
    +    for (let i = 0; i < nodeAndPriorities.length; i++) {
    +      var n = nodePair[0].child((nodeAndPriorities[i++] as string));
    +      n.setWithPriority(1, nodeAndPriorities[i], function() { setsCompleted++; });
    +    }
    +
    +    var expectedOutput = "noPriorityA, noPriorityB, noPriorityC, num10, num20, num30, num40, num41, num42, num50, num60, num70, num80, alpha10, alpha20, alpha30, alpha40, alpha41, alpha42, ";
    +
    +    const snap = await nodePair[0].once('value');
    +    
    +    var output = "";
    +    snap.forEach(function (n) {
    +      output += n.key + ", ";
    +    });
    +
    +    expect(output).to.equal(expectedOutput);
    +
    +    var eventsFired = false;
    +    var output = "";
    +    nodePair[1].on('value', function(snap) {
    +      snap.forEach(function (n) {
    +        output += n.key + ", ";
    +      });
    +      expect(output).to.equal(expectedOutput);
    +      eventsFired = true;
    +    });
    +  });
    +
    +  it("Verify order of integer keys.", async function () {
    +    var ref = (getRandomNode() as Reference);
    +    var keys = [
    +      "foo",
    +      "bar",
    +      "03",
    +      "0",
    +      "100",
    +      "20",
    +      "5",
    +      "3",
    +      "003",
    +      "9"
    +    ];
    +
    +    var setsCompleted = 0;
    +    for (var i = 0; i < keys.length; i++) {
    +      var child = ref.child(keys[i]);
    +      child.set(true, function() { setsCompleted++; });
    +    }
    +
    +    var expectedOutput = "0, 3, 03, 003, 5, 9, 20, 100, bar, foo, ";
    +
    +    const snap = await ref.once('value');
    +    var output = "";
    +    snap.forEach(function (n) {
    +      output += n.key + ", ";
    +    });
    +
    +    expect(output).to.equal(expectedOutput);
    +  });
    +
    +  it("Ensure prevName is correct on child_added event.", function() {
    +    var node = (getRandomNode() as Reference);
    +
    +    var added = '';
    +    node.on('child_added', function(snap, prevName) {
    +      added += snap.key + " " + prevName + ", ";
    +    });
    +
    +    node.set({"a" : 1, "b": 2, "c": 3});
    +
    +    expect(added).to.equal('a null, b a, c b, ');
    +  });
    +
    +  it("Ensure prevName is correct when adding new nodes.", function() {
    +    var node = (getRandomNode() as Reference);
    +
    +    var added = '';
    +    node.on('child_added', function(snap, prevName) {
    +      added += snap.key + " " + prevName + ", ";
    +    });
    +
    +    node.set({"b" : 2, "c": 3, "d": 4});
    +
    +    expect(added).to.equal('b null, c b, d c, ');
    +
    +    added = '';
    +    node.child('a').set(1);
    +    expect(added).to.equal('a null, ');
    +
    +    added = '';
    +    node.child('e').set(5);
    +    expect(added).to.equal('e d, ');
    +  });
    +
    +  it("Ensure prevName is correct when adding new nodes with JSON.", function() {
    +    var node = (getRandomNode() as Reference);
    +
    +    var added = '';
    +    node.on('child_added', function(snap, prevName) {
    +      added += snap.key + " " + prevName + ", ";
    +    });
    +
    +    node.set({"b" : 2, "c": 3, "d": 4});
    +
    +    expect(added).to.equal('b null, c b, d c, ');
    +
    +    added = '';
    +    node.set({"a": 1, "b" : 2, "c": 3, "d": 4});
    +    expect(added).to.equal('a null, ');
    +
    +    added = '';
    +    node.set({"a": 1, "b" : 2, "c": 3, "d": 4, "e": 5});
    +    expect(added).to.equal('e d, ');
    +  });
    +
    +  it("Ensure prevName is correct when moving nodes.", function() {
    +    var node = (getRandomNode() as Reference);
    +
    +    var moved = '';
    +    node.on('child_moved', function(snap, prevName) {
    +      moved += snap.key + " " + prevName + ", ";
    +    });
    +
    +    node.child('a').setWithPriority('a', 1);
    +    node.child('b').setWithPriority('b', 2);
    +    node.child('c').setWithPriority('c', 3);
    +    node.child('d').setWithPriority('d', 4);
    +
    +    node.child('d').setPriority(0);
    +    expect(moved).to.equal('d null, ');
    +
    +    moved = '';
    +    node.child('a').setPriority(4);
    +    expect(moved).to.equal('a c, ');
    +
    +    moved = '';
    +    node.child('c').setPriority(0.5);
    +    expect(moved).to.equal('c d, ');
    +  });
    +
    +  it("Ensure prevName is correct when moving nodes by setting whole JSON.", function() {
    +    var node = (getRandomNode() as Reference);
    +
    +    var moved = '';
    +    node.on('child_moved', function(snap, prevName) {
    +      moved += snap.key + " " + prevName + ", ";
    +    });
    +
    +    node.set({
    +      a: {'.value': 'a', '.priority': 1},
    +      b: {'.value': 'b', '.priority': 2},
    +      c: {'.value': 'c', '.priority': 3},
    +      d: {'.value': 'd', '.priority': 4}
    +    });
    +
    +    node.set({
    +      d: {'.value': 'd', '.priority': 0},
    +      a: {'.value': 'a', '.priority': 1},
    +      b: {'.value': 'b', '.priority': 2},
    +      c: {'.value': 'c', '.priority': 3}
    +    });
    +    expect(moved).to.equal('d null, ');
    +
    +    moved = '';
    +    node.set({
    +      d: {'.value': 'd', '.priority': 0},
    +      b: {'.value': 'b', '.priority': 2},
    +      c: {'.value': 'c', '.priority': 3},
    +      a: {'.value': 'a', '.priority': 4}
    +    });
    +    expect(moved).to.equal('a c, ');
    +
    +    moved = '';
    +    node.set({
    +      d: {'.value': 'd', '.priority': 0},
    +      c: {'.value': 'c', '.priority': 0.5},
    +      b: {'.value': 'b', '.priority': 2},
    +      a: {'.value': 'a', '.priority': 4}
    +    });
    +    expect(moved).to.equal('c d, ');
    +  });
    +
    +  it("Case 595: Should not get child_moved event when deleting prioritized grandchild.", function() {
    +    var f = (getRandomNode() as Reference);
    +    var moves = 0;
    +    f.on('child_moved', function() {
    +      moves++;
    +    });
    +
    +    f.child('test/foo').setWithPriority(42, '5');
    +    f.child('test/foo2').setWithPriority(42, '10');
    +    f.child('test/foo').remove();
    +    f.child('test/foo2').remove();
    +
    +    expect(moves).to.equal(0, 'Should *not* have received any move events.');
    +  });
    +
    +  it("Can set value with priority of 0.", function() {
    +    var f = (getRandomNode() as Reference);
    +
    +    var snap = null;
    +    f.on('value', function(s) {
    +      snap = s;
    +    });
    +
    +    f.setWithPriority('test', 0);
    +
    +    expect(snap.getPriority()).to.equal(0);
    +  });
    +
    +  it("Can set object with priority of 0.", function() {
    +    var f = (getRandomNode() as Reference);
    +
    +    var snap = null;
    +    f.on('value', function(s) {
    +      snap = s;
    +    });
    +
    +    f.setWithPriority({x: 'test', y: 7}, 0);
    +
    +    expect(snap.getPriority()).to.equal(0);
    +  });
    +
    +  it("Case 2003: Should get child_moved for any priority change, regardless of whether it affects ordering.", function() {
    +    var f = (getRandomNode() as Reference);
    +    var moved = [];
    +    f.on('child_moved', function(snap) { moved.push(snap.key); });
    +    f.set({
    +      a: {'.value': 'a', '.priority': 0},
    +      b: {'.value': 'b', '.priority': 1},
    +      c: {'.value': 'c', '.priority': 2},
    +      d: {'.value': 'd', '.priority': 3}
    +    });
    +
    +    expect(moved).to.deep.equal([]);
    +    f.child('b').setWithPriority('b', 1.5);
    +    expect(moved).to.deep.equal(['b']);
    +  });
    +
    +  it("Case 2003: Should get child_moved for any priority change, regardless of whether it affects ordering (2).", function() {
    +    var f = (getRandomNode() as Reference);
    +    var moved = [];
    +    f.on('child_moved', function(snap) { moved.push(snap.key); });
    +    f.set({
    +      a: {'.value': 'a', '.priority': 0},
    +      b: {'.value': 'b', '.priority': 1},
    +      c: {'.value': 'c', '.priority': 2},
    +      d: {'.value': 'd', '.priority': 3}
    +    });
    +
    +    expect(moved).to.deep.equal([]);
    +    f.set({
    +      a: {'.value': 'a', '.priority': 0},
    +      b: {'.value': 'b', '.priority': 1.5},
    +      c: {'.value': 'c', '.priority': 2},
    +      d: {'.value': 'd', '.priority': 3}
    +    });
    +    expect(moved).to.deep.equal(['b']);
    +  });
    +});
    diff --git a/tests/database/order_by.test.ts b/tests/database/order_by.test.ts
    new file mode 100644
    index 00000000000..ed907422fab
    --- /dev/null
    +++ b/tests/database/order_by.test.ts
    @@ -0,0 +1,392 @@
    +import { expect } from "chai";
    +import { getRandomNode } from "./helpers/util";
    +import { EventAccumulatorFactory } from "./helpers/EventAccumulator";
    +import { Reference } from "../../src/database/api/Reference";
    +
    +describe('.orderBy tests', function() {
    +
    +  // TODO: setup spy on console.warn
    +
    +  var clearRef = (getRandomNode() as Reference);
    +
    +  it('Snapshots are iterated in order', function() {
    +    var ref = (getRandomNode() as Reference);
    +
    +    var initial = {
    +      alex: {nuggets: 60},
    +      rob: {nuggets: 56},
    +      vassili: {nuggets: 55.5},
    +      tony: {nuggets: 52},
    +      greg: {nuggets: 52}
    +    };
    +
    +    var expectedOrder = ['greg', 'tony', 'vassili', 'rob', 'alex'];
    +    var expectedPrevNames = [null, 'greg', 'tony', 'vassili', 'rob'];
    +
    +    var valueOrder = [];
    +    var addedOrder = [];
    +    var addedPrevNames = [];
    +
    +    var orderedRef = ref.orderByChild('nuggets');
    +
    +    orderedRef.on('value', function(snap) {
    +      snap.forEach(function(childSnap) {
    +        valueOrder.push(childSnap.key);
    +      });
    +    });
    +
    +    orderedRef.on('child_added', function(snap, prevName) {
    +      addedOrder.push(snap.key);
    +      addedPrevNames.push(prevName);
    +    });
    +
    +    ref.set(initial);
    +
    +    expect(addedOrder).to.deep.equal(expectedOrder);
    +    expect(valueOrder).to.deep.equal(expectedOrder);
    +    expect(addedPrevNames).to.deep.equal(expectedPrevNames);
    +  });
    +
    +  it('Snapshots are iterated in order for value', function() {
    +    var ref = (getRandomNode() as Reference);
    +
    +    var initial = {
    +      alex: 60,
    +      rob: 56,
    +      vassili: 55.5,
    +      tony: 52,
    +      greg: 52
    +    };
    +
    +    var expectedOrder = ['greg', 'tony', 'vassili', 'rob', 'alex'];
    +    var expectedPrevNames = [null, 'greg', 'tony', 'vassili', 'rob'];
    +
    +    var valueOrder = [];
    +    var addedOrder = [];
    +    var addedPrevNames = [];
    +
    +    var orderedRef = ref.orderByValue();
    +
    +    orderedRef.on('value', function(snap) {
    +      snap.forEach(function(childSnap) {
    +        valueOrder.push(childSnap.key);
    +      });
    +    });
    +
    +    orderedRef.on('child_added', function(snap, prevName) {
    +      addedOrder.push(snap.key);
    +      addedPrevNames.push(prevName);
    +    });
    +
    +    ref.set(initial);
    +
    +    expect(addedOrder).to.deep.equal(expectedOrder);
    +    expect(valueOrder).to.deep.equal(expectedOrder);
    +    expect(addedPrevNames).to.deep.equal(expectedPrevNames);
    +  });
    +
    +  it('Fires child_moved events', function() {
    +    var ref = (getRandomNode() as Reference);
    +
    +    var initial = {
    +      alex: {nuggets: 60},
    +      rob: {nuggets: 56},
    +      vassili: {nuggets: 55.5},
    +      tony: {nuggets: 52},
    +      greg: {nuggets: 52}
    +    };
    +
    +    var orderedRef = ref.orderByChild('nuggets');
    +
    +    var moved = false;
    +    orderedRef.on('child_moved', function(snap, prevName) {
    +      moved = true;
    +      expect(snap.key).to.equal('greg');
    +      expect(prevName).to.equal('rob');
    +      expect(snap.val()).to.deep.equal({nuggets: 57});
    +    });
    +
    +    ref.set(initial);
    +    ref.child('greg/nuggets').set(57);
    +    expect(moved).to.equal(true);
    +  });
    +
    +  it('Callback removal works', async function() {
    +    var ref = (getRandomNode() as Reference);
    +
    +    var reads = 0;
    +    var fooCb;
    +    var barCb;
    +    var bazCb;
    +    const ea = EventAccumulatorFactory.waitsForCount(4);
    +
    +    fooCb = ref.orderByChild('foo').on('value', function() {
    +      reads++;
    +      ea.addEvent();
    +    });
    +    barCb = ref.orderByChild('bar').on('value', function() {
    +      reads++;
    +      ea.addEvent();
    +    });
    +    bazCb = ref.orderByChild('baz').on('value', function() {
    +      reads++;
    +      ea.addEvent();
    +    });
    +    ref.on('value', function() {
    +      reads++;
    +      ea.addEvent();
    +    });
    +
    +    ref.set(1);
    +
    +    await ea.promise;
    +
    +    ref.off('value', fooCb);
    +    ref.set(2);
    +    expect(reads).to.equal(7);
    +
    +    // Should be a no-op, resulting in 3 more reads
    +    ref.orderByChild('foo').off('value', bazCb);
    +    ref.set(3);
    +    expect(reads).to.equal(10);
    +
    +    ref.orderByChild('bar').off('value');
    +    ref.set(4);
    +    expect(reads).to.equal(12);
    +
    +    // Now, remove everything
    +    ref.off();
    +    ref.set(5);
    +    expect(reads).to.equal(12);
    +  });
    +
    +  it('child_added events are in the correct order', function() {
    +    var ref = (getRandomNode() as Reference);
    +
    +    var initial = {
    +      a: {value: 5},
    +      c: {value: 3}
    +    };
    +
    +    var added = [];
    +    ref.orderByChild('value').on('child_added', function(snap) {
    +      added.push(snap.key);
    +    });
    +    ref.set(initial);
    +
    +    expect(added).to.deep.equal(['c', 'a']);
    +
    +    ref.update({
    +      b: {value: 4},
    +      d: {value: 2}
    +    });
    +
    +    expect(added).to.deep.equal(['c', 'a', 'd', 'b']);
    +  });
    +
    +  it('Can use key index', async function() {
    +    var ref = (getRandomNode() as Reference);
    +
    +    var data = {
    +      a: { '.priority': 10, '.value': 'a' },
    +      b: { '.priority': 5, '.value': 'b' },
    +      c: { '.priority': 20, '.value': 'c' },
    +      d: { '.priority': 7, '.value': 'd' },
    +      e: { '.priority': 30, '.value': 'e' },
    +      f: { '.priority': 8, '.value': 'f' }
    +    };
    +
    +    await ref.set(data);
    +
    +    const snap = await ref.orderByKey().startAt('c').once('value');
    +    
    +    var keys = [];
    +    snap.forEach(function(child) {
    +      keys.push(child.key);
    +    });
    +    expect(keys).to.deep.equal(['c', 'd', 'e', 'f']);
    +
    +    const ea = EventAccumulatorFactory.waitsForCount(5);
    +    var keys = [];
    +    
    +    ref.orderByKey().limitToLast(5).on('child_added', function(child) {
    +      keys.push(child.key);
    +      ea.addEvent();
    +    });
    +
    +    await ea.promise;
    +
    +    ref.orderByKey().off();
    +    expect(keys).to.deep.equal(['b', 'c', 'd', 'e', 'f']);
    +  });
    +
    +  it('Queries work on leaf nodes', function(done) {
    +    var ref = (getRandomNode() as Reference);
    +
    +    ref.set('leaf-node', function() {
    +      ref.orderByChild('foo').limitToLast(1).on('value', function(snap) {
    +        expect(snap.val()).to.be.null;
    +        done();
    +      });
    +    });
    +  });
    +
    +  it('Updates for unindexed queries work', function(done) {
    +    var refs = (getRandomNode(2) as Reference[]);
    +    var reader = refs[0];
    +    var writer = refs[1];
    +
    +    var value = {
    +      'one': { 'index': 1, 'value': 'one' },
    +      'two': { 'index': 2, 'value': 'two' },
    +      'three': { 'index': 3, 'value': 'three' }
    +    };
    +
    +    var count = 0;
    +
    +    writer.set(value, function() {
    +      reader.orderByChild('index').limitToLast(2).on('value', function(snap) {
    +        if (count === 0) {
    +          expect(snap.val()).to.deep.equal({
    +            'two': { 'index': 2, 'value': 'two' },
    +            'three': { 'index': 3, 'value': 'three' }
    +          });
    +          // update child which should trigger value event
    +          writer.child('one/index').set(4);
    +        } else if (count === 1) {
    +          expect(snap.val()).to.deep.equal({
    +            'three': { 'index': 3, 'value': 'three' },
    +            'one': { 'index': 4, 'value': 'one' }
    +          });
    +          done();
    +        }
    +        count++;
    +      });
    +    });
    +  });
    +
    +  it('Server respects KeyIndex', function(done) {
    +    var refs = (getRandomNode(2) as Reference[]);
    +    var reader = refs[0];
    +    var writer = refs[1];
    +
    +    var initial = {
    +      a: 1,
    +      b: 2,
    +      c: 3
    +    };
    +
    +    var expected = ['b', 'c'];
    +
    +    var actual = [];
    +
    +    var orderedRef = reader.orderByKey().startAt('b').limitToFirst(2);
    +    writer.set(initial, function() {
    +      orderedRef.on('value', function(snap) {
    +        snap.forEach(function(childSnap) {
    +          actual.push(childSnap.key);
    +        });
    +        expect(actual).to.deep.equal(expected);
    +        done();
    +      });
    +    });
    +  });
    +
    +  it('startAt/endAt works on value index', function() {
    +    var ref = (getRandomNode() as Reference);
    +
    +    var initial = {
    +      alex: 60,
    +      rob: 56,
    +      vassili: 55.5,
    +      tony: 52,
    +      greg: 52
    +    };
    +
    +    var expectedOrder = ['tony', 'vassili', 'rob'];
    +    var expectedPrevNames = [null, 'tony', 'vassili'];
    +
    +    var valueOrder = [];
    +    var addedOrder = [];
    +    var addedPrevNames = [];
    +
    +    var orderedRef = ref.orderByValue().startAt(52, 'tony').endAt(59);
    +
    +    orderedRef.on('value', function(snap) {
    +      snap.forEach(function(childSnap) {
    +        valueOrder.push(childSnap.key);
    +      });
    +    });
    +
    +    orderedRef.on('child_added', function(snap, prevName) {
    +      addedOrder.push(snap.key);
    +      addedPrevNames.push(prevName);
    +    });
    +
    +    ref.set(initial);
    +
    +    expect(addedOrder).to.deep.equal(expectedOrder);
    +    expect(valueOrder).to.deep.equal(expectedOrder);
    +    expect(addedPrevNames).to.deep.equal(expectedPrevNames);
    +  });
    +
    +  it('Removing default listener removes non-default listener that loads all data', function(done) {
    +    var ref = (getRandomNode() as Reference);
    +
    +    var initial = { key: 'value' };
    +    ref.set(initial, function(err) {
    +      expect(err).to.be.null;
    +      ref.orderByKey().on('value', function() {});
    +      ref.on('value', function() {});
    +      // Should remove both listener and should remove the listen sent to the server
    +      ref.off();
    +
    +      // This used to crash because a listener for ref.orderByKey() existed already
    +      ref.orderByKey().once('value', function(snap) {
    +        expect(snap.val()).to.deep.equal(initial);
    +        done();
    +      });
    +    });
    +  });
    +
    +  it('Can define and use an deep index', function(done) {
    +    var ref = (getRandomNode() as Reference);
    +
    +    var initial = {
    +      alex: {deep: {nuggets: 60}},
    +      rob: {deep: {nuggets: 56}},
    +      vassili: {deep: {nuggets: 55.5}},
    +      tony: {deep: {nuggets: 52}},
    +      greg: {deep: {nuggets: 52}}
    +    };
    +
    +    var expectedOrder = ['greg', 'tony', 'vassili'];
    +    var expectedPrevNames = [null, 'greg', 'tony'];
    +
    +    var valueOrder = [];
    +    var addedOrder = [];
    +    var addedPrevNames = [];
    +
    +    var orderedRef = ref.orderByChild('deep/nuggets').limitToFirst(3);
    +
    +    // come before value event
    +    orderedRef.on('child_added', function(snap, prevName) {
    +      addedOrder.push(snap.key);
    +      addedPrevNames.push(prevName);
    +    });
    +
    +    orderedRef.once('value', function(snap) {
    +      snap.forEach(function(childSnap) {
    +        valueOrder.push(childSnap.key);
    +      });
    +    });
    +
    +    ref.set(initial, function(err) {
    +      expect(err).to.be.null;
    +      expect(addedOrder).to.deep.equal(expectedOrder);
    +      expect(valueOrder).to.deep.equal(expectedOrder);
    +      expect(addedPrevNames).to.deep.equal(expectedPrevNames);
    +      done();
    +    });
    +  });
    +});
    diff --git a/tests/database/path.test.ts b/tests/database/path.test.ts
    new file mode 100644
    index 00000000000..ee9c99e00ea
    --- /dev/null
    +++ b/tests/database/path.test.ts
    @@ -0,0 +1,59 @@
    +import { expect } from "chai";
    +import { Path } from "../../src/database/core/util/Path";
    +
    +describe('Path Tests', function () {
    +  var expectGreater = function(left, right) {
    +    expect(Path.comparePaths(new Path(left), new Path(right))).to.equal(1)
    +    expect(Path.comparePaths(new Path(right), new Path(left))).to.equal(-1)
    +  };
    +
    +  var expectEqual = function(left, right) {
    +    expect(Path.comparePaths(new Path(left), new Path(right))).to.equal(0)
    +  };
    +
    +  it('contains() contains the path and any child path.', function () {
    +    expect(new Path('/').contains(new Path('/a/b/c'))).to.equal(true);
    +    expect(new Path('/a').contains(new Path('/a/b/c'))).to.equal(true);
    +    expect(new Path('/a/b').contains(new Path('/a/b/c'))).to.equal(true);
    +    expect(new Path('/a/b/c').contains(new Path('/a/b/c'))).to.equal(true);
    +
    +    expect(new Path('/a/b/c').contains(new Path('/a/b'))).to.equal(false);
    +    expect(new Path('/a/b/c').contains(new Path('/a'))).to.equal(false);
    +    expect(new Path('/a/b/c').contains(new Path('/'))).to.equal(false);
    +
    +    expect(new Path('/a/b/c').popFront().contains(new Path('/b/c'))).to.equal(true);
    +    expect(new Path('/a/b/c').popFront().contains(new Path('/b/c/d'))).to.equal(true);
    +
    +    expect(new Path('/a/b/c').contains(new Path('/b/c'))).to.equal(false);
    +    expect(new Path('/a/b/c').contains(new Path('/a/c/b'))).to.equal(false);
    +
    +    expect(new Path('/a/b/c').popFront().contains(new Path('/a/b/c'))).to.equal(false);
    +    expect(new Path('/a/b/c').popFront().contains(new Path('/b/c'))).to.equal(true);
    +    expect(new Path('/a/b/c').popFront().contains(new Path('/b/c/d'))).to.equal(true);
    +  });
    +
    +  it('popFront() returns the parent', function() {
    +    expect(new Path('/a/b/c').popFront().toString()).to.equal('/b/c')
    +    expect(new Path('/a/b/c').popFront().popFront().toString()).to.equal('/c');
    +    expect(new Path('/a/b/c').popFront().popFront().popFront().toString()).to.equal('/');
    +    expect(new Path('/a/b/c').popFront().popFront().popFront().popFront().toString()).to.equal('/');
    +  });
    +
    +  it('parent() returns the parent', function() {
    +    expect(new Path('/a/b/c').parent().toString()).to.equal('/a/b');
    +    expect(new Path('/a/b/c').parent().parent().toString()).to.equal('/a');
    +    expect(new Path('/a/b/c').parent().parent().parent().toString()).to.equal('/');
    +    expect(new Path('/a/b/c').parent().parent().parent().parent()).to.equal(null);
    +  });
    +
    +  it('comparePaths() works as expected', function() {
    +    expectEqual('/', '');
    +    expectEqual('/a', '/a');
    +    expectEqual('/a', '/a//');
    +    expectEqual('/a///b/b//', '/a/b/b');
    +    expectGreater('/b', '/a');
    +    expectGreater('/ab', '/a');
    +    expectGreater('/a/b', '/a');
    +    expectGreater('/a/b', '/a//');
    +  });
    +});
    diff --git a/tests/database/promise.test.ts b/tests/database/promise.test.ts
    new file mode 100644
    index 00000000000..bb61cf093dd
    --- /dev/null
    +++ b/tests/database/promise.test.ts
    @@ -0,0 +1,194 @@
    +import { expect } from "chai";
    +import { getRandomNode, getRootNode } from "./helpers/util";
    +import { Reference } from "../../src/database/api/Reference";
    +
    +describe('Promise Tests', function() {
    +  /**
    +   * Enabling test retires, wrapping the onDisconnect
    +   * methods seems to be flakey
    +   */
    +  this.retries(3);
    +  it('wraps Query.once', function() {
    +    return (getRandomNode() as Reference).once('value').then(function(snap) {
    +      expect(snap.val()).to.equal(null);
    +    });
    +  });
    +
    +  it('wraps Firebase.set', function() {
    +    var ref = (getRandomNode() as Reference);
    +    return ref.set(5).then(function() {
    +      return ref.once('value');
    +    }).then(function(read) {
    +      expect(read.val()).to.equal(5);
    +    });
    +  });
    +
    +  it('wraps Firebase.push when no value is passed', function() {
    +    var ref = (getRandomNode() as Reference);
    +    var pushed = ref.push();
    +    return pushed.then(function(childRef) {
    +      expect(pushed.ref.parent.toString()).to.equal(ref.toString());
    +      expect(pushed.toString()).to.equal(childRef.toString());
    +      return pushed.once('value');
    +    })
    +    .then(function(snap) {
    +      expect(snap.val()).to.equal(null);
    +      expect(snap.ref.toString()).to.equal(pushed.toString());
    +    });
    +  });
    +
    +  it('wraps Firebase.push when a value is passed', function() {
    +    var ref = (getRandomNode() as Reference);
    +    var pushed = ref.push(6);
    +    return pushed.then(function(childRef) {
    +      expect(pushed.ref.parent.toString()).to.equal(ref.toString());
    +      expect(pushed.toString()).to.equal(childRef.toString());
    +      return pushed.once('value');
    +    }).then(function(snap) {
    +      expect(snap.val()).to.equal(6);
    +      expect(snap.ref.toString()).to.equal(pushed.toString());
    +    });
    +  });
    +
    +  it('wraps Firebase.remove', function() {
    +    var ref = (getRandomNode() as Reference);
    +    return ref.set({'a': 'b'}).then(function() {
    +      var p = ref.child('a').remove();
    +      expect(typeof p.then === 'function').to.equal(true);
    +      return p;
    +    }).then(function() {
    +      return ref.once('value');
    +    }).then(function(snap) {
    +      expect(snap.val()).to.equal(null);
    +    });
    +  });
    +
    +  it('wraps Firebase.update', function() {
    +    var ref = (getRandomNode() as Reference);
    +    return ref.set({'a': 'b'}).then(function() {
    +      var p = ref.update({'c': 'd'});
    +      expect(typeof p.then === 'function').to.equal(true);
    +      return p;
    +    }).then(function() {
    +      return ref.once('value');
    +    }).then(function(snap) {
    +      expect(snap.val()).to.deep.equal({'a': 'b', 'c': 'd'});
    +    });
    +  });
    +
    +  it('wraps Fireabse.setPriority', function() {
    +    var ref = (getRandomNode() as Reference);
    +    return ref.set({'a': 'b'}).then(function() {
    +      var p = ref.child('a').setPriority(5);
    +      expect(typeof p.then === 'function').to.equal(true);
    +      return p;
    +    }).then(function() {
    +      return ref.once('value');
    +    }).then(function(snap) {
    +      expect(snap.child('a').getPriority()).to.equal(5);
    +    });
    +  });
    +
    +  it('wraps Firebase.setWithPriority', function() {
    +    var ref = (getRandomNode() as Reference);
    +    return ref.setWithPriority('hi', 5).then(function() {
    +      return ref.once('value');
    +    }).then(function(snap) {
    +      expect(snap.getPriority()).to.equal(5);
    +      expect(snap.val()).to.equal('hi');
    +    });
    +  });
    +
    +  it('wraps Firebase.transaction', function() {
    +    var ref = (getRandomNode() as Reference);
    +    return ref.transaction(function() {
    +      return 5;
    +    }).then(function(result) {
    +      expect(result.committed).to.equal(true);
    +      expect(result.snapshot.val()).to.equal(5);
    +      return ref.transaction(function() { return undefined; });
    +    }).then(function(result) {
    +      expect(result.committed).to.equal(false);
    +    });
    +  });
    +
    +  it('exposes catch in the return of Firebase.push', function() {
    +    // Catch is a pain in the bum to provide safely because "catch" is a reserved word and ES3 and below require
    +    // you to use quotes to define it, but the closure linter really doesn't want you to do that either.
    +    var ref = (getRandomNode() as Reference);
    +    var pushed = ref.push(6);
    +
    +    expect(typeof ref.then === 'function').to.equal(false);
    +    expect(typeof ref.catch === 'function').to.equal(false);
    +    expect(typeof pushed.then === 'function').to.equal(true);
    +    expect(typeof pushed.catch === 'function').to.equal(true);
    +    return pushed;
    +  });
    +
    +  it('wraps onDisconnect.remove', function() {
    +    var refs = (getRandomNode(2) as Reference[]);
    +    var writer = refs[0];
    +    var reader = refs[1];
    +    var refInfo = getRootNode(0, '.info/connected');
    +
    +    refInfo.once('value', function(snapshot) {
    +      expect(snapshot.val()).to.equal(true);
    +    });
    +
    +    return writer.child('here today').set('gone tomorrow').then(function() {
    +      var p = writer.child('here today').onDisconnect().remove();
    +      expect(typeof p.then === 'function').to.equal(true);
    +      return p;
    +    }).then(function() {
    +      writer.database.goOffline();
    +      writer.database.goOnline();
    +      return reader.once('value');
    +    }).then(function(snap) {
    +      expect(snap.val()).to.equal(null);
    +    });
    +  });
    +
    +  it('wraps onDisconnect.update', function() {
    +    var refs = (getRandomNode(2) as Reference[]);
    +    var writer = refs[0];
    +    var reader = refs[1];
    +    return writer.set({'foo': 'baz'}).then(function() {
    +      var p = writer.onDisconnect().update({'foo': 'bar'});
    +      expect(typeof p.then === 'function').to.equal(true);
    +      return p;
    +    }).then(function() {
    +      writer.database.goOffline();
    +      writer.database.goOnline();
    +      return reader.once('value');
    +    }).then(function(snap) {
    +      expect(snap.val()).to.deep.equal({'foo': 'bar'});
    +    });
    +  });
    +
    +  it('wraps onDisconnect.set', function() {
    +    var refs = (getRandomNode(2) as Reference[]);
    +    var writer = refs[0];
    +    var reader = refs[1];
    +    return writer.child('hello').onDisconnect().set('world').then(function() {
    +      writer.database.goOffline();
    +      writer.database.goOnline();
    +      return reader.once('value');
    +    }).then(function(snap) {
    +      expect(snap.val()).to.deep.equal({'hello': 'world'});
    +    });
    +  });
    +
    +  it('wraps onDisconnect.setWithPriority', function() {
    +    var refs = (getRandomNode(2) as Reference[]);
    +    var writer = refs[0];
    +    var reader = refs[1];
    +    return writer.child('meaning of life').onDisconnect().setWithPriority('ultimate question', 42).then(function() {
    +      writer.database.goOffline();
    +      writer.database.goOnline();
    +      return reader.once('value');
    +    }).then(function(snap) {
    +      expect(snap.val()).to.deep.equal({'meaning of life': 'ultimate question'});
    +      expect(snap.child('meaning of life').getPriority()).to.equal(42);
    +    });
    +  });
    +});
    diff --git a/tests/database/query.test.ts b/tests/database/query.test.ts
    new file mode 100644
    index 00000000000..1ca8f697c37
    --- /dev/null
    +++ b/tests/database/query.test.ts
    @@ -0,0 +1,2717 @@
    +import { expect } from "chai";
    +import firebase from '../../src/app';
    +import { Reference } from "../../src/database/api/Reference";
    +import { Query } from "../../src/database/api/Query";
    +import "../../src/database/core/snap/ChildrenNode";
    +import { 
    +  getQueryValue,
    +  getRandomNode,
    +  getPath, 
    +  pause
    +} from "./helpers/util";
    +import {
    +  EventAccumulator,
    +  EventAccumulatorFactory 
    +} from "./helpers/EventAccumulator";
    +
    +const _ = require('lodash');
    +
    +type TaskList = [Query, any][];
    +
    +describe('Query Tests', function() {
    +  // Little helper class for testing event callbacks w/ contexts.
    +  var EventReceiver = function() {
    +    this.gotValue = false;
    +    this.gotChildAdded = false;
    +  };
    +  EventReceiver.prototype.onValue = function() {
    +    this.gotValue = true;
    +  };
    +  EventReceiver.prototype.onChildAdded = function() {
    +    this.gotChildAdded = true;
    +  };
    +
    +  it('Can create basic queries.', function() {
    +    var path = (getRandomNode() as Reference);
    +
    +    path.limitToLast(10);
    +    path.startAt('199').limitToFirst(10);
    +    path.startAt('199', 'test').limitToFirst(10);
    +    path.endAt('199').limitToLast(1);
    +    path.startAt('50', 'test').endAt('100', 'tree');
    +    path.startAt('4').endAt('10');
    +    path.startAt().limitToFirst(10);
    +    path.endAt().limitToLast(10);
    +    path.orderByKey().startAt('foo');
    +    path.orderByKey().endAt('foo');
    +    path.orderByKey().equalTo('foo');
    +    path.orderByChild("child");
    +    path.orderByChild("child/deep/path");
    +    path.orderByValue();
    +    path.orderByPriority();
    +  });
    +
    +  it('Exposes database as read-only property', function() {
    +    var path = (getRandomNode() as Reference);
    +    var child = path.child('child');
    +
    +    var db = path.database;
    +    var dbChild = child.database;
    +
    +    expect(db).to.equal(dbChild);
    +    /**
    +     * TS throws an error here (as is expected)
    +     * casting to any to allow the code to run
    +     */
    +    expect(() => (path as any).database = "can't overwrite").to.throw();
    +    expect(path.database).to.equal(db);
    +  });
    +
    +  it('Invalid queries throw', function() {
    +    var path = (getRandomNode() as Reference);
    +    
    +    /**
    +     * Because we are testing invalid queries, I am casting
    +     * to `any` to avoid the typechecking error. This can
    +     * occur when a user uses the SDK through a pure JS 
    +     * client, rather than typescript
    +     */
    +    expect(function() { (path as any).limitToLast(); }).to.throw();
    +    expect(function() { (path as any).limitToLast('100'); }).to.throw();
    +    expect(function() { (path as any).limitToLast({ x: 5 }); }).to.throw();
    +    expect(function() { path.limitToLast(100).limitToLast(100); }).to.throw();
    +    expect(function() { path.limitToLast(100).limitToFirst(100); }).to.throw();
    +    expect(function() { path.limitToLast(100).limitToLast(100); }).to.throw();
    +    expect(function() { path.limitToFirst(100).limitToLast(100); }).to.throw();
    +    expect(function() { path.limitToFirst(100).limitToFirst(100); }).to.throw();
    +    expect(function() { path.limitToFirst(100).limitToLast(100); }).to.throw();
    +    expect(function() { path.limitToLast(100).limitToLast(100); }).to.throw();
    +    expect(function() { path.limitToLast(100).limitToFirst(100); }).to.throw();
    +    expect(function() { path.limitToLast(100).limitToLast(100); }).to.throw();
    +    expect(function() { path.orderByPriority().orderByPriority(); }).to.throw();
    +    expect(function() { path.orderByPriority().orderByKey(); }).to.throw();
    +    expect(function() { path.orderByPriority().orderByChild('foo'); }).to.throw();
    +    expect(function() { path.orderByPriority().startAt(true); }).to.throw();
    +    expect(function() { path.orderByPriority().endAt(false); }).to.throw();
    +    expect(function() { path.orderByPriority().equalTo(true); }).to.throw();
    +    expect(function() { path.orderByKey().orderByPriority(); }).to.throw();
    +    expect(function() { path.orderByKey().orderByKey(); }).to.throw();
    +    expect(function() { path.orderByKey().orderByChild('foo'); }).to.throw();
    +    expect(function() { path.orderByChild('foo').orderByPriority(); }).to.throw();
    +    expect(function() { path.orderByChild('foo').orderByKey(); }).to.throw();
    +    expect(function() { path.orderByChild('foo').orderByChild('foo'); }).to.throw();
    +    expect(function() { (path as any).orderByChild('foo').startAt({a: 1}); }).to.throw();
    +    expect(function() { (path as any).orderByChild('foo').endAt({a: 1}); }).to.throw();
    +    expect(function() { (path as any).orderByChild('foo').equalTo({a: 1}); }).to.throw();
    +    expect(function() { path.startAt('foo').startAt('foo')}).to.throw();
    +    expect(function() { path.startAt('foo').equalTo('foo')}).to.throw();
    +    expect(function() { path.endAt('foo').endAt('foo')}).to.throw();
    +    expect(function() { path.endAt('foo').equalTo('foo')}).to.throw();
    +    expect(function() { path.equalTo('foo').startAt('foo')}).to.throw();
    +    expect(function() { path.equalTo('foo').endAt('foo')}).to.throw();
    +    expect(function() { path.equalTo('foo').equalTo('foo')}).to.throw();
    +    expect(function() { path.orderByKey().startAt('foo', 'foo')}).to.throw();
    +    expect(function() { path.orderByKey().endAt('foo', 'foo')}).to.throw();
    +    expect(function() { path.orderByKey().equalTo('foo', 'foo')}).to.throw();
    +    expect(function() { path.orderByKey().startAt(1)}).to.throw();
    +    expect(function() { path.orderByKey().startAt(true)}).to.throw();
    +    expect(function() { path.orderByKey().startAt(null)}).to.throw();
    +    expect(function() { path.orderByKey().endAt(1)}).to.throw();
    +    expect(function() { path.orderByKey().endAt(true)}).to.throw();
    +    expect(function() { path.orderByKey().endAt(null)}).to.throw();
    +    expect(function() { path.orderByKey().equalTo(1)}).to.throw();
    +    expect(function() { path.orderByKey().equalTo(true)}).to.throw();
    +    expect(function() { path.orderByKey().equalTo(null)}).to.throw();
    +    expect(function() { path.startAt('foo', 'foo').orderByKey()}).to.throw();
    +    expect(function() { path.endAt('foo', 'foo').orderByKey()}).to.throw();
    +    expect(function() { path.equalTo('foo', 'foo').orderByKey()}).to.throw();
    +    expect(function() { path.startAt(1).orderByKey()}).to.throw();
    +    expect(function() { path.startAt(true).orderByKey()}).to.throw();
    +    expect(function() { path.endAt(1).orderByKey()}).to.throw();
    +    expect(function() { path.endAt(true).orderByKey()}).to.throw();
    +  });
    +
    +  it('can produce a valid ref', function() {
    +    var path = (getRandomNode() as Reference);
    +
    +    var query = path.limitToLast(1);
    +    var ref = query.ref;
    +
    +    expect(ref.toString()).to.equal(path.toString());
    +  });
    +
    +  it('Passing invalidKeys to startAt / endAt throws.', function() {
    +    var f = (getRandomNode() as Reference);
    +    var badKeys = ['.test', 'test.', 'fo$o', '[what', 'ever]', 'ha#sh', '/thing', 'th/ing', 'thing/'];
    +    // Changed from basic array iteration to avoid closure issues accessing mutable state
    +    _.each(badKeys, function(badKey) {
    +      expect(function() { f.startAt(null, badKey); }).to.throw();
    +      expect(function() { f.endAt(null, badKey); }).to.throw();
    +    });
    +  });
    +
    +  it('Passing invalid paths to orderBy throws', function() {
    +    var ref = (getRandomNode() as Reference);
    +    expect(function() { ref.orderByChild('$child/foo'); }).to.throw();
    +    expect(function() { ref.orderByChild('$key'); }).to.throw();
    +    expect(function() { ref.orderByChild('$priority'); }).to.throw();
    +  });
    +
    +  it('Query.queryIdentifier works.', function() {
    +    var path = (getRandomNode() as Reference);
    +    var queryId = function(query) {
    +      return query.queryIdentifier(query);
    +    };
    +
    +    expect(queryId(path)).to.equal('default');
    +
    +    expect(queryId(path.startAt('pri', 'name')))
    +      .to.equal('{"sn":"name","sp":"pri"}');
    +    expect(queryId(path.startAt('spri').endAt('epri')))
    +      .to.equal('{"ep":"epri","sp":"spri"}');
    +    expect(queryId(path.startAt('spri', 'sname').endAt('epri', 'ename')))
    +      .to.equal('{"en":"ename","ep":"epri","sn":"sname","sp":"spri"}');
    +    expect(queryId(path.startAt('pri').limitToFirst(100)))
    +      .to.equal('{"l":100,"sp":"pri","vf":"l"}');
    +    expect(queryId(path.startAt('bar').orderByChild('foo')))
    +      .to.equal('{"i":"foo","sp":"bar"}');
    +  });
    +
    +  it('Passing invalid queries to isEqual throws', function() {
    +    var ref = (getRandomNode() as Reference);
    +    expect(function() { (ref as any).isEqual(); }).to.throw();
    +    expect(function() { (ref as any).isEqual(''); }).to.throw();
    +    expect(function() { (ref as any).isEqual('foo'); }).to.throw();
    +    expect(function() { (ref as any).isEqual({}); }).to.throw();
    +    expect(function() { (ref as any).isEqual([]); }).to.throw();
    +    expect(function() { (ref as any).isEqual(0); }).to.throw();
    +    expect(function() { (ref as any).isEqual(1); }).to.throw();
    +    expect(function() { (ref as any).isEqual(NaN); }).to.throw();
    +    expect(function() { ref.isEqual(null); }).to.throw();
    +    expect(function() { (ref as any).isEqual({a:1}); }).to.throw();
    +    expect(function() { (ref as any).isEqual(ref, 'extra'); }).to.throw();
    +  });
    +
    +  it('Query.isEqual works.', function() {
    +    var path = (getRandomNode() as Reference);
    +    var rootRef = path.root;
    +    var childRef = rootRef.child('child');
    +
    +    // Equivalent refs
    +    expect(path.isEqual(path), 'Query.isEqual - 1').to.be.true;
    +    expect(rootRef.isEqual(rootRef), 'Query.isEqual - 2').to.be.true;
    +    expect(rootRef.isEqual(childRef.parent), 'Query.isEqual - 3').to.be.true;
    +    expect(rootRef.child('child').isEqual(childRef), 'Query.isEqual - 4').to.be.true;
    +
    +    // Refs with different repos
    +    // var rootRefDifferentRepo = TESTS.getFreshRepo(TEST_ALT_NAMESPACE);
    +    // rootRefDifferentRepo.database.goOffline();
    +
    +    // expect(rootRef.isEqual(rootRefDifferentRepo), 'Query.isEqual - 5').to.be.false;
    +    // expect(childRef.isEqual(rootRefDifferentRepo.child('child')), 'Query.isEqual - 6').to.be.false;
    +
    +    // Refs with different paths
    +    expect(rootRef.isEqual(childRef), 'Query.isEqual - 7').to.be.false;
    +    expect(childRef.isEqual(rootRef.child('otherChild')), 'Query.isEqual - 8').to.be.false;
    +
    +    var childQueryLast25 = childRef.limitToLast(25);
    +    var childQueryOrderedByKey = childRef.orderByKey();
    +    var childQueryOrderedByPriority = childRef.orderByPriority();
    +    var childQueryOrderedByTimestamp = childRef.orderByChild("timestamp");
    +    var childQueryStartAt1 = childQueryOrderedByTimestamp.startAt(1);
    +    var childQueryStartAt2 = childQueryOrderedByTimestamp.startAt(2);
    +    var childQueryEndAt2 = childQueryOrderedByTimestamp.endAt(2);
    +    var childQueryStartAt1EndAt2 = childQueryOrderedByTimestamp.startAt(1).endAt(2);
    +
    +    // Equivalent queries
    +    expect(childRef.isEqual(childQueryLast25.ref), 'Query.isEqual - 9').to.be.true;
    +    expect(childQueryLast25.isEqual(childRef.limitToLast(25)), 'Query.isEqual - 10').to.be.true;
    +    expect(childQueryStartAt1EndAt2.isEqual(childQueryOrderedByTimestamp.startAt(1).endAt(2)), 'Query.isEqual - 11').to.be.true;
    +
    +    // Non-equivalent queries
    +    expect(childQueryLast25.isEqual(childRef), 'Query.isEqual - 12').to.be.false;
    +    expect(childQueryLast25.isEqual(childQueryOrderedByKey), 'Query.isEqual - 13').to.be.false;
    +    expect(childQueryLast25.isEqual(childQueryOrderedByPriority), 'Query.isEqual - 14').to.be.false;
    +    expect(childQueryLast25.isEqual(childQueryOrderedByTimestamp), 'Query.isEqual - 15').to.be.false;
    +    expect(childQueryOrderedByKey.isEqual(childQueryOrderedByPriority), 'Query.isEqual - 16').to.be.false;
    +    expect(childQueryOrderedByKey.isEqual(childQueryOrderedByTimestamp), 'Query.isEqual - 17').to.be.false;
    +    expect(childQueryStartAt1.isEqual(childQueryStartAt2), 'Query.isEqual - 18').to.be.false;
    +    expect(childQueryStartAt1.isEqual(childQueryStartAt1EndAt2), 'Query.isEqual - 19').to.be.false;
    +    expect(childQueryEndAt2.isEqual(childQueryStartAt2), 'Query.isEqual - 20').to.be.false;
    +    expect(childQueryEndAt2.isEqual(childQueryStartAt1EndAt2), 'Query.isEqual - 21').to.be.false;
    +  });
    +
    +  it('Query.off can be called on the default query.', function() {
    +    var path = (getRandomNode() as Reference);
    +    var eventFired = false;
    +
    +    var callback = function() { eventFired = true; };
    +    path.limitToLast(5).on('value', callback);
    +
    +    path.set({a: 5, b: 6});
    +    expect(eventFired).to.be.true;
    +    eventFired = false;
    +
    +    path.off('value', callback);
    +    path.set({a: 6, b: 5});
    +    expect(eventFired).to.be.false;
    +  });
    +
    +  it('Query.off can be called on the specific query.', function() {
    +    var path = (getRandomNode() as Reference);
    +    var eventFired = false;
    +
    +    var callback = function() { eventFired = true; };
    +    path.limitToLast(5).on('value', callback);
    +
    +    path.set({a: 5, b: 6});
    +    expect(eventFired).to.be.true;
    +    eventFired = false;
    +
    +    path.limitToLast(5).off('value', callback);
    +    path.set({a: 6, b: 5});
    +    expect(eventFired).to.be.false;
    +  });
    +
    +  it('Query.off can be called without a callback specified.', function() {
    +    var path = (getRandomNode() as Reference);
    +    var eventFired = false;
    +
    +    var callback1 = function() { eventFired = true; };
    +    var callback2 = function() { eventFired = true; };
    +    path.on('value', callback1);
    +    path.limitToLast(5).on('value', callback2);
    +
    +    path.set({a: 5, b: 6});
    +    expect(eventFired).to.be.true;
    +    eventFired = false;
    +
    +    path.off('value');
    +    path.set({a: 6, b: 5});
    +    expect(eventFired).to.be.false;
    +  });
    +
    +  it('Query.off can be called without an event type or callback specified.', function() {
    +    var path = (getRandomNode() as Reference);
    +    var eventFired = false;
    +
    +    var callback1 = function() { eventFired = true; };
    +    var callback2 = function() { eventFired = true; };
    +    path.on('value', callback1);
    +    path.limitToLast(5).on('value', callback2);
    +
    +    path.set({a: 5, b: 6});
    +    expect(eventFired).to.be.true;
    +    eventFired = false;
    +
    +    path.off();
    +    path.set({a: 6, b: 5});
    +    expect(eventFired).to.be.false;
    +  });
    +
    +  it('Query.off respects provided context (for value events).', function() {
    +    var ref = (getRandomNode() as Reference);
    +
    +    var a = new EventReceiver(),
    +        b = new EventReceiver();
    +
    +    ref.on('value', a.onValue, a);
    +    ref.on('value', b.onValue, b);
    +
    +    ref.set('hello!');
    +    expect(a.gotValue).to.be.true;
    +    expect(b.gotValue).to.be.true;
    +    a.gotValue = b.gotValue = false;
    +
    +    // unsubscribe b
    +    ref.off('value', b.onValue, b);
    +
    +    // Only a should get this event.
    +    ref.set(42);
    +    expect(a.gotValue).to.be.true;
    +    expect(b.gotValue).to.be.false;
    +
    +    ref.off('value', a.onValue, a);
    +  });
    +
    +  it('Query.off respects provided context (for child events).', function() {
    +    var ref = (getRandomNode() as Reference);
    +
    +    var a = new EventReceiver(),
    +        b = new EventReceiver();
    +
    +    ref.on('child_added', a.onChildAdded, a);
    +    ref.on('child_added', b.onChildAdded, b);
    +
    +    ref.push('hello!');
    +    expect(a.gotChildAdded).to.be.true;
    +    expect(b.gotChildAdded).to.be.true;
    +    a.gotChildAdded = b.gotChildAdded = false;
    +
    +    // unsubscribe b.
    +    ref.off('child_added', b.onChildAdded, b);
    +
    +    // Only a should get this event.
    +    ref.push(42);
    +    expect(a.gotChildAdded).to.be.true;
    +    expect(b.gotChildAdded).to.be.false;
    +
    +    ref.off('child_added', a.onChildAdded, a);
    +  });
    +
    +  it('Query.off with no callback/context removes all callbacks, even with contexts (for value events).', function() {
    +    var ref = (getRandomNode() as Reference);
    +
    +    var a = new EventReceiver(),
    +        b = new EventReceiver();
    +
    +    ref.on('value', a.onValue, a);
    +    ref.on('value', b.onValue, b);
    +
    +    ref.set('hello!');
    +    expect(a.gotValue).to.be.true;
    +    expect(b.gotValue).to.be.true;
    +    a.gotValue = b.gotValue = false;
    +
    +    // unsubscribe value events.
    +    ref.off('value');
    +
    +    // Should get no events.
    +    ref.set(42);
    +    expect(a.gotValue).to.be.false;
    +    expect(b.gotValue).to.be.false;
    +  });
    +
    +  it('Query.off with no callback/context removes all callbacks, even with contexts (for child events).', function() {
    +    var ref = (getRandomNode() as Reference);
    +
    +    var a = new EventReceiver(),
    +        b = new EventReceiver();
    +
    +    ref.on('child_added', a.onChildAdded, a);
    +    ref.on('child_added', b.onChildAdded, b);
    +
    +    ref.push('hello!');
    +    expect(a.gotChildAdded).to.be.true;
    +    expect(b.gotChildAdded).to.be.true;
    +    a.gotChildAdded = b.gotChildAdded = false;
    +
    +    // unsubscribe child_added.
    +    ref.off('child_added');
    +
    +    // Should get no events.
    +    ref.push(42);
    +    expect(a.gotChildAdded).to.be.false;
    +    expect(b.gotChildAdded).to.be.false;
    +  });
    +
    +  it('Query.off with no event type / callback removes all callbacks (even those with contexts).', function() {
    +    var ref = (getRandomNode() as Reference);
    +
    +    var a = new EventReceiver(),
    +        b = new EventReceiver();
    +
    +    ref.on('value', a.onValue, a);
    +    ref.on('value', b.onValue, b);
    +    ref.on('child_added', a.onChildAdded, a);
    +    ref.on('child_added', b.onChildAdded, b);
    +
    +    ref.set(null);
    +    ref.push('hello!');
    +    expect(a.gotChildAdded).to.be.true;
    +    expect(a.gotValue).to.be.true;
    +    expect(b.gotChildAdded).to.be.true;
    +    expect(b.gotValue).to.be.true;
    +    a.gotValue = b.gotValue = a.gotChildAdded = b.gotChildAdded = false;
    +
    +    // unsubscribe all events.
    +    ref.off();
    +
    +    // We should get no events.
    +    ref.push(42);
    +    expect(a.gotChildAdded).to.be.false;
    +    expect(b.gotChildAdded).to.be.false;
    +    expect(a.gotValue).to.be.false;
    +    expect(b.gotValue).to.be.false;
    +  });
    +
    +  it('Set a limit of 5, add a bunch of nodes, ensure only last 5 items are kept.', function() {
    +    var node = (getRandomNode() as Reference);
    +    var snap = null;
    +    node.limitToLast(5).on('value', function(s) { snap = s; });
    +
    +    node.set({});
    +    for (var i = 0; i < 10; i++) {
    +      node.push().set(i);
    +    }
    +
    +    var expected = 5;
    +    snap.forEach(function(child) {
    +      expect(child.val()).to.equal(expected);
    +      expected++;
    +    });
    +
    +    expect(expected).to.equal(10);
    +  });
    +
    +  it('Set a limit of 5, add a bunch of nodes, ensure only last 5 items are sent from server.', async function() {
    +    var node = (getRandomNode() as Reference);
    +    await node.set({});
    +
    +    const pushPromises = [];
    +
    +    for (let i = 0; i < 10; i++) {
    +      let promise = node.push().set(i);
    +      pushPromises.push(promise);
    +    }
    +
    +    await Promise.all(pushPromises);
    +
    +    const ea = EventAccumulatorFactory.waitsForCount(1);
    +
    +    node.limitToLast(5).on('value', snap => {
    +      ea.addEvent(snap);
    +    });
    +
    +    const [snap] = await ea.promise;
    +
    +    let expected = 5;
    +      
    +    snap.forEach(function(child) {
    +      expect(child.val()).to.equal(expected);
    +      expected++;
    +    });
    +
    +    expect(expected).to.equal(10);
    +  });
    +
    +  it('Set various limits, ensure resulting data is correct.', async function() {
    +    var node = (getRandomNode() as Reference);
    +
    +    await node.set({a: 1, b: 2, c: 3});    
    +
    +    const tasks: TaskList = [
    +      [node.limitToLast(1), {c: 3}],,
    +      [node.endAt().limitToLast(1), {c: 3}],
    +      [node.limitToLast(2), {b: 2, c: 3}],
    +      [node.limitToLast(3), {a: 1, b: 2, c: 3}],
    +      [node.limitToLast(4), {a: 1, b: 2, c: 3}]
    +    ];
    +
    +    return Promise.all(tasks.map(async task => {
    +      const [query, val] = task;
    +      const ea = EventAccumulatorFactory.waitsForCount(1);
    +      query.on('value', snap => {
    +        ea.addEvent(snap.val());
    +      });
    +      const [newVal] = await ea.promise;
    +      expect(newVal).to.deep.equal(val);
    +    }));
    +  });
    +
    +  it('Set various limits with a startAt name, ensure resulting data is correct.', async function() {
    +    var node = (getRandomNode() as Reference);
    +
    +    await node.set({a: 1, b: 2, c: 3});
    +
    +    const tasks: TaskList = [
    +      [node.startAt().limitToFirst(1), {a: 1}],
    +      [node.startAt(null, 'c').limitToFirst(1), {c: 3}],
    +      [node.startAt(null, 'b').limitToFirst(1), {b: 2}],
    +      [node.startAt(null, 'b').limitToFirst(2), {b: 2, c: 3}],
    +      [node.startAt(null, 'b').limitToFirst(3), {b: 2, c: 3}],
    +      [node.startAt(null, 'b').limitToLast(1), {c: 3}],
    +      [node.startAt(null, 'b').limitToLast(1), {c: 3}],
    +      [node.startAt(null, 'b').limitToLast(2), {b: 2, c: 3}],
    +      [node.startAt(null, 'b').limitToLast(3), {b: 2, c: 3}],
    +      [node.limitToFirst(1).startAt(null, 'c'), {c: 3}],
    +      [node.limitToFirst(1).startAt(null, 'b'), {b: 2}],
    +      [node.limitToFirst(2).startAt(null, 'b'), {b: 2, c: 3}],
    +      [node.limitToFirst(3).startAt(null, 'b'), {b: 2, c: 3}],
    +      [node.limitToLast(1).startAt(null, 'b'), {c: 3}],
    +      [node.limitToLast(1).startAt(null, 'b'), {c: 3}],
    +      [node.limitToLast(2).startAt(null, 'b'), {b: 2, c: 3}],
    +      [node.limitToLast(3).startAt(null, 'b'), {b: 2, c: 3}],
    +    ];
    +
    +    return Promise.all(tasks.map(async task => {
    +      const [query, val] = task;
    +      const ea = EventAccumulatorFactory.waitsForCount(1);
    +      query.on('value', snap => {
    +        ea.addEvent(snap.val());
    +      });
    +      const [newVal] = await ea.promise;
    +      expect(newVal).to.deep.equal(val);
    +    }));
    +  });
    +
    +  it('Set various limits with a endAt name, ensure resulting data is correct.', async function() {
    +    var node = (getRandomNode() as Reference);
    +
    +    await node.set({a: 1, b: 2, c: 3});
    +
    +    const tasks: TaskList = [
    +      [node.endAt().limitToFirst(1), {a: 1}],
    +      [node.endAt(null, 'c').limitToFirst(1), {a: 1}],
    +      [node.endAt(null, 'b').limitToFirst(1), {a: 1}],
    +      [node.endAt(null, 'b').limitToFirst(2), {a: 1, b: 2}],
    +      [node.endAt(null, 'b').limitToFirst(3), {a: 1, b: 2}],
    +      [node.endAt(null, 'c').limitToLast(1), {c: 3}],
    +      [node.endAt(null, 'b').limitToLast(1), {b: 2}],
    +      [node.endAt(null, 'b').limitToLast(2), {a: 1, b: 2}],
    +      [node.endAt(null, 'b').limitToLast(3), {a: 1, b: 2}],
    +      [node.limitToFirst(1).endAt(null, 'c'), {a: 1}],
    +      [node.limitToFirst(1).endAt(null, 'b'), {a: 1}],
    +      [node.limitToFirst(2).endAt(null, 'b'), {a: 1, b: 2}],
    +      [node.limitToFirst(3).endAt(null, 'b'), {a: 1, b: 2}],
    +      [node.limitToLast(1).endAt(null, 'c'), {c: 3}],
    +      [node.limitToLast(1).endAt(null, 'b'), {b: 2}],
    +      [node.limitToLast(2).endAt(null, 'b'), {a: 1, b: 2}],
    +      [node.limitToLast(3).endAt(null, 'b'), {a: 1, b: 2}],
    +    ];
    +
    +    return Promise.all(tasks.map(async task => {
    +      const [query, val] = task;
    +      const ea = EventAccumulatorFactory.waitsForCount(1);
    +      query.on('value', snap => {
    +        ea.addEvent(snap.val());
    +      });
    +      const [newVal] = await ea.promise;
    +      expect(newVal).to.deep.equal(val);
    +    }));
    +  });
    +
    +  it('Set various limits with a startAt name, ensure resulting data is correct from the server.', async function() {
    +    var node = (getRandomNode() as Reference);
    +
    +    await node.set({a: 1, b: 2, c: 3});
    +
    +    const tasks: TaskList = [
    +      [node.startAt().limitToFirst(1), {a: 1}],
    +      [node.startAt(null, 'c').limitToFirst(1), {c: 3}],
    +      [node.startAt(null, 'b').limitToFirst(1), {b: 2}],
    +      // NOTE: technically there is a race condition here. The limitToFirst(1) query will return a single value, which will be
    +      // raised for the limitToFirst(2) callback as well, if it exists already. However, once the server gets the limitToFirst(2)
    +      // query, it will send more data and the correct state will be returned.
    +      [node.startAt(null, 'b').limitToFirst(2), {b: 2, c: 3}],
    +      [node.startAt(null, 'b').limitToFirst(3), {b: 2, c: 3}],
    +    ];
    +
    +    return Promise.all(tasks.map(async task => {
    +      const [query, val] = task;
    +      const ea = EventAccumulatorFactory.waitsForCount(1);
    +      query.on('value', snap => {
    +        ea.addEvent(snap.val());
    +      });
    +      const [newVal] = await ea.promise;
    +      expect(newVal).to.deep.equal(val);
    +    }));
    +  });
    +
    +  it('Set limit, ensure child_removed and child_added events are fired when limit is hit.', function() {
    +    var node = (getRandomNode() as Reference);
    +    var added = '', removed = '';
    +    node.limitToLast(2).on('child_added', function(snap) { added += snap.key + ' '});
    +    node.limitToLast(2).on('child_removed', function(snap) { removed += snap.key + ' '});
    +    node.set({a: 1, b: 2, c: 3});
    +
    +    expect(added).to.equal('b c ');
    +    expect(removed).to.equal('');
    +
    +    added = '';
    +    node.child('d').set(4);
    +    expect(added).to.equal('d ');
    +    expect(removed).to.equal('b ');
    +  });
    +
    +  it('Set limit, ensure child_removed and child_added events are fired when limit is hit, using server data', async function() {
    +    var node = (getRandomNode() as Reference);
    +
    +    await node.set({a: 1, b: 2, c: 3});    
    +
    +    const ea = EventAccumulatorFactory.waitsForCount(2);
    +
    +    var added = '', removed = '';
    +    node.limitToLast(2).on('child_added', function(snap) { 
    +      added += snap.key + ' '; 
    +      ea.addEvent();
    +    });
    +    node.limitToLast(2).on('child_removed', function(snap) { 
    +      removed += snap.key + ' '
    +    });
    +
    +    await ea.promise;
    +
    +    expect(added).to.equal('b c ');
    +    expect(removed).to.equal('');
    +
    +    added = '';
    +    await node.child('d').set(4);
    +
    +    expect(added).to.equal('d ');
    +    expect(removed).to.equal('b ');
    +  });
    +
    +  it('Set start and limit, ensure child_removed and child_added events are fired when limit is hit.', function() {
    +    var node = (getRandomNode() as Reference);
    +
    +    var added = '', removed = '';
    +    node.startAt(null, 'a').limitToFirst(2).on('child_added', function(snap) { added += snap.key + ' '});
    +    node.startAt(null, 'a').limitToFirst(2).on('child_removed', function(snap) { removed += snap.key + ' '});
    +    node.set({a: 1, b: 2, c: 3});
    +    expect(added).to.equal('a b ');
    +    expect(removed).to.equal('');
    +
    +    added = '';
    +    node.child('aa').set(4);
    +    expect(added).to.equal('aa ');
    +    expect(removed).to.equal('b ');
    +  });
    +
    +  it('Set start and limit, ensure child_removed and child_added events are fired when limit is hit, using server data', async function() {
    +    var node = <Reference>getRandomNode()
    +
    +    await node.set({a: 1, b: 2, c: 3});    
    +    const ea = EventAccumulatorFactory.waitsForCount(2);
    +
    +    var added = '', removed = '';
    +    node.startAt(null, 'a').limitToFirst(2).on('child_added', function(snap) { 
    +      added += snap.key + ' '; 
    +      ea.addEvent();
    +    });
    +    node.startAt(null, 'a').limitToFirst(2).on('child_removed', function(snap) { 
    +      removed += snap.key + ' '
    +    });
    +    
    +    await ea.promise;
    +
    +    expect(added).to.equal('a b ');
    +    expect(removed).to.equal('');
    +
    +    added = '';
    +    await node.child('aa').set(4);
    +
    +    expect(added).to.equal('aa ');
    +    expect(removed).to.equal('b ');
    +  });
    +
    +  it("Set start and limit, ensure child_added events are fired when limit isn't hit yet.", function() {
    +    var node = (getRandomNode() as Reference);
    +
    +    var added = '', removed = '';
    +    node.startAt(null, 'a').limitToFirst(2).on('child_added', function(snap) { added += snap.key + ' '});
    +    node.startAt(null, 'a').limitToFirst(2).on('child_removed', function(snap) { removed += snap.key + ' '});
    +    node.set({c: 3});
    +    expect(added).to.equal('c ');
    +    expect(removed).to.equal('');
    +
    +    added = '';
    +    node.child('b').set(4);
    +    expect(added).to.equal('b ');
    +    expect(removed).to.equal('');
    +  });
    +
    +  it("Set start and limit, ensure child_added events are fired when limit isn't hit yet, using server data", async function() {
    +    var node = (getRandomNode() as Reference);
    +
    +    await node.set({c: 3});
    +
    +    const ea = EventAccumulatorFactory.waitsForCount(1);
    +
    +    let added = '';
    +    let removed = '';
    +    node.startAt(null, 'a').limitToFirst(2).on('child_added', function(snap) { 
    +      added += snap.key + ' '
    +      ea.addEvent();
    +    });
    +    node.startAt(null, 'a').limitToFirst(2).on('child_removed', function(snap) { 
    +      removed += snap.key + ' '
    +    });
    +
    +    await ea.promise;
    +
    +    expect(added).to.equal('c ');
    +    expect(removed).to.equal('');
    +
    +    added = '';
    +    await node.child('b').set(4);
    +
    +    expect(added).to.equal('b ');
    +    expect(removed).to.equal('');
    +  });
    +
    +  it('Set a limit, ensure child_removed and child_added events are fired when limit is satisfied and you remove an item.', async function() {
    +    var node = (getRandomNode() as Reference);
    +    const ea = EventAccumulatorFactory.waitsForCount(1);
    +
    +    var added = '', removed = '';
    +    node.limitToLast(2).on('child_added', function(snap) { 
    +      added += snap.key + ' '
    +      ea.addEvent();
    +    });
    +    node.limitToLast(2).on('child_removed', function(snap) { removed += snap.key + ' '});
    +    node.set({a: 1, b: 2, c: 3});
    +    expect(added).to.equal('b c ');
    +    expect(removed).to.equal('');
    +
    +    added = '';
    +    node.child('b').remove();
    +    expect(removed).to.equal('b ');
    +    
    +    await ea.promise;
    +  });
    +
    +  it('Set a limit, ensure child_removed and child_added events are fired when limit is satisfied and you remove an item. Using server data', async function() {
    +    var node = (getRandomNode() as Reference);
    +
    +    await node.set({a: 1, b: 2, c: 3});
    +
    +    let ea = EventAccumulatorFactory.waitsForCount(2);
    +    var added = '', removed = '';
    +    node.limitToLast(2).on('child_added', function(snap) { 
    +      added += snap.key + ' '; 
    +      ea.addEvent();
    +    });
    +    node.limitToLast(2).on('child_removed', function(snap) { 
    +      removed += snap.key + ' '
    +    });
    +
    +    await ea.promise;
    +
    +    expect(added).to.equal('b c ');
    +    expect(removed).to.equal('');
    +
    +    // We are going to wait for one more event before closing
    +    ea = EventAccumulatorFactory.waitsForCount(1);    
    +    added = '';
    +    await node.child('b').remove();
    +
    +    expect(removed).to.equal('b ');
    +
    +    await ea.promise;
    +    expect(added).to.equal('a ');
    +  });
    +
    +  it('Set a limit, ensure child_removed events are fired when limit is satisfied, you remove an item, and there are no more.', function() {
    +    var node = (getRandomNode() as Reference);
    +
    +    var added = '', removed = '';
    +    node.limitToLast(2).on('child_added', function(snap) { added += snap.key + ' '});
    +    node.limitToLast(2).on('child_removed', function(snap) { removed += snap.key + ' '});
    +    node.set({b: 2, c: 3});
    +    expect(added).to.equal('b c ');
    +    expect(removed).to.equal('');
    +
    +    added = '';
    +    node.child('b').remove();
    +    expect(added).to.equal('');
    +    expect(removed).to.equal('b ');
    +    node.child('c').remove();
    +    expect(removed).to.equal('b c ');
    +  });
    +
    +  it('Set a limit, ensure child_removed events are fired when limit is satisfied, you remove an item, and there are no more. Using server data', async function() {
    +    var node = (getRandomNode() as Reference);
    +    const ea = EventAccumulatorFactory.waitsForCount(2);
    +    let added = '';
    +    let removed = '';
    +    await node.set({b: 2, c: 3});
    +
    +    node.limitToLast(2).on('child_added', function(snap) { 
    +      added += snap.key + ' ';
    +      ea.addEvent();
    +    });
    +    node.limitToLast(2).on('child_removed', function(snap) { 
    +      removed += snap.key + ' '
    +    });
    +
    +    await ea.promise;
    +
    +    expect(added).to.equal('b c ');
    +    expect(removed).to.equal('');
    +
    +    added = '';
    +    
    +    await node.child('b').remove();
    +
    +    expect(added).to.equal('');
    +    expect(removed).to.equal('b ');
    +  });
    +
    +  it('Ensure startAt / endAt with priority works.', async function() {
    +    var node = (getRandomNode() as Reference);
    +
    +    const tasks: TaskList = [
    +      [node.startAt('w').endAt('y'), {b: 2, c: 3, d: 4}],
    +      [node.startAt('w').endAt('w'), {d: 4 }],
    +      [node.startAt('a').endAt('c'), null],
    +    ]
    +
    +    await node.set({
    +      a: {'.value': 1, '.priority': 'z'},
    +      b: {'.value': 2, '.priority': 'y'},
    +      c: {'.value': 3, '.priority': 'x'},
    +      d: {'.value': 4, '.priority': 'w'}
    +    });
    +
    +    return Promise.all(tasks.map(async task => {
    +      const [query, val] = task;
    +      const ea = EventAccumulatorFactory.waitsForCount(1);
    +      query.on('value', snap => {
    +        ea.addEvent(snap.val());
    +      });
    +      const [newVal] = await ea.promise;
    +      expect(newVal).to.deep.equal(val);
    +    }));
    +  });
    +
    +  it('Ensure startAt / endAt with priority work with server data.', async function() {
    +    var node = (getRandomNode() as Reference);
    +    
    +    await node.set({
    +      a: {'.value': 1, '.priority': 'z'},
    +      b: {'.value': 2, '.priority': 'y'},
    +      c: {'.value': 3, '.priority': 'x'},
    +      d: {'.value': 4, '.priority': 'w'}
    +    });
    +
    +    const tasks: TaskList = [
    +      [node.startAt('w').endAt('y'), {b: 2, c: 3, d: 4}],
    +      [node.startAt('w').endAt('w'), {d: 4 }],
    +      [node.startAt('a').endAt('c'), null],
    +    ];
    +
    +    return Promise.all(tasks.map(async task => {
    +      const [query, val] = task;
    +      const ea = EventAccumulatorFactory.waitsForCount(1);
    +      query.on('value', snap => {
    +        ea.addEvent(snap.val());
    +      });
    +      const [newVal] = await ea.promise;
    +      expect(newVal).to.deep.equal(val);
    +    }));
    +  });
    +
    +  it('Ensure startAt / endAt with priority and name works.', async function() {
    +    var node = (getRandomNode() as Reference);
    +
    +    await node.set({
    +      a: {'.value': 1, '.priority': 1},
    +      b: {'.value': 2, '.priority': 1},
    +      c: {'.value': 3, '.priority': 2},
    +      d: {'.value': 4, '.priority': 2}
    +    });
    +
    +    const tasks: TaskList = [
    +      [node.startAt(1, 'a').endAt(2, 'd'), {a: 1, b: 2, c: 3, d: 4}],
    +      [node.startAt(1, 'b').endAt(2, 'c'), {b: 2, c: 3}],
    +      [node.startAt(1, 'c').endAt(2), {c: 3, d: 4}],
    +    ];
    +
    +    return Promise.all(tasks.map(async task => {
    +      const [query, val] = task;
    +      const ea = EventAccumulatorFactory.waitsForCount(1);
    +      query.on('value', snap => {
    +        ea.addEvent(snap.val());
    +      });
    +      const [newVal] = await ea.promise;
    +      expect(newVal).to.deep.equal(val);
    +    }));
    +  });
    +
    +  it('Ensure startAt / endAt with priority and name work with server data', async function() {
    +    var node = (getRandomNode() as Reference);
    +
    +    await node.set({
    +      a: {'.value': 1, '.priority': 1},
    +      b: {'.value': 2, '.priority': 1},
    +      c: {'.value': 3, '.priority': 2},
    +      d: {'.value': 4, '.priority': 2}
    +    });
    +    const tasks: TaskList = [
    +      [node.startAt(1, 'a').endAt(2, 'd'), {a: 1, b: 2, c: 3, d: 4}],
    +      [node.startAt(1, 'b').endAt(2, 'c'), {b: 2, c: 3}],
    +      [node.startAt(1, 'c').endAt(2), {c: 3, d: 4}],
    +    ];
    +    return Promise.all(tasks.map(async task => {
    +      const [query, val] = task;
    +      const ea = EventAccumulatorFactory.waitsForCount(1);
    +      query.on('value', snap => {
    +        ea.addEvent(snap.val());
    +      });
    +      const [newVal] = await ea.promise;
    +      expect(newVal).to.deep.equal(val);
    +    }));
    +  });
    +
    +  it('Ensure startAt / endAt with priority and name works (2).', function() {
    +    var node = (getRandomNode() as Reference);
    +
    +    const tasks: TaskList = [
    +      [node.startAt(1, 'c').endAt(2, 'b'), {a: 1, b: 2, c: 3, d: 4}],
    +      [node.startAt(1, 'd').endAt(2, 'a'), {d: 4, a: 1}],
    +      [node.startAt(1, 'e').endAt(2), {a: 1, b: 2}],
    +    ]
    +
    +    node.set({
    +      c: {'.value': 3, '.priority': 1},
    +      d: {'.value': 4, '.priority': 1},
    +      a: {'.value': 1, '.priority': 2},
    +      b: {'.value': 2, '.priority': 2}
    +    });
    +
    +    return Promise.all(tasks.map(async task => {
    +      const [query, val] = task;
    +      const ea = EventAccumulatorFactory.waitsForCount(1);
    +      query.on('value', snap => {
    +        ea.addEvent(snap.val());
    +      });
    +      const [newVal] = await ea.promise;
    +      expect(newVal).to.deep.equal(val);
    +    }));
    +  });
    +
    +  it('Ensure startAt / endAt with priority and name works (2). With server data', async function() {
    +    var node = (getRandomNode() as Reference);
    +    
    +    await node.set({
    +      c: {'.value': 3, '.priority': 1},
    +      d: {'.value': 4, '.priority': 1},
    +      a: {'.value': 1, '.priority': 2},
    +      b: {'.value': 2, '.priority': 2}
    +    });
    +
    +    const tasks: TaskList = [
    +      [node.startAt(1, 'c').endAt(2, 'b'), {a: 1, b: 2, c: 3, d: 4}],
    +      [node.startAt(1, 'd').endAt(2, 'a'), {d: 4, a: 1}],
    +      [node.startAt(1, 'e').endAt(2), {a: 1, b: 2}],
    +    ];
    +    
    +    return Promise.all(tasks.map(async task => {
    +      const [query, val] = task;
    +      const ea = EventAccumulatorFactory.waitsForCount(1);
    +      query.on('value', snap => {
    +        ea.addEvent(snap.val());
    +      });
    +      const [newVal] = await ea.promise;
    +      expect(newVal).to.deep.equal(val);
    +    }));
    +  });
    +
    +  it('Set a limit, add some nodes, ensure prevName works correctly.', function() {
    +    var node = (getRandomNode() as Reference);
    +
    +    var added = '';
    +    node.limitToLast(2).on('child_added', function(snap, prevName) {
    +      added += snap.key + ' ' + prevName + ', ';
    +    });
    +
    +    node.child('a').set(1);
    +    expect(added).to.equal('a null, ');
    +
    +    added = '';
    +    node.child('c').set(3);
    +    expect(added).to.equal('c a, ');
    +
    +    added = '';
    +    node.child('b').set(2);
    +    expect(added).to.equal('b null, ');
    +
    +    added = '';
    +    node.child('d').set(4);
    +    expect(added).to.equal('d c, ');
    +  });
    +
    +  it('Set a limit, add some nodes, ensure prevName works correctly. With server data', async function() {
    +    var node = (getRandomNode() as Reference);
    +
    +    let added = '';
    +    await node.child('a').set(1);
    +    
    +    const ea = EventAccumulatorFactory.waitsForCount(1);
    +    node.limitToLast(2).on('child_added', function(snap, prevName) {
    +      added += snap.key + ' ' + prevName + ', ';
    +      ea.addEvent();
    +    });
    +
    +    await ea.promise;
    +
    +    expect(added).to.equal('a null, ');
    +
    +    added = '';
    +    await node.child('c').set(3);
    +
    +    expect(added).to.equal('c a, ');
    +
    +    added = '';
    +    await node.child('b').set(2);
    +
    +    expect(added).to.equal('b null, ');
    +
    +    added = '';
    +    await node.child('d').set(4);
    +
    +    expect(added).to.equal('d c, ');
    +  });
    +
    +  it('Set a limit, move some nodes, ensure prevName works correctly.', function() {
    +    var node = (getRandomNode() as Reference);
    +    var moved = '';
    +    node.limitToLast(2).on('child_moved', function(snap, prevName) {
    +      moved += snap.key + ' ' + prevName + ', ';
    +    });
    +
    +    node.child('a').setWithPriority('a', 10);
    +    node.child('b').setWithPriority('b', 20);
    +    node.child('c').setWithPriority('c', 30);
    +    node.child('d').setWithPriority('d', 40);
    +
    +    node.child('c').setPriority(50);
    +    expect(moved).to.equal('c d, ');
    +
    +    moved = '';
    +    node.child('c').setPriority(35);
    +    expect(moved).to.equal('c null, ');
    +
    +    moved = '';
    +    node.child('b').setPriority(33);
    +    expect(moved).to.equal('');
    +  });
    +
    +  it('Set a limit, move some nodes, ensure prevName works correctly, with server data', async function() {
    +    var node = (getRandomNode() as Reference);
    +    var moved = '';
    +
    +    node.child('a').setWithPriority('a', 10);
    +    node.child('b').setWithPriority('b', 20);
    +    node.child('c').setWithPriority('c', 30);
    +    await node.child('d').setWithPriority('d', 40);
    +
    +    node.limitToLast(2).on('child_moved', async function(snap, prevName) {
    +      moved += snap.key + ' ' + prevName + ', ';
    +    });
    +    // Need to load the data before the set so we'll see the move
    +    await node.limitToLast(2).once('value');
    +
    +    await node.child('c').setPriority(50);
    +
    +    expect(moved).to.equal('c d, ');
    +
    +    moved = '';
    +    await node.child('c').setPriority(35);
    +  
    +    expect(moved).to.equal('c null, ');
    +    moved = '';
    +    await node.child('b').setPriority(33);
    +  
    +    expect(moved).to.equal('');
    +  });
    +
    +  it('Numeric priorities: Set a limit, move some nodes, ensure prevName works correctly.', function() {
    +    var node = (getRandomNode() as Reference);
    +
    +    var moved = '';
    +    node.limitToLast(2).on('child_moved', function(snap, prevName) {
    +      moved += snap.key + ' ' + prevName + ', ';
    +    });
    +
    +    node.child('a').setWithPriority('a', 1);
    +    node.child('b').setWithPriority('b', 2);
    +    node.child('c').setWithPriority('c', 3);
    +    node.child('d').setWithPriority('d', 4);
    +
    +    node.child('c').setPriority(10);
    +    expect(moved).to.equal('c d, ');
    +  });
    +
    +  it('Numeric priorities: Set a limit, move some nodes, ensure prevName works correctly. With server data', async function() {
    +    var node = (getRandomNode() as Reference);
    +    let moved = '';
    +
    +    node.child('a').setWithPriority('a', 1);
    +    node.child('b').setWithPriority('b', 2);
    +    node.child('c').setWithPriority('c', 3);
    +    await node.child('d').setWithPriority('d', 4);
    +
    +    node.limitToLast(2).on('child_moved', function(snap, prevName) {
    +      moved += snap.key + ' ' + prevName + ', ';
    +    });
    +    // Need to load the data before the set so we'll see the move
    +    await node.limitToLast(2).once('value');
    +
    +    await node.child('c').setPriority(10);
    +    
    +    expect(moved).to.equal('c d, ');
    +  });
    +
    +  it('Set a limit, add a bunch of nodes, ensure local events are correct.', function() {
    +    var node = (getRandomNode() as Reference);
    +    node.set({});
    +    var eventHistory = '';
    +
    +    node.limitToLast(2).on('child_added', function(snap) {
    +      eventHistory = eventHistory + snap.val() + ' added, ';
    +    });
    +    node.limitToLast(2).on('child_removed', function(snap) {
    +      eventHistory = eventHistory + snap.val() + ' removed, ';
    +    });
    +
    +    for (var i = 0; i < 5; i++) {
    +      var n = node.push();
    +      n.set(i);
    +    }
    +
    +    expect(eventHistory).to.equal('0 added, 1 added, 0 removed, 2 added, 1 removed, 3 added, 2 removed, 4 added, ');
    +  });
    +
    +  it('Set a limit, add a bunch of nodes, ensure remote events are correct.', async function() {
    +    var nodePair = getRandomNode(2);
    +    var writeNode = nodePair[0];
    +    var readNode = nodePair[1];
    +    const ea = new EventAccumulator(() => {
    +      try {
    +        expect(eventHistory).to.equal('3 added, 4 added, ');
    +        return true;
    +      } catch(err) {
    +        return false;
    +      }
    +    });
    +    var eventHistory = '';
    +
    +    readNode.limitToLast(2).on('child_added', function(snap) {
    +      eventHistory = eventHistory + snap.val() + ' added, ';
    +      ea.addEvent();
    +    });
    +    readNode.limitToLast(2).on('child_removed', function(snap) {
    +      eventHistory = eventHistory.replace(snap.val() + ' added, ', '');
    +      /**
    +       * This test expects this code NOT to fire, so by adding this
    +       * I trigger the resolve early if it happens to fire and fail
    +       * the expect at the end
    +       */
    +      ea.addEvent();
    +    });
    +
    +    const promises = [];
    +    for (var i = 0; i < 5; i++) {
    +      var n = writeNode.push();
    +      n.set(i);
    +    }
    +
    +    await ea.promise;
    +  });
    +
    +  it('Ensure on() returns callback function.', function() {
    +    var node = (getRandomNode() as Reference);
    +    var callback = function() { };
    +    var ret = node.on('value', callback);
    +    expect(ret).to.equal(callback);
    +  });
    +
    +  it("Limit on unsynced node fires 'value'.", function(done) {
    +    var f = (getRandomNode() as Reference);
    +    f.limitToLast(1).on('value', function() {
    +      done();
    +    });
    +  });
    +
    +  it('Filtering to only null priorities works.', async function() {
    +    var f = (getRandomNode() as Reference);
    +
    +    const ea = EventAccumulatorFactory.waitsForCount(1);
    +    f.root.child('.info/connected').on('value', function(snap) {
    +      ea.addEvent();
    +    });
    +
    +    await ea.promise;
    +
    +    f.set({
    +      a: {'.priority': null, '.value': 0},
    +      b: {'.priority': null, '.value': 1},
    +      c: {'.priority': '2', '.value': 2},
    +      d: {'.priority': 3, '.value': 3},
    +      e: {'.priority': 'hi', '.value': 4}
    +    });
    +
    +    const snapAcc = EventAccumulatorFactory.waitsForCount(1);
    +    f.startAt(null).endAt(null).on('value', snap => {
    +      snapAcc.addEvent(snap.val());
    +    });
    +
    +    const [val] = await snapAcc.promise;
    +    expect(val).to.deep.equal({a: 0, b: 1});
    +  });
    +
    +  it('null priorities included in endAt(2).', async function() {
    +    var f = (getRandomNode() as Reference);
    +    
    +    f.set({
    +      a: {'.priority': null, '.value': 0},
    +      b: {'.priority': null, '.value': 1},
    +      c: {'.priority': 2, '.value': 2},
    +      d: {'.priority': 3, '.value': 3},
    +      e: {'.priority': 'hi', '.value': 4}
    +    });
    +
    +    const ea = EventAccumulatorFactory.waitsForCount(1);
    +    f.endAt(2).on('value', snap => {
    +      ea.addEvent(snap.val());
    +    });
    +    
    +    const [val] = await ea.promise;
    +    expect(val).to.deep.equal({a: 0, b: 1, c: 2});
    +  });
    +
    +  it('null priorities not included in startAt(2).', async function() {
    +    var f = (getRandomNode() as Reference);
    +    
    +    f.set({
    +      a: {'.priority': null, '.value': 0},
    +      b: {'.priority': null, '.value': 1},
    +      c: {'.priority': 2, '.value': 2},
    +      d: {'.priority': 3, '.value': 3},
    +      e: {'.priority': 'hi', '.value': 4}
    +    });
    +
    +    const ea = EventAccumulatorFactory.waitsForCount(1);
    +    
    +    f.startAt(2).on('value', snap => {
    +      ea.addEvent(snap.val());
    +    });
    +
    +    const [val] = await ea.promise;
    +    expect(val).to.deep.equal({c: 2, d: 3, e: 4});
    +  });
    +
    +  function dumpListens(node: Query) {
    +    var listens = node.repo.persistentConnection_.listens_;
    +    var nodePath = getPath(node);
    +    var listenPaths = [];
    +    for (var path in listens) {
    +      if (path.substring(0, nodePath.length) === nodePath) {
    +        listenPaths.push(path);
    +      }
    +    }
    +
    +    listenPaths.sort();
    +    var dumpPieces = [];
    +    for (var i = 0; i < listenPaths.length; i++) {
    +
    +      var queryIds = [];
    +      for (var queryId in listens[listenPaths[i]]) {
    +        queryIds.push(queryId);
    +      }
    +      queryIds.sort();
    +      if (queryIds.length > 0) {
    +        dumpPieces.push(listenPaths[i].substring(nodePath.length) + ':' + queryIds.join(','));
    +      }
    +    }
    +
    +    return dumpPieces.join(';');
    +  }
    +
    +  it('Dedupe listens: listen on parent.', function() {
    +    var node = (getRandomNode() as Reference);
    +    expect(dumpListens(node)).to.equal('');
    +
    +    var aOn = node.child('a').on('value', function() { });
    +    expect(dumpListens(node)).to.equal('/a:default');
    +
    +    var rootOn = node.on('value', function() {});
    +    expect(dumpListens(node)).to.equal(':default');
    +
    +    node.off('value', rootOn);
    +    expect(dumpListens(node)).to.equal('/a:default');
    +
    +    node.child('a').off('value', aOn);
    +    expect(dumpListens(node)).to.equal('');
    +  });
    +
    +  it('Dedupe listens: listen on grandchild.', function() {
    +    var node = (getRandomNode() as Reference);
    +
    +    var rootOn = node.on('value', function() {});
    +    expect(dumpListens(node)).to.equal(':default');
    +
    +    var aaOn = node.child('a/aa').on('value', function() { });
    +    expect(dumpListens(node)).to.equal(':default');
    +
    +    node.off('value', rootOn);
    +    node.child('a/aa').off('value', aaOn);
    +    expect(dumpListens(node)).to.equal('');
    +  });
    +
    +  it('Dedupe listens: listen on grandparent of two children.', function() {
    +    var node = (getRandomNode() as Reference);
    +    expect(dumpListens(node)).to.equal('');
    +
    +    var aaOn = node.child('a/aa').on('value', function() { });
    +    expect(dumpListens(node)).to.equal('/a/aa:default');
    +
    +    var bbOn = node.child('a/bb').on('value', function() { });
    +    expect(dumpListens(node)).to.equal('/a/aa:default;/a/bb:default');
    +
    +    var rootOn = node.on('value', function() {});
    +    expect(dumpListens(node)).to.equal(':default');
    +
    +    node.off('value', rootOn);
    +    expect(dumpListens(node)).to.equal('/a/aa:default;/a/bb:default');
    +
    +    node.child('a/aa').off('value', aaOn);
    +    expect(dumpListens(node)).to.equal('/a/bb:default');
    +
    +    node.child('a/bb').off('value', bbOn);
    +    expect(dumpListens(node)).to.equal('');
    +  });
    +
    +  it('Dedupe queried listens: multiple queried listens; no dupes', function() {
    +    var node = (getRandomNode() as Reference);
    +    expect(dumpListens(node)).to.equal('');
    +
    +    var aLim1On = node.child('a').limitToLast(1).on('value', function() { });
    +    expect(dumpListens(node)).to.equal('/a:{"l":1,"vf":"r"}');
    +
    +    var rootLim1On = node.limitToLast(1).on('value', function() { });
    +    expect(dumpListens(node)).to.equal(':{"l":1,"vf":"r"};/a:{"l":1,"vf":"r"}');
    +
    +    var aLim5On = node.child('a').limitToLast(5).on('value', function() { });
    +    expect(dumpListens(node)).to.equal(':{"l":1,"vf":"r"};/a:{"l":1,"vf":"r"},{"l":5,"vf":"r"}');
    +
    +    node.limitToLast(1).off('value', rootLim1On);
    +    expect(dumpListens(node)).to.equal('/a:{"l":1,"vf":"r"},{"l":5,"vf":"r"}');
    +
    +    node.child('a').limitToLast(1).off('value', aLim1On);
    +    node.child('a').limitToLast(5).off('value', aLim5On);
    +    expect(dumpListens(node)).to.equal('');
    +  });
    +
    +  it('Dedupe queried listens: listen on parent of queried children.', function() {
    +    var node = (getRandomNode() as Reference);
    +
    +    var aLim1On = node.child('a').limitToLast(1).on('value', function() { });
    +    expect(dumpListens(node)).to.equal('/a:{"l":1,"vf":"r"}');
    +
    +    var bLim1On = node.child('b').limitToLast(1).on('value', function() { });
    +    expect(dumpListens(node)).to.equal('/a:{"l":1,"vf":"r"};/b:{"l":1,"vf":"r"}');
    +
    +    var rootOn = node.on('value', function() { });
    +    expect(dumpListens(node)).to.equal(':default');
    +
    +    // remove in slightly random order.
    +    node.child('a').limitToLast(1).off('value', aLim1On);
    +    expect(dumpListens(node)).to.equal(':default');
    +
    +    node.off('value', rootOn);
    +    expect(dumpListens(node)).to.equal('/b:{"l":1,"vf":"r"}');
    +
    +    node.child('b').limitToLast(1).off('value', bLim1On);
    +    expect(dumpListens(node)).to.equal('');
    +  });
    +
    +  it('Limit with mix of null and non-null priorities.', function() {
    +    var node = (getRandomNode() as Reference);
    +
    +    var children = [];
    +    node.limitToLast(5).on('child_added', function(childSnap) {
    +      children.push(childSnap.key);
    +    });
    +
    +    node.set({
    +      'Vikrum': {'.priority': 1000, 'score': 1000, 'name': 'Vikrum'},
    +      'Mike': {'.priority': 500, 'score': 500, 'name': 'Mike'},
    +      'Andrew': {'.priority': 50, 'score': 50, 'name': 'Andrew'},
    +      'James': {'.priority': 7, 'score': 7, 'name': 'James'},
    +      'Sally': {'.priority': -7, 'score': -7, 'name': 'Sally'},
    +      'Fred': {'score': 0, 'name': 'Fred'}
    +    });
    +
    +    expect(children.join(',')).to.equal('Sally,James,Andrew,Mike,Vikrum');
    +  });
    +
    +  it('Limit with mix of null and non-null priorities using server data', async function() {
    +    var node = <Reference>getRandomNode(),
    +        done, count;
    +
    +    var children = [];
    +    await node.set({
    +      'Vikrum': {'.priority': 1000, 'score': 1000, 'name': 'Vikrum'},
    +      'Mike': {'.priority': 500, 'score': 500, 'name': 'Mike'},
    +      'Andrew': {'.priority': 50, 'score': 50, 'name': 'Andrew'},
    +      'James': {'.priority': 7, 'score': 7, 'name': 'James'},
    +      'Sally': {'.priority': -7, 'score': -7, 'name': 'Sally'},
    +      'Fred': {'score': 0, 'name': 'Fred'}
    +    });
    +
    +    const ea = EventAccumulatorFactory.waitsForCount(5);
    +    node.limitToLast(5).on('child_added', function(childSnap) {
    +      children.push(childSnap.key);
    +      ea.addEvent();
    +    });
    +
    +    await ea.promise;
    +
    +    expect(children.join(',')).to.equal('Sally,James,Andrew,Mike,Vikrum');
    +  });
    +
    +  it('.on() with a context works.', function() {
    +    var ref = (getRandomNode() as Reference);
    +
    +    var ListenerDoohickey = function() { this.snap = null; };
    +    ListenerDoohickey.prototype.onEvent = function(snap) {
    +      this.snap = snap;
    +    };
    +
    +    var l = new ListenerDoohickey();
    +    ref.on('value', l.onEvent, l);
    +
    +    ref.set('test');
    +    expect(l.snap.val()).to.equal('test');
    +
    +    ref.off('value', l.onEvent, l);
    +
    +    // Ensure we don't get any more events.
    +    ref.set('blah');
    +    expect(l.snap.val()).to.equal('test');
    +  });
    +
    +  it('.once() with a context works.', function() {
    +    var ref = (getRandomNode() as Reference);
    +
    +    var ListenerDoohickey = function() { this.snap = null; };
    +    ListenerDoohickey.prototype.onEvent = function(snap) {
    +      this.snap = snap;
    +    };
    +
    +    var l = new ListenerDoohickey();
    +    ref.once('value', l.onEvent, l);
    +
    +    ref.set('test');
    +    expect(l.snap.val()).to.equal('test');
    +
    +    // Shouldn't get any more events.
    +    ref.set('blah');
    +    expect(l.snap.val()).to.equal('test');
    +  });
    +
    +  it('handles an update that deletes the entire window in a query', function() {
    +    var ref = (getRandomNode() as Reference);
    +
    +    var snaps = [];
    +    ref.limitToLast(2).on('value', function(snap) {
    +      snaps.push(snap.val());
    +    });
    +
    +    ref.set({
    +      a: {'.value': 1, '.priority': 1},
    +      b: {'.value': 2, '.priority': 2},
    +      c: {'.value': 3, '.priority': 3}
    +    });
    +    ref.update({
    +      b: null,
    +      c: null
    +    });
    +
    +    expect(snaps.length).to.equal(2);
    +    expect(snaps[0]).to.deep.equal({b: 2, c: 3});
    +    // The original set is still outstanding (synchronous API), so we have a full cache to re-window against
    +    expect(snaps[1]).to.deep.equal({a: 1});
    +  });
    +
    +  it('handles an out-of-view query on a child', function() {
    +    var ref = (getRandomNode() as Reference);
    +
    +    var parent = null;
    +    ref.limitToLast(1).on('value', function(snap) {
    +      parent = snap.val();
    +    });
    +
    +    var child = null;
    +    ref.child('a').on('value', function(snap) {
    +      child = snap.val();
    +    });
    +
    +    ref.set({a: 1, b: 2});
    +    expect(parent).to.deep.equal({b: 2});
    +    expect(child).to.equal(1);
    +
    +    ref.update({c: 3});
    +    expect(parent).to.deep.equal({c: 3});
    +    expect(child).to.equal(1);
    +  });
    +
    +  it('handles a child query going out of view of the parent', function() {
    +    var ref = (getRandomNode() as Reference);
    +
    +    var parent = null;
    +    ref.limitToLast(1).on('value', function(snap) {
    +      parent = snap.val();
    +    });
    +
    +    var child = null;
    +    ref.child('a').on('value', function(snap) {
    +      child = snap.val();
    +    });
    +
    +    ref.set({a: 1});
    +    expect(parent).to.deep.equal({a: 1});
    +    expect(child).to.equal(1);
    +    ref.child('b').set(2);
    +    expect(parent).to.deep.equal({b: 2});
    +    expect(child).to.equal(1);
    +    ref.child('b').remove();
    +    expect(parent).to.deep.equal({a: 1});
    +    expect(child).to.equal(1);
    +  });
    +
    +  it('handles diverging views', function() {
    +    var ref = (getRandomNode() as Reference);
    +
    +    var c = null;
    +    ref.limitToLast(1).endAt(null, 'c').on('value', function(snap) {
    +      c = snap.val();
    +    });
    +
    +    var d = null;
    +    ref.limitToLast(1).endAt(null, 'd').on('value', function(snap) {
    +      d = snap.val();
    +    });
    +
    +    ref.set({a: 1, b: 2, c: 3});
    +    expect(c).to.deep.equal({c: 3});
    +    expect(d).to.deep.equal({c: 3});
    +    ref.child('d').set(4);
    +    expect(c).to.deep.equal({c: 3});
    +    expect(d).to.deep.equal({d: 4});
    +  });
    +
    +  it('handles removing a queried element', async function() {
    +    var ref = (getRandomNode() as Reference);
    +
    +    var val;
    +    const ea = EventAccumulatorFactory.waitsForCount(1);
    +    ref.limitToLast(1).on('child_added', function(snap) {
    +      val = snap.val();
    +      ea.addEvent();
    +    });
    +
    +    ref.set({a: 1, b: 2});
    +    expect(val).to.equal(2);
    +
    +    ref.child('b').remove();
    +
    +    await ea.promise;
    +
    +    expect(val).to.equal(1);
    +  });
    +
    +  it('.startAt().limitToFirst(1) works.', function(done) {
    +    var ref = (getRandomNode() as Reference);
    +    ref.set({a: 1, b: 2});
    +    
    +    var val;
    +    ref.startAt().limitToFirst(1).on('child_added', function(snap) {
    +      val = snap.val();
    +      if (val === 1) {
    +        done();
    +      }
    +    });
    +  });
    +
    +  it('.startAt().limitToFirst(1) and then remove first child (case 1664).', async function() {
    +    var ref = (getRandomNode() as Reference);
    +    ref.set({a: 1, b: 2});
    +
    +    const ea = EventAccumulatorFactory.waitsForCount(1);
    +    var val;
    +    ref.startAt().limitToFirst(1).on('child_added', function(snap) {
    +      val = snap.val();
    +      ea.addEvent();
    +    });
    +
    +    await ea.promise;
    +    expect(val).to.equal(1);
    +
    +    ea.reset();
    +    ref.child('a').remove();
    +
    +    await ea.promise;
    +    expect(val).to.equal(2);
    +  });
    +
    +  it('.startAt() with two arguments works properly (case 1169).', function(done) {
    +    var ref = (getRandomNode() as Reference);
    +    const data = { 
    +      'Walker': { 
    +        name: 'Walker', 
    +        score: 20, 
    +        '.priority': 20 
    +      }, 
    +      'Michael': { 
    +        name: 'Michael', 
    +        score: 100, 
    +        '.priority': 100 
    +      } 
    +    };
    +    ref.set(data, function() {
    +      ref.startAt(20, 'Walker').limitToFirst(2).on('value', function(s) {
    +        var childNames = [];
    +        s.forEach(function(node) { childNames.push(node.key); });
    +        expect(childNames).to.deep.equal(['Walker', 'Michael']);
    +        done();
    +      });
    +    });
    +  });
    +
    +  it('handles multiple queries on the same node', async function() {
    +    var ref = (getRandomNode() as Reference);
    +
    +    await ref.set({
    +      a: 1,
    +      b: 2,
    +      c: 3,
    +      d: 4,
    +      e: 5,
    +      f: 6
    +    });
    +
    +    const ea = EventAccumulatorFactory.waitsForCount(1);
    +
    +    var firstListen = false
    +    ref.limitToLast(2).on('value', function(snap) {
    +      // This shouldn't get called twice, we don't update the values here
    +      expect(firstListen).to.be.false;
    +      firstListen = true;
    +      ea.addEvent();
    +    });
    +
    +    await ea.promise;
    +
    +    // now do consecutive once calls
    +    await ref.limitToLast(1).once('value');
    +    const snap = await ref.limitToLast(1).once('value');
    +    var val = snap.val();
    +    expect(val).to.deep.equal({f: 6});
    +  });
    +
    +  it('handles once called on a node with a default listener', async function() {
    +    var ref = (getRandomNode() as Reference);
    +
    +    await ref.set({
    +      a: 1,
    +      b: 2,
    +      c: 3,
    +      d: 4,
    +      e: 5,
    +      f: 6
    +    });
    +
    +    const ea = EventAccumulatorFactory.waitsForCount(1);
    +    // Setup value listener
    +    ref.on('value', function(snap) {
    +      ea.addEvent();
    +    });
    +
    +    await ea.promise;
    +
    +    // now do the once call
    +    const snap = await ref.limitToLast(1).once('child_added');
    +    var val = snap.val();
    +    expect(val).to.equal(6);
    +  });
    +
    +
    +  it('handles once called on a node with a default listener and non-complete limit', async function() {
    +    var ref = <Reference>getRandomNode(),
    +        ready, done;
    +    
    +    await ref.set({
    +      a: 1,
    +      b: 2,
    +      c: 3
    +    });
    +
    +    const ea = EventAccumulatorFactory.waitsForCount(1);
    +    // Setup value listener
    +    ref.on('value', function(snap) {
    +      ea.addEvent();
    +    });
    +
    +    await ea.promise;
    +
    +    // now do the once call
    +    const snap = await ref.limitToLast(5).once('value');
    +    var val = snap.val();
    +    expect(val).to.deep.equal({a: 1, b: 2, c: 3});
    +  });
    +
    +  it('Remote remove triggers events.', function(done) {
    +    var refPair = getRandomNode(2), writeRef = refPair[0], readRef = refPair[1];
    +
    +    writeRef.set({ a: 'a', b: 'b', c: 'c', d: 'd', e: 'e' }, function() {
    +
    +      // Wait to get the initial data, and then remove 'c' remotely and wait for new data.
    +      var count = 0;
    +      readRef.limitToLast(5).on('value', function(s) {
    +        count++;
    +        if (count == 1) {
    +          expect(s.val()).to.deep.equal({a: 'a', b: 'b', c: 'c', d: 'd', e: 'e' });
    +          writeRef.child('c').remove();
    +        } else {
    +          expect(count).to.equal(2);
    +          expect(s.val()).to.deep.equal({a: 'a', b: 'b', d: 'd', e: 'e' });
    +          done();
    +        }
    +      });
    +    });
    +  });
    +
    +  it(".endAt(null, 'f').limitToLast(5) returns the right set of children.", function(done) {
    +    var ref = (getRandomNode() as Reference);
    +    ref.set({ a: 'a', b: 'b', c: 'c', d: 'd', e: 'e', f: 'f', g: 'g', h: 'h' }, function() {
    +      ref.endAt(null, 'f').limitToLast(5).on('value', function(s) {
    +        expect(s.val()).to.deep.equal({b: 'b', c: 'c', d: 'd', e: 'e', f: 'f' });
    +        done();
    +      });
    +    });
    +  });
    +
    +  it('complex update() at query root raises correct value event', function(done) {
    +    var nodePair = getRandomNode(2);
    +    var writer = nodePair[0];
    +    var reader = nodePair[1];
    +
    +    var readerLoaded = false, numEventsReceived = 0;
    +    writer.child('foo').set({a: 1, b: 2, c: 3, d: 4, e: 5}, function(error, dummy) {
    +      reader.child('foo').startAt().limitToFirst(4).on('value', function(snapshot) {
    +        var val = snapshot.val();
    +        if (!readerLoaded) {
    +          readerLoaded = true;
    +          expect(val).to.deep.equal({a: 1, b: 2, c: 3, d: 4});
    +
    +          // This update causes the following to happen:
    +          // 1. An in-view child is set to null (b)
    +          // 2. An in-view child has its value changed (c)
    +          // 3. An in-view child is changed and bumped out-of-view (d)
    +          // We expect to get null values for b and d, along with the new children and updated value for c
    +          writer.child('foo').update({b: null, c: 'a', cc: 'new', cd: 'new2', d: 'gone'});
    +        } else {
    +          done();
    +          expect(val).to.deep.equal({a: 1, c: 'a', cc: 'new', cd: 'new2'});
    +        }
    +      });
    +    });
    +  });
    +
    +  it('update() at query root raises correct value event', function(done) {
    +    var nodePair = getRandomNode(2);
    +    var writer = nodePair[0];
    +    var reader = nodePair[1];
    +
    +    var readerLoaded = false, numEventsReceived = 0;
    +    writer.child('foo').set({ 'bar': 'a', 'baz': 'b', 'bam': 'c' }, function(error, dummy) {
    +      reader.child('foo').limitToLast(10).on('value', function(snapshot) {
    +        var val = snapshot.val();
    +        if (!readerLoaded) {
    +          readerLoaded = true;
    +          expect(val.bar).to.equal('a');
    +          expect(val.baz).to.equal('b');
    +          expect(val.bam).to.equal('c');
    +          writer.child('foo').update({ 'bar': 'd', 'bam': null, 'bat': 'e' });
    +        } else {
    +          expect(val.bar).to.equal('d');
    +          expect(val.baz).to.equal('b');
    +          expect(val.bat).to.equal('e');
    +          expect(val.bam).to.equal(undefined);
    +          done();
    +        }
    +      });
    +    });
    +  });
    +
    +  it('set() at query root raises correct value event', function(done) {
    +    var nodePair = getRandomNode(2);
    +    var writer = nodePair[0];
    +    var reader = nodePair[1];
    +
    +    var readerLoaded = false, numEventsReceived = 0;
    +    writer.child('foo').set({ 'bar': 'a', 'baz': 'b', 'bam': 'c' }, function(error, dummy) {
    +      reader.child('foo').limitToLast(10).on('value', function(snapshot) {
    +        var val = snapshot.val();
    +        if (!readerLoaded) {
    +          readerLoaded = true;
    +          expect(val.bar).to.equal('a');
    +          expect(val.baz).to.equal('b');
    +          expect(val.bam).to.equal('c');
    +          writer.child('foo').set({ 'bar': 'd', 'baz': 'b', 'bat': 'e' });
    +        } else {
    +          expect(val.bar).to.equal('d');
    +          expect(val.baz).to.equal('b');
    +          expect(val.bat).to.equal('e');
    +          expect(val.bam).to.equal(undefined);
    +          done();
    +        }
    +      });
    +    });
    +  });
    +
    +
    +  it('listen for child_added events with limit and different types fires properly', function(done) {
    +    var nodePair = getRandomNode(2);
    +    var writer = nodePair[0];
    +    var reader = nodePair[1];
    +
    +    var numEventsReceived = 0, gotA = false, gotB = false, gotC = false;
    +    writer.child('a').set(1, function(error, dummy) {
    +      writer.child('b').set('b', function(error, dummy) {
    +        writer.child('c').set({ 'deep': 'path', 'of': { 'stuff': true }}, function(error, dummy) {
    +          reader.limitToLast(3).on('child_added', function(snap) {
    +            var val = snap.val();
    +            switch (snap.key) {
    +              case 'a':
    +                gotA = true;
    +                expect(val).to.equal(1);
    +                break;
    +              case 'b':
    +                gotB = true;
    +                expect(val).to.equal('b');
    +                break;
    +              case 'c':
    +                gotC = true;
    +                expect(val.deep).to.equal('path');
    +                expect(val.of.stuff).to.be.true;
    +                break;
    +              default:
    +                expect(false).to.be.true;
    +            }
    +            numEventsReceived += 1;
    +            expect(numEventsReceived).to.be.lessThan(4);
    +            if (gotA && gotB && gotC) done();
    +          });
    +        });
    +      });
    +    });
    +  });
    +
    +  it('listen for child_changed events with limit and different types fires properly', function(done) {
    +    var nodePair = getRandomNode(2);
    +    var writer = nodePair[0];
    +    var reader = nodePair[1];
    +
    +    var numEventsReceived = 0, gotA = false, gotB = false, gotC = false, readerLoaded = false;
    +    writer.set({ a: 'something', b: "we'll", c: 'overwrite '}, function(error, dummy) {
    +      reader.limitToLast(3).on('value', function(snapshot) {
    +        if (!readerLoaded) {
    +          readerLoaded = true;
    +          // Set up listener for upcoming change events
    +          reader.limitToLast(3).on('child_changed', function(snap) {
    +            var val = snap.val();
    +            switch (snap.key) {
    +              case 'a':
    +                gotA = true;
    +                expect(val).to.equal(1);
    +                break;
    +              case 'b':
    +                gotB = true;
    +                expect(val).to.equal('b');
    +                break;
    +              case 'c':
    +                gotC = true;
    +                expect(val.deep).to.equal('path');
    +                expect(val.of.stuff).to.be.true;
    +                break;
    +              default:
    +                expect(false).to.be.true;
    +            }
    +            numEventsReceived += 1;
    +            expect(numEventsReceived).to.be.lessThan(4);
    +            if (gotA && gotB && gotC) done();
    +          });
    +
    +          // Begin changing every key
    +          writer.child('a').set(1);
    +          writer.child('b').set('b');
    +          writer.child('c').set({ 'deep': 'path', 'of': { 'stuff': true }});
    +        }
    +      });
    +    });
    +  });
    +
    +  it('listen for child_remove events with limit and different types fires properly', function(done) {
    +    var nodePair = getRandomNode(2);
    +    var writer = nodePair[0];
    +    var reader = nodePair[1];
    +
    +    var numEventsReceived = 0, gotA = false, gotB = false, gotC = false, readerLoaded = false;
    +    writer.set({ a: 1, b: 'b', c: { 'deep': 'path', 'of': { 'stuff': true }} }, function(error, dummy) {
    +      reader.limitToLast(3).on('value', function(snapshot) {
    +        if (!readerLoaded) {
    +          readerLoaded = true;
    +
    +          // Set up listener for upcoming change events
    +          reader.limitToLast(3).on('child_removed', function(snap) {
    +            var val = snap.val();
    +            switch (snap.key) {
    +              case 'a':
    +                gotA = true;
    +                expect(val).to.equal(1);
    +                break;
    +              case 'b':
    +                gotB = true;
    +                expect(val).to.equal('b');
    +                break;
    +              case 'c':
    +                gotC = true;
    +                expect(val.deep).to.equal('path');
    +                expect(val.of.stuff).to.be.true;
    +                break;
    +              default:
    +                expect(false).to.be.true;
    +            }
    +            numEventsReceived += 1;
    +            expect(numEventsReceived).to.be.lessThan(4);
    +            if (gotA && gotB && gotC) done();
    +          });
    +
    +          // Begin removing every key
    +          writer.child('a').remove();
    +          writer.child('b').remove();
    +          writer.child('c').remove();
    +        }
    +      });
    +    });
    +  });
    +
    +  it('listen for child_remove events when parent removed', function(done) {
    +    var nodePair = getRandomNode(2);
    +    var writer = nodePair[0];
    +    var reader = nodePair[1];
    +
    +    var numEventsReceived = 0, gotA = false, gotB = false, gotC = false, readerLoaded = false;
    +    writer.set({ a: 1, b: 'b', c: { 'deep': 'path', 'of': { 'stuff': true }} }, function(error, dummy) {
    +
    +      reader.limitToLast(3).on('value', function(snapshot) {
    +        if (!readerLoaded) {
    +          readerLoaded = true;
    +
    +          // Set up listener for upcoming change events
    +          reader.limitToLast(3).on('child_removed', function(snap) {
    +            var val = snap.val();
    +            switch (snap.key) {
    +              case 'a':
    +                gotA = true;
    +                expect(val).to.equal(1);
    +                break;
    +              case 'b':
    +                gotB = true;
    +                expect(val).to.equal('b');
    +                break;
    +              case 'c':
    +                gotC = true;
    +                expect(val.deep).to.equal('path');
    +                expect(val.of.stuff).to.be.true;
    +                break;
    +              default:
    +                expect(false).to.be.true;
    +            }
    +            numEventsReceived += 1;
    +            expect(numEventsReceived).to.be.lessThan(4);
    +            if (gotA && gotB && gotC) done();
    +          });
    +
    +          // Remove the query parent
    +          writer.remove();
    +        }
    +      });
    +    });
    +  });
    +
    +  it('listen for child_remove events when parent set to scalar', function(done) {
    +    var nodePair = getRandomNode(2);
    +    var writer = nodePair[0];
    +    var reader = nodePair[1];
    +
    +    var numEventsReceived = 0, gotA = false, gotB = false, gotC = false, readerLoaded = false;
    +    writer.set({ a: 1, b: 'b', c: { 'deep': 'path', 'of': { 'stuff': true }} }, function(error, dummy) {
    +
    +      reader.limitToLast(3).on('value', function(snapshot) {
    +        if (!readerLoaded) {
    +          readerLoaded = true;
    +
    +          // Set up listener for upcoming change events
    +          reader.limitToLast(3).on('child_removed', function(snap) {
    +            var val = snap.val();
    +            switch (snap.key) {
    +              case 'a':
    +                gotA = true;
    +                expect(val).to.equal(1);
    +                break;
    +              case 'b':
    +                gotB = true;
    +                expect(val).to.equal('b');
    +                break;
    +              case 'c':
    +                gotC = true;
    +                expect(val.deep).to.equal('path');
    +                expect(val.of.stuff).to.be.true;
    +                break;
    +              default:
    +                expect(false).to.be.true;
    +            }
    +            numEventsReceived += 1;
    +            expect(numEventsReceived).to.be.lessThan(4);
    +            if (gotA && gotB && gotC) done();
    +          });
    +
    +          // Set the parent to a scalar
    +          writer.set('scalar');
    +        }
    +      });
    +    });
    +  });
    +
    +
    +  it('Queries behave wrong after .once().', async function() {
    +    var refPair = getRandomNode(2),
    +        writeRef = refPair[0],
    +        readRef = refPair[1],
    +        done, startAtCount, defaultCount;
    +
    +    await writeRef.set({a: 1, b: 2, c: 3, d: 4 });
    +
    +    await readRef.once('value');
    +
    +    const ea = EventAccumulatorFactory.waitsForCount(5);
    +    startAtCount = 0;
    +    readRef.startAt(null, 'd').on('child_added', function() {
    +      startAtCount++;
    +      ea.addEvent();
    +    });
    +    expect(startAtCount).to.equal(0);
    +
    +    defaultCount = 0;
    +    readRef.on('child_added', function() {
    +      defaultCount++;
    +      ea.addEvent();
    +    });
    +    expect(defaultCount).to.equal(0);
    +
    +    readRef.on('child_removed', function() {
    +      expect(false).to.be.true;
    +    });
    +
    +    return ea.promise;
    +  });
    +
    +  it('Case 2003: Correctly get events for startAt/endAt queries when priority changes.', function() {
    +    var ref = (getRandomNode() as Reference);
    +    var addedFirst = [], removedFirst = [], addedSecond = [], removedSecond = [];
    +    ref.startAt(0).endAt(10).on('child_added', function(snap) { addedFirst.push(snap.key); });
    +    ref.startAt(0).endAt(10).on('child_removed', function(snap) { removedFirst.push(snap.key); });
    +    ref.startAt(10).endAt(20).on('child_added', function(snap) { addedSecond.push(snap.key); });
    +    ref.startAt(10).endAt(20).on('child_removed', function(snap) { removedSecond.push(snap.key); });
    +
    +    ref.child('a').setWithPriority('a', 5);
    +    expect(addedFirst).to.deep.equal(['a']);
    +    ref.child('a').setWithPriority('a', 15);
    +    expect(removedFirst).to.deep.equal(['a']);
    +    expect(addedSecond).to.deep.equal(['a']);
    +
    +    ref.child('a').setWithPriority('a', 10);
    +    expect(addedFirst).to.deep.equal(['a', 'a']);
    +
    +    ref.child('a').setWithPriority('a', 5);
    +    expect(removedSecond).to.deep.equal(['a']);
    +  });
    +
    +  it('Behaves with diverging queries', async function() {
    +    var refs = getRandomNode(2);
    +    var writer = refs[0];
    +    var reader = refs[1];
    +
    +    await writer.set({
    +      a: {b: 1, c: 2},
    +      e: 3
    +    });
    +
    +    var childCount = 0;
    +
    +    reader.child('a/b').on('value', function(snap) {
    +      var val = snap.val();
    +      childCount++;
    +      if (childCount == 1) {
    +        expect(val).to.equal(1);
    +      } else {
    +        // fail this, nothing should have changed
    +        expect(true).to.be.false;
    +      }
    +    });
    +
    +    const ea = EventAccumulatorFactory.waitsForCount(1);
    +    var count = 0;
    +    reader.limitToLast(2).on('value', function(snap) {
    +      ea.addEvent();
    +      var val = snap.val();
    +      count++;
    +      if (count == 1) {
    +        expect(val).to.deep.equal({a: {b: 1, c: 2}, e: 3});
    +      } else if (count == 2) {
    +        expect(val).to.deep.equal({d: 4, e: 3});
    +      }
    +    });
    +
    +    await ea.promise;
    +
    +    ea.reset();
    +    writer.child('d').set(4);
    +
    +    return ea.promise;
    +  });
    +
    +  it('Priority-only updates are processed correctly by server.', async function() {
    +    var refPair = (getRandomNode(2) as Reference[]), readRef = refPair[0], writeRef = refPair[1];
    +
    +    const ea = EventAccumulatorFactory.waitsForCount(1);
    +    var readVal;
    +    readRef.limitToLast(2).on('value', function(s) {
    +      readVal = s.val();
    +      if (readVal) {
    +        ea.addEvent();
    +      }
    +    });
    +    writeRef.set({ 
    +      a: { '.priority': 10, '.value': 1},
    +      b: { '.priority': 20, '.value': 2},
    +      c: { '.priority': 30, '.value': 3}
    +    });
    +
    +    await ea.promise;
    +    expect(readVal).to.deep.equal({ b: 2, c: 3 });
    +
    +    ea.reset();
    +    writeRef.child('a').setPriority(25);
    +
    +    await ea.promise;
    +    expect(readVal).to.deep.equal({ a: 1, c: 3 });
    +  });
    +
    +  it('Server: Test re-listen', function(done) {
    +    var refPair = (getRandomNode(2) as Reference[]), ref = refPair[0], ref2 = refPair[1];
    +    ref.set({
    +      a: 'a',
    +      b: 'b',
    +      c: 'c',
    +      d: 'd',
    +      e: 'e',
    +      f: 'f',
    +      g: 'g'
    +    });
    +
    +    var before;
    +    ref.startAt(null, 'a').endAt(null, 'b').on('value', function(b) {
    +      before = b.val();
    +    });
    +
    +    ref.child('aa').set('aa', function() {
    +      ref2.startAt(null, 'a').endAt(null, 'b').on('value', function(b) {
    +        expect(b.val()).to.deep.equal(before);
    +        done();
    +      });
    +    });
    +  });
    +
    +  it('Server: Test re-listen 2', function(done) {
    +    var refPair = getRandomNode(2), ref = refPair[0], ref2 = refPair[1];
    +    ref.set({
    +      a: 'a',
    +      b: 'b',
    +      c: 'c',
    +      d: 'd',
    +      e: 'e',
    +      f: 'f',
    +      g: 'g'
    +    });
    +
    +    var before;
    +    ref.startAt(null, 'b').limitToFirst(3).on('value', function(b) {
    +      before = b.val();
    +    });
    +
    +    ref.child('aa').update({ 'a': 5, 'aa': 4, 'b': 7, 'c': 4, 'd': 4, 'dd': 3 }, function() {
    +      ref2.startAt(null, 'b').limitToFirst(3).on('value', function(b) {
    +        expect(b.val()).to.deep.equal(before);
    +        done();
    +      });
    +    });
    +  });
    +
    +  it('Server: Test re-listen 3', function(done) {
    +    var refPair = getRandomNode(2), ref = refPair[0], ref2 = refPair[1];
    +    ref.set({
    +      a: 'a',
    +      b: 'b',
    +      c: 'c',
    +      d: 'd',
    +      e: 'e',
    +      f: 'f',
    +      g: 'g'
    +    });
    +
    +    var before;
    +    ref.limitToLast(3).on('value', function(b) {
    +      before = b.val();
    +    });
    +
    +    ref.child('h').set('h', function() {
    +      ref2.limitToLast(3).on('value', function(b) {
    +        expect(b.val()).to.deep.equal(before);
    +        done();
    +      });
    +    });
    +  });
    +
    +  it('Server limit below limit works properly.', async function() {
    +    var refPair = <Reference[]>getRandomNode(2),
    +        readRef = refPair[0],
    +        writeRef = refPair[1],
    +        childData;
    +
    +    await writeRef.set({
    +      a: {
    +        aa: {'.priority': 1, '.value': 1 },
    +        ab: {'.priority': 1, '.value': 1 }
    +      } 
    +    });
    +
    +    readRef.limitToLast(1).on('value', function(s) {
    +      expect(s.val()).to.deep.equal({a: { aa: 1, ab: 1}});
    +    });
    +
    +    const ea = EventAccumulatorFactory.waitsForCount(1);
    +    readRef.child('a').startAt(1).endAt(1).on('value', function(s) {
    +      childData = s.val();
    +      if (childData) {
    +        ea.addEvent();
    +      }
    +    });
    +
    +    await ea.promise;
    +    expect(childData).to.deep.equal({ aa: 1, ab: 1 });
    +
    +    // This should remove an item from the child query, but *not* the parent query.
    +    ea.reset();
    +    writeRef.child('a/ab').setWithPriority(1, 2);
    +
    +    await ea.promise
    +
    +    expect(childData).to.deep.equal({ aa: 1 });    
    +  });
    +
    +  it('Server: Setting grandchild of item in limit works.', async function() {
    +    var refPair = getRandomNode(2), ref = refPair[0], ref2 = refPair[1];
    +
    +    ref.set({ a: {
    +      name: 'Mike'
    +    }});
    +
    +    const ea = EventAccumulatorFactory.waitsForCount(1);
    +    var snaps = [];
    +    ref2.limitToLast(1).on('value', function(s) {
    +      var val = s.val();
    +      if (val !== null) {
    +        snaps.push(val);
    +        ea.addEvent();
    +      }
    +    });
    +
    +    await ea.promise;
    +    expect(snaps).to.deep.equal( [{ a: { name: 'Mike' } }]);
    +
    +    ea.reset();
    +    ref.child('a/name').set('Fred');
    +
    +    await ea.promise;
    +    expect(snaps).to.deep.equal([{ a: { name: 'Mike' } }, { a: { name: 'Fred' } }]);
    +  });
    +
    +  it('Server: Updating grandchildren of item in limit works.', async function() {
    +    var refPair = getRandomNode(2), ref = refPair[0], ref2 = refPair[1];
    +
    +    ref.set({ a: {
    +      name: 'Mike'
    +    }});
    +
    +    const ea = EventAccumulatorFactory.waitsForCount(1);
    +    var snaps = [];
    +    ref2.limitToLast(1).on('value', function(s) {
    +      var val = s.val();
    +      if (val !== null) {
    +        snaps.push(val);
    +        ea.addEvent();
    +      }
    +    });
    +
    +    /**
    +     * If I put this artificial pause here, this test works however
    +     * something about the timing is broken
    +     */
    +    await ea.promise;
    +    expect(snaps).to.deep.equal([{ a: { name: 'Mike' } }]);
    +
    +    ea.reset();
    +    ref.child('a').update({ name: null, Name: 'Fred' });
    +    await ea.promise;
    +
    +    expect(snaps).to.deep.equal([{ a: { name: 'Mike' } }, { a: { Name: 'Fred' } }]);
    +  });
    +
    +  it('Server: New child at end of limit shows up.', async function() {
    +    var refPair = getRandomNode(2), ref = refPair[0], ref2 = refPair[1];
    +
    +    const ea = EventAccumulatorFactory.waitsForCount(1);
    +    var snap;
    +    ref2.limitToLast(1).on('value', function(s) {
    +      snap = s.val();
    +      ea.addEvent();
    +    });
    +
    +    await ea.promise;
    +    expect(snap).to.be.null;
    +    ea.reset();
    +
    +    ref.child('a').set('new child');
    +
    +    /**
    +     * If I put this artificial pause here, this test works however
    +     * something about the timing is broken
    +     */
    +    await ea.promise;
    +    expect(snap).to.deep.equal({ a: 'new child' });
    +  });
    +
    +  it('Server: Priority-only updates are processed correctly by server (1).', async function() {
    +    var refPair = getRandomNode(2), readRef = refPair[0], writeRef = refPair[1];
    +
    +    const ea = EventAccumulatorFactory.waitsForCount(1);
    +    var readVal;
    +    readRef.limitToLast(2).on('value', function(s) {
    +      readVal = s.val();
    +      if (readVal) {
    +        ea.addEvent();
    +      }
    +    });
    +    writeRef.set({ 
    +      a: { '.priority': 10, '.value': 1},
    +      b: { '.priority': 20, '.value': 2},
    +      c: { '.priority': 30, '.value': 3}
    +    });
    +
    +    await ea.promise
    +    expect(readVal).to.deep.equal({ b: 2, c: 3 });
    +    
    +    ea.reset();
    +    writeRef.child('a').setPriority(25);
    +
    +    await ea.promise;
    +    expect(readVal).to.deep.equal({ a: 1, c: 3 });
    +  });
    +
    +  // Same as above but with an endAt() so we hit CompoundQueryView instead of SimpleLimitView.
    +  it('Server: Priority-only updates are processed correctly by server (2).', async function() {
    +    var refPair = getRandomNode(2), readRef = refPair[0], writeRef = refPair[1];
    +
    +    const ea = EventAccumulatorFactory.waitsForCount(1);
    +    var readVal;
    +    readRef.endAt(50).limitToLast(2).on('value', function(s) {
    +      readVal = s.val();
    +      if (readVal) {
    +        ea.addEvent();
    +      }
    +    });
    +    
    +    writeRef.set({ 
    +      a: { '.priority': 10, '.value': 1},
    +      b: { '.priority': 20, '.value': 2},
    +      c: { '.priority': 30, '.value': 3}
    +    });
    +
    +    await ea.promise;
    +    expect(readVal).to.deep.equal({ b: 2, c: 3 });
    +
    +    ea.reset();
    +    writeRef.child('a').setPriority(25);
    +
    +    await ea.promise;
    +    expect(readVal).to.deep.equal({ a: 1, c: 3 });
    +  });
    +
    +  it('Latency compensation works with limit and pushed object.', function() {
    +    var ref = (getRandomNode() as Reference);
    +    var events = [];
    +    ref.limitToLast(3).on('child_added', function(s) { events.push(s.val()); });
    +
    +    // If you change this to ref.push('foo') it works.
    +    ref.push({a: 'foo'});
    +
    +    // Should have synchronously gotten an event.
    +    expect(events.length).to.equal(1);
    +  });
    +
    +  it("Cache doesn't remove items that have fallen out of view.", async function() {
    +    var refPair = getRandomNode(2), readRef = refPair[0], writeRef = refPair[1];
    +
    +    let ea = EventAccumulatorFactory.waitsForCount(1);
    +    var readVal;
    +    readRef.limitToLast(2).on('value', function(s) {
    +      readVal = s.val();
    +      ea.addEvent();
    +    });
    +
    +    await ea.promise;
    +    expect(readVal).to.be.null;
    +
    +    ea = EventAccumulatorFactory.waitsForCount(4)
    +    for (var i = 0; i < 4; i++) {
    +      writeRef.child('k' + i).set(i);
    +    }
    +
    +    await ea.promise;
    +
    +    await pause(500);
    +    expect(readVal).to.deep.equal({'k2': 2, 'k3': 3});
    +    
    +    ea = EventAccumulatorFactory.waitsForCount(1)
    +    writeRef.remove();
    +
    +    await ea.promise;
    +    expect(readVal).to.be.null;
    +  });
    +
    +  it('handles an update that moves another child that has a deeper listener out of view', async function() {
    +    var refs = getRandomNode(2);
    +    var reader = refs[0];
    +    var writer = refs[1];
    +
    +    await writer.set({ 
    +      a: { '.priority': 10, '.value': 1},
    +      b: { '.priority': 20, d: 4 },
    +      c: { '.priority': 30, '.value': 3}
    +    });
    +    
    +    reader.child('b/d').on('value', function(snap) {
    +      expect(snap.val()).to.equal(4);
    +    });
    +
    +    const ea = EventAccumulatorFactory.waitsForCount(1);
    +    var val;
    +    reader.limitToLast(2).on('value', function(snap) {
    +      val = snap.val();
    +      if (val) {
    +        ea.addEvent();
    +      }
    +    });
    +
    +    await ea.promise;
    +    expect(val).to.deep.equal({b: {d: 4}, c: 3});
    +
    +    ea.reset();
    +    writer.child('a').setWithPriority(1, 40);
    +
    +    await ea.promise;
    +    expect(val).to.deep.equal({c: 3, a: 1});
    +  });
    +
    +  it('Integer keys behave numerically 1.', function(done) {
    +    var ref = (getRandomNode() as Reference);
    +    ref.set({1: true, 50: true, 550: true, 6: true, 600: true, 70: true, 8: true, 80: true }, function() {
    +      ref.startAt(null, '80').once('value', function(s) {
    +        expect(s.val()).to.deep.equal({80: true, 550: true, 600: true });
    +        done();
    +      });
    +    });
    +  });
    +
    +  it('Integer keys behave numerically 2.', function(done) {
    +    var ref = (getRandomNode() as Reference);
    +    ref.set({1: true, 50: true, 550: true, 6: true, 600: true, 70: true, 8: true, 80: true }, function() {
    +      ref.endAt(null, '50').once('value', function(s) {
    +        expect(s.val()).to.deep.equal({1: true, 6: true, 8: true, 50: true });
    +        done();
    +      });
    +    });
    +  });
    +
    +  it('Integer keys behave numerically 3.', function(done) {
    +    var ref = (getRandomNode() as Reference);
    +    ref.set({1: true, 50: true, 550: true, 6: true, 600: true, 70: true, 8: true, 80: true}, function() {
    +      ref.startAt(null, '50').endAt(null, '80').once('value', function(s) {
    +        expect(s.val()).to.deep.equal({50: true, 70: true, 80: true });
    +        done();
    +      });
    +    });
    +  });
    +
    +  it('.limitToLast() on node with priority.', function(done) {
    +    var ref = (getRandomNode() as Reference);
    +    ref.set({'a': 'blah', '.priority': 'priority'}, function() {
    +      ref.limitToLast(2).once('value', function(s) {
    +        expect(s.exportVal()).to.deep.equal({a: 'blah' });
    +        done();
    +      });
    +    });
    +  });
    +
    +  it('.equalTo works', async function() {
    +    var ref = (getRandomNode() as Reference);
    +    var done = false;
    +
    +    await ref.set({
    +      a: 1,
    +      b: {'.priority': 2, '.value': 2},
    +      c: {'.priority': '3', '.value': 3}
    +    });
    +
    +    const snap1 = await ref.equalTo(2).once('value');
    +    var val1 = snap1.exportVal();
    +    expect(val1).to.deep.equal({b: {'.priority': 2, '.value': 2}});
    +
    +    const snap2 = await ref.equalTo('3', 'c').once('value');
    +    
    +    var val2 = snap2.exportVal();
    +    expect(val2).to.deep.equal({c: {'.priority': '3', '.value': 3}});
    +
    +    const snap3 = await ref.equalTo(null, 'c').once('value');
    +    var val3 = snap3.exportVal();
    +    expect(val3).to.be.null;
    +  });
    +
    +  it('Handles fallback for orderBy', async function() {
    +    var ref = (getRandomNode() as Reference);
    +
    +    const children = [];
    +    
    +    ref.orderByChild('foo').on('child_added', function(snap) {
    +      children.push(snap.key);
    +    });
    +
    +    // Set initial data
    +    await ref.set({
    +      a: {foo: 3},
    +      b: {foo: 1},
    +      c: {foo: 2}
    +    });
    +
    +    expect(children).to.deep.equal(['b', 'c', 'a']);
    +  });
    +
    +  it("Get notified of deletes that happen while offline.", async function() {
    +    var refPair = getRandomNode(2);
    +    var queryRef = refPair[0];
    +    var writerRef = refPair[1];
    +    var readSnapshot = null;
    +
    +    // Write 3 children and then start our limit query.
    +    await writerRef.set({a: 1, b: 2, c: 3});
    +
    +    const ea = EventAccumulatorFactory.waitsForCount(1);
    +    queryRef.limitToLast(3).on('value', function(s) { 
    +      readSnapshot = s;
    +      if (readSnapshot) {
    +        ea.addEvent();
    +      }
    +    });
    +
    +    // Wait for us to read the 3 children.
    +    await ea.promise;
    +
    +    expect(readSnapshot.val()).to.deep.equal({a: 1, b: 2, c: 3 });
    +
    +    queryRef.database.goOffline();
    +
    +    // Delete an item in the query and then bring our connection back up.
    +    ea.reset();
    +    await writerRef.child('b').remove();
    +    queryRef.database.goOnline();
    +
    +    await ea.promise;
    +    expect(readSnapshot.child('b').val()).to.be.null;
    +  });
    +
    +  it('Snapshot children respect default ordering', function(done) {
    +    var refPair = getRandomNode(2);
    +    var queryRef = refPair[0], writerRef = refPair[1];
    +
    +    var list = {
    +      'a': {
    +        thisvaluefirst: { '.value': true, '.priority': 1 },
    +        name: { '.value': 'Michael', '.priority': 2 },
    +        thisvaluelast: { '.value': true, '.priority': 3 }
    +      },
    +      'b': {
    +        thisvaluefirst: { '.value': true, '.priority': null },
    +        name: { '.value': 'Rob', '.priority': 2 },
    +        thisvaluelast: { '.value': true, '.priority': 3 }
    +      },
    +      'c': {
    +        thisvaluefirst: { '.value': true, '.priority': 1 },
    +        name: { '.value': 'Jonny', '.priority': 2 },
    +        thisvaluelast: { '.value': true, '.priority': 'somestring' }
    +      }
    +    };
    +
    +    writerRef.set(list, function() {
    +      queryRef.orderByChild('name').once('value', function(snap) {
    +        var expectedKeys = ['thisvaluefirst', 'name', 'thisvaluelast'];
    +        var expectedNames = ['Jonny', 'Michael', 'Rob'];
    +
    +
    +        // Validate that snap.child() resets order to default for child snaps
    +        var orderedKeys = [];
    +        snap.child('b').forEach(function(childSnap) {
    +          orderedKeys.push(childSnap.key);
    +        });
    +        expect(orderedKeys).to.deep.equal(expectedKeys);
    +
    +        // Validate that snap.forEach() resets ordering to default for child snaps
    +        var orderedNames = [];
    +        snap.forEach(function(childSnap) {
    +          orderedNames.push(childSnap.child('name').val());
    +          var orderedKeys = [];
    +          childSnap.forEach(function(grandchildSnap) {
    +            orderedKeys.push(grandchildSnap.key);
    +          });
    +          expect(orderedKeys).to.deep.equal(['thisvaluefirst', 'name', 'thisvaluelast']);
    +        });
    +        expect(orderedNames).to.deep.equal(expectedNames);
    +        done();
    +      });
    +    });
    +  });
    +
    +  it('Adding listens for the same paths does not check fail', function(done) {
    +    // This bug manifests itself if there's a hierarchy of query listener, default listener and one-time listener
    +    // underneath. During one-time listener registration, sync-tree traversal stopped as soon as it found a complete
    +    // server cache (this is the case for not indexed query view). The problem is that the same traversal was
    +    // looking for a ancestor default view, and the early exit prevented from finding the default listener above the
    +    // one-time listener. Event removal code path wasn't removing the listener because it stopped as soon as it
    +    // found the default view. This left the zombie one-time listener and check failed on the second attempt to
    +    // create a listener for the same path (asana#61028598952586).
    +    var ref = getRandomNode(1)[0];
    +
    +    ref.child('child').set({name: "John"}, function() {
    +      ref.orderByChild('name').equalTo('John').on('value', function(snap) {
    +        ref.child('child').on('value', function(snap) {
    +          ref.child('child').child('favoriteToy').once('value', function (snap) {
    +            ref.child('child').child('favoriteToy').once('value', function (snap) {
    +              done();
    +            });
    +          });
    +        });
    +      });
    +    });
    +  });
    +
    +  it('Can JSON serialize refs', function() {
    +    var ref = (getRandomNode() as Reference);
    +    expect(JSON.stringify(ref)).to.equal('"' + ref.toString() + '"');
    +  });
    +});
    diff --git a/tests/database/repoinfo.test.ts b/tests/database/repoinfo.test.ts
    new file mode 100644
    index 00000000000..daba6f371fe
    --- /dev/null
    +++ b/tests/database/repoinfo.test.ts
    @@ -0,0 +1,19 @@
    +import { testRepoInfo } from "./helpers/util";
    +import { CONSTANTS } from "../../src/database/realtime/Constants";
    +import { expect } from "chai";
    +
    +describe('RepoInfo', function() {
    +  it('should return the correct URL', function() {
    +    var repoInfo = testRepoInfo('https://test-ns.firebaseio.com');
    +
    +    var urlParams = {};
    +    urlParams[CONSTANTS.VERSION_PARAM] = CONSTANTS.PROTOCOL_VERSION;
    +    urlParams[CONSTANTS.LAST_SESSION_PARAM] = 'test';
    +
    +    var websocketUrl = repoInfo.connectionURL(CONSTANTS.WEBSOCKET, urlParams);
    +    expect(websocketUrl).to.equal('wss://test-ns.firebaseio.com/.ws?v=5&ls=test');
    +
    +    var longPollingUrl = repoInfo.connectionURL(CONSTANTS.LONG_POLLING, urlParams);
    +    expect(longPollingUrl).to.equal('https://test-ns.firebaseio.com/.lp?v=5&ls=test');
    +  });
    +});
    diff --git a/tests/database/sortedmap.test.ts b/tests/database/sortedmap.test.ts
    new file mode 100644
    index 00000000000..a4a8fdf9201
    --- /dev/null
    +++ b/tests/database/sortedmap.test.ts
    @@ -0,0 +1,392 @@
    +import { expect } from "chai";
    +import { 
    +  SortedMap,
    +  LLRBNode
    +} from "../../src/database/core/util/SortedMap";
    +import { shuffle } from "./helpers/util";
    +
    +
    +// Many of these were adapted from the mugs source code.
    +// http://mads379.github.com/mugs/
    +describe("SortedMap Tests", function() {
    +  var defaultCmp = function(a, b) {
    +    if (a === b) {
    +      return 0;
    +    } else if (a < b) {
    +      return -1;
    +    } else {
    +      return 1;
    +    }
    +  };
    +
    +  it("Create node", function() {
    +    var map = new SortedMap(defaultCmp).insert("key", "value");
    +    expect(map.root_.left.isEmpty()).to.equal(true);
    +    expect(map.root_.right.isEmpty()).to.equal(true);
    +  });
    +
    +  it("You can search a map for a specific key", function() {
    +    var map = new SortedMap(defaultCmp).insert(1,1).insert(2,2);
    +    expect(map.get(1)).to.equal(1);
    +    expect(map.get(2)).to.equal(2);
    +    expect(map.get(3)).to.equal(null);
    +  });
    +
    +  it("You can insert a new key/value pair into the tree", function() {
    +    var map = new SortedMap(defaultCmp).insert(1,1).insert(2,2);
    +    expect(map.root_.key).to.equal(2);
    +    expect(map.root_.left.key).to.equal(1);
    +  });
    +
    +  it("You can remove a key/value pair from the map",function() {
    +    var map = new SortedMap(defaultCmp).insert(1,1).insert(2,2);
    +    var newMap = map.remove(1);
    +    expect(newMap.get(2)).to.equal(2);
    +    expect(newMap.get(1)).to.equal(null);
    +  });
    +
    +  it("More removals",function(){
    +    var map = new SortedMap(defaultCmp)
    +        .insert(1,1)
    +        .insert(50,50)
    +        .insert(3,3)
    +        .insert(4,4)
    +        .insert(7,7)
    +        .insert(9,9)
    +        .insert(20,20)
    +        .insert(18,18)
    +        .insert(2,2)
    +        .insert(71,71)
    +        .insert(42,42)
    +        .insert(88,88);
    +
    +    var m1 = map.remove(7);
    +    var m2 = m1.remove(3);
    +    var m3 = m2.remove(1);
    +    expect(m3.count()).to.equal(9);
    +    expect(m3.get(1)).to.equal(null);
    +    expect(m3.get(3)).to.equal(null);
    +    expect(m3.get(7)).to.equal(null);
    +    expect(m3.get(20)).to.equal(20);
    +  });
    +
    +  it("Removal bug", function() {
    +    var map = new SortedMap(defaultCmp)
    +        .insert(1, 1)
    +        .insert(2, 2)
    +        .insert(3, 3);
    +
    +    var m1 = map.remove(2);
    +    expect(m1.get(1)).to.equal(1);
    +    expect(m1.get(3)).to.equal(3);
    +  });
    +
    +  it("Test increasing", function(){
    +    var total = 100;
    +    var item;
    +    var map = new SortedMap(defaultCmp).insert(1,1);
    +    for (item = 2; item < total ; item++) {
    +      map = map.insert(item,item);
    +    }
    +    expect(map.root_.checkMaxDepth_()).to.equal(true);
    +    for (item = 2; item < total ; item++) {
    +      map = map.remove(item);
    +    }
    +    expect(map.root_.checkMaxDepth_()).to.equal(true);
    +  });
    +
    +  it("The structure should be valid after insertion (1)",function(){
    +    var map = new SortedMap(defaultCmp).insert(1,1).insert(2,2).insert(3,3);
    +
    +    expect(map.root_.key).to.equal(2);
    +    expect(map.root_.left.key).to.equal(1);
    +    expect(map.root_.right.key).to.equal(3);
    +  });
    +
    +  it("The structure should be valid after insertion (2)",function(){
    +    var map = new SortedMap(defaultCmp)
    +        .insert(1,1)
    +        .insert(2,2)
    +        .insert(3,3)
    +        .insert(4,4)
    +        .insert(5,5)
    +        .insert(6,6)
    +        .insert(7,7)
    +        .insert(8,8)
    +        .insert(9,9)
    +        .insert(10,10)
    +        .insert(11,11)
    +        .insert(12,12);
    +
    +    expect(map.count()).to.equal(12);
    +    expect(map.root_.checkMaxDepth_()).to.equal(true);
    +  });
    +
    +  it("Rotate left leaves the tree in a valid state",function(){
    +    var node = new LLRBNode(4,4,false,
    +        new LLRBNode(2,2,false,null, null),
    +        new LLRBNode(7,7,true,
    +            new LLRBNode(5,5,false,null,null),
    +            new LLRBNode(8,8,false,null,null)));
    +
    +    var node2 = node.rotateLeft_();
    +    expect(node2.count()).to.equal(5);
    +    expect(node2.checkMaxDepth_()).to.equal(true);
    +  });
    +
    +  it("Rotate right leaves the tree in a valid state", function(){
    +    var node = new LLRBNode(7,7,false,
    +        new LLRBNode(4,4,true,
    +            new LLRBNode(2,2,false, null, null),
    +            new LLRBNode(5,5,false, null, null)),
    +        new LLRBNode(8,8,false, null, null));
    +
    +    var node2 = node.rotateRight_();
    +    expect(node2.count()).to.equal(5);
    +    expect(node2.key).to.equal(4);
    +    expect(node2.left.key).to.equal(2);
    +    expect(node2.right.key).to.equal(7);
    +    expect(node2.right.left.key).to.equal(5);
    +    expect(node2.right.right.key).to.equal(8);
    +  });
    +
    +  it("The structure should be valid after insertion (3)",function(){
    +    var map = new SortedMap(defaultCmp)
    +        .insert(1,1)
    +        .insert(50,50)
    +        .insert(3,3)
    +        .insert(4,4)
    +        .insert(7,7)
    +        .insert(9,9);
    +
    +    expect(map.count()).to.equal(6);
    +    expect(map.root_.checkMaxDepth_()).to.equal(true);
    +
    +    var m2 = map
    +        .insert(20,20)
    +        .insert(18,18)
    +        .insert(2,2);
    +
    +    expect(m2.count()).to.equal(9);
    +    expect(m2.root_.checkMaxDepth_()).to.equal(true);
    +
    +    var m3 = m2
    +        .insert(71,71)
    +        .insert(42,42)
    +        .insert(88,88);
    +
    +    expect(m3.count()).to.equal(12);
    +    expect(m3.root_.checkMaxDepth_()).to.equal(true);
    +  });
    +
    +  it("you can overwrite a value",function(){
    +    var map = new SortedMap(defaultCmp).insert(10,10).insert(10,8);
    +    expect(map.get(10)).to.equal(8);
    +  });
    +
    +  it("removing the last element returns an empty map",function() {
    +    var map = new SortedMap(defaultCmp).insert(10,10).remove(10);
    +    expect(map.isEmpty()).to.equal(true);
    +  });
    +
    +  it("empty .get()",function() {
    +    var empty = new SortedMap(defaultCmp);
    +    expect(empty.get("something")).to.equal(null);
    +  });
    +
    +  it("empty .count()",function() {
    +    var empty = new SortedMap(defaultCmp);
    +    expect(empty.count()).to.equal(0);
    +  });
    +
    +  it("empty .remove()",function() {
    +    var empty = new SortedMap(defaultCmp);
    +    expect(empty.remove("something").count()).to.equal(0);
    +  });
    +
    +  it(".reverseTraversal() works.", function() {
    +    var map = new SortedMap(defaultCmp).insert(1, 1).insert(5, 5).insert(3, 3).insert(2, 2).insert(4, 4);
    +    var next = 5;
    +    map.reverseTraversal(function(key, value) {
    +      expect(key).to.equal(next);
    +      next--;
    +    });
    +    expect(next).to.equal(0);
    +  });
    +
    +  it("insertion and removal of 100 items in random order.", function() {
    +    var N = 100;
    +    var toInsert = [], toRemove = [];
    +    for(var i = 0; i < N; i++) {
    +      toInsert.push(i);
    +      toRemove.push(i);
    +    }
    +
    +    shuffle(toInsert);
    +    shuffle(toRemove);
    +
    +    var map = new SortedMap(defaultCmp);
    +
    +    for (i = 0 ; i < N ; i++ ) {
    +      map = map.insert(toInsert[i], toInsert[i]);
    +      expect(map.root_.checkMaxDepth_()).to.equal(true);
    +    }
    +    expect(map.count()).to.equal(N);
    +
    +    // Ensure order is correct.
    +    var next = 0;
    +    map.inorderTraversal(function(key, value) {
    +      expect(key).to.equal(next);
    +      expect(value).to.equal(next);
    +      next++;
    +    });
    +    expect(next).to.equal(N);
    +
    +    for (i = 0 ; i < N ; i++ ) {
    +      expect(map.root_.checkMaxDepth_()).to.equal(true);
    +      map = map.remove(toRemove[i]);
    +    }
    +    expect(map.count()).to.equal(0);
    +  });
    +
    +  // A little perf test for convenient benchmarking.
    +  xit("Perf", function() {
    +    for(var j = 0; j < 5; j++) {
    +      var map = new SortedMap(defaultCmp);
    +      var start = new Date().getTime();
    +      for(var i = 0; i < 50000; i++) {
    +        map = map.insert(i, i);
    +      }
    +
    +      for(var i = 0; i < 50000; i++) {
    +        map = map.remove(i);
    +      }
    +      var end = new Date().getTime();
    +      // console.log(end-start);
    +    }
    +  });
    +
    +  xit("Perf: Insertion and removal with various # of items.", function() {
    +    var verifyTraversal = function(map, max) {
    +      var next = 0;
    +      map.inorderTraversal(function(key, value) {
    +        expect(key).to.equal(next);
    +        expect(value).to.equal(next);
    +        next++;
    +      });
    +      expect(next).to.equal(max);
    +    };
    +
    +    for(var N = 10; N <= 100000; N *= 10) {
    +      var toInsert = [], toRemove = [];
    +      for(var i = 0; i < N; i++) {
    +        toInsert.push(i);
    +        toRemove.push(i);
    +      }
    +
    +      shuffle(toInsert);
    +      shuffle(toRemove);
    +
    +      var map = new SortedMap(defaultCmp);
    +
    +      var start = new Date().getTime();
    +      for (i = 0 ; i < N ; i++ ) {
    +        map = map.insert(toInsert[i], toInsert[i]);
    +      }
    +
    +      // Ensure order is correct.
    +      verifyTraversal(map, N);
    +
    +      for (i = 0 ; i < N ; i++ ) {
    +        map = map.remove(toRemove[i]);
    +      }
    +
    +      var elapsed = new Date().getTime() - start;
    +      // console.log(N + ": " +elapsed);
    +    }
    +  });
    +
    +  xit("Perf: Comparison with {}: Insertion and removal with various # of items.", function() {
    +    var verifyTraversal = function(tree, max) {
    +      var keys = [];
    +      for(var k in tree)
    +        keys.push(k);
    +
    +      keys.sort();
    +      expect(keys.length).to.equal(max);
    +      for(var i = 0; i < max; i++)
    +        expect(tree[i]).to.equal(i);
    +    };
    +
    +    for(var N = 10; N <= 100000; N *= 10) {
    +      var toInsert = [], toRemove = [];
    +      for(var i = 0; i < N; i++) {
    +        toInsert.push(i);
    +        toRemove.push(i);
    +      }
    +
    +      shuffle(toInsert);
    +      shuffle(toRemove);
    +
    +      var tree = { };
    +
    +      var start = new Date().getTime();
    +      for (i = 0 ; i < N ; i++ ) {
    +        tree[i] = i;
    +      }
    +
    +      // Ensure order is correct.
    +      //verifyTraversal(tree, N);
    +
    +      for (i = 0 ; i < N ; i++ ) {
    +        delete tree[i];
    +      }
    +
    +      var elapsed = (new Date().getTime()) - start;
    +      // console.log(N + ": " +elapsed);
    +    }
    +  });
    +
    +  it("SortedMapIterator empty test.", function() {
    +    var map = new SortedMap(defaultCmp);
    +    var iterator = map.getIterator();
    +    expect(iterator.getNext()).to.equal(null);
    +  });
    +
    +  it("SortedMapIterator test with 10 items.", function() {
    +    var items = [];
    +    for(var i = 0; i < 10; i++)
    +      items.push(i);
    +    shuffle(items);
    +
    +    var map = new SortedMap(defaultCmp);
    +    for(i = 0; i < 10; i++)
    +      map = map.insert(items[i], items[i]);
    +
    +    var iterator = map.getIterator();
    +    var n, expected = 0;
    +    while ((n = iterator.getNext()) !== null) {
    +      expect(n.key).to.equal(expected);
    +      expect(n.value).to.equal(expected);
    +      expected++;
    +    }
    +    expect(expected).to.equal(10);
    +  });
    +
    +  it("SortedMap.getPredecessorKey works.", function() {
    +    var map = new SortedMap(defaultCmp)
    +        .insert(1,1)
    +        .insert(50,50)
    +        .insert(3,3)
    +        .insert(4,4)
    +        .insert(7,7)
    +        .insert(9,9);
    +
    +    expect(map.getPredecessorKey(1)).to.equal(null);
    +    expect(map.getPredecessorKey(3)).to.equal(1);
    +    expect(map.getPredecessorKey(4)).to.equal(3);
    +    expect(map.getPredecessorKey(7)).to.equal(4);
    +    expect(map.getPredecessorKey(9)).to.equal(7);
    +    expect(map.getPredecessorKey(50)).to.equal(9);
    +  });
    +});
    diff --git a/tests/database/sparsesnapshottree.test.ts b/tests/database/sparsesnapshottree.test.ts
    new file mode 100644
    index 00000000000..4ee627050a0
    --- /dev/null
    +++ b/tests/database/sparsesnapshottree.test.ts
    @@ -0,0 +1,178 @@
    +import { expect } from "chai";
    +import { SparseSnapshotTree } from "../../src/database/core/SparseSnapshotTree";
    +import { Path } from "../../src/database/core/util/Path";
    +import { nodeFromJSON } from "../../src/database/core/snap/nodeFromJSON";
    +import { ChildrenNode } from "../../src/database/core/snap/ChildrenNode";
    +
    +describe("SparseSnapshotTree Tests", function () {
    +  it("Basic remember and find.", function () {
    +    var st = new SparseSnapshotTree();
    +    var path = new Path("a/b");
    +    var node = nodeFromJSON("sdfsd");
    +
    +    st.remember(path, node);
    +    expect(st.find(new Path("a/b")).isEmpty()).to.equal(false);
    +    expect(st.find(new Path("a"))).to.equal(null);
    +  });
    +
    +
    +  it("Find inside an existing snapshot", function () {
    +    var st = new SparseSnapshotTree();
    +    var path = new Path("t/tt");
    +    var node = nodeFromJSON({ a: "sdfsd", x: 5, "999i": true });
    +    node = node.updateImmediateChild("apples", nodeFromJSON({ "goats": 88 }));
    +    st.remember(path, node);
    +
    +    expect(st.find(new Path("t/tt")).isEmpty()).to.equal(false);
    +    expect(st.find(new Path("t/tt/a")).val()).to.equal("sdfsd");
    +    expect(st.find(new Path("t/tt/999i")).val()).to.equal(true);
    +    expect(st.find(new Path("t/tt/apples")).isEmpty()).to.equal(false);
    +    expect(st.find(new Path("t/tt/apples/goats")).val()).to.equal(88);
    +  });
    +
    +
    +  it("Write a snapshot inside a snapshot.", function () {
    +    var st = new SparseSnapshotTree();
    +    st.remember(new Path("t"), nodeFromJSON({ a: { b: "v" } }));
    +    st.remember(new Path("t/a/rr"), nodeFromJSON(19));
    +    expect(st.find(new Path("t/a/b")).val()).to.equal("v");
    +    expect(st.find(new Path("t/a/rr")).val()).to.equal(19);
    +  });
    +
    +
    +  it("Write a null value and confirm it is remembered.", function () {
    +    var st = new SparseSnapshotTree();
    +    st.remember(new Path("awq/fff"), nodeFromJSON(null));
    +    expect(st.find(new Path("awq/fff"))).to.equal(ChildrenNode.EMPTY_NODE);
    +    expect(st.find(new Path("awq/sdf"))).to.equal(null);
    +    expect(st.find(new Path("awq/fff/jjj"))).to.equal(ChildrenNode.EMPTY_NODE);
    +    expect(st.find(new Path("awq/sdf/sdf/q"))).to.equal(null);
    +  });
    +
    +
    +  it("Overwrite with null and confirm it is remembered.", function () {
    +    var st = new SparseSnapshotTree();
    +    st.remember(new Path("t"), nodeFromJSON({ a: { b: "v" } }));
    +    expect(st.find(new Path("t")).isEmpty()).to.equal(false);
    +    st.remember(new Path("t"), ChildrenNode.EMPTY_NODE);
    +    expect(st.find(new Path("t")).isEmpty()).to.equal(true);
    +  });
    +
    +
    +  it("Simple remember and forget.", function () {
    +    var st = new SparseSnapshotTree();
    +    st.remember(new Path("t"), nodeFromJSON({ a: { b: "v" } }));
    +    expect(st.find(new Path("t")).isEmpty()).to.equal(false);
    +    st.forget(new Path("t"));
    +    expect(st.find(new Path("t"))).to.equal(null);
    +  });
    +
    +
    +  it("Forget the root.", function () {
    +    var st = new SparseSnapshotTree();
    +    st.remember(new Path("t"), nodeFromJSON({ a: { b: "v" } }));
    +    expect(st.find(new Path("t")).isEmpty()).to.equal(false);
    +    st.forget(new Path(""));
    +    expect(st.find(new Path("t"))).to.equal(null);
    +  });
    +
    +
    +  it("Forget snapshot inside snapshot.", function () {
    +    var st = new SparseSnapshotTree();
    +    st.remember(new Path("t"), nodeFromJSON({ a: { b: "v", c: 9, art: false } }));
    +    expect(st.find(new Path("t/a/c")).isEmpty()).to.equal(false);
    +    expect(st.find(new Path("t")).isEmpty()).to.equal(false);
    +
    +    st.forget(new Path("t/a/c"));
    +    expect(st.find(new Path("t"))).to.equal(null);
    +    expect(st.find(new Path("t/a"))).to.equal(null);
    +    expect(st.find(new Path("t/a/b")).val()).to.equal("v");
    +    expect(st.find(new Path("t/a/c"))).to.equal(null);
    +    expect(st.find(new Path("t/a/art")).val()).to.equal(false);
    +  });
    +
    +
    +  it("Forget path shallower than snapshots.", function () {
    +    var st = new SparseSnapshotTree();
    +    st.remember(new Path("t/x1"), nodeFromJSON(false));
    +    st.remember(new Path("t/x2"), nodeFromJSON(true));
    +    st.forget(new Path("t"));
    +    expect(st.find(new Path("t"))).to.equal(null);
    +  });
    +
    +
    +  it("Iterate children.", function () {
    +    var st = new SparseSnapshotTree();
    +    st.remember(new Path("t"), nodeFromJSON({ b: "v", c: 9, art: false }));
    +    st.remember(new Path("q"), ChildrenNode.EMPTY_NODE);
    +
    +    var num = 0, gotT = false, gotQ = false;
    +    st.forEachChild(function(key, child) {
    +      num += 1;
    +      if (key === "t") {
    +        gotT = true;
    +      } else if (key === "q") {
    +        gotQ = true;
    +      } else {
    +        expect(false).to.equal(true);
    +      }
    +    });
    +
    +    expect(gotT).to.equal(true);
    +    expect(gotQ).to.equal(true);
    +    expect(num).to.equal(2);
    +  });
    +
    +
    +  it("Iterate trees.", function () {
    +    var st = new SparseSnapshotTree();
    +
    +    var count = 0;
    +    st.forEachTree(new Path(""), function(path, tree) {
    +      count += 1;
    +    });
    +    expect(count).to.equal(0);
    +
    +    st.remember(new Path("t"), nodeFromJSON(1));
    +    st.remember(new Path("a/b"), nodeFromJSON(2));
    +    st.remember(new Path("a/x/g"), nodeFromJSON(3));
    +    st.remember(new Path("a/x/null"), nodeFromJSON(null));
    +
    +    var num = 0, got1 = false, got2 = false, got3 = false, got4 = false;
    +    st.forEachTree(new Path("q"), function(path, node) {
    +      num += 1;
    +      var pathString = path.toString();
    +      if (pathString === "/q/t") {
    +        got1 = true;
    +        expect(node.val()).to.equal(1);
    +      } else if (pathString === "/q/a/b") {
    +        got2 = true;
    +        expect(node.val()).to.equal(2);
    +      } else if (pathString === "/q/a/x/g") {
    +        got3 = true;
    +        expect(node.val()).to.equal(3);
    +      } else if (pathString === "/q/a/x/null") {
    +        got4 = true;
    +        expect(node.val()).to.equal(null);
    +      } else {
    +        expect(false).to.equal(true);
    +      }
    +    });
    +
    +    expect(got1).to.equal(true);
    +    expect(got2).to.equal(true);
    +    expect(got3).to.equal(true);
    +    expect(got4).to.equal(true);
    +    expect(num).to.equal(4);
    +  });
    +
    +  it("Set leaf, then forget deeper path", function() {
    +    var st = new SparseSnapshotTree();
    +
    +    st.remember(new Path('foo'), nodeFromJSON('bar'));
    +    var safeToRemove = st.forget(new Path('foo/baz'));
    +    // it's not safe to remove this node
    +    expect(safeToRemove).to.equal(false);
    +  });
    +
    +});
    diff --git a/tests/database/transaction.test.ts b/tests/database/transaction.test.ts
    new file mode 100644
    index 00000000000..d266a146893
    --- /dev/null
    +++ b/tests/database/transaction.test.ts
    @@ -0,0 +1,1238 @@
    +import { expect } from "chai";
    +import { Reference } from "../../src/database/api/Reference";
    +import { 
    +  canCreateExtraConnections,
    +  getFreshRepoFromReference,
    +  getRandomNode, 
    +  getVal, 
    +} from "./helpers/util";
    +import { eventTestHelper } from "./helpers/events";
    +import { EventAccumulator, EventAccumulatorFactory } from "./helpers/EventAccumulator";
    +import { hijackHash } from "../../src/database/api/test_access";
    +import firebase from "../../src/app";
    +import "../../src/database";
    +
    +// declare var runs;
    +// declare var waitsFor;
    +declare var TEST_TIMEOUT;
    +
    +describe('Transaction Tests', function() {
    +  it('New value is immediately visible.', function() {
    +    var node = (getRandomNode() as Reference);
    +    node.child('foo').transaction(function() {
    +      return 42;
    +    });
    +
    +    var val = null;
    +    node.child('foo').on('value', function(snap) {
    +      val = snap.val();
    +    });
    +    expect(val).to.equal(42);
    +  });
    +
    +  it.skip('Event is raised for new value.', function() {
    +    var node = (getRandomNode() as Reference);
    +    var fooNode = node.child('foo');
    +    var eventHelper = eventTestHelper([
    +      [fooNode, ['value', '']]
    +    ]);
    +
    +    node.child('foo').transaction(function() {
    +      return 42;
    +    });
    +
    +    expect(eventHelper.waiter()).to.equal(true);
    +  });
    +
    +  it('Non-aborted transaction sets committed to true in callback.', function(done) {
    +    var node = (getRandomNode() as Reference);
    +
    +    node.transaction(function() {
    +          return 42;
    +        },
    +        function(error, committed, snapshot) {
    +          expect(error).to.equal(null);
    +          expect(committed).to.equal(true);
    +          expect(snapshot.val()).to.equal(42);
    +          done();
    +        });
    +  });
    +
    +  it('Aborted transaction sets committed to false in callback.', function(done) {
    +    var node = (getRandomNode() as Reference);
    +
    +    node.transaction(function() {},
    +        function(error, committed, snapshot) {
    +          expect(error).to.equal(null);
    +          expect(committed).to.equal(false);
    +          expect(snapshot.val()).to.be.null;
    +          done();
    +        });
    +  });
    +
    +  it('Tetris bug test - set data, reconnect, do transaction that aborts once data arrives, verify correct events.',
    +      async function() {
    +    var nodePair = (getRandomNode(2) as Reference[]);
    +    var node = nodePair[0];
    +    var dataWritten = false;
    +    var eventsReceived = 0;
    +    const ea = EventAccumulatorFactory.waitsForCount(2);
    +
    +    await node.child('foo').set(42);
    +
    +    node = nodePair[1];
    +    node.child('foo').on('value', function(snap) {
    +      if (eventsReceived === 0) {
    +        expect(snap.val()).to.equal('temp value');
    +      }
    +      else if (eventsReceived === 1) {
    +        expect(snap.val()).to.equal(42);
    +      }
    +      else {
    +        // Extra event detected.
    +        expect(true).to.equal(false);
    +      }
    +      eventsReceived++;
    +      ea.addEvent();
    +    });
    +
    +    node.child('foo').transaction(function(value) {
    +      if (value === null)
    +        return 'temp value';
    +      else
    +        return;
    +    }, function(error, committed, snapshot) {
    +      expect(error).to.equal(null);
    +      expect(committed).to.equal(false);
    +      expect(snapshot.val()).to.equal(42);
    +    });
    +
    +    return ea.promise;
    +  });
    +
    +  it('Use transaction to create a node, make sure exactly one event is received.', function() {
    +    var node = (getRandomNode() as Reference);
    +    var events = 0, done = false;
    +
    +    const ea = new EventAccumulator(() => done && events === 1);
    +
    +    node.child('a').on('value', function() {
    +      events++;
    +      ea.addEvent();
    +      if (events > 1) throw 'Expected 1 event on a, but got two.';
    +    });
    +
    +    node.child('a').transaction(function() {
    +      return 42;
    +    }, function() {
    +      done = true;
    +      ea.addEvent();
    +    });
    +
    +    return ea.promise;
    +  });
    +
    +  it('Use transaction to update one of two existing child nodes. ' +
    +    'Make sure events are only raised for the changed node.', async function() {
    +    var nodePair = (getRandomNode(2) as Reference[]);
    +    var node = nodePair[0].child('foo');
    +    var writesDone = 0;
    +
    +    await Promise.all([
    +      node.child('a').set(42),
    +      node.child('b').set(42)
    +    ]);
    +
    +    node = nodePair[1].child('foo');
    +    const eventHelper = eventTestHelper([
    +      [node.child('a'), ['value', '']],
    +      [node.child('b'), ['value', '']]
    +    ]);
    +
    +    await eventHelper.promise;
    +
    +    eventHelper.addExpectedEvents([
    +      [node.child('b'), ['value', '']]
    +    ]);
    +    
    +    const transaction = node.transaction(function() {
    +      return {a: 42, b: 87};
    +    }, function(error, committed, snapshot) {
    +      expect(error).to.be.null;
    +      expect(committed).to.equal(true);
    +      expect(snapshot.val()).to.deep.equal({a: 42, b: 87});
    +    });
    +
    +    return Promise.all([
    +      eventHelper.promise,
    +      transaction
    +    ]);
    +  });
    +
    +  it('Transaction is only called once when initializing an empty node.', function() {
    +    var node = (getRandomNode() as Reference);
    +    var updateCalled = 0;
    +
    +    const ea = EventAccumulatorFactory.waitsForCount(1);
    +    node.transaction(function(value) {
    +      expect(value).to.equal(null);
    +      updateCalled++;
    +      ea.addEvent();
    +      if (updateCalled > 1)
    +        throw 'Transaction called too many times.';
    +
    +      if (value === null) {
    +        return { a: 5, b: 3 };
    +      }
    +    });
    +
    +    return ea.promise;
    +  });
    +
    +  it('Second transaction gets run immediately on previous output and only runs once.', function(done) {
    +    var nodePair = (getRandomNode(2) as Reference[]);
    +    var firstRun = false, firstDone = false, secondRun = false, secondDone = false;
    +
    +    function onComplete() {
    +      if (firstDone && secondDone) {
    +        nodePair[1].on('value', function(snap) {
    +          expect(snap.val()).to.equal(84);
    +          done();
    +        });
    +      }
    +    }
    +
    +    nodePair[0].transaction(function() {
    +      expect(firstRun).to.equal(false);
    +      firstRun = true;
    +      return 42;
    +    }, function(error, committed, snapshot) {
    +      expect(error).to.equal(null);
    +      expect(committed).to.equal(true);
    +      firstDone = true;
    +      onComplete();
    +    });
    +    expect(firstRun).to.equal(true);
    +
    +    nodePair[0].transaction(function(value) {
    +      expect(secondRun).to.equal(false);
    +      secondRun = true;
    +      expect(value).to.equal(42);
    +      return 84;
    +    }, function(error, committed, snapshot) {
    +      expect(error).to.equal(null);
    +      expect(committed).to.equal(true);
    +      secondDone = true;
    +      onComplete();
    +    });
    +    expect(secondRun).to.equal(true);
    +    
    +    expect(getVal(nodePair[0])).to.equal(84);
    +  });
    +
    +  it('Set() cancels pending transactions and re-runs affected transactions.', async function() {
    +    // We do 3 transactions: 1) At /foo, 2) At /, and 3) At /bar.
    +    // Only #1 is sent to the server immediately (since 2 depends on 1 and 3 depends on 2).
    +    // We set /foo to 0.
    +    //   Transaction #1 should complete as planned (since it was already sent).
    +    //   Transaction #2 should be aborted by the set.
    +    //   Transaction #3 should be re-run after #2 is reverted, and then be sent to the server and succeed.
    +    var firstDone = false, secondDone = false, thirdDone = false;
    +    var node = (getRandomNode() as Reference);
    +    var nodeSnap = null;
    +    var nodeFooSnap = null;
    +
    +    node.on('value', function(s) {
    +      var str = JSON.stringify(s.val());
    +      nodeSnap = s;
    +    });
    +    node.child('foo').on('value', function(s) {
    +      var str = JSON.stringify(s.val());
    +      nodeFooSnap = s;
    +    });
    +
    +
    +    var firstRun = false, secondRun = false, thirdRunCount = 0;
    +    const ea = new EventAccumulator(() => firstDone && thirdDone);
    +    node.child('foo').transaction(
    +      function() {
    +        expect(firstRun).to.equal(false);
    +        firstRun = true;
    +        return 42;
    +      },
    +      function(error, committed, snapshot) {
    +        expect(error).to.equal(null);
    +        expect(committed).to.equal(true);
    +        expect(snapshot.val()).to.equal(42);
    +        firstDone = true;
    +        ea.addEvent();
    +      });
    +    expect(nodeFooSnap.val()).to.deep.equal(42);
    +
    +    node.transaction(
    +      function() {
    +        expect(secondRun).to.equal(false);
    +        secondRun = true;
    +        return { 'foo' : 84, 'bar' : 1};
    +      },
    +      function(error, committed, snapshot) {
    +        expect(committed).to.equal(false);
    +        secondDone = true;
    +        ea.addEvent();
    +      }
    +    );
    +    expect(secondRun).to.equal(true);
    +    expect(nodeSnap.val()).to.deep.equal({'foo': 84, 'bar': 1});
    +
    +    node.child('bar').transaction(function(val) {
    +      thirdRunCount++;
    +      if (thirdRunCount === 1) {
    +        expect(val).to.equal(1);
    +        return 'first';
    +      } else if (thirdRunCount === 2) {
    +        expect(val).to.equal(null);
    +        return 'second';
    +      } else {
    +        throw new Error('Called too many times!');
    +      }
    +    }, function(error, committed, snapshot) {
    +      expect(error).to.equal(null);
    +      expect(committed).to.equal(true);
    +      expect(snapshot.val()).to.equal('second');
    +      thirdDone = true;
    +      ea.addEvent();
    +    });
    +    expect(thirdRunCount).to.equal(1);
    +    expect(nodeSnap.val()).to.deep.equal({'foo' : 84, 'bar': 'first'});
    +
    +    // This rolls back the second transaction, and triggers a re-run of the third.
    +    // However, a new value event won't be triggered until the listener is complete,
    +    // so we're left with the last value event
    +    node.child('foo').set(0);
    +
    +    expect(firstDone).to.equal(false);
    +    expect(secondDone).to.equal(true);
    +    expect(thirdRunCount).to.equal(2);
    +    // Note that the set actually raises two events, one overlaid on top of the original transaction value, and a
    +    // second one with the re-run value from the third transaction
    +
    +    await ea.promise;
    +
    +    expect(nodeSnap.val()).to.deep.equal({'foo' : 0, 'bar': 'second'});
    +  });
    +
    +  it('transaction(), set(), set() should work.', function(done) {
    +    var ref = (getRandomNode() as Reference);
    +    ref.transaction(function(curr) {
    +      expect(curr).to.equal(null);
    +      return 'hi!';
    +    }, function(error, committed) {
    +      expect(error).to.equal(null);
    +      expect(committed).to.equal(true);
    +      done();
    +    });
    +
    +    ref.set('foo');
    +    ref.set('bar');
    +  });
    +
    +  it('Priority is preserved when setting data.', async function() {
    +    var node = (getRandomNode() as Reference), complete = false;
    +    var snap;
    +    node.on('value', function(s) { snap = s; });
    +    node.setWithPriority('test', 5);
    +    expect(snap.getPriority()).to.equal(5);
    +
    +    const promise = node.transaction(
    +        function() { return 'new value'},
    +        function() { complete = true; }
    +    );
    +
    +    expect(snap.val()).to.equal('new value');
    +    expect(snap.getPriority()).to.equal(5);
    +
    +    await promise;
    +    expect(snap.getPriority()).to.equal(5);
    +  });
    +
    +  it('Tetris bug test - Can do transactions from transaction callback.', async function() {
    +    var nodePair = (getRandomNode(2) as Reference[]), writeDone = false;
    +    await nodePair[0].child('foo').set(42);
    +
    +    var transactionTwoDone = false;
    +    
    +    var node = nodePair[1];
    +
    +    return new Promise(resolve => {
    +      node.child('foo').transaction(function(val) {
    +        if (val === null)
    +          return 84;
    +      }, function() {
    +        node.child('bar').transaction(function(val) {
    +          resolve();
    +          return 168;
    +        });
    +      });
    +    })
    +  });
    +
    +  it('Resulting snapshot is passed to onComplete callback.', async function() {
    +    var nodePair = (getRandomNode(2) as Reference[]);
    +    var done = false;
    +    await nodePair[0].transaction(function(v) {
    +      if (v === null)
    +        return 'hello!';
    +    }, function(error, committed, snapshot) {
    +      expect(error).to.equal(null);
    +      expect(committed).to.equal(true);
    +      expect(snapshot.val()).to.equal('hello!');
    +    });
    +
    +    // Do it again for the aborted case.
    +    await nodePair[0].transaction(function(v) {
    +      if (v === null)
    +        return 'hello!';
    +    }, function(error, committed, snapshot) {
    +      expect(committed).to.equal(false);
    +      expect(snapshot.val()).to.equal('hello!');
    +    });
    +
    +    // Do it again on a fresh connection, for the aborted case.
    +    await nodePair[1].transaction(function(v) {
    +      if (v === null)
    +        return 'hello!';
    +    }, function(error, committed, snapshot) {
    +      expect(committed).to.equal(false);
    +      expect(snapshot.val()).to.equal('hello!');
    +    });
    +  });
    +
    +  it('Transaction aborts after 25 retries.', function(done) {
    +    var restoreHash = hijackHash(function() {
    +      return 'duck, duck, goose.';
    +    });
    +
    +    var node = (getRandomNode() as Reference);
    +    var tries = 0;
    +    node.transaction(function(curr) {
    +      expect(tries).to.be.lessThan(25);
    +      tries++;
    +      return 'hello!';
    +    }, function(error, committed, snapshot) {
    +      expect(error.message).to.equal('maxretry');
    +      expect(committed).to.equal(false);
    +      expect(tries).to.equal(25);
    +      restoreHash();
    +      done();
    +    });
    +  });
    +
    +  it('Set should cancel already sent transactions that come back as datastale.', function(done) {
    +    var nodePair = (getRandomNode(2) as Reference[]);
    +    var transactionCalls = 0;
    +    nodePair[0].set(5, function() {
    +      nodePair[1].transaction(function(old) {
    +        expect(transactionCalls).to.equal(0);
    +        expect(old).to.equal(null);
    +        transactionCalls++;
    +        return 72;
    +      }, function(error, committed, snapshot) {
    +        expect(error.message).to.equal('set');
    +        expect(committed).to.equal(false);
    +        done();
    +      });
    +
    +      // Transaction should get sent but fail due to stale data, and then aborted because of the below set().
    +      nodePair[1].set(32);
    +    });
    +  });
    +
    +  it('Update should not cancel unrelated transactions', async function() {
    +    var node = (getRandomNode() as Reference);
    +    var fooTransactionDone = false;
    +    var barTransactionDone = false;
    +    var restoreHash = hijackHash(function() {
    +      return 'foobar';
    +    });
    +
    +    await node.child('foo').set(5);
    +    
    +    // 'foo' gets overwritten in the update so the transaction gets cancelled.
    +    node.child('foo').transaction(function(old) {
    +      return 72;
    +    }, function(error, committed, snapshot) {
    +      expect(error.message).to.equal('set');
    +      expect(committed).to.equal(false);
    +      fooTransactionDone = true;
    +    });
    +
    +    // 'bar' does not get touched during the update and the transaction succeeds.
    +    node.child('bar').transaction(function(old) {
    +      return 72;
    +    }, function(error, committed, snapshot) {
    +      expect(error).to.equal(null);
    +      expect(committed).to.equal(true);
    +      barTransactionDone = true;
    +    });
    +
    +    await node.update({
    +      'foo': 'newValue',
    +      'boo': 'newValue',
    +      'loo' : {
    +        'doo' : {
    +          'boo': 'newValue'
    +        }
    +      }
    +    });
    +
    +    expect(fooTransactionDone).to.equal(true);
    +    expect(barTransactionDone).to.equal(false);
    +    restoreHash();
    +  });
    +
    +  it('Test transaction on wacky unicode data.', function(done) {
    +    var nodePair = (getRandomNode(2) as Reference[]);
    +    nodePair[0].set('♜♞♝♛♚♝♞♜', function() {
    +      nodePair[1].transaction(function(current) {
    +        if (current !== null)
    +          expect(current).to.equal('♜♞♝♛♚♝♞♜');
    +        return '♖♘♗♕♔♗♘♖';
    +      }, function(error, committed, snapshot) {
    +        expect(error).to.equal(null);
    +        expect(committed).to.equal(true);
    +        done();
    +      });
    +    });
    +  });
    +
    +  it('Test immediately aborted transaction.', function(done) {
    +    var node = (getRandomNode() as Reference);
    +    // without callback.
    +    node.transaction(function(curr) {
    +      return;
    +    });
    +
    +    // with callback.
    +    node.transaction(function(curr) {
    +      return;
    +    }, function(error, committed, snapshot) {
    +      expect(committed).to.equal(false);
    +      done();
    +    });
    +  });
    +
    +  it('Test adding to an array with a transaction.', function(done) {
    +    var node = (getRandomNode() as Reference);
    +    node.set(['cat', 'horse'], function() {
    +      node.transaction(function(current) {
    +        if (current) {
    +          current.push('dog');
    +        } else {
    +          current = ['dog'];
    +        }
    +        return current;
    +      }, function(error, committed, snapshot) {
    +        expect(error).to.equal(null);
    +        expect(committed).to.equal(true);
    +        expect(snapshot.val()).to.deep.equal(['cat', 'horse', 'dog']);
    +        done();
    +      });
    +    });
    +  });
    +
    +  it('Merged transactions have correct snapshot in onComplete.', async function() {
    +    var nodePair = (getRandomNode(2) as Reference[]), node1 = nodePair[0], node2 = nodePair[1];
    +    var transaction1Done, transaction2Done;
    +    await node1.set({a: 0});
    +    
    +    const tx1 = node2.transaction(function(val) {
    +      if (val !== null) {
    +        expect(val).to.deep.equal({a: 0});
    +      }
    +      return {a: 1};
    +    }, function(error, committed, snapshot) {
    +      expect(error).to.equal(null);
    +      expect(committed).to.equal(true);
    +      expect(snapshot.key).to.equal(node2.key);
    +      // Per new behavior, will include the accepted value of the transaction, if it was successful.
    +      expect(snapshot.val()).to.deep.equal({a: 1});
    +      transaction1Done = true;
    +    });
    +
    +    const tx2 = node2.child('a').transaction(function(val) {
    +      if (val !== null) {
    +        expect(val).to.equal(1); // should run after the first transaction.
    +      }
    +      return 2;
    +    }, function(error, committed, snapshot) {
    +      expect(error).to.equal(null)
    +      expect(committed).to.equal(true);
    +      expect(snapshot.key).to.equal('a');
    +      expect(snapshot.val()).to.deep.equal(2);
    +      transaction2Done = true;
    +    });
    +
    +    return Promise.all([ tx1, tx2 ])
    +  });
    +
    +  it('Doing set() in successful transaction callback works. Case 870.', function(done) {
    +    var node = (getRandomNode() as Reference);
    +    var transactionCalled = false;
    +    var callbackCalled = false;
    +    node.transaction(function(val) {
    +      expect(transactionCalled).to.not.be.ok;
    +      transactionCalled = true;
    +      return 'hi';
    +    }, function() {
    +      expect(callbackCalled).to.not.be.ok;
    +      callbackCalled = true;
    +      node.set('transaction done', function() {
    +        done();
    +      });
    +    });
    +  });
    +
    +  it('Doing set() in aborted transaction callback works. Case 870.', function(done) {
    +    var nodePair = (getRandomNode(2) as Reference[]), node1 = nodePair[0], node2 = nodePair[1];
    +
    +    node1.set('initial', function() {
    +      var transactionCalled = false;
    +      var callbackCalled = false;
    +      node2.transaction(function(val) {
    +        // Return dummy value until we're called with the actual current value.
    +        if (val === null)
    +          return 'hi';
    +
    +        expect(transactionCalled).to.not.be.ok;
    +        transactionCalled = true;
    +        return;
    +      }, function(error, committed, snapshot) {
    +        expect(callbackCalled).to.not.be.ok;
    +        callbackCalled = true;
    +        node2.set('transaction done', function() {
    +          done();
    +        });
    +      });
    +    });
    +  });
    +
    +  it('Pending transactions are canceled on disconnect.', function(done) {
    +    var ref = (getRandomNode() as Reference);
    +
    +    // wait to be connected and some data set.
    +    ref.set('initial', function() {
    +      ref.transaction(function(current) {
    +        return 'new';
    +      }, function(error, committed, snapshot) {
    +        expect(committed).to.equal(false);
    +        expect(error.message).to.equal('disconnect');
    +        done();
    +      });
    +
    +      // Kill the connection, which should cancel the outstanding transaction, since we don't know if it was
    +      // committed on the server or not.
    +      ref.database.goOffline();
    +      ref.database.goOnline();
    +    });
    +  });
    +
    +  it('Transaction without local events (1)', async function() {
    +    var ref = (getRandomNode() as Reference), actions = [];
    +    let ea = EventAccumulatorFactory.waitsForCount(1);
    +
    +    ref.on('value', function(s) {
    +      actions.push('value ' + s.val());
    +      ea.addEvent();
    +    });
    +
    +    await ea.promise;
    +
    +    ea = new EventAccumulator(() => actions.length >= 4);
    +    
    +    ref.transaction(function() {
    +      return 'hello!';
    +    }, function(error, committed, snapshot) {
    +      expect(error).to.be.null;
    +      expect(committed).to.equal(true);
    +      expect(snapshot.val()).to.equal('hello!');
    +
    +      actions.push('txn completed');
    +      ea.addEvent();      
    +    }, /*applyLocally=*/false);
    +
    +    // Shouldn't have gotten any events yet.
    +    expect(actions).to.deep.equal(['value null']);
    +    actions.push('txn run');
    +    ea.addEvent();    
    +
    +    await ea.promise;
    +
    +    expect(actions).to.deep.equal(['value null', 'txn run', 'value hello!', 'txn completed']);
    +  });
    +
    +  // This test is meant to ensure that with applyLocally=false, while the transaction is outstanding, we continue
    +  // to get events from other clients.
    +  it('Transaction without local events (2)', function(done) {
    +    var refPair = (getRandomNode(2) as Reference[]), ref1 = refPair[0], ref2 = refPair[1];
    +    var restoreHash = hijackHash(function() { return 'badhash'; });
    +    var SETS = 4;
    +    var events = [], retries = 0, setsDone = 0;
    +    var ready = false;
    +
    +    function txn1(next) {
    +      // Do a transaction on the first connection which will keep retrying (cause we hijacked the hash).
    +      // Make sure we're getting events for the sets happening on the second connection.
    +      ref1.transaction(function(current) {
    +        retries++;
    +        // We should be getting server events while the transaction is outstanding.
    +        for (var i = 0; i < (current || 0); i++) {
    +          expect(events[i]).to.equal(i);
    +        }
    +
    +        if (current === SETS - 1) {
    +          restoreHash();
    +        }
    +        return 'txn result';
    +      }, function(error, committed, snapshot) {
    +        expect(error).to.equal(null);
    +        expect(committed).to.equal(true);
    +
    +        expect(snapshot && snapshot.val()).to.equal('txn result');
    +        next()
    +      }, /*applyLocally=*/false);
    +
    +
    +      // Meanwhile, do sets from the second connection.
    +      var doSet = function() {
    +        ref2.set(setsDone, function() {
    +          setsDone++;
    +          if (setsDone < SETS)
    +            doSet();
    +        });
    +      };
    +      doSet();
    +    }
    +
    +    ref1.set(0, function() {
    +      ref1.on('value', function(snap) {
    +        events.push(snap.val());
    +        if (events.length === 1 && events[0] === 0) {
    +          txn1(function() {
    +            // Sanity check stuff.
    +            expect(setsDone).to.equal(SETS);
    +            if (retries === 0)
    +              throw 'Transaction should have had to retry!';
    +
    +            // Validate we got the correct events.
    +            for (var i = 0; i < SETS; i++) {
    +              expect(events[i]).to.equal(i);
    +            }
    +            expect(events[SETS]).to.equal('txn result');
    +
    +            restoreHash();
    +            done();
    +          });
    +        }
    +      });
    +    });
    +  });
    +
    +  it('Transaction from value callback.', function(done) {
    +    var ref = (getRandomNode() as Reference);
    +    var COUNT = 1;
    +    ref.on('value', function(snap) {
    +      var shouldCommit = true;
    +      ref.transaction(function(current) {
    +        if (current == null) {
    +          return 0;
    +        } else if (current < COUNT) {
    +          return current + 1;
    +        } else {
    +          shouldCommit = false;
    +        }
    +
    +        if (snap.val() === COUNT) {
    +          done();
    +        }
    +      }, function(error, committed, snap) {
    +        expect(committed).to.equal(shouldCommit);
    +      });
    +    });
    +  });
    +
    +  it('Transaction runs on null only once after reconnect (Case 1981).', async function() {
    +    if (!canCreateExtraConnections()) return;
    +
    +    var ref = (getRandomNode() as Reference);
    +    await ref.set(42);
    +    var newRef = getFreshRepoFromReference(ref);
    +    var run = 0;
    +    return newRef.transaction(function(curr) {
    +      run++;
    +      if (run === 1) {
    +        expect(curr).to.equal(null);
    +      } else if (run === 2) {
    +        expect(curr).to.equal(42);
    +      }
    +      return 3.14;
    +    }, function(error, committed, resultSnapshot) {
    +      expect(error).to.equal(null);
    +      expect(committed).to.equal(true);
    +      expect(run).to.equal(2);
    +      expect(resultSnapshot.val()).to.equal(3.14);
    +    });
    +  });
    +
    +  // Provided by bk@thinkloop.com, this was failing when we sent puts before listens, but passes now.
    +  it('makeFriends user test case.', function() {
    +    const ea = EventAccumulatorFactory.waitsForCount(12);
    +    if (!canCreateExtraConnections()) return;
    +
    +    function makeFriends(accountID, friendAccountIDs, firebase) {
    +      var friendAccountID,
    +          i;
    +
    +      // add friend relationships
    +      for (i in friendAccountIDs) {
    +        if (friendAccountIDs.hasOwnProperty(i)) {
    +          friendAccountID = friendAccountIDs[i];
    +          makeFriend(friendAccountID, accountID, firebase);
    +          makeFriend(accountID, friendAccountID, firebase);
    +        }
    +      }
    +    }
    +
    +    function makeFriend(accountID, friendAccountID, firebase) {
    +      firebase.child(accountID).child(friendAccountID).transaction(function(r) {
    +            if (r == null) {
    +              r = { accountID: accountID, friendAccountID: friendAccountID, percentCommon: 0 };
    +            }
    +
    +            return r;
    +          },
    +          function(error, committed, snapshot) {
    +            if (error) {
    +              throw error;
    +            }
    +            else if (!committed) {
    +              throw 'All should be committed!';
    +            }
    +            else {
    +              count++;
    +              ea.addEvent();
    +              snapshot.ref.setPriority(snapshot.val().percentCommon);
    +            }
    +          }, false);
    +    }
    +
    +    var firebase = (getRandomNode() as Reference);
    +    firebase.database.goOffline();
    +    firebase.database.goOnline();
    +    var count = 0;
    +    makeFriends('a1', ['a2', 'a3'], firebase);
    +    makeFriends('a2', ['a1', 'a3'], firebase);
    +    makeFriends('a3', ['a1', 'a2'], firebase);
    +    return ea.promise;
    +  });
    +
    +  it('transaction() respects .priority.', function(done) {
    +    var ref = (getRandomNode() as Reference);
    +    var values = [];
    +    ref.on('value', function(s) { values.push(s.exportVal()); });
    +
    +    ref.transaction(function(curr) {
    +      expect(curr).to.equal(null);
    +      return {'.value': 5, '.priority': 5};
    +    }, function() {
    +      ref.transaction(function(curr) {
    +        expect(curr).to.equal(5);
    +        return {'.value': 10, '.priority': 10 };
    +      }, function() {
    +        expect(values).to.deep.equal([
    +          {'.value': 5, '.priority': 5},
    +          {'.value': 10, '.priority': 10}
    +        ]);
    +        done();
    +      });
    +    });
    +  });
    +
    +  it('Transaction properly reverts data when you add a deeper listen.', function(done) {
    +    var refPair = (getRandomNode(2) as Reference[]), ref1 = refPair[0], ref2 = refPair[1];
    +    var gotTest;
    +    ref1.child('y').set('test', function() {
    +      ref2.transaction(function(curr) {
    +        if (curr === null) {
    +          return { x: 1 };
    +        }
    +      });
    +
    +      ref2.child('y').on('value', function(s) {
    +        if (s.val() === 'test') {
    +          done();
    +        };
    +      });
    +    });
    +  });
    +
    +  it('Transaction with integer keys', function(done) {
    +    var ref = (getRandomNode() as Reference);
    +    ref.set({1: 1, 5: 5, 10: 10, 20: 20}, function() {
    +      ref.transaction(function(current) {
    +        return 42;
    +      }, function(error, committed) {
    +        expect(error).to.be.null;
    +        expect(committed).to.equal(true);
    +        done();
    +      });
    +    });
    +  });
    +
    +  it('Return null from first run of transaction.', function(done) {
    +    var ref = (getRandomNode() as Reference);
    +    ref.transaction(function(c) {
    +      return null;
    +    }, function(error, committed) {
    +      expect(error).to.equal(null);
    +      expect(committed).to.equal(true);
    +      done();
    +    });
    +  });
    +
    +  // https://app.asana.com/0/5673976843758/9259161251948
    +  it('Bubble-app transaction bug.', function(done) {
    +    var ref = (getRandomNode() as Reference);
    +    ref.child('a').transaction(function() {
    +      return 1;
    +    });
    +    ref.child('a').transaction(function(current) {
    +      return current + 42;
    +    });
    +    ref.child('b').transaction(function() {
    +      return 7;
    +    });
    +    ref.transaction(function(current) {
    +      if (current && current.a && current.b) {
    +        return current.a + current.b;
    +      } else {
    +        return 'dummy';
    +      }
    +    }, function(error, committed, snap) {
    +      expect(error).to.equal(null);
    +      expect(committed).to.equal(true);
    +      expect(snap.val()).to.deep.equal(50);
    +      done();
    +    });
    +  });
    +
    +  it('Transaction and priority: Can set priority in transaction on empty node', async function() {
    +    var ref = (getRandomNode() as Reference);
    +    var done = false;
    +
    +    await ref.transaction(function(current) {
    +      return { '.value': 42, '.priority': 7 };
    +    });
    +
    +    return ref.once('value', function(s) {
    +      expect(s.exportVal()).to.deep.equal({ '.value': 42, '.priority': 7});
    +    });
    +  });
    +
    +  it("Transaction and priority: Transaction doesn't change priority.", async function() {
    +    var ref = (getRandomNode() as Reference);
    +    var done = false;
    +
    +    await ref.set({ '.value': 42, '.priority': 7 });
    +
    +    await ref.transaction(function(current) {
    +      return 12;
    +    });
    +
    +    const snap = await ref.once('value');
    +
    +    expect(snap.exportVal()).to.deep.equal({ '.value': 12, '.priority': 7});
    +  });
    +
    +  it('Transaction and priority: Transaction can change priority on non-empty node.', async function() {
    +    var ref = (getRandomNode() as Reference);
    +    var done = false;
    +
    +    await ref.set({ '.value': 42, '.priority': 7 });
    +
    +    await ref.transaction(function(current) {
    +      return { '.value': 43, '.priority': 8 };
    +    }, function() {
    +      done = true;
    +    });
    +
    +    return ref.once('value', function(s) {
    +      expect(s.exportVal()).to.deep.equal({ '.value': 43, '.priority': 8});
    +    });
    +  });
    +
    +  it('Transaction and priority: Changing priority on siblings.', async function() {
    +    var ref = (getRandomNode() as Reference);
    +    var done = false, done2 = false;
    +
    +    await ref.set({ 
    +      a: { '.value': 'a', '.priority': 'a' }, 
    +      b: { '.value': 'b', '.priority': 'b' } 
    +    });
    +
    +    const tx1 = ref.child('a').transaction(function(current) {
    +      return { '.value': 'a2', '.priority': 'a2' };
    +    });
    +
    +    const tx2 = ref.child('b').transaction(function(current) {
    +      return { '.value': 'b2', '.priority': 'b2' };
    +    });
    +
    +    await Promise.all([tx1, tx2]);
    +
    +    return ref.once('value', function(s) {
    +      expect(s.exportVal()).to.deep.equal({ a: { '.value': 'a2', '.priority': 'a2' }, b: { '.value': 'b2', '.priority': 'b2' } });
    +    });
    +  });
    +
    +  it('Transaction and priority: Leaving priority on siblings.', async function() {
    +    var ref = (getRandomNode() as Reference);
    +    var done = false, done2 = false;
    +
    +    await ref.set({a: {'.value': 'a', '.priority': 'a'}, b: {'.value': 'b', '.priority': 'b'}});
    +
    +    const tx1 = ref.child('a').transaction(function(current) {
    +      return 'a2';
    +    });
    +
    +    const tx2 = ref.child('b').transaction(function(current) {
    +      return 'b2';
    +    });
    +
    +    await Promise.all([tx1, tx2]);
    +
    +    return ref.once('value', function(s) {
    +      expect(s.exportVal()).to.deep.equal({ a: { '.value': 'a2', '.priority': 'a' }, b: { '.value': 'b2', '.priority': 'b' } });
    +    });
    +  });
    +
    +  it('transaction() doesn\'t pick up cached data from previous once().', function(done) {
    +    var refPair = (getRandomNode(2) as Reference[]);
    +    var me = refPair[0], other = refPair[1];
    +    me.set('not null', function() {
    +      me.once('value', function(snapshot) {
    +        other.set(null, function() {
    +          me.transaction(function(snapshot) {
    +            if (snapshot === null) {
    +              return 'it was null!';
    +            } else {
    +              return 'it was not null!';
    +            }
    +          }, function(err, committed, snapshot) {
    +            expect(err).to.equal(null);
    +            expect(committed).to.equal(true);
    +            expect(snapshot.val()).to.deep.equal('it was null!');
    +            done();
    +          });
    +        });
    +      });
    +    });
    +  });
    +
    +  it('transaction() doesn\'t pick up cached data from previous transaction.', function(done) {
    +    var refPair = (getRandomNode(2) as Reference[]);
    +    var me = refPair[0], other = refPair[1];
    +    me.transaction(function() {
    +      return 'not null';
    +    }, function(err, committed) {
    +      expect(err).to.equal(null);
    +      expect(committed).to.equal(true);
    +      other.set(null, function() {
    +        me.transaction(function(snapshot) {
    +          if (snapshot === null) {
    +            return 'it was null!';
    +          } else {
    +            return 'it was not null!';
    +          }
    +        }, function(err, committed, snapshot) {
    +          expect(err).to.equal(null);
    +          expect(committed).to.equal(true);
    +          expect(snapshot.val()).to.deep.equal('it was null!');
    +          done();
    +        });
    +      });
    +    });
    +  });
    +
    +  it("server values: local timestamp should eventually (but not immediately) match the server with txns", function(done) {
    +    var refPair = (getRandomNode(2) as Reference[]),
    +        writer = refPair[0],
    +        reader = refPair[1],
    +        readSnaps = [], writeSnaps = [];
    +
    +    var evaluateCompletionCriteria = function() {
    +      if (readSnaps.length === 1 && writeSnaps.length === 2) {
    +        expect(Math.abs(new Date().getTime() - writeSnaps[0].val()) < 10000).to.equal(true);
    +        expect(Math.abs(new Date().getTime() - writeSnaps[0].getPriority()) < 10000).to.equal(true);
    +        expect(Math.abs(new Date().getTime() - writeSnaps[1].val()) < 10000).to.equal(true);
    +        expect(Math.abs(new Date().getTime() - writeSnaps[1].getPriority()) < 10000).to.equal(true);
    +
    +        expect(writeSnaps[0].val() === writeSnaps[1].val()).to.equal(false);
    +        expect(writeSnaps[0].getPriority() === writeSnaps[1].getPriority()).to.equal(false);
    +        expect(writeSnaps[1].val() === readSnaps[0].val()).to.equal(true);
    +        expect(writeSnaps[1].getPriority() === readSnaps[0].getPriority()).to.equal(true);
    +        done();
    +      }
    +    };
    +
    +    // 1st non-null event = actual server timestamp
    +    reader.on('value', function(snap) {
    +      if (snap.val() === null) return;
    +      readSnaps.push(snap);
    +      evaluateCompletionCriteria();
    +    });
    +
    +    // 1st non-null event = local timestamp estimate
    +    // 2nd non-null event = actual server timestamp
    +    writer.on('value', function(snap) {
    +      if (snap.val() === null) return;
    +      writeSnaps.push(snap);
    +      evaluateCompletionCriteria();
    +    });
    +
    +    // Generate the server value offline to make sure there's a time gap between the client's guess of the timestamp
    +    // and the server's actual timestamp.
    +    writer.database.goOffline();
    +
    +    writer.transaction(function(current) {
    +      return {
    +        '.value'    : firebase.database.ServerValue.TIMESTAMP,
    +        '.priority' : firebase.database.ServerValue.TIMESTAMP
    +      };
    +    });
    +
    +    writer.database.goOnline();
    +  });
    +
    +  it("transaction() still works when there's a query listen.", function(done) {
    +    var ref = (getRandomNode() as Reference);
    +
    +    ref.set({
    +      a: 1,
    +      b: 2
    +    }, function() {
    +      ref.limitToFirst(1).on('child_added', function() {});
    +
    +      ref.child('a').transaction(function(current) {
    +        return current;
    +      }, function(error, committed, snapshot) {
    +        expect(error).to.equal(null);
    +        expect(committed).to.equal(true);
    +        if (!error) {
    +          expect(snapshot.val()).to.deep.equal(1);
    +        }
    +        done();
    +      }, false);
    +    });
    +  });
    +
    +  it("transaction() on queried location doesn't run initially on null (firebase-worker-queue depends on this).",
    +      function(done) {
    +    var ref = (getRandomNode() as Reference);
    +    ref.push({ a: 1, b: 2}, function() {
    +      ref.startAt().limitToFirst(1).on('child_added', function(snap) {
    +        snap.ref.transaction(function(current) {
    +          expect(current).to.deep.equal({a: 1, b: 2});
    +          return null;
    +        }, function(error, committed, snapshot) {
    +          expect(error).to.equal(null);
    +          expect(committed).to.equal(true);
    +          expect(snapshot.val()).to.equal(null);
    +          done();
    +        });
    +      });
    +    });
    +  });
    +
    +  it('transactions raise correct child_changed events on queries', async function() {
    +    var ref = (getRandomNode() as Reference);
    +
    +    var value = { foo: { value: 1 } };
    +    var txnDone = false;
    +    var snapshots = [];
    +
    +    await ref.set(value)
    +
    +    var query = ref.endAt(Number.MIN_VALUE);
    +    query.on('child_added', function(snapshot) {
    +      snapshots.push(snapshot);
    +    });
    +
    +    query.on('child_changed', function(snapshot) {
    +      snapshots.push(snapshot);
    +    });
    +
    +    await ref.child('foo').transaction(function(current) {
    +      return {value: 2};
    +    }, function(error, committed, snapshot) {
    +      expect(error).to.equal(null);
    +      expect(committed).to.equal(true);
    +    }, false);
    +
    +    expect(snapshots.length).to.equal(2);
    +    var addedSnapshot = snapshots[0];
    +    expect(addedSnapshot.key).to.equal('foo');
    +    expect(addedSnapshot.val()).to.deep.equal({ value: 1 });
    +    var changedSnapshot = snapshots[1];
    +    expect(changedSnapshot.key).to.equal('foo');
    +    expect(changedSnapshot.val()).to.deep.equal({ value: 2 });
    +  });
    +
    +  it('transactions can use local merges', function(done) {
    +    var ref = (getRandomNode() as Reference);
    +
    +    ref.update({'foo': 'bar'});
    +
    +    ref.child('foo').transaction(function(current) {
    +      expect(current).to.equal('bar');
    +      return current;
    +    }, function(error, committed, snapshot) {
    +      expect(error).to.equal(null);
    +      expect(committed).to.equal(true);
    +      done();
    +    });
    +  });
    +
    +  it('transactions works with merges without the transaction path', function(done) {
    +    var ref = (getRandomNode() as Reference);
    +
    +    ref.update({'foo': 'bar'});
    +
    +    ref.child('non-foo').transaction(function(current) {
    +      expect(current).to.equal(null);
    +      return current;
    +    }, function(error, committed, snapshot) {
    +      expect(error).to.equal(null);
    +      expect(committed).to.equal(true);
    +      done();
    +    });
    +  });
    +
    +  //See https://app.asana.com/0/15566422264127/23303789496881
    +  it('out of order remove writes are handled correctly', function(done) {
    +    var ref = (getRandomNode() as Reference);
    +
    +    ref.set({foo: 'bar'});
    +    ref.transaction(function() {
    +      return 'transaction-1';
    +    }, function() { });
    +    ref.transaction(function() {
    +      return 'transaction-2';
    +    }, function() { });
    +
    +    // This will trigger an abort of the transaction which should not cause the client to crash
    +    ref.update({qux: 'quu' }, function(error) {
    +      expect(error).to.equal(null);
    +      done();
    +    });
    +  });
    +});
    diff --git a/tests/package/binary/browser/binary_namespace.test.ts b/tests/package/binary/browser/binary_namespace.test.ts
    index a423a5ab42d..216742a3e57 100644
    --- a/tests/package/binary/browser/binary_namespace.test.ts
    +++ b/tests/package/binary/browser/binary_namespace.test.ts
    @@ -23,7 +23,7 @@ import { FirebaseNamespace } from "../../../../src/app/firebase_app";
     import { firebaseSpec } from "../../utils/definitions/firebase";
     import { storageInstanceSpec } from "../../utils/definitions/storage";
     import { authInstanceSpec } from "../../utils/definitions/auth";
    -import { compiledMessagingInstanceSpec } from "../../utils/definitions/messaging";
    +import { messagingInstanceSpec } from "../../utils/definitions/messaging";
     import { databaseInstanceSpec } from "../../utils/definitions/database";
     
     const appConfig = {
    @@ -66,7 +66,7 @@ describe('Binary Namespace Test', () => {
       });
       describe('firebase.messaging() Verification', () => {
         it('firebase.messaging() should expose proper namespace', () => {
    -      checkProps('firebase.messaging()', (firebase as any).messaging(), compiledMessagingInstanceSpec);
    +      checkProps('firebase.messaging()', (firebase as any).messaging(), messagingInstanceSpec);
         });
       });
     });
    diff --git a/tests/app/unit/deep_copy.test.ts b/tests/utils/deep_copy.test.ts
    similarity index 97%
    rename from tests/app/unit/deep_copy.test.ts
    rename to tests/utils/deep_copy.test.ts
    index fa696638d9f..1c6425caed9 100644
    --- a/tests/app/unit/deep_copy.test.ts
    +++ b/tests/utils/deep_copy.test.ts
    @@ -14,7 +14,7 @@
     * limitations under the License.
     */
     import {assert} from 'chai';
    -import {deepCopy, deepExtend} from '../../../src/app/deep_copy';
    +import {deepCopy, deepExtend} from '../../src/utils/deep_copy';
     
     describe("deepCopy()", () => {
       it("Scalars", () => {
    diff --git a/tools/third_party/closure-compiler.jar b/tools/third_party/closure-compiler.jar
    deleted file mode 100644
    index a297dc0f126..00000000000
    Binary files a/tools/third_party/closure-compiler.jar and /dev/null differ
    diff --git a/tools/third_party/depswriter.py b/tools/third_party/depswriter.py
    deleted file mode 100755
    index bc3be88a350..00000000000
    --- a/tools/third_party/depswriter.py
    +++ /dev/null
    @@ -1,204 +0,0 @@
    -#!/usr/bin/env python
    -#
    -# Copyright 2009 The Closure Library Authors. All Rights Reserved.
    -#
    -# Licensed under the Apache License, Version 2.0 (the "License");
    -# you may not use this file except in compliance with the License.
    -# You may obtain a copy of the License at
    -#
    -#      http://www.apache.org/licenses/LICENSE-2.0
    -#
    -# Unless required by applicable law or agreed to in writing, software
    -# distributed under the License is distributed on an "AS-IS" BASIS,
    -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    -# See the License for the specific language governing permissions and
    -# limitations under the License.
    -
    -
    -"""Generates out a Closure deps.js file given a list of JavaScript sources.
    -
    -Paths can be specified as arguments or (more commonly) specifying trees
    -with the flags (call with --help for descriptions).
    -
    -Usage: depswriter.py [path/to/js1.js [path/to/js2.js] ...]
    -"""
    -
    -import logging
    -import optparse
    -import os
    -import posixpath
    -import shlex
    -import sys
    -
    -import source
    -import treescan
    -
    -
    -__author__ = 'nnaze@google.com (Nathan Naze)'
    -
    -
    -def MakeDepsFile(source_map):
    -  """Make a generated deps file.
    -
    -  Args:
    -    source_map: A dict map of the source path to source.Source object.
    -
    -  Returns:
    -    str, A generated deps file source.
    -  """
    -
    -  # Write in path alphabetical order
    -  paths = sorted(source_map.keys())
    -
    -  lines = []
    -
    -  for path in paths:
    -    js_source = source_map[path]
    -
    -    # We don't need to add entries that don't provide anything.
    -    if js_source.provides:
    -      lines.append(_GetDepsLine(path, js_source))
    -
    -  return ''.join(lines)
    -
    -
    -def _GetDepsLine(path, js_source):
    -  """Get a deps.js file string for a source."""
    -
    -  provides = sorted(js_source.provides)
    -  requires = sorted(js_source.requires)
    -  module = 'true' if js_source.is_goog_module else 'false'
    -
    -  return 'goog.addDependency(\'%s\', %s, %s, %s);\n' % (
    -      path, provides, requires, module)
    -
    -
    -def _GetOptionsParser():
    -  """Get the options parser."""
    -
    -  parser = optparse.OptionParser(__doc__)
    -
    -  parser.add_option('--output_file',
    -                    dest='output_file',
    -                    action='store',
    -                    help=('If specified, write output to this path instead of '
    -                          'writing to standard output.'))
    -  parser.add_option('--root',
    -                    dest='roots',
    -                    default=[],
    -                    action='append',
    -                    help='A root directory to scan for JS source files. '
    -                    'Paths of JS files in generated deps file will be '
    -                    'relative to this path.  This flag may be specified '
    -                    'multiple times.')
    -  parser.add_option('--root_with_prefix',
    -                    dest='roots_with_prefix',
    -                    default=[],
    -                    action='append',
    -                    help='A root directory to scan for JS source files, plus '
    -                    'a prefix (if either contains a space, surround with '
    -                    'quotes).  Paths in generated deps file will be relative '
    -                    'to the root, but preceded by the prefix.  This flag '
    -                    'may be specified multiple times.')
    -  parser.add_option('--path_with_depspath',
    -                    dest='paths_with_depspath',
    -                    default=[],
    -                    action='append',
    -                    help='A path to a source file and an alternate path to '
    -                    'the file in the generated deps file (if either contains '
    -                    'a space, surround with whitespace). This flag may be '
    -                    'specified multiple times.')
    -  return parser
    -
    -
    -def _NormalizePathSeparators(path):
    -  """Replaces OS-specific path separators with POSIX-style slashes.
    -
    -  Args:
    -    path: str, A file path.
    -
    -  Returns:
    -    str, The path with any OS-specific path separators (such as backslash on
    -      Windows) replaced with URL-compatible forward slashes. A no-op on systems
    -      that use POSIX paths.
    -  """
    -  return path.replace(os.sep, posixpath.sep)
    -
    -
    -def _GetRelativePathToSourceDict(root, prefix=''):
    -  """Scans a top root directory for .js sources.
    -
    -  Args:
    -    root: str, Root directory.
    -    prefix: str, Prefix for returned paths.
    -
    -  Returns:
    -    dict, A map of relative paths (with prefix, if given), to source.Source
    -      objects.
    -  """
    -  # Remember and restore the cwd when we're done. We work from the root so
    -  # that paths are relative from the root.
    -  start_wd = os.getcwd()
    -  os.chdir(root)
    -
    -  path_to_source = {}
    -  for path in treescan.ScanTreeForJsFiles('.'):
    -    prefixed_path = _NormalizePathSeparators(os.path.join(prefix, path))
    -    path_to_source[prefixed_path] = source.Source(source.GetFileContents(path))
    -
    -  os.chdir(start_wd)
    -
    -  return path_to_source
    -
    -
    -def _GetPair(s):
    -  """Return a string as a shell-parsed tuple.  Two values expected."""
    -  try:
    -    # shlex uses '\' as an escape character, so they must be escaped.
    -    s = s.replace('\\', '\\\\')
    -    first, second = shlex.split(s)
    -    return (first, second)
    -  except:
    -    raise Exception('Unable to parse input line as a pair: %s' % s)
    -
    -
    -def main():
    -  """CLI frontend to MakeDepsFile."""
    -  logging.basicConfig(format=(sys.argv[0] + ': %(message)s'),
    -                      level=logging.INFO)
    -  options, args = _GetOptionsParser().parse_args()
    -
    -  path_to_source = {}
    -
    -  # Roots without prefixes
    -  for root in options.roots:
    -    path_to_source.update(_GetRelativePathToSourceDict(root))
    -
    -  # Roots with prefixes
    -  for root_and_prefix in options.roots_with_prefix:
    -    root, prefix = _GetPair(root_and_prefix)
    -    path_to_source.update(_GetRelativePathToSourceDict(root, prefix=prefix))
    -
    -  # Source paths
    -  for path in args:
    -    path_to_source[path] = source.Source(source.GetFileContents(path))
    -
    -  # Source paths with alternate deps paths
    -  for path_with_depspath in options.paths_with_depspath:
    -    srcpath, depspath = _GetPair(path_with_depspath)
    -    path_to_source[depspath] = source.Source(source.GetFileContents(srcpath))
    -
    -  # Make our output pipe.
    -  if options.output_file:
    -    out = open(options.output_file, 'w')
    -  else:
    -    out = sys.stdout
    -
    -  out.write('// This file was autogenerated by %s.\n' % sys.argv[0])
    -  out.write('// Please do not edit.\n')
    -
    -  out.write(MakeDepsFile(path_to_source))
    -
    -
    -if __name__ == '__main__':
    -  main()
    diff --git a/tsconfig.json b/tsconfig.json
    index 671c4b66356..cb38bbcf432 100644
    --- a/tsconfig.json
    +++ b/tsconfig.json
    @@ -8,6 +8,7 @@
           "dom"
         ],
         "module": "es2015",
    +    "moduleResolution": "node",
         "noImplicitAny": false,
         "outDir": "dist/es2015",
         "rootDir": "src",
    diff --git a/tsconfig.test.json b/tsconfig.test.json
    index df5542946d6..3ea71ea523f 100644
    --- a/tsconfig.test.json
    +++ b/tsconfig.test.json
    @@ -2,10 +2,12 @@
       "extends": "./tsconfig.json",
       "compilerOptions": {
         "rootDir": ".",
    -    "module": "CommonJS",
    +    "module": "commonjs",
         "target": "es5",
         "allowJs": true,
    -    "declaration": false
    +    "declaration": false,
    +    "outDir": "./dist",
    +    "sourceMap": true
       },
       "compileOnSave": true,
       "include": [
    diff --git a/yarn.lock b/yarn.lock
    index 1da081e53ba..fdc2f1d0974 100644
    --- a/yarn.lock
    +++ b/yarn.lock
    @@ -100,17 +100,26 @@ after@0.8.2:
       version "0.8.2"
       resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
     
    -ajv-keywords@^1.1.1:
    -  version "1.5.1"
    -  resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c"
    +ajv-keywords@^2.0.0:
    +  version "2.1.0"
    +  resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.0.tgz#a296e17f7bfae7c1ce4f7e0de53d29cb32162df0"
     
    -ajv@^4.7.0, ajv@^4.9.1:
    +ajv@^4.9.1:
       version "4.11.8"
       resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
       dependencies:
         co "^4.6.0"
         json-stable-stringify "^1.0.1"
     
    +ajv@^5.1.5:
    +  version "5.2.0"
    +  resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.2.0.tgz#c1735024c5da2ef75cc190713073d44f098bf486"
    +  dependencies:
    +    co "^4.6.0"
    +    fast-deep-equal "^0.1.0"
    +    json-schema-traverse "^0.3.0"
    +    json-stable-stringify "^1.0.1"
    +
     align-text@^0.1.1, align-text@^0.1.3:
       version "0.1.4"
       resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117"
    @@ -1534,6 +1543,13 @@ create-hmac@^1.1.0, create-hmac@^1.1.2:
         create-hash "^1.1.0"
         inherits "^2.0.1"
     
    +cross-env@^5.0.1:
    +  version "5.0.1"
    +  resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-5.0.1.tgz#ff4e72ea43b47da2486b43a7f2043b2609e44913"
    +  dependencies:
    +    cross-spawn "^5.1.0"
    +    is-windows "^1.0.0"
    +
     cross-spawn@^4.0.2:
       version "4.0.2"
       resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41"
    @@ -1541,7 +1557,7 @@ cross-spawn@^4.0.2:
         lru-cache "^4.0.1"
         which "^1.2.9"
     
    -cross-spawn@^5.0.1:
    +cross-spawn@^5.0.1, cross-spawn@^5.1.0:
       version "5.1.0"
       resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
       dependencies:
    @@ -1998,7 +2014,7 @@ es5-ext@^0.10.14, es5-ext@^0.10.9, es5-ext@~0.10.14:
         es6-iterator "2"
         es6-symbol "~3.1"
     
    -es6-iterator@2, es6-iterator@^2.0.1:
    +es6-iterator@2, es6-iterator@^2.0.1, es6-iterator@~2.0.1:
       version "2.0.1"
       resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.1.tgz#8e319c9f0453bf575d374940a655920e59ca5512"
       dependencies:
    @@ -2006,6 +2022,17 @@ es6-iterator@2, es6-iterator@^2.0.1:
         es5-ext "^0.10.14"
         es6-symbol "^3.1"
     
    +es6-map@^0.1.3:
    +  version "0.1.5"
    +  resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0"
    +  dependencies:
    +    d "1"
    +    es5-ext "~0.10.14"
    +    es6-iterator "~2.0.1"
    +    es6-set "~0.1.5"
    +    es6-symbol "~3.1.1"
    +    event-emitter "~0.3.5"
    +
     es6-object-assign@^1.0.3:
       version "1.1.0"
       resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c"
    @@ -2014,7 +2041,17 @@ es6-promise@^4.0.5:
       version "4.1.0"
       resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.1.0.tgz#dda03ca8f9f89bc597e689842929de7ba8cebdf0"
     
    -es6-symbol@^3.1, es6-symbol@^3.1.1, es6-symbol@~3.1:
    +es6-set@~0.1.5:
    +  version "0.1.5"
    +  resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1"
    +  dependencies:
    +    d "1"
    +    es5-ext "~0.10.14"
    +    es6-iterator "~2.0.1"
    +    es6-symbol "3.1.1"
    +    event-emitter "~0.3.5"
    +
    +es6-symbol@3.1.1, es6-symbol@^3.1, es6-symbol@^3.1.1, es6-symbol@~3.1, es6-symbol@~3.1.1:
       version "3.1.1"
       resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77"
       dependencies:
    @@ -2070,6 +2107,15 @@ escodegen@~1.1.0:
       optionalDependencies:
         source-map "~0.1.30"
     
    +escope@^3.6.0:
    +  version "3.6.0"
    +  resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3"
    +  dependencies:
    +    es6-map "^0.1.3"
    +    es6-weak-map "^2.0.1"
    +    esrecurse "^4.1.0"
    +    estraverse "^4.1.1"
    +
     escope@~0.0.13:
       version "0.0.16"
       resolved "https://registry.yarnpkg.com/escope/-/escope-0.0.16.tgz#418c7a0afca721dafe659193fd986283e746538f"
    @@ -2100,6 +2146,13 @@ esprima@~1.0.2, esprima@~1.0.4:
       version "1.0.4"
       resolved "https://registry.yarnpkg.com/esprima/-/esprima-1.0.4.tgz#9f557e08fc3b4d26ece9dd34f8fbf476b62585ad"
     
    +esrecurse@^4.1.0:
    +  version "4.2.0"
    +  resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.0.tgz#fa9568d98d3823f9a41d91e902dcab9ea6e5b163"
    +  dependencies:
    +    estraverse "^4.1.0"
    +    object-assign "^4.0.1"
    +
     esrefactor@~0.1.0:
       version "0.1.0"
       resolved "https://registry.yarnpkg.com/esrefactor/-/esrefactor-0.1.0.tgz#d142795a282339ab81e936b5b7a21b11bf197b13"
    @@ -2108,7 +2161,11 @@ esrefactor@~0.1.0:
         esprima "~1.0.2"
         estraverse "~0.0.4"
     
    -"estraverse@>= 0.0.2", estraverse@^1.9.1:
    +"estraverse@>= 0.0.2", estraverse@^4.1.0, estraverse@^4.1.1:
    +  version "4.2.0"
    +  resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13"
    +
    +estraverse@^1.9.1:
       version "1.9.3"
       resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44"
     
    @@ -2128,6 +2185,13 @@ esutils@~1.0.0:
       version "1.0.0"
       resolved "https://registry.yarnpkg.com/esutils/-/esutils-1.0.0.tgz#8151d358e20c8acc7fb745e7472c0025fe496570"
     
    +event-emitter@~0.3.5:
    +  version "0.3.5"
    +  resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39"
    +  dependencies:
    +    d "1"
    +    es5-ext "~0.10.14"
    +
     eventemitter3@1.x.x:
       version "1.2.0"
       resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.2.0.tgz#1c86991d816ad1e504750e73874224ecf3bec508"
    @@ -2234,6 +2298,10 @@ fancy-log@^1.1.0:
         chalk "^1.1.1"
         time-stamp "^1.0.0"
     
    +fast-deep-equal@^0.1.0:
    +  version "0.1.0"
    +  resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-0.1.0.tgz#5c6f4599aba6b333ee3342e2ed978672f1001f8d"
    +
     fast-levenshtein@~1.0.0:
       version "1.0.7"
       resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-1.0.7.tgz#0178dcdee023b92905193af0959e8a7639cfdcb9"
    @@ -3259,6 +3327,10 @@ is-windows@^0.2.0:
       version "0.2.0"
       resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-0.2.0.tgz#de1aa6d63ea29dd248737b69f1ff8b8002d2108c"
     
    +is-windows@^1.0.0:
    +  version "1.0.1"
    +  resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.1.tgz#310db70f742d259a16a369202b51af84233310d9"
    +
     isarray@0.0.1:
       version "0.0.1"
       resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
    @@ -3415,6 +3487,10 @@ json-loader@^0.5.4:
       version "0.5.4"
       resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.4.tgz#8baa1365a632f58a3c46d20175fc6002c96e37de"
     
    +json-schema-traverse@^0.3.0:
    +  version "0.3.1"
    +  resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340"
    +
     json-schema@0.2.3:
       version "0.2.3"
       resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
    @@ -3682,7 +3758,7 @@ loader-utils@^0.2.11, loader-utils@^0.2.16:
         json5 "^0.5.0"
         object-assign "^4.0.1"
     
    -loader-utils@^1.0.2:
    +loader-utils@^1.0.2, loader-utils@^1.1.0:
       version "1.1.0"
       resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.1.0.tgz#c98aef488bcceda2ffb5e2de646d6a754429f5cd"
       dependencies:
    @@ -5307,9 +5383,9 @@ socket.io@1.7.3:
         socket.io-client "1.7.3"
         socket.io-parser "2.3.1"
     
    -source-list-map@^1.1.1:
    -  version "1.1.1"
    -  resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-1.1.1.tgz#1a33ac210ca144d1e561f906ebccab5669ff4cb4"
    +source-list-map@^2.0.0:
    +  version "2.0.0"
    +  resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085"
     
     source-list-map@~0.1.7:
       version "0.1.8"
    @@ -5848,9 +5924,9 @@ typescript@^2.2.1:
       version "2.3.2"
       resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.3.2.tgz#f0f045e196f69a72f06b25fd3bd39d01c3ce9984"
     
    -uglify-js@^2.6, uglify-js@^2.8.5, uglify-js@~2.8.10:
    -  version "2.8.22"
    -  resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.22.tgz#d54934778a8da14903fa29a326fb24c0ab51a1a0"
    +uglify-js@^2.6, uglify-js@^2.8.29:
    +  version "2.8.29"
    +  resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"
       dependencies:
         source-map "~0.5.1"
         yargs "~3.10.0"
    @@ -5882,6 +5958,15 @@ uglify-js@~2.7.3:
         uglify-to-browserify "~1.0.0"
         yargs "~3.10.0"
     
    +uglify-js@~2.8.10:
    +  version "2.8.22"
    +  resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.22.tgz#d54934778a8da14903fa29a326fb24c0ab51a1a0"
    +  dependencies:
    +    source-map "~0.5.1"
    +    yargs "~3.10.0"
    +  optionalDependencies:
    +    uglify-to-browserify "~1.0.0"
    +
     uglify-save-license@^0.4.1:
       version "0.4.1"
       resolved "https://registry.yarnpkg.com/uglify-save-license/-/uglify-save-license-0.4.1.tgz#95726c17cc6fd171c3617e3bf4d8d82aa8c4cce1"
    @@ -5890,6 +5975,14 @@ uglify-to-browserify@~1.0.0:
       version "1.0.2"
       resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7"
     
    +uglifyjs-webpack-plugin@^0.4.4:
    +  version "0.4.6"
    +  resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz#b951f4abb6bd617e66f63eb891498e391763e309"
    +  dependencies:
    +    source-map "^0.5.6"
    +    uglify-js "^2.8.29"
    +    webpack-sources "^1.0.1"
    +
     uid-number@^0.0.6:
       version "0.0.6"
       resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81"
    @@ -6132,11 +6225,11 @@ webpack-core@^0.6.8, webpack-core@~0.6.9:
         source-list-map "~0.1.7"
         source-map "~0.4.1"
     
    -webpack-sources@^0.2.3:
    -  version "0.2.3"
    -  resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-0.2.3.tgz#17c62bfaf13c707f9d02c479e0dcdde8380697fb"
    +webpack-sources@^1.0.1:
    +  version "1.0.1"
    +  resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.0.1.tgz#c7356436a4d13123be2e2426a05d1dad9cbe65cf"
       dependencies:
    -    source-list-map "^1.1.1"
    +    source-list-map "^2.0.0"
         source-map "~0.5.3"
     
     webpack-stream@^3.2.0:
    @@ -6171,30 +6264,31 @@ webpack@^1.12.9:
         watchpack "^0.2.1"
         webpack-core "~0.6.9"
     
    -webpack@^2.5.0:
    -  version "2.5.0"
    -  resolved "https://registry.yarnpkg.com/webpack/-/webpack-2.5.0.tgz#5a17089f8d0e43442e606d6cf9b2a146c8ed9911"
    +webpack@^3.0.0:
    +  version "3.0.0"
    +  resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.0.0.tgz#ee9bcebf21247f7153cb410168cab45e3a59d4d7"
       dependencies:
         acorn "^5.0.0"
         acorn-dynamic-import "^2.0.0"
    -    ajv "^4.7.0"
    -    ajv-keywords "^1.1.1"
    +    ajv "^5.1.5"
    +    ajv-keywords "^2.0.0"
         async "^2.1.2"
         enhanced-resolve "^3.0.0"
    +    escope "^3.6.0"
         interpret "^1.0.0"
         json-loader "^0.5.4"
         json5 "^0.5.1"
         loader-runner "^2.3.0"
    -    loader-utils "^0.2.16"
    +    loader-utils "^1.1.0"
         memory-fs "~0.4.1"
         mkdirp "~0.5.0"
         node-libs-browser "^2.0.0"
         source-map "^0.5.3"
         supports-color "^3.1.0"
         tapable "~0.2.5"
    -    uglify-js "^2.8.5"
    +    uglifyjs-webpack-plugin "^0.4.4"
         watchpack "^1.3.1"
    -    webpack-sources "^0.2.3"
    +    webpack-sources "^1.0.1"
         yargs "^6.0.0"
     
     websocket-driver@>=0.5.1: